diff --git a/.agent/rules/commit_style.md b/.agent/rules/commit_style.md new file mode 100644 index 000000000000..668bbbbde84e --- /dev/null +++ b/.agent/rules/commit_style.md @@ -0,0 +1,28 @@ +--- +trigger: always_on +--- + +# Agent Commit Rules + +The user requires all commit messages generated by the agent to follow a specific style and include a proper sign-off. + +## Commit Message Style + +Commit messages must be formatted with a subject line and a body, following this format: +``` +: + + +``` + +* **``**: A short name or tag representing the feature or component being modified. +* **``**: A succinct one-line description of the change. +* **``**: A detailed description of the changes made in the commit. The body must be at least one sentence describing the changes. + +## Sign-off + +Every commit message must end with a `Signed-off-by:` line using the patch author's name and email (from the local git config): + +``` +Signed-off-by: +``` diff --git a/.agent/rules/documentation.md b/.agent/rules/documentation.md new file mode 100644 index 000000000000..5d88e6aa3dd4 --- /dev/null +++ b/.agent/rules/documentation.md @@ -0,0 +1,13 @@ +# Documentation Rules + +The user expects all new features and in-code documentation to adhere to Doxygen standards. + +## Doxygen Requirements + +1. **Mandatory Documentation:** All new features, functions, and structures must include Doxygen comments describing their purpose, parameters, and return values. +2. **Clean Build:** Any in-code documentation added or modified must build with Doxygen without producing any new errors or warnings. +3. **Format:** Use standard Doxygen formatting tags (e.g., `@brief`, `@param`, `@return` or `\brief`, `\param`, `\return`). Ensure the styling matches the existing codebase conventions. + +## Directory Documentation + +When creating a new file or modifying an existing one, check if there is an `architecture.md` or `readme.md` (or `README.md`) file in the same directory. If present, evaluate whether the code changes require an update to these documentation files and make the necessary updates to keep them synchronized with the code. diff --git a/.agent/rules/topology2_design.md b/.agent/rules/topology2_design.md new file mode 100644 index 000000000000..35d98473a57c --- /dev/null +++ b/.agent/rules/topology2_design.md @@ -0,0 +1,12 @@ +--- +trigger: glob +glob: tools/topology/topology2/** +--- + +# Topology2 Design Rule + +When working in tools/topology/topology2, follow the canonical guidance in +.github/instructions/topology2-design.instructions.md. + +Apply those instructions for topology structure, ID assignment, routing, +platform overrides, and topology target registration. \ No newline at end of file diff --git a/.agent/workflows/build_and_validate.md b/.agent/workflows/build_and_validate.md new file mode 100644 index 000000000000..7a3614fc8254 --- /dev/null +++ b/.agent/workflows/build_and_validate.md @@ -0,0 +1,22 @@ +--- +description: Build and validate new C code features +--- + +This workflow describes the process for building and validating any new C code features in the SOF repository. + +**Note:** The QEMU build targets must be used for both building and testing. The user requires the build must be error and warning free and the ztests must all pass. + +// turbo-all +1. Build the new C code feature using the `xtensa-build-zephyr.py` script. + ```bash + source ../.venv/bin/activate + ./scripts/xtensa-build-zephyr.py qemu_xtensa + ``` + +2. Validate the feature with a ztest run using the `sof-qemu-run.sh` script. + ```bash + source ../.venv/bin/activate + ./scripts/sof-qemu-run.sh build-qemu_xtensa + ``` + +3. Ensure that all new features and functions have appropriate Doxygen comments and that the Doxygen documentation builds without errors or warnings. \ No newline at end of file diff --git a/.agent/workflows/module_development.md b/.agent/workflows/module_development.md new file mode 100644 index 000000000000..6036da58034d --- /dev/null +++ b/.agent/workflows/module_development.md @@ -0,0 +1,22 @@ +--- +description: Develop and validate new audio processing modules +--- + +This workflow describes the expected steps to create and validate a new audio processing module within the SOF repository. + +// turbo-all +1. **(Optional)** Generate the module skeleton using the `sdk-create-module.py` script. + ```bash + # Run the script with relevant arguments to create a new module template + ./scripts/sdk-create-module.py --name --version + ``` + +2. Develop the module logic within the generated skeleton. + +3. Validate the module by executing the module within the host testbench. This ensures that the module functions as expected outside of full system simulations. + ```bash + # Configure and run the testbench against the developed module + ./scripts/host-testbench.sh -l + ``` + +4. Document the new module using Doxygen comments. Validate that the Doxygen build completes without errors or warnings. Add a README.md for the module. \ No newline at end of file diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000000..145353dd0a2d --- /dev/null +++ b/.clang-format @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Note: The list of ForEachMacros can be obtained using: +# +# git grep -h '^#define [^[:space:]]*FOR_EACH[^[:space:]]*(' include/ \ +# | sed "s,^#define \([^[:space:]]*FOR_EACH[^[:space:]]*\)(.*$, - '\1'," \ +# | sort | uniq +# +# References: +# - https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +# Based on https://github.com/zephyrproject-rtos/zephyr/blob/main/.clang-format + +--- +BasedOnStyle: LLVM +AlignConsecutiveMacros: AcrossComments +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AttributeMacros: + - __aligned + - __deprecated + - __packed + - __printf_like + - __syscall + - __syscall_always_inline + - __subsystem +BitFieldColonSpacing: After +BreakBeforeBraces: Linux +ColumnLimit: 100 +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +ForEachMacros: + - 'ARRAY_FOR_EACH' + - 'ARRAY_FOR_EACH_PTR' + - 'FOR_EACH' + - 'FOR_EACH_FIXED_ARG' + - 'FOR_EACH_IDX' + - 'FOR_EACH_IDX_FIXED_ARG' + - 'FOR_EACH_NONEMPTY_TERM' + - 'FOR_EACH_FIXED_ARG_NONEMPTY_TERM' + - 'RB_FOR_EACH' + - 'RB_FOR_EACH_CONTAINER' + - 'SYS_DLIST_FOR_EACH_CONTAINER' + - 'SYS_DLIST_FOR_EACH_CONTAINER_SAFE' + - 'SYS_DLIST_FOR_EACH_NODE' + - 'SYS_DLIST_FOR_EACH_NODE_SAFE' + - 'SYS_SEM_LOCK' + - 'SYS_SFLIST_FOR_EACH_CONTAINER' + - 'SYS_SFLIST_FOR_EACH_CONTAINER_SAFE' + - 'SYS_SFLIST_FOR_EACH_NODE' + - 'SYS_SFLIST_FOR_EACH_NODE_SAFE' + - 'SYS_SLIST_FOR_EACH_CONTAINER' + - 'SYS_SLIST_FOR_EACH_CONTAINER_SAFE' + - 'SYS_SLIST_FOR_EACH_NODE' + - 'SYS_SLIST_FOR_EACH_NODE_SAFE' + - '_WAIT_Q_FOR_EACH' + - '_WAIT_Q_FOR_EACH_SAFE' + - 'Z_FOR_EACH' + - 'Z_FOR_EACH_ENGINE' + - 'Z_FOR_EACH_EXEC' + - 'Z_FOR_EACH_FIXED_ARG' + - 'Z_FOR_EACH_FIXED_ARG_EXEC' + - 'Z_FOR_EACH_IDX' + - 'Z_FOR_EACH_IDX_EXEC' + - 'Z_FOR_EACH_IDX_FIXED_ARG' + - 'Z_FOR_EACH_IDX_FIXED_ARG_EXEC' + - 'Z_GENLIST_FOR_EACH_CONTAINER' + - 'Z_GENLIST_FOR_EACH_CONTAINER_SAFE' + - 'Z_GENLIST_FOR_EACH_NODE' + - 'Z_GENLIST_FOR_EACH_NODE_SAFE' + - 'STRUCT_SECTION_FOREACH' + - 'STRUCT_SECTION_FOREACH_ALTERNATE' + - 'TYPE_SECTION_FOREACH' + - 'K_SPINLOCK' + - 'COAP_RESOURCE_FOREACH' + - 'COAP_SERVICE_FOREACH' + - 'COAP_SERVICE_FOREACH_RESOURCE' + - 'HTTP_RESOURCE_FOREACH' + - 'HTTP_SERVER_CONTENT_TYPE_FOREACH' + - 'HTTP_SERVICE_FOREACH' + - 'HTTP_SERVICE_FOREACH_RESOURCE' + - 'I3C_BUS_FOR_EACH_I3CDEV' + - 'I3C_BUS_FOR_EACH_I3CDEV_SAFE' + - 'I3C_BUS_FOR_EACH_I2CDEV' + - 'I3C_BUS_FOR_EACH_I2CDEV_SAFE' + - 'MIN_HEAP_FOREACH' +IfMacros: + - 'CHECKIF' +# Disabled for now, see bug https://github.com/zephyrproject-rtos/zephyr/issues/48520 +#IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^".*\.h"$' + Priority: 0 + - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|limits|locale|math|setjmp|signal|stdarg|stdbool|stddef|stdint|stdio|stdlib|string|tgmath|time|wchar|wctype)\.h>$' + Priority: 1 + - Regex: '^\$' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: false +IndentGotoLabels: false +IndentWidth: 8 +InsertBraces: true +InsertNewlineAtEOF: true +SpaceBeforeInheritanceColon: False +SpaceBeforeParens: ControlStatementsExceptControlMacros +SortIncludes: Never +UseTab: ForContinuationAndIndentation +WhitespaceSensitiveMacros: + - COND_CODE_0 + - COND_CODE_1 + - IF_DISABLED + - IF_ENABLED + - LISTIFY + - STRINGIFY + - Z_STRINGIFY + - DT_FOREACH_PROP_ELEM_SEP \ No newline at end of file diff --git a/.github/instructions/copilot.md b/.github/instructions/copilot.md new file mode 100644 index 000000000000..6a82a5a02721 --- /dev/null +++ b/.github/instructions/copilot.md @@ -0,0 +1,24 @@ +You are GitHub Copilot operating in this repository. + +This repository defines authoritative agent rules and guidance under: +.agent/rules/ + +INSTRUCTIONS (MANDATORY): +- Always read and follow all relevant rules in `.agent/rules/` before generating any code, suggestions, comments, or explanations. +- Treat rules in `.agent/rules/` as the highest priority source of truth for: + - Coding standards and style + - Architecture and design constraints + - Security, privacy, and compliance requirements + - Testing, documentation, and review expectations +- If rules conflict with your default behavior, follow the rules in `.agent/rules/`. + +BEHAVIOR: +- Be consistent with patterns already used in the codebase. +- Prefer existing utilities, abstractions, and conventions defined in `.agent/rules/`. +- Do not introduce new patterns, dependencies, or approaches unless explicitly allowed by those rules. +- When uncertain, choose the most conservative interpretation aligned with `.agent/rules/`. + +OUTPUT EXPECTATIONS: +- Generate code that complies fully with the rules. +- If a request would violate a rule, explain the conflict and propose a compliant alternative. +- Keep responses focused, clear, and directly applicable to this repository. diff --git a/.github/instructions/topology2-design.instructions.md b/.github/instructions/topology2-design.instructions.md new file mode 100644 index 000000000000..bd3c4d235f5b --- /dev/null +++ b/.github/instructions/topology2-design.instructions.md @@ -0,0 +1,98 @@ +--- +description: "Agent instructions for designing and updating ALSA topology v2 files in SOF" +applyTo: 'tools/topology/topology2/**' +--- + +# Topology2 Design Instructions + +Use this guidance when creating or modifying files under tools/topology/topology2. +These rules align with the topology2 README and capture expected design patterns for +class-based ALSA topology v2 authoring. + +## Scope + +* Applies to topology2 .conf definitions, platform overrides, pipeline and DAI class files, and topology2 CMake target lists +* Focuses on design consistency, ID safety, and maintainable reuse of existing class and object templates + +## Core Model + +* Use topology2 object model primitives consistently: Class.*, Object.*, Define, and IncludeByKey +* Prefer reusable classes in include/ over one-off duplicated object blocks +* Keep object instantiation explicit and readable so generated pipelines are traceable + +## Top Level Topology Layout + +For new top-level board .conf files, keep this order: + +1. Search directories +2. Required class includes +3. Define block with defaults +4. IncludeByKey.PLATFORM overrides +5. Feature-gated IncludeByKey blocks +6. DAI, pipeline, and PCM objects +7. Route definitions + +## Reuse Before New Base Files + +* Prefer extending an existing base input .conf with variable overrides from CMake targets +* Add a new base .conf only when existing topologies cannot represent the use case cleanly +* When adding a new target, use this tuple structure. In CMake quoted strings, escape each semicolon as `\;`. + +```text +Logical tuple format: +"input-conf;output-name;variable1=value1,variable2=value2" + +CMake string form: +"input-conf\;output-name\;variable1=value1,variable2=value2" +``` + +## ID Conventions and Safety + +* Keep PCM IDs unique within a single topology +* Keep pipeline indexes unique within a single topology +* Pair FE and BE pipelines as N and N+1 where applicable +* For SoundWire pipelines, follow index equals PCM ID times 10 unless a documented topology-specific exception exists +* For HDMI pipelines, keep stride-10 layout with host at N0 and DAI at N1 +* When combining features such as SDW, PCH DMIC, HDMI, deep buffer, or compress, verify there are no ID collisions after overrides + +## Routing Rules + +* Connect FE mixin outputs to BE mixout inputs using Object.Base.route +* Keep route naming and widget references aligned with topology naming patterns +* Validate that each route endpoint maps to a declared widget in the same compiled topology + +## Widget Naming + +* Follow naming pattern type.pipeline-index.instance +* Keep naming stable and descriptive for easier graph inspection and debug + +## Platform Overrides + +* Use IncludeByKey.PLATFORM for platform-specific Define overrides +* Restrict platform-specific tuning to platform/intel/*.conf instead of duplicating board-level logic +* Ensure platform keys remain consistent with the authoritative in-tree overrides under tools/topology/topology2/platform/intel/*.conf; current examples include tgl, adl, mtl, lnl, ptl, and nvl + +## CMake Target Placement + +Register targets in the correct file for platform generation: + +* Tiger Lake and Alder Lake: production/tplg-targets-cavs25.cmake +* Meteor Lake: production/tplg-targets-ace1.cmake +* Lunar Lake: production/tplg-targets-ace2.cmake +* Panther Lake: production/tplg-targets-ace3.cmake +* Nova Lake / sof-nvl-*: production/tplg-targets-ace4.cmake +* i.MX8 platforms: production/tplg-targets-imx8.cmake +* SDCA generic topologies: production/tplg-targets-sdca-generic.cmake +* HDA generic: production/tplg-targets-hda-generic.cmake +* Development and test topologies: development/tplg-targets.cmake + +If a target family is not listed above, use the existing tplg-targets-*.cmake +file that already contains similar topologies as the source of truth, and keep new +targets grouped with the same platform or product family in either production/ or +development/. + +## Validation Expectations + +* Keep topology2 buildable through the topologies2 target +* Preserve compatibility with alsatplg pre-processing mode used by the build system +* Ensure topology edits remain synchronized with nearby architecture or README documentation when design behavior changes diff --git a/.github/workflows/SPDX-README.md b/.github/workflows/SPDX-README.md new file mode 100644 index 000000000000..5bc30f0cc9b5 --- /dev/null +++ b/.github/workflows/SPDX-README.md @@ -0,0 +1,34 @@ +Read this section if there are some SPDX warnings above. +Adding correct SPDX headers to new files can be tricky because: + +- a different SPDX style is expected for .c versus .h files. + This is because some .h files are included in linker scripts or + assembly code. +- Some SOF reviewers reject C99 comments starting with // + +A trick is to keep the SPDX separate, see solution below. + +References: +- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/license-rules.rst#n71 +- https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9f3a89926d6d + + +Start .h files like this: +``` +/* SPDX-License-Identifier: ... */ +/* + * Copyright(c) ... + * + * Author: ... + */ +``` + +Start .c files like this: +``` +// SPDX-License-Identifier: ... +/* + * Copyright(c) ... + * + * Author: ... + */ +``` diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml new file mode 100644 index 000000000000..19fee4a98ca4 --- /dev/null +++ b/.github/workflows/build_all.yml @@ -0,0 +1,73 @@ +--- + +name: Build test all components + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab + +# yamllint disable-line rule:truthy +on: [pull_request, workflow_dispatch, workflow_call] + +permissions: + contents: read + +jobs: + + stub-build: + runs-on: ubuntu-24.04 + strategy: + matrix: + # Keep these names short due to questionable Github UI choices + IPC: [3, 4] + + steps: + - name: add i386 arch + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + + - 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++-14-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@v4 + with: + path: ./workspace/sof + filter: 'tree:0' + + - name: west update + run: | + cd workspace/sof + pip3 install west + west init -l + west update --narrow --fetch-opt=--filter=tree:0 + + # This is not fuzzing. Fuzzing just happens to require stubbing + # which provides be a great solution to compile-check many CONFIG_* + # at once. + - name: stubs build + run: | + cd workspace + clang --verbose + set -x + sof/scripts/fuzz.sh -b -i '${{ matrix.IPC }}' -- \ + -DEXTRA_CFLAGS='-Werror' -DEXTRA_CXXFLAGS='-Werror' \ + -DEXTRA_CONF_FILE='stub_build_all_ipc${{ matrix.IPC }}.conf' diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml new file mode 100644 index 000000000000..052878a5cdd2 --- /dev/null +++ b/.github/workflows/close-stale.yml @@ -0,0 +1,31 @@ +--- +name: "Close stale issues" + +# yamllint disable-line rule:truthy +on: + schedule: + - cron: "30 1 * * *" + +permissions: + contents: read + +jobs: + stale: + name: Find stale issues + runs-on: ubuntu-24.04 + if: github.repository == 'thesofproject/sof' + permissions: + issues: write + + steps: + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 + with: + stale-issue-message: 'This issue has been marked as stale because it has been open (more + than) 60 days with no activity. Remove the stale label or add a comment saying that you + would like to have the label removed otherwise this issue will automatically be closed + in 14 days. Note, that you can always re-open a closed issue at any time.' + days-before-stale: 60 + days-before-close: 14 + stale-issue-label: 'stale' + exempt-issue-labels: 'metabug,in progress,enhancement' + operations-per-run: 400 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000000..4f7c29d6c831 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,50 @@ +--- +name: "CodeQL Analysis" +# yamllint disable-line rule:truthy +on: + pull_request: + branches: + - 'main' + +permissions: + contents: read + +# Specifies group name that stops previous workflows if the name matches +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze GitHub Actions Workflows + runs-on: ubuntu-latest + permissions: + security-events: write # Required to upload SARIF results + actions: read # Required to read workflow information + contents: read # Required to checkout repository + + strategy: + fail-fast: false + matrix: + language: ['actions'] # Analyze GitHub Actions workflows + + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Initialize CodeQL + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4 + with: + languages: ${{ matrix.language }} + # Optional: Specify custom queries + # queries: security-extended,security-and-quality + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4 + with: + category: "/language:${{ matrix.language }}" + upload: true + # Upload SARIF results to GitHub Security tab + output: sarif-results diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml new file mode 100644 index 000000000000..ea9e0a20d150 --- /dev/null +++ b/.github/workflows/codestyle.yml @@ -0,0 +1,34 @@ +--- +# SPDX-License-Identifier: BSD-3-Clause +# Tools that can save round-trips to github and a lot of time: +# +# yamllint -f parsable this.yml +# pip3 install ruamel.yaml.cmd +# yaml merge-expand this.yml exp.yml && diff -w -u this.yml exp.yml +# +# github.com also has a powerful web editor that can be used without +# committing. + +name: codestyle + +# yamllint disable-line rule:truthy +on: [pull_request, workflow_call, workflow_dispatch] + +permissions: + contents: read + +jobs: + yamllint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + filter: 'tree:0' + + - name: run yamllint + # Quoting to please all parsers is hard. This indirection helps. + env: + yamllint_config: '{extends: default, rules: {line-length: {max: 100}}}' + run: yamllint -f parsable + -d "$yamllint_config" + --strict .github/workflows/*.yml *.yml diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml new file mode 100644 index 000000000000..139c946c3d84 --- /dev/null +++ b/.github/workflows/daily-tests.yml @@ -0,0 +1,57 @@ +--- +# https://docs.github.com/en/actions/using-workflows/reusing-workflows +# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule + +name: Daily tests + +# yamllint disable-line rule:truthy +on: + # To configure goto https://crontab.guru/ + schedule: + # daily at 00:00 UTC + - cron: '0 0 * * *' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + +jobs: + + # Keep in .yml alphabetical order + + zephyr-stub-all: + uses: ./.github/workflows/build_all.yml + + # TODO: separate "fetchPRcommits" which can't work in daily tests + # uses: ./.github/workflows/codestyle.yml + + zephyr-fuzz-IPC: + uses: ./.github/workflows/ipc_fuzzer.yml + with: + fuzzing_duration_s: 300 + + # A legacy, semi-random mix + main-PR-workflows: + uses: ./.github/workflows/pull-request.yml + + XTOS-reproducible: + uses: ./.github/workflows/repro-build.yml + + rimage: + uses: ./.github/workflows/rimage.yml + + zephyr-sparse-analyzer: + uses: ./.github/workflows/sparse-zephyr.yml + + user-space-testbench: + uses: ./.github/workflows/testbench.yml + + user-space-other-tools: + uses: ./.github/workflows/tools.yml + + cmocka-unit-tests: + uses: ./.github/workflows/unit-tests.yml + + zephyr-builds: + uses: ./.github/workflows/zephyr.yml diff --git a/.github/workflows/ipc_fuzzer.yml b/.github/workflows/ipc_fuzzer.yml new file mode 100644 index 000000000000..755dbf4b5d9b --- /dev/null +++ b/.github/workflows/ipc_fuzzer.yml @@ -0,0 +1,96 @@ +--- + +name: IPC fuzzing + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab + +# yamllint disable-line rule:truthy +on: + workflow_call: + inputs: + fuzzing_duration_s: + type: number + default: 300 # 5 minutes + + workflow_dispatch: + inputs: + fuzzing_duration_s: + type: number + default: 300 + + pull_request: + # TODO: can we provide a default inputs here too? + +permissions: + contents: read + +jobs: + + simple-IPC-fuzz_sh: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + # Keep these names short due to questionable Github UI choices + IPC: [3, 4] + + steps: + - name: add i386 arch + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + + - 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++-14-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@v4 + with: + path: ./workspace/sof + filter: 'tree:0' + + - name: west update + run: | + cd workspace/sof + pip3 install west + west init -l + west update --narrow --fetch-opt=--filter=tree:0 + + - name: build and run fuzzer for a few minutes + run: | + cd workspace + clang --verbose + set -x + duration="${{inputs.fuzzing_duration_s}}" + duration="${duration:-301}" # pull_request has not 'inputs.' :-( + # Note libFuzzer makes a difference between -jobs and -workers (capped at nproc/2) + sof/scripts/fuzz.sh -i '${{ matrix.IPC }}' -o fuzz-stdout.txt -t "$duration" -j"$(nproc)" + + - name: Upload stdout + uses: actions/upload-artifact@v4 + if: failure() + with: + name: ${{ matrix.IPC }} logs + path: | + workspace/crash-* + workspace/fuzz-stdout.txt + workspace/fuzz-*.log diff --git a/.github/workflows/llext.yml b/.github/workflows/llext.yml new file mode 100644 index 000000000000..149c9e2e3571 --- /dev/null +++ b/.github/workflows/llext.yml @@ -0,0 +1,55 @@ +--- + +name: Zephyr LLEXT + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab +# yamllint disable-line rule:truthy +on: [pull_request, workflow_dispatch] + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-24.04 + container: + image: thesofproject/zephyr-lite:v0.29.0 + + strategy: + fail-fast: false + matrix: + platform: [mtl, lnl] + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + path: sof + fetch-depth: 0 # fix git describe + filter: 'tree:0' + + - name: west update + working-directory: sof + run: | + west init -l + west update --narrow --fetch-opt=--depth=5 + + - name: print all available sdks in /opt/toolchains/ + run: | + ls -l /opt/toolchains/ + + - name: llext build + run: | + ln -s /opt/toolchains/zephyr-sdk-* ~/ + python sof/scripts/xtensa-build-zephyr.py \ + --cmake-args=-DEXTRA_CFLAGS=-Werror \ + --cmake-args=-DEXTRA_CXXFLAGS=-Werror \ + --cmake-args=-DEXTRA_AFLAGS='-Werror -Wa,--fatal-warnings' \ + --cmake-args=--warn-uninitialized \ + --overlay=sof/app/configs/${{ matrix.platform }}/modules.conf \ + ${{ matrix.platform }} diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 000000000000..0bd3865dec97 --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,66 @@ +--- +# Tools that can save round-trips to github and a lot of time: +# +# yamllint -f parsable pull_request.yml +# pip3 install ruamel.yaml.cmd +# yaml merge-expand pull_request.yml exp.yml && +# diff -w -u pull_request.yml exp.yml +# +# github.com also has a powerful web editor that can be used without +# committing. + +# TODO: finish scattering this very old workflow to more specific +# .yml files +name: Main Actions + +# yamllint disable-line rule:truthy +on: + push: + branches: + - 'main' + - 'stable-**' + - '**-stable' + pull_request: + branches: + - 'main' + - 'stable-**' + - '**-stable' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + # Allows to call this forkflow from other workflows + workflow_call: + +permissions: + contents: read + +jobs: + + doxygen: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + with: + filter: 'tree:0' + + - name: apt get doxygen graphviz + run: sudo apt-get -y install ninja-build doxygen graphviz + + - name: Show warnings but fail only on errors + run: cmake -GNinja -S doc -B docbuild && ninja -C docbuild -v doc + + # Build again (it's very quick) so warnings don't go unnoticed. + # For older doxygen versions that don't have FAIL_ON_WARNINGS, use + # WARN_AS_ERROR = YES instead. 'YES' is inferior because it stops + # on the first error. + # + # Note some doxygen bug(s) can cause some specific error types to + # escape WARN_AS_ERROR, example: + # https://github.com/doxygen/doxygen/issues/7970 and + # https://github.com/thesofproject/sof/pull/5978 + + - name: Fail on warnings + run: printf + 'WARN_AS_ERROR = FAIL_ON_WARNINGS\n' >> doc/sof.doxygen.in && + ninja -C docbuild -v doc diff --git a/.github/workflows/repro-build.yml b/.github/workflows/repro-build.yml new file mode 100644 index 000000000000..abe48a8cecb2 --- /dev/null +++ b/.github/workflows/repro-build.yml @@ -0,0 +1,32 @@ +--- +# SPDX-License-Identifier: BSD-3-Clause +# Tools that can save round-trips to github and a lot of time: +# +# yamllint -f parsable this.yml +# pip3 install ruamel.yaml.cmd +# yaml merge-expand this.yml exp.yml && diff -w -u this.yml exp.yml +# +# github.com also has a powerful web editor that can be used without +# committing. + +name: Reproducible builds + +# yamllint disable-line rule:truthy +on: [pull_request, workflow_dispatch, workflow_call] + +permissions: + contents: read + +jobs: + main: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + with: {fetch-depth: 0, submodules: recursive, filter: 'tree:0'} + + - name: docker pull + run: docker pull thesofproject/sof && docker tag thesofproject/sof sof + + - name: repro test + run: ./scripts/docker-run.sh ./scripts/test-repro-build.sh diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml new file mode 100644 index 000000000000..53059681ae9d --- /dev/null +++ b/.github/workflows/rimage.yml @@ -0,0 +1,64 @@ +--- +# SPDX-License-Identifier: BSD-3-Clause +# Tools that can save round-trips to github and a lot of time: +# +# yamllint -f parsable this.yml +# pip3 install ruamel.yaml.cmd +# yaml merge-expand this.yml exp.yml && diff -w -u this.yml exp.yml +# +# github.com also has a powerful web editor that can be used without +# committing. + +name: rimage + +# yamllint disable-line rule:truthy +on: + workflow_call: + workflow_dispatch: + pull_request: + paths: + - tools/rimage/** + push: + paths: + - tools/rimage/** + +permissions: + contents: read + +jobs: + + # Basic build test + build: + runs-on: ubuntu-24.04 + env: + # FIXME: add -Wpointer-arith + _CFLGS: -Werror -Wall -Wmissing-prototypes + -Wimplicit-fallthrough=3 + + + steps: + - uses: actions/checkout@v4 + with: {submodules: recursive, fetch-depth: 0, filter: 'tree:0'} + + - run: cmake -B build-rimage/ -S tools/rimage/ -DCMAKE_C_FLAGS="${_CFLGS}" + + # VERBOSE because CFLAGS (and -Wpointer-arith) used to be ignored + # for years and no one noticed + - run: cmake --build build-rimage/ -- -j$(nproc) VERBOSE=1 + + + # cppcheck + cppcheck: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: {submodules: recursive, fetch-depth: 0, filter: 'tree:0'} + + - name: apt install cppcheck + run: sudo apt update && sudo apt-get -y install cppcheck + + # TODO enable more types of checks as they are fixed + - name: run cppcheck + run: cppcheck --platform=unix32 --force --max-configs=1024 + --inconclusive --inline-suppr + --error-exitcode=1 tools/rimage/ diff --git a/.github/workflows/shallowfetchPRcommits.sh b/.github/workflows/shallowfetchPRcommits.sh new file mode 100755 index 000000000000..d43525b2defd --- /dev/null +++ b/.github/workflows/shallowfetchPRcommits.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause + +set -e + +# This script fetches Pull Request commits missing from a shallow clone +# and creates a PR_SHAs.txt file. This script has a limit of 500 commits but the +# github API used has a lower limit of 250 commits. + +# It does not rely on git merge-bases which basically don't work with +# shallow clones: +# https://github.com/thesofproject/linux/issues/2556 + +# Design goals: +# +# - Keep the code short and as simple as possible. No one is interested +# in maintaining this sort of script. +# +# - Fast and accurate for small Pull Requests +# +# - For large Pull Requests _with merges_ the only objective is to +# complete in a reasonable time; say less than 10 minutes. It's very +# unlikely will look at 250 checkpatch results and time optimizations +# should not make this script more complex. + + +# Sample usage: +# $0 thesoftproject/linux 2772 +main() +{ + local gh_project="$1" + local pr_number="$2" + + printf '%s: fetching PR %d for project %s\n' "$0" "$pr_number" "$gh_project" + + # As of March 2021, Github's documented limit is 250 commits + # Let's have another cap a 500. + # https://docs.github.com/en/rest/reference/pulls#list-commits-on-a-pull-request + local pagelen PRlen=0 + for i in 1 2 3 4 5; do + curl -H 'Accept: application/vnd.github.v3+json' \ + "https://api.github.com/repos/$gh_project/pulls/$pr_number/commits?per_page=100&page=$i" \ + > commits_"$i".json + pagelen=$(jq length < commits_$i.json) + if [ "$pagelen" -eq 0 ]; then + break + fi + PRlen=$((PRlen + pagelen)) + done + + printf 'Found %d commits, SHA1 list is in PR_SHAs.txt\n' "$PRlen" + + # 'cut' removes double quotes + cat commits_?.json | + jq '.[] | .sha' | + cut -b2-41 > PR_SHAs.txt + + # PRlen+1 gets us the merge base for simple, linear histories. For + # pull requests with merges, depth=PRLEN goes already much further + # than needed and +1 makes little difference. It's not clear when + # and for what sort of PRs git fetching individual commits would be + # faster so keep a single and simple fetch for now. + + set -x # this command may take a while so show it + git fetch --depth "$((PRlen+1))" "https://github.com/$gh_project" "pull/$pr_number/head" + +} + +main "$@" diff --git a/.github/workflows/sof-docs.yml b/.github/workflows/sof-docs.yml new file mode 100644 index 000000000000..63af4acfc714 --- /dev/null +++ b/.github/workflows/sof-docs.yml @@ -0,0 +1,62 @@ +--- +# yamllint disable-line rule:truthy +on: + push: + branches: + - 'main' + - 'stable-**' + - '**-stable' + pull_request: + branches: + - 'main' + - 'stable-**' + - '**-stable' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + # Allows to call this forkflow from other workflows + workflow_call: + +permissions: + contents: read + +jobs: + + # This is unfortunately a mix of sof-docs/.github/ + pull-request.yml#doxygen + # duplicating a bit of both: please keep in sync with both. We + # build sof-docs here too because waiting for sof-docs CI to find + # regressions introduced in sof.git is very time-consuming, see + # example in + # https://github.com/thesofproject/sof/pull/5731#issuecomment-1175630147 + sof-docs: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + with: + filter: 'tree:0' + + - name: apt-get update + run: sudo apt-get update + + - name: apt-get install + run: | + sudo apt-get -yq install doxygen make \ + default-jre graphviz cmake ninja-build \ + libjpeg-dev + + - name: doxygen + run: cmake -GNinja -S doc/ -B doxybuild/ && ninja -C doxybuild/ -v doc + + # Nested git clone, this is fine + - name: clone sof-docs + run: git clone https://github.com/thesofproject/sof-docs sof-docs/ + + - name: PATH += .local/bin + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: 'pip install -r sof-docs/scripts/requirements.txt' + run: pip install -r sof-docs/scripts/requirements.txt + + - name: build sof-docs + run: LAX=1 make -C sof-docs/ html SOF_DOC_BUILD="$(pwd)"/doxybuild/ diff --git a/.github/workflows/sparse-zephyr.yml b/.github/workflows/sparse-zephyr.yml new file mode 100644 index 000000000000..5afa6361f51a --- /dev/null +++ b/.github/workflows/sparse-zephyr.yml @@ -0,0 +1,87 @@ +--- + +name: Sparse Zephyr + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab +# yamllint disable-line rule:truthy +on: [push, pull_request, workflow_dispatch, workflow_call] + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + # As of sparse commit ce1a6720f69e / Sept 2022, the exit status of + # sparse.c is an unusable mess and always zero in practice. Moreover + # SOF has hundreds of sparse warnings right now. So fail only on a + # small subset of specific warnings defined in + # sof/scripts/parse_sparse_output.sh + warnings-subset: + # disable until https://github.com/zephyrproject-rtos/zephyr/issues/93444 + # is fixed + if: false + + # We're sharing the sparse binary with the zephyr-build container so keep + # this in sync with it. + runs-on: ubuntu-24.04 + container: + image: thesofproject/zephyr-lite:v0.29.0 + + strategy: + fail-fast: false + matrix: + platform: [tgl, mtl, lnl] + + steps: + - name: git clone sparse analyzer + uses: actions/checkout@v4 + with: + repository: thesofproject/sparse + fetch-depth: 0 + filter: 'tree:0' + path: sparse + + # As of its 2023 commit 98b203419679, sparse-llvm.c uses symbols + # (LLVMConstGEP, LLVMBuildLoad, LLVMBuildCall,...) which are: + # - -Wdeprecated in LLVM v14 + # - Removed in LLVM v16 + - name: build sparse analyzer + working-directory: sparse + run: | + make -j4 # HAVE_LLVM=no + + - name: git clone sof + uses: actions/checkout@v4 + with: + path: sof + fetch-depth: 0 # fix git describe + filter: 'tree:0' + + - name: west update + working-directory: sof + run: | + west init -l + west update --narrow --fetch-opt=--depth=5 + + - name: print all available sdks in /opt/toolchains/ + run: | + ls -l /opt/toolchains/ + + # --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. + # "sparse" is currently incompatible with PICOLIBC (the new Zephyr default), + # see https://github.com/zephyrproject-rtos/zephyr/issues/63003 + - name: analyze zephyr + run: | + ./sof/zephyr/docker-build.sh ${{ matrix.platform }} \ + --cmake-args=-DZEPHYR_SCA_VARIANT=sparse --cmake-args=-DCONFIG_LOG_USE_VLA=n \ + --cmake-args=-DCONFIG_MINIMAL_LIBC=y \ + --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 new file mode 100644 index 000000000000..290fe8e56dee --- /dev/null +++ b/.github/workflows/testbench.yml @@ -0,0 +1,96 @@ +--- +# Tools that can save round-trips to github and a lot of time: +# +# yamllint -f parsable pull_request.yml +# pip3 install ruamel.yaml.cmd +# yaml merge-expand pull_request.yml exp.yml && +# diff -w -u pull_request.yml exp.yml +# +# github.com also has a powerful web editor that can be used without +# committing. + +name: testbench + +# yamllint disable-line rule:truthy +on: + push: + branches: + - 'main' + - 'stable-**' + - '**-stable' + pull_request: + branches: + - 'main' + - 'stable-**' + - '**-stable' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + workflow_call: + +permissions: + contents: read + +jobs: + build-and-test: + runs-on: ubuntu-24.04 + + steps: + - name: Checkout SOF repository (PR source) + uses: actions/checkout@v4 + with: + path: sof + + # note: libasound-dev needed for testbench build which still + # requires system ALSA headers to be present + - name: apt get + run: sudo apt-get update && + sudo apt-get -y install valgrind ninja-build + octave octave-signal automake autoconf libtool + gettext libasound2-dev + + - name: Build Alsa-lib + run: | + cd ${GITHUB_WORKSPACE} + git clone https://github.com/thesofproject/alsa-lib.git + cd alsa-lib + git checkout df8f1cc1ec9d9ee15be5e2c23ad25b9389fd8766 -b build + ./gitcompile --prefix=${GITHUB_WORKSPACE}/tools + make install + + - name: Build Alsa-utils + run: | + cd ${GITHUB_WORKSPACE} + git clone https://github.com/thesofproject/alsa-utils.git + cd alsa-utils + git checkout 0ffa105942a06cdfa98e5918b8dc82e3cac12792 -b build + ./gitcompile --prefix=${GITHUB_WORKSPACE}/tools \ + --with-alsa-prefix=${GITHUB_WORKSPACE}/tools \ + --with-alsa-inc-prefix=${GITHUB_WORKSPACE}/tools/include \ + --with-sysroot=${GITHUB_WORKSPACE}/tools \ + --with-udev-rules-dir=${GITHUB_WORKSPACE}/tools \ + PKG_CONFIG_PATH=${GITHUB_WORKSPACE}/tools \ + LDFLAGS=-L${GITHUB_WORKSPACE}/tools/lib \ + --disable-old-symbols \ + --enable-alsatopology \ + --with-asound-state-dir=${GITHUB_WORKSPACE}/tools/var/lib/alsa \ + --with-systemdsystemunitdir=${GITHUB_WORKSPACE}/tools/lib/systemd/system + make install + + # testbench needs some topologies. + - name: build test topologies + run: | + CMAKE_BUILD_TYPE=Release ./sof/scripts/build-tools.sh -Y || + VERBOSE=1 NO_PROCESSORS=1 USE_XARGS=no + CMAKE_BUILD_TYPE=Release ./sof/scripts/build-tools.sh -Y + + # build testbench + - name: build testbench + run: | + ./sof/scripts/rebuild-testbench.sh || + ./sof/scripts/rebuild-testbench.sh -j 1 + + # run testbench + - name: run testbench + run: | + ./sof/scripts/host-testbench.sh diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml new file mode 100644 index 000000000000..7c70e93ddb5f --- /dev/null +++ b/.github/workflows/tools.yml @@ -0,0 +1,60 @@ +--- +name: User space tools/ directory + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab + +# yamllint disable-line rule:truthy +on: [pull_request, workflow_dispatch, workflow_call] + +permissions: + contents: read + +jobs: + # This is not the same as building every ./build-tools.sh option. + top-level_default_CMake_target_ALL: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + filter: 'tree:0' + + # The ALSA version in Ubuntu 20.04 is buggy + # (https://github.com/thesofproject/sof/issues/2543) and likely + # getting out of date soon + - name: docker + run: docker pull thesofproject/sof && docker tag thesofproject/sof sof + + # For some reason gcc has more warnings in Release mode + - name: build-tools + run: CMAKE_BUILD_TYPE=Release ./scripts/docker-run.sh + ./scripts/build-tools.sh || + VERBOSE=1 NO_PROCESSORS=1 USE_XARGS=no + CMAKE_BUILD_TYPE=Release ./scripts/docker-run.sh + ./scripts/build-tools.sh + + + SOF-alsa-plugin: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: {filter: 'tree:0'} + + - name: apt install + run: sudo apt-get update; + sudo apt-get -y install ninja-build libasound2-dev + + # One space character is enough to detect most quoting issues + - name: configure + run: cmake -GNinja -B 'build plugin' -S tools/plugin + -GNinja -Wdev -Werror=dev --warn-uninitialized + + # Retry with -j1 in case of error because parallel builds drown error + # messages. + - name: build ExternalProjects first to avoid build race condition + run: cmake --build 'build plugin' -- sof_ep parser_ep || + cmake --build 'build plugin' -- sof_ep parser_ep -j1 + + - name: Remaining build steps + run: cmake --build 'build plugin' || + cmake --build 'build plugin' -j1 diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 000000000000..de8577e87171 --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,24 @@ +--- + +# https://thesofproject.github.io/latest/developer_guides/unit_tests.html + +name: Unit tests + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab + +# yamllint disable-line rule:truthy +on: [pull_request, workflow_dispatch, workflow_call] + +permissions: + contents: read + +jobs: + cmocka_utests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: {fetch-depth: 2, filter: 'tree:0'} + + - name: build and run all defconfigs + run: ./test/test-all-defconfigs.sh diff --git a/.github/workflows/zephyr-main.yml b/.github/workflows/zephyr-main.yml new file mode 100644 index 000000000000..0b6f0cbe3e28 --- /dev/null +++ b/.github/workflows/zephyr-main.yml @@ -0,0 +1,17 @@ +--- +name: Zephyr Main Branch + +# yamllint disable-line rule:truthy +on: + schedule: + - cron: '0 4,16 * * *' + workflow_dispatch: + +permissions: + contents: read + +jobs: + zephyr-main-builds: + uses: ./.github/workflows/zephyr.yml + with: + zephyr_revision: 'zmain' diff --git a/.github/workflows/zephyr-shell.yml b/.github/workflows/zephyr-shell.yml new file mode 100644 index 000000000000..23f8e6947b22 --- /dev/null +++ b/.github/workflows/zephyr-shell.yml @@ -0,0 +1,64 @@ +--- +# SPDX-License-Identifier: BSD-3-Clause +# Tools that can save round-trips to github and a lot of time: +# +# yamllint -f parsable zephyr-shell.yml +# pip3 install ruamel.yaml.cmd +# yaml merge-expand zephyr-shell.yml exp.yml && diff -w -u zephyr-shell.yml exp.yml +# +# github.com also has a powerful web editor that can be used without +# committing. + +name: Zephyr Shell + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab +# yamllint disable-line rule:truthy +on: [pull_request, workflow_dispatch] + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-24.04 + container: + image: thesofproject/zephyr-lite:v0.29.0 + + strategy: + fail-fast: false + matrix: + platform: [tgl, mtl, lnl] + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + path: sof + fetch-depth: 0 # fix git describe + filter: 'tree:0' + + - name: west update + working-directory: sof + run: | + west init -l + west update --narrow --fetch-opt=--depth=5 + + - name: print all available sdks in /opt/toolchains/ + run: | + ls -l /opt/toolchains/ + + - name: shell build + run: | + ln -s /opt/toolchains/zephyr-sdk-* ~/ + python sof/scripts/xtensa-build-zephyr.py \ + --cmake-args=-DEXTRA_CFLAGS=-Werror \ + --cmake-args=-DEXTRA_CXXFLAGS=-Werror \ + --cmake-args=-DEXTRA_AFLAGS='-Werror -Wa,--fatal-warnings' \ + --cmake-args=--warn-uninitialized \ + --overlay=sof/app/shell_overlay.conf \ + ${{ matrix.platform }} diff --git a/.github/workflows/zephyr-unit-tests.yml b/.github/workflows/zephyr-unit-tests.yml new file mode 100644 index 000000000000..ed089a148597 --- /dev/null +++ b/.github/workflows/zephyr-unit-tests.yml @@ -0,0 +1,61 @@ +--- +name: "Unit tests" +# yamllint disable-line rule:truthy +on: + pull_request: + branches: + - 'main' + +permissions: + contents: read + +# Specifies group name that stops previous workflows if the name matches +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + zephyr-utests: + name: Zephyr Unit Tests (ZTest) + runs-on: ubuntu-24.04 + timeout-minutes: 10 + + steps: + - name: Install build tools + run: | + sudo apt-get update + sudo apt-get -y install clang llvm ninja-build device-tree-compiler \ + python3-pyelftools + # Install multilib packages required for native_sim i386 target + sudo apt-get install gcc-multilib g++-multilib + + - name: Checkout SOF repository + uses: actions/checkout@v4 + with: + path: ./workspace/sof + fetch-depth: 2 + filter: 'tree:0' + + - name: West update + run: | + cd workspace/sof + pip3 install west + west init -l + west update --narrow --fetch-opt=--filter=tree:0 + + - name: Install Python dependencies + run: | + cd workspace/zephyr + pip3 install --user -r scripts/requirements.txt + + - name: Build and run unit tests + run: | + cd workspace + export ZEPHYR_TOOLCHAIN_VARIANT=host/llvm + west twister --testsuite-root sof/test/ztest/unit/ --platform native_sim --verbose \ + --inline-logs + # This part is commented out because it is not needed at the moment. + # - name: Install Zephyr SDK + # run: | + # cd workspace/zephyr + # west sdk install --version 0.16.9 -t xtensa-intel_ace30_ptl_zephyr-elf diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml new file mode 100644 index 000000000000..ecfc6f4089ee --- /dev/null +++ b/.github/workflows/zephyr.yml @@ -0,0 +1,516 @@ +--- + +name: Zephyr + +# 'workflow_dispatch' allows running this workflow manually from the +# 'Actions' tab +# yamllint disable-line rule:truthy +on: + push: + pull_request: + workflow_dispatch: + workflow_call: + inputs: + zephyr_revision: + description: 'Zephyr revision to build against' + type: string + required: false + default: 'mnfst' + +# Specifies group name that stops previous wokrflows if the name matches +concurrency: + # eg. "Zephyr-pull_request-my_fork_branch_to_merge" + # eg. "Zephyr-push-refs/heads/my_branch_merging" + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + manifest-check: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + container: + image: thesofproject/zephyr-lite:v0.29.0 + steps: + - uses: actions/checkout@v4 + with: + path: sof + filter: 'tree:0' + + - name: plain west update + working-directory: sof + run: | + : This plain 'west update' does not provide 100% certainty that + : all the manifest revisions make sense but it is quick and + : will catch many revision problems. Other jobs typically + : use 'west update --narrow' which is faster but + : also able to fetch "wild" SHA1s from any random place! --narrow + : is useful for testing unmerged Zephyr commits but risks + : accepting "invalid" ones, this will not. + + west init -l + west update --fetch-opt=--filter=tree:0 + + # Temporary check until we change west.yml and stop nesting rimage + # and tomlc99 inside sof which will cleanly separate them from + # XTOS submodules and... temporarily break every CI, which is why + # it hasn't been done yet. + - name: git submodules consistency + working-directory: sof + run: | + git submodule update --init --recursive + + west update + if git status --porcelain=v2 | grep ^ ; then + git status + echo 'FAIL: inconsistency between git submodules and west.yml!' + echo 'See rimage comment in west.yml.' + echo 'Always use "git status"' + exit 1 + fi + + + # Temporary hacks to compile the very first LP64 configuration early + # before it becomes supported by the regular + # sof/scripts/xtensa-build-zephyr.py configuration script. Then this + # job will be disappear, folded back in the regular build-* jobs below. + LP64-WIP: + runs-on: ubuntu-24.04 + defaults: + run: + shell: bash + container: + image: thesofproject/zephyr-lite:v0.29.0 + + steps: + - uses: actions/checkout@v4 + with: + path: sof + filter: 'tree:0' + + - name: west update + working-directory: sof + run: | + west init -l + west update --narrow --fetch-opt=--filter=tree:0 + + - name: print all available sdks in /opt/toolchains/ + run: | + ls -l /opt/toolchains/ + + - name: 64 bits build + run: | + ln -s /opt/toolchains/zephyr-sdk-* ~/ + west build --board imx93_evk/mimx9352/a55 sof/app \ + -- -DEXTRA_CFLAGS=-Werror -DEXTRA_CXXFLAGS=-Werror \ + -DEXTRA_AFLAGS=-Werror + + build-linux: + runs-on: ubuntu-24.04 + defaults: + run: + shell: bash + container: + image: thesofproject/zephyr-lite:v0.29.0 + 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: [ + "${{ inputs.zephyr_revision || 'mnfst' }}" + ] + # Using groups to avoid spamming the small results box with too + # many lines. Pay attention to COMMAS. + IPC_platforms: [ + # - IPC3 default + imx8 imx8x, + imx8m imx8ulp, + # - IPC4 default, released + mtl, + lnl, + # active development + ptl, + # Temporary testbed for Zephyr development. + tgl, + tgl-h + ] + 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: lnl + + # Due to GitHub size limitations we can't afford to run --all and + # duplicate builds already built in previous steps. + # This will now build any platform that would've run with --all that + # isn't already built above. + - zephyr_revision: mnfst + IPC_platforms: wcl imx95 + + steps: + - uses: actions/checkout@v4 + # Download a full clone to fix `git describe`, sof_version.h and + # build reproducibility. sof.git is still small. + # This is especially useful for daily builds (but not just). + with: + fetch-depth: 0 + filter: 'tree:0' + path: sof + + - name: west update + working-directory: sof + run: | + west init -l + west update --narrow --fetch-opt=--filter=tree:0 + + - name: select zephyr revision + run: | + if [ 'mnfst' = '${{ matrix.zephyr_revision }}' ]; then + rem_rev=$(git -C zephyr rev-parse HEAD) + else + 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 + ) + time west update --narrow --fetch-opt=--filter=tree:0 + fi + + # Get some tags to fix `git describe` hence BUILD_VERSION, etc. + # Keep in sync with build-windows below + - name: Fetch tags for git describe + working-directory: zephyr + run: | + # Because we used git tricks to speed things up, we now have two git + # problems: + # + # 1. git fetch without a refspec fetches zero tag. So `git describe` is + # different from everyone else. west normally adds `--tags` as a workaround + # but this is inefficient because it fetches ALL tags; so `west --narrow` + # does not use --tags. + # + # 2. west fetches using the remote URL, not the remote name. So remote + # branches are missing from --decorate below. Cosmetic but annoying. + + set -x + # Fix problem 2. Do NOT assume anything about remote names: nothing is guaranteed. + _zurl=$(west list -f '{url}' zephyr) + # Use an ugly remote name to avoid a collision + git remote add sof_zep_rem "$_zurl" + time git fetch --filter=tree:0 sof_zep_rem "$rem_rev" + # Fix problem 1. Indirectly fetches useless branches but is very quick thanks to + # the --filter + time git fetch --filter=tree:0 --tags sof_zep_rem + + west list + west status + git log --oneline -n 5 --decorate --graph --no-abbrev-commit + git describe --long --always --dirty + git describe --long --always --dirty --tags + + - name: print all available sdks in /opt/toolchains/ + run: | + ls -l /opt/toolchains/ + + - name: build + run: | + ./sof/zephyr/docker-build.sh --cmake-args=-DEXTRA_CFLAGS=-Werror \ + --cmake-args=-DEXTRA_CXXFLAGS=-Werror \ + --cmake-args=-DEXTRA_AFLAGS='-Werror -Wa,--fatal-warnings' \ + --cmake-args=--warn-uninitialized \ + --overlay=sof/app/configs/repro-build.conf \ + --no-tarball \ + ${{ matrix.build_opts }} ${{ matrix.IPC_platforms }} + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: linux-build ${{ matrix.build_opts }} ${{ matrix.IPC_platforms }} + if-no-files-found: error + path: | + build-sof-staging + ./**/compile_commands.json + + build-windows: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + # Search "zephyr_revision" and see below what they expand to. + zephyr_revision: [ + "${{ inputs.zephyr_revision || 'mnfst' }}" + ] + # Using groups to avoid spamming the small results box with too + # many lines. Pay attention to COMMAS. + platforms: [ + # - IPC3 default + imx8 imx8x, + imx8m imx8ulp, + # - IPC4 default, released + mtl, + lnl, + # active development + ptl, + # legacy + tgl, + tgl-h + ] + build_opts: [""] + # Sparse matrices are complicated, see comments on Linux matrix above. + include: + - build_opts: -d + zephyr_revision: mnfst + platforms: lnl + + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + filter: 'tree:0' + path: ./workspace/sof + + # Cache artifacts so we do not overload external servers with downloads + # Remember to change step key if you change the tools so old cache is not restored, + # or delete cache manually in Github Actions tab + - name: Cache unzip + id: cache-unzip + uses: actions/cache@v4 + with: + path: unzip-5.51-1-bin.zip + key: ${{ runner.os }}-cache-unzip-5-51-1 + + - name: Cache wget + id: cache-wget + uses: actions/cache@v4 + with: + path: wget-1.11.4-1-bin.zip + key: ${{ runner.os }}-cache-wget-1-11-4-1 + + # Keep this SDK version identical to the one in + # sof/zephyr/docker-run.sh + - name: Cache Zephyr SDK 1.0.0 + id: cache-zephyr-sdk + uses: actions/cache@v4 + with: + path: zephyr-sdk-1.0.0_windows-x86_64_gnu.7z + key: ${{ runner.os }}-cache-zephyr-sdk-1-0-0 + + # Wget is needed by Zephyr SDK setup.cmd installation script + - name: Download wget + if: ${{ steps.cache-wget.outputs.cache-hit != 'true' }} + run: | + curl -L -O http://downloads.sourceforge.net/gnuwin32/wget-1.11.4-1-bin.zip + + - name: Download Zephyr SDK 1.0.0 + 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/v1.0.0/zephyr-sdk-1.0.0_windows-x86_64_gnu.7z + + # Unzips every .zip package to directory matching its name without extension + - name: Unzip downloaded packages + run: | + 7z x *.zip -o* + 7z x *.7z -o* + + - name: Add unzip to system PATH + run: | + echo "${{ github.workspace }}/unzip-5.51-1-bin/bin" | ` + Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Add wget to system PATH + run: | + echo "${{ github.workspace }}/wget-1.11.4-1-bin/bin" | ` + Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + # Install Zephyr SDK - all toolchains including Host Tools + # and registering CMake package in the registry + # 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-1.0.0_windows-x86_64_gnu/zephyr-sdk-1.0.0/setup.cmd /t all /h /c + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: West install + run: pip3 install west + + - name: West clone + working-directory: ${{ github.workspace }}/workspace + # Keep in sync with build-linux above + run: | + west init -l sof + west update --narrow --fetch-opt=--filter=tree:0 + + - name: select zephyr revision + working-directory: ${{ github.workspace }}/workspace + run: | + if ('mnfst' -eq '${{ matrix.zephyr_revision }}') { + $rem_rev = $(git -C zephyr rev-parse HEAD) + } else { + switch ('${{ matrix.zephyr_revision }}') { + 'zmain' { $rem_rev = 'main' } + default { Write-Error 'Unknown matrix.zephyr_revision'; exit 1 } + } + Push-Location sof/submanifests/ + (Get-Content sof-ci-jenkins/zephyr-override-template.yml) ` + -replace '=sof_zephyr_revision_override=', "$rem_rev" ` + | Set-Content test-zephyr-main.yml + Pop-Location + west update --narrow --fetch-opt=--filter=tree:0 + } + + # Get some tags to fix `git describe` etc., see detailed build-linux comments above. + - name: Fetch tags for git describe + working-directory: ${{ github.workspace }}/workspace/zephyr + # Keep in sync with build-linux above + run: | + # Set-PSDebug -Trace 2 + $_rev = "$(git rev-parse HEAD)" + $_zurl = "$(west list -f '{url}' zephyr)" + git remote add sof_zep_rem "${_zurl}" + # Unlike Linux above, hardcode "main" for now. Will make no difference most + # of the time but keeps this bit consistent with Linux, tested and ready to use. + git fetch --filter=tree:0 sof_zep_rem main + git fetch --filter=tree:0 --tags sof_zep_rem + + west list + west status + git log --oneline -n 5 --decorate --graph --no-abbrev-commit + git describe --long --always --dirty + git describe --long --always --dirty --tags + + # Call Setup Python again to save the PIP packages in cache + - name: Setup Python + uses: actions/setup-python@v5 + id: cache-python + with: + python-version: '3.12' + cache: 'pip' + cache-dependency-path: workspace/zephyr/scripts/requirements.txt + + # All requirements will be satisfied if the restored cache matches existing state + - name: Validate python PIP cache + working-directory: ${{ github.workspace }}/workspace + run: pip install -r zephyr/scripts/requirements.txt + + # Ninja has been coming and going, see #8250 + - name: choco install ninja + run: | + choco install ninja + ninja.exe --version + + # MSYS2 provides gcc x86_64 toolchain, openssl & gperf + # Installs in D:/a/_temp/msys64 + # + # Note there is already C:/msys64/ provided by + # https://github.com/actions/runner-images/blob/win22/20230918.1/images/win/Windows2022-Readme.md + # Is it not good enough? Maybe it could save 20-30s. + - name: Initialize MSYS2 + uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2 + with: + msystem: MSYS + install: gcc openssl-devel gperf + path-type: inherit + + - name: Build + shell: msys2 {0} + working-directory: ${{ github.workspace }}/workspace + run: python sof/scripts/xtensa-build-zephyr.py + --no-interactive + --cmake-args=-DEXTRA_CFLAGS=-Werror + --cmake-args=-DEXTRA_CXXFLAGS=-Werror + --cmake-args=-DEXTRA_AFLAGS='-Werror -Wa,--fatal-warnings' + --cmake-args=--warn-uninitialized + --overlay=sof/app/configs/repro-build.conf + --no-tarball + ${{ matrix.build_opts }} ${{ matrix.platforms }} + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: windows-build ${{ matrix.build_opts }} ${{ matrix.platforms }} + if-no-files-found: error + path: | + ${{ github.workspace }}/workspace/build-sof-staging + ${{ github.workspace }}/workspace/**/compile_commands.json + + + compare-linux-win: + + runs-on: ubuntu-latest + + # - We don't compare _all_ the builds, and + # - even when some of the ones we compare fail, we still want to compare the rest. + if: ${{ always() }} + needs: [build-linux, build-windows] + + steps: + - uses: actions/checkout@v4 + # we need only one script but it's simpler to get the (last + # revision of the) whole repo and it takes seconds. + with: + # Isolate the clone in a subdirectory to make sure globbing + # does not catch random SOF files. + path: ./sof + filter: 'tree:0' + + - name: Download Windows and Linux builds + uses: actions/download-artifact@v4 + + - name: apt-get dos2unix + run: sudo apt-get update; sudo apt-get -y install dos2unix + + - name: Delete and fix expected differences + run: | + ls -l + # run it twice to make sure it's idempotent + for i in 0 1; do + ./sof/zephyr/scripts/clean-expected-release-differences.sh \ + windows-build* linux-build* + done + + - name: Compare Linux vs Windows builds + run: | + diffs=0; ls -l + + # Look for a few samples to + # check not too much is missing (it happened!) + # http://mywiki.wooledge.org/ParsingLs + for regdir in 'linux-build *-d *.*' \ + 'linux-build *.*lnl.*' \ + 'windows-build *.*mtl.*' \ + 'windows-build *tgl-h' \ + 'windows-build *tgl'; do + find . -maxdepth 1 | grep -q "\./${regdir}\$" || + { >&2 printf 'Missing %s\n' "${regdir}"; exit 1; } + done + + # The disassembly is one of the most important things in this + # context, so make sure CONFIG_OUTPUT_DISSASSEMBLY was on. + ls -l */build-sof-staging/sof-info/*/zephyr.lst* + + set -x + for windir in windows-build*; do + lindir=linux-"${windir#windows-}" + diff -qr "$lindir" "$windir" || : $((diffs++)) + done + exit $diffs diff --git a/.gitignore b/.gitignore index 5f2c1e93b8f0..043112c6ff78 100644 --- a/.gitignore +++ b/.gitignore @@ -15,13 +15,11 @@ *.rom *.man .version -.tarball-version *.x .build *.dis *.lst *.log -.* *.html *.js *.png @@ -33,9 +31,6 @@ *.xslt *.mbox -doc/doxygen -*.doxygen - *.gz *.xz src/arch/xtensa/sof @@ -46,21 +41,21 @@ src/arch/xtensa/module src/arch/xtensa/rom src/arch/xtensa/rom-* boot_module -module -rimage/rimage tap-driver.sh test-driver *.trs +tools/test/audio/reports/* +tools/test/audio/zeros_in.raw __pycache__ build*/ -CMakeCache.txt -CMakeFiles -doc/*.cmake -doc/*.ninja -doc/Makefile + +# Eclipse project metadata +.settings +.project +.cproject /tags /TAGS @@ -68,3 +63,4 @@ doc/Makefile # cscope files cscope.* ncscope.* + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..99bed093e833 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,17 @@ +# This is required for non-Zephyr ("XTOS") configurations. Zephyr +# configs also get it from sof/west.yml which adds the burden of keeping +# both tomlc99 SHA1s synchronized but in practice this barely ever moves. +[submodule "tomlc99"] + path = tools/rimage/tomlc99 + # This is a _absolute_ submodule URL. In some use cases it's + # better than an _relative_ 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. + # + # A local and temporary edit of this url can be enough because + # .gitmodules is used _only once_ to submodule --init[ialize] + # .git/config the first time. Then .gitmodules is never used + # again after cloning tomlc99 the first time. + url = https://github.com/thesofproject/tomlc99.git + branch = master diff --git a/.sourcegraph/ignore b/.sourcegraph/ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 250b3a542e94..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,74 +0,0 @@ -sudo: required - -language: c - -git: - depth: false - -services: - - docker -stages: - - test - - qemutest - -before_install: - - docker pull thesofproject/sof && docker tag thesofproject/sof sof - -env: - - PLATFORM=byt - - PLATFORM=cht - - PLATFORM=bdw - - PLATFORM=hsw - - PLATFORM=apl - - PLATFORM=skl - - PLATFORM=kbl - - PLATFORM=cnl - - PLATFORM=sue - - PLATFORM=icl - - PLATFORM=jsl - - PLATFORM=imx8 - - PLATFORM=imx8x - - PLATFORM=imx8m - -script: ./scripts/docker-run.sh ./scripts/xtensa-build-all.sh -j $PLATFORM - -jobs: - include: - - stage: test - script: ./scripts/docker-run.sh ./scripts/build-tools.sh - env: PLATFORM=tools - - stage: test - script: ./scripts/docker-run.sh ./scripts/host-build-all.sh -l - env: PLATFORM=host - # Matrix hack: Declare the same stage name multiple times to test multiple - # versions. Use a YAML alias to prevent redundancy. - - &qemuboottest - stage: qemutest - script: - - sed -i $(($(grep "config HAVE_AGENT" -n src/platform/Kconfig | cut -f1 -d:)+2))"s/default y/default n/" src/platform/Kconfig - - ./scripts/docker-run.sh ./scripts/xtensa-build-all.sh -r -j $PLATFORM - - ./scripts/docker-qemu.sh ../sof.git/scripts/qemu-check.sh $PLATFORM - env: PLATFORM=byt - before_install: - - docker pull thesofproject/sof && docker tag thesofproject/sof sof - - docker pull thesofproject/sofqemu && docker tag thesofproject/sofqemu sofqemu - - <<: *qemuboottest - env: PLATFORM=cht - - <<: *qemuboottest - env: PLATFORM=bdw - - <<: *qemuboottest - env: PLATFORM=hsw - - <<: *qemuboottest - env: PLATFORM=apl - - <<: *qemuboottest - env: PLATFORM=skl - - <<: *qemuboottest - env: PLATFORM=kbl - - <<: *qemuboottest - env: PLATFORM=cnl - - <<: *qemuboottest - env: PLATFORM=icl - - <<: *qemuboottest - env: PLATFORM=imx8 - - <<: *qemuboottest - env: PLATFORM=imx8x diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000000..462c39f0d343 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# Sound Open Firmware (SOF) Agent Workflows and Rules + +This document outlines the rules AI agents must follow when checking out branches, writing code, documenting features, and running the development environment. Follow these rules carefully: + +## Development Standards + +### Commitment and Sign-off Rules +* **Commit Subject:** Must follow the format `subsystem: component: short description` matching the SOF project convention. Use the git history of the modified file(s) (`git log --oneline -10 -- `) to determine the correct subsystem and component prefix. Examples: + * `audio: chain_dma: add user-space scheduling support` + * `ipc4: handler: fix large config dispatch` + * `schedule: zephyr_domain: add user-space LL thread` +* **Commit Body:** Should describe the changes in detail in the commit message body. +* **Sign-off:** All commits must be signed off by the developer (`Signed-off-by: Name `) using the identity from the local git config. + +### Documentation Requirements +* **Doxygen Comments:** Any new C code or features must include Doxygen comments. +* **Documentation Builds:** Integration of new code must not introduce any new Doxygen errors or warnings. Code additions should be verified against a clean documentation build. +* **Architectural Consistency:** When adding or updating a file, any `architecture.md` or `README.md` in the same directory must be reviewed. The agent is responsible for ensuring documentation stays in sync with code logic changes. + +### Codestyle and Linting +* **Standard:** Use `clangd` instead of `checkpatch` for codestyle verification. +* **Rationale:** `checkpatch` is prone to confusion with assembly and non-standard C; `clangd` provides better integration with IDEs and AI tools and is easier to maintain. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 000000000000..e236a2b659e6 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,46 @@ +# Sound Open Firmware (SOF) Architecture + +This document provides a high-level overview of the Sound Open Firmware (SOF) architecture. SOF provides an open-source audio DSP firmware and an SDK for audio development. + +## 1. High-Level Overview + +At a macro level, the SOF stack consists of: +* **Host Driver (OS):** The OS-level driver (Linux ALSA/ASoC, Windows, etc.) that acts as the frontend, managing audio devices, streams, and IPC communication. +* **Firmware (DSP):** The embedded firmware running on the Audio DSP (typically Xtensa/Tensilica or other DSPs). +* **Topology:** A configuration file loaded by the host driver that defines the hardware constraints, routing, and instantiated audio processing graphs (pipelines). + +## 2. Firmware Architecture + +The SOF firmware is built with a modular, layered architecture to support multiple platforms, DSP architectures, and operating systems. + +### 2.1 OS Abstraction and RTOS +* **Zephyr RTOS:** Modern SOF extensively leverages the Zephyr RTOS for core operating system services, including thread scheduling, synchronization, logging, and hardware abstraction. +* **XTOS / Bare-metal (Legacy):** Older platforms or specific stripped-down environments might use XTOS or bare-metal abstractions. + +### 2.2 Inter-Process Communication (IPC) +The IPC subsystem is responsible for all communication between the Host OS and the DSP Firmware. +* **Message Passing:** Uses hardware mailboxes, shared memory, and interrupts to send messages. +* **Commands:** Includes stream setup, pipeline instantiation, run/pause/stop commands, volume changes, and parameter updates. +* **Versions:** IPC relies on a versioned message protocol (e.g., IPC3, IPC4) allowing the host and firmware to understand each other's commands. + +### 2.3 Audio Processing Pipelines +At the core of the SOF firmware is the DSP pipeline. A pipeline is a directed graph consisting of connected audio modules (components) that process streams of data. +* **Endpoints:** Pipelines connect external interfaces (like I2S/HDA/DMIC DAIs - Digital Audio Interfaces) to host DMA buffers. +* **Scheduling:** Each pipeline is scheduled to run periodically based on its timing requirements and deadlines. SOF provides an LL (Low Latency) scheduler and an EDF (Earliest Deadline First) scheduler. + +### 2.4 Audio Components (Modules) +The firmware processing graph is assembled using individual audio modules, which are dynamically instantiated based on the topology file: +* **Host / DAI Components:** Read/write audio frames from/to DMA buffers or hardware interfaces. +* **Copier:** Moves data between buffers or other components without modification. +* **Volume / Mixer:** Changes signal amplitude or mixes multiple streams. +* **SRC (Sample Rate Converter):** Resamples audio streams. +* **Effect Modules:** EQs (Equalizers), DRCs (Dynamic Range Compressors), smart amplifiers, arrays, and other algorithmic components. + +### 2.5 Memory Management +The DSP handles multiple memory domains depending on the hardware (SRAM, L1 Cache, L2, external memory). +* **Heaps:** Different memory heaps exist for dynamic allocation (e.g., system heap, buffer heap, runtime heap) to ensure real-time constraints and avoid fragmentation. +* **Data Buffers:** Audio buffers are carefully allocated in appropriate memory to minimize power consumption and pipeline latency. + +## 3. Topologies + +The host driver parses a topology file (`.tplg`) which describes the expected processing graphs. Instead of hardcoding audio routing in the firmware, SOF uses these topology constraints. The firmware receives the component creation sequences, parameter configurations, and connections over IPC to construct pipelines at runtime. diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dda22470e38..65747ffe1a8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") message(FATAL_ERROR @@ -10,18 +10,17 @@ if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") ) endif() -if(NOT (${CMAKE_VERSION} VERSION_LESS "3.13.0")) - # CMake 3.13+ has less restrictive rules for target_link_libraries() - # Until we make 3.13 as required minimum version we want to - # use old behaviour for compatibility - cmake_policy(SET CMP0079 OLD) -endif() +find_package(Python3 COMPONENTS Interpreter) +set(PYTHON3 "${Python3_EXECUTABLE}") -option(BUILD_LIBRARY "Build library" OFF) option(BUILD_UNIT_TESTS "Build unit tests" OFF) +option(BUILD_UNIT_TESTS_HOST "Build unit tests for host" OFF) +option(BUILD_UNIT_TESTS_XTENSA_GCC "Build xtensa unit test using GCC" OFF) option(BUILD_CLANG_SCAN "Build for clang's scan-build" OFF) +option(BUILD_COUNTERS "Enable build counter(s), timestamps and any other +non-deterministic build features" OFF) -if(BUILD_LIBRARY) +if(CONFIG_LIBRARY OR BUILD_UNIT_TESTS_HOST OR CONFIG_ZEPHYR_POSIX) set(ARCH host) else() # firmware build supports only xtensa arch for now @@ -44,9 +43,14 @@ project(SOF C ASM) set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}") set(SOF_ROOT_BINARY_DIRECTORY "${PROJECT_BINARY_DIR}") +set(RIMAGE_TOP "${PROJECT_SOURCE_DIR}/tools/rimage") + # check git hooks include(scripts/cmake/git-hooks.cmake) +# Check submodules +include(scripts/cmake/git-submodules.cmake) + # most of other options are set on per-arch and per-target basis set(CMAKE_ASM_FLAGS -DASSEMBLY) @@ -62,6 +66,12 @@ add_library(sof_options INTERFACE) target_link_libraries(sof_options INTERFACE sof_public_headers) +if(BUILD_COUNTERS) +target_compile_definitions(sof_options INTERFACE BLD_COUNTERS=1) +else() +target_compile_definitions(sof_options INTERFACE BLD_COUNTERS=0) +endif() + # interface library that is used only as container for sof statically # linked libraries add_library(sof_static_libraries INTERFACE) @@ -84,43 +94,34 @@ set(GENERATED_DIRECTORY ${PROJECT_BINARY_DIR}/generated) file(MAKE_DIRECTORY ${GENERATED_DIRECTORY}/include) set(DOT_CONFIG_PATH ${GENERATED_DIRECTORY}/.config) -set(CONFIG_H_PATH ${GENERATED_DIRECTORY}/include/config.h) -set(VERSION_H_PATH ${GENERATED_DIRECTORY}/include/version.h) +set(CONFIG_H_PATH ${GENERATED_DIRECTORY}/include/autoconfig.h CACHE + PATH "Path to kconfig's .h output file") +set(VERSION_H_PATH ${GENERATED_DIRECTORY}/include/sof_versions.h) include(scripts/cmake/version.cmake) include(scripts/cmake/dist.cmake) -# cmake itself cannot depend on files that don't exist -# so to make it regenerate when .config file is created, -# we make it depend on containing directory -# NOTE: some filesystems may be unable to watch directory change, -# in that case cmake may need to be regenerated from CLI -set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS - ${GENERATED_DIRECTORY} ${DOT_CONFIG_PATH}) - -if(EXISTS ${DOT_CONFIG_PATH}) - read_kconfig_config(${DOT_CONFIG_PATH}) -endif() - -if(${CMAKE_VERSION} VERSION_LESS "3.12.0") - # FindPythonInterp is bugged and may sometimes be unable to find - # Python 3 when both Python 2 & 3 are in PATH, - # so it's always better to use CMake 3.12+ - find_package(PythonInterp 3.0) - set(PYTHON3 "${PYTHON_EXECUTABLE}") -else() - find_package(Python3 COMPONENTS Interpreter) - set(PYTHON3 "${Python3_EXECUTABLE}") -endif() - include(scripts/cmake/kconfig.cmake) +read_kconfig_config(${DOT_CONFIG_PATH}) + +# FIXME: this successful triggers CMake to re-run, however -imacros +# hides the generated .h dependency from CMake and most sources are NOT +# recompiled. +set_property(DIRECTORY APPEND + PROPERTY CMAKE_CONFIGURE_DEPENDS ${DOT_CONFIG_PATH}) add_dependencies(sof_public_headers genconfig check_version_h) target_include_directories(sof_public_headers INTERFACE ${GENERATED_DIRECTORY}/include) -if(BUILD_LIBRARY) - add_library(sof SHARED "") +include(scripts/cmake/uuid-registry.cmake) + +if(CONFIG_LIBRARY) + if (CONFIG_LIBRARY_STATIC) + add_library(sof STATIC "") + else() + add_library(sof SHARED "") + endif() target_link_libraries(sof PRIVATE sof_options) target_link_libraries(sof PRIVATE sof_static_libraries) install(TARGETS sof DESTINATION lib) @@ -162,6 +163,8 @@ install( ${PROJECT_SOURCE_DIR}/src/include/ipc ${PROJECT_SOURCE_DIR}/src/include/kernel ${PROJECT_SOURCE_DIR}/src/include/user + ${RIMAGE_TOP}/src/include/sof/kernel + ${RIMAGE_TOP}/src/include/sof/user DESTINATION include/sof PATTERN "*.h" ) @@ -169,6 +172,9 @@ install( add_library(sof_ld_flags INTERFACE) add_library(sof_ld_scripts INTERFACE) +target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/third_party_include) +link_directories(${PROJECT_SOURCE_DIR}/third_party_libraries) + # declare target with no sources to let cmake know about it add_executable(sof "") target_link_libraries(sof PRIVATE sof_options) @@ -176,7 +182,9 @@ target_link_libraries(sof PRIVATE sof_ld_scripts) target_link_libraries(sof PRIVATE sof_ld_flags) target_link_libraries(sof PRIVATE sof_static_libraries) +if (BUILD_COUNTERS) sof_add_build_counter_rule() +endif() add_subdirectory(src) diff --git a/CODEOWNERS b/CODEOWNERS index dabd581d16d1..9cd3ec9bcb48 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,78 +2,118 @@ # Each line is a file pattern followed by one or more owners. # These owners will be the default owners for everything in the repo. -* @lgirdwood @plbossart @mmaka1 @lbetlej @dbaluta @tlauda @jajanusz +* @lgirdwood @plbossart @mmaka1 @lbetlej @dbaluta @kv2019i # Order is important. The last matching pattern has the most precedence. -# So if a pull request only touches javascript files, only these owners -# will be requested to review. +# File patterns work mostly like .gitignore. Try to keep this file +# simple because it's literally impossible to test. +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners # include files -src/include/sof/dmic.h @singalsu -src/include/host/* @ranj063 +src/include/sof/drivers/dmic.h @singalsu src/include/ipc/** @thesofproject/steering-committee +src/include/ipc/** @randerwang @tmleman @pblaszko +src/include/ipc4/** @randerwang @tmleman @pblaszko src/include/kernel/** @thesofproject/steering-committee src/include/user/** @thesofproject/steering-committee -src/include/gdb/* @mrajwa -src/include/audio/kpb.h @mrajwa -src/include/audio/mux.h @akloniex +src/include/sof/debug/gdb/* @abonislawski +src/include/sof/audio/aria/* @abonislawski +src/include/sof/audio/kpb.h @fkwasowi @iganakov +src/include/sof/audio/mux.h @fkwasowi +src/include/sof/audio/up_down_mixer/* @abonislawski +src/include/sof/audio/codec_adapter/* @cujomalainey @abonislawski @dbaluta +src/include/sof/audio/module_adapter/* @ranj063 @jxstelter +src/include/sof/drivers/acp_dai_dma.h @bhiregoudar @sunilkumardommati +src/include/sof/drivers/afe* @yaochunhung # audio component -src/audio/src* @singalsu +src/audio/src* @singalsu @abonislawski +# src/audio/chain_dma* TODO +src/audio/copier/* @randerwang @abonislawski @pblaszko src/audio/eq* @singalsu -src/audio/fir* @singalsu -src/audio/iir* @singalsu +src/audio/eq_fir* @singalsu +src/audio/eq_iir* @singalsu src/audio/tone.c @singalsu -src/audio/kpb.c @mrajwa -src/audio/mux/* @akloniex +src/audio/kpb.c @fkwasowi @iganakov +src/audio/mux/* @fkwasowi +src/audio/dcblock* @thesofproject/google +src/audio/crossover* @thesofproject/google +src/audio/tdfb* @singalsu +src/audio/drc/* @thesofproject/google +src/audio/selector/* @tlissows +src/audio/up_down_mixer/* @abonislawski +src/audio/multiband_drc/* @thesofproject/google +src/audio/codec_adapter/* @cujomalainey @abonislawski @dbaluta +src/audio/module_adapter/* @ranj063 @jxstelter +src/audio/google/* @thesofproject/google # platforms -src/arch/xtensa/* @tlauda -src/platform/* @tlauda -src/platform/baytrail/* @xiulipan -src/platform/haswell/* @xiulipan @randerwang -src/platform/suecreek/* @lyakh -src/arch/xtensa/gdb/* @mrajwa +src/arch/xtensa/debug/gdb/* @abonislawski src/platform/imx8/** @dbaluta +src/platform/amd/** @bhiregoudar @sunilkumardommati +src/platform/mt8195/** @yaochunhung @kuanhsuncheng # drivers -src/drivers/intel/cavs/dmic.c @singalsu -src/drivers/intel/cavs/sue-iomux.c @lyakh -src/drivers/intel/haswell/* @randerwang +src/drivers/intel/dmic.c @singalsu src/drivers/imx/** @dbaluta src/drivers/dw/* @lyakh +src/drivers/amd/* @bhiregoudar @sunilkumardommati +src/drivers/mediatek/mt8195/* @yaochunhung @kuanhsuncheng # other libs -src/host/* @ranj063 src/math/* @singalsu -src/ipc/* @xiulipan @bardliao -src/ipc/sue-ipc.c @lyakh -src/lib/* @libinyang -src/gdb/* @mrajwa -src/schedule @tlauda @mrajwa +src/ipc/* @bardliao @tmleman @pblaszko +# src/lib/* TODO +src/debug/gdb/* @abonislawski +src/schedule @pblaszko @marcinszkudlinski @dbaluta @LaurentiuM1234 + +# samples +samples/audio/detect_test.c @iganakov # other helpers -test/** @jajanusz -scripts/* @xiulipan -rimage/* @xiulipan - -# tools(old soft) -tools/logger/* @xiulipan @bkokoszx @akloniex -tools/topology/* @ranj063 @xiulipan -tools/test/* @xiulipan +# Many files overridden by *.(ba)sh pattern below +# scripts/* TODO + +# tools(old 'soft' repo) +tools/logger/* @bkokoszx @akloniex +tools/topology/** @ranj063 +tools/topology/topology2/** @ranj063 @jsarha +tools/testbench/* @ranj063 tools/test/audio/* @singalsu -tools/eqctl/* @singalsu +tools/ctl/* @singalsu tools/tune/* @singalsu +tools/tune/crossover/* @thesofproject/google +tools/tune/dcblock/* @thesofproject/google +tools/tune/drc/* @thesofproject/google +tools/oss-fuzz/* @thesofproject/google + +zephyr/** @kv2019i @lyakh @iuliana-prodan @dbaluta @abonislawski +zephyr/lib/cpu.c @tmleman +zephyr/lib/alloc.c @dabekjakub +zephyr/lib/regions_mm.c @dabekjakub + +# installer +# installer/** TODO + +# CMake + +# Include only "top-level" CMakeLists.txt files; the other ones are just +# dumb list of source files and generate too much noise. +# /CMakeLists.txt TODO +#/*/CMakeLists.txt TODO +# /test/cmocka/CMakeLists.txt TODO + +# There's a small enough number of files in tools/ and little +# churn: keep it simple and take them all. +# FIXME: some topology CMakeLists.txt files are configuration files +# in disguise. Move them to actual configuration files. +# /tools/**/CMakeLists.txt TODO -# build system -**/CMakeLists.txt @jajanusz -**/Kconfig @jajanusz -scripts/cmake/** @jajanusz -scripts/kconfig/** @jajanusz +# *.sh TODO +# *.bash TODO +*trace.* @akloniex -# related fileds -*.sh @jajanusz -*trace.* @xiulipan @akloniex +/.github/ @dbaluta @cujomalainey @lgirdwood # You can also use email addresses if you prefer. #docs/* docs@example.com diff --git a/Kconfig b/Kconfig index 46c98af12ca3..a192aa93ab09 100644 --- a/Kconfig +++ b/Kconfig @@ -4,270 +4,4 @@ mainmenu "SOF $(PROJECTVERSION) Configuration" comment "Compiler: $(CC_VERSION_TEXT)" -menu "CAVS" - depends on CAVS - -config HP_MEMORY_BANKS - int "HP memory banks count" - default 8 - help - Available memory banks count for High Performance memory - Lowering available banks could result in lower power consumption - Too low count should result in unresponsive/crashing image due to not - enough space for FW base image - Banks are 64kb in size. - -config LP_MEMORY_BANKS - int "LP memory banks count" - default 0 - help - Available memory banks count for Low Power memory. - It can be used to turn ON/OFF LPSRAM bank/s. - Firmware will turn on only as many banks as are defined here. - -config LP_SRAM - bool - default LP_MEMORY_BANKS > 0 - help - Indicates that platform uses LPSRAM. - -config CAVS_LPS - bool "Intel cAVS Low Power Sequencer for Power Management" - depends on CAVS - default n - help - Select this to enable Intel cAVS Low Power Sequencer. - This option is required to support S0ix/D0ix mode - on cAVS platforms. - -endmenu - -config WAITI_DELAY - bool - default n - help - LX6 Xtensa platforms may require additional delay to flush loads - and stores before entering WAITI. - -config HOST_PTABLE - bool - default n - -config BOOT_LOADER - bool - default n - -config HAVE_RESET_VECTOR_ROM - bool - default n - help - Select if your platform has the reset vector - in ROM. - -config IRQ_MAP - bool - default n - -config DMA_GW - bool - default n - -config MEM_WND - bool - default n - -config INTEL_IOMUX - bool - default n - -config HW_LLI - bool - default n - help - Hardware linked list is the DW-DMA feature, which allows - to automatically reload the next programmed linked list - item from memory without stopping the transfer. Without - it the transfer stops after every lli read and FW needs - to manually setup the next transfer. - - Any platforms with hardware linked list support - should set this. - -config DW_DMA_AGGREGATED_IRQ - bool - default n - help - Some platforms cannot register interrupt per DW-DMA channel - and have the possibility only to register interrupts per - DMA controller, which require manual handling of aggregated - irq. - - Any platforms with DW-DMA aggregated interrupts support - should set this. - -config DMA_SUSPEND_DRAIN - bool - default n - help - Some platforms cannot just simple disable DMA - channel during the transfer, because it will - hang the whole DMA controller. Instead we can - suspend the channel and drain the FIFO in order - to stop the channel as soon as possible. - - Any platforms without the ability to disable - the DMA channel right away should set this. - -config DMA_FIFO_PARTITION - bool - default n - help - Some platforms require to manually set DMA - FIFO partitions before starting any transfer. - - Any platforms without automatic FIFO partitions - should set this. - -config INTERRUPT_LEVEL_1 - bool - default n - help - Select if the platform supports any interrupts of level 1. - Disabling this option allows for less memory consumption. - -config INTERRUPT_LEVEL_2 - bool - default n - help - Select if the platform supports any interrupts of level 2. - Disabling this option allows for less memory consumption. - -config INTERRUPT_LEVEL_3 - bool - default n - help - Select if the platform supports any interrupts of level 3. - Disabling this option allows for less memory consumption. - -config INTERRUPT_LEVEL_4 - bool - default n - help - Select if the platform supports any interrupts of level 4. - Disabling this option allows for less memory consumption. - -config INTERRUPT_LEVEL_5 - bool - default n - help - Select if the platform supports any interrupts of level 5. - Disabling this option allows for less memory consumption. - -source "src/Kconfig" - -choice - prompt "Optimization" - default OPTIMIZE_FOR_PERFORMANCE - help - Controls how compiler should optimize binary. - This config should affect only compiler settings and is - not meant to be used for conditional compilation of code. - -config OPTIMIZE_FOR_PERFORMANCE - bool "Optimize for performance" - help - Apply compiler optimizations prioritizing performance. - It means -O2 for GCC or equivalent for other compilers. - -config OPTIMIZE_FOR_SIZE - bool "Optimize for size" - help - Apply compiler optimizations prioritizing binary size. - It means -Os for GCC or equivalent for other compilers. - -config OPTIMIZE_FOR_DEBUG - bool "Optimize for debug" - help - Apply compiler optimizations prioritizing debugging experience. - It means -Og for GCC or equivalent for other compilers. - -config OPTIMIZE_FOR_NONE - bool "Don't optimize" - help - Apply no compiler optimizations. - It means -O0 for GCC or equivalent for other compilers. - -endchoice - -menu "Debug" - -config DEBUG - bool "Enable debug build" - default n - help - Select for debug build - -config GDB_DEBUG - bool "GDB Stub" - default n - help - Select for GDB debugging - -config DEBUG_HEAP - bool "Heap debug" - default n - help - Select for enable heap alloc debugging - -config DEBUG_BLOCK_FREE - bool "Blocks freeing debug" - default n - help - It enables checking if free was called multiple times on - already freed block of memory. Enabling this feature increases - number of memory writes and reads, due to checks for memory patterns - that may be performed on allocation and deallocation. - -config DEBUG_LOCKS - bool "Spinlock debug" - default n - help - It adds additional information to the spinlocks about - the current user of the lock. Also executes panic - on deadlock. - -config DEBUG_LOCKS_VERBOSE - bool "Spinlock verbose debug" - depends on DEBUG_LOCKS - default n - help - In addition to DEBUG_LOCKS it also adds spinlock traces - every time the lock is acquired. - -config BUILD_VM_ROM - bool "Build VM ROM" - default n - help - Select if you want to build VM ROM - -config DEBUG_IPC_COUNTERS - bool "IPC counters" - depends on CAVS - depends on DEBUG - default n - help - Select for enabling tracing IPC counter in SRAM_REG mailbox - -config PERFORMANCE_COUNTERS - bool "Performance counters" - default n - help - Enables tracing of simple performance measurements. - A basic use case is to measure number of platform & cpu clock ticks - passed between two checkpoints (init() and stamp()), for example - total time spent on running low latency scheduler tasks. - Platforms that gate cpu clock in wait-for-interrupt calls may also - use the stamp() macro periodically to find out how long the cpu - was in active/sleep state between the calls and estimate the cpu load. - -endmenu +source "Kconfig.sof" diff --git a/Kconfig.sof b/Kconfig.sof new file mode 100644 index 000000000000..29c6f549fca8 --- /dev/null +++ b/Kconfig.sof @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: BSD-3-Clause + + +config HOST_PTABLE + bool + default n + +config COMPILER_WORKAROUND_CACHE_ATTR + bool + default n + depends on XTENSA + help + Select this to activate use of functions instead of macros + to decide whether an address is cacheable or not. + There is a weird optimization bug with gcc10x and gcc8.1 + (with -O2 flags) on IMX platforms. See PR #4605. + +config COMPILER_INLINE_FUNCTION_OPTION + bool + default y if CAVS_VERSION_2_5 || ACE + default n + help + When enabled, -fno-inline-function option is not passed to compiler + +config COLD_STORE_EXECUTE_DRAM + bool "Execute and use cold data and code in DRAM" + help + Non-performance critical data and code can be kept in DRAM to be + accessed and executed there without copying to SRAM. Select this + option to enable this feature to save SRAM and to speed up SRAM + copying of performance-critical data and code. + + +config COLD_STORE_EXECUTE_DEBUG + bool "Enable checks for cold code on hot paths" + help + This enables an assert_can_be_cold() check, which causes an exception + if called in the LL task context and assert() evaluation is enabled. + +config FAST_GET + bool "Enable simple refcounting DRAM data copier" + help + Enable simple refcounting DRAM data copier for copying processing + module data from DRAM to SRAM when the data is needed and freeing + the SRAM when the data is not needed anymore. If multiple module + instances need the same chunk the same copy is used with reference + counting. Source is src/lib/fast-get.c. The option should be selected + on platforms, where __cold_rodata is supported. + +config SOF_OS_LINUX_COMPAT_PRIORITY + bool "Prioritize backwards compatibility for old Linux kernels" + help + Build option to maintain maximal backwards compatibility with old + versions of Linux SOF driver. When this is not set, firmware may + require newer version of host, and/or use features that are not + available in stable Linux kernel trees. + +rsource "Kconfig.xtos" + +rsource "src/Kconfig" + +if ZEPHYR_SOF_MODULE + rsource "Kconfig.zephyr-log" +endif + +menu "Debug" + +config DEBUG + bool "Enable debug build" + default n + help + Select for debug build + +config GDB_DEBUG + bool "GDB Stub" + default n + help + Select for GDB debugging + +config DEBUG_MEMORY_USAGE_SCAN + bool "Memory usage scan" + default y + help + It enables memory usage scan at demand in runtime. + This feature does not affect standard memory operations, + especially allocation and deallocation. + +config DEBUG_IPC_COUNTERS + bool "IPC counters" + depends on CAVS + depends on DEBUG + default n + help + Select for enabling tracing IPC counter in SRAM_REG mailbox + +config DEBUG_IPC_TIMINGS + bool "Enable IPC message handling time logging" + depends on DEBUG + default n + help + Adds a logging after IPC handling before putting IPC reply + to send queue. The logging contains both the reply and the + original request message headers and the time that it took + to process the request in micro seconds. The value can be + used to collect statistics on changes in firmware response + times. This also disables the logging of the received + request on core 0 to avoid flooding the logs too much. + +config SCHEDULE_LOG_CYCLE_STATISTICS + bool "Log cycles per tick statistics for each task separately" + default y + help + Log DSP cycle usage statistics about once per second (1ms * + 1024) for each task separately. The printed data is task's + meta information, average number of cycles/tick, and maximum + number of cycles/tick during the previous 1024 tick period. + +config PERFORMANCE_COUNTERS + bool "Performance counters" + default n + help + Enables tracing of simple performance measurements. + A basic use case is to measure number of platform & cpu clock ticks + passed between two checkpoints (init() and stamp()), for example + total time spent on running low latency scheduler tasks. + Platforms that gate cpu clock in wait-for-interrupt calls may also + use the stamp() macro periodically to find out how long the cpu + was in active/sleep state between the calls and estimate the cpu load. + +config PERFORMANCE_COUNTERS_COMPONENT + bool "Use performance counters to track component execution" + default n + depends on PERFORMANCE_COUNTERS + help + Use performance counters to trace low-latency task execution. + This enables to observe average and peak execution times at + audio component level granularity. + Results are reported via logging subsystem. + +config PERFORMANCE_COUNTERS_LL_TASKS + bool "Use performance counters to track LL task execution" + default n + depends on PERFORMANCE_COUNTERS + help + Use performance counters to trace low-latency task execution. + This enables to observe average and peak execution times at + task level granularity. + Results are reported via logging subsystem. + +config DSP_RESIDENCY_COUNTERS + bool "DSP residency counters" + default n + help + Enables simple DSP residency counters in SRAM_REG mailbox. + R0, R1, R2 are abstract states which can be used differently + based on platform implementation. + +endmenu diff --git a/Kconfig.xtos b/Kconfig.xtos new file mode 100644 index 000000000000..2aa6b991fe7a --- /dev/null +++ b/Kconfig.xtos @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# This file contains build options needed to support +# legacy driver code that still partially rely on XTOS +# definitions, even when used with Zephyr RTOS. +# +# When all platforms have moved over to native Zephyr +# drivers, this file can be removed + +config XT_WAITI_DELAY + bool + default n + help + LX6 Xtensa platforms may require additional delay to flush loads + and stores before entering WAITI. + +config XT_HAVE_RESET_VECTOR_ROM + bool + default n + help + Select if your platform has the reset vector + in ROM. + +config XT_IRQ_MAP + bool + default n + +config DMA_HW_LLI + bool + default n + help + Hardware linked list is DMA feature, which allows + to automatically reload the next programmed linked list + item from memory without stopping the transfer. Without + it the transfer stops after every lli read and FW needs + to manually setup the next transfer. + + Any platforms with hardware linked list support + should set this. + +config DMA_SUSPEND_DRAIN + bool + default n + help + Some platforms cannot just simple disable DMA + channel during the transfer, because it will + hang the whole DMA controller. Instead we can + suspend the channel and drain the FIFO in order + to stop the channel as soon as possible. + + Any platforms without the ability to disable + the DMA channel right away should set this. + +config DMA_FIFO_PARTITION + bool + default n + help + Some platforms require to manually set DMA + FIFO partitions before starting any transfer. + + Any platforms without automatic FIFO partitions + should set this. + +config XT_INTERRUPT_LEVEL_1 + bool + default n + help + Select if the platform supports any interrupts of level 1. + Disabling this option allows for less memory consumption. + +config XT_INTERRUPT_LEVEL_2 + bool + default n + help + Select if the platform supports any interrupts of level 2. + Disabling this option allows for less memory consumption. + +config XT_INTERRUPT_LEVEL_3 + bool + default n + help + Select if the platform supports any interrupts of level 3. + Disabling this option allows for less memory consumption. + +config XT_INTERRUPT_LEVEL_4 + bool + default n + help + Select if the platform supports any interrupts of level 4. + Disabling this option allows for less memory consumption. + +config XT_INTERRUPT_LEVEL_5 + bool + default n + help + Select if the platform supports any interrupts of level 5. + Disabling this option allows for less memory consumption. diff --git a/Kconfig.zephyr-log b/Kconfig.zephyr-log new file mode 100644 index 000000000000..ca0f54c64c82 --- /dev/null +++ b/Kconfig.zephyr-log @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "Logging" + +config ZEPHYR_LOG + bool "Enable Logging via Zephyr" + default n + help + Select for Zephyr logging support, and logging + via SOF will be disabled. If not selected, SOF + logging will be used. + +choice "SOF_LOG_LEVEL_CHOICE" + prompt "Max compiled-in log level for SOF" + default SOF_LOG_LEVEL_INF + depends on LOG + +config SOF_LOG_LEVEL_OFF + bool "Off" + help + Set log level to off + +config SOF_LOG_LEVEL_ERR + bool "Error" + help + Set log level to error + +config SOF_LOG_LEVEL_WRN + bool "Warning" + help + Set log level to warning + +config SOF_LOG_LEVEL_INF + bool "Info" + help + Set log level to info + +config SOF_LOG_LEVEL_DBG + bool "Debug" + help + Set log level to debug + +endchoice + +config SOF_LOG_LEVEL + int + depends on LOG + default 0 if SOF_LOG_LEVEL_OFF + default 1 if SOF_LOG_LEVEL_ERR + default 2 if SOF_LOG_LEVEL_WRN + default 3 if SOF_LOG_LEVEL_INF + default 4 if SOF_LOG_LEVEL_DBG + +config SOF_LOG_DBG_BUFFER + bool "Log buffer state on each consume/produce call" + default n + help + Dumps buffer struct audio_stream values on each call to comp_update_buffer_consume() + and comp_update_buffer_produce(). + WARNING: Produces too much log output which usually results in many log messaged been + dropped! Also, if selected log backend formats log messages at runtime, enabling this + option results in significant CPU load! + +endmenu diff --git a/LICENCE b/LICENCE index b222fca6da22..1f72cd21c9df 100644 --- a/LICENCE +++ b/LICENCE @@ -1,6 +1,13 @@ +// SOF reuses some dual licensed header files where interfaces must be maintained +// between SOF and other software. Where a dual licensed file contains the +// GPL (any version) as a license option, then SOF will always use the permissive +// license option (e.g. BSD, MIT or Apache or another permissive license) instead +// of the GPL option + /* * BSD 3 Clause * Copyright (c) 2016, Intel Corporation + * Copyright 2020 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,6 +59,55 @@ // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/* + * Copyright (c) 2006-2020 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. + */ + +/* + * The definitions in this file are derived from the OpenMAX AL version 1.1 + * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below. + * + * Copyright (c) 2007-2010 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and/or associated documentation files (the + * "Materials "), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are 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 Materials. + * + * THE MATERIALS ARE 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 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + */ Files with ISC licence: @@ -75,46 +131,3 @@ scripts/kconfig/olddefconfig.py # AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Files with 2-Clause BSD licence: - -rimage/elf.h - -/* - * Derived from: - * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $ - * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $ - * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $ - * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $ - * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $ - * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $ - * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $ - * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $ - * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $ - * - * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. - * Copyright (c) 2001 David E. O'Brien - * Portions Copyright 2009 The Go Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ diff --git a/README.md b/README.md index d3b08e98918a..e1fa62ce9b09 100644 --- a/README.md +++ b/README.md @@ -1,100 +1,29 @@ # Sound Open Firmware ### Status -[![Build Status](https://travis-ci.org/thesofproject/sof.svg?branch=master)](https://travis-ci.org/thesofproject/sof) +[![Daily Actions](https://github.com/thesofproject/sof/actions/workflows/daily-tests.yml/badge.svg)](https://github.com/thesofproject/sof/actions/workflows/daily-tests.yml) +[![Zephyr Main Branch](https://github.com/thesofproject/sof/actions/workflows/zephyr-main.yml/badge.svg)](https://github.com/thesofproject/sof/actions/workflows/zephyr-main.yml) -### Documentation - -See [docs](https://thesofproject.github.io/latest/index.html) - -### Prerequisites - -* Docker -* CMake (version >= 3.10) - -### Build Instructions - -1. Create directory in checked out repo for build files: -``` -mkdir build && cd build -``` - -2. Run configuration for your toolchain: - -Baytrail / Cherrytrail: - -``` -cmake -DTOOLCHAIN=xtensa-byt-elf -DROOT_DIR=`pwd`/../../xtensa-root/xtensa-byt-elf .. -``` - -Haswell / Broadwell: - -``` -cmake -DTOOLCHAIN=xtensa-hsw-elf -DROOT_DIR=`pwd`/../../xtensa-root/xtensa-hsw-elf .. -``` - -Apollolake: - -``` -cmake -DTOOLCHAIN=xtensa-apl-elf -DROOT_DIR=`pwd`/../../xtensa-root/xtensa-apl-elf .. -``` - -Cannonlake: - -``` -cmake -DTOOLCHAIN=xtensa-cnl-elf -DROOT_DIR=`pwd`/../../xtensa-root/xtensa-cnl-elf .. -``` +### Community -3. Apply default config for your platform. +[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/thesofproject/community) -Baytrail: +Additional community support is available via the `#sof` channel in the Zephyr Project Discord server. See the [Resources section of the @zephyrproject-rtos GitHub organization README](https://github.com/zephyrproject-rtos#resources) for Discord access information. -``` -make baytrail_defconfig -``` - -Cherrytrail: - -``` -make cherrytrail_defconfig -``` - -Haswell: - -``` -make haswell_defconfig -``` - -Broadwell: - -``` -make broadwell_defconfig -``` +### Documentation -Apollolake: +See [docs](https://thesofproject.github.io/latest/index.html) -``` -make apollolake_defconfig -``` +## Quickstart -Cannonlake: +You can easily set up the complete SOF development environment, including Zephyr SDK and QEMU, by running our interactive installer script. To run the installer locally: +```bash +curl -fsSLo sdk-install.sh https://raw.githubusercontent.com/thesofproject/vscode-workspace/main/sdk-install.sh +bash sdk-install.sh ``` -make cannonlake_defconfig -``` - -4. (Optional) Customize your configuration -``` -make menuconfig -``` - -5. Build firmware - -``` -make bin -# or `make bin -j` for parallel build -``` +The script will guide you through the process of installing system dependencies, cloning the repositories, configuring Python virtual environments, and setting up the Zephyr SDK and QEMU. ## Running the tests diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 000000000000..832d4eb12098 --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.21.0) + +find_package(Zephyr HINTS $ENV{ZEPHYR_BASE}) +project(sample_sof) + +target_sources(app PRIVATE + src/main.c + ) + +zephyr_library_include_directories(app PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../src/arch/xtensa/include + ${CMAKE_CURRENT_SOURCE_DIR}/../src/include + ) diff --git a/app/Kconfig b/app/Kconfig new file mode 100644 index 000000000000..56ada456367e --- /dev/null +++ b/app/Kconfig @@ -0,0 +1,16 @@ +config SCHED_CPU_MASK_PIN_ONLY + default y if SMP + +config SMP_BOOT_DELAY + default y if SMP + +# Allow compiler to determine whether to generate FLIX instructions. +choice COMPILER_CODEGEN_VLIW + default COMPILER_CODEGEN_VLIW_AUTO if "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "xt-clang" +endchoice + +source "Kconfig.zephyr" + +if SOC_FAMILY_INTEL_ADSP + rsource "boards/intel_adsp/Kconfig.defconfig" +endif diff --git a/app/boards/acp_6_0_adsp.conf b/app/boards/acp_6_0_adsp.conf new file mode 100644 index 000000000000..b527ea3753a7 --- /dev/null +++ b/app/boards/acp_6_0_adsp.conf @@ -0,0 +1,40 @@ +CONFIG_REMBRANDT=y +CONFIG_HAVE_AGENT=n +CONFIG_DCACHE_LINE_SIZE_DETECT=n +CONFIG_DCACHE_LINE_SIZE=128 +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_SHARED_INTERRUPTS=n +CONFIG_ZEPHYR_LOG=n +CONFIG_DMA=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=n +CONFIG_AMS=n +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_CROSSOVER=n +CONFIG_COMP_DRC=n +CONFIG_COMP_MULTIBAND_DRC=n +CONFIG_COMP_TONE=n +CONFIG_COMP_KPB=n +CONFIG_MAXIM_DSM=n +CONFIG_COMP_ASRC=n +CONFIG_COMP_IGO_NR=n +CONFIG_COMP_COPIER=n +CONFIG_COMP_RTNR=n +CONFIG_COMP_ARIA=n +CONFIG_COMP_BASEFW_IPC4=n +CONFIG_COMP_UP_DOWN_MIXER=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_MIXER=n +CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_08000=n +CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100=n diff --git a/app/boards/acp_7_0_adsp.conf b/app/boards/acp_7_0_adsp.conf new file mode 100644 index 000000000000..3c5f791fdcb6 --- /dev/null +++ b/app/boards/acp_7_0_adsp.conf @@ -0,0 +1,52 @@ +CONFIG_ACP_7_0=y +CONFIG_HAVE_AGENT=n +CONFIG_DCACHE_LINE_SIZE_DETECT=n +CONFIG_DCACHE_LINE_SIZE=128 +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_SHARED_INTERRUPTS=n +CONFIG_ZEPHYR_LOG=y +CONFIG_LOG_MODE_DEFERRED=n +CONFIG_LOG_MODE_MINIMAL=y +CONFIG_DMA=y +CONFIG_DMA_DOMAIN=n +CONFIG_ZEPHYR_NATIVE_DRIVERS=y +CONFIG_INTC_AMD_ACP=y +CONFIG_DMA_AMD_ACP_HOST=y +CONFIG_DMA_AMD_ACP_SDW=y +CONFIG_DAI_AMD_SDW=y +CONFIG_AMS=n +CONFIG_WRAP_ACTUAL_POSITION=y +CONFIG_TRACE=n +CONFIG_COMP_VOLUME=y +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_CROSSOVER=n +CONFIG_COMP_DRC=n +CONFIG_COMP_MULTIBAND_DRC=n +CONFIG_COMP_TONE=n +CONFIG_COMP_KPB=n +CONFIG_MAXIM_DSM=n +CONFIG_COMP_ASRC=n +CONFIG_COMP_IGO_NR=n +CONFIG_COMP_COPIER=n +CONFIG_COMP_RTNR=n +CONFIG_COMP_ARIA=n +CONFIG_COMP_BASEFW_IPC4=n +CONFIG_COMP_UP_DOWN_MIXER=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_MIXER=n +CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_08000=n +CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000=n +CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100=n +CONFIG_CORE_COUNT=1 +CONFIG_FORMAT_CONVERT_HIFI3=n diff --git a/app/boards/imx8mp_evk_mimx8ml8_adsp.conf b/app/boards/imx8mp_evk_mimx8ml8_adsp.conf new file mode 100644 index 000000000000..da9e56d759a4 --- /dev/null +++ b/app/boards/imx8mp_evk_mimx8ml8_adsp.conf @@ -0,0 +1,12 @@ +CONFIG_IMX8M=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n +CONFIG_DMA=y +CONFIG_DMA_NXP_SDMA=y +CONFIG_DAI_NXP_MICFIL=y +CONFIG_TRACE=n +CONFIG_SHARED_INTERRUPTS=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y +CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y +CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK=y diff --git a/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay b/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay new file mode 100644 index 000000000000..6748b621985a --- /dev/null +++ b/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay @@ -0,0 +1,29 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&sdma3 { + status = "okay"; +}; + +&sai3 { + rx-fifo-watermark = <65>; + tx-fifo-watermark = <65>; + fifo-depth = <128>; + rx-sync-mode = <1>; + status = "okay"; +}; + +&micfil { + status = "okay"; +}; diff --git a/app/boards/imx8mp_evk_mimx8ml8_m7_ddr.conf b/app/boards/imx8mp_evk_mimx8ml8_m7_ddr.conf new file mode 100644 index 000000000000..290f27a2b933 --- /dev/null +++ b/app/boards/imx8mp_evk_mimx8ml8_m7_ddr.conf @@ -0,0 +1,15 @@ +CONFIG_IMX8M_CM7=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y +CONFIG_CACHE_MANAGEMENT=y +CONFIG_NOCACHE_MEMORY=y +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_SHARED_INTERRUPTS=y +CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK=y +CONFIG_ROMSTART_RELOCATION_ROM=y +CONFIG_DMA_NXP_SOF_HOST_DMA_ALIGN=32 +CONFIG_DMA=y +CONFIG_DMA_NXP_SDMA=y +CONFIG_DAI_NXP_SAI=y +CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y +CONFIG_COMP_ASRC=n + diff --git a/app/boards/imx8mp_evk_mimx8ml8_m7_ddr.overlay b/app/boards/imx8mp_evk_mimx8ml8_m7_ddr.overlay new file mode 100644 index 000000000000..3f712e3ad00c --- /dev/null +++ b/app/boards/imx8mp_evk_mimx8ml8_m7_ddr.overlay @@ -0,0 +1,27 @@ +/* + * Copyright 2026 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&sdma3 { + status = "okay"; +}; + +&sai3 { + pinctrl-0 = <&sai3_default>; + pinctrl-names = "default"; + rx-fifo-watermark = <64>; + tx-fifo-watermark = <64>; + fifo-depth = <96>; + rx-sync-mode = <1>; + status = "okay"; +}; diff --git a/app/boards/imx8qm_mek_mimx8qm6_adsp.conf b/app/boards/imx8qm_mek_mimx8qm6_adsp.conf new file mode 100644 index 000000000000..6c8eb26b6e9a --- /dev/null +++ b/app/boards/imx8qm_mek_mimx8qm6_adsp.conf @@ -0,0 +1,8 @@ +CONFIG_IMX8=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n +CONFIG_DMA=y +CONFIG_DMA_NXP_EDMA_ENABLE_HALFMAJOR_IRQ=y +CONFIG_SHARED_INTERRUPTS=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y diff --git a/app/boards/imx8qm_mek_mimx8qm6_adsp.overlay b/app/boards/imx8qm_mek_mimx8qm6_adsp.overlay new file mode 100644 index 000000000000..87df0d8194da --- /dev/null +++ b/app/boards/imx8qm_mek_mimx8qm6_adsp.overlay @@ -0,0 +1,56 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&lpuart2 { + /* note for developers: this is disabled + * because the firmware running on one of the M4 + * cores uses the same LPUART instance. As such, + * to debug you need to make sure that: + * 1) Your SOF DTS doesn't include the RPMSG + * DTS but instead the base DTS (which is + * "imx8qm-mek.dts") + * 2) Your u-boot doesn't include the M4 firmware + * images. + */ + status = "disabled"; +}; + +&sai1 { + rx-fifo-watermark = <48>; + tx-fifo-watermark = <2>; + fifo-depth = <48>; + rx-sync-mode = <1>; + status = "okay"; +}; + +&esai0 { + fifo-depth = <96>; + /* note: not the same semantic as SAI TX watermark. For ESAI + * the DMA requests are generated when number of empty slots + * in the transmit FIFO reaches the chosen watermark value. + * In this case, DMA requests will be generated when transmit + * FIFO has 128 empty slots (equivalent to the FIFO having + * 2 words since the FIFO depth is 128 words). + */ + tx-fifo-watermark = <126>; + rx-fifo-watermark = <96>; + /* needed for internal CS42888 workaround. Remove when possible */ + esai-clock-configuration = , + ; + status = "okay"; +}; + +&edma0 { + status = "okay"; +}; diff --git a/app/boards/imx8qxp_mek_mimx8qx6_adsp.conf b/app/boards/imx8qxp_mek_mimx8qx6_adsp.conf new file mode 100644 index 000000000000..e6b3ce395c39 --- /dev/null +++ b/app/boards/imx8qxp_mek_mimx8qx6_adsp.conf @@ -0,0 +1,8 @@ +CONFIG_IMX8X=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n +CONFIG_DMA=y +CONFIG_DMA_NXP_EDMA_ENABLE_HALFMAJOR_IRQ=y +CONFIG_SHARED_INTERRUPTS=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y diff --git a/app/boards/imx8qxp_mek_mimx8qx6_adsp.overlay b/app/boards/imx8qxp_mek_mimx8qx6_adsp.overlay new file mode 100644 index 000000000000..8011407417d8 --- /dev/null +++ b/app/boards/imx8qxp_mek_mimx8qx6_adsp.overlay @@ -0,0 +1,42 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&sai1 { + rx-fifo-watermark = <48>; + tx-fifo-watermark = <2>; + fifo-depth = <48>; + rx-sync-mode = <1>; + status = "okay"; +}; + +&esai0 { + fifo-depth = <96>; + /* note: not the same semantic as SAI TX watermark. For ESAI + * the DMA requests are generated when number of empty slots + * in transmit FIFO reaches the chosen watermark value. + * In this case, DMA requests will be generated when transmit + * FIFO has 126 empty slots (equivalent to the FIFO having + * 2 words since the FIFO depth is 128 words). + */ + tx-fifo-watermark = <126>; + rx-fifo-watermark = <96>; + /* needed for internal CS42888 workaround. Remove when possible */ + esai-clock-configuration = , + ; + status = "okay"; +}; + +&edma0 { + status = "okay"; +}; diff --git a/app/boards/imx8ulp_evk_mimx8ud7_adsp.conf b/app/boards/imx8ulp_evk_mimx8ud7_adsp.conf new file mode 100644 index 000000000000..5df4c87d3c18 --- /dev/null +++ b/app/boards/imx8ulp_evk_mimx8ud7_adsp.conf @@ -0,0 +1,14 @@ +CONFIG_IMX8ULP=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n + + +CONFIG_DMA=y +CONFIG_DMA_NXP_EDMA_ENABLE_HALFMAJOR_IRQ=y + +# TODO: remove this from here. Should be extracted +# from DAI bespoke configuration or DTS. +CONFIG_SAI_FIFO_WORD_SIZE=2 + +CONFIG_ZEPHYR_NATIVE_DRIVERS=y diff --git a/app/boards/imx8ulp_evk_mimx8ud7_adsp.overlay b/app/boards/imx8ulp_evk_mimx8ud7_adsp.overlay new file mode 100644 index 000000000000..1fe8b6551a56 --- /dev/null +++ b/app/boards/imx8ulp_evk_mimx8ud7_adsp.overlay @@ -0,0 +1,42 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&edma2 { + status = "okay"; +}; + +&sai5 { + rx-fifo-watermark = <8>; + tx-fifo-watermark = <1>; + fifo-depth = <8>; + rx-sync-mode = <1>; + status = "okay"; +}; + +/* + * TODO: this node shouldn't be here. For now, we only support + * the EVK board in Zephyr, while in SOF we support the EVK and + * the EVK9 boards. This is an issue because the two boards use + * different SAI instances for BT communication (SAI5 - EVK, + * SAI6 - EVK9). Ideally, we should have two boards in Zephyr + * and SOF but for now this workaround will suffice. + */ +&sai6 { + rx-fifo-watermark = <8>; + tx-fifo-watermark = <1>; + fifo-depth = <8>; + rx-sync-mode = <1>; + tx-dataline = <2>; + status = "okay"; +}; diff --git a/app/boards/imx93_evk_mimx9352_a55.conf b/app/boards/imx93_evk_mimx9352_a55.conf new file mode 100644 index 000000000000..7c0667da66b9 --- /dev/null +++ b/app/boards/imx93_evk_mimx9352_a55.conf @@ -0,0 +1,29 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 + +# Enable dynamic interrupts +CONFIG_DYNAMIC_INTERRUPTS=y + +CONFIG_ARM64_VA_BITS_40=y +CONFIG_ARM64_PA_BITS_40=y + +CONFIG_DCACHE_LINE_SIZE_DETECT=n +CONFIG_DCACHE_LINE_SIZE=64 + +CONFIG_IMX93_A55=y + +# DAI-related configurations +CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y +CONFIG_SAI_IMX93_ERRATA_051421=y + +# DMA-related configurations +CONFIG_DMA=y +CONFIG_DMA_NXP_EDMA_ENABLE_HALFMAJOR_IRQ=y + +# needed because EDMA uses same interrupt for multiple +# channels. +CONFIG_SHARED_INTERRUPTS=y + +CONFIG_ZEPHYR_NATIVE_DRIVERS=y diff --git a/app/boards/imx93_evk_mimx9352_a55.overlay b/app/boards/imx93_evk_mimx9352_a55.overlay new file mode 100644 index 000000000000..6db63b22bd69 --- /dev/null +++ b/app/boards/imx93_evk_mimx9352_a55.overlay @@ -0,0 +1,67 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /delete-node/ memory@d0000000; + /* Inmate memory, reserved through "mem=1248MB" boot argument, + * starts at 0xce000000. + */ + dram: memory@ce000000 { + reg = <0xce000000 DT_SIZE_M(1)>; + }; + + /* TODO: all of the nodes below are needed by SOF and should + * be removed once all drivers used by SOF have been moved + * to Zephyr. + * + * They are added in the DTS for the sake of not using hardcoded + * values in mmu_regions.c + */ + mu2_a: memory@42430000 { + reg = <0x42430000 DT_SIZE_K(64)>; + }; + + outbox: memory@ce100000 { + reg = <0xce100000 DT_SIZE_K(4)>; + }; + + inbox: memory@ce101000 { + reg = <0xce101000 DT_SIZE_K(4)>; + }; + + stream: memory@ce102000 { + reg = <0xce102000 DT_SIZE_K(4)>; + }; + + /* TODO: this is extremely bad and it's needed here because of + * the fact that the DMA buffer shared by host and FW is situated + * in this region. For now, it's easier to create a mapping for the + * whole region but in the future a mapping should only be created + * for the physical address of the buffer sent to the FW through an + * IPC. + */ + host_ram: memory@80000000 { + reg = <0x80000000 DT_SIZE_M(1024)>; + }; + + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&sai3 { + tx-fifo-watermark = <2>; + rx-fifo-watermark = <96>; + fifo-depth = <96>; + rx-sync-mode = <1>; + status = "okay"; +}; + +&edma4 { + status = "okay"; +}; diff --git a/app/boards/imx95_evk_mimx9596_m7_ddr.conf b/app/boards/imx95_evk_mimx9596_m7_ddr.conf new file mode 100644 index 000000000000..aec33d7c7e91 --- /dev/null +++ b/app/boards/imx95_evk_mimx9596_m7_ddr.conf @@ -0,0 +1,12 @@ +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y +CONFIG_IMX95=y + +CONFIG_SAI_HAS_MCLK_CONFIG_OPTION=y + +CONFIG_DMA=y +CONFIG_DMA_NXP_EDMA_ENABLE_HALFMAJOR_IRQ=y +CONFIG_DMA_NXP_EDMA_ALIGN=32 +CONFIG_DMA_NXP_SOF_HOST_DMA_ALIGN=32 + +CONFIG_SHARED_INTERRUPTS=y diff --git a/app/boards/imx95_evk_mimx9596_m7_ddr.overlay b/app/boards/imx95_evk_mimx9596_m7_ddr.overlay new file mode 100644 index 000000000000..f1d2cce00781 --- /dev/null +++ b/app/boards/imx95_evk_mimx9596_m7_ddr.overlay @@ -0,0 +1,40 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* this'll select Cortex-M SysTick as the system timer */ + chosen { + /delete-property/ zephyr,system-timer; + }; + + host_dma: dma { + compatible = "nxp,sof-host-dma"; + dma-channels = <32>; + #dma-cells = <0>; + }; +}; + +&sai3 { + tx-fifo-watermark = <8>; + rx-fifo-watermark = <96>; + fifo-depth = <96>; + rx-sync-mode = <1>; + dmas = <&edma2 30 60>, <&edma2 31 61>; + status = "okay"; +}; + +&edma2 { + compatible = "nxp,edma"; + reg = <0x42000000 (DT_SIZE_K(64) * 33)>; + valid-channels = <30>, <31>; + interrupts = <143 0>, <143 0>; + /delete-property/ nxp,version; + /delete-property/ dma-channels; + /delete-property/ dma-requests; + /delete-property/ no-error-irq; + /delete-property/ channels-shared-irq-mask; + status = "okay"; +}; diff --git a/app/boards/intel_adsp/Kconfig.defconfig b/app/boards/intel_adsp/Kconfig.defconfig new file mode 100644 index 000000000000..f705960eee1a --- /dev/null +++ b/app/boards/intel_adsp/Kconfig.defconfig @@ -0,0 +1,185 @@ +# Common defaults for all Intel ADSP SOF targets +# +# SPDX-License-Identifier: BSD-3-Clause + +# --- +# NOTICE! defconfig files cannot override settings that already have +# a default set. Thus some settings (especially choice values with +# a default), must be set in the board config files even if the value +# is same for all Intel DSPs. +# --- + +# SOF / IPC configuration +# ----------------------- + +config IPC4_BASE_FW_INTEL + default y + +# SOF / audio pipeline and module settings +# ---------------------------------------- + +config COMP_CHAIN_DMA + default y + +config COMP_KPB + default y + +config COMP_UP_DOWN_MIXER + default y + +config COMP_VOLUME_WINDOWS_FADE + default y + +config FAST_GET + default y + +config FORMAT_A_LAW + default y + +config FORMAT_FLOAT + default y + +config FORMAT_MU_LAW + default y + +config FORMAT_U8 + default y + +config PCM_CONVERTER_FORMAT_A_LAW + default y + +config PCM_CONVERTER_FORMAT_FLOAT + default y + +config PCM_CONVERTER_FORMAT_MU_LAW + default y + +config PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32 + default y + +config PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32 + default y + +config PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32 + default y + +config PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32 + default y + +config PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32 + default y + +config PCM_CONVERTER_FORMAT_S24_C32_AND_S24_C24 + default y + +config PCM_CONVERTER_FORMAT_U8 + default y + +config PIPELINE_2_0 + default y + +# SOF / infrastructure +# ---------------------------------------- + +config L3_HEAP + default y if ACE + +config ZEPHYR_DP_SCHEDULER + default y + +config ZEPHYR_NATIVE_DRIVERS + default y + +# SOF / logging +# ---------------------------------------- + +config ZEPHYR_LOG + default y + +# Zephyr / device drivers +# ---------------------------------------- + +config CLOCK_CONTROL + default y + +# note: CONFIG_CLOCK_CONTROL_ADSP is enabled by default +# based on DT definition. + +config DAI + default y + +config DAI_INTEL_DMIC + default y + +config DAI_INTEL_SSP + default y + +config INTEL_ADSP_IPC + default y + +config INTEL_ADSP_TIMER + default y + +config MM_DRV + default y + +config UAOL + default y if ACE + + +# # Zephyr / power settings +# ---------------------------------------- + +config PM + default y + +config PM_DEVICE + default y + +config PM_DEVICE_RUNTIME + default y + +config PM_DEVICE_SYSTEM_MANAGED + default y + +config POWER_DOMAIN + default y + +# note: POWER_DOMAIN_INTEL_ADSP will be set based on DT + +# Zephyr / logging +# ---------------------------------------- + +config LOG_BACKEND_ADSP_MTRACE + default y + +config LOG_FUNC_NAME_PREFIX_ERR + default y + +config LOG_FUNC_NAME_PREFIX_WRN + default y + +config LOG_FUNC_NAME_PREFIX_INF + default y + +config LOG_FUNC_NAME_PREFIX_DBG + default y + +config LOG_CORE_ID_PREFIX + default y + +config LOG_TIMESTAMP_64BIT + default y + +# Zephyr / debugging +# ---------------------------------------- + +config ZTEST + default SOF_BOOT_TEST_SUPPORTED && SOF_BOOT_TEST_ALLOWED + +# Zephyr / debug slot manager +# ---------------------------------------- + +config INTEL_ADSP_DEBUG_SLOT_MANAGER + default y + diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf new file mode 100644 index 000000000000..4f124eee5285 --- /dev/null +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -0,0 +1,88 @@ +CONFIG_METEORLAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="mtl" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_ARIA=y +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DRC=y +CONFIG_COMP_TESTER=m +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_SRC_LITE=y +CONFIG_COMP_MFCC=y +CONFIG_COMP_MULTIBAND_DRC=y +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_SAMPLE_KEYPHRASE=y +CONFIG_COMP_STFT_PROCESS=y + +# SOF / audio modules / mocks +# This mock is part of official sof-bin releases because the CI that +# tests it can't use extra CONFIGs. See #9410, #8722 and #9386 +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m +CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK=y + +# SOF / infrastructure +CONFIG_AMS=y +CONFIG_COUNTER=y +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=y +CONFIG_LL_WATCHDOG=y +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2 +CONFIG_SOF_TELEMETRY=y +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=y +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=y +CONFIG_ZEPHYR_TWB_SCHEDULER=y +CONFIG_COLD_STORE_EXECUTE_DRAM=y +CONFIG_SOF_BOOT_TEST_SUPPORTED=n + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_AUTH_SUPPORT=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 +CONFIG_LIBRARY_BUILD_LIB=y + +# SOF / logging +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_DEBUG_COREDUMP=y +CONFIG_DEBUG_COREDUMP_BACKEND_INTEL_ADSP_MEM_WINDOW=y +CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_LLEXT_EXPERIMENTAL=y +CONFIG_MODULES=y +CONFIG_TIMING_FUNCTIONS=y +CONFIG_WATCHDOG=y +CONFIG_TIMESLICE_PER_THREAD=y +CONFIG_THREAD_RUNTIME_STATS=y +CONFIG_SCHED_THREAD_USAGE=y + +# Zephyr / device drivers +CONFIG_DAI_DMIC_HAS_OWNERSHIP=y +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DMA_DW_LLI_POOL_SIZE=50 +CONFIG_DMA_INTEL_ADSP_GPDMA=y +CONFIG_MEMORY_WIN_2_SIZE=12288 +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=3 +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=38400000 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 + +# Zephyr / power settings +CONFIG_ADSP_IDLE_CLOCK_GATING=y +CONFIG_ADSP_IMR_CONTEXT_SAVE=n +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_PM_DEVICE_RUNTIME_ASYNC=n + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_LOG_BACKEND_SOF_PROBE=n +CONFIG_WINSTREAM_CONSOLE=n +CONFIG_LOG_FLUSH_SLEEP_US=5000 diff --git a/app/boards/intel_adsp_ace20_lnl.conf b/app/boards/intel_adsp_ace20_lnl.conf new file mode 100644 index 000000000000..2aef09fb9a4a --- /dev/null +++ b/app/boards/intel_adsp_ace20_lnl.conf @@ -0,0 +1,65 @@ +CONFIG_LUNARLAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="lnl" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_ARIA=y +CONFIG_COMP_DRC=m +CONFIG_COMP_TESTER=m +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_SAMPLE_KEYPHRASE=y +CONFIG_COMP_STFT_PROCESS=y + +# SOF / infrastructure +CONFIG_AMS=y +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2 +CONFIG_SOF_TELEMETRY=y +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=y +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=y +CONFIG_COLD_STORE_EXECUTE_DRAM=y + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_AUTH_SUPPORT=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 +CONFIG_LIBRARY_MANAGER=y + +# SOF / logging +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_COUNTER=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_LLEXT_EXPERIMENTAL=y +CONFIG_MODULES=y +CONFIG_TIMING_FUNCTIONS=y + +# Zephyr / device drivers +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DAI_DMIC_HAS_OWNERSHIP=n +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_MEMORY_WIN_2_SIZE=12288 +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=3 +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=38400000 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 + +# Zephyr / power settings +CONFIG_ADSP_IDLE_CLOCK_GATING=y +CONFIG_ADSP_IMR_CONTEXT_SAVE=y +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_PM_DEVICE_RUNTIME_ASYNC=n + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_WINSTREAM_CONSOLE=n +CONFIG_LOG_FLUSH_SLEEP_US=5000 diff --git a/app/boards/intel_adsp_ace30_ptl.conf b/app/boards/intel_adsp_ace30_ptl.conf new file mode 100644 index 000000000000..a79ca6e67764 --- /dev/null +++ b/app/boards/intel_adsp_ace30_ptl.conf @@ -0,0 +1,77 @@ +CONFIG_PANTHERLAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="ptl" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_TESTER=m +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_FORMAT_CONVERT_HIFI3=n + +# SOF / audio modules / mocks +# This mock is part of official sof-bin releases because the CI that +# tests it can't use extra CONFIGs. See #9410, #8722 and #9386 +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m +CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK=y +CONFIG_COMP_STFT_PROCESS=y + +# SOF / infrastructure +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2 +CONFIG_SOF_TELEMETRY=y +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=y +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=y +CONFIG_COLD_STORE_EXECUTE_DRAM=y + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_AUTH_SUPPORT=y +CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 +CONFIG_LIBRARY_BUILD_LIB=y +CONFIG_LIBRARY_DEFAULT_MODULAR=y + +# SOF / logging +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_COUNTER=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_LLEXT_EXPERIMENTAL=y +CONFIG_MODULES=y + +# Zephyr / device drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_DMIC_HAS_OWNERSHIP=n +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_DMA_DW_LLI_POOL_SIZE=50 +CONFIG_MEMORY_WIN_2_SIZE=12288 +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=3 +CONFIG_XTENSA_MMU_NUM_L2_TABLES=128 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 + +# Zephyr / power settings +CONFIG_ADSP_IMR_CONTEXT_SAVE=y +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_PM_DEVICE_RUNTIME_ASYNC=n + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_LOG_FLUSH_SLEEP_US=5000 +CONFIG_WINSTREAM_CONSOLE=n + +# Userspace options +CONFIG_USERSPACE=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_ALLOC=y +CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y +CONFIG_SOF_STACK_SIZE=8192 +CONFIG_SOF_USERSPACE_PROXY=y +CONFIG_MAX_THREAD_BYTES=3 diff --git a/app/boards/intel_adsp_ace30_ptl_sim.conf b/app/boards/intel_adsp_ace30_ptl_sim.conf new file mode 100644 index 000000000000..477450d2d271 --- /dev/null +++ b/app/boards/intel_adsp_ace30_ptl_sim.conf @@ -0,0 +1,47 @@ +CONFIG_PANTHERLAKE=y +CONFIG_IPC_MAJOR_4=y + +# turn off SOF drivers +CONFIG_COMP_SRC=y + +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y + +# power settings +CONFIG_PM=n + +# enable Zephyr drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 +CONFIG_DAI_DMIC_HAS_OWNERSHIP=y +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DAI_INTEL_SSP=n +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_DMA_DW_LLI_POOL_SIZE=50 +CONFIG_INTEL_MODULES=n +CONFIG_LIBRARY_MANAGER=n + +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_RIMAGE_SIGNING_SCHEMA="ptl" + +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_LOG=n +CONFIG_LOG_MODE_DEFERRED=n +CONFIG_LOG_FUNC_NAME_PREFIX_INF=n +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 + +CONFIG_LOG_BACKEND_ADSP_MTRACE=n +CONFIG_SOF_LOG_LEVEL_INF=n +CONFIG_SOF_LOG_LEVEL_OFF=y +CONFIG_ZEPHYR_LOG=n + +CONFIG_INTEL_ADSP_IPC=y + + +# Temporary disabled options +CONFIG_PM_DEVICE_RUNTIME=n +CONFIG_PM_DEVICE_POWER_DOMAIN=n +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_COMP_KPB=n + +CONFIG_USERSPACE=y diff --git a/app/boards/intel_adsp_ace30_wcl.conf b/app/boards/intel_adsp_ace30_wcl.conf new file mode 100644 index 000000000000..999a3c309d41 --- /dev/null +++ b/app/boards/intel_adsp_ace30_wcl.conf @@ -0,0 +1,64 @@ +CONFIG_WILDCATLAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="ptl" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_TESTER=m +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_FORMAT_CONVERT_HIFI3=n + +# SOF / audio modules / mocks +# This mock is part of official sof-bin releases because the CI that +# tests it can't use extra CONFIGs. See #9410, #8722 and #9386 +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m +CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK=y +CONFIG_COMP_STFT_PROCESS=y + +# SOF / infrastructure +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2 +CONFIG_SOF_TELEMETRY=y +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=y +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=y +CONFIG_COLD_STORE_EXECUTE_DRAM=y + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 +CONFIG_LIBRARY_BUILD_LIB=y +CONFIG_LIBRARY_DEFAULT_MODULAR=y + +# SOF / logging +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_LLEXT_EXPERIMENTAL=y +CONFIG_MODULES=y + +# Zephyr / device drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_DMIC_HAS_OWNERSHIP=n +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_MEMORY_WIN_2_SIZE=12288 +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=3 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 + +# Zephyr / power settings +CONFIG_ADSP_IMR_CONTEXT_SAVE=y +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_PM_DEVICE_RUNTIME_ASYNC=n + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_LOG_FLUSH_SLEEP_US=5000 +CONFIG_WINSTREAM_CONSOLE=n diff --git a/app/boards/intel_adsp_ace30_wcl_sim.conf b/app/boards/intel_adsp_ace30_wcl_sim.conf new file mode 100644 index 000000000000..288305be6313 --- /dev/null +++ b/app/boards/intel_adsp_ace30_wcl_sim.conf @@ -0,0 +1,43 @@ +CONFIG_WILDCATLAKE=y +CONFIG_IPC_MAJOR_4=y + +# turn off SOF drivers +CONFIG_COMP_SRC=y + +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y + +# power settings +CONFIG_PM=n + +# enable Zephyr drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 +CONFIG_DAI_DMIC_HAS_OWNERSHIP=y +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DAI_INTEL_SSP=n +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_INTEL_MODULES=n +CONFIG_LIBRARY_MANAGER=n +CONFIG_INTEL_ADSP_TIMER=y + +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_RIMAGE_SIGNING_SCHEMA="ptl" + +CONFIG_LOG=n +CONFIG_LOG_MODE_DEFERRED=n +CONFIG_LOG_FUNC_NAME_PREFIX_INF=n +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 + +CONFIG_LOG_BACKEND_ADSP_MTRACE=n +CONFIG_SOF_LOG_LEVEL_INF=n +CONFIG_SOF_LOG_LEVEL_OFF=y +CONFIG_ZEPHYR_LOG=n + +# Temporary disabled options +CONFIG_PM_DEVICE_RUNTIME=n +CONFIG_PM_DEVICE_POWER_DOMAIN=n +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_COMP_KPB=n + +CONFIG_USERSPACE=y diff --git a/app/boards/intel_adsp_ace40_nvl.conf b/app/boards/intel_adsp_ace40_nvl.conf new file mode 100644 index 000000000000..becef1a65f10 --- /dev/null +++ b/app/boards/intel_adsp_ace40_nvl.conf @@ -0,0 +1,62 @@ +CONFIG_NOVALAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="nvl" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_SRC=y +CONFIG_COMP_ARIA=y +CONFIG_COMP_DRC=y +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_TESTER=y +CONFIG_FORMAT_CONVERT_HIFI3=n + +# SOF / infrastructure +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2 +CONFIG_COLD_STORE_EXECUTE_DRAM=y + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 +CONFIG_LIBRARY_BUILD_LIB=y +CONFIG_LIBRARY_DEFAULT_MODULAR=y + +# SOF / logging +CONFIG_TRACE=n +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_LLEXT_EXPERIMENTAL=y +CONFIG_MODULES=y + +# Zephyr / device drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_DMIC_HAS_OWNERSHIP=n +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=3 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 + +# Zephyr / power settings +CONFIG_ADSP_IMR_CONTEXT_SAVE=y +CONFIG_PM_POLICY_CUSTOM=y +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_SRAM_RETENTION_MODE=n +CONFIG_PM_DEVICE_RUNTIME_ASYNC=n + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_WINSTREAM_CONSOLE=n +CONFIG_LOG_RUNTIME_FILTERING=y +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=1 + +# Zephyr / debug: temporary, until fixed +CONFIG_GDBSTUB=n diff --git a/app/boards/intel_adsp_ace40_nvls.conf b/app/boards/intel_adsp_ace40_nvls.conf new file mode 100644 index 000000000000..becef1a65f10 --- /dev/null +++ b/app/boards/intel_adsp_ace40_nvls.conf @@ -0,0 +1,62 @@ +CONFIG_NOVALAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="nvl" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_SRC=y +CONFIG_COMP_ARIA=y +CONFIG_COMP_DRC=y +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_TESTER=y +CONFIG_FORMAT_CONVERT_HIFI3=n + +# SOF / infrastructure +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2 +CONFIG_COLD_STORE_EXECUTE_DRAM=y + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_BASE_ADDRESS=0xa0688000 +CONFIG_LIBRARY_BUILD_LIB=y +CONFIG_LIBRARY_DEFAULT_MODULAR=y + +# SOF / logging +CONFIG_TRACE=n +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_LLEXT=y +CONFIG_LLEXT_STORAGE_WRITABLE=y +CONFIG_LLEXT_EXPERIMENTAL=y +CONFIG_MODULES=y + +# Zephyr / device drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_DMIC_HAS_OWNERSHIP=n +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_MM_DRV_INTEL_VIRTUAL_REGION_COUNT=3 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 + +# Zephyr / power settings +CONFIG_ADSP_IMR_CONTEXT_SAVE=y +CONFIG_PM_POLICY_CUSTOM=y +CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y +CONFIG_SRAM_RETENTION_MODE=n +CONFIG_PM_DEVICE_RUNTIME_ASYNC=n + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_WINSTREAM_CONSOLE=n +CONFIG_LOG_RUNTIME_FILTERING=y +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=1 + +# Zephyr / debug: temporary, until fixed +CONFIG_GDBSTUB=n diff --git a/app/boards/intel_adsp_cavs25.conf b/app/boards/intel_adsp_cavs25.conf new file mode 100644 index 000000000000..7cd938ec7ff8 --- /dev/null +++ b/app/boards/intel_adsp_cavs25.conf @@ -0,0 +1,57 @@ +CONFIG_TIGERLAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="tgl-cavs" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_ARIA=y +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DRC=y +CONFIG_COMP_MFCC=y +CONFIG_COMP_MULTIBAND_DRC=y +CONFIG_COMP_VOLUME_WINDOWS_FADE=y +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_PCM_CONVERTER_FORMAT_S16LE=y +CONFIG_PCM_CONVERTER_FORMAT_S24LE=y +CONFIG_PCM_CONVERTER_FORMAT_S32LE=y +CONFIG_PCM_CONVERTER_FORMAT_S24_3LE=y + +# SOF / infrastructure +CONFIG_AMS=y +CONFIG_LP_MEMORY_BANKS=1 +CONFIG_HP_MEMORY_BANKS=30 + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=n + +# SOF / logging +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_DEBUG_COREDUMP=y +CONFIG_DEBUG_COREDUMP_BACKEND_INTEL_ADSP_MEM_WINDOW=y +CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +# Zephyr / device drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DMA_DW_LLI_POOL_SIZE=100 +CONFIG_DMA_DW_HW_LLI=y +CONFIG_DMA_DW_FIFO_PARTITION=y +CONFIG_DMA_INTEL_ADSP_GPDMA_HAS_LLP=y + +# Zephyr / power settings +CONFIG_PM_POLICY_CUSTOM=y + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_LOG_BACKEND_ADSP_MTRACE=y +CONFIG_LOG_FUNC_NAME_PREFIX_ERR=y +CONFIG_LOG_FUNC_NAME_PREFIX_WRN=y +CONFIG_LOG_FUNC_NAME_PREFIX_INF=y +CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y +CONFIG_LOG_TIMESTAMP_64BIT=y +CONFIG_WINSTREAM_CONSOLE=n diff --git a/app/boards/intel_adsp_cavs25_tgph.conf b/app/boards/intel_adsp_cavs25_tgph.conf new file mode 100644 index 000000000000..0c1d1dab1ad6 --- /dev/null +++ b/app/boards/intel_adsp_cavs25_tgph.conf @@ -0,0 +1,59 @@ +CONFIG_TIGERLAKE=y +CONFIG_RIMAGE_SIGNING_SCHEMA="tgl-cavs" + +# SOF / IPC configuration +CONFIG_IPC_MAJOR_4=y + +# SOF / audio pipeline and module settings +CONFIG_COMP_ARIA=y +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DRC=y +CONFIG_COMP_MFCC=y +CONFIG_COMP_MULTIBAND_DRC=y +CONFIG_COMP_VOLUME_WINDOWS_FADE=y +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_PCM_CONVERTER_FORMAT_S16LE=y +CONFIG_PCM_CONVERTER_FORMAT_S24LE=y +CONFIG_PCM_CONVERTER_FORMAT_S32LE=y +CONFIG_PCM_CONVERTER_FORMAT_S24_3LE=y + +# SOF / infrastructure +CONFIG_LP_MEMORY_BANKS=1 +CONFIG_HP_MEMORY_BANKS=30 + +# SOF / loadable modules +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=n + +# SOF / logging +CONFIG_SOF_LOG_LEVEL_INF=y + +# Zephyr / OS features +CONFIG_DEBUG_COREDUMP=y +CONFIG_DEBUG_COREDUMP_BACKEND_INTEL_ADSP_MEM_WINDOW=y +CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +# Zephyr / device drivers +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DMA_DW_LLI_POOL_SIZE=100 +CONFIG_DMA_DW_HW_LLI=y +CONFIG_DMA_DW_FIFO_PARTITION=y +CONFIG_DMA_INTEL_ADSP_GPDMA_HAS_LLP=y + +# Zephyr / power settings +CONFIG_PM=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_PM_POLICY_CUSTOM=y + +# Zephyr / logging +CONFIG_LOG_BACKEND_ADSP=n +CONFIG_LOG_BACKEND_ADSP_MTRACE=y +CONFIG_LOG_FUNC_NAME_PREFIX_ERR=y +CONFIG_LOG_FUNC_NAME_PREFIX_WRN=y +CONFIG_LOG_FUNC_NAME_PREFIX_INF=y +CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y +CONFIG_LOG_TIMESTAMP_64BIT=y +CONFIG_WINSTREAM_CONSOLE=n diff --git a/app/boards/mt8186_mt8186_adsp.conf b/app/boards/mt8186_mt8186_adsp.conf new file mode 100644 index 000000000000..0d44864b6144 --- /dev/null +++ b/app/boards/mt8186_mt8186_adsp.conf @@ -0,0 +1,6 @@ +# Boilerplate. Because the "Platform" is a kconfig "choice" (of which +# "MTK" is an member), it can't be selected automatically from other +# kconfigs, nor expressed as a default. Don't put anything else here. +# Board-level config goes in Zephyr (and ideally in DTS). App-level +# config goes in prj.conf. +CONFIG_MTK=y diff --git a/app/boards/mt8188_mt8188_adsp.conf b/app/boards/mt8188_mt8188_adsp.conf new file mode 100644 index 000000000000..0b77906a891f --- /dev/null +++ b/app/boards/mt8188_mt8188_adsp.conf @@ -0,0 +1,10 @@ +# Boilerplate. Because the "Platform" is a kconfig "choice" (of which +# "MTK" is an member), it can't be selected automatically from other +# kconfigs, nor expressed as a default. Don't put anything else here. +# Board-level config goes in Zephyr (and ideally in DTS). App-level +# config goes in prj.conf. +CONFIG_MTK=y + +# Override project default setting so 1 millisecond is exactly +# represented by an integral number of ticks. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=13000 diff --git a/app/boards/mt8195_mt8195_adsp.conf b/app/boards/mt8195_mt8195_adsp.conf new file mode 100644 index 000000000000..0b77906a891f --- /dev/null +++ b/app/boards/mt8195_mt8195_adsp.conf @@ -0,0 +1,10 @@ +# Boilerplate. Because the "Platform" is a kconfig "choice" (of which +# "MTK" is an member), it can't be selected automatically from other +# kconfigs, nor expressed as a default. Don't put anything else here. +# Board-level config goes in Zephyr (and ideally in DTS). App-level +# config goes in prj.conf. +CONFIG_MTK=y + +# Override project default setting so 1 millisecond is exactly +# represented by an integral number of ticks. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=13000 diff --git a/app/boards/mt8196_mt8196_adsp.conf b/app/boards/mt8196_mt8196_adsp.conf new file mode 100644 index 000000000000..0d44864b6144 --- /dev/null +++ b/app/boards/mt8196_mt8196_adsp.conf @@ -0,0 +1,6 @@ +# Boilerplate. Because the "Platform" is a kconfig "choice" (of which +# "MTK" is an member), it can't be selected automatically from other +# kconfigs, nor expressed as a default. Don't put anything else here. +# Board-level config goes in Zephyr (and ideally in DTS). App-level +# config goes in prj.conf. +CONFIG_MTK=y diff --git a/app/boards/mt8365_mt8365_adsp.conf b/app/boards/mt8365_mt8365_adsp.conf new file mode 100644 index 000000000000..7c9d3647e8cc --- /dev/null +++ b/app/boards/mt8365_mt8365_adsp.conf @@ -0,0 +1,10 @@ +# Boilerplate. Because the "Platform" is a kconfig "choice" (of which +# "MTK" is an member), it can't be selected automatically from other +# kconfigs, nor expressed as a default. Don't put anything else here. +# Board-level config goes in Zephyr (and ideally in DTS). App-level +# config goes in prj.conf. +CONFIG_MTK=y + +# Override project default setting so 1 millisecond is exactly +# represented by an integral number of ticks. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=13000 \ No newline at end of file diff --git a/app/boards/native_sim_libfuzzer.conf b/app/boards/native_sim_libfuzzer.conf new file mode 100644 index 000000000000..ece1e35845c9 --- /dev/null +++ b/app/boards/native_sim_libfuzzer.conf @@ -0,0 +1,11 @@ +# See https://docs.zephyrproject.org/latest/build/kconfig/setting.html#initial-conf + +CONFIG_ZEPHYR_POSIX=y +CONFIG_ASSERT=y +CONFIG_EXCEPTION_DEBUG=y +CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y +CONFIG_SYS_HEAP_BIG_ONLY=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y +CONFIG_ARCH_POSIX_LIBFUZZER=y +CONFIG_ZEPHYR_POSIX_FUZZ_TICKS=100 +CONFIG_ZEPHYR_LOG=n diff --git a/app/boards/qemu_xtensa_dc233c.conf b/app/boards/qemu_xtensa_dc233c.conf new file mode 100644 index 000000000000..effed89802af --- /dev/null +++ b/app/boards/qemu_xtensa_dc233c.conf @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause +CONFIG_IPC_MAJOR_4=y +CONFIG_ZTEST=y +CONFIG_MM_DRV=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y + +# Ensure the kernel can exit QEMU on shutdown/panic +CONFIG_REBOOT=y diff --git a/app/boards/qemu_xtensa_dc233c_mmu.conf b/app/boards/qemu_xtensa_dc233c_mmu.conf new file mode 100644 index 000000000000..8489a30197e6 --- /dev/null +++ b/app/boards/qemu_xtensa_dc233c_mmu.conf @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +CONFIG_IPC_MAJOR_4=y +CONFIG_USERSPACE=y +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_MM_DRV=y +CONFIG_ZEPHYR_NATIVE_DRIVERS=y + +# Ensure the kernel can exit QEMU on shutdown/panic +CONFIG_REBOOT=y diff --git a/app/compr/README.txt b/app/compr/README.txt new file mode 100644 index 000000000000..a9c28957edbb --- /dev/null +++ b/app/compr/README.txt @@ -0,0 +1,37 @@ +Cadence Codec Configuration Overlays +===================================== + +This directory contains Kconfig overlay files for enabling Cadence codec support +in SOF firmware builds. + +Prerequisites +------------- +The Cadence codec libraries must be placed in the cadence_libs directory, one level +up from the SOF project directory: + sof/../cadence_libs/ + +Available Overlay Files +----------------------- +cadence.conf - Base Cadence codec module only (no individual codecs) +mp3.conf - MP3 decoder and encoder +aac.conf - AAC decoder +vorbis.conf - Vorbis decoder +all_codecs.conf - All supported codecs (MP3, AAC, Vorbis) + +Usage Examples +-------------- +Use with scripts/xtensa-build-zephyr.py via -o parameter: + +# Base module only (e.g., for Tiger Lake) +scripts/xtensa-build-zephyr.py tgl -o app/compr/cadence.conf + +# Single codec +scripts/xtensa-build-zephyr.py mtl -o app/compr/mp3.conf + +# Multiple codecs (use separate -o for each) +scripts/xtensa-build-zephyr.py mtl -o app/compr/mp3.conf -o app/compr/aac.conf + +# All codecs +scripts/xtensa-build-zephyr.py mtl -o app/compr/all_codecs.conf + +For more information about Cadence codecs, see the SOF documentation. diff --git a/app/compr/aac.conf b/app/compr/aac.conf new file mode 100644 index 000000000000..2adf1db86007 --- /dev/null +++ b/app/compr/aac.conf @@ -0,0 +1,4 @@ +# Cadence AAC decoder +CONFIG_CADENCE_CODEC=y +CONFIG_CADENCE_CODEC_AAC_DEC=y +CONFIG_CADENCE_CODEC_AAC_DEC_LIB="../cadence_libs/xa_aac_dec.a" diff --git a/app/compr/all_codecs.conf b/app/compr/all_codecs.conf new file mode 100644 index 000000000000..26b507f7f452 --- /dev/null +++ b/app/compr/all_codecs.conf @@ -0,0 +1,11 @@ +# All Cadence codecs (MP3, AAC, Vorbis) +CONFIG_CADENCE_CODEC=y +CONFIG_CADENCE_CODEC_MP3_DEC=y +CONFIG_CADENCE_CODEC_MP3_DEC_LIB="../cadence_libs/xa_mp3_dec.a" +CONFIG_CADENCE_CODEC_MP3_ENC=y +CONFIG_CADENCE_CODEC_MP3_ENC_LIB="../cadence_libs/xa_mp3_enc.a" +CONFIG_CADENCE_CODEC_AAC_DEC=y +CONFIG_CADENCE_CODEC_AAC_DEC_LIB="../cadence_libs/xa_aac_dec.a" +CONFIG_CADENCE_CODEC_VORBIS_DEC=y +CONFIG_CADENCE_CODEC_VORBIS_DEC_LIB="../cadence_libs/xa_vorbis_dec.a" + diff --git a/app/compr/cadence.conf b/app/compr/cadence.conf new file mode 100644 index 000000000000..9223140cab73 --- /dev/null +++ b/app/compr/cadence.conf @@ -0,0 +1,2 @@ +# Cadence codec module base support +CONFIG_CADENCE_CODEC=y diff --git a/app/compr/mp3.conf b/app/compr/mp3.conf new file mode 100644 index 000000000000..968f97295f57 --- /dev/null +++ b/app/compr/mp3.conf @@ -0,0 +1,6 @@ +# Cadence MP3 decoder and encoder +CONFIG_CADENCE_CODEC=y +CONFIG_CADENCE_CODEC_MP3_DEC=y +CONFIG_CADENCE_CODEC_MP3_DEC_LIB="../cadence_libs/xa_mp3_dec.a" +CONFIG_CADENCE_CODEC_MP3_ENC=y +CONFIG_CADENCE_CODEC_MP3_ENC_LIB="../cadence_libs/xa_mp3_enc.a" diff --git a/app/compr/vorbis.conf b/app/compr/vorbis.conf new file mode 100644 index 000000000000..064ac71b6616 --- /dev/null +++ b/app/compr/vorbis.conf @@ -0,0 +1,4 @@ +# Cadence Vorbis decoder +CONFIG_CADENCE_CODEC=y +CONFIG_CADENCE_CODEC_VORBIS_DEC=y +CONFIG_CADENCE_CODEC_VORBIS_DEC_LIB="../cadence_libs/xa_vorbis_dec.a" diff --git a/app/configs/fuzz_IPC3_features.conf b/app/configs/fuzz_IPC3_features.conf new file mode 100644 index 000000000000..059bae416abc --- /dev/null +++ b/app/configs/fuzz_IPC3_features.conf @@ -0,0 +1 @@ +# See main file fuzz_features.conf diff --git a/app/configs/fuzz_IPC4_features.conf b/app/configs/fuzz_IPC4_features.conf new file mode 100644 index 000000000000..55c6796a46cc --- /dev/null +++ b/app/configs/fuzz_IPC4_features.conf @@ -0,0 +1,5 @@ +# See main file fuzz_features.conf + +CONFIG_COMP_UP_DOWN_MIXER=y +CONFIG_COMP_ARIA=y +CONFIG_PIPELINE_2_0=y diff --git a/app/configs/fuzz_asan.conf b/app/configs/fuzz_asan.conf new file mode 100644 index 000000000000..a4b504ea7617 --- /dev/null +++ b/app/configs/fuzz_asan.conf @@ -0,0 +1 @@ +CONFIG_ASAN=y diff --git a/app/configs/fuzz_coverage.conf b/app/configs/fuzz_coverage.conf new file mode 100644 index 000000000000..baa08487a428 --- /dev/null +++ b/app/configs/fuzz_coverage.conf @@ -0,0 +1,2 @@ +CONFIG_COVERAGE=y +CONFIG_COVERAGE_NATIVE_SOURCE=y diff --git a/app/configs/fuzz_features.conf b/app/configs/fuzz_features.conf new file mode 100644 index 000000000000..0a2efca0a1b8 --- /dev/null +++ b/app/configs/fuzz_features.conf @@ -0,0 +1,50 @@ +# The goal of this file is to: +# 1. Fuzz more code +# 2. Reduce the gap between fuzzed SOF and the real thing. + +# KConfig warnings are NOT fatal so you must always INSPECT build logs when changing +# .conf files. See https://github.com/thesofproject/sof/issues/9386 + +# Note 1. is not as simple as enabling as many CONFIG_ as possible. Enabling some CONFIG_ +# can technically _disable_ some code paths. But the opposite is more common so let's add +# more. + +# In the longer term we should have some more elaborate configuration framework to reduce +# duplicate/diverge between fuzzing and production but also across product +# generations. Something like config fragments including each other? Not something as +# complicated as Yocto fragments but something more flexible than +# https://docs.zephyrproject.org/latest/build/kconfig/setting.html#initial-conf +# Or maybe use "snippets"? +# https://docs.zephyrproject.org/latest/build/snippets/writing.html +# +# Discuss in https://github.com/thesofproject/sof/issues/9386 + +# Many of these features are too far from IPC to make any fuzzing difference. But as long +# as they reduce the size of the textual difference between build-fuzz/zephyr/.config and +# build-xxx/zephyr/.config, they make that manual comparison easier which is still a win. + + +CONFIG_COUNTER=y + +CONFIG_PROBE=y + +CONFIG_CRYPTO=y + +CONFIG_LOG_TIMESTAMP_64BIT=y +CONFIG_MM_DRV=y + +CONFIG_DMA=y + +CONFIG_DAI=y + +CONFIG_PM_DEVICE=y +CONFIG_POWER_DOMAIN=y + +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DRC=y +CONFIG_COMP_KPB=y + +CONFIG_MATH_LUT_SINE_FIXED=y +CONFIG_MATH_EXP=y +CONFIG_MATH_IIR_DF2T=y diff --git a/app/configs/fuzz_ubsan.conf b/app/configs/fuzz_ubsan.conf new file mode 100644 index 000000000000..ceae016bdc4f --- /dev/null +++ b/app/configs/fuzz_ubsan.conf @@ -0,0 +1 @@ +CONFIG_UBSAN=y diff --git a/app/configs/lnl/modules.conf b/app/configs/lnl/modules.conf new file mode 100644 index 000000000000..fbef3ae182c7 --- /dev/null +++ b/app/configs/lnl/modules.conf @@ -0,0 +1,22 @@ +CONFIG_DTS_CODEC=m +CONFIG_SAMPLE_SMART_AMP=m +CONFIG_COMP_STUBS=y +CONFIG_COMP_MIXIN_MIXOUT=m +CONFIG_COMP_FIR=m +CONFIG_COMP_IIR=m +CONFIG_COMP_DRC=m +CONFIG_COMP_MUX=m +CONFIG_COMP_SEL=m +CONFIG_COMP_SRC=m +CONFIG_COMP_ARIA=m +CONFIG_COMP_ASRC=m +CONFIG_COMP_MFCC=m +CONFIG_COMP_RTNR=m +CONFIG_COMP_TDFB=m +CONFIG_COMP_IGO_NR=m +CONFIG_COMP_VOLUME=m +CONFIG_COMP_DCBLOCK=m +CONFIG_COMP_CROSSOVER=m +CONFIG_COMP_MULTIBAND_DRC=m +CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING=m +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m diff --git a/app/configs/mtl/modules.conf b/app/configs/mtl/modules.conf new file mode 100644 index 000000000000..36ad94c263ab --- /dev/null +++ b/app/configs/mtl/modules.conf @@ -0,0 +1,23 @@ +CONFIG_DTS_CODEC=m +CONFIG_SAMPLE_SMART_AMP=m +CONFIG_COMP_STUBS=y +CONFIG_COMP_MIXIN_MIXOUT=m +CONFIG_COMP_FIR=m +CONFIG_COMP_IIR=m +CONFIG_COMP_DRC=m +CONFIG_COMP_MUX=m +CONFIG_COMP_SEL=m +CONFIG_COMP_SRC=m +CONFIG_COMP_ARIA=m +CONFIG_COMP_ASRC=m +CONFIG_COMP_MFCC=m +CONFIG_COMP_RTNR=m +CONFIG_COMP_TDFB=m +CONFIG_COMP_IGO_NR=m +CONFIG_COMP_VOLUME=m +CONFIG_COMP_DCBLOCK=m +CONFIG_COMP_CROSSOVER=m +CONFIG_COMP_MULTIBAND_DRC=m +CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING=m +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m +CONFIG_COMP_TESTER=m diff --git a/app/configs/repro-build.conf b/app/configs/repro-build.conf new file mode 100644 index 000000000000..25e49e619e6c --- /dev/null +++ b/app/configs/repro-build.conf @@ -0,0 +1,3 @@ +CONFIG_OUTPUT_DISASSEMBLY=y +CONFIG_OUTPUT_DISASSEMBLY_WITH_SOURCE=n +CONFIG_MODULES=n diff --git a/app/ctf_kernel_traces_overlay.conf b/app/ctf_kernel_traces_overlay.conf new file mode 100644 index 000000000000..9cbbe33735cd --- /dev/null +++ b/app/ctf_kernel_traces_overlay.conf @@ -0,0 +1,9 @@ +# enable traces from Zephyr kernel + +CONFIG_TRACING_BACKEND_ADSP_MEMORY_WINDOW=y +CONFIG_TRACING_ASYNC=n +CONFIG_TRACING_SYNC=y +CONFIG_TRACING=y +CONFIG_TRACING_CTF=y +CONFIG_THREAD_NAME=y +CONFIG_DEBUG_THREAD_INFO=y diff --git a/app/debug_overlay.conf b/app/debug_overlay.conf new file mode 100644 index 000000000000..e99910ebfff1 --- /dev/null +++ b/app/debug_overlay.conf @@ -0,0 +1,33 @@ +CONFIG_DEBUG=y +CONFIG_ASSERT=y + +CONFIG_ZTEST_NO_YIELD=n +CONFIG_ZTEST_SUMMARY=n +CONFIG_ZTEST_TEST_DELAY_MS=1 +CONFIG_SOF_BOOT_TEST_ALLOWED=y +CONFIG_TEST_EXTRA_STACK_SIZE=7168 + +CONFIG_DAI_VERBOSE_GLITCH_WARNINGS=y + +# Following options can be enabled additionally, +# but will incur a higher runtime cost, so are thus +# disabled by default. +# +# CONFIG_STACK_SENTINEL=y +# CONFIG_SYS_HEAP_VALIDATE=y +# CONFIG_SPIN_VALIDATE=y +# CONFIG_SPIN_LOCK_TIME_LIMIT=50000 + +CONFIG_COLD_STORE_EXECUTE_DEBUG=y + +# GDB stub + +CONFIG_GDBSTUB=y +CONFIG_GDBSTUB_ENTER_IMMEDIATELY=n + +# Logging options +# Set default runtime log level to INFO (3) to maintain expected behavior in SOF CI. +# This ensures firmware starts with INFO level logging, same as previous configuration. +# Testing with runtime filtering enabled ensures the same feature set is validated. +# Note: This setting has no effect if CONFIG_LOG_RUNTIME_FILTERING is disabled. +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=3 diff --git a/app/debug_stream_overlay.conf b/app/debug_stream_overlay.conf new file mode 100644 index 000000000000..7edd6bf6709c --- /dev/null +++ b/app/debug_stream_overlay.conf @@ -0,0 +1,41 @@ +# Enable debug-stream protocol +CONFIG_SOF_DEBUG_STREAM_SLOT=y +# Enable text message sending with ds_msg() +CONFIG_SOF_DEBUG_STREAM_TEXT_MSG=y +# Add thread_info-client for debug stream +CONFIG_SOF_DEBUG_STREAM_THREAD_INFO=y +# Zephyr option for storing human readable thread names +CONFIG_THREAD_NAME=y +# For Zephyr to compile with thread names on PTL we need to increase THREAD_BYTES +CONFIG_MAX_THREAD_BYTES=4 +# Shrink number of CPU sections +# As the number of supported cores shrink, the available circular +# buffer size increases. This means increased bandwidth. This is +# particularly useful, when debugging a problem on core 0. +#CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS=1 + +# Direct the assert prints to debug stream +# This option obeys CONFIG_EXCEPTION_DUMP_HOOK_ONLY. If it is selected +# the assert print is sent only to debug stream. Without it the assert +# prints are printed with vprintk too, +CONFIG_SOF_DEBUG_STREAM_TEXT_MSG_ASSERT_PRINT=y + +# Debug window slot configuration 1 +# The CONFIG_SOF_TELEMETRY uses slot 2, but with performance and IO-performance +# it extends beyond slot 3. +CONFIG_MEMORY_WIN_2_SIZE=16384 +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n + +# If we turn telemetry off altogether, we can use slot 2. Slot 1 is used by mtrace +#CONFIG_SOF_DEBUG_STREAM_SLOT_NUMBER=2 +#CONFIG_SOF_TELEMETRY=n +#CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n +#CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n + +# Enable Zephyr exception printing hook; debug stream is sensitive to this option too +CONFIG_EXCEPTION_DUMP_HOOK=y +# Do not try to send exception prints through logs; this causes problems on PTL with mtrace +CONFIG_EXCEPTION_DUMP_HOOK_ONLY=y +# Print also backtrace through the exception hook +CONFIG_XTENSA_BACKTRACE_EXCEPTION_DUMP_HOOK=y diff --git a/app/llext_relocatable.conf b/app/llext_relocatable.conf new file mode 100644 index 000000000000..76b5339e1bb0 --- /dev/null +++ b/app/llext_relocatable.conf @@ -0,0 +1 @@ +CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y diff --git a/app/logging_mipisystcat_overlay.conf b/app/logging_mipisystcat_overlay.conf new file mode 100644 index 000000000000..a61b08b33911 --- /dev/null +++ b/app/logging_mipisystcat_overlay.conf @@ -0,0 +1,9 @@ +# Enable MIPI Sys-T Catalog FW logging +# ref: https://docs.zephyrproject.org/latest/samples/subsys/logging/syst/README.html +CONFIG_LOG_MIPI_SYST_ENABLE=y +CONFIG_LOG_MIPI_SYST_USE_CATALOG=y + +# set as output type of all SOF backends +CONFIG_LOG_BACKEND_ADSP_OUTPUT_SYST=y +CONFIG_LOG_BACKEND_ADSP_OUTPUT_SYST=y +CONFIG_LOG_BACKEND_ADSP_MTRACE_OUTPUT_SYST=y diff --git a/app/os_linux_overlay.conf b/app/os_linux_overlay.conf new file mode 100644 index 000000000000..18024b4e6106 --- /dev/null +++ b/app/os_linux_overlay.conf @@ -0,0 +1,27 @@ +# +# Overlay definitions to build SOF firmware for use +# with SOF driver in Linux kernel +# + +# As a general rule, update of SOF firmware shall never +# break existing systems by depending on Linux kernel patches +# that have been upstreamed after commercial availability +# of a product. +CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY=y + +# SOF Linux driver does not require FW to retain its +# state, so context save can be disabled +CONFIG_ADSP_IMR_CONTEXT_SAVE=n +CONFIG_SOF_USERSPACE_PROXY=n + +# Logging options + +# Set default runtime log level to INFO (3). +# Note: This setting only has effect when CONFIG_LOG_RUNTIME_FILTERING is enabled. +# By default, the runtime level equals the compile-time level, but it is explicitly +# set here to INFO to ensure expected behavior if platform configurations set a +# lower default level (e.g., ERROR). +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=3 + +# Disable additional VMH buffers to use memory for virtual regions. +CONFIG_VIRTUAL_HEAP_EXTENDED=n diff --git a/app/overlays/lnl/fpga_overlay.conf b/app/overlays/lnl/fpga_overlay.conf new file mode 100644 index 000000000000..0cc927a119ee --- /dev/null +++ b/app/overlays/lnl/fpga_overlay.conf @@ -0,0 +1,8 @@ +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 +CONFIG_XTENSA_CCOUNT_HZ=40000000 + +# improves LPSRAM and HPSRAM access time +CONFIG_SRAM_RETENTION_MODE=n + +CONFIG_IDC_TIMEOUT_US=50000 diff --git a/app/overlays/mt8196/ctc_overlay.conf b/app/overlays/mt8196/ctc_overlay.conf new file mode 100644 index 000000000000..f609996f03c1 --- /dev/null +++ b/app/overlays/mt8196/ctc_overlay.conf @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING=y diff --git a/app/overlays/mt8196/dts_overlay.conf b/app/overlays/mt8196/dts_overlay.conf new file mode 100644 index 000000000000..0160eaea199a --- /dev/null +++ b/app/overlays/mt8196/dts_overlay.conf @@ -0,0 +1,3 @@ +CONFIG_COMP_IIR=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_DTS_CODEC=y diff --git a/app/overlays/mt8196/waves_ctc_overlay.conf b/app/overlays/mt8196/waves_ctc_overlay.conf new file mode 100644 index 000000000000..fcd9e1e5730b --- /dev/null +++ b/app/overlays/mt8196/waves_ctc_overlay.conf @@ -0,0 +1,3 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y +CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING=y diff --git a/app/overlays/mt8196/waves_overlay.conf b/app/overlays/mt8196/waves_overlay.conf new file mode 100644 index 000000000000..6e0143275ba6 --- /dev/null +++ b/app/overlays/mt8196/waves_overlay.conf @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y diff --git a/app/overlays/mtl/dax_overlay.conf b/app/overlays/mtl/dax_overlay.conf new file mode 100644 index 000000000000..8bf245126b57 --- /dev/null +++ b/app/overlays/mtl/dax_overlay.conf @@ -0,0 +1,16 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING=y +CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK=n +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +CONFIG_SOF_STACK_SIZE=8192 +CONFIG_IDC_TIMEOUT_US=50000 + +# LLEXT +CONFIG_LLEXT_HEAP_SIZE=32 +# Disabled due to issues encountered on the MTL platform. +# See https://github.com/thesofproject/sof/issues/10370 +CONFIG_LLEXT_EXPERIMENTAL=n + +# Log settings +CONFIG_LOG_BUFFER_SIZE=8192 +CONFIG_MTRACE_LOG_CACHE_BUF_SIZE=12288 diff --git a/app/overlays/mtl/dts_overlay.conf b/app/overlays/mtl/dts_overlay.conf new file mode 100644 index 000000000000..9838aa891bb0 --- /dev/null +++ b/app/overlays/mtl/dts_overlay.conf @@ -0,0 +1,8 @@ +# Use DTS pre-built library for production +CONFIG_COMP_STUBS=n +# Google RTC library is WIP +CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK=y + +CONFIG_COMP_IIR=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_DTS_CODEC=y diff --git a/app/overlays/mtl/fpga_overlay.conf b/app/overlays/mtl/fpga_overlay.conf new file mode 100644 index 000000000000..0cc927a119ee --- /dev/null +++ b/app/overlays/mtl/fpga_overlay.conf @@ -0,0 +1,8 @@ +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 +CONFIG_XTENSA_CCOUNT_HZ=40000000 + +# improves LPSRAM and HPSRAM access time +CONFIG_SRAM_RETENTION_MODE=n + +CONFIG_IDC_TIMEOUT_US=50000 diff --git a/app/overlays/nvl/fpga_overlay.conf b/app/overlays/nvl/fpga_overlay.conf new file mode 100644 index 000000000000..176598376be0 --- /dev/null +++ b/app/overlays/nvl/fpga_overlay.conf @@ -0,0 +1,8 @@ +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 +CONFIG_XTENSA_CCOUNT_HZ=40105000 + +# limit logs to minimize runtime overhead of logging +CONFIG_SOF_LOG_LEVEL_ERR=y + +CONFIG_IDC_TIMEOUT_US=50000 diff --git a/app/overlays/ptl/ctc_overlay.conf b/app/overlays/ptl/ctc_overlay.conf new file mode 100644 index 000000000000..f609996f03c1 --- /dev/null +++ b/app/overlays/ptl/ctc_overlay.conf @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING=y diff --git a/app/overlays/ptl/dax_overlay.conf b/app/overlays/ptl/dax_overlay.conf new file mode 100644 index 000000000000..7dcdf749dbe1 --- /dev/null +++ b/app/overlays/ptl/dax_overlay.conf @@ -0,0 +1,13 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING=y +CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK=n +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +CONFIG_SOF_STACK_SIZE=8192 +CONFIG_IDC_TIMEOUT_US=50000 + +# LLEXT +CONFIG_LLEXT_HEAP_SIZE=32 + +# Log settings +CONFIG_LOG_BUFFER_SIZE=8192 +CONFIG_MTRACE_LOG_CACHE_BUF_SIZE=12288 diff --git a/app/overlays/ptl/dts_overlay.conf b/app/overlays/ptl/dts_overlay.conf new file mode 100644 index 000000000000..793559ad5de7 --- /dev/null +++ b/app/overlays/ptl/dts_overlay.conf @@ -0,0 +1,6 @@ +CONFIG_COMP_IIR=m +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_DTS_CODEC=y +CONFIG_LLEXT_HEAP_SIZE=64 +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +CONFIG_SOF_STACK_SIZE=8192 diff --git a/app/overlays/ptl/fpga_overlay.conf b/app/overlays/ptl/fpga_overlay.conf new file mode 100644 index 000000000000..f2f0eee4ab2d --- /dev/null +++ b/app/overlays/ptl/fpga_overlay.conf @@ -0,0 +1,10 @@ +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 + +# limit logs to minimize runtime overhead of logging +CONFIG_SOF_LOG_LEVEL_ERR=y + +# improves LPSRAM and HPSRAM access time +CONFIG_SRAM_RETENTION_MODE=n + +CONFIG_IDC_TIMEOUT_US=50000 diff --git a/app/overlays/ptl/userspace_overlay.conf b/app/overlays/ptl/userspace_overlay.conf new file mode 100644 index 000000000000..c484a2182807 --- /dev/null +++ b/app/overlays/ptl/userspace_overlay.conf @@ -0,0 +1,14 @@ +CONFIG_USERSPACE=y +CONFIG_XTENSA_MMU_NUM_L2_TABLES=86 +CONFIG_MAX_THREAD_BYTES=4 + +CONFIG_INIT_STACKS=n +CONFIG_THREAD_STACK_INFO=n +CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_POOL_SIZE=4 +CONFIG_DYNAMIC_THREAD_ALLOC=n +# IADK module adapter store some buffers on stack, so we need to increase stack size +CONFIG_DYNAMIC_THREAD_STACK_SIZE=8192 +CONFIG_SOF_STACK_SIZE=8192 +CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD=y diff --git a/app/overlays/wcl/fpga_overlay.conf b/app/overlays/wcl/fpga_overlay.conf new file mode 100644 index 000000000000..f2f0eee4ab2d --- /dev/null +++ b/app/overlays/wcl/fpga_overlay.conf @@ -0,0 +1,10 @@ +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 + +# limit logs to minimize runtime overhead of logging +CONFIG_SOF_LOG_LEVEL_ERR=y + +# improves LPSRAM and HPSRAM access time +CONFIG_SRAM_RETENTION_MODE=n + +CONFIG_IDC_TIMEOUT_US=50000 diff --git a/app/perf_overlay.conf b/app/perf_overlay.conf new file mode 100644 index 000000000000..4f08b61fc3c3 --- /dev/null +++ b/app/perf_overlay.conf @@ -0,0 +1,16 @@ +CONFIG_PERFORMANCE_COUNTERS=y +CONFIG_PERFORMANCE_COUNTERS_COMPONENT=y +# disable ll task level statistics to reduce logging overhead +#CONFIG_PERFORMANCE_COUNTERS_LL_TASKS=y +CONFIG_SYS_HEAP_RUNTIME_STATS=y +CONFIG_TIMING_FUNCTIONS=y +CONFIG_ADSP_IDLE_CLOCK_GATING=n +CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n +# disable top-level statistics to reduce logging overhead +CONFIG_SCHEDULE_LL_STATS_LOG=n + +# vendor/target dependent options +# +# uncomment to disable Intel HD-DMA L1 exit ISR. this affects +# the peak execution times at component level +#CONFIG_DMA_INTEL_ADSP_HDA_TIMING_L1_EXIT=n diff --git a/app/prj.conf b/app/prj.conf new file mode 100644 index 000000000000..5c22e19d6e0e --- /dev/null +++ b/app/prj.conf @@ -0,0 +1,51 @@ +CONFIG_BUILD_OUTPUT_BIN=n + +# The additional stripped .elf files are deterministic. +# This adds very few files in the build directory and has +# absolutely no other effect whatsoever. +# See on-going discussion in +# https://github.com/zephyrproject-rtos/zephyr/pull/51954 +# and usage in xtensa-build-zephyr.py +CONFIG_BUILD_OUTPUT_STRIPPED=y + +CONFIG_HAVE_AGENT=n + +# Since Zephyr commit f0daf904bb0202c PICOLIBC is the new default. +# We need more time to test and evaluate. +CONFIG_MINIMAL_LIBC=y + +CONFIG_ZEPHYR_LOG=y +CONFIG_TRACE=n +CONFIG_LOG=y +CONFIG_LOG_PRINTK=y +# Log processing is offloaded to a low-priority thread. +CONFIG_LOG_MODE_DEFERRED=y +# Wake the low-priority log thread every time new log +# messages are available +CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD=1 +# Frontend buffer must be large enough to cover all +# typical bursts of log messages. +CONFIG_LOG_BUFFER_SIZE=4096 +# Use stack that is sufficient for SOF backends +CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=4096 +# Use Linux kernel style timestamp format +CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y + +# Requires heap_info() be implemented, but no Zephyr wrapper +CONFIG_DEBUG_MEMORY_USAGE_SCAN=n + +# Ensure -O2 (or similar) is used for optimization +CONFIG_SPEED_OPTIMIZATIONS=y + +# Zephyr top-level default of -fno-strict-overflow is +# not a good fit for audio DSP code +CONFIG_COMPILER_OPT="-fstrict-overflow" + +CONFIG_SCHED_DEADLINE=y +CONFIG_SCHED_CPU_MASK=y + +# Fix the sys ticks value until following bugs are solved: +# - https://github.com/zephyrproject-rtos/zephyr/issues/46378 +CONFIG_SYS_CLOCK_TICKS_PER_SEC=15000 +CONFIG_DAI=y +CONFIG_HEAP_MEM_POOL_SIZE=2048 diff --git a/app/sample.yaml b/app/sample.yaml new file mode 100644 index 000000000000..e40ad5cc4902 --- /dev/null +++ b/app/sample.yaml @@ -0,0 +1,35 @@ +--- +sample: + description: Audio with SOF + name: sof +common: + tags: audio + modules: + - sof +tests: + sample.audio.sof: + tags: sof + build_only: true + platform_allow: + - intel_adsp/cavs25 + - intel_adsp/ace15_mtpm + - intel_adsp/ace20_lnl + - intel_adsp/ace30/ptl + - intel_adsp/ace30/ptl/sim + - intel_adsp/ace30/wcl + - intel_adsp/ace30/wcl/sim + - intel_adsp/ace40/nvl + - intel_adsp/ace40/nvls + - imx8qm_mek/mimx8qm6/adsp + - imx8qxp_mek/mimx8qx6/adsp + - imx8mp_evk/mimx8ml8/adsp + - imx8ulp_evk/mimx8ud7/adsp + + integration_platforms: + - intel_adsp/cavs25 # TGL + - intel_adsp/ace15_mtpm # MTL + - intel_adsp/ace20_lnl + - imx8qm_mek/mimx8qm6/adsp + - imx8qxp_mek/mimx8qx6/adsp + - imx8mp_evk/mimx8ml8/adsp + - imx8ulp_evk/mimx8ud7/adsp diff --git a/app/shell_overlay.conf b/app/shell_overlay.conf new file mode 100644 index 000000000000..963acd1d6e60 --- /dev/null +++ b/app/shell_overlay.conf @@ -0,0 +1,20 @@ +CONFIG_SHELL=y +CONFIG_SHELL_HELP=y +CONFIG_SHELL_CMDS=y +CONFIG_SHELL_LOG_BACKEND=n +CONFIG_SHELL_AUTOSTART=y + +CONFIG_SHELL_BACKEND_ADSP_MEMORY_WINDOW=y + +# mtrace uses the same window2.1 slot, so needs to be disabled +CONFIG_LOG_BACKEND_ADSP_MTRACE=n + +# as mtrace is disable, enable logging via winstream/window3 +CONFIG_LOG_BACKEND_ADSP=y +CONFIG_WINSTREAM_CONSOLE=y + +# The SOF telemetry performance measurements use +# the same window 3 as winstream ADSP log backend, so +# these must be disabled in order to use the console. +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n diff --git a/app/src/main.c b/app/src/main.c new file mode 100644 index 000000000000..12cc3ffdc73a --- /dev/null +++ b/app/src/main.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); + +/* define qemu boot tests if any qemu target is defined, add targets to end */ +#if defined(CONFIG_BOARD_QEMU_XTENSA_DC233C) ||\ + defined(CONFIG_BOARD_QEMU_XTENSA_DC233C_MMU) +#define QEMU_BOOT_TESTS +#endif + +/** + * Should be included from sof/schedule/task.h + * but triggers include chain issue + * FIXME + */ +int sof_main(int argc, char *argv[]); + +/** + * TODO: Here comes SOF initialization + */ + +static int sof_app_main(void) +{ + int ret; + + LOG_INF("SOF on %s", CONFIG_BOARD); + + /* sof_main is actually SOF initialization */ + ret = sof_main(0, NULL); + if (ret) { + LOG_ERR("SOF initialization failed"); + } + + LOG_INF("SOF initialized"); + +#ifdef CONFIG_ARCH_POSIX_LIBFUZZER + /* Workaround for an apparent timing bug in libfuzzer+asan. + * If the initial/main thread is allowed to return, ASAN will + * fairly reliably report a "stack overflow" where the ESP and + * EPC (instruction pointer!) registers are both set to the + * same value, which is non-sensical. See some discussion in + * https://github.com/zephyrproject-rtos/zephyr/pull/52769 + * + * But suspending the main thread instead of aborting is cheap + * and easy. + */ + k_thread_suspend(k_current_get()); +#endif + return 0; +} + +#if CONFIG_SOF_BOOT_TEST && defined(QEMU_BOOT_TESTS) +/* cleanly exit qemu so CI can continue and check test results */ +static inline void qemu_xtensa_exit(int status) +{ + register int syscall_id __asm__ ("a2") = 1; /* SYS_exit is 1 */ + register int exit_status __asm__ ("a3") = status; + + __asm__ __volatile__ ( + "simcall\n" + : + : "r" (syscall_id), "r" (exit_status) + : "memory" + ); +} +#endif + +#if CONFIG_ZTEST +void test_main(void) +{ + sof_app_main(); +#if CONFIG_SOF_BOOT_TEST && defined(QEMU_BOOT_TESTS) + sof_run_boot_tests(); + qemu_xtensa_exit(0); +#endif +} +#else +int main(void) +{ + return sof_app_main(); +} +#endif diff --git a/app/stub_build_all_ipc3.conf b/app/stub_build_all_ipc3.conf new file mode 100644 index 000000000000..8f98329a7419 --- /dev/null +++ b/app/stub_build_all_ipc3.conf @@ -0,0 +1,16 @@ +CONFIG_COMP_STUBS=y +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=y +CONFIG_COMP_TONE=n +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DRC=y +CONFIG_COMP_MULTIBAND_DRC=y +CONFIG_PASSTHROUGH_CODEC=y +CONFIG_WAVES_CODEC=y +CONFIG_DTS_CODEC=y +CONFIG_COMP_IGO_NR=y +CONFIG_COMP_RTNR=y +CONFIG_COMP_SMART_AMP=y +CONFIG_MAXIM_DSM=y +CONFIG_SAMPLES=y +CONFIG_SAMPLE_SMART_AMP=y +CONFIG_CADENCE_CODEC=y diff --git a/app/stub_build_all_ipc4.conf b/app/stub_build_all_ipc4.conf new file mode 100644 index 000000000000..6fdbd7209e47 --- /dev/null +++ b/app/stub_build_all_ipc4.conf @@ -0,0 +1,8 @@ +CONFIG_COMP_STUBS=y +CONFIG_COMP_ARIA=y +CONFIG_COMP_CHAIN_DMA=y +CONFIG_COMP_UP_DOWN_MIXER=y +CONFIG_IPC_MAJOR_4=y +CONFIG_SAMPLES=y +CONFIG_SAMPLE_SMART_AMP=y +CONFIG_CADENCE_CODEC=y diff --git a/app/winconsole_overlay.conf b/app/winconsole_overlay.conf new file mode 100644 index 000000000000..cc2ddf227fec --- /dev/null +++ b/app/winconsole_overlay.conf @@ -0,0 +1,19 @@ +# Overlay to enable logging via winstream backend. This is +# alternative memory window based logging backend that typically +# uses memory window 3 as transport. The backend is directly +# using Zephyr winstream protocol, and has no dependency to SOF +# IPC definitions. +# +# One client is available in Zephyr upstream at: +# zephyr/soc/intel/intel_adsp/tools/cavstool.py +# +# Note: winstream backend is not supported by Linux SOF driver +# +CONFIG_LOG_BACKEND_ADSP=y +CONFIG_WINSTREAM_CONSOLE=y + +# The SOF telemetry performance measurements use +# the same window 3 as winstream ADSP log backend, so +# these must be disabled in order to use the console. +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 8362f07291a3..8a85dd2e7ab1 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) project(SOF_DOC NONE) @@ -13,7 +13,7 @@ configure_file( "${PROJECT_BINARY_DIR}/sof.doxygen" ) -add_custom_target("doc" +add_custom_target("doc" ALL COMMAND doxygen sof.doxygen VERBATIM USES_TERMINAL diff --git a/doc/sof.doxygen.in b/doc/sof.doxygen.in index 85739893cee7..6379da500f11 100644 --- a/doc/sof.doxygen.in +++ b/doc/sof.doxygen.in @@ -9,11 +9,13 @@ CASE_SENSE_NAMES = NO INPUT = @top_srcdir@/src/include/ipc \ @top_srcdir@/src/include/kernel \ @top_srcdir@/src/include/user \ - @top_srcdir@/src/include/sof -EXCLUDE = + @top_srcdir@/src/include/sof \ + @top_srcdir@/xtos/include +# Exlude some 3rd party codec headers with external references +EXCLUDE = @top_srcdir@/src/include/sof/audio/MaxxEffect RECURSIVE = YES FILE_PATTERNS = *.c *.h -EXAMPLE_PATH = ../test +EXAMPLE_PATH = @top_srcdir@/test IMAGE_PATH = QUIET = YES @@ -26,7 +28,10 @@ INHERIT_DOCS = YES ENABLED_SECTIONS = "" MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES -PREDEFINED = __attribute__(x)= +PREDEFINED = "__attribute__(x)= " \ + "CONFIG_FORMAT_S16LE=1" \ + "CONFIG_FORMAT_S32LE=1" \ + "CONFIG_TRACE=1" OPTIMIZE_OUTPUT_FOR_C = YES TYPEDEF_HIDES_STRUCT = YES @@ -35,3 +40,4 @@ TYPEDEF_HIDES_STRUCT = YES #FILTER_SOURCE_FILES = YES HTML_TIMESTAMP = NO +WARN_AS_ERROR = NO diff --git a/installer/.gitignore b/installer/.gitignore new file mode 100644 index 000000000000..24404a12cf22 --- /dev/null +++ b/installer/.gitignore @@ -0,0 +1 @@ +/staging/sof* diff --git a/installer/GNUmakefile b/installer/GNUmakefile new file mode 100644 index 000000000000..39eb635e4ebd --- /dev/null +++ b/installer/GNUmakefile @@ -0,0 +1,348 @@ + +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2021 Intel Corporation + + +.DEFAULT_GOAL := stage +.PHONY: clean stage rsync tarball +.PHONY: signed unsigned ldicts topologies tools build_tools +.PHONY: compare signed_dummies + +# Override ?= variables in config.mk +-include config.mk + +# The default values of UNSIGNED_list and SIGNED_list used to be the +# list of /lib/firmware/sof/ images and symbolic links officially +# released by Intel at https://github.com/thesofproject/sof-bin +# +# All Intel firmware in this branch is now Zephyr-based. So this +# Makefile is NOT used anymore for sof-bin releases. However it is still +# useful as a single command, fully parallelized and much faster +# alternative to build: (1) all XTOS platforms currently supported by +# scripts/xtensa-build-zephyr.sh -a (2) all user space tools (3) all +# topologies. +# +# Using this script still builds a pseudo /lib/firmware/sof/ tree +# structure in the staging directory - ignore that. + +# Keep this line in sync with the DEFAULT_PLATFORMS in +# xtensa-build-zephyr.sh -a +UNSIGNED_list ?= imx8m rn rmb vangogh mt8186 mt8195 + + +# 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 + +# Not supported in the main branch anymore, go to stable-v2.3 +# UNSIGNED_list += bdw byt cht +# SIGNED_list += apl cnl icl jsl +# ALIAS_SAME_KEY_list += glk cfl cml +# ALIAS_OTHER_KEY_list += ehl + +# Much older platforms +# UNSIGNED_list += hsw sue +# SIGNED_list += kbl skl + +# Sample way to create a symbolic link in /lib/firmware/sof/ +# This requires adl-s to be listed in some ALIAS_some_list above. +# target_of_adl-s := tgl-h + +ALIAS_list := ${ALIAS_SAME_KEY_list} ${ALIAS_OTHER_KEY_list} + +$(info UNSIGNED_list = ${UNSIGNED_list} ) +$(info SIGNED_list = ${SIGNED_list} ) +$(info ALIAS_list = ${ALIAS_list} ) + +ifeq (,${TOOLCHAIN}) + ifeq (,${XTENSA_TOOLS_ROOT}) + TOOLCHAIN := gcc + else + TOOLCHAIN := xcc + endif +endif + +TREE_OPTS ?= --sort=size --dirsfirst +INSTALL_OPTS ?= -D -p -m 0664 + +# Keep SOF_VERSION optional + +SOF_VERSION ?= $(shell git describe --dirty) +ifneq (${SOF_VERSION},) +VERSION_DIR := ${SOF_VERSION}/ +VERSION_SUFFIX := -${SOF_VERSION} +endif + + + + ################################ + ### Top-level directories #### + ################################ + +# Our input: build_*_?cc/ directories +BUILDS_ROOT ?= ${CURDIR}/../installer-builds +BUILD_TOOLS ?= ${BUILDS_ROOT}/build_tools + +STAGING_SOF ?= staging/sof +STAGING_SOF_VERSION := ${STAGING_SOF}${VERSION_SUFFIX} + +STAGING_SOF_TPLG ?= staging/sof-tplg + +STAGING_TOOLS ?= staging/tools + +stage: signed unsigned ldicts aliases topologies tools + test -n "${UNSIGNED_list}${SIGNED_list}" # is there any FW to stage? +ifneq (${STAGING_SOF_VERSION},${STAGING_SOF}) + ln -sfT sof${VERSION_SUFFIX} ${STAGING_SOF} + test -e ${STAGING_SOF} +endif + @file ${STAGING_SOF} + @tree ${TREE_OPTS} ${STAGING_SOF_VERSION} + +COMMUNITY := ${STAGING_SOF_VERSION}/community +INTEL_SIGNED := ${STAGING_SOF_VERSION}/intel-signed +${COMMUNITY} ${INTEL_SIGNED} ${BUILDS_ROOT} ${STAGING_SOF_VERSION}: + mkdir -p $@ + +# The noise for incremental, do-nothing builds is incredible otherwise, +# especially for build_tools +GNUMAKEFLAGS = --no-print-directory + + ##################################### + ### rsync to local or remote #### + ##################################### + +# Default value +FW_DESTDIR ?= /lib/firmware/intel/ + +# The rsync target does not depend on any other target so: +# - it's possible to deploy a staging _subset_, e.g.: only topologies +# only,... +# - "sudo make rsync" never builds as root by accident +rsync: +# The --mkpath option is too recent, dealing with both remote and local +# would be complicated and this is also a safety against typos. + # The destination directory must already exist + rsync -a --info=progress2 staging/sof* "${FW_DESTDIR}" +ifneq (${USER_DESTDIR},) + # TODO: add more user space binaries: sof-ctl, probes,... + # absorbe scripts/sof-target-install.sh + cd ${BUILD_TOOLS} && rsync -a ${TOOLS_RELPATHS} ${USER_DESTDIR} +endif + +clean: + ${RM} -r ${STAGING_SOF}* ${STAGING_SOF_TPLG}* ${STAGING_TOOLS}* + ${RM} ${BUILDS_ROOT}/staging_sof_tree.txt + +cleanall: clean + ${RM} -r "${BUILD_TOOLS}/" "${BUILDS_ROOT}"/build_*_?cc/ + + + ##################################### + ### tarball #### + ##################################### + +tarball: stage + cd staging && tar cfz sof-build${VERSION_SUFFIX}.tgz \ + sof${VERSION_SUFFIX} sof-tplg${VERSION_SUFFIX} \ + tools${VERSION_SUFFIX} + + + ##################################### + ### Stage tools #### + ##################################### + +# This is only for the tarball, rsync takes the RELPATHS shortcut +tools: build_tools + mkdir -p ${STAGING_TOOLS}${VERSION_SUFFIX} + cd ${BUILD_TOOLS} && \ + cp -p ${TOOLS_RELPATHS} ${CURDIR}/${STAGING_TOOLS}${VERSION_SUFFIX} + + ########################################################## + ### Stage sof-*.ri firmware files and symbolic links #### + ########################################################## + +# +# 1. Stages all *.ri files +# +# 2. Create symbolic links, including (broken) intel-signed symbolic +# links that must be fixed in a final release, otherwise the release +# is incomplete. To check all symlinks: file $(find -type l) +# + +# '%' is the platform name +SIGNED_FWS := ${SIGNED_list:%=${COMMUNITY}/sof-%.ri} +# $(info SIGNED_FWS = ${SIGNED_FWS}) +signed: ${SIGNED_FWS} +${SIGNED_FWS}: ${COMMUNITY}/sof-%.ri: \ + ${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri \ + | ${COMMUNITY} ${INTEL_SIGNED} + install ${INSTALL_OPTS} $< $@ + ln -sfT intel-signed/sof-$*.ri ${STAGING_SOF_VERSION}/sof-$*.ri + +# '%' is the platform name +UNSIGNED_FWS := ${UNSIGNED_list:%=${STAGING_SOF_VERSION}/sof-%.ri} +# $(info UNSIGNED_FWS = ${UNSIGNED_FWS}) +unsigned: ${UNSIGNED_FWS} +${UNSIGNED_FWS}: ${STAGING_SOF_VERSION}/sof-%.ri: \ + ${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri + install ${INSTALL_OPTS} $< $@ + + +BUILD_SOF_RIS := \ + ${UNSIGNED_list:%=${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri} \ + ${SIGNED_list:%=${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri} + +# When the build is not deterministic use this to reduce noise when testing +# this Makefile. +# Also very useful with XCC, see next comment. +ifneq (true,${BUILD_ONLY_ONCE}) +.PHONY: ${BUILD_SOF_RIS} +endif + +# Incremental builds are not possible with XCC because the entire +# toolchain requires $XTENSA_SYSTEM but CMake does not support +# build-time environment variables. In the future we could move the +# XTENSA_SYSTEM values out of xtensa-build-all.sh and into some shared +# config file included here. +${BUILD_SOF_RIS}: ${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri: | ${BUILDS_ROOT} + cd ${BUILDS_ROOT} && bdir="$$(dirname $@)" && \ + if [ -e $${bdir}/build.ninja -o -e $${bdir}/Makefile ] && \ + [ xcc != "${TOOLCHAIN}" ] ; then \ + cmake --build $${bdir} -- bin; else \ + $(CURDIR)/../scripts/xtensa-build-all.sh -i "${IPC_VERSION}" $*; fi + + + ######################################## + ### Stage *.ldc logger dictionaries ### + ######################################## + +# '%' is the platform name +LDICTS := ${UNSIGNED_list:%=${STAGING_SOF_VERSION}/sof-%.ldc} \ + ${SIGNED_list:%=${STAGING_SOF_VERSION}/sof-%.ldc} +# $(info LDICTS = ${LDICTS}) +ldicts: ${LDICTS} +${LDICTS}: ${STAGING_SOF_VERSION}/sof-%.ldc: \ + ${BUILDS_ROOT}/build_%_${TOOLCHAIN}/sof.ri + if test -e ${BUILDS_ROOT}/build_$*_${TOOLCHAIN}/sof.ldc; then \ + install ${INSTALL_OPTS} ${BUILDS_ROOT}/build_$*_${TOOLCHAIN}/sof.ldc $@ ; \ + else printf '# CONFIG_TRACE was disabled\n' > $@; fi + + + ####################################### + ### Platform -> platform aliases #### + ####################################### + +# '%' is the platform name +COMM_ALIASES := ${ALIAS_list:%=${STAGING_SOF_VERSION}/community/sof-%.ri} +DICT_ALIASES := ${ALIAS_list:%=${STAGING_SOF_VERSION}/sof-%.ldc} + +${COMM_ALIASES}: ${STAGING_SOF_VERSION}/community/sof-%.ri: | ${COMMUNITY} + ln -sfT sof-${target_of_$*}.ri $@ + +${DICT_ALIASES}: ${STAGING_SOF_VERSION}/sof-%.ldc: | ${STAGING_SOF_VERSION} + ln -sfT sof-${target_of_$*}.ldc $@ + +# ->intel-signed/ symlinks for platform aliases. The other, identical +# looking ->intel-signed/ symlinks for the other, "normal" platforms are +# created here but by the signed: target. +# +# Some have the same key, others just the code. We don't make any +# difference, no platform re-direction here, this is merely pointing at +# ->intel-signed/same.ri +SIGNED_ALIASES := ${ALIAS_list:%=${STAGING_SOF_VERSION}/sof-%.ri} +${SIGNED_ALIASES}: ${STAGING_SOF_VERSION}/sof-%.ri: | ${STAGING_SOF_VERSION} + ln -sfT intel-signed/sof-$*.ri $@ + +# Platform indirection inside the intel-signed/ directory +SIGNED_PLATFORM_ALIASES := ${ALIAS_SAME_KEY_list:%=${INTEL_SIGNED}/sof-%.ri} +${SIGNED_PLATFORM_ALIASES}: ${INTEL_SIGNED}/sof-%.ri: | ${INTEL_SIGNED} + ln -sfT sof-${target_of_$*}.ri $@ + + +aliases: ${COMM_ALIASES} ${DICT_ALIASES} ${SIGNED_ALIASES} \ + ${SIGNED_PLATFORM_ALIASES} + + ################################## + ### Stage sof-tplg/ topologies ### + ################################## + +# The build is not deterministic; use this to reduce noise when testing +# this Makefile +ifneq (true,${BUILD_ONLY_ONCE}) +.PHONY: ${BUILD_TOOLS} +endif + +# Deploy and release only "official", top-level topology files starting +# with the 'sof-' prefix to avoid any experimental stuff. +topologies: ${BUILD_TOOLS} + install ${INSTALL_OPTS} -t ${STAGING_SOF_TPLG}${VERSION_SUFFIX}/ \ + ${BUILD_TOOLS}/topology/sof-*.tplg +ifneq (,${VERSION_SUFFIX}) + ln -sfT sof-tplg${VERSION_SUFFIX} ${STAGING_SOF_TPLG} + test -e ${STAGING_SOF_TPLG} +endif + @file ${STAGING_SOF_TPLG} + @tree ${TREE_OPTS} ${STAGING_SOF_TPLG}${VERSION_SUFFIX} | \ + head -n 10; printf '├── ...\n..\n' + + + ###################### + ### build-tools.sh ### + ###################### + +TOOLS_RELPATHS := ctl/sof-ctl logger/sof-logger probes/sof-probes +TOOLS_TARGETS := sof-ctl sof-logger sof-probes +TOOLS_FLAGS := -c -l -p + +.PHONY: build_tools +build_tools: ${BUILD_TOOLS} + +# We could use more targets rather than "set -e" with a multi-lines "for" loop. +# That would be more flexible but also quite verbose. +${BUILD_TOOLS}: + set -e; if test -e ${BUILD_TOOLS}/build.ninja || \ + test -e ${BUILD_TOOLS}/Makefile; then \ + for i in topologies ${TOOLS_TARGETS}; do \ + cmake --build ${BUILD_TOOLS} -- $$i; done; else \ + BUILD_TOOLS_DIR=${BUILD_TOOLS} ../scripts/build-tools.sh -T ${TOOLS_FLAGS} ; \ + fi + + + #################### + ### Self-Testing ### + #################### + +COMPARE_REFS ?= /lib/firmware/intel + +checktree: + cd ${STAGING_SOF_VERSION} && \ + tree -a -v --dirsfirst . > ${BUILDS_ROOT}/staging_sof_tree.txt + diff -u tests/staging_sof${IPC_VERSION}_ref.txt ${BUILDS_ROOT}/staging_sof_tree.txt + # Check two random topologies are there + test -f ${STAGING_SOF_TPLG}/sof-imx8-wm8960.tplg + for t in sof-ctl sof-logger sof-probes; do \ + test -f ${STAGING_TOOLS}${VERSION_SUFFIX}/$${t}; done + +# Useful for testing this Makefile. COMPARE_REFS can be /lib/firmware, +# sof-bin, a previous version of this Makefile,... +# As the first arguments maybe symbolic links, their trailing slash is +# critical. +compare: stage + ! diff -qr --no-dereference ${COMPARE_REFS}/sof/ \ + ${STAGING_SOF_VERSION}/ \ + | grep -v ' differ$$' # || true + ! diff -qr --no-dereference ${COMPARE_REFS}/sof-tplg/ \ + ${STAGING_SOF_TPLG}${VERSION_SUFFIX}/ \ + | grep -v ' differ$$' + +# Invoke this manually to check symbolic links are correct +SIGNED_DUMMIES := ${SIGNED_list:%=${INTEL_SIGNED}/sof-%.ri} \ + ${ALIAS_OTHER_KEY_list:%=${INTEL_SIGNED}/sof-%.ri} +signed_dummies: ${SIGNED_DUMMIES} + ! file $$(find staging -type l) | grep -i broken + +${SIGNED_DUMMIES}: | ${INTEL_SIGNED} + touch $@ diff --git a/installer/README.md b/installer/README.md new file mode 100644 index 000000000000..5819a4a80d89 --- /dev/null +++ b/installer/README.md @@ -0,0 +1,85 @@ +The GNUmakefile in this directory prepares ``/lib/firmware/intel/sof/`` and +``/lib/firmware/intel/sof-tplg/`` directories. + +It extracts what's needed from the output of the scripts +``./scripts/xtensa-build-all.sh`` and ``./scripts/build-tools.sh -T +-l``. It automatically runs these scripts when needed for the platforms +listed in config.mk and performs incremental builds when they have +already been run. + +It does not copy anything to ``/lib/firmware/`` directly but to local, +"staging" subdirectory first. The staging area can then be installed with +rsync to a local or remote ``/lib/firmware/intel/`` or to a release +location. This gives an opportunity to inspect the staging area and +avoids running everything as root. + +The default target (re-)generates the staging area: + + make -C installer/ + +Then, to install the staging area: + + sudo make -C installer/ rsync + +By default, the "rsync" target installs to the local +``/lib/firmware/intel/`` directory. To install to a different host or +different directory, copy the ``sample-config.mk`` file to ``config.mk`` +and follow the instructions inside the file. ``config.mk`` can also be +used to change the list of platforms installed and a number of other +Make variables. As usual with Make, many parameters can also be +overridden on the command line. + +To stage and install in one go: + + make -C installer/ stage rsync + +"stage" is the default target and it tries to stage everything: +firmware, dictionaries and topologies. As usual with Make, it's possible +to invoke individual targets. Find a list of targets at the top of +GNUMakefile. + +You can use `make -jN stage` to build multiple platforms faster but do +*not* `make -jN stage rsync` as this will start deploying before the +builds are all complete. That's because we want the rsync target to be +able to deploy subsets. Instead do: `make -jN somethings && make rsync`. + +Sample output: + + staging/sof: symbolic link to sof-v1.6.1 + staging/sof-v1.6.1/ + ├── community/ + │   ├── sof-tgl.ri + │   ├── sof-cnl.ri + │   ├── sof-icl.ri + │   ├── sof-jsl.ri + │   ├── sof-apl.ri + │   ├── sof-cfl.ri -> sof-cnl.ri + │   ├── sof-cml.ri -> sof-cnl.ri + │   ├── sof-ehl.ri -> sof-tgl.ri + │   └── sof-glk.ri -> sof-apl.ri + ├── intel-signed/ + ├── sof-bdw.ri + ├── sof-cht.ri + ├── sof-byt.ri + ├── sof-cnl.ldc + ├── sof-tgl.ldc + ├── sof-icl.ldc + ├── sof-jsl.ldc + ├── sof-apl.ldc + ├── sof-bdw.ldc + ├── sof-byt.ldc + ├── sof-cht.ldc + ├── sof-apl.ri -> intel-signed/sof-apl.ri + ├── sof-cfl.ri -> intel-signed/sof-cfl.ri + ├── sof-cml.ri -> intel-signed/sof-cml.ri + ├── sof-cnl.ri -> intel-signed/sof-cnl.ri + ├── sof-ehl.ri -> intel-signed/sof-ehl.ri + ├── sof-glk.ri -> intel-signed/sof-glk.ri + ├── sof-icl.ri -> intel-signed/sof-icl.ri + ├── sof-jsl.ri -> intel-signed/sof-jsl.ri + ├── sof-tgl.ri -> intel-signed/sof-tgl.ri + ├── sof-cfl.ldc -> sof-cnl.ldc + ├── sof-cml.ldc -> sof-cnl.ldc + ├── sof-ehl.ldc -> sof-tgl.ldc + └── sof-glk.ldc -> sof-apl.ldc + diff --git a/installer/sample-config.mk b/installer/sample-config.mk new file mode 100644 index 000000000000..870f83a0a1ce --- /dev/null +++ b/installer/sample-config.mk @@ -0,0 +1,37 @@ +# To customize the installation, copy this file to config.mk and edit +# it. Leave undefined to use default values. + +# As usual with Make, all these can also be passed as either CLI +# arguments or environment variables. Warning: undefined is NOT the +# same as blank! + +# You MUST "make cleanall" after changing anything here + +# Everything is installed by default. To install and deploy fewer +# patforms override the default lists like this: +# UNSIGNED_list := +# SIGNED_list := apl tgl + +# The default FW_DESTDIR is the local /lib/firmware/intel directory +# _remote := test-system.local +# FW_DESTDIR := root@${_remote}:/lib/firmware/intel +# USER_DESTDIR := ${_remote}:bin/ + +# Passed to ./scripts/xtensa-build-all.sh -i +# Ignored by incremental builds, MUST cleanall after changing this +# IPC_VERSION := IPC4 + +# Define this empty for a plain sof/ directory and no sof -> sof-v1.2.3 +# symbolic links. This is _only_ to override the top-level directory +# name; for sof_versions.h see version.cmake and try sof/.tarball-version +# SOF_VERSION := +# +# SOF_VERSION := $(shell git describe --tags ) +# SOF_VERSION := v1.6.14 + +# Uncomment this to have the build_*_?cc/ directories at the top-level +# BUILDS_ROOT := ${CURDIR}/.. + +# The build is not deterministic; use this to reduce noise when testing +# the installer/ itself +# BUILD_ONLY_ONCE := true diff --git a/installer/tests/staging_sofIPC4_ref.txt b/installer/tests/staging_sofIPC4_ref.txt new file mode 100644 index 000000000000..2cad7d207e4b --- /dev/null +++ b/installer/tests/staging_sofIPC4_ref.txt @@ -0,0 +1,23 @@ +. +├── 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 + +2 directories, 18 files diff --git a/installer/tests/staging_sof_ref.txt b/installer/tests/staging_sof_ref.txt new file mode 100644 index 000000000000..7a5f6a92d5e2 --- /dev/null +++ b/installer/tests/staging_sof_ref.txt @@ -0,0 +1,5 @@ +. +├── sof-imx8m.ldc +└── sof-imx8m.ri + +0 directories, 2 files diff --git a/rimage/keys/README b/keys/README similarity index 100% rename from rimage/keys/README rename to keys/README diff --git a/rimage/keys/otc_private_key.pem b/keys/otc_private_key.pem similarity index 100% rename from rimage/keys/otc_private_key.pem rename to keys/otc_private_key.pem diff --git a/rimage/keys/otc_private_key_3k.pem b/keys/otc_private_key_3k.pem similarity index 100% rename from rimage/keys/otc_private_key_3k.pem rename to keys/otc_private_key_3k.pem diff --git a/rimage/keys/otc_public_key.pem b/keys/otc_public_key.pem similarity index 100% rename from rimage/keys/otc_public_key.pem rename to keys/otc_public_key.pem diff --git a/rimage/keys/otc_public_key_3k.pem b/keys/otc_public_key_3k.pem similarity index 100% rename from rimage/keys/otc_public_key_3k.pem rename to keys/otc_public_key_3k.pem diff --git a/lmdk/README.md b/lmdk/README.md new file mode 100644 index 000000000000..f38bfd69e219 --- /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" -DSIGNING_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" -DSIGNING_KEY="path/to/key" diff --git a/lmdk/cmake/build.cmake b/lmdk/cmake/build.cmake new file mode 100644 index 000000000000..047a085257f8 --- /dev/null +++ b/lmdk/cmake/build.cmake @@ -0,0 +1,90 @@ +# 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) + +# Build common module functions from sof to a static library +add_library(sof STATIC) +target_include_directories(sof PRIVATE "${SOF_BASE}/src/include") +add_subdirectory("${SOF_BASE}/src/module" module_api) + +foreach(MODULE ${MODULES_LIST}) + add_executable(${MODULE}) + add_subdirectory(${LMDK_BASE}/modules/${MODULE} ${MODULE}_module) + + # uncomment line below to compile module with debug information + #target_compile_options(${MODULE} PUBLIC "-g3") + + target_include_directories(${MODULE} PRIVATE + "${LMDK_BASE}/include" + "${RIMAGE_INCLUDE_DIR}" + "${SOF_BASE}/src/include/module" + ) + + # 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 + ) + + # Link module with sof common module functions + target_link_libraries(${MODULE} sof) + + target_link_options(${MODULE} PRIVATE + "-nostartfiles" + "-Wl,--no-undefined" "-Wl,--unresolved-symbols=report-all" "-Wl,--error-unresolved-symbols" + "-Wl,--gc-sections" + "-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) + +foreach(MOD_NAME IN LISTS MODULES_LIST) + list(APPEND RIMAGE_MODULES_LIST ${MOD_NAME}.mod) + + # Change .module section flags to tell rimage to not include it in a final image + add_custom_target(${MOD_NAME}.mod + COMMENT "Preparing .mod(ule) files for rimage" + DEPENDS ${MOD_NAME} + COMMAND ${CMAKE_OBJCOPY} + --set-section-flags .module=noload,readonly + ${MOD_NAME} ${MOD_NAME}.mod +) +endforeach() + +find_program(RIMAGE_COMMAND NAMES rimage + PATHS "${RIMAGE_INSTALL_DIR}" + HINTS "${RIMAGE_SOF_INSTALL_DIR}" + REQUIRED) + +add_custom_target(${PROJECT_NAME}_target ALL + DEPENDS ${RIMAGE_MODULES_LIST} + COMMAND ${RIMAGE_COMMAND} -l -k ${SIGNING_KEY} -f 2.0.0 -b 1 -o ${RIMAGE_OUTPUT_FILE} -c ${TOML} -e ${RIMAGE_MODULES_LIST} + COMMAND ${CMAKE_COMMAND} -E cat ${RIMAGE_OUTPUT_FILE}.xman ${RIMAGE_OUTPUT_FILE} > ${OUTPUT_FILE} +) diff --git a/lmdk/cmake/config.cmake b/lmdk/cmake/config.cmake new file mode 100644 index 000000000000..17e2294613bd --- /dev/null +++ b/lmdk/cmake/config.cmake @@ -0,0 +1,42 @@ + +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}/tools/rimage/src/include) +cmake_path(ABSOLUTE_PATH RIMAGE_INCLUDE_DIR NORMALIZE) + +# Adds sources to target like target_sources, but assumes that +# paths are relative to subdirectory. +# Works like: +# Cmake >= 3.13: +# target_sources( PRIVATE ) +# Cmake < 3.13: +# target_sources( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/) +function(add_local_sources target) + foreach(arg ${ARGN}) + if(IS_ABSOLUTE ${arg}) + set(path ${arg}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg}) + endif() + + target_sources(${target} PRIVATE ${path}) + endforeach() +endfunction() + +# Currently loadable modules do not support the Zephyr build system +macro(is_zephyr ret) + set(${ret} FALSE) +endmacro() 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..4d76356f8630 --- /dev/null +++ b/lmdk/cmake/ldscripts/bss_linker_script.txt @@ -0,0 +1,33 @@ + +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.*) + + /* Heap memory */ + . = ALIGN(4); + __stack = .; + _end = .; + KEEP(*(.heap_mem)) + + /* Use the unused rest of the memory page as a heap */ + . = ALIGN(4096); + + /* The sbrk function implementation by xtensa incorrectly checks whether the allocated + memory block fits in the heap, so we have to add 1 to the end of the heap marker. */ + _heap_sentry = . + 1; + } >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..343107e7d37d --- /dev/null +++ b/lmdk/cmake/ldscripts/common_rodata_linker_script.txt @@ -0,0 +1,35 @@ +/* The .rodata PHDR is already defined in data_linker_script.txt */ + +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..ecdd39d738c4 --- /dev/null +++ b/lmdk/cmake/ldscripts/common_text_linker_script.txt @@ -0,0 +1,21 @@ +/* The .text PHDR is already defined in text_linker_script.txt */ + +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..9327079f4d7b --- /dev/null +++ b/lmdk/cmake/ldscripts/data_linker_script.txt @@ -0,0 +1,31 @@ + +PHDRS { + data_phdr PT_LOAD; + rodata_phdr PT_LOAD; +} + +EXTERN(HPSRAM) + +SECTIONS { + .data : ALIGN(4096) { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.*.data) + _data_end = ABSOLUTE(.); + } >HPSRAM_seg : data_phdr + + .rodata : { + _rodata_start = ABSOLUTE(.); + *(.gnu.linkonce.r.*) + *(.rodata) + *(.rodata.*) + KEEP (*(.eh_frame)) + _rodata_end = ABSOLUTE(.); + } >HPSRAM_seg : rodata_phdr + + /* Module manifest is here */ + .module : { + 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..d1d3e1fa0d5e --- /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(.); + KEEP(*(.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..50601a612a43 --- /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}clang + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +# clang++ or xc++ +find_program(CMAKE_CXX_COMPILER NAMES ${CROSS_COMPILE}clang++ + 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..fdb963483976 --- /dev/null +++ b/lmdk/libraries/dummy/CMakeLists.txt @@ -0,0 +1,13 @@ + +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") + +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..58b3820331fa --- /dev/null +++ b/lmdk/libraries/dummy/dummy_mtl.toml @@ -0,0 +1,85 @@ +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" +[[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 = "01234567-89AB-CDEF-0102-030405060708" + 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..de126062bad0 --- /dev/null +++ b/lmdk/modules/dummy/dummy.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2023 Intel Corporation. All rights reserved. + */ + +#include +#include + +DECLARE_LOADABLE_MODULE_API_VERSION(dummy); + +void *dummyPackageEntryPoint(void *mod_cfg, void *parent_ppl, void **mod_ptr) +{ + /* 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 = { 0x01234567, 0x89AB, 0xCDEF, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08 }}, + .entry_point = (uint32_t)dummyPackageEntryPoint, + .type = { + .load_type = SOF_MAN_MOD_TYPE_MODULE, + .domain_ll = 1 + }, + .affinity_mask = 3, + } +}; diff --git a/posix/include/CMakeLists.txt b/posix/include/CMakeLists.txt new file mode 100644 index 000000000000..fd819740233b --- /dev/null +++ b/posix/include/CMakeLists.txt @@ -0,0 +1 @@ +target_include_directories(sof_public_headers INTERFACE include) diff --git a/posix/include/rtos/alloc.h b/posix/include/rtos/alloc.h new file mode 100644 index 000000000000..84751ef9f1f4 --- /dev/null +++ b/posix/include/rtos/alloc.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/** + * \file xtos/include/rtos/alloc.h + * \brief Memory Allocation API definition + * \author Liam Girdwood + * \author Keyon Jie + */ + +#ifndef __SOF_LIB_ALLOC_H__ +#define __SOF_LIB_ALLOC_H__ + +#include +#include +#include +#include + +#include +#include + +/** \addtogroup alloc_api Memory Allocation API + * @{ + */ + +/** \name Heap zone flags + * @{ + */ + +/* + * for compatibility with the initial `flags` meaning + * SOF_MEM_FLAG_ should start at BIT(2) + * the first two positions are reserved for SOF_BUF_ flags + */ + + /** \brief Allocate DMA-able memory. */ +#define SOF_MEM_FLAG_DMA BIT(2) +/** \brief realloc() skips copying the original content. */ +#define SOF_MEM_FLAG_NO_COPY BIT(3) +/** \brief Allocate uncached address. */ +#define SOF_MEM_FLAG_COHERENT BIT(4) +/** \brief Allocate L3 address. */ +#define SOF_MEM_FLAG_L3 BIT(5) +/** \brief Allocate Low power memory address. */ +#define SOF_MEM_FLAG_LOW_POWER BIT(6) +/** \brief Allocate kernel memory address. */ +#define SOF_MEM_FLAG_KERNEL BIT(7) +/** \brief Allocate user memory address. */ +#define SOF_MEM_FLAG_USER BIT(8) +/** \brief Allocate shared user memory address. */ +#define SOF_MEM_FLAG_USER_SHARED_BUFFER BIT(9) +/** \brief Use allocation method for large buffers. */ +#define SOF_MEM_FLAG_LARGE_BUFFER BIT(10) + +/** @} */ + +/** + * Allocates memory block. + * @param flags Flags, see SOF_MEM_FLAG_... + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + */ +void *rmalloc_align(uint32_t flags, size_t bytes, + uint32_t alignment); + +/** + * Similar to rmalloc_align(), but no alignment can be specified. + */ +void *rmalloc(uint32_t flags, size_t bytes); + +/** + * Similar to rmalloc(), guarantees that returned block is zeroed. + */ +void *rzalloc(uint32_t flags, size_t bytes); + +/** + * Allocates memory block. + * @param flags Flags, see SOF_MEM_FLAG_... + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + */ +void *rballoc_align(uint32_t flags, size_t bytes, + uint32_t alignment); + +/** + * Similar to rballoc_align(), returns buffer aligned to PLATFORM_DCACHE_ALIGN. + */ +static inline void *rballoc(uint32_t flags, size_t bytes) +{ + return rballoc_align(flags, bytes, PLATFORM_DCACHE_ALIGN); +} + +/** + * Frees the memory block. + * @param ptr Pointer to the memory block. + */ +void rfree(void *ptr); + +/** + * Allocates memory block from the system heap reserved for the specified core. + * @param core Core id. + * @param bytes Size in bytes. + */ +void *rzalloc_core_sys(int core, size_t bytes); + +struct k_heap; +static inline void k_heap_init(struct k_heap *heap, void *mem, size_t bytes) +{ +} +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment); +void sof_heap_free(struct k_heap *heap, void *addr); +struct k_heap *sof_sys_heap_get(void); +struct k_heap *sof_sys_user_heap_get(void); + +/** + * Calculates length of the null-terminated string. + * @param s String. + * @return Length of the string in bytes. + */ +int rstrlen(const char *s); + +/** + * Compares two strings, see man strcmp. + * @param s1 First string to compare. + * @param s2 Second string to compare. + * @return See man strcmp. + */ +int rstrcmp(const char *s1, const char *s2); + +static inline void l3_heap_save(void) {} + +/** @}*/ + +#endif /* __SOF_LIB_ALLOC_H__ */ diff --git a/src/include/sof/atomic.h b/posix/include/rtos/atomic.h similarity index 100% rename from src/include/sof/atomic.h rename to posix/include/rtos/atomic.h diff --git a/posix/include/rtos/bit.h b/posix/include/rtos/bit.h new file mode 100644 index 000000000000..3dde908c2d6b --- /dev/null +++ b/posix/include/rtos/bit.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __XTOS_RTOS_BIT_H__ +#define __XTOS_RTOS_BIT_H__ + +#if ASSEMBLY +#define BIT(b) (1 << (b)) +#else +#define BIT(b) (1UL << (b)) +#endif + +#define MASK(b_hi, b_lo) \ + (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) +#define SET_BIT(b, x) (((x) & 1) << (b)) +#define SET_BITS(b_hi, b_lo, x) \ + (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) +#define GET_BIT(b, x) \ + (((x) & (1ULL << (b))) >> (b)) +#define GET_BITS(b_hi, b_lo, x) \ + (((x) & MASK(b_hi, b_lo)) >> (b_lo)) + +#endif /* __XTOS_RTOS_BIT_H__ */ diff --git a/posix/include/rtos/cache.h b/posix/include/rtos/cache.h new file mode 100644 index 000000000000..914e61b52984 --- /dev/null +++ b/posix/include/rtos/cache.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file xtos/include/rtos/cache.h + * \brief Cache header file + * \authors Tomasz Lauda + */ + +#ifndef __SOF_LIB_CACHE_H__ +#define __SOF_LIB_CACHE_H__ + +#include + +/* writeback and invalidate data */ +#define CACHE_WRITEBACK_INV 0 + +/* invalidate data */ +#define CACHE_INVALIDATE 1 + +#endif /* __SOF_LIB_CACHE_H__ */ diff --git a/posix/include/rtos/clk.h b/posix/include/rtos/clk.h new file mode 100644 index 000000000000..e9a36796bc42 --- /dev/null +++ b/posix/include/rtos/clk.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Janusz Jankowski + */ + +#ifndef __SOF_LIB_CLK_H__ +#define __SOF_LIB_CLK_H__ + +#include +#include +#include +#include +#include + +struct timer; + +#define CLOCK_NOTIFY_PRE 0 +#define CLOCK_NOTIFY_POST 1 + +struct clock_notify_data { + uint32_t old_freq; + uint32_t old_ticks_per_msec; + uint32_t freq; + uint32_t ticks_per_msec; + uint32_t message; +}; + +struct freq_table { + uint32_t freq; + uint32_t ticks_per_msec; +}; + +struct clock_info { + uint32_t freqs_num; + const struct freq_table *freqs; + uint32_t default_freq_idx; + uint32_t current_freq_idx; + uint32_t lowest_freq_idx; /* lowest possible clock */ + uint32_t notification_id; + uint32_t notification_mask; + + /* persistent change clock value in active state, caller must hold clk_lock */ + int (*set_freq)(int clock, int freq_idx); + + /* temporary change clock - don't modify default clock settings */ + void (*low_power_mode)(int clock, bool enable); +}; + +uint32_t clock_get_freq(int clock); + +void clock_set_freq(int clock, uint32_t hz); + +void clock_low_power_mode(int clock, bool enable); + +uint64_t clock_ms_to_ticks(int clock, uint64_t ms); + +uint64_t clock_us_to_ticks(int clock, uint64_t us); + +uint64_t clock_ns_to_ticks(int clock, uint64_t ns); + +uint64_t clock_ticks_per_sample(int clock, uint32_t sample_rate); + +extern struct k_spinlock clk_lock; + +static inline k_spinlock_key_t clock_lock(void) +{ + return k_spin_lock(&clk_lock); +} + +static inline void clock_unlock(k_spinlock_key_t key) +{ + k_spin_unlock(&clk_lock, key); +} + +static inline struct clock_info *clocks_get(void) +{ + return sof_get()->clocks; +} + +#endif /* __SOF_LIB_CLK_H__ */ diff --git a/posix/include/rtos/idc.h b/posix/include/rtos/idc.h new file mode 100644 index 000000000000..a9a03258712f --- /dev/null +++ b/posix/include/rtos/idc.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file include/rtos/idc.h + * \brief IDC header file + * \authors Tomasz Lauda + */ + +#ifndef __POSIX_RTOS_IDC_H__ +#define __POSIX_RTOS_IDC_H__ + +#include +#include +#include +#include +#include +#include +#include + +/** \brief IDC send blocking flag. */ +#define IDC_BLOCKING 0 + +/** \brief IDC send non-blocking flag. */ +#define IDC_NON_BLOCKING 1 + +/** \brief IDC send core power up flag. */ +#define IDC_POWER_UP 2 + +/** \brief IDC send core power down flag. */ +#define IDC_POWER_DOWN 3 + +/** \brief IDC task deadline. */ +#define IDC_DEADLINE 100 + +/** \brief ROM wake version parsed by ROM during core wake up. */ +#define IDC_ROM_WAKE_VERSION 0x2 + +/** \brief IDC message type. */ +#define IDC_TYPE_SHIFT 24 +#define IDC_TYPE_MASK 0x7f +#define IDC_TYPE(x) (((x) & IDC_TYPE_MASK) << IDC_TYPE_SHIFT) + +#define IDC_MSG_BIND IDC_TYPE(0xD) +#define IDC_MSG_UNBIND IDC_TYPE(0xE) +#define IDC_MSG_GET_ATTRIBUTE IDC_TYPE(0xF) + +/** \brief IDC component delete message. */ +#define IDC_MSG_FREE IDC_TYPE(0x10) +#define IDC_MSG_FREE_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC pipeline set state message. */ +#define IDC_MSG_PPL_STATE IDC_TYPE(0xC) +#define IDC_PPL_STATE_PPL_ID_SHIFT 0 +#define IDC_PPL_STATE_PPL_ID_MASK MASK(23, 0) +#define IDC_PPL_STATE_PHASE_SHIFT 24 +#define IDC_PPL_STATE_PHASE_MASK MASK(27, 24) +#define IDC_PPL_STATE_PHASE_SET(x) (((x) << IDC_PPL_STATE_PHASE_SHIFT) & \ + IDC_PPL_STATE_PHASE_MASK) +#define IDC_PPL_STATE_PHASE_GET(x) (((x) & IDC_PPL_STATE_PHASE_MASK) >> \ + IDC_PPL_STATE_PHASE_SHIFT) +#define IDC_PPL_STATE_PHASE_PREPARE BIT(0) +#define IDC_PPL_STATE_PHASE_TRIGGER BIT(1) +#define IDC_PPL_STATE_PHASE_ONESHOT (IDC_PPL_STATE_PHASE_PREPARE | \ + IDC_PPL_STATE_PHASE_TRIGGER) + +#define IDC_MSG_PPL_STATE_EXT(_ppl_id, _action) \ + IDC_EXTENSION(((_ppl_id) & IDC_PPL_STATE_PPL_ID_MASK) | \ + IDC_PPL_STATE_PHASE_SET(_action)) + +/** \brief IDC message header. */ +#define IDC_HEADER_MASK 0xffffff +#define IDC_HEADER(x) ((x) & IDC_HEADER_MASK) + +/** \brief IDC message extension. */ +#define IDC_EXTENSION_MASK 0x3fffffff +#define IDC_EXTENSION(x) ((x) & IDC_EXTENSION_MASK) + +/** \brief IDC power up message. */ +#define IDC_MSG_POWER_UP (IDC_TYPE(0x1) | \ + IDC_HEADER(IDC_ROM_WAKE_VERSION)) +#define IDC_MSG_POWER_UP_EXT IDC_EXTENSION(SOF_TEXT_START >> 2) + +/** \brief IDC power down message. */ +#define IDC_MSG_POWER_DOWN IDC_TYPE(0x2) +#define IDC_MSG_POWER_DOWN_EXT IDC_EXTENSION(0x0) + +/** \brief IDC notify message. */ +#define IDC_MSG_NOTIFY IDC_TYPE(0x3) +#define IDC_MSG_NOTIFY_EXT IDC_EXTENSION(0x0) + +/** \brief IDC IPC processing message. */ +#define IDC_MSG_IPC IDC_TYPE(0x4) +#define IDC_MSG_IPC_EXT IDC_EXTENSION(0x0) + +/** \brief IDC component params message. */ +#define IDC_MSG_PARAMS IDC_TYPE(0x5) +#define IDC_MSG_PARAMS_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component prepare message. */ +#define IDC_MSG_PREPARE IDC_TYPE(0x6) +#define IDC_MSG_PREPARE_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component trigger message. */ +#define IDC_MSG_TRIGGER IDC_TYPE(0x7) +#define IDC_MSG_TRIGGER_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component reset message. */ +#define IDC_MSG_RESET IDC_TYPE(0x8) +#define IDC_MSG_RESET_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC prepare D0ix message. */ +#define IDC_MSG_PREPARE_D0ix IDC_TYPE(0x9) +#define IDC_MSG_PREPARE_D0ix_EXT IDC_EXTENSION(0x0) + +/** \brief IDC secondary core crashed notify message. */ +#define IDC_MSG_SECONDARY_CORE_CRASHED IDC_TYPE(0xA) +#define IDC_MSG_SECONDARY_CORE_CRASHED_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC process async msg */ +#define IDC_MSG_AMS IDC_TYPE(0xB) +#define IDC_MSG_AMS_EXT IDC_EXTENSION(0x0) + +#define IDC_HEADER_TO_AMS_SLOT_MASK(x) (x & 0xFFFF) + +/** \brief IDC_MSG_SECONDARY_CORE_CRASHED header fields. */ +#define IDC_SCC_CORE_SHIFT 0 +#define IDC_SCC_CORE_MASK 0xff +#define IDC_SCC_CORE(x) (((x) & IDC_SCC_CORE_MASK) << IDC_SCC_CORE_SHIFT) + +#define IDC_SCC_REASON_SHIFT 8 +#define IDC_SCC_REASON_MASK 0xff +#define IDC_SCC_REASON(x) (((x) & IDC_SCC_REASON_MASK) << IDC_SCC_REASON_SHIFT) + +/** \brief Secondary core crash reasons. */ +#define IDC_SCC_REASON_WATCHDOG 0x00 +#define IDC_SCC_REASON_EXCEPTION 0x01 + +/** \brief Decodes IDC message type. */ +#define iTS(x) (((x) >> IDC_TYPE_SHIFT) & IDC_TYPE_MASK) + +/** \brief Max IDC message payload size in bytes. */ +#define IDC_MAX_PAYLOAD_SIZE (DCACHE_LINE_SIZE * 2) + +/** \brief IDC free function flags */ +#define IDC_FREE_IRQ_ONLY BIT(0) /**< disable only irqs */ + +/** \brief IDC message payload. */ +struct idc_payload { + uint8_t data[IDC_MAX_PAYLOAD_SIZE]; +}; + +/** \brief IDC message. */ +struct idc_msg { + uint32_t header; /**< header value */ + uint32_t extension; /**< extension value */ + uint32_t core; /**< core id */ + uint32_t size; /**< payload size in bytes */ + void *payload; /**< pointer to payload data */ +}; + +/** \brief IDC data. */ +struct idc { + uint32_t busy_bit_mask; /**< busy interrupt mask */ + struct idc_msg received_msg; /**< received message */ + struct task idc_task; /**< IDC processing task */ + struct idc_payload *payload; + int irq; +}; + +/* idc trace context, used by multiple units */ +extern struct tr_ctx idc_tr; + +static inline struct idc_payload *idc_payload_get(struct idc *idc, + uint32_t core) +{ + return idc->payload + core; +} + +void idc_enable_interrupts(int target_core, int source_core); + +void idc_free(uint32_t flags); + +int platform_idc_init(void); + +int platform_idc_restore(void); + +enum task_state idc_do_cmd(void *data); + +void idc_cmd(struct idc_msg *msg); + +int idc_msg_status_get(uint32_t core); + +void idc_init_thread(void); + +#endif /* __POSIX_RTOS_IDC_H__ */ diff --git a/posix/include/rtos/init.h b/posix/include/rtos/init.h new file mode 100644 index 000000000000..7744d6b5b1f3 --- /dev/null +++ b/posix/include/rtos/init.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __POSIX_RTOS_INIT_H__ +#define __POSIX_RTOS_INIT_H__ + +#define SOF_MODULE_INIT(name, init) + +#endif /* __POSIX_RTOS_INIT_H__ */ diff --git a/posix/include/rtos/interrupt.h b/posix/include/rtos/interrupt.h new file mode 100644 index 000000000000..58cefae94c81 --- /dev/null +++ b/posix/include/rtos/interrupt.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski + */ + +#ifndef __SOF_DRIVERS_INTERRUPT_H__ +#define __SOF_DRIVERS_INTERRUPT_H__ + +#include + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * \brief child IRQ descriptor for cascading IRQ controllers. + */ +struct irq_child { + int enable_count[CONFIG_CORE_COUNT]; /**< IRQ enable counter */ + struct list_item list; /**< head for IRQ descriptors, + * sharing this interrupt + */ +}; + +/** + * \brief interrupt client descriptor + */ +struct irq_desc { + int irq; /**< virtual IRQ number */ + void (*handler)(void *arg); /**< interrupt handler function */ + void *handler_arg; /**< interrupt handler argument */ + uint32_t cpu_mask; /**< a mask of CPUs on which this + * interrupt is enabled + */ + struct list_item irq_list; /**< to link to other irq_desc */ +}; + +/** + * \brief cascading IRQ controller operations. + */ +struct irq_cascade_ops { + void (*mask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< mask */ + void (*unmask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< unmask */ +}; + +/** + * \brief cascading interrupt controller descriptor. + */ +struct irq_cascade_desc { + const char *name; /**< name of the + * controller + */ + int irq_base; /**< first virtual IRQ + * number, assigned to + * this controller + */ + const struct irq_cascade_ops *ops; /**< cascading interrupt + * controller driver + * operations + */ + struct irq_desc desc; /**< the interrupt, that + * this controller is + * generating + */ + struct irq_cascade_desc *next; /**< link to the global + * list of interrupt + * controllers + */ + bool global_mask; /**< the controller + * cannot mask input + * interrupts per core + */ + struct k_spinlock lock; /**< protect child + * lists, enable and + * child counters + */ + int enable_count[CONFIG_CORE_COUNT]; /**< enabled child + * interrupt counter + */ + unsigned int num_children[CONFIG_CORE_COUNT]; /**< number of children + */ + struct irq_child child[PLATFORM_IRQ_CHILDREN]; /**< array of child + * lists - one per + * multiplexed IRQ + */ +}; + +/* A descriptor for cascading interrupt controller template */ +struct irq_cascade_tmpl { + const char *name; + const struct irq_cascade_ops *ops; + int irq; + void (*handler)(void *arg); + bool global_mask; +}; + +/** + * \brief Cascading interrupt controller root. + */ +struct cascade_root { + struct k_spinlock lock; /**< locking mechanism */ + struct irq_cascade_desc *list; /**< list of child cascade irqs */ + int last_irq; /**< last registered cascade irq */ +}; + +static inline struct cascade_root *cascade_root_get(void) +{ + return sof_get()->cascade_root; +} + +/* For i.MX, while building SOF with Zephyr use the interrupt_* + * functions from second level interrupt handling and IRQ_STEER. + */ +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +int mux_interrupt_get_irq(unsigned int irq, const char *cascade); +int mux_interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void mux_interrupt_unregister(uint32_t irq, const void *arg); +uint32_t mux_interrupt_enable(uint32_t irq, void *arg); +uint32_t mux_interrupt_disable(uint32_t irq, void *arg); +#endif + +int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void interrupt_unregister(uint32_t irq, const void *arg); +uint32_t interrupt_enable(uint32_t irq, void *arg); +uint32_t interrupt_disable(uint32_t irq, void *arg); + +/* Zephyr compat */ +#if !defined(__ZEPHYR__) +#define arch_irq_lock() arch_interrupt_disable_mask(0xffffffff) +#endif + +void platform_interrupt_init(void); + +void platform_interrupt_set(uint32_t irq); +void platform_interrupt_clear(uint32_t irq, uint32_t mask); +uint32_t platform_interrupt_get_enabled(void); +void interrupt_mask(uint32_t irq, unsigned int cpu); +void interrupt_unmask(uint32_t irq, unsigned int cpu); + +/* + * On platforms, supporting cascading interrupts cascaded interrupt numbers + * are greater than or equal to PLATFORM_IRQ_HW_NUM + */ +#define interrupt_is_dsp_direct(irq) (!PLATFORM_IRQ_CHILDREN || \ + irq < PLATFORM_IRQ_HW_NUM) + +void interrupt_init(struct sof *sof); +int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl); +struct irq_cascade_desc *interrupt_get_parent(uint32_t irq); +int interrupt_get_irq(unsigned int irq, const char *cascade); + +static inline void interrupt_set(int irq) +{ + platform_interrupt_set(irq); +} + +static inline void interrupt_clear_mask(int irq, uint32_t mask) +{ + platform_interrupt_clear(irq, mask); +} + +static inline void interrupt_clear(int irq) +{ + interrupt_clear_mask(irq, 1); +} + +static inline uint32_t interrupt_global_disable(void) +{ + return arch_interrupt_global_disable(); +} + +static inline void interrupt_global_enable(uint32_t flags) +{ + arch_interrupt_global_enable(flags); +} + +#if CONFIG_LIBRARY + +/* temporary fix to remove build warning for testbench that will need shortly + * realigned when Zephyr native APIs are used. + */ +static inline void __irq_local_disable(unsigned long flags) {} +static inline void __irq_local_enable(unsigned long flags) {} + +/* disables all IRQ sources on current core - NO effect on library */ +#define irq_local_disable(flags) \ + do { \ + flags = 0; \ + __irq_local_disable(flags); \ + } while (0) + +/* re-enables IRQ sources on current core - NO effect on library*/ +#define irq_local_enable(flags) \ + __irq_local_enable(flags) + +#else +/* disables all IRQ sources on current core */ +#define irq_local_disable(flags) \ + (flags = interrupt_global_disable()) + +/* re-enables IRQ sources on current core */ +#define irq_local_enable(flags) \ + interrupt_global_enable(flags) +#endif +#endif +#endif /* __SOF_DRIVERS_INTERRUPT_H__ */ diff --git a/posix/include/rtos/kernel.h b/posix/include/rtos/kernel.h new file mode 100644 index 000000000000..9fa3962a3589 --- /dev/null +++ b/posix/include/rtos/kernel.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jyri Sarha + */ + +#ifndef __POSIX_RTOS_KERNEL_H__ +#define __POSIX_RTOS_KERNEL_H__ + +#include + +#include +#include + +#ifdef __ZEPHYR__ +#error "This file should only be included in XTOS builds." +#endif + +typedef uint32_t k_ticks_t; + +typedef struct { + k_ticks_t ticks; +} k_timeout_t; + +#define Z_TIMEOUT_TICKS(t) ((k_timeout_t) { .ticks = (t) }) + +#define Z_TIMEOUT_US(t) ((k_timeout_t) { .ticks = clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, t) }) + +#define Z_TIMEOUT_MS(t) ((k_timeout_t) { .ticks = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, t) }) + +struct k_thread; +static inline bool thread_is_userspace(struct k_thread *thread) +{ + (void)thread; + return false; +} + +static inline void k_sleep(k_timeout_t timeout) +{ + wait_delay(timeout.ticks); +} + +static inline void k_msleep(int32_t ms) +{ + wait_delay_ms(ms); +} + +static inline void k_usleep(int32_t us) +{ + wait_delay_us(us); +} + +struct k_heap { + int unused; +}; + +#endif /* __POSIX_RTOS_KERNEL_H__ */ diff --git a/posix/include/rtos/mutex.h b/posix/include/rtos/mutex.h new file mode 100644 index 000000000000..19b360bdaea5 --- /dev/null +++ b/posix/include/rtos/mutex.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/* + * Simple mutex implementation for SOF. + */ + +#ifndef __POSIX_RTOS_MUTEX_H +#define __POSIX_RTOS_MUTEX_H + +#include +#include +#include + +#define K_FOREVER ((k_timeout_t) { .ticks = 0xffffffff }) + +struct k_mutex { + struct k_spinlock lock; + k_spinlock_key_t key; +}; + +static inline int k_mutex_init(struct k_mutex *mutex) +{ + k_spinlock_init(&mutex->lock); + return 0; +} + +static inline int k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout) +{ + mutex->key = k_spin_lock(&mutex->lock); + return 0; +} + +static inline int k_mutex_unlock(struct k_mutex *mutex) +{ + k_spin_unlock(&mutex->lock, mutex->key); + return 0; +} + +/* provide a no-op implementation for zephyr/sys/mutex.h */ + +struct sys_mutex { +}; + +#define SYS_MUTEX_DEFINE(name) \ + struct sys_mutex name + +static inline void sys_mutex_init(struct sys_mutex *mutex) +{ +} + +static inline int sys_mutex_lock(struct sys_mutex *mutex, k_timeout_t timeout) +{ + return 0; +} + +static inline int sys_mutex_unlock(struct sys_mutex *mutex) +{ + return 0; +} + +#endif diff --git a/posix/include/rtos/panic.h b/posix/include/rtos/panic.h new file mode 100644 index 000000000000..ca0578c51fa9 --- /dev/null +++ b/posix/include/rtos/panic.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_PANIC_H__ +#define __POSIX_RTOS_PANIC_H__ + +#include +#include +#include + +#ifdef __ZEPHYR__ +#error "This file should only be included in XTOS builds." +#endif /* __ZEPHYR__ */ + +#ifdef __clang_analyzer__ +#define SOF_NORETURN __attribute__((analyzer_noreturn)) +#elif __GNUC__ +#define SOF_NORETURN __attribute__((noreturn)) +#else +#define SOF_NORETURN +#endif + +#ifndef RELATIVE_FILE +#error "This file requires RELATIVE_FILE to be defined. "\ + "Add it to CMake's target with sof_append_relative_path_definitions." +#endif + +void dump_panicinfo(void *addr, struct sof_ipc_panic_info *panic_info); +void panic_dump(uint32_t p, struct sof_ipc_panic_info *panic_info, + uintptr_t *data) SOF_NORETURN; +void __panic(uint32_t p, const char *filename, uint32_t linenum) SOF_NORETURN; + +/** panic dump filename and linenumber of the call + * + * \param x panic code defined in ipc/trace.h + */ + +#define sof_panic(x) __panic((x), (RELATIVE_FILE), (__LINE__)) + +/* runtime assertion */ +#ifndef assert +#define assert(cond) (void)((cond) || (sof_panic(SOF_IPC_PANIC_ASSERT), 0)) +#endif + +#endif /* __POSIX_RTOS_PANIC_H__ */ diff --git a/posix/include/rtos/sof.h b/posix/include/rtos/sof.h new file mode 100644 index 000000000000..d6aa0fce66db --- /dev/null +++ b/posix/include/rtos/sof.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_SOF_H__ +#define __POSIX_RTOS_SOF_H__ + +#include +#include +#include + +struct cascade_root; +struct clock_info; +struct comp_driver_list; +struct dai_info; +struct dma_info; +struct dma_trace_data; +struct ipc; +struct ll_schedule_domain; +struct mm; +struct mn; +struct ams_shared_context; +struct notify_data; +struct pm_runtime_data; +struct sa; +struct timer; +struct trace; +struct pipeline_posn; +struct probe_pdata; + +/** + * \brief General firmware context. + * This structure holds all the global pointers, which can potentially + * be accessed by SMP code, hence it should be aligned to platform's + * data cache line size. Alignments in the both beginning and end are needed + * to avoid potential before and after data evictions. + */ +struct sof { + /* init data */ + int argc; + char **argv; + + /* ipc */ + struct ipc *ipc; + + /* system agent */ + struct sa *sa; + + /* DMA for Trace*/ + struct dma_trace_data *dmat; + + /* generic trace structure */ + struct trace *trace; + + /* platform clock information */ + struct clock_info *clocks; + + /* default platform timer */ + struct timer *platform_timer; + + /* cpu (arch) timers - 1 per core */ + struct timer *cpu_timers; + + /* timer domain for driving timer LL scheduler */ + struct ll_schedule_domain *platform_timer_domain; + + /* DMA domain for driving DMA LL scheduler */ + struct ll_schedule_domain *platform_dma_domain; + + /* memory map */ + struct mm *memory_map; + + /* runtime power management data */ + struct pm_runtime_data *prd; + +#ifdef CONFIG_AMS + /* asynchronous messaging service */ + struct ams_shared_context *ams_shared_ctx; +#endif + + /* shared notifier data */ + struct notify_data *notify_data; + + /* platform dai information */ + const struct dai_info *dai_info; + + /* platform DMA information */ + const struct dma_info *dma_info; + + /* cascading interrupt controller root */ + struct cascade_root *cascade_root; + + /* list of registered component drivers */ + struct comp_driver_list *comp_drivers; + + /* M/N dividers */ + struct mn *mn; + + /* probes */ + struct probe_pdata *probe; + + /* pipelines stream position */ + struct pipeline_posn *pipeline_posn; + +#ifdef CONFIG_LIBRARY_MANAGER + /* dynamically loaded libraries */ + struct ext_library *ext_library; +#endif + + __aligned(PLATFORM_DCACHE_ALIGN) int alignment[0]; +} __aligned(PLATFORM_DCACHE_ALIGN); + +struct sof *sof_get(void); + +#endif /* __POSIX_RTOS_SOF_H__ */ diff --git a/posix/include/rtos/spinlock.h b/posix/include/rtos/spinlock.h new file mode 100644 index 000000000000..22580246519f --- /dev/null +++ b/posix/include/rtos/spinlock.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/* + * Simple spinlock implementation for SOF. + */ + +#ifndef __POSIX_RTOS_SPINLOCK_H__ +#define __POSIX_RTOS_SPINLOCK_H__ + +#include + +struct k_spinlock { +}; + +typedef uint32_t k_spinlock_key_t; + +#define trace_lock(__e) do {} while (0) +#define tracev_lock(__e) do {} while (0) + +#define spin_lock_dbg(line) do {} while (0) +#define spin_unlock_dbg(line) do {} while (0) + +#define k_spinlock_init(lock) do {} while (0) + +static inline k_spinlock_key_t k_spin_lock(struct k_spinlock *l) +{ + return 0; +} + +static inline void k_spin_unlock(struct k_spinlock *l, + k_spinlock_key_t key) +{ + (void)l; + (void)key; +} + +#endif /* __POSIX_RTOS_SPINLOCK_H__ */ diff --git a/posix/include/rtos/string.h b/posix/include/rtos/string.h new file mode 100644 index 000000000000..b3ca03f9ca4e --- /dev/null +++ b/posix/include/rtos/string.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_STRING_H__ +#define __POSIX_RTOS_STRING_H__ + +#include +#include + +/* C memcpy for arch that don't have arch_memcpy() */ +void cmemcpy(void *dest, void *src, size_t size); +int memcmp(const void *p, const void *q, size_t count); +int rstrlen(const char *s); +int rstrcmp(const char *s1, const char *s2); + +#if defined(arch_memcpy) +#define rmemcpy(dest, src, size) \ + arch_memcpy(dest, src, size) +#else +#define rmemcpy(dest, src, size) \ + cmemcpy(dest, src, size) +#endif + +#endif /* __POSIX_RTOS_STRING_H__ */ diff --git a/posix/include/rtos/string_macro.h b/posix/include/rtos/string_macro.h new file mode 100644 index 000000000000..679edb7f1e32 --- /dev/null +++ b/posix/include/rtos/string_macro.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian + */ + +#ifndef __POSIX_RTOS_STRING_MACRO_H__ +#define __POSIX_RTOS_STRING_MACRO_H__ + +#define Z_STRINGIFY(x) #x +#define STRINGIFY(s) Z_STRINGIFY(s) + +#define _DO_CONCAT(x, y) x ## y +#define _CONCAT(x, y) _DO_CONCAT(x, y) + +#endif /* __POSIX_RTOS_STRING_MACRO_H__ */ diff --git a/posix/include/rtos/symbol.h b/posix/include/rtos/symbol.h new file mode 100644 index 000000000000..e234945cb789 --- /dev/null +++ b/posix/include/rtos/symbol.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __RTOS_SYMBOL_H__ +#define __RTOS_SYMBOL_H__ + +#define EXPORT_SYMBOL(x) + +#endif diff --git a/posix/include/rtos/task.h b/posix/include/rtos/task.h new file mode 100644 index 000000000000..5aca574a5787 --- /dev/null +++ b/posix/include/rtos/task.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __POSIX_RTOS_TASK_H__ +#define __POSIX_RTOS_TASK_H__ + +#include +#include +#include +#include +#include +#include +#include + +struct comp_dev; +struct sof; + +/** \brief Predefined LL task priorities. */ +#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */ +#define SOF_TASK_PRI_MED 4 /* priority level 4 - medium */ +#define SOF_TASK_PRI_LOW 9 /* priority level 9 - low */ + +/** \brief Predefined EDF task deadlines. */ +#define SOF_TASK_DEADLINE_IDLE UINT64_MAX +#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1) +#define SOF_TASK_DEADLINE_NOW 0 + +/** \brief Task counter initial value. */ +#define SOF_TASK_SKIP_COUNT 0xFFFFu + +/** \brief Task states. */ +enum task_state { + SOF_TASK_STATE_INIT = 0, + SOF_TASK_STATE_QUEUED, + SOF_TASK_STATE_PENDING, + SOF_TASK_STATE_RUNNING, + SOF_TASK_STATE_PREEMPTED, + SOF_TASK_STATE_COMPLETED, + SOF_TASK_STATE_FREE, + SOF_TASK_STATE_CANCEL, + SOF_TASK_STATE_RESCHEDULE, +}; + +/** \brief Task operations. */ +struct task_ops { + enum task_state (*run)(void *data); /**< task's main operation */ + void (*complete)(void *data); /**< executed on completion */ + uint64_t (*get_deadline)(void *data); /**< returns current deadline */ +}; + +/** \brief Task used by schedulers. */ +struct task { + uint64_t start; /**< start time in [ms] since now (LL only) */ + const struct sof_uuid_entry *uid; /**< Uuid */ + uint16_t type; /**< type of the task (LL or EDF) */ + uint16_t priority; /**< priority of the task (used by LL) */ + uint16_t core; /**< execution core */ + uint16_t flags; /**< custom flags */ + enum task_state state; /**< current state */ + void *data; /**< custom data passed to all ops */ + struct list_item list; /**< used by schedulers to hold tasks */ + void *priv_data; /**< task private data */ + struct task_ops ops; /**< task operations */ +#if defined(CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS) + uint32_t cycles_sum; + uint32_t cycles_max; + uint32_t cycles_cnt; +#endif +#if CONFIG_PERFORMANCE_COUNTERS + struct perf_cnt_data pcd; +#endif +}; + +static inline bool task_is_active(struct task *task) +{ + switch (task->state) { + case SOF_TASK_STATE_QUEUED: + case SOF_TASK_STATE_PENDING: + case SOF_TASK_STATE_RUNNING: + case SOF_TASK_STATE_PREEMPTED: + case SOF_TASK_STATE_RESCHEDULE: + return true; + default: + return false; + } +} + +static inline enum task_state task_run(struct task *task) +{ + assert(task->ops.run); + + return task->ops.run(task->data); +} + +static inline void task_complete(struct task *task) +{ + if (task->ops.complete) + task->ops.complete(task->data); +} + +static inline uint64_t task_get_deadline(struct task *task) +{ + assert(task->ops.get_deadline); + + return task->ops.get_deadline(task->data); +} + +enum task_state task_main_primary_core(void *data); + +enum task_state task_main_secondary_core(void *data); + +void task_main_init(void); + +void task_main_free(void); + +int task_main_start(struct sof *sof); +int start_complete(void); + +#endif /* __POSIX_RTOS_TASK_H__ */ diff --git a/posix/include/rtos/timer.h b/posix/include/rtos/timer.h new file mode 100644 index 000000000000..b9756b66c87c --- /dev/null +++ b/posix/include/rtos/timer.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski + */ + +#ifndef __SOF_DRIVERS_TIMER_H__ +#define __SOF_DRIVERS_TIMER_H__ + +#include +#include +#include +#include +#include +#include + +struct comp_dev; +struct sof_ipc_stream_posn; + +#define TIMER0 0 +#define TIMER1 1 +#define TIMER2 2 +#define TIMER3 3 +#define TIMER4 4 + +int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg); +void timer_unregister(struct timer *timer, void *arg); +void timer_enable(struct timer *timer, void *arg, int core); +void timer_disable(struct timer *timer, void *arg, int core); + +static inline struct timer *timer_get(void) +{ + return sof_get()->platform_timer; +} + +static inline struct timer *cpu_timer_get(void) +{ + return &(sof_get()->cpu_timers[cpu_get_id()]); +} + +static inline int64_t timer_set(struct timer *timer, uint64_t ticks) +{ + return arch_timer_set(timer, ticks); +} + +void timer_set_ms(struct timer *timer, unsigned int ms); + +static inline void timer_clear(struct timer *timer) +{ + arch_timer_clear(timer); +} + +unsigned int timer_get_count(struct timer *timer); + +unsigned int timer_get_count_delta(struct timer *timer); + +static inline uint64_t timer_get_system(struct timer *timer) +{ + return arch_timer_get_system(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks); +void platform_timer_clear(struct timer *timer); +uint64_t platform_timer_get(struct timer *timer); +uint64_t platform_timer_get_atomic(struct timer *timer); + +static inline uint64_t platform_safe_get_time(struct timer *timer) +{ + /* Default to something small but at least 1.0 microsecond so it + * does not look like an uninitialized zero; not even when the + * user does not request any microseconds decimals. See + * DEFAULT_CLOCK constant in logger.c + */ + return timer ? platform_timer_get(timer) : 50; +} + +void platform_timer_start(struct timer *timer); +void platform_timer_stop(struct timer *timer); + +static inline uint64_t k_ms_to_cyc_ceil64(uint64_t ms) +{ + return clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, ms); +} + +static inline uint64_t k_us_to_cyc_ceil64(uint64_t us) +{ + return clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, us); +} + +static inline uint64_t k_ns_to_cyc_near64(uint64_t ns) +{ + return clock_ns_to_ticks(PLATFORM_DEFAULT_CLOCK, ns); +} + +static inline uint64_t k_cyc_to_ms_near64(uint64_t ticks) +{ + return ticks / clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); +} + +static inline uint64_t k_cyc_to_us_near64(uint64_t ticks) +{ + return ticks / clock_us_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); +} + +static inline uint64_t sof_cycle_get_64(void) +{ + return platform_timer_get(timer_get()); +} + +static inline uint64_t sof_cycle_get_64_atomic(void) +{ + return platform_timer_get_atomic(timer_get()); +} + +static inline uint64_t sof_cycle_get_64_safe(void) +{ + return platform_safe_get_time(timer_get()); +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn); + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn); + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock); + +#endif /* __SOF_DRIVERS_TIMER_H__ */ diff --git a/posix/include/rtos/userspace_helper.h b/posix/include/rtos/userspace_helper.h new file mode 100644 index 000000000000..09a52b7804d5 --- /dev/null +++ b/posix/include/rtos/userspace_helper.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + * Adrian Warecki + */ + +/** + * \brief Userspace support functions. + */ +#ifndef __RTOS_USERSPACE_HELPER_H__ +#define __RTOS_USERSPACE_HELPER_H__ + +#include +#include + +#include + +#define APP_TASK_BSS +#define APP_TASK_DATA + +struct sys_heap; + +#ifdef CONFIG_USERSPACE +/** + * Initialize private processing module heap. + * @param N/A. + * @return pointer to the k_heap structure. + * + * @note + * Function used only when CONFIG_USERSPACE is set. + * The private heap is used only for non-privileged modules for all processing module allocations + * that should be isolated. The heap helps to accumulate all dynamic allocations in single memory + * region which is then added to modules memory domain. + */ +static inline struct k_heap *module_driver_heap_init(void) +{ + return NULL; +} +#endif + +/** + * Free private processing module heap. + * @param sys_heap pointer to the sys_heap structure. + * + * @note + * Function used only when CONFIG_USERSPACE is set. + * Frees private module heap. + */ +static inline void module_driver_heap_remove(struct k_heap *mod_drv_heap) +{ } + +#endif /* __RTOS_USERSPACE_HELPER_H__ */ diff --git a/posix/include/rtos/wait.h b/posix/include/rtos/wait.h new file mode 100644 index 000000000000..c6cd029ec6b6 --- /dev/null +++ b/posix/include/rtos/wait.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +/* + * Simple wait for event completion and signaling with timeouts. + */ + +#ifndef __POSIX_RTOS_WAIT_H__ +#define __POSIX_RTOS_WAIT_H__ + +#include +#include + +#if !CONFIG_LIBRARY +#include +#include +#include +#include +#include +#include + +extern struct tr_ctx wait_tr; + +static inline void wait_for_interrupt(int level) +{ + LOG_MODULE_DECLARE(wait, CONFIG_SOF_LOG_LEVEL); + + tr_dbg(&wait_tr, "WFE"); + platform_wait_for_interrupt(level); + tr_dbg(&wait_tr, "WFX"); +} + +/** + * \brief Waits at least passed number of clocks. + * \param[in] number_of_clks Minimum number of clocks to wait. + */ +void wait_delay(uint64_t number_of_clks); + +/** + * \brief Waits at least passed number of milliseconds. + * \param[in] ms Minimum number of milliseconds to wait. + */ +void wait_delay_ms(uint64_t ms); + +/** + * \brief Waits at least passed number of microseconds. + * \param[in] us Minimum number of microseconds to wait. + */ +void wait_delay_us(uint64_t us); +#else +static inline void wait_delay(uint64_t number_of_clks) {} +static inline void wait_delay_ms(uint64_t ms) {} +static inline void wait_delay_us(uint64_t us) {} +#endif + +int poll_for_register_delay(uint32_t reg, uint32_t mask, + uint32_t val, uint64_t us); + +#endif /* __POSIX_RTOS_WAIT_H__ */ diff --git a/posix/include/sof/compiler_attributes.h b/posix/include/sof/compiler_attributes.h new file mode 100644 index 000000000000..a223012d44ab --- /dev/null +++ b/posix/include/sof/compiler_attributes.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + */ + +#ifdef __ZEPHYR__ + +/* Get __sparse_cache and __sparse_force definitions if __CHECKER__ is defined */ +#include + +#else + +#define __sparse_cache +#define __sparse_force + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#ifndef __unused +#define __unused __attribute__((unused)) +#endif + +#ifndef __maybe_unused +#define __maybe_unused __attribute__((unused)) +#endif + +#endif + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif + +#ifndef __section +#define __section(x) __attribute__((section(x))) +#endif + +/* The fallthrough attribute is supported since GCC 7.0 + * and Clang 10.0.0. + * + * Note that Clang sets __GNUC__ == 4 so the GCC version + * test will not be true here, and must go through + * the Clang version test. + */ +#if ((defined(__GNUC__) && (__GNUC__ >= 7)) || \ + (defined(__clang__) && (__clang_major__ >= 10))) && !defined(__CHECKER__) + +#define COMPILER_FALLTHROUGH __attribute__((fallthrough)) + +#else + +#define COMPILER_FALLTHROUGH /* fallthrough */ + +#endif diff --git a/posix/include/sof/compiler_info.h b/posix/include/sof/compiler_info.h new file mode 100644 index 000000000000..9716575b7188 --- /dev/null +++ b/posix/include/sof/compiler_info.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski + */ + +/** + * \file xtos/include/sof/compiler_info.h + * \brief Compiler version and name descriptor + * \author Karol Trzcinski + */ + +#ifndef __SOF_COMPILER_INFO_H__ +#define __SOF_COMPILER_INFO_H__ + +#include + +#endif /* __SOF_COMPILER_INFO_H__ */ diff --git a/posix/include/sof/init.h b/posix/include/sof/init.h new file mode 100644 index 000000000000..ce8522cd34ad --- /dev/null +++ b/posix/include/sof/init.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __SOF_INIT_H__ +#define __SOF_INIT_H__ + +struct sof; + +/* main firmware entry point - argc and argv not currently used */ +#ifndef CONFIG_ARCH_POSIX +int main(int argc, char *argv[]); +#endif + +#if CONFIG_MULTICORE + +int secondary_core_init(struct sof *sof); + +#endif /* CONFIG_MULTICORE */ + +int arch_init(void); + +#endif /* __SOF_INIT_H__ */ diff --git a/posix/include/sof/lib/agent.h b/posix/include/sof/lib/agent.h new file mode 100644 index 000000000000..6e70a4ce997d --- /dev/null +++ b/posix/include/sof/lib/agent.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __SOF_LIB_AGENT_H__ +#define __SOF_LIB_AGENT_H__ + +#include +#include +#include +#include +#include + +#include +#include + +struct sof; + +/* simple agent */ +struct sa { + uint64_t last_check; /* time of last activity checking */ + uint64_t panic_timeout; /* threshold of panic */ + uint64_t warn_timeout; /* threshold of warning */ +#if CONFIG_PERFORMANCE_COUNTERS + struct perf_cnt_data pcd; +#endif + struct task work; + atomic_t panic_cnt; /**< ref counter for panic_on_delay property */ + bool panic_on_delay; /**< emits panic on delay if true */ +}; + +#if CONFIG_HAVE_AGENT + +/** + * Enables or disables panic on agent delay. + * @param enabled True for panic enabling, false otherwise. + */ +static inline void sa_set_panic_on_delay(bool enabled) +{ + struct sa *sa = sof_get()->sa; + + if (enabled) + atomic_add(&sa->panic_cnt, 1); + else + atomic_sub(&sa->panic_cnt, 1); + + /* enable panic only if no refs */ + sa->panic_on_delay = !atomic_read(&sa->panic_cnt); + +} + +void sa_init(struct sof *sof, uint64_t timeout); +void sa_exit(struct sof *sof); + +#else + +static inline void sa_init(struct sof *sof, uint64_t timeout) { } +static inline void sa_exit(struct sof *sof) { } +static inline void sa_set_panic_on_delay(bool enabled) { } + +#endif + +#endif /* __SOF_LIB_AGENT_H__ */ diff --git a/posix/include/sof/lib/cpu.h b/posix/include/sof/lib/cpu.h new file mode 100644 index 000000000000..d53e15e7535a --- /dev/null +++ b/posix/include/sof/lib/cpu.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file xtos/include/sof/lib/cpu.h + * \brief CPU header file + * \authors Tomasz Lauda + */ + +#ifndef __SOF_LIB_CPU_H__ +#define __SOF_LIB_CPU_H__ +#ifndef __ZEPHYR__ + +#include + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include +#include + +/* let the compiler optimise when in single core mode */ +#if CONFIG_CORE_COUNT == 1 + +static inline int cpu_get_id(void) +{ + return 0; +} + +static inline bool cpu_is_primary(int id) +{ + return 1; +} + +static inline bool cpu_is_me(int id) +{ + return 1; +} + +#else + +static inline int cpu_get_id(void) +{ + return arch_cpu_get_id(); +} + +static inline bool cpu_is_primary(int id) +{ + return id == PLATFORM_PRIMARY_CORE_ID; +} + +static inline bool cpu_is_me(int id) +{ + return id == cpu_get_id(); +} +#endif + +static inline int cpu_enable_core(int id) +{ + return arch_cpu_enable_core(id); +} + +static inline void cpu_disable_core(int id) +{ + arch_cpu_disable_core(id); +} + +static inline int cpu_is_core_enabled(int id) +{ + return arch_cpu_is_core_enabled(id); +} + +static inline int cpu_enabled_cores(void) +{ + return arch_cpu_enabled_cores(); +} + +static inline int cpu_restore_secondary_cores(void) +{ + return arch_cpu_restore_secondary_cores(); +} + +static inline int cpu_secondary_cores_prepare_d0ix(void) +{ + return arch_cpu_secondary_cores_prepare_d0ix(); +} + +#endif +#endif +#endif /* __SOF_LIB_CPU_H__ */ diff --git a/posix/include/sof/lib/dai.h b/posix/include/sof/lib/dai.h new file mode 100644 index 000000000000..47677c19ae4c --- /dev/null +++ b/posix/include/sof/lib/dai.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/** + * \file xtos/include/sof/lib/dai.h + * \brief DAI Drivers definition + * \author Liam Girdwood + * \author Keyon Jie + */ + +#ifndef __SOF_LIB_DAI_H__ +#define __SOF_LIB_DAI_H__ + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +#include +#else +#include +#endif + +struct ipc4_ipcgtw_cmd; + +static inline int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, + void *reply_payload, uint32_t *reply_payload_size) +{ + return 0; +} + +#endif /* __SOF_LIB_DAI_H__ */ diff --git a/posix/include/sof/lib/dma.h b/posix/include/sof/lib/dma.h new file mode 100644 index 000000000000..cb829dcaa21a --- /dev/null +++ b/posix/include/sof/lib/dma.h @@ -0,0 +1,602 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +/** + * \file xtos/include/sof/lib/dma.h + * \brief DMA Drivers definition + * \author Liam Girdwood + * \author Keyon Jie + */ + +#ifndef __SOF_LIB_DMA_H__ +#define __SOF_LIB_DMA_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __ZEPHYR__ +#include +#include +#endif + +struct comp_buffer; +struct comp_dev; +struct k_heap; + +/** \addtogroup sof_dma_drivers DMA Drivers + * DMA Drivers API specification. + * @{ + */ + +/* DMA direction bitmasks used to define DMA copy direction */ +#define DMA_DIR_MEM_TO_MEM BIT(0) /**< local memory copy */ +#define DMA_DIR_HMEM_TO_LMEM BIT(1) /**< host memory to local mem copy */ +#define DMA_DIR_LMEM_TO_HMEM BIT(2) /**< local mem to host mem copy */ +#define DMA_DIR_MEM_TO_DEV BIT(3) /**< local mem to dev copy */ +#define DMA_DIR_DEV_TO_MEM BIT(4) /**< dev to local mem copy */ +#define DMA_DIR_DEV_TO_DEV BIT(5) /**< dev to dev copy */ +#define SOF_DMA_DIR_MEM_TO_MEM DMA_DIR_MEM_TO_MEM +#define SOF_DMA_DIR_HMEM_TO_LMEM DMA_DIR_HMEM_TO_LMEM +#define SOF_DMA_DIR_LMEM_TO_HMEM DMA_DIR_LMEM_TO_HMEM +#define SOF_DMA_DIR_MEM_TO_DEV DMA_DIR_MEM_TO_DEV +#define SOF_DMA_DIR_DEV_TO_MEM DMA_DIR_DEV_TO_MEM +#define SOF_DMA_DIR_DEV_TO_DEV DMA_DIR_DEV_TO_DEV + +/* DMA capabilities bitmasks used to define the type of DMA */ +#define DMA_CAP_HDA BIT(0) /**< HDA DMA */ +#define DMA_CAP_GP_LP BIT(1) /**< GP LP DMA */ +#define DMA_CAP_GP_HP BIT(2) /**< GP HP DMA */ +#define DMA_CAP_BT BIT(3) /**< BT DMA */ +#define DMA_CAP_SP BIT(4) /**< SP DMA */ +#define DMA_CAP_DMIC BIT(5) /**< ACP DMA DMIC > */ +#define DMA_CAP_SP_VIRTUAL BIT(6) /**< SP VIRTUAL DMA */ +#define DMA_CAP_HS_VIRTUAL BIT(7) /**< HS VIRTUAL DMA */ + +/* DMA dev type bitmasks used to define the type of DMA */ + +#define DMA_DEV_HOST BIT(0) /**< connectable to host */ +#define DMA_DEV_HDA BIT(1) /**< connectable to HD/A link */ +#define DMA_DEV_SSP BIT(2) /**< connectable to SSP fifo */ +#define DMA_DEV_DMIC BIT(3) /**< connectable to DMIC fifo */ +#define DMA_DEV_SSI BIT(4) /**< connectable to SSI / SPI fifo */ +#define DMA_DEV_ALH BIT(5) /**< connectable to ALH link */ +#define DMA_DEV_SAI BIT(6) /**< connectable to SAI fifo */ +#define DMA_DEV_ESAI BIT(7) /**< connectable to ESAI fifo */ +#define DMA_DEV_BT BIT(8) /**< connectable to ACP BT I2S */ +#define DMA_DEV_SP BIT(9) /**< connectable to ACP SP I2S */ +#define DMA_DEV_AFE_MEMIF BIT(10) /**< connectable to AFE fifo */ +#define DMA_DEV_SP_VIRTUAL BIT(11) /**< connectable to ACP SP VIRTUAL I2S */ +#define DMA_DEV_HS_VIRTUAL BIT(12) /**< connectable to ACP HS VIRTUAL I2S */ +#define SOF_DMA_DEV_HOST DMA_DEV_HOST + +/* DMA access privilege flag */ +#define DMA_ACCESS_EXCLUSIVE 1 +#define DMA_ACCESS_SHARED 0 + +/* DMA copy flags */ +#define DMA_COPY_BLOCKING BIT(0) +#define DMA_COPY_ONE_SHOT BIT(1) + +/* We will use this enum in cb handler to inform dma what + * action we need to perform. + */ +enum dma_cb_status { + DMA_CB_STATUS_RELOAD = 0, + DMA_CB_STATUS_END, +}; + +#define SOF_DMA_CB_STATUS_RELOAD DMA_CB_STATUS_RELOAD +#define SOF_DMA_CB_STATUS_END DMA_CB_STATUS_END + +/* DMA interrupt commands */ +enum dma_irq_cmd { + DMA_IRQ_STATUS_GET = 0, + DMA_IRQ_CLEAR, + DMA_IRQ_MASK, + DMA_IRQ_UNMASK +}; + +#define DMA_CHAN_INVALID 0xFFFFFFFF +#define DMA_CORE_INVALID 0xFFFFFFFF +#define SOF_DMA_CHAN_INVALID DMA_CHAN_INVALID +#define SOF_DMA_CORE_INVALID DMA_CORE_INVALID + +/* Attributes have been ported to Zephyr. This condition is necessary until full support of + * CONFIG_SOF_ZEPHYR_STRICT_HEADERS. + */ +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS +/* DMA attributes */ +#define DMA_ATTR_BUFFER_ALIGNMENT 0 +#define DMA_ATTR_COPY_ALIGNMENT 1 +#define DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT 2 +#define DMA_ATTR_BUFFER_PERIOD_COUNT 3 +#endif + +struct dma; + +/** + * \brief Element of SG list (as array item). + */ +struct dma_sg_elem { + uint32_t src; /**< source address */ + uint32_t dest; /**< destination address */ + uint32_t size; /**< size (in bytes) */ +}; + +/** + * \brief Data used in DMA callbacks. + */ +struct dma_cb_data { + struct dma_chan_data *channel; + struct dma_sg_elem elem; + enum dma_cb_status status; +}; + +/** + * \brief SG elem array. + */ +struct dma_sg_elem_array { + uint32_t count; /**< number of elements in elems */ + struct dma_sg_elem *elems; /**< elements */ +}; + +/* DMA physical SG params */ +struct dma_sg_config { + uint32_t src_width; /* in bytes */ + uint32_t dest_width; /* in bytes */ + uint32_t burst_elems; + uint32_t direction; + uint32_t src_dev; + uint32_t dest_dev; + uint32_t cyclic; /* circular buffer */ + uint64_t period; + struct dma_sg_elem_array elem_array; /* array of dma_sg elems */ + bool scatter; + bool irq_disabled; + /* true if configured DMA channel is the scheduling source */ + bool is_scheduling_source; +}; + +struct dma_chan_status { + uint32_t state; + uint32_t flags; + uint32_t w_pos; + uint32_t r_pos; + uint32_t timestamp; + + /* dma position info for ipc4 */ + void *ipc_posn_data; +}; + +/* DMA operations */ +struct dma_ops { + + struct dma_chan_data *(*channel_get)(struct dma *dma, + unsigned int req_channel); + void (*channel_put)(struct dma_chan_data *channel); + + int (*start)(struct dma_chan_data *channel); + int (*stop)(struct dma_chan_data *channel); + int (*stop_delayed)(struct dma_chan_data *channel); + int (*copy)(struct dma_chan_data *channel, int bytes, uint32_t flags); + int (*pause)(struct dma_chan_data *channel); + int (*release)(struct dma_chan_data *channel); + int (*status)(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction); + + int (*set_config)(struct dma_chan_data *channel, + struct dma_sg_config *config); + + int (*probe)(struct dma *dma); + int (*remove)(struct dma *dma); + + int (*get_data_size)(struct dma_chan_data *channel, uint32_t *avail, + uint32_t *free); + + int (*get_attribute)(struct dma *dma, uint32_t type, uint32_t *value); + + int (*interrupt)(struct dma_chan_data *channel, enum dma_irq_cmd cmd); +}; + +/* DMA platform data */ +struct dma_plat_data { + uint32_t id; + uint32_t dir; /* bitmask of supported copy directions */ + uint32_t caps; /* bitmask of supported capabilities */ + uint32_t devs; /* bitmask of supported devs */ + uint32_t base; + uint32_t channels; + int irq; + const char *irq_name; + uint32_t chan_size; + const void *drv_plat_data; +#ifdef __ZEPHYR__ + uint32_t period_count; +#endif +}; + +struct dma { + struct dma_plat_data plat_data; + struct k_spinlock lock; /**< locking mechanism */ + int sref; /**< simple ref counter, guarded by lock */ + const struct dma_ops *ops; + atomic_t num_channels_busy; /* number of busy channels */ + struct dma_chan_data *chan; /* channels array */ +#ifdef __ZEPHYR__ + const struct device *z_dev; /* Zephyr driver */ +#endif + void *priv_data; +}; + +struct dma_chan_data { + struct dma *dma; + + uint32_t status; + uint32_t direction; + uint32_t desc_count; + uint32_t index; + uint32_t core; + uint64_t period; /* DMA channel's transfer period in us */ + /* true if this DMA channel is the scheduling source */ + bool is_scheduling_source; + + /* device specific data set by the device that requests the DMA channel */ + void *dev_data; + + void *priv_data; +}; + +struct dma_info { + struct dma *dma_array; + size_t num_dmas; +}; + +struct audio_stream; +typedef int (*dma_process_func)(const struct audio_stream __sparse_cache *source, + uint32_t ioffset, struct audio_stream __sparse_cache *sink, + uint32_t ooffset, uint32_t source_samples, uint32_t chmap); + +/** + * \brief API to initialize a platform DMA controllers. + * + * \param[in] sof Pointer to firmware main context. + */ +int dmac_init(struct sof *sof); + +/** + * \brief API to request a platform DMAC. + * + * Users can request DMAC based on dev type, copy direction, capabilities + * and access privilege. + * For exclusive access, ret DMAC with no channels draining. + * For shared access, ret DMAC with the least number of channels draining. + */ +struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags); + +/** + * \brief API to release a platform DMAC. + * + * @param[in] dma DMAC to relese. + */ +void dma_put(struct dma *dma); + +#define dma_set_drvdata(dma, data) \ + (dma->priv_data = data) +#define dma_get_drvdata(dma) \ + dma->priv_data +#define dma_base(dma) \ + dma->plat_data.base +#define dma_irq(dma) \ + dma->plat_data.irq +#define dma_irq_name(dma) \ + dma->plat_data.irq_name +#define dma_chan_size(dma) \ + dma->plat_data.chan_size +#define dma_chan_base(dma, chan) \ + (dma->plat_data.base + chan * dma->plat_data.chan_size) +#define dma_chan_get_data(chan) \ + ((chan)->priv_data) +#define dma_chan_set_data(chan, data) \ + ((chan)->priv_data = data) + +/* DMA API + * Programming flow is :- + * + * 1) dma_channel_get() + * 2) notifier_register() + * 3) dma_set_config() + * 4) dma_start() + * ... DMA now running ... + * 5) dma_stop() + * 6) dma_stop_delayed() + * 7) dma_channel_put() + */ + +static inline struct dma_chan_data *dma_channel_get_legacy(struct dma *dma, + int req_channel) +{ + if (!dma || !dma->ops || !dma->ops->channel_get) + return NULL; + + struct dma_chan_data *chan = dma->ops->channel_get(dma, req_channel); + + return chan; +} + +static inline void dma_channel_put_legacy(struct dma_chan_data *channel) +{ + channel->dma->ops->channel_put(channel); +} + +static inline int dma_start_legacy(struct dma_chan_data *channel) +{ + return channel->dma->ops->start(channel); +} + +static inline int dma_stop_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->stop) + return channel->dma->ops->stop(channel); + + return 0; +} + +static inline int dma_stop_delayed_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->stop_delayed) + return channel->dma->ops->stop_delayed(channel); + + return 0; +} + +/** \defgroup sof_dma_copy_func static int dma_copy (struct dma_chan_data * channel, int bytes, uint32_t flags) + * + * This function is in a separate subgroup to solve a name clash with + * struct dma_copy {} + * @{ + */ +static inline int dma_copy_legacy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + return channel->dma->ops->copy(channel, bytes, flags); +} +/** @} */ + +static inline int dma_pause_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->pause) + return channel->dma->ops->pause(channel); + + return 0; +} + +static inline int dma_release_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->release) + return channel->dma->ops->release(channel); + + return 0; +} + +static inline int dma_status_legacy(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction) +{ + return channel->dma->ops->status(channel, status, direction); +} + +static inline int dma_set_config_legacy(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + return channel->dma->ops->set_config(channel, config); +} + +static inline int dma_probe_legacy(struct dma *dma) +{ + return dma->ops->probe(dma); +} + +static inline int dma_remove_legacy(struct dma *dma) +{ + return dma->ops->remove(dma); +} + +static inline int dma_get_data_size_legacy(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + return channel->dma->ops->get_data_size(channel, avail, free); +} + +static inline int dma_get_attribute_legacy(struct dma *dma, uint32_t type, + uint32_t *value) +{ + return dma->ops->get_attribute(dma, type, value); +} + +static inline int dma_interrupt_legacy(struct dma_chan_data *channel, + enum dma_irq_cmd cmd) +{ + return channel->dma->ops->interrupt(channel, cmd); +} + +/* DMA hardware register operations */ +static inline uint32_t dma_reg_read(struct dma *dma, uint32_t reg) +{ + return io_reg_read(dma_base(dma) + reg); +} + +static inline uint16_t dma_reg_read16(struct dma *dma, uint32_t reg) +{ + return io_reg_read16(dma_base(dma) + reg); +} + +static inline void dma_reg_write(struct dma *dma, uint32_t reg, uint32_t value) +{ + io_reg_write(dma_base(dma) + reg, value); +} + +static inline void dma_reg_write16(struct dma *dma, uint32_t reg, + uint16_t value) +{ + io_reg_write16(dma_base(dma) + reg, value); +} + +static inline void dma_reg_update_bits(struct dma *dma, uint32_t reg, + uint32_t mask, uint32_t value) +{ + io_reg_update_bits(dma_base(dma) + reg, mask, value); +} + +static inline uint32_t dma_chan_reg_read(struct dma_chan_data *channel, + uint32_t reg) +{ + return io_reg_read(dma_chan_base(channel->dma, channel->index) + reg); +} + +static inline uint16_t dma_chan_reg_read16(struct dma_chan_data *channel, + uint32_t reg) +{ + return io_reg_read16(dma_chan_base(channel->dma, channel->index) + reg); +} + +static inline void dma_chan_reg_write(struct dma_chan_data *channel, + uint32_t reg, uint32_t value) +{ + io_reg_write(dma_chan_base(channel->dma, channel->index) + reg, value); +} + +static inline void dma_chan_reg_write16(struct dma_chan_data *channel, + uint32_t reg, uint16_t value) +{ + io_reg_write16(dma_chan_base(channel->dma, channel->index) + reg, + value); +} + +static inline void dma_chan_reg_update_bits(struct dma_chan_data *channel, + uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(dma_chan_base(channel->dma, channel->index) + reg, + mask, value); +} + +static inline void dma_chan_reg_update_bits16(struct dma_chan_data *channel, + uint32_t reg, uint16_t mask, + uint16_t value) +{ + io_reg_update_bits16(dma_chan_base(channel->dma, channel->index) + reg, + mask, value); +} + +static inline bool dma_is_scheduling_source(struct dma_chan_data *channel) +{ + return channel->is_scheduling_source; +} + +static inline void dma_sg_init(struct dma_sg_elem_array *ea) +{ + ea->count = 0; + ea->elems = NULL; +} + +int dma_sg_alloc(struct k_heap *heap, + struct dma_sg_elem_array *ea, + uint32_t flags, + uint32_t direction, + uint32_t buffer_count, uint32_t buffer_bytes, + uintptr_t dma_buffer_addr, uintptr_t external_addr); + +void dma_sg_free(struct k_heap *heap, struct dma_sg_elem_array *ea); + +/** + * \brief Get the total size of SG buffer + * + * \param ea Array of SG elements. + * \return Size of the buffer. + */ +static inline uint32_t dma_sg_get_size(struct dma_sg_elem_array *ea) +{ + int i; + uint32_t size = 0; + + for (i = 0 ; i < ea->count; i++) + size += ea->elems[i].size; + + return size; +} + +/* copies data from DMA buffer using provided processing function */ +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, uint32_t chmap); + +/* 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, + dma_process_func process, uint32_t sink_bytes, uint32_t chmap); + +/* + * Used when copying stream audio 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 stream_copy_from_no_consume(struct comp_dev *dev, + struct comp_buffer __sparse_cache *source, + struct comp_buffer __sparse_cache *sink, + dma_process_func process, + uint32_t source_bytes, uint32_t chmap); + +/* generic DMA DSP <-> Host copier */ + +struct dma_copy { + struct dma_chan_data *chan; + struct dma *dmac; +}; + +/* init dma copy context */ +int dma_copy_new(struct dma_copy *dc); + +/* free dma copy context resources */ +static inline void dma_copy_free(struct dma_copy *dc) +{ + dma_channel_put_legacy(dc->chan); +} + +/* DMA copy data from host to DSP */ +int dma_copy_from_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_from_host_nowait(struct dma_copy *dc, + struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, + int32_t size); + +/* DMA copy data from DSP to host */ +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); + + +int dma_copy_set_stream_tag(struct dma_copy *dc, uint32_t stream_tag); + +static inline const struct dma_info *dma_info_get(void) +{ + return sof_get()->dma_info; +} + +/** @}*/ + +#endif /* __SOF_LIB_DMA_H__ */ diff --git a/posix/include/sof/lib/io.h b/posix/include/sof/lib/io.h new file mode 100644 index 000000000000..07f1e5aa1fbe --- /dev/null +++ b/posix/include/sof/lib/io.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + */ + +#ifndef __XTOS_POSIX_LIB_IO_H__ +#define __XTOS_POSIX_LIB_IO_H__ + + +#include + +#if CONFIG_LIBRARY + +static inline uint32_t io_reg_read(uint32_t reg) { return 0; } +static inline void io_reg_write(uint32_t reg, uint32_t val) {} +static inline void io_reg_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) {} +static inline uint16_t io_reg_read16(uint32_t reg) { return 0; } +static inline void io_reg_write16(uint32_t reg, uint16_t val) {} +static inline void io_reg_update_bits16(uint32_t reg, uint16_t mask, + uint16_t value) {} + +#else + +static inline uint32_t io_reg_read(uint32_t reg) +{ + return *((volatile uint32_t *)reg); +} + +static inline void io_reg_write(uint32_t reg, uint32_t val) +{ + *((volatile uint32_t *)reg) = val; +} + +static inline void io_reg_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_write(reg, (io_reg_read(reg) & (~mask)) | (value & mask)); +} + +static inline uint16_t io_reg_read16(uint32_t reg) +{ + return *((volatile uint16_t *)reg); +} + +static inline void io_reg_write16(uint32_t reg, uint16_t val) +{ + *((volatile uint16_t *)reg) = val; +} + +static inline uint64_t io_reg_read64(uint32_t reg) +{ + return (uint64_t)io_reg_read(reg) + + (((uint64_t)io_reg_read(reg + 4)) << 32); +} + +static inline void io_reg_write64(uint32_t reg, uint64_t val) +{ + *((volatile uint64_t *)reg) = val; +} + +static inline void io_reg_update_bits16(uint32_t reg, uint16_t mask, + uint16_t value) +{ + io_reg_write16(reg, (io_reg_read16(reg) & (~mask)) | (value & mask)); +} + +static inline uint8_t io_reg_read8(uint32_t reg) +{ + return *((volatile uint8_t *)reg); +} + +static inline void io_reg_write8(uint32_t reg, uint8_t val) +{ + *((volatile uint8_t *)reg) = val; +} + +static inline void io_reg_update_bits8(uint32_t reg, uint8_t mask, + uint8_t value) +{ + io_reg_write8(reg, (io_reg_read8(reg) & (~mask)) | (value & mask)); +} + +#endif + +#endif /* __XTOS_POSIX_LIB_IO_H__ */ diff --git a/posix/include/sof/lib/mailbox.h b/posix/include/sof/lib/mailbox.h new file mode 100644 index 000000000000..06e2659a5847 --- /dev/null +++ b/posix/include/sof/lib/mailbox.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Xiuli Pan + */ + +#ifndef __SOF_LIB_MAILBOX_H__ +#define __SOF_LIB_MAILBOX_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define mailbox_get_exception_base() \ + MAILBOX_EXCEPTION_BASE + +#define mailbox_get_exception_size() \ + MAILBOX_EXCEPTION_SIZE + +#define mailbox_get_dspbox_base() \ + MAILBOX_DSPBOX_BASE + +#define mailbox_get_dspbox_size() \ + MAILBOX_DSPBOX_SIZE + +#define mailbox_get_hostbox_base() \ + MAILBOX_HOSTBOX_BASE + +#define mailbox_get_hostbox_size() \ + MAILBOX_HOSTBOX_SIZE + +#define mailbox_get_debug_base() \ + MAILBOX_DEBUG_BASE + +#define mailbox_get_debug_size() \ + MAILBOX_DEBUG_SIZE + +static inline +void mailbox_dspbox_write(size_t offset, const void *src, size_t bytes) +{ + int dsp_write_err __unused = memcpy_s((void *)(MAILBOX_DSPBOX_BASE + offset), + MAILBOX_DSPBOX_SIZE - offset, src, bytes); + + assert(!dsp_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_DSPBOX_BASE + + offset), bytes); +} + +static inline +void mailbox_dspbox_read(void *dest, size_t dest_size, + size_t offset, size_t bytes) +{ + int dsp_read_err __unused; + + dcache_invalidate_region((__sparse_force void __sparse_cache *)(MAILBOX_DSPBOX_BASE + + offset), bytes); + dsp_read_err = memcpy_s(dest, dest_size, + (void *)(MAILBOX_DSPBOX_BASE + offset), bytes); + assert(!dsp_read_err); +} + +#if CONFIG_LIBRARY + +#define mailbox_hostbox_write(_offset, _src, _bytes) \ + memcpy((char *)ipc->comp_data + _offset, _src, _bytes) + +#else + +static inline +void mailbox_hostbox_write(size_t offset, const void *src, size_t bytes) +{ + int host_write_err __unused = memcpy_s((void *)(MAILBOX_HOSTBOX_BASE + offset), + MAILBOX_HOSTBOX_SIZE - offset, src, bytes); + + assert(!host_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_HOSTBOX_BASE + + offset), bytes); +} + +#endif + +static inline +void mailbox_hostbox_read(void *dest, size_t dest_size, + size_t offset, size_t bytes) +{ + int host_read_err __unused; + + dcache_invalidate_region((__sparse_force void __sparse_cache *)(MAILBOX_HOSTBOX_BASE + + offset), bytes); + host_read_err = memcpy_s(dest, dest_size, + (void *)(MAILBOX_HOSTBOX_BASE + offset), bytes); + assert(!host_read_err); +} + +static inline +void mailbox_stream_write(size_t offset, const void *src, size_t bytes) +{ + int stream_write_err __unused = memcpy_s((void *)(MAILBOX_STREAM_BASE + offset), + MAILBOX_STREAM_SIZE - offset, src, bytes); + + assert(!stream_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_STREAM_BASE + + offset), bytes); +} + +#endif /* __SOF_LIB_MAILBOX_H__ */ diff --git a/posix/include/sof/lib/memory.h b/posix/include/sof/lib/memory.h new file mode 100644 index 000000000000..456049a3bddb --- /dev/null +++ b/posix/include/sof/lib/memory.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +#ifndef __SOF_LIB_MEMORY_H__ +#define __SOF_LIB_MEMORY_H__ + +#include + +#ifndef __cold +#define __cold +#endif + +#ifndef __cold_rodata +#define __cold_rodata +#endif + +#define assert_can_be_cold() do {} while (0) +#define dbg_path_hot_confirm() do {} while (0) + +#endif /* __SOF_LIB_MEMORY_H__ */ diff --git a/posix/include/sof/lib/mm_heap.h b/posix/include/sof/lib/mm_heap.h new file mode 100644 index 000000000000..84bcc893d101 --- /dev/null +++ b/posix/include/sof/lib/mm_heap.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __SOF_LIB_MM_HEAP_H__ +#define __SOF_LIB_MM_HEAP_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct dma_copy; +struct dma_sg_config; + +struct mm_info { + uint32_t used; + uint32_t free; +}; + +struct block_hdr { + uint16_t size; /* size in blocks for continuous allocation */ + uint16_t used; /* usage flags for page */ + void *unaligned_ptr; /* align ptr */ +} __packed; + +struct block_map { + uint16_t block_size; /* size of block in bytes */ + uint16_t count; /* number of blocks in map */ + uint16_t free_count; /* number of free blocks */ + uint16_t first_free; /* index of first free block */ + struct block_hdr *block; /* base block header */ + uint32_t base; /* base address of space */ +}; + +#define BLOCK_DEF(sz, cnt, hdr) \ + {.block_size = sz, .count = cnt, .free_count = cnt, .block = hdr, \ + .first_free = 0} + +struct mm_heap { + uint32_t blocks; + struct block_map *map; +#if CONFIG_LIBRARY + unsigned long heap; +#else + uint32_t heap; +#endif + uint32_t size; + uint32_t caps; + struct mm_info info; +}; + +/* heap block memory map */ +struct mm { + /* system heap - used during init cannot be freed */ + struct mm_heap system[PLATFORM_HEAP_SYSTEM]; + /* system runtime heap - used for runtime system components */ + struct mm_heap system_runtime[PLATFORM_HEAP_SYSTEM_RUNTIME]; +#if CONFIG_CORE_COUNT > 1 + /* object shared between different cores - used during init cannot be freed */ + struct mm_heap system_shared[PLATFORM_HEAP_SYSTEM_SHARED]; + /* object shared between different cores */ + struct mm_heap runtime_shared[PLATFORM_HEAP_RUNTIME_SHARED]; +#endif + /* general heap for components */ + struct mm_heap runtime[PLATFORM_HEAP_RUNTIME]; + /* general component buffer heap */ + struct mm_heap buffer[PLATFORM_HEAP_BUFFER]; + + struct mm_info total; + uint32_t heap_trace_updated; /* updates that can be presented */ + struct k_spinlock lock; /* all allocs and frees are atomic */ +}; + +/* Heap save/restore contents and context for PM D0/D3 events */ +uint32_t mm_pm_context_size(void); + +/* heap initialisation */ +void init_heap(struct sof *sof); + +/* frees entire heap (supported for secondary core system heap atm) */ +void free_heap(void); + +/* status */ +void heap_trace_all(int force); +void heap_trace(struct mm_heap *heap, int size); + +#if CONFIG_DEBUG_MEMORY_USAGE_SCAN +/** Fetch runtime information about heap, like used and free memory space + * @param zone to check, see enum mem_zone. + * @param index heap index, eg. cpu core index for any *SYS* zone + * @param out output variable + * @return error code or zero + */ +int heap_info(int index, struct mm_info *out); +#endif + +/* retrieve memory map pointer */ +static inline struct mm *memmap_get(void) +{ + return sof_get()->memory_map; +} + +#endif /* __SOF_LIB_MM_HEAP_H__ */ diff --git a/posix/include/sof/lib/perf_cnt.h b/posix/include/sof/lib/perf_cnt.h new file mode 100644 index 000000000000..bddda9c8e06b --- /dev/null +++ b/posix/include/sof/lib/perf_cnt.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Marcin Maka + */ + +/** + * \file xtos/include/sof/lib/perf_cnt.h + * \brief Simple performance counters + * \author Marcin Maka + */ + +#ifndef __SOF_LIB_PERF_CNT_H__ +#define __SOF_LIB_PERF_CNT_H__ + +#include + +struct perf_cnt_data { + uint32_t plat_ts; + uint32_t cpu_ts; + uint32_t plat_delta_last; + uint32_t plat_delta_peak; + uint32_t cpu_delta_last; + uint32_t cpu_delta_peak; + uint32_t cpu_delta_sum; + uint32_t sample_cnt; +}; + +#if CONFIG_PERFORMANCE_COUNTERS + +#define perf_cnt_trace(ctx, pcd) \ + tr_info(ctx, "perf plat last %u peak %u cpu last %u, peak %u", \ + (uint32_t)((pcd)->plat_delta_last), \ + (uint32_t)((pcd)->plat_delta_peak), \ + (uint32_t)((pcd)->cpu_delta_last), \ + (uint32_t)((pcd)->cpu_delta_peak)) + +/** \brief Clears performance counters data. */ +#define perf_cnt_clear(pcd) memset((pcd), 0, sizeof(struct perf_cnt_data)) + +/* NOTE: Zephyr's arch_timing_counter_get() might not be implemented + * for a particular platform. In this case let's fallback to use + * Zephyr's k_cycle_get_64(). This will result in both "platform" and + * "cpu" timestamps to be equal. + */ +#ifdef __ZEPHYR__ + #ifdef CONFIG_TIMING_FUNCTIONS + #define perf_cnt_get_cpu_ts arch_timing_counter_get + #else + #define perf_cnt_get_cpu_ts sof_cycle_get_64 + #endif /* CONFIG_TIMING_FUNCTIONS */ +#else + #define perf_cnt_get_cpu_ts() timer_get_system(cpu_timer_get()) +#endif /* __ZEPHYR__ */ + +/** \brief Initializes timestamps with current timer values. */ +#define perf_cnt_init(pcd) do { \ + (pcd)->plat_ts = sof_cycle_get_64(); \ + (pcd)->cpu_ts = perf_cnt_get_cpu_ts(); \ + } while (0) + +/* Trace macros that can be used as trace_m argument of the perf_cnt_stamp() + * to trace PCD values if the last arch timer reading exceeds the previous + * peak value. + * + * arg passed to perf_cnt_stamp() is forwarded to the trace_m() macro + * as the second argument. + */ + +/** \brief No trace when detecting peak value. */ +#define perf_trace_null(pcd, arg) + +/** \brief Simple trace, all values are printed, arg should be a tr_ctx address. + */ +#define perf_trace_simple(pcd, arg) perf_cnt_trace(arg, pcd) + +/* perf measurement windows size 2^x */ +#define PERF_CNT_CHECK_WINDOW_SIZE 10 +#define task_perf_avg_info(pcd, task_p, class) \ + tr_info(task_p, "perf_cycle task %p, %pU cpu avg %u peak %u",\ + class, (class)->uid, \ + (uint32_t)((pcd)->cpu_delta_sum), \ + (uint32_t)((pcd)->cpu_delta_peak)) +#define task_perf_cnt_avg(pcd, trace_m, arg, class) do { \ + (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \ + if (++(pcd)->sample_cnt == 1 << PERF_CNT_CHECK_WINDOW_SIZE) { \ + (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \ + trace_m(pcd, arg, class); \ + (pcd)->cpu_delta_sum = 0; \ + (pcd)->sample_cnt = 0; \ + (pcd)->plat_delta_peak = 0; \ + (pcd)->cpu_delta_peak = 0; \ + } \ + } while (0) + +/** \brief Accumulates cpu timer delta samples calculated by perf_cnt_stamp(). + * + * If current sample count reaches the window size, compute the average and run trace_m. + * \param pcd Performance counters data. + * \param trace_m Trace function trace_m(pcd, arg) or trace macro if a + * more precise line number is desired in the logs. + * \param arg Argument passed to trace_m as arg. + */ +#define perf_cnt_average(pcd, trace_m, arg) do { \ + (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \ + if (++(pcd)->sample_cnt == 1 << PERF_CNT_CHECK_WINDOW_SIZE) {\ + (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \ + trace_m(pcd, arg); \ + (pcd)->cpu_delta_sum = 0; \ + (pcd)->sample_cnt = 0; \ + (pcd)->plat_delta_peak = 0; \ + (pcd)->cpu_delta_peak = 0; \ + } \ + } while (0) + +/** \brief Reads the timers and computes delta to the previous readings. + * + * If current arch delta exceeds the previous peak value, trace_m is run. + * \param pcd Performance counters data. + * \param trace_m Trace function trace_m(pcd, arg) or trace macro if a + * more precise line number is desired in the logs. + * \param arg Argument passed to trace_m as arg. + */ +#define perf_cnt_stamp(pcd, trace_m, arg) do { \ + uint32_t plat_ts = \ + (uint32_t)sof_cycle_get_64(); \ + uint32_t cpu_ts = \ + (uint32_t)perf_cnt_get_cpu_ts(); \ + if (plat_ts > (pcd)->plat_ts) \ + (pcd)->plat_delta_last = plat_ts - (pcd)->plat_ts; \ + else \ + (pcd)->plat_delta_last = UINT32_MAX - (pcd)->plat_ts \ + + plat_ts; \ + if (cpu_ts > (pcd)->cpu_ts) \ + (pcd)->cpu_delta_last = cpu_ts - (pcd)->cpu_ts; \ + else \ + (pcd)->cpu_delta_last = UINT32_MAX - (pcd)->cpu_ts \ + + cpu_ts;\ + if ((pcd)->plat_delta_last > (pcd)->plat_delta_peak) \ + (pcd)->plat_delta_peak = (pcd)->plat_delta_last; \ + if ((pcd)->cpu_delta_last > (pcd)->cpu_delta_peak) { \ + (pcd)->cpu_delta_peak = (pcd)->cpu_delta_last; \ + trace_m(pcd, arg); \ + } \ + } while (0) + +/** + * For simple performance measurement and optimization in development stage, + * tic-toc api is provided. Performance data are traced at each tok call, + * to allow fast clocks usage deviation estimation. Example: + * + * \code{.c} + * void foo(struct comp_dev *dev) { + * static struct perf_cnt_data pcd; + * + * perf_tic(&pcd); + * bar(); + * perf_toc(&pcd, dev); + * } + * \endcode + */ + +/** \brief Save start timestamp in pcd structure + * + * \param pcd Performance counters data. + */ +#define perf_tic(pcd) \ + perf_cnt_init(pcd) + +/** \brief Save start timestamp in pcd structure + * + * \param pcd Performance counters data. + * \param comp Component used to get corresponding trace context. + */ +#define perf_toc(pcd, comp) do { \ + perf_cnt_stamp(pcd, perf_trace_null, NULL); \ + perf_trace_simple(pcd, trace_comp_get_tr_ctx(comp)); \ + } while (0) + +#else +#define perf_cnt_clear(pcd) +#define perf_cnt_init(pcd) +#define perf_cnt_stamp(pcd, trace_m, arg) +#define perf_cnt_average(pcd, trace_m, arg) +#endif + +#endif /* __SOF_LIB_PERF_CNT_H__ */ diff --git a/posix/include/sof/lib/pm_runtime.h b/posix/include/sof/lib/pm_runtime.h new file mode 100644 index 000000000000..c0a24116e629 --- /dev/null +++ b/posix/include/sof/lib/pm_runtime.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + * Janusz Jankowski + */ + +/** + * \file xtos/include/sof/lib/pm_runtime.h + * \brief Runtime power management header file + * \author Tomasz Lauda + */ + +#ifndef __SOF_LIB_PM_RUNTIME_H__ +#define __SOF_LIB_PM_RUNTIME_H__ + +#include +#include +#include +#include +#include +#include + +/** \addtogroup pm_runtime PM Runtime + * PM runtime specification. + * @{ + */ + +/* PM runtime flags */ + +#define RPM_ASYNC 0x01 /**< Request is asynchronous */ + +/** \brief Runtime power management context */ +enum pm_runtime_context { + PM_RUNTIME_HOST_DMA_L1 = 0, /**< Host DMA L1 */ + SSP_CLK, /**< SSP Clock */ + SSP_POW, /**< SSP Power */ + DMIC_CLK, /**< DMIC Clock */ + DMIC_POW, /**< DMIC Power */ + DW_DMAC_CLK, /**< DW DMAC Clock */ + CORE_MEMORY_POW, /**< Core Memory power */ + CORE_HP_CLK, /**< High Performance Clock*/ + PM_RUNTIME_DSP /**< DSP */ +}; + +/** \brief Runtime power management data. */ +struct pm_runtime_data { + struct k_spinlock lock; /**< lock mechanism */ + void *platform_data; /**< platform specific data */ +#if CONFIG_DSP_RESIDENCY_COUNTERS + struct r_counters_data *r_counters; /**< diagnostic DSP residency counters */ +#endif +}; + +#if CONFIG_DSP_RESIDENCY_COUNTERS +/** + * \brief DSP residency counters + * R0, R1, R2 are DSP residency counters which can be used differently + * based on platform implementation. + * In general R0 is the highest power consumption state while R2 is + * the lowest power consumption state. See platform specific pm_runtime.h + * for the platform HW specific mapping. + */ +enum dsp_r_state { + r0_r_state = 0, + r1_r_state, + r2_r_state +}; + +/** \brief Diagnostic DSP residency counters data */ +struct r_counters_data { + enum dsp_r_state cur_r_state; /**< current dsp_r_state */ + uint64_t ts; /**< dsp_r_state timestamp */ +}; +#endif + +/** + * \brief Initializes runtime power management. + */ +void pm_runtime_init(struct sof *sof); + +/** + * \brief Retrieves power management resource (async). + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_get(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Retrieves power management resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_get_sync(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Releases power management resource (async). + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_put(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Releases power management resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_put_sync(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Enables power management operations for the resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_enable(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Disables power management operations for the resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_disable(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Reports state of the power managed resource. + * + * @param context Type of power management context. + * @param index Index of the resource. + * + * @return true if the resource is active or pm disabled, false otherwise. + */ +bool pm_runtime_is_active(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Retrieves pointer to runtime power management data. + * + * @return Runtime power management data pointer. + */ +static inline struct pm_runtime_data *pm_runtime_data_get(void) +{ + return sof_get()->prd; +} + +#if CONFIG_DSP_RESIDENCY_COUNTERS +/** + * \brief Initializes DSP residency counters. + * + * \param[in] context Type of power management context. + */ +void init_dsp_r_state(enum dsp_r_state); + +/** + * \brief Reports DSP residency state. + * + * \param[in] new state + */ +void report_dsp_r_state(enum dsp_r_state); + +/** + * \brief Retrieves current DSP residency state. + * + * @return active DSP residency state + */ +enum dsp_r_state get_dsp_r_state(void); +#endif + +/** @}*/ + +#endif /* __SOF_LIB_PM_RUNTIME_H__ */ diff --git a/src/include/sof/lib/shim.h b/posix/include/sof/lib/shim.h similarity index 100% rename from src/include/sof/lib/shim.h rename to posix/include/sof/lib/shim.h diff --git a/posix/include/sof/list.h b/posix/include/sof/list.h new file mode 100644 index 000000000000..a81576fb5e68 --- /dev/null +++ b/posix/include/sof/list.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + */ + +#ifndef __SOF_LIST_H__ +#define __SOF_LIST_H__ + +/* Really simple list manipulation */ + +struct list_item; + +struct list_item { + struct list_item *next; + struct list_item *prev; +}; + +/* a static list head initialiser */ +#define LIST_INIT(head) {&head, &head} + +/* initialise list before any use - list will point to itself */ +static inline void list_init(struct list_item *list) +{ + list->next = list; + list->prev = list; +} + +/* add new item to the start or head of the list */ +static inline void list_item_prepend(struct list_item *item, + struct list_item *list) +{ + struct list_item *next = list->next; + + next->prev = item; + item->next = next; + item->prev = list; + list->next = item; +} + +/* add new item to the end or tail of the list */ +static inline void list_item_append(struct list_item *item, + struct list_item *list) +{ + struct list_item *tail = list->prev; + + tail->next = item; + item->next = list; + item->prev = tail; + list->prev = item; +} + +/* delete item from the list leaves deleted list item + *in undefined state list_is_empty will return true + */ +static inline void list_item_del(struct list_item *item) +{ + item->next->prev = item->prev; + item->prev->next = item->next; + list_init(item); +} + +/* is list item the last item in list ? */ +static inline int list_item_is_last(struct list_item *item, + struct list_item *list) +{ + return item->next == list; +} + +/* is list empty ? */ +#define list_is_empty(item) \ + ((item)->next == item) + +#define __list_object(item, type, offset) \ + ((type *)((char *)(item) - (offset))) + +/* get the container object of the list item */ +#define list_item(item, type, member) \ + __list_object(item, type, offsetof(type, member)) + +/* get the container object of the first item in the list */ +#define list_first_item(list, type, member) \ + __list_object((list)->next, type, offsetof(type, member)) + +/* get the next container object in the list */ +#define list_next_item(object, member) \ + list_item((object)->member.next, typeof(*(object)), member) + +/* list iterator */ +#define list_for_item(item, list) \ + for (item = (list)->next; item != (list); item = item->next) + +/* list iterator */ +#define list_for_item_prev(item, list) \ + for (item = (list)->prev; item != (list); item = item->prev) + +/* list iterator - safe to delete items */ +#define list_for_item_safe(item, tmp, list) \ + for (item = (list)->next, tmp = item->next;\ + item != (list); \ + item = tmp, tmp = item->next) + +/** + * Re-links the list when head address changed (list moved). + * @param new_list New address of the head. + * @param old_list Old address of the head. + */ +static inline void list_relink(struct list_item *new_list, + struct list_item *old_list) +{ + struct list_item *li; + + if (new_list->next == old_list) { + list_init(new_list); + } else { + list_for_item(li, new_list) + if (li->next == old_list) + li->next = new_list; /* for stops here */ + list_for_item_prev(li, new_list) + if (li->prev == old_list) + li->prev = new_list; /* for stops here */ + } +} + +#endif /* __SOF_LIST_H__ */ diff --git a/src/include/sof/trace/preproc-private-dec.h b/posix/include/sof/trace/preproc-private-dec.h similarity index 100% rename from src/include/sof/trace/preproc-private-dec.h rename to posix/include/sof/trace/preproc-private-dec.h diff --git a/src/include/sof/trace/preproc-private-inc.h b/posix/include/sof/trace/preproc-private-inc.h similarity index 100% rename from src/include/sof/trace/preproc-private-inc.h rename to posix/include/sof/trace/preproc-private-inc.h diff --git a/src/include/sof/trace/preproc-private.h b/posix/include/sof/trace/preproc-private.h similarity index 75% rename from src/include/sof/trace/preproc-private.h rename to posix/include/sof/trace/preproc-private.h index 19397d35e932..37202b5a2044 100644 --- a/src/include/sof/trace/preproc-private.h +++ b/posix/include/sof/trace/preproc-private.h @@ -75,8 +75,6 @@ * META_RECURSE(META_REPEAT */ -#define _META_NO_ARGS(...) 0 - /* _META_IS_PROBE(...) evaluates to 0 when __VA_ARGS__ is single token * _META_IS_PROBE(PROBE()) evaulates to 1, because it is equivalent to * _META_GET_ARG_2(~, 1, 0) @@ -117,13 +115,6 @@ #define _META_IIF_1(x, ...) x /* primitive recursion */ -#define _META_REQRS_1024(...) _META_REQRS_512(_META_REQRS_512(__VA_ARGS__)) -#define _META_REQRS_512(...) _META_REQRS_256(_META_REQRS_256(__VA_ARGS__)) -#define _META_REQRS_256(...) _META_REQRS_128(_META_REQRS_128(__VA_ARGS__)) -#define _META_REQRS_128(...) _META_REQRS_64( _META_REQRS_64 (__VA_ARGS__)) -#define _META_REQRS_64(...) _META_REQRS_32( _META_REQRS_32 (__VA_ARGS__)) -#define _META_REQRS_32(...) _META_REQRS_16( _META_REQRS_16 (__VA_ARGS__)) -#define _META_REQRS_16(...) _META_REQRS_8( _META_REQRS_8 (__VA_ARGS__)) #define _META_REQRS_8(...) _META_REQRS_4( _META_REQRS_4 (__VA_ARGS__)) #define _META_REQRS_4(...) _META_REQRS_2( _META_REQRS_2 (__VA_ARGS__)) #define _META_REQRS_2(...) _META_REQRS_1( _META_REQRS_1 (__VA_ARGS__)) @@ -141,42 +132,9 @@ */ #define _META_EMPTY() -/* These two will expand to: - * _META_EMPTY _META_EMPTY ... _META_EMPTY - * () () ... () - * Why '_META_EMPTY() _META_EMPTY' instead of '_META_EMPTY'? - * Using simply '_META_EMPTY' would produce - * _META_EMPTY_META_EMPTY_META_EMPTY - * and adding _META_EMPTY() introduces a " "(space) token. - */ -#define _META_EMPTY_GEN(i, rest) _META_EMPTY() _META_EMPTY -#define _META_PAREN_GEN(i, rest) () -/* You cannot use here META_RECURSE - * and must instead use _META_REQRS_{NUMBER}. - * If META_RECURSE was used, things like - * META_RECURSE(MAP_AGGREGATE -* would break. - */ -#define _META_DEFER_N(depth) \ - META_RECURSE_N(16, META_REPEAT(depth, _META_EMPTY_GEN, ~)) \ - META_RECURSE_N(16, META_REPEAT(depth, _META_PAREN_GEN, ~)) - /* Special, implicit defer implementation for META_REPEAT to work */ #define _META_DEFER_2(m) m _META_EMPTY _META_EMPTY () () -/* helpers for consuming every single arg from __VA_ARGS__ */ -// expand and discard -#define _META_EAT(...) -// force expansion, reverse of META_DEFER -#define _META_EXPAND(...) __VA_ARGS__ -#define _META_WHEN(c) META_IF(c)(_META_EXPAND, _META_EAT) - -/* while(count--!=0) do - * uses DEC so count == N can only work if all following exist - * DEC_0, DEC_1, ..., DEC_N-1, DEC_N - */ -#define _META_REPEAT_INDIRECT() META_REPEAT - /* map every group of arg_count arguments onto function m * i.e. arg_count=2;m=ADD;args=1,2,3,4,5,6,7... * results in ADD(1,2) ADD(3,4) ADD(5,6) and so on @@ -187,24 +145,24 @@ /* implements MAP(1, m, ...) */ #define _META_MAP_1(m, arg1, ...)\ m(arg1)\ - _META_MAP_BODY(1, m, __VA_ARGS__) + _META_DEFER_2(_META_MAP_BODY_TMP)()(1, m, __VA_ARGS__) /* implements MAP(2, m, ...) */ #define _META_MAP_2(m, arg1, arg2, ...)\ m(arg1, arg2)\ - _META_MAP_BODY(2, m, __VA_ARGS__) + _META_DEFER_2(_META_MAP_BODY_TMP)()(2, m, __VA_ARGS__) /* implements MAP(3, m, ...) */ #define _META_MAP_3(m, arg1, arg2, arg3, ...)\ m(arg1, arg2, arg3)\ - _META_MAP_BODY(3, m, __VA_ARGS__) + _META_DEFER_2(_META_MAP_BODY_TMP)()(3, m, __VA_ARGS__) /* used by macro MAP, don't use on its own */ #define _META_MAP_BODY(arg_count, m, ...)\ META_IF_ELSE(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__))(\ - _META_DEFER_2(_META_MAP)()\ - (arg_count, m, __VA_ARGS__)\ + META_CONCAT(_META_MAP_, arg_count)(m, __VA_ARGS__) \ )() +#define _META_MAP_BODY_TMP() _META_MAP_BODY /* map aggregator and every group of arg_count arguments onto function m * i.e. aggr=x;arg_count=1;m=ADD;args=1,2,3,4,5,6,7... @@ -228,12 +186,6 @@ (arg_count, m, aggr, __VA_ARGS__)\ )(aggr) -/* META_CONCAT with parametrised delimeter between concatenised tokens - * META_CONCAT_SEQ_DELIM_(A,B,C,D) tokenizes as A_B_C_D - */ -#define _META_CONCAT_DELIM(delim, x, y) META_CONCAT(META_CONCAT(x, delim),y) -#define _META_CONCAT_DELIM_(x, y) _META_CONCAT_DELIM(_, x, y) - /* UNUSED private macros */ #define _META_VOID(x) (void)(x) #define _META_VOID2(x, y) x; _META_VOID(y) diff --git a/posix/include/sof/trace/preproc.h b/posix/include/sof/trace/preproc.h new file mode 100644 index 000000000000..88e4986ea240 --- /dev/null +++ b/posix/include/sof/trace/preproc.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Michal Jerzy Wierzbicki + */ + +#ifndef __SOF_TRACE_PREPROC_H__ +#define __SOF_TRACE_PREPROC_H__ + +/* Macros in this file are to be invoked directly from code. + * In order to work, they require a number of other macros that are + * defined in the header file specified below. + * Macros from the file specified below are not to meant to be used + * directly / independently. + * For more detailed commentary of innards of macros in this file, + * see file specified below. + */ +#include +#include + +/* count number of var args - during preprocesing + * works for predefined number of args + * META_COUNT_VARAGS_BEFORE_COMPILE(A,B,C,D) evaluates to 4 + */ +#define META_COUNT_VARAGS_BEFORE_COMPILE(...)\ + META_DEC(\ + _META_PP_NARG_BEFORE_COMPILE_(\ + _, ##__VA_ARGS__, _META_PP_RSEQ_N()\ + )\ + ) + +/* treat x as string while forcing x expansion beforehand */ +#define META_QUOTE(x) _META_QUOTE(x) + +/* concat x and y while forcing x and y expansion beforehand */ +#define META_CONCAT(x, y) _META_CONCAT_BASE(x, y) + +/* Only META_NOT(0) evaulates to 1 + * notice, that any x!=0 would also result in 0 + * e.x. META_NOT(123) evaluates to 0 + */ +#define META_NOT(x) _META_IS_PROBE(META_CONCAT(_META_NOT_, x)) +/* hacky way to convert tokens into 0 1*/ +#define META_BOOL(x) META_NOT(META_NOT(x)) + +/* META_IF_ELSE(X)(a)(b) expands to + * b for X == 0 + * a for X != 0 + */ +#define META_IF_ELSE(condition) _META_IF_ELSE(META_BOOL(condition)) + +/* same story with indirection as META_IF_ELSE */ +#define META_IF(condition) _META_IIF(META_BOOL(condition)) + +/* primitive recursion + * default depth is 8 + */ +#define META_RECURSE(...) _META_REQRS_8(__VA_ARGS__) + +/* The only sane way I found to increment values in cpreproc */ +#define META_INC(x) META_CONCAT(_META_INC_, x) + +/* The only sane way I found to decrement values in cpreproc */ +#define META_DEC(x) META_CONCAT(_META_DEC_, x) + +/* map every group of arg_count arguments onto function m + * i.e. arg_count=2;m=ADD;args=1,2,3,4,5,6,7... + * results in ADD(1,2) ADD(3,4) ADD(5,6) and so on + * MAP##N must exist for arg_count == N to work + */ +#define META_MAP(arg_count, m, ...) META_RECURSE(\ + _META_MAP_BODY(arg_count, m, __VA_ARGS__)) + +/* map aggregator and every group of arg_count arguments onto function m + * i.e. aggr=x;arg_count=1;m=ADD;args=1,2,3,4,5,6,7... + * results in x = ... ADD(7,ADD(6,ADD(5,ADD(4,ADD(3,ADD(2,ADD(1,x))))))) ... + * MAP##N must exist for arg_count == N to work + */ +#define META_MAP_AGGREGATE(arg_count, m, aggr, ...)\ + META_CONCAT(_META_MAP_AGGREGATE_, arg_count)(m, aggr, __VA_ARGS__) + +/* counteract compiler warning about unused variables */ +#define SOF_TRACE_UNUSED(arg1, ...) do { META_RECURSE( \ + META_MAP_AGGREGATE(1, _META_VOID2, _META_VOID(arg1), __VA_ARGS__)); \ + } while (0) + +#endif /* __SOF_TRACE_PREPROC_H__ */ diff --git a/rimage/CMakeLists.txt b/rimage/CMakeLists.txt deleted file mode 100644 index dc5d3ac794f8..000000000000 --- a/rimage/CMakeLists.txt +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.10) - -project(SOF_RIMAGE C) - -set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}/..") - -if(NOT DEFINED VERSION_H_PATH) - message(FATAL_ERROR - " Please specify version.h path.\n" - " Example: cmake -DVERSION_H_PATH=${VERSION_H_PATH} ...\n" -) -endif() - -if(NOT DEFINED PEM_KEY_PREFIX) - set(PEM_KEY_PREFIX "/usr/local/share/rimage") -endif() - -get_filename_component(VERSION_H_DIRECTORY ${VERSION_H_PATH} DIRECTORY) - -add_executable(rimage - file_simple.c - man_apl.c - man_cnl.c - man_kbl.c - man_sue.c - man_tgl.c - cse.c - css.c - plat_auth.c - hash.c - pkcs1_5.c - manifest.c - elf.c - rimage.c -) - -target_compile_options(rimage PRIVATE - -O2 -g -Wall -Werror -Wl,-EL -Wmissing-prototypes -Wimplicit-fallthrough=3 -) - -target_compile_definitions(rimage PRIVATE - PEM_KEY_PREFIX="${PEM_KEY_PREFIX}" -) - -target_link_libraries(rimage PRIVATE "-lcrypto") - -target_include_directories(rimage PRIVATE - "${SOF_ROOT_SOURCE_DIRECTORY}/src/include" - "${VERSION_H_DIRECTORY}" -) diff --git a/rimage/cse.c b/rimage/cse.c deleted file mode 100644 index f3bea3826ae7..000000000000 --- a/rimage/cse.c +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie - -#include -#include "rimage.h" -#include "cse.h" -#include "manifest.h" - -void ri_cse_create(struct image *image) -{ - struct CsePartitionDirHeader *cse_hdr = image->fw_image; - struct sof_man_adsp_meta_file_ext_v1_8 *meta = image->fw_image + - MAN_META_EXT_OFFSET_V1_8; - struct CsePartitionDirEntry *cse_entry = - image->fw_image + sizeof(*cse_hdr); - uint8_t csum = 0, *val = image->fw_image; - int i, size; - - fprintf(stdout, " cse: completing CSE V1.8 manifest\n"); - - cse_entry[2].length = meta->comp_desc[0].limit_offset - - MAN_DESC_OFFSET_V1_8; - - /* calculate checksum using BSD algo */ - size = sizeof(*cse_hdr) + sizeof(*cse_entry) * MAN_CSE_PARTS; - for (i = 0; i < size; i++) { - if (i == 11) - continue; - csum += val[i]; - } - cse_hdr->checksum = 0x100 - csum; -} diff --git a/rimage/cse.h b/rimage/cse.h deleted file mode 100644 index d262fbafd481..000000000000 --- a/rimage/cse.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - */ - -#ifndef __CSE_H__ -#define __CSE_H__ - -#include - -struct image; - -#define CSE_HEADER_MAKER 0x44504324 /* "DPC$" */ - -struct CsePartitionDirHeader { - uint32_t header_marker; - uint32_t nb_entries; - uint8_t header_version; - uint8_t entry_version; - uint8_t header_length; - uint8_t checksum; - uint8_t partition_name[4]; -} __attribute__((packed)); - -struct CsePartitionDirEntry { - uint8_t entry_name[12]; - uint32_t offset; - uint32_t length; - uint32_t reserved; -} __attribute__((packed)); - -void ri_cse_create(struct image *image); - -#endif diff --git a/rimage/css.c b/rimage/css.c deleted file mode 100644 index 1e9de6d8bc86..000000000000 --- a/rimage/css.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie - -#include -#include -#include "rimage.h" -#include "css.h" -#include "manifest.h" - -void ri_css_v1_8_hdr_create(struct image *image) -{ - struct css_header_v1_8 *css = image->fw_image + MAN_CSS_HDR_OFFSET; - struct tm *date; - struct timeval tv; - time_t seconds; - int val; - - fprintf(stdout, " cse: completing CSS manifest\n"); - - /* get local time and date */ - gettimeofday(&tv, NULL); - seconds = tv.tv_sec; - date = localtime(&seconds); - - if (!date) { - fprintf(stderr, "error: cant get localtime %d\n", -errno); - return; - } - - date->tm_year += 1900; - fprintf(stdout, " css: set build date to %d:%2.2d:%2.2d\n", - date->tm_year, date->tm_mon, date->tm_mday); - - /* year yYyy */ - val = date->tm_year / 1000; - css->date |= val << 28; - date->tm_year -= val * 1000; - /* year yyYy */ - val = date->tm_year / 100; - css->date |= val << 24; - date->tm_year -= val * 100; - /* year yyyY */ - val = date->tm_year / 10; - css->date |= val << 20; - date->tm_year -= val * 10; - /* year Yyyy */ - val = date->tm_year; - css->date |= val << 16; - - /* month Mm - for some reason month starts at 0 */ - val = ++date->tm_mon / 10; - css->date |= val << 12; - date->tm_mon -= (val * 10); - /* month mM */ - val = date->tm_mon; - css->date |= val << 8; - - /* Day Dd */ - val = date->tm_mday / 10; - css->date |= val << 4; - date->tm_mday -= (val * 10); - /* Day dD */ - val = date->tm_mday; - css->date |= val << 0; -} - -void ri_css_v1_5_hdr_create(struct image *image) -{ - struct css_header_v1_5 *css = image->fw_image; - struct tm *date; - struct timeval tv; - time_t seconds; - int val; - - fprintf(stdout, " cse: completing CSS manifest\n"); - - /* get local time and date */ - gettimeofday(&tv, NULL); - seconds = tv.tv_sec; - date = localtime(&seconds); - - if (!date) { - fprintf(stderr, "error: cant get localtime %d\n", -errno); - return; - } - - date->tm_year += 1900; - fprintf(stdout, " css: set build date to %d:%2.2d:%2.2d\n", - date->tm_year, date->tm_mon, date->tm_mday); - - /* year yYyy */ - val = date->tm_year / 1000; - css->date |= val << 28; - date->tm_year -= val * 1000; - /* year yyYy */ - val = date->tm_year / 100; - css->date |= val << 24; - date->tm_year -= val * 100; - /* year yyyY */ - val = date->tm_year / 10; - css->date |= val << 20; - date->tm_year -= val * 10; - /* year Yyyy */ - val = date->tm_year; - css->date |= val << 16; - - /* month Mm - for some reason month starts at 0 */ - val = ++date->tm_mon / 10; - css->date |= val << 12; - date->tm_mon -= (val * 10); - /* month mM */ - val = date->tm_mon; - css->date |= val << 8; - - /* Day Dd */ - val = date->tm_mday / 10; - css->date |= val << 4; - date->tm_mday -= (val * 10); - /* Day dD */ - val = date->tm_mday; - css->date |= val << 0; -} diff --git a/rimage/css.h b/rimage/css.h deleted file mode 100644 index e322cbf68dfc..000000000000 --- a/rimage/css.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - */ - -#ifndef __CSS_H__ -#define __CSS_H__ - -#include - -struct image; - -#define MAN_CSS_LT_MODULE_TYPE 0x00000006 -#define MAN_CSS_MOD_TYPE 4 -#define MAN_CSS_HDR_SIZE 161 /* in words */ -#define MAN_CSS_HDR_VERSION 0x10000 -#define MAN_CSS_MOD_VENDOR 0x8086 -#define MAN_CSS_HDR_ID {'$', 'M', 'N', '2'} - -#define MAN_CSS_KEY_SIZE (MAN_RSA_KEY_MODULUS_LEN >> 2) -#define MAN_CSS_MOD_SIZE (MAN_RSA_KEY_MODULUS_LEN >> 2) -#define MAN_CSS_EXP_SIZE (MAN_RSA_KEY_EXPONENT_LEN >> 2) -#define MAN_CSS_MAN_SIZE_V1_8 \ - (sizeof(struct fw_image_manifest_v1_8) >> 2) -#define MAN_CSS_MAN_SIZE_V1_5 \ - (sizeof(struct fw_image_manifest_v1_5) >> 2) - -/* - * RSA Key and Crypto - */ -#define MAN_RSA_KEY_MODULUS_LEN 256 -#define MAN_RSA_KEY_EXPONENT_LEN 4 -#define MAN_RSA_SIGNATURE_LEN 256 - -struct fw_version { - uint16_t major_version; - uint16_t minor_version; - uint16_t hotfix_version; - uint16_t build_version; -} __attribute__((packed)); - -struct css_header_v1_8 { - uint32_t header_type; - uint32_t header_len; - uint32_t header_version; - uint32_t reserved0; /* must be 0x0 */ - uint32_t module_vendor; - uint32_t date; - uint32_t size; - uint8_t header_id[4]; - uint32_t padding; /* must be 0x0 */ - struct fw_version version; - uint32_t svn; - uint32_t reserved1[18]; /* must be 0x0 */ - uint32_t modulus_size; - uint32_t exponent_size; - uint8_t modulus[MAN_RSA_KEY_MODULUS_LEN]; - uint8_t exponent[MAN_RSA_KEY_EXPONENT_LEN]; - uint8_t signature[MAN_RSA_SIGNATURE_LEN]; -} __attribute__((packed)); - -struct css_header_v1_5 { - uint32_t module_type; - uint32_t header_len; - uint32_t header_version; - uint32_t reserved0; /* must be 0x0 */ - uint32_t module_vendor; - uint32_t date; - uint32_t size; - uint32_t key_size; - uint32_t modulus_size; - uint32_t exponent_size; - uint32_t reserved[22]; - uint8_t modulus[MAN_RSA_KEY_MODULUS_LEN]; - uint8_t exponent[MAN_RSA_KEY_EXPONENT_LEN]; - uint8_t signature[MAN_RSA_SIGNATURE_LEN]; -} __attribute__((packed)); - -void ri_css_v1_8_hdr_create(struct image *image); -void ri_css_v1_5_hdr_create(struct image *image); - -#endif diff --git a/rimage/elf.c b/rimage/elf.c deleted file mode 100644 index 1b5420439da7..000000000000 --- a/rimage/elf.c +++ /dev/null @@ -1,645 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie - -#include -#include -#include "rimage.h" -#include "cse.h" -#include "manifest.h" - -static int elf_read_sections(struct image *image, struct module *module, - int module_index) -{ - Elf32_Ehdr *hdr = &module->hdr; - Elf32_Shdr *section = module->section; - size_t count; - int i, ret; - uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); - - /* read in section header */ - ret = fseek(module->fd, hdr->shoff, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: can't seek to %s section header %d\n", - module->elf_file, ret); - return ret; - } - - /* allocate space for each section header */ - section = calloc(sizeof(Elf32_Shdr), hdr->shnum); - if (!section) - return -ENOMEM; - module->section = section; - - /* read in sections */ - count = fread(section, sizeof(Elf32_Shdr), hdr->shnum, module->fd); - if (count != hdr->shnum) { - fprintf(stderr, "error: failed to read %s section header %d\n", - module->elf_file, -errno); - return -errno; - } - - /* read in strings */ - module->strings = calloc(1, section[hdr->shstrndx].size); - if (!module->strings) { - fprintf(stderr, "error: failed %s to read ELF strings for %d\n", - module->elf_file, -errno); - return -errno; - } - - ret = fseek(module->fd, section[hdr->shstrndx].off, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: can't seek to %s stringss %d\n", - module->elf_file, ret); - return ret; - } - - count = fread(module->strings, 1, section[hdr->shstrndx].size, - module->fd); - if (count != section[hdr->shstrndx].size) { - fprintf(stderr, "error: failed to read %s strings %d\n", - module->elf_file, -errno); - return -errno; - } - - if (image->num_modules > 1 && module_index == 0) { - /* In case of multiple modules first one should be bootloader, - * that should not have these sections. - */ - fprintf(stdout, "info: ignore .bss" - " section for bootloader module\n"); - - module->bss_start = 0; - module->bss_end = 0; - - fprintf(stdout, "info: ignore .static_log_entries" - " section for bootloader module\n"); - - module->logs_index = -EINVAL; - - fprintf(stdout, "info: ignore .static_uuids section for bootloader module\n"); - module->uids_index = -EINVAL; - - fprintf(stdout, "info: ignore .fw_ready" - " section for bootloader module\n"); - - module->fw_ready_index = -EINVAL; - } else { - /* find manifest module data */ - module->bss_index = elf_find_section(image, module, ".bss"); - if (module->bss_index < 0) - return module->bss_index; - - /* find log entries and fw ready sections */ - module->logs_index = elf_find_section(image, module, - ".static_log_entries"); - - module->uids_index = elf_find_section(image, module, - ".static_uuid_entries"); - - module->fw_ready_index = elf_find_section(image, module, - ".fw_ready"); - if (module->fw_ready_index < 0) - return module->fw_ready_index; - } - - /* parse each section */ - for (i = 0; i < hdr->shnum; i++) { - /* only write valid sections */ - if (!(section[i].flags & valid)) - continue; - - switch (section[i].type) { - case SHT_NOBITS: - /* bss */ - module->bss_size += section[i].size; - module->num_bss++; - break; - case SHT_PROGBITS: - /* text or data */ - module->fw_size += section[i].size; - - if (section[i].flags & SHF_EXECINSTR) - module->text_size += section[i].size; - else - module->data_size += section[i].size; - break; - default: - continue; - } - - module->num_sections++; - - if (!image->verbose) - continue; - - fprintf(stdout, " %s section-%d: \ttype\t 0x%8.8x\n", - module->elf_file, i, section[i].type); - fprintf(stdout, " %s section-%d: \tflags\t 0x%8.8x\n", - module->elf_file, i, section[i].flags); - fprintf(stdout, " %s section-%d: \taddr\t 0x%8.8x\n", - module->elf_file, i, section[i].vaddr); - fprintf(stdout, " %s section-%d: \toffset\t 0x%8.8x\n", - module->elf_file, i, section[i].off); - fprintf(stdout, " %s section-%d: \tsize\t 0x%8.8x\n", - module->elf_file, i, section[i].size); - fprintf(stdout, " %s section-%d: \tlink\t 0x%8.8x\n", - module->elf_file, i, section[i].link); - fprintf(stdout, " %s section-%d: \tinfo\t 0x%8.8x\n\n", - module->elf_file, i, section[i].info); - } - - return 0; -} - -static int elf_read_programs(struct image *image, struct module *module) -{ - Elf32_Ehdr *hdr = &module->hdr; - Elf32_Phdr *prg = module->prg; - size_t count; - int i, ret; - - /* read in program header */ - ret = fseek(module->fd, hdr->phoff, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: cant seek to %s program header %d\n", - module->elf_file, ret); - return ret; - } - - /* allocate space for programs */ - prg = calloc(sizeof(Elf32_Phdr), hdr->phnum); - if (!prg) - return -ENOMEM; - module->prg = prg; - - /* read in programs */ - count = fread(prg, sizeof(Elf32_Phdr), hdr->phnum, module->fd); - if (count != hdr->phnum) { - fprintf(stderr, "error: failed to read %s program header %d\n", - module->elf_file, -errno); - return -errno; - } - - /* check each program */ - for (i = 0; i < hdr->phnum; i++) { - if (prg[i].filesz == 0) - continue; - - if (!image->verbose) - continue; - - fprintf(stdout, "%s program-%d: \ttype\t 0x%8.8x\n", - module->elf_file, i, prg[i].type); - fprintf(stdout, "%s program-%d: \toffset\t 0x%8.8x\n", - module->elf_file, i, prg[i].off); - fprintf(stdout, "%s program-%d: \tvaddr\t 0x%8.8x\n", - module->elf_file, i, prg[i].vaddr); - fprintf(stdout, "%s program-%d: \tpaddr\t 0x%8.8x\n", - module->elf_file, i, prg[i].paddr); - fprintf(stdout, "%s program-%d: \tfsize\t 0x%8.8x\n", - module->elf_file, i, prg[i].filesz); - fprintf(stdout, "%s program-%d: \tmsize\t 0x%8.8x\n", - module->elf_file, i, prg[i].memsz); - fprintf(stdout, "%s program-%d: \tflags\t 0x%8.8x\n\n", - module->elf_file, i, prg[i].flags); - } - - return 0; -} - -static int elf_read_hdr(struct image *image, struct module *module) -{ - Elf32_Ehdr *hdr = &module->hdr; - size_t count; - - /* read in elf header */ - count = fread(hdr, sizeof(*hdr), 1, module->fd); - if (count != 1) { - fprintf(stderr, "error: failed to read %s elf header %d\n", - module->elf_file, -errno); - return -errno; - } - - if (!image->verbose) - return 0; - - fprintf(stdout, "%s elf: \tentry point\t 0x%8.8x\n", - module->elf_file, hdr->entry); - fprintf(stdout, "%s elf: \tprogram offset\t 0x%8.8x\n", - module->elf_file, hdr->phoff); - fprintf(stdout, "%s elf: \tsection offset\t 0x%8.8x\n", - module->elf_file, hdr->shoff); - fprintf(stdout, "%s elf: \tprogram size\t 0x%8.8x\n", - module->elf_file, hdr->phentsize); - fprintf(stdout, "%s elf: \tprogram count\t 0x%8.8x\n", - module->elf_file, hdr->phnum); - fprintf(stdout, "%s elf: \tsection size\t 0x%8.8x\n", - module->elf_file, hdr->shentsize); - fprintf(stdout, "%s elf: \tsection count\t 0x%8.8x\n", - module->elf_file, hdr->shnum); - fprintf(stdout, "%s elf: \tstring index\t 0x%8.8x\n\n", - module->elf_file, hdr->shstrndx); - - return 0; -} - -int elf_is_rom(struct image *image, Elf32_Shdr *section) -{ - uint32_t start, end; - uint32_t base, size; - - start = section->vaddr; - end = section->vaddr + section->size; - - base = image->adsp->mem_zones[SOF_FW_BLK_TYPE_ROM].base; - size = image->adsp->mem_zones[SOF_FW_BLK_TYPE_ROM].size; - - if (start < base || start > base + size) - return 0; - if (end < base || end > base + size) - return 0; - return 1; -} - -static void elf_module_size(struct image *image, struct module *module, - Elf32_Shdr *section, int index) -{ - switch (section->type) { - case SHT_PROGBITS: - /* text or data */ - if (section->flags & SHF_EXECINSTR) { - /* text */ - if (module->text_start > section->vaddr) - module->text_start = section->vaddr; - if (module->text_end < section->vaddr + section->size) - module->text_end = section->vaddr + - section->size; - - fprintf(stdout, "\tTEXT\t"); - } else { - /* initialized data, also calc the writable sections */ - if (module->data_start > section->vaddr) - module->data_start = section->vaddr; - if (module->data_end < section->vaddr + section->size) - module->data_end = section->vaddr + - section->size; - - fprintf(stdout, "\tDATA\t"); - } - break; - case SHT_NOBITS: - /* bss */ - if (index == module->bss_index) { - /* updated the .bss segment */ - module->bss_start = section->vaddr; - module->bss_end = section->vaddr + section->size; - fprintf(stdout, "\tBSS\t"); - } else { - fprintf(stdout, "\tHEAP\t"); - } - break; - case SHT_NOTE: - fprintf(stdout, "\tNOTE\t"); - break; - default: - break; - } -} - -static void elf_module_size_reloc(struct image *image, struct module *module, - Elf32_Shdr *section, int index) -{ - switch (section->type) { - case SHT_PROGBITS: - /* text or data */ - if (section->flags & SHF_EXECINSTR) { - /* text */ - module->text_start = 0; - module->text_end += section->size; - - fprintf(stdout, "\tTEXT\t"); - } else { - /* initialized data, also calc the writable sections */ - module->data_start = 0; - module->data_end += section->size; - - fprintf(stdout, "\tDATA\t"); - } - break; - case SHT_NOBITS: - /* bss */ - if (index == module->bss_index) { - /* updated the .bss segment */ - module->bss_start = section->vaddr; - module->bss_end = section->vaddr + section->size; - fprintf(stdout, "\tBSS\t"); - } else { - fprintf(stdout, "\tHEAP\t"); - } - break; - default: - break; - } -} - -static void elf_module_limits(struct image *image, struct module *module) -{ - Elf32_Shdr *section; - uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); - int i; - - module->text_start = 0xffffffff; - module->data_start = 0xffffffff; - module->bss_start = 0; - module->text_end = 0; - module->data_end = 0; - module->bss_end = 0; - - fprintf(stdout, " Found %d sections, listing valid sections......\n", - module->hdr.shnum); - - fprintf(stdout, "\tNo\tStart\t\tEnd\t\tSize\tType\tName\n"); - - /* iterate all sections and get size of segments */ - for (i = 0; i < module->hdr.shnum; i++) { - section = &module->section[i]; - - /* module bss can sometimes be missed */ - if (i != module->bss_index && i != module->logs_index && - i != module->fw_ready_index) { - /* only check valid sections */ - if (!(section->flags & valid)) - continue; - - if (section->size == 0) - continue; - - if (elf_is_rom(image, section)) - continue; - } - - fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%x", i, - section->vaddr, section->vaddr + section->size, - section->size); - - /* text or data section */ - if (image->reloc) - elf_module_size_reloc(image, module, section, i); - else - elf_module_size(image, module, section, i); - - /* section name */ - fprintf(stdout, "%s\n", module->strings + section->name); - } - - fprintf(stdout, "\n"); -} - -/* make sure no section overlap from any modules */ -int elf_validate_section(struct image *image, struct module *module, - Elf32_Shdr *section, int index) -{ - struct module *m; - Elf32_Shdr *s; - uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); - int i, j; - - /* for each module */ - for (i = 0; i < image->num_modules; i++) { - m = &image->module[i]; - - /* for each section */ - for (j = 0; j < m->hdr.shnum; j++) { - s = &m->section[j]; - - if (s == section) - continue; - - /* only check valid sections */ - if (!(s->flags & valid)) - continue; - - if (s->size == 0) - continue; - - /* is section start non overlapping ? */ - if (section->vaddr >= s->vaddr && - section->vaddr < - s->vaddr + s->size) { - goto err; - } - - /* is section end non overlapping ? */ - if (section->vaddr + section->size > s->vaddr && - section->vaddr + section->size <= - s->vaddr + s->size) { - goto err; - } - } - } - - return 0; - -err: - fprintf(stderr, "error: section overlap between %s:%d and %s:%d\n", - module->elf_file, index, m->elf_file, j); - fprintf(stderr, " [0x%x : 0x%x] overlaps with [0x%x :0x%x]\n", - section->vaddr, section->vaddr + section->size, - s->vaddr, s->vaddr + s->size); - return -EINVAL; -} - -/* make sure no section overlaps from any modules */ -int elf_validate_modules(struct image *image) -{ - struct module *module; - Elf32_Shdr *section; - uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); - int i, j, ret; - - /* relocatable modules have no physical addresses until runtime */ - if (image->reloc) - return 0; - - /* for each module */ - for (i = 0; i < image->num_modules; i++) { - module = &image->module[i]; - - /* for each section */ - for (j = 0; j < module->hdr.shnum; j++) { - section = &module->section[j]; - - /* only check valid sections */ - if (!(section->flags & valid)) - continue; - - if (section->size == 0) - continue; - - /* is section non overlapping ? */ - ret = elf_validate_section(image, module, section, j); - if (ret < 0) - return ret; - } - } - - return 0; -} - -int elf_find_section(struct image *image, struct module *module, - const char *name) -{ - Elf32_Ehdr *hdr = &module->hdr; - Elf32_Shdr *section, *s; - char *buffer; - size_t count; - int ret, i; - - section = &module->section[hdr->shstrndx]; - - /* alloc data data */ - buffer = calloc(1, section->size); - if (!buffer) - return -ENOMEM; - - /* read in section string data */ - ret = fseek(module->fd, section->off, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: cant seek to string section %d\n", ret); - goto out; - } - - count = fread(buffer, 1, section->size, module->fd); - if (count != section->size) { - fprintf(stderr, "error: can't read string section %d\n", - -errno); - ret = -errno; - goto out; - } - - /* find section with name */ - for (i = 0; i < hdr->shnum; i++) { - s = &module->section[i]; - if (!strcmp(name, buffer + s->name)) { - ret = i; - goto out; - } - } - - fprintf(stderr, "warning: can't find section %s in module %s\n", name, - module->elf_file); - ret = -EINVAL; - -out: - free(buffer); - return ret; -} - -int elf_parse_module(struct image *image, int module_index, const char *name) -{ - struct module *module; - uint32_t rem; - int ret = 0; - - /* validate module index */ - if (module_index >= MAX_MODULES) { - fprintf(stderr, "error: too any modules\n"); - return -EINVAL; - } - - module = &image->module[module_index]; - - /* open the elf input file */ - module->fd = fopen(name, "rb"); - if (!module->fd) { - fprintf(stderr, "error: unable to open %s for reading %d\n", - name, errno); - return -EINVAL; - } - module->elf_file = name; - - /* get file size */ - ret = fseek(module->fd, 0, SEEK_END); - if (ret < 0) - goto hdr_err; - module->file_size = ftell(module->fd); - ret = fseek(module->fd, 0, SEEK_SET); - if (ret < 0) - goto hdr_err; - - /* read in elf header */ - ret = elf_read_hdr(image, module); - if (ret < 0) - goto hdr_err; - - /* read in programs */ - ret = elf_read_programs(image, module); - if (ret < 0) { - fprintf(stderr, "error: failed to read program sections %d\n", - ret); - goto hdr_err; - } - - /* read sections */ - ret = elf_read_sections(image, module, module_index); - if (ret < 0) { - fprintf(stderr, "error: failed to read base sections %d\n", - ret); - goto sec_err; - } - - /* check limits */ - elf_module_limits(image, module); - - elf_find_section(image, module, ""); - - fprintf(stdout, " module: input size %d (0x%x) bytes %d sections\n", - module->fw_size, module->fw_size, module->num_sections); - fprintf(stdout, " module: text %d (0x%x) bytes\n" - " data %d (0x%x) bytes\n" - " bss %d (0x%x) bytes\n\n", - module->text_size, module->text_size, - module->data_size, module->data_size, - module->bss_size, module->bss_size); - - /* file sizes round up to nearest page */ - module->text_file_size = module->text_end - module->text_start; - rem = module->text_file_size % MAN_PAGE_SIZE; - if (rem) - module->text_file_size += MAN_PAGE_SIZE - rem; - - /* data section */ - module->data_file_size = module->data_end - module->data_start; - rem = module->data_file_size % MAN_PAGE_SIZE; - if (rem) - module->data_file_size += MAN_PAGE_SIZE - rem; - - /* bss section */ - module->bss_file_size = module->bss_end - module->bss_start; - rem = module->bss_file_size % MAN_PAGE_SIZE; - if (rem) - module->bss_file_size += MAN_PAGE_SIZE - rem; - - return 0; - -sec_err: - free(module->prg); -hdr_err: - fclose(module->fd); - - return ret; -} - -void elf_free_module(struct image *image, int module_index) -{ - struct module *module = &image->module[module_index]; - - free(module->prg); - free(module->section); - free(module->strings); - fclose(module->fd); -} diff --git a/rimage/elf.h b/rimage/elf.h deleted file mode 100644 index a9a6505e7793..000000000000 --- a/rimage/elf.h +++ /dev/null @@ -1,931 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. - * Copyright (c) 2001 David E. O'Brien - * Portions Copyright 2009 The Go Authors. All rights reserved. - */ - -/* - * ELF definitions that are independent of architecture or word size. - */ - -/* - * Note header. The ".note" section contains an array of notes. Each - * begins with this header, aligned to a word boundary. Immediately - * following the note header is n_namesz bytes of name, padded to the - * next word boundary. Then comes n_descsz bytes of descriptor, again - * padded to a word boundary. The values of n_namesz and n_descsz do - * not include the padding. - */ - -#include - -typedef uint64_t uint64; -typedef uint32_t uint32; -typedef uint16_t uint16; -typedef uint8_t uint8; - -typedef int64_t int64; -typedef int32_t int32; -typedef int16_t int16; -typedef int8_t int8; - - -typedef struct { - uint32 n_namesz; /* Length of name. */ - uint32 n_descsz; /* Length of descriptor. */ - uint32 n_type; /* Type of this note. */ -} Elf_Note; - -/* Indexes into the e_ident array. Keep synced with - http://www.sco.com/developer/gabi/ch4.eheader.html */ -#define EI_MAG0 0 /* Magic number, byte 0. */ -#define EI_MAG1 1 /* Magic number, byte 1. */ -#define EI_MAG2 2 /* Magic number, byte 2. */ -#define EI_MAG3 3 /* Magic number, byte 3. */ -#define EI_CLASS 4 /* Class of machine. */ -#define EI_DATA 5 /* Data format. */ -#define EI_VERSION 6 /* ELF format version. */ -#define EI_OSABI 7 /* Operating system / ABI identification */ -#define EI_ABIVERSION 8 /* ABI version */ -#define OLD_EI_BRAND 8 /* Start of architecture identification. */ -#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ -#define EI_NIDENT 16 /* Size of e_ident array. */ - -/* Values for the magic number bytes. */ -#define ELFMAG0 0x7f -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" /* magic string */ -#define SELFMAG 4 /* magic string size */ - -/* Values for e_ident[EI_VERSION] and e_version. */ -#define EV_NONE 0 -#define EV_CURRENT 1 - -/* Values for e_ident[EI_CLASS]. */ -#define ELFCLASSNONE 0 /* Unknown class. */ -#define ELFCLASS32 1 /* 32-bit architecture. */ -#define ELFCLASS64 2 /* 64-bit architecture. */ - -/* Values for e_ident[EI_DATA]. */ -#define ELFDATANONE 0 /* Unknown data format. */ -#define ELFDATA2LSB 1 /* 2's complement little-endian. */ -#define ELFDATA2MSB 2 /* 2's complement big-endian. */ - -/* Values for e_ident[EI_OSABI]. */ -#define ELFOSABI_NONE 0 /* UNIX System V ABI */ -#define ELFOSABI_HPUX 1 /* HP-UX operating system */ -#define ELFOSABI_NETBSD 2 /* NetBSD */ -#define ELFOSABI_LINUX 3 /* GNU/Linux */ -#define ELFOSABI_HURD 4 /* GNU/Hurd */ -#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ -#define ELFOSABI_SOLARIS 6 /* Solaris */ -#define ELFOSABI_AIX 7 /* AIX */ -#define ELFOSABI_IRIX 8 /* IRIX */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD */ -#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD */ -#define ELFOSABI_OPENVMS 13 /* Open VMS */ -#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ -#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ - -/* e_ident */ -#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ - (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ - (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ - (ehdr).e_ident[EI_MAG3] == ELFMAG3) - -/* Values for e_type. */ -#define ET_NONE 0 /* Unknown type. */ -#define ET_REL 1 /* Relocatable. */ -#define ET_EXEC 2 /* Executable. */ -#define ET_DYN 3 /* Shared object. */ -#define ET_CORE 4 /* Core file. */ -#define ET_LOOS 0xfe00 /* First operating system specific. */ -#define ET_HIOS 0xfeff /* Last operating system-specific. */ -#define ET_LOPROC 0xff00 /* First processor-specific. */ -#define ET_HIPROC 0xffff /* Last processor-specific. */ - -/* Values for e_machine. */ -#define EM_NONE 0 /* Unknown machine. */ -#define EM_M32 1 /* AT&T WE32100. */ -#define EM_SPARC 2 /* Sun SPARC. */ -#define EM_386 3 /* Intel i386. */ -#define EM_68K 4 /* Motorola 68000. */ -#define EM_88K 5 /* Motorola 88000. */ -#define EM_860 7 /* Intel i860. */ -#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ -#define EM_S370 9 /* IBM System/370. */ -#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ -#define EM_PARISC 15 /* HP PA-RISC. */ -#define EM_VPP500 17 /* Fujitsu VPP500. */ -#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ -#define EM_960 19 /* Intel 80960. */ -#define EM_PPC 20 /* PowerPC 32-bit. */ -#define EM_PPC64 21 /* PowerPC 64-bit. */ -#define EM_S390 22 /* IBM System/390. */ -#define EM_V800 36 /* NEC V800. */ -#define EM_FR20 37 /* Fujitsu FR20. */ -#define EM_RH32 38 /* TRW RH-32. */ -#define EM_RCE 39 /* Motorola RCE. */ -#define EM_ARM 40 /* ARM. */ -#define EM_SH 42 /* Hitachi SH. */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ -#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ -#define EM_ARC 45 /* Argonaut RISC Core. */ -#define EM_H8_300 46 /* Hitachi H8/300. */ -#define EM_H8_300H 47 /* Hitachi H8/300H. */ -#define EM_H8S 48 /* Hitachi H8S. */ -#define EM_H8_500 49 /* Hitachi H8/500. */ -#define EM_IA_64 50 /* Intel IA-64 Processor. */ -#define EM_MIPS_X 51 /* Stanford MIPS-X. */ -#define EM_COLDFIRE 52 /* Motorola ColdFire. */ -#define EM_68HC12 53 /* Motorola M68HC12. */ -#define EM_MMA 54 /* Fujitsu MMA. */ -#define EM_PCP 55 /* Siemens PCP. */ -#define EM_NCPU 56 /* Sony nCPU. */ -#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ -#define EM_STARCORE 58 /* Motorola Star*Core processor. */ -#define EM_ME16 59 /* Toyota ME16 processor. */ -#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ -#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ -#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ - -/* Non-standard or deprecated. */ -#define EM_486 6 /* Intel i486. */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ -#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ -#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ - -/* Special section indexes. */ -#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ -#define SHN_LORESERVE 0xff00 /* First of reserved range. */ -#define SHN_LOPROC 0xff00 /* First processor-specific. */ -#define SHN_HIPROC 0xff1f /* Last processor-specific. */ -#define SHN_LOOS 0xff20 /* First operating system-specific. */ -#define SHN_HIOS 0xff3f /* Last operating system-specific. */ -#define SHN_ABS 0xfff1 /* Absolute values. */ -#define SHN_COMMON 0xfff2 /* Common data. */ -#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ -#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ - -/* sh_type */ -#define SHT_NULL 0 /* inactive */ -#define SHT_PROGBITS 1 /* program defined information */ -#define SHT_SYMTAB 2 /* symbol table section */ -#define SHT_STRTAB 3 /* string table section */ -#define SHT_RELA 4 /* relocation section with addends */ -#define SHT_HASH 5 /* symbol hash table section */ -#define SHT_DYNAMIC 6 /* dynamic section */ -#define SHT_NOTE 7 /* note section */ -#define SHT_NOBITS 8 /* no space section */ -#define SHT_REL 9 /* relocation section - no addends */ -#define SHT_SHLIB 10 /* reserved - purpose unknown */ -#define SHT_DYNSYM 11 /* dynamic symbol table section */ -#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ -#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ -#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ -#define SHT_GROUP 17 /* Section group. */ -#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ -#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ -#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ -#define SHT_GNU_VERDEF 0x6ffffffd -#define SHT_GNU_VERNEED 0x6ffffffe -#define SHT_GNU_VERSYM 0x6fffffff -#define SHT_LOPROC 0x70000000 /* reserved range for processor */ -#define SHT_HIPROC 0x7fffffff /* specific section header types */ -#define SHT_LOUSER 0x80000000 /* reserved range for application */ -#define SHT_HIUSER 0xffffffff /* specific indexes */ - -/* Flags for sh_flags. */ -#define SHF_WRITE 0x1 /* Section contains writable data. */ -#define SHF_ALLOC 0x2 /* Section occupies memory. */ -#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ -#define SHF_MERGE 0x10 /* Section may be merged. */ -#define SHF_STRINGS 0x20 /* Section contains strings. */ -#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ -#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ -#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ -#define SHF_GROUP 0x200 /* Member of section group. */ -#define SHF_TLS 0x400 /* Section contains TLS data. */ -#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ -#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ - -/* Values for p_type. */ -#define PT_NULL 0 /* Unused entry. */ -#define PT_LOAD 1 /* Loadable segment. */ -#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ -#define PT_INTERP 3 /* Pathname of interpreter. */ -#define PT_NOTE 4 /* Auxiliary information. */ -#define PT_SHLIB 5 /* Reserved (not used). */ -#define PT_PHDR 6 /* Location of program header itself. */ -#define PT_TLS 7 /* Thread local storage segment */ -#define PT_LOOS 0x60000000 /* First OS-specific. */ -#define PT_HIOS 0x6fffffff /* Last OS-specific. */ -#define PT_LOPROC 0x70000000 /* First processor-specific type. */ -#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ -#define PT_GNU_STACK 0x6474e551 -#define PT_PAX_FLAGS 0x65041580 - -/* Values for p_flags. */ -#define PF_X 0x1 /* Executable. */ -#define PF_W 0x2 /* Writable. */ -#define PF_R 0x4 /* Readable. */ -#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ - -/* Values for d_tag. */ -#define DT_NULL 0 /* Terminating entry. */ -/* String table offset of a needed shared library. */ -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ -#define DT_PLTGOT 3 /* Processor-dependent address. */ -#define DT_HASH 4 /* Address of symbol hash table. */ -#define DT_STRTAB 5 /* Address of string table. */ -#define DT_SYMTAB 6 /* Address of symbol table. */ -#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ -#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ -#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ -#define DT_STRSZ 10 /* Size of string table. */ -#define DT_SYMENT 11 /* Size of each symbol table entry. */ -#define DT_INIT 12 /* Address of initialization function. */ -#define DT_FINI 13 /* Address of finalization function. */ -/* String table offset of shared object name. */ -#define DT_SONAME 14 -#define DT_RPATH 15 /* String table offset of library path. [sup] */ -#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ -#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ -#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ -#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ -#define DT_PLTREL 20 /* Type of relocation used for PLT. */ -#define DT_DEBUG 21 /* Reserved (not used). */ -/* Indicates there may be relocations in non-writable segments. [sup] */ -#define DT_TEXTREL 22 -#define DT_JMPREL 23 /* Address of PLT relocations. */ -#define DT_BIND_NOW 24 /* [sup] */ -/* Address of the array of pointers to initialization functions */ -#define DT_INIT_ARRAY 25 -/* Address of the array of pointers to termination functions */ -#define DT_FINI_ARRAY 26 -/* Size in bytes of the array of initialization functions. */ -#define DT_INIT_ARRAYSZ 27 -/* Size in bytes of the array of terminationfunctions. */ -#define DT_FINI_ARRAYSZ 28 -/* String table offset of a null-terminated library search path string. */ -#define DT_RUNPATH 29 -#define DT_FLAGS 30 /* Object specific flag values. */ -/* Values greater than or equal to DT_ENCODING and less than - DT_LOOS follow the rules for the interpretation of the d_un - union as follows: even == 'd_ptr', even == 'd_val' or none */ -#define DT_ENCODING 32 -/* Address of the array of pointers to pre-initialization functions. */ -#define DT_PREINIT_ARRAY 32 -/* Size in bytes of the array of pre-initialization functions. */ -#define DT_PREINIT_ARRAYSZ 33 -#define DT_LOOS 0x6000000d /* First OS-specific */ -#define DT_HIOS 0x6ffff000 /* Last OS-specific */ -#define DT_LOPROC 0x70000000 /* First processor-specific type. */ -#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ - -#define DT_VERNEED 0x6ffffffe -#define DT_VERNEEDNUM 0x6fffffff -#define DT_VERSYM 0x6ffffff0 - -/* Values for DT_FLAGS */ -/* Indicates that the object being loaded may make reference to - the $ORIGIN substitution string */ -#define DF_ORIGIN 0x0001 -#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ -/* Indicates there may be relocations in non-writable segments. */ -#define DF_TEXTREL 0x0004 -/* Indicates that the dynamic linker should process all - relocations for the object containing this entry before - transferring control to the program. */ -#define DF_BIND_NOW 0x0008 -/* Indicates that the shared object or executable contains code - using a static thread-local storage scheme. */ -#define DF_STATIC_TLS 0x0010 - -/* Values for n_type. Used in core files. */ -#define NT_PRSTATUS 1 /* Process status. */ -#define NT_FPREGSET 2 /* Floating point registers. */ -#define NT_PRPSINFO 3 /* Process state info. */ - -/* Symbol Binding - ELFNN_ST_BIND - st_info */ -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* like global - lower precedence */ -#define STB_LOOS 10 /* Reserved range for operating system */ -#define STB_HIOS 12 /* specific semantics. */ -#define STB_LOPROC 13 /* reserved range for processor */ -#define STB_HIPROC 15 /* specific semantics. */ - -/* Symbol type - ELFNN_ST_TYPE - st_info */ -#define STT_NOTYPE 0 /* Unspecified type. */ -#define STT_OBJECT 1 /* Data object. */ -#define STT_FUNC 2 /* Function. */ -#define STT_SECTION 3 /* Section. */ -#define STT_FILE 4 /* Source file. */ -#define STT_COMMON 5 /* Uninitialized common block. */ -#define STT_TLS 6 /* TLS object. */ -#define STT_LOOS 10 /* Reserved range for operating system */ -#define STT_HIOS 12 /* specific semantics. */ -#define STT_LOPROC 13 /* reserved range for processor */ -#define STT_HIPROC 15 /* specific semantics. */ - -/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ -#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ -#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ -#define STV_HIDDEN 0x2 /* Not visible. */ -#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ - -/* Special symbol table indexes. */ -#define STN_UNDEF 0 /* Undefined symbol index. */ - -/* - * ELF definitions common to all 32-bit architectures. - */ - -typedef uint32 Elf32_Addr; -typedef uint16 Elf32_Half; -typedef uint32 Elf32_Off; -typedef int32 Elf32_Sword; -typedef uint32 Elf32_Word; - -typedef Elf32_Word Elf32_Hashelt; - -/* Non-standard class-dependent datatype used for abstraction. */ -typedef Elf32_Word Elf32_Size; -typedef Elf32_Sword Elf32_Ssize; - -/* - * ELF header. - */ - -typedef struct { - unsigned char ident[EI_NIDENT]; /* File identification. */ - Elf32_Half type; /* File type. */ - Elf32_Half machine; /* Machine architecture. */ - Elf32_Word version; /* ELF format version. */ - Elf32_Addr entry; /* Entry point. */ - Elf32_Off phoff; /* Program header file offset. */ - Elf32_Off shoff; /* Section header file offset. */ - Elf32_Word flags; /* Architecture-specific flags. */ - Elf32_Half ehsize; /* Size of ELF header in bytes. */ - Elf32_Half phentsize; /* Size of program header entry. */ - Elf32_Half phnum; /* Number of program header entries. */ - Elf32_Half shentsize; /* Size of section header entry. */ - Elf32_Half shnum; /* Number of section header entries. */ - Elf32_Half shstrndx; /* Section name strings section. */ -} Elf32_Ehdr; - -/* - * Section header. - */ - -typedef struct { - Elf32_Word name; /* Section name (index into the - section header string table). */ - Elf32_Word type; /* Section type. */ - Elf32_Word flags; /* Section flags. */ - Elf32_Addr vaddr; /* Address in memory image. */ - Elf32_Off off; /* Offset in file. */ - Elf32_Word size; /* Size in bytes. */ - Elf32_Word link; /* Index of a related section. */ - Elf32_Word info; /* Depends on section type. */ - Elf32_Word addralign; /* Alignment in bytes. */ - Elf32_Word entsize; /* Size of each entry in section. */ -} Elf32_Shdr; - -/* - * Program header. - */ - -typedef struct { - Elf32_Word type; /* Entry type. */ - Elf32_Off off; /* File offset of contents. */ - Elf32_Addr vaddr; /* Virtual address in memory image. */ - Elf32_Addr paddr; /* Physical address (not used). */ - Elf32_Word filesz; /* Size of contents in file. */ - Elf32_Word memsz; /* Size of contents in memory. */ - Elf32_Word flags; /* Access permission flags. */ - Elf32_Word align; /* Alignment in memory and file. */ -} Elf32_Phdr; - -/* - * Dynamic structure. The ".dynamic" section contains an array of them. - */ - -typedef struct { - Elf32_Sword d_tag; /* Entry type. */ - union { - Elf32_Word d_val; /* Integer value. */ - Elf32_Addr d_ptr; /* Address value. */ - } d_un; -} Elf32_Dyn; - -/* - * Relocation entries. - */ - -/* Relocations that don't need an addend field. */ -typedef struct { - Elf32_Addr off; /* Location to be relocated. */ - Elf32_Word info; /* Relocation type and symbol index. */ -} Elf32_Rel; - -/* Relocations that need an addend field. */ -typedef struct { - Elf32_Addr off; /* Location to be relocated. */ - Elf32_Word info; /* Relocation type and symbol index. */ - Elf32_Sword addend; /* Addend. */ -} Elf32_Rela; - -/* Macros for accessing the fields of r_info. */ -#define ELF32_R_SYM(info) ((info) >> 8) -#define ELF32_R_TYPE(info) ((unsigned char)(info)) - -/* Macro for constructing r_info from field values. */ -#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) - -/* - * Relocation types. - */ - -#define R_X86_64_NONE 0 /* No relocation. */ -#define R_X86_64_64 1 /* Add 64 bit symbol value. */ -#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ -#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ -#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ -#define R_X86_64_COPY 5 /* Copy data from shared object. */ -#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ -#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ -#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ -#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ -#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ -#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ -#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ -#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ -#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ -#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ -#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ -#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ -#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ -#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ -#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ -#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ -#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ -#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ - -#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ - - -#define R_ALPHA_NONE 0 /* No reloc */ -#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ -#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ -#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ -#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ -#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ -#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ -#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ -#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ -#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ -#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ -#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ -#define R_ALPHA_OP_PUSH 12 /* OP stack push */ -#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ -#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ -#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ -#define R_ALPHA_GPVALUE 16 -#define R_ALPHA_GPRELHIGH 17 -#define R_ALPHA_GPRELLOW 18 -#define R_ALPHA_IMMED_GP_16 19 -#define R_ALPHA_IMMED_GP_HI32 20 -#define R_ALPHA_IMMED_SCN_HI32 21 -#define R_ALPHA_IMMED_BR_HI32 22 -#define R_ALPHA_IMMED_LO32 23 -#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ -#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ -#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ -#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ - -#define R_ALPHA_COUNT 28 - - -#define R_ARM_NONE 0 /* No relocation. */ -#define R_ARM_PC24 1 -#define R_ARM_ABS32 2 -#define R_ARM_REL32 3 -#define R_ARM_PC13 4 -#define R_ARM_ABS16 5 -#define R_ARM_ABS12 6 -#define R_ARM_THM_ABS5 7 -#define R_ARM_ABS8 8 -#define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 -#define R_ARM_THM_PC8 11 -#define R_ARM_AMP_VCALL9 12 -#define R_ARM_SWI24 13 -#define R_ARM_THM_SWI8 14 -#define R_ARM_XPC25 15 -#define R_ARM_THM_XPC22 16 -#define R_ARM_COPY 20 /* Copy data from shared object. */ -#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ -#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ -#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ -#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ -#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ -#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ -#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ -#define R_ARM_CALL 28 -#define R_ARM_JUMP24 29 -#define R_ARM_V4BX 40 -#define R_ARM_GOT_PREL 96 -#define R_ARM_GNU_VTENTRY 100 -#define R_ARM_GNU_VTINHERIT 101 -#define R_ARM_TLS_IE32 107 -#define R_ARM_TLS_LE32 108 -#define R_ARM_RSBREL32 250 -#define R_ARM_THM_RPC22 251 -#define R_ARM_RREL32 252 -#define R_ARM_RABS32 253 -#define R_ARM_RPC24 254 -#define R_ARM_RBASE 255 - -#define R_ARM_COUNT 38 /* Count of defined relocation types. */ - - -#define R_386_NONE 0 /* No relocation. */ -#define R_386_32 1 /* Add symbol value. */ -#define R_386_PC32 2 /* Add PC-relative symbol value. */ -#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ -#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ -#define R_386_COPY 5 /* Copy data from shared object. */ -#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ -#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ -#define R_386_RELATIVE 8 /* Add load address of shared object. */ -#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ -#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ -#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ -#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ -#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ -#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ -#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ -#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ -#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ -#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ -#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ -#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ -#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ -#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ -#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ -#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ -#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ -#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ -#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ -#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ -#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ -#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ - -#define R_386_COUNT 38 /* Count of defined relocation types. */ - -#define R_PPC_NONE 0 /* No relocation. */ -#define R_PPC_ADDR32 1 -#define R_PPC_ADDR24 2 -#define R_PPC_ADDR16 3 -#define R_PPC_ADDR16_LO 4 -#define R_PPC_ADDR16_HI 5 -#define R_PPC_ADDR16_HA 6 -#define R_PPC_ADDR14 7 -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 -#define R_PPC_REL14 11 -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 - -#define R_PPC_COUNT 37 /* Count of defined relocation types. */ - -#define R_PPC_TLS 67 -#define R_PPC_DTPMOD32 68 -#define R_PPC_TPREL16 69 -#define R_PPC_TPREL16_LO 70 -#define R_PPC_TPREL16_HI 71 -#define R_PPC_TPREL16_HA 72 -#define R_PPC_TPREL32 73 -#define R_PPC_DTPREL16 74 -#define R_PPC_DTPREL16_LO 75 -#define R_PPC_DTPREL16_HI 76 -#define R_PPC_DTPREL16_HA 77 -#define R_PPC_DTPREL32 78 -#define R_PPC_GOT_TLSGD16 79 -#define R_PPC_GOT_TLSGD16_LO 80 -#define R_PPC_GOT_TLSGD16_HI 81 -#define R_PPC_GOT_TLSGD16_HA 82 -#define R_PPC_GOT_TLSLD16 83 -#define R_PPC_GOT_TLSLD16_LO 84 -#define R_PPC_GOT_TLSLD16_HI 85 -#define R_PPC_GOT_TLSLD16_HA 86 -#define R_PPC_GOT_TPREL16 87 -#define R_PPC_GOT_TPREL16_LO 88 -#define R_PPC_GOT_TPREL16_HI 89 -#define R_PPC_GOT_TPREL16_HA 90 - -#define R_PPC_EMB_NADDR32 101 -#define R_PPC_EMB_NADDR16 102 -#define R_PPC_EMB_NADDR16_LO 103 -#define R_PPC_EMB_NADDR16_HI 104 -#define R_PPC_EMB_NADDR16_HA 105 -#define R_PPC_EMB_SDAI16 106 -#define R_PPC_EMB_SDA2I16 107 -#define R_PPC_EMB_SDA2REL 108 -#define R_PPC_EMB_SDA21 109 -#define R_PPC_EMB_MRKREF 110 -#define R_PPC_EMB_RELSEC16 111 -#define R_PPC_EMB_RELST_LO 112 -#define R_PPC_EMB_RELST_HI 113 -#define R_PPC_EMB_RELST_HA 114 -#define R_PPC_EMB_BIT_FLD 115 -#define R_PPC_EMB_RELSDA 116 - - /* Count of defined relocation types. */ -#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1) - - -#define R_SPARC_NONE 0 -#define R_SPARC_8 1 -#define R_SPARC_16 2 -#define R_SPARC_32 3 -#define R_SPARC_DISP8 4 -#define R_SPARC_DISP16 5 -#define R_SPARC_DISP32 6 -#define R_SPARC_WDISP30 7 -#define R_SPARC_WDISP22 8 -#define R_SPARC_HI22 9 -#define R_SPARC_22 10 -#define R_SPARC_13 11 -#define R_SPARC_LO10 12 -#define R_SPARC_GOT10 13 -#define R_SPARC_GOT13 14 -#define R_SPARC_GOT22 15 -#define R_SPARC_PC10 16 -#define R_SPARC_PC22 17 -#define R_SPARC_WPLT30 18 -#define R_SPARC_COPY 19 -#define R_SPARC_GLOB_DAT 20 -#define R_SPARC_JMP_SLOT 21 -#define R_SPARC_RELATIVE 22 -#define R_SPARC_UA32 23 -#define R_SPARC_PLT32 24 -#define R_SPARC_HIPLT22 25 -#define R_SPARC_LOPLT10 26 -#define R_SPARC_PCPLT32 27 -#define R_SPARC_PCPLT22 28 -#define R_SPARC_PCPLT10 29 -#define R_SPARC_10 30 -#define R_SPARC_11 31 -#define R_SPARC_64 32 -#define R_SPARC_OLO10 33 -#define R_SPARC_HH22 34 -#define R_SPARC_HM10 35 -#define R_SPARC_LM22 36 -#define R_SPARC_PC_HH22 37 -#define R_SPARC_PC_HM10 38 -#define R_SPARC_PC_LM22 39 -#define R_SPARC_WDISP16 40 -#define R_SPARC_WDISP19 41 -#define R_SPARC_GLOB_JMP 42 -#define R_SPARC_7 43 -#define R_SPARC_5 44 -#define R_SPARC_6 45 -#define R_SPARC_DISP64 46 -#define R_SPARC_PLT64 47 -#define R_SPARC_HIX22 48 -#define R_SPARC_LOX10 49 -#define R_SPARC_H44 50 -#define R_SPARC_M44 51 -#define R_SPARC_L44 52 -#define R_SPARC_REGISTER 53 -#define R_SPARC_UA64 54 -#define R_SPARC_UA16 55 - - -/* - * Magic number for the elf trampoline, chosen wisely to be an immediate - * value. - */ -#define ARM_MAGIC_TRAMP_NUMBER 0x5c000003 - - -/* - * Symbol table entries. - */ - -typedef struct { - Elf32_Word name; /* String table index of name. */ - Elf32_Addr value; /* Symbol value. */ - Elf32_Word size; /* Size of associated object. */ - unsigned char info; /* Type and binding information. */ - unsigned char other; /* Reserved (not used). */ - Elf32_Half shndx; /* Section index of symbol. */ -} Elf32_Sym; - -/* Macros for accessing the fields of st_info. */ -#define ELF32_ST_BIND(info) ((info) >> 4) -#define ELF32_ST_TYPE(info) ((info) & 0xf) - -/* Macro for constructing st_info from field values. */ -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Macro for accessing the fields of st_other. */ -#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) - -/* - * ELF definitions common to all 64-bit architectures. - */ - -typedef uint64 Elf64_Addr; -typedef uint16 Elf64_Half; -typedef uint64 Elf64_Off; -typedef int32 Elf64_Sword; -typedef int64 Elf64_Sxword; -typedef uint32 Elf64_Word; -typedef uint64 Elf64_Xword; - -/* - * Types of dynamic symbol hash table bucket and chain elements. - * - * This is inconsistent among 64 bit architectures, so a machine dependent - * typedef is required. - */ - -#ifdef __alpha__ -typedef Elf64_Off Elf64_Hashelt; -#else -typedef Elf64_Word Elf64_Hashelt; -#endif - -/* Non-standard class-dependent datatype used for abstraction. */ -typedef Elf64_Xword Elf64_Size; -typedef Elf64_Sxword Elf64_Ssize; - -/* - * ELF header. - */ - -typedef struct { - unsigned char ident[EI_NIDENT]; /* File identification. */ - Elf64_Half type; /* File type. */ - Elf64_Half machine; /* Machine architecture. */ - Elf64_Word version; /* ELF format version. */ - Elf64_Addr entry; /* Entry point. */ - Elf64_Off phoff; /* Program header file offset. */ - Elf64_Off shoff; /* Section header file offset. */ - Elf64_Word flags; /* Architecture-specific flags. */ - Elf64_Half ehsize; /* Size of ELF header in bytes. */ - Elf64_Half phentsize; /* Size of program header entry. */ - Elf64_Half phnum; /* Number of program header entries. */ - Elf64_Half shentsize; /* Size of section header entry. */ - Elf64_Half shnum; /* Number of section header entries. */ - Elf64_Half shstrndx; /* Section name strings section. */ -} Elf64_Ehdr; - -/* - * Section header. - */ - -typedef struct Elf64_Shdr Elf64_Shdr; -struct Elf64_Shdr { - Elf64_Word name; /* Section name (index into the - section header string table). */ - Elf64_Word type; /* Section type. */ - Elf64_Xword flags; /* Section flags. */ - Elf64_Addr addr; /* Address in memory image. */ - Elf64_Off off; /* Offset in file. */ - Elf64_Xword size; /* Size in bytes. */ - Elf64_Word link; /* Index of a related section. */ - Elf64_Word info; /* Depends on section type. */ - Elf64_Xword addralign; /* Alignment in bytes. */ - Elf64_Xword entsize; /* Size of each entry in section. */ -}; - -/* - * Program header. - */ - -typedef struct { - Elf64_Word type; /* Entry type. */ - Elf64_Word flags; /* Access permission flags. */ - Elf64_Off off; /* File offset of contents. */ - Elf64_Addr vaddr; /* Virtual address in memory image. */ - Elf64_Addr paddr; /* Physical address (not used). */ - Elf64_Xword filesz; /* Size of contents in file. */ - Elf64_Xword memsz; /* Size of contents in memory. */ - Elf64_Xword align; /* Alignment in memory and file. */ -} Elf64_Phdr; - -/* - * Dynamic structure. The ".dynamic" section contains an array of them. - */ - -typedef struct { - Elf64_Sxword d_tag; /* Entry type. */ - union { - Elf64_Xword d_val; /* Integer value. */ - Elf64_Addr d_ptr; /* Address value. */ - } d_un; -} Elf64_Dyn; - -/* - * Relocation entries. - */ - -/* Relocations that don't need an addend field. */ -typedef struct { - Elf64_Addr off; /* Location to be relocated. */ - Elf64_Xword info; /* Relocation type and symbol index. */ -} Elf64_Rel; - -/* Relocations that need an addend field. */ -typedef struct { - Elf64_Addr off; /* Location to be relocated. */ - Elf64_Xword info; /* Relocation type and symbol index. */ - Elf64_Sxword addend; /* Addend. */ -} Elf64_Rela; - -/* Macros for accessing the fields of r_info. */ -#define ELF64_R_SYM(info) ((info) >> 32) -#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) - -/* Macro for constructing r_info from field values. */ -#define ELF64_R_INFO(sym, type) ((((uint64)(sym)) << 32) + (((uint64)(type)) & 0xffffffffULL)) - -/* - * Symbol table entries. - */ - -typedef struct { - Elf64_Word name; /* String table index of name. */ - unsigned char info; /* Type and binding information. */ - unsigned char other; /* Reserved (not used). */ - Elf64_Half shndx; /* Section index of symbol. */ - Elf64_Addr value; /* Symbol value. */ - Elf64_Xword size; /* Size of associated object. */ -} Elf64_Sym; - -/* Macros for accessing the fields of st_info. */ -#define ELF64_ST_BIND(info) ((info) >> 4) -#define ELF64_ST_TYPE(info) ((info) & 0xf) - -/* Macro for constructing st_info from field values. */ -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Macro for accessing the fields of st_other. */ -#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) - -/* - * Go linker interface - */ - -#define ELF64HDRSIZE 64 -#define ELF64PHDRSIZE 56 -#define ELF64SHDRSIZE 64 -#define ELF64RELSIZE 16 -#define ELF64RELASIZE 24 -#define ELF64SYMSIZE sizeof(Elf64_Sym) - -#define ELF32HDRSIZE sizeof(Elf32_Ehdr) -#define ELF32PHDRSIZE sizeof(Elf32_Phdr) -#define ELF32SHDRSIZE sizeof(Elf32_Shdr) -#define ELF32SYMSIZE sizeof(Elf32_Sym) -#define ELF32RELSIZE 8 diff --git a/rimage/file_format.h b/rimage/file_format.h deleted file mode 100644 index dc43dc9f947f..000000000000 --- a/rimage/file_format.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood - */ - -/* - * Firmware file format . - */ - -#ifndef __INCLUDE_FILE_FORMAT_H__ -#define __INCLUDE_FILE_FORMAT_H__ - -#include -#include - -#define SND_SOF_LOGS_SIG_SIZE 4 -#define SND_SOF_LOGS_SIG "Logs" - -#define SND_SOF_UIDS_SIG_SIZE 4 -#define SND_SOF_UIDS_SIG "Uids" - -/* - * Logs dictionary file header. - */ -struct snd_sof_logs_header { - unsigned char sig[SND_SOF_LOGS_SIG_SIZE]; /* "Logs" */ - uint32_t base_address; /* address of log entries section */ - uint32_t data_length; /* amount of bytes following this header */ - uint32_t data_offset; /* offset to first entry in this file */ - struct sof_ipc_fw_version version; -}; - -struct snd_sof_uids_header { - unsigned char sig[SND_SOF_UIDS_SIG_SIZE]; /* "Uids" */ - uint32_t base_address; - uint32_t data_length; - uint32_t data_offset; -}; -#endif diff --git a/rimage/file_simple.c b/rimage/file_simple.c deleted file mode 100644 index b68483f2ebab..000000000000 --- a/rimage/file_simple.c +++ /dev/null @@ -1,731 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2015 Intel Corporation. All rights reserved. - -#include -#include -#include -#include -#include -#include - -#include "rimage.h" -#include "file_format.h" - -#define BYT_IRAM_BASE 0xff2c0000 -#define BYT_IRAM_HOST_OFFSET 0x0C0000 -#define BYT_IRAM_SIZE (80 * 1024) -#define BYT_DRAM_BASE 0xff300000 -#define BYT_DRAM_HOST_OFFSET 0x100000 -#define BYT_DRAM_SIZE (160 * 1024) - -#define HSW_IRAM_BASE 0x00000000 -#define HSW_IRAM_HOST_OFFSET 0x00080000 -#define HSW_IRAM_SIZE (384 * 1024) -#define HSW_DRAM_BASE 0x00400000 -#define HSW_DRAM_HOST_OFFSET 0x00000000 -#define HSW_DRAM_SIZE (512 * 1024) - -#define BDW_IRAM_BASE 0x00000000 -#define BDW_IRAM_HOST_OFFSET 0x000A0000 -#define BDW_IRAM_SIZE (320 * 1024) -#define BDW_DRAM_BASE 0x00400000 -#define BDW_DRAM_HOST_OFFSET 0x00000000 -#define BDW_DRAM_SIZE (640 * 1024) - -#define IMX8_IRAM_BASE 0x596f8000 -#define IMX8_IRAM_HOST_OFFSET 0x10000 -#define IMX8_IRAM_SIZE 0x800 -#define IMX8_DRAM_BASE 0x596e8000 -#define IMX8_DRAM_SIZE 0x8000 -#define IMX8_SRAM_BASE 0x92400000 -#define IMX8_SRAM_SIZE 0x800000 - -#define IMX8M_IRAM_BASE 0x3b6f8000 -#define IMX8M_IRAM_HOST_OFFSET 0x10000 -#define IMX8M_IRAM_SIZE 0x800 -#define IMX8M_DRAM_BASE 0x3b6e8000 -#define IMX8M_DRAM_SIZE 0x8000 -#define IMX8M_SRAM_BASE 0x92400000 -#define IMX8M_SRAM_SIZE 0x800000 - -static int get_mem_zone_type(struct image *image, Elf32_Shdr *section) -{ - const struct adsp *adsp = image->adsp; - uint32_t start, end, base, size; - int i; - - start = section->vaddr; - end = section->vaddr + section->size; - - for (i = SOF_FW_BLK_TYPE_START; i < SOF_FW_BLK_TYPE_NUM; i++) { - base = adsp->mem_zones[i].base; - size = adsp->mem_zones[i].size; - - if (start < base) - continue; - if (start >= base + size) - continue; - if (end > base + size) - continue; - return i; - } - return SOF_FW_BLK_TYPE_INVALID; -} - -static int fw_version_copy(struct snd_sof_logs_header *header, - const struct module *module) -{ - Elf32_Shdr *section = NULL; - struct sof_ipc_ext_data_hdr *ext_hdr = NULL; - void *buffer = NULL; - - if (module->fw_ready_index <= 0) - return 0; - - section = &module->section[module->fw_ready_index]; - - buffer = calloc(1, section->size); - if (!buffer) - return -ENOMEM; - - fseek(module->fd, section->off, SEEK_SET); - size_t count = fread(buffer, 1, - section->size, module->fd); - - if (count != section->size) { - fprintf(stderr, "error: can't read ready section %d\n", -errno); - free(buffer); - return -errno; - } - - memcpy(&header->version, - &((struct sof_ipc_fw_ready *)buffer)->version, - sizeof(header->version)); - - /* fw_ready structure contains main (primarily kernel) - * ABI version. - */ - - fprintf(stdout, "fw abi main version: %d:%d:%d\n", - SOF_ABI_VERSION_MAJOR(header->version.abi_version), - SOF_ABI_VERSION_MINOR(header->version.abi_version), - SOF_ABI_VERSION_PATCH(header->version.abi_version)); - - /* let's find dbg abi version, which the log client - * is interested in and override the kernel's one. - * - * skip the base fw-ready record and begin from the first extension. - */ - ext_hdr = buffer + ((struct sof_ipc_fw_ready *)buffer)->hdr.size; - while ((uintptr_t)ext_hdr < (uintptr_t)buffer + section->size) { - if (ext_hdr->type == SOF_IPC_EXT_USER_ABI_INFO) { - header->version.abi_version = - ((struct sof_ipc_user_abi_version *) - ext_hdr)->abi_dbg_version; - break; - } - //move to the next entry - ext_hdr = (struct sof_ipc_ext_data_hdr *) - ((uint8_t *)ext_hdr + ext_hdr->hdr.size); - } - - fprintf(stdout, "fw abi dbg version: %d:%d:%d\n", - SOF_ABI_VERSION_MAJOR(header->version.abi_version), - SOF_ABI_VERSION_MINOR(header->version.abi_version), - SOF_ABI_VERSION_PATCH(header->version.abi_version)); - - free(buffer); - - return 0; -} - -static int block_idx; - -static int write_block(struct image *image, struct module *module, - Elf32_Shdr *section) -{ - const struct adsp *adsp = image->adsp; - struct snd_sof_blk_hdr block; - uint32_t padding = 0; - size_t count; - void *buffer; - int ret; - - block.size = section->size; - if (block.size % 4) { - /* make block.size divisible by 4 to avoid unaligned accesses */ - padding = 4 - (block.size % 4); - block.size += padding; - } - - ret = get_mem_zone_type(image, section); - if (ret != SOF_FW_BLK_TYPE_INVALID) { - block.type = ret; - block.offset = section->vaddr - adsp->mem_zones[ret].base - + adsp->mem_zones[ret].host_offset; - } else { - fprintf(stderr, "error: invalid block address/size 0x%x/0x%x\n", - section->vaddr, section->size); - return -EINVAL; - } - - /* write header */ - count = fwrite(&block, sizeof(block), 1, image->out_fd); - if (count != 1) - return -errno; - - /* alloc data data */ - buffer = calloc(1, section->size); - if (!buffer) - return -ENOMEM; - - /* read in section data */ - ret = fseek(module->fd, section->off, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: cant seek to section %d\n", ret); - goto out; - } - count = fread(buffer, 1, section->size, module->fd); - if (count != section->size) { - fprintf(stderr, "error: cant read section %d\n", -errno); - ret = -errno; - goto out; - } - - /* write out section data */ - count = fwrite(buffer, 1, block.size, image->out_fd); - if (count != block.size) { - fprintf(stderr, "error: cant write section %d\n", -errno); - fprintf(stderr, " foffset %d size 0x%x mem addr 0x%x\n", - section->off, section->size, section->vaddr); - ret = -errno; - goto out; - } - - fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%8.8lx\t%s\n", block_idx++, - section->vaddr, section->size, ftell(image->out_fd), - block.type == SOF_FW_BLK_TYPE_IRAM ? "TEXT" : "DATA"); - -out: - free(buffer); - /* return padding size */ - if (ret >= 0) - return padding; - - return ret; -} - -static int simple_write_module(struct image *image, struct module *module) -{ - struct snd_sof_mod_hdr hdr; - Elf32_Shdr *section; - size_t count; - int i, err; - uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); - int ptr_hdr, ptr_cur; - uint32_t padding = 0; - - hdr.num_blocks = module->num_sections - module->num_bss; - hdr.size = module->text_size + module->data_size + - sizeof(struct snd_sof_blk_hdr) * hdr.num_blocks; - hdr.type = SOF_FW_BASE; - - /* Get the pointer of writing hdr */ - ptr_hdr = ftell(image->out_fd); - count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); - if (count != 1) { - fprintf(stderr, "error: failed to write section header %d\n", - -errno); - return -errno; - } - - fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize"); - - fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->text_start, module->text_end, - module->text_end - module->text_start); - fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->data_start, module->data_end, - module->data_end - module->data_start); - fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ", - module->bss_start, module->bss_end, - module->bss_end - module->bss_start); - - fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\t\tType\n"); - - for (i = 0; i < module->hdr.shnum; i++) { - section = &module->section[i]; - - /* only write valid sections */ - if (!(module->section[i].flags & valid)) - continue; - - /* dont write bss */ - if (section->type == SHT_NOBITS) - continue; - - err = write_block(image, module, section); - if (err < 0) { - fprintf(stderr, "error: failed to write section #%d\n", - i); - return err; - } - /* write_block will return padding size */ - padding += err; - } - hdr.size += padding; - /* Record current pointer, will set it back after overwriting hdr */ - ptr_cur = ftell(image->out_fd); - /* overwrite hdr */ - fseek(image->out_fd, ptr_hdr, SEEK_SET); - count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); - if (count != 1) { - fprintf(stderr, "error: failed to write section header %d\n", - -errno); - return -errno; - } - fseek(image->out_fd, ptr_cur, SEEK_SET); - - fprintf(stdout, "\n"); - /* return padding size */ - return padding; -} - -static int write_block_reloc(struct image *image, struct module *module) -{ - struct snd_sof_blk_hdr block; - size_t count; - void *buffer; - int ret; - - block.size = module->file_size; - block.type = SOF_FW_BLK_TYPE_DRAM; - block.offset = 0; - - /* write header */ - count = fwrite(&block, sizeof(block), 1, image->out_fd); - if (count != 1) - return -errno; - - /* alloc data data */ - buffer = calloc(1, module->file_size); - if (!buffer) - return -ENOMEM; - - /* read in section data */ - ret = fseek(module->fd, 0, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: can't seek to section %d\n", ret); - goto out; - } - count = fread(buffer, 1, module->file_size, module->fd); - if (count != module->file_size) { - fprintf(stderr, "error: can't read section %d\n", -errno); - ret = -errno; - goto out; - } - - /* write out section data */ - count = fwrite(buffer, 1, module->file_size, image->out_fd); - if (count != module->file_size) { - fprintf(stderr, "error: can't write section %d\n", -errno); - ret = -errno; - goto out; - } - - fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%8.8lx\t%s\n", block_idx++, - 0, module->file_size, ftell(image->out_fd), - block.type == SOF_FW_BLK_TYPE_IRAM ? "TEXT" : "DATA"); - -out: - free(buffer); - return ret; -} - -static int simple_write_module_reloc(struct image *image, struct module *module) -{ - struct snd_sof_mod_hdr hdr; - size_t count; - int err; - - hdr.num_blocks = 1; - hdr.size = module->text_size + module->data_size; - hdr.type = SOF_FW_BASE; // module - - count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); - if (count != 1) { - fprintf(stderr, "error: failed to write section header %d\n", - -errno); - return -errno; - } - - fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize"); - - fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->text_start, module->text_end, - module->text_end - module->text_start); - fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->data_start, module->data_end, - module->data_end - module->data_start); - fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ", - module->bss_start, module->bss_end, - module->bss_end - module->bss_start); - - fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\t\tType\n"); - - err = write_block_reloc(image, module); - if (err < 0) { - fprintf(stderr, "error: failed to write section #%d\n", err); - return err; - } - - fprintf(stdout, "\n"); - return 0; -} - -/* used by others */ -static int simple_write_firmware(struct image *image) -{ - struct snd_sof_fw_header hdr; - struct module *module; - size_t count; - int i, ret; - - memcpy(hdr.sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE); - - hdr.num_modules = image->num_modules; - hdr.abi = SND_SOF_FW_ABI; - hdr.file_size = 0; - - for (i = 0; i < image->num_modules; i++) { - module = &image->module[i]; - module->fw_size += sizeof(struct snd_sof_blk_hdr) * - (module->num_sections - module->num_bss); - module->fw_size += sizeof(struct snd_sof_mod_hdr) * - hdr.num_modules; - hdr.file_size += module->fw_size; - } - - count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); - if (count != 1) - return -errno; - - for (i = 0; i < image->num_modules; i++) { - module = &image->module[i]; - - fprintf(stdout, "writing module %d %s\n", i, module->elf_file); - - if (image->reloc) - ret = simple_write_module_reloc(image, module); - else - ret = simple_write_module(image, module); - if (ret < 0) { - fprintf(stderr, "error: failed to write module %d\n", - i); - return ret; - } - /* add padding size */ - hdr.file_size += ret; - } - /* overwrite hdr */ - fseek(image->out_fd, 0, SEEK_SET); - count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); - if (count != 1) - return -errno; - - fprintf(stdout, "firmware: image size %ld (0x%lx) bytes %d modules\n\n", - (long)(hdr.file_size + sizeof(hdr)), - (long)(hdr.file_size + sizeof(hdr)), - hdr.num_modules); - - return 0; -} - -static int write_logs_dictionary(struct image *image) -{ - struct snd_sof_logs_header header; - int i, ret = 0; - void *buffer = NULL; - - memcpy(header.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE); - header.data_offset = sizeof(struct snd_sof_logs_header); - - for (i = 0; i < image->num_modules; i++) { - struct module *module = &image->module[i]; - - /* extract fw_version from fw_ready message located - * in .fw_ready section - */ - ret = fw_version_copy(&header, module); - if (ret < 0) - goto out; - - if (module->logs_index > 0) { - Elf32_Shdr *section = - &module->section[module->logs_index]; - - header.base_address = section->vaddr; - header.data_length = section->size; - - fwrite(&header, sizeof(struct snd_sof_logs_header), 1, - image->ldc_out_fd); - - buffer = calloc(1, section->size); - if (!buffer) - return -ENOMEM; - - fseek(module->fd, section->off, SEEK_SET); - size_t count = fread(buffer, 1, section->size, - module->fd); - if (count != section->size) { - fprintf(stderr, - "error: can't read logs section %d\n", - -errno); - ret = -errno; - goto out; - } - count = fwrite(buffer, 1, section->size, - image->ldc_out_fd); - if (count != section->size) { - fprintf(stderr, - "error: can't write section %d\n", - -errno); - ret = -errno; - goto out; - } - - fprintf(stdout, "logs dictionary: size %u\n", - header.data_length + header.data_offset); - fprintf(stdout, "including fw version of size: %lu\n", - (unsigned long)sizeof(header.version)); - } - } -out: - if (buffer) - free(buffer); - - return ret; -} - -static int write_uids_dictionary(struct image *image) -{ - struct snd_sof_uids_header header; - Elf32_Shdr *section; - int i, ret = 0; - void *buffer = NULL; - - memcpy(header.sig, SND_SOF_UIDS_SIG, SND_SOF_UIDS_SIG_SIZE); - header.data_offset = sizeof(struct snd_sof_uids_header); - - for (i = 0; i < image->num_modules; i++) { - struct module *module = &image->module[i]; - - if (module->uids_index <= 0) - continue; - section = &module->section[module->uids_index]; - - header.base_address = section->vaddr; - header.data_length = section->size; - - fwrite(&header, sizeof(struct snd_sof_uids_header), 1, - image->ldc_out_fd); - - buffer = calloc(1, section->size); - if (!buffer) - return -ENOMEM; - fseek(module->fd, section->off, SEEK_SET); - if (fread(buffer, 1, section->size, module->fd) != - section->size) { - fprintf(stderr, "error: can't read uids section %d\n", - -errno); - ret = -errno; - goto out; - } - if (fwrite(buffer, 1, section->size, image->ldc_out_fd) != - section->size) { - fprintf(stderr, "error: cant't write section %d\n", - -errno); - ret = -errno; - goto out; - } - fprintf(stdout, "uids dictionary: size %u\n", - header.data_length + header.data_offset); - } -out: - free(buffer); - return ret; -} - -int write_dictionaries(struct image *image) -{ - int ret = 0; - - ret = write_logs_dictionary(image); - if (ret) - goto out; - - ret = write_uids_dictionary(image); - -out: - return ret; -} - -const struct adsp machine_byt = { - .name = "byt", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = BYT_IRAM_BASE, - .size = BYT_IRAM_SIZE, - .host_offset = BYT_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = BYT_DRAM_BASE, - .size = BYT_DRAM_SIZE, - .host_offset = BYT_DRAM_HOST_OFFSET, - }, - }, - .machine_id = MACHINE_BAYTRAIL, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_cht = { - .name = "cht", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = BYT_IRAM_BASE, - .size = BYT_IRAM_SIZE, - .host_offset = BYT_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = BYT_DRAM_BASE, - .size = BYT_DRAM_SIZE, - .host_offset = BYT_DRAM_HOST_OFFSET, - }, - }, - .machine_id = MACHINE_CHERRYTRAIL, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_bsw = { - .name = "bsw", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = BYT_IRAM_BASE, - .size = BYT_IRAM_SIZE, - .host_offset = BYT_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = BYT_DRAM_BASE, - .size = BYT_DRAM_SIZE, - .host_offset = BYT_DRAM_HOST_OFFSET, - }, - }, - .machine_id = MACHINE_BRASWELL, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_hsw = { - .name = "hsw", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = HSW_IRAM_BASE, - .size = HSW_IRAM_SIZE, - .host_offset = HSW_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = HSW_DRAM_BASE, - .size = HSW_DRAM_SIZE, - .host_offset = HSW_DRAM_HOST_OFFSET, - }, - }, - .machine_id = MACHINE_HASWELL, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_bdw = { - .name = "bdw", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = BDW_IRAM_BASE, - .size = BDW_IRAM_SIZE, - .host_offset = BDW_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = BDW_DRAM_BASE, - .size = BDW_DRAM_SIZE, - .host_offset = BDW_DRAM_HOST_OFFSET, - }, - }, - .machine_id = MACHINE_BROADWELL, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_imx8 = { - .name = "imx8", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = IMX8_IRAM_BASE, - .size = IMX8_IRAM_SIZE, - .host_offset = IMX8_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = IMX8_DRAM_BASE, - .size = IMX8_DRAM_SIZE, - .host_offset = 0, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = IMX8_SRAM_BASE, - .size = IMX8_SRAM_SIZE, - .host_offset = 0, - }, - }, - .machine_id = MACHINE_IMX8, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_imx8x = { - .name = "imx8x", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = IMX8_IRAM_BASE, - .size = IMX8_IRAM_SIZE, - .host_offset = IMX8_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = IMX8_DRAM_BASE, - .size = IMX8_DRAM_SIZE, - .host_offset = 0, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = IMX8_SRAM_BASE, - .size = IMX8_SRAM_SIZE, - .host_offset = 0, - }, - }, - .machine_id = MACHINE_IMX8X, - .write_firmware = simple_write_firmware, -}; - -const struct adsp machine_imx8m = { - .name = "imx8m", - .mem_zones = { - [SOF_FW_BLK_TYPE_IRAM] = { - .base = IMX8M_IRAM_BASE, - .size = IMX8M_IRAM_SIZE, - .host_offset = IMX8M_IRAM_HOST_OFFSET, - }, - [SOF_FW_BLK_TYPE_DRAM] = { - .base = IMX8M_DRAM_BASE, - .size = IMX8M_DRAM_SIZE, - .host_offset = 0, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = IMX8M_SRAM_BASE, - .size = IMX8M_SRAM_SIZE, - .host_offset = 0, - }, - }, - .machine_id = MACHINE_IMX8M, - .write_firmware = simple_write_firmware, -}; diff --git a/rimage/hash.c b/rimage/hash.c deleted file mode 100644 index 24d11a27b94c..000000000000 --- a/rimage/hash.c +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "rimage.h" -#include "file_format.h" -#include "manifest.h" - -#if OPENSSL_VERSION_NUMBER < 0x10100000L -void EVP_MD_CTX_free(EVP_MD_CTX *ctx); -EVP_MD_CTX *EVP_MD_CTX_new(void); - -static void *OPENSSL_zalloc(size_t num) -{ - void *ret = OPENSSL_malloc(num); - - if (ret) - memset(ret, 0, num); - return ret; -} - -EVP_MD_CTX *EVP_MD_CTX_new(void) -{ - return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); -} - -void EVP_MD_CTX_free(EVP_MD_CTX *ctx) -{ - EVP_MD_CTX_cleanup(ctx); - OPENSSL_free(ctx); -} -#endif - -#define DEBUG_HASH 0 - -void module_sha256_create(struct image *image) -{ - image->md = EVP_sha256(); - image->mdctx = EVP_MD_CTX_new(); - - EVP_DigestInit_ex(image->mdctx, image->md, NULL); -} - -void module_sha_update(struct image *image, uint8_t *data, size_t bytes) -{ - EVP_DigestUpdate(image->mdctx, data, bytes); -} - -void module_sha_complete(struct image *image, uint8_t *hash) -{ - unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len; -#if DEBUG_HASH - int i; -#endif - EVP_DigestFinal_ex(image->mdctx, md_value, &md_len); - EVP_MD_CTX_free(image->mdctx); - - memcpy(hash, md_value, md_len); -#if DEBUG_HASH - fprintf(stdout, "Module digest is: "); - for (i = 0; i < md_len; i++) - fprintf(stdout, "%02x", md_value[i]); - fprintf(stdout, "\n"); -#endif -} - -void ri_sha256(struct image *image, unsigned int offset, unsigned int size, - uint8_t *hash) -{ - module_sha256_create(image); - module_sha_update(image, image->fw_image + offset, size); - module_sha_complete(image, hash); -} - -static void module_sha384_create(struct image *image) -{ - image->md = EVP_sha384(); - image->mdctx = EVP_MD_CTX_new(); - - EVP_DigestInit_ex(image->mdctx, image->md, NULL); -} - -void ri_sha384(struct image *image, unsigned int offset, unsigned int size, - uint8_t *hash) -{ - module_sha384_create(image); - module_sha_update(image, image->fw_image + offset, size); - module_sha_complete(image, hash); -} diff --git a/rimage/man_apl.c b/rimage/man_apl.c deleted file mode 100644 index 7618fb2c576a..000000000000 --- a/rimage/man_apl.c +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. - -#include "css.h" -#include "cse.h" -#include "plat_auth.h" -#include "manifest.h" -#include - -/* manifest template */ -struct fw_image_manifest_v1_8 apl_manifest = { - .cse_partition_dir_header = { - .header_marker = CSE_HEADER_MAKER, - .nb_entries = MAN_CSE_PARTS, - .header_version = 1, - .entry_version = 1, - .header_length = sizeof(struct CsePartitionDirHeader), - .checksum = 0, - .partition_name = "ADSP", - }, - - .cse_partition_dir_entry = { - { - /* CssHeader + platformFirmwareAuthenticationExtension - padding */ - .entry_name = "ADSP.man", - .offset = MAN_CSS_HDR_OFFSET, - .length = sizeof(struct css_header_v1_8) + - PLAT_AUTH_SIZE, - }, - { /* ADSPMetadataFileExtension */ - .entry_name = "cavs0015.met", - .offset = MAN_META_EXT_OFFSET_V1_8, - .length = sizeof(struct sof_man_adsp_meta_file_ext_v1_8), - }, - { /* AdspFwBinaryDesc */ - .entry_name = "cavs0015", - .offset = MAN_FW_DESC_OFFSET_V1_8, - .length = 0, /* calculated by rimage - */ - }, - - }, - - .css = { - .header_type = MAN_CSS_MOD_TYPE, - .header_len = MAN_CSS_HDR_SIZE, - .header_version = MAN_CSS_HDR_VERSION, - .module_vendor = MAN_CSS_MOD_VENDOR, - .size = 222, - .header_id = MAN_CSS_HDR_ID, - .padding = 0, - .version = { - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - }, - .modulus_size = MAN_CSS_MOD_SIZE, - .exponent_size = MAN_CSS_EXP_SIZE, - }, - - .signed_pkg = { - .ext_type = SIGN_PKG_EXT_TYPE, - .ext_len = sizeof(struct signed_pkg_info_ext), - .name = "ADSP", - .vcn = 0, - .bitmap = {0, 0, 0, 0, 8}, - - .module[0] = { - .name = "cavs0015.met", - .meta_size = 96, - .type = 0x03, - .hash_algo = 0x02, /* SHA 256 */ - .hash_size = 0x20, - }, - }, - - .partition_info = { - .ext_type = PART_INFO_EXT_TYPE, - .ext_len = sizeof(struct partition_info_ext), - - .name = "ADSP", - .length = 0, /* calculated by rimage - rounded up to nearest PAGE */ - .part_version = 0x10000000, - .instance_id = 1, - .reserved[0 ... 19] = 0xff, - - .module[0] = { - .name = "cavs0015.met", - .meta_size = 96, - .type = 0x03, - .reserved = {0x00, 0xff, 0xff}, - }, - - }, - - .cse_padding[0 ... 47] = 0xff, - - .adsp_file_ext = { - .ext_type = 17, - .ext_len = sizeof(struct sof_man_adsp_meta_file_ext_v1_8), - .comp_desc[0] = { - .version = 0, - .base_offset = MAN_DESC_OFFSET_V1_8, - .limit_offset = 0, /* calculated length + MAN_DESC_OFFSET */ - }, - - }, - - .reserved[0 ... 31] = 0xff, - - .desc = { - .header = { - .header_id = SOF_MAN_FW_HDR_ID, - .header_len = sizeof(struct sof_man_fw_header), - .name = SOF_MAN_FW_HDR_NAME, - .preload_page_count = 0, /* size in pages from $CPD */ - .fw_image_flags = SOF_MAN_FW_HDR_FLAGS, - .feature_mask = SOF_MAN_FW_HDR_FEATURES, - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - .load_offset = MAN_DESC_OFFSET_V1_8, - }, - }, -}; diff --git a/rimage/man_cnl.c b/rimage/man_cnl.c deleted file mode 100644 index 575c2c8e6451..000000000000 --- a/rimage/man_cnl.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. - -#include "css.h" -#include "cse.h" -#include "plat_auth.h" -#include "manifest.h" -#include - -/* manifest template */ -struct fw_image_manifest_v1_8 cnl_manifest = { - .cse_partition_dir_header = { - .header_marker = CSE_HEADER_MAKER, - .nb_entries = MAN_CSE_PARTS, - .header_version = 1, - .entry_version = 1, - .header_length = sizeof(struct CsePartitionDirHeader), - .partition_name = "ADSP", - }, - - .cse_partition_dir_entry = { - { - /* CssHeader + platformFirmwareAuthenticationExtension - padding */ - .entry_name = "ADSP.man", - .offset = MAN_CSS_HDR_OFFSET, - .length = sizeof(struct css_header_v1_8) + - PLAT_AUTH_SIZE, - }, - { /* ADSPMetadataFileExtension */ - .entry_name = "cavs0015.met", - .offset = MAN_META_EXT_OFFSET_V1_8, - .length = sizeof(struct sof_man_adsp_meta_file_ext_v1_8), - }, - { /* AdspFwBinaryDesc */ - .entry_name = "cavs0015", - .offset = MAN_FW_DESC_OFFSET_V1_8, - .length = 0, /* calculated by rimage - */ - }, - - }, - - .css = { - .header_type = MAN_CSS_MOD_TYPE, - .header_len = MAN_CSS_HDR_SIZE, - .header_version = MAN_CSS_HDR_VERSION, - .module_vendor = MAN_CSS_MOD_VENDOR, - .size = 222, - .header_id = MAN_CSS_HDR_ID, - .padding = 0, - .version = { - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - }, - .modulus_size = MAN_CSS_MOD_SIZE, - .exponent_size = MAN_CSS_EXP_SIZE, - }, - - .signed_pkg = { - .ext_type = SIGN_PKG_EXT_TYPE, - .ext_len = sizeof(struct signed_pkg_info_ext), - .name = "ADSP", - .vcn = 0, - .bitmap = {0, 0, 0, 0, 8}, - - .module[0] = { - .name = "cavs0015.met", - .meta_size = 96, - .type = 0x03, - .hash_algo = 0x02, /* SHA 256 */ - .hash_size = 0x20, - }, - }, - - .partition_info = { - .ext_type = PART_INFO_EXT_TYPE, - .ext_len = sizeof(struct partition_info_ext), - - .name = "ADSP", - .length = 0, /* calculated by rimage - rounded up to nearest PAGE */ - .part_version = 0x10000000, - .instance_id = 1, - .reserved[0 ... 19] = 0xff, - - .module[0] = { - .name = "cavs0015.met", - .meta_size = 96, - .type = 0x03, - .reserved = {0x00, 0xff, 0xff}, - }, - - }, - - .cse_padding[0 ... 47] = 0xff, - - .adsp_file_ext = { - .ext_type = 17, - .ext_len = sizeof(struct sof_man_adsp_meta_file_ext_v1_8), - .comp_desc[0] = { - .version = 0, - .base_offset = MAN_DESC_OFFSET_V1_8, - .limit_offset = 0, /* calculated length + MAN_DESC_OFFSET */ - }, - - }, - - .reserved[0 ... 31] = 0xff, - - .desc = { - .header = { - .header_id = SOF_MAN_FW_HDR_ID, - .header_len = sizeof(struct sof_man_fw_header), - .name = SOF_MAN_FW_HDR_NAME, - .preload_page_count = 0, /* size in pages from $CPD */ - .fw_image_flags = SOF_MAN_FW_HDR_FLAGS, - .feature_mask = SOF_MAN_FW_HDR_FEATURES, - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - .load_offset = 0x30000, - }, - }, -}; diff --git a/rimage/man_kbl.c b/rimage/man_kbl.c deleted file mode 100644 index 5c37f876c71a..000000000000 --- a/rimage/man_kbl.c +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. - -#include "css.h" -#include "cse.h" -#include "plat_auth.h" -#include "manifest.h" -#include - -/* - * TODO: check if all platform for 1.5 are the same base and length. - * if yes, define it as HARDWARE_BUFFER_BASE_V1_5, HARDWARE_BUFFER_LEN_v1_5 - * if not, define a platform specific base and length. - */ -#define KBL_HARDWARE_BUFFER_BASE 0xBE500000 -#define KBL_HARDWARE_BUFFER_LEN 0x4A000 - -/* manifest template */ -struct fw_image_manifest_v1_5 kbl_manifest = { - .css_header = { - .module_type = MAN_CSS_LT_MODULE_TYPE, - .header_len = MAN_CSS_HDR_SIZE, - .header_version = MAN_CSS_HDR_VERSION, - .module_vendor = MAN_CSS_MOD_VENDOR, - .size = 0x800, - .key_size = MAN_CSS_KEY_SIZE, - .modulus_size = MAN_CSS_MOD_SIZE, - .exponent_size = MAN_CSS_EXP_SIZE, - }, - - .desc = { - .header = { - .header_id = SOF_MAN_FW_HDR_ID, - .header_len = sizeof(struct sof_man_fw_header), - .name = SOF_MAN_FW_HDR_NAME, - /* size in pages from $CPD */ - .preload_page_count = 0, - .fw_image_flags = SOF_MAN_FW_HDR_FLAGS, - .feature_mask = SOF_MAN_FW_HDR_FEATURES, - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - .load_offset = 0, - .hw_buf_base_addr = KBL_HARDWARE_BUFFER_BASE, - .hw_buf_length = KBL_HARDWARE_BUFFER_LEN - }, - }, -}; diff --git a/rimage/man_sue.c b/rimage/man_sue.c deleted file mode 100644 index 225ca519f4dd..000000000000 --- a/rimage/man_sue.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. - -#include "css.h" -#include "cse.h" -#include "plat_auth.h" -#include "manifest.h" -#include - -/* manifest template */ -struct fw_image_manifest_v1_5_sue sue_manifest = { - .desc = { - .header = { - .header_id = SOF_MAN_FW_HDR_ID, - .header_len = sizeof(struct sof_man_fw_header), - .name = SOF_MAN_FW_HDR_NAME, - .preload_page_count = 0, /* size in pages from $CPD */ - .fw_image_flags = SOF_MAN_FW_HDR_FLAGS, - .feature_mask = SOF_MAN_FW_HDR_FEATURES, - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - .load_offset = 0x2000, - }, - }, -}; diff --git a/rimage/man_tgl.c b/rimage/man_tgl.c deleted file mode 100644 index 83877e198af7..000000000000 --- a/rimage/man_tgl.c +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. - -#include "css.h" -#include "cse.h" -#include "plat_auth.h" -#include "manifest.h" -#include - -/* manifest template */ -struct fw_image_manifest_v2_5 tgl_manifest = { - .cse_partition_dir_header = { - .header_marker = CSE_HEADER_MAKER, - .nb_entries = MAN_CSE_PARTS, - .header_version = 1, - .entry_version = 1, - .header_length = sizeof(struct CsePartitionDirHeader), - .partition_name = "ADSP", - }, - - .cse_partition_dir_entry = { - { - /* CssHeader + platformFirmwareAuthenticationExtension - padding */ - .entry_name = "ADSP.man", - .offset = MAN_CSS_HDR_OFFSET, - .length = sizeof(struct css_header_v1_8) + - PLAT_AUTH_SIZE, - }, - { /* ADSPMetadataFileExtension */ - .entry_name = "cavs0015.met", - .offset = MAN_META_EXT_OFFSET_V1_8, - .length = sizeof(struct sof_man_adsp_meta_file_ext_v2_5), - }, - { /* AdspFwBinaryDesc */ - .entry_name = "cavs0015", - .offset = MAN_FW_DESC_OFFSET_V2_5, - .length = 0, /* calculated by rimage - */ - }, - - }, - - .css = { - .header_type = MAN_CSS_MOD_TYPE, - .header_len = MAN_CSS_HDR_SIZE, - .header_version = MAN_CSS_HDR_VERSION, - .module_vendor = MAN_CSS_MOD_VENDOR, - .size = 222, - .header_id = MAN_CSS_HDR_ID, - .padding = 0, - .version = { - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - }, - .modulus_size = MAN_CSS_MOD_SIZE, - .exponent_size = MAN_CSS_EXP_SIZE, - }, - - .signed_pkg = { - .ext_type = SIGN_PKG_EXT_TYPE, - .ext_len = sizeof(struct signed_pkg_info_ext), - .name = "ADSP", - .vcn = 0, - .bitmap = {0, 0, 0, 0, 8}, - - .module[0] = { - .name = "cavs0015.met", - .meta_size = 96, - .type = 0x03, - .hash_algo = 0x02, /* SHA 256 */ - .hash_size = 0x20, - }, - }, - - .partition_info = { - .ext_type = PART_INFO_EXT_TYPE, - .ext_len = sizeof(struct partition_info_ext), - - .name = "ADSP", - .length = 0, /* calculated by rimage - rounded up to nearest PAGE */ - .part_version = 0x10000000, - .instance_id = 1, - .reserved[0 ... 19] = 0xff, - - .module[0] = { - .name = "cavs0015.met", - .meta_size = 96, - .type = 0x03, - .reserved = {0x00, 0xff, 0xff}, - }, - - }, - - .cse_padding[0 ... 47] = 0xff, - - .adsp_file_ext = { - .ext_type = 17, - .ext_len = sizeof(struct sof_man_adsp_meta_file_ext_v2_5), - .comp_desc[0] = { - .version = 0, - .base_offset = MAN_DESC_OFFSET_V1_8, - .limit_offset = 0, /* calculated length + MAN_DESC_OFFSET */ - }, - - }, - - .reserved[0 ... 31] = 0xff, - - .desc = { - .header = { - .header_id = SOF_MAN_FW_HDR_ID, - .header_len = sizeof(struct sof_man_fw_header), - .name = SOF_MAN_FW_HDR_NAME, - .preload_page_count = 0, /* size in pages from $CPD */ - .fw_image_flags = SOF_MAN_FW_HDR_FLAGS, - .feature_mask = SOF_MAN_FW_HDR_FEATURES, - .major_version = SOF_MAJOR, - .minor_version = SOF_MINOR, - .hotfix_version = 0, - .build_version = SOF_BUILD, - .load_offset = 0x30000, - }, - }, -}; diff --git a/rimage/manifest.c b/rimage/manifest.c deleted file mode 100644 index 87a36c37c8a4..000000000000 --- a/rimage/manifest.c +++ /dev/null @@ -1,1360 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie -// Janusz Jankowski - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "rimage.h" -#include "file_format.h" -#include "css.h" -#include "cse.h" -#include "plat_auth.h" -#include "manifest.h" - -static int man_open_rom_file(struct image *image) -{ - uint32_t size; - - sprintf(image->out_rom_file, "%s.rom", image->out_file); - unlink(image->out_rom_file); - - size = image->adsp->mem_zones[SOF_FW_BLK_TYPE_ROM].size; - - /* allocate ROM image */ - image->rom_image = calloc(size, 1); - if (!image->rom_image) - return -ENOMEM; - - /* open ROM outfile for writing */ - image->out_rom_fd = fopen(image->out_rom_file, "wb"); - if (!image->out_rom_fd) { - fprintf(stderr, "error: unable to open %s for writing %d\n", - image->out_rom_file, errno); - return -errno; - } - - return 0; -} - -static int man_open_unsigned_file(struct image *image) -{ - sprintf(image->out_unsigned_file, "%s.uns", image->out_file); - unlink(image->out_unsigned_file); - - /* open unsigned FW outfile for writing */ - image->out_unsigned_fd = fopen(image->out_unsigned_file, "wb"); - if (!image->out_unsigned_fd) { - fprintf(stderr, "error: unable to open %s for writing %d\n", - image->out_unsigned_file, errno); - return -errno; - } - - return 0; -} - -static int man_open_manifest_file(struct image *image) -{ - /* open manifest outfile for writing */ - sprintf(image->out_man_file, "%s.met", image->out_file); - unlink(image->out_man_file); - - image->out_man_fd = fopen(image->out_man_file, "wb"); - if (!image->out_man_fd) { - fprintf(stderr, "error: unable to open %s for writing %d\n", - image->out_man_file, errno); - return -errno; - } - - return 0; -} - -static int man_init_image_v1_5(struct image *image) -{ - /* allocate image and copy template manifest */ - image->fw_image = calloc(image->adsp->image_size, 1); - if (!image->fw_image) - return -ENOMEM; - - memcpy(image->fw_image, image->adsp->man_v1_5, - sizeof(struct fw_image_manifest_v1_5)); - - return 0; -} - -static int man_init_image_v1_5_sue(struct image *image) -{ - /* allocate image and copy template manifest */ - image->fw_image = calloc(image->adsp->image_size, 1); - if (!image->fw_image) - return -ENOMEM; - - /* copy 1.5 sue manifest */ - memcpy(image->fw_image + MAN_DESC_OFFSET_V1_5_SUE, - image->adsp->man_v1_5_sue, - sizeof(struct fw_image_manifest_v1_5_sue)); - - return 0; -} - -static int man_init_image_v1_8(struct image *image) -{ - /* allocate image and copy template manifest */ - image->fw_image = calloc(image->adsp->image_size, 1); - if (!image->fw_image) - return -ENOMEM; - - memcpy(image->fw_image, image->adsp->man_v1_8, - sizeof(struct fw_image_manifest_v1_8)); - - return 0; -} - -/* we should call this after all segments size set up via iterate */ -static uint32_t elf_to_file_offset(struct image *image, - struct module *module, - struct sof_man_module *man_module, - Elf32_Shdr *section) -{ - uint32_t elf_addr = section->vaddr, file_offset = 0; - - if (section->type == SHT_PROGBITS) { - if (section->flags & SHF_EXECINSTR) { - /* text segment */ - file_offset = elf_addr - module->text_start + - module->foffset; - } else { - /* rodata segment, append to text segment */ - file_offset = elf_addr - module->data_start + - module->foffset + module->text_fixup_size; - } - } else if (section->type == SHT_NOBITS) { - /* bss segment */ - file_offset = 0; - } - - return file_offset; -} - -/* write SRAM sections */ -static int man_copy_sram(struct image *image, Elf32_Shdr *section, - struct module *module, - struct sof_man_module *man_module, - int section_idx) -{ - uint32_t offset = elf_to_file_offset(image, module, - man_module, section); - uint32_t end = offset + section->size; - int seg_type = -1; - void *buffer = image->fw_image + offset; - size_t count; - - switch (section->type) { - case SHT_PROGBITS: - /* text or data */ - if (section->flags & SHF_EXECINSTR) - seg_type = SOF_MAN_SEGMENT_TEXT; - else - seg_type = SOF_MAN_SEGMENT_RODATA; - break; - case SHT_NOBITS: - seg_type = SOF_MAN_SEGMENT_BSS; - /* FALLTHRU */ - default: - return 0; - } - - /* file_offset for segment should not be 0s, we set it to - * the smallest offset of its modules ATM. - */ - if (man_module->segment[seg_type].file_offset > offset || - man_module->segment[seg_type].file_offset == 0) - man_module->segment[seg_type].file_offset = offset; - - count = fread(buffer, 1, section->size, module->fd); - if (count != section->size) { - fprintf(stderr, "error: cant read section %d\n", -errno); - return -errno; - } - - /* get module end offset ? */ - if (end > image->image_end) - image->image_end = end; - - fprintf(stdout, "\t%d\t0x%x\t0x%x\t\t0x%x\t%s\n", section_idx, - section->vaddr, section->size, offset, - seg_type == SOF_MAN_SEGMENT_TEXT ? "TEXT" : "DATA"); - - return 0; -} - -static int man_copy_elf_section(struct image *image, Elf32_Shdr *section, - struct module *module, - struct sof_man_module *man_module, int idx) -{ - int ret; - - /* seek to ELF section */ - ret = fseek(module->fd, section->off, SEEK_SET); - if (ret < 0) { - fprintf(stderr, "error: can't seek to section %d\n", ret); - return ret; - } - - /* write data to DRAM or ROM image */ - if (!elf_is_rom(image, section)) - return man_copy_sram(image, section, module, man_module, idx); - - return 0; -} - -static int man_get_module_manifest(struct image *image, struct module *module, - struct sof_man_module *man_module) -{ - Elf32_Shdr *section; - struct sof_man_segment_desc *segment; - struct sof_man_module_manifest sof_mod; - size_t count; - int ret, man_section_idx; - - fprintf(stdout, "Module Write: %s\n", module->elf_file); - - /* find manifest module data */ - man_section_idx = elf_find_section(image, module, ".module"); - if (man_section_idx < 0) - return -EINVAL; - - fprintf(stdout, " Manifest module metadata section at index %d\n", - man_section_idx); - section = &module->section[man_section_idx]; - - /* load in manifest data */ - /* module built using xcc has preceding bytes */ - if (section->size > sizeof(sof_mod)) - ret = fseek(module->fd, - section->off + image->xcc_mod_offset, SEEK_SET); - else - ret = fseek(module->fd, section->off, SEEK_SET); - - if (ret < 0) { - fprintf(stderr, "error: can't seek to section %d\n", ret); - return ret; - } - - count = fread(&sof_mod, 1, sizeof(sof_mod), module->fd); - if (count != sizeof(sof_mod)) { - fprintf(stderr, "error: can't read section %d\n", -errno); - return -errno; - } - - /* configure man_module with sofmod data */ - memcpy(man_module->struct_id, "$AME", 4); - man_module->entry_point = sof_mod.module.entry_point; - memcpy(man_module->name, sof_mod.module.name, SOF_MAN_MOD_NAME_LEN); - memcpy(man_module->uuid, sof_mod.module.uuid, 16); - man_module->affinity_mask = sof_mod.module.affinity_mask; - man_module->type.auto_start = sof_mod.module.type.auto_start; - man_module->type.domain_dp = sof_mod.module.type.domain_dp; - man_module->type.domain_ll = sof_mod.module.type.domain_ll; - man_module->type.load_type = sof_mod.module.type.load_type; - - /* read out text_fixup_size from memory mapping */ - module->text_fixup_size = sof_mod.text_size; - - /* text segment */ - segment = &man_module->segment[SOF_MAN_SEGMENT_TEXT]; - segment->flags.r.contents = 1; - segment->flags.r.alloc = 1; - segment->flags.r.load = 1; - segment->flags.r.readonly = 1; - segment->flags.r.code = 1; - - /* data segment */ - segment = &man_module->segment[SOF_MAN_SEGMENT_RODATA]; - segment->flags.r.contents = 1; - segment->flags.r.alloc = 1; - segment->flags.r.load = 1; - segment->flags.r.readonly = 1; - segment->flags.r.data = 1; - segment->flags.r.type = 1; - - /* bss segment */ - segment = &man_module->segment[SOF_MAN_SEGMENT_BSS]; - segment->flags.r.alloc = 1; - segment->flags.r.type = 2; - - fprintf(stdout, " Entry point 0x%8.8x\n", man_module->entry_point); - - return 0; -} - -static inline const char *segment_name(int i) -{ - switch (i) { - case SOF_MAN_SEGMENT_TEXT: - return "TEXT"; - case SOF_MAN_SEGMENT_RODATA: - return "DATA"; - case SOF_MAN_SEGMENT_BSS: - return "BSS"; - default: - return "NONE"; - } -} - -/* make sure no segments collide */ -static int man_module_validate(struct sof_man_module *man_module) -{ - uint32_t istart, iend; - uint32_t jstart, jend; - int i, j; - - for (i = 0; i < 3; i++) { - istart = man_module->segment[i].v_base_addr; - iend = istart + man_module->segment[i].flags.r.length * - MAN_PAGE_SIZE; - - for (j = 0; j < 3; j++) { - /* don't validate segment against itself */ - if (i == j) - continue; - - jstart = man_module->segment[j].v_base_addr; - jend = jstart + man_module->segment[j].flags.r.length * - MAN_PAGE_SIZE; - - if (jstart > istart && jstart < iend) - goto err; - - if (jend > istart && jend < iend) - goto err; - } - } - - /* success, no overlapping segments */ - return 0; - -err: - fprintf(stderr, "error: segment %s [0x%8.8x:0x%8.8x] overlaps", - segment_name(i), istart, iend); - fprintf(stderr, " with %s [0x%8.8x:0x%8.8x]\n", - segment_name(j), jstart, jend); - return -EINVAL; -} - -static int man_module_create(struct image *image, struct module *module, - struct sof_man_module *man_module) -{ - /* create module and segments */ - uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); - Elf32_Shdr *section; - int i, err; - unsigned int pages; - - image->image_end = 0; - - err = man_get_module_manifest(image, module, man_module); - if (err < 0) - return err; - - /* stack size ??? convert sizes to PAGES */ - man_module->instance_bss_size = 1; - - /* max number of instances of this module ?? */ - man_module->instance_max_count = 1; - - fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize"); - - fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->text_start, module->text_end, - module->text_end - module->text_start); - fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->data_start, module->data_end, - module->data_end - module->data_start); - fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ", - module->bss_start, module->bss_end, - module->bss_end - module->bss_start); - - /* main module */ - /* text section is first */ - man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset = - module->foffset; - man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = - module->text_start; - - /* calculates those padding 0s by the start of next segment */ - pages = module->text_file_size / MAN_PAGE_SIZE; - if (module->text_file_size % MAN_PAGE_SIZE) - pages += 1; - - if (module->text_fixup_size == 0) - module->text_fixup_size = module->text_file_size; - - /* check if text_file_size is bigger then text_fixup_size */ - if (module->text_file_size > module->text_fixup_size) { - fprintf(stderr, "error: too small text size assigned!\n"); - return -EINVAL; - } - - man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = pages; - - /* data section */ - man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = - module->data_start; - man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset = - module->foffset + module->text_fixup_size; - pages = module->data_file_size / MAN_PAGE_SIZE; - if (module->data_file_size % MAN_PAGE_SIZE) - pages += 1; - - man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = pages; - - /* bss is last */ - man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0; - man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = - module->bss_start; - pages = (module->bss_end - module->bss_start) / MAN_PAGE_SIZE; - if ((module->bss_end - module->bss_start) % MAN_PAGE_SIZE) - pages += 1; - man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = pages; - if (pages == 0) { - man_module->segment[SOF_MAN_SEGMENT_BSS].flags.ul = 0; - man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.type = - SOF_MAN_SEGMENT_EMPTY; - } - - fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\tType\n"); - - if (man_module_validate(man_module) < 0) - return -EINVAL; - - /* find all sections and copy to corresponding segments */ - for (i = 0; i < module->hdr.shnum; i++) { - section = &module->section[i]; - - /* only check valid sections */ - if (!(section->flags & valid)) - continue; - - if (section->size == 0) - continue; - - /* text or data section */ - if (!elf_is_rom(image, section)) - err = man_copy_elf_section(image, section, module, - man_module, i); - - if (err < 0) { - fprintf(stderr, "error: failed to write section #%d\n", - i); - return err; - } - } - fprintf(stdout, "\n"); - - /* no need to update end for exec headers */ - if (module->exec_header) { - image->image_end = FILE_TEXT_OFFSET_V1_5_SUE; - goto out; - } - - /* round module end upto nearest page */ - if (image->image_end % MAN_PAGE_SIZE) { - image->image_end = (image->image_end / MAN_PAGE_SIZE) + 1; - image->image_end *= MAN_PAGE_SIZE; - } - -out: - fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n", - man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length, - man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length, - man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length, - image->image_end); - return 0; -} - -static int man_module_create_reloc(struct image *image, struct module *module, - struct sof_man_module *man_module) -{ - /* create module and segments */ - int err; - unsigned int pages; - void *buffer = image->fw_image + module->foffset; - size_t count; - - image->image_end = 0; - - err = man_get_module_manifest(image, module, man_module); - if (err < 0) - return err; - - /* stack size ??? convert sizes to PAGES */ - man_module->instance_bss_size = 1; - - /* max number of instances of this module ?? */ - man_module->instance_max_count = 1; - - fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize"); - - fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->text_start, module->text_end, - module->text_end - module->text_start); - fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%x\n", - module->data_start, module->data_end, - module->data_end - module->data_start); - fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%x\n\n ", - module->bss_start, module->bss_end, - module->bss_end - module->bss_start); - - /* main module */ - /* text section is first */ - man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset = - module->foffset; - man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = 0; - man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = 0; - - /* data section */ - man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = 0; - man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset = - module->foffset; - pages = module->data_file_size / MAN_PAGE_SIZE; - if (module->data_file_size % MAN_PAGE_SIZE) - pages += 1; - - man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = pages; - - /* bss is last */ - man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0; - man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = 0; - man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = 0; - - fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\tType\n"); - - /* seek to beginning of file */ - err = fseek(module->fd, 0, SEEK_SET); - if (err < 0) { - fprintf(stderr, "error: can't seek to section %d\n", err); - return err; - } - - count = fread(buffer, 1, module->file_size, module->fd); - if (count != module->file_size) { - fprintf(stderr, "error: can't read section %d\n", -errno); - return -errno; - } - - fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%x\t%s\n", 0, - 0, module->file_size, 0, "DATA"); - - fprintf(stdout, "\n"); - image->image_end = module->foffset + module->file_size; - - /* round module end up to nearest page */ - if (image->image_end % MAN_PAGE_SIZE) { - image->image_end = (image->image_end / MAN_PAGE_SIZE) + 1; - image->image_end *= MAN_PAGE_SIZE; - } - - fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n", - man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length, - man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length, - man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length, - image->image_end); - return 0; -} - -static int man_write_unsigned_mod(struct image *image, int meta_start_offset, - int meta_end_offset, size_t ext_file_size) -{ - int count; - - /* write metadata file for unsigned FW */ - count = fwrite(image->fw_image + meta_start_offset, - ext_file_size, 1, - image->out_man_fd); - - /* did the metadata/manifest write succeed ? */ - if (count != 1) { - fprintf(stderr, "error: failed to write meta %s %d\n", - image->out_man_file, -errno); - return -errno; - } - fclose(image->out_man_fd); - - /* now prepare the unsigned rimage */ - count = fwrite(image->fw_image + meta_end_offset, - image->image_end - meta_end_offset, - 1, image->out_unsigned_fd); - - /* did the unsigned FW write succeed ? */ - if (count != 1) { - fprintf(stderr, "error: failed to write firmware %s %d\n", - image->out_unsigned_file, -errno); - return -errno; - } - fclose(image->out_unsigned_fd); - - return 0; -} - -static int man_write_fw_mod(struct image *image) -{ - int count; - - /* write manifest and signed image */ - count = fwrite(image->fw_image, image->image_end, 1, image->out_fd); - - /* did the image write succeed ? */ - if (count != 1) { - fprintf(stderr, "error: failed to write signed firmware %s %d\n", - image->out_file, -errno); - return -errno; - } - - return 0; -} - -static int man_create_modules(struct image *image, struct sof_man_fw_desc *desc, - int file_text_offset) -{ - struct module *module; - struct sof_man_module *man_module; - int err; - int i = 0, offset = 0; - - /* if first module is executable then write before manifest */ - if (image->adsp->exec_boot_ldr) { - man_module = (void *)desc + SOF_MAN_MODULE_OFFSET(0); - module = &image->module[0]; - - fprintf(stdout, "Module: %s used as executable header\n", - module->elf_file); - module->exec_header = 1; - - /* set module file offset */ - module->foffset = 0; - - err = man_module_create(image, module, man_module); - if (err < 0) - return err; - - /* setup man_modules for missing exec loader module */ - i = 1; - offset = 1; - } - - for (; i < image->num_modules; i++) { - man_module = (void *)desc + SOF_MAN_MODULE_OFFSET(i - offset); - module = &image->module[i]; - - if (i == 0) - module->foffset = file_text_offset; - else - module->foffset = image->image_end; - - if (image->reloc) - err = man_module_create_reloc(image, module, - man_module); - else - err = man_module_create(image, module, man_module); - - if (err < 0) - return err; - } - - return 0; -} - -static int man_hash_modules(struct image *image, struct sof_man_fw_desc *desc) -{ - struct sof_man_module *man_module; - int i; - - for (i = 0; i < image->num_modules; i++) { - man_module = (void *)desc + SOF_MAN_MODULE_OFFSET(i); - - if (image->adsp->exec_boot_ldr && i == 0) { - fprintf(stdout, " module: no need to hash %s\n as its exec header\n", - man_module->name); - continue; - } - - ri_sha256(image, - man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset, - (man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length + - man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length) * - MAN_PAGE_SIZE, man_module->hash); - } - - return 0; -} - -/* used by others */ -static int man_write_fw_v1_5(struct image *image) -{ - struct sof_man_fw_desc *desc; - struct fw_image_manifest_v1_5 *m; - int ret; - - /* init image */ - ret = man_init_image_v1_5(image); - if (ret < 0) - goto err; - - /* open ROM image */ - ret = man_open_rom_file(image); - if (ret < 0) - goto err; - - /* open unsigned firmware */ - ret = man_open_unsigned_file(image); - if (ret < 0) - goto err; - - /* create the manifest */ - ret = man_open_manifest_file(image); - if (ret < 0) - goto err; - - /* create the module */ - m = image->fw_image; - desc = image->fw_image + MAN_DESC_OFFSET_V1_5; - - /* create each module */ - m->desc.header.num_module_entries = image->num_modules; - man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_5); - - fprintf(stdout, "Firmware completing manifest v1.5\n"); - - /* create structures from end of file to start of file */ - ri_css_v1_5_hdr_create(image); - - fprintf(stdout, "Firmware file size 0x%x page count %d\n", - FILE_TEXT_OFFSET_V1_5 - MAN_DESC_OFFSET_V1_5 + image->image_end, - desc->header.preload_page_count); - - /* calculate hash for each module */ - man_hash_modules(image, desc); - - /* sign manifest */ - ret = ri_manifest_sign_v1_5(image); - if (ret < 0) - goto err; - - /* write the firmware */ - ret = man_write_fw_mod(image); - if (ret < 0) - goto err; - - /* write the unsigned files*/ - ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET_V1_5, - MAN_FW_DESC_OFFSET_V1_5, - sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); - if (ret < 0) - goto err; - - fprintf(stdout, "Firmware manifest and signing completed !\n"); - return 0; - -err: - free(image->rom_image); - free(image->fw_image); - unlink(image->out_file); - unlink(image->out_rom_file); - return ret; -} - -/* used by others */ -static int man_write_fw_v1_5_sue(struct image *image) -{ - struct fw_image_manifest_v1_5_sue *m; - uint32_t preload_size; - int ret; - - /* init image */ - ret = man_init_image_v1_5_sue(image); - if (ret < 0) - goto err; - - /* create the manifest */ - ret = man_open_manifest_file(image); - if (ret < 0) - goto err; - - /* create the module */ - m = image->fw_image + MAN_DESC_OFFSET_V1_5_SUE; - - /* create each module - subtract the boot loader exec header */ - m->desc.header.num_module_entries = image->num_modules - 1; - man_create_modules(image, &m->desc, FILE_TEXT_OFFSET_V1_5_SUE); - fprintf(stdout, "Firmware completing manifest v1.5\n"); - - /* write preload page count */ - preload_size = image->image_end - MAN_DESC_OFFSET_V1_5_SUE; - preload_size += MAN_PAGE_SIZE - (preload_size % MAN_PAGE_SIZE); - m->desc.header.preload_page_count = preload_size / MAN_PAGE_SIZE; - - fprintf(stdout, "Firmware file size 0x%x page count %d\n", - FILE_TEXT_OFFSET_V1_5_SUE - MAN_DESC_OFFSET_V1_5_SUE + - image->image_end, m->desc.header.preload_page_count); - - /* calculate hash for each module */ - man_hash_modules(image, &m->desc); - - /* write the firmware */ - ret = man_write_fw_mod(image); - if (ret < 0) - goto err; - - fprintf(stdout, "Firmware manifest and signing completed !\n"); - return 0; - -err: - free(image->fw_image); - unlink(image->out_file); - return ret; -} - -/* used by others */ -static int man_write_fw_v1_8(struct image *image) -{ - struct sof_man_fw_desc *desc; - struct fw_image_manifest_v1_8 *m; - uint8_t hash[SOF_MAN_MOD_SHA256_LEN]; - int ret, i; - - /* init image */ - ret = man_init_image_v1_8(image); - if (ret < 0) - goto err; - - /* open ROM image */ - ret = man_open_rom_file(image); - if (ret < 0) - goto err; - - /* open unsigned firmware */ - ret = man_open_unsigned_file(image); - if (ret < 0) - goto err; - - /* create the manifest */ - ret = man_open_manifest_file(image); - if (ret < 0) - goto err; - - /* create the module */ - m = image->fw_image; - desc = image->fw_image + MAN_DESC_OFFSET_V1_8; - - /* create each module */ - m->desc.header.num_module_entries = image->num_modules; - man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); - - fprintf(stdout, "Firmware completing manifest v1.8\n"); - - /* create structures from end of file to start of file */ - ri_adsp_meta_data_create_v1_8(image, MAN_META_EXT_OFFSET_V1_8, - MAN_FW_DESC_OFFSET_V1_8); - ri_plat_ext_data_create(image); - ri_css_v1_8_hdr_create(image); - ri_cse_create(image); - - fprintf(stdout, "Firmware file size 0x%x page count %d\n", - FILE_TEXT_OFFSET_V1_8 - MAN_DESC_OFFSET_V1_8 + image->image_end, - desc->header.preload_page_count); - - /* calculate hash for each module */ - man_hash_modules(image, desc); - - /* calculate hash for ADSP meta data extension - 0x480 to end */ - ri_sha256(image, MAN_FW_DESC_OFFSET_V1_8, image->image_end - - MAN_FW_DESC_OFFSET_V1_8, - m->adsp_file_ext.comp_desc[0].hash); - - /* calculate hash for platform auth data - repeated in hash 2 and 4 */ - ri_sha256(image, MAN_META_EXT_OFFSET_V1_8, - sizeof(struct sof_man_adsp_meta_file_ext_v1_8), hash); - - /* hash values in reverse order */ - for (i = 0; i < SOF_MAN_MOD_SHA256_LEN; i++) { - m->signed_pkg.module[0].hash[i] = - m->partition_info.module[0].hash[i] = - hash[SOF_MAN_MOD_SHA256_LEN - 1 - i]; - } - - /* sign manifest */ - ret = ri_manifest_sign_v1_8(image); - if (ret < 0) - goto err; - - /* write the firmware */ - ret = man_write_fw_mod(image); - if (ret < 0) - goto err; - - /* write the unsigned files*/ - ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET_V1_8, - MAN_FW_DESC_OFFSET_V1_8, - sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); - if (ret < 0) - goto err; - - fprintf(stdout, "Firmware manifest and signing completed !\n"); - return 0; - -err: - free(image->rom_image); - free(image->fw_image); - unlink(image->out_file); - unlink(image->out_rom_file); - return ret; -} - -/* used to sign with MEU */ -static int man_write_fw_meu_v1_5(struct image *image) -{ - const int meta_start_offset = image->meu_offset - - sizeof(struct sof_man_adsp_meta_file_ext_v1_8) - MAN_EXT_PADDING; - struct sof_man_adsp_meta_file_ext_v1_8 *meta; - struct sof_man_fw_desc *desc; - uint32_t preload_size; - int ret; - - /* allocate image */ - image->fw_image = calloc(image->adsp->image_size, 1); - if (!image->fw_image) { - ret = -ENOMEM; - goto err; - } - - /* open unsigned firmware */ - ret = man_open_unsigned_file(image); - if (ret < 0) - goto err; - - /* create the manifest */ - ret = man_open_manifest_file(image); - if (ret < 0) - goto err; - - /* create the module */ - meta = image->fw_image + meta_start_offset; - desc = image->fw_image + MAN_DESC_OFFSET_V1_5; - - /* copy data */ - memcpy(desc, &image->adsp->man_v1_5->desc, - sizeof(struct sof_man_fw_desc)); - - /* create each module */ - desc->header.num_module_entries = image->num_modules; - man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_5); - - fprintf(stdout, "Firmware completing manifest v1.5\n"); - - /* create structures from end of file to start of file */ - ri_adsp_meta_data_create_v1_8(image, meta_start_offset, - image->meu_offset); - - /* write preload page count */ - preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_5; - preload_size += MAN_PAGE_SIZE - (preload_size % MAN_PAGE_SIZE); - desc->header.preload_page_count = preload_size / MAN_PAGE_SIZE; - - /* calculate hash for each module */ - man_hash_modules(image, desc); - - /* calculate hash for ADSP meta data extension */ - ri_sha256(image, image->meu_offset, image->image_end - - image->meu_offset, meta->comp_desc[0].hash); - - /* write the unsigned files */ - ret = man_write_unsigned_mod(image, meta_start_offset, - image->meu_offset, - sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); - if (ret < 0) - goto err; - - fprintf(stdout, "Firmware manifest completed!\n"); - return 0; - -err: - free(image->fw_image); - unlink(image->out_file); - return ret; -} - -/* used to sign with MEU */ -static int man_write_fw_meu_v1_8(struct image *image) -{ - const int meta_start_offset = image->meu_offset - - sizeof(struct sof_man_adsp_meta_file_ext_v1_8) - MAN_EXT_PADDING; - struct sof_man_adsp_meta_file_ext_v1_8 *meta; - struct sof_man_fw_desc *desc; - uint32_t preload_size; - int ret; - - /* allocate image */ - image->fw_image = calloc(image->adsp->image_size, 1); - if (!image->fw_image) { - ret = -ENOMEM; - goto err; - } - - /* open unsigned firmware */ - ret = man_open_unsigned_file(image); - if (ret < 0) - goto err; - - /* create the manifest */ - ret = man_open_manifest_file(image); - if (ret < 0) - goto err; - - /* create the module */ - meta = image->fw_image + meta_start_offset; - desc = image->fw_image + MAN_DESC_OFFSET_V1_8; - - /* copy data */ - memcpy(meta, &image->adsp->man_v1_8->adsp_file_ext, - sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); - memcpy(desc, &image->adsp->man_v1_8->desc, - sizeof(struct sof_man_fw_desc)); - - /* create each module */ - desc->header.num_module_entries = image->num_modules; - man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); - - fprintf(stdout, "Firmware completing manifest v1.8\n"); - - /* create structures from end of file to start of file */ - ri_adsp_meta_data_create_v1_8(image, meta_start_offset, - image->meu_offset); - - /* write preload page count */ - preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; - preload_size += MAN_PAGE_SIZE - (preload_size % MAN_PAGE_SIZE); - desc->header.preload_page_count = preload_size / MAN_PAGE_SIZE; - - /* calculate hash for each module */ - man_hash_modules(image, desc); - - /* calculate hash for ADSP meta data extension */ - ri_sha256(image, image->meu_offset, image->image_end - - image->meu_offset, meta->comp_desc[0].hash); - - /* write the unsigned files */ - ret = man_write_unsigned_mod(image, meta_start_offset, - image->meu_offset, - sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); - if (ret < 0) - goto err; - - fprintf(stdout, "Firmware manifest completed!\n"); - return 0; - -err: - free(image->fw_image); - unlink(image->out_file); - return ret; -} - -/* used to sign with MEU */ -static int man_write_fw_meu_v2_5(struct image *image) -{ - const int meta_start_offset = image->meu_offset - - sizeof(struct sof_man_adsp_meta_file_ext_v2_5) - MAN_EXT_PADDING; - struct sof_man_adsp_meta_file_ext_v2_5 *meta; - struct sof_man_fw_desc *desc; - uint32_t preload_size; - int ret; - - /* allocate image */ - image->fw_image = calloc(image->adsp->image_size, 1); - if (!image->fw_image) { - ret = -ENOMEM; - goto err; - } - - /* open unsigned firmware */ - ret = man_open_unsigned_file(image); - if (ret < 0) - goto err; - - /* create the manifest */ - ret = man_open_manifest_file(image); - if (ret < 0) - goto err; - - /* create the module */ - meta = image->fw_image + meta_start_offset; - desc = image->fw_image + MAN_DESC_OFFSET_V1_8; - - /* copy data */ - memcpy(meta, &image->adsp->man_v2_5->adsp_file_ext, - sizeof(struct sof_man_adsp_meta_file_ext_v2_5)); - memcpy(desc, &image->adsp->man_v2_5->desc, - sizeof(struct sof_man_fw_desc)); - - /* create each module */ - desc->header.num_module_entries = image->num_modules; - man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); - - fprintf(stdout, "Firmware completing manifest v2.5\n"); - - /* create structures from end of file to start of file */ - ri_adsp_meta_data_create_v2_5(image, meta_start_offset, - image->meu_offset); - - /* write preload page count */ - preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; - preload_size += MAN_PAGE_SIZE - (preload_size % MAN_PAGE_SIZE); - desc->header.preload_page_count = preload_size / MAN_PAGE_SIZE; - - /* calculate hash for each module */ - man_hash_modules(image, desc); - - /* calculate hash for ADSP meta data extension */ - ri_sha384(image, image->meu_offset, image->image_end - - image->meu_offset, meta->comp_desc[0].hash); - - /* write the unsigned files */ - ret = man_write_unsigned_mod(image, meta_start_offset, - image->meu_offset, - sizeof(struct sof_man_adsp_meta_file_ext_v2_5)); - if (ret < 0) - goto err; - - fprintf(stdout, "Firmware manifest completed!\n"); - return 0; - -err: - free(image->fw_image); - unlink(image->out_file); - return ret; -} - -#define ADSP_APL_DSP_ROM_BASE 0xBEFE0000 -#define ADSP_APL_DSP_ROM_SIZE 0x00002000 -#define APL_DSP_BASE_ENTRY 0xa000a000 - -#define ADSP_KBL_DSP_ROM_BASE 0xBEFE0000 -#define ADSP_KBL_DSP_ROM_SIZE 0x00002000 -#define KBL_DSP_BASE_ENTRY 0xa000a000 - -#define ADSP_SKL_DSP_ROM_BASE 0xBEFE0000 -#define ADSP_SKL_DSP_ROM_SIZE 0x00002000 -#define SKL_DSP_BASE_ENTRY 0xa000a000 - -#define ADSP_CNL_DSP_ROM_BASE 0xBEFE0000 -#define ADSP_CNL_DSP_ROM_SIZE 0x00002000 -#define CNL_DSP_IMR_BASE_ENTRY 0xb0038000 -#define CNL_DSP_HP_BASE_ENTRY 0xbe040000 - -#define ADSP_SUE_DSP_ROM_BASE 0xBEFE0000 -#define ADSP_SUE_DSP_ROM_SIZE 0x00002000 -#define SUE_DSP_IMR_BASE_ENTRY 0xb0038000 -#define SUE_DSP_HP_BASE_ENTRY 0xbe000000 - -#define ADSP_ICL_DSP_ROM_BASE 0xBEFE0000 -#define ADSP_ICL_DSP_ROM_SIZE 0x00002000 -#define ICL_DSP_IMR_BASE_ENTRY 0xb0038000 -#define ICL_DSP_HP_BASE_ENTRY 0xbe040000 - -#define ADSP_TGL_DSP_ROM_BASE 0x9F180000 -#define ADSP_TGL_DSP_ROM_SIZE 0x00002000 -#define TGL_DSP_IMR_BASE_ENTRY 0xb0038000 -#define TGL_DSP_HP_BASE_ENTRY 0xbe040000 - -/* list of supported adsp */ -const struct adsp machine_apl = { - .name = "apl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_APL_DSP_ROM_BASE, - .size = ADSP_APL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = APL_DSP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_APOLLOLAKE, - .write_firmware = man_write_fw_v1_8, - .write_firmware_meu = man_write_fw_meu_v1_8, - .man_v1_8 = &apl_manifest, -}; - -const struct adsp machine_kbl = { - .name = "kbl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_KBL_DSP_ROM_BASE, - .size = ADSP_KBL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = KBL_DSP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_KABYLAKE, - .write_firmware = man_write_fw_v1_5, - .write_firmware_meu = man_write_fw_meu_v1_5, - .man_v1_5 = &kbl_manifest, -}; - -const struct adsp machine_skl = { - .name = "skl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_SKL_DSP_ROM_BASE, - .size = ADSP_SKL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = SKL_DSP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_SKYLAKE, - .write_firmware = man_write_fw_v1_5, - .write_firmware_meu = man_write_fw_meu_v1_5, - .man_v1_5 = &kbl_manifest, -}; - -const struct adsp machine_cnl = { - .name = "cnl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_CNL_DSP_ROM_BASE, - .size = ADSP_CNL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_IMR] = { - .base = CNL_DSP_IMR_BASE_ENTRY, - .size = 0x100000, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = CNL_DSP_HP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_CANNONLAKE, - .write_firmware = man_write_fw_v1_8, - .write_firmware_meu = man_write_fw_meu_v1_8, - .man_v1_8 = &cnl_manifest, -}; - -const struct adsp machine_icl = { - .name = "icl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_ICL_DSP_ROM_BASE, - .size = ADSP_ICL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_IMR] = { - .base = ICL_DSP_IMR_BASE_ENTRY, - .size = 0x100000, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = ICL_DSP_HP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_ICELAKE, - .write_firmware = man_write_fw_v1_8, - .write_firmware_meu = man_write_fw_meu_v1_8, - .man_v1_8 = &cnl_manifest, // use the same as CNL -}; - -const struct adsp machine_jsl = { - .name = "jsl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_ICL_DSP_ROM_BASE, - .size = ADSP_ICL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_IMR] = { - .base = ICL_DSP_IMR_BASE_ENTRY, - .size = 0x100000, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = ICL_DSP_HP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_ICELAKE, - .write_firmware = man_write_fw_v1_8, - .write_firmware_meu = man_write_fw_meu_v1_8, - .man_v1_8 = &cnl_manifest, // use the same as CNL -}; - -const struct adsp machine_tgl = { - .name = "tgl", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_TGL_DSP_ROM_BASE, - .size = ADSP_TGL_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_IMR] = { - .base = TGL_DSP_IMR_BASE_ENTRY, - .size = 0x100000, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = TGL_DSP_HP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_TIGERLAKE, - .write_firmware = NULL, /* not yet implemented */ - .write_firmware_meu = man_write_fw_meu_v2_5, - .man_v2_5 = &tgl_manifest, -}; - -const struct adsp machine_sue = { - .name = "sue", - .mem_zones = { - [SOF_FW_BLK_TYPE_ROM] = { - .base = ADSP_SUE_DSP_ROM_BASE, - .size = ADSP_SUE_DSP_ROM_SIZE, - }, - [SOF_FW_BLK_TYPE_IMR] = { - .base = SUE_DSP_IMR_BASE_ENTRY, - .size = 0x100000, - }, - [SOF_FW_BLK_TYPE_SRAM] = { - .base = SUE_DSP_HP_BASE_ENTRY, - .size = 0x100000, - }, - }, - .image_size = 0x100000, - .dram_offset = 0, - .machine_id = MACHINE_SUECREEK, - .write_firmware = man_write_fw_v1_5_sue, - .write_firmware_meu = man_write_fw_v1_5_sue, - .man_v1_5_sue = &sue_manifest, - .exec_boot_ldr = 1, -}; diff --git a/rimage/manifest.h b/rimage/manifest.h deleted file mode 100644 index 32e0574e8db5..000000000000 --- a/rimage/manifest.h +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - */ - -#ifndef __MANIFEST_H__ -#define __MANIFEST_H__ - -#include -#include -#include "css.h" -#include "cse.h" -#include "plat_auth.h" - -#define MAN_PAGE_SIZE 4096 - -/* start offset for modules built using xcc */ -#define DEFAULT_XCC_MOD_OFFSET 0x8 - -/* start offset for base FW module */ -#define FILE_TEXT_OFFSET_V1_8 0x8000 -#define FILE_TEXT_OFFSET_V1_5 0x2000 -#define FILE_TEXT_OFFSET_V1_5_SUE 0xA000 - -/* - * CSE values for CNL - */ -#define MAN_CSE_PARTS 3 - - -#define MAN_CSE_HDR_OFFSET 0 -#define MAN_CSE_PADDING_SIZE 0x30 -#define MAN_EXT_PADDING 0x20 -#define MAN_DESC_OFFSET_V1_8 0x2000 -#define MAN_DESC_OFFSET_V1_5 0x284 -#define MAN_DESC_OFFSET_V1_5_SUE 0x2000 -#define MAN_DEFAULT_IMR_TYPE 3 - -#define MAN_CSS_HDR_OFFSET \ - (MAN_CSE_HDR_OFFSET + \ - sizeof(struct CsePartitionDirHeader) + \ - MAN_CSE_PARTS * sizeof(struct CsePartitionDirEntry)) - -#define MAN_FW_DESC_OFFSET_V2_5 \ - (MAN_META_EXT_OFFSET_V1_8 + \ - sizeof(struct sof_man_adsp_meta_file_ext_v2_5) + \ - MAN_EXT_PADDING) - -#define MAN_DESC_PADDING_SIZE_V2_5 \ - (MAN_DESC_OFFSET_V1_8 - MAN_FW_DESC_OFFSET_V2_5) - -#define MAN_SIG_PKG_OFFSET_V1_8 \ - (MAN_CSS_HDR_OFFSET + \ - sizeof(struct css_header_v1_8)) - -#define MAN_PART_INFO_OFFSET_V1_8 \ - (MAN_SIG_PKG_OFFSET_V1_8 + \ - sizeof(struct signed_pkg_info_ext)) - -#define MAN_META_EXT_OFFSET_V1_8 \ - (MAN_SIG_PKG_OFFSET_V1_8 + \ - sizeof(struct signed_pkg_info_ext) + \ - sizeof(struct partition_info_ext) + \ - MAN_CSE_PADDING_SIZE) - -#define MAN_FW_DESC_OFFSET_V1_8 \ - (MAN_META_EXT_OFFSET_V1_8 + \ - sizeof(struct sof_man_adsp_meta_file_ext_v1_8) + \ - MAN_EXT_PADDING) - -#define MAN_DESC_PADDING_SIZE_V1_8 \ - (MAN_DESC_OFFSET_V1_8 - MAN_FW_DESC_OFFSET_V1_8) - -#define MAN_SIG_PKG_OFFSET_V1_5 \ - (MAN_CSS_HDR_OFFSET + \ - sizeof(struct css_header_v1_5)) - -#define MAN_META_EXT_OFFSET_V1_5 \ - (MAN_SIG_PKG_OFFSET_V1_5 + \ - sizeof(struct signed_pkg_info_ext) + \ - sizeof(struct partition_info_ext) + \ - MAN_CSE_PADDING_SIZE) - -#define MAN_FW_DESC_OFFSET_V1_5 \ - (MAN_META_EXT_OFFSET_V1_5 + \ - sizeof(struct sof_man_adsp_meta_file_ext_v1_8) + \ - MAN_EXT_PADDING) - -/* - * Firmware manifest header V2.5 used on TGL onwards - */ -struct fw_image_manifest_v2_5 { - /* MEU tool needs these sections to be 0s */ - struct CsePartitionDirHeader cse_partition_dir_header; - struct CsePartitionDirEntry cse_partition_dir_entry[MAN_CSE_PARTS]; - struct css_header_v1_8 css; - struct signed_pkg_info_ext signed_pkg; - struct partition_info_ext partition_info; - uint8_t cse_padding[MAN_CSE_PADDING_SIZE]; - struct sof_man_adsp_meta_file_ext_v2_5 adsp_file_ext; - - /* reserved / pading at end of ext data - all 0s*/ - uint8_t reserved[MAN_EXT_PADDING]; - - /* start of the unsigned binary for MEU input must start at MAN_DESC_OFFSET */ - uint8_t padding[MAN_DESC_PADDING_SIZE_V2_5]; - - struct sof_man_fw_desc desc; /* at offset MAN_DESC_OFFSET */ -} __attribute__((packed)); - -extern struct fw_image_manifest_v2_5 tgl_manifest; - -/* - * Firmware manifest header V1.8 used on APL onwards - */ -struct fw_image_manifest_v1_8 { - /* MEU tool needs these sections to be 0s */ - struct CsePartitionDirHeader cse_partition_dir_header; - struct CsePartitionDirEntry cse_partition_dir_entry[MAN_CSE_PARTS]; - struct css_header_v1_8 css; - struct signed_pkg_info_ext signed_pkg; - struct partition_info_ext partition_info; - uint8_t cse_padding[MAN_CSE_PADDING_SIZE]; - struct sof_man_adsp_meta_file_ext_v1_8 adsp_file_ext; - - /* reserved / pading at end of ext data - all 0s*/ - uint8_t reserved[MAN_EXT_PADDING]; - - /* start of the unsigned binary for MEU input must start at MAN_DESC_OFFSET */ - uint8_t padding[MAN_DESC_PADDING_SIZE_V1_8]; - - struct sof_man_fw_desc desc; /* at offset MAN_DESC_OFFSET */ -} __attribute__((packed)); - -extern struct fw_image_manifest_v1_8 apl_manifest; -extern struct fw_image_manifest_v1_8 cnl_manifest; - -/* - * Firmware manifest header V1.5 used on SKL and KBL - */ -struct fw_image_manifest_v1_5 { - struct css_header_v1_5 css_header; - struct sof_man_fw_desc desc; -} __attribute__((packed)); - -struct fw_image_manifest_v1_5_sue { - struct sof_man_fw_desc desc; -} __attribute__((packed)); - -/* - * TODO: verify if we need platform specific manifest, or just - * define manifest_v1_5 and manifest_v1_8. - */ -extern struct fw_image_manifest_v1_5 skl_manifest; -extern struct fw_image_manifest_v1_5 kbl_manifest; -extern struct fw_image_manifest_v1_5_sue sue_manifest; -#endif diff --git a/rimage/pkcs1_5.c b/rimage/pkcs1_5.c deleted file mode 100644 index 4da4d4877284..000000000000 --- a/rimage/pkcs1_5.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rimage.h" -#include "css.h" -#include "manifest.h" - -#if OPENSSL_VERSION_NUMBER < 0x10100000L -void RSA_get0_key(const RSA *r, - const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); - -void RSA_get0_key(const RSA *r, - const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) -{ - if (n) - *n = r->n; - if (e) - *e = r->e; - if (d) - *d = r->d; -} -#endif - -#define DEBUG_PKCS 0 - -static void bytes_swap(uint8_t *ptr, uint32_t size) -{ - uint8_t tmp; - uint32_t index; - - for (index = 0; index < (size / 2); index++) { - tmp = ptr[index]; - ptr[index] = ptr[size - 1 - index]; - ptr[size - 1 - index] = tmp; - } -} - -/* - * RSA signature of manifest. The signature is an PKCS - * #1-v1_5 of the entire manifest structure, including all - * extensions, and excluding the last 3 fields of the - * manifest header (Public Key, Exponent and Signature). - */ - -int pkcs_v1_5_sign_man_v1_5(struct image *image, - struct fw_image_manifest_v1_5 *man, - void *ptr1, unsigned int size1) -{ - RSA *priv_rsa = NULL; - EVP_PKEY *privkey; - FILE *fp; - - const BIGNUM *n, *e, *d; - unsigned char digest[SHA256_DIGEST_LENGTH]; - unsigned char mod[MAN_RSA_KEY_MODULUS_LEN]; - unsigned int siglen = MAN_RSA_SIGNATURE_LEN; - char path[256]; - int ret = -EINVAL, i; - -#if DEBUG_PKCS - fprintf(stdout, "offsets 0x%lx size 0x%x\n", - ptr1 - (void *)man, size1); -#endif - - /* create new key */ - privkey = EVP_PKEY_new(); - if (!privkey) - return -ENOMEM; - - /* load in RSA private key from PEM file */ - if (!image->key_name) { - snprintf(path, sizeof(path), "%s/otc_private_key.pem", PEM_KEY_PREFIX); - } else { - memset(path, 0, sizeof(path)); - strncpy(path, image->key_name, sizeof(path) - 1); - } - - fprintf(stdout, " pkcs: signing with key %s\n", path); - fp = fopen(path, "rb"); - if (!fp) { - fprintf(stderr, "error: can't open file %s %d\n", - path, -errno); - return -errno; - } - PEM_read_PrivateKey(fp, &privkey, NULL, NULL); - fclose(fp); - - /* validate RSA private key */ - priv_rsa = EVP_PKEY_get1_RSA(privkey); - if (RSA_check_key(priv_rsa)) { - fprintf(stdout, " pkcs: RSA private key is valid.\n"); - } else { - fprintf(stderr, "error: validating RSA private key.\n"); - return -EINVAL; - } - - /* calculate the digest */ - module_sha256_create(image); - module_sha_update(image, ptr1, size1); - module_sha_complete(image, digest); - - fprintf(stdout, " pkcs: digest for manifest is "); - for (i = 0; i < SHA256_DIGEST_LENGTH; i++) - fprintf(stdout, "%02x", digest[i]); - fprintf(stdout, "\n"); - - /* sign the manifest */ - ret = RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH, - (unsigned char *)man->css_header.signature, - &siglen, priv_rsa); - if (ret < 0) - fprintf(stderr, "error: failed to sign manifest\n"); - - /* copy public key modulus and exponent to manifest */ - RSA_get0_key(priv_rsa, &n, &e, &d); - BN_bn2bin(n, mod); - BN_bn2bin(e, (unsigned char *)man->css_header.exponent); - - /* modulus is reveresd */ - for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN; i++) - man->css_header.modulus[i] - = mod[MAN_RSA_KEY_MODULUS_LEN - (1 + i)]; - - /* signature is reveresd, swap it */ - bytes_swap(man->css_header.signature, - sizeof(man->css_header.signature)); - - EVP_PKEY_free(privkey); - return ret; -} - -/* - * RSA signature of manifest. The signature is an PKCS - * #1-v1_5 of the entire manifest structure, including all - * extensions, and excluding the last 3 fields of the - * manifest header (Public Key, Exponent and Signature). - */ - -int pkcs_v1_5_sign_man_v1_8(struct image *image, - struct fw_image_manifest_v1_8 *man, - void *ptr1, unsigned int size1, void *ptr2, - unsigned int size2) -{ - RSA *priv_rsa = NULL; - EVP_PKEY *privkey; - FILE *fp; - const BIGNUM *n, *e, *d; - unsigned char digest[SHA256_DIGEST_LENGTH]; - unsigned char mod[MAN_RSA_KEY_MODULUS_LEN]; - unsigned int siglen = MAN_RSA_SIGNATURE_LEN; - char path[256]; - int ret = -EINVAL, i; - -#if DEBUG_PKCS - fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", - ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); -#endif - - /* create new key */ - privkey = EVP_PKEY_new(); - if (!privkey) - return -ENOMEM; - - /* load in RSA private key from PEM file */ - if (!image->key_name) { - snprintf(path, sizeof(path), "%s/otc_private_key.pem", PEM_KEY_PREFIX); - } else { - memset(path, 0, sizeof(path)); - strncpy(path, image->key_name, sizeof(path) - 1); - } - - fprintf(stdout, " pkcs: signing with key %s\n", path); - fp = fopen(path, "rb"); - if (!fp) { - fprintf(stderr, "error: can't open file %s %d\n", - path, -errno); - return -errno; - } - PEM_read_PrivateKey(fp, &privkey, NULL, NULL); - fclose(fp); - - /* validate RSA private key */ - priv_rsa = EVP_PKEY_get1_RSA(privkey); - if (RSA_check_key(priv_rsa)) { - fprintf(stdout, " pkcs: RSA private key is valid.\n"); - } else { - fprintf(stderr, "error: validating RSA private key.\n"); - return -EINVAL; - } - - /* calculate the digest */ - module_sha256_create(image); - module_sha_update(image, ptr1, size1); - module_sha_update(image, ptr2, size2); - module_sha_complete(image, digest); - - fprintf(stdout, " pkcs: digest for manifest is "); - for (i = 0; i < SHA256_DIGEST_LENGTH; i++) - fprintf(stdout, "%02x", digest[i]); - fprintf(stdout, "\n"); - - /* sign the manifest */ - ret = RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH, - (unsigned char *)man->css.signature, - &siglen, priv_rsa); - if (ret < 0) - fprintf(stderr, "error: failed to sign manifest\n"); - - /* copy public key modulus and exponent to manifest */ - RSA_get0_key(priv_rsa, &n, &e, &d); - BN_bn2bin(n, mod); - BN_bn2bin(e, (unsigned char *)man->css.exponent); - - /* modulus is reveresd */ - for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN; i++) - man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN - (1 + i)]; - - /* signature is reveresd, swap it */ - bytes_swap(man->css.signature, sizeof(man->css.signature)); - - EVP_PKEY_free(privkey); - return ret; -} - -int ri_manifest_sign_v1_5(struct image *image) -{ - struct fw_image_manifest_v1_5 *man = image->fw_image; - - pkcs_v1_5_sign_man_v1_5(image, man, - (void *)man + MAN_CSS_MAN_SIZE_V1_5, - image->image_end - sizeof(*man)); - return 0; -} - -int ri_manifest_sign_v1_8(struct image *image) -{ - struct fw_image_manifest_v1_8 *man = image->fw_image; - - pkcs_v1_5_sign_man_v1_8(image, man, (void *)man + MAN_CSS_HDR_OFFSET, - sizeof(struct css_header_v1_8) - - (MAN_RSA_KEY_MODULUS_LEN + - MAN_RSA_KEY_EXPONENT_LEN + - MAN_RSA_SIGNATURE_LEN), - (void *)man + MAN_SIG_PKG_OFFSET_V1_8, - (man->css.size - man->css.header_len) - * sizeof(uint32_t)); - return 0; -} diff --git a/rimage/plat_auth.c b/rimage/plat_auth.c deleted file mode 100644 index e8645611f327..000000000000 --- a/rimage/plat_auth.c +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood -// Keyon Jie - -#include "rimage.h" -#include "manifest.h" -#include "plat_auth.h" - -void ri_adsp_meta_data_create_v1_8(struct image *image, int meta_start_offset, - int meta_end_offset) -{ - struct sof_man_adsp_meta_file_ext_v1_8 *meta = - image->fw_image + meta_start_offset; - - fprintf(stdout, " meta: completing ADSP manifest\n"); - - meta->comp_desc[0].limit_offset = MAN_DESC_OFFSET_V1_8 + - image->image_end - meta_end_offset; - - fprintf(stdout, " meta: limit is 0x%x\n", - meta->comp_desc[0].limit_offset); - /* now hash the AdspFwBinaryDesc -> EOF */ -} - -void ri_adsp_meta_data_create_v2_5(struct image *image, int meta_start_offset, - int meta_end_offset) -{ - struct sof_man_adsp_meta_file_ext_v2_5 *meta = - image->fw_image + meta_start_offset; - - fprintf(stdout, " meta: completing ADSP manifest\n"); - - meta->comp_desc[0].limit_offset = MAN_DESC_OFFSET_V1_8 + - image->image_end - meta_end_offset; - - fprintf(stdout, " meta: limit is 0x%x\n", - meta->comp_desc[0].limit_offset); - /* now hash the AdspFwBinaryDesc -> EOF */ -} - -void ri_plat_ext_data_create(struct image *image) -{ - struct partition_info_ext *part = image->fw_image - + MAN_PART_INFO_OFFSET_V1_8; - struct sof_man_adsp_meta_file_ext_v1_8 *meta = - image->fw_image + MAN_META_EXT_OFFSET_V1_8; - struct sof_man_fw_desc *desc = image->fw_image + MAN_DESC_OFFSET_V1_8; - - fprintf(stdout, " auth: completing authentication manifest\n"); - - part->length = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; - part->length += MAN_PAGE_SIZE - (part->length % MAN_PAGE_SIZE); - - /* do this here atm */ - desc->header.preload_page_count = part->length / MAN_PAGE_SIZE; -} diff --git a/rimage/plat_auth.h b/rimage/plat_auth.h deleted file mode 100644 index 7e94f8ae12ba..000000000000 --- a/rimage/plat_auth.h +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - */ - -#ifndef __PLAT_AUTH_H__ -#define __PLAT_AUTH_H__ - -#include - -struct image; - -#define PLAT_AUTH_SHA256_LEN 32 -#define PLAT_AUTH_NAME_LEN 12 -#define PLAT_AUTH_PADDING 48 /* pad at end of struct */ - -#define SIGN_PKG_EXT_TYPE 15 -#define SIGN_PKG_NUM_MODULE 1 - -struct signed_pkg_info_module { - uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */ - uint8_t type; - uint8_t hash_algo; - uint16_t hash_size; - uint32_t meta_size; - uint8_t hash[PLAT_AUTH_SHA256_LEN]; -} __attribute__((packed)); - -struct signed_pkg_info_ext { - uint32_t ext_type; - uint32_t ext_len; - - uint8_t name[4]; - uint32_t vcn; - uint8_t bitmap[16]; - uint32_t svn; - uint8_t fw_type; - uint8_t fw_sub_type; - uint8_t reserved[14]; /* must be 0 */ - - /* variable length of modules */ - struct signed_pkg_info_module module[SIGN_PKG_NUM_MODULE]; -} __attribute__((packed)); - - -#define PART_INFO_EXT_TYPE 3 -#define PART_INFO_NUM_MODULE 1 - -struct partition_info_module { - uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */ - uint8_t type; - uint8_t reserved[3]; - uint32_t meta_size; - uint8_t hash[PLAT_AUTH_SHA256_LEN]; -} __attribute__((packed)); - -struct partition_info_ext { - uint32_t ext_type; - uint32_t ext_len; - - uint8_t name[4]; /* "ADSP" */ - uint32_t length; - uint8_t hash[PLAT_AUTH_SHA256_LEN]; - - uint32_t vcn; - uint32_t part_version; - uint32_t fmt_version; - uint32_t instance_id; - uint32_t part_flags; - uint8_t reserved[20]; /* must be 0 */ - - /* variable length of modules */ - struct partition_info_module module[PART_INFO_NUM_MODULE]; -} __attribute__((packed)); - - -#define PLAT_AUTH_SIZE \ - (sizeof(struct partition_info_ext) + \ - sizeof(struct signed_pkg_info_ext)) - -void ri_adsp_meta_data_create_v1_8(struct image *image, int meta_start_offset, - int meta_end_offset); -void ri_adsp_meta_data_create_v2_5(struct image *image, int meta_start_offset, - int meta_end_offset); -void ri_plat_ext_data_create(struct image *image); - -#endif diff --git a/rimage/rimage.c b/rimage/rimage.c deleted file mode 100644 index 6f94a2fd33d0..000000000000 --- a/rimage/rimage.c +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2015 Intel Corporation. All rights reserved. - -#include -#include -#include -#include -#include - -#include "rimage.h" -#include "file_format.h" -#include "manifest.h" - -static const struct adsp *machine[] = { - &machine_byt, - &machine_cht, - &machine_bsw, - &machine_hsw, - &machine_bdw, - &machine_apl, - &machine_cnl, - &machine_icl, - &machine_jsl, - &machine_tgl, - &machine_sue, - &machine_kbl, - &machine_skl, - &machine_imx8, - &machine_imx8x, - &machine_imx8m, -}; - -static void usage(char *name) -{ - fprintf(stdout, "%s:\t -m machine -o outfile -k [key] ELF files\n", - name); - fprintf(stdout, "\t -v enable verbose output\n"); - fprintf(stdout, "\t -r enable relocatable ELF files\n"); - fprintf(stdout, "\t -s MEU signing offset\n"); - fprintf(stdout, "\t -p log dictionary outfile\n"); - fprintf(stdout, "\t -i set IMR type\n"); - fprintf(stdout, "\t -x set xcc module offset\n"); - exit(0); -} - -int main(int argc, char *argv[]) -{ - struct image image; - const char *mach = NULL; - int opt, ret, i, elf_argc = 0; - int imr_type = MAN_DEFAULT_IMR_TYPE; - - memset(&image, 0, sizeof(image)); - - image.xcc_mod_offset = DEFAULT_XCC_MOD_OFFSET; - - while ((opt = getopt(argc, argv, "ho:p:m:vba:s:k:l:ri:x:")) != -1) { - switch (opt) { - case 'o': - image.out_file = optarg; - break; - case 'p': - image.ldc_out_file = optarg; - break; - case 'm': - mach = optarg; - break; - case 'v': - image.verbose = 1; - break; - case 's': - image.meu_offset = atoi(optarg); - break; - case 'a': - image.abi = atoi(optarg); - break; - case 'k': - image.key_name = optarg; - break; - case 'r': - image.reloc = 1; - break; - case 'i': - imr_type = atoi(optarg); - break; - case 'x': - image.xcc_mod_offset = atoi(optarg); - break; - case 'h': - usage(argv[0]); - break; - default: - break; - } - } - - elf_argc = optind; - - /* make sure we have an outfile and machine */ - if (!image.out_file || !mach) - usage(argv[0]); - - if (!image.ldc_out_file) - image.ldc_out_file = "out.ldc"; - - /* find machine */ - for (i = 0; i < ARRAY_SIZE(machine); i++) { - if (!strcmp(mach, machine[i]->name)) { - image.adsp = machine[i]; - goto found; - } - } - fprintf(stderr, "error: machine %s not found\n", mach); - fprintf(stderr, "error: available machines "); - for (i = 0; i < ARRAY_SIZE(machine); i++) - fprintf(stderr, "%s, ", machine[i]->name); - fprintf(stderr, "\n"); - - return -EINVAL; - -found: - - /* set IMR Type in found machine definition */ - if (image.adsp->man_v1_8) - image.adsp->man_v1_8->adsp_file_ext.imr_type = imr_type; - - if (image.adsp->man_v2_5) - image.adsp->man_v2_5->adsp_file_ext.imr_type = imr_type; - - /* parse input ELF files */ - image.num_modules = argc - elf_argc; - for (i = elf_argc; i < argc; i++) { - fprintf(stdout, "\nModule Reading %s\n", argv[i]); - ret = elf_parse_module(&image, i - elf_argc, argv[i]); - if (ret < 0) - goto out; - } - - /* validate all modules */ - ret = elf_validate_modules(&image); - if (ret < 0) - goto out; - - /* open outfile for writing */ - unlink(image.out_file); - image.out_fd = fopen(image.out_file, "wb"); - if (!image.out_fd) { - fprintf(stderr, "error: unable to open %s for writing %d\n", - image.out_file, errno); - ret = -EINVAL; - goto out; - } - - /* process and write output */ - if (image.meu_offset) - ret = image.adsp->write_firmware_meu(&image); - else - ret = image.adsp->write_firmware(&image); - - unlink(image.ldc_out_file); - image.ldc_out_fd = fopen(image.ldc_out_file, "wb"); - if (!image.ldc_out_fd) { - fprintf(stderr, "error: unable to open %s for writing %d\n", - image.ldc_out_file, errno); - ret = -EINVAL; - goto out; - } - ret = write_dictionaries(&image); -out: - /* close files */ - if (image.out_fd) - fclose(image.out_fd); - - if (image.ldc_out_fd) - fclose(image.ldc_out_fd); - - return ret; -} diff --git a/rimage/rimage.h b/rimage/rimage.h deleted file mode 100644 index 72992a0cbae5..000000000000 --- a/rimage/rimage.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2015-2018 Intel Corporation. All rights reserved. - */ - -#ifndef __RIMAGE_H__ -#define __RIMAGE_H__ - -#include "elf.h" - -#include -#include - -#include -#include -#include -#include - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#define MAX_MODULES 32 - -struct adsp; -struct manifest; -struct man_module; - -/* list of supported targets */ -enum machine_id { - MACHINE_BAYTRAIL = 0, - MACHINE_CHERRYTRAIL, - MACHINE_BRASWELL, - MACHINE_HASWELL, - MACHINE_BROADWELL, - MACHINE_APOLLOLAKE, - MACHINE_KABYLAKE, - MACHINE_SKYLAKE, - MACHINE_CANNONLAKE, - MACHINE_ICELAKE, - MACHINE_TIGERLAKE, - MACHINE_SUECREEK, - MACHINE_IMX8, - MACHINE_IMX8X, - MACHINE_IMX8M, - MACHINE_MAX -}; - -/* - * ELF module data - */ -struct module { - const char *elf_file; - FILE *fd; - - Elf32_Ehdr hdr; - Elf32_Shdr *section; - Elf32_Phdr *prg; - char *strings; - - uint32_t text_start; - uint32_t text_end; - uint32_t data_start; - uint32_t data_end; - uint32_t bss_start; - uint32_t bss_end; - uint32_t foffset; - - int num_sections; - int num_bss; - int fw_size; - int bss_index; - int logs_index; - int uids_index; - int fw_ready_index; - - /* sizes do not include any gaps */ - int bss_size; - int text_size; - int data_size; - - /* sizes do include gaps to nearest page */ - int bss_file_size; - int text_file_size; - int text_fixup_size; - int data_file_size; - - /* total file size */ - int file_size; - - /* executable header module */ - int exec_header; -}; - -/* - * Firmware image context. - */ -struct image { - - const char *out_file; - const char *ldc_out_file; - FILE *out_fd; - FILE *ldc_out_fd; - void *pos; - - const struct adsp *adsp; - int abi; - int verbose; - int reloc; /* ELF data is relocatable */ - int num_modules; - struct module module[MAX_MODULES]; - uint32_t image_end;/* module end, equal to output image size */ - int meu_offset; - int xcc_mod_offset; - - /* SHA 256 & 384 */ - const char *key_name; - EVP_MD_CTX *mdctx; - const EVP_MD *md; - - /* file IO */ - void *fw_image; - void *rom_image; - FILE *out_rom_fd; - FILE *out_man_fd; - FILE *out_unsigned_fd; - char out_rom_file[256]; - char out_man_file[256]; - char out_unsigned_file[256]; -}; - -struct mem_zone { - uint32_t base; - uint32_t size; - uint32_t host_offset; -}; - -/* - * Audio DSP descriptor and operations. - */ -struct adsp { - const char *name; - struct mem_zone mem_zones[SOF_FW_BLK_TYPE_NUM]; - - uint32_t image_size; - uint32_t dram_offset; - - enum machine_id machine_id; - int (*write_firmware)(struct image *image); - int (*write_firmware_meu)(struct image *image); - struct fw_image_manifest_v2_5 *man_v2_5; - struct fw_image_manifest_v1_8 *man_v1_8; - struct fw_image_manifest_v1_5 *man_v1_5; - struct fw_image_manifest_v1_5_sue *man_v1_5_sue; - int exec_boot_ldr; -}; - -int write_dictionaries(struct image *image); - -void module_sha256_create(struct image *image); -void module_sha_update(struct image *image, uint8_t *data, size_t bytes); -void module_sha_complete(struct image *image, uint8_t *hash); -int ri_manifest_sign_v1_5(struct image *image); -int ri_manifest_sign_v1_8(struct image *image); -void ri_sha256(struct image *image, unsigned int offset, unsigned int size, - uint8_t *hash); -void ri_sha384(struct image *image, unsigned int offset, unsigned int size, - uint8_t *hash); - -int pkcs_v1_5_sign_man_v1_5(struct image *image, - struct fw_image_manifest_v1_5 *man, - void *ptr1, unsigned int size1); -int pkcs_v1_5_sign_man_v1_8(struct image *image, - struct fw_image_manifest_v1_8 *man, - void *ptr1, unsigned int size1, void *ptr2, - unsigned int size2); - -int elf_parse_module(struct image *image, int module_index, const char *name); -void elf_free_module(struct image *image, int module_index); -int elf_is_rom(struct image *image, Elf32_Shdr *section); -int elf_validate_modules(struct image *image); -int elf_find_section(struct image *image, struct module *module, - const char *name); -int elf_validate_section(struct image *image, struct module *module, - Elf32_Shdr *section, int index); - -/* supported machines */ -extern const struct adsp machine_byt; -extern const struct adsp machine_cht; -extern const struct adsp machine_bsw; -extern const struct adsp machine_hsw; -extern const struct adsp machine_bdw; -extern const struct adsp machine_apl; -extern const struct adsp machine_cnl; -extern const struct adsp machine_icl; -extern const struct adsp machine_jsl; -extern const struct adsp machine_tgl; -extern const struct adsp machine_sue; -extern const struct adsp machine_skl; -extern const struct adsp machine_kbl; -extern const struct adsp machine_imx8; -extern const struct adsp machine_imx8x; -extern const struct adsp machine_imx8m; - -#endif diff --git a/scripts/README.docker b/scripts/README.docker deleted file mode 100644 index c51170e73fa9..000000000000 --- a/scripts/README.docker +++ /dev/null @@ -1,34 +0,0 @@ -The docker container provided in docker_build sets up a build environment for -building Sound Open Firmware. A working docker installation is needed to run -the docker build container. - -Note: In order to run docker as non sudo/root user please run. - -sudo usermod -aG docker your-user-name - -Then logout and login again. - -Quick Start: - -First, build the docker container. This step needs to be done initially and -when the toolchain or alsa dependencies are updated. - -cd scripts/docker_build - -./docker-build.sh - -After the container is built, it can be used to run the scripts. - -To build for baytrail: -./scripts/docker-run.sh ./scripts/xtensa-build-all.sh -l byt -or (may need password test0000 for rimage install) -./scripts/docker-run.sh ./scripts/xtensa-build-all.sh byt - -To rebuild the topology and logger: -./scripts/docker-run.sh ./scripts/build-tools.sh - -An incremental sof.git build: -./scripts/docker-run.sh make - -Or enter a shell: -./scripts/docker-run.sh bash diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000000..30441422899b --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,167 @@ +# SOF Helper Scripts + +This folder contains a lot of useful scripts that can speed up development for routine tasks or simplify execution of complex tasks. + +## Build Scripts + +SOF has several build targets depending on whether you are building firmware, tooling, documentation or topologies. This directory has a helper for each. + +### Firmware Build (`xtensa-build-zephyr.py`) + +Firmware can either be built using west commands directly or by the `xtensa-build-zephyr.py` script. This script wraps up the west commands and can build using either the Zephyr SDK compiler or the Cadence xtensa compiler for xtensa targets. + +Please run the script with `--help` to see all options. + +E.g to build SOF for Intel Pantherlake: + +1) Enable the python virtual environment for west. This should be in your SOF workspace installation directory. Default is `~/work/sof` (only needs run once). + +```bash +source ~/work/sof/.venv/bin/activate +``` + +2) Now run the build script. *Note: most build errors are a result of ingredients being out of sync with the west manifest. Please run `west update` and rebuild before fixing/reporting build errors.* + +```bash +./scripts/xtensa-build-zephyr.py -p ptl +``` + +### Reproducible Output Builds (`test-repro-build.sh`) + +This script can be used to locally reproduce the exact build steps and environment of specific CI validation tests. + +```bash +./scripts/test-repro-build.sh --help +``` + +## Tools and Topologies + +Tooling and topology can be built together using one script. To build all topologies please run: + +```bash +./scripts/build-tools.sh +``` + +**Options for `build-tools.sh`:** + +* `-c` : Rebuild `ctl/` tool +* `-l` : Rebuild `logger/` tool +* `-p` : Rebuild `probes/` tool +* `-T` : Rebuild ALL `topology/` targets +* `-X` : Rebuild topology1 only +* `-Y` : Rebuild topology2 only +* `-t` : Rebuild test topologies +* `-A` : Clone and rebuild the local ALSA git version for `alsa-lib` and `alsa-utils` with latest non-distro features. +* `-C` : No build, only CMake re-configuration. Shows CMake targets. + +*Warning: building tools is incremental by default. To build from scratch delete the `tools/build_tools` directory or use `-C`.* + +### ALSA Specific Build (`build-alsa-tools.sh`) + +If you want to pull down and explicitly recompile only the associated ALSA libraries from their public `alsa-lib` GitHub upstream independently of SOF topologies: + +```bash +./scripts/build-alsa-tools.sh +``` + +## Testbench and Emulation + +Testbench is a host application that is used to run SOF processing modules on developers PC. This allows for module development using regular host based tooling. + +### Rebuilding the Testbench (`rebuild-testbench.sh`) + +This script cleans and rebuilds the host test application binary. Ensure you supply the correct target platform wrapper or fuzzing backend. + +**Usage Options:** + +* `-p ` : Build testbench binary for `xt-run` for selected platform (e.g. `-p tgl`). When omitted, performs a `BUILD_TYPE=native`, compile-only check. +* `-f` : Build testbench via a compiler provided by a fuzzer (default path: `.../AFL/afl-gcc`). +* `-j` : Number of parallel make jobs (defaults to `nproc`). + +### Running the Testbench (`host-testbench.sh`) + +Starts the testing sequences. This invokes specific components to ensure basic inputs process without segfaults. + +```bash +./scripts/host-testbench.sh +``` + +### QEMU Check (`qemu-check.sh`) + +Automated verifier for executing firmware builds under QEMU emulation. + +**Usage:** + +```bash +./scripts/qemu-check.sh [platform(s)] +``` + +* Supported platforms are: `imx8`, `imx8x`, `imx8m`. +* Runs all supported platforms by default if none are provided. + +## SDK Support + +There is some SDK support in this directory for speeding up or simplifying tasks with multiple steps. + +### New Modules (`sdk-create-module.py`) + +A new module can be created by running the SDK Create Module script. This python helper copies the SOF template audio module and renames all strings, Cmakefiles, and Kconfigs automatically. It also correctly registers a new DSP UUID and TOML entries. + +Please run: + +```bash +./scripts/sdk-create-module.py new_module_name +``` + +## Docker + +The docker container provided in `docker_build` sets up a build environment for building Sound Open Firmware. A working docker installation is needed to run the docker build container. + +*Note: In order to run docker as non sudo/root user please run:* + +```bash +sudo usermod -aG docker your-user-name +``` + +Then logout and login again. + +**Quick Start:** + +First, build the docker container. This step needs to be done initially and when the toolchain or ALSA dependencies are updated. + +```bash +cd scripts/docker_build +./docker-build.sh +``` + +After the container is built, it can be used to run the scripts. + +To build for tigerlake: + +```bash +./scripts/docker-run.sh ./scripts/xtensa-build-all.sh -l tgl +``` + +or (this command may prompt for a password during rimage installation inside the container) + +```bash +./scripts/docker-run.sh ./scripts/xtensa-build-all.sh tgl +``` + +To rebuild the topology and logger: + +```bash +./scripts/docker-run.sh ./scripts/build-tools.sh +``` + +An incremental `sof.git` build: + +```bash +./scripts/docker-run.sh make +``` + +Or enter a shell: + +```bash +./scripts/docker-run.sh bash +``` diff --git a/scripts/build-alsa-tools.sh b/scripts/build-alsa-tools.sh new file mode 100755 index 000000000000..5e1e7f75d39d --- /dev/null +++ b/scripts/build-alsa-tools.sh @@ -0,0 +1,127 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2025 Intel Corporation. All rights reserved. + +# fail immediately on any errors +set -e + +# Array of ALSA Git repository URLs. Add or remove repositories as needed. +declare -a REPOS=( + "https://github.com/thesofproject/alsa-lib.git" + "https://github.com/thesofproject/alsa-utils.git" + # Add more repositories here... +) + +# Commit ID to check for (optional). If specified, the script will update +# the repository if this commit ID is not found. Leave empty to skip. +# This array order must align with REPO array above. +declare -a COMMIT_ID=( + "df8f1cc1ec9d9ee15be5e2c23ad25b9389fd8766" + "09550cd393b1a7d307ee6f26637b1ed7bd275e38" + # Add more IDs here... +) + +# Directory where repositories will be cloned/updated. +if [[ -z "$SOF_WORKSPACE" ]]; then + # Environment variable is empty or unset so use default + BASE_DIR="$HOME/work/sof" +else + # Environment variable exists and has a value + BASE_DIR="$SOF_WORKSPACE" +fi + +# Arguments to pass to ./configure for each repository. Add or remove +declare -a CONFIGURE_ARGS=( + "--prefix=${BASE_DIR}/tools" + "--prefix=${BASE_DIR}/tools \ + --with-alsa-prefix=${BASE_DIR}/tools \ + --with-alsa-inc-prefix=${BASE_DIR}/tools/include \ + --with-sysroot=${BASE_DIR}/tools \ + --with-udev-rules-dir=${BASE_DIR}/tools \ + PKG_CONFIG_PATH=${BASE_DIR}/tools \ + LDFLAGS=-L${BASE_DIR}/tools/lib \ + --with-asound-state-dir=${BASE_DIR}/tools/var/lib/alsa \ + --with-systemdsystemunitdir=${BASE_DIR}/tools/lib/systemd/system" +) + +# Arguments to pass to make for each repository. Add or remove arguments as needed. +declare -a TARGET_ARGS=( + "--disable-old-symbols" + "--enable-alsatopology" +) + +# Function to check if a commit ID exists in a repository +check_commit() { + local repo_dir="$1" + local commit_id="$2" + + if [ -z "$commit_id" ]; then + return 0 # Skip check if no commit ID is provided + fi + + if ! git -C "$repo_dir" rev-parse --quiet --verify "$commit_id" >/dev/null 2>&1; then + return 1 # Commit ID not found + else + return 0 # Commit ID found + fi +} + + +# Function to update the repository +update_repo() { + local repo_dir="$1" + echo "Updating repository: $repo_dir" + git -C "$repo_dir" fetch --all + git -C "$repo_dir" pull +} + +# Function to build and install the repository +build_and_install() { + local repo_dir="$1" + local configure_args="$2" + local target_args="$3" + + echo "Building and installing: $repo_dir $configure_args $target_args" + + if [ ! -f "$repo_dir/gitcompile" ]; then + echo "Error: gitcompile not found in $repo_dir" >&2 + exit 1 + fi + + # if Makefile exists then we can just run make + if [ ! -f "$repo_dir/Makefile" ]; then + (cd "$repo_dir" && ./gitcompile $configure_args $target_args) || \ + { echo "configure failed in $repo_dir"; exit 1; } + else + (cd "$repo_dir" && make -j) || { echo "make failed in $repo_dir"; exit 1; } + fi + + (cd "$repo_dir" && make install) || { echo "make install failed in $repo_dir"; exit 1; } + + echo "Build and installation complete for $repo_dir" +} + +# Main script logic +mkdir -p "$BASE_DIR" + +for ((i = 0; i < ${#REPOS[@]}; i++)); do + echo "Counter: $i, Value: ${REPOS[i]}" + repo_url=${REPOS[i]} + + repo_name=$(basename "$repo_url" .git) # Extract repo name + repo_dir="$BASE_DIR/$repo_name" + + if [ ! -d "$repo_dir" ]; then + echo "Cloning repository: $repo_url" + git clone "$repo_url" "$repo_dir" || { echo "git clone failed for $repo_url"; exit 1; } + elif ! check_commit "$repo_dir" "${COMMIT_ID[i]}"; then + update_repo "$repo_dir" + else + echo "Repository $repo_name is up to date." + fi + + build_and_install "$repo_dir" "${CONFIGURE_ARGS[i]}" + +done + +echo "All repositories processed." diff --git a/scripts/build-tools.sh b/scripts/build-tools.sh index 7d633592401a..6304265820cd 100755 --- a/scripts/build-tools.sh +++ b/scripts/build-tools.sh @@ -5,27 +5,176 @@ # fail immediately on any errors set -e -cd tools - -rm -rf build_tools - -mkdir build_tools -cd build_tools -cmake .. -make -j$(nproc) -for args in $@ -do - #build test topologies - if [[ "$args" == "-t" ]]; then - make tests -j$(nproc) - fi - #build fuzzer - if [[ "$args" == "-f" ]]; then - rm -rf build_fuzzer - mkdir build_fuzzer - cd build_fuzzer - cmake ../../fuzzer - make -j$(nproc) - cd ../ - fi -done +SOF_TOP=$(cd "$(dirname "$0")/.." && pwd) + +print_usage() +{ + cat < (the ugly bit) -# (c) 2007,2008, Andy Whitcroft (new conditions, test suite) -# (c) 2008-2010 Andy Whitcroft -# (c) 2010-2018 Joe Perches - -use strict; -use warnings; -use POSIX; -use File::Basename; -use Cwd 'abs_path'; -use Term::ANSIColor qw(:constants); -use Encode qw(decode encode); - -my $P = $0; -my $D = dirname(abs_path($P)); - -my $V = '0.32'; - -use Getopt::Long qw(:config no_auto_abbrev); - -my $SOF = 1; # enables SOF-specific behaviour -my $quiet = 0; -my $tree = 1; -my $chk_signoff = 1; -my $chk_patch = 1; -my $tst_only; -my $emacs = 0; -my $terse = 0; -my $showfile = 0; -my $file = 0; -my $git = 0; -my %git_commits = (); -my $check = 0; -my $check_orig = 0; -my $summary = 1; -my $mailback = 0; -my $summary_file = 0; -my $show_types = 0; -my $list_types = 0; -my $fix = 0; -my $fix_inplace = 0; -my $root; -my %debug; -my %camelcase = (); -my %use_type = (); -my @use = (); -my %ignore_type = (); -my @ignore = (); -my $help = 0; -my $configuration_file = ".checkpatch.conf"; -my $max_line_length = 80; -my $ignore_perl_version = 0; -my $minimum_perl_version = 5.10.0; -my $min_conf_desc_length = 4; -my $spelling_file = "$D/spelling.txt"; -my $codespell = 0; -my $codespellfile = "/usr/share/codespell/dictionary.txt"; -my $conststructsfile = "$D/const_structs.checkpatch"; -my $typedefsfile = ""; -my $color = "auto"; -my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE -# git output parsing needs US English output, so first set backtick child process LANGUAGE -my $git_command ='export LANGUAGE=en_US.UTF-8; git'; - -sub help { - my ($exitcode) = @_; - - print << "EOM"; -Usage: $P [OPTION]... [FILE]... -Version: $V - -Options: - -q, --quiet quiet - --no-tree run without a kernel tree - --no-signoff do not check for 'Signed-off-by' line - --patch treat FILE as patchfile (default) - --emacs emacs compile window format - --terse one line per report - --showfile emit diffed file position, not input file position - -g, --git treat FILE as a single commit or git revision range - single git commit with: - - ^ - ~n - multiple git commits with: - .. - ... - - - git merges are ignored - -f, --file treat FILE as regular source file - --subjective, --strict enable more subjective tests - --list-types list the possible message types - --types TYPE(,TYPE2...) show only these comma separated message types - --ignore TYPE(,TYPE2...) ignore various comma separated message types - --show-types show the specific message type in the output - --max-line-length=n set the maximum line length, if exceeded, warn - --min-conf-desc-length=n set the min description length, if shorter, warn - --root=PATH PATH to the kernel tree root - --no-summary suppress the per-file summary - --mailback only produce a report in case of warnings/errors - --summary-file include the filename in summary - --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of - 'values', 'possible', 'type', and 'attr' (default - is all off) - --test-only=WORD report only warnings/errors containing WORD - literally - --fix EXPERIMENTAL - may create horrible results - If correctable single-line errors exist, create - ".EXPERIMENTAL-checkpatch-fixes" - with potential errors corrected to the preferred - checkpatch style - --fix-inplace EXPERIMENTAL - may create horrible results - Is the same as --fix, but overwrites the input - file. It's your fault if there's no backup or git - --ignore-perl-version override checking of perl version. expect - runtime errors. - --codespell Use the codespell dictionary for spelling/typos - (default:/usr/share/codespell/dictionary.txt) - --codespellfile Use this codespell dictionary - --typedefsfile Read additional types from this file - --color[=WHEN] Use colors 'always', 'never', or only when output - is a terminal ('auto'). Default is 'auto'. - -h, --help, --version display this help and exit - -When FILE is - read standard input. -EOM - - exit($exitcode); -} - -sub uniq { - my %seen; - return grep { !$seen{$_}++ } @_; -} - -sub list_types { - my ($exitcode) = @_; - - my $count = 0; - - local $/ = undef; - - open(my $script, '<', abs_path($P)) or - die "$P: Can't read '$P' $!\n"; - - my $text = <$script>; - close($script); - - my @types = (); - # Also catch when type or level is passed through a variable - for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) { - push (@types, $_); - } - @types = sort(uniq(@types)); - print("#\tMessage type\n\n"); - foreach my $type (@types) { - print(++$count . "\t" . $type . "\n"); - } - - exit($exitcode); -} - -my $conf = which_conf($configuration_file); -if (-f $conf) { - my @conf_args; - open(my $conffile, '<', "$conf") - or warn "$P: Can't find a readable $configuration_file file $!\n"; - - while (<$conffile>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - $line =~ s/\s+/ /g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my @words = split(" ", $line); - foreach my $word (@words) { - last if ($word =~ m/^#/); - push (@conf_args, $word); - } - } - close($conffile); - unshift(@ARGV, @conf_args) if @conf_args; -} - -# Perl's Getopt::Long allows options to take optional arguments after a space. -# Prevent --color by itself from consuming other arguments -foreach (@ARGV) { - if ($_ eq "--color" || $_ eq "-color") { - $_ = "--color=$color"; - } -} - -GetOptions( - 'q|quiet+' => \$quiet, - 'tree!' => \$tree, - 'signoff!' => \$chk_signoff, - 'patch!' => \$chk_patch, - 'emacs!' => \$emacs, - 'terse!' => \$terse, - 'showfile!' => \$showfile, - 'f|file!' => \$file, - 'g|git!' => \$git, - 'subjective!' => \$check, - 'strict!' => \$check, - 'ignore=s' => \@ignore, - 'types=s' => \@use, - 'show-types!' => \$show_types, - 'list-types!' => \$list_types, - 'max-line-length=i' => \$max_line_length, - 'min-conf-desc-length=i' => \$min_conf_desc_length, - 'root=s' => \$root, - 'summary!' => \$summary, - 'mailback!' => \$mailback, - 'summary-file!' => \$summary_file, - 'fix!' => \$fix, - 'fix-inplace!' => \$fix_inplace, - 'ignore-perl-version!' => \$ignore_perl_version, - 'debug=s' => \%debug, - 'test-only=s' => \$tst_only, - 'codespell!' => \$codespell, - 'codespellfile=s' => \$codespellfile, - 'typedefsfile=s' => \$typedefsfile, - 'color=s' => \$color, - 'no-color' => \$color, #keep old behaviors of -nocolor - 'nocolor' => \$color, #keep old behaviors of -nocolor - 'h|help' => \$help, - 'version' => \$help -) or help(1); - -help(0) if ($help); - -list_types(0) if ($list_types); - -$fix = 1 if ($fix_inplace); -$check_orig = $check; - -my $exit = 0; - -my $perl_version_ok = 1; -if ($^V && $^V lt $minimum_perl_version) { - $perl_version_ok = 0; - printf "$P: requires at least perl version %vd\n", $minimum_perl_version; - exit(1) if (!$ignore_perl_version); -} - -#if no filenames are given, push '-' to read patch from stdin -if ($#ARGV < 0) { - push(@ARGV, '-'); -} - -if ($color =~ /^[01]$/) { - $color = !$color; -} elsif ($color =~ /^always$/i) { - $color = 1; -} elsif ($color =~ /^never$/i) { - $color = 0; -} elsif ($color =~ /^auto$/i) { - $color = (-t STDOUT); -} else { - die "Invalid color mode: $color\n"; -} - -sub hash_save_array_words { - my ($hashRef, $arrayRef) = @_; - - my @array = split(/,/, join(',', @$arrayRef)); - foreach my $word (@array) { - $word =~ s/\s*\n?$//g; - $word =~ s/^\s*//g; - $word =~ s/\s+/ /g; - $word =~ tr/[a-z]/[A-Z]/; - - next if ($word =~ m/^\s*#/); - next if ($word =~ m/^\s*$/); - - $hashRef->{$word}++; - } -} - -sub hash_show_words { - my ($hashRef, $prefix) = @_; - - if (keys %$hashRef) { - print "\nNOTE: $prefix message types:"; - foreach my $word (sort keys %$hashRef) { - print " $word"; - } - print "\n"; - } -} - -hash_save_array_words(\%ignore_type, \@ignore); -hash_save_array_words(\%use_type, \@use); - -my $dbg_values = 0; -my $dbg_possible = 0; -my $dbg_type = 0; -my $dbg_attr = 0; -for my $key (keys %debug) { - ## no critic - eval "\${dbg_$key} = '$debug{$key}';"; - die "$@" if ($@); -} - -my $rpt_cleaners = 0; - -if ($terse) { - $emacs = 1; - $quiet++; -} - -if ($tree) { - if (defined $root) { - if (!top_of_kernel_tree($root)) { - die "$P: $root: --root does not point at a valid tree\n"; - } - } else { - if (top_of_kernel_tree('.')) { - $root = '.'; - } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && - top_of_kernel_tree($1)) { - $root = $1; - } - } - - if (!defined $root) { - print "Must be run from the top-level dir. of a kernel tree\n"; - exit(2); - } -} - -my $emitted_corrupt = 0; - -our $Ident = qr{ - [A-Za-z_][A-Za-z\d_]* - (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* - }x; -our $Storage = qr{extern|static|asmlinkage}; -our $Sparse = qr{ - __user| - __kernel| - __force| - __iomem| - __must_check| - __kprobes| - __ref| - __refconst| - __refdata| - __rcu| - __private - }x; -our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; -our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; -our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; -our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; -our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; - -# Notes to $Attribute: -# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check -our $Attribute = qr{ - const| - __percpu| - __nocast| - __safe| - __bitwise| - __packed__| - __packed2__| - __naked| - __maybe_unused| - __always_unused| - __noreturn| - __used| - __cold| - __pure| - __noclone| - __deprecated| - __read_mostly| - __ro_after_init| - __kprobes| - $InitAttribute| - ____cacheline_aligned| - ____cacheline_aligned_in_smp| - ____cacheline_internodealigned_in_smp| - __weak - }x; -our $Modifier; -our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; -our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; -our $Lval = qr{$Ident(?:$Member)*}; - -our $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; -our $Binary = qr{(?i)0b[01]+$Int_type?}; -our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; -our $Int = qr{[0-9]+$Int_type?}; -our $Octal = qr{0[0-7]+$Int_type?}; -our $String = qr{"[X\t]*"}; -our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; -our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; -our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; -our $Float = qr{$Float_hex|$Float_dec|$Float_int}; -our $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; -our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; -our $Compare = qr{<=|>=|==|!=|<|(?}; -our $Arithmetic = qr{\+|-|\*|\/|%}; -our $Operators = qr{ - <=|>=|==|!=| - =>|->|<<|>>|<|>|!|~| - &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic - }x; - -our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; - -our $BasicType; -our $NonptrType; -our $NonptrTypeMisordered; -our $NonptrTypeWithAttr; -our $Type; -our $TypeMisordered; -our $Declare; -our $DeclareMisordered; - -our $NON_ASCII_UTF8 = qr{ - [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte - | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs - | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte - | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates - | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 - | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 - | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 -}x; - -our $UTF8 = qr{ - [\x09\x0A\x0D\x20-\x7E] # ASCII - | $NON_ASCII_UTF8 -}x; - -our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; -our $typeOtherOSTypedefs = qr{(?x: - u_(?:char|short|int|long) | # bsd - u(?:nchar|short|int|long) # sysv -)}; -our $typeKernelTypedefs = qr{(?x: - (?:__)?(?:u|s|be|le)(?:8|16|32|64)| - atomic_t -)}; -our $typeTypedefs = qr{(?x: - $typeC99Typedefs\b| - $typeOtherOSTypedefs\b| - $typeKernelTypedefs\b -)}; - -our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; - -our $logFunctions = qr{(?x: - printk(?:_ratelimited|_once|_deferred_once|_deferred|)| - (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| - TP_printk| - WARN(?:_RATELIMIT|_ONCE|)| - panic| - MODULE_[A-Z_]+| - seq_vprintf|seq_printf|seq_puts| - trace[a-z_]+ -)}; - -our $allocFunctions = qr{(?x: - (?:(?:devm_)? - (?:kv|k|v)[czm]alloc(?:_node|_array)? | - kstrdup(?:_const)? | - kmemdup(?:_nul)?) | - (?:\w+)?alloc_skb(?:ip_align)? | - # dev_alloc_skb/netdev_alloc_skb, et al - dma_alloc_coherent -)}; - -our $signature_tags = qr{(?xi: - Signed-off-by:| - Co-developed-by:| - Acked-by:| - Tested-by:| - Reviewed-by:| - Reported-by:| - Suggested-by:| - To:| - Cc: -)}; - -our @typeListMisordered = ( - qr{char\s+(?:un)?signed}, - qr{int\s+(?:(?:un)?signed\s+)?short\s}, - qr{int\s+short(?:\s+(?:un)?signed)}, - qr{short\s+int(?:\s+(?:un)?signed)}, - qr{(?:un)?signed\s+int\s+short}, - qr{short\s+(?:un)?signed}, - qr{long\s+int\s+(?:un)?signed}, - qr{int\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed\s+int}, - qr{int\s+(?:un)?signed\s+long}, - qr{int\s+(?:un)?signed}, - qr{int\s+long\s+long\s+(?:un)?signed}, - qr{long\s+long\s+int\s+(?:un)?signed}, - qr{long\s+long\s+(?:un)?signed\s+int}, - qr{long\s+long\s+(?:un)?signed}, - qr{long\s+(?:un)?signed}, -); - -our @typeList = ( - qr{void}, - qr{(?:(?:un)?signed\s+)?char}, - qr{(?:(?:un)?signed\s+)?short\s+int}, - qr{(?:(?:un)?signed\s+)?short}, - qr{(?:(?:un)?signed\s+)?int}, - qr{(?:(?:un)?signed\s+)?long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, - qr{(?:(?:un)?signed\s+)?long\s+long}, - qr{(?:(?:un)?signed\s+)?long}, - qr{(?:un)?signed}, - qr{float}, - qr{double}, - qr{bool}, - qr{struct\s+$Ident}, - qr{union\s+$Ident}, - qr{enum\s+$Ident}, - qr{${Ident}_t}, - qr{${Ident}_handler}, - qr{${Ident}_handler_fn}, - @typeListMisordered, -); - -our $C90_int_types = qr{(?x: - long\s+long\s+int\s+(?:un)?signed| - long\s+long\s+(?:un)?signed\s+int| - long\s+long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+long\s+int| - (?:(?:un)?signed\s+)?long\s+long| - int\s+long\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long\s+long| - - long\s+int\s+(?:un)?signed| - long\s+(?:un)?signed\s+int| - long\s+(?:un)?signed| - (?:(?:un)?signed\s+)?long\s+int| - (?:(?:un)?signed\s+)?long| - int\s+long\s+(?:un)?signed| - int\s+(?:(?:un)?signed\s+)?long| - - int\s+(?:un)?signed| - (?:(?:un)?signed\s+)?int -)}; - -our @typeListFile = (); -our @typeListWithAttr = ( - @typeList, - qr{struct\s+$InitAttribute\s+$Ident}, - qr{union\s+$InitAttribute\s+$Ident}, -); - -our @modifierList = ( - qr{fastcall}, -); -our @modifierListFile = (); - -our @mode_permission_funcs = ( - ["module_param", 3], - ["module_param_(?:array|named|string)", 4], - ["module_param_array_named", 5], - ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], - ["proc_create(?:_data|)", 2], - ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2], - ["IIO_DEV_ATTR_[A-Z_]+", 1], - ["SENSOR_(?:DEVICE_|)ATTR_2", 2], - ["SENSOR_TEMPLATE(?:_2|)", 3], - ["__ATTR", 2], -); - -#Create a search pattern for all these functions to speed up a loop below -our $mode_perms_search = ""; -foreach my $entry (@mode_permission_funcs) { - $mode_perms_search .= '|' if ($mode_perms_search ne ""); - $mode_perms_search .= $entry->[0]; -} -$mode_perms_search = "(?:${mode_perms_search})"; - -our %deprecated_apis = ( - "synchronize_rcu_bh" => "synchronize_rcu", - "synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited", - "call_rcu_bh" => "call_rcu", - "rcu_barrier_bh" => "rcu_barrier", - "synchronize_sched" => "synchronize_rcu", - "synchronize_sched_expedited" => "synchronize_rcu_expedited", - "call_rcu_sched" => "call_rcu", - "rcu_barrier_sched" => "rcu_barrier", - "get_state_synchronize_sched" => "get_state_synchronize_rcu", - "cond_synchronize_sched" => "cond_synchronize_rcu", -); - -#Create a search pattern for all these strings to speed up a loop below -our $deprecated_apis_search = ""; -foreach my $entry (keys %deprecated_apis) { - $deprecated_apis_search .= '|' if ($deprecated_apis_search ne ""); - $deprecated_apis_search .= $entry; -} -$deprecated_apis_search = "(?:${deprecated_apis_search})"; - -our $mode_perms_world_writable = qr{ - S_IWUGO | - S_IWOTH | - S_IRWXUGO | - S_IALLUGO | - 0[0-7][0-7][2367] -}x; - -our %mode_permission_string_types = ( - "S_IRWXU" => 0700, - "S_IRUSR" => 0400, - "S_IWUSR" => 0200, - "S_IXUSR" => 0100, - "S_IRWXG" => 0070, - "S_IRGRP" => 0040, - "S_IWGRP" => 0020, - "S_IXGRP" => 0010, - "S_IRWXO" => 0007, - "S_IROTH" => 0004, - "S_IWOTH" => 0002, - "S_IXOTH" => 0001, - "S_IRWXUGO" => 0777, - "S_IRUGO" => 0444, - "S_IWUGO" => 0222, - "S_IXUGO" => 0111, -); - -#Create a search pattern for all these strings to speed up a loop below -our $mode_perms_string_search = ""; -foreach my $entry (keys %mode_permission_string_types) { - $mode_perms_string_search .= '|' if ($mode_perms_string_search ne ""); - $mode_perms_string_search .= $entry; -} -our $single_mode_perms_string_search = "(?:${mode_perms_string_search})"; -our $multi_mode_perms_string_search = qr{ - ${single_mode_perms_string_search} - (?:\s*\|\s*${single_mode_perms_string_search})* -}x; - -sub perms_to_octal { - my ($string) = @_; - - return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/); - - my $val = ""; - my $oval = ""; - my $to = 0; - my $curpos = 0; - my $lastpos = 0; - while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) { - $curpos = pos($string); - my $match = $2; - my $omatch = $1; - last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos)); - $lastpos = $curpos; - $to |= $mode_permission_string_types{$match}; - $val .= '\s*\|\s*' if ($val ne ""); - $val .= $match; - $oval .= $omatch; - } - $oval =~ s/^\s*\|\s*//; - $oval =~ s/\s*\|\s*$//; - return sprintf("%04o", $to); -} - -our $allowed_asm_includes = qr{(?x: - irq| - memory| - time| - reboot -)}; -# memory.h: ARM has a custom one - -# Load common spelling mistakes and build regular expression list. -my $misspellings; -my %spelling_fix; - -if (open(my $spelling, '<', $spelling_file)) { - while (<$spelling>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - - my ($suspect, $fix) = split(/\|\|/, $line); - - $spelling_fix{$suspect} = $fix; - } - close($spelling); -} else { - warn "No typos will be found - file '$spelling_file': $!\n"; -} - -if ($codespell) { - if (open(my $spelling, '<', $codespellfile)) { - while (<$spelling>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - next if ($line =~ m/, disabled/i); - - $line =~ s/,.*$//; - - my ($suspect, $fix) = split(/->/, $line); - - $spelling_fix{$suspect} = $fix; - } - close($spelling); - } else { - warn "No codespell typos will be found - file '$codespellfile': $!\n"; - } -} - -$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; - -sub read_words { - my ($wordsRef, $file) = @_; - - if (open(my $words, '<', $file)) { - while (<$words>) { - my $line = $_; - - $line =~ s/\s*\n?$//g; - $line =~ s/^\s*//g; - - next if ($line =~ m/^\s*#/); - next if ($line =~ m/^\s*$/); - if ($line =~ /\s/) { - print("$file: '$line' invalid - ignored\n"); - next; - } - - $$wordsRef .= '|' if ($$wordsRef ne ""); - $$wordsRef .= $line; - } - close($file); - return 1; - } - - return 0; -} - -my $const_structs = ""; -read_words(\$const_structs, $conststructsfile) - or warn "No structs that should be const will be found - file '$conststructsfile': $!\n"; - -my $typeOtherTypedefs = ""; -if (length($typedefsfile)) { - read_words(\$typeOtherTypedefs, $typedefsfile) - or warn "No additional types will be considered - file '$typedefsfile': $!\n"; -} -$typeTypedefs .= '|' . $typeOtherTypedefs if ($typeOtherTypedefs ne ""); - -sub build_types { - my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; - my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; - my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; - my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; - $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; - $BasicType = qr{ - (?:$typeTypedefs\b)| - (?:${all}\b) - }x; - $NonptrType = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${all}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeMisordered = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:${Misordered}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $NonptrTypeWithAttr = qr{ - (?:$Modifier\s+|const\s+)* - (?: - (?:typeof|__typeof__)\s*\([^\)]*\)| - (?:$typeTypedefs\b)| - (?:${allWithAttr}\b) - ) - (?:\s+$Modifier|\s+const)* - }x; - $Type = qr{ - $NonptrType - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $TypeMisordered = qr{ - $NonptrTypeMisordered - (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? - (?:\s+$Inline|\s+$Modifier)* - }x; - $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; - $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; -} -build_types(); - -our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; - -# Using $balanced_parens, $LvalOrFunc, or $FuncArg -# requires at least perl version v5.10.0 -# Any use must be runtime checked with $^V - -our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; -our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; -our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; - -our $declaration_macros = qr{(?x: - (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| - (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(| - (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(| - (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\( -)}; - -sub deparenthesize { - my ($string) = @_; - return "" if (!defined($string)); - - while ($string =~ /^\s*\(.*\)\s*$/) { - $string =~ s@^\s*\(\s*@@; - $string =~ s@\s*\)\s*$@@; - } - - $string =~ s@\s+@ @g; - - return $string; -} - -sub seed_camelcase_file { - my ($file) = @_; - - return if (!(-f $file)); - - local $/; - - open(my $include_file, '<', "$file") - or warn "$P: Can't read '$file' $!\n"; - my $text = <$include_file>; - close($include_file); - - my @lines = split('\n', $text); - - foreach my $line (@lines) { - next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); - if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { - $camelcase{$1} = 1; - } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { - $camelcase{$1} = 1; - } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { - $camelcase{$1} = 1; - } - } -} - -sub is_maintained_obsolete { - my ($filename) = @_; - - return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl")); - - my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`; - - return $status =~ /obsolete/i; -} - -sub is_SPDX_License_valid { - my ($license) = @_; - - return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$root/.git")); - - my $root_path = abs_path($root); - my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`; - return 0 if ($status ne ""); - return 1; -} - -my $camelcase_seeded = 0; -sub seed_camelcase_includes { - return if ($camelcase_seeded); - - my $files; - my $camelcase_cache = ""; - my @include_files = (); - - $camelcase_seeded = 1; - - if (-e ".git") { - my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`; - chomp $git_last_include_commit; - $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; - } else { - my $last_mod_date = 0; - $files = `find $root/include -name "*.h"`; - @include_files = split('\n', $files); - foreach my $file (@include_files) { - my $date = POSIX::strftime("%Y%m%d%H%M", - localtime((stat $file)[9])); - $last_mod_date = $date if ($last_mod_date < $date); - } - $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; - } - - if ($camelcase_cache ne "" && -f $camelcase_cache) { - open(my $camelcase_file, '<', "$camelcase_cache") - or warn "$P: Can't read '$camelcase_cache' $!\n"; - while (<$camelcase_file>) { - chomp; - $camelcase{$_} = 1; - } - close($camelcase_file); - - return; - } - - if (-e ".git") { - $files = `${git_command} ls-files "include/*.h"`; - @include_files = split('\n', $files); - } - - foreach my $file (@include_files) { - seed_camelcase_file($file); - } - - if ($camelcase_cache ne "") { - unlink glob ".checkpatch-camelcase.*"; - open(my $camelcase_file, '>', "$camelcase_cache") - or warn "$P: Can't write '$camelcase_cache' $!\n"; - foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { - print $camelcase_file ("$_\n"); - } - close($camelcase_file); - } -} - -sub git_commit_info { - my ($commit, $id, $desc) = @_; - - return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); - - my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`; - $output =~ s/^\s*//gm; - my @lines = split("\n", $output); - - return ($id, $desc) if ($#lines < 0); - - if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) { -# Maybe one day convert this block of bash into something that returns -# all matching commit ids, but it's very slow... -# -# echo "checking commits $1..." -# git rev-list --remotes | grep -i "^$1" | -# while read line ; do -# git log --format='%H %s' -1 $line | -# echo "commit $(cut -c 1-12,41-)" -# done - } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { - $id = undef; - } else { - $id = substr($lines[0], 0, 12); - $desc = substr($lines[0], 41); - } - - return ($id, $desc); -} - -$chk_signoff = 0 if ($file); - -my @rawlines = (); -my @lines = (); -my @fixed = (); -my @fixed_inserted = (); -my @fixed_deleted = (); -my $fixlinenr = -1; - -# If input is git commits, extract all commits from the commit expressions. -# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'. -die "$P: No git repository found\n" if ($git && !-e ".git"); - -if ($git) { - my @commits = (); - foreach my $commit_expr (@ARGV) { - my $git_range; - if ($commit_expr =~ m/^(.*)-(\d+)$/) { - $git_range = "-$2 $1"; - } elsif ($commit_expr =~ m/\.\./) { - $git_range = "$commit_expr"; - } else { - $git_range = "-1 $commit_expr"; - } - my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`; - foreach my $line (split(/\n/, $lines)) { - $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/; - next if (!defined($1) || !defined($2)); - my $sha1 = $1; - my $subject = $2; - unshift(@commits, $sha1); - $git_commits{$sha1} = $subject; - } - } - die "$P: no git commits after extraction!\n" if (@commits == 0); - @ARGV = @commits; -} - -my $vname; -$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"}; -for my $filename (@ARGV) { - my $FILE; - if ($git) { - open($FILE, '-|', "git format-patch -M --stdout -1 $filename") || - die "$P: $filename: git format-patch failed - $!\n"; - } elsif ($file) { - open($FILE, '-|', "diff -u /dev/null $filename") || - die "$P: $filename: diff failed - $!\n"; - } elsif ($filename eq '-') { - open($FILE, '<&STDIN'); - } else { - open($FILE, '<', "$filename") || - die "$P: $filename: open failed - $!\n"; - } - if ($filename eq '-') { - $vname = 'Your patch'; - } elsif ($git) { - $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")'; - } else { - $vname = $filename; - } - while (<$FILE>) { - chomp; - push(@rawlines, $_); - } - close($FILE); - - if ($#ARGV > 0 && $quiet == 0) { - print '-' x length($vname) . "\n"; - print "$vname\n"; - print '-' x length($vname) . "\n"; - } - - if (!process($filename)) { - $exit = 1; - } - @rawlines = (); - @lines = (); - @fixed = (); - @fixed_inserted = (); - @fixed_deleted = (); - $fixlinenr = -1; - @modifierListFile = (); - @typeListFile = (); - build_types(); -} - -if (!$quiet) { - hash_show_words(\%use_type, "Used"); - hash_show_words(\%ignore_type, "Ignored"); - - if (!$perl_version_ok) { - print << "EOM" - -NOTE: perl $^V is not modern enough to detect all possible issues. - An upgrade to at least perl $minimum_perl_version is suggested. -EOM - } - if ($exit) { - print << "EOM" - -NOTE: If any of the errors are false positives, please report - them to the maintainer, see CHECKPATCH in MAINTAINERS. -EOM - } -} - -exit($exit); - -sub top_of_kernel_tree { - my ($root) = @_; - - my @tree_check = ( - "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", - "README", "Documentation", "arch", "include", "drivers", - "fs", "init", "ipc", "kernel", "lib", "scripts", - ); - - foreach my $check (@tree_check) { - if (! -e $root . '/' . $check) { - return 0; - } - } - return 1; -} - -sub parse_email { - my ($formatted_email) = @_; - - my $name = ""; - my $address = ""; - my $comment = ""; - - if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { - $name = $1; - $address = $2; - $comment = $3 if defined $3; - } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { - $address = $1; - $comment = $2 if defined $2; - $formatted_email =~ s/\Q$address\E.*$//; - $name = $formatted_email; - $name = trim($name); - $name =~ s/^\"|\"$//g; - # If there's a name left after stripping spaces and - # leading quotes, and the address doesn't have both - # leading and trailing angle brackets, the address - # is invalid. ie: - # "joe smith joe@smith.com" bad - # "joe smith ]+>$/) { - $name = ""; - $address = ""; - $comment = ""; - } - } - - $name = trim($name); - $name =~ s/^\"|\"$//g; - $address = trim($address); - $address =~ s/^\<|\>$//g; - - if ($name =~ /[^\w \-]/i) { ##has "must quote" chars - $name =~ s/(?"; - } - - return $formatted_email; -} - -sub which { - my ($bin) = @_; - - foreach my $path (split(/:/, $ENV{PATH})) { - if (-e "$path/$bin") { - return "$path/$bin"; - } - } - - return ""; -} - -sub which_conf { - my ($conf) = @_; - - foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { - if (-e "$path/$conf") { - return "$path/$conf"; - } - } - - return ""; -} - -sub expand_tabs { - my ($str) = @_; - - my $res = ''; - my $n = 0; - for my $c (split(//, $str)) { - if ($c eq "\t") { - $res .= ' '; - $n++; - for (; ($n % 8) != 0; $n++) { - $res .= ' '; - } - next; - } - $res .= $c; - $n++; - } - - return $res; -} -sub copy_spacing { - (my $res = shift) =~ tr/\t/ /c; - return $res; -} - -sub line_stats { - my ($line) = @_; - - # Drop the diff line leader and expand tabs - $line =~ s/^.//; - $line = expand_tabs($line); - - # Pick the indent from the front of the line. - my ($white) = ($line =~ /^(\s*)/); - - return (length($line), length($white)); -} - -my $sanitise_quote = ''; - -sub sanitise_line_reset { - my ($in_comment) = @_; - - if ($in_comment) { - $sanitise_quote = '*/'; - } else { - $sanitise_quote = ''; - } -} -sub sanitise_line { - my ($line) = @_; - - my $res = ''; - my $l = ''; - - my $qlen = 0; - my $off = 0; - my $c; - - # Always copy over the diff marker. - $res = substr($line, 0, 1); - - for ($off = 1; $off < length($line); $off++) { - $c = substr($line, $off, 1); - - # Comments we are whacking completely including the begin - # and end, all to $;. - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { - $sanitise_quote = '*/'; - - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { - $sanitise_quote = ''; - substr($res, $off, 2, "$;$;"); - $off++; - next; - } - if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { - $sanitise_quote = '//'; - - substr($res, $off, 2, $sanitise_quote); - $off++; - next; - } - - # A \ in a string means ignore the next character. - if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && - $c eq "\\") { - substr($res, $off, 2, 'XX'); - $off++; - next; - } - # Regular quotes. - if ($c eq "'" || $c eq '"') { - if ($sanitise_quote eq '') { - $sanitise_quote = $c; - - substr($res, $off, 1, $c); - next; - } elsif ($sanitise_quote eq $c) { - $sanitise_quote = ''; - } - } - - #print "c<$c> SQ<$sanitise_quote>\n"; - if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { - substr($res, $off, 1, $;); - } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { - substr($res, $off, 1, 'X'); - } else { - substr($res, $off, 1, $c); - } - } - - if ($sanitise_quote eq '//') { - $sanitise_quote = ''; - } - - # The pathname on a #include may be surrounded by '<' and '>'. - if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { - my $clean = 'X' x length($1); - $res =~ s@\<.*\>@<$clean>@; - - # The whole of a #error is a string. - } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { - my $clean = 'X' x length($1); - $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; - } - - if ($allow_c99_comments && $res =~ m@(//.*$)@) { - my $match = $1; - $res =~ s/\Q$match\E/"$;" x length($match)/e; - } - - return $res; -} - -sub get_quoted_string { - my ($line, $rawline) = @_; - - return "" if (!defined($line) || !defined($rawline)); - return "" if ($line !~ m/($String)/g); - return substr($rawline, $-[0], $+[0] - $-[0]); -} - -sub ctx_statement_block { - my ($linenr, $remain, $off) = @_; - my $line = $linenr - 1; - my $blk = ''; - my $soff = $off; - my $coff = $off - 1; - my $coff_set = 0; - - my $loff = 0; - - my $type = ''; - my $level = 0; - my @stack = (); - my $p; - my $c; - my $len = 0; - - my $remainder; - while (1) { - @stack = (['', 0]) if ($#stack == -1); - - #warn "CSB: blk<$blk> remain<$remain>\n"; - # If we are about to drop off the end, pull in more - # context. - if ($off >= $len) { - for (; $remain > 0; $line++) { - last if (!defined $lines[$line]); - next if ($lines[$line] =~ /^-/); - $remain--; - $loff = $len; - $blk .= $lines[$line] . "\n"; - $len = length($blk); - $line++; - last; - } - # Bail if there is no further context. - #warn "CSB: blk<$blk> off<$off> len<$len>\n"; - if ($off >= $len) { - last; - } - if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { - $level++; - $type = '#'; - } - } - $p = $c; - $c = substr($blk, $off, 1); - $remainder = substr($blk, $off); - - #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; - - # Handle nested #if/#else. - if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, [ $type, $level ]); - } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { - ($type, $level) = @{$stack[$#stack - 1]}; - } elsif ($remainder =~ /^#\s*endif\b/) { - ($type, $level) = @{pop(@stack)}; - } - - # Statement ends at the ';' or a close '}' at the - # outermost level. - if ($level == 0 && $c eq ';') { - last; - } - - # An else is really a conditional as long as its not else if - if ($level == 0 && $coff_set == 0 && - (!defined($p) || $p =~ /(?:\s|\}|\+)/) && - $remainder =~ /^(else)(?:\s|{)/ && - $remainder !~ /^else\s+if\b/) { - $coff = $off + length($1) - 1; - $coff_set = 1; - #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; - #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; - } - - if (($type eq '' || $type eq '(') && $c eq '(') { - $level++; - $type = '('; - } - if ($type eq '(' && $c eq ')') { - $level--; - $type = ($level != 0)? '(' : ''; - - if ($level == 0 && $coff < $soff) { - $coff = $off; - $coff_set = 1; - #warn "CSB: mark coff<$coff>\n"; - } - } - if (($type eq '' || $type eq '{') && $c eq '{') { - $level++; - $type = '{'; - } - if ($type eq '{' && $c eq '}') { - $level--; - $type = ($level != 0)? '{' : ''; - - if ($level == 0) { - if (substr($blk, $off + 1, 1) eq ';') { - $off++; - } - last; - } - } - # Preprocessor commands end at the newline unless escaped. - if ($type eq '#' && $c eq "\n" && $p ne "\\") { - $level--; - $type = ''; - $off++; - last; - } - $off++; - } - # We are truly at the end, so shuffle to the next line. - if ($off == $len) { - $loff = $len + 1; - $line++; - $remain--; - } - - my $statement = substr($blk, $soff, $off - $soff + 1); - my $condition = substr($blk, $soff, $coff - $soff + 1); - - #warn "STATEMENT<$statement>\n"; - #warn "CONDITION<$condition>\n"; - - #print "coff<$coff> soff<$off> loff<$loff>\n"; - - return ($statement, $condition, - $line, $remain + 1, $off - $loff + 1, $level); -} - -sub statement_lines { - my ($stmt) = @_; - - # Strip the diff line prefixes and rip blank lines at start and end. - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_rawlines { - my ($stmt) = @_; - - my @stmt_lines = ($stmt =~ /\n/g); - - return $#stmt_lines + 2; -} - -sub statement_block_size { - my ($stmt) = @_; - - $stmt =~ s/(^|\n)./$1/g; - $stmt =~ s/^\s*{//; - $stmt =~ s/}\s*$//; - $stmt =~ s/^\s*//; - $stmt =~ s/\s*$//; - - my @stmt_lines = ($stmt =~ /\n/g); - my @stmt_statements = ($stmt =~ /;/g); - - my $stmt_lines = $#stmt_lines + 2; - my $stmt_statements = $#stmt_statements + 1; - - if ($stmt_lines > $stmt_statements) { - return $stmt_lines; - } else { - return $stmt_statements; - } -} - -sub ctx_statement_full { - my ($linenr, $remain, $off) = @_; - my ($statement, $condition, $level); - - my (@chunks); - - # Grab the first conditional/block pair. - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "F: c<$condition> s<$statement> remain<$remain>\n"; - push(@chunks, [ $condition, $statement ]); - if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { - return ($level, $linenr, @chunks); - } - - # Pull in the following conditional/block pairs and see if they - # could continue the statement. - for (;;) { - ($statement, $condition, $linenr, $remain, $off, $level) = - ctx_statement_block($linenr, $remain, $off); - #print "C: c<$condition> s<$statement> remain<$remain>\n"; - last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); - #print "C: push\n"; - push(@chunks, [ $condition, $statement ]); - } - - return ($level, $linenr, @chunks); -} - -sub ctx_block_get { - my ($linenr, $remain, $outer, $open, $close, $off) = @_; - my $line; - my $start = $linenr - 1; - my $blk = ''; - my @o; - my @c; - my @res = (); - - my $level = 0; - my @stack = ($level); - for ($line = $start; $remain > 0; $line++) { - next if ($rawlines[$line] =~ /^-/); - $remain--; - - $blk .= $rawlines[$line]; - - # Handle nested #if/#else. - if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { - push(@stack, $level); - } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { - $level = $stack[$#stack - 1]; - } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { - $level = pop(@stack); - } - - foreach my $c (split(//, $lines[$line])) { - ##print "C<$c>L<$level><$open$close>O<$off>\n"; - if ($off > 0) { - $off--; - next; - } - - if ($c eq $close && $level > 0) { - $level--; - last if ($level == 0); - } elsif ($c eq $open) { - $level++; - } - } - - if (!$outer || $level <= 1) { - push(@res, $rawlines[$line]); - } - - last if ($level == 0); - } - - return ($level, @res); -} -sub ctx_block_outer { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); - return @r; -} -sub ctx_block { - my ($linenr, $remain) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); - return @r; -} -sub ctx_statement { - my ($linenr, $remain, $off) = @_; - - my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); - return @r; -} -sub ctx_block_level { - my ($linenr, $remain) = @_; - - return ctx_block_get($linenr, $remain, 0, '{', '}', 0); -} -sub ctx_statement_level { - my ($linenr, $remain, $off) = @_; - - return ctx_block_get($linenr, $remain, 0, '(', ')', $off); -} - -sub ctx_locate_comment { - my ($first_line, $end_line) = @_; - - # Catch a comment on the end of the line itself. - my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); - return $current_comment if (defined $current_comment); - - # Look through the context and try and figure out if there is a - # comment. - my $in_comment = 0; - $current_comment = ''; - for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { - my $line = $rawlines[$linenr - 1]; - #warn " $line\n"; - if ($linenr == $first_line and $line =~ m@^.\s*\*@) { - $in_comment = 1; - } - if ($line =~ m@/\*@) { - $in_comment = 1; - } - if (!$in_comment && $current_comment ne '') { - $current_comment = ''; - } - $current_comment .= $line . "\n" if ($in_comment); - if ($line =~ m@\*/@) { - $in_comment = 0; - } - } - - chomp($current_comment); - return($current_comment); -} -sub ctx_has_comment { - my ($first_line, $end_line) = @_; - my $cmt = ctx_locate_comment($first_line, $end_line); - - ##print "LINE: $rawlines[$end_line - 1 ]\n"; - ##print "CMMT: $cmt\n"; - - return ($cmt ne ''); -} - -sub raw_line { - my ($linenr, $cnt) = @_; - - my $offset = $linenr - 1; - $cnt++; - - my $line; - while ($cnt) { - $line = $rawlines[$offset++]; - next if (defined($line) && $line =~ /^-/); - $cnt--; - } - - return $line; -} - -sub get_stat_real { - my ($linenr, $lc) = @_; - - my $stat_real = raw_line($linenr, 0); - for (my $count = $linenr + 1; $count <= $lc; $count++) { - $stat_real = $stat_real . "\n" . raw_line($count, 0); - } - - return $stat_real; -} - -sub get_stat_here { - my ($linenr, $cnt, $here) = @_; - - my $herectx = $here . "\n"; - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } - - return $herectx; -} - -sub cat_vet { - my ($vet) = @_; - my ($res, $coded); - - $res = ''; - while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { - $res .= $1; - if ($2 ne '') { - $coded = sprintf("^%c", unpack('C', $2) + 64); - $res .= $coded; - } - } - $res =~ s/$/\$/; - - return $res; -} - -my $av_preprocessor = 0; -my $av_pending; -my @av_paren_type; -my $av_pend_colon; - -sub annotate_reset { - $av_preprocessor = 0; - $av_pending = '_'; - @av_paren_type = ('E'); - $av_pend_colon = 'O'; -} - -sub annotate_values { - my ($stream, $type) = @_; - - my $res; - my $var = '_' x length($stream); - my $cur = $stream; - - print "$stream\n" if ($dbg_values > 1); - - while (length($cur)) { - @av_paren_type = ('E') if ($#av_paren_type < 0); - print " <" . join('', @av_paren_type) . - "> <$type> <$av_pending>" if ($dbg_values > 1); - if ($cur =~ /^(\s+)/o) { - print "WS($1)\n" if ($dbg_values > 1); - if ($1 =~ /\n/ && $av_preprocessor) { - $type = pop(@av_paren_type); - $av_preprocessor = 0; - } - - } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { - print "CAST($1)\n" if ($dbg_values > 1); - push(@av_paren_type, $type); - $type = 'c'; - - } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { - print "DECLARE($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^($Modifier)\s*/) { - print "MODIFIER($1)\n" if ($dbg_values > 1); - $type = 'T'; - - } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { - print "DEFINE($1,$2)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - if ($2 ne '') { - $av_pending = 'N'; - } - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { - print "UNDEF($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - push(@av_paren_type, $type); - - } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { - print "PRE_START($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { - print "PRE_RESTART($1)\n" if ($dbg_values > 1); - $av_preprocessor = 1; - - push(@av_paren_type, $av_paren_type[$#av_paren_type]); - - $type = 'E'; - - } elsif ($cur =~ /^(\#\s*(?:endif))/o) { - print "PRE_END($1)\n" if ($dbg_values > 1); - - $av_preprocessor = 1; - - # Assume all arms of the conditional end as this - # one does, and continue as if the #endif was not here. - pop(@av_paren_type); - push(@av_paren_type, $type); - $type = 'E'; - - } elsif ($cur =~ /^(\\\n)/o) { - print "PRECONT($1)\n" if ($dbg_values > 1); - - } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { - print "ATTR($1)\n" if ($dbg_values > 1); - $av_pending = $type; - $type = 'N'; - - } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { - print "SIZEOF($1)\n" if ($dbg_values > 1); - if (defined $2) { - $av_pending = 'V'; - } - $type = 'N'; - - } elsif ($cur =~ /^(if|while|for)\b/o) { - print "COND($1)\n" if ($dbg_values > 1); - $av_pending = 'E'; - $type = 'N'; - - } elsif ($cur =~/^(case)/o) { - print "CASE($1)\n" if ($dbg_values > 1); - $av_pend_colon = 'C'; - $type = 'N'; - - } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { - print "KEYWORD($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(\()/o) { - print "PAREN('$1')\n" if ($dbg_values > 1); - push(@av_paren_type, $av_pending); - $av_pending = '_'; - $type = 'N'; - - } elsif ($cur =~ /^(\))/o) { - my $new_type = pop(@av_paren_type); - if ($new_type ne '_') { - $type = $new_type; - print "PAREN('$1') -> $type\n" - if ($dbg_values > 1); - } else { - print "PAREN('$1')\n" if ($dbg_values > 1); - } - - } elsif ($cur =~ /^($Ident)\s*\(/o) { - print "FUNC($1)\n" if ($dbg_values > 1); - $type = 'V'; - $av_pending = 'V'; - - } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { - if (defined $2 && $type eq 'C' || $type eq 'T') { - $av_pend_colon = 'B'; - } elsif ($type eq 'E') { - $av_pend_colon = 'L'; - } - print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Ident|$Constant)/o) { - print "IDENT($1)\n" if ($dbg_values > 1); - $type = 'V'; - - } elsif ($cur =~ /^($Assignment)/o) { - print "ASSIGN($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~/^(;|{|})/) { - print "END($1)\n" if ($dbg_values > 1); - $type = 'E'; - $av_pend_colon = 'O'; - - } elsif ($cur =~/^(,)/) { - print "COMMA($1)\n" if ($dbg_values > 1); - $type = 'C'; - - } elsif ($cur =~ /^(\?)/o) { - print "QUESTION($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(:)/o) { - print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); - - substr($var, length($res), 1, $av_pend_colon); - if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { - $type = 'E'; - } else { - $type = 'N'; - } - $av_pend_colon = 'O'; - - } elsif ($cur =~ /^(\[)/o) { - print "CLOSE($1)\n" if ($dbg_values > 1); - $type = 'N'; - - } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { - my $variant; - - print "OPV($1)\n" if ($dbg_values > 1); - if ($type eq 'V') { - $variant = 'B'; - } else { - $variant = 'U'; - } - - substr($var, length($res), 1, $variant); - $type = 'N'; - - } elsif ($cur =~ /^($Operators)/o) { - print "OP($1)\n" if ($dbg_values > 1); - if ($1 ne '++' && $1 ne '--') { - $type = 'N'; - } - - } elsif ($cur =~ /(^.)/o) { - print "C($1)\n" if ($dbg_values > 1); - } - if (defined $1) { - $cur = substr($cur, length($1)); - $res .= $type x length($1); - } - } - - return ($res, $var); -} - -sub possible { - my ($possible, $line) = @_; - my $notPermitted = qr{(?: - ^(?: - $Modifier| - $Storage| - $Type| - DEFINE_\S+ - )$| - ^(?: - goto| - return| - case| - else| - asm|__asm__| - do| - \#| - \#\#| - )(?:\s|$)| - ^(?:typedef|struct|enum)\b - )}x; - warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); - if ($possible !~ $notPermitted) { - # Check for modifiers. - $possible =~ s/\s*$Storage\s*//g; - $possible =~ s/\s*$Sparse\s*//g; - if ($possible =~ /^\s*$/) { - - } elsif ($possible =~ /\s/) { - $possible =~ s/\s*$Type\s*//g; - for my $modifier (split(' ', $possible)) { - if ($modifier !~ $notPermitted) { - warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); - push(@modifierListFile, $modifier); - } - } - - } else { - warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); - push(@typeListFile, $possible); - } - build_types(); - } else { - warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); - } -} - -my $prefix = ''; - -sub show_type { - my ($type) = @_; - - $type =~ tr/[a-z]/[A-Z]/; - - return defined $use_type{$type} if (scalar keys %use_type > 0); - - return !defined $ignore_type{$type}; -} - -sub report { - my ($level, $type, $msg) = @_; - - if (!show_type($type) || - (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { - return 0; - } - my $output = ''; - if ($color) { - if ($level eq 'ERROR') { - $output .= RED; - } elsif ($level eq 'WARNING') { - $output .= YELLOW; - } else { - $output .= GREEN; - } - } - $output .= $prefix . $level . ':'; - if ($show_types) { - $output .= BLUE if ($color); - $output .= "$type:"; - } - $output .= RESET if ($color); - $output .= ' ' . $msg . "\n"; - - if ($showfile) { - my @lines = split("\n", $output, -1); - splice(@lines, 1, 1); - $output = join("\n", @lines); - } - $output = (split('\n', $output))[0] . "\n" if ($terse); - - push(our @report, $output); - - return 1; -} - -sub report_dump { - our @report; -} - -sub fixup_current_range { - my ($lineRef, $offset, $length) = @_; - - if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { - my $o = $1; - my $l = $2; - my $no = $o + $offset; - my $nl = $l + $length; - $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; - } -} - -sub fix_inserted_deleted_lines { - my ($linesRef, $insertedRef, $deletedRef) = @_; - - my $range_last_linenr = 0; - my $delta_offset = 0; - - my $old_linenr = 0; - my $new_linenr = 0; - - my $next_insert = 0; - my $next_delete = 0; - - my @lines = (); - - my $inserted = @{$insertedRef}[$next_insert++]; - my $deleted = @{$deletedRef}[$next_delete++]; - - foreach my $old_line (@{$linesRef}) { - my $save_line = 1; - my $line = $old_line; #don't modify the array - if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename - $delta_offset = 0; - } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk - $range_last_linenr = $new_linenr; - fixup_current_range(\$line, $delta_offset, 0); - } - - while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { - $deleted = @{$deletedRef}[$next_delete++]; - $save_line = 0; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); - } - - while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { - push(@lines, ${$inserted}{'LINE'}); - $inserted = @{$insertedRef}[$next_insert++]; - $new_linenr++; - fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); - } - - if ($save_line) { - push(@lines, $line); - $new_linenr++; - } - - $old_linenr++; - } - - return @lines; -} - -sub fix_insert_line { - my ($linenr, $line) = @_; - - my $inserted = { - LINENR => $linenr, - LINE => $line, - }; - push(@fixed_inserted, $inserted); -} - -sub fix_delete_line { - my ($linenr, $line) = @_; - - my $deleted = { - LINENR => $linenr, - LINE => $line, - }; - - push(@fixed_deleted, $deleted); -} - -sub ERROR { - my ($type, $msg) = @_; - - if (report("ERROR", $type, $msg)) { - our $clean = 0; - our $cnt_error++; - return 1; - } - return 0; -} -sub WARN { - my ($type, $msg) = @_; - - if (report("WARNING", $type, $msg)) { - our $clean = 0; - our $cnt_warn++; - return 1; - } - return 0; -} -sub CHK { - my ($type, $msg) = @_; - - if ($check && report("CHECK", $type, $msg)) { - our $clean = 0; - our $cnt_chk++; - return 1; - } - return 0; -} - -sub check_absolute_file { - my ($absolute, $herecurr) = @_; - my $file = $absolute; - - ##print "absolute<$absolute>\n"; - - # See if any suffix of this path is a path within the tree. - while ($file =~ s@^[^/]*/@@) { - if (-f "$root/$file") { - ##print "file<$file>\n"; - last; - } - } - if (! -f _) { - return 0; - } - - # It is, so see if the prefix is acceptable. - my $prefix = $absolute; - substr($prefix, -length($file)) = ''; - - ##print "prefix<$prefix>\n"; - if ($prefix ne ".../") { - WARN("USE_RELATIVE_PATH", - "use relative pathname instead of absolute in changelog text\n" . $herecurr); - } -} - -sub trim { - my ($string) = @_; - - $string =~ s/^\s+|\s+$//g; - - return $string; -} - -sub ltrim { - my ($string) = @_; - - $string =~ s/^\s+//; - - return $string; -} - -sub rtrim { - my ($string) = @_; - - $string =~ s/\s+$//; - - return $string; -} - -sub string_find_replace { - my ($string, $find, $replace) = @_; - - $string =~ s/$find/$replace/g; - - return $string; -} - -sub tabify { - my ($leading) = @_; - - my $source_indent = 8; - my $max_spaces_before_tab = $source_indent - 1; - my $spaces_to_tab = " " x $source_indent; - - #convert leading spaces to tabs - 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; - #Remove spaces before a tab - 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; - - return "$leading"; -} - -sub pos_last_openparen { - my ($line) = @_; - - my $pos = 0; - - my $opens = $line =~ tr/\(/\(/; - my $closes = $line =~ tr/\)/\)/; - - my $last_openparen = 0; - - if (($opens == 0) || ($closes >= $opens)) { - return -1; - } - - my $len = length($line); - - for ($pos = 0; $pos < $len; $pos++) { - my $string = substr($line, $pos); - if ($string =~ /^($FuncArg|$balanced_parens)/) { - $pos += length($1) - 1; - } elsif (substr($line, $pos, 1) eq '(') { - $last_openparen = $pos; - } elsif (index($string, '(') == -1) { - last; - } - } - - return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; -} - -sub process { - my $filename = shift; - - my $linenr=0; - my $prevline=""; - my $prevrawline=""; - my $stashline=""; - my $stashrawline=""; - - my $length; - my $indent; - my $previndent=0; - my $stashindent=0; - - our $clean = 1; - my $signoff = 0; - my $author = ''; - my $authorsignoff = 0; - my $is_patch = 0; - my $is_binding_patch = -1; - my $in_header_lines = $file ? 0 : 1; - my $in_commit_log = 0; #Scanning lines before patch - my $has_commit_log = 0; #Encountered lines before patch - my $commit_log_lines = 0; #Number of commit log lines - my $commit_log_possible_stack_dump = 0; - my $commit_log_long_line = 0; - my $commit_log_has_diff = 0; - my $reported_maintainer_file = 0; - my $reported_abi_update = 0; - my $non_utf8_charset = 0; - - my $last_blank_line = 0; - my $last_coalesced_string_linenr = -1; - - our @report = (); - our $cnt_lines = 0; - our $cnt_error = 0; - our $cnt_warn = 0; - our $cnt_chk = 0; - - # Trace the real file/line as we go. - my $realfile = ''; - my $realline = 0; - my $realcnt = 0; - my $here = ''; - my $context_function; #undef'd unless there's a known function - my $in_comment = 0; - my $comment_edge = 0; - my $first_line = 0; - my $p1_prefix = ''; - - my $prev_values = 'E'; - - # suppression flags - my %suppress_ifbraces; - my %suppress_whiletrailers; - my %suppress_export; - my $suppress_statement = 0; - - my %signatures = (); - - # Pre-scan the patch sanitizing the lines. - # Pre-scan the patch looking for any __setup documentation. - # - my @setup_docs = (); - my $setup_docs = 0; - - my $camelcase_file_seeded = 0; - - my $checklicenseline = 1; - - sanitise_line_reset(); - my $line; - foreach my $rawline (@rawlines) { - $linenr++; - $line = $rawline; - - push(@fixed, $rawline) if ($fix); - - if ($rawline=~/^\+\+\+\s+(\S+)/) { - $setup_docs = 0; - if ($1 =~ m@Documentation/admin-guide/kernel-parameters.rst$@) { - $setup_docs = 1; - } - #next; - } - if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - $in_comment = 0; - - # Guestimate if this is a continuing comment. Run - # the context looking for a comment "edge". If this - # edge is a close comment then we must be in a comment - # at context start. - my $edge; - my $cnt = $realcnt; - for (my $ln = $linenr + 1; $cnt > 0; $ln++) { - next if (defined $rawlines[$ln - 1] && - $rawlines[$ln - 1] =~ /^-/); - $cnt--; - #print "RAW<$rawlines[$ln - 1]>\n"; - last if (!defined $rawlines[$ln - 1]); - if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && - $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { - ($edge) = $1; - last; - } - } - if (defined $edge && $edge eq '*/') { - $in_comment = 1; - } - - # Guestimate if this is a continuing comment. If this - # is the start of a diff block and this line starts - # ' *' then it is very likely a comment. - if (!defined $edge && - $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) - { - $in_comment = 1; - } - - ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; - sanitise_line_reset($in_comment); - - } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { - # Standardise the strings and chars within the input to - # simplify matching -- only bother with positive lines. - $line = sanitise_line($rawline); - } - - # Check if ABI is being updated. If so, there's probably no need to - # emit the "does ABI need updating?" message on file add/move/delete - if ($SOF && - ($line =~ /\+#define SOF_ABI_MAJOR*/ || - $line =~ /\+#define SOF_ABI_MINOR*/ || - $line =~ /\+#define SOF_ABI_PATCH*/)) { - $reported_abi_update = 1; - } - - push(@lines, $line); - - if ($realcnt > 1) { - $realcnt-- if ($line =~ /^(?:\+| |$)/); - } else { - $realcnt = 0; - } - - #print "==>$rawline\n"; - #print "-->$line\n"; - - if ($setup_docs && $line =~ /^\+/) { - push(@setup_docs, $line); - } - } - - $prefix = ''; - - $realcnt = 0; - $linenr = 0; - $fixlinenr = -1; - foreach my $line (@lines) { - $linenr++; - $fixlinenr++; - my $sline = $line; #copy of $line - $sline =~ s/$;/ /g; #with comments as spaces - - my $rawline = $rawlines[$linenr - 1]; - -# check if it's a mode change, rename or start of a patch - if (!$in_commit_log && - ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ || - ($line =~ /^rename (?:from|to) \S+\s*$/ || - $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) { - $is_patch = 1; - } - -#extract the line range in the file after the patch is applied - if (!$in_commit_log && - $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) { - my $context = $4; - $is_patch = 1; - $first_line = $linenr + 1; - $realline=$1-1; - if (defined $2) { - $realcnt=$3+1; - } else { - $realcnt=1+1; - } - annotate_reset(); - $prev_values = 'E'; - - %suppress_ifbraces = (); - %suppress_whiletrailers = (); - %suppress_export = (); - $suppress_statement = 0; - if ($context =~ /\b(\w+)\s*\(/) { - $context_function = $1; - } else { - undef $context_function; - } - next; - -# track the line number as we move through the hunk, note that -# new versions of GNU diff omit the leading space on completely -# blank context lines so we need to count that too. - } elsif ($line =~ /^( |\+|$)/) { - $realline++; - $realcnt-- if ($realcnt != 0); - - # Measure the line length and indent. - ($length, $indent) = line_stats($rawline); - - # Track the previous line. - ($prevline, $stashline) = ($stashline, $line); - ($previndent, $stashindent) = ($stashindent, $indent); - ($prevrawline, $stashrawline) = ($stashrawline, $rawline); - - #warn "line<$line>\n"; - - } elsif ($realcnt == 1) { - $realcnt--; - } - - my $hunk_line = ($realcnt != 0); - - $here = "#$linenr: " if (!$file); - $here = "#$realline: " if ($file); - - my $found_file = 0; - # extract the filename as it passes - if ($line =~ /^diff --git.*?(\S+)$/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@ if (!$file); - $in_commit_log = 0; - $found_file = 1; - } elsif ($line =~ /^\+\+\+\s+(\S+)/) { - $realfile = $1; - $realfile =~ s@^([^/]*)/@@ if (!$file); - $in_commit_log = 0; - - $p1_prefix = $1; - if (!$file && $tree && $p1_prefix ne '' && - -e "$root/$p1_prefix") { - WARN("PATCH_PREFIX", - "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); - } - - if ($realfile =~ m@^include/asm/@) { - ERROR("MODIFIED_INCLUDE_ASM", - "do not modify files in include/asm, change architecture specific files in include/asm-\n" . "$here$rawline\n"); - } - $found_file = 1; - } - -#make up the handle for any error we report on this line - if ($showfile) { - $prefix = "$realfile:$realline: " - } elsif ($emacs) { - if ($file) { - $prefix = "$filename:$realline: "; - } else { - $prefix = "$filename:$linenr: "; - } - } - - if ($found_file) { - if (is_maintained_obsolete($realfile)) { - WARN("OBSOLETE", - "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n"); - } - if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { - $check = 1; - } else { - $check = $check_orig; - } - $checklicenseline = 1; - - if ($realfile !~ /^MAINTAINERS/) { - my $last_binding_patch = $is_binding_patch; - - $is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@; - - if (($last_binding_patch != -1) && - ($last_binding_patch ^ $is_binding_patch)) { - WARN("DT_SPLIT_BINDING_PATCH", - "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.txt\n"); - } - } - - next; - } - - $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); - - my $hereline = "$here\n$rawline\n"; - my $herecurr = "$here\n$rawline\n"; - my $hereprev = "$here\n$prevrawline\n$rawline\n"; - - $cnt_lines++ if ($realcnt != 0); - -# Verify the existence of a commit log if appropriate -# 2 is used because a $signature is counted in $commit_log_lines - if ($in_commit_log) { - if ($line !~ /^\s*$/) { - $commit_log_lines++; #could be a $signature - } - } elsif ($has_commit_log && $commit_log_lines < 2) { - WARN("COMMIT_MESSAGE", - "Missing commit description - Add an appropriate one\n"); - $commit_log_lines = 2; #warn only once - } - -# Check if the commit log has what seems like a diff which can confuse patch - if ($in_commit_log && !$commit_log_has_diff && - (($line =~ m@^\s+diff\b.*a/[\w/]+@ && - $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) || - $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || - $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { - ERROR("DIFF_IN_COMMIT_MSG", - "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); - $commit_log_has_diff = 1; - } - -# Check for incorrect file permissions - if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { - my $permhere = $here . "FILE: $realfile\n"; - if ($realfile !~ m@scripts/@ && - $realfile !~ /\.(py|pl|awk|sh)$/) { - ERROR("EXECUTE_PERMISSIONS", - "do not set execute permissions for source files\n" . $permhere); - } - } - -# Check the patch for a From: - if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) { - $author = $1; - $author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i); - $author =~ s/"//g; - } - -# Check the patch for a signoff: - if ($line =~ /^\s*signed-off-by:/i) { - $signoff++; - $in_commit_log = 0; - if ($author ne '') { - my $l = $line; - $l =~ s/"//g; - if ($l =~ /^\s*signed-off-by:\s*\Q$author\E/i) { - $authorsignoff = 1; - } - } - } - - -# Check if MAINTAINERS is being updated. If so, there's probably no need to -# emit the "does MAINTAINERS need updating?" message on file add/move/delete - if ($line =~ /^\s*MAINTAINERS\s*\|/) { - $reported_maintainer_file = 1; - } - -# Check signature styles - if (!$in_header_lines && - $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { - my $space_before = $1; - my $sign_off = $2; - my $space_after = $3; - my $email = $4; - my $ucfirst_sign_off = ucfirst(lc($sign_off)); - - if ($sign_off !~ /$signature_tags/) { - WARN("BAD_SIGN_OFF", - "Non-standard signature: $sign_off\n" . $herecurr); - } - if (defined $space_before && $space_before ne "") { - if (WARN("BAD_SIGN_OFF", - "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - } - if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { - if (WARN("BAD_SIGN_OFF", - "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - - } - if (!defined $space_after || $space_after ne " ") { - if (WARN("BAD_SIGN_OFF", - "Use a single space after $ucfirst_sign_off\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = - "$ucfirst_sign_off $email"; - } - } - - my ($email_name, $email_address, $comment) = parse_email($email); - my $suggested_email = format_email(($email_name, $email_address)); - if ($suggested_email eq "") { - ERROR("BAD_SIGN_OFF", - "Unrecognized email address: '$email'\n" . $herecurr); - } else { - my $dequoted = $suggested_email; - $dequoted =~ s/^"//; - $dequoted =~ s/" $comment" ne $email && - "$suggested_email$comment" ne $email) { - WARN("BAD_SIGN_OFF", - "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); - } - } - -# Check for duplicate signatures - my $sig_nospace = $line; - $sig_nospace =~ s/\s//g; - $sig_nospace = lc($sig_nospace); - if (defined $signatures{$sig_nospace}) { - WARN("BAD_SIGN_OFF", - "Duplicate signature\n" . $herecurr); - } else { - $signatures{$sig_nospace} = 1; - } - -# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email - if ($sign_off =~ /^co-developed-by:$/i) { - if ($email eq $author) { - WARN("BAD_SIGN_OFF", - "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline); - } - if (!defined $lines[$linenr]) { - WARN("BAD_SIGN_OFF", - "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline); - } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) { - WARN("BAD_SIGN_OFF", - "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); - } elsif ($1 ne $email) { - WARN("BAD_SIGN_OFF", - "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); - } - } - } - -# Check email subject for common tools that don't need to be mentioned - if ($in_header_lines && - $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { - WARN("EMAIL_SUBJECT", - "A patch subject line should describe the change not the tool that found it\n" . $herecurr); - } - -# Check for unwanted Gerrit info - if ($in_commit_log && $line =~ /^\s*change-id:/i) { - ERROR("GERRIT_CHANGE_ID", - "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); - } - -# Check if the commit log is in a possible stack dump - if ($in_commit_log && !$commit_log_possible_stack_dump && - ($line =~ /^\s*(?:WARNING:|BUG:)/ || - $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || - # timestamp - $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) || - $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ || - $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) { - # stack dump address styles - $commit_log_possible_stack_dump = 1; - } - -# Check for line lengths > 75 in commit log, warn once - if ($in_commit_log && !$commit_log_long_line && - length($line) > 75 && - !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || - # file delta changes - $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || - # filename then : - $line =~ /^\s*(?:Fixes:|Link:)/i || - # A Fixes: or Link: line - $commit_log_possible_stack_dump)) { - WARN("COMMIT_LOG_LONG_LINE", - "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); - $commit_log_long_line = 1; - } - -# Reset possible stack dump if a blank line is found - if ($in_commit_log && $commit_log_possible_stack_dump && - $line =~ /^\s*$/) { - $commit_log_possible_stack_dump = 0; - } - -# Check for git id commit length and improperly formed commit descriptions - if ($in_commit_log && !$commit_log_possible_stack_dump && - $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i && - $line !~ /^This reverts commit [0-9a-f]{7,40}/ && - ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || - ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i && - $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && - $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { - my $init_char = "c"; - my $orig_commit = ""; - my $short = 1; - my $long = 0; - my $case = 1; - my $space = 1; - my $hasdesc = 0; - my $hasparens = 0; - my $id = '0123456789ab'; - my $orig_desc = "commit description"; - my $description = ""; - - if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { - $init_char = $1; - $orig_commit = lc($2); - } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { - $orig_commit = lc($1); - } - - $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); - $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); - $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); - $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); - if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { - $orig_desc = $1; - $hasparens = 1; - } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && - defined $rawlines[$linenr] && - $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { - $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; - $orig_desc = $1; - $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; - $orig_desc .= " " . $1; - $hasparens = 1; - } - - ($id, $description) = git_commit_info($orig_commit, - $id, $orig_desc); - - if (defined($id) && - ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) { - ERROR("GIT_COMMIT_ID", - "Please use git commit description style 'commit <12+ chars of sha1> (\"\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); - } - } - -# Check for added, moved or deleted files - if (!$SOF && - (!$reported_maintainer_file && !$in_commit_log && - ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || - $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || - ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && - (defined($1) || defined($2)))))) { - $is_patch = 1; - $reported_maintainer_file = 1; - WARN("FILE_PATH_CHANGES", - "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); - } - -# Check for wrappage within a valid hunk of the file - if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { - ERROR("CORRUPTED_PATCH", - "patch seems to be corrupt (line wrapped?)\n" . - $herecurr) if (!$emitted_corrupt++); - } - -# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php - if (($realfile =~ /^$/ || $line =~ /^\+/) && - $rawline !~ m/^$UTF8*$/) { - my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); - - my $blank = copy_spacing($rawline); - my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; - my $hereptr = "$hereline$ptr\n"; - - CHK("INVALID_UTF8", - "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); - } - -# Check if it's the start of a commit log -# (not a header line and we haven't seen the patch filename) - if ($in_header_lines && $realfile =~ /^$/ && - !($rawline =~ /^\s+(?:\S|$)/ || - $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) { - $in_header_lines = 0; - $in_commit_log = 1; - $has_commit_log = 1; - } - -# Check if there is UTF-8 in a commit log when a mail header has explicitly -# declined it, i.e defined some charset where it is missing. - if ($in_header_lines && - $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && - $1 !~ /utf-8/i) { - $non_utf8_charset = 1; - } - - if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && - $rawline =~ /$NON_ASCII_UTF8/) { - WARN("UTF8_BEFORE_PATCH", - "8-bit UTF-8 used in possible commit log\n" . $herecurr); - } - -# Check for absolute kernel paths in commit message - if ($tree && $in_commit_log) { - while ($line =~ m{(?:^|\s)(/\S*)}g) { - my $file = $1; - - if ($file =~ m{^(.*?)(?::\d+)+:?$} && - check_absolute_file($1, $herecurr)) { - # - } else { - check_absolute_file($file, $herecurr); - } - } - } - -# Check for various typo / spelling mistakes - if (defined($misspellings) && - ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { - while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { - my $typo = $1; - my $typo_fix = $spelling_fix{lc($typo)}; - $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); - $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); - my $msg_level = \&WARN; - $msg_level = \&CHK if ($file); - if (&{$msg_level}("TYPO_SPELLING", - "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; - } - } - } - -# check for invalid commit id - if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) { - my $id; - my $description; - ($id, $description) = git_commit_info($2, undef, undef); - if (!defined($id)) { - WARN("UNKNOWN_COMMIT_ID", - "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr); - } - } - -# ignore non-hunk lines and lines being removed - next if (!$hunk_line || $line =~ /^-/); - -#trailing whitespace - if ($line =~ /^\+.*\015/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("DOS_LINE_ENDINGS", - "DOS line endings\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/[\s\015]+$//; - } - } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (ERROR("TRAILING_WHITESPACE", - "trailing whitespace\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+$//; - } - - $rpt_cleaners = 1; - } - -# Check for FSF mailing addresses. - if ($rawline =~ /\bwrite to the Free/i || - $rawline =~ /\b675\s+Mass\s+Ave/i || - $rawline =~ /\b59\s+Temple\s+Pl/i || - $rawline =~ /\b51\s+Franklin\s+St/i) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - my $msg_level = \&ERROR; - $msg_level = \&CHK if ($file); - &{$msg_level}("FSF_MAILING_ADDRESS", - "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet) - } - -# check for Kconfig help text having a real description -# Only applies when adding the entry originally, after that we do not have -# sufficient context to determine whether it is indeed long enough. - if ($realfile =~ /Kconfig/ && - # 'choice' is usually the last thing on the line (though - # Kconfig supports named choices), so use a word boundary - # (\b) rather than a whitespace character (\s) - $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) { - my $length = 0; - my $cnt = $realcnt; - my $ln = $linenr + 1; - my $f; - my $is_start = 0; - my $is_end = 0; - for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { - $f = $lines[$ln - 1]; - $cnt-- if ($lines[$ln - 1] !~ /^-/); - $is_end = $lines[$ln - 1] =~ /^\+/; - - next if ($f =~ /^-/); - last if (!$file && $f =~ /^\@\@/); - - if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) { - $is_start = 1; - } elsif ($lines[$ln - 1] =~ /^\+\s*(?:help|---help---)\s*$/) { - if ($lines[$ln - 1] =~ "---help---") { - WARN("CONFIG_DESCRIPTION", - "prefer 'help' over '---help---' for new help texts\n" . $herecurr); - } - $length = -1; - } - - $f =~ s/^.//; - $f =~ s/#.*//; - $f =~ s/^\s+//; - next if ($f =~ /^$/); - - # This only checks context lines in the patch - # and so hopefully shouldn't trigger false - # positives, even though some of these are - # common words in help texts - if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice| - if|endif|menu|endmenu|source)\b/x) { - $is_end = 1; - last; - } - $length++; - } - if ($is_start && $is_end && $length < $min_conf_desc_length) { - WARN("CONFIG_DESCRIPTION", - "please write a paragraph that describes the config symbol fully\n" . $herecurr); - } - #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; - } - -# check for MAINTAINERS entries that don't have the right form - if ($realfile =~ /^MAINTAINERS$/ && - $rawline =~ /^\+[A-Z]:/ && - $rawline !~ /^\+[A-Z]:\t\S/) { - if (WARN("MAINTAINERS_STYLE", - "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/; - } - } - -# discourage the use of boolean for type definition attributes of Kconfig options - if ($realfile =~ /Kconfig/ && - $line =~ /^\+\s*\bboolean\b/) { - WARN("CONFIG_TYPE_BOOLEAN", - "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); - } - - if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && - ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { - my $flag = $1; - my $replacement = { - 'EXTRA_AFLAGS' => 'asflags-y', - 'EXTRA_CFLAGS' => 'ccflags-y', - 'EXTRA_CPPFLAGS' => 'cppflags-y', - 'EXTRA_LDFLAGS' => 'ldflags-y', - }; - - WARN("DEPRECATED_VARIABLE", - "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); - } - -# check for DT compatible documentation - if (defined $root && - (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || - ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { - - my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; - - my $dt_path = $root . "/Documentation/devicetree/bindings/"; - my $vp_file = $dt_path . "vendor-prefixes.yaml"; - - foreach my $compat (@compats) { - my $compat2 = $compat; - $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; - my $compat3 = $compat; - $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; - `grep -Erq "$compat|$compat2|$compat3" $dt_path`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); - } - - next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; - my $vendor = $1; - `grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`; - if ( $? >> 8 ) { - WARN("UNDOCUMENTED_DT_STRING", - "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); - } - } - } - -# check for using SPDX license tag at beginning of files - if ($realline == $checklicenseline) { - if ($rawline =~ /^[ \+]\s*\#\!\s*\//) { - $checklicenseline = 2; - } elsif ($rawline =~ /^\+/) { - my $comment = ""; - if ($realfile =~ /\.(h|s|S)$/) { - $comment = '/*'; - } elsif ($realfile =~ /\.(c|dts|dtsi)$/) { - $comment = '//'; - } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc)$/) { - $comment = '#'; - } elsif ($realfile =~ /\.rst$/) { - $comment = '..'; - } - -# check SPDX comment style for .[chsS] files - if ($realfile =~ /\.[chsS]$/ && - $rawline =~ /SPDX-License-Identifier:/ && - $rawline !~ m@^\+\s*\Q$comment\E\s*@) { - WARN("SPDX_LICENSE_TAG", - "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr); - } - - if ($comment !~ /^$/ && - $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) { - WARN("SPDX_LICENSE_TAG", - "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr); - } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) { - my $spdx_license = $1; - if (!is_SPDX_License_valid($spdx_license)) { - WARN("SPDX_LICENSE_TAG", - "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr); - } - } - } - } - -# check we are in a valid source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); - -# check for using SPDX-License-Identifier on the wrong line number - if ($realline != $checklicenseline && - $rawline =~ /\bSPDX-License-Identifier:/ && - substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) { - WARN("SPDX_LICENSE_TAG", - "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr); - } - -# line length limit (with some exclusions) -# -# There are a few types of lines that may extend beyond $max_line_length: -# logging functions like pr_info that end in a string -# lines with a single string -# #defines that are a single string -# lines with an RFC3986 like URL -# -# There are 3 different line length message types: -# LONG_LINE_COMMENT a comment starts before but extends beyond $max_line_length -# LONG_LINE_STRING a string starts before but extends beyond $max_line_length -# LONG_LINE all other lines longer than $max_line_length -# -# if LONG_LINE is ignored, the other 2 types are also ignored -# - - if ($line =~ /^\+/ && $length > $max_line_length) { - my $msg_type = "LONG_LINE"; - - # Check the allowed long line types first - - # logging functions that end in a string that starts - # before $max_line_length - if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = ""; - - # lines with only strings (w/ possible termination) - # #defines with only strings - } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || - $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { - $msg_type = ""; - - # More special cases - } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ || - $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) { - $msg_type = ""; - - # URL ($rawline is used in case the URL is in a comment) - } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) { - $msg_type = ""; - - # Otherwise set the alternate message types - - # a comment starts before $max_line_length - } elsif ($line =~ /($;[\s$;]*)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = "LONG_LINE_COMMENT" - - # a quoted string starts before $max_line_length - } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && - length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { - $msg_type = "LONG_LINE_STRING" - } - - if ($msg_type ne "" && - (show_type("LONG_LINE") || show_type($msg_type))) { - WARN($msg_type, - "line over $max_line_length characters\n" . $herecurr); - } - } - -# check for adding lines without a newline. - if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { - WARN("MISSING_EOF_NEWLINE", - "adding a line without newline at end of file\n" . $herecurr); - } - -# check we are in a valid source file C or perl if not then ignore this hunk - next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); - -# at the beginning of a line any tabs must come first and anything -# more than 8 must use tabs. - if ($rawline =~ /^\+\s* \t\s*\S/ || - $rawline =~ /^\+\s* \s*/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - $rpt_cleaners = 1; - if (ERROR("CODE_INDENT", - "code indent should use tabs where possible\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check for space before tabs. - if ($rawline =~ /^\+/ && $rawline =~ / \t/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("SPACE_BEFORE_TAB", - "please, no space before tabs\n" . $herevet) && - $fix) { - while ($fixed[$fixlinenr] =~ - s/(^\+.*) {8,8}\t/$1\t\t/) {} - while ($fixed[$fixlinenr] =~ - s/(^\+.*) +\t/$1\t/) {} - } - } - -# check for assignments on the start of a line - if ($sline =~ /^\+\s+($Assignment)[^=]/) { - CHK("ASSIGNMENT_CONTINUATIONS", - "Assignment operator '$1' should be on the previous line\n" . $hereprev); - } - -# check for && or || at the start of a line - if ($rawline =~ /^\+\s*(&&|\|\|)/) { - CHK("LOGICAL_CONTINUATIONS", - "Logical continuations should be on the previous line\n" . $hereprev); - } - -# check indentation starts on a tab stop - if ($perl_version_ok && - $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) { - my $indent = length($1); - if ($indent % 8) { - if (WARN("TABSTOP", - "Statements should start on a tabstop\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e; - } - } - } - -# check multi-line statement indentation matches previous line - if ($perl_version_ok && - $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { - $prevline =~ /^\+(\t*)(.*)$/; - my $oldindent = $1; - my $rest = $2; - - my $pos = pos_last_openparen($rest); - if ($pos >= 0) { - $line =~ /^(\+| )([ \t]*)/; - my $newindent = $2; - - my $goodtabindent = $oldindent . - "\t" x ($pos / 8) . - " " x ($pos % 8); - my $goodspaceindent = $oldindent . " " x $pos; - - if ($newindent ne $goodtabindent && - $newindent ne $goodspaceindent) { - - if (CHK("PARENTHESIS_ALIGNMENT", - "Alignment should match open parenthesis\n" . $hereprev) && - $fix && $line =~ /^\+/) { - $fixed[$fixlinenr] =~ - s/^\+[ \t]*/\+$goodtabindent/; - } - } - } - } - -# check for space after cast like "(int) foo" or "(struct foo) bar" -# avoid checking a few false positives: -# "sizeof(<type>)" or "__alignof__(<type>)" -# function pointer declarations like "(*foo)(int) = bar;" -# structure definitions like "(struct foo) { 0 };" -# multiline macros that define functions -# known attributes or the __attribute__ keyword - if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && - (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { - if (CHK("SPACING", - "No space is necessary after a cast\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/(\(\s*$Type\s*\))[ \t]+/$1/; - } - } - -# Block comment styles -# Networking with an initial /* - if ($realfile =~ m@^(drivers/net/|net/)@ && - $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && - $rawline =~ /^\+[ \t]*\*/ && - $realline > 2) { - WARN("NETWORKING_BLOCK_COMMENT_STYLE", - "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); - } - -# UAPI ABI version - if ($SOF && - $realfile =~ m@^(src/include/ipc/|src/include/kernel/|src/include/user/)@ && - $rawline =~ /^\+/ && - !$reported_abi_update) { - WARN("ABI update ??", - "Please update ABI in accordance with http://semver.org\n" . $hereprev); - } - -# Block comments use * on subsequent lines - if ($prevline =~ /$;[ \t]*$/ && #ends in comment - $prevrawline =~ /^\+.*?\/\*/ && #starting /* - $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ - $rawline =~ /^\+/ && #line is new - $rawline !~ /^\+[ \t]*\*/) { #no leading * - WARN("BLOCK_COMMENT_STYLE", - "Block comments use * on subsequent lines\n" . $hereprev); - } - -# Block comments use */ on trailing lines - if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ - $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ - $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ - $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ - WARN("BLOCK_COMMENT_STYLE", - "Block comments use a trailing */ on a separate line\n" . $herecurr); - } - -# Block comment * alignment - if ($prevline =~ /$;[ \t]*$/ && #ends in comment - $line =~ /^\+[ \t]*$;/ && #leading comment - $rawline =~ /^\+[ \t]*\*/ && #leading * - (($prevrawline =~ /^\+.*?\/\*/ && #leading /* - $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ - $prevrawline =~ /^\+[ \t]*\*/)) { #leading * - my $oldindent; - $prevrawline =~ m@^\+([ \t]*/?)\*@; - if (defined($1)) { - $oldindent = expand_tabs($1); - } else { - $prevrawline =~ m@^\+(.*/?)\*@; - $oldindent = expand_tabs($1); - } - $rawline =~ m@^\+([ \t]*)\*@; - my $newindent = $1; - $newindent = expand_tabs($newindent); - if (length($oldindent) ne length($newindent)) { - WARN("BLOCK_COMMENT_STYLE", - "Block comments should align the * on each line\n" . $hereprev); - } - } - -# check for missing blank lines after struct/union declarations -# with exceptions for various attributes and macros - if ($prevline =~ /^[\+ ]};?\s*$/ && - $line =~ /^\+/ && - !($line =~ /^\+\s*$/ || - $line =~ /^\+\s*EXPORT_SYMBOL/ || - $line =~ /^\+\s*MODULE_/i || - $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || - $line =~ /^\+[a-z_]*init/ || - $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || - $line =~ /^\+\s*DECLARE/ || - $line =~ /^\+\s*builtin_[\w_]*driver/ || - $line =~ /^\+\s*__setup/)) { - if (CHK("LINE_SPACING", - "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for multiple consecutive blank lines - if ($prevline =~ /^[\+ ]\s*$/ && - $line =~ /^\+\s*$/ && - $last_blank_line != ($linenr - 1)) { - if (CHK("LINE_SPACING", - "Please don't use multiple blank lines\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - - $last_blank_line = $linenr; - } - -# check for missing blank lines after declarations - if ($sline =~ /^\+\s+\S/ && #Not at char 1 - # actual declarations - ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || - # function pointer declarations - $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || - # known declaration macros - $prevline =~ /^\+\s+$declaration_macros/) && - # for "else if" which can look like "$Ident $Ident" - !($prevline =~ /^\+\s+$c90_Keywords\b/ || - # other possible extensions of declaration lines - $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || - # not starting a section or a macro "\" extended line - $prevline =~ /(?:\{\s*|\\)$/) && - # looks like a declaration - !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || - # function pointer declarations - $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || - # foo bar; where foo is some local typedef or #define - $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || - # known declaration macros - $sline =~ /^\+\s+$declaration_macros/ || - # start of struct or union or enum - $sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ || - # start or end of block or continuation of declaration - $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || - # bitfield continuation - $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || - # other possible extensions of declaration lines - $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && - # indentation of previous and current line are the same - (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { - if (WARN("LINE_SPACING", - "Missing a blank line after declarations\n" . $hereprev) && - $fix) { - fix_insert_line($fixlinenr, "\+"); - } - } - -# check for spaces at the beginning of a line. -# Exceptions: -# 1) within comments -# 2) indented preprocessor commands -# 3) hanging labels - if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { - my $herevet = "$here\n" . cat_vet($rawline) . "\n"; - if (WARN("LEADING_SPACE", - "please, no spaces at the start of a line\n" . $herevet) && - $fix) { - $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; - } - } - -# check we are in a valid C source file if not then ignore this hunk - next if ($realfile !~ /\.(h|c)$/); - -# check for unusual line ending [ or ( - if ($line =~ /^\+.*([\[\(])\s*$/) { - CHK("OPEN_ENDED_LINE", - "Lines should not end with a '$1'\n" . $herecurr); - } - -# check if this appears to be the start function declaration, save the name - if ($sline =~ /^\+\{\s*$/ && - $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) { - $context_function = $1; - } - -# check if this appears to be the end of function declaration - if ($sline =~ /^\+\}\s*$/) { - undef $context_function; - } - -# check indentation of any line with a bare else -# (but not if it is a multiple line "if (foo) return bar; else return baz;") -# if the previous line is a break or return and is indented 1 tab more... - if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { - my $tabs = length($1) + 1; - if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || - ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && - defined $lines[$linenr] && - $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { - WARN("UNNECESSARY_ELSE", - "else is not generally useful after a break or return\n" . $hereprev); - } - } - -# check indentation of a line with a break; -# if the previous line is a goto or return and is indented the same # of tabs - if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { - my $tabs = $1; - if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { - WARN("UNNECESSARY_BREAK", - "break is not useful after a goto or return\n" . $hereprev); - } - } - -# check for RCS/CVS revision markers - if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { - WARN("CVS_KEYWORD", - "CVS style keyword markers, these will _not_ be updated\n". $herecurr); - } - -# check for old HOTPLUG __dev<foo> section markings - if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { - WARN("HOTPLUG_SECTION", - "Using $1 is unnecessary\n" . $herecurr); - } - -# Check for potential 'bare' types - my ($stat, $cond, $line_nr_next, $remain_next, $off_next, - $realline_next); -#print "LINE<$line>\n"; - if ($linenr > $suppress_statement && - $realcnt && $sline =~ /.\s*\S/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0); - $stat =~ s/\n./\n /g; - $cond =~ s/\n./\n /g; - -#print "linenr<$linenr> <$stat>\n"; - # If this statement has no statement boundaries within - # it there is no point in retrying a statement scan - # until we hit end of it. - my $frag = $stat; $frag =~ s/;+\s*$//; - if ($frag !~ /(?:{|;)/) { -#print "skip<$line_nr_next>\n"; - $suppress_statement = $line_nr_next; - } - - # Find the real next line. - $realline_next = $line_nr_next; - if (defined $realline_next && - (!defined $lines[$realline_next - 1] || - substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { - $realline_next++; - } - - my $s = $stat; - $s =~ s/{.*$//s; - - # Ignore goto labels. - if ($s =~ /$Ident:\*$/s) { - - # Ignore functions being called - } elsif ($s =~ /^.\s*$Ident\s*\(/s) { - - } elsif ($s =~ /^.\s*else\b/s) { - - # declarations always start with types - } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) { - my $type = $1; - $type =~ s/\s+/ /g; - possible($type, "A:" . $s); - - # definitions in global scope can only start with types - } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { - possible($1, "B:" . $s); - } - - # any (foo ... *) is a pointer cast, and foo is a type - while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { - possible($1, "C:" . $s); - } - - # Check for any sort of function declaration. - # int foo(something bar, other baz); - # void (*store_gdt)(x86_descr_ptr *); - if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { - my ($name_len) = length($1); - - my $ctx = $s; - substr($ctx, 0, $name_len + 1, ''); - $ctx =~ s/\)[^\)]*$//; - - for my $arg (split(/\s*,\s*/, $ctx)) { - if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { - - possible($1, "D:" . $s); - } - } - } - - } - -# -# Checks which may be anchored in the context. -# - -# Check for switch () and associated case and default -# statements should be at the same indent. - if ($line=~/\bswitch\s*\(.*\)/) { - my $err = ''; - my $sep = ''; - my @ctx = ctx_block_outer($linenr, $realcnt); - shift(@ctx); - for my $ctx (@ctx) { - my ($clen, $cindent) = line_stats($ctx); - if ($ctx =~ /^\+\s*(case\s+|default:)/ && - $indent != $cindent) { - $err .= "$sep$ctx\n"; - $sep = ''; - } else { - $sep = "[...]\n"; - } - } - if ($err ne '') { - ERROR("SWITCH_CASE_INDENT_LEVEL", - "switch and case should be at the same indent\n$hereline$err"); - } - } - -# if/while/etc brace do not go on next line, unless defining a do while loop, -# or if that brace on the next line is for something else - if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { - my $pre_ctx = "$1$2"; - - my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); - - if ($line =~ /^\+\t{6,}/) { - WARN("DEEP_INDENTATION", - "Too many leading tabs - consider code refactoring\n" . $herecurr); - } - - my $ctx_cnt = $realcnt - $#ctx - 1; - my $ctx = join("\n", @ctx); - - my $ctx_ln = $linenr; - my $ctx_skip = $realcnt; - - while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && - defined $lines[$ctx_ln - 1] && - $lines[$ctx_ln - 1] =~ /^-/)) { - ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; - $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); - $ctx_ln++; - } - - #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; - #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; - - if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { - ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && - $ctx =~ /\)\s*\;\s*$/ && - defined $lines[$ctx_ln - 1]) - { - my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); - if ($nindent > $indent) { - WARN("TRAILING_SEMICOLON", - "trailing semicolon indicates no statements, indent implies otherwise\n" . - "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); - } - } - } - -# Check relative indent for conditionals and blocks. - if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($s, $c) = ($stat, $cond); - - substr($s, 0, length($c), ''); - - # remove inline comments - $s =~ s/$;/ /g; - $c =~ s/$;/ /g; - - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - - # Make sure we remove the line prefixes as we have - # none on the first line, and are going to readd them - # where necessary. - $s =~ s/\n./\n/gs; - while ($s =~ /\n\s+\\\n/) { - $cond_lines += $s =~ s/\n\s+\\\n/\n/g; - } - - # We want to check the first line inside the block - # starting at the end of the conditional, so remove: - # 1) any blank line termination - # 2) any opening brace { on end of the line - # 3) any do (...) { - my $continuation = 0; - my $check = 0; - $s =~ s/^.*\bdo\b//; - $s =~ s/^\s*{//; - if ($s =~ s/^\s*\\//) { - $continuation = 1; - } - if ($s =~ s/^\s*?\n//) { - $check = 1; - $cond_lines++; - } - - # Also ignore a loop construct at the end of a - # preprocessor statement. - if (($prevline =~ /^.\s*#\s*define\s/ || - $prevline =~ /\\\s*$/) && $continuation == 0) { - $check = 0; - } - - my $cond_ptr = -1; - $continuation = 0; - while ($cond_ptr != $cond_lines) { - $cond_ptr = $cond_lines; - - # If we see an #else/#elif then the code - # is not linear. - if ($s =~ /^\s*\#\s*(?:else|elif)/) { - $check = 0; - } - - # Ignore: - # 1) blank lines, they should be at 0, - # 2) preprocessor lines, and - # 3) labels. - if ($continuation || - $s =~ /^\s*?\n/ || - $s =~ /^\s*#\s*?/ || - $s =~ /^\s*$Ident\s*:/) { - $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; - if ($s =~ s/^.*?\n//) { - $cond_lines++; - } - } - } - - my (undef, $sindent) = line_stats("+" . $s); - my $stat_real = raw_line($linenr, $cond_lines); - - # Check if either of these lines are modified, else - # this is not this patch's fault. - if (!defined($stat_real) || - $stat !~ /^\+/ && $stat_real !~ /^\+/) { - $check = 0; - } - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n"; - - if ($check && $s ne '' && - (($sindent % 8) != 0 || - ($sindent < $indent) || - ($sindent == $indent && - ($s !~ /^\s*(?:\}|\{|else\b)/)) || - ($sindent > $indent + 8))) { - WARN("SUSPECT_CODE_INDENT", - "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); - } - } - - # Track the 'values' across context and added lines. - my $opline = $line; $opline =~ s/^./ /; - my ($curr_values, $curr_vars) = - annotate_values($opline . "\n", $prev_values); - $curr_values = $prev_values . $curr_values; - if ($dbg_values) { - my $outline = $opline; $outline =~ s/\t/ /g; - print "$linenr > .$outline\n"; - print "$linenr > $curr_values\n"; - print "$linenr > $curr_vars\n"; - } - $prev_values = substr($curr_values, -1); - -#ignore lines not being added - next if ($line =~ /^[^\+]/); - -# check for dereferences that span multiple lines - if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ && - $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) { - $prevline =~ /($Lval\s*(?:\.|->))\s*$/; - my $ref = $1; - $line =~ /^.\s*($Lval)/; - $ref .= $1; - $ref =~ s/\s//g; - WARN("MULTILINE_DEREFERENCE", - "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev); - } - -# check for declarations of signed or unsigned without int - while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { - my $type = $1; - my $var = $2; - $var = "" if (!defined $var); - if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { - my $sign = $1; - my $pointer = $2; - - $pointer = "" if (!defined $pointer); - - if (WARN("UNSPECIFIED_INT", - "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && - $fix) { - my $decl = trim($sign) . " int "; - my $comp_pointer = $pointer; - $comp_pointer =~ s/\s//g; - $decl .= $comp_pointer; - $decl = rtrim($decl) if ($var eq ""); - $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; - } - } - } - -# TEST: allow direct testing of the type matcher. - if ($dbg_type) { - if ($line =~ /^.\s*$Declare\s*$/) { - ERROR("TEST_TYPE", - "TEST: is type\n" . $herecurr); - } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { - ERROR("TEST_NOT_TYPE", - "TEST: is not type ($1 is)\n". $herecurr); - } - next; - } -# TEST: allow direct testing of the attribute matcher. - if ($dbg_attr) { - if ($line =~ /^.\s*$Modifier\s*$/) { - ERROR("TEST_ATTR", - "TEST: is attr\n" . $herecurr); - } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { - ERROR("TEST_NOT_ATTR", - "TEST: is not attr ($1 is)\n". $herecurr); - } - next; - } - -# check for initialisation to aggregates open brace on the next line - if ($line =~ /^.\s*{/ && - $prevline =~ /(?:^|[^=])=\s*$/) { - if (ERROR("OPEN_BRACE", - "that open brace { should be on the previous line\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/\s*=\s*$/ = {/; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $line; - $fixedline =~ s/^(.\s*)\{\s*/$1/; - fix_insert_line($fixlinenr, $fixedline); - } - } - -# -# Checks which are anchored on the added line. -# - -# check for malformed paths in #include statements (uses RAW line) - if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { - my $path = $1; - if ($path =~ m{//}) { - ERROR("MALFORMED_INCLUDE", - "malformed #include filename\n" . $herecurr); - } - if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { - ERROR("UAPI_INCLUDE", - "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); - } - } - -# no C99 // comments - if ($line =~ m{//}) { - if (ERROR("C99_COMMENTS", - "do not use C99 // comments\n" . $herecurr) && - $fix) { - my $line = $fixed[$fixlinenr]; - if ($line =~ /\/\/(.*)$/) { - my $comment = trim($1); - $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; - } - } - } - # Remove C99 comments. - $line =~ s@//.*@@; - $opline =~ s@//.*@@; - -# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider -# the whole statement. -#print "APW <$lines[$realline_next - 1]>\n"; - if (defined $realline_next && - exists $lines[$realline_next - 1] && - !defined $suppress_export{$realline_next} && - ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { - # Handle definitions which produce identifiers with - # a prefix: - # XXX(foo); - # EXPORT_SYMBOL(something_foo); - my $name = $1; - if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && - $name =~ /^${Ident}_$2/) { -#print "FOO C name<$name>\n"; - $suppress_export{$realline_next} = 1; - - } elsif ($stat !~ /(?: - \n.}\s*$| - ^.DEFINE_$Ident\(\Q$name\E\)| - ^.DECLARE_$Ident\(\Q$name\E\)| - ^.LIST_HEAD\(\Q$name\E\)| - ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| - \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() - )/x) { -#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; - $suppress_export{$realline_next} = 2; - } else { - $suppress_export{$realline_next} = 1; - } - } - if (!defined $suppress_export{$linenr} && - $prevline =~ /^.\s*$/ && - ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || - $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { -#print "FOO B <$lines[$linenr - 1]>\n"; - $suppress_export{$linenr} = 2; - } - if (defined $suppress_export{$linenr} && - $suppress_export{$linenr} == 2) { - WARN("EXPORT_SYMBOL", - "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); - } - -# check for global initialisers. - if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { - if (ERROR("GLOBAL_INITIALISERS", - "do not initialise globals to $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; - } - } -# check for static initialisers. - if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { - if (ERROR("INITIALISED_STATIC", - "do not initialise statics to $1\n" . - $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; - } - } - -# check for misordered declarations of char/short/int/long with signed/unsigned - while ($sline =~ m{(\b$TypeMisordered\b)}g) { - my $tmp = trim($1); - WARN("MISORDERED_TYPE", - "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); - } - -# check for unnecessary <signed> int declarations of short/long/long long - while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) { - my $type = trim($1); - next if ($type !~ /\bint\b/); - next if ($type !~ /\b(?:short|long\s+long|long)\b/); - my $new_type = $type; - $new_type =~ s/\b\s*int\s*\b/ /; - $new_type =~ s/\b\s*(?:un)?signed\b\s*/ /; - $new_type =~ s/^const\s+//; - $new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/); - $new_type = "const $new_type" if ($type =~ /^const\b/); - $new_type =~ s/\s+/ /g; - $new_type = trim($new_type); - if (WARN("UNNECESSARY_INT", - "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/; - } - } - -# check for static const char * arrays. - if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static const char * array should probably be static const char * const\n" . - $herecurr); - } - -# check for initialized const char arrays that should be static const - if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) { - if (WARN("STATIC_CONST_CHAR_ARRAY", - "const array should probably be static const\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/; - } - } - -# check for static char foo[] = "bar" declarations. - if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "static char array declaration should probably be static const char\n" . - $herecurr); - } - -# check for const <foo> const where <foo> is not a pointer or array type - if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { - my $found = $1; - if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { - WARN("CONST_CONST", - "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); - } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { - WARN("CONST_CONST", - "'const $found const' should probably be 'const $found'\n" . $herecurr); - } - } - -# check for non-global char *foo[] = {"bar", ...} declarations. - if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { - WARN("STATIC_CONST_CHAR_ARRAY", - "char * array declaration might be better as static const\n" . - $herecurr); - } - -# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) - if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { - my $array = $1; - if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { - my $array_div = $1; - if (WARN("ARRAY_SIZE", - "Prefer ARRAY_SIZE($array)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; - } - } - } - -# check for function declarations without arguments like "int foo()" - if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { - if (ERROR("FUNCTION_WITHOUT_ARGS", - "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; - } - } - -# check for new typedefs, only function parameters and sparse annotations -# make sense. - if ($line =~ /\btypedef\s/ && - $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && - $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && - $line !~ /\b$typeTypedefs\b/ && - $line !~ /\b__bitwise\b/) { - WARN("NEW_TYPEDEFS", - "do not add new typedefs\n" . $herecurr); - } - -# * goes on variable not on type - # (char*[ const]) - while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { - #print "AA<$1>\n"; - my ($ident, $from, $to) = ($1, $2, $2); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - -## print "1: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to) { - if (ERROR("POINTER_LOCATION", - "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && - $fix) { - my $sub_from = $ident; - my $sub_to = $ident; - $sub_to =~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { - #print "BB<$1>\n"; - my ($match, $from, $to, $ident) = ($1, $2, $2, $3); - - # Should start with a space. - $to =~ s/^(\S)/ $1/; - # Should not end with a space. - $to =~ s/\s+$//; - # '*'s should not have spaces between. - while ($to =~ s/\*\s+\*/\*\*/) { - } - # Modifiers should have spaces. - $to =~ s/(\b$Modifier$)/$1 /; - -## print "2: from<$from> to<$to> ident<$ident>\n"; - if ($from ne $to && $ident !~ /^$Modifier$/) { - if (ERROR("POINTER_LOCATION", - "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && - $fix) { - - my $sub_from = $match; - my $sub_to = $match; - $sub_to =~ s/\Q$from\E/$to/; - $fixed[$fixlinenr] =~ - s@\Q$sub_from\E@$sub_to@; - } - } - } - -# avoid BUG() or BUG_ON() - if ($line =~ /\b(?:BUG|BUG_ON)\b/) { - my $msg_level = \&WARN; - $msg_level = \&CHK if ($file); - &{$msg_level}("AVOID_BUG", - "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); - } - -# avoid LINUX_VERSION_CODE - if ($line =~ /\bLINUX_VERSION_CODE\b/) { - WARN("LINUX_VERSION_CODE", - "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); - } - -# check for uses of printk_ratelimit - if ($line =~ /\bprintk_ratelimit\s*\(/) { - WARN("PRINTK_RATELIMITED", - "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); - } - -# printk should use KERN_* levels - if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) { - WARN("PRINTK_WITHOUT_KERN_LEVEL", - "printk() should include KERN_<LEVEL> facility level\n" . $herecurr); - } - - if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; - my $level = lc($orig); - $level = "warn" if ($level eq "warning"); - my $level2 = $level; - $level2 = "dbg" if ($level eq "debug"); - WARN("PREFER_PR_LEVEL", - "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); - } - - if ($line =~ /\bpr_warning\s*\(/) { - if (WARN("PREFER_PR_LEVEL", - "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\bpr_warning\b/pr_warn/; - } - } - - if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { - my $orig = $1; - my $level = lc($orig); - $level = "warn" if ($level eq "warning"); - $level = "dbg" if ($level eq "debug"); - WARN("PREFER_DEV_LEVEL", - "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); - } - -# ENOSYS means "bad syscall nr" and nothing else. This will have a small -# number of false positives, but assembly files are not checked, so at -# least the arch entry code will not trigger this warning. - if ($line =~ /\bENOSYS\b/) { - WARN("ENOSYS", - "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); - } - -# function brace can't be on same line, except for #defines of do while, -# or if closed on same line - if ($perl_version_ok && - $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ && - $sline !~ /\#\s*define\b.*do\s*\{/ && - $sline !~ /}/) { - if (ERROR("OPEN_BRACE", - "open brace '{' following function definitions go on the next line\n" . $herecurr) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - my $fixed_line = $rawline; - $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; - my $line1 = $1; - my $line2 = $2; - fix_insert_line($fixlinenr, ltrim($line1)); - fix_insert_line($fixlinenr, "\+{"); - if ($line2 !~ /^\s*$/) { - fix_insert_line($fixlinenr, "\+\t" . trim($line2)); - } - } - } - -# open braces for enum, union and struct go on the same line. - if ($line =~ /^.\s*{/ && - $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { - if (ERROR("OPEN_BRACE", - "open brace '{' following $1 go on the same line\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = rtrim($prevrawline) . " {"; - fix_insert_line($fixlinenr, $fixedline); - $fixedline = $rawline; - $fixedline =~ s/^(.\s*)\{\s*/$1\t/; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -# missing space after union, struct or enum definition - if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { - if (WARN("SPACING", - "missing space after $1 definition\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; - } - } - -# Function pointer declarations -# check spacing between type, funcptr, and args -# canonical declaration is "type (*funcptr)(args...)" - if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { - my $declare = $1; - my $pre_pointer_space = $2; - my $post_pointer_space = $3; - my $funcname = $4; - my $post_funcname_space = $5; - my $pre_args_space = $6; - -# the $Declare variable will capture all spaces after the type -# so check it for a missing trailing missing space but pointer return types -# don't need a space so don't warn for those. - my $post_declare_space = ""; - if ($declare =~ /(\s+)$/) { - $post_declare_space = $1; - $declare = rtrim($declare); - } - if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { - WARN("SPACING", - "missing space after return type\n" . $herecurr); - $post_declare_space = " "; - } - -# unnecessary space "type (*funcptr)(args...)" -# This test is not currently implemented because these declarations are -# equivalent to -# int foo(int bar, ...) -# and this is form shouldn't/doesn't generate a checkpatch warning. -# -# elsif ($declare =~ /\s{2,}$/) { -# WARN("SPACING", -# "Multiple spaces after return type\n" . $herecurr); -# } - -# unnecessary space "type ( *funcptr)(args...)" - if (defined $pre_pointer_space && - $pre_pointer_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer open parenthesis\n" . $herecurr); - } - -# unnecessary space "type (* funcptr)(args...)" - if (defined $post_pointer_space && - $post_pointer_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr )(args...)" - if (defined $post_funcname_space && - $post_funcname_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space after function pointer name\n" . $herecurr); - } - -# unnecessary space "type (*funcptr) (args...)" - if (defined $pre_args_space && - $pre_args_space =~ /^\s/) { - WARN("SPACING", - "Unnecessary space before function pointer arguments\n" . $herecurr); - } - - if (show_type("SPACING") && $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; - } - } - -# check for spacing round square brackets; allowed: -# 1. with a type on the left -- int [] a; -# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, -# 3. inside a curly brace -- = { [0...10] = 5 } - while ($line =~ /(.*?\s)\[/g) { - my ($where, $prefix) = ($-[1], $1); - if ($prefix !~ /$Type\s+$/ && - ($where != 0 || $prefix !~ /^.\s+$/) && - $prefix !~ /[{,:]\s+$/) { - if (ERROR("BRACKET_SPACE", - "space prohibited before open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(\+.*?)\s+\[/$1\[/; - } - } - } - -# check for spaces between functions and their parentheses. - while ($line =~ /($Ident)\s+\(/g) { - my $name = $1; - my $ctx_before = substr($line, 0, $-[1]); - my $ctx = "$ctx_before$name"; - - # Ignore those directives where spaces _are_ permitted. - if ($name =~ /^(?: - if|for|while|switch|return|case| - volatile|__volatile__| - __attribute__|format|__extension__| - asm|__asm__)$/x) - { - # cpp #define statements have non-optional spaces, ie - # if there is a space between the name and the open - # parenthesis it is simply not a parameter group. - } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { - - # cpp #elif statement condition may start with a ( - } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { - - # If this whole things ends with a type its most - # likely a typedef for a function. - } elsif ($ctx =~ /$Type$/) { - - } else { - if (WARN("SPACING", - "space prohibited between function name and open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\b$name\s+\(/$name\(/; - } - } - } - -# Check operator spacing. - if (!($line=~/\#\s*include/)) { - my $fixed_line = ""; - my $line_fixed = 0; - - my $ops = qr{ - <<=|>>=|<=|>=|==|!=| - \+=|-=|\*=|\/=|%=|\^=|\|=|&=| - =>|->|<<|>>|<|>|=|!|~| - &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| - \?:|\?|: - }x; - my @elements = split(/($ops|;)/, $opline); - -## print("element count: <" . $#elements . ">\n"); -## foreach my $el (@elements) { -## print("el: <$el>\n"); -## } - - my @fix_elements = (); - my $off = 0; - - foreach my $el (@elements) { - push(@fix_elements, substr($rawline, $off, length($el))); - $off += length($el); - } - - $off = 0; - - my $blank = copy_spacing($opline); - my $last_after = -1; - - for (my $n = 0; $n < $#elements; $n += 2) { - - my $good = $fix_elements[$n] . $fix_elements[$n + 1]; - -## print("n: <$n> good: <$good>\n"); - - $off += length($elements[$n]); - - # Pick up the preceding and succeeding characters. - my $ca = substr($opline, 0, $off); - my $cc = ''; - if (length($opline) >= ($off + length($elements[$n + 1]))) { - $cc = substr($opline, $off + length($elements[$n + 1])); - } - my $cb = "$ca$;$cc"; - - my $a = ''; - $a = 'V' if ($elements[$n] ne ''); - $a = 'W' if ($elements[$n] =~ /\s$/); - $a = 'C' if ($elements[$n] =~ /$;$/); - $a = 'B' if ($elements[$n] =~ /(\[|\()$/); - $a = 'O' if ($elements[$n] eq ''); - $a = 'E' if ($ca =~ /^\s*$/); - - my $op = $elements[$n + 1]; - - my $c = ''; - if (defined $elements[$n + 2]) { - $c = 'V' if ($elements[$n + 2] ne ''); - $c = 'W' if ($elements[$n + 2] =~ /^\s/); - $c = 'C' if ($elements[$n + 2] =~ /^$;/); - $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); - $c = 'O' if ($elements[$n + 2] eq ''); - $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); - } else { - $c = 'E'; - } - - my $ctx = "${a}x${c}"; - - my $at = "(ctx:$ctx)"; - - my $ptr = substr($blank, 0, $off) . "^"; - my $hereptr = "$hereline$ptr\n"; - - # Pull out the value of this operator. - my $op_type = substr($curr_values, $off + 1, 1); - - # Get the full operator variant. - my $opv = $op . substr($curr_vars, $off, 1); - - # Ignore operators passed as parameters. - if ($op_type ne 'V' && - $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { - -# # Ignore comments -# } elsif ($op =~ /^$;+$/) { - - # ; should have either the end of line or a space or \ after it - } elsif ($op eq ';') { - if ($ctx !~ /.x[WEBC]/ && - $cc !~ /^\\/ && $cc !~ /^;/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed = 1; - } - } - - # // is a comment - } elsif ($op eq '//') { - - # : when part of a bitfield - } elsif ($opv eq ':B') { - # skip the bitfield test for now - - # No spaces for: - # -> - } elsif ($op eq '->') { - if ($ctx =~ /Wx.|.xW/) { - if (ERROR("SPACING", - "spaces prohibited around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # , must not have a space before and must have a space on the right. - } elsif ($op eq ',') { - my $rtrim_before = 0; - my $space_after = 0; - if ($ctx =~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $line_fixed = 1; - $rtrim_before = 1; - } - } - if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { - if (ERROR("SPACING", - "space required after that '$op' $at\n" . $hereptr)) { - $line_fixed = 1; - $last_after = $n; - $space_after = 1; - } - } - if ($rtrim_before || $space_after) { - if ($rtrim_before) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - } else { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); - } - if ($space_after) { - $good .= " "; - } - } - - # '*' as part of a type definition -- reported already. - } elsif ($opv eq '*_') { - #warn "'*' is part of type\n"; - - # unary operators should have a space before and - # none after. May be left adjacent to another - # unary operator, or a cast - } elsif ($op eq '!' || $op eq '~' || - $opv eq '*U' || $opv eq '-U' || - $opv eq '&U' || $opv eq '&&U') { - if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { - if (ERROR("SPACING", - "space required before that '$op' $at\n" . $hereptr)) { - if ($n != $last_after + 2) { - $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - } - if ($op eq '*' && $cc =~/\s*$Modifier\b/) { - # A unary '*' may be const - - } elsif ($ctx =~ /.xW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # unary ++ and unary -- are allowed no space on one side. - } elsif ($op eq '++' or $op eq '--') { - if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { - if (ERROR("SPACING", - "space required one side of that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; - $line_fixed = 1; - } - } - if ($ctx =~ /Wx[BE]/ || - ($ctx =~ /Wx./ && $cc =~ /^;/)) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - if ($ctx =~ /ExW/) { - if (ERROR("SPACING", - "space prohibited after that '$op' $at\n" . $hereptr)) { - $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # << and >> may either have or not have spaces both sides - } elsif ($op eq '<<' or $op eq '>>' or - $op eq '&' or $op eq '^' or $op eq '|' or - $op eq '+' or $op eq '-' or - $op eq '*' or $op eq '/' or - $op eq '%') - { - if ($check) { - if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { - if (CHK("SPACING", - "spaces preferred around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - $fix_elements[$n + 2] =~ s/^\s+//; - $line_fixed = 1; - } - } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { - if (CHK("SPACING", - "space preferred before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { - if (ERROR("SPACING", - "need consistent spacing around '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - - # A colon needs no spaces before when it is - # terminating a case value or a label. - } elsif ($opv eq ':C' || $opv eq ':L') { - if ($ctx =~ /Wx./) { - if (ERROR("SPACING", - "space prohibited before that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); - $line_fixed = 1; - } - } - - # All the others need spaces both sides. - } elsif ($ctx !~ /[EWC]x[CWE]/) { - my $ok = 0; - - # Ignore email addresses <foo@bar> - if (($op eq '<' && - $cc =~ /^\S+\@\S+>/) || - ($op eq '>' && - $ca =~ /<\S+\@\S+$/)) - { - $ok = 1; - } - - # for asm volatile statements - # ignore a colon with another - # colon immediately before or after - if (($op eq ':') && - ($ca =~ /:$/ || $cc =~ /^:/)) { - $ok = 1; - } - - # messages are ERROR, but ?: are CHK - if ($ok == 0) { - my $msg_level = \&ERROR; - $msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); - - if (&{$msg_level}("SPACING", - "spaces required around that '$op' $at\n" . $hereptr)) { - $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; - if (defined $fix_elements[$n + 2]) { - $fix_elements[$n + 2] =~ s/^\s+//; - } - $line_fixed = 1; - } - } - } - $off += length($elements[$n + 1]); - -## print("n: <$n> GOOD: <$good>\n"); - - $fixed_line = $fixed_line . $good; - } - - if (($#elements % 2) == 0) { - $fixed_line = $fixed_line . $fix_elements[$#elements]; - } - - if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { - $fixed[$fixlinenr] = $fixed_line; - } - - - } - -# check for whitespace before a non-naked semicolon - if ($line =~ /^\+.*\S\s+;\s*$/) { - if (WARN("SPACING", - "space prohibited before semicolon\n" . $herecurr) && - $fix) { - 1 while $fixed[$fixlinenr] =~ - s/^(\+.*\S)\s+;/$1;/; - } - } - -# check for multiple assignments - if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { - CHK("MULTIPLE_ASSIGNMENTS", - "multiple assignments should be avoided\n" . $herecurr); - } - -## # check for multiple declarations, allowing for a function declaration -## # continuation. -## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && -## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { -## -## # Remove any bracketed sections to ensure we do not -## # falsly report the parameters of functions. -## my $ln = $line; -## while ($ln =~ s/\([^\(\)]*\)//g) { -## } -## if ($ln =~ /,/) { -## WARN("MULTIPLE_DECLARATION", -## "declaring multiple variables together should be avoided\n" . $herecurr); -## } -## } - -#need space before brace following if, while, etc - if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || - $line =~ /\b(?:else|do)\{/) { - if (ERROR("SPACING", - "space required before the open brace '{'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/; - } - } - -## # check for blank lines before declarations -## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && -## $prevrawline =~ /^.\s*$/) { -## WARN("SPACING", -## "No blank lines before declarations\n" . $hereprev); -## } -## - -# closing brace should have a space following it when it has anything -# on the line - if ($line =~ /}(?!(?:,|;|\)|\}))\S/) { - if (ERROR("SPACING", - "space required after that close brace '}'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/}((?!(?:,|;|\)))\S)/} $1/; - } - } - -# check spacing on square brackets - if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { - if (ERROR("SPACING", - "space prohibited after that open square bracket '['\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\[\s+/\[/; - } - } - if ($line =~ /\s\]/) { - if (ERROR("SPACING", - "space prohibited before that close square bracket ']'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\s+\]/\]/; - } - } - -# check spacing on parentheses - if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && - $line !~ /for\s*\(\s+;/) { - if (ERROR("SPACING", - "space prohibited after that open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\(\s+/\(/; - } - } - if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && - $line !~ /for\s*\(.*;\s+\)/ && - $line !~ /:\s+\)/) { - if (ERROR("SPACING", - "space prohibited before that close parenthesis ')'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\s+\)/\)/; - } - } - -# check unnecessary parentheses around addressof/dereference single $Lvals -# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar - - while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { - my $var = $1; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around $var\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; - } - } - -# check for unnecessary parentheses around function pointer uses -# ie: (foo->bar)(); should be foo->bar(); -# but not "if (foo->bar) (" to avoid some false positives - if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { - my $var = $2; - if (CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around function pointer $var\n" . $herecurr) && - $fix) { - my $var2 = deparenthesize($var); - $var2 =~ s/\s//g; - $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; - } - } - -# check for unnecessary parentheses around comparisons in if uses -# when !drivers/staging or command-line uses --strict - if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) && - $perl_version_ok && defined($stat) && - $stat =~ /(^.\s*if\s*($balanced_parens))/) { - my $if_stat = $1; - my $test = substr($2, 1, -1); - my $herectx; - while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) { - my $match = $1; - # avoid parentheses around potential macro args - next if ($match =~ /^\s*\w+\s*$/); - if (!defined($herectx)) { - $herectx = $here . "\n"; - my $cnt = statement_rawlines($if_stat); - for (my $n = 0; $n < $cnt; $n++) { - my $rl = raw_line($linenr, $n); - $herectx .= $rl . "\n"; - last if $rl =~ /^[ \+].*\{/; - } - } - CHK("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses around '$match'\n" . $herectx); - } - } - -#goto labels aren't indented, allow a single space however - if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and - !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { - if (WARN("INDENTED_LABEL", - "labels should not be indented\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.)\s+/$1/; - } - } - -# return is not a function - if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { - my $spacing = $1; - if ($perl_version_ok && - $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { - my $value = $1; - $value = deparenthesize($value); - if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { - ERROR("RETURN_PARENTHESES", - "return is not a function, parentheses are not required\n" . $herecurr); - } - } elsif ($spacing !~ /\s+/) { - ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr); - } - } - -# unnecessary return in a void function -# at end-of-function, with the previous line a single leading tab, then return; -# and the line before that not a goto label target like "out:" - if ($sline =~ /^[ \+]}\s*$/ && - $prevline =~ /^\+\treturn\s*;\s*$/ && - $linenr >= 3 && - $lines[$linenr - 3] =~ /^[ +]/ && - $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { - WARN("RETURN_VOID", - "void function return statements are not generally useful\n" . $hereprev); - } - -# if statements using unnecessary parentheses - ie: if ((foo == bar)) - if ($perl_version_ok && - $line =~ /\bif\s*((?:\(\s*){2,})/) { - my $openparens = $1; - my $count = $openparens =~ tr@\(@\(@; - my $msg = ""; - if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { - my $comp = $4; #Not $1 because of $LvalOrFunc - $msg = " - maybe == should be = ?" if ($comp eq "=="); - WARN("UNNECESSARY_PARENTHESES", - "Unnecessary parentheses$msg\n" . $herecurr); - } - } - -# comparisons with a constant or upper case identifier on the left -# avoid cases like "foo + BAR < baz" -# only fix matches surrounded by parentheses to avoid incorrect -# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" - if ($perl_version_ok && - $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { - my $lead = $1; - my $const = $2; - my $comp = $3; - my $to = $4; - my $newcomp = $comp; - if ($lead !~ /(?:$Operators|\.)\s*$/ && - $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && - WARN("CONSTANT_COMPARISON", - "Comparisons should place the constant on the right side of the test\n" . $herecurr) && - $fix) { - if ($comp eq "<") { - $newcomp = ">"; - } elsif ($comp eq "<=") { - $newcomp = ">="; - } elsif ($comp eq ">") { - $newcomp = "<"; - } elsif ($comp eq ">=") { - $newcomp = "<="; - } - $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; - } - } - -# Return of what appears to be an errno should normally be negative - if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { - my $name = $1; - if ($name ne 'EOF' && $name ne 'ERROR') { - WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); - } - } - -# Need a space before open parenthesis after if, while etc - if ($line =~ /\b(if|while|for|switch)\(/) { - if (ERROR("SPACING", - "space required before the open parenthesis '('\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/\b(if|while|for|switch)\(/$1 \(/; - } - } - -# Check for illegal assignment in if conditional -- and check for trailing -# statements after the conditional. - if ($line =~ /do\s*(?!{)/) { - ($stat, $cond, $line_nr_next, $remain_next, $off_next) = - ctx_statement_block($linenr, $realcnt, 0) - if (!defined $stat); - my ($stat_next) = ctx_statement_block($line_nr_next, - $remain_next, $off_next); - $stat_next =~ s/\n./\n /g; - ##print "stat<$stat> stat_next<$stat_next>\n"; - - if ($stat_next =~ /^\s*while\b/) { - # If the statement carries leading newlines, - # then count those as offsets. - my ($whitespace) = - ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = - statement_rawlines($whitespace) - 1; - - $suppress_whiletrailers{$line_nr_next + - $offset} = 1; - } - } - if (!defined $suppress_whiletrailers{$linenr} && - defined($stat) && defined($cond) && - $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { - my ($s, $c) = ($stat, $cond); - - if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { - ERROR("ASSIGN_IN_IF", - "do not use assignment in if condition\n" . $herecurr); - } - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - $s =~ s/$;//g; # Remove any comments - if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && - $c !~ /}\s*while\s*/) - { - # Find out how long the conditional actually is. - my @newlines = ($c =~ /\n/gs); - my $cond_lines = 1 + $#newlines; - my $stat_real = ''; - - $stat_real = raw_line($linenr, $cond_lines) - . "\n" if ($cond_lines); - if (defined($stat_real) && $cond_lines > 1) { - $stat_real = "[...]\n$stat_real"; - } - - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr . $stat_real); - } - } - -# Check for bitwise tests written as boolean - if ($line =~ / - (?: - (?:\[|\(|\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\|) - | - (?:\&\&|\|\|) - \s*0[xX][0-9]+\s* - (?:\&\&|\|\||\)|\]) - )/x) - { - WARN("HEXADECIMAL_BOOLEAN_TEST", - "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); - } - -# if and else should not have general statements after it - if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { - my $s = $1; - $s =~ s/$;//g; # Remove any comments - if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - } -# if should not continue a brace - if ($line =~ /}\s*if\b/) { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line (or did you mean 'else if'?)\n" . - $herecurr); - } -# case and default should not have general statements after them - if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && - $line !~ /\G(?: - (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| - \s*return\s+ - )/xg) - { - ERROR("TRAILING_STATEMENTS", - "trailing statements should be on next line\n" . $herecurr); - } - - # Check for }<nl>else {, these must be at the same - # indent level to be relevant to each other. - if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && - $previndent == $indent) { - if (ERROR("ELSE_AFTER_BRACE", - "else should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/}\s*$//; - if ($fixedline !~ /^\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $fixedline = $rawline; - $fixedline =~ s/^(.\s*)else/$1} else/; - fix_insert_line($fixlinenr, $fixedline); - } - } - - if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && - $previndent == $indent) { - my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); - - # Find out what is on the end of the line after the - # conditional. - substr($s, 0, length($c), ''); - $s =~ s/\n.*//g; - - if ($s =~ /^\s*;/) { - if (ERROR("WHILE_AFTER_BRACE", - "while should follow close brace '}'\n" . $hereprev) && - $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - my $trailing = $rawline; - $trailing =~ s/^\+//; - $trailing = trim($trailing); - $fixedline =~ s/}\s*$/} $trailing/; - fix_insert_line($fixlinenr, $fixedline); - } - } - } - -#Specific variable tests - while ($line =~ m{($Constant|$Lval)}g) { - my $var = $1; - -#CamelCase - if ($var !~ /^$Constant$/ && - $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && -#Ignore Page<foo> variants - $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && -#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show) - $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ && -#Ignore some three character SI units explicitly, like MiB and KHz - $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { - while ($var =~ m{($Ident)}g) { - my $word = $1; - next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); - if ($check) { - seed_camelcase_includes(); - if (!$file && !$camelcase_file_seeded) { - seed_camelcase_file($realfile); - $camelcase_file_seeded = 1; - } - } - if (!defined $camelcase{$word}) { - $camelcase{$word} = 1; - CHK("CAMELCASE", - "Avoid CamelCase: <$word>\n" . $herecurr); - } - } - } - } - -#no spaces allowed after \ in define - if ($line =~ /\#\s*define.*\\\s+$/) { - if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", - "Whitespace after \\ makes next lines useless\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+$//; - } - } - -# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes -# itself <asm/foo.h> (uses RAW line) - if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { - my $file = "$1.h"; - my $checkfile = "include/linux/$file"; - if (-f "$root/$checkfile" && - $realfile ne $checkfile && - $1 !~ /$allowed_asm_includes/) - { - my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; - if ($asminclude > 0) { - if ($realfile =~ m{^arch/}) { - CHK("ARCH_INCLUDE_LINUX", - "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); - } else { - WARN("INCLUDE_LINUX", - "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); - } - } - } - } - -# multi-statement macros should be enclosed in a do while loop, grab the -# first statement and ensure its the whole macro if its not enclosed -# in a known good container - if ($realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - my $has_flow_statement = 0; - my $has_arg_concat = 0; - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $realcnt, 0); - $ctx = $dstat; - #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; - #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; - - $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); - $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); - - $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//; - my $define_args = $1; - my $define_stmt = $dstat; - my @def_args = (); - - if (defined $define_args && $define_args ne "") { - $define_args = substr($define_args, 1, length($define_args) - 2); - $define_args =~ s/\s*//g; - $define_args =~ s/\\\+?//g; - @def_args = split(",", $define_args); - } - - $dstat =~ s/$;//g; - $dstat =~ s/\\\n.//g; - $dstat =~ s/^\s*//s; - $dstat =~ s/\s*$//s; - - # Flatten any parentheses and braces - while ($dstat =~ s/\([^\(\)]*\)/1/ || - $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/.\[[^\[\]]*\]/1/) - { - } - - # Flatten any obvious string concatentation. - while ($dstat =~ s/($String)\s*$Ident/$1/ || - $dstat =~ s/$Ident\s*($String)/$1/) - { - } - - # Make asm volatile uses seem like a generic function - $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; - - my $exceptions = qr{ - $Declare| - module_param_named| - MODULE_PARM_DESC| - DECLARE_PER_CPU| - DEFINE_PER_CPU| - __typeof__\(| - union| - struct| - \.$Ident\s*=\s*| - ^\"|\"$| - ^\[ - }x; - #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; - - $ctx =~ s/\n*$//; - my $stmt_cnt = statement_rawlines($ctx); - my $herectx = get_stat_here($linenr, $stmt_cnt, $here); - - if ($dstat ne '' && - $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), - $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); - $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz - $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants - $dstat !~ /$exceptions/ && - $dstat !~ /^\.$Ident\s*=/ && # .foo = - $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo - $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) - $dstat !~ /^for\s*$Constant$/ && # for (...) - $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() - $dstat !~ /^do\s*{/ && # do {... - $dstat !~ /^\(\{/ && # ({... - $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) - { - if ($dstat =~ /^\s*if\b/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx"); - } elsif ($dstat =~ /;/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); - } else { - ERROR("COMPLEX_MACRO", - "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); - } - - } - - # Make $define_stmt single line, comment-free, etc - my @stmt_array = split('\n', $define_stmt); - my $first = 1; - $define_stmt = ""; - foreach my $l (@stmt_array) { - $l =~ s/\\$//; - if ($first) { - $define_stmt = $l; - $first = 0; - } elsif ($l =~ /^[\+ ]/) { - $define_stmt .= substr($l, 1); - } - } - $define_stmt =~ s/$;//g; - $define_stmt =~ s/\s+/ /g; - $define_stmt = trim($define_stmt); - -# check if any macro arguments are reused (ignore '...' and 'type') - foreach my $arg (@def_args) { - next if ($arg =~ /\.\.\./); - next if ($arg =~ /^type$/i); - my $tmp_stmt = $define_stmt; - $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; - $tmp_stmt =~ s/\#+\s*$arg\b//g; - $tmp_stmt =~ s/\b$arg\s*\#\#//g; - my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g; - if ($use_cnt > 1) { - CHK("MACRO_ARG_REUSE", - "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx"); - } -# check if any macro arguments may have other precedence issues - if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m && - ((defined($1) && $1 ne ',') || - (defined($2) && $2 ne ','))) { - CHK("MACRO_ARG_PRECEDENCE", - "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx"); - } - } - -# check for macros with flow control, but without ## concatenation -# ## concatenation is commonly a macro that defines a function so ignore those - if ($has_flow_statement && !$has_arg_concat) { - my $cnt = statement_rawlines($ctx); - my $herectx = get_stat_here($linenr, $cnt, $here); - - WARN("MACRO_WITH_FLOW_CONTROL", - "Macros with flow control statements should be avoided\n" . "$herectx"); - } - -# check for line continuations outside of #defines, preprocessor #, and asm - - } else { - if ($prevline !~ /^..*\\$/ && - $line !~ /^\+\s*\#.*\\$/ && # preprocessor - $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm - $line =~ /^\+.*\\$/) { - WARN("LINE_CONTINUATIONS", - "Avoid unnecessary line continuations\n" . $herecurr); - } - } - -# do {} while (0) macro tests: -# single-statement macros do not need to be enclosed in do while (0) loop, -# macro should not end with a semicolon - if ($perl_version_ok && - $realfile !~ m@/vmlinux.lds.h$@ && - $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { - my $ln = $linenr; - my $cnt = $realcnt; - my ($off, $dstat, $dcond, $rest); - my $ctx = ''; - ($dstat, $dcond, $ln, $cnt, $off) = - ctx_statement_block($linenr, $realcnt, 0); - $ctx = $dstat; - - $dstat =~ s/\\\n.//g; - $dstat =~ s/$;/ /g; - - if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { - my $stmts = $2; - my $semis = $3; - - $ctx =~ s/\n*$//; - my $cnt = statement_rawlines($ctx); - my $herectx = get_stat_here($linenr, $cnt, $here); - - if (($stmts =~ tr/;/;/) == 1 && - $stmts !~ /^\s*(if|while|for|switch)\b/) { - WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", - "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); - } - if (defined $semis && $semis ne "") { - WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", - "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); - } - } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { - $ctx =~ s/\n*$//; - my $cnt = statement_rawlines($ctx); - my $herectx = get_stat_here($linenr, $cnt, $here); - - WARN("TRAILING_SEMICOLON", - "macros should not use a trailing semicolon\n" . "$herectx"); - } - } - -# check for redundant bracing round if etc - if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, 1); - #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; - #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; - if ($#chunks > 0 && $level == 0) { - my @allowed = (); - my $allow = 0; - my $seen = 0; - my $herectx = $here . "\n"; - my $ln = $linenr - 1; - for my $chunk (@chunks) { - my ($cond, $block) = @{$chunk}; - - # If the condition carries leading newlines, then count those as offsets. - my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); - my $offset = statement_rawlines($whitespace) - 1; - - $allowed[$allow] = 0; - #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; - - # We have looked at and allowed this specific line. - $suppress_ifbraces{$ln + $offset} = 1; - - $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; - $ln += statement_rawlines($block) - 1; - - substr($block, 0, length($cond), ''); - - $seen++ if ($block =~ /^\s*{/); - - #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed[$allow] = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed[$allow] = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed[$allow] = 1; - } - $allow++; - } - if ($seen) { - my $sum_allowed = 0; - foreach (@allowed) { - $sum_allowed += $_; - } - if ($sum_allowed == 0) { - WARN("BRACES", - "braces {} are not necessary for any arm of this statement\n" . $herectx); - } elsif ($sum_allowed != $allow && - $seen != $allow) { - CHK("BRACES", - "braces {} should be used on all arms of this statement\n" . $herectx); - } - } - } - } - if (!defined $suppress_ifbraces{$linenr - 1} && - $line =~ /\b(if|while|for|else)\b/) { - my $allowed = 0; - - # Check the pre-context. - if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { - #print "APW: ALLOWED: pre<$1>\n"; - $allowed = 1; - } - - my ($level, $endln, @chunks) = - ctx_statement_full($linenr, $realcnt, $-[0]); - - # Check the condition. - my ($cond, $block) = @{$chunks[0]}; - #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if (statement_lines($cond) > 1) { - #print "APW: ALLOWED: cond<$cond>\n"; - $allowed = 1; - } - if ($block =~/\b(?:if|for|while)\b/) { - #print "APW: ALLOWED: block<$block>\n"; - $allowed = 1; - } - if (statement_block_size($block) > 1) { - #print "APW: ALLOWED: lines block<$block>\n"; - $allowed = 1; - } - # Check the post-context. - if (defined $chunks[1]) { - my ($cond, $block) = @{$chunks[1]}; - if (defined $cond) { - substr($block, 0, length($cond), ''); - } - if ($block =~ /^\s*\{/) { - #print "APW: ALLOWED: chunk-1 block<$block>\n"; - $allowed = 1; - } - } - if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { - my $cnt = statement_rawlines($block); - my $herectx = get_stat_here($linenr, $cnt, $here); - - WARN("BRACES", - "braces {} are not necessary for single statement blocks\n" . $herectx); - } - } - -# check for single line unbalanced braces - if ($sline =~ /^.\s*\}\s*else\s*$/ || - $sline =~ /^.\s*else\s*\{\s*$/) { - CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr); - } - -# check for unnecessary blank lines around braces - if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && - $fix && $prevrawline =~ /^\+/) { - fix_delete_line($fixlinenr - 1, $prevrawline); - } - } - if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { - if (CHK("BRACES", - "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && - $fix) { - fix_delete_line($fixlinenr, $rawline); - } - } - -# no volatiles please - my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; - if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { - WARN("VOLATILE", - "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr); - } - -# Check for user-visible strings broken across lines, which breaks the ability -# to grep for the string. Make exceptions when the previous string ends in a -# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' -# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value - if ($line =~ /^\+\s*$String/ && - $prevline =~ /"\s*$/ && - $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { - if (WARN("SPLIT_STRING", - "quoted string split across lines\n" . $hereprev) && - $fix && - $prevrawline =~ /^\+.*"\s*$/ && - $last_coalesced_string_linenr != $linenr - 1) { - my $extracted_string = get_quoted_string($line, $rawline); - my $comma_close = ""; - if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { - $comma_close = $1; - } - - fix_delete_line($fixlinenr - 1, $prevrawline); - fix_delete_line($fixlinenr, $rawline); - my $fixedline = $prevrawline; - $fixedline =~ s/"\s*$//; - $fixedline .= substr($extracted_string, 1) . trim($comma_close); - fix_insert_line($fixlinenr - 1, $fixedline); - $fixedline = $rawline; - $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; - if ($fixedline !~ /\+\s*$/) { - fix_insert_line($fixlinenr, $fixedline); - } - $last_coalesced_string_linenr = $linenr; - } - } - -# check for missing a space in a string concatenation - if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { - WARN('MISSING_SPACE', - "break quoted strings at a space character\n" . $hereprev); - } - -# check for an embedded function name in a string when the function is known -# This does not work very well for -f --file checking as it depends on patch -# context providing the function name or a single line form for in-file -# function declarations - if (!$SOF && - $line =~ /^\+.*$String/ && - defined($context_function) && - get_quoted_string($line, $rawline) =~ /\b$context_function\b/ && - length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) { - WARN("EMBEDDED_FUNCTION_NAME", - "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr); - } - -# check for spaces before a quoted newline - if ($rawline =~ /^.*\".*\s\\n/) { - if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", - "unnecessary whitespace before a quoted newline\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; - } - - } - -# concatenated string without spaces between elements - if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) { - if (CHK("CONCATENATED_STRING", - "Concatenated strings should use spaces between elements\n" . $herecurr) && - $fix) { - while ($line =~ /($String)/g) { - my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]); - $fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/; - $fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/; - } - } - } - -# uncoalesced string fragments - if ($line =~ /$String\s*"/) { - if (WARN("STRING_FRAGMENTS", - "Consecutive strings are generally better as a single string\n" . $herecurr) && - $fix) { - while ($line =~ /($String)(?=\s*")/g) { - my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]); - $fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e; - } - } - } - -# check for non-standard and hex prefixed decimal printf formats - my $show_L = 1; #don't show the same defect twice - my $show_Z = 1; - while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { - my $string = substr($rawline, $-[1], $+[1] - $-[1]); - $string =~ s/%%/__/g; - # check for %L - if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) { - WARN("PRINTF_L", - "\%L$1 is non-standard C, use %ll$1\n" . $herecurr); - $show_L = 0; - } - # check for %Z - if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) { - WARN("PRINTF_Z", - "%Z$1 is non-standard C, use %z$1\n" . $herecurr); - $show_Z = 0; - } - # check for 0x<decimal> - if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) { - ERROR("PRINTF_0XDECIMAL", - "Prefixing 0x with decimal output is defective\n" . $herecurr); - } - } - -# check for line continuations in quoted strings with odd counts of " - if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) { - WARN("LINE_CONTINUATIONS", - "Avoid line continuations in quoted strings\n" . $herecurr); - } - -# warn about #if 0 - if ($line =~ /^.\s*\#\s*if\s+0\b/) { - WARN("IF_0", - "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr); - } - -# warn about #if 1 - if ($line =~ /^.\s*\#\s*if\s+1\b/) { - WARN("IF_1", - "Consider removing the #if 1 and its #endif\n" . $herecurr); - } - -# check for needless "if (<foo>) fn(<foo>)" uses - if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { - my $tested = quotemeta($1); - my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; - if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { - my $func = $1; - if (WARN('NEEDLESS_IF', - "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && - $fix) { - my $do_fix = 1; - my $leading_tabs = ""; - my $new_leading_tabs = ""; - if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { - $leading_tabs = $1; - } else { - $do_fix = 0; - } - if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { - $new_leading_tabs = $1; - if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { - $do_fix = 0; - } - } else { - $do_fix = 0; - } - if ($do_fix) { - fix_delete_line($fixlinenr - 1, $prevrawline); - $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; - } - } - } - } - -# check for unnecessary "Out of Memory" messages - if ($line =~ /^\+.*\b$logFunctions\s*\(/ && - $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && - (defined $1 || defined $3) && - $linenr > 3) { - my $testval = $2; - my $testline = $lines[$linenr - 3]; - - my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); -# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); - - if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ && - $s !~ /\b__GFP_NOWARN\b/ ) { - WARN("OOM_MESSAGE", - "Possible unnecessary 'out of memory' message\n" . $hereprev); - } - } - -# check for logging functions with KERN_<LEVEL> - if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && - $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { - my $level = $1; - if (WARN("UNNECESSARY_KERN_LEVEL", - "Possible unnecessary $level\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s*$level\s*//; - } - } - -# check for logging continuations - if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) { - WARN("LOGGING_CONTINUATION", - "Avoid logging continuation uses where feasible\n" . $herecurr); - } - -# check for mask then right shift without a parentheses - if ($perl_version_ok && - $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && - $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so - WARN("MASK_THEN_SHIFT", - "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); - } - -# check for pointer comparisons to NULL - if ($perl_version_ok) { - while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { - my $val = $1; - my $equal = "!"; - $equal = "" if ($4 eq "!="); - if (CHK("COMPARISON_TO_NULL", - "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; - } - } - } - -# check for bad placement of section $InitAttribute (e.g.: __initdata) - if ($line =~ /(\b$InitAttribute\b)/) { - my $attr = $1; - if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { - my $ptr = $1; - my $var = $2; - if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && - ERROR("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr)) || - ($ptr !~ /\b(union|struct)\s+$attr\b/ && - WARN("MISPLACED_INIT", - "$attr should be placed after $var\n" . $herecurr))) && - $fix) { - $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e; - } - } - } - -# check for $InitAttributeData (ie: __initdata) with const - if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { - my $attr = $1; - $attr =~ /($InitAttributePrefix)(.*)/; - my $attr_prefix = $1; - my $attr_type = $2; - if (ERROR("INIT_ATTRIBUTE", - "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/$InitAttributeData/${attr_prefix}initconst/; - } - } - -# check for $InitAttributeConst (ie: __initconst) without const - if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { - my $attr = $1; - if (ERROR("INIT_ATTRIBUTE", - "Use of $attr requires a separate use of const\n" . $herecurr) && - $fix) { - my $lead = $fixed[$fixlinenr] =~ - /(^\+\s*(?:static\s+))/; - $lead = rtrim($1); - $lead = "$lead " if ($lead !~ /^\+$/); - $lead = "${lead}const "; - $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; - } - } - -# check for __read_mostly with const non-pointer (should just be const) - if ($line =~ /\b__read_mostly\b/ && - $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { - if (ERROR("CONST_READ_MOSTLY", - "Invalid use of __read_mostly with const type\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; - } - } - -# don't use __constant_<foo> functions outside of include/uapi/ - if ($realfile !~ m@^include/uapi/@ && - $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { - my $constant_func = $1; - my $func = $constant_func; - $func =~ s/^__constant_//; - if (WARN("CONSTANT_CONVERSION", - "$constant_func should be $func\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; - } - } - -# prefer usleep_range over udelay - if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { - my $delay = $1; - # ignore udelay's < 10, however - if (! ($delay < 10) ) { - CHK("USLEEP_RANGE", - "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr); - } - if ($delay > 2000) { - WARN("LONG_UDELAY", - "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); - } - } - -# warn about unexpectedly long msleep's - if ($line =~ /\bmsleep\s*\((\d+)\);/) { - if ($1 < 20) { - WARN("MSLEEP", - "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr); - } - } - -# check for comparisons of jiffies - if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { - WARN("JIFFIES_COMPARISON", - "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); - } - -# check for comparisons of get_jiffies_64() - if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { - WARN("JIFFIES_COMPARISON", - "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); - } - -# warn about #ifdefs in C files -# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { -# print "#ifdef in C files should be avoided\n"; -# print "$herecurr"; -# $clean = 0; -# } - -# warn about spacing in #ifdefs - if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { - if (ERROR("SPACING", - "exactly one space required after that #$1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ - s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; - } - - } - -# check for spinlock_t definitions without a comment. - if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || - $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { - my $which = $1; - if (!ctx_has_comment($first_line, $linenr)) { - CHK("UNCOMMENTED_DEFINITION", - "$1 definition without comment\n" . $herecurr); - } - } -# check for memory barriers without a comment. - - my $barriers = qr{ - mb| - rmb| - wmb| - read_barrier_depends - }x; - my $barrier_stems = qr{ - mb__before_atomic| - mb__after_atomic| - store_release| - load_acquire| - store_mb| - (?:$barriers) - }x; - my $all_barriers = qr{ - (?:$barriers)| - smp_(?:$barrier_stems)| - virt_(?:$barrier_stems) - }x; - - if ($line =~ /\b(?:$all_barriers)\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("MEMORY_BARRIER", - "memory barrier without comment\n" . $herecurr); - } - } - - my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; - - if ($realfile !~ m@^include/asm-generic/@ && - $realfile !~ m@/barrier\.h$@ && - $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && - $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { - WARN("MEMORY_BARRIER", - "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); - } - -# check for waitqueue_active without a comment. - if ($line =~ /\bwaitqueue_active\s*\(/) { - if (!ctx_has_comment($first_line, $linenr)) { - WARN("WAITQUEUE_ACTIVE", - "waitqueue_active without comment\n" . $herecurr); - } - } - -# check for smp_read_barrier_depends and read_barrier_depends - if (!$file && $line =~ /\b(smp_|)read_barrier_depends\s*\(/) { - WARN("READ_BARRIER_DEPENDS", - "$1read_barrier_depends should only be used in READ_ONCE or DEC Alpha code\n" . $herecurr); - } - -# check of hardware specific defines - if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { - CHK("ARCH_DEFINES", - "architecture specific defines should be avoided\n" . $herecurr); - } - -# check that the storage class is not after a type - if ($line =~ /\b($Type)\s+($Storage)\b/) { - WARN("STORAGE_CLASS", - "storage class '$2' should be located before type '$1'\n" . $herecurr); - } -# Check that the storage class is at the beginning of a declaration - if ($line =~ /\b$Storage\b/ && - $line !~ /^.\s*$Storage/ && - $line =~ /^.\s*(.+?)\$Storage\s/ && - $1 !~ /[\,\)]\s*$/) { - WARN("STORAGE_CLASS", - "storage class should be at the beginning of the declaration\n" . $herecurr); - } - -# check the location of the inline attribute, that it is between -# storage class and type. - if ($line =~ /\b$Type\s+$Inline\b/ || - $line =~ /\b$Inline\s+$Storage\b/) { - ERROR("INLINE_LOCATION", - "inline keyword should sit between storage class and type\n" . $herecurr); - } - -# Check for __inline__ and __inline, prefer inline - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b(__inline__|__inline)\b/) { - if (WARN("INLINE", - "plain inline is preferred over $1\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; - - } - } - -# Check for __attribute__ packed, prefer __packed - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { - WARN("PREFER_PACKED", - "__packed is preferred over __attribute__((packed))\n" . $herecurr); - } - -# Check for __attribute__ aligned, prefer __aligned - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { - WARN("PREFER_ALIGNED", - "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); - } - -# Check for __attribute__ section, prefer __section - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) { - my $old = substr($rawline, $-[1], $+[1] - $-[1]); - my $new = substr($old, 1, -1); - if (WARN("PREFER_SECTION", - "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/; - } - } - -# Check for __attribute__ format(printf, prefer __printf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { - if (WARN("PREFER_PRINTF", - "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; - - } - } - -# Check for __attribute__ format(scanf, prefer __scanf - if ($realfile !~ m@\binclude/uapi/@ && - $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { - if (WARN("PREFER_SCANF", - "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; - } - } - -# Check for __attribute__ weak, or __weak declarations (may have link issues) - if ($perl_version_ok && - $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && - ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || - $line =~ /\b__weak\b/)) { - ERROR("WEAK_DECLARATION", - "Using weak declarations can have unintended link defects\n" . $herecurr); - } - -# check for c99 types like uint8_t used outside of uapi/ and tools/ - if (!$SOF && - $realfile !~ m@\binclude/uapi/@ && - $realfile !~ m@\btools/@ && - $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { - my $type = $1; - if ($type =~ /\b($typeC99Typedefs)\b/) { - $type = $1; - my $kernel_type = 'u'; - $kernel_type = 's' if ($type =~ /^_*[si]/); - $type =~ /(\d+)/; - $kernel_type .= $1; - if (CHK("PREFER_KERNEL_TYPES", - "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; - } - } - } - -# check for cast of C90 native int or longer types constants - if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { - my $cast = $1; - my $const = $2; - if (WARN("TYPECAST_INT_CONSTANT", - "Unnecessary typecast of c90 int constant\n" . $herecurr) && - $fix) { - my $suffix = ""; - my $newconst = $const; - $newconst =~ s/${Int_type}$//; - $suffix .= 'U' if ($cast =~ /\bunsigned\b/); - if ($cast =~ /\blong\s+long\b/) { - $suffix .= 'LL'; - } elsif ($cast =~ /\blong\b/) { - $suffix .= 'L'; - } - $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; - } - } - -# check for sizeof(&) - if ($line =~ /\bsizeof\s*\(\s*\&/) { - WARN("SIZEOF_ADDRESS", - "sizeof(& should be avoided\n" . $herecurr); - } - -# check for sizeof without parenthesis - if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { - if (WARN("SIZEOF_PARENTHESIS", - "sizeof $1 should be sizeof($1)\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; - } - } - -# check for struct spinlock declarations - if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { - WARN("USE_SPINLOCK_T", - "struct spinlock should be spinlock_t\n" . $herecurr); - } - -# check for seq_printf uses that could be seq_puts - if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { - my $fmt = get_quoted_string($line, $rawline); - $fmt =~ s/%%//g; - if ($fmt !~ /%/) { - if (WARN("PREFER_SEQ_PUTS", - "Prefer seq_puts to seq_printf\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; - } - } - } - -# check for memcpy uses that should be memcpy_s - if ($SOF && ($line =~ /memcpy\s*\(.*/)) { - my $fmt = get_quoted_string($line, $rawline); - $fmt =~ s/%%//g; - if ($fmt !~ /%/) { - if (WARN("PREFER_MEMCPY_S", - "Use safe version of memcpy - memcpy_s whenever possible\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/memcpy\b/memcpy_s/; - } - } - } - -# check for vsprintf extension %p<foo> misuses - if ($perl_version_ok && - defined $stat && - $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s && - $1 !~ /^_*volatile_*$/) { - my $stat_real; - - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - for (my $count = $linenr; $count <= $lc; $count++) { - my $specifier; - my $extension; - my $bad_specifier = ""; - my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0)); - $fmt =~ s/%%//g; - - while ($fmt =~ /(\%[\*\d\.]*p(\w))/g) { - $specifier = $1; - $extension = $2; - if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOxt]/) { - $bad_specifier = $specifier; - last; - } - if ($extension eq "x" && !defined($stat_real)) { - if (!defined($stat_real)) { - $stat_real = get_stat_real($linenr, $lc); - } - WARN("VSPRINTF_SPECIFIER_PX", - "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n"); - } - } - if ($bad_specifier ne "") { - my $stat_real = get_stat_real($linenr, $lc); - my $ext_type = "Invalid"; - my $use = ""; - if ($bad_specifier =~ /p[Ff]/) { - $ext_type = "Deprecated"; - $use = " - use %pS instead"; - $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/); - } - - WARN("VSPRINTF_POINTER_EXTENSION", - "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n"); - } - } - } - -# Check for misused memsets - if ($perl_version_ok && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { - - my $ms_addr = $2; - my $ms_val = $7; - my $ms_size = $12; - - if ($ms_size =~ /^(0x|)0$/i) { - ERROR("MEMSET", - "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); - } elsif ($ms_size =~ /^(0x|)1$/i) { - WARN("MEMSET", - "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); - } - } - -# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) -# if ($perl_version_ok && -# defined $stat && -# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { -# if (WARN("PREFER_ETHER_ADDR_COPY", -# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && -# $fix) { -# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; -# } -# } - -# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) -# if ($perl_version_ok && -# defined $stat && -# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { -# WARN("PREFER_ETHER_ADDR_EQUAL", -# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") -# } - -# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr -# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr -# if ($perl_version_ok && -# defined $stat && -# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { -# -# my $ms_val = $7; -# -# if ($ms_val =~ /^(?:0x|)0+$/i) { -# if (WARN("PREFER_ETH_ZERO_ADDR", -# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && -# $fix) { -# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; -# } -# } elsif ($ms_val =~ /^(?:0xff|255)$/i) { -# if (WARN("PREFER_ETH_BROADCAST_ADDR", -# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && -# $fix) { -# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; -# } -# } -# } - -# typecasts on min/max could be min_t/max_t - if ($perl_version_ok && - defined $stat && - $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { - if (defined $2 || defined $7) { - my $call = $1; - my $cast1 = deparenthesize($2); - my $arg1 = $3; - my $cast2 = deparenthesize($7); - my $arg2 = $8; - my $cast; - - if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { - $cast = "$cast1 or $cast2"; - } elsif ($cast1 ne "") { - $cast = $cast1; - } else { - $cast = $cast2; - } - WARN("MINMAX", - "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); - } - } - -# check usleep_range arguments - if ($perl_version_ok && - defined $stat && - $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { - my $min = $1; - my $max = $7; - if ($min eq $max) { - WARN("USLEEP_RANGE", - "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n"); - } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && - $min > $max) { - WARN("USLEEP_RANGE", - "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n"); - } - } - -# check for naked sscanf - if ($perl_version_ok && - defined $stat && - $line =~ /\bsscanf\b/ && - ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && - $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && - $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = get_stat_real($linenr, $lc); - WARN("NAKED_SSCANF", - "unchecked sscanf return value\n" . "$here\n$stat_real\n"); - } - -# check for simple sscanf that should be kstrto<foo> - if ($perl_version_ok && - defined $stat && - $line =~ /\bsscanf\b/) { - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = get_stat_real($linenr, $lc); - if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { - my $format = $6; - my $count = $format =~ tr@%@%@; - if ($count == 1 && - $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { - WARN("SSCANF_TO_KSTRTO", - "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); - } - } - } - -# check for new externs in .h files. - if ($realfile =~ /\.h$/ && - $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { - if (CHK("AVOID_EXTERNS", - "extern prototypes should be avoided in .h files\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; - } - } - -# check for new externs in .c files. - if ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) - { - my $function_name = $1; - my $paren_space = $2; - - my $s = $stat; - if (defined $cond) { - substr($s, 0, length($cond), ''); - } - if ($s =~ /^\s*;/ && - $function_name ne 'uninitialized_var') - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - - if ($paren_space =~ /\n/) { - WARN("FUNCTION_ARGUMENTS", - "arguments for function declarations should follow identifier\n" . $herecurr); - } - - } elsif ($realfile =~ /\.c$/ && defined $stat && - $stat =~ /^.\s*extern\s+/) - { - WARN("AVOID_EXTERNS", - "externs should be avoided in .c files\n" . $herecurr); - } - -# check for function declarations that have arguments without identifier names - if (defined $stat && - $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s && - $1 ne "void") { - my $args = trim($1); - while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) { - my $arg = trim($1); - if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) { - WARN("FUNCTION_ARGUMENTS", - "function definition argument '$arg' should also have an identifier name\n" . $herecurr); - } - } - } - -# check for function definitions - if ($perl_version_ok && - defined $stat && - $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) { - $context_function = $1; - -# check for multiline function definition with misplaced open brace - my $ok = 0; - my $cnt = statement_rawlines($stat); - my $herectx = $here . "\n"; - for (my $n = 0; $n < $cnt; $n++) { - my $rl = raw_line($linenr, $n); - $herectx .= $rl . "\n"; - $ok = 1 if ($rl =~ /^[ \+]\{/); - $ok = 1 if ($rl =~ /\{/ && $n == 0); - last if $rl =~ /^[ \+].*\{/; - } - if (!$ok) { - ERROR("OPEN_BRACE", - "open brace '{' following function definitions go on the next line\n" . $herectx); - } - } - -# checks for new __setup's - if ($rawline =~ /\b__setup\("([^"]*)"/) { - my $name = $1; - - if (!grep(/$name/, @setup_docs)) { - CHK("UNDOCUMENTED_SETUP", - "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.rst\n" . $herecurr); - } - } - -# check for pointless casting of alloc functions - if ($line =~ /\*\s*\)\s*$allocFunctions\b/) { - WARN("UNNECESSARY_CASTS", - "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); - } - -# alloc style -# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) - if ($perl_version_ok && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { - CHK("ALLOC_SIZEOF_STRUCT", - "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); - } - -# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc - if ($perl_version_ok && - defined $stat && - $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { - my $oldfunc = $3; - my $a1 = $4; - my $a2 = $10; - my $newfunc = "kmalloc_array"; - $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); - my $r1 = $a1; - my $r2 = $a2; - if ($a1 =~ /^sizeof\s*\S/) { - $r1 = $a2; - $r2 = $a1; - } - if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && - !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { - my $cnt = statement_rawlines($stat); - my $herectx = get_stat_here($linenr, $cnt, $here); - - if (WARN("ALLOC_WITH_MULTIPLY", - "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) && - $cnt == 1 && - $fix) { - $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; - } - } - } - -# check for krealloc arg reuse - if ($perl_version_ok && - $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ && - $1 eq $3) { - WARN("KREALLOC_ARG_REUSE", - "Reusing the krealloc arg is almost always a bug\n" . $herecurr); - } - -# check for alloc argument mismatch - if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { - WARN("ALLOC_ARRAY_ARGS", - "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); - } - -# check for multiple semicolons - if ($line =~ /;\s*;\s*$/) { - if (WARN("ONE_SEMICOLON", - "Statements terminations use 1 semicolon\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; - } - } - -# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi - if ($realfile !~ m@^include/uapi/@ && - $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { - my $ull = ""; - $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); - if (CHK("BIT_MACRO", - "Prefer using the BIT$ull macro\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; - } - } - -# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE - if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { - my $config = $1; - if (WARN("PREFER_IS_ENABLED", - "Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)"; - } - } - -# check for case / default statements not preceded by break/fallthrough/switch - if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { - my $has_break = 0; - my $has_statement = 0; - my $count = 0; - my $prevline = $linenr; - while ($prevline > 1 && ($file || $count < 3) && !$has_break) { - $prevline--; - my $rline = $rawlines[$prevline - 1]; - my $fline = $lines[$prevline - 1]; - last if ($fline =~ /^\@\@/); - next if ($fline =~ /^\-/); - next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/); - $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i); - next if ($fline =~ /^.[\s$;]*$/); - $has_statement = 1; - $count++; - $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|exit\s*\(\b|return\b|goto\b|continue\b)/); - } - if (!$has_break && $has_statement) { - WARN("MISSING_BREAK", - "Possible switch case/default not preceded by break or fallthrough comment\n" . $herecurr); - } - } - -# check for switch/default statements without a break; - if ($perl_version_ok && - defined $stat && - $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { - my $cnt = statement_rawlines($stat); - my $herectx = get_stat_here($linenr, $cnt, $here); - - WARN("DEFAULT_NO_BREAK", - "switch default: should use break\n" . $herectx); - } - -# check for gcc specific __FUNCTION__ - if ($line =~ /\b__FUNCTION__\b/) { - if (WARN("USE_FUNC", - "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; - } - } - -# check for uses of __DATE__, __TIME__, __TIMESTAMP__ - while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { - ERROR("DATE_TIME", - "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); - } - -# check for use of yield() - if ($line =~ /\byield\s*\(\s*\)/) { - WARN("YIELD", - "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); - } - -# check for comparisons against true and false - if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { - my $lead = $1; - my $arg = $2; - my $test = $3; - my $otype = $4; - my $trail = $5; - my $op = "!"; - - ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); - - my $type = lc($otype); - if ($type =~ /^(?:true|false)$/) { - if (("$test" eq "==" && "$type" eq "true") || - ("$test" eq "!=" && "$type" eq "false")) { - $op = ""; - } - - CHK("BOOL_COMPARISON", - "Using comparison to $otype is error prone\n" . $herecurr); - -## maybe suggesting a correct construct would better -## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); - - } - } - -# check for semaphores initialized locked - if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { - WARN("CONSIDER_COMPLETION", - "consider using a completion\n" . $herecurr); - } - -# recommend kstrto* over simple_strto* and strict_strto* - if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { - WARN("CONSIDER_KSTRTO", - "$1 is obsolete, use k$3 instead\n" . $herecurr); - } - -# check for __initcall(), use device_initcall() explicitly or more appropriate function please - if ($line =~ /^.\s*__initcall\s*\(/) { - WARN("USE_DEVICE_INITCALL", - "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); - } - -# check for spin_is_locked(), suggest lockdep instead - if ($line =~ /\bspin_is_locked\(/) { - WARN("USE_LOCKDEP", - "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr); - } - -# check for deprecated apis - if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) { - my $deprecated_api = $1; - my $new_api = $deprecated_apis{$deprecated_api}; - WARN("DEPRECATED_API", - "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr); - } - -# check for various structs that are normally const (ops, kgdb, device_tree) -# and avoid what seem like struct definitions 'struct foo {' - if ($line !~ /\bconst\b/ && - $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) { - WARN("CONST_STRUCT", - "struct $1 should normally be const\n" . $herecurr); - } - -# use of NR_CPUS is usually wrong -# ignore definitions of NR_CPUS and usage to define arrays as likely right - if ($line =~ /\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && - $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && - $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) - { - WARN("NR_CPUS", - "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); - } - -# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. - if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { - ERROR("DEFINE_ARCH_HAS", - "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); - } - -# likely/unlikely comparisons similar to "(likely(foo) > 0)" - if ($perl_version_ok && - $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { - WARN("LIKELY_MISUSE", - "Using $1 should generally have parentheses around the comparison\n" . $herecurr); - } - -# nested likely/unlikely calls - if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) { - WARN("LIKELY_MISUSE", - "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr); - } - -# whine mightly about in_atomic - if ($line =~ /\bin_atomic\s*\(/) { - if ($realfile =~ m@^drivers/@) { - ERROR("IN_ATOMIC", - "do not use in_atomic in drivers\n" . $herecurr); - } elsif ($realfile !~ m@^kernel/@) { - WARN("IN_ATOMIC", - "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); - } - } - -# check for mutex_trylock_recursive usage - if ($line =~ /mutex_trylock_recursive/) { - ERROR("LOCKING", - "recursive locking is bad, do not use this ever.\n" . $herecurr); - } - -# check for lockdep_set_novalidate_class - if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || - $line =~ /__lockdep_no_validate__\s*\)/ ) { - if ($realfile !~ m@^kernel/lockdep@ && - $realfile !~ m@^include/linux/lockdep@ && - $realfile !~ m@^drivers/base/core@) { - ERROR("LOCKDEP", - "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); - } - } - - if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || - $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { - WARN("EXPORTED_WORLD_WRITABLE", - "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - -# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO> -# and whether or not function naming is typical and if -# DEVICE_ATTR permissions uses are unusual too - if ($perl_version_ok && - defined $stat && - $stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) { - my $var = $1; - my $perms = $2; - my $show = $3; - my $store = $4; - my $octal_perms = perms_to_octal($perms); - if ($show =~ /^${var}_show$/ && - $store =~ /^${var}_store$/ && - $octal_perms eq "0644") { - if (WARN("DEVICE_ATTR_RW", - "Use DEVICE_ATTR_RW\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/; - } - } elsif ($show =~ /^${var}_show$/ && - $store =~ /^NULL$/ && - $octal_perms eq "0444") { - if (WARN("DEVICE_ATTR_RO", - "Use DEVICE_ATTR_RO\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/; - } - } elsif ($show =~ /^NULL$/ && - $store =~ /^${var}_store$/ && - $octal_perms eq "0200") { - if (WARN("DEVICE_ATTR_WO", - "Use DEVICE_ATTR_WO\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/; - } - } elsif ($octal_perms eq "0644" || - $octal_perms eq "0444" || - $octal_perms eq "0200") { - my $newshow = "$show"; - $newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show"); - my $newstore = $store; - $newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store"); - my $rename = ""; - if ($show ne $newshow) { - $rename .= " '$show' to '$newshow'"; - } - if ($store ne $newstore) { - $rename .= " '$store' to '$newstore'"; - } - WARN("DEVICE_ATTR_FUNCTIONS", - "Consider renaming function(s)$rename\n" . $herecurr); - } else { - WARN("DEVICE_ATTR_PERMS", - "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr); - } - } - -# Mode permission misuses where it seems decimal should be octal -# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop -# o Ignore module_param*(...) uses with a decimal 0 permission as that has a -# specific definition of not visible in sysfs. -# o Ignore proc_create*(...) uses with a decimal 0 permission as that means -# use the default permissions - if ($perl_version_ok && - defined $stat && - $line =~ /$mode_perms_search/) { - foreach my $entry (@mode_permission_funcs) { - my $func = $entry->[0]; - my $arg_pos = $entry->[1]; - - my $lc = $stat =~ tr@\n@@; - $lc = $lc + $linenr; - my $stat_real = get_stat_real($linenr, $lc); - - my $skip_args = ""; - if ($arg_pos > 1) { - $arg_pos--; - $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; - } - my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]"; - if ($stat =~ /$test/) { - my $val = $1; - $val = $6 if ($skip_args ne ""); - if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") && - (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || - ($val =~ /^$Octal$/ && length($val) ne 4))) { - ERROR("NON_OCTAL_PERMISSIONS", - "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real); - } - if ($val =~ /^$Octal$/ && (oct($val) & 02)) { - ERROR("EXPORTED_WORLD_WRITABLE", - "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real); - } - } - } - } - -# check for uses of S_<PERMS> that could be octal for readability - while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) { - my $oval = $1; - my $octal = perms_to_octal($oval); - if (WARN("SYMBOLIC_PERMS", - "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/; - } - } - -# validate content of MODULE_LICENSE against list from include/linux/module.h - if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { - my $extracted_string = get_quoted_string($line, $rawline); - my $valid_licenses = qr{ - GPL| - GPL\ v2| - GPL\ and\ additional\ rights| - Dual\ BSD/GPL| - Dual\ MIT/GPL| - Dual\ MPL/GPL| - Proprietary - }x; - if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { - WARN("MODULE_LICENSE", - "unknown module license " . $extracted_string . "\n" . $herecurr); - } - } - -# check for sysctl duplicate constants - if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) { - WARN("DUPLICATED_SYSCTL_CONST", - "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr); - } - } - - # If we have no input at all, then there is nothing to report on - # so just keep quiet. - if ($#rawlines == -1) { - exit(0); - } - - # In mailback mode only produce a report in the negative, for - # things that appear to be patches. - if ($mailback && ($clean == 1 || !$is_patch)) { - exit(0); - } - - # This is not a patch, and we are are in 'no-patch' mode so - # just keep quiet. - if (!$chk_patch && !$is_patch) { - exit(0); - } - - if (!$is_patch && $filename !~ /cover-letter\.patch$/) { - ERROR("NOT_UNIFIED_DIFF", - "Does not appear to be a unified-diff format patch\n"); - } - if ($is_patch && $has_commit_log && $chk_signoff) { - if ($signoff == 0) { - ERROR("MISSING_SIGN_OFF", - "Missing Signed-off-by: line(s)\n"); - } elsif (!$authorsignoff) { - WARN("NO_AUTHOR_SIGN_OFF", - "Missing Signed-off-by: line by nominal patch author '$author'\n"); - } - } - - print report_dump(); - if ($summary && !($clean == 1 && $quiet == 1)) { - print "$filename " if ($summary_file); - print "total: $cnt_error errors, $cnt_warn warnings, " . - (($check)? "$cnt_chk checks, " : "") . - "$cnt_lines lines checked\n"; - } - - if ($quiet == 0) { - # If there were any defects found and not already fixing them - if (!$clean and !$fix) { - print << "EOM" - -NOTE: For some of the reported defects, checkpatch may be able to - mechanically convert to the typical style using --fix or --fix-inplace. -EOM - } - # If there were whitespace errors which cleanpatch can fix - # then suggest that. - if ($rpt_cleaners) { - $rpt_cleaners = 0; - print << "EOM" - -NOTE: Whitespace errors detected. - You may wish to use scripts/cleanpatch or scripts/cleanfile -EOM - } - } - - if ($clean == 0 && $fix && - ("@rawlines" ne "@fixed" || - $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { - my $newfile = $filename; - $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); - my $linecount = 0; - my $f; - - @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); - - open($f, '>', $newfile) - or die "$P: Can't open $newfile for write\n"; - foreach my $fixed_line (@fixed) { - $linecount++; - if ($file) { - if ($linecount > 3) { - $fixed_line =~ s/^\+//; - print $f $fixed_line . "\n"; - } - } else { - print $f $fixed_line . "\n"; - } - } - close($f); - - if (!$quiet) { - print << "EOM"; - -Wrote EXPERIMENTAL --fix correction(s) to '$newfile' - -Do _NOT_ trust the results written to this file. -Do _NOT_ submit these changes without inspecting them for correctness. - -This EXPERIMENTAL file is simply a convenience to help rewrite patches. -No warranties, expressed or implied... -EOM - } - } - - if ($quiet == 0) { - print "\n"; - if ($clean == 1) { - print "$vname has no obvious style problems and is ready for submission.\n"; - } else { - print "$vname has style problems, please review.\n"; - } - } - return $clean; -} diff --git a/scripts/cmake/defconfigs.cmake b/scripts/cmake/defconfigs.cmake index 2448aea0540b..9bdbd23539a8 100644 --- a/scripts/cmake/defconfigs.cmake +++ b/scripts/cmake/defconfigs.cmake @@ -1,8 +1,8 @@ # SPDX-License-Identifier: BSD-3-Clause -# Looks for defconfig files in arch directory -set(DEFCONFIGS_DIRECTORY "${PROJECT_SOURCE_DIR}/src/arch/${ARCH}/configs/*_defconfig") -file(GLOB DEFCONFIG_PATHS ${DEFCONFIGS_DIRECTORY}) +# Looks for defconfig files in arch directories where kconfig.cmake looks too. +set(DEFCONFIGS_DIRECTORY "${PROJECT_SOURCE_DIR}/src/arch/${ARCH}/configs") +file(GLOB DEFCONFIG_PATHS "${DEFCONFIGS_DIRECTORY}/*_defconfig") # Adds dependency on defconfigs directory set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${DEFCONFIGS_DIRECTORY}) @@ -27,3 +27,27 @@ foreach(defconfig_path ${DEFCONFIG_PATHS}) USES_TERMINAL ) endforeach() + +set(OVERRIDE_DEFCONFIGS_DIRECTORY "${DEFCONFIGS_DIRECTORY}/override") +file(GLOB OVERRIDE_DEFCONFIGS_PATHS "${OVERRIDE_DEFCONFIGS_DIRECTORY}/*.config") + +foreach(config_path ${OVERRIDE_DEFCONFIGS_PATHS}) + get_filename_component(config_name ${config_path} NAME_WE) + add_custom_target( + "${config_name}_overridedefconfig" + COMMAND ${CMAKE_COMMAND} -E copy + ${config_path} + ${PROJECT_BINARY_DIR}/override.config + COMMAND ${CMAKE_COMMAND} -E env + srctree=${PROJECT_SOURCE_DIR} + CC_VERSION_TEXT=${CC_VERSION_TEXT} + ARCH=${ARCH} + ${PYTHON3} ${PROJECT_SOURCE_DIR}/scripts/kconfig/overrideconfig.py + ${PROJECT_SOURCE_DIR}/Kconfig + ${PROJECT_BINARY_DIR}/override.config + WORKING_DIRECTORY ${GENERATED_DIRECTORY} + COMMENT "Applying overrideconfig with ${config_name}" + VERBATIM + USES_TERMINAL + ) +endforeach() diff --git a/scripts/cmake/dist.cmake b/scripts/cmake/dist.cmake index cb9f639ffc30..ea7f1ead5621 100644 --- a/scripts/cmake/dist.cmake +++ b/scripts/cmake/dist.cmake @@ -1,20 +1,34 @@ # SPDX-License-Identifier: BSD-3-Clause -# depends on version.cmake -# Adds dist target +# This creates a release tarball from a git checkout. +# +# Warning: a ".tarball-version" at the top of the source directory takes +# precedence; even for git checkouts it does! This can be used to make +# the build "more deterministic". See GIT_TAG in version.cmake. -set(TARBALL_PATH_TMP "${PROJECT_BINARY_DIR}/sof-${GIT_TAG}.tar") -set(TARBALL_PATH "${PROJECT_BINARY_DIR}/sof-${GIT_TAG}.tgz") +set(TAR_BASENAME sof-${GIT_TAG}) +set(TARBALL_PATH_TMP "${PROJECT_BINARY_DIR}/${TAR_BASENAME}.tar") +set(TARBALL_PATH "${PROJECT_BINARY_DIR}/${TAR_BASENAME}.tgz") set(TARBALL_VERSION_BINARY_PATH "${PROJECT_BINARY_DIR}/${TARBALL_VERSION_FILE_NAME}") add_custom_target(dist - COMMAND git archive -o "${TARBALL_PATH_TMP}" HEAD + COMMAND git archive --prefix=${TAR_BASENAME}/ -o "${TARBALL_PATH_TMP}" HEAD + + # .tarball-version in the top build directory for git users' convenience COMMAND ${CMAKE_COMMAND} -E echo "${GIT_TAG}" > "${TARBALL_VERSION_BINARY_PATH}" COMMAND ${CMAKE_COMMAND} -E echo "${GIT_LOG_HASH}" >> "${TARBALL_VERSION_BINARY_PATH}" - COMMAND tar rf "${TARBALL_PATH_TMP}" -C "${PROJECT_BINARY_DIR}" "${TARBALL_VERSION_FILE_NAME}" + + # ${TAR_BASENAME}/.tarball-version for the release tarball + COMMAND ${CMAKE_COMMAND} -E make_directory "${PROJECT_BINARY_DIR}/${TAR_BASENAME}" + COMMAND ${CMAKE_COMMAND} -E copy "${TARBALL_VERSION_BINARY_PATH}" "${PROJECT_BINARY_DIR}/${TAR_BASENAME}/${TARBALL_VERSION_FILE_NAME}" + COMMAND tar rf "${TARBALL_PATH_TMP}" -C "${PROJECT_BINARY_DIR}" "${TAR_BASENAME}/${TARBALL_VERSION_FILE_NAME}" + COMMAND gzip -9 < "${TARBALL_PATH_TMP}" > "${TARBALL_PATH}" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" - COMMENT "Creating tarball: ${TARBALL_PATH}" + COMMENT "Creating tarball: ${TARBALL_PATH} +Warning: you must invoke make/ninja 'rebuild_cache' when the version changes, 'clean' is not enough. +" BYPRODUCTS "$TARBALL_VERSION_BINARY_PATH" "${TARBALL_PATH_TMP}" "${TARBALL_PATH}" VERBATIM USES_TERMINAL diff --git a/scripts/cmake/git-submodules.cmake b/scripts/cmake/git-submodules.cmake new file mode 100644 index 000000000000..56c559491b90 --- /dev/null +++ b/scripts/cmake/git-submodules.cmake @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: BSD-3-Clause + +set(RIMAGE_SUBMODULE "${SOF_ROOT_SOURCE_DIRECTORY}/rimage") +if(EXISTS "${RIMAGE_SUBMODULE}/CMakeLists.txt") + message(WARNING + "${RIMAGE_SUBMODULE} is deprecated and ignored" + ) +endif() + +find_package(Git) +set(TOMLC99_MAKE "${SOF_ROOT_SOURCE_DIRECTORY}/tools/rimage/tomlc99/Makefile") +if(GIT_FOUND AND EXISTS "${SOF_ROOT_SOURCE_DIRECTORY}/.git") + + if(EXISTS "${TOMLC99_MAKE}") + + # As incredible as it sounds, some people run neither + # "git status" nor "git diff" every few minutes and not + # even when their build fails. There has been reports + # that they're puzzled when they miss a required + # submodule update. This is an attempt to draw their + # attention based on the assumption that they pay more + # attention to the CMake logs. The warning can be + # silenced with I_KNOW_SUBMODULES, see below. + execute_process(COMMAND ${GIT_EXECUTABLE} submodule status --recursive + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE stdout + RESULT_VARIABLE status) + + if(NOT "${status}" EQUAL "0") + # stderr was passed-through + message(FATAL_ERROR +"git submodule status --recursive failed, returned: ${status}\n${stdout}") + endif() + + if(NOT "$ENV{I_KNOW_SUBMODULES}" AND + ("${stdout}" MATCHES "^[^ ]" OR "${stdout}" MATCHES "\n[^ ]")) + message(WARNING +"There are submodule changes, check git status and git diff\n${stdout}") + endif() + + elseif(NOT BUILD_UNIT_TESTS AND + NOT CONFIG_LIBRARY) + + message(FATAL_ERROR +"${TOMLC99_MAKE} not found. You should have used 'git clone --recursive'. \ +To fix this existing git clone run: +git submodule update --init --merge tools/rimage/tomlc99 +") + endif() # tomlc99/Makefile + +endif() # .git/ diff --git a/scripts/cmake/kconfig.cmake b/scripts/cmake/kconfig.cmake index e503381fd8e5..0472f606fcc1 100644 --- a/scripts/cmake/kconfig.cmake +++ b/scripts/cmake/kconfig.cmake @@ -1,9 +1,105 @@ # SPDX-License-Identifier: BSD-3-Clause -# Kconfig targets - include(${CMAKE_CURRENT_LIST_DIR}/defconfigs.cmake) + + ### configure-time .config ### + + +if(NOT INIT_CONFIG_found) +# Brand new build directory, search for initial configuration + +# Default value when no -DINIT_CONFIG on the command line +set(INIT_CONFIG "initial.config" CACHE STRING "Initial .config file") + +# - ".' is the top source directory. +# - "src/arch/${arch}/configs" is for convenience and compatibility with +# defconfigs.cmake. +# - First found wins. +# - If two archs ever use the same platform_defconfig name then a full +# path must be used, e.g.: -DINIT_CONFIG=src/arch/myarch/collision_defconfig + +set(init_config_search_list ".") +foreach(arch "xtensa" "host") +list(APPEND init_config_search_list "src/arch/${arch}/configs") +endforeach() + +find_file(INIT_CONFIG_found + NAMES ${INIT_CONFIG} + NO_CMAKE_FIND_ROOT_PATH + NO_DEFAULT_PATH + PATHS ${init_config_search_list} +) + +else() # old build directory + +if (INIT_CONFIG) +message(WARNING + "IGNORING '-DINIT_CONFIG=${INIT_CONFIG}!!' " + "Using up-to-date ${INIT_CONFIG_found} instead." +) +endif() + +endif() # new/old build directory + + +if(NOT INIT_CONFIG_found) +message(FATAL_ERROR + "Initial configuration missing, no ${INIT_CONFIG} found. " + "Provide a ${PROJECT_SOURCE_DIR}/initial.config file or specify some " + "other -DINIT_CONFIG=location relative to '${PROJECT_SOURCE_DIR}/' or " + "'${PROJECT_SOURCE_DIR}/src/arch/*/configs/'" +) +endif() + +# Did someone or something remove our generated/.config? +if(NOT EXISTS ${INIT_CONFIG_found}) +message(FATAL_ERROR "The file ${INIT_CONFIG_found} vanished!") +endif() + +# Don't confuse this configure-time, .config generation with +# the build-time, autoconfig.h genconfig target below +message(STATUS + "(Re-)generating ${DOT_CONFIG_PATH}\n" + " and ${CONFIG_H_PATH}\n" + " from ${INIT_CONFIG_found}" +) +execute_process( + COMMAND ${CMAKE_COMMAND} -E env + KCONFIG_CONFIG=${INIT_CONFIG_found} + srctree=${PROJECT_SOURCE_DIR} + CC_VERSION_TEXT=${CC_VERSION_TEXT} + ARCH=${ARCH} + ${PYTHON3} ${PROJECT_SOURCE_DIR}/scripts/kconfig/genconfig.py + --config-out=${DOT_CONFIG_PATH} + --header-path ${CONFIG_H_PATH} + ${PROJECT_SOURCE_DIR}/Kconfig + WORKING_DIRECTORY ${GENERATED_DIRECTORY} + # Available only from CMake 3.18. Amazingly not the default. + # COMMAND_ERROR_IS_FATAL ANY + RESULT_VARIABLE _genret +) +if(${_genret}) +message(FATAL_ERROR + "genconfig.py from ${INIT_CONFIG_found} to ${DOT_CONFIG_PATH} failed") +endif() + +if(NOT ${INIT_CONFIG_found} STREQUAL ${DOT_CONFIG_PATH}) +# Brand new build directory and config. +message(STATUS + "Done, future changes to ${INIT_CONFIG_found}\n" + " will be IGNORED by this build directory! The primary .config\n" + " file is now 'generated/.config' in the build directory." +) +endif() +# Now force CMake to forget about the initial config and to re-use our +# own private ${DOT_CONFIG_PATH} when it decides it must re-run itself. +unset(INIT_CONFIG CACHE) +set(INIT_CONFIG_found ${DOT_CONFIG_PATH} CACHE FILEPATH "active .config" FORCE) + + + ### build-time Kconfig targets ### + add_custom_target( menuconfig COMMAND ${CMAKE_COMMAND} -E env @@ -33,24 +129,9 @@ add_custom_target( file(GLOB_RECURSE KCONFIG_FILES "${SOF_ROOT_SOURCE_DIRECTORY}/Kconfig") -if(EXISTS ${DOT_CONFIG_PATH}) - # Update with olddefconfig only if config was previously generated - add_custom_command( - OUTPUT ${DOT_CONFIG_PATH} - COMMAND ${CMAKE_COMMAND} -E env - srctree=${PROJECT_SOURCE_DIR} - CC_VERSION_TEXT=${CC_VERSION_TEXT} - ARCH=${ARCH} - ${PYTHON3} ${PROJECT_SOURCE_DIR}/scripts/kconfig/olddefconfig.py - ${PROJECT_SOURCE_DIR}/Kconfig - DEPENDS ${KCONFIG_FILES} - WORKING_DIRECTORY ${GENERATED_DIRECTORY} - COMMENT "Regenerating .config with olddefconfig" - VERBATIM - USES_TERMINAL - ) -endif() +# Don't confuse this build-time, .h target with the +# configure-time, .config genconfig above. add_custom_command( OUTPUT ${CONFIG_H_PATH} COMMAND ${CMAKE_COMMAND} -E env diff --git a/scripts/cmake/llext_write_uuids.cmake b/scripts/cmake/llext_write_uuids.cmake new file mode 100644 index 000000000000..ad608c0e5e17 --- /dev/null +++ b/scripts/cmake/llext_write_uuids.cmake @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Used by LLEXT modules to create a file with module UUIDs +file(STRINGS ${ZEPHYR_BINARY_DIR}/${MODULE}_llext/rimage_config.toml uuids REGEX "^[ \t]*uuid *=") + +set(UUIDS_LIST_FILE ${ZEPHYR_BINARY_DIR}/${MODULE}_llext/llext.uuid) +file(REMOVE ${UUIDS_LIST_FILE}) +foreach(line IN LISTS uuids) + # extract UUID value - drop the 'uuid = ' part of the assignment line + string(REGEX REPLACE "^[ \t]*uuid *= \"([0-9A-Fa-f\\-]*)\"" "\\1" uuid ${line}) + string(TOUPPER ${uuid} uuid) + file(APPEND ${UUIDS_LIST_FILE} "${uuid}\n") +endforeach() diff --git a/scripts/cmake/misc.cmake b/scripts/cmake/misc.cmake index c4af6019f66d..647b69c8c478 100644 --- a/scripts/cmake/misc.cmake +++ b/scripts/cmake/misc.cmake @@ -35,9 +35,37 @@ function(get_optimization_flag OUT_VAR) set(${OUT_VAR} "Og" PARENT_SCOPE) elseif(CONFIG_OPTIMIZE_FOR_NONE) set(${OUT_VAR} "O0" PARENT_SCOPE) + else() + message(FATAL_ERROR "no CONFIG_OPTIMIZE_ found") endif() endfunction() +# Zephyr duplicate in sof/zephyr/CMakeLists.txt; keep in sync +macro(is_zephyr ret) + if(CONFIG_ZEPHYR_SOF_MODULE) + set(${ret} TRUE) + else() + set(${ret} FALSE) + endif() +endmacro() + +# This macro +# - saves a LOT of repetition, and +# - mimics Zephyr, which helps with compatibility. +macro(add_local_sources_ifdef condition target) + if(${condition}) + add_local_sources(${target} ${ARGN}) + endif() +endmacro() + +# helper macro used similarly as add_local_sources_ifdef +# Zephyr duplicate in sof/zephyr/CMakeLists.txt; keep in sync +macro(sof_list_append_ifdef feature_toggle list) + if(${${feature_toggle}}) + list(APPEND ${list} ${ARGN}) + endif() +endmacro() + # Adds sources to target like target_sources, but assumes that # paths are relative to subdirectory. # Works like: @@ -54,6 +82,12 @@ function(add_local_sources target) endif() target_sources(${target} PRIVATE ${path}) + # -imacros${CONFIG_H_PATH} escapes regular .h dep scanning + # add_dependencies(${target} genconfig) # has no effect? + set_source_files_properties(${path} + PROPERTIES + OBJECT_DEPENDS ${CONFIG_H_PATH} + ) endforeach() endfunction() diff --git a/scripts/cmake/uuid-registry.cmake b/scripts/cmake/uuid-registry.cmake new file mode 100644 index 000000000000..0d3b287a7d62 --- /dev/null +++ b/scripts/cmake/uuid-registry.cmake @@ -0,0 +1,37 @@ +# +# UUID registry generation +# + +# Simple target. FOUR (really 4.5, as LIBRARY builds use the same +# CMakeLists.txt but differ significantly in how it executes) +# different cmake environments into which it needs to build. +is_zephyr(zephyr) +if(zephyr) + set(TOPDIR ${sof_top_dir}) + set(UUID_REG_H ${PROJECT_BINARY_DIR}/include/generated/uuid-registry.h) + set(DEP_TARGET zephyr_interface) +elseif(${PROJECT_NAME} STREQUAL "SOF_TOOLS") + set(TOPDIR "${PROJECT_SOURCE_DIR}/..") + set(UUID_REG_H "${CMAKE_CURRENT_BINARY_DIR}/uuid-registry.h") + set(DEP_TARGET sof-logger) +elseif(${PROJECT_NAME} STREQUAL "SOF_TPLG_PARSER") + set(TOPDIR "${PROJECT_SOURCE_DIR}/../..") + set(UUID_REG_H "${PROJECT_BINARY_DIR}/include/uuid-registry.h") + set(DEP_TARGET sof_tplg_parser) +else() + # Legacy SOF, or CONFIG_LIBRARY + set(TOPDIR ${PROJECT_SOURCE_DIR}) + set(UUID_REG_H ${PROJECT_BINARY_DIR}/generated/include/uuid-registry.h) + set(DEP_TARGET sof_public_headers) +endif() + +add_custom_command( + OUTPUT ${UUID_REG_H} + COMMAND + ${PYTHON_EXECUTABLE} ${TOPDIR}/scripts/gen-uuid-reg.py + ${TOPDIR}/uuid-registry.txt + ${UUID_REG_H}) + +add_custom_target(uuid_reg_h DEPENDS ${UUID_REG_H}) + +add_dependencies(${DEP_TARGET} uuid_reg_h) diff --git a/scripts/cmake/version-build-counter.cmake b/scripts/cmake/version-build-counter.cmake index 7946c0f59845..c3bcb3b5985b 100644 --- a/scripts/cmake/version-build-counter.cmake +++ b/scripts/cmake/version-build-counter.cmake @@ -2,12 +2,16 @@ # Implements build counter and adds it as post-build action for sof -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) set(VERSION_BUILD_COUNTER_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/version-build-counter.cmake) 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 719cfd9852e1..54e4d0339493 100644 --- a/scripts/cmake/version.cmake +++ b/scripts/cmake/version.cmake @@ -1,49 +1,93 @@ # 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.10) +cmake_minimum_required(VERSION 3.19) set(VERSION_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/version.cmake) + +# In an ideal world, every CI engine records the most basic and most +# important information: +# - current date and time +# - git version of the pull request +# - git version of the moving branch it's being merged with +# +# In the real world, some CI results use a random timezone without +# telling which one or don't provide any time at all. +string(TIMESTAMP build_start_time UTC) +message(STATUS "SOF version.cmake starting at ${build_start_time} UTC") + +# Most CI engines test a temporary merge of the pull request with a +# moving target: the latest target branch. In that case the HEAD SHA is +# very volatile and the --parents are much more relevant and useful. +# +# --no-abbrev-commit because some git servers like github allow fetching +# by full length SHA (others forbid this entirely, see last page of +# `git help fetch-pack`) +message(STATUS "${SOF_ROOT_SOURCE_DIRECTORY} is at git commit with parent(s):") +# Note execute_process() failures are ignored by default (missing git...) +execute_process( + COMMAND git -C "${SOF_ROOT_SOURCE_DIRECTORY}" + log --parents --no-abbrev-commit --decorate -n 1 HEAD + ) + + +# Don't confuse this manual _input_ file with the other, output file of +# the same name auto-generated in the top _build_ directory by "make +# dist", see dist.cmake set(TARBALL_VERSION_FILE_NAME ".tarball-version") + set(TARBALL_VERSION_SOURCE_PATH "${SOF_ROOT_SOURCE_DIRECTORY}/${TARBALL_VERSION_FILE_NAME}") if(EXISTS ${TARBALL_VERSION_SOURCE_PATH}) file(STRINGS ${TARBALL_VERSION_SOURCE_PATH} lines ENCODING "UTF-8") list(GET lines 0 GIT_TAG) list(GET lines 1 GIT_LOG_HASH) - message(STATUS "Found ${TARBALL_VERSION_FILE_NAME}") - message(STATUS "Version: ${GIT_TAG} / ${GIT_LOG_HASH}") + message(STATUS "Found ${TARBALL_VERSION_SOURCE_PATH}") else() - execute_process(COMMAND git describe --tags --abbrev=4 + # execute_process() errors are not fatal by default! + execute_process( + COMMAND git describe --tags --abbrev=12 --match v* --dirty + WORKING_DIRECTORY ${SOF_ROOT_SOURCE_DIRECTORY} OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET ) execute_process(COMMAND git log --pretty=format:%h -1 + WORKING_DIRECTORY ${SOF_ROOT_SOURCE_DIRECTORY} OUTPUT_VARIABLE GIT_LOG_HASH OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET ) endif() if(NOT GIT_TAG MATCHES "^v") + message(WARNING + "git describe found ${GIT_TAG} / nothing starting with 'v'. Shallow clone?") set(GIT_TAG "v0.0-0-g0000") endif() -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}) +message(STATUS "GIT_TAG / GIT_LOG_HASH : ${GIT_TAG} / ${GIT_LOG_HASH}") + +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() @@ -52,9 +96,71 @@ if(NOT SOF_TAG) set(SOF_TAG 0) endif() +# Calculate source hash value, used to check ldc file and firmware compatibility +if(EXISTS ${SOF_ROOT_SOURCE_DIRECTORY}/.git/) + set(SOURCE_HASH_DIR "${SOF_ROOT_BINARY_DIRECTORY}/source_hash") + file(MAKE_DIRECTORY ${SOURCE_HASH_DIR}) + + # When building with Zephyr, add a few extra files so the XTOS + # and Zephyr .ldc files (which have different content!) do not + # end up with the exact same "source checksum". The concept of + # source checksum is flawed (see issue #3890) but this is much + # better than nothing at all. + # + # Warning: ZEPHYR_CURRENT_MODULE_DIR is _undefined_ the first + # time we're run and _defined empty_ the second time. To + # understand why look at the check_version_h target below. + if("${ZEPHYR_CURRENT_MODULE_DIR}" STREQUAL "") + set(_sof_zephyr_dir "") + else() + set(_sof_zephyr_dir "zephyr/") + endif() + + # list tracked files from src directory + execute_process(COMMAND git ls-files src/ scripts/ ${_sof_zephyr_dir} + WORKING_DIRECTORY ${SOF_ROOT_SOURCE_DIRECTORY} + OUTPUT_FILE "${SOURCE_HASH_DIR}/tracked_file_list" + ) + # calculate hash of each listed files (from file version saved in file system) + execute_process(COMMAND git hash-object --stdin-paths + WORKING_DIRECTORY ${SOF_ROOT_SOURCE_DIRECTORY} + INPUT_FILE "${SOURCE_HASH_DIR}/tracked_file_list" + OUTPUT_FILE "${SOURCE_HASH_DIR}/tracked_file_hash_list" + ) + # then calculate single hash of previously calculated hash list + execute_process(COMMAND git hash-object --stdin + WORKING_DIRECTORY ${SOF_ROOT_SOURCE_DIRECTORY} + OUTPUT_STRIP_TRAILING_WHITESPACE + INPUT_FILE "${SOURCE_HASH_DIR}/tracked_file_hash_list" + OUTPUT_VARIABLE SOF_SRC_HASH_LONG + ) + string(SUBSTRING ${SOF_SRC_HASH_LONG} 0 8 SOF_SRC_HASH) + message(STATUS "Source content hash: ${SOF_SRC_HASH}. \ +Notes: + - by design, source hash is broken by Kconfig changes. See #3890. + - Source hash is also broken by _asymmetric_ autocrlf=input, see + #5917 and reverted #5920.") +else() # Zephyr, tarball,... + if(NOT "${GIT_LOG_HASH}" STREQUAL "") + string(SUBSTRING "${GIT_LOG_HASH}" 0 8 SOF_SRC_HASH) + else() + set(SOF_SRC_HASH "baadf00d") + endif() + message(WARNING "${SOF_ROOT_SOURCE_DIRECTORY}/.git not found, \ +source content hash cannot computed for the .ldc. Using SOF_SRC_HASH=${SOF_SRC_HASH} \ +from GIT_LOG_HASH instead") +endif() + # for SOF_BUILD include(${CMAKE_CURRENT_LIST_DIR}/version-build-counter.cmake) +# (Re)-generate "${VERSION_H_PATH}" but overwrite the old one only if +# different to avoid a full rebuild. TODO: check how Zephyr solves this +# problem, see Zephyr commit 91709778a4878c +# +# This function is called only below; not supposed to be used elsewhere. +# This entire file is run at CMake configure time _and_ invoked +# again at build time. function(sof_check_version_h) string(CONCAT header_content "#define SOF_MAJOR ${SOF_MAJOR}\n" @@ -62,21 +168,28 @@ function(sof_check_version_h) "#define SOF_MICRO ${SOF_MICRO}\n" "#define SOF_TAG \"${SOF_TAG}\"\n" "#define SOF_BUILD ${SOF_BUILD}\n" + "#define SOF_GIT_TAG \"${GIT_TAG}\"\n" + "#define SOF_SRC_HASH 0x${SOF_SRC_HASH}\n" ) if(EXISTS "${VERSION_H_PATH}") file(READ "${VERSION_H_PATH}" old_version_content) if("${header_content}" STREQUAL "${old_version_content}") - message(STATUS "Up-to-date ${VERSION_H_PATH}") + message(STATUS "Unchanged ${VERSION_H_PATH}") return() endif() - endif() + endif() - message(STATUS "Generating ${VERSION_H_PATH}") file(WRITE "${VERSION_H_PATH}" "${header_content}") + message(STATUS "Generated new ${VERSION_H_PATH}") endfunction() -# Run these only if not run as script +# This ${VERSION_CMAKE_PATH} file is run in two (very) different ways: +# +# 1. explicitly included by some other, top-level CMakeLists.txt file, and +# 2. directly and "recursively" invoking itself with 'cmake -P myself' here. +# +# Add this check_version_h target only in case 1. (no "infinite recursion") if("${CMAKE_SCRIPT_MODE_FILE}" STREQUAL "") add_custom_target( check_version_h @@ -85,8 +198,9 @@ if("${CMAKE_SCRIPT_MODE_FILE}" STREQUAL "") -DVERSION_H_PATH=${VERSION_H_PATH} -DSOF_ROOT_SOURCE_DIRECTORY=${SOF_ROOT_SOURCE_DIRECTORY} -DSOF_ROOT_BINARY_DIRECTORY=${SOF_ROOT_BINARY_DIRECTORY} + -DZEPHYR_CURRENT_MODULE_DIR=${ZEPHYR_CURRENT_MODULE_DIR} -P ${VERSION_CMAKE_PATH} - COMMENT "Checking ${VERSION_H_PATH}" + COMMENT "cmake -P ${VERSION_CMAKE_PATH}" VERBATIM USES_TERMINAL ) diff --git a/scripts/cmake/xtensa-toolchain.cmake b/scripts/cmake/xtensa-toolchain.cmake index c65caa2a934e..7bc29be3e434 100644 --- a/scripts/cmake/xtensa-toolchain.cmake +++ b/scripts/cmake/xtensa-toolchain.cmake @@ -6,7 +6,7 @@ else() " Please specify toolchain to use.\n" " Examples:\n" " 1) cmake -DTOOLCHAIN=xt ...\n" - " 2) cmake -DTOOLCHAIN=xtensa-apl-elf ...\n" + " 2) cmake -DTOOLCHAIN=xtensa-cnl-elf ...\n" ) endif() @@ -49,13 +49,17 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # xt toolchain only partially follows gcc convention if(TOOLCHAIN STREQUAL "xt") set(XCC 1) - set(CMAKE_C_COMPILER ${CROSS_COMPILE}xcc) -else() - set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc) endif() +if(NOT DEFINED SOF_CC_BASE) +set(SOF_CC_BASE "gcc") +endif() +# e.g.: "xt-" + "xcc" +set(CMAKE_C_COMPILER ${CROSS_COMPILE}${SOF_CC_BASE}) + find_program(CMAKE_LD NAMES "${CROSS_COMPILE}ld" PATHS ENV PATH NO_DEFAULT_PATH) find_program(CMAKE_AR NAMES "${CROSS_COMPILE}ar" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_RANLIB NAMES "${CROSS_COMPILE}ranlib" PATHS ENV PATH NO_DEFAULT_PATH) find_program(CMAKE_OBJCOPY NAMES "${CROSS_COMPILE}objcopy" PATHS ENV PATH NO_DEFAULT_PATH) find_program(CMAKE_OBJDUMP NAMES "${CROSS_COMPILE}objdump" PATHS ENV PATH NO_DEFAULT_PATH) @@ -70,14 +74,26 @@ if(XCC) COMMAND ${CMAKE_C_COMPILER} --show-config=config OUTPUT_VARIABLE cc_config_output OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET + RESULT_VARIABLE show_config_res ) + if(NOT ${show_config_res} EQUAL 0) + message(WARNING "${CMAKE_C_COMPILER} --show-config " + "failed with: ${show_config_res}") + endif() string(REGEX MATCH "[a-zA-Z]+-[0-9]+.[0-9]+-[a-zA-Z]*" XCC_TOOLS_VERSION "${cc_config_output}") if(NOT XCC_TOOLS_VERSION) - message(WARNING "Couldn't get compiler description from '${cc_config_output}'") + message(WARNING + "Couldn't get ${CMAKE_C_COMPILER} description," + " --show-config printed: '${cc_config_output}'") set(XCC_TOOLS_VERSION "UNKNOWN-${CMAKE_SYSTEM_NAME}") endif() else() string(REGEX MATCH "([^\/\\]+)$" XCC_TOOLS_VERSION "${TOOLCHAIN}") endif() + +string(LENGTH "${XCC_TOOLS_VERSION}" XCC_TOOLS_VERSION_STR_LEN) +math(EXPR XCC_TOOLS_VERSION_PADDING "(${XCC_TOOLS_VERSION_STR_LEN} + 1) % 4") +if(XCC_TOOLS_VERSION_PADDING EQUAL 0) + set(XCC_TOOLS_VERSION "<${XCC_TOOLS_VERSION}>") +endif() diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch deleted file mode 100644 index ab2bbb5402c0..000000000000 --- a/scripts/const_structs.checkpatch +++ /dev/null @@ -1,4 +0,0 @@ -comp_func_map -dma_ops -dai_driver -freq_table \ No newline at end of file diff --git a/scripts/docker-run.sh b/scripts/docker-run.sh index ce0f3d618422..29383275152b 100755 --- a/scripts/docker-run.sh +++ b/scripts/docker-run.sh @@ -5,10 +5,40 @@ # Runs a given script in the docker container you can generate from the # docker_build directory. # Example: -# To build sof for baytrail: -# ./scripts/docker-run.sh ./scripts/xtensa-build-all.sh byt # To build topology: # ./scripts/docker-run.sh ./scripts/build-tools.sh -docker run -i -t -v `pwd`:/home/sof/work/sof.git \ - --user `id -u` sof $@ +# set -x + +set -e + +SOF_TOP="$(cd "$(dirname "$0")"/.. && /bin/pwd)" + +# Log container versions +for rep in sof thesofproject/sof; do + docker images --digests "$rep" +done + +if tty --quiet; then + SOF_DOCKER_RUN="$SOF_DOCKER_RUN --tty" +fi + +# The --user option below can cause the command to run as a user who +# does not exist in the container. So far so good but in case something +# ever goes wrong try replacing --user with the newer +# scripts/sudo-cwd.sh script. +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 +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 \ + --env PRIVATE_KEY_OPTION \ + --env USE_XARGS \ + --env NO_PROCESSORS \ + --env VERBOSE \ + --env http_proxy="$http_proxy" \ + --env https_proxy="$https_proxy" \ + $SOF_DOCKER_RUN \ + thesofproject/sof:latest ./scripts/sudo-cwd.sh "$@" diff --git a/scripts/docker_build/sof_builder/Dockerfile b/scripts/docker_build/sof_builder/Dockerfile index 9b9d00b42a39..843b5a448663 100644 --- a/scripts/docker_build/sof_builder/Dockerfile +++ b/scripts/docker_build/sof_builder/Dockerfile @@ -14,21 +14,29 @@ # docker run -it -v <insert sof dir here>:/home/sof/work/sof.git --user `id -u` sof ./incremental.sh # -FROM ubuntu:18.04 -ARG UID=1000 +FROM ubuntu:22.04 +# pick random high value to intentionally mismatch local UID +ARG UID=1999 -# Set up proxy from host -COPY apt.conf /etc/apt/ ARG host_http_proxy ARG host_https_proxy ENV http_proxy $host_http_proxy ENV https_proxy $host_https_proxy +# for non-interactive package install +ARG DEBIAN_FRONTEND=noninteractive + RUN apt-get -y update && \ apt-get install -y \ - autoconf \ + dialog \ + apt-utils \ + vim \ + jed \ + autoconf \ bison \ build-essential \ + ninja-build \ + python3-pyelftools \ flex \ gawk \ gettext \ @@ -43,6 +51,7 @@ RUN apt-get -y update && \ software-properties-common \ sudo \ texinfo \ + tree \ udev \ wget \ unzip \ @@ -50,59 +59,92 @@ RUN apt-get -y update && \ python3 \ libglib2.0-dev - -# Use ToT alsa utils for the latest topology patches. -RUN mkdir -p /root/alsa-build && cd /root/alsa-build && \ -git clone https://github.com/thesofproject/alsa-lib.git && \ -git clone https://github.com/thesofproject/alsa-utils.git && \ -cd /root/alsa-build/alsa-lib && ./gitcompile && make install && \ -cd /root/alsa-build/alsa-utils && ./gitcompile && make install && \ -cd /root/ && rm -rf alsa-build +ARG CLONE_DEFAULTS="--depth 5" # Set up sof user RUN useradd --create-home -d /home/sof -u $UID -G sudo sof && \ -echo "sof:test0000" | chpasswd && adduser sof sudo + 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. +# Note: For alsa-lib, set default library directory to /usr/lib/x86_64-linux-gnu. +# By default it goes to /usr/lib64, but Ubuntu 20.04's default shared library +# path does not have this. Typical build error is like, +# alsatplg: error while loading shared libraries: libatopology.so.2: cannot open shared object file: No such file or directory +RUN mkdir -p "$HOME"/work/alsa && cd "$HOME"/work/alsa && \ + git clone $CLONE_DEFAULTS https://github.com/thesofproject/alsa-lib.git && \ + git clone $CLONE_DEFAULTS https://github.com/thesofproject/alsa-utils.git && \ + cd "$HOME"/work/alsa/alsa-lib && ./gitcompile --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu/ && make install && \ + cd "$HOME"/work/alsa/alsa-utils && ./gitcompile && make install && \ + chown -R sof:sof "$HOME" && \ + echo "Stage1: alsa-lib, alsa-utils are done!" + +ARG GITHUB_SOF=https://github.com/thesofproject +ARG XT_OVERLAY_REPO=$GITHUB_SOF/xtensa-overlay.git +ARG CT_NG_REPO=$GITHUB_SOF/crosstool-ng.git # build cross compiler USER sof -RUN cd /home/sof && git clone https://github.com/thesofproject/xtensa-overlay.git && \ - cd xtensa-overlay && git checkout sof-gcc8.1 && cd ../ && \ - git clone https://github.com/thesofproject/crosstool-ng.git && \ - mkdir -p /home/sof/work/ && \ - cd crosstool-ng && git checkout sof-gcc8.1 && \ +RUN cd "$HOME" && \ + git clone $CLONE_DEFAULTS --branch sof-gcc10.2 $XT_OVERLAY_REPO && \ + git clone $CLONE_DEFAULTS --branch sof-gcc10x $CT_NG_REPO && \ + cd crosstool-ng && \ ./bootstrap && ./configure --prefix=`pwd` && make && make install && \ - for arch in byt hsw apl cnl imx imx8m; do \ - cp config-${arch}-gcc8.1-gdb8.1 .config && \ -# replace the build dist to save space + for arch in byt hsw apl cnl imx imx8m imx8ulp rn rmb vangogh mt8186 mt8195 mt8188; do \ + echo "$arch: ct-ng build start..." && \ + cp config-${arch}-gcc10.2-gdb9 .config && \ + # replace the build dist to save space sed -i 's#${CT_TOP_DIR}\/builds#\/home\/sof\/work#g' .config && \ -# gl_cv_func_getcwd_path_max=yes is used to avoid too-long confdir3/confdir3/... + # gl_cv_func_getcwd_path_max=yes is used to avoid too-long confdir3/confdir3/... gl_cv_func_getcwd_path_max=yes ./ct-ng build && \ ./ct-ng distclean ; \ done && \ - cd /home/sof/ && rm -rf xtensa-overlay && rm -rf crosstool-ng + 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-vangogh-elf/bin:${PATH}" ENV PATH="/home/sof/work/xtensa-imx-elf/bin:${PATH}" ENV PATH="/home/sof/work/xtensa-imx8m-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-imx8ulp-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-mt8186-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-mt8195-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-mt8188-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-mt8196-elf/bin:${PATH}" -RUN cd /home/sof && git clone https://github.com/jcmvbkbc/newlib-xtensa.git newlib-xtensa.git && \ - cd newlib-xtensa.git && git checkout -b xtensa origin/xtensa && \ - for arch in byt hsw apl cnl imx imx8m; do \ +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 byt hsw apl cnl imx imx8m imx8ulp rn rmb vangogh mt8186 mt8195 mt8188; do \ ./configure --target=xtensa-${arch}-elf \ --prefix=/home/sof/work/xtensa-root && \ - make && \ - make install && \ + make && make install && \ rm -rf etc/config.cache; \ done && \ - cd /home/sof/ && rm -rf newlib-xtensa.git + echo "Stage3: newlib-xtensa is done!" +# log all hashes for each repo to a file +ARG SOF_WORK="$HOME"/work +# FIXME: this will fail when any whitespace in SOF_WORK. bash array probably good option to consider +ARG REPOS="$SOF_WORK/alsa/alsa-lib $SOF_WORK/alsa/alsa-utils $HOME/xtensa-overlay $HOME/crosstool-ng $HOME/newlib-xtensa" +ARG HASH_LIST="$SOF_WORK"/sof_docker_hash.txt +RUN echo "Build date: $(date +%Y%m%d)" > "$HASH_LIST" && set -e && \ + for repo in $REPOS; do \ + cd "$repo"; pwd; git log --oneline -5; \ + done >> "$HASH_LIST" && \ + cd "$HOME" && rm -rf xtensa-overlay crosstool-ng newlib-xtensa; \ + echo "Stage4: git versions saved and repos deleted." # Create direcroties for the host machines sof directories to be mounted. -RUN mkdir -p /home/sof/work/sof.git +RUN mkdir -p "$HOME"/work/sof.git USER sof WORKDIR /home/sof/work/sof.git/ diff --git a/scripts/docker_build/sof_builder/docker-build.sh b/scripts/docker_build/sof_builder/docker-build.sh index b676f0c13643..f3eb15388d2c 100755 --- a/scripts/docker_build/sof_builder/docker-build.sh +++ b/scripts/docker_build/sof_builder/docker-build.sh @@ -2,9 +2,5 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation. All rights reserved. -if [ -f "/etc/apt/apt.conf" ]; then - cp /etc/apt/apt.conf ./ -else - touch apt.conf -fi -docker build --build-arg UID=$(id -u) --build-arg host_http_proxy=$http_proxy --build-arg host_https_proxy=$https_proxy -t sof . +docker build --build-arg UID=$(id -u) --build-arg host_http_proxy="$http_proxy" \ + --build-arg host_https_proxy="$https_proxy" -t sof . diff --git a/scripts/docker_build/sof_qemu/Dockerfile b/scripts/docker_build/sof_qemu/Dockerfile index 0606379cdb59..d712478b23d7 100644 --- a/scripts/docker_build/sof_qemu/Dockerfile +++ b/scripts/docker_build/sof_qemu/Dockerfile @@ -12,18 +12,23 @@ # ./scripts/docker-qemu.sh scrpits-or-command-you-want-run # -FROM ubuntu:18.04 +FROM ubuntu:20.04 ARG UID=1000 -# Set up proxy from host -COPY apt.conf /etc/apt/ ARG host_http_proxy ARG host_https_proxy ENV http_proxy $host_http_proxy ENV https_proxy $host_https_proxy +# for non-interactive package install +ARG DEBIAN_FRONTEND=noninteractive + RUN apt-get -y update && \ apt-get install -y \ + vim \ + jed \ + dialog \ + apt-utils \ autoconf \ build-essential \ git \ @@ -33,17 +38,22 @@ RUN apt-get -y update && \ libpixman-1-dev \ pkg-config \ sudo \ - bsdmainutils + bsdmainutils \ + bison \ + flex # Set up sof user RUN useradd --create-home -d /home/sof -u $UID -G sudo sof && \ echo "sof:test0000" | chpasswd && adduser sof sudo ENV HOME /home/sof +ARG GITHUB_SOF=https://github.com/thesofproject +ARG SOF_REPO=$GITHUB_SOF/qemu.git +ARG CLONE_DEFAULTS="--depth 5" # build qemu USER sof -RUN cd /home/sof && git clone https://github.com/thesofproject/qemu.git && \ - cd qemu && git checkout sof-v4.2 && \ +RUN cd /home/sof && git clone $CLONE_DEFAULTS --branch sof-v4.2 $SOF_REPO && \ + cd qemu && \ # replace the submodule git repo to github mirror sed -i 's#git://git.qemu.org#https://github.com/qemu#g' .gitmodules && \ sed -i 's#git://git.qemu-project.org#https://github.com/qemu#g' .gitmodules && \ diff --git a/scripts/docker_build/sof_qemu/docker-build.sh b/scripts/docker_build/sof_qemu/docker-build.sh index 5beba7985625..66a520e06a65 100755 --- a/scripts/docker_build/sof_qemu/docker-build.sh +++ b/scripts/docker_build/sof_qemu/docker-build.sh @@ -2,9 +2,5 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation. All rights reserved. -if [ -f "/etc/apt/apt.conf" ]; then - cp /etc/apt/apt.conf ./ -else - touch apt.conf -fi -docker build --build-arg UID=$(id -u) --build-arg host_http_proxy=$http_proxy --build-arg host_https_proxy=$https_proxy -t sofqemu . +docker build --build-arg UID=$(id -u) --build-arg host_http_proxy="$http_proxy" \ + --build-arg host_https_proxy="$https_proxy" -t sofqemu . diff --git a/scripts/docker_build/zephyr_lite/Dockerfile b/scripts/docker_build/zephyr_lite/Dockerfile new file mode 100644 index 000000000000..c6d6e28159c8 --- /dev/null +++ b/scripts/docker_build/zephyr_lite/Dockerfile @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2025 Intel Corporation. All rights reserved. + +# Use zephyr-build as base image +FROM ghcr.io/zephyrproject-rtos/zephyr-build:v0.29.0 as base + +# Remove additional toolchains. +# As this is not ideal solution there is a plan to build docker image without zephyr-build as the base +# and install only needed toolchains in the future. +USER root + +RUN rm -rvf /opt/toolchains/zephyr-sdk-1.0.0/hosttools/sysroots && \ + rm -rvf /opt/fvps && \ + cd /opt/toolchains/zephyr-sdk-1.0.0/gnu && \ + rm -rvf arc* \ + micro* \ + mips* \ + nios* \ + risc* \ + sparc* \ + x86* \ + xtensa-espressif* \ + xtensa-sample* \ + xtensa-dc233c* + +# Use ubuntu24.04 as base for zephyr-lite +FROM ubuntu:24.04 as zephyr-lite + +# Copy only required files from base image to zephyr-lite +# /opt for toolchains and sdk +# /usr for binaries and libs +# /home for libs installed in .local +# /etc/ssl for ssl certs for python packages +COPY --from=base /opt /opt +COPY --from=base /usr /usr +COPY --from=base /home /home +COPY --from=base /etc/ssl /etc/ssl + +USER root + +# Create a user if it doesn't already exist and grant them permission to /home/user. +# Add user to dialout and sudo group +RUN useradd -ms /bin/bash user && \ + chown -R user:user /home/user && \ + chown -R user:user /opt/python && \ + usermod -a -G dialout,sudo user + +USER user + +# Install cmake and jsonschema in venv +RUN /opt/python/venv/bin/pip install 'cmake>=3.21' jsonschema + +# Set zephyr env variables +ENV PATH="/opt/python/venv/bin/:$PATH" +ENV ZEPHYR_SDK_INSTALL_DIR=/opt/toolchains/zephyr-sdk-1.0.0 +ENV ZSDK_VERSION=1.0.0 +ENV ZEPHYR_TOOLCHAIN_VARIANT=zephyr + +CMD ["/bin/bash", "-l"] diff --git a/scripts/fuzz.sh b/scripts/fuzz.sh new file mode 100755 index 000000000000..b8b69b5fd1d2 --- /dev/null +++ b/scripts/fuzz.sh @@ -0,0 +1,213 @@ +#!/bin/bash +set -e + +print_help() +{ + cat <<EOFHELP + +Usage: + + $0 -b -- -DEXTRA_CONF_FILE=stub_build_all_ipc4.conf -DEXTRA_CFLAGS="-O0 -g3" ... + $0 -t 500 -- -DEXTRA_CONF_FILE=stub_build_all_ipc3.conf ... + + -i4 Appends: -- -DCONFIG_IPC_MAJOR_4=y + fuzz_IPC4_features.conf + -i3 See above + -s Which sanitizer to use, defaults to address + -p Delete build-fuzz/ first ("pristine") + -b Do not run/fuzz: stop after the build. + -t n Fuzz for n seconds. + -o ofile Redirect the fuzzer's extremely verbose stdout. The + relatively verbose stderr is not redirected by -o. + -j n Number of concurrent -jobs=n. Defaults to 1. + The value 0 uses the output of the 'nproc' command. + -a arch The architecture to build against (i386, x86_64) + +Arguments after -- are passed as is to CMake (through west). +When passing conflicting -DVAR='VAL UE1' -DVAR='VAL UE2' to CMake, +the last 'VAL UE2' wins; previous values are silently ignored. + +The number of jobs defaults to 1 for (at least) two reasons: +- Other workers do not stop immediately after one worker fails. +- When higher than 1, this script has to unfortunately disable the + (very verbose) stdout because libFuzzer mixes it with the (terse and + useful) stderr. + +Fuzzing happens to require stubbing which provides a great solution to +compile-check many CONFIG_* at once. So you can stop after the build +with the -b option. + +Simple wrapper around a libfuzzer test run, as much for +documentation as direct use. The idea here is really simple: build +for the Zephyr "native_sim" board (which is a just a x86 +executable for the build host, not an emulated device) and run the +resulting zephyr.exe file. This specifies a "fuzz_corpus" directory +to save the seeds that produce useful coverage output for use in +repeated runs (these are not particularly large, we might consider +curating and committing such a seed directory to the tree). + +The tool will run until it finds a failure condition. You will see +MANY errors on stdout from all the randomized input. Don't try to +capture this, either redirect to a file with '-o fuzz.out' or arrange +to keep only the last XXX lines after the tool exits. + +The only prerequisite to install is a clang compiler on the host. +Versions 12+ have all been observed to work. + +You will need the kconfigs specified below for correct operation, +but can add more at the end of this script's command line to +duplicate configurations as needed. Alternatively you can pass +extra config files in kconfig syntax via: + + fuzz.sh -t 300 -- -DEXTRA_CONF_FILE='debug.conf;other.conf' -DEXTRA_CFLAGS='-Wone -Wtwo' ... + +EOFHELP +} + + +# To test this test, make the following change locally: +: <<EOF_TEST_PATCH +--- a/src/ipc/ipc3/handler.c ++++ b/src/ipc/ipc3/handler.c +@@ -1609,6 +1609,8 @@ void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) + + void ipc_cmd(struct ipc_cmd_hdr *_hdr) + { ++ __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() +{ + setup + + # Default values + local JOBS=1 + local PRISTINE=false + local BUILD_ONLY=false + local FUZZER_STDOUT=/dev/stdout # bashism + local TEST_DURATION=3 + local SANITIZER=address + local ARCH=i386 + local IPC + local BOARD + + # Parse "$@". getopts stops after '--' + while getopts "i:hj:ps:a:o:t:b" opt; do + case "$opt" in + i) IPC="$OPTARG";; + h) print_help; exit 0;; + j) if [ "$OPTARG" -eq 0 ]; then JOBS=$(nproc); else JOBS="$OPTARG"; fi;; + p) PRISTINE=true;; + s) SANITIZER="$OPTARG";; + o) FUZZER_STDOUT="$OPTARG";; + t) TEST_DURATION="$OPTARG";; + a) ARCH="$OPTARG";; + b) BUILD_ONLY=true;; + *) print_help; exit 1;; + esac + done + + # Pass all "$@" arguments remaining after '--' to cmake. + # This also drops _leading_ '--'. + shift $((OPTIND-1)) + + # https://docs.zephyrproject.org/latest/build/kconfig/setting.html#initial-conf + local conf_files_list='prj.conf;boards/native_sim_libfuzzer.conf' + + conf_files_list+=';configs/fuzz_features.conf' + if [ -n "$IPC" ]; then + conf_files_list+=";configs/fuzz_IPC${IPC}_features.conf" + fi + + case $SANITIZER in + address) conf_files_list+=";configs/fuzz_asan.conf";; + undefined) conf_files_list+=";configs/fuzz_ubsan.conf";; + coverage) conf_files_list+=";configs/fuzz_coverage.conf";; + *) echo "Unknown fuzzer type"; print_help; exit 1;; + esac + + case $ARCH in + i386) BOARD="native_sim";; + x86_64) BOARD="native_sim/native/64";; + *) echo "Unknown arch type"; print_help; exit 1;; + esac + + # Note there's never any reason to delete fuzz_corpus/. + # Don't trust `west build -p` because it is not 100% unreliable, + # especially not when doing unusual toolchain things. + if $PRISTINE; then rm -rf build-fuzz/; fi + + # When passing conflicting -DVAR='VAL UE1' -DVAR='VAL UE2' to CMake, + # the last 'VAL UE2' wins. Previous ones are silently ignored. + local cmake_args=( -DCONF_FILE="$conf_files_list" ) + if [ -n "$IPC" ]; then + cmake_args+=( "-DCONFIG_IPC_MAJOR_$IPC=y" ) + fi + + cmake_args+=( "$@" ) + + (set -x + west build -d build-fuzz -b $BOARD "$SOF_TOP"/app/ -- "${cmake_args[@]}" + ) + + if $BUILD_ONLY; then + exit 0 + fi + + mkdir -p ./fuzz_corpus + + local jobs_opts=( ) + # Do not use '-jobs=1' because it ignores FUZZER_STDOUT too + if [ "$JOBS" -gt 1 ]; then + # stdout and stderr get mixed and can't be separated anymore, so + # kiss stdout goodbye. + [ "$FUZZER_STDOUT" = /dev/stdout ] || + >&2 printf 'WARN: redirection to %s EMPTY when jobs > 1\n' "$FUZZER_STDOUT" + jobs_opts+=( -jobs="$JOBS" -close_fd_mask=1 ) + fi + + date + # Help is at: -help=1 + ( set -x + >"$FUZZER_STDOUT" build-fuzz/zephyr/zephyr.exe -max_total_time="$TEST_DURATION" \ + -verbosity=0 "${jobs_opts[@]}" ./fuzz_corpus ) || { + ret=$? + >&2 printf 'zephyr.exe returned: %d\n' $ret + date + die "FAIL. To debug, run: gdb -tui ./build-fuzz/zephyr/zephyr.exe -ex 'run > _ ./crash-...'" + } + + date +} + + +setup() +{ + SOF_TOP=$(cd "$(dirname "$0")/.." && pwd) + export SOF_TOP + + export ZEPHYR_TOOLCHAIN_VARIANT=host/llvm + + # Define ZEPHYR_BASE so this can be invoked even outside the west workspace. + local WS_TOP + WS_TOP=$(cd "$SOF_TOP"; west topdir) + # The manifest itself is not a west project + ZEP_DIR=$(2>/dev/null west list -f '{path}' zephyr || echo 'zephyr') + export ZEPHYR_BASE="$WS_TOP/$ZEP_DIR" + +} + +die() +{ + >&2 printf '%s ERROR: ' "$0" + # We want die() to be usable exactly like printf + # shellcheck disable=SC2059 + >&2 printf "$@" + >&2 printf '\n' + exit 1 +} + +main "$@" diff --git a/scripts/gen-doc.sh b/scripts/gen-doc.sh index bf3b40352517..7b36c0da96d6 100755 --- a/scripts/gen-doc.sh +++ b/scripts/gen-doc.sh @@ -6,8 +6,25 @@ # According to instructions: # https://thesofproject.github.io/latest/howtos/process/docbuild.html -# fail immediately on any errors -set -e +# this needs to run from the Zephyr python virtual environment +# so that the python packages are available (and more up to date than +# the system packages). + +# check if Zephyr environment is set up +if [ ! -z "$ZEPHYR_BASE" ]; then + VENV_DIR="$ZEPHYR_BASE/.venv" + echo "Using Zephyr environment at $ZEPHYR_BASE" +elif [ ! -z "$SOF_WORKSPACE" ]; then + VENV_DIR="$SOF_WORKSPACE/zephyr/.venv" + echo "Using SOF/Zephyr environment at $SOF_WORKSPACE" +else + # fallback to the zephyr default from the getting started guide + VENV_DIR="$HOME/zephyrproject/.venv" + echo "Using default Zephyr environment at $VENV_DIR" +fi + +# start the virtual environment +source ${VENV_DIR}/bin/activate function print_usage() { @@ -21,46 +38,38 @@ function print_usage() # make it runnable from any location # user shouldn't be confused from which dir this script has to be run SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) - # expected paths of repositories needed for documentation process SOF_REPO=$(dirname "$SCRIPT_DIR") DOCS_REPO="$(dirname "$SOF_REPO")/sof-docs" PUBLISH_REPO="$(dirname "$SOF_REPO")/thesofproject.github.io" +BUILD_DIR="$(dirname "$SOF_REPO")/build-sof-docs" # parse arguments -DO_BUILD=no -DO_CLEAN=no -DO_PUBLISH=no -DO_CLONE=no - -for args in $@ -do - if [[ "$args" == "-b" ]] - then - DO_BUILD=yes - elif [[ "$args" == "-c" ]] - then - DO_CLEAN=yes - elif [[ "$args" == "-p" ]] - then - DO_PUBLISH=yes - elif [[ "$args" == "-r" ]] - then - DO_CLONE=yes - fi +DO_BUILD=false +DO_CLEAN=false +DO_PUBLISH=false +DO_FETCH=false + +while getopts "bcpr" OPTION; do + case "$OPTION" in + b) DO_BUILD=true ;; + c) DO_CLEAN=true ;; + p) DO_PUBLISH=true ;; + r) DO_FETCH=true ;; + *) print_usage; exit 1 ;; + esac done +shift "$(($OPTIND - 1))" -if [ "x$DO_BUILD" == "xno" ] && \ - [ "x$DO_CLEAN" == "xno" ] && \ - [ "x$DO_PUBLISH" == "xno" ] +if ! { "$DO_BUILD" || "$DO_CLEAN" || "$DO_PUBLISH"; } then - print_usage - exit 1 + print_usage + exit 1 fi if [ ! -d "$DOCS_REPO" ] then - if [ "x$DO_CLONE" == "xyes" ] + if "$DO_FETCH" then echo "No sof-docs repo at: $DOCS_REPO" echo "Cloning sof-docs repo" @@ -81,32 +90,31 @@ then fi fi -cd "$SOF_REPO/doc" - -if [ "x$DO_CLEAN" == "xyes" ] +if "$DO_CLEAN" then echo "Cleaning $SOF_REPO" - cmake . + cd ${BUILD_DIR} make clean make doc-clean fi -if [ "x$DO_BUILD" == "xyes" ] +if "$DO_BUILD" then echo "Building $SOF_REPO" - cmake . + cd "$SOF_REPO/doc" + cmake -S . -B ${BUILD_DIR} make doc fi cd "$DOCS_REPO" -if [ "x$DO_CLEAN" == "xyes" ] +if "$DO_CLEAN" then echo "Cleaning $DOCS_REPO" make clean fi -if [ "x$DO_BUILD" == "xyes" ] +if "$DO_BUILD" then echo "Building $DOCS_REPO" make html @@ -115,12 +123,12 @@ then echo "It can be viewed at: $DOCS_REPO/_build/html/index.html" fi -if [ "x$DO_PUBLISH" == "xyes" ] +if "$DO_PUBLISH" then if [ ! -d "$PUBLISH_REPO" ] then - if [ "x$DO_CLONE" == "xyes" ] + if "$DO_FETCH" then echo "No publishing repo at: $PUBLISH_REPO" echo "Cloning thesofproject.github.io.git repo" @@ -141,3 +149,6 @@ then cd "$DOCS_REPO" make publish fi + +# cleanup +deactivate diff --git a/scripts/gen-uuid-reg.py b/scripts/gen-uuid-reg.py new file mode 100755 index 000000000000..316f35315544 --- /dev/null +++ b/scripts/gen-uuid-reg.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +import re +import sys + +# Very simple UUID registry validator and C header generator. Parses +# uuid-registry.txt (passed as the first command line argument) and +# writes a C header (named in the second argument) containing +# definitions to be used at build time. Fails via assertion if the +# any element in the registry is invalid. + +header = """/* + * GENERATED CODE. DO NOT EDIT. + * + * Generated UUID records (initializers for struct sof_uuid) + * See scripts/gen-uuid-reg.py + */ +#ifndef _UUID_REGISTRY_H +#define _UUID_REGISTRY_H +""" + +all_syms = set() +all_uuids = set() +out_recs = [] + +def emit_uuid_rec(uu, sym): + recs = uu.split('-') + brec = recs[3] + wrecs = [ "0x" + r for r in recs[0:3] ] + byts = [ "0x" + brec[ 2*i : 2*i+2 ] for i in range(int(len(brec) / 2)) ] + uuidinit = "{ " + ", ".join(wrecs) + ", { " + ", ".join(byts) + " } }" + out_recs.append(f"#define _UUIDREG_{sym} {uuidinit}") + + uuidstr = uu[:23] + '-' + uu[23:] + out_recs.append(f'#define UUIDREG_STR_{sym.upper()} "{uuidstr}"') + +def main(): + with open(sys.argv[1]) as f: + for line in f.readlines(): + line = re.sub(r'\s*#.*', '', line) # trim comments + line = re.sub(r'^\s*', '', line) # trim leading ws + line = re.sub(r'\s*$', '', line) # trim trailing ws + if line == "": + continue + m = re.match(r'(.*)\s+(.*)', line) + assert m + (uu, sym) = (m.group(1).lower(), m.group(2)) + assert re.match(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){2}-[0-9a-f]{16}', uu) + assert re.match(r'[a-zA-Z_][a-zA-Z0-9_]*', sym) + assert len(sym) < 32 + assert uu not in all_uuids + assert sym not in all_syms + all_uuids.add(uu) + all_syms.add(sym) + emit_uuid_rec(uu, sym) + print(f"Added UUID {uu} with symbol {sym}") + + with open(sys.argv[2], "w") as f: + f.write(header) + for l in out_recs: + f.write(l + "\n") + f.write("#endif /* _UUID_REGISTRY_H */\n") + +if __name__ == "__main__": + main() diff --git a/scripts/host-build-all.sh b/scripts/host-build-all.sh deleted file mode 100755 index d56885e5c3c0..000000000000 --- a/scripts/host-build-all.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Intel Corporation. All rights reserved. - -# fail on any errors -set -e - -cd tools -cd testbench - -rm -rf build_testbench - -mkdir build_testbench -cd build_testbench - -cmake -DCMAKE_INSTALL_PREFIX=install \ - -DCMAKE_VERBOSE_MAKEFILE=ON \ - .. - -make -j$(nproc --all) -make install diff --git a/scripts/host-testbench.sh b/scripts/host-testbench.sh index c6efcd62a022..4780b78f6de6 100755 --- a/scripts/host-testbench.sh +++ b/scripts/host-testbench.sh @@ -1,42 +1,137 @@ -#!/bin/sh +#!/bin/bash # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation. All rights reserved. -#build host library -sudo ./scripts/host-build-all.sh +# +# Usage: +# please run following scrits for the test tplg and host build +# ./scripts/build-tools.sh -t +# ./scripts/rebuild-testbench.sh +# Run test +# ./scripts/host-testbench.sh +# -#input file -input_file="48000Hz_stereo_16bit.raw" +# stop on most errors +set -e -#output_file -output_file="out.raw" +function filesize() { + du -b "$1" | awk '{print $1}' +} -#input bit format -bits_in="S16_LE" +function comparesize() { + INPUT_SIZE=$1 + OUTPUT_SIZE=$2 + INPUT_SIZE_MIN=$(echo "$INPUT_SIZE*0.9/1"|bc) + # echo "MIN SIZE with 90% tolerance is $INPUT_SIZE_MIN" + # echo "ACTUALL SIZE is $OUTPUT_SIZE" + if [[ "$OUTPUT_SIZE" -gt "$INPUT_SIZE" ]]; then + echo "OUTPUT_SIZE $OUTPUT_SIZE too big" + return 1 + fi + if [[ "$OUTPUT_SIZE" -lt "$INPUT_SIZE_MIN" ]]; then + echo "OUTPUT_SIZE $OUTPUT_SIZE too small" + return 1 + fi -#input sample rate (this is an optional argument for SRC based pipelines) -#should be used with -r option -fs_in="48000" + return 0 +} -#output sample rate (this is an optional argument for SRC based pipelines) -#should be used with -R option -fs_out="96000" +function srcsize() { + INPUT_SIZE=$1 + INPUT_RATE=$2 + OUTPUT_RATE=$3 + OUTPUT_SIZE=$(echo "${INPUT_SIZE}*${OUTPUT_RATE}/${INPUT_RATE}"|bc) + echo "$OUTPUT_SIZE" +} -# topology file -# please use simple volume/src topologies for now +function die() { + printf "$@" + exit 1 +} -topology_file="./tools/test/topology/test-playback-ssp2-I2S-volume-s16le-s32le-48k-24576k-codec.tplg" +process_test_cmd() { + octave -q --eval "pkg load signal; [n_fail]=process_test('$1', $2, $3, $4, $5);exit(n_fail)" +} -#example src topology -#topology_file="./tools/test/topology/test-playback-ssp5-LEFT_J-src-s24le-s24le-48k-19200k-codec.tplg" +# function test_component() +# $1 : component name +# $2 : input bits per sample +# $3 : output bits per sample +# $4 : sampling rate +# $5 : quick test=0, fulltest=1 +test_component() { + test "$#" -eq 5 || die "Have $# parameters but 5 expected" -#optional libraries to override -libraries="vol=libsof_volume.so,src=libsof_src.so" + echo "------------------------------------------------------------" + echo "test $1 component with $2 $3 $4 $5" + if process_test_cmd "$@"; then + echo "$1 test passed!" + else + die "$1 test failed!" + fi +} -# Use -d to enable debug prints +SCRIPTS_DIR=$(dirname "${BASH_SOURCE[0]}") +SOF_DIR=$SCRIPTS_DIR/../ +TESTBENCH_DIR=${SOF_DIR}/tools/test/audio +INPUT_FILE_SIZE=10240 -# run volume testbench -./src/host/testbench -i $input_file -o $output_file -b $bits_in -t $topology_file -a $libraries -d +cd "$TESTBENCH_DIR" +rm -rf ./*.raw -# run src testbench -#./src/host/testbench -i $input_file -o $output_file -b $bits_in -t $topology_file -a $libraries -r $fs_in -R $fs_out -d +# create input zeros raw file +head -c ${INPUT_FILE_SIZE} < /dev/zero > zeros_in.raw + +# by default quick test +FullTest=${FullTest:-0} + +# test with volume +test_component gain 16 16 48000 "$FullTest" +test_component gain 24 24 48000 "$FullTest" +test_component gain 32 32 48000 "$FullTest" + +# test with eq-iir +test_component eqiir 16 16 48000 "$FullTest" +test_component eqiir 24 24 48000 "$FullTest" +test_component eqiir 32 32 48000 "$FullTest" + +# test with eq-fir +test_component eqfir 32 32 48000 "$FullTest" + +# test with dcblock +test_component dcblock 32 32 48000 "$FullTest" + +# test with drc +test_component drc 32 32 48000 "$FullTest" + +# test with multiband-drc +test_component drc_multiband 32 32 48000 "$FullTest" + +# test with src +test_component src 24 24 48000 "$FullTest" + +# test with tdfb +test_component tdfb 32 32 48000 "$FullTest" + +# test with aria +test_component aria 24 24 48000 "$FullTest" + +# test with asrc +test_component asrc 32 32 48000 "$FullTest" + +# test with template component +test_component template_comp 32 32 48000 "$FullTest" + +# test with Dolby DAX with stub +test_component dolby-dax 32 32 48000 "$FullTest" + +# test with level_multiplier +test_component level_multiplier 32 32 48000 "$FullTest" + +# test with micsel +test_component micsel 32 32 48000 "$FullTest" + +# test with sound_dose +test_component sound_dose 32 32 48000 "$FullTest" + +echo "All tests are done!" diff --git a/scripts/llext_link_helper.py b/scripts/llext_link_helper.py new file mode 100755 index 000000000000..f10777c9918f --- /dev/null +++ b/scripts/llext_link_helper.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause + +# We need to calculate ELF section addresses of an LLEXT module and use them to +# run the linker. We could just use Python to calculate addresses and pass them +# back to cmake to have it call the linker. However, there doesn't seem to be a +# portable way to do that. Therefore we pass the linker path and all the command +# line parameters to this script and call the linker directly. + +import os +import argparse +import subprocess +from elftools.elf.elffile import ELFFile +from elftools.elf.constants import SH_FLAGS +import re +import pathlib + +args = None +def parse_args(): + global args + + parser = argparse.ArgumentParser(description='Helper utility to run a linker command ' + 'with calculated ELF section addresses') + + parser.add_argument('command', type=str, help='Linker command to execute') + parser.add_argument('params', nargs='+', help='Additional linker parameters') + parser.add_argument("-f", "--file", required=True, type=str, + help='Object file name') + parser.add_argument("-c", "--copy", required=True, type=str, + help='Objcopy command') + parser.add_argument("-o", "--output", required=True, type=str, + help='Output file name') + parser.add_argument("-t", "--text-addr", required=True, type=str, + help='.text section address') + parser.add_argument("-s", "--size-file", required=True, type=str, + help='File with stored accumulated size') + + args = parser.parse_args() + +def align_up(addr, align): + upper = addr + align - 1 + return upper - (upper % align) + +def max_alignment(addr, align1, align2): + if align2 > align1: + align1 = align2 + + upper = addr + align1 - 1 + return upper - (upper % align1) + +def main(): + global args + + parse_args() + + # Get the size of the previous module, if this isn't the first one. + # It is used to automatically calculate starting address of the current + # module. + try: + with open(args.size_file, 'r') as f_size: + size = int(f_size.read().strip(), base = 0) + except OSError: + size = 0 + + text_addr = int(args.text_addr, 0) + size + text_size = 0 + + # File names differ when building shared or relocatable objects + if args.file[:-3] == '.so': + p = re.compile(r'(^lib|\.so$)') + fname = args.file + else: + fpath = pathlib.Path(args.file) + fname = fpath.name + p = re.compile(r'(^lib|_llext_lib\.obj$)') + module = p.sub('', fname) + + command = [args.command] + + executable = [] + writable = [] + readonly = [] + readonly_dram = [] + + text_found = False + + elf = ELFFile(open(args.file, 'rb')) + + # Create an object file with sections grouped by their properties, + # similar to how program segments are created: all executable sections, + # then all read-only data sections, and eventually all writable data + # sections like .data and .bss. Each group is aligned on a page boundary + # (0x1000) to make dynamic memory mapping possible. The resulting object + # file will either be a shared library or a relocatable (partially + # linked) object, depending on the build configuration. + for section in elf.iter_sections(): + s_flags = section.header['sh_flags'] + s_type = section.header['sh_type'] + s_name = section.name + s_size = section.header['sh_size'] + s_alignment = section.header['sh_addralign'] + + if not s_flags & SH_FLAGS.SHF_ALLOC: + continue + + if (s_flags & (SH_FLAGS.SHF_ALLOC | SH_FLAGS.SHF_EXECINSTR) == + SH_FLAGS.SHF_ALLOC | SH_FLAGS.SHF_EXECINSTR and + s_type == 'SHT_PROGBITS'): + # An executable section. + if s_name == '.text': + text_found = True + text_addr = max_alignment(text_addr, 0x1000, s_alignment) + text_size = s_size + command.append(f'-Wl,-Ttext=0x{text_addr:x}') + else: + executable.append(section) + + continue + + if (s_flags & (SH_FLAGS.SHF_WRITE | SH_FLAGS.SHF_ALLOC) == + SH_FLAGS.SHF_WRITE | SH_FLAGS.SHF_ALLOC): + # .data, .bss or other writable sections + writable.append(section) + continue + + if s_type == 'SHT_PROGBITS' and s_flags & SH_FLAGS.SHF_ALLOC: + # .rodata or other read-only sections + if s_name == '.coldrodata': + readonly_dram.append(section) + else: + readonly.append(section) + + if not text_found: + raise RuntimeError('No .text section found in the object file') + + # The original LLEXT support in SOF linked all LLEXT modules with pre- + # calculated addresses. Such modules can only be used at those exact + # addresses, so we map memory buffers for such modules to those + # addresses and copy them there. + # Now we also need to be able to re-link parts of modules at run-time to + # run at arbitrary memory locations. One of the use-cases is running + # parts of the module directly in DRAM - sacrificing performance but + # saving scarce SRAM. We achieve this by placing non-performance + # critical functions in a .cold ELF section, read-only data in a + # .coldrodata ELF section, etc. When compiling and linking such + # functions, an additional .cold.literal section is automatically + # created. Note, that for some reason the compiler also marks .cold as + # executable. + # This script links those sections at address 0. We could hard-code + # section names, but so far we choose to only link .text the "original" + # way and all other executable sections we link at 0. For data sections + # we accept only the .coldrodata name for now. + + dram_addr = 0 + first_dram_text = None + first_dram_rodata = None + + for section in executable: + s_alignment = section.header['sh_addralign'] + s_name = section.name + + if not first_dram_text: + first_dram_text = s_name + + dram_addr = align_up(dram_addr, s_alignment) + + command.append(f'-Wl,--section-start={s_name}=0x{dram_addr:x}') + + dram_addr += section.header['sh_size'] + + for section in readonly_dram: + s_alignment = section.header['sh_addralign'] + s_name = section.name + + if not first_dram_rodata: + first_dram_rodata = s_name + + dram_addr = align_up(dram_addr, s_alignment) + + command.append(f'-Wl,--section-start={s_name}=0x{dram_addr:x}') + + dram_addr += section.header['sh_size'] + + start_addr = align_up(text_addr + text_size, 0x1000) + + for section in readonly: + s_alignment = section.header['sh_addralign'] + s_name = section.name + + start_addr = align_up(start_addr, s_alignment) + + command.append(f'-Wl,--section-start={s_name}=0x{start_addr:x}') + + start_addr += section.header['sh_size'] + + start_addr = align_up(start_addr, 0x1000) + + for section in writable: + s_alignment = section.header['sh_addralign'] + s_name = section.name + + start_addr = align_up(start_addr, s_alignment) + + if s_name == '.data': + command.append(f'-Wl,-Tdata=0x{start_addr:x}') + else: + command.append(f'-Wl,--section-start={s_name}=0x{start_addr:x}') + + start_addr += section.header['sh_size'] + + command.extend(['-o', f'{args.file}.tmp']) + command.extend(args.params) + + subprocess.run(command) + + copy_command = [args.copy] + + if first_dram_text: + copy_command.extend(['--set-section-alignment', f'{first_dram_text}=4096']) + if first_dram_rodata: + copy_command.extend(['--set-section-alignment', f'{first_dram_rodata}=4096']) + + copy_command.extend([f'{args.file}.tmp', f'{args.output}']) + subprocess.run(copy_command) + +if __name__ == "__main__": + main() diff --git a/scripts/llext_offset_calc.py b/scripts/llext_offset_calc.py new file mode 100755 index 000000000000..0f302a8cbe12 --- /dev/null +++ b/scripts/llext_offset_calc.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause + +# Add rounded new file size to accumulated module size cache + +import argparse +import pathlib +import os +from elftools.elf.elffile import ELFFile +from elftools.elf.constants import SH_FLAGS + +args = None + +def parse_args(): + global args + + parser = argparse.ArgumentParser(description='Add a file size to a sum in a file') + + parser.add_argument("-i", "--input", required=True, type=str, + help='Object file name') + parser.add_argument("-s", "--size-file", required=True, type=str, + help='File to store accumulated size') + + args = parser.parse_args() + +def get_elf_size(elf_name): + start = 0xffffffff + # SOF_MODULE_DRAM_LINK_END + min_start = 0x08000000 + end = 0 + with open(elf_name, 'rb') as f_elf: + elf = ELFFile(f_elf) + + for section in elf.iter_sections(): + s_flags = section.header['sh_flags'] + + if not s_flags & SH_FLAGS.SHF_ALLOC: + continue + + # Ignore detached sections, to be used in DRAM, their addresses + # are below min_start + if section.header['sh_addr'] < min_start: + continue + + if section.header['sh_addr'] < start: + start = section.header['sh_addr'] + if section.header['sh_addr'] + section.header['sh_size'] > end: + end = section.header['sh_addr'] + section.header['sh_size'] + + size = end - start + + return size + +def main(): + global args + + parse_args() + + f_output = pathlib.Path(args.size_file) + + try: + with open(f_output, 'r') as f_size: + size = int(f_size.read().strip(), base = 0) + except OSError: + size = 0 + + size += get_elf_size(args.input) + 0xfff + # align to a page border + size &= ~0xfff + + # Failure will raise an exception + f_size = open(f_output, "w") + f_size.write(f'0x{size:x}\n') + +if __name__ == "__main__": + main() diff --git a/scripts/parse_sparse_output.sh b/scripts/parse_sparse_output.sh new file mode 100755 index 000000000000..04d767eeb794 --- /dev/null +++ b/scripts/parse_sparse_output.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause + +# "sparse" is not designed for automated testing: its exit code is +# mostly useless. So this script extracts from its output the most +# important messages instead and returns 1 if any is found. + +# As of Sep. 2022, sparse's exit status is by default always zero even +# when there is an error, see check_symbols() in sparse.c. There is a +# -DEXTRA_CFLAGS=-Wsparse-error option that returns non-zero... for any +# warning even the most harmless one and it seems to stops on the first +# one. SOF has hundreds of sparse warnings now. + +main() +{ + local platform="$1" # optional + local sparse_errors=() + + >&2 printf 'Reminder: to see ALL warnings you must as usual build _from scratch_\n' + + # To reproduce an 'error: ' and test this script try commenting out + # `defined(__CHECKER__)` in common.h. + # + # To reproduce the 'different address space' warning and test this + # script try deleting a __sparse_cache annotation like the one in + # src/audio/mixer/mixer.c + + 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[@]}" + +} + +main "$@" diff --git a/scripts/qemu-check.sh b/scripts/qemu-check.sh index 6801db90f33b..ba1795625a7f 100755 --- a/scripts/qemu-check.sh +++ b/scripts/qemu-check.sh @@ -1,130 +1,166 @@ #!/bin/bash # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation. All rights reserved. +set -e -SUPPORTED_PLATFORMS=(byt cht bdw hsw apl icl skl kbl cnl imx8 imx8x imx8m) -READY_MSG="6c 00 00 00 00 00 00 70" +SUPPORTED_PLATFORMS=(imx8 imx8x imx8m) + +SOF_DIR=$(cd "$(dirname "$0")" && cd .. && pwd) + +: "${SOF_BUILDS:=${SOF_DIR}}" rm -f dump-*.txt -if [ "$#" -eq 0 ] -then - PLATFORMS=${SUPPORTED_PLATFORMS[@]} +die() +{ + >&2 printf '%s ERROR: ' "$0" + # We want die() to be usable exactly like printf + # shellcheck disable=SC2059 + >&2 printf "$@" + exit 1 +} + +print_usage() +{ + cat <<EOF +usage: qemu-check.sh [ platform(s) ] + Supported platforms are ${SUPPORTED_PLATFORMS[*]} + Runs all supported platforms by default. +EOF +} + +find_qemu_xtensa() +{ + local xhs=xtensa-host.sh + for d in . ../qemu* qemu*; do + if test -e "$d"/$xhs; then + printf '%s' "$d"/$xhs; + return + fi + done + die '%s not found\n' $xhs +} + + +while getopts "" OPTION; do + case "$OPTION" in + *) print_usage; exit 1 ;; + esac +done +shift $((OPTIND-1)) + +PLATFORMS=() +if [ "$#" -eq 0 ]; then + PLATFORMS=("${SUPPORTED_PLATFORMS[@]}") else - for args in $@ - do - for i in ${SUPPORTED_PLATFORMS[@]} - do - if [ $i == $args ] - then - PLATFORMS+=$i" " + for arg in "$@"; do + platform=unknown + for sp in "${SUPPORTED_PLATFORMS[@]}"; do + if [ x"$sp" = x"$arg" ]; then + PLATFORMS=("${PLATFORMS[@]}" "$sp") + platform=$sp + shift + break fi done + if [ "$platform" = "unknown" ]; then + echo "Error: Unknown platform specified: $arg" + echo "Supported platforms: ${SUPPORTED_PLATFORMS[*]}" + exit 1 + fi done fi -# check target platform(s) have been passed in -if [ ${#PLATFORMS[@]} -eq 0 ]; -then - echo "Error: No platforms specified. Supported are: ${SUPPORTED_PLATFORMS[@]}" - exit 1 -fi - -for j in ${PLATFORMS[@]} +for platform in "${PLATFORMS[@]}" do - FWNAME="sof-$j.ri" - PLATFORM=$j + FWNAME="sof-$platform.ri" + PLATFORM=$platform # reset variable to avoid issue in random order ROM='' OUTBOX_OFFSET='' - if [ $j == "byt" ] - then - READY_IPC="00 88 02 70 00 00 00 80" - SHM_IPC_REG=qemu-bridge-shim-io - SHM_MBOX=qemu-bridge-mbox-io - fi - if [ $j == "cht" ] - then - READY_IPC="00 88 02 70 00 00 00 80" - SHM_IPC_REG=qemu-bridge-shim-io - SHM_MBOX=qemu-bridge-mbox-io - fi - if [ $j == "bdw" ] - then - READY_IPC="00 3c 01 80" - OUTBOX_OFFSET="9e000" - SHM_IPC_REG=qemu-bridge-shim-io - SHM_MBOX=qemu-bridge-dram-mem - fi - if [ $j == "hsw" ] - then - READY_IPC="00 fc 00 80" - OUTBOX_OFFSET="7e000" - SHM_IPC_REG=qemu-bridge-shim-io - SHM_MBOX=qemu-bridge-dram-mem - fi - if [ $j == "apl" ] - then - READY_IPC="00 00 00 f0" - SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io" - OUTBOX_OFFSET="7000" - SHM_MBOX=qemu-bridge-hp-sram-mem - ROM="-r ../sof.git/build_${j}_gcc/src/arch/xtensa/rom-$j.bin" - fi - if [ $j == "skl" ] - then - READY_IPC="00 00 00 f0" - SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io" - OUTBOX_OFFSET="7000" - SHM_MBOX=qemu-bridge-hp-sram-mem - ROM="-r ../sof.git/build_${j}_gcc/src/arch/xtensa/rom-$j.bin" - fi - if [ $j == "kbl" ] - then - READY_IPC="00 00 00 f0" - SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io" - OUTBOX_OFFSET="7000" - SHM_MBOX=qemu-bridge-hp-sram-mem - ROM="-r ../sof.git/build_${j}_gcc/src/arch/xtensa/rom-$j.bin" - fi - if [ $j == "cnl" ] - then - READY_IPC="00 00 00 f0" - SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io" - OUTBOX_OFFSET="5000" - SHM_MBOX=qemu-bridge-hp-sram-mem - ROM="-r ../sof.git/build_${j}_gcc/src/arch/xtensa/rom-$j.bin" - fi - if [ $j == "icl" ] - then - READY_IPC="00 00 00 f0" - SHM_IPC_REG="qemu-bridge-ipc(|-dsp)-io" - OUTBOX_OFFSET="5000" - SHM_MBOX=qemu-bridge-hp-sram-mem - ROM="-r ../sof.git/build_${j}_gcc/src/arch/xtensa/rom-$j.bin" - fi - if [ $j == "imx8" ] || [ $j == "imx8x" ] || [ $j == "imx8m" ] - then - READY_IPC="00 00 00 00 00 00 04 c0" - SHM_IPC_REG=qemu-bridge-mu-io - SHM_MBOX=qemu-bridge-mbox-io + + has_rom=false + case "$platform" in + imx8 | imx8x | imx8m) + # This READY_IPC value comes from: + # + # /* Disable interrupt from MU: + # * GP #0 for Host -> DSP message notification + # * GP #1 for DSP -> Host message confirmation + # * GP #2 and #3 not used + # */ + # imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, 0, + # IMX_MU_xCR_GIEn(IMX_MU_VERSION, 0) | + # IMX_MU_xCR_GIEn(IMX_MU_VERSION, 1) | + # IMX_MU_xCR_GIEn(IMX_MU_VERSION, 2) | + # IMX_MU_xCR_GIEn(IMX_MU_VERSION, 3)); + # /* Clear all pending interrupts from MU */ + # imx_mu_write(IMX_MU_xSR_GIPn(IMX_MU_VERSION, 0) | + # IMX_MU_xSR_GIPn(IMX_MU_VERSION, 1) | + # IMX_MU_xSR_GIPn(IMX_MU_VERSION, 2) | + # IMX_MU_xSR_GIPn(IMX_MU_VERSION, 3), + # IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); + # /* Enable GP #0 and #1 for Host -> DSP and + # * DSP -> Host message notification + # */ + # 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); + # /* Now interrupt host to tell it we are done booting */ + # imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, + # IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); + # So, "00 00 00 f0 00 00 04 c0" is the MU's xSR and xCR registers: + # xSR: F0000000 and xCR: C00400000 + READY_IPC="00 00 00 f0 00 00 04 c0" + SHM_IPC_REG=qemu-bridge-mu-io + SHM_MBOX=qemu-bridge-mbox-io + ;; + esac + + if $has_rom; then + ROM=(-r "${SOF_BUILDS}/build_${platform}_gcc/src/arch/xtensa/rom-$platform.bin") fi - ./xtensa-host.sh $PLATFORM -k ../sof.git/build_${j}_gcc/src/arch/xtensa/$FWNAME $ROM -o 2.0 ../sof.git/dump-$j.txt + xtensa_host_sh=$(find_qemu_xtensa) + + ret=0 + ( set -x + + ${xtensa_host_sh} "$PLATFORM" -k \ + "${SOF_BUILDS}"/build_"${platform}"_gcc/src/arch/xtensa/"$FWNAME" \ + "${ROM[@]}" \ + -o 2.0 "${SOF_BUILDS}"/dump-"$platform".txt # dump log into sof.git incase running in docker + ) || ret=$? # this defeats set -e + # See 'man timeout' + test $ret = 124 || die 'qemu failed before we stopped it!\n' + + # use regular expression to match the SHM IPC REG file name, one of: + # /dev/shm/qemu-bridge-{shim,ipc,dsp}-io + SHM_IPC_REG_FILE=$(ls /dev/shm/ | grep -E $SHM_IPC_REG) || true + + test -e /dev/shm/"${SHM_IPC_REG_FILE}" || + die '%s: %s not found in /dev/shm/\n' "$0" "$SHM_IPC_REG" - # use regular expression to match the SHM IPC REG file name - SHM_IPC_REG_FILE=$(ls /dev/shm/ | grep -E $SHM_IPC_REG) + # Check if ready ipc header is in the ipc regs doorbell + # registers or shared memory for older platforms. + # See: + # - 'adsp_reg_space' in qemu/ + # - shim_write() or ipc_write() in sof/ + IPC_REG=$(hexdump -C /dev/shm/"$SHM_IPC_REG_FILE" | + grep "$READY_IPC") || true - # check if ready ipc header is in the ipc regs - IPC_REG=$(hexdump -C /dev/shm/$SHM_IPC_REG_FILE | grep "$READY_IPC") - # check if ready ipc message is in the mbox - IPC_MSG=$(hexdump -C /dev/shm/$SHM_MBOX | grep -A 4 "$READY_MSG" | grep -A 4 "$OUTBOX_OFFSET") + # Check if ready ipc message is in the mbox-io / sram-mem + # See "struct sof_ipc_fw_ready" and + # objdump -s -j .fw_ready -s build/sof + READY_MSG="6c 00 00 00 00 00 00 70" + IPC_MSG=$(hexdump -C /dev/shm/$SHM_MBOX | grep -A 4 "$READY_MSG" | + grep -A 4 "$OUTBOX_OFFSET") || true if [ "$IPC_REG" ]; then echo "ipc reg dump:" # directly output the log to be nice to look - hexdump -C /dev/shm/$SHM_IPC_REG_FILE | grep "$READY_IPC" + hexdump -C /dev/shm/"$SHM_IPC_REG_FILE" | grep "$READY_IPC" if [ "$IPC_MSG" ]; then echo "ipc message dump:" # directly output the log to be nice to look @@ -140,7 +176,7 @@ do echo "Boot success"; else echo "Error boot failed" - tail -n 50 ../sof.git/dump-$j.txt + tail -n 50 "${SOF_BUILDS}"/dump-"$platform".txt exit 2; fi done diff --git a/scripts/rebuild-testbench.sh b/scripts/rebuild-testbench.sh new file mode 100755 index 000000000000..996d16f45a8c --- /dev/null +++ b/scripts/rebuild-testbench.sh @@ -0,0 +1,177 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020, Mohana Datta Yelugoti + +# stop on most errors +set -e + +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +SOF_REPO=$(dirname "$SCRIPT_DIR") +TESTBENCH_DIR="$SOF_REPO"/tools/testbench + +# Defaults +BUILD_BACKEND='make' +BUILD_TYPE=native +BUILD_DIR_NAME=build_testbench +BUILD_TARGET=install +: "${SOF_AFL:=$HOME/sof/work/AFL/afl-gcc}" + +print_usage() +{ + cat <<EOFUSAGE +usage: $0 [-f] [-p <platform>] + -p Build testbench binary for xt-run for selected platform, e.g. -p tgl + When omitted, perform a BUILD_TYPE=native, compile-only check. + -f Build testbench with compiler provided by fuzzer + (default path: $HOME/sof/work/AFL/afl-gcc) + -j number of parallel $BUILD_BACKEND 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() +{ + local bdir="$BUILD_DIR_NAME" + cd "$TESTBENCH_DIR" + + rm -rf "$bdir" + cmake -B "$bdir" -DCMAKE_INSTALL_PREFIX="$bdir"/install + cmake --build "$bdir" -- -j"${jobs}" $BUILD_TARGET +} + +export_CC_with_afl() +{ + printf 'export CC=%s\n' "${SOF_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 "${TOOLCHAIN_VER}" || + die "Illegal platform $BUILD_PLATFORM, no TOOLCHAIN_VER found.\n" + test -n "${XTENSA_CORE}" || + die "Illegal platform $BUILD_PLATFORM, no XTENSA_CORE found.\n" + + # This (local?) variable should probably be inlined + COMPILER=xt-"$SOF_CC_BASE" + + install_bin=install/tools/$TOOLCHAIN_VER/XtensaTools/bin + tools_bin=$XTENSA_TOOLS_ROOT/$install_bin + testbench_sections="-Wl,--sections-placement $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 $testbench_sections" + export XTENSA_CORE +} + +export_xtensa_setup() +{ + export_dir=$TESTBENCH_DIR/$BUILD_DIR_NAME + export_script=$export_dir/xtrun_env.sh + xtbench=$export_dir/sof-testbench4 + xtbench_run="XTENSA_CORE=$XTENSA_CORE \$XTENSA_TOOLS_ROOT/$install_bin/xt-run $xtbench" + cat <<EOFSETUP > "$export_script" +export XTENSA_TOOLS_ROOT=$XTENSA_TOOLS_ROOT +export XTENSA_CORE=$XTENSA_CORE +export XTENSA_PATH=$tools_bin +EOFSETUP +} + +testbench_usage() +{ + local src_env_msg + if [ "$BUILD_TYPE" = 'xt' ]; then + export_xtensa_setup + src_env_msg="source $export_script" + fi + +cat <<EOF0 +Success! + +For temporary, interactive Kconfiguration use: + + $BUILD_BACKEND -C $TESTBENCH_DIR/$BUILD_DIR_NAME/sof_ep/build/ menuconfig + +Permanent configuration is "src/arch/host/configs/library_defconfig". + +For instant, incremental build: + + $src_env_msg + $BUILD_BACKEND -C $TESTBENCH_DIR/$BUILD_DIR_NAME/ -j$(nproc) + +EOF0 + + case "$BUILD_TYPE" in + xt) + cat <<EOFUSAGE +Testbench binary for $BUILD_PLATFORM is in $xtbench +it can be run with command: + +$xtbench_run -h + +Alternatively with environment setup to match build: + +source $export_script +\$XTENSA_PATH/xt-run $xtbench -h + +EOFUSAGE + ;; + *) >&2 printf 'testbench_usage: unknown/missing BUILD_TYPE=%s\n' "$BUILD_TYPE" ;; + esac +} + +main() +{ + 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 0;; + *) print_usage; exit 1;; + esac + done + + # This automagically removes the -- sentinel itself if any. + shift "$((OPTIND -1))" + # Error on spurious arguments. + test $# -eq 0 || { + print_usage + die "Unknown arguments: %s\n" "$*" + } + + rebuild_testbench + + printf '\n' + testbench_usage +} + +main "$@" diff --git a/scripts/run-mocks.sh b/scripts/run-mocks.sh new file mode 100755 index 000000000000..168608d5b12f --- /dev/null +++ b/scripts/run-mocks.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2021 Intel Corporation. All rights reserved. + + +# Stop on most errors +set -e + +SOFTOP=$(cd "$(dirname "$0")"/.. && pwd) + +usage() +{ + cat <<EOF +Usage: [ -v ] [ -c platform_defconfig ] + +Re-compiles unit tests with the host toolchain and runs them one by +one, optionally with valgrind. If you don't need valgrind it's faster +and better looking to run "make -j test". See +https://thesofproject.github.io/latest/developer_guides/unit_tests.html +EOF + exit 1 +} + +parse_opts() +{ + # default config if none supplied + CONFIG="unit_test_defconfig" + VALGRIND_CMD="" + + while getopts "vc:" flag; do + case "${flag}" in + c) CONFIG=${OPTARG} + ;; + v) VALGRIND_CMD="valgrind --tool=memcheck --track-origins=yes \ +--leak-check=full --show-leak-kinds=all --error-exitcode=1" + ;; + ?) usage + ;; + esac + done + + shift $((OPTIND -1 )) + # anything left? + test -z "$1" || usage +} + +rebuild_ut() +{ + # -DINIT_CONFIG is ignored after the first time. Invoke make (or + # -ninja) after this for faster, incremental builds. + rm -rf build_ut/ + + cmake -S "$SOFTOP" -B build_ut -DBUILD_UNIT_TESTS=ON -DBUILD_UNIT_TESTS_HOST=ON \ + -DINIT_CONFIG="${CONFIG}" + + cmake --build build_ut -- -j"$(nproc --all)" +} + +run_ut() +{ + local TESTS; TESTS=$(find build_ut/test -type f -executable -print) + echo test are "${TESTS}" + for test in ${TESTS} + do + if [ x"$test" = x'build_ut/test/cmocka/src/lib/alloc/alloc' ]; then + printf 'SKIP alloc test until it is fixed on HOST (passes with xt-run)' + continue + fi + + printf 'Running %s\n' "${test}" + ( set -x + ${VALGRIND_CMD} ./"${test}" + ) + done +} + +main() +{ + parse_opts "$@" + rebuild_ut + run_ut +} + +main "$@" diff --git a/scripts/scan/clang-scan-build-xtensa.sh b/scripts/scan/clang-scan-build-xtensa.sh index 5bf97d044af2..1c8cd27f2ec6 100755 --- a/scripts/scan/clang-scan-build-xtensa.sh +++ b/scripts/scan/clang-scan-build-xtensa.sh @@ -15,7 +15,7 @@ function usage { echo " [-j n] Set number of make build jobs." echo " [-v] Verbose output." echo "Examples:" - echo " $0 -t xt -c apollolake \\" + echo " $0 -t xt -c tigerlake \\" echo " -r \$CONFIG_PATH/xtensa-elf" echo " $0 -t xtensa-cnl-elf -c cannonlake \\" echo " -r \`pwd\`/../xtensa-cnl-elf" diff --git a/scripts/sdk-create-module.py b/scripts/sdk-create-module.py new file mode 100755 index 000000000000..bc80db16dfe9 --- /dev/null +++ b/scripts/sdk-create-module.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# +# Creates new module based on template module. + +import os +import sys +import shutil +import uuid +import re + +def process_directory(directory_path, old_text, new_text): + """ + Recursively walks through a directory to rename files and replace content. + This function processes files first, then directories, to allow for renaming + of the directories themselves after their contents are handled. + """ + # Walk through the directory tree + for dirpath, dirnames, filenames in os.walk(directory_path, topdown=False): + # --- Process Files --- + for filename in filenames: + original_filepath = os.path.join(dirpath, filename) + + # a) Replace content within files + # Only process C/H files for content replacement + if filename.endswith(('.c', '.h', '.cpp', '.hpp', '.txt', '.toml', 'Kconfig')): + replace_text_in_file(original_filepath, old_text, new_text) + if filename.endswith(('.c', '.h', '.cpp', '.hpp', '.txt', '.toml', 'Kconfig')): + replace_text_in_file(original_filepath, old_text.upper(), new_text.upper()) + if filename.endswith(('.c', '.h', '.cpp', '.hpp', '.txt', '.toml', 'Kconfig')): + replace_text_in_file(original_filepath, "template", new_text) + if filename.endswith(('.c', '.h', '.cpp', '.hpp', '.txt', '.toml', 'Kconfig')): + replace_text_in_file(original_filepath, "TEMPLATE", new_text.upper()) + + # b) Rename the file if its name contains the template text + if "template" in filename: + new_filename = filename.replace("template", new_text) + new_filepath = os.path.join(dirpath, new_filename) + print(f" -> Renaming file: '{original_filepath}' to '{new_filepath}'") + os.rename(original_filepath, new_filepath) + +def replace_text_in_file(filepath, old_text, new_text): + """ + Replaces all occurrences of old_text with new_text in a given file. + """ + try: + # Read the file content + with open(filepath, 'r', encoding='utf-8') as file: + content = file.read() + + # Perform the replacement + new_content = content.replace(old_text, new_text) + + # If content has changed, write it back + if new_content != content: + print(f" -> Updating content in: '{filepath}'") + with open(filepath, 'w', encoding='utf-8') as file: + file.write(new_content) + + except Exception as e: + print(f" -> [WARNING] Could not process file '{filepath}'. Reason: {e}") + +def insert_uuid_name(filepath: str, new_name: str): + """ + Inserts a newly generated UUID and a given name into a file, maintaining + alphabetical order by name. Ignores and preserves lines starting with '#'. + + Args: + filepath (str): The path to the file to be updated. + new_name (str): The name to associate with the new UUID. + """ + data_entries = [] + other_lines = [] # To store comments and blank lines + + # --- 1. Read existing entries and comments from the file --- + try: + with open(filepath, 'r', encoding='utf-8') as f: + for line in f: + stripped_line = line.strip() + # Check for comments or blank lines + if not stripped_line or stripped_line.startswith('#'): + other_lines.append(line) # Preserve the original line with newline + continue + + # It's a data line, so process it + # Split only on the first space to handle names that might contain spaces + parts = stripped_line.split(' ', 1) + if len(parts) == 2: + data_entries.append((parts[0], parts[1])) + except FileNotFoundError: + print(f"File '{filepath}' not found. A new file will be created.") + except Exception as e: + print(f"An error occurred while reading the file: {e}") + return + + # --- 2. Check if the name already exists in data entries --- + if any(name == new_name for _, name in data_entries): + print(f"Name '{new_name}' already exists in the file. No changes made.") + return + + # --- 3. Add the new entry to the data list --- + new_uuid = str(uuid.uuid4()) + + # We split the string from the right at the last hyphen and then join the parts. + parts = new_uuid.rsplit('-', 1) + custom_format_uuid = ''.join(parts) + + data_entries.append((custom_format_uuid, new_name)) + print(f"Generated new entry: {new_uuid} {new_name}") + + # --- 4. Sort the list of data entries by name (the second element of the tuple) --- + data_entries.sort(key=lambda item: item[1]) + + # --- 5. Write the comments and then the sorted data back to the file --- + try: + with open(filepath, 'w', encoding='utf-8') as f: + # Write all the comments and other non-data lines first + for line in other_lines: + f.write(line) + + # Write the sorted data entries + for entry_uuid, entry_name in data_entries: + f.write(f"{entry_uuid} {entry_name}\n") + print(f"Successfully updated '{filepath}'.") + except Exception as e: + print(f"An error occurred while writing to the file: {e}") + +# Define the markers for the managed block in the CMakeLists.txt file. +CMAKE_START_MARKER = " # directories and files included conditionally (alphabetical order)" +CMAKE_END_MARKER = " # end of directories and files included conditionally (alphabetical order)" + +def insert_cmake_rule(filepath: str, kconfig_option: str, subdir_name: str): + """ + Reads a CMakeLists.txt file, adds a new rule, and writes it back. + + Args: + filepath (str): Path to the CMakeLists.txt file. + kconfig_option (str): The Kconfig flag to check. + subdir_name (str): The subdirectory to add. + """ + if not os.path.exists(filepath): + print(f"[ERROR] File not found at: '{filepath}'") + return + + # --- 1. Read the entire file content --- + with open(filepath, 'r', encoding='utf-8') as f: + lines = f.readlines() + + # --- 2. Find the start and end of the managed block --- + try: + start_index = lines.index(CMAKE_START_MARKER + '\n') + end_index = lines.index(CMAKE_END_MARKER + '\n') + except ValueError: + print(f"[ERROR] Could not find the required marker blocks in '{filepath}'.") + print(f"Please ensure the file contains both '{CMAKE_START_MARKER}' and '{CMAKE_END_MARKER}'.") + return + + # --- 3. Extract the lines before, during, and after the block --- + lines_before = lines[:start_index + 1] + block_lines = lines[start_index + 1 : end_index] + lines_after = lines[end_index:] + + # --- 4. Parse the existing rules within the block --- + rules = [] + # Regex to find: if(CONFIG_NAME) ... add_subdirectory(subdir) ... endif() + # This is robust against extra whitespace and blank lines. + block_content = "".join(block_lines) + pattern = re.compile( + r"if\s*\((?P<kconfig>CONFIG_[A-Z0-9_]+)\)\s*" + r"add_subdirectory\s*\((?P<subdir>[a-zA-Z0-9_]+)\)\s*" + r"endif\(\)", + re.DOTALL + ) + + for match in pattern.finditer(block_content): + rules.append(match.groupdict()) + + # --- 5. Check if the rule already exists --- + if any(rule['kconfig'] == kconfig_option for rule in rules): + print(f"[INFO] Rule for '{kconfig_option}' already exists. No changes made.") + return + + # --- 6. Add the new rule and sort alphabetically --- + rules.append({'kconfig': kconfig_option, 'subdir': subdir_name}) + rules.sort(key=lambda r: r['kconfig']) + print(f"Adding rule for '{kconfig_option}' -> '{subdir_name}' and re-sorting.") + + # --- 7. Rebuild the block content from the sorted rules --- + new_block_lines = [] + for i, rule in enumerate(rules): + new_block_lines.append(f"\tif({rule['kconfig']})\n") + new_block_lines.append(f"\t\tadd_subdirectory({rule['subdir']})\n") + new_block_lines.append("\tendif()\n") + + # --- 8. Assemble the new file content and write it back --- + new_content = "".join(lines_before + new_block_lines + lines_after) + with open(filepath, 'w', encoding='utf-8') as f: + f.write(new_content) + + print(f"Successfully updated '{filepath}'.") + +# Define the markers for the managed block in the Kconfig file. +KCONFIG_START_MARKER = "# --- Kconfig Sources (alphabetical order) ---" +KCONFIG_END_MARKER = "# --- End Kconfig Sources (alphabetical order) ---" + +def insert_kconfig_source(filepath: str, source_path: str): + """ + Reads a Kconfig file, adds a new rsource rule, and writes it back. + + Args: + filepath (str): Path to the Kconfig file. + source_path (str): The path to the Kconfig file to be sourced. + """ + if not os.path.exists(filepath): + print(f"[ERROR] File not found at: '{filepath}'") + return + + # --- 1. Read the entire file content --- + try: + with open(filepath, 'r', encoding='utf-8') as f: + lines = f.readlines() + except Exception as e: + print(f"[ERROR] Could not read file: {e}") + return + + # --- 2. Find the start and end of the managed block --- + try: + start_index = lines.index(KCONFIG_START_MARKER + '\n') + end_index = lines.index(KCONFIG_END_MARKER + '\n') + except ValueError: + print(f"[ERROR] Could not find the required marker blocks in '{filepath}'.") + print(f"Please ensure the file contains both '{KCONFIG_START_MARKER}' and '{KCONFIG_END_MARKER}'.") + return + + # --- 3. Extract the lines before, during, and after the block --- + lines_before = lines[:start_index + 1] + block_lines = lines[start_index + 1 : end_index] + lines_after = lines[end_index:] + + # --- 4. Parse the existing rsource rules within the block --- + source_paths = [] + # Regex to find: rsource "path/to/file" + pattern = re.compile(r'rsource\s+"(?P<path>.*?)"') + + for line in block_lines: + match = pattern.search(line) + if match: + source_paths.append(match.group('path')) + + # --- 5. Check if the source path already exists --- + if source_path in source_paths: + print(f"[INFO] Source path '{source_path}' already exists. No changes made.") + return + + # --- 6. Add the new path and sort alphabetically --- + source_paths.append(source_path) + source_paths.sort() + print(f"Adding source '{source_path}' and re-sorting.") + + # --- 7. Rebuild the block content from the sorted paths --- + new_block_lines = [] + for path in source_paths: + new_block_lines.append(f'rsource "{path}"\n') + + # --- 8. Assemble the new file content and write it back --- + new_content = "".join(lines_before + new_block_lines + lines_after) + with open(filepath, 'w', encoding='utf-8') as f: + f.write(new_content) + + print(f"Successfully updated '{filepath}'.") + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Define the markers for the managed block in the header file. +HEADER_START_MARKER = "/* Start of modules in alphabetical order */" +HEADER_END_MARKER = "/* End of modules in alphabetical order */" + +def insert_c_declaration(header_path: str, name: str) -> bool: + """ + Inserts a C function declaration alphabetically into a header file between + start and end markers. + + The function declaration format is: + "void sys_comp_module_${name}_interface_init(void);" + + Args: + header_path (str): The full path to the C header file. + name (str): The component name to be inserted into the function declaration. + HEADER_START_MARKER (str): The string marking the beginning of the declaration block. + HEADER_END_MARKER (str): The string marking the end of the declaration block. + + Returns: + bool: True if the file was modified or already up-to-date, False on error. + """ + new_declaration = f"void sys_comp_module_{name}_interface_init(void);" + line_to_insert = new_declaration + "\n" + + # --- 1. Read existing lines from the header file --- + try: + with open(header_path, 'r') as f: + lines = f.readlines() + except FileNotFoundError: + print(f"Error: Header file not found at '{header_path}'", file=sys.stderr) + return False + except IOError as e: + print(f"Error: Could not read file '{header_path}': {e}", file=sys.stderr) + return False + + # --- 2. Find start and end markers --- + start_index = -1 + end_index = -1 + for i, line in enumerate(lines): + if HEADER_START_MARKER in line: + start_index = i + elif HEADER_END_MARKER in line: + end_index = i + break # Assume end marker always comes after the start marker + + if start_index == -1 or end_index == -1: + print(f"Error: Start ('{HEADER_START_MARKER}') or end ('{HEADER_END_MARKER}') marker not found.", file=sys.stderr) + return False + if end_index <= start_index: + print(f"Error: End marker appears before start marker.", file=sys.stderr) + return False + + # --- 3. Check if the declaration already exists within the block --- + # Isolate the block of lines where declarations are allowed + declaration_block = lines[start_index + 1 : end_index] + if line_to_insert in declaration_block: + print(f"Declaration for '{name}' already exists within the block. No changes made.") + return True + + # --- 4. Find the correct alphabetical insertion point within the block --- + relative_insert_index = len(declaration_block) + for i, line in enumerate(declaration_block): + # Compare with the stripped content of each line in the block + if line.strip() > new_declaration: + relative_insert_index = i + break + + # Calculate the final insertion index relative to the whole file + final_insert_index = start_index + 1 + relative_insert_index + + # --- 5. Insert the new line into the main list of lines --- + lines.insert(final_insert_index, line_to_insert) + print(f"Inserting declaration for '{name}' at line {final_insert_index + 1}.") + + # --- 6. Write the modified list back to the file --- + try: + with open(header_path, 'w') as f: + f.writelines(lines) + except IOError as e: + print(f"Error: Could not write to file '{header_path}': {e}", file=sys.stderr) + return False + + return True + +def main(): + """ + Main function to drive the script logic. + """ + print("--- SOF SDK New Module Creator ---") + + # Argument Validation --- + if len(sys.argv) == 2 and sys.argv[1] in ['-h', '--help']: + print("Usage: sdk-create-module.py <new_module_name>") + sys.exit(0) + elif len(sys.argv) != 2: + print("\n[ERROR] Invalid number of arguments.") + print("Usage: sdk-create-module.py <new_module_name>") + sys.exit(1) + + # Configuration --- paths are with respect to script dir + modules_root = SCRIPT_DIR + "/../src/audio" + template_name = "template" + new_module_name = sys.argv[1] + uuid_file = SCRIPT_DIR + "/../uuid-registry.txt" + cmake_file = SCRIPT_DIR + "/../src/audio/CMakeLists.txt" + kconfig_file = SCRIPT_DIR + "/../src/audio/Kconfig" + component_file = SCRIPT_DIR + "/../src/include/sof/audio/component.h" + + template_dir = os.path.join(modules_root, template_name) + new_module_dir = os.path.join(modules_root, new_module_name) + + print(f"\nConfiguration:") + print(f" - Modules Root: '{modules_root}'") + print(f" - Template Name: '{template_name}'") + print(f" - New Module Name:'{new_module_name}'") + print(f" - UUID file: '{uuid_file}'") + print(f" - Cmake file: '{cmake_file}'") + print(f" - Kconfig file: '{kconfig_file}'") + print(f" - Component file: '{component_file}'") + + # Check for Pre-existing Directories --- + if not os.path.isdir(template_dir): + print(f"\n[ERROR] Template directory not found at: '{template_dir}'") + sys.exit(1) + + if os.path.exists(new_module_dir): + print(f"\n[ERROR] A directory with the new module name already exists: '{new_module_dir}'") + sys.exit(1) + + # Copy Template Directory --- + try: + print(f"\n[1/6] Copying template directory...") + shutil.copytree(template_dir, new_module_dir) + print(f" -> Successfully copied to '{new_module_dir}'") + except OSError as e: + print(f"\n[ERROR] Could not copy directory. Reason: {e}") + sys.exit(1) + + # Rename Files and Replace Content --- + # We walk through the newly created directory. + print(f"\n[2/6] Renaming files and replacing content...") + process_directory(new_module_dir, template_name, new_module_name) + insert_c_declaration(component_file, new_module_name) + + # Generate UUID for the new module --- + print("\n[3/6] Generating UUID for module...") + insert_uuid_name(uuid_file, new_module_name) + + # Add CMake rule for new module --- + print("\n[4/6] Module creation process finished successfully!") + kconfig_option = f"CONFIG_COMP_{new_module_name.upper()}" + print(f" -> Adding CMake rule for '{kconfig_option}'") + insert_cmake_rule(cmake_file, kconfig_option, new_module_name) + + # Add Kconfig rsource for new module + print("\n[5/6] Module creation process finished successfully!") + insert_kconfig_source(kconfig_file, f"{new_module_name}/Kconfig") + + print("\n[6/6] Module creation process finished successfully!") + print("--- Done ---") + +if __name__ == "__main__": + main() + diff --git a/scripts/set_xtensa_params.sh b/scripts/set_xtensa_params.sh new file mode 100644 index 000000000000..a3932818edc1 --- /dev/null +++ b/scripts/set_xtensa_params.sh @@ -0,0 +1,183 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation. All rights reserved. + +# Because this is meant to be sourced +# shellcheck disable=SC2148 +# shellcheck disable=SC2034 + +### XTENSA_ toolchain configuration shared across projects ### + +# These variables are currently used in/by: +# +# - script/rebuild-testbench.sh +# - before Zephyr's `twister` or `west build` +# +# Not all variables are used in all use cases. Some are. +# +# Find some information about XTENSA_SYSTEM and XTENSA_CORE in +# ./scripts/xtensa-build-zephyr.py --help +# +# The variables used by Zephyr are duplicated in +# xtensa-build-zephyr.py, please keep in sync! + +# To maximize reuse, keep this script very basic and minimal and don't +# `export`: leave which the decision for each variable to the caller. + + +# Sourced script argument $1 is a non-standard bash extension +[ -n "$1" ] || { + >&2 printf 'Missing platform argument\n' + return 1 # Not exit! +} +platform=$1 + +# If adding a new variable is required, avoid adding it to the mass +# duplication in this first, very verbose `case` statement. Prefer +# adding a new, smarter, per-variable `case` statement like the one for +# ZEPHYR_TOOLCHAIN_VARIANT below +PLATFORM="$platform" +case "$platform" in + + # Intel + tgl) + PLATFORM="tgplp" + XTENSA_CORE="cavs2x_LX6HiFi3_2017_8" + HOST="xtensa-cnl-elf" + TOOLCHAIN_VER="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" + TOOLCHAIN_VER="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" + ;; + mtl|lnl) + XTENSA_CORE="ace10_LX7HiFi4_2022_10" + TOOLCHAIN_VER="RI-2022.10-linux" + ;; + ptl) + XTENSA_CORE="ace30_LX7HiFi4_PIF" + TOOLCHAIN_VER="RI-2022.10-linux" + ;; + nvl) + PLATFORM="$platform" + XTENSA_CORE="ace4px_HiFi5MMU_PIF_nlib" + TOOLCHAIN_VER="RI-2022.10-linux" + ;; + + # NXP + imx8) + XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017" + HOST="xtensa-imx-elf" + TOOLCHAIN_VER="RG-2017.8-linux" + ;; + imx8x) + XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017" + HOST="xtensa-imx-elf" + TOOLCHAIN_VER="RG-2017.8-linux" + ;; + imx8m) + XTENSA_CORE="hifi4_mscale_v0_0_2_2017" + HOST="xtensa-imx8m-elf" + TOOLCHAIN_VER="RG-2017.8-linux" + ;; + imx8ulp) + XTENSA_CORE="hifi4_nxp2_ulp_prod" + HOST="xtensa-imx8ulp-elf" + TOOLCHAIN_VER="RG-2017.8-linux" + ;; + + # AMD + rn) + PLATFORM="renoir" + XTENSA_CORE="ACP_3_1_001_PROD_2019_1" + HOST="xtensa-rn-elf" + TOOLCHAIN_VER="RI-2019.1-linux" + ;; + rmb) + PLATFORM="rembrandt" + XTENSA_CORE="LX7_HiFi5_PROD" + HOST="xtensa-rmb-elf" + TOOLCHAIN_VER="RI-2019.1-linux" + ;; + vangogh) + XTENSA_CORE="ACP_5_0_001_PROD" + HOST="xtensa-vangogh-elf" + TOOLCHAIN_VER="RI-2019.1-linux" + ;; + acp_6_3) + XTENSA_CORE="ACP_6_3_HiFi5_PROD_Linux" + HOST="xtensa-acp_6_3-elf" + TOOLCHAIN_VER="RI-2021.6-linux" + ;; + acp_7_0) + XTENSA_CORE="ACP_7_0_HiFi5_NNE_PROD" + HOST="xtensa-acp_7_0-elf" + TOOLCHAIN_VER="RI-2023.11-linux" + ;; + + # Mediatek + mt8186) + XTENSA_CORE="hifi5_7stg_I64D128" + HOST="xtensa-mt8186-elf" + TOOLCHAIN_VER="RI-2020.5-linux" + ;; + mt8188) + XTENSA_CORE="hifi5_7stg_I64D128" + HOST="xtensa-mt8188-elf" + TOOLCHAIN_VER="RI-2020.5-linux" + ;; + mt8195) + XTENSA_CORE="hifi4_8195_PROD" + HOST="xtensa-mt8195-elf" + TOOLCHAIN_VER="RI-2019.1-linux" + ;; + mt8196) + XTENSA_CORE="HiFi5_MPU_lock_2023_11" + HOST="xtensa-mt8196-elf" + TOOLCHAIN_VER="RI-2023.11-linux" + ;; + mt8365) + PLATFORM="mt8365" + XTENSA_CORE="hifi4_Aquila_E2_PROD" + HOST="xtensa-mt8365-elf" + TOOLCHAIN_VER="RG-2018.9-linux" + ;; + qemu_xtensa | qemu_xtensa_mmu) + PLATFORM="$1" + XTENSA_CORE="" + HOST="xtensa-zephyr-elf" + TOOLCHAIN_VER="" + ;; + *) + >&2 printf 'Unknown xtensa platform=%s\n' "$platform" + return 1 + ;; +esac + +# Pre-zephyr "XTOS" build, testbench,... +case "$platform" in + mtl|lnl|ptl|acp_7_0|mt8196|nvl) + SOF_CC_BASE='clang';; + *) + SOF_CC_BASE='xcc';; +esac + +# For Zephyr unit tests +case "$platform" in + qemu_xtensa | qemu_xtensa_mmu) + ZEPHYR_TOOLCHAIN_VARIANT='zephyr';; + imx8*|mtl|lnl) + ZEPHYR_TOOLCHAIN_VARIANT='xt-clang';; + *) # The previous, main case/esac already caught invalid input. + # This won't hurt platforms that don't use Zephyr (it's not even + # exported). + ZEPHYR_TOOLCHAIN_VARIANT='xcc';; +esac diff --git a/scripts/sof-crash-decode.py b/scripts/sof-crash-decode.py new file mode 100755 index 000000000000..8f76921431be --- /dev/null +++ b/scripts/sof-crash-decode.py @@ -0,0 +1,501 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 Intel Corporation. All rights reserved. +""" +decode_crash.py - Zephyr Xtensa Crash Dump Decoder + +Parses a Zephyr crash dump, extracts CPU registers/backtraces, and correlates them +to source code files and function names using the `objdump` output of the ELF file. + +Dependencies: + - python3 + - binutils for your target architecture (e.g. xtensa-zephyr-elf-objdump) + - Optional: `xclip`, `xsel`, or `wl-paste` (for --clipboard support on Linux) + +Usage Examples: + # 1. Provide the ELF and read crash from stdin + cat crash.txt | ./sof-crash-decode.py --elf zephyr.elf + + # 2. Automatically locate ELF/objdump from a Zephyr build directory, read crash from file + ./sof-crash-decode.py --build-dir build-qemu_xtensa/ --dump crash.txt + + # 3. Read directly from the system clipboard + ./sof-crash-decode.py --build-dir build-qemu_xtensa/ --clipboard + + # 4. Pipe a live trace to the decoder + tail -f log.txt | ./sof-crash-decode.py --build-dir build_dir/ + +""" + +import sys +import re +import argparse +import subprocess +import bisect +import os +import json +import shlex + +XTENSA_EXCCAUSE = { + 0: "No Error (or IllegalInstruction)", + 1: "Syscall", + 2: "InstructionFetchError", + 3: "LoadStoreError", + 4: "Level1Interrupt", + 5: "Alloca", + 6: "IntegerDivideByZero", + 8: "Privileged", + 9: "LoadStoreAlignment", + 12: "InstrPIFDataError", + 13: "LoadStorePIFDataError", + 14: "InstrPIFAddrError", + 15: "LoadStorePIFAddrError", + 16: "InstTLBMiss", + 17: "InstTLBMultiHit", + 18: "InstFetchPrivilege", + 20: "InstFetchProhibited", + 24: "LoadStoreTLBMiss", + 25: "LoadStoreTLBMultiHit", + 26: "LoadStorePrivilege", + 28: "LoadStoreProhibited", + 32: "Coprocessor0Disabled", + 33: "Coprocessor1Disabled", + 34: "Coprocessor2Disabled", + 35: "Coprocessor3Disabled", + 36: "Coprocessor4Disabled", + 37: "Coprocessor5Disabled", + 38: "Coprocessor6Disabled", + 39: "Coprocessor7Disabled", +} + +def parse_crash_log(content): + + registers = {} + backtraces = [] + + # Detect QEMU format + if re.search(r'\bPC=[0-9a-fA-F]+\b', content): + reg_pattern = re.compile(r'\b([A-Z0-9]+)=([0-9a-fA-F]+)\b') + for match in reg_pattern.finditer(content): + reg = match.group(1) + val = int(match.group(2), 16) + + if reg == 'EXCVADDR': + reg = 'VADDR' + elif re.match(r'^A\d{2}$', reg): + reg = f"A{int(reg[1:])}" + elif re.match(r'^AR\d{2}$', reg): + reg = f"AR{int(reg[2:])}" + + if re.match(r'^(PC|PR|SP|A\d+|AR\d+|EXCCAUSE|VADDR|LBEG|LEND|SAR|EPC\d+|EPS\d+|PS)$', reg): + registers[reg] = val + else: + # Standard format + # regex for registers: we want standalone pairs like PC 0x123 or A0 0x123 or EXCCAUSE 9 + reg_pattern = re.compile(r'\b([A-Z0-9]+)\s+(0x[0-9a-fA-F]+|\d+|(?:nil))\b') + for match in reg_pattern.finditer(content): + reg = match.group(1) + val_str = match.group(2) + if val_str == "(nil)": + val = 0 + elif val_str.startswith("0x"): + val = int(val_str, 16) + else: + val = int(val_str) + + # Keep only known registers or likely candidates + if re.match(r'^(PC|PR|SP|A\d+|AR\d+|EXCCAUSE|VADDR|LBEG|LEND|SAR|EPC\d+|EPS\d+|PS)$', reg): + registers[reg] = val + + # Backtrace parsing + bt_idx = content.find("Backtrace:") + if bt_idx != -1: + bt_line = content[bt_idx:content.find('\n', bt_idx)] + bt_pattern = re.compile(r'(0x[0-9a-fA-F]+):(0x[0-9a-fA-F]+)') + for match in bt_pattern.finditer(bt_line): + pc = int(match.group(1), 16) + sp = int(match.group(2), 16) + backtraces.append((pc, sp)) + + return registers, backtraces, content + +def get_objdump_output(elf_path, objdump_cmd): + print(f"Running {objdump_cmd} -d -S -l \"{elf_path}\" ...") + try: + # Check if objdump exists + result = subprocess.run([objdump_cmd, "-d", "-S", "-l", elf_path], + capture_output=True, text=True, check=True) + return result.stdout + except FileNotFoundError: + print(f"Error: {objdump_cmd} not found. Please provide the correct objdump command using --objdump.") + sys.exit(1) + except subprocess.CalledProcessError as e: + print(f"Error running objdump: {e}") + sys.exit(1) + +def parse_linker_cmd(filepath): + regions = [] + try: + with open(filepath, 'r') as f: + content = f.read() + m_block = re.search(r'MEMORY\s*\{(.*?)\}', content, re.DOTALL) + if m_block: + for line in m_block.group(1).splitlines(): + line = line.strip() + if not line or ':' not in line: continue + name, rest = line.split(':', 1) + name = name.strip() + m_org = re.search(r'org\s*=\s*(.*?),', rest) + m_len = re.search(r'len\s*=\s*(.*)', rest) + if m_org and m_len: + org_expr = m_org.group(1).strip() + len_expr = m_len.group(1).strip() + try: + org_val = eval(org_expr) + len_val = eval(len_expr) + # Ignore debug regions + if not (name.startswith('.debug') or name.startswith('.stab')): + regions.append({'name': name, 'start': org_val, 'end': org_val + len_val}) + except Exception: + pass + except Exception as e: + print(f"Warning: Failed to parse {filepath}: {e}") + return regions + +def parse_zephyr_stat(filepath): + sections = [] + try: + with open(filepath, 'r') as f: + for line in f: + m = re.match(r'^\s*\[\s*\d+\]\s+(\S+)\s+[A-Z0-9]+\s+([0-9a-fA-F]+)\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)', line) + if m: + name = m.group(1) + start = int(m.group(2), 16) + size = int(m.group(3), 16) + # Ignore debug sections + if size > 0 and not (name.startswith('.debug') or name.startswith('.stab')): + sections.append({'name': name, 'start': start, 'end': start + size}) + except Exception as e: + print(f"Warning: Failed to parse {filepath}: {e}") + return sections + +def parse_zephyr_dts(filepath): + regions = [] + try: + with open(filepath, 'r') as f: + lines = f.read().splitlines() + + current_node_path = [] + for line in lines: + line = line.strip() + # Simple node match: node_name: some_name@addr { + m_node = re.match(r'^(?:[a-zA-Z0-9_]+:\s*)?([a-zA-Z0-9_\-]+(?:@[0-9a-fA-Fx]+)?)\s*\{', line) + if m_node: + node_name = m_node.group(1) + current_node_path.append(node_name) + continue + + if line == "};": + if current_node_path: + current_node_path.pop() + continue + + # match reg = < ... > + m_reg = re.match(r'^reg\s*=\s*<\s*(.*?)\s*>;', line) + if m_reg and current_node_path: + reg_vals = m_reg.group(1).split() + if len(reg_vals) >= 2: + try: + addr = int(reg_vals[0], 16) if reg_vals[0].startswith('0x') else int(reg_vals[0]) + size = int(reg_vals[1], 16) if reg_vals[1].startswith('0x') else int(reg_vals[1]) + if size > 0: + node_name = current_node_path[-1] + regions.append({'name': node_name, 'start': addr, 'end': addr + size}) + except ValueError: + pass + except Exception as e: + print(f"Warning: Failed to parse {filepath}: {e}") + return regions + +def build_address_map(objdump_text): + current_func = "<unknown>" + current_context = [] + last_was_asm = False + address_map = {} + + func_re = re.compile(r'^([0-9a-fA-F]+)\s+<([^>]+)>:$') + asm_re = re.compile(r'^\s*([0-9a-fA-F]+):\s+(.*)$') + + for line in objdump_text.splitlines(): + line = line.rstrip() + if not line or line.startswith("Disassembly of section"): + continue + + m_func = func_re.match(line) + if m_func: + current_func = m_func.group(2) + current_context = [] + last_was_asm = False + continue + + m_asm = asm_re.match(line) + if m_asm: + addr = int(m_asm.group(1), 16) + address_map[addr] = { + 'func': current_func, + 'context': list(current_context), + 'asm': m_asm.group(2) + } + last_was_asm = True + continue + + if last_was_asm: + current_context = [] + last_was_asm = False + current_context.append(line) + + return address_map + +def find_closest_instruction(addr, address_map, sorted_addresses): + if addr in address_map: + return addr, address_map[addr] + + # Extract lower 29 bits for physical address mappings on Xtensa + physical = addr & 0x1FFFFFFF + if physical in address_map: + return physical, address_map[physical] + + idx = bisect.bisect_right(sorted_addresses, physical) + if idx > 0: + closest = sorted_addresses[idx-1] + # Return if within 16 bytes (typical small instruction offset) + if physical - closest < 16: + return closest, address_map[closest] + + return addr, None + +def decode_ps_bits(val): + intlevel = val & 0xF + excm = (val >> 4) & 1 + um = (val >> 5) & 1 + ring = (val >> 6) & 3 + owb = (val >> 8) & 0xF + callinc = (val >> 16) & 3 + woe = (val >> 18) & 1 + + flags = [] + flags.append(f"INTLEVEL:{intlevel}") + if excm: flags.append("EXCM") + flags.append(f"UM:{um}") + flags.append(f"RING:{ring}") + flags.append(f"OWB:{owb}") + flags.append(f"CALLINC:{callinc}") + flags.append(f"WOE:{woe}") + + return " | ".join(flags) + +def main(): + # Set default color explicitly at start + print("\x1b[0m", end='', flush=True) + + parser = argparse.ArgumentParser(description="Decode Xtensa/Zephyr crash dump using objdump.") + parser.add_argument("--elf", required=False, help="Path to the ELF file. Overridden if --build-dir is provided.") + parser.add_argument("--build-dir", required=False, help="Path to the Zephyr build directory.") + parser.add_argument("--dump", default="-", help="Path to the crash dump file. Default is '-' for stdin.") + parser.add_argument("--clipboard", action="store_true", help="Read crash dump from the clipboard instead of file/stdin.") + parser.add_argument("--objdump", default="xtensa-sof-zephyr-elf-objdump", help="Objdump command to use. e.g. xtensa-zephyr-elf-objdump") + args = parser.parse_args() + + objdump_cmd = args.objdump + + if args.build_dir: + # Resolve zephyr.elf + default_elf = os.path.join(args.build_dir, "zephyr", "zephyr.elf") + if os.path.isfile(default_elf): + args.elf = default_elf + + # Try to find objdump from compile_commands + cc_path = os.path.join(args.build_dir, "compile_commands.json") + if not os.path.isfile(cc_path): + cc_path = os.path.join(args.build_dir, "compile_commands.txt") + + if os.path.isfile(cc_path): + try: + with open(cc_path, 'r') as f: + cc_data = json.load(f) + if cc_data and len(cc_data) > 0 and 'command' in cc_data[0]: + # The command might contain arguments, we extract the first token + cmd_tokens = shlex.split(cc_data[0]['command']) + compiler_path = cmd_tokens[0] + # Replace gcc, g++, clang, etc. with objdump + if compiler_path.endswith('gcc') or compiler_path.endswith('g++') or compiler_path.endswith('cc'): + new_cmd = re.sub(r'(g?cc|g\+\+)$', 'objdump', compiler_path) + if os.path.isfile(new_cmd) and os.access(new_cmd, os.X_OK): + objdump_cmd = new_cmd + except Exception as e: + print(f"Warning: Failed to parse {cc_path} to deduce objdump: {e}") + + linker_regions = [] + stat_sections = [] + dts_regions = [] + if args.build_dir: + linker_cmd_path = os.path.join(args.build_dir, "zephyr", "linker.cmd") + zephyr_stat_path = os.path.join(args.build_dir, "zephyr", "zephyr.stat") + zephyr_dts_path = os.path.join(args.build_dir, "zephyr", "zephyr.dts") + + if os.path.isfile(linker_cmd_path): + linker_regions = parse_linker_cmd(linker_cmd_path) + if os.path.isfile(zephyr_stat_path): + stat_sections = parse_zephyr_stat(zephyr_stat_path) + if os.path.isfile(zephyr_dts_path): + dts_regions = parse_zephyr_dts(zephyr_dts_path) + + if not args.elf: + print("Error: --elf or --build-dir must be provided.") + sys.exit(1) + + if not os.path.isfile(args.elf): + print(f"Cannot find ELF file: {args.elf}") + sys.exit(1) + + if args.clipboard: + try: + dump_content = subprocess.check_output(['xclip', '-o', '-selection', 'clipboard'], text=True) + except (subprocess.CalledProcessError, FileNotFoundError): + try: + dump_content = subprocess.check_output(['xsel', '--clipboard', '--output'], text=True) + except (subprocess.CalledProcessError, FileNotFoundError): + try: + dump_content = subprocess.check_output(['wl-paste'], text=True) + except (subprocess.CalledProcessError, FileNotFoundError): + print("Error: Could not read from clipboard. Make sure xclip, xsel, or wl-paste is installed.") + sys.exit(1) + elif args.dump == "-": + dump_content = sys.stdin.read() + else: + if not os.path.isfile(args.dump): + print(f"Cannot find Dump file: {args.dump}") + sys.exit(1) + with open(args.dump, 'r') as f: + dump_content = f.read() + + registers, backtraces, raw_content = parse_crash_log(dump_content) + + print(f"Found {len(registers)} registers and {len(backtraces)} backtrace elements in crash dump.") + + print("Parsing objdump (this may take a few seconds)...") + + # Actually, many systems might use standard xtensa-zephyr-elf-objdump + # We can try to dynamically choose if the user just provided a prefix or left default + + # Try running the objdump to ensure it exists + import shutil + if not os.path.isfile(objdump_cmd) and not shutil.which(objdump_cmd) and "zephyr" in objdump_cmd: + # try without sof if user has a different one + alt_cmds = [ + "xtensa-zephyr-elf-objdump", + "xtensa-intel-elf-objdump", + "zephyr-sdk/xtensa-zephyr-elf-objdump", + "objdump" + ] + for alt in alt_cmds: + if shutil.which(alt): + print(f"Warning: {objdump_cmd} not found, falling back to {alt}") + objdump_cmd = alt + break + + objdump_text = get_objdump_output(args.elf, objdump_cmd) + address_map = build_address_map(objdump_text) + sorted_addresses = sorted(address_map.keys()) + + print("\n--- Summary ---") + print("PS Register Legend:") + print(" INTLEVEL : Interrupt Level EXCM : Exception Mode") + print(" UM : User Mode (1=User) RING : Privilege Ring") + print(" OWB : Old Window Base WOE : Window Overflow Enable") + print(" CALLINC : Call Increment") + print() + + def print_decoded(name, val): + if val == 0: + print(f"{name:5}: 0x00000000 -> (nil)") + return + + addr, info = find_closest_instruction(val, address_map, sorted_addresses) + if info: + print(f"{name:5}: 0x{val:08x} -> <{info['func']}>") + for ctx in info['context']: + ctx_strip = ctx.strip() + if re.match(r'^[^ \t:]+:\d+', ctx_strip): + print(f" \x1b[35m{ctx_strip}\x1b[0m") + else: + print(f" \x1b[93m{ctx_strip}\x1b[0m") + print(f" \x1b[93m{addr:08x}: {info['asm']}\x1b[0m") + print() + else: + dts_str = "" + for d in dts_regions: + if d['start'] <= val < d['end']: + dts_str = f", DT: {d['name']}" + break + region_str = "" + for r in linker_regions: + if r['start'] <= val < r['end']: + region_str = f", Region: {r['name']}" + break + sec_str = "" + for s in stat_sections: + if s['start'] <= val < s['end']: + sec_str = f", Section: {s['name']}" + break + + if dts_str or region_str or sec_str: + print(f"{name:5}: 0x{val:08x} -> <unknown{dts_str}{region_str}{sec_str}>") + else: + print(f"{name:5}: 0x{val:08x} -> <unknown/no code section>") + + # Prioritize specific registers + for reg in ['PC', 'EXCCAUSE', 'VADDR', 'SP', 'PS']: + if reg in registers: + if reg == 'EXCCAUSE': + cause_code = registers[reg] + cause_str = XTENSA_EXCCAUSE.get(cause_code, "Unknown/Unassigned") + print(f"EXCCAUSE: {cause_code} ({cause_str})") + elif reg == 'VADDR': + print(f"{reg:5}: 0x{registers[reg]:08x}") + elif reg == 'PS': + print(f"{reg:5}: 0x{registers[reg]:08x} -> [{decode_ps_bits(registers[reg])}]\n") + else: + print_decoded(reg, registers[reg]) + + for i in range(1, 8): + reg = f"EPC{i}" + if reg in registers: + print_decoded(reg, registers[reg]) + + print() + for i in range(2, 8): + reg = f"EPS{i}" + if reg in registers: + print(f"{reg:5}: 0x{registers[reg]:08x} -> [{decode_ps_bits(registers[reg])}]") + + print("\n--- Physical Windowed Registers (A) ---") + for i in range(16): + reg = f"A{i}" + if reg in registers: + print_decoded(reg, registers[reg]) + + print("\n--- Saved Stack Registers (AR) ---") + for i in range(64): + reg = f"AR{i}" + if reg in registers: + print_decoded(reg, registers[reg]) + + print("\n--- Backtrace Decode ---") + # Backtraces: + for i, (pc, sp) in enumerate(backtraces): + print(f"Frame {i}: SP = 0x{sp:08x}") + print_decoded("PC", pc) + +if __name__ == '__main__': + main() diff --git a/scripts/sof-post-commit-hook.sh b/scripts/sof-post-commit-hook.sh deleted file mode 100755 index e20fce11d5e0..000000000000 --- a/scripts/sof-post-commit-hook.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Intel Corporation. All rights reserved. - -set -e -exec git show --format=email HEAD | ./scripts/checkpatch.pl --no-tree --strict --codespell diff --git a/scripts/sof-pre-commit-hook.sh b/scripts/sof-pre-commit-hook.sh deleted file mode 100755 index cd754f6db661..000000000000 --- a/scripts/sof-pre-commit-hook.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Intel Corporation. All rights reserved. - -exec git diff --cached | scripts/checkpatch.pl --no-tree --codespell --no-signoff -q - - diff --git a/scripts/sof-qemu-run.py b/scripts/sof-qemu-run.py new file mode 100755 index 000000000000..fc985e254d51 --- /dev/null +++ b/scripts/sof-qemu-run.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 Intel Corporation. All rights reserved. +""" +sof-qemu-run.py - Automated QEMU test runner and crash analyzer + +This script runs `west -v build -t run` for Zephyr, monitors the output, and +waits for 2 seconds after the last log event. If a Zephyr/QEMU crash occurs, +it decodes it using `sof-crash-decode.py`. If no crash occurred, it enters +the QEMU monitor (Ctrl-A c), issues `info registers`, and passes the output +to the crash decoder. +""" + +import sys +import pexpect +import subprocess +import argparse +import os + +import re + +# ANSI Color Codes +COLOR_RED = "\x1b[31;1m" +COLOR_YELLOW = "\x1b[33;1m" +COLOR_RESET = "\x1b[0m" + +def colorize_line(line): + """Colorize significant Zephyr log items.""" + if "<err>" in line or "[ERR]" in line or "Fatal fault" in line or "Oops" in line: + return COLOR_RED + line + COLOR_RESET + elif "<wrn>" in line or "[WRN]" in line: + return COLOR_YELLOW + line + COLOR_RESET + return line + +def check_for_crash(output): + """ + Check if the collected output indicates a crash. + Look for known Zephyr/Xtensa oops or exceptions, or QEMU crash register dumps. + """ + crash_keywords = [ + "Fatal fault", + "Oops", + "ZEPHYR FATAL ERROR", + "Exception", + "PC=", # QEMU PC output format + "EXCCAUSE=", + "Backtrace:" + ] + for keyword in crash_keywords: + if keyword in output: + return True + return False + +def run_sof_crash_decode(build_dir, dump_content): + """ + Invokes sof-crash-decode.py and feeds it the crash dump via stdin. + """ + # Find sof-crash-decode.py in the same directory as this script, or fallback to relative path + decoder_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "sof-crash-decode.py") + if not os.path.isfile(decoder_script): + decoder_script = "sof-crash-decode.py" + + print("\n====================================") + print("Running sof-crash-decode.py Analysis") + print("====================================\n") + + cmd = [sys.executable, decoder_script, "--build-dir", build_dir] + + try: + proc = subprocess.Popen(cmd, stdin=subprocess.PIPE) + proc.communicate(input=dump_content.encode('utf-8')) + except Exception as e: + print(f"Failed to run sof-crash-decode.py: {e}") + +def main(): + parser = argparse.ArgumentParser(description="Run QEMU via west and automatically decode crashes.") + parser.add_argument("--build-dir", default="build", help="Path to the build directory containing zephyr.elf, linker.cmd, etc. Defaults to 'build'.") + parser.add_argument("--log-file", default="qemu-run.log", help="Path to save the QEMU output log. Defaults to 'qemu-run.log'.") + args = parser.parse_args() + + # Make absolute path just in case + build_dir = os.path.abspath(args.build_dir) + + print(f"Starting QEMU test runner. Monitoring for crashes (Build Dir: {args.build_dir})...") + + # We will use pexpect to spawn the west command to get PTY features + import shutil + west_path = shutil.which("west") + if not west_path: + print("[sof-qemu-run] Error: 'west' command not found in PATH.") + print("Please ensure you have sourced the Zephyr environment (e.g., source zephyr-env.sh).") + sys.exit(1) + + child = pexpect.spawn(west_path, ["-v", "build", "-t", "run"], encoding='utf-8') + + # We will accumulate output to check for crashes + full_output = "" + + with open(args.log_file, "w") as log_file: + try: + # Loop reading output until EOF or a timeout occurs + qemu_started = False + while True: + try: + # Read character by character or line by line + # Pexpect's readline() doesn't consistently trigger timeout on idle + # We can use read_nonblocking and an explicit exceptTIMEOUT + index = child.expect([r'\r\n', pexpect.TIMEOUT, pexpect.EOF], timeout=2) + if index == 0: + line = child.before + '\n' + # Strip ANSI escape codes from output to write raw text to log file + clean_line = re.sub(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])', '', line) + log_file.write(clean_line) + log_file.flush() + + colored_line = colorize_line(line) + sys.stdout.write(colored_line) + sys.stdout.flush() + + full_output += line + if not qemu_started and ("Booting Zephyr OS" in line or "To exit from QEMU" in line or "qemu-system-" in line): + qemu_started = True + elif index == 1: # TIMEOUT + if qemu_started or check_for_crash(full_output): + print("\n\n[sof-qemu-run] 2 seconds passed since last log event. Checking status...") + break + else: + # Still building or loading, continue waiting + pass + elif index == 2: # EOF + print("\n\n[sof-qemu-run] QEMU process terminated.") + break + + except pexpect.TIMEOUT: + if qemu_started or check_for_crash(full_output): + print("\n\n[sof-qemu-run] 2 seconds passed since last log event. Checking status...") + break + else: + # Still building or loading, continue waiting + pass + except pexpect.EOF: + print("\n\n[sof-qemu-run] QEMU process terminated.") + break + + except KeyboardInterrupt: + print("\n[sof-qemu-run] Interrupted by user.") + # Proceed with what we have + + crashed = check_for_crash(full_output) + + if crashed: + print("\n[sof-qemu-run] Detected crash signature in standard output!") + # Stop QEMU if it's still running + if child.isalive(): + child.sendline("\x01x") # Ctrl-A x to quit qemu + child.close(force=True) + + run_sof_crash_decode(build_dir, full_output) + else: + print("\n[sof-qemu-run] No crash detected. Interacting with QEMU Monitor to grab registers...") + + # We need to send Ctrl-A c to enter the monitor + if child.isalive(): + child.send("\x01c") # Ctrl-A c + try: + # Wait for (qemu) prompt + child.expect(r"\(qemu\)", timeout=5) + # Send "info registers" + child.sendline("info registers") + # Wait for the next prompt + child.expect(r"\(qemu\)", timeout=5) + + info_regs_output = child.before + print("\n[sof-qemu-run] Successfully extracted registers from QEMU monitor.\n") + + # Quit qemu safely + child.sendline("quit") + child.expect(pexpect.EOF, timeout=2) + child.close() + + # Run the decoder on the intercepted register output + run_sof_crash_decode(build_dir, info_regs_output) + except pexpect.TIMEOUT: + print("\n[sof-qemu-run] Timed out waiting for QEMU monitor. Is it running?") + child.close(force=True) + except pexpect.EOF: + print("\n[sof-qemu-run] QEMU terminated before we could run monitor commands.") + else: + print("\n[sof-qemu-run] Process is no longer alive, cannot extract registers.") + +if __name__ == "__main__": + main() diff --git a/scripts/sof-qemu-run.sh b/scripts/sof-qemu-run.sh new file mode 100755 index 000000000000..e1ece1dd5125 --- /dev/null +++ b/scripts/sof-qemu-run.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 Intel Corporation. All rights reserved. + +# Define the build directory from the first argument (or default) +BUILD_DIR="${1:-build}" + +# Find and source the zephyr environment script, typically via the sof-venv wrapper +# or directly if running in a known zephyrproject layout. +# We will use the existing helper sof-venv.sh to get the right environment. + +# Get the directory of this script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOF_WORKSPACE="$(dirname "$(dirname "$SCRIPT_DIR")")" + +# Use the SOF workspace to locate the virtual environment +VENV_DIR="$SOF_WORKSPACE/.venv" +echo "Using SOF environment at $SOF_WORKSPACE" + +# start the virtual environment +source ${VENV_DIR}/bin/activate + +# Execute the QEMU runner from within the correct build directory +cd "${BUILD_DIR}" || exit 1 + +# Finally run the python script which will now correctly inherit 'west' from the sourced environment. +python3 "${SCRIPT_DIR}/sof-qemu-run.py" --build-dir "${BUILD_DIR}" + diff --git a/scripts/sof-rebuild-processing-comp-blobs.sh b/scripts/sof-rebuild-processing-comp-blobs.sh new file mode 100755 index 000000000000..617669c10646 --- /dev/null +++ b/scripts/sof-rebuild-processing-comp-blobs.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Intel Corporation. + +set -e + +if [ -z "${SOF_WORKSPACE}" ]; then + echo "Error: environment variable SOF_WORKSPACE need to be set to top level sof directory" + exit 1 +fi + +if ! command -v octave &> /dev/null; then + echo "Error: this script needs GNU Octave, see https://octave.org/" + exit 1 +fi + +"$SOF_WORKSPACE"/sof/scripts/build-tools.sh -c + +if ! command -v sof-ctl &> /dev/null; then + echo "Error: The sof-ctl utility is not found from path for executables. It is needed" + echo " to retrieve SOF ABI header It can be added with e.g. symlink to user's binaries:" + echo " ln -s $SOF_WORKSPACE/sof/tools/build_tools/ctl/sof-ctl $HOME/bin/sof-ctl" + exit 1 +fi + +cmp --quiet "$(which sof-ctl)" "$SOF_WORKSPACE"/sof/tools/build_tools/ctl/sof-ctl || { + echo "Error: The sof-ctl in user's path is not the same as sof-ctl build from tools." + exit 1 +} + +OCTAVE="octave --quiet --no-window-system" +cd "$SOF_WORKSPACE"/sof/src/audio/aria/tune; $OCTAVE sof_aria_blobs.m +cd "$SOF_WORKSPACE"/sof/src/audio/crossover/tune; $OCTAVE sof_example_crossover.m +cd "$SOF_WORKSPACE"/sof/src/audio/dcblock/tune; $OCTAVE sof_example_dcblock.m +cd "$SOF_WORKSPACE"/sof/src/audio/drc/tune; $OCTAVE sof_example_drc.m +cd "$SOF_WORKSPACE"/sof/src/audio/eq_iir/tune; $OCTAVE sof_example_iir_eq.m +cd "$SOF_WORKSPACE"/sof/src/audio/eq_iir/tune; $OCTAVE sof_example_fir_eq.m +cd "$SOF_WORKSPACE"/sof/src/audio/eq_iir/tune; $OCTAVE sof_example_iir_bandsplit.m +cd "$SOF_WORKSPACE"/sof/src/audio/eq_iir/tune; $OCTAVE sof_example_spk_eq.m +cd "$SOF_WORKSPACE"/sof/src/audio/multiband_drc/tune; $OCTAVE sof_example_multiband_drc.m +cd "$SOF_WORKSPACE"/sof/src/audio/tdfb/tune; ./sof_example_all.sh +cd "$SOF_WORKSPACE"/sof/src/audio/selector/tune; $OCTAVE ./sof_selector_blobs.m +cd "$SOF_WORKSPACE"/sof/tools/tune/mfcc; $OCTAVE setup_mfcc.m +cd "$SOF_WORKSPACE"/sof/src/audio/level_multiplier/tune; $OCTAVE sof_level_multiplier_blobs.m diff --git a/scripts/sof-testbench-build-profile.sh b/scripts/sof-testbench-build-profile.sh new file mode 100755 index 000000000000..73a880a353b9 --- /dev/null +++ b/scripts/sof-testbench-build-profile.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause + +set -e + +usage() { + echo "Usage: $0 <options>" + echo " -d <directory> directory to place code profiling reports" + echo " -h shows this text" + echo " -p <platform> sets platform for scripts/rebuild-testbench.sh" + echo +} + +MODULES_S32_44K_48K="asrc src" +MODULES_S32="dcblock drc drc_multiband dolby-dax eqfir eqiir gain level_multiplier micsel \ + sound_dose stft_process_1536_240_ template_comp tdfb" +MODULES_S24="aria" + +if [ -z "${SOF_WORKSPACE}" ]; then + echo "Error: environment variable SOF_WORKSPACE need to be set to top level sof directory" + exit 1 +fi + +PLATFORM=none +PDIR=$SOF_WORKSPACE/sof/tools/testbench/profile + +while getopts "hp:d:" opt; do + case "${opt}" in + d) + PDIR=${OPTARG} + ;; + h) + usage + exit + ;; + p) + PLATFORM=${OPTARG} + ;; + *) + usage + exit + ;; + esac +done +shift $((OPTIND-1)) + +# Build +SCRIPTS=$SOF_WORKSPACE/sof/scripts +mkdir -p "$PDIR" +"$SCRIPTS"/rebuild-testbench.sh -p "$PLATFORM" +HELPER="$SCRIPTS"/sof-testbench-helper.sh + +echo "Profiler reports are stored to $PDIR" + +# Run sof-hda-generic.tplg playback +echo "Profiling sof-hda-generic.tplg ..." +$HELPER -x -t production/sof-hda-generic.tplg -n 1,2 \ + -p "$PDIR/profile-$PLATFORM-generic.txt" > "$PDIR/log-$PLATFORM-generic.txt" + +# Run sof-hda-benchmark-generic.tplg playback +echo "Profiling sof-hda-benchmark-generic.tplg ..." +$HELPER -x -t development/sof-hda-benchmark-generic.tplg -n 1,2,3 \ + -p "$PDIR/profile-$PLATFORM-benchmark.txt" > "$PDIR/log-$PLATFORM-benchmark.txt" + +# Profile modules +for mod in $MODULES_S32_44K_48K +do + echo "Profiling $mod ..." + $HELPER -r 44100 -x -m "$mod" \ + -p "$PDIR/profile-$PLATFORM-$mod.txt" > "$PDIR/log-$PLATFORM-$mod.txt" +done + +for mod in $MODULES_S32 +do + echo "Profiling $mod ..." + $HELPER -x -m "$mod" -p "$PDIR/profile-$PLATFORM-$mod.txt" > "$PDIR/log-$PLATFORM-$mod.txt" +done + +for mod in $MODULES_S24 +do + echo "Profiling $mod ..." + $HELPER -b 24 -x -m "$mod" -p "$PDIR/profile-$PLATFORM-$mod.txt" > "$PDIR/log-$PLATFORM-$mod.txt" +done diff --git a/scripts/sof-testbench-helper.sh b/scripts/sof-testbench-helper.sh new file mode 100755 index 000000000000..ea7a6590ee67 --- /dev/null +++ b/scripts/sof-testbench-helper.sh @@ -0,0 +1,187 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause + +set -e + +usage() { + echo "Usage: $0 <options>" + echo "Options" + echo " -b <bits>, default 32" + echo " -c <channels>, default 2" + echo " -h shows this text" + echo " -i <input wav>, default /usr/share/sounds/alsa/Front_Center.wav" + echo " -k keep temporary files in /tmp" + echo " -m <module>, default gain" + echo " -n <pipelines>, default 1,2" + echo " -o <output wav>, default none" + echo " -p <profiling result text>, use with -x, default none" + echo " -r <rate>, input rate, default 48000" + echo " -R <rate>, output rate, default 48000" + echo " -t <force topology>, default none, e.g. production/sof-hda-generic.tplg" + echo " -v runs with valgrind, not available with -x" + echo " -x runs testbench with xt-run simulator" + echo + echo "Example: run DRC with xt-run with profiling (slow)" + echo "$0 -x -m drc -p profile-drc32.txt" + echo + echo "Example: process with native build DRC file Front_Center.wav (fast)" + echo "$0 -m drc -i /usr/share/sounds/alsa/Front_Center.wav -o ~/tmp/Front_Center_with_DRC.wav" + echo + echo "Example: check component eqiir with valgrind" + echo "$0 -v -m eqiir" + echo +} + +if [ -z "${SOF_WORKSPACE}" ]; then + echo "Error: environment variable SOF_WORKSPACE need to be set to top level sof directory" + exit 1 +fi + +OUTWAV= +CLIP=/usr/share/sounds/alsa/Front_Center.wav +MODULE=gain +BITS=32 +RATE_IN=48000 +RATE_OUT=48000 +CHANNELS_IN=2 +CHANNELS_OUT=2 +PIPELINES="1,2" +INFILE1=$(mktemp --tmpdir=/tmp in-XXXX.raw) +OUTFILE1=$(mktemp --tmpdir=/tmp out-XXXX.raw) +TRACEFILE=$(mktemp --tmpdir=/tmp trace-XXXX.txt) +PROFILEOUT=$(mktemp --tmpdir=/tmp profile-XXXX.out) +KEEP_TMP=false +XTRUN=false +PROFILE=false +TPLG0= +VALGRIND= + +while getopts "b:c:hi:km:n:o:p:r:R:t:vx" opt; do + case "${opt}" in + b) + BITS=${OPTARG} + ;; + c) + CHANNELS_IN=${OPTARG} + CHANNELS_OUT=${OPTARG} + ;; + h) + usage + exit + ;; + i) + CLIP=${OPTARG} + ;; + k) + KEEP_TMP=true + ;; + m) + MODULE=${OPTARG} + ;; + n) + PIPELINES=${OPTARG} + ;; + o) + OUTWAV=${OPTARG} + ;; + p) + PROFILETXT=${OPTARG} + PROFILE=true + ;; + r) + RATE_IN=${OPTARG} + ;; + R) + RATE_OUT=${OPTARG} + ;; + t) + TPLG0=${OPTARG} + ;; + v) + VALGRIND=valgrind + ;; + x) + XTRUN=true + ;; + *) + usage + exit + ;; + esac +done +shift $((OPTIND-1)) + +echo Converting clip "$CLIP" to raw input +if [[ "$BITS" == "24" ]]; then + # Sox does not support S24_4LE format + # Note gain 0.00390615 is empically find just a bit lower gain than + # 1/256 = 0.00390625 that doesn't cause sox rounding to exceed + # INT24_MIN .. INT24_MAX range. + sox --encoding signed-integer "$CLIP" -L -r "$RATE_IN" -c "$CHANNELS_IN" -b 32 "$INFILE1" vol 0.00390615 +else + sox --encoding signed-integer "$CLIP" -L -r "$RATE_IN" -c "$CHANNELS_IN" -b "$BITS" "$INFILE1" +fi + +TB4="$SOF_WORKSPACE/sof/tools/testbench/build_testbench/install/bin/sof-testbench4" +XTB4="$SOF_WORKSPACE/sof/tools/testbench/build_xt_testbench/sof-testbench4" +XTB4_SETUP="$SOF_WORKSPACE/sof/tools/testbench/build_xt_testbench/xtrun_env.sh" +if [ -z "$TPLG0" ]; then + TPLG="$SOF_WORKSPACE/sof/tools/build_tools/topology/topology2/development/sof-hda-benchmark-${MODULE}${BITS}.tplg" +else + TPLG="$SOF_WORKSPACE/sof/tools/build_tools/topology/topology2/$TPLG0" +fi +FMT="S${BITS}_LE" +OPTS="-r $RATE_IN -R $RATE_OUT -c $CHANNELS_IN -c $CHANNELS_OUT -b $FMT -p $PIPELINES -t $TPLG -i $INFILE1 -o $OUTFILE1" + +if [ ! -f "$TPLG" ]; then + echo "Error: Topology $TPLG is not found" + echo "Build with scripts/build-tools.sh -Y" + exit 1 +fi + +if [[ "$XTRUN" == true ]]; then + if [ ! -x "$XTB4" ]; then + echo "Error: No executable found from $XTB4" + echo "Build with scripts/rebuild-testbench.sh -p <platform>" + exit 1 + fi + echo "Running xtensa testbench" + echo " topology: $TPLG" + echo " input: $INFILE1, output: $OUTFILE1, trace: $TRACEFILE, profile: $PROFILETXT" + source "$XTB4_SETUP" + if [[ $PROFILE == true ]]; then + "$XTENSA_PATH"/xt-run --mem_model --profile="$PROFILEOUT" "$XTB4" $OPTS 2> "$TRACEFILE" + "$XTENSA_PATH"/xt-gprof "$XTB4" "$PROFILEOUT" > "$PROFILETXT" + else + "$XTENSA_PATH"/xt-run --mem_model "$XTB4" $OPTS 2> "$TRACEFILE" + fi +else + if [ ! -x "$TB4" ]; then + echo "Error: No executable found from $TB4" + exit 1 + fi + echo "Running testbench" + echo " topology: $TPLG" + echo " input: $INFILE1, output: $OUTFILE1, trace: $TRACEFILE" + $VALGRIND "$TB4" $OPTS 2> "$TRACEFILE" || { + cat "$TRACEFILE" + exit $? + } + if [ -n "$VALGRIND" ]; then + cat "$TRACEFILE" + fi +fi + +if [ -n "$OUTWAV" ]; then + echo Converting raw output to "$OUTWAV" + if [[ "$BITS" == "24" ]]; then + sox --encoding signed-integer -L -r "$RATE_OUT" -c "$CHANNELS_OUT" -b 32 "$OUTFILE1" "$OUTWAV" vol 256 + else + sox --encoding signed-integer -L -r "$RATE_OUT" -c "$CHANNELS_OUT" -b "$BITS" "$OUTFILE1" "$OUTWAV" + fi +fi + +if [[ "$KEEP_TMP" == false ]]; then + echo Deleting temporary files + rm -f "$INFILE1" "$OUTFILE1" "$TRACEFILE" "$PROFILEOUT" +fi diff --git a/scripts/sudo-cwd.sh b/scripts/sudo-cwd.sh new file mode 100755 index 000000000000..2823cf2f6c73 --- /dev/null +++ b/scripts/sudo-cwd.sh @@ -0,0 +1,77 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022 Intel Corporation. All rights reserved. + +# This is a "brute force" solution to filesystem permission issues: +# +# If the current user does not own the current directory then this +# wrapper script switches to the user who does own the current directory +# before running the given command. + +# If no user owns the current directory, a user who does gets created +# first! + +# The main use case is to run this first thing inside a container to +# solve file ownership mismatches. + +# `docker run --user=$(id -un) ...` achieves something very similar +# without any code except the resulting user many not exist inside the +# container. Some commands may not like that. +# +# To understand more about the Docker problem solved here take a look at +# https://stackoverflow.com/questions/35291520/docker-and-userns-remap-how-to-manage-volume-permissions-to-share-data-betwee +# and many other similar questions. + +# TODO: replace sudo with gosu? + +set -e +set -x + +main() +{ + cwd_uid="$(stat --printf='%u' .)" + local current_uid; current_uid="$(id -u)" + if test "$current_uid" = "$cwd_uid"; then + exec "$@" + else + exec_as_cwd_uid "$@" + fi +} + +exec_as_cwd_uid() +{ + # If missing, add new user owning the current directory + local cwd_user; cwd_user="$(id "$cwd_uid")" || { + cwd_user='cwd_user' + + local cwd_guid; cwd_guid="$(stat --printf='%g' .)" + + getent group "$cwd_guid" || + sudo groupadd -g "$cwd_guid" 'cwd_group' + + sudo useradd -m -u "$cwd_uid" -g "$cwd_guid" "$cwd_user" + + local current_user; current_user="$(id -un)" + + # Copy sudo permissions just in case the build needs it + if test -e /etc/sudoers.d/"$current_user"; then + sudo sed -e "s/$current_user/$cwd_user/" /etc/sudoers.d/"$current_user" | + sudo tee -a /etc/sudoers.d/"$cwd_user" + sudo chmod --reference=/etc/sudoers.d/"$current_user" \ + /etc/sudoers.d/"$cwd_user" + fi + } + + # Double sudo to work around some funny restriction in + # zephyr-build:/etc/sudoers: 'user' can do anything but... only as + # root. + # Passing empty http[s]_proxy is OK + # shellcheck disable=SC2154 + sudo sudo -u "$cwd_user" REAL_CC="$REAL_CC" \ + http_proxy="$http_proxy" https_proxy="$https_proxy" \ + "$@" + + exit "$?" +} + +main "$@" diff --git a/scripts/tensorflow-clone.sh b/scripts/tensorflow-clone.sh new file mode 100755 index 000000000000..d3f67d0a835e --- /dev/null +++ b/scripts/tensorflow-clone.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2025 Intel Corporation. All rights reserved. + +# fail immediately on any errors +set -e + +# Array of TFLM Git repository URLs. Add or remove repositories as needed. +declare -a REPOS=( + "https://github.com/thesofproject/nnlib-hifi4" + "https://github.com/tensorflow/tflite-micro" + "https://github.com/thesofproject/flatbuffers" + "https://github.com/google/gemmlowp" + "https://github.com/google/ruy" +) + +# Commit ID to check for (optional). If specified, the script will update +# the repository if this commit ID is not found. Leave empty to skip. +declare -a COMMIT_ID=( + "cdedfb1a1044eb774915de21b63a1b6aa93276f6" + "e86d97b6237f88ab5925c0b41e3e3589a1560d86" + "f5acabf4e1a3fcba024081bb1871a2ed59aa1c28" + "719139ce755a0f31cbf1c37f7f98adcc7fc9f425" + "d37128311b445e758136b8602d1bbd2a755e115d" +) + +# Directory where repositories will be cloned/updated. +BASE_DIR="$HOME/work/sof" # Or any other desired location + +# Function to check if a commit ID exists in a repository +check_commit() { + local repo_dir="$1" + local commit_id="$2" + + if [ -z "$commit_id" ]; then + return 0 # Skip check if no commit ID is provided + fi + + if ! git -C "$repo_dir" rev-parse --quiet --verify "$commit_id" >/dev/null 2>&1; then + return 1 # Commit ID not found + else + return 0 # Commit ID found + fi +} + + +# Function to update the repository +update_repo() { + local repo_dir="$1" + echo "Updating repository: $repo_dir" + git -C "$repo_dir" fetch --all + git -C "$repo_dir" pull +} + +# Main script logic +mkdir -p "$BASE_DIR" + +for ((i = 0; i < ${#REPOS[@]}; i++)); do + echo "Counter: $i, Value: ${REPOS[i]}" + repo_url=${REPOS[i]} + + repo_name=$(basename "$repo_url" .git) # Extract repo name + repo_dir="$BASE_DIR/$repo_name" + + if [ ! -d "$repo_dir" ]; then + echo "Cloning repository: $repo_url" + git clone "$repo_url" "$repo_dir" || { echo "git clone failed for $repo_url"; exit 1; } + elif ! check_commit "$repo_dir" "${COMMIT_ID[i]}"; then + update_repo "$repo_dir" + else + echo "Repository $repo_name is up to date." + fi +done + +echo "All repositories processed." diff --git a/scripts/test-repro-build.sh b/scripts/test-repro-build.sh new file mode 100755 index 000000000000..3a3cea4660fd --- /dev/null +++ b/scripts/test-repro-build.sh @@ -0,0 +1,195 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2021 Intel Corporation. All rights reserved. + +# This builds SOF twice with some environment variations and then +# compares the binary outputs. + +# Big caveats: +# +# - Only -g0 is supported, no BUILD_PATH_PREFIX_MAP +# - rimage uses the current date (day month year) in the +# signature. +# - Starting from TGL, signatures also include a random salt. +# +# rimage makes sof.ri non-deterministic even when sof.elf is +# deterministic. See https://github.com/thesofproject/rimage/issues/41 +# and below for more details and future directions. + +# The following, basic environment variations are currently tested: +# +# - timestamps (obviously) +# - source directory +# - disorderfs + +# For a list of other, non-tested environment variations check the +# "Achieve deterministic builds" list found at +# https://reproducible-builds.org/docs/ + + +set -e + + +SOF_TOP=$(cd "$(dirname "$0")"/.. && /bin/pwd) +SOF_PARENT=$(cd "$SOF_TOP"/.. && /bin/pwd) + + +SOF2="$SOF_PARENT"/sof-bind-mount-DO-NOT-DELETE +# To avoid ripple effects and reduce the number of differences +# considerably, replace "sof" with something of the same length: +# SOF2="$SOF_PARENT"/sog + +PLATFS=(rmb) + +# 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 +# suggestion for local use. Requires less -R. +diffo () +{ + # Omitting $2 ("and") allows copy/paste of the output of diff -r + diffoscope --exclude-directory-metadata=recursive \ + --text-color=always "$1" "$3" +} + +hexdiff () +{ + # cut -b10 removes the offset + diff --color=auto -U20 \ + <(hexdump -vC "$1" | cut -b10- ) \ + <(hexdump -vC "$2" | cut -b10- ) | less +} + +init() +{ + # -E(xtended) regex + local excluded_endings=( + '\.log' /deps + '\.c?make' '\.ninja' /TargetDirectories.txt + /CMakeCache.txt /progress.marks /CMakeRulesHashes.txt /Makefile + /CMakeRuleHashes.txt /Makefile2 + '/depend\.internal' /link.txt '\.includecache' + '/.ninja_deps' '/.ninja_log' + '.*\.c\.o\.d' + '/rimage_ep.*' + '/smex_ep.*' + ) + + # The signing process is not deterministic. + # Keep 'reproducible.ri' INCLUDED! + excluded_endings+=('/sof-[a-z-]{,6}\.rix?') + excluded_endings+=('/sof\.ri' '/sof-no-xman\.ri' ) + + GREP_EXCLUDE_ARGS=() + for fpath in "${excluded_endings[@]}"; do + GREP_EXCLUDE_ARGS+=('-e' "$fpath differ\$") + done + + # For debug + # declare -p GREP_EXCLUDE_ARGS # exit +} + + +trap _unmount EXIT + +_unmount() +{ + set +e + + if mount | grep -q "${SOF2}.*fuse"; then + umount "$SOF2" + rmdir "$SOF2" + fi +} + + +diff_some_files() +{ + local p f + ( set +e + + for p in "${PLATFS[@]}"; do + + # Compare some ELF section headers. Look at the smallest .c.o + # first + for f in CMakeFiles/sof.dir/src/arch/xtensa/init.c.o sof; do + + diff --report-identical-files \ + {b0,b1}/build_"$p"_?cc/"$f" || + diff -u --ignore-matching-lines='file format ' \ + <(objdump -h b0/build_"$p"_?cc/"$f") \ + <(objdump -h b1/build_"$p"_?cc/"$f") + + done + + for f in generated/include/sof_versions.h sof.ri \ + src/arch/xtensa/reproducible.ri; do + diff -u --report-identical-files \ + {b0,b1}/build_"$p"_?cc/"$f" + # report unsupported reproducible.ri + test -s b0/build_"$p"_?cc/"$f" || + printf '\t%s is EMPTY\n' b0/build_"$p"_?cc/"$f" + done + + done + true + ) | sed -e 's/differ/DIFFER/g' +} + +main() +{ + init + + test -e "$SOF2"/CMakeLists.txt || { + mkdir -p "$SOF2" + # This will fail in Docker; Docker should provide this bind + # mount for us. + disorderfs "${SOF_TOP}" "$SOF2" + } + + # Chances of name collisions with the user should be pretty small + rm -rf reprobld/b0/ reprobld/b1/ + mkdir -p reprobld/b0/ reprobld/b1/ + + local oldTZ="$TZ" # typically undefined, coming from some /etc file + # instead. + + export EXTRA_CFLAGS='-g0' + + # Going once + + export TZ='Pacific/Midway' # -11:00 + "${SOF_TOP}"/scripts/xtensa-build-all.sh "${PLATFS[@]}" + mv build_*_?cc reprobld/b0/ + + + # Going twice + + # Use this to "break" rimage that makes the date (in local time! + # BIOS fans?) part of the CSS signature. See caveats above. + # +14:00 - -11:00 = +25:00 = always on a different date + export TZ='Pacific/Kiritimati' # +14:00 + + "$SOF2"/scripts/xtensa-build-all.sh "${PLATFS[@]}" + mv build_*_?cc reprobld/b1/ + + + # Restore TZ just in case we want to use dates later. + TZ="$oldTZ" + + + cd reprobld + diff -qr b0 b1/ | + grep -E -v "${GREP_EXCLUDE_ARGS[@]}" || { + printf \ + "\n\n ---- PASS: no unexpected difference found between %s/b0/ and b1/ --- \n\n" "$(pwd)" + exit 0 + } + + printf "\n\n ---- FAIL: differences found between %s/b0/ and b1/ --- \n\n" "$(pwd)" + diff_some_files + printf "\n\n ---- FAIL: differences found between %s/b0/ and b1/ --- \n\n" "$(pwd)" +} + +test -x "${SOF_TOP}"/scripts/xtensa-build-all.sh || exit 0 + +main "$@" diff --git a/scripts/vscode-task.sh b/scripts/vscode-task.sh new file mode 100755 index 000000000000..b5a3ba1cecd5 --- /dev/null +++ b/scripts/vscode-task.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2025 Intel Corporation. All rights reserved. + +# Simple helper script for vscode task support. +# Current vscode tasks have difficulty executing multiple commands. + +# check if Zephyr environment is set up +if [ ! -z "$ZEPHYR_BASE" ]; then + VENV_DIR="$ZEPHYR_BASE/.venv" + echo "Using Zephyr environment at $ZEPHYR_BASE" +elif [ ! -z "$SOF_WORKSPACE" ]; then + VENV_DIR="$SOF_WORKSPACE/zephyr/.venv" + echo "Using SOF/Zephyr environment at $SOF_WORKSPACE" +else + # fallback to the zephyr default from the getting started guide + VENV_DIR="$HOME/zephyrproject/.venv" + echo "Using default Zephyr environment at $VENV_DIR" +fi + +# start the virtual environment +source ${VENV_DIR}/bin/activate + +# The vscode workspace is the parent directory of the SOF Firmware directory +# we need to cd into sof to run the zephyr build script +cd sof + +# run the zephyr script +./scripts/xtensa-build-zephyr.py "$@" + +# cleanup +deactivate diff --git a/scripts/xtensa-build-all.sh b/scripts/xtensa-build-all.sh deleted file mode 100755 index 38f63c5b1c0e..000000000000 --- a/scripts/xtensa-build-all.sh +++ /dev/null @@ -1,367 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 Intel Corporation. All rights reserved. - -SUPPORTED_PLATFORMS=(byt cht bdw hsw apl skl kbl cnl sue icl jsl \ - imx8 imx8x imx8m) -BUILD_ROM=no -BUILD_DEBUG=no -BUILD_FORCE_UP=no -BUILD_JOBS=$(nproc --all) -BUILD_JOBS_NEXT=0 -BUILD_VERBOSE=OFF - -PATH=$pwd/local/bin:$PATH - -pwd=`pwd` - -if [ "$#" -eq 0 ] -then - echo "usage: xtensa-build.sh [options] platform(s)" - echo " [-r] Build rom (gcc only)" - echo " [-a] Build all platforms" - echo " [-u] Force UP ARCH" - echo " [-d] Enable debug build" - echo " [-c] Configure defconfig" - echo " [-k] Use private key" - echo " [-v] Verbose Makefile log" - echo " [-j [n]] Set number of make build jobs." \ - "Jobs=#cores when no flag. Inifinte when no arg." - echo " Supported platforms ${SUPPORTED_PLATFORMS[@]}" -else - # parse the args - for args in $@ - do - if [[ "$args" == "-r" ]] - then - BUILD_ROM=yes - - elif [[ "$args" == "-u" ]] - then - BUILD_FORCE_UP=yes - - elif [[ "$args" == "-d" ]] - then - BUILD_DEBUG=yes - - elif [[ "$args" == "-j" ]] - then - BUILD_JOBS_NEXT=1 - BUILD_JOBS="" - - elif [[ "$args" == "-c" ]] - then - MAKE_MENUCONFIG=yes - - elif [[ "$args" == "-k" ]] - then - USE_PRIVATE_KEY=yes - - elif [[ "$args" == "-v" ]] - then - BUILD_VERBOSE=ON - - # Build all platforms - elif [[ "$args" == "-a" ]] - then - PLATFORMS=${SUPPORTED_PLATFORMS[@]} - else - # check for plaform - for i in ${SUPPORTED_PLATFORMS[@]} - do - if [ $i == $args ] - then - PLATFORMS+=$i" " - BUILD_JOBS_NEXT=0 - fi - done - - # check for jobs - if [ ${BUILD_JOBS_NEXT} == 1 ] - then - BUILD_JOBS=$args - BUILD_JOBS_NEXT=0 - fi - fi - done -fi - -# check target platform(s) have been passed in -if [ ${#PLATFORMS[@]} -eq 0 ]; -then - echo "Error: No platforms specified. Supported are: ${SUPPORTED_PLATFORMS[@]}" - exit 1 -fi - -if [ "x$USE_PRIVATE_KEY" == "xyes" ] -then - if [ -z ${RIMAGE_PRIVATE_KEY+x} ] - then - echo "Error: No variable specified for RIMAGE_PRIVATE_KEY" - exit 1 - fi - PRIVATE_KEY_OPTION="-DRIMAGE_PRIVATE_KEY=${RIMAGE_PRIVATE_KEY}" -fi - -# fail on any errors -set -e - -OLDPATH=$PATH -WORKDIR="$pwd" - -# build platform -for j in ${PLATFORMS[@]} -do - HAVE_ROM='no' - DEFCONFIG_PATCH='' - if [ $j == "byt" ] - then - PLATFORM="baytrail" - ARCH="xtensa" - XTENSA_CORE="Intel_HiFiEP" - ROOT="$pwd/../xtensa-root/xtensa-byt-elf" - HOST="xtensa-byt-elf" - XTENSA_TOOLS_VERSION="RD-2012.5-linux" - fi - if [ $j == "cht" ] - then - PLATFORM="cherrytrail" - ARCH="xtensa" - XTENSA_CORE="CHT_audio_hifiep" - ROOT="$pwd/../xtensa-root/xtensa-byt-elf" - HOST="xtensa-byt-elf" - XTENSA_TOOLS_VERSION="RD-2012.5-linux" - fi - if [ $j == "bdw" ] - then - PLATFORM="broadwell" - ARCH="xtensa" - XTENSA_CORE="LX4_langwell_audio_17_8" - ROOT="$pwd/../xtensa-root/xtensa-hsw-elf" - HOST="xtensa-hsw-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - fi - if [ $j == "hsw" ] - then - PLATFORM="haswell" - ARCH="xtensa" - XTENSA_CORE="LX4_langwell_audio_17_8" - ROOT="$pwd/../xtensa-root/xtensa-hsw-elf" - HOST="xtensa-hsw-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - fi - if [ $j == "apl" ] - then - PLATFORM="apollolake" - ARCH="xtensa-smp" - XTENSA_CORE="X4H3I16w2D48w3a_2017_8" - - # test APL compiler aliases and ignore set -e here - type xtensa-bxt-elf-gcc > /dev/null 2>&1 && true - if [ $? == 0 ] - then - HOST="xtensa-bxt-elf" - else - HOST="xtensa-apl-elf" - fi - - ROOT="$pwd/../xtensa-root/$HOST" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "skl" ] - then - PLATFORM="skylake" - ARCH="xtensa" - XTENSA_CORE="X4H3I16w2D48w3a_2017_8" - - # test APL compiler aliases and ignore set -e here - type xtensa-bxt-elf-gcc > /dev/null 2>&1 && true - if [ $? == 0 ] - then - HOST="xtensa-bxt-elf" - else - HOST="xtensa-apl-elf" - fi - - ROOT="$pwd/../xtensa-root/$HOST" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "kbl" ] - then - PLATFORM="kabylake" - ARCH="xtensa" - XTENSA_CORE="X4H3I16w2D48w3a_2017_8" - - # test APL compiler aliases and ignore set -e here - type xtensa-bxt-elf-gcc > /dev/null 2>&1 && true - if [ $? == 0 ] - then - HOST="xtensa-bxt-elf" - else - HOST="xtensa-apl-elf" - fi - - ROOT="$pwd/../xtensa-root/$HOST" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "cnl" ] - then - PLATFORM="cannonlake" - ARCH="xtensa-smp" - XTENSA_CORE="X6H3CNL_2017_8" - ROOT="$pwd/../xtensa-root/xtensa-cnl-elf" - HOST="xtensa-cnl-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "sue" ] - then - PLATFORM="suecreek" - ARCH="xtensa" - XTENSA_CORE="X6H3CNL_2017_8" - ROOT="$pwd/../xtensa-root/xtensa-cnl-elf" - HOST="xtensa-cnl-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "icl" ] - then - PLATFORM="icelake" - ARCH="xtensa-smp" - XTENSA_CORE="X6H3CNL_2017_8" - ROOT="$pwd/../xtensa-root/xtensa-cnl-elf" - HOST="xtensa-cnl-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "jsl" ] - then - PLATFORM="jasperlake" - ARCH="xtensa-smp" - XTENSA_CORE="X6H3CNL_2017_8" - ROOT="$pwd/../xtensa-root/xtensa-cnl-elf" - HOST="xtensa-cnl-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - fi - if [ $j == "imx8" ] - then - PLATFORM="imx8" - ARCH="xtensa" - XTENSA_CORE="hifi4_nxp_v3_3_1_2_dev" - ROOT="$pwd/../xtensa-root/xtensa-imx-elf" - HOST="xtensa-imx-elf" - XTENSA_TOOLS_VERSION="RF-2016.4-linux" - fi - if [ $j == "imx8x" ] - then - PLATFORM="imx8x" - ARCH="xtensa" - XTENSA_CORE="hifi4_nxp_v3_3_1_2_dev" - ROOT="$pwd/../xtensa-root/xtensa-imx-elf" - HOST="xtensa-imx-elf" - XTENSA_TOOLS_VERSION="RF-2016.4-linux" - fi - if [ $j == "imx8m" ] - then - PLATFORM="imx8m" - ARCH="xtensa" - XTENSA_CORE="hifi4_mscale_v0_0_2_prod" - ROOT="$pwd/../xtensa-root/xtensa-imx8m-elf" - HOST="xtensa-imx8m-elf" - XTENSA_TOOLS_VERSION="RF-2016.4-linux" - fi - - if [ $XTENSA_TOOLS_ROOT ] - then - XTENSA_TOOLS_DIR="$XTENSA_TOOLS_ROOT/install/tools/$XTENSA_TOOLS_VERSION" - XTENSA_BUILDS_DIR="$XTENSA_TOOLS_ROOT/install/builds/$XTENSA_TOOLS_VERSION" - - # make sure the required version of xtensa tools is installed - if [ -d $XTENSA_TOOLS_DIR ] - then - XCC="xt-xcc" - XTOBJCOPY="xt-objcopy" - XTOBJDUMP="xt-objdump" - else - XCC="none" - XTOBJCOPY="none" - XTOBJDUMP="none" - echo "XTENSA_TOOLS_DIR is not a directory" - fi - fi - - # update ROOT directory for xt-xcc - if [ "$XCC" == "xt-xcc" ] - then - TOOLCHAIN=xt - ROOT="$XTENSA_BUILDS_DIR/$XTENSA_CORE/xtensa-elf" - export XTENSA_SYSTEM=$XTENSA_BUILDS_DIR/$XTENSA_CORE/config - PATH=$XTENSA_TOOLS_DIR/XtensaTools/bin:$OLDPATH - COMPILER="xcc" - else - TOOLCHAIN=$HOST - PATH=$pwd/../$HOST/bin:$OLDPATH - COMPILER="gcc" - - case $j in - byt|cht|cnl|sue) DEFCONFIG_PATCH="_gcc";; - *) DEFCONFIG_PATCH="";; - esac - fi - - BUILD_DIR=build_${j}_${COMPILER} - echo "Build in "$BUILD_DIR - - # only delete binary related to this build - rm -fr $BUILD_DIR - mkdir $BUILD_DIR - cd $BUILD_DIR - - cmake -DTOOLCHAIN=$TOOLCHAIN \ - -DROOT_DIR=$ROOT \ - -DCMAKE_VERBOSE_MAKEFILE=${BUILD_VERBOSE} \ - ${PRIVATE_KEY_OPTION} \ - .. - - make ${PLATFORM}${DEFCONFIG_PATCH}_defconfig - - if [[ "x$MAKE_MENUCONFIG" == "xyes" ]] - then - make menuconfig - fi - - rm -fr override.config - - if [[ "x$BUILD_DEBUG" == "xyes" ]] - then - echo "CONFIG_DEBUG=y" >> override.config - fi - - if [[ "x$BUILD_ROM" == "xyes" && "x$HAVE_ROM" == "xyes" ]] - then - echo "CONFIG_BUILD_VM_ROM=y" >> override.config - fi - - # override default ARCH if BUILD_FORCE_UP is set - if [ "x$BUILD_FORCE_UP" == "xyes" ] - then - echo "Force building UP(xtensa)..." - echo "CONFIG_SMP=n" >> override.config - fi - - if [ -e override.config ] - then - make overrideconfig - fi - - make bin -j ${BUILD_JOBS} - - cd "$WORKDIR" -done - -# list all the images -ls -l build_*/*.ri diff --git a/scripts/xtensa-build-zephyr.py b/scripts/xtensa-build-zephyr.py new file mode 100755 index 000000000000..36c0a25aabb5 --- /dev/null +++ b/scripts/xtensa-build-zephyr.py @@ -0,0 +1,1396 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause + +# Too much noise for now, these can be re-enabled after they've been +# fixed (if that does not break `git blame` too much) + +# W0311, W0312, W0603 +# pylint:disable=bad-indentation +# pylint:disable=mixed-indentation +# pylint:disable=global-statement + +# C0103, C0114, C0116 +# pylint:disable=invalid-name +# pylint:disable=missing-module-docstring +# pylint:disable=missing-function-docstring + +# Non-indentation whitespace has been removed from newer pylint. It does +# not hurt to keep them for older versions. The recommendation is to use +# a formatter like `black` instead, unfortunately this would totally +# destroy git blame, git revert, etc. + +# C0326, C0330 +# pylint:disable=bad-whitespace +# pylint:disable=bad-continuation + +import argparse +import shlex +import subprocess +import pathlib +import errno +import platform as py_platform +import sys +import shutil +import os +import warnings +import fnmatch +import hashlib +import json +import gzip +import dataclasses +import concurrent.futures as concurrent +import tarfile +import re + +from west import configuration as west_config + +# anytree module is defined in Zephyr build requirements +from anytree import AnyNode, RenderTree, render +from packaging import version + +# https://chrisyeh96.github.io/2017/08/08/definitive-guide-python-imports.html#case-3-importing-from-parent-directory +sys.path.insert(1, os.path.join(sys.path[0], '..')) +from tools.sof_ri_info import sof_ri_info + +MIN_PYTHON_VERSION = 3, 8 +assert sys.version_info >= MIN_PYTHON_VERSION, \ + f"Python {MIN_PYTHON_VERSION} or above is required." + +# Version of this script matching Major.Minor.Patch style. +VERSION = version.Version("2.0.0") + +# Constant value resolves SOF_TOP directory as: "this script directory/.." +SOF_TOP = pathlib.Path(__file__).parents[1].resolve() +west_top = pathlib.Path(SOF_TOP, "..").resolve() + +sof_fw_version = None + +signing_key = None + +if py_platform.system() == "Windows": + xtensa_tools_version_postfix = "-win32" +elif py_platform.system() == "Linux": + xtensa_tools_version_postfix = "-linux" +else: + xtensa_tools_version_postfix = "-unsupportedOS" + warnings.warn(f"Your operating system: {py_platform.system()} is not supported") + + +@dataclasses.dataclass +# pylint:disable=too-many-instance-attributes +class PlatformConfig: + "Product parameters" + vendor: str + PLAT_CONFIG: str + XTENSA_TOOLS_VERSION: str + XTENSA_CORE: str + DEFAULT_TOOLCHAIN_VARIANT: str = "xt-clang" + RIMAGE_KEY: pathlib.Path = pathlib.Path(SOF_TOP, "keys", "otc_private_key_3k.pem") + aliases: list = dataclasses.field(default_factory=list) + ipc4: bool = False + +# These cannot be built by everyone out of the box yet. +# For instance: there's no open-source toolchain available for them yet. +extra_platform_configs = { + "wcl-sim" : PlatformConfig( + "intel", "intel_adsp/ace30/wcl/sim", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace30_LX7HiFi4_PIF", + ipc4 = True + ), + "ptl-sim" : PlatformConfig( + "intel", "intel_adsp/ace30/ptl/sim", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace30_LX7HiFi4_PIF", + ipc4 = True + ), + # AMD platforms + "acp_6_0" : PlatformConfig( + "amd", "acp_6_0_adsp/acp_6_0", + f"RI-2019.1{xtensa_tools_version_postfix}", + "rmb_LX7_HiFi5_PROD", + RIMAGE_KEY = "key param ignored by acp_6_0" + ), + "acp_7_0" : PlatformConfig( + "amd", "acp_7_0_adsp/acp_7_0", + f"RI-2023.11{xtensa_tools_version_postfix}", + "ACP_7_0_HiFi5_NNE_PROD", + RIMAGE_KEY = "key param ignored by acp_7_0" + ), + # MediaTek platforms + # (move to platform_configs_all on next Zephyr SDK release after 0.17.0) + "mt8195" : PlatformConfig( + "mtk", "mt8195/mt8195/adsp", + f"RJ-2024.3{xtensa_tools_version_postfix}", + "hifi4_8195_PROD", + ), + "mt8186" : PlatformConfig( + "mtk", "mt8186/mt8186/adsp", + f"RJ-2024.3{xtensa_tools_version_postfix}", + "hifi5_7stg_I64D128", + ), + "mt8188" : PlatformConfig( + "mtk", "mt8188/mt8188/adsp", + f"RJ-2024.3{xtensa_tools_version_postfix}", + "hifi5_7stg_I64D128", + ), + "mt8196" : PlatformConfig( + "mtk", "mt8196/mt8196/adsp", + f"RJ-2024.3{xtensa_tools_version_postfix}", + "HiFi5_MPU_lock_2023_11", + ), + "mt8365" : PlatformConfig( + "mtk", "mt8365/mt8365/adsp", + f"RJ-2024.3{xtensa_tools_version_postfix}", + "hifi4_Aquila_E2_PROD", + ), +} + +# These can all be built out of the box. --all builds all these. +# Some of these values are duplicated in sof/scripts/set_xtensa_param.sh: keep them in sync. +platform_configs_all = { + # Intel platforms + "tgl" : PlatformConfig( + "intel", "intel_adsp/cavs25", + f"RG-2017.8{xtensa_tools_version_postfix}", + "cavs2x_LX6HiFi3_2017_8", + "xcc", + aliases = ['adl', 'adl-n', 'rpl'], + ipc4 = True + ), + "tgl-h" : PlatformConfig( + "intel", "intel_adsp/cavs25/tgph", + f"RG-2017.8{xtensa_tools_version_postfix}", + "cavs2x_LX6HiFi3_2017_8", + "xcc", + aliases = ['adl-s', 'rpl-s'], + ipc4 = True + ), + "mtl" : PlatformConfig( + "intel", "intel_adsp/ace15_mtpm", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace10_LX7HiFi4_2022_10", + aliases = ['arl', 'arl-s'], + ipc4 = True + ), + "lnl" : PlatformConfig( + "intel", "intel_adsp/ace20_lnl", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace10_LX7HiFi4_2022_10", + ipc4 = True + ), + "ptl" : PlatformConfig( + "intel", "intel_adsp/ace30/ptl", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace30_LX7HiFi4_PIF", + ipc4 = True + ), + "wcl" : PlatformConfig( + "intel", "intel_adsp/ace30/wcl", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace30_LX7HiFi4_PIF", + ipc4 = True + ), + "nvl" : PlatformConfig( + "intel", "intel_adsp/ace40/nvl", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace4px_HiFi5MMU_PIF_nlib", + ipc4 = True + ), + "nvl-s" : PlatformConfig( + "intel", "intel_adsp/ace40/nvls", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace4px_HiFi5MMU_PIF_nlib", + ipc4 = True + ), + # NXP platforms + "imx8" : PlatformConfig( + "imx", "imx8qm_mek/mimx8qm6/adsp", + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_nxp_v5_3_1_prod", + RIMAGE_KEY = "key param ignored by imx8", + ), + "imx8x" : PlatformConfig( + "imx", "imx8qxp_mek/mimx8qx6/adsp", + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_nxp_v5_3_1_prod", + RIMAGE_KEY = "key param ignored by imx8x" + ), + "imx8m" : PlatformConfig( + "imx", "imx8mp_evk/mimx8ml8/adsp", + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_mscale_v2_0_2_prod", + RIMAGE_KEY = "key param ignored by imx8m" + ), + "imx8m_cm7" : PlatformConfig( + "imx", "imx8mp_evk/mimx8ml8/m7/ddr", + "", "", "", "" + ), + "imx8ulp" : PlatformConfig( + "imx", "imx8ulp_evk/mimx8ud7/adsp", + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_nxp2_s7_v2_1a_prod", + RIMAGE_KEY = "key param ignored by imx8ulp" + ), + "imx95" : PlatformConfig( + "imx", "imx95_evk/mimx9596/m7/ddr", + "", "", "", "" + ), + "qemu_xtensa" : PlatformConfig( + "zephyr", "qemu_xtensa/dc233c", + "", "", "zephyr" + ), + "qemu_xtensa_mmu" : PlatformConfig( + "zephyr", "qemu_xtensa/dc233c/mmu", + "", "", "zephyr" + ), +} + +platform_configs = platform_configs_all.copy() +platform_configs.update(extra_platform_configs) + +class validate_platforms_arguments(argparse.Action): + """Validates positional platform arguments whether provided platform name is supported.""" + def __call__(self, parser, namespace, values, option_string=None): + if values: + for value in values: + if value not in platform_configs: + raise argparse.ArgumentError(self, f"Unsupported platform: {value}") + setattr(namespace, "platforms", values) + +args = None +def parse_args(): + global args + global west_top + parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, + epilog=( + +f"""This script supports XtensaTools but only when installed in a specific directory +structure where a single --xtensa-core is registered per --xtensa-system registry, example +below. Different layouts may or may not work. + +myXtensa/ +└── install/ + ├── builds/ + │ ├── RD-2012.5{xtensa_tools_version_postfix} + │ │ └── Intel_HiFiEP/config/ # XTENSA_SYSTEM registry + │ │ ├── default-params + │ │ └── Intel_HiFiEP-params # single, default XTENSA_CORE per registry + │ └── RG-2017.8{xtensa_tools_version_postfix} + │ ├── LX4_langwell_audio_17_8/config/ + │ │ ├── default-params + │ │ └── LX4_langwell_audio_17_8-params + │ └── X4H3I16w2D48w3a_2017_8/config/ + │ ├── default-params + │ └── X4H3I16w2D48w3a_2017_8-params + └── tools/ + ├── RD-2012.5{xtensa_tools_version_postfix} + │ └── XtensaTools + └── RG-2017.8{xtensa_tools_version_postfix} + └── XtensaTools/ + +$XTENSA_TOOLS_ROOT=/path/to/myXtensa ... + +Supported platforms: {list(platform_configs)}""" + + ), add_help=False) + + parser.add_argument('-h', '--help', action='store_true', help='show help') + parser.add_argument("-a", "--all", required=False, action="store_true", + help="Build all currently supported platforms") + parser.add_argument("platforms", nargs="*", action=validate_platforms_arguments, + help="List of platforms to build. Zero platform + any flag (-p) still creates 'tools/'") + parser.add_argument("-d", "--debug", required=False, action="store_true", + help="Shortcut for: -o sof/app/debug_overlay.conf") + # NO SOF release will ever user the option --fw-naming. + # This option is only for disguising SOF IPC4 as CAVS IPC4 and only in cases where + # the kernel 'ipc_type' expects CAVS IPC4. In this way, developers and CI can test + # IPC4 on older platforms. + parser.add_argument("--fw-naming", required=False, choices=["AVS", "SOF"], + default="SOF", +help="""Determine firmware naming conversion and folder structure. +See also the newer and better '--deployable-build' for IPC4. +With "SOF" (default): + +build-sof-staging (for /lib/firmware/intel/sof/) + ├───community + │ └── sof-tgl.ri + ├── dbgkey + │ └── sof-tgl.ri + ├── sof-tgl.ri + └── sof-tgl.ldc + +With "AVS"; filename 'dsp_basefw.bin'. +'AVS' automatically enables --use-platform-subdir which uses one subdirectory for each platform: + +build-sof-staging (for old, developer /lib/firmware/intel/sof-ipc4/) + └── tgl + ├── community + │ └── dsp_basefw.bin + ├── dbgkey + │ └── dsp_basefw.bin + ├── dsp_basefw.bin + └── sof-tgl.ldc + +""") + parser.add_argument("-j", "--jobs", required=False, type=int, + help="Number of concurrent jobs. Passed to west build and" + " to cmake (for rimage)") + parser.add_argument("-k", "--key", type=pathlib.Path, required=False, + help="Path to a non-default rimage signing key.") + + # https://docs.zephyrproject.org/latest/build/kconfig/setting.html#initial-conf + # https://docs.zephyrproject.org/latest/develop/application/index.html#important-build-system-variables + # TODO, support "snippets"? + # https://docs.zephyrproject.org/latest/build/snippets/writing.html + parser.add_argument("-o", "--overlay", type=pathlib.Path, required=False, action='append', + default=[], help= +"""All '-o arg1 -o arg2 ...' arguments are combined into a single -DEXTRA_CONF_FILE='arg1;arg2;...' +list. This tweaks the build CONFIGuration like Device Tree "overlays" and Zephyr snippets do. +Files latter in the list seem to have precedence. Direct -C=-DCONFIG_xxx=.. options seem to +have precedence over -DEXTRA_CONF_FILE=... Rely on precedence as little as possible.""") + + parser.add_argument("-p", "--pristine", required=False, action="store_true", + help="Perform pristine build removing build directory.") + parser.add_argument("-u", "--update", required=False, action="store_true", + help="""Runs west update command - clones SOF dependencies. Downloads next to this sof clone a new Zephyr +project with its required dependencies. Creates a modules/audio/sof symbolic link pointing +back at this sof clone. All projects are checkout out to +revision defined in manifests of SOF and Zephyr.""") + parser.add_argument('-v', '--verbose', default=0, action='count', + help="""Verbosity level. Repetition of the flag increases verbosity. +The same number of '-v' is passed to "west". +""", + ) + # Cannot use a standard -- delimiter because argparse deletes it. + parser.add_argument("-C", "--cmake-args", action='append', default=[], + help="""Cmake arguments passed as is to cmake configure step. +Can be passed multiple times; whitespace is preserved Example: + + -C=--warn-uninitialized -C '-DEXTRA_FLAGS=-Werror -g0' + +Note '-C --warn-uninitialized' is not supported by argparse, an equal +sign must be used (https://bugs.python.org/issue9334)""", + ) + + parser.add_argument("--key-type-subdir", default="community", + choices=["community", "none", "dbgkey"], + help="""Output subdirectory for rimage signing key type. +Default key type subdirectory is \"community\".""") + + + parser.add_argument("--use-platform-subdir", default = False, + action="store_true", + help="""Use an output subdirectory for each platform. +Otherwise, all firmware files are installed in the same staging directory by default.""") + + parser.add_argument("--no-interactive", default=False, action="store_true", + help="""Run script in non-interactive mode when user input can not be provided. +This should be used with programmatic script invocations (eg. Continuous Integration). + """) + + deploy_args = parser.add_mutually_exclusive_group() + # argparse.BooleanOptionalAction requires Python 3.9 + parser.set_defaults(deployable_build=True) + deploy_args.add_argument("--no-deployable-build", dest='deployable_build', action='store_false') + deploy_args.add_argument("--deployable-build", dest='deployable_build', action='store_true', + help="""Create a directory structure for the firmware files which can be deployed on target as it is. +This option will cause the --fw-naming and --use-platform-subdir options to be ignored! +The generic, default directory and file structure is IPC version dependent: +IPC3 + build-sof-staging/sof/VENDOR/sof/ (on target: /lib/firmware/VENDOR/sof/) + ├── community + │ └── sof-PLAT.ri + ├── dbgkey + │ └── sof-PLAT.ri + └── sof-PLAT.ri +IPC4 + build-sof-staging/sof/VENDOR/sof-ipc4/ (on target: /lib/firmware/VENDOR/sof-ipc4/) + └── PLAT + ├── community + │ └── sof-PLAT.ri + ├── dbgkey + │ └── sof-PLAT.ri + └── sof-PLAT.ri\n + """) + + parser.add_argument("--no-tarball", default=False, action='store_true', + help="""Do not create a tar file of the installed firmware files under build-sof-staging.""") + parser.add_argument("--version", required=False, action="store_true", + help="Prints version of this script.") + parser.add_argument("-m", "--menuconfig", required=False, action="store_true", + help="Build menuconfig for target") + parser.add_argument("-z", "--zephyrsdk", required=False, action="store_true", + help="Force Build using Zephyr SDK for target") + + args = parser.parse_args() + + # This does NOT include "extra", experimental platforms. + if args.all: + args.platforms = list(platform_configs_all) + + # print help message if no arguments provided + if len(sys.argv) == 1 or args.help: + for platform in platform_configs: + if platform_configs[platform].aliases: + parser.epilog += "\nPlatform aliases for '" + platform + "':\t" + parser.epilog += f"{list(platform_configs[platform].aliases)}" + + parser.print_help() + sys.exit(0) + + if args.deployable_build: + if args.fw_naming == 'AVS' or args.use_platform_subdir: + sys.exit("Options '--fw-naming=AVS' and '--use-platform-subdir'" + " are incompatible with deployable builds, try --no-deployable-build?") + + if args.fw_naming == 'AVS': + if not args.use_platform_subdir: + args.use_platform_subdir=True + warnings.warn("The option '--fw-naming AVS' has to be used with '--use-platform-subdir'. Enable '--use-platform-subdir' automatically.") + +def execute_command(*run_args, **run_kwargs): + """[summary] Provides wrapper for subprocess.run that prints + command executed when 'more verbose' verbosity level is set.""" + command_args = run_args[0] + + # If you really need the shell in some non-portable section then + # invoke subprocess.run() directly. + if run_kwargs.get('shell') or not isinstance(command_args, list): + raise RuntimeError("Do not rely on non-portable shell parsing") + + if args.verbose >= 0: + cwd = run_kwargs.get('cwd') + print_cwd = f"In dir: {cwd}" if cwd else f"in current dir: {os.getcwd()}" + print_args = shlex.join(command_args) + 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 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"{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 not 'check' in run_kwargs: + run_kwargs['check'] = True + #pylint:disable=subprocess-run-check + + return subprocess.run(*run_args, **run_kwargs) + +def symlink_or_copy(targetdir, targetfile, linkdir, linkfile): + """Create a relative symbolic link or copy. Don't bother Windows users + with symbolic links because they require special privileges. + Windows don't care about /lib/firmware/sof/ anyway. + Make a copy instead to preserve cross-platform consistency. + """ + target = pathlib.Path(targetdir) / targetfile + link = pathlib.Path(linkdir) / linkfile + if py_platform.system() == "Windows": + shutil.copy2(target, link) + else: + link.symlink_to(os.path.relpath(target, linkdir)) + +def show_installed_files(): + """[summary] Scans output directory building binary tree from files and folders + then presents them in similar way to linux tree command.""" + graph_root = AnyNode(name=STAGING_DIR.name, long_name=".", parent=None) + relative_entries = [ + entry.relative_to(STAGING_DIR) for entry in sorted(STAGING_DIR.glob("**/*")) + ] + nodes = [ graph_root ] + for entry in relative_entries: + # Node's documentation does allow random attributes + # pylint: disable=no-member + # sorted() makes sure our parent is already there. + # This is slightly awkward, a recursive function would be more readable + matches = [node for node in nodes if node.long_name == str(entry.parent)] + assert len(matches) == 1, f'"{entry}" does not have exactly one parent' + nodes.append(AnyNode(name=entry.name, long_name=str(entry), parent=matches[0])) + + for pre, _, node in RenderTree(graph_root, render.AsciiStyle): + fpath = STAGING_DIR / node.long_name + + # pathLib.readlink() requires Python 3.9 + symlink_trailer = f" -> {os.readlink(fpath)}" if fpath.is_symlink() else "" + + stem = node.name[:-3] if node.name.endswith(".gz") else node.name + + shasum_trailer = "" + if checksum_wanted(stem) and fpath.is_file() and not fpath.is_symlink(): + shasum_trailer = "\tsha256=" + checksum(fpath) + + print(f"{pre}{node.name} {symlink_trailer} {shasum_trailer}") + + +# TODO: among other things in this file it should be less SOF-specific; +# try to move as much as possible to generic Zephyr code. See +# discussions in https://github.com/zephyrproject-rtos/zephyr/pull/51954 +def checksum_wanted(stem): + for pattern in CHECKSUM_WANTED: + if fnmatch.fnmatch(stem, pattern): + return True + return False + + +def checksum(fpath): + if fpath.suffix == ".gz": + inputf = gzip.GzipFile(fpath, "rb") + else: + inputf = open(fpath, "rb") + chksum = hashlib.sha256(inputf.read()).hexdigest() + inputf.close() + return chksum + + +def check_west_installation(): + west_path = shutil.which("west") + if not west_path: + raise FileNotFoundError("Install west and a west toolchain," + "https://docs.zephyrproject.org/latest/getting_started/index.html") + print(f"Found west: {west_path}") + +def west_reinitialize(west_root_dir: pathlib.Path, west_manifest_path: pathlib.Path): + """[summary] Performs west reinitialization to SOF manifest file asking user for permission. + Prints error message if script is running in non-interactive mode. + + :param west_root_dir: directory where is initialized. + :type west_root_dir: pathlib.Path + :param west_manifest_path: manifest file to which west is initialized. + :type west_manifest_path: pathlib.Path + :raises RuntimeError: Raised when west is initialized to wrong manifest file + (not SOFs manifest) and script is running in non-interactive mode. + """ + global west_top + message = "West is initialized to manifest other than SOFs!\n" + message += f"Initialized to manifest: {west_manifest_path}." + "\n" + dot_west_directory = pathlib.Path(west_root_dir.resolve(), ".west") + if args.no_interactive: + message += f"Try deleting {dot_west_directory } directory and rerun this script." + raise RuntimeError(message) + question = message + "Reinitialize west to SOF manifest? [Y/n] " + print(f"{question}") + while True: + reinitialize_answer = input().lower() + if reinitialize_answer in ["y", "n"]: + break + sys.stdout.write('Please respond with \'Y\' or \'n\'.\n') + + if reinitialize_answer != 'y': + sys.exit("Can not proceed. Reinitialize your west manifest to SOF and rerun this script.") + shutil.rmtree(dot_west_directory) + execute_command(["west", "init", "-l", f"{SOF_TOP}"], cwd=west_top) + + +# TODO: use west APIs directly instead of all these indirect subprocess.run("west", ...) processes +def west_init_if_needed(): + """[summary] Validates whether west workspace had been initialized and points to SOF manifest. + Peforms west initialization if needed. + """ + global west_top, SOF_TOP + west_manifest_path = pathlib.Path(SOF_TOP, "west.yml") + result_rootdir = execute_command(["west", "topdir"], capture_output=True, cwd=west_top, + timeout=10, check=False) + if result_rootdir.returncode != 0: + execute_command(["west", "init", "-l", f"{SOF_TOP}"], cwd=west_top) + return + west_root_dir = pathlib.Path(result_rootdir.stdout.decode().rstrip()).resolve() + result_manifest_dir = execute_command(["west", "config", "manifest.path"], capture_output=True, + cwd=west_top, timeout=10, check=True) + west_manifest_dir = pathlib.Path(west_root_dir, result_manifest_dir.stdout.decode().rstrip()).resolve() + manifest_file_result = execute_command(["west", "config", "manifest.file"], capture_output=True, + cwd=west_top, timeout=10, check=True) + returned_manifest_path = pathlib.Path(west_manifest_dir, manifest_file_result.stdout.decode().rstrip()) + if not returned_manifest_path.samefile(west_manifest_path): + west_reinitialize(west_root_dir, returned_manifest_path) + else: + print(f"West workspace: {west_root_dir}") + print(f"West manifest path: {west_manifest_path}") + +def create_zephyr_directory(): + global west_top + # Do not fail when there's only an empty directory left over + # (because of some early interruption of this script or proxy + # misconfiguration, etc.) + try: + # rmdir() is safe: it deletes empty directories ONLY. + west_top.rmdir() + except OSError as oserr: + if oserr.errno not in [errno.ENOTEMPTY, errno.ENOENT]: + raise oserr + # else when not empty then let the next line fail with a + # _better_ error message: + # "zephyrproject already exists" + + west_top.mkdir(parents=False, exist_ok=False) + west_top = west_top.resolve(strict=True) + +def create_zephyr_sof_symlink(): + global west_top, SOF_TOP + if not west_top.exists(): + raise FileNotFoundError("No west top: {}".format(west_top)) + audio_modules_dir = pathlib.Path(west_top, "modules", "audio") + audio_modules_dir.mkdir(parents=True, exist_ok=True) + sof_symlink = pathlib.Path(audio_modules_dir, "sof") + # Symlinks creation requires administrative privileges in Windows or special user rights + try: + if not sof_symlink.exists(): + sof_symlink.symlink_to(SOF_TOP, target_is_directory=True) + except: + print(f"Failed to create symbolic link: {sof_symlink} to {SOF_TOP}." + "\nIf you run script on Windows run it with administrative privileges or\n" + "grant user symlink creation rights -" + "see: https://docs.microsoft.com/en-us/windows/security/threat-protection/" + "security-policy-settings/create-symbolic-links") + raise + +def west_update(): + """[summary] Clones all west manifest projects to specified revisions""" + global west_top + execute_command(["west", "update"], check=True, timeout=3000, cwd=west_top) + + +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, + extract the version information from sof/versions.json and later platforms will + reuse it. + """ + global sof_fw_version + if sof_fw_version: + return sof_fw_version + + versions = {} + 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" + if os.path.exists(directory): + shutil.rmtree(directory) + +def clean_staging(platform): + print(f"Cleaning {platform} from {STAGING_DIR}") + + rmtree_if_exists(STAGING_DIR / "sof-info" / platform) + + sof_output_dir = STAGING_DIR / "sof" + + # --use-platform-subdir + rmtree_if_exists(sof_output_dir / platform) + + # Remaining .ri and .ldc files + for p in [ platform ] + platform_configs[platform].aliases: + for f in sof_output_dir.glob(f"**/sof-{p}.*"): + os.remove(f) + + # remove IPC4 deployable build directories + if platform_configs[platform].ipc4: + # e.g.: "build-sof-staging/sof/intel/sof-ipc4/mtl/" + sof_vendor_dir = sof_output_dir / platform_configs[platform].vendor + rmtree_if_exists(sof_vendor_dir / "sof-ipc4" / platform) + rmtree_if_exists(sof_vendor_dir / "sof-ipc4-lib" / platform) + for p_alias in platform_configs[platform].aliases: + rmtree_if_exists(sof_vendor_dir / "sof-ipc4" / p_alias) + rmtree_if_exists(sof_vendor_dir / "sof-ipc4-lib" / p_alias) + +RIMAGE_BUILD_DIR = west_top / "build-rimage" +RIMAGE_SOURCE_DIR = west_top / "sof" / "tools" / "rimage" + + +def rimage_west_configuration(platform_dict, dest_dir): + """Configure rimage in a new file `dest_dir/westconfig.ini`, starting + from the workspace .west/config. + Returns a tuple: (west.configuration.Configuration, pathlib.Path to that new file). + """ + + # This complex and painful saving and copying can be dropped and + # greatly simplified once any of these alternatives gets finally + # implemented in `west config`: + # https://github.com/zephyrproject-rtos/west/issues/429 or 849, 867,.. + saved_local_var = os.environ.get('WEST_CONFIG_LOCAL') + workspace_west_config_path = os.environ.get('WEST_CONFIG_LOCAL', + str(west_top / ".west" / "config")) + platform_west_config_path = dest_dir / "westconfig.ini" + dest_dir.mkdir(parents=True, exist_ok=True) + shutil.copyfile(workspace_west_config_path, platform_west_config_path) + + # Create `platform_wconfig` object pointing at our copy + os.environ['WEST_CONFIG_LOCAL'] = str(platform_west_config_path) + platform_wconfig = west_config.Configuration() + if saved_local_var is None: + del os.environ['WEST_CONFIG_LOCAL'] + else: + os.environ['WEST_CONFIG_LOCAL'] = saved_local_var + + # By default, run rimage directly from the rimage build directory + if platform_wconfig.get("rimage.path") is None: + rimage_executable = shutil.which("rimage", path=RIMAGE_BUILD_DIR) + assert pathlib.Path(str(rimage_executable)).exists() + platform_wconfig.set("rimage.path", shlex.quote(rimage_executable), + west_config.ConfigFile.LOCAL) + + _ws_args = platform_wconfig.get("rimage.extra-args") + workspace_extra_args = [] if _ws_args is None else shlex.split(_ws_args) + + # Flatten default rimage options while giving precedence to the workspace = + # the user input. We could just append and leave duplicates but that would be + # at best confusing and at worst relying on undocumented rimage precedence. + extra_args = [] + for default_opt in rimage_options(platform_dict): + if not default_opt[0] in workspace_extra_args: + extra_args += default_opt + + extra_args += workspace_extra_args + + platform_wconfig.set("rimage.extra-args", shlex.join(extra_args)) + + return platform_wconfig, platform_west_config_path + + +def build_rimage(): + + old_rimage_loc = SOF_TOP / "rimage" + # Don't warn on empty directories + if ( old_rimage_loc / "CMakeLists.txt" ).exists(): + warnings.warn(f"""{old_rimage_loc} is now ignored, + new location is {RIMAGE_SOURCE_DIR}""" + ) + rimage_dir_name = RIMAGE_BUILD_DIR.name + # CMake build rimage module + if not (RIMAGE_BUILD_DIR / "CMakeCache.txt").is_file(): + execute_command(["cmake", "-B", rimage_dir_name, "-G", "Ninja", + "-S", str(RIMAGE_SOURCE_DIR)], + cwd=west_top) + rimage_build_cmd = ["cmake", "--build", rimage_dir_name] + if args.jobs is not None: + rimage_build_cmd.append(f"-j{args.jobs}") + if args.verbose > 1: + rimage_build_cmd.append("-v") + execute_command(rimage_build_cmd, cwd=west_top) + + +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),... ] + + """ + global signing_key + opts = [] + + if args.verbose > 0: + opts.append(("-v",) * args.verbose) + + if args.key: + key_path = pathlib.Path(args.key) + assert key_path.exists(), f"{key_path} not found" + signing_key = key_path.resolve() + elif "RIMAGE_KEY" in platform_dict: + signing_key = platform_dict["RIMAGE_KEY"] + + if signing_key is not None: + 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")) + + return opts + + +STAGING_DIR = None +def build_platforms(): + global west_top, SOF_TOP + print(f"SOF_TOP={SOF_TOP}") + print(f"west_top={west_top}") + + global STAGING_DIR + STAGING_DIR = pathlib.Path(west_top, "build-sof-staging") + # Don't leave the install of an old build behind + if args.pristine: + rmtree_if_exists(STAGING_DIR) + else: + # This is important in (at least) two use cases: + # - when switching `--use-platform-subdir` on/off or changing key subdir, + # - when the build starts failing after a code change. + # Do not delete platforms that were not requested so this script can be + # invoked once per platform. + for platform in args.platforms: + clean_staging(platform) + rmtree_if_exists(STAGING_DIR / "tools") + + + # smex does not use 'install -D' + sof_output_dir = pathlib.Path(STAGING_DIR, "sof") + sof_output_dir.mkdir(parents=True, exist_ok=True) + + platform_build_dir_name = None + for platform in args.platforms: + platf_build_environ = os.environ.copy() + + if args.deployable_build: + vendor_output_dir = pathlib.Path(sof_output_dir, platform_configs[platform].vendor) + if platform_configs[platform].ipc4: + sof_platform_output_dir = pathlib.Path(vendor_output_dir, "sof-ipc4") + else: + sof_platform_output_dir = pathlib.Path(vendor_output_dir, "sof") + + sof_platform_output_dir.mkdir(parents=True, exist_ok=True) + else: + if args.use_platform_subdir: + sof_platform_output_dir = pathlib.Path(sof_output_dir, platform) + sof_platform_output_dir.mkdir(parents=True, exist_ok=True) + else: + sof_platform_output_dir = sof_output_dir + + # For now convert the new dataclass to what it used to be + _dict = dataclasses.asdict(platform_configs[platform]) + platform_dict = { k:v for (k,v) in _dict.items() if _dict[k] is not None } + + if args.zephyrsdk: + print("Using Zephyr SDK for building") + xtensa_tools_root_dir = None + else: + print("Using Xtensa tools for building") + xtensa_tools_root_dir = os.getenv("XTENSA_TOOLS_ROOT") + # when XTENSA_TOOLS_ROOT environmental variable is set, + # use user installed Xtensa tools not Zephyr SDK + if "XTENSA_TOOLS_VERSION" in platform_dict and xtensa_tools_root_dir: + xtensa_tools_root_dir = pathlib.Path(xtensa_tools_root_dir) + if not xtensa_tools_root_dir.is_dir(): + raise RuntimeError(f"Platform {platform} uses Xtensa toolchain." + f"\nVariable XTENSA_TOOLS_ROOT={xtensa_tools_root_dir} points " + "to a path that does not exist or is not a directory") + + # Set environment variables expected by + # zephyr/cmake/toolchain/x*/*.cmake. Note CMake cannot set (evil) + # build-time environment variables at configure time: + # https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-get-or-set-environment-variables + + # Top-level "switch". When undefined, the Zephyr build system + # automatically searches for the Zephyr SDK and ignores all the + # following variables. + platf_build_environ["ZEPHYR_TOOLCHAIN_VARIANT"] = platf_build_environ.get("ZEPHYR_TOOLCHAIN_VARIANT", + platform_dict["DEFAULT_TOOLCHAIN_VARIANT"]) + platf_build_environ["XTENSA_TOOLCHAIN_PATH"] = str( + xtensa_tools_root_dir / "install" / "tools" + ) + # Toolchain sub-directory + TOOLCHAIN_VER = platform_dict["XTENSA_TOOLS_VERSION"] + platf_build_environ["TOOLCHAIN_VER"] = TOOLCHAIN_VER + + # This XTENSA_SYSTEM variable was copied as is from XTOS + # scripts/xtensa-build-all.sh but it is not required by (recent?) + # toolchains when installed exactly as described in the --help (= a + # single --xtensa-core installed per --xtensa-system registry and maybe + # other constraints). Let's keep exporting it in case some build + # systems have their toolchains installed differently which might + # require it. Note: "not needed" is different from "ignored"! The + # compiler fails when the value is incorrect. + builds_toolchainver = xtensa_tools_root_dir / "install" / "builds" / TOOLCHAIN_VER + XTENSA_SYSTEM = str(builds_toolchainver / platform_dict["XTENSA_CORE"] / "config") + platf_build_environ["XTENSA_SYSTEM"] = XTENSA_SYSTEM + + platform_build_dir_name = f"build-{platform}" + + PLAT_CONFIG = platform_dict["PLAT_CONFIG"] + + build_cmd = ["west"] + build_cmd += ["-v"] * args.verbose + if args.menuconfig: + build_cmd += ["build", "-t", "menuconfig", "--build-dir", platform_build_dir_name] + else: + build_cmd += ["build", "--build-dir", platform_build_dir_name] + source_dir = pathlib.Path(SOF_TOP, "app") + build_cmd += ["--board", PLAT_CONFIG, str(source_dir)] + if args.pristine: + build_cmd += ["-p", "always"] + + if args.jobs is not None: + build_cmd += [f"--build-opt=-j{args.jobs}"] + + build_cmd.append('--') + if args.cmake_args: + build_cmd += args.cmake_args + + extra_conf_files = [str(item.resolve(True)) for item in args.overlay] + # The '-d' option is a shortcut for '-o path_to_debug_overlay', we are good + # if both are provided, because it's no harm to merge the same overlay twice. + if args.debug: + extra_conf_files.append(str(pathlib.Path(SOF_TOP, "app", "debug_overlay.conf"))) + + # The xt-cland Cadence toolchain currently cannot link shared + # libraries for Xtensa. Therefore when it's used we switch to + # building relocatable ELF objects. + if platf_build_environ.get("ZEPHYR_TOOLCHAIN_VARIANT") == 'xt-clang': + extra_conf_files.append(str(pathlib.Path(SOF_TOP, "app", "llext_relocatable.conf"))) + + if extra_conf_files: + extra_conf_files = ";".join(extra_conf_files) + build_cmd.append(f"-DEXTRA_CONF_FILE={extra_conf_files}") + + 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 extra_conf_files: + warnings.warn("""CMake args slow down incremental builds. + Passing CMake parameters and -o conf files 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.""") + + platform_wcfg, wcfg_path = rimage_west_configuration( + platform_dict, + STAGING_DIR / "sof-info" / platform + ) + + # SOF marks ELF sections in the range [SOF_MODULE_DRAM_LINK_START, SOF_MODULE_DRAM_LINK_END] + # as "detached". On imx8m_cm7 that address range overlaps with the M7 ITCM, so rimage would + # incorrectly classify ITCM sections as detached. Pass -d to ignore detached classification + if platform == "imx8m_cm7": + existing = platform_wcfg.get("rimage.extra-args") or "" + platform_wcfg.set("rimage.extra-args", + shlex.join(shlex.split(existing) + ["-d"])) + + platf_build_environ['WEST_CONFIG_LOCAL'] = str(wcfg_path) + + # Make sure the build logs don't leave anything hidden + execute_command(['west', 'config', '-l'], cwd=west_top, + env=platf_build_environ, sof_log_env=True) + print() + + # Build + try: + 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): + sys.exit("Zephyr project not found. Please run this script with -u flag or `west update zephyr` manually.") + else: # unknown failure + raise cpe + + # no output to display if building menuconfig + if args.menuconfig: + return + + # reproducible-zephyr.ri is less useful now that show_installed_files() shows + # checksums too. However: - it's still useful when only the .ri file is + # available (no build logs for the other image), - it makes sure sof_ri_info.py + # itself does not bitrot, - it can catch rimage issues, see for instance rimage + # fix 4fb9fe00575b + if platform not in RI_INFO_UNSUPPORTED: + reproducible_checksum(platform, west_top / platform_build_dir_name / "zephyr" / "zephyr.ri") + + install_platform(platform, sof_platform_output_dir, platf_build_environ, platform_wcfg) + + src_dest_list = [] + tools_output_dir = pathlib.Path(STAGING_DIR, "tools") + + src_dest_list += [(pathlib.Path(SOF_TOP) / + "tools" / "mtrace"/ "mtrace-reader.py", + tools_output_dir / "mtrace-reader.py")] + + # Append future files to `src_dest_list` here (but prefer + # copying entire directories; more flexible) + + for _src, _dst in src_dest_list: + os.makedirs(os.path.dirname(_dst), exist_ok=True) + # looses file owner and group - file is commonly accessible + shutil.copy2(str(_src), str(_dst)) + + # cavstool and friends + shutil.copytree(pathlib.Path(west_top) / + "zephyr" / "soc" / "intel" / "intel_adsp" / "tools", + tools_output_dir, + symlinks=True, ignore_dangling_symlinks=True, dirs_exist_ok=True) + + +def install_lib(platform, sof_output_dir, abs_build_dir, platform_wconfig): + """[summary] Sign loadable llext modules, if any, copy them to the + deployment tree and create UUID links for the kernel to find and load + them.""" + + global signing_key + + libs = dict() + lib_uuids = dict() + rimage_cmd = shlex.split(platform_wconfig.get('rimage.path'))[0] + _ws_args = platform_wconfig.get("rimage.extra-args") + + sof_lib_dir = sof_output_dir / '..' / 'sof-ipc4-lib' / platform + + if args.key_type_subdir != "none": + sof_lib_dir = sof_lib_dir / args.key_type_subdir + + sof_lib_dir.mkdir(parents=True, exist_ok=True) + + dirlist = [d for d in os.listdir(str(abs_build_dir)) if os.path.isdir(abs_build_dir / d)] + # Find all auxiliary modules, they're called "aux1_", "aux2_", etc., + # where lower numbers mean fewer dependent levels, so we need to sort + # them in reversed order to have all dependencies satisfied + pattern_aux = re.compile(r'^aux\d_.+_llext$') + aux = sorted([d for d in dirlist if pattern_aux.match(d)], reverse=True) + llext_dirs = [d for d in dirlist if d.endswith('_llext') and d not in aux] + final_list = aux + llext_dirs + + for entry in final_list: + entry_path = abs_build_dir / entry + + uuids = entry_path / 'llext.uuid' + if not os.path.exists(uuids): + print(f"Directory {entry} has no llext.uuid file. Skipping.") + continue + + # replace '_llext' with '.llext', e.g. + # eq_iir_llext/eq_iir.llext + llext_base = entry[:-6] + llext_file = llext_base + '.llext' + lib_name = '' + + lib_fname = entry_path / 'lib_name.txt' + if os.path.exists(lib_fname): + with open(lib_fname, 'r') as libs_f: + lib_name = libs_f.read() + if lib_name not in libs.keys(): + libs[lib_name] = [] + libs[lib_name].append(str(entry_path / llext_file)) + else: + dst = sof_lib_dir / llext_file + + rimage_cfg = entry_path / 'rimage_config.toml' + llext_input = entry_path / (llext_base + '.llext') + llext_output = entry_path / (llext_file + '.ri') + + # See why the shlex() parsing step is required at + # https://docs.zephyrproject.org/latest/develop/west/sign.html#rimage + # and in Zephyr commit 030b740bd1ec + sign_cmd = [rimage_cmd, "-o", str(llext_output), + "-e", "-c", str(rimage_cfg), + "-k", str(signing_key), "-l", "-r"] + if _ws_args is not None: + sign_cmd.extend(shlex.split(_ws_args)) + sign_cmd.append(str(llext_input)) + execute_command(sign_cmd, cwd=west_top) + + # An intuitive way to make this multiline would be + # with (open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext, + # open(llext_output.with_suffix('.llext.xman'), 'rb') as fman): + # but a Python version, used on Windows errored out on this. + # Thus we're left with a choice between a 150-character + # long line and an illogical split like this + with open(dst, 'wb') as fdst, open(llext_output, 'rb') as fllext, open( + llext_output.with_suffix('.ri.xman'), 'rb') as fman: + # Concatenate the manifest and the llext + shutil.copyfileobj(fman, fdst) + shutil.copyfileobj(fllext, fdst) + + # Create symbolic links for all UUIDs + with open(uuids, 'r') as uuids_f: + for uuid in uuids_f: + if os.path.exists(lib_fname): + if lib_name not in lib_uuids.keys(): + lib_uuids[lib_name] = [] + lib_uuids[lib_name].append(uuid.strip()) + else: + linkname = uuid.strip() + '.bin' + symlink_or_copy(sof_lib_dir, llext_file, + sof_lib_dir, linkname) + + lib_install_dir = sof_output_dir / platform + if args.key_type_subdir != "none": + lib_install_dir = lib_install_dir / args.key_type_subdir + + for key in libs.keys(): + lib_path = abs_build_dir / ''.join(['lib', key, '.ri']) + sign_cmd = [rimage_cmd, "-o", str(lib_path), "-e", + "-c", str(abs_build_dir / 'misc' / 'generated' / 'rimage_config_full.toml'), + "-k", str(signing_key), "-l", "-r"] + if _ws_args is not None: + sign_cmd.extend(shlex.split(_ws_args)) + sign_cmd.extend(libs[key]) + execute_command(sign_cmd, cwd=west_top) + lib_name = ''.join(['sof-', platform, '-', key, '.ri']) + dst = lib_install_dir / lib_name + with open(dst, 'wb') as fdst, open(lib_path, 'rb') as fllext, open( + lib_path.with_suffix('.ri.xman'), 'rb') as fman: + # Concatenate the manifest and the llext + shutil.copyfileobj(fman, fdst) + shutil.copyfileobj(fllext, fdst) + + for p_alias in platform_configs[platform].aliases: + lib_dir = sof_output_dir / p_alias + + if args.key_type_subdir != "none": + lib_dir = lib_dir / args.key_type_subdir + lib_dir.mkdir(parents=True, exist_ok=True) + alias_libname = ''.join(['sof-', p_alias, '-', key, '.ri']) + symlink_or_copy(lib_install_dir, lib_name, + lib_dir, alias_libname) + +def install_platform(platform, sof_output_dir, platf_build_environ, platform_wconfig): + + # Keep in sync with caller + platform_build_dir_name = f"build-{platform}" + + # Install to STAGING_DIR + abs_build_dir = pathlib.Path(west_top) / platform_build_dir_name / "zephyr" + + if args.fw_naming == "AVS": + # Disguise ourselves for local testing purposes + output_fwname = "dsp_basefw.bin" + else: + # Regular name (deployable build also uses SOF naming convention) + output_fwname = "".join(["sof-", platform, ".ri"]) + + if args.deployable_build and platform_configs[platform].ipc4: + install_key_dir = pathlib.Path(sof_output_dir, platform) + else: + install_key_dir = sof_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, dont install qemu. + if platform not in ("qemu_xtensa", "qemu_xtensa_mmu"): + shutil.copy2(abs_build_dir / "zephyr.ri", install_key_dir / output_fwname) + + if args.deployable_build and platform_configs[platform].ipc4: + # IPC4 deployable builds are using separate directories per platforms + # create the structure and symlinks for the alias platforms + for p_alias in platform_configs[platform].aliases: + alias_fwname = "".join(["sof-", p_alias, ".ri"]) + + alias_key_dir = pathlib.Path(sof_output_dir, p_alias) + if args.key_type_subdir != "none": + alias_key_dir = alias_key_dir / args.key_type_subdir + + os.makedirs(alias_key_dir, exist_ok=True) + symlink_or_copy(install_key_dir, output_fwname, alias_key_dir, alias_fwname) + else: + # non deployable builds and IPC3 deployable builds are using the same symlink scheme + # The production key is usually different + if args.key_type_subdir != "none" and args.fw_naming != "AVS": + for p_alias in platform_configs[platform].aliases: + symlink_or_copy(install_key_dir, output_fwname, install_key_dir, f"sof-{p_alias}.ri") + + if args.deployable_build and platform_configs[platform].ipc4: + install_lib(platform, sof_output_dir, abs_build_dir, platform_wconfig) + + + # sof-info/ directory + + @dataclasses.dataclass + class InstFile: + 'How to install one file' + name: pathlib.Path + renameTo: pathlib.Path = None + # TODO: upgrade this to 3 states: optional/warning/error + optional: bool = False + gzip: bool = True + txt: bool = False + + installed_files = [ + # Fail if one of these is missing + InstFile(".config", "config", txt=True), + InstFile("include/generated/zephyr/autoconf.h", "generated_autoconf.h", txt=True), + InstFile("include/generated/zephyr/version.h", "zephyr_version.h", + gzip=False, txt=True), + InstFile("include/generated/sof_versions.h", "sof_versions.h", + gzip=False, txt=True), + InstFile(BIN_NAME + ".elf"), + InstFile(BIN_NAME + ".lst", txt=True, optional=True), + InstFile(BIN_NAME + ".map", txt=True), + + # Optional because it's not generated for all platforms. + InstFile(f"misc/generated/rimage_config.toml", "generated_rimage_config.toml", + optional=True, gzip=False, txt=True), + + # CONFIG_BUILD_OUTPUT_STRIPPED + # Renaming ELF files highlights the workaround below that strips the .comment section + InstFile(BIN_NAME + ".strip", renameTo=f"stripped-{BIN_NAME}.elf"), + + # Not every platform has intermediate rimage modules + InstFile("main-stripped.mod", renameTo="stripped-main.elf", optional=True), + InstFile("boot.mod", optional=True), + InstFile("main.mod", optional=True), + ] + + # We cannot import at the start because zephyr may not be there yet + sys.path.insert(1, os.path.join(sys.path[0], + '..', '..', 'zephyr', 'scripts', 'west_commands')) + import zcmake + + cmake_cache = zcmake.CMakeCache.from_build_dir(abs_build_dir.parent) + objcopy = cmake_cache.get("CMAKE_OBJCOPY") + + sof_info = pathlib.Path(STAGING_DIR) / "sof-info" / platform + sof_info.mkdir(parents=True, exist_ok=True) + gzip_threads = concurrent.ThreadPoolExecutor() + gzip_futures = [] + for f in installed_files: + if not pathlib.Path(abs_build_dir / f.name).is_file() and f.optional: + continue + dstname = f.renameTo or f.name + + src = abs_build_dir / f.name + dst = sof_info / dstname + + # Some Xtensa compilers (ab?)use the .ident / .comment + # section and append the typically absolute and not + # reproducible /path/to/the.c file after the usual + # compiler ID. + # https://sourceware.org/binutils/docs/as/Ident.html + # + # --strip-all does not remove the .comment section. + # Remove it like some gcc test scripts do: + # https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c7046906c3ae + if "strip" in str(dstname): + execute_command( + [str(x) for x in [objcopy, "--remove-section", ".comment", src, dst]], + # Some xtensa installs don't have a + # XtensaTools/config/default-params symbolic link + env=platf_build_environ, + ) + elif f.txt: + dos2unix(src, dst) + else: + shutil.copy2(src, dst) + if f.gzip: + gzip_futures.append(gzip_threads.submit(gzip_compress, dst)) + for gzip_res in concurrent.as_completed(gzip_futures): + gzip_res.result() # throws exception if gzip unexpectedly failed + gzip_threads.shutdown() + +# Zephyr's CONFIG_KERNEL_BIN_NAME default value +BIN_NAME = 'zephyr' + +CHECKSUM_WANTED = [ + # Rimage now uses a cryptographic salt and produces a non-deterministic + # signature; but the ability to match some release with the corresponding + # build log is still useful. + '*.ri', '*.llext', + 'dsp_basefw.bin', + + '*version*.h', + '*autoconf.h', # .config has absolute paths in comments, this has not. + '*.toml', # rimage + '*.strip', '*stripped*', # stripped ELF files are reproducible + 'boot.mod', # no debug section -> no need to strip this ELF + BIN_NAME + '.lst', # objdump --disassemble + '*.ldc', +] + +# Prefer CRLF->LF because unlike LF->CRLF it's (normally) idempotent. +def dos2unix(in_name, out_name): + with open(in_name, "rb") as inf: + # must read all at once otherwise could fall between CR and LF + content = inf.read() + assert content + with open(out_name, "wb") as outf: + outf.write(content.replace(b"\r\n", b"\n")) + +def gzip_compress(fname, gzdst=None): + gzdst = gzdst or pathlib.Path(f"{fname}.gz") + with open(fname, 'rb') as inputf: + # mtime=0 for recursive diff convenience + with gzip.GzipFile(gzdst, 'wb', mtime=0) as gzf: + shutil.copyfileobj(inputf, gzf) + os.remove(fname) + + +# As of October 2022, sof_ri_info.py expects .ri files to include a CSE manifest / signature. +# Don't run sof_ri_info and ignore silently .ri files that don't have one. +RI_INFO_UNSUPPORTED = [] + +RI_INFO_UNSUPPORTED += ['imx8', 'imx8x', 'imx8m', 'imx8m_cm7', 'imx8ulp', 'imx95'] +RI_INFO_UNSUPPORTED += ['rn', 'acp_6_0', 'acp_7_0'] +RI_INFO_UNSUPPORTED += ['mt8186', 'mt8188', 'mt8195', 'mt8196', 'mt8365'] +RI_INFO_UNSUPPORTED += ['qemu_xtensa', 'qemu_xtensa_mmu'] + + +# For temporary workarounds. Unlike _UNSUPPORTED above, the platforms below will print a warning. +RI_INFO_FIXME = [ ] + +def reproducible_checksum(platform, ri_file): + + if platform in RI_INFO_FIXME: + print(f"FIXME: sof_ri_info does not support '{platform}'") + return + + parsed_ri = sof_ri_info.parse_fw_bin(ri_file, False, False) + repro_output = ri_file.parent / ("reproducible-" + ri_file.name) + chk256 = sof_ri_info.EraseVariables(ri_file, parsed_ri, west_top / repro_output) + print('sha256sum {0}\n{1} {0}'.format(repro_output, chk256)) + +def create_tarball(): + # vendor directories (typically under /lib/firmware) to include + # in the tarball + vendor_dirs = [ 'intel'] + + build_top = west_top / 'build-sof-staging' / 'sof' + + tarball_name = 'sof.tgz' + + prev_cwd = os.getcwd() + os.chdir(build_top) + + tarball_path = build_top / tarball_name + with tarfile.open(tarball_path, 'w:gz') as tarball: + for vendor_dir in vendor_dirs: + vendor_dir_path = build_top / vendor_dir + if not vendor_dir_path.exists(): + continue + tarball.add(vendor_dir, recursive=True) + print(f"Tarball %s created" % tarball_path) + + os.chdir(prev_cwd) + +def main(): + parse_args() + if args.version: + print(VERSION) + sys.exit(0) + check_west_installation() + if len(args.platforms) == 0: + print("No platform build requested") + else: + print("Building platforms: {}".format(" ".join(args.platforms))) + + west_init_if_needed() + + if args.update: + # Initialize zephyr project with west + west_update() + create_zephyr_sof_symlink() + + build_rimage() + build_platforms() + if args.menuconfig: + return + if not args.no_tarball: + create_tarball() + show_installed_files() + +if __name__ == "__main__": + main() diff --git a/smex/CMakeLists.txt b/smex/CMakeLists.txt new file mode 100644 index 000000000000..01d9bf8778b3 --- /dev/null +++ b/smex/CMakeLists.txt @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.13) + +project(SOF_SMEX C) + +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "No CMAKE_BUILD_TYPE, defaulting to Debug") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE) +endif() + +set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}/..") + +add_executable(smex + elf.c + ldc.c + smex.c +) + +# In addition to the usual flags from CMAKE_BUILD_TYPE +target_compile_options(smex PRIVATE + -Wall -Werror -Wmissing-prototypes -Wimplicit-fallthrough +) + +target_link_options(smex PRIVATE + -Wall -Werror +) + +target_include_directories(smex PRIVATE + "${SOF_ROOT_SOURCE_DIRECTORY}/src/include" + "${SOF_ROOT_SOURCE_DIRECTORY}/tools/rimage/src/include" +) + +# TODO: smex should not need RTOS headers: FIX. +target_include_directories(smex PRIVATE + "${SOF_ROOT_SOURCE_DIRECTORY}/xtos/include" +) diff --git a/smex/README.md b/smex/README.md new file mode 100644 index 000000000000..f8bf7f33c561 --- /dev/null +++ b/smex/README.md @@ -0,0 +1,5 @@ +# SOF Metadata Extractor + +SMEX (*SOF Metadata EXtractor*) is a tool used to extract needed +information from SOF source code and output files and then put then save +them in convenient form like logs dictionary file (*ldc*). diff --git a/smex/elf.c b/smex/elf.c new file mode 100644 index 000000000000..eb0994530c6b --- /dev/null +++ b/smex/elf.c @@ -0,0 +1,564 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "elf_defs.h" +#include "elf.h" + +static int elf_read_sections(struct elf_module *module, bool verbose) +{ + Elf32_Ehdr *hdr = &module->hdr; + Elf32_Shdr *section; + size_t count; + int i, ret; + uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); + + /* read in section header */ + ret = fseek(module->fd, hdr->shoff, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "error: can't seek to %s section header %d\n", + module->elf_file, ret); + return -errno; + } + + /* allocate space for each section header */ + section = calloc(sizeof(Elf32_Shdr), hdr->shnum); + if (!section) + return -ENOMEM; + module->section = section; + + /* read in sections */ + count = fread(section, sizeof(Elf32_Shdr), hdr->shnum, module->fd); + if (count != hdr->shnum) { + fprintf(stderr, "error: failed to read %s section header %d\n", + module->elf_file, -errno); + return count > 0 ? -ENODATA : -errno; + } + + /* read in strings */ + module->strings = calloc(1, section[hdr->shstrndx].size); + if (!module->strings) { + fprintf(stderr, "error: failed %s to read ELF strings for %d\n", + module->elf_file, -errno); + return -errno; + } + + ret = fseek(module->fd, section[hdr->shstrndx].off, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "error: can't seek to %s stringss %d\n", + module->elf_file, ret); + return -errno; + } + + count = fread(module->strings, 1, section[hdr->shstrndx].size, + module->fd); + if (count != section[hdr->shstrndx].size) { + fprintf(stderr, "error: failed to read %s strings %d\n", + module->elf_file, -errno); + return count > 0 ? -ENODATA : -errno; + } + + module->bss_index = elf_find_section(module, ".bss"); + if (module->bss_index < 0) { + fprintf(stderr, "Can't find .bss section in %s", + module->elf_file); + return -EINVAL; + } + + /* parse each section */ + for (i = 0; i < hdr->shnum; i++) { + /* only write valid sections */ + if (!(section[i].flags & valid)) + continue; + + switch (section[i].type) { + case SHT_NOBITS: + /* bss */ + module->bss_size += section[i].size; + module->num_bss++; + break; + case SHT_PROGBITS: + /* text or data */ + module->fw_size += section[i].size; + + if (section[i].flags & SHF_EXECINSTR) + module->text_size += section[i].size; + else + module->data_size += section[i].size; + break; + default: + continue; + } + + module->num_sections++; + + if (!verbose) + continue; + + fprintf(stdout, " %s section-%d: \tname\t %s\n", + module->elf_file, i, module->strings + section[i].name); + fprintf(stdout, " %s section-%d: \ttype\t 0x%8.8x\n", + module->elf_file, i, section[i].type); + fprintf(stdout, " %s section-%d: \tflags\t 0x%8.8x\n", + module->elf_file, i, section[i].flags); + fprintf(stdout, " %s section-%d: \taddr\t 0x%8.8x\n", + module->elf_file, i, section[i].vaddr); + fprintf(stdout, " %s section-%d: \toffset\t 0x%8.8x\n", + module->elf_file, i, section[i].off); + fprintf(stdout, " %s section-%d: \tsize\t 0x%8.8x\n", + module->elf_file, i, section[i].size); + fprintf(stdout, " %s section-%d: \tlink\t 0x%8.8x\n", + module->elf_file, i, section[i].link); + fprintf(stdout, " %s section-%d: \tinfo\t 0x%8.8x\n\n", + module->elf_file, i, section[i].info); + } + + return 0; +} + +static int elf_read_programs(struct elf_module *module, bool verbose) +{ + Elf32_Ehdr *hdr = &module->hdr; + Elf32_Phdr *prg; + size_t count; + int i, ret; + + /* read in program header */ + ret = fseek(module->fd, hdr->phoff, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "error: cant seek to %s program header %d\n", + module->elf_file, ret); + return -errno; + } + + /* allocate space for programs */ + prg = calloc(sizeof(Elf32_Phdr), hdr->phnum); + if (!prg) + return -ENOMEM; + module->prg = prg; + + /* read in programs */ + count = fread(prg, sizeof(Elf32_Phdr), hdr->phnum, module->fd); + if (count != hdr->phnum) { + fprintf(stderr, "error: failed to read %s program header %d\n", + module->elf_file, -errno); + return count > 0 ? -ENODATA : -errno; + } + + /* check each program */ + for (i = 0; i < hdr->phnum; i++) { + if (prg[i].filesz == 0) + continue; + + if (!verbose) + continue; + + fprintf(stdout, "%s program-%d: \ttype\t 0x%8.8x\n", + module->elf_file, i, prg[i].type); + fprintf(stdout, "%s program-%d: \toffset\t 0x%8.8x\n", + module->elf_file, i, prg[i].off); + fprintf(stdout, "%s program-%d: \tvaddr\t 0x%8.8x\n", + module->elf_file, i, prg[i].vaddr); + fprintf(stdout, "%s program-%d: \tpaddr\t 0x%8.8x\n", + module->elf_file, i, prg[i].paddr); + fprintf(stdout, "%s program-%d: \tfsize\t 0x%8.8x\n", + module->elf_file, i, prg[i].filesz); + fprintf(stdout, "%s program-%d: \tmsize\t 0x%8.8x\n", + module->elf_file, i, prg[i].memsz); + fprintf(stdout, "%s program-%d: \tflags\t 0x%8.8x\n\n", + module->elf_file, i, prg[i].flags); + } + + return 0; +} + +static int elf_read_hdr(struct elf_module *module, bool verbose) +{ + Elf32_Ehdr *hdr = &module->hdr; + size_t count; + + /* read in elf header */ + count = fread(hdr, sizeof(*hdr), 1, module->fd); + if (count != 1) { + fprintf(stderr, "error: failed to read %s elf header %d\n", + module->elf_file, -errno); + return count > 0 ? -ENODATA : -errno; + } + + if (!verbose) + return 0; + + fprintf(stdout, "%s elf: \tentry point\t 0x%8.8x\n", + module->elf_file, hdr->entry); + fprintf(stdout, "%s elf: \tprogram offset\t 0x%8.8x\n", + module->elf_file, hdr->phoff); + fprintf(stdout, "%s elf: \tsection offset\t 0x%8.8x\n", + module->elf_file, hdr->shoff); + fprintf(stdout, "%s elf: \tprogram size\t 0x%8.8x\n", + module->elf_file, hdr->phentsize); + fprintf(stdout, "%s elf: \tprogram count\t 0x%8.8x\n", + module->elf_file, hdr->phnum); + fprintf(stdout, "%s elf: \tsection size\t 0x%8.8x\n", + module->elf_file, hdr->shentsize); + fprintf(stdout, "%s elf: \tsection count\t 0x%8.8x\n", + module->elf_file, hdr->shnum); + fprintf(stdout, "%s elf: \tstring index\t 0x%8.8x\n\n", + module->elf_file, hdr->shstrndx); + + return 0; +} + +static void elf_module_size(struct elf_module *module, Elf32_Shdr *section, + int index) +{ + switch (section->type) { + case SHT_PROGBITS: + /* text or data */ + if (section->flags & SHF_EXECINSTR) { + /* text */ + if (module->text_start > section->vaddr) + module->text_start = section->vaddr; + if (module->text_end < section->vaddr + section->size) + module->text_end = section->vaddr + + section->size; + + fprintf(stdout, "\tTEXT\t"); + } else { + /* initialized data, also calc the writable sections */ + if (module->data_start > section->vaddr) + module->data_start = section->vaddr; + if (module->data_end < section->vaddr + section->size) + module->data_end = section->vaddr + + section->size; + + fprintf(stdout, "\tDATA\t"); + } + break; + case SHT_NOBITS: + /* bss */ + if (index == module->bss_index) { + /* updated the .bss segment */ + module->bss_start = section->vaddr; + module->bss_end = section->vaddr + section->size; + fprintf(stdout, "\tBSS\t"); + } else { + fprintf(stdout, "\tHEAP\t"); + } + break; + case SHT_NOTE: + fprintf(stdout, "\tNOTE\t"); + break; + default: + break; + } +} + +static void elf_module_limits(struct elf_module *module) +{ + Elf32_Shdr *section; + int i; + + module->text_start = 0xffffffff; + module->data_start = 0xffffffff; + module->bss_start = 0; + module->text_end = 0; + module->data_end = 0; + module->bss_end = 0; + + fprintf(stdout, " Found %d sections, listing valid sections......\n", + module->hdr.shnum); + + fprintf(stdout, "\tNo\tStart\t\tEnd\t\tSize\tType\tName\n"); + + /* iterate all sections and get size of segments */ + for (i = 0; i < module->hdr.shnum; i++) { + section = &module->section[i]; + + /* module bss can sometimes be missed */ + if (i != module->bss_index) { + if (section->vaddr == 0) + continue; + + if (section->size == 0) + continue; + } + + fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%x", i, + section->vaddr, section->vaddr + section->size, + section->size); + + /* text or data section */ + elf_module_size(module, section, i); + + /* section name */ + fprintf(stdout, "%s\n", module->strings + section->name); + } + + fprintf(stdout, "\n"); +} + +/* make sure no section overlap */ +static int elf_validate_section(struct elf_module *module, + Elf32_Shdr *section, int index) +{ + Elf32_Shdr *s; + uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); + int i; + + /* for each section */ + for (i = 0; i < module->hdr.shnum; i++) { + s = &module->section[i]; + + if (s == section) + continue; + + /* only check valid sections */ + if (!(s->flags & valid)) + continue; + + if (s->size == 0) + continue; + + /* is section start non overlapping ? */ + if (section->vaddr >= s->vaddr && + section->vaddr < s->vaddr + s->size) { + goto err; + } + + /* is section end non overlapping ? */ + if (section->vaddr + section->size > s->vaddr && + section->vaddr + section->size <= s->vaddr + s->size) { + goto err; + } + } + + return 0; + +err: + fprintf(stderr, "error: section overlap between %s:%d and %s:%d\n", + module->elf_file, index, module->elf_file, i); + fprintf(stderr, " [0x%x : 0x%x] overlaps with [0x%x :0x%x]\n", + section->vaddr, section->vaddr + section->size, + s->vaddr, s->vaddr + s->size); + return -EINVAL; +} + +/* make sure no section overlaps from any modules */ +static int elf_validate_module(struct elf_module *module) +{ + Elf32_Shdr *section; + uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); + int i, ret; + + /* for each section */ + for (i = 0; i < module->hdr.shnum; i++) { + section = &module->section[i]; + + /* only check valid sections */ + if (!(section->flags & valid)) + continue; + + if (section->size == 0) + continue; + + /* is section non overlapping ? */ + ret = elf_validate_section(module, section, i); + if (ret < 0) + return ret; + } + + return 0; +} + +int elf_find_section(const struct elf_module *module, const char *name) +{ + const Elf32_Ehdr *hdr = &module->hdr; + const Elf32_Shdr *section, *s; + char *buffer; + size_t count; + int ret, i; + + if (module->section == NULL) { + fprintf(stderr, "error: NULL module section\n"); + return -EINVAL; + } + + section = &module->section[hdr->shstrndx]; + + /* alloc data data */ + buffer = calloc(1, section->size); + if (!buffer) + return -ENOMEM; + + /* read in section string data */ + ret = fseek(module->fd, section->off, SEEK_SET); + if (ret < 0) { + fprintf(stderr, "error: cant seek to string section %d\n", ret); + ret = -errno; + goto out; + } + + count = fread(buffer, 1, section->size, module->fd); + if (count != section->size) { + fprintf(stderr, "error: can't read string section %d\n", + -errno); + ret = count > 0 ? -ENODATA : -errno; + goto out; + } + buffer[section->size - 1] = '\0'; + + /* find section with name */ + for (i = 0; i < hdr->shnum; i++) { + s = &module->section[i]; + if (s->name >= section->size) { + fprintf(stderr, "error: invalid section name string index %d\n", s->name); + ret = -EINVAL; + goto out; + } + + if (!strcmp(name, buffer + s->name)) { + ret = i; + goto out; + } + } + + fprintf(stderr, "warning: can't find section %s in module %s\n", name, + module->elf_file); + ret = -EINVAL; + +out: + free(buffer); + return ret; +} + +int elf_read_section(const struct elf_module *module, const char *section_name, + const Elf32_Shdr **dst_section, void **dst_buff) +{ + const Elf32_Shdr *section; + int section_index; + int ret; + + section_index = elf_find_section(module, section_name); + if (section_index < 0) { + fprintf(stderr, "error: section %s can't be found\n", + section_name); + return -EINVAL; + } + + section = &module->section[section_index]; + if (dst_section) + *dst_section = section; + + /* alloc buffer for section content */ + *dst_buff = calloc(1, section->size); + if (!*dst_buff) + return -ENOMEM; + + /* fill buffer with section content */ + ret = fseek(module->fd, section->off, SEEK_SET); + if (ret) { + fprintf(stderr, "error: can't seek to %s section %d\n", section_name, -errno); + ret = -errno; + goto error; + } + + ret = fread(*dst_buff, 1, section->size, module->fd); + if (ret != section->size) { + fprintf(stderr, "error: can't read %s section %d\n", section_name, -errno); + ret = ret < 0 ? -errno : -ENODATA; + goto error; + } + + return section->size; + +error: + free(*dst_buff); + return ret; +} + +int elf_read_module(struct elf_module *module, const char *name, bool verbose) +{ + int ret = 0; + + /* open the elf input file */ + module->fd = fopen(name, "rb"); + if (!module->fd) { + fprintf(stderr, "error: unable to open %s for reading: %s\n", + name, strerror(errno)); + return -EINVAL; + } + module->elf_file = name; + + /* get file size */ + ret = fseek(module->fd, 0, SEEK_END); + if (ret < 0) { + ret = -errno; + goto err; + } + module->file_size = ftell(module->fd); + ret = fseek(module->fd, 0, SEEK_SET); + if (ret < 0) { + ret = -errno; + goto err; + } + + /* read in elf header */ + ret = elf_read_hdr(module, verbose); + if (ret < 0) + goto err; + + /* read in programs */ + ret = elf_read_programs(module, verbose); + if (ret < 0) { + fprintf(stderr, "error: failed to read program sections %d\n", + ret); + goto err; + } + + /* read sections */ + ret = elf_read_sections(module, verbose); + if (ret < 0) { + fprintf(stderr, "error: failed to read base sections %d\n", + ret); + goto err; + } + + elf_module_limits(module); + elf_find_section(module, ""); + + fprintf(stdout, " module: input size %d (0x%x) bytes %d sections\n", + module->fw_size, module->fw_size, module->num_sections); + fprintf(stdout, " module: text %d (0x%x) bytes\n" + " data %d (0x%x) bytes\n" + " bss %d (0x%x) bytes\n\n", + module->text_size, module->text_size, + module->data_size, module->data_size, + module->bss_size, module->bss_size); + + elf_validate_module(module); + + return 0; + +err: + fclose(module->fd); + + return ret; +} + +void elf_free_module(struct elf_module *module) +{ + free(module->prg); + free(module->section); + free(module->strings); + if (module->fd) + fclose(module->fd); +} diff --git a/smex/elf.h b/smex/elf.h new file mode 100644 index 000000000000..ace85b815e0b --- /dev/null +++ b/smex/elf.h @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#ifndef __INCLUDE_ELF_H__ +#define __INCLUDE_ELF_H__ + +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include "elf_defs.h" + +/* + * ELF module data + */ +struct elf_module { + const char *elf_file; + FILE *fd; + + Elf32_Ehdr hdr; + Elf32_Shdr *section; + Elf32_Phdr *prg; + char *strings; + + uint32_t text_start; + uint32_t text_end; + uint32_t data_start; + uint32_t data_end; + uint32_t bss_start; + uint32_t bss_end; + uint32_t foffset; + + int num_sections; + int num_bss; + int fw_size; + int bss_index; + + /* sizes do not include any gaps */ + int bss_size; + int text_size; + int data_size; + + /* sizes do include gaps to nearest page */ + int bss_file_size; + int text_file_size; + int text_fixup_size; + int data_file_size; + + /* total file size */ + int file_size; + + /* executable header module */ + int exec_header; +}; + +int elf_read_module(struct elf_module *module, const char *name, bool verbose); +void elf_free_module(struct elf_module *module); +int elf_find_section(const struct elf_module *module, const char *name); +int elf_read_section(const struct elf_module *module, const char *section_name, + const Elf32_Shdr **dst_section, void **dst_buff); + +#endif /* __INCLUDE_ELF_H__ */ diff --git a/smex/elf_defs.h b/smex/elf_defs.h new file mode 100644 index 000000000000..1f42322a7281 --- /dev/null +++ b/smex/elf_defs.h @@ -0,0 +1,930 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. + * Copyright (c) 2001 David E. O'Brien + * Portions Copyright 2009 The Go Authors. All rights reserved. + */ + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +#ifndef __INCLUDE_ELF_DEFS_H__ +#define __INCLUDE_ELF_DEFS_H__ + +#include <stdbool.h> +#include <stdint.h> + +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; + +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; + +typedef struct { + uint32 n_namesz; /* Length of name. */ + uint32 n_descsz; /* Length of descriptor. */ + uint32 n_type; /* Type of this note. */ +} Elf_Note; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developer/gabi/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_GNU_VERDEF 0x6ffffffd +#define SHT_GNU_VERNEED 0x6ffffffe +#define SHT_GNU_VERSYM 0x6fffffff +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ +#define PT_GNU_STACK 0x6474e551 +#define PT_PAX_FLAGS 0x65041580 + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +/* String table offset of a needed shared library. */ +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +/* String table offset of shared object name. */ +#define DT_SONAME 14 +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +/* Indicates there may be relocations in non-writable segments. [sup] */ +#define DT_TEXTREL 22 +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +/* Address of the array of pointers to initialization functions */ +#define DT_INIT_ARRAY 25 +/* Address of the array of pointers to termination functions */ +#define DT_FINI_ARRAY 26 +/* Size in bytes of the array of initialization functions. */ +#define DT_INIT_ARRAYSZ 27 +/* Size in bytes of the array of terminationfunctions. */ +#define DT_FINI_ARRAYSZ 28 +/* String table offset of a null-terminated library search path string. */ +#define DT_RUNPATH 29 +#define DT_FLAGS 30 /* Object specific flag values. */ +/* Values greater than or equal to DT_ENCODING and less than + DT_LOOS follow the rules for the interpretation of the d_un + union as follows: even == 'd_ptr', even == 'd_val' or none */ +#define DT_ENCODING 32 +/* Address of the array of pointers to pre-initialization functions. */ +#define DT_PREINIT_ARRAY 32 +/* Size in bytes of the array of pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define DT_VERSYM 0x6ffffff0 + +/* Values for DT_FLAGS */ +/* Indicates that the object being loaded may make reference to + the $ORIGIN substitution string */ +#define DF_ORIGIN 0x0001 +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +/* Indicates there may be relocations in non-writable segments. */ +#define DF_TEXTREL 0x0004 +/* Indicates that the dynamic linker should process all + relocations for the object containing this entry before + transferring control to the program. */ +#define DF_BIND_NOW 0x0008 +/* Indicates that the shared object or executable contains code + using a static thread-local storage scheme. */ +#define DF_STATIC_TLS 0x0010 + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32 Elf32_Addr; +typedef uint16 Elf32_Half; +typedef uint32 Elf32_Off; +typedef int32 Elf32_Sword; +typedef uint32 Elf32_Word; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char ident[EI_NIDENT]; /* File identification. */ + Elf32_Half type; /* File type. */ + Elf32_Half machine; /* Machine architecture. */ + Elf32_Word version; /* ELF format version. */ + Elf32_Addr entry; /* Entry point. */ + Elf32_Off phoff; /* Program header file offset. */ + Elf32_Off shoff; /* Section header file offset. */ + Elf32_Word flags; /* Architecture-specific flags. */ + Elf32_Half ehsize; /* Size of ELF header in bytes. */ + Elf32_Half phentsize; /* Size of program header entry. */ + Elf32_Half phnum; /* Number of program header entries. */ + Elf32_Half shentsize; /* Size of section header entry. */ + Elf32_Half shnum; /* Number of section header entries. */ + Elf32_Half shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word name; /* Section name (index into the + section header string table). */ + Elf32_Word type; /* Section type. */ + Elf32_Word flags; /* Section flags. */ + Elf32_Addr vaddr; /* Address in memory image. */ + Elf32_Off off; /* Offset in file. */ + Elf32_Word size; /* Size in bytes. */ + Elf32_Word link; /* Index of a related section. */ + Elf32_Word info; /* Depends on section type. */ + Elf32_Word addralign; /* Alignment in bytes. */ + Elf32_Word entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word type; /* Entry type. */ + Elf32_Off off; /* File offset of contents. */ + Elf32_Addr vaddr; /* Virtual address in memory image. */ + Elf32_Addr paddr; /* Physical address (not used). */ + Elf32_Word filesz; /* Size of contents in file. */ + Elf32_Word memsz; /* Size of contents in memory. */ + Elf32_Word flags; /* Access permission flags. */ + Elf32_Word align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr off; /* Location to be relocated. */ + Elf32_Word info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr off; /* Location to be relocated. */ + Elf32_Word info; /* Relocation type and symbol index. */ + Elf32_Sword addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Relocation types. + */ + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + +#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ + +#define R_ALPHA_COUNT 28 + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_V4BX 40 +#define R_ARM_GOT_PREL 96 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_TLS_IE32 107 +#define R_ARM_TLS_LE32 108 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +#define R_ARM_COUNT 38 /* Count of defined relocation types. */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +#define R_386_COUNT 38 /* Count of defined relocation types. */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +#define R_PPC_COUNT 37 /* Count of defined relocation types. */ + +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + + /* Count of defined relocation types. */ +#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1) + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 + +/* + * Magic number for the elf trampoline, chosen wisely to be an immediate + * value. + */ +#define ARM_MAGIC_TRAMP_NUMBER 0x5c000003 + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word name; /* String table index of name. */ + Elf32_Addr value; /* Symbol value. */ + Elf32_Word size; /* Size of associated object. */ + unsigned char info; /* Type and binding information. */ + unsigned char other; /* Reserved (not used). */ + Elf32_Half shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64 Elf64_Addr; +typedef uint16 Elf64_Half; +typedef uint64 Elf64_Off; +typedef int32 Elf64_Sword; +typedef int64 Elf64_Sxword; +typedef uint32 Elf64_Word; +typedef uint64 Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +#ifdef __alpha__ +typedef Elf64_Off Elf64_Hashelt; +#else +typedef Elf64_Word Elf64_Hashelt; +#endif + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char ident[EI_NIDENT]; /* File identification. */ + Elf64_Half type; /* File type. */ + Elf64_Half machine; /* Machine architecture. */ + Elf64_Word version; /* ELF format version. */ + Elf64_Addr entry; /* Entry point. */ + Elf64_Off phoff; /* Program header file offset. */ + Elf64_Off shoff; /* Section header file offset. */ + Elf64_Word flags; /* Architecture-specific flags. */ + Elf64_Half ehsize; /* Size of ELF header in bytes. */ + Elf64_Half phentsize; /* Size of program header entry. */ + Elf64_Half phnum; /* Number of program header entries. */ + Elf64_Half shentsize; /* Size of section header entry. */ + Elf64_Half shnum; /* Number of section header entries. */ + Elf64_Half shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct Elf64_Shdr Elf64_Shdr; +struct Elf64_Shdr { + Elf64_Word name; /* Section name (index into the + section header string table). */ + Elf64_Word type; /* Section type. */ + Elf64_Xword flags; /* Section flags. */ + Elf64_Addr addr; /* Address in memory image. */ + Elf64_Off off; /* Offset in file. */ + Elf64_Xword size; /* Size in bytes. */ + Elf64_Word link; /* Index of a related section. */ + Elf64_Word info; /* Depends on section type. */ + Elf64_Xword addralign; /* Alignment in bytes. */ + Elf64_Xword entsize; /* Size of each entry in section. */ +}; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word type; /* Entry type. */ + Elf64_Word flags; /* Access permission flags. */ + Elf64_Off off; /* File offset of contents. */ + Elf64_Addr vaddr; /* Virtual address in memory image. */ + Elf64_Addr paddr; /* Physical address (not used). */ + Elf64_Xword filesz; /* Size of contents in file. */ + Elf64_Xword memsz; /* Size of contents in memory. */ + Elf64_Xword align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr off; /* Location to be relocated. */ + Elf64_Xword info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr off; /* Location to be relocated. */ + Elf64_Xword info; /* Relocation type and symbol index. */ + Elf64_Sxword addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) ((((uint64)(sym)) << 32) + (((uint64)(type)) & 0xffffffffULL)) + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word name; /* String table index of name. */ + unsigned char info; /* Type and binding information. */ + unsigned char other; /* Reserved (not used). */ + Elf64_Half shndx; /* Section index of symbol. */ + Elf64_Addr value; /* Symbol value. */ + Elf64_Xword size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* + * Go linker interface + */ + +#define ELF64HDRSIZE 64 +#define ELF64PHDRSIZE 56 +#define ELF64SHDRSIZE 64 +#define ELF64RELSIZE 16 +#define ELF64RELASIZE 24 +#define ELF64SYMSIZE sizeof(Elf64_Sym) + +#define ELF32HDRSIZE sizeof(Elf32_Ehdr) +#define ELF32PHDRSIZE sizeof(Elf32_Phdr) +#define ELF32SHDRSIZE sizeof(Elf32_Shdr) +#define ELF32SYMSIZE sizeof(Elf32_Sym) +#define ELF32RELSIZE 8 + +#endif /* __INCLUDE_ELF_DEFS_H__ */ diff --git a/smex/ldc.c b/smex/ldc.c new file mode 100644 index 000000000000..4eccdb1c0918 --- /dev/null +++ b/smex/ldc.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ldc.h" +#include "smex.h" + +static int fw_version_copy(const struct elf_module *src, + struct snd_sof_logs_header *header) +{ + struct ext_man_elem_header *ext_hdr = NULL; + void *buffer = NULL; + int section_size; + + section_size = elf_read_section(src, ".fw_ready", NULL, &buffer); + + if (section_size < 0) + return section_size; + + memcpy(&header->version, + &((struct sof_ipc_fw_ready *)buffer)->version, + sizeof(header->version)); + free(buffer); + + /* fw_ready structure contains main (primarily kernel) + * ABI version. + */ + fprintf(stdout, "fw abi main version:\t%d.%d.%d\n", + SOF_ABI_VERSION_MAJOR(header->version.abi_version), + SOF_ABI_VERSION_MINOR(header->version.abi_version), + SOF_ABI_VERSION_PATCH(header->version.abi_version)); + + /* let's find dbg abi version, which the log client + * is interested in and override the kernel's one. + * + * skip the base fw-ready record and begin from the first extension. + */ + section_size = elf_read_section(src, ".fw_metadata", NULL, &buffer); + + if (section_size < 0) + return section_size; + + ext_hdr = (struct ext_man_elem_header *)buffer; + while ((uintptr_t)ext_hdr < (uintptr_t)buffer + section_size) { + if (ext_hdr->type == EXT_MAN_ELEM_DBG_ABI) { + header->version.abi_version = + ((struct ext_man_dbg_abi *) + ext_hdr)->dbg_abi.abi_dbg_version; + break; + } + //move to the next entry + ext_hdr = (struct ext_man_elem_header *) + ((uint8_t *)ext_hdr + ext_hdr->elem_size); + } + free(buffer); + + fprintf(stdout, "fw abi dbg version:\t%d.%d.%d\n", + SOF_ABI_VERSION_MAJOR(header->version.abi_version), + SOF_ABI_VERSION_MINOR(header->version.abi_version), + SOF_ABI_VERSION_PATCH(header->version.abi_version)); + + return 0; +} + +static int write_logs_dictionary(struct image *image, + const struct elf_module *src) +{ + struct snd_sof_logs_header header; + const Elf32_Shdr *section; + void *buffer = NULL; + int count; + int ret; + + memcpy(header.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE); + header.data_offset = sizeof(struct snd_sof_logs_header); + + /* extract fw_version from fw_ready message located + * in .fw_ready section + */ + ret = fw_version_copy(src, &header); + if (ret < 0) + goto out; + + ret = elf_read_section(src, ".static_log_entries", §ion, &buffer); + if (ret < 0) + goto out; + + ret = 0; + header.base_address = section->vaddr; + header.data_length = section->size; + + count = fwrite(&header, sizeof(struct snd_sof_logs_header), 1, + image->ldc_out_fd); + if (count != 1) { + fprintf(stderr, "error: can't write header\n"); + ret = -errno; + goto out; + } + + count = fwrite(buffer, 1, section->size, image->ldc_out_fd); + if (count != section->size) { + fprintf(stderr, + "error: can't write section %d\n", + -errno); + ret = -errno; + goto out; + } + + fprintf(stdout, "logs dictionary size:\t%u\n", + header.data_length + header.data_offset); + fprintf(stdout, "including fw version of size:\t%lu\n", + (unsigned long)sizeof(header.version)); +out: + if (buffer) + free(buffer); + + return ret; +} + +static int write_uids_dictionary(struct image *image, + const struct elf_module *src) +{ + struct snd_sof_uids_header header; + const Elf32_Shdr *section; + void *buffer = NULL; + int ret; + + memcpy(header.sig, SND_SOF_UIDS_SIG, SND_SOF_UIDS_SIG_SIZE); + header.data_offset = sizeof(struct snd_sof_uids_header); + + ret = elf_read_section(src, ".static_uuid_entries", §ion, &buffer); + if (ret < 0) + goto out; + + ret = 0; + header.base_address = section->vaddr; + header.data_length = section->size; + + if (fwrite(&header, sizeof(struct snd_sof_uids_header), 1, + image->ldc_out_fd) != 1) { + fprintf(stderr, "error: cant't write header\n"); + ret = -errno; + goto out; + } + + if (fwrite(buffer, 1, section->size, image->ldc_out_fd) != + section->size) { + fprintf(stderr, "error: cant't write section %d\n", + -errno); + ret = -errno; + goto out; + } + fprintf(stdout, "uids dictionary size:\t%u\n", + header.data_length + header.data_offset); +out: + if (buffer) + free(buffer); + return ret; +} + +int write_dictionaries(struct image *image, const struct elf_module *src) +{ + int ret = 0; + + ret = write_logs_dictionary(image, src); + if (ret) + goto out; + + ret = write_uids_dictionary(image, src); + +out: + return ret; +} diff --git a/smex/ldc.h b/smex/ldc.h new file mode 100644 index 000000000000..2fbb90e593d3 --- /dev/null +++ b/smex/ldc.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +/* + * Functions from this file is responsible for LDC file creation + */ + +#ifndef __INCLUDE_LDC_H__ +#define __INCLUDE_LDC_H__ + +#include <ipc/info.h> + +#define SND_SOF_LOGS_SIG_SIZE 4 +#define SND_SOF_LOGS_SIG "Logs" + +#define SND_SOF_UIDS_SIG_SIZE 4 +#define SND_SOF_UIDS_SIG "Uids" + +/* + * Logs dictionary file header. + */ +struct snd_sof_logs_header { + unsigned char sig[SND_SOF_LOGS_SIG_SIZE]; /* "Logs" */ + uint32_t base_address; /* address of log entries section */ + uint32_t data_length; /* amount of bytes following this header */ + uint32_t data_offset; /* offset to first entry in this file */ + struct sof_ipc_fw_version version; +}; + +struct snd_sof_uids_header { + unsigned char sig[SND_SOF_UIDS_SIG_SIZE]; /* "Uids" */ + uint32_t base_address; + uint32_t data_length; + uint32_t data_offset; +}; + +struct image; +struct elf_module; + +int write_dictionaries(struct image *image, const struct elf_module *src); + +#endif /* __INCLUDE_LDC_H__ */ diff --git a/smex/smex.c b/smex/smex.c new file mode 100644 index 000000000000..415435da18e0 --- /dev/null +++ b/smex/smex.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> + +#include "elf.h" +#include "ldc.h" +#include "smex.h" + +static void usage(char *name) +{ + fprintf(stdout, "%s:\t in_file\n", name); + fprintf(stdout, "\t -l log dictionary outfile\n"); + fprintf(stdout, "\t -v enable verbose output\n"); + fprintf(stdout, "\t -h this help message\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct image image; + int opt, ret; + + memset(&image, 0, sizeof(image)); + + while ((opt = getopt(argc, argv, "hl:v")) != -1) { + switch (opt) { + case 'l': + image.ldc_out_file = optarg; + break; + case 'v': + image.verbose = true; + break; + case 'h': + usage(argv[0]); + break; + default: + break; + } + } + + /* make sure we have an outfile */ + if (!image.ldc_out_file) + image.ldc_out_file = "out.ldc"; + + /* make sure we have an input ELF file */ + if (argc - optind != 1) { + usage(argv[0]); + return -EINVAL; + } + + /* read source elf file */ + ret = elf_read_module(&image.module, argv[optind], image.verbose); + if (ret < 0) + goto out; + + /* open outfile for writing */ + unlink(image.ldc_out_file); + image.ldc_out_fd = fopen(image.ldc_out_file, "wb"); + if (!image.ldc_out_fd) { + fprintf(stderr, "error: unable to open %s for writing %d\n", + image.ldc_out_file, errno); + ret = -EINVAL; + goto out; + } + + /* write dictionaries */ + ret = write_dictionaries(&image, &image.module); + if (ret) { + fprintf(stderr, "error: unable to write dictionaries, %d\n", + ret); + /* Don't corrupt the build with an empty or incomplete output */ + unlink(image.ldc_out_file); + goto out; + } + +out: + /* close files */ + if (image.ldc_out_fd) + fclose(image.ldc_out_fd); + + elf_free_module(&image.module); + + return ret; +} diff --git a/smex/smex.h b/smex/smex.h new file mode 100644 index 000000000000..6df4f550d4e4 --- /dev/null +++ b/smex/smex.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include "elf.h" + +/* + * Firmware image context. + */ +struct image { + const char *ldc_out_file; + FILE *ldc_out_fd; + + bool verbose; + struct elf_module module; +}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4c980f93e269..e1455a75bd7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,30 +2,38 @@ add_subdirectory(platform) add_subdirectory(arch) +add_subdirectory(ipc) +add_subdirectory(audio) +add_subdirectory(lib) +add_subdirectory(math) +add_subdirectory(module) -if(BUILD_LIBRARY) - add_subdirectory(ipc) - add_subdirectory(audio) - add_subdirectory(lib) - add_local_sources(sof spinlock.c) - return() +if(CONFIG_SAMPLES) + add_subdirectory(samples) endif() -add_subdirectory(audio) -add_subdirectory(debug) add_subdirectory(drivers) -add_subdirectory(init) -add_subdirectory(ipc) -add_subdirectory(lib) -add_subdirectory(math) -add_subdirectory(schedule) if (CONFIG_TRACE) add_subdirectory(trace) endif() +if(CONFIG_LIBRARY) + return() +endif() + +add_subdirectory(debug) +add_subdirectory(init) +add_subdirectory(schedule) + if (CONFIG_PROBE) add_subdirectory(probe) endif() -add_local_sources(sof spinlock.c) +if (CONFIG_MULTICORE) + add_subdirectory(idc) +endif() + +if (CONFIG_LOADABLE_MODULES) + add_subdirectory(library_manager) +endif() diff --git a/src/Kconfig b/src/Kconfig index 0cbb55d912f8..0ad749042db8 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -1,13 +1,32 @@ # SPDX-License-Identifier: BSD-3-Clause -source "src/arch/Kconfig" +rsource "arch/Kconfig" -source "src/platform/Kconfig" +rsource "platform/Kconfig" -source "src/drivers/Kconfig" +rsource "drivers/Kconfig" -source "src/audio/Kconfig" +rsource "audio/Kconfig" -source "src/trace/Kconfig" +rsource "trace/Kconfig" -source "src/probe/Kconfig" +rsource "probe/Kconfig" + +rsource "samples/Kconfig" + +rsource "schedule/Kconfig" +rsource "schedule/Kconfig.threads_prio" + +rsource "idc/Kconfig" + +rsource "ipc/Kconfig" + +rsource "math/Kconfig" + +rsource "library_manager/Kconfig" + +rsource "debug/telemetry/Kconfig" + +rsource "debug/debug_stream/Kconfig" + +rsource "debug/tester/Kconfig" diff --git a/src/arch/Kconfig b/src/arch/Kconfig index 14b4319a9c72..1453ee3ffd8b 100644 --- a/src/arch/Kconfig +++ b/src/arch/Kconfig @@ -2,4 +2,4 @@ # Generic architecture configs -source "src/arch/$(ARCH)/Kconfig" +orsource "$(ARCH)/Kconfig" diff --git a/src/arch/host/CMakeLists.txt b/src/arch/host/CMakeLists.txt index b663462d2c94..75314f00f556 100644 --- a/src/arch/host/CMakeLists.txt +++ b/src/arch/host/CMakeLists.txt @@ -3,8 +3,26 @@ # includes target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/src/arch/host/include) target_include_directories(sof_public_headers INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/library/include) +include(CheckCCompilerFlag) + +if (NOT CONFIG_SOF_ZEPHYR_STRICT_HEADERS) +target_include_directories(sof_public_headers INTERFACE + ${PROJECT_SOURCE_DIR}/posix/include +) +endif() + +# -Wimplicit-fallthrough is preferred, check if it's supported +check_c_compiler_flag(-Wimplicit-fallthrough supports_implicit_fallthrough) +if (supports_implicit_fallthrough) + set(implicit_fallthrough -Wimplicit-fallthrough) +endif() # C & ASM flags -target_compile_options(sof_options INTERFACE -g -O3 -Wall -Werror -Wl,-EL -Wmissing-prototypes -Wimplicit-fallthrough=3 -Wpointer-arith) +target_compile_options(sof_options INTERFACE -g -O3 -fPIC -DPIC -std=c99 -std=gnu99 -fgnu89-inline + -Wall -Werror -Wmissing-prototypes ${implicit_fallthrough} -Wno-pointer-to-int-cast + -Wno-int-to-pointer-cast -Wpointer-arith + -DCONFIG_LIBRARY "-imacros${CONFIG_H_PATH}") -add_subdirectory(lib) +if(NOT BUILD_UNIT_TESTS_HOST) + add_subdirectory(lib) +endif() diff --git a/src/arch/host/Kconfig b/src/arch/host/Kconfig deleted file mode 100644 index deded9c32300..000000000000 --- a/src/arch/host/Kconfig +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -# Host architecture configs diff --git a/src/arch/host/configs/library_defconfig b/src/arch/host/configs/library_defconfig index ff5008760c9a..28c486bec58d 100644 --- a/src/arch/host/configs/library_defconfig +++ b/src/arch/host/configs/library_defconfig @@ -1 +1,36 @@ +CONFIG_COMP_ARIA=y +CONFIG_COMP_ASRC=y +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DCBLOCK=y +CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING=y +CONFIG_COMP_DRC=y +CONFIG_COMP_FIR=y +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=y +CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING=y +CONFIG_COMP_IIR=y +CONFIG_COMP_IGO_NR=y +CONFIG_COMP_LEVEL_MULTIPLIER=y +CONFIG_COMP_MFCC=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_COMP_MULTIBAND_DRC=y +CONFIG_COMP_MUX=y +CONFIG_COMP_RTNR=y +CONFIG_COMP_SEL=y +CONFIG_COMP_SOUND_DOSE=y +CONFIG_COMP_SRC=y +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_STFT_PROCESS=y +CONFIG_COMP_STUBS=y +CONFIG_COMP_TDFB=y +CONFIG_COMP_TONE=y +CONFIG_COMP_VOLUME=y +CONFIG_COMP_VOLUME_LINEAR_RAMP=y +CONFIG_COMP_VOLUME_WINDOWS_FADE=y +CONFIG_DEBUG_MEMORY_USAGE_SCAN=n +CONFIG_IPC_MAJOR_3=n +CONFIG_IPC_MAJOR_4=y CONFIG_LIBRARY=y +CONFIG_LIBRARY_STATIC=y +CONFIG_MATH_IIR_DF2T=y +CONFIG_TRACEV=y +CONFIG_XT_RUN=y diff --git a/src/arch/host/configs/plugin_ipc4_defconfig b/src/arch/host/configs/plugin_ipc4_defconfig new file mode 100644 index 000000000000..0398ea947dda --- /dev/null +++ b/src/arch/host/configs/plugin_ipc4_defconfig @@ -0,0 +1,22 @@ +CONFIG_IPC_MAJOR_4=y +CONFIG_LIBRARY=y +CONFIG_TRACEV=y +CONFIG_DEBUG_MEMORY_USAGE_SCAN=n +CONFIG_COMP_CROSSOVER=y +CONFIG_COMP_DRC=y +CONFIG_COMP_MULTIBAND_DRC=y +CONFIG_COMP_SRC=y +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y +CONFIG_COMP_MFCC=y +CONFIG_COMP_GAIN=y +CONFIG_COMP_VOLUME_WINDOWS_FADE=y +CONFIG_COMP_MODULES_SO=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_COMP_MIXIN_MIXOUT=y +CONFIG_IPC4_GATEWAY=n +CONFIG_COMP_DAI_GROUP=n +CONFIG_FORMAT_S16LE=y +CONFIG_FORMAT_S32LE=y +CONFIG_FORMAT_S24LE=y +CONFIG_COMP_PEAK_VOL=n +CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD=y diff --git a/src/arch/host/include/arch/atomic.h b/src/arch/host/include/arch/atomic.h index 40613c6a3278..797ba5f5e1d4 100644 --- a/src/arch/host/include/arch/atomic.h +++ b/src/arch/host/include/arch/atomic.h @@ -17,9 +17,44 @@ typedef struct { volatile int32_t value; } atomic_t; +#if defined __GNUC__ && !defined __XCC__ + +static inline int32_t arch_atomic_read(const atomic_t *a) +{ + return __atomic_load_n(&a->value, __ATOMIC_SEQ_CST); +} + +static inline void arch_atomic_set(atomic_t *a, int32_t value) +{ + __atomic_store_n(&a->value, value, __ATOMIC_SEQ_CST); +} + +static inline void arch_atomic_init(atomic_t *a, int32_t value) +{ + __atomic_store_n(&a->value, value, __ATOMIC_SEQ_CST); +} + +static inline int32_t arch_atomic_add(atomic_t *a, int32_t value) +{ + return __atomic_add_fetch(&a->value, value, __ATOMIC_SEQ_CST); +} + +static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value) +{ + return __atomic_sub_fetch(&a->value, value, __ATOMIC_SEQ_CST); +} + +#elif defined __XCC__ + +/* fake locking: obviously this does nothing, and provides no real locking */ +#define lock() do {} while (0) +#define unlock() do {} while (0) + +/* Fake atomic functions for xt-run static single-thread testbench */ + static inline int32_t arch_atomic_read(const atomic_t *a) { - return (*(volatile int32_t *)&a->value); + return a->value; } static inline void arch_atomic_set(atomic_t *a, int32_t value) @@ -32,17 +67,34 @@ static inline void arch_atomic_init(atomic_t *a, int32_t value) arch_atomic_set(a, value); } -/* use gcc atomic built-ins for host library */ static inline int32_t arch_atomic_add(atomic_t *a, int32_t value) { - return __sync_fetch_and_add(&a->value, value); + int32_t tmp; + + lock(); + tmp = a->value; + a->value += value; + unlock(); + return tmp; } static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value) { - return __sync_fetch_and_sub(&a->value, value); + int32_t tmp; + + lock(); + tmp = a->value; + a->value -= value; + unlock(); + return tmp; } +#else + +#error "Not gcc, not xt-xcc" + +#endif + #endif /* __ARCH_ATOMIC_H__ */ #else diff --git a/src/arch/host/include/arch/debug/backtrace.h b/src/arch/host/include/arch/debug/backtrace.h new file mode 100644 index 000000000000..e9abe3de0471 --- /dev/null +++ b/src/arch/host/include/arch/debug/backtrace.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + */ + +#ifdef __SOF_DEBUG_BACKTRACE_H__ + +#ifndef __ARCH_DEBUG_BACKTRACE_H__ +#define __ARCH_DEBUG_BACKTRACE_H__ + +#include <execinfo.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +/* architecture specific stack frames to dump */ +#define ARCH_STACK_DUMP_FRAMES 32 + +static inline void *arch_get_stack_ptr(void) +{ + void *frames[ARCH_STACK_DUMP_FRAMES]; + size_t frame_count; + size_t i; + char **symbols; + + frame_count = backtrace(frames, ARCH_STACK_DUMP_FRAMES); + symbols = backtrace_symbols(frames, frame_count); + + fprintf(stderr, "Dumping %zd stack frames.\n", frame_count); + + for (i = 0; i < frame_count; i++) + fprintf(stderr, "\t%s\n", symbols[i]); + + free(symbols); + + return NULL; +} + +#endif /* __ARCH_DEBUG_BACKTRACE_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/debug/backtrace.h" + +#endif /* __SOF_DEBUG_BACKTRACE_H__ */ diff --git a/src/arch/xtensa/include/arch/debug/gdb/init.h b/src/arch/host/include/arch/debug/gdb/init.h similarity index 100% rename from src/arch/xtensa/include/arch/debug/gdb/init.h rename to src/arch/host/include/arch/debug/gdb/init.h diff --git a/src/arch/host/include/arch/debug/gdb/utilities.h b/src/arch/host/include/arch/debug/gdb/utilities.h new file mode 100644 index 000000000000..9d0c53bdc066 --- /dev/null +++ b/src/arch/host/include/arch/debug/gdb/utilities.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Curtis <cujomalainey@chromium.org> + */ + +/* + * Header file for host-GDB utilities. + */ + +#ifndef __ARCH_DEBUG_GDB_UTILITIES_H__ +#define __ARCH_DEBUG_GDB_UTILITIES_H__ + +void arch_gdb_read_sr(int sr); +void arch_gdb_write_sr(int sr, int *sregs); +unsigned char arch_gdb_load_from_memory(void *mem); +void arch_gdb_memory_load_and_store(void *mem, unsigned char ch); +void arch_gdb_single_step(int *sregs); + +#endif /* __ARCH_DEBUG_GDB_UTILITIES_H__ */ diff --git a/src/arch/host/include/arch/debug/panic.h b/src/arch/host/include/arch/debug/panic.h index 7b930e70bed7..85f47a5ecbbc 100644 --- a/src/arch/host/include/arch/debug/panic.h +++ b/src/arch/host/include/arch/debug/panic.h @@ -5,7 +5,7 @@ * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> */ -#ifdef __SOF_DEBUG_PANIC_H__ +#ifdef __POSIX_RTOS_PANIC_H__ #ifndef __ARCH_DEBUG_PANIC_H__ #define __ARCH_DEBUG_PANIC_H__ @@ -19,6 +19,6 @@ static inline void arch_dump_regs(void *dump_buf, uintptr_t stack_ptr, #else -#error "This file shouldn't be included from outside of sof/debug/panic.h" +#error "This file shouldn't be included from outside of XTOS's rtos/panic.h" -#endif /* __SOF_DEBUG_PANIC_H__ */ +#endif /* __POSIX_RTOS_PANIC_H__ */ diff --git a/src/arch/host/include/arch/drivers/idc.h b/src/arch/host/include/arch/drivers/idc.h index 01cf9a556c52..3f3e67b89d76 100644 --- a/src/arch/host/include/arch/drivers/idc.h +++ b/src/arch/host/include/arch/drivers/idc.h @@ -5,7 +5,7 @@ * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> */ -#ifdef __SOF_DRIVERS_IDC_H__ +#ifdef __POSIX_RTOS_IDC_H__ #ifndef __ARCH_DRIVERS_IDC_H__ #define __ARCH_DRIVERS_IDC_H__ @@ -14,6 +14,6 @@ #else -#error "This file shouldn't be included from outside of sof/drivers/idc.h" +#error "This file shouldn't be included from outside of XTOS's rtos/idc.h" -#endif /* __SOF_DRIVERS_IDC_H__ */ +#endif /* __POSIX_RTOS_IDC_H__ */ diff --git a/src/arch/host/include/arch/drivers/timer.h b/src/arch/host/include/arch/drivers/timer.h index 76305224afed..fdf8156066e6 100644 --- a/src/arch/host/include/arch/drivers/timer.h +++ b/src/arch/host/include/arch/drivers/timer.h @@ -13,6 +13,8 @@ #include <stdint.h> struct timer { + uint32_t id; + uint64_t delta; }; static inline int arch_timer_register(struct timer *timer, @@ -20,7 +22,7 @@ static inline int arch_timer_register(struct timer *timer, static inline void arch_timer_unregister(struct timer *timer) {} static inline void arch_timer_enable(struct timer *timer) {} static inline void arch_timer_disable(struct timer *timer) {} -static inline uint32_t arch_timer_get_system(struct timer *timer) {return 0; } +static inline uint64_t arch_timer_get_system(struct timer *timer) {return 0; } static inline int64_t arch_timer_set(struct timer *timer, uint64_t ticks) {return 0; } static inline void arch_timer_clear(struct timer *timer) {} diff --git a/src/arch/host/include/arch/lib/cache.h b/src/arch/host/include/arch/lib/cache.h index a849c1c77fc8..e1ca9714e290 100644 --- a/src/arch/host/include/arch/lib/cache.h +++ b/src/arch/host/include/arch/lib/cache.h @@ -18,6 +18,8 @@ static inline void icache_invalidate_region(void *addr, size_t size) {} static inline void dcache_writeback_invalidate_region(void *addr, size_t size) {} +#define DCACHE_LINE_SIZE 64 + #endif /* __ARCH_LIB_CACHE_H__ */ #else diff --git a/src/arch/host/include/arch/lib/cpu.h b/src/arch/host/include/arch/lib/cpu.h index 51c362180860..e2cfb76260b7 100644 --- a/src/arch/host/include/arch/lib/cpu.h +++ b/src/arch/host/include/arch/lib/cpu.h @@ -10,8 +10,9 @@ #ifndef __ARCH_LIB_CPU_H__ #define __ARCH_LIB_CPU_H__ -static inline void arch_cpu_enable_core(int id) +static inline int arch_cpu_enable_core(int id) { + return 0; } static inline void arch_cpu_disable_core(int id) @@ -23,11 +24,26 @@ static inline int arch_cpu_is_core_enabled(int id) return 0; } +static inline int arch_cpu_enabled_cores(void) +{ + return 1; +} + static inline int arch_cpu_get_id(void) { return 0; } +static inline int arch_cpu_restore_secondary_cores(void) +{ + return 0; +} + +static inline int arch_cpu_secondary_cores_prepare_d0ix(void) +{ + return 0; +} + static inline void cpu_write_threadptr(int threadptr) { } diff --git a/src/arch/host/include/arch/schedule/task.h b/src/arch/host/include/arch/schedule/task.h index daabc78c9544..2b89d264e0a6 100644 --- a/src/arch/host/include/arch/schedule/task.h +++ b/src/arch/host/include/arch/schedule/task.h @@ -11,7 +11,7 @@ * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com> */ -#ifdef __SOF_SCHEDULE_TASK_H__ +#ifdef __POSIX_RTOS_TASK_H__ #ifndef __ARCH_SCHEDULE_TASK_H__ #define __ARCH_SCHEDULE_TASK_H__ @@ -20,6 +20,6 @@ #else -#error "This file shouldn't be included from outside of sof/schedule/task.h" +#error "This file shouldn't be included from outside of XTOS's posix/task.h" -#endif /* __SOF_SCHEDULE_TASK_H__ */ +#endif /* __POSIX_RTOS_TASK_H__ */ diff --git a/src/arch/host/include/arch/sof.h b/src/arch/host/include/arch/sof.h index 423b583d213e..9b4d7a1da993 100644 --- a/src/arch/host/include/arch/sof.h +++ b/src/arch/host/include/arch/sof.h @@ -5,43 +5,15 @@ * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> */ -#ifdef __SOF_SOF_H__ +#ifdef __XTOS_RTOS_SOF_H__ #ifndef __ARCH_SOF_H__ #define __ARCH_SOF_H__ -#include <execinfo.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -/* architecture specific stack frames to dump */ -#define ARCH_STACK_DUMP_FRAMES 32 - -static inline void *arch_get_stack_ptr(void) -{ - void *frames[ARCH_STACK_DUMP_FRAMES]; - size_t frame_count; - size_t i; - char **symbols; - - frame_count = backtrace(frames, ARCH_STACK_DUMP_FRAMES); - symbols = backtrace_symbols(frames, frame_count); - - fprintf(stderr, "Dumping %zd stack frames.\n", frame_count); - - for (i = 0; i < frame_count; i++) - fprintf(stderr, "\t%s\n", symbols[i]); - - free(symbols); - - return NULL; -} - #endif /* __ARCH_SOF_H__ */ #else -#error "This file shouldn't be included from outside of sof/sof.h" +#error "This file shouldn't be included from outside of XTOS's rtos/sof.h" -#endif /* __SOF_SOF_H__ */ +#endif /* __XTOS_RTOS_SOF_H__ */ diff --git a/src/arch/host/include/arch/spinlock.h b/src/arch/host/include/arch/spinlock.h deleted file mode 100644 index 50fcd8f42d8a..000000000000 --- a/src/arch/host/include/arch/spinlock.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_SPINLOCK_H__ - -#ifndef __ARCH_SPINLOCK_H__ -#define __ARCH_SPINLOCK_H__ - -typedef struct { -} spinlock_t; - -static inline void arch_spinlock_init(spinlock_t *lock) { } -static inline void arch_spin_lock(spinlock_t *lock) {} -static inline int arch_try_lock(spinlock_t *lock) -{ - return 1; -} -static inline void arch_spin_unlock(spinlock_t *lock) {} - -#endif /* __ARCH_SPINLOCK_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/spinlock.h" - -#endif /* __SOF_SPINLOCK_H__ */ diff --git a/src/arch/host/include/arch/string.h b/src/arch/host/include/arch/string.h index dfe0b3d79694..125f7bf555a6 100644 --- a/src/arch/host/include/arch/string.h +++ b/src/arch/host/include/arch/string.h @@ -5,7 +5,7 @@ * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> */ -#ifdef __SOF_STRING_H__ +#ifdef __POSIX_RTOS_STRING_H__ #ifndef __ARCH_STRING_H__ #define __ARCH_STRING_H__ @@ -17,31 +17,33 @@ #define arch_memcpy(dest, src, size) \ memcpy(dest, src, size) -#define arch_bzero(ptr, size) \ +#define bzero(ptr, size) \ memset(ptr, 0, size) - void *memcpy(void *dest, const void *src, size_t length); void *memset(void *dest, int data, size_t count); int memset_s(void *dest, size_t dest_size, int data, size_t count); int memcpy_s(void *dest, size_t dest_size, - const void *src, size_t src_size); + const void *src, size_t count); + +void *__vec_memcpy(void *dst, const void *src, size_t len); +void *__vec_memset(void *dest, int data, size_t src_size); static inline int arch_memcpy_s(void *dest, size_t dest_size, - const void *src, size_t src_size) + const void *src, size_t count) { if (!dest || !src) return -EINVAL; - if ((dest >= src && (char *)dest < ((char *)src + src_size)) || + if ((dest >= src && (char *)dest < ((char *)src + count)) || (src >= dest && (char *)src < ((char *)dest + dest_size))) return -EINVAL; - if (src_size > dest_size) + if (count > dest_size) return -EINVAL; - memcpy(dest, src, src_size); + memcpy(dest, src, count); return 0; } diff --git a/src/arch/host/lib/ams.c b/src/arch/host/lib/ams.c new file mode 100644 index 000000000000..946611d26fa1 --- /dev/null +++ b/src/arch/host/lib/ams.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Krzysztof Frydryk <krzysztofx.frydryk@intel.com> + +/** + * \file + * \brief Xtensa Asynchronous Messaging Service implementation file + * \authors Krzysztof Frydryk <krzysztofx.frydryk@intel.com> + */ + +#include <sof/lib/cpu.h> +#include <sof/lib/ams.h> +#include <xtos-structs.h> + +static struct async_message_service *host_ams; + +struct async_message_service **arch_ams_get(void) +{ + return &host_ams; +} diff --git a/src/arch/host/lib/notifier.c b/src/arch/host/lib/notifier.c index 8c609e8139c3..f79f93771c9e 100644 --- a/src/arch/host/lib/notifier.c +++ b/src/arch/host/lib/notifier.c @@ -11,15 +11,12 @@ */ #include <ipc/topology.h> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> #include <sof/lib/notifier.h> static struct notify *host_notify; struct notify **arch_notify_get(void) { - if (!host_notify) - host_notify = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(*host_notify)); return &host_notify; } diff --git a/src/arch/xtensa/CMakeLists.txt b/src/arch/xtensa/CMakeLists.txt deleted file mode 100644 index ae1003477828..000000000000 --- a/src/arch/xtensa/CMakeLists.txt +++ /dev/null @@ -1,437 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -# platform-specific values - -if(CONFIG_BAYTRAIL) - set(platform_folder baytrail) -elseif(CONFIG_CHERRYTRAIL) - set(platform_folder baytrail) -elseif(CONFIG_HASWELL) - set(platform_folder haswell) -elseif(CONFIG_BROADWELL) - set(platform_folder haswell) -elseif(CONFIG_APOLLOLAKE) - set(platform_folder apollolake) -elseif(CONFIG_CANNONLAKE) - set(platform_folder cannonlake) -elseif(CONFIG_SUECREEK) - set(platform_folder suecreek) -elseif(CONFIG_ICELAKE) - set(platform_folder icelake) -elseif(CONFIG_TIGERLAKE) - set(platform_folder tigerlake) - if(XCC) - set(RIMAGE_MOD_OFFSET_FLAG -x 24) - endif() -elseif(CONFIG_IMX8) - set(platform_folder imx8) -elseif(CONFIG_IMX8X) - set(platform_folder imx8) -elseif(CONFIG_IMX8M) - set(platform_folder imx8m) -endif() - -set(fw_name ${CONFIG_FIRMWARE_SHORT_NAME}) - -if(CONFIG_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) - -# includes - -target_include_directories(sof_options INTERFACE - ${PROJECT_SOURCE_DIR}/src/arch/xtensa/include - ${PROJECT_SOURCE_DIR}/src/arch/xtensa/xtos -) - -target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/${platform_folder}/include) - -if(XCC) - target_include_directories(sof_options INTERFACE ${ROOT_DIR}/arch/include) -else() - target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/${platform_folder}/include/arch) -endif() - -target_include_directories(sof_options INTERFACE ${ROOT_DIR}/include) - -if(BUILD_UNIT_TESTS) - set(stdlib_flag "") -else() - set(stdlib_flag "-nostdlib") -endif() - -get_optimization_flag(optimization_flag) - -if(BUILD_CLANG_SCAN) - # pretend to be xtensa compiler to go trough the same paths for AST - target_compile_definitions(sof_options INTERFACE -D__XTENSA__=1) - - if(XCC) - # clang has to compile objects in order to analyze sources, - # so it needs xcc's headers - find_program(XCC_PATH NAMES "xt-xcc" PATHS ENV PATH NO_DEFAULT_PATH) - get_filename_component(XCC_DIR ${XCC_PATH} DIRECTORY) - target_include_directories(sof_options INTERFACE ${XCC_DIR}/../xtensa-elf/include) - endif() - - # Clang by default compiles for host architecture, - # but xtensa is always 32 bit, what may cause mismatch in definitions, - # that depend on bitness, so force compilation for 32 bit. - set(XTENSA_C_ASM_FLAGS -m32) - set(XTENSA_C_FLAGS) -else() - set(XTENSA_C_ASM_FLAGS -mlongcalls) - set(XTENSA_C_FLAGS -mtext-section-literals) -endif() - -# linker flags -target_link_libraries(sof_options INTERFACE ${stdlib_flag} -Wl,--no-check-sections -ucall_user_start -Wl,-static) - -# C & ASM flags -target_compile_options(sof_options INTERFACE ${stdlib_flag} -fno-inline-functions ${XTENSA_C_ASM_FLAGS}) - -# C flags -# TODO: Generator expressions are supported only with Make and Ninja, -# if we want to support other generators, we would have to find some other way -# for setting flags just for C files. -# Possible solutions: -# 1) CMAKE_<LANG>_FLAGS - works, but is global, we prefer target_* functions -# 2) set_source_files_properties - need to be done for each source file, it's -# better to have set of default flags and change it only for special cases -# 3) custom function that is used instead of target_sources and sets flags -# for each added source based on file extension -target_compile_options(sof_options INTERFACE $<$<COMPILE_LANGUAGE:C>: -${optimization_flag} -g -Wall -Werror -Wl,-EL -Wmissing-prototypes -Wpointer-arith ${XTENSA_C_FLAGS}>) - -if(BUILD_UNIT_TESTS) - # rest of this file is not needed for unit tests - return() -endif() - -if(XCC) - file(GLOB LINK_DEPS - ${ROOT_DIR}/arch/include/xtensa/config/core-isa*) -else() - file(GLOB LINK_DEPS - ${PROJECT_SOURCE_DIR}/src/platform/${platform_folder}/include/arch/xtensa/config/core-isa*) -endif() - -# linker scripts - -function(sof_add_ld_script binary_name script_name) - if(NOT EXISTS ${DOT_CONFIG_PATH}) - return() - endif() - - set(lds_in ${PROJECT_SOURCE_DIR}/src/platform/${platform_folder}/${script_name}.in) - set(lds_out ${PROJECT_BINARY_DIR}/${script_name}) - - get_target_property(incdirs sof_options INTERFACE_INCLUDE_DIRECTORIES) - - set(iflags "") - set(glob_predicates "") - foreach(d ${incdirs}) - list(APPEND iflags "-I${d}") - list(APPEND glob_predicates "${d}/*.h") - endforeach() - - get_target_property(incdirs sof_public_headers INTERFACE_INCLUDE_DIRECTORIES) - - foreach(d ${incdirs}) - list(APPEND iflags "-I${d}") - list(APPEND glob_predicates "${d}/*.h") - endforeach() - - file(GLOB lds_headers ${glob_predicates}) - - add_custom_command(OUTPUT ${lds_out} - COMMAND ${CMAKE_C_COMPILER} -E -DLINKER -P ${iflags} -o ${lds_out} -x c ${lds_in} - DEPENDS ${lds_in} ${LINK_DEPS} genconfig ${CONFIG_H_PATH} ${lds_headers} - WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - COMMENT "Generating linker script: ${lds_out}" - VERBATIM - USES_TERMINAL - ) - - add_custom_target("ld_script_${script_name}" DEPENDS ${lds_out}) - add_dependencies(${binary_name} "ld_script_${script_name}") - set_target_properties(${binary_name} PROPERTIES LINK_DEPENDS ${lds_in}) -endfunction() - -sof_add_ld_script(sof ${platform_ld_script}) - -# binaries - -add_library(reset STATIC "") -target_link_libraries(reset sof_options) -target_compile_options(reset PRIVATE -mtext-section-literals) - -add_subdirectory(debug) -add_subdirectory(drivers) -add_subdirectory(hal) -add_subdirectory(lib) -add_subdirectory(schedule) -add_subdirectory(xtos) - -add_local_sources(reset xtos/memctl_default.S xtos/reset-vector.S) - -add_local_sources(sof - xtos/crt1-boards.S - xtos/_vectors.S - init.c - exc-dump.S -) - -# TODO: order of these libraries does matter, what is bad, -# we should switch to building with thin archives without symbols index -# and made it before final link so dependencies won't matter -target_link_libraries(sof_static_libraries INTERFACE xtos) -target_link_libraries(sof_static_libraries INTERFACE hal) - -if(CONFIG_INTERRUPT_LEVEL_2) -target_link_libraries(sof_static_libraries INTERFACE xlevel2) -endif() -if(CONFIG_INTERRUPT_LEVEL_3) -target_link_libraries(sof_static_libraries INTERFACE xlevel3) -endif() -if(CONFIG_INTERRUPT_LEVEL_4) -target_link_libraries(sof_static_libraries INTERFACE xlevel4) -endif() -if(CONFIG_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_ld_flags INTERFACE "-lgcc") -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}") - -add_custom_target( - prepare_sof_post_process - DEPENDS sof - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/sof sof-${fw_name} -) - -# contains steps that should be performed before fw image is ready for being -# processed by tools like rimage and MEU -add_custom_target(sof_post_process DEPENDS prepare_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 "") - target_link_libraries(bootloader PRIVATE sof_options) - add_local_sources(bootloader xtos/_vectors.S boot_entry.S boot_loader.c) - target_link_libraries(bootloader PRIVATE reset) - target_link_libraries(bootloader PRIVATE hal) - target_link_libraries(bootloader PRIVATE "-lgcc") - 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 ${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_custom_target( - process_base_module - COMMAND ${CMAKE_OBJCOPY} -O binary ${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-${fw_name} - DEPENDS prepare_sof_post_process base_module bootloader_dump - VERBATIM - USES_TERMINAL - ) - - add_dependencies(sof_post_process process_base_module) -else() - set(bootloader_binary_path) -endif() - -if(CONFIG_BUILD_VM_ROM) - add_executable(rom "") - target_link_libraries(rom PRIVATE sof_options) - target_link_libraries(rom PRIVATE "-lgcc") - target_link_libraries(rom PRIVATE "-T${PROJECT_BINARY_DIR}/${platform_rom_ld_script}") - sof_add_ld_script(rom ${platform_rom_ld_script}) - - # We have to make additional define, because sources - # are reused for other objects with different flags. - target_compile_definitions(rom PRIVATE -DCONFIG_VM_ROM) - - add_local_sources(rom - xtos/crt1-boards-rom.S - xtos/memctl_default.S - xtos/reset-vector.S - ) - - add_custom_target( - rom_dump - COMMAND ${CMAKE_COMMAND} -E copy rom rom-${fw_name} - COMMAND ${CMAKE_OBJCOPY} -O binary rom rom-${fw_name}.bin - COMMAND ${CMAKE_OBJDUMP} -h -D rom > rom-${fw_name}.lmap - COMMAND ${CMAKE_OBJDUMP} -S rom > rom-${fw_name}.lst - COMMAND ${CMAKE_OBJDUMP} -D rom > rom-${fw_name}.dis - DEPENDS rom - VERBATIM - USES_TERMINAL - ) - - add_dependencies(bin_extras rom_dump) -endif() - -if(BUILD_CLANG_SCAN) - # steps below don't compile parts of fw, - # so they are not needed for scan-build - return() -endif() - -add_custom_target( - sof_dump - COMMAND ${CMAKE_OBJDUMP} -S sof-${fw_name} > sof-${fw_name}.lst - COMMAND ${CMAKE_OBJDUMP} -h sof-${fw_name} > sof-${fw_name}.lmap - COMMAND ${CMAKE_OBJDUMP} -D sof-${fw_name} > sof-${fw_name}.dis - DEPENDS sof_post_process - VERBATIM - USES_TERMINAL -) - -# rimage - -include(ExternalProject) - -ExternalProject_Add(rimage_ep - DEPENDS check_version_h - DOWNLOAD_COMMAND "" - SOURCE_DIR "${PROJECT_SOURCE_DIR}/rimage" - PREFIX "${PROJECT_BINARY_DIR}/rimage_ep" - BINARY_DIR "${PROJECT_BINARY_DIR}/rimage_ep/build" - BUILD_ALWAYS 1 - CMAKE_ARGS -DVERSION_H_PATH=${VERSION_H_PATH} - -DPEM_KEY_PREFIX=${PROJECT_SOURCE_DIR}/rimage/keys - INSTALL_COMMAND "" -) - -if(NOT DEFINED RIMAGE_PRIVATE_KEY) - set(RIMAGE_PRIVATE_KEY ${PROJECT_SOURCE_DIR}/rimage/keys/otc_private_key.pem) -endif() - -if(NOT DEFINED RIMAGE_IMR_TYPE) - # default value for non-production firmware - set(RIMAGE_IMR_TYPE 3) -endif() - -if(MEU_PATH) - execute_process( - COMMAND ${MEU_PATH}/meu -ver - OUTPUT_VARIABLE MEU_VERSION_FULL_TEXT - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - string(REGEX MATCH "Version:[\t\n ]*([^\t\n ]+)" ignored "${MEU_VERSION_FULL_TEXT}") - set(MEU_VERSION ${CMAKE_MATCH_1}) - - if(MEU_VERSION VERSION_LESS 12.0.0.1035) - set(MEU_OFFSET 1152) - elseif(MEU_VERSION VERSION_LESS 15.0.0.7041) - set(MEU_OFFSET 1088) - else() - set(MEU_OFFSET 1344) - endif() - - add_custom_target( - run_rimage - COMMAND ${PROJECT_BINARY_DIR}/rimage_ep/build/rimage - -o sof-${fw_name}.ri - -p sof-${fw_name}.ldc - -m ${fw_name} - -s ${MEU_OFFSET} - -k ${RIMAGE_PRIVATE_KEY} - -i ${RIMAGE_IMR_TYPE} - ${RIMAGE_MOD_OFFSET_FLAG} - ${bootloader_binary_path} - sof-${fw_name} - DEPENDS sof_dump rimage_ep - VERBATIM - USES_TERMINAL - ) - - if(NOT DEFINED MEU_OPENSSL) - set(MEU_OPENSSL "/usr/bin/openssl") - endif() - - if(NOT DEFINED MEU_FLAGS) - set(MEU_FLAGS - -f ${MEU_PATH}/generic_meu_conf.xml - -mnver 0.0.0.0 - -key ${MEU_PRIVATE_KEY} - -stp ${MEU_OPENSSL} - ${MEU_EXTRA_FLAGS} - ) - endif() - - add_custom_target( - run_meu - COMMAND ${MEU_PATH}/meu -w ./ -s sof-${fw_name} - ${MEU_FLAGS} - -o sof-${fw_name}.ri - DEPENDS run_rimage - VERBATIM - USES_TERMINAL - ) -else() - add_custom_target( - run_rimage - COMMAND ${PROJECT_BINARY_DIR}/rimage_ep/build/rimage - -o sof-${fw_name}.ri - -p sof-${fw_name}.ldc - -m ${fw_name} - -k ${RIMAGE_PRIVATE_KEY} - -i ${RIMAGE_IMR_TYPE} - ${RIMAGE_MOD_OFFSET_FLAG} - ${bootloader_binary_path} - sof-${fw_name} - DEPENDS sof_dump rimage_ep - VERBATIM - USES_TERMINAL - ) - add_custom_target(run_meu DEPENDS run_rimage) -endif() - -add_custom_target( - bin ALL - COMMAND ${CMAKE_COMMAND} -E copy sof-${fw_name}.ri ${PROJECT_BINARY_DIR}/sof-${fw_name}.ri - COMMAND ${CMAKE_COMMAND} -E copy sof-${fw_name}.ldc ${PROJECT_BINARY_DIR}/sof-${fw_name}.ldc - DEPENDS run_meu bin_extras - VERBATIM - USES_TERMINAL -) - -install( - FILES ${PROJECT_BINARY_DIR}/sof-${fw_name}.ri - ${PROJECT_BINARY_DIR}/sof-${fw_name}.ldc - DESTINATION bin -) diff --git a/src/arch/xtensa/Kconfig b/src/arch/xtensa/Kconfig index becf840ae9b8..3bb2d4abd80d 100644 --- a/src/arch/xtensa/Kconfig +++ b/src/arch/xtensa/Kconfig @@ -2,28 +2,9 @@ # Xtensa-specific architecture configs -menu "Xtensa Architecture" - -config CORE_COUNT - int "Number of cores" - default 1 - help - Number of used cores - Lowering available core count could result in lower power consumption - -config SMP - bool - default CORE_COUNT > 1 - help - Indicates that architecture uses multiple cores - -config WAKEUP_HOOK +config NO_SECONDARY_CORE_ROM bool default n help - Enables hook that is called and after coming back from WAITI. - This config should be selected by other platform-level configs. - Platforms that use it, have to implement hook function - platform_interrupt_on_wakeup. - -endmenu + Indicates that secondary core have rom, alternate reset vector + is needed if not diff --git a/src/arch/xtensa/boot_entry.S b/src/arch/xtensa/boot_entry.S deleted file mode 100644 index 8708d73043e5..000000000000 --- a/src/arch/xtensa/boot_entry.S +++ /dev/null @@ -1,229 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -/* - * Entry point from ROM - assumes :- - * - * 1) C runtime environment is initalised by ROM. - * 2) Stack is in first HPSRAM bank. - */ - -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/platform.h> -#include <config.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/corebits.h> - - .type boot_master_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 !defined CONFIG_SUECREEK -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 -#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 - -fw_loaded_status_value: - .word 0x00000005 - -fw_no_errors_value: - .word 0x00000000 - -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 !defined CONFIG_SUECREEK - /* 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 */ - rsr.prid a2 - movi a3, PLATFORM_MASTER_CORE_ID - beq a2, a3, 1f - - /* no core should get here */ - j dead - -1: - /* we are primary core so boot it */ - call8 boot_master_core - -dead: - /* should never get here - we are dead */ - j dead - - .size boot_entry, . - boot_entry - - .end literal_prefix diff --git a/src/arch/xtensa/boot_loader.c b/src/arch/xtensa/boot_loader.c deleted file mode 100644 index 61153edcfeff..000000000000 --- a/src/arch/xtensa/boot_loader.c +++ /dev/null @@ -1,356 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <cavs/version.h> -#include <sof/bit.h> -#include <sof/lib/cache.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/lib/wait.h> -#include <sof/platform.h> -#include <sof/sof.h> -#include <sof/trace/trace.h> -#include <user/manifest.h> -#include <config.h> -#include <stddef.h> -#include <stdint.h> - -#if CONFIG_SUECREEK -#define MANIFEST_BASE BOOT_LDR_MANIFEST_BASE -#else -#define MANIFEST_BASE IMR_BOOT_LDR_MANIFEST_BASE -#endif - -#if CONFIG_BOOT_LOADER -#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; - } - } -} - -/* On Sue Creek the boot loader is attached separately, no need to skip it */ -#if CONFIG_SUECREEK -#define MAN_SKIP_ENTRIES 0 -#else -#define MAN_SKIP_ENTRIES 1 -#endif - -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 = MAN_SKIP_ENTRIES; 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; -} - -/* 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 = MAN_SKIP_ENTRIES; 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); - } -} -#endif - -#if CAVS_VERSION >= CAVS_VERSION_1_8 -/* function powers up a number of memory banks provided as an argument and - * gates remaining memory banks - */ -static int32_t hp_sram_pm_banks(uint32_t banks) -{ - int delay_count = 256; - uint32_t status; - uint32_t ebb_mask0, ebb_mask1, ebb_avail_mask0, ebb_avail_mask1; - uint32_t total_banks_count = PLATFORM_HPSRAM_EBB_COUNT; - - shim_write(SHIM_LDOCTL, SHIM_LDOCTL_HPSRAM_LDO_ON); - - /* add some delay before touch power register */ - idelay(delay_count); - - /* bit masks reflect total number of available EBB (banks) in each - * segment; current implementation supports 2 segments 0,1 - */ - if (total_banks_count > EBB_SEGMENT_SIZE) { - ebb_avail_mask0 = (uint32_t)MASK(EBB_SEGMENT_SIZE - 1, 0); - ebb_avail_mask1 = (uint32_t)MASK(total_banks_count - - EBB_SEGMENT_SIZE - 1, 0); - } else{ - ebb_avail_mask0 = (uint32_t)MASK(total_banks_count - 1, - 0); - ebb_avail_mask1 = 0; - } - - /* bit masks of banks that have to be powered up in each segment */ - if (banks > EBB_SEGMENT_SIZE) { - ebb_mask0 = (uint32_t)MASK(EBB_SEGMENT_SIZE - 1, 0); - ebb_mask1 = (uint32_t)MASK(banks - EBB_SEGMENT_SIZE - 1, - 0); - } else{ - /* assumption that ebb_in_use is > 0 */ - ebb_mask0 = (uint32_t)MASK(banks - 1, 0); - ebb_mask1 = 0; - } - - /* HSPGCTL, HSRMCTL use reverse logic - 0 means EBB is power gated */ - io_reg_write(HSPGCTL0, (~ebb_mask0) & ebb_avail_mask0); - io_reg_write(HSRMCTL0, (~ebb_mask0) & ebb_avail_mask0); - io_reg_write(HSPGCTL1, (~ebb_mask1) & ebb_avail_mask1); - io_reg_write(HSRMCTL1, (~ebb_mask1) & ebb_avail_mask1); - - /* query the power status of first part of HP memory */ - /* to check whether it has been powered up. A few */ - /* cycles are needed for it to be powered up */ - status = io_reg_read(HSPGISTS0); - while (status != ((~ebb_mask0) & ebb_avail_mask0)) { - idelay(delay_count); - status = io_reg_read(HSPGISTS0); - } - /* query the power status of second part of HP memory */ - /* and do as above code */ - - status = io_reg_read(HSPGISTS1); - while (status != ((~ebb_mask1) & ebb_avail_mask1)) { - idelay(delay_count); - status = io_reg_read(HSPGISTS1); - } - /* add some delay before touch power register */ - idelay(delay_count); - - shim_write(SHIM_LDOCTL, SHIM_LDOCTL_HPSRAM_LDO_BYPASS); - - return 0; -} - -static uint32_t hp_sram_power_on_memory(uint32_t memory_size) -{ - uint32_t ebb_in_use; - - /* calculate total number of used SRAM banks (EBB) - * to power up only necessary banks - */ - ebb_in_use = (!(memory_size % SRAM_BANK_SIZE)) ? - (memory_size / SRAM_BANK_SIZE) : - (memory_size / SRAM_BANK_SIZE) + 1; - - return hp_sram_pm_banks(ebb_in_use); -} - -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_on_memory(memory_size); -} - -static int32_t hp_sram_init(void) -{ - return hp_sram_power_on_memory(HP_SRAM_SIZE); -} - -#else - -static int32_t hp_sram_power_off_unused_banks(uint32_t memory_size) -{ - return 0; -} - -static uint32_t hp_sram_init(void) -{ - return 0; -} - -#endif - -#if CONFIG_LP_SRAM -static int32_t lp_sram_init(void) -{ - uint32_t status; - uint32_t lspgctl_value; - uint32_t timeout_counter, delay_count = 256; - - timeout_counter = delay_count; - - shim_write(SHIM_LDOCTL, SHIM_LDOCTL_LPSRAM_LDO_ON); - - /* add some delay before writing power registers */ - idelay(delay_count); - - lspgctl_value = io_reg_read(LSPGISTS); - io_reg_write(LSPGCTL, lspgctl_value & ~LPSRAM_MASK(0)); - - /* add some delay before checking the status */ - idelay(delay_count); - - /* query the power status of first part of LP memory */ - /* to check whether it has been powered up. A few */ - /* cycles are needed for it to be powered up */ - status = io_reg_read(LSPGISTS); - while (status) { - if (!timeout_counter--) { - platform_panic(SOF_IPC_PANIC_MEM); - break; - } - idelay(delay_count); - status = io_reg_read(LSPGISTS); - } - - shim_write(SHIM_LDOCTL, SHIM_LDOCTL_LPSRAM_LDO_BYPASS); - - return status; -} -#endif - -/* boot master core */ -void boot_master_core(void) -{ - int32_t result; - - trace_point(TRACE_BOOT_LDR_ENTRY); - - /* init the HPSRAM */ - trace_point(TRACE_BOOT_LDR_HPSRAM); - result = hp_sram_init(); - if (result < 0) { - platform_panic(SOF_IPC_PANIC_MEM); - return; - } - -#if CONFIG_LP_SRAM - /* init the LPSRAM */ - trace_point(TRACE_BOOT_LDR_LPSRAM); - - result = lp_sram_init(); - if (result < 0) { - platform_panic(SOF_IPC_PANIC_MEM); - return; - } -#endif - -#if CONFIG_BOOT_LOADER - /* parse manifest and copy modules */ - trace_point(TRACE_BOOT_LDR_MANIFEST); - parse_manifest(); - - 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/arch/xtensa/configs/acp_6_3_defconfig b/src/arch/xtensa/configs/acp_6_3_defconfig new file mode 100644 index 000000000000..6b391bacc861 --- /dev/null +++ b/src/arch/xtensa/configs/acp_6_3_defconfig @@ -0,0 +1,37 @@ +CONFIG_ACP_6_3=y +CONFIG_RIMAGE_SIGNING_SCHEMA="acp_6_3" +CONFIG_TRACE_CHANNEL=7 +CONFIG_WRAP_ACTUAL_POSITION=y +CONFIG_AMD_BT=n +CONFIG_AMD_SP=n +CONFIG_CORE_COUNT=1 +CONFIG_LP_MEMORY_BANKS=0 +CONFIG_HP_MEMORY_BANKS=10 +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_LP_SRAM=n +CONFIG_HAVE_AGENT=n +CONFIG_COMP_VOLUME=n +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_CROSSOVER=n +CONFIG_COMP_DRC=n +CONFIG_COMP_MULTIBAND_DRC=n +CONFIG_COMP_TONE=n +CONFIG_COMP_SWITCH=n +CONFIG_COMP_KPB=n +CONFIG_MAXIM_DSM=n +CONFIG_COMP_ASRC=n +CONFIG_COMP_IGO_NR=n +CONFIG_COMP_COPIER=n +CONFIG_COMP_RTNR=n +CONFIG_COMP_ARIA=n +CONFIG_COMP_BASEFW_IPC4=n +CONFIG_COMP_UP_DOWN_MIXER=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +#CONFIG_COMP_MUX=n +CONFIG_COMP_SEL=n +CONFIG_COMP_MIXER=n +CONFIG_AMD_BINARY_BUILD=y diff --git a/src/arch/xtensa/configs/acp_7_0_defconfig b/src/arch/xtensa/configs/acp_7_0_defconfig new file mode 100644 index 000000000000..c5e3d4952294 --- /dev/null +++ b/src/arch/xtensa/configs/acp_7_0_defconfig @@ -0,0 +1,36 @@ +CONFIG_ACP_7_0=y +CONFIG_RIMAGE_SIGNING_SCHEMA="acp_7_0" +CONFIG_TRACE_CHANNEL=7 +CONFIG_WRAP_ACTUAL_POSITION=y +CONFIG_AMD_BT=n +CONFIG_AMD_SP=n +CONFIG_CORE_COUNT=1 +CONFIG_LP_MEMORY_BANKS=20 +CONFIG_HP_MEMORY_BANKS=10 +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_LP_SRAM=n +CONFIG_HAVE_AGENT=n +CONFIG_COMP_VOLUME=n +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_CROSSOVER=n +CONFIG_COMP_DRC=n +CONFIG_COMP_MULTIBAND_DRC=n +CONFIG_COMP_TONE=n +CONFIG_COMP_SWITCH=n +CONFIG_COMP_KPB=n +CONFIG_MAXIM_DSM=n +CONFIG_COMP_ASRC=n +CONFIG_COMP_IGO_NR=n +CONFIG_COMP_COPIER=n +CONFIG_COMP_RTNR=n +CONFIG_COMP_ARIA=n +CONFIG_COMP_BASEFW_IPC4=n +CONFIG_COMP_UP_DOWN_MIXER=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_MUX=n +CONFIG_COMP_SEL=n +CONFIG_COMP_MIXER=n +CONFIG_PROBE=n diff --git a/src/arch/xtensa/configs/apollolake_defconfig b/src/arch/xtensa/configs/apollolake_defconfig deleted file mode 100644 index 7c831628e0a0..000000000000 --- a/src/arch/xtensa/configs/apollolake_defconfig +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_APOLLOLAKE=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_LP_MEMORY_BANKS=2 -CONFIG_HP_MEMORY_BANKS=8 diff --git a/src/arch/xtensa/configs/baytrail_defconfig b/src/arch/xtensa/configs/baytrail_defconfig deleted file mode 100644 index 4771aad18b30..000000000000 --- a/src/arch/xtensa/configs/baytrail_defconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_BAYTRAIL=y -CONFIG_COMP_TEST_KEYPHRASE=n -CONFIG_COMP_KPB=n -CONFIG_COMP_SEL=n -CONFIG_COMP_MUX=n -CONFIG_COMP_FIR=n -CONFIG_COMP_IIR=n -CONFIG_COMP_ASRC=n -CONFIG_OPTIMIZE_FOR_SIZE=y diff --git a/src/arch/xtensa/configs/baytrail_gcc_defconfig b/src/arch/xtensa/configs/baytrail_gcc_defconfig deleted file mode 100644 index 27970ac66e67..000000000000 --- a/src/arch/xtensa/configs/baytrail_gcc_defconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_BAYTRAIL=y -CONFIG_COMP_TEST_KEYPHRASE=n -CONFIG_COMP_KPB=n -CONFIG_COMP_SEL=n -CONFIG_COMP_MUX=n -CONFIG_COMP_FIR=n -CONFIG_COMP_IIR=n -CONFIG_COMP_ASRC=n diff --git a/src/arch/xtensa/configs/broadwell_defconfig b/src/arch/xtensa/configs/broadwell_defconfig deleted file mode 100644 index 646af6a3d70e..000000000000 --- a/src/arch/xtensa/configs/broadwell_defconfig +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_BROADWELL=y -CONFIG_COMP_ASRC=n diff --git a/src/arch/xtensa/configs/cannonlake_defconfig b/src/arch/xtensa/configs/cannonlake_defconfig deleted file mode 100644 index 60b02f93fc93..000000000000 --- a/src/arch/xtensa/configs/cannonlake_defconfig +++ /dev/null @@ -1,10 +0,0 @@ -CONFIG_CANNONLAKE=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CAVS_ALH=y -CONFIG_CAVS_LPS=y -CONFIG_CAVS_LPRO=y -CONFIG_CORE_COUNT=4 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=47 -CONFIG_PERFORMANCE_COUNTERS=y diff --git a/src/arch/xtensa/configs/cannonlake_gcc_defconfig b/src/arch/xtensa/configs/cannonlake_gcc_defconfig deleted file mode 100644 index fe1408458690..000000000000 --- a/src/arch/xtensa/configs/cannonlake_gcc_defconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_CANNONLAKE=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CAVS_ALH=y -CONFIG_CAVS_LPS=y -CONFIG_CORE_COUNT=4 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=47 diff --git a/src/arch/xtensa/configs/cherrytrail_defconfig b/src/arch/xtensa/configs/cherrytrail_defconfig deleted file mode 100644 index b3cce0603899..000000000000 --- a/src/arch/xtensa/configs/cherrytrail_defconfig +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG_CHERRYTRAIL=y -CONFIG_COMP_TEST_KEYPHRASE=n -CONFIG_COMP_KPB=n -CONFIG_COMP_SEL=n -CONFIG_COMP_MUX=n -CONFIG_COMP_FIR=n -CONFIG_COMP_IIR=n -CONFIG_COMP_ASRC=n -CONFIG_OPTIMIZE_FOR_SIZE=y diff --git a/src/arch/xtensa/configs/cherrytrail_gcc_defconfig b/src/arch/xtensa/configs/cherrytrail_gcc_defconfig deleted file mode 100644 index a6407a569b4d..000000000000 --- a/src/arch/xtensa/configs/cherrytrail_gcc_defconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_CHERRYTRAIL=y -CONFIG_COMP_TEST_KEYPHRASE=n -CONFIG_COMP_KPB=n -CONFIG_COMP_SEL=n -CONFIG_COMP_MUX=n -CONFIG_COMP_FIR=n -CONFIG_COMP_IIR=n -CONFIG_COMP_ASRC=n diff --git a/src/arch/xtensa/configs/haswell_defconfig b/src/arch/xtensa/configs/haswell_defconfig deleted file mode 100644 index efffbdd22599..000000000000 --- a/src/arch/xtensa/configs/haswell_defconfig +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_HASWELL=y -CONFIG_COMP_ASRC=n diff --git a/src/arch/xtensa/configs/icelake_defconfig b/src/arch/xtensa/configs/icelake_defconfig deleted file mode 100644 index 160a542b405a..000000000000 --- a/src/arch/xtensa/configs/icelake_defconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_ICELAKE=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CAVS_ALH=y -CONFIG_CAVS_LPRO=y -CONFIG_CORE_COUNT=4 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=47 diff --git a/src/arch/xtensa/configs/imx8_defconfig b/src/arch/xtensa/configs/imx8_defconfig index 2ed258fa96ff..a245738a5d80 100644 --- a/src/arch/xtensa/configs/imx8_defconfig +++ b/src/arch/xtensa/configs/imx8_defconfig @@ -1 +1,4 @@ CONFIG_IMX8=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n diff --git a/src/arch/xtensa/configs/imx8m_defconfig b/src/arch/xtensa/configs/imx8m_defconfig index 1905c6ed0e09..bb9d86024498 100644 --- a/src/arch/xtensa/configs/imx8m_defconfig +++ b/src/arch/xtensa/configs/imx8m_defconfig @@ -1 +1,4 @@ CONFIG_IMX8M=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n diff --git a/src/arch/xtensa/configs/imx8ulp_defconfig b/src/arch/xtensa/configs/imx8ulp_defconfig new file mode 100644 index 000000000000..28247a20678e --- /dev/null +++ b/src/arch/xtensa/configs/imx8ulp_defconfig @@ -0,0 +1,4 @@ +CONFIG_IMX8ULP=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n diff --git a/src/arch/xtensa/configs/imx8x_defconfig b/src/arch/xtensa/configs/imx8x_defconfig index 5a1976d11486..a7766c19bb61 100644 --- a/src/arch/xtensa/configs/imx8x_defconfig +++ b/src/arch/xtensa/configs/imx8x_defconfig @@ -1 +1,4 @@ CONFIG_IMX8X=y +CONFIG_HAVE_AGENT=n +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_KPB_FORCE_COPY_TYPE_NORMAL=n diff --git a/src/arch/xtensa/configs/jasperlake_defconfig b/src/arch/xtensa/configs/jasperlake_defconfig deleted file mode 100644 index dda0bb6427bb..000000000000 --- a/src/arch/xtensa/configs/jasperlake_defconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_ICELAKE=y -CONFIG_FIRMWARE_SHORT_NAME="jsl" -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CAVS_ALH=y -CONFIG_CORE_COUNT=2 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=16 diff --git a/src/arch/xtensa/configs/kabylake_defconfig b/src/arch/xtensa/configs/kabylake_defconfig deleted file mode 100644 index 1396721b4731..000000000000 --- a/src/arch/xtensa/configs/kabylake_defconfig +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_APOLLOLAKE=y -CONFIG_FIRMWARE_SHORT_NAME="kbl" -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CORE_COUNT=2 -CONFIG_LP_MEMORY_BANKS=2 -CONFIG_HP_MEMORY_BANKS=30 diff --git a/src/arch/xtensa/configs/mt8186_defconfig b/src/arch/xtensa/configs/mt8186_defconfig new file mode 100644 index 000000000000..e9555a1fb31f --- /dev/null +++ b/src/arch/xtensa/configs/mt8186_defconfig @@ -0,0 +1,16 @@ +CONFIG_MT8186=y +CONFIG_CORE_COUNT=1 +CONFIG_XT_VIRTUAL_OPS=1 +CONFIG_COMP_VOLUME=y +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_TONE=n +CONFIG_COMP_MIXER=n +CONFIG_COMP_MUX=n +CONFIG_COMP_KPB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_ASRC=n + diff --git a/src/arch/xtensa/configs/mt8188_defconfig b/src/arch/xtensa/configs/mt8188_defconfig new file mode 100644 index 000000000000..b495a2e9a1f0 --- /dev/null +++ b/src/arch/xtensa/configs/mt8188_defconfig @@ -0,0 +1,14 @@ +CONFIG_MT8188=y +CONFIG_CORE_COUNT=1 +CONFIG_COMP_VOLUME=y +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_TONE=n +CONFIG_COMP_MIXER=n +CONFIG_COMP_MUX=n +CONFIG_COMP_KPB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_ASRC=n diff --git a/src/arch/xtensa/configs/mt8195_defconfig b/src/arch/xtensa/configs/mt8195_defconfig new file mode 100644 index 000000000000..cffe02dd842c --- /dev/null +++ b/src/arch/xtensa/configs/mt8195_defconfig @@ -0,0 +1,16 @@ +CONFIG_MT8195=y +CONFIG_CORE_COUNT=1 +CONFIG_XT_VIRTUAL_OPS=1 +CONFIG_COMP_VOLUME=y +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_TONE=n +CONFIG_COMP_MIXER=n +CONFIG_COMP_MUX=n +CONFIG_COMP_KPB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_ASRC=n + diff --git a/src/arch/xtensa/configs/mt8196_defconfig b/src/arch/xtensa/configs/mt8196_defconfig new file mode 100644 index 000000000000..f030ddc4fe2f --- /dev/null +++ b/src/arch/xtensa/configs/mt8196_defconfig @@ -0,0 +1,16 @@ +CONFIG_MT8196=y +CONFIG_CORE_COUNT=1 +CONFIG_COMP_VOLUME=y +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_TONE=n +CONFIG_COMP_MIXER=n +CONFIG_COMP_MUX=n +CONFIG_COMP_KPB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_ASRC=n +CONFIG_DEBUG=y +CONFIG_SCHEDULE_LL_NO_RESCHEDULE_TASK=y diff --git a/src/arch/xtensa/configs/mt8365_defconfig b/src/arch/xtensa/configs/mt8365_defconfig new file mode 100644 index 000000000000..3631692a10ff --- /dev/null +++ b/src/arch/xtensa/configs/mt8365_defconfig @@ -0,0 +1,15 @@ +CONFIG_MT8365=y +CONFIG_CORE_COUNT=1 +CONFIG_XT_VIRTUAL_OPS=1 +CONFIG_COMP_VOLUME=y +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_TONE=n +CONFIG_COMP_MIXER=n +CONFIG_COMP_MUX=n +CONFIG_COMP_KPB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_ASRC=n diff --git a/src/arch/xtensa/configs/override/mt8186_chrome_dts.config b/src/arch/xtensa/configs/override/mt8186_chrome_dts.config new file mode 100644 index 000000000000..0160eaea199a --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8186_chrome_dts.config @@ -0,0 +1,3 @@ +CONFIG_COMP_IIR=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_DTS_CODEC=y diff --git a/src/arch/xtensa/configs/override/mt8186_chrome_waves.config b/src/arch/xtensa/configs/override/mt8186_chrome_waves.config new file mode 100644 index 000000000000..6e0143275ba6 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8186_chrome_waves.config @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y diff --git a/src/arch/xtensa/configs/override/mt8188_chrome_waves.config b/src/arch/xtensa/configs/override/mt8188_chrome_waves.config new file mode 100644 index 000000000000..6e0143275ba6 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8188_chrome_waves.config @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y diff --git a/src/arch/xtensa/configs/override/mt8195_chrome_dts.config b/src/arch/xtensa/configs/override/mt8195_chrome_dts.config new file mode 100644 index 000000000000..7d91a2206da3 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8195_chrome_dts.config @@ -0,0 +1,4 @@ + +CONFIG_COMP_IIR=y +CONFIG_COMP_CODEC_ADAPTER=y +CONFIG_DTS_CODEC=y diff --git a/src/arch/xtensa/configs/override/mt8195_chrome_google_rtc_rtnr.config b/src/arch/xtensa/configs/override/mt8195_chrome_google_rtc_rtnr.config new file mode 100644 index 000000000000..7a0c166abb57 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8195_chrome_google_rtc_rtnr.config @@ -0,0 +1,3 @@ +CONFIG_COMP_RTNR=y +CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=y +CONFIG_COMP_MUX=y diff --git a/src/arch/xtensa/configs/override/mt8195_chrome_rtnr.config b/src/arch/xtensa/configs/override/mt8195_chrome_rtnr.config new file mode 100644 index 000000000000..96da46bb8baa --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8195_chrome_rtnr.config @@ -0,0 +1 @@ +CONFIG_COMP_RTNR=y diff --git a/src/arch/xtensa/configs/override/mt8196_chrome_dts.config b/src/arch/xtensa/configs/override/mt8196_chrome_dts.config new file mode 100644 index 000000000000..0160eaea199a --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8196_chrome_dts.config @@ -0,0 +1,3 @@ +CONFIG_COMP_IIR=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_DTS_CODEC=y diff --git a/src/arch/xtensa/configs/override/mt8196_chrome_waves.config b/src/arch/xtensa/configs/override/mt8196_chrome_waves.config new file mode 100644 index 000000000000..6e0143275ba6 --- /dev/null +++ b/src/arch/xtensa/configs/override/mt8196_chrome_waves.config @@ -0,0 +1,2 @@ +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_WAVES_CODEC=y diff --git a/src/arch/xtensa/configs/override/renoir_chrome_dts.config b/src/arch/xtensa/configs/override/renoir_chrome_dts.config new file mode 100644 index 000000000000..0160eaea199a --- /dev/null +++ b/src/arch/xtensa/configs/override/renoir_chrome_dts.config @@ -0,0 +1,3 @@ +CONFIG_COMP_IIR=y +CONFIG_COMP_MODULE_ADAPTER=y +CONFIG_DTS_CODEC=y diff --git a/src/arch/xtensa/configs/rembrandt_defconfig b/src/arch/xtensa/configs/rembrandt_defconfig new file mode 100644 index 000000000000..6d5a00745050 --- /dev/null +++ b/src/arch/xtensa/configs/rembrandt_defconfig @@ -0,0 +1,36 @@ +CONFIG_REMBRANDT=y +CONFIG_RIMAGE_SIGNING_SCHEMA="rmb" +CONFIG_TRACE_CHANNEL=7 +CONFIG_WRAP_ACTUAL_POSITION=y +CONFIG_AMD_BT=n +CONFIG_AMD_SP=n +CONFIG_CORE_COUNT=1 +CONFIG_LP_MEMORY_BANKS=0 +CONFIG_HP_MEMORY_BANKS=10 +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_LP_SRAM=n +CONFIG_HAVE_AGENT=n +CONFIG_COMP_VOLUME=n +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_CROSSOVER=n +CONFIG_COMP_DRC=n +CONFIG_COMP_MULTIBAND_DRC=n +CONFIG_COMP_TONE=n +CONFIG_COMP_KPB=n +CONFIG_MAXIM_DSM=n +CONFIG_COMP_ASRC=n +CONFIG_COMP_IGO_NR=n +CONFIG_COMP_COPIER=n +CONFIG_COMP_RTNR=n +CONFIG_COMP_ARIA=n +CONFIG_COMP_BASEFW_IPC4=n +CONFIG_COMP_UP_DOWN_MIXER=n +CONFIG_COMP_TDFB=n +##CONFIG_COMP_MUX=n +CONFIG_COMP_SEL=n +CONFIG_COMP_MIXER=n +CONFIG_PROBE=y +CONFIG_PROBE_POINTS_MAX=16 diff --git a/src/arch/xtensa/configs/renoir_defconfig b/src/arch/xtensa/configs/renoir_defconfig new file mode 100644 index 000000000000..f86a843bdc5d --- /dev/null +++ b/src/arch/xtensa/configs/renoir_defconfig @@ -0,0 +1,12 @@ +CONFIG_RENOIR=y +CONFIG_TRACE_CHANNEL=7 +CONFIG_WRAP_ACTUAL_POSITION=y +CONFIG_AMD_BT=n +CONFIG_CORE_COUNT=1 +CONFIG_LP_MEMORY_BANKS=0 +CONFIG_HP_MEMORY_BANKS=10 +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_LP_SRAM=n +CONFIG_HAVE_AGENT=n +CONFIG_PROBE=y +CONFIG_PROBE_POINTS_MAX=16 \ No newline at end of file diff --git a/src/arch/xtensa/configs/skylake_defconfig b/src/arch/xtensa/configs/skylake_defconfig deleted file mode 100644 index e64db7de2375..000000000000 --- a/src/arch/xtensa/configs/skylake_defconfig +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_APOLLOLAKE=y -CONFIG_FIRMWARE_SHORT_NAME="skl" -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CORE_COUNT=2 -CONFIG_LP_MEMORY_BANKS=2 -CONFIG_HP_MEMORY_BANKS=30 diff --git a/src/arch/xtensa/configs/suecreek_defconfig b/src/arch/xtensa/configs/suecreek_defconfig deleted file mode 100644 index 9650a159ad4a..000000000000 --- a/src/arch/xtensa/configs/suecreek_defconfig +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_SUECREEK=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CORE_COUNT=4 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=47 -CONFIG_OPTIMIZE_FOR_SIZE=y diff --git a/src/arch/xtensa/configs/suecreek_gcc_defconfig b/src/arch/xtensa/configs/suecreek_gcc_defconfig deleted file mode 100644 index d25426ae41bc..000000000000 --- a/src/arch/xtensa/configs/suecreek_gcc_defconfig +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG_SUECREEK=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CORE_COUNT=4 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=47 diff --git a/src/arch/xtensa/configs/tigerlake_defconfig b/src/arch/xtensa/configs/tigerlake_defconfig deleted file mode 100644 index aabcfca06988..000000000000 --- a/src/arch/xtensa/configs/tigerlake_defconfig +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_TIGERLAKE=y -CONFIG_CAVS_DMIC=y -CONFIG_CAVS_SSP=y -CONFIG_CAVS_ALH=y -CONFIG_CAVS_LPRO=y -CONFIG_CORE_COUNT=4 -CONFIG_LP_MEMORY_BANKS=1 -CONFIG_HP_MEMORY_BANKS=46 diff --git a/src/arch/xtensa/configs/unit_test_defconfig b/src/arch/xtensa/configs/unit_test_defconfig new file mode 100644 index 000000000000..afe031acedba --- /dev/null +++ b/src/arch/xtensa/configs/unit_test_defconfig @@ -0,0 +1,2 @@ +CONFIG_METEORLAKE=y +CONFIG_COMP_DRC=y diff --git a/src/arch/xtensa/configs/vangogh_defconfig b/src/arch/xtensa/configs/vangogh_defconfig new file mode 100644 index 000000000000..f022b070de2e --- /dev/null +++ b/src/arch/xtensa/configs/vangogh_defconfig @@ -0,0 +1,28 @@ +CONFIG_VANGOGH=y +CONFIG_RIMAGE_SIGNING_SCHEMA="vangogh" +CONFIG_TRACE_CHANNEL=7 +CONFIG_WRAP_ACTUAL_POSITION=y +CONFIG_AMD_BT=n +CONFIG_CORE_COUNT=1 +CONFIG_LP_MEMORY_BANKS=0 +CONFIG_HP_MEMORY_BANKS=20 +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_LP_SRAM=n +CONFIG_HAVE_AGENT=n +CONFIG_COMP_SRC=n +CONFIG_COMP_FIR=n +CONFIG_COMP_IIR=n +CONFIG_COMP_DCBLOCK=n +CONFIG_COMP_TDFB=n +CONFIG_COMP_TONE=n +CONFIG_COMP_MIXER=n +CONFIG_COMP_MUX=n +CONFIG_COMP_SWITCH=n +CONFIG_COMP_KPB=n +CONFIG_COMP_SEL=n +CONFIG_COMP_ASRC=n +CONFIG_TRACE=y +CONFIG_TRACEE=y +CONFIG_TRACEV=y +CONFIG_PROBE=y +CONFIG_PROBE_POINTS_MAX=16 diff --git a/src/arch/xtensa/debug/CMakeLists.txt b/src/arch/xtensa/debug/CMakeLists.txt deleted file mode 100644 index 2148cd3bd201..000000000000 --- a/src/arch/xtensa/debug/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -if (CONFIG_GDB_DEBUG) - add_subdirectory(gdb) -endif() diff --git a/src/arch/xtensa/debug/gdb/CMakeLists.txt b/src/arch/xtensa/debug/gdb/CMakeLists.txt deleted file mode 100644 index 2718ca511758..000000000000 --- a/src/arch/xtensa/debug/gdb/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof init.S debugexception.S utilities.c) diff --git a/src/arch/xtensa/debug/gdb/debugexception.S b/src/arch/xtensa/debug/gdb/debugexception.S deleted file mode 100644 index d129261256e2..000000000000 --- a/src/arch/xtensa/debug/gdb/debugexception.S +++ /dev/null @@ -1,230 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> - */ - -/* - * Debug context switch. - * - */ - -#include <arch/debug/gdb/xtensa-defs.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/specreg.h> - -#define DENSITY_BREAK_INS_IDENT 0x40 -#define NEXT_INST_OFFSET 0x03 -#define PS_EXCM_EXCEPTION_MODE 0x10 -#define PS_EXCM_MODE_MASK (~PS_EXCM_EXCEPTION_MODE) -#define DEBUG_GDB_MEM_LOC 0x9E008060 - -/* -Save special register designated by 'reg' into -backup space calculated by offset 'loc * 4' from -memory pointed by a3. -*/ -.macro SAVE_ reg, loc - rsr a1, \reg - s32i a1, a3, \loc * 4 -.endm - -.macro SAVE reg - SAVE_ \reg, \reg -.endm - -/* -Load special register designated by 'reg' from -backup space calculated by offset 'loc * 4' from -memory pointed by a3. -*/ -.macro LOAD_ reg, loc - l32i a1, a3, \loc * 4 - wsr a1, \reg -.endm - -.macro LOAD reg - LOAD_ \reg, \reg -.endm - - - -.text - -/* -Temporary stack for context switch -TODO: move it to dedicated GDB_STACK section -*/ - -gdb_stack: - .fill 0x1000 , 4 , 0 -gdb_stack_end: - -.global DebugExceptionEntry -.align 4 - -/* -Backup important special registers plus -all regular ones (whole register file). -Change EXCM field of PS back to normal mode -after an interrupt took place. -*/ -DebugExceptionEntry: - - movi a2, aregs - s32i a0, a2, 0 - s32i a1, a2, 4 - rsr a1, DEBUG_EXCSAVE - s32i a1, a2, 8 - s32i a3, a2, 12 - - movi a3, sregs - SAVE LBEG - SAVE LEND - SAVE LCOUNT - SAVE SAR - SAVE WINDOWBASE - SAVE WINDOWSTART - - rsr a1, DEBUG_PC - l8ui a2, a1, 1 - movi a0, DENSITY_BREAK_INS_IDENT - bne a2, a0, 1f - addi a1, a1, NEXT_INST_OFFSET -1: - s32i a1, a3, DEBUG_PC * 4 - - SAVE EXCSAVE_1 - SAVE_ DEBUG_PS, PS - SAVE EXCCAUSE - SAVE DEBUGCAUSE - SAVE EXCVADDR - - /* - (XCHAL_NUM_AREGS / 4 - 1) - A number which holds information on how many - registers are left to backup. Divide by four since we backup registers - in group of four. Minus one, since one group has already been saved. - */ - movi a1, XCHAL_NUM_AREGS / 4 - 1 - movi a2, aregs -1: - s32i a4, a2, 16 - s32i a5, a2, 20 - s32i a6, a2, 24 - s32i a7, a2, 28 - - addi a6, a2, 16 - addi a5, a1, -1 - rotw 1 - bnez a1, 1b - - movi a1, 1 - wsr a1, windowstart - movi a0, 0 - wsr a0, windowbase - rsync - - /* Setup of stack frame with 20 bytes for extra save area */ - movi a0, 0 - movi a1, gdb_stack + STACK_SIZE - 20 - rsr a2, PS - - /* Set exception mode back to normal */ - movi a3, PS_EXCM_MODE_MASK - and a2, a2, a3 - wsr a2, PS - rsync - - /* reset icountlevel - essential when coming back from single step */ - movi a2, 0x00 - wsr a2, ICOUNTLEVEL - - movi a4, gdb_handle_exception - callx4 a4 - -/* -Restore important special registers plus -all regular ones (whole register file). -Change EXCM field of PS back to exception mode -and return from interrupt. -*/ -DebugExceptionExit: - movi a2, DebugExceptionEntry - wsr a2, DEBUG_EXCSAVE - - rsr a4, PS - movi a3, PS_EXCM_EXCEPTION_MODE - or a4, a4, a3 - wsr a4, PS - rsync - - movi a3, sregs - LOAD LBEG - LOAD LEND - LOAD LCOUNT - LOAD SAR - LOAD WINDOWBASE - rsync - - movi a3, sregs - LOAD WINDOWSTART - LOAD DEBUG_PC - LOAD EXCSAVE_1 - LOAD EXCCAUSE - LOAD EXCVADDR - LOAD INTENABLE - rsync - - movi a6, aregs - movi a5, XCHAL_NUM_AREGS / 4 - 2 -1: - l32i a0, a6, 0 - l32i a1, a6, 4 - l32i a2, a6, 8 - l32i a3, a6, 12 - - beqz a5, 2f - addi a10, a6, 16 - addi a9, a5, -1 - rotw 1 - j 1b -2: - l32i a4, a6, 16 - l32i a5, a6, 20 - l32i a7, a6, 28 - l32i a6, a6, 24 - rotw 2 - - rfi XCHAL_DEBUGLEVEL - - -/* -Put some important interrupt related registers into memory window -pointed by DEBUG_GDB_MEM_LOC -*/ -.global gdb_debug_info -.align 4 - -gdb_debug_info: - - entry a1, 16 - movi a3, DEBUG_GDB_MEM_LOC - l32i a4, a2, 0 //load 4 bytes of message ID from incoming argv - rsr a4, EPC_1 - rsr a5, EPC_2 - rsr a6, EXCCAUSE - rsr a7, DEPC - rsr a8, DEBUG_PS - - s32i a4, a3, 0 - s32i a5, a3, 4 - s32i a6, a3, 8 - s32i a7, a3, 12 - s32i a8, a3, 16 - - isync - rsync - retw - -.size gdb_debug_info, . -gdb_debug_info diff --git a/src/arch/xtensa/debug/gdb/init.S b/src/arch/xtensa/debug/gdb/init.S deleted file mode 100644 index 336816aa41d4..000000000000 --- a/src/arch/xtensa/debug/gdb/init.S +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> - */ - -/* - * Init debug exeption and enable global breakpoints. - * - */ - -#include <arch/debug/gdb/xtensa-defs.h> - -.text -.global gdb_init_debug_exception -.align 4 - -gdb_init_debug_exception: - entry a1, 16 - - movi a3, DebugExceptionEntry - wsr a3, DEBUG_EXCSAVE - - /* enable breakpoints */ - movi a3, 1 - wsr a3, DEBUG_IBREAKENABLE - - isync - rsync - retw - -.size gdb_init_debug_exception, . - gdb_init_debug_exception diff --git a/src/arch/xtensa/debug/gdb/utilities.c b/src/arch/xtensa/debug/gdb/utilities.c deleted file mode 100644 index 35579d763026..000000000000 --- a/src/arch/xtensa/debug/gdb/utilities.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> - -/* - * Xtensa related functions for GDB. - * - */ -#define GDB_DISABLE_LOWER_INTERRUPTS_MASK ~0x1F - -#include <arch/debug/gdb/utilities.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/specreg.h> - -void arch_gdb_read_sr(int sr) -{ - int val; - - asm volatile ("movi a3, 1f + 1\n" - "s8i %1, a3, 0\n" - "dhwb a3, 0\n" - "ihi a3, 0\n" - "isync\n" - "1:\n" - "rsr %0, lbeg\n" - : "=r"(val) - : "r"(sr) - : "a3", "memory"); -} - -void arch_gdb_write_sr(int sr, int *sregs) -{ - asm volatile ("movi a3, 1f + 1\n" - "s8i %1, a3, 0\n" - "dhwb a3, 0\n" - "ihi a3, 0\n" - "isync\n" - "1:\n" - "wsr %0, lbeg\n" - : - : "r"(sregs[sr]), "r"(sr) - : "a3", "memory"); -} - -unsigned char arch_gdb_load_from_memory(void *mem) -{ - unsigned long v; - unsigned long addr = (unsigned long)mem; - unsigned char ch; - - asm volatile ("_l32i %0, %1, 0\n" - : "=r"(v) - : "r"(addr & ~3) - : "memory"); - ch = v >> (addr & 3) * 8; - - return ch; -} - -void arch_gdb_memory_load_and_store(void *mem, unsigned char ch) -{ - unsigned long tmp; - unsigned long addr = (unsigned long)mem; - - asm volatile ("_l32i %0, %1, 0\n" - "and %0, %0, %2\n" - "or %0, %0, %3\n" - "_s32i %0, %1, 0\n" - "dhwb %1, 0\n" - "ihi %1, 0\n" - : "=&r"(tmp) - : "r"(addr & ~3), "r"(0xffffffff ^ (0xff << - (addr & 3) * 8)), - "r"(ch << (addr & 3) * 8) - : "memory"); -} - -void arch_gdb_single_step(int *sregs) -{ - /* leave debug just for one instruction */ - sregs[ICOUNT] = 0xfffffffe; - sregs[ICOUNTLEVEL] = XCHAL_DEBUGLEVEL; - /* disable low level interrupts */ - sregs[INTENABLE] &= ~GDB_DISABLE_LOWER_INTERRUPTS_MASK; - arch_gdb_write_sr(ICOUNTLEVEL, sregs); - arch_gdb_write_sr(ICOUNT, sregs); - arch_gdb_write_sr(INTENABLE, sregs); -} diff --git a/src/arch/xtensa/drivers/CMakeLists.txt b/src/arch/xtensa/drivers/CMakeLists.txt deleted file mode 100644 index 90376763c3ee..000000000000 --- a/src/arch/xtensa/drivers/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof interrupt.c timer.c) diff --git a/src/arch/xtensa/drivers/cache_attr.c b/src/arch/xtensa/drivers/cache_attr.c new file mode 100644 index 000000000000..265afe0b3ac4 --- /dev/null +++ b/src/arch/xtensa/drivers/cache_attr.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Iuliana Prodan <iuliana.prodan@nxp.com> + +#ifdef CONFIG_COMPILER_WORKAROUND_CACHE_ATTR + +#include <xtensa/config/core.h> +#include <sof/drivers/cache_attr.h> + +/* + * We want to avoid buggy compiler optimization (function inlining). + * So we replace the call to glb_addr_attr() from glb_is_cached() + * with a function pointer that is initialized here. + */ +uint32_t (*get_addr_attr)(void *address) = glb_addr_attr; + +/* + * The _memmap_cacheattr_reset linker script variable has + * dedicate cache attribute for every 512M in 4GB space + * 1: write through + * 2: cache bypass + * 4: write back + * F: invalid access + */ + +/* + * Since each hex digit keeps the attributes for a 512MB region, + * we have the following address ranges: + * Address range - hex digit + * 0 - 1FFFFFFF - 0 + * 20000000 - 3FFFFFFF - 1 + * 40000000 - 5FFFFFFF - 2 + * 60000000 - 7FFFFFFF - 3 + * 80000000 - 9FFFFFFF - 4 + * A0000000 - BFFFFFFF - 5 + * C0000000 - DFFFFFFF - 6 + * E0000000 - FFFFFFFF - 7 + */ + +/* + * For the given address, get the corresponding hex digit + * from the linker script variable that contains the cache attributes + */ +uint32_t glb_addr_attr(void *address) +{ + uint32_t addr_attr = xthal_get_cacheattr(); + + /* Based on the above information, get the address region id (0-7) */ + uint32_t addr_shift = ((uint32_t)(uintptr_t)address) >> 29; + + addr_shift &= 0x7; + + /* Get the position of the cache attribute for a certain memory region. + * There are 4 bits per hex digit. + */ + addr_shift <<= 2; + + /* Get the corresponding hex digit from the linker script + * variable that contains the cache attributes of the address region + */ + addr_attr >>= addr_shift; + addr_attr &= 0xF; + + return addr_attr; +} + +/* + * Check if the address is cacheable or not, by verifying the addr_attr, + * which for cacheable addresses might be 1 or 4 + */ +uint32_t glb_is_cached(void *address) +{ + /* Do not call glb_addr_attr() directly + * to avoid buggy compiler optimizations + */ + uint32_t addr_attr = get_addr_attr(address); + + if (addr_attr == 1 || addr_attr == 4) + return 1; + + return 0; +} +#endif /* CONFIG_COMPILER_WORKAROUND_CACHE_ATTR */ diff --git a/src/arch/xtensa/drivers/interrupt.c b/src/arch/xtensa/drivers/interrupt.c deleted file mode 100644 index 16269fd09d2f..000000000000 --- a/src/arch/xtensa/drivers/interrupt.c +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2020 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/drivers/interrupt.h> - -#if CONFIG_WAKEUP_HOOK -void arch_interrupt_on_wakeup(void) -{ - platform_interrupt_on_wakeup(); -} -#endif diff --git a/src/arch/xtensa/drivers/timer.c b/src/arch/xtensa/drivers/timer.c deleted file mode 100644 index 9169196807c2..000000000000 --- a/src/arch/xtensa/drivers/timer.c +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/hal.h> -#include <errno.h> -#include <stdint.h> - -void timer_64_handler(void *arg) -{ - struct timer *timer = arg; - uint32_t ccompare; - - if (timer->id >= ARCH_TIMER_COUNT) - goto out; - - /* get comparator value - will tell us timeout reason */ - ccompare = xthal_get_ccompare(timer->id); - - /* is this a 32 bit rollover ? */ - if (ccompare == 1) { - /* roll over the timer */ - timer->hitime++; - arch_timer_clear(timer); - } else { - /* no roll over, run the handler */ - timer->handler(timer->data); - } - - /* get next timeout value */ - if (timer->hitimeout == timer->hitime) { - /* timeout is in this 32 bit period */ - ccompare = timer->lowtimeout; - } else { - /* timeout is in another 32 bit period */ - ccompare = 1; - } - - xthal_set_ccompare(timer->id, ccompare); - -out: - platform_shared_commit(timer, sizeof(*timer)); -} - -int timer64_register(struct timer *timer, void(*handler)(void *arg), void *arg) -{ - if (timer->id >= ARCH_TIMER_COUNT) - return -EINVAL; - - timer->handler = handler; - timer->data = arg; - timer->hitime = 0; - timer->hitimeout = 0; - - return 0; -} - -uint64_t arch_timer_get_system(struct timer *timer) -{ - uint64_t time = 0; - uint32_t flags; - uint32_t low; - uint32_t high; - uint32_t ccompare; - - if (timer->id >= ARCH_TIMER_COUNT) - goto out; - - ccompare = xthal_get_ccompare(timer->id); - - flags = arch_interrupt_global_disable(); - - /* read low 32 bits */ - low = xthal_get_ccount(); - - /* check and see whether 32bit IRQ is pending for timer */ - if (arch_interrupt_get_status() & (1 << timer->irq) && ccompare == 1) { - /* yes, overflow has occured but handler has not run */ - high = timer->hitime + 1; - } else { - /* no overflow */ - high = timer->hitime; - } - - time = ((uint64_t)high << 32) | low; - - arch_interrupt_global_enable(flags); - -out: - platform_shared_commit(timer, sizeof(*timer)); - - return time; -} - -int64_t arch_timer_set(struct timer *timer, uint64_t ticks) -{ - uint32_t time = 1; - uint32_t hitimeout = ticks >> 32; - uint32_t flags; - int64_t ret; - - if (timer->id >= ARCH_TIMER_COUNT) { - ret = -EINVAL; - goto out; - } - - /* value of 1 represents rollover */ - if ((ticks & 0xffffffff) == 0x1) - ticks++; - - flags = arch_interrupt_global_disable(); - - /* same hi 64 bit context as ticks ? */ - if (hitimeout < timer->hitime) { - /* cant be in the past */ - arch_interrupt_global_enable(flags); - ret = -EINVAL; - goto out; - } - - /* set for checking at next timeout */ - time = ticks; - timer->hitimeout = hitimeout; - timer->lowtimeout = ticks; - - xthal_set_ccompare(timer->id, time); - - arch_interrupt_global_enable(flags); - - ret = ticks; - -out: - platform_shared_commit(timer, sizeof(*timer)); - - return ret; -} diff --git a/src/arch/xtensa/exc-dump.S b/src/arch/xtensa/exc-dump.S deleted file mode 100644 index cb9746c0af42..000000000000 --- a/src/arch/xtensa/exc-dump.S +++ /dev/null @@ -1,152 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - */ - -#include <arch/debug/offset-defs.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/corebits.h> - - .section .text, "ax" - .align 64 -literals: - .literal_position - .global arch_dump_regs_a - .type arch_dump_regs_a, @function - -/* - * params: - * a2 - ptr to dump mem buffer - */ -arch_dump_regs_a: - entry a1, 16 - - /* all accessible physical registers */ - - s32i a0, a2, REG_OFFSET_AR_BEGIN - s32i a1, a2, REG_OFFSET_AR_BEGIN + 0x4 - s32i a2, a2, REG_OFFSET_AR_BEGIN + 0x8 - s32i a3, a2, REG_OFFSET_AR_BEGIN + 0xc - s32i a4, a2, REG_OFFSET_AR_BEGIN + 0x10 - s32i a5, a2, REG_OFFSET_AR_BEGIN + 0x14 - s32i a6, a2, REG_OFFSET_AR_BEGIN + 0x18 - s32i a7, a2, REG_OFFSET_AR_BEGIN + 0x1c - memw - - /* store PS */ - rsr a3, PS - s32i a3, a2, REG_OFFSET_PS - - /* - * copy original a2 to a3 as we will increment it in the loop with - * offset to AR registers with addition of 8 registers already read. - * It will be the base for next reg dump - */ - movi a3, REG_OFFSET_AR_BEGIN + 8*4 - add a3, a2, a3 - - /* - * storing rest of AREGS starts here - * a4 - number of 8-reg chunks to save (a0-a7 already done) - */ - movi a4, XCHAL_NUM_AREGS / 8 - 1 - - /* set exception mode if we are on core 0 */ - rsr a6, PRID - bnez a6, mask_interrupts_on_core0 - movi a5, PS_EXCM | PS_INTLEVEL(0x5) - wsr a5, PS - rsync - - /* exception mode set so no need to set interrupt mask */ - j store_register_loop - -mask_interrupts_on_core0: - /* - * if we are in core context different than 0 - * disable interrupts on core 0 - * only level 2 interrupts disabled for now on - */ - /* TODO */ - -store_register_loop: - s32i a8, a3, 0 - s32i a9, a3, 4 - s32i a10, a3, 8 - s32i a11, a3, 0xc - s32i a12, a3, 0x10 - s32i a13, a3, 0x14 - s32i a14, a3, 0x18 - s32i a15, a3, 0x1c - - addi a11, a3, 32 // after rotation a11 will be next a3 - addi a12, a4, -1 // after rotation a12 will be next a4 - iter decrement - /* - * restore registers from current window to preserve backtrace - * upon return - */ - addi a3, a3, -20 - l32i a4, a3, 4 - l32i a3, a3, 0 - rotw 2 - bnez a4, store_register_loop - rotw 2 - memw - -dump_special_registers: - rsr a6, EPC2 - s32i a6, a2, REG_OFFSET_EPC2 - rsr a6, EPC3 - s32i a6, a2, REG_OFFSET_EPC3 - rsr a6, EPC4 - s32i a6, a2, REG_OFFSET_EPC4 - rsr a6, EPC5 - s32i a6, a2, REG_OFFSET_EPC5 -#if XCHAL_INTLEVEL6_MASK - rsr a6, EPC6 - s32i a6, a2, REG_OFFSET_EPC6 -#endif -#if XCHAL_INTLEVEL7_MASK - rsr a6, EPC7 - s32i a6, a2, REG_OFFSET_EPC7 -#endif - rsr a6, EPS2 - s32i a6, a2, REG_OFFSET_EPS2 - rsr a6, EPS3 - s32i a6, a2, REG_OFFSET_EPS3 - rsr a6, EPS4 - s32i a6, a2, REG_OFFSET_EPS4 - rsr a6, EPS5 - s32i a6, a2, REG_OFFSET_EPS5 -#if XCHAL_INTLEVEL6_MASK - rsr a6, EPS6 - s32i a6, a2, REG_OFFSET_EPS6 -#endif -#if XCHAL_INTLEVEL7_MASK - rsr a6, EPS7 - s32i a6, a2, REG_OFFSET_EPS7 -#endif - rsr a6, DEPC - s32i a6, a2, REG_OFFSET_DEPC - rsr a6, DEBUGCAUSE - s32i a6, a2, REG_OFFSET_DEBUGCAUSE - rsr a6, EXCCAUSE - s32i a6, a2, REG_OFFSET_EXCCAUSE - rsr a6, INTERRUPT - s32i a6, a2, REG_OFFSET_INTERRUPT - rsr a6, EXCVADDR - s32i a6, a2, REG_OFFSET_EXCVADDR - rsr a6, EXCSAVE1 - s32i a6, a2, REG_OFFSET_EXCSAVE1 - rsr a6, WINDOWBASE - s32i a6, a2, REG_OFFSET_WINDOWBASE - rsr a6, WINDOWSTART - s32i a6, a2, REG_OFFSET_WINDOWSTART - - /* restore processor_state */ -restore_processor_state: - /* restore previously saved PS before return */ - l32i a3, a2, REG_OFFSET_PS - wsr a3, PS - rsync - retw diff --git a/src/arch/xtensa/hal/CMakeLists.txt b/src/arch/xtensa/hal/CMakeLists.txt deleted file mode 100644 index 66281a9bb3df..000000000000 --- a/src/arch/xtensa/hal/CMakeLists.txt +++ /dev/null @@ -1,159 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -set(STATE_DEFS - -D__SPLIT__extra_size - -D__SPLIT__extra_align - -D__SPLIT__cpregs_size - -D__SPLIT__cpregs_align - -D__SPLIT__cp_names - -D__SPLIT__all_extra_size - -D__SPLIT__all_extra_align - -D__SPLIT__num_coprocessors - -D__SPLIT__cp_num - -D__SPLIT__cp_max - -D__SPLIT__cp_mask - -D__SPLIT__cp_id_mappings - -D__SPLIT__cp_mask_mappings - -D__SPLIT__init_mem_extra - -D__SPLIT__init_mem_cp - -D__SPLIT__save_extra - -D__SPLIT__restore_extra - -D__SPLIT__save_cpregs - -D__SPLIT__save_cp0 - -D__SPLIT__save_cp1 - -D__SPLIT__save_cp2 - -D__SPLIT__save_cp3 - -D__SPLIT__save_cp4 - -D__SPLIT__save_cp5 - -D__SPLIT__save_cp6 - -D__SPLIT__save_cp7 - -D__SPLIT__restore_cpregs - -D__SPLIT__restore_cp0 - -D__SPLIT__restore_cp1 - -D__SPLIT__restore_cp2 - -D__SPLIT__restore_cp3 - -D__SPLIT__restore_cp4 - -D__SPLIT__restore_cp5 - -D__SPLIT__restore_cp6 - -D__SPLIT__restore_cp7 - -D__SPLIT__cpregs_save_fn - -D__SPLIT__cpregs_restore_fn - -D__SPLIT__validate_cp - -D__SPLIT__invalidate_cp - -D__SPLIT__get_cpenable - -D__SPLIT__set_cpenable -) - -set(DISASS_DEFS - -D__SPLIT__op0_format_lengths - -D__SPLIT__byte0_format_lengths - -D__SPLIT__disassemble_size - -D__SPLIT__disassemble -) - -set(MISC_DEFS - -D__SPLIT__clear_regcached_code -) - -# Call0 ABI means the xthal... and xthal..._nw functions are -# identical. If we're building for Call0 ABI, omit the ..._nw -# functions (except for xthal_get_intpending_nw, an interrupt handler -# helper function for which there is no duplicate and which does not -# obey _any_ calling conventions). -set(INTERRUPTS_DEFS - -D__SPLIT__num_intlevels - -D__SPLIT__num_interrupts - -D__SPLIT__excm_level - -D__SPLIT__intlevel - -D__SPLIT__get_intenable - -D__SPLIT__set_intenable - -D__SPLIT__get_interrupt - -D__SPLIT__set_intset - -D__SPLIT__set_intclear -) - -set(CACHE_DEFS - -D__SPLIT__get_cacheattr - -D__SPLIT__get_icacheattr - -D__SPLIT__set_cacheattr - -D__SPLIT__set_icacheattr - -D__SPLIT__set_dcacheattr - -D__SPLIT__set_idcacheattr - -D__SPLIT__idcache_is_enabled - -D__SPLIT__icache_is_enabled - -D__SPLIT__dcache_is_enabled - -D__SPLIT__idcache_is_enabled - -D__SPLIT__icache_all_invalidate - -D__SPLIT__dcache_all_invalidate - -D__SPLIT__dcache_all_writeback - -D__SPLIT__dcache_all_writeback_inv - -D__SPLIT__icache_all_unlock - -D__SPLIT__dcache_all_unlock - -D__SPLIT__icache_region_invalidate - -D__SPLIT__dcache_region_invalidate - -D__SPLIT__dcache_region_writeback - -D__SPLIT__dcache_region_writeback_inv - -D__SPLIT__icache_region_lock - -D__SPLIT__dcache_region_lock - -D__SPLIT__icache_region_unlock - -D__SPLIT__dcache_region_unlock - -D__SPLIT__icache_line_invalidate - -D__SPLIT__dcache_line_invalidate - -D__SPLIT__dcache_line_writeback - -D__SPLIT__dcache_line_writeback_inv - -D__SPLIT__icache_line_lock - -D__SPLIT__dcache_line_lock - -D__SPLIT__icache_line_unlock - -D__SPLIT__dcache_line_unlock - -D__SPLIT__icache_sync - -D__SPLIT__dcache_sync - -D__SPLIT__icache_get_ways - -D__SPLIT__icache_set_ways - -D__SPLIT__dcache_get_ways - -D__SPLIT__dcache_set_ways - -D__SPLIT__cache_coherence_on - -D__SPLIT__cache_coherence_off - -D__SPLIT__set_cache_prefetch_long - -D__SPLIT__set_cache_prefetch - -D__SPLIT__get_cache_prefetch - -D__SPLIT__hw_configid0 - -D__SPLIT__hw_configid1 - -D__SPLIT__release_major - -D__SPLIT__release_minor -) - -add_library(hal STATIC "") -target_link_libraries(hal sof_options) -target_compile_definitions(hal PRIVATE - ${STATE_DEFS} - ${DISASS_DEFS} - ${MISC_DEFS} - ${INTERRUPTS_DEFS} - ${CACHE_DEFS} -) - -add_local_sources(hal - attribute.c - cache.c - cache_asm.S - clock.S - coherence.c - debug.c - debug_hndlr.S - disass.c - int_asm.S - interrupts.c - memcopy.S - mem_ecc_parity.S - misc.c - miscellaneous.S - mmu.c - mp_asm.S - mpu_asm.S - mpu.c - set_region_translate.c - state_asm.S - state.c - syscache_asm.S - windowspill_asm.S -) diff --git a/src/arch/xtensa/hal/attribute.c b/src/arch/xtensa/hal/attribute.c deleted file mode 100644 index 7d663b2e55fe..000000000000 --- a/src/arch/xtensa/hal/attribute.c +++ /dev/null @@ -1,282 +0,0 @@ -/* attribute.c - Cache attribute (memory access mode) related functions */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/attribute.c#1 $ */ - -/* - * Copyright (c) 2004-2009 Tensilica 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 <xtensa/config/core.h> - - - -/* - * Set the "cache attribute" (encoded memory access modes) - * of the region of memory specified by <vaddr> and <size>. - * - * This function is only supported on processor configurations - * with region protection (or XEA1). It has no effect on - * a processor configured with an MMU (with autorefill). - * - * SPECIFYING THE MEMORY REGION - * The full (4 GB) address space may be specified with an - * address of zero and a size of 0xFFFFFFFF (or -1); - * in fact whenever <vaddr>+<size> equal 0xFFFFFFFF, <size> - * is interpreted as one byte greater than that specified. - * - * If the specified memory range exactly covers a series - * of consecutive 512 MB regions, the cache attributes of - * these regions are updated with the requested attribute. - * If this is not the case, e.g. if either or both the - * start and end of the range only partially cover a 512 MB - * region, one of three results are possible: - * - * 1. By default, the cache attribute of all regions - * covered, even just partially, is changed to - * the requested attribute. - * - * 2. If the XTHAL_CAFLAG_EXACT flag is specified, - * a non-zero error code is returned. - * - * 3. If the XTHAL_CAFLAG_NO_PARTIAL flag is specified - * (but not the EXACT flag), only regions fully - * covered by the specified range are updated with - * the requested attribute. - * - * WRITEBACK CACHE HANDLING - * This function automatically writes back dirty data when - * switching a region from writeback mode to a non-writeback mode. - * This writeback is done safely, ie. by first switching to writethrough - * mode, then invoking xthal_dcache_all_writeback(), then switching to - * the selected <cattr> mode. Such a sequence is necessary to ensure - * there is no longer any dirty data in the memory region by the time - * this function returns, even in the presence of interrupts, speculation, etc. - * This avoids memory coherency problems when switching from writeback - * to bypass mode (in bypass mode, loads go directly to memory, ignoring - * any dirty data in the cache; also, such dirty data can still be castout - * due to seemingly unrelated stores). - * This automatic write-back can be disabled using the XTHAL_CAFLAG_NO_AUTO_WB flag. - * - * CACHE DISABLE THEN ENABLE HANDLING - * To avoid cache coherency issues when the cache is disabled, then - * memory is modified, then then cache is re-enabled (thus making - * visible stale cache entries), this function automatically - * invalidates the cache when any region switches to bypass mode. - * For efficiency, the entire cache is invalidated -- this is done - * using writeback-invalidate operations to ensure coherency even - * when other regions still have write-back caches enabled. - * This automatic invalidate can be disabled using the XTHAL_CAFLAG_NO_AUTO_INV flag. - * - * Parameters: - * vaddr starting virtual address of region of memory - * - * size number of bytes in region of memory - * (see above, SPECIFYING THE MEMORY REGION) - * - * cattr cache attribute (encoded); - * typically taken from compile-time HAL constants - * XCHAL_CA_{BYPASS[BUF], WRITETHRU, WRITEBACK[_NOALLOC], ILLEGAL} - * (defined in <xtensa/config/core.h>); - * in XEA1, this corresponds to the value of a nibble - * in the CACHEATTR register; - * in XEA2, this corresponds to the value of the - * cache attribute (CA) field of each TLB entry - * - * On MPU configurations, the cattr is composed of accessRights - * and memoryType. The accessRights occupy bits 0..3 and are - * typically taken from the XTHAL_AR constants. The memory type - * is specified by either a bitwise or-ing of the XTHAL_MEM_... - * constants or if none of the XTHAL_MEM_... constants are - * specified, bits 4..12 are used for the memory type (that - * allows a cattr obtained by xthal_v2p() to be passed directly. - * - * In addition on MPU configurations if the - * XTHAL_MPU_USE_EXISTING_MEMORY_TYPE bit is set then the existing - * memoryType at the first address in the region is used for the - * memoryType of the new region. - * - * Likewise, if the XTHAL_MPU_USE_EXISTING_ACCESS_RIGHTS bit is set - * in cattr, then the existing accessRights at the first address - * in the region are used for the accessRights of the new region. - * - * flags bitwise combination of flags XTHAL_CAFLAG_* - * (see xtensa/hal.h for brief description of each flag); - * (see also various descriptions above); - * - * The XTHAL_CAFLAG_EXPAND flag prevents attribute changes - * to regions whose current cache attribute already provide - * greater access than the requested attribute. - * This ensures access to each region can only "expand", - * and thus continue to work correctly in most instances, - * possibly at the expense of performance. This helps - * make this flag safer to use in a variety of situations. - * For the purposes of this flag, cache attributes are - * ordered (in "expansion" order, from least to greatest - * access) as follows: - * XCHAL_CA_ILLEGAL no access allowed - * (various special and reserved attributes) - * XCHAL_CA_WRITEBACK writeback cached - * XCHAL_CA_WRITEBACK_NOALLOC writeback no-write-alloc - * XCHAL_CA_WRITETHRU writethrough cached - * XCHAL_CA_BYPASSBUF bypass with write buffering - * XCHAL_CA_BYPASS bypass (uncached) - * This is consistent with requirements of certain - * devices that no caches be used, or in certain cases - * that writethrough caching is allowed but not writeback. - * Thus, bypass mode is assumed to work for most/all types - * of devices and memories (albeit at reduced performance - * compared to cached modes), and is ordered as providing - * greatest access (to most devices). - * Thus, this XTHAL_CAFLAG_EXPAND flag has no effect when - * requesting the XCHAL_CA_BYPASS attribute (one can always - * expand to bypass mode). And at the other extreme, - * no action is ever taken by this function when specifying - * both the XTHAL_CAFLAG_EXPAND flag and the XCHAL_CA_ILLEGAL - * cache attribute. - * - * The XTHAL_CAFLAG_EXPAND is not supported on MPU configurations. - * - * Returns: - * 0 successful, or size is zero - * -1 XTHAL_CAFLAG_NO_PARTIAL flag specified and address range - * is valid with a non-zero size, however no 512 MB region (or page) - * is completely covered by the range - * -2 XTHAL_CAFLAG_EXACT flag specified, and address range does - * not exactly specify a 512 MB region (or page) - * -3 invalid address range specified (wraps around the end of memory) - * -4 function not supported in this processor configuration - */ -int xthal_set_region_attribute( void *vaddr, unsigned size, unsigned cattr, unsigned flags ) -{ -#if XCHAL_HAVE_MPU - if (cattr & 0xffffe000) // check if XTHAL mem flags were supplied - // in this case just pass cattr as the memType paramenter - return xthal_mpu_set_region_attribute(vaddr, size, cattr, cattr, flags); - else - // otherwise we take the bits 0-3 for accessRights and bits 4-13 as the memoryType - return xthal_mpu_set_region_attribute(vaddr, size, cattr & 0xf, (cattr & 0x1ff0) >> 4, flags); -#elif XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY - return -4; /* full MMU not supported */ -#else -/* These cache attribute encodings are valid for XEA1 and region protection only: */ -# if XCHAL_HAVE_PTP_MMU -# define CA_BYPASS XCHAL_CA_BYPASS -# ifdef XCHAL_CA_BYPASSBUF -# define CA_BYPASSBUF XCHAL_CA_BYPASSBUF -# else -# define CA_BYPASSBUF XCHAL_CA_BYPASS -# endif -# define CA_WRITETHRU XCHAL_CA_WRITETHRU -# define CA_WRITEBACK XCHAL_CA_WRITEBACK -# define CA_WRITEBACK_NOALLOC XCHAL_CA_WRITEBACK_NOALLOC -# define CA_ILLEGAL XCHAL_CA_ILLEGAL -# else -/* Hardcode these, because they get remapped when caches or writeback not configured: */ -# define CA_BYPASS 2 -# define CA_BYPASSBUF 6 -# define CA_WRITETHRU 1 -# define CA_WRITEBACK 4 -# define CA_WRITEBACK_NOALLOC 5 -# define CA_ILLEGAL 15 -# endif -# define CA_MASK 0xF /*((1L<<XCHAL_CA_BITS)-1)*/ /* mask of cache attribute bits */ -# define IS_CACHED(attr) ((attr == CA_BYPASS) || (attr == CA_BYPASSBUF)) - - unsigned start_region, start_offset, end_vaddr, end_region, end_offset; - unsigned cacheattr, cachewrtr, i, disabled_cache = 0; - - if (size == 0) - return 0; - end_vaddr = (unsigned)vaddr + size - 1; - if (end_vaddr < (unsigned)vaddr) - return -3; /* address overflow/wraparound error */ - if (end_vaddr == 0xFFFFFFFE /*&& (unsigned)vaddr == 0*/ ) - end_vaddr = 0xFFFFFFFF; /* allow specifying 4 GB */ - start_region = ((unsigned)vaddr >> 29); - start_offset = ((unsigned)vaddr & 0x1FFFFFFF); - end_region = (end_vaddr >> 29); - end_offset = ((end_vaddr+1) & 0x1FFFFFFF); - if (flags & XTHAL_CAFLAG_EXACT) { - if (start_offset != 0 || end_offset != 0) - return -2; /* not an exact-sized range */ - } else if (flags & XTHAL_CAFLAG_NO_PARTIAL) { - if (start_offset != 0) - start_region++; - if (end_offset != 0) - end_region--; - if (start_region > end_region) - return -1; /* nothing fully covered by specified range */ - } - cacheattr = cachewrtr = xthal_get_cacheattr(); - cattr &= CA_MASK; -# if XCHAL_ICACHE_SIZE == 0 && XCHAL_DCACHE_SIZE == 0 - if (cattr == CA_WRITETHRU || cattr == CA_WRITEBACK || cattr == CA_WRITEBACK_NOALLOC) - cattr = CA_BYPASS; /* no caches configured, only do protection */ -# elif XCHAL_DCACHE_IS_WRITEBACK == 0 - if (cattr == CA_WRITEBACK || cattr == CA_WRITEBACK_NOALLOC) - cattr = CA_WRITETHRU; /* no writeback configured for data cache */ -# endif - for (i = start_region; i <= end_region; i++) { - unsigned sh = (i << 2); /* bit offset of nibble for region i */ - unsigned oldattr = ((cacheattr >> sh) & CA_MASK); - unsigned newattr = cattr; - if (flags & XTHAL_CAFLAG_EXPAND) { - /* This array determines whether a cache attribute can be changed - * from <a> to <b> with the EXPAND flag; an attribute's "pri" - * value (from this array) can only monotonically increase: */ - const static signed char _Xthal_ca_pri[16] = {[CA_ILLEGAL] = -1, - [CA_WRITEBACK] = 3, [CA_WRITEBACK_NOALLOC] = 3, [CA_WRITETHRU] = 4, [CA_BYPASSBUF] = 8, [CA_BYPASS] = 9 }; - if (_Xthal_ca_pri[newattr] < _Xthal_ca_pri[oldattr]) - newattr = oldattr; /* avoid going to lesser access */ - } - if (IS_CACHED(newattr) && !IS_CACHED(oldattr)) - disabled_cache = 1; /* we're disabling the cache for some region */ -# if XCHAL_DCACHE_IS_WRITEBACK - { - unsigned tmpattr = newattr; - if ((oldattr == CA_WRITEBACK || oldattr == CA_WRITEBACK_NOALLOC) - && newattr != CA_WRITEBACK && newattr != CA_WRITEBACK_NOALLOC) /* leaving writeback mode? */ - tmpattr = CA_WRITETHRU; /* leave it safely! */ - cachewrtr = ((cachewrtr & ~(CA_MASK << sh)) | (tmpattr << sh)); - } -# endif - cacheattr = ((cacheattr & ~(CA_MASK << sh)) | (newattr << sh)); - } -# if XCHAL_DCACHE_IS_WRITEBACK - if (cacheattr != cachewrtr /* need to leave writeback safely? */ - && (flags & XTHAL_CAFLAG_NO_AUTO_WB) == 0) { - xthal_set_cacheattr(cachewrtr); /* set to writethru first, to safely writeback any dirty data */ - xthal_dcache_all_writeback(); /* much quicker than scanning entire 512MB region(s) */ - } -# endif - xthal_set_cacheattr(cacheattr); - /* After disabling the cache, invalidate cache entries - * to avoid coherency issues when later re-enabling it: */ - if (disabled_cache && (flags & XTHAL_CAFLAG_NO_AUTO_INV) == 0) { - xthal_dcache_all_writeback_inv(); /* we might touch regions of memory still enabled write-back, - so must use writeback-invalidate, not just invalidate */ - xthal_icache_all_invalidate(); - } - return( 0 ); -#endif /* !(XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY) */ -} - diff --git a/src/arch/xtensa/hal/cache.c b/src/arch/xtensa/hal/cache.c deleted file mode 100644 index 4f6e292e6153..000000000000 --- a/src/arch/xtensa/hal/cache.c +++ /dev/null @@ -1,53 +0,0 @@ -// -// cache.c -- cache management routines -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/cache.c#1 $ - -// Copyright (c) 2002 Tensilica 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 <xtensa/config/core.h> - -// size of the cache lines in log2(bytes) -const unsigned char Xthal_icache_linewidth = XCHAL_ICACHE_LINEWIDTH; -const unsigned char Xthal_dcache_linewidth = XCHAL_DCACHE_LINEWIDTH; - -// size of the cache lines in bytes -const unsigned short Xthal_icache_linesize = XCHAL_ICACHE_LINESIZE; -const unsigned short Xthal_dcache_linesize = XCHAL_DCACHE_LINESIZE; - -// number of cache sets in log2(lines per way) -const unsigned char Xthal_icache_setwidth = XCHAL_ICACHE_SETWIDTH; -const unsigned char Xthal_dcache_setwidth = XCHAL_DCACHE_SETWIDTH; - -// cache set associativity (number of ways) -const unsigned int Xthal_icache_ways = XCHAL_ICACHE_WAYS; -const unsigned int Xthal_dcache_ways = XCHAL_DCACHE_WAYS; - -// size of the caches in bytes (ways * 2^(linewidth + setwidth)) -const unsigned int Xthal_icache_size = XCHAL_ICACHE_SIZE; -const unsigned int Xthal_dcache_size = XCHAL_DCACHE_SIZE; - -// cache features -const unsigned char Xthal_dcache_is_writeback = XCHAL_DCACHE_IS_WRITEBACK; -const unsigned char Xthal_icache_line_lockable = XCHAL_ICACHE_LINE_LOCKABLE; -const unsigned char Xthal_dcache_line_lockable = XCHAL_DCACHE_LINE_LOCKABLE; - diff --git a/src/arch/xtensa/hal/cache_asm.S b/src/arch/xtensa/hal/cache_asm.S deleted file mode 100644 index 9bb10438936b..000000000000 --- a/src/arch/xtensa/hal/cache_asm.S +++ /dev/null @@ -1,1073 +0,0 @@ -// -// cache_asm.S - assembly language cache management routines -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/cache_asm.S#1 $ - -// Copyright (c) 1999-2015 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 <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/xtensa-versions.h> - - - - -//---------------------------------------------------------------------- -// Huge Range cache routines -//---------------------------------------------------------------------- - - // void xthal_dcache_hugerange_<name>(void *addr, unsigned size); - // - // Invalidate and/or writeback dcache entries for an arbitrary large - // virtual address range with a single scan of the dcache. - // Assumes no address translation, i.e. virtual = physical. - // - // a2 = ptr to range - // a3 = size of range - // - // Note: -128 is a valid immediate for ADDI, but +128 is not, - // and ADDI can relax to ADDMI for multiples of 256. So scanning - // cache backwards (from end to start) allows all cache line sizes - // without creating an extra instruction for the ADDI. - // - .macro dcache_hugefunc name, instruction - .text - .align 4 - .type xthal_dcache_hugerange_\name,@function - .global xthal_dcache_hugerange_\name -xthal_dcache_hugerange_\name: - abi_entry -#if (!defined(XCHAL_HAVE_NX) || XCHAL_HAVE_NX == 0) && XCHAL_DCACHE_SIZE > 0 \ - && XCHAL_HAVE_DCACHE_TEST && XCHAL_HAVE_MINMAX && XCHAL_HAVE_LOOPS - movi a4, XCHAL_DCACHE_SIZE*2 // size at which to use huge algorithm - movi a7, -XCHAL_DCACHE_LINESIZE // for rounding to cache line size - bltu a3, a4, 7f // use normal (line-by-line hit) function -#if XCHAL_HAVE_PREFETCH - movi a11, 0 - xsr.prefctl a11 // temporarily disable prefetch (invalidates prefetch bufs!) -#endif - add a5, a3, a2 // a5 = end of range - and a4, a2, a7 // a4 = low end, rounded to containing cache line - addi a5, a5, /*XCHAL_DCACHE_LINESIZE*/-1 - and a5, a5, a7 // a5 = high end, rounded to containing cache line - movi a7, XCHAL_DCACHE_SIZE/XCHAL_DCACHE_LINESIZE // a7 = number of lines in dcache - movi a3, XCHAL_DCACHE_SIZE-XCHAL_DCACHE_LINESIZE // way index - mov a6, a5 - //movi a8, -XCHAL_DCACHE_SETSIZE // use if LDCT gives non-zero index bits - movi a10, (XCHAL_DCACHE_SIZE/XCHAL_DCACHE_WAYS) - 1 - - loopgtz a7, 1f - ldct a7, a3 // a3 = cache tag for cache entry [a7] - \instruction a2, 0 - .begin schedule - //extui a9, a3, 0, XCHAL_DCACHE_SETWIDTH+XCHAL_DCACHE_LINEWIDTH - and a9, a3, a10 - addi a3, a3, -XCHAL_DCACHE_LINESIZE - .end schedule - .begin schedule - //and a7, a7, a8 // uncomment if LDCT reports non-zero index bits - maxu a6, a6, a4 // a4 = low end of range - minu a2, a6, a5 // a5 = high end of range - or a6, a7, a9 - .end schedule -1: - - \instruction a2, 0 - maxu a6, a6, a4 - minu a2, a6, a5 - \instruction a2, 0 -#if XCHAL_HAVE_PREFETCH - wsr.prefctl a11 // restore prefetch -#endif - isync_return_nop - abi_return -#endif /* dcache supports hugerange */ -// Jump to non-huge routine -7: j.l xthal_dcache_region_\name + ABI_ENTRY_MINSIZE, a4 - .size xthal_dcache_hugerange_\name, . - xthal_dcache_hugerange_\name - .endm - - - - // void xthal_icache_hugerange_<name>(void *addr, unsigned size); - // - // Invalidate icache entries for an arbitrary large - // virtual address range with a single scan of the icache. - // Assumes no address translation, i.e. virtual = physical. - // - // a2 = ptr to range - // a3 = size of range - // - // Note: -128 is a valid immediate for ADDI, but +128 is not, - // and ADDI can relax to ADDMI for multiples of 256. So scanning - // cache backwards (from end to start) allows all cache line sizes - // without creating an extra instruction for the ADDI. - // - .macro icache_hugefunc name, instruction - .text - .align 4 - .type xthal_icache_hugerange_\name,@function - .global xthal_icache_hugerange_\name -xthal_icache_hugerange_\name: - abi_entry -#if (!defined(XCHAL_HAVE_NX) || XCHAL_HAVE_NX == 0) &&XCHAL_ICACHE_SIZE > 0 && \ - XCHAL_HAVE_ICACHE_TEST && XCHAL_HAVE_MINMAX && XCHAL_HAVE_LOOPS - movi a4, XCHAL_ICACHE_SIZE*2 // size at which to use huge algorithm - movi a7, -XCHAL_ICACHE_LINESIZE // for rounding to cache line size - bltu a3, a4, 7f // use normal (line-by-line hit) function - add a5, a3, a2 // a5 = end of range - and a4, a2, a7 // a4 = low end, rounded to containing cache line - addi a5, a5, XCHAL_ICACHE_LINESIZE-1 - and a5, a5, a7 // a5 = high end, rounded to containing cache line - movi a7, XCHAL_ICACHE_SIZE/XCHAL_ICACHE_LINESIZE // a7 = number of lines in dcache - movi a3, XCHAL_ICACHE_SIZE-XCHAL_ICACHE_LINESIZE // way index - mov a6, a5 - //movi a8, -XCHAL_ICACHE_SETSIZE // use if LICT gives non-zero index bits - movi a10, (XCHAL_ICACHE_SIZE/XCHAL_ICACHE_WAYS) - 1 - - loopgtz a7, 1f - lict a7, a3 // a3 = cache tag for cache entry [a7] - \instruction a2, 0 - .begin schedule - //extui a9, a3, 0, XCHAL_ICACHE_SETWIDTH+XCHAL_ICACHE_LINEWIDTH - and a9, a3, a10 - addi a3, a3, -XCHAL_ICACHE_LINESIZE - .end schedule - .begin schedule - //and a7, a7, a8 // uncomment if LDCT reports non-zero index bits - maxu a6, a6, a4 // a4 = low end of range - minu a2, a6, a5 // a5 = high end of range - or a6, a7, a9 - .end schedule -1: - - \instruction a2, 0 - maxu a6, a6, a4 - minu a2, a6, a5 - \instruction a2, 0 - isync_return_nop - abi_return -#endif /* icache supports hugerange */ -7: j.l xthal_icache_region_\name + ABI_ENTRY_MINSIZE, a4 - .size xthal_icache_hugerange_\name, . - xthal_icache_hugerange_\name - .endm - - - - - .text - -//---------------------------------------------------------------------- -// Read CACHEATTR register -//---------------------------------------------------------------------- - -#if defined(__SPLIT__get_cacheattr) ||\ - defined(__SPLIT__get_cacheattr_nw) - -// unsigned xthal_get_cacheattr(void); - -DECLFUNC(xthal_get_cacheattr) -DECLFUNC(xthal_get_dcacheattr) -# if XCHAL_HAVE_CACHEATTR /* single CACHEATTR register used for both I and D */ -DECLFUNC(xthal_get_icacheattr) -# endif - abi_entry - dcacheattr_get - abi_return - endfunc - -#endif - -#if defined(__SPLIT__get_icacheattr) ||\ - defined(__SPLIT__get_icacheattr_nw) - -// unsigned xthal_get_icacheattr(void); - -# if !XCHAL_HAVE_CACHEATTR /* possibly independent CACHEATTR states used for I and D */ -DECLFUNC(xthal_get_icacheattr) - abi_entry - icacheattr_get - abi_return - endfunc -# endif - -#endif /*split*/ - - -//---------------------------------------------------------------------- -// Write CACHEATTR register, or equivalent. -//---------------------------------------------------------------------- - -/* - * Set CACHEATTR register in a safe manner. - * - * void xthal_set_cacheattr( unsigned new_cacheattr ); - * void xthal_set_icacheattr( unsigned new_cacheattr ); - * void xthal_set_dcacheattr( unsigned new_cacheattr ); - */ - -#if defined(__SPLIT__set_cacheattr) ||\ - defined(__SPLIT__set_cacheattr_nw) - -# if XCHAL_HAVE_CACHEATTR /* single CACHEATTR register used for both I and D accesses */ -DECLFUNC(xthal_set_icacheattr) -DECLFUNC(xthal_set_dcacheattr) -# endif -DECLFUNC(xthal_set_cacheattr) - abi_entry - cacheattr_set - abi_return - endfunc - -#endif /*split*/ - - -#if XCHAL_HAVE_CACHEATTR - - /* - * Already done above. - * - * Since we can't enable/disable the icache and dcache independently, - * and don't have a nice place to store a state which would enable - * us to only enable them both when both have been requested to be - * enabled, we simply enable both for any request to enable either, - * and disable both for any request to disable either cache. - */ - -#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - -# if defined(__SPLIT__set_icacheattr) \ - || defined(__SPLIT__set_icacheattr_nw) - -DECLFUNC(xthal_set_icacheattr) - abi_entry - icacheattr_set - isync_return_nop - abi_return - endfunc - -# endif - -# if defined(__SPLIT__set_dcacheattr) \ - || defined(__SPLIT__set_dcacheattr_nw) - -DECLFUNC(xthal_set_dcacheattr) - abi_entry - dcacheattr_set - abi_return - endfunc - -# endif /*split*/ - -#else /* full MMU (pre-v3): */ - -# if defined(__SPLIT__set_idcacheattr) \ - || defined(__SPLIT__set_idcacheattr_nw) - -// These functions aren't applicable to arbitrary MMU configurations. -// Do nothing in this case. - -DECLFUNC(xthal_set_icacheattr) -DECLFUNC(xthal_set_dcacheattr) - abi_entry - abi_return - endfunc - -# endif /*split*/ - -#endif /* cacheattr/MMU type */ - - -//---------------------------------------------------------------------- -// Determine (guess) whether caches are "enabled" -//---------------------------------------------------------------------- - -/* - * There is no "cache enable" bit in the Xtensa architecture, - * but we can use CACHEATTR (if it or its equivalent exists) - * as an indication that caches have been enabled. - */ - -#if XCHAL_HAVE_CACHEATTR - -# if defined(__SPLIT__idcache_is_enabled) || \ - defined(__SPLIT__idcache_is_enabled_nw) - -DECLFUNC(xthal_icache_is_enabled) -DECLFUNC(xthal_dcache_is_enabled) - abi_entry - cacheattr_is_enabled 2f - movi a2, 0 - abi_return -2: movi a2, 1 - abi_return - endfunc - -# endif /*split*/ - -#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR - -# if defined(__SPLIT__icache_is_enabled) || \ - defined(__SPLIT__icache_is_enabled_nw) - -DECLFUNC(xthal_icache_is_enabled) - abi_entry - icacheattr_is_enabled 2f - movi a2, 0 - abi_return -2: movi a2, 1 - abi_return - endfunc - -# endif - -# if defined(__SPLIT__dcache_is_enabled) || \ - defined(__SPLIT__dcache_is_enabled_nw) - -DECLFUNC(xthal_dcache_is_enabled) - abi_entry - dcacheattr_is_enabled 2f - movi a2, 0 - abi_return -2: movi a2, 1 - abi_return - endfunc - -# endif /*split*/ - -#else - -// These functions aren't applicable to arbitrary MMU configurations. -// Assume caches are enabled in this case (!). - -# if defined(__SPLIT__idcache_is_enabled) || \ - defined(__SPLIT__idcache_is_enabled_nw) - -DECLFUNC(xthal_icache_is_enabled) -DECLFUNC(xthal_dcache_is_enabled) - abi_entry - movi a2, 1 - abi_return - endfunc -# endif /*split*/ - -#endif - - - -//---------------------------------------------------------------------- -// invalidate the icache -//---------------------------------------------------------------------- - -#if defined(__SPLIT__icache_all_invalidate) || \ - defined(__SPLIT__icache_all_invalidate_nw) - -// void xthal_icache_all_invalidate(void); - -DECLFUNC(xthal_icache_all_invalidate) - abi_entry - icache_invalidate_all a2, a3 - isync_return_nop - abi_return - endfunc - -//---------------------------------------------------------------------- -// invalidate the dcache -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_all_invalidate) || \ - defined(__SPLIT__dcache_all_invalidate_nw) - -// void xthal_dcache_all_invalidate(void); - -DECLFUNC(xthal_dcache_all_invalidate) - abi_entry - dcache_invalidate_all a2, a3 - abi_return - endfunc - -//---------------------------------------------------------------------- -// write dcache dirty data -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_all_writeback) || \ - defined(__SPLIT__dcache_all_writeback_nw) - -// void xthal_dcache_all_writeback(void); - -DECLFUNC(xthal_dcache_all_writeback) - abi_entry - dcache_writeback_all a2, a3, a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// write dcache dirty data and invalidate -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_all_writeback_inv) || \ - defined(__SPLIT__dcache_all_writeback_inv_nw) - -// void xthal_dcache_all_writeback_inv(void); - -DECLFUNC(xthal_dcache_all_writeback_inv) - abi_entry - dcache_writeback_inv_all a2, a3, a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// unlock instructions from icache -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_all_unlock) || \ - defined(__SPLIT__icache_all_unlock_nw) - -// void xthal_icache_all_unlock(void); - -DECLFUNC(xthal_icache_all_unlock) - abi_entry - icache_unlock_all a2, a3 - abi_return - endfunc - -//---------------------------------------------------------------------- -// unlock data from dcache -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_all_unlock) || \ - defined(__SPLIT__dcache_all_unlock_nw) - -// void xthal_dcache_all_unlock(void); - -DECLFUNC(xthal_dcache_all_unlock) - abi_entry - dcache_unlock_all a2, a3 - abi_return - endfunc - -//---------------------------------------------------------------------- -// invalidate the address range in the icache -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_region_invalidate) || \ - defined(__SPLIT__icache_region_invalidate_nw) - -// void xthal_icache_region_invalidate( void *addr, unsigned size ); - -DECLFUNC(xthal_icache_region_invalidate) - abi_entry - icache_invalidate_region a2, a3, a4 - isync_return_nop - abi_return - endfunc - -#endif - -#if defined(__SPLIT__icache_hugerange_invalidate) - -// void xthal_icache_hugerange_invalidate( void *addr, unsigned size ); -icache_hugefunc invalidate, ihi - -#endif - -#if defined(__SPLIT__icache_hugerange_unlock) - -# if XCHAL_ICACHE_LINE_LOCKABLE -// void xthal_icache_hugerange_unlock( void *addr, unsigned size ); -icache_hugefunc unlock, ihu -# endif - -#endif - -#if defined(__SPLIT__dcache_hugerange_invalidate) - -// void xthal_dcache_hugerange_invalidate( void *addr, unsigned size ); -dcache_hugefunc invalidate, dhi - -#endif - -#if defined(__SPLIT__dcache_hugerange_unlock) - -# if XCHAL_DCACHE_LINE_LOCKABLE -// void xthal_dcache_hugerange_unlock( void *addr, unsigned size ); -dcache_hugefunc unlock, dhu -# endif - -#endif - -#if defined(__SPLIT__dcache_hugerange_writeback) - -// void xthal_dcache_hugerange_writeback( void *addr, unsigned size ); -dcache_hugefunc writeback, dhwb - -#endif - -#if defined(__SPLIT__dcache_hugerange_writeback_inv) - -// void xthal_dcache_hugerange_writeback_inv( void *addr, unsigned size ); -dcache_hugefunc writeback_inv, dhwbi - - - -//---------------------------------------------------------------------- -// invalidate the address range in the dcache -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_region_invalidate) || \ - defined(__SPLIT__dcache_region_invalidate_nw) - -// void xthal_dcache_region_invalidate( void *addr, unsigned size ); - -DECLFUNC(xthal_dcache_region_invalidate) - abi_entry - dcache_invalidate_region a2, a3, a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// write dcache region dirty data -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_region_writeback) || \ - defined(__SPLIT__dcache_region_writeback_nw) - -// void xthal_dcache_region_writeback( void *addr, unsigned size ); - -DECLFUNC(xthal_dcache_region_writeback) - abi_entry - dcache_writeback_region a2, a3, a4, a5 - abi_return - endfunc - -//---------------------------------------------------------------------- -// write dcache region dirty data and invalidate -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_region_writeback_inv) || \ - defined(__SPLIT__dcache_region_writeback_inv_nw) - -// void xthal_dcache_region_writeback_inv( void *addr, unsigned size ); - -DECLFUNC(xthal_dcache_region_writeback_inv) - abi_entry - dcache_writeback_inv_region a2, a3, a4, a5 - abi_return - endfunc - -//---------------------------------------------------------------------- -// lock instructions in icache region -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_region_lock) || \ - defined(__SPLIT__icache_region_lock_nw) - -// void xthal_icache_region_lock(void); - -DECLFUNC(xthal_icache_region_lock) - abi_entry - icache_lock_region a2, a3, a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// lock data in dcache region -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_region_lock) || \ - defined(__SPLIT__dcache_region_lock_nw) - -// void xthal_dcache_region_lock(void); - -DECLFUNC(xthal_dcache_region_lock) - abi_entry - dcache_lock_region a2, a3, a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// unlock instructions from icache region -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_region_unlock) || \ - defined(__SPLIT__icache_region_unlock_nw) - -// void xthal_icache_region_unlock(void); - -DECLFUNC(xthal_icache_region_unlock) - abi_entry - icache_unlock_region a2, a3, a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// unlock data from dcache region -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_region_unlock) || \ - defined(__SPLIT__dcache_region_unlock_nw) - -// void xthal_dcache_region_unlock(void); - -DECLFUNC(xthal_dcache_region_unlock) - abi_entry - dcache_unlock_region a2, a3, a4 - abi_return - endfunc - - -//---------------------------------------------------------------------- -// invalidate single icache line -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_line_invalidate) || \ - defined(__SPLIT__icache_line_invalidate_nw) - -// void xthal_icache_line_invalidate(void *addr); - -DECLFUNC(xthal_icache_line_invalidate) - abi_entry - icache_invalidate_line a2, 0 - isync_return_nop - abi_return - endfunc - - -//---------------------------------------------------------------------- -// invalidate single dcache line -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_line_invalidate) || \ - defined(__SPLIT__dcache_line_invalidate_nw) - -// void xthal_dcache_line_invalidate(void *addr); - -DECLFUNC(xthal_dcache_line_invalidate) - abi_entry - dcache_invalidate_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// write single dcache line dirty data -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_line_writeback) || \ - defined(__SPLIT__dcache_line_writeback_nw) - -// void xthal_dcache_line_writeback(void *addr); - -DECLFUNC(xthal_dcache_line_writeback) - abi_entry - dcache_writeback_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// write single dcache line dirty data and invalidate -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_line_writeback_inv) || \ - defined(__SPLIT__dcache_line_writeback_inv_nw) - -// void xthal_dcache_line_writeback_inv(void *addr); - -DECLFUNC(xthal_dcache_line_writeback_inv) - abi_entry - dcache_writeback_inv_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// lock instructions in icache line -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_line_lock) || \ - defined(__SPLIT__icache_line_lock_nw) - -// void xthal_icache_line_lock(void); - -DECLFUNC(xthal_icache_line_lock) - abi_entry - icache_lock_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// lock data in dcache line -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_line_lock) || \ - defined(__SPLIT__dcache_line_lock_nw) - -// void xthal_dcache_line_lock(void); - -DECLFUNC(xthal_dcache_line_lock) - abi_entry - dcache_lock_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// unlock instructions from icache line -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_line_unlock) || \ - defined(__SPLIT__icache_line_unlock_nw) - -// void xthal_icache_line_unlock(void); - -DECLFUNC(xthal_icache_line_unlock) - abi_entry - icache_unlock_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// unlock data from dcache line -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_line_unlock) || \ - defined(__SPLIT__dcache_line_unlock_nw) - -// void xthal_dcache_line_unlock(void); - -DECLFUNC(xthal_dcache_line_unlock) - abi_entry - dcache_unlock_line a2, 0 - abi_return - endfunc - -//---------------------------------------------------------------------- -// sync icache and memory (???) -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__icache_sync) || \ - defined(__SPLIT__icache_sync_nw) - -// void xthal_icache_sync(void); - -DECLFUNC(xthal_icache_sync) - abi_entry - icache_sync a2 - isync_return_nop - abi_return - endfunc - -//---------------------------------------------------------------------- -// sync dcache and memory (???) -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__dcache_sync) || \ - defined(__SPLIT__dcache_sync_nw) - -// void xthal_dcache_sync(void); - -DECLFUNC(xthal_dcache_sync) - abi_entry - dcache_sync a2 - abi_return - endfunc - -//---------------------------------------------------------------------- -// Get/Set icache number of ways enabled -//---------------------------------------------------------------------- - -#endif - -#if defined (__SPLIT__icache_get_ways) || \ - defined (__SPLIT__icache_get_ways_nw) - -// unsigned int xthal_icache_get_ways(void); - -DECLFUNC(xthal_icache_get_ways) - abi_entry - icache_get_ways a2 - abi_return - endfunc - -#endif - -#if defined (__SPLIT__icache_set_ways) || \ - defined(__SPLIT__icache_set_ways_nw) - -/// void xthal_icache_set_ways(unsigned int ways); - -DECLFUNC(xthal_icache_set_ways) - abi_entry - icache_set_ways a2 a3 a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// Get/Set dcache number of ways enabled -//---------------------------------------------------------------------- - -#endif - -#if defined (__SPLIT__dcache_get_ways) || \ - defined (__SPLIT__dcache_get_ways_nw) - -// unsigned int xthal_dcache_get_ways(void); - -DECLFUNC(xthal_dcache_get_ways) - abi_entry - dcache_get_ways a2 - abi_return - endfunc - -#endif - -#if defined (__SPLIT__dcache_set_ways) || \ - defined (__SPLIT__dcache_set_ways_nw) - -// void xthal_dcache_set_ways(unsigned int ways); - -DECLFUNC(xthal_dcache_set_ways) - abi_entry - dcache_set_ways a2 a3 a4 - abi_return - endfunc - -//---------------------------------------------------------------------- -// opt into and out of coherence -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__cache_coherence_on) || \ - defined(__SPLIT__cache_coherence_on_nw) - -// The opt-in routine assumes cache was initialized at reset, -// so it's equivalent to the low-level coherence_on routine. - -// void xthal_cache_coherence_optin(void) -// void xthal_cache_coherence_on(void) - -DECLFUNC(xthal_cache_coherence_optin) -DECLFUNC(xthal_cache_coherence_on) - abi_entry - cache_coherence_on a2, a3 - abi_return - endfunc - -#endif - -#if defined(__SPLIT__cache_coherence_off) || \ - defined(__SPLIT__cache_coherence_off_nw) - -// The coherence_off routines should not normally be called directly. -// Use the xthal_cache_coherence_optout() C routine instead -// (which first empties the cache). - -// void xthal_cache_coherence_off - -DECLFUNC(xthal_cache_coherence_off) - abi_entry - cache_coherence_off a2, a3 - abi_return - endfunc - - -//---------------------------------------------------------------------- -// Control cache prefetch -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__set_cache_prefetch_long) || \ - defined(__SPLIT__set_cache_prefetch_long_nw) - -# if XCHAL_HAVE_BE -# define aH a2 /* msb word = prefctl mask */ -# define aL a3 /* lsb word = prefctl value */ -# else -# define aH a3 /* msb word = prefctl mask */ -# define aL a2 /* lsb word = prefctl value */ -# endif - -// Set cache prefetch state (-1=enable, 0=disable, and see XTHAL_*PREFETCH_*), -// and return previous one. -// -// int xthal_set_cache_prefetch_long( unsigned long long ); -// -DECLFUNC(xthal_set_cache_prefetch_long) - abi_entry -# if XCHAL_HAVE_PREFETCH - movi a5, XCHAL_CACHE_PREFCTL_DEFAULT - addi a4, aL, 1 // does prefctl value aL == -1 ? - moveqz aL, a5, a4 // if yes (XTHAL_PREFETCH_ENABLE), set it to default - movgez a2, aL, aL // if the high bit is not set, then we want to transfer the contents of aL to prefctl - // so we move it to a2 - bgez aL, 1f // high bit set indicates masked update - ssai 16 // 16-bit right shifts - src a5, aL, aH // get 16-bit-swapped 32-bit value - src a5, a5, a5 // get 32-bit value (rotate by 16) - rsr.prefctl a4 - src a3, aH, aL // get 32-bit mask - or a4, a4, a3 // set masked bits - xor a4, a4, a3 // clear masked bits - and a5, a5, a3 // only use masked bits - or a2, a4, a5 // combine masked bits -1: -# if XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RC_2010_1 /* for erratum #325 */ - j 1f ; .align 8 ; 1: xsr.prefctl a2 ; isync // ensure XSR.PREFCTL;ISYNC wholly within an icache line -# else - xsr.prefctl a2 -# endif -# else - movi a2, 0 -# endif - abi_return - endfunc - -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__set_cache_prefetch) || \ - defined(__SPLIT__set_cache_prefetch_nw) - -// FOR BACKWARD COMPATIBILITY WITH PRE-RF RELEASE OBJECT CODE ONLY. -// Set cache prefetch state (-1=enable, 0=disable, and see the -// definitions of XTHAL_*PREFETCH_* with only the lower 32 bits set), -// and return previous one. -// int xthal_set_cache_prefetch( int ) -// -DECLFUNC(xthal_set_cache_prefetch) - abi_entry -# if XCHAL_HAVE_PREFETCH - movi a3, XCHAL_CACHE_PREFCTL_DEFAULT - addi a4, a2, 1 // does a2 == -1 ? - moveqz a2, a3, a4 // if yes (XTHAL_PREFETCH_ENABLE), set it to default - bbci.l a2, 31, 1f // high bit set indicates masked update - rsr.prefctl a4 - extui a5, a2, 16, 15 - or a4, a4, a5 // set masked bits - xor a4, a4, a5 // clear masked bits - and a2, a2, a5 // only use masked bits - or a2, a4, a2 // combine masked bits -1: -# if XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RC_2010_1 /* for erratum #325 */ - j 1f ; .align 8 ; 1: xsr.prefctl a2 ; isync // ensure XSR.PREFCTL;ISYNC wholly within an icache line -# else - xsr.prefctl a2 -# endif -# else - movi a2, 0 -# endif - abi_return - endfunc - -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__get_cache_prefetch) ||\ - defined(__SPLIT__get_cache_prefetch_nw) - -// Return current cache prefetch state. -// int xthal_get_cache_prefetch( void ) -DECLFUNC(xthal_get_cache_prefetch) - abi_entry -# if XCHAL_HAVE_PREFETCH - rsr.prefctl a2 -# else - movi a2, 0 -# endif - abi_return - endfunc - -//---------------------------------------------------------------------- -// Misc configuration info -//---------------------------------------------------------------------- -#endif - -// Eventually these will move to their own file: -#if defined(__SPLIT__hw_configid0) - .set xthals_hw_configid0, XCHAL_HW_CONFIGID0 -#endif - -#if defined(__SPLIT__hw_configid1) - .set xthals_hw_configid1, XCHAL_HW_CONFIGID1 -#endif - -#if defined(__SPLIT__release_major) - .set xthals_release_major, XTHAL_RELEASE_MAJOR -#endif - -#if defined(__SPLIT__release_minor) - .set xthals_release_minor, XTHAL_RELEASE_MINOR - -#endif /*split*/ - - .global xthals_hw_configid0, xthals_hw_configid1 - .global xthals_release_major, xthals_release_minor - -//---------------------------------------------------------------------- - diff --git a/src/arch/xtensa/hal/clock.S b/src/arch/xtensa/hal/clock.S deleted file mode 100644 index 7ea86d3f1b15..000000000000 --- a/src/arch/xtensa/hal/clock.S +++ /dev/null @@ -1,138 +0,0 @@ -// -// clock.S - assembly language clock routines -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/clock.S#1 $ - -// Copyright (c) 2003-2010 Tensilica 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 <xtensa/coreasm.h> - - -// A useful looping macro: -// 'iterate' invokes 'what' (an instruction, pseudo-op or other macro) -// multiple times, passing it a numbered parameter from 'from' to 'to' -// inclusively. Does not invoke 'what' at all if from > to. -// Maximum difference between 'from' and 'to' is 99 minus nesting depth -// (GNU 'as' doesn't allow nesting deeper than 100). -// - .macro iterate from, to, what - .ifeq ((\to-\from) & ~0xFFF) - \what \from - iterate "(\from+1)", \to, \what - .endif - .endm // iterate - - -//---------------------------------------------------------------------- -// Read CCOUNT register -//---------------------------------------------------------------------- - -// unsigned xthal_get_ccount(void) -// - .global xthal_get_ccount - .type xthal_get_ccount,@function - .align 4 -xthal_get_ccount: - abi_entry -#if XCHAL_HAVE_CCOUNT - rsr.ccount a2 -/* - * The following alternative (in absence of CCOUNT) doesn't work well, - * because ICOUNT is often used for debugging. (And when it isn't, - * one would have to ensure that ICOUNTLEVEL is high enough and that - * ICOUNT is incremented to zero in the debug exception handler upon - * ICOUNT exceptions.) - * - * #elif XCHAL_HAVE_DEBUG - * rsr.icount a2 // no CCOUNT, return ICOUNT if available - */ -#else - movi a2, 0 // else no counter at all, just return zero -#endif - abi_return - .size xthal_get_ccount, . - xthal_get_ccount - - -//---------------------------------------------------------------------- -// Access CCOMPAREn registers -//---------------------------------------------------------------------- - -// void xthal_set_ccompare(int, unsigned) -// - .global xthal_set_ccompare - .type xthal_set_ccompare,@function - .align 4 -xthal_set_ccompare: - abi_entry -#if XCHAL_NUM_TIMERS > 0 - bnez a2, 1f - wsr.ccompare0 a3 - rsync - abi_return -#endif -1: -#if XCHAL_NUM_TIMERS > 1 - bnei a2, 1, 2f - wsr.ccompare1 a3 - rsync - abi_return -#endif -2: -#if XCHAL_NUM_TIMERS > 2 - bnei a2, 2, 3f - wsr.ccompare2 a3 - rsync -#endif -3: - abi_return - .size xthal_set_ccompare, . - xthal_set_ccompare - - -// unsigned xthal_get_ccompare(int) -// - .global xthal_get_ccompare - .type xthal_get_ccompare,@function - .align 4 -xthal_get_ccompare: - abi_entry -#if XCHAL_NUM_TIMERS > 0 - bnez a2, 1f - rsr.ccompare0 a2 - abi_return -#endif -1: -#if XCHAL_NUM_TIMERS > 1 - bnei a2, 1, 2f - rsr.ccompare1 a2 - abi_return -#endif -2: -#if XCHAL_NUM_TIMERS > 2 - bnei a2, 2, 3f - rsr.ccompare2 a2 - abi_return -#endif -3: - movi a2, 0 - abi_return - .size xthal_get_ccompare, . - xthal_get_ccompare - diff --git a/src/arch/xtensa/hal/coherence.c b/src/arch/xtensa/hal/coherence.c deleted file mode 100644 index 066557325bcf..000000000000 --- a/src/arch/xtensa/hal/coherence.c +++ /dev/null @@ -1,59 +0,0 @@ -/* coherence.c - Cache coherence opt-in / opt-out functions */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/coherence.c#1 $ */ - -/* - * Copyright (c) 2008 Tensilica 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 <xtensa/config/core.h> - - -/* - * Opt-out of cache coherence. - * - * Caveat: on a core with full MMU, cache attribute handling done here only - * works well with the default (reset) TLB mapping of eight 512MB regions. - * It likely won't work correctly when other page sizes are in use (it may - * appear to work but be open to race conditions, depending on situation). - */ -void xthal_cache_coherence_optout( void ) -{ -#if XCHAL_HAVE_EXTERN_REGS && XCHAL_DCACHE_IS_COHERENT - unsigned ca = xthal_get_cacheattr(); - /* Writeback all dirty entries. Writethru mode avoids new dirty entries. */ - xthal_set_region_attribute(0,0xFFFFFFFF, XCHAL_CA_WRITETHRU, XTHAL_CAFLAG_EXPAND); - xthal_dcache_all_writeback(); - /* Invalidate all cache entries. Cache-bypass mode avoids new entries. */ - xthal_set_region_attribute(0,0xFFFFFFFF, XCHAL_CA_BYPASS, XTHAL_CAFLAG_EXPAND); - xthal_dcache_all_writeback_inv(); - /* Wait for everything to settle. */ - asm("memw"); - xthal_dcache_sync(); - xthal_icache_sync(); - /* Opt-out of cache coherency protocol. */ - xthal_cache_coherence_off(); - /* Restore cache attributes, as of entry to this function. */ - xthal_set_cacheattr(ca); -#endif -} - diff --git a/src/arch/xtensa/hal/debug.c b/src/arch/xtensa/hal/debug.c deleted file mode 100644 index 9e2b2654d303..000000000000 --- a/src/arch/xtensa/hal/debug.c +++ /dev/null @@ -1,525 +0,0 @@ -// -// debug.c - debug related constants and functions -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/debug.c#1 $ - -// Copyright (c) 2002 Tensilica 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 <xtensa/hal.h> -#include <xtensa/config/core.h> - - -/* 1 if debug option configured, 0 if not: */ -const int Xthal_debug_configured = XCHAL_HAVE_DEBUG; - -/* Number of instruction and data break registers: */ -const int Xthal_num_ibreak = XCHAL_NUM_IBREAK; -const int Xthal_num_dbreak = XCHAL_NUM_DBREAK; - - -#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE -/* This array is incorrect: */ -const unsigned short Xthal_ill_inst_16[16] = -{ -#if XCHAL_HAVE_BE - 0xfd0f, 0xfd1f, 0xfd2f, 0xfd3f, - 0xfd4f, 0xfd5f, 0xfd6f, 0xfd7f, - 0xfd8f, 0xfd9f, 0xfdaf, 0xfdbf, - 0xfdcf, 0xfddf, 0xfdef, 0xfdff -#else - 0xf0fd, 0xf1fd, 0xf2fd, 0xf3fd, - 0xf4fd, 0xf5fd, 0xf6fd, 0xf7fd, - 0xf8fd, 0xf9fd, 0xfafd, 0xfbfd, - 0xfcfd, 0xfdfd, 0xfefd, 0xfffd -#endif -}; -#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */ - - -#undef XTHAL_24_BIT_BREAK -#undef XTHAL_16_BIT_BREAK -#define XTHAL_24_BIT_BREAK 0x80000000 -#define XTHAL_16_BIT_BREAK 0x40000000 - - - -// set software breakpoint and synchronize cache -unsigned int -xthal_set_soft_break(void *addr) -{ - unsigned inst; - int is24bit = (xthal_disassemble_size( (unsigned char *)addr ) == 3); - unsigned int ret_val; - -#if XCHAL_HAVE_BE - inst = ((((char *)addr)[0])<<24) + - ((((char *)addr)[1])<<16) + - ((((char *)addr)[2])<<8); -#else - inst = ((((char *)addr)[0])) + - ((((char *)addr)[1])<<8) + - ((((char *)addr)[2])<<16); -#endif -#if XCHAL_HAVE_BE - if (is24bit) { - ret_val = XTHAL_24_BIT_BREAK & ((inst>>8)&0xffffff); - ((unsigned char *)addr)[0] = 0x00; - ((unsigned char *)addr)[1] = 0x04; - ((unsigned char *)addr)[2] = 0x00; - } else { - ret_val = XTHAL_16_BIT_BREAK & ((inst>>16)&0xffff); - ((unsigned char *)addr)[0] = 0xD2; - ((unsigned char *)addr)[1] = 0x0f; - } -#else - if (is24bit) { - ret_val = XTHAL_24_BIT_BREAK & (inst&0xffffff); - ((unsigned char *)addr)[0] = 0x00; - ((unsigned char *)addr)[1] = 0x40; - ((unsigned char *)addr)[2] = 0x00; - } else { - ret_val = XTHAL_16_BIT_BREAK & (inst&0xffff); - ((unsigned char *)addr)[0] = 0x2D; - ((unsigned char *)addr)[1] = 0xf0; - } -#endif - *((unsigned int *)addr) = inst; -#if XCHAL_DCACHE_IS_WRITEBACK - xthal_dcache_region_writeback((void*)addr, 3); -#endif -#if XCHAL_ICACHE_SIZE > 0 - xthal_icache_region_invalidate((void*)addr, 3); -#endif - return ret_val; -} - - -// remove software breakpoint and synchronize cache -void -xthal_remove_soft_break(void *addr, unsigned int inst) -{ -#if XCHAL_HAVE_BE - if (inst&XTHAL_24_BIT_BREAK) { - ((unsigned char *)addr)[0] = (inst>>16)&0xff; - ((unsigned char *)addr)[1] = (inst>>8)&0xff; - ((unsigned char *)addr)[2] = inst&0xff; - } else { - ((unsigned char *)addr)[0] = (inst>>8)&0xff; - ((unsigned char *)addr)[1] = inst&0xff; - } -#else - ((unsigned char *)addr)[0] = inst&0xff; - ((unsigned char *)addr)[1] = (inst>>8)&0xff; - if (inst&XTHAL_24_BIT_BREAK) - ((unsigned char *)addr)[2] = (inst>>16)&0xff; -#endif -#if XCHAL_DCACHE_IS_WRITEBACK - xthal_dcache_region_writeback((void*)addr, 3); -#endif -#if XCHAL_ICACHE_SIZE > 0 - xthal_icache_region_invalidate((void*)addr, 3); -#endif -} - - - - -#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE - -// return instruction type -unsigned int -xthal_inst_type(void *addr) -{ - unsigned int inst_type = 0; - unsigned inst; -// unsigned int inst = *((unsigned int *)addr); - unsigned char op0, op1, op2; - unsigned char i, m, n, r, s, t, z; - -#if XCHAL_HAVE_BE - inst = ((((char *)addr)[0])<<24) + - ((((char *)addr)[1])<<16) + - ((((char *)addr)[2])<<8); - op0 = inst>>28; - op1 = (inst>>12)&0xf; - op2 = (inst>>16)&0xf; - i = (inst>>27)&0x1; - z = (inst>>26)&0x1; - m = (inst>>24)&0x3; - n = (inst>>26)&0x3; - r = (inst>>16)&0xf; - s = (inst>>20)&0xf; - t = (inst>>24)&0xf; -#else - inst = ((((char *)addr)[0])) + - ((((char *)addr)[1])<<8) + - ((((char *)addr)[2])<<16); - op0 = inst&0xf; - op1 = (inst&0xf0000)>>16; - op2 = (inst&0xf00000)>>20; - i = (inst&0x80)>>7; - z = (inst&0x40)>>6; - m = (inst&0xc0)>>6; - n = (inst&0x30)>>4; - r = (inst&0xf000)>>12; - s = (inst&0xf00)>>8; - t = (inst&0xf0)>4; -#endif - switch (op0) { - case 0x0: - inst_type |= XTHAL_24_BIT_INST; - if ((op1==0)&&(op2==0)) - switch (r) { - case 0: - if (m==0x2) { - if (!(n&0x2)) // RET, RETW - inst_type |= XTHAL_RET_INST; - else if (n==0x2) // JX - inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REG_INST); - inst_type |= (s<<28); - } else if (m==3) // CALLX - inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REG_INST); - inst_type |= (s<<28); - break; - case 0x3: - if (t==0) - switch (s) { - case 0x0: // RFE - inst_type |= XTHAL_RFE_INST; - break; - case 0x1: // RFUE - inst_type |= XTHAL_RFUE_INST; - break; - case 0x4: // RFW - case 0x5: - inst_type |= XTHAL_RFW_INST; - break; - } - else if (t==1) // RFI - inst_type |= XTHAL_RFI_INST; - break; - case 0x4: // BREAK - inst_type |= XTHAL_BREAK_INST; - break; - case 0x5: // SYSCALL - inst_type |= XTHAL_SYSCALL_INST; - break; - } - break; - case 0x5: // CALL - inst_type |= XTHAL_24_BIT_INST; - inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REL_INST); - break; - case 0x6: // B - inst_type |= XTHAL_24_BIT_INST; - if (n==0) // J - inst_type |= (XTHAL_JUMP_INST|XTHAL_DEST_REL_INST); - else if ((n==0x1)||(n==0x2)) - inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST); - else { - if (m&0x2) - inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST); - else if ((m==0x1)&&((r==0x0)||(r==0x1))) - inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST); - } - break; - case 0x7: // B - inst_type |= XTHAL_24_BIT_INST; - inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST); - break; -#if XCHAL_HAVE_DENSITY - case 0x8: // L32I.N - case 0x9: // S32I.N - case 0xA: // ADD.N - case 0xb: // ADDI.N - inst_type |= XTHAL_16_BIT_INST; - break; - case 0xc: - inst_type |= XTHAL_16_BIT_INST; // MOVI.N BEQZ.N, BNEZ.N - if (i) - inst_type |= (XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST); - break; - case 0xd: // MOV.N NOP.N - inst_type |= XTHAL_16_BIT_INST; - if (r==0xf) - switch(t) { - case 0x0: - case 0x1: - inst_type |= XTHAL_RET_INST; // RET.N, RETW.N - break; - case 0x2: - inst_type |= XTHAL_BREAK_INST; // BREAK.N - break; - } - break; -#endif /* XCHAL_HAVE_DENSITY */ - default: - inst_type |= XTHAL_24_BIT_INST; - } - return inst_type; -} - -// returns branch address -unsigned int -xthal_branch_addr(void *addr) -{ - unsigned int b_addr = (unsigned int) addr; - unsigned inst; -// unsigned int inst = *((unsigned int *)addr); - int offset; - unsigned int inst_type = xthal_inst_type(addr); - unsigned int inst_type_mask; -#if XCHAL_HAVE_BE - inst = ((((char *)addr)[0])<<24) + - ((((char *)addr)[1])<<16) + - ((((char *)addr)[2])<<8); -#else - inst = ((((char *)addr)[0])) + - ((((char *)addr)[1])<<8) + - ((((char *)addr)[2])<<16); -#endif -#if XCHAL_HAVE_DENSITY - inst_type_mask = XTHAL_16_BIT_INST|XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST; - if ((inst_type&inst_type_mask)==inst_type_mask) { -# if XCHAL_HAVE_BE - b_addr += (4+((inst&0x3000000)>>20)+((inst&0xf0000)>>16)); -# else - b_addr += (4+(inst&0x30)+((inst&0xf000)>>12)); -# endif - } -#endif /* XCHAL_HAVE_DENSITY */ - inst_type_mask = XTHAL_24_BIT_INST|XTHAL_BRANCH_INST|XTHAL_DEST_REL_INST; - if ((inst_type&inst_type_mask)==inst_type_mask) { -#if XCHAL_HAVE_BE - if ((inst&0xf0000000)==0x70000000) - offset = ((int)(inst<<16))>>24; - else if ((inst&0xf2000000)==0x62000000) - offset = ((int)(inst<<16))>>24; - else - offset = ((int)(inst<<12))>>20; -#else - if ((inst&0xf)==0x7) - offset = ((int)(inst<<8))>>24; - else if ((inst&0x2f)==0x26) - offset = ((int)(inst<<8))>>24; - else - offset = ((int)(inst<<8))>>20; -#endif - b_addr += 4 + offset; - } - inst_type_mask = XTHAL_24_BIT_INST|XTHAL_JUMP_INST|XTHAL_DEST_REL_INST; - if ((inst_type&inst_type_mask)==inst_type_mask) { -#if XCHAL_HAVE_BE - if ((inst&0xfc000000)==0x60000000) - offset = ((int)(inst<<6))>>14; - else - { - b_addr &= 0xfffffffc; - offset = ((int)(inst<<6))>>12; - } -#else - if ((inst&0x3f)==0x6) - offset = ((int)(inst<<8))>>14; - else - { - b_addr &= 0xfffffffc; - offset = ((int)(inst<<8))>>12; - } -#endif - b_addr += 4 + offset; - } - return b_addr; -} - -// return pc of next instruction for a given state -unsigned int xthal_get_npc(XTHAL_STATE *user_state) -{ - unsigned inst_type; - unsigned npc; - inst_type = xthal_inst_type((void *)user_state->pc); - if (inst_type & XTHAL_24_BIT_INST) - npc = user_state->pc + 3; - else - npc = user_state->pc + 2; - if (inst_type & XTHAL_RFW_INST) { - /* Can not debug level 1 interrupts */ - // xt_panic(); - } else if (inst_type & XTHAL_RFUE_INST) { - /* Can not debug level 1 interrupts */ - // xt_panic(); - } else if (inst_type & XTHAL_RFI_INST) { - /* Can not debug level 1 interrupts */ - // xt_panic(); - } else if (inst_type & XTHAL_RFE_INST) { - /* Can not debug level 1 interrupts */ - // xt_panic(); - } else if (inst_type & XTHAL_RET_INST) { - npc = (user_state->pc&0xc0000000)+(user_state->ar[0]&0x3fffffff); - } else if (inst_type & XTHAL_BREAK_INST) { - /* Can not debug break */ - // xt_panic(); - } else if (inst_type & XTHAL_SYSCALL_INST) { - /* Can not debug exceptions */ - // xt_panic(); - } else if (inst_type & XTHAL_LOOP_END) { - // xt_panic(); - } else if (inst_type & XTHAL_JUMP_INST) { - if (inst_type & XTHAL_DEST_REG_INST) { - return user_state->ar[inst_type>>28]; - } else if (inst_type & XTHAL_DEST_REL_INST) { - return xthal_branch_addr((void *)user_state->pc); - } - } else if (inst_type & XTHAL_BRANCH_INST) { - int branch_taken = 0; - unsigned short inst; - unsigned char op0, t, s, r, m, n; - memcpy(&inst, (void *)user_state->pc, 2); -#if XCHAL_HAVE_BE - op0 = (inst&0xf000)>>12; - t = (inst&0x0f00)>>8; - s = (inst&0x00f0)>>4; - r = (inst&0x000f); - m = t&3; - n = t>>2; -#else - op0 = (inst&0x000f); - t = (inst&0x00f0)>>4; - s = (inst&0x0f00)>>8; - r = (inst&0xf000)>>12; - m = t>>2; - n = t&3; -#endif - if (inst_type &XTHAL_16_BIT_INST) { -#if XCHAL_HAVE_BE - if (inst&0x400) /* BNEZ.N */ - branch_taken = (user_state->ar[(inst>>4)&0xf]!=0); - else /* BEQZ.N */ - branch_taken = (user_state->ar[(inst>>4)&0xf]==0); -#else - if (inst&0x40) /* BNEZ.N */ - branch_taken = (user_state->ar[(inst>>8)&0xf]!=0); - else /* BEQZ.N */ - branch_taken = (user_state->ar[(inst>>8)&0xf]==0); -#endif - } - if (op0==0x6) { - if (n==1) { - if (m==0) { /* BEQZ */ - branch_taken = (user_state->ar[s]==0); - } else if (m==1) { /* BNEZ */ - branch_taken = (user_state->ar[s]!=0); - } else if (m==2) { /* BLTZ */ - branch_taken = (((int)user_state->ar[s])<0); - } else if (m==3) { /* BGEZ */ - branch_taken = (((int)user_state->ar[s])>=0); - } - } else if (n==2) { - int b4const[16] = - { -1, 1, 2, 3, 4, 5, 6, 7, - 8, 10, 12, 16, 32, 62, 128, 256 }; - if (m==0) { /* BEQI */ - branch_taken = (user_state->ar[s]==b4const[r]); - } else if (m==1) { /* BNEI */ - branch_taken = (user_state->ar[s]!=b4const[r]); - } else if (m==2) { /* BLTI */ - branch_taken = (((int)user_state->ar[s])<b4const[r]); - } else if (m==3) { /* BGEI */ - branch_taken = (((int)user_state->ar[s])>=b4const[r]); - } - } else if (n==3) { - int b4constu[16] = - { 32768, 65536, 2, 3, 4, 5, 6, 7, - 8, 10, 12, 16, 32, 62, 128, 256 }; - if (m==2) { /* BLTUI */ - branch_taken = (user_state->ar[s]<b4constu[r]); - } else if (m==3) { /* BGEUI */ - branch_taken = (user_state->ar[s]>=b4constu[r]); - } - } - } else if (op0==0x7) { - if (r==0) { /* BNONE */ - branch_taken = ((user_state->ar[s]&user_state->ar[t])==0); - } else if (r==1) { /* BEQ */ - branch_taken = (user_state->ar[s]==user_state->ar[t]); - } else if (r==2) { /* BLT */ - branch_taken = ((int)user_state->ar[s]<(int)user_state->ar[t]); - } else if (r==3) { /* BLTU */ - branch_taken = (user_state->ar[s]<user_state->ar[t]); - } else if (r==4) { /* BALL */ - branch_taken = (((~user_state->ar[s])&user_state->ar[t])==0); - } else if (r==5) { /* BBC */ -#if XCHAL_HAVE_BE - branch_taken = ((user_state->ar[s]&(0x80000000>>user_state->ar[t]))==0); - } else if (r==6) { /* BBCI */ - branch_taken = ((user_state->ar[s]&(0x80000000>>t))==0); - } else if (r==7) { /* BBCI */ - branch_taken = ((user_state->ar[s]&(0x80000000>>(t+16)))==0); -#else - branch_taken = ((user_state->ar[s]&(1<<user_state->ar[t]))==0); - } else if (r==6) { /* BBCI */ - branch_taken = ((user_state->ar[s]&(1<<t))==0); - } else if (r==7) { /* BBCI */ - branch_taken = ((user_state->ar[s]&(1<<(t+16)))==0); -#endif - } else if (r==8) { /* BANY */ - branch_taken = ((user_state->ar[s]&user_state->ar[t])!=0); - } else if (r==9) { /* BNE */ - branch_taken = (user_state->ar[s]!=user_state->ar[t]); - } else if (r==10) { /* BGE */ - branch_taken = ((int)user_state->ar[s]>=(int)user_state->ar[t]); - } else if (r==11) { /* BGEU */ - branch_taken = (user_state->ar[s]>=user_state->ar[t]); - } else if (r==12) { /* BNALL */ - branch_taken = (((~user_state->ar[s])&user_state->ar[t])!=0); - } else if (r==13) { /* BBS */ -#if XCHAL_HAVE_BE - branch_taken = ((user_state->ar[s]&(0x80000000>>user_state->ar[t]))!=0); - } else if (r==14) { /* BBSI */ - branch_taken = ((user_state->ar[s]&(0x80000000>>t))!=0); - } else if (r==15) { /* BBSI */ - branch_taken = ((user_state->ar[s]&(0x80000000>>(t+16)))!=0); -#else - branch_taken = ((user_state->ar[s]&(1<<user_state->ar[t]))!=0); - } else if (r==14) { /* BBSI */ - branch_taken = ((user_state->ar[s]&(1<<t))!=0); - } else if (r==15) { /* BBSI */ - branch_taken = ((user_state->ar[s]&(1<<(t+16)))!=0); -#endif - } - } - if (branch_taken) { - if (inst_type & XTHAL_DEST_REG_INST) { - return user_state->ar[inst_type>>24]; - } else if (inst_type & XTHAL_DEST_REL_INST) { - return xthal_branch_addr((void *)user_state->pc); - } - } -#if XCHAL_HAVE_LOOPS - else if (user_state->lcount && (npc==user_state->lend)) - return user_state->lbeg; -#endif - } - return npc; -} - -#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */ - diff --git a/src/arch/xtensa/hal/debug_hndlr.S b/src/arch/xtensa/hal/debug_hndlr.S deleted file mode 100644 index 172f61c03966..000000000000 --- a/src/arch/xtensa/hal/debug_hndlr.S +++ /dev/null @@ -1,146 +0,0 @@ -// -// debug_hndlr.S -- default Xtensa debug exception handler -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/debug_hndlr.S#1 $ - -// Copyright (c) 2003-2010 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/config/system.h> - -#if XCHAL_HAVE_DEBUG && XCHAL_HAVE_EXCEPTIONS - - /* - * Default debug exception handler. - * - * Note that the debug exception vector must save a3 - * in EXCSAVE+XCHAL_DEBUGLEVEL before jumping here. - * - * This handler is used when no debugger is present. - * The end result of executing this default handler - * is as if no debug exception had occurred, eg. as if - * the core was running at PS.INTLEVEL >= DEBUGLEVEL. - * - * Because the debug exception vector might get - * placed in ROM, and be expected to work regardless - * of what executable image or OS is running in RAM, - * we're very careful not to use any RAM here. - * We don't know what RAM we can safely use. - * This tricky part to accomplishing this feat - * is to use only *one* register (a3, which was - * saved in EXCSAVE+XCHAL_DEBUGLEVEL), because we don't - * have RAM in which to safely store other regs. - * - * A real debugger application would normally - * have some kind of conventions, or special - * hardware support, to have its own RAM workspace - * in which to save context and do real work - * in this handler. - */ - - -#if XSHAL_DEBUG_VECTOR_ISROM - // Debug exception vector is in ROM, so place the handler - // in ROM also. Otherwise running different executables - // with that ROM will not work because the handler would - // likely not be there or be at the wrong address. - // - .section .srom.text, "ax" -#else - // Debug exception vector is in RAM, so we can safely - // place the handler in RAM as well. - // - .text -#endif - - .global xthal_debugexc_defhndlr_nw - .align 4 -xthal_debugexc_defhndlr_nw: - rsr.debugcause a3 // get cause of debug exception - - // Check for possible debug causes, in priority order. - // We only handle the highest priority condition present. - // (If there are multiple conditions, the lower priority - // condition(s) will normally trigger upon return from - // this exception handler.) - - bbci.l a3, DEBUGCAUSE_ICOUNT_SHIFT, 1f // ICOUNT trap? - movi a3, 0 - wsr.icount a3 // clear ICOUNT - j 3f - -/* - * Ensure that we have IBREAKs, otherwise the IBREAKENABLE - * special register is not there: - */ -#if XCHAL_NUM_IBREAK > 0 -1: bbci.l a3, DEBUGCAUSE_IBREAK_SHIFT, 1f // IBREAK match? - movi a3, 0 - wsr.ibreakenable a3 // disable IBREAK traps - j 3f -#endif - -/* Also check for DBREAK registers: */ -#if XCHAL_NUM_DBREAK > 0 -1: bbci.l a3, DEBUGCAUSE_DBREAK_SHIFT, 1f // DBREAK match? - movi a3, 0 - wsr.dbreakc0 a3 // disable DBREAK register 0 -# if XCHAL_NUM_DBREAK > 1 - wsr.dbreakc1 a3 // disable DBREAK register 1 -# endif - j 3f -#endif - -1: bbci.l a3, DEBUGCAUSE_BREAK_SHIFT, 1f // BREAK instruction? - //readsr epc XCHAL_DEBUGLEVEL a3 // get PC pointing to BREAK - //l8ui a3, a3, 1 // get first 4-bit operand of BREAK (in 2nd byte) - //extui a3, a3, (XCHAL_HAVE_BE*4), 4 // pos depends on endianness - //bnei a3, 1, 3f // is it a BREAK 1,x instruction? - readsr epc XCHAL_DEBUGLEVEL a3 // get PC pointing to BREAK - addi a3, a3, 3 // skip BREAK instruction - writesr epc XCHAL_DEBUGLEVEL a3 // update PC - j 3f - -1: bbci.l a3, DEBUGCAUSE_BREAKN_SHIFT, 1f // BREAK.N instruction? - readsr epc XCHAL_DEBUGLEVEL a3 // get PC pointing to BREAK - addi a3, a3, 2 // skip BREAK.N instruction - writesr epc XCHAL_DEBUGLEVEL a3 // update PC - j 3f - -1: bbci.l a3, DEBUGCAUSE_DEBUGINT_SHIFT, 1f // debug interrupt? - // Nothing to do... - j 3f - -1: // Unknown debug case? ignore - -3: readsr excsave XCHAL_DEBUGLEVEL a3 // restore a3 - rfi XCHAL_DEBUGLEVEL // return from debug exception - - .size xthal_debugexc_defhndlr_nw, . - xthal_debugexc_defhndlr_nw - - -#if XSHAL_DEBUG_VECTOR_ISROM - .text // in case this gets included by something else -#endif - -#endif /* XCHAL_HAVE_DEBUG */ - diff --git a/src/arch/xtensa/hal/disass.c b/src/arch/xtensa/hal/disass.c deleted file mode 100644 index 5f8d8517c551..000000000000 --- a/src/arch/xtensa/hal/disass.c +++ /dev/null @@ -1,153 +0,0 @@ -// -// disass.c - disassembly routines for Xtensa -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/disass.c#1 $ - -// Copyright (c) 2004-2013 Tensilica 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 <xtensa/hal.h> -#include <xtensa/config/core.h> - -#ifdef XCHAL_OP0_FORMAT_LENGTHS -extern const unsigned char Xthal_op0_format_lengths[16]; -#endif -extern const unsigned char Xthal_byte0_format_lengths[256]; - - -#if defined(__SPLIT__op0_format_lengths) - -/* Instruction length in bytes as function of its op0 field (first nibble): */ -#ifdef XCHAL_OP0_FORMAT_LENGTHS -const unsigned char Xthal_op0_format_lengths[16] = { - XCHAL_OP0_FORMAT_LENGTHS -}; -#endif - - -#elif defined(__SPLIT__byte0_format_lengths) - -/* Instruction length in bytes as function of its first byte: */ -const unsigned char Xthal_byte0_format_lengths[256] = { - XCHAL_BYTE0_FORMAT_LENGTHS -}; - - -#elif defined(__SPLIT__disassemble_size) - -// -// Disassembly is currently not supported in xtensa hal. -// - -int xthal_disassemble_size( unsigned char *instr_buf ) -{ -#ifdef XCHAL_OP0_FORMAT_LENGTHS - /* Extract op0 field of instruction (first nibble used for decoding): */ -# if XCHAL_HAVE_BE - int op0 = ((*instr_buf >> 4) & 0xF); -# else - int op0 = (*instr_buf & 0xF); -# endif - /*return (op0 & 8) ? 2 : 3;*/ /* simple case only works consistently on older hardware */ - return Xthal_op0_format_lengths[op0]; -#else - return Xthal_byte0_format_lengths[*instr_buf]; -#endif -} - - -#elif defined(__SPLIT__disassemble) - -/* - * Note: we make sure to avoid the use of library functions, - * to minimize dependencies. - */ -int xthal_disassemble( - unsigned char *instr_buffer, /* the address of the instructions */ - void *tgt_address, /* where the instruction is to be */ - char *buffer, /* where the result goes */ - unsigned buflen, /* size of buffer */ - unsigned options /* what to display */ - ) -{ -#define OUTC(c) do{ if( p < endp ) *p = c; p++; }while(0) - int i, n; - char *p = buffer, *endp = buffer + buflen - 1; - /*static char *ret = " decoding not supported";*/ - static const char _hexc[16] = "0123456789ABCDEF"; - - n = xthal_disassemble_size( instr_buffer ); - - if( options & XTHAL_DISASM_OPT_ADDR ) { - unsigned addr = (unsigned)tgt_address; - for( i = 0; i < 8; i++ ) { - OUTC( _hexc[(addr >> 28) & 0xF] ); - addr <<= 4; - } - } - - if( options & XTHAL_DISASM_OPT_OPHEX ) { - if( p > buffer ) - OUTC( ' ' ); - for( i = 0; i < 3; i++ ) { - if( i < n ) { - OUTC( _hexc[(*instr_buffer >> 4) & 0xF] ); - OUTC( _hexc[*instr_buffer++ & 0xF] ); - } else { - OUTC( ' ' ); - OUTC( ' ' ); - } - OUTC( ' ' ); - } - } - - if( options & XTHAL_DISASM_OPT_OPCODE ) { - if( p > buffer ) - OUTC( ' ' ); - OUTC( '?' ); - OUTC( '?' ); - OUTC( '?' ); - OUTC( ' ' ); - OUTC( ' ' ); - OUTC( ' ' ); - OUTC( ' ' ); - } - - if( options & XTHAL_DISASM_OPT_PARMS ) { - if( p > buffer ) - OUTC( ' ' ); - OUTC( '?' ); - OUTC( '?' ); - OUTC( '?' ); - } - - if( p < endp ) - *p = 0; - else if( buflen > 0 ) - *endp = 0; - - return p - buffer; /* return length needed, even if longer than buflen */ -} - -#undef OUTC - - -#endif /*split*/ diff --git a/src/arch/xtensa/hal/int_asm.S b/src/arch/xtensa/hal/int_asm.S deleted file mode 100644 index 4ce36da45a26..000000000000 --- a/src/arch/xtensa/hal/int_asm.S +++ /dev/null @@ -1,643 +0,0 @@ -// -// int_asm.S - assembly language interrupt utility routines -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/int_asm.S#1 $ - -// Copyright (c) 2003-2010 Tensilica 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 <xtensa/coreasm.h> - - -#if XCHAL_HAVE_INTERRUPTS -/* Offsets of XtHalVPriState structure members (Xthal_vpri_state variable): */ -#define XTHAL_VPRI_VPRI_OFS 0x00 -#define XTHAL_VPRI_LOCKLEVEL_OFS 0x01 -#define XTHAL_VPRI_LOCKVPRI_OFS 0x02 -#define XTHAL_VPRI_PAD0_OFS 0x03 -#define XTHAL_VPRI_ENABLED_OFS 0x04 -#define XTHAL_VPRI_LOCKMASK_OFS 0x08 -#define XTHAL_VPRI_PAD1_OFS 0x0C -#define XTHAL_VPRI_ENABLEMAP_OFS 0x10 -#define XTHAL_VPRI_RESOLVEMAP_OFS (0x10+0x40*(XCHAL_NUM_INTLEVELS+1)) -#define XTHAL_VPRI_END_OFS (0x10+0x40*(XCHAL_NUM_INTLEVELS*2+1)) -#endif /* XCHAL_HAVE_INTERRUPTS */ - - -#if defined(__SPLIT__get_intenable) || \ - defined(__SPLIT__get_intenable_nw) - -//---------------------------------------------------------------------- -// Access INTENABLE register from C -//---------------------------------------------------------------------- - -// unsigned xthal_get_intenable(void) -// -DECLFUNC(xthal_get_intenable) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - rsr.intenable a2 -# else - movi a2, 0 // if no INTENABLE (no interrupts), tell caller nothing is enabled -# endif - abi_return - endfunc - -#endif - -#if defined(__SPLIT__set_intenable) || \ - defined(__SPLIT__set_intenable_nw) - -// void xthal_set_intenable(unsigned) -// -DECLFUNC(xthal_set_intenable) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - wsr.intenable a2 -# endif - abi_return - endfunc - - -//---------------------------------------------------------------------- -// Access INTERRUPT, INTSET, INTCLEAR register from C -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__get_interrupt) || \ - defined (__SPLIT__get_interrupt_nw) - -// unsigned xthal_get_interrupt(void) -// -DECLFUNC (xthal_get_interrupt) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - rsr.interrupt a2 -# else - movi a2, 0 // if no INTERRUPT (no interrupts), tell caller nothing is pending -# endif - abi_return - endfunc - -#endif - -#if defined(__SPLIT__get_intread) || \ - defined(__SPLIT__get_intread_nw) - -DECLFUNC (xthal_get_intread) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - rsr.interrupt a2 -# else - movi a2, 0 // if no INTERRUPT (no interrupts), tell caller nothing is pending -# endif - abi_return - endfunc - -#endif - -#if defined(__SPLIT__set_intset) || \ - defined(__SPLIT__set_intset_nw) - -// void xthal_set_intset(unsigned) -// -DECLFUNC(xthal_set_intset) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - wsr.intset a2 -# endif - abi_return - endfunc - -#endif - -#if defined(__SPLIT__set_intclear) || \ - defined(__SPLIT__set_intclear_nw) - -// void xthal_set_intclear(unsigned) -// -DECLFUNC(xthal_set_intclear) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - wsr.intclear a2 -# endif - abi_return - endfunc - - - -//---------------------------------------------------------------------- -// Virtual PS.INTLEVEL support: -// allows running C code at virtual PS.INTLEVEL > 0 -// using INTENABLE to simulate the masking that PS.INTLEVEL would do. -//---------------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__get_vpri) ||\ - defined(__SPLIT__get_vpri_nw) - -// unsigned xthal_get_vpri(void); - -DECLFUNC(xthal_get_vpri) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - movi a2, Xthal_vpri_state - l8ui a2, a2, XTHAL_VPRI_VPRI_OFS -# else - movi a2, 0 // no interrupts, report we're always at level 0 -# endif - abi_return - endfunc - -#endif - -#if defined(__SPLIT__set_vpri_nw) - -// unsigned xthal_set_vpri_nw(unsigned) -// -// Must be called at PS.INTLEVEL <= 1. -// Doesn't touch the stack (doesn't reference a1 at all). -// Normally, PS should be restored with a6 after return from this call -// (it isn't restored automatically because some exception handlers -// want to keep ints locked for a while). -// -// On entry: -// a2 = new virtual interrupt priority (0x00 .. 0x1F) -// a3-a6 = undefined -// PS.INTLEVEL <= 1 -// On exit: -// a2 = previous virtual interrupt priority (0x0F .. 0x1F, or 0 if no interrupts) -// a3-a5 = clobbered -// a6 = PS as it was on entry -// PS.INTLEVEL = 1 -// !!!!!!!!! PS.WOE = 0 (but not if there are no interrupts; is this really needed???) -// INTENABLE = updated according to new vpri - -_SYM(xthal_set_vpri_nw) - -# if XCHAL_HAVE_INTERRUPTS - /* Make sure a2 is in the range 0x0F .. 0x1F: */ - movi a3, 0x1F // highest legal virtual interrupt priority - sub a4, a2, a3 // (a4 = newlevel - maxlevel) - movgez a2, a3, a4 // newlevel = maxlevel if (newlevel - maxlevel) >= 0 - movi a3, 15 // lowest legal virtual interrupt priority - sub a4, a2, a3 // (a4 = newlevel - 15) - movltz a2, a3, a4 // newlevel = 15 if newlevel < 15 - -xthal_set_vpri_nw_common: - movi a4, Xthal_vpri_state // address of vpri state structure - - /* - * Lockout interrupts for exclusive access to virtual priority structure - * while we examine and modify it. - * Note that we accessed a4 and don't access any further than a6, - * so we won't cause any spills, so we could leave WOE enabled (if it is), - * but we clear it because that might be what the caller wants, - * and is cleaner. - */ - // Get PS and mask off INTLEVEL: - rsil a6, 1 // save a6 = PS, set PS.INTLEVEL = 1 - - // Clear PS.WOE. (Can we get rid of this?!!!!!): - movi a3, ~0x00040000 // mask to... - rsr.ps a5 // get and save a6 = PS -//a2,a3,a4,a5,a6 - and a5, a5, a3 // ... clear a5.WOE - wsr.ps a5 // clear PS.WOE - rsync - -//a2,a4,a6 - /* Get mask of interrupts to be turned off at requested level: */ - l32i a5, a4, XTHAL_VPRI_ENABLED_OFS // get the global mask - addx4 a3, a2, a4 // a3 = a4 + a2*4 (index into enablemap[] array) -//a2,a3,a4,a5,a6 - l32i a3, a3, XTHAL_VPRI_ENABLEMAP_OFS // get the per-level mask - and a3, a5, a3 // new INTENABLE value according to new intlevel - wsr.intenable a3 // set it! -//a2,a4,a6 - - l8ui a5, a4, XTHAL_VPRI_VPRI_OFS // previous virtual priority - s8i a2, a4, XTHAL_VPRI_VPRI_OFS // new virtual priority - - // Let the caller restore PS: - //wsr.ps a6 // restore PS.INTLEVEL - //rsync - - mov a2, a5 // return previous virtual intlevel - -# else /* ! XCHAL_HAVE_INTERRUPTS */ -xthal_set_vpri_nw_common: -# if XCHAL_HAVE_EXCEPTIONS - rsr.ps a6 // return PS for caller to restore -# else - movi a6, 0 -# endif - movi a2, 0 // no interrupts, report we're always at virtual priority 0 -# endif /* XCHAL_HAVE_INTERRUPTS */ - ret - endfunc - - - -// unsigned xthal_set_vpri_intlevel_nw(unsigned); -// -// Same as xthal_set_vpri_nw() except that it accepts -// an interrupt level rather than a virtual interrupt priority. -// This just converts intlevel to vpri and jumps to xthal_set_vpri_nw. - -_SYM(xthal_set_vpri_intlevel_nw) -# if XCHAL_HAVE_INTERRUPTS - movi a3, 0x10 - movnez a2, a3, a2 // a2 = (a2 ? 0x10 : 0) - addi a2, a2, 0x0F // a2 += 0x0F -# endif - j xthal_set_vpri_nw_common // set vpri to a2 - endfunc - - - -#endif - -#if defined(__SPLIT__set_vpri) - -// unsigned xthal_set_vpri (unsigned newvpri); -// -// Normal windowed call (PS.INTLEVEL=0 and PS.WOE=1 on entry and exit). -// (PS.UM = 0 or 1) -// -// Returns previous virtual interrupt priority -// (0x0F .. 0x1F, or 0 if no interrupts). -// -// On entry: -// a2 = new virtual interrupt priority (0x00 .. 0x1F) -// On exit: -// a2 = previous vpri -// INTENABLE = updated according to new vpri - -DECLFUNC(xthal_set_vpri) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - /* Make sure a2 is in the range 0x0F .. 0x1F: */ - movi a3, 0x1F // highest legal virtual interrupt priority - sub a4, a2, a3 // (a4 = newlevel - maxlevel) - movgez a2, a3, a4 // newlevel = maxlevel if (newlevel - maxlevel) >= 0 - movi a3, 15 // lowest legal virtual interrupt priority - sub a4, a2, a3 // (a4 = newlevel - 15) - movltz a2, a3, a4 // newlevel = 15 if newlevel < 15 - -xthal_set_vpri_common1: - movi a4, Xthal_vpri_state // address of vpri state structure - - /* - * Lockout interrupts for exclusive access to virtual priority structure - * while we examine and modify it. - * Note that we accessed a4 and don't access any further than a6, - * so we won't cause any spills, so we can leave WOE enabled. - */ - // Get PS and mask off INTLEVEL: - rsil a6, 1 // save a6 = PS, set PS.INTLEVEL = 1 - - l8ui a7, a4, XTHAL_VPRI_VPRI_OFS // previous virtual priority (vpri) - - /* Get mask of interrupts to be turned off at requested level: */ - l32i a5, a4, XTHAL_VPRI_ENABLED_OFS // get the global mask - addx4 a3, a2, a4 // a3 = a4 + a2*4 (index into enablemap[] array) - l32i a3, a3, XTHAL_VPRI_ENABLEMAP_OFS // get the per-level mask - s8i a2, a4, XTHAL_VPRI_VPRI_OFS // new virtual priority (in load-slot) - and a3, a5, a3 // new INTENABLE value according to new intlevel - wsr.intenable a3 // set it! - - wsr.ps a6 // restore PS.INTLEVEL - rsync - - mov a2, a7 // return previous vpri - -# else /* ! XCHAL_HAVE_INTERRUPTS */ - movi a2, 0 // no interrupts, report we're always at virtual priority 0 -# endif /* XCHAL_HAVE_INTERRUPTS */ - abi_return - endfunc - - - -// unsigned xthal_set_vpri_intlevel (unsigned intlevel); -// -// Equivalent to xthal_set_vpri(XTHAL_VPRI(intlevel,0xF)). -// This just converts intlevel to vpri and jumps inside xthal_set_vpri. - -DECLFUNC(xthal_set_vpri_intlevel) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - movi a3, 0x10 - movnez a2, a3, a2 // a2 = (a2 ? 0x10 : 0) - addi a2, a2, 0x0F // a2 += 0x0F - j xthal_set_vpri_common1 // set vpri to a2 -# else - movi a2, 0 // no interrupts, report we're always at virtual priority 0 - abi_return -# endif - endfunc - - - -// unsigned xthal_set_vpri_lock (void); -// -// Equivalent to xthal_set_vpri(0x1F); -// Returns previous virtual interrupt priority. -// -DECLFUNC(xthal_set_vpri_lock) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - movi a2, 0x1F // lock at intlevel 1 - j xthal_set_vpri_common1 -# else - movi a2, 0 // no interrupts, report we're always at virtual priority 0 - abi_return -# endif - endfunc - - -#endif - -#if defined(__SPLIT__get_intpending_nw) - -// unsigned xthal_get_intpending_nw(void) -// -// Of the pending level-1 interrupts, returns -// the bitmask of interrupts at the highest software priority, -// and the index of the first of these. -// It also disables interrupts of that software priority and lower -// via INTENABLE. -// -// On entry: -// a0 = return PC -// a1 = sp -// a2-a6 = (available) (undefined) -// PS.INTLEVEL = 1 -// PS.WOE = 0 -// On exit: -// a0 = return PC -// a1 = sp (NOTE: stack is untouched, a1 is never referenced) -// a2 = index of first highest-soft-pri pending l1 interrupt (0..31), or -1 if none -// a3 = bitmask of highest-soft-pri pending l1 interrupts (0 if none) (may be deprecated) -// a4 = (clobbered) -// a5 = new vpri (not typically used by caller? so might get deprecated...?) -// a6 = old vpri (eg. to be saved as part of interrupt context's state) -// INTENABLE = updated according to new vpri -// INTERRUPT bit cleared for interrupt returned in a2 (if any), if software or edge-triggered or write-error -// all others = preserved - -_SYM(xthal_get_intpending_nw) -# if XCHAL_HAVE_INTERRUPTS - // Give us one more register to play with - //wsr.excsave1 a4 - - // Figure out which interrupt to process - - /* - Perform a binary search to find a mask of the interrupts that are - ready at the highest virtual priority level. - Xthal_vpri_resolvemap is a binary tree implemented within an array, - sorted by priority: each node contains the set of interrupts in - the range of priorities corresponding to the right half of its branch. - The mask of enabled & pending interrupts is compared with each node to - determine in which subbranch (left or right) the highest priority one is - present. After 4 such masks and comparisons (for 16 priorities), we have - determined the priority of the highest priority enabled&pending interrupt. - - Table entries for intlevel 'i' are bitmasks defined as follows (map=Xthal_vpri_resolvemap[i-1]): - map[8+(x=0)] = ints at pri x + 8..15 (8-15) - map[4+(x=0,8)] = ints at pri x + 4..7 (4-7,12-15) - map[2+(x=0,4,8,12)] = ints at pri x + 2..3 (2-3,6-7,10-11,14-15) - map[1+(x=0,2..12,14)] = ints at pri x + 1 (1,3,5,7,9,11,13,15) - map[0] = 0 (unused; for alignment) - */ - - rsr.interrupt a4 // a4 = mask of interrupts pending, including those disabled - rsr.intenable a2 // a2 = mask of interrupts enabled - movi a3, Xthal_vpri_state - and a4, a2, a4 // a4 = mask of enabled interrupts pending - beqz a4, gipfail // if none (can happen for spurious level-triggered interrupts, - // or ???), we're done - - mov a5, a3 - l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+8*4 - bnone a2, a4, 1f - addi a5, a5, 8*4 -1: l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+4*4 - bnone a2, a4, 1f - addi a5, a5, 4*4 -1: l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+2*4 - bnone a2, a4, 1f - addi a5, a5, 2*4 -1: l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+1*4 - bnone a2, a4, 1f - addi a5, a5, 1*4 -1: - -# if 0 - a5 = address of map ... - l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+8*4 - addi a?, a5, 8*4 - and a2, a2, a4 - movnez a5, a?, a2 - l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+4*4 - addi a?, a5, 4*4 - and a2, a2, a4 - movnez a5, a?, a2 - l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+2*4 - addi a?, a5, 2*4 - and a2, a2, a4 - movnez a5, a?, a2 - l32i a2, a5, XTHAL_VPRI_RESOLVEMAP_OFS+1*4 - addi a?, a5, 1*4 - and a2, a2, a4 - movnez a5, a?, a2 -# endif - - // Here: - // a3 = Xthal_vpri_state - // a5 = Xthal_vpri_state + softpri*4 - // a4 = mask of enabled interrupts pending - // a2,a6 = available - - // Lock interrupts during virtual priority data structure transaction: - //rsil a6, 1 // set PS.INTLEVEL = 1 (a6 ignored) - // a2,a6 = available - - // The highest priority interrupt(s) in a4 is at softpri = (a5-a3) / 4. - // So interrupts in enablemap[1][softpri] are not in a4 (they are higher priority). - // The set of interrupts at softpri are: - // enablemap[1][softpri-1] - enablemap[1][softpri] - // So and'ing a4 with enablemap[1][softpri - 1] will give us - // the set of interrupts pending at the highest soft priority. - // - l32i a2, a5, XTHAL_VPRI_ENABLEMAP_OFS + 16*4 - 4 // get enablemap[1][softpri-1] - and a4, a2, a4 // only keep interrupts of highest pri (softpri) - - // a4 now has mask of pending interrupts at highest ready level (new vpri) - - // Update INTENABLE for this new virtual priority - l32i a2, a5, XTHAL_VPRI_ENABLEMAP_OFS + 16*4 // get vpri-specific mask = enablemap[1][softpri] - l32i a6, a3, XTHAL_VPRI_ENABLED_OFS // get global mask - sub a5, a5, a3 // a5 = softpri * 4 (for below; here for efficiency) - and a2, a2, a6 // and together - wsr.intenable a2 // disable interrupts at or below new vpri - // a2,a6 = available - - // Update new virtual priority: - l8ui a6, a3, XTHAL_VPRI_VPRI_OFS // get old vpri (returned) - srli a5, a5, 2 // a5 = softpri (0..15) - addi a5, a5, 0x10 // a5 = 0x10 + softpri = new virtual priority - s8i a5, a3, XTHAL_VPRI_VPRI_OFS // store new vpri (returned) - - // Undo the temporary lock (if was at PS.INTLEVEL > 1): - //rsil a2, 1 - - mov a3, a4 // save for the caller (in case it wants it?) - - // Choose one of the set of highest-vpri pending interrupts to process. - // For speed (and simplicity), use this simple two-instruction sequence - // to select the least significant bit set in a4. This implies that - // interrupts with a lower interrupt number take precedence over those - // with a higher interrupt number (!!). - // - neg a2, a4 // keep only the least-significant bit that is set... - and a4, a2, a4 // ... in a4 - - // Software, edge-triggered, and write-error interrupts are cleared by writing to the - // INTCLEAR pseudo-reg (to clear relevant bits of the INTERRUPT register). - // To simplify interrupt handlers (so they avoid tracking which type of - // interrupt they handle and act accordingly), clear such interrupts here. - // To avoid race conditions, the clearing must occur *after* we undertake - // to process the interrupt, and *before* actually handling the interrupt. - // Interrupt handlers may additionally clear the interrupt themselves - // at appropriate points if needed to avoid unnecessary interrupts. - // -#define CLEARABLE_INTLEVEL1_MASK (XCHAL_INTLEVEL1_MASK & XCHAL_INTCLEARABLE_MASK) -# if CLEARABLE_INTLEVEL1_MASK != 0 - //movi a2, CLEARABLE_INTLEVEL1_MASK - //and a2, a2, a4 - //wsr.intclear a2 - wsr.intclear a4 // no effect if a4 not a software or edge-triggered or write-error interrupt -# endif - - // Convert the single-bit interrupt mask to an interrupt number. - // (ie. compute log2 using either the NSAU instruction or a binary search) - - find_ms_setbit a2, a4, a2, 0 // set a2 to index of lsbit set in a4 (0..31) - // NOTE: assumes a4 != 0 (otherwise a2 is undefined[?]) - - // a2 has vector number (0..31) - - //rsr.excsave1 a4 - ret - -gipfail: - l8ui a6, a3, XTHAL_VPRI_VPRI_OFS // get old vpri - mov a5, a6 // is also new vpri (unchanged) -# else /* XCHAL_HAVE_INTERRUPTS */ - // No interrupts configured! - movi a5, 0 // return zero new vpri - movi a6, 0 // return zero old vpri -# endif /* XCHAL_HAVE_INTERRUPTS */ - movi a2, -1 // return bogus vector number (eg. can be quickly tested for negative) - movi a3, 0 // return zero bitmask of interrupts pending - ret - endfunc - -// ----------------------------------------------------------------- - -#endif - -#if defined(__SPLIT__vpri_lock) || \ - defined(__SPLIT__vpri_lock_nw) - -// void xthal_vpri_lock() -// -// Used internally by the Core HAL to block interrupts of higher or equal -// priority than Xthal_vpri_locklevel during virtual interrupt operations. -// -DECLFUNC(xthal_vpri_lock) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - rsil a6, 1 // save a6 = PS, set PS.INTLEVEL = 1 - - // if( Xthal_vpri_level < Xthal_vpri_locklevel ) - // - movi a2, Xthal_vpri_state // a2 := address of global var. Xthal_vpri_state - //interlock - l8ui a3, a2, XTHAL_VPRI_VPRI_OFS // a3 := Xthal_vpri_level == Xthal_vpri_state.vpri - l8ui a5, a2, XTHAL_VPRI_LOCKLEVEL_OFS // a5 := Xthal_vpri_locklevel - l32i a4, a2, XTHAL_VPRI_ENABLED_OFS // a4 := Xthal_vpri_enabled - bgeu a3, a5, xthal_vpri_lock_done - - // xthal_set_intenable( Xthal_vpri_enablemap[0][Xthal_vpri_locklevel] & Xthal_vpri_enabled ); - // - addx4 a3, a5, a2 // a3 := a2 + a5*4 (index into enablemap[] array) - l32i a3, a3, XTHAL_VPRI_ENABLEMAP_OFS // a3 := Xthal_vpri_enablemap[0][Xthal_vpri_locklevel] - //interlock - and a2, a4, a3 - wsr.intenable a2 - -xthal_vpri_lock_done: - wsr.ps a6 // restore PS.INTLEVEL - rsync -# endif - abi_return - endfunc - -#endif - -#if defined(__SPLIT__vpri_unlock) || \ - defined(__SPLIT__vpri_unlock_nw) - -// void xthal_vpri_unlock(void) -// -// Enable interrupts according to the current virtual interrupt priority. -// This effectively "unlocks" interrupts disabled by xthal_vpri_lock() -// (assuming the virtual interrupt priority hasn't changed). -// -DECLFUNC(xthal_vpri_unlock) - abi_entry -# if XCHAL_HAVE_INTERRUPTS - // - // This should be free of race-conditions. - // - // xthal_set_intenable( Xthal_vpri_enablemap[0][Xthal_vpri_level] & Xthal_vpri_enabled ); - // - movi a2, Xthal_vpri_state // a2 := address of global var. Xthal_vpri_state - //interlock - l8ui a3, a2, XTHAL_VPRI_VPRI_OFS // a3 := Xthal_vpri_level == Xthal_vpri_state.vpri - l32i a4, a2, XTHAL_VPRI_ENABLED_OFS // a4 := Xthal_vpri_enabled - addx4 a3, a3, a2 // a3 := a2 + a3*4 (index into enablemap[] array) - l32i a3, a3, XTHAL_VPRI_ENABLEMAP_OFS // a3 := Xthal_vpri_enablemap[0][Xthal_vpri_level] - //interlock - and a2, a4, a3 - wsr.intenable a2 -# endif - abi_return - endfunc - -#endif /*SPLIT*/ - diff --git a/src/arch/xtensa/hal/interrupts.c b/src/arch/xtensa/hal/interrupts.c deleted file mode 100644 index 1bf8bd99c559..000000000000 --- a/src/arch/xtensa/hal/interrupts.c +++ /dev/null @@ -1,850 +0,0 @@ -// -// interrupts.c - interrupts related constants and functions -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/interrupts.c#1 $ - -// Copyright (c) 2002-2004 Tensilica 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 <xtensa/config/core.h> - -#if XCHAL_HAVE_INTERRUPTS - -/* For internal use by the HAL: */ -// static void xthal_vpri_lock(void); -// static void xthal_vpri_unlock(void); -extern void xthal_vpri_lock(void); -extern void xthal_vpri_unlock(void); - - -/* - * Definitions: - * - * Virtual interrupt level = 0 .. 0xFF - * - * ... - */ - -#define XTHAL_DEFAULT_SOFTPRI 4 /* default software priority (range 0..15) */ - /* IMPORTANT: if you change this, you also - need to update the initial resolvemap[] - value below... */ - -/* - * Macros to convert between: - * intlevel (0..15) and software priority within an intlevel (0..15) - * and - * virtual interrupt priority (0..0xFF), which is a combination of the above two. - */ -#define XTHAL_VPRI_INTLEVEL(vpri) (((vpri) >> 4) & 0xF) -#define XTHAL_VPRI_SOFTPRI(vpri) ((vpri) & 0xF) -#define XTHAL_VPRI(intlevel,softpri) ((((intlevel)&0xF)<<4)|((softpri)&0xF)) - - -/* - * Virtual priority management data structures. - * This structure is instantiated as Xthal_vpri_state (below). - * - * IMPORTANT: if you change anything in this structure, - * you must accordingly change structure offsets - * defined in int_asm.S . - * - * IMPORTANT: the worst-case offset of the resolvemap[] field is 976 bytes - * (0x10 + 0x40*15), which is accessed in int_asm.S at a further - * offset of 8*4==32 for a total offset of 1008, very close - * to l32i's offset limit of 1020. So you can't push it much - * further. - * - * [INTERNAL NOTE: There might be a trick that will save 64 bytes, - * if really needed, by trimming 15 word entries from the start - * of enablemap[] ... -MG] - */ -typedef struct XtHalVPriState { - /* - * Current virtual interrupt priority (0x0F .. 0xFF) - * (or actually, 0x0F .. XCHAL_NUM_INTLEVELS*0x10+0x0F). - * Virtual priorities 0x00 to 0x0E are mapped to 0x0F (they're all - * equivalent, because there's no such thing as a level 0 interrupt), - * which may help optimize the size of enablemap[] in the future. - * Virtual priorities above XCHAL_NUM_INTLEVELS*0x10+0x0F are - * mapped to XCHAL_NUM_INTLEVELS*0x10+0x0F, which is equivalent. - * - * NOTE: this variable is actually part of the processor context, - * which means (for most OSes) that it must be saved - * in the task control block along with other register state. - */ - unsigned char vpri; // current virtual interrupt priority (0x0F..0xFF) - unsigned char locklevel; // real interrupt level used to get exclusive - // access to this structure; MUST be at least one (1) - unsigned char lockvpri; // virtual interrupt level used to get exclusive - // access to this structure; MUST be XTHAL_VPRI(locklevel,15) - // (so it's at least 0x1F); placed here for efficiency - unsigned char pad0; // (alignment padding, unused) - - unsigned enabled; // mask of which interrupts are enabled, regardless of level - // (level masking is applied on top of this) - - unsigned lockmask; // (unused?) INTENABLE value used to lock out - // interrupts for exclusive access to this structure - - unsigned pad1; // (alignment padding, unused) - - /* - * For each virtual interrupt priority, this array provides the - * bitmask of interrupts of greater virtual priority - * (ie. the set of interrupts to enable at that virtual priority, - * if all interrupts were enabled in field 'enabled'). - */ - unsigned enablemap[XCHAL_NUM_INTLEVELS+1][16]; - - /* - * Table entries for intlevel 'i' are bitmasks defined as follows, - * with map == Xthal_vpri_resolvemap[i-1]: - * map[8+(x=0)] = ints at pri x + 8..15 (8-15) - * map[4+(x=0,8)] = ints at pri x + 4..7 (4-7,12-15) - * map[2+(x=0,4,8,12)] = ints at pri x + 2..3 (2-3,6-7,10-11,14-15) - * map[1+(x=0,2..12,14)] = ints at pri x + 1 (1,3,5,7,9,11,13,15) - * map[0] = 0 (unused; for alignment) - */ - unsigned resolvemap[XCHAL_NUM_INTLEVELS][16]; - -} XtHalVPriState; - - -extern XtHalVPriState Xthal_vpri_state; -extern unsigned char Xthal_int_vpri[32]; -extern XtHalVoidFunc * Xthal_tram_trigger_fn; - -extern void xthal_null_func(void); - -/* Shorthand for structure members: */ -#define Xthal_vpri_level Xthal_vpri_state.vpri -#define Xthal_vpri_locklevel Xthal_vpri_state.locklevel -#define Xthal_vpri_lockvpri Xthal_vpri_state.lockvpri -#define Xthal_vpri_enabled Xthal_vpri_state.enabled -#define Xthal_vpri_lockmask Xthal_vpri_state.lockmask // unused? -#define Xthal_vpri_enablemap Xthal_vpri_state.enablemap -#define Xthal_vpri_resolvemap Xthal_vpri_state.resolvemap -#if 0 -Combined refs: - - enablemap, vpri, enabled (xthal_set_vpri[_nw]) - - enablemap, vpri, enabled, resolvemap (xthal_get_intpending_nw) - - enablemap, vpri, enabled, locklevel (xthal_vpri_lock) - - enablemap, vpri, enabled (xthal_vpri_unlock) -#endif - -#endif /* XCHAL_HAVE_INTERRUPTS */ - - - -#if defined(__SPLIT__num_intlevels) - -// the number of interrupt levels -const unsigned char Xthal_num_intlevels = XCHAL_NUM_INTLEVELS; - -#endif - -#if defined(__SPLIT__num_interrupts) - -// the number of interrupts -const unsigned char Xthal_num_interrupts = XCHAL_NUM_INTERRUPTS; - -#endif - -#if defined(__SPLIT__excm_level) - -// the highest level of interrupts masked by PS.EXCM (if XEA2) -const unsigned char Xthal_excm_level = XCHAL_EXCM_LEVEL; - -#endif - -#if defined(__SPLIT__intlevel_mask) - -// mask of interrupts at each intlevel -const unsigned Xthal_intlevel_mask[16] = { - XCHAL_INTLEVEL_MASKS -}; - -#endif - -#if defined(__SPLIT__intlevel_andbelow_mask) - -// mask for level 1 to N interrupts -const unsigned Xthal_intlevel_andbelow_mask[16] = { - XCHAL_INTLEVEL_ANDBELOW_MASKS -}; - -#endif - -#if defined(__SPLIT__intlevel) - -// level per interrupt -const unsigned char Xthal_intlevel[32] = { - XCHAL_INT_LEVELS -}; - -#endif - -#if defined(__SPLIT__inttype) - -// type of each interrupt -const unsigned char Xthal_inttype[32] = { - XCHAL_INT_TYPES -}; - -#endif - -#if defined(__SPLIT__inttype_mask) - -const unsigned Xthal_inttype_mask[XTHAL_MAX_INTTYPES] = { - XCHAL_INTTYPE_MASKS -}; - -#endif - -#if defined(__SPLIT__timer_interrupt) - -// interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned -const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS] = { - XCHAL_TIMER_INTERRUPTS -}; - -#endif - -#if defined(__SPLIT__vpri) - -#if XCHAL_HAVE_INTERRUPTS - -/* - * Note: this structure changes dynamically at run-time, - * but is initialized here for efficiency and simplicity, - * according to configuration. - */ -XtHalVPriState Xthal_vpri_state = { - 0x00, /* vpri */ - 1, /* locklevel */ - 0x1F, /* lockvpri */ - 0, /* pad0 */ - 0x00000000, /* enabled */ - 0x00000000, /* lockmask (unused?) */ - 0, /* pad1 */ - -#define DEFAULT_ENABLEMAP(levela,levelb) \ - { (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 0 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 1 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 2 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 3 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 4 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 5 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 6 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 7 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 8 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 9 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >10 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >11 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >12 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >13 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >14 ? levela : levelb)), \ - (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >15 ? levela : levelb)) } - - /* Xthal_vpri_enablemap[XCHAL_NUM_INTLEVELS+1][16]: */ - { - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL0_ANDBELOW_MASK,XCHAL_INTLEVEL0_ANDBELOW_MASK), -#if XCHAL_NUM_INTLEVELS >= 1 - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL0_ANDBELOW_MASK,XCHAL_INTLEVEL1_ANDBELOW_MASK), -#endif -#if XCHAL_NUM_INTLEVELS >= 2 - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL1_ANDBELOW_MASK,XCHAL_INTLEVEL2_ANDBELOW_MASK), -#endif -#if XCHAL_NUM_INTLEVELS >= 3 - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL2_ANDBELOW_MASK,XCHAL_INTLEVEL3_ANDBELOW_MASK), -#endif -#if XCHAL_NUM_INTLEVELS >= 4 - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL3_ANDBELOW_MASK,XCHAL_INTLEVEL4_ANDBELOW_MASK), -#endif -#if XCHAL_NUM_INTLEVELS >= 5 - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL4_ANDBELOW_MASK,XCHAL_INTLEVEL5_ANDBELOW_MASK), -#endif -#if XCHAL_NUM_INTLEVELS >= 6 - DEFAULT_ENABLEMAP(XCHAL_INTLEVEL5_ANDBELOW_MASK,XCHAL_INTLEVEL6_ANDBELOW_MASK), -#endif -#if XCHAL_NUM_INTLEVELS >= 7 -# error Interrupt levels greater than 6 not currently supported in the HAL interrupt routines. -#endif - }, - - /* Xthal_vpri_resolvemap[XCHAL_NUM_INTLEVELS][16]: */ - { -#if XCHAL_NUM_INTLEVELS >= 1 /* set for default soft priority of 4: */ - {0,0,0,0, XCHAL_INTLEVEL1_MASK,0,0,0, 0,0,0,0, 0,0,0,0}, -#endif -#if XCHAL_NUM_INTLEVELS >= 2 /* set for default soft priority of 4: */ - {0,0,0,0, XCHAL_INTLEVEL2_MASK,0,0,0, 0,0,0,0, 0,0,0,0}, -#endif -#if XCHAL_NUM_INTLEVELS >= 3 /* set for default soft priority of 4: */ - {0,0,0,0, XCHAL_INTLEVEL3_MASK,0,0,0, 0,0,0,0, 0,0,0,0}, -#endif -#if XCHAL_NUM_INTLEVELS >= 4 /* set for default soft priority of 4: */ - {0,0,0,0, XCHAL_INTLEVEL4_MASK,0,0,0, 0,0,0,0, 0,0,0,0}, -#endif -#if XCHAL_NUM_INTLEVELS >= 5 /* set for default soft priority of 4: */ - {0,0,0,0, XCHAL_INTLEVEL5_MASK,0,0,0, 0,0,0,0, 0,0,0,0}, -#endif -#if XCHAL_NUM_INTLEVELS >= 6 /* set for default soft priority of 4: */ - {0,0,0,0, XCHAL_INTLEVEL6_MASK,0,0,0, 0,0,0,0, 0,0,0,0}, -#endif -#if XCHAL_NUM_INTLEVELS >= 7 /* set for default soft priority of 4: */ -# error Interrupt levels greater than 6 not currently supported in the HAL interrupt routines. -#endif - } - -}; - - -/* - * Virtual (software) priority (0x00..0xFF) of each interrupt. - * This isn't referenced by assembler. - */ -unsigned char Xthal_int_vpri[32] = { -#define DEFAULT_INTVPRI(level) (level ? ((level << 4) | XTHAL_DEFAULT_SOFTPRI) : 0) - DEFAULT_INTVPRI( XCHAL_INT0_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT1_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT2_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT3_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT4_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT5_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT6_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT7_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT8_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT9_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT10_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT11_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT12_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT13_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT14_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT15_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT16_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT17_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT18_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT19_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT20_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT21_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT22_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT23_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT24_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT25_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT26_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT27_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT28_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT29_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT30_LEVEL ), - DEFAULT_INTVPRI( XCHAL_INT31_LEVEL ) -}; - - -#if 0 -/* - * A number of things may have already been written not calling - * this function, so it isn't straightforward to start requiring it: - */ -void xthal_vpri_init( int default_vpri ) -{ - int i, j; - - Xthal_vpri_level = 0; /* vpri */ - Xthal_vpri_locklevel = 1; /* locklevel */ - Xthal_vpri_lockvpri = 0x1F; /* lockvpri */ - Xthal_vpri_enabled = 0x00000000; /* enabled */ - Xthal_vpri_lockmask = 0x00000000; /* lockmask (unused?) */ - for( i = 0; i < XCHAL_NUM_INTLEVELS; i++ ) { - for( j = 0; j < 16; j++ ) - Xthal_vpri_enablemap[i][j] = XCHAL_INTLEVEL15_ANDBELOW_MASK - & ~Xthal_intlevel_andbelow_mask[i - (j < default_vpri && i > 0)]; - } - for( i = 1; i < XCHAL_NUM_INTLEVELS; i++ ) { - for( j = 0; j < 16; j++ ) - Xthal_vpri_resolvemap[i-1][j] = 0; - if( (default_vpri & 1) != 0 ) - Xthal_vpri_resolvemap[i-1][default_vpri & 0xF] |= Xthal_intlevel_mask[i]; - if( (default_vpri & 2) != 0 ) - Xthal_vpri_resolvemap[i-1][default_vpri & 0xE] |= Xthal_intlevel_mask[i]; - if( (default_vpri & 4) != 0 ) - Xthal_vpri_resolvemap[i-1][default_vpri & 0xC] |= Xthal_intlevel_mask[i]; - if( (default_vpri & 8) != 0 ) - Xthal_vpri_resolvemap[i-1][default_vpri & 0x8] |= Xthal_intlevel_mask[i]; - } - for( i = 0; i < 32; i++ ) - Xthal_int_vpri[i] = (Xthal_intlevel[i] << 4) | (default_vpri & 0xF); -} -#endif /*0*/ - -void xthal_null_func(void) { } -XtHalVoidFunc *Xthal_tram_trigger_fn = xthal_null_func; - - -#endif /* XCHAL_HAVE_INTERRUPTS */ - -#endif - -#if defined(__SPLIT__vpri_to_intlevel) - -/* - * xthal_vpri_to_intlevel - * - * Converts a virtual interrupt priority to the closest equivalent - * (equal or higher) interrupt level. - */ -unsigned xthal_vpri_to_intlevel(unsigned vpri) -{ -#if XCHAL_HAVE_INTERRUPTS - return( XTHAL_VPRI_INTLEVEL( vpri ) ); -#else - return( vpri ); -#endif -} - -#endif - -#if defined(__SPLIT__intlevel_to_vpri) - -/* - * xthal_intlevel_to_vpri - * - * Converts an interrupt level to a virtual interrupt priority. - */ -unsigned xthal_intlevel_to_vpri(unsigned intlevel) -{ -#if XCHAL_HAVE_INTERRUPTS - return( XTHAL_VPRI( intlevel, 0xF ) ); -#else - return( intlevel ); -#endif -} - -#endif - -#if defined(__SPLIT__vpri_int_enable) - -/* - * xthal_int_enable - * - * Enables given set of interrupts, and returns previous enabled-state of these interrupts. - */ -unsigned xthal_int_enable(unsigned mask) -{ -#if XCHAL_HAVE_INTERRUPTS - unsigned prev_enabled, syncmask; - - xthal_vpri_lock(); - prev_enabled = Xthal_vpri_enabled | Xthal_tram_enabled; - - /* Figure out which bits must go in Xthal_tram_enabled: */ - syncmask = (mask & Xthal_tram_pending & Xthal_tram_sync); - if( syncmask != 0 ) { - Xthal_tram_enabled |= syncmask; - mask &= ~syncmask; - /* - * If we are re-enabling a pending trampolined interrupt, - * there is a possibility that the level-1 software interrupt - * is no longer pending, having already occurred (without processing - * the trampoline because it was disabled). So we have to - * ensure that the level-1 software interrupt used for trampolining - * is pending. - * We let the BSP do this rather than the HAL, because it could - * potentially use an external level-1 interrupt to trampoline - * (if proper hardware was available) rather than a software interrupt. - */ - (*Xthal_tram_trigger_fn)(); - } - /* The rest go in the global enabled mask: */ - Xthal_vpri_enabled |= mask; - - xthal_vpri_unlock(); /* update INTENABLE as per current vpri */ - return( prev_enabled ); - -#else /* XCHAL_HAVE_INTERRUPTS */ - return( 0 ); -#endif /* XCHAL_HAVE_INTERRUPTS */ -} - -#endif - -#if defined(__SPLIT__vpri_int_disable) - -/* - * xthal_int_disable - * - * Disables given set of interrupts, and returns previous enabled-state of these interrupts. - */ -unsigned xthal_int_disable(unsigned mask) -{ -#if XCHAL_HAVE_INTERRUPTS - unsigned prev_enabled; - - xthal_vpri_lock(); - prev_enabled = Xthal_vpri_enabled | Xthal_tram_enabled; - Xthal_vpri_enabled &= ~mask; - Xthal_tram_enabled &= ~mask; - xthal_vpri_unlock(); /* update INTENABLE as per current vpri */ - return( prev_enabled ); -#else - return( 0 ); -#endif -} - -#endif - -#if defined(__SPLIT__set_vpri_locklevel) - -void xthal_set_vpri_locklevel(unsigned intlevel) -{ -#if XCHAL_HAVE_INTERRUPTS - if( intlevel < 1 ) - intlevel = 1; - else if( intlevel > XCHAL_NUM_INTLEVELS ) - intlevel = XCHAL_NUM_INTLEVELS; - Xthal_vpri_state.locklevel = intlevel; - Xthal_vpri_state.lockvpri = XTHAL_VPRI(intlevel, 15); -#endif -} - -#endif - -#if defined(__SPLIT__get_vpri_locklevel) - -unsigned xthal_get_vpri_locklevel(void) -{ -#if XCHAL_HAVE_INTERRUPTS - return( Xthal_vpri_state.locklevel ); -#else - return( 1 ); /* must return at least 1, some OSes assume this */ -#endif -} - -#endif - -#if defined(__SPLIT__set_int_vpri) - -/* - * xthal_set_int_vpri (was intSetL1Pri) - * - * Set the virtual (software) priority of an interrupt. - * Note: the intlevel of an interrupt CANNOT be changed -- this is - * set in hardware according to the core configuration file. - * - * intnum interrupt number (0..31) - * vpri virtual interrupt priority (0..15, or intlevel*16+(0..15) ) - */ -int xthal_set_int_vpri(int intnum, int vpri) -{ -#if XCHAL_HAVE_INTERRUPTS - unsigned mask, maskoff, basepri, prevpri, intlevel, *maskp, i; - - /* - * Verify parameters: - */ - if( (unsigned)intnum >= XCHAL_NUM_INTERRUPTS || (unsigned)vpri > 0xFF ) - return( 0 ); /* error: bad parameter(s) */ - /* - * If requested priority specifies an intlevel, it must match that - * of the interrupt specified; otherwise (0..15) the proper intlevel of - * the specified interrupt is assumed, and added to the parameter: - */ - intlevel = Xthal_intlevel[intnum]; /* intnum's intlevel */ - if( intlevel == 0 || intlevel > XCHAL_NUM_INTLEVELS ) - return( 0 ); /* error: no support for setting priority of NMI etc. */ - basepri = intlevel << 4; /* intnum's base soft-pri. */ - if( vpri > 0x0F ) { /* intlevel portion given? */ - if( (vpri & 0xF0) != basepri ) /* then it must be correct */ - return( 0 ); /* error: intlevel mismatch */ - vpri &= 0x0F; /* remove it */ - } - - mask = 1L << intnum; - - /* - * Lock interrupts during virtual priority data structure updates: - */ - xthal_vpri_lock(); - - /* - * Update virtual priority of 'intnum': - */ - prevpri = Xthal_int_vpri[intnum]; /* save for return value */ - Xthal_int_vpri[intnum] = basepri | vpri; - /* This interrupt must only be enabled at virtual priorities lower than its own: */ - for( i = 0; i < vpri; i++ ) - Xthal_vpri_enablemap[0][basepri++] |= mask; - maskoff = ~mask; - for( ; i <= 0x0F; i++ ) - Xthal_vpri_enablemap[0][basepri++] &= maskoff; - - /* - * Update the prioritization table used to resolve priorities by binary search: - */ - /* Remove interrupt <intnum> from prioritization table: */ - maskp = Xthal_vpri_resolvemap[intlevel-1]; - for (i=0; i<16; i++) - maskp[i] &= maskoff; - /* Add interrupt <intnum> to prioritization table at its (new) given priority: */ - if( vpri & 0x1 ) - maskp[vpri] |= mask; - if( vpri & 0x2 ) - maskp[vpri & 0xE] |= mask; - if( vpri & 0x4 ) - maskp[vpri & 0xC] |= mask; - if( vpri & 0x8 ) - maskp[vpri & 0x8] |= mask; - - /* - * Unlock interrupts (back to current level) and update INTENABLE: - */ - xthal_vpri_unlock(); - - return( prevpri ); -#else /* XCHAL_HAVE_INTERRUPTS */ - return( 0 ); -#endif /* XCHAL_HAVE_INTERRUPTS */ -} /* xthal_set_int_vpri */ - -#endif - -#if defined(__SPLIT__get_int_vpri) - -int xthal_get_int_vpri(int intnum) -{ -#if XCHAL_HAVE_INTERRUPTS - if( (unsigned)intnum >= XCHAL_NUM_INTERRUPTS ) - return( 0 ); /* error: bad parameter */ - return( Xthal_int_vpri[intnum] ); -#else - return( 0 ); -#endif -} - - -#endif - -#if defined(__SPLIT__trampolines) - - - /* - SUPPORT FOR TRAMPOLINES - - NOTE: trampolining is a special case. - There are two ways (defined here) to trampoline down - from a high-level interrupt to a level-one interrupt. - - a) Synchronous (restrained) trampolining. - Trampolining without clearing the high-level interrupt, - letting the level-one interrupt handler clear the - source of the interrupt. - Here the high-level interrupt must be kept disabled - while trampolining down, and re-enabled after the - level-one interrupt handler completes. - This is what one might do to "convert" a high-level - interrupt into a level-one interrupt. - The high-level interrupt handler code can be generic. - [One could argue this type of trampolining isn't required, - which may? be true...] - b) Asynchronous (free) trampolining. - Trampolining when clearing the high-level interrupt - right away in the high-level interrupt handler. - Here the high-level interrupt is allowed to remain - enabled while trampolining occurs. This is very - useful when some processing must occur with low - latency, but the rest of the processing can occur - at lower (eg. level-one) priority. It is particularly - useful when the lower-priority processing occurs - for only some of the high-level interrupts. - Of course this requires custom assembler code to - handle the high-level interrupt and clear the source - of the interrupt, so the high-level interrupt handler - cannot be generic (as opposed to synchronous trampolining). - - In both cases, a level-one software interrupt is used - for trampolining (one could also trampoline from level - m to n, m > n, n > 1, but that isn't nearly as useful; - it's generally the ability to execute C code and - to process exceptions that is sought after). - - Default trampolining support is currently implemented as follows. - - Trampoline handler: - - A high-level interrupt is considered enabled if *either* - its INTENABLE bit or its xt_tram_ints bit is set - (note that both should never be set at the same time). - - */ - - -/* These are described in xtensa/hal.h (assumed initialized to zero, in BSS): */ -unsigned Xthal_tram_pending; -unsigned Xthal_tram_enabled; -unsigned Xthal_tram_sync; - - - -XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn ) -{ -#if XCHAL_HAVE_INTERRUPTS - XtHalVoidFunc *fn; - - fn = Xthal_tram_trigger_fn; - Xthal_tram_trigger_fn = trigger_fn; - return( fn ); -#else - (void)trigger_fn; - return( 0 ); -#endif -} - - -/* - * xthal_tram_set_sync - * - * Configure type of trampoline for a high-level interrupt. - * By default any trampoline is asynchronous, this need only - * be called to tell the Core HAL that a high-level interrupt - * will be using synchronous trampolining (down to a level-1 interrupt). - * - * intnum interrupt number (0 .. 31) - * sync 0 = async, 1 = synchronous - * - * Returns previous sync state of interrupt (0 or 1) - * or -1 if invalid interrupt number provided. - */ -int xthal_tram_set_sync( int intnum, int sync ) -{ -#if XCHAL_HAVE_INTERRUPTS - unsigned mask; - int prev; - - if( (unsigned)intnum >= XCHAL_NUM_INTERRUPTS ) - return( -1 ); - mask = 1L << intnum; - prev = ((Xthal_tram_sync & mask) != 0); - if( sync ) - Xthal_tram_sync |= mask; - else - Xthal_tram_sync &= ~mask; - return( prev ); -#else /* XCHAL_HAVE_INTERRUPTS */ - return( 0 ); -#endif /* XCHAL_HAVE_INTERRUPTS */ -} - - -/* - * xthal_tram_pending_to_service - * - * This is called by the trampoline interrupt handler - * (eg. by a level-one software interrupt handler) - * to obtain the bitmask of high-level interrupts - * that it must service. - * Returns that bitmask (note: this can sometimes be zero, - * eg. if currently executing level-one code disables the high-level - * interrupt before the trampoline handler has a chance to run). - * - * This call automatically clears the trampoline pending - * bits for the interrupts in the returned mask. - * So the caller *must* process all interrupts that have - * a corresponding bit set if the value returned by this function - * (otherwise those interrupts may likely be lost). - * - * This function should be called with level-one interrupts disabled - * (via INTENABLE; can't be via PS.INTLEVEL because this is C code). - */ -unsigned xthal_tram_pending_to_service( void ) -{ -#if XCHAL_HAVE_INTERRUPTS - unsigned service_mask; - - service_mask = ( Xthal_tram_pending - & (Xthal_vpri_enabled | Xthal_tram_enabled) ) ; - - /* - * Clear trampoline pending bits. - * Each bit must be cleared *before* processing of the corresponding - * interrupt occurs, to avoid missing interrupts. - * Here we just clear all bits for simplicity and convenience. - */ - Xthal_tram_pending &= ~service_mask; - - return( service_mask ); -#else /* XCHAL_HAVE_INTERRUPTS */ - return( 0 ); -#endif /* XCHAL_HAVE_INTERRUPTS */ -} - -/* - * xthal_tram_done - * - * This is called by the trampoline interrupt handler - * (eg. by a level-one software interrupt handler) - * to indicate that processing of a trampolined interrupt - * (eg. one or more of the bits it received from - * xthal_tram_acknowledge()) has completed. - * - * For asynchronously trampolined interrupt(s), there is nothing to do. - * For synchronously trampolined interrupt(s), the high-level - * interrupt(s) must be re-enabled (presumably the level-one - * interrupt handler that just completed has cleared the source - * of the high-level interrupt). - * - * This function should be called with level-one interrupts disabled - * (via INTENABLE; can't be via PS.INTLEVEL because this is C code). - */ -void xthal_tram_done( unsigned serviced_mask ) -{ -#if XCHAL_HAVE_INTERRUPTS - serviced_mask &= Xthal_tram_enabled; /* sync. trampolined interrupts that completed */ - Xthal_tram_enabled &= ~serviced_mask; - xthal_int_enable( serviced_mask ); -#endif -} - -#endif - -#if defined(__SPLIT__deprecated) - - -/**********************************************************************/ - -#ifdef INCLUDE_DEPRECATED_HAL_CODE -/* These definitions were present in an early beta version of the HAL and should not be used: */ -const unsigned Xthal_num_int_levels = XCHAL_NUM_INTLEVELS; -const unsigned Xthal_num_ints = XCHAL_NUM_INTERRUPTS; -__asm__(".global Xthal_int_level_mask\n" ".set Xthal_int_level_mask, Xthal_intlevel_mask+4"); -__asm__(".global Xthal_int_level1_to_n_mask\n" ".set Xthal_int_level1_to_n_mask, Xthal_intlevel_andbelow_mask+8"); -/*const unsigned Xthal_int_level_mask[15] = { XCHAL_INTLEVEL_MASKS }; ... minus the first entry ...*/ -/*const unsigned Xthal_int_level1_to_n_mask[14] = { XCHAL_INTLEVEL_ANDBELOW_MASKS }; ... minus the first two entries ...*/ -const unsigned Xthal_int_level[32] = { XCHAL_INT_LEVELS }; -const unsigned Xthal_int_type_edge = XCHAL_INTTYPE_MASK_EXTERN_EDGE; -const unsigned Xthal_int_type_level = XCHAL_INTTYPE_MASK_EXTERN_LEVEL; -const unsigned Xthal_int_type_timer = XCHAL_INTTYPE_MASK_TIMER; -const unsigned Xthal_int_type_software = XCHAL_INTTYPE_MASK_SOFTWARE; -#endif /* INCLUDE_DEPRECATED_HAL_CODE */ - - -#endif /* SPLITs */ - diff --git a/src/arch/xtensa/hal/mem_ecc_parity.S b/src/arch/xtensa/hal/mem_ecc_parity.S deleted file mode 100644 index 2a85a3ecb37b..000000000000 --- a/src/arch/xtensa/hal/mem_ecc_parity.S +++ /dev/null @@ -1,285 +0,0 @@ -// -// mem_ecc_parity.S - utility routines for the local memory ECC/parity option -// (memory error checking and exceptions) -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/mem_ecc_parity.S#1 $ - -// Copyright (c) 2006-2010 Tensilica 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 <xtensa/coreasm.h> - - -/* - * For most functions, the link-time HAL defines two entry points: - * xthal_...() and xthal_..._nw(). The former is the main entry point - * invoked from C code, or assembly code that follows the C ABI. - * The latter is for use in assembly code that cannot easily follow - * all the requirements of the windowed ABI, e.g. in exception handlers; - * these use the call0 ABI instead (in most cases; some use their own conventions). - * - * When software tools are configured to use the call0 ABI, both variants - * are identical (with some exceptions as noted). To avoid duplicating - * code, we define both labels for the same function body. The Makefile - * defines __SPLIT__..._nw macros with windowed ABI but not with Call0 ABI. - * Use SYM_NW() for the _nw variants defined with the __SPLIT_..._nw macros, - * i.e. for call0 ABI variants when windowed ABI is in use; these are not - * C callable so SYM_NW() does not specify .type information. - * Use SYMBOL() otherwise, which defines both symbols if call0 ABI is selected. - */ - -#if defined (__XTENSA_CALL0_ABI__) -# define SYMBOL(x) .global x ; .type x,@function ; \ - .global x ## _nw ; .type x ## _nw,@function ; \ - .align 4 ; x: ; x ## _nw: -#else -# define SYMBOL(x) .global x ; .type x,@function ; .align 4 ; x: -#endif -#define SYM_NW(x) .global x ; .align 4 ; x: - - -/* Compute smaller of I and D cache line sizes: */ -#if XCHAL_ICACHE_LINEWIDTH < XCHAL_DCACHE_LINEWIDTH && XCHAL_ICACHE_SIZE > 0 -# define CACHE_LINEWIDTH_MIN XCHAL_ICACHE_LINEWIDTH -# define CACHE_LINESIZE_MIN XCHAL_ICACHE_LINESIZE -#else -# define CACHE_LINEWIDTH_MIN XCHAL_DCACHE_LINEWIDTH -# define CACHE_LINESIZE_MIN XCHAL_DCACHE_LINESIZE -#endif - - - .text - -//------------------------------------------------------------------------ -// Inject errors into instruction and/or data RAMs, or cache data or tags -//------------------------------------------------------------------------ - -#if defined(__SPLIT__memep_inject_error) - -// void xthal_memep_inject_error(void *addr, int size, int flags); -// where: -// addr (a2) pointer to local memory, or cache address -// size (a3) size in bytes (gets aligned to words or lines) -// flags (a4) is a combination of the following bits: -// bit 31-5: (reserved) -// bit 4: 0 = inject non-correctable error, -// 16 = inject correctable error (if ECC) -// bit 3: (reserved) -// bit 2: 0 = local memory, 4 = cache -// bit 1: 0 = data cache, 2 = instruction cache -// bit 0: 0 = cache data, 1 = cache tag -// -// (note: data cache data is handled same as local memories; -// to access specific dcache data entries, you have to setup -// a region or page in cache-isolate mode yourself) - -SYMBOL(xthal_memep_inject_error) - abi_entry - -#if XCHAL_HAVE_MEM_ECC_PARITY - - // These MOVIs may be L32Rs, load them before enabling test mode: - movi a6, 0x02020202 // XOR'ing this creates a correctable error - bbsi.l a4, 4, 1f // branch if correctable error requested - movi a6, 0x03030303 // XOR'ing this creates a non-correctable error -1: - - // Lock out all interrupts, to avoid interrupt handlers running with - // test mode enabled (corrupting their stores, likely leading to - // non-correctable memory errors). - // - // If NMI is possible, you're toast - // (no stores during NMI handler will have properly computed ECC/parity bits) - // although you might make the NMI handler check MESR.ERRTEST and save/clear - // it if it's set on entry, so that its stores work correctly. - // - // If memory exceptions are possible, might be okay as long as the - // handler checks whether test mode is on, and turns it off temporarily - // to do its work. - // -# if XCHAL_HAVE_INTERRUPTS - rsil a11, 15 -# endif - - // Save current MESR and set test mode: - - rsr.mesr a8 - bbsi.l a8, MESR_ERRTEST_SHIFT, .Lproceed // already in test mode? - addmi a9, a8, MESR_ERRTEST // enable test mode - bbci.l a8, MESR_ERRENAB_SHIFT, 1f - addmi a9, a9, - MESR_ERRENAB // disable error checks -1: xsr.mesr a9 - beq a8, a9, .Lproceed // clean update, continue - bbci.l a9, MESR_RCE_SHIFT, .Lproceed // we likely restored a lost RCE, just keep it - // At this point, either we: - // a) cleared an RCE record that got created between RSR and XSR - // b) cleared LCE bits that got set between RSR and XSR - // c) more eclectic, and presumably much less likely, cases of - // RCE/LCE bits being cleared and set again between RSR and XSR - // due to multiple memory errors and memory error exceptions - // in that period; for now, we ignore this possibility - // (decreasing returns on addressing these arbitrarily complex cases) - // Assuming (a) or (b), restore the bits we took away. - //addmi a8, a8, MESR_ERRTEST - addmi a9, a9, MESR_ERRTEST - bbci.l a9, MESR_ERRENAB_SHIFT, 1f - addmi a9, a9, - MESR_ERRENAB // disable error checks -1: wsr.mesr a9 - //xsr.mesr a9 - //beq a8, a9, .Lproceed // updated fine, continue - // - // Above we could have used XSR instead of WSR. - // However, it's not clear at this point what's the cleanest thing - // to do if what we read back doesn't match what we expected, - // because at that point we have multiple errors to deal with. - // Unless we have code here to handle (fix and/or log) these errors, - // we have to chuck something away or write a bunch more code to - // handle another LCE bit getting set etc (also starting to be - // a low probability occurrence). -.Lproceed: - // Test mode enabled. From this point until we restore MESR, - // the only loads and stores done are for injecting errors. - -# if XCHAL_ICACHE_SIZE || XCHAL_DCACHE_SIZE - bbci.l a4, 2, .L_inject_local // branch if injecting to local memory - bbsi.l a4, 1, .L_inject_icache // branch if injecting to icache - // Inject errors in dcache: - bbci.l a4, 0, .L_inject_local // branch if injecting to dcache data -# if XCHAL_DCACHE_SIZE && XCHAL_HAVE_DCACHE_TEST - // Inject errors in dcache tags: - - // Round addr/size to fully rather than partially cover - // all aligned cache lines: - extui a9, a2, 0, XCHAL_DCACHE_LINEWIDTH - sub a2, a2, a9 - add a3, a3, a9 - addi a3, a3, XCHAL_DCACHE_LINESIZE-1 - srli a3, a3, XCHAL_DCACHE_LINEWIDTH // size in cache lines - - floopgtz a3, .Ldctagloop - ldct a9, a2 // load dcache line tag - rsr.mecr a7 // get check bits - xor a7, a7, a6 // ECC: single-bit error; Parity: NO-OP - wsr.mecr a7 // setup modified check bits - sdct a9, a2 // store tag with modified check bits - addi a2, a2, XCHAL_DCACHE_LINESIZE // increment to next line - floopend a3, .Ldctagloop -# endif /* have dcache */ - j .L_inject_done - - // Inject errors in icache: -.L_inject_icache: -# if XCHAL_ICACHE_SIZE && XCHAL_HAVE_ICACHE_TEST - bbci.l a4, 0, .L_inject_icw // branch if injecting to icache data - - // Inject errors in icache tags: - // Round addr/size to fully rather than partially cover - // all aligned cache lines: - extui a9, a2, 0, XCHAL_ICACHE_LINEWIDTH - sub a2, a2, a9 - add a3, a3, a9 - addi a3, a3, XCHAL_ICACHE_LINESIZE-1 - srli a3, a3, XCHAL_ICACHE_LINEWIDTH // size in cache lines - - floopgtz a3, .Lictagloop - lict a9, a2 // load icache line tag - rsr.mecr a7 // get check bits - xor a7, a7, a6 // ECC: single-bit error; Parity: NO-OP - wsr.mecr a7 // setup modified check bits - sict a9, a2 // store tag with modified check bits - addi a2, a2, XCHAL_ICACHE_LINESIZE // increment to next line - floopend a3, .Lictagloop - j .L_inject_done - -.L_inject_icw: -# if XCHAL_ICACHE_ACCESS_SIZE <= 4 /* SICW does not work usefully (replicates data) if accessWidth > 32 bits */ - // Inject errors in icache data words: - // Round addr/size to fully rather than partially cover - // all aligned 32-bit words: - extui a9, a2, 0, 2 - sub a2, a2, a9 - add a3, a3, a9 - addi a3, a3, 3 - srli a3, a3, 2 // size in words - - floopgtz a3, .Licwloop - licw a9, a2 // load word of icache line data - rsr.mecr a7 // get check bits - xor a7, a7, a6 // ECC: single-bit error; Parity: NO-OP - wsr.mecr a7 // setup modified check bits - sicw a9, a2 // store data with modified check bits - addi a2, a2, 4 // increment to next word - floopend a3, .Licwloop -# endif -# endif /* have icache */ - j .L_inject_done -# endif /* have icache or dcache */ - -.L_inject_local: - // Round addr/size to fully rather than partially cover - // all aligned 32-bit words: - extui a9, a2, 0, 2 - sub a2, a2, a9 - add a3, a3, a9 - addi a3, a3, 3 - srli a3, a3, 2 // size in words - - floopgtz a3, .Lendloop - l32i a9, a2, 0 // load data - rsr.mecr a7 // get check bits - xor a7, a7, a6 // ECC: single-bit error; Parity: NO-OP - wsr.mecr a7 // setup modified check bits - s32i a9, a2, 0 // store data with modified check bits - addi a2, a2, 4 // increment to next word - floopend a3, .Lendloop - -.L_inject_done: - // Restore MESR (a8 is the saved original MESR): - bbsi.l a8, MESR_ERRTEST_SHIFT, 2f // was already in test mode - rsr.mesr a6 - addmi a9, a6, - MESR_ERRTEST // disable test mode - bbci.l a8, MESR_ERRENAB_SHIFT, 1f - addmi a9, a9, MESR_ERRENAB // enable error checks -1: xsr.mesr a9 - beq a6, a9, 2f // clean update, done - bbci.l a9, MESR_RCE_SHIFT, 2f // we likely restored a lost RCE, just keep it - addmi a9, a9, - MESR_ERRTEST - bbci.l a8, MESR_ERRENAB_SHIFT, 1f - addmi a9, a9, MESR_ERRENAB // disable error checks -1: wsr.mesr a9 -2: - - // Restore PS.INTLEVEL: -# if XCHAL_HAVE_INTERRUPTS - wsr.ps a11 - rsync -# endif -#endif /* XCHAL_HAVE_MEM_ECC_PARITY */ - - abi_return - - .size xthal_memep_inject_error, . - xthal_memep_inject_error - - -#endif /*split*/ - -//---------------------------------------------------------------------- - diff --git a/src/arch/xtensa/hal/memcopy.S b/src/arch/xtensa/hal/memcopy.S deleted file mode 100644 index 5cabcf166d9b..000000000000 --- a/src/arch/xtensa/hal/memcopy.S +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Core HAL library functions xthal_memcpy and xthal_bcopy - */ - -/* - * Copyright (c) 2003, 2006, 2010 Tensilica 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 <xtensa/coreasm.h> - - -#ifdef __XTENSA_EB__ -# define BL(b,l) b -#else -# define BL(b,l) l -#endif - - .macro srcel r, early, late // combine early and late words, shift into \r - src \r, BL(\early,\late), BL(\late,\early) - .endm - - .macro ssa8f r // set shift-amount for shift *from* given 2-bit alignment - BL(ssa8b,ssa8l) \r - .endm - - .macro ssa8t r // set shift-amount for shift *to* given 2-bit alignment - BL(ssa8l,ssa8b) \r // (reverse of ssa8f) - .endm - - .macro s2ll r, s // shift-to-later logical (away from zero-addressed byte) - BL(srl,sll) \r, \s - .endm - - .macro s2el r, s // shift-to-early logical (towards zero-addressed byte) - BL(sll,srl) \r, \s - .endm - -/* - * void *xthal_memcpy(void *dst, const void *src, size_t len); - * void *xthal_bcopy(const void *src, void *dst, size_t len); - * - * This function is intended to do the same thing as the standard - * library function memcpy() (or bcopy()) for most cases. - * However, it uses strictly 32-bit load and store instructions - * to copy data. This ensures this function will work - * where the source and/or destination references an - * instruction RAM or ROM, which can only be accessed - * using l32i (IRAM+IROM) and s32i (IRAM). - * - * The bcopy version is provided here to avoid the overhead - * of an extra call, for callers that require this convention. - * - * The (general case) algorithm is as follows: - * If destination is unaligned, align it by copying 1 to 3 bytes. - * If source is aligned, - * do 16 bytes with a loop, and then finish up with - * 8, 4, and 0-3 byte copies conditional on the length; - * else (if source is unaligned), - * do the same, but use SRC to align the source data. - * This code tries to use fall-through branches for the common - * case of aligned source and destination and multiple - * of 4 length. - * - * Register use: - * a0/ return address - * a1/ stack pointer - * a2/ return value - * a3/ src - * a4/ length - * a5/ dst - * a6/ tmp - * a7/ tmp - * a8/ tmp - * a9/ tmp - * a10/ tmp - * a11/ tmp - * a12/ tmp - */ - -/* xthal_bcopy and xthal_memcpy need to allocate the same stack size - * on entry since they share the same function-return code. Also, - * there is more than one return point. */ - -#define SAVE_A0 0 -#define SAVE_A3 4 -#define SAVE_A4 8 -#define SAVE_A5 12 -#define SAVE_A12 16 -#define STKSIZE 32 - - - .text - .align 4 - .global xthal_bcopy - .type xthal_bcopy,@function -xthal_bcopy: -#ifdef __XTENSA_CALL0_ABI__ - addi sp, sp, -STKSIZE - s32i a12, a1, SAVE_A12 -#else - entry sp, 32 // allow for call8 below -#endif - // a2=src, a3=dst, a4=len - mov a5, a3 // copy dst so that a2 is return value - mov a3, a2 - mov a2, a5 - j .Lcommon // go to common code for memcpy+bcopy - - .size xthal_bcopy, . - xthal_bcopy - - - -/* - * Destination is unaligned - */ - - .align 4 -xthal_memcpy.prefixcode: // purely for purpose of .size -.Ldstunaligned: - mov a10, a5 - mov a11, a3 - movi a12, 4 - sub a6, a12, a6 // number of bytes to copy for dst alignment - mov a12, a6 -#ifdef __XTENSA_CALL0_ABI__ - s32i a0, a1, SAVE_A0 // preserve live registers - s32i a3, a1, SAVE_A3 - s32i a4, a1, SAVE_A4 - s32i a5, a1, SAVE_A5 - call0 xthal_copy123 - l32i a0, a1, SAVE_A0 // restore live registers - l32i a3, a1, SAVE_A3 - l32i a4, a1, SAVE_A4 - l32i a5, a1, SAVE_A5 - mov a6, a12 // restore a6 from callee-saved register -#else - call8 xthal_copy123 -#endif - add a5, a5, a6 - add a3, a3, a6 - sub a4, a4, a6 - j .Ldstaligned - - // Not sure how else to count code that precedes a function, in .size: - .size xthal_memcpy.prefixcode, . - xthal_memcpy.prefixcode - - - .align 4 - .global xthal_memcpy - .type xthal_memcpy,@function -xthal_memcpy: -#ifdef __XTENSA_CALL0_ABI__ - addi sp, sp, -STKSIZE - s32i a12, a1, SAVE_A12 -#else - entry sp, 32 // allow for call8 below -#endif - // a2=dst, a3=src, a4=len - mov a5, a2 // copy dst so that a2 is return value -.Lcommon: -#ifdef __XTENSA_CALL0_ABI__ - /* - * have to restore the stack - */ - _bgeui a4, 4, 1f - mov a12, a0 // preserve return address - call0 xthal_copy123 - mov a0, a12 // restore return address - l32i a12, a1, SAVE_A12 - addi sp, sp, STKSIZE - ret -1: -#else - bltui a4, 4, xthal_copy123_pastentry // NOTE: sometimes relaxes -#endif - - extui a6, a2, 0, 2 // destination unalignment offset - bnez a6, .Ldstunaligned // align the destination -.Ldstaligned: // return here once dst is aligned - srli a7, a4, 4 // number of loop iterations of 16-bytes each - extui a11, a3, 0, 2 // source unalignment offset - _bnez a11, .Lsrcunaligned // if source not aligned, use shifting copy - /* - * Destination and source are 32-bit aligned, use 32-bit copy. - */ -#if XCHAL_HAVE_LOOPS - loopnez a7, .Loop1done -#else /* !XCHAL_HAVE_LOOPS */ - beqz a7, .Loop1done - slli a8, a7, 4 - add a8, a8, a3 // a8 = end of last 16B source chunk -#endif /* !XCHAL_HAVE_LOOPS */ -.Loop1: - l32i a6, a3, 0 - l32i a7, a3, 4 - s32i a6, a5, 0 - l32i a6, a3, 8 - s32i a7, a5, 4 - l32i a7, a3, 12 - s32i a6, a5, 8 - addi a3, a3, 16 - s32i a7, a5, 12 - addi a5, a5, 16 -#if !XCHAL_HAVE_LOOPS - blt a3, a8, .Loop1 -#endif /* !XCHAL_HAVE_LOOPS */ -.Loop1done: - bbci.l a4, 3, .L2 - // copy 8 bytes - l32i a6, a3, 0 - l32i a7, a3, 4 - addi a3, a3, 8 - s32i a6, a5, 0 - s32i a7, a5, 4 - addi a5, a5, 8 -.L2: - bbci.l a4, 2, .L3 - // copy 4 bytes - l32i a6, a3, 0 - addi a3, a3, 4 - s32i a6, a5, 0 - addi a5, a5, 4 -.L3: - // Copy last 0 to 3 bytes using 32-bit accesses (aligned source and destination): - extui a4, a4, 0, 2 // any bytes to copy? - beqz a4, 1f // if not, skip this to avoid extraneous loads/stores - l32i a6, a3, 0 // get source word - l32i a7, a5, 0 // get destination word - ssa8f a4 // shift from length (end of source) - s2ll a6, a6 // align source to last byte - s2el a7, a7 // align parts of a7 following modified bytes, to early byte - ssa8t a4 // shift to end of modified destination (length) - srcel a7, a6, a7 // combine source with late-dst to form last word - s32i a7, a5, 0 // update last word -1: - -#ifdef __XTENSA_CALL0_ABI__ - l32i a12, a1, SAVE_A12 - addi sp, sp, STKSIZE - ret -#else - retw -#endif - - .size xthal_memcpy, . - xthal_memcpy - - - // void xthal_copy123(dst, src, len); - // - // Copy from 0 to 3 bytes, using only 32-bit loads and stores, - // with arbitrarily aligned source and destination. - // - // arg1 = a2 = dst - // arg2 = a3 = src - // arg3 = a4 = len - - .global xthal_copy123 - .type xthal_copy123,@function - .align 4 -xthal_copy123: - abi_entry - -xthal_copy123_pastentry: - _beqz a4, cdone // don't load or store if zero bytes - // First get the bytes: - movi a5, ~3 - and a5, a3, a5 // align src address - l32i a6, a5, 0 - l32i a7, a5, 4 - ssa8f a3 - srcel a3, a6, a7 - // a3 now contains source bytes, aligned to 1st byte (memory order) - // (source address is no longer needed at this point) - - // Does destination span two words?: - extui a10, a2, 0, 2 // destination alignment - sub a5, a2, a10 // align destination address - l32i a8, a5, 0 // get first destination word regardless - add a6, a10, a4 // dst_align + len - ssa8f a2 // shift from dst_align (to 1st or last byte) - s2ll a10, a8 // a10 = first part of destination, aligned to last byte - bltui a6, 4, oneword // branch if destination contained in single word - - // Two-word destination case: - l32i a8, a5, 4 // get second word - ssa8t a2 // shift to dst_align - srcel a10, a10, a3 // with a10 in early bytes, a3 in later bytes - s32i a10, a5, 0 // update first word - addi a5, a5, 4 // advance to last word for common code below - //movi a10, 0 // not needed, gets dropped - -oneword: - // One-word (and two-word) destination case: - // a8 = contents of last destination word - // a10 = early part of a8 preceding modified bytes, shifted towards last byte - // - ssa8f a4 // shift from length (end of source) - srcel a3, a10, a3 // combine early-destination with source, aligned to last byte - - ssa8f a6 // shift from end of modified destination (dst_align+len) - s2el a8, a8 // align parts of a8 following modified bytes, to early byte - ssa8t a6 // shift to end of modified destination (dst_align+len) - srcel a8, a3, a8 // combine early-dst+source with late-dst to form last word - s32i a8, a5, 0 // update last word -cdone: abi_return // return dst - -/* - * Destination is aligned, Source is unaligned - */ - - .align 4 -.Lsrcunaligned: - // Copy 16 bytes per iteration for word-aligned dst and unaligned src - ssa8f a3 // set shift amount from byte offset -#define SIM_CHECKS_ALIGNMENT 1 /* set to 1 when running on ISS (simulator) with the - lint or ferret client, or 0 to save a few cycles */ -#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT - extui a11, a3, 0, 2 // save unalignment offset for below - sub a3, a3, a11 // align a3 -#endif - l32i a6, a3, 0 // load first word -#if XCHAL_HAVE_LOOPS - loopnez a7, .Loop2done -#else /* !XCHAL_HAVE_LOOPS */ - beqz a7, .Loop2done - slli a10, a7, 4 - add a10, a10, a3 // a10 = end of last 16B source chunk -#endif /* !XCHAL_HAVE_LOOPS */ -.Loop2: - l32i a7, a3, 4 - l32i a8, a3, 8 - srcel a6, a6, a7 - s32i a6, a5, 0 - l32i a9, a3, 12 - srcel a7, a7, a8 - s32i a7, a5, 4 - l32i a6, a3, 16 - srcel a8, a8, a9 - s32i a8, a5, 8 - addi a3, a3, 16 - srcel a9, a9, a6 - s32i a9, a5, 12 - addi a5, a5, 16 -#if !XCHAL_HAVE_LOOPS - blt a3, a10, .Loop2 -#endif /* !XCHAL_HAVE_LOOPS */ -.Loop2done: - bbci.l a4, 3, .L12 - // copy 8 bytes - l32i a7, a3, 4 - l32i a8, a3, 8 - srcel a6, a6, a7 - s32i a6, a5, 0 - addi a3, a3, 8 - srcel a7, a7, a8 - s32i a7, a5, 4 - addi a5, a5, 8 - mov a6, a8 -.L12: - bbci.l a4, 2, .L13 - // copy 4 bytes - l32i a7, a3, 4 - addi a3, a3, 4 - srcel a6, a6, a7 - s32i a6, a5, 0 - addi a5, a5, 4 - mov a6, a7 -.L13: - // Copy last 0 to 3 bytes using 32-bit accesses (shifting source, aligned destination): - //_beqz a4[1:0], cdone // don't load or store if zero bytes - l32i a7, a3, 4 // get source word - l32i a3, a5, 0 // get destination word - srcel a6, a6, a7 // source bytes, aligned to early (1st) byte - ssa8f a4 // shift from length (end of source) - s2ll a6, a6 // combine early-destination with source, aligned to last byte - s2el a3, a3 // align parts of a3 following modified bytes, to early byte - ssa8t a4 // shift to end of modified destination (length) - srcel a3, a6, a3 // combine early-dst+source with late-dst to form last word - s32i a3, a5, 0 // update last word -.Ldone: -#ifdef __XTENSA_CALL0_ABI__ - l32i a12, a1, SAVE_A12 - addi sp, sp, STKSIZE - ret -#else - retw -#endif - - .size xthal_copy123, . - xthal_copy123 - diff --git a/src/arch/xtensa/hal/misc.c b/src/arch/xtensa/hal/misc.c deleted file mode 100644 index 7742851e291f..000000000000 --- a/src/arch/xtensa/hal/misc.c +++ /dev/null @@ -1,178 +0,0 @@ -// -// misc.c - miscellaneous constants -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/misc.c#1 $ - -// Copyright (c) 2004-2005 Tensilica 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 <xtensa/config/core.h> - - -// Software release info (not configuration-specific!): -const unsigned int Xthal_release_major = XTHAL_RELEASE_MAJOR; -const unsigned int Xthal_release_minor = XTHAL_RELEASE_MINOR; -const char * const Xthal_release_name = XTHAL_RELEASE_NAME; -#ifdef XTHAL_RELEASE_INTERNAL -const char * const Xthal_release_internal = XTHAL_RELEASE_INTERNAL; -#else -const char * const Xthal_release_internal = 0; -#endif -/* Old format, for backward compatibility: */ -const unsigned int Xthal_rev_no = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV; - -// number of registers in register window, or number of registers if not windowed -const unsigned int Xthal_num_aregs = XCHAL_NUM_AREGS; -const unsigned char Xthal_num_aregs_log2 = XCHAL_NUM_AREGS_LOG2; - -const unsigned char Xthal_memory_order = XCHAL_MEMORY_ORDER; -const unsigned char Xthal_have_windowed = XCHAL_HAVE_WINDOWED; -const unsigned char Xthal_have_density = XCHAL_HAVE_DENSITY; -const unsigned char Xthal_have_booleans = XCHAL_HAVE_BOOLEANS; -const unsigned char Xthal_have_loops = XCHAL_HAVE_LOOPS; -const unsigned char Xthal_have_nsa = XCHAL_HAVE_NSA; -const unsigned char Xthal_have_minmax = XCHAL_HAVE_MINMAX; -const unsigned char Xthal_have_sext = XCHAL_HAVE_SEXT; -const unsigned char Xthal_have_clamps = XCHAL_HAVE_CLAMPS; -const unsigned char Xthal_have_mac16 = XCHAL_HAVE_MAC16; -const unsigned char Xthal_have_mul16 = XCHAL_HAVE_MUL16; -const unsigned char Xthal_have_fp = XCHAL_HAVE_FP; -const unsigned char Xthal_have_speculation = XCHAL_HAVE_SPECULATION; -const unsigned char Xthal_have_exceptions = XCHAL_HAVE_EXCEPTIONS; -const unsigned char Xthal_xea_version = XCHAL_XEA_VERSION; -const unsigned char Xthal_have_interrupts = XCHAL_HAVE_INTERRUPTS; -const unsigned char Xthal_have_highlevel_interrupts = XCHAL_HAVE_HIGHLEVEL_INTERRUPTS; -const unsigned char Xthal_have_nmi = XCHAL_HAVE_NMI; -const unsigned char Xthal_have_prid = XCHAL_HAVE_PRID; -const unsigned char Xthal_have_release_sync = XCHAL_HAVE_RELEASE_SYNC; -const unsigned char Xthal_have_s32c1i = XCHAL_HAVE_S32C1I; -const unsigned char Xthal_have_threadptr = XCHAL_HAVE_THREADPTR; - -const unsigned char Xthal_have_pif = XCHAL_HAVE_PIF; -const unsigned short Xthal_num_writebuffer_entries = XCHAL_NUM_WRITEBUFFER_ENTRIES; - -const unsigned int Xthal_build_unique_id = XCHAL_BUILD_UNIQUE_ID; -// Release info for hardware targeted by software upgrades: -const unsigned int Xthal_hw_configid0 = XCHAL_HW_CONFIGID0; -const unsigned int Xthal_hw_configid1 = XCHAL_HW_CONFIGID1; -const unsigned int Xthal_hw_release_major = XCHAL_HW_VERSION_MAJOR; -const unsigned int Xthal_hw_release_minor = XCHAL_HW_VERSION_MINOR; -const char * const Xthal_hw_release_name = XCHAL_HW_VERSION_NAME; -const unsigned int Xthal_hw_min_version_major = XCHAL_HW_MIN_VERSION_MAJOR; -const unsigned int Xthal_hw_min_version_minor = XCHAL_HW_MIN_VERSION_MINOR; -const unsigned int Xthal_hw_max_version_major = XCHAL_HW_MAX_VERSION_MAJOR; -const unsigned int Xthal_hw_max_version_minor = XCHAL_HW_MAX_VERSION_MINOR; -#ifdef XCHAL_HW_RELEASE_INTERNAL -const char * const Xthal_hw_release_internal = XCHAL_HW_RELEASE_INTERNAL; -#else -const char * const Xthal_hw_release_internal = 0; -#endif - -/* MMU related info... */ - -const unsigned char Xthal_have_spanning_way = XCHAL_HAVE_SPANNING_WAY; -const unsigned char Xthal_have_identity_map = XCHAL_HAVE_IDENTITY_MAP; -const unsigned char Xthal_have_mimic_cacheattr = XCHAL_HAVE_MIMIC_CACHEATTR; -const unsigned char Xthal_have_xlt_cacheattr = XCHAL_HAVE_XLT_CACHEATTR; -const unsigned char Xthal_have_cacheattr = XCHAL_HAVE_CACHEATTR; -const unsigned char Xthal_have_tlbs = XCHAL_HAVE_TLBS; -#if XCHAL_HAVE_MPU -const unsigned char Xthal_mmu_asid_bits = 0; -const unsigned char Xthal_mmu_asid_kernel = 0; -const unsigned char Xthal_mmu_rings = 0; -const unsigned char Xthal_mmu_ring_bits = 0; -const unsigned char Xthal_mmu_sr_bits = 0; -const unsigned char Xthal_mmu_ca_bits = 0; -#else -const unsigned char Xthal_mmu_asid_bits = XCHAL_MMU_ASID_BITS; -const unsigned char Xthal_mmu_asid_kernel = XCHAL_MMU_ASID_KERNEL; -const unsigned char Xthal_mmu_rings = XCHAL_MMU_RINGS; -const unsigned char Xthal_mmu_ring_bits = XCHAL_MMU_RING_BITS; -const unsigned char Xthal_mmu_sr_bits = XCHAL_MMU_SR_BITS; -const unsigned char Xthal_mmu_ca_bits = XCHAL_MMU_CA_BITS; -#endif -#if XCHAL_HAVE_TLBS -const unsigned int Xthal_mmu_max_pte_page_size = XCHAL_MMU_MAX_PTE_PAGE_SIZE; -const unsigned int Xthal_mmu_min_pte_page_size = XCHAL_MMU_MIN_PTE_PAGE_SIZE; -const unsigned char Xthal_itlb_way_bits = XCHAL_ITLB_WAY_BITS; -const unsigned char Xthal_itlb_ways = XCHAL_ITLB_WAYS; -const unsigned char Xthal_itlb_arf_ways = XCHAL_ITLB_ARF_WAYS; -const unsigned char Xthal_dtlb_way_bits = XCHAL_DTLB_WAY_BITS; -const unsigned char Xthal_dtlb_ways = XCHAL_DTLB_WAYS; -const unsigned char Xthal_dtlb_arf_ways = XCHAL_DTLB_ARF_WAYS; -#else -const unsigned int Xthal_mmu_max_pte_page_size = 0; -const unsigned int Xthal_mmu_min_pte_page_size = 0; -const unsigned char Xthal_itlb_way_bits = 0; -const unsigned char Xthal_itlb_ways = 0; -const unsigned char Xthal_itlb_arf_ways = 0; -const unsigned char Xthal_dtlb_way_bits = 0; -const unsigned char Xthal_dtlb_ways = 0; -const unsigned char Xthal_dtlb_arf_ways = 0; -#endif - - -/* Internal memories... */ - -const unsigned char Xthal_num_instrom = XCHAL_NUM_INSTROM; -const unsigned char Xthal_num_instram = XCHAL_NUM_INSTRAM; -const unsigned char Xthal_num_datarom = XCHAL_NUM_DATAROM; -const unsigned char Xthal_num_dataram = XCHAL_NUM_DATARAM; -const unsigned char Xthal_num_xlmi = XCHAL_NUM_XLMI; - -/* Define arrays of internal memories' addresses and sizes: */ -#define MEMTRIPLET(n,mem,memcap) _MEMTRIPLET(n,mem,memcap) -#define _MEMTRIPLET(n,mem,memcap) MEMTRIPLET##n(mem,memcap) -#define MEMTRIPLET0(mem,memcap) \ - const unsigned int Xthal_##mem##_vaddr[1] = { 0 }; \ - const unsigned int Xthal_##mem##_paddr[1] = { 0 }; \ - const unsigned int Xthal_##mem##_size [1] = { 0 }; -#define MEMTRIPLET1(mem,memcap) \ - const unsigned int Xthal_##mem##_vaddr[1] = { XCHAL_##memcap##0_VADDR }; \ - const unsigned int Xthal_##mem##_paddr[1] = { XCHAL_##memcap##0_PADDR }; \ - const unsigned int Xthal_##mem##_size [1] = { XCHAL_##memcap##0_SIZE }; -#define MEMTRIPLET2(mem,memcap) \ - const unsigned int Xthal_##mem##_vaddr[2] = { XCHAL_##memcap##0_VADDR, XCHAL_##memcap##1_VADDR }; \ - const unsigned int Xthal_##mem##_paddr[2] = { XCHAL_##memcap##0_PADDR, XCHAL_##memcap##1_PADDR }; \ - const unsigned int Xthal_##mem##_size [2] = { XCHAL_##memcap##0_SIZE, XCHAL_##memcap##1_SIZE }; -MEMTRIPLET(XCHAL_NUM_INSTROM, instrom, INSTROM) -MEMTRIPLET(XCHAL_NUM_INSTRAM, instram, INSTRAM) -MEMTRIPLET(XCHAL_NUM_DATAROM, datarom, DATAROM) -MEMTRIPLET(XCHAL_NUM_DATARAM, dataram, DATARAM) -MEMTRIPLET(XCHAL_NUM_XLMI, xlmi, XLMI) - -/* Timer info... */ - -const unsigned char Xthal_have_ccount = XCHAL_HAVE_CCOUNT; -const unsigned char Xthal_num_ccompare = XCHAL_NUM_TIMERS; - -#ifdef INCLUDE_DEPRECATED_HAL_CODE -const unsigned char Xthal_have_old_exc_arch = XCHAL_HAVE_XEA1; -const unsigned char Xthal_have_mmu = XCHAL_HAVE_TLBS; -const unsigned int Xthal_num_regs = XCHAL_NUM_AREGS; /*DEPRECATED*/ -const unsigned char Xthal_num_irom = XCHAL_NUM_INSTROM; /*DEPRECATED*/ -const unsigned char Xthal_num_iram = XCHAL_NUM_INSTRAM; /*DEPRECATED*/ -const unsigned char Xthal_num_drom = XCHAL_NUM_DATAROM; /*DEPRECATED*/ -const unsigned char Xthal_num_dram = XCHAL_NUM_DATARAM; /*DEPRECATED*/ -const unsigned int Xthal_configid0 = XCHAL_HW_CONFIGID0; -const unsigned int Xthal_configid1 = XCHAL_HW_CONFIGID1; -#endif - diff --git a/src/arch/xtensa/hal/miscellaneous.S b/src/arch/xtensa/hal/miscellaneous.S deleted file mode 100644 index 1a3ebf49b001..000000000000 --- a/src/arch/xtensa/hal/miscellaneous.S +++ /dev/null @@ -1,56 +0,0 @@ -// -// miscellaneous.S - miscellaneous assembly language routines -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/miscellaneous.S#1 $ - -// Copyright (c) 2011 Tensilica 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 <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/xtensa-versions.h> - - - .text - -//---------------------------------------------------------------------- -// Clear any remnant register state pointing to (or containing) code. -// Specifically, clear loop registers (LCOUNT) to avoid hardware loopback -// from LEND to LBEGIN when new code is loaded where code containing a -// zero-overhead loop was located. See the HAL chapter of the Tensilica -// System Software Reference Manual for details on the use of this function. -//---------------------------------------------------------------------- - -#if defined(__SPLIT__clear_regcached_code) || \ - defined(__SPLIT__clear_regcached_code_nw) - -DECLFUNC(xthal_clear_regcached_code) - abi_entry -# if XCHAL_HAVE_LOOPS - movi a2, 0 - wsr.lcount a2 -# endif - isync_retw_nop - abi_return - endfunc - -#endif - diff --git a/src/arch/xtensa/hal/mmu.c b/src/arch/xtensa/hal/mmu.c deleted file mode 100644 index ef4165206795..000000000000 --- a/src/arch/xtensa/hal/mmu.c +++ /dev/null @@ -1,93 +0,0 @@ -// -// mmu.c - MMU related functions -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/mmu.c#1 $ - -// Copyright (c) 2002, 2008 Tensilica 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 <xtensa/config/core.h> - -/* - * Convert a virtual address to a physical address - * (through static maps only). - * Returns 0 if successful (*paddrp is set), -1 if not (no mapping). - */ -int xthal_static_v2p( unsigned vaddr, unsigned *paddrp /*, unsigned len, unsigned rasid*/ ) -{ -#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY - if( vaddr >= XCHAL_KSEG_CACHED_VADDR - && vaddr <= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_SIZE ) - vaddr += XCHAL_KSEG_CACHED_PADDR - XCHAL_KSEG_CACHED_VADDR; - else if( vaddr >= XCHAL_KSEG_BYPASS_VADDR - && vaddr <= XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_SIZE ) - vaddr += XCHAL_KSEG_BYPASS_PADDR - XCHAL_KSEG_BYPASS_VADDR; - else if( vaddr >= XCHAL_KIO_CACHED_VADDR - && vaddr <= XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE ) - vaddr += XCHAL_KIO_CACHED_PADDR - XCHAL_KIO_CACHED_VADDR; - else if( vaddr >= XCHAL_KIO_BYPASS_VADDR - && vaddr <= XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE ) - vaddr += XCHAL_KIO_BYPASS_PADDR - XCHAL_KIO_BYPASS_VADDR; - else - return( -1 ); /* no known mapping */ -#endif /* XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY */ - *paddrp = vaddr; /* virtual == physical */ - return( 0 ); -} - -/* - * Convert a physical address to a virtual address - * (through static maps only). - * Returns 0 if successful (*vaddrp is set), -1 if not (no mapping). - * - * NOTE: A physical address can be mapped from multiple virtual addresses - * (or one or none). - * There should be better parameter(s) to help select the mapping returned - * (eg. cache mode, address, asid, etc), or somehow return them all. - * Mappings returned currently assume the current RASID setting. - */ -int xthal_static_p2v( unsigned paddr, unsigned *vaddrp, /*unsigned len, unsigned rasid,*/ unsigned cached ) -{ -#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY - if( cached ) { - if( paddr >= XCHAL_KSEG_CACHED_PADDR - && paddr <= XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE ) - paddr += XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_CACHED_PADDR; - else if( paddr >= XCHAL_KIO_BYPASS_PADDR - && paddr <= XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE ) - paddr += XCHAL_KIO_BYPASS_VADDR - XCHAL_KIO_BYPASS_PADDR; - else - return -1; /* no known mapping */ - } else { - if( paddr >= XCHAL_KSEG_BYPASS_PADDR - && paddr <= XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE ) - paddr += XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_BYPASS_PADDR; - else if( paddr >= XCHAL_KIO_CACHED_PADDR - && paddr <= XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE ) - paddr += XCHAL_KIO_CACHED_VADDR - XCHAL_KIO_CACHED_PADDR; - else - return -1; /* no known mapping */ - } -#endif /* XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY */ - *vaddrp = paddr; /* virtual == physical */ - return( 0 ); -} - diff --git a/src/arch/xtensa/hal/mp_asm.S b/src/arch/xtensa/hal/mp_asm.S deleted file mode 100644 index cc203436ad67..000000000000 --- a/src/arch/xtensa/hal/mp_asm.S +++ /dev/null @@ -1,123 +0,0 @@ -// -// mp_asm.S - multi-processor synchronization routines -// -// $Id$ - -// Copyright (c) 2003, 2005, 2010 Tensilica 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 <xtensa/coreasm.h> - - -/* - int xthal_compare_and_set( int *address, int test_value, int set_value ) - - Atomically sets *address to set_value if *address equals test_value. - Returns the previous value of *address (the one compared with test_value). - - Uses the S32C1I instruction if available. - S32C1I requires special support from the memory controller for - memory accessed via the PIF interface. For this and other reasons, - S32C1I might not work on the entire 4GB address range. This function - does not test address validity. That is the responsibility of the - software invoking this function. -*/ - .text - .align 4 - .global xthal_compare_and_set - .type xthal_compare_and_set,@function - -xthal_compare_and_set: - abi_entry - // a2 == address - // a3 == test value - // a4 == set value - -#if XCHAL_HAVE_EXCLUSIVE - mov a6, a4 // a6 = copy of set_value -1: - l32ex a5, a2 // a5 = *address, set monitor - bne a5, a3, 2f // skip write if *address != test_value - mov a4, a6 // a4 = set_value - s32ex a4, a2 // *address = set_value - getex a4 // get result of store - beqz a4, 1b -2: - mov a2, a5 // a2 = *address, return value - clrex // in case we skipped write -#elif XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION_MAJOR >= 2200 - mov a6, a4 // a6 = copy of set_value - movi a5, -1 - xor a5, a5, a3 // a5 = ~a3 - wsr.scompare1 a3 // set test_value -1: - mov a4, a6 // a4 = set_value - s32c1i a4, a2, 0 - bne a4, a5, 2f // if a4 != ~SCOMPARE1 then done - l32i a4, a2, 0 // a4 = *address - bne a4, a5, 1b // retry if *address != ~SCOMPARE1 -2: - mov a2, a4 -#else - mov a7, a2 // a7 == address, a2 is return val -# if XCHAL_HAVE_INTERRUPTS - rsil a5, 15 // a5 == new ps -# endif - l32i a2, a7, 0 // a2 == value to test, return val - bne a3, a2, done // test - - s32i a4, a7, 0 // write the new value - -done: -# if XCHAL_HAVE_INTERRUPTS - wsr.ps a5 // restore the PS - rsync -# endif -#endif - abi_return - - .size xthal_compare_and_set, . - xthal_compare_and_set - - -/* - unsigned xthal_get_prid( void ); - - Returns the value of the PRID register (processor ID), - or 0 if not configured. - (Note: this register, when present, cannot / must-not - change value during runtime; on certain processors, - its value may get sampled only at reset. - It can never be written to, hence - there is no xthal_set_prid() function.) -*/ - .align 4 - .global xthal_get_prid - .type xthal_get_prid,@function -xthal_get_prid: - abi_entry -#if XCHAL_HAVE_PRID - rsr.prid a2 -#else - movi a2, 0 -#endif - abi_return - .size xthal_get_prid, . - xthal_get_prid - diff --git a/src/arch/xtensa/hal/mpu.c b/src/arch/xtensa/hal/mpu.c deleted file mode 100644 index bacbfc6ff0c7..000000000000 --- a/src/arch/xtensa/hal/mpu.c +++ /dev/null @@ -1,1830 +0,0 @@ -/* - * Copyright (c) 2004-2015 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 <xtensa/config/core.h> - -#if XCHAL_HAVE_MPU -#include <xtensa/core-macros.h> -#include <xtensa/hal.h> -#include <string.h> -#include <stdlib.h> - -/* - * General notes: - * Wherever an address is represented as an unsigned, it has only the 27 most significant bits. This is how - * the addresses are represented in the MPU. It has the benefit that we don't need to worry about overflow. - * - * The asserts in the code are ignored unless an assert handler is set (as it is during testing). - * - * If an assert handler is set, then the MPU map is checked for correctness after every update. - * - * On some configs (actually all configs right now), the MPU entries must be aligned to the background map. - * The constant: XCHAL_MPU_ALIGN_REQ indicates if alignment is required: - * - * The rules for a valid map are: - * - * 1) The entries' vStartAddress fields must always be in non-descending order. - * 2) The entries' memoryType and accessRights must contain valid values - * - * If XCHAL_MPU_ALIGN_REQ == 1 then the following additional rules are enforced: - * 3) If entry0's Virtual Address Start field is nonzero, then that field must equal one of the - * Background Map's Virtual Address Start field values if software ever intends to assert entry0's MPUENB bit. - * 4) If entryN's MPUENB bit will ever be negated while at the same time entryN+1's MPUENB bit is asserted, - * then entryN+1's Virtual Address Start field must equal one of the Background Map's Virtual Address Start field values. - * - * The internal function are first, and the external 'xthal_' functions are at the end. - * - */ -extern void (*_xthal_assert_handler)(); -extern void xthal_write_map_raw(const xthal_MPU_entry* fg, unsigned int n); -extern void xthal_read_map_raw(const xthal_MPU_entry* fg); -extern xthal_MPU_entry _xthal_get_entry(const xthal_MPU_entry* fg, const xthal_MPU_entry* bg, - unsigned int addr, int* infgmap); - -#define MPU_ADDRESS_MASK (0xffffffff << XCHAL_MPU_ALIGN_BITS) -#define MPU_ALIGNMENT_MASK (0xffffffff - MPU_ADDRESS_MASK) - -#define MPU_VSTART_CORRECTNESS_MASK ((0x1 << (XCHAL_MPU_ALIGN_BITS)) - 1) -// Set this to 1 for more extensive internal checking / 0 for production -#define MPU_DEVELOPMENT_MODE 0 - -#if XCHAL_MPU_ALIGN_REQ -#define XCHAL_MPU_WORST_CASE_ENTRIES_FOR_REGION 3 -#else -#define XCHAL_MPU_WORST_CASE_ENTRIES_FOR_REGION 2 -#endif - -/* - * At some point it is faster to commit/invalidate the entire cache rather than going on line at a time. - * If a region is bigger than 'CACHE_REGION_THRESHOLD' we operate on the entire cache. - */ -#if XCHAL_DCACHE_LINESIZE -#define CACHE_REGION_THRESHOLD (32 * XCHAL_DCACHE_LINESIZE / XCHAL_MPU_ALIGN) -#else -#define CACHE_REGION_THRESHOLD 0 -#endif - - -/* - * Normally these functions are no-ops, but the MPU test harness sets an assert handler to detect any inconsistencies in MPU - * entries or any other unexpected internal condition. - */ -#if MPU_DEVELOPMENT_MODE -static void my_assert(int arg) -{ - if (_xthal_assert_handler && !arg) - _xthal_assert_handler(); -} - -static void assert_map_valid() -{ - - if (_xthal_assert_handler) - { - xthal_MPU_entry fg[XCHAL_MPU_ENTRIES]; - xthal_read_map(fg); - if (xthal_check_map(fg, XCHAL_MPU_ENTRIES)) - _xthal_assert_handler(); - } -} - -static void assert_attributes_equivalent(unsigned addr, const xthal_MPU_entry* initial, - const xthal_MPU_entry* fg, const xthal_MPU_entry* bg) -{ - - xthal_MPU_entry e1 = _xthal_get_entry(initial, bg, addr, 0); - xthal_MPU_entry e2 = _xthal_get_entry(fg, bg, addr, 0); - my_assert((XTHAL_MPU_ENTRY_GET_ACCESS(e1) == XTHAL_MPU_ENTRY_GET_ACCESS(e2)) && (XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(e1) == XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(e2))); -} - -static void assert_maps_equivalent(const xthal_MPU_entry* initial, const xthal_MPU_entry* fg, - const xthal_MPU_entry* bg) -{ - /* this function checks that for every address the MPU entries 'initial' result in the same attributes as the entries in 'fg'. - * We only need to check at the addresses that appear in 'initial', 'fg', or 'bg'. - */ - int i; - for (i = 0; i < XCHAL_MPU_ENTRIES; i++) - { - assert_attributes_equivalent(XTHAL_MPU_ENTRY_GET_VSTARTADDR(initial[i]), initial, fg, bg); - assert_attributes_equivalent(XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]), initial, fg, bg); - } - for (i = 0; i < XCHAL_MPU_BACKGROUND_ENTRIES; i++) - assert_attributes_equivalent(XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[i]), initial, fg, bg); -} -#else -#define my_assert(x) -#define assert_map_valid(x) -#endif - -#if 0 -// These functions aren't used, but am leaving the definitions in place -// for possible future use. -static inline unsigned read_mpucfg() -{ - unsigned long tmp; - __asm__ __volatile__("rsr.mpucfg %0\n\t" - : "=a" (tmp)); - return tmp; -} - -static inline unsigned read_mpuenb() -{ - unsigned long tmp; - __asm__ __volatile__("rsr.mpuenb %0\n\t" - : "=a" (tmp)); - return tmp; -} - -/* This function writes the enable for the MPU entries */ -static inline void write_mpuenb(unsigned v) -{ - __asm__ __volatile__("wsr.mpuenb %0\n\t" - : : "a" (v)); -} - -#endif - -static inline void isync() -{ - __asm__ __volatile__("isync\n\t"); -} - -/* This function writes the cache disable register which - * disables the cache by 512MB registers to save power*/ -static inline void write_cacheadrdis(unsigned v) -{ - __asm__ __volatile__("wsr.cacheadrdis %0\n\t" - : : "a" (v)); -} - -inline static int is_cacheable(unsigned int mt); - -#if 0 -static inline void read_map_entry(unsigned en_num, xthal_MPU_entry* en) -{ - unsigned as; - unsigned at0; - unsigned at1; - as = en_num; - __asm__ __volatile__("RPTLB0 %0, %1\n\t" : "+a" (at0) : "a" (as)); - __asm__ __volatile__("RPTLB1 %0, %1\n\t" : "+a" (at1) : "a" (as)); - en->as = at0; - en->at = at1; -} -#endif - -inline static int is_cacheable(unsigned int mt) -{ - return (0x180 & mt) || ((mt & 0x18) == 0x10) || ((mt & 0x30) == 0x30); -} - -inline static int is_writeback(unsigned int mt) -{ - return (((0x180 & mt) && (mt & 0x11)) || - ((((mt & 0x18) == 0x10) || ((mt & 0x30) == 0x30)) & 0x1)); -} - -inline static int is_device(unsigned int mt) -{ - return ((mt & 0x1f0) == 0); -} - -inline static int is_kernel_readable(int accessRights) -{ - switch (accessRights) - { - case XTHAL_AR_R: - case XTHAL_AR_Rr: - case XTHAL_AR_RX: - case XTHAL_AR_RXrx: - case XTHAL_AR_RW: - case XTHAL_AR_RWX: - case XTHAL_AR_RWr: - case XTHAL_AR_RWrw: - case XTHAL_AR_RWrwx: - case XTHAL_AR_RWXrx: - case XTHAL_AR_RWXrwx: - return 1; - case XTHAL_AR_NONE: - case XTHAL_AR_Ww: - return 0; - default: - return XTHAL_BAD_ACCESS_RIGHTS; - } -} - -inline static int is_kernel_writeable(int accessRights) -{ - switch (accessRights) - { - case XTHAL_AR_RW: - case XTHAL_AR_RWX: - case XTHAL_AR_RWr: - case XTHAL_AR_RWrw: - case XTHAL_AR_RWrwx: - case XTHAL_AR_RWXrx: - case XTHAL_AR_RWXrwx: - case XTHAL_AR_Ww: - return 1; - case XTHAL_AR_NONE: - case XTHAL_AR_R: - case XTHAL_AR_Rr: - case XTHAL_AR_RX: - case XTHAL_AR_RXrx: - return 0; - default: - return XTHAL_BAD_ACCESS_RIGHTS; - } -} - -inline static int is_kernel_executable(int accessRights) -{ - switch (accessRights) - { - case XTHAL_AR_RX: - case XTHAL_AR_RXrx: - case XTHAL_AR_RWX: - case XTHAL_AR_RWXrx: - case XTHAL_AR_RWXrwx: - return 1; - case XTHAL_AR_NONE: - case XTHAL_AR_Ww: - case XTHAL_AR_R: - case XTHAL_AR_Rr: - case XTHAL_AR_RW: - case XTHAL_AR_RWr: - case XTHAL_AR_RWrw: - case XTHAL_AR_RWrwx: - return 0; - default: - return XTHAL_BAD_ACCESS_RIGHTS; - } -} - -inline static int is_user_readable(int accessRights) -{ - switch (accessRights) - { - case XTHAL_AR_Rr: - case XTHAL_AR_RXrx: - case XTHAL_AR_RWr: - case XTHAL_AR_RWrw: - case XTHAL_AR_RWrwx: - case XTHAL_AR_RWXrx: - case XTHAL_AR_RWXrwx: - return 1; - case XTHAL_AR_R: - case XTHAL_AR_RX: - case XTHAL_AR_RW: - case XTHAL_AR_RWX: - case XTHAL_AR_NONE: - case XTHAL_AR_Ww: - return 0; - default: - return XTHAL_BAD_ACCESS_RIGHTS; - } -} - -inline static int is_user_writeable(int accessRights) -{ - switch (accessRights) - { - case XTHAL_AR_Ww: - case XTHAL_AR_RWrw: - case XTHAL_AR_RWrwx: - case XTHAL_AR_RWXrwx: - return 1; - case XTHAL_AR_NONE: - case XTHAL_AR_R: - case XTHAL_AR_Rr: - case XTHAL_AR_RX: - case XTHAL_AR_RXrx: - case XTHAL_AR_RW: - case XTHAL_AR_RWX: - case XTHAL_AR_RWr: - case XTHAL_AR_RWXrx: - return 0; - default: - return XTHAL_BAD_ACCESS_RIGHTS; - } -} - -inline static int is_user_executable(int accessRights) -{ - switch (accessRights) - { - case XTHAL_AR_RXrx: - case XTHAL_AR_RWrwx: - case XTHAL_AR_RWXrx: - case XTHAL_AR_RWXrwx: - return 1; - case XTHAL_AR_RW: - case XTHAL_AR_RWX: - case XTHAL_AR_RWr: - case XTHAL_AR_RWrw: - case XTHAL_AR_R: - case XTHAL_AR_Rr: - case XTHAL_AR_RX: - case XTHAL_AR_NONE: - case XTHAL_AR_Ww: - return 0; - default: - return XTHAL_BAD_ACCESS_RIGHTS; - } -} - -/* This function returns the map entry that is used for the address 'addr' (27msb). - * - */ -#if defined(__SPLIT__mpu_basic) - -xthal_MPU_entry _xthal_get_entry(const xthal_MPU_entry* fg, const xthal_MPU_entry* bg, - unsigned int addr, int* infgmap) -{ - int i; - for (i = XCHAL_MPU_ENTRIES - 1; i >= 0; i--) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) <= addr) - { - if (XTHAL_MPU_ENTRY_GET_VALID(fg[i])) - { - if (infgmap) - *infgmap = 1; - return fg[i]; - } - else - break; - } - } - for (i = XCHAL_MPU_BACKGROUND_ENTRIES - 1; i >= 0; i--) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[i]) <= addr) - { - if (infgmap) - *infgmap = 0; - return bg[i]; - } - } - return bg[0]; // never reached ... just to get rid of compilation warning -} - -/* returns true if the supplied address (27msb) is in the background map. */ -int _xthal_in_bgmap(unsigned int address, const xthal_MPU_entry* bg) -{ - int i; - for (i = 0; i < XCHAL_MPU_BACKGROUND_ENTRIES; i++) - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[i]) == address) - return 1; - return 0; -} - -#endif - -#if defined(__SPLIT__mpu_attributes) - -/* This function updates the map entry as well as internal duplicate of the map - * state in fg. The assumption is that reading map entries could be somewhat - * expensive in some situations so we are keeping a copy of the map in memory when - * doing extensive map manipulations. - */ -static void write_map_entry(xthal_MPU_entry* fg, unsigned en_num, xthal_MPU_entry en) -{ - en.at = (en.at & 0xffffffe0) | (en_num & 0x1f); - xthal_mpu_set_entry(en); - assert_map_valid(); - fg[en_num] = en; -} - -static void move_map_down(xthal_MPU_entry* fg, int dup, int idx) -{ - /* moves the map entry list down one (leaving duplicate entries at idx and idx+1. This function assumes that the last - * entry is invalid ... call MUST check this - */ - unsigned int i; - for (i = dup; i > idx; i--) - { - write_map_entry(fg, i, fg[i - 1]); - } -} - -static void move_map_up(xthal_MPU_entry* fg, int dup, int idx) -{ - /* moves the map entry list up one (leaving duplicate entries at idx and idx-1, removing the entry at dup - */ - int i; - for (i = dup; i < idx - 1; i++) - { - write_map_entry(fg, i, fg[i + 1]); - } -} - -static int bubble_free_to_ip(xthal_MPU_entry* fg, int ip, int required) -{ - /* This function shuffles the entries in the MPU to get at least 'required' free entries at - * the insertion point 'ip'. This function returns the new insertion point (after all the shuffling). - */ - int i; - int rv = ip; - if (required < 1) - return ip; - my_assert(required <= XCHAL_MPU_ENTRIES); - /* first we search for duplicate or unused entries at an index less than 'ip'. We start looking at ip-1 - * (rather than 0) to minimize the number of shuffles required. - */ - for (i = ip - 2; i >= 0 && required;) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) == XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i + 1])) - { - move_map_up(fg, i, ip); - rv--; - required--; - } - i--; - } - // if there are any invalid entries at top of the map, we can remove them to make space - while (required) - { - if (!XTHAL_MPU_ENTRY_GET_VALID(fg[0])) - { - move_map_up(fg, 0, ip); - rv--; - required--; - } - else - break; - } - /* If there are not enough unneeded entries at indexes less than ip, then we search at indexes > ip. - * We start the search at ip+1 and move down, again to minimize the number of shuffles required. - */ - - for (i = ip + 1; i < XCHAL_MPU_ENTRIES && required;) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) == XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i - 1])) - { - move_map_down(fg, i, ip); - required--; - } - else - i++; - } - my_assert(required == 0); - return rv; -} - - -/* This function removes 'inaccessible' entries from the MPU map (those that are hidden by previous entries - * in the map). It leaves any entries that match background entries in place. - */ -static void remove_inaccessible_entries(xthal_MPU_entry* fg, const xthal_MPU_entry* bg) -{ - int i; - for (i = 1; i < XCHAL_MPU_ENTRIES; i++) - { - if (((XTHAL_MPU_ENTRY_GET_VALID(fg[i]) == XTHAL_MPU_ENTRY_GET_VALID(fg[i - 1])) && (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) > XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i - 1])) - && (XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(fg[i]) == XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(fg[i - 1])) && (XTHAL_MPU_ENTRY_GET_ACCESS(fg[i]) == XTHAL_MPU_ENTRY_GET_ACCESS(fg[i - 1])) && - /* we can only remove the background map entry if either background alignment is not required, or - * if the previous entry is enabled. - */ - (!_xthal_in_bgmap(XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]), bg))) - || ((!XTHAL_MPU_ENTRY_GET_VALID(fg[i]) && (!XTHAL_MPU_ENTRY_GET_VALID(fg[i - 1])) && (!_xthal_in_bgmap(XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]), bg))))) - { - write_map_entry(fg, i, fg[i - 1]); - } - } -} - -/* This function takes bitwise or'd combination of access rights and memory type, and extracts - * the access rights. It returns the access rights, or -1. - */ -static int encode_access_rights(int cattr) -{ - cattr = cattr & 0xF; - if ((cattr) > 0 && (cattr < 4)) - return -1; - else - return cattr; -} - -/* - * returns the largest value rv, such that for every index < rv, - * entrys[index].vStartAddress < first. - * - * Assumes an ordered entry array (even disabled entries must be ordered). - * value returned is in the range [0, XCHAL_MPU_ENTRIES]. - * - */ -static int find_entry(xthal_MPU_entry* fg, unsigned first) -{ - int i; - for (i = XCHAL_MPU_ENTRIES - 1; i >= 0; i--) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) <= first) - return i + 1; - } - return 0; // if it is less than all existing entries return 0 -} - -/* - * This function returns 1 if there is an exact match for first and first+size - * so that no manipulations are necessary before safing and updating the attributes - * for [first, first+size). The the first and end entries - * must be valid, as well as all the entries in between. Otherwise the memory - * type might change across the region and we wouldn't be able to safe the caches. - * - * An alternative would be to require alignment regions in this case, but that seems - * more wasteful. - */ -static int needed_entries_exist(xthal_MPU_entry* fg, unsigned first, unsigned last) -{ - int i; - for (i = 0; i < XCHAL_MPU_ENTRIES; i++) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) == first) - { - int j; - /* special case ... is last at the end of the address space - * ... if so there is no end entry needed. - */ - if (last == 0xFFFFFFFF) - { - int k; - for (k = i; k < XCHAL_MPU_ENTRIES; k++) - if (!XTHAL_MPU_ENTRY_GET_VALID(fg[k])) - return 0; - return 1; - } - /* otherwise search for the end entry */ - for (j = i; j < XCHAL_MPU_ENTRIES; j++) - if (last == XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[j])) - { - int k; - for (k = i; k <= j; k++) - if (!XTHAL_MPU_ENTRY_GET_VALID(fg[k])) - return 0; - return 1; - } - return 0; - } - } - return 0; -} - -/* This function computes the number of MPU entries that are available for use in creating a new - * region. - */ -static int number_available(xthal_MPU_entry* fg) -{ - int i; - int rv = 0; - int valid_seen = 0; - for (i = 0; i < XCHAL_MPU_ENTRIES; i++) - { - if (!valid_seen) - { - if (XTHAL_MPU_ENTRY_GET_VALID(fg[i])) - valid_seen = 1; - else - { - rv++; - continue; - } - } - else - { - if (i && (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) == XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i - 1]))) - rv++; - } - } - return rv; -} - -/* - * This function returns index of the background map entry that maps the address 'first' if there are no - * enabled/applicable foreground map entries. - */ -static int get_bg_map_index(const xthal_MPU_entry* bg, unsigned first) -{ - int i; - for (i = XCHAL_MPU_BACKGROUND_ENTRIES - 1; i >= 0; i--) - if (first > XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[i])) - return i; - return 0; -} - -inline static unsigned int covert_to_writethru_memtype(unsigned int wb_memtype) -{ - unsigned int prefix = wb_memtype & 0x1f0; - if (prefix == 0x10) - return wb_memtype & 0xfffffffe; - else - return wb_memtype & 0xffffffee; -} - -/* - * This function takes the region pointed to by ip, and makes it safe from the aspect of cache coherency, before - * changing the memory type and possibly corrupting the cache. If wb is 0, then that indicates - * that we should ignore uncommitted entries. If the inv argument is 0 that indicates that we shouldn't invalidate - * the cache before switching to bypass. - */ -static void safe_region(xthal_MPU_entry* fg, int ip, unsigned end_of_segment, int memoryType, int wb, int inv, - unsigned int* post_inv_all) -{ - unsigned length = end_of_segment - XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[ip]); // initially keep length 27msb to avoid possibility of overflow - if (!length) - return; // if the region is empty, there is no need to safe it - - int cmemType = XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(fg[ip]); - - if (memoryType == cmemType) - return; // not changing memory types ... we don't need to do anything - - int mt_is_wb = is_writeback(memoryType); - int mt_is_ch = is_cacheable(memoryType); - - // nothing needs to be done in these cases - if (mt_is_wb || (!wb && (!inv || mt_is_ch))) - return; - - int need_flush = wb && (is_writeback(cmemType) && !is_writeback(memoryType)); - int need_invalidate = inv && (is_cacheable(cmemType) && !is_cacheable(memoryType)); - - void* addr = (void*) XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[ip]); - - int write_by_region = length < CACHE_REGION_THRESHOLD; - - if (need_flush) - { - XTHAL_MPU_ENTRY_SET_MEMORY_TYPE(fg[ip], covert_to_writethru_memtype(XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(fg[ip]))); - // If the AR == NONE, the writing back the cache may generate exception. Temporarily open up the protections ... - // ... - if (XTHAL_MPU_ENTRY_GET_ACCESS(fg[ip]) == XTHAL_AR_NONE) - XTHAL_MPU_ENTRY_SET_ACCESS(fg[ip], XTHAL_AR_RWXrwx); - // bit 0 determines if it wb/wt - write_map_entry(fg, ip, fg[ip]); - if (!write_by_region) - { - /* unfortunately there is no straight forward way to avoid the possibility of doing - * multiple xthal_dcache_all_writeback() calls during a region update. The reason for this - * is that: - * - * 1) The writeback must be done before the memory type is changed to non-cacheable before - * an invalidate (see below) - * - * 2) it isn't possible to reorganize the loop so that all the writebacks are done before - * any of the invalidates because if part of the region of interest is (initially) mapped - * by the background map, then a single foreground entry is reused to 'safe' across - * each background map entry that is overlapped. - */ - xthal_dcache_all_writeback(); - } - else if (length) - xthal_dcache_region_writeback(addr, length); - } - - if (need_invalidate) - { - XTHAL_MPU_ENTRY_SET_MEMORY_TYPE(fg[ip], - XTHAL_ENCODE_MEMORY_TYPE(XCHAL_CA_BYPASS)); - write_map_entry(fg, ip, fg[ip]); - /* only need to call all_invalidate once ... check - * if it has already been done. - */ - if (!*post_inv_all) - { - if (!write_by_region) - { - *post_inv_all = 1; - } - else if (length) - { - xthal_icache_region_invalidate(addr, length); - xthal_dcache_region_writeback_inv(addr, length); - } - } - } -} - -static unsigned max(unsigned a, unsigned b, unsigned c) -{ - if (a > b && a > c) - return a; - else if (b > c) - return b; - else - return c; -} - -/* This function returns the next address to commit which will be the greatest of the following: - * 1) The start of the region we are creating - * 2) The vStartAddress of the previous entry - * 3) The background map entry that precedes the current address (last address committed). - */ -static unsigned next_address_to_commit(xthal_MPU_entry* fg, const xthal_MPU_entry* bg, unsigned first, - int current_index) -{ - unsigned current = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[current_index]); - return max(first, XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[current_index - 1]), XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[get_bg_map_index(bg, current)])); -} - -/* - * This function does a series of calls to safe_region() to ensure that no data will be corrupted when changing the memory type - * of an MPU entry. These calls are made for every entry address in the range[first,end), as well as at any background region boundary - * in the range[first,end). In general it is necessary to safe at the background region boundaries, because the memory type could - * change at that address. - * - * This function is written to reuse already needed entries for the background map 'safes' which complicates things somewhat. - * - * After the calls to safe region are complete, then the entry attributes are updated for every entry in the range [first,end). - */ -static void safe_and_commit_overlaped_regions(xthal_MPU_entry* fg, const xthal_MPU_entry*bg, unsigned first, - unsigned last, int memoryType, int accessRights, int wb, int inv) -{ - int i; - unsigned int next; - unsigned end_of_segment = last; - unsigned post_inv_all = 0; - unsigned int cachedisadr; - write_cacheadrdis(0); - for (i = XCHAL_MPU_ENTRIES - 1; i >= 0; i--) - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) < last) - { - // first we want to commit the first entry - safe_region(fg, i, end_of_segment, memoryType, wb, inv, &post_inv_all); - end_of_segment = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]); - do - { - next = next_address_to_commit(fg, bg, first, i); - if (next == XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i - 1])) - i--; - XTHAL_MPU_ENTRY_SET_VSTARTADDR(fg[i], next); - safe_region(fg, i, last, memoryType, wb, inv, &post_inv_all); - end_of_segment = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]); - } while (next > first); - if (post_inv_all) - { - xthal_icache_all_invalidate(); - xthal_dcache_all_writeback_inv(); - } - for (; i < XCHAL_MPU_ENTRIES && XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) < last; i++) - { - XTHAL_MPU_ENTRY_SET_MEMORY_TYPE(fg[i], memoryType); - XTHAL_MPU_ENTRY_SET_ACCESS(fg[i], accessRights); - XTHAL_MPU_ENTRY_SET_VALID(fg[i], 1); - write_map_entry(fg, i, fg[i]); - } - break; - } - cachedisadr = xthal_calc_cacheadrdis(fg, XCHAL_MPU_ENTRIES); - write_cacheadrdis(cachedisadr); -} - -static void handle_invalid_pred(xthal_MPU_entry* fg, const xthal_MPU_entry* bg, unsigned first, int ip) -{ - /* Handle the case where there is an invalid entry immediately preceding the entry we - * are creating. If the entries addresses correspond to the same bg map, then we - * make the previous entry valid with same attributes as the background map entry. - * - * The case where an invalid entry exists immediately preceding whose address corresponds to a different - * background map entry is handled by create_aligning_entries_if_required(), so nothing is done here. - */ - /* todo ... optimization opportunity, the following block loops through the background map up to 4 times, - * - */ - if (!ip || XTHAL_MPU_ENTRY_GET_VALID(fg[ip - 1])) - return; - { - int i; - unsigned fgipm1_addr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[ip - 1]); - int first_in_bg_map = 0; - int first_bg_map_index = -1; - int fgipm1_bg_map_index = -1; -#if MPU_DEVELOPMENT_MODE - unsigned fgip_addr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[ip]); - int fgip_bg_map_index = -1; -#endif - for (i = XCHAL_MPU_BACKGROUND_ENTRIES - 1; i >= 0; i--) - { - unsigned addr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[i]); - if (addr == first) - first_in_bg_map = 1; - if (addr < fgipm1_addr && fgipm1_bg_map_index == -1) - fgipm1_bg_map_index = i; -#if MPU_DEVELOPMENT_MODE - if (addr < fgip_addr && fgip_bg_map_index == -1) - fgip_bg_map_index = i; -#endif - if (addr < first && first_bg_map_index == -1) - first_bg_map_index = i; - } - if (!first_in_bg_map && (first_bg_map_index == fgipm1_bg_map_index)) - { - // There should be a subsequent entry that falls in the address range of same - // background map entry ... if not, we have a problem because the following - // will corrupt the memory map -#if MPU_DEVELOPMENT_MODE - { - my_assert(fgip_bg_map_index == fgipm1_bg_map_index); - } -#endif - xthal_MPU_entry temp = _xthal_get_entry(fg, bg, XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[ip - 1]), 0); - XTHAL_MPU_ENTRY_SET_VSTARTADDR(temp, XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[ip - 1])); - write_map_entry(fg, ip - 1, temp); - } - } -} - -/* This function inserts a entry (unless it already exists) with vStartAddress of first. The new entry has - * the same accessRights and memoryType as the address first had before the call. - * - * If 'invalid' is specified, then insert an invalid region if no foreground entry exists for the address 'first'. - */ -static int insert_entry_if_needed_with_existing_attr(xthal_MPU_entry* fg, const xthal_MPU_entry* bg, - unsigned first, int invalid) -{ - int i; - int ip; - int infg; - int found = 0; - - for (i = XCHAL_MPU_ENTRIES - 1; i >= 0; i--) - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) == first) - { - if (XTHAL_MPU_ENTRY_GET_VALID(fg[i]) || invalid) - return XTHAL_SUCCESS; - else - { - found = 1; - ip = i; - break; - } - } - - if (!found) - { - if (!number_available(fg)) - return XTHAL_OUT_OF_ENTRIES; - - ip = find_entry(fg, first); - ip = bubble_free_to_ip(fg, ip, 1); - } - if (!invalid) - handle_invalid_pred(fg, bg, first, ip); - xthal_MPU_entry n; - memset(&n, 0, sizeof(n)); - n = _xthal_get_entry(fg, bg, first, &infg); - - if (invalid && !infg) // If the entry mapping is currently in the foreground we can't make - // the entry invalid without corrupting the attributes of the following entry. - XTHAL_MPU_ENTRY_SET_VALID(n, 0); - XTHAL_MPU_ENTRY_SET_VSTARTADDR(n,first); - write_map_entry(fg, ip, n); - return XTHAL_SUCCESS; -} - -static unsigned int smallest_entry_greater_than_equal(xthal_MPU_entry* fg, unsigned x) -{ - int i; - for (i = 0; i < XCHAL_MPU_ENTRIES; i++) - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) >= x) - return XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]); - return 0; -} - -/* This function creates background map aligning entries if required.*/ -static unsigned int create_aligning_entries_if_required(xthal_MPU_entry* fg, const xthal_MPU_entry* bg, - unsigned x) -{ -#if XCHAL_MPU_ALIGN_REQ - int i; - int rv; - unsigned next_entry_address = 0; - unsigned next_entry_valid = 0; - int preceding_bg_entry_index_x = get_bg_map_index(bg, x); - unsigned preceding_bg_entry_x_addr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[preceding_bg_entry_index_x]); - for (i = XCHAL_MPU_ENTRIES - 1; i >= 0; i--) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) < x) - { - if (XTHAL_MPU_ENTRY_GET_VALID(fg[i])) - return XTHAL_SUCCESS; // If there is a valid entry immediately before the proposed new entry - // ... then no aligning entries are required - break; - } - else - { - next_entry_address = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]); - next_entry_valid = XTHAL_MPU_ENTRY_GET_VALID(fg[i]); - } - } - - /* - * before creating the aligning entry, we may need to create an entry or entries a higher - * addresses to limit the scope of the aligning entry. - */ - if ((!next_entry_address) || (!next_entry_valid) || (_xthal_in_bgmap(next_entry_address, bg))) - { - /* in this case, we can just create an invalid entry at the start of the new region because - * a valid entry could have an alignment problem. An invalid entry is safe because we know that - * the next entry is either invalid, or is on a bg map entry - */ - if ((rv = insert_entry_if_needed_with_existing_attr(fg, bg, x, 1)) != XTHAL_SUCCESS) - { - return rv; - } - } - else - { - unsigned next_bg_entry_index; - for (next_bg_entry_index = 0; next_bg_entry_index < XCHAL_MPU_BACKGROUND_ENTRIES; next_bg_entry_index++) - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[next_bg_entry_index]) > x) - break; - if (next_entry_address == XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[next_bg_entry_index])) // In this case there is no intervening bg entry - // between the new entry x, and the next existing entry so, we don't need any limiting entry - // (the existing next_entry serves as the limiting entry) - { /* intentionally empty */ - } - else - { - // In this case we need to create a valid region at the background entry that immediately precedes - // next_entry_address, and then create an invalid entry at the background entry immediately after - // x - if ((rv = insert_entry_if_needed_with_existing_attr(fg, bg, XTHAL_MPU_ENTRY_GET_VSTARTADDR(_xthal_get_entry(fg, bg, x, 0)), 0)) - != XTHAL_SUCCESS) - { - return rv; - } - if ((rv = insert_entry_if_needed_with_existing_attr(fg, bg, - XTHAL_MPU_ENTRY_GET_VSTARTADDR(_xthal_get_entry(fg, bg, XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[next_bg_entry_index]), 0)), 1)) != XTHAL_SUCCESS) - { - return rv; - } - } - } - - /* now we are finally ready to create the aligning entry.*/ - if (!(x == preceding_bg_entry_x_addr)) - if ((rv = insert_entry_if_needed_with_existing_attr(fg, bg, preceding_bg_entry_x_addr, 0)) != XTHAL_SUCCESS) - { - return rv; - } - - return XTHAL_SUCCESS; - -#else - return XTHAL_SUCCESS; -#endif -} - -static unsigned start_initial_region(xthal_MPU_entry* fg, const xthal_MPU_entry* bg, unsigned first, - unsigned end) -{ - int i; - unsigned addr; - for (i = XCHAL_MPU_BACKGROUND_ENTRIES - 1; i >= 0; i--) - { - addr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(bg[i]); - if (addr <= first) - break; - if (addr < end) - return addr; - } - return first; -} - -static int safe_add_region(unsigned first, unsigned last, unsigned accessRights, unsigned memoryType, - unsigned writeback, unsigned invalidate) -{ - /* This function sets the memoryType and accessRights on a region of memory. If necessary additional MPU entries - * are created so that the attributes of any memory outside the specified region are not changed. - * - * This function has 2 stages: - * 1) The map is updated one entry at a time to create (if necessary) new entries to mark the beginning and end of the - * region as well as addition alignment entries if needed. During this stage the map is always correct, and the memoryType - * and accessRights for every address remain the same. - * 2) The entries inside the update region are then safed for cache consistency (if necessary) and then written with - * the new accessRights, and memoryType. - * - * If the function fails (by running out of available map entries) during stage 1 then everything is still consistent and - * it is safe to return an error code. - * - * If XCHAL_MPU_ALIGN_REQ is provided then extra entries are create if needed - * to satisfy these alignment conditions: - * - * 1) If entry0's Virtual Address Start field is nonzero, then that field must equal one of the Background Map's - * Virtual Address Start field values if software ever intends to assert entry0's MPUENB bit. - * 2) If entryN's MPUENB bit will ever be negated while at the same time entryN+1's MPUENB bit is - * asserted, then entryN+1's Virtual Address Start field must equal one of the Background Map's Virtual Address Start field values. - * - * Between 0 and 2 available entries will be used by this function. In addition, if XCHAL_MPU_ALIGN_REQ == 1 up to ??? - * additional entries will be needed to meet background map alignment requirements. - * - * This function keeps a copy of the current map in 'fg'. This is kept in sync with contents of the MPU at all times. - * - */ - - int rv; - - xthal_MPU_entry fg[XCHAL_MPU_ENTRIES]; -#if MPU_DEVELOPMENT_MODE - xthal_MPU_entry on_entry[XCHAL_MPU_ENTRIES]; - xthal_read_map(on_entry); -#endif - xthal_read_map(fg); - assert_map_valid(); - - /* First we check and see if consecutive entries at first, and first + size already exist. - * in this important special case we don't need to do anything but safe and update the entries [first, first+size). - * - */ - - if (!needed_entries_exist(fg, first, last)) - { - unsigned x; - unsigned pbg; - - /* - * If we are tight on entries, the first step is to remove any redundant entries in the MPU - * to make room to ensure that there is room for the new entries we need. - * - * We need to call it here ... once we have started transforming the map it is too late - * (the process involves creating inaccessible entries that could potentially get removed). - */ - if (number_available(fg) < XCHAL_MPU_WORST_CASE_ENTRIES_FOR_REGION) - remove_inaccessible_entries(fg, Xthal_mpu_bgmap); -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - // First we create foreground entries that 'duplicate' background entries to aide in - // maintaining proper alignment. - if ((rv = create_aligning_entries_if_required(fg, Xthal_mpu_bgmap, first)) != XTHAL_SUCCESS) - return rv; - - // First we write the terminating entry for our region - // 5 cases: - // 1) end is at the end of the address space, then we don't need to do anything ... takes 0 entries - // 2) There is an existing entry at end ... another nop ... 0 entries - // 3) end > than any existing entry ... in this case we just create a new invalid entry at end to mark - // end of the region. No problem with alignment ... this takes 1 entry - // 4) otherwise if there is a background map boundary between end and x ,the smallest existing entry that is - // greater than end, then we first create an equivalent foreground map entry for the background map entry that immediately - // precedes x, and then we write an invalid entry for end. Takes 2 entries - // 5) otherwise x is in the same background map entry as end, in this case we write a new foreground entry with the existing - // attributes at end - - if (last == 0xFFFFFFFF) - { /* the end is the end of the address space ... do nothing */ - } - else - { - x = smallest_entry_greater_than_equal(fg, last); - if (last == x) - { /* another nop */ - } - else if (last > x) - { /* there is no entry that has a start after the new region ends - ... we handle this by creating an invalid entry at the end point */ - if ((rv = insert_entry_if_needed_with_existing_attr(fg, Xthal_mpu_bgmap, last, 1)) != XTHAL_SUCCESS) - { -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - return rv; - } -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - } - else - { - pbg = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[get_bg_map_index(Xthal_mpu_bgmap, x)]); - /* so there is an existing entry we must deal with. We next need to find - * if there is an existing background entry in between the end of - * the new region and beginning of the next. - */ - if ((pbg != x) && (pbg > last)) - { - /* okay ... there is an intervening background map entry. We need - * to handle this by inserting an aligning entry (if the architecture requires it) - * and then placing writing an invalid entry at end. - */ - if (XCHAL_MPU_ALIGN_REQ) - { - if ((rv = insert_entry_if_needed_with_existing_attr(fg, Xthal_mpu_bgmap, pbg, 0)) != XTHAL_SUCCESS) - { -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - return rv; - } -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - } - if ((rv = insert_entry_if_needed_with_existing_attr(fg, Xthal_mpu_bgmap, last, 1)) != XTHAL_SUCCESS) - { -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - return rv; - } -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - } - else - /* ok so there are no background map entry in between end and x, in this case - * we just need to create a new entry at end writing the existing attributes. - */ - if ((rv = insert_entry_if_needed_with_existing_attr(fg, Xthal_mpu_bgmap, last, 1)) != XTHAL_SUCCESS) - { -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - return rv; - } -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - } - } - - /* last, but not least we need to insert a entry at the starting address for our new region */ - if ((rv = insert_entry_if_needed_with_existing_attr(fg, Xthal_mpu_bgmap, start_initial_region(fg, Xthal_mpu_bgmap, first, last), 0)) - != XTHAL_SUCCESS) - { -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - return rv; - } -#if MPU_DEVELOPMENT_MODE - assert_maps_equivalent(on_entry, fg, Xthal_mpu_bgmap); -#endif - } - // up to this point, the attributes of every byte in the address space should be the same as when this function - // was called. - safe_and_commit_overlaped_regions(fg, Xthal_mpu_bgmap, first, last, memoryType, accessRights, writeback, invalidate); - - assert_map_valid(); - return XTHAL_SUCCESS; -} - -// checks if x (full 32bit) is mpu_aligned for MPU -static unsigned int mpu_aligned(unsigned x) -{ - return !(x & MPU_ALIGNMENT_MASK); -} - -static unsigned int mpu_align(unsigned int x, unsigned int roundUp) -{ - if (roundUp) - return (x + MPU_ALIGNMENT_MASK) & MPU_ADDRESS_MASK; - else - return (x & MPU_ADDRESS_MASK); -} - -#endif - -#if defined(__SPLIT__mpu_check) -static int bad_accessRights(unsigned ar) -{ - if (ar == 0 || (ar >= 4 && ar <= 15)) - return 0; - else - return 1; -} - -/* this function checks if the supplied map 'fg' is a valid MPU map using 3 criteria: - * 1) if an entry is valid, then that entries accessRights must be defined (0 or 4-15). - * 2) The map entries' 'vStartAddress's must be in increasing order. - * 3) If the architecture requires background map alignment then: - * a) If entry0's 'vStartAddress' field is nonzero, then that field must equal - * one of the Background Map's 'vStartAddress' field values if the entry 0's valid bit is set. - * b) If entryN's 'valid' bit is 0 and entry[N+1]'s 'valid' bit is 1, then - * entry[N+1]'s 'vStartAddress' field must equal one of the Background Map's 'vStartAddress' field values. - * - * This function returns XTHAL_SUCCESS if the map satisfies the condition, otherwise it returns - * XTHAL_BAD_ACCESS_RIGHTS, XTHAL_OUT_OF_ORDER_MAP, or XTHAL_MAP_NOT_ALIGNED. - * - */ -static int check_map(const xthal_MPU_entry* fg, unsigned int n, const xthal_MPU_entry* bg) -{ - int i; - unsigned current = 0; - if (!n) - return XTHAL_SUCCESS; - if (n > XCHAL_MPU_ENTRIES) - return XTHAL_OUT_OF_ENTRIES; - for (i = 0; i < n; i++) - { - if (XTHAL_MPU_ENTRY_GET_VALID(fg[i]) && bad_accessRights(XTHAL_MPU_ENTRY_GET_ACCESS(fg[i]))) - return XTHAL_BAD_ACCESS_RIGHTS; - if ((XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) < current)) - return XTHAL_OUT_OF_ORDER_MAP; - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]) & MPU_VSTART_CORRECTNESS_MASK) - return XTHAL_MAP_NOT_ALIGNED; - current = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i]); - } - if (XCHAL_MPU_ALIGN_REQ && XTHAL_MPU_ENTRY_GET_VALID(fg[0]) && XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[0]) - && !_xthal_in_bgmap(XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[0]), bg)) - return XTHAL_MAP_NOT_ALIGNED; - for (i = 0; i < n- 1; i++) - if (XCHAL_MPU_ALIGN_REQ && !XTHAL_MPU_ENTRY_GET_VALID(fg[i]) && XTHAL_MPU_ENTRY_GET_VALID(fg[i + 1]) - && !_xthal_in_bgmap(XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[i + 1]), bg)) - return XTHAL_MAP_NOT_ALIGNED; - return XTHAL_SUCCESS; -} - - - -/* - * this function checks that the bit-wise or-ed XTHAL_MEM_... bits in x correspond to a valid - * MPU memoryType. If x is valid, then 0 is returned, otherwise XTHAL_BAD_MEMORY_TYPE is - * returned. - */ -static int check_memory_type(unsigned x) -{ - unsigned system_cache_type = _XTHAL_MEM_CACHE_MASK(x); - unsigned processor_cache_type = (((x) & _XTHAL_LOCAL_CACHE_BITS) >> 4); - if ((system_cache_type > XTHAL_MEM_NON_CACHEABLE) || (processor_cache_type > XTHAL_MEM_NON_CACHEABLE)) - return XTHAL_BAD_MEMORY_TYPE; - int processor_cache_type_set = 1; - if (!processor_cache_type) - { - processor_cache_type = system_cache_type << 4; - processor_cache_type_set = 0; - } - unsigned device = _XTHAL_MEM_IS_DEVICE(x); - unsigned system_noncacheable = _XTHAL_IS_SYSTEM_NONCACHEABLE(x); - - if (device | system_noncacheable) - { - if ((system_cache_type || processor_cache_type_set) && device) - return XTHAL_BAD_MEMORY_TYPE; - if (processor_cache_type_set) - return XTHAL_BAD_MEMORY_TYPE; // if memory is device or non cacheable, then processor cache type should not be set - if (system_noncacheable && (x & XTHAL_MEM_INTERRUPTIBLE)) - return XTHAL_BAD_MEMORY_TYPE; - { - unsigned z = x & XTHAL_MEM_SYSTEM_SHAREABLE; - if ((z == XTHAL_MEM_INNER_SHAREABLE) || (z == XTHAL_MEM_OUTER_SHAREABLE)) - return XTHAL_BAD_MEMORY_TYPE; - } - } - else - { - if ((x & XTHAL_MEM_SYSTEM_SHAREABLE) == XTHAL_MEM_SYSTEM_SHAREABLE) - return XTHAL_BAD_MEMORY_TYPE; - if ((x & (XTHAL_MEM_BUFFERABLE | XTHAL_MEM_INTERRUPTIBLE))) - return XTHAL_BAD_MEMORY_TYPE; - } - - return 0; -} -#endif - -#endif // is MPU - -#if defined(__SPLIT__mpu_basic) -/* - * These functions accept encoded access rights, and return 1 if the supplied memory type has the property specified by the function name. - */ -extern int xthal_is_kernel_readable(int accessRights) -{ -#if XCHAL_HAVE_MPU - return is_kernel_readable(accessRights); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -extern int xthal_is_kernel_writeable(int accessRights) -{ -#if XCHAL_HAVE_MPU - return is_kernel_writeable(accessRights); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -extern int xthal_is_kernel_executable(int accessRights) -{ -#if XCHAL_HAVE_MPU - return is_kernel_executable(accessRights); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -extern int xthal_is_user_readable(int accessRights) -{ -#if XCHAL_HAVE_MPU - return is_user_readable(accessRights); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -extern int xthal_is_user_writeable(int accessRights) -{ -#if XCHAL_HAVE_MPU - return is_user_writeable(accessRights); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -extern int xthal_is_user_executable(int accessRights) -{ -#if XCHAL_HAVE_MPU - return is_user_executable(accessRights); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -/* - * These functions accept either an encoded or unencoded memory type, and - * return 1 if the supplied memory type has property specified by the - * function name. - */ -int xthal_is_cacheable(unsigned int mt) -{ -#if XCHAL_HAVE_MPU - return is_cacheable(mt); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -int xthal_is_writeback(unsigned int mt) -{ -#if XCHAL_HAVE_MPU - return is_writeback(mt); -#else - return XTHAL_UNSUPPORTED; -#endif -} - -int xthal_is_device(unsigned int mt) -{ -#if XCHAL_HAVE_MPU - return is_device(mt); -#else - return XTHAL_UNSUPPORTED; -#endif -} -#endif - -/* - * This function converts a bit-wise combination of the XTHAL_MEM_.. constants - * to the corresponding MPU memory type (9-bits). - * - * If none of the XTHAL_MEM_.. bits are present in the argument, then - * bits 4-12 (9-bits) are returned ... this supports using an already encoded - * memoryType (perhaps obtained from an xthal_MPU_entry structure) as input - * to xthal_set_region_attribute(). - * - * This function first checks that the supplied constants are a valid and - * supported combination. If not, it returns XTHAL_BAD_MEMORY_TYPE. - */ -#if defined(__SPLIT__mpu_check) -int xthal_encode_memory_type(unsigned int x) -{ -#if XCHAL_HAVE_MPU - const unsigned int MemoryTypeMask = 0x1ff0; - const unsigned int MemoryFlagMask = 0xffffe000; - /* - * Encodes the memory type bits supplied in an | format (XCHAL_CA_PROCESSOR_CACHE_WRITEALLOC | XCHAL_CA_PROCESSOR_CACHE_WRITEBACK) - */ - unsigned memoryFlags = x & MemoryFlagMask; - if (!memoryFlags) - return (x & MemoryTypeMask) >> XTHAL_AR_WIDTH; - else - { - int chk = check_memory_type(memoryFlags); - if (chk < 0) - return chk; - else - return XTHAL_ENCODE_MEMORY_TYPE(memoryFlags); - } -#else - return XTHAL_UNSUPPORTED; -#endif -} -#endif - -#if defined(__SPLIT__mpu_rmap) - -/* - * Copies the current MPU entry list into 'entries' which - * must point to available memory of at least - * sizeof(xthal_MPU_entry) * XCHAL_MPU_ENTRIES. - * - * This function returns XTHAL_SUCCESS. - * XTHAL_INVALID, or - * XTHAL_UNSUPPORTED. - */ -int xthal_read_map(xthal_MPU_entry* fg_map) -{ -#if XCHAL_HAVE_MPU - unsigned i; - if (!fg_map) - return XTHAL_INVALID; - xthal_read_map_raw(fg_map); - return XTHAL_SUCCESS; -#else - return XTHAL_UNSUPPORTED; -#endif -} - -#if XCHAL_HAVE_MPU - #undef XCHAL_MPU_BGMAP - #define XCHAL_MPU_BGMAP(s,vstart,vend,rights,mtype,x...) XTHAL_MPU_ENTRY(vstart,1,rights,mtype), -const xthal_MPU_entry Xthal_mpu_bgmap[] = { XCHAL_MPU_BACKGROUND_MAP(0) }; -#endif - - -/* - * Copies the MPU background map into 'entries' which must point - * to available memory of at least - * sizeof(xthal_MPU_entry) * XCHAL_MPU_BACKGROUND_ENTRIES. - * - * This function returns XTHAL_SUCCESS. - * XTHAL_INVALID, or - * XTHAL_UNSUPPORTED. - */ -int xthal_read_background_map(xthal_MPU_entry* bg_map) -{ -#if XCHAL_HAVE_MPU - if (!bg_map) - return XTHAL_INVALID; - memcpy(bg_map, Xthal_mpu_bgmap, sizeof(Xthal_mpu_bgmap)); - return XTHAL_SUCCESS; -#else - return XTHAL_UNSUPPORTED; -#endif -} -#endif -/* - * Writes the map pointed to by 'entries' to the MPU. Before updating - * the map, it commits any uncommitted - * cache writes, and invalidates the cache if necessary. - * - * This function does not check for the correctness of the map. Generally - * xthal_check_map() should be called first to check the map. - * - * If n == 0 then the existing map is cleared, and no new map is written - * (useful for returning to reset state) - * - * If (n > 0 && n < XCHAL_MPU_ENTRIES) then a new map is written with - * (XCHAL_MPU_ENTRIES-n) padding entries added to ensure a properly ordered - * map. The resulting foreground map will be equivalent to the map vector - * fg, but the position of the padding entries should not be relied upon. - * - * If n == XCHAL_MPU_ENTRIES then the complete map as specified by fg is - * written. - * - * xthal_write_map() disables the MPU foreground map during the MPU - * update and relies on the background map. - * - * As a result any interrupt that does not meet the following conditions - * must be disabled before calling xthal_write_map(): - * 1) All code and data needed for the interrupt must be - * mapped by the background map with sufficient access rights. - * 2) The interrupt code must not access the MPU. - * - */ -#if defined(__SPLIT__mpu_wmap) -void xthal_write_map(const xthal_MPU_entry* fg, unsigned int n) -{ -#if XCHAL_HAVE_MPU - unsigned int cacheadrdis = xthal_calc_cacheadrdis(fg, n); - xthal_dcache_all_writeback_inv(); - xthal_icache_all_invalidate(); - xthal_write_map_raw(fg, n); - write_cacheadrdis(cacheadrdis); - isync(); // ditto -#endif -} -#endif - -#if defined(__SPLIT__mpu_check) -/* - * Checks if entry vector 'fg' of length 'n' is a valid MPU access map. - * Returns: - * XTHAL_SUCCESS if valid, - * XTHAL_OUT_OF_ENTRIES - * XTHAL_MAP_NOT_ALIGNED, - * XTHAL_BAD_ACCESS_RIGHTS, - * XTHAL_OUT_OF_ORDER_MAP, or - * XTHAL_UNSUPPORTED if config doesn't have an MPU. - */ -int xthal_check_map(const xthal_MPU_entry* fg, unsigned int n) -{ -#if XCHAL_HAVE_MPU - return check_map(fg, XCHAL_MPU_ENTRIES, Xthal_mpu_bgmap); -#else - return XTHAL_UNSUPPORTED; -#endif -} -#endif - -#if defined(__SPLIT__mpu_basic) -/* - * Returns the MPU entry that maps 'vaddr'. If 'infgmap' is non-NULL then it is - * set to 1 if 'vaddr' is mapped by the foreground map, or 0 if 'vaddr' - * is mapped by the background map. - */ -extern xthal_MPU_entry xthal_get_entry_for_address(void* paddr, int* infgmap) - { -#if XCHAL_HAVE_MPU - xthal_MPU_entry e; - unsigned int p; - __asm__ __volatile__("PPTLB %0, %1\n\t" : "=a" (p) : "a" (paddr)); - if ((p & 0x80000000)) - { - if (infgmap) - *infgmap = 1; - e.at = (p & 0x1fffff); - __asm__ __volatile__("RPTLB0 %0, %1\n\t" : "=a" (e.as) : "a" (p & 0x1f)); - return e; - } - else - { - int i; - if (infgmap) - *infgmap = 0; - for (i = XCHAL_MPU_BACKGROUND_ENTRIES - 1; i > 0; i--) - { - if (XTHAL_MPU_ENTRY_GET_VSTARTADDR(Xthal_mpu_bgmap[i]) <= (unsigned) paddr) - { - return Xthal_mpu_bgmap[i]; - } - } // in background map - return Xthal_mpu_bgmap[0]; - } -#else - xthal_MPU_entry e; - return e; -#endif - } -#endif -/* - * This function is intended as an MPU specific version of - * xthal_set_region_attributes(). xthal_set_region_attributes() calls - * this function for MPU configurations. - * - * This function sets the attributes for the region [vaddr, vaddr+size) - * in the MPU. - * - * Depending on the state of the MPU this function will require from - * 0 to 3 unused MPU entries. - * - * This function typically will move, add, and subtract entries from - * the MPU map during execution, so that the resulting map may - * be quite different than when the function was called. - * - * This function does make the following guarantees: - * 1) The MPU access map remains in a valid state at all times - * during its execution. - * 2) At all points during (and after) completion the memoryType - * and accessRights remain the same for all addresses - * that are not in the range [vaddr, vaddr+size). - * 3) If XTHAL_SUCCESS is returned, then the range - * [vaddr, vaddr+size) will have the accessRights and memoryType - * specified. - * - * The accessRights parameter should be either a 4-bit value corresponding - * to an MPU access mode (as defined by the XTHAL_AR_.. constants), or - * XTHAL_MPU_USE_EXISTING_ACCESS_RIGHTS. - * - * The memoryType parameter should be either a bit-wise or-ing of XTHAL_MEM_.. - * constants that represent a valid MPU memoryType, a 9-bit MPU memoryType - * value, or XTHAL_MPU_USE_EXISTING_MEMORY_TYPE. - * - * In addition to the error codes that xthal_set_region_attribute() - * returns, this function can also return: XTHAL_BAD_ACCESS_RIGHTS - * (if the access rights bits map to an unsupported combination), or - * XTHAL_OUT_OF_ENTRIES (if there are not enough unused MPU entries). - * - * If this function is called with an invalid MPU map, then this function - * will return one of the codes that is returned by xthal_check_map(). - * - * The flag, XTHAL_CAFLAG_EXPAND, is not supported. - * - */ -#if defined(__SPLIT__mpu_attributes) -int xthal_mpu_set_region_attribute(void* vaddr, unsigned size, int accessRights, int memoryType, unsigned flags) -{ -#if XCHAL_HAVE_MPU - unsigned int first; - unsigned int last; - int rv; - - if (flags & XTHAL_CAFLAG_EXPAND) - return XTHAL_UNSUPPORTED; - if (size == 0) - return XTHAL_ZERO_SIZED_REGION; - first = (unsigned) vaddr; - last = first + size; - if (last != 0xFFFFFFFF) - last--; - if (first >= last) - return XTHAL_INVALID_ADDRESS_RANGE; // Wraps around - - if (accessRights & XTHAL_MPU_USE_EXISTING_ACCESS_RIGHTS) - { - accessRights = XTHAL_MPU_ENTRY_GET_ACCESS(xthal_get_entry_for_address(vaddr, 0)); - } - else - { - accessRights = encode_access_rights(accessRights); - if (accessRights < 0) - return XTHAL_BAD_ACCESS_RIGHTS; - } - if (memoryType & XTHAL_MPU_USE_EXISTING_MEMORY_TYPE) - { - memoryType = XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(xthal_get_entry_for_address(vaddr, 0)); - } - else - { - if (memoryType & 0xffffe000) // Tests if any of the XTHAL MEM flags are present - memoryType = xthal_encode_memory_type(memoryType); - else - if (memoryType & 0xfffffe00) // Tests if any of bits from 9 to 13 are set indicating - // that the memoryType was improperly shifted - // we flag this as an error - return XTHAL_BAD_MEMORY_TYPE; - if (memoryType < 0) - return XTHAL_BAD_MEMORY_TYPE; - } - if (flags & XTHAL_CAFLAG_EXACT) - if (!mpu_aligned(first) || !mpu_aligned(last + 1)) - return XTHAL_INEXACT; - - first = mpu_align(first, (flags & XTHAL_CAFLAG_NO_PARTIAL)); - if (last != 0xffffffff) - { - last = mpu_align(last + 1, !(flags & XTHAL_CAFLAG_NO_PARTIAL)); - if (first >= last) - return ((flags & XTHAL_CAFLAG_NO_PARTIAL) ? XTHAL_ZERO_SIZED_REGION : 0); - } - rv = safe_add_region(first, last, accessRights, memoryType, !(flags & XTHAL_CAFLAG_NO_AUTO_WB), - !(flags & XTHAL_CAFLAG_NO_AUTO_INV)); - isync(); - return rv; -#else - return XTHAL_UNSUPPORTED; -#endif -} -#endif - - -#if defined(__SPLIT__mpu_cachedis) - -inline static unsigned int max2(unsigned int a, unsigned int b) - { - if (a>b) - return a; - else - return b; - } - -inline static unsigned int mask_cachedis(unsigned int current, int first_region, - int last_region) - { - unsigned int x; - x = ((1 << (last_region - first_region + 1)) - 1) << first_region; - current &= ~x; - return current; - } - -/* - * xthal_calc_cacheadrdis() computes the value that should be written - * to the CACHEADRDIS register. The return value has bits 0-7 set according as: - * bit n: is zero if any part of the region [512MB * n, 512MB* (n-1)) is cacheable. - * is one if NO part of the region [512MB * n, 512MB* (n-1)) is cacheable. - * - * This function looks at both the loops through both the foreground and background maps - * to find cacheable area. Once one cacheable area is found in a 512MB region, then we - * skip to the next 512MB region. - */ -unsigned int xthal_calc_cacheadrdis(const xthal_MPU_entry* fg, unsigned int num_entries) - { -#if XCHAL_HAVE_MPU - unsigned int cachedis = 0xff; - int fg_index = num_entries - 1; - int bg_index = XCHAL_MPU_BACKGROUND_ENTRIES - 1; - int working_region = 7; - int ending_region; - unsigned int vaddr = 0xffffffff; - while (bg_index >= 0 || fg_index >= 0) - { - if ((fg_index >= 0 && XTHAL_MPU_ENTRY_GET_VALID(fg[fg_index]))) - { - vaddr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[fg_index]); - ending_region = vaddr >> 29; - if (ending_region <= working_region) - { - unsigned int mt = XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(fg[fg_index]); - if (is_cacheable(mt)) - { - cachedis = mask_cachedis(cachedis, ending_region, - working_region); - /* Optimize since we have found one cacheable entry in the region ... no need to look for more */ - if (ending_region == 0) - return cachedis; - else - working_region = ending_region - 1; - } - else - if (vaddr & 0x1fffffff) // If vaddr is on a 512MB region we want to move to the next region - working_region = ending_region; - else - working_region = ending_region - 1; - } - } - else if ((bg_index >= 0) - && ((fg_index <= 0) - || XTHAL_MPU_ENTRY_GET_VALID(fg[fg_index-1]))&& vaddr) - { - unsigned int caddr; - unsigned int low_addr = ( - (fg_index >= 0) ? - (XTHAL_MPU_ENTRY_GET_VSTARTADDR(fg[fg_index])) : - 0); - /* First skip any background entries that start after the address of interest */ - while ((caddr = XTHAL_MPU_ENTRY_GET_VSTARTADDR(Xthal_mpu_bgmap[bg_index])) >= vaddr) - bg_index--; - do - { - caddr = max2(XTHAL_MPU_ENTRY_GET_VSTARTADDR(Xthal_mpu_bgmap[bg_index]), - low_addr); - ending_region = caddr >> 29; - if (ending_region <= working_region) - { - unsigned int mt = XTHAL_MPU_ENTRY_GET_MEMORY_TYPE( - Xthal_mpu_bgmap[bg_index]); - if (is_cacheable(mt)) - { - cachedis = mask_cachedis(cachedis, ending_region, - working_region); - /* Optimize since we have found one cacheable entry in the region ... - * no need to look for more */ - if (ending_region == 0) - return cachedis; // we are done - else - working_region = ending_region - 1; - } - else - if (caddr & 0x1fffffff) - working_region = ending_region; - else - working_region = ending_region - 1; - } - bg_index--; - }while (caddr > low_addr); - vaddr = caddr; - } - fg_index--; - if (!vaddr) - break; - } - return cachedis; -#else - return 0; -#endif - } -#endif - -#if defined(__SPLIT__mpu_basic) -void (*_xthal_assert_handler)(); -/* Undocumented internal testing function */ -extern void _xthal_set_assert_handler(void (*handler)()) -{ -#if XCHAL_HAVE_MPU - _xthal_assert_handler = handler; -#endif -} -#endif diff --git a/src/arch/xtensa/hal/mpu_asm.S b/src/arch/xtensa/hal/mpu_asm.S deleted file mode 100644 index a2a544bd354d..000000000000 --- a/src/arch/xtensa/hal/mpu_asm.S +++ /dev/null @@ -1,78 +0,0 @@ -// -// mpu_asm.S - Assembler routine(s) for the MPU -// -// $Id$ - -// Copyright (c) 2015 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/mpuasm.h> - -#if defined(__SPLIT__write_map_raw) ||\ - defined(__SPLIT__write_map_raw_nw) - -/* - void xthal_write_map_raw( const struct xthal_MPU_entry* map, unsigned n); - - Updates the MPU with the MPU entries provided: - map pointer to array of MPU entries - n number of entries in array (0 <= n <= XCHAL_MPU_ENTRIES) - - The entries provided must have monotonically increasing addresses. - This function otherwise orders its updates to ensure the MPU always has - all its entries in monotonically increasing sequence. - - on entry - a2 => vector of MPU entries to write - a3 => number of entries to write - a4-a7 => destroyed -*/ - -DECLFUNC (xthal_write_map_raw) - abi_entry - mpu_write_map a2, a3, a4, a5, a6, a7 - abi_return - endfunc - -#endif - -/* - void xthal_read_map_raw(struct xthal_MPU_entry* map); - - Reads the current map from the MPU and puts it the vector - pointed to by map. - - a2 => vector of MPU entries where the current MPU state is copied - a3-a4 => destroyed -*/ - -#if defined(__SPLIT__read_map_raw) ||\ - defined(__SPLIT__read_map_raw_nw) - -DECLFUNC (xthal_read_map_raw) - abi_entry - mpu_read_map a2, a3, a4 - abi_return - endfunc - -#endif - diff --git a/src/arch/xtensa/hal/set_region_translate.c b/src/arch/xtensa/hal/set_region_translate.c deleted file mode 100644 index b1b53ed4ab21..000000000000 --- a/src/arch/xtensa/hal/set_region_translate.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright (c) 2004-2014 Tensilica 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 <xtensa/config/core.h> - -#if XCHAL_HAVE_XEA2 && (!XCHAL_HAVE_MPU) -/* - * C-stubs to issue the tlb related instructions (with dsync and isync's if needed). - * - */ -static inline void write_dtlb_entry(unsigned vpn_way, unsigned ppn_ca) { - __asm__ __volatile__("wdtlb %1, %0; dsync\n\t" - : : "r" (vpn_way), "r" (ppn_ca) ); -} - -static inline void write_itlb_entry(unsigned vpn_way, unsigned ppn_ca) { - __asm__ __volatile__("witlb %1, %0; isync\n\t" - : : "r" (vpn_way), "r" (ppn_ca) ); -} - -static inline unsigned read_dtlb1_entry(unsigned addr) { - unsigned long tmp; - __asm__ __volatile__("rdtlb1 %0, %1\n\t" - : "=a" (tmp) - : "a" (addr)); - return tmp; -} - -static inline unsigned read_itlb1_entry(unsigned addr) { - unsigned long tmp; - __asm__ __volatile__("ritlb1 %0, %1\n\t" - : "=a" (tmp) - : "a" (addr)); - return tmp; -} - -static inline unsigned probe_dtlb(unsigned addr) { - unsigned long tmp; - __asm__ __volatile__("pdtlb %0, %1\n\t" - : "=a" (tmp) - : "a" (addr)); - return tmp; -} - -static inline unsigned probe_itlb(unsigned addr) { - unsigned long tmp; - __asm__ __volatile__("pitlb %0, %1\n\t" - : "=a" (tmp) - : "a" (addr)); - return tmp; -} - -static inline void invalidate_dtlb_entry(unsigned addr) { - __asm__ __volatile__("idtlb %0; dsync \n\t" - : : "a" (addr)); -} - -static inline void invalidate_itlb_entry(unsigned addr) { - __asm__ __volatile__("iitlb %0 ; isync\n\t" - : : "a" (addr)); -} - -static inline unsigned read_dtlbcfg() { - unsigned long tmp; - __asm__ __volatile__("rsr.dtlbcfg %0\n\t" - : "=a" (tmp)); - return tmp; -} - -static inline unsigned read_itlbcfg() { - unsigned long tmp; - __asm__ __volatile__("rsr.itlbcfg %0\n\t" - : "=a" (tmp)); - return tmp; -} - -#endif - -/* - * xthal_set_region_translation_raw is a quick and simple function - * to set both physical address <paddr> and cache attribute <cattr> for - * a 512MB region at <vaddr>. - * - * Parameters: - * void* vaddr 512MB aligned pointer representing the start of virtual address region - * void* paddr 512MB aligned pointer representing the start of physical address region - * unsigned cattr 4 bit value encoding the caching properties and rights (MMU only). - * - * returns 0 (XCHAL_SUCCESS) if successful - * returns non zero (XCHAL_UNSUPPORTED) on failure - * - * This function has the following limitations: - * - * 1) Requires either the Region Translation Option or a v3 MMU running in the default mode (with spanning way) - * 2) It does no error checking. - * 3) Deals with one 512MB region (vaddr and paddr are required to be 512MB aligned although that is not explicitly checked) - * 4) It requires the caller to do any cache flushing that is needed - * 5) Doesn't support mnemonically setting the 'rights' (rwx, rw, ... ) bit on the MMU - * 6) It is illegal to change the mapping of the region containing the current PC (not checked) - * - */ -int xthal_set_region_translation_raw(void *vaddr, void *paddr, unsigned cattr) { -#if XCHAL_HAVE_MPU - return XTHAL_UNSUPPORTED; -#else -#if XCHAL_HAVE_XEA2 -#if XCHAL_HAVE_XLT_CACHEATTR || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) -# if XCHAL_HAVE_XLT_CACHEATTR - unsigned vpn_way = (unsigned)vaddr; -# else - unsigned vpn_way = ((unsigned) vaddr & 0xFFFFFFF0) + XCHAL_SPANNING_WAY; -# endif - unsigned ppn_ca = ((unsigned) paddr & 0xFFFFFFF0) + (cattr & 0xF); - write_dtlb_entry(vpn_way, ppn_ca); - write_itlb_entry(vpn_way, ppn_ca); - return XTHAL_SUCCESS; -#else - return XTHAL_UNSUPPORTED; -#endif -#else - return XTHAL_UNSUPPORTED; -#endif -#endif -} - -/* - * xthal_v2p() takes a virtual address as input, and if that virtual address is mapped to a physical address - * by the MMU, it returns the: - * a) corresponding physical address - * b) the tlb way that is used to translate the address - * c) cache attribute for translation - * - * Parameters: - * void* vaddr A pointer representing the virtual address (there are no alignment requirements for this address) - * void** paddr This value can be 0, or can point to a pointer variable which will be updated to contain the physical address - * unsigned* way This value can be 0, or can point to an unsigned variable which will be updated to contain the TLB way. - * unsigned* cattr This value can be 0, or can point to an unsigned variable which will be updated to contain the cache attr - * For MPU configurations bits 0..3 hold the access rights and bits 4..8 hold the encoded memory type - * - * Returns 0 (XCHAL_SUCCESS) if successful - * XTHAL_NO_MAPPING if there is no current mapping for the virtual address - * XCHAL_UNSUPPORTED if unsupported - * - * Limitations: - * Assumes that architecture variable DVARWAY56 is "Variable" - * Uses the D-TLBS for the translation ... assumption is that ITLB's have same mappings - */ -int xthal_v2p(void* vaddr, void** paddr, unsigned *way, unsigned* cattr) { -#if XCHAL_HAVE_XEA2 -#if XCHAL_HAVE_MPU - if (paddr) - *paddr = vaddr; - if (way) - *way = 0; - if (cattr) - { - struct xthal_MPU_entry x = xthal_get_entry_for_address(vaddr, 0); - *cattr = XTHAL_MPU_ENTRY_GET_ACCESS(x) | XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(x) << XTHAL_AR_WIDTH; - } - return XTHAL_SUCCESS; -#else - unsigned long probe = probe_dtlb((unsigned) vaddr); -#if !XCHAL_HAVE_PTP_MMU - if (!(0x1 & probe)) - return XTHAL_NO_MAPPING; - if (way) - *way = 1; - if (paddr || cattr) { - unsigned long temp; - temp = read_dtlb1_entry(probe); - unsigned ppn = 0xe0000000 & temp; - unsigned att = 0xf & temp; - if (paddr) - *paddr = ((void*) (ppn + (((unsigned) vaddr) & 0x1fffffff))); - if (cattr) - *cattr = att; - } -#else - { - unsigned iway; - if (!(0x10 & probe)) - return XTHAL_NO_MAPPING; - iway = 0xf & probe; - if (way) - *way = iway; - if (paddr || cattr) { - unsigned temp; - unsigned ppn; - unsigned ppn1; - unsigned dtlbcfg = read_dtlbcfg(); - temp = read_dtlb1_entry(probe); - unsigned att = 0xf & temp; - if (cattr) - *cattr = att; - if (paddr) - switch (iway) // followin code derived from fig 4-40 from ISA MMU Option Data (at) Format for RxTLB1 - { /* 4k pages */ - case 0: - case 1: - case 2: - case 3: - case 7: - case 8: - case 9: - ppn = 0xfffff000; // 4k pages - break; - case 4: { - switch ((dtlbcfg & (0x3 << 16)) >> 16) // bits 16 & 17 - { - case 0: // 1MB pages - ppn = 0xfff00000; - break; - case 1: // 4MB pages - ppn = 0xffc00000; - break; - case 2: // 16MB pages - ppn = 0xff000000; - break; - case 3: // 64MB pages - ppn = 0xfc000000; - break; - default: - return XTHAL_UNSUPPORTED; - } - } - break; - case 5: - if ((dtlbcfg & (1 << 20))) - ppn = 0xf8000000; // 128MB pages - else - ppn = 0xf0000000; // 256MB pages - break; - case 6: - if ((dtlbcfg & (1 << 24))) - ppn = 0xe0000000; // 512MB pages - else - ppn = 0xf0000000; // 256MB pages - break; - default: - return XTHAL_UNSUPPORTED; - break; - } - ppn1 = ppn & temp; - *paddr = ((void*) (ppn1 + (((unsigned) vaddr) & (~ppn)))); - } - } -#endif - return XTHAL_SUCCESS; -#endif -#else - return XTHAL_UNSUPPORTED; -#endif -} - -/* these constants borrowed from xthal_set_region_attribute */ -# if XCHAL_HAVE_PTP_MMU -# define CA_BYPASS XCHAL_CA_BYPASS -# define CA_WRITETHRU XCHAL_CA_WRITETHRU -# define CA_WRITEBACK XCHAL_CA_WRITEBACK -# define CA_WRITEBACK_NOALLOC XCHAL_CA_WRITEBACK_NOALLOC -# define CA_ILLEGAL XCHAL_CA_ILLEGAL -# else -/* Hardcode these, because they get remapped when caches or writeback not configured: */ -# define CA_BYPASS 2 -# define CA_WRITETHRU 1 -# define CA_WRITEBACK 4 -# define CA_WRITEBACK_NOALLOC 5 -# define CA_ILLEGAL 15 -# endif - -/* internal function that returns 1 if the supplied attr indicates the - * cache is in writeback mode. - */ -static inline int is_writeback(unsigned attr) { -#if XCHAL_HAVE_XLT_CACHEATTR - return attr == CA_WRITEBACK || attr == CA_WRITEBACK_NOALLOC; -#endif -#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY - return (attr | 0x3) == CA_WRITEBACK; -#endif - return -1; /* unsupported */ -} - -/* - * xthal_set_region_translation() - * - * Establishes a new mapping (with the supplied cache attributes) - * between a virtual address region, and a physical address region. - * - * This function is only supported with following processor configurations: - * a) Region Translation - * b) v3 MMU with a spanning way running in the default mode - * - * If the specified memory range exactly covers a series - * of consecutive 512 MB regions, the address mapping and cache - * attributes of these regions are updated. - * - * If this is not the case, e.g. if either or both the - * start and end of the range only partially cover a 512 MB - * region, one of three results are possible: - * - * 1. By default, the cache attribute of all regions - * covered, even just partially, is changed to - * the requested attribute. - * - * 2. If the XTHAL_CAFLAG_EXACT flag is specified, - * a non-zero error code is returned. - * - * 3. If the XTHAL_CAFLAG_NO_PARTIAL flag is specified - * (but not the EXACT flag), only regions fully - * covered by the specified range are updated with - * the requested attribute. - * - * CACHE HANDLING - * - * This function automatically writes back dirty data before remapping a - * virtual address region. - * - * This writeback is done safely, ie. by first switching to writethrough - * mode, and then invoking xthal_dcache_all_writeback(). Such a sequence is - * necessary to ensure there is no longer any dirty data in the memory region by the time - * this function returns, even in the presence of interrupts, speculation, etc. - * This automatic write-back can be disabled using the XTHAL_CAFLAG_NO_AUTO_WB flag. - * - * This function also invalidates the caches after remapping a region because the - * cache could contain (now invalid) data from the previous mapping. - * This automatic invalidate can be disabled using the XTHAL_CAFLAG_NO_AUTO_INV flag. - * - * Parameters: - * vaddr starting virtual address of region of memory - * - * paddr starting physical address for the mapping (this should be 512MB aligned to vaddr such that ((vaddr ^ paddr) & 0x10000000 == 0) - * - * size number of bytes in region of memory - * (see above, SPECIFYING THE MEMORY REGION) - * - * cattr cache attribute (encoded); - * typically taken from compile-time HAL constants - * XCHAL_CA_{BYPASS, WRITETHRU, WRITEBACK[_NOALLOC], ILLEGAL} - * (defined in <xtensa/config/core.h>); - * in XEA1, this corresponds to the value of a nibble - * in the CACHEATTR register; - * in XEA2, this corresponds to the value of the - * cache attribute (CA) field of each TLB entry - * - * flags bitwise combination of flags XTHAL_CAFLAG_* - * - * XTHAL_CAFLAG_EXACT - If this flag is present, - * the mapping will only be done if the specified - * region exactly matches on or more 512MB pages otherwise - * XCHAL_INEXACT is returned (and no mapping is done). - * - * XTHAL_CAFLAG_NO_PARTIAL - If this flag is specified, then - * only pages that are completely covered by the specified region - * are affected. If this flag is specified, and no pages are completely - * covered by the region, then no pages are affected and XCHAL_NO_REGIONS_COVERED - * is returned. - * - * - * - * Returns: - * XCHAL_SUCCESS - successful, or size is zero - * - * XCHAL_NO_REGIONS_COVERED - XTHAL_CAFLAG_NO_PARTIAL flag specified and address range - * is valid with a non-zero size, however no 512 MB region (or page) - * is completely covered by the range - * - * XCHAL_INEXACT XTHAL_CAFLAG_EXACT flag specified, and address range does - * not exactly specify a 512 MB region (or page) - * - * XCHAL_INVALID_ADDRESS invalid address range specified (wraps around the end of memory) - * - * XCHAL_ADDRESS_MISALIGNED virtual and physical addresses are not aligned (512MB) - * - * - * XCHAL_UNSUPPORTED_ON_THIS_ARCH function not supported in this processor configuration - */ -int xthal_set_region_translation(void* vaddr, void* paddr, unsigned size, - unsigned cattr, unsigned flags) { -#if XCHAL_HAVE_XEA2 & !XCHAL_HAVE_MPU -#if XCHAL_HAVE_XLT_CACHEATTR || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - const unsigned CA_MASK = 0xF; - const unsigned addr_mask = 0x1fffffff; - const unsigned addr_shift = 29; - unsigned vaddr_a = (unsigned) vaddr; - unsigned paddr_a = (unsigned) paddr; - unsigned end_vaddr; - unsigned end_paddr; - unsigned start_va_reg; - unsigned end_va_reg; - unsigned start_pa_reg; - unsigned icache_attr = 0; - int rv; - int i; - if (size == 0) - return XTHAL_SUCCESS; - if ((vaddr_a & addr_mask) ^ (paddr_a & addr_mask)) - return XTHAL_ADDRESS_MISALIGNED; - icache_attr = cattr & CA_MASK; -#if (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - // if using the mmu in spanning way mode then 'and in' the R, RX, RW, RWX bits - if ((cattr & 0x40000000) && (icache_attr < 12)) - icache_attr = icache_attr & ((cattr & 0xF0) >> 4); -#endif - end_vaddr = vaddr_a + size - 1; - end_paddr = paddr_a + size - 1; - - if ((end_vaddr < vaddr_a) || (end_paddr < paddr_a)) - return XTHAL_INVALID_ADDRESS; - start_va_reg = vaddr_a >> addr_shift; - end_va_reg = end_vaddr >> addr_shift; - start_pa_reg = paddr_a >> addr_shift; - if ((flags & XTHAL_CAFLAG_EXACT) - && ((size & addr_mask) || (vaddr_a & addr_mask) - || (paddr_a & addr_mask))) - return XTHAL_INEXACT; - if (flags & XTHAL_CAFLAG_NO_PARTIAL) { - if (vaddr_a & addr_mask) { - start_va_reg++; - start_pa_reg++; - } - if ((end_vaddr & addr_mask) != addr_mask) - end_va_reg--; - } - if (end_va_reg < start_va_reg) - return XTHAL_NO_REGIONS_COVERED; - /* - * Now we need to take care of any uncommitted cache writes in the affected regions - * 1) first determine if any regions are in write back mode - * 2) change those pages to write through - * 3) force the writeback of d-cache by calling xthal_dcach_all_writeback() - */ -#if ((XCHAL_DCACHE_SIZE >0) && XCHAL_DCACHE_IS_WRITEBACK) - if (!(flags & XTHAL_CAFLAG_NO_AUTO_WB)) { - unsigned old_cache_attr = xthal_get_cacheattr(); - unsigned cachewrtr = old_cache_attr; - unsigned need_safe_writeback = 0; - for (i = start_va_reg; i <= end_va_reg; i++) { - unsigned sh = i << 2; - unsigned old_attr = (old_cache_attr >> sh) & CA_MASK; - if (is_writeback(old_attr)) { - need_safe_writeback = 1; - cachewrtr = (cachewrtr & ~(CA_MASK << sh)) - | (CA_WRITETHRU << sh); - } - } - - if (need_safe_writeback) { - xthal_set_cacheattr(cachewrtr); /* set to writethru first, to safely writeback any dirty data */ - xthal_dcache_all_writeback(); /* much quicker than scanning entire 512MB region(s) */ - } - } -#endif - /* Now we set the affected region translations */ - for (i = start_va_reg; i <= end_va_reg; i++) { - if ((rv = xthal_set_region_translation_raw( - (void*) ((start_va_reg++) << addr_shift), - (void*) ((start_pa_reg++) << addr_shift), icache_attr))) - return rv; - } - - /* - * Now we need to invalidate the cache in the affected regions. For now invalidate entire cache, - * but investigate if there are faster alternatives on some architectures. - */ - if (!(flags & XTHAL_CAFLAG_NO_AUTO_INV)) { -# if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_all_writeback_inv(); /* some areas in memory (outside the intended region) may have uncommitted - data so we need the writeback_inv(). */ -#endif -#if XCHAL_ICACHE_SIZE >0 - xthal_icache_all_invalidate(); -#endif - } - return XTHAL_SUCCESS; -#else - return XTHAL_UNSUPPORTED; -#endif -#else - return XTHAL_UNSUPPORTED; -#endif -} - -/* xthal_invalidate_region() - * invalidates the tlb entry for the specified region. - * - * This function is only supported on processor configurations - * with a v3 MMU with a spanning way. - * - * Parameter - * vaddr - virtual address of region to invalidate (512MB aligned) - * - * returns: - * XCHAL_SUCCESS - Success - * XCHAL_UNSUPPORTED_ON_THIS_ARCH - Unsupported - * - */ -int xthal_invalidate_region(void* vaddr) { -#if XCHAL_HAVE_XEA2 & !XCHAL_HAVE_MPU -#if (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - unsigned addr = (unsigned) vaddr; - if (addr & 0x1fffffff) - return XTHAL_INVALID_ADDRESS; - addr += XCHAL_SPANNING_WAY; - invalidate_dtlb_entry(addr); - invalidate_itlb_entry(addr); - return XTHAL_SUCCESS; -#else - return XTHAL_UNSUPPORTED; -#endif -#else - return XTHAL_UNSUPPORTED; -#endif -} - diff --git a/src/arch/xtensa/hal/state.c b/src/arch/xtensa/hal/state.c deleted file mode 100644 index 316ddb4e8298..000000000000 --- a/src/arch/xtensa/hal/state.c +++ /dev/null @@ -1,321 +0,0 @@ -// -// processor_state.c - processor state management routines -// - -// Copyright (c) 2005-2010 Tensilica 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 <xtensa/hal.h> -#include <xtensa/config/core.h> - - -//---------------------------------------------------------------------- - -#if defined(__SPLIT__extra_size) -// space for "extra" (user special registers and non-coprocessor TIE) state: -const unsigned int Xthal_extra_size = XCHAL_NCP_SA_SIZE; - -#elif defined(__SPLIT__extra_align) -const unsigned int Xthal_extra_align = XCHAL_NCP_SA_ALIGN; - -#elif defined(__SPLIT__cpregs_size) -// space for state of TIE coprocessors: -const unsigned int Xthal_cpregs_size[8] = - { - XCHAL_CP0_SA_SIZE, - XCHAL_CP1_SA_SIZE, - XCHAL_CP2_SA_SIZE, - XCHAL_CP3_SA_SIZE, - XCHAL_CP4_SA_SIZE, - XCHAL_CP5_SA_SIZE, - XCHAL_CP6_SA_SIZE, - XCHAL_CP7_SA_SIZE - }; - -#elif defined(__SPLIT__cpregs_align) -const unsigned int Xthal_cpregs_align[8] = - { - XCHAL_CP0_SA_ALIGN, - XCHAL_CP1_SA_ALIGN, - XCHAL_CP2_SA_ALIGN, - XCHAL_CP3_SA_ALIGN, - XCHAL_CP4_SA_ALIGN, - XCHAL_CP5_SA_ALIGN, - XCHAL_CP6_SA_ALIGN, - XCHAL_CP7_SA_ALIGN - }; - -#elif defined(__SPLIT__cp_names) -const char * const Xthal_cp_names[8] = - { - XCHAL_CP0_NAME, - XCHAL_CP1_NAME, - XCHAL_CP2_NAME, - XCHAL_CP3_NAME, - XCHAL_CP4_NAME, - XCHAL_CP5_NAME, - XCHAL_CP6_NAME, - XCHAL_CP7_NAME - }; - -#elif defined(__SPLIT__all_extra_size) -// total save area size (extra + all coprocessors + min 16-byte alignment everywhere) -const unsigned int Xthal_all_extra_size = XCHAL_TOTAL_SA_SIZE; - -#elif defined(__SPLIT__all_extra_align) -// maximum required alignment for the total save area (this might be useful): -const unsigned int Xthal_all_extra_align = XCHAL_TOTAL_SA_ALIGN; - -#elif defined(__SPLIT__num_coprocessors) -// number of coprocessors starting contiguously from zero -// (same as Xthal_cp_max, but included for Tornado2): -const unsigned int Xthal_num_coprocessors = XCHAL_CP_MAX; - -#elif defined(__SPLIT__cp_num) -// actual number of coprocessors: -const unsigned char Xthal_cp_num = XCHAL_CP_NUM; - -#elif defined(__SPLIT__cp_max) -// index of highest numbered coprocessor, plus one: -const unsigned char Xthal_cp_max = XCHAL_CP_MAX; - -// index of highest allowed coprocessor number, per cfg, plus one: -//const unsigned char Xthal_cp_maxcfg = XCHAL_CP_MAXCFG; - -#elif defined(__SPLIT__cp_mask) -// bitmask of which coprocessors are present: -const unsigned int Xthal_cp_mask = XCHAL_CP_MASK; - -#elif defined(__SPLIT__cp_id_mappings) -// Coprocessor ID from its name - -# ifdef XCHAL_CP0_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP0_IDENT) = 0; -# endif -# ifdef XCHAL_CP1_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP1_IDENT) = 1; -# endif -# ifdef XCHAL_CP2_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP2_IDENT) = 2; -# endif -# ifdef XCHAL_CP3_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP3_IDENT) = 3; -# endif -# ifdef XCHAL_CP4_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP4_IDENT) = 4; -# endif -# ifdef XCHAL_CP5_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP5_IDENT) = 5; -# endif -# ifdef XCHAL_CP6_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP6_IDENT) = 6; -# endif -# ifdef XCHAL_CP7_IDENT -const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP7_IDENT) = 7; -# endif - -#elif defined(__SPLIT__cp_mask_mappings) -// Coprocessor "mask" (1 << ID) from its name - -# ifdef XCHAL_CP0_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP0_IDENT) = (1 << 0); -# endif -# ifdef XCHAL_CP1_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP1_IDENT) = (1 << 1); -# endif -# ifdef XCHAL_CP2_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP2_IDENT) = (1 << 2); -# endif -# ifdef XCHAL_CP3_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP3_IDENT) = (1 << 3); -# endif -# ifdef XCHAL_CP4_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP4_IDENT) = (1 << 4); -# endif -# ifdef XCHAL_CP5_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP5_IDENT) = (1 << 5); -# endif -# ifdef XCHAL_CP6_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP6_IDENT) = (1 << 6); -# endif -# ifdef XCHAL_CP7_IDENT -const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP7_IDENT) = (1 << 7); -# endif - -//---------------------------------------------------------------------- - -#elif defined(__SPLIT__init_mem_extra) -// CMS: I have made the assumptions that 0's are safe initial -// values. That may be wrong at some point. -// -// initialize the extra processor -void -xthal_init_mem_extra(void *address) -/* not clear that it is safe to call memcpy and also not clear - that performance is important. */ -{ - unsigned int *ptr; - unsigned int *end; - - ptr = (unsigned int *)address; - end = (unsigned int *)((int)address + XCHAL_NCP_SA_SIZE); - while( ptr < end ) - { - *ptr++ = 0; - } -} - -#elif defined(__SPLIT__init_mem_cp) -// initialize the TIE coprocessor -void -xthal_init_mem_cp(void *address, int cp) -{ - unsigned int *ptr; - unsigned int *end; - - if( cp <= 7 ) - { - end = (unsigned int *)((int)address + Xthal_cpregs_size[cp]); - ptr = (unsigned int *)address; - while( ptr < end ) - { - *ptr++ = 0; - } - } -} - -#endif /*splitting*/ - - -/* Nothing implemented below this point. */ -/************************************************************************/ - -// save all extra+cp processor state (NOT IMPLEMENTED) -/*void xthal_save_all_extra(void *base) -{ - xthal_save_extra(base); - ... here we need to iterate over configured coprocessor register files ... -// xthal_save_cpregs(base+XCHAL_NCP_SA_SIZE, 0); -}*/ - -// restore all extra+cp processor state (NOT IMPLEMENTED) -/*void xthal_restore_all_extra(void *base) -{ - xthal_restore_extra(base); - ... here we need to iterate over configured coprocessor register files ... -// xthal_restore_cpregs(base+XCHAL_NCP_SA_SIZE, 0); -}*/ - - -// initialize the extra processor (NOT IMPLEMENTED) -/*void xthal_init_extra() -{ -}*/ - -// initialize the TIE coprocessor (NOT IMPLEMENTED) -/*void xthal_init_cp(int cp) -{ -}*/ - - -#if 0 - -/* read extra state register (NOT IMPLEMENTED) */ -int xthal_read_extra(void *base, unsigned reg, unsigned *value) -{ - if (reg&0x1000) { - switch(reg) { -#if XCHAL_HAVE_MAC16 - case 16: - *value = ((unsigned *)base)[0]; - return reg; - case 17: - *value = ((unsigned *)base)[1]; - return reg; - case 32: - *value = ((unsigned *)base)[2]; - return reg; - case 33: - *value = ((unsigned *)base)[3]; - return reg; - case 34: - *value = ((unsigned *)base)[4]; - return reg; - case 35: - *value = ((unsigned *)base)[5]; - return reg; -#endif /* XCHAL_HAVE_MAC16 */ - } - } - return -1; -} - -/* write extra state register (NOT IMPLEMENTED) */ -int xthal_write_extra(void *base, unsigned reg, unsigned value) -{ - if (reg&0x1000) { - switch(reg) { -#if XCHAL_HAVE_MAC16 - case 16: - ((unsigned *)base)[0] = value; - return reg; - case 17: - ((unsigned *)base)[1] = value; - return reg; - case 32: - ((unsigned *)base)[2] = value; - return reg; - case 33: - ((unsigned *)base)[3] = value; - return reg; - case 34: - ((unsigned *)base)[4] = value; - return reg; - case 35: - ((unsigned *)base)[5] = value; - return reg; -#endif /* XCHAL_HAVE_MAC16 */ - } - } - return -1; -} - -#endif /*0*/ - - -/* read TIE coprocessor register (NOT IMPLEMENTED) */ -/*int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value) -{ - return -1; -}*/ - -/* write TIE coproessor register (NOT IMPLEMENTED) */ -/*int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value) -{ - return -1; -}*/ - -/* return coprocessor number based on register (NOT IMPLEMENTED) */ -/*int xthal_which_cp(unsigned reg) -{ - return -1; -}*/ - diff --git a/src/arch/xtensa/hal/state_asm.S b/src/arch/xtensa/hal/state_asm.S deleted file mode 100644 index 108986228584..000000000000 --- a/src/arch/xtensa/hal/state_asm.S +++ /dev/null @@ -1,433 +0,0 @@ -/* - * state_asm.S - assembly language processor management routines - */ - -/* - * Copyright (c) 2005-2010 Tensilica 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 <xtensa/coreasm.h> - - .text - -//---------------------------------------------------------------------- -// save the extra processor state. -//---------------------------------------------------------------------- - -#if defined(__SPLIT__save_extra) ||\ - defined(__SPLIT__save_extra_nw) - -// void xthal_save_extra(void *base) - -DECLFUNC(xthal_save_extra) - abi_entry - xchal_extra_store_funcbody - abi_return - endfunc - - -//---------------------------------------------------------------------- -// restore the extra processor state. -//---------------------------------------------------------------------- - -#elif defined(__SPLIT__restore_extra) ||\ - defined(__SPLIT__restore_extra_nw) - -// void xthal_restore_extra(void *base) - -DECLFUNC(xthal_restore_extra) - abi_entry - xchal_extra_load_funcbody - abi_return - endfunc - -//---------------------------------------------------------------------- -// save the TIE COPROCESSORS state -//---------------------------------------------------------------------- - -#elif defined(__SPLIT__save_cpregs) ||\ - defined(__SPLIT__save_cpregs_nw) - -// void xthal_save_cpregs(void *base, int) -DECLFUNC(xthal_save_cpregs) - abi_entry - xchal_cpi_store_funcbody - abi_return - endfunc -#elif defined(__SPLIT__save_cp0) ||\ - defined(__SPLIT__save_cp0_nw) -// void xthal_save_cp0(void *base) -DECLFUNC(xthal_save_cp0) - abi_entry - xchal_cp0_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp1) ||\ - defined(__SPLIT__save_cp1_nw) -// void xthal_save_cp1(void *base) -DECLFUNC(xthal_save_cp1) - abi_entry - xchal_cp1_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp2) ||\ - defined(__SPLIT__save_cp2_nw) -// void xthal_save_cp2(void *base) -DECLFUNC(xthal_save_cp2) - abi_entry - xchal_cp2_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp3) ||\ - defined(__SPLIT__save_cp3_nw) -// void xthal_save_cp3(void *base) -DECLFUNC(xthal_save_cp3) - abi_entry - xchal_cp3_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp4) ||\ - defined(__SPLIT__save_cp4_nw) -// void xthal_save_cp4(void *base) -DECLFUNC(xthal_save_cp4) - abi_entry - xchal_cp4_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp5) ||\ - defined(__SPLIT__save_cp5_nw) -// void xthal_save_cp5(void *base) -DECLFUNC(xthal_save_cp5) - abi_entry - xchal_cp5_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp6) || \ - defined(__SPLIT__save_cp6_nw) -// void xthal_save_cp6(void *base) -DECLFUNC(xthal_save_cp6) - abi_entry - xchal_cp6_store_a2 - abi_return - endfunc -#elif defined(__SPLIT__save_cp7) ||\ - defined(__SPLIT__save_cp7_nw) -// void xthal_save_cp7(void *base) -DECLFUNC(xthal_save_cp7) - abi_entry - xchal_cp7_store_a2 - abi_return - endfunc - -//---------------------------------------------------------------------- -// restore the TIE coprocessor state -//---------------------------------------------------------------------- - -#elif defined(__SPLIT__restore_cpregs) ||\ - defined(__SPLIT__restore_cpregs_nw) - -// void xthal_restore_cpregs(void *base, int) - -DECLFUNC(xthal_restore_cpregs) - abi_entry - xchal_cpi_load_funcbody - abi_return - endfunc -#elif defined(__SPLIT__restore_cp0) ||\ - defined(__SPLIT__restore_cp0_nw) -// void xthal_restore_cp0(void *base) -DECLFUNC(xthal_restore_cp0) - abi_entry - xchal_cp0_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp1) ||\ - defined(__SPLIT__restore_cp1_nw) -// void xthal_restore_cp1(void *base) -DECLFUNC(xthal_restore_cp1) - abi_entry - xchal_cp1_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp2) ||\ - defined(__SPLIT__restore_cp2_nw) -// void xthal_restore_cp2(void *base) -DECLFUNC(xthal_restore_cp2) - abi_entry - xchal_cp2_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp3) || \ - defined(__SPLIT__restore_cp3_nw) -// void xthal_restore_cp3(void *base) -DECLFUNC(xthal_restore_cp3) - abi_entry - xchal_cp3_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp4) || \ - defined(__SPLIT__restore_cp4_nw) -// void xthal_restore_cp4(void *base) -DECLFUNC(xthal_restore_cp4) - abi_entry - xchal_cp4_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp5) || \ - defined(__SPLIT__restore_cp5_nw) -// void xthal_restore_cp5(void *base) -DECLFUNC(xthal_restore_cp5) - abi_entry - xchal_cp5_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp6) || \ - defined(__SPLIT__restore_cp6_nw) -// void xthal_restore_cp6(void *base) -DECLFUNC(xthal_restore_cp6) - abi_entry - xchal_cp6_load_a2 - abi_return - endfunc -#elif defined(__SPLIT__restore_cp7) || \ - defined(__SPLIT__restore_cp7_nw) -// void xthal_restore_cp7(void *base) -DECLFUNC(xthal_restore_cp7) - abi_entry - xchal_cp7_load_a2 - abi_return - endfunc - -#elif defined(__SPLIT__cpregs_save_fn) - .section .rodata, "a" -_SYM(Xthal_cpregs_save_fn) -# ifdef __XTENSA_CALL0_ABI__ -_SYM(Xthal_cpregs_save_nw_fn) -# endif - .long xthal_save_cp0 - .long xthal_save_cp1 - .long xthal_save_cp2 - .long xthal_save_cp3 - .long xthal_save_cp4 - .long xthal_save_cp5 - .long xthal_save_cp6 - .long xthal_save_cp7 - endfunc - .text - -#elif defined(__SPLIT__cpregs_save_nw_fn) -# ifndef __XTENSA_CALL0_ABI__ - .section .rodata, "a" -_SYM(Xthal_cpregs_save_nw_fn) - .long xthal_save_cp0_nw - .long xthal_save_cp1_nw - .long xthal_save_cp2_nw - .long xthal_save_cp3_nw - .long xthal_save_cp4_nw - .long xthal_save_cp5_nw - .long xthal_save_cp6_nw - .long xthal_save_cp7_nw - endfunc - .text -# endif - -#elif defined(__SPLIT__cpregs_restore_fn) - .section .rodata, "a" -_SYM(Xthal_cpregs_restore_fn) -# ifdef __XTENSA_CALL0_ABI__ -_SYM(Xthal_cpregs_restore_nw_fn) -# endif - .long xthal_restore_cp0 - .long xthal_restore_cp1 - .long xthal_restore_cp2 - .long xthal_restore_cp3 - .long xthal_restore_cp4 - .long xthal_restore_cp5 - .long xthal_restore_cp6 - .long xthal_restore_cp7 - endfunc - .text - -#elif defined(__SPLIT__cpregs_restore_nw_fn) -# ifndef __XTENSA_CALL0_ABI__ - .section .rodata, "a" -_SYM(Xthal_cpregs_restore_nw_fn) - .long xthal_restore_cp0_nw - .long xthal_restore_cp1_nw - .long xthal_restore_cp2_nw - .long xthal_restore_cp3_nw - .long xthal_restore_cp4_nw - .long xthal_restore_cp5_nw - .long xthal_restore_cp6_nw - .long xthal_restore_cp7_nw - endfunc - .text -# endif - - -//---------------------------------------------------------------------- -// coprocessor enable/disable -//---------------------------------------------------------------------- - -#elif defined(__SPLIT__validate_cp) ||\ - defined(__SPLIT__validate_cp_nw) - -// validate the register file. -// void xthal_validate_cp(int) - -DECLFUNC(xthal_validate_cp) - abi_entry -#if XCHAL_HAVE_CP - rsr.cpenable a3 - movi a4, 1 - ssl a2 - sll a4, a4 - or a3, a3, a4 - wsr.cpenable a3 -#endif - abi_return - endfunc - -#elif defined(__SPLIT__invalidate_cp) || \ - defined(__SPLIT__invalidate_cp_nw) - -// invalidate the register file. -// void xthal_invalidate_cp(int) - -DECLFUNC(xthal_invalidate_cp) - abi_entry -#if XCHAL_HAVE_CP - rsr.cpenable a3 - movi a4, 1 - ssl a2 - sll a4, a4 - and a4, a3, a4 - xor a3, a3, a4 - wsr.cpenable a3 -#endif - abi_return - endfunc - - -//---------------------------------------------------------------------- -// Access the CPENABLE register -//---------------------------------------------------------------------- - -#elif defined(__SPLIT__get_cpenable) || \ - defined(__SPLIT__get_cpenable_nw) - -// unsigned xthal_get_cpenable(void); - -DECLFUNC(xthal_get_cpenable) - abi_entry -#if XCHAL_HAVE_CP - rsr.cpenable a2 -#else - movi a2, 0 // if no CPENABLE (no coprocessors), none is ever enabled -#endif - abi_return - endfunc - -#elif defined(__SPLIT__set_cpenable) ||\ - defined(__SPLIT__set_cpenable_nw) - -// void xthal_set_cpenable(unsigned); -// -// Note: to help asm code performance (eg. OS task switch), -// this routine returns the previous value of CPENABLE in a3 -// (not a2, because that could require an extra mov instruction). -// This return value is not shown in the prototype, because -// C code won't see it. -// [Perhaps this should go in an RTOS-specific Core HAL or BSP. TBD.] - -DECLFUNC(xthal_set_cpenable) - abi_entry -#if XCHAL_HAVE_CP - //rsr.cpenable a3 // return previous CPENABLE - movi a3, 0 // for now, always return 0 (VxWorks currently done that way) - - wsr.cpenable a2 -#else - movi a3, 0 // if no CPENABLE (no coprocessors), none is ever enabled -#endif - abi_return - endfunc -#endif - - -/* Nothing implemented below this point. */ -/************************************************************************/ - -#if 0 - -//---------------------------------------------------------------------- -// initialize the processor state -//---------------------------------------------------------------------- - -// void xthal_init_extra_nw() - .global xthal_init_extra_nw - .align 4 -xthal_init_extra_nw: - //addi sp, sp, 0 - ... NOT IMPLEMENTED ... - ret - -//---------------------------------------------------------------------- -// initialize the TIE coprocessor -//---------------------------------------------------------------------- - -// void xthal_init_cp_nw(int) - .global xthal_init_cp_nw - .align 4 -xthal_init_cp_nw: - //addi sp, sp, 0 - ... NOT IMPLEMENTED ... - ret - -//---------------------------------------------------------------------- -// -//---------------------------------------------------------------------- - -// initialize the extra processor -// void xthal_init_mem_extra_nw() - .global xthal_init_mem_extra_nw - .align 4 -xthal_init_mem_extra_nw: - //addi sp, sp, 0 - ... NOT IMPLEMENTED ... - ret - -//---------------------------------------------------------------------- -// -//---------------------------------------------------------------------- - -// initialize the TIE coprocessor -// void xthal_init_mem_cp_nw(int) - .global xthal_init_mem_cp_nw - .align 4 -xthal_init_mem_cp_nw: - //addi sp, sp, 0 - ... NOT IMPLEMENTED ... - ret - -#endif /*0*/ - diff --git a/src/arch/xtensa/hal/syscache_asm.S b/src/arch/xtensa/hal/syscache_asm.S deleted file mode 100644 index 0716ddca17ff..000000000000 --- a/src/arch/xtensa/hal/syscache_asm.S +++ /dev/null @@ -1,141 +0,0 @@ -// -// syscache_asm.S - system-dependent assembly language cache management routines -// -// These functions are now obsolete. They cannot be properly implemented -// in the HAL, because the required settings of CACHEATTR are entirely -// system- or board-dependent. The HAL is not board specific; it is merely -// processor-configuration specific. These cache enable and disable -// functions do a "best-guess" of what values may be appropriate. -// They should be avoided. (Instead, use xthal_set_[id]cacheattr() -// and provide specific CACHEATTR values for the board or system. -// See the LSP ref manual for info on how to obtain such a value as -// computed by xt-genldscripts for a specific LSP, e.g. by using the -// address of the _memmap_cacheattr_reset symbol.) -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/syscache_asm.S#1 $ - -// Copyright (c) 2003-2013 Tensilica 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. - -#ifdef INCLUDE_DEPRECATED_HAL_CACHE_CODE - -#include <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/config/system.h> - -/*** Modify this for your particular board or system: ***/ -#define CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_DEFAULT -#define CACHEATTR_BYPASS XSHAL_ISS_CACHEATTR_BYPASS - -//---------------------------------------------------------------------- -// Enable and disable the caches -//---------------------------------------------------------------------- - - .text - - .global xthal_icache_enable - .global xthal_dcache_enable - .global xthal_icache_enable_nw - .global xthal_dcache_enable_nw - - .global xthal_icache_disable - .global xthal_dcache_disable - .global xthal_icache_disable_nw - .global xthal_dcache_disable_nw - - /* - * Since we can't enable/disable the icache and dcache independently, - * and don't have a nice place to store a state which would enable - * us to only enable them both when both have been requested to be - * enabled, we simply enable both for any request to enable either, - * and disable both for any request to disable either cache. - */ - - .align 4 -xthal_icache_enable: - abi_entry - movi a3, xthal_set_icacheattr - movi a6, CACHEATTR_DEFAULT // get cache-enabled attributes - callx4 a3 // enable i-cache - mov a2, a6 // (in case future version has a return value) - abi_return - .size xthal_icache_enable, . - xthal_icache_enable - - .align 4 -xthal_dcache_enable: - abi_entry - movi a3, xthal_set_dcacheattr - movi a6, CACHEATTR_DEFAULT // get cache-enabled attributes - callx4 a3 // enable d-cache - mov a2, a6 // (in case future version has a return value) - abi_return - .size xthal_dcache_enable, . - xthal_dcache_enable - - .align 4 -xthal_icache_disable: - abi_entry - movi a3, xthal_set_icacheattr - movi a6, CACHEATTR_BYPASS // get cache-disabled attributes - callx4 a3 // disable i-cache - mov a2, a6 // (in case future version has a return value) - abi_return - .size xthal_icache_disable, . - xthal_icache_disable - - .align 4 -xthal_dcache_disable: - abi_entry - movi a3, xthal_set_dcacheattr - movi a6, CACHEATTR_BYPASS // get cache-disabled attributes - callx4 a3 // disable d-cache - mov a2, a6 // (in case future version has a return value) - abi_return - .size xthal_dcache_disable, . - xthal_dcache_disable - - .align 4 -xthal_icache_enable_nw: - movi a3, xthal_set_icacheattr_nw - movi a2, CACHEATTR_DEFAULT // get cache-enabled attributes - jx a3 // enable i-cache - .size xthal_icache_enable_nw, . - xthal_icache_enable_nw - - .align 4 -xthal_dcache_enable_nw: - movi a3, xthal_set_dcacheattr_nw - movi a2, CACHEATTR_DEFAULT // get cache-enabled attributes - jx a3 // enable d-cache - .size xthal_dcache_enable_nw, . - xthal_dcache_enable_nw - - .align 4 -xthal_icache_disable_nw: - movi a3, xthal_set_icacheattr_nw - movi a2, CACHEATTR_BYPASS // get cache-disabled attributes - jx a3 // disable i-cache - .size xthal_icache_disable_nw, . - xthal_icache_disable_nw - - .align 4 -xthal_dcache_disable_nw: - movi a3, xthal_set_dcacheattr_nw - movi a2, CACHEATTR_BYPASS // get cache-disabled attributes - jx a3 // disable d-cache - .size xthal_dcache_disable_nw, . - xthal_dcache_disable_nw - -#endif /* INCLUDE_DEPRECATED_HAL_CACHE_CODE */ - diff --git a/src/arch/xtensa/hal/windowspill_asm.S b/src/arch/xtensa/hal/windowspill_asm.S deleted file mode 100644 index 4568a41f5175..000000000000 --- a/src/arch/xtensa/hal/windowspill_asm.S +++ /dev/null @@ -1,386 +0,0 @@ -// -// windowspill.S -- register window spill routine -// -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/windowspill_asm.S#1 $ - -// Copyright (c) 1999-2010 Tensilica 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 <xtensa/coreasm.h> - - -// xthal_window_spill_nw -// -// Spill live register windows to the stack. -// -// Required entry conditions: -// PS.WOE = 0 -// PS.INTLEVEL >= XCHAL_EXCM_LEVEL -// a1 = valid stack pointer (note: some regs may be spilled at a1-16) -// a0 = return PC (usually set by call0 or callx0 when calling this function) -// a2,a3 undefined -// a4 thru a15 valid, if they are part of window(s) to be spilled -// (Current window a0..a15 saved if necessary.) -// WINDOWSTART[WINDOWBASE] = 1 -// -// Exit conditions: -// PS.WOE, PS.INTLEVEL = same as on entry -// WINDOWBASE = same as on entry -// WINDOWSTART updated to reflect spilled windows -// (equals 1<<WINDOWBASE if successful return) -// a0 = return PC -// a1 = same as on entry -// a2 = error code: -// 0 --> successful -// (WINDOWSTART = 1<<WINDOWBASE) -// 1 --> invalid WINDOWSTART (WINDOWBASE bit not set) -// (WINDOWSTART unchanged) -// 2 --> invalid window size (not 4, 8 or 12 regs) -// (WINDOWSTART bits of successfully spilled -// windows are cleared, others left intact) -// a3 clobbered -// a4,a5,a8,a9,a12,a13 = same as on entry -// a6,a7,a10,a11,a14,a15 clobbered if they were part of window(s) -// to be spilled, otherwise they are the same as on entry -// loop registers (LCOUNT,LBEG,LEND) are NOT affected (they were in earlier versions) -// SAR clobbered -// -// All non-spilled register windows will be spilled. -// Beware that this may include a4..a15 of the current window, -// so generally these should not have been clobbered by the -// caller if it is at all possible that these registers -// are part of an unspilled window (it often is possible) -// (otherwise the spilled stack would be invalid). -// -// THIS MEANS: the caller is responsible for saving a0-a15 but -// the caller must leave a4-a15 intact when control is transferred -// here. -// -// It may be reentrant (but stack pointer is invalid during -// execution due to window rotations, so can't take interrupts -// and exceptions in the usual manner, so ... what does -// reentrancy really mean here?). - - - // The xthal_spill_registers_into_stack_nw entry point - // is kept here only for backwards compatibility. - // It will be removed in the very near future. - .global xthal_spill_registers_into_stack_nw - - .text - .align 4 - .global xthal_window_spill_nw -xthal_window_spill_nw: -xthal_spill_registers_into_stack_nw: // BACKWARD COMPATIBILITY ONLY - see above - -#if ! XCHAL_HAVE_WINDOWED - // Nothing to do -- window option was not selected. - movi a2, 0 // always report success - ret -#else /* XCHAL_HAVE_WINDOWED */ -#define WSBITS (XCHAL_NUM_AREGS / 4) /* width of WINDOWSTART register in bits */ -#define WBBITS (XCHAL_NUM_AREGS_LOG2 - 2) /* width of WINDOWBASE register in bits */ - /* - * Rearrange (rotate) window start bits relative to the current - * window (WINDOWBASE). WINDOWSTART currently looks like this: - * - * a15-a0 - * NAREG-1 | | 0 - * | vvvv | - * xxxxxxxxxx1yyyyy - * ^ - * | - * WINDOWBASE - * - * The start bit pointed to by WINDOWBASE must be set - * (we return an error if it isn't), as it corresponds - * to the start of the current window (shown as a0-a15). - * - * We want the window start bits rotated to look like this: - * 1yyyyyxxxxxxxxxx - * - * Note that there is one start bit for every four registers; - * and the total number of registers (NAREG) can be 32 or 64; - * so the number of start bits in WINDOWSTART is NAREG/4, - * and the size of WINDOWSTART can be 8 or 16. - */ - - rsr.windowbase a2 - addi a2, a2, 1 - ssr a2 // sar = WINDOWBASE + 1 - rsr.windowstart a3 - srl a2, a3 // a2 is 0... | 000000xxxxxxxxxx = WINDOWSTART >> sar - sll a3, a3 // a3 is 1yyyyy0000000000 | 0... = WINDOWSTART << (32 - sar) - bgez a3, .Linvalid_ws // verify that msbit is indeed set - - srli a3, a3, 32-WSBITS // a3 is 0... | 1yyyyy0000000000 = a3 >> (32-NAREG/4) - or a2, a2, a3 // a2 is 0... | 1yyyyyxxxxxxxxxx - - /* - * FIND THE FIRST ONE - * - * Now we have (in a2) the window start bits rotated in order - * from oldest (closest to lsbit) to current (msbit set). - * Each start bit (that is set), other than the current one, - * corresponds to a window frame to spill. - * - * Now find the first start bit, ie. the first frame to spill, - * by looking for the first bit set in a2 (from lsbit side). - */ - -#if XCHAL_HAVE_NSA - neg a3, a2 // keep only the least-significant bit set of a2 ... - and a3, a3, a2 // ... in a3 - nsau a3, a3 // get index of that bit, numbered from msbit (32 if absent) - ssl a3 // set sar = 32 - a3 = bit index numbered from lsbit + 1 -#else /* XCHAL_HAVE_NSA */ - wsr.windowstart a2 // temporarily save rotated start bits - // (we can use WINDOWSTART because WOE=0) - - // NOTE: this could be optimized a bit, by explicit coding rather than the macro. - find_ls_one a3, a2 // set a3 to index of lsmost bit set in a2 (a2 clobbered) - - addi a2, a3, 1 // index+1 - ssr a2 // set sar = index + 1 - rsr.windowstart a2 // restore a2 (rotated start bits) -#endif /* XCHAL_HAVE_NSA */ - srl a2, a2 // right-justify the rotated start bits (dropping lsbit set) - wsr.windowstart a2 // save rotated + justified window start bits, - // because a2 will disappear when modifying WINDOWBASE - // again, we can use WINDOWSTART because WOE=0 - - /* - * Rotate WindowBase so that a0 of the next window to spill is in a4 - * (ie. leaving us with a2 and a3 to play with, because a0 and a1 - * may be those of the original window which we must preserve). - */ - rsr.windowbase a2 -#if XCHAL_HAVE_NSA - addi a2, a2, 31 - sub a3, a2, a3 // a3 = WINDOWBASE + index = WINDOWBASE + (31 - msbit_index) -#else /* XCHAL_HAVE_NSA */ - add a3, a2, a3 // a3 = WINDOWBASE + index -#endif /* XCHAL_HAVE_NSA */ - wsr.windowbase a3 // effectively do: rotw index - rsync // wait for write to WINDOWBASE to complete - // Now our registers have changed! - - rsr.windowstart a2 // restore a2 (rotated + justified window start bits) - - /* - * We are now ready to start the window spill loop. - * Relative to the above, a2 and WINDOWBASE are now as follows: - * - * 1yyyyyxxxxxxxxxx = rotated start bits as shown above - * 1yyyyyxxxx100000 = actual rotated start bits (example) - * 0000001yyyyyxxxx ^ = a2 = rotated + justified start bits - * ^ xxx1^ = window being spilled - * ^ ^ - * | | - * original current - * WINDOWBASE WINDOWBASE - * - * The first window to spill (save) starts at what is now a4. - * The spill loop maintains the adjusted start bits in a2, - * shifting them right as each window is spilled. - */ - -.Lspill_loop: - // Top of save loop. - // Find the size of this call and branch to the appropriate save routine. - - beqz a2, .Ldone // if no start bit remaining, we're done - bbsi.l a2, 0, .Lspill4 // if next start bit is set, it's a call4 - bbsi.l a2, 1, .Lspill8 // if 2nd next bit set, it's a call8 - bbsi.l a2, 2, .Lspill12 // if 3rd next bit set, it's a call12 - j .Linvalid_window // else it's an invalid window! - - - - // SAVE A CALL4 -.Lspill4: - addi a3, a9, -16 // a3 gets call[i+1]'s sp - 16 - s32i a4, a3, 0 // store call[i]'s a0 - s32i a5, a3, 4 // store call[i]'s a1 - s32i a6, a3, 8 // store call[i]'s a2 - s32i a7, a3, 12 // store call[i]'s a3 - - srli a6, a2, 1 // move and shift the start bits - rotw 1 // rotate the window - - j .Lspill_loop - - // SAVE A CALL8 -.Lspill8: - addi a3, a13, -16 // a0 gets call[i+1]'s sp - 16 - s32i a4, a3, 0 // store call[i]'s a0 - s32i a5, a3, 4 // store call[i]'s a1 - s32i a6, a3, 8 // store call[i]'s a2 - s32i a7, a3, 12 // store call[i]'s a3 - - addi a3, a5, -12 // call[i-1]'s sp address - l32i a3, a3, 0 // a3 is call[i-1]'s sp - // (load slot) - addi a3, a3, -32 // a3 points to our spill area - - s32i a8, a3, 0 // store call[i]'s a4 - s32i a9, a3, 4 // store call[i]'s a5 - s32i a10, a3, 8 // store call[i]'s a6 - s32i a11, a3, 12 // store call[i]'s a7 - - srli a10, a2, 2 // move and shift the start bits - rotw 2 // rotate the window - - j .Lspill_loop - - // SAVE A CALL12 -.Lspill12: - rotw 1 // rotate to see call[i+1]'s sp - - addi a13, a13, -16 // set to the reg save area - s32i a0, a13, 0 // store call[i]'s a0 - s32i a1, a13, 4 // store call[i]'s a1 - s32i a2, a13, 8 // store call[i]'s a2 - s32i a3, a13, 12 // store call[i]'s a3 - - addi a3, a1, -12 // call[i-1]'s sp address - l32i a3, a3, 0 // a3 has call[i-1]'s sp - addi a13, a13, 16 // restore call[i+1]'s sp (here to fill load slot) - addi a3, a3, -48 // a3 points to our save area - - s32i a4, a3, 0 // store call[i]'s a4 - s32i a5, a3, 4 // store call[i]'s a5 - s32i a6, a3, 8 // store call[i]'s a6 - s32i a7, a3, 12 // store call[i]'s a7 - s32i a8, a3, 16 // store call[i]'s a4 - s32i a9, a3, 20 // store call[i]'s a5 - s32i a10, a3, 24 // store call[i]'s a6 - s32i a11, a3, 28 // store call[i]'s a7 - - rotw -1 // rotate to see start bits (a2) - srli a14, a2, 3 // move and shift the start bits - rotw 3 // rotate to next window - - j .Lspill_loop - - - -.Ldone: - rotw 1 // back to the original window - rsr.windowbase a2 // get (original) window base - ssl a2 // setup for shift left by WINDOWBASE - movi a2, 1 - sll a2, a2 // compute new WINDOWSTART = 1<<WINDOWBASE - wsr.windowstart a2 // and apply it - rsync - movi a2, 0 // done! - ret - //jx a0 - - - // Invalid WINDOWSTART register. - // -.Linvalid_ws: - movi a2, 1 // indicate invalid WINDOWSTART - ret // return from subroutine - - - // Invalid window size! - // The three bits following the start bit are all clear, so - // we have an invalid window state (can't determine a window size). - // - // So we exit with an error, but to do that we must first restore - // the original WINDOWBASE. We also compute a sensible - // WINDOWSTART that has the start bits of spilled windows - // cleared, but all other start bits intact, so someone debugging - // the failure can look at WINDOWSTART to see which window - // failed to spill. - // -.Linvalid_window: - slli a2, a2, 1 // space for missing start bit - addi a2, a2, 1 // add missing start bit - rsr.windowbase a3 // get current WINDOWBASE - bbsi.l a2, WSBITS-1, 2f // branch if current WINDOWBASE==original -1: addi a3, a3, -1 // decrement towards original WINDOWBASE - slli a2, a2, 1 // shift towards original WINDOWSTART alignment - bbci.l a2, WSBITS-1, 1b // repeat until ms start bit set - extui a3, a3, 0, WBBITS // mask out upper base bits, in case of carry-over -2: // Here, a3 = original WINDOWBASE; - // and msbit of start bits in a2 is set, and no other bits above it. - // Now rotate a2 to become the correct WINDOWSTART. - ssl a3 // set shift left ... (sar = 32 - orig WB) - slli a3, a2, 32-WSBITS // left-justify start bits - src a2, a2, a3 // rotate left by original WINDOWBASE - extui a2, a2, 0, WSBITS // keep only significant start bits - wsr.windowstart a2 // we've cleared only start bits of spilled windows - rsr.sar a3 // retrieve 32 - original WINDOWBASE - movi a2, 32 - sub a3, a2, a3 // restore original WINDOWBASE - wsr.windowbase a3 // back to original WINDOWBASE - rsync - - movi a2, 2 // indicate invalid window size - ret - -#endif /* XCHAL_HAVE_WINDOWED */ - - .size xthal_window_spill_nw, . - xthal_window_spill_nw - - -// void xthal_window_spill (void); -// -// Spill live register windows to the stack. -// -// This will spill all register windows except this -// function's window, and possibly that of its caller. -// (Currently, the caller's window is spilled and reloaded -// when this function returns. This may change with -// future optimisations.) -// -// Another, simpler way to implement this might be -// to use an appropriate sequence of call/entry/retw -// instructions to force overflow of any live windows. -// -// Assumes that PS.INTLEVEL=0 and PS.WOE=1 on entry/exit. -// - .text - .align 4 - .global xthal_window_spill - .type xthal_window_spill,@function -xthal_window_spill: - abi_entry -#if XCHAL_HAVE_WINDOWED - movi a6, ~(PS_WOE_MASK|PS_INTLEVEL_MASK) // (using a6 ensures any window using this a4..a7 is spilled) - rsr.ps a5 - mov a4, a0 // save a0 - and a2, a5, a6 // clear WOE, INTLEVEL - addi a2, a2, XCHAL_EXCM_LEVEL // set INTLEVEL = XCHAL_EXCM_LEVEL - wsr.ps a2 // apply to PS - rsync - call0 xthal_window_spill_nw - mov a0, a4 // restore a0 - wsr.ps a5 // restore PS - rsync -#endif /* XCHAL_HAVE_WINDOWED */ - abi_return - - .size xthal_window_spill, . - xthal_window_spill - diff --git a/src/arch/xtensa/include/arch/atomic.h b/src/arch/xtensa/include/arch/atomic.h deleted file mode 100644 index fcb98446e5ae..000000000000 --- a/src/arch/xtensa/include/arch/atomic.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_ATOMIC_H__ - -#ifndef __ARCH_ATOMIC_H__ -#define __ARCH_ATOMIC_H__ - -#include <stdint.h> - -typedef struct { - volatile int32_t value; -} atomic_t; - -static inline int32_t arch_atomic_read(const atomic_t *a) -{ - return (*(volatile int32_t *)&a->value); -} - -static inline void arch_atomic_set(atomic_t *a, int32_t value) -{ - a->value = value; -} - -static inline void arch_atomic_init(atomic_t *a, int32_t value) -{ - arch_atomic_set(a, value); -} - -static inline int32_t arch_atomic_add(atomic_t *a, int32_t value) -{ - int32_t result, current; - - __asm__ __volatile__( - "1: l32i %1, %2, 0\n" - " wsr %1, scompare1\n" - " add %0, %1, %3\n" - " s32c1i %0, %2, 0\n" - " bne %0, %1, 1b\n" - : "=&a" (result), "=&a" (current) - : "a" (&a->value), "a" (value) - : "memory"); - - return (*(volatile int32_t *)&a->value); -} - -static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value) -{ - int32_t result, current; - - __asm__ __volatile__( - "1: l32i %1, %2, 0\n" - " wsr %1, scompare1\n" - " sub %0, %1, %3\n" - " s32c1i %0, %2, 0\n" - " bne %0, %1, 1b\n" - : "=&a" (result), "=&a" (current) - : "a" (&a->value), "a" (value) - : "memory"); - - return (*(volatile int32_t *)&a->value); -} - -#endif /* __ARCH_ATOMIC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/atomic.h" - -#endif /* __SOF_ATOMIC_H__ */ diff --git a/src/arch/xtensa/include/arch/compiler_info.h b/src/arch/xtensa/include/arch/compiler_info.h deleted file mode 100644 index d59da46a7a1f..000000000000 --- a/src/arch/xtensa/include/arch/compiler_info.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> - */ - -/** - * \file include/sof/compiler_info.h - * \brief Compiler version and name descriptor - * \author Karol Trzcinski <karolx.trzcinski@linux.intel.com> - */ - -#ifndef __ARCH_COMPILER_INFO_H__ -#define __ARCH_COMPILER_INFO_H__ - -#include <xtensa/hal.h> - -/* read used compilator name and version */ -/* CC_NAME must consist of 3 characters with null termination */ -/* See declaration of sof_ipc_cc_version. */ -#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 - -#endif /* __ARCH_COMPILER_INFO_H__ */ diff --git a/src/arch/xtensa/include/arch/debug/gdb/utilities.h b/src/arch/xtensa/include/arch/debug/gdb/utilities.h deleted file mode 100644 index c786d774c6fe..000000000000 --- a/src/arch/xtensa/include/arch/debug/gdb/utilities.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> - */ - -/* - * Header file for Xtensa-GDB utilities. - */ - -#ifndef __ARCH_DEBUG_GDB_UTILITIES_H__ -#define __ARCH_DEBUG_GDB_UTILITIES_H__ - -/* Implicit inclusion from sof/debug/gdb/gdb.h */ -#include <arch/debug/gdb/xtensa-defs.h> - -void arch_gdb_read_sr(int sr); -void arch_gdb_write_sr(int sr, int *sregs); -unsigned char arch_gdb_load_from_memory(void *mem); -void arch_gdb_memory_load_and_store(void *mem, unsigned char ch); -void arch_gdb_single_step(int *sregs); - -#endif /* __ARCH_DEBUG_GDB_UTILITIES_H__ */ diff --git a/src/arch/xtensa/include/arch/debug/gdb/xtensa-defs.h b/src/arch/xtensa/include/arch/debug/gdb/xtensa-defs.h deleted file mode 100644 index 8ae65da38472..000000000000 --- a/src/arch/xtensa/include/arch/debug/gdb/xtensa-defs.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> - */ - -/* - * Header file for xtensa specific defs for GDB. - */ - -#ifndef __ARCH_DEBUG_GDB_XTENSA_DEFS_H__ -#define __ARCH_DEBUG_GDB_XTENSA_DEFS_H__ - -#include <xtensa/config/core-isa.h> -#include <xtensa/specreg.h> - -#define _AREG0 256 - -#define STACK_SIZE 1024 -#define DEBUG_PC (EPC + XCHAL_DEBUGLEVEL) -#define DEBUG_EXCSAVE (EXCSAVE + XCHAL_DEBUGLEVEL) -#define DEBUG_PS (EPS + XCHAL_DEBUGLEVEL) -#define DEBUG_WINDOWBASE WINDOWBASE -#define DEBUG_NUM_IBREAK XCHAL_NUM_IBREAK -#define DEBUG_IBREAKENABLE IBREAKENABLE -#define DEBUG_IBREAKA IBREAKA -#define DEBUG_INTENABLE INTENABLE -#define DEBUG_NUM_AREGS XCHAL_NUM_AREGS - -#endif /* __ARCH_DEBUG_GDB_XTENSA_DEFS_H__ */ diff --git a/src/arch/xtensa/include/arch/debug/offset-defs.h b/src/arch/xtensa/include/arch/debug/offset-defs.h deleted file mode 100644 index 682e90c5f97b..000000000000 --- a/src/arch/xtensa/include/arch/debug/offset-defs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - */ - -#ifndef __ARCH_DEBUG_OFFSET_DEFS_H__ -#define __ARCH_DEBUG_OFFSET_DEFS_H__ - -#include <xtensa/config/core-isa.h> - -#define REG_OFFSET_EXCCAUSE 0x0 -#define REG_OFFSET_EXCVADDR 0x4 -#define REG_OFFSET_PS 0x8 -#define REG_OFFSET_EPC1 0xc -#define REG_OFFSET_EPC2 0x10 -#define REG_OFFSET_EPC3 0x14 -#define REG_OFFSET_EPC4 0x18 -#define REG_OFFSET_EPC5 0x1c -#define REG_OFFSET_EPC6 0x20 -#define REG_OFFSET_EPC7 0x24 -#define REG_OFFSET_EPS2 0x28 -#define REG_OFFSET_EPS3 0x2c -#define REG_OFFSET_EPS4 0x30 -#define REG_OFFSET_EPS5 0x34 -#define REG_OFFSET_EPS6 0x38 -#define REG_OFFSET_EPS7 0x3c -#define REG_OFFSET_DEPC 0x40 -#define REG_OFFSET_INTENABLE 0x44 -#define REG_OFFSET_INTERRUPT 0x48 -#define REG_OFFSET_SAR 0x4c -#define REG_OFFSET_DEBUGCAUSE 0x50 -#define REG_OFFSET_WINDOWBASE 0x54 -#define REG_OFFSET_WINDOWSTART 0x58 -#define REG_OFFSET_EXCSAVE1 0x5c -#define REG_OFFSET_AR_BEGIN 0x60 -#define REG_OFFSET_AR_END (REG_OFFSET_AR_BEGIN + 4 * XCHAL_NUM_AREGS) - -#endif /* __ARCH_DEBUG_OFFSET_DEFS_H__ */ diff --git a/src/arch/xtensa/include/arch/debug/panic.h b/src/arch/xtensa/include/arch/debug/panic.h deleted file mode 100644 index 558964514809..000000000000 --- a/src/arch/xtensa/include/arch/debug/panic.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DEBUG_PANIC_H__ - -#ifndef __ARCH_DEBUG_PANIC_H__ -#define __ARCH_DEBUG_PANIC_H__ - -#include <sof/lib/cache.h> -#include <ipc/trace.h> -#include <ipc/xtensa.h> -#include <xtensa/config/core-isa.h> -#include <stdint.h> - -/* xtensa core specific oops size */ -#define ARCH_OOPS_SIZE (sizeof(struct sof_ipc_dsp_oops_xtensa) \ - + (XCHAL_NUM_AREGS * sizeof(uint32_t))) - -void arch_dump_regs_a(void *dump_buf); - -static inline void fill_core_dump(struct sof_ipc_dsp_oops_xtensa *oops, - uintptr_t stack_ptr, uintptr_t *epc1) -{ - oops->arch_hdr.arch = ARCHITECTURE_ID; - oops->arch_hdr.totalsize = ARCH_OOPS_SIZE; -#if XCHAL_HW_CONFIGID_RELIABLE - oops->plat_hdr.configidhi = XCHAL_HW_CONFIGID0; - oops->plat_hdr.configidlo = XCHAL_HW_CONFIGID1; -#else - oops->plat_hdr.configidhi = 0; - oops->plat_hdr.configidlo = 0; -#endif - oops->plat_hdr.numaregs = XCHAL_NUM_AREGS; - oops->plat_hdr.stackoffset = oops->arch_hdr.totalsize - + sizeof(struct sof_ipc_panic_info); - oops->plat_hdr.stackptr = stack_ptr; - - if (epc1) - oops->epc1 = *epc1; - - arch_dump_regs_a((void *)&oops->exccause); -} - -static inline void arch_dump_regs(void *dump_buf, uintptr_t stack_ptr, - uintptr_t *epc1) -{ - fill_core_dump(dump_buf, stack_ptr, epc1); - - dcache_writeback_region(dump_buf, ARCH_OOPS_SIZE); -} - -#endif /* __ARCH_DEBUG_PANIC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/debug/panic.h" - -#endif /* __SOF_DEBUG_PANIC_H__ */ diff --git a/src/arch/xtensa/include/arch/drivers/interrupt.h b/src/arch/xtensa/include/arch/drivers/interrupt.h index afb4921141a8..c1a9306c59a5 100644 --- a/src/arch/xtensa/include/arch/drivers/interrupt.h +++ b/src/arch/xtensa/include/arch/drivers/interrupt.h @@ -14,7 +14,7 @@ #include <xtensa/xtruntime.h> #include <stddef.h> #include <stdint.h> -#include <config.h> + static inline int arch_interrupt_register(int irq, void (*handler)(void *arg), void *arg) @@ -73,14 +73,14 @@ static inline uint32_t arch_interrupt_global_disable(void) { uint32_t flags; - asm volatile("rsil %0, 5" + __asm__ __volatile__("rsil %0, 5" : "=a" (flags) :: "memory"); return flags; } static inline void arch_interrupt_global_enable(uint32_t flags) { - asm volatile("wsr %0, ps; rsync" + __asm__ __volatile__("wsr %0, ps; rsync" :: "a" (flags) : "memory"); } diff --git a/src/arch/xtensa/include/arch/drivers/timer.h b/src/arch/xtensa/include/arch/drivers/timer.h deleted file mode 100644 index 1836750d47cc..000000000000 --- a/src/arch/xtensa/include/arch/drivers/timer.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_TIMER_H__ - -#ifndef __ARCH_DRIVERS_TIMER_H__ -#define __ARCH_DRIVERS_TIMER_H__ - -#include <sof/drivers/interrupt.h> -#include <sof/lib/memory.h> -#include <stdint.h> - -#define ARCH_TIMER_COUNT 3 - -struct timer { - uint32_t id; - int irq; - int logical_irq; /* used for external timers */ - const char *irq_name; - void (*handler)(void *data); /* optional timer handler */ - void *data; /* optional timer handler's data */ - uint32_t hitime; /* high end of 64bit timer */ - uint32_t hitimeout; - uint32_t lowtimeout; - uint64_t delta; -}; - -/* internal API calls */ -int timer64_register(struct timer *timer, void (*handler)(void *arg), - void *arg); -void timer_64_handler(void *arg); - -static inline int arch_timer_register(struct timer *timer, - void (*handler)(void *arg), void *arg) -{ - uint32_t flags; - int ret; - - flags = arch_interrupt_global_disable(); - timer64_register(timer, handler, arg); - ret = arch_interrupt_register(timer->irq, timer_64_handler, timer); - arch_interrupt_global_enable(flags); - - platform_shared_commit(timer, sizeof(*timer)); - - return ret; -} - -static inline void arch_timer_unregister(struct timer *timer) -{ - arch_interrupt_unregister(timer->irq); -} - -static inline void arch_timer_enable(struct timer *timer) -{ - arch_interrupt_enable_mask(1 << timer->irq); -} - -static inline void arch_timer_disable(struct timer *timer) -{ - arch_interrupt_disable_mask(1 << timer->irq); -} - -uint64_t arch_timer_get_system(struct timer *timer); - -int64_t arch_timer_set(struct timer *timer, uint64_t ticks); - -static inline void arch_timer_clear(struct timer *timer) -{ - arch_interrupt_clear(timer->irq); -} - -#endif /* __ARCH_DRIVERS_TIMER_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/timer.h" - -#endif /* __SOF_DRIVERS_TIMER_H__ */ diff --git a/src/arch/xtensa/include/arch/init.h b/src/arch/xtensa/include/arch/init.h deleted file mode 100644 index 31286eda4203..000000000000 --- a/src/arch/xtensa/include/arch/init.h +++ /dev/null @@ -1,148 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -/** - * \file arch/xtensa/include/arch/init.h - * \brief Arch init header file - * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_INIT_H__ - -#ifndef __ARCH_INIT_H__ -#define __ARCH_INIT_H__ - -#include <sof/debug/panic.h> -#include <ipc/trace.h> -#include <config.h> -#include <xtensa/corebits.h> -#include <xtensa/xtruntime.h> -#include <stddef.h> -#include <stdint.h> - -struct sof; - -/** - * \brief Called in the case of exception. - */ -static inline void exception(void) -{ - uintptr_t epc1; - - __asm__ __volatile__("rsr %0, EPC1" : "=a" (epc1) : : "memory"); - - /* now panic and rewind 8 stack frames. */ - /* TODO: we could invoke a GDB stub here */ - panic_rewind(SOF_IPC_PANIC_EXCEPTION, 8 * sizeof(uint32_t), - NULL, &epc1); -} - -/** - * \brief Registers exception handlers. - */ -static inline void register_exceptions(void) -{ - - /* 0 - 9 */ - _xtos_set_exception_handler( - EXCCAUSE_ILLEGAL, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_SYSCALL, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_INSTR_ERROR, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_LOAD_STORE_ERROR, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_ALLOCA, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_DIVIDE_BY_ZERO, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_SPECULATION, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_PRIVILEGED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_UNALIGNED, (void *)&exception); - - /* Reserved 10..11 */ - - _xtos_set_exception_handler( - EXCCAUSE_INSTR_DATA_ERROR, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_LOAD_STORE_DATA_ERROR, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_INSTR_ADDR_ERROR, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_LOAD_STORE_ADDR_ERROR, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_ITLB_MISS, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_ITLB_MULTIHIT, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_INSTR_RING, (void *)&exception); - - /* Reserved 19 */ - - _xtos_set_exception_handler( - EXCCAUSE_INSTR_PROHIBITED, (void *)&exception); - - /* Reserved 21..23 */ - _xtos_set_exception_handler( - EXCCAUSE_DTLB_MISS, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_DTLB_MULTIHIT, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_LOAD_STORE_RING, (void *)&exception); - - /* Reserved 27 */ - _xtos_set_exception_handler( - EXCCAUSE_LOAD_PROHIBITED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_STORE_PROHIBITED, (void *)&exception); - - /* Reserved 30..31 */ - _xtos_set_exception_handler( - EXCCAUSE_CP0_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP1_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP2_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP3_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP4_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP5_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP6_DISABLED, (void *)&exception); - _xtos_set_exception_handler( - EXCCAUSE_CP7_DISABLED, (void *)&exception); - - /* Reserved 40..63 */ -} - -/** - * \brief Called from assembler context with no return or parameters. - */ -static inline void __memmap_init(void) { } - -#if CONFIG_SMP - -int slave_core_init(struct sof *sof); - -#else - -static inline int slave_core_init(struct sof *sof) { return 0; } - -#endif /* CONFIG_SMP */ - -#endif /* __ARCH_INIT_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/init.h" - -#endif /* __SOF_INIT_H__ */ diff --git a/src/arch/xtensa/include/arch/lib/cache.h b/src/arch/xtensa/include/arch/lib/cache.h deleted file mode 100644 index 4cdcccea4e58..000000000000 --- a/src/arch/xtensa/include/arch/lib/cache.h +++ /dev/null @@ -1,87 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_CACHE_H__ - -#ifndef __ARCH_LIB_CACHE_H__ -#define __ARCH_LIB_CACHE_H__ - -#include <xtensa/config/core-isa.h> - -#define DCACHE_LINE_SIZE XCHAL_DCACHE_LINESIZE - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <xtensa/hal.h> -#include <stddef.h> -#include <stdint.h> - -static inline void dcache_writeback_region(void *addr, size_t size) -{ -#if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_region_writeback(addr, size); -#endif -} - -static inline void dcache_writeback_all(void) -{ -#if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_all_writeback(); -#endif -} - -static inline void dcache_invalidate_region(void *addr, size_t size) -{ -#if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_region_invalidate(addr, size); -#endif -} - -static inline void dcache_invalidate_all(void) -{ -#if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_all_invalidate(); -#endif -} - -static inline void icache_invalidate_region(void *addr, size_t size) -{ -#if XCHAL_ICACHE_SIZE > 0 - xthal_icache_region_invalidate(addr, size); -#endif -} - -static inline void icache_invalidate_all(void) -{ -#if XCHAL_ICACHE_SIZE > 0 - xthal_icache_all_invalidate(); -#endif -} - -static inline void dcache_writeback_invalidate_region(void *addr, size_t size) -{ -#if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_region_writeback_inv(addr, size); -#endif -} - -static inline void dcache_writeback_invalidate_all(void) -{ -#if XCHAL_DCACHE_SIZE > 0 - xthal_dcache_all_writeback_inv(); -#endif -} - -#endif /* !defined(__ASSEMBLER__) && !defined(LINKER) */ - -#endif /* __ARCH_LIB_CACHE_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/lib/cache.h" - -#endif /* __SOF_LIB_CACHE_H__ */ diff --git a/src/arch/xtensa/include/arch/lib/cpu.h b/src/arch/xtensa/include/arch/lib/cpu.h deleted file mode 100644 index 10e2b636ef33..000000000000 --- a/src/arch/xtensa/include/arch/lib/cpu.h +++ /dev/null @@ -1,128 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Rander Wang <rander.wang@linux.intel.com> - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __ARCH_LIB_CPU_H__ -#define __ARCH_LIB_CPU_H__ - -#include <config.h> -#include <xtensa/config/core-isa.h> - -#if CONFIG_SMP - -void cpu_power_down_core(void); - -void cpu_alloc_core_context(int id); - -void arch_cpu_enable_core(int id); - -void arch_cpu_disable_core(int id); - -int arch_cpu_is_core_enabled(int id); - -#else - -static inline void arch_cpu_enable_core(int id) { } - -static inline void arch_cpu_disable_core(int id) { } - -static inline int arch_cpu_is_core_enabled(int id) { return 1; } - -#endif - -static inline int arch_cpu_get_id(void) -{ - int prid; -#if XCHAL_HAVE_PRID - __asm__("rsr.prid %0" : "=a"(prid)); -#else - prid = PLATFORM_MASTER_CORE_ID; -#endif - return prid; -} - -#if !XCHAL_HAVE_THREADPTR -extern unsigned int _virtual_thread_start; -static unsigned int *virtual_thread_ptr = - (unsigned int *)&_virtual_thread_start; -#endif - -static inline void cpu_write_threadptr(int threadptr) -{ -#if XCHAL_HAVE_THREADPTR - __asm__ __volatile__( - "wur.threadptr %0" : : "a" (threadptr) : "memory"); -#else - *virtual_thread_ptr = threadptr; -#endif -} - -static inline int cpu_read_threadptr(void) -{ - int threadptr; -#if XCHAL_HAVE_THREADPTR - __asm__ __volatile__( - "rur.threadptr %0" : "=a"(threadptr)); -#else - threadptr = *virtual_thread_ptr; -#endif - return threadptr; -} - -static inline int cpu_read_vecbase(void) -{ - int vecbase; - - __asm__ __volatile__("rsr.vecbase %0" - : "=a"(vecbase)); - return vecbase; -} - -static inline int cpu_read_excsave2(void) -{ - int excsave2; - - __asm__ __volatile__("rsr.excsave2 %0" - : "=a"(excsave2)); - return excsave2; -} - -static inline int cpu_read_excsave3(void) -{ - int excsave3; - - __asm__ __volatile__("rsr.excsave3 %0" - : "=a"(excsave3)); - return excsave3; -} - -static inline int cpu_read_excsave4(void) -{ - int excsave4; - - __asm__ __volatile__("rsr.excsave4 %0" - : "=a"(excsave4)); - return excsave4; -} - -static inline int cpu_read_excsave5(void) -{ - int excsave5; - - __asm__ __volatile__("rsr.excsave5 %0" - : "=a"(excsave5)); - return excsave5; -} - -#endif /* __ARCH_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/arch/xtensa/include/arch/lib/wait.h b/src/arch/xtensa/include/arch/lib/wait.h deleted file mode 100644 index 1445f0f35d34..000000000000 --- a/src/arch/xtensa/include/arch/lib/wait.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __ARCH_LIB_WAIT_H__ -#define __ARCH_LIB_WAIT_H__ - -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <ipc/trace.h> -#include <config.h> -#include <xtensa/xtruntime.h> - -#if (CONFIG_WAITI_DELAY) - -static inline void arch_wait_for_interrupt(int level) -{ - int i; - - /* need to make sure the interrupt level won't be lowered */ - if (level) - panic(SOF_IPC_PANIC_WFI); - - /* this sequence must be atomic on LX6 */ - XTOS_SET_INTLEVEL(5); - - /* LX6 needs a delay */ - for (i = 0; i < 128; i++) - asm volatile("nop"); - - /* and to flush all loads/stores prior to wait */ - asm volatile("isync"); - asm volatile("extw"); - - /* now wait */ - asm volatile("waiti 0"); -} - -#else - -static inline void arch_wait_for_interrupt(int level) -{ - /* need to make sure the interrupt level won't be lowered */ - if (level) - panic(SOF_IPC_PANIC_WFI); - - asm volatile("waiti 0"); -} - -#endif - -static inline void idelay(int n) -{ - while (n--) - asm volatile("nop"); -} - -#endif /* __ARCH_LIB_WAIT_H__ */ diff --git a/src/arch/xtensa/include/arch/schedule/task.h b/src/arch/xtensa/include/arch/schedule/task.h deleted file mode 100644 index 493241cd18d8..000000000000 --- a/src/arch/xtensa/include/arch/schedule/task.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file arch/xtensa/include/arch/schedule/task.h - * \brief Arch task header file - * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_SCHEDULE_TASK_H__ - -#ifndef __ARCH_SCHEDULE_TASK_H__ -#define __ARCH_SCHEDULE_TASK_H__ - -/** - * \brief Returns main task data. - * \return Pointer to pointer of main task data. - */ -struct task **task_main_get(void); - -/** - * \brief Returns current system context. - */ -volatile void *task_context_get(void); - -/** - * \brief Switches system context. - * \param[in,out] task_ctx Task context to be set. - */ -void task_context_set(void *task_ctx); - -/** - * \brief Allocates task context. - * \param[in,out] task_ctx Assigned to allocated structure on return. - */ -int task_context_alloc(void **task_ctx); - -/** - * \brief Initializes task context. - * \param[in,out] task_ctx Task context to be initialized. - * \param[in] entry Entry point for task execution. - * \param[in] arg0 First argument to be passed to entry function. - * \param[in] arg1 Second argument to be passed to entry function. - * \param[in] task_core Id of the core that task will be executed on. - * \param[in] stack Address of the stack, if NULL then allocated internally. - * \param[in] stack_size Size of the stack, ignored if stack is NULL. - */ -int task_context_init(void *task_ctx, void *entry, void *arg0, void *arg1, - int task_core, void *stack, int stack_size); - -/** - * \brief Frees task context. - * \param[in,out] task_ctx Task with context to be freed. - */ -void task_context_free(void *task_ctx); - -/** - * \brief Performs cache operation on task's context. - * \param[in,out] task_ctx Context to be wtb/inv. - * \param[in] cmd Cache operation to be performed. - */ -void task_context_cache(void *task_ctx, int cmd); - -#endif /* __ARCH_SCHEDULE_TASK_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/schedule/task.h" - -#endif /* __SOF_SCHEDULE_TASK_H__ */ diff --git a/src/arch/xtensa/include/arch/sof.h b/src/arch/xtensa/include/arch/sof.h deleted file mode 100644 index bf1cc377837d..000000000000 --- a/src/arch/xtensa/include/arch/sof.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifdef __SOF_SOF_H__ - -#ifndef __ARCH_SOF_H__ -#define __ARCH_SOF_H__ - -#include <sof/schedule/task.h> -#include <xtensa/xtruntime-frames.h> -#include <stdint.h> - -/* entry point to main firmware */ -void _ResetVector(void); - -void boot_master_core(void); - -static inline void *arch_get_stack_ptr(void) -{ - void *ptr; - - /* stack pointer is in a1 */ - __asm__ __volatile__ ("mov %0, a1" - : "=a" (ptr) - : - : "memory"); - return ptr; -} - -static inline void *arch_get_stack_entry(void) -{ - volatile xtos_task_context *task_ctx = task_context_get(); - - return task_ctx->stack_base; -} - -static inline uint32_t arch_get_stack_size(void) -{ - volatile xtos_task_context *task_ctx = task_context_get(); - - return task_ctx->stack_size; -} - -#endif /* __ARCH_SOF_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/sof.h" - -#endif /* __SOF_SOF_H__ */ diff --git a/src/arch/xtensa/include/arch/spinlock.h b/src/arch/xtensa/include/arch/spinlock.h deleted file mode 100644 index c1772be6009f..000000000000 --- a/src/arch/xtensa/include/arch/spinlock.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_SPINLOCK_H__ - -#ifndef __ARCH_SPINLOCK_H__ -#define __ARCH_SPINLOCK_H__ - -#include <config.h> -#include <stdint.h> - -typedef struct { - volatile uint32_t lock; -#if CONFIG_DEBUG_LOCKS - uint32_t user; -#endif -} spinlock_t; - -static inline void arch_spinlock_init(spinlock_t *lock) -{ - lock->lock = 0; -} - -static inline void arch_spin_lock(spinlock_t *lock) -{ - uint32_t result; - - /* TODO: Should be platform specific, since on SMP platforms - * without uncached memory region we'll need additional cache - * invalidations in a loop - */ - __asm__ __volatile__( - " movi %0, 0\n" - " wsr %0, scompare1\n" - "1: movi %0, 1\n" - " s32c1i %0, %1, 0\n" - " bnez %0, 1b\n" - : "=&a" (result) - : "a" (&lock->lock) - : "memory"); -} - -static inline int arch_try_lock(spinlock_t *lock) -{ - uint32_t result; - - __asm__ __volatile__( - " movi %0, 0\n" - " wsr %0, scompare1\n" - " movi %0, 1\n" - " s32c1i %0, %1, 0\n" - : "=&a" (result) - : "a" (&lock->lock) - : "memory"); - - /* return 0 for failed lock, 1 otherwise */ - return result ? 0 : 1; -} - -static inline void arch_spin_unlock(spinlock_t *lock) -{ - uint32_t result; - - __asm__ __volatile__( - " movi %0, 0\n" - " s32ri %0, %1, 0\n" - : "=&a" (result) - : "a" (&lock->lock) - : "memory"); -} - -#endif /* __ARCH_SPINLOCK_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/spinlock.h" - -#endif /* __SOF_SPINLOCK_H__ */ diff --git a/src/arch/xtensa/include/arch/string.h b/src/arch/xtensa/include/arch/string.h deleted file mode 100644 index 11c55452b643..000000000000 --- a/src/arch/xtensa/include/arch/string.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_STRING_H__ - -#ifndef __ARCH_STRING_H__ -#define __ARCH_STRING_H__ - -#include <config.h> -#include <xtensa/hal.h> -#include <errno.h> -#include <stddef.h> -#include <string.h> - -#define arch_memcpy(dest, src, size) \ - xthal_memcpy(dest, src, size) - -#if __XCC__ && !defined(UNIT_TEST) -#define arch_bzero(ptr, size) \ - memset_s(ptr, size, 0, size) -#else -#define arch_bzero(ptr, size) \ - memset(ptr, 0, size) -#endif - -void *memcpy(void *dest, const void *src, size_t length); -void *memset(void *dest, int data, size_t count); -void *xthal_memcpy(void *dst, const void *src, size_t len); - -int memset_s(void *dest, size_t dest_size, - int data, size_t count); -int memcpy_s(void *dest, size_t dest_size, - const void *src, size_t src_size); - -#if __XCC__ && XCHAL_HAVE_HIFI3 && !CONFIG_LIBRARY -void *__vec_memcpy(void *dst, const void *src, size_t len); -void *__vec_memset(void *dest, int data, size_t src_size); -#endif - -static inline int arch_memcpy_s(void *dest, size_t dest_size, - const void *src, size_t src_size) -{ - if (!dest || !src) - return -EINVAL; - - if ((dest >= src && (char *)dest < ((char *)src + src_size)) || - (src >= dest && (char *)src < ((char *)dest + dest_size))) - return -EINVAL; - - if (src_size > dest_size) - return -EINVAL; - -#if __XCC__ && XCHAL_HAVE_HIFI3 && !CONFIG_LIBRARY - __vec_memcpy(dest, src, src_size); -#else - memcpy(dest, src, src_size); -#endif - - return 0; -} - -static inline int arch_memset_s(void *dest, size_t dest_size, - int data, size_t count) -{ - if (!dest) - return -EINVAL; - - if (count > dest_size) - return -EINVAL; - -#if __XCC__ && XCHAL_HAVE_HIFI3 && !CONFIG_LIBRARY - if (!__vec_memset(dest, data, count)) - return -ENOMEM; -#else - memset(dest, data, count); -#endif - return 0; -} - -#endif /* __ARCH_STRING_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/string.h" - -#endif /* __SOF_STRING_H__ */ diff --git a/src/arch/xtensa/include/xtensa/board.h b/src/arch/xtensa/include/xtensa/board.h deleted file mode 100644 index c6b04a250575..000000000000 --- a/src/arch/xtensa/include/xtensa/board.h +++ /dev/null @@ -1,28 +0,0 @@ -/* This header is supposed to be obtained from <board>/xtensa/board.h - using a -I directive passed to the compiler. */ - -#error "Unspecified board. Missing -I directive to select supported Xtensa board, usually -I XTENSA_TOOLS_ROOT/xtensa-elf/include/xtensa/<BOARD> (XTENSA_TOOLS_ROOT is root of Xtensa Tools install, see xt-run --show-config=xttools)" - -/* - * Copyright (c) 2013 Tensilica 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. - */ - diff --git a/src/arch/xtensa/include/xtensa/c6x-compat.h b/src/arch/xtensa/include/xtensa/c6x-compat.h deleted file mode 100755 index 4b17987ea95c..000000000000 --- a/src/arch/xtensa/include/xtensa/c6x-compat.h +++ /dev/null @@ -1,1758 +0,0 @@ -/* - * Copyright (c) 2006-2010 Tensilica Inc. ALL RIGHTS RESERVED. - * - * 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. - */ - -#ifndef __C6X_COMPAT__H -#define __C6X_COMPAT__H - -/* Unimplemented functions _gmpy, _gmpy4, _xormpy, _lssub, _cmpy, _cmpyr, - _cmpyr1, _ddotpl2r, _ddotph2r */ - - -typedef long long C6X_COMPAT_LONG40; - - -#define _memd8(a) (*((double*)(a))) -#define _memd8_const(a) (*((const double*)(a))) - -#define _amemd8(a) (*((double*)(a))) -#define _amemd8_const(a) (*((const double*)(a))) - -#define _mem8(a) (*((unsigned long long*)(a))) -#define _mem8_const(a) (*((const unsigned long long*)(a))) - -#define _mem4(a) (*((unsigned*)(a))) -#define _mem4_const(a) (*((const unsigned*)(a))) -#define _amem4_const(a) (*((const unsigned*)(a))) - -/* NOTE: To emulate a C6X properly you should define global variables - for your Xtensa with these names. Some of the emulation routines - will set these values. */ - -extern int _carry; -extern int _overflow; - -// Utility routines - - -#define TESTBIT(x,n) (((x) >> (n)) & 1) - -#define NSA_BITS 32 - -static inline unsigned int norm_shift_amt_U_and_non_U(int is_signed, int inp) { -int j=0, k=0; -int x=inp; -if (is_signed) { - /* Invert signed val if negative */ - x= TESTBIT(x,(NSA_BITS-1))? ~x: x; - x= (x&1)|(x<<1); /* Shift up to return count-1 */ - if (x ==0) - return NSA_BITS-1; - } - if (x ==0) - return NSA_BITS; - /* Now count leading zeros */ - for (j=0, k=NSA_BITS-1; k>=0; j++, k--) { - if (TESTBIT(x,k)) - return j; - } - return NSA_BITS; -} - - - -static inline long long -orig_L40_set( long long L40_var1) { - long long L40_var_out; - - L40_var_out = L40_var1 & 0x000000ffffffffffLL; - - if( L40_var1 & 0x8000000000LL) - L40_var_out = L40_var_out | 0xffffff0000000000LL; - - return( L40_var_out); -} - - - -static inline signed long long -util_saturate_n_no_state(signed long long t, int n) -{ - signed long long maxv, minv; - maxv = (1LL << (n-1)) - 1; - minv = (-1LL << (n-1)); - if (t > maxv) { - t = maxv; - } else if (t < minv) { - t = minv; - } - return t; -} - - -static inline signed long long -util_saturate_n_sgn(signed long long t, int n) -{ - signed long long result; - signed long long maxv, minv; - maxv = (1LL << (n-1)) - 1; - minv = (-1LL << (n-1)); - if (t > 0) { - result = maxv; - _overflow = 1; - } else if (t < 0) { - result = minv; - _overflow = 1; - } else { - result = 0; - } - return result; -} - - - - -/* well-behaved signed shift right (left on negative) with - saturation */ -static inline signed long long -util_shift_right_saturate_n(signed long long t, int shval, int n) -{ - /* n should be <= 62 */ - long long result; - - signed long long mask; - int actual_shift = shval; - long long shft = actual_shift > 0 ? actual_shift : -actual_shift; - - if (t == 0 || actual_shift == 0) - return t; - - if (actual_shift >= n) { - return (t < 0) ? -1 : 0; - } - if (actual_shift <= -n) { - return util_saturate_n_sgn(t, n); - } - if (actual_shift > 0) { - return t >> actual_shift; - } - /* actual_shift < 0. Check for saturation after shift. */ - mask = (-1LL << (n-shft-1)); - if (t > 0 && ((mask & t) != 0)) { - return util_saturate_n_sgn(t, n); - } - if (t < 0 && ((mask & t) != mask)) { - return util_saturate_n_sgn(t, n); - } - result = t << shft; - - return result; -} - - -/* Implemented c6x standard C compatibility functions (alphabetical - order) */ - - -static inline int _abs(int src1) { - if ((unsigned) src1 == (unsigned) 0x80000000) { - return 0x7fffffff; - } - return abs(src1); -} - - -static inline int _abs2(int src1) { - short s1[2],r[2]; - int result; - *((int*)s1) = src1; - if ((unsigned short) s1[1] == (unsigned short) 0x8000) r[1] = 0x7fff; - else r[1] = abs(s1[1]); - if ((unsigned short) s1[0] == (unsigned short) 0x8000) r[0] = 0x7fff; - else r[0] = abs(s1[0]); - result = *(int*)r; - return result; - } - - - - -static inline int _add2(int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] + s2[0]; - r[1] = s1[1] + s2[1]; - result = *(int*)r; - return result; -} - -static inline int _add4(int src1, int src2) { - char c1[4], c2[4], r[4]; - int result; - *((int*)c1) = src1; - *((int*)c2) = src2; - r[0] = c1[0] + c2[0]; - r[1] = c1[1] + c2[1]; - r[2] = c1[2] + c2[2]; - r[3] = c1[3] + c2[3]; - result = *(int*)r; - return result; -} - - - -static inline long long _addsub(unsigned int src1, unsigned int src2) -{ - - int res_lo; - int res_hi; - - res_hi = src1+src2; - res_lo = src1-src2; - return (((unsigned long long) res_hi) << 32) | ((unsigned int) res_lo) ; -} - - -static inline long long _addsub2(unsigned int src1, unsigned int src2) -{ - short s1[2], s2[2], ra[2], rs[2]; - int res_lo; - int res_hi; - - *((int*)s1) = src1; - *((int*)s2) = src2; - ra[0] = s1[0] + s2[0]; - ra[1] = s1[1] + s2[1]; - rs[0] = s1[0] - s2[0]; - rs[1] = s1[1] - s2[1]; - - res_hi = *(int*)ra; - res_lo = *(int*)rs; - return (((unsigned long long) res_hi) << 32) | ((unsigned int) res_lo) ; -} - - -static inline int _avg2(int src1, int src2) { - int low = (((int)1 + (short) src1 + (short) src2) >> 1) & 0XFFFF; - int high1 = src1 >> 16; - int high2 = src2 >> 16; - int high = ((high1 + high2 + 1) >> 1)<< 16; - return high | low; -} - - - -static inline unsigned int _avgu4(unsigned int src1, unsigned int src2) { -unsigned int res0 = ((src1 & 0xFF) + (src2 & 0xFF) + 1) >> 1; - unsigned int res1 = (((src1 & 0xFF00) >> 8) + ((src2 & 0xFF00) >> 8) + 1) >> 1; - unsigned int res2 = (((src1 & 0xFF0000) >> 16) + ((src2 & 0xFF0000) >> 16) + 1) >> 1; - unsigned int res3 = (((src1 & 0xFF000000) >> 24) + ((src2 & 0xFF000000) >> 24) + 1) >> 1; - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - - -static inline int TEN_popc (unsigned char b) -{ - int i, result = 0; - for (i = 0; i < 8; i++){ - if (b & 0x1) - result++; - b >>= 1; - } - return result; -} - -static inline unsigned int _bitc4(unsigned int src1) -{ - unsigned int res0 = TEN_popc(src1 & 0xFF); - unsigned int res1 = TEN_popc((src1 & 0xFF00) >> 8); - unsigned int res2 = TEN_popc((src1 & 0xFF0000) >> 16); - unsigned int res3 = TEN_popc((src1 & 0xFF000000) >> 24); - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - -static inline unsigned int _bitr(unsigned int src) { - int i; - unsigned r = 0; - for (i = 0; i< 32; ++i) { - r = r | (((src >> i) & 1)<<(31-i)); - } - return r; -} - - -static inline unsigned int _clr(unsigned int src2, int csta, int cstb) -{ - csta &= 0x1f; - cstb &= 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 & (~mask); - } -} - -static inline unsigned int _clrr(unsigned int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 & (~mask); - } -} - - - - -static inline int _cmpeq2(int src1, int src2) { - short s1[2], s2[2]; - int r0, r1; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r0 = s1[0] == s2[0] ? 1 : 0; - r1 = s1[1] == s2[1] ? 1 : 0; - result = (r1 << 1) | r0; - return result; -} - -static inline int _cmpeq4(int src1, int src2) { - char s1[4], s2[4]; - int r0, r1, r2, r3; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r0 = s1[0] == s2[0] ? 1 : 0; - r1 = s1[1] == s2[1] ? 1 : 0; - r2 = s1[2] == s2[2] ? 1 : 0; - r3 = s1[3] == s2[3] ? 1 : 0; - result = (r3 << 3) | (r2 << 2) | (r1 << 1) | r0; - return result; -} - - -static inline int _cmpgt2(int src1, int src2) { - short s1[2], s2[2]; - int r1, r0; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r0 = s1[0] > s2[0] ? 1 : 0; - r1 = s1[1] > s2[1] ? 1 : 0; - result = (r1<<1) | r0; - return result; -} - - -static inline unsigned int _cmpgtu4(unsigned int src1, unsigned int src2) { - unsigned int s1_0 = (src1 & 0xFF); - unsigned int s1_1 = (src1 & 0xFF00) >> 8; - unsigned int s1_2 = (src1 & 0xFF0000) >> 16; - unsigned int s1_3 = (src1 & 0xFF000000) >> 24; - - unsigned int s2_0 = (src2 & 0xFF); - unsigned int s2_1 = (src2 & 0xFF00) >> 8; - unsigned int s2_2 = (src2 & 0xFF0000) >> 16; - unsigned int s2_3 = (src2 & 0xFF000000) >> 24; - - unsigned int result = 0; - - if (s1_0 > s2_0) - result |= 0x1; - - if (s1_1 > s2_1) - result |= 0x2; - - if (s1_2 > s2_2) - result |= 0x4; - - if (s1_3 > s2_3) - result |= 0x8; - - return result; -} - - - - -static inline long long _ddotp4(unsigned int src1, unsigned int src2) { - unsigned int res0, res1; - short s1_0 = (src1 & 0xffff); - short s1_1 = (src1 & 0xfff0000) >> 16; - - unsigned short s2_0 = (src2 & 0xff); - unsigned short s2_1 = (src2 & 0xff00) >> 8; - unsigned short s2_2 = (src2 & 0xff0000) >> 16; - unsigned short s2_3 = (src2 & 0xff000000) >> 24; - - res0 = ((int)s1_0) * s2_0 + ((int)s1_1) * s2_1; - res1 = ((int)s1_0) * s2_2 + ((int)s1_1) * s2_3; - - return (res1 << 16) | res0; -} - - -static inline long long _ddotph2(long long src1_o_src1_e, unsigned int src2) -{ - - unsigned int src1_o = src1_o_src1_e >> 32; - unsigned int src1_e = src1_o_src1_e & 0xFFFFFFFF; - short ls1_o = src1_o & 0XFFFF; - short hs1_o = src1_o >> 16; -// short ls1_e = src1_e & 0XFFFF; - short hs1_e = src1_e >> 16; - short ls2 = src2 & 0XFFFF; - short hs2 = src2 >> 16; - - unsigned long long res_hi = ls2 * ls1_o + hs2 * hs1_o; - unsigned int res_lo = ls1_o * hs2 + hs1_e * ls2; - return (res_hi << 32) | res_lo; -} - - -static inline long long _ddotpl2(long long src1_o_src1_e, unsigned int src2) -{ - unsigned int src1_o = src1_o_src1_e >> 32; - unsigned int src1_e = src1_o_src1_e & 0xFFFFFFFF; - short ls1_o = src1_o & 0XFFFF; -// short hs1_o = src1_o >> 16; - short ls1_e = src1_e & 0XFFFF; - short hs1_e = src1_e >> 16; - short ls2 = src2 & 0XFFFF; - short hs2 = src2 >> 16; - - unsigned long long res_hi = ls2 * hs1_e + hs2 * ls1_o; - unsigned res_lo = hs1_e * hs2 + ls1_e * ls2; - return (res_hi << 32) | res_lo; -} - - -static inline unsigned int _deal(unsigned int src) -{ - int i; - unsigned short lo = 0, hi = 0; - for (i = 0; i < 32; i+= 2) { - lo >>= 1; - lo |= (src & 0x1) << 15; - src >>= 1; - hi >>= 1; - hi |= (src & 0x1) << 15; - src >>= 1; - } - return (hi << 16) | lo; -} - - -static inline long long _dmv(unsigned int src1, unsigned int src2) -{ - return (((long long) src1) << 32) | src2; -} - - -static inline int _dotpn2(int src1, int src2) { -short int s1_h = src1>>16; - short int s1_l = src1; - short int s2_h = src2>>16; - short int s2_l = src2; - return s1_h * s2_h - s1_l * s2_l; -} - - -static inline int _dotp2(int src1, int src2) { - short int s1_h = src1>>16; - short int s1_l = src1; - short int s2_h = src2>>16; - short int s2_l = src2; - return s1_h * s2_h + s1_l * s2_l; -} - - - -static inline int _dotpnrsu2(int src1, unsigned int src2) -{ - short ls1 = src1 & 0XFFFF; - unsigned short ls2 = src2 & 0XFFFF; - short hs1 = src1 >> 16; - unsigned short hs2 = src2 >> 16; - - int result = (((long long) (int)(hs1 * hs2)) - ((long long) (int)(ls1 * ls2)) + (1 << 15)) >> 16; - return result; -} - - - -static inline int _dotprsu2(int src1, unsigned int src2) { - short ls1 = src1 & 0XFFFF; - unsigned short ls2 = (src2 & 0XFFFF); - short hs1 = src1 >> 16; - unsigned short hs2 = (src2 >> 16); - - int result = (((long long) (int) (ls1 * ls2)) + ((long long) (int) (hs1 * hs2)) + (1LL << 15)) >> 16; - return result; -} - - - - - - - -static inline int _dotpsu4(int src1, unsigned int src2) { - int result; - signed char s1_0 = (src1 & 0xff); - signed char s1_1 = (src1 & 0xff00) >> 8; - signed char s1_2 = (src1 & 0xff0000) >> 16; - signed char s1_3 = (src1 & 0xff000000) >> 24; - - unsigned int s2_0 = (src2 & 0xff); - unsigned int s2_1 = (src2 & 0xff00) >> 8; - unsigned int s2_2 = (src2 & 0xff0000) >> 16; - unsigned int s2_3 = (src2 & 0xff000000) >> 24; - - result = s1_0 * s2_0 + s1_1 * s2_1 + s1_2 * s2_2 + s1_3 * s2_3; - return result; -} - - -static inline unsigned int _dotpu4(unsigned int src1, unsigned int src2) { - unsigned char v1_0 = src1 & 0xff; - unsigned char v1_1 = (src1>>8) & 0xff; - unsigned char v1_2 = (src1>>16) & 0xff; - unsigned char v1_3 = (src1>>24) & 0xff; - - unsigned char v2_0 = src2 & 0xff; - unsigned char v2_1 = (src2>>8) & 0xff; - unsigned char v2_2 = (src2>>16) & 0xff; - unsigned char v2_3 = (src2>>24) & 0xff; - - unsigned v = v1_0 * v2_0 + v1_1 * v2_1 + v1_2 * v2_2 + v1_3 * v2_3; - return v; -} - - -static inline long long _dpack2(unsigned int src1, unsigned int src2){ -unsigned short s1[2], s2[2]; -*((int*)s1) = src1; -*((int*)s2) = src2; -return ((unsigned long long) s1[1] << 48) | ((unsigned long long) s2[1] << 32) | ((unsigned long long) s1[0] << 16) | ((unsigned long long) s2[0]); -} - - -static inline long long _dpackx2(unsigned int src1, unsigned int src2){ -unsigned short s1[2], s2[2]; -*((int*)s1) = src1; -*((int*)s2) = src2; -return ((unsigned long long) s2[0] << 48) | ((unsigned long long) s1[1] << 32) | ((unsigned long long) s1[0] << 16) | ((unsigned long long) s2[1]); -} - -static inline int _ext(int src2, unsigned int csta, unsigned int cstb) -{ - return (src2 << csta) >> cstb; -} - -static inline int _extr(int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - return (src2 << csta) >> cstb; -} - -static inline unsigned int _extu(unsigned int src2, unsigned int csta, unsigned int cstb) -{ - return (src2 << csta) >> cstb; -} - -static inline unsigned int _extur(unsigned int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - return (src2 << csta) >> cstb; -} - - -static inline unsigned long long _hi(double src) { - unsigned long long v; - *(double*)&v = src; - return v>>32; -} - -static inline unsigned int _hill (long long src) -{ - return (unsigned int) (src >> 32); -} - - - -static inline double _itod(unsigned hi, unsigned lo) { - double v; - unsigned long long ll = ((((unsigned long long)(hi))<<32) | (unsigned long long)((unsigned)lo)); - *((unsigned long long *)&v) = ll; - return v; -} - - -static inline long long _itoll(unsigned int src2, unsigned int src1) -{ - return (((long long) src2) << 32) | src1; -} - - -static inline C6X_COMPAT_LONG40 _labs(C6X_COMPAT_LONG40 src2) -{ - long long maxv = (1LL << (40 -1)) - 1; - long long minv = (-1LL << (40 - 1)); - C6X_COMPAT_LONG40 lres = orig_L40_set(src2); - - lres = lres < 0 ? -lres : lres; - if (lres > maxv) lres = maxv; - else if (lres < minv) lres = minv; - - return lres; -} - - -static inline C6X_COMPAT_LONG40 _ldotp2(int src1, int src2) { -return (C6X_COMPAT_LONG40) _dotp2(src1, src2); -} - - -static inline unsigned int _lmbd(unsigned int src1, unsigned int src2) -{ - return norm_shift_amt_U_and_non_U(0,(((int) (src1 << 31)) >> 31) ^ (~src2)); -} - - -static inline unsigned int _lnorm(C6X_COMPAT_LONG40 src2) { -if (src2 == 0) - return 39; - else { - int hi = (int)(src2 >> 32); - int lo = (int)src2; - - - long long temp = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; - temp = orig_L40_set(temp); - - if (temp == 0) return 0; - int cnt = 0; - while (((temp >> 39) & 1) == ((temp >> 38) & 1)) { - temp <<= 1; - cnt++; - } - return cnt; - } -} - - -static inline unsigned long long _lo(double src) { - unsigned long long v; - *(double*)&v = src; - return v; -} - - -static inline unsigned int _loll (long long src) -{ - return (unsigned int) src; -} - - -static inline C6X_COMPAT_LONG40 _lsadd(int src1, C6X_COMPAT_LONG40 src2) -{ - long long maxv = (1LL << (40 -1)) - 1; - long long minv = (-1LL << (40 - 1)); - int hi = (int)(src2 >> 32); - int lo = (int)src2; - long long src2_int = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; - - - long long src2_int2 = orig_L40_set(src2_int); - - long long res = src1 + src2_int2; - - if (res > maxv) { - res = maxv; - _overflow = 1; - } - else if (res < minv) { - res = minv; - _overflow = 1; - } - - long long res2 = orig_L40_set(res); - - res2 = (signed char)(res2 >> 32); - - C6X_COMPAT_LONG40 lres = (((C6X_COMPAT_LONG40) res2) << 32) | ((unsigned int)res); - return lres; -} - - - -static inline int _max2 (int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] > s2[0] ? s1[0] : s2[0]; - r[1] = s1[1] > s2[1] ? s1[1] : s2[1]; - result = *(int*)r; - return result; -} - - - - - - -static inline unsigned int _maxu4(unsigned int src1, unsigned int src2) { - unsigned int res0, res1, res2, res3; - unsigned int s1_0 = res0 = (src1 & 0xFF); - unsigned int s1_1 = res1 = (src1 & 0xFF00) >> 8; - unsigned int s1_2 = res2 = (src1 & 0xFF0000) >> 16; - unsigned int s1_3 = res3 = (src1 & 0xFF000000) >> 24; - - unsigned int s2_0 = (src2 & 0xFF); - unsigned int s2_1 = (src2 & 0xFF00) >> 8; - unsigned int s2_2 = (src2 & 0xFF0000) >> 16; - unsigned int s2_3 = (src2 & 0xFF000000) >> 24; - -// unsigned int res = 0; - - if (s1_0 < s2_0) - res0 = s2_0; - - if (s1_1 < s2_1) - res1 = s2_1; - - if (s1_2 < s2_2) - res2 = s2_2; - - if (s1_3 < s2_3) - res3 = s2_3; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; - - -} - -static inline int _min2(int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] < s2[0] ? s1[0] : s2[0]; - r[1] = s1[1] < s2[1] ? s1[1] : s2[1]; - result = *(int*)r; - return result; -} - - -static inline unsigned int _minu4(unsigned int src1, unsigned int src2) { -unsigned int res0, res1, res2, res3; - unsigned int s1_0 = res0 = (src1 & 0xFF); - unsigned int s1_1 = res1 = (src1 & 0xFF00) >> 8; - unsigned int s1_2 = res2 = (src1 & 0xFF0000) >> 16; - unsigned int s1_3 = res3 = (src1 & 0xFF000000) >> 24; - - unsigned int s2_0 = (src2 & 0xFF); - unsigned int s2_1 = (src2 & 0xFF00) >> 8; - unsigned int s2_2 = (src2 & 0xFF0000) >> 16; - unsigned int s2_3 = (src2 & 0xFF000000) >> 24; - -// unsigned int res = 0; - - if (s1_0 > s2_0) - res0 = s2_0; - - if (s1_1 > s2_1) - res1 = s2_1; - - if (s1_2 > s2_2) - res2 = s2_2; - - if (s1_3 > s2_3) - res3 = s2_3; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - - -static inline int _mpy(int src1, int src2) { -return (short) src1 * (short) src2; -} - - -static inline int _mpyh(int src1, int src2) { -return (short) (src1 >> 16) * (short) (src2 >> 16); -} - - -static inline long long _mpyhill (int src1, int src2) -{ - short s1 = src1 >> 16; - return ((long long) src2) * s1; -} - -static inline int _mpyhir(int src1, int src2) -{ - short s1 = src1 >> 16; - long long result = ((long long) src2) * s1 + (1 << 14); - result >>= 15; - return result; -} - - -static inline int _mpyhl(int src1, int src2) { -return (short) (src1 >> 16) * (short) (src2); -} - -static inline unsigned int _mpyhlu(unsigned int src1, unsigned int src2) { -return (unsigned short) (src1 >> 16) * (unsigned short) (src2); -} - -static inline int _mpyhslu(int src1, unsigned int src2) { -return (short) (src1 >> 16) * (unsigned short) src2; -} - - -static inline int _mpyhsu(int src1, unsigned int src2) { -return (short) (src1 >>16) * (unsigned short) (src2 >>16); -} - - -static inline unsigned int _mpyhu(unsigned int src1, unsigned int src2) { -return (unsigned short) (src1 >>16) * (unsigned short) (src2 >> 16); -} - - -static inline int _mpyhuls(unsigned int src1, int src2) { -return (unsigned short) (src1 >>16) * (signed short) (src2); -} - - -static inline int _mpyhus(unsigned int src1, int src2) { -return (unsigned short) (src1 >> 16) * (short) (src2 >>16); -} - - - -static inline long long _mpyidll (int src1, int src2) -{ - return (long long) src1 * src2; -} - - -static inline int _mpylh(int src1, int src2) { -return (signed short) (src1 & 0xffff) * (signed short) (src2 >> 16); -} - -static inline unsigned int _mpylhu(unsigned int src1, unsigned int src2) { -return (unsigned short) src1 * (unsigned short) (src2 >> 16); -} - - -static inline long long _mpylill (int src1, int src2) -{ - return ((long long) src2) * ((short)src1); -} - - - -static inline int _mpylir(int src1, int src2) -{ - short s1 = src1; - long long result = ((long long) src2) * s1 + (1 << 14); - result >>= 15; - return result; -} - - -static inline int _mpylshu(int src1, unsigned int src2) { -return (short) src1 * (unsigned short) (src2 >> 16); -} - - -static inline int _mpyluhs(unsigned int src1, int src2) { -return (unsigned short) src1 * (short) (src2 >> 16); -} - - - -static inline int _mpysu(int src1, unsigned int src2) { -return (short) src1 * (unsigned short) src2; -} - - - -static inline long long _mpysu4ll (int src1, unsigned int src2) { - unsigned short res0, res1, res2, res3; - signed char s1_0 = (src1 & 0xff); - signed char s1_1 = (src1 & 0xff00) >> 8; - signed char s1_2 = (src1 & 0xff0000) >> 16; - signed char s1_3 = (src1 & 0xff000000) >> 24; - - unsigned short s2_0 = (src2 & 0xff); - unsigned short s2_1 = (src2 & 0xff00) >> 8; - unsigned short s2_2 = (src2 & 0xff0000) >> 16; - unsigned short s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 * s2_0; - res1 = s1_1 * s2_1; - res2 = s1_2 * s2_2; - res3 = s1_3 * s2_3; - - return (((unsigned long long) res3) << 48) - | (((unsigned long long) res2) << 32) - | (((unsigned long long) res1) << 16) - | res0; -} - -static inline unsigned int _mpyu(unsigned int src1, unsigned int src2) { - unsigned v = (unsigned short)src1 * (unsigned short)src2; - return v; -} - -static inline int _mpyus(unsigned int src1, int src2) { -return (unsigned short) src1 * (short) src2; -} - -static inline long long _mpyu4ll (unsigned int src1, unsigned int src2) { - unsigned short res0, res1, res2, res3; - unsigned char s1_0 = (src1 & 0xff); - unsigned char s1_1 = (src1 & 0xff00) >> 8; - unsigned char s1_2 = (src1 & 0xff0000) >> 16; - unsigned char s1_3 = (src1 & 0xff000000) >> 24; - - unsigned short s2_0 = (src2 & 0xff); - unsigned short s2_1 = (src2 & 0xff00) >> 8; - unsigned short s2_2 = (src2 & 0xff0000) >> 16; - unsigned short s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 * s2_0; - res1 = s1_1 * s2_1; - res2 = s1_2 * s2_2; - res3 = s1_3 * s2_3; - - return (((unsigned long long) res3) << 48) - | (((unsigned long long) res2) << 32) - | (((unsigned long long) res1) << 16) - | res0; -} - - -static inline long long _mpy2ir(unsigned int src1, unsigned int src2) -{ - if ((src1 == 0x8000) && (src2 == 0x80000000)) { - _overflow = 1; - return 0; - } - else { - short ls1 = src1 & 0xffff; - short hs1 = src1 >> 16; - unsigned long long hi = (((long long) hs1) * (int) src2 + (1 << 14)) >> 15; - unsigned long long lo = ((((long long) ls1) * (int) src2 + (1 << 14)) >> 15) & 0xFFFFFFFF; - return (hi << 32) | lo; - } -} - - -static inline long long _mpy2ll (int src1, int src2) { - short ls1 = src1 & 0xffff; - short hs1 = src1 >> 16; - short ls2 = src2 & 0xffff; - short hs2 = src2 >> 16; - - unsigned long long hi = hs1 * hs2; - unsigned long long lo = (ls1 * ls2) & 0xFFFFFFFF; - - return (hi << 32) | lo; - -} - - -static inline int _mpy32(int src1, int src2) -{ - return src1 * src2; -} - - -static inline long long _mpy32ll(int src1, int src2) -{ - return ((long long) src1) * src2; -} - -static inline long long _mpy32su(int src1, unsigned int src2) -{ - return ((long long) src1) * ((int) src2); -} - -static inline long long _mpy32u(unsigned int src1, unsigned int src2) -{ - return ((long long) ((int) src1)) * ((long long) ((int) src2)); -} - -static inline long long _mpy32us(unsigned int src1, int src2) -{ - return ((int) src1) * ((long long) src2); -} - -static inline int _mvd (int src2) -{ - return src2; -} - - -static inline unsigned int _norm(int src2) -{ - return norm_shift_amt_U_and_non_U(1,src2); -} - - -static inline unsigned int _pack2 (unsigned int src1, unsigned int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s2[0]; - r[1] = s1[0]; - result = *(int*)r; - return result; -} - - -static inline int _packh2 (unsigned int src1, unsigned int src2) { - unsigned v0 = src1 & 0xffff0000; - unsigned v1 = src2 >> 16; - unsigned v = v0|v1; - return v; - -} - -static inline unsigned int _packh4 (unsigned int src1, unsigned int src2) { - unsigned v3 = (src1 >> 24) & 0xff; - unsigned v2 = (src1 >> 8) & 0xff; - unsigned v1 = (src2 >> 24) & 0xff; - unsigned v0 = (src2 >> 8) & 0xff; - unsigned v = (v3<<24) | (v2<<16) | (v1 << 8) | v0; - return v; -} - -static inline unsigned int _packhl2 (unsigned int src1, unsigned int src2) { - unsigned v0 = src1 & 0xffff0000; - unsigned v1 = src2 & 0x0000ffff; - unsigned v = v0|v1; - return v; -} - -static inline unsigned int _packlh2 (unsigned int src1, unsigned int src2) { - unsigned v0 = src1 << 16; - unsigned v1 = (src2 >> 16) & 0xffff; - unsigned v = v0|v1; - return v; -} - - - - -static inline unsigned int _packl4 (unsigned int src1, unsigned int src2) { - unsigned v3 = (src1 >> 16) & 0xff; - unsigned v2 = (src1) & 0xff; - unsigned v1 = (src2 >> 16) & 0xff; - unsigned v0 = (src2) & 0xff; - unsigned v = (v3<<24) | (v2<<16) | (v1 << 8) | v0; - return v; -} - - - - -static inline unsigned int _rpack2 (unsigned int src1, unsigned int src2) { -int s1 = (int) src1; -int s2 = (int) src2; -s1 = util_shift_right_saturate_n (s1, -1, 32); -s2 = util_shift_right_saturate_n (s2, -1, 32); -return (unsigned int) (s1 & 0xffff0000) | (unsigned int) ((s2 & 0xffff0000) >>16); -} - - -static inline unsigned int _rotl (unsigned int src1, unsigned int src2) -{ - src2 &= 0x1f; - return (src1 << src2) | (src1 >> (32 - src2)); -} - - -static inline int _sadd(int src1, int src2) { -signed long long res; -signed long long maxv, minv; -maxv = (1LL << (32-1)) - 1; -minv = (-1LL << (32-1)); -res = (long long) src1 + (long long) src2; -if (res > maxv) { - res = maxv; - _overflow = 1; - } -else if (res < minv ) { - res = minv; - _overflow = 1; - } -return (int) res; -} - -static inline long long _saddsub(unsigned int src1, unsigned int src2) { -int radd; -signed long long rsub; - -signed long long maxv, minv; -maxv = (1LL << (32-1)) - 1; -minv = (-1LL << (32-1)); - -radd = (int) src1 + (int) src2; - -// saturate on subtract, not add - - -rsub = (long long) ((int) src1) - (long long) ((int) src2); -if (rsub > maxv) { - rsub = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (rsub < minv ) { - rsub = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -return (((unsigned long long) radd) << 32) | ( rsub & 0x00000000ffffffff ) ; -} - - - -static inline long long _saddsub2(unsigned int src1, unsigned int src2) { -signed int radd[2]; -signed int rsub[2]; -signed short s1[2], s2[2]; - -signed int maxv, minv; -maxv = (1L << (16-1)) - 1; -minv = (-1L << (16-1)); - -*((int*)s1) = src1; -*((int*)s2) = src2; - -radd[0] = (int) s1[0] + (int) s2[0]; -radd[1] = (int) s1[1] + (int) s2[1]; - -rsub[0] = (int) s1[0] - (int) s2[0]; -rsub[1] = (int) s1[1] - (int) s2[1]; - -if (radd[0] > maxv) { - radd[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (radd[0] < minv ) { - radd[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -if (radd[1] > maxv) { - radd[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (radd[1] < minv ) { - radd[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - - -if (rsub[0] > maxv) { - rsub[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (rsub[0] < minv ) { - rsub[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -if (rsub[1] > maxv) { - rsub[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (rsub[1] < minv ) { - rsub[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - - -return ((((unsigned long long) radd[1]) & 0x000000000000ffff) << 48) | - ((((unsigned long long) radd[0]) & 0x000000000000ffff) << 32) | - ((((unsigned long long) rsub[1]) & 0x000000000000ffff) << 16) | - ((((unsigned long long) rsub[0]) & 0x000000000000ffff)); -} - - - -static inline int _sadd2(int src1, int src2) { -signed short s1[2], s2[2]; -signed int r[2], maxv, minv; - -maxv = (1L << (16-1)) - 1; -minv = (-1L << (16-1)); - - -*((int*)s1) = src1; -*((int*)s2) = src2; - -r[0] = (int) s1[0] + (int) s2[0]; -r[1] = (int) s1[1] + (int) s2[1]; - -if (r[0] > maxv) { - r[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[0] < minv ) { - r[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -if (r[1] > maxv) { - r[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[1] < minv ) { - r[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -return ((r[1] & 0xffff) << 16 ) | (r[0] & 0xffff) ; -} - - -static inline int _saddus2(unsigned int src1, int src2) { -int res0, res1; - unsigned int s1_0 = (src1 & 0xffff); - unsigned int s1_1 = (src1 & 0xffff0000) >> 16; - - short s2_0 = (src2 & 0xffff); - short s2_1 = (src2 & 0xffff0000) >> 16; - - res0 = s1_0 + s2_0; - res1 = s1_1 + s2_1; - - if (res0 >= 0x10000) - res0 = 0xffff; - else if (res0 < 0) - res0 = 0; - - if (res1 >= 0x10000) - res1 = 0xffff; - else if (res1 < 0) - res1 = 0; - - return (res1 << 16) | res0; -} - - -static inline unsigned int _saddu4(unsigned int src1, unsigned int src2) { -unsigned int res0, res1, res2, res3; - unsigned int s1_0 = (src1 & 0xff); - unsigned int s1_1 = (src1 & 0xff00) >> 8; - unsigned int s1_2 = (src1 & 0xff0000) >> 16; - unsigned int s1_3 = (src1 & 0xff000000) >> 24; - - unsigned int s2_0 = (src2 & 0xff); - unsigned int s2_1 = (src2 & 0xff00) >> 8; - unsigned int s2_2 = (src2 & 0xff0000) >> 16; - unsigned int s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 + s2_0; - res1 = s1_1 + s2_1; - res2 = s1_2 + s2_2; - res3 = s1_3 + s2_3; - - if (res0 >= 0x100) - res0 = 0xff; - - if (res1 >= 0x100) - res1 = 0xff; - - if (res2 >= 0x100) - res2 = 0xff; - - if (res3 >= 0x100) - res3 = 0xff; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; - -} - - - -static inline int _sat(C6X_COMPAT_LONG40 src2) -{ - long long maxv = (1LL << (32-1)) - 1; - long long minv = (-1LL << (32-1)); - - int hi = (int)(src2 >> 32); - int lo = (int)src2; - long long temp = (unsigned long long)(unsigned)lo | (unsigned long long)hi << 32; - temp = orig_L40_set(temp); - - if (temp > maxv) { - temp = maxv; - _overflow = 1; - } - else if (temp < minv) { - temp = minv; - _overflow = 1; - } - return (int) temp; -} - -static inline unsigned int _set(unsigned int src2, unsigned int csta, unsigned int cstb) -{ - csta &= 0x1f; - cstb &= 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 | mask; - } -} - -static inline unsigned int _setr(unsigned int src2, int src1) -{ - unsigned int csta = (src1 >> 5) & 0x1f; - unsigned int cstb = src1 & 0x1f; - if (csta > cstb) - return src2; - else { - unsigned int mask = (((1 << (cstb - csta)) << 1) - 1) << csta; - return src2 | mask; - } -} - - -static inline unsigned int _shfl (unsigned int src2) -{ - unsigned short lo = src2; - unsigned short hi = src2 >> 16; - unsigned int result = 0; - int i; - for (i = 0; i < 32; i+= 2) { - result >>= 1; - result |= (lo & 0x1) << 31; - lo >>= 1; - result >>= 1; - result |= (hi & 0x1) << 31; - hi >>= 1; - } - return result; -} - -static inline long long _shfl3 (unsigned int src1, unsigned int src2) -{ - unsigned short lo = src2; - unsigned short hi = src1 >> 16; - unsigned short mid = src1; - unsigned long long result = 0; - int i; - for (i = 0; i < 32; i+= 2) { - result >>= 1; - result |= ((unsigned long long) (lo & 0x1)) << 47; - lo >>= 1; - result >>= 1; - result |= ((unsigned long long) (mid & 0x1)) << 47; - mid >>= 1; - result >>= 1; - result |= ((unsigned long long) (hi & 0x1)) << 47; - hi >>= 1; - } - return result; -} - - - -static inline unsigned int _shlmb (unsigned int src1, unsigned int src2) -{ - return (src2 << 8) | (src1 >> 24); -} - -static inline unsigned int _shrmb (unsigned int src1, unsigned int src2) -{ - return (src2 >> 8) | (src1 << 24); -} - - -static inline unsigned int _shru2 (unsigned int src1, unsigned int src2) { -unsigned short hs1 = src1 >> 16; - unsigned short ls1 = src1 & 0xFFFF; - hs1 >>= src2; - ls1 >>= src2; - return (hs1 << 16) | ls1; -} - - -static inline int _shr2 (int src1, unsigned int src2) { - short s1[2], result[2]; - *((int*)s1) = src1; - src2 = src2 & 31; - result[0] = (int)s1[0] >> src2; - result[1] = (int)s1[1] >> src2; - - return *(int*)result; -} - - -static inline int _smpy (int src1, int src2) { -unsigned long long result; -result = (((short) src1 * (short) src2) << 1); - -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline int _smpyh (int src1, int src2) { -unsigned long long result; -result = ((short) (src1 >> 16) * (short) (src2 >> 16)) << 1; -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline int _smpyhl (int src1, int src2) { -unsigned long long result; -result = ((short) (src1 >> 16) * (short) (src2)) << 1; -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline int _smpylh (int src1, int src2) { -unsigned long long result; -result = ((short) (src1) * (short) (src2 >> 16)) << 1; -if ((result & 0xffffffff) == 0x80000000){ - result = 0x7fffffff; - _overflow = 1; - } -return (int) (result); -} - -static inline long long _smpy2ll (int src1, int src2) { - short ls1 = src1 & 0XFFFF; - short hs1 = src1 >> 16; - short ls2 = src2 & 0XFFFF; - short hs2 = src2 >> 16; - - unsigned long long hi = (hs1 * hs2) << 1; - unsigned long long lo = ((ls1 * ls2) << 1) & 0xFFFFFFFF; - if ((hi & 0xffffffff) == 0x80000000){ - hi = 0x7fffffff; - _overflow = 1; - } - - if ((lo & 0xffffffff) == 0x80000000){ - lo = 0x7fffffff; - _overflow = 1; - } - - return (hi << 32) | lo; -} - - - - -static inline int _smpy32(int src1, int src2) -{ - long long res = (long long) src1 * src2; - res <<= 1; - res >>= 32; - return res; -} - -static inline unsigned char TEN_satu8 (short src) -{ - if (src > 0xff) - return 0xff; - else if (src < 0) - return 0; - else - return src; -} - -static inline int _spack2 (int src1, int src2) { -short s1 = (short) util_saturate_n_no_state(src1,16); -short s2 = (short) util_saturate_n_no_state(src2,16); -return ( (unsigned int) s1 << 16) | (((int) s2) & 0xFFFF); -} - - -static inline unsigned int _spacku4 (int src1, int src2) { - short lolo = src2; - short lohi = src2 >> 16; - short hilo = src1; - short hihi = src1 >> 16; - - lolo = TEN_satu8(lolo); - lohi = TEN_satu8(lohi); - hilo = TEN_satu8(hilo); - hihi = TEN_satu8(hihi); - - return (((unsigned int) hihi) << 24) | (((unsigned int) hilo) << 16) | (lohi << 8) | lolo; -} - - - -static inline int _sshl (int src1, unsigned int src2) { -short local2 = (short)(src2 & 0x7FFF); -return (int) util_shift_right_saturate_n(src1, -local2, 32); -} - - - - -static inline int _sshvl (int src2, int src1) { - short s1; - if (src1 > 31) - s1 = 31; - else if (src1 < -31) - s1 = -31; - else - s1 = src1; - - return (int) util_shift_right_saturate_n(src2, -s1, 32); -} - - - - - -static inline int _sshvr (int src2, int src1) { -short s1; - if (src1 > 31) - s1 = 31; - else if (src1 < -31) - s1 = -31; - else - s1 = src1; - return (int) util_shift_right_saturate_n(src2, s1, 32); -} - - - - -static inline int _ssub(int src1, int src2) { -signed long long res; -signed long long maxv, minv; -maxv = (1LL << (32-1)) - 1; -minv = (-1LL << (32-1)); -res = (long long) src1 - (long long) src2; -if (res > maxv) { - res = maxv; - _overflow = 1; - } -else if (res < minv ) { - res = minv; - _overflow = 1; - } -return (int) res; -} - -static inline int _ssub2(int src1, int src2) { -signed short s1[2], s2[2]; -signed int r[2], maxv, minv; - -maxv = (1L << (16-1)) - 1; -minv = (-1L << (16-1)); - - -*((int*)s1) = src1; -*((int*)s2) = src2; - -r[0] = (int) s1[0] - (int) s2[0]; -r[1] = (int) s1[1] - (int) s2[1]; - -if (r[0] > maxv) { - r[0] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[0] < minv ) { - r[0] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -if (r[1] > maxv) { - r[1] = maxv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } -else if (r[1] < minv ) { - r[1] = minv; - /* NOTE: TI c6x does NOT set the overflow register even if results saturate */ - /* _overflow = 1; */ - } - -return ((r[1] & 0xffff) << 16 ) | (r[0] & 0xffff) ; -} - - -static inline int _subabs4 (int src1, int src2) { - int res0, res1, res2, res3; - unsigned int s1_0 = (src1 & 0xff); - unsigned int s1_1 = (src1 & 0xff00) >> 8; - unsigned int s1_2 = (src1 & 0xff0000) >> 16; - unsigned int s1_3 = (src1 & 0xff000000) >> 24; - - unsigned int s2_0 = (src2 & 0xff); - unsigned int s2_1 = (src2 & 0xff00) >> 8; - unsigned int s2_2 = (src2 & 0xff0000) >> 16; - unsigned int s2_3 = (src2 & 0xff000000) >> 24; - - res0 = s1_0 - s2_0; - res1 = s1_1 - s2_1; - res2 = s1_2 - s2_2; - res3 = s1_3 - s2_3; - - if (res0 < 0) - res0 = -res0; - - if (res1 < 0) - res1 = -res1; - - if (res2 < 0) - res2 = -res2; - - if (res3 < 0) - res3 = -res3; - - return (res3 << 24) | (res2 << 16) | (res1 << 8) | res0; -} - - -static inline unsigned int _subc (unsigned int src1, unsigned int src2) -{ - if ( src1 >= src2) - return ((src1 - src2) << 1) + 1; - else - return src1 << 1; -} - - - -static inline int _sub2(int src1, int src2) { - short s1[2], s2[2], r[2]; - int result; - *((int*)s1) = src1; - *((int*)s2) = src2; - r[0] = s1[0] - s2[0]; - r[1] = s1[1] - s2[1]; - result = *(int*)r; - return result; -} - - -static inline int _sub4(int src1, int src2) { - char c1[4], c2[4], r[4]; - int result; - *((int*)c1) = src1; - *((int*)c2) = src2; - r[0] = c1[0] - c2[0]; - r[1] = c1[1] - c2[1]; - r[2] = c1[2] - c2[2]; - r[3] = c1[3] - c2[3]; - result = *(int*)r; - return result; -} - - -static inline int _swap4 (unsigned int src1) { - unsigned char v0 = src1; - unsigned char v1 = src1 >> 8; - unsigned char v2 = src1 >> 16; - unsigned char v3 = src1 >> 24; - unsigned v = v0<<8 | v1 | v2<<24 | v3<<16; - return v; -} - -static inline unsigned int _unpkhu4 (unsigned int src1) { - unsigned v0 = src1>>24; - unsigned v1 = (src1>>16) & 0xff; - return (v0<<16) | v1; -} - -static inline unsigned int _unpklu4 (unsigned int src1) { - unsigned v1 = (src1>>8) & 0xff; - unsigned v0 = (src1) & 0xff; - return (v1<<16) | v0; -} - - - - -static inline unsigned int _xpnd2 (unsigned int src1) { - int v0 = (src1 & 0x1) ? 0x0000ffff : 0x00000000; - int v1 = (src1 & 0x2) ? 0xffff0000 : 0x00000000; - return v0|v1; -} - -static inline unsigned int _xpnd4 (unsigned int src1) { - int v0 = (src1 & 0x1) ? 0x000000ff : 0x00000000; - int v1 = (src1 & 0x2) ? 0x0000ff00 : 0x00000000; - int v2 = (src1 & 0x4) ? 0x00ff0000 : 0x00000000; - int v3 = (src1 & 0x8) ? 0xff000000 : 0x00000000; - int r = v0|v1|v2|v3; - return r; -} - - - -// end of Implemented in alphabetical order - - -#endif /* __C6X_COMPAT__H */ diff --git a/src/arch/xtensa/include/xtensa/cacheasm.h b/src/arch/xtensa/include/xtensa/cacheasm.h deleted file mode 100644 index 9cb2c8fcc6b8..000000000000 --- a/src/arch/xtensa/include/xtensa/cacheasm.h +++ /dev/null @@ -1,962 +0,0 @@ -/* - * xtensa/cacheasm.h -- assembler-specific cache related definitions - * that depend on CORE configuration - * - * This file is logically part of xtensa/coreasm.h , - * but is kept separate for modularity / compilation-performance. - */ - -/* - * Copyright (c) 2001-2014 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. - */ - -#ifndef XTENSA_CACHEASM_H -#define XTENSA_CACHEASM_H - -#include <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/xtensa-xer.h> -#include <xtensa/xtensa-versions.h> - -/* - * This header file defines assembler macros of the form: - * <x>cache_<func> - * where <x> is 'i' or 'd' for instruction and data caches, - * and <func> indicates the function of the macro. - * - * The following functions <func> are defined, - * and apply only to the specified cache (I or D): - * - * reset - * Resets the cache. - * - * sync - * Makes sure any previous cache instructions have been completed; - * ie. makes sure any previous cache control operations - * have had full effect and been synchronized to memory. - * Eg. any invalidate completed [so as not to generate a hit], - * any writebacks or other pipelined writes written to memory, etc. - * - * invalidate_line (single cache line) - * invalidate_region (specified memory range) - * invalidate_all (entire cache) - * Invalidates all cache entries that cache - * data from the specified memory range. - * NOTE: locked entries are not invalidated. - * - * writeback_line (single cache line) - * writeback_region (specified memory range) - * writeback_all (entire cache) - * Writes back to memory all dirty cache entries - * that cache data from the specified memory range, - * and marks these entries as clean. - * NOTE: on some future implementations, this might - * also invalidate. - * NOTE: locked entries are written back, but never invalidated. - * NOTE: instruction caches never implement writeback. - * - * writeback_inv_line (single cache line) - * writeback_inv_region (specified memory range) - * writeback_inv_all (entire cache) - * Writes back to memory all dirty cache entries - * that cache data from the specified memory range, - * and invalidates these entries (including all clean - * cache entries that cache data from that range). - * NOTE: locked entries are written back but not invalidated. - * NOTE: instruction caches never implement writeback. - * - * lock_line (single cache line) - * lock_region (specified memory range) - * Prefetch and lock the specified memory range into cache. - * NOTE: if any part of the specified memory range cannot - * be locked, a Load/Store Error (for dcache) or Instruction - * Fetch Error (for icache) exception occurs. These macros don't - * do anything special (yet anyway) to handle this situation. - * - * unlock_line (single cache line) - * unlock_region (specified memory range) - * unlock_all (entire cache) - * Unlock cache entries that cache the specified memory range. - * Entries not already locked are unaffected. - * - * coherence_on - * coherence_off - * Turn off and on cache coherence - * - */ - - - -/*************************** GENERIC -- ALL CACHES ***************************/ - - -/* - * The following macros assume the following cache size/parameter limits - * in the current Xtensa core implementation: - * cache size: 1024 bytes minimum - * line size: 16 - 64 bytes - * way count: 1 - 4 - * - * Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4 - * Hence the assumption that each loop can execute four cache instructions. - * - * Correspondingly, the offset range of instructions is assumed able to cover - * four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for - * both hit and indexed cache instructions. Ie. these offsets are all - * valid: 0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64). - * This is true of all original cache instructions - * (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets - * of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2). - * This is also true of subsequent cache instructions - * (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets - * of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4). - * - * (Maximum cache size, currently 32k, doesn't affect the following macros. - * Cache ways > MMU min page size cause aliasing but that's another matter.) - */ - - - -/* - * Macro to apply an 'indexed' cache instruction to the entire cache. - * - * Parameters: - * cainst instruction/ that takes an address register parameter - * and an offset parameter (in range 0 .. 3*linesize). - * size size of cache in bytes - * linesize size of cache line in bytes (always power-of-2) - * assoc_or1 number of associativities (ways/sets) in cache - * if all sets affected by cainst, - * or 1 if only one set (or not all sets) of the cache - * is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]). - * aa, ab unique address registers (temporaries). - * awb set to other than a0 if wb type of instruction - * loopokay 1 allows use of zero-overhead loops, 0 does not - * immrange range (max value) of cainst's immediate offset parameter, in bytes - * (NOTE: macro assumes immrange allows power-of-2 number of lines) - */ - - .macro cache_index_all cainst, size, linesize, assoc_or1, aa, ab, loopokay, maxofs, awb=a0 - - // Number of indices in cache (lines per way): - .set .Lindices, (\size / (\linesize * \assoc_or1)) - // Number of indices processed per loop iteration (max 4): - .set .Lperloop, .Lindices - .ifgt .Lperloop - 4 - .set .Lperloop, 4 - .endif - // Also limit instructions per loop if cache line size exceeds immediate range: - .set .Lmaxperloop, (\maxofs / \linesize) + 1 - .ifgt .Lperloop - .Lmaxperloop - .set .Lperloop, .Lmaxperloop - .endif - // Avoid addi of 128 which takes two instructions (addmi,addi): - .ifeq .Lperloop*\linesize - 128 - .ifgt .Lperloop - 1 - .set .Lperloop, .Lperloop / 2 - .endif - .endif - - // \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst. - // XCHAL_ERRATUM_497 - don't execute using loop, to reduce the amount of added code - .ifne (\loopokay & XCHAL_HAVE_LOOPS && !XCHAL_ERRATUM_497) - - movi \aa, .Lindices / .Lperloop // number of loop iterations - // Possible improvement: need only loop if \aa > 1 ; - // however \aa == 1 is highly unlikely. - movi \ab, 0 // to iterate over cache - loop \aa, .Lend_cachex\@ - .set .Li, 0 ; .rept .Lperloop - \cainst \ab, .Li*\linesize - .set .Li, .Li+1 ; .endr - addi \ab, \ab, .Lperloop*\linesize // move to next line -.Lend_cachex\@: - - .else - - movi \aa, (\size / \assoc_or1) - // Possible improvement: need only loop if \aa > 1 ; - // however \aa == 1 is highly unlikely. - movi \ab, 0 // to iterate over cache - .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // don't use awb if set to a0 - movi \awb, 0 - .endif -.Lstart_cachex\@: - .set .Li, 0 ; .rept .Lperloop - \cainst \ab, .Li*\linesize - .set .Li, .Li+1 ; .endr - .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // do memw after 8 cainst wb instructions - addi \awb, \awb, .Lperloop - blti \awb, 8, .Lstart_memw\@ - memw - movi \awb, 0 -.Lstart_memw\@: - .endif - addi \ab, \ab, .Lperloop*\linesize // move to next line - bltu \ab, \aa, .Lstart_cachex\@ - .endif - - .endm - - -/* - * Macro to apply a 'hit' cache instruction to a memory region, - * ie. to any cache entries that cache a specified portion (region) of memory. - * Takes care of the unaligned cases, ie. may apply to one - * more cache line than $asize / lineSize if $aaddr is not aligned. - * - * - * Parameters are: - * cainst instruction/macro that takes an address register parameter - * and an offset parameter (currently always zero) - * and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.) - * linesize_log2 log2(size of cache line in bytes) - * addr register containing start address of region (clobbered) - * asize register containing size of the region in bytes (clobbered) - * askew unique register used as temporary - * awb unique register used as temporary for erratum 497. - * - * Note: A possible optimization to this macro is to apply the operation - * to the entire cache if the region exceeds the size of the cache - * by some empirically determined amount or factor. Some experimentation - * is required to determine the appropriate factors, which also need - * to be tunable if required. - */ - - .macro cache_hit_region cainst, linesize_log2, addr, asize, askew, awb=a0 - - // Make \asize the number of iterations: - extui \askew, \addr, 0, \linesize_log2 // get unalignment amount of \addr - add \asize, \asize, \askew // ... and add it to \asize - addi \asize, \asize, (1 << \linesize_log2) - 1 // round up! - srli \asize, \asize, \linesize_log2 - - // Iterate over region: - .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // don't use awb if set to a0 - movi \awb, 0 - .endif - floopnez \asize, cacheh\@ - \cainst \addr, 0 - .ifne ((\awb !=a0) & XCHAL_ERRATUM_497) // do memw after 8 cainst wb instructions - addi \awb, \awb, 1 - blti \awb, 8, .Lstart_memw\@ - memw - movi \awb, 0 -.Lstart_memw\@: - .endif - addi \addr, \addr, (1 << \linesize_log2) // move to next line - floopend \asize, cacheh\@ - .endm - - - - - -/*************************** INSTRUCTION CACHE ***************************/ - - -/* - * Reset/initialize the instruction cache by simply invalidating it: - * (need to unlock first also, if cache locking implemented): - * - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro icache_reset aa, ab, loopokay=0 - icache_unlock_all \aa, \ab, \loopokay - icache_invalidate_all \aa, \ab, \loopokay - .endm - - -/* - * Synchronize after an instruction cache operation, - * to be sure everything is in sync with memory as to be - * expected following any previous instruction cache control operations. - * - * Even if a config doesn't have caches, an isync is still needed - * when instructions in any memory are modified, whether by a loader - * or self-modifying code. Therefore, this macro always produces - * an isync, whether or not an icache is present. - * - * Parameters are: - * ar an address register (temporary) (currently unused, but may be used in future) - */ - .macro icache_sync ar - isync - .endm - - - -/* - * Invalidate a single line of the instruction cache. - * Parameters are: - * ar address register that contains (virtual) address to invalidate - * (may get clobbered in a future implementation, but not currently) - * offset (optional) offset to add to \ar to compute effective address to invalidate - * (note: some number of lsbits are ignored) - */ - .macro icache_invalidate_line ar, offset -#if XCHAL_ICACHE_SIZE > 0 - ihi \ar, \offset // invalidate icache line - icache_sync \ar -#endif - .endm - - - - -/* - * Invalidate instruction cache entries that cache a specified portion of memory. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro icache_invalidate_region astart, asize, ac -#if XCHAL_ICACHE_SIZE > 0 - // Instruction cache region invalidation: - cache_hit_region ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac - icache_sync \ac - // End of instruction cache region invalidation -#endif - .endm - - - -/* - * Invalidate entire instruction cache. - * - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro icache_invalidate_all aa, ab, loopokay=1 -#if XCHAL_ICACHE_SIZE > 0 - // Instruction cache invalidation: - cache_index_all iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab, \loopokay, 1020 - icache_sync \aa - // End of instruction cache invalidation -#endif - .endm - - - -/* - * Lock (prefetch & lock) a single line of the instruction cache. - * - * Parameters are: - * ar address register that contains (virtual) address to lock - * (may get clobbered in a future implementation, but not currently) - * offset offset to add to \ar to compute effective address to lock - * (note: some number of lsbits are ignored) - */ - .macro icache_lock_line ar, offset -#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE - ipfl \ar, \offset /* prefetch and lock icache line */ - icache_sync \ar -#endif - .endm - - - -/* - * Lock (prefetch & lock) a specified portion of memory into the instruction cache. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro icache_lock_region astart, asize, ac -#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE - // Instruction cache region lock: - cache_hit_region ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac - icache_sync \ac - // End of instruction cache region lock -#endif - .endm - - - -/* - * Unlock a single line of the instruction cache. - * - * Parameters are: - * ar address register that contains (virtual) address to unlock - * (may get clobbered in a future implementation, but not currently) - * offset offset to add to \ar to compute effective address to unlock - * (note: some number of lsbits are ignored) - */ - .macro icache_unlock_line ar, offset -#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE - ihu \ar, \offset /* unlock icache line */ - icache_sync \ar -#endif - .endm - - - -/* - * Unlock a specified portion of memory from the instruction cache. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro icache_unlock_region astart, asize, ac -#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE - // Instruction cache region unlock: - cache_hit_region ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac - icache_sync \ac - // End of instruction cache region unlock -#endif - .endm - - - -/* - * Unlock entire instruction cache. - * - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro icache_unlock_all aa, ab, loopokay=1 -#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE - // Instruction cache unlock: - cache_index_all iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240 - icache_sync \aa - // End of instruction cache unlock -#endif - .endm - - - - - -/*************************** DATA CACHE ***************************/ - - - -/* - * Reset/initialize the data cache by simply invalidating it - * (need to unlock first also, if cache locking implemented): - * - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro dcache_reset aa, ab, loopokay=0 - dcache_unlock_all \aa, \ab, \loopokay - dcache_invalidate_all \aa, \ab, \loopokay - .endm - - - - -/* - * Synchronize after a data cache operation, - * to be sure everything is in sync with memory as to be - * expected following any previous data cache control operations. - * - * Parameters are: - * ar an address register (temporary) (currently unused, but may be used in future) - */ - .macro dcache_sync ar, wbtype=0 -#if XCHAL_DCACHE_SIZE > 0 - // No synchronization is needed. - // (memw may be desired e.g. after writeback operation to help ensure subsequent - // external accesses are seen to follow that writeback, however that's outside - // the scope of this macro) - - //dsync - .ifne (\wbtype & XCHAL_ERRATUM_497) - memw - .endif -#endif - .endm - - - -/* - * Turn on cache coherence. - * - * WARNING: for RE-201x.x and later hardware, any interrupt that tries - * to change MEMCTL will see its changes dropped if the interrupt comes - * in the middle of this routine. If this might be an issue, call this - * routine with interrupts disabled. - * - * Parameters are: - * ar,at two scratch address registers (both clobbered) - */ - .macro cache_coherence_on ar at -#if XCHAL_DCACHE_IS_COHERENT -# if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0 - /* Have MEMCTL. Enable snoop responses. */ - rsr.memctl \ar - movi \at, MEMCTL_SNOOP_EN - or \ar, \ar, \at - wsr.memctl \ar -# elif XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MX - /* Opt into coherence for MX (for backward compatibility / testing). */ - movi \ar, 1 - movi \at, XER_CCON - wer \ar, \at - extw -# endif -#endif - .endm - - - -/* - * Turn off cache coherence. - * - * NOTE: this is generally preceded by emptying the cache; - * see xthal_cache_coherence_optout() in hal/coherence.c for details. - * - * WARNING: for RE-201x.x and later hardware, any interrupt that tries - * to change MEMCTL will see its changes dropped if the interrupt comes - * in the middle of this routine. If this might be an issue, call this - * routine with interrupts disabled. - * - * Parameters are: - * ar,at two scratch address registers (both clobbered) - */ - .macro cache_coherence_off ar at -#if XCHAL_DCACHE_IS_COHERENT -# if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0 - /* Have MEMCTL. Disable snoop responses. */ - rsr.memctl \ar - movi \at, ~MEMCTL_SNOOP_EN - and \ar, \ar, \at - wsr.memctl \ar -# elif XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MX - /* Opt out of coherence, for MX (for backward compatibility / testing). */ - extw - movi \at, 0 - movi \ar, XER_CCON - wer \at, \ar - extw -# endif -#endif - .endm - - - -/* - * Synchronize after a data store operation, - * to be sure the stored data is completely off the processor - * (and assuming there is no buffering outside the processor, - * that the data is in memory). This may be required to - * ensure that the processor's write buffers are emptied. - * A MEMW followed by a read guarantees this, by definition. - * We also try to make sure the read itself completes. - * - * Parameters are: - * ar an address register (temporary) - */ - .macro write_sync ar - memw // ensure previous memory accesses are complete prior to subsequent memory accesses - l32i \ar, sp, 0 // completing this read ensures any previous write has completed, because of MEMW - //slot - add \ar, \ar, \ar // use the result of the read to help ensure the read completes (in future architectures) - .endm - - -/* - * Invalidate a single line of the data cache. - * Parameters are: - * ar address register that contains (virtual) address to invalidate - * (may get clobbered in a future implementation, but not currently) - * offset (optional) offset to add to \ar to compute effective address to invalidate - * (note: some number of lsbits are ignored) - */ - .macro dcache_invalidate_line ar, offset -#if XCHAL_DCACHE_SIZE > 0 - dhi \ar, \offset - dcache_sync \ar -#endif - .endm - - - - - -/* - * Invalidate data cache entries that cache a specified portion of memory. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro dcache_invalidate_region astart, asize, ac -#if XCHAL_DCACHE_SIZE > 0 - // Data cache region invalidation: - cache_hit_region dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac - dcache_sync \ac - // End of data cache region invalidation -#endif - .endm - - - -/* - * Invalidate entire data cache. - * - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro dcache_invalidate_all aa, ab, loopokay=1 -#if XCHAL_DCACHE_SIZE > 0 - // Data cache invalidation: - cache_index_all dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab, \loopokay, 1020 - dcache_sync \aa - // End of data cache invalidation -#endif - .endm - - - -/* - * Writeback a single line of the data cache. - * Parameters are: - * ar address register that contains (virtual) address to writeback - * (may get clobbered in a future implementation, but not currently) - * offset offset to add to \ar to compute effective address to writeback - * (note: some number of lsbits are ignored) - */ - .macro dcache_writeback_line ar, offset -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK - dhwb \ar, \offset - dcache_sync \ar, wbtype=1 -#endif - .endm - - - -/* - * Writeback dirty data cache entries that cache a specified portion of memory. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro dcache_writeback_region astart, asize, ac, awb -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK - // Data cache region writeback: - cache_hit_region dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac, \awb - dcache_sync \ac, wbtype=1 - // End of data cache region writeback -#endif - .endm - - - -/* - * Writeback entire data cache. - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro dcache_writeback_all aa, ab, awb, loopokay=1 -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK - // Data cache writeback: - cache_index_all diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240, \awb, - dcache_sync \aa, wbtype=1 - // End of data cache writeback -#endif - .endm - - - -/* - * Writeback and invalidate a single line of the data cache. - * Parameters are: - * ar address register that contains (virtual) address to writeback and invalidate - * (may get clobbered in a future implementation, but not currently) - * offset offset to add to \ar to compute effective address to writeback and invalidate - * (note: some number of lsbits are ignored) - */ - .macro dcache_writeback_inv_line ar, offset -#if XCHAL_DCACHE_SIZE > 0 - dhwbi \ar, \offset /* writeback and invalidate dcache line */ - dcache_sync \ar, wbtype=1 -#endif - .endm - - - -/* - * Writeback and invalidate data cache entries that cache a specified portion of memory. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro dcache_writeback_inv_region astart, asize, ac, awb -#if XCHAL_DCACHE_SIZE > 0 - // Data cache region writeback and invalidate: - cache_hit_region dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac, \awb - dcache_sync \ac, wbtype=1 - // End of data cache region writeback and invalidate -#endif - .endm - - - -/* - * Writeback and invalidate entire data cache. - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro dcache_writeback_inv_all aa, ab, awb, loopokay=1 -#if XCHAL_DCACHE_SIZE > 0 - // Data cache writeback and invalidate: -#if XCHAL_DCACHE_IS_WRITEBACK - cache_index_all diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240, \awb - dcache_sync \aa, wbtype=1 -#else /*writeback*/ - // Data cache does not support writeback, so just invalidate: */ - dcache_invalidate_all \aa, \ab, \loopokay -#endif /*writeback*/ - // End of data cache writeback and invalidate -#endif - .endm - - - - -/* - * Lock (prefetch & lock) a single line of the data cache. - * - * Parameters are: - * ar address register that contains (virtual) address to lock - * (may get clobbered in a future implementation, but not currently) - * offset offset to add to \ar to compute effective address to lock - * (note: some number of lsbits are ignored) - */ - .macro dcache_lock_line ar, offset -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE - dpfl \ar, \offset /* prefetch and lock dcache line */ - dcache_sync \ar -#endif - .endm - - - -/* - * Lock (prefetch & lock) a specified portion of memory into the data cache. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro dcache_lock_region astart, asize, ac -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE - // Data cache region lock: - cache_hit_region dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac - dcache_sync \ac - // End of data cache region lock -#endif - .endm - - - -/* - * Unlock a single line of the data cache. - * - * Parameters are: - * ar address register that contains (virtual) address to unlock - * (may get clobbered in a future implementation, but not currently) - * offset offset to add to \ar to compute effective address to unlock - * (note: some number of lsbits are ignored) - */ - .macro dcache_unlock_line ar, offset -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE - dhu \ar, \offset /* unlock dcache line */ - dcache_sync \ar -#endif - .endm - - - -/* - * Unlock a specified portion of memory from the data cache. - * Parameters are: - * astart start address (register gets clobbered) - * asize size of the region in bytes (register gets clobbered) - * ac unique register used as temporary - */ - .macro dcache_unlock_region astart, asize, ac -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE - // Data cache region unlock: - cache_hit_region dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac - dcache_sync \ac - // End of data cache region unlock -#endif - .endm - - - -/* - * Unlock entire data cache. - * - * Parameters: - * aa, ab unique address registers (temporaries) - */ - .macro dcache_unlock_all aa, ab, loopokay=1 -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE - // Data cache unlock: - cache_index_all diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab, \loopokay, 240 - dcache_sync \aa - // End of data cache unlock -#endif - .endm - - - -/* - * Get the number of enabled icache ways. Note that this may - * be different from the value read from the MEMCTL register. - * - * Parameters: - * aa address register where value is returned - */ - .macro icache_get_ways aa -#if XCHAL_ICACHE_SIZE > 0 -#if XCHAL_HAVE_ICACHE_DYN_WAYS - // Read from MEMCTL and shift/mask - rsr.memctl \aa - extui \aa, \aa, MEMCTL_ICWU_SHIFT, MEMCTL_ICWU_BITS - blti \aa, XCHAL_ICACHE_WAYS, .Licgw - movi \aa, XCHAL_ICACHE_WAYS -.Licgw: -#else - // All ways are always enabled - movi \aa, XCHAL_ICACHE_WAYS -#endif -#else - // No icache - movi \aa, 0 -#endif - .endm - - - -/* - * Set the number of enabled icache ways. - * - * Parameters: - * aa address register specifying number of ways (trashed) - * ab,ac address register for scratch use (trashed) - */ - .macro icache_set_ways aa, ab, ac -#if XCHAL_ICACHE_SIZE > 0 -#if XCHAL_HAVE_ICACHE_DYN_WAYS - movi \ac, MEMCTL_ICWU_CLR_MASK // set up to clear bits 18-22 - rsr.memctl \ab - and \ab, \ab, \ac - movi \ac, MEMCTL_INV_EN // set bit 23 - slli \aa, \aa, MEMCTL_ICWU_SHIFT // move to right spot - or \ab, \ab, \aa - or \ab, \ab, \ac - wsr.memctl \ab - isync -#else - // All ways are always enabled -#endif -#else - // No icache -#endif - .endm - - - -/* - * Get the number of enabled dcache ways. Note that this may - * be different from the value read from the MEMCTL register. - * - * Parameters: - * aa address register where value is returned - */ - .macro dcache_get_ways aa -#if XCHAL_DCACHE_SIZE > 0 -#if XCHAL_HAVE_DCACHE_DYN_WAYS - // Read from MEMCTL and shift/mask - rsr.memctl \aa - extui \aa, \aa, MEMCTL_DCWU_SHIFT, MEMCTL_DCWU_BITS - blti \aa, XCHAL_DCACHE_WAYS, .Ldcgw - movi \aa, XCHAL_DCACHE_WAYS -.Ldcgw: -#else - // All ways are always enabled - movi \aa, XCHAL_DCACHE_WAYS -#endif -#else - // No dcache - movi \aa, 0 -#endif - .endm - - - -/* - * Set the number of enabled dcache ways. - * - * Parameters: - * aa address register specifying number of ways (trashed) - * ab,ac address register for scratch use (trashed) - */ - .macro dcache_set_ways aa, ab, ac -#if (XCHAL_DCACHE_SIZE > 0) && XCHAL_HAVE_DCACHE_DYN_WAYS - movi \ac, MEMCTL_DCWA_CLR_MASK // set up to clear bits 13-17 - rsr.memctl \ab - and \ab, \ab, \ac // clear ways allocatable - slli \ac, \aa, MEMCTL_DCWA_SHIFT - or \ab, \ab, \ac // set ways allocatable - wsr.memctl \ab -#if XCHAL_DCACHE_IS_WRITEBACK - // Check if the way count is increasing or decreasing - extui \ac, \ab, MEMCTL_DCWU_SHIFT, MEMCTL_DCWU_BITS // bits 8-12 - ways in use - bge \aa, \ac, .Ldsw3 // equal or increasing - slli \ab, \aa, XCHAL_DCACHE_LINEWIDTH + XCHAL_DCACHE_SETWIDTH // start way number - slli \ac, \ac, XCHAL_DCACHE_LINEWIDTH + XCHAL_DCACHE_SETWIDTH // end way number -.Ldsw1: - diwbui.p \ab // auto-increments ab - bge \ab, \ac, .Ldsw2 - beqz \ab, .Ldsw2 - j .Ldsw1 -.Ldsw2: - rsr.memctl \ab -#endif -.Ldsw3: - // No dirty data to write back, just set the new number of ways - movi \ac, MEMCTL_DCWU_CLR_MASK // set up to clear bits 8-12 - and \ab, \ab, \ac // clear ways in use - movi \ac, MEMCTL_INV_EN - or \ab, \ab, \ac // set bit 23 - slli \aa, \aa, MEMCTL_DCWU_SHIFT - or \ab, \ab, \aa // set ways in use - wsr.memctl \ab -#else - // No dcache or no way disable support -#endif - .endm - -#endif /*XTENSA_CACHEASM_H*/ - diff --git a/src/arch/xtensa/include/xtensa/cacheattrasm.h b/src/arch/xtensa/include/xtensa/cacheattrasm.h deleted file mode 100644 index 211803aedbf3..000000000000 --- a/src/arch/xtensa/include/xtensa/cacheattrasm.h +++ /dev/null @@ -1,436 +0,0 @@ -/* - * xtensa/cacheattrasm.h -- assembler-specific CACHEATTR register related definitions - * that depend on CORE configuration - * - * This file is logically part of xtensa/coreasm.h (or perhaps xtensa/cacheasm.h), - * but is kept separate for modularity / compilation-performance. - */ - -/* - * Copyright (c) 2001-2009 Tensilica 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. - */ - -#ifndef XTENSA_CACHEATTRASM_H -#define XTENSA_CACHEATTRASM_H - -#include <xtensa/coreasm.h> - -/* Determine whether cache attributes are controlled using eight 512MB entries: */ -#define XCHAL_CA_8X512 (XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \ - || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY)) - - -/* - * This header file defines assembler macros of the form: - * <x>cacheattr_<func> - * where: - * <x> is 'i', 'd' or absent for instruction, data - * or both caches; and - * <func> indicates the function of the macro. - * - * The following functions are defined: - * - * icacheattr_get - * Reads I-cache CACHEATTR into a2 (clobbers a3-a5). - * - * dcacheattr_get - * Reads D-cache CACHEATTR into a2 (clobbers a3-a5). - * (Note: for configs with a real CACHEATTR register, the - * above two macros are identical.) - * - * cacheattr_set - * Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered). - * Works even when changing one's own code's attributes. - * - * icacheattr_is_enabled label - * Branches to \label if I-cache appears to have been enabled - * (eg. if CACHEATTR contains a cache-enabled attribute). - * (clobbers a2-a5,SAR) - * - * dcacheattr_is_enabled label - * Branches to \label if D-cache appears to have been enabled - * (eg. if CACHEATTR contains a cache-enabled attribute). - * (clobbers a2-a5,SAR) - * - * cacheattr_is_enabled label - * Branches to \label if either I-cache or D-cache appears to have been enabled - * (eg. if CACHEATTR contains a cache-enabled attribute). - * (clobbers a2-a5,SAR) - * - * The following macros are only defined under certain conditions: - * - * icacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR) - * Writes I-cache CACHEATTR from a2 (a3-a8 clobbered). - * - * dcacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR) - * Writes D-cache CACHEATTR from a2 (a3-a8 clobbered). - */ - - - -/*************************** GENERIC -- ALL CACHES ***************************/ - -/* - * _cacheattr_get - * - * (Internal macro.) - * Returns value of CACHEATTR register (or closest equivalent) in a2. - * - * Entry: - * (none) - * Exit: - * a2 value read from CACHEATTR - * a3-a5 clobbered (temporaries) - */ - .macro _cacheattr_get tlb -#if XCHAL_HAVE_CACHEATTR - rsr.cacheattr a2 -#elif XCHAL_CA_8X512 - // We have a config that "mimics" CACHEATTR using a simplified - // "MMU" composed of a single statically-mapped way. - // DTLB and ITLB are independent, so there's no single - // cache attribute that can describe both. So for now - // just return the DTLB state. - movi a5, 0xE0000000 - movi a2, 0 - movi a3, XCHAL_SPANNING_WAY -1: add a3, a3, a5 // next segment - r&tlb&1 a4, a3 // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0 - dsync // interlock??? - slli a2, a2, 4 - extui a4, a4, 0, 4 // extract CA - or a2, a2, a4 - bgeui a3, 16, 1b -#else - // This macro isn't applicable to arbitrary MMU configurations. - // Just return zero. - movi a2, 0 -#endif - .endm - - .macro icacheattr_get - _cacheattr_get itlb - .endm - - .macro dcacheattr_get - _cacheattr_get dtlb - .endm - - -/* Default (powerup/reset) value of CACHEATTR, - all BYPASS mode (ie. disabled/bypassed caches): */ -#if XCHAL_HAVE_PTP_MMU -# define XCHAL_CACHEATTR_ALL_BYPASS 0x33333333 -#else -# define XCHAL_CACHEATTR_ALL_BYPASS 0x22222222 -#endif - -#if XCHAL_CA_8X512 - -#if XCHAL_HAVE_PTP_MMU -# define XCHAL_FCA_ENAMASK 0x0AA0 /* bitmap of fetch attributes that require enabled icache */ -# define XCHAL_LCA_ENAMASK 0x0FF0 /* bitmap of load attributes that require enabled dcache */ -# define XCHAL_SCA_ENAMASK 0x0CC0 /* bitmap of store attributes that require enabled dcache */ -#else -# define XCHAL_FCA_ENAMASK 0x003A /* bitmap of fetch attributes that require enabled icache */ -# define XCHAL_LCA_ENAMASK 0x0033 /* bitmap of load attributes that require enabled dcache */ -# define XCHAL_SCA_ENAMASK 0x0033 /* bitmap of store attributes that require enabled dcache */ -#endif -#define XCHAL_LSCA_ENAMASK (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK) /* l/s attrs requiring enabled dcache */ -#define XCHAL_ALLCA_ENAMASK (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK) /* all attrs requiring enabled caches */ - -/* - * _cacheattr_is_enabled - * - * (Internal macro.) - * Branches to \label if CACHEATTR in a2 indicates an enabled - * cache, using mask in a3. - * - * Parameters: - * label where to branch to if cache is enabled - * Entry: - * a2 contains CACHEATTR value used to determine whether - * caches are enabled - * a3 16-bit constant where each bit correspond to - * one of the 16 possible CA values (in a CACHEATTR mask); - * CA values that indicate the cache is enabled - * have their corresponding bit set in this mask - * (eg. use XCHAL_xCA_ENAMASK , above) - * Exit: - * a2,a4,a5 clobbered - * SAR clobbered - */ - .macro _cacheattr_is_enabled label - movi a4, 8 // loop 8 times -.Lcaife\@: - extui a5, a2, 0, 4 // get CA nibble - ssr a5 // index into mask according to CA... - srl a5, a3 // ...and get CA's mask bit in a5 bit 0 - bbsi.l a5, 0, \label // if CA indicates cache enabled, jump to label - srli a2, a2, 4 // next nibble - addi a4, a4, -1 - bnez a4, .Lcaife\@ // loop for each nibble - .endm - -#else /* XCHAL_CA_8X512 */ - .macro _cacheattr_is_enabled label - j \label // macro not applicable, assume caches always enabled - .endm -#endif /* XCHAL_CA_8X512 */ - - - -/* - * icacheattr_is_enabled - * - * Branches to \label if I-cache is enabled. - * - * Parameters: - * label where to branch to if icache is enabled - * Entry: - * (none) - * Exit: - * a2-a5, SAR clobbered (temporaries) - */ - .macro icacheattr_is_enabled label -#if XCHAL_CA_8X512 - icacheattr_get - movi a3, XCHAL_FCA_ENAMASK -#endif - _cacheattr_is_enabled \label - .endm - -/* - * dcacheattr_is_enabled - * - * Branches to \label if D-cache is enabled. - * - * Parameters: - * label where to branch to if dcache is enabled - * Entry: - * (none) - * Exit: - * a2-a5, SAR clobbered (temporaries) - */ - .macro dcacheattr_is_enabled label -#if XCHAL_CA_8X512 - dcacheattr_get - movi a3, XCHAL_LSCA_ENAMASK -#endif - _cacheattr_is_enabled \label - .endm - -/* - * cacheattr_is_enabled - * - * Branches to \label if either I-cache or D-cache is enabled. - * - * Parameters: - * label where to branch to if a cache is enabled - * Entry: - * (none) - * Exit: - * a2-a5, SAR clobbered (temporaries) - */ - .macro cacheattr_is_enabled label -#if XCHAL_HAVE_CACHEATTR - rsr.cacheattr a2 - movi a3, XCHAL_ALLCA_ENAMASK -#elif XCHAL_CA_8X512 - icacheattr_get - movi a3, XCHAL_FCA_ENAMASK - _cacheattr_is_enabled \label - dcacheattr_get - movi a3, XCHAL_LSCA_ENAMASK -#endif - _cacheattr_is_enabled \label - .endm - - - -/* - * The ISA does not have a defined way to change the - * instruction cache attributes of the running code, - * ie. of the memory area that encloses the current PC. - * However, each micro-architecture (or class of - * configurations within a micro-architecture) - * provides a way to deal with this issue. - * - * Here are a few macros used to implement the relevant - * approach taken. - */ - -#if XCHAL_CA_8X512 && !XCHAL_HAVE_CACHEATTR - // We have a config that "mimics" CACHEATTR using a simplified - // "MMU" composed of a single statically-mapped way. - -/* - * icacheattr_set - * - * Entry: - * a2 cacheattr value to set - * Exit: - * a2 unchanged - * a3-a8 clobbered (temporaries) - */ - .macro icacheattr_set - - movi a5, 0xE0000000 // mask of upper 3 bits - movi a6, 3f // PC where ITLB is set - movi a3, XCHAL_SPANNING_WAY // start at region 0 (0 .. 7) - mov a7, a2 // copy a2 so it doesn't get clobbered - and a6, a6, a5 // upper 3 bits of local PC area - j 3f - - // Use micro-architecture specific method. - // The following 4-instruction sequence is aligned such that - // it all fits within a single I-cache line. Sixteen byte - // alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE - // actually causes problems because that can be greater than - // the alignment of the reset vector, where this macro is often - // invoked, which would cause the linker to align the reset - // vector code away from the reset vector!!). - .begin no-transform - .align 16 /*XCHAL_ICACHE_LINESIZE*/ -1: witlb a4, a3 // write wired PTE (CA, no PPN) of 512MB segment to ITLB - isync - .end no-transform - nop - nop - - sub a3, a3, a5 // next segment (add 0x20000000) - bltui a3, 16, 4f // done? - - // Note that in the WITLB loop, we don't do any load/stores - // (may not be an issue here, but it is important in the DTLB case). -2: srli a7, a7, 4 // next CA -3: -# if XCHAL_HAVE_MIMIC_CACHEATTR - extui a4, a7, 0, 4 // extract CA to set -# else /* have translation, preserve it: */ - ritlb1 a8, a3 // get current PPN+CA of segment - //dsync // interlock??? - extui a4, a7, 0, 4 // extract CA to set - srli a8, a8, 4 // clear CA but keep PPN ... - slli a8, a8, 4 // ... - add a4, a4, a8 // combine new CA with PPN to preserve -# endif - beq a3, a6, 1b // current PC's region? if so, do it in a safe way - witlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to ITLB - sub a3, a3, a5 // next segment (add 0x20000000) - bgeui a3, 16, 2b - isync // make sure all ifetch changes take effect -4: - .endm // icacheattr_set - - -/* - * dcacheattr_set - * - * Entry: - * a2 cacheattr value to set - * Exit: - * a2 unchanged - * a3-a8 clobbered (temporaries) - */ - - .macro dcacheattr_set - - movi a5, 0xE0000000 // mask of upper 3 bits - movi a3, XCHAL_SPANNING_WAY // start at region 0 (0 .. 7) - mov a7, a2 // copy a2 so it doesn't get clobbered - // Note that in the WDTLB loop, we don't do any load/stores -2: // (including implicit l32r via movi) because it isn't safe. -# if XCHAL_HAVE_MIMIC_CACHEATTR - extui a4, a7, 0, 4 // extract CA to set -# else /* have translation, preserve it: */ - rdtlb1 a8, a3 // get current PPN+CA of segment - //dsync // interlock??? - extui a4, a7, 0, 4 // extract CA to set - srli a8, a8, 4 // clear CA but keep PPN ... - slli a8, a8, 4 // ... - add a4, a4, a8 // combine new CA with PPN to preserve -# endif - wdtlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to DTLB - sub a3, a3, a5 // next segment (add 0x20000000) - srli a7, a7, 4 // next CA - bgeui a3, 16, 2b - dsync // make sure all data path changes take effect - .endm // dcacheattr_set - -#endif /* XCHAL_CA_8X512 && !XCHAL_HAVE_CACHEATTR */ - - - -/* - * cacheattr_set - * - * Macro that sets the current CACHEATTR safely - * (both i and d) according to the current contents of a2. - * It works even when changing the cache attributes of - * the currently running code. - * - * Entry: - * a2 cacheattr value to set - * Exit: - * a2 unchanged - * a3-a8 clobbered (temporaries) - */ - .macro cacheattr_set - -#if XCHAL_HAVE_CACHEATTR -# if XCHAL_ICACHE_LINESIZE < 4 - // No i-cache, so can always safely write to CACHEATTR: - wsr.cacheattr a2 -# else - // The Athens micro-architecture, when using the old - // exception architecture option (ie. with the CACHEATTR register) - // allows changing the cache attributes of the running code - // using the following exact sequence aligned to be within - // an instruction cache line. (NOTE: using XCHAL_ICACHE_LINESIZE - // alignment actually causes problems because that can be greater - // than the alignment of the reset vector, where this macro is often - // invoked, which would cause the linker to align the reset - // vector code away from the reset vector!!). - j 1f - .begin no-transform - .align 16 /*XCHAL_ICACHE_LINESIZE*/ // align to within an I-cache line -1: wsr.cacheattr a2 - isync - .end no-transform - nop - nop -# endif -#elif XCHAL_CA_8X512 - // DTLB and ITLB are independent, but to keep semantics - // of this macro we simply write to both. - icacheattr_set - dcacheattr_set -#else - // This macro isn't applicable to arbitrary MMU configurations. - // Do nothing in this case. -#endif - .endm - - -#endif /*XTENSA_CACHEATTRASM_H*/ - diff --git a/src/arch/xtensa/include/xtensa/config/core.h b/src/arch/xtensa/include/xtensa/config/core.h deleted file mode 100644 index f5bb44faf2ab..000000000000 --- a/src/arch/xtensa/include/xtensa/config/core.h +++ /dev/null @@ -1,1408 +0,0 @@ -/* - * xtensa/config/core.h -- HAL definitions dependent on CORE configuration - * - * This header file is sometimes referred to as the "compile-time HAL" or CHAL. - * It pulls definitions tailored for a specific Xtensa processor configuration. - * - * Sources for binaries meant to be configuration-independent generally avoid - * including this file (they may use the configuration-specific HAL library). - * It is normal for the HAL library source itself to include this file. - */ - -/* - * Copyright (c) 2005-2015 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. - */ - - -#ifndef XTENSA_CONFIG_CORE_H -#define XTENSA_CONFIG_CORE_H - -/* CONFIGURATION INDEPENDENT DEFINITIONS: */ -#ifdef __XTENSA__ -#include <xtensa/hal.h> -#include <xtensa/xtensa-versions.h> -#else -#include "../hal.h" -#include "../xtensa-versions.h" -#endif - -/* CONFIGURATION SPECIFIC DEFINITIONS: */ -#ifdef __XTENSA__ -#include <xtensa/config/core-isa.h> -#include <xtensa/config/core-matmap.h> -#include <xtensa/config/tie.h> -#else -#include "core-isa.h" -#include "core-matmap.h" -#include "tie.h" -#endif - -#if defined (_ASMLANGUAGE) || defined (__ASSEMBLER__) -#ifdef __XTENSA__ -#include <xtensa/config/tie-asm.h> -#else -#include "tie-asm.h" -#endif -#endif /*_ASMLANGUAGE or __ASSEMBLER__*/ - - -/*---------------------------------------------------------------------- - GENERAL - ----------------------------------------------------------------------*/ - -/* - * Separators for macros that expand into arrays. - * These can be predefined by files that #include this one, - * when different separators are required. - */ -/* Element separator for macros that expand into 1-dimensional arrays: */ -#ifndef XCHAL_SEP -#define XCHAL_SEP , -#endif -/* Array separator for macros that expand into 2-dimensional arrays: */ -#ifndef XCHAL_SEP2 -#define XCHAL_SEP2 },{ -#endif - - -/*---------------------------------------------------------------------- - ERRATA - ----------------------------------------------------------------------*/ - -/* - * Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1; - * relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled): - */ -#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN (XCHAL_HAVE_XEA1 && \ - (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \ - || XCHAL_HW_RELEASE_AT(1050,0))) -/* - * Erratum 453 present in RE-2013.2 up to RF-2014.0, fixed in RF-2014.1. - * Applies to specific set of configuration options. - * Part of the workaround is to add ISYNC at certain points in the code. - * The workaround gated by this macro can be disabled if not needed, e.g. if - * zero-overhead loop buffer will be disabled, by defining _NO_ERRATUM_453. - */ -#if ( XCHAL_HW_MAX_VERSION >= XTENSA_HWVERSION_RE_2013_2 && \ - XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RF_2014_0 && \ - XCHAL_ICACHE_SIZE != 0 && XCHAL_HAVE_PIF /*covers also AXI/AHB*/ && \ - XCHAL_HAVE_LOOPS && XCHAL_LOOP_BUFFER_SIZE != 0 && \ - XCHAL_CLOCK_GATING_GLOBAL && !defined(_NO_ERRATUM_453) ) -#define XCHAL_ERRATUM_453 1 -#else -#define XCHAL_ERRATUM_453 0 -#endif - -/* - * Erratum 497 present in RE-2012.2 up to RG/RF-2015.2 - * Applies to specific set of configuration options. - * Workaround is to add MEMWs after at most 8 cache WB instructions - */ -#if ( ((XCHAL_HW_MAX_VERSION >= XTENSA_HWVERSION_RE_2012_0 && \ - XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RF_2015_2) || \ - (XCHAL_HW_MAX_VERSION >= XTENSA_HWVERSION_RG_2015_0 && \ - XCHAL_HW_MIN_VERSION <= XTENSA_HWVERSION_RG_2015_2) \ - ) && \ - XCHAL_DCACHE_IS_WRITEBACK && \ - XCHAL_HAVE_AXI && \ - XCHAL_HAVE_PIF_WR_RESP && \ - XCHAL_HAVE_PIF_REQ_ATTR && !defined(_NO_ERRATUM_497) \ - ) -#define XCHAL_ERRATUM_497 1 -#else -#define XCHAL_ERRATUM_497 0 -#endif - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#if XCHAL_HAVE_BE -# define XCHAL_HAVE_LE 0 -# define XCHAL_MEMORY_ORDER XTHAL_BIGENDIAN -#else -# define XCHAL_HAVE_LE 1 -# define XCHAL_MEMORY_ORDER XTHAL_LITTLEENDIAN -#endif - - - -/*---------------------------------------------------------------------- - INTERRUPTS - ----------------------------------------------------------------------*/ - -/* Indexing macros: */ -#define _XCHAL_INTLEVEL_MASK(n) XCHAL_INTLEVEL ## n ## _MASK -#define XCHAL_INTLEVEL_MASK(n) _XCHAL_INTLEVEL_MASK(n) /* n = 0 .. 15 */ -#define _XCHAL_INTLEVEL_ANDBELOWMASK(n) XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK -#define XCHAL_INTLEVEL_ANDBELOW_MASK(n) _XCHAL_INTLEVEL_ANDBELOWMASK(n) /* n = 0 .. 15 */ -#define _XCHAL_INTLEVEL_NUM(n) XCHAL_INTLEVEL ## n ## _NUM -#define XCHAL_INTLEVEL_NUM(n) _XCHAL_INTLEVEL_NUM(n) /* n = 0 .. 15 */ -#define _XCHAL_INT_LEVEL(n) XCHAL_INT ## n ## _LEVEL -#define XCHAL_INT_LEVEL(n) _XCHAL_INT_LEVEL(n) /* n = 0 .. 31 */ -#define _XCHAL_INT_TYPE(n) XCHAL_INT ## n ## _TYPE -#define XCHAL_INT_TYPE(n) _XCHAL_INT_TYPE(n) /* n = 0 .. 31 */ -#define _XCHAL_TIMER_INTERRUPT(n) XCHAL_TIMER ## n ## _INTERRUPT -#define XCHAL_TIMER_INTERRUPT(n) _XCHAL_TIMER_INTERRUPT(n) /* n = 0 .. 3 */ - - -#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS XCHAL_HAVE_HIGHPRI_INTERRUPTS -#define XCHAL_NUM_LOWPRI_LEVELS 1 /* number of low-priority interrupt levels (always 1) */ -#define XCHAL_FIRST_HIGHPRI_LEVEL (XCHAL_NUM_LOWPRI_LEVELS+1) /* level of first high-priority interrupt (always 2) */ -/* Note: 1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15 */ - -/* These values are constant for existing Xtensa processor implementations: */ -#define XCHAL_INTLEVEL0_MASK 0x00000000 -#define XCHAL_INTLEVEL8_MASK 0x00000000 -#define XCHAL_INTLEVEL9_MASK 0x00000000 -#define XCHAL_INTLEVEL10_MASK 0x00000000 -#define XCHAL_INTLEVEL11_MASK 0x00000000 -#define XCHAL_INTLEVEL12_MASK 0x00000000 -#define XCHAL_INTLEVEL13_MASK 0x00000000 -#define XCHAL_INTLEVEL14_MASK 0x00000000 -#define XCHAL_INTLEVEL15_MASK 0x00000000 - -/* Array of masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL_MASKS XCHAL_INTLEVEL0_MASK \ - XCHAL_SEP XCHAL_INTLEVEL1_MASK \ - XCHAL_SEP XCHAL_INTLEVEL2_MASK \ - XCHAL_SEP XCHAL_INTLEVEL3_MASK \ - XCHAL_SEP XCHAL_INTLEVEL4_MASK \ - XCHAL_SEP XCHAL_INTLEVEL5_MASK \ - XCHAL_SEP XCHAL_INTLEVEL6_MASK \ - XCHAL_SEP XCHAL_INTLEVEL7_MASK \ - XCHAL_SEP XCHAL_INTLEVEL8_MASK \ - XCHAL_SEP XCHAL_INTLEVEL9_MASK \ - XCHAL_SEP XCHAL_INTLEVEL10_MASK \ - XCHAL_SEP XCHAL_INTLEVEL11_MASK \ - XCHAL_SEP XCHAL_INTLEVEL12_MASK \ - XCHAL_SEP XCHAL_INTLEVEL13_MASK \ - XCHAL_SEP XCHAL_INTLEVEL14_MASK \ - XCHAL_SEP XCHAL_INTLEVEL15_MASK - -/* These values are constant for existing Xtensa processor implementations: */ -#define XCHAL_INTLEVEL0_ANDBELOW_MASK 0x00000000 -#define XCHAL_INTLEVEL8_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL9_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL10_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL11_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL12_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL13_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL14_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK -#define XCHAL_INTLEVEL15_ANDBELOW_MASK XCHAL_INTLEVEL7_ANDBELOW_MASK - -/* Mask of all low-priority interrupts: */ -#define XCHAL_LOWPRI_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK - -/* Mask of all interrupts masked by PS.EXCM (or CEXCM): */ -#define XCHAL_EXCM_MASK XCHAL_INTLEVEL_ANDBELOW_MASK(XCHAL_EXCM_LEVEL) - -/* Array of masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL_ANDBELOW_MASKS XCHAL_INTLEVEL0_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL1_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL2_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL3_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL4_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL5_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL6_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL7_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL8_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL9_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL10_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL11_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL12_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL13_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL14_ANDBELOW_MASK \ - XCHAL_SEP XCHAL_INTLEVEL15_ANDBELOW_MASK - -#if 0 /*XCHAL_HAVE_NMI*/ -/* NMI "interrupt level" (for use with EXCSAVE_n, EPS_n, EPC_n, RFI n): */ -# define XCHAL_NMILEVEL (XCHAL_NUM_INTLEVELS+1) -#endif - -/* Array of levels of each possible interrupt: */ -#define XCHAL_INT_LEVELS XCHAL_INT0_LEVEL \ - XCHAL_SEP XCHAL_INT1_LEVEL \ - XCHAL_SEP XCHAL_INT2_LEVEL \ - XCHAL_SEP XCHAL_INT3_LEVEL \ - XCHAL_SEP XCHAL_INT4_LEVEL \ - XCHAL_SEP XCHAL_INT5_LEVEL \ - XCHAL_SEP XCHAL_INT6_LEVEL \ - XCHAL_SEP XCHAL_INT7_LEVEL \ - XCHAL_SEP XCHAL_INT8_LEVEL \ - XCHAL_SEP XCHAL_INT9_LEVEL \ - XCHAL_SEP XCHAL_INT10_LEVEL \ - XCHAL_SEP XCHAL_INT11_LEVEL \ - XCHAL_SEP XCHAL_INT12_LEVEL \ - XCHAL_SEP XCHAL_INT13_LEVEL \ - XCHAL_SEP XCHAL_INT14_LEVEL \ - XCHAL_SEP XCHAL_INT15_LEVEL \ - XCHAL_SEP XCHAL_INT16_LEVEL \ - XCHAL_SEP XCHAL_INT17_LEVEL \ - XCHAL_SEP XCHAL_INT18_LEVEL \ - XCHAL_SEP XCHAL_INT19_LEVEL \ - XCHAL_SEP XCHAL_INT20_LEVEL \ - XCHAL_SEP XCHAL_INT21_LEVEL \ - XCHAL_SEP XCHAL_INT22_LEVEL \ - XCHAL_SEP XCHAL_INT23_LEVEL \ - XCHAL_SEP XCHAL_INT24_LEVEL \ - XCHAL_SEP XCHAL_INT25_LEVEL \ - XCHAL_SEP XCHAL_INT26_LEVEL \ - XCHAL_SEP XCHAL_INT27_LEVEL \ - XCHAL_SEP XCHAL_INT28_LEVEL \ - XCHAL_SEP XCHAL_INT29_LEVEL \ - XCHAL_SEP XCHAL_INT30_LEVEL \ - XCHAL_SEP XCHAL_INT31_LEVEL - -/* Array of types of each possible interrupt: */ -#define XCHAL_INT_TYPES XCHAL_INT0_TYPE \ - XCHAL_SEP XCHAL_INT1_TYPE \ - XCHAL_SEP XCHAL_INT2_TYPE \ - XCHAL_SEP XCHAL_INT3_TYPE \ - XCHAL_SEP XCHAL_INT4_TYPE \ - XCHAL_SEP XCHAL_INT5_TYPE \ - XCHAL_SEP XCHAL_INT6_TYPE \ - XCHAL_SEP XCHAL_INT7_TYPE \ - XCHAL_SEP XCHAL_INT8_TYPE \ - XCHAL_SEP XCHAL_INT9_TYPE \ - XCHAL_SEP XCHAL_INT10_TYPE \ - XCHAL_SEP XCHAL_INT11_TYPE \ - XCHAL_SEP XCHAL_INT12_TYPE \ - XCHAL_SEP XCHAL_INT13_TYPE \ - XCHAL_SEP XCHAL_INT14_TYPE \ - XCHAL_SEP XCHAL_INT15_TYPE \ - XCHAL_SEP XCHAL_INT16_TYPE \ - XCHAL_SEP XCHAL_INT17_TYPE \ - XCHAL_SEP XCHAL_INT18_TYPE \ - XCHAL_SEP XCHAL_INT19_TYPE \ - XCHAL_SEP XCHAL_INT20_TYPE \ - XCHAL_SEP XCHAL_INT21_TYPE \ - XCHAL_SEP XCHAL_INT22_TYPE \ - XCHAL_SEP XCHAL_INT23_TYPE \ - XCHAL_SEP XCHAL_INT24_TYPE \ - XCHAL_SEP XCHAL_INT25_TYPE \ - XCHAL_SEP XCHAL_INT26_TYPE \ - XCHAL_SEP XCHAL_INT27_TYPE \ - XCHAL_SEP XCHAL_INT28_TYPE \ - XCHAL_SEP XCHAL_INT29_TYPE \ - XCHAL_SEP XCHAL_INT30_TYPE \ - XCHAL_SEP XCHAL_INT31_TYPE - -/* Array of masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASKS XCHAL_INTTYPE_MASK_UNCONFIGURED \ - XCHAL_SEP XCHAL_INTTYPE_MASK_SOFTWARE \ - XCHAL_SEP XCHAL_INTTYPE_MASK_EXTERN_EDGE \ - XCHAL_SEP XCHAL_INTTYPE_MASK_EXTERN_LEVEL \ - XCHAL_SEP XCHAL_INTTYPE_MASK_TIMER \ - XCHAL_SEP XCHAL_INTTYPE_MASK_NMI \ - XCHAL_SEP XCHAL_INTTYPE_MASK_WRITE_ERROR \ - XCHAL_SEP XCHAL_INTTYPE_MASK_IDMA_DONE \ - XCHAL_SEP XCHAL_INTTYPE_MASK_IDMA_ERR \ - XCHAL_SEP XCHAL_INTTYPE_MASK_GS_ERR - -/* Interrupts that can be cleared using the INTCLEAR special register: */ -#define XCHAL_INTCLEARABLE_MASK (XCHAL_INTTYPE_MASK_SOFTWARE+XCHAL_INTTYPE_MASK_EXTERN_EDGE+XCHAL_INTTYPE_MASK_WRITE_ERROR) -/* Interrupts that can be triggered using the INTSET special register: */ -#define XCHAL_INTSETTABLE_MASK XCHAL_INTTYPE_MASK_SOFTWARE - -/* Array of interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3): */ -#define XCHAL_TIMER_INTERRUPTS XCHAL_TIMER0_INTERRUPT \ - XCHAL_SEP XCHAL_TIMER1_INTERRUPT \ - XCHAL_SEP XCHAL_TIMER2_INTERRUPT \ - XCHAL_SEP XCHAL_TIMER3_INTERRUPT - - - -/* For backward compatibility and for the array macros, define macros for - * each unconfigured interrupt number (unfortunately, the value of - * XTHAL_INTTYPE_UNCONFIGURED is not zero): */ -#if XCHAL_NUM_INTERRUPTS == 0 -# define XCHAL_INT0_LEVEL 0 -# define XCHAL_INT0_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 1 -# define XCHAL_INT1_LEVEL 0 -# define XCHAL_INT1_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 2 -# define XCHAL_INT2_LEVEL 0 -# define XCHAL_INT2_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 3 -# define XCHAL_INT3_LEVEL 0 -# define XCHAL_INT3_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 4 -# define XCHAL_INT4_LEVEL 0 -# define XCHAL_INT4_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 5 -# define XCHAL_INT5_LEVEL 0 -# define XCHAL_INT5_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 6 -# define XCHAL_INT6_LEVEL 0 -# define XCHAL_INT6_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 7 -# define XCHAL_INT7_LEVEL 0 -# define XCHAL_INT7_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 8 -# define XCHAL_INT8_LEVEL 0 -# define XCHAL_INT8_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 9 -# define XCHAL_INT9_LEVEL 0 -# define XCHAL_INT9_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 10 -# define XCHAL_INT10_LEVEL 0 -# define XCHAL_INT10_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 11 -# define XCHAL_INT11_LEVEL 0 -# define XCHAL_INT11_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 12 -# define XCHAL_INT12_LEVEL 0 -# define XCHAL_INT12_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 13 -# define XCHAL_INT13_LEVEL 0 -# define XCHAL_INT13_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 14 -# define XCHAL_INT14_LEVEL 0 -# define XCHAL_INT14_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 15 -# define XCHAL_INT15_LEVEL 0 -# define XCHAL_INT15_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 16 -# define XCHAL_INT16_LEVEL 0 -# define XCHAL_INT16_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 17 -# define XCHAL_INT17_LEVEL 0 -# define XCHAL_INT17_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 18 -# define XCHAL_INT18_LEVEL 0 -# define XCHAL_INT18_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 19 -# define XCHAL_INT19_LEVEL 0 -# define XCHAL_INT19_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 20 -# define XCHAL_INT20_LEVEL 0 -# define XCHAL_INT20_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 21 -# define XCHAL_INT21_LEVEL 0 -# define XCHAL_INT21_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 22 -# define XCHAL_INT22_LEVEL 0 -# define XCHAL_INT22_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 23 -# define XCHAL_INT23_LEVEL 0 -# define XCHAL_INT23_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 24 -# define XCHAL_INT24_LEVEL 0 -# define XCHAL_INT24_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 25 -# define XCHAL_INT25_LEVEL 0 -# define XCHAL_INT25_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 26 -# define XCHAL_INT26_LEVEL 0 -# define XCHAL_INT26_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 27 -# define XCHAL_INT27_LEVEL 0 -# define XCHAL_INT27_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 28 -# define XCHAL_INT28_LEVEL 0 -# define XCHAL_INT28_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 29 -# define XCHAL_INT29_LEVEL 0 -# define XCHAL_INT29_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 30 -# define XCHAL_INT30_LEVEL 0 -# define XCHAL_INT30_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif -#if XCHAL_NUM_INTERRUPTS <= 31 -# define XCHAL_INT31_LEVEL 0 -# define XCHAL_INT31_TYPE XTHAL_INTTYPE_UNCONFIGURED -#endif - - -/* - * Masks and levels corresponding to each *external* interrupt. - */ - -#define XCHAL_EXTINT0_MASK (1 << XCHAL_EXTINT0_NUM) -#define XCHAL_EXTINT0_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT0_NUM) -#define XCHAL_EXTINT1_MASK (1 << XCHAL_EXTINT1_NUM) -#define XCHAL_EXTINT1_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT1_NUM) -#define XCHAL_EXTINT2_MASK (1 << XCHAL_EXTINT2_NUM) -#define XCHAL_EXTINT2_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT2_NUM) -#define XCHAL_EXTINT3_MASK (1 << XCHAL_EXTINT3_NUM) -#define XCHAL_EXTINT3_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT3_NUM) -#define XCHAL_EXTINT4_MASK (1 << XCHAL_EXTINT4_NUM) -#define XCHAL_EXTINT4_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT4_NUM) -#define XCHAL_EXTINT5_MASK (1 << XCHAL_EXTINT5_NUM) -#define XCHAL_EXTINT5_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT5_NUM) -#define XCHAL_EXTINT6_MASK (1 << XCHAL_EXTINT6_NUM) -#define XCHAL_EXTINT6_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT6_NUM) -#define XCHAL_EXTINT7_MASK (1 << XCHAL_EXTINT7_NUM) -#define XCHAL_EXTINT7_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT7_NUM) -#define XCHAL_EXTINT8_MASK (1 << XCHAL_EXTINT8_NUM) -#define XCHAL_EXTINT8_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT8_NUM) -#define XCHAL_EXTINT9_MASK (1 << XCHAL_EXTINT9_NUM) -#define XCHAL_EXTINT9_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT9_NUM) -#define XCHAL_EXTINT10_MASK (1 << XCHAL_EXTINT10_NUM) -#define XCHAL_EXTINT10_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT10_NUM) -#define XCHAL_EXTINT11_MASK (1 << XCHAL_EXTINT11_NUM) -#define XCHAL_EXTINT11_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT11_NUM) -#define XCHAL_EXTINT12_MASK (1 << XCHAL_EXTINT12_NUM) -#define XCHAL_EXTINT12_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT12_NUM) -#define XCHAL_EXTINT13_MASK (1 << XCHAL_EXTINT13_NUM) -#define XCHAL_EXTINT13_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT13_NUM) -#define XCHAL_EXTINT14_MASK (1 << XCHAL_EXTINT14_NUM) -#define XCHAL_EXTINT14_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT14_NUM) -#define XCHAL_EXTINT15_MASK (1 << XCHAL_EXTINT15_NUM) -#define XCHAL_EXTINT15_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT15_NUM) -#define XCHAL_EXTINT16_MASK (1 << XCHAL_EXTINT16_NUM) -#define XCHAL_EXTINT16_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT16_NUM) -#define XCHAL_EXTINT17_MASK (1 << XCHAL_EXTINT17_NUM) -#define XCHAL_EXTINT17_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT17_NUM) -#define XCHAL_EXTINT18_MASK (1 << XCHAL_EXTINT18_NUM) -#define XCHAL_EXTINT18_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT18_NUM) -#define XCHAL_EXTINT19_MASK (1 << XCHAL_EXTINT19_NUM) -#define XCHAL_EXTINT19_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT19_NUM) -#define XCHAL_EXTINT20_MASK (1 << XCHAL_EXTINT20_NUM) -#define XCHAL_EXTINT20_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT20_NUM) -#define XCHAL_EXTINT21_MASK (1 << XCHAL_EXTINT21_NUM) -#define XCHAL_EXTINT21_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT21_NUM) -#define XCHAL_EXTINT22_MASK (1 << XCHAL_EXTINT22_NUM) -#define XCHAL_EXTINT22_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT22_NUM) -#define XCHAL_EXTINT23_MASK (1 << XCHAL_EXTINT23_NUM) -#define XCHAL_EXTINT23_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT23_NUM) -#define XCHAL_EXTINT24_MASK (1 << XCHAL_EXTINT24_NUM) -#define XCHAL_EXTINT24_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT24_NUM) -#define XCHAL_EXTINT25_MASK (1 << XCHAL_EXTINT25_NUM) -#define XCHAL_EXTINT25_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT25_NUM) -#define XCHAL_EXTINT26_MASK (1 << XCHAL_EXTINT26_NUM) -#define XCHAL_EXTINT26_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT26_NUM) -#define XCHAL_EXTINT27_MASK (1 << XCHAL_EXTINT27_NUM) -#define XCHAL_EXTINT27_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT27_NUM) -#define XCHAL_EXTINT28_MASK (1 << XCHAL_EXTINT28_NUM) -#define XCHAL_EXTINT28_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT28_NUM) -#define XCHAL_EXTINT29_MASK (1 << XCHAL_EXTINT29_NUM) -#define XCHAL_EXTINT29_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT29_NUM) -#define XCHAL_EXTINT30_MASK (1 << XCHAL_EXTINT30_NUM) -#define XCHAL_EXTINT30_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT30_NUM) -#define XCHAL_EXTINT31_MASK (1 << XCHAL_EXTINT31_NUM) -#define XCHAL_EXTINT31_LEVEL XCHAL_INT_LEVEL(XCHAL_EXTINT31_NUM) - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -/* For backward compatibility ONLY -- DO NOT USE (will be removed in future release): */ -#define XCHAL_HAVE_OLD_EXC_ARCH XCHAL_HAVE_XEA1 /* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */ -#define XCHAL_HAVE_EXCM XCHAL_HAVE_XEA2 /* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */ -#ifdef XCHAL_USER_VECTOR_VADDR -#define XCHAL_PROGRAMEXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR -#define XCHAL_USEREXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR -#endif -#ifdef XCHAL_USER_VECTOR_PADDR -# define XCHAL_PROGRAMEXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR -# define XCHAL_USEREXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR -#endif -#ifdef XCHAL_KERNEL_VECTOR_VADDR -# define XCHAL_STACKEDEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR -# define XCHAL_KERNELEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR -#endif -#ifdef XCHAL_KERNEL_VECTOR_PADDR -# define XCHAL_STACKEDEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR -# define XCHAL_KERNELEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR -#endif - -#if 0 -#if XCHAL_HAVE_DEBUG -# define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) -/* This one should only get defined if the corresponding intlevel paddr macro exists: */ -# define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL_VECTOR_PADDR(XCHAL_DEBUGLEVEL) -#endif -#endif - -/* Indexing macros: */ -#define _XCHAL_INTLEVEL_VECTOR_VADDR(n) XCHAL_INTLEVEL ## n ## _VECTOR_VADDR -#define XCHAL_INTLEVEL_VECTOR_VADDR(n) _XCHAL_INTLEVEL_VECTOR_VADDR(n) /* n = 0 .. 15 */ - -/* - * General Exception Causes - * (values of EXCCAUSE special register set by general exceptions, - * which vector to the user, kernel, or double-exception vectors). - * - * DEPRECATED. Please use the equivalent EXCCAUSE_xxx macros - * defined in <xtensa/corebits.h>. (Note that these have slightly - * different names, they don't just have the XCHAL_ prefix removed.) - */ -#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION 0 /* Illegal Instruction */ -#define XCHAL_EXCCAUSE_SYSTEM_CALL 1 /* System Call */ -#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR 2 /* Instruction Fetch Error */ -#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error */ -#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt */ -#define XCHAL_EXCCAUSE_ALLOCA 5 /* Stack Extension Assist */ -#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero */ -#define XCHAL_EXCCAUSE_SPECULATION 7 /* Speculation */ -#define XCHAL_EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction */ -#define XCHAL_EXCCAUSE_UNALIGNED 9 /* Unaligned Load Store */ -/*10..15 reserved*/ -#define XCHAL_EXCCAUSE_ITLB_MISS 16 /* ITlb Miss Exception */ -#define XCHAL_EXCCAUSE_ITLB_MULTIHIT 17 /* ITlb Mutltihit Exception */ -#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE 18 /* ITlb Privilege Exception */ -#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION 19 /* ITlb Size Restriction Exception */ -#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20 /* Fetch Cache Attribute Exception */ -/*21..23 reserved*/ -#define XCHAL_EXCCAUSE_DTLB_MISS 24 /* DTlb Miss Exception */ -#define XCHAL_EXCCAUSE_DTLB_MULTIHIT 25 /* DTlb Multihit Exception */ -#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE 26 /* DTlb Privilege Exception */ -#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION 27 /* DTlb Size Restriction Exception */ -#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28 /* Load Cache Attribute Exception */ -#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE 29 /* Store Cache Attribute Exception */ -/*30..31 reserved*/ -#define XCHAL_EXCCAUSE_COPROCESSOR0_DISABLED 32 /* Coprocessor 0 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR1_DISABLED 33 /* Coprocessor 1 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR2_DISABLED 34 /* Coprocessor 2 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR3_DISABLED 35 /* Coprocessor 3 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR4_DISABLED 36 /* Coprocessor 4 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR5_DISABLED 37 /* Coprocessor 5 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR6_DISABLED 38 /* Coprocessor 6 disabled */ -#define XCHAL_EXCCAUSE_COPROCESSOR7_DISABLED 39 /* Coprocessor 7 disabled */ -/*40..63 reserved*/ - - -/* - * Miscellaneous special register fields. - * - * For each special register, and each field within each register: - * XCHAL_<regname>_VALIDMASK is the set of bits defined in the register. - * XCHAL_<regname>_<field>_BITS is the number of bits in the field. - * XCHAL_<regname>_<field>_NUM is 2^bits, the number of possible values - * of the field. - * XCHAL_<regname>_<field>_SHIFT is the position of the field within - * the register, starting from the least significant bit. - * - * DEPRECATED. Please use the equivalent macros defined in - * <xtensa/corebits.h>. (Note that these have different names.) - */ - -/* DBREAKC (special register number 160): */ -#define XCHAL_DBREAKC_VALIDMASK 0xC000003F -#define XCHAL_DBREAKC_MASK_BITS 6 -#define XCHAL_DBREAKC_MASK_NUM 64 -#define XCHAL_DBREAKC_MASK_SHIFT 0 -#define XCHAL_DBREAKC_MASK_MASK 0x0000003F -#define XCHAL_DBREAKC_LOADBREAK_BITS 1 -#define XCHAL_DBREAKC_LOADBREAK_NUM 2 -#define XCHAL_DBREAKC_LOADBREAK_SHIFT 30 -#define XCHAL_DBREAKC_LOADBREAK_MASK 0x40000000 -#define XCHAL_DBREAKC_STOREBREAK_BITS 1 -#define XCHAL_DBREAKC_STOREBREAK_NUM 2 -#define XCHAL_DBREAKC_STOREBREAK_SHIFT 31 -#define XCHAL_DBREAKC_STOREBREAK_MASK 0x80000000 -/* PS (special register number 230): */ -#define XCHAL_PS_VALIDMASK 0x00070F3F -#define XCHAL_PS_INTLEVEL_BITS 4 -#define XCHAL_PS_INTLEVEL_NUM 16 -#define XCHAL_PS_INTLEVEL_SHIFT 0 -#define XCHAL_PS_INTLEVEL_MASK 0x0000000F -#define XCHAL_PS_EXCM_BITS 1 -#define XCHAL_PS_EXCM_NUM 2 -#define XCHAL_PS_EXCM_SHIFT 4 -#define XCHAL_PS_EXCM_MASK 0x00000010 -#define XCHAL_PS_UM_BITS 1 -#define XCHAL_PS_UM_NUM 2 -#define XCHAL_PS_UM_SHIFT 5 -#define XCHAL_PS_UM_MASK 0x00000020 -#define XCHAL_PS_RING_BITS 2 -#define XCHAL_PS_RING_NUM 4 -#define XCHAL_PS_RING_SHIFT 6 -#define XCHAL_PS_RING_MASK 0x000000C0 -#define XCHAL_PS_OWB_BITS 4 -#define XCHAL_PS_OWB_NUM 16 -#define XCHAL_PS_OWB_SHIFT 8 -#define XCHAL_PS_OWB_MASK 0x00000F00 -#define XCHAL_PS_CALLINC_BITS 2 -#define XCHAL_PS_CALLINC_NUM 4 -#define XCHAL_PS_CALLINC_SHIFT 16 -#define XCHAL_PS_CALLINC_MASK 0x00030000 -#define XCHAL_PS_WOE_BITS 1 -#define XCHAL_PS_WOE_NUM 2 -#define XCHAL_PS_WOE_SHIFT 18 -#define XCHAL_PS_WOE_MASK 0x00040000 -/* EXCCAUSE (special register number 232): */ -#define XCHAL_EXCCAUSE_VALIDMASK 0x0000003F -#define XCHAL_EXCCAUSE_BITS 6 -#define XCHAL_EXCCAUSE_NUM 64 -#define XCHAL_EXCCAUSE_SHIFT 0 -#define XCHAL_EXCCAUSE_MASK 0x0000003F -/* DEBUGCAUSE (special register number 233): */ -#define XCHAL_DEBUGCAUSE_VALIDMASK 0x0000003F -#define XCHAL_DEBUGCAUSE_ICOUNT_BITS 1 -#define XCHAL_DEBUGCAUSE_ICOUNT_NUM 2 -#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT 0 -#define XCHAL_DEBUGCAUSE_ICOUNT_MASK 0x00000001 -#define XCHAL_DEBUGCAUSE_IBREAK_BITS 1 -#define XCHAL_DEBUGCAUSE_IBREAK_NUM 2 -#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT 1 -#define XCHAL_DEBUGCAUSE_IBREAK_MASK 0x00000002 -#define XCHAL_DEBUGCAUSE_DBREAK_BITS 1 -#define XCHAL_DEBUGCAUSE_DBREAK_NUM 2 -#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT 2 -#define XCHAL_DEBUGCAUSE_DBREAK_MASK 0x00000004 -#define XCHAL_DEBUGCAUSE_BREAK_BITS 1 -#define XCHAL_DEBUGCAUSE_BREAK_NUM 2 -#define XCHAL_DEBUGCAUSE_BREAK_SHIFT 3 -#define XCHAL_DEBUGCAUSE_BREAK_MASK 0x00000008 -#define XCHAL_DEBUGCAUSE_BREAKN_BITS 1 -#define XCHAL_DEBUGCAUSE_BREAKN_NUM 2 -#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT 4 -#define XCHAL_DEBUGCAUSE_BREAKN_MASK 0x00000010 -#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS 1 -#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM 2 -#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT 5 -#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK 0x00000020 - - - - -/*---------------------------------------------------------------------- - TIMERS - ----------------------------------------------------------------------*/ - -/*#define XCHAL_HAVE_TIMERS XCHAL_HAVE_CCOUNT*/ - - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_IROM XCHAL_NUM_INSTROM /* (DEPRECATED) */ -#define XCHAL_NUM_IRAM XCHAL_NUM_INSTRAM /* (DEPRECATED) */ -#define XCHAL_NUM_DROM XCHAL_NUM_DATAROM /* (DEPRECATED) */ -#define XCHAL_NUM_DRAM XCHAL_NUM_DATARAM /* (DEPRECATED) */ - -#define XCHAL_IROM0_VADDR XCHAL_INSTROM0_VADDR /* (DEPRECATED) */ -#define XCHAL_IROM0_PADDR XCHAL_INSTROM0_PADDR /* (DEPRECATED) */ -#define XCHAL_IROM0_SIZE XCHAL_INSTROM0_SIZE /* (DEPRECATED) */ -#define XCHAL_IROM1_VADDR XCHAL_INSTROM1_VADDR /* (DEPRECATED) */ -#define XCHAL_IROM1_PADDR XCHAL_INSTROM1_PADDR /* (DEPRECATED) */ -#define XCHAL_IROM1_SIZE XCHAL_INSTROM1_SIZE /* (DEPRECATED) */ -#define XCHAL_IRAM0_VADDR XCHAL_INSTRAM0_VADDR /* (DEPRECATED) */ -#define XCHAL_IRAM0_PADDR XCHAL_INSTRAM0_PADDR /* (DEPRECATED) */ -#define XCHAL_IRAM0_SIZE XCHAL_INSTRAM0_SIZE /* (DEPRECATED) */ -#define XCHAL_IRAM1_VADDR XCHAL_INSTRAM1_VADDR /* (DEPRECATED) */ -#define XCHAL_IRAM1_PADDR XCHAL_INSTRAM1_PADDR /* (DEPRECATED) */ -#define XCHAL_IRAM1_SIZE XCHAL_INSTRAM1_SIZE /* (DEPRECATED) */ -#define XCHAL_DROM0_VADDR XCHAL_DATAROM0_VADDR /* (DEPRECATED) */ -#define XCHAL_DROM0_PADDR XCHAL_DATAROM0_PADDR /* (DEPRECATED) */ -#define XCHAL_DROM0_SIZE XCHAL_DATAROM0_SIZE /* (DEPRECATED) */ -#define XCHAL_DROM1_VADDR XCHAL_DATAROM1_VADDR /* (DEPRECATED) */ -#define XCHAL_DROM1_PADDR XCHAL_DATAROM1_PADDR /* (DEPRECATED) */ -#define XCHAL_DROM1_SIZE XCHAL_DATAROM1_SIZE /* (DEPRECATED) */ -#define XCHAL_DRAM0_VADDR XCHAL_DATARAM0_VADDR /* (DEPRECATED) */ -#define XCHAL_DRAM0_PADDR XCHAL_DATARAM0_PADDR /* (DEPRECATED) */ -#define XCHAL_DRAM0_SIZE XCHAL_DATARAM0_SIZE /* (DEPRECATED) */ -#define XCHAL_DRAM1_VADDR XCHAL_DATARAM1_VADDR /* (DEPRECATED) */ -#define XCHAL_DRAM1_PADDR XCHAL_DATARAM1_PADDR /* (DEPRECATED) */ -#define XCHAL_DRAM1_SIZE XCHAL_DATARAM1_SIZE /* (DEPRECATED) */ - - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - - -/* Default PREFCTL value to enable prefetch. */ -#if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RE_2012_0 -#define XCHAL_CACHE_PREFCTL_DEFAULT 0x00044 /* enabled, not aggressive */ -#elif XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RF_2014_0 -#define XCHAL_CACHE_PREFCTL_DEFAULT 0x01044 /* + enable prefetch to L1 */ -#elif ((XCHAL_PREFETCH_ENTRIES >= 16) && XCHAL_HAVE_CACHE_BLOCKOPS) -#define XCHAL_CACHE_PREFCTL_DEFAULT 0x81044 /* 12 entries for block ops */ -#elif ((XCHAL_PREFETCH_ENTRIES >= 8) && XCHAL_HAVE_CACHE_BLOCKOPS) -#define XCHAL_CACHE_PREFCTL_DEFAULT 0x51044 /* 5 entries for block ops */ -#else -#define XCHAL_CACHE_PREFCTL_DEFAULT 0x01044 /* 0 entries for block ops */ -#endif - - -/* Max for both I-cache and D-cache (used for general alignment): */ -#if XCHAL_ICACHE_LINESIZE > XCHAL_DCACHE_LINESIZE -# define XCHAL_CACHE_LINEWIDTH_MAX XCHAL_ICACHE_LINEWIDTH -# define XCHAL_CACHE_LINESIZE_MAX XCHAL_ICACHE_LINESIZE -#else -# define XCHAL_CACHE_LINEWIDTH_MAX XCHAL_DCACHE_LINEWIDTH -# define XCHAL_CACHE_LINESIZE_MAX XCHAL_DCACHE_LINESIZE -#endif - -#define XCHAL_ICACHE_SETSIZE (1<<XCHAL_ICACHE_SETWIDTH) -#define XCHAL_DCACHE_SETSIZE (1<<XCHAL_DCACHE_SETWIDTH) -/* Max for both I and D caches (used for cache-coherency page alignment): */ -#if XCHAL_ICACHE_SETWIDTH > XCHAL_DCACHE_SETWIDTH -# define XCHAL_CACHE_SETWIDTH_MAX XCHAL_ICACHE_SETWIDTH -# define XCHAL_CACHE_SETSIZE_MAX XCHAL_ICACHE_SETSIZE -#else -# define XCHAL_CACHE_SETWIDTH_MAX XCHAL_DCACHE_SETWIDTH -# define XCHAL_CACHE_SETSIZE_MAX XCHAL_DCACHE_SETSIZE -#endif - -/* Instruction cache tag bits: */ -#define XCHAL_ICACHE_TAG_V_SHIFT 0 -#define XCHAL_ICACHE_TAG_V 0x1 /* valid bit */ -#if XCHAL_ICACHE_WAYS > 1 -# define XCHAL_ICACHE_TAG_F_SHIFT 1 -# define XCHAL_ICACHE_TAG_F 0x2 /* fill (LRU) bit */ -#else -# define XCHAL_ICACHE_TAG_F_SHIFT 0 -# define XCHAL_ICACHE_TAG_F 0 /* no fill (LRU) bit */ -#endif -#if XCHAL_ICACHE_LINE_LOCKABLE -# define XCHAL_ICACHE_TAG_L_SHIFT (XCHAL_ICACHE_TAG_F_SHIFT+1) -# define XCHAL_ICACHE_TAG_L (1 << XCHAL_ICACHE_TAG_L_SHIFT) /* lock bit */ -#else -# define XCHAL_ICACHE_TAG_L_SHIFT XCHAL_ICACHE_TAG_F_SHIFT -# define XCHAL_ICACHE_TAG_L 0 /* no lock bit */ -#endif -/* Data cache tag bits: */ -#define XCHAL_DCACHE_TAG_V_SHIFT 0 -#define XCHAL_DCACHE_TAG_V 0x1 /* valid bit */ -#if XCHAL_DCACHE_WAYS > 1 -# define XCHAL_DCACHE_TAG_F_SHIFT 1 -# define XCHAL_DCACHE_TAG_F 0x2 /* fill (LRU) bit */ -#else -# define XCHAL_DCACHE_TAG_F_SHIFT 0 -# define XCHAL_DCACHE_TAG_F 0 /* no fill (LRU) bit */ -#endif -#if XCHAL_DCACHE_IS_WRITEBACK -# define XCHAL_DCACHE_TAG_D_SHIFT (XCHAL_DCACHE_TAG_F_SHIFT+1) -# define XCHAL_DCACHE_TAG_D (1 << XCHAL_DCACHE_TAG_D_SHIFT) /* dirty bit */ -#else -# define XCHAL_DCACHE_TAG_D_SHIFT XCHAL_DCACHE_TAG_F_SHIFT -# define XCHAL_DCACHE_TAG_D 0 /* no dirty bit */ -#endif -#if XCHAL_DCACHE_LINE_LOCKABLE -# define XCHAL_DCACHE_TAG_L_SHIFT (XCHAL_DCACHE_TAG_D_SHIFT+1) -# define XCHAL_DCACHE_TAG_L (1 << XCHAL_DCACHE_TAG_L_SHIFT) /* lock bit */ -#else -# define XCHAL_DCACHE_TAG_L_SHIFT XCHAL_DCACHE_TAG_D_SHIFT -# define XCHAL_DCACHE_TAG_L 0 /* no lock bit */ -#endif - -/* Whether MEMCTL register has anything useful */ -#define XCHAL_USE_MEMCTL (((XCHAL_LOOP_BUFFER_SIZE > 0) || \ - XCHAL_DCACHE_IS_COHERENT || \ - XCHAL_HAVE_ICACHE_DYN_WAYS || \ - XCHAL_HAVE_DCACHE_DYN_WAYS) && \ - (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0)) - -#if XCHAL_DCACHE_IS_COHERENT -#define _MEMCTL_SNOOP_EN 0x02 /* Enable snoop */ -#else -#define _MEMCTL_SNOOP_EN 0x00 /* Don't enable snoop */ -#endif - -#if (XCHAL_LOOP_BUFFER_SIZE == 0) || XCHAL_ERRATUM_453 -#define _MEMCTL_L0IBUF_EN 0x00 /* No loop buffer or don't enable */ -#else -#define _MEMCTL_L0IBUF_EN 0x01 /* Enable loop buffer */ -#endif - -/* Default MEMCTL values: */ -#if XCHAL_HAVE_ICACHE_DYN_WAYS || XCHAL_HAVE_DCACHE_DYN_WAYS -#define XCHAL_CACHE_MEMCTL_DEFAULT (0xFFFFFF00 | _MEMCTL_L0IBUF_EN) -#else -#define XCHAL_CACHE_MEMCTL_DEFAULT (0x00000000 | _MEMCTL_L0IBUF_EN) -#endif - -#define XCHAL_SNOOP_LB_MEMCTL_DEFAULT (_MEMCTL_SNOOP_EN | _MEMCTL_L0IBUF_EN) - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See <xtensa/config/core-matmap.h> for more details. */ - -/* Has different semantic in open source headers (where it means HAVE_PTP_MMU), - so comment out starting with RB-2008.3 release; later, might get - get reintroduced as a synonym for XCHAL_HAVE_PTP_MMU instead: */ -/*#define XCHAL_HAVE_MMU XCHAL_HAVE_TLBS*/ /* (DEPRECATED; use XCHAL_HAVE_TLBS instead) */ - -/* Indexing macros: */ -#define _XCHAL_ITLB_SET(n,_what) XCHAL_ITLB_SET ## n ## _what -#define XCHAL_ITLB_SET(n,what) _XCHAL_ITLB_SET(n, _ ## what ) -#define _XCHAL_ITLB_SET_E(n,i,_what) XCHAL_ITLB_SET ## n ## _E ## i ## _what -#define XCHAL_ITLB_SET_E(n,i,what) _XCHAL_ITLB_SET_E(n,i, _ ## what ) -#define _XCHAL_DTLB_SET(n,_what) XCHAL_DTLB_SET ## n ## _what -#define XCHAL_DTLB_SET(n,what) _XCHAL_DTLB_SET(n, _ ## what ) -#define _XCHAL_DTLB_SET_E(n,i,_what) XCHAL_DTLB_SET ## n ## _E ## i ## _what -#define XCHAL_DTLB_SET_E(n,i,what) _XCHAL_DTLB_SET_E(n,i, _ ## what ) -/* - * Example use: XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES) - * to get the value of XCHAL_ITLB_SET<n>_ENTRIES where <n> is the first auto-refill set. - */ - -/* Number of entries per autorefill way: */ -#define XCHAL_ITLB_ARF_ENTRIES (1<<XCHAL_ITLB_ARF_ENTRIES_LOG2) -#define XCHAL_DTLB_ARF_ENTRIES (1<<XCHAL_DTLB_ARF_ENTRIES_LOG2) - -/* - * Determine whether we have a full MMU (with Page Table and Protection) - * usable for an MMU-based OS: - */ -#if 0 -#if XCHAL_HAVE_TLBS && !XCHAL_HAVE_SPANNING_WAY && XCHAL_ITLB_ARF_WAYS > 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2 -# define XCHAL_HAVE_PTP_MMU 1 /* have full MMU (with page table [autorefill] and protection) */ -#else -# define XCHAL_HAVE_PTP_MMU 0 /* don't have full MMU */ -#endif -#endif - -/* - * For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings: - */ -#if XCHAL_HAVE_PTP_MMU && !XCHAL_HAVE_SPANNING_WAY -#define XCHAL_KSEG_CACHED_VADDR 0xD0000000 /* virt.addr of kernel RAM cached static map */ -#define XCHAL_KSEG_CACHED_PADDR 0x00000000 /* phys.addr of kseg_cached */ -#define XCHAL_KSEG_CACHED_SIZE 0x08000000 /* size in bytes of kseg_cached (assumed power of 2!!!) */ -#define XCHAL_KSEG_BYPASS_VADDR 0xD8000000 /* virt.addr of kernel RAM bypass (uncached) static map */ -#define XCHAL_KSEG_BYPASS_PADDR 0x00000000 /* phys.addr of kseg_bypass */ -#define XCHAL_KSEG_BYPASS_SIZE 0x08000000 /* size in bytes of kseg_bypass (assumed power of 2!!!) */ - -#define XCHAL_KIO_CACHED_VADDR 0xE0000000 /* virt.addr of kernel I/O cached static map */ -#define XCHAL_KIO_CACHED_PADDR 0xF0000000 /* phys.addr of kio_cached */ -#define XCHAL_KIO_CACHED_SIZE 0x10000000 /* size in bytes of kio_cached (assumed power of 2!!!) */ -#define XCHAL_KIO_BYPASS_VADDR 0xF0000000 /* virt.addr of kernel I/O bypass (uncached) static map */ -#define XCHAL_KIO_BYPASS_PADDR 0xF0000000 /* phys.addr of kio_bypass */ -#define XCHAL_KIO_BYPASS_SIZE 0x10000000 /* size in bytes of kio_bypass (assumed power of 2!!!) */ - -#define XCHAL_SEG_MAPPABLE_VADDR 0x00000000 /* start of largest non-static-mapped virtual addr area */ -#define XCHAL_SEG_MAPPABLE_SIZE 0xD0000000 /* size in bytes of " */ -/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size. */ -#endif - - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -/* Data alignment required if used for instructions: */ -#if XCHAL_INST_FETCH_WIDTH > XCHAL_DATA_WIDTH -# define XCHAL_ALIGN_MAX XCHAL_INST_FETCH_WIDTH -#else -# define XCHAL_ALIGN_MAX XCHAL_DATA_WIDTH -#endif - -/* - * Names kept for backward compatibility. - * (Here "RELEASE" is now a misnomer; these are product *versions*, not the releases - * under which they are released. In the T10##.# era there was no distinction.) - */ -#define XCHAL_HW_RELEASE_MAJOR XCHAL_HW_VERSION_MAJOR -#define XCHAL_HW_RELEASE_MINOR XCHAL_HW_VERSION_MINOR -#define XCHAL_HW_RELEASE_NAME XCHAL_HW_VERSION_NAME - - - - -/*---------------------------------------------------------------------- - COPROCESSORS and EXTRA STATE - ----------------------------------------------------------------------*/ - -#define XCHAL_EXTRA_SA_SIZE XCHAL_NCP_SA_SIZE -#define XCHAL_EXTRA_SA_ALIGN XCHAL_NCP_SA_ALIGN -#define XCHAL_CPEXTRA_SA_SIZE XCHAL_TOTAL_SA_SIZE -#define XCHAL_CPEXTRA_SA_ALIGN XCHAL_TOTAL_SA_ALIGN - -#if defined (_ASMLANGUAGE) || defined (__ASSEMBLER__) - - /* Invoked at start of save area load/store sequence macro to setup macro - * internal offsets. Not usually invoked directly. - * continue 0 for 1st sequence, 1 for subsequent consecutive ones. - * totofs offset from original ptr to next load/store location. - */ - .macro xchal_sa_start continue totofs - .ifeq \continue - .set .Lxchal_pofs_, 0 /* offset from original ptr to current \ptr */ - .set .Lxchal_ofs_, 0 /* offset from current \ptr to next load/store location */ - .endif - .if \totofs + 1 /* if totofs specified (not -1) */ - .set .Lxchal_ofs_, \totofs - .Lxchal_pofs_ /* specific offset from original ptr */ - .endif - .endm - - /* Align portion of save area and bring ptr in range if necessary. - * Used by save area load/store sequences. Not usually invoked directly. - * Allows combining multiple (sub-)sequences arbitrarily. - * ptr pointer to save area (may be off, see .Lxchal_pofs_) - * minofs,maxofs range of offset from cur ptr to next load/store loc; - * minofs <= 0 <= maxofs (0 must always be valid offset) - * range must be within +/- 30kB or so. - * ofsalign alignment granularity of minofs .. maxofs (pow of 2) - * (restriction on offset from ptr to next load/store loc) - * totalign align from orig ptr to next load/store loc (pow of 2) - */ - .macro xchal_sa_align ptr minofs maxofs ofsalign totalign - /* First align where we start accessing the next register - * per \totalign relative to original ptr (i.e. start of the save area): - */ - .set .Lxchal_ofs_, ((.Lxchal_pofs_ + .Lxchal_ofs_ + \totalign - 1) & -\totalign) - .Lxchal_pofs_ - /* If necessary, adjust \ptr to bring .Lxchal_ofs_ in acceptable range: */ - .if (((\maxofs) - .Lxchal_ofs_) & 0xC0000000) | ((.Lxchal_ofs_ - (\minofs)) & 0xC0000000) | (.Lxchal_ofs_ & (\ofsalign-1)) - .set .Ligmask, 0xFFFFFFFF /* TODO: optimize to addmi, per aligns and .Lxchal_ofs_ */ - addi \ptr, \ptr, (.Lxchal_ofs_ & .Ligmask) - .set .Lxchal_pofs_, .Lxchal_pofs_ + (.Lxchal_ofs_ & .Ligmask) - .set .Lxchal_ofs_, (.Lxchal_ofs_ & ~.Ligmask) - .endif - .endm - /* - * We could optimize for addi to expand to only addmi instead of - * "addmi;addi", where possible. Here's a partial example how: - * .set .Lmaxmask, -(\ofsalign) & -(\totalign) - * .if (((\maxofs) + ~.Lmaxmask + 1) & 0xFFFFFF00) && ((.Lxchal_ofs_ & ~.Lmaxmask) == 0) - * .set .Ligmask, 0xFFFFFF00 - * .elif ... ditto for negative ofs range ... - * .set .Ligmask, 0xFFFFFF00 - * .set ... adjust per offset ... - * .else - * .set .Ligmask, 0xFFFFFFFF - * .endif - */ - - /* Invoke this after xchal_XXX_{load,store} macros to restore \ptr. */ - .macro xchal_sa_ptr_restore ptr - .if .Lxchal_pofs_ - addi \ptr, \ptr, - .Lxchal_pofs_ - .set .Lxchal_ofs_, .Lxchal_ofs_ + .Lxchal_pofs_ - .set .Lxchal_pofs_, 0 - .endif - .endm - - /* - * Use as eg: - * xchal_atmps_store a1, SOMEOFS, XCHAL_SA_NUM_ATMPS, a4, a5 - * xchal_ncp_load a2, a0,a3,a4,a5 - * xchal_atmps_load a1, SOMEOFS, XCHAL_SA_NUM_ATMPS, a4, a5 - * - * Specify only the ARs you *haven't* saved/restored already, up to 4. - * They *must* be the *last* ARs (in same order) specified to save area - * load/store sequences. In the example above, a0 and a3 were already - * saved/restored and unused (thus available) but a4 and a5 were not. - */ -#define xchal_atmps_store xchal_atmps_loadstore s32i, -#define xchal_atmps_load xchal_atmps_loadstore l32i, - .macro xchal_atmps_loadstore inst ptr offset nreq aa=0 ab=0 ac=0 ad=0 - .set .Lnsaved_, 0 - .irp reg,\aa,\ab,\ac,\ad - .ifeq 0x\reg ; .set .Lnsaved_,.Lnsaved_+1 ; .endif - .endr - .set .Laofs_, 0 - .irp reg,\aa,\ab,\ac,\ad - .ifgt (\nreq)-.Lnsaved_ - \inst \reg, \ptr, .Laofs_+\offset - .set .Laofs_,.Laofs_+4 - .set .Lnsaved_,.Lnsaved_+1 - .endif - .endr - .endm - -/*#define xchal_ncp_load_a2 xchal_ncp_load a2,a3,a4,a5,a6*/ -/*#define xchal_ncp_store_a2 xchal_ncp_store a2,a3,a4,a5,a6*/ -#define xchal_extratie_load xchal_ncptie_load -#define xchal_extratie_store xchal_ncptie_store -#define xchal_extratie_load_a2 xchal_ncptie_load a2,a3,a4,a5,a6 -#define xchal_extratie_store_a2 xchal_ncptie_store a2,a3,a4,a5,a6 -#define xchal_extra_load xchal_ncp_load -#define xchal_extra_store xchal_ncp_store -#define xchal_extra_load_a2 xchal_ncp_load a2,a3,a4,a5,a6 -#define xchal_extra_store_a2 xchal_ncp_store a2,a3,a4,a5,a6 -#define xchal_extra_load_funcbody xchal_ncp_load a2,a3,a4,a5,a6 -#define xchal_extra_store_funcbody xchal_ncp_store a2,a3,a4,a5,a6 -#define xchal_cp0_store_a2 xchal_cp0_store a2,a3,a4,a5,a6 -#define xchal_cp0_load_a2 xchal_cp0_load a2,a3,a4,a5,a6 -#define xchal_cp1_store_a2 xchal_cp1_store a2,a3,a4,a5,a6 -#define xchal_cp1_load_a2 xchal_cp1_load a2,a3,a4,a5,a6 -#define xchal_cp2_store_a2 xchal_cp2_store a2,a3,a4,a5,a6 -#define xchal_cp2_load_a2 xchal_cp2_load a2,a3,a4,a5,a6 -#define xchal_cp3_store_a2 xchal_cp3_store a2,a3,a4,a5,a6 -#define xchal_cp3_load_a2 xchal_cp3_load a2,a3,a4,a5,a6 -#define xchal_cp4_store_a2 xchal_cp4_store a2,a3,a4,a5,a6 -#define xchal_cp4_load_a2 xchal_cp4_load a2,a3,a4,a5,a6 -#define xchal_cp5_store_a2 xchal_cp5_store a2,a3,a4,a5,a6 -#define xchal_cp5_load_a2 xchal_cp5_load a2,a3,a4,a5,a6 -#define xchal_cp6_store_a2 xchal_cp6_store a2,a3,a4,a5,a6 -#define xchal_cp6_load_a2 xchal_cp6_load a2,a3,a4,a5,a6 -#define xchal_cp7_store_a2 xchal_cp7_store a2,a3,a4,a5,a6 -#define xchal_cp7_load_a2 xchal_cp7_load a2,a3,a4,a5,a6 - -/* Empty placeholder macros for undefined coprocessors: */ -#if (XCHAL_CP_MASK & ~XCHAL_CP_PORT_MASK) == 0 -# if XCHAL_CP0_SA_SIZE == 0 - .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP1_SA_SIZE == 0 - .macro xchal_cp1_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp1_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP2_SA_SIZE == 0 - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP3_SA_SIZE == 0 - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP4_SA_SIZE == 0 - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP5_SA_SIZE == 0 - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP6_SA_SIZE == 0 - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -# if XCHAL_CP7_SA_SIZE == 0 - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm -# endif -#endif - - /******************** - * Macros to create functions that save and restore the state of *any* TIE - * coprocessor (by dynamic index). - */ - - /* - * Macro that expands to the body of a function - * that stores the selected coprocessor's state (registers etc). - * Entry: a2 = ptr to save area in which to save cp state - * a3 = coprocessor number - * Exit: any register a2-a15 (?) may have been clobbered. - */ - .macro xchal_cpi_store_funcbody -#if (XCHAL_CP_MASK & ~XCHAL_CP_PORT_MASK) -# if XCHAL_CP0_SA_SIZE - bnez a3, 99f - xchal_cp0_store_a2 - j 90f -99: -# endif -# if XCHAL_CP1_SA_SIZE - bnei a3, 1, 99f - xchal_cp1_store_a2 - j 90f -99: -# endif -# if XCHAL_CP2_SA_SIZE - bnei a3, 2, 99f - xchal_cp2_store_a2 - j 90f -99: -# endif -# if XCHAL_CP3_SA_SIZE - bnei a3, 3, 99f - xchal_cp3_store_a2 - j 90f -99: -# endif -# if XCHAL_CP4_SA_SIZE - bnei a3, 4, 99f - xchal_cp4_store_a2 - j 90f -99: -# endif -# if XCHAL_CP5_SA_SIZE - bnei a3, 5, 99f - xchal_cp5_store_a2 - j 90f -99: -# endif -# if XCHAL_CP6_SA_SIZE - bnei a3, 6, 99f - xchal_cp6_store_a2 - j 90f -99: -# endif -# if XCHAL_CP7_SA_SIZE - bnei a3, 7, 99f - xchal_cp7_store_a2 - j 90f -99: -# endif -90: -#endif - .endm - - /* - * Macro that expands to the body of a function - * that loads the selected coprocessor's state (registers etc). - * Entry: a2 = ptr to save area from which to restore cp state - * a3 = coprocessor number - * Exit: any register a2-a15 (?) may have been clobbered. - */ - .macro xchal_cpi_load_funcbody -#if (XCHAL_CP_MASK & ~XCHAL_CP_PORT_MASK) -# if XCHAL_CP0_SA_SIZE - bnez a3, 99f - xchal_cp0_load_a2 - j 90f -99: -# endif -# if XCHAL_CP1_SA_SIZE - bnei a3, 1, 99f - xchal_cp1_load_a2 - j 90f -99: -# endif -# if XCHAL_CP2_SA_SIZE - bnei a3, 2, 99f - xchal_cp2_load_a2 - j 90f -99: -# endif -# if XCHAL_CP3_SA_SIZE - bnei a3, 3, 99f - xchal_cp3_load_a2 - j 90f -99: -# endif -# if XCHAL_CP4_SA_SIZE - bnei a3, 4, 99f - xchal_cp4_load_a2 - j 90f -99: -# endif -# if XCHAL_CP5_SA_SIZE - bnei a3, 5, 99f - xchal_cp5_load_a2 - j 90f -99: -# endif -# if XCHAL_CP6_SA_SIZE - bnei a3, 6, 99f - xchal_cp6_load_a2 - j 90f -99: -# endif -# if XCHAL_CP7_SA_SIZE - bnei a3, 7, 99f - xchal_cp7_load_a2 - j 90f -99: -# endif -90: -#endif - .endm - -#endif /*_ASMLANGUAGE or __ASSEMBLER__*/ - - -/* Other default macros for undefined coprocessors: */ -#ifndef XCHAL_CP0_NAME -# define XCHAL_CP0_NAME 0 -# define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP0_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP1_NAME -# define XCHAL_CP1_NAME 0 -# define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP1_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP2_NAME -# define XCHAL_CP2_NAME 0 -# define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP2_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP3_NAME -# define XCHAL_CP3_NAME 0 -# define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP3_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP4_NAME -# define XCHAL_CP4_NAME 0 -# define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP4_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP5_NAME -# define XCHAL_CP5_NAME 0 -# define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP5_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP6_NAME -# define XCHAL_CP6_NAME 0 -# define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP6_SA_CONTENTS_LIBDB /* empty */ -#endif -#ifndef XCHAL_CP7_NAME -# define XCHAL_CP7_NAME 0 -# define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM 0 -# define XCHAL_CP7_SA_CONTENTS_LIBDB /* empty */ -#endif - -#if XCHAL_CP_MASK == 0 -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP0_SA_SIZE 0 -#define XCHAL_CP0_SA_ALIGN 1 -#define XCHAL_CP1_SA_SIZE 0 -#define XCHAL_CP1_SA_ALIGN 1 -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 -#endif - - -/* Indexing macros: */ -#define _XCHAL_CP_SA_SIZE(n) XCHAL_CP ## n ## _SA_SIZE -#define XCHAL_CP_SA_SIZE(n) _XCHAL_CP_SA_SIZE(n) /* n = 0 .. 7 */ -#define _XCHAL_CP_SA_ALIGN(n) XCHAL_CP ## n ## _SA_ALIGN -#define XCHAL_CP_SA_ALIGN(n) _XCHAL_CP_SA_ALIGN(n) /* n = 0 .. 7 */ - -#define XCHAL_CPEXTRA_SA_SIZE_TOR2 XCHAL_CPEXTRA_SA_SIZE /* Tor2Beta only - do not use */ - -/* Link-time HAL global variables that report coprocessor numbers by name - (names are case-preserved from the original TIE): */ -#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) -# define _XCJOIN(a,b) a ## b -# define XCJOIN(a,b) _XCJOIN(a,b) -# ifdef XCHAL_CP0_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP0_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP0_IDENT); -# endif -# ifdef XCHAL_CP1_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP1_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP1_IDENT); -# endif -# ifdef XCHAL_CP2_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP2_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP2_IDENT); -# endif -# ifdef XCHAL_CP3_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP3_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP3_IDENT); -# endif -# ifdef XCHAL_CP4_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP4_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP4_IDENT); -# endif -# ifdef XCHAL_CP5_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP5_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP5_IDENT); -# endif -# ifdef XCHAL_CP6_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP6_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP6_IDENT); -# endif -# ifdef XCHAL_CP7_NAME -extern const unsigned char XCJOIN(Xthal_cp_id_,XCHAL_CP7_IDENT); -extern const unsigned int XCJOIN(Xthal_cp_mask_,XCHAL_CP7_IDENT); -# endif -#endif - - - - -/*---------------------------------------------------------------------- - DERIVED - ----------------------------------------------------------------------*/ - -#if XCHAL_HAVE_BE -#define XCHAL_INST_ILLN 0xD60F /* 2-byte illegal instruction, msb-first */ -#define XCHAL_INST_ILLN_BYTE0 0xD6 /* 2-byte illegal instruction, 1st byte */ -#define XCHAL_INST_ILLN_BYTE1 0x0F /* 2-byte illegal instruction, 2nd byte */ -#else -#define XCHAL_INST_ILLN 0xF06D /* 2-byte illegal instruction, lsb-first */ -#define XCHAL_INST_ILLN_BYTE0 0x6D /* 2-byte illegal instruction, 1st byte */ -#define XCHAL_INST_ILLN_BYTE1 0xF0 /* 2-byte illegal instruction, 2nd byte */ -#endif -/* Belongs in xtensa/hal.h: */ -#define XTHAL_INST_ILL 0x000000 /* 3-byte illegal instruction */ - - -/* - * Because information as to exactly which hardware version is targeted - * by a given software build is not always available, compile-time HAL - * Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE): - * (Here "RELEASE" is now a misnomer; these are product *versions*, not the releases - * under which they are released. In the T10##.# era there was no distinction.) - */ -#if XCHAL_HW_CONFIGID_RELIABLE -# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) (XTHAL_REL_LE( XCHAL_HW_VERSION_MAJOR,XCHAL_HW_VERSION_MINOR, major,minor ) ? 1 : 0) -# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) (XTHAL_REL_GE( XCHAL_HW_VERSION_MAJOR,XCHAL_HW_VERSION_MINOR, major,minor ) ? 1 : 0) -# define XCHAL_HW_RELEASE_AT(major,minor) (XTHAL_REL_EQ( XCHAL_HW_VERSION_MAJOR,XCHAL_HW_VERSION_MINOR, major,minor ) ? 1 : 0) -# define XCHAL_HW_RELEASE_MAJOR_AT(major) ((XCHAL_HW_VERSION_MAJOR == (major)) ? 1 : 0) -#else -# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) ( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \ - : ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \ - : XTHAL_MAYBE ) -# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) ( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \ - : (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \ - : XTHAL_MAYBE ) -# define XCHAL_HW_RELEASE_AT(major,minor) ( (((major) < 1040 && XCHAL_HAVE_XEA2) || \ - ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE) -# define XCHAL_HW_RELEASE_MAJOR_AT(major) XCHAL_HW_RELEASE_AT(major,0) -#endif - - -#endif /*XTENSA_CONFIG_CORE_H*/ - diff --git a/src/arch/xtensa/include/xtensa/core-macros.h b/src/arch/xtensa/include/xtensa/core-macros.h deleted file mode 100644 index 8b8a16b49a30..000000000000 --- a/src/arch/xtensa/include/xtensa/core-macros.h +++ /dev/null @@ -1,506 +0,0 @@ -/* - * xtensa/core-macros.h -- C specific definitions - * that depend on CORE configuration - */ - -/* - * Copyright (c) 2012 Tensilica 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. - */ - -#ifndef XTENSA_CACHE_H -#define XTENSA_CACHE_H - -#include <xtensa/config/core.h> - -/* Only define things for C code. */ -#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) - - - -/*************************** CACHE ***************************/ - -/* All the macros are in the lower case now and some of them - * share the name with the existing functions from hal.h. - * Including this header file will define XTHAL_USE_CACHE_MACROS - * which directs hal.h not to use the functions. - */ - -/* - * Single-cache-line operations in C-callable inline assembly. - * Essentially macro versions (uppercase) of: - * - * xthal_icache_line_invalidate(void *addr); - * xthal_icache_line_lock(void *addr); - * xthal_icache_line_unlock(void *addr); - * xthal_icache_sync(void); - * - * NOTE: unlike the above functions, the following macros do NOT - * execute the xthal_icache_sync() as part of each line operation. - * This sync must be called explicitly by the caller. This is to - * allow better optimization when operating on more than one line. - * - * xthal_dcache_line_invalidate(void *addr); - * xthal_dcache_line_writeback(void *addr); - * xthal_dcache_line_writeback_inv(void *addr); - * xthal_dcache_line_lock(void *addr); - * xthal_dcache_line_unlock(void *addr); - * xthal_dcache_sync(void); - * xthal_dcache_line_prefetch_for_write(void *addr); - * xthal_dcache_line_prefetch_for_read(void *addr); - * - * All are made memory-barriers, given that's how they're typically used - * (ops operate on a whole line, so clobbers all memory not just *addr). - * - * NOTE: All the block block cache ops and line prefetches are implemented - * using intrinsics so they are better optimized regarding memory barriers etc. - * - * All block downgrade functions exist in two forms: with and without - * the 'max' parameter: This parameter allows compiler to optimize - * the functions whenever the parameter is smaller than the cache size. - * - * xthal_dcache_block_invalidate(void *addr, unsigned size); - * xthal_dcache_block_writeback(void *addr, unsigned size); - * xthal_dcache_block_writeback_inv(void *addr, unsigned size); - * xthal_dcache_block_invalidate_max(void *addr, unsigned size, unsigned max); - * xthal_dcache_block_writeback_max(void *addr, unsigned size, unsigned max); - * xthal_dcache_block_writeback_inv_max(void *addr, unsigned size, unsigned max); - * - * xthal_dcache_block_prefetch_for_read(void *addr, unsigned size); - * xthal_dcache_block_prefetch_for_write(void *addr, unsigned size); - * xthal_dcache_block_prefetch_modify(void *addr, unsigned size); - * xthal_dcache_block_prefetch_read_write(void *addr, unsigned size); - * xthal_dcache_block_prefetch_for_read_grp(void *addr, unsigned size); - * xthal_dcache_block_prefetch_for_write_grp(void *addr, unsigned size); - * xthal_dcache_block_prefetch_modify_grp(void *addr, unsigned size); - * xthal_dcache_block_prefetch_read_write_grp(void *addr, unsigned size) - * - * xthal_dcache_block_wait(); - * xthal_dcache_block_required_wait(); - * xthal_dcache_block_abort(); - * xthal_dcache_block_prefetch_end(); - * xthal_dcache_block_newgrp(); - */ - -/*** INSTRUCTION CACHE ***/ - -#define XTHAL_USE_CACHE_MACROS - -#if XCHAL_ICACHE_SIZE > 0 -# define xthal_icache_line_invalidate(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("ihi %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -#else -# define xthal_icache_line_invalidate(addr) do {/*nothing*/} while(0) -#endif - -#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE -# define xthal_icache_line_lock(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("ipfl %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -# define xthal_icache_line_unlock(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("ihu %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -#else -# define xthal_icache_line_lock(addr) do {/*nothing*/} while(0) -# define xthal_icache_line_unlock(addr) do {/*nothing*/} while(0) -#endif - -/* - * Even if a config doesn't have caches, an isync is still needed - * when instructions in any memory are modified, whether by a loader - * or self-modifying code. Therefore, this macro always produces - * an isync, whether or not an icache is present. - */ -#define xthal_icache_sync() \ - __asm__ __volatile__("isync":::"memory") - - -/*** DATA CACHE ***/ - -#if XCHAL_DCACHE_SIZE > 0 - -# include <xtensa/tie/xt_datacache.h> - -# define xthal_dcache_line_invalidate(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("dhi %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -# define xthal_dcache_line_writeback(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("dhwb %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -# define xthal_dcache_line_writeback_inv(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("dhwbi %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -# define xthal_dcache_sync() \ - __asm__ __volatile__("" /*"dsync"?*/:::"memory") -# define xthal_dcache_line_prefetch_for_read(addr) do { \ - XT_DPFR((const int*)addr, 0); \ - } while(0) -#else -# define xthal_dcache_line_invalidate(addr) do {/*nothing*/} while(0) -# define xthal_dcache_line_writeback(addr) do {/*nothing*/} while(0) -# define xthal_dcache_line_writeback_inv(addr) do {/*nothing*/} while(0) -# define xthal_dcache_sync() __asm__ __volatile__("":::"memory") -# define xthal_dcache_line_prefetch_for_read(addr) do {/*nothing*/} while(0) -#endif - -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE -# define xthal_dcache_line_lock(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("dpfl %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -# define xthal_dcache_line_unlock(addr) do { void *__a = (void*)(addr); \ - __asm__ __volatile__("dhu %0, 0" :: "a"(__a) : "memory"); \ - } while(0) -#else -# define xthal_dcache_line_lock(addr) do {/*nothing*/} while(0) -# define xthal_dcache_line_unlock(addr) do {/*nothing*/} while(0) -#endif - -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK - -# define xthal_dcache_line_prefetch_for_write(addr) do { \ - XT_DPFW((const int*)addr, 0); \ - } while(0) -#else -# define xthal_dcache_line_prefetch_for_write(addr) do {/*nothing*/} while(0) -#endif - - -/***** Block Operations *****/ - -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_HAVE_CACHE_BLOCKOPS - -/* upgrades */ - -# define _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, type) \ - { \ - type((const int*)addr, size); \ - } - -/*downgrades */ - -# define _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, type) \ - unsigned _s = size; \ - unsigned _a = (unsigned) addr; \ - do { \ - unsigned __s = (_s > XCHAL_DCACHE_SIZE) ? \ - XCHAL_DCACHE_SIZE : _s; \ - type((const int*)_a, __s); \ - _s -= __s; \ - _a += __s; \ - } while(_s > 0); - -# define _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, type, max) \ - if (max <= XCHAL_DCACHE_SIZE) { \ - unsigned _s = size; \ - unsigned _a = (unsigned) addr; \ - type((const int*)_a, _s); \ - } \ - else { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, type); \ - } - -# define xthal_dcache_block_invalidate(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, XT_DHI_B); \ - } while(0) -# define xthal_dcache_block_writeback(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, XT_DHWB_B); \ - } while(0) -# define xthal_dcache_block_writeback_inv(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE(addr, size, XT_DHWBI_B); \ - } while(0) - -# define xthal_dcache_block_invalidate_max(addr, size, max) do { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, XT_DHI_B, max); \ - } while(0) -# define xthal_dcache_block_writeback_max(addr, size, max) do { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, XT_DHWB_B, max); \ - } while(0) -# define xthal_dcache_block_writeback_inv_max(addr, size, max) do { \ - _XTHAL_DCACHE_BLOCK_DOWNGRADE_MAX(addr, size, XT_DHWBI_B, max); \ - } while(0) - -/* upgrades that are performed even with write-thru caches */ - -# define xthal_dcache_block_prefetch_read_write(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_B); \ - } while(0) -# define xthal_dcache_block_prefetch_read_write_grp(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_BF); \ - } while(0) -# define xthal_dcache_block_prefetch_for_read(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFR_B); \ - } while(0) -# define xthal_dcache_block_prefetch_for_read_grp(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFR_BF); \ - } while(0) - -/* abort all or end optional block cache operations */ -# define xthal_dcache_block_abort() do { \ - XT_PFEND_A(); \ - } while(0) -# define xthal_dcache_block_end() do { \ - XT_PFEND_O(); \ - } while(0) - -/* wait for all/required block cache operations to finish */ -# define xthal_dcache_block_wait() do { \ - XT_PFWAIT_A(); \ - } while(0) -# define xthal_dcache_block_required_wait() do { \ - XT_PFWAIT_R(); \ - } while(0) -/* Start a new group */ -# define xthal_dcache_block_newgrp() do { \ - XT_PFNXT_F(); \ - } while(0) -#else -# define xthal_dcache_block_invalidate(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_writeback(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_writeback_inv(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_invalidate_max(addr, size, max) do {/*nothing*/} while(0) -# define xthal_dcache_block_writeback_max(addr, size, max) do {/*nothing*/} while(0) -# define xthal_dcache_block_writeback_inv_max(addr, size, max) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_read_write(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_read_write_grp(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_for_read(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_for_read_grp(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_end() do {/*nothing*/} while(0) -# define xthal_dcache_block_abort() do {/*nothing*/} while(0) -# define xthal_dcache_block_wait() do {/*nothing*/} while(0) -# define xthal_dcache_block_required_wait() do {/*nothing*/} while(0) -# define xthal_dcache_block_newgrp() do {/*nothing*/} while(0) -#endif - -#if XCHAL_DCACHE_SIZE > 0 && XCHAL_HAVE_CACHE_BLOCKOPS && XCHAL_DCACHE_IS_WRITEBACK - -# define xthal_dcache_block_prefetch_for_write(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_B); \ - } while(0) -# define xthal_dcache_block_prefetch_modify(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFM_B); \ - } while(0) -# define xthal_dcache_block_prefetch_for_write_grp(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFW_BF); \ - } while(0) -# define xthal_dcache_block_prefetch_modify_grp(addr, size) do { \ - _XTHAL_DCACHE_BLOCK_UPGRADE(addr, size, XT_DPFM_BF); \ - } while(0) -#else -# define xthal_dcache_block_prefetch_for_write(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_modify(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_for_write_grp(addr, size) do {/*nothing*/} while(0) -# define xthal_dcache_block_prefetch_modify_grp(addr, size) do {/*nothing*/} while(0) -#endif - -/*************************** INTERRUPTS ***************************/ - -/* - * Macro versions of: - * unsigned xthal_get_intenable( void ); - * void xthal_set_intenable( unsigned ); - * unsigned xthal_get_interrupt( void ); - * void xthal_set_intset( unsigned ); - * void xthal_set_intclear( unsigned ); - * unsigned xthal_get_ccount(void); - * void xthal_set_ccompare(int, unsigned); - * unsigned xthal_get_ccompare(int); - * - * NOTE: for {set,get}_ccompare, the first argument MUST be a decimal constant. - */ - -#if XCHAL_HAVE_INTERRUPTS -# define XTHAL_GET_INTENABLE() ({ int __intenable; \ - __asm__("rsr.intenable %0" : "=a"(__intenable)); \ - __intenable; }) -# define XTHAL_SET_INTENABLE(v) do { int __intenable = (int)(v); \ - __asm__ __volatile__("wsr.intenable %0" :: "a"(__intenable):"memory"); \ - } while(0) -# define XTHAL_GET_INTERRUPT() ({ int __interrupt; \ - __asm__("rsr.interrupt %0" : "=a"(__interrupt)); \ - __interrupt; }) -# define XTHAL_SET_INTSET(v) do { int __interrupt = (int)(v); \ - __asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \ - } while(0) -# define XTHAL_SET_INTCLEAR(v) do { int __interrupt = (int)(v); \ - __asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \ - } while(0) -# define XTHAL_GET_CCOUNT() ({ int __ccount; \ - __asm__("rsr.ccount %0" : "=a"(__ccount)); \ - __ccount; }) -# define XTHAL_SET_CCOUNT(v) do { int __ccount = (int)(v); \ - __asm__ __volatile__("wsr.ccount %0" :: "a"(__ccount):"memory"); \ - } while(0) -# define _XTHAL_GET_CCOMPARE(n) ({ int __ccompare; \ - __asm__("rsr.ccompare" #n " %0" : "=a"(__ccompare)); \ - __ccompare; }) -# define XTHAL_GET_CCOMPARE(n) _XTHAL_GET_CCOMPARE(n) -# define _XTHAL_SET_CCOMPARE(n,v) do { int __ccompare = (int)(v); \ - __asm__ __volatile__("wsr.ccompare" #n " %0 ; esync" :: "a"(__ccompare):"memory"); \ - } while(0) -# define XTHAL_SET_CCOMPARE(n,v) _XTHAL_SET_CCOMPARE(n,v) -#else -# define XTHAL_GET_INTENABLE() 0 -# define XTHAL_SET_INTENABLE(v) do {/*nothing*/} while(0) -# define XTHAL_GET_INTERRUPT() 0 -# define XTHAL_SET_INTSET(v) do {/*nothing*/} while(0) -# define XTHAL_SET_INTCLEAR(v) do {/*nothing*/} while(0) -# define XTHAL_GET_CCOUNT() 0 -# define XTHAL_SET_CCOUNT(v) do {/*nothing*/} while(0) -# define XTHAL_GET_CCOMPARE(n) 0 -# define XTHAL_SET_CCOMPARE(n,v) do {/*nothing*/} while(0) -#endif - -/* New functions added to accomodate XEA3 and allow deprecation of older - functions. For this release they just map to the older ones. */ - -/* Enables the specified interrupt. */ -static inline void xthal_interrupt_enable(unsigned intnum) -{ - xthal_int_enable(1 << intnum); -} - -/* Disables the specified interrupt. */ -static inline void xthal_interrupt_disable(unsigned intnum) -{ - xthal_int_disable(1 << intnum); -} - -/* Triggers the specified interrupt. */ -static inline void xthal_interrupt_trigger(unsigned intnum) -{ - xthal_set_intset(1 << intnum); -} - -/* Clears the specified interrupt. */ -static inline void xthal_interrupt_clear(unsigned intnum) -{ - xthal_set_intclear(1 << intnum); -} - - -/*************************** MISC ***************************/ - -/* - * Macro or inline versions of: - * void xthal_clear_regcached_code( void ); - * unsigned xthal_get_prid( void ); - * unsigned xthal_compare_and_set( int *addr, int testval, int setval ); - */ - -#if XCHAL_HAVE_LOOPS -# define XTHAL_CLEAR_REGCACHED_CODE() \ - __asm__ __volatile__("wsr.lcount %0" :: "a"(0) : "memory") -#else -# define XTHAL_CLEAR_REGCACHED_CODE() do {/*nothing*/} while(0) -#endif - -#if XCHAL_HAVE_PRID -# define XTHAL_GET_PRID() ({ int __prid; \ - __asm__("rsr.prid %0" : "=a"(__prid)); \ - __prid; }) -#else -# define XTHAL_GET_PRID() 0 -#endif - - -static inline unsigned XTHAL_COMPARE_AND_SET( int *addr, int testval, int setval ) -{ - int result; - -#if XCHAL_HAVE_S32C1I && XCHAL_HW_MIN_VERSION_MAJOR >= 2200 - __asm__ __volatile__ ( - " wsr.scompare1 %2 \n" - " s32c1i %0, %3, 0 \n" - : "=a"(result) : "0" (setval), "a" (testval), "a" (addr) - : "memory"); -#elif XCHAL_HAVE_INTERRUPTS - int tmp; - __asm__ __volatile__ ( - " rsil %4, 15 \n" // %4 == saved ps - " l32i %0, %3, 0 \n" // %0 == value to test, return val - " bne %2, %0, 9f \n" // test - " s32i %1, %3, 0 \n" // write the new value - "9: wsr.ps %4 ; rsync \n" // restore the PS - : "=a"(result) - : "0" (setval), "a" (testval), "a" (addr), "a" (tmp) - : "memory"); -#else - __asm__ __volatile__ ( - " l32i %0, %3, 0 \n" // %0 == value to test, return val - " bne %2, %0, 9f \n" // test - " s32i %1, %3, 0 \n" // write the new value - "9: \n" - : "=a"(result) : "0" (setval), "a" (testval), "a" (addr) - : "memory"); -#endif - return result; -} - -#if XCHAL_HAVE_EXTERN_REGS - -static inline unsigned XTHAL_RER (unsigned int reg) -{ - unsigned result; - - __asm__ __volatile__ ( - " rer %0, %1" - : "=a" (result) : "a" (reg) : "memory"); - - return result; -} - -static inline void XTHAL_WER (unsigned reg, unsigned value) -{ - __asm__ __volatile__ ( - " wer %0, %1" - : : "a" (value), "a" (reg) : "memory"); -} - -#endif /* XCHAL_HAVE_EXTERN_REGS */ - -/* - * Sets a single entry at 'index' within the MPU - * - * The caller must ensure that the resulting MPU map is ordered. - */ -static inline void xthal_mpu_set_entry (xthal_MPU_entry entry) -{ -#if XCHAL_HAVE_MPU - __asm__ __volatile__("j 1f\n\t.align 8\n\t1: memw\n\twptlb %0, %1\n\t" : : "a" (entry.at), "a"(entry.as)); -#endif -} - -/* Same as xthal_mpu_set_entry except that this function must not be used to change the MPU entry - * for the currently executing instruction ... use xthal_mpu_set_entry instead. */ -static inline void xthal_mpu_set_entry_ (xthal_MPU_entry entry) -{ -#if XCHAL_HAVE_MPU - __asm__ __volatile__("wptlb %0, %1\n\t" : : "a" (entry.at), "a"(entry.as)); -#endif -} - - - -#endif /* C code */ - -#endif /*XTENSA_CACHE_H*/ - diff --git a/src/arch/xtensa/include/xtensa/coreasm.h b/src/arch/xtensa/include/xtensa/coreasm.h deleted file mode 100644 index 335c0c30b7a2..000000000000 --- a/src/arch/xtensa/include/xtensa/coreasm.h +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * xtensa/coreasm.h -- assembler-specific definitions that depend on CORE configuration - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * It is perfectly normal, however, for the HAL itself to include this file. - * - * This file must NOT include xtensa/config/system.h. Any assembler - * header file that depends on system information should likely go - * in a new systemasm.h (or sysasm.h) header file. - * - * NOTE: macro beqi32 is NOT configuration-dependent, and is placed - * here until we have a proper configuration-independent header file. - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/include/xtensa/coreasm.h#1 $ */ - -/* - * Copyright (c) 2000-2014 Tensilica 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. - */ - -#ifndef XTENSA_COREASM_H -#define XTENSA_COREASM_H - -/* - * Tell header files this is assembly source, so they can avoid non-assembler - * definitions (eg. C types etc): - */ -#ifndef _ASMLANGUAGE /* conditionalize to avoid cpp warnings (3rd parties might use same macro) */ -#define _ASMLANGUAGE -#endif - -#include <xtensa/config/core.h> -#include <xtensa/config/specreg.h> -#include <xtensa/config/system.h> - -/* - * Assembly-language specific definitions (assembly macros, etc.). - */ - -/*---------------------------------------------------------------------- - * find_ms_setbit - * - * This macro finds the most significant bit that is set in <as> - * and return its index + <base> in <ad>, or <base> - 1 if <as> is zero. - * The index counts starting at zero for the lsbit, so the return - * value ranges from <base>-1 (no bit set) to <base>+31 (msbit set). - * - * Parameters: - * <ad> destination address register (any register) - * <as> source address register - * <at> temporary address register (must be different than <as>) - * <base> constant value added to result (usually 0 or 1) - * On entry: - * <ad> = undefined if different than <as> - * <as> = value whose most significant set bit is to be found - * <at> = undefined - * no other registers are used by this macro. - * On exit: - * <ad> = <base> + index of msbit set in original <as>, - * = <base> - 1 if original <as> was zero. - * <as> clobbered (if not <ad>) - * <at> clobbered (if not <ad>) - * Example: - * find_ms_setbit a0, a4, a0, 0 -- return in a0 index of msbit set in a4 - */ - - .macro find_ms_setbit ad, as, at, base -#if XCHAL_HAVE_NSA - movi \at, 31+\base - nsau \as, \as // get index of \as, numbered from msbit (32 if absent) - sub \ad, \at, \as // get numbering from lsbit (0..31, -1 if absent) -#else /* XCHAL_HAVE_NSA */ - movi \at, \base // start with result of 0 (point to lsbit of 32) - - beqz \as, 2f // special case for zero argument: return -1 - bltui \as, 0x10000, 1f // is it one of the 16 lsbits? (if so, check lower 16 bits) - addi \at, \at, 16 // no, increment result to upper 16 bits (of 32) - //srli \as, \as, 16 // check upper half (shift right 16 bits) - extui \as, \as, 16, 16 // check upper half (shift right 16 bits) -1: bltui \as, 0x100, 1f // is it one of the 8 lsbits? (if so, check lower 8 bits) - addi \at, \at, 8 // no, increment result to upper 8 bits (of 16) - srli \as, \as, 8 // shift right to check upper 8 bits -1: bltui \as, 0x10, 1f // is it one of the 4 lsbits? (if so, check lower 4 bits) - addi \at, \at, 4 // no, increment result to upper 4 bits (of 8) - srli \as, \as, 4 // shift right 4 bits to check upper half -1: bltui \as, 0x4, 1f // is it one of the 2 lsbits? (if so, check lower 2 bits) - addi \at, \at, 2 // no, increment result to upper 2 bits (of 4) - srli \as, \as, 2 // shift right 2 bits to check upper half -1: bltui \as, 0x2, 1f // is it the lsbit? - addi \at, \at, 2 // no, increment result to upper bit (of 2) -2: addi \at, \at, -1 // (from just above: add 1; from beqz: return -1) - //srli \as, \as, 1 -1: // done! \at contains index of msbit set (or -1 if none set) - .if 0x\ad - 0x\at // destination different than \at ? (works because regs are a0-a15) - mov \ad, \at // then move result to \ad - .endif -#endif /* XCHAL_HAVE_NSA */ - .endm // find_ms_setbit - -/*---------------------------------------------------------------------- - * find_ls_setbit - * - * This macro finds the least significant bit that is set in <as>, - * and return its index in <ad>. - * Usage is the same as for the find_ms_setbit macro. - * Example: - * find_ls_setbit a0, a4, a0, 0 -- return in a0 index of lsbit set in a4 - */ - - .macro find_ls_setbit ad, as, at, base - neg \at, \as // keep only the least-significant bit that is set... - and \as, \at, \as // ... in \as - find_ms_setbit \ad, \as, \at, \base - .endm // find_ls_setbit - -/*---------------------------------------------------------------------- - * find_ls_one - * - * Same as find_ls_setbit with base zero. - * Source (as) and destination (ad) registers must be different. - * Provided for backward compatibility. - */ - - .macro find_ls_one ad, as - find_ls_setbit \ad, \as, \ad, 0 - .endm // find_ls_one - -/*---------------------------------------------------------------------- - * floop, floopnez, floopgtz, floopend - * - * These macros are used for fast inner loops that - * work whether or not the Loops options is configured. - * If the Loops option is configured, they simply use - * the zero-overhead LOOP instructions; otherwise - * they use explicit decrement and branch instructions. - * - * They are used in pairs, with floop, floopnez or floopgtz - * at the beginning of the loop, and floopend at the end. - * - * Each pair of loop macro calls must be given the loop count - * address register and a unique label for that loop. - * - * Example: - * - * movi a3, 16 // loop 16 times - * floop a3, myloop1 - * : - * bnez a7, end1 // exit loop if a7 != 0 - * : - * floopend a3, myloop1 - * end1: - * - * Like the LOOP instructions, these macros cannot be - * nested, must include at least one instruction, - * cannot call functions inside the loop, etc. - * The loop can be exited by jumping to the instruction - * following floopend (or elsewhere outside the loop), - * or continued by jumping to a NOP instruction placed - * immediately before floopend. - * - * Unlike LOOP instructions, the register passed to floop* - * cannot be used inside the loop, because it is used as - * the loop counter if the Loops option is not configured. - * And its value is undefined after exiting the loop. - * And because the loop counter register is active inside - * the loop, you can't easily use this construct to loop - * across a register file using ROTW as you might with LOOP - * instructions, unless you copy the loop register along. - */ - - /* Named label version of the macros: */ - - .macro floop ar, endlabel - floop_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel - .endm - - .macro floopnez ar, endlabel - floopnez_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel - .endm - - .macro floopgtz ar, endlabel - floopgtz_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel - .endm - - .macro floopend ar, endlabel - floopend_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel - .endm - - /* Numbered local label version of the macros: */ -#if 0 /*UNTESTED*/ - .macro floop89 ar - floop_ \ar, 8, 9f - .endm - - .macro floopnez89 ar - floopnez_ \ar, 8, 9f - .endm - - .macro floopgtz89 ar - floopgtz_ \ar, 8, 9f - .endm - - .macro floopend89 ar - floopend_ \ar, 8b, 9 - .endm -#endif /*0*/ - - /* Underlying version of the macros: */ - - .macro floop_ ar, startlabel, endlabelref - .ifdef _infloop_ - .if _infloop_ - .err // Error: floop cannot be nested - .endif - .endif - .set _infloop_, 1 -#if XCHAL_HAVE_LOOPS - loop \ar, \endlabelref -#else /* XCHAL_HAVE_LOOPS */ -\startlabel: - addi \ar, \ar, -1 -#endif /* XCHAL_HAVE_LOOPS */ - .endm // floop_ - - .macro floopnez_ ar, startlabel, endlabelref - .ifdef _infloop_ - .if _infloop_ - .err // Error: floopnez cannot be nested - .endif - .endif - .set _infloop_, 1 -#if XCHAL_HAVE_LOOPS - loopnez \ar, \endlabelref -#else /* XCHAL_HAVE_LOOPS */ - beqz \ar, \endlabelref -\startlabel: - addi \ar, \ar, -1 -#endif /* XCHAL_HAVE_LOOPS */ - .endm // floopnez_ - - .macro floopgtz_ ar, startlabel, endlabelref - .ifdef _infloop_ - .if _infloop_ - .err // Error: floopgtz cannot be nested - .endif - .endif - .set _infloop_, 1 -#if XCHAL_HAVE_LOOPS - loopgtz \ar, \endlabelref -#else /* XCHAL_HAVE_LOOPS */ - bltz \ar, \endlabelref - beqz \ar, \endlabelref -\startlabel: - addi \ar, \ar, -1 -#endif /* XCHAL_HAVE_LOOPS */ - .endm // floopgtz_ - - - .macro floopend_ ar, startlabelref, endlabel - .ifndef _infloop_ - .err // Error: floopend without matching floopXXX - .endif - .ifeq _infloop_ - .err // Error: floopend without matching floopXXX - .endif - .set _infloop_, 0 -#if ! XCHAL_HAVE_LOOPS - bnez \ar, \startlabelref -#endif /* XCHAL_HAVE_LOOPS */ -\endlabel: - .endm // floopend_ - -/*---------------------------------------------------------------------- - * crsil -- conditional RSIL (read/set interrupt level) - * - * Executes the RSIL instruction if it exists, else just reads PS. - * The RSIL instruction does not exist in the new exception architecture - * if the interrupt option is not selected. - */ - - .macro crsil ar, newlevel -#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS - rsil \ar, \newlevel -#else - rsr.ps \ar -#endif - .endm // crsil - -/*---------------------------------------------------------------------- - * safe_movi_a0 -- move constant into a0 when L32R is not safe - * - * This macro is typically used by interrupt/exception handlers. - * Loads a 32-bit constant in a0, without using any other register, - * and without corrupting the LITBASE register, even when the - * value of the LITBASE register is unknown (eg. when application - * code and interrupt/exception handling code are built independently, - * and thus with independent values of the LITBASE register; - * debug monitors are one example of this). - * - * Worst-case size of resulting code: 17 bytes. - */ - - .macro safe_movi_a0 constant -#if XCHAL_HAVE_ABSOLUTE_LITERALS - /* Contort a PC-relative literal load even though we may be in litbase-relative mode: */ - j 1f - .begin no-transform // ensure what follows is assembled exactly as-is - .align 4 // ensure constant and call0 target ... - .byte 0 // ... are 4-byte aligned (call0 instruction is 3 bytes long) -1: call0 2f // read PC (that follows call0) in a0 - .long \constant // 32-bit constant to load into a0 -2: - .end no-transform - l32i a0, a0, 0 // load constant -#else - movi a0, \constant // no LITBASE, can assume PC-relative L32R -#endif - .endm - - - - -/*---------------------------------------------------------------------- - * window_spill{4,8,12} - * - * These macros spill callers' register windows to the stack. - * They work for both privileged and non-privileged tasks. - * Must be called from a windowed ABI context, eg. within - * a windowed ABI function (ie. valid stack frame, window - * exceptions enabled, not in exception mode, etc). - * - * This macro requires a single invocation of the window_spill_common - * macro in the same assembly unit and section. - * - * Note that using window_spill{4,8,12} macros is more efficient - * than calling a function implemented using window_spill_function, - * because the latter needs extra code to figure out the size of - * the call to the spilling function. - * - * Example usage: - * - * .text - * .align 4 - * .global some_function - * .type some_function,@function - * some_function: - * entry a1, 16 - * : - * : - * - * window_spill4 // Spill windows of some_function's callers; preserves a0..a3 only; - * // to use window_spill{8,12} in this example function we'd have - * // to increase space allocated by the entry instruction, because - * // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed - * // for call8/window_spill8 or call12/window_spill12 respectively. - * - * : - * - * retw - * - * window_spill_common // instantiates code used by window_spill4 - * - * - * On entry: - * none (if window_spill4) - * stack frame has enough space allocated for call8 (if window_spill8) - * stack frame has enough space allocated for call12 (if window_spill12) - * On exit: - * a4..a15 clobbered (if window_spill4) - * a8..a15 clobbered (if window_spill8) - * a12..a15 clobbered (if window_spill12) - * no caller windows are in live registers - */ - - .macro window_spill4 -#if XCHAL_HAVE_WINDOWED -# if XCHAL_NUM_AREGS == 16 - movi a15, 0 // for 16-register files, no need to call to reach the end -# elif XCHAL_NUM_AREGS == 32 - call4 .L__wdwspill_assist28 // call deep enough to clear out any live callers -# elif XCHAL_NUM_AREGS == 64 - call4 .L__wdwspill_assist60 // call deep enough to clear out any live callers -# endif -#endif - .endm // window_spill4 - - .macro window_spill8 -#if XCHAL_HAVE_WINDOWED -# if XCHAL_NUM_AREGS == 16 - movi a15, 0 // for 16-register files, no need to call to reach the end -# elif XCHAL_NUM_AREGS == 32 - call8 .L__wdwspill_assist24 // call deep enough to clear out any live callers -# elif XCHAL_NUM_AREGS == 64 - call8 .L__wdwspill_assist56 // call deep enough to clear out any live callers -# endif -#endif - .endm // window_spill8 - - .macro window_spill12 -#if XCHAL_HAVE_WINDOWED -# if XCHAL_NUM_AREGS == 16 - movi a15, 0 // for 16-register files, no need to call to reach the end -# elif XCHAL_NUM_AREGS == 32 - call12 .L__wdwspill_assist20 // call deep enough to clear out any live callers -# elif XCHAL_NUM_AREGS == 64 - call12 .L__wdwspill_assist52 // call deep enough to clear out any live callers -# endif -#endif - .endm // window_spill12 - - -/*---------------------------------------------------------------------- - * window_spill_function - * - * This macro outputs a function that will spill its caller's callers' - * register windows to the stack. Eg. it could be used to implement - * a version of xthal_window_spill() that works in non-privileged tasks. - * This works for both privileged and non-privileged tasks. - * - * Typical usage: - * - * .text - * .align 4 - * .global my_spill_function - * .type my_spill_function,@function - * my_spill_function: - * window_spill_function - * - * On entry to resulting function: - * none - * On exit from resulting function: - * none (no caller windows are in live registers) - */ - - .macro window_spill_function -#if XCHAL_HAVE_WINDOWED -# if XCHAL_NUM_AREGS == 32 - entry sp, 48 - bbci.l a0, 31, 1f // branch if called with call4 - bbsi.l a0, 30, 2f // branch if called with call12 - call8 .L__wdwspill_assist16 // called with call8, only need another 8 - retw -1: call12 .L__wdwspill_assist16 // called with call4, only need another 12 - retw -2: call4 .L__wdwspill_assist16 // called with call12, only need another 4 - retw -# elif XCHAL_NUM_AREGS == 64 - entry sp, 48 - bbci.l a0, 31, 1f // branch if called with call4 - bbsi.l a0, 30, 2f // branch if called with call12 - call4 .L__wdwspill_assist52 // called with call8, only need a call4 - retw -1: call8 .L__wdwspill_assist52 // called with call4, only need a call8 - retw -2: call12 .L__wdwspill_assist40 // called with call12, can skip a call12 - retw -# elif XCHAL_NUM_AREGS == 16 - entry sp, 16 - bbci.l a0, 31, 1f // branch if called with call4 - bbsi.l a0, 30, 2f // branch if called with call12 - movi a7, 0 // called with call8 - retw -1: movi a11, 0 // called with call4 -2: retw // if called with call12, everything already spilled - -// movi a15, 0 // trick to spill all but the direct caller -// j 1f -// // The entry instruction is magical in the assembler (gets auto-aligned) -// // so we have to jump to it to avoid falling through the padding. -// // We need entry/retw to know where to return. -//1: entry sp, 16 -// retw -# else -# error "unrecognized address register file size" -# endif - -#endif /* XCHAL_HAVE_WINDOWED */ - window_spill_common - .endm // window_spill_function - -/*---------------------------------------------------------------------- - * window_spill_common - * - * Common code used by any number of invocations of the window_spill## - * and window_spill_function macros. - * - * Must be instantiated exactly once within a given assembly unit, - * within call/j range of and same section as window_spill## - * macro invocations for that assembly unit. - * (Is automatically instantiated by the window_spill_function macro.) - */ - - .macro window_spill_common -#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64) - .ifndef .L__wdwspill_defined -# if XCHAL_NUM_AREGS >= 64 -.L__wdwspill_assist60: - entry sp, 32 - call8 .L__wdwspill_assist52 - retw -.L__wdwspill_assist56: - entry sp, 16 - call4 .L__wdwspill_assist52 - retw -.L__wdwspill_assist52: - entry sp, 48 - call12 .L__wdwspill_assist40 - retw -.L__wdwspill_assist40: - entry sp, 48 - call12 .L__wdwspill_assist28 - retw -# endif -.L__wdwspill_assist28: - entry sp, 48 - call12 .L__wdwspill_assist16 - retw -.L__wdwspill_assist24: - entry sp, 32 - call8 .L__wdwspill_assist16 - retw -.L__wdwspill_assist20: - entry sp, 16 - call4 .L__wdwspill_assist16 - retw -.L__wdwspill_assist16: - entry sp, 16 - movi a15, 0 - retw - .set .L__wdwspill_defined, 1 - .endif -#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */ - .endm // window_spill_common - -/*---------------------------------------------------------------------- - * beqi32 - * - * macro implements version of beqi for arbitrary 32-bit immediate value - * - * beqi32 ax, ay, imm32, label - * - * Compares value in register ax with imm32 value and jumps to label if - * equal. Clobbers register ay if needed - * - */ - .macro beqi32 ax, ay, imm, label - .ifeq ((\imm-1) & ~7) // 1..8 ? - beqi \ax, \imm, \label - .else - .ifeq (\imm+1) // -1 ? - beqi \ax, \imm, \label - .else - .ifeq (\imm) // 0 ? - beqz \ax, \label - .else - // We could also handle immediates 10,12,16,32,64,128,256 - // but it would be a long macro... - movi \ay, \imm - beq \ax, \ay, \label - .endif - .endif - .endif - .endm // beqi32 - -/*---------------------------------------------------------------------- - * isync_retw_nop - * - * This macro must be invoked immediately after ISYNC if ISYNC - * would otherwise be immediately followed by RETW (or other instruction - * modifying WindowBase or WindowStart), in a context where - * kernel vector mode may be selected, and level-one interrupts - * and window overflows may be enabled, on an XEA1 configuration. - * - * On hardware with erratum "XEA1KWIN" (see <xtensa/core.h> for details), - * XEA1 code must have at least one instruction between ISYNC and RETW if - * run in kernel vector mode with interrupts and window overflows enabled. - */ - .macro isync_retw_nop -#if XCHAL_MAYHAVE_ERRATUM_XEA1KWIN - nop -#endif - .endm - -/*---------------------------------------------------------------------- - * isync_return_nop - * - * This macro should be used instead of isync_retw_nop in code that is - * intended to run on both the windowed and call0 ABIs - */ - .macro isync_return_nop -#ifdef __XTENSA_WINDOWED_ABI__ - isync_retw_nop -#endif - .endm - -/*---------------------------------------------------------------------- - * isync_erratum453 - * - * This macro must be invoked at certain points in the code, - * such as in exception and interrupt vectors in particular, - * to work around erratum 453. - */ - .macro isync_erratum453 -#if XCHAL_ERRATUM_453 - isync -#endif - .endm - - -/*---------------------------------------------------------------------- - * readsr - * - * wrapper for 'rsr' that constructs register names that involve levels - * e.g. EPCn etc. Use like so: - * readsr epc XCHAL_DEBUGLEVEL a2 - */ - .macro readsr reg suf ar - rsr.\reg\suf \ar - .endm - -/*---------------------------------------------------------------------- - * writesr - * - * wrapper for 'wsr' that constructs register names that involve levels - * e.g. EPCn etc. Use like so: - * writesr epc XCHAL_DEBUGLEVEL a2 - */ - .macro writesr reg suf ar - wsr.\reg\suf \ar - .endm - -/*---------------------------------------------------------------------- - * xchgsr - * - * wrapper for 'xsr' that constructs register names that involve levels - * e.g. EPCn etc. Use like so: - * xchgsr epc XCHAL_DEBUGLEVEL a2 - */ - .macro xchgsr reg suf ar - xsr.\reg\suf \ar - .endm - -/*---------------------------------------------------------------------- - * INDEX_SR - * - * indexing wrapper for rsr/wsr/xsr that constructs register names from - * the provided base name and the current index. Use like so: - * .set _idx, 0 - * INDEX_SR rsr.ccompare a2 - * - * this yields: rsr.ccompare0 a2 - */ - .macro INDEX_SR instr ar -.ifeq (_idx) - &instr&0 \ar -.endif -.ifeq (_idx-1) - &instr&1 \ar -.endif -.ifeq (_idx-2) - &instr&2 \ar -.endif -.ifeq (_idx-3) - &instr&3 \ar -.endif -.ifeq (_idx-4) - &instr&4 \ar -.endif -.ifeq (_idx-5) - &instr&5 \ar -.endif -.ifeq (_idx-6) - &instr&6 \ar -.endif -.ifeq (_idx-7) - &instr&7 \ar -.endif - .endm - - -/*---------------------------------------------------------------------- - * abs - * - * implements abs on machines that do not have it configured - */ - -#if !XCHAL_HAVE_ABS - .macro abs arr, ars - .ifc \arr, \ars - //src equal dest is less efficient - bgez \arr, 1f - neg \arr, \arr -1: - .else - neg \arr, \ars - movgez \arr, \ars, \ars - .endif - .endm -#endif /* !XCHAL_HAVE_ABS */ - - -/*---------------------------------------------------------------------- - * addx2 - * - * implements addx2 on machines that do not have it configured - * - */ - -#if !XCHAL_HAVE_ADDX - .macro addx2 arr, ars, art - .ifc \arr, \art - .ifc \arr, \ars - // addx2 a, a, a (not common) - .err - .else - add \arr, \ars, \art - add \arr, \ars, \art - .endif - .else - //addx2 a, b, c - //addx2 a, a, b - //addx2 a, b, b - slli \arr, \ars, 1 - add \arr, \arr, \art - .endif - .endm -#endif /* !XCHAL_HAVE_ADDX */ - -/*---------------------------------------------------------------------- - * addx4 - * - * implements addx4 on machines that do not have it configured - * - */ - -#if !XCHAL_HAVE_ADDX - .macro addx4 arr, ars, art - .ifc \arr, \art - .ifc \arr, \ars - // addx4 a, a, a (not common) - .err - .else - //# addx4 a, b, a - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - .endif - .else - //addx4 a, b, c - //addx4 a, a, b - //addx4 a, b, b - slli \arr, \ars, 2 - add \arr, \arr, \art - .endif - .endm -#endif /* !XCHAL_HAVE_ADDX */ - -/*---------------------------------------------------------------------- - * addx8 - * - * implements addx8 on machines that do not have it configured - * - */ - -#if !XCHAL_HAVE_ADDX - .macro addx8 arr, ars, art - .ifc \arr, \art - .ifc \arr, \ars - //addx8 a, a, a (not common) - .err - .else - //addx8 a, b, a - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - add \arr, \ars, \art - .endif - .else - //addx8 a, b, c - //addx8 a, a, b - //addx8 a, b, b - slli \arr, \ars, 3 - add \arr, \arr, \art - .endif - .endm -#endif /* !XCHAL_HAVE_ADDX */ - - -/*---------------------------------------------------------------------- - * rfe_rfue - * - * Maps to RFUE on XEA1, and RFE on XEA2. No mapping on XEAX. - */ - -#if XCHAL_HAVE_XEA1 - .macro rfe_rfue - rfue - .endm -#elif XCHAL_HAVE_XEA2 - .macro rfe_rfue - rfe - .endm -#endif - - -/*---------------------------------------------------------------------- - * abi_entry - * - * Generate proper function entry sequence for the current ABI - * (windowed or call0). Takes care of allocating stack space (up to 1kB) - * and saving the return PC, if necessary. The corresponding abi_return - * macro does the corresponding stack deallocation and restoring return PC. - * - * Parameters are: - * - * locsize Number of bytes to allocate on the stack - * for local variables (and for args to pass to - * callees, if any calls are made). Defaults to zero. - * The macro rounds this up to a multiple of 16. - * NOTE: large values are allowed (e.g. up to 1 GB). - * - * callsize Maximum call size made by this function. - * Leave zero (default) for leaf functions, i.e. if - * this function makes no calls to other functions. - * Otherwise must be set to 4, 8, or 12 according - * to whether the "largest" call made is a call[x]4, - * call[x]8, or call[x]12 (for call0 ABI, it makes - * no difference whether this is set to 4, 8 or 12, - * but it must be set to one of these values). - * - * NOTE: It is up to the caller to align the entry point, declare the - * function symbol, make it global, etc. - * - * NOTE: This macro relies on assembler relaxation for large values - * of locsize. It might not work with the no-transform directive. - * NOTE: For the call0 ABI, this macro ensures SP is allocated or - * de-allocated cleanly, i.e. without temporarily allocating too much - * (or allocating negatively!) due to addi relaxation. - * - * NOTE: Generating the proper sequence and register allocation for - * making calls in an ABI independent manner is a separate topic not - * covered by this macro. - * - * NOTE: To access arguments, you can't use a fixed offset from SP. - * The offset depends on the ABI, whether the function is leaf, etc. - * The simplest method is probably to use the .locsz symbol, which - * is set by this macro to the actual number of bytes allocated on - * the stack, in other words, to the offset from SP to the arguments. - * E.g. for a function whose arguments are all 32-bit integers, you - * can get the 7th and 8th arguments (1st and 2nd args stored on stack) - * using: - * l32i a2, sp, .locsz - * l32i a3, sp, .locsz+4 - * (this example works as long as locsize is under L32I's offset limit - * of 1020 minus up to 48 bytes of ABI-specific stack usage; - * otherwise you might first need to do "addi a?, sp, .locsz" - * or similar sequence). - * - * NOTE: For call0 ABI, this macro (and abi_return) may clobber a9 - * (a caller-saved register). - * - * Examples: - * abi_entry - * abi_entry 5 - * abi_entry 22, 8 - * abi_entry 0, 4 - */ - - /* - * Compute .locsz and .callsz without emitting any instructions. - * Used by both abi_entry and abi_return. - * Assumes locsize >= 0. - */ - .macro abi_entry_size locsize=0, callsize=0 -#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ - .ifeq \callsize - .set .callsz, 16 - .else - .ifeq \callsize-4 - .set .callsz, 16 - .else - .ifeq \callsize-8 - .set .callsz, 32 - .else - .ifeq \callsize-12 - .set .callsz, 48 - .else - .error "abi_entry: invalid call size \callsize" - .endif - .endif - .endif - .endif - .set .locsz, .callsz + ((\locsize + 15) & -16) -#else - .set .callsz, \callsize - .if .callsz /* if calls, need space for return PC */ - .set .locsz, (\locsize + 4 + 15) & -16 - .else - .set .locsz, (\locsize + 15) & -16 - .endif -#endif - .endm - - .macro abi_entry locsize=0, callsize=0 - .iflt \locsize - .error "abi_entry: invalid negative size of locals (\locsize)" - .endif - abi_entry_size \locsize, \callsize -#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ -# define ABI_ENTRY_MINSIZE 3 /* size of abi_entry (no arguments) instructions in bytes */ - .ifgt .locsz - 32760 /* .locsz > 32760 (ENTRY's max range)? */ - /* Funky computation to try to have assembler use addmi efficiently if possible: */ - entry sp, 0x7F00 + (.locsz & 0xF0) - addi a12, sp, - ((.locsz & -0x100) - 0x7F00) - movsp sp, a12 - .else - entry sp, .locsz - .endif -#else -# define ABI_ENTRY_MINSIZE 0 /* size of abi_entry (no arguments) instructions in bytes */ - .if .locsz - .ifle .locsz - 128 /* if locsz <= 128 */ - addi sp, sp, -.locsz - .if .callsz - s32i a0, sp, .locsz - 4 - .endif - .elseif .callsz /* locsz > 128, with calls: */ - movi a9, .locsz - 16 /* note: a9 is caller-saved */ - addi sp, sp, -16 - s32i a0, sp, 12 - sub sp, sp, a9 - .else /* locsz > 128, no calls: */ - movi a9, .locsz - sub sp, sp, a9 - .endif /* end */ - .endif -#endif - .endm - - - -/*---------------------------------------------------------------------- - * abi_return - * - * Generate proper function exit sequence for the current ABI - * (windowed or call0). Takes care of freeing stack space and - * restoring the return PC, if necessary. - * NOTE: This macro MUST be invoked following a corresponding - * abi_entry macro invocation. For call0 ABI in particular, - * all stack and PC restoration are done according to the last - * abi_entry macro invoked before this macro in the assembly file. - * - * Normally this macro takes no arguments. However to allow - * for placing abi_return *before* abi_entry (as must be done - * for some highly optimized assembly), it optionally takes - * exactly the same arguments as abi_entry. - */ - - .macro abi_return locsize=-1, callsize=0 - .ifge \locsize - abi_entry_size \locsize, \callsize - .endif -#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ - retw -#else - .if .locsz - .iflt .locsz - 128 /* if locsz < 128 */ - .if .callsz - l32i a0, sp, .locsz - 4 - .endif - addi sp, sp, .locsz - .elseif .callsz /* locsz >= 128, with calls: */ - addi a9, sp, .locsz - 16 - l32i a0, a9, 12 - addi sp, a9, 16 - .else /* locsz >= 128, no calls: */ - movi a9, .locsz - add sp, sp, a9 - .endif /* end */ - .endif - ret -#endif - .endm - - -/* - * HW erratum fixes. - */ - - .macro hw_erratum_487_fix -#if defined XSHAL_ERRATUM_487_FIX - isync -#endif - .endm - -/* - * These macros are internal, subject to change, and should not be used in - * any new code. - */ - -#define _GBL(x) .global x -#define _TYP(x) .type x,@function -#define _ALN(x) .align x -#define _SIZ(x) .size x, . - x -#define _MKEND(x) .purgem endfunc ; .macro endfunc ; _SIZ(x) ; .purgem endfunc ; .macro endfunc ; .endm ; .endm -#define _SYMT(x) _GBL(x); _MKEND(x); _TYP(x); _ALN(4); x: -#define _SYM2(x) _GBL(x); _TYP(x); x: -#define _SYM(x) _GBL(x); _MKEND(x); _ALN(4); x: -.macro endfunc ; .endm - -/* - * the DECLFUNC() macro provides a mechanism for implementing both the - * standard and _nw interface with a single copy of the code. - * - * For Call0 ABI there is one function definition which is labeled with - * both the xthal_..._nw and xthal_... symbols. - * - * For windowed ABI, two compilations are involved (one with the __NW_FUNCTION__ - * symbol defined) resulting in two separate functions (the _nw one without - * the window adjustments). -*/ - -#if defined(__NW_FUNCTION__) -# define DECLFUNC(x) _SYMT(x ## _nw) -#else -# if defined (__XTENSA_CALL0_ABI__) -# define DECLFUNC(x) _SYMT(x); _SYM2(x ## _nw) -# else -# define DECLFUNC(x) _SYMT(x) -# endif -#endif - -#endif /*XTENSA_COREASM_H*/ - diff --git a/src/arch/xtensa/include/xtensa/corebits.h b/src/arch/xtensa/include/xtensa/corebits.h deleted file mode 100644 index c14dabcdcc3c..000000000000 --- a/src/arch/xtensa/include/xtensa/corebits.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * xtensa/corebits.h - Xtensa Special Register field positions, masks, values. - * - * (In previous releases, these were defined in specreg.h, a generated file. - * This file is not generated, ie. it is processor configuration independent.) - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/include/xtensa/corebits.h#1 $ */ - -/* - * Copyright (c) 2005-2011 Tensilica 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. - */ - -#ifndef XTENSA_COREBITS_H -#define XTENSA_COREBITS_H - -/* EXCCAUSE register fields: */ -#define EXCCAUSE_EXCCAUSE_SHIFT 0 -#define EXCCAUSE_EXCCAUSE_MASK 0x3F -/* EXCCAUSE register values: */ -/* - * General Exception Causes - * (values of EXCCAUSE special register set by general exceptions, - * which vector to the user, kernel, or double-exception vectors). - */ -#define EXCCAUSE_ILLEGAL 0 /* Illegal Instruction */ -#define EXCCAUSE_SYSCALL 1 /* System Call (SYSCALL instruction) */ -#define EXCCAUSE_INSTR_ERROR 2 /* Instruction Fetch Error */ -# define EXCCAUSE_IFETCHERROR 2 /* (backward compatibility macro, deprecated, avoid) */ -#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error */ -# define EXCCAUSE_LOADSTOREERROR 3 /* (backward compatibility macro, deprecated, avoid) */ -#define EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt */ -# define EXCCAUSE_LEVEL1INTERRUPT 4 /* (backward compatibility macro, deprecated, avoid) */ -#define EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (MOVSP instruction) for alloca */ -#define EXCCAUSE_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero */ -#define EXCCAUSE_SPECULATION 7 /* Use of Failed Speculative Access (not implemented) */ -#define EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction */ -#define EXCCAUSE_UNALIGNED 9 /* Unaligned Load or Store */ -/* Reserved 10..11 */ -#define EXCCAUSE_INSTR_DATA_ERROR 12 /* PIF Data Error on Instruction Fetch (RB-200x and later) */ -#define EXCCAUSE_LOAD_STORE_DATA_ERROR 13 /* PIF Data Error on Load or Store (RB-200x and later) */ -#define EXCCAUSE_INSTR_ADDR_ERROR 14 /* PIF Address Error on Instruction Fetch (RB-200x and later) */ -#define EXCCAUSE_LOAD_STORE_ADDR_ERROR 15 /* PIF Address Error on Load or Store (RB-200x and later) */ -#define EXCCAUSE_ITLB_MISS 16 /* ITLB Miss (no ITLB entry matches, hw refill also missed) */ -#define EXCCAUSE_ITLB_MULTIHIT 17 /* ITLB Multihit (multiple ITLB entries match) */ -#define EXCCAUSE_INSTR_RING 18 /* Ring Privilege Violation on Instruction Fetch */ -/* Reserved 19 */ /* Size Restriction on IFetch (not implemented) */ -#define EXCCAUSE_INSTR_PROHIBITED 20 /* Cache Attribute does not allow Instruction Fetch */ -/* Reserved 21..23 */ -#define EXCCAUSE_DTLB_MISS 24 /* DTLB Miss (no DTLB entry matches, hw refill also missed) */ -#define EXCCAUSE_DTLB_MULTIHIT 25 /* DTLB Multihit (multiple DTLB entries match) */ -#define EXCCAUSE_LOAD_STORE_RING 26 /* Ring Privilege Violation on Load or Store */ -/* Reserved 27 */ /* Size Restriction on Load/Store (not implemented) */ -#define EXCCAUSE_LOAD_PROHIBITED 28 /* Cache Attribute does not allow Load */ -#define EXCCAUSE_STORE_PROHIBITED 29 /* Cache Attribute does not allow Store */ -/* Reserved 30..31 */ -#define EXCCAUSE_CP_DISABLED(n) (32+(n)) /* Access to Coprocessor 'n' when disabled */ -#define EXCCAUSE_CP0_DISABLED 32 /* Access to Coprocessor 0 when disabled */ -#define EXCCAUSE_CP1_DISABLED 33 /* Access to Coprocessor 1 when disabled */ -#define EXCCAUSE_CP2_DISABLED 34 /* Access to Coprocessor 2 when disabled */ -#define EXCCAUSE_CP3_DISABLED 35 /* Access to Coprocessor 3 when disabled */ -#define EXCCAUSE_CP4_DISABLED 36 /* Access to Coprocessor 4 when disabled */ -#define EXCCAUSE_CP5_DISABLED 37 /* Access to Coprocessor 5 when disabled */ -#define EXCCAUSE_CP6_DISABLED 38 /* Access to Coprocessor 6 when disabled */ -#define EXCCAUSE_CP7_DISABLED 39 /* Access to Coprocessor 7 when disabled */ -/* Reserved 40..63 */ - -/* PS register fields: */ -#define PS_WOE_SHIFT 18 -#define PS_WOE_MASK 0x00040000 -#define PS_WOE PS_WOE_MASK -#define PS_CALLINC_SHIFT 16 -#define PS_CALLINC_MASK 0x00030000 -#define PS_CALLINC(n) (((n)&3)<<PS_CALLINC_SHIFT) /* n = 0..3 */ -#define PS_OWB_SHIFT 8 -#define PS_OWB_MASK 0x00000F00 -#define PS_OWB(n) (((n)&15)<<PS_OWB_SHIFT) /* n = 0..15 (or 0..7) */ -#define PS_RING_SHIFT 6 -#define PS_RING_MASK 0x000000C0 -#define PS_RING(n) (((n)&3)<<PS_RING_SHIFT) /* n = 0..3 */ -#define PS_UM_SHIFT 5 -#define PS_UM_MASK 0x00000020 -#define PS_UM PS_UM_MASK -#define PS_EXCM_SHIFT 4 -#define PS_EXCM_MASK 0x00000010 -#define PS_EXCM PS_EXCM_MASK -#define PS_INTLEVEL_SHIFT 0 -#define PS_INTLEVEL_MASK 0x0000000F -#define PS_INTLEVEL(n) ((n)&PS_INTLEVEL_MASK) /* n = 0..15 */ -/* ABI-derived field values: */ -#ifdef __XTENSA_CALL0_ABI__ -#define PS_WOE_ABI 0 -#define PS_WOECALL4_ABI 0 -#else -#define PS_WOE_ABI PS_WOE /* 0x40000 */ -#define PS_WOECALL4_ABI (PS_WOE | PS_CALLINC(1)) /* 0x50000, per call4 */ -#endif -/* Backward compatibility (deprecated): */ -#define PS_PROGSTACK_SHIFT PS_UM_SHIFT -#define PS_PROGSTACK_MASK PS_UM_MASK -#define PS_PROG_SHIFT PS_UM_SHIFT -#define PS_PROG_MASK PS_UM_MASK -#define PS_PROG PS_UM - -/* DBREAKCn register fields: */ -#define DBREAKC_MASK_SHIFT 0 -#define DBREAKC_MASK_MASK 0x0000003F -#define DBREAKC_LOADBREAK_SHIFT 30 -#define DBREAKC_LOADBREAK_MASK 0x40000000 -#define DBREAKC_STOREBREAK_SHIFT 31 -#define DBREAKC_STOREBREAK_MASK 0x80000000 - -/* DEBUGCAUSE register fields: */ -#define DEBUGCAUSE_DEBUGINT_SHIFT 5 -#define DEBUGCAUSE_DEBUGINT_MASK 0x20 /* debug interrupt */ -#define DEBUGCAUSE_BREAKN_SHIFT 4 -#define DEBUGCAUSE_BREAKN_MASK 0x10 /* BREAK.N instruction */ -#define DEBUGCAUSE_BREAK_SHIFT 3 -#define DEBUGCAUSE_BREAK_MASK 0x08 /* BREAK instruction */ -#define DEBUGCAUSE_DBREAK_SHIFT 2 -#define DEBUGCAUSE_DBREAK_MASK 0x04 /* DBREAK match */ -#define DEBUGCAUSE_IBREAK_SHIFT 1 -#define DEBUGCAUSE_IBREAK_MASK 0x02 /* IBREAK match */ -#define DEBUGCAUSE_ICOUNT_SHIFT 0 -#define DEBUGCAUSE_ICOUNT_MASK 0x01 /* ICOUNT would increment to zero */ - -/* MESR register fields: */ -#define MESR_MEME 0x00000001 /* memory error */ -#define MESR_MEME_SHIFT 0 -#define MESR_DME 0x00000002 /* double memory error */ -#define MESR_DME_SHIFT 1 -#define MESR_RCE 0x00000010 /* recorded memory error */ -#define MESR_RCE_SHIFT 4 -#define MESR_LCE -#define MESR_LCE_SHIFT ? -#define MESR_LCE_L -#define MESR_ERRENAB 0x00000100 -#define MESR_ERRENAB_SHIFT 8 -#define MESR_ERRTEST 0x00000200 -#define MESR_ERRTEST_SHIFT 9 -#define MESR_DATEXC 0x00000400 -#define MESR_DATEXC_SHIFT 10 -#define MESR_INSEXC 0x00000800 -#define MESR_INSEXC_SHIFT 11 -#define MESR_WAYNUM_SHIFT 16 -#define MESR_ACCTYPE_SHIFT 20 -#define MESR_MEMTYPE_SHIFT 24 -#define MESR_ERRTYPE_SHIFT 30 - -/* MEMCTL register fields: */ -#define MEMCTL_SNOOP_EN_SHIFT 1 -#define MEMCTL_SNOOP_EN 0x02 /* enable snoop responses (default 0) */ -#define MEMCTL_L0IBUF_EN_SHIFT 0 -#define MEMCTL_L0IBUF_EN 0x01 /* enable loop instr. buffer (default 1) */ -#define MEMCTL_INV_EN_SHIFT 23 -#define MEMCTL_INV_EN 0x00800000 /* invalidate cache ways being increased */ -#define MEMCTL_DCWU_SHIFT 8 -#define MEMCTL_DCWU_BITS 5 -#define MEMCTL_DCWA_SHIFT 13 -#define MEMCTL_DCWA_BITS 5 -#define MEMCTL_ICWU_SHIFT 18 -#define MEMCTL_ICWU_BITS 5 -#define MEMCTL_DCWU_MASK 0x00001F00 /* Bits 8-12 dcache ways in use */ -#define MEMCTL_DCWA_MASK 0x0003E000 /* Bits 13-17 dcache ways allocatable */ -#define MEMCTL_ICWU_MASK 0x007C0000 /* Bits 18-22 icache ways in use */ -#define MEMCTL_DCWU_CLR_MASK ~(MEMCTL_DCWU_MASK) -#define MEMCTL_DCWA_CLR_MASK ~(MEMCTL_DCWA_MASK) -#define MEMCTL_ICWU_CLR_MASK ~(MEMCTL_ICWU_MASK) -#define MEMCTL_DCW_CLR_MASK (MEMCTL_DCWU_CLR_MASK | MEMCTL_DCWA_CLR_MASK) -#define MEMCTL_IDCW_CLR_MASK (MEMCTL_DCW_CLR_MASK | MEMCTL_ICWU_CLR_MASK) - - -#endif /*XTENSA_COREBITS_H*/ - diff --git a/src/arch/xtensa/include/xtensa/hal.h b/src/arch/xtensa/include/xtensa/hal.h deleted file mode 100644 index 9db5df3bcda8..000000000000 --- a/src/arch/xtensa/include/xtensa/hal.h +++ /dev/null @@ -1,1518 +0,0 @@ -/* - xtensa/hal.h -- contains a definition of the Core HAL interface - - All definitions in this header file are independent of any specific - Xtensa processor configuration. Thus software (eg. OS, application, - etc) can include this header file and be compiled into configuration- - independent objects that can be distributed and eventually linked - to the HAL library (libhal.a) to create a configuration-specific - final executable. - - Certain definitions, however, are release/version-specific -- such as - the XTHAL_RELEASE_xxx macros (or additions made in later versions). - - - $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/target-os-src/hal.h.tpp#1 $ - - Copyright (c) 1999-2015 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. -*/ - -#ifndef XTENSA_HAL_H -#define XTENSA_HAL_H - - -/**************************************************************************** - Definitions Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - - -/*---------------------------------------------------------------------- - Constant Definitions (shared with assembly) - ----------------------------------------------------------------------*/ - -/* - * Software (Xtensa Tools) version information. Not configuration-specific! - * - * NOTE: "release" is a misnomer here, these are really product "version" - * numbers. A "release" is a collection of product versions - * made available at once (together) to customers. - * In the past, release and version names all matched in T####.# form, - * making the distinction irrelevant. This is no longer the case. - */ -#define XTHAL_RELEASE_MAJOR 12000 -#define XTHAL_RELEASE_MINOR 8 -#define XTHAL_RELEASE_NAME "12.0.8" -#define XTHAL_REL_12 1 -#define XTHAL_REL_12_0 1 -#define XTHAL_REL_12_0_8 1 - -/* HAL version numbers (these names are for backward compatibility): */ -#define XTHAL_MAJOR_REV XTHAL_RELEASE_MAJOR -#define XTHAL_MINOR_REV XTHAL_RELEASE_MINOR -/* - * A bit of software release/version history on values of XTHAL_{MAJOR,MINOR}_REV: - * - * SW Version MAJOR MINOR Comment - * ======= ===== ===== ======= - * T1015.n n/a n/a (HAL not yet available) - * T1020.{0,1,2} 0 1 (HAL beta) - * T1020.{3,4} 0 2 First release. - * T1020.n (n>4) 0 2 or >3 (TBD) - * T1030.0 0 1 (HAL beta) - * T1030.{1,2} 0 3 Equivalent to first release. - * T1030.n (n>=3) 0 >= 3 (TBD) - * T1040.n 1040 n Full CHAL available from T1040.2 - * T1050.n 1050 n . - * 6.0.n 6000 n Xtensa Tools v6 (RA-200x.n) - * 7.0.n 7000 n Xtensa Tools v7 (RB-200x.n) - * 7.1.n 7010 n Xtensa Tools v7.1 (RB-200x.(n+2)) - * 8.0.n 8000 n Xtensa Tools v8 (RC-20xx.n) - * 9.0.n 9000 n Xtensa Tools v9 (RD-201x.n) - * 10.0.n 10000 n Xtensa Tools v10 (RE-201x.n) - * - * - * Note: there is a distinction between the software version with - * which something is compiled (accessible using XTHAL_RELEASE_* macros) - * and the software version with which the HAL library was compiled - * (accessible using Xthal_release_* global variables). This - * distinction is particularly relevant for vendors that distribute - * configuration-independent binaries (eg. an OS), where their customer - * might link it with a HAL of a different Xtensa software version. - * In this case, it may be appropriate for the OS to verify at run-time - * whether XTHAL_RELEASE_* and Xthal_release_* are compatible. - * [Guidelines as to which version is compatible with which are not - * currently provided explicitly, but might be inferred from reading - * OSKit documentation for all releases -- compatibility is also highly - * dependent on which HAL features are used. Each version is usually - * backward compatible, with very few exceptions if any.] - */ - -/* Version comparison operators (among major/minor pairs): */ -#define XTHAL_REL_GE(maja,mina, majb,minb) ((maja) > (majb) || \ - ((maja) == (majb) && (mina) >= (minb))) -#define XTHAL_REL_GT(maja,mina, majb,minb) ((maja) > (majb) || \ - ((maja) == (majb) && (mina) > (minb))) -#define XTHAL_REL_LE(maja,mina, majb,minb) ((maja) < (majb) || \ - ((maja) == (majb) && (mina) <= (minb))) -#define XTHAL_REL_LT(maja,mina, majb,minb) ((maja) < (majb) || \ - ((maja) == (majb) && (mina) < (minb))) -#define XTHAL_REL_EQ(maja,mina, majb,minb) ((maja) == (majb) && (mina) == (minb)) - -/* Fuzzy (3-way) logic operators: */ -#define XTHAL_MAYBE -1 /* 0=NO, 1=YES, -1=MAYBE */ -#define XTHAL_FUZZY_AND(a,b) (((a)==0 || (b)==0) ? 0 : ((a)==1 && (b)==1) ? 1 : XTHAL_MAYBE) -#define XTHAL_FUZZY_OR(a,b) (((a)==1 || (b)==1) ? 1 : ((a)==0 && (b)==0) ? 0 : XTHAL_MAYBE) -#define XTHAL_FUZZY_NOT(a) (((a)==0 || (a)==1) ? (1-(a)) : XTHAL_MAYBE) - - -/* - * Architectural limit, independent of configuration: - */ -#define XTHAL_MAX_CPS 8 /* max number of coprocessors (0..7) */ - -/* Misc: */ -#define XTHAL_LITTLEENDIAN 0 -#define XTHAL_BIGENDIAN 1 - - - -#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) -#ifdef __cplusplus -extern "C" { -#endif - -/*---------------------------------------------------------------------- - HAL - ----------------------------------------------------------------------*/ - -/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */ -extern const unsigned int Xthal_rev_no; - - -/*---------------------------------------------------------------------- - Optional/Custom Processor State - ----------------------------------------------------------------------*/ - -/* save & restore the extra processor state */ -extern void xthal_save_extra(void *base); -extern void xthal_restore_extra(void *base); - -extern void xthal_save_cpregs(void *base, int); -extern void xthal_restore_cpregs(void *base, int); -/* versions specific to each coprocessor id */ -extern void xthal_save_cp0(void *base); -extern void xthal_save_cp1(void *base); -extern void xthal_save_cp2(void *base); -extern void xthal_save_cp3(void *base); -extern void xthal_save_cp4(void *base); -extern void xthal_save_cp5(void *base); -extern void xthal_save_cp6(void *base); -extern void xthal_save_cp7(void *base); -extern void xthal_restore_cp0(void *base); -extern void xthal_restore_cp1(void *base); -extern void xthal_restore_cp2(void *base); -extern void xthal_restore_cp3(void *base); -extern void xthal_restore_cp4(void *base); -extern void xthal_restore_cp5(void *base); -extern void xthal_restore_cp6(void *base); -extern void xthal_restore_cp7(void *base); -/* pointers to each of the functions above */ -extern void* Xthal_cpregs_save_fn[XTHAL_MAX_CPS]; -extern void* Xthal_cpregs_restore_fn[XTHAL_MAX_CPS]; -/* similarly for non-windowed ABI (may be same or different) */ -extern void* Xthal_cpregs_save_nw_fn[XTHAL_MAX_CPS]; -extern void* Xthal_cpregs_restore_nw_fn[XTHAL_MAX_CPS]; - -/*extern void xthal_save_all_extra(void *base);*/ -/*extern void xthal_restore_all_extra(void *base);*/ - -/* space for processor state */ -extern const unsigned int Xthal_extra_size; -extern const unsigned int Xthal_extra_align; -extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS]; -extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS]; -extern const unsigned int Xthal_all_extra_size; -extern const unsigned int Xthal_all_extra_align; -/* coprocessor names */ -extern const char * const Xthal_cp_names[XTHAL_MAX_CPS]; - -/* initialize the extra processor */ -/*extern void xthal_init_extra(void);*/ -/* initialize the TIE coprocessor */ -/*extern void xthal_init_cp(int);*/ - -/* initialize the extra processor */ -extern void xthal_init_mem_extra(void *); -/* initialize the TIE coprocessor */ -extern void xthal_init_mem_cp(void *, int); - -/* the number of TIE coprocessors contiguous from zero (for Tor2) */ -extern const unsigned int Xthal_num_coprocessors; - -/* actual number of coprocessors */ -extern const unsigned char Xthal_cp_num; -/* index of highest numbered coprocessor, plus one */ -extern const unsigned char Xthal_cp_max; -/* index of highest allowed coprocessor number, per cfg, plus one */ -/*extern const unsigned char Xthal_cp_maxcfg;*/ -/* bitmask of which coprocessors are present */ -extern const unsigned int Xthal_cp_mask; - -/* read & write extra state register */ -/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/ -/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/ - -/* read & write a TIE coprocessor register */ -/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/ -/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/ - -/* return coprocessor number based on register */ -/*extern int xthal_which_cp(unsigned reg);*/ - - -/*---------------------------------------------------------------------- - Register Windows - ----------------------------------------------------------------------*/ - -/* number of registers in register window */ -extern const unsigned int Xthal_num_aregs; -extern const unsigned char Xthal_num_aregs_log2; - - -/*---------------------------------------------------------------------- - Cache - ----------------------------------------------------------------------*/ - -/* size of the cache lines in log2(bytes) */ -extern const unsigned char Xthal_icache_linewidth; -extern const unsigned char Xthal_dcache_linewidth; -/* size of the cache lines in bytes (2^linewidth) */ -extern const unsigned short Xthal_icache_linesize; -extern const unsigned short Xthal_dcache_linesize; - -/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */ -extern const unsigned int Xthal_icache_size; -extern const unsigned int Xthal_dcache_size; -/* cache features */ -extern const unsigned char Xthal_dcache_is_writeback; - -/* cache region operations*/ -extern void xthal_icache_region_invalidate( void *addr, unsigned size ); -extern void xthal_dcache_region_invalidate( void *addr, unsigned size ); -extern void xthal_dcache_region_writeback( void *addr, unsigned size ); -extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size ); - -#ifndef XTHAL_USE_CACHE_MACROS -/* cache line operations*/ -extern void xthal_icache_line_invalidate(void *addr); -extern void xthal_dcache_line_invalidate(void *addr); -extern void xthal_dcache_line_writeback(void *addr); -extern void xthal_dcache_line_writeback_inv(void *addr); -/* sync icache and memory */ -extern void xthal_icache_sync( void ); -/* sync dcache and memory */ -extern void xthal_dcache_sync( void ); -#endif - -/* get/set number of icache ways enabled */ -extern unsigned int xthal_icache_get_ways(void); -extern void xthal_icache_set_ways(unsigned int ways); -/* get/set number of dcache ways enabled */ -extern unsigned int xthal_dcache_get_ways(void); -extern void xthal_dcache_set_ways(unsigned int ways); - -/* coherency (low-level -- not normally called directly) */ -extern void xthal_cache_coherence_on( void ); -extern void xthal_cache_coherence_off( void ); -/* coherency (high-level) */ -extern void xthal_cache_coherence_optin( void ); -extern void xthal_cache_coherence_optout( void ); - -/* - * Cache prefetch control. - * The parameter to xthal_set_cache_prefetch() contains both - * a PREFCTL register value and a mask of which bits to actually modify. - * This allows easily combining field macros (below) by ORing, - * leaving unspecified fields unmodified. - * - * For backward compatibility with the older version of this routine - * (that took 15-bit value and mask in a 32-bit parameter, for pre-RF - * cores with only the lower 15 bits of PREFCTL defined), the 32-bit - * value and mask are staggered as follows in a 64-bit parameter: - * param[63:48] are PREFCTL[31:16] if param[31] is set - * param[47:32] are mask[31:16] if param[31] is set - * param[31] is set if mask is used, 0 if not - * param[31:16] are mask[15:0] if param[31] is set - * param[31:16] are PREFCTL[31:16] if param[31] is clear - * param[15:0] are PREFCTL[15:0] - * - * Limitation: PREFCTL register bit 31 cannot be set without masking, - * and bit 15 must always be set when using masking, so it is hoped that - * these two bits will remain reserved, read-as-zero in PREFCTL. - */ -#define XTHAL_PREFETCH_ENABLE -1 /* enable inst+data prefetch */ -#define XTHAL_PREFETCH_DISABLE 0xFFFF0000 /* disab inst+data prefetch*/ -#define XTHAL_DCACHE_PREFETCH(n) (0x800F0000+((n)&0xF)) /* data-side */ -#define XTHAL_DCACHE_PREFETCH_OFF XTHAL_DCACHE_PREFETCH(0) /* disable */ -#define XTHAL_DCACHE_PREFETCH_LOW XTHAL_DCACHE_PREFETCH(4) /* less aggr.*/ -#define XTHAL_DCACHE_PREFETCH_MEDIUM XTHAL_DCACHE_PREFETCH(5) /* mid aggr. */ -#define XTHAL_DCACHE_PREFETCH_HIGH XTHAL_DCACHE_PREFETCH(8) /* more aggr.*/ -#define XTHAL_DCACHE_PREFETCH_L1_OFF 0x90000000 /* to prefetch buffers*/ -#define XTHAL_DCACHE_PREFETCH_L1 0x90001000 /* direct to L1 dcache*/ -#define XTHAL_ICACHE_PREFETCH(n) (0x80F00000+(((n)&0xF)<<4)) /* i-side */ -#define XTHAL_ICACHE_PREFETCH_OFF XTHAL_ICACHE_PREFETCH(0) /* disable */ -#define XTHAL_ICACHE_PREFETCH_LOW XTHAL_ICACHE_PREFETCH(4) /* less aggr.*/ -#define XTHAL_ICACHE_PREFETCH_MEDIUM XTHAL_ICACHE_PREFETCH(5) /* mid aggr. */ -#define XTHAL_ICACHE_PREFETCH_HIGH XTHAL_ICACHE_PREFETCH(8) /* more aggr.*/ -#define XTHAL_ICACHE_PREFETCH_L1_OFF 0xA0000000 /* (not implemented) */ -#define XTHAL_ICACHE_PREFETCH_L1 0xA0002000 /* (not implemented) */ -#define _XTHAL_PREFETCH_BLOCKS(n) ((n)<0?0:(n)<5?(n):(n)<15?((n)>>1)+2:9) -#define XTHAL_PREFETCH_BLOCKS(n) (0x0000000F80000000ULL + \ - (((unsigned long long)_XTHAL_PREFETCH_BLOCKS(n))<<48)) - -extern int xthal_get_cache_prefetch( void ); -extern int xthal_set_cache_prefetch( int ); -extern int xthal_set_cache_prefetch_long( unsigned long long ); -/* Only use the new extended function from now on: */ -#define xthal_set_cache_prefetch xthal_set_cache_prefetch_long -#define xthal_set_cache_prefetch_nw xthal_set_cache_prefetch_long_nw - - -/*---------------------------------------------------------------------- - Debug - ----------------------------------------------------------------------*/ - -/* 1 if debug option configured, 0 if not: */ -extern const int Xthal_debug_configured; - -/* Set (plant) and remove software breakpoint, both synchronizing cache: */ -extern unsigned int xthal_set_soft_break(void *addr); -extern void xthal_remove_soft_break(void *addr, unsigned int); - - -/*---------------------------------------------------------------------- - Disassembler - ----------------------------------------------------------------------*/ - -/* Max expected size of the return buffer for a disassembled instruction (hint only): */ -#define XTHAL_DISASM_BUFSIZE 80 - -/* Disassembly option bits for selecting what to return: */ -#define XTHAL_DISASM_OPT_ADDR 0x0001 /* display address */ -#define XTHAL_DISASM_OPT_OPHEX 0x0002 /* display opcode bytes in hex */ -#define XTHAL_DISASM_OPT_OPCODE 0x0004 /* display opcode name (mnemonic) */ -#define XTHAL_DISASM_OPT_PARMS 0x0008 /* display parameters */ -#define XTHAL_DISASM_OPT_ALL 0x0FFF /* display everything */ - -/* routine to get a string for the disassembled instruction */ -extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr, - char *buffer, unsigned buflen, unsigned options ); - -/* routine to get the size of the next instruction. Returns 0 for - illegal instruction */ -extern int xthal_disassemble_size( unsigned char *instr_buf ); - - -/*---------------------------------------------------------------------- - Instruction/Data RAM/ROM Access - ----------------------------------------------------------------------*/ - -extern void* xthal_memcpy(void *dst, const void *src, unsigned len); -extern void* xthal_bcopy(const void *src, void *dst, unsigned len); - - -/*---------------------------------------------------------------------- - MP Synchronization - ----------------------------------------------------------------------*/ - -extern int xthal_compare_and_set( int *addr, int test_val, int compare_val ); - -/*extern const char Xthal_have_s32c1i;*/ - - -/*---------------------------------------------------------------------- - Miscellaneous - ----------------------------------------------------------------------*/ - -extern const unsigned int Xthal_release_major; -extern const unsigned int Xthal_release_minor; -extern const char * const Xthal_release_name; -extern const char * const Xthal_release_internal; - -extern const unsigned char Xthal_memory_order; -extern const unsigned char Xthal_have_windowed; -extern const unsigned char Xthal_have_density; -extern const unsigned char Xthal_have_booleans; -extern const unsigned char Xthal_have_loops; -extern const unsigned char Xthal_have_nsa; -extern const unsigned char Xthal_have_minmax; -extern const unsigned char Xthal_have_sext; -extern const unsigned char Xthal_have_clamps; -extern const unsigned char Xthal_have_mac16; -extern const unsigned char Xthal_have_mul16; -extern const unsigned char Xthal_have_fp; -extern const unsigned char Xthal_have_speculation; -extern const unsigned char Xthal_have_threadptr; - -extern const unsigned char Xthal_have_pif; -extern const unsigned short Xthal_num_writebuffer_entries; - -extern const unsigned int Xthal_build_unique_id; -/* Version info for hardware targeted by software upgrades: */ -extern const unsigned int Xthal_hw_configid0; -extern const unsigned int Xthal_hw_configid1; -extern const unsigned int Xthal_hw_release_major; -extern const unsigned int Xthal_hw_release_minor; -extern const char * const Xthal_hw_release_name; -extern const char * const Xthal_hw_release_internal; - -/* Clear any remnant code-dependent state (i.e. clear loop count regs). */ -extern void xthal_clear_regcached_code( void ); - -#ifdef __cplusplus -} -#endif -#endif /*!_ASMLANGUAGE && !_NOCLANGUAGE && !__ASSEMBLER__ */ - - - - - -/**************************************************************************** - Definitions Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - Constant Definitions (shared with assembly) - ----------------------------------------------------------------------*/ - -/* - * Architectural limits, independent of configuration. - * Note that these are ISA-defined limits, not micro-architecture implementation - * limits enforced by the Xtensa Processor Generator (which may be stricter than - * these below). - */ -#define XTHAL_MAX_INTERRUPTS 32 /* max number of interrupts (0..31) */ -#define XTHAL_MAX_INTLEVELS 16 /* max number of interrupt levels (0..15) */ - /* (as of T1040, implementation limit is 7: 0..6) */ -#define XTHAL_MAX_TIMERS 4 /* max number of timers (CCOMPARE0..CCOMPARE3) */ - /* (as of T1040, implementation limit is 3: 0..2) */ - -/* Interrupt types: */ -#define XTHAL_INTTYPE_UNCONFIGURED 0 -#define XTHAL_INTTYPE_SOFTWARE 1 -#define XTHAL_INTTYPE_EXTERN_EDGE 2 -#define XTHAL_INTTYPE_EXTERN_LEVEL 3 -#define XTHAL_INTTYPE_TIMER 4 -#define XTHAL_INTTYPE_NMI 5 -#define XTHAL_INTTYPE_WRITE_ERROR 6 -#define XTHAL_INTTYPE_PROFILING 7 -#define XTHAL_INTTYPE_IDMA_DONE 8 -#define XTHAL_INTTYPE_IDMA_ERR 9 -#define XTHAL_INTTYPE_GS_ERR 10 -#define XTHAL_INTTYPE_SG_ERR 10 /* backward compatibility name - deprecated */ -#define XTHAL_MAX_INTTYPES 11 /* number of interrupt types */ - -/* Timer related: */ -#define XTHAL_TIMER_UNCONFIGURED -1 /* Xthal_timer_interrupt[] value for non-existent timers */ -#define XTHAL_TIMER_UNASSIGNED XTHAL_TIMER_UNCONFIGURED /* (for backwards compatibility only) */ - -/* Local Memory ECC/Parity: */ -#define XTHAL_MEMEP_PARITY 1 -#define XTHAL_MEMEP_ECC 2 -/* Flags parameter to xthal_memep_inject_error(): */ -#define XTHAL_MEMEP_F_LOCAL 0 /* local memory (default) */ -#define XTHAL_MEMEP_F_DCACHE_DATA 4 /* data cache data */ -#define XTHAL_MEMEP_F_DCACHE_TAG 5 /* data cache tag */ -#define XTHAL_MEMEP_F_ICACHE_DATA 6 /* instruction cache data */ -#define XTHAL_MEMEP_F_ICACHE_TAG 7 /* instruction cache tag */ -#define XTHAL_MEMEP_F_CORRECTABLE 16 /* inject correctable error - (default is non-corr.) */ - - -/* Access Mode bits (tentative): */ /* bit abbr unit short_name PPC equ - Description */ -#define XTHAL_AMB_EXCEPTION 0 /* 001 E EX fls: EXception none - exception on any access (aka "illegal") */ -#define XTHAL_AMB_HITCACHE 1 /* 002 C CH fls: use Cache on Hit ~(I CI) - [or H HC] way from tag match; - [or U UC] (ISA: same except Isolate case) */ -#define XTHAL_AMB_ALLOCATE 2 /* 004 A AL fl?: ALlocate none - [or F FI fill] refill cache on miss, way from LRU - (ISA: Read/Write Miss Refill) */ -#define XTHAL_AMB_WRITETHRU 3 /* 008 W WT --s: WriteThrough W WT - store immediately to memory (ISA: same) */ -#define XTHAL_AMB_ISOLATE 4 /* 010 I IS fls: ISolate none - use cache regardless of hit-vs-miss, - way from vaddr (ISA: use-cache-on-miss+hit) */ -#define XTHAL_AMB_GUARD 5 /* 020 G GU ?l?: GUard G * - non-speculative; spec/replay refs not permitted */ -#define XTHAL_AMB_COHERENT 6 /* 040 M MC ?ls: Mem/MP Coherent M - on read, other CPU/bus-master may need to supply data; - on write, maybe redirect to or flush other CPU dirty line; etc */ -#if 0 -#define XTHAL_AMB_BUFFERABLE x /* 000 B BU --s: BUfferable ? - write response may return earlier than from final destination */ -#define XTHAL_AMB_ORDERED x /* 000 O OR fls: ORdered G * - mem accesses cannot be out of order */ -#define XTHAL_AMB_FUSEWRITES x /* 000 F FW --s: FuseWrites none - allow combining/merging/coalescing multiple writes - (to same datapath data unit) into one - (implied by writeback) */ -#define XTHAL_AMB_TRUSTED x /* 000 T TR ?l?: TRusted none - memory will not bus error (if it does, - handle as fatal imprecise interrupt) */ -#define XTHAL_AMB_PREFETCH x /* 000 P PR fl?: PRefetch none - on refill, read line+1 into prefetch buffers */ -#define XTHAL_AMB_STREAM x /* 000 S ST ???: STreaming none - access one of N stream buffers */ -#endif /*0*/ - -#define XTHAL_AM_EXCEPTION (1<<XTHAL_AMB_EXCEPTION) -#define XTHAL_AM_HITCACHE (1<<XTHAL_AMB_HITCACHE) -#define XTHAL_AM_ALLOCATE (1<<XTHAL_AMB_ALLOCATE) -#define XTHAL_AM_WRITETHRU (1<<XTHAL_AMB_WRITETHRU) -#define XTHAL_AM_ISOLATE (1<<XTHAL_AMB_ISOLATE) -#define XTHAL_AM_GUARD (1<<XTHAL_AMB_GUARD) -#define XTHAL_AM_COHERENT (1<<XTHAL_AMB_COHERENT) -#if 0 -#define XTHAL_AM_BUFFERABLE (1<<XTHAL_AMB_BUFFERABLE) -#define XTHAL_AM_ORDERED (1<<XTHAL_AMB_ORDERED) -#define XTHAL_AM_FUSEWRITES (1<<XTHAL_AMB_FUSEWRITES) -#define XTHAL_AM_TRUSTED (1<<XTHAL_AMB_TRUSTED) -#define XTHAL_AM_PREFETCH (1<<XTHAL_AMB_PREFETCH) -#define XTHAL_AM_STREAM (1<<XTHAL_AMB_STREAM) -#endif /*0*/ - -/* - * Allowed Access Modes (bit combinations). - * - * Columns are: - * "FOGIWACE" - * Access mode bits (see XTHAL_AMB_xxx above). - * <letter> = bit is set - * '-' = bit is clear - * '.' = bit is irrelevant / don't care, as follows: - * E=1 makes all others irrelevant - * W,F relevant only for stores - * "2345" - * Indicates which Xtensa releases support the corresponding - * access mode. Releases for each character column are: - * 2 = prior to T1020.2: T1015 (V1.5), T1020.0, T1020.1 - * 3 = T1020.2 and later: T1020.2+, T1030 - * 4 = T1040 - * 5 = T1050 (maybe), LX1, LX2, LX2.1 - * 7 = LX2.2 - * 8 = LX3, LX4 - * 9 = LX5 - * And the character column contents are: - * <number> = supported by release(s) - * "." = unsupported by release(s) - * "?" = support unknown - */ - /* foMGIWACE 2345789 */ -/* For instruction fetch: */ -#define XTHAL_FAM_EXCEPTION 0x001 /* ........E 2345789 exception */ -/*efine XTHAL_FAM_ISOLATE*/ /*0x012*/ /* .---I.-C- ....... isolate */ -#define XTHAL_FAM_BYPASS 0x000 /* .----.--- 2345789 bypass */ -/*efine XTHAL_FAM_NACACHED*/ /*0x002*/ /* .----.-C- ....... cached no-allocate (frozen) */ -#define XTHAL_FAM_CACHED 0x006 /* .----.AC- 2345789 cached */ -/* For data load: */ -#define XTHAL_LAM_EXCEPTION 0x001 /* ........E 2345789 exception */ -#define XTHAL_LAM_ISOLATE 0x012 /* .---I.-C- 2345789 isolate */ -#define XTHAL_LAM_BYPASS 0x000 /* .O---.--- 2...... bypass speculative */ -#define XTHAL_LAM_BYPASSG 0x020 /* .O-G-.--- .345789 bypass guarded */ -#define XTHAL_LAM_CACHED_NOALLOC 0x002 /* .O---.-C- 2345789 cached no-allocate speculative */ -#define XTHAL_LAM_NACACHED XTHAL_LAM_CACHED_NOALLOC -#define XTHAL_LAM_NACACHEDG 0x022 /* .O-G-.-C- .?..... cached no-allocate guarded */ -#define XTHAL_LAM_CACHED 0x006 /* .----.AC- 2345789 cached speculative */ -#define XTHAL_LAM_COHCACHED 0x046 /* .-M--.AC- ....*89 cached speculative MP-coherent */ -/* For data store: */ -#define XTHAL_SAM_EXCEPTION 0x001 /* ........E 2345789 exception */ -#define XTHAL_SAM_ISOLATE 0x032 /* .--GI--C- 2345789 isolate */ -#define XTHAL_SAM_BYPASS 0x028 /* -O-G-W--- 2345789 bypass */ -#define XTHAL_SAM_WRITETHRU 0x02A /* -O-G-W-C- 2345789 writethrough */ -/*efine XTHAL_SAM_WRITETHRU_ALLOC*/ /*0x02E*/ /* -O-G-WAC- ....... writethrough allocate */ -#define XTHAL_SAM_WRITEBACK 0x026 /* F--G--AC- ...5789 writeback */ -#define XTHAL_SAM_WRITEBACK_NOALLOC 0x022 /* ?--G---C- .....89 writeback no-allocate */ -#define XTHAL_SAM_COHWRITEBACK 0x066 /* F-MG--AC- ....*89 writeback MP-coherent */ -/* For PIF attributes: */ /* -PIwrWCBUUUU ...9 */ -#define XTHAL_PAM_BYPASS 0x000 /* xxx00000xxxx ...9 bypass non-bufferable */ -#define XTHAL_PAM_BYPASS_BUF 0x010 /* xxx0000bxxxx ...9 bypass */ -#define XTHAL_PAM_CACHED_NOALLOC 0x030 /* xxx0001bxxxx ...9 cached no-allocate */ -#define XTHAL_PAM_WRITETHRU 0x0B0 /* xxx0101bxxxx ...9 writethrough (WT) */ -#define XTHAL_PAM_WRITEBACK_NOALLOC 0x0F0 /* xxx0111bxxxx ...9 writeback no-alloc (WBNA) */ -#define XTHAL_PAM_WRITEBACK 0x1F0 /* xxx1111bxxxx ...9 writeback (WB) */ -/*efine XTHAL_PAM_NORMAL*/ /*0x050*/ /* xxx0010bxxxx .... (unimplemented) */ -/*efine XTHAL_PAM_WRITETHRU_WA*/ /*0x130*/ /* xxx1001bxxxx .... (unimplemented, less likely) */ -/*efine XTHAL_PAM_WRITETHRU_RWA*/ /*0x1B0*/ /* xxx1101bxxxx .... (unimplemented, less likely) */ -/*efine XTHAL_PAM_WRITEBACK_WA*/ /*0x170*/ /* xxx1011bxxxx .... (unimplemented, less likely) */ - - -#if 0 -/* - Cache attribute encoding for CACHEATTR (per ISA): - (Note: if this differs from ISA Ref Manual, ISA has precedence) - - Inst-fetches Loads Stores - ------------- ------------ ------------- -0x0 FCA_EXCEPTION LCA_NACACHED SCA_WRITETHRU cached no-allocate (previously misnamed "uncached") -0x1 FCA_CACHED LCA_CACHED SCA_WRITETHRU cached -0x2 FCA_BYPASS LCA_BYPASS_G* SCA_BYPASS bypass cache (what most people call uncached) -0x3 FCA_CACHED LCA_CACHED SCA_WRITEALLOCF write-allocate - or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented) -0x4 FCA_CACHED LCA_CACHED SCA_WRITEBACK[M] write-back [MP-coherent] - or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented) -0x5 FCA_CACHED LCA_CACHED SCA_WRITEBACK_NOALLOC write-back no-allocate - or FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (if unimplemented) -0x6..D FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (reserved) -0xE FCA_EXCEPTION LCA_ISOLATE SCA_ISOLATE isolate -0xF FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION illegal - * Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G) -*/ -#endif /*0*/ - - -#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) -#ifdef __cplusplus -extern "C" { -#endif - - -/*---------------------------------------------------------------------- - Register Windows - ----------------------------------------------------------------------*/ - -/* This spill any live register windows (other than the caller's): - * (NOTE: current implementation require privileged code, but - * a user-callable implementation is possible.) */ -extern void xthal_window_spill( void ); - - -/*---------------------------------------------------------------------- - Optional/Custom Processor State - ----------------------------------------------------------------------*/ - -/* validate & invalidate the TIE register file */ -extern void xthal_validate_cp(int); -extern void xthal_invalidate_cp(int); - -/* read and write cpenable register */ -extern void xthal_set_cpenable(unsigned); -extern unsigned xthal_get_cpenable(void); - - -/*---------------------------------------------------------------------- - Interrupts - ----------------------------------------------------------------------*/ - -/* the number of interrupt levels */ -extern const unsigned char Xthal_num_intlevels; -/* the number of interrupts */ -extern const unsigned char Xthal_num_interrupts; -/* the highest level of interrupts masked by PS.EXCM */ -extern const unsigned char Xthal_excm_level; - -/* mask for level of interrupts */ -extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS]; -/* mask for level 0 to N interrupts */ -extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS]; - -/* level of each interrupt */ -extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS]; - -/* type per interrupt */ -extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS]; - -/* masks of each type of interrupt */ -extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES]; - -/* interrupt numbers assigned to each timer interrupt */ -extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS]; - -/* INTENABLE,INTERRUPT,INTSET,INTCLEAR register access functions: */ -extern unsigned xthal_get_intenable( void ); -extern void xthal_set_intenable( unsigned ); -extern unsigned xthal_get_interrupt( void ); -#define xthal_get_intread xthal_get_interrupt /* backward compatibility */ - -/* These two functions are deprecated. Use the newer functions - xthal_interrupt_trigger and xthal_interrupt_clear instead. */ -extern void xthal_set_intset( unsigned ); -extern void xthal_set_intclear( unsigned ); - - -/*---------------------------------------------------------------------- - Debug - ----------------------------------------------------------------------*/ - -/* Number of instruction and data break registers: */ -extern const int Xthal_num_ibreak; -extern const int Xthal_num_dbreak; - - -/*---------------------------------------------------------------------- - Core Counter - ----------------------------------------------------------------------*/ - -/* counter info */ -extern const unsigned char Xthal_have_ccount; /* set if CCOUNT register present */ -extern const unsigned char Xthal_num_ccompare; /* number of CCOMPAREn registers */ - -/* get CCOUNT register (if not present return 0) */ -extern unsigned xthal_get_ccount(void); - -/* set and get CCOMPAREn registers (if not present, get returns 0) */ -extern void xthal_set_ccompare(int, unsigned); -extern unsigned xthal_get_ccompare(int); - - -/*---------------------------------------------------------------------- - Miscellaneous - ----------------------------------------------------------------------*/ - -extern const unsigned char Xthal_have_prid; -extern const unsigned char Xthal_have_exceptions; -extern const unsigned char Xthal_xea_version; -extern const unsigned char Xthal_have_interrupts; -extern const unsigned char Xthal_have_highlevel_interrupts; -extern const unsigned char Xthal_have_nmi; - -extern unsigned xthal_get_prid( void ); - - -/*---------------------------------------------------------------------- - Virtual interrupt prioritization (DEPRECATED) - ----------------------------------------------------------------------*/ - -/* Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities: */ -extern unsigned xthal_vpri_to_intlevel(unsigned vpri); -extern unsigned xthal_intlevel_to_vpri(unsigned intlevel); - -/* Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints: */ -/* These functions are deprecated. Use xthal_interrupt_enable and xthal_interrupt_disable instead. */ -extern unsigned xthal_int_enable(unsigned); -extern unsigned xthal_int_disable(unsigned); - -/* Set/get virtual priority of an interrupt: */ -extern int xthal_set_int_vpri(int intnum, int vpri); -extern int xthal_get_int_vpri(int intnum); - -/* Set/get interrupt lockout level for exclusive access to virtual priority data structures: */ -extern void xthal_set_vpri_locklevel(unsigned intlevel); -extern unsigned xthal_get_vpri_locklevel(void); - -/* Set/get current virtual interrupt priority: */ -extern unsigned xthal_set_vpri(unsigned vpri); -extern unsigned xthal_get_vpri(void); -extern unsigned xthal_set_vpri_intlevel(unsigned intlevel); -extern unsigned xthal_set_vpri_lock(void); - - -/*---------------------------------------------------------------------- - Generic Interrupt Trampolining Support (DEPRECATED) - ----------------------------------------------------------------------*/ - -typedef void (XtHalVoidFunc)(void); - -/* Bitmask of interrupts currently trampolining down: */ -extern unsigned Xthal_tram_pending; - -/* - * Bitmask of which interrupts currently trampolining down synchronously are - * actually enabled; this bitmask is necessary because INTENABLE cannot hold - * that state (sync-trampolining interrupts must be kept disabled while - * trampolining); in the current implementation, any bit set here is not set - * in INTENABLE, and vice-versa; once a sync-trampoline is handled (at level - * one), its enable bit must be moved from here to INTENABLE: - */ -extern unsigned Xthal_tram_enabled; - -/* Bitmask of interrupts configured for sync trampolining: */ -extern unsigned Xthal_tram_sync; - -/* Trampoline support functions: */ -extern unsigned xthal_tram_pending_to_service( void ); -extern void xthal_tram_done( unsigned serviced_mask ); -extern int xthal_tram_set_sync( int intnum, int sync ); -extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn ); - - -/*---------------------------------------------------------------------- - Internal Memories - ----------------------------------------------------------------------*/ - -extern const unsigned char Xthal_num_instrom; -extern const unsigned char Xthal_num_instram; -extern const unsigned char Xthal_num_datarom; -extern const unsigned char Xthal_num_dataram; -extern const unsigned char Xthal_num_xlmi; - -/* Each of the following arrays contains at least one entry, - * or as many entries as needed if more than one: */ -extern const unsigned int Xthal_instrom_vaddr[]; -extern const unsigned int Xthal_instrom_paddr[]; -extern const unsigned int Xthal_instrom_size []; -extern const unsigned int Xthal_instram_vaddr[]; -extern const unsigned int Xthal_instram_paddr[]; -extern const unsigned int Xthal_instram_size []; -extern const unsigned int Xthal_datarom_vaddr[]; -extern const unsigned int Xthal_datarom_paddr[]; -extern const unsigned int Xthal_datarom_size []; -extern const unsigned int Xthal_dataram_vaddr[]; -extern const unsigned int Xthal_dataram_paddr[]; -extern const unsigned int Xthal_dataram_size []; -extern const unsigned int Xthal_xlmi_vaddr[]; -extern const unsigned int Xthal_xlmi_paddr[]; -extern const unsigned int Xthal_xlmi_size []; - - -/*---------------------------------------------------------------------- - Cache - ----------------------------------------------------------------------*/ - -/* number of cache sets in log2(lines per way) */ -extern const unsigned char Xthal_icache_setwidth; -extern const unsigned char Xthal_dcache_setwidth; -/* cache set associativity (number of ways) */ -extern const unsigned int Xthal_icache_ways; -extern const unsigned int Xthal_dcache_ways; -/* cache features */ -extern const unsigned char Xthal_icache_line_lockable; -extern const unsigned char Xthal_dcache_line_lockable; - -/* cache attribute register control (used by other HAL routines) */ -extern unsigned xthal_get_cacheattr( void ); -extern unsigned xthal_get_icacheattr( void ); -extern unsigned xthal_get_dcacheattr( void ); -extern void xthal_set_cacheattr( unsigned ); -extern void xthal_set_icacheattr( unsigned ); -extern void xthal_set_dcacheattr( unsigned ); -/* set cache attribute (access modes) for a range of memory */ -extern int xthal_set_region_attribute( void *addr, unsigned size, - unsigned cattr, unsigned flags ); -/* Bits of flags parameter to xthal_set_region_attribute(): */ -#define XTHAL_CAFLAG_EXPAND 0x000100 /* only expand allowed access to range, don't reduce it */ -#define XTHAL_CAFLAG_EXACT 0x000200 /* return error if can't apply change to exact range specified */ -#define XTHAL_CAFLAG_NO_PARTIAL 0x000400 /* don't apply change to regions partially covered by range */ -#define XTHAL_CAFLAG_NO_AUTO_WB 0x000800 /* don't writeback data after leaving writeback attribute */ -#define XTHAL_CAFLAG_NO_AUTO_INV 0x001000 /* don't invalidate after disabling cache (entering bypass) */ - -/* enable caches */ -extern void xthal_icache_enable( void ); /* DEPRECATED */ -extern void xthal_dcache_enable( void ); /* DEPRECATED */ -/* disable caches */ -extern void xthal_icache_disable( void ); /* DEPRECATED */ -extern void xthal_dcache_disable( void ); /* DEPRECATED */ - -/* whole cache operations (privileged) */ -extern void xthal_icache_all_invalidate( void ); -extern void xthal_dcache_all_invalidate( void ); -extern void xthal_dcache_all_writeback( void ); -extern void xthal_dcache_all_writeback_inv( void ); -extern void xthal_icache_all_unlock( void ); -extern void xthal_dcache_all_unlock( void ); - -/* address-range cache operations (privileged) */ -/* prefetch and lock specified memory range into cache */ -extern void xthal_icache_region_lock( void *addr, unsigned size ); -extern void xthal_dcache_region_lock( void *addr, unsigned size ); -/* unlock from cache */ -extern void xthal_icache_region_unlock( void *addr, unsigned size ); -extern void xthal_dcache_region_unlock( void *addr, unsigned size ); - -/* huge-range cache operations (privileged) (EXPERIMENTAL) */ -extern void xthal_icache_hugerange_invalidate( void *addr, unsigned size ); -extern void xthal_icache_hugerange_unlock( void *addr, unsigned size ); -extern void xthal_dcache_hugerange_invalidate( void *addr, unsigned size ); -extern void xthal_dcache_hugerange_unlock( void *addr, unsigned size ); -extern void xthal_dcache_hugerange_writeback( void *addr, unsigned size ); -extern void xthal_dcache_hugerange_writeback_inv( void *addr, unsigned size ); - -# ifndef XTHAL_USE_CACHE_MACROS -/* cache line operations (privileged) */ -extern void xthal_icache_line_lock(void *addr); -extern void xthal_dcache_line_lock(void *addr); -extern void xthal_icache_line_unlock(void *addr); -extern void xthal_dcache_line_unlock(void *addr); -# endif - - - -/*---------------------------------------------------------------------- - Local Memory ECC/Parity - ----------------------------------------------------------------------*/ - -/* Inject memory errors; flags is bit combination of XTHAL_MEMEP_F_xxx: */ -extern void xthal_memep_inject_error(void *addr, int size, int flags); - - - -/*---------------------------------------------------------------------- - Memory Management Unit - ----------------------------------------------------------------------*/ - -extern const unsigned char Xthal_have_spanning_way; -extern const unsigned char Xthal_have_identity_map; -extern const unsigned char Xthal_have_mimic_cacheattr; -extern const unsigned char Xthal_have_xlt_cacheattr; -extern const unsigned char Xthal_have_cacheattr; -extern const unsigned char Xthal_have_tlbs; - -extern const unsigned char Xthal_mmu_asid_bits; /* 0 .. 8 */ -extern const unsigned char Xthal_mmu_asid_kernel; -extern const unsigned char Xthal_mmu_rings; /* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */ -extern const unsigned char Xthal_mmu_ring_bits; -extern const unsigned char Xthal_mmu_sr_bits; -extern const unsigned char Xthal_mmu_ca_bits; -extern const unsigned int Xthal_mmu_max_pte_page_size; -extern const unsigned int Xthal_mmu_min_pte_page_size; - -extern const unsigned char Xthal_itlb_way_bits; -extern const unsigned char Xthal_itlb_ways; -extern const unsigned char Xthal_itlb_arf_ways; -extern const unsigned char Xthal_dtlb_way_bits; -extern const unsigned char Xthal_dtlb_ways; -extern const unsigned char Xthal_dtlb_arf_ways; - -/* Return error codes for hal functions */ - -/* function sucessful, operation completed as expected */ -#define XTHAL_SUCCESS 0 -/* XTHAL_CAFLAGS_NO_PARTIAL was specified, and no full region is - * covered by the address range. */ -#define XTHAL_NO_REGIONS_COVERED -1 -/* The XTHAL_CAFLAGS_EXACT flag was given, but no exact mapping is possible. */ -#define XTHAL_INEXACT -2 -/* The supplied address doesn't correspond to the start of a region. */ -#define XTHAL_INVALID_ADDRESS -3 -/* This functionality is not available on this architecture. */ -#define XTHAL_UNSUPPORTED -4 -/* Translation failed because vaddr and paddr were not aligned. */ -#define XTHAL_ADDRESS_MISALIGNED -5 -/* There is mapping for the supplied address. */ -#define XTHAL_NO_MAPPING -6 -/* The requested access rights are not supported */ -#define XTHAL_BAD_ACCESS_RIGHTS -7 -/* The requested memory type is not supported */ -#define XTHAL_BAD_MEMORY_TYPE -8 -/* The entries supplied are not properly aligned to the MPU's background map. */ -#define XTHAL_MAP_NOT_ALIGNED -9 -/* There are not enough MPU entries available to do the requeste mapping. */ -#define XTHAL_OUT_OF_ENTRIES -10 -/* The entries supplied are not properly ordered for the MPU. */ -#define XTHAL_OUT_OF_ORDER_MAP -11 -/* an invalid argument such as a null pointer was supplied to the function */ -#define XTHAL_INVALID -12 -/* specified region is of zero size, therefore no mapping is done. */ -#define XTHAL_ZERO_SIZED_REGION -13 -/* specified range wraps around '0' */ -#define XTHAL_INVALID_ADDRESS_RANGE -14 - -/* - For backward compatibility we retain the following inconsistenly named - constants. Do not use them as they may be removed in a future release. - */ -#define XCHAL_SUCCESS XTHAL_SUCCESS -#define XCHAL_ADDRESS_MISALIGNED XTHAL_ADDRESS_MISALIGNED -#define XCHAL_INEXACT XTHAL_INEXACT -#define XCHAL_INVALID_ADDRESS XTHAL_INVALID_ADDRESS -#define XCHAL_UNSUPPORTED_ON_THIS_ARCH XTHAL_UNSUPPORTED -#define XCHAL_NO_PAGES_MAPPED XTHAL_NO_REGIONS_COVERED - - -/* Convert between virtual and physical addresses (through static maps only) - * WARNING: these two functions may go away in a future release; - * don't depend on them! -*/ -extern int xthal_static_v2p( unsigned vaddr, unsigned *paddrp ); -extern int xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached ); - -extern int xthal_set_region_translation(void* vaddr, void* paddr, - unsigned size, unsigned cache_atr, unsigned flags); -extern int xthal_v2p(void*, void**, unsigned*, unsigned*); -extern int xthal_invalidate_region(void* addr); -extern int xthal_set_region_translation_raw(void *vaddr, void *paddr, unsigned cattr); - -/*------------------------------------------------------------------------ - MPU (Memory Protection Unit) --------------------------------------------------------------------------*/ - -/* - * General notes on MPU (Memory Protection Unit): - * - * The MPU supports setting the access rights (read, write, execute) as - * well as the memory type (cacheablity, ...) - * for regions of memory. The granularity can be as small as 32 bytes. - * (XCHAL_MPU_ALIGN specifies the granularity for any specific MPU config) - * - * The MPU doesn't support mapping between virtual and physical addresses. - * - * The MPU contains a fixed number of map changeable forground map entries, - * and a background map which is fixed at configuration time. - * - * Each entry has a start address (up to 27 bits), valid flag, - * access rights (4 bits), and memory type (9 bits); - * - */ - - -/* - MPU access rights constants: - Only the combinations listed below are supported by the MPU. -*/ - -#define XTHAL_AR_NONE 0 /* no access */ -#define XTHAL_AR_R 4 /* Kernel read, User no access*/ -#define XTHAL_AR_RX 5 /* Kernel read/execute, User no access */ -#define XTHAL_AR_RW 6 /* Kernel read/write, User no access */ -#define XTHAL_AR_RWX 7 /* Kernel read/write/execute, User no access */ -#define XTHAL_AR_Ww 8 /* Kernel write, User write */ -#define XTHAL_AR_RWrwx 9 /* Kernel read/write , User read/write/execute */ -#define XTHAL_AR_RWr 10 /* Kernel read/write, User read */ -#define XTHAL_AR_RWXrx 11 /* Kernel read/write/execute, User read/execute */ -#define XTHAL_AR_Rr 12 /* Kernel read, User read */ -#define XTHAL_AR_RXrx 13 /* Kernel read/execute, User read/execute */ -#define XTHAL_AR_RWrw 14 /* Kernel read/write, User read/write */ -#define XTHAL_AR_RWXrwx 15 /* Kernel read/write/execute, - User read/write/execute */ - -#define XTHAL_AR_WIDTH 4 /* # bits used to encode access rights */ - -/* If the bit XTHAL_MPU_USE_EXISTING_ACCESS_RIGHTS is set in the accessRights - * argument to xthal_mpu_set_region_attribute(), or to the cattr argument of - * xthal_set_region_attribute() then the existing access rights for the first - * byte of the region will be used as the access rights of the new region. - */ -#define XTHAL_MPU_USE_EXISTING_ACCESS_RIGHTS 0x00002000 - -/* If the bit XTHAL_MPU_USE_EXISTING_MEMORY_TYPE is set in the memoryType - * argument to xthal_mpu_set_region_attribute(), or to the cattr argument of - * xthal_set_region_attribute() then the existing memory type for the first - * byte of the region will be used as the memory type of the new region. - */ -#define XTHAL_MPU_USE_EXISTING_MEMORY_TYPE 0x00004000 - -/* The following groups of constants are bit-wise or'd together to specify - * the memory type as input to the macros and functions that accept an - * unencoded memory type specifier: - * XTHAL_ENCODE_MEMORY_TYPE, xthal_encode_memory_type, - * xthal_mpu_set_region_attribute(), and xthal_set_region_attribute(). - * - * example: - * XTHAL_MEM_DEVICE | XTHAL_MEM_INTERRUPTIBLE | XTHAL_MEM_SYSTEM_SHARABLE - * - * or - * XTHAL_MEM_WRITEBACK | XTHAL_MEM_INNER_SHAREABLE - * - * If it is desired to specify different attributes for the system and - * local cache, then macro XTHAL_MEM_PROC_CACHE is used: - * - * XTHAL_MEM_PROC_CACHE(XTHAL_MEM_WRITEBACK, XTHAL_MEM_WRITETHRU) - * - * indicates the shared cache is writeback, but the processor's local cache - * is writethrough. - * - */ - -/* The following group of constants are used to specify cache attributes of - * an MPU entry. If the processors local cache and the system's shared cache - * have the same attributes (or if there aren't distinct local and shared - * caches) then the constant can be used directly. If different attributes - * for the shared and local caches, then use these constants as the parameters - * to the XTHAL_MEM_PROC_CACHE() macro. - */ -#define XTHAL_MEM_DEVICE 0x00008000 -#define XTHAL_MEM_NON_CACHEABLE 0x00090000 -#define XTHAL_MEM_WRITETHRU_NOALLOC 0x00080000 -#define XTHAL_MEM_WRITETHRU 0x00040000 -#define XTHAL_MEM_WRITETHRU_WRITEALLOC 0x00060000 -#define XTHAL_MEM_WRITEBACK_NOALLOC 0x00050000 -#define XTHAL_MEM_WRITEBACK 0x00070000 - -/* Indicates a read is interruptible. Only applicable to devices */ -#define XTHAL_MEM_INTERRUPTIBLE 0x08000000 - -/* Indicates if writes to this memory are bufferable ... only applicable - * to devices, and non-cacheable memory. - */ -#define XTHAL_MEM_BUFFERABLE 0x01000000 - -/* The following group of constants indicates the scope of the sharing of - * the memory region. XTHAL_MEM_INNER_SHAREABLE and XTHAL_MEM_OUTER_SHARABLE are - * only applicable to cacheable regions. XTHAL_MEM_SYSTEM_SHAREABLE is only - * applicable to devices and non-cacheable regions. - */ -#define XTHAL_MEM_NON_SHAREABLE 0x00000000 -#define XTHAL_MEM_INNER_SHAREABLE 0x02000000 -#define XTHAL_MEM_OUTER_SHAREABLE 0x04000000 -#define XTHAL_MEM_SYSTEM_SHAREABLE 0x06000000 - - -/* - * This macro is needed when the cache attributes are different for the shared - * and processor's local caches. For example: - * - * XTHAL_MEM_PROC_CACHE(XTHAL_MEM_WRITEBACK, XTHAL_MEM_NON_CACHEABLE) - * creates a memory type that is writeback cacheable in the system cache, and not - * cacheable in the processor's local cache. - */ -#define XTHAL_MEM_PROC_CACHE(system, processor) \ - (((system) & 0x000f0000) | (((processor) & 0x000f0000 ) << 4) | \ - (((system) & XTHAL_MEM_DEVICE) | ((processor) & XTHAL_MEM_DEVICE))) - -/* - * This macro converts a bit-wise combination of the XTHAL_MEM_... constants - * to the corresponding MPU memory type (9-bits). - * - * Unsupported combinations are mapped to the best available substitute. - * - * The same functionality plus error checking is available from - * xthal_encode_memory_type(). - */ -#define XTHAL_ENCODE_MEMORY_TYPE(x) \ - (((x) & 0xffffe000) ? \ - (_XTHAL_MEM_IS_DEVICE((x)) ? _XTHAL_ENCODE_DEVICE((x)) : \ - (_XTHAL_IS_SYSTEM_NONCACHEABLE((x)) ? \ - _XTHAL_ENCODE_SYSTEM_NONCACHEABLE((x)) : \ - _XTHAL_ENCODE_SYSTEM_CACHEABLE((x)))) : (x)) - -/* - * This structure is used to represent each MPU entry (both foreground and - * background). The internal representation of the structure is subject to - * change, so it should only be accessed by the XTHAL_MPU_ENTRY_... macros - * below. - */ -typedef struct xthal_MPU_entry -{ - unsigned as; /* virtual start address, and valid bit */ - unsigned at; /* access rights, and memory type (and space for entry index) */ -} xthal_MPU_entry; - -extern const xthal_MPU_entry Xthal_mpu_bgmap[]; - - - - -/* - * XTHAL_MPU_ENTRY creates an MPU entry from its component values. It is - * intended for initializing an MPU map. Example: - * const struct xthal_MPU_entry mpumap[] = - { XTHAL_MPU_ENTRY( 0x00000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), - XTHAL_MPU_ENTRY( 0xE0000000, 1, XTHAL_AR_RWXrwx, - XTHAL_MEM_NON_CACHEABLE | XTHAL_MEM_BUFFERABLE), - XTHAL_MPU_ENTRY( 0xF0000000, 1, XTHAL_AR_RWX, - XTHAL_MEM_NON_CACHEABLE | XTHAL_MEM_BUFFERABLE) }; - xthal_write_map(mpumap, sizeof(mpumap) / sizeof(struct xthal_MPU_entry)); - * - */ -#define XTHAL_MPU_ENTRY(vaddr, valid, access, memtype) \ - { (((vaddr) & 0xffffffe0) | ((valid & 0x1))), \ - (((XTHAL_ENCODE_MEMORY_TYPE(memtype)) << 12) | (((access) & 0xf) << 8)) } - -/* - * These macros get (or set) the specified field of the MPU entry. - */ -#define XTHAL_MPU_ENTRY_GET_VSTARTADDR(x) ((x).as & 0xffffffe0) - -#define XTHAL_MPU_ENTRY_SET_VSTARTADDR(x, vaddr) (x).as = \ - (((x).as) & 0x1) | ((vaddr) & 0xffffffe0) - -#define XTHAL_MPU_ENTRY_GET_VALID(x) (((x).as & 0x1)) - -#define XTHAL_MPU_ENTRY_SET_VALID(x, valid) (x).as = \ - (((x).as & 0xfffffffe) | ((valid) & 0x1)) -#define XTHAL_MPU_ENTRY_GET_ACCESS(x) ((((x).at) >> 8) & 0xf) - -#define XTHAL_MPU_ENTRY_SET_ACCESS(x, accessRights) ((x).at = \ - ((x).at & 0xfffff0ff) | (((accessRights) & 0xf) << 8)) - -#define XTHAL_MPU_ENTRY_GET_MEMORY_TYPE(x) ((((x).at) >> 12) & 0x1ff) - -#define XTHAL_MPU_ENTRY_SET_MEMORY_TYPE(x, memtype) ((x).at = \ - ((x).at & 0xffe00fff) | (((XTHAL_ENCODE_MEMORY_TYPE(memtype)) & 0x1ff) << 12)) - -/* - * These functions accept encoded access rights, and return 1 if the - * supplied memory type has the property specified by the function name, - * otherwise they return 0. - */ -extern int xthal_is_kernel_readable(int accessRights); -extern int xthal_is_kernel_writeable(int accessRights); -extern int xthal_is_kernel_executable(int accessRights); -extern int xthal_is_user_readable(int accessRights); -extern int xthal_is_user_writeable (int accessRights); -extern int xthal_is_user_executable(int accessRights); - - -/* - * This function converts a bit-wise combination of the XTHAL_MEM_.. constants - * to the corresponding MPU memory type (9-bits). - * - * If none of the XTHAL_MEM_.. bits are present in the argument, then - * bits 4-12 (9-bits) are returned ... this supports using an already encoded - * memoryType (perhaps obtained from an xthal_MPU_entry structure) as input - * to xthal_set_region_attribute(). - * - * This function first checks that the supplied constants are a valid and - * supported combination. If not, it returns XTHAL_BAD_MEMORY_TYPE. - */ -extern int xthal_encode_memory_type(unsigned int x); - -/* - * This function accepts a 9-bit memory type value (such as returned by - * XTHAL_MEM_ENTRY_GET_MEMORY_TYPE() or xthal_encode_memory_type(). They - * return 1 if the memoryType has the property specified in the function - * name and 0 otherwise. - */ -extern int xthal_is_cacheable(unsigned int memoryType); -extern int xthal_is_writeback(unsigned int memoryType); -extern int xthal_is_device(unsigned int memoryType); - -/* - * Copies the current MPU entry list into 'entries' which - * must point to available memory of at least - * sizeof(struct xthal_MPU_entry) * XCHAL_MPU_ENTRIES. - * - * This function returns XTHAL_SUCCESS. - * XTHAL_INVALID, or - * XTHAL_UNSUPPORTED. - */ -extern int xthal_read_map(struct xthal_MPU_entry* entries); - -/* - * Writes the map pointed to by 'entries' to the MPU. Before updating - * the map, it commits any uncommitted - * cache writes, and invalidates the cache if necessary. - * - * This function does not check for the correctness of the map. Generally - * xthal_check_map() should be called first to check the map. - * - * If n == 0 then the existing map is cleared, and no new map is written - * (useful for returning to reset state) - * - * If (n > 0 && n < XCHAL_MPU_ENTRIES) then a new map is written with - * (XCHAL_MPU_ENTRIES-n) padding entries added to ensure a properly ordered - * map. The resulting foreground map will be equivalent to the map vector - * fg, but the position of the padding entries should not be relied upon. - * - * If n == XCHAL_MPU_ENTRIES then the complete map as specified by fg is - * written. - * - * The CACHEADRDIS register will be set to enable caching any 512MB region - * that is overlapped by an MPU region with a cacheable memory type. - * Caching will be disabled if none of the 512 MB region is cacheable. - * - * xthal_write_map() disables the MPU foreground map during the MPU - * update and relies on the background map. - * - * As a result any interrupt that does not meet the following conditions - * must be disabled before calling xthal_write_map(): - * 1) All code and data needed for the interrupt must be - * mapped by the background map with sufficient access rights. - * 2) The interrupt code must not access the MPU. - * - */ -extern void xthal_write_map(const struct xthal_MPU_entry* entries, unsigned n); - -/* - * Checks if entry vector 'entries' of length 'n' is a valid MPU access map. - * Returns: - * XTHAL_SUCCESS if valid, - * XTHAL_OUT_OF_ENTRIES - * XTHAL_MAP_NOT_ALIGNED, - * XTHAL_BAD_ACCESS_RIGHTS, - * XTHAL_OUT_OF_ORDER_MAP, or - * XTHAL_UNSUPPORTED if config doesn't have an MPU. - */ -extern int xthal_check_map(const struct xthal_MPU_entry* entries, unsigned n); - -/* - * Returns the MPU entry that maps 'vaddr'. If 'infgmap' is non-NULL then - * *infgmap is set to 1 if 'vaddr' is mapped by the foreground map, and - * *infgmap is set to 0 if 'vaddr' is mapped by the background map. - */ -extern struct xthal_MPU_entry xthal_get_entry_for_address(void* vaddr, - int* infgmap); - -/* - * Scans the supplied MPU map and returns a value suitable for writing to - * the CACHEADRDIS register: - * Bits 0-7 -> 1 if there are no cacheable areas in the corresponding 512MB - * region and 0 otherwise. - * Bits 8-31 -> undefined. - * This function can accept a partial memory map in the same manner - * xthal_write_map() does, */ -extern unsigned int -xthal_calc_cacheadrdis(const struct xthal_MPU_entry* e, unsigned n); - -/* - * This function is intended as an MPU specific version of - * xthal_set_region_attributes(). xthal_set_region_attributes() calls - * this function for MPU configurations. - * - * This function sets the attributes for the region [vaddr, vaddr+size) - * in the MPU. - * - * Depending on the state of the MPU this function will require from - * 0 to 3 unused MPU entries. - * - * This function typically will move, add, and subtract entries from - * the MPU map during execution, so that the resulting map may - * be quite different than when the function was called. - * - * This function does make the following guarantees: - * 1) The MPU access map remains in a valid state at all times - * during its execution. - * 2) At all points during (and after) completion the memoryType - * and accessRights remain the same for all addresses - * that are not in the range [vaddr, vaddr+size). - * 3) If XTHAL_SUCCESS is returned, then the range - * [vaddr, vaddr+size) will have the accessRights and memoryType - * specified. - * 4) The CACHEADRDIS register will be set to enable caching any 512MB region - * that is overlapped by an MPU region with a cacheable memory type. - * Caching will be disabled if none of the 512 MB region is cacheable. - * - * The accessRights parameter should be either a 4-bit value corresponding - * to an MPU access mode (as defined by the XTHAL_AR_.. constants), or - * XTHAL_MPU_USE_EXISTING_ACCESS_RIGHTS. - * - * The memoryType parameter should be either a bit-wise or-ing of XTHAL_MEM_.. - * constants that represent a valid MPU memoryType, a 9-bit MPU memoryType - * value, or XTHAL_MPU_USE_EXISTING_MEMORY_TYPE. - * - * In addition to the error codes that xthal_set_region_attribute() - * returns, this function can also return: XTHAL_BAD_ACCESS_RIGHTS - * (if the access rights bits map to an unsupported combination), or - * XTHAL_OUT_OF_MAP_ENTRIES (if there are not enough unused MPU entries) - * - * If this function is called with an invalid MPU map, then this function - * will return one of the codes that is returned by xthal_check_map(). - * - * The flag, XTHAL_CAFLAG_EXPAND, is not supported - * - */ - -extern int xthal_mpu_set_region_attribute(void* vaddr, unsigned size, - int accessRights, int memoryType, unsigned flags); - -/* The following are internal implementation macros. These should not - * be directly used except by the hal code and headers. -*/ - -/* - * Layout of the MPU specifier for: XTHAL_ENCODE_MEMORY_TYPE(), - * xthal_encode_memory_type(), xthal_set_region_attribute(), - * and xthal_mpu_set_region_attribute(). THIS IS SUBJECT TO CHANGE: - * - * Bits 0-3 - reserved for pass through of accessRights - * Bits 4-12 - reserved for pass through of memoryType bits - * Bit 13 - indicates to use existing access rights of region - * Bit 14 - indicates to use existing memory type of region - * Bit 15 - indicates device - * Bit 16-19- system cache properties - * Bit 20-23- local cache properties - * Bit 24 - indicates bufferable - * Bit 25-26- encodes shareability (1=inner, 2=outer, 3=system) - * Bit 27 - indicates interruptible - * Bits 28-31- reserved for future use - */ -#define _XTHAL_SYSTEM_CACHE_BITS 0x000f0000 -#define _XTHAL_LOCAL_CACHE_BITS 0x00f00000 -#define _XTHAL_MEM_SYSTEM_RWC_MASK 0x00070000 -#define _XTHAL_MEM_LOCAL_RWC_MASK 0x00700000 -#define _XTHAL_SHIFT_RWC 16 - -#define _XTHAL_MEM_ANY_SHAREABLE(x) (((x) & XTHAL_MEM_SYSTEM_SHAREABLE) ? 1 : 0) - -#define _XTHAL_MEM_INNER_SHAREABLE(x) ((((x) & XTHAL_MEM_SYSTEM_SHAREABLE) \ - == XTHAL_MEM_INNER_SHAREABLE) ? 1 : 0) - -#define _XTHAL_MEM_IS_BUFFERABLE(x) (((x) & XTHAL_MEM_BUFFERABLE) ? 1 : 0) - -#define _XTHAL_MEM_IS_DEVICE(x) (((x) & XTHAL_MEM_DEVICE) ? 1 : 0) - -#define _XTHAL_NON_CACHEABLE_DOMAIN(x) \ - (_XTHAL_MEM_IS_DEVICE(x) || _XTHAL_MEM_ANY_SHAREABLE(x)? 0x3 : 0) - -#define _XTHAL_CACHEABLE_DOMAIN(x) (_XTHAL_MEM_ANY_SHAREABLE(x) ? \ - 0x3 : 0x1) - -#define _XTHAL_MEM_CACHE_MASK(x) ((x) & _XTHAL_SYSTEM_CACHE_BITS) - -#define _XTHAL_IS_SYSTEM_NONCACHEABLE(x) \ - (((_XTHAL_MEM_CACHE_MASK(x) & XTHAL_MEM_NON_CACHEABLE) == \ - XTHAL_MEM_NON_CACHEABLE) ? 1 : 0) - -#define _XTHAL_ENCODE_DEVICE(x) \ - (((((x) & XTHAL_MEM_INTERRUPTIBLE) ? 1 : 0) << 3) | \ - (_XTHAL_NON_CACHEABLE_DOMAIN(x) << 1) | _XTHAL_MEM_IS_BUFFERABLE(x)) - -#define _XTHAL_ENCODE_SYSTEM_NONCACHEABLE(x) \ - (0x18 | (_XTHAL_NON_CACHEABLE_DOMAIN(x) << 1) \ - | _XTHAL_MEM_IS_BUFFERABLE(x)) - -#define _XTHAL_ENCODE_SYSTEM_CACHEABLE(x) \ - (((((((x) & _XTHAL_LOCAL_CACHE_BITS) >> 4) & XTHAL_MEM_NON_CACHEABLE) == \ - XTHAL_MEM_NON_CACHEABLE) ? 1 : 0) ? \ - (_XTHAL_CACHEABLE_DOMAIN(x) << 4) : \ - _XTHAL_ENCODE_SYSTEM_CACHEABLE_LOCAL_CACHEABLE(x)) | \ - ((_XTHAL_MEM_INNER_SHAREABLE(x) << 3) | \ - (_XTHAL_MEM_CACHE_MASK(x) & _XTHAL_MEM_SYSTEM_RWC_MASK) \ - >> _XTHAL_SHIFT_RWC) - -#define _XTHAL_ENCODE_SYSTEM_CACHEABLE_LOCAL_CACHEABLE(x) \ - ((_XTHAL_CACHEABLE_DOMAIN(x) << 7) | (((((x) & _XTHAL_LOCAL_CACHE_BITS) ? \ - ((x) & _XTHAL_LOCAL_CACHE_BITS) : \ - (_XTHAL_MEM_CACHE_MASK(x) << 4)) \ - & (_XTHAL_MEM_LOCAL_RWC_MASK)) >> _XTHAL_SHIFT_RWC )) - -/* End of internal macros */ - -/* The functions and constants below here have been deprecated.*/ -#define XTHAL_MEM_NON_CACHED XTHAL_MEM_NON_CACHEABLE -#define XTHAL_MEM_NON_SHARED XTHAL_MEM_NON_SHAREABLE -#define XTHAL_MEM_INNER_SHARED XTHAL_MEM_INNER_SHAREABLE -#define XTHAL_MEM_OUTER_SHARED XTHAL_MEM_OUTER_SHAREABLE -#define XTHAL_MEM_SYSTEM_SHARED XTHAL_MEM_SYSTEM_SHAREABLE -#define XTHAL_MEM_SW_SHAREABLE 0 - -#define xthal_is_cached(memoryType) (xthal_is_cacheable((memoryType))) -extern int xthal_read_background_map(struct xthal_MPU_entry* entries); - -/* end deprecated functions and constants */ - -#ifdef __cplusplus -} -#endif -#endif /*!_ASMLANGUAGE && !_NOCLANGUAGE && !__ASSEMBLER__ */ - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - - - -/**************************************************************************** - EXPERIMENTAL and DEPRECATED Definitions - ****************************************************************************/ - - -#if !defined(_ASMLANGUAGE) && !defined(_NOCLANGUAGE) && !defined(__ASSEMBLER__) -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef INCLUDE_DEPRECATED_HAL_CODE -extern const unsigned char Xthal_have_old_exc_arch; -extern const unsigned char Xthal_have_mmu; -extern const unsigned int Xthal_num_regs; -extern const unsigned char Xthal_num_iroms; -extern const unsigned char Xthal_num_irams; -extern const unsigned char Xthal_num_droms; -extern const unsigned char Xthal_num_drams; -extern const unsigned int Xthal_configid0; -extern const unsigned int Xthal_configid1; -#endif - -#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE -#define XTHAL_24_BIT_BREAK 0x80000000 -#define XTHAL_16_BIT_BREAK 0x40000000 -extern const unsigned short Xthal_ill_inst_16[16]; -#define XTHAL_DEST_REG 0xf0000000 /* Mask for destination register */ -#define XTHAL_DEST_REG_INST 0x08000000 /* Branch address is in register */ -#define XTHAL_DEST_REL_INST 0x04000000 /* Branch address is relative */ -#define XTHAL_RFW_INST 0x00000800 -#define XTHAL_RFUE_INST 0x00000400 -#define XTHAL_RFI_INST 0x00000200 -#define XTHAL_RFE_INST 0x00000100 -#define XTHAL_RET_INST 0x00000080 -#define XTHAL_BREAK_INST 0x00000040 -#define XTHAL_SYSCALL_INST 0x00000020 -#define XTHAL_LOOP_END 0x00000010 /* Not set by xthal_inst_type */ -#define XTHAL_JUMP_INST 0x00000008 /* Call or jump instruction */ -#define XTHAL_BRANCH_INST 0x00000004 /* Branch instruction */ -#define XTHAL_24_BIT_INST 0x00000002 -#define XTHAL_16_BIT_INST 0x00000001 -typedef struct xthal_state { - unsigned pc; - unsigned ar[16]; - unsigned lbeg; - unsigned lend; - unsigned lcount; - unsigned extra_ptr; - unsigned cpregs_ptr[XTHAL_MAX_CPS]; -} XTHAL_STATE; -extern unsigned int xthal_inst_type(void *addr); -extern unsigned int xthal_branch_addr(void *addr); -extern unsigned int xthal_get_npc(XTHAL_STATE *user_state); -#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */ - -#ifdef __cplusplus -} -#endif -#endif /*!_ASMLANGUAGE && !_NOCLANGUAGE && !__ASSEMBLER__ */ - -#endif /*XTENSA_HAL_H*/ - diff --git a/src/arch/xtensa/include/xtensa/idmaasm.h b/src/arch/xtensa/include/xtensa/idmaasm.h deleted file mode 100755 index 2669ff064ffd..000000000000 --- a/src/arch/xtensa/include/xtensa/idmaasm.h +++ /dev/null @@ -1,72 +0,0 @@ -/* $Id: //depot/dev/Foxhill/Xtensa/OS/include/xtensa/mpuasm.h#5 $ */ - -/* - * Copyright (c) 2016 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. - */ - -#ifndef _IDMAASM_H_ -#define _IDMAASM_H_ - -#if XCHAL_HAVE_IDMA -#include <xtensa/idma.h> -#endif - -/* - * Macro for restore IDMA regs - * - * Parameters: - * a_save => address register containing pointer to IDMA save area - * a_temp1, a_temp2, a_temp3. => address register temporaries - */ -// IDMA_REG_SETTINGS, -// IDMA_REG_TIMEOUT, -// IDMA_REG_DESC_START, -// IDMA_REG_CONTROL, -// IDMA_REG_USERPRIV, - -.macro _idma_restore a_save, a_temp1, a_temp2, a_temp3 -#if XCHAL_HAVE_IDMA - l32i \a_temp1, \a_save, 0 - movi \a_temp3, idmareg_base - movi \a_temp2, IDMA_REG_SETTINGS - add \a_temp2, \a_temp2, \a_temp3 - wer \a_temp1, \a_temp2 - l32i \a_temp1, \a_save, 4 - movi \a_temp2, IDMA_REG_TIMEOUT - add \a_temp2, \a_temp2, \a_temp3 - wer \a_temp1, \a_temp2 - l32i \a_temp1, \a_save, 8 - movi \a_temp2, IDMA_REG_DESC_START - add \a_temp2, \a_temp2, \a_temp3 - wer \a_temp1, \a_temp2 - l32i \a_temp1, \a_save, 12 - movi \a_temp2, IDMA_REG_CONTROL - add \a_temp2, \a_temp2, \a_temp3 - wer \a_temp1, \a_temp2 - l32i \a_temp1, \a_save, 16 - movi \a_temp2, IDMA_REG_USERPRIV - add \a_temp2, \a_temp2, \a_temp3 - wer \a_temp1, \a_temp2 -#endif -.endm - -#endif //_IDMAASM_H_ diff --git a/src/arch/xtensa/include/xtensa/mpuasm.h b/src/arch/xtensa/include/xtensa/mpuasm.h deleted file mode 100644 index f14dacc0b044..000000000000 --- a/src/arch/xtensa/include/xtensa/mpuasm.h +++ /dev/null @@ -1,111 +0,0 @@ -/* $Id: //depot/dev/Foxhill/Xtensa/OS/include/xtensa/mpuasm.h#5 $ */ - -/* - * Copyright (c) 2016 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. - */ - -#ifndef _MPUASM_H_ -#define _MPUASM_H_ -#include <xtensa/config/core.h> - -/* - * Macro for writing MPU map. - * - * Parameters: - * a_map => address register containing pointer to MPU map - * a_num_entries => number of entries in the forementioned map - * a_temp1, a_temp2. => address register temporaries - * a_temp3, a_temp4 - */ - -.macro mpu_write_map a_map, a_num_entries, a_temp1, a_temp2, a_temp3, a_temp4 -#if XCHAL_HAVE_MPU - movi \a_temp1, 0 - wsr.cacheadrdis \a_temp1 // enable the cache in all regions - wsr.mpuenb \a_temp1 // disable all foreground entries - - // Clear out the unused entries. - // - // Currently we are clearing out all the entries because currently - // the entries must be ordered even if they are all disabled. - // If out of order entries were permitted when all are disabled, - // performance could be improved by clearing XCHAL_MPU_ENTRIES - n - // (n = number of entries) rather than XCHAL_MPU_ENTRIES - 1 entries. - // - movi \a_temp2, 0 - movi \a_temp3, XCHAL_MPU_ENTRIES - 1 - j 1f - .align 16 // this alignment is done to ensure that -1: - memw // todo currently wptlb must be preceeded by a memw. The instructions must - // be aligned to ensure that both are in the same cache line. These statements should be - // properly conditionalized when that restriction is removed from the HW - wptlb \a_temp2, \a_temp1 - addi \a_temp2, \a_temp2, 1 - bltu \a_temp2, \a_temp3, 1b - - // Write the new entries. - // - beqz \a_num_entries, 4f // if no entries, skip loop - addx8 \a_map, \a_num_entries, \a_map // compute end of provided map - j 3f - .align 16 -2: memw // todo currently wptlb must be preceeded by a memw. The instructions must - // be aligned to ensure that both are in the same cache line. These statements should be - // properly conditionalized when that restriction is removed from the HW - wptlb \a_temp2, \a_temp4 - addi \a_temp3, \a_temp3, -1 - beqz \a_num_entries, 4f // loop until done -3: addi \a_map, \a_map, -8 - l32i \a_temp2, \a_map, 4 // get at (acc.rights, memtype) - l32i \a_temp4, \a_map, 0 // get as (vstart, valid) - addi \a_num_entries, \a_num_entries, -1 - extui \a_temp1, \a_temp2, 0, 5 // entry index portion - xor \a_temp2, \a_temp2, \a_temp1 // zero it - or \a_temp2, \a_temp2, \a_temp3 // set index = \a_temp3 - j 2b -4: -#endif -.endm - -/* - * Macro for reading MPU map - * - * Parameters: - * a_map_ptr => address register pointing to memory where map is written - * a_temp1, a_temp2 => address register temporaries - */ -.macro mpu_read_map a_map_ptr, a_temp1, a_temp2 -#if XCHAL_HAVE_MPU - movi \a_temp1, XCHAL_MPU_ENTRIES // set index to last entry + 1 - addx8 \a_map_ptr, \a_temp1, \a_map_ptr // set map ptr to last entry + 1 -1: addi \a_temp1, \a_temp1, -1 // decrement index - addi \a_map_ptr, \a_map_ptr, -8 // decrement index - rptlb0 \a_temp2, \a_temp1 // read 1/2 of entry - s32i \a_temp2, \a_map_ptr, 0 // write 1/2 of entry - rptlb1 \a_temp2, \a_temp1 - s32i \a_temp2, \a_map_ptr, 4 - bnez \a_temp1, 1b // loop until done -#endif - .endm - -#endif diff --git a/src/arch/xtensa/include/xtensa/overlay.h b/src/arch/xtensa/include/xtensa/overlay.h deleted file mode 100644 index 9e41cd2ebc2d..000000000000 --- a/src/arch/xtensa/include/xtensa/overlay.h +++ /dev/null @@ -1,190 +0,0 @@ -// overlay.h -- Overlay manager header file -// $Id$ - -// Copyright (c) 2013 Tensilica 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. - - -#ifndef OVERLAY_H -#define OVERLAY_H - - -#include <xtensa/xtruntime.h> - - -#ifdef __cplusplus -extern "C" { -#endif - - -// Overlays not supported for CALL0 ABI -#if defined (__XTENSA_CALL0_ABI__) -#undef XT_DISABLE_OVERLAYS -#define XT_DISABLE_OVERLAYS 1 -#endif - -// Define this to turn off overlay support -#ifdef XT_DISABLE_OVERLAYS - -#define OVERLAY(n) -#define DECLARE_OVERLAY(n) - -#define xt_overlay_map(ov_id) -#define xt_overlay_map_async(ov_id) 0 -#define xt_overlay_map_in_progress() 0 -#define xt_overlay_get_id() 0 -#define xt_overlay_get_state(pc) 0 -#define xt_overlay_check_map(pc,ps,ovstate,sp) 0 - -#else - -// Shorthand for convenience and portability. -#define OVERLAY(n) __attribute__((overlay(n))) - -// Structure of the overlay table required by gdb and the overlay -// manager. Should not be accessed by user code unless overriding -// the load process. -struct ovly_table { - void * vma; // The overlay's mapped address. - unsigned int size; // The size of the overlay, in bytes. - void * lma; // The overlay's load address. - unsigned int mapped; // Non-zero if overlay is currently mapped; zero otherwise. -}; - -// Constructed by the linker. Required for gdb and for the overlay -// manager. Should not be accessed by user code unless overriding -// the load process. -extern struct ovly_table _ovly_table[]; - -// Functions. -void xt_overlay_map(int ov_id); -int xt_overlay_map_async(int ov_id); -int xt_overlay_map_in_progress(void); -unsigned int xt_overlay_get_state(unsigned int pc); -unsigned int xt_overlay_check_map(unsigned int * pc, unsigned int * ps, - unsigned int ovstate, unsigned int sp); -int xt_overlay_start_map(void * dst, void * src, unsigned int len, int ov_id); -int xt_overlay_is_mapping(int ov_id); -void xt_overlay_fatal_error(int ov_id); - - -// Returns the current overlay ID. If no overlay is mapped or an overlay -// is in the middle of being mapped, returns -1. Inlined to avoid calling -// out of overlay (wastes cycles, can end up reading wrong ID on interrupt -// activity). -// -static inline int __attribute__((always_inline)) xt_overlay_get_id(void) -{ -extern short _mapping_id; -extern short _ovly_id; - - int ret; - unsigned int flags = XTOS_SET_INTLEVEL(15); - - if (_mapping_id >= 0) { - ret = -1; - } - else { - ret = _ovly_id; - } - - XTOS_RESTORE_INTLEVEL(flags); - return ret; -} - - -// The following macros are used to declare numbered overlays and generate -// the corresponding call stubs. Use as follows: -// -// DECLARE_OVERLAY(n) -// -// See documentation for more details. - -//#include <xtensa/config/core-isa.h> - -// At this time overlays are not supported without windowing. -#if defined(__XTENSA_WINDOWED_ABI__) - -#define xstr(x) str(x) -#define str(x) #x - -// At entry, register a8 holds the return address and a9 holds the target -// function address. This stub saves a8 on the stack at (SP - 20) which -// is the only location that is safe for us to use. Then it allocates 32 -// bytes on the stack for working storage, loads the overlay number into -// a8, and jumps to the common handler. The common handler will make sure -// that the called function is loaded into memory before calling it. -// NOTE: we are using the stack area normally reserved for nested functions. -// This means nested functions cannot be used when overlays are in use. - -#define CALL_IN(num) \ - asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \ - ".global _overlay_call_in_" xstr(num) "_\n" \ - ".align 4\n" \ - "_overlay_call_in_" xstr(num) "_:\n" \ - "s32e a8, a1, -20\n" \ - "addi a8, a1, -32\n" \ - "movsp a1, a8\n" \ - "movi a8, " xstr(num) "\n" \ - "j _overlay_call_in_common\n" \ - ".size _overlay_call_in_" xstr(num) "_, . - _overlay_call_in_" xstr(num) "_\n"); - -// The call-out stub first calls the target function, then loads the overlay -// number into register a14 and jumps to the common handler. The handler will -// make sure that the caller function is present in memory before returning. -// Note that registers a10-a13 may contain return values so must be preserved. -// -// Because we came here via a call4, the return address is in a4, and the top -// 2 bits are set to the window increment. We'll restore the top 2 bits of -// the return address from the called function's address, assuming that both -// are in the same 1 GB segment. For now this is always true. - -#define CALL_OUT(num) \ - asm(".section .gnu.linkonce.t.overlay.call." xstr(num) ".text, \"ax\"\n" \ - ".global _overlay_call_out_" xstr(num) "_\n" \ - ".align 4\n" \ - "_overlay_call_out_" xstr(num) "_:\n" \ - "slli a4, a4, 2\n" \ - "srli a4, a4, 2\n" \ - "extui a8, a9, 30, 2\n" \ - "slli a8, a8, 30\n" \ - "or a4, a4, a8\n" \ - "callx8 a9\n" \ - "movi a14, " xstr(num) "\n" \ - "j _overlay_call_out_common\n" \ - ".size _overlay_call_out_" xstr(num) "_, . - _overlay_call_out_" xstr(num) "_\n"); - -// Generate a call-in and a call-out stub for each overlay. - -#define DECLARE_OVERLAY(num) \ - CALL_IN(num) \ - CALL_OUT(num) - -#endif // defined(__XTENSA_WINDOWED_ABI__) - -#endif // XT_DISABLE_OVERLAYS - -#ifdef __cplusplus -} -#endif - -#endif // OVERLAY_H - diff --git a/src/arch/xtensa/include/xtensa/overlay_os_asm.h b/src/arch/xtensa/include/xtensa/overlay_os_asm.h deleted file mode 100644 index 4adc044e6a6c..000000000000 --- a/src/arch/xtensa/include/xtensa/overlay_os_asm.h +++ /dev/null @@ -1,140 +0,0 @@ -// overlay_os_asm.h -- Overlay manager assembly macros for OS use. -// $Id$ - -// Copyright (c) 2013 Tensilica 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. - - -#ifndef OVERLAY_OS_ASM_H -#define OVERLAY_OS_ASM_H - -// The macros in here are intended to be used by RTOS task switch code -// to check overlay status. Such code is usually in assembly and cannot -// call C code without penalty. For C code usage, it is best to use the -// corresponding C functions from the library. - - -// Inline assembly version of xt_overlay_get_state(). The arguments are -// three AR registers (a0-a15): -// -// "pcreg" - should contain the outgoing task's PC, i.e. the point at -// which the task got interrupted. The return value is also -// returned in this register. -// "sr1/2" - Scratch registers. These must be distinct from "pcreg". -// -// The return value is a 32-bit result that should be saved with the -// task context and passed as-is to xt_overlay_check_map. - - .macro _xt_overlay_get_state pcreg sr1 sr2 - - movi \sr1, _mapping_id - movi \sr2, _ovly_id - l16si \sr1, \sr1, 0 - l16ui \sr2, \sr2, 0 - slli \sr1, \sr1, 16 - or \pcreg, \sr1, \sr2 - - .endm - - -// Inline assembly version of xt_overlay_check_map(). It requires 5 AR -// registers (a0-a15) as arguments. -// -// "pcreg" - should contain the interrupted task's PC, i.e. the point -// at which the task got interrupted. This will be adjusted -// if required. -// "psreg" - should contain the interrupted task's PS. This will be -// adjusted if required. -// "ovreg" - should contain the overlay state on entry. Contents may -// be clobbered. -// "spreg" - should contain the tasks stack pointer on entry. -// "sr1" - Scratch register. Must be distinct from any of the above. -// -// The return values are "pcreg" and "psreg" and these must be used -// to update the task's PC and PS. -// Note that this macro may store data below the "spreg" pointer. If -// it does, then it will also disable interrupts via the PS, so that -// the task resumes with all interrupts disabled (to avoid corrupting -// this data). -// -// (SP - 24) Overlay ID to restore -// (SP - 28) Task PC -// (SP - 32) Task PS - - .macro _xt_overlay_check_map pcreg psreg ovreg spreg sr1 - -// There are four cases to deal with: -// -// _ovly_id = -1, _mapping_id = -1 -// No overlay is mapped or mapping, nothing to do. -// -// _ovly_id >= 0, _mapping_id = -1 -// An overlay was mapped, check PC to see if we need a restore. -// -// _ovly_id = -1, _mapping_id >= 0 -// An overlay is being mapped. Either it belongs to this task, which -// implies that the PC is in the mapping function, or it does not -// belong to this task. Either way there is nothing to do. -// -// _ovly_id >= 0, _mapping_id >= 0 -// Illegal, cannot happen by design. Don't need to handle this. -// -// So, the logic is to check _ovly_id first. If this is >= 0, then -// we check the task PC. If the PC is in the regions of interest then -// we'll patch the return PC to invoke xt_overlay_restore. - -.L1: - extui \sr1, \ovreg, 0, 16 // Extract _ovly_id - bbsi.l \sr1, 15, .Lno // If -1 then we're done - mov \ovreg, \sr1 // Restore this one - -// Next check the PC to see if it falls within the ranges of interest. - -.L2: - movi \sr1, _overlay_vma // Is PC < VMA range ? - bltu \pcreg, \sr1, .L3 - movi \sr1, _overlay_vma_end // Is PC > VMA range ? - bgeu \pcreg, \sr1, .L3 - j .L4 // PC is in VMA range -.L3: - movi \sr1, _overlay_call_stubs_start // Is PC < call stubs range ? - bltu \pcreg, \sr1, .Lno - movi \sr1, _overlay_call_stubs_end // Is PC > call stubs range ? - bgeu \pcreg, \sr1, .Lno - -// If we get here then a restore is needed. Save the overlay ID, PC and PS. -// Return modified PC and PS so that xt_overlay_restore() will execute in -// the context of the task when resumed. Note that the OS resumption code -// may expect PS.EXCM to be set so we leave it as is in the return value. - -.L4: - s32e \ovreg, \spreg, -24 // Save overlay ID - s32e \pcreg, \spreg, -28 // Save task PC - s32e \psreg, \spreg, -32 // Save task PS - movi \pcreg, xt_overlay_restore // Adjust resumption PC - movi \sr1, 15 - or \psreg, \psreg, \sr1 // Set intlevel to highest -.Lno: - - .endm - -#endif // OVERLAY_OS_ASM_H - diff --git a/src/arch/xtensa/include/xtensa/simboard.h b/src/arch/xtensa/include/xtensa/simboard.h deleted file mode 100644 index 980b0b759635..000000000000 --- a/src/arch/xtensa/include/xtensa/simboard.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2001 Tensilica 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. - */ - -/* simboard.h - Xtensa ISS "Board" specific definitions */ - -#ifndef _INC_SIMBOARD_H_ -#define _INC_SIMBOARD_H_ - -#include <xtensa/config/core.h> -#include <xtensa/config/system.h> - - -/* - * Device addresses. - */ - -/* System ROM: */ -#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE -#ifdef XSHAL_ROM_VADDR -#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR -#endif -#ifdef XSHAL_ROM_PADDR -#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR -#endif - -/* System RAM: */ -#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE -#ifdef XSHAL_RAM_VADDR -#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR -#endif -#ifdef XSHAL_RAM_PADDR -#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR -#endif - - -/* - * Things that depend on device addresses. - */ - -#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_ISS_CACHEATTR_WRITEBACK -#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_ISS_CACHEATTR_WRITEALLOC -#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_ISS_CACHEATTR_WRITETHRU -#define XTBOARD_CACHEATTR_BYPASS XSHAL_ISS_CACHEATTR_BYPASS -#define XTBOARD_CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_DEFAULT - -#define XTBOARD_BUSINT_PIPE_REGIONS 0 -#define XTBOARD_BUSINT_SDRAM_REGIONS 0 - - -#endif /*_INC_SIMBOARD_H_*/ - diff --git a/src/arch/xtensa/include/xtensa/specreg.h b/src/arch/xtensa/include/xtensa/specreg.h deleted file mode 100644 index 1805811c28eb..000000000000 --- a/src/arch/xtensa/include/xtensa/specreg.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/include/xtensa/specreg.h#1 $ */ - -/* - * Copyright (c) 2005-2011 Tensilica 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. - */ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define LITBASE 5 -#define SCOMPARE1 12 -#define ACCLO 16 -#define ACCHI 17 -#define MR_0 32 -#define MR_1 33 -#define MR_2 34 -#define MR_3 35 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define PTEVADDR 83 -#define RASID 90 -#define ITLBCFG 91 -#define DTLBCFG 92 -#define IBREAKENABLE 96 -#define MEMCTL 97 -#define CACHEATTR 98 /* until T1050, XEA1 */ -#define CACHEADRDIS 98 /* LX7+ */ -#define ATOMCTL 99 -#define DDR 104 -#define MECR 110 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define CONFIGID0 176 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define CONFIGID1 208 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTREAD INTERRUPT /* alternate name for backward compatibility */ -#define INTSET INTERRUPT /* alternate name for backward compatibility */ -#define INTCLEAR 227 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 -#define MISC_REG_0 244 -#define MISC_REG_1 245 -#define MISC_REG_2 246 -#define MISC_REG_3 247 - -/* Special cases (bases of special register series): */ -#define MR 32 -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 -#define MISC_REG 244 - -/* Tensilica-defined user registers: */ -#if 0 -/*#define ... 21..24 */ /* (545CK) */ -/*#define ... 140..143 */ /* (545CK) */ -#define EXPSTATE 230 /* Diamond */ -#define THREADPTR 231 /* threadptr option */ -#define FCR 232 /* FPU */ -#define FSR 233 /* FPU */ -#define AE_OVF_SAR 240 /* HiFi2 */ -#define AE_BITHEAD 241 /* HiFi2 */ -#define AE_TS_FTS_BU_BP 242 /* HiFi2 */ -#define AE_SD_NO 243 /* HiFi2 */ -#define VSAR 240 /* VectraLX */ -#define ROUND_LO 242 /* VectraLX */ -#define ROUND_HI 243 /* VectraLX */ -#define CBEGIN 246 /* VectraLX */ -#define CEND 247 /* VectraLX */ -#endif - -#endif /* XTENSA_SPECREG_H */ - diff --git a/src/arch/xtensa/include/xtensa/trax-api.h b/src/arch/xtensa/include/xtensa/trax-api.h deleted file mode 100644 index aa1584359bc4..000000000000 --- a/src/arch/xtensa/include/xtensa/trax-api.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Misc TRAX API function definitions. - - Copyright (c) 2007-2012 Tensilica 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. */ - -#ifndef _TRAX_API_H_ -#define _TRAX_API_H_ - -#include <xtensa-isa.h> -#include <xtensa-params.h> -#include "tpack.h" -#include "traxreg.h" - -#include "xdm-regs.h" - -/* Flags for trax_stop(): */ -#define TRAX_STOP_HALT 0x0001 /* halt immediately, don't wait for post-stop-trigger capture */ -#define TRAX_STOP_QUIET 0x0002 /* don't display informative messages */ - - -/* - * Describes a TRAX channel (based on tpack). - */ -typedef struct { - tpack_channel chan; /* channel structure header */ - /* Per TRAX unit information: */ - int trax_version; /* TRAX_ID_VER(id), one of TRAX_VER_xxx macros */ - unsigned long trax_tram_size; /* size of trace RAM in bytes */ - int trax_erratum10; /* set if TRAX 1.0 erratum workarounds needed */ - int trax_erratum20; /* set if TRAX 2.0 erratum workaround needed (PR 22161)*/ - int trax_erratum20_size; - int trax_has_busy; /* has trace-busy feature */ - int trax_has_atb; /* has ATB feature */ - /*FIXME: add various features: coresight regs (don't call it that), APB, ATB, TRAM, ... */ -} trax_channel; - - -/* Prototypes: */ - -/* TRAX Protocol API: */ -extern int trax_read_register(tpack_channel *tchan, int regno, unsigned *value); -extern int trax_write_register(tpack_channel *tchan, int regno, unsigned value); -extern int trax_read_memory(tpack_channel *tchan, int address, int size, unsigned char *pdata); -extern int trax_fill_memory(tpack_channel *tchan, int address, int size, tpack_u32 pattern); -extern int trax_enumerate_devices(tpack_channel *tchan, int * buf, int * size); - -/* TRAX Network API: */ -extern unsigned long trax_ram_size(tpack_channel *traxchan); -extern unsigned long trax_ram_size_addr(tpack_channel *traxchan); -extern int trax_create_tracefile(tpack_channel *traxchan, int size, unsigned char * data, - char *filename, int hflags, const char *toolver); -extern int trax_memaccess_safe(tpack_channel *traxchan, const char *what); -extern int trax_start(tpack_channel *traxchan, int flags); -extern int trax_stop(tpack_channel *traxchan, int flags); -extern int trax_halt(tpack_channel *traxchan, int flags); -extern int trax_save(tpack_channel *traxchan, char *filename, int flags, const char *toolver, int erratum); - -/* TRAX Misc API (no network dependencies): */ -int trax_fixed_hw(unsigned * regs); -extern int trax_display_id(unsigned id, const char *prefix); -extern int trax_display_summary(unsigned id, - unsigned status, - unsigned control, - unsigned address, - unsigned delay, - unsigned trigger, - unsigned match, - unsigned startaddr, - unsigned endaddr, - const char *prefix); - -/* Other: */ - -#endif /* _TRAX_API_H_ */ - diff --git a/src/arch/xtensa/include/xtensa/trax-core-config.h b/src/arch/xtensa/include/xtensa/trax-core-config.h deleted file mode 100644 index 42a03334aa17..000000000000 --- a/src/arch/xtensa/include/xtensa/trax-core-config.h +++ /dev/null @@ -1,144 +0,0 @@ -/* Definitions for Xtensa processor config info needed for TRAX. - - Copyright (c) 2005-2011 Tensilica 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. */ - -#ifndef TRAX_CORE_CONFIG_H -#define TRAX_CORE_CONFIG_H - -#include "xtensa-params.h" - -/* - * Vector Enumerations. - */ - -/* These must match the LX2.0 and later traceport spec: */ -#define VEC_NO_VECTOR 0 -#define VEC_FIRST VEC_RESET /* first valid vector */ -#define VEC_RESET 1 -#define VEC_DEBUG 2 -#define VEC_NMI 3 -#define VEC_USER 4 -#define VEC_KERNEL 5 -#define VEC_DOUBLE 6 -#define VEC_MEMERR 7 -#define VEC_RESERVED8 8 -#define VEC_RESERVED9 9 -#define VEC_WINO4 10 -#define VEC_WINU4 11 -#define VEC_WINO8 12 -#define VEC_WINU8 13 -#define VEC_WINO12 14 -#define VEC_WINU12 15 -#define VEC_INTLEVEL2 16 -#define VEC_INTLEVEL3 17 -#define VEC_INTLEVEL4 18 -#define VEC_INTLEVEL5 19 -#define VEC_INTLEVEL6 20 -/* These are internal, i.e. don't appear like this on traceport: */ -#define VEC_DEBUG_OCD 21 -#define VEC_UNKNOWN 22 -/* Enumerations 23 through 31 are also reserved, but putting */ -/* placeholders here seems wasteful and unnecessary. */ -#define VEC_COUNT 23 - -/* Other branch (change-of-PC-flow) type encodings; - * if PC changes due to an exception or interrupt vector, - * one of the VEC_* values above is used, otherwise - * (or if it's unknown whether it's due to an exception/interrupt) - * one of the following is used: */ - -#define BRANCH_IS_VEC(n) ((n) < VEC_COUNT) /* is known to be except/interrupt? */ -#define BRANCH_OR_VEC 24 /* unknown type of branch (branch/exception/interrupt/etc) */ -#define BRANCH_UNKNOWN 25 /* unknown type of branch (anything but except/interrupt) */ -#define BRANCH_UNKNOWN_ERR 26 /* like BRANCH_UNKNOWN with known error (non-branch instr) */ -#define BRANCH_LOOPBACK 28 /* zero-overhead loopback (from LEND to LBEG) */ -#define BRANCH_CONDTAKEN 29 /* conditional branch taken (or LOOP{NEZ,GTZ} loop skip) */ -#define BRANCH_JUMP 30 /* jump (unconditional branch, i.e. J or JX) */ -#define BRANCH_IS_CALL(n) (((n) & ~3) == 32) /* is a function call? */ -#define BRANCH_CALL0 32 /* non-windowed function call (CALL0, CALLX0) */ -#define BRANCH_CALL4 33 /* windowed function call (CALL4, CALLX4) */ -#define BRANCH_CALL8 34 /* windowed function call (CALL8, CALLX8) */ -#define BRANCH_CALL12 35 /* windowed function call (CALL12, CALLX12) */ -#define BRANCH_IS_RETURN(n) ((n) >= 36) /* is any kind of return? */ -#define BRANCH_IS_CALLRETURN(n) (((n) & ~1) == 36) /* is a function return? */ -#define BRANCH_RET 36 /* non-windowed function return (RET or RET.N) */ -#define BRANCH_RETW 37 /* windowed function return (RETW or RETW.N) */ -#define BRANCH_IS_EIRETURN(n) ((n) >= 38) /* is an except/inter. return? */ -#define BRANCH_RFE 38 /* RFE or RFUE */ -#define BRANCH_RFDE 39 /* RFDE */ -#define BRANCH_RFWO 40 /* RFWO */ -#define BRANCH_RFWU 41 /* RFWU */ -#define BRANCH_RFI_2 42 /* RFI 2 */ -#define BRANCH_RFI_3 43 /* RFI 3 */ -#define BRANCH_RFI_4 44 /* RFI 4 */ -#define BRANCH_RFI_5 45 /* RFI 5 */ -#define BRANCH_RFI_6 46 /* RFI 6 */ -#define BRANCH_RFI_NMI 47 /* RFI NMILEVEL */ -#define BRANCH_RFI_DEBUG 48 /* RFI DEBUGLEVEL */ -#define BRANCH_RFME 49 /* RFME */ -#define BRANCH_COUNT 50 /* (number of defined BRANCH_xxx values) */ - - - -typedef struct { - unsigned vaddr; - unsigned vaddr2; /* for static vectors only (reloc vectors option) */ - int is_configured; -} trax_vector_t; - - -/* - * This structure describes those portion of a Tensilica processor's - * configuration that are useful for trace. - */ -typedef struct { - char ** isa_dlls; - char * core_name; /* (XPG core name, not necessarily same as XTENSA_CORE) */ - int big_endian; /* 0 = little-endian, 1 = big-endian */ - int has_loops; /* 1 = zero overhead loops configured */ - int has_autorefill; /* 1 = TLB autorefill (MMU) configured */ - unsigned max_instr_size; /* in bytes (eg. 3, 4, 8, ...) */ - unsigned int_level_max; /* number of interrupt levels configured (without NMI) */ - int debug_level; /* debug intlevel, 0 if debug not configured */ - int nmi_level; /* NMI intlevel, 0 if NMI not configured */ - unsigned targethw_min; /* min. targeted hardware version (XTENSA_HWVERSION_<rel>) */ - unsigned targethw_max; /* max. targeted hardware version (XTENSA_HWVERSION_<rel>) */ - int reloc_vectors; /* 0 = fixed vectors, 1 = relocatable vectors */ - int statvec_select; /* 0 = stat vec base 0, 1 = stat vec base 1 (SW default) */ - int vecbase_align; /* number of bits to align VECBASE (32 - bits in VECBASE) */ - unsigned statvec_base0; /* static vector base 0 */ - unsigned statvec_base1; /* static vector base 1 */ - unsigned vecbase_reset; /* reset value of VECBASE */ - trax_vector_t vectors[VEC_COUNT]; /* all vectors... */ -} trax_core_config_t; - - -/* Globals: */ -//extern const char * const trax_vector_short_names[/*VEC_COUNT*/]; // nobody uses this one -extern const char * const trax_vector_names[/*VEC_COUNT*/]; - -/* Prototypes: */ -extern int trax_read_params (trax_core_config_t *c, xtensa_params p); -extern int trax_vector_from_address(trax_core_config_t *config, unsigned long vaddr, unsigned long *vecbases); - -#endif /* TRAX_CORE_CONFIG_H */ - diff --git a/src/arch/xtensa/include/xtensa/trax-proto.h b/src/arch/xtensa/include/xtensa/trax-proto.h deleted file mode 100644 index 41d5c9fd769d..000000000000 --- a/src/arch/xtensa/include/xtensa/trax-proto.h +++ /dev/null @@ -1,91 +0,0 @@ -/* This file contains functions that are hidden from the user. These are - * protocol specific functions used to read and write TRAX registers - * and the trace memory - */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ -#ifndef _TRAX_PROTO_H -#define _TRAX_PROTO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Function to read register - * - * regno : The register number to be read (not ERI addressed) - * data : Location where the read value is kept - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_read_register_eri (int regno, unsigned *data); - -/* Function to write a value into a register - * - * regno : The register number to be written (not ERI addressed) - * value : The value to be written at that register location - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_write_register_eri (int regno, unsigned value); - -/* Function to read memory - * - * address : Address of the TraceRAM memory, each location has a word - * len : Amount of memory in bytes, to be read - * data : buffer in which the read memory is stored - * final_address: Next address to be read in the following call to this - * function (trace save mechanism) - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_read_memory_eri (unsigned address, int len, int *data, - unsigned *final_address); - -/* Function to write a value to the memory address - * - * address : Address of the TraceRAM memory - * value : The value to be written inside that location - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_write_memory_eri (int address, unsigned value); - -/* Function to write to a subfield of the register. - * Called by set and show parameter functions. - * - * regno : Register number - * regmask : Mask in order to toggle appropriate bits - * value : Value to be written in the masked location - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_write_register_field_eri (int regno, unsigned regmask, - unsigned value); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/arch/xtensa/include/xtensa/trax-util.h b/src/arch/xtensa/include/xtensa/trax-util.h deleted file mode 100644 index 123ac366dfb4..000000000000 --- a/src/arch/xtensa/include/xtensa/trax-util.h +++ /dev/null @@ -1,63 +0,0 @@ -/* This file contains utility functions that can be used for polling TRAX - * or executing higher level save functionality - * It assumes that print subroutines and file I/O routines are available - * on the system - */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ - -#ifndef _TRAX_UTIL_H -#define _TRAX_UTIL_H - - -#ifdef __cplusplus -extern "C" { -#endif - -/* User can use this function if he wants to generate a tracefile output. - * Internally it calls trax_get_trace in a loop until it realizes that - * the entire trace has been read. - * - * context : pointer to structure which contains information about the - * current TRAX session - * filename : user specified output trace file name. If the file does not - * exist, it would create the new file, else would append to it - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_save (trax_context *context, char *filename); - -/* Displays a brief machine readable status. - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_poll (trax_context *context); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/arch/xtensa/include/xtensa/trax.h b/src/arch/xtensa/include/xtensa/trax.h deleted file mode 100644 index 47049c51d215..000000000000 --- a/src/arch/xtensa/include/xtensa/trax.h +++ /dev/null @@ -1,409 +0,0 @@ -/* Header file for TRAX control Library */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ - -#ifndef _TRAX_H -#define _TRAX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define TRAX_STOP_HALT 0x0001 -#define TRAX_STOP_QUIET 0x0002 - -/* Flag values to indicate if the user wanted to reverse the pcstop - * parameters */ -#define TRAX_PCSTOP_REVERSE 0x0001 -#define TRAX_PCSTOP_NO_REVERSE 0x0000 - -/* Indicating whether postsize should be in terms of bytes, instructions - * or percentage of trace size captured */ -#define TRAX_POSTSIZE_BYTES 0x0000 -#define TRAX_POSTSIZE_INSTR 0x0001 -#define TRAX_POSTSIZE_PERCENT 0x0002 - -/* Size of the header inside the trace file */ -#define TRAX_HEADER_SIZE 256 - -/* Minimum size between start and end addresses */ -#define TRAX_MIN_TRACEMEM 64 - -/* For basic debugging */ -#define DEBUG 0 - -#include <stdbool.h> - -#define ffs(i) __builtin_ffs(i) - -/* Data structures */ - -/* Represents the context of the TRAX unit and the current TRAX session. - * To be used by set and show function calls to set and show appropriate - * parameters of appropriate TRAX unit. - */ - -typedef struct { - int trax_version; /* TRAX PC version information */ - unsigned long trax_tram_size; /* If trace RAM is present,size of it */ - int hflags; /* Flags that can be used to debug, - print info, etc. */ - int address_read_last; /* During saving of the trace, this - indicates the address from which - the current trace reading must - resume */ - unsigned long bytes_read; /* bytes read uptil now */ - unsigned long total_memlen; /* Total bytes to be read based on the - trace collected in the trace RAM */ - bool get_trace_started; /* indicates that the first chunk of - bytes (which include the header) has - been read */ -} trax_context; - - -/* -----------------------TRAX Initialization ------------------------------*/ - -/* Initializing the trax context. Reads registers and sets values for version, - * trace RAM size, total memory length, etc. Most of the other values are - * initialized to their default case. - * - * context : pointer to structure which contains information about the - * current TRAX session - * - * returns : 0 if successful, -1 if unsuccessful, -2 if ram_size if - * incorrect - */ -int trax_context_init_eri (trax_context *context); - -/* -----------------Starting/Stopping TRAX session -------------------------*/ - -/* Start tracing with current parameter setting. If tracing is already in - * progress, an error is reported. Otherwise, tracing starts and any unsaved - * contents of the TraceRAM is discarded - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if successful, 1 if trace is already active, - * -1 if unsuccessful - */ -int trax_start (trax_context *context); - -/* This command initiates a stop trigger or halts a trace session based of the - * value of the flag parameter passed. In case stop trigger is initiated, any - * selected post-stop-trigger capture proceeds normally. - * If trace capture was not in progress, or a stop was already triggered, the - * return value indicates appropriately. - * - * context : pointer to structure which contains information about the - * current TRAX session - * flags : To differentiate between stopping trace without any - * post-size-trigger capture (trax_halt) or with that. - * A zero value would stop the trace based on trigger and a - * value of one would halt it - * - * returns : 0 if successful, 1 if already stopped, -1 if unsuccessful - */ -int trax_stop_halt (trax_context *context, int flags); - -/* Resets the TRAX parameters to their default values which would internally - * involve resetting the TRAX registers. To invoke another trace session or - * reset the current tracing mechanism, this function needs to be called as - * it resets parameters of the context that deal with tracing information - * - * context : pointer to structure which contains information about the - * current TRAX session - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_reset (trax_context *context); - -/* ---------------Set/Get several TRAX parameters --------------------------*/ - -/* Sets the start address and end address (word aligned) of the trace in the - * TraceRAM. Care must be taken to ensure that the difference between the - * start and the end addresses is atleast TRAX_MIN_TRACEMEM bytes. If not, - * the values are reset to default, which is 0 for startaddr and - * traceRAM_words -1 for endaddr - * - * context : pointer to structure which contains information about the - * current TRAX session - * startaddr : value to which the start address must be set. Can be - * any value between 0 - (traceRAM_words - 1) - * endaddr : value to which the end address must be set. Can be any value - * between 0 - (traceRAM_words - 1) - * - * returns : 0 if successful, -1 if unsuccessful, -2 if the difference - * between the start and end addresses is less than - * TRAX_MIN_TRACEMEM bytes or if they are passed incorrect - * values, -3 if memory shared option is not configured, in - * which case, start and end addresses are set to default - * values instead of those passed by the user - */ -int trax_set_ram_boundaries (trax_context *context, unsigned startaddr, - unsigned endaddr); - -/* Shows the start address and end address(word aligned) of the trace in the - * TraceRAM. If incorrect, the startaddress and the endaddress values are - * set to default, i.e. 0 for startaddr and traceRAM_words - 1 for endaddr - * - * context : pointer to structure which contains information about the - * current TRAX session - * startaddr : pointer to value which will contain the start address - * endaddr : pointer to value which will contain the end address - * - * returns : 0 if successful, -1 if unsuccessful - * - */ -int trax_get_ram_boundaries (trax_context *context, unsigned *startaddr, - unsigned *endaddr); - -/* Selects stop trigger via cross-trigger input - * - * context : pointer to structure which contains information about the - * current TRAX session - * value : 0 = off (reset value), 1 = on - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ctistop (trax_context *context, unsigned value); - -/* Shows if stop-trigger via cross-trigger input is off or on - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if off, 1 if on, -1 if unsuccessful - */ -int trax_get_ctistop (trax_context *context); - -/* Selects stop trigger via processor-trigger input - * - * context : pointer to structure which contains information about the - * current TRAX session - * value : 0 = off (reset value), 1 = on - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ptistop (trax_context *context, unsigned value); - -/* Shows if stop trigger visa processor-trigger input is off or on - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if off, 1 if on, -1 if unsuccessful - */ -int trax_get_ptistop (trax_context *context); - -/* Reports cross trigger output state - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if CTO bit is reset, 1 if CTO bit is set - */ -int trax_get_cto (trax_context *context); - -/* Reports processor trigger output state - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if PTO bit is reset, 1 if PTO bit is set - */ -int trax_get_pto (trax_context *context); - -/* Selects condition that asserts cross trigger output - * - * context : pointer to structure which contains information about the - * current TRAX session - * option : 0 = off(reset value)/1 = ontrig/2 = onhalt - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ctowhen (trax_context *context, int option); - -/* Shows condition that asserted cross trigger output. It can be - * any of: ontrig or onhalt or even off - * - * context : pointer to structure which contains information about the - * current TRAX session - * - * returns : 0 if off, 1 if ontrig, 2 if onhalt, -1 if unsuccessful - */ -int trax_get_ctowhen (trax_context *context); - -/* Selects condition that asserts processor trigger output - * - * context : pointer to structure which contains information about the - * current TRAX session - * option : 0 = off(reset value)/1 = ontrig/2 = onhalt - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_set_ptowhen (trax_context *context, int option); - - -/* Shows condition that asserted processor trigger output. It can be - * any of: ontrig or onhalt or even off - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : 0 if off, 1 if ontrig, 2 if onhalt, -1 if unsuccessful - */ -int trax_get_ptowhen (trax_context *context); - -/* Selects the trace synchronization message period. - * If ATEN enabled, we cannot allow syncper to be off, set it to reset value. - * Also, if no trace RAM, and ATEN enabled, set syncper to be reset value - * i.e. 256. A value of 1 i.e. on indicates that internally the message - * frequency is set to an optimal value. This option should be preferred - * if the user is not sure what message frequency option to set for the - * trace session. - * - * context : pointer to structure which contains information about the - * current TRAX session - * option : 0 = off, 1 = on, -1 = auto, 8, 16, 32, 64, 128, - * 256 (reset value) - * - * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect - * arguments - */ -int trax_set_syncper (trax_context *context, int option); - -/* Shows trace synchronization message period. Can be one of: - * off, on, auto, 8, 16, 32, 64, 128, 256 (reset value) - * - * context : pointer to structure which contains information about the - * current TRAX session - * returns : value of sync period, 0 if off, -1 if unsuccessful - */ -int trax_get_syncper (trax_context *context); - -/* Selects stop trigger via PC match. Specifies the address or - * address range to match against program counter. Trace stops when the - * processor executes an instruction matching the specified address - * or range. - * - * context : pointer to structure which contains information about the - * current TRAX session - * index : indicates the number of stop trigger (currently there is - * only one i.e. index = 0) - * startaddress : start range of the address at which the stop trigger - * should be activated - * enaddress : end range of the address at which the stop trigger should - * be activated - * flags : If non-zero, this inverts the range. i.e. trace stops - * when the processor executes an instruction that does not - * match the specified address or range - * - * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect - * arguments (unaligned) - * - * Note : For the current version of TRAX library, the endaddress and - * startaddress can differ by at most 31 bytes and the total - * range i.e. (endaddress - startaddress + 1) has to be a power - * of two - */ -int trax_set_pcstop (trax_context *context, int index, unsigned long startaddress, - unsigned long endaddress, int flags); - -/* Shows the stop trigger via PC match - * - * context : pointer to structure which contains information about the - * current TRAX session - * index : container of information about the number of stop triggers - * startaddress : container of start range of stop trigger - * endaddress : container of end range of stop trigger - * flags : container of information whcih indicates whether the - * pc stop range is inverted or not. - * - * returns : 0 if successful, -1 if unsuccessful - */ -int trax_get_pcstop (trax_context *context, int *index, - unsigned long *startaddress, - unsigned long *endaddress, int *flags); - -/* This function is used to set the amount of trace to be captured past - * the stop trigger. - * - * context : pointer to structure which contains information about the - * current TRAX session - * count_unit : contains the count of units (instructions or bytes) to be - * captured post trigger. If 0, it implies that this is off - * unit : unit of measuring the count. 0 is bytes, 1 is instructions - * 2 is percentage of trace - * - * returns : 0 if successful, -1 if unsuccessful, -2 if incorrect - * arguments - * - */ -int trax_set_postsize (trax_context *context, int count_unit, int unit); - -/* This function shows the amount of TraceRAM in terms of the number of - * instructions or bytes, captured post the stop trigger - * - * context : pointer to structure which contains information about the - * current TRAX session - * count_unit : will contain the count of units(instructions or bytes) post - * trigger - * unit : will contain information about the events that are counted - * 0 implies that the traceRAM words consumed are counted and - * 1 implies that the target processor instructions executed and - * excpetions/interrupts taken are counted - * - * returns : 0 if postsize was got successfully, -1 if unsuccessful - */ -int trax_get_postsize (trax_context *context, int *count_unit, int *unit); - -/* -------------------------- TRAX save routines ---------------------------*/ - -/* This function should be called by the user to return a chunk of - * bytes in buf. It can be a lower layer function of save, or can be - * called by the user explicitly. If bytes_actually_read contains a 0 - * after a call to this function has been made, it implies that the entire - * trace has been read successfully. - * - * context : pointer to structure which contains information about - * the current TRAX session - * buf : Buffer that is allocated by the user, all the trace - * data read would be put in this buffer, which can then - * be used to generate a tracefile. - * The first TRAX_HEADER_SIZE of the buffer will always - * contain the header information. - * bytes_to_be_read : Indicates the bytes the user wants to read. The first - * invocation would need this parameter to be - * TRAX_HEADER_SIZE at least. - * - * returns : bytes actually read during the call to this function. - * 0 implies that all the bytes in the trace have been - * read, -1 if unsuccessful read/write of - * registers or memory, -2 if trace was active while - * this function was called, -3 if user enters - * bytes_to_be_read < TRAX_HEADER_SIZE in the first - * pass - */ -int trax_get_trace (trax_context *context, void *buf, - int bytes_to_be_read); -#ifdef __cplusplus -} -#endif - -#endif /* _TRAX_H */ diff --git a/src/arch/xtensa/include/xtensa/traxfile.h b/src/arch/xtensa/include/xtensa/traxfile.h deleted file mode 100644 index 4afc926a5076..000000000000 --- a/src/arch/xtensa/include/xtensa/traxfile.h +++ /dev/null @@ -1,62 +0,0 @@ -/* TRAX file header definition. - - Copyright (c) 2007-2012 Tensilica 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. */ - - -#define TRAX_FHEAD_MAGIC "TRAXdmp" -#define TRAX_FHEAD_VERSION 1 - -/* Header flags: */ -#define TRAX_FHEADF_OCD_ENABLED 0x00000001 /* set if OCD was enabled while capturing trace */ -#define TRAX_FHEADF_TESTDUMP 0x00000002 /* set if is a test file - (from 'memsave' instead of 'save') */ -#define TRAX_FHEADF_OCD_ENABLED_WHILE_EXIT 0x00000004 /* set if OCD was enabled while capturing trace and - we were exiting the OCD mode */ - -/* Header at the start of a TRAX dump file. */ -typedef struct { - char magic[8]; /* 00: "TRAXdmp\0" (TRAX_FHEAD_MAGIC) */ - char endianness; /* 08: 0=little-endian, 1=big-endian */ - char version; /* 09: TRAX_FHEAD_VERSION */ - char reserved0[2]; /* 0A: ... */ - unsigned filesize; /* 0C: size of the trace file, including this header */ - unsigned trace_ofs; /* 10: start of trace output, byte offset from start of header */ - unsigned trace_size; /* 14: size of trace output in bytes */ - unsigned dumptime; /* 18: date/time of capture save (secs since 1970-01-01), 0 if unknown */ - unsigned flags; /* 1C: misc flags (TRAX_FHEAD_F_xxx) */ - char username[16]; /* 20: user doing the capture/save (up to 15 chars) */ - char toolver[24]; /* 30: tool + version used for capture/save (up to 23 chars) */ - char reserved2[40]; /* 48: (reserved - could be hostname used for dump (up to 39 chars)) */ - unsigned configid[2]; /* 70: processor ConfigID values, 0 if unknown */ - unsigned ts_freq; /* 78: timestamp frequency, 0 if not specified */ - unsigned reserved3; /* 7C: (reserved) */ - unsigned id; /* 80: TRAX registers at time of save (0 if not read) */ - unsigned control; - unsigned status; - unsigned reserved4; /* Data register (should not be read) */ - unsigned address; - unsigned trigger; - unsigned match; - unsigned delay; - unsigned trax_regs[24]; /*100: (total size) -- dummy allocation (FIXME) */ -} trax_file_header; - diff --git a/src/arch/xtensa/include/xtensa/traxreg.h b/src/arch/xtensa/include/xtensa/traxreg.h deleted file mode 100644 index 282ba1feef21..000000000000 --- a/src/arch/xtensa/include/xtensa/traxreg.h +++ /dev/null @@ -1,199 +0,0 @@ -/* TRAX register definitions - - Copyright (c) 2006-2012 Tensilica 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. */ - -#ifndef _TRAX_REGISTERS_H_ -#define _TRAX_REGISTERS_H_ - -#define SHOW 1 -#define HIDE 0 - -#define RO 0 -#define RW 1 - -/* TRAX Register Numbers (from possible range of 0..127) */ -#if 0 -#define TRAXREG_ID 0 -#define TRAXREG_CONTROL 1 -#define TRAXREG_STATUS 2 -#define TRAXREG_DATA 3 -#define TRAXREG_ADDRESS 4 -#define TRAXREG_TRIGGER 5 -#define TRAXREG_MATCH 6 -#define TRAXREG_DELAY 7 -#define TRAXREG_STARTADDR 8 -#define TRAXREG_ENDADDR 9 -/* Internal use only (unpublished): */ -#define TRAXREG_P4CHANGE 16 -#define TRAXREG_P4REV 17 -#define TRAXREG_P4DATE 18 -#define TRAXREG_P4TIME 19 -#define TRAXREG_PDSTATUS 20 -#define TRAXREG_PDDATA 21 -#define TRAXREG_STOP_PC 22 -#define TRAXREG_STOP_ICNT 23 -#define TRAXREG_MSG_STATUS 24 -#define TRAXREG_FSM_STATUS 25 -#define TRAXREG_IB_STATUS 26 -#define TRAXREG_MAX 27 -#define TRAXREG_ITCTRL 96 -#endif -/* The registers above match the NAR addresses. So, their values are used for NAR access */ - -/* TRAX Register Fields */ - -/* TRAX ID register fields: */ -#define TRAX_ID_PRODNO 0xf0000000 /* product number (0=TRAX) */ -#define TRAX_ID_PRODOPT 0x0f000000 /* product options */ -#define TRAX_ID_MIW64 0x08000000 /* opt: instruction width */ -#define TRAX_ID_AMTRAX 0x04000000 /* opt: collection of options, - internal (VER_2_0 or later)*/ -#define TRAX_ID_MAJVER(id) (((id) >> 20) & 0x0f) -#define TRAX_ID_MINVER(id) (((id) >> 17) & 0x07) -#define TRAX_ID_VER(id) ((TRAX_ID_MAJVER(id)<<4)|TRAX_ID_MINVER(id)) -#define TRAX_ID_STDCFG 0x00010000 /* standard config */ -#define TRAX_ID_CFGID 0x0000ffff /* TRAX configuration ID */ -#define TRAX_ID_MEMSHARED 0x00001000 /* Memshared option in TRAX */ -#define TRAX_ID_FROM_VER(ver) ((((ver) & 0xf0) << 16) | (((ver) & 0x7) << 17)) -/* Other TRAX ID register macros: */ -/* TRAX versions of interest (TRAX_ID_VER(), ie. MAJVER*16 + MINVER): */ -#define TRAX_VER_1_0 0x10 /* RA */ -#define TRAX_VER_1_1 0x11 /* RB thru RC-2010.1 */ -#define TRAX_VER_2_0 0x20 /* RC-2010.2, RD-2010.0, - RD-2011.1 */ -#define TRAX_VER_2_1 0x21 /* RC-2011.3 / RD-2011.2 and - later */ -#define TRAX_VER_3_0 0x30 /* RE-2012.0 */ -#define TRAX_VER_3_1 0x31 /* RE-2012.1 */ -#define TRAX_VER_HUAWEI_3 TRAX_VER_3_0 /* For Huawei, PRs: 25223, 25224 - , 24880 */ - - -/* TRAX version 1.0 requires a couple software workarounds: */ -#define TRAX_ID_1_0_ERRATUM(id) (TRAX_ID_VER(id) == TRAX_VER_1_0) -/* TRAX version 2.0 requires software workaround for PR 22161: */ -#define TRAX_ID_MEMSZ_ERRATUM(id) (TRAX_ID_VER(id) == TRAX_VER_2_0) - -/* TRAX Control register fields: */ -#define TRAX_CONTROL_TREN 0x00000001 -#define TRAX_CONTROL_TRSTP 0x00000002 -#define TRAX_CONTROL_PCMEN 0x00000004 -#define TRAX_CONTROL_PTIEN 0x00000010 -#define TRAX_CONTROL_CTIEN 0x00000020 -#define TRAX_CONTROL_TMEN 0x00000080 /* 2.0+ */ -#define TRAX_CONTROL_CNTU 0x00000200 -#define TRAX_CONTROL_BIEN 0x00000400 -#define TRAX_CONTROL_BOEN 0x00000800 -#define TRAX_CONTROL_TSEN 0x00000800 -#define TRAX_CONTROL_SMPER 0x00007000 -#define TRAX_CONTROL_SMPER_SHIFT 12 -#define TRAX_CONTROL_PTOWT 0x00010000 -#define TRAX_CONTROL_CTOWT 0x00020000 -#define TRAX_CONTROL_PTOWS 0x00100000 -#define TRAX_CONTROL_CTOWS 0x00200000 -#define TRAX_CONTROL_ATID 0x7F000000 /* 2.0+, amtrax */ -#define TRAX_CONTROL_ATID_SHIFT 24 -#define TRAX_CONTROL_ATEN 0x80000000 /* 2.0+, amtrax */ - -#define TRAX_CONTROL_PTOWS_ER 0x00020000 /* For 3.0 */ -#define TRAX_CONTROL_CTOWT_ER 0x00100000 /* For 3.0 */ - -#define TRAX_CONTROL_ITCTO 0x00400000 /* For 3.0 */ -#define TRAX_CONTROL_ITCTIA 0x00800000 /* For 3.0 */ -#define TRAX_CONTROL_ITATV 0x01000000 /* For 3.0 */ - - -/* TRAX Status register fields: */ -#define TRAX_STATUS_TRACT 0x00000001 -#define TRAX_STATUS_TRIG 0x00000002 -#define TRAX_STATUS_PCMTG 0x00000004 -#define TRAX_STATUS_BUSY 0x00000008 /* ER ??? */ -#define TRAX_STATUS_PTITG 0x00000010 -#define TRAX_STATUS_CTITG 0x00000020 -#define TRAX_STATUS_MEMSZ 0x00001F00 -#define TRAX_STATUS_MEMSZ_SHIFT 8 -#define TRAX_STATUS_PTO 0x00010000 -#define TRAX_STATUS_CTO 0x00020000 - -#define TRAX_STATUS_ITCTOA 0x00400000 /* For 3.0 */ -#define TRAX_STATUS_ITCTI 0x00800000 /* For 3.0 */ -#define TRAX_STATUS_ITATR 0x01000000 /* For 3.0 */ - - -/* TRAX Address register fields: */ -#define TRAX_ADDRESS_TWSAT 0x80000000 -#define TRAX_ADDRESS_TWSAT_SHIFT 31 -#define TRAX_ADDRESS_TOTALMASK 0x00FFFFFF -// !!! VUakiVU. added for new TRAX: -#define TRAX_ADDRESS_WRAPCNT 0x7FE00000 /* version ???... */ -#define TRAX_ADDRESS_WRAP_SHIFT 21 - -/* TRAX PCMatch register fields: */ -#define TRAX_PCMATCH_PCML 0x0000001F -#define TRAX_PCMATCH_PCML_SHIFT 0 -#define TRAX_PCMATCH_PCMS 0x80000000 - -/* Compute trace ram buffer size (in bytes) from status register: */ -#define TRAX_MEM_SIZE(status) (1L << (((status) & TRAX_STATUS_MEMSZ) >> TRAX_STATUS_MEMSZ_SHIFT)) - -#if 0 -/* Describes a field within a register: */ -typedef struct { - const char* name; -// unsigned width; -// unsigned shift; - char width; - char shift; - char visible; /* 0 = internal use only, 1 = shown */ - char reserved; -} trax_regfield_t; -#endif - -/* Describes a TRAX register: */ -typedef struct { - const char* name; - unsigned id; - char width; - char visible; - char writable; - char reserved; - //const trax_regfield_t * fieldset; -} trax_regdef_t; - - -extern const trax_regdef_t trax_reglist[]; -extern const signed char trax_readable_regs[]; - -#ifdef __cplusplus -extern "C" { -#endif - -/* Prototypes: */ -extern int trax_find_reg(char * regname, char **errmsg); -extern const char * trax_regname(int regno); - -#ifdef __cplusplus -} -#endif - -#endif /* _TRAX_REGISTERS_H_ */ - diff --git a/src/arch/xtensa/include/xtensa/uart-16550.h b/src/arch/xtensa/include/xtensa/uart-16550.h deleted file mode 100644 index c551c64c1375..000000000000 --- a/src/arch/xtensa/include/xtensa/uart-16550.h +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - - Copyright (c) 2006-2007 Tensilica 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. - --------------------------------------------------------------------------------- - -uart-16550.h Generic definitions for National Semiconductor 16550 UART - -This is used by board-support-packages with one or more 16550 compatible UARTs. -A BSP provides a base address for each instance of a 16550 UART on the board. - -Note that a 16552 DUART (Dual UART) is simply two instances of a 16550 UART. - -*******************************************************************************/ - -#ifndef _UART_16550_H_ -#define _UART_16550_H_ - -/* C interface to UART registers. */ -struct uart_dev_s { - union { - uart16550_reg_t rxb; /* DLAB=0: receive buffer, read-only */ - uart16550_reg_t txb; /* DLAB=0: transmit buffer, write-only */ - uart16550_reg_t dll; /* DLAB=1: divisor, LS byte latch */ - } w0; - union { - uart16550_reg_t ier; /* DLAB=0: interrupt-enable register */ - uart16550_reg_t dlm; /* DLAB=1: divisor, MS byte latch */ - } w1; - - union { - uart16550_reg_t isr; /* DLAB=0: interrupt status register, read-only */ - uart16550_reg_t fcr; /* DLAB=0: FIFO control register, write-only */ - uart16550_reg_t afr; /* DLAB=1: alternate function register */ - } w2; - - uart16550_reg_t lcr; /* line control-register, write-only */ - uart16550_reg_t mcr; /* modem control-regsiter, write-only */ - uart16550_reg_t lsr; /* line status register, read-only */ - uart16550_reg_t msr; /* modem status register, read-only */ - uart16550_reg_t scr; /* scratch regsiter, read/write */ -}; - - -#define _RXB(u) ((u)->w0.rxb) -#define _TXB(u) ((u)->w0.txb) -#define _DLL(u) ((u)->w0.dll) -#define _IER(u) ((u)->w1.ier) -#define _DLM(u) ((u)->w1.dlm) -#define _ISR(u) ((u)->w2.isr) -#define _FCR(u) ((u)->w2.fcr) -#define _AFR(u) ((u)->w2.afr) -#define _LCR(u) ((u)->lcr) -#define _MCR(u) ((u)->mcr) -#define _LSR(u) ((u)->lsr) -#define _MSR(u) ((u)->msr) -#define _SCR(u) ((u)->scr) - -typedef volatile struct uart_dev_s uart_dev_t; - -/* IER bits */ -#define RCVR_DATA_REG_INTENABLE 0x01 -#define XMIT_HOLD_REG_INTENABLE 0x02 -#define RCVR_STATUS_INTENABLE 0x04 -#define MODEM_STATUS_INTENABLE 0x08 - -/* FCR bits */ -#define _FIFO_ENABLE 0x01 -#define RCVR_FIFO_RESET 0x02 -#define XMIT_FIFO_RESET 0x04 -#define DMA_MODE_SELECT 0x08 -#define RCVR_TRIGGER_LSB 0x40 -#define RCVR_TRIGGER_MSB 0x80 - -/* AFR bits */ -#define AFR_CONC_WRITE 0x01 -#define AFR_BAUDOUT_SEL 0x02 -#define AFR_RXRDY_SEL 0x04 - -/* ISR bits */ -#define INT_STATUS(r) ((r)&1) -#define INT_PRIORITY(r) (((r)>>1)&0x7) - -/* LCR bits */ -#define WORD_LENGTH(n) (((n)-5)&0x3) -#define STOP_BIT_ENABLE 0x04 -#define PARITY_ENABLE 0x08 -#define EVEN_PARITY 0x10 -#define FORCE_PARITY 0x20 -#define XMIT_BREAK 0x40 -#define DLAB_ENABLE 0x80 - -/* MCR bits */ -#define _DTR 0x01 -#define _RTS 0x02 -#define _OP1 0x04 -#define _OP2 0x08 -#define LOOP_BACK 0x10 - -/* LSR Bits */ -#define RCVR_DATA_READY 0x01 -#define OVERRUN_ERROR 0x02 -#define PARITY_ERROR 0x04 -#define FRAMING_ERROR 0x08 -#define BREAK_INTERRUPT 0x10 -#define XMIT_HOLD_EMPTY 0x20 -#define XMIT_EMPTY 0x40 -#define FIFO_ERROR 0x80 -#define RCVR_READY(u) (_LSR(u)&RCVR_DATA_READY) -#define XMIT_READY(u) (_LSR(u)&XMIT_HOLD_EMPTY) - -/* MSR bits */ -#define _RDR 0x01 -#define DELTA_DSR 0x02 -#define DELTA_RI 0x04 -#define DELTA_CD 0x08 -#define _CTS 0x10 -#define _DSR 0x20 -#define _RI 0x40 -#define _CD 0x80 - - -/* Compute 16-bit divisor for baudrate generator, with rounding: */ -#define UART_DIVISOR(clock,baud) (((clock)/16 + (baud)/2)/(baud)) - -/* Prototypes of driver functions */ -extern void uart16550_init( uart_dev_t *u, unsigned baud, unsigned ndata, - unsigned parity, unsigned nstop ); -extern void uart16550_out( uart_dev_t *u, char c ); -extern char uart16550_in( uart_dev_t *u ); -extern unsigned uart16550_measure_sys_clk( uart_dev_t *u ); - -#endif /* _UART_16550_H_ */ diff --git a/src/arch/xtensa/include/xtensa/xdm-regs.h b/src/arch/xtensa/include/xtensa/xdm-regs.h deleted file mode 100644 index c220bc96ca65..000000000000 --- a/src/arch/xtensa/include/xtensa/xdm-regs.h +++ /dev/null @@ -1,534 +0,0 @@ -/* xdm-regs.h - Common register and related definitions for the XDM - (Xtensa Debug Module) */ - -/* Copyright (c) 2016 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. */ - - -#ifndef _XDM_REGS_H_ -#define _XDM_REGS_H_ - -/* NOTE: This header file is included by C, assembler, and other sources. - So any C-specific or asm-specific content must be appropriately #ifdef'd. */ - - -/* - * XDM registers can be accessed using APB, ERI, or JTAG (via NAR). - * Address offsets for APB and ERI are the same, and for JTAG - * is different (due to the limited 7-bit NAR addressing). - * - * Here, we first provide the constants as APB / ERI address offsets. - * This is necessary for assembler code (which accesses XDM via ERI), - * because complex conversion macros between the two address maps - * don't work in the assembler. - * Conversion macros are used to convert these to/from JTAG (NAR), - * addresses, for software using JTAG. - */ -/* FIXME: maybe provide only MISC+CS registers here, and leave specific - subsystem registers in separate headers? eg. for TRAX, PERF, OCD */ - -/* XDM_.... ERI addr [NAR addr] Description...... */ - -/* TRAX */ -#define XDM_TRAX_ID 0x100000 /*[0x00] ID */ -#define XDM_TRAX_CONTROL 0x100004 /*[0x01] Control */ -#define XDM_TRAX_STATUS 0x100008 /*[0x02] Status */ -#define XDM_TRAX_DATA 0x10000C /*[0x03] Data */ -#define XDM_TRAX_ADDRESS 0x100010 /*[0x04] Address */ -#define XDM_TRAX_TRIGGER 0x100014 /*[0x05] Stop PC */ -#define XDM_TRAX_MATCH 0x100018 /*[0x06] Stop PC Range */ -#define XDM_TRAX_DELAY 0x10001C /*[0x07] Post Stop Trigger Capture Size */ -#define XDM_TRAX_STARTADDR 0x100020 /*[0x08] Trace Memory Start */ -#define XDM_TRAX_ENDADDR 0x100024 /*[0x09] Trace Memory End */ -#define XDM_TRAX_DEBUGPC 0x10003C /*[0x0F] Debug PC */ -#define XDM_TRAX_P4CHANGE 0x100040 /*[0x10] X */ -#define XDM_TRAX_TIME0 0x100040 /*[0x10] First Time Register */ -#define XDM_TRAX_P4REV 0x100044 /*[0x11] X */ -#define XDM_TRAX_TIME1 0x100044 /*[0x11] Second Time Register */ -#define XDM_TRAX_P4DATE 0x100048 /*[0x12] X */ -#define XDM_TRAX_INTTIME_MAX 0x100048 /*[0x12] maximal Value of Timestamp IntTime */ -#define XDM_TRAX_P4TIME 0x10004C /*[0x13] X */ -#define XDM_TRAX_PDSTATUS 0x100050 /*[0x14] Sample of PDebugStatus */ -#define XDM_TRAX_PDDATA 0x100054 /*[0x15] Sample of PDebugData */ -#define XDM_TRAX_STOP_PC 0x100058 /*[0x16] X */ -#define XDM_TRAX_STOP_ICNT 0x10005C /*[0x16] X */ -#define XDM_TRAX_MSG_STATUS 0x100060 /*[0x17] X */ -#define XDM_TRAX_FSM_STATUS 0x100064 /*[0x18] X */ -#define XDM_TRAX_IB_STATUS 0x100068 /*[0x19] X */ -#define XDM_TRAX_STOPCNT 0x10006C /*[0x1A] X */ - -/* Performance Monitoring Counters */ -#define XDM_PERF_PMG 0x101000 /*[0x20] perf. mon. global control register */ -#define XDM_PERF_INTPC 0x101010 /*[0x24] perf. mon. interrupt PC */ -#define XDM_PERF_PM0 0x101080 /*[0x28] perf. mon. counter 0 value */ -#define XDM_PERF_PM1 0x101084 /*[0x29] perf. mon. counter 1 value */ -#define XDM_PERF_PM2 0x101088 /*[0x2A] perf. mon. counter 2 value */ -#define XDM_PERF_PM3 0x10108C /*[0x2B] perf. mon. counter 3 value */ -#define XDM_PERF_PM4 0x101090 /*[0x2C] perf. mon. counter 4 value */ -#define XDM_PERF_PM5 0x101094 /*[0x2D] perf. mon. counter 5 value */ -#define XDM_PERF_PM6 0x101098 /*[0x2E] perf. mon. counter 6 value */ -#define XDM_PERF_PM7 0x10109C /*[0x2F] perf. mon. counter 7 value */ -#define XDM_PERF_PM(n) (0x101080+((n)<<2)) /* perfmon cnt n=0..7 value */ -#define XDM_PERF_PMCTRL0 0x101100 /*[0x30] perf. mon. counter 0 control */ -#define XDM_PERF_PMCTRL1 0x101104 /*[0x31] perf. mon. counter 1 control */ -#define XDM_PERF_PMCTRL2 0x101108 /*[0x32] perf. mon. counter 2 control */ -#define XDM_PERF_PMCTRL3 0x10110C /*[0x33] perf. mon. counter 3 control */ -#define XDM_PERF_PMCTRL4 0x101110 /*[0x34] perf. mon. counter 4 control */ -#define XDM_PERF_PMCTRL5 0x101114 /*[0x35] perf. mon. counter 5 control */ -#define XDM_PERF_PMCTRL6 0x101118 /*[0x36] perf. mon. counter 6 control */ -#define XDM_PERF_PMCTRL7 0x10111C /*[0x37] perf. mon. counter 7 control */ -#define XDM_PERF_PMCTRL(n) (0x101100+((n)<<2)) /* perfmon cnt n=0..7 control */ -#define XDM_PERF_PMSTAT0 0x101180 /*[0x38] perf. mon. counter 0 status */ -#define XDM_PERF_PMSTAT1 0x101184 /*[0x39] perf. mon. counter 1 status */ -#define XDM_PERF_PMSTAT2 0x101188 /*[0x3A] perf. mon. counter 2 status */ -#define XDM_PERF_PMSTAT3 0x10118C /*[0x3B] perf. mon. counter 3 status */ -#define XDM_PERF_PMSTAT4 0x101190 /*[0x3C] perf. mon. counter 4 status */ -#define XDM_PERF_PMSTAT5 0x101194 /*[0x3D] perf. mon. counter 5 status */ -#define XDM_PERF_PMSTAT6 0x101198 /*[0x3E] perf. mon. counter 6 status */ -#define XDM_PERF_PMSTAT7 0x10119C /*[0x3F] perf. mon. counter 7 status */ -#define XDM_PERF_PMSTAT(n) (0x101180+((n)<<2)) /* perfmon cnt n=0..7 status */ - -/* On-Chip-Debug (OCD) */ -#define XDM_OCD_ID 0x102000 /*[0x40] ID register */ -#define XDM_OCD_DCR_CLR 0x102008 /*[0x42] Debug Control reg clear */ -#define XDM_OCD_DCR_SET 0x10200C /*[0x43] Debug Control reg set */ -#define XDM_OCD_DSR 0x102010 /*[0x44] Debug Status reg */ -#define XDM_OCD_DDR 0x102014 /*[0x45] Debug Data reg */ -#define XDM_OCD_DDREXEC 0x102018 /*[0x46] Debug Data reg + execute-DIR */ -#define XDM_OCD_DIR0EXEC 0x10201C /*[0x47] Debug Instruction reg, word 0 + execute-DIR */ -#define XDM_OCD_DIR0 0x102020 /*[0x48] Debug Instruction reg, word 1 */ -#define XDM_OCD_DIR1 0x102024 /*[0x49] Debug Instruction reg, word 2 */ -#define XDM_OCD_DIR2 0x102028 /*[0x4A] Debug Instruction reg, word 3 */ -#define XDM_OCD_DIR3 0x10202C /*[0x49] Debug Instruction reg, word 4 */ -#define XDM_OCD_DIR4 0x102030 /*[0x4C] Debug Instruction reg, word 5 */ -#define XDM_OCD_DIR5 0x102034 /*[0x4D] Debug Instruction reg, word 5 */ -#define XDM_OCD_DIR6 0x102038 /*[0x4E] Debug Instruction reg, word 6 */ -#define XDM_OCD_DIR7 0x10203C /*[0x4F] Debug Instruction reg, word 7 */ - -/* Miscellaneous Registers */ -#define XDM_MISC_PWRCTL 0x103020 /*[0x58] Power and Reset Control */ -#define XDM_MISC_PWRSTAT 0x103024 /*[0x59] Power and Reset Status */ -#define XDM_MISC_ERISTAT 0x103028 /*[0x5A] ERI Transaction Status */ -#define XDM_MISC_DATETIME 0x103034 -#define XDM_MISC_CONFIGID1_V0 0x103034 /*[0x5D] [INTERNAL] ConfigID1 in XDM v0/1 */ -#define XDM_MISC_CONFIGID1_V2 0x10007c /*[0x1F] [INTERNAL] ConfigID1 since XDM v2 */ -#define XDM_MISC_CONFIGID0_V2 0x100078 /*[0x1E] [INTERNAL] ConfigID0 since XDM v2 */ -#define XDM_MISC_UBID 0x103038 /*[0x5E] [INTERNAL] Build Unique ID */ -#define XDM_MISC_CID 0x10303C /*[0x5F] [INTERNAL] Customer ID */ - -/* CoreSight compatibility */ -#define XDM_CS_ITCTRL 0x103F00 /*[0x60] InTegration Mode control reg */ -#define XDM_CS_CLAIMSET 0x103FA0 /*[0x68] Claim Tag Set reg */ -#define XDM_CS_CLAIMCLR 0x103FA4 /*[0x69] Claim Tag Clear reg */ -#define XDM_CS_LOCK_ACCESS 0x103FB0 /*[0x6B] Lock Access (writing 0xC5ACCE55 unlocks) */ -#define XDM_CS_LOCK_STATUS 0x103FB4 /*[0x6D] Lock Status */ -#define XDM_CS_AUTH_STATUS 0x103FB8 /*[0x6E] Authentication Status */ -#define XDM_CS_DEV_ID 0x103FC8 /*[0x72] Device ID */ -#define XDM_CS_DEV_TYPE 0x103FCC /*[0x73] Device Type */ -#define XDM_CS_PER_ID4 0x103FD0 /*[0x74] Peripheral ID reg byte 4 */ -#define XDM_CS_PER_ID5 0x103FD4 /*[0x75] Peripheral ID reg byte 5 */ -#define XDM_CS_PER_ID6 0x103FD8 /*[0x76] Peripheral ID reg byte 6 */ -#define XDM_CS_PER_ID7 0x103FDC /*[0x77] Peripheral ID reg byte 7 */ -#define XDM_CS_PER_ID0 0x103FE0 /*[0x78] Peripheral ID reg byte 0 */ -#define XDM_CS_PER_ID1 0x103FE4 /*[0x79] Peripheral ID reg byte 1 */ -#define XDM_CS_PER_ID2 0x103FE8 /*[0x7A] Peripheral ID reg byte 2 */ -#define XDM_CS_PER_ID3 0x103FEC /*[0x7B] Peripheral ID reg byte 3 */ -#define XDM_CS_COMP_ID0 0x103FF0 /*[0x7C] Component ID reg byte 0 */ -#define XDM_CS_COMP_ID1 0x103FF4 /*[0x7D] Component ID reg byte 1 */ -#define XDM_CS_COMP_ID2 0x103FF8 /*[0x7E] Component ID reg byte 2 */ -#define XDM_CS_COMP_ID3 0x103FFC /*[0x7F] Component ID reg byte 3 */ - -#define CS_PER_ID0 0x00000003 -#define CS_PER_ID1 0x00000021 -#define CS_PER_ID2 0x0000000f -#define CS_PER_ID3 0x00000000 -#define CS_PER_ID4 0x00000024 - -#define CS_COMP_ID0 0x0000000d -#define CS_COMP_ID1 0x00000090 -#define CS_COMP_ID2 0x00000005 -#define CS_COMP_ID3 0x000000b1 - -#define CS_DEV_TYPE 0x00000015 - -#define XTENSA_IDCODE 0x120034e5 // FIXME (upper bits not spec. out but BE is !) -#define XTENSA_MFC_ID (XTENSA_IDCODE & 0xFFF) -#define CS_DEV_ID XTENSA_IDCODE //FIXME - for XDM v0 only, for v2 is the new ID, that includes vars like PRID but also can be custom -#define CS_DEV_ID_v0_MASK 0x00000FFF // can compare only the lower 12 bits -#define CS_DEV_ID_v2_MASK 0xF0000000 // can compare only the upper 4 bits - -#define NXS_OCD_REG(val) ((val >= 0x40) && (val <= 0x5F)) -#define NXS_TRAX_REG(val) val <= 0x3F - -#define ERI_TRAX_REG(val) ((val & 0xFFFF) < 0x1000) -#define ERI_OCD_REG(val) ((val & 0xFFFF) >= 0x2000) && ((val & 0xFFFF) < 0x4000)) - -/* Convert above 14-bit ERI/APB address/offset to 7-bit NAR address: */ -#define _XDM_ERI_TO_NAR(a) ( ((a)&0x3F80)==0x0000 ? (((a)>>2) & 0x1F) \ - : ((a)&0x3E00)==0x1000 ? (0x20 | (((a)>>2) & 7) | (((a)>>4) & 0x18)) \ - : ((a)&0x3FC0)==0x2000 ? (0x40 | (((a)>>2) & 0xF)) \ - : ((a)&0x3FE0)==0x3020 ? (0x50 | (((a)>>2) & 0xF)) \ - : ((a)&0x3FFC)==0x3F00 ? 0x60 \ - : ((a)&0x3F80)==0x3F80 ? (0x60 | (((a)>>2) & 0x1F)) \ - : -1 ) - -#define XDM_ERI_TO_NAR(a) _XDM_ERI_TO_NAR(a & 0xFFFF) - -/* Convert 7-bit NAR address back to ERI/APB address/offset: */ -#define _XDM_NAR_TO_APB(a) ((a) <= 0x1f ? ((a) << 2) \ - :(a) >= 0x20 && (a) <= 0x3F ? (0x1000 | (((a)& 7) << 2) | (((a)&0x18)<<4)) \ - :(a) >= 0x40 && (a) <= 0x4F ? (0x2000 | (((a)&0xF) << 2)) \ - :(a) >= 0x58 && (a) <= 0x5F ? (0x3000 | (((a)&0xF) << 2)) \ - :(a) == 0x60 ? (0x3F00) \ - :(a) >= 0x68 && (a) <= 0x7F ? (0x3F80 | (((a)&0x1F) << 2)) \ - : -1) - -#define XDM_NAR_TO_APB(a) _XDM_NAR_TO_APB((a & 0xFFFF)) -#define XDM_NAR_TO_ERI(a) _XDM_NAR_TO_APB((a & 0xFFFF)) | 0x100000 - -/* Convert APB to ERI address */ -#define XDM_APB_TO_ERI(a) ((a) | (0x100000)) -#define XDM_ERI_TO_APB(a) ((a) & (0x0FFFFF)) - -/*********** Bit definitions within some of the above registers ***********/ -#define OCD_ID_LSDDRP 0x01000000 -#define OCD_ID_LSDDRP_SHIFT 24 -#define OCD_ID_ENDIANESS 0x00000001 -#define OCD_ID_ENDIANESS_SHIFT 0 -#define OCD_ID_PSO 0x0000000C -#define OCD_ID_PSO_SHIFT 2 -#define OCD_ID_TRACEPORT 0x00000080 -#define OCD_ID_TRACEPORT_SHIFT 7 - -#define OCD_ID_LSDDRP_XEA3 0x00000400 - -/* Power Status register. NOTE: different bit positions in JTAG vs. ERI/APB !! */ -/* ERI/APB: */ -#define PWRSTAT_CORE_DOMAIN_ON 0x00000001 /* set if core is powered on */ -#define PWRSTAT_CORE_DOMAIN_ON_SHIFT 0 -#define PWRSTAT_WAKEUP_RESET 0x00000002 /* [ERI only] 0=cold start, 1=PSO wakeup */ -#define PWRSTAT_WAKEUP_RESET_SHIFT 1 -#define PWRSTAT_CACHES_LOST_POWER 0x00000004 /* [ERI only] set if caches (/localmems?) lost power */ - /* FIXME: does this include local memories? */ -#define PWRSTAT_CACHES_LOST_POWER_SHIFT 2 -#define PWRSTAT_CORE_STILL_NEEDED 0x00000010 /* set if others keeping core awake */ -#define PWRSTAT_CORE_STILL_NEEDED_SHIFT 4 -#define PWRSTAT_MEM_DOMAIN_ON 0x00000100 /* set if memory domain is powered on */ -#define PWRSTAT_MEM_DOMAIN_ON_SHIFT 8 -#define PWRSTAT_DEBUG_DOMAIN_ON 0x00001000 /* set if debug domain is powered on */ -#define PWRSTAT_DEBUG_DOMAIN_ON_SHIFT 12 -#define PWRSTAT_ALL_ON (PWRSTAT_CORE_DOMAIN_ON | PWRSTAT_MEM_DOMAIN_ON | PWRSTAT_DEBUG_DOMAIN_ON) -#define PWRSTAT_CORE_WAS_RESET 0x00010000 /* [APB only] set if core got reset */ -#define PWRSTAT_CORE_WAS_RESET_SHIFT 16 -#define PWRSTAT_DEBUG_WAS_RESET 0x10000000 /* set if debug module got reset */ -#define PWRSTAT_DEBUG_WAS_RESET_SHIFT 28 -/* JTAG: */ -#define J_PWRSTAT_CORE_DOMAIN_ON 0x01 /* set if core is powered on */ -#define J_PWRSTAT_MEM_DOMAIN_ON 0x02 /* set if memory domain is powered on */ -#define J_PWRSTAT_DEBUG_DOMAIN_ON 0x04 /* set if debug domain is powered on */ -#define J_PWRSTAT_ALL_ON (J_PWRSTAT_CORE_DOMAIN_ON | J_PWRSTAT_MEM_DOMAIN_ON | J_PWRSTAT_DEBUG_DOMAIN_ON) -#define J_PWRSTAT_CORE_STILL_NEEDED 0x08 /* set if others keeping core awake */ -#define J_PWRSTAT_CORE_WAS_RESET 0x10 /* set if core got reset */ -#define J_PWRSTAT_DEBUG_WAS_RESET 0x40 /* set if debug module got reset */ - -/* Power Control register. NOTE: different bit positions in JTAG vs. ERI/APB !! */ -/* ERI/APB: */ -#define PWRCTL_CORE_SHUTOFF 0x00000001 /* [ERI only] core wants to shut off on WAITI */ -#define PWRCTL_CORE_SHUTOFF_SHIFT 0 -#define PWRCTL_CORE_WAKEUP 0x00000001 /* [APB only] set to force core to stay powered on */ -#define PWRCTL_CORE_WAKEUP_SHIFT 0 -#define PWRCTL_MEM_WAKEUP 0x00000100 /* set to force memory domain to stay powered on */ -#define PWRCTL_MEM_WAKEUP_SHIFT 8 -#define PWRCTL_DEBUG_WAKEUP 0x00001000 /* set to force debug domain to stay powered on */ -#define PWRCTL_DEBUG_WAKEUP_SHIFT 12 -#define PWRCTL_ALL_ON (PWRCTL_CORE_WAKEUP | PWRCTL_MEM_WAKEUP | PWRCTL_DEBUG_WAKEUP) -#define PWRCTL_CORE_RESET 0x00010000 /* [APB only] set to assert core reset */ -#define PWRCTL_CORE_RESET_SHIFT 16 -#define PWRCTL_DEBUG_RESET 0x10000000 /* set to assert debug module reset */ -#define PWRCTL_DEBUG_RESET_SHIFT 28 -/* JTAG: */ -#define J_PWRCTL_CORE_WAKEUP 0x01 /* set to force core to stay powered on */ -#define J_PWRCTL_MEM_WAKEUP 0x02 /* set to force memory domain to stay powered on */ -#define J_PWRCTL_DEBUG_WAKEUP 0x04 /* set to force debug domain to stay powered on */ -#define J_DEBUG_USE 0x80 /* */ -#define J_PWRCTL_ALL_ON (J_DEBUG_USE | J_PWRCTL_CORE_WAKEUP | J_PWRCTL_MEM_WAKEUP | J_PWRCTL_DEBUG_WAKEUP) -#define J_PWRCTL_DEBUG_ON J_DEBUG_USE | J_PWRCTL_DEBUG_WAKEUP -#define J_PWRCTL_CORE_RESET 0x10 /* set to assert core reset */ -#define J_PWRCTL_DEBUG_RESET 0x40 /* set to assert debug module reset */ - -#define J_PWRCTL_WRITE_MASK 0xFF -#define J_PWRSTAT_WRITE_MASK 0xFF - -#define PWRCTL_WRITE_MASK ~0 -#define PWRSTAT_WRITE_MASK ~0 - -/************ The following are only relevant for JTAG, so perhaps belong in OCD only **************/ - -/* XDM 5-bit JTAG Instruction Register (IR) values: */ -#define XDM_IR_PWRCTL 0x08 /* select 8-bit Power/Reset Control (PRC) */ -#define XDM_IR_PWRSTAT 0x09 /* select 8-bit Power/Reset Status (PRS) */ -#define XDM_IR_NAR_SEL 0x1c /* select altern. 8-bit NAR / 32-bit NDR (Nexus-style) */ -#define XDM_IR_NDR_SEL 0x1d /* select altern. 32-bit NDR / 8-bit NAR - (FIXME - functionality not yet in HW) */ -#define XDM_IR_IDCODE 0x1e /* select 32-bit JTAG IDCODE */ -#define XDM_IR_BYPASS 0x1f /* select 1-bit bypass */ - -#define XDM_IR_WIDTH 5 /* width of IR for Xtensa TAP */ - -/* NAR register bits: */ -#define XDM_NAR_WRITE 0x01 -#define XDM_NAR_ADDR_MASK 0xFE -#define XDM_NAR_ADDR_SHIFT 1 - -#define XDM_NAR_BUSY 0x02 -#define XDM_NAR_ERROR 0x01 - -#define NEXUS_DIR_READ 0x00 -#define NEXUS_DIR_WRITE 0x01 - -/************ Define DCR register bits **************/ - -#define DCR_ENABLEOCD 0x0000001 -#define DCR_ENABLEOCD_SHIFT 0 -#define DCR_DEBUG_INT 0x0000002 -#define DCR_DEBUG_INT_SHIFT 1 -#define DCR_DEBUG_OVERRIDE 0x0000004 -#define DCR_DEBUG_OVERRIDE_SHIFT 2 -#define DCR_DEBUG_SS_REQ 0x0000008 -#define DCR_DEBUG_SS_REQ_SHIFT 3 -#define DCR_MASK_NMI 0x0000020 -#define DCR_MASK_NMI_SHIFT 5 -#define DCR_STEP_ENABLE 0x0000040 -#define DCR_STEP_ENABLE_SHIFT 6 -#define DCR_BREAK_IN_EN 0x0010000 -#define DCR_BREAK_IN_EN_SHIFT 16 -#define DCR_BREAK_OUT_EN 0x0020000 -#define DCR_BREAK_OUT_EN_SHIFT 17 -#define DCR_DEBUG_INT_EN 0x0040000 -#define DCR_DEBUG_INT_EN_SHIFT 18 -#define DCR_DBG_SW_ACTIVE 0x0100000 -#define DCR_DBG_SW_ACTIVE_SHIFT 20 -#define DCR_STALL_IN_EN 0x0200000 -#define DCR_STALL_IN_EN_SHIFT 21 -#define DCR_DEBUG_OUT_EN 0x0400000 -#define DCR_DEBUG_OUT_EN_SHIFT 22 -#define DCR_BREAK_OUT_ITO 0x1000000 -#define DCR_STALL_OUT_ITO 0x2000000 -#define DCR_STALL_OUT_ITO_SHIFT 25 - -/************ Define DSR register bits **************/ - -#define DOSR_STOP_CAUSE_SHIFT 5 -#define DOSR_STOP_CAUSE_MASK 0xF - -#define DOSR_EXECDONE_SHIFT 0 -#define DOSR_EXECDONE_ER 0x01 -#define DOSR_EXECDONE_SHIFT 0 -#define DOSR_EXCEPTION_ER 0x02 -#define DOSR_EXCEPTION_SHIFT 1 -#define DOSR_BUSY 0x04 -#define DOSR_BUSY_SHIFT 2 -#define DOSR_OVERRUN 0x08 -#define DOSR_OVERRUN_SHIFT 3 -#define DOSR_INOCDMODE_ER 0x10 -#define DOSR_INOCDMODE_SHIFT 4 -#define DOSR_CORE_WROTE_DDR_ER 0x400 -#define DOSR_CORE_WROTE_DDR_SHIFT 10 -#define DOSR_CORE_READ_DDR_ER 0x800 -#define DOSR_CORE_READ_DDR_SHIFT 11 -#define DOSR_HOST_WROTE_DDR_ER 0x4000 -#define DOSR_HOST_WROTE_DDR_SHIFT 14 -#define DOSR_HOST_READ_DDR_ER 0x8000 -#define DOSR_HOST_READ_DDR_SHIFT 15 - -#define DOSR_DEBUG_PEND_BIN 0x10000 -#define DOSR_DEBUG_PEND_HOST 0x20000 -#define DOSR_DEBUG_PEND_TRAX 0x40000 -#define DOSR_DEBUG_BIN 0x100000 -#define DOSR_DEBUG_HOST 0x200000 -#define DOSR_DEBUG_TRAX 0x400000 -#define DOSR_DEBUG_PEND_BIN_SHIFT 16 -#define DOSR_DEBUG_PEND_HOST_SHIFT 17 -#define DOSR_DEBUG_PEND_TRAX_SHIFT 18 -#define DOSR_DEBUG_BREAKIN 0x0100000 -#define DOSR_DEBUG_BREAKIN_SHIFT 20 -#define DOSR_DEBUG_HOST_SHIFT 21 -#define DOSR_DEBUG_TRAX_SHIFT 22 - -#define DOSR_DEBUG_STALL 0x1000000 -#define DOSR_DEBUG_STALL_SHIFT 24 - -#define DOSR_CORE_ON 0x40000000 -#define DOSR_CORE_ON_SHIFT 30 -#define DOSR_DEBUG_ON 0x80000000 -#define DOSR_DEBUG_ON_SHIFT 31 - -/********** Performance monitor registers bits **********/ - -#define PERF_PMG_ENABLE 0x00000001 /* global enable bit */ -#define PERF_PMG_ENABLE_SHIFT 0 - -#define PERF_PMCTRL_INT_ENABLE 0x00000001 /* assert interrupt on overflow */ -#define PERF_PMCTRL_INT_ENABLE_SHIFT 0 -#define PERF_PMCTRL_KRNLCNT 0x00000008 /* ignore TRACELEVEL */ -#define PERF_PMCTRL_KRNLCNT_SHIFT 3 -#define PERF_PMCTRL_TRACELEVEL 0x000000F0 /* count when CINTLEVEL <= TRACELEVEL */ -#define PERF_PMCTRL_TRACELEVEL_SHIFT 4 -#define PERF_PMCTRL_SELECT 0x00001F00 /* events group selector */ -#define PERF_PMCTRL_SELECT_SHIFT 8 -#define PERF_PMCTRL_MASK 0xFFFF0000 /* events mask */ -#define PERF_PMCTRL_MASK_SHIFT 16 - -#define PERF_PMSTAT_OVERFLOW 0x00000001 /* counter overflowed */ -#define PERF_PMSTAT_OVERFLOW_SHIFT 0 -#define PERF_PMSTAT_INT 0x00000010 /* interrupt asserted */ -#define PERF_PMSTAT_INT_SHIFT 4 - -#if defined (USE_XDM_REGNAME) || defined (USE_DAP_REGNAME) -/* Describes XDM register: */ -typedef struct { - int reg; - char* name; -} regdef_t; - -/* - * Returns the name of the specified XDM register number, - * or simply "???" if the register number is not recognized. - * FIXME - requires -1 as the last entry - change to compare the name to ??? - * or even better, make the code above to work. - */ -static char* -regname(regdef_t* list, int reg) -{ - int i = 0; - while (list[i].reg != -1) { - if (list[i].reg == reg) - break; - i++; - } - return list[i].name; -} - -#if defined (USE_XDM_REGNAME) -static regdef_t xdm_reglist[] = -{ - {XDM_OCD_DSR ,"DOSR" }, - {XDM_OCD_DDR ,"DDR" }, - {XDM_OCD_DDREXEC ,"DDREXEC" }, - {XDM_OCD_DIR0EXEC ,"DIR0EXEC"}, - {XDM_OCD_DCR_CLR ,"DCR_CLR" }, - {XDM_OCD_DCR_SET ,"DCR_SET" }, - {XDM_TRAX_CONTROL ,"CONTROL" }, - {XDM_TRAX_STATUS ,"STATUS" }, - {XDM_TRAX_DATA ,"DATA" }, - {XDM_TRAX_ADDRESS ,"ADDRESS" }, - - {XDM_TRAX_ID ,"TRAX_ID" }, - - {XDM_TRAX_TRIGGER ,"TRIGGER PC" }, - {XDM_TRAX_MATCH ,"PC MATCH" }, - {XDM_TRAX_DELAY ,"DELAY CNT." }, - {XDM_TRAX_STARTADDR ,"START ADDRESS"}, - {XDM_TRAX_ENDADDR ,"END ADDRESS" }, - {XDM_TRAX_DEBUGPC ,"DEBUG PC" }, - {XDM_TRAX_P4CHANGE ,"P4 CHANGE" }, - {XDM_TRAX_P4REV ,"P4 REV." }, - {XDM_TRAX_P4DATE ,"P4 DATE" }, - {XDM_TRAX_P4TIME ,"P4 TIME" }, - {XDM_TRAX_PDSTATUS ,"PD STATUS" }, - {XDM_TRAX_PDDATA ,"PD DATA" }, - {XDM_TRAX_STOP_PC ,"STOP PC" }, - {XDM_TRAX_STOP_ICNT ,"STOP ICNT" }, - {XDM_TRAX_MSG_STATUS,"MSG STAT." }, - {XDM_TRAX_FSM_STATUS,"FSM STAT." }, - {XDM_TRAX_IB_STATUS ,"IB STAT." }, - - {XDM_OCD_ID ,"OCD_ID" }, - {XDM_OCD_DIR0 ,"DIR0" }, - {XDM_OCD_DIR1 ,"DIR1" }, - {XDM_OCD_DIR2 ,"DIR2" }, - {XDM_OCD_DIR3 ,"DIR3" }, - {XDM_OCD_DIR4 ,"DIR4" }, - {XDM_OCD_DIR5 ,"DIR5" }, - {XDM_OCD_DIR6 ,"DIR6" }, - {XDM_OCD_DIR7 ,"DIR7" }, - - {XDM_PERF_PMG ,"PMG" }, - {XDM_PERF_INTPC ,"INTPC" }, - {XDM_PERF_PM0 ,"PM0 " }, - {XDM_PERF_PM1 ,"PM1 " }, - {XDM_PERF_PM2 ,"PM2 " }, - {XDM_PERF_PM3 ,"PM3 " }, - {XDM_PERF_PM4 ,"PM4 " }, - {XDM_PERF_PM5 ,"PM5 " }, - {XDM_PERF_PM6 ,"PM6 " }, - {XDM_PERF_PM7 ,"PM7 " }, - {XDM_PERF_PMCTRL0 ,"PMCTRL0"}, - {XDM_PERF_PMCTRL1 ,"PMCTRL1"}, - {XDM_PERF_PMCTRL2 ,"PMCTRL2"}, - {XDM_PERF_PMCTRL3 ,"PMCTRL3"}, - {XDM_PERF_PMCTRL4 ,"PMCTRL4"}, - {XDM_PERF_PMCTRL5 ,"PMCTRL5"}, - {XDM_PERF_PMCTRL6 ,"PMCTRL6"}, - {XDM_PERF_PMCTRL7 ,"PMCTRL7"}, - {XDM_PERF_PMSTAT0 ,"PMSTAT0"}, - {XDM_PERF_PMSTAT1 ,"PMSTAT1"}, - {XDM_PERF_PMSTAT2 ,"PMSTAT2"}, - {XDM_PERF_PMSTAT3 ,"PMSTAT3"}, - {XDM_PERF_PMSTAT4 ,"PMSTAT4"}, - {XDM_PERF_PMSTAT5 ,"PMSTAT5"}, - {XDM_PERF_PMSTAT6 ,"PMSTAT6"}, - {XDM_PERF_PMSTAT7 ,"PMSTAT7"}, - - {XDM_MISC_PWRCTL ,"PWRCTL" }, - {XDM_MISC_PWRSTAT ,"PWRSTAT" }, - {XDM_MISC_ERISTAT ,"ERISTAT" }, - {XDM_MISC_DATETIME ,"DATETIME"}, - {XDM_MISC_UBID ,"UBID" }, - {XDM_MISC_CID ,"CID" }, - - {XDM_CS_ITCTRL ,"ITCTRL" }, - {XDM_CS_CLAIMSET ,"CLAIMSET" }, - {XDM_CS_CLAIMCLR ,"CLAIMCLR" }, - {XDM_CS_LOCK_ACCESS ,"LOCK_ACCESS"}, - {XDM_CS_LOCK_STATUS ,"LOCK_STATUS"}, - {XDM_CS_AUTH_STATUS ,"AUTH_STATUS"}, - {XDM_CS_DEV_ID ,"DEV_ID" }, - {XDM_CS_DEV_TYPE ,"DEV_TYPE" }, - {XDM_CS_PER_ID4 ,"PER_ID4" }, - {XDM_CS_PER_ID5 ,"PER_ID5" }, - {XDM_CS_PER_ID6 ,"PER_ID6" }, - {XDM_CS_PER_ID7 ,"PER_ID7" }, - {XDM_CS_PER_ID0 ,"PER_ID0" }, - {XDM_CS_PER_ID1 ,"PER_ID1" }, - {XDM_CS_PER_ID2 ,"PER_ID2" }, - {XDM_CS_PER_ID3 ,"PER_ID3" }, - {XDM_CS_COMP_ID0 ,"COMP_ID0" }, - {XDM_CS_COMP_ID1 ,"COMP_ID1" }, - {XDM_CS_COMP_ID2 ,"COMP_ID2" }, - {XDM_CS_COMP_ID3 ,"COMP_ID3" }, - {-1 ,"???" }, -}; -#endif - -#endif - -#endif /* _XDM_REGS_H_ */ diff --git a/src/arch/xtensa/include/xtensa/xmon.h b/src/arch/xtensa/include/xtensa/xmon.h deleted file mode 100644 index 34c90dc92902..000000000000 --- a/src/arch/xtensa/include/xtensa/xmon.h +++ /dev/null @@ -1,156 +0,0 @@ -/* xmon.h - XMON definitions - * - * $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xmon/xmon.h#1 $ - * - * Copyright (c) 2001-2013 Tensilica 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. - */ - -#ifndef __H_XMON -#define __H_XMON - -#ifndef UCHAR -# define UCHAR unsigned char -#endif - -#ifndef C_UCHAR -# define C_UCHAR const unsigned char -#endif - -#ifndef UINT32 -# define UINT32 unsigned int -#endif - -/* Default GDB packet size */ -#define GDB_PKT_SIZE 4096 - -/*XMON signals */ -#define XMON_SIGINT 2 /*target was interrupted */ -#define XMON_SIGILL 4 /*illegal instruction */ -#define XMON_SIGTRAP 5 /*general exception */ -#define XMON_SIGSEGV 11 /*page faults */ - - -/* Type of log message from XMON to the application */ -typedef enum { - XMON_LOG, - XMON_TRACE, - XMON_ERR, -} xmon_log_t; - - -#ifdef _cplusplus -extern "C" { -#endif - -/* - * THE FOLLOWING ROUTINES ARE USED BY THE USER - */ - -/** - * Initialize XMON so GDB can attach. - * gdbBuf - pointer to a buffer XMON uses to comm. with GDB - * gdbPktSize - Size of the allocated buffer for GDB communication. - * xlog - log handler for XMON produced errors/logs/traces - - */ -extern int -_xmon_init(char* gdbBuf, int gdbPktSize, - void(*xlog)(xmon_log_t type, const char* str)); - -/** - * Detach from XMON. Can execute at any time - */ -extern void -_xmon_close(void); - -/** - * Print message to GDB - */ -extern void -_xmon_consoleString(const char* str); - -/** - * XMON version - */ -extern const char* -_xmon_version(); - -/** - * Enable disable various logging and tracing chains - * app_log_en - enable/disable logging to the app log handler. - * ENABLED BY DEFAULT. - * app_trace_en - enable/disable tracing to the app log handler. - * DISABLED BY DEFAULT. - * gdb_log_en - enable/disable log notifications to the GDB. - * ENABLED BY DEFAULT. - * gdb_trace_en - enable/disable tracing notifications to the GDB. - * DISABLED BY DEFAULT. - */ -extern void -_xmon_log(char app_log_en, char app_trace_en, - char gdb_log_en, char gdb_trace_en); - -//extern int -//_xmon_process_packet (int len, char* buf); - -//extern int -//_xmon_process_packet2 (void); - -/* - * THE FOLLOWING ROUTINES NEED TO BE PROVIDED BY USER - */ - -/* - * Receive remote packet bytes from GDB - * wait: If the function would block waiting for more - * characters from gdb, wait=0 instructs it to - * return 0 immediatelly. Otherwise, if wait=1, - * the function may or may not wait for GDB. - * NOTE: Current XMON version supports single char - * input only (return value is 1 always) - * buf: Pointer to the buffer for the received data. - * Returns: 0 - no data avaiable, - >0 - length of received array in buf. - */ -extern int -_xmon_in(int wait, UCHAR* buf); - -/* - * Output an array of chars to GDB - * len - number of chars in the array - */ -extern void -_xmon_out(int len, UCHAR*); - -/* - * Flush output characthers - * XMON invokes this one when a full response is ready - */ -extern int -_xmon_flush(void); // flush output characters - -#ifdef _cplusplus -} -#endif - - -#endif diff --git a/src/arch/xtensa/include/xtensa/xtbsp.h b/src/arch/xtensa/include/xtensa/xtbsp.h deleted file mode 100644 index 0781e4154f4f..000000000000 --- a/src/arch/xtensa/include/xtensa/xtbsp.h +++ /dev/null @@ -1,287 +0,0 @@ -/******************************************************************************* - - Copyright (c) 2006-2009 Tensilica 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. - --------------------------------------------------------------------------------- - -xtbsp.h Xtensa Board Support Package API - -This API defines a minimal set of board-support functions that every supported -Xtensa board is expected to provide in the board-support-package (BSP) library -associated with the board-specific LSP. Only basic board functions are provided -in this board-independent API. API functions not applicable to a board must be -stubbed in its BSP library. More complex operations must use a board-specific -interface. Functions are grouped by type of peripheral device. - -*******************************************************************************/ - -#ifndef _XTBSP_H_ -#define _XTBSP_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - - -/******************************************************************************* -BOARD INITIALIZATION. -The board with all its devices is initialized by xtbsp_board_init(). -Individual devices represented by this API can be reinitialized at any -time by calling their inidividual device init functions (grouped with -other device functions). This might be useful to (say) change the baud -rate of the UART. -*/ - - -/* -Initialize the board. Must call before any other API function. -Iniitializes BSP, board in general, and all devices on the board. -*/ -extern void xtbsp_board_init(void); - - -/******************************************************************************* -BOARD CHARACTERISTICS and CONVENIENCE FUNCTIONS. -Board support functions not associated with a particular peripheral device. -*/ - -/* -Return a short string representing the type of board. -If the board has a display, the string must fit on a single line. -*/ -extern const char * xtbsp_board_name(void); - -/* -Hardware reset the entire board (if possible). Does not return if successful. -If this function returns, it is stubbed out or not possible with this board. -*/ -extern void xtbsp_board_reset(void); - -/* -Return the clock frequency in Hertz. May be constant or computed. -*/ -extern unsigned xtbsp_clock_freq_hz(void); - -/* -Return the clock period in picoseconds. May be constant or computed. -*/ -extern unsigned xtbsp_clock_period_ps(void); - -/* -Spin (at least) a number of cycles per the processor's CCOUNT register. -Unlike a s/w delay loop, the duration is not affected by compiler -optimization or interrupts completed within the delay period. -If the processor doesn't have CCOUNT, a s/w delay loop is used to obtain -a rough approximation of the cycle count. -*/ -extern void xtbsp_delay_cycles(unsigned cycles); - -/* -Spin at least a number of nanoseconds (approximate and err in the high side). -BSP implementation should do this efficiently, avoiding integer overflow or -excessive loss of precision, run-time division or floating point. -Function implementation (vs. macro) allows BSP to optimize for the clock -frequency by pre-computing (or using constant) scale factors. -*/ -extern void xtbsp_delay_ns(unsigned ns); - - -/******************************************************************************* -C LIBRARY SUPPORT. -These functions are called by the C library libgloss interface. -Their names are predetermined apart from this BSP API. -*/ - -/* -Initialize the board. Called by C library initialization code. -Usually simply calls xtbsp_board_init(). -*/ -extern void board_init(void); - -/* -(Wait for and) Input a single byte from the default character I/O -device. Return -1 if there is no input device. -This device is usually a UART and this function calls xtbsp_uart_getchar(). -On some boards (eg.) it might be a directly connected keyboard. -*/ -extern int inbyte(void); - -/* -Output a single char to the default character I/O device (and wait -until it's been taken). -This device is usually a UART and this function calls xtbsp_uart_putchar(). -On some boards (eg.) it might be a directly connected bit-mapped screen. -*/ -extern void outbyte(int c); - - -/******************************************************************************* -UART (SERIAL I/O). -Supports a single UART in a simple polling mode and provides control of -receiver and transmitter data interrupts (client must provide handler). -Provides a mapping to processor interrupt number which can be used with -the HAL to control processor interrupt enable (INTENABLE) etc. -*/ - -/* Bitmasks to identify UART interrupts. */ -typedef enum xtbsp_uart_int { - xtbsp_uart_int_rx = 1<<0, - xtbsp_uart_int_tx = 1<<1, - /* mask of all valid interrupt bits */ - xtbsp_uart_int_all = (1<<2)-1 -} xtbsp_uart_int; - -/* -Return non-zero if the board has a UART. -*/ -extern int xtbsp_uart_exists(void); - -/* -Initialize the UART: - parity = 0 (none), 1 (odd), or 2 (even). - nstop = 1 or 2 (stop bits). - ndata = 7 or 8 (data bits). -Disables all UART interrupts. -Returns non-zero if failed (perhaps due to unsupported parameter values). -Must call before any of the following functions. -*/ -extern int xtbsp_uart_init(unsigned baud, unsigned ndata, - unsigned parity, unsigned nstop); -#define xtbsp_uart_init_default() xtbsp_uart_init(38400, 8, 0, 1) - -/* - Extended init routine for 'portable' UART. Allows specifying the UART - base address and interrupt number (if interrupt operation desired). - Meant for use on platforms other than the FPGA boards (e.g. XTSC sim - or Palladium). - - NOTE: Using the 'portable' UART may require that you implement function - xtbsp_clock_freq_hz() if your target platform does not provide it. - We recommend you implement it as a weak function so that it can be - overridden by the target platform implementation if available. - */ -extern int xtbsp_uart_init_ex(unsigned uart_baseaddr, - unsigned uart_intnum, - unsigned baud, - unsigned ndata, - unsigned parity, - unsigned nstop); - -/* -(Wait for and) Input a single char from the UART. -Any pending xtbsp_uart_int_rx interrupt is cleared. -*/ -extern char xtbsp_uart_getchar(void); - -/* -(Wait for transmitter ready and) Output a single char to the UART. -Any pending xtbsp_uart_int_tx interrupt is cleared. -*/ -extern void xtbsp_uart_putchar(const char c); - -/* -Return true (non-zero) if a character has been received and is ready -to be input by xtbsp_uart_getchar() without waiting, else return 0. -*/ -extern int xtbsp_uart_get_isready(void); - -/* -Return non-zero if a character may be output by xtbsp_uart_putchar() -without waiting, else return 0. -Any pending xtbsp_uart_int_tx interrupt is cleared. -*/ -extern int xtbsp_uart_put_isready(void); - -/* -Return the enable status of all UART interrupts represented by this API, -that is those with bits defined in type xtbsp_uart_int (1 bit = enabled). -This is the enable status at the device, not the processor's INTENABLE. -*/ -extern xtbsp_uart_int xtbsp_uart_int_enable_status(void); - -/* -Enable selected UART interrupts at the device. -*/ -extern void xtbsp_uart_int_enable(const xtbsp_uart_int mask); - -/* -Disable selected UART interrupts at the device. -*/ -extern void xtbsp_uart_int_disable(const xtbsp_uart_int mask); - -/* -Return the interrupt number (0..31) to which the selected UART interrupt -is connected. May be used with the link-time HAL to obtain more information, -eg. Xthal_intlevel_mask[xtbsp_uart_int_number(xtbsp_uart_int_rx)] -This information can be used to control the processor's INTENABLE, etc. -Result is -1 if not connected, undefined if mask has more than 1 bit set. -*/ -extern int xtbsp_uart_int_number(const xtbsp_uart_int mask); - - -/******************************************************************************* -DISPLAY. -Supports a single display that can render a series of ASCII characters. -Functions are provided to perform generic display tasks such as display -a string, display character by character, or blank the display. -Chars are 7-bit printable ASCII. Strings are C style NUL \0 terminated. -These functions busy-wait for any required timing delays so the caller does -not have to deal with timing. Some displays require long delays which in -some client applications warrant a board and RTOS specific approach to -driving the display, however that is beyond the scope of this API. -*/ - -/* -Return non-zero if board has a display. -*/ -extern int xtbsp_display_exists(void); - -/* -Initialize the display. Must call before any of the following functions. -*/ -extern void xtbsp_display_init(void); - -/* -Display a single char at position pos (0 is leftmost). Other positions are -left untouched. Positions beyond the width of the display are ignored. -*/ -extern void xtbsp_display_char(unsigned pos, const char c); - -/* -Display a string. Blank-pad to or truncate at the end of the display -(overwrites any previous string so don't need to blank display first). -*/ -extern void xtbsp_display_string(const char *s); - -/* -Blank (clear) the entire display. -*/ -extern void xtbsp_display_blank(void); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _XTBSP_H_ */ diff --git a/src/arch/xtensa/include/xtensa/xtensa-libdb-macros.h b/src/arch/xtensa/include/xtensa/xtensa-libdb-macros.h deleted file mode 100644 index 8f67184d3454..000000000000 --- a/src/arch/xtensa/include/xtensa/xtensa-libdb-macros.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * xtensa-libdb-macros.h - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/Software/libdb/xtensa-libdb-macros.h#1 $ */ - -/* Copyright (c) 2004-2008 Tensilica 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. */ - -#ifndef __H_LIBDB_MACROS -#define __H_LIBDB_MACROS - -/* - * This header file provides macros used to construct, identify and use - * "target numbers" that are assigned to various types of Xtensa processor - * registers and states. These target numbers are used by GDB in the remote - * protocol, and are thus used by all GDB debugger agents (targets). - * They are also used in ELF debugger information sections (stabs, dwarf, etc). - * - * These macros are separated from xtensa-libdb.h because they are needed - * by certain debugger agents that do not use or have access to libdb, - * e.g. the OCD daemon, RedBoot, XMON, etc. - * - * For the time being, for compatibility with certain 3rd party debugger - * software vendors, target numbers are limited to 16 bits. It is - * conceivable that this will be extended in the future to 32 bits. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef uint32 - #define uint32 unsigned int -#endif -#ifndef int32 - #define int32 int -#endif - - -/* - * Macros to form register "target numbers" for various standard registers/states: - */ -#define XTENSA_DBREGN_INVALID -1 /* not a valid target number */ -#define XTENSA_DBREGN_A(n) (0x0000+(n)) /* address registers a0..a15 */ -#define XTENSA_DBREGN_B(n) (0x0010+(n)) /* boolean bits b0..b15 */ -#define XTENSA_DBREGN_PC 0x0020 /* program counter */ - /* 0x0021 RESERVED for use by Tensilica */ -#define XTENSA_DBREGN_BO(n) (0x0022+(n)) /* boolean octuple-bits bo0..bo1 */ -#define XTENSA_DBREGN_BQ(n) (0x0024+(n)) /* boolean quadruple-bits bq0..bq3 */ -#define XTENSA_DBREGN_BD(n) (0x0028+(n)) /* boolean double-bits bd0..bd7 */ -#define XTENSA_DBREGN_F(n) (0x0030+(n)) /* floating point registers f0..f15 */ -#define XTENSA_DBREGN_VEC(n) (0x0040+(n)) /* Vectra vec regs v0..v15 */ -#define XTENSA_DBREGN_VSEL(n) (0x0050+(n)) /* Vectra sel s0..s3 (V1) ..s7 (V2) */ -#define XTENSA_DBREGN_VALIGN(n) (0x0058+(n)) /* Vectra valign regs u0..u3 */ -#define XTENSA_DBREGN_VCOEFF(n) (0x005C+(n)) /* Vectra I vcoeff regs c0..c1 */ - /* 0x005E..0x005F RESERVED for use by Tensilica */ -#define XTENSA_DBREGN_AEP(n) (0x0060+(n)) /* HiFi2 Audio Engine regs aep0..aep7 */ -#define XTENSA_DBREGN_AEQ(n) (0x0068+(n)) /* HiFi2 Audio Engine regs aeq0..aeq3 */ - /* 0x006C..0x00FF RESERVED for use by Tensilica */ -#define XTENSA_DBREGN_AR(n) (0x0100+(n)) /* physical address regs ar0..ar63 - (note: only with window option) */ - /* 0x0140..0x01FF RESERVED for use by Tensilica */ -#define XTENSA_DBREGN_SREG(n) (0x0200+(n)) /* special registers 0..255 (core) */ -#define XTENSA_DBREGN_BR XTENSA_DBREGN_SREG(0x04) /* all 16 boolean bits, BR */ -#define XTENSA_DBREGN_MR(n) XTENSA_DBREGN_SREG(0x20+(n)) /* MAC16 registers m0..m3 */ -#define XTENSA_DBREGN_UREG(n) (0x0300+(n)) /* user registers 0..255 (TIE) */ - /* 0x0400..0x0FFF RESERVED for use by Tensilica */ - /* 0x1000..0x1FFF user-defined regfiles */ - /* 0x2000..0xEFFF other states (and regfiles) */ -#define XTENSA_DBREGN_DBAGENT(n) (0xF000+(n)) /* non-processor "registers" 0..4095 for - 3rd-party debugger agent defined use */ - /* > 0xFFFF (32-bit) RESERVED for use by Tensilica */ -/*#define XTENSA_DBREGN_CONTEXT(n) (0x02000000+((n)<<20))*/ /* add this macro's value to a target - number to identify a specific context 0..31 - for context-replicated registers */ -#define XTENSA_DBREGN_MASK 0xFFFF /* mask of valid target_number bits */ -#define XTENSA_DBREGN_WRITE_SIDE 0x04000000 /* flag to request write half of a register - split into distinct read and write entries - with the same target number (currently only - valid in a couple of libdb API functions; - see xtensa-libdb.h for details) */ - -/* - * Macros to identify specific ranges of target numbers (formed above): - * NOTE: any context number (or other upper 12 bits) are considered - * modifiers and are thus stripped out for identification purposes. - */ -#define XTENSA_DBREGN_IS_VALID(tn) (((tn) & ~0xFFFF) == 0) /* just tests it's 16-bit unsigned */ -#define XTENSA_DBREGN_IS_A(tn) (((tn) & 0xFFF0)==0x0000) /* is a0..a15 */ -#define XTENSA_DBREGN_IS_B(tn) (((tn) & 0xFFF0)==0x0010) /* is b0..b15 */ -#define XTENSA_DBREGN_IS_PC(tn) (((tn) & 0xFFFF)==0x0020) /* is program counter */ -#define XTENSA_DBREGN_IS_BO(tn) (((tn) & 0xFFFE)==0x0022) /* is bo0..bo1 */ -#define XTENSA_DBREGN_IS_BQ(tn) (((tn) & 0xFFFC)==0x0024) /* is bq0..bq3 */ -#define XTENSA_DBREGN_IS_BD(tn) (((tn) & 0xFFF8)==0x0028) /* is bd0..bd7 */ -#define XTENSA_DBREGN_IS_F(tn) (((tn) & 0xFFF0)==0x0030) /* is f0..f15 */ -#define XTENSA_DBREGN_IS_VEC(tn) (((tn) & 0xFFF0)==0x0040) /* is v0..v15 */ -#define XTENSA_DBREGN_IS_VSEL(tn) (((tn) & 0xFFF8)==0x0050) /* is s0..s7 (s0..s3 in V1) */ -#define XTENSA_DBREGN_IS_VALIGN(tn) (((tn) & 0xFFFC)==0x0058) /* is u0..u3 */ -#define XTENSA_DBREGN_IS_VCOEFF(tn) (((tn) & 0xFFFE)==0x005C) /* is c0..c1 */ -#define XTENSA_DBREGN_IS_AEP(tn) (((tn) & 0xFFF8)==0x0060) /* is aep0..aep7 */ -#define XTENSA_DBREGN_IS_AEQ(tn) (((tn) & 0xFFFC)==0x0068) /* is aeq0..aeq3 */ -#define XTENSA_DBREGN_IS_AR(tn) (((tn) & 0xFFC0)==0x0100) /* is ar0..ar63 */ -#define XTENSA_DBREGN_IS_SREG(tn) (((tn) & 0xFF00)==0x0200) /* is special register */ -#define XTENSA_DBREGN_IS_BR(tn) (((tn) & 0xFFFF)==XTENSA_DBREGN_SREG(0x04)) /* is BR */ -#define XTENSA_DBREGN_IS_MR(tn) (((tn) & 0xFFFC)==XTENSA_DBREGN_SREG(0x20)) /* m0..m3 */ -#define XTENSA_DBREGN_IS_UREG(tn) (((tn) & 0xFF00)==0x0300) /* is user register */ -#define XTENSA_DBREGN_IS_DBAGENT(tn) (((tn) & 0xF000)==0xF000) /* is non-processor */ -/*#define XTENSA_DBREGN_IS_CONTEXT(tn) (((tn) & 0x02000000) != 0)*/ /* specifies context # */ - -/* - * Macros to extract register index from a register "target number" - * when a specific range has been identified using one of the _IS_ macros above. - * These macros only return a useful value if the corresponding _IS_ macro returns true. - */ -#define XTENSA_DBREGN_A_INDEX(tn) ((tn) & 0x0F) /* 0..15 for a0..a15 */ -#define XTENSA_DBREGN_B_INDEX(tn) ((tn) & 0x0F) /* 0..15 for b0..b15 */ -#define XTENSA_DBREGN_BO_INDEX(tn) ((tn) & 0x01) /* 0..1 for bo0..bo1 */ -#define XTENSA_DBREGN_BQ_INDEX(tn) ((tn) & 0x03) /* 0..3 for bq0..bq3 */ -#define XTENSA_DBREGN_BD_INDEX(tn) ((tn) & 0x07) /* 0..7 for bd0..bd7 */ -#define XTENSA_DBREGN_F_INDEX(tn) ((tn) & 0x0F) /* 0..15 for f0..f15 */ -#define XTENSA_DBREGN_VEC_INDEX(tn) ((tn) & 0x0F) /* 0..15 for v0..v15 */ -#define XTENSA_DBREGN_VSEL_INDEX(tn) ((tn) & 0x07) /* 0..7 for s0..s7 */ -#define XTENSA_DBREGN_VALIGN_INDEX(tn) ((tn) & 0x03) /* 0..3 for u0..u3 */ -#define XTENSA_DBREGN_VCOEFF_INDEX(tn) ((tn) & 0x01) /* 0..1 for c0..c1 */ -#define XTENSA_DBREGN_AEP_INDEX(tn) ((tn) & 0x07) /* 0..7 for aep0..aep7 */ -#define XTENSA_DBREGN_AEQ_INDEX(tn) ((tn) & 0x03) /* 0..3 for aeq0..aeq3 */ -#define XTENSA_DBREGN_AR_INDEX(tn) ((tn) & 0x3F) /* 0..63 for ar0..ar63 */ -#define XTENSA_DBREGN_SREG_INDEX(tn) ((tn) & 0xFF) /* 0..255 for special registers */ -#define XTENSA_DBREGN_MR_INDEX(tn) ((tn) & 0x03) /* 0..3 for m0..m3 */ -#define XTENSA_DBREGN_UREG_INDEX(tn) ((tn) & 0xFF) /* 0..255 for user registers */ -#define XTENSA_DBREGN_DBAGENT_INDEX(tn) ((tn) & 0xFFF) /* 0..4095 for non-processor */ -/*#define XTENSA_DBREGN_CONTEXT_INDEX(tn) (((tn) >> 20) & 0x1F)*/ /* 0..31 context numbers */ - - - - -#ifdef __cplusplus -} -#endif - -#endif /* __H_LIBDB_MACROS */ - diff --git a/src/arch/xtensa/include/xtensa/xtensa-versions.h b/src/arch/xtensa/include/xtensa/xtensa-versions.h deleted file mode 100644 index 30f318eb0e6b..000000000000 --- a/src/arch/xtensa/include/xtensa/xtensa-versions.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - xtensa-versions.h -- definitions of Xtensa version and release numbers - - This file defines most Xtensa-related product versions and releases - that exist so far. - It also provides a bit of information about which ones are current. - This file changes every release, as versions/releases get added. - - - $Id: //depot/rel/Foxhill/dot.8/Xtensa/Software/misc/xtensa-versions.h.tpp#1 $ - - Copyright (c) 2006-2010 Tensilica 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. -*/ - -#ifndef XTENSA_VERSIONS_H -#define XTENSA_VERSIONS_H - - -/* - * NOTE: A "release" is a collection of product versions - * made available at once (together) to customers. - * In the past, release and version names all matched in T####.# form, - * making the distinction irrelevant. - * Starting with the RA-2004.1 release, this is no longer the case. - */ - - -/* Hardware (Xtensa/Diamond processor) versions: */ -#define XTENSA_HWVERSION_T1020_0 102000 /* versions T1020.0 */ -#define XTENSA_HWCIDSCHEME_T1020_0 10 -#define XTENSA_HWCIDVERS_T1020_0 2 -#define XTENSA_HWVERSION_T1020_1 102001 /* versions T1020.1 */ -#define XTENSA_HWCIDSCHEME_T1020_1 10 -#define XTENSA_HWCIDVERS_T1020_1 3 -#define XTENSA_HWVERSION_T1020_2 102002 /* versions T1020.2 */ -#define XTENSA_HWCIDSCHEME_T1020_2 10 -#define XTENSA_HWCIDVERS_T1020_2 4 -#define XTENSA_HWVERSION_T1020_2B 102002 /* versions T1020.2b */ -#define XTENSA_HWCIDSCHEME_T1020_2B 10 -#define XTENSA_HWCIDVERS_T1020_2B 5 -#define XTENSA_HWVERSION_T1020_3 102003 /* versions T1020.3 */ -#define XTENSA_HWCIDSCHEME_T1020_3 10 -#define XTENSA_HWCIDVERS_T1020_3 6 -#define XTENSA_HWVERSION_T1020_4 102004 /* versions T1020.4 */ -#define XTENSA_HWCIDSCHEME_T1020_4 10 -#define XTENSA_HWCIDVERS_T1020_4 7 -#define XTENSA_HWVERSION_T1030_0 103000 /* versions T1030.0 */ -#define XTENSA_HWCIDSCHEME_T1030_0 10 -#define XTENSA_HWCIDVERS_T1030_0 9 -#define XTENSA_HWVERSION_T1030_1 103001 /* versions T1030.1 */ -#define XTENSA_HWCIDSCHEME_T1030_1 10 -#define XTENSA_HWCIDVERS_T1030_1 10 -#define XTENSA_HWVERSION_T1030_2 103002 /* versions T1030.2 */ -#define XTENSA_HWCIDSCHEME_T1030_2 10 -#define XTENSA_HWCIDVERS_T1030_2 11 -#define XTENSA_HWVERSION_T1030_3 103003 /* versions T1030.3 */ -#define XTENSA_HWCIDSCHEME_T1030_3 10 -#define XTENSA_HWCIDVERS_T1030_3 12 -#define XTENSA_HWVERSION_T1040_0 104000 /* versions T1040.0 */ -#define XTENSA_HWCIDSCHEME_T1040_0 10 -#define XTENSA_HWCIDVERS_T1040_0 15 -#define XTENSA_HWVERSION_T1040_1 104001 /* versions T1040.1 */ -#define XTENSA_HWCIDSCHEME_T1040_1 01 -#define XTENSA_HWCIDVERS_T1040_1 32 -#define XTENSA_HWVERSION_T1040_1P 104001 /* versions T1040.1-prehotfix */ -#define XTENSA_HWCIDSCHEME_T1040_1P 10 -#define XTENSA_HWCIDVERS_T1040_1P 16 -#define XTENSA_HWVERSION_T1040_2 104002 /* versions T1040.2 */ -#define XTENSA_HWCIDSCHEME_T1040_2 01 -#define XTENSA_HWCIDVERS_T1040_2 33 -#define XTENSA_HWVERSION_T1040_3 104003 /* versions T1040.3 */ -#define XTENSA_HWCIDSCHEME_T1040_3 01 -#define XTENSA_HWCIDVERS_T1040_3 34 -#define XTENSA_HWVERSION_T1050_0 105000 /* versions T1050.0 */ -#define XTENSA_HWCIDSCHEME_T1050_0 1100 -#define XTENSA_HWCIDVERS_T1050_0 1 -#define XTENSA_HWVERSION_T1050_1 105001 /* versions T1050.1 */ -#define XTENSA_HWCIDSCHEME_T1050_1 1100 -#define XTENSA_HWCIDVERS_T1050_1 2 -#define XTENSA_HWVERSION_T1050_2 105002 /* versions T1050.2 */ -#define XTENSA_HWCIDSCHEME_T1050_2 1100 -#define XTENSA_HWCIDVERS_T1050_2 4 -#define XTENSA_HWVERSION_T1050_3 105003 /* versions T1050.3 */ -#define XTENSA_HWCIDSCHEME_T1050_3 1100 -#define XTENSA_HWCIDVERS_T1050_3 6 -#define XTENSA_HWVERSION_T1050_4 105004 /* versions T1050.4 */ -#define XTENSA_HWCIDSCHEME_T1050_4 1100 -#define XTENSA_HWCIDVERS_T1050_4 7 -#define XTENSA_HWVERSION_T1050_5 105005 /* versions T1050.5 */ -#define XTENSA_HWCIDSCHEME_T1050_5 1100 -#define XTENSA_HWCIDVERS_T1050_5 8 -#define XTENSA_HWVERSION_RA_2004_1 210000 /* versions LX1.0.0 */ -#define XTENSA_HWCIDSCHEME_RA_2004_1 1100 -#define XTENSA_HWCIDVERS_RA_2004_1 3 -#define XTENSA_HWVERSION_RA_2005_1 210001 /* versions LX1.0.1 */ -#define XTENSA_HWCIDSCHEME_RA_2005_1 1100 -#define XTENSA_HWCIDVERS_RA_2005_1 20 -#define XTENSA_HWVERSION_RA_2005_2 210002 /* versions LX1.0.2 */ -#define XTENSA_HWCIDSCHEME_RA_2005_2 1100 -#define XTENSA_HWCIDVERS_RA_2005_2 21 -#define XTENSA_HWVERSION_RA_2005_3 210003 /* versions LX1.0.3, X6.0.3 */ -#define XTENSA_HWCIDSCHEME_RA_2005_3 1100 -#define XTENSA_HWCIDVERS_RA_2005_3 22 -#define XTENSA_HWVERSION_RA_2006_4 210004 /* versions LX1.0.4, X6.0.4 */ -#define XTENSA_HWCIDSCHEME_RA_2006_4 1100 -#define XTENSA_HWCIDVERS_RA_2006_4 23 -#define XTENSA_HWVERSION_RA_2006_5 210005 /* versions LX1.0.5, X6.0.5 */ -#define XTENSA_HWCIDSCHEME_RA_2006_5 1100 -#define XTENSA_HWCIDVERS_RA_2006_5 24 -#define XTENSA_HWVERSION_RA_2006_6 210006 /* versions LX1.0.6, X6.0.6 */ -#define XTENSA_HWCIDSCHEME_RA_2006_6 1100 -#define XTENSA_HWCIDVERS_RA_2006_6 25 -#define XTENSA_HWVERSION_RA_2007_7 210007 /* versions LX1.0.7, X6.0.7 */ -#define XTENSA_HWCIDSCHEME_RA_2007_7 1100 -#define XTENSA_HWCIDVERS_RA_2007_7 26 -#define XTENSA_HWVERSION_RA_2008_8 210008 /* versions LX1.0.8, X6.0.8 */ -#define XTENSA_HWCIDSCHEME_RA_2008_8 1100 -#define XTENSA_HWCIDVERS_RA_2008_8 27 -#define XTENSA_HWVERSION_RB_2006_0 220000 /* versions LX2.0.0, X7.0.0 */ -#define XTENSA_HWCIDSCHEME_RB_2006_0 1100 -#define XTENSA_HWCIDVERS_RB_2006_0 48 -#define XTENSA_HWVERSION_RB_2007_1 220001 /* versions LX2.0.1, X7.0.1 */ -#define XTENSA_HWCIDSCHEME_RB_2007_1 1100 -#define XTENSA_HWCIDVERS_RB_2007_1 49 -#define XTENSA_HWVERSION_RB_2007_2 221000 /* versions LX2.1.0, X7.1.0 */ -#define XTENSA_HWCIDSCHEME_RB_2007_2 1100 -#define XTENSA_HWCIDVERS_RB_2007_2 52 -#define XTENSA_HWVERSION_RB_2008_3 221001 /* versions LX2.1.1, X7.1.1 */ -#define XTENSA_HWCIDSCHEME_RB_2008_3 1100 -#define XTENSA_HWCIDVERS_RB_2008_3 53 -#define XTENSA_HWVERSION_RB_2008_4 221002 /* versions LX2.1.2, X7.1.2 */ -#define XTENSA_HWCIDSCHEME_RB_2008_4 1100 -#define XTENSA_HWCIDVERS_RB_2008_4 54 -#define XTENSA_HWVERSION_RB_2009_5 221003 /* versions LX2.1.3, X7.1.3 */ -#define XTENSA_HWCIDSCHEME_RB_2009_5 1100 -#define XTENSA_HWCIDVERS_RB_2009_5 55 -#define XTENSA_HWVERSION_RB_2007_2_MP 221100 /* versions LX2.1.8-MP, X7.1.8-MP */ -#define XTENSA_HWCIDSCHEME_RB_2007_2_MP 1100 -#define XTENSA_HWCIDVERS_RB_2007_2_MP 64 -#define XTENSA_HWVERSION_RC_2009_0 230000 /* versions LX3.0.0, X8.0.0, MX1.0.0 */ -#define XTENSA_HWCIDSCHEME_RC_2009_0 1100 -#define XTENSA_HWCIDVERS_RC_2009_0 65 -#define XTENSA_HWVERSION_RC_2010_1 230001 /* versions LX3.0.1, X8.0.1, MX1.0.1 */ -#define XTENSA_HWCIDSCHEME_RC_2010_1 1100 -#define XTENSA_HWCIDVERS_RC_2010_1 66 -#define XTENSA_HWVERSION_RC_2010_2 230002 /* versions LX3.0.2, X8.0.2, MX1.0.2 */ -#define XTENSA_HWCIDSCHEME_RC_2010_2 1100 -#define XTENSA_HWCIDVERS_RC_2010_2 67 -#define XTENSA_HWVERSION_RC_2011_3 230003 /* versions LX3.0.3, X8.0.3, MX1.0.3 */ -#define XTENSA_HWCIDSCHEME_RC_2011_3 1100 -#define XTENSA_HWCIDVERS_RC_2011_3 68 -#define XTENSA_HWVERSION_RD_2010_0 240000 /* versions LX4.0.0, X9.0.0, MX1.1.0, TX1.0.0 */ -#define XTENSA_HWCIDSCHEME_RD_2010_0 1100 -#define XTENSA_HWCIDVERS_RD_2010_0 80 -#define XTENSA_HWVERSION_RD_2011_1 240001 /* versions LX4.0.1, X9.0.1, MX1.1.1, TX1.0.1 */ -#define XTENSA_HWCIDSCHEME_RD_2011_1 1100 -#define XTENSA_HWCIDVERS_RD_2011_1 81 -#define XTENSA_HWVERSION_RD_2011_2 240002 /* versions LX4.0.2, X9.0.2, MX1.1.2, TX1.0.2 */ -#define XTENSA_HWCIDSCHEME_RD_2011_2 1100 -#define XTENSA_HWCIDVERS_RD_2011_2 82 -#define XTENSA_HWVERSION_RD_2011_3 240003 /* versions LX4.0.3, X9.0.3, MX1.1.3, TX1.0.3 */ -#define XTENSA_HWCIDSCHEME_RD_2011_3 1100 -#define XTENSA_HWCIDVERS_RD_2011_3 83 -#define XTENSA_HWVERSION_RD_2012_4 240004 /* versions LX4.0.4, X9.0.4, MX1.1.4, TX1.0.4 */ -#define XTENSA_HWCIDSCHEME_RD_2012_4 1100 -#define XTENSA_HWCIDVERS_RD_2012_4 84 -#define XTENSA_HWVERSION_RD_2012_5 240005 /* versions LX4.0.5, X9.0.5, MX1.1.5, TX1.0.5 */ -#define XTENSA_HWCIDSCHEME_RD_2012_5 1100 -#define XTENSA_HWCIDVERS_RD_2012_5 85 -#define XTENSA_HWVERSION_RE_2012_0 250000 /* versions LX5.0.0, X10.0.0, MX1.2.0 */ -#define XTENSA_HWCIDSCHEME_RE_2012_0 1100 -#define XTENSA_HWCIDVERS_RE_2012_0 96 -#define XTENSA_HWVERSION_RE_2012_1 250001 /* versions LX5.0.1, X10.0.1, MX1.2.1 */ -#define XTENSA_HWCIDSCHEME_RE_2012_1 1100 -#define XTENSA_HWCIDVERS_RE_2012_1 97 -#define XTENSA_HWVERSION_RE_2013_2 250002 /* versions LX5.0.2, X10.0.2, MX1.2.2 */ -#define XTENSA_HWCIDSCHEME_RE_2013_2 1100 -#define XTENSA_HWCIDVERS_RE_2013_2 98 -#define XTENSA_HWVERSION_RE_2013_3 250003 /* versions LX5.0.3, X10.0.3, MX1.2.3 */ -#define XTENSA_HWCIDSCHEME_RE_2013_3 1100 -#define XTENSA_HWCIDVERS_RE_2013_3 99 -#define XTENSA_HWVERSION_RE_2013_4 250004 /* versions LX5.0.4, X10.0.4, MX1.2.4 */ -#define XTENSA_HWCIDSCHEME_RE_2013_4 1100 -#define XTENSA_HWCIDVERS_RE_2013_4 100 -#define XTENSA_HWVERSION_RE_2014_5 250005 /* versions LX5.0.5, X10.0.5, MX1.2.5 */ -#define XTENSA_HWCIDSCHEME_RE_2014_5 1100 -#define XTENSA_HWCIDVERS_RE_2014_5 101 -#define XTENSA_HWVERSION_RE_2015_6 250006 /* versions LX5.0.6, X10.0.6, MX1.2.6 */ -#define XTENSA_HWCIDSCHEME_RE_2015_6 1100 -#define XTENSA_HWCIDVERS_RE_2015_6 102 -#define XTENSA_HWVERSION_RF_2014_0 260000 /* versions LX6.0.0, X11.0.0, MX1.3.0 */ -#define XTENSA_HWCIDSCHEME_RF_2014_0 1100 -#define XTENSA_HWCIDVERS_RF_2014_0 112 -#define XTENSA_HWVERSION_RF_2014_1 260001 /* versions LX6.0.1, X11.0.1 */ -#define XTENSA_HWCIDSCHEME_RF_2014_1 1100 -#define XTENSA_HWCIDVERS_RF_2014_1 113 -#define XTENSA_HWVERSION_RF_2015_2 260002 /* versions LX6.0.2, X11.0.2 */ -#define XTENSA_HWCIDSCHEME_RF_2015_2 1100 -#define XTENSA_HWCIDVERS_RF_2015_2 114 -#define XTENSA_HWVERSION_RF_2015_3 260003 /* versions LX6.0.3, X11.0.3 */ -#define XTENSA_HWCIDSCHEME_RF_2015_3 1100 -#define XTENSA_HWCIDVERS_RF_2015_3 115 -#define XTENSA_HWVERSION_RF_2016_4 260004 /* versions LX6.0.4, X11.0.4 */ -#define XTENSA_HWCIDSCHEME_RF_2016_4 1100 -#define XTENSA_HWCIDVERS_RF_2016_4 116 -#define XTENSA_HWVERSION_RG_2015_0 270000 /* versions LX7.0.0 */ -#define XTENSA_HWCIDSCHEME_RG_2015_0 1100 -#define XTENSA_HWCIDVERS_RG_2015_0 128 -#define XTENSA_HWVERSION_RG_2015_1 270001 /* versions LX7.0.1 */ -#define XTENSA_HWCIDSCHEME_RG_2015_1 1100 -#define XTENSA_HWCIDVERS_RG_2015_1 129 -#define XTENSA_HWVERSION_RG_2015_2 270002 /* versions LX7.0.2 */ -#define XTENSA_HWCIDSCHEME_RG_2015_2 1100 -#define XTENSA_HWCIDVERS_RG_2015_2 130 -#define XTENSA_HWVERSION_RG_2016_3 270003 /* versions LX7.0.3 */ -#define XTENSA_HWCIDSCHEME_RG_2016_3 1100 -#define XTENSA_HWCIDVERS_RG_2016_3 131 -#define XTENSA_HWVERSION_RG_2016_4 270004 /* versions LX7.0.4 */ -#define XTENSA_HWCIDSCHEME_RG_2016_4 1100 -#define XTENSA_HWCIDVERS_RG_2016_4 132 -#define XTENSA_HWVERSION_RG_2017_5 270005 /* versions LX7.0.5 */ -#define XTENSA_HWCIDSCHEME_RG_2017_5 1100 -#define XTENSA_HWCIDVERS_RG_2017_5 133 -#define XTENSA_HWVERSION_RG_2017_6 270006 /* versions LX7.0.6 */ -#define XTENSA_HWCIDSCHEME_RG_2017_6 1100 -#define XTENSA_HWCIDVERS_RG_2017_6 134 -#define XTENSA_HWVERSION_RG_2017_7 270007 /* versions LX7.0.7 */ -#define XTENSA_HWCIDSCHEME_RG_2017_7 1100 -#define XTENSA_HWCIDVERS_RG_2017_7 135 -#define XTENSA_HWVERSION_RG_2017_8 270008 /* versions LX7.0.8 */ -#define XTENSA_HWCIDSCHEME_RG_2017_8 1100 -#define XTENSA_HWCIDVERS_RG_2017_8 136 -#define XTENSA_HWVERSION_RH_2016_0 280000 /* versions LX8.0.0, NX1.0.0, SX1.0.0 */ -#define XTENSA_HWCIDSCHEME_RH_2016_0 1100 -#define XTENSA_HWCIDVERS_RH_2016_0 144 - -/* Software (Xtensa Tools) versions: */ -#define XTENSA_SWVERSION_T1020_0 102000 /* versions T1020.0 */ -#define XTENSA_SWVERSION_T1020_1 102001 /* versions T1020.1 */ -#define XTENSA_SWVERSION_T1020_2 102002 /* versions T1020.2 */ -#define XTENSA_SWVERSION_T1020_2B 102002 /* versions T1020.2b */ -#define XTENSA_SWVERSION_T1020_3 102003 /* versions T1020.3 */ -#define XTENSA_SWVERSION_T1020_4 102004 /* versions T1020.4 */ -#define XTENSA_SWVERSION_T1030_0 103000 /* versions T1030.0 */ -#define XTENSA_SWVERSION_T1030_1 103001 /* versions T1030.1 */ -#define XTENSA_SWVERSION_T1030_2 103002 /* versions T1030.2 */ -#define XTENSA_SWVERSION_T1030_3 103003 /* versions T1030.3 */ -#define XTENSA_SWVERSION_T1040_0 104000 /* versions T1040.0 */ -#define XTENSA_SWVERSION_T1040_1 104001 /* versions T1040.1 */ -#define XTENSA_SWVERSION_T1040_1P 104001 /* versions T1040.1-prehotfix */ -#define XTENSA_SWVERSION_T1040_2 104002 /* versions T1040.2 */ -#define XTENSA_SWVERSION_T1040_3 104003 /* versions T1040.3 */ -#define XTENSA_SWVERSION_T1050_0 105000 /* versions T1050.0 */ -#define XTENSA_SWVERSION_T1050_1 105001 /* versions T1050.1 */ -#define XTENSA_SWVERSION_T1050_2 105002 /* versions T1050.2 */ -#define XTENSA_SWVERSION_T1050_3 105003 /* versions T1050.3 */ -#define XTENSA_SWVERSION_T1050_4 105004 /* versions T1050.4 */ -#define XTENSA_SWVERSION_T1050_5 105005 /* versions T1050.5 */ -#define XTENSA_SWVERSION_RA_2004_1 600000 /* versions 6.0.0 */ -#define XTENSA_SWVERSION_RA_2005_1 600001 /* versions 6.0.1 */ -#define XTENSA_SWVERSION_RA_2005_2 600002 /* versions 6.0.2 */ -#define XTENSA_SWVERSION_RA_2005_3 600003 /* versions 6.0.3 */ -#define XTENSA_SWVERSION_RA_2006_4 600004 /* versions 6.0.4 */ -#define XTENSA_SWVERSION_RA_2006_5 600005 /* versions 6.0.5 */ -#define XTENSA_SWVERSION_RA_2006_6 600006 /* versions 6.0.6 */ -#define XTENSA_SWVERSION_RA_2007_7 600007 /* versions 6.0.7 */ -#define XTENSA_SWVERSION_RA_2008_8 600008 /* versions 6.0.8 */ -#define XTENSA_SWVERSION_RB_2006_0 700000 /* versions 7.0.0 */ -#define XTENSA_SWVERSION_RB_2007_1 700001 /* versions 7.0.1 */ -#define XTENSA_SWVERSION_RB_2007_2 701000 /* versions 7.1.0 */ -#define XTENSA_SWVERSION_RB_2008_3 701001 /* versions 7.1.1 */ -#define XTENSA_SWVERSION_RB_2008_4 701002 /* versions 7.1.2 */ -#define XTENSA_SWVERSION_RB_2009_5 701003 /* versions 7.1.3 */ -#define XTENSA_SWVERSION_RB_2007_2_MP 701100 /* versions 7.1.8-MP */ -#define XTENSA_SWVERSION_RC_2009_0 800000 /* versions 8.0.0 */ -#define XTENSA_SWVERSION_RC_2010_1 800001 /* versions 8.0.1 */ -#define XTENSA_SWVERSION_RC_2010_2 800002 /* versions 8.0.2 */ -#define XTENSA_SWVERSION_RC_2011_3 800003 /* versions 8.0.3 */ -#define XTENSA_SWVERSION_RD_2010_0 900000 /* versions 9.0.0 */ -#define XTENSA_SWVERSION_RD_2011_1 900001 /* versions 9.0.1 */ -#define XTENSA_SWVERSION_RD_2011_2 900002 /* versions 9.0.2 */ -#define XTENSA_SWVERSION_RD_2011_3 900003 /* versions 9.0.3 */ -#define XTENSA_SWVERSION_RD_2012_4 900004 /* versions 9.0.4 */ -#define XTENSA_SWVERSION_RD_2012_5 900005 /* versions 9.0.5 */ -#define XTENSA_SWVERSION_RE_2012_0 1000000 /* versions 10.0.0 */ -#define XTENSA_SWVERSION_RE_2012_1 1000001 /* versions 10.0.1 */ -#define XTENSA_SWVERSION_RE_2013_2 1000002 /* versions 10.0.2 */ -#define XTENSA_SWVERSION_RE_2013_3 1000003 /* versions 10.0.3 */ -#define XTENSA_SWVERSION_RE_2013_4 1000004 /* versions 10.0.4 */ -#define XTENSA_SWVERSION_RE_2014_5 1000005 /* versions 10.0.5 */ -#define XTENSA_SWVERSION_RE_2015_6 1000006 /* versions 10.0.6 */ -#define XTENSA_SWVERSION_RF_2014_0 1100000 /* versions 11.0.0 */ -#define XTENSA_SWVERSION_RF_2014_1 1100001 /* versions 11.0.1 */ -#define XTENSA_SWVERSION_RF_2015_2 1100002 /* versions 11.0.2 */ -#define XTENSA_SWVERSION_RF_2015_3 1100003 /* versions 11.0.3 */ -#define XTENSA_SWVERSION_RF_2016_4 1100004 /* versions 11.0.4 */ -#define XTENSA_SWVERSION_RG_2015_0 1200000 /* versions 12.0.0 */ -#define XTENSA_SWVERSION_RG_2015_1 1200001 /* versions 12.0.1 */ -#define XTENSA_SWVERSION_RG_2015_2 1200002 /* versions 12.0.2 */ -#define XTENSA_SWVERSION_RG_2016_3 1200003 /* versions 12.0.3 */ -#define XTENSA_SWVERSION_RG_2016_4 1200004 /* versions 12.0.4 */ -#define XTENSA_SWVERSION_RG_2017_5 1200005 /* versions 12.0.5 */ -#define XTENSA_SWVERSION_RG_2017_6 1200006 /* versions 12.0.6 */ -#define XTENSA_SWVERSION_RG_2017_7 1200007 /* versions 12.0.7 */ -#define XTENSA_SWVERSION_RG_2017_8 1200008 /* versions 12.0.8 */ -#define XTENSA_SWVERSION_RH_2016_0 1300000 /* versions 13.0.0 */ -#define XTENSA_SWVERSION_T1040_1_PREHOTFIX XTENSA_SWVERSION_T1040_1P /* T1040.1-prehotfix */ -#define XTENSA_SWVERSION_6_0_0 XTENSA_SWVERSION_RA_2004_1 /* 6.0.0 */ -#define XTENSA_SWVERSION_6_0_1 XTENSA_SWVERSION_RA_2005_1 /* 6.0.1 */ -#define XTENSA_SWVERSION_6_0_2 XTENSA_SWVERSION_RA_2005_2 /* 6.0.2 */ -#define XTENSA_SWVERSION_6_0_3 XTENSA_SWVERSION_RA_2005_3 /* 6.0.3 */ -#define XTENSA_SWVERSION_6_0_4 XTENSA_SWVERSION_RA_2006_4 /* 6.0.4 */ -#define XTENSA_SWVERSION_6_0_5 XTENSA_SWVERSION_RA_2006_5 /* 6.0.5 */ -#define XTENSA_SWVERSION_6_0_6 XTENSA_SWVERSION_RA_2006_6 /* 6.0.6 */ -#define XTENSA_SWVERSION_6_0_7 XTENSA_SWVERSION_RA_2007_7 /* 6.0.7 */ -#define XTENSA_SWVERSION_6_0_8 XTENSA_SWVERSION_RA_2008_8 /* 6.0.8 */ -#define XTENSA_SWVERSION_7_0_0 XTENSA_SWVERSION_RB_2006_0 /* 7.0.0 */ -#define XTENSA_SWVERSION_7_0_1 XTENSA_SWVERSION_RB_2007_1 /* 7.0.1 */ -#define XTENSA_SWVERSION_7_1_0 XTENSA_SWVERSION_RB_2007_2 /* 7.1.0 */ -#define XTENSA_SWVERSION_7_1_1 XTENSA_SWVERSION_RB_2008_3 /* 7.1.1 */ -#define XTENSA_SWVERSION_7_1_2 XTENSA_SWVERSION_RB_2008_4 /* 7.1.2 */ -#define XTENSA_SWVERSION_7_1_3 XTENSA_SWVERSION_RB_2009_5 /* 7.1.3 */ -#define XTENSA_SWVERSION_7_1_8_MP XTENSA_SWVERSION_RB_2007_2_MP /* 7.1.8-MP */ -#define XTENSA_SWVERSION_8_0_0 XTENSA_SWVERSION_RC_2009_0 /* 8.0.0 */ -#define XTENSA_SWVERSION_8_0_1 XTENSA_SWVERSION_RC_2010_1 /* 8.0.1 */ -#define XTENSA_SWVERSION_8_0_2 XTENSA_SWVERSION_RC_2010_2 /* 8.0.2 */ -#define XTENSA_SWVERSION_8_0_3 XTENSA_SWVERSION_RC_2011_3 /* 8.0.3 */ -#define XTENSA_SWVERSION_9_0_0 XTENSA_SWVERSION_RD_2010_0 /* 9.0.0 */ -#define XTENSA_SWVERSION_9_0_1 XTENSA_SWVERSION_RD_2011_1 /* 9.0.1 */ -#define XTENSA_SWVERSION_9_0_2 XTENSA_SWVERSION_RD_2011_2 /* 9.0.2 */ -#define XTENSA_SWVERSION_9_0_3 XTENSA_SWVERSION_RD_2011_3 /* 9.0.3 */ -#define XTENSA_SWVERSION_9_0_4 XTENSA_SWVERSION_RD_2012_4 /* 9.0.4 */ -#define XTENSA_SWVERSION_9_0_5 XTENSA_SWVERSION_RD_2012_5 /* 9.0.5 */ -#define XTENSA_SWVERSION_10_0_0 XTENSA_SWVERSION_RE_2012_0 /* 10.0.0 */ -#define XTENSA_SWVERSION_10_0_1 XTENSA_SWVERSION_RE_2012_1 /* 10.0.1 */ -#define XTENSA_SWVERSION_10_0_2 XTENSA_SWVERSION_RE_2013_2 /* 10.0.2 */ -#define XTENSA_SWVERSION_10_0_3 XTENSA_SWVERSION_RE_2013_3 /* 10.0.3 */ -#define XTENSA_SWVERSION_10_0_4 XTENSA_SWVERSION_RE_2013_4 /* 10.0.4 */ -#define XTENSA_SWVERSION_10_0_5 XTENSA_SWVERSION_RE_2014_5 /* 10.0.5 */ -#define XTENSA_SWVERSION_10_0_6 XTENSA_SWVERSION_RE_2015_6 /* 10.0.6 */ -#define XTENSA_SWVERSION_11_0_0 XTENSA_SWVERSION_RF_2014_0 /* 11.0.0 */ -#define XTENSA_SWVERSION_11_0_1 XTENSA_SWVERSION_RF_2014_1 /* 11.0.1 */ -#define XTENSA_SWVERSION_11_0_2 XTENSA_SWVERSION_RF_2015_2 /* 11.0.2 */ -#define XTENSA_SWVERSION_11_0_3 XTENSA_SWVERSION_RF_2015_3 /* 11.0.3 */ -#define XTENSA_SWVERSION_11_0_4 XTENSA_SWVERSION_RF_2016_4 /* 11.0.4 */ -#define XTENSA_SWVERSION_12_0_0 XTENSA_SWVERSION_RG_2015_0 /* 12.0.0 */ -#define XTENSA_SWVERSION_12_0_1 XTENSA_SWVERSION_RG_2015_1 /* 12.0.1 */ -#define XTENSA_SWVERSION_12_0_2 XTENSA_SWVERSION_RG_2015_2 /* 12.0.2 */ -#define XTENSA_SWVERSION_12_0_3 XTENSA_SWVERSION_RG_2016_3 /* 12.0.3 */ -#define XTENSA_SWVERSION_12_0_4 XTENSA_SWVERSION_RG_2016_4 /* 12.0.4 */ -#define XTENSA_SWVERSION_12_0_5 XTENSA_SWVERSION_RG_2017_5 /* 12.0.5 */ -#define XTENSA_SWVERSION_12_0_6 XTENSA_SWVERSION_RG_2017_6 /* 12.0.6 */ -#define XTENSA_SWVERSION_12_0_7 XTENSA_SWVERSION_RG_2017_7 /* 12.0.7 */ -#define XTENSA_SWVERSION_12_0_8 XTENSA_SWVERSION_RG_2017_8 /* 12.0.8 */ -#define XTENSA_SWVERSION_13_0_0 XTENSA_SWVERSION_RH_2016_0 /* 13.0.0 */ - - -/* The current release: */ -#define XTENSA_RELEASE_NAME "RG-2017.8" -#define XTENSA_RELEASE_CANONICAL_NAME "RG-2017.8" - -/* The product versions within the current release: */ -#define XTENSA_SWVERSION XTENSA_SWVERSION_RG_2017_8 -#define XTENSA_SWVERSION_NAME "12.0.8" -#define XTENSA_SWVERSION_NAME_IDENT 12_0_8 -#define XTENSA_SWVERSION_CANONICAL_NAME "12.0.8" -#define XTENSA_SWVERSION_MAJORMID_NAME "12.0" -#define XTENSA_SWVERSION_MAJOR_NAME "12" -/* For product licensing (not necessarily same as *_MAJORMID_NAME): */ -#define XTENSA_SWVERSION_LICENSE_NAME "12.0" - -/* Note: there may be multiple hardware products in one release, - and software can target older hardware, so the notion of - "current" hardware versions is partially configuration dependent. - For now, "current" hardware product version info is left out - to avoid confusion. */ - -#endif /*XTENSA_VERSIONS_H*/ - diff --git a/src/arch/xtensa/include/xtensa/xtensa-xer.h b/src/arch/xtensa/include/xtensa/xtensa-xer.h deleted file mode 100644 index 900bda333843..000000000000 --- a/src/arch/xtensa/include/xtensa/xtensa-xer.h +++ /dev/null @@ -1,149 +0,0 @@ -/* xer-constants.h -- various constants describing external registers accessed - via wer and rer. - - TODO: find a better prefix. Also conditionalize certain constants based - on number of cores and interrupts actually present. -*/ - -/* - * Copyright (c) 1999-2008 Tensilica 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 <xtensa/config/core.h> - -#define NUM_INTERRUPTS 27 -#define NUM_CORES 4 - -/* Routing of NMI (BInterrupt2) and interrupts 0..n-1 (BInterrupt3+) - RER reads - WER writes - */ - -#define XER_MIROUT 0x0000 -#define XER_MIROUT_LAST (XER_MIROUT + NUM_INTERRUPTS) - - -/* IPI to core M (all 16 causes). - - RER reads - WER clears - */ -#define XER_MIPICAUSE 0x0100 -#define XER_MIPICAUSE_FIELD_A_FIRST 0x0 -#define XER_MIPICAUSE_FIELD_A_LAST 0x0 -#define XER_MIPICAUSE_FIELD_B_FIRST 0x1 -#define XER_MIPICAUSE_FIELD_B_LAST 0x3 -#define XER_MIPICAUSE_FIELD_C_FIRST 0x4 -#define XER_MIPICAUSE_FIELD_C_LAST 0x7 -#define XER_MIPICAUSE_FIELD_D_FIRST 0x8 -#define XER_MIPICAUSE_FIELD_D_LAST 0xF - - -/* IPI from cause bit 0..15 - - RER invalid - WER sets -*/ -#define XER_MIPISET 0x0140 -#define XER_MIPISET_LAST 0x014F - - -/* Global enable - - RER read - WER clear -*/ -#define XER_MIENG 0x0180 - - -/* Global enable - - RER invalid - WER set -*/ -#define XER_MIENG_SET 0x0184 - -/* Global assert - - RER read - WER clear -*/ -#define XER_MIASG 0x0188 - - -/* Global enable - - RER invalid - WER set -*/ -#define XER_MIASG_SET 0x018C - - -/* IPI partition register - - RER read - WER write -*/ -#define XER_PART 0x0190 -#define XER_IPI0 0x0 -#define XER_IPI1 0x1 -#define XER_IPI2 0x2 -#define XER_IPI3 0x3 - -#define XER_PART_ROUTE_IPI(NUM, FIELD) ((NUM) << ((FIELD) << 2)) - -#define XER_PART_ROUTE_IPI_CAUSE(TO_A, TO_B, TO_C, TO_D) \ - (XER_PART_ROUTE_IPI(TO_A, XER_IPI0) | \ - XER_PART_ROUTE_IPI(TO_B, XER_IPI1) | \ - XER_PART_ROUTE_IPI(TO_C, XER_IPI2) | \ - XER_PART_ROUTE_IPI(TO_D, XER_IPI3)) - -#define XER_IPI_WAKE_EXT_INTERRUPT XCHAL_EXTINT0_NUM -#define XER_IPI_WAKE_CAUSE XER_MIPICAUSE_FIELD_C_FIRST -#define XER_IPI_WAKE_ADDRESS (XER_MIPISET + XER_IPI_WAKE_CAUSE) -#define XER_DEFAULT_IPI_ROUTING XER_PART_ROUTE_IPI_CAUSE(XER_IPI1, XER_IPI0, XER_IPI2, XER_IPI3) - - -/* System configuration ID - - RER read - WER invalid -*/ -#define XER_SYSCFGID 0x01A0 - - -/* RunStall to slave processors - - RER read - WER write -*/ -#define XER_MPSCORE 0x0200 - - -/* Cache coherency ON - - RER read - WER write -*/ -#define XER_CCON 0x0220 - - diff --git a/src/arch/xtensa/include/xtensa/xtruntime-core-state.h b/src/arch/xtensa/include/xtensa/xtruntime-core-state.h deleted file mode 100644 index 94cc719af822..000000000000 --- a/src/arch/xtensa/include/xtensa/xtruntime-core-state.h +++ /dev/null @@ -1,240 +0,0 @@ -/* xtruntime-core-state.h - core state save area (used eg. by PSO) */ -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/include/xtensa/xtruntime-core-state.h#1 $ */ - -/* - * Copyright (c) 2012-2013 Tensilica 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. - */ - -#ifndef _XTOS_CORE_STATE_H_ -#define _XTOS_CORE_STATE_H_ - -/* Import STRUCT_xxx macros for defining structures: */ -#include <xtensa/xtruntime-frames.h> -#include <xtensa/config/core.h> -#include <xtensa/config/tie.h> -#if XCHAL_HAVE_IDMA -#include <xtensa/idma.h> -#endif - -//#define XTOS_PSO_TEST 1 // uncommented for internal PSO testing only - -#define CORE_STATE_SIGNATURE 0xB1C5AFED // pattern that indicates state was saved - - -/* - * Save area for saving entire core state, such as across Power Shut-Off (PSO). - */ - -STRUCT_BEGIN -STRUCT_FIELD (long,4,CS_SA_,signature) // for checking whether state was saved -STRUCT_FIELD (long,4,CS_SA_,restore_label) -STRUCT_FIELD (long,4,CS_SA_,aftersave_label) -STRUCT_AFIELD(long,4,CS_SA_,areg,XCHAL_NUM_AREGS) -#if XCHAL_HAVE_WINDOWED -STRUCT_AFIELD(long,4,CS_SA_,caller_regs,16) // save a max of 16 caller regs -STRUCT_FIELD (long,4,CS_SA_,caller_regs_saved) // flag to show if caller regs saved -#endif -#if XCHAL_HAVE_PSO_CDM -STRUCT_FIELD (long,4,CS_SA_,pwrctl) -#endif -#if XCHAL_HAVE_WINDOWED -STRUCT_FIELD (long,4,CS_SA_,windowbase) -STRUCT_FIELD (long,4,CS_SA_,windowstart) -#endif -STRUCT_FIELD (long,4,CS_SA_,sar) -#if XCHAL_HAVE_EXCEPTIONS -STRUCT_FIELD (long,4,CS_SA_,epc1) -STRUCT_FIELD (long,4,CS_SA_,ps) -STRUCT_FIELD (long,4,CS_SA_,excsave1) -# ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR -STRUCT_FIELD (long,4,CS_SA_,depc) -# endif -#endif -#if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI >= 2 -STRUCT_AFIELD(long,4,CS_SA_,epc, XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI - 1) -STRUCT_AFIELD(long,4,CS_SA_,eps, XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI - 1) -STRUCT_AFIELD(long,4,CS_SA_,excsave,XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI - 1) -#endif -#if XCHAL_HAVE_LOOPS -STRUCT_FIELD (long,4,CS_SA_,lcount) -STRUCT_FIELD (long,4,CS_SA_,lbeg) -STRUCT_FIELD (long,4,CS_SA_,lend) -#endif -#if XCHAL_HAVE_ABSOLUTE_LITERALS -STRUCT_FIELD (long,4,CS_SA_,litbase) -#endif -#if XCHAL_HAVE_VECBASE -STRUCT_FIELD (long,4,CS_SA_,vecbase) -#endif -#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) /* have ATOMCTL ? */ -STRUCT_FIELD (long,4,CS_SA_,atomctl) -#endif -#if XCHAL_HAVE_PREFETCH -STRUCT_FIELD (long,4,CS_SA_,prefctl) -#endif -#if XCHAL_USE_MEMCTL -STRUCT_FIELD (long,4,CS_SA_,memctl) -#endif -#if XCHAL_HAVE_CCOUNT -STRUCT_FIELD (long,4,CS_SA_,ccount) -STRUCT_AFIELD(long,4,CS_SA_,ccompare, XCHAL_NUM_TIMERS) -#endif -#if XCHAL_HAVE_INTERRUPTS -STRUCT_FIELD (long,4,CS_SA_,intenable) -STRUCT_FIELD (long,4,CS_SA_,interrupt) -#endif -#if XCHAL_HAVE_DEBUG -STRUCT_FIELD (long,4,CS_SA_,icount) -STRUCT_FIELD (long,4,CS_SA_,icountlevel) -STRUCT_FIELD (long,4,CS_SA_,debugcause) -// DDR not saved -# if XCHAL_NUM_DBREAK -STRUCT_AFIELD(long,4,CS_SA_,dbreakc, XCHAL_NUM_DBREAK) -STRUCT_AFIELD(long,4,CS_SA_,dbreaka, XCHAL_NUM_DBREAK) -# endif -# if XCHAL_NUM_IBREAK -STRUCT_AFIELD(long,4,CS_SA_,ibreaka, XCHAL_NUM_IBREAK) -STRUCT_FIELD (long,4,CS_SA_,ibreakenable) -# endif -#endif -#if XCHAL_NUM_MISC_REGS -STRUCT_AFIELD(long,4,CS_SA_,misc,XCHAL_NUM_MISC_REGS) -#endif -#if XCHAL_HAVE_MEM_ECC_PARITY -STRUCT_FIELD (long,4,CS_SA_,mepc) -STRUCT_FIELD (long,4,CS_SA_,meps) -STRUCT_FIELD (long,4,CS_SA_,mesave) -STRUCT_FIELD (long,4,CS_SA_,mesr) -STRUCT_FIELD (long,4,CS_SA_,mecr) -STRUCT_FIELD (long,4,CS_SA_,mevaddr) -#endif - -/* We put this ahead of TLB and other TIE state, - to keep it within S32I/L32I offset range. */ -#if XCHAL_HAVE_CP -STRUCT_FIELD (long,4,CS_SA_,cpenable) -#endif - -/* TLB state */ -#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR -STRUCT_AFIELD(long,4,CS_SA_,tlbs,8*2) -#endif -#if XCHAL_HAVE_PTP_MMU -/* Compute number of auto-refill (ARF) entries as max of I and D, - to simplify TLB save logic. On the unusual configs with - ITLB ARF != DTLB ARF entries, we'll just end up - saving/restoring some extra entries redundantly. */ -# if XCHAL_DTLB_ARF_ENTRIES_LOG2 + XCHAL_ITLB_ARF_ENTRIES_LOG2 > 4 -# define ARF_ENTRIES 8 -# else -# define ARF_ENTRIES 4 -# endif -STRUCT_FIELD (long,4,CS_SA_,ptevaddr) -STRUCT_FIELD (long,4,CS_SA_,rasid) -STRUCT_FIELD (long,4,CS_SA_,dtlbcfg) -STRUCT_FIELD (long,4,CS_SA_,itlbcfg) -/*** WARNING: past this point, field offsets may be larger than S32I/L32I range ***/ -STRUCT_AFIELD(long,4,CS_SA_,tlbs,((4*ARF_ENTRIES+4)*2+3)*2) -# if XCHAL_HAVE_SPANNING_WAY /* MMU v3 */ -STRUCT_AFIELD(long,4,CS_SA_,tlbs_ways56,(4+8)*2*2) -# endif -#endif -/* MPU state */ -#if XCHAL_HAVE_MPU -STRUCT_AFIELD(long,4,CS_SA_,mpuentry,8*XCHAL_MPU_ENTRIES) -STRUCT_FIELD (long,4,CS_SA_,cacheadrdis) -#endif - -#if XCHAL_HAVE_IDMA -STRUCT_AFIELD(long,4,CS_SA_,idmaregs, IDMA_PSO_SAVE_SIZE) -#endif - -/* TIE state */ -/* NOTE: NCP area is aligned to XCHAL_TOTAL_SA_ALIGN not XCHAL_NCP_SA_ALIGN, - because the offsets of all subsequent coprocessor save areas are relative - to the NCP save area. */ -STRUCT_AFIELD_A(char,1,XCHAL_TOTAL_SA_ALIGN,CS_SA_,ncp,XCHAL_NCP_SA_SIZE) -#if XCHAL_HAVE_CP -#if XCHAL_CP0_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP0_SA_ALIGN,CS_SA_,cp0,XCHAL_CP0_SA_SIZE) -#endif -#if XCHAL_CP1_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP1_SA_ALIGN,CS_SA_,cp1,XCHAL_CP1_SA_SIZE) -#endif -#if XCHAL_CP2_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP2_SA_ALIGN,CS_SA_,cp2,XCHAL_CP2_SA_SIZE) -#endif -#if XCHAL_CP3_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP3_SA_ALIGN,CS_SA_,cp3,XCHAL_CP3_SA_SIZE) -#endif -#if XCHAL_CP4_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP4_SA_ALIGN,CS_SA_,cp4,XCHAL_CP4_SA_SIZE) -#endif -#if XCHAL_CP5_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP5_SA_ALIGN,CS_SA_,cp5,XCHAL_CP5_SA_SIZE) -#endif -#if XCHAL_CP6_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP6_SA_ALIGN,CS_SA_,cp6,XCHAL_CP6_SA_SIZE) -#endif -#if XCHAL_CP7_SA_SIZE > 0 -STRUCT_AFIELD_A(char,1,XCHAL_CP7_SA_ALIGN,CS_SA_,cp7,XCHAL_CP7_SA_SIZE) -#endif -//STRUCT_AFIELD_A(char,1,XCHAL_CP8_SA_ALIGN,CS_SA_,cp8,XCHAL_CP8_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP9_SA_ALIGN,CS_SA_,cp9,XCHAL_CP9_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP10_SA_ALIGN,CS_SA_,cp10,XCHAL_CP10_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP11_SA_ALIGN,CS_SA_,cp11,XCHAL_CP11_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP12_SA_ALIGN,CS_SA_,cp12,XCHAL_CP12_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP13_SA_ALIGN,CS_SA_,cp13,XCHAL_CP13_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP14_SA_ALIGN,CS_SA_,cp14,XCHAL_CP14_SA_SIZE) -//STRUCT_AFIELD_A(char,1,XCHAL_CP15_SA_ALIGN,CS_SA_,cp15,XCHAL_CP15_SA_SIZE) -#endif - -STRUCT_END(XtosCoreState) - - - -// These are part of non-coprocessor state (ncp): -#if XCHAL_HAVE_MAC16 -//STRUCT_FIELD (long,4,CS_SA_,acclo) -//STRUCT_FIELD (long,4,CS_SA_,acchi) -//STRUCT_AFIELD(long,4,CS_SA_,mr, 4) -#endif -#if XCHAL_HAVE_THREADPTR -//STRUCT_FIELD (long,4,CS_SA_,threadptr) -#endif -#if XCHAL_HAVE_S32C1I -//STRUCT_FIELD (long,4,CS_SA_,scompare1) -#endif -#if XCHAL_HAVE_BOOLEANS -//STRUCT_FIELD (long,4,CS_SA_,br) -#endif - -// Not saved: -// EXCCAUSE ?? -// DEBUGCAUSE ?? -// EXCVADDR ?? -// DDR -// INTERRUPT -// ... locked cache lines ... - -#endif /* _XTOS_CORE_STATE_H_ */ - diff --git a/src/arch/xtensa/include/xtensa/xtruntime-frames.h b/src/arch/xtensa/include/xtensa/xtruntime-frames.h deleted file mode 100644 index f54911f37762..000000000000 --- a/src/arch/xtensa/include/xtensa/xtruntime-frames.h +++ /dev/null @@ -1,202 +0,0 @@ -/* xtruntime-frames.h - exception stack frames for single-threaded run-time */ -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/include/xtensa/xtruntime-frames.h#1 $ */ - -/* - * Copyright (c) 2002-2012 Tensilica 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. - */ - -#ifndef _XTRUNTIME_FRAMES_H_ -#define _XTRUNTIME_FRAMES_H_ - -#include <xtensa/config/core.h> - -/* Macros that help define structures for both C and assembler: */ -#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) -#define STRUCT_BEGIN .pushsection .text; .struct 0 -#define STRUCT_FIELD(ctype,size,pre,name) pre##name: .space size -#define STRUCT_AFIELD(ctype,size,pre,name,n) pre##name: .if n ; .space (size)*(n) ; .endif -#define STRUCT_AFIELD_A(ctype,size,align,pre,name,n) .balign align ; pre##name: .if n ; .space (size)*(n) ; .endif -#define STRUCT_END(sname) sname##Size:; .popsection -#else /*_ASMLANGUAGE||__ASSEMBLER__*/ -#define STRUCT_BEGIN typedef struct { -#define STRUCT_FIELD(ctype,size,pre,name) ctype name; -#define STRUCT_AFIELD(ctype,size,pre,name,n) ctype name[n]; -#define STRUCT_AFIELD_A(ctype,size,align,pre,name,n) ctype name[n] __attribute__((aligned(align))); -#define STRUCT_END(sname) } sname; -#endif /*_ASMLANGUAGE||__ASSEMBLER__*/ - -/* Coprocessors masks. - * NOTE: currently only 2 supported. - */ -#define CP0_MASK (1 << 0) -#define CP1_MASK (1 << 1) - -/* - * Kernel vector mode exception stack frame. - * - * NOTE: due to the limited range of addi used in the current - * kernel exception vector, and the fact that historically - * the vector is limited to 12 bytes, the size of this - * stack frame is limited to 128 bytes (currently at 64). - */ -STRUCT_BEGIN -STRUCT_FIELD (long,4,KEXC_,pc) /* "parm" */ -STRUCT_FIELD (long,4,KEXC_,ps) -STRUCT_AFIELD(long,4,KEXC_,areg, 4) /* a12 .. a15 */ -STRUCT_FIELD (long,4,KEXC_,sar) /* "save" */ -#if XCHAL_HAVE_LOOPS -STRUCT_FIELD (long,4,KEXC_,lcount) -STRUCT_FIELD (long,4,KEXC_,lbeg) -STRUCT_FIELD (long,4,KEXC_,lend) -#endif -#if XCHAL_HAVE_MAC16 -STRUCT_FIELD (long,4,KEXC_,acclo) -STRUCT_FIELD (long,4,KEXC_,acchi) -STRUCT_AFIELD(long,4,KEXC_,mr, 4) -#endif -STRUCT_END(KernelFrame) - - -/* - * User vector mode exception stack frame: - * - * WARNING: if you modify this structure, you MUST modify the - * computation of the pad size (ALIGNPAD) accordingly. - */ -STRUCT_BEGIN -STRUCT_FIELD (long,4,UEXC_,pc) -STRUCT_FIELD (long,4,UEXC_,ps) -STRUCT_FIELD (long,4,UEXC_,sar) -STRUCT_FIELD (long,4,UEXC_,vpri) -STRUCT_FIELD (long,4,UEXC_,a0) -STRUCT_FIELD (long,4,UEXC_,a1) -STRUCT_FIELD (long,4,UEXC_,a2) -STRUCT_FIELD (long,4,UEXC_,a3) -STRUCT_FIELD (long,4,UEXC_,a4) -STRUCT_FIELD (long,4,UEXC_,a5) -STRUCT_FIELD (long,4,UEXC_,a6) -STRUCT_FIELD (long,4,UEXC_,a7) -STRUCT_FIELD (long,4,UEXC_,a8) -STRUCT_FIELD (long,4,UEXC_,a9) -STRUCT_FIELD (long,4,UEXC_,a10) -STRUCT_FIELD (long,4,UEXC_,a11) -STRUCT_FIELD (long,4,UEXC_,a12) -STRUCT_FIELD (long,4,UEXC_,a13) -STRUCT_FIELD (long,4,UEXC_,a14) -STRUCT_FIELD (long,4,UEXC_,a15) -STRUCT_FIELD (long,4,UEXC_,exccause) /* NOTE: can probably rid of this one (pass direct) */ -STRUCT_FIELD (long,4,UEXC_,align1) /* alignment to 8 bytes */ -#if XCHAL_HAVE_LOOPS -STRUCT_FIELD (long,4,UEXC_,lcount) -STRUCT_FIELD (long,4,UEXC_,lbeg) -STRUCT_FIELD (long,4,UEXC_,lend) -STRUCT_FIELD (long,4,UEXC_,align2) /* alignment to 8 bytes */ -#endif -#if XCHAL_HAVE_MAC16 -STRUCT_FIELD (long,4,UEXC_,acclo) -STRUCT_FIELD (long,4,UEXC_,acchi) -STRUCT_AFIELD(long,4,UEXC_,mr, 4) -#endif -#if (XCHAL_CP_MASK & CP0_MASK) -STRUCT_AFIELD (long,4,UEXC_,cp0, XCHAL_CP0_SA_SIZE / 4) -#endif -#if (XCHAL_CP_MASK & CP1_MASK) -STRUCT_AFIELD (long,4,UEXC_,cp1, XCHAL_CP1_SA_SIZE / 4) -#endif -/* ALIGNPAD is the 16-byte alignment padding. */ -#define ALIGNPAD ((2 + XCHAL_HAVE_MAC16*2 + ((XCHAL_CP0_SA_SIZE%16)/4) + ((XCHAL_CP1_SA_SIZE%16)/4)) & 3) -#if ALIGNPAD -STRUCT_AFIELD(long,4,UEXC_,pad, ALIGNPAD) /* 16-byte alignment padding */ -#endif -/*STRUCT_AFIELD_A(char,1,XCHAL_CPEXTRA_SA_ALIGN,UEXC_,ureg, (XCHAL_CPEXTRA_SA_SIZE+3)&-4)*/ /* not used */ -STRUCT_END(UserFrame) - -/* - * xtos_structures_pointers contains ptrs to all structures created for - * each processor individually. - * - * To access the core specific structure from ASM (after threadptr is set): - * xtos_addr_percore a13, xtos_interrupt_table - */ -STRUCT_BEGIN -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_enabled) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_intstruct) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_interrupt_table) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_interrupt_mask_table) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_stack_for_interrupt_1) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_stack_for_interrupt_2) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_stack_for_interrupt_3) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_stack_for_interrupt_4) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_stack_for_interrupt_5) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_interrupt_ctx) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_saved_ctx) -STRUCT_FIELD(void*,4,XTOS_PTR_TO_,xtos_saved_sp) -STRUCT_END(xtos_structures_pointers) - -/* - * xtos_task_context contains information about currently - * executed task - */ - -#define XTOS_TASK_CONTEXT_OWN_STACK 1 - -STRUCT_BEGIN -STRUCT_FIELD (UserFrame*,4,TC_,stack_pointer) -STRUCT_FIELD (void*,4,TC_,stack_base) -STRUCT_FIELD (long,4,TC_,stack_size) -STRUCT_FIELD (long,4,TC_,flags) -STRUCT_END(xtos_task_context) - -#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) - - -/* Check for UserFrameSize small enough not to require rounding...: */ - /* Skip 16-byte save area, then 32-byte space for 8 regs of call12 - * (which overlaps with 16-byte GCC nested func chaining area), - * then exception stack frame: */ - .set UserFrameTotalSize, 16+32+UserFrameSize - /* Greater than 112 bytes? (max range of ADDI, both signs, when aligned to 16 bytes): */ - .ifgt UserFrameTotalSize-112 - /* Round up to 256-byte multiple to accelerate immediate adds: */ - .set UserFrameTotalSize, ((UserFrameTotalSize+255) & 0xFFFFFF00) - .endif -# define ESF_TOTALSIZE UserFrameTotalSize - -#endif /* _ASMLANGUAGE || __ASSEMBLER__ */ - - -#if XCHAL_NUM_CONTEXTS > 1 -/* Structure of info stored on new context's stack for setup: */ -STRUCT_BEGIN -STRUCT_FIELD (long,4,INFO_,sp) -STRUCT_FIELD (long,4,INFO_,arg1) -STRUCT_FIELD (long,4,INFO_,funcpc) -STRUCT_FIELD (long,4,INFO_,prevps) -STRUCT_END(SetupInfo) -#endif - - -#define KERNELSTACKSIZE 1024 - - -#endif /* _XTRUNTIME_FRAMES_H_ */ - diff --git a/src/arch/xtensa/include/xtensa/xtruntime.h b/src/arch/xtensa/include/xtensa/xtruntime.h deleted file mode 100644 index d5d1f1dd3ff2..000000000000 --- a/src/arch/xtensa/include/xtensa/xtruntime.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * xtruntime.h -- general C definitions for single-threaded run-time - * - * Copyright (c) 2002-2013 Tensilica 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. - */ - -#ifndef XTRUNTIME_H -#define XTRUNTIME_H - -#include <xtensa/config/core.h> -#include <xtensa/config/specreg.h> -#include <xtensa/xtruntime-core-state.h> - -#ifndef XTSTR -#define _XTSTR(x) # x -#define XTSTR(x) _XTSTR(x) -#endif - -/* _xtos_core_shutoff() flags parameter values: */ -#define XTOS_KEEPON_MEM 0x00000100 /* ==PWRCTL_MEM_WAKEUP */ -#define XTOS_KEEPON_MEM_SHIFT 8 -#define XTOS_KEEPON_DEBUG 0x00001000 /* ==PWRCTL_DEBUG_WAKEUP */ -#define XTOS_KEEPON_DEBUG_SHIFT 12 - -#define XTOS_IDMA_NO_WAIT 0x00010000 /* Do not wait for idma to finish. Disable if necessary */ -#define XTOS_IDMA_WAIT_STANDBY 0x00020000 /* Also treat standby state as the end of wait */ - -#define XTOS_COREF_PSO 0x00000001 /* do power shutoff */ -#define XTOS_COREF_PSO_SHIFT 0 - -#define _xtos_set_execption_handler _xtos_set_exception_handler /* backward compatibility */ -#define _xtos_set_saved_intenable _xtos_ints_on /* backward compatibility */ -#define _xtos_clear_saved_intenable _xtos_ints_off /* backward compatibility */ - -#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(XTOS_MISRA) -typedef void (_xtos_handler_func)(void *); -#elif defined(__cplusplus) -typedef void (_xtos_handler_func)(...); -#else -typedef void (_xtos_handler_func)(); -#endif -typedef _xtos_handler_func *_xtos_handler; - -/* - * unsigned XTOS_SET_INTLEVEL(int intlevel); - * This macro sets the current interrupt level. - * The 'intlevel' parameter must be a constant. - * This macro returns a 32-bit value that must be passed to - * XTOS_RESTORE_INTLEVEL() to restore the previous interrupt level. - * XTOS_RESTORE_JUST_INTLEVEL() also does this, but in XEA2 configs - * it restores only PS.INTLEVEL rather than the entire PS register - * and thus is slower. - */ -#if !XCHAL_HAVE_INTERRUPTS -# define XTOS_SET_INTLEVEL(intlevel) 0 -# define XTOS_SET_MIN_INTLEVEL(intlevel) 0 -# define XTOS_RESTORE_INTLEVEL(restoreval) -# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) -#elif XCHAL_HAVE_XEA2 -/* In XEA2, we can simply safely set PS.INTLEVEL directly: */ -/* NOTE: these asm macros don't modify memory, but they are marked - * as such to act as memory access barriers to the compiler because - * these macros are sometimes used to delineate critical sections; - * function calls are natural barriers (the compiler does not know - * whether a function modifies memory) unless declared to be inlined. */ -# define XTOS_SET_INTLEVEL(intlevel) ({ unsigned __tmp; \ - __asm__ __volatile__( "rsil %0, " XTSTR(intlevel) "\n" \ - : "=a" (__tmp) : : "memory" ); \ - __tmp;}) -# define XTOS_SET_MIN_INTLEVEL(intlevel) ({ unsigned __tmp, __tmp2, __tmp3; \ - __asm__ __volatile__( "rsr.ps %0\n" /* get old (current) PS.INTLEVEL */ \ - "movi %2, " XTSTR(intlevel) "\n" \ - "extui %1, %0, 0, 4\n" /* keep only INTLEVEL bits of parameter */ \ - "blt %2, %1, 1f\n" \ - "rsil %0, " XTSTR(intlevel) "\n" \ - "1:\n" \ - : "=a" (__tmp), "=&a" (__tmp2), "=&a" (__tmp3) : : "memory" ); \ - __tmp;}) -# define XTOS_RESTORE_INTLEVEL(restoreval) do{ unsigned __tmp = (restoreval); \ - __asm__ __volatile__( "wsr.ps %0 ; rsync\n" \ - : : "a" (__tmp) : "memory" ); \ - }while(0) -# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) _xtos_set_intlevel(restoreval) -#else -/* In XEA1, we have to rely on INTENABLE register virtualization: */ -extern unsigned _xtos_set_vpri( unsigned vpri ); -extern unsigned _xtos_vpri_enabled; /* current virtual priority */ -# define XTOS_SET_INTLEVEL(intlevel) _xtos_set_vpri(~XCHAL_INTLEVEL_ANDBELOW_MASK(intlevel)) -# define XTOS_SET_MIN_INTLEVEL(intlevel) _xtos_set_vpri(_xtos_vpri_enabled & ~XCHAL_INTLEVEL_ANDBELOW_MASK(intlevel)) -# define XTOS_RESTORE_INTLEVEL(restoreval) _xtos_set_vpri(restoreval) -# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) _xtos_set_vpri(restoreval) -#endif - -/* - * The following macros build upon the above. They are generally used - * instead of invoking the SET_INTLEVEL and SET_MIN_INTLEVEL macros directly. - * They all return a value that can be used with XTOS_RESTORE_INTLEVEL() - * or _xtos_restore_intlevel() or _xtos_restore_just_intlevel() to restore - * the effective interrupt level to what it was before the macro was invoked. - * In XEA2, the DISABLE macros are much faster than the MASK macros - * (in all configs, DISABLE sets the effective interrupt level, whereas MASK - * makes ensures the effective interrupt level is at least the level given - * without lowering it; in XEA2 with INTENABLE virtualization, these macros - * affect PS.INTLEVEL only, not the virtual priority, so DISABLE has partial - * MASK semantics). - * - * A typical critical section sequence might be: - * unsigned rval = XTOS_DISABLE_EXCM_INTERRUPTS; - * ... critical section ... - * XTOS_RESTORE_INTLEVEL(rval); - */ -/* Enable all interrupts (those activated with _xtos_ints_on()): */ -#define XTOS_ENABLE_INTERRUPTS XTOS_SET_INTLEVEL(0) -/* Disable low priority level interrupts (they can interact with the OS): */ -#define XTOS_DISABLE_LOWPRI_INTERRUPTS XTOS_SET_INTLEVEL(XCHAL_NUM_LOWPRI_LEVELS) -#define XTOS_MASK_LOWPRI_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XCHAL_NUM_LOWPRI_LEVELS) -/* Disable interrupts that can interact with the OS: */ -#define XTOS_DISABLE_EXCM_INTERRUPTS XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL) -#define XTOS_MASK_EXCM_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL) -#if 0 /* XTOS_LOCK_LEVEL is not exported to applications */ -/* Disable interrupts that can interact with the OS, or manipulate virtual INTENABLE: */ -#define XTOS_DISABLE_LOCK_INTERRUPTS XTOS_SET_INTLEVEL(XTOS_LOCK_LEVEL) -#define XTOS_MASK_LOCK_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XTOS_LOCK_LEVEL) -#endif -/* Disable ALL interrupts (not for common use, particularly if one's processor - * configuration has high-level interrupts and one cares about their latency): */ -#define XTOS_DISABLE_ALL_INTERRUPTS XTOS_SET_INTLEVEL(15) - -/* These two are deprecated. Use the newer functions below. */ -extern unsigned int _xtos_ints_off( unsigned int mask ); -extern unsigned int _xtos_ints_on( unsigned int mask ); - -/* Newer functions to enable/disable the specified interrupt. */ -static inline void _xtos_interrupt_enable(unsigned int intnum) -{ - _xtos_ints_on(1 << intnum); -} - -static inline void _xtos_interrupt_disable(unsigned int intnum) -{ - _xtos_ints_off(1 << intnum); -} - -extern unsigned _xtos_set_intlevel( int intlevel ); -extern unsigned _xtos_set_min_intlevel( int intlevel ); -extern unsigned _xtos_restore_intlevel( unsigned restoreval ); -extern unsigned _xtos_restore_just_intlevel( unsigned restoreval ); -extern _xtos_handler _xtos_set_interrupt_handler( int n, _xtos_handler f ); -extern _xtos_handler _xtos_set_interrupt_handler_arg( int n, _xtos_handler f, void *arg ); -extern _xtos_handler _xtos_set_exception_handler( int n, _xtos_handler f ); - -extern void _xtos_memep_initrams( void ); -extern void _xtos_memep_enable( int flags ); - -/* For use with the tiny LSP (see LSP reference manual). */ -#if XCHAL_NUM_INTLEVELS >= 1 -extern void _xtos_dispatch_level1_interrupts( void ); -#endif -#if XCHAL_NUM_INTLEVELS >= 2 -extern void _xtos_dispatch_level2_interrupts( void ); -#endif -#if XCHAL_NUM_INTLEVELS >= 3 -extern void _xtos_dispatch_level3_interrupts( void ); -#endif -#if XCHAL_NUM_INTLEVELS >= 4 -extern void _xtos_dispatch_level4_interrupts( void ); -#endif -#if XCHAL_NUM_INTLEVELS >= 5 -extern void _xtos_dispatch_level5_interrupts( void ); -#endif -#if XCHAL_NUM_INTLEVELS >= 6 -extern void _xtos_dispatch_level6_interrupts( void ); -#endif - -/* Deprecated (but kept because they were documented): */ -extern unsigned int _xtos_read_ints( void ); -extern void _xtos_clear_ints( unsigned int mask ); - - -/* Power shut-off related routines. */ -extern int _xtos_core_shutoff(unsigned flags); -extern int _xtos_core_save(unsigned flags, XtosCoreState *savearea, void *code); -extern void _xtos_core_restore(unsigned retvalue, XtosCoreState *savearea); - - -#if XCHAL_NUM_CONTEXTS > 1 -extern unsigned _xtos_init_context(int context_num, int stack_size, - _xtos_handler_func *start_func, int arg1); -#endif - -/* Deprecated: */ -#if XCHAL_NUM_TIMERS > 0 -extern void _xtos_timer_0_delta( int cycles ); -#endif -#if XCHAL_NUM_TIMERS > 1 -extern void _xtos_timer_1_delta( int cycles ); -#endif -#if XCHAL_NUM_TIMERS > 2 -extern void _xtos_timer_2_delta( int cycles ); -#endif -#if XCHAL_NUM_TIMERS > 3 -extern void _xtos_timer_3_delta( int cycles ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */ - -#endif /* XTRUNTIME_H */ - diff --git a/src/arch/xtensa/init.c b/src/arch/xtensa/init.c deleted file mode 100644 index 5623eed526c0..000000000000 --- a/src/arch/xtensa/init.c +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -/** - * \file arch/xtensa/init.c - * \brief Xtensa initialization functions - * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#include "xtos-internal.h" -#include <sof/common.h> -#include <sof/init.h> -#include <sof/lib/cpu.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <config.h> -#include <xtensa/xtruntime-frames.h> -#include <xtos-structs.h> -#include <stddef.h> -#include <stdint.h> - -/* UserFrame's size needs to be 16 bytes aligned */ -STATIC_ASSERT((sizeof(UserFrame) % 16) == 0, invalid_UserFrame_alignment); - -/* verify xtos_active_task offset */ -STATIC_ASSERT(offsetof(struct thread_data, xtos_active_task) == - XTOS_TASK_CONTEXT_OFFSET, invalid_xtos_active_task_offset); - -#if CONFIG_DEBUG_LOCKS -/** \brief Debug lock. */ -uint32_t lock_dbg_atomic; - -/** \brief Debug locks per user. */ -uint32_t lock_dbg_user[DBG_LOCK_USERS] = {0}; -#endif - -/** \brief Core context for master core. */ -static struct core_context master_core_ctx; - -/** \brief Core context pointers for all the cores. */ -struct core_context *core_ctx_ptr[PLATFORM_CORE_COUNT] = { 0 }; - -/** \brief Xtos core data for master core. */ -struct xtos_core_data master_core_data; - -/** \brief Xtos core data pointers for all the cores. */ -struct xtos_core_data *core_data_ptr[PLATFORM_CORE_COUNT] = { 0 }; - -/** - * \brief Initializes core specific data. - */ -static void initialize_pointers_per_core(void) -{ - int core = cpu_get_id(); - struct xtos_core_data *core_data; - xtos_structures_pointers *p; - - if (core == PLATFORM_MASTER_CORE_ID) { - master_core_data.thread_data_ptr = &master_core_ctx.td; - core_ctx_ptr[PLATFORM_MASTER_CORE_ID] = &master_core_ctx; - core_data_ptr[PLATFORM_MASTER_CORE_ID] = &master_core_data; - } - - cpu_write_threadptr((int)core_ctx_ptr[core]); - - core_data = core_data_ptr[core]; - - p = &core_data->thread_data_ptr->xtos_ptrs; - p->xtos_interrupt_ctx = &core_data->xtos_interrupt_ctx; - p->xtos_saved_sp = &core_data->xtos_saved_sp; -#if CONFIG_INTERRUPT_LEVEL_1 - p->xtos_stack_for_interrupt_1 = core_data->xtos_stack_for_interrupt_1; -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - p->xtos_stack_for_interrupt_2 = core_data->xtos_stack_for_interrupt_2; -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - p->xtos_stack_for_interrupt_3 = core_data->xtos_stack_for_interrupt_3; -#endif -#if CONFIG_INTERRUPT_LEVEL_4 - p->xtos_stack_for_interrupt_4 = core_data->xtos_stack_for_interrupt_4; -#endif -#if CONFIG_INTERRUPT_LEVEL_5 - p->xtos_stack_for_interrupt_5 = core_data->xtos_stack_for_interrupt_5; -#endif -#if CONFIG_SMP - p->xtos_enabled = &core_data->xtos_int_data.xtos_enabled; - p->xtos_intstruct = &core_data->xtos_int_data; - p->xtos_interrupt_table = - &core_data->xtos_int_data.xtos_interrupt_table.array[0]; - p->xtos_interrupt_mask_table = - &core_data->xtos_int_data.xtos_interrupt_mask_table[0]; -#endif -} - -/** - * \brief Initializes architecture. - * \return Error status. - */ -int arch_init(void) -{ - initialize_pointers_per_core(); - register_exceptions(); - return 0; -} - -#if CONFIG_SMP - -#include <sof/debug/panic.h> -#include <sof/drivers/idc.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/notifier.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/ll_schedule_domain.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/trace.h> - -int slave_core_init(struct sof *sof) -{ - int err; - - /* init architecture */ - trace_point(TRACE_BOOT_ARCH); - err = arch_init(); - if (err < 0) - panic(SOF_IPC_PANIC_ARCH); - - trace_point(TRACE_BOOT_SYS_NOTIFIER); - init_system_notify(sof); - - /* interrupts need to be initialized before any usage */ - trace_point(TRACE_BOOT_PLATFORM_IRQ); - platform_interrupt_init(); - - trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(); - scheduler_init_ll(timer_domain_get()); - scheduler_init_ll(dma_domain_get()); - - /* initialize IDC mechanism */ - trace_point(TRACE_BOOT_PLATFORM_IDC); - err = idc_init(); - if (err < 0) - return err; - - trace_point(TRACE_BOOT_PLATFORM); - - /* task initialized in edf_scheduler_init */ - schedule_task(*task_main_get(), 0, UINT64_MAX); - - return err; -} - -#endif diff --git a/src/arch/xtensa/lib/CMakeLists.txt b/src/arch/xtensa/lib/CMakeLists.txt deleted file mode 100644 index 9610d6277525..000000000000 --- a/src/arch/xtensa/lib/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof notifier.c) - -if (CONFIG_SMP) - add_local_sources(sof cpu.c) -endif() diff --git a/src/arch/xtensa/lib/cpu.c b/src/arch/xtensa/lib/cpu.c deleted file mode 100644 index feeb99a1c7a0..000000000000 --- a/src/arch/xtensa/lib/cpu.c +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -/** - * \file arch/xtensa/cpu.c - * \brief Xtensa CPU implementation file - * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#include <sof/common.h> -#include <sof/drivers/idc.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/wait.h> -#include <sof/schedule/schedule.h> -#include <sof/sof.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <xtos-structs.h> -#include <stdint.h> - -/* cpu tracing */ -#define trace_cpu(__e) trace_event(TRACE_CLASS_CPU, __e) -#define trace_cpu_error(__e) trace_error(TRACE_CLASS_CPU, __e) -#define tracev_cpu(__e) tracev_event(TRACE_CLASS_CPU, __e) - -extern struct core_context *core_ctx_ptr[PLATFORM_CORE_COUNT]; -extern struct xtos_core_data *core_data_ptr[PLATFORM_CORE_COUNT]; - -static uint32_t active_cores_mask; - -void arch_cpu_enable_core(int id) -{ - struct idc_msg power_up = { - IDC_MSG_POWER_UP, IDC_MSG_POWER_UP_EXT, id }; - uint32_t flags; - - irq_local_disable(flags); - - if (!arch_cpu_is_core_enabled(id)) { - pm_runtime_get(PM_RUNTIME_DSP, id); - - /* Turn on stack memory for core */ - pm_runtime_get(CORE_MEMORY_POW, id); - - /* allocate resources for core */ - cpu_alloc_core_context(id); - - /* enable IDC interrupt for the the slave core */ - idc_enable_interrupts(id, cpu_get_id()); - - /* send IDC power up message */ - idc_send_msg(&power_up, IDC_NON_BLOCKING); - - active_cores_mask |= (1 << id); - } - - irq_local_enable(flags); -} - -void arch_cpu_disable_core(int id) -{ - struct idc_msg power_down = { - IDC_MSG_POWER_DOWN, IDC_MSG_POWER_DOWN_EXT, id }; - uint32_t flags; - - irq_local_disable(flags); - - if (arch_cpu_is_core_enabled(id)) { - idc_send_msg(&power_down, IDC_NON_BLOCKING); - - active_cores_mask ^= (1 << id); - } - - irq_local_enable(flags); -} - -int arch_cpu_is_core_enabled(int id) -{ - return id == PLATFORM_MASTER_CORE_ID || - active_cores_mask & (1 << id); -} - -void cpu_alloc_core_context(int core) -{ - struct core_context *core_ctx; - - core_ctx = rzalloc_core_sys(core, sizeof(*core_ctx)); - dcache_writeback_invalidate_region(core_ctx, sizeof(*core_ctx)); - - core_data_ptr[core] = rzalloc_core_sys(core, - sizeof(*core_data_ptr[core])); - core_data_ptr[core]->thread_data_ptr = &core_ctx->td; - dcache_writeback_invalidate_region(core_data_ptr[core], - sizeof(*core_data_ptr[core])); - - dcache_writeback_invalidate_region(core_data_ptr, - sizeof(core_data_ptr)); - - core_ctx_ptr[core] = core_ctx; - dcache_writeback_invalidate_region(core_ctx_ptr, - sizeof(core_ctx_ptr)); - - /* share pointer to sof context */ - dcache_writeback_region(sof_get(), sizeof(*sof_get())); -} - -void cpu_power_down_core(void) -{ - arch_interrupt_global_disable(); - - idc_free(); - - schedule_free(); - - free_system_notify(); - - /* free entire sys heap, an instance dedicated for this core */ - free_heap(SOF_MEM_ZONE_SYS); - - dcache_writeback_invalidate_all(); - - /* Turn off stack memory for core */ - pm_runtime_put(CORE_MEMORY_POW, cpu_get_id()); - - pm_runtime_put(PM_RUNTIME_DSP, cpu_get_id()); - - /* arch_wait_for_interrupt() not used, because it will cause panic. - * This code is executed on irq lvl > 0, which is expected. - * Core will be put into reset by host anyway. - */ - while (1) - arch_wait_for_interrupt(0); -} diff --git a/src/arch/xtensa/lib/notifier.c b/src/arch/xtensa/lib/notifier.c deleted file mode 100644 index 3143138c8195..000000000000 --- a/src/arch/xtensa/lib/notifier.c +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -/** - * \file arch/xtensa/notifier.c - * \brief Xtensa notifier implementation file - * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#include <sof/lib/cpu.h> -#include <sof/lib/notifier.h> -#include <xtos-structs.h> - -struct notify **arch_notify_get(void) -{ - struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - - return &ctx->notify; -} diff --git a/src/arch/xtensa/main-entry.S b/src/arch/xtensa/main-entry.S deleted file mode 100644 index 630744f39e1d..000000000000 --- a/src/arch/xtensa/main-entry.S +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Rander Wang <rander.wang@intel.com> - */ - -/* - * Entry point from boot loader. - * Fix link address of this entry to SOF_TEXT_START so that - * it is easy for boot loader to jump to the baseFW becasue - * the boot loader and baseFW are in different elf file. - */ - - -// Exports -.global _MainEntry - - -/**************************************************************************/ - - .begin literal_prefix .MainEntry - .section .MainEntry.text, "ax" - - .align 4 - .global _MainEntry - -_MainEntry: - - call0 _start - - .size _MainEntry, . - _MainEntry - - .end literal_prefix diff --git a/src/arch/xtensa/schedule/CMakeLists.txt b/src/arch/xtensa/schedule/CMakeLists.txt deleted file mode 100644 index d462729c7245..000000000000 --- a/src/arch/xtensa/schedule/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof schedule.c task.c) diff --git a/src/arch/xtensa/schedule/schedule.c b/src/arch/xtensa/schedule/schedule.c deleted file mode 100644 index 23382fdf3784..000000000000 --- a/src/arch/xtensa/schedule/schedule.c +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -/** - * \file arch/xtensa/schedule.c - * \brief Xtensa schedule implementation file - * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#include <sof/lib/cpu.h> -#include <sof/schedule/schedule.h> -#include <xtos-structs.h> - -struct schedulers **arch_schedulers_get(void) -{ - struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - - return &ctx->schedulers; -} diff --git a/src/arch/xtensa/schedule/task.c b/src/arch/xtensa/schedule/task.c deleted file mode 100644 index 7a6bc612d7dc..000000000000 --- a/src/arch/xtensa/schedule/task.c +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Tomasz Lauda <tomasz.lauda@linux.intel.com> - -/** - * \file arch/xtensa/task.c - * \brief Arch task implementation file - * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/wait.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <ipc/topology.h> -#include <config.h> -#include <xtensa/corebits.h> -#include <xtensa/xtruntime-frames.h> -#include <xtos-structs.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -enum task_state task_main_slave_core(void *data) -{ -#if CONFIG_SMP - /* main audio processing loop */ - while (1) { - /* sleep until next IDC or DMA */ - wait_for_interrupt(0); - } -#endif - - return SOF_TASK_STATE_COMPLETED; -} - -struct task **task_main_get(void) -{ - struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - - return &ctx->main_task; -} - -volatile void *task_context_get(void) -{ - struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - - return ctx->td.xtos_active_task; -} - -void task_context_set(void *task_ctx) -{ - struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - - ctx->td.xtos_active_task = task_ctx; -} - -int task_context_alloc(void **task_ctx) -{ - *task_ctx = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(xtos_task_context)); - if (!*task_ctx) - return -ENOMEM; - return 0; -} - -int task_context_init(void *task_ctx, void *entry, void *arg0, void *arg1, - int task_core, void *stack, int stack_size) -{ - xtos_task_context *ctx = task_ctx; - UserFrame *sp; - - /* allocate stack if not provided */ - if (stack) { - ctx->stack_base = stack; - ctx->stack_size = stack_size; - } else { - ctx->stack_base = rballoc(0, SOF_MEM_CAPS_RAM, - PLATFORM_TASK_DEFAULT_STACK_SIZE); - if (!ctx->stack_base) - return -ENOMEM; - ctx->stack_size = PLATFORM_TASK_DEFAULT_STACK_SIZE; - ctx->flags |= XTOS_TASK_CONTEXT_OWN_STACK; - } - bzero(ctx->stack_base, ctx->stack_size); - - /* set initial stack pointer */ - sp = (UserFrame *)((char *)ctx->stack_base + ctx->stack_size - - sizeof(UserFrame)); - - /* entry point */ - sp->pc = (uint32_t)entry; - - /* a1 is pointer to stack */ - sp->a1 = (uint32_t)sp; - - /* PS_WOECALL4_ABI - window overflow and increment enable - * PS_UM - user vector mode enable - */ - sp->ps = PS_WOECALL4_ABI | PS_UM; - - /* a6 and a7 are the first parameters */ - sp->a6 = (uint32_t)arg0; - sp->a7 = (uint32_t)arg1; - - ctx->stack_pointer = sp; - - return 0; -} - -void task_context_free(void *task_ctx) -{ - xtos_task_context *ctx = task_ctx; - - if (ctx->flags & XTOS_TASK_CONTEXT_OWN_STACK) - rfree(ctx->stack_base); - - ctx->stack_size = 0; - ctx->stack_pointer = NULL; - - rfree(ctx); -} diff --git a/src/arch/xtensa/xtos/CMakeLists.txt b/src/arch/xtensa/xtos/CMakeLists.txt deleted file mode 100644 index c2bb43a156bf..000000000000 --- a/src/arch/xtensa/xtos/CMakeLists.txt +++ /dev/null @@ -1,93 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -set(VECTOR_DEFS - -D__SPLIT__vector - -D__SPLIT__handler - -D__SPLIT__user -) - -# Builds lib for each level from the same source files - -function(sof_xtos_add_level level) - set(lib_name "xlevel${level}") - add_library(${lib_name} STATIC "") - add_local_sources(${lib_name} - int-handler.S - int-vector.S - int-initlevel.S - ) - target_link_libraries(${lib_name} sof_options) - target_compile_definitions(${lib_name} PRIVATE - ${VECTOR_DEFS} - -D_INTERRUPT_LEVEL=${level} - ) -endfunction() - -if(CONFIG_INTERRUPT_LEVEL_1) - list(APPEND VECTOR_DEFS -D__SPLIT__level1int) -endif() - -if(CONFIG_INTERRUPT_LEVEL_2) - list(APPEND VECTOR_DEFS -D__SPLIT__level2) - list(APPEND levels 2) -endif() - -if(CONFIG_INTERRUPT_LEVEL_3) - list(APPEND VECTOR_DEFS -D__SPLIT__level3) - list(APPEND levels 3) -endif() - -if(CONFIG_INTERRUPT_LEVEL_4) - list(APPEND VECTOR_DEFS -D__SPLIT__level4) - list(APPEND levels 4) -endif() - -if(CONFIG_INTERRUPT_LEVEL_5) - list(APPEND VECTOR_DEFS -D__SPLIT__level5) - list(APPEND levels 5) -endif() - -foreach(level ${levels}) - sof_xtos_add_level(${level}) -endforeach() - -add_library(xtos STATIC "") -add_local_sources(xtos - core-restore.S - core-save.S - core-shutoff.S - double-vector.S - debug-vector.S - xea1/exc-alloca-handler.S - xea1/exc-c-wrapper-handler.S - xea2/exc-c-wrapper-handler.S - xea1/exc-return.S - xea2/exc-return.S - exc-sethandler.c - exc-syscall-handler.S - exc-table.S - exc-unhandled.S - interrupt-table.S - int-sethandler.c - xea1/intlevel-restore.S - xea2/intlevel-restore.S - xea1/intlevel-setmin.S - xea2/intlevel-setmin.S - xea1/intlevel-set.S - xea2/intlevel-set.S - xea1/int-lowpri-dispatcher.S - xea2/int-lowpri-dispatcher.S - ints-off.S - ints-on.S - kernel-vector.S - memep-enable.S - memep-initrams.S - memerror-vector.S - nmi-vector.S - xea2/reloc-vectors.S - user-vector.S - xea1/window-vectors.S - xea2/window-vectors.S -) -target_link_libraries(xtos sof_options) -target_compile_definitions(xtos PRIVATE ${VECTOR_DEFS}) diff --git a/src/arch/xtensa/xtos/_sharedvectors-for-reset.S b/src/arch/xtensa/xtos/_sharedvectors-for-reset.S deleted file mode 100644 index ef60901d53e8..000000000000 --- a/src/arch/xtensa/xtos/_sharedvectors-for-reset.S +++ /dev/null @@ -1,40 +0,0 @@ -// _sharedvectors-for-reset.S -- Reference to pull in a shared reset vector -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/_sharedvectors-for-reset.S#1 $ - -// Copyright (c) 2008 Tensilica 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 <xtensa/coreasm.h> - -/* Multicore build flows can use this file (_sharedvectors-for-reset.o) - by copying it to _sharedvectors.o early in the linker search path - (to override the default one), and updating the memory map or linker - scripts accordingly. - This file pulls in a sharable reset vector (typically - shared-reset-vector.S, which requires the PRID option). */ - -.global _SharedResetVector - -/* The following allows this object file to be pulled in by reference: */ -.text -.global _xtos_sharedvectors_ref_ -.set _xtos_sharedvectors_ref_, 0 - diff --git a/src/arch/xtensa/xtos/_sharedvectors.S b/src/arch/xtensa/xtos/_sharedvectors.S deleted file mode 100644 index def144132519..000000000000 --- a/src/arch/xtensa/xtos/_sharedvectors.S +++ /dev/null @@ -1,37 +0,0 @@ -// _sharedvectors.S -- Reference symbols to pull in any shared vectors -// (default version, used when not sharing any vector) -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/_sharedvectors.S#1 $ - -// Copyright (c) 2008 Tensilica 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 <xtensa/coreasm.h> - -/* Not present by default. Multicore build flows build/use a custom - version of _sharedvectors.o that may pull in shared vectors. */ - -/* .global _SharedResetVector */ - -/* The following allows this object file to be pulled in by reference: */ -.text -.global _xtos_sharedvectors_ref_ -.set _xtos_sharedvectors_ref_, 0 - diff --git a/src/arch/xtensa/xtos/_vectors.S b/src/arch/xtensa/xtos/_vectors.S deleted file mode 100644 index 8c70e3f2514f..000000000000 --- a/src/arch/xtensa/xtos/_vectors.S +++ /dev/null @@ -1,94 +0,0 @@ -// _vectors.S -- Reference symbols to pull in all required vectors -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/_vectors.S#1 $ - -// Copyright (c) 2004, 2006-2007 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/config/system.h> /* for XSHAL_VECTORS_PACKED */ - -.global _ResetVector - -#if XCHAL_HAVE_EXCEPTIONS - -# if XCHAL_HAVE_DEBUG -.global _DebugExceptionVector -# endif - -.global _KernelExceptionVector -.global _UserExceptionVector - -# ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR -.global _DoubleExceptionVector -# endif - -# if XCHAL_HAVE_NMI -.global _NMIExceptionVector -# endif - -# if XCHAL_HAVE_WINDOWED -.global _WindowOverflow4 -.global _WindowUnderflow4 -.global _WindowOverflow8 -.global _WindowUnderflow8 -.global _WindowOverflow12 -.global _WindowUnderflow12 -# endif - -# if XCHAL_HAVE_MEM_ECC_PARITY -.global _MemErrorVector -# endif - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - - -#if (XCHAL_NUM_INTLEVELS >= 2) && (2 != XCHAL_DEBUGLEVEL) -.global _Level2Vector -#endif -#if (XCHAL_NUM_INTLEVELS >= 3) && (3 != XCHAL_DEBUGLEVEL) -.global _Level3Vector -#endif -#if (XCHAL_NUM_INTLEVELS >= 4) && (4 != XCHAL_DEBUGLEVEL) -.global _Level4Vector -#endif -#if (XCHAL_NUM_INTLEVELS >= 5) && (5 != XCHAL_DEBUGLEVEL) -.global _Level5Vector -#endif -#if (XCHAL_NUM_INTLEVELS >= 6) && (6 != XCHAL_DEBUGLEVEL) -.global _Level6Vector -#endif - -#if XCHAL_HAVE_VECBASE && XSHAL_VECTORS_PACKED -.global _RelocVectors -#endif - -/* These don't take up space: */ -.global xthals_hw_configid0 -.global xthals_hw_configid1 -.global xthals_release_major -.global xthals_release_minor - -/* The following allows this object file to be pulled in by reference: */ -.text -.global _xtos_vectors_ref_ -.set _xtos_vectors_ref_, 0 - - diff --git a/src/arch/xtensa/xtos/checkvecsize b/src/arch/xtensa/xtos/checkvecsize deleted file mode 100755 index 70789816de81..000000000000 --- a/src/arch/xtensa/xtos/checkvecsize +++ /dev/null @@ -1,71 +0,0 @@ -# Script to check that vector code is 16 bytes or less -# $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/checkvecsize#1 $ - -# Copyright (c) 2001 Tensilica 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. - -package Xtensa::checkvecsize; - -# Perl library modules -use strict; -use Getopt::Long; -use FileHandle; - -# Program - -use vars qw($objdump $maxsize); - -{ - $::myname = 'checkvecsize'; - - # command line - $maxsize = 16; - die("Usage is: $::myname -objdump prog [-maxsize n] files...\n") - unless &GetOptions("objdump=s" => \$objdump, - "maxsize=i" => \$maxsize) - && @ARGV > 0 && defined($objdump); - my $file; - foreach $file (@ARGV) { - checkvecsize ($file); - } -} - -sub checkvecsize { - my ($file) = @_; - my $od = new FileHandle "${objdump} -h $file|"; - die("$::myname: $!, opening pipe to $objdump -h $file.\n") - unless $od; - while (<$od>) { - if (/^\s*\d+\s+(\S+)\s+([0-9A-Fa-f]{8})\s/) { - my $size = hex($2); - die("$::myname: $file $1 section size is $size bytes.\n") - if $size > $maxsize; - } - } - $od->close(); -} - - -# Local Variables: -# mode:perl -# perl-indent-level:2 -# cperl-indent-level:2 -# End: diff --git a/src/arch/xtensa/xtos/core-restore.S b/src/arch/xtensa/xtos/core-restore.S deleted file mode 100644 index 7aee8c1ebc5a..000000000000 --- a/src/arch/xtensa/xtos/core-restore.S +++ /dev/null @@ -1,607 +0,0 @@ -// core-restore.S -- core state restore routine (used by PSO) -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/core-restore.S#1 $ - -// Copyright (c) 2012-2013 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/xdm-regs.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/mpuasm.h> -#include <xtensa/xtruntime-core-state.h> -#include "xtos-internal.h" -#include <xtensa/idmaasm.h> - - .text - - - - // void _xtos_core_restore(unsigned retvalue, XtosCoreState *savearea) - // - // Restore processor state. - // If save area signature is bad, function just returns. - // Else, processor state is restored, and execution resumes - // according to that saved processor state. - // - // On entry: - // Caches are ready to use (initialized or warm, as the case may be). - // - .align 4 - .global _xtos_core_restore - .type _xtos_core_restore,@function -_xtos_core_restore: - abi_entry - - // Check the save area's signature: - movi a5, CORE_STATE_SIGNATURE - l32i a4, a3, CS_SA_signature - movi a6, 0 - bne a4, a5, 1f // if bad, just return - -#if XCHAL_HAVE_INTERRUPTS - rsil a4, 15 // disable interrupts... - wsr.intenable a6 -#endif - - // Here, call0 is used as an unlimited range jump. It does not return. - call0 _xtos_core_restore_nw - -1: abi_return - - .size _xtos_core_restore, . - _xtos_core_restore - - - - // Restore processor state. - // On entry: - // Caches are ready to use (initialized or warm, as the case may be). - // a2 = return value passed to restored processor state - // a3 = pointer to save area to restore from - // INTENABLE = 0 (interrupts all disabled) - // LITBASE = initialized (per reset vector, not restored) - // touching a4..a7 won't overflow - // other registers are mostly undefined - // - .align 4 - .global _xtos_core_restore_nw - .type _xtos_core_restore_nw,@function -_xtos_core_restore_nw: - -#if XCHAL_HAVE_WINDOWED - s32i a2, a3, CS_SA_areg + 2*4 // save a2 thru rotation - wsr.excsave1 a3 // save a3 thru rotation - l32i a6, a3, CS_SA_windowstart // restore windowstart - l32i a5, a3, CS_SA_windowbase // restore windowbase - wsr.windowstart a6 - wsr.windowbase a5 - rsync - // a0-a15 have possibly all changed, so need to reload a3 - rsr.excsave1 a3 // restore a3 - l32i a2, a3, CS_SA_areg + 2*4 // restore a2 (return value) -#endif - - //movi a0, 0 - l32i a0, a3, CS_SA_restore_label // _xtos_core_save_common's return PC - - // Just for consistency... -#if XCHAL_HAVE_INTERRUPTS || XCHAL_HAVE_EXCEPTIONS - movi a4, 0x11 - wsr.ps a4 - rsync -#endif - - l32i a5, a3, CS_SA_sar // restore sar - wsr.sar a5 - -#if XCHAL_HAVE_PSO_CDM - // Restore PWRCTL (except ShutProcOffOnPWait, cleared when all is done). - movi a4, XDM_MISC_PWRCTL - movi a7, PWRCTL_CORE_SHUTOFF // aka ShutProcOffOnPWait - rer a6, a4 // read pwrctl - l32i a5, a3, CS_SA_pwrctl // get saved pwrctl - and a7, a7, a6 // keep just ShutProcOffOnPWait bit - or a5, a5, a7 // keep it set if already set (clear later) - wer a5, a4 // restore pwrctl (except ShutProcOffOnPWait) -#endif - - .set _idx, 2 - .rept XCHAL_NUM_INTLEVELS+XCHAL_HAVE_NMI-1 - l32i a5, a3, CS_SA_epc + 4*(_idx-2) - INDEX_SR wsr.epc a5 - l32i a5, a3, CS_SA_eps + 4*(_idx-2) - INDEX_SR wsr.eps a5 - l32i a5, a3, CS_SA_excsave + 4*(_idx-2) - INDEX_SR wsr.excsave a5 - .set _idx, _idx+1 - .endr - -#if XCHAL_HAVE_LOOPS - l32i a5, a3, CS_SA_lbeg - wsr.lbeg a5 - l32i a5, a3, CS_SA_lend - wsr.lend a5 - l32i a5, a3, CS_SA_lcount - wsr.lcount a5 -#endif -#if XCHAL_HAVE_ABSOLUTE_LITERALS - l32i a5, a3, CS_SA_litbase - wsr.litbase a5 -#endif -#if XCHAL_HAVE_VECBASE - l32i a5, a3, CS_SA_vecbase - wsr.vecbase a5 -#endif -#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) /* have ATOMCTL ? */ - l32i a5, a3, CS_SA_atomctl - wsr.atomctl a5 -#endif -#if XCHAL_HAVE_PREFETCH - l32i a5, a3, CS_SA_prefctl - wsr.prefctl a5 -#endif -#if XCHAL_USE_MEMCTL - l32i a5, a3, CS_SA_memctl - wsr.memctl a5 -#endif -#if XCHAL_HAVE_DEBUG - // NOTE: restore of debug state is conditional, - // as the power-down and wakeup code might be actively debugged. - rsr.icountlevel a5 - bnez a5, 1f // skip if being single-stepped (not failsafe!) - l32i a5, a3, CS_SA_icount - wsr.icount a5 - l32i a5, a3, CS_SA_icountlevel - wsr.icountlevel a5 -1: - //l32i a5, a3, CS_SA_debugcause // (won't get restored?) - //wsr.debugcause a5 - //l32i a5, a3, CS_SA_ddr - //wsr.ddr a5 -# if XCHAL_NUM_IBREAK - rsr.ibreakenable a6 - bnez a5, 1f // skip restore if already some ibreaks defined - - .set _idx, 0 - .rept XCHAL_NUM_IBREAK - l32i a5, a3, CS_SA_ibreaka + 4*_idx - INDEX_SR wsr.ibreaka a5 - .set _idx, _idx+1 - .endr - - l32i a5, a3, CS_SA_ibreakenable - wsr.ibreakenable a5 -1: -# endif - .set _idx, 0 - .rept XCHAL_NUM_DBREAK - INDEX_SR rsr.dbreakc a6 - bbsi.l a6, 30, 1f // skip restore of that dbreak if already active - bbsi.l a6, 31, 1f // ditto - l32i a5, a3, CS_SA_dbreaka + 4*_idx - INDEX_SR wsr.dbreaka a5 - l32i a5, a3, CS_SA_dbreakc + 4*_idx - INDEX_SR wsr.dbreakc a5 -1: - .set _idx, _idx+1 - .endr -#endif - - .set _idx, 0 - .rept XCHAL_NUM_MISC_REGS - l32i a5, a3, CS_SA_misc + 4*_idx - INDEX_SR wsr.misc a5 - .set _idx, _idx+1 - .endr - -#if XCHAL_HAVE_MEM_ECC_PARITY - l32i a5, a3, CS_SA_mepc - wsr.mepc a5 - l32i a5, a3, CS_SA_meps - wsr.meps a5 - l32i a5, a3, CS_SA_mesave - wsr.mesave a5 - l32i a5, a3, CS_SA_mesr - wsr.mesr a5 - l32i a5, a3, CS_SA_mecr - wsr.mecr a5 - l32i a5, a3, CS_SA_mevaddr - wsr.mevaddr a5 -#endif - - /* TIE state */ - addi a4, a3, CS_SA_ncp - xchal_ncp_load a4, a5,a6,a7,a8 // restore non-coprocessor state -#if XCHAL_HAVE_CP - movi a6, -1 - wsr.cpenable a6 // enable all coprocessors - rsync - xchal_cp0_load a4, a5,a6,a7,a8 continue=1 - xchal_cp1_load a4, a5,a6,a7,a8 continue=1 - xchal_cp2_load a4, a5,a6,a7,a8 continue=1 - xchal_cp3_load a4, a5,a6,a7,a8 continue=1 - xchal_cp4_load a4, a5,a6,a7,a8 continue=1 - xchal_cp5_load a4, a5,a6,a7,a8 continue=1 - xchal_cp6_load a4, a5,a6,a7,a8 continue=1 - xchal_cp7_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp8_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp9_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp10_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp11_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp12_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp13_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp14_load a4, a5,a6,a7,a8 continue=1 - //xchal_cp15_load a4, a5,a6,a7,a8 continue=1 - l32i a5, a3, CS_SA_cpenable - wsr.cpenable a5 -#endif - - /* TLB state (for known MMU types only, not internal custom) */ - // FIXME FIXME FIXME TODO: - // This restore code does not work in the general case, - // for CaXLT or full MMU, in particular when any address mappings - // were active when saved, that don't match reset state and affect - // code and data currently being accessed for restore. -#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR - addi a4, a3, CS_SA_tlbs // where to start loading TLB entry info - movi a5, 0x20000000 - movi a6, 0 -1: - l32i a7, a4, 0 - wdtlb a7, a6 // write DTLB entry PPN + CA - dsync - l32i a7, a4, 4 - j 2f - // Ensure WITLB and ISYNC are in same cache line, when writing ITLB - // entry that maps this currently running code - // (micro-architecture defined sequence): - .begin no-transform - .align 16 -2: witlb a7, a6 // write ITLB entry PPN + CA - isync - .end no-transform - nop - nop - addi a4, a4, 8 - add a6, a6, a5 - bnez a6, 1b - -#elif XCHAL_HAVE_PTP_MMU - addi a4, a3, CS_SA_tlbs // where to start storing TLB entry info - movi a10, _xtos_pso_tlbmap - movi a11, _xtos_pso_tlbmap_end - l32i a14, a3, CS_SA_dtlbcfg - l32i a15, a3, CS_SA_itlbcfg - wsr.dtlbcfg a14 // page size index (0..3) for each DTLB way - wsr.itlbcfg a15 // page size index (0..3) for each ITLB way - l32i a5, a3, CS_SA_ptevaddr - wsr.ptevaddr a5 - rsync - // Loop from last way to first (less register pressure that way). -.Loop_tlbmap_rest: - addi a11, a11, -8 // next way - l32i a8, a11, 0 // map of four (page size log2) per index for this way - // DTLB page size: - extui a12, a14, 0, 4 // page size index for this DTLB way - srli a14, a14, 4 // (for next way) - ssa8l a12 // prepare to shift right by 8*a12 - srl a12, a8 // page size log2 for this DTLB way - ssl a12 // prepare to shift left by a12 - movi a12, 1 // (to compute 1 << (page size log2)) - sll a12, a12 // page size for this DTLB way - - // Restore all entries of this DTLB way: - l32i a9, a11, 4 // number of entries for this way - sub a5, a11, a10 // way number * 8 - srli a5, a5, 3 // way number - extui a9, a9, 0, 8 -1: - l32i a6, a4, 0 // read entry VPN + ASID - extui a7, a6, 0, 8 // get ASID - bnez a7, 2f // if non-zero, need WDTLB - add a6, a6, a5 // zero, so need IDTLB - add way number - idtlb a6 // invalidate DTLB entry - j 5f -2: // Non-zero ASID. Put in RASID and adjust PS.RING accordingly. - bgeui a7, 5, 3f // branch if ASID >= 5 - addi a7, a7, -1 - slli a7, a7, 6 // PS.RING = ASID - 1 - addi a7, a7, 0x11 // PS.EXCM=1, PS.INTLEVEL=1 - movi a6, 0x04030201 // for ASID in {1 .. 4} - j 4f -3: // ASID >= 5, place it in RASID - movi a6, 0x00030201 - slli a7, a7, 24 - add a6, a7, a6 // RASID = 0x <ASID> 03 02 01 - movi a7, 0xd1 // PS.RING=3, PS.EXCM=1, PS.INTLEVEL=1 -4: wsr.rasid a6 - wsr.ps a7 - rsync - l32i a6, a4, 0 // read entry VPN + ASID - l32i a7, a4, 4 // read entry PPN + CA - srli a6, a6, 8 // replace ASID ... - slli a6, a6, 8 // ... - add a6, a6, a5 // ... with way number - wdtlb a7, a6 // write DTLB entry ... -5: dsync - addi a4, a4, 8 - add a5, a5, a12 // next entry of this DTLB way - addi a9, a9, -1 - bnez a9, 1b - - // ITLB page size: - extui a12, a15, 0, 4 // page size index for this ITLB way - srli a15, a15, 4 // (for next way) - ssa8l a12 // prepare to shift right by 8*a12 - srl a12, a8 // page size log2 for this ITLB way - ssl a12 // prepare to shift left by a12 - movi a12, 1 // (to compute 1 << (page size log2)) - sll a12, a12 // page size for this ITLB way - - // Restore all entries of this ITLB way: - l32i a9, a11, 4 // number of entries for this way - sub a5, a11, a10 // way number * 8 - srli a5, a5, 3 // way number - bbsi.l a9, 15, 6f // skip ITLB if is a DTLB-only way - extui a9, a9, 0, 8 -1: - l32i a6, a4, 0 // read entry VPN + ASID - extui a7, a6, 0, 8 // get ASID - bnez a7, 2f // if non-zero, need WITLB - add a6, a6, a5 // zero, so need IITLB - add way number - iitlb a6 // invalidate ITLB entry - j 5f -2: // Non-zero ASID. Put in RASID and adjust PS.RING accordingly. - bgeui a7, 5, 3f // branch if ASID >= 5 - addi a7, a7, -1 - slli a7, a7, 6 // PS.RING = ASID - 1 - addi a7, a7, 0x11 // PS.EXCM=1, PS.INTLEVEL=1 - movi a6, 0x04030201 // for ASID in {1 .. 4} - j 4f -3: // ASID >= 5, place it in RASID - movi a6, 0x00030201 - slli a7, a7, 24 - add a6, a7, a6 // RASID = 0x <ASID> 03 02 01 - movi a7, 0xd1 // PS.RING=3, PS.EXCM=1, PS.INTLEVEL=1 -4: wsr.rasid a6 - wsr.ps a7 - rsync - l32i a6, a4, 0 // read entry VPN + ASID - l32i a7, a4, 4 // read entry PPN + CA - srli a6, a6, 8 // replace ASID ... - slli a6, a6, 8 // ... - add a6, a6, a5 // ... with way number - j 8f - .align 16 // ensure WITLB and ISYNC in same cache line -8: witlb a7, a6 // write ITLB entry ... -5: isync - addi a4, a4, 8 - add a5, a5, a12 // next entry of this ITLB way - addi a9, a9, -1 - bnez a9, 1b -6: - - bne a11, a10, .Loop_tlbmap_rest // loop for next TLB way - l32i a5, a3, CS_SA_rasid - wsr.rasid a5 - movi a6, 0x11 - wsr.ps a6 - rsync - // Done saving TLBs. -#endif - -#if XCHAL_HAVE_MPU - addi a4, a3, CS_SA_mpuentry // MPU restore location - movi a5, XCHAL_MPU_ENTRIES - mpu_write_map a4, a5, a6, a7, a8, a9 - l32i a4, a3, CS_SA_cacheadrdis - wsr.cacheadrdis a4 -#endif - -#if XCHAL_HAVE_IDMA - addi a4, a3, CS_SA_idmaregs // IDMA regs restore location - _idma_restore a4, a5, a6, a7 -#endif - -#if XCHAL_HAVE_WINDOWED - // All the stack frames (except for our own) are supposed to be spilled - // into the stack. So now we restore the saved registers for our caller - // (and its caller) into the correct locations in the stack. See the - // comments in core-save.S and also the Xtensa Programmers Guide for - // more information. Of course we only restore if there is valid saved - // state. - - l32i a4, a3, CS_SA_caller_regs_saved // flag - beqz a4, .Lendcr // skip restore if 0 - - // Restore our caller's a0-a3 - - l32i a1, a3, CS_SA_areg + 1*4 // restore a1 - addi a4, a1, -16 - l32i a5, a3, CS_SA_caller_regs - l32i a6, a3, CS_SA_caller_regs + 4 - s32i a5, a4, 0 // caller a0 - s32i a6, a4, 4 // caller a1 - l32i a5, a3, CS_SA_caller_regs + 8 - l32i a6, a3, CS_SA_caller_regs + 12 - s32i a5, a4, 8 // caller a2 - s32i a6, a4, 12 // caller a3 - - // Now restore our callers caller's a0-a3 - - l32i a5, a3, CS_SA_caller_regs + 16 - l32i a6, a3, CS_SA_caller_regs + 20 - s32i a5, a1, 0 // caller caller a0 - s32i a6, a1, 4 // caller caller a1 - l32i a5, a3, CS_SA_caller_regs + 24 - l32i a6, a3, CS_SA_caller_regs + 28 - s32i a5, a1, 8 // caller caller a2 - s32i a6, a1, 12 // caller caller a3 - - // Now restore caller's a4-a11 as required - // NOTE a0 is pointing to _xtos_core_save() not the actual caller - - l32i a4, a3, CS_SA_areg // load actual return address - extui a4, a4, 30, 2 // top 2 bits of ret addr - blti a4, 2, .Lendcr - l32i a5, a1, 4 // a5 <- caller caller a1 - slli a4, a4, 4 - sub a4, a5, a4 // a4 <- bottom of extra save area - addi a5, a5, -16 // a5 <- top of extra save area - addi a6, a3, CS_SA_caller_regs + 32 // location to start restore from -.Lcrloop: - l32i a7, a6, 0 // Restore in groups of 4 registers - l32i a8, a6, 4 - s32i a7, a4, 0 - s32i a8, a4, 4 - l32i a7, a6, 8 - l32i a8, a6, 12 - s32i a7, a4, 8 - s32i a8, a4, 12 - addi a4, a4, 16 - addi a6, a6, 16 - blt a4, a5, .Lcrloop -.Lendcr: -#endif - - // Restore timers and CCOUNT right before enabling interrupts. We will - // try to restore any timer interrupts that were pending (as indicated - // by the INTERRUPT register) at the time of the state save. -#if XCHAL_HAVE_CCOUNT - .macro restore_timer num intr - l32i a5, a3, CS_SA_ccompare + 4*\num // Load CCOMPARE value - l32i a6, a3, CS_SA_interrupt // Load old INTERRUPT value - writesr ccompare \num a5 // Restore CCOMPARE - bbci.l a6, \intr, .Lrtdone\num // Intr not set for this timer - addi a5, a5, -1 // CCOUNT = CCOMPARE - 1 -.Lrttry\num: - wsr.ccount a5 // Set CCOUNT and wait - esync - nop - rsr.interrupt a6 - bbci.l a6, \intr, .Lrttry\num // If intr not set then retry -.Lrtdone\num: - .endm - -#if XCHAL_NUM_TIMERS > 0 - restore_timer 0 XCHAL_TIMER0_INTERRUPT -#endif -#if XCHAL_NUM_TIMERS > 1 - restore_timer 1 XCHAL_TIMER1_INTERRUPT -#endif -#if XCHAL_NUM_TIMERS > 2 - restore_timer 2 XCHAL_TIMER2_INTERRUPT -#endif -#if XCHAL_NUM_TIMERS > 3 - restore_timer 3 XCHAL_TIMER3_INTERRUPT -#endif - - // Attempt to clear any spurious timer interrupts caused by the CCOUNT - // dance above. -#if XCHAL_NUM_TIMERS > 0 - l32i a5, a3, CS_SA_ccount // Restore CCOUNT - wsr.ccount a5 - l32i a5, a3, CS_SA_interrupt // Load old intr value - bbsi.l a5, XCHAL_TIMER0_INTERRUPT, .Lx1 // Skip if timer0 intr set - rsr.ccompare0 a6 // Force timer0 intr clear - wsr.ccompare0 a6 -.Lx1: -#if XCHAL_NUM_TIMERS > 1 - bbsi.l a5, XCHAL_TIMER1_INTERRUPT, .Lx2 // Skip if timer1 intr set - rsr.ccompare1 a6 // Force timer1 intr clear - wsr.ccompare1 a6 -.Lx2: -#endif -#if XCHAL_NUM_TIMERS > 2 - bbsi.l a5, XCHAL_TIMER2_INTERRUPT, .Lx3 // Skip if timer2 intr set - rsr.ccompare2 a6 // Force timer2 intr clear - wsr.ccompare2 a6 -.Lx3: -#endif -#if XCHAL_NUM_TIMERS > 3 - bbsi.l a5, XCHAL_TIMER3_INTERRUPT, .Lx4 // Skip if timer3 intr set - rsr.ccompare3 a6 // Force timer3 intr clear - wsr.ccompare3 a6 -.Lx4: -#endif -#endif - - l32i a5, a3, CS_SA_ccount // Restore CCOUNT again - wsr.ccount a5 -#endif - -#if XCHAL_HAVE_INTERRUPTS - rsil a6, 15 // disable interrupts before enabling with INTENABLE - l32i a5, a3, CS_SA_intenable - wsr.intenable a5 - movi a4, XCHAL_INTTYPE_MASK_SOFTWARE // restore any pending software interrupts - l32i a5, a3, CS_SA_interrupt - and a5, a5, a4 - wsr.intset a5 - rsync -#endif - - //l32i a0, a3, CS_SA_restore_label // _xtos_core_save_common's return PC -#if XCHAL_HAVE_INTERRUPTS || XCHAL_HAVE_EXCEPTIONS - //l32i a4, a3, CS_SA_ps - l32i a5, a3, CS_SA_epc1 - wsr.epc1 a5 - l32i a5, a3, CS_SA_excsave1 - wsr.excsave1 a5 -# ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR - l32i a5, a3, CS_SA_depc - wsr.depc a5 -# endif - //wsr.ps a4 // PS restored by caller - //rsync -#endif - -#if XCHAL_HAVE_PSO_CDM - // As late as possible, wait for debug to wakeup, and clear PWRCTL.ShutProcOffOnPWait. - movi a4, XDM_MISC_PWRCTL - rer a5, a4 // read pwrctl - - // Wait for debug powerup to complete (if started): - bbci.l a5, PWRCTL_DEBUG_WAKEUP_SHIFT, 1f - movi a7, XDM_MISC_PWRSTAT -2: rer a6, a7 // read PWRSTAT - bbci.l a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b // loop until debug is powered up -1: - - movi a7, ~PWRCTL_CORE_SHUTOFF // aka ShutProcOffOnPWait - and a5, a5, a7 // clear ShutProcOffOnPWait bit - wer a5, a4 // update pwrctl -#endif - - movi a4, 0 - s32i a4, a3, CS_SA_signature // make sure save area is marked as no longer valid -#if XCHAL_DCACHE_IS_WRITEBACK - dhwb a3, CS_SA_signature -#endif - ret // return from _xtos_core_save_common - // NOTE: a2 holds return value as specified to - // _xtos_core_restore() - - .size _xtos_core_restore_nw, . - _xtos_core_restore_nw - diff --git a/src/arch/xtensa/xtos/core-save.S b/src/arch/xtensa/xtos/core-save.S deleted file mode 100644 index 2312404c84ba..000000000000 --- a/src/arch/xtensa/xtos/core-save.S +++ /dev/null @@ -1,763 +0,0 @@ -// core-save.S -- core state save/restore routines (used by PSO) -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/core-save.S#1 $ - -// Copyright (c) 2012-2013 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/xdm-regs.h> -#include <xtensa/xtruntime-core-state.h> -#include <xtensa/mpuasm.h> -#include "xtos-internal.h" - -.weak _idma_pso_save -//.type xtos_C_core_save, @function - - - .text - - - // (Place this alternate entry symbol *outside* the _xtos_core_save() - // function, to avoid confusing debugging / profiling / etc.) - .align 4 - .global _xtos_core_save_entry - .type _xtos_core_save_entry,@function -_xtos_core_save_entry: - j .Lcore_save - .size _xtos_core_save_entry, . - _xtos_core_save_entry - - - // int _xtos_core_save(unsigned flags, XtosCoreState *savearea, void *code) - // - // Generic processor state save routine. - // - // On entry (after ENTRY if windowed): - // a0 = return PC - // a2 = flags argument - // a3 = ptr to save area - // a4 = ptr to code to jump to after save (just return if 0) - // Returns: - // 0 when first returning from this call (if a4 == 0) - // non-zero (passed from restore call) when returning from restore - // (if a4 != 0, return behavior if any depends on code at a4) - // - .align 4 - .global _xtos_core_save - .type _xtos_core_save,@function -_xtos_core_save: - abi_entry - -.Lcore_save: - s32i a0, a3, CS_SA_areg + 0*4 // save a0 (clobbered below) - s32i a1, a3, CS_SA_areg + 1*4 // save a1 - s32i a2, a3, CS_SA_areg + 2*4 // save a2 (flags arg, for debugging only) - s32i a4, a3, CS_SA_areg + 4*4 // save a4 (code to jump to after saving) -#ifdef __XTENSA_CALL0_ABI__ - // Callee-saved regs: - s32i a12, a3, CS_SA_areg + 12*4 // save a12 - s32i a13, a3, CS_SA_areg + 13*4 // save a13 - s32i a14, a3, CS_SA_areg + 14*4 // save a14 - s32i a15, a3, CS_SA_areg + 15*4 // save a15 -#else - call4 xthal_window_spill // spill live caller windows to stack -#endif - j .Ls1 - - .align 16 -.Ls1: -#if XCHAL_HAVE_INTERRUPTS - rsil a4, 15 // disable interrupts before clobbering a0 -#elif XCHAL_HAVE_EXCEPTIONS - rsr.ps a4 -#endif - -#if XCHAL_HAVE_EXCEPTIONS - s32i a4, a3, CS_SA_ps // save PS -#endif - -#if XCHAL_HAVE_IDMA - movi a4, _idma_pso_save - beqz a4, .LnoIDMA -# ifdef __XTENSA_CALL0_ABI__ - mov a13, a3 - mov a12, a2 - addi a3, a3, CS_SA_idmaregs // location for IDMA regs save - call0 _idma_pso_save - mov a3, a13 - mov a2, a12 -# else - mov a6, a2 - addi a7, a3, CS_SA_idmaregs // location for IDMA regs save - call4 _idma_pso_save -# endif -.LnoIDMA: -#endif - -// not yet implemented -//# ifdef __XTENSA_CALL0_ABI__ -// mov a13, a3 -// mov a12, a2 -// call0 xtos_C_core_save -// mov a3, a13 -// mov a2, a12 -//# else -// mov a6, a2 -// mov a7, a3 -// call4 xtos_C_core_save -//# endif -//#endif - -#if XCHAL_HAVE_CCOUNT - rsr.ccount a5 // save CCOUNT restore value -#endif -#if XCHAL_HAVE_INTERRUPTS - rsr.interrupt a6 // save pending interrupts - s32i a6, a3, CS_SA_interrupt -#endif -#if XCHAL_HAVE_CCOUNT - s32i a5, a3, CS_SA_ccount -#endif - - call0 _xtos_core_save_common // save and shutoff -- returns after wakeup - - // a2 now contains return value. - // a3 still points to save area. - // Interrupts still disabled. - - // Restore WINDOWSTART to single window. Leave WINDOWBASE wherever it is. - //rsr.windowbase a6 - //movi a5, 1 - //ssl a6 - //sll a5, a5 - //wsr.windowstart a5 - //rsync - - l32i a0, a3, CS_SA_areg + 0*4 // restore a0 - l32i a1, a3, CS_SA_areg + 1*4 // restore a1 -#ifdef __XTENSA_CALL0_ABI__ - // Callee-saved regs: - l32i a12, a3, CS_SA_areg + 12*4 // restore a12 - l32i a13, a3, CS_SA_areg + 13*4 // restore a13 - l32i a14, a3, CS_SA_areg + 14*4 // restore a14 - l32i a15, a3, CS_SA_areg + 15*4 // restore a15 -#endif - -#if XCHAL_HAVE_EXCEPTIONS - // Now that we've restored windowed state (a0,a1), we can restore interrupts. - l32i a4, a3, CS_SA_ps // restore ps - wsr.ps a4 - rsync -#endif - - abi_return - - - - // Generic processor state save routine, callable from assembly-level - // (Does not assume valid stack, saves all ARs, no window-spill etc.) - // - // On entry: - // a0 = return PC - // a2 = flags argument - // a3 = ptr to save area - // a4 = ptr to code to jump to after save (just return if 0) - // All other registers are saved. - // Returns: - // 0 when first returning from this call (if a4 == 0) - // non-zero (passed from restore call) when returning from restore - // (if a4 != 0, return behavior if any depends on code at a4) - // - .align 4 - .global _xtos_core_save_nw -_xtos_core_save_nw: - s32i a0, a3, CS_SA_areg + 0*4 // save a0 (clobbered below) - s32i a1, a3, CS_SA_areg + 1*4 // save a1 - s32i a2, a3, CS_SA_areg + 2*4 // save a2 (flags arg, for debugging only) - s32i a4, a3, CS_SA_areg + 4*4 // save a4 (code to jump to after saving) - s32i a5, a3, CS_SA_areg + 5*4 // save a5 - s32i a6, a3, CS_SA_areg + 6*4 // save a6 - s32i a7, a3, CS_SA_areg + 7*4 // save a7 - j .Ls2 - - .align 16 -.Ls2: -#if XCHAL_HAVE_INTERRUPTS - rsil a4, 15 // disable interrupts before rotating etc -#elif XCHAL_HAVE_EXCEPTIONS - rsr.ps a4 -#endif - -#if XCHAL_HAVE_EXCEPTIONS - s32i a4, a3, CS_SA_ps // save PS -#endif - -#if XCHAL_HAVE_CCOUNT - rsr.ccount a5 // save CCOUNT restore value -#endif -#if XCHAL_HAVE_INTERRUPTS - rsr.interrupt a6 // save pending interrupts - s32i a6, a3, CS_SA_interrupt -#endif -#if XCHAL_HAVE_CCOUNT - s32i a5, a3, CS_SA_ccount -#endif - -#if XCHAL_HAVE_WINDOWED - movi a5, XCHAL_NUM_AREGS / 8 - 1 // number of 8-reg chunks to save (a0-a7 already done) -#endif -1: s32i a8, a3, CS_SA_areg + 8*4 // save a8 - s32i a9, a3, CS_SA_areg + 9*4 // save a9 - s32i a10,a3, CS_SA_areg + 10*4 // save a10 - s32i a11,a3, CS_SA_areg + 11*4 // save a11 - s32i a12,a3, CS_SA_areg + 12*4 // save a12 - s32i a13,a3, CS_SA_areg + 13*4 // save a13 - s32i a14,a3, CS_SA_areg + 14*4 // save a14 - s32i a15,a3, CS_SA_areg + 15*4 // save a15 -#if XCHAL_HAVE_WINDOWED - addi a11, a3, 8*4 // next frame (a11 will become a3, a13 become a5) - addi a13, a5, -1 - rotw 2 - bnez a5, 1b // loop until all frames done - rotw 2 // back to starting windowbase -#endif - - movi a1, 0 // not to save any regs from stack - call0 _xtos_core_save_common - - // a2 now contains return value. - // a3 still points to save area. - // Interrupts still disabled. - -#if XCHAL_HAVE_WINDOWED - rotw -2 - movi a5, XCHAL_NUM_AREGS / 8 - 1 // 8-reg chunks to restore (a0-a7 already done) - addi a3, a11, XCHAL_NUM_AREGS * 4 -1: rotw -2 - addi a3, a11, -8*4 - addi a5, a13, -1 -#endif - l32i a8, a3, CS_SA_areg + 8*4 // restore a8 - l32i a9, a3, CS_SA_areg + 9*4 // restore a9 - l32i a10,a3, CS_SA_areg + 10*4 // restore a10 - l32i a11,a3, CS_SA_areg + 11*4 // restore a11 - l32i a12,a3, CS_SA_areg + 12*4 // restore a12 - l32i a13,a3, CS_SA_areg + 13*4 // restore a13 - l32i a14,a3, CS_SA_areg + 14*4 // restore a14 - l32i a15,a3, CS_SA_areg + 15*4 // restore a15 -#if XCHAL_HAVE_WINDOWED - bnez a5, 1b // loop until all frames done - // We're now back to starting windowbase, and original a3. -#endif - - l32i a0, a3, CS_SA_areg + 0*4 // restore a0 - l32i a1, a3, CS_SA_areg + 1*4 // restore a1 - // Don't clobber return value, so don't restore a2. - l32i a4, a3, CS_SA_areg + 4*4 // restore a4 - l32i a5, a3, CS_SA_areg + 5*4 // restore a5 - l32i a6, a3, CS_SA_areg + 6*4 // restore a6 -#if XCHAL_HAVE_EXCEPTIONS - // Now that we've restored windowed state (a0,a1,done rotating), we can restore interrupts. - l32i a7, a3, CS_SA_ps // restore ps - wsr.ps a7 - rsync -#endif - l32i a7, a3, CS_SA_areg + 7*4 // restore a7 - ret - - - - - // Common state save / shut-off code. - // - // a0 = return PC within caller shut-off routine - // a1 = stack if != 0 - // a2 = flags argument - // a3 = pointer to _xtos_pso_savearea - // a4 = PS to save/restore - // PS.INTLEVEL = 15 (interrupts disabled, except NMI) - // a5-a15 (and other ARs) are available. - // NOTE: CCOUNT and INTERRUPT have already been saved in save area. - // - .align 4 - //.global _xtos_core_save_common -_xtos_core_save_common: -//#if XCHAL_HAVE_EXCEPTIONS -// s32i a4, a3, CS_SA_ps // save PS -//#endif - -#if XCHAL_HAVE_CACHE_BLOCKOPS - pfend.o // terminate non-essential block-prefetch ops -#endif - -#if XCHAL_HAVE_WINDOWED - // The following discussion is valid if we have a stack: - // At this point, all non-live register windows have been spilled to the - // stack. However, we cannot leave any spilled registers in our stack frame - // or our caller's stack frame, since these frames could change after we - // return and before restore() is called. So all spilled registers in the - // current and previous stack frames must be saved to the save area. This - // means a max of 16 registers: 4 base save registers for our caller, upto - // 8 extra save registers for our caller, and 4 base save registers for the - // next function up from our caller. The stack looks like this: - // - // ------------------------------- <---- stack ptr of function (i - 2) - // Base save area i - 3 - // ------------------------------- - // Extra save area i - 1 - // (0-8 registers depending on call type) - // ------------------------------- - // Locals i - 1 - // ------------------------------- <---- stack ptr of function (i - 1) - // Base save area i - 2 (our caller) - // - // ------------------------------- <---- Our stack ptr (a1) - // Base save area i - 1 - // ------------------------------- - // - // We don't have any extra save area or locals in our frame. See the - // Xtensa Programmer's Guide for more details of the stack layout. - // - // NOTE that we are not counting the call0 to _xtos_core_save_common() since - // that does not result in any register window rotation nor stack ptr change. - - s32i a1, a3, CS_SA_caller_regs_saved // save flag - beqz a1, .Lendcr // skip if no stack - - // Save our caller's a0-a3 from the base save area (a1-16) - - addi a4, a1, -16 - l32i a5, a4, 0 - l32i a6, a4, 4 - s32i a5, a3, CS_SA_caller_regs // caller a0 - s32i a6, a3, CS_SA_caller_regs + 4 // caller a1 - l32i a5, a4, 8 - l32i a6, a4, 12 - s32i a5, a3, CS_SA_caller_regs + 8 // caller a2 - s32i a6, a3, CS_SA_caller_regs + 12 // caller a3 - - // Save our callers caller's a0-a3 from its base save area (a1+0) - - l32i a5, a1, 0 - l32i a6, a1, 4 - s32i a5, a3, CS_SA_caller_regs + 16 // caller caller a0 - s32i a6, a3, CS_SA_caller_regs + 20 // caller caller a1 - l32i a5, a1, 8 - l32i a6, a1, 12 - s32i a5, a3, CS_SA_caller_regs + 24 // caller caller a2 - s32i a6, a3, CS_SA_caller_regs + 28 // caller caller a3 - - // Now save 0-8 registers for our caller from its ext save area - // NOTE we can't use a0 directly because we are one level down - - l32i a4, a3, CS_SA_areg // pull in the return address - extui a4, a4, 30, 2 // Top 2 bits of ret addr - blti a4, 2, .Lendcr // No regs to save - l32i a5, a1, 4 // a5 <- caller caller a1 - slli a4, a4, 4 - sub a4, a5, a4 // a4 <- bottom of extra save area - addi a5, a5, -16 // a5 <- top of extra save area - addi a6, a3, CS_SA_caller_regs + 32 // location to start saving to -.Lcrloop: - l32i a7, a4, 0 // Save in groups of 4 registers - l32i a8, a4, 4 - s32i a7, a6, 0 - s32i a8, a6, 4 - l32i a7, a4, 8 - l32i a8, a4, 12 - s32i a7, a6, 8 - s32i a8, a6, 12 - addi a4, a4, 16 - addi a6, a6, 16 - blt a4, a5, .Lcrloop -.Lendcr: -#endif - - // We want to save the CCOUNT value as soon as feasible after disabling - // interrupts, so that the counter does not run past any CCOMPARE value - // and miss a timer interrupt. The callers of this function have saved - // the values of CCOUNT and INTERRUPT immediately after disabling interrupts. - -#if XCHAL_HAVE_CCOUNT - .set _idx, 0 - .rept XCHAL_NUM_TIMERS - INDEX_SR rsr.ccompare a5 - s32i a5, a3, CS_SA_ccompare + 4*_idx - .set _idx, _idx+1 - .endr -#endif - - s32i a0, a3, CS_SA_restore_label // where to return to, to return from function -#if XCHAL_HAVE_INTERRUPTS || XCHAL_HAVE_EXCEPTIONS - rsr.epc1 a5 - s32i a5, a3, CS_SA_epc1 - rsr.excsave1 a5 - s32i a5, a3, CS_SA_excsave1 -# ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR - rsr.depc a5 - s32i a5, a3, CS_SA_depc -# endif -#endif -#if XCHAL_HAVE_WINDOWED - rsr.windowbase a5 - s32i a5, a3, CS_SA_windowbase // save windowbase - rsr.windowstart a5 - s32i a5, a3, CS_SA_windowstart // save windowstart -#endif - rsr.sar a5 - s32i a5, a3, CS_SA_sar // save sar - -#if XCHAL_HAVE_PSO_CDM - // Save PWRCTL, and update according to flags argument. - movi a4, XDM_MISC_PWRCTL - movi a6, PWRCTL_MEM_WAKEUP - rer a7, a4 // get pwrctl - s32i a7, a3, CS_SA_pwrctl // save pwrctl - // Avoid setting power-control bits if not already set, i.e. clear them only. - bbci.l a2, XTOS_COREF_PSO_SHIFT, 1f // if not shutting off, don't touch power bits - - // Set PWRCTL MEM_WAKEUP bit according to flags (whether to let mem power off). - or a5, a7, a6 // set... - xor a5, a5, a6 // ... and clear MEM_WAKEUP bit to write - and a6, a2, a6 // isolate MEM_WAKEUP bit from flags - or a5, a5, a6 // set MEM_WAKEUP bit to write from flags - // Clear PWRCTL DEBUG_WAKEUP bit if cleared in flags (if letting debug power off). - movi a6, ~PWRCTL_DEBUG_WAKEUP - or a6, a2, a6 // isolate DEBUG_WAKEUP bit from flags - and a6, a5, a6 // clear it if was clear in flags - // Update PWRCTL - wer a6, a4 // write new pwrctl - //extw // let the new pwrctl value settle -1: -#endif - - .set _idx, 2 - .rept XCHAL_NUM_INTLEVELS+XCHAL_HAVE_NMI-1 - INDEX_SR rsr.epc a5 - s32i a5, a3, CS_SA_epc + 4*(_idx-2) - INDEX_SR rsr.eps a5 - s32i a5, a3, CS_SA_eps + 4*(_idx-2) - INDEX_SR rsr.excsave a5 - s32i a5, a3, CS_SA_excsave + 4*(_idx-2) - .set _idx, _idx+1 - .endr - -#if XCHAL_HAVE_LOOPS - rsr.lbeg a5 - s32i a5, a3, CS_SA_lbeg - rsr.lend a5 - s32i a5, a3, CS_SA_lend - rsr.lcount a5 - s32i a5, a3, CS_SA_lcount -#endif -#if XCHAL_HAVE_ABSOLUTE_LITERALS - rsr.litbase a5 - s32i a5, a3, CS_SA_litbase -#endif -#if XCHAL_HAVE_VECBASE - rsr.vecbase a5 - s32i a5, a3, CS_SA_vecbase -#endif -#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) /* have ATOMCTL ? */ - rsr.atomctl a5 - s32i a5, a3, CS_SA_atomctl -#endif -#if XCHAL_HAVE_PREFETCH - movi a5, 0 // disable prefetch during shutoff - xsr.prefctl a5 - s32i a5, a3, CS_SA_prefctl -#endif -#if XCHAL_USE_MEMCTL - rsr.memctl a5 - s32i a5, a3, CS_SA_memctl -#endif -#if XCHAL_HAVE_INTERRUPTS - rsr.intenable a5 - s32i a5, a3, CS_SA_intenable -#endif -#if XCHAL_HAVE_DEBUG - // NOTE: restore of debug state is conditional, - // as the power-down and wakeup code might be actively debugged. - rsr.icount a5 - s32i a5, a3, CS_SA_icount - rsr.icountlevel a5 - s32i a5, a3, CS_SA_icountlevel - rsr.debugcause a5 - s32i a5, a3, CS_SA_debugcause // (won't get restored?) - //rsr.ddr a5 - //s32i a5, a3, CS_SA_ddr -# if XCHAL_NUM_IBREAK - rsr.ibreakenable a5 - s32i a5, a3, CS_SA_ibreakenable -# endif - .set _idx, 0 - .rept XCHAL_NUM_IBREAK - INDEX_SR rsr.ibreaka a5 - s32i a5, a3, CS_SA_ibreaka + 4*_idx - .set _idx, _idx+1 - .endr - .set _idx, 0 - .rept XCHAL_NUM_DBREAK - INDEX_SR rsr.dbreakc a5 - s32i a5, a3, CS_SA_dbreakc + 4*_idx - INDEX_SR rsr.dbreaka a5 - s32i a5, a3, CS_SA_dbreaka + 4*_idx - .set _idx, _idx+1 - .endr -#endif - - .set _idx, 0 - .rept XCHAL_NUM_MISC_REGS - INDEX_SR rsr.misc a5 - s32i a5, a3, CS_SA_misc + 4*_idx - .set _idx, _idx+1 - .endr - -#if XCHAL_HAVE_MEM_ECC_PARITY - rsr.mepc a5 - s32i a5, a3, CS_SA_mepc - rsr.meps a5 - s32i a5, a3, CS_SA_meps - rsr.mesave a5 - s32i a5, a3, CS_SA_mesave - rsr.mesr a5 - s32i a5, a3, CS_SA_mesr - rsr.mecr a5 - s32i a5, a3, CS_SA_mecr - rsr.mevaddr a5 - s32i a5, a3, CS_SA_mevaddr -#endif - - /* TIE state */ - addi a4, a3, CS_SA_ncp - xchal_ncp_store a4, a5,a6,a7,a8 // save non-coprocessor state -#if XCHAL_HAVE_CP - rsr.cpenable a5 - s32i a5, a3, CS_SA_cpenable - movi a6, -1 - wsr.cpenable a6 // enable all coprocessors - rsync - xchal_cp0_store a4, a5,a6,a7,a8 continue=1 - xchal_cp1_store a4, a5,a6,a7,a8 continue=1 - xchal_cp2_store a4, a5,a6,a7,a8 continue=1 - xchal_cp3_store a4, a5,a6,a7,a8 continue=1 - xchal_cp4_store a4, a5,a6,a7,a8 continue=1 - xchal_cp5_store a4, a5,a6,a7,a8 continue=1 - xchal_cp6_store a4, a5,a6,a7,a8 continue=1 - xchal_cp7_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp8_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp9_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp10_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp11_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp12_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp13_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp14_store a4, a5,a6,a7,a8 continue=1 - //xchal_cp15_store a4, a5,a6,a7,a8 continue=1 -#endif - - /* TLB state (for known MMU types only, not internal custom) */ -#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR - addi a4, a3, CS_SA_tlbs // where to start storing TLB entry info - movi a5, 0x20000000 - movi a6, 0 -1: rdtlb1 a7, a6 // read DTLB entry PPN + CA - s32i a7, a4, 0 - ritlb1 a7, a6 // read ITLB entry PPN + CA - s32i a7, a4, 4 - addi a4, a4, 8 - add a6, a6, a5 - bnez a6, 1b - -#elif XCHAL_HAVE_PTP_MMU - // Declare a table of TLB entries to save/restore. - // Each entry is a 32-bit index to use directly with [rw][di]tlb[01]. - // Indices assume ITLBCFG == DTLBCFG == 0. - // Bit 4 means not-for-dtlb, and bit 5 means not-for-itlb - // (these bits aren't used by these instructions, so okay to use for this). - .section .rodata, "a" - .global _xtos_pso_tlbmap - .global _xtos_pso_tlbmap_end - .type _xtos_pso_tlbmap, @object -_xtos_pso_tlbmap: - .long 0x0C0C0C0C, ARF_ENTRIES // *TLB way 0, 4/8 entries of 4KB - .long 0x0C0C0C0C, ARF_ENTRIES // *TLB way 1, 4/8 entries of 4KB - .long 0x0C0C0C0C, ARF_ENTRIES // *TLB way 2, 4/8 entries of 4KB - .long 0x0C0C0C0C, ARF_ENTRIES // *TLB way 3, 4/8 entries of 4KB - .long 0x1A181614, 4 // *TLB way 4, 4 entries of 1MB/4MB/16MB/64MB -# if XCHAL_HAVE_SPANNING_WAY /* MMU v3 */ - .long 0x1C1B1C1B, 4 // *TLB way 5, 4 entries of 128MB/256MB - .long 0x1B1D1B1D, 8 // *TLB way 6, 8 entries of 512MB/128MB -# endif - .long 0x0C0C0C0C, 0x8001 // DTLB way 7, 1 entry of 4KB - .long 0x0C0C0C0C, 0x8001 // DTLB way 8, 1 entry of 4KB - .long 0x0C0C0C0C, 0x8001 // DTLB way 9, 1 entry of 4KB -_xtos_pso_tlbmap_end: - .size _xtos_pso_tlbmap, . - _xtos_pso_tlbmap - - .text - addi a4, a3, CS_SA_tlbs // where to start storing TLB entry info - movi a10, _xtos_pso_tlbmap - movi a11, _xtos_pso_tlbmap_end - rsr.dtlbcfg a14 // page size index (0..3) for each DTLB way - rsr.itlbcfg a15 // page size index (0..3) for each ITLB way - s32i a14, a3, CS_SA_dtlbcfg - s32i a15, a3, CS_SA_itlbcfg - rsr.ptevaddr a5 - s32i a5, a3, CS_SA_ptevaddr - rsr.rasid a5 - s32i a5, a3, CS_SA_rasid - // Loop from last way to first (less register pressure that way). -.Loop_tlbmap: - addi a11, a11, -8 // next way - l32i a8, a11, 0 // map of four (page size log2) per index for this way - // DTLB page size: - extui a12, a14, 0, 4 // page size index for this DTLB way - srli a14, a14, 4 // (for next way) - ssa8l a12 // prepare to shift right by 8*a12 - srl a12, a8 // page size log2 for this DTLB way - ssl a12 // prepare to shift left by a12 - movi a12, 1 // (to compute 1 << (page size log2)) - sll a12, a12 // page size for this DTLB way - - // Save all entries of this DTLB way: - l32i a9, a11, 4 // number of entries for this way - sub a5, a11, a10 // way number * 8 - srli a5, a5, 3 // way number - extui a9, a9, 0, 8 -1: rdtlb0 a6, a5 // read DTLB entry VPN + ASID ... - rdtlb1 a7, a5 // read DTLB entry PPN + CA ... - add a5, a5, a12 // next entry of this DTLB way - s32i a6, a4, 0 // save entry ... - s32i a7, a4, 4 - addi a4, a4, 8 - addi a9, a9, -1 - bnez a9, 1b - - // ITLB page size: - extui a12, a15, 0, 4 // page size index for this ITLB way - srli a15, a15, 4 // (for next way) - ssa8l a12 // prepare to shift right by 8*a12 - srl a12, a8 // page size log2 for this ITLB way - ssl a12 // prepare to shift left by a12 - movi a12, 1 // (to compute 1 << (page size log2)) - sll a12, a12 // page size for this ITLB way - - // Save all entries of this ITLB way: - l32i a9, a11, 4 // number of entries for this way - sub a5, a11, a10 // way number * 8 - srli a5, a5, 3 // way number - bbsi.l a9, 15, 2f // skip ITLB if is a DTLB-only way - extui a9, a9, 0, 8 -1: ritlb0 a6, a5 // read ITLB entry VPN + ASID ... - ritlb1 a7, a5 // read ITLB entry PPN + CA ... - add a5, a5, a12 // next entry of this ITLB way - s32i a6, a4, 0 // save entry ... - s32i a7, a4, 4 - addi a4, a4, 8 - addi a9, a9, -1 - bnez a9, 1b -2: - bne a11, a10, .Loop_tlbmap // loop for next TLB way - // Done saving TLBs. -#endif - -#if XCHAL_HAVE_CACHE_BLOCKOPS - pfwait.a // wait for any remaining block-prefetch ops -#endif - -#if XCHAL_HAVE_MPU - addi a4, a3, CS_SA_mpuentry // location for MPU save - mpu_read_map a4, a5, a6 - rsr.cacheadrdis a4 - addi a5, a3, CS_SA_cacheadrdis - s32i a4, a5, 0 - -#if XCHAL_DCACHE_IS_WRITEBACK - // Must write this piece back to memory, because if it stays - // in the cache and we try to restore with caches bypassed, - // the wrong values will be fetched from memory. - // TODO: See if possible to replace with call to xthal_dcache_region_writeback - // TODO: If going to write back full dcache below, skip this step - addi a4, a3, CS_SA_mpuentry - movi a5, CS_SA_ncp - CS_SA_mpuentry - dcache_writeback_region a4, a5, a7, a8 -#endif -#endif - - // With data cache coherency enabled, need a full data cache - // writeback and invalidate, then disable coherency, before shut-off. - // Otherwise, if we'll let dcache power off, writeback its contents. - // - // We make sure the signature only gets written after everything - // else is written back (if we writeback), and only gets written - // back if the rest gets written back. - movi a6, CORE_STATE_SIGNATURE -#if XCHAL_DCACHE_IS_WRITEBACK -# if XCHAL_HAVE_PSO_CDM && XCHAL_DCACHE_IS_COHERENT && XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0 - rsr.memctl a4 - bbci.l a2, XTOS_COREF_PSO_SHIFT, 1f // if not shutting off, leave snoops as is - bbci.l a4, MEMCTL_SNOOP_EN_SHIFT, 1f // snoops (coherence) enabled? - dcache_writeback_inv_all a4, a5, a7, 0 // yes: writeback-invalidate - memw // wait for writeback to complete - s32i a6, a3, CS_SA_signature - dhwbi a3, CS_SA_signature - // Now that dcache is empty, make sure snoops are off during shut-off. - addi a4, a4, -MEMCTL_SNOOP_EN - wsr.memctl a4 - j 9f -1: -# endif - bbsi.l a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f // letting caches power off? - dcache_writeback_all a4, a5, a7, 0 // yes: writeback - memw // wait for writeback to complete - j 8f - - // The signature and the cache/TLB state must be written out to - // main memory even though the caches stay on, because on restart - // we will come up with caches bypassed and need to read the state - // back before the cache/TLB is set up. -7: - mov a4, a3 - movi a5, CS_SA_ncp - dcache_writeback_region a4, a5, a7, a8 - memw -8: - s32i a6, a3, CS_SA_signature - dhwb a3, CS_SA_signature // needed even if caches stay on -#else - s32i a6, a3, CS_SA_signature -#endif - -9: l32i a4, a3, CS_SA_areg + 4*4 // restore a4 (code to jump to after saving) - memw // wait for signature to be in memory - - beqz a4, 1f // code to jump to? - jx a4 // yes, jump to it -1: l32i a0, a3, CS_SA_restore_label // no, return: restore return PC - movi a2, 0 // return 0 - ret - - - .size _xtos_core_save, . - _xtos_core_save - diff --git a/src/arch/xtensa/xtos/core-shutoff.S b/src/arch/xtensa/xtos/core-shutoff.S deleted file mode 100644 index c848e38ca1ab..000000000000 --- a/src/arch/xtensa/xtos/core-shutoff.S +++ /dev/null @@ -1,425 +0,0 @@ -// reset-pso.S -- PSO restore routine, invoked from Reset Vector -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/core-shutoff.S#1 $ - -// Copyright (c) 2012-2013 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/xdm-regs.h> -#include <xtensa/xtruntime-core-state.h> -#include "xtos-internal.h" - -#if XCHAL_HAVE_PSO - .macro simulate_reset - // Single or multiple power domains, no retention. - // Just simulate reset. Set PS: - movi a5, 0x1F - wsr.ps a5 - rsync - // Scramble things: - rotw 3 - // Jump to reset vector: - movi a5, _ResetVector - jx a5 - .endm -#endif - - -#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION - // PSO: core state save area. - // This could be pretty large (includes TIE state, TLB state, many regs). - // - .section .bss, "aw" - .align XCHAL_TOTAL_SA_ALIGN - .global _xtos_pso_savearea - .type _xtos_pso_savearea, @object - .size _xtos_pso_savearea, XtosCoreStateSize -_xtos_pso_savearea: - .space XtosCoreStateSize -#endif - - - .text - - - // This version of the _xtos_core_shutoff() function can be called from assembly-level, - // where the stack might not be defined/usable, so can't do window-spill - // etc. This saves address registers per call0 ABI (all except a0/a2..a11). - // - // On entry: a0 = return PC, a2 = flags argument, a3..a11 = undefined/available. - // All other registers are saved/restored. - // - .align 4 - .global _xtos_core_shutoff_nw - .type _xtos_core_shutoff_nw,@function -_xtos_core_shutoff_nw: -#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION - movi a5, _xtos_core_save_nw -#endif - mov a11, a0 // ABI-independent return PC - j .Lcommon_shutoff - .size _xtos_core_shutoff_nw, . - _xtos_core_shutoff_nw - - - - // int _xtos_core_shutoff(unsigned flags) - // - // Save all processor state and shut-off the core. - // Returns when the core wakes up, and all state was restored - // (except in single power domain case, see below). - // - // For more details see: System SW Ref Manual, XTOS Chapter. - // - // Possible return values: - // - // 0 core did shut-off (return via reset vector, - // or after waiti for full-retention case) - // - // 1,2 core did not shut-off (other requestors were already - // requesting this core to stay on at time of call) - // (1 == early, 2 == late) - // - // 3 core did not shut-off (multi-power-domains no retention, - // and waiti resumed; FIXME: can this happen?) - // - // -1 core does not have PSO feature - // - // NOTE: in the single power domain case, this function never returns. - // The external system must power the core off than back on, - // and execution resumes at the reset vector. - // - // The flags parameter indicates whether to request memory and/or debug domains - // to stay powered on while the core is shut-off. (This parameter is ignored - // for the single power domain case.) If 0, they are both allowed to - // shut-off (although other external requesters may keep them powered on). - // Otherwise, one or both of these bits may be specified (or'ed together): - // XTOS_KEEPON_MEM force memory domain on during core power shut-off - // XTOS_KEEPON_DEBUG force debug domain on during core power shut-off - // If XTOS_KEEPON_MEM is specified, dcache writeback is NOT done. - // - // Effectively, the flags parameter sets the value of these two PWRCTL register - // bits (over ERI) during core power shut-off. The value of these two bits - // (as they were prior to calling this function) are saved, and restored on wakeup. - // Thus, if the core was requesting that the debug domain be powered on, and - // _xtos_core_shutoff() lets it power-off, then upon wakeup, the software restore - // sequence restores debug domain power, and waits for debug power to be ON. - // - // - .align 4 - .global _xtos_core_shutoff - .type _xtos_core_shutoff,@function -_xtos_core_shutoff: - abi_entry - -#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION - movi a5, _xtos_core_save_entry -#endif - movi a11, 1f // ABI-independent return PC - j .Lcommon_shutoff - -1: abi_return - - - - - .align 4 -.Lcommon_shutoff: - - - -#if XCHAL_HAVE_PSO_CDM && XCHAL_HAVE_PSO_FULL_RETENTION - // Multiple power domains, full retention in HW. - // Do the minimum required (things that need to be changed during shutoff): - - // Check whether other agents are keeping this core powered on, - // and avoid going through save sequence if we're not going to - // power down anyway. - movi a3, XDM_MISC_PWRSTAT - rer a6, a3 - movi a5, 1 // indicates other agents want this core powered on - bbsi.l a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, 1f - - rsil a8, 15 // disable interrupts - -# if XCHAL_HAVE_PREFETCH - // Save prefetch control and disable prefetch. - movi a10, 0 - xsr.prefctl a10 -# endif - -# if XCHAL_DCACHE_IS_WRITEBACK - bbsi.l a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f // letting caches power off? - dcache_writeback_all a4, a7, a9,0 // yes: writeback - memw // wait for writeback to complete -7: -# endif - - // Save PWRCTL, and set ShutProcOffOnPWait (for WAITI to shut-off the core). - // (With dcache coherence, can this be used as signal to system - // to turn off snoops to this core?) - // - movi a4, XDM_MISC_PWRCTL - rer a9, a4 // get pwrctl - movi a6, PWRCTL_CORE_SHUTOFF // aka ShutProcOffOnPWait - or a7, a9, a6 // indicate WAITI will shut-off - xor a9, a7, a6 // make sure it's clear in saved pwrctl - wer a7, a4 // write new pwrctl - - // Make sure everything stabilizes: - isync - extw - - // With ShutProcOffOnPWait set, external agents can't change their mind. - // So check again whether other agents are keeping this core powered on, - // and avoid going through save sequence if we're not going to - // power down anyway. - rer a6, a3 // read PWRSTAT - movi a5, 2 // if abort: external agent wants core powered on - bbsi.l a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, .Lshutoff_late_abort - - // Set PWRCTL MEM_WAKEUP bit according to flags (whether to let mem power off). - movi a6, PWRCTL_MEM_WAKEUP - or a5, a7, a6 // set... - xor a5, a5, a6 // ... and clear MEM_WAKEUP bit to write - and a6, a2, a6 // isolate MEM_WAKEUP bit from flags - or a5, a5, a6 // set MEM_WAKEUP bit to write from flags - // Clear PWRCTL DEBUG_WAKEUP bit if cleared in flags (if letting debug power off). - movi a6, ~PWRCTL_DEBUG_WAKEUP - or a6, a2, a6 // isolate DEBUG_WAKEUP bit from flags - and a6, a5, a6 // clear it if was clear in flags - // Update PWRCTL - wer a6, a4 // write new pwrctl - extw // let the new pwrctl value settle - - // Okay, go for it -- power down (shutoff). - -# if !XTOS_PSO_TEST - waiti 0 // now shut-off! (interrupts enabled for power-on) -# endif - // Resumes here after power comes back on, after some interrupt taken. - wsr.ps a8 // restore interrupts - movi a5, 0 // successful - rsync // ensure wsr.ps completes - - // FIXME: do we need to initialize caches? - -.Lshutoff_late_abort: - wer a7, a4 // restore pwrctl (except ShutProcOffOnPWait still set) - - // Wait for debug powerup to complete (if started): - bbci.l a7, PWRCTL_DEBUG_WAKEUP_SHIFT, 3f - movi a6, XDM_MISC_PWRSTAT -2: rer a6, a6 // read PWRSTAT - bbci.l a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b // loop until powered up -3: - -# if XCHAL_HAVE_PREFETCH - wsr.prefctl a10 // restore prefetch control -# endif - - // If CachesLostPower bit set, is there need to initialize caches? - - wer a9, a4 // clear ShutProcOffOnPWait - - wsr.ps a8 // restore interrupts - rsync // ensure wsr.ps completes - -1: mov a2, a5 - jx a11 // return (to ABI-dependent code if C callable) - - - -#elif XCHAL_HAVE_PSO_CDM /*&& !XCHAL_HAVE_PSO_FULL_RETENTION*/ - // Multiple power domains, no hardware retention. - // Do full core state save/restore in software. - - // Check whether other agents are keeping this core powered on, - // and avoid going through save sequence if we're not going to - // power down anyway. - movi a3, XDM_MISC_PWRSTAT - rer a3, a3 - bbsi.l a3, PWRSTAT_CORE_STILL_NEEDED_SHIFT, 1f - - movi a3, XTOS_COREF_PSO - or a2, a2, a3 // indicate power shutoff in flags - - movi a3, _xtos_pso_savearea - movi a4, _xtos_core_shutoff_aftersave - jx a5 // continue in _xtos_core_save (past prologue) - // which saves processor state, powers down - // debug/mem per a2, shuts off prefetch and - // snooping, and jumps to a4 - -1: movi a2, 1 // other agents want this core powered on - jx a11 // return (to ABI-dependent code if C callable) - - .align 4 - //.global _xtos_core_shutoff_aftersave -_xtos_core_shutoff_aftersave: - - // Multiple power domains, no retention. - - // Set ShutProcOffOnPWait, for WAITI to shut-off the core. - // (With dcache coherence, can this be used as signal to system - // to turn off snoops to this core?) - // - movi a4, XDM_MISC_PWRCTL - rer a7, a4 // get pwrctl - movi a6, PWRCTL_CORE_SHUTOFF // aka ShutProcOffOnPWait - or a7, a7, a6 // indicate WAITI will shut-off - wer a7, a4 // write new pwrctl - - // Make sure everything stabilizes: - isync - extw - - // Check whether other agents are keeping this core powered on, - // and avoid going through save sequence if we're not going to - // power down anyway. - movi a4, XDM_MISC_PWRSTAT - movi a2, 2 // if abort: external agent wants core powered on - rer a6, a4 - bbsi.l a6, PWRSTAT_CORE_STILL_NEEDED_SHIFT, .Lshutoff_late_abort - - // Call system-specific function to wait for system specific - // transactions to quiesce before shutting down the processor. - // This function may also abort the shutdown, however whoever - // attempts it must do it carefully: the function must know - // that it's possible to abort, it must do whatever's needed - // in the system to resume normal execution (e.g. restart - // snoops, DMA, etc), and for power reasons the software must - // avoid calling this shutdown routine in the first place if - // it can know then that it would end up aborting here. - // - // This is always a call0 function. - // TBD: can it be a C function instead? - // TBD: describe exact calling conventions, if asm call0 - - .weak xtos_system_ready_for_core_shutoff - movi a2, xtos_system_ready_for_core_shutoff - //isync - beqz a2, 1f - callx0 a2 - bnez a2, .Lshutoff_late_abort // if function returns error, abort shutdown -1: - - // Okay, go for it -- power down (shutoff). - - -# if XTOS_PSO_TEST - // Test only -- weakly simulate shutoff in sw, don't actually do it. - simulate_reset -# elif XCHAL_HAVE_INTERRUPTS - waiti 15 // now shut-off! -# elif XCHAL_HAVE_HALT - halt -# else -# error "PSO assumes interrupts (for WAITI) or HALT architecture (for HALT)" -# endif - - // Execution should not proceed here. - // If we get here, some error has occurred [FIXME] - - movi a2, 3 // WAITI resumed - -.Lshutoff_late_abort: - // We end up here if returning from shutoff request. - // Here, a2 == return code. - // Restore what's been clobbered (and doesn't get restored by caller): - // PWRCTL, MEMCTL, return PC. - - l32i a0, a3, CS_SA_restore_label // restore return PC - - // Restore PWRCTL. - movi a4, XDM_MISC_PWRCTL - l32i a5, a3, CS_SA_pwrctl // get saved pwrctl - wer a5, a4 // restore pwrctl - // Wait for debug powerup to complete (if started): - bbci.l a5, PWRCTL_DEBUG_WAKEUP_SHIFT, 1f - movi a7, XDM_MISC_PWRSTAT -2: rer a6, a7 // read PWRSTAT - bbci.l a6, PWRSTAT_DEBUG_DOMAIN_ON_SHIFT, 2b // loop until powered up -1: - - // Restore MEMCTL. -# if XCHAL_USE_MEMCTL - l32i a5, a3, CS_SA_memctl - wsr.memctl a5 -# endif - - // Clear the signature, to mark save area as no longer valid. - s32i a2, a3, CS_SA_signature -# if XCHAL_DCACHE_IS_WRITEBACK - dhwb a3, CS_SA_signature -# endif - - ret // return from _xtos_core_save_common - - - -#elif XCHAL_HAVE_PSO - // Single power domain. (No retention.) - - rsil a8, 15 // disable interrupts - -# if XCHAL_HAVE_PREFETCH - // Disable prefetch. - movi a10, 0 - wsr.memctl a10 -# endif - -# if XCHAL_DCACHE_IS_WRITEBACK - bbsi.l a2, PWRCTL_MEM_WAKEUP_SHIFT, 7f // letting caches power off? - dcache_writeback_all a4, a5, a6, 0 // yes: writeback - memw // wait for writeback to complete -7: -# endif - -1: waiti 15 // wait for shut-off - j 1b // loop until we get powered off - - - -#else - // No PSO. - movi a2, -1 - jx a11 // return (to ABI-dependent code if C callable) - -#endif - - - - -#if XCHAL_HAVE_PSO_CDM -# if XCHAL_HAVE_PSO_FULL_RETENTION - -# else /* not full retention */ - - -# endif /* !retention */ -#endif /* multi power domains */ - - - .size _xtos_core_shutoff, . - _xtos_core_shutoff - diff --git a/src/arch/xtensa/xtos/crt0-app.S b/src/arch/xtensa/xtos/crt0-app.S deleted file mode 100644 index 7f12337fd535..000000000000 --- a/src/arch/xtensa/xtos/crt0-app.S +++ /dev/null @@ -1,174 +0,0 @@ -// crt0-app.S -// Applications downloaded in RAM using a debug monitor (eg. XMON, RedBoot) -// start here at _app_reset. Such applications don't have any vectors: -// all exceptions are handled by the debug monitor. -// Thus, this file essentially plays the role of the reset vector -// to setup a few things before jumping to _start (in crt1*.S). - -// Copyright (c) 2005-2013 Tensilica 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 <xtensa/cacheattrasm.h> -#include <xtensa/coreasm.h> - - -// Assumptions on entry to _app_reset: -// - debug monitor handles all exceptions, has setup all vectors -// - interrupt related state is initialized -// (interrupts disabled or enabled for debug monitor's purposes) -// - debug option related state is initialized (for debug monitor) -// - any MMU related state is initialized (all handled by debug monitor) -// - caches are initialized (cache attributes not necessarily correct) -// - entire application is loaded (no unpacking needed here) - -// Assumptions on exit from _app_reset, ie. when jumping to _start: -// - low (level-one) and medium priority interrupts are disabled -// - C calling context not initialized: -// - PS not fully initialized (eg. PS.WOE not set per ABI) -// - SP not initialized -// - the following are initialized: -// - LITBASE, WindowBase, WindowStart, LCOUNT, CPENABLE, FP's FCR and FSR, -// cache attributes - -/**************************************************************************/ - - .text - .global _app_reset -_app_reset: - /* _app_reset may be required to be located at the beginning of the text - segment. However, the constant pool for _app_reset must be placed - before the code. Jump over the constant pool to solve this. */ - j .LpastInitialConstants - - .literal_position // tells the assembler/linker to place literals here - -.LpastInitialConstants: - // 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. - // - movi a0, 0 // keep this register zero. - -#if XCHAL_HAVE_LOOPS - wsr.lcount a0 // loop count = 0 -#endif /* XCHAL_HAVE_LOOPS */ - - // Interrupts might be enabled, make sure at least medium and low priority - // interrupts are disabled until WindowBase, WindowStart, SP, and the stack - // are all properly setup (which will happen outside this file, after the - // _start label). We leave loops enabled on new exception architecture. -#if XCHAL_HAVE_EXCEPTIONS - movi a2, XCHAL_EXCM_LEVEL - wsr.ps a2 // set PS.INTLEVEL=EXCM_LEVEL, PS.WOE=0, PS.EXCM=0 - rsync -#endif - - // DO THIS FIRST: initialize the window start and base - // before, so that windows don't move under us. -#if XCHAL_HAVE_WINDOWED - // We do this even if we are assembling for the - // call0 abi, but it's not really needed. - movi a2, 1 - wsr.windowstart a2 // window start = 1 - wsr.windowbase a0 // window base = 0 - rsync - - // NOTE: a0 may no longer be zero here, because - // we wrote to WindowBase. So clear it again. - movi a0, 0 -#endif - - // Now, BEFORE we do any L32R (or MOVI with non-immediate - // range which results in an L32R), ensure LITBASE is set - // correctly. This is necessary for RAM applications loaded - // using a target-side debug monitor -- such applications - // don't have a reset vector and start execution at _start. - // (This part is unnecessary if running from a reset vector.) - // The target-side debug monitor might have set LITBASE to - // anything at all, so we cannot rely on its value here. -#if XCHAL_HAVE_ABSOLUTE_LITERALS - wsr.litbase a0 // force PC-relative L32R - rsync -# if XSHAL_USE_ABSOLUTE_LITERALS - .begin no-absolute-literals // use PC-rel L32R to load - movi a2, _lit4_start + 0x40001 // address of absolute literals - .end no-absolute-literals // (see handlers/ResetVector.S - wsr.litbase a2 // for explanation) - rsync -# endif -#endif - - - /* - * Now "enable" the caches. - * - * NOTE: We don't *initialize* the caches here, because the loader - * (eg. target debugger agent / debug monitor, boot code, etc) - * is expected to have initialized them for us. - * - * The _memmap_cacheattr_reset symbol's value (address) is defined - * by the LSP's linker script, as generated by xt-genldscripts. - * - * (NOTE: for configs that don't have CACHEATTR or region protection, - * ie. for full MMUs, there is no equivalent cache attribute layout, - * and the following code has no effect. We assume for now that the - * application restricts itself to the static TLB entries, i.e. to - * virtual addresses 0xD0000000 thru 0xFFFFFFFF.) - */ -#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \ - || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - movi a2, _memmap_cacheattr_reset /* note: absolute symbol, not a ptr */ - cacheattr_set /* set CACHEATTR from a2 (clobbers a3-a8) */ -#endif - - - - // Coprocessor option initialization -#if XCHAL_HAVE_CP - //movi a2, XCHAL_CP_MASK // enable existing CPs - // To allow creating new coprocessors using TC that are not known - // at GUI build time without having to explicitly enable them, - // all CPENABLE bits must be set, even though they may not always - // correspond to a coprocessor. - movi a2, 0xFF // enable *all* bits, to allow dynamic TIE - wsr.cpenable a2 -#endif - - // Floating point coprocessor option initialization -#if XCHAL_HAVE_FP - rsync /* wait for WSR to CPENABLE to complete before accessing FP coproc state */ - wur.fcr a0 /* clear FCR (default rounding mode, round-nearest) */ - wur.fsr a0 /* clear FSR */ -#endif - - - /* NOTE: Future releases may clear BSS here rather than in the CRT1. */ - - - /* - * Now jump to the application. This is typically the - * C run-time initialization ("CRT") which in turn calls main(): - */ - movi a4, _start - jx a4 // jump to _start - - .size _app_reset, . - _app_reset - 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 fad52b3ecc77..000000000000 --- a/src/arch/xtensa/xtos/crt1-boards-rom.S +++ /dev/null @@ -1,175 +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 <sof/lib/memory.h> -#include <config.h> -#include <xtensa/coreasm.h> - -// 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 -#if CONFIG_SUECREEK -_boot_ldr_entry: - .word BOOT_LDR_TEXT_ENTRY_BASE -#else -_boot_ldr_entry: - .word IMR_BOOT_LDR_TEXT_ENTRY_BASE -#endif - .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_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 -#if CONFIG_SUECREEK - callx8 a0 // jump to the handler -#else - callx12 a0 // jump to the handler -#endif - -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/arch/xtensa/xtos/crt1-boards.S b/src/arch/xtensa/xtos/crt1-boards.S deleted file mode 100644 index b473822dbb78..000000000000 --- a/src/arch/xtensa/xtos/crt1-boards.S +++ /dev/null @@ -1,337 +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 <config.h> -#if CONFIG_SMP -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#endif -#include <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -// 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 - -.type master_core_data, @object -.type core_data_ptr, @object - -// 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 - -_start: -#if CONFIG_SMP - // each core unpacks xtos structures for itself - // nevertheless core 0 initializes shared xtosstruct - get_prid a5 -#if PLATFORM_MASTER_CORE_ID == 0 - bnez a5, xtos_per_core -#else - movi a4, PLATFORM_MASTER_CORE_ID - bne a5, a4, xtos_per_core -#endif -#endif - - // _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 - - // Init xtos struct ptr - movi a2, master_core_data - movi a3, core_data_ptr - s32i a2, a3, 0 - -#if CONFIG_SMP - // Initialize the stack pointer. - // See the "ABI and Software Conventions" chapter in the - // Xtensa ISA Reference manual for details. - - // NOTE: Because the _start routine does not use any memory in its - // stack frame, and because all of its CALL instructions use a - // window size of 4 (or zero), the stack frame for _start can be empty. - -// Common xtos structures used by all cores. -xtos_common: - // Unpack xtos_exc_handler_table from rodata. - movi a6, xtos_exc_handler_table - movi a9, xtos_exc_handler_table_r - movi a13, XCHAL_EXCCAUSE_NUM*4 -xtos_exc_handler_table_loop: - l32i a12, a9, 0 - s32i a12, a6, 0 - addi a13, a13, -4 - addi a6, a6, 4 - addi a9, a9, 4 - bnez a13, xtos_exc_handler_table_loop - -// Xtos structures initialized per core from rodata. -xtos_per_core: -#endif -#if CONFIG_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 - -#if CONFIG_SMP - get_prid a5 -#if PLATFORM_MASTER_CORE_ID == 0 - beqz a5, xtos_per_core_obtain_xtos_structs -#else - movi a4, PLATFORM_MASTER_CORE_ID - beq a5, a4, xtos_per_core_obtain_xtos_structs -#endif - -xtos_per_core_cacheattr: -#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || \ - XCHAL_HAVE_XLT_CACHEATTR || \ - (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - movi a2, _memmap_cacheattr_reset /* absolute symbol, not a ptr */ - cacheattr_set /* set CACHEATTR from a2 (clobbers a3-a8) */ -#endif - -xtos_per_core_vecbase: -#if XCHAL_HAVE_VECBASE - /* note: absolute symbol, not a ptr */ - movi a2, _memmap_vecbase_reset - wsr.vecbase a2 -#endif - -// Obtain core structs from given address. -xtos_per_core_obtain_xtos_structs: - get_prid a5 - movi a2, 4 - mull a2, a2, a5 - movi a3, core_data_ptr - add a3, a3, a2 - l32i a3, a3, 0 - -xtos_per_core_init_intstruct: - movi a2, 0 - s32i a2, a3, 0 - movi a2, 0xFFFFFFFF - s32i a2, a3, 4 - addi a3, a3, XTOS_INTSTRUCT_SIZE_PER_CORE - -xtos_per_core_init_interrupt_table: - // Setup iterator. - movi a6, XCHAL_NUM_INTERRUPTS - - // Setup init constants. - movi a2, xtos_unhandled_interrupt - - 1: - addi a6, a6, -1 - s32i a2, a3, 0 - s32i a6, a3, 4 - // Int handler size should be 8. - addi a3, a3, 8 - bnez a6, 1b - -xtos_per_core_init_interrupt_mask: - movi a6, XCHAL_NUM_INTERRUPTS - movi a5, ~XCHAL_LOWPRI_MASK - movi a7, -2 - - 2: - // i <==> a6 - addi a6, a6, -1 - // a4 := 1 << i - movi a4, 1 - ssl a6 - sll a4, a4 - // a2 := (-2 * (1 << i) - 1) | ~XCHAL_LOWPRI_MASK - mull a2, a4, a7 - addi a2, a2, -1 - or a2, a2, a5 - - s32i a2, a3, 0 - s32i a4, a3, 4 - // Int handler size should be 8. - addi a3, a3, 8 - addi a4, a4, 1 - bnez a6, 2b - - // Assign stack ptr before PS is initialized to avoid any debugger - // side effects and prevent from double exception. - xtos_stack_addr_percore sp, a3, _stack_sentry, _sof_core_s_start, SOF_STACK_SIZE -#else /* CONFIG_SMP */ - movi sp, __stack -#endif - - /* - * 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: - -/* bootloader takes care of zeroing BSS */ -#if !CONFIG_BOOT_LOADER - /* - * Clear the BSS (uninitialized data) segments. - * This code supports multiple zeroed sections (*.bss). - * - * Register allocation: - * a0 = 0 - * a6 = pointer to start of table, and through table - * a7 = pointer to end of table - * a8 = start address of bytes to be zeroed - * a9 = end address of bytes to be zeroed - * a10 = length of bytes to be zeroed - */ - movi a0, 0 - movi a6, _bss_table_start - movi a7, _bss_table_end - bgeu a6, a7, .L3zte - -.L0zte: l32i a8, a6, 0 // get start address, assumed multiple of 4 - l32i a9, a6, 4 // get end address, assumed multiple of 4 - addi a6, a6, 8 // next entry - sub a10, a9, a8 // a10 = length, assumed a multiple of 4 - bbci.l a10, 2, .L1zte - s32i a0, a8, 0 // clear 4 bytes to make length multiple of 8 - addi a8, a8, 4 -.L1zte: bbci.l a10, 3, .L2zte - s32i a0, a8, 0 // clear 8 bytes to make length multiple of 16 - s32i a0, a8, 4 - addi a8, a8, 8 -.L2zte: srli a10, a10, 4 // length is now multiple of 16, divide by 16 - floopnez a10, clearzte - s32i a0, a8, 0 // clear 16 bytes at a time... - s32i a0, a8, 4 - s32i a0, a8, 8 - s32i a0, a8, 12 - addi a8, a8, 16 - floopend a10, clearzte - - bltu a6, a7, .L0zte // loop until end of table of *.bss sections -.L3zte: -#endif - - // Call: int main(int argc, char ** argv, char ** environ); - CALL main - // Does not return here. - - .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/arch/xtensa/xtos/crt1-sim.S b/src/arch/xtensa/xtos/crt1-sim.S deleted file mode 100644 index 90687927449f..000000000000 --- a/src/arch/xtensa/xtos/crt1-sim.S +++ /dev/null @@ -1,290 +0,0 @@ -// crt1-sim.S -// For the Xtensa simulator target, this code sets up the C calling context -// and calls main() (via __clibrary_start). -// 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 <xtensa/simboard.h> -#include <xtensa/simcall.h> -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -// Exports -.global _start - -// Imports -// __clibrary_init from C library (eg. newlib or uclibc) -// exit from C library -// main from user application -// __stack from linker script (see LSP Ref Manual) - -.type __clibrary_init, @function -.type main, @function -.type exit, @function - - -// Macros to abstract away ABI differences - -#if __XTENSA_CALL0_ABI__ -# define CALL call0 -# define CALLX callx0 -# define ARG1 a2 /* 1st outgoing call argument */ -# define ARG2 a3 /* 2nd outgoing call argument */ -# define ARG3 a4 /* 3rd outgoing call argument */ -# define ARG4 a5 /* 4th outgoing call argument */ -# define ARG5 a6 /* 5th outgoing call argument */ -#else -# define CALL call4 -# define CALLX callx4 -# define ARG1 a6 /* 1st outgoing call argument */ -# define ARG2 a7 /* 2nd outgoing call argument */ -# define ARG3 a8 /* 3rd outgoing call argument */ -# define ARG4 a9 /* 4th outgoing call argument */ -# define ARG5 a10 /* 5th outgoing call argument */ -#endif - - .data - .weak _start_envp // allow overriding - .align 4 -_start_envp: .word 0 // empty environ - - - - .text - .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. - // - movi a0, 0 // keep this register zero. - -#if XTOS_RESET_UNNEEDED -#include "reset-unneeded.S" -#endif - - - // Initialize the stack pointer. - // See the "ABI and Software Conventions" chapter in the - // Xtensa ISA Reference manual for details. - - // NOTE: Because the _start routine does not use any memory in its - // stack frame, and because all of its CALL instructions use a - // window size of 4, the stack frame for _start can be empty. - movi sp, __stack - - // reserve stack space for - // - argv array - // - argument strings - movi a2, SYS_iss_argv_size - simcall // returns size of argv[] + its strings in a2 -#if XCHAL_HAVE_PIF - // The stack only needs 16-byte alignment. - // However, here we round up the argv size further to 128 byte multiples - // so that in most cases, variations in argv[0]'s path do not result in - // different stack allocation. Otherwise, such variations can impact - // execution timing (eg. due to cache effects etc) for the same code and data. - // If we have a PIF, it's more likely the extra required space is okay. - addi a2, a2, 127 - srli a2, a2, 7 - slli a2, a2, 7 -#else - // Keep stack 16-byte aligned. - addi a2, a2, 15 - srli a2, a2, 4 - slli a2, a2, 4 -#endif - // No need to use MOVSP because we have no caller (we're the - // base caller); in fact it's better not to use MOVSP in this - // context, to avoid unnecessary ALLOCA exceptions and copying - // from undefined memory: - // sub a3, sp, a2 - // movsp sp, a3 - sub sp, sp, a2 - - - /* - * 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: - -#if !XCHAL_HAVE_BOOTLOADER /* boot loader takes care of zeroing BSS */ - - /* If a system-specific BSS init routine is defined, call it. - * Such a routine must be named __bss_init(). It can be a C - * function, however it must be written to be able to work - * with BSS not yet initialized. This function is optional. - * It is marked as a weak symbol, so that it gets value zero - * if not defined. - */ - .weak __bss_init - movi a4, __bss_init - beqz a4, 2f - movi ARG1, _bss_table_start - movi ARG2, _bss_table_end - CALLX a4 - j .Lnobss // skip default BSS init code -2: - - /* The new ISS simcall only appeared after RB-2007.2: */ -#if (XCHAL_HW_MAX_VERSION > XTENSA_HWVERSION_RB_2007_2) - /* - * Clear the BSS (uninitialized data) segments. - * This code supports multiple zeroed sections (*.bss). - * For speed, we clear memory using an ISS simcall - * (see crt1-boards.S for more generic BSS clearing code). - */ - movi a6, _bss_table_start - movi a7, _bss_table_end - bgeu a6, a7, .Lnobss -.Lbssloop: - movi a2, SYS_memset - l32i a3, a6, 0 // arg1 = fill start address - movi a4, 0 // arg2 = fill pattern - l32i a5, a6, 4 // get end address - addi a6, a6, 8 // next bss table entry - sub a5, a5, a3 // arg3 = fill size in bytes - simcall // memset(a3,a4,a5) - bltu a6, a7, .Lbssloop // loop until end of bss table -#endif /* XCHAL_HW_MAX_VERSION */ -.Lnobss: -#endif /* XCHAL_HAVE_BOOTLOADER */ - - - /* - * Call __clibrary_init to initialize the C library: - * - * void __clibrary_init(int argc, char ** argv, char ** environ, - * void(*init_func)(void), void(*fini_func)(void)); - */ - - // Get argv with the arguments from the ISS - mov a3, sp // tell simcall where to write argv[] - movi a2, SYS_iss_set_argv - simcall // write argv[] array at a3 - - movi a2, SYS_iss_argc - simcall // put argc in a2 - - -// Alternative smaller code for Xtensa TX. -// Many starting with simulation assume a full C env, so NOT DONE FOR NOW. -// -//#if XCHAL_HAVE_HALT -// -// // Assume minimalist environment for memory-constrained TX cores. -// // No C library or board initialization, and no call to exit(). -// // However, in the interest of software regressions, for now we -// // still pass parameters to main (but not the rarely used envp). -// -// //mov ARG1, a2 // argc already in a2. -// mov ARG2, sp // argv -// CALL main -// halt -// -//#else /* !HALT */ -// ... - - -#if __XTENSA_CALL0_ABI__ - mov a12, a2 // save argc (a2 is ARG1) -#else - mov ARG1, a2 // argc -#endif - mov ARG2, sp // argv - movi ARG3, _start_envp // envp - movi ARG4, _init // _init - movi ARG5, _fini // _fini - CALL __clibrary_init - - // Call: int main(int argc, char ** argv, char ** environ); -#if __XTENSA_CALL0_ABI__ - mov ARG1, a12 // argc -#else - mov ARG1, a2 // argc -#endif - mov ARG2, sp // argv - movi ARG3, _start_envp // envp = [0] - CALL main - // The return value is the same register as the first outgoing argument. - CALL exit // exit with main's return value - // Does not return here. - - .size _start, . - _start - - -// Local Variables: -// mode:fundamental -// comment-start: "// " -// comment-start-skip: "// *" -// End: diff --git a/src/arch/xtensa/xtos/crt1-tiny.S b/src/arch/xtensa/xtos/crt1-tiny.S deleted file mode 100644 index d1684c5e76ad..000000000000 --- a/src/arch/xtensa/xtos/crt1-tiny.S +++ /dev/null @@ -1,127 +0,0 @@ -// crt1-tiny.S -// -// This is a reduced version of the code in crt1-boards.S . -// For most hardware / boards, this code sets up the C calling context -// (setting up stack, PS, and clearing BSS) and calls main(). -// It has some limitations (see LSP Ref Manual for details) such as: -// - does not setup the C library (...) -// - does not call C++ static constructors and destructors -// - only clears .bss , not other *.bss sections -// -// Control arrives here at _start from the reset vector or from crt0-app.S. - -// Copyright (c) 1998-2013 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/xtensa-versions.h> -#include <xtensa/simcall.h> - - -// Imports -// __stack from linker script (see LSP Ref Manual) -// _bss_start from linker script (see LSP Ref Manual) -// _bss_end from linker script (see LSP Ref Manual) -// main from user application - - - -#ifdef __XTENSA_CALL0_ABI__ -# define CALL call0 -#else -# define CALL call4 -#endif - - -/**************************************************************************/ - - .text - .align 4 - .global _start -_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). - // See crt1-boards.S for assumptions on entry to _start , - // and for comments on what is being done in this file. - -#if !XCHAL_HAVE_HALT || !XCHAL_HAVE_BOOTLOADER // not needed for Xtensa TX - movi a0, 0 // mark base of call stack -#endif - - movi sp, __stack // setup the stack - -#if XCHAL_HAVE_EXCEPTIONS - movi a3, PS_UM|PS_WOE_ABI // PS: WOE=0|1, UM=1, EXCM=0, INTLEVEL=0 - wsr.ps a3 // setup PS for the application - rsync -#endif - - - // Clear the BSS (uninitialized data) segment. - // - // This code only supports .bss, not multiple *.bss sections. - // Corresponding code in crt1-boards.S does, and is faster but bigger. - -#if !XCHAL_HAVE_BOOTLOADER - movi a6, _bss_start - movi a7, _bss_end - bgeu a6, a7, 2f -1: s32i a0, a6, 0 - addi a6, a6, 4 - bltu a6, a7, 1b -2: -#endif - - // We can now call C code, the C calling environment is initialized. - // This tiny C runtime assumes main is declared as "void main(void)" - // rather than with the usual argc,argv. So there are no arguments. - - CALL main - - // In this tiny C runtime, main() is not expected to return. - // If it does, just loop forever. - - //CALL xthal_dcache_all_writeback // sync dirty dcaches to memory - //extw // sync TIE queues/ports/etc (LX or later only) - -.L0: -#if XCHAL_HAVE_HALT - halt -#else -# if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2013_2 /* SIMCALL is NOP in hw? */ - movi a2, SYS_exit - simcall // exit if in simulator, else NOP -# endif -# if XCHAL_HAVE_DEBUG - break 1, 15 // give control to debugger -# endif -#endif - j .L0 - - .size _start, . - _start - - -// Local Variables: -// mode:fundamental -// comment-start: "// " -// comment-start-skip: "// *" -// End: diff --git a/src/arch/xtensa/xtos/debug-vector.S b/src/arch/xtensa/xtos/debug-vector.S deleted file mode 100644 index 7b76976a2c8e..000000000000 --- a/src/arch/xtensa/xtos/debug-vector.S +++ /dev/null @@ -1,73 +0,0 @@ -// debug-vector.S -- Debug Exception Vector -// $Id: //depot/rel/Eaglenest/Xtensa/OS/xtos/debug-vector.S#2 $ - -// Copyright (c) 2003-2013 Tensilica 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 <arch/debug/gdb/xtensa-defs.h> -#include <config.h> -#include <xtensa/xtensa-versions.h> -#include <xtensa/coreasm.h> -#include <xtensa/config/specreg.h> -#ifdef SIMULATOR -#include <xtensa/simcall.h> -#endif - -#if XCHAL_HAVE_DEBUG && XCHAL_HAVE_EXCEPTIONS - - // This code goes at the debug exception vector - - .begin literal_prefix .DebugExceptionVector - .section .DebugExceptionVector.text, "ax" - .align 4 - .global _DebugExceptionVector -_DebugExceptionVector: - - isync_erratum453 -#if ((defined(SIMULATOR) || \ - (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2013_2)) \ - && !CONFIG_GDB_DEBUG) /* SIMCALL is NOP in hw? */ - // In the simulator (ISS), let the debugger (if any is attached) - // handle the debug exception, else simply stop the simulation: - // - simcall // have ISS handle the debug exception -# endif -# if (!defined(SIMULATOR) && !CONFIG_GDB_DEBUG) - // For hardware, this code does not handle debug exceptions. - // To implement a target-side debug monitor, replace this - // vector with a real one that uses target-specific facilities - // to communicate with the debugger. - // -1: - // unexpected debug exception, loop in low-power mode - //waiti XCHAL_DEBUGLEVEL - j 1b // infinite loop - unexpected debug exception -# endif /*!SIMULATOR && !CONFIG_GDB_DEBUG*/ - -#if CONFIG_GDB_DEBUG - xsr a2, DEBUG_EXCSAVE - jx a2 -#endif - - .end literal_prefix - .size _DebugExceptionVector, . - _DebugExceptionVector - -#endif /* XCHAL_HAVE_DEBUG && XCHAL_HAVE_EXCEPTIONS */ diff --git a/src/arch/xtensa/xtos/deprecated.S b/src/arch/xtensa/xtos/deprecated.S deleted file mode 100644 index db746dbfa3aa..000000000000 --- a/src/arch/xtensa/xtos/deprecated.S +++ /dev/null @@ -1,122 +0,0 @@ -// deprecated.S -- Deprecated assembler functions - -// Copyright (c) 2003-2015 Tensilica 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 <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2 - - .text - -/* - void _xtos_timer_<N>_delta(int cycles) - - Set the timer from the current ccount. - DEPRECATED. PLEASE USE xthal_set_ccompare() AND xthal_get_ccount() - INSTEAD, OR USE DIFFERENT ALGORITHM THAT UPDATES CCOMPAREn RELATIVE TO - LAST CCOMPAREn FOR DRIFT-FREE PERIODIC TIMER INTERRUPTS. -*/ - .macro define_timer_delta num, numtimers - .if ((\num-\numtimers) & ~0xFFF) // num < numtimers ? - .align 4 - .global _xtos_timer_&num&_delta - .type _xtos_timer_&num&_delta,@function -_xtos_timer_&num&_delta: - abi_entry - rsr.ccount a3 - add a3, a3, a2 - writesr ccompare \num a3 - abi_return - .size _xtos_timer_&num&_delta, . - _xtos_timer_&num&_delta - .endif - .endm - - - -#if defined(__SPLIT__t0_delta) - - define_timer_delta 0, XCHAL_NUM_TIMERS - -#elif defined(__SPLIT__t1_delta) - - define_timer_delta 1, XCHAL_NUM_TIMERS - -#elif defined(__SPLIT__t2_delta) - - define_timer_delta 2, XCHAL_NUM_TIMERS - -#elif defined(__SPLIT__t3_delta) - - define_timer_delta 3, XCHAL_NUM_TIMERS - - -#elif defined(__SPLIT__read_ints) - - // - // u32 _xtos_read_ints( void ) - // - // _xtos_read_ints() reads the INTERRUPT register and returns it. - // DEPRECATED. - // [Kept temporarily because it was documented in T1050 System SW Ref Manual.] - // - .text - .align 4 - .global _xtos_read_ints - .type _xtos_read_ints,@function -_xtos_read_ints: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - rsr.interrupt a2 -#else /*XCHAL_HAVE_INTERRUPTS*/ - movi a2, 0 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - .size _xtos_read_ints, . - _xtos_read_ints - - -#elif defined(__SPLIT__clear_ints) - - // - // void _xtos_clear_ints( u32 mask ) - // - // _xtos_clear_ints() clears selected bits of the INTERRUPT register. - // DEPRECATED. - // [Kept temporarily because it was documented in T1050 System SW Ref Manual.] - // - .text - .align 4 - .global _xtos_clear_ints - .type _xtos_clear_ints,@function -_xtos_clear_ints: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - wsr.intclear a2 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - .size _xtos_clear_ints, . - _xtos_clear_ints - -#endif /* splitting */ - -#endif /* XEA1 or XEA2 */ - diff --git a/src/arch/xtensa/xtos/double-vector.S b/src/arch/xtensa/xtos/double-vector.S deleted file mode 100644 index f52e38462e4f..000000000000 --- a/src/arch/xtensa/xtos/double-vector.S +++ /dev/null @@ -1,98 +0,0 @@ -// double-vector.S -- Double Exception Vector -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/double-vector.S#1 $ - -// Copyright (c) 2000-2004, 2006, 2010 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/config/system.h> -#ifdef SIMULATOR -#include <xtensa/simcall.h> -#endif - - -#if XCHAL_HAVE_EXCEPTIONS && defined(XCHAL_DOUBLEEXC_VECTOR_VADDR) - -/* - * This is a very minimalist implementation of the double - * exception vector. For XEA2 configurations without a - * full MMU, this vector is only expected to be executed - * upon fatal errors (exceptions that occur within critical - * sections of exception vectors and handlers). - * - * For configurations with a full MMU (ie. with TLBs and - * auto-refill) and the windowed address registers option, - * a more complete version of this handler is necessary if: - * dynamic page mapping is implemented, and the stack - * can ever point to a dynamically mapped area. - * In this case, a double exception is a normal occurrence - * when a stack access within a window handler causes - * a TLB miss exception or other expected MMU fault. - * XTOS does not support this scenario, hence a minimalist - * double exception vector is sufficient. - */ - - .begin literal_prefix .DoubleExceptionVector - .section .DoubleExceptionVector.text, "ax" - - .align 4 - .global _DoubleExceptionVector -_DoubleExceptionVector: - -# if XCHAL_HAVE_DEBUG -1: break 1,4 // unhandled double exception -# elif defined(SIMULATOR) - wsr.excsave1 a2 // save a2 where simulator expects it - movi a2, SYS_unhandled_double_exc -1: simcall // let simulator/debugger report unhandled exception -# else -1: -# endif - j 1b // infinite loop - - // NOTE: a non-minimalist vector may choose to - // process the double exception in the vector itself - // (by default, much more space is allocated to double - // exception vectors than to most other vectors); - // or, to jump to a double exception handler located - // elsewhere. If only the normal case of double - // exceptions occurring within a window handler is - // being handled, then it is safe to use EXCSAVE_1 to - // do this jump (window handlers don't use EXCSAVE_1). - // For example: - // - // wsr.excsave1 a0 - // movi a0, _DoubleExceptionFromVector - // jx a0 - // - // .text - // .align 4 - // .global _DoubleExceptionFromVector - //_DoubleExceptionFromVector: - // ... - - - .size _DoubleExceptionVector, . - _DoubleExceptionVector - .text - .end literal_prefix - -#endif /* have double exceptions */ - diff --git a/src/arch/xtensa/xtos/exc-sethandler.c b/src/arch/xtensa/xtos/exc-sethandler.c deleted file mode 100644 index 9df2eff8ea89..000000000000 --- a/src/arch/xtensa/xtos/exc-sethandler.c +++ /dev/null @@ -1,70 +0,0 @@ - -/* exc-sethandler.c - register an exception handler in XTOS */ - -/* - * Copyright (c) 1999-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 <xtensa/config/core.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_EXCEPTIONS - -extern void xtos_c_wrapper_handler(void *arg); /* assembly-level wrapper for C handlers */ -extern void xtos_unhandled_exception(void *arg); /* assembly-level handler for exceptions - with no registered handler */ -extern void xtos_p_none(void *arg); /* default/empty C handler */ - - -extern _xtos_handler xtos_c_handler_table[XCHAL_EXCCAUSE_NUM]; -extern _xtos_handler xtos_exc_handler_table[XCHAL_EXCCAUSE_NUM]; - -/* - * Register a C handler for the specified general exception - * (specified EXCCAUSE value). - */ -_xtos_handler _xtos_set_exception_handler( int n, _xtos_handler f ) -{ - _xtos_handler ret = 0; - - if( n < XCHAL_EXCCAUSE_NUM ) { - _xtos_handler func = f; - - if( func == 0 ) { - func = &xtos_p_none; - } - ret = xtos_c_handler_table[n]; - xtos_exc_handler_table[n] = ( (func == &xtos_p_none) - ? &xtos_unhandled_exception - : &xtos_c_wrapper_handler ); - xtos_c_handler_table[n] = func; - if( ret == &xtos_p_none ) { - ret = 0; - } - } - - return ret; -} - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/exc-syscall-handler.S b/src/arch/xtensa/xtos/exc-syscall-handler.S deleted file mode 100644 index 9c647ce22a32..000000000000 --- a/src/arch/xtensa/xtos/exc-syscall-handler.S +++ /dev/null @@ -1,192 +0,0 @@ -/* exc-syscall-handler.S - XTOS syscall instruction handler */ - -/* - * Copyright (c) 1999-2010 Tensilica 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. - */ - -/* - * The SYSCALL instruction is typically used to implement system calls. - * By convention, register a2 identifies the requested system call. - * Typically, other parameters are passed in registers a3 and up, - * and results are returned in a2. - * - * The Xtensa windowed ABI reserves the value zero of register a2 - * as a request to force register windows to the stack. The call0 ABI, - * which has no equivalent operation, reserves this value as a no-op. - * - * Generally, only code that traverses the stack in unusual ways needs - * to force (spill) register windows to the stack. In generic C or C++, - * there are four cases, and they all use the standard SYSCALL mechanism: - * - * 1. C++ exceptions - * 2. setjmp and longjmp - * 3. functions using the GNU extension "__builtin_return_address" - * 4. functions using the GNU extension "nonlocal goto" - * - * NOTE: Specific operating systems often need to spill register windows - * to the stack in other situations such as context-switching, passing - * Unix-like signals to threads, displaying stack tracebacks, etc. - * They may choose to use the SYSCALL mechanism to do so, or use other - * means such as calling xthal_window_spill() or other methods. - * - * If you want to handle other system calls, you can modify this file, or - * use the C version of it in exc-syscall-handler.c . The Xtensa ABIs only - * define system call zero; the behavior of other system calls is up to you. - */ - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_EXCEPTIONS - -//Vector: -// addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. -// s32i a2, a1, UEXC_a2 -// s32i a3, a1, UEXC_a3 -// movi a3, xtos_exc_handler_table -// rsr.exccause a2 -// addx4 a2, a2, a3 -// l32i a2, a2, 0 -// s32i a4, a1, UEXC_a4 -// jx a2 // jump to cause-specific handler - - .global _need_user_vector_ // pull-in real user vector (tiny LSP) - - - /* - * The SYSCALL handler is entered when the processor - * executes the SYSCALL instruction. - * By convention, the system call to execute is specified in a2. - */ - .text - .align 4 - .global _xtos_syscall_handler -_xtos_syscall_handler: - // HERE: a2, a3, a4 have been saved to the exception stack frame allocated with a1 (sp). - // We ignore that a4 was saved, we don't clobber it. - - rsr.epc1 a3 -#if XCHAL_HAVE_LOOPS - // If the SYSCALL instruction was the last instruction in the body of - // a zero-overhead loop, and the loop will execute again, decrement - // the loop count and resume execution at the head of the loop: - // - rsr.lend a2 - addi a3, a3, 3 // increment EPC to skip the SYSCALL instruction - bne a2, a3, 1f - rsr.lcount a2 - beqz a2, 1f - addi a2, a2, -1 - wsr.lcount a2 - rsr.lbeg a3 -1: l32i a2, a1, UEXC_a2 // get the system call number -#else - // No loop registers. - l32i a2, a1, UEXC_a2 // get the system call number - addi a3, a3, 3 // increment EPC to skip the SYSCALL instruction -#endif - wsr.epc1 a3 // update EPC1 past SYSCALL - l32i a3, a1, UEXC_a3 // restore a3 - // If you want to handle other system calls, check a2 here. - -#ifdef __XTENSA_WINDOWED_ABI__ - bnez a2, .Lnotzero // is syscall number zero? - - /* Spill register windows to the stack. */ - - // Save a2 thru a5 in the nested-C-function area, where an interrupt - // won't clobber them. The pseudo-CALL's ENTRY below clobbers a4 and a5. - //s32i a2, a1, (ESF_TOTALSIZE - 32) + 0 // a2 is zero, no need to save - s32i a3, a1, (ESF_TOTALSIZE - 32) + 4 - s32i a4, a1, (ESF_TOTALSIZE - 32) + 8 - s32i a5, a1, (ESF_TOTALSIZE - 32) + 12 - - movi a3, PS_WOE|PS_CALLINC(1)|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) // CALL4 emulation - rsr.ps a2 // save PS in a2 - wsr.ps a3 // PS.INTLEVEL=EXCMLEVEL (1 for XEA1) - // HERE: window overflows enabled but NOT SAFE yet, touch only a0..a3 until it's safe. - rsr.epc1 a3 // save EPC1 in a3 - addi a1, a1, ESF_TOTALSIZE // restore sp (dealloc ESF) for sane stack again - rsync // wait for WSR to PS to complete - // HERE: Window overflows and interrupts are safe, we saved EPC1 and - // restored a1, and a4-a15 are unmodified. - // Pseudo-CALL: make it look as if the code that executed SYSCALL - // made a CALL4 to here. See user exc. handler comments for details. - // ENTRY cannot cause window overflow; touch a4 to ensure a4-a7 - // overflow if needed: - movi a4, 0 // clears pseudo-CALL's return PC - // NOTE: On XEA1 processors, return from window overflow re-enables - // interrupts (by clearing PS.INTLEVEL). This is okay even though SP - // is unallocated because we saved state safe from interrupt dispatch. - .global _SyscallException -_SyscallException: // label makes tracebacks look nicer - _entry a1, 64 // as if after a CALL4 (PS.CALLINC==1) - // Call deep enough to force spill of entire address register file. - _call12 __deep_call -1: movi a14, 0x80000000 + .Ldelta_done - add a0, a12, a14 // clear a0 msbit (per CALL4), offset -3: retw // return from pseudo-CALL4 - - // NOTE: a5 still contains the exception window's exception stack frame pointer. -.LMdon: wsr.ps a2 // for XEA2, this sets EXCM; for XEA1, this sets INTLEVEL to 1; ... - movi a2, 0 // indicate successful SYSCALL (?) - l32i a4, a5, 32 + 8 - rsync // complete WSR to PS for safe write to EPC1 - wsr.epc1 a3 - l32i a3, a5, 32 + 4 - l32i a5, a5, 32 + 12 - rfe_rfue - - .set .Ldelta_retw, (3b - 1b) - .set .Ldelta_done, (.LMdon - 1b) - - .align 4 - .local __deep_call -__deep_call: - entry a1, 48 -#if XCHAL_NUM_AREGS < 64 - mov a15, a15 // touch just far enough to overflow 32 -#else - movi a12, .Ldelta_retw // use movi/add because of relocation - add a12, a0, a12 // set return PC as per CALL12 - _entry a1, 48 // last call was call12 so PS.CALLINC==3 - mov a12, a0 // set return PC - _entry a1, 48 - mov a12, a0 // set return PC - _entry a1, 16 - mov a11, a11 // touch just far enough to overflow 64 -#endif - retw - -#endif /* __XTENSA_WINDOWED_ABI__ */ - -.Lnotzero: - movi a2, -1 /*ENOSYS*/ // system call not supported - addi a1, a1, ESF_TOTALSIZE - rfe_rfue - - .size _xtos_syscall_handler, . - _xtos_syscall_handler - - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/exc-table.S b/src/arch/xtensa/xtos/exc-table.S deleted file mode 100644 index a1281332e930..000000000000 --- a/src/arch/xtensa/xtos/exc-table.S +++ /dev/null @@ -1,61 +0,0 @@ -// exc-table.S - general exception C handler table - -// Copyright (c) 1999-2010 Tensilica 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 <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_EXCEPTIONS - - /* - * Table of exception handlers (in C) for user vectored exceptions. - * Provides entries for all possible 64 exception causes - * currently allowed for in the EXCCAUSE register. - */ - .data - .global xtos_c_handler_table - .align 4 -xtos_c_handler_table: - .rept XCHAL_EXCCAUSE_NUM - .word xtos_p_none - .endr - - /* - * Default/empty exception C handler. - * This is just a placeholder for exception causes with no registered - * handler; it normally never gets executed. - * NOTE: control goes first to the debugger if one is present; - * see xtos_unhandled_exception in exc-unhandled.S . - */ - .text - .align 4 - .global xtos_p_none - .type xtos_p_none,@function -xtos_p_none: - abi_entry - // Do nothing. - abi_return - .size xtos_p_none, . - xtos_p_none - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/exc-unhandled.S b/src/arch/xtensa/xtos/exc-unhandled.S deleted file mode 100644 index 2f569c0c8e49..000000000000 --- a/src/arch/xtensa/xtos/exc-unhandled.S +++ /dev/null @@ -1,83 +0,0 @@ -// exc-unhandled.S - General Exception Handler for unhandled exceptions - -// Copyright (c) 2002-2004, 2006, 2010 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include "xtos-internal.h" -#ifdef SIMULATOR -#include <xtensa/simcall.h> -#endif - -#if XCHAL_HAVE_EXCEPTIONS - -/* - * Assembly-level exception handler used when no handler was - * registered for the specific exception cause. - * - * The BREAK instruction is used to give control to the debugger, - * if one is present and active. (If none is present and active, - * the default debug exception handler will typically skip over - * this break instruction.) - * This code follows the convention documented in the ISA manual - * to use BREAK instructions to signal unhandled exceptions to the - * debugger. For the debugger to report or handle this condition - * in an OS-independent manner, all processor state (except PC) - * must be restored as it was when the unhandled exception just - * occurred (ie. as it was at the beginning of the vector). - * If execution continues after the BREAK instruction (in which - * case any register might have been modified by the debugger), - * just return. - */ - .text - .align 4 - - // If not pulled-in some other way, define it as unhandled: - .weak xtos_cause3_handler - .global xtos_cause3_handler -xtos_cause3_handler: - - .global xtos_unhandled_exception -xtos_unhandled_exception: -#if XCHAL_HAVE_DEBUG || defined(SIMULATOR) - l32i a2, a1, UEXC_a2 // restore a2 - l32i a3, a1, UEXC_a3 // restore a3 - // Note: a4-a5 not clobbered, no need to restore. - addi a1, a1, ESF_TOTALSIZE // restore sp -# if XCHAL_HAVE_DEBUG - break 1, 1 // give control to the debugger (if any present) -# else - wsr.excsave1 a2 // save a2 where simulator expects it - movi a2, SYS_unhandled_user_exc - simcall // let simulator/debugger report unhandled exception - rsr.excsave1 a2 // restore a2 -# endif - rfe_rfue // if sim/debug resume, just return -#else /* DEBUG or SIMULATOR */ - j xtos_unhandled_exception // just loop forever -#endif /* DEBUG or SIMULATOR */ - - .size xtos_unhandled_exception, . - xtos_unhandled_exception - - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/exit.S b/src/arch/xtensa/xtos/exit.S deleted file mode 100644 index eaee4364312b..000000000000 --- a/src/arch/xtensa/xtos/exit.S +++ /dev/null @@ -1,93 +0,0 @@ -// exit.S -// -// For hardware / boards, this is the default _exit routine called by the -// C library exit() function. If the program ever exits, we eventually -// end up here after all C library cleanup (such as closing open files, -// calling exit callbacks and C++ destructors, etc) is complete. - -// Copyright (c) 1998-2013 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/config/core-isa.h> -#include <xtensa/simcall.h> -#include "xtos-internal.h" - -// Macros to abstract away ABI differences -#if __XTENSA_CALL0_ABI__ -# define CALL call0 -#else -# define CALL call4 -#endif - - - .text - .align 4 - .global _exit - .type _exit, @function -_exit: - abi_entry 0, 4 - -#if __XTENSA_CALL0_ABI__ - // save exit code as cache writeback will clobber a2 in call0 - mov a12, a2 -#endif - - // sync dirty data to memory before terminating -#if XCHAL_DCACHE_IS_COHERENT - CALL xthal_cache_coherence_optout -#elif XCHAL_DCACHE_IS_WRITEBACK - CALL xthal_dcache_all_writeback -#endif - - // sync queues (if any, only for LX and later): -#if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RA_2004_1 /* LX or later? */ - extw -#endif - // can break to debug monitor, go to sleep with waiti, or just spin in a loop -.L0: -#if XCHAL_HAVE_HALT - halt -#else -# if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2013_2 /* SIMCALL is NOP in hw? */ - // ISS expects exit code in a3 -# if __XTENSA_CALL0_ABI__ - mov a3, a12 -# else - mov a3, a2 -# endif - mov a4, a3 // save exitcode for the debugger, as simcall will erase a3 - movi a2, SYS_exit - simcall // exit if in simulator, else NOP - mov a2, a4 -# endif -# if XCHAL_HAVE_DEBUG - break 1, 15 // back to debugger, if one is attached -# endif -# if XCHAL_HAVE_INTERRUPTS - waiti 15 -# endif -#endif - j .L0 - //abi_exit - - .size _exit, . - _exit - diff --git a/src/arch/xtensa/xtos/int-handler.S b/src/arch/xtensa/xtos/int-handler.S deleted file mode 100644 index 3c86252c9aa5..000000000000 --- a/src/arch/xtensa/xtos/int-handler.S +++ /dev/null @@ -1,59 +0,0 @@ -// int-handler.S - Interrupt Handler Template (for levels > 1) -// $Id: //depot/main/Xtensa/OS/xtos/inth-template.S#1 $ - -// Copyright (c) 2003-2004, 2006 Tensilica 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. - - -// To use this template file, define a macro called _INTERRUPT_LEVEL -// to be the interrupt priority level of the vector, then include this file. -// The default Makefile defines _INTERRUPT_LEVEL when assembling this file -// for each medium and high priority interrupt level. - - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_INTERRUPTS - -# if INTERRUPT_IS_HI(_INTERRUPT_LEVEL) - -# if _INTERRUPT_LEVEL > XTOS_LOCKLEVEL - /* Not safe to dispatch interrupts in C above XTOS_LOCKLEVEL, - * so default to assembly high-priority interrupt handlers template - * in this case (with the default XTOS_LOCKLEVEL this never happens): - */ -# include "int-highpri-template.S" -# else - /* Dispatch high-priority interrupt handlers in C: */ -# include "int-highpri-dispatcher.S" -# endif - -# elif INTERRUPT_IS_MED(_INTERRUPT_LEVEL) - -# include "int-medpri-dispatcher.S" - -# elif (_INTERRUPT_LEVEL <= XCHAL_NUM_INTLEVELS) && (_INTERRUPT_LEVEL != XCHAL_DEBUGLEVEL) -# error INTERNAL ERROR: Interrupt priority levels > 1 must be either hi or medium priority! -# endif - -#endif /* XCHAL_HAVE_INTERRUPTS */ diff --git a/src/arch/xtensa/xtos/int-highpri-dispatcher.S b/src/arch/xtensa/xtos/int-highpri-dispatcher.S deleted file mode 100644 index 42f28c2c1fba..000000000000 --- a/src/arch/xtensa/xtos/int-highpri-dispatcher.S +++ /dev/null @@ -1,514 +0,0 @@ -// High-Priority Interrupt Dispatcher Template -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/int-highpri-dispatcher.S#1 $ - -// Copyright (c) 2004-2015 Tensilica 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. - -// -// This file allows writing high-priority interrupt handlers in C, -// providing convenience at a significant cost in performance. -// -// By default, this file is included by inth-template.S . -// The default Makefile defines _INTERRUPT_LEVEL when assembling -// inth-template.S for each medium and high priority interrupt level. -// -// To use this template file, define a macro called _INTERRUPT_LEVEL -// to be the interrupt priority level of the vector, then include this file. - -#include <config.h> -#if CONFIG_SMP -#include <sof/lib/cpu.h> -#endif -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_INTERRUPTS && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) - -#define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL) -#define SINGLE_INTERRUPT ((INTERRUPT_MASK & (INTERRUPT_MASK - 1)) == 0) -#define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL) - - -#define INTLEVEL_N_MASK INTERRUPT_MASK // mask of interrupts at this priority -#define INTLEVEL_N_NUM SINGLE_INT_NUM // interrupt number if there is only one -#define INTLEVEL_N_BELOW_MASK XCHAL_INTLEVEL_ANDBELOW_MASK(_INTERRUPT_LEVEL) - -/* Indicates whether there are multiple interrupts at this interrupt - * priority, ie. mapped to this interrupt vector. - * If there is only one, its number is INTLEVEL_N_NUM - */ -#define MULTIPLE_INTERRUPTS (!SINGLE_INTERRUPT) - -/* - * High priority interrupt stack frame: - */ -STRUCT_BEGIN -STRUCT_FIELD (long,4,HESF_,SAR) -STRUCT_FIELD (long,4,HESF_,WINDOWSTART) -STRUCT_FIELD (long,4,HESF_,WINDOWBASE) -STRUCT_FIELD (long,4,HESF_,EPC1) -STRUCT_FIELD (long,4,HESF_,EXCCAUSE) -STRUCT_FIELD (long,4,HESF_,EXCVADDR) -STRUCT_FIELD (long,4,HESF_,EXCSAVE1) -STRUCT_FIELD (long,4,HESF_,VPRI) /* (XEA1 only) */ -#if XCHAL_HAVE_MAC16 -STRUCT_FIELD (long,4,HESF_,ACCLO) -STRUCT_FIELD (long,4,HESF_,ACCHI) -/*STRUCT_AFIELD(long,4,HESF_,MR, 4)*/ -#endif -#if XCHAL_HAVE_LOOPS -STRUCT_FIELD (long,4,HESF_,LCOUNT) -STRUCT_FIELD (long,4,HESF_,LBEG) -STRUCT_FIELD (long,4,HESF_,LEND) -#endif -STRUCT_AFIELD(long,4,HESF_,AREG, 64) /* address registers ar0..ar63 */ -#define HESF_AR(n) HESF_AREG+((n)*4) -STRUCT_END(HighPriFrame) -#define HESF_TOTALSIZE HighPriFrameSize+32 /* 32 bytes for interrupted code's save areas under SP */ - - -#if XCHAL_HAVE_XEA1 && HAVE_XSR /* could be made true for T1040 and T1050 */ -# error "high-priority interrupt stack frame needs adjustment if HAVE_XSR is allowed with XEA1" -#endif - - -#define PRI_N_STACK_SIZE 1024 /* default to 1 kB stack for each level-N handling */ - - - // Allocate save area and stack: - // (must use .bss, not .comm, because the subsequent .set does not work otherwise) -#if CONFIG_SMP - .macro generate_stack_for_int core_id - .if GREATERTHAN(PLATFORM_CORE_COUNT, \core_id) - .section .bss, "aw" - .align 16 -LABEL(_Pri_,_Stack&core_id): .space PRI_N_STACK_SIZE + HESF_TOTALSIZE - .endif - .endm - - generate_stack_for_int 0 - generate_stack_for_int 1 - generate_stack_for_int 2 - generate_stack_for_int 3 -#else - .section .bss, "aw" - .align 16 -LABEL(_Pri_,_Stack): .space PRI_N_STACK_SIZE + HESF_TOTALSIZE -#endif - -#if HAVE_XSR - .data - .global LABEL(_Pri_,_HandlerAddress) -LABEL(_Pri_,_HandlerAddress): .space 4 -#endif - - - .text - .align 4 - .global LABEL(_Level,FromVector) -LABEL(_Level,FromVector): -#if CONFIG_SMP - xtos_stack_addr_percore_add a2, LABEL(_Pri_,_Stack), PRI_N_STACK_SIZE // get ptr to save area -#else - movi a2, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE -#endif - // interlock - - // Save a few registers so we can do some work: - s32i a0, a2, HESF_AR(0) -#if HAVE_XSR - //movi a0, LABEL(_Level,FromVector) // this dispatcher's address - movi a0, LABEL(_Pri_,_HandlerAddress) // dispatcher address var. - s32i a1, a2, HESF_AR(1) - l32i a0, a0, 0 // get dispatcher address - s32i a3, a2, HESF_AR(3) - xchgsr excsave _INTERRUPT_LEVEL a0 // get saved a2, restore dispatcher address -#else - readsr excsave _INTERRUPT_LEVEL a0 // get saved a2 - s32i a1, a2, HESF_AR(1) - s32i a3, a2, HESF_AR(3) -#endif - s32i a4, a2, HESF_AR(4) - s32i a0, a2, HESF_AR(2) - - // Save/restore all exception state - // (IMPORTANT: this code assumes no general exceptions occur - // during the execution of this dispatcher until this state - // is completely saved and from the point it is restored.) - // - // Exceptions that may normally occur within the C handler - // include window exceptions (affecting EPC1), alloca exceptions - // (affecting EPC1/EXCCAUSE and its handling uses EXCSAVE1), - // and possibly others depending on the particular C handler - // (possibly needing save/restore of EXCVADDR; and EXCVADDR - // is also possibly corrupted by any access thru an auto-refill - // way on a processor with a full MMU). - // - rsr.epc1 a3 - rsr.exccause a4 - s32i a3, a2, HESF_EPC1 - s32i a4, a2, HESF_EXCCAUSE -#if !XCHAL_HAVE_XEA1 - rsr.excvaddr a3 - s32i a3, a2, HESF_EXCVADDR -#endif - rsr.excsave1 a4 - s32i a4, a2, HESF_EXCSAVE1 - -#ifdef __XTENSA_WINDOWED_ABI__ - // Save remainder of entire address register file (!): - movi a0, XCHAL_NUM_AREGS - 8 // how many saved so far -#endif - - s32i a5, a2, HESF_AR(5) - s32i a6, a2, HESF_AR(6) - s32i a7, a2, HESF_AR(7) - -1: s32i a8, a2, HESF_AR(8) - s32i a9, a2, HESF_AR(9) - s32i a10, a2, HESF_AR(10) - s32i a11, a2, HESF_AR(11) - s32i a12, a2, HESF_AR(12) - s32i a13, a2, HESF_AR(13) - s32i a14, a2, HESF_AR(14) - s32i a15, a2, HESF_AR(15) - -#ifdef __XTENSA_WINDOWED_ABI__ - addi a8, a0, -8 - addi a10, a2, 8*4 - rotw 2 - bnez a0, 1b // loop until done - - rotw 2 - // back to original a2 ... - - // Save a few other registers required for C: - rsr.windowstart a3 - rsr.windowbase a4 - s32i a3, a2, HESF_WINDOWSTART - s32i a4, a2, HESF_WINDOWBASE - - // Setup window registers for first caller: - movi a3, 1 - movi a4, 0 - wsr.windowstart a3 - wsr.windowbase a4 - rsync - - // Note: register window has rotated, ie. a0..a15 clobbered. - -#endif /* __XTENSA_WINDOWED_ABI__ */ - -#if CONFIG_SMP - xtos_stack_addr_percore_add a1, LABEL(_Pri_,_Stack), PRI_N_STACK_SIZE // get ptr to save area -#else - movi a1, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE // get ptr to save area -#endif - movi a0, 0 // mark start of call frames in stack - - // Critical state saved, a bit more to do to allow window exceptions... - - // We now have a C-coherent stack and window state. - // Still have to fix PS while making sure interrupts stay disabled - // at the appropriate level (ie. level 2 and below are disabled in this case). - -#if XCHAL_HAVE_XEA1 -#if CONFIG_SMP - xtos_addr_percore a7, xtos_intstruct // address of interrupt management globals -#else - movi a7, _xtos_intstruct // address of interrupt management globals -#endif - rsilft a3, _INTERRUPT_LEVEL, XTOS_LOCKLEVEL // lockout - movi a4, ~INTLEVEL_N_BELOW_MASK // mask out all interrupts at this level or lower - l32i a3, a7, XTOS_VPRI_ENABLED_OFS // read previous _xtos_vpri_enabled - l32i a5, a7, XTOS_ENABLED_OFS // read _xtos_enabled - s32i a4, a7, XTOS_VPRI_ENABLED_OFS // set new _xtos_vpri_enabled (mask interrupts as if at _INTERRUPT_LEVEL) - s32i a3, a1, HESF_VPRI // save previous vpri - movi a2, PS_WOECALL4_ABI + PS_UM // UM=1, INTLEVEL=0 - and a3, a5, a4 // mask out selected interrupts - wsr.intenable a3 // disable all low-priority interrupts -#else - // Load PS for C code, clear EXCM (NOTE: this step is different for XEA1): - movi a2, PS_WOECALL4_ABI + PS_UM + _INTERRUPT_LEVEL // UM=1, INTLEVEL=N, EXCM=0, RING=0 -#endif - wsr.ps a2 // update PS to enable window exceptions, etc as per above - rsync - - // Okay, window exceptions can now happen (although we have to call - // deep before any will happen because we've reset WINDOWSTART). - - // Save other state that might get clobbered by C code: - -////////////////// COMMON DISPATCH CODE BEGIN - - rsr.sar a14 - s32i a14, a1, HESF_SAR -#if XCHAL_HAVE_LOOPS - rsr.lcount a14 - s32i a14, a1, HESF_LCOUNT - rsr.lbeg a14 - s32i a14, a1, HESF_LBEG - rsr.lend a14 - s32i a14, a1, HESF_LEND -#endif -#if XCHAL_HAVE_MAC16 - rsr.acclo a14 - s32i a14, a1, HESF_ACCLO - rsr.acchi a14 - s32i a14, a1, HESF_ACCHI -#endif - -#if MULTIPLE_INTERRUPTS /* > 1 interrupts at this priority */ // _split_ multi_setup -#define TABLE_OFS 0 - - rsr.interrupt a15 // mask of pending interrupts -# if XCHAL_HAVE_XEA1 - l32i a12, a7, XTOS_ENABLED_OFS // mask of enabled interrupts -# else - rsr.intenable a12 // mask of enabled interrupts -# endif - movi a13, INTLEVEL_N_MASK // mask of interrupts at this priority level - and a15, a15, a12 - and a15, a15, a13 // enabled & pending interrupts at this priority - _beqz a15, LABEL(Pri_,_spurious) // handle spurious interrupts (eg. level-trig.) -LABEL(Pri_,_loop): // handle all enabled & pending interrupts - neg a14, a15 - and a14, a14, a15 // single-out least-significant bit set in mask - wsr.intclear a14 // clear if edge-trig. or s/w or wr/err (else no effect) - - // Compute pointer to interrupt table entry, given mask a14 with single bit set: - -# if XCHAL_HAVE_NSA -#if CONFIG_SMP - xtos_addr_percore_sub a12, xtos_interrupt_table, (32-XCHAL_NUM_INTERRUPTS)*8 -#else - movi a12, xtos_interrupt_table - (32-XCHAL_NUM_INTERRUPTS)*8 -#endif - nsau a14, a14 // get index of bit in a14, numbered from msbit - addx8 a12, a14, a12 -# else /* XCHAL_HAVE_NSA */ -#if CONFIG_SMP - xtos_addr_percore a12, xtos_interrupt_table // pointer to interrupt table -#else - movi a12, xtos_interrupt_table // pointer to interrupt table -#endif - bltui a14, 0x10000, 1f // in 16 lsbits? (if so, check them) - addi a12, a12, 16*8 // no, index is at least 16 entries further - // (the above ADDI expands to an ADDI+ADDMI sequence, +128 is outside its range) - extui a14, a14, 16,16 // shift right upper 16 bits -1: bltui a14, 0x100, 1f // in 8 lsbits? (if so, check them) - addi a12, a12, 8*8 // no, index is at least 8 entries further - srli a14, a14, 8 // shift right upper 8 bits -1: bltui a14, 0x10, 1f // in 4 lsbits? (if so, check them) - addi a12, a12, 4*8 // no, index is at least 4 entries further - srli a14, a14, 4 // shift right 4 bits -1: bltui a14, 0x4, 1f // in 2 lsbits? (if so, check them) - addi a12, a12, 2*8 // no, index is at least 2 entries further - srli a14, a14, 2 // shift right 2 bits -1: bltui a14, 0x2, 1f // is it the lsbit? - addi a12, a12, 1*8 // no, index is one entry further -1: // done! a12 points to interrupt's table entry -# endif /* XCHAL_HAVE_NSA */ - -#else /* !MULTIPLE_INTERRUPTS */ - -# if XCHAL_HAVE_NSA -# define TABLE_OFS 8 * (XCHAL_NUM_INTERRUPTS - 1 - INTLEVEL_N_NUM) -# else -# define TABLE_OFS 8 * INTLEVEL_N_NUM -# endif - - movi a13, INTLEVEL_N_MASK // (if interrupt is s/w or edge-triggered or write/err only) -#if CONFIG_SMP - xtos_addr_percore a12, xtos_interrupt_table // get pointer to its interrupt table entry -#else - movi a12, xtos_interrupt_table // get pointer to its interrupt table entry -#endif - wsr.intclear a13 // clear the interrupt (if s/w or edge or wr/err only) - -#endif /* ifdef MULTIPLE_INTERRUPTS */ - - l32i a13, a12, TABLE_OFS + 0 // get pointer to handler from table entry -#ifdef __XTENSA_CALL0_ABI__ - l32i a2, a12, TABLE_OFS + 4 // pass single argument to C handler - callx0 a13 // call interrupt's C handler -#else - l32i a6, a12, TABLE_OFS + 4 // pass single argument to C handler - callx4 a13 // call interrupt's C handler -#endif - -#if XCHAL_HAVE_XEA1 -#if CONFIG_SMP - xtos_addr_percore a7, xtos_intstruct // address of interrupt management globals -#else - movi a7, _xtos_intstruct // address of interrupt management globals -#endif -#endif -#if MULTIPLE_INTERRUPTS /* > 1 interrupts at this priority */ - rsr.interrupt a15 // get pending interrupts -# if XCHAL_HAVE_XEA1 - l32i a12, a7, XTOS_ENABLED_OFS // get enabled interrupts -# else - rsr.intenable a12 // get enabled interrupts -# endif - movi a13, INTLEVEL_N_MASK // get mask of interrupts at this priority level - and a15, a15, a12 - and a15, a15, a13 // pending+enabled interrupts at this priority - _bnez a15, LABEL(Pri_,_loop) // if any remain, dispatch one -LABEL(Pri_,_spurious): -#endif /* MULTIPLE_INTERRUPTS */ - - // Restore everything, and return. - -#if XCHAL_HAVE_EXCLUSIVE - // Clear exclusive monitors. - clrex -#endif - - // Three temp registers are required for this code to be optimal (no interlocks) in - // T2xxx microarchitectures with 7-stage pipe; otherwise only two - // registers would be needed. - // -#if XCHAL_HAVE_LOOPS - l32i a13, a1, HESF_LCOUNT - l32i a14, a1, HESF_LBEG - l32i a15, a1, HESF_LEND - wsr.lcount a13 - wsr.lbeg a14 - wsr.lend a15 -#endif - -#if XCHAL_HAVE_MAC16 - l32i a13, a1, HESF_ACCLO - l32i a14, a1, HESF_ACCHI - wsr.acclo a13 - wsr.acchi a14 -#endif - l32i a15, a1, HESF_SAR - wsr.sar a15 - -////////////////// COMMON DISPATCH CODE END - -#if XCHAL_HAVE_XEA1 - // Here, a7 = address of interrupt management globals - l32i a4, a1, HESF_VPRI // restore previous vpri - rsil a3, XTOS_LOCKLEVEL // lockout - l32i a5, a7, XTOS_ENABLED_OFS // read _xtos_enabled - s32i a4, a7, XTOS_VPRI_ENABLED_OFS // set new _xtos_vpri_enabled - movi a2, 0x00020 + _INTERRUPT_LEVEL // WOE=0, UM=1, INTLEVEL=N - and a3, a5, a4 // mask out selected interrupts - wsr.intenable a3 // disable all low-priority interrupts -#else - // Load PS for interrupt exit, set EXCM: - movi a2, 0x00030 + _INTERRUPT_LEVEL // WOE=0, CALLINC=0, UM=1, INTLEVEL=N, EXCM=1, RING=0 -#endif - wsr.ps a2 // update PS to disable window exceptions, etc as per above - rsync - - // NOTE: here for XEA1, restore INTENABLE etc... - -#ifdef __XTENSA_WINDOWED_ABI__ - // Restore window registers: - l32i a2, a1, HESF_WINDOWSTART - l32i a3, a1, HESF_WINDOWBASE - wsr.windowstart a2 - wsr.windowbase a3 - rsync - // Note: register window has rotated, ie. a0..a15 clobbered. - - // Reload initial stack pointer: -#if CONFIG_SMP - xtos_stack_addr_percore_add a1, LABEL(_Pri_,_Stack), PRI_N_STACK_SIZE // - 16 -#else - movi a1, LABEL(_Pri_,_Stack) + PRI_N_STACK_SIZE // - 16 -#endif - movi a6, XCHAL_NUM_AREGS - 8 // how many saved so far - addi a7, a1, -8*4 - - // Restore entire register file (!): - -1: - addi a14, a6, -8 - addi a15, a7, 8*4 - l32i a4, a15, HESF_AR(4) - l32i a5, a15, HESF_AR(5) - l32i a6, a15, HESF_AR(6) - l32i a7, a15, HESF_AR(7) - l32i a8, a15, HESF_AR(8) - l32i a9, a15, HESF_AR(9) - l32i a10,a15, HESF_AR(10) - l32i a11,a15, HESF_AR(11) - rotw 2 - bnez a6, 1b // loop until done - - l32i a4, a7, HESF_AR(12) - l32i a5, a7, HESF_AR(13) - l32i a6, a7, HESF_AR(14) - l32i a7, a7, HESF_AR(15) - rotw 2 - - // back to original a1 ... - -#else /* Call0 ABI: */ - - l32i a4, a1, HESF_AR(4) // restore general registers - l32i a5, a1, HESF_AR(5) - l32i a6, a1, HESF_AR(6) - l32i a7, a1, HESF_AR(7) - l32i a8, a1, HESF_AR(8) - l32i a9, a1, HESF_AR(9) - l32i a10, a1, HESF_AR(10) - l32i a11, a1, HESF_AR(11) - l32i a12, a1, HESF_AR(12) - l32i a13, a1, HESF_AR(13) - l32i a14, a1, HESF_AR(14) - l32i a15, a1, HESF_AR(15) - -#endif /* __XTENSA_WINDOWED_ABI__ */ - - // Restore exception state: - l32i a2, a1, HESF_EPC1 - l32i a3, a1, HESF_EXCCAUSE - wsr.epc1 a2 - wsr.exccause a3 -#if !XCHAL_HAVE_XEA1 - l32i a2, a1, HESF_EXCVADDR - wsr.excvaddr a2 -#endif - l32i a3, a1, HESF_EXCSAVE1 - wsr.excsave1 a3 - - l32i a0, a1, HESF_AR(0) - l32i a2, a1, HESF_AR(2) - l32i a3, a1, HESF_AR(3) - l32i a1, a1, HESF_AR(1) - rfi _INTERRUPT_LEVEL - - .size LABEL(_Level,FromVector), . - LABEL(_Level,FromVector) - - // This symbol exists solely for the purpose of being able to pull-in this - // dispatcher using _xtos_dispatch_level<n>() routines with the tiny-rt LSP: - .global LABEL(_Level,HandlerLabel) - .set LABEL(_Level,HandlerLabel), 0 - -#endif /* XCHAL_HAVE_INTERRUPTS */ - diff --git a/src/arch/xtensa/xtos/int-highpri-template.S b/src/arch/xtensa/xtos/int-highpri-template.S deleted file mode 100644 index e41cc846c0e6..000000000000 --- a/src/arch/xtensa/xtos/int-highpri-template.S +++ /dev/null @@ -1,160 +0,0 @@ -// High-Priority Interrupt Handler Template -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/int-highpri-template.S#1 $ - -// Copyright (c) 2004-2010 Tensilica 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. - -// -// This file provides skeleton code for writing high-priority interrupt -// handlers in assembler for performance. -// -// By default, this file is included by inth-template.S . -// The default Makefile defines _INTERRUPT_LEVEL when assembling -// inth-template.S for each medium and high priority interrupt level. -// -// To use this template file, define a macro called _INTERRUPT_LEVEL -// to be the interrupt priority level of the vector, then include this file. - - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_INTERRUPTS - -#define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL) -#define SINGLE_INTERRUPT (INTERRUPT_MASK & (INTERRUPT_MASK - 1) == 0) -#define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL) - - -// NOTE: It is strongly recommended that high-priority -// interrupt handlers be written in assembly. -// -// High-priority interrupt handlers can be written in C, -// but only at the cost of an unreasonable amount of state -// save and restore (including the entire physical address -// register file and others, see int-highpri-dispatcher.S) -// that makes high-priority interrupt dispatching much slower -// than for low and medium priority interrupts. -// (Low and medium priority interrupts are masked by atomic -// register window operations, so they take advantage of a -// coherent window state for fast entry. High priority -// interrupts are not masked by window operations so they -// can interrupt them, leading to a potentially incoherent -// window state at the time of the interrupt. Given that -// high priority handlers must save and restore everything -// they touch, they end up needing to save and restore the -// entire window state [physical address register file etc.] -// and all exception state which they can also interrupt.) -// See also the Microprocessor Programmer's Guide. - -// High-priority interrupts are designed to be very fast and with -// very low latency. -// Typical high-priority interrupt service routines are kept -// relatively small and fast. Either there is little to do, -// or the routine handles only the necessary high priority -// activities related to a device and leaves the rest -// (other more complex and time-consuming activities) -// to be scheduled later, eg. by triggering a level-one -// (low-priority) or medium-priority software interrupt whose -// handler can be written in C for the more extensive processing. - -// NOTE: The following handler is just skeleton example -// code. It is NOT a functional handler. For software, edge- -// triggered and write-error interrupts, it simply does nothing -// and return. For other types (timer and level-triggered), -// this code does not clear the source(s) of interrupt, -// hence if any interrupt at this priority level are both enabled -// and triggered, the processor repeatedly takes the interrupt -// in a loop. This is all okay as a default, because -// XTOS (and other operating systems) clears the INTENABLE -// register at startup, requiring the application to -// enable specific interrupts before they can be taken. -// So as long as you don't enable any interrupt of this -// priority level, this example handler will never execute. - -// Exports -.global LABEL(_Level,FromVector) - - .data - .align 4 -LABEL(int,save): - .space 4 // save area - - .text - .align 4 -LABEL(_Level,FromVector): - // The vectoring code has already saved a2 in EXCSAVEn. - // Save any other registers we'll use: - movi a2, LABEL(int,save) - s32i a1, a2, 0 - // ... add more as needed (increase save area accordingly) ... - - // WRITE YOUR INTERRUPT HANDLING CODE HERE... - - // If multiple interrupts are mapped to this priority level, - // you'll probably need to distinguish which interrupt(s) - // occurred by reading the INTERRUPT (INTREAD) and - // INTENABLE registers, and'ing them together, and - // looking at what bits are set in both. - // If any of the interrupts are level-triggered, be ready - // to handle the case where no interrupts are to be handled - // -- this is called a spurious interrupt, and can happen - // when the level-triggered interrupt line goes inactive - // after the interrupt is taken but before the INTERRUPT - // register is read. - - // You'll also normally want to clear the source of - // the interrupt before returning, to avoid getting - // the same interrupt again immediately. For illustration, - // this code clears all software, edge-triggered, and - // write-error interrupts at this priority level (if any). - // NOTE: Timer interrupts must be cleared by writing to - // the corresponding CCOMPAREn register; and level-sensitive - // interrupts can only be cleared externally, usually by - // requesting the associated device to do so (in a - // device-specific manner). - // - movi a1, INTERRUPT_MASK - wsr.intclear a1 - - // Restore registers: - l32i a1, a2, 0 -#if HAVE_XSR - movi a2, LABEL(_Level,FromVector) // restore handler address - xchgsr excsave _INTERRUPT_LEVEL a2 -#else - readsr excsave _INTERRUPT_LEVEL a2 -#endif - // ... add more if more are saved above ... - -#if XCHAL_HAVE_EXCLUSIVE - // If your code used L32EX/S32EX, then clear any active excl monitors. - // Uncomment the line below. - // clrex -#endif - - // Return: - rfi _INTERRUPT_LEVEL - - .size LABEL(_Level,FromVector), . - LABEL(_Level,FromVector) - -#endif /* XCHAL_HAVE_INTERRUPTS */ diff --git a/src/arch/xtensa/xtos/int-initlevel.S b/src/arch/xtensa/xtos/int-initlevel.S deleted file mode 100644 index 1b09f2597439..000000000000 --- a/src/arch/xtensa/xtos/int-initlevel.S +++ /dev/null @@ -1,59 +0,0 @@ -// int-initlevel.S - Routines used to pull-in interrupt dispatch code -// in the tiny-rt LSP. -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/int-initlevel.S#1 $ - -// Copyright (c) 2006-2010 Tensilica 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. - - -// To assemble this template file, define a macro called _INTERRUPT_LEVEL -// to be the interrupt level of the vector. We use the same template for both -// high-level and medium-level interrupts, but not debug level. - - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_INTERRUPTS && (_INTERRUPT_LEVEL <= XCHAL_NUM_INTLEVELS) && (_INTERRUPT_LEVEL != XCHAL_DEBUGLEVEL) - - // Nothing to do at runtime. This function only has effect - // at link-time. - // - .text - .global LABEL(_xtos_dispatch_level,_interrupts) - .align 4 -LABEL(_xtos_dispatch_level,_interrupts): - abi_entry - abi_return - .size LABEL(_xtos_dispatch_level,_interrupts), . - LABEL(_xtos_dispatch_level,_interrupts) - - // This reference is what does the work of pulling-in the - // relevant interrupt vector at the specified level. - // This is only needed in the tiny-rt LSP. - // -# if _INTERRUPT_LEVEL == 1 - .global _need_level1int_ -# else - .global LABEL(_Level,Vector) -# endif - -#endif /* XCHAL_HAVE_INTERRUPTS */ diff --git a/src/arch/xtensa/xtos/int-medpri-dispatcher.S b/src/arch/xtensa/xtos/int-medpri-dispatcher.S deleted file mode 100644 index d2f998a725ff..000000000000 --- a/src/arch/xtensa/xtos/int-medpri-dispatcher.S +++ /dev/null @@ -1,401 +0,0 @@ -// Medium-Priority Interrupt Dispatcher Template -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/int-medpri-dispatcher.S#1 $ - -// Copyright (c) 2004-2010 Tensilica 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. - -// -// By default, this file is included by inth-template.S . -// The default Makefile defines _INTERRUPT_LEVEL when assembling -// inth-template.S for each medium and high priority interrupt level. -// -// To use this template file, define a macro called _INTERRUPT_LEVEL -// to be the interrupt priority level of the vector, then include this file. - -#include <sof/lib/memory.h> -#include <config.h> -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -#if XCHAL_HAVE_INTERRUPTS - -#define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL) -#define SINGLE_INTERRUPT ((INTERRUPT_MASK & (INTERRUPT_MASK - 1)) == 0) -#define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL) - - -// Strict non-preemptive prioritization - - - .text - .align 4 - .global LABEL(_Level,FromVector) -LABEL(_Level,FromVector): - -/* Allocate an exception stack frame, save a2, a4, and a5, and fix PS as: - * - * if not Call0 ABI - * - enable windowing for 'entry' (ps.woe=1, ps.excm=0) - * - setup ps.callinc to simulate call4 - * endif - * - preserve user mode - * - mask all interrupts at EXCM_LEVEL and lower - * - * Then deallocate the stack, 'rsync' for the write to PS, then use - * 'entry' to re-allocate the stack frame and rotate the register - * window (like a call4, preserving a0..a3). */ - -#if HAVE_XSR - xchgsr excsave _INTERRUPT_LEVEL a2 -#else - readsr excsave _INTERRUPT_LEVEL a2 -#endif - addi a1, a1, -ESF_TOTALSIZE - s32i a2, a1, UEXC_a2 - movi a2, PS_WOECALL4_ABI|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) - s32i a4, a1, UEXC_a4 - s32i a5, a1, UEXC_a5 - wsr.ps a2 - rsync - - /* store ps and pc */ - readsr eps, _INTERRUPT_LEVEL a2 - s32i a2, a1, UEXC_ps - readsr epc, _INTERRUPT_LEVEL a2 - s32i a2, a1, UEXC_pc - - /* store rest of the registers */ - s32i a0, a1, UEXC_a0 - s32i a3, a1, UEXC_a3 - s32i a6, a1, UEXC_a6 - s32i a7, a1, UEXC_a7 - s32i a8, a1, UEXC_a8 - s32i a9, a1, UEXC_a9 - s32i a10, a1, UEXC_a10 - s32i a11, a1, UEXC_a11 - s32i a12, a1, UEXC_a12 - s32i a13, a1, UEXC_a13 - s32i a14, a1, UEXC_a14 - s32i a15, a1, UEXC_a15 - - /* store current sp */ - xtos_addr_percore a2, xtos_saved_sp - s32i a1, a2, 0 - - /* store current task sp if context exists (not first irq) */ - xtos_task_ctx_percore a2 - beqz a2, no_context - s32i a1, a2, TC_stack_pointer - -no_context: -# if XTOS_CNEST - l32i a2, a1, ESF_TOTALSIZE-20 // save nested-C-func call-chain ptr -# endif - addi a1, a1, ESF_TOTALSIZE -# if XTOS_DEBUG_PC - readsr epc _INTERRUPT_LEVEL a4 // [for debug] get return PC - movi a5, 0xC0000000 // [for debug] setup call size... - or a4, a5, a4 // [for debug] set upper two bits of return PC - addx2 a4, a5, a4 // [for debug] clear upper bit -# else - movi a4, 0 /* terminate stack frames, overflow check */ -# endif - _entry a1, ESF_TOTALSIZE - -/* Reset the interrupt level to xtos locklevel (lvl 6 on most systems) */ - - rsil a15, XTOS_LOCKLEVEL - -#if SINGLE_INTERRUPT /* if only one interrupt at this priority level... */ - -/* Preserve the SAR, loop, MAC16 regs and coprocessors. Also, clear the interrupt. */ - -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp0 - xchal_cp0_store a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp1 - xchal_cp1_store a11, a12, a13, a14, a15 -#endif -#endif - rsr.sar a14 - movi a12, INTERRUPT_MASK - s32i a14, a1, UEXC_sar - wsr.intclear a12 // clear if edge-trig or s/w or wr/err (else no effect) - save_loops_mac16 a1, a13, a14 - - /* switch to interrupt stack */ - xtos_int_stack_addr_percore a13, _INTERRUPT_LEVEL, xtos_stack_for_interrupt - s32i a1, a13, 0 - addi a1, a13, SOF_STACK_SIZE - - /* set stack base and size for interrupt context */ - xtos_addr_percore a11, xtos_interrupt_ctx - s32i a13, a11, TC_stack_base - movi a13, SOF_STACK_SIZE - s32i a13, a11, TC_stack_size - - /* save task context */ - xtos_task_ctx_percore a13 - xtos_store_percore a13, a14, xtos_saved_ctx - - /* set interrupt task context */ - xtos_task_ctx_store_percore a11, a14 - -/* Load the handler from the table, initialize two args (interrupt - * number and exception stack frame), then call the interrupt handler. - * Note: The callx12 preserves the original user task's a4..a15.*/ - - xtos_on_wakeup - -#if CONFIG_SMP - xtos_addr_percore_add a12, xtos_interrupt_table, MAPINT(SINGLE_INT_NUM)*XIE_SIZE -#else - movi a12, xtos_interrupt_table + (MAPINT(SINGLE_INT_NUM) * XIE_SIZE) -#endif - l32i a13, a12, XIE_HANDLER - l32i a14, a12, XIE_ARG - mov a15, a1 - callx12 a13 - -#else /* > 1 interrupts at this priority level */ - -/* Get bit list of pending interrupts at the current interrupt priority level. - * If bit list is empty, interrupt is spurious (can happen if a - * genuine interrupt brings control this direction, but the interrupt - * goes away before we read the INTERRUPT register). Also save off - * sar, loops, mac16 registers and coprocessors. */ - -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp0 - xchal_cp0_store a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp1 - xchal_cp1_store a11, a12, a13, a14, a15 -#endif -#endif - rsr.interrupt a15 - rsr.intenable a12 - movi a13, INTERRUPT_MASK - and a15, a15, a12 - and a15, a15, a13 - rsr.sar a14 - s32i a14, a1, UEXC_sar - save_loops_mac16 a1, a13, a14 - - /* switch to interrupt stack */ - xtos_int_stack_addr_percore a13, _INTERRUPT_LEVEL, xtos_stack_for_interrupt - s32i a1, a13, 0 - addi a1, a13, SOF_STACK_SIZE - - _beqz a15, LABEL(spurious,int) - - /* set stack base and size for interrupt context */ - xtos_addr_percore a11, xtos_interrupt_ctx - s32i a13, a11, TC_stack_base - movi a13, SOF_STACK_SIZE - s32i a13, a11, TC_stack_size - - /* save task context */ - xtos_task_ctx_percore a13 - xtos_store_percore a13, a14, xtos_saved_ctx - - /* set interrupt task context */ - xtos_task_ctx_store_percore a11, a14 - - xtos_on_wakeup - -/* Loop to handle all pending interrupts. */ - -LABEL(.L1,_loop0): - neg a12, a15 - and a12, a12, a15 - wsr.intclear a12 // clear if edge-trig or s/w or wr/err (else no effect) -#if CONFIG_SMP - xtos_addr_percore a13, xtos_interrupt_table -#else - movi a13, xtos_interrupt_table -#endif - find_ms_setbit a15, a12, a14, 0 - mapint a15 - addx8 a12, a15, a13 - l32i a13, a12, XIE_HANDLER - l32i a14, a12, XIE_ARG - mov a15, a1 - callx12 a13 - - rsr.interrupt a15 - rsr.intenable a12 - movi a13, INTERRUPT_MASK - and a15, a15, a12 - and a15, a15, a13 - _bnez a15, LABEL(.L1,_loop0) - -#endif /* SINGLE_INTERRUPT */ - -/* Restore everything, and return. */ - - /* restore task context if needed */ - xtos_task_ctx_percore a11 - xtos_addr_percore a12, xtos_interrupt_ctx - bne a11, a12, restore_cp - xtos_addr_percore a12, xtos_saved_ctx - xtos_task_ctx_store_percore a12, a11 - -restore_cp: -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - xtos_task_ctx_percore a11 - beqz a11, no_context_2 - l32i a11, a11, TC_stack_pointer - addi a11, a11, UEXC_cp0 - xchal_cp0_load a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - xtos_task_ctx_percore a11 - beqz a11, no_context_2 - l32i a11, a11, TC_stack_pointer - addi a11, a11, UEXC_cp1 - xchal_cp1_load a11, a12, a13, a14, a15 -#endif -#endif - -no_context_2: - restore_loops_mac16 a1, a13, a14, a15 - l32i a14, a1, UEXC_sar -LABEL(spurious,int): - -#if XCHAL_HAVE_EXCLUSIVE - // Clear exclusive monitors. - clrex -#endif - - movi a0, LABEL(return,from_exc) - movi a13, 0xC0000000 - wsr.sar a14 - or a0, a0, a13 - addx2 a0, a13, a0 -# if _INTERRUPT_LEVEL < XCHAL_EXCM_LEVEL -/* Raise the interrupt mask before - * returning to avoid a race condition where we deallocate the - * exception stack frame but still have more register values to - * restore from it. */ - rsil a14, XCHAL_EXCM_LEVEL -# endif - retw -LABEL(return,from_exc): - /* a5 contains interrupt stack pointer */ - addi a5, a5, -SOF_STACK_SIZE - l32i a5, a5, 0 - -# if XTOS_CNEST - s32i a2, a5, ESF_TOTALSIZE-20 // restore nested-C-func call-chain ptr -# endif - - /* store sp after returning from handler */ - s32i a1, a5, UEXC_a1 - -restore: - /* load registers for window spill */ - l32i a4, a5, UEXC_a4 - l32i a6, a5, UEXC_a6 - l32i a7, a5, UEXC_a7 - l32i a8, a5, UEXC_a8 - l32i a9, a5, UEXC_a9 - l32i a10, a5, UEXC_a10 - l32i a11, a5, UEXC_a11 - l32i a12, a5, UEXC_a12 - l32i a13, a5, UEXC_a13 - l32i a14, a5, UEXC_a14 - - /* check if switch is needed */ - xtos_addr_percore a2, xtos_saved_sp - xtos_task_ctx_percore a1 - beqz a1, noSwitch - l32i a1, a1, TC_stack_pointer - l32i a0, a2, 0 - beq a0, a1, noSwitch - -doSwitch: - /* store new task sp */ - s32i a1, a2, 0 - - /* restore sp of task being preempted */ - l32i a1, a5, UEXC_a1 - - /* spill register windows to the stack */ - rsr.ps a2 - movi a3, PS_WOE_MASK - xor a2, a2, a3 - wsr.ps a2 - - call0 xthal_window_spill_nw - - /* restore previous ps */ - rsr.ps a2 - movi a3, PS_WOE_MASK - or a2, a2, a3 - wsr.ps a2 - - /* change stack */ - xtos_addr_percore a5, xtos_saved_sp - l32i a5, a5, 0 - j restore - -noSwitch: - /* restore ps and pc */ - l32i a0, a5, UEXC_ps - writesr eps _INTERRUPT_LEVEL a0 - rsync - l32i a0, a5, UEXC_pc - writesr epc _INTERRUPT_LEVEL a0 - - /* restore sar, loops and mac16 registers */ - l32i a0, a5, UEXC_sar - wsr.sar a0 - restore_loops_mac16 a5, a0, a1, a2 - - /* restore rest of the registers */ - l32i a0, a5, UEXC_a0 - l32i a1, a5, UEXC_a1 - l32i a2, a5, UEXC_a2 - l32i a3, a5, UEXC_a3 - l32i a15, a5, UEXC_a15 - l32i a5, a5, UEXC_a5 - rfi _INTERRUPT_LEVEL - - .size LABEL(_Level,FromVector), . - LABEL(_Level,FromVector) - - // This symbol exists solely for the purpose of being able to pull-in this - // dispatcher using _xtos_dispatch_level<n>() routines with the tiny-rt LSP: - .global LABEL(_Level,HandlerLabel) - .set LABEL(_Level,HandlerLabel), 0 - -#endif /* XCHAL_HAVE_INTERRUPT */ diff --git a/src/arch/xtensa/xtos/int-sethandler.c b/src/arch/xtensa/xtos/int-sethandler.c deleted file mode 100644 index 5d5a06d55c40..000000000000 --- a/src/arch/xtensa/xtos/int-sethandler.c +++ /dev/null @@ -1,88 +0,0 @@ - -/* int-sethandler.c - register an interrupt handler in XTOS */ - -/* - * Copyright (c) 1999-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 "xtos-internal.h" -#include "xtos-structs.h" -#include <sof/lib/cpu.h> -#include <config.h> - -#if XCHAL_HAVE_INTERRUPTS -#if CONFIG_SMP -extern struct xtos_core_data *core_data_ptr[PLATFORM_CORE_COUNT]; -#else -/* - * Table of interrupt handlers. - * NOTE: if the NSA/NSAU instructions are configured, then to save - * a few cycles in the interrupt dispatcher code, the - * xtos_interrupt_table[] array is filled in reverse. - * IMPORTANT: Use the MAPINT() macro defined in xtos-internal.h to index entries in this array. - */ -extern XtosIntHandlerEntry xtos_interrupt_table[XCHAL_NUM_INTERRUPTS]; -#endif -#endif - -_xtos_handler _xtos_set_interrupt_handler_arg( int n, _xtos_handler f, void *arg ) -{ -#if XCHAL_HAVE_INTERRUPTS - XtosIntHandlerEntry *entry; - _xtos_handler old; - _xtos_handler ret; - - if( (n < 0) || (n >= XCHAL_NUM_INTERRUPTS) ) { - ret = 0; /* invalid interrupt number */ - } - else if( (int) Xthal_intlevel[n] > XTOS_LOCKLEVEL ) { - ret = 0; /* priority level too high to safely handle in C */ - } - else { -#if CONFIG_SMP - entry = &(core_data_ptr[cpu_get_id()]->xtos_int_data.xtos_interrupt_table.array[MAPINT(n)]); -#else - entry = xtos_interrupt_table + MAPINT(n); -#endif - old = entry->handler; - if (f) { - entry->handler = f; - entry->u.varg = arg; - } else { - entry->handler = &xtos_unhandled_interrupt; - entry->u.narg = n; - } - ret = (old == &xtos_unhandled_interrupt) ? 0 : old; - } - - return ret; -#else - return 0; -#endif -} - - -_xtos_handler _xtos_set_interrupt_handler( int n, _xtos_handler f ) -{ - return _xtos_set_interrupt_handler_arg( n, f, (void *) n ); -} - diff --git a/src/arch/xtensa/xtos/int-vector.S b/src/arch/xtensa/xtos/int-vector.S deleted file mode 100644 index f23ad50844b7..000000000000 --- a/src/arch/xtensa/xtos/int-vector.S +++ /dev/null @@ -1,70 +0,0 @@ -// int-vector.S - Interrupt Vector Template (for levels > 1) -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/int-vector.S#1 $ - -// Copyright (c) 2003-2017 Tensilica 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. - - -// To use this template file, define a macro called _INTERRUPT_LEVEL -// to be the interrupt level of the vector, include "xtos-internal.h", -// then include this file. We use the same template for both high-level -// and medium-level interrupts, but not debug level. - - -#define _ASMLANGUAGE -#include "xtos-internal.h" -#include <xtensa/coreasm.h> -#include <xtensa/config/system.h> - - -#if XCHAL_HAVE_INTERRUPTS && (_INTERRUPT_LEVEL <= XCHAL_NUM_INTLEVELS) && (_INTERRUPT_LEVEL != XCHAL_DEBUGLEVEL) - - .begin literal_prefix LABEL(.Level,InterruptVector) - .section LABEL(.Level,InterruptVector.text), "ax" - .align 4 - .global LABEL(_Level,Vector) -LABEL(_Level,Vector): - // Medium and high priority interrupt vector: - -# if HAVE_XSR - // With XSR, we can use this vector which has the advantage of being ROMable - // without requiring the handler to also be in ROM; however, it requires - // initializing the EXCSAVEn register (see reset-vector.S) and a slightly - // different save/restore sequence in the handler: - hw_erratum_487_fix - xchgsr excsave _INTERRUPT_LEVEL a2 - jx a2 - - // Pull-in the real handler by reference, to ensure the reset vector gets it: - .global LABEL(_Level,FromVector) - -# else - writesr excsave _INTERRUPT_LEVEL a2 - movi a2, LABEL(_Level,FromVector) - jx a2 -# endif - - .size LABEL(_Level,Vector), . - LABEL(_Level,Vector) - .text - .end literal_prefix - -#endif /* interrupt at that level */ - diff --git a/src/arch/xtensa/xtos/interrupt-pri.h b/src/arch/xtensa/xtos/interrupt-pri.h deleted file mode 100644 index ae22cd2b5761..000000000000 --- a/src/arch/xtensa/xtos/interrupt-pri.h +++ /dev/null @@ -1,177 +0,0 @@ -/* interrupt-pri.h - Definitions and macros related to interrupt prioritization */ -/* - * Copyright (c) 2002-2004, 2006 Tensilica 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. - */ - -#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) -# error "The interrupt-pri.h header file is meant for inclusion by assembly source code only." -#endif - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - -/* - * The following macros are used by int-lowpri-dispatcher.S to - * implement prioritized interrupt dispatching and fairness. - * The prioritization scheme is set by XTOS parameters in xtos-params.h . - */ - - -#if XCHAL_HAVE_INTERRUPTS - - // msindex_int - // - // Return in register \aindex the index of the first (most significant) bit set - // in register \amask. - // Register \amask is clobbered (modified) by this macro. - // - // Note: this code is similar to the find_ms_setbit macro in <xtensa/coreasm.h>. - // - .macro msindex_int aindex, amask -# if XCHAL_HAVE_NSA - nsau \aindex, \amask // \aindex = interrupt index, from 0 to 31, from left to right - //movi \amask, 31 - //sub \aindex, \amask, \aindex -# else - movi \aindex, 0 // start with result of 0 (point to lsbit of 32) -# if XCHAL_NUM_INTERRUPTS > 16 - bltui \amask, 0x10000, 2f // is it one of the 16 lsbits? (if so, check lower 16 bits) - addi \aindex, \aindex, 16 // no, increment result to upper 16 bits (of 32) - extui \amask, \amask, 16, 16 // check upper half (shift right 16 bits) -2: -# endif -# if XCHAL_NUM_INTERRUPTS > 8 - bltui \amask, 0x100, 2f // is it one of the 8 lsbits? (if so, check lower 8 bits) - addi \aindex, \aindex, 8 // no, increment result to upper 8 bits (of 16) - srli \amask, \amask, 8 // shift right to check upper 8 bits -2: -# endif -# if XCHAL_NUM_INTERRUPTS > 4 - bltui \amask, 0x10, 2f // is it one of the 4 lsbits? (if so, check lower 4 bits) - addi \aindex, \aindex, 4 // no, increment result to upper 4 bits (of 8) - srli \amask, \amask, 4 // shift right 4 bits to check upper half -2: -# endif - bltui \amask, 0x4, 2f // is it one of the 2 lsbits? (if so, check lower 2 bits) - addi \aindex, \aindex, 2 // no, increment result to upper 2 bits (of 4) - srli \amask, \amask, 2 // shift right 2 bits to check upper half -2: - bltui \amask, 0x2, 2f // is it the lsbit? - addi \aindex, \aindex, 1 // no, increment result to upper bit (of 2) -2: // done! -# endif /*!NSA*/ - // HERE: \aindex = index of interrupt to handle - // \amask is available - .endm - - - // msindex_int_nc - // - // Same as msindex_int, but does not clobber \amask. - // Uses extra register \atmp (a temporary register) if needed. - // - .macro msindex_int_nc aindex, amask, atmp -# if XCHAL_HAVE_NSA - msindex_int \aindex, \amask // does not clobber \amask in this case -# else - mov \atmp, \amask - msindex_int \aindex, \atmp -# endif - .endm - - - // indexmask_int - // - // Compute index of highest priority interrupt in given mask, - // and trim mask to single bit corresponding to that interrupt. - // This is used for interrupt dispatching. - // - // Entry: - // \index = (undefined) - // \mask = non-zero mask of interrupt bits to consider handling - // \intptr = &_xtos_intstruct if INTENABLE virtualized, else undefined - // \tmp = (undefined) - // Exit: - // \index = index of interrupt (reversed if NSA present) - // \mask = single bit corresponding to index - // \intptr = (preserved) - // \tmp = (clobbered) - // - .macro indexmask_int index, mask, intptr, tmp -# if XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_LO - - msindex_int \index, \mask // \index = index of msbit set in \mask (\tmp is tmp, \mask clobbered) - // \index now contains the index of the highest priority pending+enabled interrupt. -# if XCHAL_HAVE_NSA - movi \mask, 0x80000000 - ssr \index - srl \mask, \mask // \mask = single bit set corresponding to interrupt to be processed... -# else - movi \mask, 1 - ssl \index - sll \mask, \mask // \mask = single bit set corresponding to interrupt to be processed... -# endif - -# elif XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI - - neg \index, \mask // find lsbit in \mask ... - and \mask, \index, \mask // ... - msindex_int_nc \index, \mask, \tmp // \index = index of msbit set in \mask (\tmp is tmp, \mask not clobbered) - -# else -# error Unsupported priority ordering. -# endif /*SUBPRI_ORDER*/ - .endm - - - // index_int - // - // Compute index of highest priority interrupt in given mask. - // This is used for fairness computations. - // - // Entry: - // \index = (undefined) - // \mask = non-zero mask of interrupt bits to consider handling - // \intptr = &_xtos_intptr - // \tmp = (undefined) - // Exit: - // \index = index of interrupt (reversed if NSA present) - // \mask = (preserved) - // \intptr = (preserved) - // \tmp = (clobbered) - // - .macro index_int index, mask, intptr, tmp -# if XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_LO - msindex_int_nc \index, \mask, \tmp // \index = index of msbit set in \mask (\mask not clobbered) -# elif XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI - neg \tmp, \mask // find lsbit in \mask ... - and \tmp, \tmp, \mask // ... - msindex_int \index, \tmp // \index = index of msbit set in \tmp (\tmp is clobbered) -# else -# error oops -# endif - .endm // index_int - - -#endif /* XCHAL_HAVE_INTERRUPTS */ - - diff --git a/src/arch/xtensa/xtos/interrupt-table.S b/src/arch/xtensa/xtos/interrupt-table.S deleted file mode 100644 index aad8a275949d..000000000000 --- a/src/arch/xtensa/xtos/interrupt-table.S +++ /dev/null @@ -1,129 +0,0 @@ -// interrupt-table.S - Interrupt handler table and default handler - -// Copyright (c) 2004-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 <config.h> -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - -#if !CONFIG_SMP -#if XCHAL_HAVE_INTERRUPTS - - .data - - .global _xtos_intstruct - .align 8 -_xtos_intstruct: -# if XTOS_VIRTUAL_INTENABLE - .global _xtos_enabled - .type _xtos_enabled,@object - .size _xtos_enabled,4 - .global _xtos_vpri_enabled - .type _xtos_vpri_enabled,@object - .size _xtos_vpri_enabled,4 -_xtos_enabled: .word 0 -_xtos_vpri_enabled: .word 0xFFFFFFFF -# endif -# if XTOS_VIRTUAL_INTERRUPT -# error Virtualized INTERRUPT register not yet supported. - .global _xtos_pending - .type _xtos_pending,@object - .size _xtos_pending,4 -_xtos_pending: .word 0 -# endif - - /* - * Table of C-level interrupt handlers (and args, etc) for each interrupt. - * NOTE: if the NSA/NSAU instructions are configured, then to save a few - * cycles in the interrupt dispatcher code, this table is filled in reverse. - * C code uses the MAPINT() macro defined in xtos-internal.h to index entries. - * NOTE: Under some conditions (turned off by default in xtos-params.h), - * this table gets properly initialized by the _xtos_init() function in - * init.c . NOTA: A future enhancement may be to always configure - * and build this table at build-time rather than ever doing it at run-time. - */ -#define i .Li /* workaround a silly GDB testsuite regression */ - .data - .global xtos_interrupt_table - .align 8 -xtos_interrupt_table: - .set i, XCHAL_HAVE_NSA*(XCHAL_NUM_INTERRUPTS-1) - .rept XCHAL_NUM_INTERRUPTS - .word xtos_unhandled_interrupt - .word i // parameter: interrupt number - .set i, i+1-(XCHAL_HAVE_NSA*2) - .endr - -# if XIE_EXTEND - /* MUST *IMMEDIATELY* follow xtos_interrupt_table: */ - .global xtos_interrupt_mask_table -xtos_interrupt_mask_table: - .set i, XCHAL_HAVE_NSA*(XCHAL_NUM_INTERRUPTS-1) - .rept XCHAL_NUM_INTERRUPTS - /* Default to all low-priority (level-one) interrupts at their own virtual priority: */ -# if XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI - .word ((1<<i)-1) | ~XCHAL_LOWPRI_MASK // vpri_mask default - lower-numbered ints (and high/medium-pri ints) pre-empt other low-pri ints -# else - .word (-2*(1<<i)) | ~XCHAL_LOWPRI_MASK // vpri_mask default - higher-numbered ints (and high/medium-pri ints) pre-empt other low-pri ints -# endif - .word (1<<i) // level_mask default - each low-pri (level-one) interrupt at its own subpriority - .set i, i+1-(XCHAL_HAVE_NSA*2) - .endr -# endif /*XIE_EXTEND*/ - -#endif /* XCHAL_HAVE_INTERRUPTS */ - - .text -#endif /* CONFIG_SMP */ - -#if XCHAL_HAVE_INTERRUPTS - - // - // void xtos_unhandled_interrupt( int n ); - // - // Default/empty interrupt handler. - // This is used for interrupts with no registered handler. - // Parameter n is the interrupt number (0 thru 31). - // - - .text - .align 4 - .global xtos_unhandled_interrupt - .type xtos_unhandled_interrupt,@function - -xtos_unhandled_interrupt: - abi_entry -# if XCHAL_HAVE_DEBUG - // Break into the debugger if one is present and active: -# if XCHAL_NUM_INTLEVELS > XCHAL_DEBUGLEVEL - rsil a3, XCHAL_DEBUGLEVEL-1 // ensure break takes effect -# endif - break 1, 15 // unhandled (unregistered) interrupt $a2 -# else -1: j 1b // unhandled interrupt - loop forever -# endif - abi_return - - .size xtos_unhandled_interrupt, . - xtos_unhandled_interrupt - -#endif /* XCHAL_HAVE_INTERRUPTS */ - diff --git a/src/arch/xtensa/xtos/ints-off.S b/src/arch/xtensa/xtos/ints-off.S deleted file mode 100644 index a45eff347a1b..000000000000 --- a/src/arch/xtensa/xtos/ints-off.S +++ /dev/null @@ -1,78 +0,0 @@ -// ints-off.S - Interrupt related assembler code - _xtos_ints_off - -// Copyright (c) 2004-2015 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -/*************************************************************************** - * _xtos_ints_on() and _xtos_ints_off() are used - * to enable and disable interrupts from C code; - * they can be called from the application or from a C interrupt handler. - */ - -// u32 _xtos_ints_off( u32 mask ); [T1050.0 docs this as returning old INTENABLE value] -// Disables a set of interrupts. See _xtos_ints_on(). -// -// MUST NOT be called when PS.INTLEVEL > XTOS_LOCKLEVEL -// (otherwise PS.INTLEVEL gets lowered; and operation may be inconsistent -// if this is called in the handler of an interrupt of level > LOCKLEVEL). -// - .text - .align 4 - .global _xtos_ints_off - .type _xtos_ints_off,@function -_xtos_ints_off: - abi_entry -#if XCHAL_HAVE_INTERRUPTS && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) -# if XTOS_VIRTUAL_INTENABLE -#if CONFIG_SMP - xtos_addr_percore a4, xtos_intstruct -#else - movi a4, _xtos_intstruct -#endif - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - l32i a3, a4, XTOS_ENABLED_OFS // a3 = xtos_enabled - l32i a6, a4, XTOS_VPRI_ENABLED_OFS // a6 = xtos_vpri_enabled - or a5, a3, a2 // a5 = xtos_enabled | mask - xor a5, a5, a2 // a5 = xtos_enabled & ~mask - s32i a5, a4, XTOS_ENABLED_OFS // xtos_enabled &= ~mask - and a5, a5, a6 // a5 = xtos_enabled & xtos_vpri_enabled -# else - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - rsr.intenable a3 - //interlock - or a5, a3, a2 // a5 = INTENABLE | mask - xor a5, a5, a2 // a5 = INTENABLE & ~mask -# endif - wsr.intenable a5 - xtos_unlock a7 - mov a2, a3 // return previous (virtual or real) INTENABLE value -#else /*XCHAL_HAVE_INTERRUPTS*/ - movi a2, 0 // this config does not have interrupts, so return 0 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - - .size _xtos_ints_off, . - _xtos_ints_off - diff --git a/src/arch/xtensa/xtos/ints-on.S b/src/arch/xtensa/xtos/ints-on.S deleted file mode 100644 index f14c1194ce1a..000000000000 --- a/src/arch/xtensa/xtos/ints-on.S +++ /dev/null @@ -1,79 +0,0 @@ -// ints-on.S - Interrupt related assembler code - _xtos_ints_on - -// Copyright (c) 2004-2015 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - - -/*************************************************************************** - * _xtos_ints_on() and _xtos_ints_off() are used - * to enable and disable interrupts from C code; - * they can be called from the application or from a C interrupt handler. - */ - - -// u32 _xtos_ints_on( u32 mask ); -// Enables a set of interrupts. -// With INTENABLE virtualizing, does not simply set INTENABLE directly, but rather -// computes it as a function of the current virtual priority. -// -// MUST NOT be called when PS.INTLEVEL > XTOS_LOCKLEVEL -// (otherwise PS.INTLEVEL gets lowered; and operation may be inconsistent -// if this is called in the handler of an interrupt of level > LOCKLEVEL). -// - .text - .align 4 - .global _xtos_ints_on - .type _xtos_ints_on,@function -_xtos_ints_on: - abi_entry -#if XCHAL_HAVE_INTERRUPTS && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) -# if XTOS_VIRTUAL_INTENABLE -#if CONFIG_SMP - xtos_addr_percore a4, xtos_intstruct -#else - movi a4, _xtos_intstruct -#endif - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - l32i a3, a4, XTOS_ENABLED_OFS // a3 = xtos_enabled - l32i a6, a4, XTOS_VPRI_ENABLED_OFS // a6 = xtos_vpri_enabled - or a5, a3, a2 // xtos_enabled | mask - s32i a5, a4, XTOS_ENABLED_OFS // xtos_enabled |= mask - and a5, a5, a6 // a5 = xtos_enabled & xtos_vpri_enabled -# else - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - rsr.intenable a3 - //interlock - or a5, a3, a2 // INTENABLE | mask -# endif - wsr.intenable a5 - xtos_unlock a7 - mov a2, a3 // return previous (virtual or real) INTENABLE value -#else /*XCHAL_HAVE_INTERRUPTS*/ - movi a2, 0 // this config does not have interrupts, so return 0 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - - .size _xtos_ints_on, . - _xtos_ints_on - diff --git a/src/arch/xtensa/xtos/kernel-vector.S b/src/arch/xtensa/xtos/kernel-vector.S deleted file mode 100644 index 3f86b0ea4857..000000000000 --- a/src/arch/xtensa/xtos/kernel-vector.S +++ /dev/null @@ -1,73 +0,0 @@ -// kernel-vector.S - Kernel Vector for General Exceptions -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/kernel-vector.S#1 $ - -// Copyright (c) 1999-2015 Tensilica 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. - -/* - * General exceptions in kernel vector mode (PS.UM==0) go to this kernel - * vector. This kernel vector does very little. - * Under normal operation of the single-threaded runtime ("XTOS"), kernel - * vectored general exceptions do not occur, so nothing needs to be done. - * However when debugging, such as when writing exception and - * interrupt handlers, kernel vectored exceptions may occur. - * They are usually the sign of a bug, so here we take a breakpoint - * (if debug option enabled) or take drastic action (infinite loop) - * otherwise. - * - * XTOS does not allow exceptions in interrupt or exception handlers. - * If it did, a more elaborate kernel vector handler would be needed. - * See the Xtensa Microprocessor Programmer's Guide for an - * example of how to implement such a kernel vector handler. - */ - -#include <xtensa/coreasm.h> -#include <xtensa/config/system.h> -#ifdef SIMULATOR -#include <xtensa/simcall.h> -#endif - -#if XCHAL_HAVE_EXCEPTIONS && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) - - .begin literal_prefix .KernelExceptionVector - .section .KernelExceptionVector.text, "ax" - - .align 4 - .global _KernelExceptionVector -_KernelExceptionVector: - -# if XCHAL_HAVE_DEBUG -1: break 1,0 // unexpected kernel exception -# elif defined(SIMULATOR) - wsr a2, EXCSAVE1 // save a2 where simulator expects it - movi a2, SYS_unhandled_kernel_exc -1: simcall // let simulator/debugger report unhandled exception -# else -1: -# endif - j 1b // infinite loop - unexpected kernel exception - - .size _KernelExceptionVector, . - _KernelExceptionVector - .text - .end literal_prefix - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/memctl_default.S b/src/arch/xtensa/xtos/memctl_default.S deleted file mode 100644 index 164f2c2d2f58..000000000000 --- a/src/arch/xtensa/xtos/memctl_default.S +++ /dev/null @@ -1,42 +0,0 @@ -// memctl_default.S - Default startup value for MEMCTL register. - -// Copyright (c) 1998-2015 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 <xtensa/coreasm.h> -#include <xtensa/config/system.h> - - -// This file just contains this one symbol, used by the reset code. -// It is here rather than in reset-vector.S because we want the symbol -// to be external, so resolution is delayed until link time. -// -// To define your own value to override this default, redefine the -// symbol __memctl_default to the desired value, e.g. - -// -// xt-xcc test.c -g -o test -Wl,--defsym=__memctl_default=0x08080808 -// - - .global __memctl_default - .weak __memctl_default - .equ __memctl_default, XCHAL_CACHE_MEMCTL_DEFAULT - diff --git a/src/arch/xtensa/xtos/memep-enable.S b/src/arch/xtensa/xtos/memep-enable.S deleted file mode 100644 index c3724204675c..000000000000 --- a/src/arch/xtensa/xtos/memep-enable.S +++ /dev/null @@ -1,63 +0,0 @@ -// memep-enable.S -- Turn on local memory ECC/parity checking -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/memep-enable.S#1 $ - -// Copyright (c) 2006-2010 Tensilica 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 <xtensa/coreasm.h> - - - /* - * void _xtos_memep_enable(int flags); - * - * Turn on local memory ECC/parity checking, for both - * data access and instruction fetch. - * - * For now, flags are ignored. Caller is expected to pass zero. - * - * _xtos_memep_initrams() must have already been called, if necessary, - * to ensure all ECC/parity bits are valid in any local instruction - * or data RAM. The normal reset vector sequence already takes care - * of initializing any local cache ECC/parity bits. - */ - .text - .align 4 - .global _xtos_memep_enable -_xtos_memep_enable: - abi_entry - -#if XCHAL_HAVE_MEM_ECC_PARITY - - // Local Memory ECC/Parity option initialization - // - // NOTE: We turn on exceptions on correctable errors and correct - // them in the memory error handler. - movi a2, MESR_ERRENAB | MESR_DATEXC | MESR_INSEXC - wsr a2, MESR - isync - -#endif /* XCHAL_HAVE_MEM_ECC_PARITY */ - - movi a2, 0 // successfully turned on what we could - abi_return - - .size _xtos_memep_enable, . - _xtos_memep_enable - diff --git a/src/arch/xtensa/xtos/memep-initrams.S b/src/arch/xtensa/xtos/memep-initrams.S deleted file mode 100644 index 8cc399e55c59..000000000000 --- a/src/arch/xtensa/xtos/memep-initrams.S +++ /dev/null @@ -1,91 +0,0 @@ -// memep-initrams.S -- Initialize local memory ECC/parity -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/memep-initrams.S#1 $ - -// Copyright (c) 2006-2010 Tensilica 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 <xtensa/coreasm.h> - - - /* - * void _xtos_memep_initrams(void); - * - * Most reset vectors initialize caches, leaving only the local memories - * (instruction and data RAMs) with potentially some words that have - * not been written to and thus have uninitialized ECC/parity bits. - * Loading such a word after enabling ECC/parity checking would result - * in an exception (or memory error reported in MESR). To avoid this, - * an application must either carefully avoid loading from uninitialized - * words, or ensure it writes to every instruction and data RAM word. - * The latter is what this function does. It reads and writes every - * word of every local instruction and data RAM. It should normally - * be called with interrupts disabled. An interrupt might come in - * between a load and store, in which case any modification made by the - * interrupt handler to that local memory location is lost when this - * function resumes and does the store. If no interrupt handler makes - * any persistent modification to local memories, disabling them around - * a call to this function may be unnecessary. - * - * On the simulator (ISS), everything comes up zeroed, so no there is - * no need for this initialization. - */ - .text - .align 4 - .global _xtos_memep_initrams -_xtos_memep_initrams: - abi_entry - - // Local Memory ECC/Parity option initialization -#if XCHAL_HAVE_MEM_ECC_PARITY && (XCHAL_NUM_DATARAM || XCHAL_NUM_INSTRAM /*|| XCHAL_NUM_URAM || XCHAL_NUM_XLMI*/) && !defined(SIMULATOR) - .section .rodata, "a" - .align 4 -.L_locmemep_start: -# if XCHAL_NUM_DATARAM >= 1 && XCHAL_DATARAM0_ECC_PARITY - .long XCHAL_DATARAM0_VADDR, XCHAL_DATARAM0_VADDR+XCHAL_DATARAM0_SIZE -# endif -# if XCHAL_NUM_DATARAM >= 2 && XCHAL_DATARAM1_ECC_PARITY - .long XCHAL_DATARAM1_VADDR, XCHAL_DATARAM1_VADDR+XCHAL_DATARAM1_SIZE -# endif -# if XCHAL_NUM_INSTRAM >= 1 && XCHAL_INSTRAM0_ECC_PARITY - .long XCHAL_INSTRAM0_VADDR, XCHAL_INSTRAM0_VADDR+XCHAL_INSTRAM0_SIZE -# endif -# if XCHAL_NUM_INSTRAM >= 2 && XCHAL_INSTRAM1_ECC_PARITY - .long XCHAL_INSTRAM1_VADDR, XCHAL_INSTRAM1_VADDR+XCHAL_INSTRAM1_SIZE -# endif -.L_locmemep_end: - .text - movi a5, .L_locmemep_start // start of table of local memory ranges - movi a6, .L_locmemep_end // end of table ... -2: l32i a3, a5, 0 // start of local memory - l32i a4, a5, 4 // end of local memory - addi a5, a5, 8 // (next entry in table) -1: l32i a2, a3, 0 // load and store every word of local memory... - s32i a2, a3, 0 // ... to initialize all parity and/or ECC bits - addi a3, a3, 4 - bltu a3, a4, 1b // loop until whole memory initialized - bltu a5, a6, 2b // loop until all memories initialized - // ECC/parity bits are now initialized, checking can be turned on. -#endif /* ECC/parity on instruction or data RAM(s) */ - - abi_return - - .size _xtos_memep_initrams, . - _xtos_memep_initrams - diff --git a/src/arch/xtensa/xtos/memerror-vector.S b/src/arch/xtensa/xtos/memerror-vector.S deleted file mode 100644 index 460b58ac997b..000000000000 --- a/src/arch/xtensa/xtos/memerror-vector.S +++ /dev/null @@ -1,581 +0,0 @@ -/* memerror-vector.S -- Memory Error Exception Vector and Handler */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/memerror-vector.S#1 $ */ - -/* - * Copyright (c) 2006-2013 Tensilica 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. - */ - - -/* - * This handler supports multiple user hooks to handle various cases. - * This is the list of available hooks: - * - * _xtos_merr_hook_fatal_dme -- fatal error, double memory exception - * _xtos_merr_hook_uncorrectable_local -- fatal error, uncorrectable error in IRAM/DRAM - * _xtos_merr_hook_uncor_dtag -- fatal error, uncorrectable error in dcache tag - * _xtos_merr_hook_uncor_dirty -- fatal error, uncorrectable error in dirty dcache data - * _xtos_merr_hook_icache_relock -- non-fatal, hook to relock icache - * _xtos_merr_hook_dcache_relock -- non-fatal, hook to relock dcache - * _xtos_merr_hook_nonfatal -- non-fatal, correctable error - */ - - -#include <xtensa/coreasm.h> -#include <xtensa/corebits.h> - -#if XCHAL_HAVE_MEM_ECC_PARITY -# if defined(__SPLIT__vector) - - // Place this code in the memory error exception vector: - .begin literal_prefix .MemoryExceptionVector - .section .MemoryExceptionVector.text, "ax" - - .global _MemErrorVector - .align 4 -_MemErrorVector: -# if 0 /* XCHAL_HAVE_DEBUG */ - // Memory errors raise PS.INTLEVEL above DEBUGLEVEL, so - // break instructions have no effect within them (debug - // exceptions are masked). So leave commented out for now. - break 1, 5 // unhandled memory error exception -# endif - xsr.mesave a0 - jx a0 - - .size _MemErrorVector, . - _MemErrorVector - .text - .end literal_prefix - - -# elif defined(__SPLIT__handler) - -/* - * Some rules and assumptions: - * - * Anything that can interrupt this handler (e.g. NMI): - * - must not lock or unlock cache lines - */ - - -#define ICACHE_WAYWIDTH (XCHAL_ICACHE_SETWIDTH + XCHAL_ICACHE_LINEWIDTH) /* LICT's "iis" */ -#define DCACHE_WAYWIDTH (XCHAL_DCACHE_SETWIDTH + XCHAL_DCACHE_LINEWIDTH) /* LDCT's "dis" */ -/* NOTE: Memory ECC/parity is not supported on XLMI or on local ROMs: */ -#define HAVE_LOCAL_RAM (XCHAL_NUM_DATARAM || XCHAL_NUM_INSTRAM /*|| XCHAL_NUM_URAM || XCHAL_NUM_XLMI*/) - - -#if XCHAL_DCACHE_LINE_LOCKABLE && XCHAL_DCACHE_WAYS > 1 && XCHAL_HAVE_PREFETCH - .comm _MemErrorSave, 12, 4 -#else - //.lcomm _MemErrorSave, 8 - .comm _MemErrorSave, 8, 4 -#endif - - .text - .align 4 - .global _MemErrorHandler -_MemErrorHandler: - hw_erratum_487_fix - rsr.mesr a0 - bbsi.l a0, MESR_DME_SHIFT, .L_fatal_dme -# if XCHAL_ICACHE_SIZE > 0 || XCHAL_DCACHE_SIZE > 0 - bbsi.l a0, MESR_MEMTYPE_SHIFT+1, .L_cache // branch if error on a cache -# endif - // Error in a local memory. -# if HAVE_LOCAL_RAM - bbsi.l a0, MESR_ERRTYPE_SHIFT, .L_uncorrectable_local - // Correctable error in a local memory (IRAM or DRAM). - // (MEVADDR has all 32 bits, so XSR preserves a register:) - xsr.mevaddr a2 - // Note: MEVADDR is always 4-byte aligned, - // so we can just do L32I/S32I to correct the error. - // However, that's not atomic, and NMI can store in between; - // that's usually a problem for D rather than I, avoid the - // issue using S32C1I if configured (else NMI must not write DataRAM!?!): -# if (XCHAL_HAVE_S32C1I && (XCHAL_NUM_DATARAM /*|| XCHAL_NUM_URAM || XCHAL_NUM_XLMI*/)) - bbci.l a0, MESR_MEMTYPE_SHIFT, .L_instram // branch if error on InstRAM - // Unfortunately we need 3 registers to do S32C1I (data,addr,SCOMPARE1) so - // we need to save to _MemErrorSave: - movi a0, _MemErrorSave - s32i a4, a0, 0 // save a4 - l32i a4, a2, 0 // load data (re-correct) - rsr.scompare1 a0 // save SCOMPARE1 - wsr.scompare1 a4 - s32c1i a4, a2, 0 // store if still contains same value (else other store corrected error) - movi a4, _MemErrorSave - wsr.scompare1 a0 // restore SCOMPARE1 - l32i a4, a4, 0 // restore a4 - j 2f -.L_instram: -# endif - l32i a0, a2, 0 // load data (re-correct) - s32i a0, a2, 0 // store data to correct ECC bits -2: xsr.mevaddr a2 -# endif /* HAVE_LOCAL_RAM */ - - - // Weak reference: if unresolved, links okay but with zero value: - // - // This hook must return using a RET instruction. It will receive - // the return address in a0, and the MESR register value in a2. - // The hook may use and trash a2 and a3, but all other registers - // must be preserved. - - .weak _xtos_merr_hook_nonfatal - -.L_done: - // Finished, now see if there is a user hook to call before returning - movi a0, _xtos_merr_hook_nonfatal // hook address - beqz a0, 1f // no hook, return - movi a0, _MemErrorSave // save area address - s32i a2, a0, 0 // save a2 - s32i a3, a0, 4 // save a3 - movi a0, _xtos_merr_hook_nonfatal // re-load hook address - rsr.mesr a2 // pass MESR value as arg - callx0 a0 // call user hook - movi a3, _MemErrorSave - l32i a2, a3, 0 // restore a2 - l32i a3, a3, 4 // restore a3 -1: movi a0, _MemErrorHandler // handler address - xsr.mesave a0 // restore a0 and MESAVE - rfme - - - // Weak reference: if unresolved, links okay but with zero value: - .weak _xtos_merr_hook_fatal_dme -.L_fatal_dme: - // Fatal (unrecoverable) error, double memory exception - movi a0, _xtos_merr_hook_fatal_dme -1: beqz a0, 1b // fatal double memory error, no hook, so infinite loop - jx a0 // jump to user hook, if present - - -# if HAVE_LOCAL_RAM - // Weak reference: if unresolved, links okay but with zero value: - .weak _xtos_merr_hook_uncorrectable_local -.L_uncorrectable_local: - // Fatal (unrecoverable) error in IRAM or DRAM: parity or uncorrectable ECC error - movi a0, _xtos_merr_hook_uncorrectable_local -1: beqz a0, 1b // fatal memory error, no hook provided, so infinite loop - jx a0 // jump to user hook, if present -# endif - - -# if XCHAL_ICACHE_SIZE > 0 || XCHAL_DCACHE_SIZE > 0 -.L_cache: - // Error in one of the caches. -# endif - -# if XCHAL_ICACHE_SIZE > 0 && XCHAL_HAVE_ICACHE_TEST -# if XCHAL_DCACHE_SIZE > 0 && XCHAL_HAVE_DCACHE_TEST - bbsi.l a0, MESR_MEMTYPE_SHIFT, .L_dcache // branch if data cache error -# endif - // Error in the instruction cache. - bbsi.l a0, MESR_ERRTYPE_SHIFT, .L_icache_noncorr // branch if uncorrectable - // Correctable error in the instruction cache. - xsr.mevaddr a2 - // TODO FIXME: remove these 5 lines if waynum is in MEVADDR!? by using III if tag and IHI otherwise!?!?!?: -# if XCHAL_ICACHE_WAYS > 1 - extui a0, a0, MESR_WAYNUM_SHIFT, 2 - slli a0, a0, ICACHE_WAYWIDTH - slli a2, a2, 32 - ICACHE_WAYWIDTH - srli a2, a2, 32 - ICACHE_WAYWIDTH - or a2, a2, a0 -# endif -# if XCHAL_ICACHE_LINE_LOCKABLE - // Preserve the lock bit. So check the tag... - lict a0, a2 // load i-cache tag - bbci.l a0, XCHAL_ICACHE_TAG_L_SHIFT, .L_icache_corr_unlocked // branch if unlocked - // Correctable error in a locked instruction cache line. - // Fix both tag and one word, quicker than figuring out whether error is in tag or data: - sict a0, a2 // fix tag - // TODO FIXME: on fetch wider than 32-bits, SICW might replicate its 32 bits to the - // whole fetch width rather than just write 32-bits, depending on how customer wires up - // I-cache RAMs. With ECC option and I-cache locking, they need 32-bit word write enables. - licw a0, a2 - sicw a0, a2 // fix data word - j .L_icache_done -.L_icache_corr_unlocked: - // We have to write the whole tag to avoid hitting an error here (if tag error). - // So use IIU (which also invalidates) not III (which reads L bit so can hit error). - iiu a2, 0 // unlock line ==> also invalidates! (I-side only) -# else - iii a2, 0 // invalidate line (whole set!) -# endif -.L_icache_done: - xsr.mevaddr a2 - j .L_done - -.L_icache_noncorr: - // Non-correctable error in the instruction cache. - bbsi.l a0, MESR_MEMTYPE_SHIFT+2, .L_icache_tag_noncorr // branch if tag error - // Non-correctable error in the instruction cache data. - // Just invalidate the line if we can. -# if XCHAL_ICACHE_LINE_LOCKABLE - // If locked, need a different fix sequence. - xsr.mevaddr a2 - -# if XCHAL_ICACHE_WAYS > 1 - // This sequence is shorter, but does not retain original MEVADDR so - // prevents subsequent use of instructions requiring a virtual address - // (such as LICW, IPFL, etc): -// extui a0, a0, MESR_WAYNUM_SHIFT, 2 -// slli a0, a0, ICACHE_WAYWIDTH -// slli a2, a2, 32 - ICACHE_WAYWIDTH -// srli a2, a2, 32 - ICACHE_WAYWIDTH -// or a2, a2, a0 - - extui a0, a0, MESR_WAYNUM_SHIFT, 2 // id of way with mem error - slli a0, a0, ICACHE_WAYWIDTH - xor a0, a2, a0 // xor corresponding bits of addr - extui a0, a0, ICACHE_WAYWIDTH, 2 // take 2 xor'ed way bits - or a2, a2, a0 // save them at bottom of addr - slli a0, a0, ICACHE_WAYWIDTH - xor a2, a2, a0 // and change 2 way bits of addr -# endif - lict a0, a2 - bbsi.l a0, XCHAL_ICACHE_TAG_L_SHIFT, .L_icache_locked_uncor // branch if locked - // Cache line is not locked, just invalidate: -# if XCHAL_ICACHE_WAYS > 1 - iii a2, 0 -# else - ihi a2, 0 -# endif - j .L_icache_done - - // NOTE: we don't use the LICW/SICW sequence below unless the line is locked, - // otherwise the i-cache line might get replaced between LICW and SICW - // (if we're not extremely careful), which would be disastrous. - // Also, for locked lines, LICW/SICW is much safer than IHU/IHI/IPFL - // because it doesn't leave a window where the line is unlocked; - // however, if the error is non-correctable, we have no choice. - -.L_icache_locked_uncor: - // If locked and uncorrectable however, the only recourse is relocking. - // So we need to recover the virtual address so we can do IPFL. - // Note: can't use MEPC instead of MEVADDR, because (a) it might not - // point to the correct cache line, and (b) it might be completely wrong - // in the case where the mem error happened e.g. during an LICW or IPFL. -# if XCHAL_ICACHE_WAYS > 1 - // Recover virtual address in a2: - extui a0, a2, 0, 2 // get saved xor'ed bits at bottom - slli a0, a0, ICACHE_WAYWIDTH // line them up - xor a2, a2, a0 // restore original MEVADDR -# endif - ihu a2, 0 // unlock line - ihi a2, 0 // invalidate line - ipfl a2, 0 // refetch-and-lock the line - j .L_icache_done -# else /* LOCKABLE */ - rsr.mevaddr a0 - ihi a0, 0 // invalidate that cache line - j .L_done -# endif /* LOCKABLE */ - -.L_icache_tag_noncorr: - // Non-correctable error in the instruction cache tag. - // Just invalidate the tag or the entire set. -# if XCHAL_ICACHE_LINE_LOCKABLE - // Note: - // With i-cache locking, IIU writes the entire tag without mem-error check, - // and III writes part of it (leaves lock bit alone) so can hit errors. - // Without i-cache locking, III writes the entire tag without mem-error check. - // (Original assumption was that SICT is needed.) -# if XCHAL_ICACHE_WAYS > 1 - // TODO FIXME: avoid this 8-line alternative if waynum is in MEVADDR!?: - xsr.mevaddr a2 - extui a0, a0, MESR_WAYNUM_SHIFT, 2 - slli a0, a0, ICACHE_WAYWIDTH - slli a2, a2, 32 - ICACHE_WAYWIDTH - srli a2, a2, 32 - ICACHE_WAYWIDTH - or a2, a2, a0 - iiu a2, 0 // unlock line ==> also invalidates! (I-side only) - xsr.mevaddr a2 -# else - rsr.mevaddr a0 - iiu a0, 0 // unlock line ==> also invalidates! (I-side only) -# endif - // If line was locked, can't recover lock state, need external info to recover. - // User can provide an assembler hook routine _xtos_merr_hook_icache_relock - // to relock the icache at the index in a2: - // - any number of lines might still be locked at that index, - // including all of them - // - no stack is provided, a0 must be used as starting point to - // load a save area and saved registers as necessary - // - unless routine just does ret (i.e. does not modify any - // register, only possible if it does nothing), it needs to - // return by restoring all registers it modified, ending with: - // movi a0, _MemErrorHandler - // xsr.mesave a0 - // rfme - // CAVEAT EMPTOR: this hook mechanism is subject to change. - .weak _xtos_merr_hook_icache_relock // if unresolved, links with zero value - movi a0, _xtos_merr_hook_icache_relock -1: beqz a0, 1b // if no hook to recover lock state on icache tag mem error, loop forever - callx0 a0 // invoke user hook to relock i-cache (index in MEVADDR) -# else - rsr.mevaddr a0 - iii a0, 0 // invalidate entire set -# endif - j .L_done -# endif /* have ICACHE */ - - -# if XCHAL_DCACHE_SIZE > 0 && XCHAL_HAVE_DCACHE_TEST -# if XCHAL_ICACHE_SIZE > 0 && XCHAL_HAVE_ICACHE_TEST -.L_dcache: -# endif - // Error in the data cache. -# if XCHAL_DCACHE_IS_WRITEBACK || XCHAL_DCACHE_LINE_LOCKABLE - bbsi.l a0, MESR_ERRTYPE_SHIFT, .L_dcache_noncorr // branch if uncorrectable - // Uncorrectable error on a writeback dcache might be unrecoverable: -# endif - bbsi.l a0, MESR_MEMTYPE_SHIFT+2, .L_dcache_tag // branch if tag error - // Error in the data cache data (correctable, or non-correctable in writethru+unlockable cache). - // MEVADDR always a real vaddr here; might point to cache-isolate mode area though. -# if XCHAL_DCACHE_LINE_LOCKABLE - // Correctable error on lockable dcache data. - // If locked, need to refetch the line (or load/store its contents, which is less safe): - xsr.mevaddr a2 -# if XCHAL_DCACHE_WAYS > 1 - // Need some extra computation to get the correct dcache way's tag: - movi a0, _MemErrorSave - s32i a4, a0, 0 // save a4 - s32i a5, a0, 4 // save a5 -# if XCHAL_HAVE_PREFETCH - s32i a6, a0, 8 // save a6 - movi a6, 0 - xsr.prefctl a6 // disable prefetch during LDCT (issue TENX-24760) -# endif - rsr.mesr a4 - extui a4, a4, MESR_WAYNUM_SHIFT, 2 - slli a4, a4, DCACHE_WAYWIDTH - slli a5, a2, 32 - DCACHE_WAYWIDTH - srli a5, a5, 32 - DCACHE_WAYWIDTH - add a4, a4, a5 - mov a5, a0 - ldct a0, a4 - l32i a4, a5, 0 // restore a4 -# if XCHAL_HAVE_PREFETCH - wsr.prefctl a6 // restore prefetch - l32i a6, a5, 8 // restore a6 -# endif - l32i a5, a5, 4 // restore a5 -# else -# if XCHAL_HAVE_PREFETCH - movi a0, _MemErrorSave - s32i a4, a0, 0 // save a4 - movi a4, 0 - xsr.prefctl a4 // disable prefetch during LDCT (issue TENX-24760) -# endif - ldct a0, a2 // invalidate and unlock that cache tag -# if XCHAL_HAVE_PREFETCH - wsr.prefctl a4 // restore prefetch - movi a4, _MemErrorSave - l32i a4, a4, 0 // restore a4 -# endif -# endif - // FIXME: if castout, a2 is a cache index (see PR 24103), from which - // we can construct a physical address! need that paddr reconstruction, - // and doesn't work with any address translation. -# if 0 /* translation */ - movi a4, _xtos_vmap_vaddr // FIXME: do we need two variables for full MMU? -1: beqz a4, 1b // if no vaddr to use, loop forever (FIXME: caxlt: could assume V==P) - rdtlb1 a5, a4 // save current contents - ... clear lower bits of a4 ... - xx = some function of a2 - wdtlb xx, a4 - a2 = virtual address, i.e. some function of a2 and a4 ... - ... do the sequence below ... - ... - wdtlb a5, a4 // restore TLB entry -# endif - // NOTE: the following sequence leaves the line temporarily unlocked, if locked. - // We assume NMI handlers don't lock lines or rely on their being locked. - // We could have used "l32i a0,a2,0; s32i a0,a2,0" but that's not atomic on the data. - dhu a2, 0 // unlock the cache line, if locked - dhwbi a2, 0 // writeback and invalidate cache line - bbci.l a0, XCHAL_DCACHE_TAG_L_SHIFT, 1f - dpfl a2, 0 // re-prefetch-and-lock the cache line -1: xsr.mevaddr a2 -# else /* LOCKABLE */ - // Error in unlockable data cache data (correctable, or non-correctable in writethru cache). - rsr.mevaddr a0 - // USELESS NOTE: if writethru dcache and NMI handlers don't store to this, we could use DHI instead: - // FIXME: if castout, a0 is a physical address! doesn't work with any address translation. - dhwbi a0, 0 // writeback (if correctable) and invalidate that cache line -# endif /* LOCKABLE */ - j .L_done - -.L_dcache_tag: - // Error in data cache tag (correctable, or non-correctable in writethru+unlockable cache). - // MEVADDR only contains cache index here (not waynum), don't expect a vaddr (the ISA - // says upper bits are undefined; actual hw does put a vaddr, but in future might not). - // Whether or not correctable, just invalidate the particular way's line: - xsr.mevaddr a2 - // NOTE: could remove these 5 lines if hw were designed with waynum in MEVADDR (but is not): -# if XCHAL_DCACHE_WAYS > 1 - extui a0, a0, MESR_WAYNUM_SHIFT, 2 - slli a0, a0, DCACHE_WAYWIDTH - slli a2, a2, 32 - DCACHE_WAYWIDTH - srli a2, a2, 32 - DCACHE_WAYWIDTH - or a2, a2, a0 -# endif -# if XCHAL_DCACHE_LINE_LOCKABLE -# if XCHAL_HAVE_PREFETCH - movi a0, _MemErrorSave - s32i a4, a0, 0 // save a4 - movi a4, 0 - xsr.prefctl a4 // disable prefetch during LDCT (issue TENX-24760) -# endif - ldct a0, a2 // invalidate and unlock that cache tag -# if XCHAL_HAVE_PREFETCH - wsr.prefctl a4 // restore prefetch - movi a4, _MemErrorSave - l32i a4, a4, 0 // restore a4 -# endif - bbci.l a0, XCHAL_DCACHE_TAG_L_SHIFT, 1f // branch if not locked - sdct a0, a2 // if locked, this safely writes whole tag -# endif -1: diwbi a2, 0 // writeback (if correctable) and invalidate the line - xsr.mevaddr a2 - j .L_done - - - -# if XCHAL_DCACHE_IS_WRITEBACK || XCHAL_DCACHE_LINE_LOCKABLE -.L_dcache_noncorr: - // Uncorrectable error on a (writeback and/or lockable) data cache. -# if XCHAL_DCACHE_IS_WRITEBACK - // On tag errors we don't know whether the line is dirty, so this is unrecoverable: - bbsi.l a0, MESR_MEMTYPE_SHIFT+2, .L_uncorrectable_dtag // branch if tag error - // Castouts are by definition dirty, uncorrectable errors on these are unrecoverable: - bbsi.l a0, MESR_ACCTYPE_SHIFT, .L_uncorrectable_dirty // branch if castout - // Note: could still be an error on dirty dcache data, also unrecoverable. -# else - bbsi.l a0, MESR_MEMTYPE_SHIFT+2, .L_dcache_tag_noncorr // branch if tag error -# endif - // Uncorrectable error in dcache data. - // May be dirty or locked, so get tag to find out. - xsr.mevaddr a2 -# if XCHAL_DCACHE_WAYS > 1 - extui a0, a0, MESR_WAYNUM_SHIFT, 2 // id of way with mem error - slli a0, a0, DCACHE_WAYWIDTH - xor a0, a2, a0 // xor corresponding bits of addr - extui a0, a0, DCACHE_WAYWIDTH, 2 // take 2 xor'ed way bits - or a2, a2, a0 // save them at bottom of addr - slli a0, a0, DCACHE_WAYWIDTH - xor a2, a2, a0 // and change 2 way bits of addr -# endif -# if XCHAL_HAVE_PREFETCH - movi a0, _MemErrorSave - s32i a4, a0, 0 // save a4 - movi a4, 0 - xsr.prefctl a4 // disable prefetch during LDCT (issue TENX-24760) -# endif - ldct a0, a2 // get dcache tag -# if XCHAL_HAVE_PREFETCH - wsr.prefctl a4 // restore prefetch - movi a4, _MemErrorSave - l32i a4, a4, 0 // restore a4 -# endif -# if XCHAL_DCACHE_IS_WRITEBACK - bbsi.l a0, XCHAL_DCACHE_TAG_D_SHIFT, .L_uncorrectable_dirty_2 // branch if dirty -# endif - // Data cache line is clean. -# if XCHAL_DCACHE_LINE_LOCKABLE - bbsi.l a0, XCHAL_DCACHE_TAG_L_SHIFT, .L_dcache_nc_locked -# endif - // Data cache line is clean and unlocked. Just invalidate it. - // FIXME: any stores to this line by an NMI handler will be lost. - // On the other hand, if we use DHWBI, any stores by an NMI handler - // that don't happen to fix the error result in an unrecoverable castout. - // -# if XCHAL_DCACHE_WAYS > 1 - // Recover virtual address in a2: - extui a0, a2, 0, 2 // get saved xor'ed bits at bottom - slli a0, a0, DCACHE_WAYWIDTH // line them up - xor a2, a2, a0 // restore original MEVADDR -# endif - dhi a2, 0 // invalidate that data cache line - xsr.mevaddr a2 - j .L_done - -# if XCHAL_DCACHE_LINE_LOCKABLE -.L_dcache_nc_locked: -# if XCHAL_DCACHE_WAYS > 1 - // Recover virtual address in a2: - extui a0, a2, 0, 2 // get saved xor'ed bits at bottom - slli a0, a0, DCACHE_WAYWIDTH // line them up - xor a2, a2, a0 // restore original MEVADDR -# endif - // Unlock, invalidate, and relock it: - dhu a2, 0 // unlock that data cache line - dhi a2, 0 // invalidate that data cache line - dpfl a2, 0 // prefetch-and-lock the line again - xsr.mevaddr a2 - j .L_done -# endif - -# if XCHAL_DCACHE_IS_WRITEBACK - // Weak reference: if unresolved, links okay but with zero value: - .weak _xtos_merr_hook_uncor_dtag -.L_uncorrectable_dtag: - // Fatal (unrecoverable) error in dcache tag (maybe dirty): parity or uncorrectable ECC error - movi a0, _xtos_merr_hook_uncor_dtag -1: beqz a0, 1b // fatal non-corr dcache tag, no hook, so infinite loop - jx a0 // jump to user hook, if present - - // Weak reference: if unresolved, links okay but with zero value: - .weak _xtos_merr_hook_uncor_dirty -.L_uncorrectable_dirty_2: - xsr.mevaddr a2 -.L_uncorrectable_dirty: - // Fatal (unrecoverable) error, parity or non-correctable ECC error on dirty cache data - movi a0, _xtos_merr_hook_uncor_dirty -1: beqz a0, 1b // fatal non-corr dirty cache line, no hook, so infinite loop - jx a0 // jump to user hook, if present -# else -.L_dcache_tag_noncorr: - // Uncorrectable error on a lockable writethru data cache tag. - // We have to invalidate the line, but that way we lose the lock bit. - // Provide a hook to relock if necessary (using knowledge outside this module - // about what needs to be locked). See _xtos_merr_hook_icache_relock for details. - // CAVEAT EMPTOR: this hook mechanism is subject to change. - .weak _xtos_merr_hook_dcache_relock // if unresolved, links with zero value - movi a0, _xtos_merr_hook_dcache_relock -1: beqz a0, 1b // if no hook to recover lock state on dcache tag mem error, loop forever - callx0 a0 // invoke user hook to relock d-cache (index in MEVADDR) - j .L_done -# endif - -# endif /* DCACHE IS WRITEBACK || LINE_LOCKABLE */ - -# endif /* have DCACHE */ - - .size _MemErrorHandler, . - _MemErrorHandler - - - -# endif /* splitting */ -#endif /* XCHAL_HAVE_MEM_ECC_PARITY */ - diff --git a/src/arch/xtensa/xtos/nmi-vector.S b/src/arch/xtensa/xtos/nmi-vector.S deleted file mode 100644 index 637dcda96940..000000000000 --- a/src/arch/xtensa/xtos/nmi-vector.S +++ /dev/null @@ -1,60 +0,0 @@ -// nmi-vector.S -- Standalone NMI Interrupt Vector/Handler -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/nmi-vector.S#1 $ - -// Copyright (c) 2003, 2006, 2010 Tensilica 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. - -// The NMI exception vector handles non-maskable interrupts. - -#include <xtensa/coreasm.h> -#include <xtensa/config/system.h> - -#if XCHAL_HAVE_NMI - - .begin literal_prefix .NMIExceptionVector - .section .NMIExceptionVector.text, "ax" - - .align 4 - .global _NMIExceptionVector -_NMIExceptionVector: - -// Insert any custom NMI handling code here. -// For example: -// writesr excsave XCHAL_NMILEVEL a0 -// movi a0, ...address of some save area specific to this code... -// s32i a1, a0, 0 // save whatever registers are needed -// : -// do something useful ... -// : -// l32i a1, a0, 0 // restore whatever registers were saved -// readsr excsave XCHAL_NMILEVEL a0 -// -// This default NMI handler does not do anything. It just returns -// immediately upon any occurrence of a non-maskable interrupt. - - rfi XCHAL_NMILEVEL - - .size _NMIExceptionVector, . - _NMIExceptionVector - .text - .end literal_prefix - -#endif /* XCHAL_HAVE_NMI */ - diff --git a/src/arch/xtensa/xtos/null-syscall.S b/src/arch/xtensa/xtos/null-syscall.S deleted file mode 100644 index fb53cf948865..000000000000 --- a/src/arch/xtensa/xtos/null-syscall.S +++ /dev/null @@ -1,38 +0,0 @@ -// null-syscall.S - Stub for Unused SYSCALL Handler -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/null-syscall.S#1 $ - -// Copyright (c) 2006-2010 Tensilica 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. - - - // Redirect SYSCALL exceptions as not handled, when - // that functionality is not needed. Done this way, a user can - // just specify this small handler to override the default one. - - .text - .weak xtos_unhandled_exception - .global _xtos_syscall_handler -_xtos_syscall_handler: - movi a3, xtos_unhandled_exception -1: beqz a3, 1b - jx a3 - .size _xtos_syscall_handler, . - _xtos_syscall_handler - diff --git a/src/arch/xtensa/xtos/null-vectors.S b/src/arch/xtensa/xtos/null-vectors.S deleted file mode 100644 index 0bb274d690c1..000000000000 --- a/src/arch/xtensa/xtos/null-vectors.S +++ /dev/null @@ -1,184 +0,0 @@ -// null-vectors.S - Stubs for Unused Vectors and Handlers -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/null-vectors.S#1 $ - -// Copyright (c) 2006-2010 Tensilica 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. - - -// NOTE: The simulator version of this file is currently not used, -// i.e. the SIMULATOR macro is never defined when assembling this file. -// The relevant simulator code is left here for illustrative purposes only. - - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" -#ifdef SIMULATOR -#include <xtensa/simcall.h> -#endif - - // These are just tiny non-functional vectors and handlers for when - // their functionality is not being used. They just try to signal - // the debugger that an unhandled exception or interrupt occurred, - // and otherwise just spin in a loop. - // - // For interrupts levels above DEBUGLEVEL, lowering PS.INTLEVEL - // for break to work is tricky, and not always possible in a - // generic fashion without interfering with normal program execution. - // So for now we don't do it. - - -#if defined(__SPLIT__user) - -# if XCHAL_HAVE_EXCEPTIONS - .begin literal_prefix .UserExceptionVector - .section .UserExceptionVector.text, "ax" - .align 4 - .global _UserExceptionVector -_UserExceptionVector: -# if XCHAL_HAVE_DEBUG - break 1, 1 // unexpected user-vectored general exception -# endif -1: j 1b // infinite loop - unexpected user-vectored exception - .size _UserExceptionVector, . - _UserExceptionVector - .end literal_prefix -# endif - -#elif defined(__SPLIT__level1int) - - .text - .global _xtos_l1int_handler -_xtos_l1int_handler: - movi a3, xtos_unhandled_exception - jx a3 - .size _xtos_l1int_handler, . - _xtos_l1int_handler - -#elif defined(__SPLIT__level2) - -# if (XCHAL_NUM_INTLEVELS >= 2) && (XCHAL_DEBUGLEVEL != 2) - .begin literal_prefix .Level2InterruptVector - .section .Level2InterruptVector.text, "ax" - .align 4 - .global _Level2Vector -_Level2Vector: -# if XCHAL_HAVE_DEBUG && (XCHAL_DEBUGLEVEL > 2) - break 1, 2 // unexpected high-priority interrupt -# elif defined(SIMULATOR) - wsr a2, EXCSAVE_2 - movi a2, SYS_unhandled_highpri_interrupt - simcall // let simulator/debugger report unhandled level-2 interrupt -# endif -1: j 1b // infinite loop - unexpected level-2 interrupt - .size _Level2Vector, . - _Level2Vector - .text - .end literal_prefix -# endif /* level 2 */ - - -#elif defined(__SPLIT__level3) - -# if (XCHAL_NUM_INTLEVELS >= 3) && (XCHAL_DEBUGLEVEL != 3) - .begin literal_prefix .Level3InterruptVector - .section .Level3InterruptVector.text, "ax" - .align 4 - .global _Level3Vector -_Level3Vector: -# if XCHAL_HAVE_DEBUG && (XCHAL_DEBUGLEVEL > 3) - break 1, 2 // unexpected high-priority interrupt -# elif defined(SIMULATOR) - wsr a2, EXCSAVE_3 - movi a2, SYS_unhandled_highpri_interrupt - simcall // let simulator/debugger report unhandled level-3 interrupt -# endif -1: j 1b // infinite loop - unexpected level-3 interrupt - .size _Level3Vector, . - _Level3Vector - .text - .end literal_prefix -# endif /* level 3 */ - - -#elif defined(__SPLIT__level4) - -# if (XCHAL_NUM_INTLEVELS >= 4) && (XCHAL_DEBUGLEVEL != 4) - .begin literal_prefix .Level4InterruptVector - .section .Level4InterruptVector.text, "ax" - .align 4 - .global _Level4Vector -_Level4Vector: -# if XCHAL_HAVE_DEBUG && (XCHAL_DEBUGLEVEL > 4) - break 1, 2 // unexpected high-priority interrupt -# elif defined(SIMULATOR) - wsr a2, EXCSAVE_4 - movi a2, SYS_unhandled_highpri_interrupt - simcall // let simulator/debugger report unhandled level-4 interrupt -# endif -1: j 1b // infinite loop - unexpected level-4 interrupt - .size _Level4Vector, . - _Level4Vector - .text - .end literal_prefix -# endif /* level 4 */ - - -#elif defined(__SPLIT__level5) - -# if (XCHAL_NUM_INTLEVELS >= 5) && (XCHAL_DEBUGLEVEL != 5) - .begin literal_prefix .Level5InterruptVector - .section .Level5InterruptVector.text, "ax" - .align 4 - .global _Level5Vector -_Level5Vector: -# if XCHAL_HAVE_DEBUG && (XCHAL_DEBUGLEVEL > 5) - break 1, 2 // unexpected high-priority interrupt -# elif defined(SIMULATOR) - wsr a2, EXCSAVE_5 - movi a2, SYS_unhandled_highpri_interrupt - simcall // let simulator/debugger report unhandled level-5 interrupt -# endif -1: j 1b // infinite loop - unexpected level-5 interrupt - .size _Level5Vector, . - _Level5Vector - .text - .end literal_prefix -# endif /* level 5 */ - - -#elif defined(__SPLIT__level6) - -# if (XCHAL_NUM_INTLEVELS >= 6) && (XCHAL_DEBUGLEVEL != 6) - .begin literal_prefix .Level6InterruptVector - .section .Level6InterruptVector.text, "ax" - .align 4 - .global _Level6Vector -_Level6Vector: -# if XCHAL_HAVE_DEBUG && (XCHAL_DEBUGLEVEL > 6) - break 1, 2 // unexpected high-priority interrupt -# elif defined(SIMULATOR) - wsr a2, EXCSAVE_6 - movi a2, SYS_unhandled_highpri_interrupt - simcall // let simulator/debugger report unhandled level-6 interrupt -# endif -1: j 1b // infinite loop - unexpected level-6 interrupt - .size _Level6Vector, . - _Level6Vector - .text - .end literal_prefix -# endif /* level 6 */ - - -#endif /* split */ - diff --git a/src/arch/xtensa/xtos/reset-unneeded.S b/src/arch/xtensa/xtos/reset-unneeded.S deleted file mode 100644 index e662a5856a75..000000000000 --- a/src/arch/xtensa/xtos/reset-unneeded.S +++ /dev/null @@ -1,156 +0,0 @@ -// reset-unneeded.S -- Optional Extraneous Reset Code -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/reset-unneeded.S#1 $ - -// Copyright (c) 2002-2006 Tensilica 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. - -// This file is meant to be included by another, e.g. crt1-***.S . -// The code it contains is generally not needed, so is kept in a -// separate file for clarity of other code. - -#if XTOS_RESET_UNNEEDED - /* - * Reset registers that don't really need to be reset, - * but may provide more predictability when buggy code - * relies on uninitialized state. It might also clear - * "X"s a bit earlier in hardware simulations. - * - * NOTE: This code is by no means exhaustive. - * More processor registers/states could be reset if desired. - * This is just an example. - * - * ASSUMPTION: a0 is still zero at this point. - */ - - // Interrupt initialization. - // Because INTENABLE is cleared by the reset vector, clearing the - // interrupt-pending register should not be needed. This assumes - // that any application setting up an interrupt will register and - // clear it before enabling it, which is the recommended sequence. - // -#if XCHAL_HAVE_INTERRUPTS && (XCHAL_INTCLEARABLE_MASK != 0) && !XCHAL_HAVE_FULL_RESET - movi a2, XCHAL_INTCLEARABLE_MASK - wsr a2, INTCLEAR // clear software and edge-trig ints -#endif - - // Timer initialization (not strictly required, but sometimes helpful) - .macro reset_timer num - wsr a0, CCOMPARE_0 + \num - .endm - iterate 0, XCHAL_NUM_TIMERS-1, reset_timer - -# if XCHAL_HAVE_WINDOWED - // Windowed address register init -- initialize entire physical AR file - movi a0, XCHAL_NUM_AREGS/8 // number of 8-register chunks -arloop: - addi a8, a0, -1 // countdown into next chunk's a0 - movi a0, 0 - movi a1, 0 - movi a2, 0 - movi a3, 0 - movi a4, 0 - movi a5, 0 - movi a6, 0 - movi a7, 0 - rotw 2 // rotate to next chunk - bnez a0, arloop - // NOTE: WINDOWBASE is back to zero at this point. -# else /* XCHAL_HAVE_WINDOWED */ - // Non-windowed address register init - movi a1, 0 - movi a2, 0 - movi a3, 0 - movi a4, 0 - movi a5, 0 - movi a6, 0 - movi a7, 0 - movi a8, 0 - movi a9, 0 - movi a10, 0 - movi a11, 0 - movi a12, 0 - movi a13, 0 - movi a14, 0 - movi a15, 0 -# endif /* XCHAL_HAVE_WINDOWED */ - // Now all address registers are zero. - - // Initialize LBEG, LEND, and LCOUNT. -# if XCHAL_HAVE_LOOPS - wsr a0, LCOUNT // note: LCOUNT gets cleared by processor reset - wsr a0, LBEG - wsr a0, LEND -# endif - -# if XCHAL_HAVE_DEBUG - .macro reset_dbreaka num - wsr a0, DBREAKA + \num - .endm - .macro reset_ibreaka num - wsr a0, IBREAKA + \num - .endm - iterate 0, XCHAL_NUM_DBREAK-1, reset_dbreaka - iterate 0, XCHAL_NUM_IBREAK-1, reset_ibreaka -# endif - - // SAR initialization - ssai 0 - - // Exception initialization -# if XCHAL_HAVE_EXCEPTIONS - wsr a0, EPC+1 - wsr a0, EXCSAVE+1 - wsr a0, EXCCAUSE -# endif - -# if XCHAL_HAVE_HIGHLEVEL_INTERRUPTS - .macro reset_int num - wsr a0, EPC + \num - wsr a0, EPS + \num - wsr a0, EXCSAVE + \num - .endm - iterate 2, XCHAL_NUM_INTLEVELS, reset_int -# endif - - // Booleans initialization -# if XCHAL_HAVE_BOOLEANS - wsr a0, BR -# endif - - // MAC16 initialization -# if XCHAL_HAVE_MAC16 - wsr a0, ACCLO - wsr a0, ACCHI - wsr a0, M0 - wsr a0, M1 - wsr a0, M2 - wsr a0, M3 -# endif - - // OCD initialization -# if XCHAL_HAVE_OCD - wsr a0, DDR -# endif - - isync // wait for all the above to take effect - -#endif /* XTOS_RESET_UNNEEDED */ - diff --git a/src/arch/xtensa/xtos/reset-vector.S b/src/arch/xtensa/xtos/reset-vector.S deleted file mode 100644 index dcda71c4f8af..000000000000 --- a/src/arch/xtensa/xtos/reset-vector.S +++ /dev/null @@ -1,657 +0,0 @@ -// reset-vector.S -- Xtensa Reset Vector -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/reset-vector.S#1 $ - -// Copyright (c) 1999-2013 Tensilica 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 <config.h> -#include <sof/common.h> -#if CONFIG_BOOT_LOADER && !CONFIG_VM_ROM -#include <sof/lib/memory.h> -#endif -#include <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/cacheasm.h> -#include <xtensa/cacheattrasm.h> -#include <xtensa/xtensa-xer.h> -#include <xtensa/xdm-regs.h> -#include <xtensa/config/system.h> /* for XSHAL_USE_ABSOLUTE_LITERALS only */ -#include <xtensa/xtruntime-core-state.h> -#include "xtos-internal.h" - -// The following reset vector avoids initializing certain registers already -// initialized by processor reset. But it does initialize some of them -// anyway, for minimal support of warm restart (restarting in software by -// jumping to the reset vector rather than asserting hardware reset). - - - .begin literal_prefix .ResetVector - .section .ResetVector.text, "ax" - - .align 4 - .global _ResetVector -_ResetVector: - -#if (!XCHAL_HAVE_HALT || defined(XTOS_UNPACK)) && XCHAL_HAVE_IMEM_LOADSTORE - // NOTE: - // - // IMPORTANT: If you move the _ResetHandler portion to a section - // other than .ResetVector.text that is outside the range of - // the reset vector's 'j' instruction, the _ResetHandler symbol - // and a more elaborate j/movi/jx sequence are needed in - // .ResetVector.text to dispatch to the new location. - -#if CONFIG_HAVE_RESET_VECTOR_ROM - j _ResetHandler -#else - // This is our VM ROM, it simply jumps to the reset handler. - j .sram_jump // jump over the literals - - .align 4 - .literal_position // tells the assembler/linker to place literals here - -_reset_sram: - .word _ResetHandler - .align 4 -.sram_jump: - l32r a0, _reset_sram // load SRAM reset handler address - jx a0 // jump to the handler -#endif - .size _ResetVector, . - _ResetVector - -# if XCHAL_HAVE_HALT - // Xtensa TX: reset vector segment is only 4 bytes, so must place the - // unpacker code elsewhere in the memory that contains the reset vector. -# if XCHAL_RESET_VECTOR_VADDR == XCHAL_INSTRAM0_VADDR - .section .iram0.text, "ax" -# elif XCHAL_RESET_VECTOR_VADDR == XCHAL_INSTROM0_VADDR - .section .irom0.text, "ax" -# elif XCHAL_RESET_VECTOR_VADDR == XCHAL_URAM0_VADDR - .section .uram0.text, "ax" -# else -# warning "Xtensa TX reset vector not at start of iram0, irom0, or uram0 -- ROMing LSPs may not work" - .text -# endif -# endif - - .extern __memctl_default - -#if CONFIG_BOOT_LOADER || CONFIG_VM_ROM - .section .ResetHandler.text, "ax" - j _ResetHandler -#endif - .align 4 - .literal_position // tells the assembler/linker to place literals here - - // For MPU empty background map -- see XCHAL_HAVE_MPU code further below. - // Cannot put this in .rodata (not unpacked before MPU init). -# if XCHAL_HAVE_MPU && XCHAL_MPU_ENTRIES >= 8 && XCHAL_MPU_BACKGROUND_ENTRIES <= 2 - .global _xtos_mpu_attribs - .align 4 -_xtos_mpu_attribs: - .word 0x00006000+XCHAL_MPU_ENTRIES-8 // Illegal (---) - .word 0x000F7700+XCHAL_MPU_ENTRIES-8 // Writeback (rwx Cacheable Non-shareable wb rd-alloc wr-alloc) - .word 0x000D5700+XCHAL_MPU_ENTRIES-8 // WBNA (rwx Cacheable Non-shareable wb rd-alloc) - .word 0x000C4700+XCHAL_MPU_ENTRIES-8 // Writethru (rwx Cacheable Non-shareable wt rd-alloc) - .word 0x00006700+XCHAL_MPU_ENTRIES-8 // Bypass (rwx Device non-interruptible system-shareable) -# endif - - .align 4 - .global _ResetHandler -_ResetHandler: -#endif - -#if !XCHAL_HAVE_HALT - - /* - * Even if the processor supports the non-PC-relative L32R option, - * it will always start up in PC-relative mode. We take advantage of - * this, and use PC-relative mode at least until we're sure the .lit4 - * section is in place (which is sometimes only after unpacking). - */ - .begin no-absolute-literals - - // If we have dynamic cache way support, init the caches as soon - // as we can, which is now. Except, if we are waking up from a - // PSO event, then we need to do this slightly later. - -#if XCHAL_HAVE_ICACHE_DYN_WAYS || XCHAL_HAVE_DCACHE_DYN_WAYS -# if XCHAL_HAVE_PSO_CDM && !XCHAL_HAVE_PSO_FULL_RETENTION - // Do this later on in the code -- see below -# else - movi a0, __memctl_default - wsr.memctl a0 -# endif -#endif - - // If we have PSO support, then we must check for a warm start with - // caches left powered on. If the caches had been left powered on, - // we must restore the state of MEMCTL to the saved state if any. - // Note that MEMCTL may not be present depending on config. - -#if XCHAL_HAVE_PSO_CDM && !XCHAL_HAVE_PSO_FULL_RETENTION - movi a2, XDM_MISC_PWRSTAT // Read PWRSTAT - movi a3, _xtos_pso_savearea // Save area address - retained for later - movi a5, CORE_STATE_SIGNATURE // Signature for compare - retained for later - rer a7, a2 // PWRSTAT value - retained for later - extui a4, a7, 1, 2 // Now bottom 2 bits are core wakeup and cache power lost - bnei a4, 1, .Lcold_start // a4==1 means PSO wakeup, caches did not lose power - l32i a4, a3, CS_SA_signature // Load save area signature field - sub a4, a4, a5 - bnez a4, .Lcold_start // If signature mismatch then do cold start -#if XCHAL_USE_MEMCTL - l32i a4, a3, CS_SA_memctl // Load saved MEMCTL value - movi a0, ~MEMCTL_INV_EN - and a0, a4, a0 // Clear invalidate bit - wsr.memctl a0 -#endif - j .Lwarm_start - -.Lcold_start: - -#if XCHAL_HAVE_ICACHE_DYN_WAYS || XCHAL_HAVE_DCACHE_DYN_WAYS - // Enable and invalidate all ways of both caches. If there is no - // dynamic way support then this write will have no effect. - - movi a0, __memctl_default - wsr.memctl a0 -#endif - -.Lwarm_start: - -#endif - - movi a0, 0 // a0 is always 0 in this code, used to initialize lots of things - -#if XCHAL_HAVE_INTERRUPTS // technically this should be under !FULL_RESET, assuming hard reset - wsr.intenable a0 // make sure that interrupts are shut off (*before* we lower PS.INTLEVEL and PS.EXCM!) -#endif - -#if !XCHAL_HAVE_FULL_RESET - -#if XCHAL_HAVE_CCOUNT && (XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RB_2006_0) /* pre-LX2 cores only */ - wsr.ccount a0 // not really necessary, but nice; best done very early -#endif - - // For full MMU configs, put page table at an unmapped virtual address. - // This ensures that accesses outside the static maps result - // in miss exceptions rather than random behaviour. - // Assumes XCHAL_SEG_MAPPABLE_VADDR == 0 (true in released MMU). -#if XCHAL_ITLB_ARF_WAYS > 0 || XCHAL_DTLB_ARF_WAYS > 0 - wsr.ptevaddr a0 -#endif - - // Debug initialization - // - // NOTE: DBREAKCn must be initialized before the combination of these two things: - // any load/store, and a lowering of PS.INTLEVEL below DEBUG_LEVEL. - // The processor already resets IBREAKENABLE appropriately. - // -#if XCHAL_HAVE_DEBUG -# if XCHAL_NUM_DBREAK -# if XCHAL_NUM_DBREAK >= 2 - wsr.dbreakc1 a0 -# endif - wsr.dbreakc0 a0 - dsync // wait for WSRs to DBREAKCn to complete -# endif - -# if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RA_2004_1 /* pre-LX cores only */ - // Starting in Xtensa LX, ICOUNTLEVEL resets to zero (not 15), so no need to initialize it. - // Prior to that we do, otherwise we get an ICOUNT exception, 2^32 instructions after reset. - rsr.icountlevel a2 // are we being debugged? (detected by ICOUNTLEVEL not 15, or dropped below 12) - bltui a2, 12, 1f // if so, avoid initializing ICOUNTLEVEL which drops single-steps through here - wsr.icountlevel a0 // avoid ICOUNT exceptions - isync // wait for WSR to ICOUNTLEVEL to complete -1: -# endif -#endif - -#endif /* !XCHAL_HAVE_FULL_RESET */ - -#if XCHAL_HAVE_ABSOLUTE_LITERALS - // Technically, this only needs to be done under !FULL_RESET, assuming hard reset: - wsr.litbase a0 - rsync -#endif - -#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION - // If we're powering up from a temporary power shut-off (PSO), - // restore state saved just prior to shut-off. Note that the - // MEMCTL register was already restored earlier, and as a side - // effect, registers a3, a5, a7 are now preloaded with values - // that we will use here. - // a3 - pointer to save area base address (_xtos_pso_savearea) - // a5 - saved state signature (CORE_STATE_SIGNATURE) - // a7 - contents of PWRSTAT register - - l32i a4, a3, CS_SA_signature // load save area signature - sub a4, a4, a5 // compare signature with expected one -# if XTOS_PSO_TEST - movi a7, PWRSTAT_WAKEUP_RESET // pretend PSO warm start with warm caches -# endif - bbci.l a7, PWRSTAT_WAKEUP_RESET_SHIFT, 1f // wakeup from PSO? (branch if not) - // Yes, wakeup from PSO. Check whether state was properly saved. - addi a5, a7, - PWRSTAT_WAKEUP_RESET // speculatively clear PSO-wakeup bit - movnez a7, a5, a4 // if state not saved (corrupted?), mark as cold start - bnez a4, 1f // if state not saved, just continue with reset - // Wakeup from PSO with good signature. Now check cache status: - bbci.l a7, PWRSTAT_CACHES_LOST_POWER_SHIFT, .Lpso_restore // if caches warm, restore now - // Caches got shutoff. Continue reset, we'll end up initializing caches, and check again later for PSO. -# if XCHAL_HAVE_PRID && XCHAL_HAVE_S32C1I - j .Ldonesync // skip reset sync, only done for cold start -# endif -1: // Cold start. (Not PSO wakeup.) Proceed with normal full reset. -#endif - -#if XCHAL_HAVE_PRID && XCHAL_HAVE_S32C1I - /* Core 0 initializes the XMP synchronization variable, if present. This operation needs to - happen as early as possible in the startup sequence so that the other cores can be released - from reset. */ - .weak _ResetSync - movi a2, _ResetSync // address of sync variable - rsr.prid a3 // core and multiprocessor ID - extui a3, a3, 0, 8 // extract core ID (FIXME: need proper constants for PRID bits to extract) - beqz a2, .Ldonesync // skip if no sync variable - bnez a3, .Ldonesync // only do this on core 0 - s32i a0, a2, 0 // clear sync variable -.Ldonesync: -#endif -#if XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MP_RUNSTALL - /* On core 0, this releases other cores. On other cores this has no effect, because - runstall control is unconnected. */ - movi a2, XER_MPSCORE - wer a0, a2 -#endif - - /* - * For processors with relocatable vectors, apply any alternate - * vector base given to xt-genldscripts, which sets the - * _memmap_vecbase_reset symbol accordingly. - */ -#if XCHAL_HAVE_VECBASE - movi a2, _memmap_vecbase_reset /* note: absolute symbol, not a ptr */ - wsr.vecbase a2 -#endif - -#if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0) /* have ATOMCTL ? */ -# if XCHAL_DCACHE_IS_COHERENT - movi a3, 0x25 /* MX -- internal for writeback, RCW otherwise */ -# else - movi a3, 0x15 /* non-MX -- always RCW */ -# endif - wsr.atomctl a3 -#endif - -#if XCHAL_HAVE_INTERRUPTS && XCHAL_HAVE_DEBUG - rsil a2, 1 // lower PS.INTLEVEL here to make reset vector easier to debug -#endif - - /* If either of the caches does not have dynamic way support, then - * use the old (slow) method to init them. If the cache is absent - * the macros will expand to empty. - */ -#if ! XCHAL_HAVE_ICACHE_DYN_WAYS - icache_reset a2, a3 -#endif -#if ! XCHAL_HAVE_DCACHE_DYN_WAYS - dcache_reset a2, a3 -#endif - -#if XCHAL_HAVE_PSO_CDM && ! XCHAL_HAVE_PSO_FULL_RETENTION - // Here, a7 still contains status from the power status register, - // or zero if signature check failed. - bbci.l a7, PWRSTAT_WAKEUP_RESET_SHIFT, .Lcoldstart // wakeup from PSO with good signature? - // Yes, wakeup from PSO. Caches had been powered down, now are initialized. -.Lpso_restore: - // Assume memory still initialized, so all code still unpacked etc. - // So we can just jump/call to relevant state restore code (wherever located). - movi a2, 0 // make shutoff routine return zero - movi a3, _xtos_pso_savearea - // Here, as below for _start, call0 is used as an unlimited-range jump. - call0 _xtos_core_restore_nw - // (does not return) -.Lcoldstart: -#endif - -#if XCHAL_HAVE_PREFETCH - /* Enable cache prefetch if present. */ -#if CONFIG_APOLLOLAKE - -#if CONFIG_SKYLAKE || CONFIG_KABYLAKE - movi.n a2, 0 /* skylake and kabylake */ -#else - movi.n a2, 34 /* apollolake */ -#endif - -#else - movi.n a2, 68 /* eveything else */ -#endif - wsr a2, PREFCTL -#endif - - /* - * Now setup the memory attributes. On some cores this "enables" caches. - * We do this ahead of unpacking, so it can proceed more efficiently. - * - * The _memmap_cacheattr_reset symbol's value (address) is defined - * by the LSP's linker script, as generated by xt-genldscripts. - * If defines 4-bit attributes for eight 512MB regions. - * - * (NOTE: for cores with the older MMU v1 or v2, or without any memory - * protection mechanism, the following code has no effect.) - */ -#if XCHAL_HAVE_MPU - /* If there's an empty background map, setup foreground maps to mimic region protection: */ -# if XCHAL_MPU_ENTRIES >= 8 && XCHAL_MPU_BACKGROUND_ENTRIES <= 2 - // We assume reset state: all MPU entries zeroed and disabled. - // Otherwise we'd need a loop to zero everything. - - movi a2, _memmap_cacheattr_reset // note: absolute symbol, not a ptr - movi a3, _xtos_mpu_attribs // see literal area at start of reset vector - movi a4, 0x20000000 // 512 MB delta - movi a6, 8 - movi a7, 1 // MPU entry vaddr 0, with valid bit set - movi a9, 0 // cacheadrdis value - wsr.cacheadrdis a9 // enable everything temporarily while MPU updates - - // Write eight MPU entries, from the last one going backwards (entries n-1 thru n-8) - // -2: extui a8, a2, 28, 4 // get next attribute nibble (msb first) - extui a5, a8, 0, 2 // lower two bit indicate whether cached - slli a9, a9, 1 // add a bit to cacheadrdis... - addi a10, a9, 1 // set that new bit if... - moveqz a9, a10, a5 // ... that region is non-cacheable - addx4 a5, a8, a3 // index into _xtos_mpu_attribs table - addi a8, a8, -5 // make valid attrib indices negative - movgez a5, a3, a8 // if not valid attrib, use Illegal - l32i a5, a5, 0 // load access rights, memtype from table entry - slli a2, a2, 4 - sub a7, a7, a4 // next 512MB region (last to first) - addi a6, a6, -1 - add a5, a5, a6 // add the index - wptlb a5, a7 // write the MPU entry - bnez a6, 2b // loop until done -# else - movi a9, XCHAL_MPU_BG_CACHEADRDIS // default value of CACHEADRDIS for bgnd map -# endif - wsr.cacheadrdis a9 // update cacheadrdis -#elif XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR \ - || (XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY) - movi a2, _memmap_cacheattr_reset /* note: absolute symbol, not a ptr */ - cacheattr_set /* set CACHEATTR from a2 (clobbers a3-a8) */ -#endif - - /* Now that caches are initialized, cache coherency can be enabled. */ -#if XCHAL_DCACHE_IS_COHERENT -# if XCHAL_HAVE_EXTERN_REGS && XCHAL_HAVE_MX && (XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RE_2012_0) - /* Opt into coherence for MX (for backward compatibility / testing). */ - movi a3, 1 - movi a2, XER_CCON - wer a3, a2 -# endif -#endif - - /* Enable zero-overhead loop instr buffer and snoop responses if configured. */ - /* If HW erratum 453 fix is to be applied then disable loop instr buffer. */ -#if XCHAL_USE_MEMCTL && (XCHAL_SNOOP_LB_MEMCTL_DEFAULT || XCHAL_ERRATUM_453) - rsr.memctl a2 -#if XCHAL_SNOOP_LB_MEMCTL_DEFAULT - movi a3, XCHAL_SNOOP_LB_MEMCTL_DEFAULT - or a2, a2, a3 -#endif -#if XCHAL_ERRATUM_453 - srli a2, a2, 1 /* clear bit 0 (ZOL buffer enable) */ - slli a2, a2, 1 -#endif - wsr.memctl a2 -#endif - - /* Caches are all up and running, clear PWRCTL.ShutProcOffOnPWait. */ -#if XCHAL_HAVE_PSO_CDM - movi a2, XDM_MISC_PWRCTL - movi a4, ~PWRCTL_CORE_SHUTOFF - rer a3, a2 - and a3, a3, a4 - wer a3, a2 -#endif - -#endif /* !XCHAL_HAVE_HALT */ - - /* - * At this point we can unpack code and data (e.g. copy segments from - * ROM to RAM, vectors into their proper location, etc.). However, - * - * 1) the destination of the unpack may require some setup, - * for instance a DDR controller may need to be initialized - * and enabled before anything is unpacked into DDR. - * 2) users may wish to provide their own unpack code which works - * faster or in a different way than the default unpack code. - * - * To support such uses, we provide a user hook at this point. - * If the user hook function is defined, then it is called from - * here, and its return value (in a2) is checked. If the return - * value is non-zero, then we assume that code unpacking has been - * completed. The user hook function must be written in assembly - * and should make minimal assumptions about system state. - */ - - .weak __reset_user_init - - movi a2, __reset_user_init - beqz a2, 1f // no user hook - callx0 a2 // execute user hook - movi a0, 0 // ensure a0 continues to hold 0 - bnez a2, unpackdone // if a2 != 0 then unpack is done -1: - -#if defined(XTOS_UNPACK) - movi a2, _rom_store_table - beqz a2, unpackdone -unpack: l32i a3, a2, 0 // start vaddr - l32i a4, a2, 4 // end vaddr - l32i a5, a2, 8 // store vaddr - addi a2, a2, 12 - bgeu a3, a4, upnext // skip unless start < end -uploop: l32i a6, a5, 0 - addi a5, a5, 4 - s32i a6, a3, 0 - addi a3, a3, 4 - bltu a3, a4, uploop - j unpack -upnext: bnez a3, unpack - bnez a5, unpack -#endif /* XTOS_UNPACK */ - -unpackdone: - -#if defined(XTOS_UNPACK) || defined(XTOS_MP) - /* - * If writeback caches are configured and enabled, unpacked data must be - * written out to memory before trying to execute it: - */ - dcache_writeback_all a2, a3, a4, 0 - icache_sync a2 // ensure data written back is visible to i-fetch - /* - * Note: no need to invalidate the i-cache after the above, because we - * already invalidated it further above and did not execute anything within - * unpacked regions afterwards. [Strictly speaking, if an unpacked region - * follows this code very closely, it's possible for cache-ahead to have - * cached a bit of that unpacked region, so in the future we may need to - * invalidate the entire i-cache here again anyway.] - */ -#endif - - -#if !XCHAL_HAVE_HALT /* skip for TX */ - - /* - * Now that we know the .lit4 section is present (if got unpacked) - * (and if absolute literals are used), initialize LITBASE to use it. - */ -#if XCHAL_HAVE_ABSOLUTE_LITERALS && XSHAL_USE_ABSOLUTE_LITERALS - /* - * Switch from PC-relative to absolute (litbase-relative) L32R mode. - * Set LITBASE to 256 kB beyond the start of the literals in .lit4 - * (aligns to the nearest 4 kB boundary, LITBASE does not have bits 1..11) - * and set the enable bit (_lit4_start is assumed 4-byte aligned). - */ - movi a2, _lit4_start + 0x40001 - wsr.litbase a2 - rsync -#endif /* have and use absolute literals */ - .end no-absolute-literals // we can now start using absolute literals - - -// Technically, this only needs to be done pre-LX2, assuming hard reset: -# if XCHAL_HAVE_WINDOWED && defined(__XTENSA_WINDOWED_ABI__) - // Windowed register init, so we can call windowed code (eg. C code). - movi a1, 1 - wsr.windowstart a1 - // The processor always clears WINDOWBASE at reset, so no need to clear it here. - // It resets WINDOWSTART to 1 starting with LX2.0/X7.0 (RB-2006.0). - // However, assuming hard reset is not yet always practical, so do this anyway: - wsr.windowbase a0 - rsync - movi a0, 0 // possibly a different a0, clear it -# endif - -#if XCHAL_HW_MIN_VERSION < XTENSA_HWVERSION_RB_2006_0 /* only pre-LX2 needs this */ - // Coprocessor option initialization -# if XCHAL_HAVE_CP - //movi a2, XCHAL_CP_MASK // enable existing CPs - // To allow creating new coprocessors using TC that are not known - // at GUI build time without having to explicitly enable them, - // all CPENABLE bits must be set, even though they may not always - // correspond to a coprocessor. - movi a2, 0xFF // enable *all* bits, to allow dynamic TIE - wsr.cpenable a2 -# endif - - // Floating point coprocessor option initialization (at least - // rounding mode, so that floating point ops give predictable results) -# if XCHAL_HAVE_FP && !XCHAL_HAVE_VECTORFPU2005 - rsync /* wait for WSR to CPENABLE to complete before accessing FP coproc state */ - wur.fcr a0 /* clear FCR (default rounding mode, round-nearest) */ - wur.fsr a0 /* clear FSR */ -# endif -#endif /* pre-LX2 */ - - - // Initialize memory error handler address. - // Putting this address in a register allows multiple instances of - // the same configured core (with separate program images but shared - // code memory, thus forcing memory error vector to be shared given - // it is not VECBASE relative) to have the same memory error vector, - // yet each have their own handler and associated data save area. -#if XCHAL_HAVE_MEM_ECC_PARITY_IGNORE - movi a4, _MemErrorHandler - wsr.mesave a4 -#endif - - - /* - * Initialize medium and high priority interrupt dispatchers: - */ -#if HAVE_XSR && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) - -#if !CONFIG_BOOT_LOADER || CONFIG_VM_ROM -# ifndef XCHAL_DEBUGLEVEL /* debug option not selected? */ -# define XCHAL_DEBUGLEVEL 99 /* bogus value outside 2..6 */ -# endif - - .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_<n>_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 - - init_vector 2 - init_vector 3 - init_vector 4 - init_vector 5 - init_vector 6 -#endif -#endif /*HAVE_XSR*/ - - - /* - * Complete reset initialization outside the vector, - * to avoid requiring a vector that is larger than necessary. - * This 2nd-stage startup code sets up the C Run-Time (CRT) and calls main(). - * - * Here we use call0 not because we expect any return, but - * because the assembler/linker dynamically sizes call0 as - * needed (with -mlongcalls) which it doesn't with j or jx. - * Note: This needs to be call0 regardless of the selected ABI. - */ - -#if CONFIG_BOOT_LOADER && !CONFIG_VM_ROM - movi a0, SOF_TEXT_BASE - callx0 a0 -#else - call0 _start // jump to _start (in crt1-*.S) -#endif - /* does not return */ - -#else /* XCHAL_HAVE_HALT */ - - j _start // jump to _start (in crt1-*.S) - // (TX has max 64kB IRAM, so J always in range) - - // Paranoia -- double-check requirements / assumptions of this Xtensa TX code: -# if !defined(__XTENSA_CALL0_ABI__) || !XCHAL_HAVE_FULL_RESET || XCHAL_HAVE_INTERRUPTS || XCHAL_HAVE_CCOUNT || XCHAL_DTLB_ARF_WAYS || XCHAL_HAVE_DEBUG || XCHAL_HAVE_S32C1I || XCHAL_HAVE_ABSOLUTE_LITERALS || XCHAL_DCACHE_SIZE || XCHAL_ICACHE_SIZE || XCHAL_HAVE_PIF || XCHAL_HAVE_WINDOWED -# error "Halt architecture (Xtensa TX) requires: call0 ABI, all flops reset, no exceptions or interrupts, no TLBs, no debug, no S32C1I, no LITBASE, no cache, no PIF, no windowed regs" -# endif - -#endif /* XCHAL_HAVE_HALT */ - - -#if (!XCHAL_HAVE_HALT || defined(XTOS_UNPACK)) && XCHAL_HAVE_IMEM_LOADSTORE - .size _ResetHandler, . - _ResetHandler -#else - .size _ResetVector, . - _ResetVector -#endif - - .text - .global xthals_hw_configid0, xthals_hw_configid1 - .global xthals_release_major, xthals_release_minor - .end literal_prefix diff --git a/src/arch/xtensa/xtos/shared-reset-vector.S b/src/arch/xtensa/xtos/shared-reset-vector.S deleted file mode 100644 index ae457f9507d3..000000000000 --- a/src/arch/xtensa/xtos/shared-reset-vector.S +++ /dev/null @@ -1,73 +0,0 @@ -// shared-reset-vector.S -- Sharable Reset Vector (requires PRID option) - -// Copyright (c) 1999-2010 Tensilica 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 <xtensa/coreasm.h> - - // Populate this processor's entry in the reset table. - // The core instance specific LSP should put this section - // in the correct location within the table. - // - .section .ResetTable.rodata, "a" - .word _ResetHandler - - // This sharable reset code assumes RC-2009.0 or later hardware, - // to guarantee that no processor state initialization is required - // prior to doing loads etc. - // Total size is 28 bytes (or 27 with density option). - // By necessity, none of these bytes vary by core instance; - // the appropriate reset table entry is selected using PRID. - // -#if XCHAL_HAVE_PRID - .section .SharedResetVector.text, "ax" - .begin no-absolute-literals - - .align 4 - .global _SharedResetVector -_SharedResetVector: - j .LSharedResetHandler - - .align 4 - .literal_position - - // Use L32R if available -#if XCHAL_HAVE_L32R - .literal rtbase, _ResetTable_base -#endif - - .align 4 -.LSharedResetHandler: - rsr.prid a0 // get processor ID (16 bits) -#if XCHAL_HAVE_L32R - l32r a1, rtbase // force use of L32R -#else - movi a1, _ResetTable_base // No L32R, will likely become CONST16 -#endif - extui a0, a0, 0, 4 // ID of core within the multiprocessor (FIXME: need proper constant...) - addx4 a1, a0, a1 - l32i a1, a1, 0 - jx a1 // jump to core-specific initialization - - .size _SharedResetVector, . - _SharedResetVector - .end no-absolute-literals -#endif - diff --git a/src/arch/xtensa/xtos/textaddr b/src/arch/xtensa/xtos/textaddr deleted file mode 100755 index 4355facf1b4e..000000000000 --- a/src/arch/xtensa/xtos/textaddr +++ /dev/null @@ -1,59 +0,0 @@ -# Program to determine -Ttext parameter for ld -# $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/textaddr#1 $ - -# Copyright (c) 2001 Tensilica 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. - -package textaddr; - -use strict; -use FileHandle; - -{ - $::myname = 'textaddr'; - - die("Usage is: $::myname objfile label address\n") - unless @ARGV == 3; - my($objfile, $label, $address) = @ARGV; - - - my $nm = new FileHandle "xt-nm $objfile|"; - die("$::myname: $!, opening pipe to xt-nm $objfile.\n") - unless $nm; - while (<$nm>) { - if (/^([0-9a-f]{8}) . (\w+)$/) { - my $oaddress = $1; - my $olabel = $2; - if ($olabel eq $label) { - printf ("0x%x\n", hex($address) - hex($oaddress)); - exit(0); - } - } - } - die ("$::myname: $label not found in $objfile.\n"); -} - -# -# Local Variables: -# mode:perl -# perl-indent-level:2 -# cperl-indent-level:2 -# End: diff --git a/src/arch/xtensa/xtos/tiny-refs-min.S b/src/arch/xtensa/xtos/tiny-refs-min.S deleted file mode 100644 index 453001cb7294..000000000000 --- a/src/arch/xtensa/xtos/tiny-refs-min.S +++ /dev/null @@ -1,28 +0,0 @@ -// tiny-refs-min.S - References to pull-in selected modules into tiny LSPs - -// Copyright (c) 2006 Tensilica 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. - - - .global _need_user_vector_ - .set _need_user_vector_, 0 // define this, so if referenced... - .global _UserExceptionVector // ... we pull-in this - diff --git a/src/arch/xtensa/xtos/tiny-refs.S b/src/arch/xtensa/xtos/tiny-refs.S deleted file mode 100644 index d89407e0eed9..000000000000 --- a/src/arch/xtensa/xtos/tiny-refs.S +++ /dev/null @@ -1,33 +0,0 @@ -// tiny-refs.S - References to pull-in selected modules into tiny LSPs - -// Copyright (c) 2006 Tensilica 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. - -#if defined(__SPLIT__level1int) - - .global _need_level1int_ - .set _need_level1int_, 0 // define this, so if referenced... - .global _need_user_vector_ // ... we pull-in this - .global _xtos_l1int_handler // and this - -#endif - - diff --git a/src/arch/xtensa/xtos/user-vector-min.S b/src/arch/xtensa/xtos/user-vector-min.S deleted file mode 100644 index d8f19ea5c1cd..000000000000 --- a/src/arch/xtensa/xtos/user-vector-min.S +++ /dev/null @@ -1,110 +0,0 @@ -// user-vector-min.S - Minimal User Vector for General Exceptions -// Takes less table space, but does not allow registering new handlers. -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/user-vector-min.S#1 $ - -// Copyright (c) 2003-2015 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/config/system.h> -#include "xtos-internal.h" - -#if XCHAL_HAVE_EXCEPTIONS && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) - - // Vector code - .begin literal_prefix .UserExceptionVector - .section .UserExceptionVector.text, "ax" - .align 4 - .global _UserExceptionVector -_UserExceptionVector: -# if (((XSHAL_USER_VECTOR_SIZE >= 28) && XCHAL_HAVE_ADDX && XCHAL_HAVE_DENSITY && XCHAL_HAVE_L32R) || (XSHAL_USER_VECTOR_SIZE >= 36) || XSHAL_VECTORS_PACKED) && !defined(XSHAL_ERRATUM_487_FIX) - - addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. - s32i a2, a1, UEXC_a2 - s32i a3, a1, UEXC_a3 - rsr.exccause a2 // get exception cause - movi a3, _xtos_min_handler_table - bgeui a2, 6, 1f // causes 6 and above map to zero - addx4 a3, a2, a3 // index by cause if 1 .. 5 -1: l32i a3, a3, 0 - s32i a4, a1, UEXC_a4 - jx a3 // jump to cause-specific handler - - .size _UserExceptionVector, . - _UserExceptionVector - .end literal_prefix - -# else /*vector as small as 12 bytes:*/ - - addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. - s32i a2, a1, UEXC_a2 - movi a2, _UserExceptionFromVector // load user exception handler address - //interlock - jx a2 // jump to handler - - .size _UserExceptionVector, . - _UserExceptionVector - .end literal_prefix - - // Dispatch outside vector: - .text - .align 4 - .global _UserExceptionFromVector -_UserExceptionFromVector: - hw_erratum_487_fix - rsr.exccause a2 // get exception cause - s32i a3, a1, UEXC_a3 - movi a3, _xtos_min_handler_table - bgeui a2, 6, 1f // causes 6 and above map to zero - addx4 a3, a2, a3 // index by cause if 1 .. 5 -1: l32i a3, a3, 0 - s32i a4, a1, UEXC_a4 - jx a3 // jump to cause-specific handler - .size _UserExceptionFromVector, . - _UserExceptionFromVector - -# endif - - - /* - * Read-only minimal table of assembly-level exception handlers - * for user vectored exceptions. - * Only provides entries for SYSCALL, MOVSP, and level-1 interrupt causes. - */ - .section .rodata, "a" - .global _xtos_min_handler_table - .align 4 -_xtos_min_handler_table: - .word xtos_unhandled_exception // 0 Illegal Instruction, and causes > 5 - .word _xtos_syscall_handler // 1 SYSCALL Instruction - .word xtos_unhandled_exception // 2 Instruction Fetch Error - .word xtos_unhandled_exception // 3 Load/Store Error -# if XCHAL_HAVE_INTERRUPTS - .word _xtos_l1int_handler // 4 Level-1 Interrupt -# else - .word xtos_unhandled_exception // 4 Level-1 Interrupt (not configured) -# endif -# if XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) - .word _xtos_alloca_handler // 5 Alloca (MOVSP Instruction) -# else - .word xtos_unhandled_exception // 5 Alloca (MOVSP Instruction) (not configured) -# endif - .text - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/user-vector.S b/src/arch/xtensa/xtos/user-vector.S deleted file mode 100644 index 15375e2e7058..000000000000 --- a/src/arch/xtensa/xtos/user-vector.S +++ /dev/null @@ -1,200 +0,0 @@ -// user-vector.S - User Vector for General Exceptions -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/user-vector.S#1 $ - -// Copyright (c) 1998-2015 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include <xtensa/config/system.h> -#include "xtos-internal.h" - -#if XCHAL_HAVE_EXCEPTIONS && (XCHAL_HAVE_XEA1 || XCHAL_HAVE_XEA2) - - // Vector code - .section .UserExceptionVector.text, "ax" - .align 4 - .global _UserExceptionVector -_UserExceptionVector: -# if (((XSHAL_USER_VECTOR_SIZE >= 28) && XCHAL_HAVE_ADDX && XCHAL_HAVE_DENSITY && XCHAL_HAVE_L32R) || (XSHAL_USER_VECTOR_SIZE >= 36) || XSHAL_VECTORS_PACKED) && !defined (XSHAL_ERRATUM_487_FIX) - // There is space to dispatch right at the vector: - - addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. - s32i a2, a1, UEXC_a2 - s32i a3, a1, UEXC_a3 - movi a3, xtos_exc_handler_table - rsr.exccause a2 // get exception cause - //interlock - addx4 a3, a2, a3 - l32i a3, a3, 0 - s32i a4, a1, UEXC_a4 - jx a3 // jump to cause-specific handler - - .size _UserExceptionVector, . - _UserExceptionVector - -# else - // The vector may be as small as 12 bytes: - - addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. - s32i a2, a1, UEXC_a2 - movi a2, _UserExceptionFromVector // load user exception handler address - //interlock - jx a2 // jump to handler - - .size _UserExceptionVector, . - _UserExceptionVector - - // Dispatch outside vector: - .text - //.subsection 2 - .align 4 - .global _UserExceptionFromVector -_UserExceptionFromVector: - hw_erratum_487_fix - s32i a3, a1, UEXC_a3 - movi a3, xtos_exc_handler_table - rsr.exccause a2 // get exception cause - s32i a4, a1, UEXC_a4 - addx4 a3, a2, a3 - l32i a3, a3, 0 - jx a3 // jump to cause-specific handler - - .size _UserExceptionFromVector, . - _UserExceptionFromVector - -# endif - - - .weak xtos_cause3_handler - - /* - * Table of assembly-level general-exception handlers - * (quickly entered) for user vectored exceptions. - * Provides entries for all possible 64 exception causes - * currently allowed for in the EXCCAUSE register. - * - * NOTE: entries that have a corresponding C handler - * (registered at run-time) point to xtos_c_wrapper_handler; - * entries that have no handler point to xtos_unhandled_exception. - */ - .data -#if CONFIG_SMP - .global xtos_exc_handler_table_r -#else - .global xtos_exc_handler_table -#endif - .align 4 -#if CONFIG_SMP -xtos_exc_handler_table_r: -#else -xtos_exc_handler_table: -#endif - .word xtos_unhandled_exception // 0 IllegalInstruction - .word _xtos_syscall_handler // 1 Syscall - .word xtos_unhandled_exception // 2 InstructionFetchError - .word xtos_unhandled_exception // 3 LoadStoreError -# if XCHAL_HAVE_INTERRUPTS - .word _xtos_l1int_handler // 4 Level1Interrupt -# else - .word xtos_unhandled_exception // 4 Level1Interrupt (not configured) -# endif -# if XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) - .word _xtos_alloca_handler // 5 Alloca (MOVSP) -# else - .word xtos_unhandled_exception // 5 Alloca (MOVSP) (not configured) -# endif - .word xtos_unhandled_exception // 6 IntegerDivideByZero - .word xtos_unhandled_exception // 7 Speculation - .word xtos_unhandled_exception // 8 Privileged - .word xtos_unhandled_exception // 9 Unaligned - .word xtos_unhandled_exception //10 (reserved for Tensilica) - .word xtos_unhandled_exception //11 (reserved for Tensilica) - .word xtos_cause3_handler //12 PIF data error on fetch - .word xtos_cause3_handler //13 PIF data error on ld/st - .word xtos_cause3_handler //14 PIF address error on fetch - .word xtos_cause3_handler //15 PIF address error on ld/st - .word xtos_unhandled_exception //16 InstTLBMiss - .word xtos_unhandled_exception //17 InstTLBMultiHit - .word xtos_unhandled_exception //18 InstFetchPrivilege - .word xtos_unhandled_exception //19 (reserved for Tensilica) - .word xtos_unhandled_exception //20 InstFetchProhibited - .word xtos_unhandled_exception //21 (reserved for Tensilica) - .word xtos_unhandled_exception //22 (reserved for Tensilica) - .word xtos_unhandled_exception //23 (reserved for Tensilica) - .word xtos_unhandled_exception //24 LoadStoreTLBMiss - .word xtos_unhandled_exception //25 LoadStoreTLBMultiHit - .word xtos_unhandled_exception //26 LoadStorePrivilege - .word xtos_unhandled_exception //27 (reserved for Tensilica) - .word xtos_unhandled_exception //28 LoadProhibited - .word xtos_unhandled_exception //29 StoreProhibited - .word xtos_unhandled_exception //30 (reserved for Tensilica) - .word xtos_unhandled_exception //31 (reserved for Tensilica) - .rept 8 - .word xtos_unhandled_exception //32-39 Coprocessor<n>Disabled (n = 0..7) - .endr - - .rept XCHAL_EXCCAUSE_NUM-40 - .word xtos_unhandled_exception //40-63 (reserved for TIE) - .endr -#if CONFIG_SMP - .section .bss - .global xtos_exc_handler_table - .align 4 -xtos_exc_handler_table: - .space XCHAL_EXCCAUSE_NUM*4 -#endif - .text - - - // NOTES: - // - // Here are alternative vectors. They will NOT work with - // the handlers currently provided with XTOS. However they - // might be useful to someone writing their own handlers - // from scratch. Note that XSR is only available on T1040 - // and later hardware. - // -//*** The typical tiny 9-byte vector: *** -// wsr.excsave1 a3 // save user a3 -// movi a3, _UserExceptionFromVector // load user exception handler address -// jx a3 -// -//*** Minimizing EXCCAUSE-dispatch delay, not assuming valid SP: *** -// wsr.depc a0 // save a0 (double exceptions fatal here, so not expected) -// rsr.exccause a0 -// xsr.excsave1 a1 // EXCSAVE_1 always contains &exception_handlers[0] -// //interlock -// addx4 a0, a0, a1 -// l32i a0, a0, TABLE_OFS + EXC_CODE_KERNEL*4 -// xsr.excsave1 a1 // restore a1 (DEPC contains original a0) -// jx a0 // jump to cause-specific handler -// -//*** Doing EXCCAUSE-dispatch with table in EXCSAVE_1: *** -// addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. -// s32i a2, a1, UEXC_a2 -// rsr.exccause a2 -// xsr.excsave1 a4 // EXCSAVE_1 always contains &exception_handlers[0] -// s32i a3, a1, UEXC_a3 -// addx4 a2, a2, a4 -// l32i a2, a2, TABLE_OFS + EXC_CODE_KERNEL*4 -// xsr.excsave1 a4 // restore a1 (DEPC contains original a0) -// jx a2 // jump to cause-specific handler - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/xea1/exc-alloca-handler.S b/src/arch/xtensa/xtos/xea1/exc-alloca-handler.S deleted file mode 100644 index c3b63fb0b377..000000000000 --- a/src/arch/xtensa/xtos/xea1/exc-alloca-handler.S +++ /dev/null @@ -1,275 +0,0 @@ -// exc-alloca-handler.S - OBSOLETE - ALLOCA cause exception assembly-level handler - -#if 0 /* This handler is OBSOLETE - now part of window-vectors.S */ - -// Copyright (c) 2002-2010 Tensilica 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. - -/* - * Code written to the windowed ABI must use the MOVSP instruction to modify - * the stack pointer (except for startup code, which doesn't have a caller). - * The compiler uses MOVSP to allocate very large or variable size stack frames. - * MOVSP guarantees that the caller frame's a0-a3 registers, stored below the - * stack pointer, are moved atomically with respect to interrupts and exceptions - * to satisfy windowed ABI requirements. When user code executes the MOVSP - * instruction and the caller frame is on the stack rather than in the register - * file, the processor takes an ALLOCA exception. The ALLOCA exception handler - * moves the caller frame's a0-a3 registers to follow the stack pointer. - * This file implements this ALLOCA exception handler. - * - * Code written in C can generate a MOVSP in four situations: - * - * 1. By calling "alloca": - * - * void foo(int array_size) { - * char * bar = alloca(array_size); - * ... - * - * 2. By using variable sized arrays (a GNU C extension): - * - * void foo(int array_size) { - * char bar[array_size]; - * ... - * - * 3. By using nested C functions (also a GNU C extension): - * - * void afunction(void) { - * ... - * int anotherfunction(void) { - * } - * ... - * - * 4. By using very large amounts of stack space in a single function. The exact - * limit is 32,760 bytes (including 16-48 bytes of caller frame overhead). - * Typically, users don't encounter this limit unless they have functions - * that locally declare large arrays, for example: - * - * void foo(void) { - * int an_array[8192]; // 32,768 bytes - * int another_array[100]; // 400 bytes - * ... - * - * - * NOTE: This handler only works when MOVSP's destination register is the stack - * pointer "a1" (synonym with "sp"), i.e. "MOVSP a1, <as>". This is the only - * meaningful form of MOVSP in the windowed ABI, and the only form generated - * by the compiler and used in assembly. The code below does not check the - * destination register, so other forms of MOVSP cause unexpected behaviour. - */ - -#include <xtensa/coreasm.h> -#include "xtos-internal.h" - -#define ERROR_CHECKING 1 // define as 0 to save a few bytes - - -#if XCHAL_HAVE_EXCEPTIONS - -//Vector: -// addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. -// s32i a2, a1, UEXC_a2 -// s32i a3, a1, UEXC_a3 -// movi a3, xtos_exc_handler_table -// rsr.exccause a2 -// addx4 a2, a2, a3 -// l32i a2, a2, 0 -// s32i a4, a1, UEXC_a4 -// jx a2 // jump to cause-specific handler - - .global _need_user_vector_ // pull-in real user vector (tiny LSP) - - .text - .align 4 - .global _xtos_alloca_handler -_xtos_alloca_handler: -#if !XCHAL_HAVE_WINDOWED || defined(__XTENSA_CALL0_ABI__) - rfe_rfue -#else /* we have windows w/o call0 abi */ - // HERE: a2, a3, a4 have been saved to - // exception stack frame allocated with a1 (sp). - // a2 contains EXCCAUSE. - // (12 cycles from vector to here, assuming cache hits, 5-stage pipe, etc) - - /* - * Skip the MOVSP instruction so we don't execute it again on return: - */ - - rsr.epc1 a3 // load instruction address (PC) - s32i a5, a1, UEXC_a5 // save a5 - addi a2, a3, 3 // increment PC to skip MOVSP instruction -#if XCHAL_HAVE_LOOPS - /* - * If the MOVSP instruction is the last instruction in the body of - * a zero-overhead loop that must be executed again, then decrement - * the loop count and resume execution at the head of the loop. - */ - rsr.lend a4 - rsr.lcount a5 - bne a4, a2, 1f // done unless next-PC matches LEND - beqz a5, 1f // if LCOUNT zero, not in loop - addi a5, a5, -1 // z.o. loopback! decrement LCOUNT... - wsr.lcount a5 - rsr.lbeg a2 // PC back to start of loop -#endif /*XCHAL_HAVE_LOOPS*/ -1: wsr.epc1 a2 // update return PC past MOVSP - - /* - * Figure out what register MOVSP is moving from ('s' field, 2nd byte). - * If MOVSP is in an instruction RAM or ROM, we can only access it with - * 32-bit loads. So use shifts to read the byte from a 32-bit load. - */ - - addi a3, a3, 1 // advance to byte containing 's' field - extui a2, a3, 0, 2 // get bits 0 and 1 of address of this byte - sub a3, a3, a2 // put address on 32-bit boundary - l32i a3, a3, 0 // get word containing byte (can't use l8ui on IRAM/IROM) - rsr.sar a4 // save SAR - // NOTE: possible addition here: verify destination register is indeed a1. -# if XCHAL_HAVE_BE - ssa8b a2 - sll a3, a3 - extui a3, a3, 28, 4 // extract source register number -# else - ssa8l a2 - srl a3, a3 - extui a3, a3, 0, 4 // extract source register number -# endif - wsr.sar a4 // restore SAR - // (+?? cycles max above = ?? cycles, assuming cache hits, 5-stage pipe, no zoloops, etc) - - movi a4, .Ljmptable // jump table - mov a5, a1 // save the exception stack frame ptr in a5 - addi a1, a1, ESF_TOTALSIZE // restore a1 (in case of MOVSP a1,a1) - -# if XCHAL_HAVE_DENSITY - addx4 a4, a3, a4 // index by src reg number * 4 -# define ALIGN .align 4 // 4-byte jmptable entries -# define MOV _mov.n -# define L32I _l32i.n -# define DONE _bnez.n a4, .Lmove_save_area // a4 known non-zero -# else - addx8 a4, a3, a4 // index by src reg number * 8 -# define ALIGN .align 8 // 8-byte jmptable entries -# define MOV mov -# define L32I l32i -# define DONE j .Lmove_save_area -# endif - - jx a4 // jump into the following table - - ALIGN -.Ljmptable: MOV a1, a0 ; DONE // MOVSP a1, a0 - ALIGN ; DONE // MOVSP a1, a1 - ALIGN ; L32I a1, a5, UEXC_a2 ; DONE // MOVSP a1, a2 - ALIGN ; L32I a1, a5, UEXC_a3 ; DONE // MOVSP a1, a3 - ALIGN ; L32I a1, a5, UEXC_a4 ; DONE // MOVSP a1, a4 - ALIGN ; L32I a1, a5, UEXC_a5 ; DONE // MOVSP a1, a5 - ALIGN ; MOV a1, a6 ; DONE // MOVSP a1, a6 - ALIGN ; MOV a1, a7 ; DONE // MOVSP a1, a7 - ALIGN ; MOV a1, a8 ; DONE // MOVSP a1, a8 - ALIGN ; MOV a1, a9 ; DONE // MOVSP a1, a9 - ALIGN ; MOV a1, a10 ; DONE // MOVSP a1, a10 - ALIGN ; MOV a1, a11 ; DONE // MOVSP a1, a11 - ALIGN ; MOV a1, a12 ; DONE // MOVSP a1, a12 - ALIGN ; MOV a1, a13 ; DONE // MOVSP a1, a13 - ALIGN ; MOV a1, a14 ; DONE // MOVSP a1, a14 - ALIGN ; MOV a1, a15 // MOVSP a1, a15 - -.Lmove_save_area: - // Okay. a1 now contains the new SP value. - -# if ERROR_CHECKING - // Verify it is sensible: - extui a3, a1, 0, 2 // verify that new SP is 4-byte aligned - beqz a3, 1f // if so, skip fixup - -// .global _xtos_misaligned_movsp // make label visible for debugging -//_xtos_misaligned_movsp: -# if XCHAL_HAVE_DEBUG - break 1, 15 // break into debugger (if any) -# endif - sub a1, a1, a3 // FORCE alignment of the new pointer (!) -1: -# endif - -# if XCHAL_HAVE_XEA2 - addi a2, a5, ESF_TOTALSIZE // compute a2 = old SP -# else /*XEA1:*/ - addi a2, a5, ESF_TOTALSIZE-16 // compute a2 = old SP's save area -# endif - // Does new SP (in a1) overlap with exception stack frame (in a5)?: - movi a4, ESF_TOTALSIZE // size of exception stack frame - sub a3, a1, a5 // distance from ESF ptr to new SP - bgeu a3, a4, 1f // does new SP overlap ESF? branch if not - // Move ESF down so it doesn't overlap with the new register save area: - // (a1 = current ESF, a2 = new SP, a4 = ESF_TOTALSIZE) - sub a5, a5, a4 // shift down ESF (by ESF size) - l32i a3, a5, UEXC_a2+ESF_TOTALSIZE - l32i a4, a5, UEXC_a3+ESF_TOTALSIZE - s32i a3, a5, UEXC_a2 - s32i a4, a5, UEXC_a3 - l32i a3, a5, UEXC_a4+ESF_TOTALSIZE - l32i a4, a5, UEXC_a5+ESF_TOTALSIZE - s32i a3, a5, UEXC_a4 - s32i a4, a5, UEXC_a5 -1: - - // Move the register save area (from old SP to new SP): -# if XCHAL_HAVE_XEA2 - l32e a3, a2, -16 - l32e a4, a2, -12 - s32e a3, a1, -16 - s32e a4, a1, -12 - l32e a3, a2, -8 - l32e a4, a2, -4 - s32e a3, a1, -8 - s32e a4, a1, -4 -# else /*XEA1:*/ - addi a1, a1, -16 // point to new save area - l32i a3, a2, 0 - l32i a4, a2, 4 - s32i a3, a1, 0 - s32i a4, a1, 4 - l32i a3, a2, 8 - l32i a4, a2, 12 - s32i a3, a1, 8 - s32i a4, a1, 12 - addi a1, a1, 16 // back to correct new SP -# endif /*XEA1*/ - // (+?? cycles max above = ?? cycles, assuming cache hits, 5-stage pipe, etc) - - // Restore a2, a3, a4, a5, and return: - l32i a2, a5, UEXC_a2 - l32i a3, a5, UEXC_a3 - l32i a4, a5, UEXC_a4 - l32i a5, a5, UEXC_a5 - rfe_rfue - // (+?? cycles max above = ?? cycles, assuming cache hits, 5-stage pipe, etc) - - -#endif /* !XCHAL_HAVE_WINDOWED || __XTENSA_CALL0_ABI */ - - .size _xtos_alloca_handler, . - _xtos_alloca_handler - -#endif /* XCHAL_HAVE_EXCEPTIONS */ - -#endif /* 0 */ - diff --git a/src/arch/xtensa/xtos/xea1/exc-c-wrapper-handler.S b/src/arch/xtensa/xtos/xea1/exc-c-wrapper-handler.S deleted file mode 100644 index 9937e8f7208a..000000000000 --- a/src/arch/xtensa/xtos/xea1/exc-c-wrapper-handler.S +++ /dev/null @@ -1,374 +0,0 @@ -// xea1/exc-c-wrapper-handler.S - General Exception Handler that Dispatches C Handlers - -// Copyright (c) 2002-2016 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/config/specreg.h> -#include "../xtos-internal.h" -#ifdef SIMULATOR -#include <xtensa/simcall.h> -#endif - -#if XCHAL_HAVE_XEA1 && XCHAL_HAVE_EXCEPTIONS /* note - XEA1 always has exceptions */ - - -/* - * This assembly-level handler causes the associated exception (usually causes 12-15) - * to be handled as if it were exception cause 3 (load/store error exception). - * This provides forward-compatibility with a possible future split of the - * load/store error cause into multiple more specific causes. - */ - .align 4 - .global xtos_cause3_handler -xtos_cause3_handler: - movi a2, EXCCAUSE_LOAD_STORE_ERROR - j xtos_c_wrapper_handler - .size xtos_cause3_handler, . - xtos_cause3_handler - - -/* - * This is the general exception assembly-level handler that dispatches C handlers. - */ - .align 4 - .global xtos_c_wrapper_handler -xtos_c_wrapper_handler: -#ifdef __XTENSA_CALL0_ABI__ - // Redundantly de-allocate and re-allocate stack, so that GDB prologue - // analysis picks up the allocate part, and figures out how to traceback - // through the call stack through the exception. - addi a1, a1, ESF_TOTALSIZE // de-allocate stack frame (FIXME is it safe) -.global xtos_c_wrapper_dispatch -xtos_c_wrapper_dispatch: - // GDB starts analyzing prologue after most recent global symbol, so here: - addi a1, a1, -ESF_TOTALSIZE // re-allocate stack frame -#endif - - // HERE: a2, a3, a4 have been saved to exception stack frame allocated with a1 (sp). - // a2 contains EXCCAUSE. - s32i a5, a1, UEXC_a5 // a5 will get clobbered by ENTRY after the pseudo-CALL4 - // (a4..a15 spilled as needed; save if modified) - - //NOTA: Possible future improvement: - // keep interrupts disabled until we get into the handler, such that - // we don't have to save other critical state such as EXCVADDR here. - //rsr.excvaddr a3 - s32i a2, a1, UEXC_exccause - //s32i a3, a1, UEXC_excvaddr - -#if XCHAL_HAVE_INTERRUPTS - rsilft a3, 1, XTOS_LOCKLEVEL // lockout - rsr.intenable a2 - //movi a3, ~XCHAL_EXCM_MASK - movi a3, ~XTOS_LOCKOUT_MASK // mask out low and medium priority levels, and high priority levels covered by - // XTOS_LOCKLEVEL if any, so we can run at PS.INTLEVEL=0 while manipulating INTENABLE - s32i a2, a1, UEXC_sar // (temporary holding place for INTENABLE value to restore after pseudo-CALL4 below) - and a3, a2, a3 // mask out selected interrupts - wsr.intenable a3 // disable all interrupts up to and including XTOS_LOCKLEVEL -#endif - movi a3, PS_WOECALL4_ABI|PS_UM // WOE=0|1, UM=1, INTLEVEL=0, CALLINC=0|1 (call4 emul), OWB=(dontcare)=0 - - // NOTE: could use XSR here if targeting T1040 or T1050 hardware (requiring slight sequence adjustment as for XEA2): - rsr.ps a2 - rsync //NOT-ISA-DEFINED // wait for WSR to INTENABLE to complete before clearing PS.INTLEVEL - wsr.ps a3 // PS.INTLEVEL=0, effective INTLEVEL (via INTENABLE) is XTOS_LOCKLEVEL - - // HERE: window overflows enabled, but NOT SAFE because we're not quite - // in a valid windowed context (haven't restored a1 yet...); - // so don't cause any (keep to a0..a3) until we've saved critical state and restored a1: - - // NOTE: MUST SAVE EPC1 before causing any overflows, because overflows corrupt EPC1. - rsr.epc1 a3 - s32i a2, a1, UEXC_ps - s32i a3, a1, UEXC_pc - - -#ifdef __XTENSA_CALL0_ABI__ - - s32i a0, a1, UEXC_a0 // save the rest of the registers - s32i a6, a1, UEXC_a6 - s32i a7, a1, UEXC_a7 - s32i a8, a1, UEXC_a8 - s32i a9, a1, UEXC_a9 - s32i a10, a1, UEXC_a10 - s32i a11, a1, UEXC_a11 - s32i a12, a1, UEXC_a12 - s32i a13, a1, UEXC_a13 - s32i a14, a1, UEXC_a14 - s32i a15, a1, UEXC_a15 -# if XTOS_DEBUG_PC - // TODO: setup return PC for call traceback through interrupt dispatch -# endif - - rsync // wait for WSR to PS to complete - -#else /* ! __XTENSA_CALL0_ABI__ */ - -# if XTOS_CNEST - l32i a2, a1, ESF_TOTALSIZE-20 // save nested-C-func call-chain ptr -# endif - addi a1, a1, ESF_TOTALSIZE // restore sp (dealloc ESF) for sane stack again - rsync // wait for WSR to PS to complete - - /* HERE: we can SAFELY get window overflows. - * - * From here, registers a4..a15 automatically get spilled if needed. - * They become a0..a11 after the ENTRY instruction. - * Currently, we don't check whether or not these registers - * get spilled, so we must save and restore any that we - * modify. We've already saved a4 and a5 - * which we modify as part of the pseudo-CALL. - * - * IMPLEMENTATION NOTE: - * - * The pseudo-CALL below effectively saves registers a2..a3 so - * that they are available again after the corresponding - * RETW when returning from the exception handling. We - * could choose to put something like EPC1 or PS in - * there, so they're available more quickly when - * restoring. HOWEVER, exception handlers may wish to - * change such values, or anything on the exception stack - * frame, and expect these to be restored as modified. - * - * NOTA: future: figure out what's the best thing to put - * in a2 and a3. (candidate: a4 and a5 below; but what - * if exception handler manipulates ARs, as in a syscall - * handler.... oh well) - * - * - * Now do the pseudo-CALL. - * Make it look as if the code that got the exception made a - * CALL4 to the exception handling code. (We call - * this the "pseudo-CALL".) - * - * This pseudo-CALL is important and done this way: - * - * 1. There are only three ways to safely update the stack pointer - * in the windowed ABI, such that window exceptions work correctly: - * (a) spill all live windows to stack then switch to a new stack - * (or, save the entire address register file and window - * registers, which is likely even more expensive) - * (b) use MOVSP (or equivalent) - * (c) use ENTRY/RETW - * Doing (a) is excessively expensive, and doing (b) here requires - * copying 16 bytes back and forth which is also time-consuming; - * whereas (c) is very efficient, so that's what we do here. - * - * 2. Normally we cannot do a pseudo-CALL8 or CALL12 here. - * According to the - * windowed ABI, a function must allocate enough space - * for the largest call that it makes. However, the - * pseudo-CALL is executed in the context of the - * function that happened to be executing at the time - * the interrupt was taken, and that function might or - * might not have allocated enough stack space for a - * CALL8 or a CALL12. If we try doing a pseudo-CALL8 - * or -CALL12 here, we corrupt the stack if the - * interrupted function happened to not have allocated - * space for such a call. - * - * 3. We set the return PC, but it's not strictly - * necessary for proper operation. It does make - * debugging, ie. stack tracebacks, much nicer if it - * can point to the interrupted code (not always - * possible, eg. if interrupted code is in a different - * GB than the interrupt handling code, which is - * unlikely in a system without protection where - * interrupt handlers and general application code are - * typically linked together). - * - * IMPORTANT: Interrupts must stay disabled while doing the pseudo-CALL, - * or at least until after the ENTRY instruction, because SP has been - * restored to its original value that does not reflect the exception - * stack frame's allocation. An interrupt taken here would - * corrupt the exception stack frame (ie. allocate another over it). - * (High priority interrupts can remain enabled, they save and restore - * all of their state and use their own stack or save area.) - * For the same reason, we mustn't get any exceptions in this code - * (other than window exceptions where noted) until ENTRY is done. - */ - - // HERE: may get a single window overflow (caused by the following instruction). - -# if XTOS_DEBUG_PC - movi a4, 0xC0000000 // [for debug] for return PC computation below - or a3, a4, a3 // [for debug] set upper two bits of return PC - addx2 a4, a4, a3 // [for debug] clear upper bit -# else - movi a4, 0 // entry cannot cause overflow, cause it here -# endif - - .global _GeneralException -_GeneralException: // this label makes tracebacks through exceptions look nicer - - _entry a1, ESF_TOTALSIZE // as if after a CALL4 (PS.CALLINC set to 1 above) - - /* - * The above ENTRY instruction does a number of things: - * - * 1. Because we're emulating CALL4, the ENTRY rotates windows - * forward by 4 registers (as per 'ROTW +1'), so that - * a4-a15 became a0-a11. So now: a0-a11 are part of - * the interrupted context to be preserved. a0-a1 - * were already saved above when they were a4-a5. - * a12-a15 are free to use as they're NOT part of the - * interrupted context. We don't need to save/restore - * them, and they will get spilled if needed. - * - * 2. Updates SP (new a1), allocating the exception stack - * frame in the new window, preserving the old a1 in - * the previous window. - * - * 3. The underscore prefix prevents the assembler from - * automatically aligning the ENTRY instruction on a - * 4-byte boundary, which could create a fatal gap in - * the instruction stream. - * - * At this point, ie. before we re-enable interrupts, we know the caller is - * always live so we can safely modify a1 without using MOVSP (we can use MOVSP - * but it will never cause an ALLOCA or underflow exception here). - * So this is a good point to modify the stack pointer if we want eg. to - * switch to an interrupt stack (if we do, we need to save the current SP - * because certain things have been saved to that exception stack frame). - * We couldn't do this easily before ENTRY, where the caller wasn't - * necessarily live. - * - * NOTE: We don't switch to an interrupt stack here, because exceptions - * are generally caused by executing code -- so we handle exceptions in - * the context of the thread that cause them, and thus remain on the same - * stack. This means a thread's stack must be large enough to handle - * the maximum level of nesting of exceptions that the thread can cause. - */ - - // NOTA: exception handlers for certain causes may need interrupts to be kept - // disabled through their dispatch, so they can turn them off themselves at - // the right point (if at all), eg. to save critical state unknown to this - // code here, or for some recovery action that must be atomic with respect - // to interrupts.... - // - // Perhaps two versions of this assembly-level handler are needed, one that restores - // interrupts to what they were before the exception was taken (as here) - // and one that ensures at least low-priority interrupts are kept disabled? - // NOTA: For now, always enable interrupts here. - - /* - * Now we can enable interrupts. - * (Pseudo-CALL is complete, and SP reflects allocation of exception stack frame.) - */ - -#endif /* __XTENSA_CALL0_ABI__ */ - - -#if XCHAL_HAVE_INTERRUPTS - //... recompute and set INTENABLE ... - l32i a13, a1, UEXC_sar // (temporary holding place for INTENABLE value saved before pseudo-CALL4 above) - rsr.sar a12 - wsr.intenable a13 // restore INTENABLE as it was on entry -#else - rsr.sar a12 -#endif - - movi a13, xtos_c_handler_table // &table - l32i a15, a1, UEXC_exccause // arg2: exccause - - s32i a12, a1, UEXC_sar - save_loops_mac16 a1, a12, a14 // save LOOP & MAC16 regs, if configured - - addx4 a12, a15, a13 // a12 = table[exccause] - l32i a12, a12, 0 // ... -#ifdef __XTENSA_CALL0_ABI__ - mov a2, a1 // arg1: exception parameters - mov a3, a15 // arg2: exccause - beqz a12, 1f // null handler => skip call - callx0 a12 // call C exception handler for this exception -#else - mov a14, a1 // arg1: exception parameters - // mov a15, a15 // arg2: exccause, already in a15 - beqz a12, 1f // null handler => skip call - callx12 a12 // call C exception handler for this exception -#endif -1: - // Now exit the handler. - - - // Restore special registers - - restore_loops_mac16 a1, a13, a14, a15 // restore LOOP & MAC16 regs, if configured - l32i a14, a1, UEXC_sar - - /* - * Disable interrupts while returning from the pseudo-CALL setup above, - * for the same reason they were disabled while doing the pseudo-CALL: - * this sequence restores SP such that it doesn't reflect the allocation - * of the exception stack frame, which we still need to return from - * the exception. - */ - -#if XCHAL_HAVE_INTERRUPTS - // Must disable interrupts via INTENABLE, because PS.INTLEVEL gets zeroed - // by any window exception exit, eg. the window underflow that may happen - // upon executing the RETW instruction. - // Also, must disable at XTOS_LOCKLEVEL, not just EXCM_LEVEL, because this - // code effectively manipulates virtual INTENABLE state up to the point - // INTENABLE is written in _xtos_return_from_exc. - // - rsilft a12, 1, XTOS_LOCKLEVEL // lockout - rsr.intenable a12 - //movi a13, ~XCHAL_EXCM_MASK - movi a13, ~XTOS_LOCKOUT_MASK // mask out low and medium priority levels, and high priority levels covered by - // XTOS_LOCKLEVEL if any, so we can run at PS.INTLEVEL=0 while manipulating INTENABLE - s32i a12, a1, UEXC_sar // (temporary holding place for INTENABLE value to restore after pseudo-CALL4 below) - and a13, a12, a13 // mask out selected interrupts - wsr.intenable a13 // disable all interrupts up to and including XTOS_LOCKLEVEL -#endif - wsr.sar a14 - - movi a0, _xtos_return_from_exc -#ifdef __XTENSA_CALL0_ABI__ - jx a0 -#else /* ! __XTENSA_CALL0_ABI__ */ - /* Now return from the pseudo-CALL from the interrupted code, to rotate - * our windows back... */ - - movi a13, 0xC0000000 - //movi a13, 3 - //slli a13, a13, 30 -# if XCHAL_HAVE_INTERRUPTS - rsync //NOT-ISA-DEFINED // wait for WSR to INTENABLE to complete before doing RETW - // (ie. before underflow exception exit) - // (not needed, because underflow exception entry does implicit ISYNC ?? - // but in case underflow not taken, WSR must complete before wsr to PS that lowers PS.INTLEVEL - // possibly below XTOS_LOCKLEVEL, in which RETW's jump is not sufficient sync, so a sync - // is needed but it can be placed just before WSR to PS -- but here is fine) -# endif - or a0, a0, a13 // set upper two bits - addx2 a0, a13, a0 // clear upper bit - retw -#endif /* ! __XTENSA_CALL0_ABI__ */ - - /* FIXME: what about _GeneralException ? */ - - .size xtos_c_wrapper_handler, . - xtos_c_wrapper_handler - - -#endif /* XCHAL_HAVE_XEA1 && XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/xea1/exc-return.S b/src/arch/xtensa/xtos/xea1/exc-return.S deleted file mode 100644 index 25bfa32b71ab..000000000000 --- a/src/arch/xtensa/xtos/xea1/exc-return.S +++ /dev/null @@ -1,123 +0,0 @@ -// xea1/exc-return.S - Shared exception/interrupt return code - -// Copyright (c) 2002-2016 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include <xtensa/config/specreg.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA1 && XCHAL_HAVE_EXCEPTIONS /* XEA1 always has exceptions */ - - .text - .align 4 - .global _xtos_return_from_exc -_xtos_return_from_exc: - -#ifdef __XTENSA_CALL0_ABI__ - - l32i a0, a1, UEXC_a0 // restore general registers, pc, ps - l32i a4, a1, UEXC_a4 - l32i a5, a1, UEXC_a5 - l32i a6, a1, UEXC_a6 - l32i a7, a1, UEXC_a7 - l32i a8, a1, UEXC_a8 - l32i a9, a1, UEXC_a9 - l32i a10, a1, UEXC_a10 - l32i a11, a1, UEXC_a11 - l32i a12, a1, UEXC_a12 - l32i a13, a1, UEXC_a13 - l32i a14, a1, UEXC_a14 - l32i a15, a1, UEXC_a15 - - l32i a2, a1, UEXC_pc - l32i a3, a1, UEXC_ps - wsr.epc1 a2 - wsr.ps a3 - - l32i a2, a1, UEXC_a2 - l32i a3, a1, UEXC_a3 - - rsync // wait for WSR to PS to complete - - addi a1, a1, ESF_TOTALSIZE // restore sp - - rfe - -#else /* ! __XTENSA_CALL0_ABI__ */ - - - // Here we rotated back by N registers, to the interrupted code's register window. - // NOTA: a2 and a3 might contain something useful, but we haven't determined - // what that might be yet (for now, a2 contains nested-C-func call-chain ptr). - - // NOTE: a5 still contains the exception window's exception stack frame pointer. - -# if XTOS_CNEST - s32i a2, a5, ESF_TOTALSIZE-20 // restore nested-C-func call-chain ptr -# endif - l32i a2, a5, UEXC_ps - l32i a3, a5, UEXC_pc - wsr.ps a2 // this sets INTLEVEL to 1; ... - -# if XCHAL_HAVE_INTERRUPTS - l32i a4, a5, UEXC_sar // load INTENABLE value that restores original vpri - l32i a2, a5, UEXC_a2 - rsync // wait for WSR to PS to complete - wsr.intenable a4 // update INTENABLE to restore original vpri (PS.INTLEVEL=1 here) - l32i a4, a5, UEXC_a4 -# else - l32i a2, a5, UEXC_a2 - l32i a4, a5, UEXC_a4 - rsync // wait for WSR to PS to complete -# endif - - /* FIXME: Enabling this here may break task-engine builds - * because task engines have exceptions (sort of), but they do - * not have the EPC_1 special register. XCHAL_HAVE_INTERRUPTS - * is incorrect for normal configs without interrupts but with - * exceptions (we still need to restore EPC_1). The correct - * solution is to define XCHAL_HAVE_EXCEPTIONS more strictly - * to mean something like "Have exceptions with - * user/kernel/double vectors" so that task engines are - * excluded. This would be a change to - * <xtensa/config/core.h>. */ - - wsr.epc1 a3 - // HERE: - // - we cannot get window overflows anymore -- we're NOT in a valid windowed context - // - low-priority interrupts are still disabled - - // NOTE: we don't restore EXCCAUSE or EXCVADDR, not needed. - - // Restore a3, a5: - l32i a3, a5, UEXC_a3 - l32i a5, a5, UEXC_a5 - - rfe_rfue - -#endif /* __XTENSA_CALL0_ABI__ */ - - .size _xtos_return_from_exc, . - _xtos_return_from_exc - -#endif /* XCHAL_HAVE_XEA1 && XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/xea1/int-lowpri-dispatcher.S b/src/arch/xtensa/xtos/xea1/int-lowpri-dispatcher.S deleted file mode 100644 index 681010b49965..000000000000 --- a/src/arch/xtensa/xtos/xea1/int-lowpri-dispatcher.S +++ /dev/null @@ -1,324 +0,0 @@ -// XEA1 - Level-one interrupt dispatcher (user vectored handler) - -// Copyright (c) 1999-2016 Tensilica 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 <sof/lib/memory.h> -#include <config.h> -#include <xtensa/coreasm.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA1 && XCHAL_HAVE_EXCEPTIONS && XCHAL_HAVE_INTERRUPTS - -#define _INTERRUPT_LEVEL 1 - - - // NOTE: something equivalent to the following vector is executed - // before entering this handler (see user-vector.S). -//_UserExceptionVector: -// addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. -// s32i a2, a1, UEXC_a2 -// s32i a3, a1, UEXC_a3 -// movi a3, xtos_exc_handler_table -// rsr.exccause a2 -// addx4 a2, a2, a3 -// l32i a2, a2, 0 -// s32i a4, a1, UEXC_a4 -// jx a2 // jump to cause-specific handler - - .global _need_user_vector_ // pull-in real user vector (tiny LSP) - - .text - .align 4 - .global _xtos_l1int_handler -_xtos_l1int_handler: - // HERE: a2, a3, a4 have been saved to exception stack frame allocated with a1 (sp). - - s32i a5, a1, UEXC_a5 // a5 will get clobbered by ENTRY after pseudo-CALL4 - // (a4..a15 spilled as needed; save if modified) - -#if HAVE_XSR - movi a2, PS_WOECALL4_ABI|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) - xsr.ps a2 - s32i a2, a1, UEXC_ps -#else - rsr.ps a2 - s32i a2, a1, UEXC_ps - movi a2, PS_WOECALL4_ABI|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) - wsr.ps a2 -#endif - rsync - - /* store pc */ - rsr.epc1 a2 - s32i a2, a1, UEXC_pc - - /* store rest of the registers */ - s32i a0, a1, UEXC_a0 - s32i a6, a1, UEXC_a6 - s32i a7, a1, UEXC_a7 - s32i a8, a1, UEXC_a8 - s32i a9, a1, UEXC_a9 - s32i a10, a1, UEXC_a10 - s32i a11, a1, UEXC_a11 - s32i a12, a1, UEXC_a12 - s32i a13, a1, UEXC_a13 - s32i a14, a1, UEXC_a14 - s32i a15, a1, UEXC_a15 - - /* store current sp */ - xtos_addr_percore a2, xtos_saved_sp - s32i a1, a2, 0 - - /* store current task sp */ - xtos_task_ctx_percore a2 - beqz a2, no_context - s32i a1, a2, TC_stack_pointer - -no_context: -# if XTOS_CNEST - l32i a2, a1, ESF_TOTALSIZE-20 // save nested-C-func call-chain ptr -# endif - addi a1, a1, ESF_TOTALSIZE -# if XTOS_DEBUG_PC - rsr.epc1 a4 // [for debug] get return PC - movi a5, 0xC0000000 // [for debug] setup call size... - or a4, a5, a4 // [for debug] set upper two bits of return PC - addx2 a4, a5, a4 // [for debug] clear upper bit -# else - movi a4, 0 /* terminate stack frames, overflow check */ -# endif - _entry a1, ESF_TOTALSIZE - -/* Reset the interrupt level to xtos locklevel (lvl 6 on most systems) */ - - rsil a15, XTOS_LOCKLEVEL - -/* Get bit list of pending interrupts at the current interrupt priority level. - * If bit list is empty, interrupt is spurious (can happen if a - * genuine interrupt brings control this direction, but the interrupt - * goes away before we read the INTERRUPT register). Also save off - * sar, loops, mac16 registers and coprocessors. */ - -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp0 - xchal_cp0_store a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp1 - xchal_cp1_store a11, a12, a13, a14, a15 -#endif -#endif - rsr.interrupt a15 - rsr.intenable a12 - movi a13, XCHAL_INTLEVEL1_MASK - and a15, a15, a12 - and a15, a15, a13 - rsr.sar a14 - s32i a14, a1, UEXC_sar - save_loops_mac16 a1, a13, a14 - - /* switch to interrupt stack */ - xtos_int_stack_addr_percore a13, _INTERRUPT_LEVEL, xtos_stack_for_interrupt - s32i a1, a13, 0 - addi a1, a13, SOF_STACK_SIZE - - _beqz a15, LABEL(spurious,int) - - /* set stack base and size for interrupt context */ - xtos_addr_percore a11, xtos_interrupt_ctx - s32i a13, a11, TC_stack_base - movi a13, SOF_STACK_SIZE - s32i a13, a11, TC_stack_size - - /* save task context */ - xtos_task_ctx_percore a13 - xtos_store_percore a13, a14, xtos_saved_ctx - - /* set interrupt task context */ - xtos_task_ctx_store_percore a11, a14 - - xtos_on_wakeup - -/* Loop to handle all pending interrupts. */ - -LABEL(.L1,_loop0): - neg a12, a15 - and a12, a12, a15 - wsr.intclear a12 // clear if edge-trig or s/w or wr/err (else no effect) -#if CONFIG_SMP - xtos_addr_percore a13, xtos_interrupt_table -#else - movi a13, xtos_interrupt_table -#endif - find_ms_setbit a15, a12, a14, 0 - mapint a15 - addx8 a12, a15, a13 - l32i a13, a12, XIE_HANDLER - l32i a14, a12, XIE_ARG - mov a15, a1 - callx12 a13 - - rsr.interrupt a15 - rsr.intenable a12 - movi a13, XCHAL_INTLEVEL1_MASK - and a15, a15, a12 - and a15, a15, a13 - _bnez a15, LABEL(.L1,_loop0) - -/* Restore everything, and return. */ - - /* restore task context if needed */ - xtos_task_ctx_percore a11 - xtos_addr_percore a12, xtos_interrupt_ctx - bne a11, a12, restore_cp - xtos_addr_percore a12, xtos_saved_ctx - xtos_task_ctx_store_percore a12, a11 - -restore_cp: -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - xtos_task_ctx_percore a11 - beqz a11, no_context_2 - l32i a11, a11, TC_stack_pointer - addi a11, a11, UEXC_cp0 - xchal_cp0_load a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - xtos_task_ctx_percore a11 - beqz a11, no_context_2 - l32i a11, a11, TC_stack_pointer - addi a11, a11, UEXC_cp1 - xchal_cp1_load a11, a12, a13, a14, a15 -#endif -#endif - -no_context_2: - restore_loops_mac16 a1, a13, a14, a15 - l32i a14, a1, UEXC_sar -LABEL(spurious,int): - -#if XCHAL_HAVE_EXCLUSIVE - // Clear exclusive monitors. - clrex -#endif - - movi a0, LABEL(return,from_exc) - movi a13, 0xC0000000 - wsr.sar a14 - or a0, a0, a13 - addx2 a0, a13, a0 -# if _INTERRUPT_LEVEL < XCHAL_EXCM_LEVEL -/* Raise the interrupt mask before - * returning to avoid a race condition where we deallocate the - * exception stack frame but still have more register values to - * restore from it. */ - rsil a14, XCHAL_EXCM_LEVEL -# endif - retw -LABEL(return,from_exc): - /* a5 contains interrupt stack pointer */ - addi a5, a5, -SOF_STACK_SIZE - l32i a5, a5, 0 - -# if XTOS_CNEST - s32i a2, a5, ESF_TOTALSIZE-20 // restore nested-C-func call-chain ptr -# endif - - /* store sp after returning from handler */ - s32i a1, a5, UEXC_a1 - -restore: - /* load registers for window spill */ - l32i a4, a5, UEXC_a4 - l32i a6, a5, UEXC_a6 - l32i a7, a5, UEXC_a7 - l32i a8, a5, UEXC_a8 - l32i a9, a5, UEXC_a9 - l32i a10, a5, UEXC_a10 - l32i a11, a5, UEXC_a11 - l32i a12, a5, UEXC_a12 - l32i a13, a5, UEXC_a13 - l32i a14, a5, UEXC_a14 - - /* check if switch is needed */ - xtos_addr_percore a2, xtos_saved_sp - xtos_task_ctx_percore a1 - beqz a1, noSwitch - l32i a1, a1, TC_stack_pointer - l32i a0, a2, 0 - beq a0, a1, noSwitch - -doSwitch: - /* store new task sp */ - s32i a1, a2, 0 - - /* restore sp of task being preempted */ - l32i a1, a5, UEXC_a1 - - /* spill register windows to the stack */ - rsr.ps a2 - movi a3, PS_WOE_MASK - xor a2, a2, a3 - wsr.ps a2 - - call0 xthal_window_spill_nw - - /* restore previous ps */ - rsr.ps a2 - movi a3, PS_WOE_MASK - or a2, a2, a3 - wsr.ps a2 - - /* change stack */ - xtos_addr_percore a5, xtos_saved_sp - l32i a5, a5, 0 - j restore - -noSwitch: - /* restore ps and pc */ - l32i a0, a5, UEXC_ps - wsr.ps a0 - rsync - l32i a0, a5, UEXC_pc - wsr.epc1 a0 - - /* restore sar, loops and mac16 registers */ - l32i a0, a5, UEXC_sar - wsr.sar a0 - restore_loops_mac16 a5, a0, a1, a2 - - /* restore rest of the registers */ - l32i a0, a5, UEXC_a0 - l32i a1, a5, UEXC_a1 - l32i a2, a5, UEXC_a2 - l32i a3, a5, UEXC_a3 - l32i a15, a5, UEXC_a15 - l32i a5, a5, UEXC_a5 - rfe - - /* FIXME: what about _LevelOneInterrupt ? */ - .size _xtos_l1int_handler, . - _xtos_l1int_handler - -#endif /* XCHAL_HAVE_XEA1 && XCHAL_HAVE_EXCEPTIONS && XCHAL_HAVE_INTERRUPTS */ diff --git a/src/arch/xtensa/xtos/xea1/intlevel-restore.S b/src/arch/xtensa/xtos/xea1/intlevel-restore.S deleted file mode 100644 index 69d54a86e965..000000000000 --- a/src/arch/xtensa/xtos/xea1/intlevel-restore.S +++ /dev/null @@ -1,75 +0,0 @@ -// xea1/intlevel-restore.S - Interrupt related assembler code - _xtos_restore_intlevel - -// Copyright (c) 2004-2016 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include <xtensa/config/specreg.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA1 - -/*************************************************************************** - * void _xtos_restore_intlevel(unsigned restoreval); - * - * _xtos_restore_intlevel() restores the current interrupt level - * according to a value returned by _xtos_set_intlevel() or - * _xtos_set_min_intlevel() (or one of the corresponding macros). - * - * NOTE: In XEA1, this function is implemented identically - * to _xtos_set_vpri(). - */ - -/*************************************************************************** - * _xtos_set_vpri() is used to set the current virtual priority from C code; - * it can be called from the application or from a C interrupt handler. - */ - - .text - .global _xtos_restore_intlevel - .type _xtos_restore_intlevel,@function - .global _xtos_set_vpri - .type _xtos_set_vpri,@function - .align 4 -_xtos_set_vpri: -_xtos_restore_intlevel: - abi_entry -#if XCHAL_HAVE_INTERRUPTS && XTOS_VIRTUAL_INTENABLE - mov a3, a2 -#if CONFIG_SMP - xtos_addr_percore a4, xtos_intstruct -#else - movi a4, _xtos_intstruct -#endif - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - l32i a2, a4, XTOS_VPRI_ENABLED_OFS // return old xtos_vpri_enabled (current vpri) - l32i a5, a4, XTOS_ENABLED_OFS // a3 = xtos_enabled - s32i a3, a4, XTOS_VPRI_ENABLED_OFS // set new xtos_vpri_enabled (current vpri) - and a5, a5, a3 // a5 = xtos_enabled & xtos_vpri_enabled - wsr.intenable a5 - xtos_unlock a7 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - .size _xtos_set_vpri, . - _xtos_set_vpri - -#endif /* XEA1 */ - diff --git a/src/arch/xtensa/xtos/xea1/intlevel-set.S b/src/arch/xtensa/xtos/xea1/intlevel-set.S deleted file mode 100644 index b015f03ec73a..000000000000 --- a/src/arch/xtensa/xtos/xea1/intlevel-set.S +++ /dev/null @@ -1,76 +0,0 @@ -// xea1/intlevel-set.S - Interrupt related assembler code - _xtos_set_intlevel - -// Copyright (c) 2004-2016 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include <xtensa/config/specreg.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA1 - - -/*************************************************************************** - * unsigned _xtos_set_intlevel(int intlevel); - * - * _xtos_set_intlevel() is used to set the current priority from C code; - * it can be called from the application or from a C interrupt handler. - * - * NOTE: This version allows the 'intlevel' parameter to be computed - * at run-time, and thus is longer. It is much more efficient, and - * highly recommented, to use the XTOS_SET_INTLEVEL(intlevel) macro instead - * (which requires a constant intlevel). - */ - - .text - .align 4 - .global _xtos_set_intlevel - .type _xtos_set_intlevel,@function -_xtos_set_intlevel: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - /* In XEA1, we have to rely on INTENABLE register virtualization: */ - movi a4, Xthal_intlevel_andbelow_mask - extui a3, a2, 0, 4 // keep only INTLEVEL bits of parameter - addx4 a5, a3, a4 // index mask to use - l32i a3, a5, 0 // get mask of interrupts at requested intlevel and below - movi a5, -1 // all 1's -#if CONFIG_SMP - xtos_addr_percore a4, xtos_intstruct -#else - movi a4, _xtos_intstruct -#endif - xor a3, a3, a5 // mask of interrupts at intlevels above the requested one (to enable) - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - l32i a2, a4, XTOS_VPRI_ENABLED_OFS // return old xtos_vpri_enabled (current vpri) - l32i a5, a4, XTOS_ENABLED_OFS // a5 = xtos_enabled - s32i a3, a4, XTOS_VPRI_ENABLED_OFS // set new xtos_vpri_enabled (current vpri) - and a5, a5, a3 // a5 = xtos_enabled & xtos_vpri_enabled - wsr.intenable a5 - xtos_unlock a7 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - - .size _xtos_set_intlevel, . - _xtos_set_intlevel - -#endif /* XEA1 */ - diff --git a/src/arch/xtensa/xtos/xea1/intlevel-setmin.S b/src/arch/xtensa/xtos/xea1/intlevel-setmin.S deleted file mode 100644 index f48a049894d2..000000000000 --- a/src/arch/xtensa/xtos/xea1/intlevel-setmin.S +++ /dev/null @@ -1,79 +0,0 @@ -// xea1/intlevel-setmin.S - Interrupt related assembler code - _xtos_set_min_intlevel - -// Copyright (c) 2004-2016 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include <xtensa/config/specreg.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA1 - - -/*************************************************************************** - * unsigned _xtos_set_min_intlevel(int intlevel); - * - * _xtos_set_min_intlevel() is identical to _xtos_set_intlevel() except - * that it will not lower the current interrupt level. Instead, - * it ensures that the current interrupt level is at least as high - * as specified. - * - * NOTE: This version allows the 'intlevel' parameter to be computed - * at run-time, and thus is longer. It is much more efficient, and - * highly recommented, to use the XTOS_SET_MIN_INTLEVEL(intlevel) macro instead - * (which requires a constant intlevel). - */ - - .text - .align 4 - .global _xtos_set_min_intlevel - .type _xtos_set_min_intlevel,@function -_xtos_set_min_intlevel: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - /* In XEA1, we have to rely on INTENABLE register virtualization: */ - movi a4, Xthal_intlevel_andbelow_mask - extui a3, a2, 0, 4 // keep only INTLEVEL bits of parameter - addx4 a5, a3, a4 // index mask to use - l32i a3, a5, 0 // get mask of interrupts at requested intlevel and below - movi a5, -1 // all 1's -#if CONFIG_SMP - xtos_addr_percore a4, xtos_intstruct -#else - movi a4, _xtos_intstruct -#endif - xor a3, a3, a5 // mask of interrupts at intlevels above the requested one (to enable) - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - l32i a2, a4, XTOS_VPRI_ENABLED_OFS // return old xtos_vpri_enabled (current vpri) - l32i a5, a4, XTOS_ENABLED_OFS // a5 = xtos_enabled - and a3, a3, a2 // make sure we don't enable any new interrupts - s32i a3, a4, XTOS_VPRI_ENABLED_OFS // set new xtos_vpri_enabled (current vpri) - and a5, a5, a3 // a5 = xtos_enabled & xtos_vpri_enabled - wsr.intenable a5 - xtos_unlock a7 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - - .size _xtos_set_min_intlevel, . - _xtos_set_min_intlevel - -#endif /* XEA1 */ - diff --git a/src/arch/xtensa/xtos/xea1/window-vectors.S b/src/arch/xtensa/xtos/xea1/window-vectors.S deleted file mode 100644 index 1670ed988429..000000000000 --- a/src/arch/xtensa/xtos/xea1/window-vectors.S +++ /dev/null @@ -1,355 +0,0 @@ -// window-vectors-xea1.S - Register Window Overflow/Underflow Handlers for XEA1 -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/xea1/window-vectors.S#1 $ - -// Copyright (c) 1999-2013 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/xtruntime-frames.h> - -#if XCHAL_HAVE_XEA1 -#if XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) - -# ifndef NO_SECTION_DIRECTIVES -// Exports -.global _WindowOverflow4 -.global _WindowUnderflow4 -.global _WindowOverflow8 -.global _WindowUnderflow8 -.global _WindowOverflow12 -.global _WindowUnderflow12 -.global _xtos_alloca_handler - - // Note: the current window exception vectors do not generate any - // literals. Hence the literal_prefix directive is not necessary. - // Specifying it "just in case" creates an empty section (named - // ".WindowVectors.literal") which can in some cases cause linking - // problems (the linker scripts don't place it anywhere). - // So leave it commented out: - // - //.begin literal_prefix .WindowVectors - - .section .WindowVectors.text, "ax" -# endif - - -// -// GENERAL NOTES: -// -// These window exception handlers need not be modified. -// They are specific to the windowed call ABI only. -// -// Underflow Handlers: -// -// The underflow handler for returning from call[i+1] to call[i] -// must preserve all the registers from call[i+1]'s window. -// In particular, a0 and a1 must be preserved because the RETW instruction -// will be reexecuted (and may even underflow again if an intervening -// exception has flushed call[i]'s registers). -// Registers a2 and up may contain return values. -// -// The caller could also potentially assume that the callee's a0 and a1 -// (its own a4&a5 if call4, a8&a9 if call8, a12&a13 if call12) -// are correct for whatever reason (not a clean thing to do in general, -// but if it's possible, unless the ABI explicitly prohibits it, -// it will eventually be done :) -- whether the the ABI needs to -// prohibit this is a different question). -// -// Timing of Handlers: -// -// Here is an overview of the overhead of taking a window exception, -// ie. the number of additional cycles taken relative to case where -// an exception is not taken. -// NOTE: these numbers do not take into account any cache misses, -// write buffer stalls, or other external stalls, if they occur. -// The totals consist of 5 cycles to enter the handler (or 6 or 7 -// for optional longer pipelines in Xtensa LX), the number of instructions -// and interlocks (2nd and 3rd columns below), and 2 cycles jump delay -// on return (3 cycles for optional longer I-side pipeline in Xtensa LX): -// -// Instruction+bubbles Totals (5-stage) -// XEA1 XEA2 XEA1 XEA2 -// Overflow-4 7 5 14 12 -// Overflow-8 14 10 21 17 -// Overflow-12 18 14 25 21 -// Underflow-4 6 5 13 12 -// Underflow-8 14 10 21 17 -// Underflow-12 18 14 25 21 -// -// Underflow-8 15 12 25 22 (7-stage; could be made 1 less) -// Underflow-12 19 16 29 26 (7-stage; could be made 1 less) - -#ifndef WINDOW_BASE_VECOFS -#define WINDOW_BASE_VECOFS XCHAL_WINDOW_OF4_VECOFS -#endif - - -// 4-Register Window Overflow Vector (Handler) -// -// Invoked if a call[i] referenced a register (a4-a15) -// that contains data from ancestor call[j]; -// call[j] had done a call4 to call[j+1]. -// On entry here: -// window rotated to call[j] start point; -// a0-a3 are registers to be saved; -// a4-a15 must be preserved; -// a5 is call[j+1]'s stack pointer. - - .org XCHAL_WINDOW_OF4_VECOFS - WINDOW_BASE_VECOFS -_WindowOverflow4: - addi a5, a5, -16 // to make store offsets positive - s32i a0, a5, 0 // save a0 to call[j+1]'s stack frame - s32i a1, a5, 4 // save a1 to call[j+1]'s stack frame - s32i a2, a5, 8 // save a2 to call[j+1]'s stack frame - s32i a3, a5, 12 // save a3 to call[j+1]'s stack frame - addi a5, a5, 16 // restore a5 - rfwo // rotates back to call[i] position - - .size _WindowOverflow4, . - _WindowOverflow4 - - -// ALLOCA exception handler -// -// NOTE: The alloca exception handler is squeezed in between the window exception -// handlers in order to save space, and also to allow short-range jumps to the -// window underflow handlers (see below for why). Because of the limited space in -// between the window handlers, this function is split into two to fit. -// -// Code written to the windowed ABI must use the MOVSP instruction to modify -// the stack pointer (except for startup code, which doesn't have a caller). -// The compiler uses MOVSP to allocate very large or variable size stack frames. -// MOVSP guarantees that the caller frame's a0-a3 registers, stored below the -// stack pointer, are moved atomically with respect to interrupts and exceptions -// to satisfy windowed ABI requirements. When user code executes the MOVSP -// instruction and the caller frame is on the stack rather than in the register -// file, the processor takes an ALLOCA exception. -// -// The XTOS user exception dispatcher allocates an exception frame on the -// stack and saves a2-a4 into that frame before calling us. So we need to -// restore those registers and deallocate the stack frame before jumping -// to the window underflow handler - which will restore the spilled registers -// back into the register file. -// The fact the alloca exception was taken means the registers associated with -// the base-save area have been spilled and will be restored by the underflow -// handler, so those 4 registers are available for scratch. - - .align 4 - -_xtos_alloca_handler: - - l32i a2, a1, UEXC_a2 // restore a2-a4 and deallocate frame - l32i a3, a1, UEXC_a3 - l32i a4, a1, UEXC_a4 - addi a1, a1, ESF_TOTALSIZE - wsr.excsave1 a0 // save a0 - rsr.windowbase a0 // grab WINDOWBASE before rotw changes it - rotw -1 // WINDOWBASE goes to a4, new a0-a3 are scratch - rsr.ps a2 - extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS - xor a3, a3, a4 // bits changed from old to current windowbase - j _xtos_alloca_2 // not enough room here... - - .size _xtos_alloca_handler, . - _xtos_alloca_handler - - -// 4-Register Window Underflow Vector (Handler) -// -// Invoked by RETW returning from call[i+1] to call[i] -// where call[i]'s registers must be reloaded (not live in ARs); -// call[i] had done a call4 to call[i+1]. -// On entry here: -// window rotated to call[i] start point; -// a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; -// a4-a15 must be preserved (they are call[i+1].reg[0..11]); -// a5 is call[i+1]'s stack pointer. - - .org XCHAL_WINDOW_UF4_VECOFS - WINDOW_BASE_VECOFS -_WindowUnderflow4: - addi a3, a5, -16 // to make load offsets positive - l32i a0, a3, 0 // restore a0 from call[i+1]'s stack frame - l32i a1, a3, 4 // restore a1 from call[i+1]'s stack frame - l32i a2, a3, 8 // restore a2 from call[i+1]'s stack frame - l32i a3, a3, 12 // restore a3 from call[i+1]'s stack frame - rfwu - - .size _WindowUnderflow4, . - _WindowUnderflow4 - - -// This is the second part of the alloca handler. - - .align 4 - -_xtos_alloca_2: - - rsr.excsave1 a4 // restore original a0 (now in a4) - slli a3, a3, XCHAL_PS_OWB_SHIFT - xor a2, a2, a3 // flip changed bits in old window base - wsr.ps a2 // update PS.OWB to new window base - rsync - _bbci.l a4, 31, _WindowUnderflow4 - rotw -1 // original a0 goes to a8 - _bbci.l a8, 30, _WindowUnderflow8 - rotw -1 - j _WindowUnderflow12 - - .size _xtos_alloca_2, . - _xtos_alloca_2 - -// 8-Register Window Overflow Vector (Handler) -// -// Invoked if a call[i] referenced a register (a4-a15) -// that contains data from ancestor call[j]; -// call[j] had done a call8 to call[j+1]. -// On entry here: -// window rotated to call[j] start point; -// a0-a7 are registers to be saved; -// a8-a15 must be preserved; -// a9 is call[j+1]'s stack pointer. - - .org XCHAL_WINDOW_OF8_VECOFS - WINDOW_BASE_VECOFS -_WindowOverflow8: - addi a9, a9, -16 // to make store offsets positive - s32i a0, a9, 0 // save a0 to call[j+1]'s stack frame - addi a0, a1, -16 // a0 <- call[j-1]'s sp - s32i a1, a9, 4 // save a1 to call[j+1]'s stack frame - l32i a0, a0, 4 // (used to find end of call[j]'s frame) - s32i a2, a9, 8 // save a2 to call[j+1]'s stack frame - s32i a3, a9, 12 // save a3 to call[j+1]'s stack frame - addi a9, a9, 16 // restore a9 - addi a0, a0, -32 // to make load offsets positive - s32i a4, a0, 0 // save a4 to call[j]'s stack frame - s32i a5, a0, 4 // save a5 to call[j]'s stack frame - s32i a6, a0, 8 // save a6 to call[j]'s stack frame - s32i a7, a0, 12 // save a7 to call[j]'s stack frame - rfwo // rotates back to call[i] position - - .size _WindowOverflow8, . - _WindowOverflow8 - - -// 8-Register Window Underflow Vector (Handler) -// -// Invoked by RETW returning from call[i+1] to call[i] -// where call[i]'s registers must be reloaded (not live in ARs); -// call[i] had done a call8 to call[i+1]. -// On entry here: -// window rotated to call[i] start point; -// a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; -// a8-a15 must be preserved (they are call[i+1].reg[0..7]); -// a9 is call[i+1]'s stack pointer. - - .org XCHAL_WINDOW_UF8_VECOFS - WINDOW_BASE_VECOFS -_WindowUnderflow8: - addi a9, a9, -16 // to make load offsets positive - l32i a0, a9, 0 // restore a0 from call[i+1]'s stack frame - l32i a1, a9, 4 // restore a1 from call[i+1]'s stack frame - l32i a2, a9, 8 // restore a2 from call[i+1]'s stack frame - addi a7, a1, -16 // a7 <- call[i-1]'s sp - l32i a7, a7, 4 // (used to find end of call[i]'s frame) - l32i a3, a9, 12 // restore a3 from call[i+1]'s stack frame - addi a9, a9, 16 // restore a9 - addi a7, a7, -32 // to make load offsets positive - l32i a4, a7, 0 // restore a4 from call[i]'s stack frame - l32i a5, a7, 4 // restore a5 from call[i]'s stack frame - l32i a6, a7, 8 // restore a6 from call[i]'s stack frame - l32i a7, a7, 12 // restore a7 from call[i]'s stack frame - rfwu - - .size _WindowUnderflow8, . - _WindowUnderflow8 - - -// 12-Register Window Overflow Vector (Handler) -// -// Invoked if a call[i] referenced a register (a4-a15) -// that contains data from ancestor call[j]; -// call[j] had done a call12 to call[j+1]. -// On entry here: -// window rotated to call[j] start point; -// a0-a11 are registers to be saved; -// a12-a15 must be preserved; -// a13 is call[j+1]'s stack pointer. - - .org XCHAL_WINDOW_OF12_VECOFS - WINDOW_BASE_VECOFS -_WindowOverflow12: - addi a13, a13, -16 // to make store offsets positive - s32i a0, a13, 0 // save a0 to call[j+1]'s stack frame - addi a0, a1, -16 // a0 <- call[j-1]'s sp - s32i a1, a13, 4 // save a1 to call[j+1]'s stack frame - l32i a0, a0, 4 // (used to find end of call[j]'s frame) - s32i a2, a13, 8 // save a2 to call[j+1]'s stack frame - s32i a3, a13, 12 // save a3 to call[j+1]'s stack frame - addi a13, a13, 16 // restore a13 - addi a0, a0, -48 // to make load offsets positive - s32i a4, a0, 0 // save a4 to end of call[j]'s stack frame - s32i a5, a0, 4 // save a5 to end of call[j]'s stack frame - s32i a6, a0, 8 // save a6 to end of call[j]'s stack frame - s32i a7, a0, 12 // save a7 to end of call[j]'s stack frame - s32i a8, a0, 16 // save a8 to end of call[j]'s stack frame - s32i a9, a0, 20 // save a9 to end of call[j]'s stack frame - s32i a10, a0, 24 // save a10 to end of call[j]'s stack frame - s32i a11, a0, 28 // save a11 to end of call[j]'s stack frame - rfwo // rotates back to call[i] position - - .size _WindowOverflow12, . - _WindowOverflow12 - - -// 12-Register Window Underflow Vector (Handler) -// -// Invoked by RETW returning from call[i+1] to call[i] -// where call[i]'s registers must be reloaded (not live in ARs); -// call[i] had done a call12 to call[i+1]. -// On entry here: -// window rotated to call[i] start point; -// a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; -// a12-a15 must be preserved (they are call[i+1].reg[0..3]); -// a13 is call[i+1]'s stack pointer. - - .org XCHAL_WINDOW_UF12_VECOFS - WINDOW_BASE_VECOFS -_WindowUnderflow12: - addi a13, a13, -16 // to make load offsets positive - l32i a0, a13, 0 // restore a0 from call[i+1]'s stack frame - l32i a1, a13, 4 // restore a1 from call[i+1]'s stack frame - l32i a2, a13, 8 // restore a2 from call[i+1]'s stack frame - addi a11, a1, -16 // a11 <- call[i-1]'s sp - l32i a11, a11, 4 // (used to find end of call[i]'s frame) - l32i a3, a13, 12 // restore a3 from call[i+1]'s stack frame - addi a13, a13, 16 // restore a13 - addi a11, a11, -48 // to make load offsets positive - l32i a4, a11, 0 // restore a4 from end of call[i]'s stack frame - l32i a5, a11, 4 // restore a5 from end of call[i]'s stack frame - l32i a6, a11, 8 // restore a6 from end of call[i]'s stack frame - l32i a7, a11, 12 // restore a7 from end of call[i]'s stack frame - l32i a8, a11, 16 // restore a8 from end of call[i]'s stack frame - l32i a9, a11, 20 // restore a9 from end of call[i]'s stack frame - l32i a10, a11, 24 // restore a10 from end of call[i]'s stack frame - l32i a11, a11, 28 // restore a11 from end of call[i]'s stack frame - rfwu - - .size _WindowUnderflow12, . - _WindowUnderflow12 - - -# ifndef NO_SECTION_DIRECTIVES - //.end literal_prefix - .text -# endif - - -#endif /* XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) */ -#endif /* XCHAL_HAVE_XEA1 */ - diff --git a/src/arch/xtensa/xtos/xea2/exc-c-wrapper-handler.S b/src/arch/xtensa/xtos/xea2/exc-c-wrapper-handler.S deleted file mode 100644 index 08beb65b6b3a..000000000000 --- a/src/arch/xtensa/xtos/xea2/exc-c-wrapper-handler.S +++ /dev/null @@ -1,361 +0,0 @@ -// exc-c-wrapper-handler.S - General Exception Handler that Dispatches C Handlers - -// Copyright (c) 2002-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 <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA2 && XCHAL_HAVE_EXCEPTIONS - - -/* - * This assembly-level handler causes the associated exception (usually causes 12-15) - * to be handled as if it were exception cause 3 (load/store error exception). - * This provides forward-compatibility with a possible future split of the - * load/store error cause into multiple more specific causes. - */ - .align 4 - .global xtos_cause3_handler -xtos_cause3_handler: - movi a2, EXCCAUSE_LOAD_STORE_ERROR - j xtos_c_wrapper_handler - .size xtos_cause3_handler, . - xtos_cause3_handler - - - .align 4 -.Lhi: addi a2, a2, -XCHAL_EXCM_LEVEL - add a2, a2, a3 - j .Lps - - -/* - * This is the general exception assembly-level handler that dispatches C handlers. - */ - .align 4 - .global xtos_c_wrapper_handler -xtos_c_wrapper_handler: -#ifdef __XTENSA_CALL0_ABI__ - // Redundantly de-allocate and re-allocate stack, so that GDB prologue - // analysis picks up the allocate part, and figures out how to traceback - // through the call stack through the exception. - addi a1, a1, ESF_TOTALSIZE // de-allocate stack frame (FIXME is it safe) -.global xtos_c_wrapper_dispatch -xtos_c_wrapper_dispatch: - // GDB starts analyzing prologue after most recent global symbol, so here: - addi a1, a1, -ESF_TOTALSIZE // re-allocate stack frame -#endif - - // HERE: a2, a3, a4 have been saved to exception stack frame allocated with a1 (sp). - // a2 contains EXCCAUSE. - s32i a5, a1, UEXC_a5 // a5 will get clobbered by ENTRY after the pseudo-CALL4 - // (a4..a15 spilled as needed; save if modified) - - //NOTA: Possible future improvement: - // keep interrupts disabled until we get into the handler, such that - // we don't have to save other critical state such as EXCVADDR here. - //rsr.excvaddr a3 - s32i a2, a1, UEXC_exccause - //s32i a3, a1, UEXC_excvaddr - - // Set PS fields: - // EXCM = 0 - // WOE = __XTENSA_CALL0_ABI__ ? 0 : 1 - // UM = 1 - // INTLEVEL = MIN(INTLEVEL,EXCM_LEVEL) - // CALLINC = __XTENSA_CALL0_ABI__ ? 0 : 1 - // OWB = 0 (really, a dont care if !__XTENSA_CALL0_ABI__) - - rsr.ps a3 - movi a2, PS_WOECALL4_ABI|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) // CALL4 emulation - s32i a3, a1, UEXC_ps - extui a3, a3, 0, 4 // extract PS.INTLEVEL - bgeui a3, XCHAL_EXCM_LEVEL+1, .Lhi // at PS.INTLEVEL > EXCM_LEVEL ? -.Lps: rsr.epc1 a3 - wsr.ps a2 - - // HERE: window overflows enabled, but NOT SAFE because we're not quite - // in a valid windowed context (haven't restored a1 yet...); - // so don't cause any (keep to a0..a3) until we've saved critical state and restored a1: - - // NOTE: MUST SAVE EPC1 before causing any overflows, because overflows corrupt EPC1. - s32i a3, a1, UEXC_pc - -#ifdef __XTENSA_CALL0_ABI__ - - s32i a0, a1, UEXC_a0 // save the rest of the registers - s32i a6, a1, UEXC_a6 - s32i a7, a1, UEXC_a7 - s32i a8, a1, UEXC_a8 - s32i a9, a1, UEXC_a9 - s32i a10, a1, UEXC_a10 - s32i a11, a1, UEXC_a11 - s32i a12, a1, UEXC_a12 - s32i a13, a1, UEXC_a13 - s32i a14, a1, UEXC_a14 - s32i a15, a1, UEXC_a15 -# if XTOS_DEBUG_PC - // TODO: setup return PC for call traceback through interrupt dispatch -# endif - - rsync // wait for WSR to PS to complete - -#else /* ! __XTENSA_CALL0_ABI__ */ - -# if XTOS_CNEST - l32i a2, a1, ESF_TOTALSIZE-20 // save nested-C-func call-chain ptr -# endif - addi a1, a1, ESF_TOTALSIZE // restore sp (dealloc ESF) for sane stack again - rsync // wait for WSR to PS to complete - - /* HERE: we can SAFELY get window overflows. - * - * From here, registers a4..a15 automatically get spilled if needed. - * They become a0..a11 after the ENTRY instruction. - * Currently, we don't check whether or not these registers - * get spilled, so we must save and restore any that we - * modify. We've already saved a4 and a5 - * which we modify as part of the pseudo-CALL. - * - * IMPLEMENTATION NOTE: - * - * The pseudo-CALL below effectively saves registers a2..a3 so - * that they are available again after the corresponding - * RETW when returning from the exception handling. We - * could choose to put something like EPC1 or PS in - * there, so they're available more quickly when - * restoring. HOWEVER, exception handlers may wish to - * change such values, or anything on the exception stack - * frame, and expect these to be restored as modified. - * - * NOTA: future: figure out what's the best thing to put - * in a2 and a3. (candidate: a4 and a5 below; but what - * if exception handler manipulates ARs, as in a syscall - * handler.... oh well) - * - * - * Now do the pseudo-CALL. - * Make it look as if the code that got the exception made a - * CALL4 to the exception handling code. (We call - * this the "pseudo-CALL".) - * - * This pseudo-CALL is important and done this way: - * - * 1. There are only three ways to safely update the stack pointer - * in the windowed ABI, such that window exceptions work correctly: - * (a) spill all live windows to stack then switch to a new stack - * (or, save the entire address register file and window - * registers, which is likely even more expensive) - * (b) use MOVSP (or equivalent) - * (c) use ENTRY/RETW - * Doing (a) is excessively expensive, and doing (b) here requires - * copying 16 bytes back and forth which is also time-consuming; - * whereas (c) is very efficient, so that's what we do here. - * - * 2. Normally we cannot do a pseudo-CALL8 or CALL12 here. - * According to the - * windowed ABI, a function must allocate enough space - * for the largest call that it makes. However, the - * pseudo-CALL is executed in the context of the - * function that happened to be executing at the time - * the interrupt was taken, and that function might or - * might not have allocated enough stack space for a - * CALL8 or a CALL12. If we try doing a pseudo-CALL8 - * or -CALL12 here, we corrupt the stack if the - * interrupted function happened to not have allocated - * space for such a call. - * - * 3. We set the return PC, but it's not strictly - * necessary for proper operation. It does make - * debugging, ie. stack tracebacks, much nicer if it - * can point to the interrupted code (not always - * possible, eg. if interrupted code is in a different - * GB than the interrupt handling code, which is - * unlikely in a system without protection where - * interrupt handlers and general application code are - * typically linked together). - * - * IMPORTANT: Interrupts must stay disabled while doing the pseudo-CALL, - * or at least until after the ENTRY instruction, because SP has been - * restored to its original value that does not reflect the exception - * stack frame's allocation. An interrupt taken here would - * corrupt the exception stack frame (ie. allocate another over it). - * (High priority interrupts can remain enabled, they save and restore - * all of their state and use their own stack or save area.) - * For the same reason, we mustn't get any exceptions in this code - * (other than window exceptions where noted) until ENTRY is done. - */ - - // HERE: may get a single window overflow (caused by the following instruction). - -# if XTOS_DEBUG_PC - movi a4, 0xC0000000 // [for debug] for return PC computation below - or a3, a4, a3 // [for debug] set upper two bits of return PC - addx2 a4, a4, a3 // [for debug] clear upper bit -# else - movi a4, 0 // entry cannot cause overflow, cause it here -# endif - - _entry a1, ESF_TOTALSIZE // as if after a CALL4 (PS.CALLINC set to 1 above) - - /* - * The above ENTRY instruction does a number of things: - * - * 1. Because we're emulating CALL4, the ENTRY rotates windows - * forward by 4 registers (as per 'ROTW +1'), so that - * a4-a15 became a0-a11. So now: a0-a11 are part of - * the interrupted context to be preserved. a0-a1 - * were already saved above when they were a4-a5. - * a12-a15 are free to use as they're NOT part of the - * interrupted context. We don't need to save/restore - * them, and they will get spilled if needed. - * - * 2. Updates SP (new a1), allocating the exception stack - * frame in the new window, preserving the old a1 in - * the previous window. - * - * 3. The underscore prefix prevents the assembler from - * automatically aligning the ENTRY instruction on a - * 4-byte boundary, which could create a fatal gap in - * the instruction stream. - * - * At this point, ie. before we re-enable interrupts, we know the caller is - * always live so we can safely modify a1 without using MOVSP (we can use MOVSP - * but it will never cause an ALLOCA or underflow exception here). - * So this is a good point to modify the stack pointer if we want eg. to - * switch to an interrupt stack (if we do, we need to save the current SP - * because certain things have been saved to that exception stack frame). - * We couldn't do this easily before ENTRY, where the caller wasn't - * necessarily live. - * - * NOTE: We don't switch to an interrupt stack here, because exceptions - * are generally caused by executing code -- so we handle exceptions in - * the context of the thread that cause them, and thus remain on the same - * stack. This means a thread's stack must be large enough to handle - * the maximum level of nesting of exceptions that the thread can cause. - */ - - // NOTA: exception handlers for certain causes may need interrupts to be kept - // disabled through their dispatch, so they can turn them off themselves at - // the right point (if at all), eg. to save critical state unknown to this - // code here, or for some recovery action that must be atomic with respect - // to interrupts.... - // - // Perhaps two versions of this assembly-level handler are needed, one that restores - // interrupts to what they were before the exception was taken (as here) - // and one that ensures at least low-priority interrupts are kept disabled? - // NOTA: For now, always enable interrupts here. - - /* - * Now we can enable interrupts. - * (Pseudo-CALL is complete, and SP reflects allocation of exception stack frame.) - */ - -#endif /* __XTENSA_CALL0_ABI__ */ - - -#if XCHAL_HAVE_INTERRUPTS - rsr.sar a12 - // Restore PS.INTLEVEL to its saved value (re-enables interrupts - // if they were enabled before taking the exception): - l32i a13, a1, UEXC_ps - rsr.ps a14 - extui a13, a13, 0, 4 // extract saved PS.INTLEVEL - extui a15, a14, 0, 4 // extract current PS.INTLEVEL - xor a14, a14, a15 // clear a14.INTLEVEL - xor a14, a14, a13 // replace with saved PS.INTLEVEL - wsr.ps a14 // restore PS.INTLEVEL -#else - rsr.sar a12 -#endif - - movi a13, xtos_c_handler_table // &table - l32i a15, a1, UEXC_exccause // arg2: exccause - - s32i a12, a1, UEXC_sar - save_loops_mac16 a1, a12, a14 // save LOOP & MAC16 regs, if configured - - addx4 a12, a15, a13 // a12 = table[exccause] - l32i a12, a12, 0 // ... - .global _GeneralException -_GeneralException: // this label makes tracebacks through exceptions look nicer - -#ifdef __XTENSA_CALL0_ABI__ - .global _GeneralExceptionFrameSize - .set _GeneralExceptionFrameSize, ESF_TOTALSIZE - .global _GeneralExceptionRegisterSaveOffset - .set _GeneralExceptionRegisterSaveOffset, UEXC_a0 - mov a2, a1 // arg1: exception parameters - mov a3, a15 // arg2: exccause - beqz a12, 1f // null handler => skip call - callx0 a12 // call C exception handler for this exception -#else - mov a14, a1 // arg1: exception parameters - // mov a15, a15 // arg2: exccause, already in a15 - beqz a12, 1f // null handler => skip call - callx12 a12 // call C exception handler for this exception -#endif - .size _GeneralException, . - _GeneralException -1: - // Now exit the handler. - - - // Restore special registers - - restore_loops_mac16 a1, a13, a14, a15 // restore LOOP & MAC16 regs, if configured - l32i a14, a1, UEXC_sar - - /* - * Disable interrupts while returning from the pseudo-CALL setup above, - * for the same reason they were disabled while doing the pseudo-CALL: - * this sequence restores SP such that it doesn't reflect the allocation - * of the exception stack frame, which we still need to return from - * the exception. - */ - -#if XCHAL_HAVE_INTERRUPTS - rsil a12, XCHAL_EXCM_LEVEL -#endif - wsr.sar a14 - - movi a0, _xtos_return_from_exc -#ifdef __XTENSA_CALL0_ABI__ - jx a0 -#else /* ! __XTENSA_CALL0_ABI__ */ - /* Now return from the pseudo-CALL from the interrupted code, to rotate - * our windows back... */ - - movi a13, 0xC0000000 - //movi a13, 3 - //slli a13, a13, 30 - or a0, a0, a13 // set upper two bits - addx2 a0, a13, a0 // clear upper bit - retw -#endif /* ! __XTENSA_CALL0_ABI__ */ - - /* FIXME: what about _GeneralException ? */ - - .size xtos_c_wrapper_handler, . - xtos_c_wrapper_handler - - -#endif /* XCHAL_HAVE_XEA2 && XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/xea2/exc-return.S b/src/arch/xtensa/xtos/xea2/exc-return.S deleted file mode 100644 index 083d78206905..000000000000 --- a/src/arch/xtensa/xtos/xea2/exc-return.S +++ /dev/null @@ -1,114 +0,0 @@ -// exc-return.S - Shared exception/interrupt return code - -// Copyright (c) 2002-2015 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/corebits.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA2 && XCHAL_HAVE_EXCEPTIONS - - .text - .align 4 - .global _xtos_return_from_exc -_xtos_return_from_exc: - -#ifdef __XTENSA_CALL0_ABI__ - - l32i a0, a1, UEXC_a0 // restore general registers, pc, ps - l32i a4, a1, UEXC_a4 - l32i a5, a1, UEXC_a5 - l32i a6, a1, UEXC_a6 - l32i a7, a1, UEXC_a7 - l32i a8, a1, UEXC_a8 - l32i a9, a1, UEXC_a9 - l32i a10, a1, UEXC_a10 - l32i a11, a1, UEXC_a11 - l32i a12, a1, UEXC_a12 - l32i a13, a1, UEXC_a13 - l32i a14, a1, UEXC_a14 - l32i a15, a1, UEXC_a15 - - l32i a2, a1, UEXC_pc - l32i a3, a1, UEXC_ps - wsr.epc1 a2 - wsr.ps a3 - - l32i a2, a1, UEXC_a2 - l32i a3, a1, UEXC_a3 - - rsync // wait for WSR to PS to complete - - addi a1, a1, ESF_TOTALSIZE // restore sp - - rfe - -#else /* ! __XTENSA_CALL0_ABI__ */ - - - // Here we rotated back by N registers, to the interrupted code's register window. - // NOTA: a2 and a3 might contain something useful, but we haven't determined - // what that might be yet (for now, a2 contains nested-C-func call-chain ptr). - - // NOTE: a5 still contains the exception window's exception stack frame pointer. - -# if XTOS_CNEST - s32i a2, a5, ESF_TOTALSIZE-20 // restore nested-C-func call-chain ptr -# endif - l32i a2, a5, UEXC_ps - l32i a3, a5, UEXC_pc - wsr.ps a2 // this sets PS.EXCM - - l32i a2, a5, UEXC_a2 - l32i a4, a5, UEXC_a4 - rsync // wait for WSR to PS to complete - - /* FIXME: Enabling this here may break task-engine builds - * because task engines have exceptions (sort of), but they do - * not have the EPC_1 special register. XCHAL_HAVE_INTERRUPTS - * is incorrect for normal configs without interrupts but with - * exceptions (we still need to restore EPC_1). The correct - * solution is to define XCHAL_HAVE_EXCEPTIONS more strictly - * to mean something like "Have exceptions with - * user/kernel/double vectors" so that task engines are - * excluded. This would be a change to - * <xtensa/config/core.h>. */ - - wsr.epc1 a3 - // HERE: - // - we cannot get window overflows anymore -- we're NOT in a valid windowed context - // - low-priority interrupts are still disabled - - // NOTE: we don't restore EXCCAUSE or EXCVADDR, not needed. - - // Restore a3, a5: - l32i a3, a5, UEXC_a3 - l32i a5, a5, UEXC_a5 - - rfe_rfue - -#endif /* __XTENSA_CALL0_ABI__ */ - - .size _xtos_return_from_exc, . - _xtos_return_from_exc - -#endif /* XCHAL_HAVE_XEA2 && XCHAL_HAVE_EXCEPTIONS */ - diff --git a/src/arch/xtensa/xtos/xea2/int-lowpri-dispatcher.S b/src/arch/xtensa/xtos/xea2/int-lowpri-dispatcher.S deleted file mode 100644 index c70c7044c142..000000000000 --- a/src/arch/xtensa/xtos/xea2/int-lowpri-dispatcher.S +++ /dev/null @@ -1,324 +0,0 @@ -// Level-one interrupt dispatcher (user vectored handler) - -// Copyright (c) 1999-2015 Tensilica 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 <sof/lib/memory.h> -#include <config.h> -#include <xtensa/coreasm.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA2 && XCHAL_HAVE_EXCEPTIONS && XCHAL_HAVE_INTERRUPTS - -#define _INTERRUPT_LEVEL 1 - - - // NOTE: something equivalent to the following vector is executed - // before entering this handler (see user-vector.S). -//_UserExceptionVector: -// addi a1, a1, -ESF_TOTALSIZE // allocate exception stack frame, etc. -// s32i a2, a1, UEXC_a2 -// s32i a3, a1, UEXC_a3 -// movi a3, xtos_exc_handler_table -// rsr.exccause a2 -// addx4 a2, a2, a3 -// l32i a2, a2, 0 -// s32i a4, a1, UEXC_a4 -// jx a2 // jump to cause-specific handler - - .global _need_user_vector_ // pull-in real user vector (tiny LSP) - - .text - .align 4 - .global _xtos_l1int_handler -_xtos_l1int_handler: - // HERE: a2, a3, a4 have been saved to exception stack frame allocated with a1 (sp). - - s32i a5, a1, UEXC_a5 // a5 will get clobbered by ENTRY after pseudo-CALL4 - // (a4..a15 spilled as needed; save if modified) - -#if HAVE_XSR - movi a2, PS_WOECALL4_ABI|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) - xsr.ps a2 - s32i a2, a1, UEXC_ps -#else - rsr.ps a2 - s32i a2, a1, UEXC_ps - movi a2, PS_WOECALL4_ABI|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) - wsr.ps a2 -#endif - rsync - - /* store pc */ - rsr.epc1 a2 - s32i a2, a1, UEXC_pc - - /* store rest of the registers */ - s32i a0, a1, UEXC_a0 - s32i a6, a1, UEXC_a6 - s32i a7, a1, UEXC_a7 - s32i a8, a1, UEXC_a8 - s32i a9, a1, UEXC_a9 - s32i a10, a1, UEXC_a10 - s32i a11, a1, UEXC_a11 - s32i a12, a1, UEXC_a12 - s32i a13, a1, UEXC_a13 - s32i a14, a1, UEXC_a14 - s32i a15, a1, UEXC_a15 - - /* store current sp */ - xtos_addr_percore a2, xtos_saved_sp - s32i a1, a2, 0 - - /* store current task sp */ - xtos_task_ctx_percore a2 - beqz a2, no_context - s32i a1, a2, TC_stack_pointer - -no_context: -# if XTOS_CNEST - l32i a2, a1, ESF_TOTALSIZE-20 // save nested-C-func call-chain ptr -# endif - addi a1, a1, ESF_TOTALSIZE -# if XTOS_DEBUG_PC - rsr.epc1 a4 // [for debug] get return PC - movi a5, 0xC0000000 // [for debug] setup call size... - or a4, a5, a4 // [for debug] set upper two bits of return PC - addx2 a4, a5, a4 // [for debug] clear upper bit -# else - movi a4, 0 /* terminate stack frames, overflow check */ -# endif - _entry a1, ESF_TOTALSIZE - -/* Reset the interrupt level to xtos locklevel (lvl 6 on most systems) */ - - rsil a15, XTOS_LOCKLEVEL - -/* Get bit list of pending interrupts at the current interrupt priority level. - * If bit list is empty, interrupt is spurious (can happen if a - * genuine interrupt brings control this direction, but the interrupt - * goes away before we read the INTERRUPT register). Also save off - * sar, loops, mac16 registers and coprocessors. */ - -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp0 - xchal_cp0_store a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - mov a11, a1 - addi a11, a11, UEXC_cp1 - xchal_cp1_store a11, a12, a13, a14, a15 -#endif -#endif - rsr.interrupt a15 - rsr.intenable a12 - movi a13, XCHAL_INTLEVEL1_MASK - and a15, a15, a12 - and a15, a15, a13 - rsr.sar a14 - s32i a14, a1, UEXC_sar - save_loops_mac16 a1, a13, a14 - - /* switch to interrupt stack */ - xtos_int_stack_addr_percore a13, _INTERRUPT_LEVEL, xtos_stack_for_interrupt - s32i a1, a13, 0 - addi a1, a13, SOF_STACK_SIZE - - _beqz a15, LABEL(spurious,int) - - /* set stack base and size for interrupt context */ - xtos_addr_percore a11, xtos_interrupt_ctx - s32i a13, a11, TC_stack_base - movi a13, SOF_STACK_SIZE - s32i a13, a11, TC_stack_size - - /* save task context */ - xtos_task_ctx_percore a13 - xtos_store_percore a13, a14, xtos_saved_ctx - - /* set interrupt task context */ - xtos_task_ctx_store_percore a11, a14 - - xtos_on_wakeup - -/* Loop to handle all pending interrupts. */ - -LABEL(.L1,_loop0): - neg a12, a15 - and a12, a12, a15 - wsr.intclear a12 // clear if edge-trig or s/w or wr/err (else no effect) -#if CONFIG_SMP - xtos_addr_percore a13, xtos_interrupt_table -#else - movi a13, xtos_interrupt_table -#endif - find_ms_setbit a15, a12, a14, 0 - mapint a15 - addx8 a12, a15, a13 - l32i a13, a12, XIE_HANDLER - l32i a14, a12, XIE_ARG - mov a15, a1 - callx12 a13 - - rsr.interrupt a15 - rsr.intenable a12 - movi a13, XCHAL_INTLEVEL1_MASK - and a15, a15, a12 - and a15, a15, a13 - _bnez a15, LABEL(.L1,_loop0) - -/* Restore everything, and return. */ - - /* restore task context if needed */ - xtos_task_ctx_percore a11 - xtos_addr_percore a12, xtos_interrupt_ctx - bne a11, a12, restore_cp - xtos_addr_percore a12, xtos_saved_ctx - xtos_task_ctx_store_percore a12, a11 - -restore_cp: -#if __XCC__ -#if (XCHAL_CP_MASK & CP0_MASK) - xtos_task_ctx_percore a11 - beqz a11, no_context_2 - l32i a11, a11, TC_stack_pointer - addi a11, a11, UEXC_cp0 - xchal_cp0_load a11, a12, a13, a14, a15 -#endif -#if (XCHAL_CP_MASK & CP1_MASK) - xtos_task_ctx_percore a11 - beqz a11, no_context_2 - l32i a11, a11, TC_stack_pointer - addi a11, a11, UEXC_cp1 - xchal_cp1_load a11, a12, a13, a14, a15 -#endif -#endif - -no_context_2: - restore_loops_mac16 a1, a13, a14, a15 - l32i a14, a1, UEXC_sar -LABEL(spurious,int): - -#if XCHAL_HAVE_EXCLUSIVE - // Clear exclusive monitors. - clrex -#endif - - movi a0, LABEL(return,from_exc) - movi a13, 0xC0000000 - wsr.sar a14 - or a0, a0, a13 - addx2 a0, a13, a0 -# if _INTERRUPT_LEVEL < XCHAL_EXCM_LEVEL -/* Raise the interrupt mask before - * returning to avoid a race condition where we deallocate the - * exception stack frame but still have more register values to - * restore from it. */ - rsil a14, XCHAL_EXCM_LEVEL -# endif - retw -LABEL(return,from_exc): - /* a5 contains interrupt stack pointer */ - addi a5, a5, -SOF_STACK_SIZE - l32i a5, a5, 0 - -# if XTOS_CNEST - s32i a2, a5, ESF_TOTALSIZE-20 // restore nested-C-func call-chain ptr -# endif - - /* store sp after returning from handler */ - s32i a1, a5, UEXC_a1 - -restore: - /* load registers for window spill */ - l32i a4, a5, UEXC_a4 - l32i a6, a5, UEXC_a6 - l32i a7, a5, UEXC_a7 - l32i a8, a5, UEXC_a8 - l32i a9, a5, UEXC_a9 - l32i a10, a5, UEXC_a10 - l32i a11, a5, UEXC_a11 - l32i a12, a5, UEXC_a12 - l32i a13, a5, UEXC_a13 - l32i a14, a5, UEXC_a14 - - /* check if switch is needed */ - xtos_addr_percore a2, xtos_saved_sp - xtos_task_ctx_percore a1 - beqz a1, noSwitch - l32i a1, a1, TC_stack_pointer - l32i a0, a2, 0 - beq a0, a1, noSwitch - -doSwitch: - /* store new task sp */ - s32i a1, a2, 0 - - /* restore sp of task being preempted */ - l32i a1, a5, UEXC_a1 - - /* spill register windows to the stack */ - rsr.ps a2 - movi a3, PS_WOE_MASK - xor a2, a2, a3 - wsr.ps a2 - - call0 xthal_window_spill_nw - - /* restore previous ps */ - rsr.ps a2 - movi a3, PS_WOE_MASK - or a2, a2, a3 - wsr.ps a2 - - /* change stack */ - xtos_addr_percore a5, xtos_saved_sp - l32i a5, a5, 0 - j restore - -noSwitch: - /* restore ps and pc */ - l32i a0, a5, UEXC_ps - wsr.ps a0 - rsync - l32i a0, a5, UEXC_pc - wsr.epc1 a0 - - /* restore sar, loops and mac16 registers */ - l32i a0, a5, UEXC_sar - wsr.sar a0 - restore_loops_mac16 a5, a0, a1, a2 - - /* restore rest of the registers */ - l32i a0, a5, UEXC_a0 - l32i a1, a5, UEXC_a1 - l32i a2, a5, UEXC_a2 - l32i a3, a5, UEXC_a3 - l32i a15, a5, UEXC_a15 - l32i a5, a5, UEXC_a5 - rfe - - /* FIXME: what about _LevelOneInterrupt ? */ - .size _xtos_l1int_handler, . - _xtos_l1int_handler - -#endif /* XCHAL_HAVE_XEA2 && XCHAL_HAVE_EXCEPTIONS && XCHAL_HAVE_INTERRUPTS */ diff --git a/src/arch/xtensa/xtos/xea2/intlevel-restore.S b/src/arch/xtensa/xtos/xea2/intlevel-restore.S deleted file mode 100644 index ed749a2cc7ae..000000000000 --- a/src/arch/xtensa/xtos/xea2/intlevel-restore.S +++ /dev/null @@ -1,91 +0,0 @@ -// intlevel-restore.S - Interrupt related assembler code - _xtos_restore_intlevel - -// Copyright (c) 2004-2015 Tensilica 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 <config.h> -#include <xtensa/coreasm.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA2 - -/*************************************************************************** - * void _xtos_restore_intlevel(unsigned restoreval); - * - * _xtos_restore_intlevel() restores the current interrupt level - * according to a value returned by _xtos_set_intlevel() or - * _xtos_set_min_intlevel() (or one of the corresponding macros). - * - * NOTE: In XEA2, this function may restore the entire PS register, not - * just the PS.INTLEVEL field. If some other PS field(s) must be changed - * and kept intact across restoring PS.INTLEVEL (this is generally unlikely), - * use the XTOS_RESTORE_JUST_INTLEVEL() macro instead (which is slower). - * - * NOTE: The macro form of this function (XTOS_RESTORE_INTLEVEL()) - * is recommended (for XEA2 configs or where the config is unknown) - * because it may be more efficient. - */ - - .text - .global _xtos_restore_intlevel - .type _xtos_restore_intlevel,@function - .align 4 -_xtos_restore_intlevel: - abi_entry -# if XCHAL_HAVE_INTERRUPTS - wsr a2, PS // restore PS - rsync // wait for WSR to PS to complete -# endif - abi_return - .size _xtos_restore_intlevel, . - _xtos_restore_intlevel - - - -/*************************************************************************** - * _xtos_set_vpri() is used to set the current virtual priority from C code; - * it can be called from the application or from a C interrupt handler. - */ - - .global _xtos_set_vpri - .type _xtos_set_vpri,@function - .align 4 -_xtos_set_vpri: - abi_entry -#if XCHAL_HAVE_INTERRUPTS && XTOS_VIRTUAL_INTENABLE - mov a3, a2 -#if CONFIG_SMP - xtos_addr_percore a4, xtos_intstruct -#else - movi a4, _xtos_intstruct -#endif - xtos_lock a7 // MUST USE highest address register of function to avoid window overflows in critical section - l32i a2, a4, XTOS_VPRI_ENABLED_OFS // return old xtos_vpri_enabled (current vpri) - l32i a5, a4, XTOS_ENABLED_OFS // a3 = xtos_enabled - s32i a3, a4, XTOS_VPRI_ENABLED_OFS // set new xtos_vpri_enabled (current vpri) - and a5, a5, a3 // a5 = xtos_enabled & xtos_vpri_enabled - wsr a5, INTENABLE - xtos_unlock a7 -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - .size _xtos_set_vpri, . - _xtos_set_vpri - -#endif /* XEA2 */ - diff --git a/src/arch/xtensa/xtos/xea2/intlevel-set.S b/src/arch/xtensa/xtos/xea2/intlevel-set.S deleted file mode 100644 index 30a82c336fb0..000000000000 --- a/src/arch/xtensa/xtos/xea2/intlevel-set.S +++ /dev/null @@ -1,63 +0,0 @@ -// intlevel-set.S - Interrupt related assembler code - _xtos_set_intlevel - -// Copyright (c) 2004-2015 Tensilica 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 <xtensa/coreasm.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA2 - - -/*************************************************************************** - * unsigned _xtos_set_intlevel(int intlevel); - * - * _xtos_set_intlevel() is used to set the current priority from C code; - * it can be called from the application or from a C interrupt handler. - * - * NOTE: This version allows the 'intlevel' parameter to be computed - * at run-time, and thus is longer. It is much more efficient, and - * highly recommented, to use the XTOS_SET_INTLEVEL(intlevel) macro instead - * (which requires a constant intlevel). - */ - - .text - .align 4 - .global _xtos_set_intlevel - .type _xtos_set_intlevel,@function -_xtos_set_intlevel: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - /* In XEA2, we can simply safely set PS.INTLEVEL directly: */ - extui a3, a2, 0, 4 // keep only INTLEVEL bits of parameter - rsr.ps a2 // get old (current) PS.INTLEVEL - movi a4, ~0xF - and a4, a4, a2 // mask out PS.INTLEVEL - or a4, a4, a3 // insert requested INTLEVEL - wsr.ps a4 // update PS.INTLEVEL - rsync // wait for WSR to PS to complete -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - - .size _xtos_set_intlevel, . - _xtos_set_intlevel - -#endif /* XEA2 */ - diff --git a/src/arch/xtensa/xtos/xea2/intlevel-setmin.S b/src/arch/xtensa/xtos/xea2/intlevel-setmin.S deleted file mode 100644 index 0d9f70e18b96..000000000000 --- a/src/arch/xtensa/xtos/xea2/intlevel-setmin.S +++ /dev/null @@ -1,68 +0,0 @@ -// intlevel-setmin.S - Interrupt related assembler code - _xtos_set_min_intlevel - -// Copyright (c) 2004-2015 Tensilica 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 <xtensa/coreasm.h> -#include "../xtos-internal.h" - -#if XCHAL_HAVE_XEA2 - - -/*************************************************************************** - * unsigned _xtos_set_min_intlevel(int intlevel); - * - * _xtos_set_min_intlevel() is identical to _xtos_set_intlevel() except - * that it will not lower the current interrupt level. Instead, - * it ensures that the current interrupt level is at least as high - * as specified. - * - * NOTE: This version allows the 'intlevel' parameter to be computed - * at run-time, and thus is longer. It is much more efficient, and - * highly recommented, to use the XTOS_SET_MIN_INTLEVEL(intlevel) macro instead - * (which requires a constant intlevel). - */ - - .text - .align 4 - .global _xtos_set_min_intlevel - .type _xtos_set_min_intlevel,@function -_xtos_set_min_intlevel: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - /* In XEA2, we can simply safely set PS.INTLEVEL directly: */ - extui a3, a2, 0, 4 // keep only INTLEVEL bits of parameter - rsr.ps a2 // get old (current) PS.INTLEVEL - movi a4, ~0xF - extui a5, a2, 0, 4 // look at old PS.INTLEVEL - sub a5, a3, a5 // new.intlevel - old.intlevel - and a4, a4, a2 // mask out PS.INTLEVEL - or a4, a4, a3 // insert requested INTLEVEL - movltz a4, a2, a5 // keep same PS if already higher than requested - wsr.ps a4 // update PS.INTLEVEL - rsync // wait for WSR to PS to complete -#endif /*XCHAL_HAVE_INTERRUPTS*/ - abi_return - - .size _xtos_set_min_intlevel, . - _xtos_set_min_intlevel - -#endif /* XEA2 */ - diff --git a/src/arch/xtensa/xtos/xea2/reloc-vectors.S b/src/arch/xtensa/xtos/xea2/reloc-vectors.S deleted file mode 100644 index 7e9c1760495b..000000000000 --- a/src/arch/xtensa/xtos/xea2/reloc-vectors.S +++ /dev/null @@ -1,120 +0,0 @@ -// reloc-vector.S - Relocatable Vectors section -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/xea2/reloc-vectors.S#1 $ - -// Copyright (c) 2007-2017 Tensilica 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. - -/* - * This file is only used if the relocatable vectors option is enabled. - */ - - -#include <xtensa/coreasm.h> -#include <xtensa/config/system.h> - -#if XCHAL_HAVE_VECBASE - - .section .RelocatableVectors.text, "ax" - - .global _RelocVectors -_RelocVectors: - -//if XCHAL_RESET_VECBASE_OVERLAP ... -# if XSHAL_VECTORS_PACKED \ - && (XCHAL_RESET_VECTOR0_VADDR == XCHAL_VECBASE_RESET_VADDR \ - || XCHAL_RESET_VECTOR1_VADDR == XCHAL_VECBASE_RESET_VADDR) -# define JUMP_TO_RESET 1 - j .Ljump_to_reset -# endif - -# if XCHAL_HAVE_WINDOWED -# define NO_SECTION_DIRECTIVES 1 -# define WINDOW_BASE_VECOFS 0 -# include "window-vectors.S" -# endif - -#if XCHAL_HAVE_DEBUG && XCHAL_HAVE_EXCEPTIONS -# if XCHAL_DEBUGLEVEL == 2 -# define _Level2Vector _DebugExceptionVector -# elif XCHAL_DEBUGLEVEL == 3 -# define _Level3Vector _DebugExceptionVector -# elif XCHAL_DEBUGLEVEL == 4 -# define _Level4Vector _DebugExceptionVector -# elif XCHAL_DEBUGLEVEL == 5 -# define _Level5Vector _DebugExceptionVector -# elif XCHAL_DEBUGLEVEL == 6 -# define _Level6Vector _DebugExceptionVector -# endif -#endif - -# if XCHAL_HAVE_INTERRUPTS -# if XCHAL_NUM_INTLEVELS >= 2 - .org XCHAL_INTLEVEL2_VECOFS - j _Level2Vector -# endif -# if XCHAL_NUM_INTLEVELS >= 3 - .org XCHAL_INTLEVEL3_VECOFS - j _Level3Vector -# endif -# if XCHAL_NUM_INTLEVELS >= 4 - .org XCHAL_INTLEVEL4_VECOFS - j _Level4Vector -# endif -# if XCHAL_NUM_INTLEVELS >= 5 - .org XCHAL_INTLEVEL5_VECOFS - j _Level5Vector -# endif -# if XCHAL_NUM_INTLEVELS >= 6 - .org XCHAL_INTLEVEL6_VECOFS - j _Level6Vector -# endif -# if XCHAL_HAVE_NMI - .org XCHAL_NMI_VECOFS - j _NMIExceptionVector -# endif -# endif -# if XCHAL_HAVE_EXCEPTIONS - .org XCHAL_KERNEL_VECOFS - j _KernelExceptionVector - .org XCHAL_USER_VECOFS - j _UserExceptionVector - .org XCHAL_DOUBLEEXC_VECOFS - j _DoubleExceptionVector -# endif - -// Put literals here. - -// Put actual handlers here. - -# if JUMP_TO_RESET - .align 4 - .literal rvec, _ResetVector -.Ljump_to_reset: - l32r a2, rvec - jx a2 -# endif - - .size _RelocVectors, . - _RelocVectors - - .text - -#endif /* XCHAL_HAVE_VECBASE */ - diff --git a/src/arch/xtensa/xtos/xea2/switch_context.S b/src/arch/xtensa/xtos/xea2/switch_context.S deleted file mode 100644 index b4ed2fafe2af..000000000000 --- a/src/arch/xtensa/xtos/xea2/switch_context.S +++ /dev/null @@ -1,94 +0,0 @@ -/* switch_contexts.S - setup for multiple contexts */ - -/* - * Copyright (c) 2003-2010 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/xtruntime-frames.h> - -#if XCHAL_NUM_CONTEXTS > 1 - - -/* - * void _xtos_setup_context(int context_num, StartInfo *info); - */ - .align 4 - .global _xtos_setup_context - .type _xtos_setup_context,@function -_xtos_setup_context: - abi_entry -#if XCHAL_HAVE_INTERRUPTS - rsil a5, 15 /* disable interrupts so we can use EXCSAVE_1 */ -#else - rsr.ps a5 /* just read PS */ -#endif - wsr.excsave1 a3 /* save pointer to new context info */ - s32i a5, a3, INFO_prevps /* save previous PS */ - movi a4, ~0x01F00000 /* mask out PS.CTXT */ - slli a2, a2, 20 /* shift up new PS.CTXT value */ - and a4, a5, a4 - or a4, a4, a2 /* new PS value */ - wsr.ps a4 - rsync - /* We're now in the new context! */ - movi a0, 0 - movi a1, 1 - wsr.windowstart a1 - wsr.windowbase a0 - rsync - rsr.excsave1 a9 /* get pointer to context info */ - movi a0, 0 /* terminate call frames */ - l32i a1, a9, INFO_sp /* get stack pointer */ - l32i a10, a9, INFO_arg1 /* get start function's arguments... */ - l32i a8, a9, INFO_funcpc /* get start function's address */ - /* Okay, now switch back to context zero: */ - l32i a9, a9, INFO_prevps /* retrieve previous PS */ - wsr.ps a9 - rsync - /* Back to original context! */ - abi_return - - .size _xtos_setup_context, . - _xtos_setup_context - - - - /* - * This is the first thing to be executed in the new context - * by explicit setting of PC: - */ - .align 4 - .global _xtos_start_context -_xtos_start_context: -#ifdef __XTENSA_CALL0_ABI__ - Crash the assembler here: I think this is wrong. - callx0 a8 -#else - callx8 a8 -#endif -1: nop - j 1b /* do nothing until context 0 exits */ - .size _xtos_start_context, . - _xtos_start_context - - -#endif /* XCHAL_NUM_CONTEXTS > 1 */ - diff --git a/src/arch/xtensa/xtos/xea2/window-vectors.S b/src/arch/xtensa/xtos/xea2/window-vectors.S deleted file mode 100644 index b6bd0f0974dd..000000000000 --- a/src/arch/xtensa/xtos/xea2/window-vectors.S +++ /dev/null @@ -1,338 +0,0 @@ -// window-vectors-xea2.S - Register Window Overflow/Underflow Handlers for XEA2 -// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/xtos/xea2/window-vectors.S#1 $ - -// Copyright (c) 1999-2016 Tensilica 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 <xtensa/coreasm.h> -#include <xtensa/xtruntime-frames.h> - -#if XCHAL_HAVE_XEA2 && XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) - -# ifndef NO_SECTION_DIRECTIVES -// Exports -.global _WindowOverflow4 -.global _WindowUnderflow4 -.global _WindowOverflow8 -.global _WindowUnderflow8 -.global _WindowOverflow12 -.global _WindowUnderflow12 -.global _xtos_alloca_handler - - // Note: the current window exception vectors do not generate any - // literals. Hence the literal_prefix directive is not necessary. - // Specifying it "just in case" creates an empty section (named - // ".WindowVectors.literal") which can in some cases cause linking - // problems (the linker scripts don't place it anywhere). - // So leave it commented out: - // - //.begin literal_prefix .WindowVectors - - .section .WindowVectors.text, "ax" -# endif - - -// -// GENERAL NOTES: -// -// These window exception handlers need not be modified. -// They are specific to the windowed call ABI only. -// -// Underflow Handlers: -// -// The underflow handler for returning from call[i+1] to call[i] -// must preserve all the registers from call[i+1]'s window. -// In particular, a0 and a1 must be preserved because the RETW instruction -// will be reexecuted (and may even underflow again if an intervening -// exception has flushed call[i]'s registers). -// Registers a2 and up may contain return values. -// -// The caller could also potentially assume that the callee's a0 and a1 -// (its own a4&a5 if call4, a8&a9 if call8, a12&a13 if call12) -// are correct for whatever reason (not a clean thing to do in general, -// but if it's possible, unless the ABI explicitly prohibits it, -// it will eventually be done :) -- whether the the ABI needs to -// prohibit this is a different question). -// -// Timing of Handlers: -// -// Here is an overview of the overhead of taking a window exception, -// ie. the number of additional cycles taken relative to case where -// an exception is not taken. -// NOTE: these numbers do not take into account any cache misses, -// write buffer stalls, or other external stalls, if they occur. -// The totals consist of 5 cycles to enter the handler (or 6 or 7 -// for optional longer pipelines in Xtensa LX), the number of instructions -// and interlocks (2nd and 3rd columns below), and 2 cycles jump delay -// on return (3 cycles for optional longer I-side pipeline in Xtensa LX): -// -// Instruction+bubbles Totals (5-stage) -// XEA1 XEA2 XEA1 XEA2 -// Overflow-4 7 5 14 12 -// Overflow-8 14 10 21 17 -// Overflow-12 18 14 25 21 -// Underflow-4 6 5 13 12 -// Underflow-8 14 10 21 17 -// Underflow-12 18 14 25 21 -// -// Underflow-8 15 12 25 22 (7-stage; could be made 1 less) -// Underflow-12 19 16 29 26 (7-stage; could be made 1 less) - -#ifndef WINDOW_BASE_VECOFS -#define WINDOW_BASE_VECOFS XCHAL_WINDOW_OF4_VECOFS -#endif - - -// 4-Register Window Overflow Vector (Handler) -// -// Invoked if a call[i] referenced a register (a4-a15) -// that contains data from ancestor call[j]; -// call[j] had done a call4 to call[j+1]. -// On entry here: -// window rotated to call[j] start point; -// a0-a3 are registers to be saved; -// a4-a15 must be preserved; -// a5 is call[j+1]'s stack pointer. - - .org XCHAL_WINDOW_OF4_VECOFS - WINDOW_BASE_VECOFS -_WindowOverflow4: - hw_erratum_487_fix - s32e a0, a5, -16 // save a0 to call[j+1]'s stack frame - s32e a1, a5, -12 // save a1 to call[j+1]'s stack frame - s32e a2, a5, -8 // save a2 to call[j+1]'s stack frame - s32e a3, a5, -4 // save a3 to call[j+1]'s stack frame - rfwo // rotates back to call[i] position - - .size _WindowOverflow4, . - _WindowOverflow4 - - -// ALLOCA exception handler -// -// NOTE: The alloca exception handler is squeezed in between the window exception -// handlers in order to save space, and also to allow short-range jumps to the -// window underflow handlers (see below for why). Because of the limited space in -// between the window handlers, this function is split into two to fit. -// -// Code written to the windowed ABI must use the MOVSP instruction to modify -// the stack pointer (except for startup code, which doesn't have a caller). -// The compiler uses MOVSP to allocate very large or variable size stack frames. -// MOVSP guarantees that the caller frame's a0-a3 registers, stored below the -// stack pointer, are moved atomically with respect to interrupts and exceptions -// to satisfy windowed ABI requirements. When user code executes the MOVSP -// instruction and the caller frame is on the stack rather than in the register -// file, the processor takes an ALLOCA exception. -// -// The XTOS user exception dispatcher allocates an exception frame on the -// stack and saves a2-a4 into that frame before calling us. So we need to -// restore those registers and deallocate the stack frame before jumping -// to the window underflow handler - which will restore the spilled registers -// back into the register file. -// The fact the alloca exception was taken means the registers associated with -// the base-save area have been spilled and will be restored by the underflow -// handler, so those 4 registers are available for scratch. - - .align 4 - -_xtos_alloca_handler: - - l32i a2, a1, UEXC_a2 // restore a2-a4 and deallocate frame - l32i a3, a1, UEXC_a3 - l32i a4, a1, UEXC_a4 - addi a1, a1, ESF_TOTALSIZE - wsr.excsave1 a0 // save a0 - rsr.windowbase a0 // grab WINDOWBASE before rotw changes it - rotw -1 // WINDOWBASE goes to a4, new a0-a3 are scratch - rsr.ps a2 - extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS - xor a3, a3, a4 // bits changed from old to current windowbase - j _xtos_alloca_2 // not enough room here... - - .size _xtos_alloca_handler, . - _xtos_alloca_handler - - -// 4-Register Window Underflow Vector (Handler) -// -// Invoked by RETW returning from call[i+1] to call[i] -// where call[i]'s registers must be reloaded (not live in ARs); -// call[i] had done a call4 to call[i+1]. -// On entry here: -// window rotated to call[i] start point; -// a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; -// a4-a15 must be preserved (they are call[i+1].reg[0..11]); -// a5 is call[i+1]'s stack pointer. - - .org XCHAL_WINDOW_UF4_VECOFS - WINDOW_BASE_VECOFS -_WindowUnderflow4: - l32e a0, a5, -16 // restore a0 from call[i+1]'s stack frame - l32e a1, a5, -12 // restore a1 from call[i+1]'s stack frame - l32e a2, a5, -8 // restore a2 from call[i+1]'s stack frame - l32e a3, a5, -4 // restore a3 from call[i+1]'s stack frame - rfwu - - .size _WindowUnderflow4, . - _WindowUnderflow4 - - -// This is the second part of the alloca handler. - - .align 4 - -_xtos_alloca_2: - - rsr.excsave1 a4 // restore original a0 (now in a4) - slli a3, a3, XCHAL_PS_OWB_SHIFT - xor a2, a2, a3 // flip changed bits in old window base - wsr.ps a2 // update PS.OWB to new window base - rsync - _bbci.l a4, 31, _WindowUnderflow4 - rotw -1 // original a0 goes to a8 - _bbci.l a8, 30, _WindowUnderflow8 - rotw -1 - j _WindowUnderflow12 - - .size _xtos_alloca_2, . - _xtos_alloca_2 - - -// 8-Register Window Overflow Vector (Handler) -// -// Invoked if a call[i] referenced a register (a4-a15) -// that contains data from ancestor call[j]; -// call[j] had done a call8 to call[j+1]. -// On entry here: -// window rotated to call[j] start point; -// a0-a7 are registers to be saved; -// a8-a15 must be preserved; -// a9 is call[j+1]'s stack pointer. - - .org XCHAL_WINDOW_OF8_VECOFS - WINDOW_BASE_VECOFS -_WindowOverflow8: - hw_erratum_487_fix - s32e a0, a9, -16 // save a0 to call[j+1]'s stack frame - l32e a0, a1, -12 // a0 <- call[j-1]'s sp (used to find end of call[j]'s frame) - s32e a1, a9, -12 // save a1 to call[j+1]'s stack frame - s32e a2, a9, -8 // save a2 to call[j+1]'s stack frame - s32e a3, a9, -4 // save a3 to call[j+1]'s stack frame - s32e a4, a0, -32 // save a4 to call[j]'s stack frame - s32e a5, a0, -28 // save a5 to call[j]'s stack frame - s32e a6, a0, -24 // save a6 to call[j]'s stack frame - s32e a7, a0, -20 // save a7 to call[j]'s stack frame - rfwo // rotates back to call[i] position - - .size _WindowOverflow8, . - _WindowOverflow8 - - -// 8-Register Window Underflow Vector (Handler) -// -// Invoked by RETW returning from call[i+1] to call[i] -// where call[i]'s registers must be reloaded (not live in ARs); -// call[i] had done a call8 to call[i+1]. -// On entry here: -// window rotated to call[i] start point; -// a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; -// a8-a15 must be preserved (they are call[i+1].reg[0..7]); -// a9 is call[i+1]'s stack pointer. - - .org XCHAL_WINDOW_UF8_VECOFS - WINDOW_BASE_VECOFS -_WindowUnderflow8: - l32e a0, a9, -16 // restore a0 from call[i+1]'s stack frame - l32e a1, a9, -12 // restore a1 from call[i+1]'s stack frame - l32e a2, a9, -8 // restore a2 from call[i+1]'s stack frame - l32e a7, a1, -12 // a7 <- call[i-1]'s sp (used to find end of call[i]'s frame) - l32e a3, a9, -4 // restore a3 from call[i+1]'s stack frame - l32e a4, a7, -32 // restore a4 from call[i]'s stack frame - l32e a5, a7, -28 // restore a5 from call[i]'s stack frame - l32e a6, a7, -24 // restore a6 from call[i]'s stack frame - l32e a7, a7, -20 // restore a7 from call[i]'s stack frame - rfwu - - .size _WindowUnderflow8, . - _WindowUnderflow8 - - -// 12-Register Window Overflow Vector (Handler) -// -// Invoked if a call[i] referenced a register (a4-a15) -// that contains data from ancestor call[j]; -// call[j] had done a call12 to call[j+1]. -// On entry here: -// window rotated to call[j] start point; -// a0-a11 are registers to be saved; -// a12-a15 must be preserved; -// a13 is call[j+1]'s stack pointer. - - .org XCHAL_WINDOW_OF12_VECOFS - WINDOW_BASE_VECOFS -_WindowOverflow12: - hw_erratum_487_fix - s32e a0, a13, -16 // save a0 to call[j+1]'s stack frame - l32e a0, a1, -12 // a0 <- call[j-1]'s sp (used to find end of call[j]'s frame) - s32e a1, a13, -12 // save a1 to call[j+1]'s stack frame - s32e a2, a13, -8 // save a2 to call[j+1]'s stack frame - s32e a3, a13, -4 // save a3 to call[j+1]'s stack frame - s32e a4, a0, -48 // save a4 to end of call[j]'s stack frame - s32e a5, a0, -44 // save a5 to end of call[j]'s stack frame - s32e a6, a0, -40 // save a6 to end of call[j]'s stack frame - s32e a7, a0, -36 // save a7 to end of call[j]'s stack frame - s32e a8, a0, -32 // save a8 to end of call[j]'s stack frame - s32e a9, a0, -28 // save a9 to end of call[j]'s stack frame - s32e a10, a0, -24 // save a10 to end of call[j]'s stack frame - s32e a11, a0, -20 // save a11 to end of call[j]'s stack frame - rfwo // rotates back to call[i] position - - .size _WindowOverflow12, . - _WindowOverflow12 - - -// 12-Register Window Underflow Vector (Handler) -// -// Invoked by RETW returning from call[i+1] to call[i] -// where call[i]'s registers must be reloaded (not live in ARs); -// call[i] had done a call12 to call[i+1]. -// On entry here: -// window rotated to call[i] start point; -// a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; -// a12-a15 must be preserved (they are call[i+1].reg[0..3]); -// a13 is call[i+1]'s stack pointer. - - .org XCHAL_WINDOW_UF12_VECOFS - WINDOW_BASE_VECOFS -_WindowUnderflow12: - l32e a0, a13, -16 // restore a0 from call[i+1]'s stack frame - l32e a1, a13, -12 // restore a1 from call[i+1]'s stack frame - l32e a2, a13, -8 // restore a2 from call[i+1]'s stack frame - l32e a11, a1, -12 // a11 <- call[i-1]'s sp (used to find end of call[i]'s frame) - l32e a3, a13, -4 // restore a3 from call[i+1]'s stack frame - l32e a4, a11, -48 // restore a4 from end of call[i]'s stack frame - l32e a5, a11, -44 // restore a5 from end of call[i]'s stack frame - l32e a6, a11, -40 // restore a6 from end of call[i]'s stack frame - l32e a7, a11, -36 // restore a7 from end of call[i]'s stack frame - l32e a8, a11, -32 // restore a8 from end of call[i]'s stack frame - l32e a9, a11, -28 // restore a9 from end of call[i]'s stack frame - l32e a10, a11, -24 // restore a10 from end of call[i]'s stack frame - l32e a11, a11, -20 // restore a11 from end of call[i]'s stack frame - rfwu - - .size _WindowUnderflow12, . - _WindowUnderflow12 - - -# ifndef NO_SECTION_DIRECTIVES - //.end literal_prefix - .text -# endif - - -#endif /* XCHAL_HAVE_XEA2 && XCHAL_HAVE_WINDOWED && !defined(__XTENSA_CALL0_ABI__) */ - diff --git a/src/arch/xtensa/xtos/xtos-internal.h b/src/arch/xtensa/xtos/xtos-internal.h deleted file mode 100644 index 8a9c7ae361e1..000000000000 --- a/src/arch/xtensa/xtos/xtos-internal.h +++ /dev/null @@ -1,633 +0,0 @@ -/* - * xtos-internal.h -- internal definitions for single-threaded run-time - * - * Copyright (c) 2003-2010 Tensilica Inc. - * Copyright (c) 2019 Intel Corporation. All rights reserved. - * - * 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. - */ - -#ifndef XTOS_INTERNAL_H -#define XTOS_INTERNAL_H - -#include <config.h> -#if CONFIG_SMP -#include <sof/lib/cpu.h> -#endif -#include <sof/lib/memory.h> -#include <xtensa/config/core.h> -#include <xtensa/xtruntime.h> -#include <xtensa/xtruntime-frames.h> -#include <xtensa/xtensa-versions.h> -#ifndef XTOS_PARAMS_H /* this to allow indirect inclusion of this header from the outside */ -#include "xtos-params.h" -#endif - -/* Relative ordering of subpriorities within an interrupt level (or vector): */ -#define XTOS_SPO_ZERO_LO 0 /* lower (eg. zero) numbered interrupts are lower priority than higher numbered interrupts */ -#define XTOS_SPO_ZERO_HI 1 /* lower (eg. zero) numbered interrupts are higher priority than higher numbered interrupts */ - - -/* Sanity check some parameters from xtos-params.h: */ -#if XTOS_LOCKLEVEL < XCHAL_EXCM_LEVEL || XTOS_LOCKLEVEL > 15 -# error Invalid XTOS_LOCKLEVEL value, must be >= EXCM_LEVEL and <= 15, please fix xtos-params.h -#endif - -/* Mask of interrupts locked out at XTOS_LOCKLEVEL: */ -#define XTOS_LOCKOUT_MASK XCHAL_INTLEVEL_ANDBELOW_MASK(XTOS_LOCKLEVEL) -/* Mask of interrupts that can still be enabled at XTOS_LOCKLEVEL: */ -#define XTOS_UNLOCKABLE_MASK (0xFFFFFFFF-XTOS_LOCKOUT_MASK) - -/* Don't set this: */ -#define XTOS_HIGHINT_TRAMP 0 /* mapping high-pri ints to low-pri not auto-supported */ -#define XTOS_VIRTUAL_INTERRUPT XTOS_HIGHINT_TRAMP /* partially-virtualized INTERRUPT register not currently supported */ -#if XTOS_HIGHINT_TRAMP -# error Automatically-generated high-level interrupt trampolines are not presently supported. -#endif - -/* - * If single interrupt at level-one, sub-prioritization is irrelevant: - */ -#if defined(XCHAL_INTLEVEL1_NUM) -# undef XTOS_SUBPRI -# define XTOS_SUBPRI 0 /* override - only one interrupt */ -#endif - -/* - * In XEA1, the INTENABLE special register must be virtualized to provide - * standard XTOS functionality. - * In XEA2, this is only needed for software interrupt prioritization. - */ -#if XTOS_SUBPRI || XCHAL_HAVE_XEA1 -#define XTOS_VIRTUAL_INTENABLE 1 -#else -#define XTOS_VIRTUAL_INTENABLE 0 -#endif - -/* - * If single interrupt per priority, then fairness is irrelevant: - */ -#if (XTOS_SUBPRI && !XTOS_SUBPRI_GROUPS) || defined(XCHAL_INTLEVEL1_NUM) -# undef XTOS_INT_FAIRNESS -# define XTOS_INT_FAIRNESS 0 -#endif - -/* Identify special case interrupt handling code in int-lowpri-dispatcher.S: */ -#define XTOS_INT_SPECIALCASE (XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI && XTOS_INT_FAIRNESS == 0 && XTOS_SUBPRI_GROUPS == 0) - -/* - * Determine whether to extend the interrupt entry array: - */ -#define XIE_EXTEND (XTOS_VIRTUAL_INTENABLE && !XTOS_INT_SPECIALCASE) - -/* If we have the NSAU instruction, ordering of interrupts is reversed in xtos_interrupt_table[]: */ -#if XCHAL_HAVE_NSA -# define MAPINT(n) ((XCHAL_NUM_INTERRUPTS-1)-(n)) -# ifdef _ASMLANGUAGE - .macro mapint an - neg \an, \an - addi \an, \an, XCHAL_NUM_INTERRUPTS-1 - .endm -# endif -#else /* no NSA */ -# define MAPINT(n) (n) -# ifdef _ASMLANGUAGE - .macro mapint an - .endm -# endif -#endif - -#define XTOS_TASK_CONTEXT_OFFSET 48 - -#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) -/*********** Useful macros ***********/ - -/* - * A useful looping macro: - * 'iterate' invokes 'what' (an instruction, pseudo-op or other macro) - * multiple times, passing it a numbered parameter from 'from' to 'to' - * inclusively. Does not invoke 'what' at all if from > to. - * Maximum difference between 'from' and 'to' is 99 minus nesting depth - * (GNU 'as' doesn't allow nesting deeper than 100). - */ - .macro iterate from, to, what - .ifeq ((\to-\from) & ~0xFFF) - \what \from - iterate "(\from+1)", \to, \what - .endif - .endm // iterate - - - - // rsilft - // - // Execute RSIL \ar, \tolevel if \tolevel is different than \fromlevel. - // This way the RSIL is avoided if we know at assembly time that - // it will not change the level. Typically, this means the \ar register - // is ignored, ie. RSIL is used only to change PS.INTLEVEL. - // - .macro rsilft ar, fromlevel, tolevel -#if XCHAL_HAVE_INTERRUPTS - .if \fromlevel - \tolevel - rsil \ar, \tolevel - .endif -#endif - .endm - - - // Save LOOP and MAC16 registers, if configured, to the exception stack - // frame pointed to by address register \esf, using \aa and \ab as temporaries. - // - // This macro essentially saves optional registers that the compiler uses by - // default when present. - // Note that the acclo/acchi subset of MAC16 may be used even if others - // multipliers are present (e.g. mul16, mul32). - // - // Only two temp registers required for this code to be optimal (no interlocks) in both - // T10xx (Athens) and Xtensa LX microarchitectures (both 5 and 7 stage pipes): - // - .macro save_loops_mac16 esf, aa, ab -#if XCHAL_HAVE_LOOPS - rsr.lcount \aa - rsr.lbeg \ab - s32i \aa, \esf, UEXC_lcount - rsr.lend \aa - s32i \ab, \esf, UEXC_lbeg - s32i \aa, \esf, UEXC_lend -#endif -#if XCHAL_HAVE_MAC16 - rsr.acclo \aa - rsr.acchi \ab - s32i \aa, \esf, UEXC_acclo - s32i \ab, \esf, UEXC_acchi -# if XTOS_SAVE_ALL_MAC16 - rsr.m0 \aa - rsr.m1 \ab - s32i \aa, \esf, UEXC_mr + 0 - s32i \ab, \esf, UEXC_mr + 4 - rsr.m2 \aa - rsr.m3 \ab - s32i \aa, \esf, UEXC_mr + 8 - s32i \ab, \esf, UEXC_mr + 12 -# endif -#endif - .endm - - // Restore LOOP and MAC16 registers, if configured, from the exception stack - // frame pointed to by address register \esf, using \aa, \ab and \ac as temporaries. - // - // Three temp registers are required for this code to be optimal (no interlocks) in - // Xtensa LX microarchitectures with 7-stage pipe; otherwise only two - // registers would be needed. - // - .macro restore_loops_mac16 esf, aa, ab, ac -#if XCHAL_HAVE_LOOPS - l32i \aa, \esf, UEXC_lcount - l32i \ab, \esf, UEXC_lbeg - l32i \ac, \esf, UEXC_lend - wsr.lcount \aa - wsr.lbeg \ab - wsr.lend \ac -#endif -#if XCHAL_HAVE_MAC16 - l32i \aa, \esf, UEXC_acclo - l32i \ab, \esf, UEXC_acchi -# if XTOS_SAVE_ALL_MAC16 - l32i \ac, \esf, UEXC_mr + 0 - wsr.acclo \aa - wsr.acchi \ab - wsr.m0 \ac - l32i \aa, \esf, UEXC_mr + 4 - l32i \ab, \esf, UEXC_mr + 8 - l32i \ac, \esf, UEXC_mr + 12 - wsr.m1 \aa - wsr.m2 \ab - wsr.m3 \ac -# else - wsr.acclo \aa - wsr.acchi \ab -# endif -#endif - .endm - - -/* Offsets from _xtos_intstruct structure: */ - .struct 0 -#if XTOS_VIRTUAL_INTENABLE -XTOS_ENABLED_OFS: .space 4 /* _xtos_enabled variable */ -XTOS_VPRI_ENABLED_OFS: .space 4 /* _xtos_vpri_enabled variable */ -#endif -#if XTOS_VIRTUAL_INTERRUPT -XTOS_PENDING_OFS: .space 4 /* _xtos_pending variable */ -#endif - .text - - -#if XTOS_VIRTUAL_INTENABLE - // Update INTENABLE register, computing it as follows: - // INTENABLE = _xtos_enabled & _xtos_vpri_enabled - // [ & ~_xtos_pending ] - // - // Entry: - // register ax = &_xtos_intstruct - // register ay, az undefined (temporaries) - // PS.INTLEVEL set to XTOS_LOCKLEVEL or higher (eg. via xtos_lock) - // window overflows prevented (PS.WOE=0, PS.EXCM=1, or overflows - // already done for registers ax, ay, az) - // - // Exit: - // registers ax, ay, az clobbered - // PS unchanged - // caller needs to SYNC (?) for INTENABLE changes to take effect - // - // Note: in other software prioritization schemes/implementations, - // the term <_xtos_vpri_enabled> in the above expression is often - // replaced with another expression that computes the set of - // interrupts allowed to be enabled at the current software virtualized - // interrupt priority. - // - // For example, a simple alternative implementation of software - // prioritization for XTOS might have been the following: - // INTENABLE = _xtos_enabled & (vpri_enabled | UNLOCKABLE_MASK) - // which removes the need for the interrupt dispatcher to 'or' the - // UNLOCKABLE_MASK bits into _xtos_vpri_enabled, and lets other code - // disable all lockout level interrupts by just clearing _xtos_vpri_enabled - // rather than setting it to UNLOCKABLE_MASK. - // Other implementations sometimes use a table, eg: - // INTENABLE = _xtos_enabled & enable_table[current_vpri] - // The HAL (used by some 3rd party OSes) uses essentially a table-driven - // version, with other tables enabling run-time changing of priorities. - // - .macro xtos_update_intenable ax, ay, az - //movi \ax, _xtos_intstruct - l32i \ay, \ax, XTOS_VPRI_ENABLED_OFS // ay = _xtos_vpri_enabled - l32i \az, \ax, XTOS_ENABLED_OFS // az = _xtos_enabled - //interlock - and \az, \az, \ay // az = _xtos_enabled & _xtos_vpri_enabled -# if XTOS_VIRTUAL_INTERRUPT - l32i \ay, \ax, XTOS_PENDING_OFS // ay = _xtos_pending - movi \ax, -1 - xor \ay, \ay, \ax // ay = ~_xtos_pending - and \az, \az, \ay // az &= ~_xtos_pending -# endif - wsr.intenable \az - .endm -#endif /* VIRTUAL_INTENABLE */ - - .macro xtos_lock ax - rsil \ax, XTOS_LOCKLEVEL // lockout - .endm - - .macro xtos_unlock ax - wsr.ps \ax // unlock - rsync - .endm - -/* Offsets to XtosIntHandlerEntry structure fields (see below): */ -# define XIE_HANDLER 0 -# define XIE_ARG 4 -# define XIE_SIZE 8 -# if XIE_EXTEND -# define XIE_VPRIMASK (XIE_SIZE*XCHAL_NUM_INTERRUPTS+0) /* if VIRTUAL_INTENABLE [SUBPRI||XEA1] && !SPECIALCASE */ -# define XIE_LEVELMASK (XIE_SIZE*XCHAL_NUM_INTERRUPTS+4) /* [fairness preloop] if FAIRNESS && SUBPRI [&& SUBPRI_GROUPS] */ -# endif - -/* To simplify code: */ -# if XCHAL_HAVE_NSA -# define IFNSA(a,b) a -# else -# define IFNSA(a,b) b -# endif - - // get_prid ax - // Extracts core id. - .macro get_prid ax -#if XCHAL_HAVE_PRID - rsr.prid \ax - extui \ax, \ax, 0, 8 -#else - movi \ax, PLATFORM_MASTER_CORE_ID -#endif - .endm - -#if CONFIG_SMP - // xtos_stack_addr_percore_basic ax, ay, stack_name, stack_size - // Retrieves address of end of stack buffer for certain core to register ax. - .macro xtos_stack_addr_percore_basic ax, ay, stack_name, stack_size - get_prid \ax - addi \ax, \ax, 1 - movi \ay, \stack_size - mull \ax, \ax, \ay - movi \ay, \stack_name - add \ax, \ax, \ay - .endm - - // xtos_stack_addr_percore ax, ay, stack_master, stack_slave, stack_size - // Retrieves address of end of stack buffer for certain core to register ax. - .macro xtos_stack_addr_percore ax, ay, stack_master_addr, mem_blk_slave_addr, stack_size - get_prid \ax - bnei \ax, PLATFORM_MASTER_CORE_ID, core_s - movi \ax, \stack_master_addr - j exit -core_s: - addi \ax, \ax, -1 - movi \ay, _core_s_size - mull \ax, \ax, \ay - movi \ay, (HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE) - add \ax, \ax, \ay - movi \ay, \mem_blk_slave_addr - add \ax, \ax, \ay - j exit -exit: - movi \ay, \stack_size - add \ax, \ax, \ay - .endm - - // xtos_stack_addr_percore_add ax, stack_name, offset - // Pointer to dedicated interrupt stack + offset. - .macro xtos_stack_addr_percore_add ax, stack_name, offset - get_prid \ax - beqz \ax, core_0 - beqi \ax, 1, core_1 - beqi \ax, 2, core_2 - beqi \ax, 3, core_3 - j exit -core_0: - movi \ax, \stack_name\()0 + (\offset) - j exit -core_1: - movi \ax, \stack_name\()1 + (\offset) - j exit -core_2: - movi \ax, \stack_name\()2 + (\offset) - j exit -core_3: - movi \ax, \stack_name\()3 + (\offset) - j exit -exit: - .endm - - // xtos_addr_percore_add ax, symbol, offset - // Pointer to structure per core + offset. - .macro xtos_addr_percore_add ax, symbol, offset - xtos_addr_percore \ax, \symbol - addi \ax, \ax, \offset - .endm - - // xtos_addr_percore_sub ax, symbol, offset - // Pointer to structure per core - offset. - .macro xtos_addr_percore_sub ax, symbol, offset - xtos_addr_percore \ax, \symbol - addi \ax, \ax, -\offset - .endm -#endif /* CONFIG_SMP */ - - // xtos_addr_percore ax, structure_name - // Pointer to structure per core. - .macro xtos_addr_percore ax, structure_name -#if XCHAL_HAVE_THREADPTR - rur.threadptr \ax -#else - j 1f - .align 4 - .literal_position -2: - .word SOF_VIRTUAL_THREAD_BASE -1: - .align 4 - l32r \ax, 2b - l32i \ax, \ax, 0 -#endif - l32i \ax, \ax, XTOS_PTR_TO_\structure_name - .endm - - // xtos_store_percore ax, ay, structure_name - // Stores register value under the selected structure per core. - .macro xtos_store_percore ax, ay, structure_name -#if XCHAL_HAVE_THREADPTR - rur.threadptr \ay -#else - j 1f - .align 4 - .literal_position -2: - .word SOF_VIRTUAL_THREAD_BASE -1: - .align 4 - l32r \ay, 2b - l32i \ay, \ay, 0 -#endif - s32i \ax, \ay, XTOS_PTR_TO_\structure_name - .endm - - // xtos_int_stack_addr_percore ax, int_level, stack_name - // Pointer to dedicated interrupt stack. - .macro xtos_int_stack_addr_percore ax, int_level, stack_name -#if XCHAL_HAVE_THREADPTR - rur.threadptr \ax -#else - j 1f - .align 4 - .literal_position -2: - .word SOF_VIRTUAL_THREAD_BASE -1: - .align 4 - l32r \ax, 2b - l32i \ax, \ax, 0 -#endif - l32i \ax, \ax, XTOS_PTR_TO_\stack_name\()_&int_level - .endm - - // xtos_task_ctx_percore ax - // Pointer to structure per core. - .macro xtos_task_ctx_percore ax -#if XCHAL_HAVE_THREADPTR - rur.threadptr \ax -#else - j 1f - .align 4 - .literal_position -2: - .word SOF_VIRTUAL_THREAD_BASE -1: - .align 4 - l32r \ax, 2b - l32i \ax, \ax, 0 -#endif - l32i \ax, \ax, XTOS_TASK_CONTEXT_OFFSET - .endm - - // xtos_task_ctx_store_percore ax, ay - // Changes task context to point to the selected address. - .macro xtos_task_ctx_store_percore ax, ay -#if XCHAL_HAVE_THREADPTR - rur.threadptr \ay -#else - j 1f - .align 4 - .literal_position -2: - .word SOF_VIRTUAL_THREAD_BASE -1: - .align 4 - l32r \ay, 2b - l32i \ay, \ay, 0 -#endif - s32i \ax, \ay, XTOS_TASK_CONTEXT_OFFSET - .endm - - // Executes optional callback on wake up - .macro xtos_on_wakeup -#if CONFIG_WAKEUP_HOOK - call12 arch_interrupt_on_wakeup -#endif - .endm - -#else /* !_ASMLANGUAGE && !__ASSEMBLER__ */ - -/* - * Interrupt handler table entry. - * Unregistered entries have 'handler' point to xtos_unhandled_interrupt(). - */ -typedef struct XtosIntHandlerEntry { - _xtos_handler handler; - union { - void * varg; - int narg; - } u; -} XtosIntHandlerEntry; -# if XIE_EXTEND -typedef struct XtosIntMaskEntry { - unsigned vpri_mask; /* mask of interrupts enabled when this interrupt is taken */ - unsigned level_mask; /* mask of interrupts at this interrupt's level */ -} XtosIntMaskEntry; -# endif - -#if CONFIG_SMP -struct XtosIntStruct -{ - unsigned xtos_enabled; - unsigned vpri_enabled; -}; - -// XtosIntInterruptTable holds array of interrupt handler descriptors. -struct XtosIntInterruptTable -{ - struct XtosIntHandlerEntry array[XCHAL_NUM_INTERRUPTS]; -}; - -// XtosInterruptStructure describes layout of xtos interrupt structures per core -// generated for certain platform in file interrupt-table.S. -struct XtosInterruptStructure -{ - struct XtosIntStruct xtos_enabled; - struct XtosIntInterruptTable xtos_interrupt_table; - struct XtosIntMaskEntry xtos_interrupt_mask_table[XCHAL_NUM_INTERRUPTS]; - __attribute__((aligned(XCHAL_DCACHE_LINESIZE))) int al[0]; -}; -#endif - -extern void xtos_unhandled_interrupt(); - -#endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */ - -/* - * Notes... - * - * XEA1 and interrupt-SUBPRIoritization both imply virtualization of INTENABLE. - * Synchronous trampoloines imply partial virtualization of the INTERRUPT - * register, which in turn also implies virtualization of INTENABLE register. - * High-level interrupts manipulating the set of enabled interrupts implies - * at least a high XTOS_LOCK_LEVEL, although not necessarily INTENABLE virtualization. - * - * With INTENABLE register virtualization, at all times the INTENABLE - * register reflects the expression: - * (set of interrupts enabled) & (set of interrupts enabled by current - * virtual priority) - * - * Unrelated (DBREAK semantics): - * - * A[31-6] = DBA[3-6] - * --------------------- - * A[5-0] & DBC[5-C] & szmask - * - * = DBA[5-0] & szmask - * ^___ ??? - */ - - -/* Report whether the XSR instruction is available (conservative): */ -#define HAVE_XSR (XCHAL_HAVE_XEA2 || !XCHAL_HAVE_EXCEPTIONS) -/* - * This is more accurate, but not a reliable test in software releases prior to 6.0 - * (where the targeted hardware parameter was not explicit in the XPG): - * - *#define HAVE_XSR (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_T1040_0) - */ - - - -/* Macros for supporting hi-level and medium-level interrupt handling. */ - -#if XCHAL_NUM_INTLEVELS > 6 -#error Template files (*-template.S) limit support to interrupt levels <= 6 -#endif - -#if defined(__XTENSA_WINDOWED_ABI__) && XCHAL_HAVE_CALL4AND12 == 0 -#error CALL8-only is not supported! -#endif - -#define INTERRUPT_IS_HI(level) \ - ( XCHAL_HAVE_INTERRUPTS && \ - (XCHAL_EXCM_LEVEL < level) && \ - (XCHAL_NUM_INTLEVELS >= level) && \ - (XCHAL_HAVE_DEBUG ? XCHAL_DEBUGLEVEL != level : 1)) - -#define INTERRUPT_IS_MED(level) \ - (XCHAL_HAVE_INTERRUPTS && (XCHAL_EXCM_LEVEL >= level)) - - -#define _JOIN(x,y) x ## y -#define JOIN(x,y) _JOIN(x,y) - -#define _JOIN3(a,b,c) a ## b ## c -#define JOIN3(a,b,c) _JOIN3(a,b,c) - -#define LABEL(x,y) JOIN3(x,_INTERRUPT_LEVEL,y) -#define EXCSAVE_LEVEL JOIN(EXCSAVE_,_INTERRUPT_LEVEL) -#define INTLEVEL_VSIZE JOIN3(XSHAL_INTLEVEL,_INTERRUPT_LEVEL,_VECTOR_SIZE) - -/* For asm macros; works for positive a,b smaller than 1000: */ -#define GREATERTHAN(a, b) (((b) - (a)) & ~0xFFF) -#define EQUAL(a, b) ((1 << (a)) & (1 << (b))) - -#if CONFIG_SMP -// sizeof(xtos_enabled) -#define XTOS_ENABLED_SIZE_PER_CORE (4) -// sizeof(vpri_enabled) -#define XTOS_VPRI_ENABLED_SIZE_PER_CORE (4) -// sizeof(XtosIntStruct) -#define XTOS_INTSTRUCT_SIZE_PER_CORE (XTOS_ENABLED_SIZE_PER_CORE + \ - XTOS_VPRI_ENABLED_SIZE_PER_CORE) -#endif - -#endif /* XTOS_INTERNAL_H */ - diff --git a/src/arch/xtensa/xtos/xtos-params.h b/src/arch/xtensa/xtos/xtos-params.h deleted file mode 100644 index 334aba76d504..000000000000 --- a/src/arch/xtensa/xtos/xtos-params.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * xtos-params.h -- user-settable parameters for XTOS single-threaded run-time - * - * Copyright (c) 2002, 2004, 2006-2007 Tensilica 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. - */ - -#ifndef XTOS_PARAMS_H -#define XTOS_PARAMS_H - -/* - * IMPORTANT NOTE. - * This file contains XTOS parameters that may be modified - * according to needs. HOWEVER, any modifications are NOT - * supported. Handling of parameters other than the defaults - * provided in the original version of this file are for - * illustrative and educational purposes only. If you do - * change the parameters here-in (which requires rebuilding - * XTOS), please verify the resulting code extensively - * before even considering its use in production code. - * - * To rebuild XTOS, see instructions in the Xtensa System Software - * Reference Manual. The following sequence is no longer supported. - * - * cd <config_dir>/xtensa-elf/src/handlers - * xt-make clean - * xt-make - * xt-make install - * - * (Note: the last step installs the modified XTOS in *ALL* - * LSPs that normally include XTOS. You may prefer copying - * the generated files to your own custom LSP instead. Or - * better yet, also make a copy of all source files and maintain - * them somewhere completely separate -- which may require - * minor adjustments to the makefile.) - * - * PERFORMANCE TUNING: - * To slightly improve performance of interrupt dispatching, - * you can do some combination of the following: - * - change XTOS_SUBPRI to zero - * - change XTOS_SUBPRI_GROUPS to zero - * - change XTOS_SUBPRI_ORDER to XTOS_SPO_ZERO_HI - * - change XTOS_DEBUG_PC to zero - * - change XTOS_INT_FAIRNESS to zero - * - change XTOS_CNEST to zero - * There are non-trivial trade-offs in making such changes however, - * such as loss of support (see important note above), loss of - * interrupt scheduling fairness, loss of ability to traceback - * interrupt handlers across interrupted code when debugging them, - * loss of supported for nested C functions, etc. - */ - - -/* - * Lower LOCKLEVEL to XCHAL_EXCM_LEVEL for improved interrupt latency - * if you don't register C handlers for high-priority interrupts and your - * high-priority handlers don't touch INTENABLE nor virtual priorities. - * - * XTOS_LOCKLEVEL is less meaningful but still relevant if XEA2 and SUBPRI is zero, - * ie. if INTENABLE doesn't get virtualized (XTOS_VIRTUAL_INTENABLE not set); - * in this case, it is the interrupt level at which INTENABLE accesses are guarded, - * so that interrupt handlers up to this level can safely manipulate INTENABLE. - */ -#define XTOS_LOCKLEVEL XCHAL_NUM_INTLEVELS /* intlevel of INTENABLE register virtualization - (minimum is EXCM_LEVEL) */ - -/* - * NOTE: the following four parameters (SUBPRI, SUBPRI_GROUPS, SUBPRI_ORDER, INT_FAIRNESS) - * are irrelevant and ignored for interrupt vectors to which only one interrupt is mapped. - */ - -#define XTOS_SUBPRI 1 /* set to 0 if you don't need sub-prioritization - within level-one interrupts via software; - for XEA2 configs, this might improve performance of - certain sections of code, because INTENABLE register - virtualization becomes unnecessary in this case */ - -/* Ignored unless SUBPRI set: */ -#define XTOS_SUBPRI_GROUPS 1 /* 1 = support selective grouping of interrupts at the same priority */ - -#define XTOS_SUBPRI_ORDER XTOS_SPO_ZERO_LO /* one of XTOS_SPO_ZERO_LO, XTOS_SPO_ZERO_HI */ - -/* Ignored if SUBPRI set but SUBPRI_GROUPS is not (single interrupt per subpri), - * or if single interrupt configured at level/vector: */ -#define XTOS_INT_FAIRNESS 1 /* 1 = enable round-robin/fifo scheduling of interrupt - handlers of a given level or sub-priority */ - - -#define XTOS_DEBUG_PC 1 /* 1 = enable nice stack traceback showing interrupted code - when debugging interrupt or exception handler; - not implemented for high-priority handlers, or - for call0 ABI */ - -#define XTOS_CNEST 1 /* 1 = enable support for nested C functions - (save/restore nested C function call-chain pointer) */ - -/* Current compilers only use ACC (not MRn) when MAC16 is enabled, so you can leave this 0 for performance: */ -#define XTOS_SAVE_ALL_MAC16 0 /* set to save/restore MAC16 MRn registers */ - -/* Setting this might be useful to clear X's in hardware simulation a bit earlier, but - * should not be needed in production code: */ -#define XTOS_RESET_UNNEEDED 0 /* set to reset more registers than are really needed */ - -#endif /* XTOS_PARAMS_H */ - diff --git a/src/arch/xtensa/xtos/xtos-structs.h b/src/arch/xtensa/xtos/xtos-structs.h deleted file mode 100644 index 3a9997800644..000000000000 --- a/src/arch/xtensa/xtos/xtos-structs.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __XTOS_XTOS_STRUCTS_H__ -#define __XTOS_XTOS_STRUCTS_H__ - -#include "xtos-internal.h" -#include <sof/common.h> -#include <sof/lib/memory.h> -#include <config.h> -#include <xtensa/xtruntime-frames.h> -#include <stdint.h> - -struct idc; -struct notify; -struct schedulers; -struct task; - -struct thread_data { - xtos_structures_pointers xtos_ptrs; - volatile xtos_task_context *xtos_active_task; -}; - -struct xtos_core_data { -#if CONFIG_SMP - struct XtosInterruptStructure xtos_int_data; -#endif -#if CONFIG_INTERRUPT_LEVEL_1 - uint8_t xtos_stack_for_interrupt_1[SOF_STACK_SIZE] __aligned(16); -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - uint8_t xtos_stack_for_interrupt_2[SOF_STACK_SIZE] __aligned(16); -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - uint8_t xtos_stack_for_interrupt_3[SOF_STACK_SIZE] __aligned(16); -#endif -#if CONFIG_INTERRUPT_LEVEL_4 - uint8_t xtos_stack_for_interrupt_4[SOF_STACK_SIZE] __aligned(16); -#endif -#if CONFIG_INTERRUPT_LEVEL_5 - uint8_t xtos_stack_for_interrupt_5[SOF_STACK_SIZE] __aligned(16); -#endif - xtos_task_context xtos_interrupt_ctx; - uintptr_t xtos_saved_sp; - struct thread_data *thread_data_ptr; -}; - -struct core_context { - struct thread_data td; - struct task *main_task; - struct schedulers *schedulers; - struct notify *notify; - struct idc *idc; -}; - -#endif /* __XTOS_XTOS_STRUCTS_H__ */ diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 176795d0ff3b..29e602871af7 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -1,73 +1,184 @@ # SPDX-License-Identifier: BSD-3-Clause -if(NOT BUILD_LIBRARY) - add_local_sources(sof - host.c - pipeline.c - pipeline_static.c - component.c - buffer.c - channel_map.c - ) - if(CONFIG_COMP_VOLUME) - add_subdirectory(volume) +set(base_files + channel_map.c + component.c + source_api_helper.c + sink_api_helper.c + sink_source_utils.c + audio_stream.c + channel_map.c +) + +### Common actions for Zephyr/XTOS ### +if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) + # directories included unconditionally (alphabetical order) + add_subdirectory(buffers) + add_subdirectory(pcm_converter) + add_subdirectory(pipeline) + + if(CONFIG_COMP_BASEFW_IPC4 AND NOT CONFIG_LIBRARY) + add_local_sources(sof base_fw.c) endif() - if(CONFIG_COMP_SRC) - add_subdirectory(src) + add_local_sources_ifdef(CONFIG_IPC4_BASE_FW_INTEL sof base_fw_intel.c) + + # directories and files included conditionally (alphabetical order) + if(CONFIG_COMP_ARIA) + add_subdirectory(aria) + endif() + if(CONFIG_COMP_ASRC) + add_subdirectory(asrc) + endif() + if(CONFIG_COMP_COPIER) + add_subdirectory(copier) + endif() + if(CONFIG_COMP_CROSSOVER) + add_subdirectory(crossover) + endif() + if(CONFIG_COMP_DCBLOCK) + add_subdirectory(dcblock) + endif() + if(CONFIG_COMP_DRC) + add_subdirectory(drc) endif() if(CONFIG_COMP_FIR) add_subdirectory(eq_fir) endif() + if(CONFIG_COMP_IGO_NR) + add_subdirectory(igo_nr) + endif() if(CONFIG_COMP_IIR) add_subdirectory(eq_iir) endif() - if(CONFIG_COMP_TONE) - add_local_sources(sof - tone.c - ) + if(CONFIG_COMP_LEVEL_MULTIPLIER) + add_subdirectory(level_multiplier) + endif() + if(CONFIG_COMP_MFCC) + add_subdirectory(mfcc) endif() if(CONFIG_COMP_MIXER) - add_local_sources(sof - mixer.c - ) + add_subdirectory(mixer) + endif() + if(CONFIG_COMP_MIXIN_MIXOUT) + add_subdirectory(mixin_mixout) + endif() + if(CONFIG_COMP_MODULE_ADAPTER) + add_subdirectory(module_adapter) + endif() + if(CONFIG_COMP_MULTIBAND_DRC) + add_subdirectory(multiband_drc) endif() if(CONFIG_COMP_MUX) add_subdirectory(mux) endif() - if(CONFIG_COMP_SWITCH) - add_local_sources(sof - switch.c - ) + if(CONFIG_COMP_RTNR) + add_subdirectory(rtnr) endif() - if(CONFIG_COMP_DAI) - add_local_sources(sof - dai.c - ) + if(CONFIG_COMP_SEL) + add_subdirectory(selector) + endif() + if(CONFIG_COMP_SMART_AMP) + add_subdirectory(smart_amp) + endif() + if(CONFIG_COMP_SOUND_DOSE) + add_subdirectory(sound_dose) + endif() + if(CONFIG_COMP_SRC) + add_subdirectory(src) + endif() + if(CONFIG_COMP_STFT_PROCESS) + add_subdirectory(stft_process) + endif() + if(CONFIG_COMP_TDFB) + add_subdirectory(tdfb) endif() - if(CONFIG_COMP_KPB) + if(CONFIG_COMP_TEMPLATE) + add_subdirectory(template) + endif() + if(CONFIG_COMP_TENSORFLOW) + add_subdirectory(tensorflow) + endif() + if(CONFIG_COMP_UP_DOWN_MIXER) + add_subdirectory(up_down_mixer) + endif() + if(CONFIG_COMP_VOLUME) + add_subdirectory(volume) + endif() + if(CONFIG_DTS_CODEC) + add_subdirectory(codec) + endif() + # end of directories and files included conditionally (alphabetical order) + + add_subdirectory(google) + add_subdirectory(nxp) + + if(CONFIG_COMP_CHAIN_DMA) + add_local_sources(sof chain_dma.c) + endif() + if(CONFIG_COMP_KPB AND NOT CONFIG_LIBRARY_STATIC) add_local_sources(sof kpb.c ) endif() - if(CONFIG_COMP_SEL) - add_subdirectory(selector) + if(CONFIG_INTEL_ADSP_MIC_PRIVACY) + add_subdirectory(mic_privacy_manager) + endif() + if(CONFIG_COMP_TONE) + add_subdirectory(tone) endif() - if(CONFIG_COMP_TEST_KEYPHRASE) + if(CONFIG_ZEPHYR_NATIVE_DRIVERS) + list(APPEND base_files host-zephyr.c) + sof_list_append_ifdef(CONFIG_COMP_DAI base_files dai-zephyr.c) + else() + list(APPEND base_files host-legacy.c) + sof_list_append_ifdef(CONFIG_COMP_DAI base_files dai-legacy.c) + endif() +endif() + +### Common files (also used in shared library build) + +sof_list_append_ifdef(CONFIG_COMP_BLOB base_files data_blob.c) + +### (end of common files) + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + zephyr_library_sources( + ${base_files} + ) + + return() +elseif(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) + ### not shared library, e.g. testbench ### + + add_local_sources(sof + host-legacy.c + ${base_files} + ) + + if(CONFIG_COMP_DAI) add_local_sources(sof - detect_test.c + dai-legacy.c ) endif() - add_subdirectory(pcm_converter) - if(CONFIG_COMP_ASRC) - add_subdirectory(asrc) - endif() + return() endif() +### Shared library build (CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) ### + +subdirs(pipeline) + +if(CONFIG_COMP_MODULE_ADAPTER) + add_subdirectory(module_adapter) +endif() + add_local_sources(sof - pipeline.c - component.c - buffer.c + data_blob.c + buffers/comp_buffer.c + buffers/audio_buffer.c + ${base_files} ) # Audio Modules with various optimizaitons @@ -88,30 +199,68 @@ include(CheckCCompilerFlag) set(available_optimizations) # checks if flag is supported by compiler and sets needed flags -macro(check_optimization opt_name flag extra_define) +# note: to debug vectorisation please add "-fopt-info-vec-note" option after +# the enable command below. +macro(check_optimization opt_name flag enable_cmd extra_define) check_c_compiler_flag(${flag} compiles_flag_${opt_name}) if(compiles_flag_${opt_name}) list(APPEND available_optimizations ${opt_name}) - set(${opt_name}_flags ${flag} ${extra_define} -ffast-math -ftree-vectorizer-verbose=0) + set(${opt_name}_flags ${flag} ${extra_define} ${enable_cmd} -ffast-math) endif() endmacro() # modules will be compiled only for flags supported by compiler -check_optimization(sse42 -msse4.2 -DOPS_SSE42) -check_optimization(avx -mavx -DOPS_AVX) -check_optimization(avx2 -mavx2 -DOPS_AVX2) -check_optimization(fma -mfma -DOPS_FMA) -check_optimization(hifi2ep -mhifi2ep -DOPS_HIFI2EP) -check_optimization(hifi3 -mhifi3 -DOPS_HIFI3) +check_optimization(sse42 -msse4.2 -ftree-vectorize -DOPS_SSE42) +check_optimization(avx -mavx -ftree-vectorize -DOPS_AVX) +check_optimization(avx2 -mavx2 -ftree-vectorize -DOPS_AVX2) +check_optimization(fma -mfma -ftree-vectorize -DOPS_FMA) +check_optimization(hifi2ep -mhifi2ep "" -DOPS_HIFI2EP) +check_optimization(hifi3 -mhifi3 "" -DOPS_HIFI3) -set(sof_audio_modules volume src asrc eq-fir eq-iir) +set(sof_audio_modules mixer volume src asrc eq-fir eq-iir dcblock crossover tdfb drc multiband_drc mfcc mux) # sources for each module -set(volume_sources volume/volume.c volume/volume_generic.c) -set(src_sources src/src.c src/src_generic.c) +if(CONFIG_IPC_MAJOR_3) + set(volume_sources volume/volume.c volume/volume_generic.c volume/volume_ipc3.c) + set(asrc_sources asrc/asrc_ipc3.c) + set(src_sources src/src.c src/src_ipc3.c src/src_generic.c) + set(eq-iir_sources eq_iir/eq_iir_ipc3.c eq_iir/eq_iir_generic.c) + set(eq-fir_sources eq_fir/eq_fir_ipc3.c) + set(tdfb_sources tdfb/tdfb_ipc3.c) + set(tdfb_sources multiband_drc/multiband_drc_ipc3.c) + set(dcblock_sources dcblock/dcblock_ipc3.c) + set(mux_sources mux/mux_ipc3.c) + set(crossover_sources crossover/crossover_ipc3.c) +elseif(CONFIG_IPC_MAJOR_4) + set(volume_sources volume/volume.c volume/volume_generic.c volume/volume_ipc4.c) + set(asrc_sources asrc/asrc_ipc4.c) + set(src_sources src/src.c src/src_ipc4.c src/src_generic.c) + set(eq-iir_sources eq_iir/eq_iir_ipc4.c eq_iir/eq_iir_generic.c) + set(eq-fir_sources eq_fir/eq_fir_ipc4.c) + set(tdfb_sources tdfb/tdfb_ipc4.c) + set(tdfb_sources multiband_drc/multiband_drc_ipc4.c) + set(dcblock_sources dcblock/dcblock_ipc4.c) + set(mux_sources mux/mux_ipc4.c) + set(crossover_sources crossover/crossover_ipc4.c) +endif() + +if(CONFIG_IPC_MAJOR_3) + set(mixer_src mixer/mixer.c mixer/mixer_generic.c mixer/mixer_hifi3.c) +elseif(CONFIG_IPC_MAJOR_4) + set(mixer_src mixin_mixout/mixin_mixout.c mixin_mixout/mixin_mixout_generic.c mixin_mixout/mixin_mixout_hifi3.c) +endif() + +set(mixer_sources ${mixer_src}) set(asrc_sources asrc/asrc.c asrc/asrc_farrow.c asrc/asrc_farrow_generic.c) -set(eq-fir_sources eq_fir/eq_fir.c eq_fir/fir.c) -set(eq-iir_sources eq_iir/eq_iir.c eq_iir/iir.c eq_iir/iir_generic.c) +set(eq-fir_sources eq_fir/eq_fir.c eq_fir/eq_fir_generic.c) +set(eq-iir_sources eq_iir/eq_iir.c) +set(dcblock_sources dcblock/dcblock.c dcblock/dcblock_generic.c dcblock/dcblock_hifi4.c) +set(crossover_sources crossover/crossover.c crossover/crossover_generic.c) +set(tdfb_sources tdfb/tdfb.c tdfb/tdfb_generic.c tdfb/tdfb_direction.c) +set(drc_sources drc/drc.c drc/drc_generic.c drc/drc_math_generic.c) +set(multiband_drc_sources multiband_drc/multiband_drc_generic.c crossover/crossover.c drc/drc.c drc/drc_generic.c drc/drc_math_generic.c multiband_drc/multiband_drc.c ) +set(mfcc_sources mfcc/mfcc.c mfcc/mfcc_setup.c mfcc/mfcc_common.c mfcc/mfcc_generic.c mfcc/mfcc_hifi4.c mfcc/mfcc_hifi3.c) +set(mux_sources mux/mux.c mux/mux_generic.c) foreach(audio_module ${sof_audio_modules}) # first compile with no optimizations diff --git a/src/audio/Kconfig b/src/audio/Kconfig index b0f836557a53..1f7d362ffdc2 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -2,249 +2,361 @@ menu "Audio components" -config COMP_DAI - bool "DAI component" +config COMP_BASEFW_IPC4 + bool "BASEFW component" default y + depends on IPC_MAJOR_4 help - Select for DAI component + Select for BASEFW component -config COMP_VOLUME - bool "Volume component" - default y +config IPC4_BASE_FW_INTEL + bool "BASEFW component Intel vendor extensions" + depends on COMP_BASEFW_IPC4 help - Select for Volume component + Enable Intel vendor extensions for base firmware module. + This implements a set of additional IPC4 properties that + extend the base spec. -config COMP_SRC - bool "SRC component" +config HOST_DMA_RELOAD_DELAY_ENABLE + bool "Delay reloading DMA for host interfaces" default y help - Select for SRC component + When deep buffers are used the firmware does not need to have the + buffer refilled every millisecond. Select this option to enable longer + delays and to allow the memory controller to enter power saving modes. + +config HOST_DMA_RELOAD_THRESHOLD + int "DMA buffer threshold in milliseconds to reload DMA" + default 2 + depends on HOST_DMA_RELOAD_DELAY_ENABLE + help + The DMA buffer threshold in milliseconds to trigger host DMA + reloading. -config COMP_FIR - bool "FIR component" +config HOST_DMA_STREAM_SYNCHRONIZATION + bool "Stream DMA Transfers Synchronization" + default y if ACE + help + Enable synchronized Firmware Pointer Increment (FPI) register updates of HD-A gateways + belonging to a group defined by the driver. The driver may also specify an update period + for each group, different than the default one determined by the system tick frequency. + This feature will allow host lower power consumption in scenarios with deep buffering. + +config COMP_CHAIN_DMA + bool "Chain DMA component" + depends on IPC_MAJOR_4 + depends on DMA_INTEL_ADSP_HDA + help + Chain DMA support in hardware + +config XRUN_NOTIFICATIONS_ENABLE + bool "Enable xrun notification" default y + depends on IPC_MAJOR_4 help - Select for FIR component. FIR performance can differ between DSP - ISA and compiler used. FIR will perform best when MAC instructions - are available in ISA and are used by the compiler. i.e. xt-xcc on - xtensa will generate MAC instructions but GCC on xtensa won't. - Filter tap count can be severely restricted to reduce FIR cycles - and FIR performance for DSP/compilers with no MAC support + Enable xrun notifications sending to host -config COMP_IIR - bool "IIR component" +config IPC4_GATEWAY + bool "IPC4 Gateway" default y + depends on IPC_MAJOR_4 help - Select for IIR component + Select for IPC4 Gateway. IPC4 Gateway is used to transfer audio between + host and DSP without using DMA: via memory window (audio payload) and + IPC4 messages (set/get/flush commands). -config COMP_TONE - bool "Tone component" - default y +config MODULE_MAX_CONNECTIONS + int "Module maximum number of connected sink/source modules" + default 8 help - Select for Tone component + Specifies the maximum number of sink and source connections a module + may have to other modules. -config COMP_MIXER - bool "Mixer component" +config COMP_BLOB + bool "Large IPC data as compound message blobs" default y help - Select for Mixer component + Select to support sending large data blobs to firmware as + multiple IPC messages. Not all components or modules need + this. If unsure, say yes. -config COMP_MUX - bool "MUX component" - default y +config MODULE_MAX_BLOB_SIZE + int "Maximum IPC blob size in bytes" + default 8192 help - Select for MUX component + Specify the maximum size of IPC4 module blob data that can be + appended to each message. -config COMP_SWITCH - bool "Switch component" - default y +config COMP_STUBS + bool "Build all selected third-party (3P) components with stubs" help - Select for Switch component + Select to force all 3P blocks to link against stubs rather than their libraries. This + should only be used in testing environments like fuzzers or CI. config COMP_KPB bool "KPB component" default y help Select for KPB component +if COMP_KPB -config COMP_SEL - bool "Channel selector component" +config KPB_FORCE_COPY_TYPE_NORMAL + bool "KPB force copy type normal" default y help - Select for SEL component + Select this to force the kpb draining copy type to normal. + Unselecting this will keep the kpb sink copy type unchanged. -config COMP_TEST_KEYPHRASE - bool "KEYPHRASE_TEST component" - default y - help - Select for KEYPHRASE_TEST component. - Provides basic functionality for use in testing of keyphrase detection pipelines. +endif # COMP_KPB -config COMP_ASRC - bool "ASRC component" +config COMP_MODULE_ADAPTER + bool "Module adapter" default y help - Select for Asynchronous sample rate conversion (ASRC) - component. The ASRC has the capabilities of (synchronous) - SRC but can in addition track a slave DAI that is not in - sync with firmware timer. The ASRC can be setup for - synchronous operation without DAI tracking via topology - though it has a bit higher computational load than SRC. The - RAM footprint of ASRC is smaller than SRC because it does - not have pre-computed filter coefficients for every - conversion fraction that SRC does. + This component is an adapter between SoF components and any external third + party codecs/libraries. In order to make use of it the library itself should + be statically linked with the SoF FW binary image and the codec details, such as its + ID or specific methods provided in generic interface object located under + "src\include\sof\audio\module_adapter\interfaces.h". It is possible to link several + different codecs and use them in parallel. + +# --- Kconfig Sources (alphabetical order) --- +rsource "aria/Kconfig" +rsource "asrc/Kconfig" +rsource "codec/Kconfig" +rsource "copier/Kconfig" +rsource "crossover/Kconfig" +rsource "dcblock/Kconfig" +rsource "drc/Kconfig" +rsource "eq_fir/Kconfig" +rsource "eq_iir/Kconfig" +rsource "google/Kconfig" +rsource "igo_nr/Kconfig" +rsource "mfcc/Kconfig" +rsource "mixer/Kconfig" +rsource "mixin_mixout/Kconfig" +rsource "module_adapter/Kconfig" +rsource "multiband_drc/Kconfig" +rsource "mux/Kconfig" +rsource "nxp/Kconfig" +rsource "rtnr/Kconfig" +rsource "selector/Kconfig" +rsource "smart_amp/Kconfig" +rsource "sound_dose/Kconfig" +rsource "src/Kconfig" +rsource "stft_process/Kconfig" +rsource "tdfb/Kconfig" +rsource "template/Kconfig" +rsource "tensorflow/Kconfig" +rsource "tone/Kconfig" +rsource "up_down_mixer/Kconfig" +rsource "volume/Kconfig" +# --- End Kconfig Sources (alphabetical order) --- + +rsource "level_multiplier/Kconfig" -if COMP_ASRC +endmenu # "Audio components" -choice - prompt "ASRC down sampling conversions set" - default COMP_ASRC_DOWNSAMPLING_FULL +menu "Data formats" -config COMP_ASRC_DOWNSAMPLING_FULL - bool "Full downsampling conversions support" - select ASRC_SUPPORT_CONVERSION_24000_TO_08000 - select ASRC_SUPPORT_CONVERSION_24000_TO_16000 - select ASRC_SUPPORT_CONVERSION_48000_TO_08000 - select ASRC_SUPPORT_CONVERSION_48000_TO_11025 - select ASRC_SUPPORT_CONVERSION_48000_TO_12000 - select ASRC_SUPPORT_CONVERSION_48000_TO_16000 - select ASRC_SUPPORT_CONVERSION_48000_TO_22050 - select ASRC_SUPPORT_CONVERSION_48000_TO_24000 - select ASRC_SUPPORT_CONVERSION_48000_TO_32000 - select ASRC_SUPPORT_CONVERSION_48000_TO_44100 +config FORMAT_U8 + bool "Support U8" help - This option enables all supported downsampling conversions - for the asynchronous sample rate conversion. All the - upsampling conversions use the same filter always enabled - coefficients set so there is no configuration options for - them. The enabled conversions consume about 18 kB of memory. + Support unsigned 8 bit processing data format -config COMP_ASRC_DOWNSAMPLING_CUSTOM - bool "Custom downsampling conversions support" +config FORMAT_A_LAW + bool "Support A-law" help - This option used to manually select each downsampling ratio. - In order to optimize the text code size of the sample rate - converter, non-required conversion ratios can be - deactivated. Disregarding these settings, the sample rate - converter always supports all conversion ratios with fs_in - less or equal to fs_out. Therefore, it is possible to - deactivate all conversion ratios listed below, if we only - need an (asynchronous) 1:1 sample rate conversion, e.g, from - 16 kHz to 16 kHz. This option allows to trim down the coefficient - memory for conversion down from default 18 kB. Each conversion - needs about 2 kB. + Support 8 bit A-law processing data format. -endchoice - -menu "Supported downsampling conversions" - visible if COMP_ASRC_DOWNSAMPLING_CUSTOM - -config ASRC_SUPPORT_CONVERSION_24000_TO_08000 - bool "Downsample 24 kHz to 8 kHz" - default n +config FORMAT_MU_LAW + bool "Support mu-law" help - This option enables downsampling from 24 kHz to 8 kHz into - the build. The consumption of memory is 2.1 kB. + Support 8 bit mu-law processing data format. -config ASRC_SUPPORT_CONVERSION_24000_TO_16000 - bool "Downsample 24 kHz to 16 kHz" - default n +config FORMAT_S16LE + bool "Support S16LE" + default y help - This option enables downsampling from 24 kHz to 16 kHz into - the build. The consumption of memory is 1.9 kB. + Support 16 bit processing data format with sign and in little endian format -config ASRC_SUPPORT_CONVERSION_48000_TO_08000 - bool "Downsample 48 kHz to 8 kHz" - default n +config FORMAT_S24LE + bool "Support S24LE" + default y help - This option enables downsampling from 48 kHz to 8 kHz into - the build. The consumption of memory is 2.1 kB. + Support 24 bit processing data format with sign and in little endian format -config ASRC_SUPPORT_CONVERSION_48000_TO_11025 - bool "Downsample 48 kHz to 11.025 kHz" - default n +config FORMAT_S24_3LE + bool "Support S24_3LE" help - This option enables downsampling from 48 kHz to 11.025 kHz - into the build. The consumption of memory is 1.5 kB. + Support packed 24 bit processing data format with sign and in little endian format -config ASRC_SUPPORT_CONVERSION_48000_TO_12000 - bool "Downsample 48 kHz to 12 kHz" - default n +config FORMAT_S24_4LE_MSB + bool "Support S24_4LE_MSB" + default y help - This option enables downsampling from 48 kHz to 12 kHz into - the build. The consumption of memory is 1.5 kB. + Support 24 bit processing data format with sign and in msb 24 bits format -config ASRC_SUPPORT_CONVERSION_48000_TO_16000 - bool "Downsample 48 kHz to 16 kHz" - default n +config FORMAT_S32LE + bool "Support S32LE" + default y help - This option enables downsampling from 48 kHz to 16 kHz into - the build. The consumption of memory is 1.9 kB. - -config ASRC_SUPPORT_CONVERSION_48000_TO_22050 - bool "Downsample 48 kHz to 22.05 kHz" - default n - help - This option enables downsampling from 48 kHz to 22.05 kHz into - the build. The consumption of memory is 1.6 kB. + Support 32 bit processing data format with sign and in little endian format -config ASRC_SUPPORT_CONVERSION_48000_TO_24000 - bool "Downsample 48 kHz to 24 kHz" - default n +config FORMAT_FLOAT + bool "Support float" + default y help - This option enables downsampling from 48 kHz to 24 kHz into - the build. The consumption of memory is 1.6 kB. + Support floating point processing data format -config ASRC_SUPPORT_CONVERSION_48000_TO_32000 - bool "Downsample 48 kHz to 32 kHz" - default n +config FORMAT_CONVERT_HIFI3 + bool "HIFI3 optimized conversion" + default y help - This option enables downsampling from 48 kHz to 32 kHz into - the build. The consumption of memory is 1.9 kB. + Use HIFI3 extensions for optimized format conversion (experimental). -config ASRC_SUPPORT_CONVERSION_48000_TO_44100 - bool "Downsample 48 kHz to 44.1 kHz" - default n +config PCM_CONVERTER_FORMAT_U8 + bool "Support U8" help - This option enables downsampling from 48 kHz to 44.1 kHz - into the build. The consumption of memory is 1.8 kB. + Support 8 bit processing data format without sign -endmenu # "Downsampling ratios" - -endif # COMP_ASRC - -endmenu # "Audio components" +config PCM_CONVERTER_FORMAT_A_LAW + bool "Support A-law" + select MATH_A_LAW_CODEC + help + Support 8 bit A-law data format. -menu "Data formats" +config PCM_CONVERTER_FORMAT_MU_LAW + bool "Support mu-law" + select MATH_MU_LAW_CODEC + help + Support 8 bit mu-law data format. -config FORMAT_S16LE +config PCM_CONVERTER_FORMAT_S16LE bool "Support S16LE" default y help Support 16 bit processing data format with sign and in little endian format -config FORMAT_S24LE +config PCM_CONVERTER_FORMAT_S24LE bool "Support S24LE" default y help Support 24 bit processing data format with sign and in little endian format -config FORMAT_S32LE +config PCM_CONVERTER_FORMAT_S24_4LE_MSB + bool "Support S24_4LE_MSB" + default y + help + Support 24 bit processing data format with sign and in msb 24 bits format + +config PCM_CONVERTER_FORMAT_S24_3LE + bool "Support S24_3LE" + help + Support packed 24 bit processing data format with sign and in little endian format + +config PCM_CONVERTER_FORMAT_S32LE bool "Support S32LE" default y help Support 32 bit processing data format with sign and in little endian format -config FORMAT_FLOAT +config PCM_CONVERTER_FORMAT_S16_4LE + bool "Support S16_4LE" + default y + help + Support the format of signed 16-bit little-endian in the 2 lower bytes + of a 32-bit container. This format is used, for example, by the SSP gateway. + +config PCM_CONVERTER_FORMAT_FLOAT bool "Support float" default y help Support floating point processing data format -config FORMAT_CONVERT_HIFI3 +config PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32 + bool "Support S16C16 <-> S16C32" + help + Support conversion between 16 bit valid sample size in 16 bit container + and 16 bit valid sample size in 32 bit container + +config PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32 + bool "Support S16C32 <-> S32C32" + help + Support conversion between 16 bit valid sample size in 32 bit container + and 32 bit valid sample size in 32 bit container + +config PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32 + bool "Support S16C32 <-> S24C32" + help + Support conversion between 16 bit valid sample size in 32 bit container + and 24 bit valid sample size in 32 bit container + +config PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32 + bool "Support S24C24 <-> S24C32" + help + Support conversion between 24 bit valid sample size in 24 bit container + and 24 bit valid sample size in 32 bit container + +config PCM_CONVERTER_FORMAT_S24_C32_AND_S24_C24 + bool "Support S24C32 <-> S24C24" + help + Support conversion between 24 bit valid sample size in 32 bit container + and 24 bit valid sample size in 24 bit container + +config PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32 + bool "Support S16C32 <-> S16C32" + help + Support one-to-one copying conversion for 16 bit valid sample size in + 32 bit container + +config PCM_CONVERTER_FORMAT_CONVERT_HIFI3 bool "HIFI3 optimized conversion" default y help Use HIFI3 extensions for optimized format conversion (experimental). +config PCM_REMAPPING_CONVERTERS + bool "Channel remapping conversions" + default y + depends on IPC_MAJOR_4 + help + Enable conversion functions that perform both format conversion + and channel remapping simultaneously. + +config TRACE_CHANNEL + int "TRACE DMA Channel configuration" + default 0 + help + This option is used for custom configuration of trace dma channel other + than zero dma channel.Define macro DMA_TRACE_CHANNEL in platform to + configure the required channel number. + +config WRAP_ACTUAL_POSITION + bool "Buffer wrapping" + help + This option is to update the actual position information on wrap of buffer. + It is not necessary that on wrap, the buffer position would be zero.At wrap, + in some cases based on the period size, the frame may not exactly be at the + end of the buffer and roll over for some bytes from the beginning of the buffer. + +config COMP_MODULE_SHARED_LIBRARY_BUILD + bool "Build SOF modules as shared libraries" + help + Select if you want to build modules as shared objects that can be used to run + pipelines on the host with the testbench or the ALSA plugin. + +config DISABLE_DESCRIPTOR_SPLIT + bool "Disable descriptor split" + help + This option disbale the descriptor split for host p-table. + +config DAI_VERBOSE_GLITCH_WARNINGS + bool "Enable additional checks and warnings for DAI data flow" + help + Select if you want to enable additional checks and warning logs for + DAI data flow. If DAI copy is called with no data to process, + always emit a warning. This option useful to debug issues with + DAI DMA operation and issues with low-latency scheduling. + endmenu diff --git a/src/audio/aria/CMakeLists.txt b/src/audio/aria/CMakeLists.txt new file mode 100644 index 000000000000..f967fbbea895 --- /dev/null +++ b/src/audio/aria/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_ARIA STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/aria_llext) + add_dependencies(app aria) +else() + add_local_sources(sof aria.c aria_hifi5.c aria_hifi3.c aria_generic.c) +endif() diff --git a/src/audio/aria/Kconfig b/src/audio/aria/Kconfig new file mode 100644 index 000000000000..51b9cfa3381d --- /dev/null +++ b/src/audio/aria/Kconfig @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_ARIA + tristate "ARIA component" + default m if LIBRARY_DEFAULT_MODULAR + depends on IPC_MAJOR_4 + help + Select for Automatic Regressive Input Amplifier Module component + ARIA applies variable gain into incoming signal. Target gain is + 0, 6, 12, 18 dB with allowed configuration parameter values + 0, 1, 2, 3. Gain is reduced from target with high level signals + to avoid clipping. Currently ARIA introduces gain transition and + algorithmic latency equal to 1 ms. + +choice + prompt "ARIA HIFI level" + depends on COMP_ARIA + default ARIA_HIFI_MAX + +config ARIA_HIFI_MAX + bool "Max level available in the toolchain" + +config ARIA_HIFI_4 + bool "HIFI4 ARIA" + +config ARIA_HIFI_3 + bool "HIFI3 ARIA" + +config ARIA_HIFI_NONE + bool "Generic ARIA, no HIFI" + +endchoice diff --git a/src/audio/aria/README.md b/src/audio/aria/README.md new file mode 100644 index 000000000000..99dcc595ac6d --- /dev/null +++ b/src/audio/aria/README.md @@ -0,0 +1,23 @@ +# Aria Audio Component Architecture + +This directory contains the implementation of the Aria audio component. + +## Overview + +The Aria component implements an automatic regressive input amplifier that applies variable input gain, reducing gain for high-level signals to prevent clipping while introducing about 1 ms of processing latency. + +## Architecture Diagram + +```mermaid +graph LR + In[Input Data] --> Aria[Aria Core Processing] + Aria --> Out[Output Data] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the ARIA (Automatic Regressive Input Amplifier Module) component. It applies a variable gain (target: 0, 6, 12, 18 dB) that is reduced for high-level signals to prevent clipping, introducing a 1ms latency. Users can choose HIFI optimization levels (HIFI3, HIFI4, Max, Generic). +- **CMakeLists.txt**: Handles the build integration. Depends on `IPC_MAJOR_4`. If built modularly (`CONFIG_COMP_ARIA="m"`), it uses a loadable extension (`llext`); otherwise, it compiles `aria.c` and HIFI-specific files locally. +- **aria.toml**: Defines the topology parameters for the module (UUID, affinity, pin configuration) and an array of `mod_cfg` configurations defining processing constraints for various setups. +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/aria.conf`, it defines the `aria` widget object for topology generation. It exposes attributes like `cpc` (cycles per chunk) and `is_pages`. It sets up an `extctl` byte control with a maximum payload of 4096 bytes and defaults to UUID `6d:16:f7:99:2c:37:ef:43:81:f6:22:00:7a:a1:5f:03` (type `effect`). +- **MATLAB Tuning (`tune/`)**: Contains `.m` scripts (e.g., `sof_aria_blobs.m`) which generate ALSA control binary blobs, text formats, and M4 configuration fragments used at topology creation or runtime to supply operational parameters like attenuation settings (e.g., `param_1.conf`, `param_2.conf`). diff --git a/src/audio/aria/aria.c b/src/audio/aria/aria.c new file mode 100644 index 000000000000..dc265cfac240 --- /dev/null +++ b/src/audio/aria/aria.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc4/fw_reg.h> +#include <ipc/dai.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include "aria.h" + +#define ARIA_SET_ATTENUATION 1 + +LOG_MODULE_REGISTER(aria, CONFIG_SOF_LOG_LEVEL); + +/* these ids aligns windows driver requirement to support windows driver */ +SOF_DEFINE_REG_UUID(aria); + +/** + * \brief Aria gain index mapping table + */ +const int32_t sof_aria_index_tab[] = { + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 0, 1, + 2, 3, 4, 5, + 6, 7, 8, 9, + 0, 1, 2, 3 +}; + +static size_t get_required_emory(size_t chan_cnt, size_t smpl_group_cnt) +{ + /* Current implementation is able to apply 1 ms transition */ + /* internal circular buffer aligned to 8 bytes */ + const size_t num_of_ms = 1; + + return ALIGN_UP(num_of_ms * chan_cnt * smpl_group_cnt, 2) * sizeof(int32_t); +} + +static void aria_set_gains(struct aria_data *cd) +{ + int i; + + for (i = 0; i < ARIA_MAX_GAIN_STATES; ++i) + cd->gains[i] = (1ULL << (32 - cd->att - 1)) - 1; +} + +static int aria_algo_init(struct aria_data *cd, void *buffer_desc, + size_t att, size_t chan_cnt, size_t smpl_group_cnt) +{ + cd->chan_cnt = chan_cnt; + cd->smpl_group_cnt = smpl_group_cnt; + /* ensures buffer size is aligned to 8 bytes */ + cd->buff_size = ALIGN_UP(cd->chan_cnt * cd->smpl_group_cnt, 2); + cd->offset = (cd->chan_cnt * cd->smpl_group_cnt) & 1; + cd->att = att; + cd->data_addr = buffer_desc; + cd->data_ptr = cd->data_addr + cd->offset; + cd->data_end = cd->data_addr + cd->buff_size; + cd->buff_pos = 0; + + aria_set_gains(cd); + + memset((void *)cd->data_addr, 0, sizeof(int32_t) * cd->buff_size); + cd->gain_state = 0; + + return 0; +} + +static inline void aria_process_data(struct processing_module *mod, + struct audio_stream *source, + struct audio_stream *sink, + size_t frames) +{ + struct aria_data *cd = module_get_private_data(mod); + size_t data_size = audio_stream_frame_bytes(source) * frames; + size_t sample_size = audio_stream_get_channels(source) * frames; + + if (cd->att) { + aria_algo_calc_gain(cd, sof_aria_index_tab[cd->gain_state + 1], source, frames); + cd->aria_get_data(mod, sink, frames); + } else { + /* bypass processing gets unprocessed data from buffer */ + cir_buf_copy(cd->data_ptr, cd->data_addr, cd->data_end, + sink->w_ptr, sink->addr, sink->end_addr, + data_size); + } + + cir_buf_copy(source->r_ptr, source->addr, source->end_addr, + cd->data_ptr, cd->data_addr, cd->data_end, + data_size); + cd->data_ptr = cir_buf_wrap(cd->data_ptr + sample_size, cd->data_addr, cd->data_end); +} + +static int aria_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *mod_data = &mod->priv; + struct ipc4_base_module_cfg *base_cfg = &mod_data->cfg.base_cfg; + const struct ipc4_aria_module_cfg *aria = mod_data->cfg.init_data; + struct aria_data *cd; + size_t ibs, chc, sgs, sgc, req_mem, att; + void *buf; + + comp_info(dev, "entry"); + + list_init(&dev->bsource_list); + list_init(&dev->bsink_list); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) { + return -ENOMEM; + } + + ibs = base_cfg->ibs; + chc = base_cfg->audio_fmt.channels_count; + sgs = (base_cfg->audio_fmt.depth >> 3) * chc; + sgc = ibs / sgs; + req_mem = get_required_emory(chc, sgc); + att = aria->attenuation; + + if (aria->attenuation > ARIA_MAX_ATT) { + comp_warn(dev, "Attenuation value %d must not be greater than %d", + att, ARIA_MAX_ATT); + att = ARIA_MAX_ATT; + } + mod_data->private = cd; + + buf = mod_balloc(mod, req_mem); + + if (!buf) { + mod_free(mod, cd); + comp_err(dev, "allocation failed for size %d", req_mem); + return -ENOMEM; + } + + return aria_algo_init(cd, buf, att, chc, sgc); +} + +static int aria_free(struct processing_module *mod) +{ + struct aria_data *cd = module_get_private_data(mod); + + mod_free(mod, cd->data_addr); + mod_free(mod, cd); + return 0; +} + +static void aria_set_stream_params(struct comp_buffer *buffer, + struct processing_module *mod) +{ + const struct ipc4_audio_format *audio_fmt = &mod->priv.cfg.base_cfg.audio_fmt; + + ipc4_update_buffer_format(buffer, audio_fmt); +} + +static int aria_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + int ret; + struct comp_buffer *source, *sink; + struct comp_dev *dev = mod->dev; + struct aria_data *cd = module_get_private_data(mod); + + comp_info(dev, "entry"); + + source = comp_dev_get_first_data_producer(dev); + sink = comp_dev_get_first_data_consumer(dev); + if (!source || !sink) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + + aria_set_stream_params(source, mod); + aria_set_stream_params(sink, mod); + audio_stream_set_align(SOF_FRAME_BYTE_ALIGN, SOF_FRAME_COUNT_ALIGN, &source->stream); + + if (audio_stream_get_valid_fmt(&source->stream) != SOF_IPC_FRAME_S24_4LE || + audio_stream_get_valid_fmt(&sink->stream) != SOF_IPC_FRAME_S24_4LE) { + comp_err(dev, "format is not supported"); + return -EINVAL; + } + + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state."); + 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; + + cd->aria_get_data = aria_algo_get_data_func(mod); + + return 0; +} + +static int aria_reset(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct aria_data *cd = module_get_private_data(mod); + int idx; + + comp_info(dev, "entry"); + + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "aria module is in active state. Ignore resetting"); + return 0; + } + + for (idx = 0; idx < ARIA_MAX_GAIN_STATES; ++idx) + cd->gains[idx] = (1ULL << (32 - cd->att - 1)) - 1; + + memset(cd->data_addr, 0, sizeof(int32_t) * cd->buff_size); + cd->gain_state = 0; + + return 0; +} + + +static int aria_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) +{ + /* Aria algo supports only 4-bytes containers */ + struct aria_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint32_t copy_bytes; + uint32_t frames = input_buffers[0].size; + + comp_dbg(dev, "entry"); + + frames = MIN(frames, cd->smpl_group_cnt); + + /* Aria won't change the stream format and channels, so sink and source + * has the same bytes to produce and consume. + */ + copy_bytes = frames * audio_stream_frame_bytes(input_buffers[0].data); + if (copy_bytes == 0) + return 0; + + aria_process_data(mod, input_buffers[0].data, output_buffers[0].data, frames); + + input_buffers[0].consumed = copy_bytes; + output_buffers[0].size = copy_bytes; + + return 0; +} + +static int aria_set_config(struct processing_module *mod, uint32_t param_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 aria_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_info(dev, "entry"); + if (param_id == ARIA_SET_ATTENUATION) { + if (fragment_size != sizeof(uint32_t)) { + comp_err(dev, "Illegal fragment_size = %d", fragment_size); + return -EINVAL; + } + memcpy_s(&cd->att, sizeof(uint32_t), fragment, sizeof(uint32_t)); + if (cd->att > ARIA_MAX_ATT) { + comp_warn(dev, + "Attenuation parameter %d is limited to %d", + cd->att, ARIA_MAX_ATT); + cd->att = ARIA_MAX_ATT; + } + aria_set_gains(cd); + } else { + comp_err(dev, "Illegal param_id = %d", param_id); + return -EINVAL; + } + + return 0; +} + +static const struct module_interface aria_interface = { + .init = aria_init, + .prepare = aria_prepare, + .process_audio_stream = aria_process, + .reset = aria_reset, + .free = aria_free, + .set_configuration = aria_set_config, +}; + +#if CONFIG_COMP_ARIA_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("ARIA", &aria_interface, 1, SOF_REG_UUID(aria), 8); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(aria_comp_tr, SOF_UUID(aria_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(aria_interface, aria_uuid, aria_comp_tr); +SOF_MODULE_INIT(aria, sys_comp_module_aria_interface_init); + +#endif diff --git a/src/audio/aria/aria.h b/src/audio/aria/aria.h new file mode 100644 index 000000000000..368520b43f40 --- /dev/null +++ b/src/audio/aria/aria.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + */ + +/** + * \file aria.h + * \brief Aria component header file + * \authors Adrian Bonislawski <adrian.bonislawski@intel.com> + */ + +#ifndef __SOF_AUDIO_ARIA_H__ +#define __SOF_AUDIO_ARIA_H__ + +#include <sof/audio/component_ext.h> +#include <sof/audio/ipc-config.h> +#include <sof/compiler_attributes.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <sof/trace/trace.h> +#include <ipc/stream.h> +#include <ipc4/module.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc4/base-config.h> +#include <user/trace.h> +#include <stddef.h> +#include <stdint.h> + +/** \brief Aria max gain states */ +#define ARIA_MAX_GAIN_STATES 10 + +/** \brief Aria max att value */ +#define ARIA_MAX_ATT 3 + +/** + * \brief aria get data function interface + */ +typedef void (*aria_get_data_func)(struct processing_module *mod, + struct audio_stream *sink, int frames); + +struct aria_data; +/** + * \brief Aria gain processing function + */ +void aria_algo_calc_gain(struct aria_data *cd, size_t gain_idx, + struct audio_stream *source, int frames); + +aria_get_data_func aria_algo_get_data_func(struct processing_module *mod); + +/** + * \brief Aria component private data. + */ +struct aria_data { + /* channels count */ + size_t chan_cnt; + /* sample groups to process count */ + size_t smpl_group_cnt; + /* Size of chunk (1ms) in samples */ + size_t buff_size; + /* Current gain state */ + size_t gain_state; + /* current data position in circular buffer */ + size_t buff_pos; + /* Attenuation parameter */ + uint32_t att; + /* Gain states */ + int32_t gains[ARIA_MAX_GAIN_STATES]; + /* cyclic buffer pointer data */ + int32_t *data_ptr; + /* cyclic buffer end address of data */ + int32_t *data_end; + /* cyclic buffer start address of data */ + int32_t *data_addr; + + /* internal buffer offset helps to keep algorithmic delay constant */ + size_t offset; + + aria_get_data_func aria_get_data; +}; + +struct ipc4_aria_module_cfg { + struct ipc4_base_module_cfg base_cfg; + uint32_t attenuation; +} __packed __aligned(8); + +#endif /* __SOF_AUDIO_ARIA_H__ */ diff --git a/src/audio/aria/aria.toml b/src/audio/aria/aria.toml new file mode 100644 index 000000000000..f40ac691d3aa --- /dev/null +++ b/src/audio/aria/aria.toml @@ -0,0 +1,30 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Aria module config + [[module.entry]] + name = "ARIA" + uuid = UUIDREG_STR_ARIA + affinity_mask = "0x1" + instance_count = "8" + domain_types = "0" + load_type = LOAD_TYPE + init_config = "1" + module_type = "30" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # 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, 260, 1063000, 16, 21, 0, 0, 0, + 1, 0, 0, 0, 260, 1873500, 192, 256, 0, 0, 0, + 2, 0, 0, 0, 260, 2680000, 32, 42, 0, 0, 0, + 3, 0, 0, 0, 260, 3591000, 64, 85, 0, 0, 0, + 4, 0, 0, 0, 260, 4477000, 96, 128, 0, 0, 0, + 5, 0, 0, 0, 260, 7195000, 192, 192, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/aria/aria_generic.c b/src/audio/aria/aria_generic.c new file mode 100644 index 000000000000..93ec0f308dfe --- /dev/null +++ b/src/audio/aria/aria_generic.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. + +#include "aria.h" + +#if SOF_USE_HIFI(NONE, ARIA) + +extern const int32_t sof_aria_index_tab[]; + +inline void aria_algo_calc_gain(struct aria_data *cd, size_t gain_idx, + struct audio_stream *source, int frames) +{ + int32_t max_data = 0; + int32_t sample_abs; + uint32_t att = cd->att; + int64_t gain = (1ULL << (att + 32)) - 1; + int samples = frames * audio_stream_get_channels(source); + int32_t *src = audio_stream_get_rptr(source); + int i, n; + + while (samples) { + n = audio_stream_samples_without_wrap_s32(source, src); + n = MIN(samples, n); + for (i = 0; i < n; i++) { + sample_abs = ABS(sign_extend_s24(src[i])); + max_data = MAX(max_data, sample_abs); + } + + src = audio_stream_wrap(source, src + n); + samples -= n; + } + /*zero check for maxis not needed since att is in range <0;3>*/ + if (max_data > (0x007fffff >> att)) + gain = (0x007fffffULL << 32) / max_data; + + cd->gains[gain_idx] = (int32_t)(gain >> (att + 1)); +} + +static void aria_algo_get_data(struct processing_module *mod, + struct audio_stream *sink, int frames) +{ + struct aria_data *cd = module_get_private_data(mod); + int32_t step, in_sample; + int32_t gain_state_add_2 = cd->gain_state + 2; + int32_t gain_state_add_3 = cd->gain_state + 3; + int32_t gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2]]; + /* do linear approximation between points gain_begin and gain_end */ + int32_t gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3]]; + int32_t m, n, i, ch; + int32_t samples = frames * audio_stream_get_channels(sink); + int32_t *out = audio_stream_get_wptr(sink); + int32_t *in = cd->data_ptr; + int32_t gain; + const int ch_n = cd->chan_cnt; + const int shift = 31 - cd->att; + + for (i = 1; i < ARIA_MAX_GAIN_STATES - 1; i++) { + if (cd->gains[sof_aria_index_tab[gain_state_add_2 + i]] < gain_begin) + gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2 + i]]; + if (cd->gains[sof_aria_index_tab[gain_state_add_3 + i]] < gain_end) + gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3 + i]]; + } + step = (gain_end - gain_begin) / frames; + gain = gain_begin; + + while (samples) { + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, samples); + m = cir_buf_samples_without_wrap_s32(cd->data_ptr, cd->data_end); + n = MIN(m, n); + for (i = 0; i < n; i += ch_n) { + for (ch = 0; ch < ch_n; ch++) { + in_sample = sign_extend_s24(*in++); + out[ch] = q_multsr_sat_32x32_24(in_sample, gain, shift); + } + gain += step; + out += ch_n; + } + samples -= n; + in = cir_buf_wrap(in, cd->data_addr, cd->data_end); + out = audio_stream_wrap(sink, out); + } + cd->gain_state = sof_aria_index_tab[cd->gain_state + 1]; +} + +aria_get_data_func aria_algo_get_data_func(struct processing_module *mod) +{ + return aria_algo_get_data; +} +#endif diff --git a/src/audio/aria/aria_hifi3.c b/src/audio/aria/aria_hifi3.c new file mode 100644 index 000000000000..21fe7e82fffe --- /dev/null +++ b/src/audio/aria/aria_hifi3.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. + +#include "aria.h" + +#if SOF_USE_HIFI(3, ARIA) || SOF_USE_HIFI(4, ARIA) +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi3.h> + +extern const int32_t sof_aria_index_tab[]; + +inline void aria_algo_calc_gain(struct aria_data *cd, size_t gain_idx, + struct audio_stream *source, int frames) +{ + /* detecting maximum value in data chunk */ + ae_int32x2 in_sample; + ae_int32x2 max_data = AE_ZERO32(); + int32_t att = cd->att; + ae_valign inu = AE_ZALIGN64(); + uint64_t gain = (1ULL << (att + 32)) - 1; + int32_t *max_ptr = (int32_t *)&max_data; + int32_t max; + int samples = frames * audio_stream_get_channels(source); + ae_int32x2 *in = audio_stream_get_rptr(source); + int i, n, m; + + while (samples) { + n = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(samples, n); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + max_data = AE_MAXABS32S(max_data, AE_SLAI32(in_sample, 8)); + } + if (n & 1) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + max_data = AE_MAXABS32S(max_data, AE_SLAI32(in_sample, 8)); + } + in = audio_stream_wrap(source, in); + samples -= n; + } + + max = MAX(max_ptr[0], max_ptr[1]) >> 8; + + /*zero check for maxis not needed since att is in range <0;3>*/ + if (max > (0x007fffff >> att)) + gain = (0x007fffffULL << 32) / max; + + /* normalization by attenuation factor to obtain fractional range <1 / (2 pow att), 1> */ + cd->gains[gain_idx] = (int32_t)(gain >> (att + 1)); +} + +static void aria_algo_get_data_odd_channel(struct processing_module *mod, + struct audio_stream *sink, + int frames) +{ + struct aria_data *cd = module_get_private_data(mod); + size_t i, m, n, ch; + ae_int32x2 step; + int32_t gain_state_add_2 = cd->gain_state + 2; + int32_t gain_state_add_3 = cd->gain_state + 3; + int32_t gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2]]; + /* do linear approximation between points gain_begin and gain_end */ + int32_t gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3]]; + size_t samples = frames * audio_stream_get_channels(sink); + ae_int32x2 *out = audio_stream_get_wptr(sink); + ae_int32x2 *in = (ae_int32x2 *)cd->data_ptr; + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + ae_int32x2 in_sample, out_sample; + const int inc = sizeof(ae_int32); + ae_int32x2 gain; + const int ch_n = cd->chan_cnt; + const int shift_bits = 31 - cd->att - 24; + ae_int64 out1; + + for (i = 1; i < ARIA_MAX_GAIN_STATES - 1; i++) { + if (cd->gains[sof_aria_index_tab[gain_state_add_2 + i]] < gain_begin) + gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2 + i]]; + if (cd->gains[sof_aria_index_tab[gain_state_add_3 + i]] < gain_end) + gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3 + i]]; + } + + step = (gain_end - gain_begin) / frames; + gain = gain_begin; + while (samples) { + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, samples); + m = cir_buf_samples_without_wrap_s32(cd->data_ptr, cd->data_end); + n = MIN(m, n); + inu = AE_LA64_PP(in); + for (i = 0; i < n; i += ch_n) { + /*process data one by one if ch_n is odd*/ + for (ch = 0; ch < ch_n; ch++) { + AE_L32_XP(in_sample, (ae_int32 *)in, inc); + in_sample = AE_SRAI32(AE_SLAI32(in_sample, 8), 8); + out1 = AE_MUL32_HH(in_sample, gain); + out1 = AE_SRAA64(out1, shift_bits); + out_sample = AE_ROUND24X2F48SSYM(out1, out1); + AE_S32_L_XP(out_sample, (ae_int32 *)out, inc); + } + gain = AE_ADD32S(gain, step); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = cir_buf_wrap(in, cd->data_addr, cd->data_end); + out = audio_stream_wrap(sink, out); + } + cd->gain_state = sof_aria_index_tab[cd->gain_state + 1]; +} + +static void aria_algo_get_data_even_channel(struct processing_module *mod, + struct audio_stream *sink, + int frames) +{ + struct aria_data *cd = module_get_private_data(mod); + size_t i, m, n, ch; + ae_int32x2 step; + int32_t gain_state_add_2 = cd->gain_state + 2; + int32_t gain_state_add_3 = cd->gain_state + 3; + int32_t gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2]]; + /* do linear approximation between points gain_begin and gain_end */ + int32_t gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3]]; + size_t samples = frames * audio_stream_get_channels(sink); + ae_int32x2 *out = audio_stream_get_wptr(sink); + ae_int32x2 *in = (ae_int32x2 *)cd->data_ptr; + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + ae_int32x2 in_sample, out_sample; + ae_int32x2 gain; + const int ch_n = cd->chan_cnt; + const int shift_bits = 31 - cd->att - 24; + ae_int64 out1, out2; + + for (i = 1; i < ARIA_MAX_GAIN_STATES - 1; i++) { + if (cd->gains[sof_aria_index_tab[gain_state_add_2 + i]] < gain_begin) + gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2 + i]]; + if (cd->gains[sof_aria_index_tab[gain_state_add_3 + i]] < gain_end) + gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3 + i]]; + } + + step = (gain_end - gain_begin) / frames; + gain = gain_begin; + while (samples) { + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, samples); + m = cir_buf_samples_without_wrap_s32(cd->data_ptr, cd->data_end); + n = MIN(m, n); + inu = AE_LA64_PP(in); + for (i = 0; i < n; i += ch_n) { + /*process 2 samples per time if ch_n is even*/ + for (ch = 0; ch < ch_n; ch += 2) { + AE_LA32X2_IP(in_sample, inu, in); + in_sample = AE_SRAI32(AE_SLAI32(in_sample, 8), 8); + out1 = AE_MUL32_HH(in_sample, gain); + out1 = AE_SRAA64(out1, shift_bits); + out2 = AE_MUL32_LL(in_sample, gain); + out2 = AE_SRAA64(out2, shift_bits); + out_sample = AE_ROUND24X2F48SSYM(out1, out2); + AE_SA32X2_IP(out_sample, outu, out); + } + gain = AE_ADD32S(gain, step); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = cir_buf_wrap(in, cd->data_addr, cd->data_end); + out = audio_stream_wrap(sink, out); + } + cd->gain_state = sof_aria_index_tab[cd->gain_state + 1]; +} + +aria_get_data_func aria_algo_get_data_func(struct processing_module *mod) +{ + struct aria_data *cd = module_get_private_data(mod); + + if (cd->chan_cnt & 1) + return aria_algo_get_data_odd_channel; + else + return aria_algo_get_data_even_channel; +} +#endif diff --git a/src/audio/aria/aria_hifi5.c b/src/audio/aria/aria_hifi5.c new file mode 100644 index 000000000000..ebe044ab8a48 --- /dev/null +++ b/src/audio/aria/aria_hifi5.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. + +#include "aria.h" + +#if SOF_USE_HIFI(5, ARIA) +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi5.h> + +extern const int32_t sof_aria_index_tab[]; + +/* Setup circular buffer 0 */ +static inline void set_circular_buf0(const void *start, const void *end) +{ + AE_SETCBEGIN0(start); + AE_SETCEND0(end); +} + +/* Setup circular for buffer 1 */ +static inline void set_circular_buf1(const void *start, const void *end) +{ + AE_SETCBEGIN1(start); + AE_SETCEND1(end); +} + +inline void aria_algo_calc_gain(struct aria_data *cd, size_t gain_idx, + struct audio_stream *source, int frames) +{ + /* detecting maximum value in data chunk */ + ae_int32x2 in_sample; + ae_int32x2 in_sample1; + ae_int32x2 max_data = AE_ZERO32(); + int32_t att = cd->att; + ae_valignx2 inu = AE_ZALIGN128(); + uint64_t gain = (1ULL << (att + 32)) - 1; + int32_t *max_ptr = (int32_t *)&max_data; + int32_t max; + int samples = frames * audio_stream_get_channels(source); + ae_int32x4 *in = audio_stream_get_rptr(source); + int i, n, left; + + while (samples) { + n = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(samples, n); + left = n & 3; + inu = AE_LA128_PP(in); + for (i = 0; i < n; i += 4) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + max_data = AE_MAXABS32S(max_data, AE_SLAI32(in_sample1, 8)); + max_data = AE_MAXABS32S(max_data, AE_SLAI32(in_sample, 8)); + } + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + max_data = AE_MAXABS32S(max_data, AE_SLAI32(in_sample, 8)); + } + in = audio_stream_wrap(source, in); + samples -= n; + } + + max = MAX(max_ptr[0], max_ptr[1]) >> 8; + + /*zero check for maxis not needed since att is in range <0;3>*/ + if (max > (0x007fffff >> att)) + gain = (0x007fffffULL << 32) / max; + + /* normalization by attenuation factor to obtain fractional range <1 / (2 pow att), 1> */ + cd->gains[gain_idx] = (int32_t)(gain >> (att + 1)); +} + +static void aria_algo_get_data_odd_channel(struct processing_module *mod, + struct audio_stream *sink, + int frames) +{ + struct aria_data *cd = module_get_private_data(mod); + size_t i, ch; + ae_int32x2 step; + int32_t gain_state_add_2 = cd->gain_state + 2; + int32_t gain_state_add_3 = cd->gain_state + 3; + int32_t gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2]]; + /* do linear approximation between points gain_begin and gain_end */ + int32_t gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3]]; + ae_int32 *out = audio_stream_get_wptr(sink); + ae_int32 *in = (ae_int32 *)cd->data_ptr; + ae_int32x2 in_sample, out_sample; + const int inc = sizeof(ae_int32); + ae_int32x2 gain; + const int ch_n = cd->chan_cnt; + const int shift_bits = 31 - cd->att - 24; + ae_int64 out1; + + for (i = 1; i < ARIA_MAX_GAIN_STATES - 1; i++) { + if (cd->gains[sof_aria_index_tab[gain_state_add_2 + i]] < gain_begin) + gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2 + i]]; + if (cd->gains[sof_aria_index_tab[gain_state_add_3 + i]] < gain_end) + gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3 + i]]; + } + + step = (gain_end - gain_begin) / frames; + gain = gain_begin; + + set_circular_buf0(cd->data_addr, cd->data_end); + set_circular_buf1(audio_stream_get_addr(sink), audio_stream_get_end_addr(sink)); + + for (i = 0; i < frames; i++) { + /*process data one by one if ch_n is odd*/ + for (ch = 0; ch < ch_n; ch++) { + AE_L32_XC(in_sample, in, inc); + in_sample = AE_SRAI32(AE_SLAI32(in_sample, 8), 8); + out1 = AE_MUL32_HH(in_sample, gain); + out1 = AE_SRAA64(out1, shift_bits); + out_sample = AE_ROUND24X2F48SSYM(out1, out1); + AE_S32_L_XC1(out_sample, out, inc); + } + gain = AE_ADD32S(gain, step); + } + + cd->gain_state = sof_aria_index_tab[cd->gain_state + 1]; +} + +static void aria_algo_get_data_even_channel(struct processing_module *mod, + struct audio_stream *sink, + int frames) +{ + struct aria_data *cd = module_get_private_data(mod); + size_t i, ch; + ae_int32x2 step; + int32_t gain_state_add_2 = cd->gain_state + 2; + int32_t gain_state_add_3 = cd->gain_state + 3; + int32_t gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2]]; + /* do linear approximation between points gain_begin and gain_end */ + int32_t gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3]]; + ae_int32x2 *out = audio_stream_get_wptr(sink); + ae_int32x2 *in = (ae_int32x2 *)cd->data_ptr; + ae_int32x2 in_sample, out_sample; + ae_int32x2 gain; + const int ch_n = cd->chan_cnt; + const int inc = sizeof(ae_int32x2); + const int shift_bits = 31 - cd->att - 24; + ae_int64 out1, out2; + + for (i = 1; i < ARIA_MAX_GAIN_STATES - 1; i++) { + if (cd->gains[sof_aria_index_tab[gain_state_add_2 + i]] < gain_begin) + gain_begin = cd->gains[sof_aria_index_tab[gain_state_add_2 + i]]; + if (cd->gains[sof_aria_index_tab[gain_state_add_3 + i]] < gain_end) + gain_end = cd->gains[sof_aria_index_tab[gain_state_add_3 + i]]; + } + + step = (gain_end - gain_begin) / frames; + gain = gain_begin; + + set_circular_buf0(cd->data_addr, cd->data_end); + set_circular_buf1(audio_stream_get_addr(sink), audio_stream_get_end_addr(sink)); + + for (i = 0; i < frames; i++) { + /*process 2 samples per time if ch_n is even*/ + for (ch = 0; ch < ch_n; ch += 2) { + AE_L32X2_XC(in_sample, in, inc); + in_sample = AE_SRAI32(AE_SLAI32(in_sample, 8), 8); + out1 = AE_MUL32_HH(in_sample, gain); + out1 = AE_SRAA64(out1, shift_bits); + out2 = AE_MUL32_LL(in_sample, gain); + out2 = AE_SRAA64(out2, shift_bits); + out_sample = AE_ROUND24X2F48SSYM(out1, out2); + AE_S32X2_XC1(out_sample, out, inc); + } + gain = AE_ADD32S(gain, step); + } + cd->gain_state = sof_aria_index_tab[cd->gain_state + 1]; +} + +aria_get_data_func aria_algo_get_data_func(struct processing_module *mod) +{ + struct aria_data *cd = module_get_private_data(mod); + + if (cd->chan_cnt & 1) + return aria_algo_get_data_odd_channel; + else + return aria_algo_get_data_even_channel; +} +#endif diff --git a/src/audio/aria/llext/CMakeLists.txt b/src/audio/aria/llext/CMakeLists.txt new file mode 100644 index 000000000000..d6a6e0411fc1 --- /dev/null +++ b/src/audio/aria/llext/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("aria" + SOURCES ../aria.c + ../aria_hifi5.c + ../aria_hifi3.c + ../aria_generic.c + LIB openmodules +) diff --git a/src/audio/aria/llext/llext.toml.h b/src/audio/aria/llext/llext.toml.h new file mode 100644 index 000000000000..045de1f58dc3 --- /dev/null +++ b/src/audio/aria/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../aria.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/aria/tune/sof_aria_blobs.m b/src/audio/aria/tune/sof_aria_blobs.m new file mode 100644 index 000000000000..a3adaa8c668e --- /dev/null +++ b/src/audio/aria/tune/sof_aria_blobs.m @@ -0,0 +1,74 @@ +% Export configuration blobs for Aria + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. + +function sof_aria_blobs() + + % Common definitions + sof_tools = '../../../../tools'; + sof_tplg = fullfile(sof_tools, 'topology'); + fn.tpath = fullfile(sof_tplg, 'topology2/include/components/aria'); + + % Set the parameters here + sof_tools = '../../../../tools'; + sof_tplg = fullfile(sof_tools, 'topology'); + sof_tplg_aria = fullfile(sof_tplg, 'topology2/include/components/aria'); + + sof_aria_paths(true); + + blob8 = sof_aria_build_blob(0); + tplg2_fn = sprintf("%s/passthrough.conf", sof_tplg_aria); + sof_check_create_dir(tplg2_fn); + sof_tplg2_write(tplg2_fn, blob8, "aria_config", ... + "Exported with script sof_aria_blobs.m" , ... + "cd tools/tune/aria; octave sof_aria_blobs.m"); + + for param = 1:3 + blob8 = sof_aria_build_blob(param); + tplg2_fn = sprintf("%s/param_%d.conf", sof_tplg_aria, param); + sof_tplg2_write(tplg2_fn, blob8, "aria_config", ... + "Exported with script sof_aria_blobs.m" , ... + "cd tools/tune/aria; octave sof_aria_blobs.m"); + end + + sof_aria_paths(false); +end + +function sof_aria_paths(enable) + + common = '../../../../tools/tune/common'; + if enable + addpath(common); + else + rmpath(common); + end +end + +function blob8 = sof_aria_build_blob(param_values) + + blob_type = 0; + blob_param_id = 1; % ARIA_SET_ATTENUATION + data_length = length(param_values); + data_size = 4 * data_length; + ipc_ver = 4; + [abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver, blob_type, blob_param_id); + blob_size = data_size + abi_size; + blob8 = uint8(zeros(1, blob_size)); + blob8(1:abi_size) = abi_bytes; + j = abi_size + 1; + for i = 1:data_length + blob8(j:j+3) = word2byte(param_values(i)); + j=j+4; + end +end + +function bytes = word2byte(word) + sh = [0 -8 -16 -24]; + bytes = uint8(zeros(1,4)); + bytes(1) = bitand(bitshift(word, sh(1)), 255); + bytes(2) = bitand(bitshift(word, sh(2)), 255); + bytes(3) = bitand(bitshift(word, sh(3)), 255); + bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/asrc/CMakeLists.txt b/src/audio/asrc/CMakeLists.txt index a5959ae8d6a4..696549090f55 100644 --- a/src/audio/asrc/CMakeLists.txt +++ b/src/audio/asrc/CMakeLists.txt @@ -1,5 +1,16 @@ # SPDX-License-Identifier: BSD-3-Clause +if(CONFIG_COMP_ASRC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/asrc_llext) + add_dependencies(app asrc) + return() +endif() + add_local_sources(sof asrc.c asrc_farrow.c asrc_farrow_generic.c - asrc_farrow_hifi3.c) + asrc_farrow_hifi3.c asrc_farrow_hifi5.c) +if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof asrc_ipc3.c) +elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof asrc_ipc4.c) +endif() diff --git a/src/audio/asrc/Kconfig b/src/audio/asrc/Kconfig new file mode 100644 index 000000000000..1ee458363c75 --- /dev/null +++ b/src/audio/asrc/Kconfig @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_ASRC + tristate "ASRC component" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for Asynchronous sample rate conversion (ASRC) + component. The ASRC has the capabilities of (synchronous) + SRC but can in addition track a slave DAI that is not in + sync with firmware timer. The ASRC can be setup for + synchronous operation without DAI tracking via topology + though it has a bit higher computational load than SRC. The + RAM footprint of ASRC is smaller than SRC because it does + not have pre-computed filter coefficients for every + conversion fraction that SRC does. + +if COMP_ASRC != n + +rsource "Kconfig.simd" + +choice + prompt "ASRC down sampling conversions set" + default COMP_ASRC_DOWNSAMPLING_FULL + +config COMP_ASRC_DOWNSAMPLING_FULL + bool "Full downsampling conversions support" + select ASRC_SUPPORT_CONVERSION_24000_TO_08000 + select ASRC_SUPPORT_CONVERSION_24000_TO_16000 + select ASRC_SUPPORT_CONVERSION_48000_TO_08000 + select ASRC_SUPPORT_CONVERSION_48000_TO_11025 + select ASRC_SUPPORT_CONVERSION_48000_TO_12000 + select ASRC_SUPPORT_CONVERSION_48000_TO_16000 + select ASRC_SUPPORT_CONVERSION_48000_TO_22050 + select ASRC_SUPPORT_CONVERSION_48000_TO_24000 + select ASRC_SUPPORT_CONVERSION_48000_TO_32000 + select ASRC_SUPPORT_CONVERSION_48000_TO_44100 + help + This option enables all supported downsampling conversions + for the asynchronous sample rate conversion. All the + upsampling conversions use the same filter always enabled + coefficients set so there is no configuration options for + them. The enabled conversions consume about 18 kB of memory. + +config COMP_ASRC_DOWNSAMPLING_CUSTOM + bool "Custom downsampling conversions support" + help + This option used to manually select each downsampling ratio. + In order to optimize the text code size of the sample rate + converter, non-required conversion ratios can be + deactivated. Disregarding these settings, the sample rate + converter always supports all conversion ratios with fs_in + less or equal to fs_out. Therefore, it is possible to + deactivate all conversion ratios listed below, if we only + need an (asynchronous) 1:1 sample rate conversion, e.g, from + 16 kHz to 16 kHz. This option allows to trim down the coefficient + memory for conversion down from default 18 kB. Each conversion + needs about 2 kB. + +endchoice + +menu "Supported downsampling conversions" + visible if COMP_ASRC_DOWNSAMPLING_CUSTOM + +config ASRC_SUPPORT_CONVERSION_24000_TO_08000 + bool "Downsample 24 kHz to 8 kHz" + help + This option enables downsampling from 24 kHz to 8 kHz into + the build. The consumption of memory is 2.1 kB. + +config ASRC_SUPPORT_CONVERSION_24000_TO_16000 + bool "Downsample 24 kHz to 16 kHz" + help + This option enables downsampling from 24 kHz to 16 kHz into + the build. The consumption of memory is 1.9 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_08000 + bool "Downsample 48 kHz to 8 kHz" + help + This option enables downsampling from 48 kHz to 8 kHz into + the build. The consumption of memory is 2.1 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_11025 + bool "Downsample 48 kHz to 11.025 kHz" + help + This option enables downsampling from 48 kHz to 11.025 kHz + into the build. The consumption of memory is 1.5 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_12000 + bool "Downsample 48 kHz to 12 kHz" + help + This option enables downsampling from 48 kHz to 12 kHz into + the build. The consumption of memory is 1.5 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_16000 + bool "Downsample 48 kHz to 16 kHz" + help + This option enables downsampling from 48 kHz to 16 kHz into + the build. The consumption of memory is 1.9 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_22050 + bool "Downsample 48 kHz to 22.05 kHz" + help + This option enables downsampling from 48 kHz to 22.05 kHz into + the build. The consumption of memory is 1.6 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_24000 + bool "Downsample 48 kHz to 24 kHz" + help + This option enables downsampling from 48 kHz to 24 kHz into + the build. The consumption of memory is 1.6 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_32000 + bool "Downsample 48 kHz to 32 kHz" + help + This option enables downsampling from 48 kHz to 32 kHz into + the build. The consumption of memory is 1.9 kB. + +config ASRC_SUPPORT_CONVERSION_48000_TO_44100 + bool "Downsample 48 kHz to 44.1 kHz" + help + This option enables downsampling from 48 kHz to 44.1 kHz + into the build. The consumption of memory is 1.8 kB. + +endmenu # "Downsampling ratios" + +endif # COMP_ASRC diff --git a/src/audio/asrc/Kconfig.simd b/src/audio/asrc/Kconfig.simd new file mode 100644 index 000000000000..20a77107db08 --- /dev/null +++ b/src/audio/asrc/Kconfig.simd @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: BSD-3-Clause + +comment "ASRC optimization level select" + +choice "ASRC_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for ASRC module" + depends on COMP_ASRC + default ASRC_HIFI_MAX + + config ASRC_HIFI_MAX + prompt "SIMD will selected by toolchain pre-defined header" + bool + help + When this was selected, optimization level will be determined + by toolchain pre-defined macros in core isa header file. + + config ASRC_HIFI_5 + prompt "choose HIFI5 intrinsic optimized ASRC module" + bool + help + This option used to build HIFI5 optimized ASRC code + + config ASRC_HIFI_4 + prompt "choose HIFI4 intrinsic optimized ASRC module" + bool + help + This option used to build HIFI4 optimized ASRC code + + config ASRC_HIFI_3 + prompt "choose HIFI3 intrinsic optimized ASRC module" + bool + help + This option used to build HIFI3 intrinsic optimized ASRC code + + config ASRC_HIFI_NONE + prompt "choose generic C ASRC module, no HIFI SIMD involved" + bool + help + This option used to build ASRC generic code. +endchoice diff --git a/src/audio/asrc/README.md b/src/audio/asrc/README.md new file mode 100644 index 000000000000..0ed94f83f8dc --- /dev/null +++ b/src/audio/asrc/README.md @@ -0,0 +1,23 @@ +# Asynchronous Sample Rate Converter (ASRC) Architecture + +This directory contains the ASRC component implementation. + +## Overview + +The ASRC component converts the sample rate of an incoming audio stream to a different outgoing sample rate, independently of any synchronous clocks. This is commonly used when crossing clock domains. + +## Architecture Diagram + +```mermaid +graph LR + In[Input Buffer Rate A] --> ASRC[ASRC Core Engine] + ASRC --> Out[Output Buffer Rate B] + Clock[Target Clock Domain] -.-> ASRC +``` + +## Configuration and Scripts + +- **Kconfig**: Controls the ASRC component. ASRC tracks a slave DAI out of sync with firmware timers and uses less RAM than synchronous SRC. It also supports granular configuration of downsampling ratios (from 24kHz/48kHz to lower rates) to optimize memory footprint (about 1.5-2.1 kB per conversion ratio). +- **CMakeLists.txt**: Manages source inclusion (`asrc.c`, `asrc_farrow.c`, etc.). Handles modular builds (`llext`) and chooses IPC abstraction (`asrc_ipc3.c` vs `asrc_ipc4.c`) based on the active IPC major version. +- **asrc.toml**: Holds topology module entry parameters. Features pre-defined `mod_cfg` parameter arrays specifically tailored for `CONFIG_METEORLAKE`, `CONFIG_LUNARLAKE`, and `CONFIG_SOC_ACE30`/`40` SOC platforms. +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/asrc.conf`, defining the `asrc` widget object. It introduces parameters like `rate_out` (target sample rate) and `operation_mode`. Defaults to UUID `2d:40:b4:66:68:b4:f2:42:81:a7:b3:71:21:86:3d:d4` and type `asrc`. diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index 243840001954..e9c9e6e736d4 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -1,23 +1,26 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2019 Intel Corporation. All rights reserved. +// Copyright(c) 2019-2022 Intel Corporation. All rights reserved. -#include <sof/audio/asrc/asrc_farrow.h> +#include "asrc_farrow.h" +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/buffer.h> #include <sof/audio/component.h> #include <sof/audio/format.h> #include <sof/audio/pipeline.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> +#include <sof/audio/ipc-config.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> #include <sof/lib/uuid.h> #include <sof/math/numbers.h> #include <sof/trace/trace.h> #include <sof/common.h> +#include <sof/compiler_attributes.h> #include <sof/list.h> #include <sof/platform.h> -#include <sof/string.h> +#include <rtos/string.h> +#include <sof/ut.h> #include <ipc/control.h> #include <ipc/stream.h> #include <ipc/topology.h> @@ -25,60 +28,9 @@ #include <errno.h> #include <stddef.h> #include <stdint.h> +#include "asrc.h" -/* Simple count value to prevent first delta timestamp - * from being input to low-pass filter. - */ -#define TS_STABLE_DIFF_COUNT 2 - -/* Low pass filter coefficient for measured drift factor, - * The low pass function is y(n) = c1 * x(n) + c2 * y(n -1) - * coefficient c2 needs to be 1 - c1. - */ -#define COEF_C1 Q_CONVERT_FLOAT(0.01, 30) -#define COEF_C2 Q_CONVERT_FLOAT(0.99, 30) - -typedef void (*asrc_proc_func)(struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - int *consumed, - int *produced); - -static const struct comp_driver comp_asrc; - -/* c8ec72f6-8526-4faf-9d39-a23d0b541de2 */ -DECLARE_SOF_UUID("asrc", asrc_uuid, 0xc8ec72f6, 0x8526, 0x4faf, - 0x9d, 0x39, 0xa2, 0x3d, 0x0b, 0x54, 0x1d, 0xe2); - -/* asrc component private data */ -struct comp_data { - struct asrc_farrow *asrc_obj; /* ASRC core data */ - struct comp_dev *dai_dev; /* Associated DAI component */ - enum asrc_operation_mode mode; /* Control for push or pull mode */ - uint64_t ts; - uint32_t sink_rate; /* Sample rate in Hz */ - uint32_t source_rate; /* Sample rate in Hz */ - uint32_t sink_format; /* For used PCM sample format */ - uint32_t source_format; /* For used PCM sample format */ - uint32_t copy_count; /* Count copy() operations */ - int32_t ts_prev; - int32_t sample_prev; - int32_t skew; /* Rate factor in Q2.30 */ - int ts_count; - int asrc_size; /* ASRC object size */ - int buf_size; /* Samples buffer size */ - int frames; /* IO buffer length */ - int source_frames; /* Nominal # of frames to process at source */ - int sink_frames; /* Nominal # of frames to process at sink */ - int source_frames_max; /* Max # of frames to process at source */ - int sink_frames_max; /* Max # of frames to process at sink */ - int data_shift; /* Optional shift by 8 to process S24_4LE */ - uint8_t *buf; /* Samples buffer for input and output */ - uint8_t *ibuf[PLATFORM_MAX_CHANNELS]; /* Input channels pointers */ - uint8_t *obuf[PLATFORM_MAX_CHANNELS]; /* Output channels pointers */ - bool track_drift; - asrc_proc_func asrc_func; /* ASRC processing function */ -}; +LOG_MODULE_REGISTER(asrc, CONFIG_SOF_LOG_LEVEL); /* In-line functions */ @@ -95,22 +47,24 @@ static inline void src_inc_wrap_s16(int16_t **ptr, int16_t *end, size_t size) } /* A fast copy function for same in and out rate */ -static void src_copy_s32(struct comp_dev *dev, +static void src_copy_s32(struct processing_module *mod, const struct audio_stream *source, struct audio_stream *sink, int *n_read, int *n_written) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->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; int n; int ret; int i; - int frames = 0; + int in_frames = 0; + int out_frames = 0; int idx = 0; /* TODO: Optimize buffer size by circular write to snk directly */ @@ -118,67 +72,63 @@ 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 */ - if (cd->mode == ASRC_OM_PUSH) { - ret = asrc_process_push32(dev, - cd->asrc_obj, (int32_t **)cd->ibuf, - cd->source_frames, - (int32_t **)cd->obuf, &frames, + in_frames = cd->source_frames; + out_frames = cd->sink_frames; + if (cd->mode == ASRC_OM_PUSH) + ret = asrc_process_push32(dev, cd->asrc_obj, + (int32_t **)cd->ibuf, &in_frames, + (int32_t **)cd->obuf, &out_frames, &idx, 0); - n = frames * sink->channels; - } else { + else ret = asrc_process_pull32(dev, cd->asrc_obj, - (int32_t **)cd->ibuf, - &frames, (int32_t **)cd->obuf, - cd->sink_frames, cd->source_frames, - &idx); - n = cd->sink_frames * sink->channels; - } + (int32_t **)cd->ibuf, &in_frames, + (int32_t **)cd->obuf, &out_frames, + in_frames, &idx); if (ret) - comp_err(dev, "src_copy_s32(), error %d", ret); + comp_err(dev, "error %d", ret); buf = (int32_t *)cd->obuf[0]; + 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)); } - if (cd->mode == ASRC_OM_PUSH) { - *n_read = cd->source_frames; - *n_written = frames; - } else { - *n_read = frames; - *n_written = cd->sink_frames; - } + *n_read = in_frames; + *n_written = out_frames; } -static void src_copy_s16(struct comp_dev *dev, +static void src_copy_s16(struct processing_module *mod, const struct audio_stream *source, struct audio_stream *sink, 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; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + 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; @@ -186,16 +136,17 @@ static void src_copy_s16(struct comp_dev *dev, int s_copy; int ret; int n; - int frames = 0; + int in_frames = 0; + int out_frames = 0; int idx = 0; /* TODO: Optimize buffer size by circular write to snk directly */ /* 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); @@ -205,32 +156,32 @@ 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 */ - if (cd->mode == ASRC_OM_PUSH) { - ret = asrc_process_push16(dev, - cd->asrc_obj, (int16_t **)cd->ibuf, - cd->source_frames, - (int16_t **)cd->obuf, &frames, + in_frames = cd->source_frames; + out_frames = cd->sink_frames; + + if (cd->mode == ASRC_OM_PUSH) + ret = asrc_process_push16(dev, cd->asrc_obj, + (int16_t **)cd->ibuf, &in_frames, + (int16_t **)cd->obuf, &out_frames, &idx, 0); - n = frames * sink->channels; - } else { - ret = asrc_process_pull16(dev, - cd->asrc_obj, (int16_t **)cd->ibuf, - &frames, (int16_t **)cd->obuf, - cd->sink_frames, cd->source_frames, - &idx); - n = cd->sink_frames * sink->channels; - } + else + ret = asrc_process_pull16(dev, cd->asrc_obj, + (int16_t **)cd->ibuf, &in_frames, + (int16_t **)cd->obuf, &out_frames, + in_frames, &idx); if (ret) - comp_err(dev, "src_copy_s16(), error %d", ret); + comp_err(dev, "error %d", ret); buf = (int16_t *)cd->obuf[0]; + 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); @@ -240,124 +191,159 @@ 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)); } - if (cd->mode == ASRC_OM_PUSH) { - *n_read = cd->source_frames; - *n_written = frames; - } else { - *n_read = frames; - *n_written = cd->sink_frames; - } + *n_read = in_frames; + *n_written = out_frames; } -static struct comp_dev *asrc_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) +static int asrc_init(struct processing_module *mod) { - struct comp_dev *dev; - struct sof_ipc_comp_asrc *asrc; - struct sof_ipc_comp_asrc *ipc_asrc = (struct sof_ipc_comp_asrc *)comp; + struct comp_dev *dev = mod->dev; + struct module_data *mod_data = &mod->priv; + const ipc_asrc_cfg *ipc_asrc = (const ipc_asrc_cfg *)mod_data->cfg.init_data; struct comp_data *cd; - int err; - - comp_cl_info(&comp_asrc, "asrc_new()"); - comp_cl_info(&comp_asrc, "asrc_new(), source_rate=%d, sink_rate=%d, asynchronous_mode=%d, operation_mode=%d", - ipc_asrc->source_rate, ipc_asrc->sink_rate, - ipc_asrc->asynchronous_mode, ipc_asrc->operation_mode); + comp_info(dev, "source_rate=%d, sink_rate=%d, asynchronous_mode=%d, operation_mode=%d", + asrc_get_source_rate(ipc_asrc), asrc_get_sink_rate(ipc_asrc), + asrc_get_asynchronous_mode(ipc_asrc), asrc_get_operation_mode(ipc_asrc)); /* validate init data - either SRC sink or source rate must be set */ - if (ipc_asrc->source_rate == 0 && ipc_asrc->sink_rate == 0) { - comp_cl_err(&comp_asrc, "asrc_new(), sink and source rates are not set"); - return NULL; + if (asrc_get_source_rate(ipc_asrc) == 0 || asrc_get_sink_rate(ipc_asrc) == 0) { + comp_err(dev, "sink or source rates are not set"); + return -EINVAL; } - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_asrc)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_asrc); + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; - asrc = COMP_GET_IPC(dev, sof_ipc_comp_asrc); - err = memcpy_s(asrc, sizeof(*asrc), ipc_asrc, - sizeof(struct sof_ipc_comp_asrc)); - assert(!err); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); + mod_data->private = cd; + memcpy_s(&cd->ipc_config, sizeof(cd->ipc_config), ipc_asrc, sizeof(cd->ipc_config)); /* Get operation mode: * With OM_PUSH (0) use fixed input frames count, variable output. * With OM_PULL (1) use fixed output frames count, variable input. */ - cd->mode = asrc->operation_mode; + cd->mode = asrc_get_operation_mode(ipc_asrc); /* Use skew tracking for DAI if it was requested. The skew * is initialized here to zero. It is set later in prepare() to - * to 1.0 if there is no filtered skew factor from previous run. + * 1.0 if there is no filtered skew factor from previous run. */ - cd->track_drift = asrc->asynchronous_mode; + cd->track_drift = asrc_get_asynchronous_mode(ipc_asrc); cd->skew = 0; + mod->skip_src_buffer_invalidate = true; + mod->skip_sink_buffer_writeback = true; - dev->state = COMP_STATE_READY; - return dev; + return 0; } -static void asrc_free(struct comp_dev *dev) +static int asrc_initialize_buffers(struct processing_module *mod, struct asrc_farrow *src_obj) { - struct comp_data *cd = comp_get_drvdata(dev); + int32_t *buf_32; + int16_t *buf_16; + int ch; + size_t buffer_size; + + /* Set buffer_length to filter_length * 2 to compensate for + * missing element wise wrap around while loading but allowing + * aligned loads. FIR delay line write is initialized to last + * position of first copy block for reverse direction write. + */ + src_obj->buffer_length = src_obj->filter_length * 2; + src_obj->buffer_write_position = src_obj->filter_length - 1; - comp_info(dev, "asrc_free()"); + if (src_obj->bit_depth == 32) { + buffer_size = src_obj->buffer_length * sizeof(int32_t); - rfree(cd->buf); - rfree(cd->asrc_obj); - rfree(cd); - rfree(dev); -} + for (ch = 0; ch < src_obj->num_channels; ch++) { + buf_32 = mod_zalloc(mod, buffer_size); -static int asrc_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) -{ - comp_err(dev, "asrc_ctrl_cmd()"); - return -EINVAL; + if (!buf_32) + return -ENOMEM; + + src_obj->ring_buffers32[ch] = buf_32; + } + } else { + buffer_size = src_obj->buffer_length * sizeof(int16_t); + + for (ch = 0; ch < src_obj->num_channels; ch++) { + buf_16 = mod_zalloc(mod, buffer_size); + + if (!buf_16) + return -ENOMEM; + + src_obj->ring_buffers16[ch] = buf_16; + } + } + + return 0; } -/* used to pass standard and bespoke commands (with data) to component */ -static int asrc_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) +static void asrc_release_buffers(struct processing_module *mod, struct asrc_farrow *src_obj) { - struct sof_ipc_ctrl_data *cdata = data; - int ret = 0; + int32_t *buf_32; + int16_t *buf_16; + int ch; - comp_info(dev, "asrc_cmd()"); + if (!src_obj) + return; - if (cmd == COMP_CMD_SET_VALUE) - ret = asrc_ctrl_cmd(dev, cdata); + if (src_obj->bit_depth == 32) + for (ch = 0; ch < src_obj->num_channels; ch++) { + buf_32 = src_obj->ring_buffers32[ch]; - return ret; + if (buf_32) { + src_obj->ring_buffers32[ch] = NULL; + mod_free(mod, buf_32); + } + } + else + for (ch = 0; ch < src_obj->num_channels; ch++) { + buf_16 = src_obj->ring_buffers16[ch]; + + if (buf_16) { + src_obj->ring_buffers16[ch] = NULL; + mod_free(mod, buf_16); + } + } } -static int asrc_trigger(struct comp_dev *dev, int cmd) +static int asrc_free(struct processing_module *mod) { - comp_info(dev, "asrc_trigger()"); + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; - return comp_set_state(dev, cmd); + comp_dbg(dev, "entry"); + + mod_free(mod, cd->buf); + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + mod_free(mod, cd); + return 0; +} + +static int asrc_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) +{ + comp_err(mod->dev, "entry"); + return -EINVAL; } -static int asrc_verify_params(struct comp_dev *dev, +static int asrc_verify_params(struct processing_module *mod, struct sof_ipc_stream_params *params) { - struct sof_ipc_comp_asrc *asrc = COMP_GET_IPC(dev, sof_ipc_comp_asrc); + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; int ret; - comp_dbg(dev, "asrc_verify_params()"); + comp_dbg(dev, "entry"); /* check whether params->rate (received from driver) are equal * to asrc->source_rate (PLAYBACK) or asrc->sink_rate (CAPTURE) set @@ -365,13 +351,17 @@ static int asrc_verify_params(struct comp_dev *dev, * src->source/sink_rate = 0 means that source/sink rate can vary. */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - if (params->rate != asrc->source_rate && asrc->source_rate) { - comp_err(dev, "asrc_verify_params(): error: runtime stream pcm rate does not match rate fetched from ipc."); + if (asrc_get_source_rate(&cd->ipc_config) && + params->rate != asrc_get_source_rate(&cd->ipc_config)) { + comp_err(dev, "runtime stream pcm rate %u does not match rate %u fetched from ipc.", + params->rate, asrc_get_source_rate(&cd->ipc_config)); return -EINVAL; } } else { - if (params->rate != asrc->sink_rate && asrc->sink_rate) { - comp_err(dev, "asrc_verify_params(): error: runtime stream pcm rate does not match rate fetched from ipc."); + if (asrc_get_sink_rate(&cd->ipc_config) && + params->rate != asrc_get_sink_rate(&cd->ipc_config)) { + comp_err(dev, "runtime stream pcm rate %u does not match rate %u fetched from ipc.", + params->rate, asrc_get_sink_rate(&cd->ipc_config)); return -EINVAL; } } @@ -380,7 +370,7 @@ static int asrc_verify_params(struct comp_dev *dev, */ ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); if (ret < 0) { - comp_err(dev, "asrc_verify_params() error: comp_verify_params() failed."); + comp_err(dev, "comp_verify_params() failed."); return ret; } @@ -388,30 +378,49 @@ static int asrc_verify_params(struct comp_dev *dev, } /* set component audio stream parameters */ -static int asrc_params(struct comp_dev *dev, - struct sof_ipc_stream_params *pcm_params) +static int asrc_params(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sinkb; - struct comp_buffer *sourceb; + struct sof_ipc_stream_params *pcm_params = mod->stream_params; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sourceb, *sinkb; int err; - comp_info(dev, "asrc_params()"); + comp_info(dev, "entry"); - err = asrc_verify_params(dev, pcm_params); + asrc_set_stream_params(cd, pcm_params); + + err = asrc_verify_params(mod, pcm_params); if (err < 0) { - comp_err(dev, "src_params(): pcm params verification failed."); + comp_err(dev, "pcm params verification failed."); return -EINVAL; } - 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 = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + + /* update the source/sink buffer formats. Sink rate will be modified below */ + asrc_update_buffer_format(sourceb, cd); + asrc_update_buffer_format(sinkb, cd); + + /* Don't change sink rate if value from IPC is 0 (auto detect) */ + if (asrc_get_sink_rate(&cd->ipc_config)) + audio_stream_set_rate(&sinkb->stream, asrc_get_sink_rate(&cd->ipc_config)); /* set source/sink_frames/rate */ - cd->source_rate = sourceb->stream.rate; - cd->sink_rate = sinkb->stream.rate; + cd->source_rate = audio_stream_get_rate(&sourceb->stream); + cd->sink_rate = audio_stream_get_rate(&sinkb->stream); + + if (!cd->sink_rate) { + comp_err(dev, "zero sink rate"); + return -EINVAL; + } + + component_set_nearest_period_frames(dev, cd->sink_rate); cd->sink_frames = dev->frames; cd->source_frames = ceil_divide(dev->frames * cd->source_rate, cd->sink_rate); @@ -426,19 +435,17 @@ static int asrc_params(struct comp_dev *dev, cd->sink_frames_max = cd->sink_frames + 10; cd->frames = MAX(cd->source_frames_max, cd->sink_frames_max); - comp_info(dev, "asrc_params(), source_rate=%u, sink_rate=%u, source_frames_max=%d, sink_frames_max=%d", + comp_info(dev, "source_rate=%u, sink_rate=%u, source_frames_max=%d, sink_frames_max=%d", cd->source_rate, cd->sink_rate, cd->source_frames_max, cd->sink_frames_max); return 0; } -static int asrc_dai_find(struct comp_dev *dev, - struct comp_data *cd, - struct comp_buffer *sinkb, - struct comp_buffer *sourceb) +static int asrc_dai_find(struct comp_dev *dev, struct comp_data *cd) { - struct comp_dev *next_dev; + struct comp_buffer *sourceb, *sinkb; + struct comp_dev *asrc_dev = dev; int pid; /* Get current pipeline ID and walk to find the DAI */ @@ -446,98 +453,89 @@ static int asrc_dai_find(struct comp_dev *dev, cd->dai_dev = NULL; if (cd->mode == ASRC_OM_PUSH) { /* In push mode check if sink component is DAI */ - next_dev = sinkb->sink; - while (dev_comp_type(next_dev) != SOF_COMP_DAI) { - sinkb = list_first_item(&next_dev->bsink_list, - struct comp_buffer, - source_list); - next_dev = sinkb->sink; - if (!next_dev) { - comp_cl_err(&comp_asrc, "At end, no DAI found."); + do { + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sinkb) { + comp_err(asrc_dev, "At end: NULL buffer, no DAI found."); return -EINVAL; } - if (dev_comp_pipe_id(next_dev) != pid) { - comp_cl_err(&comp_asrc, "No DAI sink in pipeline."); + dev = comp_buffer_get_sink_component(sinkb); + if (!dev) { + comp_err(asrc_dev, "At end: NULL device, no DAI found."); return -EINVAL; } - } + + if (dev_comp_pipe_id(dev) != pid) { + comp_err(asrc_dev, "No DAI sink in pipeline."); + return -EINVAL; + } + + } while (dev_comp_type(dev) != SOF_COMP_DAI); } else { /* In pull mode check if source component is DAI */ - next_dev = sourceb->source; - while (dev_comp_type(next_dev) != SOF_COMP_DAI) { - sourceb = list_first_item(&next_dev->bsource_list, - struct comp_buffer, - sink_list); - next_dev = sourceb->source; - if (!next_dev) { - comp_cl_err(&comp_asrc, "At beginning, no DAI found."); + do { + sourceb = comp_dev_get_first_data_producer(dev); + if (!sourceb) { + comp_err(asrc_dev, "At beginning: NULL buffer, no DAI found."); return -EINVAL; } - if (dev_comp_pipe_id(next_dev) != pid) { - comp_cl_err(&comp_asrc, "No DAI source in pipeline."); + dev = comp_buffer_get_source_component(sourceb); + if (!dev) { + comp_err(asrc_dev, "At beginning: NULL device, no DAI found."); return -EINVAL; } - } + + if (dev_comp_pipe_id(dev) != pid) { + comp_err(asrc_dev, "No DAI source in pipeline."); + return -EINVAL; + } + } while (dev_comp_type(dev) != SOF_COMP_DAI); } /* Point dai_dev to found DAI */ - cd->dai_dev = next_dev; - return 0; -} - -static int asrc_dai_configure_timestamp(struct comp_data *cd) -{ - int ret; - - if (cd->dai_dev) - ret = cd->dai_dev->drv->ops.dai_ts_config(cd->dai_dev); - else - return -EINVAL; - - return ret; -} - -static int asrc_dai_start_timestamp(struct comp_data *cd) -{ - int ret; + cd->dai_dev = dev; - if (cd->dai_dev) - ret = cd->dai_dev->drv->ops.dai_ts_start(cd->dai_dev); - else - return -EINVAL; - - return ret; + return 0; } -static int asrc_dai_stop_timestamp(struct comp_data *cd) +static int asrc_trigger(struct processing_module *mod, int cmd) { + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; int ret; - if (cd->dai_dev) - ret = cd->dai_dev->drv->ops.dai_ts_stop(cd->dai_dev); - else - return -EINVAL; + comp_info(dev, "entry"); - return ret; -} + /* Enable timestamping in pipeline DAI */ + if (cmd == COMP_TRIGGER_START && cd->track_drift) { + ret = asrc_dai_find(dev, cd); + if (ret) { + comp_err(dev, "No DAI found to track"); + cd->track_drift = false; + return ret; + } -static int asrc_dai_get_timestamp(struct comp_data *cd, - struct timestamp_data *tsd) -{ - if (!cd->dai_dev) - return -EINVAL; + cd->ts_count = 0; + ret = asrc_dai_configure_timestamp(cd); + if (ret) { + comp_err(dev, "No timestamp capability in DAI"); + cd->track_drift = false; + return ret; + } + } - return cd->dai_dev->drv->ops.dai_ts_get(cd->dai_dev, tsd); + return comp_set_state(dev, cmd); } -static int asrc_prepare(struct comp_dev *dev) +static int asrc_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *sinkb; - struct comp_buffer *sourceb; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sourceb, *sinkb; uint32_t source_period_bytes; uint32_t sink_period_bytes; int sample_bytes; @@ -548,34 +546,33 @@ static int asrc_prepare(struct comp_dev *dev) int ret; int i; - comp_info(dev, "asrc_prepare()"); + comp_info(dev, "entry"); - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + ret = asrc_params(mod); if (ret < 0) return ret; - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - - /* SRC component 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); + /* + * SRC component will only ever have 1 source and 1 sink buffer, + * asrc_params() has checked their validity already + */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); /* get source data format and period bytes */ - cd->source_format = sourceb->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); source_period_bytes = audio_stream_period_bytes(&sourceb->stream, cd->source_frames); /* get sink data format and period bytes */ - cd->sink_format = sinkb->stream.frame_fmt; + cd->sink_format = audio_stream_get_frm_fmt(&sinkb->stream); sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, cd->sink_frames); - if (sinkb->stream.size < config->periods_sink * sink_period_bytes) { - comp_err(dev, "asrc_prepare(), sink size=%d is insufficient, when periods=%d, period_bytes=%d", - sinkb->stream.size, config->periods_sink, + if (audio_stream_get_size(&sinkb->stream) < + dev->ipc_config.periods_sink * sink_period_bytes) { + comp_err(dev, "sink buffer size %d is insufficient < %d * %d", + audio_stream_get_size(&sinkb->stream), dev->ipc_config.periods_sink, sink_period_bytes); ret = -ENOMEM; goto err; @@ -583,18 +580,18 @@ static int asrc_prepare(struct comp_dev *dev) /* validate */ if (!sink_period_bytes) { - comp_err(dev, "asrc_prepare(), sink_period_bytes = 0"); + comp_err(dev, "sink_period_bytes = 0"); ret = -EINVAL; goto err; } if (!source_period_bytes) { - comp_err(dev, "asrc_prepare(), source_period_bytes = 0"); + comp_err(dev, "source_period_bytes = 0"); ret = -EINVAL; goto err; } /* ASRC supports S16_LE, S24_4LE and S32_LE formats */ - switch (sourceb->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&sourceb->stream)) { case SOF_IPC_FRAME_S16_LE: cd->asrc_func = src_copy_s16; break; @@ -607,58 +604,50 @@ static int asrc_prepare(struct comp_dev *dev) cd->asrc_func = src_copy_s32; break; default: - comp_err(dev, "asrc_prepare(), invalid frame format"); + comp_err(dev, "invalid frame format"); return -EINVAL; } - /* - * Allocate input and output data buffer for ASRC processing - */ + /* Allocate input and output data buffer for ASRC processing */ frame_bytes = audio_stream_frame_bytes(&sourceb->stream); cd->buf_size = (cd->source_frames_max + cd->sink_frames_max) * frame_bytes; - cd->buf = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - cd->buf_size); + cd->buf = mod_zalloc(mod, cd->buf_size); if (!cd->buf) { cd->buf_size = 0; - comp_err(dev, "asrc_prepare(), allocation fail for size %d", + comp_err(dev, "allocation fail for size %d", cd->buf_size); ret = -ENOMEM; - goto err_free_buf; + goto err; } - sample_bytes = frame_bytes / sourceb->stream.channels; - for (i = 0; i < sourceb->stream.channels; i++) { + sample_bytes = frame_bytes / audio_stream_get_channels(&sourceb->stream); + for (i = 0; i < audio_stream_get_channels(&sourceb->stream); i++) { cd->ibuf[i] = cd->buf + i * sample_bytes; cd->obuf[i] = cd->ibuf[i] + cd->source_frames_max * frame_bytes; } - /* - * Get required size and allocate memory for ASRC - */ + /* Get required size and allocate memory for ASRC */ sample_bits = sample_bytes * 8; - ret = asrc_get_required_size(dev, &cd->asrc_size, - sourceb->stream.channels, + ret = asrc_get_required_size(mod, &cd->asrc_size, + audio_stream_get_channels(&sourceb->stream), sample_bits); if (ret) { - comp_err(dev, "asrc_prepare(), get_required_size_bytes failed"); + comp_err(dev, "get_required_size_bytes failed"); goto err_free_buf; } - cd->asrc_obj = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - cd->asrc_size); + cd->asrc_obj = mod_zalloc(mod, cd->asrc_size); if (!cd->asrc_obj) { - comp_err(dev, "asrc_prepare(), allocation fail for size %d", + comp_err(dev, "allocation fail for size %d", cd->asrc_size); cd->asrc_size = 0; ret = -ENOMEM; goto err_free_buf; } - /* - * Initialize ASRC - */ + /* Initialize ASRC */ if (cd->mode == ASRC_OM_PUSH) { fs_prim = cd->source_rate; fs_sec = cd->sink_rate; @@ -667,7 +656,7 @@ static int asrc_prepare(struct comp_dev *dev) fs_sec = cd->source_rate; } - ret = asrc_initialise(dev, cd->asrc_obj, sourceb->stream.channels, + ret = asrc_initialise(mod, cd->asrc_obj, audio_stream_get_channels(&sourceb->stream), fs_prim, fs_sec, ASRC_IOF_INTERLEAVED, ASRC_IOF_INTERLEAVED, ASRC_BM_LINEAR, cd->frames, sample_bits, @@ -677,6 +666,15 @@ static int asrc_prepare(struct comp_dev *dev) goto err_free_asrc; } + /* Allocate ring buffers */ + ret = asrc_initialize_buffers(mod, cd->asrc_obj); + + /* check for errors */ + if (ret) { + comp_err(dev, "asrc_initialize_buffers(), failed buffer initialize, error %d", ret); + goto err_free_asrc; + } + /* Prefer previous skew factor. If the component has not yet been * run the skew is zero from new(). In that case use factor 1.0 * to start with. @@ -684,39 +682,25 @@ static int asrc_prepare(struct comp_dev *dev) if (!cd->skew) cd->skew = Q_CONVERT_FLOAT(1.0, 30); - comp_info(dev, "asrc_prepare(), skew = %d", cd->skew); + cd->skew_min = cd->skew; + cd->skew_max = cd->skew; + + comp_info(dev, "skew = %d", cd->skew); ret = asrc_update_drift(dev, cd->asrc_obj, cd->skew); if (ret) { comp_err(dev, "asrc_update_drift(), error %d", ret); goto err_free_asrc; } - /* Enable timestamping in pipeline DAI */ - if (cd->track_drift) { - ret = asrc_dai_find(dev, cd, sinkb, sourceb); - if (ret) { - comp_err(dev, "No DAI found to track"); - cd->track_drift = false; - goto err_free_asrc; - } - - cd->ts_count = 0; - ret = asrc_dai_configure_timestamp(cd); - if (ret) { - comp_err(dev, "No timestamp capability in DAI"); - cd->track_drift = false; - goto err_free_asrc; - } - } - return 0; err_free_asrc: - rfree(cd->asrc_obj); + asrc_release_buffers(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); cd->asrc_obj = NULL; err_free_buf: - rfree(cd->buf); + mod_free(mod, cd->buf); cd->buf = NULL; err: @@ -726,7 +710,11 @@ static int asrc_prepare(struct comp_dev *dev) static int asrc_control_loop(struct comp_dev *dev, struct comp_data *cd) { +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + struct dai_ts_data tsd; +#else struct timestamp_data tsd; +#endif int64_t tmp; int32_t delta_sample; int32_t delta_ts; @@ -768,7 +756,7 @@ static int asrc_control_loop(struct comp_dev *dev, struct comp_data *cd) /* Prevent divide by zero */ if (delta_sample == 0 || tsd.walclk_rate == 0) { - comp_cl_err(&comp_asrc, "asrc_control_loop(), DAI timestamp failed"); + comp_err(dev, "DAI timestamp failed"); return -EINVAL; } @@ -784,67 +772,42 @@ static int asrc_control_loop(struct comp_dev *dev, struct comp_data *cd) tmp = ((int64_t)COEF_C1) * skew + ((int64_t)COEF_C2) * cd->skew; cd->skew = sat_int32(Q_SHIFT_RND(tmp, 60, 30)); asrc_update_drift(dev, cd->asrc_obj, cd->skew); - comp_cl_dbg(&comp_asrc, "skew %d %d %d %d", delta_sample, delta_ts, - skew, cd->skew); - return 0; -} -static void asrc_process(struct comp_dev *dev, struct comp_buffer *source, - struct comp_buffer *sink) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int consumed = 0; - int produced = 0; - - /* consumed bytes are not known at this point */ - buffer_invalidate(source, source->stream.size); - cd->asrc_func(dev, &source->stream, &sink->stream, &consumed, - &produced); - buffer_writeback(sink, produced * - audio_stream_frame_bytes(&sink->stream)); - - comp_dbg(dev, "asrc_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)); + /* Track skew variation, it helps to analyze possible problems + * with slave DAI frame clock stability. + */ + cd->skew_min = MIN(cd->skew, cd->skew_min); + cd->skew_max = MAX(cd->skew, cd->skew_max); + comp_dbg(dev, "skew %d %d %d %d", delta_sample, delta_ts, skew, cd->skew); + return 0; } /* copy and process stream data from source to sink buffers */ -static int asrc_copy(struct comp_dev *dev) +static int asrc_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 comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source; - struct comp_buffer *sink; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *source, *sink; + struct audio_stream *source_s = input_buffers[0].data; + struct audio_stream *sink_s = output_buffers[0].data; int frames_src; int frames_snk; int ret; - uint32_t flags = 0; - comp_dbg(dev, "asrc_copy()"); + comp_dbg(dev, "entry"); ret = asrc_control_loop(dev, cd); if (ret) return ret; /* asrc 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); - - buffer_lock(source, &flags); - buffer_lock(sink, &flags); - - frames_src = source->stream.avail / - audio_stream_frame_bytes(&source->stream); - frames_snk = sink->stream.free / - audio_stream_frame_bytes(&sink->stream); + source = comp_dev_get_first_data_producer(dev); + sink = comp_dev_get_first_data_consumer(dev); - buffer_unlock(sink, flags); - buffer_unlock(source, flags); + frames_src = audio_stream_get_avail_frames(source_s); + frames_snk = audio_stream_get_free_frames(sink_s); if (cd->mode == ASRC_OM_PULL) { /* Let ASRC access max number of source frames in pull mode. @@ -869,55 +832,72 @@ static int asrc_copy(struct comp_dev *dev) cd->source_frames = MIN(cd->source_frames, frames_src); } - if (cd->source_frames && cd->sink_frames) - asrc_process(dev, source, sink); + if (cd->source_frames && cd->sink_frames) { + int consumed = 0; + int produced = 0; + + /* consumed bytes are not known at this point */ + buffer_stream_invalidate(source, audio_stream_get_size(source_s)); + cd->asrc_func(mod, source_s, sink_s, &consumed, &produced); + buffer_stream_writeback(sink, produced * audio_stream_frame_bytes(sink_s)); + + comp_dbg(dev, "consumed = %u, produced = %u", consumed, produced); + + output_buffers[0].size = produced * audio_stream_frame_bytes(sink_s); + input_buffers[0].consumed = consumed * audio_stream_frame_bytes(source_s); + } return 0; } -static int asrc_reset(struct comp_dev *dev) +static int asrc_reset(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); - comp_info(dev, "asrc_reset()"); + comp_dbg(dev, "skew_min=%d, skew_max=%d", cd->skew_min, cd->skew_max); /* If any resources feasible to stop */ if (cd->track_drift) asrc_dai_stop_timestamp(cd); /* Free the allocations those were done in prepare() */ - rfree(cd->asrc_obj); - rfree(cd->buf); + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + mod_free(mod, cd->buf); cd->asrc_obj = NULL; cd->buf = NULL; - comp_set_state(dev, COMP_TRIGGER_RESET); return 0; } -static const struct comp_driver comp_asrc = { - .type = SOF_COMP_ASRC, - .uid = SOF_UUID(asrc_uuid), - .ops = { - .new = asrc_new, - .free = asrc_free, - .params = asrc_params, - .cmd = asrc_cmd, - .trigger = asrc_trigger, - .copy = asrc_copy, - .prepare = asrc_prepare, - .reset = asrc_reset, - }, +static const struct module_interface asrc_interface = { + .init = asrc_init, + .prepare = asrc_prepare, + .process_audio_stream = asrc_process, + .trigger = asrc_trigger, + .set_configuration = asrc_set_config, + .reset = asrc_reset, + .free = asrc_free, }; -static SHARED_DATA struct comp_driver_info comp_asrc_info = { - .drv = &comp_asrc, +#if CONFIG_COMP_ASRC_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { + SOF_LLEXT_MODULE_MANIFEST("ASRC", &asrc_interface, 1, SOF_REG_UUID(asrc4), 2), }; -static void sys_comp_asrc_init(void) -{ - comp_register(platform_shared_get(&comp_asrc_info, - sizeof(comp_asrc_info))); -} +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_MODULE_ADAPTER(asrc_interface, ASRC_UUID, asrc_tr); +SOF_MODULE_INIT(asrc, sys_comp_module_asrc_interface_init); -DECLARE_MODULE(sys_comp_asrc_init); +#endif diff --git a/src/audio/asrc/asrc.h b/src/audio/asrc/asrc.h new file mode 100644 index 000000000000..1c86a2cf757e --- /dev/null +++ b/src/audio/asrc/asrc.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_ASRC_H__ +#define __SOF_ASRC_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/component.h> +#include "asrc_farrow.h" + +struct comp_data; +#ifdef CONFIG_IPC_MAJOR_4 + +#include <ipc4/base-config.h> +#include "asrc_ipc4.h" + +typedef struct ipc4_asrc_module_cfg ipc_asrc_cfg; + +static inline uint32_t asrc_get_source_rate(const struct ipc4_asrc_module_cfg *ipc_asrc) +{ + return ipc_asrc->base.audio_fmt.sampling_frequency; +} + +static inline uint32_t asrc_get_sink_rate(const struct ipc4_asrc_module_cfg *ipc_asrc) +{ + return ipc_asrc->out_freq; +} + +static inline uint32_t asrc_get_operation_mode(const struct ipc4_asrc_module_cfg *ipc_asrc) +{ + return ipc_asrc->asrc_mode & (1 << IPC4_MOD_ASRC_PUSH_MODE) ? ASRC_OM_PUSH : ASRC_OM_PULL; +} + +static inline bool asrc_get_asynchronous_mode(const struct ipc4_asrc_module_cfg *ipc_asrc) +{ + return false; +} + +#else /*IPC3 version*/ +typedef struct ipc_config_asrc ipc_asrc_cfg; + +static inline uint32_t asrc_get_source_rate(const struct ipc_config_asrc *ipc_asrc) +{ + return ipc_asrc->source_rate; +} + +static inline uint32_t asrc_get_sink_rate(const struct ipc_config_asrc *ipc_asrc) +{ + return ipc_asrc->sink_rate; +} + +static inline uint32_t asrc_get_operation_mode(const struct ipc_config_asrc *ipc_asrc) +{ + return ipc_asrc->operation_mode; +} + +static inline bool asrc_get_asynchronous_mode(const struct ipc_config_asrc *ipc_asrc) +{ + return ipc_asrc->asynchronous_mode; +} + +#endif + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +int asrc_dai_get_timestamp(struct comp_data *cd, struct dai_ts_data *tsd); +#else +int asrc_dai_get_timestamp(struct comp_data *cd, struct timestamp_data *tsd); +#endif +/* Simple count value to prevent first delta timestamp + * from being input to low-pass filter. + */ +#define TS_STABLE_DIFF_COUNT 2 + +/* Low pass filter coefficient for measured drift factor, + * The low pass function is y(n) = c1 * x(n) + c2 * y(n -1) + * coefficient c2 needs to be 1 - c1. + */ +#define COEF_C1 Q_CONVERT_FLOAT(0.01, 30) +#define COEF_C2 Q_CONVERT_FLOAT(0.99, 30) + +typedef void (*asrc_proc_func)(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + int *consumed, + int *produced); +/* asrc component private data */ +struct comp_data { + ipc_asrc_cfg ipc_config; + struct asrc_farrow *asrc_obj; /* ASRC core data */ + struct comp_dev *dai_dev; /* Associated DAI component */ + enum asrc_operation_mode mode; /* Control for push or pull mode */ + uint64_t ts; + uint32_t sink_rate; /* Sample rate in Hz */ + uint32_t source_rate; /* Sample rate in Hz */ + uint32_t sink_format; /* For used PCM sample format */ + uint32_t source_format; /* For used PCM sample format */ + uint32_t copy_count; /* Count copy() operations */ + int32_t ts_prev; + int32_t sample_prev; + int32_t skew; /* Rate factor in Q2.30 */ + int32_t skew_min; + int32_t skew_max; + int ts_count; + int asrc_size; /* ASRC object size */ + int buf_size; /* Samples buffer size */ + int frames; /* IO buffer length */ + int source_frames; /* Nominal # of frames to process at source */ + int sink_frames; /* Nominal # of frames to process at sink */ + int source_frames_max; /* Max # of frames to process at source */ + int sink_frames_max; /* Max # of frames to process at sink */ + int data_shift; /* Optional shift by 8 to process S24_4LE */ + uint8_t *buf; /* Samples buffer for input and output */ + uint8_t *ibuf[PLATFORM_MAX_CHANNELS]; /* Input channels pointers */ + uint8_t *obuf[PLATFORM_MAX_CHANNELS]; /* Output channels pointers */ + bool track_drift; + asrc_proc_func asrc_func; /* ASRC processing function */ +}; + +int asrc_dai_configure_timestamp(struct comp_data *cd); +int asrc_dai_start_timestamp(struct comp_data *cd); +int asrc_dai_stop_timestamp(struct comp_data *cd); +void asrc_update_buffer_format(struct comp_buffer *buf_c, struct comp_data *cd); +void asrc_set_stream_params(struct comp_data *cd, struct sof_ipc_stream_params *params); +extern struct tr_ctx asrc_tr; + +/* Different UUID names for different build configurations... */ +#ifdef CONFIG_IPC_MAJOR_4 +#define ASRC_UUID asrc4_uuid +#else +#define ASRC_UUID asrc_uuid +#endif +extern const struct sof_uuid ASRC_UUID; + +#endif diff --git a/src/audio/asrc/asrc.toml b/src/audio/asrc/asrc.toml new file mode 100644 index 000000000000..2e8f8eac837e --- /dev/null +++ b/src/audio/asrc/asrc.toml @@ -0,0 +1,70 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "ASRC" + uuid = UUIDREG_STR_ASRC4 + affinity_mask = "0x3" + instance_count = "2" + domain_types = "0" + + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + pin = [0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 1, 0, 0xfeef, 0xc, 0x8, 0x45ff] + +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 20480, 21808000, 64, 192, 0, 21808, 0, + 1, 0, 0, 0, 20480, 45820000, 64, 384, 0, 45820, 0, + 2, 0, 0, 0, 20480, 75236000, 512, 1440, 0, 75236, 0, + 3, 0, 0, 0, 20480, 79732000, 512, 1536, 0, 79732, 0, + 4, 0, 0, 0, 20480, 50411000, 184, 384, 0, 50411, 0, + 5, 0, 0, 0, 20480, 24236000, 192, 128, 0, 24236, 0, + 6, 0, 0, 0, 20480, 46753000, 192, 384, 0, 46753, 0, + 7, 0, 0, 0, 20480, 30032000, 256, 256, 0, 30032, 0, + 8, 0, 0, 0, 20480, 48676000, 256, 384, 0, 48676, 0, + 9, 0, 0, 0, 20480, 46548000, 360, 360, 0, 46548, 0, + 10, 0, 0, 0, 20480, 94372000, 1440, 1536, 0, 94372, 0, + 11, 0, 0, 0, 20480, 42912000, 1536, 512, 0, 42912, 0, + 12, 0, 0, 0, 20480, 31871000, 384, 192, 0, 31871, 0, + 13, 0, 0, 0, 20480, 34216000, 384, 256, 0, 34216, 0, + 14, 0, 0, 0, 20480, 83448000, 1536, 1440, 0, 83448, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 20480, 22736000, 64, 192, 0, 22736, 0, + 1, 0, 0, 0, 20480, 44703000, 64, 384, 0, 44703, 0, + 2, 0, 0, 0, 20480, 73092000, 512, 1440, 0, 73092, 0, + 3, 0, 0, 0, 20480, 78604000, 512, 1536, 0, 78604, 0, + 4, 0, 0, 0, 20480, 47674000, 184, 384, 0, 47674, 0, + 5, 0, 0, 0, 20480, 19524000, 192, 128, 0, 19524, 0, + 6, 0, 0, 0, 20480, 45942000, 192, 384, 0, 45942, 0, + 7, 0, 0, 0, 20480, 31244000, 256, 256, 0, 31244, 0, + 8, 0, 0, 0, 20480, 46978000, 256, 384, 0, 46978, 0, + 9, 0, 0, 0, 20480, 45016000, 360, 360, 0, 45016, 0, + 10, 0, 0, 0, 20480, 92684000, 1440, 1536, 0, 92684, 0, + 11, 0, 0, 0, 20480, 44535000, 1536, 512, 0, 44535, 0, + 12, 0, 0, 0, 20480, 30050000, 384, 192, 0, 30050, 0, + 13, 0, 0, 0, 20480, 35152000, 384, 256, 0, 35152, 0, + 14, 0, 0, 0, 20480, 81647000, 1536, 1440, 0, 81647, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 20480, 29755000, 64, 192, 0, 29755, 0, + 1, 0, 0, 0, 20480, 58017000, 64, 384, 0, 58017, 0, + 2, 0, 0, 0, 20480, 103471000, 512, 1440, 0, 103471, 0, + 3, 0, 0, 0, 20480, 111431000, 512, 1536, 0, 111431, 0, + 4, 0, 0, 0, 20480, 59433000, 184, 384, 0, 59433, 0, + 5, 0, 0, 0, 20480, 25771000, 192, 128, 0, 25771, 0, + 6, 0, 0, 0, 20480, 54923000, 192, 384, 0, 54923, 0, + 7, 0, 0, 0, 20480, 42727000, 256, 256, 0, 42727, 0, + 8, 0, 0, 0, 20480, 55791000, 256, 384, 0, 55791, 0, + 9, 0, 0, 0, 20480, 57647000, 360, 360, 0, 57647, 0, + 10, 0, 0, 0, 20480, 129703000, 1440, 1536, 0, 129703, 0, + 11, 0, 0, 0, 20480, 60467000, 1536, 512, 0, 60467, 0, + 12, 0, 0, 0, 20480, 34239000, 384, 192, 0, 34239, 0, + 13, 0, 0, 0, 20480, 45743000, 384, 256, 0, 45743, 0, + 14, 0, 0, 0, 20480, 113667000, 1536, 1440, 0, 113667, 0] +#endif + + index = __COUNTER__ diff --git a/src/audio/asrc/asrc_farrow.c b/src/audio/asrc/asrc_farrow.c index 038186054102..dcd58fad22bf 100644 --- a/src/audio/asrc/asrc_farrow.c +++ b/src/audio/asrc/asrc_farrow.c @@ -1,19 +1,22 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2012-2019 Intel Corporation. All rights reserved. +// Copyright(c) 2012-2022 Intel Corporation. All rights reserved. /* @brief Implementation of the sample rate converter. */ #include <sof/common.h> -#include <sof/debug/panic.h> +#include <rtos/panic.h> #include <sof/math/numbers.h> #include <sof/platform.h> -#include <sof/string.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <sof/audio/format.h> +#include <sof/lib/memory.h> #include <user/trace.h> -#include <sof/audio/asrc/asrc_config.h> -#include <sof/audio/asrc/asrc_farrow.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "asrc_farrow.h" + +LOG_MODULE_DECLARE(asrc, CONFIG_SOF_LOG_LEVEL); #define CONVERT_COEFF(x) ((int32_t)(x)) @@ -92,47 +95,47 @@ struct asrc_filter_params { * filters. */ static const struct asrc_filter_params c_filter_params[CR_NUM] = { -#include <sof/audio/coefficients/asrc/asrc_farrow_param_44100Hz_to_48000Hz.h> -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_48000Hz.h> +#include "coef/asrc_farrow_param_44100Hz_to_48000Hz.h" +#include "coef/asrc_farrow_param_48000Hz_to_48000Hz.h" #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_08000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_24000Hz_to_08000Hz.h> +#include "coef/asrc_farrow_param_24000Hz_to_08000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_24000Hz_to_16000Hz.h> +#include "coef/asrc_farrow_param_24000Hz_to_16000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_08000Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_08000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_11025Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_11025Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_12000Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_12000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_16000Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_16000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_22050Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_22050Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_24000Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_24000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_32000Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_32000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100) -#include <sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_44100Hz.h> +#include "coef/asrc_farrow_param_48000Hz_to_44100Hz.h" #endif }; @@ -142,64 +145,105 @@ static const struct asrc_filter_params c_filter_params[CR_NUM] = { * coefficients will be attached to the _Src_farrow struct via the * initialise_filter function. */ -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_44100Hz_to_48000Hz.h> -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_48000Hz.h> +#if SOF_USE_MIN_HIFI(5, ASRC) +#include "coef/asrc_farrow_coeff_4x_44100Hz_to_48000Hz.h" +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_48000Hz.h" #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_08000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_08000Hz.h> +#include "coef/asrc_farrow_coeff_4x_24000Hz_to_08000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_16000Hz.h> +#include "coef/asrc_farrow_coeff_4x_24000Hz_to_16000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_08000Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_08000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_11025Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_11025Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_12000Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_12000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_16000Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_16000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_22050Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_22050Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_24000Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_24000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_32000Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_32000Hz.h" #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100) -#include <sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_44100Hz.h> +#include "coef/asrc_farrow_coeff_4x_48000Hz_to_44100Hz.h" #endif +#else +#include "coef/asrc_farrow_coeff_44100Hz_to_48000Hz.h" -/* - * FUNCTION DECLARATIONS - */ +#include "coef/asrc_farrow_coeff_48000Hz_to_48000Hz.h" + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_08000) +#include "coef/asrc_farrow_coeff_24000Hz_to_08000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000) +#include "coef/asrc_farrow_coeff_24000Hz_to_16000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000) +#include "coef/asrc_farrow_coeff_48000Hz_to_08000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025) +#include "coef/asrc_farrow_coeff_48000Hz_to_11025Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000) +#include "coef/asrc_farrow_coeff_48000Hz_to_12000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000) +#include "coef/asrc_farrow_coeff_48000Hz_to_16000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050) +#include "coef/asrc_farrow_coeff_48000Hz_to_22050Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000) +#include "coef/asrc_farrow_coeff_48000Hz_to_24000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000) +#include "coef/asrc_farrow_coeff_48000Hz_to_32000Hz.h" +#endif + +#if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100) +#include "coef/asrc_farrow_coeff_48000Hz_to_44100Hz.h" +#endif +#endif /* - * Initialises the pointers to the buffers and zeroes their content + * FUNCTION DECLARATIONS */ -static enum asrc_error_code initialise_buffer(struct asrc_farrow *src_obj); /* * Initialise the pointers to the filters, set the number of filters * and their length */ -static enum asrc_error_code initialise_filter(struct comp_dev *dev, +static enum asrc_error_code initialise_filter(struct processing_module *mod, struct asrc_farrow *src_obj); /* @@ -212,49 +256,40 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, * ------------------------------|-------------------------------------| * 0x0000 |asrc_farrow src_obj | * ------------------------------|-------------------------------------| - * &src_obj + sizeof(src_obj) |int_x *buffer_pointer[num_channels] | - * | | + * &src_obj + 1 |int32 impulse_response[filter_length]| + * ------------------------------|-------------------------------------| + * &impulse_response[0] + |int_x *buffer_pointer[num_channels] | + * filter_length | | * ------------------------------|-------------------------------------| - * &buffer_pointer[0] |int_x ring_buffer[num_channels | - * + num_channels*sizeof(int_x *)| *buffer_size] | - * ------------------------------|---------------------------------_---| - * &ring_buffer[0] |int32 impulse_response[filter_length]| - * + num_channels*buffer_size | | - * *sizeof(int_x) | | * * Info: * * buffer_pointer[num_channels]: - * Pointers to each channels data stored internally. ring_buffers_x points to - * the first of these pointers. - * - * int_x ring_buffer[num_channels * buffer_size]: - * This is where the actual input data is buffered. + * Pointers to each channels data. Buffers are allocated externally. */ -enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, +enum asrc_error_code asrc_get_required_size(struct processing_module *mod, int *required_size, int num_channels, int bit_depth) { - int filter_length = 128; - int buffer_length = 256; + struct comp_dev *dev = mod->dev; int size; /* check for parameter errors */ if (!required_size) { - comp_err(dev, "asrc_get_required_size(), invalid required_size"); + comp_err(dev, "invalid required_size"); return ASRC_EC_INVALID_POINTER; } if (num_channels < 1) { - comp_err(dev, "asrc_get_required_size(), invalid num_channels = %d", + comp_err(dev, "invalid num_channels = %d", num_channels); return ASRC_EC_INVALID_NUM_CHANNELS; } if (bit_depth != 16 && bit_depth != 32) { - comp_err(dev, "asrc_get_required_size_bytes(), invalid bit_depth = %d", + comp_err(dev, "invalid bit_depth = %d", bit_depth); return ASRC_EC_INVALID_BIT_DEPTH; } @@ -273,22 +308,22 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, /* accumulate the size */ size = sizeof(struct asrc_farrow); - size += sizeof(int32_t *) * num_channels; /* pointers the the buffers */ - /* size of the ring buffers */ - size += buffer_length * num_channels * (bit_depth / 8); + /* size of the impulse response */ - size += filter_length * sizeof(int32_t); + size += ASRC_MAX_FILTER_LENGTH * sizeof(int32_t); - *required_size = size; + /* size of pointers to the buffers */ + size += sizeof(int32_t *) * num_channels; + *required_size = size; return ASRC_EC_OK; } -enum asrc_error_code asrc_initialise(struct comp_dev *dev, +enum asrc_error_code asrc_initialise(struct processing_module *mod, 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, @@ -297,38 +332,39 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, enum asrc_control_mode control_mode, enum asrc_operation_mode operation_mode) { + struct comp_dev *dev = mod->dev; enum asrc_error_code error_code; /* check for parameter errors */ if (!src_obj) { - comp_err(dev, "asrc_initialise(), null src_obj"); + comp_err(dev, "null src_obj"); return ASRC_EC_INVALID_POINTER; } if (num_channels < 1) { - comp_err(dev, "asrc_initialise(), num_channels = %d", + comp_err(dev, "num_channels = %d", num_channels); return ASRC_EC_INVALID_NUM_CHANNELS; } if (fs_prim < 8000 || fs_prim > 192000) { - comp_err(dev, "asrc_initialise(), fs_prim = %d", fs_prim); + comp_err(dev, "fs_prim = %d", fs_prim); return ASRC_EC_INVALID_SAMPLE_RATE; } if (fs_sec < 8000 || fs_sec > 192000) { - comp_err(dev, "asrc_initialise(), fs_src = %d", fs_sec); + comp_err(dev, "fs_src = %d", fs_sec); return ASRC_EC_INVALID_SAMPLE_RATE; } if (buffer_length < 2) { - comp_err(dev, "asrc_initialise(), buffer_length = %d", + comp_err(dev, "buffer_length = %d", buffer_length); return ASRC_EC_INVALID_BUFFER_LENGTH; } if (bit_depth != 16 && bit_depth != 32) { - comp_err(dev, "asrc_initialise(), bit_depth = %d", + comp_err(dev, "bit_depth = %d", bit_depth); return ASRC_EC_INVALID_BIT_DEPTH; } @@ -361,64 +397,42 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, /* check conversion ratios */ if (src_obj->fs_ratio == 0 || src_obj->fs_ratio_inv == 0) { - comp_err(dev, "asrc_initialise(), fail to calculate ratios"); + comp_err(dev, "fail to calculate ratios"); return ASRC_EC_INVALID_CONVERSION_RATIO; } /* - * The pointer to the internal ring buffer pointers is - * pointing to the memory subsequently to the memory where the - * src_obj lies. Only one of the buffers is initialised, - * depending on the specified bit depth. + * Set the pointer for the impulse response. It is just after + * src_obj in memory. */ - if (src_obj->bit_depth == 32) { - src_obj->ring_buffers32 = (int32_t **)(src_obj + 1); - src_obj->ring_buffers16 = NULL; - } else if (src_obj->bit_depth == 16) { - src_obj->ring_buffers16 = (int16_t **)(src_obj + 1); - src_obj->ring_buffers32 = NULL; - } + src_obj->impulse_response = (int32_t *)(src_obj + 1); /* * Load the filter coefficients and parameters. This function * also sets the pointer to the corresponding * calc_impulse_response_nX function. */ - error_code = initialise_filter(dev, src_obj); + error_code = initialise_filter(mod, src_obj); /* check for errors */ if (error_code != ASRC_EC_OK) { - comp_err(dev, "asrc_initialise(), failed filter initialise"); - return error_code; - } - - /* set the channel pointers and fill buffers with zeros */ - error_code = initialise_buffer(src_obj); - - /* check for errors */ - if (error_code != ASRC_EC_OK) { - comp_err(dev, "asrc_initialise(), failed buffer initialise"); + comp_err(dev, "failed filter initialise"); return error_code; } /* - * Set the pointer for the impulse response. - * &m_impulse_response[0] = ring_buffers_x - * + num_channels * (1 + buffer_length); - * Here ring_buffer_x already points to the memory just behind - * the src_obj. The offset results from the number of pointers - * pointing to each channel and each channels buffer data. + * The pointer to the internal ring buffer pointers is + * after impulse_response. Only one of the buffers is initialised, + * depending on the specified bit depth. */ if (src_obj->bit_depth == 32) { - src_obj->impulse_response = - (int32_t *)(src_obj->ring_buffers32 + - src_obj->num_channels * - (1 + src_obj->buffer_length)); + src_obj->ring_buffers16 = NULL; + src_obj->ring_buffers32 = (int32_t **)(src_obj->impulse_response + + src_obj->filter_length); } else if (src_obj->bit_depth == 16) { - src_obj->impulse_response = - (int32_t *)(src_obj->ring_buffers16 + - src_obj->num_channels * - (1 + src_obj->buffer_length / 2)); + src_obj->ring_buffers32 = NULL; + src_obj->ring_buffers16 = (int16_t **)(src_obj->impulse_response + + src_obj->filter_length); } /* return ok, if everything worked out */ @@ -426,28 +440,30 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, return ASRC_EC_OK; } -enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, +enum asrc_error_code asrc_set_fs_ratio(struct processing_module *mod, struct asrc_farrow *src_obj, int32_t fs_prim, int32_t fs_sec) { + struct comp_dev *dev = mod->dev; + /* Check for parameter errors */ if (!src_obj) { - comp_err(dev, "asrc_set_fs_ratio(), null src_obj"); + comp_err(dev, "null src_obj"); return ASRC_EC_INVALID_POINTER; } if (!src_obj->is_initialised) { - comp_err(dev, "asrc_set_fs_ratio(), not initialised"); + comp_err(dev, "not initialised"); return ASRC_EC_INIT_FAILED; } if (fs_prim < 8000 || fs_prim > 192000) { - comp_err(dev, "asrc_set_fs_ratio(), fs_prim = %d", fs_prim); + comp_err(dev, "fs_prim = %d", fs_prim); return ASRC_EC_INVALID_SAMPLE_RATE; } if (fs_sec < 8000 || fs_sec > 192000) { - comp_err(dev, "asrc_set_fs_ratio(), fs_sec = %d", fs_sec); + comp_err(dev, "fs_sec = %d", fs_sec); return ASRC_EC_INVALID_SAMPLE_RATE; } @@ -467,7 +483,7 @@ enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, /* check conversion ratios */ if (src_obj->fs_ratio == 0 || src_obj->fs_ratio_inv == 0) { - comp_err(dev, "asrc_set_fs_ratio(), failed to calculate ratios"); + comp_err(dev, "failed to calculate ratios"); return ASRC_EC_INVALID_CONVERSION_RATIO; } @@ -478,31 +494,25 @@ enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, /* See initialise_asrc(...) for further information * Update the filters accordingly */ - enum asrc_error_code error_code = initialise_filter(dev, src_obj); - /* check for errors */ - if (error_code != ASRC_EC_OK) { - comp_err(dev, "asrc_set_fs_ratio(), failed filter initialise"); - return error_code; - } - - /* Set the channel pointers and zero the buffers */ - error_code = initialise_buffer(src_obj); + enum asrc_error_code error_code = initialise_filter(mod, src_obj); /* check for errors */ if (error_code != ASRC_EC_OK) { - comp_err(dev, "asrc_set_fs_ratio(), failed buffer initialise"); + comp_err(dev, "failed filter initialise"); return error_code; } - /* Set the pointer for the impulse response */ + /* The pointer to the internal ring buffer pointers is + * after impulse_response. Only one of the buffers is initialised, + * depending on the specified bit depth. + */ if (src_obj->bit_depth == 32) { - src_obj->impulse_response = - (int32_t *)(src_obj->ring_buffers32 + - src_obj->num_channels * (1 + src_obj->buffer_length)); + src_obj->ring_buffers16 = NULL; + src_obj->ring_buffers32 = (int32_t **)(src_obj->impulse_response + + src_obj->filter_length); } else if (src_obj->bit_depth == 16) { - src_obj->impulse_response = - (int32_t *)(src_obj->ring_buffers16 + - src_obj->num_channels * - (1 + src_obj->buffer_length / 2)); + src_obj->ring_buffers32 = NULL; + src_obj->ring_buffers16 = (int16_t **)(src_obj->impulse_response + + src_obj->filter_length); } return ASRC_EC_OK; @@ -514,12 +524,12 @@ enum asrc_error_code asrc_set_input_format(struct comp_dev *dev, { /* check for parameter errors */ if (!src_obj) { - comp_err(dev, "asrc_set_input_format(), null src_obj"); + comp_err(dev, "null src_obj"); return ASRC_EC_INVALID_POINTER; } if (!src_obj->is_initialised) { - comp_err(dev, "asrc_set_input_format(), not initialised"); + comp_err(dev, "not initialised"); return ASRC_EC_INIT_FAILED; } @@ -534,12 +544,12 @@ enum asrc_error_code asrc_set_output_format(struct comp_dev *dev, { /* check for parameter errors */ if (!src_obj) { - comp_err(dev, "asrc_set_output_format(), null src_obj"); + comp_err(dev, "null src_obj"); return ASRC_EC_INVALID_POINTER; } if (!src_obj->is_initialised) { - comp_err(dev, "asrc_set_output_format(), not initialised"); + comp_err(dev, "not initialised"); return ASRC_EC_INIT_FAILED; } @@ -548,66 +558,40 @@ enum asrc_error_code asrc_set_output_format(struct comp_dev *dev, return ASRC_EC_OK; } -/* - * BUFFER FUNCTIONS - */ -static enum asrc_error_code initialise_buffer(struct asrc_farrow *src_obj) +static const int32_t *__get_polyphase_filter(struct processing_module *mod, + const int32_t *filter, size_t size) { - uint8_t *buffer; - int ch; - int n; - - /* - * base_address points to the first address subsequently to the - * memory where the pointers to each ring buffer are stored. - */ - if (src_obj->bit_depth == 32) - buffer = (uint8_t *)(src_obj->ring_buffers32 + - src_obj->num_channels); - else if (src_obj->bit_depth == 16) - buffer = (uint8_t *)(src_obj->ring_buffers16 + - src_obj->num_channels); - - /* - * set buffer_length to filter_length * 2 to compensate for - * missing element wise wrap around while loading but allowing - * aligned loads. - */ - src_obj->buffer_length = src_obj->filter_length * 2; - src_obj->buffer_write_position = src_obj->filter_length; +#if CONFIG_FAST_GET + return mod_fast_get(mod, filter, size); +#else + return filter; +#endif +} - /* set the base addresses for every channel and initialise the - * buffers to zero - */ - if (src_obj->bit_depth == 32) { - for (ch = 0; ch < src_obj->num_channels; ch++) { - src_obj->ring_buffers32[ch] = ((int32_t *)buffer) + - ch * src_obj->buffer_length; +#define get_polyphase_filter(m, f) __get_polyphase_filter(m, f, sizeof(f)) - /* initialise to zero */ - for (n = 0; n < src_obj->buffer_length; n++) - src_obj->ring_buffers32[ch][n] = 0; - } - } else if (src_obj->bit_depth == 16) { - for (ch = 0; ch < src_obj->num_channels; ch++) { - src_obj->ring_buffers16[ch] = ((int16_t *)buffer) + - ch * src_obj->buffer_length; +static void put_polyphase_filter(struct processing_module *mod, const int32_t *filter) +{ +#if CONFIG_FAST_GET + mod_fast_put(mod, filter); +#endif +} - /* initialise to zero */ - for (n = 0; n < src_obj->buffer_length; n++) - src_obj->ring_buffers16[ch][n] = 0; - } +void asrc_free_polyphase_filter(struct processing_module *mod, struct asrc_farrow *src_obj) +{ + if (src_obj && src_obj->polyphase_filters) { + put_polyphase_filter(mod, src_obj->polyphase_filters); + src_obj->polyphase_filters = NULL; } - - return ASRC_EC_OK; } /* * FILTER FUNCTIONS */ -static enum asrc_error_code initialise_filter(struct comp_dev *dev, +static enum asrc_error_code initialise_filter(struct processing_module *mod, struct asrc_farrow *src_obj) { + struct comp_dev *dev = mod->dev; int fs_in; int fs_out; @@ -628,11 +612,11 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, /* Reset coefficients for possible exit with error. */ src_obj->filter_length = 0; src_obj->num_filters = 0; - src_obj->polyphase_filters = NULL; + asrc_free_polyphase_filter(mod, src_obj); if (fs_in == 0 || fs_out == 0) { /* Avoid possible divisions by zero. */ - comp_err(dev, "initialise_filter(), fs_in = %d, fs_out = %d", + comp_err(dev, "fs_in = %d, fs_out = %d", fs_in, fs_out); return ASRC_EC_INVALID_SAMPLE_RATE; } else if (fs_in == 48000 && fs_out >= 48000) { @@ -644,7 +628,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO48000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO48000].num_filters; - src_obj->polyphase_filters = &coeff48000to48000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to48000); } else if (fs_in <= fs_out) { /* All upsampling use cases can share the same set of * filter coefficients. @@ -653,7 +637,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_44100TO48000].filter_length; src_obj->num_filters = c_filter_params[CR_44100TO48000].num_filters; - src_obj->polyphase_filters = &coeff44100to48000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff44100to48000); } else if (fs_in == 48000) { switch (fs_out) { #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000) @@ -662,7 +646,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO08000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO08000].num_filters; - src_obj->polyphase_filters = &coeff48000to08000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to08000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025) @@ -671,7 +655,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO11025].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO11025].num_filters; - src_obj->polyphase_filters = &coeff48000to11025[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to11025); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000) @@ -680,7 +664,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO12000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO12000].num_filters; - src_obj->polyphase_filters = &coeff48000to12000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to12000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000) @@ -689,7 +673,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO16000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO16000].num_filters; - src_obj->polyphase_filters = &coeff48000to16000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to16000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050) @@ -698,7 +682,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO22050].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO22050].num_filters; - src_obj->polyphase_filters = &coeff48000to22050[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to22050); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000) @@ -707,7 +691,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO24000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO24000].num_filters; - src_obj->polyphase_filters = &coeff48000to24000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to24000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000) @@ -716,7 +700,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO32000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO32000].num_filters; - src_obj->polyphase_filters = &coeff48000to32000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to32000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100) @@ -725,11 +709,11 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO44100].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO44100].num_filters; - src_obj->polyphase_filters = &coeff48000to44100[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to44100); break; #endif default: - comp_err(dev, "initialise_filter(), fs_out = %d", + comp_err(dev, "fs_out = %d", fs_out); return ASRC_EC_INVALID_SAMPLE_RATE; } @@ -741,7 +725,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_24000TO08000].filter_length; src_obj->num_filters = c_filter_params[CR_24000TO08000].num_filters; - src_obj->polyphase_filters = &coeff24000to08000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff24000to08000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000) @@ -750,20 +734,27 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_24000TO16000].filter_length; src_obj->num_filters = c_filter_params[CR_24000TO16000].num_filters; - src_obj->polyphase_filters = &coeff24000to16000[0]; + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff24000to16000); break; #endif default: - comp_err(dev, "initialise_filter(), fs_out = %d", + comp_err(dev, "fs_out = %d", fs_out); return ASRC_EC_INVALID_SAMPLE_RATE; } } else { /* Conversion ratio is not supported. */ - comp_err(dev, "initialise_filter(), fs_in = %d", fs_in); + comp_err(dev, "fs_in = %d", fs_in); return ASRC_EC_INVALID_SAMPLE_RATE; } + /* Check that filter length does not exceed allocated */ + if (src_obj->filter_length > ASRC_MAX_FILTER_LENGTH) { + comp_err(dev, "filter_length %d exceeds max", + src_obj->filter_length); + return ASRC_EC_INVALID_FILTER_LENGTH; + } + /* The function pointer is set according to the number of polyphase * filters */ @@ -781,7 +772,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, src_obj->calc_ir = &asrc_calc_impulse_response_n7; break; default: - comp_err(dev, "initialise_filter(), num_filters = %d", + comp_err(dev, "num_filters = %d", src_obj->num_filters); return ASRC_EC_INVALID_CONVERSION_RATIO; } @@ -798,12 +789,12 @@ enum asrc_error_code asrc_update_drift(struct comp_dev *dev, /* check for parameter errors */ if (!src_obj) { - comp_err(dev, "asrc_update_drift(), null src_obj"); + comp_err(dev, "null src_obj"); return ASRC_EC_INVALID_POINTER; } if (!src_obj->is_initialised) { - comp_err(dev, "asrc_update_drift(), not initialised"); + comp_err(dev, "not initialised"); return ASRC_EC_INIT_FAILED; } @@ -814,7 +805,7 @@ enum asrc_error_code asrc_update_drift(struct comp_dev *dev, /* Skew is Q2.30 */ if (clock_skew < SKEW_MIN || clock_skew > SKEW_MAX) { - comp_err(dev, "asrc_update_drift(), clock_skew = %d", + comp_err(dev, "clock_skew = %d", clock_skew); return ASRC_EC_INVALID_CLOCK_SKEW; } @@ -846,12 +837,12 @@ enum asrc_error_code asrc_update_fs_ratio(struct comp_dev *dev, /* Check input for errors */ if (!src_obj) { - comp_err(dev, "asrc_update_fs_ratio(), null src_obj"); + comp_err(dev, "null src_obj"); return ASRC_EC_INVALID_POINTER; } if (!src_obj->is_initialised) { - comp_err(dev, "asrc_update_fs_ratio(), not initialized"); + comp_err(dev, "not initialized"); return ASRC_EC_INIT_FAILED; } @@ -897,11 +888,11 @@ void asrc_write_to_ring_buffer16(struct asrc_farrow *src_obj, int m; /* update the buffer_write_position */ - (src_obj->buffer_write_position)++; + (src_obj->buffer_write_position)--; /* since it's a ring buffer we need a wrap around */ - if (src_obj->buffer_write_position >= src_obj->buffer_length) - src_obj->buffer_write_position -= (src_obj->buffer_length >> 1); + if (src_obj->buffer_write_position < 0) + src_obj->buffer_write_position += (src_obj->buffer_length >> 1); /* handle input format */ if (src_obj->input_format == ASRC_IOF_INTERLEAVED) @@ -911,7 +902,7 @@ void asrc_write_to_ring_buffer16(struct asrc_farrow *src_obj, /* write data to each channel */ j = src_obj->buffer_write_position; - k = j - (src_obj->buffer_length >> 1); + k = j + (src_obj->buffer_length >> 1); for (ch = 0; ch < src_obj->num_channels; ch++) { /* * Since we want the filter function to load 64 bit of @@ -939,11 +930,11 @@ void asrc_write_to_ring_buffer32(struct asrc_farrow *src_obj, int m; /* update the buffer_write_position */ - (src_obj->buffer_write_position)++; + (src_obj->buffer_write_position)--; /* since it's a ring buffer we need a wrap around */ - if (src_obj->buffer_write_position >= src_obj->buffer_length) - src_obj->buffer_write_position -= (src_obj->buffer_length >> 1); + if (src_obj->buffer_write_position < 0) + src_obj->buffer_write_position += (src_obj->buffer_length >> 1); /* handle input format */ if (src_obj->input_format == ASRC_IOF_INTERLEAVED) @@ -953,7 +944,7 @@ void asrc_write_to_ring_buffer32(struct asrc_farrow *src_obj, /* write data to each channel */ j = src_obj->buffer_write_position; - k = j - (src_obj->buffer_length >> 1); + k = j + (src_obj->buffer_length >> 1); for (ch = 0; ch < src_obj->num_channels; ch++) { /* * Since we want the filter function to load 64 bit of @@ -975,7 +966,7 @@ void asrc_write_to_ring_buffer32(struct asrc_farrow *src_obj, enum asrc_error_code asrc_process_push16(struct comp_dev *dev, struct asrc_farrow *src_obj, int16_t **__restrict input_buffers, - int input_num_frames, + int *input_num_frames, int16_t **__restrict output_buffers, int *output_num_frames, int *write_index, @@ -1013,34 +1004,30 @@ enum asrc_error_code asrc_process_push16(struct comp_dev *dev, index_input_frame = 0; /* Run the state machine until all input samples are read */ - while (index_input_frame < input_num_frames) { + while (index_input_frame < *input_num_frames) { if (src_obj->time_value < TIME_VALUE_ONE) { - if (*output_num_frames < max_num_free_frames) { - /* Calculate impulse response */ - (*src_obj->calc_ir)(src_obj); - - /* Filter and write one output sample for each - * channel to the output_buffer - */ - asrc_fir_filter16(src_obj, output_buffers, - src_obj->io_buffer_idx); - - /* Update time and buffer index */ - src_obj->time_value += src_obj->fs_ratio; - src_obj->io_buffer_idx++; - if (src_obj->io_buffer_idx >= - src_obj->io_buffer_length && - src_obj->io_buffer_mode == ASRC_BM_CIRCULAR) - /* Wrap around */ - src_obj->io_buffer_idx = 0; - - (*output_num_frames)++; - } else { - comp_err(dev, "error onf=%d, max=%d", - *output_num_frames, - max_num_free_frames); + if (*output_num_frames == max_num_free_frames) break; - } + + /* Calculate impulse response */ + (*src_obj->calc_ir)(src_obj); + + /* Filter and write one output sample for each + * channel to the output_buffer + */ + asrc_fir_filter16(src_obj, output_buffers, + src_obj->io_buffer_idx); + + /* Update time and buffer index */ + src_obj->time_value += src_obj->fs_ratio; + src_obj->io_buffer_idx++; + + /* Wrap around */ + if (src_obj->io_buffer_mode == ASRC_BM_CIRCULAR && + src_obj->io_buffer_idx >= src_obj->io_buffer_length) + src_obj->io_buffer_idx = 0; + + (*output_num_frames)++; } else { /* Consume one input sample */ asrc_write_to_ring_buffer16(src_obj, input_buffers, @@ -1052,12 +1039,13 @@ enum asrc_error_code asrc_process_push16(struct comp_dev *dev, } } *write_index = src_obj->io_buffer_idx; + *input_num_frames = index_input_frame; /* if fixed control mode, update the frames counters and check * if we have reached end of control cycle. */ if (src_obj->control_mode == ASRC_CM_FIXED) { - src_obj->prim_num_frames += input_num_frames; + src_obj->prim_num_frames += *input_num_frames; src_obj->sec_num_frames += *output_num_frames; if (src_obj->prim_num_frames >= src_obj->prim_num_frames_targ && src_obj->sec_num_frames >= src_obj->sec_num_frames_targ) { @@ -1088,7 +1076,7 @@ enum asrc_error_code asrc_process_push16(struct comp_dev *dev, enum asrc_error_code asrc_process_push32(struct comp_dev *dev, struct asrc_farrow *src_obj, int32_t **__restrict input_buffers, - int input_num_frames, + int *input_num_frames, int32_t **__restrict output_buffers, int *output_num_frames, int *write_index, @@ -1124,36 +1112,30 @@ enum asrc_error_code asrc_process_push32(struct comp_dev *dev, *output_num_frames = 0; index_input_frame = 0; - while (index_input_frame < input_num_frames) { + while (index_input_frame < *input_num_frames) { if (src_obj->time_value < TIME_VALUE_ONE) { - if (*output_num_frames < max_num_free_frames) { - /* Calculate impulse response */ - (*src_obj->calc_ir)(src_obj); - - /* Filter and write output sample to - * output_buffer - */ - asrc_fir_filter32(src_obj, output_buffers, - src_obj->io_buffer_idx); - - /* Update time and index */ - src_obj->time_value += src_obj->fs_ratio; - src_obj->io_buffer_idx++; - - /* Wrap around */ - if (src_obj->io_buffer_mode == - ASRC_BM_CIRCULAR && - src_obj->io_buffer_idx >= - src_obj->io_buffer_length) - src_obj->io_buffer_idx = 0; - - (*output_num_frames)++; - } else { - comp_err(dev, "error onf=%d, max=%d", - *output_num_frames, - max_num_free_frames); + if (*output_num_frames == max_num_free_frames) break; - } + + /* Calculate impulse response */ + (*src_obj->calc_ir)(src_obj); + + /* Filter and write output sample to + * output_buffer + */ + asrc_fir_filter32(src_obj, output_buffers, + src_obj->io_buffer_idx); + + /* Update time and index */ + src_obj->time_value += src_obj->fs_ratio; + src_obj->io_buffer_idx++; + + /* Wrap around */ + if (src_obj->io_buffer_mode == ASRC_BM_CIRCULAR && + src_obj->io_buffer_idx >= src_obj->io_buffer_length) + src_obj->io_buffer_idx = 0; + + (*output_num_frames)++; } else { /* Consume input sample */ asrc_write_to_ring_buffer32(src_obj, input_buffers, @@ -1164,14 +1146,14 @@ enum asrc_error_code asrc_process_push32(struct comp_dev *dev, src_obj->time_value -= TIME_VALUE_ONE; } } - *write_index = src_obj->io_buffer_idx; + *input_num_frames = index_input_frame; /* if fixed control mode, update the frames counters and check if we * have reached end of control cycle. */ if (src_obj->control_mode == ASRC_CM_FIXED) { - src_obj->prim_num_frames += input_num_frames; + src_obj->prim_num_frames += *input_num_frames; src_obj->sec_num_frames += *output_num_frames; if (src_obj->prim_num_frames >= src_obj->prim_num_frames_targ && src_obj->sec_num_frames >= src_obj->sec_num_frames_targ) { @@ -1204,7 +1186,7 @@ enum asrc_error_code asrc_process_pull16(struct comp_dev *dev, int16_t **__restrict input_buffers, int *input_num_frames, int16_t **__restrict output_buffers, - int output_num_frames, + int *output_num_frames, int write_index, int *read_index) { @@ -1230,23 +1212,23 @@ enum asrc_error_code asrc_process_pull16(struct comp_dev *dev, *input_num_frames = 0; /* Run state machine until number of output samples are written */ - while (index_output_frame < output_num_frames) { + while (index_output_frame < *output_num_frames) { if (src_obj->time_value_pull < TIME_VALUE_ONE) { /* Consume one input sample */ - if (src_obj->io_buffer_idx != write_index) { - asrc_write_to_ring_buffer16(src_obj, - input_buffers, - src_obj->io_buffer_idx); - src_obj->io_buffer_idx++; - - /* Wrap around */ - if (src_obj->io_buffer_idx >= - src_obj->io_buffer_length && - src_obj->io_buffer_mode == ASRC_BM_CIRCULAR) - src_obj->io_buffer_idx = 0; - - (*input_num_frames)++; - } + if (src_obj->io_buffer_idx == write_index) + break; + + asrc_write_to_ring_buffer16(src_obj, + input_buffers, + src_obj->io_buffer_idx); + src_obj->io_buffer_idx++; + + /* Wrap around */ + if (src_obj->io_buffer_mode == ASRC_BM_CIRCULAR && + src_obj->io_buffer_idx >= src_obj->io_buffer_length) + src_obj->io_buffer_idx = 0; + + (*input_num_frames)++; /* Update time as Q5.27 */ src_obj->time_value = (((int64_t)TIME_VALUE_ONE - @@ -1268,12 +1250,13 @@ enum asrc_error_code asrc_process_pull16(struct comp_dev *dev, } } *read_index = src_obj->io_buffer_idx; + *output_num_frames = index_output_frame; /* if fixed control mode, update the frames counters and check if we * have reached end of control cycle. */ if (src_obj->control_mode == ASRC_CM_FIXED) { - src_obj->prim_num_frames += output_num_frames; + src_obj->prim_num_frames += *output_num_frames; src_obj->sec_num_frames += *input_num_frames; if (src_obj->prim_num_frames >= src_obj->prim_num_frames_targ && src_obj->sec_num_frames >= src_obj->sec_num_frames_targ) { @@ -1306,7 +1289,7 @@ enum asrc_error_code asrc_process_pull32(struct comp_dev *dev, int32_t **__restrict input_buffers, int *input_num_frames, int32_t **__restrict output_buffers, - int output_num_frames, + int *output_num_frames, int write_index, int *read_index) { @@ -1333,23 +1316,23 @@ enum asrc_error_code asrc_process_pull32(struct comp_dev *dev, src_obj->io_buffer_idx = 0; *input_num_frames = 0; - while (index_output_frame < output_num_frames) { + while (index_output_frame < *output_num_frames) { if (src_obj->time_value_pull < TIME_VALUE_ONE) { /* Consume input sample */ - if (src_obj->io_buffer_idx != write_index) { - asrc_write_to_ring_buffer32(src_obj, - input_buffers, - src_obj->io_buffer_idx); - src_obj->io_buffer_idx++; - - /* Wrap around */ - if (src_obj->io_buffer_idx >= - src_obj->io_buffer_length && - src_obj->io_buffer_mode == ASRC_BM_CIRCULAR) - src_obj->io_buffer_idx = 0; - - (*input_num_frames)++; - } + if (src_obj->io_buffer_idx == write_index) + break; + + asrc_write_to_ring_buffer32(src_obj, + input_buffers, + src_obj->io_buffer_idx); + src_obj->io_buffer_idx++; + + /* Wrap around */ + if (src_obj->io_buffer_mode == ASRC_BM_CIRCULAR && + src_obj->io_buffer_idx >= src_obj->io_buffer_length) + src_obj->io_buffer_idx = 0; + + (*input_num_frames)++; /* Update time as Q5.27 */ src_obj->time_value = (((int64_t)TIME_VALUE_ONE - @@ -1371,12 +1354,13 @@ enum asrc_error_code asrc_process_pull32(struct comp_dev *dev, } } *read_index = src_obj->io_buffer_idx; + *output_num_frames = index_output_frame; /* if fixed control mode, update the frames counters and check * if we have reached end of control cycle. */ if (src_obj->control_mode == ASRC_CM_FIXED) { - src_obj->prim_num_frames += output_num_frames; + src_obj->prim_num_frames += *output_num_frames; src_obj->sec_num_frames += *input_num_frames; if (src_obj->prim_num_frames >= src_obj->prim_num_frames_targ && src_obj->sec_num_frames >= src_obj->sec_num_frames_targ) { @@ -1389,7 +1373,7 @@ enum asrc_error_code asrc_process_pull32(struct comp_dev *dev, } if (src_obj->time_value_pull > TIME_VALUE_LIMIT) { - comp_err(dev, "process_pull32(): Time value = %d", + comp_err(dev, "Time value = %d", src_obj->time_value_pull); return ASRC_EC_FAILED_PULL_MODE; } diff --git a/src/include/sof/audio/asrc/asrc_farrow.h b/src/audio/asrc/asrc_farrow.h similarity index 93% rename from src/include/sof/audio/asrc/asrc_farrow.h rename to src/audio/asrc/asrc_farrow.h index c6a654e4bdbf..48e564c2d1e1 100644 --- a/src/include/sof/audio/asrc/asrc_farrow.h +++ b/src/audio/asrc/asrc_farrow.h @@ -46,6 +46,12 @@ #include <stddef.h> #include <stdint.h> +/* + * @brief FIR filter is max 128 taps and delay lines per channel are + * max 256 samples long. + */ +#define ASRC_MAX_FILTER_LENGTH 128 + /* * @brief Define whether the input and output buffers shall be * interleaved or not. @@ -103,41 +109,26 @@ enum asrc_operation_mode { */ enum asrc_error_code { ASRC_EC_OK = 0, /*!< Operation successful. */ - ASRC_EC_INIT_FAILED = -1, /*!< Initialization of the */ - /*!< component failed. */ - ASRC_EC_UPDATE_FS_FAILED = -2, /*!< Control mode is set to */ - /*!< CM_FIXED and update */ - /*!< drift is not called in */ - /*!< time. */ - ASRC_EC_INVALID_POINTER = -3, /*!< Couldn't allocate */ - /*!< memory. Bad pointer. */ - ASRC_EC_INVALID_BUFFER_POINTER = -4, /*!< Internal buffer pointers */ - /*!< are invalid. */ - ASRC_EC_INVALID_SAMPLE_RATE = -5, /*!< Sample rate is not */ - /*!< supported. */ - ASRC_EC_INVALID_CONVERSION_RATIO = -6, /*!< Conversion ratio is not */ - /*!< supported. */ - ASRC_EC_INVALID_BIT_DEPTH = -7, /*!< Bit depth is not */ - /*!< supported. Choose either */ + ASRC_EC_INIT_FAILED = -1, /*!< Initialization of the component failed. */ + ASRC_EC_UPDATE_FS_FAILED = -2, /*!< Control mode is set to CM_FIXED and update */ + /*!< drift is not called in time. */ + ASRC_EC_INVALID_POINTER = -3, /*!< Couldn't allocate memory. Bad pointer. */ + ASRC_EC_INVALID_BUFFER_POINTER = -4, /*!< Internal buffer pointers are invalid. */ + ASRC_EC_INVALID_SAMPLE_RATE = -5, /*!< Sample rate is not supported. */ + ASRC_EC_INVALID_CONVERSION_RATIO = -6, /*!< Conversion ratio is not supported. */ + ASRC_EC_INVALID_BIT_DEPTH = -7, /*!< Bit depth is not supported. Choose either */ /*!< 16 or 32 bit. */ - ASRC_EC_INVALID_NUM_CHANNELS = -8, /*!< Nummber of channels must */ - /*!< be larger than zero. */ - ASRC_EC_INVALID_BUFFER_LENGTH = -9, /*!< Buffer length must be */ - /*!< larger than one. */ - ASRC_EC_INVALID_FRAME_SIZE = -10, /*!< Invalid frame size: must */ - /*!< be greater than 0 for */ - /*!< primary side and */ - /*!< secondary side. */ - ASRC_EC_INVALID_CLOCK_SKEW = -11, /*!< The clock drift is out */ - /*!< of bounds. */ - ASRC_EC_INVALID_CONTROL_MODE = -12, /*!< Call update_fs_ratio() */ - /*!< for feedback, and */ - /*!< update_drift() for fixed */ - /*!< control mode. */ - ASRC_EC_FAILED_PUSH_MODE = -13, /*!< Push mode operation */ - /*!< failed. */ - ASRC_EC_FAILED_PULL_MODE = -14 /*!< Pull mode operation */ - /*!< failed. */ + ASRC_EC_INVALID_NUM_CHANNELS = -8, /*!< Nummber of channels must be larger */ + /*!< than zero. */ + ASRC_EC_INVALID_BUFFER_LENGTH = -9, /*!< Buffer length must be larger than one. */ + ASRC_EC_INVALID_FRAME_SIZE = -10, /*!< Invalid frame size: must be greater than 0 */ + /*!< for primary side and secondary side. */ + ASRC_EC_INVALID_CLOCK_SKEW = -11, /*!< The clock drift is out of bounds. */ + ASRC_EC_INVALID_CONTROL_MODE = -12, /*!< Call update_fs_ratio() for feedback, and */ + /*!< update_drift() for fixed control mode. */ + ASRC_EC_FAILED_PUSH_MODE = -13, /*!< Push mode operation failed. */ + ASRC_EC_FAILED_PULL_MODE = -14, /*!< Pull mode operation failed. */ + ASRC_EC_INVALID_FILTER_LENGTH = -15, /*!< Length exceeds max. */ }; /* @@ -240,7 +231,7 @@ struct asrc_farrow { * @param[in] bit_depth The wordlength that will be used for representing * the PCM samples, must be 16 or 32. */ -enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, +enum asrc_error_code asrc_get_required_size(struct processing_module *mod, int *required_size, int num_channels, int bit_depth); @@ -277,7 +268,7 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, * @param[in] operation_mode Choose 'push' or 'pull', depending on the mode * you want your ASRC to operate in. */ -enum asrc_error_code asrc_initialise(struct comp_dev *dev, +enum asrc_error_code asrc_initialise(struct processing_module *mod, struct asrc_farrow *src_obj, int num_channels, int32_t fs_prim, @@ -290,6 +281,13 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, enum asrc_control_mode control_mode, enum asrc_operation_mode operation_mode); +/* + * @brief Free polyphase filters + * + * @param[in] src_obj Pointer to the ias_src_farrow. + */ +void asrc_free_polyphase_filter(struct processing_module *mod, struct asrc_farrow *src_obj); + /* * @brief Process the sample rate converter for one frame; the frame * consists of @p input_num_frames samples within @p num_channels @@ -310,7 +308,8 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, * interleaved or deinterleaved format, * this should also be correctly * configured in the @p src_obj. - * @param[in] input_num_frames Number of samples in each channel of input + * @param[in, out] input_num_frames + * Number of samples in each channel of input * data (NOT the number of total samples). * @param[out] output_buffers Pointer to the pointers to the 16 bit * buffers the generated samples should @@ -342,7 +341,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, enum asrc_error_code asrc_process_push16(struct comp_dev *dev, struct asrc_farrow *src_obj, int16_t **__restrict input_buffers, - int input_num_frames, + int *input_num_frames, int16_t **__restrict output_buffers, int *output_num_frames, int *write_index, @@ -368,7 +367,8 @@ enum asrc_error_code asrc_process_push16(struct comp_dev *dev, * interleaved or deinterleaved format, * this should also be correctly * configured in the @p src_obj. - * @param[in] input_num_frames Number of samples in each channel of + * @param[in, out] input_num_frames + * Number of samples in each channel of * input data (NOT the number of total samples). * @param[out] output_buffers Pointer to the pointers to the 32 bit * buffers the generated samples should @@ -400,7 +400,7 @@ enum asrc_error_code asrc_process_push16(struct comp_dev *dev, enum asrc_error_code asrc_process_push32(struct comp_dev *dev, struct asrc_farrow *src_obj, int32_t **__restrict input_buffers, - int input_num_frames, + int *input_num_frames, int32_t **__restrict output_buffers, int *output_num_frames, int *write_index, @@ -434,7 +434,8 @@ enum asrc_error_code asrc_process_push32(struct comp_dev *dev, * or deinterleaved format, depending on * the configuration in @p src_obj. No * support for output ring buffers yet. - * @param[in] output_num_frames Number of samples that shall be written + * @param[in, out] output_num_frames + * Number of samples that shall be written * to the output buffer for each channel. * @param[in] write_index Index within the input ring buffer, must * point to the next frame, which has not @@ -467,7 +468,7 @@ enum asrc_error_code asrc_process_pull16(struct comp_dev *dev, int16_t **__restrict input_buffers, int *input_num_frames, int16_t **__restrict output_buffers, - int output_num_frames, + int *output_num_frames, int write_index, int *read_index); @@ -498,7 +499,8 @@ enum asrc_error_code asrc_process_pull16(struct comp_dev *dev, * or deinterleaved format, depending on * the configuration in @p src_obj. No * support for output ring buffers yet. - * @param[in] output_num_frames Number of samples that shall be written + * @param[in, out] output_num_frames + * Number of samples that shall be written * to the output buffer for each channel. * @param[in] write_index Index within the input ring buffer, must * point to the next frame, which has not @@ -531,7 +533,7 @@ enum asrc_error_code asrc_process_pull32(struct comp_dev *dev, int32_t **__restrict input_buffers, int *input_num_frames, int32_t **__restrict output_buffers, - int output_num_frames, + int *output_num_frames, int write_index, int *read_index); @@ -580,6 +582,7 @@ enum asrc_error_code asrc_update_fs_ratio(struct comp_dev *dev, * * Configures the src for given sampling rates. * Shouldn't be called on the fly because the buffers get flushed when called. + * Release buffers BEFORE call this function and allocate them again after function returns. * * Available sample rates [Hz] are: * 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000. @@ -588,7 +591,7 @@ enum asrc_error_code asrc_update_fs_ratio(struct comp_dev *dev, * @param[in] fs_prim Primary sampling rate. * @param[in] fs_sec Secondary sampling rate. */ -enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, +enum asrc_error_code asrc_set_fs_ratio(struct processing_module *mod, struct asrc_farrow *src_obj, int32_t fs_prim, int32_t fs_sec); diff --git a/src/audio/asrc/asrc_farrow_generic.c b/src/audio/asrc/asrc_farrow_generic.c index 51f4210aa429..b2decc07db23 100644 --- a/src/audio/asrc/asrc_farrow_generic.c +++ b/src/audio/asrc/asrc_farrow_generic.c @@ -2,13 +2,15 @@ // // Copyright(c) 2012-2019 Intel Corporation. All rights reserved. -#include <sof/audio/asrc/asrc_config.h> +#include <sof/common.h> -#if ASRC_GENERIC == 1 +#if SOF_USE_HIFI(NONE, ASRC) -#include <sof/audio/asrc/asrc_farrow.h> +#include "asrc_farrow.h" #include <sof/audio/format.h> +LOG_MODULE_DECLARE(asrc, CONFIG_SOF_LOG_LEVEL); + void asrc_fir_filter16(struct asrc_farrow *src_obj, int16_t **output_buffers, int index_output_frame) { @@ -42,7 +44,7 @@ void asrc_fir_filter16(struct asrc_farrow *src_obj, int16_t **output_buffers, * Data is Q1.15, coefficients are Q1.30. Prod will be Qx.45. */ for (n = 0; n < src_obj->filter_length; n++) - prod += (int64_t)(*buffer_p--) * (*filter_p++); + prod += (int64_t)(*buffer_p++) * (*filter_p++); /* Shift left after accumulation, because interim * results might saturate during filtering prod = prod @@ -94,7 +96,7 @@ void asrc_fir_filter32(struct asrc_farrow *src_obj, int32_t **output_buffers, * quality. The product is Qx.54. */ for (n = 0; n < src_obj->filter_length; n++) - prod += (int64_t)(*buffer_p--) * (*filter_p++ >> 8); + prod += (int64_t)(*buffer_p++) * (*filter_p++ >> 8); /* Shift left after accumulation, because interim * results might saturate during filtering prod = prod @@ -358,4 +360,4 @@ void asrc_calc_impulse_response_n7(struct asrc_farrow *src_obj) } } -#endif /* ASRC_GENERIC */ +#endif /* ASRC_HIFI_NONE */ diff --git a/src/audio/asrc/asrc_farrow_hifi3.c b/src/audio/asrc/asrc_farrow_hifi3.c index 5265130ca17a..d6175ac03b4c 100644 --- a/src/audio/asrc/asrc_farrow_hifi3.c +++ b/src/audio/asrc/asrc_farrow_hifi3.c @@ -1,14 +1,16 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2012-2019 Intel Corporation. All rights reserved. +// Copyright(c) 2012-2025 Intel Corporation. -#include <sof/audio/asrc/asrc_config.h> -#include <sof/audio/asrc/asrc_farrow.h> +#include <sof/common.h> -#if ASRC_HIFI3 == 1 +#if SOF_USE_HIFI(3, ASRC) || SOF_USE_HIFI(4, ASRC) +#include "asrc_farrow.h" #include <xtensa/tie/xt_hifi3.h> +LOG_MODULE_DECLARE(asrc, CONFIG_SOF_LOG_LEVEL); + void asrc_fir_filter16(struct asrc_farrow *src_obj, int16_t **output_buffers, int index_output_frame) { @@ -54,7 +56,7 @@ void asrc_fir_filter16(struct asrc_farrow *src_obj, int16_t **output_buffers, /* Iterate over the filter bins */ for (n = 0; n < n_limit; n++) { /* Read four buffered samples at once */ - AE_LA16X4_RIP(buffer0123, align_buffer, buffer_p); + AE_LA16X4_IP(buffer0123, align_buffer, buffer_p); /* Store four bins of the impulse response */ AE_LA32X2_IP(filter01, align_filter, filter_p); @@ -139,7 +141,7 @@ void asrc_fir_filter32(struct asrc_farrow *src_obj, int32_t **output_buffers, /* Iterate over the filter bins */ for (n = 0; n < n_limit; n++) { /* Read two buffered samples at once */ - AE_LA32X2_RIP(buffer01, align_buffer, buffer_p); + AE_LA32X2_IP(buffer01, align_buffer, buffer_p); /* Store two bins of the impulse response */ AE_LA32X2_IP(filter01, align_filter, filter_p); @@ -399,4 +401,4 @@ void asrc_calc_impulse_response_n7(struct asrc_farrow *src_obj) AE_SA64POS_FP(align_out, result_P); } -#endif /* ASRC Hifi3 */ +#endif /* ASRC_HIFI_3 */ diff --git a/src/audio/asrc/asrc_farrow_hifi5.c b/src/audio/asrc/asrc_farrow_hifi5.c new file mode 100644 index 000000000000..29961e8d5d4c --- /dev/null +++ b/src/audio/asrc/asrc_farrow_hifi5.c @@ -0,0 +1,403 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2012-2025 Intel Corporation. + +#include <sof/common.h> + +#if SOF_USE_MIN_HIFI(5, ASRC) + +#include "asrc_farrow.h" +#include <xtensa/tie/xt_hifi5.h> + +LOG_MODULE_DECLARE(asrc, CONFIG_SOF_LOG_LEVEL); + +void asrc_fir_filter16(struct asrc_farrow *src_obj, int16_t **output_buffers, + int index_output_frame) +{ + ae_valignx2 align_filter; + ae_valign align_buffer; + ae_int64 prod; + ae_f32x2 filter01; + ae_f32x2 filter23; + ae_f16x4 buffer0123; + ae_int32x4 *filter_p; + ae_f16x4 *buffer_p; + int n_limit; + int ch; + int n; + int i; + + /* + * Four filter bins are accumulated per iteration. + * 'n_limit' is therefore stored to reduce redundant + * calculations. Also handle possible interleaved output. + */ + n_limit = src_obj->filter_length >> 2; + if (src_obj->output_format == ASRC_IOF_INTERLEAVED) + i = src_obj->num_channels * index_output_frame; + else + i = index_output_frame; + + /* Iterate over each channel */ + for (ch = 0; ch < src_obj->num_channels; ch++) { + /* Pointer to the beginning of the impulse response */ + filter_p = (ae_int32x4 *)&src_obj->impulse_response[0]; + + /* Pointer to the buffered input data */ + buffer_p = + (ae_f16x4 *)&src_obj->ring_buffers16[ch] + [src_obj->buffer_write_position]; + + /* Allows unaligned load of 64 bit per cycle */ + align_filter = AE_LA128_PP(filter_p); + align_buffer = AE_LA64_PP(buffer_p); + + /* Initialise the accumulator */ + prod = AE_ZERO64(); + + /* Iterate over the filter bins */ + for (n = 0; n < n_limit; n++) { + /* Read four buffered samples at once */ + AE_LA16X4_IP(buffer0123, align_buffer, buffer_p); + + /* Store four bins of the impulse response */ + AE_LA32X2X2_IP(filter01, filter23, align_filter, filter_p); + + /* Multiply and accumulate */ + AE_MULAAAAFQ32X16(prod, filter01, filter23, buffer0123); + } + + /* Shift with saturation, use filter01 as scratch */ + filter01 = AE_SLAI32S(AE_ROUND32F48SASYM(prod), 1); + + /* Round 'prod' to 16 bit and store it in + * (de-)interleaved format in the output buffers + */ + AE_S16_0_X(AE_ROUND16X4F32SSYM(filter01, filter01), + (ae_f16 *)&output_buffers[ch][i], 0); + } +} + +void asrc_fir_filter32(struct asrc_farrow *src_obj, int32_t **output_buffers, + int index_output_frame) +{ + ae_valignx2 align_filter; + ae_valignx2 align_buffer; + ae_f64 prod0; + ae_f64 prod1; + ae_f32x2 buffer23; + ae_f32x2 buffer01; + ae_f32x2 filter01; + ae_f32x2 filter23; + const ae_int32x4 *filter_p; + const ae_int32x4 *buffer_p; + int n_limit; + int ch; + int n; + int i; + + /* + * Two filter bins are accumulated per iteration. + * 'n_limit' is therefore stored to reduce redundant + * calculations. Also handle possible interleaved output. + */ + n_limit = src_obj->filter_length >> 2; + if (src_obj->output_format == ASRC_IOF_INTERLEAVED) + i = src_obj->num_channels * index_output_frame; + else + i = index_output_frame; + + /* Iterate over each channel */ + for (ch = 0; ch < src_obj->num_channels; ch++) { + /* Pointer to the beginning of the impulse response */ + filter_p = (ae_int32x4 *)&src_obj->impulse_response[0]; + + /* Pointer to the buffered input data */ + buffer_p = + (ae_int32x4 *)&src_obj->ring_buffers32[ch] + [src_obj->buffer_write_position]; + + /* Allows unaligned load of 64 bit per cycle */ + align_filter = AE_LA128_PP(filter_p); + align_buffer = AE_LA128_PP(buffer_p); + + /* Initialise the accumulators */ + prod0 = AE_ZERO64(); + prod1 = AE_ZERO64(); + + /* Iterate over the filter bins */ + for (n = 0; n < n_limit; n++) { + /* Read four buffered samples */ + AE_LA32X2X2_IP(buffer01, buffer23, align_buffer, buffer_p); + + /* Load four coefficients of the impulse response */ + AE_LA32X2X2_IP(filter01, filter23, align_filter, filter_p); + + /* Multiply and accumulate */ + AE_MULAAF2D32RA_HH_LL(prod0, prod1, buffer01, buffer23, filter01, filter23); + } + + /* Add up the two accumulators */ + prod0 = AE_ADD64S(prod0, prod1); + + /* Shift with saturation */ + buffer01 = AE_SLAI32S(AE_ROUND32F48SASYM(prod0), 1); + + /* Store 'buffer01' in (de-)interleaved format in the output buffers */ + AE_S32_L_X(buffer01, (ae_f32 *)&output_buffers[ch][i], 0); + } +} + +/* + ALGORITHM SPECIFIC FUNCTIONS */ + +void asrc_calc_impulse_response_n4(struct asrc_farrow *src_obj) +{ + ae_f32x2 time_x2; + ae_f32x2 a10; + ae_f32x2 a32; + ae_f32x2 b10; + ae_f32x2 b32; + ae_int32x4 *filter_P; + ae_int32x4 *result_P; + ae_valignx2 align_f; + ae_valignx2 align_out; + int i; + int n; + + /* Set the pointer tot the polyphase filters */ + filter_P = (ae_int32x4 *)&src_obj->polyphase_filters[0]; + + /* + * Set the pointer to the impulse response. + * This is where the result is stored. + */ + result_P = (ae_int32x4 *)&src_obj->impulse_response[0]; + + /* allow unaligned load of 64 bit of polyphase filter coefficients */ + align_f = AE_LA128_PP(filter_P); + align_out = AE_ZALIGN128(); + + /* Get the current fractional time */ + time_x2 = AE_L32_X((ae_f32 *)&src_obj->time_value, 0); + time_x2 = AE_SLAI32S(time_x2, 4); + + /* + * Generates two impulse response bins per iterations. + * 'index_limit' is therefore stored to reduce redundant + * calculations. + */ + n = src_obj->filter_length >> 2; + for (i = 0; i < n; i++) { + /* + * The polyphase filters lie in storage as follows + * (For N = 4, M = 64): + * [g3,0][g3,1][g3,2][g3,3][g2,0][g2,1][g2,2][g2,3]... + * [g0,0][g0,1][g0,2][g0,3][g3,4][g3,5][g3,6][g3,7]... + * [g0,60][g0,61][g0,62][g0,63] + * + * Since the polyphase filter coefficients are stored + * in an appropriate order, we can just load them up, + * one after another. + */ + + /* Load coefficients g3,4*i g3,4*i+1 g3,4*i+2, g3,4*i+3 */ + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + + /* Load coefficients g2,4*i g2,4*i+1 g2,4*i+2, g2,4*i+3 */ + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + + /* + * Use the 'Horner's Method' to calculate the result + * in a numerically stable and efficient way: + * + * Example for one coefficient (N = 4): + * g_out,m = ((g3,m*t + g2,m)*t + g1,m)*t + g0,m + */ + AE_MULAFP32X2RS(a10, b10, time_x2); /* Dual-MAC, could not find */ + AE_MULAFP32X2RS(a32, b32, time_x2); /* suitable HiFi5 quad-MAC */ + + /* Load coefficients g1,4*i g1,4*i+1 g1,4*i+2, g1,4*i+3 */ + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + /* Load coefficients g0,4*i g0,4*i+1 g0,4*i+2, g0,4*i+3 */ + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + /* Store the result */ + AE_SA32X2X2_IP(a10, a32, align_out, result_P); + } + + AE_SA128POS_FP(align_out, result_P); +} + +void asrc_calc_impulse_response_n5(struct asrc_farrow *src_obj) +{ + /* + * See 'calc_impulse_response_n4' for a detailed description + * of the algorithm and data handling + */ + ae_f32x2 time_x2; + ae_f32x2 a10; + ae_f32x2 a32; + ae_f32x2 b10; + ae_f32x2 b32; + ae_int32x4 *filter_P; + ae_int32x4 *result_P; + ae_valignx2 align_f; + ae_valignx2 align_out; + int i; + int n; + + filter_P = (ae_int32x4 *)&src_obj->polyphase_filters[0]; + result_P = (ae_int32x4 *)&src_obj->impulse_response[0]; + + align_f = AE_LA128_PP(filter_P); + align_out = AE_ZALIGN128(); + + time_x2 = AE_L32_X((ae_f32 *)&src_obj->time_value, 0); + time_x2 = AE_SLAI32S(time_x2, 4); + + n = src_obj->filter_length >> 2; + for (i = 0; i < n; i++) { + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_SA32X2X2_IP(b10, b32, align_out, result_P); + + } + AE_SA128POS_FP(align_out, result_P); +} + +void asrc_calc_impulse_response_n6(struct asrc_farrow *src_obj) +{ + /* + * See 'calc_impulse_response_n4' for a detailed description + * of the algorithm and data handling + */ + ae_f32x2 time_x2; + ae_f32x2 a10; + ae_f32x2 a32; + ae_f32x2 b10; + ae_f32x2 b32; + ae_int32x4 *filter_P; + ae_int32x4 *result_P; + ae_valignx2 align_f; + ae_valignx2 align_out; + int i; + int n; + + filter_P = (ae_int32x4 *)&src_obj->polyphase_filters[0]; + result_P = (ae_int32x4 *)&src_obj->impulse_response[0]; + + align_f = AE_LA128_PP(filter_P); + align_out = AE_ZALIGN128(); + + time_x2 = AE_L32_X((ae_f32 *)&src_obj->time_value, 0); + time_x2 = AE_SLAI32S(time_x2, 4); + + n = src_obj->filter_length >> 2; + for (i = 0; i < n; i++) { + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_SA32X2X2_IP(a10, a32, align_out, result_P); + + } + AE_SA128POS_FP(align_out, result_P); +} + +void asrc_calc_impulse_response_n7(struct asrc_farrow *src_obj) +{ + /* + * See 'calc_impulse_response_n4' for a detailed description + * of the algorithm and data handling + */ + ae_f32x2 time_x2; + ae_f32x2 a10; + ae_f32x2 a32; + ae_f32x2 b10; + ae_f32x2 b32; + ae_int32x4 *filter_P; + ae_int32x4 *result_P; + ae_valignx2 align_f; + ae_valignx2 align_out; + int i; + int n; + + filter_P = (ae_int32x4 *)&src_obj->polyphase_filters[0]; + result_P = (ae_int32x4 *)&src_obj->impulse_response[0]; + + align_f = AE_LA128_PP(filter_P); + align_out = AE_ZALIGN128(); + + time_x2 = AE_L32_X((ae_f32 *)&src_obj->time_value, 0); + time_x2 = AE_SLAI32S(time_x2, 4); + + n = src_obj->filter_length >> 2; + for (i = 0; i < n; i++) { + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_LA32X2X2_IP(a10, a32, align_f, filter_P); + AE_MULAFP32X2RS(a10, b10, time_x2); + AE_MULAFP32X2RS(a32, b32, time_x2); + + AE_LA32X2X2_IP(b10, b32, align_f, filter_P); + AE_MULAFP32X2RS(b10, a10, time_x2); + AE_MULAFP32X2RS(b32, a32, time_x2); + + AE_SA32X2X2_IP(b10, b32, align_out, result_P); + } + AE_SA128POS_FP(align_out, result_P); +} + +#endif /* ASRC_HIFI_5 */ diff --git a/src/audio/asrc/asrc_ipc3.c b/src/audio/asrc/asrc_ipc3.c new file mode 100644 index 000000000000..ca917318d7e5 --- /dev/null +++ b/src/audio/asrc/asrc_ipc3.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019-2023 Intel Corporation. All rights reserved. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/ipc-config.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> +#include <sof/common.h> +#include <rtos/string.h> +#include <ipc/stream.h> +#include <user/trace.h> +#include <errno.h> +#include "asrc.h" + +SOF_DEFINE_REG_UUID(asrc); + +DECLARE_TR_CTX(asrc_tr, SOF_UUID(asrc_uuid), LOG_LEVEL_INFO); + +int asrc_dai_configure_timestamp(struct comp_data *cd) +{ + if (cd->dai_dev) + return cd->dai_dev->drv->ops.dai_ts_config(cd->dai_dev); + + return -EINVAL; +} + +int asrc_dai_start_timestamp(struct comp_data *cd) +{ + if (cd->dai_dev) + return cd->dai_dev->drv->ops.dai_ts_start(cd->dai_dev); + + return -EINVAL; +} + +int asrc_dai_stop_timestamp(struct comp_data *cd) +{ + if (cd->dai_dev) + return cd->dai_dev->drv->ops.dai_ts_stop(cd->dai_dev); + + return -EINVAL; +} + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +int asrc_dai_get_timestamp(struct comp_data *cd, struct dai_ts_data *tsd) +#else +int asrc_dai_get_timestamp(struct comp_data *cd, struct timestamp_data *tsd) +#endif +{ + if (!cd->dai_dev) + return -EINVAL; + + return cd->dai_dev->drv->ops.dai_ts_get(cd->dai_dev, tsd); +} + +void asrc_update_buffer_format(struct comp_buffer *buf_c, struct comp_data *cd) +{ + /* IPC3 don't need to update audio stream format here. */ +} + +void asrc_set_stream_params(struct comp_data *cd, struct sof_ipc_stream_params *params) +{ + /* IPC3 don't need to update audio stream format here. */ +} diff --git a/src/audio/asrc/asrc_ipc4.c b/src/audio/asrc/asrc_ipc4.c new file mode 100644 index 000000000000..1047799f207b --- /dev/null +++ b/src/audio/asrc/asrc_ipc4.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019-2023 Intel Corporation. All rights reserved. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/ipc-config.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> +#include <sof/common.h> +#include <rtos/string.h> +#include <ipc/stream.h> +#include <user/trace.h> +#include <errno.h> +#include "asrc.h" + +SOF_DEFINE_REG_UUID(asrc4); + +DECLARE_TR_CTX(asrc_tr, SOF_UUID(asrc4_uuid), LOG_LEVEL_INFO); + +int asrc_dai_configure_timestamp(struct comp_data *cd) +{ + if (!cd->dai_dev) + return -ENODEV; + + struct processing_module *mod = comp_mod(cd->dai_dev); + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + return ops->endpoint_ops->dai_ts_config(cd->dai_dev); +} + +int asrc_dai_start_timestamp(struct comp_data *cd) +{ + if (!cd->dai_dev) + return -ENODEV; + + struct processing_module *mod = comp_mod(cd->dai_dev); + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + return ops->endpoint_ops->dai_ts_start(cd->dai_dev); +} + +int asrc_dai_stop_timestamp(struct comp_data *cd) +{ + if (!cd->dai_dev) + return -ENODEV; + + struct processing_module *mod = comp_mod(cd->dai_dev); + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + return ops->endpoint_ops->dai_ts_stop(cd->dai_dev); +} + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +int asrc_dai_get_timestamp(struct comp_data *cd, struct dai_ts_data *tsd) +#else +int asrc_dai_get_timestamp(struct comp_data *cd, struct timestamp_data *tsd) +#endif +{ + if (!cd->dai_dev) + return -ENODEV; + + struct processing_module *mod = comp_mod(cd->dai_dev); + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + return ops->endpoint_ops->dai_ts_get(cd->dai_dev, tsd); +} + +void asrc_update_buffer_format(struct comp_buffer *buf_c, struct comp_data *cd) +{ + ipc4_update_buffer_format(buf_c, &cd->ipc_config.base.audio_fmt); +} + +void asrc_set_stream_params(struct comp_data *cd, struct sof_ipc_stream_params *params) +{ + ipc4_base_module_cfg_to_stream_params(&cd->ipc_config.base, params); +} diff --git a/src/audio/asrc/asrc_ipc4.h b/src/audio/asrc/asrc_ipc4.h new file mode 100644 index 000000000000..3ac5a33f7179 --- /dev/null +++ b/src/audio/asrc/asrc_ipc4.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/asrc.h + * \brief IPC4 asrc definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_ASRC_H__ +#define __SOF_IPC4_ASRC_H__ + +#include <stdint.h> +#include <ipc4/base-config.h> + +/* + * ASRC_CONFIG Asynchronous Sample Rate Converter module configuration. + * UUID: 66B4402D-B468-42F2-81A7-B37121863DD4 + * + * Module requirements: + * - sample size (bit_depth): 32 bit + * - number of channels: 1, 2, 3, 4, 5, 6, 7, 8 + * + * Following sample conversion ratios are supported (input_frequency/output_frequency): + * 48k/8k, 48k/16k, 48k/24k, 48k/32k, 48k/44.1k, 48k/48k, 44.1k/44.1k, 44.1k/48k, + * 32k/32k, 32k/48k, 24k/8k, 24k/16k, 24k/24k, 24k/48k, 22.05k/48k, 18.9k/48k, + * 16k/8k, 16k/16k, 16k/24k, 16k/48k, 8k/8k, 8k/24k, 8k/48k + * + * ASRC requires special IBS/OBS handling: + * + * In LL mode: + * + * 1. In Playback path (PUSH mode): + * - IBS calculated based on input frequency and sample group size + * - OBS calculated based on output frequency and sample group size, extended by X sample groups + * + * In Capture path (PULL mode): + * - IBS calculated based on input frequency and sample group size, extended by X sample groups + * - OBS calculated based on output frequency and sample group size + * X=3 is maximum number of additional samples that can be produced by ASRC in one cycle + * (related to drift and frequencies not divisible by 1000) + * + * For LL mode, jitter buffers in ASRC feature mask should be enabled (default enabled) + * + * Examples: + * + * ASRC in PULL mode, conversion 48k -> 44.1k, 32bit, 2ch + * - IBS = round_up(freq_in)/1000 * + * channels_num * + * sample_size_in_bytes + (3 * sample_group_size) = + * = 48 * 2 * 4 + 3 * 2 * 4 = 408 + * - OBS = round_up(freq_out)/1000 * + * channels_num * + * sample_size_in_bytes = 45 * 2 * 4 = 360 + * + * In DP mode: + * + * In Playback path (PUSH mode): + * - IBS calculated based on input frequency and DP frame size + * - OBS = round_up((IBS/sample_group_size) * + * (freq_out/freq_in)) * + * sample_group_size + (X * sample_group_size) + * + * In Capture path (PULL mode): + * - OBS calculated based on output frequency and DP frame size + * - IBS = round_up((OBS/sample_group_size) * + * (freq_in/freq_out)) * + * sample_group_size + (X * sample_group_size) + * X=1 is a maximum drift that can be measured for one cycle + * + * For DP mode, jitter buffers in ASRC feature mask should be disabled (default enabled) + * + * ASRC in PUSH mode, conversion 22.05k -> 48k, 32bit, 2ch, DP frame size: 5ms + * - IBS = round_up(freq_in)/1000 * + * channels_num * + * sample_size_in_bytes * + * dp_frame_size = 23 * 2 * 4 * 5 = 920 + * - OBS = round_up((IBS/sample_group_size) * + * (freq_out/freq_in)) * + * sample_group_size + 1 * sample_group_size = + * round_up( 115 * 48000 / 22050 ) * 8 + 1 * 8 = 251 * 8 + 8 = 2016 + */ + +/* This enum defines short 16bit parameters common for all modules. + * Value of module specific parameters have to be less than 0x3000. + */ +enum ipc4_asrc_module_params { + IPC4_MOD_ASRC_SAMPLE_DRIFT = 0x3001, + IPC4_MOD_ASRC_SAMPLE_DRIFT_TOTAL = 0x3002 +}; + +enum ipc4_asrc_features { + /* Playback and capture path for Asrc has different requirmetns for ibs and obs + * asrc flag defined to differentiate between these two paths. + * + * Use for playback/uplink + */ + IPC4_MOD_ASRC_PUSH_MODE = 0, + /* Use for capture/downlink + */ + IPC4_MOD_ASRC_PULL_MODE = 1, + /* Jitter buffer in ASRC implementation is optional and can be disabled + * when using DP mode. For keeping backwards compatibility, by default + * Jitter buffer is enabled + */ + IPC4_MOD_ASRC_DISABLE_JITTER_BUFFER = 4 +}; + +struct ipc4_asrc_module_cfg { + struct ipc4_base_module_cfg base; + /* ASRC output sampling frequency. */ + enum ipc4_sampling_frequency out_freq; + + /* Mask of allowed ASRC features: + * - BITS 0-1 (ASRC mode): + * a. 0 1 - Playback mode / PUSH mode + * b. 1 0 - Capture mode / PULL mode + * + * - BIT 4 (Disable Jitter Buffer): + * a. 0 - Jitter buffer enabled + * b. 1 - Jitter buffer disabled + */ + uint32_t asrc_mode; +} __packed __aligned(4); + +#endif diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_08000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_24000Hz_to_08000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_08000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_24000Hz_to_08000Hz.h index fe089c50c082..149fd5669778 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_08000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_24000Hz_to_08000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 24000 Hz to 8000 Hz */ /* NUM_FILTERS=4, FILTER_LENGTH=128, alpha=6.200000, gamma=0.454000 */ -static const int32_t coeff24000to08000[] = { +__cold_rodata static const int32_t coeff24000to08000[] = { /* Filter #4, conversion from 24000 Hz to 8000 Hz */ CONVERT_COEFF(-10830), /* Filter:4, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_16000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_24000Hz_to_16000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_16000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_24000Hz_to_16000Hz.h index 351c238d5dac..9f0070a48928 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_24000Hz_to_16000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_24000Hz_to_16000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 24000 Hz to 16000 Hz */ /* NUM_FILTERS=6, FILTER_LENGTH=80, alpha=6.800000, gamma=0.460000 */ -static const int32_t coeff24000to16000[] = { +__cold_rodata static const int32_t coeff24000to16000[] = { /* Filter #6, conversion from 24000 Hz to 16000 Hz */ CONVERT_COEFF(-26295), /* Filter:6, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_44100Hz_to_48000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_44100Hz_to_48000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_44100Hz_to_48000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_44100Hz_to_48000Hz.h index 28ff9ae7834d..fca60d5d6b2c 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_44100Hz_to_48000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_44100Hz_to_48000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 44100 Hz to 48000 Hz */ /* NUM_FILTERS=7, FILTER_LENGTH=64, alpha=7.800000, gamma=0.459000 */ -static const int32_t coeff44100to48000[] = { +__cold_rodata static const int32_t coeff44100to48000[] = { /* Filter #7, conversion from 44100 Hz to 48000 Hz */ CONVERT_COEFF(-36104), /* Filter:7, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_08000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_08000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_08000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_08000Hz.h index c4affd499b39..8db0161ae75d 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_08000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_08000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 8000 Hz */ /* NUM_FILTERS=4, FILTER_LENGTH=128, alpha=5.600000, gamma=0.415500 */ -static const int32_t coeff48000to08000[] = { +__cold_rodata static const int32_t coeff48000to08000[] = { /* Filter #4, conversion from 48000 Hz to 8000 Hz */ CONVERT_COEFF(-3301), /* Filter:4, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_11025Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_11025Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_11025Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_11025Hz.h index 0488065745d3..50c25bd2490d 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_11025Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_11025Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 11025 Hz */ /* NUM_FILTERS=4, FILTER_LENGTH=96, alpha=5.700000, gamma=0.417000 */ -static const int32_t coeff48000to11025[] = { +__cold_rodata static const int32_t coeff48000to11025[] = { /* Filter #4, conversion from 48000 Hz to 11025 Hz */ CONVERT_COEFF(-5276), /* Filter:4, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_12000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_12000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_12000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_12000Hz.h index b527b30a982d..69ae4fbd550d 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_12000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_12000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 12000 Hz */ /* NUM_FILTERS=4, FILTER_LENGTH=96, alpha=5.700000, gamma=0.424000 */ -static const int32_t coeff48000to12000[] = { +__cold_rodata static const int32_t coeff48000to12000[] = { /* Filter #4, conversion from 48000 Hz to 12000 Hz */ CONVERT_COEFF(9466), /* Filter:4, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_16000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_16000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_16000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_16000Hz.h index e085df9d34c5..a26687c4afd0 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_16000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_16000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 16000 Hz */ /* NUM_FILTERS=5, FILTER_LENGTH=96, alpha=5.700000, gamma=0.443000 */ -static const int32_t coeff48000to16000[] = { +__cold_rodata static const int32_t coeff48000to16000[] = { /* Filter #5, conversion from 48000 Hz to 16000 Hz */ CONVERT_COEFF(6003), /* Filter:5, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_22050Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_22050Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_22050Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_22050Hz.h index 71daa2c2adae..3ab3c3fc2605 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_22050Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_22050Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 22050 Hz */ /* NUM_FILTERS=5, FILTER_LENGTH=80, alpha=6.900000, gamma=0.440000 */ -static const int32_t coeff48000to22050[] = { +__cold_rodata static const int32_t coeff48000to22050[] = { /* Filter #5, conversion from 48000 Hz to 22050 Hz */ CONVERT_COEFF(7662), /* Filter:5, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_24000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_24000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_24000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_24000Hz.h index 2d075beb243f..9eed3d92451a 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_24000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_24000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 24000 Hz */ /* NUM_FILTERS=5, FILTER_LENGTH=80, alpha=7.500000, gamma=0.440000 */ -static const int32_t coeff48000to24000[] = { +__cold_rodata static const int32_t coeff48000to24000[] = { /* Filter #5, conversion from 48000 Hz to 24000 Hz */ CONVERT_COEFF(-13838), /* Filter:5, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_32000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_32000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_32000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_32000Hz.h index 7dfe46d76bcf..7f798a829ae7 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_32000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_32000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 32000 Hz */ /* NUM_FILTERS=6, FILTER_LENGTH=80, alpha=8.000000, gamma=0.452000 */ -static const int32_t coeff48000to32000[] = { +__cold_rodata static const int32_t coeff48000to32000[] = { /* Filter #6, conversion from 48000 Hz to 32000 Hz */ CONVERT_COEFF(-11561), /* Filter:6, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_44100Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_44100Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_44100Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_44100Hz.h index ef40e3bf690f..505708746f60 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_44100Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_44100Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 44100 Hz */ /* NUM_FILTERS=7, FILTER_LENGTH=64, alpha=8.150000, gamma=0.456000 */ -static const int32_t coeff48000to44100[] = { +__cold_rodata static const int32_t coeff48000to44100[] = { /* Filter #7, conversion from 48000 Hz to 44100 Hz */ CONVERT_COEFF(-34608), /* Filter:7, Coefficient: 1 */ diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_48000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_48000Hz.h similarity index 99% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_48000Hz.h rename to src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_48000Hz.h index c9e0d9b2f671..953a9adbdab3 100644 --- a/src/include/sof/audio/coefficients/asrc/asrc_farrow_coeff_48000Hz_to_48000Hz.h +++ b/src/audio/asrc/coef/asrc_farrow_coeff_48000Hz_to_48000Hz.h @@ -6,7 +6,7 @@ /* Conversion from 48000 Hz to 48000 Hz */ /* NUM_FILTERS=7, FILTER_LENGTH=48, alpha=7.150000, gamma=0.458000 */ -static const int32_t coeff48000to48000[] = { +__cold_rodata static const int32_t coeff48000to48000[] = { /* Filter #7, conversion from 48000 Hz to 48000 Hz */ CONVERT_COEFF(201584), /* Filter:7, Coefficient: 1 */ diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_24000Hz_to_08000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_24000Hz_to_08000Hz.h new file mode 100644 index 000000000000..778de8dfa56e --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_24000Hz_to_08000Hz.h @@ -0,0 +1,618 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 24000 Hz to 8000 Hz */ +/* NUM_FILTERS=4, FILTER_LENGTH=128, alpha=6.200000, gamma=0.454000 */ + +__cold_rodata static const int32_t coeff24000to08000[] = { + + /* Filter #1, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-10830), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(-19325), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-8706), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(17158), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(41187), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(5433), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(-57507), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-85177), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(53742), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(102764), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(56825), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-81566), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(-40910), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(43191), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(132068), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(122684), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(35023), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(21531), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(-20607), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(-56412), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(-28687), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(84875), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(153388), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(85079), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-198613), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(-152429), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(77423), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(318659), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-26903), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(-219188), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(-265221), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-55019), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-45627), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(16004), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(80964), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(83822), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(-97650), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-243132), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(-188414), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(74163), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(320857), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(-4716), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-436161), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(-569989), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(292318), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(469916), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(238081), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-305542), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(3428), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(-103074), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-136759), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-45156), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(342026), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(348018), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(12595), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(-425480), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(-178871), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(504223), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(887721), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(512609), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(-717573), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(-551012), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(198162), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(961755), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(113706), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(201400), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(115814), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(-100685), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-563391), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(-190843), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(456045), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(818713), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-456956), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-1233622), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(-1020591), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(215831), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(1003766), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(97129), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(-1125979), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(-1574771), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-269690), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(-219149), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(49817), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(327706), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(483675), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(-385406), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(-1078344), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(-901092), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(1533583), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(1697790), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(298404), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(-1679597), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-640937), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(1106673), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(2199991), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(1469926), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(353713), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(53122), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(-355599), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(-510586), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(159521), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(1284520), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(1431454), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(273189), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(-2496622), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(-1148947), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(1536178), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(3316675), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(-783087), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(-2766581), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(-2577984), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(34050), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-219636), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(328523), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(671539), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(455239), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(-1358235), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-2033639), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(-951202), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(1203809), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(2363113), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-953893), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(-4000055), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(-3912103), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(3113447), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(3898837), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(1239875), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-3039958), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-218603), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-807891), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-756009), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(-2224), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(2631188), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(1887961), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-716945), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-3109267), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(-210918), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(4333834), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(5693246), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(2072560), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(-5293214), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(-3091666), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(2322327), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(6542868), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(880151), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(1105224), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(358874), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-838150), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(-3059949), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(-204798), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(3314225), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(4395729), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-4059383), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-7516860), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(-4691958), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(2885839), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(5504147), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-735062), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-7351776), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(-8370954), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-1470082), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(-869768), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(620664), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(1797644), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(1651041), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-3053727), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(-5765452), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(-3689804), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(9097774), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(8056110), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(-501272), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(-10047020), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-1927609), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(7351404), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(11484456), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(5838619), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(1543877), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-152285), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-2007072), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(-2377760), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(2092009), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(6966627), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(6364024), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-127424), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(-12064250), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(-3431170), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(9849385), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(16521192), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(-6100793), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(-14529711), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(-11146964), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(3059490), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-667626), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(1968948), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(3348219), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(1996625), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(-7691699), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-9695566), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-3280325), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(7429429), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(9318936), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(-7786997), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-21129476), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-17795597), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(17076149), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(18036447), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(2522929), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(-18539360), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-1439811), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-4374392), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(-4134491), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-185988), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(13688967), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(8930617), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-5110430), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(-18240532), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(2685075), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(25435789), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(30208500), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(8011608), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-26909927), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-11976152), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(18016549), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(38981614), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(5056345), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(7681958), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(5124031), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(-1687599), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-18700492), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(-2525039), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(21825461), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(37870743), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(-28470273), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-50432144), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(-32720110), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(25573931), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(28567790), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(-13547145), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(-58824612), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(-64597690), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-8594673), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(-10910995), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-6715326), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(1653573), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(32251799), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(4871577), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(-29612069), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-50673264), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(95527010), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(134020246), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(111496535), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(33022726), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(-2840724), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(116347844), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(244337981), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(319519294), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(9058182), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(11001115), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(6613114), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(-908182), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(-45371944), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(-17020199), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(17061394), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(37099013), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-62590522), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(-125985859), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(-127527137), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(-74392732), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(303533893), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(204637406), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(72635229), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(-31218589), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-6645584), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(-7338726), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(-3379574), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(1862507), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(33592635), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(12488167), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-10270513), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(-20289677), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(-3539197), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(43642084), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(47036638), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(16924310), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(-69423135), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(-46017033), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(2774597), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(36162526), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(4687214), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(3633943), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(169088), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-2783863), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(-13928301), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(926804), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(12081784), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(12208082), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(-17765712), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(-31677983), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(-19297249), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(5057264), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(34660987), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(7654480), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-19463498), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-26510886), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-3155209), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(-1100082), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(1452075), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(2496940), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(3219751), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(-6628589), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(-9810802), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(-4999762), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(21084806), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(18281519), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(1997933), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(-13157294), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(-12029861), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(9119834), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(19673432), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(13313145), /* Filter:1, Coefficient: 80 */ + + /* Filter #21, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(1470988), /* Filter:4, Coefficient: 81 */ + CONVERT_COEFF(-530883), /* Filter:4, Coefficient: 82 */ + CONVERT_COEFF(-1826789), /* Filter:4, Coefficient: 83 */ + CONVERT_COEFF(-1519560), /* Filter:4, Coefficient: 84 */ + CONVERT_COEFF(2887991), /* Filter:3, Coefficient: 81 */ + CONVERT_COEFF(7345400), /* Filter:3, Coefficient: 82 */ + CONVERT_COEFF(5461142), /* Filter:3, Coefficient: 83 */ + CONVERT_COEFF(-374397), /* Filter:3, Coefficient: 84 */ + CONVERT_COEFF(-15778100), /* Filter:2, Coefficient: 81 */ + CONVERT_COEFF(-5804379), /* Filter:2, Coefficient: 82 */ + CONVERT_COEFF(7156002), /* Filter:2, Coefficient: 83 */ + CONVERT_COEFF(12632597), /* Filter:2, Coefficient: 84 */ + CONVERT_COEFF(-2347060), /* Filter:1, Coefficient: 81 */ + CONVERT_COEFF(-13766705), /* Filter:1, Coefficient: 82 */ + CONVERT_COEFF(-12757053), /* Filter:1, Coefficient: 83 */ + CONVERT_COEFF(-1966773), /* Filter:1, Coefficient: 84 */ + + /* Filter #22, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-77386), /* Filter:4, Coefficient: 85 */ + CONVERT_COEFF(1218353), /* Filter:4, Coefficient: 86 */ + CONVERT_COEFF(1379966), /* Filter:4, Coefficient: 87 */ + CONVERT_COEFF(441511), /* Filter:4, Coefficient: 88 */ + CONVERT_COEFF(-5068027), /* Filter:3, Coefficient: 85 */ + CONVERT_COEFF(-5140982), /* Filter:3, Coefficient: 86 */ + CONVERT_COEFF(-1197542), /* Filter:3, Coefficient: 87 */ + CONVERT_COEFF(3116904), /* Filter:3, Coefficient: 88 */ + CONVERT_COEFF(7480579), /* Filter:2, Coefficient: 85 */ + CONVERT_COEFF(-2749314), /* Filter:2, Coefficient: 86 */ + CONVERT_COEFF(-9360248), /* Filter:2, Coefficient: 87 */ + CONVERT_COEFF(-7716970), /* Filter:2, Coefficient: 88 */ + CONVERT_COEFF(8772201), /* Filter:1, Coefficient: 85 */ + CONVERT_COEFF(11107791), /* Filter:1, Coefficient: 86 */ + CONVERT_COEFF(4436017), /* Filter:1, Coefficient: 87 */ + CONVERT_COEFF(-4741987), /* Filter:1, Coefficient: 88 */ + + /* Filter #23, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-708796), /* Filter:4, Coefficient: 89 */ + CONVERT_COEFF(-1141122), /* Filter:4, Coefficient: 90 */ + CONVERT_COEFF(-618337), /* Filter:4, Coefficient: 91 */ + CONVERT_COEFF(314070), /* Filter:4, Coefficient: 92 */ + CONVERT_COEFF(4381539), /* Filter:3, Coefficient: 89 */ + CONVERT_COEFF(2040448), /* Filter:3, Coefficient: 90 */ + CONVERT_COEFF(-1562338), /* Filter:3, Coefficient: 91 */ + CONVERT_COEFF(-3425561), /* Filter:3, Coefficient: 92 */ + CONVERT_COEFF(-281783), /* Filter:2, Coefficient: 89 */ + CONVERT_COEFF(6309527), /* Filter:2, Coefficient: 90 */ + CONVERT_COEFF(7023993), /* Filter:2, Coefficient: 91 */ + CONVERT_COEFF(2144389), /* Filter:2, Coefficient: 92 */ + CONVERT_COEFF(-8900882), /* Filter:1, Coefficient: 89 */ + CONVERT_COEFF(-5510132), /* Filter:1, Coefficient: 90 */ + CONVERT_COEFF(1698787), /* Filter:1, Coefficient: 91 */ + CONVERT_COEFF(6542354), /* Filter:1, Coefficient: 92 */ + + /* Filter #24, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(865964), /* Filter:4, Coefficient: 93 */ + CONVERT_COEFF(658712), /* Filter:4, Coefficient: 94 */ + CONVERT_COEFF(-34808), /* Filter:4, Coefficient: 95 */ + CONVERT_COEFF(-598408), /* Filter:4, Coefficient: 96 */ + CONVERT_COEFF(-2338169), /* Filter:3, Coefficient: 93 */ + CONVERT_COEFF(422162), /* Filter:3, Coefficient: 94 */ + CONVERT_COEFF(2447614), /* Filter:3, Coefficient: 95 */ + CONVERT_COEFF(2257011), /* Filter:3, Coefficient: 96 */ + CONVERT_COEFF(-3705979), /* Filter:2, Coefficient: 93 */ + CONVERT_COEFF(-5807407), /* Filter:2, Coefficient: 94 */ + CONVERT_COEFF(-3061584), /* Filter:2, Coefficient: 95 */ + CONVERT_COEFF(1669136), /* Filter:2, Coefficient: 96 */ + CONVERT_COEFF(5575464), /* Filter:1, Coefficient: 93 */ + CONVERT_COEFF(397296), /* Filter:1, Coefficient: 94 */ + CONVERT_COEFF(-4329403), /* Filter:1, Coefficient: 95 */ + CONVERT_COEFF(-4978370), /* Filter:1, Coefficient: 96 */ + + /* Filter #25, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-608313), /* Filter:4, Coefficient: 97 */ + CONVERT_COEFF(-139661), /* Filter:4, Coefficient: 98 */ + CONVERT_COEFF(366507), /* Filter:4, Coefficient: 99 */ + CONVERT_COEFF(506515), /* Filter:4, Coefficient: 100 */ + CONVERT_COEFF(327984), /* Filter:3, Coefficient: 97 */ + CONVERT_COEFF(-1565787), /* Filter:3, Coefficient: 98 */ + CONVERT_COEFF(-1944169), /* Filter:3, Coefficient: 99 */ + CONVERT_COEFF(-743409), /* Filter:3, Coefficient: 100 */ + CONVERT_COEFF(4387464), /* Filter:2, Coefficient: 97 */ + CONVERT_COEFF(3269084), /* Filter:2, Coefficient: 98 */ + CONVERT_COEFF(-227334), /* Filter:2, Coefficient: 99 */ + CONVERT_COEFF(-3001559), /* Filter:2, Coefficient: 100 */ + CONVERT_COEFF(-1650694), /* Filter:1, Coefficient: 97 */ + CONVERT_COEFF(2456535), /* Filter:1, Coefficient: 98 */ + CONVERT_COEFF(4020324), /* Filter:1, Coefficient: 99 */ + CONVERT_COEFF(2215413), /* Filter:1, Coefficient: 100 */ + + /* Filter #26, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(227496), /* Filter:4, Coefficient: 101 */ + CONVERT_COEFF(-184800), /* Filter:4, Coefficient: 102 */ + CONVERT_COEFF(-384947), /* Filter:4, Coefficient: 103 */ + CONVERT_COEFF(-250573), /* Filter:4, Coefficient: 104 */ + CONVERT_COEFF(848717), /* Filter:3, Coefficient: 101 */ + CONVERT_COEFF(1522401), /* Filter:3, Coefficient: 102 */ + CONVERT_COEFF(897837), /* Filter:3, Coefficient: 103 */ + CONVERT_COEFF(-323140), /* Filter:3, Coefficient: 104 */ + CONVERT_COEFF(-2999081), /* Filter:2, Coefficient: 101 */ + CONVERT_COEFF(-663371), /* Filter:2, Coefficient: 102 */ + CONVERT_COEFF(1805833), /* Filter:2, Coefficient: 103 */ + CONVERT_COEFF(2461354), /* Filter:2, Coefficient: 104 */ + CONVERT_COEFF(-1023079), /* Filter:1, Coefficient: 101 */ + CONVERT_COEFF(-2946059), /* Filter:1, Coefficient: 102 */ + CONVERT_COEFF(-2271916), /* Filter:1, Coefficient: 103 */ + CONVERT_COEFF(46810), /* Filter:1, Coefficient: 104 */ + + /* Filter #27, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(56883), /* Filter:4, Coefficient: 105 */ + CONVERT_COEFF(266613), /* Filter:4, Coefficient: 106 */ + CONVERT_COEFF(231070), /* Filter:4, Coefficient: 107 */ + CONVERT_COEFF(21669), /* Filter:4, Coefficient: 108 */ + CONVERT_COEFF(-1085470), /* Filter:3, Coefficient: 105 */ + CONVERT_COEFF(-870963), /* Filter:3, Coefficient: 106 */ + CONVERT_COEFF(-16819), /* Filter:3, Coefficient: 107 */ + CONVERT_COEFF(696469), /* Filter:3, Coefficient: 108 */ + CONVERT_COEFF(1096398), /* Filter:2, Coefficient: 105 */ + CONVERT_COEFF(-881544), /* Filter:2, Coefficient: 106 */ + CONVERT_COEFF(-1827647), /* Filter:2, Coefficient: 107 */ + CONVERT_COEFF(-1190629), /* Filter:2, Coefficient: 108 */ + CONVERT_COEFF(1934524), /* Filter:1, Coefficient: 105 */ + CONVERT_COEFF(2002411), /* Filter:1, Coefficient: 106 */ + CONVERT_COEFF(516537), /* Filter:1, Coefficient: 107 */ + CONVERT_COEFF(-1096900), /* Filter:1, Coefficient: 108 */ + + /* Filter #28, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-165914), /* Filter:4, Coefficient: 109 */ + CONVERT_COEFF(-188751), /* Filter:4, Coefficient: 110 */ + CONVERT_COEFF(-60237), /* Filter:4, Coefficient: 111 */ + CONVERT_COEFF(89578), /* Filter:4, Coefficient: 112 */ + CONVERT_COEFF(737670), /* Filter:3, Coefficient: 109 */ + CONVERT_COEFF(199113), /* Filter:3, Coefficient: 110 */ + CONVERT_COEFF(-389567), /* Filter:3, Coefficient: 111 */ + CONVERT_COEFF(-560182), /* Filter:3, Coefficient: 112 */ + CONVERT_COEFF(247255), /* Filter:2, Coefficient: 109 */ + CONVERT_COEFF(1222537), /* Filter:2, Coefficient: 110 */ + CONVERT_COEFF(1068384), /* Filter:2, Coefficient: 111 */ + CONVERT_COEFF(124598), /* Filter:2, Coefficient: 112 */ + CONVERT_COEFF(-1569451), /* Filter:1, Coefficient: 109 */ + CONVERT_COEFF(-750469), /* Filter:1, Coefficient: 110 */ + CONVERT_COEFF(482448), /* Filter:1, Coefficient: 111 */ + CONVERT_COEFF(1101069), /* Filter:1, Coefficient: 112 */ + + /* Filter #29, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(139197), /* Filter:4, Coefficient: 113 */ + CONVERT_COEFF(70304), /* Filter:4, Coefficient: 114 */ + CONVERT_COEFF(-38289), /* Filter:4, Coefficient: 115 */ + CONVERT_COEFF(-93047), /* Filter:4, Coefficient: 116 */ + CONVERT_COEFF(-263233), /* Filter:3, Coefficient: 113 */ + CONVERT_COEFF(174746), /* Filter:3, Coefficient: 114 */ + CONVERT_COEFF(383750), /* Filter:3, Coefficient: 115 */ + CONVERT_COEFF(250958), /* Filter:3, Coefficient: 116 */ + CONVERT_COEFF(-721785), /* Filter:2, Coefficient: 113 */ + CONVERT_COEFF(-838118), /* Filter:2, Coefficient: 114 */ + CONVERT_COEFF(-289378), /* Filter:2, Coefficient: 115 */ + CONVERT_COEFF(357413), /* Filter:2, Coefficient: 116 */ + CONVERT_COEFF(755091), /* Filter:1, Coefficient: 113 */ + CONVERT_COEFF(-90734), /* Filter:1, Coefficient: 114 */ + CONVERT_COEFF(-683828), /* Filter:1, Coefficient: 115 */ + CONVERT_COEFF(-627769), /* Filter:1, Coefficient: 116 */ + + /* Filter #30, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(-63107), /* Filter:4, Coefficient: 117 */ + CONVERT_COEFF(8665), /* Filter:4, Coefficient: 118 */ + CONVERT_COEFF(56144), /* Filter:4, Coefficient: 119 */ + CONVERT_COEFF(48031), /* Filter:4, Coefficient: 120 */ + CONVERT_COEFF(-44424), /* Filter:3, Coefficient: 117 */ + CONVERT_COEFF(-235818), /* Filter:3, Coefficient: 118 */ + CONVERT_COEFF(-199384), /* Filter:3, Coefficient: 119 */ + CONVERT_COEFF(-19310), /* Filter:3, Coefficient: 120 */ + CONVERT_COEFF(583440), /* Filter:2, Coefficient: 117 */ + CONVERT_COEFF(312988), /* Filter:2, Coefficient: 118 */ + CONVERT_COEFF(-127566), /* Filter:2, Coefficient: 119 */ + CONVERT_COEFF(-358789), /* Filter:2, Coefficient: 120 */ + CONVERT_COEFF(-112449), /* Filter:1, Coefficient: 117 */ + CONVERT_COEFF(363474), /* Filter:1, Coefficient: 118 */ + CONVERT_COEFF(449326), /* Filter:1, Coefficient: 119 */ + CONVERT_COEFF(178527), /* Filter:1, Coefficient: 120 */ + + /* Filter #31, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(4767), /* Filter:4, Coefficient: 121 */ + CONVERT_COEFF(-30353), /* Filter:4, Coefficient: 122 */ + CONVERT_COEFF(-31778), /* Filter:4, Coefficient: 123 */ + CONVERT_COEFF(-7893), /* Filter:4, Coefficient: 124 */ + CONVERT_COEFF(128040), /* Filter:3, Coefficient: 121 */ + CONVERT_COEFF(136746), /* Filter:3, Coefficient: 122 */ + CONVERT_COEFF(38083), /* Filter:3, Coefficient: 123 */ + CONVERT_COEFF(-60147), /* Filter:3, Coefficient: 124 */ + CONVERT_COEFF(-257969), /* Filter:2, Coefficient: 121 */ + CONVERT_COEFF(8641), /* Filter:2, Coefficient: 122 */ + CONVERT_COEFF(190921), /* Filter:2, Coefficient: 123 */ + CONVERT_COEFF(174318), /* Filter:2, Coefficient: 124 */ + CONVERT_COEFF(-151547), /* Filter:1, Coefficient: 121 */ + CONVERT_COEFF(-276720), /* Filter:1, Coefficient: 122 */ + CONVERT_COEFF(-161692), /* Filter:1, Coefficient: 123 */ + CONVERT_COEFF(35536), /* Filter:1, Coefficient: 124 */ + + /* Filter #32, conversion from 24000 Hz to 8000 Hz */ + + CONVERT_COEFF(14756), /* Filter:4, Coefficient: 125 */ + CONVERT_COEFF(18247), /* Filter:4, Coefficient: 126 */ + CONVERT_COEFF(5816), /* Filter:4, Coefficient: 127 */ + CONVERT_COEFF(-573080), /* Filter:4, Coefficient: 128 */ + CONVERT_COEFF(-80967), /* Filter:3, Coefficient: 125 */ + CONVERT_COEFF(-32124), /* Filter:3, Coefficient: 126 */ + CONVERT_COEFF(24552), /* Filter:3, Coefficient: 127 */ + CONVERT_COEFF(872700), /* Filter:3, Coefficient: 128 */ + CONVERT_COEFF(32782), /* Filter:2, Coefficient: 125 */ + CONVERT_COEFF(-84503), /* Filter:2, Coefficient: 126 */ + CONVERT_COEFF(-95337), /* Filter:2, Coefficient: 127 */ + CONVERT_COEFF(-244664), /* Filter:2, Coefficient: 128 */ + CONVERT_COEFF(141820), /* Filter:1, Coefficient: 125 */ + CONVERT_COEFF(108395), /* Filter:1, Coefficient: 126 */ + CONVERT_COEFF(10015), /* Filter:1, Coefficient: 127 */ + CONVERT_COEFF(-54956), /* Filter:1, Coefficient: 128 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_24000Hz_to_16000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_24000Hz_to_16000Hz.h new file mode 100644 index 000000000000..c6cb368ffef1 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_24000Hz_to_16000Hz.h @@ -0,0 +1,550 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 24000 Hz to 16000 Hz */ +/* NUM_FILTERS=6, FILTER_LENGTH=80, alpha=6.800000, gamma=0.460000 */ + +__cold_rodata static const int32_t coeff24000to16000[] = { + + /* Filter #1, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-26295), /* Filter:6, Coefficient: 1 */ + CONVERT_COEFF(-6174), /* Filter:6, Coefficient: 2 */ + CONVERT_COEFF(59137), /* Filter:6, Coefficient: 3 */ + CONVERT_COEFF(-55792), /* Filter:6, Coefficient: 4 */ + CONVERT_COEFF(95136), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(-90674), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(-78081), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(262291), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(20739), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(149775), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-239278), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(-22446), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(-144563), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(217789), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(67657), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-521235), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-120977), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(-98594), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(393503), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-206930), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(42248), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-133707), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(38413), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(241342), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-44498), /* Filter:6, Coefficient: 5 */ + CONVERT_COEFF(140021), /* Filter:6, Coefficient: 6 */ + CONVERT_COEFF(-65538), /* Filter:6, Coefficient: 7 */ + CONVERT_COEFF(-159309), /* Filter:6, Coefficient: 8 */ + CONVERT_COEFF(-143888), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(-302689), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(539007), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(-33282), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(472981), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(-445555), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(-364304), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(1077686), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(409104), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(529589), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-1203596), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(246572), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-546538), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(894742), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(104473), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(-1568720), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-302760), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(-155593), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(660489), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-329457), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(250380), /* Filter:6, Coefficient: 9 */ + CONVERT_COEFF(11147), /* Filter:6, Coefficient: 10 */ + CONVERT_COEFF(-380641), /* Filter:6, Coefficient: 11 */ + CONVERT_COEFF(321305), /* Filter:6, Coefficient: 12 */ + CONVERT_COEFF(-810002), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(794826), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(490903), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(-1598783), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(-425238), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(-1277747), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(1786094), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(314731), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(1691746), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-1890565), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(-897425), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(3576853), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(1232437), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(1350041), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-3034301), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(596978), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-766480), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(1172797), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(160492), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-1874803), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(263297), /* Filter:6, Coefficient: 13 */ + CONVERT_COEFF(-680359), /* Filter:6, Coefficient: 14 */ + CONVERT_COEFF(215469), /* Filter:6, Coefficient: 15 */ + CONVERT_COEFF(752593), /* Filter:6, Coefficient: 16 */ + CONVERT_COEFF(693774), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(1664970), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(-2393909), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(-270022), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(-2867333), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(2015640), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(2321674), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-4757264), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-1759642), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(-3621615), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(5521571), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(433087), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(3906959), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(-4133829), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(-2063561), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(7454382), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(1336229), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(1573222), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(-3181847), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(419381), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-924495), /* Filter:6, Coefficient: 17 */ + CONVERT_COEFF(-243808), /* Filter:6, Coefficient: 18 */ + CONVERT_COEFF(1435511), /* Filter:6, Coefficient: 19 */ + CONVERT_COEFF(-854950), /* Filter:6, Coefficient: 20 */ + CONVERT_COEFF(3494050), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(-2545027), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(-2574960), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(5494742), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(788251), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(5808654), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(-5844798), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(-2965912), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-7943091), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(5939150), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(5840605), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-12672998), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-3286678), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-7450030), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(10475967), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(1477617), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(4031999), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-3839814), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(-2330782), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(7001267), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-1191753), /* Filter:6, Coefficient: 21 */ + CONVERT_COEFF(2084337), /* Filter:6, Coefficient: 22 */ + CONVERT_COEFF(-128069), /* Filter:6, Coefficient: 23 */ + CONVERT_COEFF(-2601191), /* Filter:6, Coefficient: 24 */ + CONVERT_COEFF(-1086047), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(-6323279), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(6516645), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(2986602), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(10152857), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(-4315876), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(-9807613), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(13486977), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(2509829), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(14660956), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(-15044393), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(-7085983), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-15070746), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(10141650), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(11626122), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(-22492705), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-2520134), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-7205710), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(9041722), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(2204328), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(2240070), /* Filter:6, Coefficient: 25 */ + CONVERT_COEFF(1583859), /* Filter:6, Coefficient: 26 */ + CONVERT_COEFF(-4145189), /* Filter:6, Coefficient: 27 */ + CONVERT_COEFF(1204705), /* Filter:6, Coefficient: 28 */ + CONVERT_COEFF(-10826352), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(4740217), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(10247700), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(-14202210), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(1961386), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(-19034008), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(12554808), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(14736870), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(25196436), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-10843609), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-24055393), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(33134987), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(2787191), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(26962307), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(-25014527), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-15146780), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(-13501440), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(7856982), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(11265305), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-19146543), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(4445165), /* Filter:6, Coefficient: 29 */ + CONVERT_COEFF(-5022270), /* Filter:6, Coefficient: 30 */ + CONVERT_COEFF(-1998803), /* Filter:6, Coefficient: 31 */ + CONVERT_COEFF(8226514), /* Filter:6, Coefficient: 32 */ + CONVERT_COEFF(-2184106), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(20242040), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(-12782630), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(-17153461), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-27924414), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(2706581), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(34610785), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-30620463), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(5074883), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-47384059), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(30833566), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(38864431), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(44598021), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-15639102), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(-46416323), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(58085501), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(581006), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(24589586), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-20506417), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-16259182), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-3439899), /* Filter:6, Coefficient: 33 */ + CONVERT_COEFF(-8925448), /* Filter:6, Coefficient: 34 */ + CONVERT_COEFF(11104297), /* Filter:6, Coefficient: 35 */ + CONVERT_COEFF(6265801), /* Filter:6, Coefficient: 36 */ + CONVERT_COEFF(30279913), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(1264181), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(-44000805), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(27404677), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(-22972428), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(60020710), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-13003893), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(-79732586), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(-72814450), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(3812134), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(102230911), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-87524750), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(16356030), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-94361261), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(53986557), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(98938922), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(41141721), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(-11448663), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(-49636394), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(60678285), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-19358245), /* Filter:6, Coefficient: 37 */ + CONVERT_COEFF(-1448253), /* Filter:6, Coefficient: 38 */ + CONVERT_COEFF(26658987), /* Filter:6, Coefficient: 39 */ + CONVERT_COEFF(1437558), /* Filter:6, Coefficient: 40 */ + CONVERT_COEFF(51523005), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(-60986563), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(-58253729), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(69683724), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(76987483), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(99162074), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-138037476), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-114554861), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(-100746036), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(243760389), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(161666543), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-338656732), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-174705650), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-35750635), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(498608183), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(308015331), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(26029323), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-140264601), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(104468300), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(595087393), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-20425535), /* Filter:6, Coefficient: 41 */ + CONVERT_COEFF(6567320), /* Filter:6, Coefficient: 42 */ + CONVERT_COEFF(15743139), /* Filter:6, Coefficient: 43 */ + CONVERT_COEFF(-9427264), /* Filter:6, Coefficient: 44 */ + CONVERT_COEFF(36693971), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(-76752453), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-18978257), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(58790681), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(160865448), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(112183817), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(-122474297), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-52614939), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(-258230261), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(238070373), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(183898488), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(-140152136), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-427437883), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(-416558699), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(122106215), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(125076115), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(520991913), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(12457163), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-124027598), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(56265475), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-7663681), /* Filter:6, Coefficient: 45 */ + CONVERT_COEFF(9874963), /* Filter:6, Coefficient: 46 */ + CONVERT_COEFF(564421), /* Filter:6, Coefficient: 47 */ + CONVERT_COEFF(-7491119), /* Filter:6, Coefficient: 48 */ + CONVERT_COEFF(-6293486), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(-36428312), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(22206365), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(14384112), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(87304224), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-5399444), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-55884369), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(33711827), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-42369119), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(106491355), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-28115935), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-58576468), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(-125087622), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(-11228768), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(89164835), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(-43176336), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(37936440), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(-56171034), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(7138480), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(35072417), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(3743976), /* Filter:6, Coefficient: 49 */ + CONVERT_COEFF(3498372), /* Filter:6, Coefficient: 50 */ + CONVERT_COEFF(-4901576), /* Filter:6, Coefficient: 51 */ + CONVERT_COEFF(234077), /* Filter:6, Coefficient: 52 */ + CONVERT_COEFF(-24281078), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(3132387), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(16560249), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(-12239715), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(21599169), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(-37380560), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(5717759), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(25010112), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(53813676), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(11709605), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-47320948), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(19538940), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-39017312), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(55027501), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-3760701), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-39483388), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(-26074542), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(-10215709), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(25770583), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(-7934321), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(3638857), /* Filter:6, Coefficient: 53 */ + CONVERT_COEFF(-2392834), /* Filter:6, Coefficient: 54 */ + CONVERT_COEFF(-1352878), /* Filter:6, Coefficient: 55 */ + CONVERT_COEFF(2683085), /* Filter:6, Coefficient: 56 */ + CONVERT_COEFF(-5372325), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(12708978), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(-3609816), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(-7612571), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(-19441937), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-7452690), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(19552722), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-6222289), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(24367027), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(-29849864), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-549202), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(23365978), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(26883932), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(13942943), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(-29246879), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(7153500), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-14873710), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(15201245), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(2157693), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-13047847), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-610388), /* Filter:6, Coefficient: 57 */ + CONVERT_COEFF(-1688412), /* Filter:6, Coefficient: 58 */ + CONVERT_COEFF(1513662), /* Filter:6, Coefficient: 59 */ + CONVERT_COEFF(349912), /* Filter:6, Coefficient: 60 */ + CONVERT_COEFF(7476439), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(1248705), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(-6509356), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(3072466), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(-11268706), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(11724570), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(1431814), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(-9841071), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-13902547), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(-9448707), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(16453057), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(-2865391), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(18159363), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-16617074), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(-3757540), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(14970543), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(6319609), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(6173527), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(-8607053), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(524563), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-1364557), /* Filter:6, Coefficient: 61 */ + CONVERT_COEFF(582053), /* Filter:6, Coefficient: 62 */ + CONVERT_COEFF(658744), /* Filter:6, Coefficient: 63 */ + CONVERT_COEFF(-838099), /* Filter:6, Coefficient: 64 */ + CONVERT_COEFF(3042256), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(-4197678), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(315404), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(2919373), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(4965896), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(4379351), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-6407530), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(667422), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-10736941), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(8712511), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(2733105), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-8122284), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(-6264447), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-7478462), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(9209549), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(-6635), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(6210778), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(-4146852), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-2148993), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(4360107), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(34742), /* Filter:6, Coefficient: 65 */ + CONVERT_COEFF(585847), /* Filter:6, Coefficient: 66 */ + CONVERT_COEFF(-385112), /* Filter:6, Coefficient: 67 */ + CONVERT_COEFF(-177297), /* Filter:6, Coefficient: 68 */ + CONVERT_COEFF(-2028360), /* Filter:5, Coefficient: 65 */ + CONVERT_COEFF(-875673), /* Filter:5, Coefficient: 66 */ + CONVERT_COEFF(1992549), /* Filter:5, Coefficient: 67 */ + CONVERT_COEFF(-596942), /* Filter:5, Coefficient: 68 */ + CONVERT_COEFF(4308258), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(-3107701), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(-1215261), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(2940913), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(2901374), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(4157080), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(-4574441), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(-218386), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-6756530), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(4038899), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(2447917), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(-4302235), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(-1020076), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(-2560492), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(2237872), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(503503), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(376287), /* Filter:6, Coefficient: 69 */ + CONVERT_COEFF(-108531), /* Filter:6, Coefficient: 70 */ + CONVERT_COEFF(-186360), /* Filter:6, Coefficient: 71 */ + CONVERT_COEFF(184575), /* Filter:6, Coefficient: 72 */ + CONVERT_COEFF(-1027019), /* Filter:5, Coefficient: 69 */ + CONVERT_COEFF(1033388), /* Filter:5, Coefficient: 70 */ + CONVERT_COEFF(66645), /* Filter:5, Coefficient: 71 */ + CONVERT_COEFF(-722338), /* Filter:5, Coefficient: 72 */ + CONVERT_COEFF(-918864), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(-1474180), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(1499478), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(87118), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(3322300), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(-1807064), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-1180769), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(1876974), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(815530), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(2473272), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(-1974352), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-499153), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(-1850371), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(717835), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(834686), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(-940634), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(7527), /* Filter:6, Coefficient: 73 */ + CONVERT_COEFF(-119787), /* Filter:6, Coefficient: 74 */ + CONVERT_COEFF(68147), /* Filter:6, Coefficient: 75 */ + CONVERT_COEFF(28404), /* Filter:6, Coefficient: 76 */ + CONVERT_COEFF(391591), /* Filter:5, Coefficient: 73 */ + CONVERT_COEFF(218433), /* Filter:5, Coefficient: 74 */ + CONVERT_COEFF(-369238), /* Filter:5, Coefficient: 75 */ + CONVERT_COEFF(93076), /* Filter:5, Coefficient: 76 */ + CONVERT_COEFF(-1021014), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(543575), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(306112), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-496977), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(-320463), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(-991740), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(753601), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(156968), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(1548719), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(-552872), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(-629254), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(660050), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(-13456), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(592881), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-309498), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-180123), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 24000 Hz to 16000 Hz */ + + CONVERT_COEFF(-55547), /* Filter:6, Coefficient: 77 */ + CONVERT_COEFF(19487), /* Filter:6, Coefficient: 78 */ + CONVERT_COEFF(15420), /* Filter:6, Coefficient: 79 */ + CONVERT_COEFF(-8783213), /* Filter:6, Coefficient: 80 */ + CONVERT_COEFF(151753), /* Filter:5, Coefficient: 77 */ + CONVERT_COEFF(-141825), /* Filter:5, Coefficient: 78 */ + CONVERT_COEFF(11411), /* Filter:5, Coefficient: 79 */ + CONVERT_COEFF(21748306), /* Filter:5, Coefficient: 80 */ + CONVERT_COEFF(114656), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(198467), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(-171608), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(-18242535), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(-504421), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(191996), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(140005), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(5774023), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(-3503), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(-338534), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(171077), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(-556806), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(261387), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(-35673), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(-106078), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(60225), /* Filter:1, Coefficient: 80 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_44100Hz_to_48000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_44100Hz_to_48000Hz.h new file mode 100644 index 000000000000..ba4434e92866 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_44100Hz_to_48000Hz.h @@ -0,0 +1,506 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 44100 Hz to 48000 Hz */ +/* NUM_FILTERS=7, FILTER_LENGTH=64, alpha=7.800000, gamma=0.459000 */ + +__cold_rodata static const int32_t coeff44100to48000[] = { + + /* Filter #1, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-36104), /* Filter:7, Coefficient: 1 */ + CONVERT_COEFF(50872), /* Filter:7, Coefficient: 2 */ + CONVERT_COEFF(-56564), /* Filter:7, Coefficient: 3 */ + CONVERT_COEFF(40229), /* Filter:7, Coefficient: 4 */ + CONVERT_COEFF(215090), /* Filter:6, Coefficient: 1 */ + CONVERT_COEFF(-343808), /* Filter:6, Coefficient: 2 */ + CONVERT_COEFF(497081), /* Filter:6, Coefficient: 3 */ + CONVERT_COEFF(-646143), /* Filter:6, Coefficient: 4 */ + CONVERT_COEFF(-224265), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(396780), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(-680396), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(1099778), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(-156406), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(276746), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-402187), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(483398), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(48725), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(-150519), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(376286), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-778623), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(140598), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(-270647), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(433819), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-598685), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(12068), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-294), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(-40869), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(127167), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(15714), /* Filter:7, Coefficient: 5 */ + CONVERT_COEFF(-132261), /* Filter:7, Coefficient: 6 */ + CONVERT_COEFF(331265), /* Filter:7, Coefficient: 7 */ + CONVERT_COEFF(-631432), /* Filter:7, Coefficient: 8 */ + CONVERT_COEFF(739353), /* Filter:6, Coefficient: 5 */ + CONVERT_COEFF(-699893), /* Filter:6, Coefficient: 6 */ + CONVERT_COEFF(427714), /* Filter:6, Coefficient: 7 */ + CONVERT_COEFF(192832), /* Filter:6, Coefficient: 8 */ + CONVERT_COEFF(-1660521), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(2335311), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(-3050136), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(3673357), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(-443096), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(177837), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(433397), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(-1512737), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(1399489), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-2253057), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(3306250), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(-4459986), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(708253), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(-678784), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(404012), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(233922), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-272876), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(486311), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(-764527), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(1087962), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(1043073), /* Filter:7, Coefficient: 9 */ + CONVERT_COEFF(-1562022), /* Filter:7, Coefficient: 10 */ + CONVERT_COEFF(2163475), /* Filter:7, Coefficient: 11 */ + CONVERT_COEFF(-2796684), /* Filter:7, Coefficient: 12 */ + CONVERT_COEFF(-1278823), /* Filter:6, Coefficient: 9 */ + CONVERT_COEFF(2928044), /* Filter:6, Coefficient: 10 */ + CONVERT_COEFF(-5192839), /* Filter:6, Coefficient: 11 */ + CONVERT_COEFF(8050849), /* Filter:6, Coefficient: 12 */ + CONVERT_COEFF(-4010927), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(3811024), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(-2780782), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(616611), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(3159157), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(-5417939), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(8246975), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-11484454), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(5535069), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-6267047), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(6314112), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(-5281074), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-1346387), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(3013765), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-5256640), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(8006079), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-1416065), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(1685077), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-1809078), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(1685203), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(3381591), /* Filter:7, Coefficient: 13 */ + CONVERT_COEFF(-3808499), /* Filter:7, Coefficient: 14 */ + CONVERT_COEFF(3941685), /* Filter:7, Coefficient: 15 */ + CONVERT_COEFF(-3627554), /* Filter:7, Coefficient: 16 */ + CONVERT_COEFF(-11376082), /* Filter:6, Coefficient: 13 */ + CONVERT_COEFF(14914588), /* Filter:6, Coefficient: 14 */ + CONVERT_COEFF(-18269373), /* Filter:6, Coefficient: 15 */ + CONVERT_COEFF(20898922), /* Filter:6, Coefficient: 16 */ + CONVERT_COEFF(2952090), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(-8108091), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(14884712), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(-23103615), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(14823547), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(-17800007), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(19798175), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-20079410), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(2760719), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(1608543), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(-8072426), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(16684120), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(-11077473), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(14152940), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(-16777161), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(18370557), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(-1203455), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(260933), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(1220394), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(-3273956), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(2707504), /* Filter:7, Coefficient: 17 */ + CONVERT_COEFF(-1035138), /* Filter:7, Coefficient: 18 */ + CONVERT_COEFF(-1502971), /* Filter:7, Coefficient: 19 */ + CONVERT_COEFF(4964055), /* Filter:7, Coefficient: 20 */ + CONVERT_COEFF(-22132797), /* Filter:6, Coefficient: 17 */ + CONVERT_COEFF(21206202), /* Filter:6, Coefficient: 18 */ + CONVERT_COEFF(-17313533), /* Filter:6, Coefficient: 19 */ + CONVERT_COEFF(9678851), /* Filter:6, Coefficient: 20 */ + CONVERT_COEFF(32319346), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(-41778175), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(50397724), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(-56771470), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(17834747), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(-12260704), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(2654160), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(11480470), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-27229456), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(39162945), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(-51563303), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(63114743), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-18262033), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(15741168), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(-10127070), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(848490), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(5868998), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-8893591), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(12142571), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(-15312249), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-9324436), /* Filter:7, Coefficient: 21 */ + CONVERT_COEFF(14453459), /* Filter:7, Coefficient: 22 */ + CONVERT_COEFF(-20084074), /* Filter:7, Coefficient: 23 */ + CONVERT_COEFF(25773112), /* Filter:7, Coefficient: 24 */ + CONVERT_COEFF(2360201), /* Filter:6, Coefficient: 21 */ + CONVERT_COEFF(-19258639), /* Filter:6, Coefficient: 22 */ + CONVERT_COEFF(41160997), /* Filter:6, Coefficient: 23 */ + CONVERT_COEFF(-67779055), /* Filter:6, Coefficient: 24 */ + CONVERT_COEFF(59198429), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(-55733258), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(44245892), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(-22473133), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(-30320143), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(53616304), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(-80596906), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(109873203), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(-72116055), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(76512776), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(-73937881), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(61731000), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(12472346), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-29940877), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(51324643), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(-76006737), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(18002687), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-19726749), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(19922792), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-17964334), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-30833137), /* Filter:7, Coefficient: 25 */ + CONVERT_COEFF(34190653), /* Filter:7, Coefficient: 26 */ + CONVERT_COEFF(-34055766), /* Filter:7, Coefficient: 27 */ + CONVERT_COEFF(27111184), /* Filter:7, Coefficient: 28 */ + CONVERT_COEFF(98212836), /* Filter:6, Coefficient: 25 */ + CONVERT_COEFF(-130600585), /* Filter:6, Coefficient: 26 */ + CONVERT_COEFF(161254866), /* Filter:6, Coefficient: 27 */ + CONVERT_COEFF(-182201584), /* Filter:6, Coefficient: 28 */ + CONVERT_COEFF(-11960805), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(61573102), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(-129062026), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(217007008), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(-139327475), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(165912061), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(-185169687), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(189903320), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(-36878749), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-4239017), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(66555533), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(-158147683), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(102957685), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(-130710897), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(157290278), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-179922417), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(13153909), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(-4675683), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(-8550270), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(28262612), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-6732875), /* Filter:7, Coefficient: 29 */ + CONVERT_COEFF(-33513548), /* Filter:7, Coefficient: 30 */ + CONVERT_COEFF(81968959), /* Filter:7, Coefficient: 31 */ + CONVERT_COEFF(-126044370), /* Filter:7, Coefficient: 32 */ + CONVERT_COEFF(173711794), /* Filter:6, Coefficient: 29 */ + CONVERT_COEFF(-91263367), /* Filter:6, Coefficient: 30 */ + CONVERT_COEFF(-97880606), /* Filter:6, Coefficient: 31 */ + CONVERT_COEFF(376032608), /* Filter:6, Coefficient: 32 */ + CONVERT_COEFF(-325394901), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(443482836), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(-458466415), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(111467000), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-165805866), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(69571438), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(317915452), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-847016031), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(295236856), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-517257770), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(938951919), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(-618933202), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(193893264), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-187311577), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(104180214), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(1104501607), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(-57986908), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(106920163), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-209369472), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(677292439), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(86233108), /* Filter:7, Coefficient: 33 */ + CONVERT_COEFF(-35501375), /* Filter:7, Coefficient: 34 */ + CONVERT_COEFF(-5636059), /* Filter:7, Coefficient: 35 */ + CONVERT_COEFF(26510404), /* Filter:7, Coefficient: 36 */ + CONVERT_COEFF(-406938858), /* Filter:6, Coefficient: 33 */ + CONVERT_COEFF(298668575), /* Filter:6, Coefficient: 34 */ + CONVERT_COEFF(-136959173), /* Filter:6, Coefficient: 35 */ + CONVERT_COEFF(21661015), /* Filter:6, Coefficient: 36 */ + CONVERT_COEFF(296331993), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(-523052704), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(446708617), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(-290145245), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(848040024), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-256558412), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-137639539), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(223543416), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(-605929650), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(936110335), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-517814517), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(297832194), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(-1104400882), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-103375582), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(186432948), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-193151946), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(677292439), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(-209369472), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(106920163), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(-57986908), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-33774390), /* Filter:7, Coefficient: 37 */ + CONVERT_COEFF(34125210), /* Filter:7, Coefficient: 38 */ + CONVERT_COEFF(-30912242), /* Filter:7, Coefficient: 39 */ + CONVERT_COEFF(25943030), /* Filter:7, Coefficient: 40 */ + CONVERT_COEFF(41951855), /* Filter:6, Coefficient: 37 */ + CONVERT_COEFF(-74109079), /* Filter:6, Coefficient: 38 */ + CONVERT_COEFF(86833071), /* Filter:6, Coefficient: 39 */ + CONVERT_COEFF(-87225838), /* Filter:6, Coefficient: 40 */ + CONVERT_COEFF(168023601), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(-79384353), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(16820075), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(25433754), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(-231084433), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(210602792), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-178568996), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(142372278), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(-161325042), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(69605744), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(-6892281), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-34721861), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(179395431), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-156965780), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(130550114), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(-102919808), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(28262612), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-8550270), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-4675683), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(13153909), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-20303032), /* Filter:7, Coefficient: 41 */ + CONVERT_COEFF(14689217), /* Filter:7, Coefficient: 42 */ + CONVERT_COEFF(-9553062), /* Filter:7, Coefficient: 43 */ + CONVERT_COEFF(5169062), /* Filter:7, Coefficient: 44 */ + CONVERT_COEFF(79900129), /* Filter:6, Coefficient: 41 */ + CONVERT_COEFF(-68107389), /* Filter:6, Coefficient: 42 */ + CONVERT_COEFF(54242139), /* Filter:6, Coefficient: 43 */ + CONVERT_COEFF(-40072964), /* Filter:6, Coefficient: 44 */ + CONVERT_COEFF(-51687526), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(65404355), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-69552118), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(66752497), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(-106166575), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(72576377), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(-43273377), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(19208349), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(60089315), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-72784419), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(75792430), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(-71757314), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(76055038), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(-51427903), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(30073627), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(-12614739), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-17964334), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(19922792), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-19726749), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(18002687), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-1674444), /* Filter:7, Coefficient: 45 */ + CONVERT_COEFF(-901531), /* Filter:7, Coefficient: 46 */ + CONVERT_COEFF(2611633), /* Filter:7, Coefficient: 47 */ + CONVERT_COEFF(-3566019), /* Filter:7, Coefficient: 48 */ + CONVERT_COEFF(26858516), /* Filter:6, Coefficient: 45 */ + CONVERT_COEFF(-15420460), /* Filter:6, Coefficient: 46 */ + CONVERT_COEFF(6205578), /* Filter:6, Coefficient: 47 */ + CONVERT_COEFF(650178), /* Filter:6, Coefficient: 48 */ + CONVERT_COEFF(-59316886), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(49231067), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(-38126705), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(27261665), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(-740031), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-12258104), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(20288296), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(-24113150), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(63038805), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(-51691475), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(39422440), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-27557546), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(-711004), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(10004241), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(-15638587), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(18181880), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(-15312249), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(12142571), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(-8893591), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(5868998), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(3908988), /* Filter:7, Coefficient: 49 */ + CONVERT_COEFF(-3798121), /* Filter:7, Coefficient: 50 */ + CONVERT_COEFF(3386896), /* Filter:7, Coefficient: 51 */ + CONVERT_COEFF(-2811604), /* Filter:7, Coefficient: 52 */ + CONVERT_COEFF(-5252911), /* Filter:6, Coefficient: 49 */ + CONVERT_COEFF(7879560), /* Filter:6, Coefficient: 50 */ + CONVERT_COEFF(-8908772), /* Filter:6, Coefficient: 51 */ + CONVERT_COEFF(8758751), /* Filter:6, Coefficient: 52 */ + CONVERT_COEFF(-17520204), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(9436366), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(-3238487), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(-1090753), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(24640267), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(-22815396), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(19532216), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(-15564685), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(17030626), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-8400622), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(1894708), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(2528815), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-18312401), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(16738756), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-14130963), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(11068153), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(-3273956), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(1220394), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(260933), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(-1203455), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(2182958), /* Filter:7, Coefficient: 53 */ + CONVERT_COEFF(-1582255), /* Filter:7, Coefficient: 54 */ + CONVERT_COEFF(1061509), /* Filter:7, Coefficient: 55 */ + CONVERT_COEFF(-646664), /* Filter:7, Coefficient: 56 */ + CONVERT_COEFF(-7836150), /* Filter:6, Coefficient: 53 */ + CONVERT_COEFF(6498637), /* Filter:6, Coefficient: 54 */ + CONVERT_COEFF(-5031961), /* Filter:6, Coefficient: 55 */ + CONVERT_COEFF(3640700), /* Filter:6, Coefficient: 56 */ + CONVERT_COEFF(3746098), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(-5030962), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(5294951), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(-4882739), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(11524851), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-7845878), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(4787215), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-2456850), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(-5106362), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(6192755), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-6190960), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(5494166), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-8005697), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(5261877), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(-3021912), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(1355425), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(1685203), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-1809078), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(1685077), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-1416065), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(342806), /* Filter:7, Coefficient: 57 */ + CONVERT_COEFF(-140284), /* Filter:7, Coefficient: 58 */ + CONVERT_COEFF(20786), /* Filter:7, Coefficient: 59 */ + CONVERT_COEFF(37371), /* Filter:7, Coefficient: 60 */ + CONVERT_COEFF(-2450499), /* Filter:6, Coefficient: 57 */ + CONVERT_COEFF(1518734), /* Filter:6, Coefficient: 58 */ + CONVERT_COEFF(-850198), /* Filter:6, Coefficient: 59 */ + CONVERT_COEFF(414533), /* Filter:6, Coefficient: 60 */ + CONVERT_COEFF(4097237), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(-3177789), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(2292208), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(-1540003), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(844451), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(140882), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(-633875), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(781606), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-4443987), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(3305948), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(-2261053), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(1410461), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(-242505), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-396647), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(672943), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(-703923), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(1087962), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(-764527), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(486311), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(-272876), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 44100 Hz to 48000 Hz */ + + CONVERT_COEFF(-55188), /* Filter:7, Coefficient: 61 */ + CONVERT_COEFF(50357), /* Filter:7, Coefficient: 62 */ + CONVERT_COEFF(-35994), /* Filter:7, Coefficient: 63 */ + CONVERT_COEFF(18259534), /* Filter:7, Coefficient: 64 */ + CONVERT_COEFF(-162721), /* Filter:6, Coefficient: 61 */ + CONVERT_COEFF(40706), /* Filter:6, Coefficient: 62 */ + CONVERT_COEFF(881), /* Filter:6, Coefficient: 63 */ + CONVERT_COEFF(-52642287), /* Filter:6, Coefficient: 64 */ + CONVERT_COEFF(963380), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(-562368), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(310806), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(55998086), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(-719947), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(558884), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-376234), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(-26993761), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-789225), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(384817), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(-156478), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(5955995), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(595664), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-431821), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(269381), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(-589635), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(127167), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(-40869), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-294), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(12068), /* Filter:1, Coefficient: 64 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_08000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_08000Hz.h new file mode 100644 index 000000000000..bb0cdb8cd0d9 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_08000Hz.h @@ -0,0 +1,618 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 8000 Hz */ +/* NUM_FILTERS=4, FILTER_LENGTH=128, alpha=5.600000, gamma=0.415500 */ + +__cold_rodata static const int32_t coeff48000to08000[] = { + + /* Filter #1, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-3301), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(-3924), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-3547), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(-2001), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(3989), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(-5958), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(-17787), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-28475), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(65517), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(63506), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(39846), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-6206), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(88725), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(154917), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(208524), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(227017), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(592), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(3785), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(6857), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(8947), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(-34495), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-32695), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-21285), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(-655), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-68868), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(-135707), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(-189365), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(-211084), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(190319), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(87541), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(-77070), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-280839), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(9255), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(7264), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(2938), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-3172), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(26209), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(53920), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(75559), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(84121), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-185467), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(-105464), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(23711), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(182957), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-483590), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(-633541), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-677765), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-575509), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-9948), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(-15871), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-19318), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-18942), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(74293), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(44149), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(-3655), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(-61592), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(340885), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(458887), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(499081), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(433742), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(-311577), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(93646), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(580763), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(1056783), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-14049), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(-4887), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(7242), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(20103), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-118123), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(-159680), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(-173513), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-150856), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(254175), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-23258), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(-355924), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-679709), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(1409874), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(1531750), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(1343813), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(821550), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(30884), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(36752), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(35500), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(26152), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(-89716), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(3439), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(113663), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(219469), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-919754), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-1005668), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(-888441), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(-555451), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(11087), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-967418), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-1932735), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-2671792), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(9393), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(-12331), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(-35074), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(-54036), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(296574), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(322901), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(283864), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(176829), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(-39793), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(579126), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(1185270), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(1645395), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(-2981375), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(-2714977), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(-1825131), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-391039), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-64488), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(-62823), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(-47496), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-19664), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(13593), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-179927), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(-367152), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(-507125), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(1835407), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(1668894), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(1121896), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(247943), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(1377035), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(3161285), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(4587051), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(5293861), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(16678), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(55149), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(87997), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(107539), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(-562646), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(-508764), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-339863), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-73626), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(-821316), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-1892108), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(-2740106), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-3153045), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(5014601), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(3647017), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(1301187), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(-1690645), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(107770), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(85829), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(42999), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-15023), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(249339), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(570716), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(824034), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(947166), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-2976939), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-2156713), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(-762064), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(1008723), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(-4809380), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-7428596), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-8928025), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(-8822328), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-78706), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(-136113), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(-174958), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-184971), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(895533), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(653455), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(241140), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(-284575), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(2850676), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(4398591), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(5291841), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(5246926), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-6880893), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(-3213125), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(1702668), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(7060108), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-160114), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-100215), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-11645), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(93176), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-836548), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(-1310257), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-1601506), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-1625994), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(4124428), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(1976711), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(-935042), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(-4161104), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(11836509), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(14963038), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(15527995), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(12978729), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(197453), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(282648), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(331646), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(331926), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(-1337215), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-739195), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(108785), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(1096994), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-7120987), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(-9191912), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-9814753), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-8599910), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(7284205), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(-976463), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(-10624045), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(-19996714), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(278128), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(173526), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(30081), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-133038), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(2079471), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(2895796), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(3397039), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(3471563), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-5414116), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(-431194), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(5865019), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(12729600), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-27165458), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-30219478), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(-27579070), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-18285419), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-292255), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(-423276), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(-505071), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(-523436), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(3066123), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(2198356), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(958050), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(-503489), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(19252509), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(24488239), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(27599287), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(27990266), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(-2217112), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(19807628), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(46067140), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(74113281), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-473520), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(-360852), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-200645), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(-15496), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-1994632), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(-3311919), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(-4271266), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-4736706), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(25410130), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(20004573), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(12308550), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(3178633), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(101068271), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(124000002), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(140320208), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(148144605), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(168169), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(324285), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(431264), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(475348), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(-4641842), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(-4000373), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(-2903906), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(-1507432), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-6325048), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(-15089017), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(-22105139), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(-26612611), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(146558923), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(135748984), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(116974214), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(92388797), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(452628), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(369409), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(240897), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(88460), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(-4920), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(1400822), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(2528987), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(3247243), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(-28200972), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(-26858406), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(-22958846), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-17191493), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(64738752), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(36982432), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(11893275), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(-8295001), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-64023), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(-194079), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(-284155), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-324136), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(3489610), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(3263104), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(2642488), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(1754510), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(-10445713), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(-3671194), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(2263465), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(6691197), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(-22148960), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(-29166675), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-29766384), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-25142508), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-312505), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(-255992), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(-167880), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(-65312), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(754742), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(-198757), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(-970391), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(-1466526), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(9227960), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(9804583), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(8647121), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(6212516), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(-17019531), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(-7348727), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(2000942), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(9509007), /* Filter:1, Coefficient: 80 */ + + /* Filter #21, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(33847), /* Filter:4, Coefficient: 81 */ + CONVERT_COEFF(114046), /* Filter:4, Coefficient: 82 */ + CONVERT_COEFF(164441), /* Filter:4, Coefficient: 83 */ + CONVERT_COEFF(180290), /* Filter:4, Coefficient: 84 */ + CONVERT_COEFF(-1646620), /* Filter:3, Coefficient: 81 */ + CONVERT_COEFF(-1524717), /* Filter:3, Coefficient: 82 */ + CONVERT_COEFF(-1161761), /* Filter:3, Coefficient: 83 */ + CONVERT_COEFF(-650773), /* Filter:3, Coefficient: 84 */ + CONVERT_COEFF(3093389), /* Filter:2, Coefficient: 81 */ + CONVERT_COEFF(-89994), /* Filter:2, Coefficient: 82 */ + CONVERT_COEFF(-2791699), /* Filter:2, Coefficient: 83 */ + CONVERT_COEFF(-4619639), /* Filter:2, Coefficient: 84 */ + CONVERT_COEFF(14188512), /* Filter:1, Coefficient: 81 */ + CONVERT_COEFF(15667833), /* Filter:1, Coefficient: 82 */ + CONVERT_COEFF(14165998), /* Filter:1, Coefficient: 83 */ + CONVERT_COEFF(10376123), /* Filter:1, Coefficient: 84 */ + + /* Filter #22, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(163170), /* Filter:4, Coefficient: 85 */ + CONVERT_COEFF(120081), /* Filter:4, Coefficient: 86 */ + CONVERT_COEFF(61686), /* Filter:4, Coefficient: 87 */ + CONVERT_COEFF(66), /* Filter:4, Coefficient: 88 */ + CONVERT_COEFF(-98000), /* Filter:3, Coefficient: 85 */ + CONVERT_COEFF(396363), /* Filter:3, Coefficient: 86 */ + CONVERT_COEFF(754499), /* Filter:3, Coefficient: 87 */ + CONVERT_COEFF(931769), /* Filter:3, Coefficient: 88 */ + CONVERT_COEFF(-5381371), /* Filter:2, Coefficient: 85 */ + CONVERT_COEFF(-5091650), /* Filter:2, Coefficient: 86 */ + CONVERT_COEFF(-3944213), /* Filter:2, Coefficient: 87 */ + CONVERT_COEFF(-2256257), /* Filter:2, Coefficient: 88 */ + CONVERT_COEFF(5285564), /* Filter:1, Coefficient: 85 */ + CONVERT_COEFF(-30634), /* Filter:1, Coefficient: 86 */ + CONVERT_COEFF(-4605459), /* Filter:1, Coefficient: 87 */ + CONVERT_COEFF(-7732849), /* Filter:1, Coefficient: 88 */ + + /* Filter #23, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-53544), /* Filter:4, Coefficient: 89 */ + CONVERT_COEFF(-90654), /* Filter:4, Coefficient: 90 */ + CONVERT_COEFF(-106725), /* Filter:4, Coefficient: 91 */ + CONVERT_COEFF(-101537), /* Filter:4, Coefficient: 92 */ + CONVERT_COEFF(920613), /* Filter:3, Coefficient: 89 */ + CONVERT_COEFF(747526), /* Filter:3, Coefficient: 90 */ + CONVERT_COEFF(464354), /* Filter:3, Coefficient: 91 */ + CONVERT_COEFF(136043), /* Filter:3, Coefficient: 92 */ + CONVERT_COEFF(-398040), /* Filter:2, Coefficient: 89 */ + CONVERT_COEFF(1278522), /* Filter:2, Coefficient: 90 */ + CONVERT_COEFF(2499600), /* Filter:2, Coefficient: 91 */ + CONVERT_COEFF(3108250), /* Filter:2, Coefficient: 92 */ + CONVERT_COEFF(-9056522), /* Filter:1, Coefficient: 89 */ + CONVERT_COEFF(-8586783), /* Filter:1, Coefficient: 90 */ + CONVERT_COEFF(-6650839), /* Filter:1, Coefficient: 91 */ + CONVERT_COEFF(-3793297), /* Filter:1, Coefficient: 92 */ + + /* Filter #24, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-78733), /* Filter:4, Coefficient: 93 */ + CONVERT_COEFF(-44705), /* Filter:4, Coefficient: 94 */ + CONVERT_COEFF(-7104), /* Filter:4, Coefficient: 95 */ + CONVERT_COEFF(26726), /* Filter:4, Coefficient: 96 */ + CONVERT_COEFF(-172582), /* Filter:3, Coefficient: 93 */ + CONVERT_COEFF(-408494), /* Filter:3, Coefficient: 94 */ + CONVERT_COEFF(-538640), /* Filter:3, Coefficient: 95 */ + CONVERT_COEFF(-553497), /* Filter:3, Coefficient: 96 */ + CONVERT_COEFF(3077680), /* Filter:2, Coefficient: 93 */ + CONVERT_COEFF(2499519), /* Filter:2, Coefficient: 94 */ + CONVERT_COEFF(1552119), /* Filter:2, Coefficient: 95 */ + CONVERT_COEFF(456990), /* Filter:2, Coefficient: 96 */ + CONVERT_COEFF(-650487), /* Filter:1, Coefficient: 93 */ + CONVERT_COEFF(2175698), /* Filter:1, Coefficient: 94 */ + CONVERT_COEFF(4221669), /* Filter:1, Coefficient: 95 */ + CONVERT_COEFF(5227614), /* Filter:1, Coefficient: 96 */ + + /* Filter #25, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(51065), /* Filter:4, Coefficient: 97 */ + CONVERT_COEFF(62685), /* Filter:4, Coefficient: 98 */ + CONVERT_COEFF(61148), /* Filter:4, Coefficient: 99 */ + CONVERT_COEFF(48532), /* Filter:4, Coefficient: 100 */ + CONVERT_COEFF(-465874), /* Filter:3, Coefficient: 97 */ + CONVERT_COEFF(-305721), /* Filter:3, Coefficient: 98 */ + CONVERT_COEFF(-112385), /* Filter:3, Coefficient: 99 */ + CONVERT_COEFF(73933), /* Filter:3, Coefficient: 100 */ + CONVERT_COEFF(-567215), /* Filter:2, Coefficient: 97 */ + CONVERT_COEFF(-1344377), /* Filter:2, Coefficient: 98 */ + CONVERT_COEFF(-1767688), /* Filter:2, Coefficient: 99 */ + CONVERT_COEFF(-1810088), /* Filter:2, Coefficient: 100 */ + CONVERT_COEFF(5157406), /* Filter:1, Coefficient: 97 */ + CONVERT_COEFF(4175038), /* Filter:1, Coefficient: 98 */ + CONVERT_COEFF(2587411), /* Filter:1, Coefficient: 99 */ + CONVERT_COEFF(768423), /* Filter:1, Coefficient: 100 */ + + /* Filter #26, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(28723), /* Filter:4, Coefficient: 101 */ + CONVERT_COEFF(6440), /* Filter:4, Coefficient: 102 */ + CONVERT_COEFF(-13774), /* Filter:4, Coefficient: 103 */ + CONVERT_COEFF(-28398), /* Filter:4, Coefficient: 104 */ + CONVERT_COEFF(219811), /* Filter:3, Coefficient: 101 */ + CONVERT_COEFF(303981), /* Filter:3, Coefficient: 102 */ + CONVERT_COEFF(319710), /* Filter:3, Coefficient: 103 */ + CONVERT_COEFF(274094), /* Filter:3, Coefficient: 104 */ + CONVERT_COEFF(-1518489), /* Filter:2, Coefficient: 101 */ + CONVERT_COEFF(-994890), /* Filter:2, Coefficient: 102 */ + CONVERT_COEFF(-369667), /* Filter:2, Coefficient: 103 */ + CONVERT_COEFF(226880), /* Filter:2, Coefficient: 104 */ + CONVERT_COEFF(-919124), /* Filter:1, Coefficient: 101 */ + CONVERT_COEFF(-2188898), /* Filter:1, Coefficient: 102 */ + CONVERT_COEFF(-2873130), /* Filter:1, Coefficient: 103 */ + CONVERT_COEFF(-2936618), /* Filter:1, Coefficient: 104 */ + + /* Filter #27, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-35477), /* Filter:4, Coefficient: 105 */ + CONVERT_COEFF(-34783), /* Filter:4, Coefficient: 106 */ + CONVERT_COEFF(-27623), /* Filter:4, Coefficient: 107 */ + CONVERT_COEFF(-16364), /* Filter:4, Coefficient: 108 */ + CONVERT_COEFF(184790), /* Filter:3, Coefficient: 105 */ + CONVERT_COEFF(75160), /* Filter:3, Coefficient: 106 */ + CONVERT_COEFF(-31027), /* Filter:3, Coefficient: 107 */ + CONVERT_COEFF(-114243), /* Filter:3, Coefficient: 108 */ + CONVERT_COEFF(689048), /* Filter:2, Coefficient: 105 */ + CONVERT_COEFF(952149), /* Filter:2, Coefficient: 106 */ + CONVERT_COEFF(998741), /* Filter:2, Coefficient: 107 */ + CONVERT_COEFF(854886), /* Filter:2, Coefficient: 108 */ + CONVERT_COEFF(-2463839), /* Filter:1, Coefficient: 105 */ + CONVERT_COEFF(-1625344), /* Filter:1, Coefficient: 106 */ + CONVERT_COEFF(-632765), /* Filter:1, Coefficient: 107 */ + CONVERT_COEFF(307301), /* Filter:1, Coefficient: 108 */ + + /* Filter #28, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-3819), /* Filter:4, Coefficient: 109 */ + CONVERT_COEFF(7377), /* Filter:4, Coefficient: 110 */ + CONVERT_COEFF(15261), /* Filter:4, Coefficient: 111 */ + CONVERT_COEFF(18835), /* Filter:4, Coefficient: 112 */ + CONVERT_COEFF(-162364), /* Filter:3, Coefficient: 109 */ + CONVERT_COEFF(-171920), /* Filter:3, Coefficient: 110 */ + CONVERT_COEFF(-147466), /* Filter:3, Coefficient: 111 */ + CONVERT_COEFF(-99442), /* Filter:3, Coefficient: 112 */ + CONVERT_COEFF(578544), /* Filter:2, Coefficient: 109 */ + CONVERT_COEFF(243498), /* Filter:2, Coefficient: 110 */ + CONVERT_COEFF(-77378), /* Filter:2, Coefficient: 111 */ + CONVERT_COEFF(-326115), /* Filter:2, Coefficient: 112 */ + CONVERT_COEFF(1031494), /* Filter:1, Coefficient: 109 */ + CONVERT_COEFF(1443736), /* Filter:1, Coefficient: 110 */ + CONVERT_COEFF(1522566), /* Filter:1, Coefficient: 111 */ + CONVERT_COEFF(1312875), /* Filter:1, Coefficient: 112 */ + + /* Filter #29, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(18119), /* Filter:4, Coefficient: 113 */ + CONVERT_COEFF(13991), /* Filter:4, Coefficient: 114 */ + CONVERT_COEFF(7872), /* Filter:4, Coefficient: 115 */ + CONVERT_COEFF(1348), /* Filter:4, Coefficient: 116 */ + CONVERT_COEFF(-41184), /* Filter:3, Coefficient: 113 */ + CONVERT_COEFF(14196), /* Filter:3, Coefficient: 114 */ + CONVERT_COEFF(56400), /* Filter:3, Coefficient: 115 */ + CONVERT_COEFF(79557), /* Filter:3, Coefficient: 116 */ + CONVERT_COEFF(-468515), /* Filter:2, Coefficient: 113 */ + CONVERT_COEFF(-496901), /* Filter:2, Coefficient: 114 */ + CONVERT_COEFF(-427126), /* Filter:2, Coefficient: 115 */ + CONVERT_COEFF(-291358), /* Filter:2, Coefficient: 116 */ + CONVERT_COEFF(906078), /* Filter:1, Coefficient: 113 */ + CONVERT_COEFF(414464), /* Filter:1, Coefficient: 114 */ + CONVERT_COEFF(-54245), /* Filter:1, Coefficient: 115 */ + CONVERT_COEFF(-417064), /* Filter:1, Coefficient: 116 */ + + /* Filter #30, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-4186), /* Filter:4, Coefficient: 117 */ + CONVERT_COEFF(-7781), /* Filter:4, Coefficient: 118 */ + CONVERT_COEFF(-9064), /* Filter:4, Coefficient: 119 */ + CONVERT_COEFF(-8214), /* Filter:4, Coefficient: 120 */ + CONVERT_COEFF(82669), /* Filter:3, Coefficient: 117 */ + CONVERT_COEFF(68978), /* Filter:3, Coefficient: 118 */ + CONVERT_COEFF(44558), /* Filter:3, Coefficient: 119 */ + CONVERT_COEFF(16546), /* Filter:3, Coefficient: 120 */ + CONVERT_COEFF(-128765), /* Filter:2, Coefficient: 117 */ + CONVERT_COEFF(23638), /* Filter:2, Coefficient: 118 */ + CONVERT_COEFF(138103), /* Filter:2, Coefficient: 119 */ + CONVERT_COEFF(200098), /* Filter:2, Coefficient: 120 */ + CONVERT_COEFF(-627465), /* Filter:1, Coefficient: 117 */ + CONVERT_COEFF(-677691), /* Filter:1, Coefficient: 118 */ + CONVERT_COEFF(-592807), /* Filter:1, Coefficient: 119 */ + CONVERT_COEFF(-419175), /* Filter:1, Coefficient: 120 */ + + /* Filter #31, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(-5833), /* Filter:4, Coefficient: 121 */ + CONVERT_COEFF(-2739), /* Filter:4, Coefficient: 122 */ + CONVERT_COEFF(251), /* Filter:4, Coefficient: 123 */ + CONVERT_COEFF(2500), /* Filter:4, Coefficient: 124 */ + CONVERT_COEFF(-8556), /* Filter:3, Coefficient: 121 */ + CONVERT_COEFF(-26141), /* Filter:3, Coefficient: 122 */ + CONVERT_COEFF(-34137), /* Filter:3, Coefficient: 123 */ + CONVERT_COEFF(-32972), /* Filter:3, Coefficient: 124 */ + CONVERT_COEFF(208777), /* Filter:2, Coefficient: 121 */ + CONVERT_COEFF(174473), /* Filter:2, Coefficient: 122 */ + CONVERT_COEFF(114277), /* Filter:2, Coefficient: 123 */ + CONVERT_COEFF(46990), /* Filter:2, Coefficient: 124 */ + CONVERT_COEFF(-210728), /* Filter:1, Coefficient: 121 */ + CONVERT_COEFF(-16339), /* Filter:1, Coefficient: 122 */ + CONVERT_COEFF(129243), /* Filter:1, Coefficient: 123 */ + CONVERT_COEFF(209618), /* Filter:1, Coefficient: 124 */ + + /* Filter #32, conversion from 48000 Hz to 8000 Hz */ + + CONVERT_COEFF(3662), /* Filter:4, Coefficient: 125 */ + CONVERT_COEFF(3707), /* Filter:4, Coefficient: 126 */ + CONVERT_COEFF(2870), /* Filter:4, Coefficient: 127 */ + CONVERT_COEFF(335927), /* Filter:4, Coefficient: 128 */ + CONVERT_COEFF(-25001), /* Filter:3, Coefficient: 125 */ + CONVERT_COEFF(-13600), /* Filter:3, Coefficient: 126 */ + CONVERT_COEFF(-2195), /* Filter:3, Coefficient: 127 */ + CONVERT_COEFF(-458842), /* Filter:3, Coefficient: 128 */ + CONVERT_COEFF(-11331), /* Filter:2, Coefficient: 125 */ + CONVERT_COEFF(-50338), /* Filter:2, Coefficient: 126 */ + CONVERT_COEFF(-66501), /* Filter:2, Coefficient: 127 */ + CONVERT_COEFF(55557), /* Filter:2, Coefficient: 128 */ + CONVERT_COEFF(226117), /* Filter:1, Coefficient: 125 */ + CONVERT_COEFF(193432), /* Filter:1, Coefficient: 126 */ + CONVERT_COEFF(133189), /* Filter:1, Coefficient: 127 */ + CONVERT_COEFF(67358), /* Filter:1, Coefficient: 128 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_11025Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_11025Hz.h new file mode 100644 index 000000000000..3ab1223bc68a --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_11025Hz.h @@ -0,0 +1,466 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 11025 Hz */ +/* NUM_FILTERS=4, FILTER_LENGTH=96, alpha=5.700000, gamma=0.417000 */ + +__cold_rodata static const int32_t coeff48000to11025[] = { + + /* Filter #1, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-5276), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(-12951), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-16487), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(-12216), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(41170), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(24714), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(-16130), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-68429), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(90439), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(156156), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(166381), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(85133), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(-36529), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(89808), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(257736), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(391514), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(540), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(18145), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(33188), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(37139), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(-107599), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-106756), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-50319), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(54036), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-87027), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(-298777), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(-456335), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(-457073), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(396015), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(201937), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(-185458), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-658946), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(24307), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(-4499), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(-40503), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-68959), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(171682), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(249813), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(237789), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(112225), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-238997), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(174254), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(656680), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(1007920), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-1024879), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(-1067924), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-648377), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(205595), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-74494), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(-48117), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(7013), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(73976), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-104001), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(-339463), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(-493890), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(-476173), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(1025112), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(596557), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(-220901), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(-1180767), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(1256824), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(2103513), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(2312568), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(1604844), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(126345), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(137657), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(93034), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(-1731), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-247687), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(147413), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(581451), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(878980), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-1906017), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-2021581), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(-1318811), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(113142), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(21881), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-2005545), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(-3742184), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(-4386660), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-118109), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(-212105), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(-239586), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-174729), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(881333), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(518154), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(-143352), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(-896882), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(1853939), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(3252995), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(3650862), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(2652871), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-3396385), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-779248), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(2779889), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(6048018), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-24432), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(168052), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(333676), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(400546), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(-1453384), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-1543048), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-1029512), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(8151), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(350965), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(-2609224), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(-5174708), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-6226971), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(7629537), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(6502907), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(2518773), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-3351884), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(322102), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(100162), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(-207102), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-497722), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(1264729), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(2286428), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(2621280), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(1995783), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(-5018466), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-1546610), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(3294826), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(7886940), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(-9170470), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(-12602533), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-11762954), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-6054156), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-657260), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-599700), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-303789), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(169268), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(453662), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(-1602376), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-3496605), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-4480875), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(10370645), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(9314284), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(4342738), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-3512410), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(3330959), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(13498465), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(20611375), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(21154438), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(685660), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(1076048), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(1189612), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(947693), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(-3992362), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(-1882814), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(1466176), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(5196025), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-11914041), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-17803913), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(-18332740), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(-11858951), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(13330874), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-1889934), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-20501310), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(-36179493), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(378181), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(-382925), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(-1125926), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-1628684), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(8192385), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(9416173), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(8242832), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(4697569), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(1316974), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(18760292), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(36372844), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(49436642), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-41896152), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(-32009702), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-4216305), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(39274782), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-1725846), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-1363486), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-620573), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(310846), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-498294), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(-6096589), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-10663877), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-12993683), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(53943647), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(47812424), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(31605996), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(8506473), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(91783432), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(143507821), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(183866425), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(204194917), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(1181314), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(1758112), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(1894276), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(1570552), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(-12461531), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-9210650), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-4109186), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(1507388), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-16471793), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(-37810559), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-50965956), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-53557320), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(200025358), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(172279208), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(127020431), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(73842077), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(897380), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(77192), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(-659808), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-1125092), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(6226751), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(8960398), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(9231586), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(7267416), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-45919329), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(-30871316), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(-12800875), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(3635617), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(23363491), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-15432232), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(-37267226), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-41497734), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-1224338), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(-977499), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(-502204), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(31518), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(3877187), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(167487), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(-2806990), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(-4344247), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(14790492), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(18905076), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(16363909), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(9303267), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(-31720872), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(-14278017), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(3817177), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(16872467), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(458491), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(668294), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(632521), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(402936), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-4258557), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(-2868976), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(-834307), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(1096696), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(754906), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-6366692), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(-10107072), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(-9905933), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(21863748), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(18819227), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(10252203), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(-56657), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(84254), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(-206679), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(-380298), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(-399448), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(2330787), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(2593273), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(1966425), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(807090), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-6539839), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(-1656983), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(2892064), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(5683926), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(-8463246), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(-12588471), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(-11859264), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(-7381325), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-283699), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(-94156), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(93448), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(216583), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(-413134), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(-1281462), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-1571374), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(-1287849), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(6114153), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(4458459), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(1633571), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-1216156), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(-1289801), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(4127659), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(7210746), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(7366642), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(245013), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(185843), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(74882), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-40571), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(-627349), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(120817), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(688759), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(917942), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(-3140159), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(-3667371), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(-2881001), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(-1291563), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(5079392), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(1556950), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-1803822), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-3921315), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-120129), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(-143205), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(-112715), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(-49779), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(794458), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(427950), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(-8978), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(-352674), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(414286), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(1640931), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(2071182), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(1722382), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(-4335656), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(-3247151), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(-1321521), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(627989), /* Filter:1, Coefficient: 80 */ + + /* Filter #21, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(17150), /* Filter:4, Coefficient: 81 */ + CONVERT_COEFF(63819), /* Filter:4, Coefficient: 82 */ + CONVERT_COEFF(78078), /* Filter:4, Coefficient: 83 */ + CONVERT_COEFF(61882), /* Filter:4, Coefficient: 84 */ + CONVERT_COEFF(-504123), /* Filter:3, Coefficient: 81 */ + CONVERT_COEFF(-451338), /* Filter:3, Coefficient: 82 */ + CONVERT_COEFF(-256412), /* Filter:3, Coefficient: 83 */ + CONVERT_COEFF(-18431), /* Filter:3, Coefficient: 84 */ + CONVERT_COEFF(875132), /* Filter:2, Coefficient: 81 */ + CONVERT_COEFF(-76722), /* Filter:2, Coefficient: 82 */ + CONVERT_COEFF(-786703), /* Filter:2, Coefficient: 83 */ + CONVERT_COEFF(-1067401), /* Filter:2, Coefficient: 84 */ + CONVERT_COEFF(1947985), /* Filter:1, Coefficient: 81 */ + CONVERT_COEFF(2336224), /* Filter:1, Coefficient: 82 */ + CONVERT_COEFF(1872047), /* Filter:1, Coefficient: 83 */ + CONVERT_COEFF(907040), /* Filter:1, Coefficient: 84 */ + + /* Filter #22, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(27740), /* Filter:4, Coefficient: 85 */ + CONVERT_COEFF(-8034), /* Filter:4, Coefficient: 86 */ + CONVERT_COEFF(-32141), /* Filter:4, Coefficient: 87 */ + CONVERT_COEFF(-38602), /* Filter:4, Coefficient: 88 */ + CONVERT_COEFF(169685), /* Filter:3, Coefficient: 85 */ + CONVERT_COEFF(253408), /* Filter:3, Coefficient: 86 */ + CONVERT_COEFF(228111), /* Filter:3, Coefficient: 87 */ + CONVERT_COEFF(129707), /* Filter:3, Coefficient: 88 */ + CONVERT_COEFF(-922590), /* Filter:2, Coefficient: 85 */ + CONVERT_COEFF(-503998), /* Filter:2, Coefficient: 86 */ + CONVERT_COEFF(-23864), /* Filter:2, Coefficient: 87 */ + CONVERT_COEFF(335367), /* Filter:2, Coefficient: 88 */ + CONVERT_COEFF(-116914), /* Filter:1, Coefficient: 85 */ + CONVERT_COEFF(-842108), /* Filter:1, Coefficient: 86 */ + CONVERT_COEFF(-1100770), /* Filter:1, Coefficient: 87 */ + CONVERT_COEFF(-928696), /* Filter:1, Coefficient: 88 */ + + /* Filter #23, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(-29393), /* Filter:4, Coefficient: 89 */ + CONVERT_COEFF(-11914), /* Filter:4, Coefficient: 90 */ + CONVERT_COEFF(5087), /* Filter:4, Coefficient: 91 */ + CONVERT_COEFF(15234), /* Filter:4, Coefficient: 92 */ + CONVERT_COEFF(12179), /* Filter:3, Coefficient: 89 */ + CONVERT_COEFF(-76760), /* Filter:3, Coefficient: 90 */ + CONVERT_COEFF(-112173), /* Filter:3, Coefficient: 91 */ + CONVERT_COEFF(-95873), /* Filter:3, Coefficient: 92 */ + CONVERT_COEFF(480135), /* Filter:2, Coefficient: 89 */ + CONVERT_COEFF(418338), /* Filter:2, Coefficient: 90 */ + CONVERT_COEFF(230980), /* Filter:2, Coefficient: 91 */ + CONVERT_COEFF(22991), /* Filter:2, Coefficient: 92 */ + CONVERT_COEFF(-502241), /* Filter:1, Coefficient: 89 */ + CONVERT_COEFF(-39321), /* Filter:1, Coefficient: 90 */ + CONVERT_COEFF(290352), /* Filter:1, Coefficient: 91 */ + CONVERT_COEFF(414260), /* Filter:1, Coefficient: 92 */ + + /* Filter #24, conversion from 48000 Hz to 11025 Hz */ + + CONVERT_COEFF(16461), /* Filter:4, Coefficient: 93 */ + CONVERT_COEFF(10800), /* Filter:4, Coefficient: 94 */ + CONVERT_COEFF(2550), /* Filter:4, Coefficient: 95 */ + CONVERT_COEFF(-797683), /* Filter:4, Coefficient: 96 */ + CONVERT_COEFF(-49051), /* Filter:3, Coefficient: 93 */ + CONVERT_COEFF(991), /* Filter:3, Coefficient: 94 */ + CONVERT_COEFF(33364), /* Filter:3, Coefficient: 95 */ + CONVERT_COEFF(1235716), /* Filter:3, Coefficient: 96 */ + CONVERT_COEFF(-122969), /* Filter:2, Coefficient: 93 */ + CONVERT_COEFF(-172363), /* Filter:2, Coefficient: 94 */ + CONVERT_COEFF(-138918), /* Filter:2, Coefficient: 95 */ + CONVERT_COEFF(-375528), /* Filter:2, Coefficient: 96 */ + CONVERT_COEFF(356624), /* Filter:1, Coefficient: 93 */ + CONVERT_COEFF(201071), /* Filter:1, Coefficient: 94 */ + CONVERT_COEFF(40502), /* Filter:1, Coefficient: 95 */ + CONVERT_COEFF(-62504), /* Filter:1, Coefficient: 96 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_12000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_12000Hz.h new file mode 100644 index 000000000000..89a08f8e1506 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_12000Hz.h @@ -0,0 +1,466 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 12000 Hz */ +/* NUM_FILTERS=4, FILTER_LENGTH=96, alpha=5.700000, gamma=0.424000 */ + +__cold_rodata static const int32_t coeff48000to12000[] = { + + /* Filter #1, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(9466), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(18324), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(18675), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(6681), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(-44320), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(-15044), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(41846), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(99856), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-108866), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(-168122), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(-143205), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-4840), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(18979), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-124739), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(-289576), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(-372252), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-14873), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(-36092), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(-43775), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(-28417), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(120645), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(74642), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-36940), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(-172008), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(212485), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(406758), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(446885), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(243397), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-270550), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(47706), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(493005), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(859159), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(8921), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(53986), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(83668), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(76633), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(-259236), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-230916), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(-63713), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(194231), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-181655), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(-668246), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-964705), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(-841844), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(902116), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(470138), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-375031), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-1319757), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(25833), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(-53679), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-127150), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-153896), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(429216), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(506489), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(338544), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(-54472), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(-229172), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(697753), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(1541275), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(1833706), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(-1890703), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(-1664796), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(-514224), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(1238423), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-107640), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(6019), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(144977), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(244094), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-527257), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(-854646), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(-830345), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-379134), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(1268127), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-96526), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(-1771933), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-2986182), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(2863711), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(3496880), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(2551682), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(94379), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(243618), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(120959), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(-89812), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-303143), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(373317), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(1118639), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(1481524), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(1194410), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-3011832), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-1547918), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(1028425), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(3697569), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-3026789), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-5421590), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-5729809), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-3309613), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-414069), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(-346290), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(-95407), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(254838), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(254718), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-1017842), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-2072112), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(-2348186), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(5163786), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(4438011), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(1391449), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-2999213), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(1279200), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(6283525), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(9357238), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(8581017), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(556057), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(654070), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(461041), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(8985), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(-1547890), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(169371), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(2173059), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(3569126), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(-6896234), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-8311637), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(-6031532), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(-353097), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(3488394), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(-4399594), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-11887580), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-15284742), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-543384), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-960956), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-1025319), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(-634838), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(3569496), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(1878806), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-1076651), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-4206990), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(6748994), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(12209118), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(13074826), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(7888560), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(-12059514), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(-2284367), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(10842409), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(21814880), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(131905), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(1022024), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(1689633), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(1826448), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(-6121966), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(-5683979), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(-2536796), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(2619817), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-2343046), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-14088848), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(-22312461), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(-22299178), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(24861172), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(16527773), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-2222990), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(-25382165), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(1291803), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(187823), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(-1156014), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-2289689), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(8156827), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(12037112), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(12558708), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(9041064), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-11640045), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(8421631), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(32901411), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(54414451), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-43234314), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(-45424925), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-24777921), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(19525839), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-2804099), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-2486101), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-1405857), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(99935), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(2176743), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(-6112957), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-13291600), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-17077204), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(65561608), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(61534767), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(41975533), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(11356417), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(80690239), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(145621917), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(198554116), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(225828200), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(1544944), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(2466704), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(2590632), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(1922395), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(-16247012), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-11073761), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-3227323), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(4820544), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-22315217), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(-50044994), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-64751780), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-63486697), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(220203456), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(183182934), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(124528682), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(59139166), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(735067), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-540990), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(-1480192), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-1812185), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(10661840), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(12763578), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(10929621), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(6261251), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-48196279), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(-24804128), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(-1006930), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(16367589), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(2395365), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-34403398), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(-46984107), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-38540927), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-1504699), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(-752135), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(118595), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(782220), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(660837), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(-3907345), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(-6107752), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(-5624729), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(23479491), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(20364635), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(10388086), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(-1396259), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(-17723958), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(4911585), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(20616375), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(25014862), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(1034412), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(852013), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(377238), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(-159449), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-3138072), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(63987), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(2647613), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(3737272), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(-10266950), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-13455602), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(-10821182), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(-4453036), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(18775762), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(6405039), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-6134454), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(-13930540), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-540437), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(-643355), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(-474537), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(-146712), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(3175158), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(1467919), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(-516205), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(-1946005), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(2499446), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(7214349), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(8236197), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(5814958), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(-14805492), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(-9671153), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(-1632211), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(5613145), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(182504), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(380962), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(391293), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(242079), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(-2350019), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(-1745607), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-551374), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(648570), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(1519255), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(-2610059), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(-4955468), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-4899346), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(9335222), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(8686809), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(4712022), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(-403519), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(22015), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(-166585), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(-252342), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-219066), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(1369416), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(1406290), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(869654), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(84471), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(-2899640), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(-115895), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(2186507), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(3171366), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(-4412139), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(-5920243), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-4796349), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-1992494), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-102810), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(32566), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(127289), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(150143), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(-582238), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(-881098), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(-762309), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(-358757), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(2695169), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(1237005), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(-416702), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(-1556295), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(1044258), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(3054325), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(3442737), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(2390972), /* Filter:1, Coefficient: 80 */ + + /* Filter #21, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(106283), /* Filter:4, Coefficient: 81 */ + CONVERT_COEFF(27996), /* Filter:4, Coefficient: 82 */ + CONVERT_COEFF(-44477), /* Filter:4, Coefficient: 83 */ + CONVERT_COEFF(-81857), /* Filter:4, Coefficient: 84 */ + CONVERT_COEFF(104868), /* Filter:3, Coefficient: 81 */ + CONVERT_COEFF(424671), /* Filter:3, Coefficient: 82 */ + CONVERT_COEFF(499517), /* Filter:3, Coefficient: 83 */ + CONVERT_COEFF(352818), /* Filter:3, Coefficient: 84 */ + CONVERT_COEFF(-1827601), /* Filter:2, Coefficient: 81 */ + CONVERT_COEFF(-1307300), /* Filter:2, Coefficient: 82 */ + CONVERT_COEFF(-381962), /* Filter:2, Coefficient: 83 */ + CONVERT_COEFF(479247), /* Filter:2, Coefficient: 84 */ + CONVERT_COEFF(626053), /* Filter:1, Coefficient: 81 */ + CONVERT_COEFF(-990379), /* Filter:1, Coefficient: 82 */ + CONVERT_COEFF(-1844980), /* Filter:1, Coefficient: 83 */ + CONVERT_COEFF(-1771871), /* Filter:1, Coefficient: 84 */ + + /* Filter #22, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-76222), /* Filter:4, Coefficient: 85 */ + CONVERT_COEFF(-39943), /* Filter:4, Coefficient: 86 */ + CONVERT_COEFF(4124), /* Filter:4, Coefficient: 87 */ + CONVERT_COEFF(35042), /* Filter:4, Coefficient: 88 */ + CONVERT_COEFF(96315), /* Filter:3, Coefficient: 85 */ + CONVERT_COEFF(-136873), /* Filter:3, Coefficient: 86 */ + CONVERT_COEFF(-254389), /* Filter:3, Coefficient: 87 */ + CONVERT_COEFF(-235483), /* Filter:3, Coefficient: 88 */ + CONVERT_COEFF(939561), /* Filter:2, Coefficient: 85 */ + CONVERT_COEFF(907226), /* Filter:2, Coefficient: 86 */ + CONVERT_COEFF(518385), /* Filter:2, Coefficient: 87 */ + CONVERT_COEFF(25446), /* Filter:2, Coefficient: 88 */ + CONVERT_COEFF(-1021645), /* Filter:1, Coefficient: 85 */ + CONVERT_COEFF(-61990), /* Filter:1, Coefficient: 86 */ + CONVERT_COEFF(668408), /* Filter:1, Coefficient: 87 */ + CONVERT_COEFF(936512), /* Filter:1, Coefficient: 88 */ + + /* Filter #23, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(42668), /* Filter:4, Coefficient: 89 */ + CONVERT_COEFF(29706), /* Filter:4, Coefficient: 90 */ + CONVERT_COEFF(7441), /* Filter:4, Coefficient: 91 */ + CONVERT_COEFF(-11516), /* Filter:4, Coefficient: 92 */ + CONVERT_COEFF(-123440), /* Filter:3, Coefficient: 89 */ + CONVERT_COEFF(8781), /* Filter:3, Coefficient: 90 */ + CONVERT_COEFF(98290), /* Filter:3, Coefficient: 91 */ + CONVERT_COEFF(118044), /* Filter:3, Coefficient: 92 */ + CONVERT_COEFF(-339383), /* Filter:2, Coefficient: 89 */ + CONVERT_COEFF(-459507), /* Filter:2, Coefficient: 90 */ + CONVERT_COEFF(-355164), /* Filter:2, Coefficient: 91 */ + CONVERT_COEFF(-138328), /* Filter:2, Coefficient: 92 */ + CONVERT_COEFF(761504), /* Filter:1, Coefficient: 89 */ + CONVERT_COEFF(341342), /* Filter:1, Coefficient: 90 */ + CONVERT_COEFF(-79676), /* Filter:1, Coefficient: 91 */ + CONVERT_COEFF(-329103), /* Filter:1, Coefficient: 92 */ + + /* Filter #24, conversion from 48000 Hz to 12000 Hz */ + + CONVERT_COEFF(-19411), /* Filter:4, Coefficient: 93 */ + CONVERT_COEFF(-15780), /* Filter:4, Coefficient: 94 */ + CONVERT_COEFF(-5811), /* Filter:4, Coefficient: 95 */ + CONVERT_COEFF(758261), /* Filter:4, Coefficient: 96 */ + CONVERT_COEFF(79948), /* Filter:3, Coefficient: 93 */ + CONVERT_COEFF(19085), /* Filter:3, Coefficient: 94 */ + CONVERT_COEFF(-29023), /* Filter:3, Coefficient: 95 */ + CONVERT_COEFF(-1187553), /* Filter:3, Coefficient: 96 */ + CONVERT_COEFF(62290), /* Filter:2, Coefficient: 93 */ + CONVERT_COEFF(164272), /* Filter:2, Coefficient: 94 */ + CONVERT_COEFF(156134), /* Filter:2, Coefficient: 95 */ + CONVERT_COEFF(378483), /* Filter:2, Coefficient: 96 */ + CONVERT_COEFF(-360897), /* Filter:1, Coefficient: 93 */ + CONVERT_COEFF(-238066), /* Filter:1, Coefficient: 94 */ + CONVERT_COEFF(-70489), /* Filter:1, Coefficient: 95 */ + CONVERT_COEFF(50810), /* Filter:1, Coefficient: 96 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_16000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_16000Hz.h new file mode 100644 index 000000000000..7f972f251991 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_16000Hz.h @@ -0,0 +1,562 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 16000 Hz */ +/* NUM_FILTERS=5, FILTER_LENGTH=96, alpha=5.700000, gamma=0.443000 */ + +__cold_rodata static const int32_t coeff48000to16000[] = { + + /* Filter #1, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(6003), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(-2286), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(-11917), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(-12263), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(16701), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(40694), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(27405), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(-25736), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(-56844), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(26944), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(132074), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(141901), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-147894), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(-187545), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(-21075), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(277248), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(14698), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-167333), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(-289523), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(-163034), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(1010), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(18750), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(23487), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(5356), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(-75665), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(-64460), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(21621), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(120266), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(-5491), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-220739), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-298783), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(-96954), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(434836), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(201545), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(-357476), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(-796006), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(218113), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(572796), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(507886), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-103264), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-24865), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(-40246), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(-20333), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(26070), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(132288), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(13456), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(-160847), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-233861), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(286982), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(528042), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(330026), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(-261850), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-608575), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(261248), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(1195810), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(1292859), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-870589), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(-1084744), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-322241), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(1022402), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(61074), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(47049), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(-16265), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(-81433), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(-100488), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(171929), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(359676), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(257462), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-794371), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(-728986), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(53574), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(1014174), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(174255), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(-1469546), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(-2223834), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(-1105863), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(1845595), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(1186048), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(-793496), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(-2620309), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-86732), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(-11725), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(93077), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(136905), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(-117314), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(-482097), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(-490512), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(-44622), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(1290134), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(433539), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(-1052827), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-1945766), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(1365285), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(3245541), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(2622791), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-576159), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(-2535935), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-84562), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(3100653), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(4273125), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(64518), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(-84123), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(-189618), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(-145818), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(552271), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(783867), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(351343), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-501169), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(-1269113), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(735909), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(2545279), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(2459933), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-4050257), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-4676104), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(-1197064), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(4181701), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(1843458), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-2859084), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-6099452), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-4589449), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(40024), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(229992), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(253530), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(54594), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(-1090434), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(-823146), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(245247), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(1324309), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(124819), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-2847668), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-3912612), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(-1694303), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(7014764), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(4162168), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(-3070757), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-9141382), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(1405180), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(7494249), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(8215482), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(1730865), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-235096), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(-376320), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(-213387), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(172458), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(1448025), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(304353), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(-1354202), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-2164152), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(2525824), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(5399928), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(4073459), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(-1173325), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(-8346879), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(91892), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(10287607), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(13522720), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(-7725810), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(-12333767), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-6913819), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(5879577), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(488565), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(444779), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(3934), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(-538903), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(-1231572), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(991042), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(2832294), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(2605690), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(-6524989), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(-7262601), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-1715100), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(6645311), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(5393659), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-9375299), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(-19144348), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-14082933), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(16237057), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(14362523), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(-839543), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(-18862506), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-743652), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(-364983), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(412423), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(1049680), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(51807), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(-3160575), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-4453939), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-2290054), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(11124179), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(6869327), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(-4598379), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-15255006), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(4836350), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(24247448), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(27060755), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(6196430), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(-24233009), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-8964202), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(18626760), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(37047113), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(1021779), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(223192), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-900926), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(-1626034), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(2394425), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(6494128), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(6785094), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(2350160), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(-15741799), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-2587077), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(17884441), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(32479337), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-26945239), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(-47161583), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(-32017732), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(20427044), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(26747798), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(-12522864), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-55553443), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(-63801692), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-1450725), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(-470498), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(661749), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(1177778), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(-4430794), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-9217671), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-8589764), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(-2482951), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(29620390), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(7771362), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-22319484), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-43669888), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(85909205), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(126153193), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(112402280), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(44979247), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(-10171046), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(99475669), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(223708992), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(305859586), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(729289), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(-368490), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(-1360978), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(-1582611), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(5588041), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(10764075), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(10021818), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(4102867), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(-43706637), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-22383172), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(7781413), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(29772819), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-44758225), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(-112244374), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-126089107), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-85924595), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(305859586), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(223708992), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(99475669), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(-10171046), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-908464), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(187247), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(989311), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(1041404), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(-3113458), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-7286202), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(-6424181), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-1920843), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(32745687), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(18147500), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-2455994), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(-15794058), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-20476276), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(31981862), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(47161892), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(26973318), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-63801692), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-55553443), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(-12522864), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(26747798), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(427927), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(-342034), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(-731079), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(-543506), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(2748904), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(4570973), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(2912804), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(-421780), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-15430280), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(-4768911), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(6810261), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(11194720), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(-6166649), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-27051114), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(-24261125), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(-4859188), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(37047113), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(18626760), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(-8964202), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(-24233009), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-11110), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(432181), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(487097), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(181137), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(-2809542), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(-2751305), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-733429), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(1447308), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(6774473), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(-1626617), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(-7269584), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-6605985), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(14069130), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(19148004), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(9390672), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(-5379859), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(-18862506), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(-839543), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(14362523), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(16237057), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-202750), /* Filter:5, Coefficient: 65 */ + CONVERT_COEFF(-371867), /* Filter:5, Coefficient: 66 */ + CONVERT_COEFF(-238987), /* Filter:5, Coefficient: 67 */ + CONVERT_COEFF(46710), /* Filter:5, Coefficient: 68 */ + CONVERT_COEFF(2187189), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(1200707), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(-491006), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(-1524430), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(-1257592), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(4047456), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(5441306), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(2592862), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-13520338), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(-10296413), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(-103461), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(8341557), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(5879577), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(-6913819), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(-12333767), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(-7725810), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(248164), /* Filter:5, Coefficient: 69 */ + CONVERT_COEFF(230638), /* Filter:5, Coefficient: 70 */ + CONVERT_COEFF(45115), /* Filter:5, Coefficient: 71 */ + CONVERT_COEFF(-140841), /* Filter:5, Coefficient: 72 */ + CONVERT_COEFF(-1253197), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(-105103), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(916311), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(1076028), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(-1655380), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(-3925882), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-2894376), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(85264), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(9145142), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(3079217), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(-4156100), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-7015142), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(1730865), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(8215482), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(7494249), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(1405180), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-188394), /* Filter:5, Coefficient: 73 */ + CONVERT_COEFF(-86846), /* Filter:5, Coefficient: 74 */ + CONVERT_COEFF(60603), /* Filter:5, Coefficient: 75 */ + CONVERT_COEFF(134904), /* Filter:5, Coefficient: 76 */ + CONVERT_COEFF(409479), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(-438001), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(-802163), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-501779), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(2455894), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(2573565), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(769517), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(-1256461), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(-4187065), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(1191611), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(4674610), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(4053062), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(-4589449), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(-6099452), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-2859084), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(1843458), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(94077), /* Filter:5, Coefficient: 77 */ + CONVERT_COEFF(-9066), /* Filter:5, Coefficient: 78 */ + CONVERT_COEFF(-84702), /* Filter:5, Coefficient: 79 */ + CONVERT_COEFF(-81382), /* Filter:5, Coefficient: 80 */ + CONVERT_COEFF(112941), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(522408), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(461411), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(70472), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(-1959787), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(-1077960), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(418428), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(1294567), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(580341), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(-2620598), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(-3246544), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(-1368066), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(4273125), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(3100653), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(-84562), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(-2535935), /* Filter:1, Coefficient: 80 */ + + /* Filter #21, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-17797), /* Filter:5, Coefficient: 81 */ + CONVERT_COEFF(45404), /* Filter:5, Coefficient: 82 */ + CONVERT_COEFF(60538), /* Filter:5, Coefficient: 83 */ + CONVERT_COEFF(26766), /* Filter:5, Coefficient: 84 */ + CONVERT_COEFF(-290075), /* Filter:4, Coefficient: 81 */ + CONVERT_COEFF(-357062), /* Filter:4, Coefficient: 82 */ + CONVERT_COEFF(-144107), /* Filter:4, Coefficient: 83 */ + CONVERT_COEFF(126933), /* Filter:4, Coefficient: 84 */ + CONVERT_COEFF(1030932), /* Filter:3, Coefficient: 81 */ + CONVERT_COEFF(67431), /* Filter:3, Coefficient: 82 */ + CONVERT_COEFF(-727987), /* Filter:3, Coefficient: 83 */ + CONVERT_COEFF(-804281), /* Filter:3, Coefficient: 84 */ + CONVERT_COEFF(1103742), /* Filter:2, Coefficient: 81 */ + CONVERT_COEFF(2223786), /* Filter:2, Coefficient: 82 */ + CONVERT_COEFF(1471128), /* Filter:2, Coefficient: 83 */ + CONVERT_COEFF(-172596), /* Filter:2, Coefficient: 84 */ + CONVERT_COEFF(-2620309), /* Filter:1, Coefficient: 81 */ + CONVERT_COEFF(-793496), /* Filter:1, Coefficient: 82 */ + CONVERT_COEFF(1186048), /* Filter:1, Coefficient: 83 */ + CONVERT_COEFF(1845595), /* Filter:1, Coefficient: 84 */ + + /* Filter #22, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-19212), /* Filter:5, Coefficient: 85 */ + CONVERT_COEFF(-39619), /* Filter:5, Coefficient: 86 */ + CONVERT_COEFF(-25052), /* Filter:5, Coefficient: 87 */ + CONVERT_COEFF(4714), /* Filter:5, Coefficient: 88 */ + CONVERT_COEFF(239663), /* Filter:4, Coefficient: 85 */ + CONVERT_COEFF(146928), /* Filter:4, Coefficient: 86 */ + CONVERT_COEFF(-31586), /* Filter:4, Coefficient: 87 */ + CONVERT_COEFF(-139998), /* Filter:4, Coefficient: 88 */ + CONVERT_COEFF(-272737), /* Filter:3, Coefficient: 85 */ + CONVERT_COEFF(326716), /* Filter:3, Coefficient: 86 */ + CONVERT_COEFF(533127), /* Filter:3, Coefficient: 87 */ + CONVERT_COEFF(294587), /* Filter:3, Coefficient: 88 */ + CONVERT_COEFF(-1292361), /* Filter:2, Coefficient: 85 */ + CONVERT_COEFF(-1196542), /* Filter:2, Coefficient: 86 */ + CONVERT_COEFF(-262345), /* Filter:2, Coefficient: 87 */ + CONVERT_COEFF(608020), /* Filter:2, Coefficient: 88 */ + CONVERT_COEFF(1022402), /* Filter:1, Coefficient: 85 */ + CONVERT_COEFF(-322241), /* Filter:1, Coefficient: 86 */ + CONVERT_COEFF(-1084744), /* Filter:1, Coefficient: 87 */ + CONVERT_COEFF(-870589), /* Filter:1, Coefficient: 88 */ + + /* Filter #23, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(22982), /* Filter:5, Coefficient: 89 */ + CONVERT_COEFF(18703), /* Filter:5, Coefficient: 90 */ + CONVERT_COEFF(1310), /* Filter:5, Coefficient: 91 */ + CONVERT_COEFF(-11946), /* Filter:5, Coefficient: 92 */ + CONVERT_COEFF(-114763), /* Filter:4, Coefficient: 89 */ + CONVERT_COEFF(-10932), /* Filter:4, Coefficient: 90 */ + CONVERT_COEFF(70685), /* Filter:4, Coefficient: 91 */ + CONVERT_COEFF(74147), /* Filter:4, Coefficient: 92 */ + CONVERT_COEFF(-93308), /* Filter:3, Coefficient: 89 */ + CONVERT_COEFF(-300945), /* Filter:3, Coefficient: 90 */ + CONVERT_COEFF(-225549), /* Filter:3, Coefficient: 91 */ + CONVERT_COEFF(-8488), /* Filter:3, Coefficient: 92 */ + CONVERT_COEFF(796245), /* Filter:2, Coefficient: 89 */ + CONVERT_COEFF(358093), /* Filter:2, Coefficient: 90 */ + CONVERT_COEFF(-201126), /* Filter:2, Coefficient: 91 */ + CONVERT_COEFF(-434862), /* Filter:2, Coefficient: 92 */ + CONVERT_COEFF(-103264), /* Filter:1, Coefficient: 89 */ + CONVERT_COEFF(507886), /* Filter:1, Coefficient: 90 */ + CONVERT_COEFF(572796), /* Filter:1, Coefficient: 91 */ + CONVERT_COEFF(218113), /* Filter:1, Coefficient: 92 */ + + /* Filter #24, conversion from 48000 Hz to 16000 Hz */ + + CONVERT_COEFF(-11816), /* Filter:5, Coefficient: 93 */ + CONVERT_COEFF(-2391), /* Filter:5, Coefficient: 94 */ + CONVERT_COEFF(5852), /* Filter:5, Coefficient: 95 */ + CONVERT_COEFF(2789237), /* Filter:5, Coefficient: 96 */ + CONVERT_COEFF(20271), /* Filter:4, Coefficient: 93 */ + CONVERT_COEFF(-31141), /* Filter:4, Coefficient: 94 */ + CONVERT_COEFF(-40353), /* Filter:4, Coefficient: 95 */ + CONVERT_COEFF(-5145454), /* Filter:4, Coefficient: 96 */ + CONVERT_COEFF(142594), /* Filter:3, Coefficient: 93 */ + CONVERT_COEFF(134883), /* Filter:3, Coefficient: 94 */ + CONVERT_COEFF(29007), /* Filter:3, Coefficient: 95 */ + CONVERT_COEFF(2574030), /* Filter:3, Coefficient: 96 */ + CONVERT_COEFF(-277542), /* Filter:2, Coefficient: 93 */ + CONVERT_COEFF(20836), /* Filter:2, Coefficient: 94 */ + CONVERT_COEFF(187526), /* Filter:2, Coefficient: 95 */ + CONVERT_COEFF(-232512), /* Filter:2, Coefficient: 96 */ + CONVERT_COEFF(-163034), /* Filter:1, Coefficient: 93 */ + CONVERT_COEFF(-289523), /* Filter:1, Coefficient: 94 */ + CONVERT_COEFF(-167333), /* Filter:1, Coefficient: 95 */ + CONVERT_COEFF(14698), /* Filter:1, Coefficient: 96 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_22050Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_22050Hz.h new file mode 100644 index 000000000000..a367a5aaeb12 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_22050Hz.h @@ -0,0 +1,470 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 22050 Hz */ +/* NUM_FILTERS=5, FILTER_LENGTH=80, alpha=6.900000, gamma=0.440000 */ + +__cold_rodata static const int32_t coeff48000to22050[] = { + + /* Filter #1, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(7662), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(-17184), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(-22717), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(18493), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(26582), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(59229), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-23847), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(-124610), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(-47392), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(71132), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(144232), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-51617), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-97554), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(-81873), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(168609), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(294217), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(-7478), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-118181), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(-86878), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(179401), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(50021), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(-716), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(-81566), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(-50232), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(-31457), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(195123), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(176350), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(-200655), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(-305430), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-114428), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(443237), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(491935), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-107851), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(-611698), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(-258982), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(827677), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(315885), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(-78832), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(-610555), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-331518), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(93705), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(135899), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(-50936), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(-230545), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(-407292), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(40422), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(637092), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(360246), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(-369778), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-1017042), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(-134226), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(1419254), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(1008537), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(-574204), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-1940858), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(-505832), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(737212), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(1062392), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-352536), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-1841477), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-76801), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(275249), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(286242), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(-192062), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(-683487), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(-963806), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(323515), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(1549537), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(1160591), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(-1248908), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(-2484661), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(65823), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(2484992), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(2450305), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(-1828062), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(-4678056), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(-798359), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(2086950), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(2599807), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(-1103167), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-515072), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(-77740), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(637488), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(520979), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(579066), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(-1719643), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(-1913093), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(1028444), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(3467676), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(2238991), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(-3179440), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-5124630), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-677091), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(5922919), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(4937918), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-4589554), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(-4357955), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-1503387), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(4861173), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(5344084), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-497338), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(-1009488), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(-19056), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(1296890), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(3210464), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(772866), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(-3684403), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-3455526), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(793879), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(7290357), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(3834155), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(-6951870), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-9665238), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-459773), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(12380065), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(8936328), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-2820697), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-8978993), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-2385048), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(10125784), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(889191), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(-1077548), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(-1876055), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(109024), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(2472912), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(6129880), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(938394), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(-7290689), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(-9648642), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(2539229), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(14225977), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(6351241), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(-10107211), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(-18425284), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(684847), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(24410695), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(9951675), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(-6442120), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(-17275963), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-3302824), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(2503811), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(1622255), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(-2108058), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(-3706384), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-6226493), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(5152980), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(11810681), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(1756465), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(-14169848), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-18068824), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(6045860), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(28349964), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(15712903), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-21218811), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(-35403029), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(3599978), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(20277588), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(18098088), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-14414412), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-34069195), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-43231), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(4988198), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(4446245), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(-2462458), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(-14505985), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-13737342), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(8767251), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(27475802), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(12429936), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(-29867986), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-41267927), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(9703094), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(50670832), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(31896562), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(-48962542), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-87373984), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(-4069199), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(44482662), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(37762356), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(-39254890), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-8050820), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(-4999058), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(4105217), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(9073725), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(15338177), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(-19743794), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-39156404), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-18221320), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(75644534), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(74121388), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(-12477230), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-103703844), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(4474816), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(169430567), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(238526201), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(112848617), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(-91913076), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-4506400), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(214304195), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(405304801), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(4173646), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(-4920958), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-8020196), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(-2482049), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(22486980), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(39548952), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(16825069), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-17561438), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(-105059398), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-14951358), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(73361822), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(77292504), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-112603327), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(-238487201), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(-169572730), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(-4590557), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(405304801), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(214304195), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-4506400), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(-91913076), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(4418383), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(4986040), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(-25488), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(-3695594), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(-26497283), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-6227664), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(14635866), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(13055417), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(11676560), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(-41128822), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-31313215), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(11383073), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(87419323), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(49090442), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(-31848996), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(-50742654), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(-39254890), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(37762356), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(44482662), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(-4069199), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-2115328), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(1610445), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(2503111), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(117640), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(-3354395), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(-11619407), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(-3795045), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(6834164), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(28805923), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(7109971), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-17815824), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(-14850789), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-3681316), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(35411365), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(21287118), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-15681405), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(-34069195), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(-14414412), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(18098088), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(20277588), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-1871020), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(-1081544), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(883235), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(1296873), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(6559989), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-1807040), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(-6018602), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-1736019), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(5784968), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(14451451), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(3098823), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(-9531104), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-24446956), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(-728979), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(18430270), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(10144287), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-3302824), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-17275963), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(-6442120), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(9951675), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-14486), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(-1007116), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(-499607), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(518015), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(3750042), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(3262673), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(-1214266), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(-3107008), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-7325337), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(3551588), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(7434859), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(1083621), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(-8921035), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-12401028), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(437331), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(9670117), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(10125784), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(-2385048), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(-8978993), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(-2820697), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(637690), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(-75416), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(-514050), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(-193261), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(-639301), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(2025342), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(1480378), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(-777830), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-5090473), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(-3382465), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(2113958), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(3558926), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(4609140), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-4932011), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(-5934824), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(666961), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(5344084), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(4861173), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-1503387), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(-4357955), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(284900), /* Filter:5, Coefficient: 65 */ + CONVERT_COEFF(275450), /* Filter:5, Coefficient: 66 */ + CONVERT_COEFF(-75748), /* Filter:5, Coefficient: 67 */ + CONVERT_COEFF(-230175), /* Filter:5, Coefficient: 68 */ + CONVERT_COEFF(-1466138), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(-138526), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(988361), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(561735), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(202115), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(-2487174), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(-1348983), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(1116387), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(4682079), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(1837378), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(-2448933), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(-2491052), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(-1103167), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(2599807), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(2086950), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(-798359), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-51484), /* Filter:5, Coefficient: 69 */ + CONVERT_COEFF(135388), /* Filter:5, Coefficient: 70 */ + CONVERT_COEFF(93830), /* Filter:5, Coefficient: 71 */ + CONVERT_COEFF(-49843), /* Filter:5, Coefficient: 72 */ + CONVERT_COEFF(-431830), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(-583157), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(31866), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(400739), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(1470096), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(-80799), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-1028729), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(-410822), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(502162), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(1943488), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(577848), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-1008802), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(-1841477), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(-352536), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(1062392), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(737212), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-81469), /* Filter:5, Coefficient: 73 */ + CONVERT_COEFF(-912), /* Filter:5, Coefficient: 74 */ + CONVERT_COEFF(49880), /* Filter:5, Coefficient: 75 */ + CONVERT_COEFF(18545), /* Filter:5, Coefficient: 76 */ + CONVERT_COEFF(149914), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(-191736), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(-168399), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(50437), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(482726), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(466197), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(-99774), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(-314278), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(-830203), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(258176), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(613009), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(108811), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(-331518), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(-610555), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-78832), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(315885), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 22050 Hz */ + + CONVERT_COEFF(-22620), /* Filter:5, Coefficient: 77 */ + CONVERT_COEFF(-17175), /* Filter:5, Coefficient: 78 */ + CONVERT_COEFF(7621), /* Filter:5, Coefficient: 79 */ + CONVERT_COEFF(1139618), /* Filter:5, Coefficient: 80 */ + CONVERT_COEFF(114508), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(9531), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(-57126), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(-2091381), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(-63466), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(145663), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(78240), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(1014579), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(-294701), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(-169322), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(81968), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(-55338), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(179401), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(-86878), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(-118181), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(-7478), /* Filter:1, Coefficient: 80 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_24000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_24000Hz.h new file mode 100644 index 000000000000..e74514d294ae --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_24000Hz.h @@ -0,0 +1,470 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 24000 Hz */ +/* NUM_FILTERS=5, FILTER_LENGTH=80, alpha=7.500000, gamma=0.440000 */ + +__cold_rodata static const int32_t coeff48000to24000[] = { + + /* Filter #1, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-13838), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(-4878), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(27346), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(15920), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(25265), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(-42584), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-60777), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(71524), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(47328), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(43014), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(-104992), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-127217), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-2834), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(111653), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(50477), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-231338), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(-41434), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(14488), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(121697), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(33752), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-45854), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(-42865), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(63570), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(93651), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(137676), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(-84397), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(-270825), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(41689), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(165291), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(305244), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-174342), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(-598509), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-207390), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(350931), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(536033), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(-368031), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-237368), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(-187652), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(341275), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(495730), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-67575), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(-172357), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(37425), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(273544), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(458722), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(112302), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(-667913), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-436742), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(41098), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(983891), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(349373), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(-1364077), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-1063316), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(121078), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(1731952), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(580588), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-335483), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(-966591), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(78327), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(1529224), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(52090), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(-376509), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(-224228), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(441602), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(820085), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(970404), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-788941), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-1699573), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-1101019), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(1549721), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(2252110), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(-1267504), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(-2355777), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(-1892010), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(2600412), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(3840272), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(582559), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(-2002140), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(-1750602), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(2088832), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(489839), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(-411054), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(-834753), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(216224), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(413580), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(2524893), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(467752), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(-3237432), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-3710975), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(204721), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(5200041), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(1907427), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-2010349), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-6224958), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(95035), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(8541845), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(3403760), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-1414199), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(-5320802), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(-392742), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(1207772), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(208047), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(-1512464), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(-902856), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(-1964673), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(3514611), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(4069138), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-2943356), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(-6229468), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(-5181060), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(6118238), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(9448813), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(3529031), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-9961767), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(-8961434), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(9386380), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(7035593), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(3578394), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-7842078), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-8128913), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(1605200), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(1860328), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(-1299691), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(-2995019), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(-6587556), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(1071316), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(9078533), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(2520726), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(-4069677), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-14153956), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-708399), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(18265964), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(15841264), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(-5580394), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(-23206259), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-2651769), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(6860332), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(13650089), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(-3152739), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-19289299), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(374618), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(4104773), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(1423065), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(-4786018), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-10790451), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(-8135144), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(10552917), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(15849886), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(8867184), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-20196992), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(-20805992), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(17591439), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(29398714), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(16316208), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(-31955417), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(-36235851), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(-4149557), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(23701422), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(15790875), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-24995516), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-4380083), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(4154074), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(8675375), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(314997), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(-6457951), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-25205239), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-5222436), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(33153210), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(36619130), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(-6512823), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-55966649), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-22123969), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(27200860), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(63486136), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(-8378210), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-101100781), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(-32577317), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(20405426), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(56329747), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(-4562349), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-11223389), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(-9182954), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(5881106), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(14830455), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(32686336), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(-17828627), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-56842565), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-29576137), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(75895153), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(107387729), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(3315284), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-129456983), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-44707785), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(159981825), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(284418268), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(144185861), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(-94322531), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-41673825), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(198691815), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(435480713), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(5793826), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(-9270194), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-11239929), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(350438), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(33611108), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(54752705), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(12202297), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-34504953), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(-132194211), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-1313049), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(106654220), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(79294325), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-144007288), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(-284533495), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(-160261654), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(44620548), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(435480713), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(198691815), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-41673825), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(-94322531), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(8697892), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(4139411), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(-4400335), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(-4782540), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(-29508465), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(8636575), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(24014024), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(3272779), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-19581710), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(-57247113), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-9049303), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(36450428), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(101282205), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(8546018), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(-63545873), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(-27357901), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(-4562349), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(56329747), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(20405426), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(-32577317), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(1438893), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(4107485), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(363683), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(-3000681), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(-16278067), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(-8279099), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(9318126), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(9464322), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(19409638), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-19986418), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-21274397), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(7861648), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(36215318), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(32067664), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(-16258232), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-29464286), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(-24995516), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(15790875), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(23701422), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(-4149557), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-1293262), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(1866746), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(1602403), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(-908649), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(-3897952), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-8522376), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(177415), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(6565670), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(18743832), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(224054), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-14211714), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(-4803433), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(2584064), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(23233877), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(5641875), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(-15842519), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-19289299), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(-3152739), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(13650089), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(6860332), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-1512218), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(212504), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(1209017), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(213290), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(1976159), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(-4356506), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(-2866105), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(2379900), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(9257256), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(6616934), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(-4879764), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(-6512863), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(-9434058), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(8947402), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(9993781), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(-3508647), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(-8128913), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(-7842078), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(3578394), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(7035593), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-836606), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(-409479), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(491682), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(441038), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(2873370), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(-885436), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-2375971), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(-64342), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(1595238), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(5317156), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(469755), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-3719261), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(-8559856), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-115583), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(6232362), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(2027557), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(-392742), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(-5320802), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-1414199), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(3403760), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(-225715), /* Filter:5, Coefficient: 65 */ + CONVERT_COEFF(-376564), /* Filter:5, Coefficient: 66 */ + CONVERT_COEFF(53103), /* Filter:5, Coefficient: 67 */ + CONVERT_COEFF(273883), /* Filter:5, Coefficient: 68 */ + CONVERT_COEFF(1688791), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(534773), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(-1030744), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(-657535), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(-1461589), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(2203284), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(1673250), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(-1033553), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-3840853), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(-2612954), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(1889068), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(2363811), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(2088832), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(-1750602), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(-2002140), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(582559), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(36846), /* Filter:5, Coefficient: 69 */ + CONVERT_COEFF(-172746), /* Filter:5, Coefficient: 70 */ + CONVERT_COEFF(-67313), /* Filter:5, Coefficient: 71 */ + CONVERT_COEFF(93968), /* Filter:5, Coefficient: 72 */ + CONVERT_COEFF(519728), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(577634), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(-189254), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(-416848), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(-1430962), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(286656), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(1012557), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(88679), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(-576512), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(-1736423), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(-124869), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(1065395), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(1529224), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(78327), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(-966591), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(-335483), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(63497), /* Filter:5, Coefficient: 73 */ + CONVERT_COEFF(-43069), /* Filter:5, Coefficient: 74 */ + CONVERT_COEFF(-45864), /* Filter:5, Coefficient: 75 */ + CONVERT_COEFF(16027), /* Filter:5, Coefficient: 76 */ + CONVERT_COEFF(16898), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(256277), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(45646), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-135456), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(-605787), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(-205368), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(303359), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(183044), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(370923), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(-536759), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(-352848), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(207503), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(495730), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(341275), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(-187652), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-237368), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 24000 Hz */ + + CONVERT_COEFF(27375), /* Filter:5, Coefficient: 77 */ + CONVERT_COEFF(-4922), /* Filter:5, Coefficient: 78 */ + CONVERT_COEFF(-13857), /* Filter:5, Coefficient: 79 */ + CONVERT_COEFF(-763703), /* Filter:5, Coefficient: 80 */ + CONVERT_COEFF(-48618), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(62211), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(30113), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(1343965), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(-123289), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(-114093), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(40096), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(-641120), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(232473), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(-50406), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(-112271), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(102292), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(33752), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(121697), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(14488), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(-41434), /* Filter:1, Coefficient: 80 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_32000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_32000Hz.h new file mode 100644 index 000000000000..1d02d5885466 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_32000Hz.h @@ -0,0 +1,550 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 32000 Hz */ +/* NUM_FILTERS=6, FILTER_LENGTH=80, alpha=8.000000, gamma=0.452000 */ + +__cold_rodata static const int32_t coeff48000to32000[] = { + + /* Filter #1, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-11561), /* Filter:6, Coefficient: 1 */ + CONVERT_COEFF(15747), /* Filter:6, Coefficient: 2 */ + CONVERT_COEFF(5105), /* Filter:6, Coefficient: 3 */ + CONVERT_COEFF(-38743), /* Filter:6, Coefficient: 4 */ + CONVERT_COEFF(9801), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(-57987), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(55855), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(57347), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(46237), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(-16129), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-97341), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(155756), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(9592), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(90049), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(-143614), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-53049), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-56068), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(83510), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(61872), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-268865), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(-22379), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-24379), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(90814), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(-27309), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(32278), /* Filter:6, Coefficient: 5 */ + CONVERT_COEFF(39046), /* Filter:6, Coefficient: 6 */ + CONVERT_COEFF(-95870), /* Filter:6, Coefficient: 7 */ + CONVERT_COEFF(23105), /* Filter:6, Coefficient: 8 */ + CONVERT_COEFF(-175841), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(72860), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(247915), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(-361409), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(35097), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(-344433), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(268897), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(365707), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(365130), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-248936), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-457784), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(858658), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(128732), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(422344), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(-623551), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(-218850), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-174868), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(210533), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(151417), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-508987), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(138684), /* Filter:6, Coefficient: 9 */ + CONVERT_COEFF(-160549), /* Filter:6, Coefficient: 10 */ + CONVERT_COEFF(-79806), /* Filter:6, Coefficient: 11 */ + CONVERT_COEFF(315837), /* Filter:6, Coefficient: 12 */ + CONVERT_COEFF(-88230), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(670200), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(-440690), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(-669306), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(-792638), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(86409), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(1208069), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-1151663), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(41857), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-1469440), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(1160033), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(1367901), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(1266645), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(-690167), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-1490906), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(2295682), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(158227), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(724561), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(-839003), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-482312), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-143037), /* Filter:6, Coefficient: 13 */ + CONVERT_COEFF(-351812), /* Filter:6, Coefficient: 14 */ + CONVERT_COEFF(494431), /* Filter:6, Coefficient: 15 */ + CONVERT_COEFF(110738), /* Filter:6, Coefficient: 16 */ + CONVERT_COEFF(1230829), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(-10053), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(-1802066), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(1456443), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(-910652), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(2480789), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-641633), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(-3110197), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-2897785), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(246665), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(4107125), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(-3569996), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(473707), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(-3847887), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(2297303), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(3846674), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(1676174), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(-570776), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(-2053116), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(2402095), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-790086), /* Filter:6, Coefficient: 17 */ + CONVERT_COEFF(463549), /* Filter:6, Coefficient: 18 */ + CONVERT_COEFF(736606), /* Filter:6, Coefficient: 19 */ + CONVERT_COEFF(-1203048), /* Filter:6, Coefficient: 20 */ + CONVERT_COEFF(1420579), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(-3164667), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(474626), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(3997758), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(3363870), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(1795377), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(-6095509), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(2170913), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-3143459), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(7478803), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(-1291163), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-9390934), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(-6253867), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-704435), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(9301477), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-6005932), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(1135780), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-4267272), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(1601388), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(4727524), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-85369), /* Filter:6, Coefficient: 21 */ + CONVERT_COEFF(1689090), /* Filter:6, Coefficient: 22 */ + CONVERT_COEFF(-1153692), /* Filter:6, Coefficient: 23 */ + CONVERT_COEFF(-1392092), /* Filter:6, Coefficient: 24 */ + CONVERT_COEFF(-3695078), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(-2619412), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(6934895), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(-1671143), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(6715445), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(-8010806), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(-3066771), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(13022550), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(8830976), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(6179129), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(-16519290), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(3931355), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-8288130), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(14331732), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(596302), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(-19674765), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-5703839), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(-2226042), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(9343886), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-3864751), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(2561676), /* Filter:6, Coefficient: 25 */ + CONVERT_COEFF(-41718), /* Filter:6, Coefficient: 26 */ + CONVERT_COEFF(-3351923), /* Filter:6, Coefficient: 27 */ + CONVERT_COEFF(2484217), /* Filter:6, Coefficient: 28 */ + CONVERT_COEFF(-7983534), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(8090613), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(4635953), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(-14057177), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(-5546048), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(-13215426), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(17029298), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(5073548), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(19154324), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(-19288118), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-11295504), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(33812123), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(13651643), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(16170479), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(-29933479), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(407469), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(-9649047), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(12189269), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(3905181), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-19010870), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(2646463), /* Filter:6, Coefficient: 29 */ + CONVERT_COEFF(-5183436), /* Filter:6, Coefficient: 30 */ + CONVERT_COEFF(113142), /* Filter:6, Coefficient: 31 */ + CONVERT_COEFF(6922098), /* Filter:6, Coefficient: 32 */ + CONVERT_COEFF(4012768), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(15785061), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(-16561721), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(-9670889), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-26242846), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(12222374), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(26293489), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-35302032), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(-9629387), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-38047097), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(40551122), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(22142931), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(39448271), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-29337586), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(-31488442), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(62886474), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(8709491), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(18945155), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-25616062), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(-6708613), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-4854058), /* Filter:6, Coefficient: 33 */ + CONVERT_COEFF(-6493349), /* Filter:6, Coefficient: 34 */ + CONVERT_COEFF(10955382), /* Filter:6, Coefficient: 35 */ + CONVERT_COEFF(3639331), /* Filter:6, Coefficient: 36 */ + CONVERT_COEFF(29320297), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(-6238872), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(-37929537), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(31607052), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(-10922848), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(57004450), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-23682378), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(-69775212), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(-71937950), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(20998625), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(89787906), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-97112393), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(-2929444), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-86584128), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(69191980), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(80706313), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(40270809), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(-21053631), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(-42367788), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(65956939), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-17266601), /* Filter:6, Coefficient: 37 */ + CONVERT_COEFF(231253), /* Filter:6, Coefficient: 38 */ + CONVERT_COEFF(21704927), /* Filter:6, Coefficient: 39 */ + CONVERT_COEFF(-2600806), /* Filter:6, Coefficient: 40 */ + CONVERT_COEFF(41975839), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(-59844606), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(-44992655), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(73711853), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(81790468), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(86455952), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-138195163), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-113308335), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(-81580682), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(240735052), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(145279809), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-321141069), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-178457029), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-14491810), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(488414096), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(292747412), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(15022342), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(-138518549), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(114569679), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(586792923), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-20066125), /* Filter:6, Coefficient: 41 */ + CONVERT_COEFF(5767713), /* Filter:6, Coefficient: 42 */ + CONVERT_COEFF(15089402), /* Filter:6, Coefficient: 43 */ + CONVERT_COEFF(-7757981), /* Filter:6, Coefficient: 44 */ + CONVERT_COEFF(38637120), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(-70881813), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-22766795), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(54397391), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(145358829), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(111916983), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(-108596377), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-60427595), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(-248537116), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(217233738), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(188328936), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(-122913915), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-407818384), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(-414365665), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(101272401), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(136295795), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(516212737), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(23787556), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(-126544125), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(46784418), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-8119365), /* Filter:6, Coefficient: 45 */ + CONVERT_COEFF(8416921), /* Filter:6, Coefficient: 46 */ + CONVERT_COEFF(2011547), /* Filter:6, Coefficient: 47 */ + CONVERT_COEFF(-7011741), /* Filter:6, Coefficient: 48 */ + CONVERT_COEFF(239202), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(-36066145), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(15579621), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(18206458), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(78881593), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(7227261), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-55803497), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(21803835), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-57723218), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(99822925), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-9284004), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-64228804), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(-112035461), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(-30308183), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(88786923), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(-24912829), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(46379080), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(-52379260), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(-3286550), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(38004833), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(2029399), /* Filter:6, Coefficient: 49 */ + CONVERT_COEFF(4158325), /* Filter:6, Coefficient: 50 */ + CONVERT_COEFF(-3721541), /* Filter:6, Coefficient: 51 */ + CONVERT_COEFF(-1133029), /* Filter:6, Coefficient: 52 */ + CONVERT_COEFF(-20392589), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(-2906434), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(16751891), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(-6818425), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(28980439), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(-30983025), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(-5048118), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(25896772), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(39777989), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(25764575), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(-43217126), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(4190043), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(-50106572), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(44996435), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(12663590), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(-40495107), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(-18138626), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(-17850332), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(23180027), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(608735), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(3433587), /* Filter:6, Coefficient: 53 */ + CONVERT_COEFF(-1029758), /* Filter:6, Coefficient: 54 */ + CONVERT_COEFF(-2029714), /* Filter:6, Coefficient: 55 */ + CONVERT_COEFF(1907010), /* Filter:6, Coefficient: 56 */ + CONVERT_COEFF(-8939750), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(10066060), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(1203126), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(-8271006), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(-10289050), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-13908366), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(15437261), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(1959317), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(30176511), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(-19720665), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-11906392), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(21431694), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(12685188), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(23538156), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(-22526671), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(-5324400), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-17751380), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(9315300), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(8260899), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-11561731), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(463533), /* Filter:6, Coefficient: 57 */ + CONVERT_COEFF(-1687787), /* Filter:6, Coefficient: 58 */ + CONVERT_COEFF(600074), /* Filter:6, Coefficient: 59 */ + CONVERT_COEFF(911501), /* Filter:6, Coefficient: 60 */ + CONVERT_COEFF(3698444), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(4136678), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(-5065760), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(-233174), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(-12705057), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(5580298), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(6376293), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(-7669533), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-2881357), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(-14454865), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(10115126), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(5126005), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(19856482), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-6933075), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(-10972601), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(11128930), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(140888), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(8573112), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(-4785738), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(-3732684), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-950577), /* Filter:6, Coefficient: 61 */ + CONVERT_COEFF(-130034), /* Filter:6, Coefficient: 62 */ + CONVERT_COEFF(756094), /* Filter:6, Coefficient: 63 */ + CONVERT_COEFF(-329642), /* Filter:6, Coefficient: 64 */ + CONVERT_COEFF(3849839), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(-1976633), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(-1672857), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(2337162), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(-439082), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(5830744), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-2898810), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(-2565926), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(-10239291), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(1875733), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(6351912), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-4786768), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(1978448), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-9164115), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(3532591), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(4618733), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(5531160), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(-269508), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-3833892), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(2235084), /* Filter:1, Coefficient: 64 */ + + /* Filter #17, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-346938), /* Filter:6, Coefficient: 65 */ + CONVERT_COEFF(420998), /* Filter:6, Coefficient: 66 */ + CONVERT_COEFF(2948), /* Filter:6, Coefficient: 67 */ + CONVERT_COEFF(-283734), /* Filter:6, Coefficient: 68 */ + CONVERT_COEFF(-118556), /* Filter:5, Coefficient: 65 */ + CONVERT_COEFF(-1556054), /* Filter:5, Coefficient: 66 */ + CONVERT_COEFF(938534), /* Filter:5, Coefficient: 67 */ + CONVERT_COEFF(530259), /* Filter:5, Coefficient: 68 */ + CONVERT_COEFF(3449180), /* Filter:4, Coefficient: 65 */ + CONVERT_COEFF(-99308), /* Filter:4, Coefficient: 66 */ + CONVERT_COEFF(-2308321), /* Filter:4, Coefficient: 67 */ + CONVERT_COEFF(1316267), /* Filter:4, Coefficient: 68 */ + CONVERT_COEFF(-1879552), /* Filter:3, Coefficient: 65 */ + CONVERT_COEFF(4332349), /* Filter:3, Coefficient: 66 */ + CONVERT_COEFF(-1033406), /* Filter:3, Coefficient: 67 */ + CONVERT_COEFF(-2361476), /* Filter:3, Coefficient: 68 */ + CONVERT_COEFF(-4953240), /* Filter:2, Coefficient: 65 */ + CONVERT_COEFF(-565926), /* Filter:2, Coefficient: 66 */ + CONVERT_COEFF(3678031), /* Filter:2, Coefficient: 67 */ + CONVERT_COEFF(-1548139), /* Filter:2, Coefficient: 68 */ + CONVERT_COEFF(1508675), /* Filter:1, Coefficient: 65 */ + CONVERT_COEFF(-2340479), /* Filter:1, Coefficient: 66 */ + CONVERT_COEFF(191583), /* Filter:1, Coefficient: 67 */ + CONVERT_COEFF(1469400), /* Filter:1, Coefficient: 68 */ + + /* Filter #18, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(154632), /* Filter:6, Coefficient: 69 */ + CONVERT_COEFF(97677), /* Filter:6, Coefficient: 70 */ + CONVERT_COEFF(-151006), /* Filter:6, Coefficient: 71 */ + CONVERT_COEFF(22864), /* Filter:6, Coefficient: 72 */ + CONVERT_COEFF(-909572), /* Filter:5, Coefficient: 69 */ + CONVERT_COEFF(153482), /* Filter:5, Coefficient: 70 */ + CONVERT_COEFF(491289), /* Filter:5, Coefficient: 71 */ + CONVERT_COEFF(-360835), /* Filter:5, Coefficient: 72 */ + CONVERT_COEFF(817805), /* Filter:4, Coefficient: 69 */ + CONVERT_COEFF(-1291146), /* Filter:4, Coefficient: 70 */ + CONVERT_COEFF(169841), /* Filter:4, Coefficient: 71 */ + CONVERT_COEFF(707188), /* Filter:4, Coefficient: 72 */ + CONVERT_COEFF(1928437), /* Filter:3, Coefficient: 69 */ + CONVERT_COEFF(514414), /* Filter:3, Coefficient: 70 */ + CONVERT_COEFF(-1484055), /* Filter:3, Coefficient: 71 */ + CONVERT_COEFF(448482), /* Filter:3, Coefficient: 72 */ + CONVERT_COEFF(-1615722), /* Filter:2, Coefficient: 69 */ + CONVERT_COEFF(1829243), /* Filter:2, Coefficient: 70 */ + CONVERT_COEFF(84371), /* Filter:2, Coefficient: 71 */ + CONVERT_COEFF(-1162547), /* Filter:2, Coefficient: 72 */ + CONVERT_COEFF(-877441), /* Filter:1, Coefficient: 69 */ + CONVERT_COEFF(-501872), /* Filter:1, Coefficient: 70 */ + CONVERT_COEFF(801814), /* Filter:1, Coefficient: 71 */ + CONVERT_COEFF(-87747), /* Filter:1, Coefficient: 72 */ + + /* Filter #19, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(77476), /* Filter:6, Coefficient: 73 */ + CONVERT_COEFF(-55647), /* Filter:6, Coefficient: 74 */ + CONVERT_COEFF(-12425), /* Filter:6, Coefficient: 75 */ + CONVERT_COEFF(36432), /* Filter:6, Coefficient: 76 */ + CONVERT_COEFF(-98904), /* Filter:5, Coefficient: 73 */ + CONVERT_COEFF(262255), /* Filter:5, Coefficient: 74 */ + CONVERT_COEFF(-86370), /* Filter:5, Coefficient: 75 */ + CONVERT_COEFF(-93036), /* Filter:5, Coefficient: 76 */ + CONVERT_COEFF(-474181), /* Filter:4, Coefficient: 73 */ + CONVERT_COEFF(-161908), /* Filter:4, Coefficient: 74 */ + CONVERT_COEFF(348709), /* Filter:4, Coefficient: 75 */ + CONVERT_COEFF(-94475), /* Filter:4, Coefficient: 76 */ + CONVERT_COEFF(655915), /* Filter:3, Coefficient: 73 */ + CONVERT_COEFF(-589182), /* Filter:3, Coefficient: 74 */ + CONVERT_COEFF(-68486), /* Filter:3, Coefficient: 75 */ + CONVERT_COEFF(343484), /* Filter:3, Coefficient: 76 */ + CONVERT_COEFF(527672), /* Filter:2, Coefficient: 73 */ + CONVERT_COEFF(407424), /* Filter:2, Coefficient: 74 */ + CONVERT_COEFF(-485562), /* Filter:2, Coefficient: 75 */ + CONVERT_COEFF(16521), /* Filter:2, Coefficient: 76 */ + CONVERT_COEFF(-432603), /* Filter:1, Coefficient: 73 */ + CONVERT_COEFF(255380), /* Filter:1, Coefficient: 74 */ + CONVERT_COEFF(118325), /* Filter:1, Coefficient: 75 */ + CONVERT_COEFF(-185814), /* Filter:1, Coefficient: 76 */ + + /* Filter #20, conversion from 48000 Hz to 32000 Hz */ + + CONVERT_COEFF(-14137), /* Filter:6, Coefficient: 77 */ + CONVERT_COEFF(-9206), /* Filter:6, Coefficient: 78 */ + CONVERT_COEFF(11763), /* Filter:6, Coefficient: 79 */ + CONVERT_COEFF(-1554661), /* Filter:6, Coefficient: 80 */ + CONVERT_COEFF(94324), /* Filter:5, Coefficient: 77 */ + CONVERT_COEFF(-8059), /* Filter:5, Coefficient: 78 */ + CONVERT_COEFF(-36850), /* Filter:5, Coefficient: 79 */ + CONVERT_COEFF(3952809), /* Filter:5, Coefficient: 80 */ + CONVERT_COEFF(-126700), /* Filter:4, Coefficient: 77 */ + CONVERT_COEFF(110024), /* Filter:4, Coefficient: 78 */ + CONVERT_COEFF(-3318), /* Filter:4, Coefficient: 79 */ + CONVERT_COEFF(-3431485), /* Filter:4, Coefficient: 80 */ + CONVERT_COEFF(-132999), /* Filter:3, Coefficient: 77 */ + CONVERT_COEFF(-93296), /* Filter:3, Coefficient: 78 */ + CONVERT_COEFF(98915), /* Filter:3, Coefficient: 79 */ + CONVERT_COEFF(1107272), /* Filter:3, Coefficient: 80 */ + CONVERT_COEFF(229610), /* Filter:2, Coefficient: 77 */ + CONVERT_COEFF(-109871), /* Filter:2, Coefficient: 78 */ + CONVERT_COEFF(-44438), /* Filter:2, Coefficient: 79 */ + CONVERT_COEFF(-62812), /* Filter:2, Coefficient: 80 */ + CONVERT_COEFF(23112), /* Filter:1, Coefficient: 77 */ + CONVERT_COEFF(73212), /* Filter:1, Coefficient: 78 */ + CONVERT_COEFF(-37195), /* Filter:1, Coefficient: 79 */ + CONVERT_COEFF(-11124), /* Filter:1, Coefficient: 80 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_44100Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_44100Hz.h new file mode 100644 index 000000000000..ad487d58af14 --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_44100Hz.h @@ -0,0 +1,506 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 44100 Hz */ +/* NUM_FILTERS=7, FILTER_LENGTH=64, alpha=8.150000, gamma=0.456000 */ + +__cold_rodata static const int32_t coeff48000to44100[] = { + + /* Filter #1, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-34608), /* Filter:7, Coefficient: 1 */ + CONVERT_COEFF(58942), /* Filter:7, Coefficient: 2 */ + CONVERT_COEFF(-85115), /* Filter:7, Coefficient: 3 */ + CONVERT_COEFF(96633), /* Filter:7, Coefficient: 4 */ + CONVERT_COEFF(69866), /* Filter:6, Coefficient: 1 */ + CONVERT_COEFF(-157606), /* Filter:6, Coefficient: 2 */ + CONVERT_COEFF(299637), /* Filter:6, Coefficient: 3 */ + CONVERT_COEFF(-469979), /* Filter:6, Coefficient: 4 */ + CONVERT_COEFF(61623), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(-49681), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(-50870), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(302189), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(-66312), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(181693), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(-384955), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(630700), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(-133695), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(219785), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(-230581), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(36535), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-1792), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(-79997), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(271909), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(-561039), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(33030), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(-71885), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(101248), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(-78725), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-67867), /* Filter:7, Coefficient: 5 */ + CONVERT_COEFF(-28521), /* Filter:7, Coefficient: 6 */ + CONVERT_COEFF(207221), /* Filter:7, Coefficient: 7 */ + CONVERT_COEFF(-452333), /* Filter:7, Coefficient: 8 */ + CONVERT_COEFF(592244), /* Filter:6, Coefficient: 5 */ + CONVERT_COEFF(-540223), /* Filter:6, Coefficient: 6 */ + CONVERT_COEFF(168968), /* Filter:6, Coefficient: 7 */ + CONVERT_COEFF(620325), /* Filter:6, Coefficient: 8 */ + CONVERT_COEFF(-730836), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(1274818), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(-1742595), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(1816487), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(-786525), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(641498), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(29205), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(-1344095), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(483560), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(-1352248), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(2396129), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(-3194402), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(844568), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(-919927), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(530444), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(525026), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-43685), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(291450), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(-633133), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(956210), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(703127), /* Filter:7, Coefficient: 9 */ + CONVERT_COEFF(-853001), /* Filter:7, Coefficient: 10 */ + CONVERT_COEFF(769748), /* Filter:7, Coefficient: 11 */ + CONVERT_COEFF(-339193), /* Filter:7, Coefficient: 12 */ + CONVERT_COEFF(-1794792), /* Filter:6, Coefficient: 9 */ + CONVERT_COEFF(3115259), /* Filter:6, Coefficient: 10 */ + CONVERT_COEFF(-4115635), /* Filter:6, Coefficient: 11 */ + CONVERT_COEFF(4175773), /* Filter:6, Coefficient: 12 */ + CONVERT_COEFF(-1127711), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(-592357), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(3316547), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(-6552082), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(3171756), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(-5026421), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(6078263), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(-5335178), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(3130331), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(-1578560), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(-1791676), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(6684486), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-2241194), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(4271071), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-5884188), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(6087444), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(-1072749), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(768744), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(104733), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-1522163), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-475432), /* Filter:7, Coefficient: 13 */ + CONVERT_COEFF(1576583), /* Filter:7, Coefficient: 14 */ + CONVERT_COEFF(-2703138), /* Filter:7, Coefficient: 15 */ + CONVERT_COEFF(3453146), /* Filter:7, Coefficient: 16 */ + CONVERT_COEFF(-2703131), /* Filter:6, Coefficient: 13 */ + CONVERT_COEFF(-602943), /* Filter:6, Coefficient: 14 */ + CONVERT_COEFF(5477993), /* Filter:6, Coefficient: 15 */ + CONVERT_COEFF(-10918971), /* Filter:6, Coefficient: 16 */ + CONVERT_COEFF(9289206), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(-10150369), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(7770551), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(-1353879), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(1998375), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(4084791), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-12023857), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(19736881), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-11958163), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(15672295), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(-15501757), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(9501580), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(-3932030), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(-1045712), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(8383285), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(-16438405), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(3198988), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(-4582047), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(4952446), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(-3644365), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-3371842), /* Filter:7, Coefficient: 17 */ + CONVERT_COEFF(2097989), /* Filter:7, Coefficient: 18 */ + CONVERT_COEFF(462769), /* Filter:7, Coefficient: 19 */ + CONVERT_COEFF(-3989397), /* Filter:7, Coefficient: 20 */ + CONVERT_COEFF(15222797), /* Filter:6, Coefficient: 17 */ + CONVERT_COEFF(-16309530), /* Filter:6, Coefficient: 18 */ + CONVERT_COEFF(12321848), /* Filter:6, Coefficient: 19 */ + CONVERT_COEFF(-2389147), /* Filter:6, Coefficient: 20 */ + CONVERT_COEFF(-8743201), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(20620478), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(-30859164), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(35112554), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(-24216328), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(22270762), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(-11641126), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(-7783920), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(2945332), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(-20300949), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(38527510), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-51525628), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(22503598), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-23386679), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(16406368), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-579401), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(335976), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(4676188), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(-10331423), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(14886324), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(7681853), /* Filter:7, Coefficient: 21 */ + CONVERT_COEFF(-10332684), /* Filter:7, Coefficient: 22 */ + CONVERT_COEFF(10556529), /* Filter:7, Coefficient: 23 */ + CONVERT_COEFF(-7162197), /* Filter:7, Coefficient: 24 */ + CONVERT_COEFF(-12649004), /* Filter:6, Coefficient: 21 */ + CONVERT_COEFF(29813575), /* Filter:6, Coefficient: 22 */ + CONVERT_COEFF(-44081375), /* Filter:6, Coefficient: 23 */ + CONVERT_COEFF(49138162), /* Filter:6, Coefficient: 24 */ + CONVERT_COEFF(-29258606), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(10919084), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(19020907), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(-55343811), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(33051579), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(-57937612), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(73731473), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-71049212), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(52464541), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(-35835631), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(-221654), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(51953451), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(-22361334), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(47518499), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(-67260276), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(72617965), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-16268114), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(12660525), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-3194146), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(-11448189), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-380917), /* Filter:7, Coefficient: 25 */ + CONVERT_COEFF(11434339), /* Filter:7, Coefficient: 26 */ + CONVERT_COEFF(-23628219), /* Filter:7, Coefficient: 27 */ + CONVERT_COEFF(32030513), /* Filter:7, Coefficient: 28 */ + CONVERT_COEFF(-38782554), /* Filter:6, Coefficient: 25 */ + CONVERT_COEFF(8866692), /* Filter:6, Coefficient: 26 */ + CONVERT_COEFF(40253511), /* Filter:6, Coefficient: 27 */ + CONVERT_COEFF(-100091024), /* Filter:6, Coefficient: 28 */ + CONVERT_COEFF(88284037), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(-104388358), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(88441513), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(-26445221), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(42410154), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(14925059), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(-96386403), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(187893880), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(-109003806), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(154763074), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-167878153), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(123866455), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(-55449878), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(10901411), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(60443544), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-151195441), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(28705285), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(-44216319), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(52284288), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-46468489), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-27579775), /* Filter:7, Coefficient: 29 */ + CONVERT_COEFF(944226), /* Filter:7, Coefficient: 30 */ + CONVERT_COEFF(39504750), /* Filter:7, Coefficient: 31 */ + CONVERT_COEFF(-55450763), /* Filter:7, Coefficient: 32 */ + CONVERT_COEFF(146139326), /* Filter:6, Coefficient: 29 */ + CONVERT_COEFF(-125193602), /* Filter:6, Coefficient: 30 */ + CONVERT_COEFF(-8119725), /* Filter:6, Coefficient: 31 */ + CONVERT_COEFF(167052942), /* Filter:6, Coefficient: 32 */ + CONVERT_COEFF(-89102768), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(248694534), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(-331843959), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(152869295), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-262248494), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(259694722), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(54567300), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(-585088494), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(6010978), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(-266538025), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(769027860), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(-550799263), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(246363387), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-319948913), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(300954467), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(871436613), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(19590070), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(39171518), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-163170521), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(660899842), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(38104285), /* Filter:7, Coefficient: 33 */ + CONVERT_COEFF(1432784), /* Filter:7, Coefficient: 34 */ + CONVERT_COEFF(-27672195), /* Filter:7, Coefficient: 35 */ + CONVERT_COEFF(31921116), /* Filter:7, Coefficient: 36 */ + CONVERT_COEFF(-224528201), /* Filter:6, Coefficient: 33 */ + CONVERT_COEFF(117817853), /* Filter:6, Coefficient: 34 */ + CONVERT_COEFF(19821501), /* Filter:6, Coefficient: 35 */ + CONVERT_COEFF(-91903193), /* Filter:6, Coefficient: 36 */ + CONVERT_COEFF(215108034), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(-360908796), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(227085039), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(-46451389), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(566423159), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(-22644330), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-290592428), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(278076526), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(-547493323), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(767195769), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(-267778001), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(8458989), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(-871689336), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-300550035), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(319555239), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-246162036), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(660899842), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(-163170521), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(39171518), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(19590070), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-23433614), /* Filter:7, Coefficient: 37 */ + CONVERT_COEFF(11233560), /* Filter:7, Coefficient: 38 */ + CONVERT_COEFF(-223441), /* Filter:7, Coefficient: 39 */ + CONVERT_COEFF(-7253420), /* Filter:7, Coefficient: 40 */ + CONVERT_COEFF(101002885), /* Filter:6, Coefficient: 37 */ + CONVERT_COEFF(-76882874), /* Filter:6, Coefficient: 38 */ + CONVERT_COEFF(40567202), /* Filter:6, Coefficient: 39 */ + CONVERT_COEFF(-5841992), /* Filter:6, Coefficient: 40 */ + CONVERT_COEFF(-64257112), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(110837148), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(-110758392), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(82493642), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(-187504747), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(85554391), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(-397767), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-55476805), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(121745909), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(-166662052), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(154450910), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-109358640), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(151201064), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(-60582140), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(-10716025), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(55283389), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(-46468489), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(52284288), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-44216319), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(28705285), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(10580704), /* Filter:7, Coefficient: 41 */ + CONVERT_COEFF(-10304561), /* Filter:7, Coefficient: 42 */ + CONVERT_COEFF(7623908), /* Filter:7, Coefficient: 43 */ + CONVERT_COEFF(-3924457), /* Filter:7, Coefficient: 44 */ + CONVERT_COEFF(-19382377), /* Filter:6, Coefficient: 41 */ + CONVERT_COEFF(32139774), /* Filter:6, Coefficient: 42 */ + CONVERT_COEFF(-33292678), /* Filter:6, Coefficient: 43 */ + CONVERT_COEFF(26137219), /* Filter:6, Coefficient: 44 */ + CONVERT_COEFF(-42829268), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(4984408), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(22596297), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(-36478796), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(79727899), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(-77180699), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(56875188), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-29072432), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(52664560), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-1000453), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(-35199577), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(52081162), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-72507573), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(67216590), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(-47532278), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(22412200), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-11448189), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(-3194146), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(12660525), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(-16268114), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(408527), /* Filter:7, Coefficient: 45 */ + CONVERT_COEFF(2131760), /* Filter:7, Coefficient: 46 */ + CONVERT_COEFF(-3383382), /* Filter:7, Coefficient: 47 */ + CONVERT_COEFF(3446766), /* Filter:7, Coefficient: 48 */ + CONVERT_COEFF(-14928192), /* Filter:6, Coefficient: 45 */ + CONVERT_COEFF(3604808), /* Filter:6, Coefficient: 46 */ + CONVERT_COEFF(5060056), /* Filter:6, Coefficient: 47 */ + CONVERT_COEFF(-9794928), /* Filter:6, Coefficient: 48 */ + CONVERT_COEFF(37496027), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(-29308651), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(16712649), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(-4136967), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(2701198), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(16300851), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(-25550339), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(25786949), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-51410197), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(38626003), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-20524157), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(3201416), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(514571), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(-16347016), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(23344971), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(-22483689), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(14886324), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(-10331423), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(4676188), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(335976), /* Filter:1, Coefficient: 48 */ + + /* Filter #13, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-2686276), /* Filter:7, Coefficient: 49 */ + CONVERT_COEFF(1556907), /* Filter:7, Coefficient: 50 */ + CONVERT_COEFF(-458759), /* Filter:7, Coefficient: 51 */ + CONVERT_COEFF(-349838), /* Filter:7, Coefficient: 52 */ + CONVERT_COEFF(10698922), /* Filter:6, Coefficient: 49 */ + CONVERT_COEFF(-8800439), /* Filter:6, Coefficient: 50 */ + CONVERT_COEFF(5504157), /* Filter:6, Coefficient: 51 */ + CONVERT_COEFF(-2104680), /* Filter:6, Coefficient: 52 */ + CONVERT_COEFF(-5353271), /* Filter:5, Coefficient: 49 */ + CONVERT_COEFF(10426821), /* Filter:5, Coefficient: 50 */ + CONVERT_COEFF(-11299744), /* Filter:5, Coefficient: 51 */ + CONVERT_COEFF(9194215), /* Filter:5, Coefficient: 52 */ + CONVERT_COEFF(-19783847), /* Filter:4, Coefficient: 49 */ + CONVERT_COEFF(11038509), /* Filter:4, Coefficient: 50 */ + CONVERT_COEFF(-2643603), /* Filter:4, Coefficient: 51 */ + CONVERT_COEFF(-3406265), /* Filter:4, Coefficient: 52 */ + CONVERT_COEFF(9283532), /* Filter:3, Coefficient: 49 */ + CONVERT_COEFF(-15360523), /* Filter:3, Coefficient: 50 */ + CONVERT_COEFF(15614973), /* Filter:3, Coefficient: 51 */ + CONVERT_COEFF(-11968720), /* Filter:3, Coefficient: 52 */ + CONVERT_COEFF(16437903), /* Filter:2, Coefficient: 49 */ + CONVERT_COEFF(-8395909), /* Filter:2, Coefficient: 50 */ + CONVERT_COEFF(1064109), /* Filter:2, Coefficient: 51 */ + CONVERT_COEFF(3914091), /* Filter:2, Coefficient: 52 */ + CONVERT_COEFF(-3644365), /* Filter:1, Coefficient: 49 */ + CONVERT_COEFF(4952446), /* Filter:1, Coefficient: 50 */ + CONVERT_COEFF(-4582047), /* Filter:1, Coefficient: 51 */ + CONVERT_COEFF(3198988), /* Filter:1, Coefficient: 52 */ + + /* Filter #14, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(773994), /* Filter:7, Coefficient: 53 */ + CONVERT_COEFF(-852306), /* Filter:7, Coefficient: 54 */ + CONVERT_COEFF(699704), /* Filter:7, Coefficient: 55 */ + CONVERT_COEFF(-448245), /* Filter:7, Coefficient: 56 */ + CONVERT_COEFF(-520111), /* Filter:6, Coefficient: 53 */ + CONVERT_COEFF(2004349), /* Filter:6, Coefficient: 54 */ + CONVERT_COEFF(-2415951), /* Filter:6, Coefficient: 55 */ + CONVERT_COEFF(2082258), /* Filter:6, Coefficient: 56 */ + CONVERT_COEFF(-5690292), /* Filter:5, Coefficient: 53 */ + CONVERT_COEFF(2181982), /* Filter:5, Coefficient: 54 */ + CONVERT_COEFF(439695), /* Filter:5, Coefficient: 55 */ + CONVERT_COEFF(-1855684), /* Filter:5, Coefficient: 56 */ + CONVERT_COEFF(6401526), /* Filter:4, Coefficient: 53 */ + CONVERT_COEFF(-6690447), /* Filter:4, Coefficient: 54 */ + CONVERT_COEFF(5225196), /* Filter:4, Coefficient: 55 */ + CONVERT_COEFF(-3082950), /* Filter:4, Coefficient: 56 */ + CONVERT_COEFF(6735661), /* Filter:3, Coefficient: 53 */ + CONVERT_COEFF(-1855964), /* Filter:3, Coefficient: 54 */ + CONVERT_COEFF(-1521598), /* Filter:3, Coefficient: 55 */ + CONVERT_COEFF(3091258), /* Filter:3, Coefficient: 56 */ + CONVERT_COEFF(-6073880), /* Filter:2, Coefficient: 53 */ + CONVERT_COEFF(5876421), /* Filter:2, Coefficient: 54 */ + CONVERT_COEFF(-4268572), /* Filter:2, Coefficient: 55 */ + CONVERT_COEFF(2242351), /* Filter:2, Coefficient: 56 */ + CONVERT_COEFF(-1522163), /* Filter:1, Coefficient: 53 */ + CONVERT_COEFF(104733), /* Filter:1, Coefficient: 54 */ + CONVERT_COEFF(768744), /* Filter:1, Coefficient: 55 */ + CONVERT_COEFF(-1072749), /* Filter:1, Coefficient: 56 */ + + /* Filter #15, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(203843), /* Filter:7, Coefficient: 57 */ + CONVERT_COEFF(-26420), /* Filter:7, Coefficient: 58 */ + CONVERT_COEFF(-68761), /* Filter:7, Coefficient: 59 */ + CONVERT_COEFF(96718), /* Filter:7, Coefficient: 60 */ + CONVERT_COEFF(-1402019), /* Filter:6, Coefficient: 57 */ + CONVERT_COEFF(704429), /* Filter:6, Coefficient: 58 */ + CONVERT_COEFF(-181684), /* Filter:6, Coefficient: 59 */ + CONVERT_COEFF(-110580), /* Filter:6, Coefficient: 60 */ + CONVERT_COEFF(2199202), /* Filter:5, Coefficient: 57 */ + CONVERT_COEFF(-1845730), /* Filter:5, Coefficient: 58 */ + CONVERT_COEFF(1207778), /* Filter:5, Coefficient: 59 */ + CONVERT_COEFF(-596672), /* Filter:5, Coefficient: 60 */ + CONVERT_COEFF(1112474), /* Filter:4, Coefficient: 57 */ + CONVERT_COEFF(227477), /* Filter:4, Coefficient: 58 */ + CONVERT_COEFF(-852533), /* Filter:4, Coefficient: 59 */ + CONVERT_COEFF(926541), /* Filter:4, Coefficient: 60 */ + CONVERT_COEFF(-3174871), /* Filter:3, Coefficient: 57 */ + CONVERT_COEFF(2392005), /* Filter:3, Coefficient: 58 */ + CONVERT_COEFF(-1357177), /* Filter:3, Coefficient: 59 */ + CONVERT_COEFF(491739), /* Filter:3, Coefficient: 60 */ + CONVERT_COEFF(-527993), /* Filter:2, Coefficient: 57 */ + CONVERT_COEFF(-527169), /* Filter:2, Coefficient: 58 */ + CONVERT_COEFF(917240), /* Filter:2, Coefficient: 59 */ + CONVERT_COEFF(-842790), /* Filter:2, Coefficient: 60 */ + CONVERT_COEFF(956210), /* Filter:1, Coefficient: 57 */ + CONVERT_COEFF(-633133), /* Filter:1, Coefficient: 58 */ + CONVERT_COEFF(291450), /* Filter:1, Coefficient: 59 */ + CONVERT_COEFF(-43685), /* Filter:1, Coefficient: 60 */ + + /* Filter #16, conversion from 48000 Hz to 44100 Hz */ + + CONVERT_COEFF(-84837), /* Filter:7, Coefficient: 61 */ + CONVERT_COEFF(58623), /* Filter:7, Coefficient: 62 */ + CONVERT_COEFF(-34394), /* Filter:7, Coefficient: 63 */ + CONVERT_COEFF(-3711660), /* Filter:7, Coefficient: 64 */ + CONVERT_COEFF(210495), /* Filter:6, Coefficient: 61 */ + CONVERT_COEFF(-195186), /* Filter:6, Coefficient: 62 */ + CONVERT_COEFF(137148), /* Filter:6, Coefficient: 63 */ + CONVERT_COEFF(10382357), /* Filter:6, Coefficient: 64 */ + CONVERT_COEFF(170808), /* Filter:5, Coefficient: 61 */ + CONVERT_COEFF(45623), /* Filter:5, Coefficient: 62 */ + CONVERT_COEFF(-107490), /* Filter:5, Coefficient: 63 */ + CONVERT_COEFF(-10759470), /* Filter:5, Coefficient: 64 */ + CONVERT_COEFF(-705509), /* Filter:4, Coefficient: 61 */ + CONVERT_COEFF(414544), /* Filter:4, Coefficient: 62 */ + CONVERT_COEFF(-186990), /* Filter:4, Coefficient: 63 */ + CONVERT_COEFF(5200106), /* Filter:4, Coefficient: 64 */ + CONVERT_COEFF(28928), /* Filter:3, Coefficient: 61 */ + CONVERT_COEFF(-225201), /* Filter:3, Coefficient: 62 */ + CONVERT_COEFF(216708), /* Filter:3, Coefficient: 63 */ + CONVERT_COEFF(-1228780), /* Filter:3, Coefficient: 64 */ + CONVERT_COEFF(560092), /* Filter:2, Coefficient: 61 */ + CONVERT_COEFF(-271537), /* Filter:2, Coefficient: 62 */ + CONVERT_COEFF(79933), /* Filter:2, Coefficient: 63 */ + CONVERT_COEFF(84418), /* Filter:2, Coefficient: 64 */ + CONVERT_COEFF(-78725), /* Filter:1, Coefficient: 61 */ + CONVERT_COEFF(101248), /* Filter:1, Coefficient: 62 */ + CONVERT_COEFF(-71885), /* Filter:1, Coefficient: 63 */ + CONVERT_COEFF(33030), /* Filter:1, Coefficient: 64 */ +}; diff --git a/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_48000Hz.h b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_48000Hz.h new file mode 100644 index 000000000000..af6e1137500f --- /dev/null +++ b/src/audio/asrc/coef/asrc_farrow_coeff_4x_48000Hz_to_48000Hz.h @@ -0,0 +1,382 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2012-2025 Intel Corporation. + */ + +/* Conversion from 48000 Hz to 48000 Hz */ +/* NUM_FILTERS=7, FILTER_LENGTH=48, alpha=7.150000, gamma=0.458000 */ + +__cold_rodata static const int32_t coeff48000to48000[] = { + + /* Filter #1, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(201584), /* Filter:7, Coefficient: 1 */ + CONVERT_COEFF(-337772), /* Filter:7, Coefficient: 2 */ + CONVERT_COEFF(532323), /* Filter:7, Coefficient: 3 */ + CONVERT_COEFF(-781809), /* Filter:7, Coefficient: 4 */ + CONVERT_COEFF(-509717), /* Filter:6, Coefficient: 1 */ + CONVERT_COEFF(901735), /* Filter:6, Coefficient: 2 */ + CONVERT_COEFF(-1563722), /* Filter:6, Coefficient: 3 */ + CONVERT_COEFF(2576238), /* Filter:6, Coefficient: 4 */ + CONVERT_COEFF(-76220), /* Filter:5, Coefficient: 1 */ + CONVERT_COEFF(108575), /* Filter:5, Coefficient: 2 */ + CONVERT_COEFF(38232), /* Filter:5, Coefficient: 3 */ + CONVERT_COEFF(-557092), /* Filter:5, Coefficient: 4 */ + CONVERT_COEFF(427848), /* Filter:4, Coefficient: 1 */ + CONVERT_COEFF(-890617), /* Filter:4, Coefficient: 2 */ + CONVERT_COEFF(1688361), /* Filter:4, Coefficient: 3 */ + CONVERT_COEFF(-2889171), /* Filter:4, Coefficient: 4 */ + CONVERT_COEFF(450982), /* Filter:3, Coefficient: 1 */ + CONVERT_COEFF(-810046), /* Filter:3, Coefficient: 2 */ + CONVERT_COEFF(1143995), /* Filter:3, Coefficient: 3 */ + CONVERT_COEFF(-1251295), /* Filter:3, Coefficient: 4 */ + CONVERT_COEFF(-134205), /* Filter:2, Coefficient: 1 */ + CONVERT_COEFF(408052), /* Filter:2, Coefficient: 2 */ + CONVERT_COEFF(-969157), /* Filter:2, Coefficient: 3 */ + CONVERT_COEFF(1915703), /* Filter:2, Coefficient: 4 */ + CONVERT_COEFF(-119772), /* Filter:1, Coefficient: 1 */ + CONVERT_COEFF(240527), /* Filter:1, Coefficient: 2 */ + CONVERT_COEFF(-379589), /* Filter:1, Coefficient: 3 */ + CONVERT_COEFF(490498), /* Filter:1, Coefficient: 4 */ + + /* Filter #2, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(1063090), /* Filter:7, Coefficient: 5 */ + CONVERT_COEFF(-1325755), /* Filter:7, Coefficient: 6 */ + CONVERT_COEFF(1486665), /* Filter:7, Coefficient: 7 */ + CONVERT_COEFF(-1428619), /* Filter:7, Coefficient: 8 */ + CONVERT_COEFF(-3983820), /* Filter:6, Coefficient: 5 */ + CONVERT_COEFF(5758133), /* Filter:6, Coefficient: 6 */ + CONVERT_COEFF(-7757839), /* Filter:6, Coefficient: 7 */ + CONVERT_COEFF(9692081), /* Filter:6, Coefficient: 8 */ + CONVERT_COEFF(1699253), /* Filter:5, Coefficient: 5 */ + CONVERT_COEFF(-3746237), /* Filter:5, Coefficient: 6 */ + CONVERT_COEFF(6958850), /* Filter:5, Coefficient: 7 */ + CONVERT_COEFF(-11504364), /* Filter:5, Coefficient: 8 */ + CONVERT_COEFF(4484829), /* Filter:4, Coefficient: 5 */ + CONVERT_COEFF(-6340864), /* Filter:4, Coefficient: 6 */ + CONVERT_COEFF(8150817), /* Filter:4, Coefficient: 7 */ + CONVERT_COEFF(-9406444), /* Filter:4, Coefficient: 8 */ + CONVERT_COEFF(828449), /* Filter:3, Coefficient: 5 */ + CONVERT_COEFF(513188), /* Filter:3, Coefficient: 6 */ + CONVERT_COEFF(-3201273), /* Filter:3, Coefficient: 7 */ + CONVERT_COEFF(7625293), /* Filter:3, Coefficient: 8 */ + CONVERT_COEFF(-3299444), /* Filter:2, Coefficient: 5 */ + CONVERT_COEFF(5081025), /* Filter:2, Coefficient: 6 */ + CONVERT_COEFF(-7084841), /* Filter:2, Coefficient: 7 */ + CONVERT_COEFF(8963125), /* Filter:2, Coefficient: 8 */ + CONVERT_COEFF(-496983), /* Filter:1, Coefficient: 5 */ + CONVERT_COEFF(295408), /* Filter:1, Coefficient: 6 */ + CONVERT_COEFF(234925), /* Filter:1, Coefficient: 7 */ + CONVERT_COEFF(-1212831), /* Filter:1, Coefficient: 8 */ + + /* Filter #3, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(1005001), /* Filter:7, Coefficient: 9 */ + CONVERT_COEFF(-51772), /* Filter:7, Coefficient: 10 */ + CONVERT_COEFF(-1592653), /* Filter:7, Coefficient: 11 */ + CONVERT_COEFF(4060025), /* Filter:7, Coefficient: 12 */ + CONVERT_COEFF(-11095974), /* Filter:6, Coefficient: 9 */ + CONVERT_COEFF(11326651), /* Filter:6, Coefficient: 10 */ + CONVERT_COEFF(-9587117), /* Filter:6, Coefficient: 11 */ + CONVERT_COEFF(4982353), /* Filter:6, Coefficient: 12 */ + CONVERT_COEFF(17367482), /* Filter:5, Coefficient: 9 */ + CONVERT_COEFF(-24255226), /* Filter:5, Coefficient: 10 */ + CONVERT_COEFF(31509193), /* Filter:5, Coefficient: 11 */ + CONVERT_COEFF(-38039723), /* Filter:5, Coefficient: 12 */ + CONVERT_COEFF(9395942), /* Filter:4, Coefficient: 9 */ + CONVERT_COEFF(-7240294), /* Filter:4, Coefficient: 10 */ + CONVERT_COEFF(1973428), /* Filter:4, Coefficient: 11 */ + CONVERT_COEFF(7334367), /* Filter:4, Coefficient: 12 */ + CONVERT_COEFF(-14032432), /* Filter:3, Coefficient: 9 */ + CONVERT_COEFF(22406684), /* Filter:3, Coefficient: 10 */ + CONVERT_COEFF(-32346679), /* Filter:3, Coefficient: 11 */ + CONVERT_COEFF(42960394), /* Filter:3, Coefficient: 12 */ + CONVERT_COEFF(-10179847), /* Filter:2, Coefficient: 9 */ + CONVERT_COEFF(10023910), /* Filter:2, Coefficient: 10 */ + CONVERT_COEFF(-7657809), /* Filter:2, Coefficient: 11 */ + CONVERT_COEFF(2202705), /* Filter:2, Coefficient: 12 */ + CONVERT_COEFF(2728545), /* Filter:1, Coefficient: 9 */ + CONVERT_COEFF(-4811819), /* Filter:1, Coefficient: 10 */ + CONVERT_COEFF(7398958), /* Filter:1, Coefficient: 11 */ + CONVERT_COEFF(-10303827), /* Filter:1, Coefficient: 12 */ + + /* Filter #4, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(-7418549), /* Filter:7, Coefficient: 13 */ + CONVERT_COEFF(11634082), /* Filter:7, Coefficient: 14 */ + CONVERT_COEFF(-16526119), /* Filter:7, Coefficient: 15 */ + CONVERT_COEFF(21713991), /* Filter:7, Coefficient: 16 */ + CONVERT_COEFF(3391495), /* Filter:6, Coefficient: 13 */ + CONVERT_COEFF(-16327279), /* Filter:6, Coefficient: 14 */ + CONVERT_COEFF(34359416), /* Filter:6, Coefficient: 15 */ + CONVERT_COEFF(-57585131), /* Filter:6, Coefficient: 16 */ + CONVERT_COEFF(42294622), /* Filter:5, Coefficient: 13 */ + CONVERT_COEFF(-42269640), /* Filter:5, Coefficient: 14 */ + CONVERT_COEFF(35559100), /* Filter:5, Coefficient: 15 */ + CONVERT_COEFF(-19433648), /* Filter:5, Coefficient: 16 */ + CONVERT_COEFF(-21417196), /* Filter:4, Coefficient: 13 */ + CONVERT_COEFF(40631722), /* Filter:4, Coefficient: 14 */ + CONVERT_COEFF(-64768213), /* Filter:4, Coefficient: 15 */ + CONVERT_COEFF(92865281), /* Filter:4, Coefficient: 16 */ + CONVERT_COEFF(-52793804), /* Filter:3, Coefficient: 13 */ + CONVERT_COEFF(59804363), /* Filter:3, Coefficient: 14 */ + CONVERT_COEFF(-61377672), /* Filter:3, Coefficient: 15 */ + CONVERT_COEFF(54364939), /* Filter:3, Coefficient: 16 */ + CONVERT_COEFF(7145457), /* Filter:2, Coefficient: 13 */ + CONVERT_COEFF(-20980397), /* Filter:2, Coefficient: 14 */ + CONVERT_COEFF(39546773), /* Filter:2, Coefficient: 15 */ + CONVERT_COEFF(-62615800), /* Filter:2, Coefficient: 16 */ + CONVERT_COEFF(13197765), /* Filter:1, Coefficient: 13 */ + CONVERT_COEFF(-15601953), /* Filter:1, Coefficient: 14 */ + CONVERT_COEFF(16892782), /* Filter:1, Coefficient: 15 */ + CONVERT_COEFF(-16315753), /* Filter:1, Coefficient: 16 */ + + /* Filter #5, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(-26537520), /* Filter:7, Coefficient: 17 */ + CONVERT_COEFF(29908749), /* Filter:7, Coefficient: 18 */ + CONVERT_COEFF(-29980490), /* Filter:7, Coefficient: 19 */ + CONVERT_COEFF(23337872), /* Filter:7, Coefficient: 20 */ + CONVERT_COEFF(85425357), /* Filter:6, Coefficient: 17 */ + CONVERT_COEFF(-116220246), /* Filter:6, Coefficient: 18 */ + CONVERT_COEFF(146323990), /* Filter:6, Coefficient: 19 */ + CONVERT_COEFF(-167617073), /* Filter:6, Coefficient: 20 */ + CONVERT_COEFF(-9079150), /* Filter:5, Coefficient: 17 */ + CONVERT_COEFF(53136657), /* Filter:5, Coefficient: 18 */ + CONVERT_COEFF(-116017890), /* Filter:5, Coefficient: 19 */ + CONVERT_COEFF(200714461), /* Filter:5, Coefficient: 20 */ + CONVERT_COEFF(-123020997), /* Filter:4, Coefficient: 17 */ + CONVERT_COEFF(152146065), /* Filter:4, Coefficient: 18 */ + CONVERT_COEFF(-175480494), /* Filter:4, Coefficient: 19 */ + CONVERT_COEFF(185308827), /* Filter:4, Coefficient: 20 */ + CONVERT_COEFF(-35083980), /* Filter:3, Coefficient: 17 */ + CONVERT_COEFF(-839184), /* Filter:3, Coefficient: 18 */ + CONVERT_COEFF(59061656), /* Filter:3, Coefficient: 19 */ + CONVERT_COEFF(-148239694), /* Filter:3, Coefficient: 20 */ + CONVERT_COEFF(89388345), /* Filter:2, Coefficient: 17 */ + CONVERT_COEFF(-118423648), /* Filter:2, Coefficient: 18 */ + CONVERT_COEFF(147552056), /* Filter:2, Coefficient: 19 */ + CONVERT_COEFF(-173608580), /* Filter:2, Coefficient: 20 */ + CONVERT_COEFF(12995329), /* Filter:1, Coefficient: 17 */ + CONVERT_COEFF(-5913276), /* Filter:1, Coefficient: 18 */ + CONVERT_COEFF(-6205575), /* Filter:1, Coefficient: 19 */ + CONVERT_COEFF(25256070), /* Filter:1, Coefficient: 20 */ + + /* Filter #6, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(-3217307), /* Filter:7, Coefficient: 21 */ + CONVERT_COEFF(-37038723), /* Filter:7, Coefficient: 22 */ + CONVERT_COEFF(86353009), /* Filter:7, Coefficient: 23 */ + CONVERT_COEFF(-97721939), /* Filter:7, Coefficient: 24 */ + CONVERT_COEFF(160008482), /* Filter:6, Coefficient: 21 */ + CONVERT_COEFF(-78261417), /* Filter:6, Coefficient: 22 */ + CONVERT_COEFF(-112362175), /* Filter:6, Coefficient: 23 */ + CONVERT_COEFF(293242487), /* Filter:6, Coefficient: 24 */ + CONVERT_COEFF(-307335294), /* Filter:5, Coefficient: 21 */ + CONVERT_COEFF(424736994), /* Filter:5, Coefficient: 22 */ + CONVERT_COEFF(-438040128), /* Filter:5, Coefficient: 23 */ + CONVERT_COEFF(198203604), /* Filter:5, Coefficient: 24 */ + CONVERT_COEFF(-166691617), /* Filter:4, Coefficient: 21 */ + CONVERT_COEFF(75780494), /* Filter:4, Coefficient: 22 */ + CONVERT_COEFF(306273762), /* Filter:4, Coefficient: 23 */ + CONVERT_COEFF(-885042156), /* Filter:4, Coefficient: 24 */ + CONVERT_COEFF(284938963), /* Filter:3, Coefficient: 21 */ + CONVERT_COEFF(-508669005), /* Filter:3, Coefficient: 22 */ + CONVERT_COEFF(934119707), /* Filter:3, Coefficient: 23 */ + CONVERT_COEFF(-607381991), /* Filter:3, Coefficient: 24 */ + CONVERT_COEFF(191344927), /* Filter:2, Coefficient: 21 */ + CONVERT_COEFF(-188272598), /* Filter:2, Coefficient: 22 */ + CONVERT_COEFF(107814255), /* Filter:2, Coefficient: 23 */ + CONVERT_COEFF(1098624520), /* Filter:2, Coefficient: 24 */ + CONVERT_COEFF(-54854236), /* Filter:1, Coefficient: 21 */ + CONVERT_COEFF(104205542), /* Filter:1, Coefficient: 22 */ + CONVERT_COEFF(-207541862), /* Filter:1, Coefficient: 23 */ + CONVERT_COEFF(676692041), /* Filter:1, Coefficient: 24 */ + + /* Filter #7, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(85978275), /* Filter:7, Coefficient: 25 */ + CONVERT_COEFF(-36956143), /* Filter:7, Coefficient: 26 */ + CONVERT_COEFF(-3244216), /* Filter:7, Coefficient: 27 */ + CONVERT_COEFF(23345067), /* Filter:7, Coefficient: 28 */ + CONVERT_COEFF(-404403423), /* Filter:6, Coefficient: 25 */ + CONVERT_COEFF(300207629), /* Filter:6, Coefficient: 26 */ + CONVERT_COEFF(-140639902), /* Filter:6, Coefficient: 27 */ + CONVERT_COEFF(27599531), /* Filter:6, Coefficient: 28 */ + CONVERT_COEFF(293327128), /* Filter:5, Coefficient: 25 */ + CONVERT_COEFF(-521588890), /* Filter:5, Coefficient: 26 */ + CONVERT_COEFF(444290293), /* Filter:5, Coefficient: 27 */ + CONVERT_COEFF(-287297861), /* Filter:5, Coefficient: 28 */ + CONVERT_COEFF(844058593), /* Filter:4, Coefficient: 25 */ + CONVERT_COEFF(-251982826), /* Filter:4, Coefficient: 26 */ + CONVERT_COEFF(-139427582), /* Filter:4, Coefficient: 27 */ + CONVERT_COEFF(221132516), /* Filter:4, Coefficient: 28 */ + CONVERT_COEFF(-603949609), /* Filter:3, Coefficient: 25 */ + CONVERT_COEFF(929187271), /* Filter:3, Coefficient: 26 */ + CONVERT_COEFF(-507498526), /* Filter:3, Coefficient: 27 */ + CONVERT_COEFF(285983393), /* Filter:3, Coefficient: 28 */ + CONVERT_COEFF(-1099221720), /* Filter:2, Coefficient: 25 */ + CONVERT_COEFF(-107131260), /* Filter:2, Coefficient: 26 */ + CONVERT_COEFF(187466276), /* Filter:2, Coefficient: 27 */ + CONVERT_COEFF(-190655157), /* Filter:2, Coefficient: 28 */ + CONVERT_COEFF(676692041), /* Filter:1, Coefficient: 25 */ + CONVERT_COEFF(-207541862), /* Filter:1, Coefficient: 26 */ + CONVERT_COEFF(104205542), /* Filter:1, Coefficient: 27 */ + CONVERT_COEFF(-54854236), /* Filter:1, Coefficient: 28 */ + + /* Filter #8, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(-29977934), /* Filter:7, Coefficient: 29 */ + CONVERT_COEFF(29900921), /* Filter:7, Coefficient: 30 */ + CONVERT_COEFF(-26527103), /* Filter:7, Coefficient: 31 */ + CONVERT_COEFF(21702815), /* Filter:7, Coefficient: 32 */ + CONVERT_COEFF(33517333), /* Filter:6, Coefficient: 29 */ + CONVERT_COEFF(-63177333), /* Filter:6, Coefficient: 30 */ + CONVERT_COEFF(73741881), /* Filter:6, Coefficient: 31 */ + CONVERT_COEFF(-72644258), /* Filter:6, Coefficient: 32 */ + CONVERT_COEFF(165959941), /* Filter:5, Coefficient: 29 */ + CONVERT_COEFF(-79430320), /* Filter:5, Coefficient: 30 */ + CONVERT_COEFF(20091574), /* Filter:5, Coefficient: 31 */ + CONVERT_COEFF(18247620), /* Filter:5, Coefficient: 32 */ + CONVERT_COEFF(-224053962), /* Filter:4, Coefficient: 29 */ + CONVERT_COEFF(199362700), /* Filter:4, Coefficient: 30 */ + CONVERT_COEFF(-164221867), /* Filter:4, Coefficient: 31 */ + CONVERT_COEFF(126509506), /* Filter:4, Coefficient: 32 */ + CONVERT_COEFF(-150024800), /* Filter:3, Coefficient: 29 */ + CONVERT_COEFF(60887712), /* Filter:3, Coefficient: 30 */ + CONVERT_COEFF(-2449324), /* Filter:3, Coefficient: 31 */ + CONVERT_COEFF(-33779561), /* Filter:3, Coefficient: 32 */ + CONVERT_COEFF(173118469), /* Filter:2, Coefficient: 29 */ + CONVERT_COEFF(-147250722), /* Filter:2, Coefficient: 30 */ + CONVERT_COEFF(118271995), /* Filter:2, Coefficient: 31 */ + CONVERT_COEFF(-89345383), /* Filter:2, Coefficient: 32 */ + CONVERT_COEFF(25256070), /* Filter:1, Coefficient: 29 */ + CONVERT_COEFF(-6205575), /* Filter:1, Coefficient: 30 */ + CONVERT_COEFF(-5913276), /* Filter:1, Coefficient: 31 */ + CONVERT_COEFF(12995329), /* Filter:1, Coefficient: 32 */ + + /* Filter #9, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(-16515450), /* Filter:7, Coefficient: 33 */ + CONVERT_COEFF(11624746), /* Filter:7, Coefficient: 34 */ + CONVERT_COEFF(-7410994), /* Filter:7, Coefficient: 35 */ + CONVERT_COEFF(4054390), /* Filter:7, Coefficient: 36 */ + CONVERT_COEFF(64749828), /* Filter:6, Coefficient: 33 */ + CONVERT_COEFF(-53438753), /* Filter:6, Coefficient: 34 */ + CONVERT_COEFF(41090862), /* Filter:6, Coefficient: 35 */ + CONVERT_COEFF(-29322557), /* Filter:6, Coefficient: 36 */ + CONVERT_COEFF(-40444649), /* Filter:5, Coefficient: 33 */ + CONVERT_COEFF(50530543), /* Filter:5, Coefficient: 34 */ + CONVERT_COEFF(-51969177), /* Filter:5, Coefficient: 35 */ + CONVERT_COEFF(47732391), /* Filter:5, Coefficient: 36 */ + CONVERT_COEFF(-90610096), /* Filter:4, Coefficient: 33 */ + CONVERT_COEFF(59102310), /* Filter:4, Coefficient: 34 */ + CONVERT_COEFF(-33359574), /* Filter:4, Coefficient: 35 */ + CONVERT_COEFF(13843008), /* Filter:4, Coefficient: 36 */ + CONVERT_COEFF(53381614), /* Filter:3, Coefficient: 33 */ + CONVERT_COEFF(-60692487), /* Filter:3, Coefficient: 34 */ + CONVERT_COEFF(59374033), /* Filter:3, Coefficient: 35 */ + CONVERT_COEFF(-52565904), /* Filter:3, Coefficient: 36 */ + CONVERT_COEFF(62645405), /* Filter:2, Coefficient: 33 */ + CONVERT_COEFF(-39619353), /* Filter:2, Coefficient: 34 */ + CONVERT_COEFF(21073095), /* Filter:2, Coefficient: 35 */ + CONVERT_COEFF(-7241772), /* Filter:2, Coefficient: 36 */ + CONVERT_COEFF(-16315753), /* Filter:1, Coefficient: 33 */ + CONVERT_COEFF(16892782), /* Filter:1, Coefficient: 34 */ + CONVERT_COEFF(-15601953), /* Filter:1, Coefficient: 35 */ + CONVERT_COEFF(13197765), /* Filter:1, Coefficient: 36 */ + + /* Filter #10, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(-1588840), /* Filter:7, Coefficient: 37 */ + CONVERT_COEFF(-54023), /* Filter:7, Coefficient: 38 */ + CONVERT_COEFF(1006037), /* Filter:7, Coefficient: 39 */ + CONVERT_COEFF(-1428806), /* Filter:7, Coefficient: 40 */ + CONVERT_COEFF(19130847), /* Filter:6, Coefficient: 37 */ + CONVERT_COEFF(-11009977), /* Filter:6, Coefficient: 38 */ + CONVERT_COEFF(5064348), /* Filter:6, Coefficient: 39 */ + CONVERT_COEFF(-1121566), /* Filter:6, Coefficient: 40 */ + CONVERT_COEFF(-40290924), /* Filter:5, Coefficient: 37 */ + CONVERT_COEFF(31587996), /* Filter:5, Coefficient: 38 */ + CONVERT_COEFF(-23032529), /* Filter:5, Coefficient: 39 */ + CONVERT_COEFF(15527527), /* Filter:5, Coefficient: 40 */ + CONVERT_COEFF(-316683), /* Filter:4, Coefficient: 37 */ + CONVERT_COEFF(-7949710), /* Filter:4, Coefficient: 38 */ + CONVERT_COEFF(11982264), /* Filter:4, Coefficient: 39 */ + CONVERT_COEFF(-12919307), /* Filter:4, Coefficient: 40 */ + CONVERT_COEFF(42881174), /* Filter:3, Coefficient: 37 */ + CONVERT_COEFF(-32366569), /* Filter:3, Coefficient: 38 */ + CONVERT_COEFF(22483813), /* Filter:3, Coefficient: 39 */ + CONVERT_COEFF(-14134393), /* Filter:3, Coefficient: 40 */ + CONVERT_COEFF(-2113613), /* Filter:2, Coefficient: 37 */ + CONVERT_COEFF(7582042), /* Filter:2, Coefficient: 38 */ + CONVERT_COEFF(-9963872), /* Filter:2, Coefficient: 39 */ + CONVERT_COEFF(10135303), /* Filter:2, Coefficient: 40 */ + CONVERT_COEFF(-10303827), /* Filter:1, Coefficient: 37 */ + CONVERT_COEFF(7398958), /* Filter:1, Coefficient: 38 */ + CONVERT_COEFF(-4811819), /* Filter:1, Coefficient: 39 */ + CONVERT_COEFF(2728545), /* Filter:1, Coefficient: 40 */ + + /* Filter #11, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(1486340), /* Filter:7, Coefficient: 41 */ + CONVERT_COEFF(-1325194), /* Filter:7, Coefficient: 42 */ + CONVERT_COEFF(1062490), /* Filter:7, Coefficient: 43 */ + CONVERT_COEFF(-781289), /* Filter:7, Coefficient: 44 */ + CONVERT_COEFF(-1159486), /* Filter:6, Coefficient: 41 */ + CONVERT_COEFF(2193279), /* Filter:6, Coefficient: 42 */ + CONVERT_COEFF(-2391815), /* Filter:6, Coefficient: 43 */ + CONVERT_COEFF(2112274), /* Filter:6, Coefficient: 44 */ + CONVERT_COEFF(-9534209), /* Filter:5, Coefficient: 41 */ + CONVERT_COEFF(5163088), /* Filter:5, Coefficient: 42 */ + CONVERT_COEFF(-2278340), /* Filter:5, Coefficient: 43 */ + CONVERT_COEFF(600969), /* Filter:5, Coefficient: 44 */ + CONVERT_COEFF(11857857), /* Filter:4, Coefficient: 41 */ + CONVERT_COEFF(-9741790), /* Filter:4, Coefficient: 42 */ + CONVERT_COEFF(7296922), /* Filter:4, Coefficient: 43 */ + CONVERT_COEFF(-5011117), /* Filter:4, Coefficient: 44 */ + CONVERT_COEFF(7729413), /* Filter:3, Coefficient: 41 */ + CONVERT_COEFF(-3293739), /* Filter:3, Coefficient: 42 */ + CONVERT_COEFF(587429), /* Filter:3, Coefficient: 43 */ + CONVERT_COEFF(773723), /* Filter:3, Coefficient: 44 */ + CONVERT_COEFF(-8932187), /* Filter:2, Coefficient: 41 */ + CONVERT_COEFF(7064806), /* Filter:2, Coefficient: 42 */ + CONVERT_COEFF(-5069022), /* Filter:2, Coefficient: 43 */ + CONVERT_COEFF(3292866), /* Filter:2, Coefficient: 44 */ + CONVERT_COEFF(-1212831), /* Filter:1, Coefficient: 41 */ + CONVERT_COEFF(234925), /* Filter:1, Coefficient: 42 */ + CONVERT_COEFF(295408), /* Filter:1, Coefficient: 43 */ + CONVERT_COEFF(-496983), /* Filter:1, Coefficient: 44 */ + + /* Filter #12, conversion from 48000 Hz to 48000 Hz */ + + CONVERT_COEFF(531937), /* Filter:7, Coefficient: 45 */ + CONVERT_COEFF(-337523), /* Filter:7, Coefficient: 46 */ + CONVERT_COEFF(201449), /* Filter:7, Coefficient: 47 */ + CONVERT_COEFF(-12084314), /* Filter:7, Coefficient: 48 */ + CONVERT_COEFF(-1628548), /* Filter:6, Coefficient: 45 */ + CONVERT_COEFF(1123843), /* Filter:6, Coefficient: 46 */ + CONVERT_COEFF(-699211), /* Filter:6, Coefficient: 47 */ + CONVERT_COEFF(35988267), /* Filter:6, Coefficient: 48 */ + CONVERT_COEFF(201557), /* Filter:5, Coefficient: 45 */ + CONVERT_COEFF(-447451), /* Filter:5, Coefficient: 46 */ + CONVERT_COEFF(397902), /* Filter:5, Coefficient: 47 */ + CONVERT_COEFF(-39316590), /* Filter:5, Coefficient: 48 */ + CONVERT_COEFF(3151503), /* Filter:4, Coefficient: 45 */ + CONVERT_COEFF(-1807037), /* Filter:4, Coefficient: 46 */ + CONVERT_COEFF(943390), /* Filter:4, Coefficient: 47 */ + CONVERT_COEFF(18887301), /* Filter:4, Coefficient: 48 */ + CONVERT_COEFF(-1214047), /* Filter:3, Coefficient: 45 */ + CONVERT_COEFF(1120557), /* Filter:3, Coefficient: 46 */ + CONVERT_COEFF(-796401), /* Filter:3, Coefficient: 47 */ + CONVERT_COEFF(-3816331), /* Filter:3, Coefficient: 48 */ + CONVERT_COEFF(-1912448), /* Filter:2, Coefficient: 45 */ + CONVERT_COEFF(967701), /* Filter:2, Coefficient: 46 */ + CONVERT_COEFF(-407415), /* Filter:2, Coefficient: 47 */ + CONVERT_COEFF(461439), /* Filter:2, Coefficient: 48 */ + CONVERT_COEFF(490498), /* Filter:1, Coefficient: 45 */ + CONVERT_COEFF(-379589), /* Filter:1, Coefficient: 46 */ + CONVERT_COEFF(240527), /* Filter:1, Coefficient: 47 */ + CONVERT_COEFF(-119772), /* Filter:1, Coefficient: 48 */ +}; diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_24000Hz_to_08000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_24000Hz_to_08000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_24000Hz_to_08000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_24000Hz_to_08000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_24000Hz_to_16000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_24000Hz_to_16000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_24000Hz_to_16000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_24000Hz_to_16000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_44100Hz_to_48000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_44100Hz_to_48000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_44100Hz_to_48000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_44100Hz_to_48000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_08000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_08000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_08000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_08000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_11025Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_11025Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_11025Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_11025Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_12000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_12000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_12000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_12000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_16000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_16000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_16000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_16000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_22050Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_22050Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_22050Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_22050Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_24000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_24000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_24000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_24000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_32000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_32000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_32000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_32000Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_44100Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_44100Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_44100Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_44100Hz.h diff --git a/src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_48000Hz.h b/src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_48000Hz.h similarity index 100% rename from src/include/sof/audio/coefficients/asrc/asrc_farrow_param_48000Hz_to_48000Hz.h rename to src/audio/asrc/coef/asrc_farrow_param_48000Hz_to_48000Hz.h diff --git a/src/audio/asrc/llext/CMakeLists.txt b/src/audio/asrc/llext/CMakeLists.txt new file mode 100644 index 000000000000..27d5889d166a --- /dev/null +++ b/src/audio/asrc/llext/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("asrc" + SOURCES ../asrc.c + ../asrc_farrow_hifi3.c + ../asrc_farrow_hifi5.c + ../asrc_farrow.c + ../asrc_farrow_generic.c + ../asrc_ipc4.c + LIB openmodules +) diff --git a/src/audio/asrc/llext/llext.toml.h b/src/audio/asrc/llext/llext.toml.h new file mode 100644 index 000000000000..680a68ece6d8 --- /dev/null +++ b/src/audio/asrc/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../asrc.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/audio_stream.c b/src/audio/audio_stream.c new file mode 100644 index 000000000000..aa16617f066c --- /dev/null +++ b/src/audio/audio_stream.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// + +#include <rtos/symbol.h> + +#include <sof/audio/audio_stream.h> +#include <sof/audio/audio_buffer.h> +#include <sof/audio/buffer.h> + +static uint32_t audio_stream_frame_align_get(const uint32_t byte_align, + const uint32_t frame_align_req, + uint32_t frame_size) +{ + /* Figure out how many frames are needed to meet the byte_align alignment requirements */ + uint32_t frame_num = byte_align / gcd(byte_align, frame_size); + + /** return the lcm of frame_num and frame_align_req*/ + return frame_align_req * frame_num / gcd(frame_num, frame_align_req); +} + +void audio_stream_recalc_align(struct audio_stream *stream) +{ + const uint32_t byte_align = stream->byte_align_req; + const uint32_t frame_align_req = stream->frame_align_req; + uint32_t process_size; + uint32_t frame_size = audio_stream_frame_bytes(stream); + + stream->runtime_stream_params.align_frame_cnt = + audio_stream_frame_align_get(byte_align, frame_align_req, frame_size); + process_size = stream->runtime_stream_params.align_frame_cnt * frame_size; + stream->runtime_stream_params.align_shift_idx = + (is_power_of_2(process_size) ? 31 : 32) - clz(process_size); +} +EXPORT_SYMBOL(audio_stream_recalc_align); + +void audio_stream_set_align(const uint32_t byte_align, + const uint32_t frame_align_req, + struct audio_stream *stream) +{ + stream->byte_align_req = byte_align; + stream->frame_align_req = frame_align_req; + audio_stream_recalc_align(stream); +} +EXPORT_SYMBOL(audio_stream_set_align); + +void audio_stream_init(struct audio_stream *audio_stream, void *buff_addr, uint32_t size) +{ + audio_stream->size = size; + audio_stream->addr = buff_addr; + audio_stream->end_addr = (char *)audio_stream->addr + size; + + audio_stream_set_align(SOF_FRAME_BYTE_ALIGN, SOF_FRAME_COUNT_ALIGN, audio_stream); + audio_stream_reset(audio_stream); +} diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c new file mode 100644 index 000000000000..b86db469765a --- /dev/null +++ b/src/audio/base_fw.c @@ -0,0 +1,847 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. +// + +#include <sof/audio/component.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/ut.h> +#include <sof/tlv.h> +#include <ipc4/base_fw.h> +#include <ipc4/base_fw_vendor.h> +#include <ipc4/pipeline.h> +#include <ipc4/logging.h> +#include <ipc4/notification.h> +#include <ipc/topology.h> +#include <ipc/compress_params.h> +#include <sof_versions.h> +#include <sof/lib/cpu-clk-manager.h> +#include <sof/lib/cpu.h> +#include <sof/platform.h> +#include <sof/lib_manager.h> +#include <rtos/clk.h> +#include <rtos/init.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/debug/telemetry/performance_monitor.h> +#include <sof/debug/telemetry/telemetry.h> +#include <sof/debug/telemetry/performance_monitor.h> +/* FIXME: + * Builds for some platforms like tgl fail because their defines related to memory windows are + * already defined somewhere else. Remove this ifdef after it's cleaned up + */ +#ifdef CONFIG_SOF_TELEMETRY +#include "mem_window.h" +#include "adsp_debug_window.h" +#endif + +#include <zephyr/logging/log_ctrl.h> + +LOG_MODULE_REGISTER(basefw, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(basefw); +DECLARE_TR_CTX(basefw_comp_tr, SOF_UUID(basefw_uuid), LOG_LEVEL_INFO); + +static struct ipc4_system_time_info global_system_time_info; +static uint64_t global_cycle_delta; + +__cold static uint32_t get_host_buffer_size(void) +{ + struct sof_dma *dma_host; + uint32_t periods; + + assert_can_be_cold(); + + dma_host = sof_dma_get(SOF_DMA_DIR_HMEM_TO_LMEM, 0, SOF_DMA_DEV_HOST, + SOF_DMA_ACCESS_SHARED); + if (!dma_host) { + LOG_WRN("Failed to get host DMA channel"); + return 0; + } + + periods = dma_host->plat_data.period_count; + + sof_dma_put(dma_host); + + return periods; +} + +struct sof_ipc4_codec_info_data { + uint32_t count; + uint32_t items[32]; +} __packed __aligned(4); + +/** + * Encodes codec and direction information into a single 32-bit value. + * @param codec Codec type (bits 0-7) + * @param dir Stream direction (bits 8-11) + * @return Encoded 32-bit value + */ +#define SET_CODEC_INFO_ITEM(codec, dir) (((codec) & 0xff) | (((dir) & 0xf) << 8)) + +static void get_codec_info(struct sof_tlv **tuple) +{ + struct sof_ipc4_codec_info_data codec_info = { 0 }; + +#ifdef CONFIG_CADENCE_CODEC_AAC_DEC + codec_info.items[codec_info.count++] = + SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_AAC, SOF_IPC_STREAM_PLAYBACK); +#endif +#ifdef CONFIG_CADENCE_CODEC_MP3_DEC + codec_info.items[codec_info.count++] = + SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_MP3, SOF_IPC_STREAM_PLAYBACK); +#endif +#ifdef CONFIG_CADENCE_CODEC_MP3_ENC + codec_info.items[codec_info.count++] = + SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_MP3, SOF_IPC_STREAM_CAPTURE); +#endif +#ifdef CONFIG_CADENCE_CODEC_VORBIS_DEC + codec_info.items[codec_info.count++] = + SET_CODEC_INFO_ITEM(SND_AUDIOCODEC_VORBIS, SOF_IPC_STREAM_PLAYBACK); +#endif + + if (!codec_info.count) + return; + + tlv_value_set(*tuple, IPC4_SOF_CODEC_INFO, sizeof(codec_info.count) + + sizeof(codec_info.items[0]) * codec_info.count, &codec_info); + + *tuple = tlv_next(*tuple); +} + +#define SOF_CONFIG_MEMBER_SIZE(struct_name) (sizeof(struct sof_tlv) + \ + sizeof(struct struct_name)) +#define SOF_CONFIG_SIZE_MAX (SOF_CONFIG_MEMBER_SIZE(sof_ipc4_codec_info_data)) + +static void base_fw_sof_config(struct sof_tlv **tuple) +{ + char sof_config_data[SOF_CONFIG_SIZE_MAX] = { 0 }; + struct sof_tlv *sof_config_tuple = (struct sof_tlv *)sof_config_data; + uint32_t sof_config_size; + + get_codec_info(&sof_config_tuple); + sof_config_size = (uint32_t)((char *)sof_config_tuple - sof_config_data); + if (sof_config_size == 0) + return; + + tlv_value_set(*tuple, IPC4_FW_SOF_INFO, sof_config_size, sof_config_data); + + *tuple = tlv_next(*tuple); +} + +__cold static int basefw_config(uint32_t *data_offset, char *data) +{ + uint16_t version[4] = {SOF_MAJOR, SOF_MINOR, SOF_MICRO, SOF_BUILD}; + struct sof_tlv *tuple = (struct sof_tlv *)data; + struct ipc4_scheduler_config sche_cfg; + uint32_t plat_data_offset = 0; + uint32_t log_bytes_size = 0; + + assert_can_be_cold(); + + tlv_value_set(tuple, IPC4_FW_VERSION_FW_CFG, sizeof(version), version); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MEMORY_RECLAIMED_FW_CFG, 1); + +#ifndef CONFIG_SOF_ZEPHYR_NO_SOF_CLOCK + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_FAST_CLOCK_FREQ_HZ_FW_CFG, CLK_MAX_CPU_HZ); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, + IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, + clock_get_freq(CPU_LOWEST_FREQ_IDX)); +#endif + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_DL_MAILBOX_BYTES_FW_CFG, MAILBOX_HOSTBOX_SIZE); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_UL_MAILBOX_BYTES_FW_CFG, MAILBOX_DSPBOX_SIZE); + + /* TODO: add log support */ + tuple = tlv_next(tuple); +#ifdef CONFIG_LOG_BACKEND_ADSP_MTRACE + log_bytes_size = SOF_IPC4_LOGGING_MTRACE_PAGE_SIZE; +#endif + tlv_value_uint32_set(tuple, IPC4_TRACE_LOG_BYTES_FW_CFG, log_bytes_size); + + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_PPL_CNT_FW_CFG, IPC4_MAX_PPL_COUNT); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_ASTATE_COUNT_FW_CFG, IPC4_MAX_CLK_STATES); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_MODULE_PIN_COUNT_FW_CFG, IPC4_MAX_SRC_QUEUE); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_MOD_INST_COUNT_FW_CFG, IPC4_MAX_MODULE_INSTANCES); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_LL_TASKS_PER_PRI_COUNT_FW_CFG, + IPC4_MAX_LL_TASKS_PER_PRI_COUNT); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_LL_PRI_COUNT, SOF_IPC4_MAX_PIPELINE_PRIORITY + 1); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_DP_TASKS_COUNT_FW_CFG, IPC4_MAX_DP_TASKS_COUNT); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MODULES_COUNT_FW_CFG, 5); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MAX_LIBS_COUNT_FW_CFG, IPC4_MAX_LIBS_COUNT); + + tuple = tlv_next(tuple); + sche_cfg.sys_tick_cfg_length = 0; + sche_cfg.sys_tick_divider = 1; + sche_cfg.sys_tick_multiplier = 1; + sche_cfg.sys_tick_source = SOF_SCHEDULE_LL_TIMER; + tlv_value_set(tuple, IPC4_SCHEDULER_CONFIGURATION, sizeof(sche_cfg), &sche_cfg); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_FW_CONTEXT_SAVE, + IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE)); + + tuple = tlv_next(tuple); + + tlv_value_uint32_set(tuple, IPC4_FW_MIN_HOST_BUFFER_PERIODS, + get_host_buffer_size()); + + tuple = tlv_next(tuple); + + base_fw_sof_config(&tuple); + + /* add platform specific tuples */ + basefw_vendor_fw_config(&plat_data_offset, (char *)tuple); + + *data_offset = (int)((char *)tuple - data) + plat_data_offset; + + return IPC4_SUCCESS; +} + +__cold static int basefw_hw_config(uint32_t *data_offset, char *data) +{ + struct sof_tlv *tuple = (struct sof_tlv *)data; + uint32_t plat_data_offset = 0; + + assert_can_be_cold(); + + tlv_value_uint32_set(tuple, IPC4_CAVS_VER_HW_CFG, HW_CFG_VERSION); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_DSP_CORES_HW_CFG, CONFIG_CORE_COUNT); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_MEM_PAGE_BYTES_HW_CFG, HOST_PAGE_SIZE); + + + tuple = tlv_next(tuple); + + /* add platform specific tuples */ + basefw_vendor_hw_config(&plat_data_offset, (char *)tuple); + + *data_offset = (int)((char *)tuple - data) + plat_data_offset; + + return IPC4_SUCCESS; +} + +__cold struct ipc4_system_time_info *basefw_get_system_time_info(void) +{ + assert_can_be_cold(); + + return &global_system_time_info; +} + +/* Cannot be cold - this function is called from the logger per log_set_timestamp_func() below */ +static log_timestamp_t basefw_get_timestamp(void) +{ + return sof_cycle_get_64() + global_cycle_delta; +} + +__cold static uint32_t basefw_set_system_time(uint32_t param_id, bool first_block, bool last_block, + uint32_t data_offset, const char *data) +{ + uint64_t dsp_time; + uint64_t dsp_cycle; + uint64_t host_time; + uint64_t host_cycle; + + assert_can_be_cold(); + + if (!(first_block && last_block)) + return IPC4_INVALID_REQUEST; + + global_system_time_info.host_time.val_l = ((const struct ipc4_system_time *)data)->val_l; + global_system_time_info.host_time.val_u = ((const struct ipc4_system_time *)data)->val_u; + + dsp_cycle = sof_cycle_get_64(); + dsp_time = k_cyc_to_us_floor64(dsp_cycle); + + global_system_time_info.dsp_time.val_l = (uint32_t)(dsp_time); + global_system_time_info.dsp_time.val_u = (uint32_t)(dsp_time >> 32); + + /* use default timestamp if 64bit is not enabled since 64bit is necessary for host time */ + if (!IS_ENABLED(CONFIG_LOG_TIMESTAMP_64BIT)) { + LOG_WRN("64bits timestamp is disabled, so use default timestamp"); + return IPC4_SUCCESS; + } + + host_time = global_system_time_info.host_time.val_l | + ((uint64_t)global_system_time_info.host_time.val_u << 32); + host_cycle = k_us_to_cyc_ceil64(host_time); + global_cycle_delta = host_cycle - dsp_cycle; + log_set_timestamp_func(basefw_get_timestamp, + sys_clock_hw_cycles_per_sec()); + + return IPC4_SUCCESS; +} + +__cold static uint32_t basefw_get_system_time(uint32_t *data_offset, char *data) +{ + struct ipc4_system_time *system_time = (struct ipc4_system_time *)data; + + assert_can_be_cold(); + + system_time->val_l = global_system_time_info.host_time.val_l; + system_time->val_u = global_system_time_info.host_time.val_u; + *data_offset = sizeof(struct ipc4_system_time); + return IPC4_SUCCESS; +} + +__cold static int basefw_register_kcps(bool first_block, bool last_block, + uint32_t data_offset_or_size, const char *data) +{ + assert_can_be_cold(); + + if (!(first_block && last_block)) + return IPC4_ERROR_INVALID_PARAM; + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + if (data_offset_or_size < sizeof(int32_t)) { + tr_err(&ipc_tr, "basefw_register_kcps: payload too small: %u", data_offset_or_size); + return IPC4_ERROR_INVALID_PARAM; + } + + /* value of kcps to request on core 0. Can be negative */ + if (core_kcps_adjust(0, *(int32_t *)data)) + return IPC4_ERROR_INVALID_PARAM; +#endif + + return IPC4_SUCCESS; +} + +__cold static int basefw_kcps_allocation_request(struct ipc4_resource_kcps *request) +{ + assert_can_be_cold(); + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + if (core_kcps_adjust(request->core_id, request->kcps)) + return IPC4_ERROR_INVALID_PARAM; +#endif + + return IPC4_SUCCESS; +} + +__cold static int basefw_resource_allocation_request(bool first_block, bool last_block, + uint32_t data_offset_or_size, const char *data) +{ + struct ipc4_resource_request *request; + + assert_can_be_cold(); + + if (!(first_block && last_block)) + return IPC4_ERROR_INVALID_PARAM; + + if (data_offset_or_size < sizeof(struct ipc4_resource_request)) { + tr_err(&ipc_tr, "basefw_resource_allocation_request: payload too small: %u < %zu", + data_offset_or_size, sizeof(struct ipc4_resource_request)); + return IPC4_ERROR_INVALID_PARAM; + } + + request = (struct ipc4_resource_request *)data; + + switch (request->ra_type) { + case IPC4_RAT_DSP_KCPS: + return basefw_kcps_allocation_request(&request->ra_data.kcps); + case IPC4_RAT_MEMORY: + return IPC4_ERROR_INVALID_PARAM; + default: + return IPC4_ERROR_INVALID_PARAM; + } +} + +__cold static int basefw_power_state_info_get(uint32_t *data_offset, char *data) +{ + assert_can_be_cold(); + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + struct sof_tlv *tuple = (struct sof_tlv *)data; + uint32_t core_kcps[CONFIG_CORE_COUNT] = {0}; + int core_id; + + tlv_value_uint32_set(tuple, IPC4_ACTIVE_CORES_MASK, cpu_enabled_cores()); + tuple = tlv_next(tuple); + + for (core_id = 0; core_id < CONFIG_CORE_COUNT; core_id++) { + if (cpu_is_core_enabled(core_id)) + core_kcps[core_id] = core_kcps_get(core_id); + } + + tlv_value_set(tuple, IPC4_CORE_KCPS, sizeof(core_kcps), core_kcps); + tuple = tlv_next(tuple); + *data_offset = (int)((char *)tuple - data); + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int basefw_libraries_info_get(uint32_t *data_offset, char *data) +{ + assert_can_be_cold(); + + if (sizeof(struct ipc4_libraries_info) + + LIB_MANAGER_MAX_LIBS * sizeof(struct ipc4_library_props) > + SOF_IPC_MSG_MAX_SIZE) { + tr_err(&basefw_comp_tr, "Error with message size"); + return IPC4_OUT_OF_MEMORY; + } + + struct ipc4_libraries_info *const libs_info = (struct ipc4_libraries_info *)data; + const struct sof_man_fw_desc *desc; + int lib_counter = 0; + + for (int lib_id = 0; lib_id < LIB_MANAGER_MAX_LIBS; ++lib_id) { + if (lib_id == 0) { + desc = basefw_vendor_get_manifest(); + } else { +#if CONFIG_LIBRARY_MANAGER + desc = lib_manager_get_library_manifest(LIB_MANAGER_PACK_LIB_ID(lib_id)); +#else + desc = NULL; +#endif + } + + if (!desc) + continue; + + libs_info->libraries[lib_counter].id = lib_id; + memcpy_s(libs_info->libraries[lib_counter].name, + SOF_MAN_FW_HDR_FW_NAME_LEN, desc->header.name, sizeof(desc->header.name)); + libs_info->libraries[lib_counter].major_version = + desc->header.major_version; + libs_info->libraries[lib_counter].minor_version = + desc->header.minor_version; + libs_info->libraries[lib_counter].hotfix_version = + desc->header.hotfix_version; + libs_info->libraries[lib_counter].build_version = + desc->header.build_version; + libs_info->libraries[lib_counter].num_module_entries = + desc->header.num_module_entries; + + lib_counter++; + } + + libs_info->library_count = lib_counter; + *data_offset = + sizeof(*libs_info) + libs_info->library_count * sizeof(libs_info->libraries[0]); + + return IPC4_SUCCESS; +} + +__cold static int basefw_modules_info_get(uint32_t *data_offset, char *data) +{ + assert_can_be_cold(); + + return basefw_vendor_modules_info_get(data_offset, data); +} + +__cold int schedulers_info_get(uint32_t *data_off_size, char *data, uint32_t core_id) +{ + assert_can_be_cold(); + + /* Check if the requested core_id is valid and within the number of configured cores */ + if (core_id >= CONFIG_CORE_COUNT) + return IPC4_ERROR_INVALID_PARAM; + + struct scheduler_props *scheduler_props; + /* the internal structs have irregular sizes so we cannot use indexing, and have to + * reassign pointers for each element + */ + struct schedulers_info *schedulers_info = (struct schedulers_info *)data; + + schedulers_info->scheduler_count = 0; + /* smallest response possible is just zero schedulers count + * here we replace max_len from data_off_size to serve as output size + */ + *data_off_size = sizeof(struct schedulers_info); + /* return empty scheduler_props if core is not active */ + if (!cpu_is_core_enabled(core_id)) + return IPC4_SUCCESS; + + if (!cpu_is_me(core_id)) + return ipc4_process_on_core(core_id, false); + + /* ===================== LL_TIMER SCHEDULER INFO ============================ */ + schedulers_info->scheduler_count++; + scheduler_props = (struct scheduler_props *)(data + *data_off_size); + scheduler_get_task_info_ll(scheduler_props, data_off_size); + + /* ===================== DP SCHEDULER INFO ============================ */ +#if CONFIG_ZEPHYR_DP_SCHEDULER + schedulers_info->scheduler_count++; + scheduler_props = (struct scheduler_props *)(data + *data_off_size); + scheduler_get_task_info_dp(scheduler_props, data_off_size); +#endif + return IPC4_SUCCESS; +} + +__cold static int basefw_pipeline_list_info_get(uint32_t *data_offset, char *data) +{ + struct ipc4_pipeline_set_state_data *ppl_data = (struct ipc4_pipeline_set_state_data *)data; + + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *ipc_pipe; + const struct ipc4_pipeline_set_state_data *pipeline_data; + + assert_can_be_cold(); + + pipeline_data = ipc4_get_pipeline_data_wrapper(); + ppl_data->pipelines_count = 0; + + for (int ppl = 0; ppl < pipeline_data->pipelines_count; ppl++) { + ipc_pipe = ipc_get_pipeline_by_id(ipc, ppl); + if (!ipc_pipe) + tr_err(&ipc_tr, "No pipeline with instance_id = %d", ppl); + else + ppl_data->ppl_id[ppl_data->pipelines_count++] = + ipc_pipe->pipeline->pipeline_id; + } + + *data_offset = sizeof(ppl_data->pipelines_count) + + ppl_data->pipelines_count * sizeof(ppl_data->ppl_id[0]); + return IPC4_SUCCESS; +} + +__cold int set_perf_meas_state(uint32_t data_size, const uint8_t *data) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY + if (data_size < sizeof(*data)) { + tr_err(&ipc_tr, "set_perf_meas_state: payload too small: %u", data_size); + return IPC4_ERROR_INVALID_PARAM; + } + + uint8_t state = *data; + + switch (state) { + case IPC4_PERF_MEASUREMENTS_DISABLED: + disable_performance_counters(); + perf_meas_set_state(IPC4_PERF_MEASUREMENTS_DISABLED); + break; + case IPC4_PERF_MEASUREMENTS_STOPPED: + enable_performance_counters(); + perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STOPPED); + reset_performance_counters(); + break; + case IPC4_PERF_MEASUREMENTS_STARTED: + enable_performance_counters(); + perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STARTED); + break; + case IPC4_PERF_MEASUREMENTS_PAUSED: + enable_performance_counters(); + perf_meas_set_state(IPC4_PERF_MEASUREMENTS_PAUSED); + break; + default: + return IPC4_ERROR_INVALID_PARAM; + } +#endif + return IPC4_SUCCESS; +} + +__cold static int extended_global_perf_data_get(uint32_t *data_off_size, char *data) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + int ret; + struct extended_global_perf_data *perf_data = (struct extended_global_perf_data *)data; + + ret = get_extended_performance_data(perf_data); + if (ret < 0) + return IPC4_ERROR_INVALID_PARAM; + *data_off_size = sizeof(*perf_data) + + perf_data->perf_item_count * sizeof(*perf_data->perf_items); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int global_perf_data_get(uint32_t *data_off_size, char *data) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + int ret; + struct global_perf_data *perf_data = (struct global_perf_data *)data; + + ret = get_performance_data(perf_data); + if (ret < 0) + return IPC4_ERROR_INVALID_PARAM; + *data_off_size = sizeof(*perf_data) + + perf_data->perf_item_count * sizeof(*perf_data->perf_items); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int io_global_perf_state_get(uint32_t *data_off_size, char *data) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + *data = io_perf_monitor_get_state(); + *data_off_size = sizeof(enum ipc4_perf_measurements_state_set); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int io_global_perf_data_get(uint32_t *data_off_size, char *data) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + int ret; + struct io_global_perf_data *perf_data = (struct io_global_perf_data *)data; + + ret = io_perf_monitor_get_performance_data(perf_data); + if (ret < 0) + return IPC4_ERROR_INVALID_PARAM; + *data_off_size = sizeof(*perf_data) + + perf_data->perf_item_count * sizeof(*perf_data->perf_items); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int io_perf_monitor_state_set(uint32_t data_size, const uint8_t *data) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + if (data_size < sizeof(*data)) { + tr_err(&ipc_tr, "io_perf_monitor_state_set: payload too small: %u", data_size); + return IPC4_ERROR_INVALID_PARAM; + } + + return io_perf_monitor_set_state(*data); +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int basefw_get_large_config(struct comp_dev *dev, uint32_t param_id, + bool first_block, bool last_block, + uint32_t *data_offset, char *data) +{ + /* We can use extended param id for both extended and standard param id */ + union ipc4_extended_param_id extended_param_id; + + assert_can_be_cold(); + + extended_param_id.full = param_id; + + switch (extended_param_id.part.parameter_type) { + case IPC4_PERF_MEASUREMENTS_STATE: + case IPC4_GLOBAL_PERF_DATA: + break; + default: + if (!first_block) + return IPC4_ERROR_INVALID_PARAM; + } + + switch (extended_param_id.part.parameter_type) { + case IPC4_FW_CONFIG: + return basefw_config(data_offset, data); + case IPC4_HW_CONFIG_GET: + return basefw_hw_config(data_offset, data); + case IPC4_SYSTEM_TIME: + return basefw_get_system_time(data_offset, data); + case IPC4_POWER_STATE_INFO_GET: + return basefw_power_state_info_get(data_offset, data); + case IPC4_SCHEDULERS_INFO_GET: + return schedulers_info_get(data_offset, data, + extended_param_id.part.parameter_instance); + case IPC4_PIPELINE_LIST_INFO_GET: + return basefw_pipeline_list_info_get(data_offset, data); + case IPC4_MODULES_INFO_GET: + return basefw_modules_info_get(data_offset, data); + case IPC4_LIBRARIES_INFO_GET: + return basefw_libraries_info_get(data_offset, data); + case IPC4_EXTENDED_GLOBAL_PERF_DATA: + return extended_global_perf_data_get(data_offset, data); + case IPC4_GLOBAL_PERF_DATA: + return global_perf_data_get(data_offset, data); + case IPC4_IO_PERF_MEASUREMENTS_STATE: + return io_global_perf_state_get(data_offset, data); + case IPC4_IO_GLOBAL_PERF_DATA: + return io_global_perf_data_get(data_offset, data); + + /* TODO: add more support */ + case IPC4_DSP_RESOURCE_STATE: + case IPC4_NOTIFICATION_MASK: + case IPC4_PIPELINE_PROPS_GET: + case IPC4_GATEWAYS_INFO_GET: + case IPC4_PERF_MEASUREMENTS_STATE: + COMPILER_FALLTHROUGH; + default: + break; + } + + return basefw_vendor_get_large_config(dev, param_id, first_block, last_block, + data_offset, data); +}; + +__cold static int basefw_notification_mask_info(uint32_t data_size, const void *data) +{ + const struct ipc4_notification_mask_info *mask_info = data; + + assert_can_be_cold(); + + if (data_size < sizeof(struct ipc4_notification_mask_info)) { + tr_err(&ipc_tr, "basefw_notification_mask_info: payload too small: %u < %zu", + data_size, sizeof(struct ipc4_notification_mask_info)); + return IPC4_ERROR_INVALID_PARAM; + } + + ipc4_update_notification_mask(mask_info->ntfy_mask, mask_info->enabled_mask); + + return IPC4_SUCCESS; +} + +__cold static int basefw_astate_table(void) +{ + assert_can_be_cold(); + + /* Trivial handler possible due to an empty Astate Table requested in get_large_config */ + STATIC_ASSERT(IPC4_MAX_CLK_STATES == 0, IPC4_NON_ZERO_ASTATE_UNSUPPORTED); + + return IPC4_SUCCESS; +} + +/** + * Handles the DMA Control IPC message to initialize or modify DMA gateway configuration. + * + * @param first_block Indicates if this is the first data block in the message. + * @param last_block Indicates if this is the last data block in the message. + * @param data_offset The offset of the data in the message. + * @param data Pointer to the data buffer containing the DMA Control message. + * @return 0 on success, error code on failure. + */ +__cold static int basefw_dma_control(bool first_block, bool last_block, uint32_t data_offset, + const char *data) +{ + struct ipc4_dma_control *dma_control; + size_t data_size; + int ret; + + assert_can_be_cold(); + + /* Ensure that the message is atomic and contains all necessary information */ + if (!first_block || !last_block) { + tr_err(&ipc_tr, "Non-atomic DMA Control message received"); + return IPC4_ERROR_INVALID_PARAM; + } + + dma_control = (struct ipc4_dma_control *)data; + data_size = data_offset - sizeof(struct ipc4_dma_control); + + if (data_size < (dma_control->config_length * sizeof(uint32_t))) { + tr_err(&ipc_tr, "DMA Control data too short: got %u, expected %u", + data_size, dma_control->config_length); + return IPC4_ERROR_INVALID_PARAM; + } + + ret = basefw_vendor_dma_control(dma_control->node_id, + (const char *)dma_control->config_data, + data_size); + if (ret > 0) { + tr_err(&ipc_tr, "DMA gateway configuration failed, error: %d", ret); + return ret; + } + + return IPC4_SUCCESS; +} + +__cold static int basefw_set_large_config(struct comp_dev *dev, uint32_t param_id, + bool first_block, bool last_block, + uint32_t data_offset, const char *data) +{ + assert_can_be_cold(); + + switch (param_id) { + case IPC4_NOTIFICATION_MASK: + return basefw_notification_mask_info(data_offset, data); + case IPC4_ASTATE_TABLE: + return basefw_astate_table(); + case IPC4_DMA_CONTROL: + return basefw_dma_control(first_block, last_block, data_offset, data); + case IPC4_PERF_MEASUREMENTS_STATE: + return set_perf_meas_state(data_offset, (const uint8_t *)data); + case IPC4_IO_PERF_MEASUREMENTS_STATE: + return io_perf_monitor_state_set(data_offset, (const uint8_t *)data); + case IPC4_SYSTEM_TIME: + return basefw_set_system_time(param_id, first_block, + last_block, data_offset, data); + case IPC4_ENABLE_LOGS: + return ipc4_logging_enable_logs(first_block, last_block, data_offset, data); + case IPC4_REGISTER_KCPS: + return basefw_register_kcps(first_block, last_block, data_offset, data); + case IPC4_RESOURCE_ALLOCATION_REQUEST: + return basefw_resource_allocation_request(first_block, last_block, data_offset, + data); + default: + break; + } + + return basefw_vendor_set_large_config(dev, param_id, first_block, last_block, + data_offset, data); +}; + +static const struct comp_driver comp_basefw = { + .uid = SOF_RT_UUID(basefw_uuid), + .tctx = &basefw_comp_tr, + .ops = { + .get_large_config = basefw_get_large_config, + .set_large_config = basefw_set_large_config, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_basefw_info = { + .drv = &comp_basefw, +}; + +UT_STATIC void sys_comp_basefw_init(void) +{ + comp_register(platform_shared_get(&comp_basefw_info, + sizeof(comp_basefw_info))); +} + +DECLARE_MODULE(sys_comp_basefw_init); +SOF_MODULE_INIT(basefw, sys_comp_basefw_init); diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c new file mode 100644 index 000000000000..510d31190a22 --- /dev/null +++ b/src/audio/base_fw_intel.c @@ -0,0 +1,641 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. +// +// Author: Kai Vehmanen <kai.vehmanen@linux.intel.com> + +#include <zephyr/logging/log_ctrl.h> + +#include <rtos/string.h> +#include <sof/tlv.h> +#include <sof/lib/dai.h> +#include <ipc/dai.h> + +#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) +#include <intel_adsp_hda.h> +#endif + +#if CONFIG_ACE_V1X_ART_COUNTER || CONFIG_ACE_V1X_RTC_COUNTER +#include <zephyr/device.h> +#include <zephyr/drivers/counter.h> +#endif +#include <zephyr/pm/device_runtime.h> + +#include <sof/lib/memory.h> +#include <sof/lib_manager.h> + +#if CONFIG_UAOL_INTEL_ADSP +#include <zephyr/drivers/uaol.h> +#endif + +#include <ipc4/base_fw.h> +#include <ipc4/alh.h> +#include <rimage/sof/user/manifest.h> +#include "copier/copier_gain.h" + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include <sof/audio/mic_privacy_manager.h> +#endif + +struct ipc4_modules_info { + uint32_t modules_count; + struct sof_man_module modules[0]; +} __packed __aligned(4); + +/* Sanity check because a subtraction of those sizes is performed later on */ +STATIC_ASSERT(sizeof(struct ipc4_modules_info) < SOF_IPC_MSG_MAX_SIZE, + invalid_modules_info_struct_size); + +#if CONFIG_UAOL_INTEL_ADSP +struct ipc4_uaol_link_capabilities { + uint32_t input_streams_supported : 4; + uint32_t output_streams_supported : 4; + uint32_t bidirectional_streams_supported : 5; + uint32_t rsvd : 19; + uint32_t max_tx_fifo_size; + uint32_t max_rx_fifo_size; +} __packed __aligned(4); + +struct ipc4_uaol_capabilities { + uint32_t link_count; + struct ipc4_uaol_link_capabilities link_caps[]; +} __packed __aligned(4); +#endif /* CONFIG_UAOL_INTEL_ADSP */ + +/* + * TODO: default to value of ACE1.x platforms. This is defined + * in multiple places in Zephyr, mm_drv_intel_adsp.h and + * cavs25/adsp_memory.h, needs to be unified (and defined + * in Zephyr side) + */ +#ifndef SRAM_BANK_SIZE +#define SRAM_BANK_SIZE (128 * 1024) +#endif + +#define EBB_BANKS_IN_SEGMENT 32 + +#define PLATFORM_LPSRAM_EBB_COUNT (DT_REG_SIZE(DT_NODELABEL(sram1)) / SRAM_BANK_SIZE) +#define PLATFORM_HPSRAM_EBB_COUNT (DT_REG_SIZE(DT_NODELABEL(sram0)) / SRAM_BANK_SIZE) + +#define DT_NUM_SSP_BASE DT_NUM_INST_STATUS_OKAY(intel_ssp) +#define DT_NUM_HDA_IN DT_PROP(DT_INST(0, intel_adsp_hda_link_in), dma_channels) +#define DT_NUM_HDA_OUT DT_PROP(DT_INST(0, intel_adsp_hda_link_out), dma_channels) + +LOG_MODULE_REGISTER(basefw_intel, CONFIG_SOF_LOG_LEVEL); + +__cold int basefw_vendor_fw_config(uint32_t *data_offset, char *data) +{ + struct sof_tlv *tuple = (struct sof_tlv *)data; + + assert_can_be_cold(); + + tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, IS_ENABLED(CONFIG_UAOL_INTEL_ADSP)); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8); + + tuple = tlv_next(tuple); + *data_offset = (int)((char *)tuple - data); + + return 0; +} + +#if CONFIG_UAOL_INTEL_ADSP +#define DEV_AND_COMMA(node) DEVICE_DT_GET(node), +static const struct device *uaol_devs[] = { + DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, DEV_AND_COMMA) +}; + +#if !CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY +__cold static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type) +{ + const size_t dev_count = ARRAY_SIZE(uaol_devs); + struct uaol_capabilities dev_cap; + struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value; + size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]); + size_t i; + int ret; + + assert_can_be_cold(); + + memset(caps, 0, caps_size); + + caps->link_count = dev_count; + for (i = 0; i < dev_count; i++) { + ret = uaol_get_capabilities(uaol_devs[i], &dev_cap); + if (ret) + continue; + + caps->link_caps[i].input_streams_supported = dev_cap.input_streams; + caps->link_caps[i].output_streams_supported = dev_cap.output_streams; + caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams; + caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size; + caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size; + } + + tlv_value_set(tuple, type, caps_size, caps); +} +#endif /* CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY */ + +__cold static int uaol_stream_id_to_hda_link_stream_id(int uaol_stream_id) +{ + size_t dev_count = ARRAY_SIZE(uaol_devs); + size_t i; + + assert_can_be_cold(); + + for (i = 0; i < dev_count; i++) { + int hda_link_stream_id = uaol_get_mapped_hda_link_stream_id(uaol_devs[i], + uaol_stream_id); + if (hda_link_stream_id >= 0) + return hda_link_stream_id; + } + + return -1; +} +#endif /* CONFIG_UAOL_INTEL_ADSP */ + +__cold int basefw_vendor_hw_config(uint32_t *data_offset, char *data) +{ + struct sof_tlv *tuple = (struct sof_tlv *)data; + uint32_t value; + + assert_can_be_cold(); + + tlv_value_uint32_set(tuple, IPC4_HP_EBB_COUNT_HW_CFG, PLATFORM_HPSRAM_EBB_COUNT); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_EBB_SIZE_BYTES_HW_CFG, SRAM_BANK_SIZE); + + tuple = tlv_next(tuple); + value = SOF_DIV_ROUND_UP(EBB_BANKS_IN_SEGMENT * SRAM_BANK_SIZE, HOST_PAGE_SIZE); + tlv_value_uint32_set(tuple, IPC4_TOTAL_PHYS_MEM_PAGES_HW_CFG, value); + + tuple = tlv_next(tuple); + /* 2 DMIC dais */ + value = DT_NUM_SSP_BASE + DT_NUM_HDA_IN + DT_NUM_HDA_OUT + + IPC4_DAI_NUM_ALH_BI_DIR_LINKS + 2; + tlv_value_uint32_set(tuple, IPC4_GATEWAY_COUNT_HW_CFG, value); + + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_LP_EBB_COUNT_HW_CFG, PLATFORM_LPSRAM_EBB_COUNT); + +#if defined(CONFIG_SOC_ACE30) || defined(CONFIG_SOC_ACE40) + tuple = tlv_next(tuple); + tlv_value_uint32_set(tuple, IPC4_I2S_CAPS_HW_CFG, I2S_VER_30_PTL); +#endif + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + struct privacy_capabilities priv_caps; + + tuple = tlv_next(tuple); + + priv_caps.privacy_version = 1; + priv_caps.capabilities_length = 1; + priv_caps.capabilities[0] = mic_privacy_get_policy_register(); + + tlv_value_set(tuple, IPC4_INTEL_MIC_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps); +#endif + + /* Linux 7.0 and older do not enable UAOL for any Intel + * hardware, so below capability check will lead to a DSP + * panic. In strict compatibility mode, bypass the capability + * check. */ +#if !defined(CONFIG_SOF_OS_LINUX_COMPAT_PRIORITY) && defined(CONFIG_UAOL_INTEL_ADSP) + tuple = tlv_next(tuple); + tlv_value_set_uaol_caps(tuple, IPC4_UAOL_CAPS_HW_CFG); +#endif + + tuple = tlv_next(tuple); + *data_offset = (int)((char *)tuple - data); + + return 0; +} + +__cold struct sof_man_fw_desc *basefw_vendor_get_manifest(void) +{ + assert_can_be_cold(); + + return (struct sof_man_fw_desc *)IMR_BOOT_LDR_MANIFEST_BASE; +} + +__cold int basefw_vendor_modules_info_get(uint32_t *data_offset, char *data) +{ + assert_can_be_cold(); + + struct ipc4_modules_info *const module_info = (struct ipc4_modules_info *)data; + const struct sof_man_fw_desc *desc; + uint32_t curr_mod_cnt, curr_cpy_size, total_mod_cnt = 0; + uint32_t total_size_left = SOF_IPC_MSG_MAX_SIZE - sizeof(struct ipc4_modules_info); + int ret; + + for (int lib_id = 0; lib_id < LIB_MANAGER_MAX_LIBS; ++lib_id) { + if (lib_id == 0) { + desc = basefw_vendor_get_manifest(); + } else { +#if CONFIG_LIBRARY_MANAGER + desc = lib_manager_get_library_manifest(LIB_MANAGER_PACK_LIB_ID(lib_id)); +#else + desc = NULL; +#endif + } + + if (!desc) + continue; + + curr_mod_cnt = desc->header.num_module_entries; + curr_cpy_size = sizeof(struct sof_man_module) * curr_mod_cnt; + + ret = memcpy_s(&module_info->modules[total_mod_cnt], total_size_left, + (char *)desc + SOF_MAN_MODULE_OFFSET(0), curr_cpy_size); + if (ret) { + tr_err(&basefw_comp_tr, "Couldn't copy module info for %d lib", lib_id); + return IPC4_OUT_OF_MEMORY; + } + + /* replace structure id ("$AME" tag) with runtime info */ + for (uint32_t idx = 0; idx < curr_mod_cnt; ++idx) { + uint32_t mod_id = LIB_MANAGER_PACK_MODULE_ID(lib_id, idx); + + module_info->modules[total_mod_cnt + idx].runtime_info.module_id = mod_id; + /* TODO: set bit[0] for modules loaded into ADSP memory */ + module_info->modules[total_mod_cnt + idx].runtime_info.state_flags = 0x0; + } + + total_mod_cnt += curr_mod_cnt; + total_size_left -= curr_cpy_size; + } + + module_info->modules_count = total_mod_cnt; + + *data_offset = sizeof(*module_info) + + module_info->modules_count * sizeof(module_info->modules[0]); + return IPC4_SUCCESS; +} + +/* There are two types of sram memory : high power mode sram and + * low power mode sram. This function retures memory size in page + * , memory bank power and usage status of each sram to host driver + */ +__cold static int basefw_mem_state_info(uint32_t *data_offset, char *data) +{ + struct sof_tlv *tuple = (struct sof_tlv *)data; + struct ipc4_sram_state_info info; + uint32_t *tuple_data; + uint32_t index; + uint32_t size; + uint16_t *ptr; + int i; + + assert_can_be_cold(); + + /* set hpsram */ + info.free_phys_mem_pages = SRAM_BANK_SIZE * PLATFORM_HPSRAM_EBB_COUNT / HOST_PAGE_SIZE; + info.ebb_state_dword_count = SOF_DIV_ROUND_UP(PLATFORM_HPSRAM_EBB_COUNT, 32); + info.page_alloc_struct.page_alloc_count = PLATFORM_HPSRAM_EBB_COUNT; + size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + + info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); + size = ALIGN(size, 4); + /* size is also saved as tuple length */ + tuple_data = rballoc(SOF_MEM_FLAG_USER, size); + if (!tuple_data) { + LOG_ERR("allocation failed"); + return IPC4_ERROR_INVALID_PARAM; + } + + /* save memory info in data array since info length is variable */ + 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++) + tuple_data[index++] = HPSRAM_REGS(i)->HSxPGCTL; + + tuple_data[index++] = info.page_alloc_struct.page_alloc_count; + /* TLB is not supported now, so all pages are marked as occupied + * TODO: add page-size allocator and TLB support + */ + ptr = (uint16_t *)(tuple_data + index); + for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) + ptr[i] = 0xfff; + + tlv_value_set(tuple, IPC4_HPSRAM_STATE, size, tuple_data); + + /* set lpsram */ + info.free_phys_mem_pages = 0; + info.ebb_state_dword_count = SOF_DIV_ROUND_UP(PLATFORM_LPSRAM_EBB_COUNT, 32); + info.page_alloc_struct.page_alloc_count = PLATFORM_LPSRAM_EBB_COUNT; + size = sizeof(info) + info.ebb_state_dword_count * sizeof(uint32_t) + + info.page_alloc_struct.page_alloc_count * sizeof(uint32_t); + size = ALIGN(size, 4); + + 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++) + tuple_data[index++] = LPSRAM_REGS(i)->USxPGCTL; + + 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++) + ptr[i] = 0xfff; + + tuple = tlv_next(tuple); + tlv_value_set(tuple, IPC4_LPSRAM_STATE, size, tuple_data); + + /* calculate total tuple size */ + tuple = tlv_next(tuple); + *data_offset = (int)((char *)tuple - data); + + rfree(tuple_data); + return IPC4_SUCCESS; +} + +__cold static uint32_t basefw_get_ext_system_time(uint32_t *data_offset, char *data) +{ + assert_can_be_cold(); + +#if CONFIG_ACE_V1X_ART_COUNTER && CONFIG_ACE_V1X_RTC_COUNTER + struct ipc4_ext_system_time *ext_system_time = (struct ipc4_ext_system_time *)(data); + struct ipc4_ext_system_time ext_system_time_data = {0}; + struct ipc4_system_time_info *time_info = basefw_get_system_time_info(); + uint64_t host_time = ((uint64_t)time_info->host_time.val_u << 32) + | (uint64_t)time_info->host_time.val_l; + uint64_t dsp_time = ((uint64_t)time_info->dsp_time.val_u << 32) + | (uint64_t)time_info->dsp_time.val_l; + + if (host_time == 0 || dsp_time == 0) + return IPC4_INVALID_RESOURCE_STATE; + + uint64_t art = 0; + uint64_t wallclk = 0; + uint64_t rtc = 0; + + const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(ace_art_counter)); + + if (!dev) { + LOG_DBG("board: ART counter device binding failed"); + return IPC4_MOD_NOT_INITIALIZED; + } + + counter_get_value_64(dev, &art); + + wallclk = sof_cycle_get_64(); + ext_system_time_data.art_l = (uint32_t)art; + ext_system_time_data.art_u = (uint32_t)(art >> 32); + uint64_t delta = (wallclk - dsp_time) / (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000); + + uint64_t new_host_time = (host_time + delta); + + ext_system_time_data.utc_l = (uint32_t)new_host_time; + ext_system_time_data.utc_u = (uint32_t)(new_host_time >> 32); + + dev = DEVICE_DT_GET(DT_NODELABEL(ace_rtc_counter)); + + if (!dev) { + LOG_DBG("board: RTC counter device binding failed"); + return IPC4_MOD_NOT_INITIALIZED; + } + + counter_get_value_64(dev, &rtc); + ext_system_time_data.rtc_l = (uint32_t)rtc; + ext_system_time_data.rtc_u = (uint32_t)(rtc >> 32); + + memcpy_s(ext_system_time, sizeof(*ext_system_time), &ext_system_time_data, + sizeof(ext_system_time_data)); + *data_offset = sizeof(struct ipc4_ext_system_time); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold int basefw_vendor_get_large_config(struct comp_dev *dev, uint32_t param_id, + bool first_block, bool last_block, + uint32_t *data_offset, char *data) +{ + assert_can_be_cold(); + + /* We can use extended param id for both extended and standard param id */ + union ipc4_extended_param_id extended_param_id; + + extended_param_id.full = param_id; + + uint32_t ret = IPC4_ERROR_INVALID_PARAM; + + switch (extended_param_id.part.parameter_type) { + case IPC4_MEMORY_STATE_INFO_GET: + return basefw_mem_state_info(data_offset, data); + case IPC4_EXTENDED_SYSTEM_TIME: + ret = basefw_get_ext_system_time(data_offset, data); + if (ret == IPC4_UNAVAILABLE) { + tr_warn(&basefw_comp_tr, + "returning success for get host EXTENDED_SYSTEM_TIME without handling it"); + return IPC4_SUCCESS; + } else { + return ret; + } + break; + default: + break; + } + + return ret; +} + +__cold static int fw_config_set_force_l1_exit(const struct sof_tlv *tlv) +{ + assert_can_be_cold(); + +#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) + const uint32_t force = tlv->value[0]; + + if (force) { + tr_info(&basefw_comp_tr, "FW config set force dmi l0 state"); + intel_adsp_force_dmi_l0_state(); + } else { + tr_info(&basefw_comp_tr, "FW config set allow dmi l1 state"); + intel_adsp_allow_dmi_l1_state(); + } + + return 0; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int basefw_set_fw_config(bool first_block, bool last_block, + uint32_t data_offset, const char *data) +{ + assert_can_be_cold(); + + /* Validate minimum TLV header (type + length fields) is present */ + if (data_offset < sizeof(struct sof_tlv)) { + tr_err(&basefw_comp_tr, "FW_CONFIG payload too small: %u < %zu", + data_offset, sizeof(struct sof_tlv)); + return IPC4_INVALID_CONFIG_DATA_LEN; + } + + const struct sof_tlv *tlv = (const struct sof_tlv *)data; + + /* Validate the TLV value payload fits within the reported buffer size */ + if (tlv->length > data_offset - sizeof(struct sof_tlv)) { + tr_err(&basefw_comp_tr, + "FW_CONFIG TLV value truncated: len %u exceeds payload %u", + tlv->length, data_offset); + return IPC4_INVALID_CONFIG_DATA_LEN; + } + + switch (tlv->type) { + case IPC4_DMI_FORCE_L1_EXIT: + if (tlv->length < sizeof(uint32_t)) { + tr_err(&basefw_comp_tr, "DMI_FORCE_L1_EXIT value too small: %u", + tlv->length); + return IPC4_INVALID_CONFIG_DATA_LEN; + } + return fw_config_set_force_l1_exit(tlv); + default: + break; + } + + tr_warn(&basefw_comp_tr, "Set FW_CONFIG: no handler for type %u", tlv->type); + return 0; +} + +static int basefw_set_mic_priv_policy(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + return 0; +#else + return IPC4_UNAVAILABLE; +#endif +} + +static int basefw_mic_priv_state_changed(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (data_offset_or_size < sizeof(uint8_t)) { + tr_err(&basefw_comp_tr, "mic_priv_state_changed: payload too small: %u", + data_offset_or_size); + return IPC4_ERROR_INVALID_PARAM; + } + + uint32_t mic_disable_status = (uint32_t)(uint8_t)(*data); + + tr_info(&basefw_comp_tr, "state changed to %u", mic_disable_status); + struct mic_privacy_settings settings; + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + + return 0; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold int basefw_vendor_set_large_config(struct comp_dev *dev, uint32_t param_id, + bool first_block, bool last_block, + uint32_t data_offset, const char *data) +{ + assert_can_be_cold(); + + switch (param_id) { + case IPC4_FW_CONFIG: + return basefw_set_fw_config(first_block, last_block, data_offset, data); + case IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK: + return basefw_set_mic_priv_policy(first_block, last_block, data_offset, data); + case IPC4_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE: + return basefw_mic_priv_state_changed(first_block, last_block, data_offset, data); + default: + break; + } + + return IPC4_UNKNOWN_MESSAGE_TYPE; +} + +__cold int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t data_size) +{ + union ipc4_connector_node_id node = (union ipc4_connector_node_id)node_id; + int dai_index = node.f.v_index; + int ret, result; + enum sof_ipc_dai_type type; + + assert_can_be_cold(); + + tr_info(&basefw_comp_tr, "node_id 0x%x, config_data 0x%x, data_size %u", + node_id, (uint32_t)config_data, data_size); + + switch (node.f.dma_type) { + case ipc4_dmic_link_input_class: + /* In DMIC case we don't need to update zephyr dai params */ + ret = copier_gain_dma_control(node, config_data, data_size, + SOF_DAI_INTEL_DMIC); + if (ret) { + tr_err(&basefw_comp_tr, + "Failed to update copier gain coefs, error: %d", ret); + return IPC4_INVALID_REQUEST; + } + return IPC4_SUCCESS; + case ipc4_i2s_link_output_class: + case ipc4_i2s_link_input_class: + type = SOF_DAI_INTEL_SSP; + break; + +#if CONFIG_UAOL_INTEL_ADSP + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: + type = SOF_DAI_INTEL_UAOL; + dai_index = uaol_stream_id_to_hda_link_stream_id(node.f.v_index); + if (dai_index < 0) { + tr_err(&basefw_comp_tr, + "HDA link stream not found! UAOL node ID: 0x%x", node_id); + return IPC4_INVALID_RESOURCE_ID; + } + break; +#endif + + default: + return IPC4_INVALID_RESOURCE_ID; + } + + const struct device *dev = dai_get_device(type, dai_index); + + if (!dev) { + tr_err(&basefw_comp_tr, + "Failed to find the DAI device for node_id: 0x%x", + node_id); + return IPC4_INVALID_RESOURCE_ID; + } + + ret = pm_device_runtime_get(dev); + if (ret < 0) { + tr_err(&basefw_comp_tr, "Failed to get resume device, error: %d", + ret); + return IPC4_FAILURE; + } + + result = dai_config_update(dev, config_data, data_size); + if (result < 0) { + tr_err(&basefw_comp_tr, + "Failed to set DMA control for DAI, error: %d", + result); + result = IPC4_FAILURE; + } + + ret = pm_device_runtime_put(dev); + if (ret < 0) + tr_err(&basefw_comp_tr, "Failed to suspend device, error: %d", + ret); + + return result; +} diff --git a/src/audio/buffer.c b/src/audio/buffer.c deleted file mode 100644 index ff99ad6057a8..000000000000 --- a/src/audio/buffer.c +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/list.h> -#include <sof/spinlock.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t align) -{ - struct comp_buffer *buffer; - - tracev_buffer("buffer_alloc()"); - - /* validate request */ - if (size == 0 || size > HEAP_BUFFER_SIZE) { - trace_buffer_error("buffer_alloc() error: " - "new size = %u is invalid", size); - return NULL; - } - - /* allocate new buffer */ - buffer = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*buffer)); - if (!buffer) { - trace_buffer_error("buffer_alloc() error: " - "could not alloc structure"); - return NULL; - } - - buffer->lock = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*buffer->lock)); - if (!buffer->lock) { - rfree(buffer); - trace_buffer_error("buffer_alloc() error: could not alloc lock"); - return NULL; - } - - buffer->stream.addr = rballoc_align(0, caps, size, align); - if (!buffer->stream.addr) { - rfree(buffer); - trace_buffer_error("buffer_alloc() error: " - "could not alloc size = %u " - "bytes of type = %u", - size, caps); - return NULL; - } - - buffer_init(buffer, size, caps); - - list_init(&buffer->source_list); - list_init(&buffer->sink_list); - spinlock_init(buffer->lock); - - return buffer; -} - -/* create a new component in the pipeline */ -struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc) -{ - struct comp_buffer *buffer; - - trace_buffer("buffer_new()"); - - /* allocate buffer */ - buffer = buffer_alloc(desc->size, desc->caps, PLATFORM_DCACHE_ALIGN); - if (buffer) { - buffer->id = desc->comp.id; - buffer->pipeline_id = desc->comp.pipeline_id; - buffer->core = desc->comp.core; - - dcache_writeback_invalidate_region(buffer, sizeof(*buffer)); - } - - return buffer; -} - -int buffer_set_size(struct comp_buffer *buffer, uint32_t size) -{ - void *new_ptr = NULL; - - /* validate request */ - if (size == 0 || size > HEAP_BUFFER_SIZE) { - trace_buffer_error_with_ids(buffer, "resize error: size = %u is invalid", - size); - return -EINVAL; - } - - if (size == buffer->stream.size) - return 0; - - new_ptr = rbrealloc(buffer->stream.addr, 0, buffer->caps, size); - - /* we couldn't allocate bigger chunk */ - if (!new_ptr && size > buffer->stream.size) { - trace_buffer_error_with_ids(buffer, "resize error: can't alloc %u bytes type %u", - buffer->stream.size, buffer->caps); - return -ENOMEM; - } - - /* use bigger chunk, else just use the old chunk but set smaller */ - if (new_ptr) - buffer->stream.addr = new_ptr; - - buffer_init(buffer, size, buffer->caps); - - return 0; -} - -/* free component in the pipeline */ -void buffer_free(struct comp_buffer *buffer) -{ - struct buffer_cb_free cb_data = { - .buffer = buffer, - }; - - tracev_buffer_with_ids(buffer, "buffer_free()"); - - notifier_event(buffer, NOTIFIER_ID_BUFFER_FREE, - NOTIFIER_TARGET_CORE_LOCAL, &cb_data, sizeof(cb_data)); - - /* In case some listeners didn't unregister from buffer's callbacks */ - notifier_unregister_all(NULL, buffer); - - list_item_del(&buffer->source_list); - list_item_del(&buffer->sink_list); - rfree(buffer->stream.addr); - rfree(buffer->lock); - rfree(buffer); -} - -void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes) -{ - uint32_t flags = 0; - struct buffer_cb_transact cb_data = { - .buffer = buffer, - .transaction_amount = bytes, - .transaction_begin_address = buffer->stream.w_ptr, - }; - char *addr; - - /* return if no bytes */ - if (!bytes) { - trace_buffer_with_ids(buffer, - "comp_update_buffer_produce(), no bytes to produce, source->comp.id = %u, source->comp.type = %u, sink->comp.id = %u, sink->comp.type = %u", - dev_comp_id(buffer->source), - dev_comp_type(buffer->source), - dev_comp_id(buffer->sink), - dev_comp_type(buffer->sink)); - return; - } - - buffer_lock(buffer, &flags); - - audio_stream_produce(&buffer->stream, bytes); - - notifier_event(buffer, NOTIFIER_ID_BUFFER_PRODUCE, - NOTIFIER_TARGET_CORE_LOCAL, &cb_data, sizeof(cb_data)); - - buffer_unlock(buffer, flags); - - addr = buffer->stream.addr; - - tracev_buffer_with_ids(buffer, - "comp_update_buffer_produce(), ((buffer->avail << 16) | buffer->free) = %08x, ((buffer->id << 16) | buffer->size) = %08x", - (buffer->stream.avail << 16) | - buffer->stream.free, - (buffer->id << 16) | buffer->stream.size); - tracev_buffer_with_ids(buffer, - "comp_update_buffer_produce(), ((buffer->r_ptr - buffer->addr) << 16 | (buffer->w_ptr - buffer->addr)) = %08x", - ((char *)buffer->stream.r_ptr - addr) << 16 | - ((char *)buffer->stream.w_ptr - addr)); -} - -void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes) -{ - uint32_t flags = 0; - struct buffer_cb_transact cb_data = { - .buffer = buffer, - .transaction_amount = bytes, - .transaction_begin_address = buffer->stream.r_ptr, - }; - char *addr; - - /* return if no bytes */ - if (!bytes) { - trace_buffer_with_ids(buffer, - "comp_update_buffer_consume(), no bytes to consume, source->comp.id = %u, source->comp.type = %u, sink->comp.id = %u, sink->comp.type = %u", - dev_comp_id(buffer->source), - dev_comp_type(buffer->source), - dev_comp_id(buffer->sink), - dev_comp_type(buffer->sink)); - return; - } - - buffer_lock(buffer, &flags); - - audio_stream_consume(&buffer->stream, bytes); - - notifier_event(buffer, NOTIFIER_ID_BUFFER_CONSUME, - NOTIFIER_TARGET_CORE_LOCAL, &cb_data, sizeof(cb_data)); - - buffer_unlock(buffer, flags); - - addr = buffer->stream.addr; - - tracev_buffer_with_ids(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", - (buffer->stream.avail << 16) | - buffer->stream.free, - (buffer->id << 16) | buffer->stream.size, - ((char *)buffer->stream.r_ptr - addr) << 16 | - ((char *)buffer->stream.w_ptr - addr)); -} diff --git a/src/audio/buffers/CMakeLists.txt b/src/audio/buffers/CMakeLists.txt new file mode 100644 index 000000000000..b035b055b449 --- /dev/null +++ b/src/audio/buffers/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof audio_buffer.c comp_buffer.c) + +add_local_sources_ifdef(CONFIG_PIPELINE_2_0 sof ring_buffer.c) diff --git a/src/audio/buffers/README.md b/src/audio/buffers/README.md new file mode 100644 index 000000000000..fcd4516dd4ab --- /dev/null +++ b/src/audio/buffers/README.md @@ -0,0 +1,20 @@ +# Audio Buffers Architecture + +This directory contains the core audio buffer management. + +## Overview + +Buffers connect the output of one component to the input of the next in an audio pipeline graph. They implement circular (ring) buffer semantics and handle cache coherency for DSP memory. + +## Architecture Diagram + +```mermaid +graph LR + CompA[Component A / Producer] -->|Write| Buf[Ring Buffer] + Buf -->|Read| CompB[Component B / Consumer] +``` + +## Configuration and Scripts + +- **CMakeLists.txt**: Includes the base core buffer source files (`audio_buffer.c`, `comp_buffer.c`). When the `CONFIG_PIPELINE_2_0` feature flag is enabled, it additionally compiles `ring_buffer.c`. +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/buffer.conf`, defining the `buffer` widget object. Key parameters include `size` (automatically computed), `periods`, `channels`, and `caps` (capabilities like `dai`, `host`, `pass`, `comp`). Defaults to UUID `92:4c:54:42:92:8e:41:4e:b6:79:34:51:9f:1c:1d:28`. diff --git a/src/audio/buffers/audio_buffer.c b/src/audio/buffers/audio_buffer.c new file mode 100644 index 000000000000..1ecf8472dd65 --- /dev/null +++ b/src/audio/buffers/audio_buffer.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Marcin Szkudlinski <marcin.szkudlinski@intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <rtos/panic.h> +#include <rtos/alloc.h> +#include <ipc/stream.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <module/ipc4/base-config.h> +#include <sof/audio/component.h> +#include <module/module/base.h> +#include <sof/audio/audio_buffer.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/sink_source_utils.h> + +#if CONFIG_PIPELINE_2_0 + +int audio_buffer_attach_secondary_buffer(struct sof_audio_buffer *buffer, bool at_input, + struct sof_audio_buffer *secondary_buffer) +{ + if (buffer->secondary_buffer_sink || buffer->secondary_buffer_source) + return -EINVAL; + + /* secondary buffer must share audio params with the primary buffer */ + secondary_buffer->audio_stream_params = buffer->audio_stream_params; + /* for performance reasons pointers to params are also kept in sink/src structures */ + secondary_buffer->_sink_api.audio_stream_params = buffer->audio_stream_params; + secondary_buffer->_source_api.audio_stream_params = buffer->audio_stream_params; + + if (at_input) + buffer->secondary_buffer_sink = secondary_buffer; + else + buffer->secondary_buffer_source = secondary_buffer; + + return 0; +} + +int audio_buffer_sync_secondary_buffer(struct sof_audio_buffer *buffer, size_t limit) +{ + int err; + + struct sof_source *data_src; + struct sof_sink *data_dst; + + if (buffer->secondary_buffer_sink) { + /* + * audio_buffer sink API is shadowed, that means there's a secondary_buffer + * at data input + * get data from secondary_buffer (use source API) + * copy to primary buffer (use sink API) + * note! can't use audio_buffer_get_sink because it will provide a shadowed + * sink handler (to a secondary buffer). + */ + data_src = audio_buffer_get_source(buffer->secondary_buffer_sink); + data_dst = &buffer->_sink_api; /* primary buffer's sink API */ + } else if (buffer->secondary_buffer_source) { + /* + * comp_buffer source API is shadowed, that means there's a secondary_buffer + * at data output + * get data from comp_buffer (use source API) + * copy to secondary_buffer (use sink API) + */ + data_src = &buffer->_source_api; + data_dst = audio_buffer_get_sink(buffer->secondary_buffer_source); + + } else { + return -EINVAL; + } + + /* + * keep data_available and free_size in local variables to avoid check_time/use_time + * race in MIN macro + */ + size_t data_available = source_get_data_available(data_src); + size_t free_size = sink_get_free_size(data_dst); + size_t to_copy = MIN(MIN(data_available, free_size), limit); + + err = source_to_sink_copy(data_src, data_dst, true, to_copy); + return err; +} + +#endif /* CONFIG_PIPELINE_2_0 */ + +void audio_buffer_free(struct sof_audio_buffer *buffer) +{ + if (!buffer) + return; + + CORE_CHECK_STRUCT(buffer); +#if CONFIG_PIPELINE_2_0 + audio_buffer_free(buffer->secondary_buffer_sink); + audio_buffer_free(buffer->secondary_buffer_source); +#endif /* CONFIG_PIPELINE_2_0 */ + /* "virtual destructor": free the buffer internals and buffer memory */ + buffer->ops->free(buffer); +} + +static +int audio_buffer_source_set_ipc_params_default(struct sof_audio_buffer *buffer, + struct sof_ipc_stream_params *params, + bool force_update) +{ + CORE_CHECK_STRUCT(buffer); + + if (audio_buffer_hw_params_configured(buffer) && !force_update) + return 0; + + struct sof_audio_stream_params *audio_stream_params = + audio_buffer_get_stream_params(buffer); + + audio_stream_params->frame_fmt = params->frame_fmt; + audio_stream_params->rate = params->rate; + audio_stream_params->channels = params->channels; + audio_stream_params->buffer_fmt = params->buffer_fmt; + + audio_buffer_set_hw_params_configured(buffer); + + if (buffer->ops->on_audio_format_set) + return buffer->ops->on_audio_format_set(buffer); + return 0; +} + +int audio_buffer_sink_set_ipc_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, + bool force_update) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_sink(sink); + + if (buffer->ops->audio_set_ipc_params) + return buffer->ops->audio_set_ipc_params(buffer, params, force_update); + return audio_buffer_source_set_ipc_params_default(buffer, params, force_update); +} + +int audio_buffer_sink_on_audio_format_set(struct sof_sink *sink) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_sink(sink); + + if (buffer->ops->on_audio_format_set) + return buffer->ops->on_audio_format_set(buffer); + return 0; +} + +int audio_buffer_sink_set_alignment_constants(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_sink(sink); + + if (buffer->ops->set_alignment_constants) + return buffer->ops->set_alignment_constants(buffer, byte_align, frame_align_req); + return 0; +} + +int audio_buffer_source_set_ipc_params(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_source(source); + + if (buffer->ops->audio_set_ipc_params) + return buffer->ops->audio_set_ipc_params(buffer, params, force_update); + return audio_buffer_source_set_ipc_params_default(buffer, params, force_update); +} + +int audio_buffer_source_on_audio_format_set(struct sof_source *source) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_source(source); + + if (buffer->ops->on_audio_format_set) + return buffer->ops->on_audio_format_set(buffer); + return 0; +} + +int audio_buffer_source_set_alignment_constants(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_source(source); + + if (buffer->ops->set_alignment_constants) + return buffer->ops->set_alignment_constants(buffer, byte_align, frame_align_req); + return 0; +} + +uint32_t audio_buffer_sink_get_lft(struct sof_sink *sink) +{ + struct sof_audio_buffer *buffer = sof_audio_buffer_from_sink(sink); + /* get number of ms in the buffer */ + size_t bytes_per_sec = sink_get_frame_bytes(&buffer->_sink_api) * + sink_get_rate(&buffer->_sink_api); + size_t bytes_per_ms = bytes_per_sec / 1000; + + /* round up for frequencies like 44100 */ + if (bytes_per_ms * 1000 != bytes_per_sec) + bytes_per_ms++; + uint32_t us_in_buffer = + 1000 * source_get_data_available(&buffer->_source_api) / bytes_per_ms; + + return us_in_buffer; + + /* + * TODO, Currently there's no DP to DP connection + * >>> the code below is never accessible and won't work because of cache incoherence <<< + * + * to make DP to DP connection possible: + * + * 1) module data must be ALWAYS located in non cached memory alias, allowing + * cross core access to params like period (needed below) and calling + * module_get_deadline for the next module, regardless of cores the modules are + * running on + * 2) comp_buffer must be removed from all pipeline code, replaced with a generic abstract + * class audio_buffer - allowing using comp_buffer and ring_buffer without current + * "hybrid buffer" solution + */ +} + +void audio_buffer_init(struct sof_audio_buffer *buffer, uint32_t buffer_type, bool is_shared, + const struct source_ops *source_ops, const struct sink_ops *sink_ops, + const struct audio_buffer_ops *audio_buffer_ops, + struct sof_audio_stream_params *audio_stream_params) +{ + CORE_CHECK_STRUCT_INIT(buffer, is_shared); + buffer->buffer_type = buffer_type; + buffer->ops = audio_buffer_ops; + assert(audio_buffer_ops->free); + buffer->audio_stream_params = audio_stream_params; + buffer->is_shared = is_shared; + + source_init(audio_buffer_get_source(buffer), source_ops, + audio_buffer_get_stream_params(buffer)); + sink_init(audio_buffer_get_sink(buffer), sink_ops, + audio_buffer_get_stream_params(buffer)); +} diff --git a/src/audio/buffers/comp_buffer.c b/src/audio/buffers/comp_buffer.c new file mode 100644 index 000000000000..cc38a7dfead7 --- /dev/null +++ b/src/audio/buffers/comp_buffer.c @@ -0,0 +1,656 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/audio_buffer.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/sink_source_utils.h> +#include <rtos/userspace_helper.h> +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/vregion.h> +#include <sof/list.h> +#include <sof/schedule/dp_schedule.h> +#include <rtos/spinlock.h> +#include <rtos/symbol.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(buffer, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(buffer); +DECLARE_TR_CTX(buffer_tr, SOF_UUID(buffer_uuid), LOG_LEVEL_INFO); + +static size_t comp_buffer_get_data_available(struct sof_source *source) +{ + struct comp_buffer *buffer = comp_buffer_get_from_source(source); + + return audio_stream_get_avail_bytes(&buffer->stream); +} + +static int comp_buffer_get_data(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, + size_t *buffer_size) +{ + struct comp_buffer *buffer = comp_buffer_get_from_source(source); + + if (req_size > audio_stream_get_avail_bytes(&buffer->stream)) + return -ENODATA; + + buffer_stream_invalidate(buffer, req_size); + + /* get circular buffer parameters */ + *data_ptr = buffer->stream.r_ptr; + *buffer_start = buffer->stream.addr; + *buffer_size = buffer->stream.size; + return 0; +} + +static int comp_buffer_release_data(struct sof_source *source, size_t free_size) +{ + struct comp_buffer *buffer = comp_buffer_get_from_source(source); + + if (free_size) + audio_stream_consume(&buffer->stream, free_size); + + return 0; +} + +static size_t comp_buffer_get_free_size(struct sof_sink *sink) +{ + struct comp_buffer *buffer = comp_buffer_get_from_sink(sink); + + return audio_stream_get_free_bytes(&buffer->stream); +} + +static int comp_buffer_get_buffer(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size) +{ + struct comp_buffer *buffer = comp_buffer_get_from_sink(sink); + + if (req_size > audio_stream_get_free_bytes(&buffer->stream)) + return -ENODATA; + + /* get circular buffer parameters */ + *data_ptr = buffer->stream.w_ptr; + *buffer_start = buffer->stream.addr; + *buffer_size = buffer->stream.size; + return 0; +} + +static int comp_buffer_commit_buffer(struct sof_sink *sink, size_t commit_size) +{ + struct comp_buffer *buffer = comp_buffer_get_from_sink(sink); + + if (commit_size) { + buffer_stream_writeback(buffer, commit_size); + audio_stream_produce(&buffer->stream, commit_size); + } + + return 0; +} + +static int comp_buffer_set_ipc_params(struct sof_audio_buffer *audio_buffer, + struct sof_ipc_stream_params *params, + bool force_update) +{ + struct comp_buffer *buffer = container_of(audio_buffer, struct comp_buffer, audio_buffer); + + return buffer_set_params(buffer, params, force_update); +} + +static int comp_buffer_format_set(struct sof_audio_buffer *audio_buffer) +{ + struct comp_buffer *buffer = container_of(audio_buffer, struct comp_buffer, audio_buffer); + + audio_stream_recalc_align(&buffer->stream); + return 0; +} + +static int comp_buffer_set_alignment_constants(struct sof_audio_buffer *audio_buffer, + const uint32_t byte_align, + const uint32_t frame_align_req) +{ + struct comp_buffer *buffer = container_of(audio_buffer, struct comp_buffer, audio_buffer); + + audio_stream_set_align(byte_align, frame_align_req, &buffer->stream); + return 0; +} + +static void comp_buffer_reset(struct sof_audio_buffer *audio_buffer) +{ + struct comp_buffer *buffer = container_of(audio_buffer, struct comp_buffer, audio_buffer); + + /* reset rw pointers and avail/free bytes counters */ + audio_stream_reset(&buffer->stream); + /* clear buffer contents */ + buffer_zero(buffer); +} + +/* free component in the pipeline */ +static void comp_buffer_free(struct sof_audio_buffer *audio_buffer) +{ + if (!audio_buffer) + return; + + CORE_CHECK_STRUCT(audio_buffer); + + struct comp_buffer *buffer = container_of(audio_buffer, struct comp_buffer, audio_buffer); + + buf_dbg(buffer, "entry"); + +#if CONFIG_PROBE + if (buffer->probe_cb_free) + buffer->probe_cb_free(buffer->probe_cb_arg); +#endif + + struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc; + +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + vregion_free(alloc->vreg, buffer->stream.addr); + else + sof_heap_free(alloc->heap, buffer->stream.addr); +#else + rfree(buffer->stream.addr); +#endif + + if (alloc && alloc->vreg) { + vregion_free(alloc->vreg, buffer); + if (!vregion_put(alloc->vreg)) + rfree(alloc); + } else { + sof_heap_free(alloc ? alloc->heap : NULL, buffer); + } +} + +APP_TASK_DATA static const struct source_ops comp_buffer_source_ops = { + .get_data_available = comp_buffer_get_data_available, + .get_data = comp_buffer_get_data, + .release_data = comp_buffer_release_data, + .audio_set_ipc_params = audio_buffer_source_set_ipc_params, + .on_audio_format_set = audio_buffer_source_on_audio_format_set, + .set_alignment_constants = audio_buffer_source_set_alignment_constants, +}; + +APP_TASK_DATA static const struct sink_ops comp_buffer_sink_ops = { + .get_free_size = comp_buffer_get_free_size, + .get_buffer = comp_buffer_get_buffer, + .commit_buffer = comp_buffer_commit_buffer, + .audio_set_ipc_params = audio_buffer_sink_set_ipc_params, + .on_audio_format_set = audio_buffer_sink_on_audio_format_set, + .set_alignment_constants = audio_buffer_sink_set_alignment_constants, + .get_lft = audio_buffer_sink_get_lft, +}; + +static const struct audio_buffer_ops audio_buffer_ops = { + .free = comp_buffer_free, + .reset = comp_buffer_reset, + .audio_set_ipc_params = comp_buffer_set_ipc_params, + .on_audio_format_set = comp_buffer_format_set, + .set_alignment_constants = comp_buffer_set_alignment_constants, +}; + +static struct comp_buffer *buffer_alloc_struct(struct mod_alloc_ctx *alloc, + void *stream_addr, size_t size, + uint32_t flags, bool is_shared) +{ + struct comp_buffer *buffer; + + tr_dbg(&buffer_tr, "entry"); + + /* allocate new buffer, but add coherent if shared with other cores */ + if (is_shared) + flags |= SOF_MEM_FLAG_COHERENT; + + if (!alloc || !alloc->vreg) + buffer = sof_heap_alloc(alloc ? alloc->heap : NULL, flags, sizeof(*buffer), 0); + else if (is_shared) + buffer = vregion_alloc_coherent(alloc->vreg, VREGION_MEM_TYPE_INTERIM, sizeof(*buffer)); + else + buffer = vregion_alloc(alloc->vreg, VREGION_MEM_TYPE_INTERIM, sizeof(*buffer)); + if (!buffer) { + tr_err(&buffer_tr, "could not alloc structure"); + return NULL; + } + + memset(buffer, 0, sizeof(*buffer)); + + buffer->flags = flags; + /* Force channels to 2 for init to prevent bad call to clz in buffer_init_stream */ + buffer->stream.runtime_stream_params.channels = 2; + + audio_buffer_init(&buffer->audio_buffer, BUFFER_TYPE_LEGACY_BUFFER, is_shared, + &comp_buffer_source_ops, &comp_buffer_sink_ops, &audio_buffer_ops, + &buffer->stream.runtime_stream_params); + + /* From here no more uncached access to the buffer object, except its list headers */ + audio_stream_set_addr(&buffer->stream, stream_addr); + buffer_init_stream(buffer, size); + + audio_stream_set_underrun(&buffer->stream, !!(flags & SOF_BUF_UNDERRUN_PERMITTED)); + audio_stream_set_overrun(&buffer->stream, !!(flags & SOF_BUF_OVERRUN_PERMITTED)); + buffer->audio_buffer.alloc = alloc; + + comp_buffer_reset_source_list(buffer); + comp_buffer_reset_sink_list(buffer); + + return buffer; +} + +struct comp_buffer *buffer_alloc(struct mod_alloc_ctx *alloc, size_t size, uint32_t flags, + uint32_t align, bool is_shared) +{ + struct comp_buffer *buffer; + void *stream_addr; + + tr_dbg(&buffer_tr, "entry"); + + /* validate request */ + if (size == 0) { + tr_err(&buffer_tr, "new size = %zu is invalid", size); + return NULL; + } + +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + stream_addr = vregion_alloc_align(alloc->vreg, VREGION_MEM_TYPE_INTERIM, size, align); + else + stream_addr = sof_heap_alloc(alloc->heap, flags, size, align); +#else + stream_addr = rballoc_align(flags, size, align); +#endif + if (!stream_addr) { + tr_err(&buffer_tr, "could not alloc size = %zu bytes of flags = 0x%x", + size, flags); + return NULL; + } + + buffer = buffer_alloc_struct(alloc, stream_addr, size, flags, is_shared); + if (!buffer) { + tr_err(&buffer_tr, "could not alloc buffer structure"); +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + vregion_free(alloc->vreg, stream_addr); + else + sof_heap_free(alloc->heap, stream_addr); +#else + rfree(stream_addr); +#endif + } + + return buffer; +} + +struct comp_buffer *buffer_alloc_range(struct mod_alloc_ctx *alloc, size_t preferred_size, + size_t minimum_size, + uint32_t flags, uint32_t align, bool is_shared) +{ + struct comp_buffer *buffer; + size_t size; + void *stream_addr = NULL; + + tr_dbg(&buffer_tr, "%zu -- %zu bytes", minimum_size, preferred_size); + + /* validate request */ + if (minimum_size == 0 || preferred_size < minimum_size) { + tr_err(&buffer_tr, "new size range %zu -- %zu is invalid", + minimum_size, preferred_size); + return NULL; + } + + /* Align preferred size to a multiple of the minimum size */ + if (preferred_size % minimum_size) + preferred_size += minimum_size - preferred_size % minimum_size; + + for (size = preferred_size; size >= minimum_size; size -= minimum_size) { +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + stream_addr = vregion_alloc_align(alloc->vreg, VREGION_MEM_TYPE_INTERIM, size, align); + else + stream_addr = sof_heap_alloc(alloc->heap, flags, size, align); +#else + stream_addr = rballoc_align(flags, size, align); +#endif + if (stream_addr) + break; + } + + tr_dbg(&buffer_tr, "allocated %zu bytes", size); + + if (!stream_addr) { + tr_err(&buffer_tr, "could not alloc size = %zu bytes of type = 0x%x", + minimum_size, flags); + return NULL; + } + + buffer = buffer_alloc_struct(alloc, stream_addr, size, flags, is_shared); + if (!buffer) { + tr_err(&buffer_tr, "could not alloc buffer structure"); +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + vregion_free(alloc->vreg, stream_addr); + else + sof_heap_free(alloc->heap, stream_addr); +#else + rfree(stream_addr); +#endif + } + + return buffer; +} + +void buffer_zero(struct comp_buffer *buffer) +{ + buf_dbg(buffer, "entry"); + CORE_CHECK_STRUCT(&buffer->audio_buffer); + + bzero(audio_stream_get_addr(&buffer->stream), audio_stream_get_size(&buffer->stream)); + if (buffer->flags & SOF_MEM_FLAG_DMA) + 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 *buffer, uint32_t size, uint32_t alignment) +{ + void *new_ptr = NULL; +#ifdef CONFIG_SOF_USERSPACE_LL + struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc; +#endif + + CORE_CHECK_STRUCT(&buffer->audio_buffer); + + /* validate request */ + if (size == 0) { + buf_err(buffer, "resize size = %u is invalid", size); + return -EINVAL; + } + + if (size == audio_stream_get_size(&buffer->stream)) + return 0; + +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + new_ptr = vregion_alloc_align(alloc->vreg, VREGION_MEM_TYPE_INTERIM, size, alignment); + else + new_ptr = sof_heap_alloc(alloc->heap, buffer->flags, size, alignment); +#else + new_ptr = rballoc_align(buffer->flags, size, alignment); +#endif + + /* we couldn't allocate bigger chunk */ + if (!new_ptr && size > audio_stream_get_size(&buffer->stream)) { + buf_err(buffer, "resize can't alloc %u bytes of flags 0x%x", + audio_stream_get_size(&buffer->stream), buffer->flags); + return -ENOMEM; + } + + /* use bigger chunk, else just use the old chunk but set smaller */ + if (new_ptr) { +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + vregion_free(alloc->vreg, audio_stream_get_addr(&buffer->stream)); + else + sof_heap_free(alloc->heap, audio_stream_get_addr(&buffer->stream)); +#else + rfree(audio_stream_get_addr(&buffer->stream)); +#endif + audio_stream_set_addr(&buffer->stream, new_ptr); + } + + buffer_init_stream(buffer, size); + + return 0; +} + +int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size, + uint32_t alignment) +{ + const size_t actual_size = audio_stream_get_size(&buffer->stream); + void *new_ptr = NULL; + size_t new_size; +#ifdef CONFIG_SOF_USERSPACE_LL + struct mod_alloc_ctx *alloc = buffer->audio_buffer.alloc; +#endif + + CORE_CHECK_STRUCT(&buffer->audio_buffer); + + /* validate request */ + if (minimum_size == 0 || preferred_size < minimum_size) { + buf_err(buffer, "resize size range %zu -- %zu is invalid", minimum_size, + preferred_size); + return -EINVAL; + } + + /* Align preferred size to a multiple of the minimum size */ + if (preferred_size % minimum_size) + preferred_size += minimum_size - preferred_size % minimum_size; + + if (preferred_size == actual_size) + return 0; + + for (new_size = preferred_size; new_size >= minimum_size; + new_size -= minimum_size) { +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + new_ptr = vregion_alloc_align(alloc->vreg, VREGION_MEM_TYPE_INTERIM, new_size, alignment); + else + new_ptr = sof_heap_alloc(alloc->heap, buffer->flags, new_size, alignment); +#else + new_ptr = rballoc_align(buffer->flags, new_size, alignment); +#endif + if (new_ptr) + break; + } + + /* we couldn't allocate bigger chunk */ + if (!new_ptr && new_size > actual_size) { + buf_err(buffer, "resize can't alloc %zu bytes of flags 0x%x", new_size, + buffer->flags); + return -ENOMEM; + } + + /* use bigger chunk, else just use the old chunk but set smaller */ + if (new_ptr) { +#ifdef CONFIG_SOF_USERSPACE_LL + assert(alloc); + if (alloc->vreg) + vregion_free(alloc->vreg, audio_stream_get_addr(&buffer->stream)); + else + sof_heap_free(alloc->heap, audio_stream_get_addr(&buffer->stream)); +#else + rfree(audio_stream_get_addr(&buffer->stream)); +#endif + audio_stream_set_addr(&buffer->stream, new_ptr); + } + + buffer_init_stream(buffer, new_size); + + return 0; +} + +int buffer_set_params(struct comp_buffer *buffer, + struct sof_ipc_stream_params *params, bool force_update) +{ + int ret; + int i; + + CORE_CHECK_STRUCT(&buffer->audio_buffer); + + if (!params) { + buf_err(buffer, "!params"); + return -EINVAL; + } + + if (audio_buffer_hw_params_configured(&buffer->audio_buffer) && !force_update) + return 0; + + ret = audio_stream_set_params(&buffer->stream, params); + if (ret < 0) { + buf_err(buffer, "audio_stream_set_params failed"); + return -EINVAL; + } + + audio_stream_set_buffer_fmt(&buffer->stream, params->buffer_fmt); + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + audio_buffer_set_chmap(&buffer->audio_buffer, i, params->chmap[i]); + + audio_buffer_set_hw_params_configured(&buffer->audio_buffer); + + return 0; +} +EXPORT_SYMBOL(buffer_set_params); + +bool buffer_params_match(struct comp_buffer *buffer, + struct sof_ipc_stream_params *params, uint32_t flag) +{ + assert(params); + CORE_CHECK_STRUCT(&buffer->audio_buffer); + + if ((flag & BUFF_PARAMS_FRAME_FMT) && + audio_stream_get_frm_fmt(&buffer->stream) != params->frame_fmt) + return false; + + if ((flag & BUFF_PARAMS_RATE) && + audio_stream_get_rate(&buffer->stream) != params->rate) + return false; + + if ((flag & BUFF_PARAMS_CHANNELS) && + audio_stream_get_channels(&buffer->stream) != params->channels) + return false; + + return true; +} + +void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes) +{ + /* return if no bytes */ + if (!bytes) { +#if CONFIG_SOF_LOG_DBG_BUFFER + struct comp_dev *src_component = comp_buffer_get_source_component(buffer); + struct comp_dev *sink_component = comp_buffer_get_sink_component(buffer); + + buf_dbg(buffer, "no bytes to produce, source->comp.id = %u, source->comp.type = %u, sink->comp.id = %u, sink->comp.type = %u", + src_component ? dev_comp_id(src_component) : (unsigned int)UINT32_MAX, + src_component ? dev_comp_type(src_component) : (unsigned int)UINT32_MAX, + sink_component ? dev_comp_id(sink_component) : (unsigned int)UINT32_MAX, + sink_component ? dev_comp_type(sink_component) : (unsigned int)UINT32_MAX); +#endif + return; + } + +#if CONFIG_PROBE + void *produce_begin = audio_stream_get_wptr(&buffer->stream); +#endif + + audio_stream_produce(&buffer->stream, bytes); + +#if CONFIG_PROBE + if (buffer->probe_cb_produce) { + struct buffer_cb_transact cb_data = { + .buffer = buffer, + .transaction_amount = bytes, + .transaction_begin_address = produce_begin, + }; + + buffer->probe_cb_produce(buffer->probe_cb_arg, &cb_data); + } +#endif + +#if CONFIG_SOF_LOG_DBG_BUFFER + buf_dbg(buffer, "((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) | audio_stream_get_size(&buffer->stream)); + buf_dbg(buffer, "((buffer->r_ptr - buffer->addr) << 16 | (buffer->w_ptr - buffer->addr)) = %08x", + ((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))); +#endif +} + +void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes) +{ + CORE_CHECK_STRUCT(&buffer->audio_buffer); + + /* return if no bytes */ + if (!bytes) { +#if CONFIG_SOF_LOG_DBG_BUFFER + struct comp_dev *src_component = comp_buffer_get_source_component(buffer); + struct comp_dev *sink_component = comp_buffer_get_sink_component(buffer); + + buf_dbg(buffer, "no bytes to consume, source->comp.id = %u, source->comp.type = %u, sink->comp.id = %u, sink->comp.type = %u", + src_component ? dev_comp_id(src_component) : (unsigned int)UINT32_MAX, + src_component ? dev_comp_type(src_component) : (unsigned int)UINT32_MAX, + sink_component ? dev_comp_id(sink_component) : (unsigned int)UINT32_MAX, + sink_component ? dev_comp_type(sink_component) : (unsigned int)UINT32_MAX); +#endif + return; + } + + audio_stream_consume(&buffer->stream, bytes); + +#if CONFIG_SOF_LOG_DBG_BUFFER + buf_dbg(buffer, "(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) | 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))); +#endif +} + +static inline struct list_item *buffer_comp_list(struct comp_buffer *buffer, + int dir) +{ + return dir == PPL_DIR_DOWNSTREAM ? + &buffer->source_list : &buffer->sink_list; +} + +/* + * Locking: must be called with interrupts disabled (or sys_mutex held for + * userspace LL builds)! Serialized IPCs protect us + * from racing attach / detach calls, but the scheduler can interrupt the IPC + * thread and begin using the buffer for streaming. FIXME: this is still a + * problem with different cores. + */ +void buffer_attach(struct comp_buffer *buffer, struct list_item *head, int dir) +{ + struct list_item *list = buffer_comp_list(buffer, dir); + CORE_CHECK_STRUCT(&buffer->audio_buffer); + list_item_prepend(list, head); +} + +/* + * Locking: must be called with interrupts disabled (or sys_mutex held for + * userspace LL builds)! See buffer_attach() above + * for details + */ +void buffer_detach(struct comp_buffer *buffer, struct list_item *head, int dir) +{ + struct list_item *buf_list = buffer_comp_list(buffer, dir); + CORE_CHECK_STRUCT(&buffer->audio_buffer); + list_item_del(buf_list); +} diff --git a/src/audio/buffers/ring_buffer.c b/src/audio/buffers/ring_buffer.c new file mode 100644 index 000000000000..fe67027df8db --- /dev/null +++ b/src/audio/buffers/ring_buffer.c @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// + +#include <sof/common.h> +#include <sof/trace/trace.h> +#include <sof/lib/uuid.h> +#include <sof/lib/vregion.h> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/ring_buffer.h> +#include <sof/audio/component.h> + +#include <rtos/alloc.h> +#include <ipc/topology.h> + +LOG_MODULE_REGISTER(ring_buffer, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(ring_buffer); +DECLARE_TR_CTX(ring_buffer_tr, SOF_UUID(ring_buffer_uuid), LOG_LEVEL_INFO); + +static inline struct ring_buffer *ring_buffer_from_sink(struct sof_sink *sink) +{ + struct sof_audio_buffer *audio_buffer = sof_audio_buffer_from_sink(sink); + + return container_of(audio_buffer, struct ring_buffer, audio_buffer); +} + +static inline struct ring_buffer *ring_buffer_from_source(struct sof_source *source) +{ + struct sof_audio_buffer *audio_buffer = sof_audio_buffer_from_source(source); + + return container_of(audio_buffer, struct ring_buffer, audio_buffer); +} + +/** + * @brief return true if the ring buffer is shared between 2 cores + */ +static inline +bool ring_buffer_is_shared(struct ring_buffer *ring_buffer) +{ + return audio_buffer_is_shared(&ring_buffer->audio_buffer); +} + +static inline uint8_t __sparse_cache *ring_buffer_buffer_end(struct ring_buffer *ring_buffer) +{ + return ring_buffer->_data_buffer + ring_buffer->data_buffer_size; +} + +static inline void ring_buffer_invalidate_shared(struct ring_buffer *ring_buffer, + void __sparse_cache *ptr, size_t size) +{ + /* no cache required in case of not shared queue */ + if (!ring_buffer_is_shared(ring_buffer)) + return; + + /* wrap-around? */ + if ((uintptr_t)ptr + size > (uintptr_t)ring_buffer_buffer_end(ring_buffer)) { + /* writeback till the end of circular buffer */ + dcache_invalidate_region + (ptr, (uintptr_t)ring_buffer_buffer_end(ring_buffer) - (uintptr_t)ptr); + size -= (uintptr_t)ring_buffer_buffer_end(ring_buffer) - (uintptr_t)ptr; + ptr = ring_buffer->_data_buffer; + } + /* invalidate rest of data */ + dcache_invalidate_region(ptr, size); +} + +static inline void ring_buffer_writeback_shared(struct ring_buffer *ring_buffer, + void __sparse_cache *ptr, size_t size) +{ + /* no cache required in case of not shared queue */ + if (!ring_buffer_is_shared(ring_buffer)) + return; + + /* wrap-around? */ + if ((uintptr_t)ptr + size > (uintptr_t)ring_buffer_buffer_end(ring_buffer)) { + /* writeback till the end of circular buffer */ + dcache_writeback_region + (ptr, (uintptr_t)ring_buffer_buffer_end(ring_buffer) - (uintptr_t)ptr); + size -= (uintptr_t)ring_buffer_buffer_end(ring_buffer) - (uintptr_t)ptr; + ptr = ring_buffer->_data_buffer; + } + /* writeback rest of data */ + dcache_writeback_region(ptr, size); +} + + +/** + * @brief remove the queue from the list, free memory + */ +static void ring_buffer_free(struct sof_audio_buffer *audio_buffer) +{ + if (!audio_buffer) + return; + + struct ring_buffer *ring_buffer = container_of(audio_buffer, + struct ring_buffer, audio_buffer); + struct mod_alloc_ctx *alloc = audio_buffer->alloc; + + if (alloc->vreg) { + vregion_free(alloc->vreg, (__sparse_force void *)ring_buffer->_data_buffer); + vregion_free(alloc->vreg, ring_buffer); + } else { + sof_heap_free(alloc->heap, (__sparse_force void *)ring_buffer->_data_buffer); + sof_heap_free(alloc->heap, ring_buffer); + } +} + +static void ring_buffer_reset(struct sof_audio_buffer *audio_buffer) +{ + struct ring_buffer *ring_buffer = + container_of(audio_buffer, struct ring_buffer, audio_buffer); + + ring_buffer->_write_offset = 0; + ring_buffer->_read_offset = 0; + + ring_buffer_invalidate_shared(ring_buffer, ring_buffer->_data_buffer, + ring_buffer->data_buffer_size); + bzero((__sparse_force void *)ring_buffer->_data_buffer, ring_buffer->data_buffer_size); + ring_buffer_writeback_shared(ring_buffer, ring_buffer->_data_buffer, + ring_buffer->data_buffer_size); +} + +static inline +uint8_t __sparse_cache *ring_buffer_get_pointer(struct ring_buffer *ring_buffer, size_t offset) +{ + /* check if offset is not in "double area" + * lines below do a quicker version of offset %= ring_buffer->data_buffer_size; + */ + if (offset >= ring_buffer->data_buffer_size) + offset -= ring_buffer->data_buffer_size; + return ring_buffer->_data_buffer + offset; +} + +static inline +size_t ring_buffer_inc_offset(struct ring_buffer *ring_buffer, size_t offset, size_t inc) +{ + assert(inc <= ring_buffer->data_buffer_size); + offset += inc; + /* wrap around ? 2*size because of "double area" */ + if (offset >= 2 * ring_buffer->data_buffer_size) + offset -= 2 * ring_buffer->data_buffer_size; + return offset; +} + +static inline +size_t _ring_buffer_get_data_available(struct ring_buffer *ring_buffer) +{ + int32_t avail_data = ring_buffer->_write_offset - ring_buffer->_read_offset; + /* wrap around ? 2*size because of "double area" */ + if (avail_data < 0) + avail_data = 2 * ring_buffer->data_buffer_size + avail_data; + + return avail_data; +} + +static size_t ring_buffer_get_data_available(struct sof_source *source) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_source(source); + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + return _ring_buffer_get_data_available(ring_buffer); +} + +static size_t ring_buffer_get_free_size(struct sof_sink *sink) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_sink(sink); + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + return ring_buffer->data_buffer_size - _ring_buffer_get_data_available(ring_buffer); +} + +static int ring_buffer_get_buffer(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_sink(sink); + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + if (req_size > ring_buffer_get_free_size(sink)) + return -ENODATA; + + /* note, __sparse_force is to be removed once sink/src use __sparse_cache for data ptrs */ + *data_ptr = (__sparse_force void *)ring_buffer_get_pointer(ring_buffer, + ring_buffer->_write_offset); + *buffer_start = (__sparse_force void *)ring_buffer->_data_buffer; + *buffer_size = ring_buffer->data_buffer_size; + + /* no need to invalidate cache - buffer is to be written only */ + return 0; +} + +static int ring_buffer_commit_buffer(struct sof_sink *sink, size_t commit_size) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_sink(sink); + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + if (commit_size) { + ring_buffer_writeback_shared(ring_buffer, + ring_buffer_get_pointer(ring_buffer, + ring_buffer->_write_offset), + commit_size); + + /* move write pointer */ + ring_buffer->_write_offset = ring_buffer_inc_offset(ring_buffer, + ring_buffer->_write_offset, + commit_size); + } + + return 0; +} + +static int ring_buffer_get_data(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, + size_t *buffer_size) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_source(source); + __sparse_cache void *data_ptr_c; + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + if (req_size > ring_buffer_get_data_available(source)) + return -ENODATA; + + data_ptr_c = ring_buffer_get_pointer(ring_buffer, ring_buffer->_read_offset); + + /* clean cache in provided data range */ + ring_buffer_invalidate_shared(ring_buffer, data_ptr_c, req_size); + + *buffer_start = (__sparse_force void *)ring_buffer->_data_buffer; + *buffer_size = ring_buffer->data_buffer_size; + *data_ptr = (__sparse_force void *)data_ptr_c; + + return 0; +} + +static int ring_buffer_release_data(struct sof_source *source, size_t free_size) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_source(source); + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + if (free_size) { + /* data consumed, free buffer space, no need for any special cache operations */ + ring_buffer->_read_offset = ring_buffer_inc_offset(ring_buffer, + ring_buffer->_read_offset, + free_size); + } + + return 0; +} + +int ring_buffer_module_unbind(struct sof_sink *sink) +{ + struct ring_buffer *ring_buffer = ring_buffer_from_sink(sink); + + CORE_CHECK_STRUCT(&ring_buffer->audio_buffer); + + /* in case of disconnection, invalidate all cache. This method is guaranteed be called on + * core that have been using sink API + */ + ring_buffer_invalidate_shared(ring_buffer, ring_buffer->_data_buffer, + ring_buffer->data_buffer_size); + + return 0; +} + +static const struct source_ops ring_buffer_source_ops = { + .get_data_available = ring_buffer_get_data_available, + .get_data = ring_buffer_get_data, + .release_data = ring_buffer_release_data, + .audio_set_ipc_params = audio_buffer_source_set_ipc_params, + .on_audio_format_set = audio_buffer_source_on_audio_format_set, + .set_alignment_constants = audio_buffer_source_set_alignment_constants, +}; + +static const struct sink_ops ring_buffer_sink_ops = { + .get_free_size = ring_buffer_get_free_size, + .get_buffer = ring_buffer_get_buffer, + .commit_buffer = ring_buffer_commit_buffer, + .on_unbind = ring_buffer_module_unbind, + .audio_set_ipc_params = audio_buffer_sink_set_ipc_params, + .on_audio_format_set = audio_buffer_sink_on_audio_format_set, + .set_alignment_constants = audio_buffer_sink_set_alignment_constants, + .get_lft = audio_buffer_sink_get_lft, +}; + +static const struct audio_buffer_ops audio_buffer_ops = { + .free = ring_buffer_free, + .reset = ring_buffer_reset, +}; + +struct ring_buffer *ring_buffer_create(struct comp_dev *dev, size_t min_available, + size_t min_free_space, bool is_shared, + uint32_t id) +{ + struct ring_buffer *ring_buffer; + struct mod_alloc_ctx *alloc = dev->mod->priv.resources.alloc; + struct k_heap *heap = alloc->heap; + struct vregion *vreg = alloc->vreg; + int memory_flags = (is_shared ? SOF_MEM_FLAG_COHERENT : 0) | + user_get_buffer_memory_region(dev->drv); + + /* allocate ring_buffer structure */ + if (!vreg) + ring_buffer = sof_heap_alloc(heap, memory_flags, sizeof(*ring_buffer), 0); + else if (is_shared) + ring_buffer = vregion_alloc_coherent(vreg, VREGION_MEM_TYPE_INTERIM, sizeof(*ring_buffer)); + else + ring_buffer = vregion_alloc(vreg, VREGION_MEM_TYPE_INTERIM, sizeof(*ring_buffer)); + if (!ring_buffer) + return NULL; + + memset(ring_buffer, 0, sizeof(*ring_buffer)); + + /* init base structure. The audio_stream_params is NULL because ring_buffer + * is currently used as a secondary buffer for DP only + * + * pointer in audio_buffer will be overwritten when attaching ring_buffer as a + * secondary buffer + */ + audio_buffer_init(&ring_buffer->audio_buffer, BUFFER_TYPE_RING_BUFFER, + is_shared, &ring_buffer_source_ops, &ring_buffer_sink_ops, + &audio_buffer_ops, NULL); + ring_buffer->audio_buffer.alloc = alloc; + ring_buffer->audio_buffer.alloc->heap = heap; + + /* set obs/ibs in sink/source interfaces */ + sink_set_min_free_space(audio_buffer_get_sink(&ring_buffer->audio_buffer), + min_free_space); + source_set_min_available(audio_buffer_get_source(&ring_buffer->audio_buffer), + min_available); + + uint32_t max_ibs_obs = MAX(min_available, min_free_space); + + /* Calculate required buffer size. This buffer must hold at least three times max_ibs_obs + * bytes to avoid starving the DP modules that process different block sizes in different + * periods (44.1 kHz case). + * + * The following example consists of one pipeline processed on core 0. One of the modules + * of this pipeline is a DP module, which processing is performed on core 1. + * DP module threads are started after LL processing on a given core is completed. + * + * An example of a DP module is src lite, which converts a 32-bit stereo stream with + * a sampling rate of 44.1 kHz to a rate of 16 kHz. With a period of 1 ms, the module should + * process 44.1 frames. In reality, this module processes 42 frames (336 bytes) for + * 9 periods and then processes 63 frames (504 bytes) for the tenth period. In this way, + * on average, over 10 periods, the module processes 44.1 frames. + * + * Consider the case of a 768-byte buffer (max_ibs_obs = 384) that is completely filled + * with samples. In the first period, the module consumes 336 bytes. The buffer is not + * replenished because the consumption occurred in the DP cycle, which is executed after + * the LL cycle. Data is transferred between modules in the pipeline during the LL cycle. + * The figure below shows the next period of the ongoing processing. + * + * /-----------------------------------------------------------------\ + * | Core 0 | [ LL 0 (B) ] [ DP 0 ] | + * |------------------------------------------------------------------ + * | Core 1 | [ LL 1 ] (A) [ DP 1 ] (C) | + * \-----------------------------------------------------------------/ + * + * A. The DP module on core 1 has 432 bytes available in the input buffer, so it can only + * process a block of 336 bytes. It is unable to process a block of 502 bytes. + * The module starts processing data. + * + * B. Pipeline processing on core 0 reaches the point where more data is delivered to + * the DP module source buffer, and processed data is received from the sink buffer. + * The source buffer has 336 free bytes, and that is how many are copied. + * + * C. The DP module finishes processing data and flushes 336 bytes from the source buffer. + * Since this buffer has just been completely filled, there are again left only + * 432 bytes available at the end of the period. + * + * As shown in the above example, the DP module will eventually be starved, causing a glitch + * in the output signal. To resolve this situation and allow the module to process + * correctly, it is necessary to allocate a buffer three times larger than max_ibs_obs. + */ + ring_buffer->data_buffer_size = 3 * max_ibs_obs; + + /* allocate data buffer - always in cached memory alias */ + ring_buffer->data_buffer_size = ALIGN_UP(ring_buffer->data_buffer_size, + PLATFORM_DCACHE_ALIGN); + + void *data_buf; + + if (vreg) + data_buf = vregion_alloc_align(vreg, VREGION_MEM_TYPE_INTERIM, ring_buffer->data_buffer_size, + PLATFORM_DCACHE_ALIGN); + else + data_buf = sof_heap_alloc(heap, user_get_buffer_memory_region(dev->drv), + ring_buffer->data_buffer_size, PLATFORM_DCACHE_ALIGN); + + if (!data_buf) + goto err; + + ring_buffer->_data_buffer = (__sparse_force __sparse_cache void *)data_buf; + + tr_info(&ring_buffer_tr, "Ring buffer created, id: %u shared: %u min_available: %u min_free_space %u, size %u", + id, ring_buffer_is_shared(ring_buffer), min_available, min_free_space, + ring_buffer->data_buffer_size); + + /* return a pointer to allocated structure */ + return ring_buffer; +err: + tr_err(&ring_buffer_tr, "Ring buffer creation failure"); + if (vreg) + vregion_free(vreg, ring_buffer); + else + sof_heap_free(heap, ring_buffer); + return NULL; +} diff --git a/src/audio/chain_dma.c b/src/audio/chain_dma.c new file mode 100644 index 000000000000..4610845b5a42 --- /dev/null +++ b/src/audio/chain_dma.c @@ -0,0 +1,701 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Piotr Makaruk <piotr.makaruk@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <ipc/dai.h> +#include <ipc4/gateway.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <ipc4/error_status.h> +#include <ipc4/module.h> +#include <ipc4/pipeline.h> +#include <sof/ut.h> +#include <zephyr/pm/policy.h> +#include <rtos/init.h> +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE +#include <ipc4/notification.h> +#endif + +#define DT_NUM_HDA_HOST_IN DT_PROP(DT_INST(0, intel_adsp_hda_host_in), dma_channels) +#define DT_NUM_HDA_HOST_OUT DT_PROP(DT_INST(0, intel_adsp_hda_host_out), dma_channels) + +#define DT_NUM_HDA_LINK_IN DT_PROP(DT_INST(0, intel_adsp_hda_link_in), dma_channels) +#define DT_NUM_HDA_LINK_OUT DT_PROP(DT_INST(0, intel_adsp_hda_link_out), dma_channels) + +static const struct comp_driver comp_chain_dma; +static const uint32_t max_chain_number = DT_NUM_HDA_HOST_OUT + DT_NUM_HDA_HOST_IN; + +LOG_MODULE_REGISTER(chain_dma, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(chain_dma); +DECLARE_TR_CTX(chain_dma_tr, SOF_UUID(chain_dma_uuid), LOG_LEVEL_INFO); + +/* chain dma component private data */ +struct chain_dma_data { + bool first_data_received; + /* node id of host HD/A DMA */ + union ipc4_connector_node_id host_connector_node_id; + /* node id of link HD/A DMA */ + union ipc4_connector_node_id link_connector_node_id; + uint32_t *hw_buffer; + struct task chain_task; + enum sof_ipc_stream_direction stream_direction; + /* container size in bytes */ + uint8_t cs; +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + bool xrun_notification_sent; +#endif + + /* local host DMA config */ + struct sof_dma *dma_host; + struct dma_chan_data *chan_host; + struct dma_config z_config_host; + struct dma_block_config dma_block_cfg_host; + + /* local link DMA config */ + struct sof_dma *dma_link; + struct dma_chan_data *chan_link; + struct dma_config z_config_link; + struct dma_block_config dma_block_cfg_link; + + struct comp_buffer *dma_buffer; +}; + +static int chain_host_start(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_start(cd->chan_host->dma->z_dev, cd->chan_host->index); + if (err < 0) + return err; + + comp_info(dev, "dma_start() host chan_index = %u", + cd->chan_host->index); + return 0; +} + +static int chain_link_start(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_start(cd->chan_link->dma->z_dev, cd->chan_link->index); + if (err < 0) + return err; + + comp_info(dev, "dma_start() link chan_index = %u", + cd->chan_link->index); + return 0; +} + +static int chain_link_stop(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_stop(cd->chan_link->dma->z_dev, cd->chan_link->index); + if (err < 0) + return err; + + comp_info(dev, "dma_stop() link chan_index = %u", + cd->chan_link->index); + + return 0; +} + +static int chain_host_stop(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int err; + + err = dma_stop(cd->chan_host->dma->z_dev, cd->chan_host->index); + if (err < 0) + return err; + + comp_info(dev, "dma_stop() host chan_index = %u", + cd->chan_host->index); + + return 0; +} + +/* Get size of data, which was consumed by link */ +static size_t chain_get_transferred_data_size(const uint32_t out_read_pos, const uint32_t in_read_pos, + const size_t buff_size) +{ + if (out_read_pos >= in_read_pos) + return out_read_pos - in_read_pos; + + return buff_size - in_read_pos + out_read_pos; +} + +/* get status from dma and check for xrun */ +static int chain_get_dma_status(struct chain_dma_data *cd, struct dma_chan_data *chan, + struct dma_status *stat) +{ + int ret = dma_get_status(chan->dma->z_dev, chan->index, stat); +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + if (ret == -EPIPE && !cd->xrun_notification_sent) { + cd->xrun_notification_sent = send_gateway_xrun_notif_msg + (cd->link_connector_node_id.dw, cd->stream_direction); + } else if (!ret) { + cd->xrun_notification_sent = false; + } +#endif + return ret; +} + +static enum task_state chain_task_run(void *data) +{ + size_t link_avail_bytes, link_free_bytes, host_avail_bytes, host_free_bytes; + struct chain_dma_data *cd = data; + uint32_t link_read_pos, host_read_pos; + struct dma_status stat; + uint32_t link_type; + int ret; + + /* Link DMA can return -EPIPE and current status if xrun occurs, then it is not critical + * and flow shall continue. Other error values will be treated as critical. + */ + ret = chain_get_dma_status(cd, cd->chan_link, &stat); + switch (ret) { + case 0: + break; + case -EPIPE: + tr_warn(&chain_dma_tr, "dma_get_status() link xrun occurred," + " ret = %d", ret); + break; + default: + tr_err(&chain_dma_tr, "dma_get_status() error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + + link_avail_bytes = stat.pending_length; + link_free_bytes = stat.free; + link_read_pos = stat.read_position; + + /* Host DMA does not report xruns. All error values will be treated as critical. */ + ret = chain_get_dma_status(cd, cd->chan_host, &stat); + if (ret < 0) { + tr_err(&chain_dma_tr, "dma_get_status() error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + + host_avail_bytes = stat.pending_length; + host_free_bytes = stat.free; + host_read_pos = stat.read_position; + + link_type = cd->link_connector_node_id.f.dma_type; + if (link_type == ipc4_hda_link_input_class) { + /* CAPTURE: + * When chained Link Input with Host Input immediately start transmitting data + * to host. In this mode task will always stream to host as much data as possible + */ + const size_t increment = MIN(host_free_bytes, link_avail_bytes); + + ret = dma_reload(cd->chan_host->dma->z_dev, cd->chan_host->index, 0, 0, increment); + if (ret < 0) { + tr_err(&chain_dma_tr, + "dma_reload() host error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + + ret = dma_reload(cd->chan_link->dma->z_dev, cd->chan_link->index, 0, 0, increment); + if (ret < 0) { + tr_err(&chain_dma_tr, + "dma_reload() link error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + } else { + /* PLAYBACK: + * When chained Host Output with Link Output then wait for half buffer full. In this + * 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 buff_size = audio_stream_get_size(&cd->dma_buffer->stream); + const size_t half_buff_size = buff_size / 2; + + if (!cd->first_data_received && host_avail_bytes > half_buff_size) { + ret = dma_reload(cd->chan_link->dma->z_dev, + cd->chan_link->index, 0, 0, + MIN(host_avail_bytes, link_free_bytes)); + if (ret < 0) { + tr_err(&chain_dma_tr, + "dma_reload() link error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + cd->first_data_received = true; + + } else if (cd->first_data_received) { + const size_t transferred = + chain_get_transferred_data_size(link_read_pos, + host_read_pos, + buff_size); + + ret = dma_reload(cd->chan_host->dma->z_dev, cd->chan_host->index, + 0, 0, transferred); + if (ret < 0) { + tr_err(&chain_dma_tr, + "dma_reload() host error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + + if (host_avail_bytes >= half_buff_size && + link_free_bytes >= half_buff_size) { + ret = dma_reload(cd->chan_link->dma->z_dev, cd->chan_link->index, + 0, 0, half_buff_size); + if (ret < 0) { + tr_err(&chain_dma_tr, + "dma_reload() link error, ret = %d", ret); + return SOF_TASK_STATE_COMPLETED; + } + } + } + } + return SOF_TASK_STATE_RESCHEDULE; +} + +static int chain_task_start(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int ret; + + comp_info(dev, "host_dma_id = 0x%08x", cd->host_connector_node_id.dw); + + switch (cd->chain_task.state) { + case SOF_TASK_STATE_QUEUED: + return 0; + case SOF_TASK_STATE_COMPLETED: + break; + case SOF_TASK_STATE_INIT: + break; + case SOF_TASK_STATE_FREE: + break; + default: + comp_err(dev, "bad state transition"); + return -EINVAL; + } + + if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { + ret = chain_host_start(dev); + if (ret) + return ret; + ret = chain_link_start(dev); + if (ret) { + chain_host_stop(dev); + return ret; + } + } else { + ret = chain_link_start(dev); + if (ret) + return ret; + ret = chain_host_start(dev); + if (ret) { + chain_link_stop(dev); + return ret; + } + } + + ret = schedule_task_init_ll(&cd->chain_task, SOF_UUID(chain_dma_uuid), + SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_HIGH, + chain_task_run, cd, 0, 0); + if (ret < 0) { + comp_err(dev, "ll task initialization failed"); + goto error_task; + } + + ret = schedule_task(&cd->chain_task, 0, 0); + if (ret < 0) { + comp_err(dev, "ll schedule task failed"); + schedule_task_free(&cd->chain_task); + goto error_task; + } + + pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + + return 0; + +error_task: + chain_host_stop(dev); + chain_link_stop(dev); + + return ret; +} + +static int chain_task_pause(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + int ret, ret2; + + if (cd->chain_task.state == SOF_TASK_STATE_FREE) + return 0; + + cd->first_data_received = false; + if (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) { + ret = chain_host_stop(dev); + ret2 = chain_link_stop(dev); + } else { + ret = chain_link_stop(dev); + ret2 = chain_host_stop(dev); + } + if (!ret) + ret = ret2; + + schedule_task_free(&cd->chain_task); + pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + + return ret; +} + +__cold static void chain_release(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + + assert_can_be_cold(); + + dma_release_channel(cd->chan_host->dma->z_dev, cd->chan_host->index); + sof_dma_put(cd->dma_host); + dma_release_channel(cd->chan_link->dma->z_dev, cd->chan_link->index); + sof_dma_put(cd->dma_link); + + if (cd->dma_buffer) { + buffer_free(cd->dma_buffer); + cd->dma_buffer = NULL; + } +} + +/* Retrieves host connector node id from dma id */ +__cold static int get_connector_node_id(uint32_t dma_id, bool host_type, + union ipc4_connector_node_id *connector_node_id) +{ + uint32_t max_out, max_in; + uint8_t type, type2; + + assert_can_be_cold(); + + if (host_type) { + type = ipc4_hda_host_output_class; + type2 = ipc4_hda_host_input_class; + max_out = DT_NUM_HDA_HOST_OUT; + max_in = DT_NUM_HDA_HOST_IN; + } else { + type = ipc4_hda_link_output_class; + type2 = ipc4_hda_link_input_class; + max_out = DT_NUM_HDA_LINK_OUT; + max_in = DT_NUM_HDA_LINK_IN; + } + + if (dma_id >= max_out) { + type = type2; + dma_id -= max_out; + if (dma_id >= max_in) + return -EINVAL; + } + connector_node_id->dw = 0; + connector_node_id->f.dma_type = type; + connector_node_id->f.v_index = dma_id; + + return 0; +} + +__cold static int chain_init(struct comp_dev *dev, void *addr, size_t length) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + struct dma_block_config *dma_block_cfg_host = &cd->dma_block_cfg_host; + struct dma_block_config *dma_block_cfg_link = &cd->dma_block_cfg_link; + struct dma_config *dma_cfg_host = &cd->z_config_host; + struct dma_config *dma_cfg_link = &cd->z_config_link; + int channel; + int err; + + assert_can_be_cold(); + + memset(dma_cfg_host, 0, sizeof(*dma_cfg_host)); + memset(dma_block_cfg_host, 0, sizeof(*dma_block_cfg_host)); + dma_cfg_host->block_count = 1; + dma_cfg_host->source_data_size = cd->cs; + dma_cfg_host->dest_data_size = cd->cs; + dma_cfg_host->head_block = dma_block_cfg_host; + dma_block_cfg_host->block_size = length; + + memset(dma_cfg_link, 0, sizeof(*dma_cfg_link)); + memset(dma_block_cfg_link, 0, sizeof(*dma_block_cfg_link)); + dma_cfg_link->block_count = 1; + dma_cfg_link->source_data_size = cd->cs; + dma_cfg_link->dest_data_size = cd->cs; + dma_cfg_link->head_block = dma_block_cfg_link; + dma_block_cfg_link->block_size = length; + + switch (cd->stream_direction) { + case SOF_IPC_STREAM_PLAYBACK: + dma_cfg_host->channel_direction = HOST_TO_MEMORY; + dma_block_cfg_host->dest_address = (uint32_t)addr; + dma_cfg_link->channel_direction = MEMORY_TO_PERIPHERAL; + dma_block_cfg_link->source_address = (uint32_t)addr; + break; + case SOF_IPC_STREAM_CAPTURE: + dma_cfg_host->channel_direction = MEMORY_TO_HOST; + dma_block_cfg_host->source_address = (uint32_t)addr; + dma_cfg_link->channel_direction = PERIPHERAL_TO_MEMORY; + dma_block_cfg_link->dest_address = (uint32_t)addr; + break; + } + + /* get host DMA channel */ + channel = cd->host_connector_node_id.f.v_index; + channel = dma_request_channel(cd->dma_host->z_dev, &channel); + if (channel < 0) { + comp_err(dev, "host dma_request_channel() failed for %u", + cd->host_connector_node_id.f.v_index); + return channel; + } + + cd->chan_host = &cd->dma_host->chan[channel]; + + err = dma_config(cd->dma_host->z_dev, cd->chan_host->index, dma_cfg_host); + if (err < 0) { + comp_err(dev, "host dma_config() failed for %d", channel); + goto error_host; + } + + /* get link DMA channel */ + channel = cd->link_connector_node_id.f.v_index; + channel = dma_request_channel(cd->dma_link->z_dev, &channel); + if (channel < 0) { + comp_err(dev, "link dma_request_channel() failed for %u", + cd->link_connector_node_id.f.v_index); + err = channel; + goto error_host; + } + + cd->chan_link = &cd->dma_link->chan[channel]; + + err = dma_config(cd->dma_link->z_dev, cd->chan_link->index, dma_cfg_link); + if (err < 0) { + comp_err(dev, "link dma_config() failed for %d", channel); + goto error_link; + } + return 0; + +error_link: + dma_release_channel(cd->dma_link->z_dev, cd->chan_link->index); + cd->chan_link = NULL; +error_host: + dma_release_channel(cd->dma_host->z_dev, cd->chan_host->index); + cd->chan_host = NULL; + return err; +} + +__cold static int chain_task_init(struct comp_dev *dev, uint8_t host_dma_id, uint8_t link_dma_id, + uint32_t fifo_size) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + uint32_t addr_align; + size_t buff_size; + void *buff_addr; + uint32_t dir; + int ret; + + assert_can_be_cold(); + + ret = get_connector_node_id(host_dma_id, true, &cd->host_connector_node_id); + if (ret < 0) + return ret; + + ret = get_connector_node_id(link_dma_id, false, &cd->link_connector_node_id); + if (ret < 0) + return ret; + + /* Verify whether HDA gateways can be chained */ + if (cd->host_connector_node_id.f.dma_type == ipc4_hda_host_output_class) { + if (cd->link_connector_node_id.f.dma_type != ipc4_hda_link_output_class) + return -EINVAL; + cd->stream_direction = SOF_IPC_STREAM_PLAYBACK; + } + if (cd->host_connector_node_id.f.dma_type == ipc4_hda_host_input_class) { + if (cd->link_connector_node_id.f.dma_type != ipc4_hda_link_input_class) + return -EINVAL; + cd->stream_direction = SOF_IPC_STREAM_CAPTURE; + } + + /* request HDA DMA with shared access privilege */ + dir = (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) ? + SOF_DMA_DIR_HMEM_TO_LMEM : SOF_DMA_DIR_LMEM_TO_HMEM; + + cd->dma_host = sof_dma_get(dir, 0, SOF_DMA_DEV_HOST, SOF_DMA_ACCESS_SHARED); + if (!cd->dma_host) { + comp_err(dev, "dma_get() returned NULL"); + return -EINVAL; + } + + dir = (cd->stream_direction == SOF_IPC_STREAM_PLAYBACK) ? + SOF_DMA_DIR_MEM_TO_DEV : SOF_DMA_DIR_DEV_TO_MEM; + + cd->dma_link = sof_dma_get(dir, SOF_DMA_CAP_HDA, SOF_DMA_DEV_HDA, SOF_DMA_ACCESS_SHARED); + if (!cd->dma_link) { + sof_dma_put(cd->dma_host); + comp_err(dev, "dma_get() returned NULL"); + return -EINVAL; + } + + /* retrieve DMA buffer address alignment */ + ret = dma_get_attribute(cd->dma_host->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (ret < 0) { + comp_err(dev, + "could not get dma buffer address alignment, err = %d", ret); + goto error; + } + + switch (cd->link_connector_node_id.f.dma_type) { + case ipc4_hda_link_input_class: + /* Increasing buffer size for capture path as L1SEN exit takes sometimes + * more than expected. To prevent from glitches and DMA overruns buffer + * is increased 5 times. + */ + fifo_size *= 5; + break; + case ipc4_hda_link_output_class: + /* Increasing buffer size for playback path as L1SEN exit takes sometimes + * more that expected + * Note, FIFO size must be smaller than half of host buffer size + * (20ms ping pong) to avoid problems with position reporting + * Size increase from default 2ms to 5ms is enough. + */ + fifo_size *= 5; + fifo_size /= 2; + break; + } + + fifo_size = ALIGN_UP_INTERNAL(fifo_size, addr_align); + /* allocate not shared buffer */ + cd->dma_buffer = buffer_alloc(NULL, fifo_size, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + addr_align, BUFFER_USAGE_NOT_SHARED); + + if (!cd->dma_buffer) { + comp_err(dev, "failed to alloc dma buffer"); + ret = -EINVAL; + goto error; + } + + /* clear dma buffer */ + buffer_zero(cd->dma_buffer); + buff_addr = audio_stream_get_addr(&cd->dma_buffer->stream); + buff_size = audio_stream_get_size(&cd->dma_buffer->stream); + + ret = chain_init(dev, buff_addr, buff_size); + if (ret < 0) { + buffer_free(cd->dma_buffer); + cd->dma_buffer = NULL; + goto error; + } + + cd->chain_task.state = SOF_TASK_STATE_INIT; + + return 0; +error: + sof_dma_put(cd->dma_host); + sof_dma_put(cd->dma_link); + return ret; +} + +static int chain_task_trigger(struct comp_dev *dev, int cmd) +{ + switch (cmd) { + case COMP_TRIGGER_START: + return chain_task_start(dev); + case COMP_TRIGGER_PAUSE: + return chain_task_pause(dev); + default: + return -EINVAL; + } +} + +__cold static struct comp_dev *chain_task_create(const struct comp_driver *drv, + const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config) +{ + const struct ipc4_chain_dma *cdma = (struct ipc4_chain_dma *)ipc_specific_config; + const uint32_t host_dma_id = cdma->primary.r.host_dma_id; + const uint32_t link_dma_id = cdma->primary.r.link_dma_id; + const uint32_t fifo_size = cdma->extension.r.fifo_size; + const bool scs = cdma->primary.r.scs; + struct chain_dma_data *cd; + struct comp_dev *dev; + int ret; + + assert_can_be_cold(); + + if (host_dma_id >= max_chain_number) + return NULL; + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) + goto error; + + cd->first_data_received = false; + cd->cs = scs ? 2 : 4; + cd->chain_task.state = SOF_TASK_STATE_INIT; + + comp_set_drvdata(dev, cd); + + ret = chain_task_init(dev, host_dma_id, link_dma_id, fifo_size); + if (!ret) + return dev; + + rfree(cd); +error: + comp_free_device(dev); + return NULL; +} + +__cold static void chain_task_free(struct comp_dev *dev) +{ + struct chain_dma_data *cd = comp_get_drvdata(dev); + + assert_can_be_cold(); + + chain_release(dev); + rfree(cd); + comp_free_device(dev); +} + +static const struct comp_driver comp_chain_dma = { + .uid = SOF_RT_UUID(chain_dma_uuid), + .tctx = &chain_dma_tr, + .ops = { + .create = chain_task_create, + .trigger = chain_task_trigger, + .free = chain_task_free, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_chain_dma_info = { + .drv = &comp_chain_dma, +}; + +UT_STATIC void sys_comp_chain_dma_init(void) +{ + comp_register(platform_shared_get(&comp_chain_dma_info, + sizeof(comp_chain_dma_info))); +} + +DECLARE_MODULE(sys_comp_chain_dma_init); +SOF_MODULE_INIT(chain_dma, sys_comp_chain_dma_init); diff --git a/src/audio/channel_map.c b/src/audio/channel_map.c index eeaed256e7c3..b743fdacb0cd 100644 --- a/src/audio/channel_map.c +++ b/src/audio/channel_map.c @@ -5,14 +5,21 @@ // Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> #include <sof/audio/channel_map.h> +#include <sof/lib/uuid.h> #include <sof/trace/trace.h> #include <user/trace.h> -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/common.h> #include <ipc/channel_map.h> #include <stdint.h> #include <stdlib.h> +LOG_MODULE_REGISTER(channel_map, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(chmap); + +DECLARE_TR_CTX(chmap_tr, SOF_UUID(chmap_uuid), LOG_LEVEL_INFO); + struct sof_ipc_channel_map *chmap_get(struct sof_ipc_stream_map *smap, int index) { @@ -21,9 +28,8 @@ struct sof_ipc_channel_map *chmap_get(struct sof_ipc_stream_map *smap, uint32_t byte = 0; if (index >= smap->num_ch_map) { - trace_error(TRACE_CLASS_CHMAP, "chmap_get() error: " - "index %d out of bounds %d", - index, smap->num_ch_map); + tr_err(&chmap_tr, "index %d out of bounds %d", + index, smap->num_ch_map); return NULL; } diff --git a/src/audio/codec/CMakeLists.txt b/src/audio/codec/CMakeLists.txt new file mode 100644 index 000000000000..5212a3631daf --- /dev/null +++ b/src/audio/codec/CMakeLists.txt @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-3-Clause + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + if(CONFIG_DTS_CODEC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(dts/llext ${PROJECT_BINARY_DIR}/dts_llext) + add_dependencies(app dts) + + elseif(CONFIG_DTS_CODEC) + zephyr_library_sources(dts/dts.c) + if (CONFIG_DTS_CODEC_STUB) + zephyr_library_sources(dts/dts_stub.c) + else() + zephyr_library_import(DtsCodec + ${sof_top_dir}/third_party/lib/libdts-sof-interface-i32.a) + endif() + endif() + + return() +endif() diff --git a/src/audio/codec/Kconfig b/src/audio/codec/Kconfig new file mode 100644 index 000000000000..0f089e3a7c54 --- /dev/null +++ b/src/audio/codec/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config DTS_CODEC + tristate "DTS codec" + select DTS_CODEC_STUB if COMP_STUBS + help + Select to include DTS codec. + In order to compile with this option enabled, a pre-compiled static library + must be provided by DTS for your target platform. If this library is not present + then compilation errors will occur. + For more information, please contact sales@xperi.com + +config DTS_CODEC_STUB + bool "DTS codec stub" + depends on DTS_CODEC + help + Select to include DTS codec stub library. This is meant for testing and CI + purposes only. diff --git a/src/audio/codec/README.md b/src/audio/codec/README.md new file mode 100644 index 000000000000..76a27e696d1a --- /dev/null +++ b/src/audio/codec/README.md @@ -0,0 +1,13 @@ +# Codec Abstraction Architecture + +This directory contains abstractions and adapters for various hardware and software audio codecs. + +## Overview + +Provides a unified interface to initialize, configure, and stream data to/from codec dependencies. + +## Configuration and Scripts + +- **Kconfig**: Specifically manages configurations for external codecs. For example, it defines options for the `DTS_CODEC`, including a testing/CI stub `DTS_CODEC_STUB` when `COMP_STUBS` is enabled. Use of the actual DTS codec requires a pre-compiled static library from Xperi. +- **CMakeLists.txt**: Specifies Zephyr build integration. For the DTS codec, it checks for modular builds (`llext`). If built statically, it either links the stub source or imports the pre-compiled `libdts-sof-interface-i32.a` library depending on configuration. +- **Topology (.conf)**: `tools/topology/topology2/include/components/dts.conf` defines the `dts` widget. It exposes `cpc` (cycles per chunk) and configures a byte control of size 2048 with `extctl` operations. Defaults to UUID `4f:c3:5f:d9:0f:37:c7:4a:bc:86:bf:dc:5b:e2:41:e6`. diff --git a/src/audio/codec/dts/dts.c b/src/audio/codec/dts/dts.c new file mode 100644 index 000000000000..cd1da3363517 --- /dev/null +++ b/src/audio/codec/dts/dts.c @@ -0,0 +1,485 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Xperi. All rights reserved. +// +// Author: Mark Barton <mark.barton@xperi.com> + +#include <rtos/init.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "DtsSofInterface.h" + +LOG_MODULE_REGISTER(dts, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dts); + +#define MAX_EXPECTED_DTS_CONFIG_DATA_SIZE 8192 + +static void *dts_effect_allocate_codec_memory(void *mod_void, unsigned int length, + unsigned int alignment) +{ + struct processing_module *mod = mod_void; + struct comp_dev *dev = mod->dev; + void *pMem; + + comp_dbg(dev, "dts_effect_allocate_codec_memory() start"); + + pMem = mod_alloc_align(mod, (uint32_t)length, (uint32_t)alignment); + + if (pMem == NULL) + comp_err(dev, + "dts_effect_allocate_codec_memory() failed to allocate %d bytes", length); + + comp_dbg(dev, "dts_effect_allocate_codec_memory() done"); + return pMem; +} + +static void dts_effect_free_codec_memory(void *mod_void, void *pMem) +{ + struct processing_module *mod = mod_void; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "start"); + + int ret = mod_free(mod, pMem); + + if (ret) + comp_err(dev, "mod_free failed %d", ret); + + comp_dbg(dev, "done"); +} + +static int dts_effect_convert_sof_interface_result(struct comp_dev *dev, + DtsSofInterfaceResult dts_result) +{ + int ret; + + switch (dts_result) { + case DTS_SOF_INTERFACE_RESULT_SUCCESS: + ret = 0; + break; + case DTS_SOF_INTERFACE_RESULT_ERROR_NO_MEMORY: + ret = -ENOMEM; + break; + case DTS_SOF_INTERFACE_RESULT_ERROR_DTS_INTERNAL_MODULE_ERROR: + ret = -EIO; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int dts_effect_populate_buffer_configuration(struct comp_dev *dev, + DtsSofInterfaceBufferConfiguration *buffer_config) +{ + struct comp_buffer *source = comp_dev_get_first_data_producer(dev); + const struct audio_stream *stream; + DtsSofInterfaceBufferLayout buffer_layout; + DtsSofInterfaceBufferFormat buffer_format; + unsigned int buffer_fmt, frame_fmt, rate, channels; + + comp_dbg(dev, "start"); + + if (!source) + return -EINVAL; + + stream = &source->stream; + buffer_fmt = audio_stream_get_buffer_fmt(stream); + frame_fmt = audio_stream_get_frm_fmt(stream); + rate = audio_stream_get_rate(stream); + channels = audio_stream_get_channels(stream); + + switch (buffer_fmt) { + case SOF_IPC_BUFFER_INTERLEAVED: + buffer_layout = DTS_SOF_INTERFACE_BUFFER_LAYOUT_INTERLEAVED; + break; + case SOF_IPC_BUFFER_NONINTERLEAVED: + buffer_layout = DTS_SOF_INTERFACE_BUFFER_LAYOUT_NONINTERLEAVED; + break; + default: + return -EINVAL; + } + + switch (frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + buffer_format = DTS_SOF_INTERFACE_BUFFER_FORMAT_SINT16LE; + break; + case SOF_IPC_FRAME_S24_4LE: + buffer_format = DTS_SOF_INTERFACE_BUFFER_FORMAT_SINT24LE; + break; + case SOF_IPC_FRAME_S32_LE: + buffer_format = DTS_SOF_INTERFACE_BUFFER_FORMAT_SINT32LE; + break; + case SOF_IPC_FRAME_FLOAT: + buffer_format = DTS_SOF_INTERFACE_BUFFER_FORMAT_FLOAT32; + break; + default: + return -EINVAL; + } + + buffer_config->bufferLayout = buffer_layout; + buffer_config->bufferFormat = buffer_format; + buffer_config->sampleRate = rate; + buffer_config->numChannels = channels; + buffer_config->periodInFrames = dev->frames; + + comp_dbg(dev, "done"); + + return 0; +} + +static int dts_codec_init(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + DtsSofInterfaceResult dts_result; + DtsSofInterfaceVersionInfo interface_version; + DtsSofInterfaceVersionInfo sdk_version; + + comp_dbg(dev, "start"); + + dts_result = dtsSofInterfaceInit((DtsSofInterfaceInst **)&(codec->private), + dts_effect_allocate_codec_memory, dts_effect_free_codec_memory, mod); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + + if (ret) + comp_err(dev, "dtsSofInterfaceInit failed %d %d", ret, dts_result); + + /* Obtain the current versions of DTS interface and SDK */ + dts_result = dtsSofInterfaceGetVersion(&interface_version, &sdk_version); + + /* Not necessary to fail initialisation if only get version failed */ + if (dts_result == DTS_SOF_INTERFACE_RESULT_SUCCESS) { + comp_info(dev, + "DTS SOF Interface version %d.%d.%d.%d", + interface_version.major, + interface_version.minor, + interface_version.patch, + interface_version.build); + comp_info(dev, + "DTS SDK version %d.%d.%d.%d", + sdk_version.major, + sdk_version.minor, + sdk_version.patch, + sdk_version.build); + } + + if (ret) + comp_err(dev, "failed %d %d", ret, dts_result); + + comp_dbg(dev, "done"); + + return ret; +} + +static int dts_codec_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + DtsSofInterfaceBufferConfiguration buffer_configuration; + DtsSofInterfaceResult dts_result; + + comp_dbg(dev, "start"); + + ret = dts_effect_populate_buffer_configuration(dev, &buffer_configuration); + if (ret) { + comp_err(dev, + "dts_effect_populate_buffer_configuration failed %d", + ret); + return ret; + } + + dts_result = dtsSofInterfacePrepare( + (DtsSofInterfaceInst *)codec->private, + &buffer_configuration, + &codec->mpd.in_buff, + &codec->mpd.in_buff_size, + &codec->mpd.out_buff, + &codec->mpd.out_buff_size); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + + if (ret) + comp_err(dev, "failed %d", ret); + + comp_dbg(dev, "done"); + + return ret; +} + +static int dts_codec_init_process(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + DtsSofInterfaceResult dts_result; + + comp_dbg(dev, "start"); + + dts_result = dtsSofInterfaceInitProcess(codec->private); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + + codec->mpd.produced = 0; + codec->mpd.consumed = 0; + codec->mpd.init_done = 1; + + if (ret) + comp_err(dev, "failed %d %d", ret, dts_result); + + comp_dbg(dev, "done"); + + return ret; +} + +static int +dts_codec_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) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + DtsSofInterfaceResult dts_result; + unsigned int bytes_processed = 0; + + /* Proceed only if we have enough data to fill the module buffer completely */ + if (input_buffers[0].size < codec->mpd.in_buff_size) { + comp_dbg(dev, "not enough data to process"); + return -ENODATA; + } + + if (!codec->mpd.init_done) { + ret = dts_codec_init_process(mod); + if (ret < 0) + return ret; + } + + memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, + input_buffers[0].data, codec->mpd.in_buff_size); + codec->mpd.avail = codec->mpd.in_buff_size; + + comp_dbg(dev, "start"); + + dts_result = dtsSofInterfaceProcess(codec->private, &bytes_processed); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + + codec->mpd.consumed = !ret ? bytes_processed : 0; + codec->mpd.produced = !ret ? bytes_processed : 0; + input_buffers[0].consumed = codec->mpd.consumed; + + if (ret) { + comp_err(dev, "failed %d %d", ret, dts_result); + return ret; + } + + /* copy the produced samples into the output buffer */ + memcpy_s(output_buffers[0].data, codec->mpd.produced, codec->mpd.out_buff, + codec->mpd.produced); + output_buffers[0].size = codec->mpd.produced; + + comp_dbg(dev, "done"); + + return ret; +} + +static int dts_codec_apply_config(struct processing_module *mod) +{ + int ret = 0; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct module_config *config; + struct module_param *param; + uint32_t config_header_size; + uint32_t config_data_size; + uint32_t param_header_size; + uint32_t param_data_size; + uint32_t i; + uint32_t param_number = 0; + DtsSofInterfaceResult dts_result; + + comp_dbg(dev, "start"); + + config = &codec->cfg; + + /* 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_warn(dev, "config->data is invalid"); + return 0; + } else if (config->size == config_header_size) { + comp_warn(dev, "size of config->data is 0"); + return 0; + } + + /* Calculate size of config->data */ + config_data_size = config->size - config_header_size; + + /* Check that config->data is not greater than the max expected for DTS data */ + if (config_data_size > MAX_EXPECTED_DTS_CONFIG_DATA_SIZE) { + comp_err(dev, + "size of config->data is larger than max for DTS data"); + return -EINVAL; + } + + /* Allow for multiple module_params to be packed into the data pointed to by config + */ + for (i = 0; i < config_data_size; param_number++) { + param = (struct module_param *)((char *)config->data + i); + param_header_size = sizeof(param->id) + sizeof(param->size); + + /* If param->size is less than param_header_size, then this param is not valid */ + if (param->size < param_header_size) { + comp_err(dev, "param is invalid"); + return -EINVAL; + } + + /* Only process param->data if it has size greater than 0 */ + if (param->size > param_header_size) { + /* Calculate size of param->data */ + param_data_size = param->size - param_header_size; + + comp_dbg(dev, "id %d size %d", + param->id, param_data_size); + + if (param_data_size) { + dts_result = dtsSofInterfaceApplyConfig(codec->private, param->id, + param->data, param_data_size); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + if (ret) { + comp_err(dev, + "dtsSofInterfaceApplyConfig failed %d", + dts_result); + return ret; + } + } + } + + /* Advance to the next module_param */ + i += param->size; + } + + comp_dbg(dev, "done"); + + return ret; +} + +static int dts_codec_reset(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + DtsSofInterfaceResult dts_result; + + comp_dbg(dev, "start"); + + dts_result = dtsSofInterfaceReset(codec->private); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + + if (ret) + comp_err(dev, "failed %d %d", ret, dts_result); + + comp_dbg(dev, "done"); + + return ret; +} + +static int dts_codec_free(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + DtsSofInterfaceResult dts_result; + + comp_dbg(dev, "start"); + + dts_result = dtsSofInterfaceFree(codec->private); + ret = dts_effect_convert_sof_interface_result(dev, dts_result); + + if (ret) + comp_err(dev, "failed %d %d", ret, dts_result); + + comp_dbg(dev, "done"); + + return ret; +} + +static int +dts_codec_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size) +{ +#if CONFIG_IPC_MAJOR_3 + struct module_data *md = &mod->priv; +#endif + struct comp_dev *dev = mod->dev; + int ret; + + ret = module_set_configuration(mod, config_id, pos, data_offset_size, fragment, + fragment_size, response, response_size); + if (ret < 0) { + comp_err(dev, "error %x from module_set_configuration()", + ret); + return ret; + } + + /* return if more fragments are expected */ + if (pos != MODULE_CFG_FRAGMENT_LAST && pos != MODULE_CFG_FRAGMENT_SINGLE) { + comp_err(dev, "pos %d error", pos); + return 0; + } + +#if CONFIG_IPC_MAJOR_3 + // return if the module is not prepared + if (md->state < MODULE_INITIALIZED) { + comp_err(dev, "state %d error", md->state); + return 0; + } +#endif + + /* whole configuration received, apply it now */ + ret = dts_codec_apply_config(mod); + if (ret) { + comp_err(dev, "error %x: runtime config apply failed", + ret); + return ret; + } + + comp_dbg(dev, "config applied"); + + return 0; +} + +static const struct module_interface dts_interface = { + .init = dts_codec_init, + .prepare = dts_codec_prepare, + .process_raw_data = dts_codec_process, + .set_configuration = dts_codec_set_configuration, + .reset = dts_codec_reset, + .free = dts_codec_free +}; + +#if CONFIG_DTS_CODEC_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("DTS", &dts_interface, 1, SOF_REG_UUID(dts), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(dts_tr, SOF_UUID(dts_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(dts_interface, dts_uuid, dts_tr); +SOF_MODULE_INIT(dts, sys_comp_module_dts_interface_init); + +#endif diff --git a/src/audio/codec/dts/dts.toml b/src/audio/codec/dts/dts.toml new file mode 100644 index 000000000000..12b8a4104ad5 --- /dev/null +++ b/src/audio/codec/dts/dts.toml @@ -0,0 +1,24 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # dts codec module config + [[module.entry]] + name = "DTS" + uuid = UUIDREG_STR_DTS + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + + REM # 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, 2048, 5000000, 384, 384, 0, 5000, 0] + + index = __COUNTER__ diff --git a/src/audio/codec/dts/dts_stub.c b/src/audio/codec/dts/dts_stub.c new file mode 100644 index 000000000000..dc81f3db251e --- /dev/null +++ b/src/audio/codec/dts/dts_stub.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Google LLC. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org> + +#include "DtsSofInterface.h" + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceInit( + DtsSofInterfaceInst **ppInst, + DtsSofInterfaceAllocateMemory pMemoryAllocationFn, + DtsSofInterfaceFreeMemory pMemoryFreeFn, + void *MemoryAllocationContext) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfacePrepare( + DtsSofInterfaceInst* pInst, + const DtsSofInterfaceBufferConfiguration* pBufferConfiguration, + void** ppSofInputBuffer, + unsigned int* pSofInputBufferSize, + void** ppSofOutputBuffer, + unsigned int* pSofOutputBufferSize) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceInitProcess( + DtsSofInterfaceInst* pInst) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceProcess( + DtsSofInterfaceInst* pInst, + unsigned int* pNumBytesProcessed) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceApplyConfig( + DtsSofInterfaceInst* pInst, + int parameterId, + const void *pData, + unsigned int dataSize) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceReset( + DtsSofInterfaceInst* pInst) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceFree( + DtsSofInterfaceInst* pInst) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceGetVersion( + DtsSofInterfaceVersionInfo* pInterfaceVersion, + DtsSofInterfaceVersionInfo* pSdkVersion) DTS_SOF_INTERFACE_NOEXCEPT +{ + return DTS_SOF_INTERFACE_RESULT_SUCCESS; +} diff --git a/src/audio/codec/dts/llext/CMakeLists.txt b/src/audio/codec/dts/llext/CMakeLists.txt new file mode 100644 index 000000000000..da7043e10511 --- /dev/null +++ b/src/audio/codec/dts/llext/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_DTS_CODEC_STUB) + sof_llext_build("dts" + SOURCES ../dts.c + ../dts_stub.c + ) + target_include_directories(dts_llext_lib PRIVATE + "../../../../../third_party/include" + ) +elseif(CONFIG_DTS_CODEC STREQUAL "m") + sof_llext_build("dts" + SOURCES ../dts.c + INCLUDES "${sof_top_dir}/third_party/include" + LIBS_PATH "${sof_top_dir}/third_party/lib/" + LIBS dts-sof-interface-i32 m c gcc + ) + +else() +message(FATAL_ERROR "Add library linking support in src/audio/codec/dts/llext/CMakeLists.txt") +endif() diff --git a/src/audio/codec/dts/llext/llext.toml.h b/src/audio/codec/dts/llext/llext.toml.h new file mode 100644 index 000000000000..cca37e4b5605 --- /dev/null +++ b/src/audio/codec/dts/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../dts.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/component.c b/src/audio/component.c index ed3f6b696475..941be20f8534 100644 --- a/src/audio/component.c +++ b/src/audio/component.c @@ -5,109 +5,93 @@ // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> #include <sof/audio/component_ext.h> +#include <sof/audio/sink_source_utils.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/memory.h> +#include <sof/debug/telemetry/performance_monitor.h> +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/uuid.h> #include <sof/list.h> -#include <sof/sof.h> -#include <sof/string.h> +#include <rtos/sof.h> +#include <rtos/string.h> +#include <rtos/symbol.h> #include <ipc/topology.h> #include <errno.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> -static SHARED_DATA struct comp_driver_list cd; - -static const struct comp_driver *get_drv(uint32_t type) -{ - struct comp_driver_list *drivers = comp_drivers_get(); - struct list_item *clist; - const struct comp_driver *drv = NULL; - struct comp_driver_info *info; - uint32_t flags; - - irq_local_disable(flags); - - /* search driver list for driver type */ - list_for_item(clist, &drivers->list) { - info = container_of(clist, struct comp_driver_info, list); - if (info->drv->type == type) { - drv = info->drv; - platform_shared_commit(info, sizeof(*info)); - goto out; - } - - platform_shared_commit(info, sizeof(*info)); - } - -out: - platform_shared_commit(drivers, sizeof(*drivers)); - irq_local_enable(flags); - return drv; -} - -struct comp_dev *comp_new(struct sof_ipc_comp *comp) -{ - struct comp_dev *cdev; - const struct comp_driver *drv; - - /* find the driver for our new component */ - drv = get_drv(comp->type); - if (!drv) { - trace_error(TRACE_CLASS_COMP, "comp_new() error: driver not found, comp->type = %u", - comp->type); - return NULL; - } - - /* validate size of ipc config */ - if (IPC_IS_SIZE_INVALID(*comp_config(comp))) { - IPC_SIZE_ERROR_TRACE(TRACE_CLASS_COMP, *comp_config(comp)); - return NULL; - } +#if defined(__XCC__) +#include <xtensa/config/core-isa.h> +# if XCHAL_HAVE_HIFI5 +# define STREAMCOPY_HIFI5 +# elif XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4 +# define STREAMCOPY_HIFI3 +#endif +#endif - trace_event(TRACE_CLASS_COMP, "comp new %s type %d pipe_id %d id %d", - drv->uid, comp->type, comp->pipeline_id, comp->id); +LOG_MODULE_REGISTER(component, CONFIG_SOF_LOG_LEVEL); - /* create the new component */ - cdev = drv->ops.new(drv, comp); - if (!cdev) { - comp_cl_err(drv, "comp_new() error: unable to create the new component"); - return NULL; - } +static SHARED_DATA struct comp_driver_list cd; - list_init(&cdev->bsource_list); - list_init(&cdev->bsink_list); +SOF_DEFINE_REG_UUID(component); - return cdev; -} +DECLARE_TR_CTX(comp_tr, SOF_UUID(component_uuid), LOG_LEVEL_INFO); int comp_register(struct comp_driver_info *drv) { struct comp_driver_list *drivers = comp_drivers_get(); - uint32_t flags; + k_spinlock_key_t key; - irq_local_disable(flags); + key = k_spin_lock(&drivers->lock); list_item_prepend(&drv->list, &drivers->list); - platform_shared_commit(drv, sizeof(*drv)); - platform_shared_commit(drivers, sizeof(*drivers)); - irq_local_enable(flags); + k_spin_unlock(&drivers->lock, key); return 0; } void comp_unregister(struct comp_driver_info *drv) { - uint32_t flags; + struct comp_driver_list *drivers = comp_drivers_get(); + k_spinlock_key_t key; - irq_local_disable(flags); + key = k_spin_lock(&drivers->lock); list_item_del(&drv->list); - platform_shared_commit(drv, sizeof(*drv)); - irq_local_enable(flags); + k_spin_unlock(&drivers->lock, key); +} + +int comp_set_adapter_ops(const struct comp_driver *drv, const struct module_interface *ops) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct list_item *clist; + + /* The list is only modified in IPC context, and we're in IPC context too */ + list_for_item(clist, &drivers->list) { + struct comp_driver_info *info = container_of(clist, struct comp_driver_info, list); + + if (!memcmp(info->drv->uid, drv->uid, UUID_SIZE)) { + /* + * This function should only be called for dynamically + * loaded component drivers and their driver info cannot + * be NULL. Do a sanity check. + */ + if (!info->adapter_ops) { + tr_err(&comp_tr, "NULL adapter ops ptr for %pU!", + info->drv->tctx->uuid_p); + return -EINVAL; + } + + tr_dbg(&comp_tr, "update uuid %pU", info->drv->tctx->uuid_p); + *info->adapter_ops = ops; + return 0; + } + } + + return -ENODEV; } /* NOTE: Keep the component state diagram up to date: @@ -117,93 +101,100 @@ void comp_unregister(struct comp_driver_info *drv) int comp_set_state(struct comp_dev *dev, int cmd) { int requested_state = comp_get_requested_state(cmd); - int ret = 0; if (dev->state == requested_state) { - comp_info(dev, "comp_set_state(), state already set to %u", + comp_info(dev, "state already set to %u", dev->state); +#ifdef CONFIG_IPC_MAJOR_4 + return 0; +#else return COMP_STATUS_STATE_ALREADY_SET; +#endif } switch (cmd) { case COMP_TRIGGER_START: - if (dev->state == COMP_STATE_PREPARE) { - dev->state = COMP_STATE_ACTIVE; - } else { - comp_err(dev, "comp_set_state() error: wrong state = %u, COMP_TRIGGER_START", + if (dev->state != COMP_STATE_PRE_ACTIVE) { + comp_err(dev, "wrong state = %u, COMP_TRIGGER_START", dev->state); - ret = -EINVAL; + return -EINVAL; } break; case COMP_TRIGGER_RELEASE: - if (dev->state == COMP_STATE_PAUSED) { - dev->state = COMP_STATE_ACTIVE; - } else { - comp_err(dev, "comp_set_state() error: wrong state = %u, COMP_TRIGGER_RELEASE", + if (dev->state != COMP_STATE_PRE_ACTIVE) { + comp_err(dev, "wrong state = %u, COMP_TRIGGER_RELEASE", dev->state); - ret = -EINVAL; + return -EINVAL; } break; case COMP_TRIGGER_STOP: - if (dev->state == COMP_STATE_ACTIVE || - dev->state == COMP_STATE_PAUSED) { - dev->state = COMP_STATE_PREPARE; - } else { - comp_err(dev, "comp_set_state() error: wrong state = %u, COMP_TRIGGER_STOP", + if (dev->state != COMP_STATE_ACTIVE && + dev->state != COMP_STATE_PAUSED) { + comp_err(dev, "wrong state = %u, COMP_TRIGGER_STOP", dev->state); - ret = -EINVAL; + return -EINVAL; } break; - case COMP_TRIGGER_XRUN: - /* reset component status to ready at xrun */ - dev->state = COMP_STATE_READY; - break; case COMP_TRIGGER_PAUSE: /* only support pausing for running */ - if (dev->state == COMP_STATE_ACTIVE) { - dev->state = COMP_STATE_PAUSED; - } else { - comp_err(dev, "comp_set_state() error: wrong state = %u, COMP_TRIGGER_PAUSE", + if (dev->state != COMP_STATE_ACTIVE) { + comp_err(dev, "wrong state = %u, COMP_TRIGGER_PAUSE", dev->state); - ret = -EINVAL; + return -EINVAL; } break; case COMP_TRIGGER_RESET: /* reset always succeeds */ - if (dev->state == COMP_STATE_ACTIVE || - dev->state == COMP_STATE_PAUSED) { - comp_err(dev, "comp_set_state() error: wrong state = %u, COMP_TRIGGER_RESET", + if (dev->state == COMP_STATE_ACTIVE) + comp_err(dev, "wrong state = %u, COMP_TRIGGER_RESET", dev->state); - ret = 0; - } - dev->state = COMP_STATE_READY; + else if (dev->state == COMP_STATE_PAUSED) + comp_info(dev, "state = %u, COMP_TRIGGER_RESET", + dev->state); break; case COMP_TRIGGER_PREPARE: - if (dev->state == COMP_STATE_READY) { - dev->state = COMP_STATE_PREPARE; - } else { - comp_err(dev, "comp_set_state() error: wrong state = %u, COMP_TRIGGER_PREPARE", + if (dev->state != COMP_STATE_READY) { + comp_err(dev, "wrong state = %u, COMP_TRIGGER_PREPARE", dev->state); - ret = -EINVAL; + return -EINVAL; } break; - default: + case COMP_TRIGGER_PRE_START: + if (dev->state != COMP_STATE_PREPARE) { + comp_err(dev, + "wrong state = %u, COMP_TRIGGER_PRE_START", + dev->state); + return -EINVAL; + } break; + case COMP_TRIGGER_PRE_RELEASE: + if (dev->state != COMP_STATE_PAUSED) { + comp_err(dev, + "wrong state = %u, COMP_TRIGGER_PRE_RELEASE", + dev->state); + return -EINVAL; + } + break; + default: + return 0; } - return ret; + dev->state = requested_state; + + return 0; } +EXPORT_SYMBOL(comp_set_state); void sys_comp_init(struct sof *sof) { sof->comp_drivers = platform_shared_get(&cd, sizeof(cd)); list_init(&sof->comp_drivers->list); - - platform_shared_commit(sof->comp_drivers, sizeof(*sof->comp_drivers)); + k_spinlock_init(&sof->comp_drivers->lock); } -void comp_get_copy_limits(struct comp_buffer *source, struct comp_buffer *sink, +void comp_get_copy_limits(struct comp_buffer *source, + struct comp_buffer *sink, struct comp_copy_limits *cl) { cl->frames = audio_stream_avail_frames(&source->stream, &sink->stream); @@ -213,132 +204,498 @@ void comp_get_copy_limits(struct comp_buffer *source, struct comp_buffer *sink, cl->sink_bytes = cl->frames * cl->sink_frame_bytes; } -/* Function overwrites PCM parameters (frame_fmt, buffer_fmt, channels, rate) - * with buffer parameters when specific flag is set. - */ -static void comp_update_params(uint32_t flag, - struct sof_ipc_stream_params *params, - struct comp_buffer *buffer) +void comp_get_copy_limits_frame_aligned(const struct comp_buffer *source, + const struct comp_buffer *sink, + struct comp_copy_limits *cl) { - if (flag & BUFF_PARAMS_FRAME_FMT) - params->frame_fmt = buffer->stream.frame_fmt; + cl->frames = audio_stream_avail_frames_aligned(&source->stream, &sink->stream); + cl->source_frame_bytes = audio_stream_frame_bytes(&source->stream); + cl->sink_frame_bytes = audio_stream_frame_bytes(&sink->stream); + cl->source_bytes = cl->frames * cl->source_frame_bytes; + cl->sink_bytes = cl->frames * cl->sink_frame_bytes; +} - if (flag & BUFF_PARAMS_BUFFER_FMT) - params->buffer_fmt = buffer->buffer_fmt; +#if defined(STREAMCOPY_HIFI5) - if (flag & BUFF_PARAMS_CHANNELS) - params->channels = buffer->stream.channels; +#include <xtensa/tie/xt_hifi5.h> - if (flag & BUFF_PARAMS_RATE) - params->rate = buffer->stream.rate; +int audio_stream_copy(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, uint32_t samples) +{ + int ssize = audio_stream_sample_bytes(source); /* src fmt == sink fmt */ + ae_int16x8 *src = (ae_int16x8 *)((int8_t *)audio_stream_get_rptr(source) + ioffset * ssize); + ae_int16x8 *dst = (ae_int16x8 *)((int8_t *)audio_stream_get_wptr(sink) + ooffset * ssize); + int shorts = samples * ssize >> 1; + int shorts_src; + int shorts_dst; + int shorts_copied; + int left, m, i; + ae_int16x4 in_sample1; + ae_int16x4 in_sample2; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + + /* copy with 16bit as the minimum unit since the minimum sample size is 16 bit*/ + while (shorts > 0) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + shorts_src = audio_stream_samples_without_wrap_s16(source, src); + shorts_dst = audio_stream_samples_without_wrap_s16(sink, dst); + shorts_copied = AE_MIN32(shorts_src, shorts_dst); + shorts_copied = AE_MIN32(shorts, shorts_copied); + m = shorts_copied >> 3; + left = shorts_copied & 0x07; + inu = AE_LA128_PP(src); + /* copy 4 * 16bit(8 bytes)per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4X2_IP(in_sample1, in_sample2, inu, src); + AE_SA16X4X2_IP(in_sample1, in_sample2, outu, dst); + } + AE_SA128POS_FP(outu, dst); + + /* process the left bits that less than 4 * 16 */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample1, (ae_int16 *)src, sizeof(ae_int16)); + AE_S16_0_IP(in_sample1, (ae_int16 *)dst, sizeof(ae_int16)); + } + shorts -= shorts_copied; + } + return samples; } -int comp_verify_params(struct comp_dev *dev, uint32_t flag, - struct sof_ipc_stream_params *params) +void cir_buf_copy(void *src, void *src_addr, void *src_end, void *dst, + void *dst_addr, void *dst_end, size_t byte_size) { - struct list_item *buffer_list; - struct list_item *source_list; - struct list_item *sink_list; - struct list_item *clist; - struct list_item *curr; - struct comp_buffer *sinkb; - struct comp_buffer *buf; - int dir = dev->direction; - uint32_t flags = 0; - - if (!params) { - comp_err(dev, "comp_verify_params() error: !params"); - return -EINVAL; + size_t bytes = byte_size; + size_t bytes_src; + size_t bytes_dst; + size_t bytes_copied; + size_t short_copied; + int left, m, i; + ae_int16x4 in_sample1, in_sample2; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int16x8 *in = (ae_int16x8 *)src; + ae_int16x8 *out = (ae_int16x8 *)dst; + + while (bytes) { + bytes_src = cir_buf_bytes_without_wrap(in, src_end); + bytes_dst = cir_buf_bytes_without_wrap(out, dst_end); + bytes_copied = MIN(bytes_src, bytes_dst); + bytes_copied = MIN(bytes, bytes_copied); + short_copied = bytes_copied >> 1; + + m = short_copied >> 3; + left = short_copied & 0x07; + inu = AE_LA128_PP(in); + /* copy 2 * 4 * 16bit(16 bytes)per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4X2_IP(in_sample1, in_sample2, inu, in); + AE_SA16X4X2_IP(in_sample1, in_sample2, outu, out); + } + AE_SA128POS_FP(outu, out); + + /* process the left bits that less than 2 * 4 * 16 */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample1, (ae_int16 *)in, sizeof(ae_int16)); + AE_S16_0_IP(in_sample1, (ae_int16 *)out, sizeof(ae_int16)); + } + + bytes -= bytes_copied; + in = cir_buf_wrap(in, src_addr, src_end); + out = cir_buf_wrap(out, dst_addr, dst_end); } +} - source_list = comp_buffer_list(dev, PPL_DIR_UPSTREAM); - sink_list = comp_buffer_list(dev, PPL_DIR_DOWNSTREAM); +#elif defined(STREAMCOPY_HIFI3) - /* searching for endpoint component e.g. HOST, DETECT_TEST, which - * has only one sink or one source buffer. - */ - if (list_is_empty(source_list) != list_is_empty(sink_list)) { - if (!list_is_empty(source_list)) - buf = list_first_item(&dev->bsource_list, - struct comp_buffer, - sink_list); - else - buf = list_first_item(&dev->bsink_list, - struct comp_buffer, - source_list); +#include <xtensa/tie/xt_hifi3.h> - buffer_lock(buf, &flags); +int audio_stream_copy(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *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 *)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; + int shorts_copied; + int left, m, i; + ae_int16x4 in_sample = AE_ZERO16(); + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + + /* copy with 16bit as the minimum unit since the minimum sample size is 16 bit*/ + while (shorts > 0) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + shorts_src = audio_stream_samples_without_wrap_s16(source, src); + shorts_dst = audio_stream_samples_without_wrap_s16(sink, dst); + shorts_copied = AE_MIN32(shorts_src, shorts_dst); + shorts_copied = AE_MIN32(shorts, shorts_copied); + m = shorts_copied >> 2; + left = shorts_copied & 0x03; + inu = AE_LA64_PP(src); + /* copy 4 * 16bit(8 bytes)per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4_IP(in_sample, inu, src); + AE_SA16X4_IP(in_sample, outu, dst); + } + AE_SA64POS_FP(outu, dst); - /* update specific pcm parameter with buffer parameter if - * specific flag is set. - */ - comp_update_params(flag, params, buf); + /* process the left bits that less than 4 * 16 */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)src, sizeof(ae_int16)); + AE_S16_0_IP(in_sample, (ae_int16 *)dst, sizeof(ae_int16)); + } + shorts -= shorts_copied; + } + return samples; +} - /* overwrite buffer parameters with modified pcm - * parameters - */ - buffer_set_params(buf, params, BUFFER_UPDATE_FORCE); +void cir_buf_copy(void *src, void *src_addr, void *src_end, void *dst, + void *dst_addr, void *dst_end, size_t byte_size) +{ + size_t bytes = byte_size; + size_t bytes_src; + size_t bytes_dst; + size_t bytes_copied; + size_t short_copied; + + int left, m, i; + ae_int16x4 in_sample = AE_ZERO16(); + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + ae_int16x4 *in = (ae_int16x4 *)src; + ae_int16x4 *out = (ae_int16x4 *)dst; + + while (bytes) { + bytes_src = cir_buf_bytes_without_wrap(in, src_end); + bytes_dst = cir_buf_bytes_without_wrap(out, dst_end); + bytes_copied = MIN(bytes_src, bytes_dst); + bytes_copied = MIN(bytes, bytes_copied); + short_copied = bytes_copied >> 1; + m = short_copied >> 2; + left = short_copied & 0x03; + inu = AE_LA64_PP(in); + /* copy 4 * 16bit(8 bytes)per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4_IP(in_sample, inu, in); + AE_SA16X4_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); - /* set component period frames */ - component_set_period_frames(dev, buf->stream.rate); + /* process the left bits that less than 4 * 16 */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_S16_0_IP(in_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + + bytes -= bytes_copied; + in = cir_buf_wrap(in, src_addr, src_end); + out = cir_buf_wrap(out, dst_addr, dst_end); + } +} - buffer_unlock(buf, flags); - } else { - /* for other components we iterate over all downstream buffers - * (for playback) or upstream buffers (for capture). - */ - buffer_list = comp_buffer_list(dev, dir); - clist = buffer_list->next; +#else - while (clist != buffer_list) { - curr = clist; +int audio_stream_copy(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *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 *)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; + size_t bytes_copied; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + bytes_copied = MIN(bytes_src, bytes_snk); + bytes_copied = MIN(bytes, bytes_copied); + memcpy(snk, src, bytes_copied); + bytes -= bytes_copied; + src = audio_stream_wrap(source, src + bytes_copied); + snk = audio_stream_wrap(sink, snk + bytes_copied); + } - buf = buffer_from_list(curr, struct comp_buffer, dir); + return samples; +} - buffer_lock(buf, &flags); +void cir_buf_copy(void *src, void *src_addr, void *src_end, void *dst, + void *dst_addr, void *dst_end, size_t byte_size) +{ + size_t bytes = byte_size; + size_t bytes_src; + size_t bytes_dst; + size_t bytes_copied; + uint8_t *in = (uint8_t *)src; + uint8_t *out = (uint8_t *)dst; + + while (bytes) { + bytes_src = cir_buf_bytes_without_wrap(in, src_end); + bytes_dst = cir_buf_bytes_without_wrap(out, dst_end); + bytes_copied = MIN(bytes_src, bytes_dst); + bytes_copied = MIN(bytes, bytes_copied); + memcpy_s(out, bytes_copied, in, bytes_copied); + bytes -= bytes_copied; + in = cir_buf_wrap(in + bytes_copied, src_addr, src_end); + out = cir_buf_wrap(out + bytes_copied, dst_addr, dst_end); + } +} - clist = clist->next; +#endif +EXPORT_SYMBOL(audio_stream_copy); +EXPORT_SYMBOL(cir_buf_copy); - comp_update_params(flag, params, buf); +void audio_stream_copy_from_linear(const void *linear_source, int ioffset, + struct audio_stream *sink, int ooffset, + unsigned int samples) +{ + 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 *)audio_stream_get_wptr(sink) + + ooffset * ssize); + size_t bytes = samples * ssize; + size_t bytes_snk; + size_t bytes_copied; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + bytes_copied = MIN(bytes, bytes_snk); + memcpy(snk, src, bytes_copied); + bytes -= bytes_copied; + src += bytes_copied; + snk = audio_stream_wrap(sink, snk + bytes_copied); + } +} - buffer_set_params(buf, params, BUFFER_UPDATE_FORCE); +void audio_stream_copy_to_linear(const struct audio_stream *source, int ioffset, + 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 *)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; + size_t bytes_copied; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + bytes_copied = MIN(bytes, bytes_src); + memcpy(snk, src, bytes_copied); + bytes -= bytes_copied; + src = audio_stream_wrap(source, src + bytes_copied); + snk += bytes_copied; + } +} - buffer_unlock(buf, flags); +static bool comp_check_eos(struct comp_dev *dev) +{ + enum sof_audio_buffer_state sink_state = AUDIOBUF_STATE_INITIAL; + struct comp_buffer *buffer; + + if (!dev->pipeline->expect_eos) + return false; + + comp_dev_for_each_producer(dev, buffer) { + struct sof_source *source = audio_buffer_get_source(&buffer->audio_buffer); + enum sof_audio_buffer_state state = source_get_state(source); + + if (source_get_pipeline_id(source) != dev->pipeline->pipeline_id) + continue; + + if (state == AUDIOBUF_STATE_END_OF_STREAM_FLUSH) { + /* Earlier in the pipeline, there is a DP module that has reached + * the EOS state. However, silence is generated to flush its internal + * buffers, so pass this state to the output buffers. + */ + comp_dbg(dev, "- EOS flush detected"); + sink_state = AUDIOBUF_STATE_END_OF_STREAM_FLUSH; + break; + } else if (state == AUDIOBUF_STATE_END_OF_STREAM) { + /* EOS is detected, so we need to set the sink state to AUDIOBUF_STATE_EOS. */ + size_t min_avail = source_get_min_available(source); + + if (source_get_data_available(source) < min_avail) { + comp_dbg(dev, "- EOS detected"); + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* For DP modules, fill missing input data with silence to + * allow it to process the remaining data. + */ + struct sof_sink *previous_mod_data_sink = + audio_buffer_get_sink(&buffer->audio_buffer); + sink_fill_with_silence(previous_mod_data_sink, min_avail); + sink_state = AUDIOBUF_STATE_END_OF_STREAM_FLUSH; + } else { + sink_state = AUDIOBUF_STATE_END_OF_STREAM; + break; + } + } } + } - /* fetch sink buffer in order to calculate period frames */ - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); + if (sink_state != AUDIOBUF_STATE_INITIAL) { + comp_dev_for_each_consumer(dev, buffer) + audio_buffer_set_state(&buffer->audio_buffer, sink_state); - buffer_lock(sinkb, &flags); + /* For AUDIOBUF_STATE_END_OF_STREAM_FLUSH process data normally. */ + return sink_state != AUDIOBUF_STATE_END_OF_STREAM_FLUSH; + } - component_set_period_frames(dev, sinkb->stream.rate); + return false; +} + +/** See comp_ops::copy */ +int comp_copy(struct comp_dev *dev) +{ + int ret = 0; + + assert(dev->drv->ops.copy); + + /* copy only if we are the owner of component OR this is DP component + * + * DP components (modules) require two stage processing: + * + * LL_mod -> [comp_buffer->ring_buffer] -> dp_mod -> [ring_buffer ->comp_buffer] -> LL_mod + * + * - in first step (it means - now) the pipeline must copy source data from comp_buffer + * to ring_buffer and result data from ring_buffer to comp_buffer + * + * - second step will be performed by a thread specific to the DP module - DP module + * will take data from input ring_buffer (using source API), process it + * and put in output ring_buffer (using sink API) + * + * this allows the current pipeline structure to see a DP module as a "normal" LL + * + * to be removed when pipeline 2.0 is ready + */ + if (cpu_is_me(dev->ipc_config.core) || + dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { +#if CONFIG_PERFORMANCE_COUNTERS_COMPONENT + perf_cnt_init(&dev->pcd); +#endif + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + const uint32_t begin_stamp = (uint32_t)telemetry_timestamp(); +#endif + + if (comp_check_eos(dev)) + return 0; - buffer_unlock(sinkb, flags); + ret = dev->drv->ops.copy(dev); + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + const uint32_t cycles_consumed = (uint32_t)telemetry_timestamp() - begin_stamp; + + comp_update_performance_data(dev, cycles_consumed); +#endif + +#if CONFIG_PERFORMANCE_COUNTERS_COMPONENT + perf_cnt_stamp(&dev->pcd, perf_trace_null, dev); + perf_cnt_average(&dev->pcd, comp_perf_avg_info, dev); +#endif } - return 0; + return ret; } -struct comp_dev *comp_make_shared(struct comp_dev *dev) +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS +void comp_init_performance_data(struct comp_dev *dev) { - struct comp_dev *old = dev; + struct perf_data_item_comp *item = dev->perf_data.perf_data_item; - dev = rrealloc(dev, SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, dev->size); - if (!dev) { - trace_error(TRACE_CLASS_COMP, "comp_make_shared() error: unable to realloc component"); - return NULL; - } + if (item) + perf_data_item_comp_init(item, dev->ipc_config.id, 0); +} - list_init(&dev->bsource_list); - list_init(&dev->bsink_list); - dev->is_shared = true; +/* returns true if budget violation occurred */ +static bool update_peak_of_measured_cpc(struct comp_dev *dev, size_t measured_cpc) +{ + if (measured_cpc <= dev->perf_data.peak_of_measured_cpc) + return false; + dev->perf_data.peak_of_measured_cpc = measured_cpc; + return measured_cpc > dev->cpc; +} + +bool comp_update_performance_data(struct comp_dev *dev, uint32_t cycles_used) +{ + struct perf_data_item_comp *item = dev->perf_data.perf_data_item; + + if (perf_meas_get_state() == IPC4_PERF_MEASUREMENTS_STARTED) { + /* we divide by ibs so we need to check if its set */ + if (item && dev->ibs != 0) { + item->total_iteration_count++; + if (item->total_iteration_count == 0) { + /* We can't allow count to overflow to 0. Overflow will also make + * some of the results incorrect. We don't want to crash in this + * case, so we just log it. We also reset cycles counter to make + * avg correct again. + */ + item->total_iteration_count = 1; + item->total_cycles_consumed = 0; + tr_err(&ipc_tr, + "overflow for module %#x, performance measurement incorrect", + dev_comp_id(dev)); + } + item->total_cycles_consumed += cycles_used; + item->item.avg_kcps = item->total_cycles_consumed * dev->ll_chunk_size + / (dev->ibs * item->total_iteration_count); + item->item.peak_kcps = + MAX(item->item.peak_kcps, (cycles_used * dev->ll_chunk_size) + / dev->ibs); + } + } + return update_peak_of_measured_cpc(dev, cycles_used); +} +#endif - platform_shared_commit(dev, sizeof(*dev)); +#if CONFIG_IPC_MAJOR_4 +static uint32_t get_sample_group_size_in_bytes(const struct ipc4_audio_format fmt) +{ + return (fmt.depth >> 3) * fmt.channels_count; +} - /* clear cache to avoid later random flushes */ - dcache_invalidate_region(old, sizeof(*old)); +static uint32_t get_one_ms_in_bytes(const struct ipc4_audio_format fmt) +{ + /* TODO Reference Firmware also has systick multiplier and divider in this equation */ + return get_sample_group_size_in_bytes(fmt) * + SOF_DIV_ROUND_UP(fmt.sampling_frequency, 1000); +} +#endif - return dev; +void comp_update_ibs_obs_cpc(struct comp_dev *dev) +{ +#if CONFIG_IPC_MAJOR_4 + int ret; + struct ipc4_base_module_cfg dev_cfg; + + ret = comp_get_attribute(dev, COMP_ATTR_BASE_CONFIG, &dev_cfg); + if (ret < 0) { + tr_err(&ipc_tr, "failed to get base config for module %#x", + dev_comp_id(dev)); + /* set neutral values */ + dev->ll_chunk_size = 0; + dev->cpc = 0; + dev->obs = 0; + dev->ibs = 0; + } + dev->ll_chunk_size = get_one_ms_in_bytes(dev_cfg.audio_fmt); + dev->obs = dev_cfg.obs; + dev->ibs = dev_cfg.ibs; + dev->cpc = dev_cfg.cpc; +#else + /* set neutral values */ + dev->ll_chunk_size = 0; + dev->cpc = 0; + dev->obs = 0; + dev->ibs = 0; +#endif } + diff --git a/src/audio/copier/CMakeLists.txt b/src/audio/copier/CMakeLists.txt new file mode 100644 index 000000000000..7cead10dabe0 --- /dev/null +++ b/src/audio/copier/CMakeLists.txt @@ -0,0 +1,10 @@ +add_local_sources(sof copier.c copier_hifi.c copier_generic.c copier_host.c copier_dai.c) +if(CONFIG_IPC4_GATEWAY) + add_local_sources(sof + copier_ipcgtw.c + ) +endif() + +if(CONFIG_COPIER_GAIN) + add_local_sources(sof copier_gain.c) +endif() diff --git a/src/audio/copier/Kconfig b/src/audio/copier/Kconfig new file mode 100644 index 000000000000..ec3e55016c10 --- /dev/null +++ b/src/audio/copier/Kconfig @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: BSD-3-Clause + +rsource "Kconfig.simd" + +config COMP_COPIER + bool "COPIER component" + default y + depends on IPC_MAJOR_4 + help + Select for COPIER component + +config COMP_DAI + bool "DAI component" + default y + help + Select for DAI component + +config COMP_DAI_STOP_TRIGGER_ORDER_REVERSE + bool "Reverse the ordering of DMA and DAI triggers during STOP/PAUSE" + help + Select if the ordering of DMA and DAI triggers during stop/pause should be reversed. + The normal order during stop/pause is to stop DAI before stopping DMA. This option will + allow reversing the order to do DMA stop before stopping DAI. + +config COMP_DAI_GROUP + bool "DAI Grouping support" + default y + help + Select for grouping physical DAIs into a logical DAI that can be + triggered atomically to synchronise stream start and stop operations. + +if COMP_COPIER + +config COPIER_GAIN + bool "COPIER gain feature" + default y + help + Select for using copier gain feature. There are three modes available: + - Static gain: gain is set at initialization and remains constant. + - Mute: gain is set to 0, signal is muted. + - Transition gain: gain is set to a target value over a specified time. + Common use cases are fade-in and fade-out effects. +endif diff --git a/src/audio/copier/Kconfig.simd b/src/audio/copier/Kconfig.simd new file mode 100644 index 000000000000..d8639fcdb069 --- /dev/null +++ b/src/audio/copier/Kconfig.simd @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: BSD-3-Clause + +comment "COPIER optimization level select" + +choice "COPIER_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for COPIER module" + depends on COMP_COPIER + default COPIER_HIFI_MAX + + config COPIER_HIFI_MAX + prompt "SIMD will selected by toolchain pre-defined header" + bool + help + When this was selected, optimization level will be determined + by toolchain pre-defined macros in core isa header file. + + config COPIER_HIFI_5 + prompt "choose HIFI5 intrinsic optimized COPIER module" + bool + help + This option used to build HIFI5 optimized COPIER code + + config COPIER_HIFI_4 + prompt "choose HIFI4 intrinsic optimized COPIER module" + bool + help + This option used to build HIFI4 optimized COPIER code + + config COPIER_HIFI_3 + prompt "choose HIFI3 intrinsic optimized COPIER module" + bool + help + This option used to build HIFI3 intrinsic optimized COPIER code + + config COPIER_HIFI_NONE + prompt "choose generic C COPIER module, no HIFI SIMD involved" + bool + help + This option used to build COPIER generic code. +endchoice diff --git a/src/audio/copier/README.md b/src/audio/copier/README.md new file mode 100644 index 000000000000..f120f9cd7a86 --- /dev/null +++ b/src/audio/copier/README.md @@ -0,0 +1,22 @@ +# Copier Architecture + +This directory contains the Copier component. + +## Overview + +The Copier is a versatile component responsible for moving data smoothly between hardware endpoints (DAIs, Host APIs) and internal buffers. It may also apply simple format conversions (e.g., 16-bit to 32-bit). + +## Architecture Diagram + +```mermaid +graph LR + DMA[DMA Engine] <--> Copier[Copier Component] + Copier <--> Buf[Internal Buffer] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the `COMP_COPIER` component (depends on IPC 4). Also defines `COMP_DAI`, options to reverse DMA/DAI trigger stop ordering (`COMP_DAI_STOP_TRIGGER_ORDER_REVERSE`), DAI grouping, and an optional copier gain feature (`COPIER_GAIN`) for static gain, mute, or transition gain (fade-in/fade-out). +- **CMakeLists.txt**: Includes base copier implementations (HIFI, generic, host, DAI). If `CONFIG_IPC4_GATEWAY` is enabled, it adds `copier_ipcgtw.c`, and if `CONFIG_COPIER_GAIN` is selected, includes `copier_gain.c`. +- **copier.toml**: Contains topology configurations, describing UUID, pins, and complex `mod_cfg` tuples tailored per platform (`CONFIG_METEORLAKE`, `CONFIG_LUNARLAKE`, or `CONFIG_SOC_ACE30`/`40`). +- **Topology (.conf)**: `tools/topology/topology2/include/components/dai-copier.conf` (among others like `host-copier`, `module-copier`) define copier widget objects. They configure connection-specific attributes like `copier_type` (e.g., `HDA`, `SSP`, `DMIC`, `SAI`), `direction` (`playback` or `capture`), `node_type`, and `cpc`. `dai-copier` defaults to UUID `83:0c:a0:9b:12:CA:83:4a:94:3c:1f:a2:e8:2f:9d:da`. diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c new file mode 100644 index 000000000000..d2aefcb13be6 --- /dev/null +++ b/src/audio/copier/copier.c @@ -0,0 +1,1219 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Rander Wang <rander.wang@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc4/alh.h> +#include <ipc4/base-config.h> +#include <ipc4/module.h> +#include <ipc4/error_status.h> +#include <ipc4/gateway.h> +#include <ipc4/fw_reg.h> +#include <ipc/dai.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "copier.h" +#include "host_copier.h" +#include "dai_copier.h" +#include "ipcgtw_copier.h" +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include <zephyr/drivers/mic_privacy/intel/mic_privacy.h> +#endif + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +#include <zephyr/drivers/dai.h> +#endif + +LOG_MODULE_REGISTER(copier, CONFIG_SOF_LOG_LEVEL); + +/* this id aligns windows driver requirement to support windows driver */ +SOF_DEFINE_REG_UUID(copier); + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +static void mic_privacy_event(void *arg, enum notify_id type, void *data) +{ + struct mic_privacy_data *mic_priv_data = arg; + struct mic_privacy_settings *mic_privacy_settings = data; + + if (type == NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE) { + LOG_INF("state1 = %d, state2 = %d ", + mic_privacy_settings->mic_privacy_state, mic_priv_data->mic_privacy_state); + + if (mic_privacy_settings->mic_privacy_state == MIC_PRIV_UNMUTED) { + if (mic_priv_data->mic_privacy_state == MIC_PRIV_MUTED) { + mic_priv_data->mic_privacy_state = MIC_PRIV_FADE_IN; + LOG_INF("switch to FADE_IN"); + } + } else { + /* In case when mute would be triggered before copier instantiation. */ + if (mic_priv_data->mic_privacy_state != MIC_PRIV_MUTED) { + mic_priv_data->mic_privacy_state = MIC_PRIV_FADE_OUT; + LOG_INF("switch to FADE_OUT"); + } + } + mic_priv_data->max_ramp_time_in_ms = (mic_privacy_settings->max_ramp_time * 1000) / + ADSP_RTC_FREQUENCY; + } +} + +static int mic_privacy_configure(struct processing_module *mod, struct copier_data *cd) +{ + struct mic_privacy_data *mic_priv_data; + int ret; + + mic_priv_data = mod_zalloc(mod, sizeof(struct mic_privacy_data)); + if (!mic_priv_data) + return -ENOMEM; + + if (cd->gtw_type == ipc4_gtw_dmic) + mic_privacy_enable_dmic_irq(true); + + mic_priv_data->audio_freq = cd->config.base.audio_fmt.sampling_frequency; + + uint32_t zeroing_wait_time = (mic_privacy_get_dma_zeroing_wait_time() * 1000) / + ADSP_RTC_FREQUENCY; + + ret = copier_gain_set_params(mod->dev, &mic_priv_data->mic_priv_gain_params, + zeroing_wait_time, SOF_DAI_INTEL_NONE); + if (ret != 0) { + mod_free(mod, mic_priv_data); + return ret; + } + + cd->mic_priv = mic_priv_data; + + ret = notifier_register(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, + mic_privacy_event, 0); + + if (ret != 0) + mod_free(mod, mic_priv_data); + + return ret; +} + +static void mic_privacy_free(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + + if (cd->gtw_type == ipc4_gtw_dmic) + mic_privacy_enable_dmic_irq(false); + + notifier_unregister(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE); + + mod_free(mod, cd->mic_priv); +} +#endif + +__cold static int copier_init(struct processing_module *mod) +{ + union ipc4_connector_node_id node_id; + struct copier_data *cd; + struct comp_dev *dev = mod->dev; + struct module_data *md = &mod->priv; + struct ipc4_copier_module_cfg *copier = (struct ipc4_copier_module_cfg *)md->cfg.init_data; + size_t cfg_total_size = sizeof(*copier); + size_t gtw_cfg_var_size = 0; + int i, ret = 0; + + assert_can_be_cold(); + + if (copier->gtw_cfg.config_length > 1) { + /* one word already included in gateway_cfg struct hence subtraction */ + gtw_cfg_var_size += (copier->gtw_cfg.config_length - 1) << 2; + cfg_total_size += gtw_cfg_var_size; + } + + cd = mod_zalloc(mod, sizeof(*cd) + gtw_cfg_var_size); + if (!cd) + return -ENOMEM; + + md->private = cd; + + if (memcpy_s(&cd->config, cfg_total_size, copier, cfg_total_size) < 0) { + ret = -EINVAL; + goto error; + } + + for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) + cd->out_fmt[i] = cd->config.out_fmt; + + node_id = copier->gtw_cfg.node_id; + /* copier is linked to gateway */ + if (node_id.dw != IPC4_INVALID_NODE_ID) { + cd->direction = get_gateway_direction(node_id.f.dma_type); + + switch (node_id.f.dma_type) { + case ipc4_hda_host_output_class: + case ipc4_hda_host_input_class: + ret = copier_host_create(mod, copier, dev->pipeline); + if (ret < 0) { + comp_err(dev, "unable to create host"); + goto error; + } +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->direction == SOF_IPC_STREAM_CAPTURE && + node_id.f.dma_type == ipc4_hda_host_output_class) { + ret = mic_privacy_configure(mod, cd); + if (ret < 0) { + comp_err(dev, "unable to configure mic privacy"); + goto error; + } + } +#endif + break; + case ipc4_hda_link_output_class: + case ipc4_hda_link_input_class: + case ipc4_dmic_link_input_class: + case ipc4_i2s_link_output_class: + case ipc4_i2s_link_input_class: + case ipc4_alh_link_output_class: + case ipc4_alh_link_input_class: + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: + ret = copier_dai_create(dev, cd, copier, dev->pipeline); + if (ret < 0) { + comp_err(dev, "unable to create dai"); + goto error; + } +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->direction == SOF_IPC_STREAM_CAPTURE) { + ret = mic_privacy_configure(mod, cd); + if (ret < 0) { + comp_err(dev, "unable to configure mic privacy"); + goto error; + } + } +#endif + break; +#if CONFIG_IPC4_GATEWAY + case ipc4_ipc_output_class: + case ipc4_ipc_input_class: + ret = copier_ipcgtw_create(mod, copier, dev->pipeline); + if (ret < 0) { + comp_err(dev, "unable to create IPC gateway"); + goto error; + } + break; +#endif + default: + comp_err(dev, "unsupported dma type %x", (uint32_t)node_id.f.dma_type); + ret = -EINVAL; + goto error; + }; + + dev->direction_set = true; + } else { + cd->gtw_type = ipc4_gtw_none; + + /* set max sink count for module copier */ + mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; + } + + dev->direction = cd->direction; + dev->state = COMP_STATE_READY; + return 0; +error: + mod_free(mod, cd); + return ret; +} + +__cold static int copier_free(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + mic_privacy_free(mod); +#endif + + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + copier_host_free(mod); + else + /* handle gtw case */ + copier_ipcgtw_free(mod); + break; + case SOF_COMP_DAI: + copier_dai_free(mod); + break; + default: + break; + } + + mod_free(mod, cd); + + return 0; +} + +static int copier_params(struct processing_module *mod); + +static int copier_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + ret = copier_params(mod); + if (ret < 0) + return ret; + + comp_info(dev, "entry"); + + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) { + ret = host_common_prepare(cd->hd); + if (ret < 0) + return ret; + } + break; + case SOF_COMP_DAI: + ret = copier_dai_prepare(dev, cd); + if (ret < 0) + return ret; + break; + default: + break; + } + + if (!cd->endpoint_num) { + /* set up format conversion function for pin 0, for other pins (if any) + * format is set in IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT handler + */ + cd->converter[0] = get_converter_func(&cd->config.base.audio_fmt, + &cd->config.out_fmt, ipc4_gtw_none, + ipc4_bidirection, DUMMY_CHMAP); + if (!cd->converter[0]) { + comp_err(dev, "can't support for in format %d, out format %d", + cd->config.base.audio_fmt.depth, cd->config.out_fmt.depth); + return -EINVAL; + } + } + + return 0; +} + +static int copier_reset(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + struct ipc4_pipeline_registers pipe_reg; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + cd->input_total_data_processed = 0; + cd->output_total_data_processed = 0; + + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + host_common_reset(cd->hd, dev->state); + else + copier_ipcgtw_reset(dev); + break; + case SOF_COMP_DAI: + copier_dai_reset(cd, dev); + break; + default: + break; + } + + if (cd->pipeline_reg_offset) { + pipe_reg.stream_start_offset = (uint64_t)-1; + pipe_reg.stream_end_offset = (uint64_t)-1; + mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg, sizeof(pipe_reg)); + } + + return 0; +} + +static int copier_comp_trigger(struct comp_dev *dev, int cmd) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct sof_ipc_stream_posn posn; + struct comp_dev *dai_copier; + struct comp_buffer *buffer; + uint32_t latency; + int ret; + + comp_dbg(dev, "entry"); + + ret = comp_set_state(dev, cmd); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) { + ret = host_common_trigger(cd->hd, dev, cmd); + if (ret < 0) + return ret; + } + break; + case SOF_COMP_DAI: + ret = copier_dai_trigger(cd, dev, cmd); + break; + default: + break; + } + + /* For capture cd->pipeline_reg_offset == 0 */ + 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) { + /* + * If the (playback) stream does not have a dai, the offset + * calculation is skipped + */ + comp_info(dev, + "No dai copier found, start/end offset is not calculated"); + return 0; + } + + /* dai is in another pipeline and it is not prepared or active */ + if (dai_copier->state <= COMP_STATE_READY) { + struct ipc4_pipeline_registers pipe_reg; + + comp_warn(dev, "dai is not ready"); + + pipe_reg.stream_start_offset = 0; + pipe_reg.stream_end_offset = 0; + mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg, sizeof(pipe_reg)); + + return 0; + } + + comp_position(dai_copier, &posn); + + /* update stream start and end offset for running message in host copier + * host driver uses DMA link counter to calculate stream position, but it is + * not fit for the following 3 cases: + * (1) dai is enabled before host since they are in different pipelines + * (2) multiple stream are mixed into one dai + * (3) one stream is paused but the dai is still working with other stream + * + * host uses stream_start_offset & stream_end_offset to deal with such cases: + * if (stream_start_offset) { + * position = DMA counter - stream_start_offset + * if (stream_stop_offset) + * position = stream_stop_offset -stream_start_offset; + * } else { + * position = 0; + * } + * When host component is started stream_start_offset is set to DMA counter + * plus the latency from host to dai since the accurate DMA counter should be + * used when the data arrives dai from host. + * + * When pipeline is paused, stream_end_offset will save current DMA counter + * for resume case + * + * When pipeline is resumed, calculate stream_start_offset based on current + * DMA counter and stream_end_offset + */ + if (cmd == COMP_TRIGGER_START) { + struct ipc4_pipeline_registers pipe_reg; + + if (list_is_empty(&dai_copier->bsource_list)) { + comp_err(dev, "No source buffer bound to dai_copier"); + return -EINVAL; + } + + buffer = comp_dev_get_first_data_producer(dai_copier); + pipe_reg.stream_start_offset = posn.dai_posn + + latency * audio_stream_period_bytes(&buffer->stream, dev->frames); + 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) { + uint64_t stream_end_offset; + + stream_end_offset = posn.dai_posn; + mailbox_sw_regs_write(cd->pipeline_reg_offset + sizeof(uint64_t), + &stream_end_offset, sizeof(stream_end_offset)); + } else if (cmd == COMP_TRIGGER_RELEASE) { + struct ipc4_pipeline_registers pipe_reg; + + pipe_reg.stream_start_offset = mailbox_sw_reg_read64(cd->pipeline_reg_offset); + pipe_reg.stream_end_offset = mailbox_sw_reg_read64(cd->pipeline_reg_offset + + sizeof(pipe_reg.stream_start_offset)); + pipe_reg.stream_start_offset += posn.dai_posn - pipe_reg.stream_end_offset; + + if (list_is_empty(&dai_copier->bsource_list)) { + comp_err(dev, "No source buffer bound to dai_copier"); + return -EINVAL; + } + + buffer = comp_dev_get_first_data_producer(dai_copier); + pipe_reg.stream_start_offset += latency * + audio_stream_period_bytes(&buffer->stream, dev->frames); + mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg.stream_start_offset, + sizeof(pipe_reg.stream_start_offset)); + } + + return ret; +} + +static int do_conversion_copy(struct comp_dev *dev, + struct copier_data *cd, + struct comp_buffer *src, + struct comp_buffer *sink, + struct comp_copy_limits *processed_data) +{ + int i; + + /* buffer params might be not yet configured by component on another pipeline */ + if (!audio_buffer_hw_params_configured(&src->audio_buffer) || + !audio_buffer_hw_params_configured(&sink->audio_buffer)) + return 0; + + comp_get_copy_limits(src, sink, processed_data); + + /* + * Buffer ID is constructed as IPC4_COMP_ID(src_queue, dst_queue). + * From the buffer's perspective, copier's sink is the source, + * so we use IPC4_SRC_QUEUE_ID() to get the correct copier sink index. + */ + i = IPC4_SRC_QUEUE_ID(buf_get_id(sink)); + if (i >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) + return -EINVAL; + buffer_stream_invalidate(src, processed_data->source_bytes); + + cd->converter[i](&src->stream, 0, &sink->stream, 0, + processed_data->frames * audio_stream_get_channels(&src->stream), + DUMMY_CHMAP); + + buffer_stream_writeback(sink, processed_data->sink_bytes); + comp_update_buffer_produce(sink, processed_data->sink_bytes); + + return 0; +} + +static int copier_copy_to_sinks(struct copier_data *cd, struct comp_dev *dev, + struct comp_buffer *src_c, + struct comp_copy_limits *processed_data) +{ + struct comp_buffer *sink; + int ret = 0; + + /* module copy, one source to multiple sink buffers */ + comp_dev_for_each_consumer(dev, sink) { + struct comp_dev *sink_dev; + + sink_dev = comp_buffer_get_sink_component(sink); + processed_data->sink_bytes = 0; + if (sink_dev->state == COMP_STATE_ACTIVE) { + ret = do_conversion_copy(dev, cd, src_c, sink, processed_data); + cd->output_total_data_processed += processed_data->sink_bytes; + } + if (ret < 0) { + comp_err(dev, "failed to copy buffer for comp %x", + dev->ipc_config.id); + break; + } + } + + if (!ret) { + comp_update_buffer_consume(src_c, processed_data->source_bytes); + /* module copy case with endpoint_num == 0 or src_c as source buffer */ + if (!cd->endpoint_num || cd->bsource_buffer) + cd->input_total_data_processed += processed_data->source_bytes; + } + + return ret; +} + +static int copier_module_copy(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 copier_data *cd = module_get_private_data(mod); + struct comp_buffer *src_c; + struct comp_copy_limits processed_data; + int i; + + if (!num_input_buffers || !num_output_buffers) + return 0; + + src_c = container_of(input_buffers[0].data, struct comp_buffer, stream); + + processed_data.source_bytes = 0; + + /* convert format and copy to each active sink */ + for (i = 0; i < num_output_buffers; i++) { + struct comp_buffer *sink_c; + struct comp_dev *sink_dev; + + sink_c = container_of(output_buffers[i].data, struct comp_buffer, stream); + sink_dev = comp_buffer_get_sink_component(sink_c); + processed_data.sink_bytes = 0; + if (sink_dev->state == COMP_STATE_ACTIVE) { + uint32_t source_samples; + int sink_queue_id; + + /* + * Buffer ID is constructed as IPC4_COMP_ID(src_queue, dst_queue). + * From the buffer's perspective, copier's sink is the source, + * so we use IPC4_SRC_QUEUE_ID() to get the correct copier sink index. + */ + sink_queue_id = IPC4_SRC_QUEUE_ID(buf_get_id(sink_c)); + if (sink_queue_id >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) + return -EINVAL; + + comp_get_copy_limits(src_c, sink_c, &processed_data); + + source_samples = processed_data.frames * + audio_stream_get_channels(input_buffers[0].data); + cd->converter[sink_queue_id](input_buffers[0].data, 0, + output_buffers[i].data, 0, + source_samples, DUMMY_CHMAP); + + output_buffers[i].size = processed_data.sink_bytes; + cd->output_total_data_processed += processed_data.sink_bytes; + } + } + + input_buffers[0].consumed = processed_data.source_bytes; + + return 0; +} + +static int copier_multi_endpoint_dai_copy(struct copier_data *cd, struct comp_dev *dev) +{ + struct comp_copy_limits processed_data; + struct comp_buffer *src; + int ret; + + processed_data.source_bytes = 0; + + if (!cd->bsource_buffer) { + /* gateway(s) as input */ + ret = dai_zephyr_multi_endpoint_copy(cd->dd, dev, cd->multi_endpoint_buffer, + cd->endpoint_num); + if (ret < 0) + return ret; + + ret = copier_copy_to_sinks(cd, dev, cd->multi_endpoint_buffer, &processed_data); + + return ret; + } + + /* component as input */ + if (list_is_empty(&dev->bsource_list)) { + comp_err(dev, "No source buffer bound"); + return -EINVAL; + } + + src = comp_dev_get_first_data_producer(dev); + + /* gateway(s) on output */ + ret = do_conversion_copy(dev, cd, src, cd->multi_endpoint_buffer, &processed_data); + if (ret < 0) + return ret; + + ret = dai_zephyr_multi_endpoint_copy(cd->dd, dev, cd->multi_endpoint_buffer, + cd->endpoint_num); + if (!ret) { + comp_update_buffer_consume(src, processed_data.source_bytes); + cd->input_total_data_processed += processed_data.source_bytes; + } + + return ret; +} + +/* Copier has one input and one or more outputs. Maximum of one gateway can be connected + * to copier or no gateway connected at all. Gateway can only be connected to either input + * pin 0 (the only input) or output pin 0. With or without connected gateway it is also + * possible to have component(s) connected on input and/or output pins. + * + * A special exception is a multichannel ALH gateway case. These are multiple gateways + * but should be treated like a single gateway to satisfy rules above. Data from such + * gateways has to be multiplexed into single stream (for input gateways) or demultiplexed + * from single stream (for output gateways) so such gateways work kind of like a single + * gateway, i.e., produce/consume single stream. + */ +static int copier_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 copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + return host_common_copy(cd->hd, dev, copier_host_dma_cb); + + /* do nothing in the gateway copier case */ + return 0; + case SOF_COMP_DAI: + if (cd->endpoint_num == 1) + return dai_common_copy(cd->dd[0], dev, cd->converter); + + return copier_multi_endpoint_dai_copy(cd, dev); + default: + break; + } + + /* module copier case */ + return copier_module_copy(mod, input_buffers, num_input_buffers, output_buffers, + num_output_buffers); +} + +static int copier_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int i, ret = 0; + + comp_dbg(dev, "entry"); + + copier_update_params(cd, dev, params); + + for (i = 0; i < cd->endpoint_num; i++) { + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + ret = copier_host_params(cd, dev, params); + else + /* handle gtw case */ + ret = copier_ipcgtw_params(cd->ipcgtw_data, dev, params); + break; + case SOF_COMP_DAI: + ret = copier_dai_params(cd, dev, params, i); + break; + default: + break; + } + + if (ret < 0) + break; + } + + return ret; +} + +__cold static int copier_set_sink_fmt(struct comp_dev *dev, const void *data, + int max_data_size) +{ + const struct ipc4_copier_config_set_sink_format *sink_fmt = data; + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + uint32_t chmap; + + assert_can_be_cold(); + + if (max_data_size < sizeof(*sink_fmt)) { + comp_err(dev, "error: max_data_size %d should be bigger than %d", max_data_size, + sizeof(*sink_fmt)); + return -EINVAL; + } + + if (sink_fmt->sink_id >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) { + comp_err(dev, "error: sink id %d is out of range", sink_fmt->sink_id); + return -EINVAL; + } + + if (memcmp(&cd->config.base.audio_fmt, &sink_fmt->source_fmt, + sizeof(sink_fmt->source_fmt))) { + comp_err(dev, "error: source fmt should be equal to input fmt"); + return -EINVAL; + } + + if (cd->endpoint_num && cd->bsource_buffer && + sink_fmt->sink_id == IPC4_COPIER_GATEWAY_PIN) { + comp_err(dev, "can't change gateway format"); + return -EINVAL; + } + + cd->out_fmt[sink_fmt->sink_id] = sink_fmt->sink_fmt; + + if (cd->endpoint_num > 0 && dev->ipc_config.type == SOF_COMP_DAI) + chmap = cd->dd[0]->chmap; + else + chmap = DUMMY_CHMAP; + + cd->converter[sink_fmt->sink_id] = get_converter_func(&sink_fmt->source_fmt, + &sink_fmt->sink_fmt, ipc4_gtw_none, + ipc4_bidirection, chmap); + + return 0; +} + +__cold static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const char *data) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + uint32_t attenuation; + enum sof_ipc_frame valid_fmt, frame_fmt; + + assert_can_be_cold(); + + /* only support attenuation in format of 32bit */ + if (data_offset > sizeof(uint32_t)) { + comp_err(dev, "attenuation data size %d is incorrect", data_offset); + return -EINVAL; + } + + attenuation = *(const uint32_t *)data; + if (attenuation > 31) { + comp_err(dev, "attenuation %d is out of range", attenuation); + return -EINVAL; + } + + audio_stream_fmt_conversion(cd->config.out_fmt.depth, + cd->config.out_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + cd->config.out_fmt.s_type); + + if (frame_fmt < SOF_IPC_FRAME_S24_4LE) { + comp_err(dev, "frame_fmt %d isn't supported by attenuation", + frame_fmt); + return -EINVAL; + } + + cd->attenuation = attenuation; + + return 0; +} + +__cold static int set_chmap(struct comp_dev *dev, const void *data, size_t data_size) +{ + const struct ipc4_copier_config_channel_map *chmap_cfg = data; + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + enum ipc4_direction_type dir; + struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt; + struct ipc4_audio_format out_fmt = cd->config.out_fmt; + pcm_converter_func process; + pcm_converter_func converters[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; + int i; + uint32_t irq_flags; + + assert_can_be_cold(); + + if (data_size < sizeof(*chmap_cfg)) { + comp_err(dev, "Wrong payload size: %d", data_size); + return -EINVAL; + } + + if (cd->endpoint_num == 0 || dev->ipc_config.type != SOF_COMP_DAI) { + comp_err(dev, "Only DAI gateway supports changing chmap"); + return -EINVAL; + } + + comp_info(dev, "New chmap requested: %x", chmap_cfg->channel_map); + + if (!cd->dd[0]->dma_buffer) { + /* DMA buffer not yet created. Remember the chmap, it will be used + * later in .params() handler. + * + * The assignment should be atomic as LL thread can preempt this IPC thread. + */ + cd->dd[0]->chmap = chmap_cfg->channel_map; + return 0; + } + + copier_dai_adjust_params(cd, &in_fmt, &out_fmt); + + dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ? + ipc4_playback : ipc4_capture; + + process = get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, chmap_cfg->channel_map); + + if (!process) { + comp_err(dev, "No gtw converter func found!"); + return -EINVAL; + } + + /* Channel map is same for all sinks. However, as sinks allowed to have different + * sample formats, get new convert/remap function for each sink. + */ + for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) { + if (cd->converter[i]) { + converters[i] = get_converter_func(&in_fmt, &cd->out_fmt[i], + ipc4_gtw_none, ipc4_bidirection, + chmap_cfg->channel_map); + /* Do not report an error if converter not found as sinks could be + * bound/unbound on a fly and out_fmt[i] may contain obsolete data. + */ + } else { + converters[i] = NULL; + } + } + + /* Atomically update chmap, process and converters */ + irq_local_disable(irq_flags); + + cd->dd[0]->chmap = chmap_cfg->channel_map; + cd->dd[0]->process = process; + for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) + cd->converter[i] = converters[i]; + + irq_local_enable(irq_flags); + + return 0; +} + +__cold static int copier_set_configuration(struct processing_module *mod, + uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, + uint8_t *response, + size_t response_size) +{ + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + comp_dbg(dev, "copier_set_config()"); + + switch (config_id) { + case IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT: + return copier_set_sink_fmt(dev, fragment, fragment_size); + case IPC4_COPIER_MODULE_CFG_ATTENUATION: + return set_attenuation(dev, fragment_size, (const char *)fragment); + case IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP: + return set_chmap(dev, fragment, fragment_size); + default: + return -EINVAL; + } +} + +static inline void convert_u64_to_u32s(uint64_t val, uint32_t *val_l, uint32_t *val_h) +{ + *val_l = (uint32_t)(val & 0xffffffff); + *val_h = (uint32_t)((val >> 32) & 0xffffffff); +} + +__cold static int copier_get_configuration(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct copier_data *cd = module_get_private_data(mod); + struct ipc4_llp_reading_extended llp_ext; + struct comp_dev *dev = mod->dev; + struct sof_ipc_stream_posn posn; + struct ipc4_llp_reading llp; + + assert_can_be_cold(); + + if (cd->ipc_gtw) + return 0; + + switch (config_id) { + case IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING: + if (!cd->endpoint_num || + comp_get_endpoint_type(dev) != + COMP_ENDPOINT_DAI) { + comp_err(dev, "Invalid component type"); + return -EINVAL; + } + + if (*data_offset_size < sizeof(struct ipc4_llp_reading)) { + comp_err(dev, "Config size %d is inadequate", *data_offset_size); + return -EINVAL; + } + + *data_offset_size = sizeof(struct ipc4_llp_reading); + memset(&llp, 0, sizeof(llp)); + + if (dev->state != COMP_STATE_ACTIVE) { + memcpy_s(fragment, sizeof(llp), &llp, sizeof(llp)); + return 0; + } + + /* get llp from dai */ + 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); + memcpy_s(fragment, sizeof(llp), &llp, sizeof(llp)); + + return 0; + + case IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED: + if (!cd->endpoint_num || + comp_get_endpoint_type(dev) != + COMP_ENDPOINT_DAI) { + comp_err(dev, "Invalid component type"); + return -EINVAL; + } + + if (*data_offset_size < sizeof(struct ipc4_llp_reading_extended)) { + comp_err(dev, "Config size %d is inadequate", *data_offset_size); + return -EINVAL; + } + + *data_offset_size = sizeof(struct ipc4_llp_reading_extended); + memset(&llp_ext, 0, sizeof(llp_ext)); + + if (dev->state != COMP_STATE_ACTIVE) { + memcpy_s(fragment, sizeof(llp_ext), &llp_ext, sizeof(llp_ext)); + return 0; + } + + /* get llp from dai */ + comp_position(dev, &posn); + + convert_u64_to_u32s(posn.comp_posn, &llp_ext.llp_reading.llp_l, + &llp_ext.llp_reading.llp_u); + convert_u64_to_u32s(posn.wallclock, &llp_ext.llp_reading.wclk_l, + &llp_ext.llp_reading.wclk_u); + + convert_u64_to_u32s(posn.dai_posn, &llp_ext.tpd_low, &llp_ext.tpd_high); + memcpy_s(fragment, sizeof(llp_ext), &llp_ext, sizeof(llp_ext)); + + return 0; + + default: + comp_err(dev, "unsupported param %d", config_id); + break; + } + + return -EINVAL; +} + +static uint64_t copier_get_processed_data(struct comp_dev *dev, uint32_t stream_no, bool input) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + uint64_t ret = 0; + bool source; + + /* + * 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) { + 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; + break; + case SOF_COMP_DAI: + source = dev->direction == SOF_IPC_STREAM_CAPTURE; + if (source == input) + ret = cd->dd[0]->total_data_processed; + break; + default: + comp_err(dev, "Unexpected gateway type encountered: %d", + dev->ipc_config.type); + break; + } + } + } else { + if (stream_no == 0) + ret = input ? cd->input_total_data_processed : + cd->output_total_data_processed; + } + + return ret; +} + +static int copier_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + int ret = 0; + + /* Exit if no endpoints */ + if (!cd->endpoint_num) + return -EINVAL; + + 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_common_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 processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct dai_data *dd = cd->dd[0]; + + return dai_common_ts_config_op(dd, dev); +} + +static int copier_dai_ts_start_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct dai_data *dd = cd->dd[0]; + + comp_dbg(dev, "dai_ts_start()"); + + return dai_common_ts_start(dd, dev); +} + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +static int copier_dai_ts_get_op(struct comp_dev *dev, struct dai_ts_data *tsd) +#else +static int copier_dai_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd) +#endif +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct dai_data *dd = cd->dd[0]; + + comp_dbg(dev, "dai_ts_get()"); + + return dai_common_ts_get(dd, dev, tsd); +} + +static int copier_dai_ts_stop_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct dai_data *dd = cd->dd[0]; + + comp_dbg(dev, "dai_ts_stop()"); + + return dai_common_ts_stop(dd, dev); +} + +__cold static int copier_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct dai_data *dd = cd->dd[0]; + + assert_can_be_cold(); + + if (dev->ipc_config.type != SOF_COMP_DAI) + return -EINVAL; + + return dai_common_get_hw_params(dd, dev, params, dir); +} + +__cold static int copier_bind(struct processing_module *mod, struct bind_info *bind_data) +{ + const struct ipc4_module_bind_unbind *const bu = bind_data->ipc4_data; + const uint32_t src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); + const uint32_t src_queue_id = bu->extension.r.src_queue; + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + if (dev->ipc_config.id != src_id) + return 0; /* Another component is a data producer */ + + /* update sink format */ + struct comp_buffer *buffer; + + comp_dev_for_each_consumer(dev, buffer) { + uint32_t id = IPC4_SRC_QUEUE_ID(buf_get_id(buffer)); + + if (src_queue_id == id) { + ipc4_update_buffer_format(buffer, &cd->out_fmt[id]); + return 0; + } + } + + comp_err(dev, "No sink buffer found for src_queue = %u", src_queue_id); + return -ENODEV; +} + +__cold static int copier_unbind(struct processing_module *mod, struct bind_info *unbind_data) +{ + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + if (dev->ipc_config.type == SOF_COMP_DAI) { + struct dai_data *dd = cd->dd[0]; + + return dai_zephyr_unbind(dd, dev, unbind_data); + } + + return 0; +} + +static struct module_endpoint_ops copier_endpoint_ops = { + .get_total_data_processed = copier_get_processed_data, + .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, + .trigger = copier_comp_trigger +}; + +static const struct module_interface copier_interface = { + .init = copier_init, + .prepare = copier_prepare, + .process_audio_stream = copier_process, + .reset = copier_reset, + .free = copier_free, + .set_configuration = copier_set_configuration, + .get_configuration = copier_get_configuration, + .bind = copier_bind, + .unbind = copier_unbind, + .endpoint_ops = &copier_endpoint_ops, +}; + +DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_uuid), LOG_LEVEL_INFO); + +DECLARE_MODULE_ADAPTER(copier_interface, copier_uuid, copier_comp_tr); +SOF_MODULE_INIT(copier, sys_comp_module_copier_interface_init); diff --git a/src/audio/copier/copier.h b/src/audio/copier/copier.h new file mode 100644 index 000000000000..4e29e18d33a6 --- /dev/null +++ b/src/audio/copier/copier.h @@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/copier.h + * \brief IPC4 copier definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_COPIER_H__ +#define __SOF_IPC4_COPIER_H__ + +#include <stdint.h> +#include <ipc4/base-config.h> +#include <ipc4/gateway.h> +#include <ipc4/alh.h> + +#include <sof/compiler_attributes.h> +#include <sof/audio/buffer.h> +#include <sof/audio/pcm_converter.h> +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include <sof/lib/notifier.h> +#include <sof/audio/mic_privacy_manager.h> +#endif + +static const uint32_t INVALID_QUEUE_ID = 0xFFFFFFFF; + +/* copier Module Configuration & Interface + * UUID: 9BA00C83-CA12-4A83-943C-1FA2E82F9DDA + * + * Copier may be instantiated and bound in one of following configurations: + * + * - case 1: + * digraph Module_Copier_Module { + * InputGateway + * InputGateway -> Copier + * + * DestinationMod + * Copier -> DestinationMod + * } + * + * digraph Module_Copier_Gateways { + * SourceMod + * SourceMod -> Copier + * + * OutputGateway + * Copier -> OutputGateway + * } + * - case 3: + * digraph Module_Copier_Module { + * SourceMod + * SourceMod -> Copier + * + * DestinationMod + * Copier -> DestinationMod + * } + * + * - case 4: + * digraph Module_Copier_Module { + * SourceMod + * + * SourceMod -> Copier + * + * DestinationMod + * OutputGateway + * + * Copier -> OutputGateway + * Copier -> DestinationMod + * } + * + * In cases 1 and 2, the initial configuration must include Gateway Configuration + * data along with valid Node ID of the gateway to be connected on either + * Copier's end. + * + * Gateway can only be connected to input pin "0" or output pin "0". + * + * Initial configuration data allows setup audio format of main Copier's pins, + * input pin "0" and output pin "0" and prepare PCM conversion routine if any is + * required. However Copier supports up to #COPIER_MODULE_OUTPUT_PINS_COUNT + * output pins. Before any additional output pin is used in binding operation, + * the host driver has to send run-time parameter to setup sink formwat + * (#COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT) first to setup a PCM conversion + * routine if any is required. + */ + +#define IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT 4 + +/* + * Gateway can only be connected to input pin "0" or output pin "0". + */ +#define IPC4_COPIER_GATEWAY_PIN 0 + +enum ipc4_copier_features { + /* ff FAST_MODE bit is set in CopierModuleCfg::copier_feature_mask then + * copier is able to transfer more than ibs. This bit shall be set only if + * all sinks are connected to data processing queue. + */ + IPC4_COPIER_FAST_MODE = 0 +}; + +#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION +#define HDA_SYNC_FPI_UPDATE_GROUP 0 +struct ipc4_copier_sync_group { + uint32_t group_id; + uint32_t fpi_update_period_usec; +} __packed __aligned(4); +#endif + +struct ipc4_copier_gateway_cfg { + /* ID of Gateway Node. If node_id is valid, i.e. != -1, copier instance is connected to the + * specified gateway using either input pin 0 or output pin 0 depending on + * the node's direction, otherwise the data in this structure is ignored. + */ + union ipc4_connector_node_id node_id; + /* preferred Gateway DMA buffer size (in bytes). + * FW attempts to allocate DMA buffer according to this value, however it may + * fall back to IBS/OBS * 2 in case there is no memory available for deeper + * buffering. + */ + uint32_t dma_buffer_size; + /* length of gateway node configuration blob specified in #config_data. + * Length must be specified in number of dwords. + * Refer to the specific gateway documentation for details on the node + * configuration blob requirements. + */ + uint32_t config_length; + /* gateway node configuration blob */ + uint32_t config_data[1]; +} __attribute__((packed, aligned(4))); + +struct ipc4_copier_module_cfg { + struct ipc4_base_module_cfg base; + + /* audio format for output pin 0 */ + struct ipc4_audio_format out_fmt; + uint32_t copier_feature_mask; + struct ipc4_copier_gateway_cfg gtw_cfg; +} __attribute__((packed, aligned(4))); + +enum ipc4_copier_module_config_params { + /* Use LARGE_CONFIG_SET to initialize timestamp event. Ipc mailbox must + * contain properly built CopierConfigTimestampInitData struct. + */ + IPC4_COPIER_MODULE_CFG_PARAM_TIMESTAMP_INIT = 1, + /* Use LARGE_CONFIG_SET to initialize copier sink. Ipc mailbox must contain + * properly built CopierConfigSetSinkFormat struct. + */ + IPC4_COPIER_MODULE_CFG_PARAM_SET_SINK_FORMAT = 2, + /* Use LARGE_CONFIG_SET to initialize and enable on Copier data segment + * event. Ipc mailbox must contain properly built DataSegmentEnabled struct. + */ + IPC4_COPIER_MODULE_CFG_PARAM_DATA_SEGMENT_ENABLED = 3, + /* Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non + * HD-A gateways. + */ + IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING = 4, + /* Use LARGE_CONFIG_GET to retrieve Linear Link Position (LLP) value for non + * HD-A gateways and corresponding total processed data + * Sample code to retrieve LlpReadingExtended: + * Message::LargeConfigOp message(true, COPIER_MODULE_ID, KPB_INSTANCE_ID); + * message.GetBits().large_param_id = COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED; + * message.GetBits().init_block = true; + * message.GetBits().final_block = true; + * message.GetBits().data_off_size = IPC_OUTPUT_MAILBOX; + * LlpReadingExtended* output_mailbox = NULL; + * send_ipc(message, input_mailbox, (uint8_t**)&output_mailbox); + */ + IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED = 5, + /* Use LARGE_CONFIG_SET to setup attenuation on output pins. Data is just + * uint32_t. Config is only allowed when output pin is set up for 32bit and + * source is connected to Gateway + */ + IPC4_COPIER_MODULE_CFG_ATTENUATION = 6, + /* Use LARGE_CONFIG_SET to setup new channel map, which allows to map channels + * from gateway buffer to copier with any order. + * Same mapping will be applied for all copier sinks. + */ + IPC4_COPIER_MODULE_CFG_PARAM_CHANNEL_MAP = 7 +}; + +struct ipc4_copier_config_timestamp_init_data { + /* Contains low-level configuration for timestamp init. + * Passed-through directly into ifc _LOCAL_TS_Control Register of + * corresponding HW i/f from DSP Timestamping Registers. + */ + uint32_t tsctrl_reg; +} __attribute__((packed, aligned(4))); + +struct ipc4_copier_config_set_sink_format { + uint32_t sink_id; + /* Input format used by the source. Must be the same as present + * if already initialized. + */ + struct ipc4_audio_format source_fmt; + /* Output format used by the sink */ + struct ipc4_audio_format sink_fmt; +} __attribute__((packed, aligned(4))); + +struct ipc4_copier_config_channel_map { + /* Each half-byte of the channel map is an index of the DMA stream channel that + * should be copied to the position determined by this half-byte index. + */ + uint32_t channel_map; +} __attribute__((packed, aligned(4))); + +#define IPC4_COPIER_DATA_SEGMENT_DISABLE (0 << 0) +#define IPC4_COPIER_DATA_SEGMENT_ENABLE (1 << 0) +#define IPC4_COPIER_DATA_SEGMENT_RESTART (1 << 1) + +struct ipc4_data_segment_enabled { + /* Gateway node id */ + uint32_t node_id; + /* Indicates whether notification should be enabled (!=0) or disabled (=0). + * Carries additional information. If bit 1 is set DS will be restarted + * immediately. + * Use only as logic or of COPIER_DATA_SEGMENT_*. + * To disable: + * COPIER_DATA_SEGMENT_DISABLE + * To enable, but finish previous: + * COPIER_DATA_SEGMENT_ENABLE + * To enable, and apply right away: + * COPIER_DATA_SEGMENT_ENABLE | COPIER_DATA_SEGMENT_RESTART + */ + uint32_t enabled; + /* Data segment size (in bytes) */ + uint32_t data_seg_size; +} __attribute__((packed, aligned(4))); + +struct copier_data { + enum ipc4_gateway_type gtw_type; + uint32_t endpoint_num; + + /* buffer to mux/demux data from/to multiple endpoints for ALH multi-gateway case */ + struct comp_buffer *multi_endpoint_buffer; + + bool bsource_buffer; + + int direction; + /* sample data >> attenuation in range of [1 - 31] */ + uint32_t attenuation; + + /* pipeline register offset in memory windows 0 */ + uint32_t pipeline_reg_offset; + uint64_t host_position; + + struct ipc4_audio_format out_fmt[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; + pcm_converter_func converter[IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT]; + uint64_t input_total_data_processed; + 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; +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + struct mic_privacy_data *mic_priv; +#endif + /* Has to be at the end due to variable size array */ + struct ipc4_copier_module_cfg config; +}; + +int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, + struct comp_buffer *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, + uint32_t chmap); + +struct comp_ipc_config; +int create_multi_endpoint_buffer(struct comp_dev *dev, + struct copier_data *cd, + const struct ipc4_copier_module_cfg *copier_cfg); + +enum sof_ipc_stream_direction + get_gateway_direction(enum ipc4_connector_node_id_type node_id_type); + +void copier_update_params(struct copier_data *cd, struct comp_dev *dev, + struct sof_ipc_stream_params *params); +#endif diff --git a/src/audio/copier/copier.toml b/src/audio/copier/copier.toml new file mode 100644 index 000000000000..acb2a5f8876f --- /dev/null +++ b/src/audio/copier/copier.toml @@ -0,0 +1,131 @@ + [[module.entry]] + name = "COPIER" + uuid = UUIDREG_STR_COPIER + affinity_mask = "0x1" + instance_count = "32" + domain_types = "0" + load_type = "0" + module_type = "3" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 280, 4918000, 768, 768, 0, 4918, 0, + 1, 0, 0, 0, 280, 6526000, 768, 768, 0, 6526, 0, + 2, 0, 0, 0, 280, 6388000, 384, 384, 0, 6388, 0, + 3, 0, 0, 0, 280, 4682000, 512, 512, 0, 4682, 0, + 4, 0, 0, 0, 280, 5738000, 512, 512, 0, 5738, 0, + 5, 0, 0, 0, 280, 6250000, 256, 256, 0, 6250, 0, + 6, 0, 0, 0, 280, 6460000, 768, 768, 0, 6460, 0, + 7, 0, 0, 0, 280, 7116000, 768, 768, 0, 7116, 0, + 8, 0, 0, 0, 280, 6008000, 384, 384, 0, 6008, 0, + 9, 0, 0, 0, 280, 6258000, 512, 512, 0, 6258, 0, + 10, 0, 0, 0, 280, 7188000, 1024, 1024, 0, 7188, 0, + 11, 0, 0, 0, 280, 7272000, 1536, 1536, 0, 7272, 0, + 12, 0, 0, 0, 280, 6290000, 768, 768, 0, 6290, 0, + 13, 0, 0, 0, 280, 6604000, 1024, 1024, 0, 6604, 0, + 14, 0, 0, 0, 280, 6198000, 384, 384, 0, 6198, 0, + 15, 0, 0, 0, 280, 6250000, 384, 384, 0, 6250, 0, + 16, 0, 0, 0, 280, 6258000, 256, 256, 0, 6258, 0, + 17, 0, 0, 0, 280, 4354000, 256, 256, 0, 4354, 0, + 18, 0, 0, 0, 280, 6198000, 256, 256, 0, 6198, 0, + 19, 0, 0, 0, 280, 6250000, 128, 128, 0, 6250, 0, + 20, 0, 0, 0, 280, 6250000, 128, 128, 0, 6250, 0, + 21, 0, 0, 0, 280, 6206000, 128, 128, 0, 6206, 0, + 22, 0, 0, 0, 280, 4170000, 64, 64, 0, 4170, 0, + 23, 0, 0, 0, 280, 4234000, 96, 96, 0, 4234, 0, + 24, 0, 0, 0, 280, 6198000, 96, 96, 0, 6198, 0, + 25, 0, 0, 0, 280, 6250000, 96, 96, 0, 6250, 0, + 26, 0, 0, 0, 280, 6198000, 192, 192, 0, 6198, 0, + 27, 0, 0, 0, 280, 6258000, 192, 192, 0, 6258, 0, + 28, 0, 0, 0, 280, 6392000, 720, 720, 0, 6392, 0, + 29, 0, 0, 0, 280, 6250000, 360, 360, 0, 6250, 0, + 30, 0, 0, 0, 280, 5326000, 360, 360, 0, 5326, 0, + 31, 0, 0, 0, 280, 6258000, 180, 180, 0, 6258, 0, + 32, 0, 0, 0, 280, 4354000, 256, 256, 0, 4354, 0, + 33, 0, 0, 0, 280, 4898000, 256, 256, 0, 4898, 0, + 34, 0, 0, 0, 280, 6246000, 128, 128, 0, 6246, 0, + 35, 0, 0, 0, 280, 6250000, 192, 192, 0, 6250, 0, + 36, 0, 0, 0, 280, 6250000, 48, 48, 0, 6250, 0, + 37, 0, 0, 0, 280, 4170000, 64, 64, 0, 4170, 0, + 38, 0, 0, 0, 280, 6198000, 64, 64, 0, 6198, 0, + 39, 0, 0, 0, 280, 6246000, 32, 32, 0, 6246, 0, + 40, 0, 0, 0, 280, 5272000, 192, 384, 0, 5272, 0, + 41, 0, 0, 0, 280, 5350000, 384, 192, 0, 5350, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 280, 6057000, 768, 768, 0, 6057, 0, + 1, 0, 0, 0, 280, 8062000, 768, 768, 0, 8062, 0, + 2, 0, 0, 0, 280, 6250000, 384, 384, 0, 6250, 0, + 3, 0, 0, 0, 280, 6290000, 512, 512, 0, 6290, 0, + 4, 0, 0, 0, 280, 7254000, 512, 512, 0, 7254, 0, + 5, 0, 0, 0, 280, 5607000, 256, 256, 0, 5607, 0, + 6, 0, 0, 0, 280, 6514000, 768, 768, 0, 6514, 0, + 7, 0, 0, 0, 280, 7974000, 768, 768, 0, 7974, 0, + 8, 0, 0, 0, 280, 6242000, 384, 384, 0, 6242, 0, + 9, 0, 0, 0, 280, 6294000, 512, 512, 0, 6294, 0, + 10, 0, 0, 0, 280, 8704000, 1024, 1024, 0, 8704, 0, + 11, 0, 0, 0, 280, 6165000, 1536, 1536, 0, 6165, 0, + 12, 0, 0, 0, 280, 5775000, 768, 768, 0, 5775, 0, + 13, 0, 0, 0, 280, 6610000, 1024, 1024, 0, 6610, 0, + 14, 0, 0, 0, 280, 6457000, 384, 384, 0, 6457, 0, + 15, 0, 0, 0, 280, 7442000, 384, 384, 0, 7442, 0, + 16, 0, 0, 0, 280, 6618000, 256, 256, 0, 6618, 0, + 17, 0, 0, 0, 280, 9104000, 128, 128, 0, 9104, 0, + 18, 0, 0, 0, 280, 6098000, 128, 128, 0, 6098, 0, + 19, 0, 0, 0, 280, 10360000, 128, 128, 0, 10360, 0, + 20, 0, 0, 0, 280, 6046000, 64, 64, 0, 6046, 0, + 21, 0, 0, 0, 280, 6026000, 96, 96, 0, 6026, 0, + 22, 0, 0, 0, 280, 10928000, 96, 96, 0, 10928, 0, + 23, 0, 0, 0, 280, 6688000, 192, 192, 0, 6688, 0, + 24, 0, 0, 0, 280, 8054000, 720, 720, 0, 8054, 0, + 25, 0, 0, 0, 280, 6978000, 360, 360, 0, 6978, 0, + 26, 0, 0, 0, 280, 6118000, 180, 180, 0, 6118, 0, + 27, 0, 0, 0, 280, 6046000, 48, 48, 0, 6046, 0, + 28, 0, 0, 0, 280, 6058000, 64, 64, 0, 6058, 0, + 29, 0, 0, 0, 280, 6198000, 64, 64, 0, 6198, 0, + 30, 0, 0, 0, 280, 6034000, 32, 32, 0, 6034, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 280, 7915000, 768, 768, 0, 7915, 0, + 1, 0, 0, 0, 280, 9487000, 768, 768, 0, 9487, 0, + 2, 0, 0, 0, 280, 7363000, 384, 384, 0, 7363, 0, + 3, 0, 0, 0, 280, 7731000, 512, 512, 0, 7731, 0, + 4, 0, 0, 0, 280, 8459000, 512, 512, 0, 8459, 0, + 5, 0, 0, 0, 280, 7523000, 256, 256, 0, 7523, 0, + 6, 0, 0, 0, 280, 7927000, 768, 768, 0, 7927, 0, + 7, 0, 0, 0, 280, 9507000, 768, 768, 0, 9507, 0, + 8, 0, 0, 0, 280, 7639000, 384, 384, 0, 7639, 0, + 9, 0, 0, 0, 280, 7787000, 512, 512, 0, 7787, 0, + 10, 0, 0, 0, 280, 10211000, 1024, 1024, 0, 10211, 0, + 11, 0, 0, 0, 280, 8387000, 1536, 1536, 0, 8387, 0, + 12, 0, 0, 0, 280, 7923000, 768, 768, 0, 7923, 0, + 13, 0, 0, 0, 280, 8075000, 1024, 1024, 0, 8075, 0, + 14, 0, 0, 0, 280, 8103000, 384, 384, 0, 8103, 0, + 15, 0, 0, 0, 280, 9431000, 2304, 2304, 0, 9431, 0, + 16, 0, 0, 0, 280, 7523000, 256, 256, 0, 7523, 0, + 17, 0, 0, 0, 280, 7479000, 256, 256, 0, 7479, 0, + 18, 0, 0, 0, 280, 7791000, 256, 256, 0, 7791, 0, + 19, 0, 0, 0, 280, 9987000, 3072, 3072, 0, 9987, 0, + 20, 0, 0, 0, 280, 7451000, 128, 128, 0, 7451, 0, + 21, 0, 0, 0, 280, 11495000, 4608, 4608, 0, 11495, 0, + 22, 0, 0, 0, 280, 7627000, 64, 64, 0, 7627, 0, + 23, 0, 0, 0, 280, 7407000, 96, 96, 0, 7407, 0, + 24, 0, 0, 0, 280, 12879000, 6144, 6144, 0, 12879, 0, + 25, 0, 0, 0, 280, 7431000, 192, 192, 0, 7431, 0, + 26, 0, 0, 0, 280, 8580000, 720, 720, 0, 8580, 0, + 27, 0, 0, 0, 280, 7935000, 360, 360, 0, 7935, 0, + 28, 0, 0, 0, 280, 7487000, 180, 180, 0, 7487, 0, + 29, 0, 0, 0, 280, 7623000, 48, 48, 0, 7623, 0, + 30, 0, 0, 0, 280, 7647000, 64, 64, 0, 7647, 0, + 31, 0, 0, 0, 280, 7103000, 32, 32, 0, 7103, 0, +] +#endif + + index = __COUNTER__ diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c new file mode 100644 index 000000000000..dfd2590c7108 --- /dev/null +++ b/src/audio/copier/copier_dai.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +#include <sof/lib/memory.h> +#include <sof/trace/trace.h> +#include <sof/audio/component_ext.h> +#include <ipc/dai.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "copier.h" +#include "dai_copier.h" +#include "copier_gain.h" + +LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL); + +static uint32_t bitmask_to_nibble_channel_map(uint8_t bitmask) +{ + int i; + int channel_count = 0; + uint32_t nibble_map = 0; + + for (i = 0; i < 8; i++) + if (bitmask & BIT(i)) { + nibble_map |= i << (channel_count * 4); + channel_count++; + } + + /* absent channel is represented as 0xf nibble */ + nibble_map |= 0xFFFFFFFF << (channel_count * 4); + + return nibble_map; +} + +static int copier_set_alh_multi_gtw_channel_map(struct comp_dev *dev, + const struct ipc4_copier_module_cfg *copier_cfg, + int index) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + const struct sof_alh_configuration_blob *alh_blob; + uint8_t chan_bitmask; + int channels; + + if (!copier_cfg->gtw_cfg.config_length) { + comp_err(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(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; +} + +static int copier_alh_assign_dai_index(struct comp_dev *dev, + void *gtw_cfg_data, + union ipc4_connector_node_id node_id, + struct ipc_config_dai *dai, + int *dai_index, + int *dai_count) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + const struct sof_alh_configuration_blob *alh_blob = gtw_cfg_data; + uint8_t *dma_config; + size_t alh_cfg_size, dma_config_length; + int i, dai_num, ret; + + if (!cd->config.gtw_cfg.config_length) { + comp_err(mod->dev, "No gateway config found in blob!"); + return -EINVAL; + } + + switch (dai->type) { + case SOF_DAI_INTEL_HDA: + /* We use DAI_INTEL_HDA for ACE 2.0 platforms */ + alh_cfg_size = get_alh_config_size(alh_blob); + dma_config = (uint8_t *)gtw_cfg_data + alh_cfg_size; + dma_config_length = (cd->config.gtw_cfg.config_length << 2) - alh_cfg_size; + + /* Here we check node_id if we need to use FW aggregation, + * in other words do we need to create multiple dai or not + */ + if (!is_multi_gateway(node_id)) { + /* Find DMA config in blob and retrieve stream_id */ + ret = ipc4_find_dma_config_multiple(dai, dma_config, dma_config_length, + alh_blob->alh_cfg.mapping[0].alh_id, 0); + if (ret != 0) { + comp_err(mod->dev, "No sndw dma_config found in blob!"); + return -EINVAL; + } + dai_index[0] = dai->host_dma_config[0]->stream_id; + return 0; + } + + dai_num = alh_blob->alh_cfg.count; + if (dai_num > IPC4_ALH_MAX_NUMBER_OF_GTW || dai_num < 0) { + comp_err(mod->dev, "Invalid dai_count: %d", dai_num); + return -EINVAL; + } + + for (i = 0; i < dai_num; i++) { + ret = ipc4_find_dma_config_multiple(dai, dma_config, + dma_config_length, + alh_blob->alh_cfg.mapping[i].alh_id, i); + if (ret != 0) { + comp_err(mod->dev, "No sndw dma_config found in blob!"); + return -EINVAL; + } + + /* To process data on SoundWire interface HD-A DMA is used so it seems + * logical to me to use stream tag as a dai_index instead of PDI. + */ + dai_index[i] = dai->host_dma_config[i]->stream_id; + } + + *dai_count = dai_num; + break; + case SOF_DAI_INTEL_ALH: + /* Use DAI_INTEL_ALH for ACE 1.0 and older */ + if (!is_multi_gateway(node_id)) { + dai_index[0] = IPC4_ALH_DAI_INDEX(node_id.f.v_index); + return 0; + } + + dai_num = alh_blob->alh_cfg.count; + if (dai_num > IPC4_ALH_MAX_NUMBER_OF_GTW || dai_num < 0) { + comp_err(mod->dev, "Invalid dai_count: %d", dai_num); + return -EINVAL; + } + + for (i = 0; i < dai_num; i++) + dai_index[i] = IPC4_ALH_DAI_INDEX(alh_blob->alh_cfg.mapping[i].alh_id); + + *dai_count = dai_num; + break; + default: + comp_err(mod->dev, "Invalid dai type selected: %d", dai->type); + return -EINVAL; + } + + return 0; +} + +__cold static int copier_dai_init(struct comp_dev *dev, + struct comp_ipc_config *config, + const struct ipc4_copier_module_cfg *copier, + struct pipeline *pipeline, + struct ipc_config_dai *dai, + enum ipc4_gateway_type type, + int index, int dai_count) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + uint32_t chmap; + struct dai_data *dd; + int ret; + + assert_can_be_cold(); + + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + enum sof_ipc_frame out_frame_fmt, out_valid_fmt; + + 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 = dev; + cd->bsource_buffer = true; + chmap = copier->base.audio_fmt.ch_map; + } 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 = dev; + chmap = copier->out_fmt.ch_map; + } + + /* save the channel map and count for ALH multi-gateway */ + if ((type == ipc4_gtw_alh || type == ipc4_gtw_link) && + is_multi_gateway(copier->gtw_cfg.node_id)) { + ret = copier_set_alh_multi_gtw_channel_map(dev, copier, index); + if (ret < 0) + return ret; + } + + dd = mod_alloc_ext(mod, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*dd), 0); + if (!dd) + return -ENOMEM; + memset(dd, 0, sizeof(*dd)); + + ret = dai_common_new(dd, dev, dai); + if (ret < 0) + goto free_dd; + + dd->chmap = chmap; + + pipeline->sched_id = config->id; + + cd->dd[index] = dd; + ret = comp_dai_config(cd->dd[index], dev, dai, copier); + if (ret < 0) + goto e_zephyr_free; + + /* Allocate gain data if selected for this dai type and set basic params */ + if (dai->apply_gain) { + struct copier_gain_params *gain_data = + mod_alloc_ext(mod, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*gain_data), 0); + if (!gain_data) { + ret = -ENOMEM; + goto e_zephyr_free; + } + memset(gain_data, 0, sizeof(*gain_data)); + cd->dd[index]->gain_data = gain_data; + + ret = copier_gain_set_params(dev, cd->dd[index]->gain_data, + GAIN_DEFAULT_FADE_PERIOD, + cd->dd[index]->dai->type); + if (ret < 0) { + comp_err(dev, "Failed to set gain params!"); + goto gain_free; + } + } + + cd->endpoint_num++; + + return 0; +gain_free: + mod_free(mod, dd->gain_data); +e_zephyr_free: + dai_common_free(dd); +free_dd: + mod_free(mod, dd); + return ret; +} + +/* if copier is linked to non-host gateway, it will manage link dma, + * ssp, dmic or alh. Sof dai component can support this case so copier + * reuses dai component to support non-host gateway. + */ +__cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, + const struct ipc4_copier_module_cfg *copier, + struct pipeline *pipeline) +{ + struct processing_module *mod = comp_mod(dev); + struct comp_ipc_config *config = &dev->ipc_config; + int dai_index[IPC4_ALH_MAX_NUMBER_OF_GTW]; + union ipc4_connector_node_id node_id; + struct ipc_config_dai dai; + int dai_count; + int i, ret; + uint8_t *gtw_cfg_data = (uint8_t *)cd->config.gtw_cfg.config_data; + size_t gtw_cfg_size = cd->config.gtw_cfg.config_length * 4; + + assert_can_be_cold(); + + config->type = SOF_COMP_DAI; + + memset(&dai, 0, sizeof(dai)); + dai_count = 1; + node_id = copier->gtw_cfg.node_id; + dai_index[dai_count - 1] = node_id.f.v_index; + dai.direction = get_gateway_direction(node_id.f.dma_type); + dai.is_config_blob = true; + dai.sampling_frequency = copier->out_fmt.sampling_frequency; + dai.feature_mask = copier->copier_feature_mask; + dai.gtw_fmt = (dai.direction == SOF_IPC_STREAM_PLAYBACK) ? + &cd->config.out_fmt : &cd->config.base.audio_fmt; + + switch (node_id.f.dma_type) { + case ipc4_hda_link_output_class: + case ipc4_hda_link_input_class: + dai.type = SOF_DAI_INTEL_HDA; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_link; + break; + case ipc4_i2s_link_output_class: + case ipc4_i2s_link_input_class: + dai.type = SOF_DAI_INTEL_SSP; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_ssp; + ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_size); + if (ret != 0) { + comp_err(dev, "No ssp dma_config found in blob!"); + return -EINVAL; + } + break; + case ipc4_alh_link_output_class: + case ipc4_alh_link_input_class: +#if ACE_VERSION > ACE_VERSION_1_5 + dai.type = SOF_DAI_INTEL_HDA; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_link; +#else + dai.type = SOF_DAI_INTEL_ALH; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_alh; +#endif /* ACE_VERSION > ACE_VERSION_1_5 */ + ret = copier_alh_assign_dai_index(dev, gtw_cfg_data, node_id, &dai, dai_index, + &dai_count); + if (ret) + return ret; + break; + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: + dai.type = SOF_DAI_INTEL_UAOL; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_alh; + ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_size); + if (ret != IPC4_SUCCESS) { + comp_err(dev, "No uaol dma_config found in blob!"); + return -EINVAL; + } + break; + case ipc4_dmic_link_input_class: + dai.type = SOF_DAI_INTEL_DMIC; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_dmic; + ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_size); + if (ret != 0) { + comp_err(dev, "No dmic dma_config found in blob!"); + return -EINVAL; + } +#if CONFIG_COPIER_GAIN + dai.apply_gain = true; +#endif + break; + default: + return -EINVAL; + } + + for (i = 0; i < dai_count; i++) { + dai.dai_index = dai_index[i]; + ret = copier_dai_init(dev, config, copier, pipeline, &dai, cd->gtw_type, i, + dai_count); + if (ret) { + comp_err(dev, "failed to create dai"); + return ret; + } + } + + cd->converter[IPC4_COPIER_GATEWAY_PIN] = + get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, cd->gtw_type, + IPC4_DIRECTION(dai.direction), DUMMY_CHMAP); + if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { + comp_err(dev, "failed to get converter type %d, dir %d", + cd->gtw_type, dai.direction); + return -EINVAL; + } + + /* create multi_endpoint_buffer for ALH multi-gateway case */ + if (dai_count > 1) { + ret = create_multi_endpoint_buffer(dev, cd, copier); + if (ret < 0) + return ret; + } + + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + pipeline->sink_comp = dev; + } else { + pipeline->source_comp = dev; + + /* set max sink count for capture */ + mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; + } + + return 0; +} + +__cold void copier_dai_free(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + for (int i = 0; i < cd->endpoint_num; i++) { + dai_common_free(cd->dd[i]); + mod_free(mod, cd->dd[i]->gain_data); + mod_free(mod, cd->dd[i]); + } + /* only dai have multi endpoint case */ + if (cd->multi_endpoint_buffer) + buffer_free(cd->multi_endpoint_buffer); +} + +int copier_dai_prepare(struct comp_dev *dev, struct copier_data *cd) +{ + int ret; + + for (int i = 0; i < cd->endpoint_num; i++) { + ret = dai_common_config_prepare(cd->dd[i], dev); + if (ret < 0) + return ret; + + ret = dai_common_prepare(cd->dd[i], dev); + if (ret < 0) + return ret; + } + + return 0; +} + +static int copy_single_channel_c16(const struct audio_stream *src, + unsigned int src_channel, + struct audio_stream *dst, + unsigned int dst_channel, unsigned int frame_count) +{ + 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()). + * So let's track samples instead. Since we only copy one channel, src_stream_sample_count + * 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 * audio_stream_get_channels(src); + + while (src_stream_sample_count) { + int src_samples_without_wrap; + int16_t *r_end_ptr, *r_ptr_before_loop; + + r_ptr = audio_stream_wrap(src, r_ptr); + w_ptr = audio_stream_wrap(dst, w_ptr); + + 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 *)audio_stream_get_end_addr(src); + + r_ptr_before_loop = r_ptr; + + do { + *w_ptr = *r_ptr; + 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 int copy_single_channel_c32(const struct audio_stream *src, + unsigned int src_channel, + struct audio_stream *dst, + unsigned int dst_channel, unsigned int frame_count) +{ + 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()). + * So let's track samples instead. Since we only copy one channel, src_stream_sample_count + * 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 * audio_stream_get_channels(src); + + while (src_stream_sample_count) { + int src_samples_without_wrap; + int32_t *r_end_ptr, *r_ptr_before_loop; + + r_ptr = audio_stream_wrap(src, r_ptr); + w_ptr = audio_stream_wrap(dst, w_ptr); + + 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 *)audio_stream_get_end_addr(src); + + r_ptr_before_loop = r_ptr; + + do { + *w_ptr = *r_ptr; + 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; +} + +void copier_dai_adjust_params(const struct copier_data *cd, + struct ipc4_audio_format *in_fmt, + struct ipc4_audio_format *out_fmt) +{ + struct comp_buffer *dma_buf; + int dma_buf_channels; + int dma_buf_container_bits, dma_buf_valid_bits; + + /* Call this func only for DAI gateway with already setup DMA buffer */ + assert(cd->dd[0] && cd->dd[0]->dma_buffer); + dma_buf = cd->dd[0]->dma_buffer; + + /* Unfortunately, configuring the gateway DMA buffer format is somewhat confusing. + * The number of channels can come from hardware parameters (extracted from a blob?) + * and also appears in the copier's input/output format. In case the value returned + * by the hardware looks valid, it should take precedence over the value from the + * copier's input/output format. + * + * The frame format comes from the topology as dev->ipc_config.frame_fmt and also + * comes as the copier's input/output format. The logic is confusing: the format + * from the topology takes priority, except when the copier's format container and + * valid sample size are different. Perhaps this is to support the 16-bit valid + * in the 32-bit container format used by SSP, as such a format cannot be specified + * in the topology? + */ + dma_buf_channels = audio_stream_get_channels(&dma_buf->stream); + dma_buf_container_bits = audio_stream_sample_bytes(&dma_buf->stream) * 8; + dma_buf_valid_bits = get_sample_bitdepth(audio_stream_get_frm_fmt(&dma_buf->stream)); + + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + out_fmt->channels_count = dma_buf_channels; + + if (!(dma_buf_container_bits == out_fmt->depth && + out_fmt->depth != out_fmt->valid_bit_depth)) { + out_fmt->depth = dma_buf_container_bits; + out_fmt->valid_bit_depth = dma_buf_valid_bits; + } + } else { + in_fmt->channels_count = dma_buf_channels; + + if (!(dma_buf_container_bits == in_fmt->depth && + in_fmt->depth != in_fmt->valid_bit_depth)) { + in_fmt->depth = dma_buf_container_bits; + in_fmt->valid_bit_depth = dma_buf_valid_bits; + } + } +} + +int copier_dai_params(struct copier_data *cd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dai_index) +{ + struct sof_ipc_stream_params demuxed_params = *params; + int container_size; + int j, ret; + + if (cd->endpoint_num == 1) { + struct ipc4_audio_format in_fmt = cd->config.base.audio_fmt; + struct ipc4_audio_format out_fmt = cd->config.out_fmt; + enum ipc4_direction_type dir; + + ret = dai_common_params(cd->dd[0], dev, params); + if (ret < 0) + return ret; + + copier_dai_adjust_params(cd, &in_fmt, &out_fmt); + + dir = (cd->direction == SOF_IPC_STREAM_PLAYBACK) ? + ipc4_playback : ipc4_capture; + + cd->dd[0]->process = + get_converter_func(&in_fmt, &out_fmt, cd->gtw_type, dir, cd->dd[0]->chmap); + + return ret; + } + + /* 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[dai_index]; + + ret = dai_common_params(cd->dd[dai_index], dev, &demuxed_params); + if (ret < 0) + return ret; + + for (j = 0; j < SOF_IPC_MAX_CHANNELS; j++) + audio_buffer_set_chmap(&cd->dd[dai_index]->dma_buffer->audio_buffer, + j, (cd->chan_map[dai_index] >> j * 4) & 0xf); + + /* set channel copy func */ + container_size = audio_stream_sample_bytes(&cd->multi_endpoint_buffer->stream); + + switch (container_size) { + case 2: + cd->dd[dai_index]->channel_copy = copy_single_channel_c16; + break; + case 4: + cd->dd[dai_index]->channel_copy = copy_single_channel_c32; + break; + default: + comp_err(dev, "Unexpected container size: %d", container_size); + return -EINVAL; + } + + return ret; +} + +void copier_dai_reset(struct copier_data *cd, struct comp_dev *dev) +{ + for (int i = 0; i < cd->endpoint_num; i++) + dai_common_reset(cd->dd[i], dev); +} + +int copier_dai_trigger(struct copier_data *cd, struct comp_dev *dev, int cmd) +{ + int ret; + + for (int i = 0; i < cd->endpoint_num; i++) { + ret = dai_common_trigger(cd->dd[i], dev, cmd); + if (ret < 0) + return ret; + } + return 0; +} diff --git a/src/audio/copier/copier_gain.c b/src/audio/copier/copier_gain.c new file mode 100644 index 000000000000..fc9f6664add8 --- /dev/null +++ b/src/audio/copier/copier_gain.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. +// +// Author: Ievgen Ganakov <ievgen.ganakov@intel.com> + +#include <sof/lib/memory.h> +#include <sof/trace/trace.h> +#include <ipc4/base-config.h> +#include <sof/audio/component_ext.h> +#include <module/module/base.h> +#include <sof/tlv.h> +#include <ipc4/dmic.h> +#include "copier.h" +#include "copier_gain.h" + +LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL); + +__cold int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain_params, + uint32_t fade_period, enum sof_ipc_dai_type dai_type) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct ipc4_base_module_cfg *ipc4_cfg = &cd->config.base; + uint32_t sampling_freq = ipc4_cfg->audio_fmt.sampling_frequency; + uint32_t frames = sampling_freq / dev->pipeline->period; + int ret; + + assert_can_be_cold(); + + /* Set basic gain parameters */ + copier_gain_set_basic_params(dev, gain_params, ipc4_cfg); + + switch (dai_type) { + case SOF_DAI_INTEL_DMIC: + { + struct dmic_config_data *dmic_cfg = + (void *)cd->config.gtw_cfg.config_data; + + union dmic_global_cfg *dmic_glb_cfg = &dmic_cfg->dmic_blob.global_cfg; + + /* Get fade period from DMIC blob */ + fade_period = dmic_glb_cfg->ext_global_cfg.fade_in_period; + /* Convert and assign silence and fade length values */ + gain_params->silence_sg_length = + frames * dmic_glb_cfg->ext_global_cfg.silence_period; + gain_params->fade_sg_length = frames * fade_period; + } + break; + default: + comp_info(dev, "Apply default fade period for dai type %d", dai_type); + break; + } + + /* Set fade parameters */ + ret = copier_gain_set_fade_params(dev, gain_params, ipc4_cfg, fade_period, frames); + if (ret) + comp_err(dev, "Failed to set fade params"); + + return ret; +} + +int copier_gain_input(struct comp_dev *dev, struct comp_buffer *buff, + struct copier_gain_params *gain_params, + enum copier_gain_envelope_dir dir, uint32_t stream_bytes) +{ + enum sof_ipc_frame frame_fmt = audio_stream_get_frm_fmt(&buff->stream); + uint32_t frames = stream_bytes / audio_stream_frame_bytes(&buff->stream); + enum copier_gain_state state; + + if (!gain_params) + return -EINVAL; + + state = copier_gain_eval_state(gain_params); + + comp_dbg(dev, "copier selected gain state %d", state); + + switch (frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + return copier_gain_input16(buff, state, dir, gain_params, frames); + case SOF_IPC_FRAME_S32_LE: + return copier_gain_input32(buff, state, dir, gain_params, frames); + default: + comp_err(dev, "unsupported frame format %d for copier gain", frame_fmt); + return -EINVAL; + } +} + +enum copier_gain_state copier_gain_eval_state(struct copier_gain_params *gain_params) +{ + enum copier_gain_state state = STATIC_GAIN; + + if (gain_params->silence_sg_count < gain_params->silence_sg_length) + state = MUTE; + else if ((gain_params->fade_in_sg_count < gain_params->fade_sg_length) && + (gain_params->fade_sg_length != 0)) + state = TRANS_GAIN; + + return state; +} + +int copier_gain_dma_control(union ipc4_connector_node_id node, const char *config_data, + size_t config_size, enum sof_ipc_dai_type dai_type) +{ + struct sof_tlv *tlv = (struct sof_tlv *)config_data; + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + struct comp_dev *dev; + struct list_item *clist; + int ret; + + list_for_item(clist, &ipc->comp_list) { + struct gain_dma_control_data *gain_data = NULL; + void *tlv_val = NULL; + + icd = container_of(clist, struct ipc_comp_dev, list); + + if (!icd || icd->type != COMP_TYPE_COMPONENT) + continue; + + dev = icd->cd; + + if (!dev || dev->ipc_config.type != SOF_COMP_DAI) + continue; + + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + + switch (dai_type) { + case SOF_DAI_INTEL_DMIC: + if (cd->dd[0]->dai->index != node.f.v_index) + continue; + + if (!config_size) { + comp_err(dev, "Config length for DMIC couldn't be zero"); + return -EINVAL; + } + + /* Gain coefficients for DMIC */ + tlv_val = tlv_value_ptr_get(tlv, DMIC_SET_GAIN_COEFFICIENTS); + if (!tlv_val) { + comp_err(dev, "No gain coefficients in DMA_CONTROL ipc"); + return -EINVAL; + } + gain_data = tlv_val; + break; + default: + comp_warn(dev, "Gain DMA control: no dai type=%d found", dai_type); + break; + } + + struct ipc4_copier_module_cfg *copier_cfg = cd->dd[0]->dai_spec_config; + const int channels = copier_cfg->base.audio_fmt.channels_count; + + ret = copier_set_gain(dev, cd->dd[0]->gain_data, gain_data, channels); + if (ret) + comp_err(dev, "Gain DMA control: failed to set gain"); + return ret; + } + + return -ENODEV; +} + +int copier_set_gain(struct comp_dev *dev, struct copier_gain_params *gain_params, + struct gain_dma_control_data *gain_data, int channels) +{ + uint16_t static_gain[MAX_GAIN_COEFFS_CNT]; + int ret; + + if (!gain_data) { + comp_err(dev, "Gain data is NULL"); + return -EINVAL; + } + + /* Set gain coefficients */ + comp_info(dev, "Update gain coefficients from DMA_CONTROL ipc"); + + size_t gain_coef_size = channels * sizeof(uint16_t); + + ret = memcpy_s(static_gain, gain_coef_size, gain_data->gain_coeffs, + gain_coef_size); + if (ret) { + comp_err(dev, "memcpy_s failed with error %d", ret); + return ret; + } + + for (int i = channels; i < MAX_GAIN_COEFFS_CNT; i++) + static_gain[i] = static_gain[i % channels]; + + ret = memcpy_s(gain_params->gain_coeffs, sizeof(static_gain), + static_gain, sizeof(static_gain)); + if (ret) { + comp_err(dev, "memcpy_s failed with error %d", ret); + return ret; + } + + gain_params->unity_gain = copier_is_unity_gain(gain_params); + + return 0; +} diff --git a/src/audio/copier/copier_gain.h b/src/audio/copier/copier_gain.h new file mode 100644 index 000000000000..ec55ff999206 --- /dev/null +++ b/src/audio/copier/copier_gain.h @@ -0,0 +1,247 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + * + * Author: Ievgen Ganakov <ievgen.ganakov@intel.com> + */ + +#ifndef __SOF_COPIER_GAIN_H__ +#define __SOF_COPIER_GAIN_H__ + +#include <sof/audio/buffer.h> +#include <ipc4/base_fw.h> +#include <ipc4/gateway.h> +#include <ipc/dai.h> +#if SOF_USE_HIFI(3, COPIER) || SOF_USE_HIFI(4, COPIER) || SOF_USE_HIFI(5, COPIER) +#include <xtensa/tie/xt_hifi3.h> +#endif +/** + * @file copier_gain.h + * @brief Header file containing definitions and functions related to audio gain + * processing for a copier module. + * + * This file provides functions, constants and structure definitions for applying gain to + * input audio buffers, both in 16-bit and 32-bit container formats. The gain can be + * applied in different directions (addition or subtraction) and has three modes: + * - static gain + * - transition gain (fade-in/fade-out) + * - mute + */ + +/* Maximum number of gain coefficients */ +#define MAX_GAIN_COEFFS_CNT 4 + +/* Common const values for applying gain feature */ +#define Q10_TO_Q31_SHIFT 6 +#define Q10_TO_Q15_SHIFT 5 +#define GAIN_Q10_INT_SHIFT 10 + +/* 16x2 store operation requires shift to middle part of 32 bit register */ +#define I64_TO_I16_SHIFT 48 +#define I64_TO_I32_SHIFT 32 +#define MIDDLE_PART_SHIFT 8 + +/* Unit gain in q10 format applied by default */ +#define UNITY_GAIN_4X_Q10 0x0400040004000400 +#define UNITY_GAIN_GENERIC 0x0400 + +/* Default fade transition in ms in high quality mode (Freq > 16000Hz) */ +#define GAIN_DEFAULT_HQ_TRANS_MS 500 +/* Default fade transition in ms in low quality mode */ +#define GAIN_DEFAULT_LQ_TRANS_MS 100 + +#define GAIN_ZERO_TRANS_MS 0xFFFF +#define GAIN_DEFAULT_FADE_PERIOD 0 + +struct dai_data; + +/** + * @brief Enumeration representing the state of the copier gain processing. + */ +enum copier_gain_state { + MUTE = 0, /**< Mute state, zero gain value applied */ + TRANS_GAIN, /**< Transition gain state, used for fade-in/fade-out */ + STATIC_GAIN, /**< Static gain state, gain value is not changing over time */ +}; + +/** + * @brief Enumeration representing the change direction of the gain envelope in + * fade context. + */ +enum copier_gain_envelope_dir { + GAIN_ADD = 0, /**< gain envelope add direction */ + GAIN_SUBTRACT, /**< gain envelope subtract direction */ +}; + +/** + * @brief Structure representing the parameters for copier gain processing. + */ +struct copier_gain_params { +#if SOF_USE_HIFI(3, COPIER) || SOF_USE_HIFI(4, COPIER) || SOF_USE_HIFI(5, COPIER) + /**< Input gain coefficients in Q10 format */ + ae_int16x4 gain_coeffs[SOF_DIV_ROUND_UP(MAX_GAIN_COEFFS_CNT, 4)]; + /**< Step for fade-in lower precision */ + ae_f16x4 step_f16; + /**< Initial gain depending on the number of channels */ + ae_f16x4 init_gain; +#else /* Generic version of gain processing */ + /**< Input gain coefficients */ + int16_t gain_coeffs[MAX_GAIN_COEFFS_CNT]; + /**< Step for fade-in */ + int16_t step_f16; + /**< Initial gain */ + int16_t init_gain[MAX_GAIN_COEFFS_CNT]; +#endif + bool unity_gain; /**< Indicates unity gain coefficients, no processing is required */ + uint32_t silence_sg_count; /**< Accumulates sample group spent on silence */ + uint32_t fade_in_sg_count; /**< Accumulates sample group spent on fade-in */ + uint32_t silence_sg_length; /**< Total count of sample group spent on silence */ + uint32_t fade_sg_length; /**< Total count of sample group spent on fade-in */ + uint64_t gain_env; /**< Gain envelope for fade-in calculated in high precision */ + uint64_t step_i64; /**< Step for fade-in envelope in high precision */ + uint16_t channels_count; /**< Number of channels */ +}; + +/** Gain Coefficients IO Control + * + * This parameter is sent by the driver to add/modify a static gain. + * Coefficients are encoded in Q10 format. + */ +struct gain_dma_control_data { + uint16_t gain_coeffs[MAX_GAIN_COEFFS_CNT]; +} __packed __aligned(4); + +/** + * @brief Sets gain parameters. + * + * This function sets the gain parameters for the copier component specified by + * the given device and DAI data. + * + * @param dev The pointer to the component device structure. + * @param gain_params The pointer to gain params structure. + * @param fade_period The fade period in milliseconds. + * @param dai_type DAI type + * @return 0 on success, negative error code on failure. + */ +int copier_gain_set_params(struct comp_dev *dev, struct copier_gain_params *gain_params, + uint32_t fade_period, enum sof_ipc_dai_type dai_type); + +/** + * @brief Sets the basic gain parameters. + * + * This function sets the basic gain parameters for the copier component specified + * by the given device and DAI data. + * + * @param dev The pointer to the component device structure. + * @param gain_params The pointer to gain params structure. + * @param ipc4_cfg The pointer to the IPC4 base module config. + */ +void copier_gain_set_basic_params(struct comp_dev *dev, struct copier_gain_params *gain_params, + struct ipc4_base_module_cfg *ipc4_cfg); + +/** + * @brief Sets the gain fade parameters. + * + * This function sets the fade gain parameters for the copier component specified + * by the given device and DAI data. + * + * @param dev The pointer to the component device structure. + * @param gain_params The pointer to gain params structure. + * @param ipc4_cfg The pointer to the IPC4 base module config. + * @param fade_period The fade period in milliseconds. + * @param frames The number of frames to fade. + * @return 0 on success, negative error code on failure. + */ +int copier_gain_set_fade_params(struct comp_dev *dev, struct copier_gain_params *gain_params, + struct ipc4_base_module_cfg *ipc4_cfg, + uint32_t fade_period, uint32_t frames); + +/** + * @brief Applies gain to a 16-bit container size. + * + * This function applies gain to the input audio buffer. There are three gain modes + * supported: static gain, mute, and gain transition (fade-in or fade-out). + * + * @param buff Pointer to the input audio buffer. + * @param state The state of the gain processing. + * @param dir direction of the gain envelope change. + * @param frames The number of frames to be processed. + */ +int copier_gain_input16(struct comp_buffer *buff, enum copier_gain_state state, + enum copier_gain_envelope_dir dir, + struct copier_gain_params *gain_params, uint32_t frames); + +/** + * @brief Applies gain to a 32-bit container size. + * + * This function applies gain to the input audio buffer. There are three gain modes + * supported: static gain, mute, and gain transition (fade-in or fade-out). + * + * @param buff Pointer to the input audio buffer. + * @param state The state of the gain processing. + * @param dir Direction of the gain envelope change. + * @param gain_params The pointer to the copier_gain_params structure. + * @param frames The number of frames to be processed. + */ +int copier_gain_input32(struct comp_buffer *buff, enum copier_gain_state state, + enum copier_gain_envelope_dir dir, + struct copier_gain_params *gain_params, uint32_t frames); + +/** + * @brief Applies gain to the input audio buffer, selects the appropriate gain method. + * + * @param dev The pointer to the comp_dev structure representing the audio component device. + * @param buff The pointer to the comp_buffer structure representing the input buffer. + * @param gain_params The pointer to the copier_gain_params structure. + * @param dir Direction of the gain envelope change. + * @param stream_bytes The number of bytes in the input buffer. + * @return 0 on success, negative error code on failure. + */ +int copier_gain_input(struct comp_dev *dev, struct comp_buffer *buff, + struct copier_gain_params *gain_params, + enum copier_gain_envelope_dir dir, uint32_t stream_bytes); + +/** + * Evaluates appropriate gain mode based on the current gain parameters + * + * @param gain_params The pointer to the copier_gain_params structure. + * @return The state of the copier gain (enum copier_gain_state). + */ +enum copier_gain_state copier_gain_eval_state(struct copier_gain_params *gain_params); + +/** + * Sets/modify gain for a copier module in runtime. + * + * @param dev The copier device structure. + * @param gain_params The pointer to the copier_gain_params structure. + * @param gain_data The gain control data structure. + * @param channels Number of audio channels. + * @return 0 on success, otherwise a negative error code. + */ +int copier_set_gain(struct comp_dev *dev, struct copier_gain_params *gain_params, + struct gain_dma_control_data *gain_data, int channels); + +/** + * Checks for unity gain mode. + * + * @param gain_params The copier gain parameters structure. + * @return true if the gain is set to unity gain, false otherwise. + */ +bool copier_is_unity_gain(struct copier_gain_params *gain_params); + +/** + * Controls the gain for a copier device using DMA Control IPC message. + * + * This function retrieves gain data from the DMA Control IPC message and updates + * corresponding dai device gain params structure. + * + * @param node Gateway node id. + * @param config_data The gain configuration data. + * @param config_size The size of the gain configuration data. + * @param dai_type The type of the DAI device. + * @return 0 on success, otherwise a negative error code. + */ +int copier_gain_dma_control(union ipc4_connector_node_id node, const char *config_data, + size_t config_size, enum sof_ipc_dai_type dai_type); + +#endif /* __SOF_COPIER_GAIN_H__ */ diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c new file mode 100644 index 000000000000..89805f25af0c --- /dev/null +++ b/src/audio/copier/copier_generic.c @@ -0,0 +1,582 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> + +#include <ipc4/base-config.h> +#include <sof/audio/component_ext.h> +#include <sof/lib/memory.h> +#include <module/module/base.h> +#include <sof/common.h> +#include <ipc/dai.h> +#include "copier.h" + +LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL); + +#if SOF_USE_HIFI(NONE, COPIER) + +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component.h> +#include <stddef.h> +#include <errno.h> +#include <stdint.h> +#include "copier_gain.h" + +int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, + struct comp_buffer *sink, int frame) +{ + int i; + int n; + int nmax; + int remaining_samples = frame * audio_stream_get_channels(&sink->stream); + uint32_t bytes = frame * audio_stream_frame_bytes(&sink->stream); + uint32_t *dst = audio_stream_rewind_wptr_by_bytes(&sink->stream, bytes); + + /* only support attenuation in format of 32bit */ + 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; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + while (remaining_samples) { + nmax = audio_stream_samples_without_wrap_s32(&sink->stream, dst); + n = MIN(remaining_samples, nmax); + for (i = 0; i < n; i++) { + *dst >>= cd->attenuation; + dst++; + } + remaining_samples -= n; + dst = audio_stream_wrap(&sink->stream, dst); + } + + return 0; + default: + comp_err(dev, "unsupported format %d for attenuation", + audio_stream_get_frm_fmt(&sink->stream)); + return -EINVAL; + } +} + +__cold void copier_gain_set_basic_params(struct comp_dev *dev, + struct copier_gain_params *gain_params, + struct ipc4_base_module_cfg *ipc4_cfg) +{ + assert_can_be_cold(); + + gain_params->channels_count = ipc4_cfg->audio_fmt.channels_count; + + for (int i = 0; i < MAX_GAIN_COEFFS_CNT; i++) + gain_params->gain_coeffs[i] = UNITY_GAIN_GENERIC; +} + +__cold int copier_gain_set_fade_params(struct comp_dev *dev, struct copier_gain_params *gain_params, + struct ipc4_base_module_cfg *ipc4_cfg, + uint32_t fade_period, uint32_t frames) +{ + uint16_t step_i64_to_i16; + + assert_can_be_cold(); + + if (fade_period == GAIN_DEFAULT_FADE_PERIOD) { + /* Set fade transition delay to default value*/ + if (ipc4_cfg->audio_fmt.sampling_frequency > IPC4_FS_16000HZ) + gain_params->fade_sg_length = frames * GAIN_DEFAULT_HQ_TRANS_MS; + else + gain_params->fade_sg_length = frames * GAIN_DEFAULT_LQ_TRANS_MS; + } else if (fade_period == GAIN_ZERO_TRANS_MS) { + /* Special case for GAIN_ZERO_TRANS_MS to support zero fade-in transition time */ + gain_params->fade_sg_length = 0; + return 0; + } else { + gain_params->fade_sg_length = frames * fade_period; + } + + /* High precision step for fade-in calculation, keeps accurate precision */ + gain_params->step_i64 = INT64_MAX / gain_params->fade_sg_length; + step_i64_to_i16 = gain_params->step_i64 >> I64_TO_I16_SHIFT; + + /* lower precision step for HIFI SIMD fade-in calculation, converted to Q16 format */ + gain_params->step_f16 = (MAX_GAIN_COEFFS_CNT / gain_params->channels_count) * + step_i64_to_i16; + + /* Initialization gain for HIFI SIMD addition, depends on channel configuration */ + for (int i = 0; i < MAX_GAIN_COEFFS_CNT; i++) { + gain_params->init_gain[i] = (i / gain_params->channels_count) * + step_i64_to_i16; + } + return 0; +} + +int copier_gain_input16(struct comp_buffer *buff, enum copier_gain_state state, + enum copier_gain_envelope_dir dir, + struct copier_gain_params *gain_params, uint32_t frames) +{ + int16_t *dst = audio_stream_get_rptr(&buff->stream); + const int nch = audio_stream_get_channels(&buff->stream); + int samples = frames * nch; + int16_t gain_env[MAX_GAIN_COEFFS_CNT] = {0}; + int16_t gain_env_sq; + int16_t gain_env_i16; + int16_t *dst_tmp; + int16_t gain; + int nmax, i, j; + + switch (state) { + case STATIC_GAIN: + /* static gain */ + if (gain_params->unity_gain) + return 0; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s16(&buff->stream, dst); + nmax = MIN(samples, nmax); + + for (j = 0; j < nch; j++) { + dst_tmp = dst + j; + gain = gain_params->gain_coeffs[j]; + for (i = 0; i < nmax; i += nch) + dst_tmp[i] = q_multsr_sat_16x16(dst_tmp[i], gain, + GAIN_Q10_INT_SHIFT); + } + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + break; + case MUTE: + while (samples) { + nmax = audio_stream_samples_without_wrap_s16(&buff->stream, dst); + nmax = MIN(samples, nmax); + size_t zeroed_bytes = nmax * sizeof(int16_t); + /* Apply mute */ + memset_s(dst, zeroed_bytes, 0, zeroed_bytes); + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + break; + case TRANS_GAIN: + while (samples) { + nmax = audio_stream_samples_without_wrap_s16(&buff->stream, dst); + nmax = MIN(samples, nmax); + + /* Precalculate gain envelope */ + gain_env_i16 = gain_params->gain_env >> I64_TO_I16_SHIFT; + for (i = 0; i < MAX_GAIN_COEFFS_CNT; i++) + gain_env[i] = gain_env_i16 + gain_params->init_gain[i]; + + /* Apply fade */ + for (j = 0; j < nch; j++) { + dst_tmp = dst + j; + /* Quadratic fade part in Q15 format*/ + gain_env_sq = q_multsr_16x16(gain_env[j], gain_env[j], 15); + + /* Calculate gain value. Gain coeffs in Q10 format but + * gain_env_sq in Q15. So shifting result by 15 bits. + */ + gain = q_multsr_16x16(gain_params->gain_coeffs[j], + gain_env_sq, 15); + + for (i = 0; i < nmax; i += nch) + dst_tmp[i] = q_multsr_sat_16x16(dst_tmp[i], gain, + GAIN_Q10_INT_SHIFT); + } + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + break; + } + + if (state == MUTE) { + gain_params->silence_sg_count += frames; + } else if (state == TRANS_GAIN) { + gain_params->fade_in_sg_count += frames; + if (dir == GAIN_ADD) + gain_params->gain_env += gain_params->step_i64 * frames; + else + gain_params->gain_env -= gain_params->step_i64 * frames; + } + + return 0; +} + +int copier_gain_input32(struct comp_buffer *buff, enum copier_gain_state state, + enum copier_gain_envelope_dir dir, + struct copier_gain_params *gain_params, uint32_t frames) +{ + int32_t *dst = audio_stream_get_rptr(&buff->stream); + const int nch = audio_stream_get_channels(&buff->stream); + int samples = frames * nch; + int16_t gain_env[MAX_GAIN_COEFFS_CNT] = {0}; + int32_t *dst_tmp; + int16_t gain, gain_env_i16, gain_env_sq; + int nmax, i, j; + + switch (state) { + case STATIC_GAIN: + /* static gain */ + if (gain_params->unity_gain) + return 0; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s32(&buff->stream, dst); + nmax = MIN(samples, nmax); + + for (j = 0; j < nch; j++) { + dst_tmp = dst + j; + /* Gain is in Q21.10 format */ + gain = gain_params->gain_coeffs[j]; + for (i = 0; i < nmax; i += nch) + dst_tmp[i] = q_multsr_sat_32x32(dst_tmp[i], gain, + GAIN_Q10_INT_SHIFT); + } + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + break; + case MUTE: + while (samples) { + nmax = audio_stream_samples_without_wrap_s32(&buff->stream, dst); + nmax = MIN(samples, nmax); + size_t zeroed_bytes = nmax * sizeof(int32_t); + + /* Apply mute*/ + memset_s(dst, zeroed_bytes, 0, zeroed_bytes); + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + break; + case TRANS_GAIN: + while (samples) { + nmax = audio_stream_samples_without_wrap_s32(&buff->stream, dst); + nmax = MIN(samples, nmax); + + /* Precalculate gain envelope */ + gain_env_i16 = gain_params->gain_env >> I64_TO_I16_SHIFT; + for (i = 0; i < MAX_GAIN_COEFFS_CNT; i++) + gain_env[i] = gain_env_i16 + gain_params->init_gain[i]; + + /* Apply fade */ + for (j = 0; j < nch; j++) { + dst_tmp = dst + j; + /* Quadratic fade part in Q15 format*/ + gain_env_sq = q_multsr_16x16(gain_env[j], gain_env[j], 15); + + /* Calculate gain value. Gain coeffs in Q10 format but + * gain_env_sq in Q15. So shifting result by 15 bits. + */ + gain = q_multsr_16x16(gain_params->gain_coeffs[j], + gain_env_sq, 15); + + for (i = 0; i < nmax; i += nch) + dst_tmp[i] = q_multsr_sat_32x32(dst_tmp[i], gain, + GAIN_Q10_INT_SHIFT); + } + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + break; + } + + if (state == MUTE) { + gain_params->silence_sg_count += frames; + } else if (state == TRANS_GAIN) { + gain_params->fade_in_sg_count += frames; + if (dir == GAIN_ADD) + gain_params->gain_env += gain_params->step_i64 * frames; + else + gain_params->gain_env -= gain_params->step_i64 * frames; + } + + return 0; +} + +bool copier_is_unity_gain(struct copier_gain_params *gain_params) +{ + /* Set unity gain flag */ + for (int i = 0; i < MAX_GAIN_COEFFS_CNT; i++) { + if (gain_params->gain_coeffs[i] != UNITY_GAIN_GENERIC) + return false; + } + return true; +} + +#endif + +void copier_update_params(struct copier_data *cd, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_buffer *sink; + + memset(params, 0, sizeof(*params)); + params->direction = cd->direction; + params->channels = cd->config.base.audio_fmt.channels_count; + params->rate = cd->config.base.audio_fmt.sampling_frequency; + params->sample_container_bytes = cd->config.base.audio_fmt.depth / 8; + params->sample_valid_bytes = cd->config.base.audio_fmt.valid_bit_depth / 8; + + params->stream_tag = cd->config.gtw_cfg.node_id.f.v_index + 1; + params->frame_fmt = dev->ipc_config.frame_fmt; + params->buffer_fmt = cd->config.base.audio_fmt.interleaving_style; + params->buffer.size = cd->config.base.ibs; + + /* disable ipc3 stream position */ + params->no_stream_position = 1; + + /* update each sink format */ + comp_dev_for_each_consumer(dev, sink) { + int j; + j = IPC4_SRC_QUEUE_ID(buf_get_id(sink)); + + ipc4_update_buffer_format(sink, &cd->out_fmt[j]); + } + + /* 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; + } +} + +__cold int create_multi_endpoint_buffer(struct comp_dev *dev, + struct copier_data *cd, + const struct ipc4_copier_module_cfg *copier_cfg) +{ + struct comp_ipc_config *config = &dev->ipc_config; + 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; + uint32_t buf_size; + uint32_t chan_map; + int i; + + assert_can_be_cold(); + + audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth, + copier_cfg->base.audio_fmt.valid_bit_depth, + &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, + copier_cfg->out_fmt.s_type); + + /* playback case: + * + * --> copier0 -----> buf1 ----> .... bufn --------> copier1 + * | /|\ |conversion | + * \|/ |conversion \|/ \|/ + * host-> endpoint buffer0 endpoint buffer1 -> dai --> + * + * capture case: + * + * copier1 <------ bufn <---- .... buf1 <------- copier0 <-- + * | |conversion /|\ | + * \|/ \|/ |conversion \|/ + * <-- host <- endpoint buffer1 endpoint buffer0 <- dai + * + * According to above graph, the format of endpoint buffer + * depends on stream direction and component type. + */ + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + if (config->type == SOF_COMP_HOST) { + config->frame_fmt = in_frame_fmt; + valid_fmt = in_valid_fmt; + buf_size = copier_cfg->base.ibs * 2; + } else { + config->frame_fmt = out_frame_fmt; + valid_fmt = out_valid_fmt; + buf_size = copier_cfg->base.obs * 2; + } + + chan_map = copier_cfg->out_fmt.ch_map; + } else { + if (config->type == SOF_COMP_HOST) { + config->frame_fmt = out_frame_fmt; + valid_fmt = out_valid_fmt; + buf_size = copier_cfg->base.obs * 2; + } else { + config->frame_fmt = in_frame_fmt; + valid_fmt = in_valid_fmt; + buf_size = copier_cfg->base.ibs * 2; + } + + chan_map = copier_cfg->base.audio_fmt.ch_map; + } + + dev->ipc_config.frame_fmt = config->frame_fmt; + + memset(&ipc_buf, 0, sizeof(ipc_buf)); + ipc_buf.size = buf_size; + ipc_buf.comp.pipeline_id = config->pipeline_id; + ipc_buf.comp.core = config->core; + buffer = buffer_new(NULL, &ipc_buf, BUFFER_USAGE_NOT_SHARED); + if (!buffer) + return -ENOMEM; + + audio_stream_set_channels(&buffer->stream, copier_cfg->base.audio_fmt.channels_count); + audio_stream_set_rate(&buffer->stream, copier_cfg->base.audio_fmt.sampling_frequency); + audio_stream_set_frm_fmt(&buffer->stream, config->frame_fmt); + audio_stream_set_valid_fmt(&buffer->stream, valid_fmt); + audio_stream_set_buffer_fmt(&buffer->stream, + copier_cfg->base.audio_fmt.interleaving_style); + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + audio_buffer_set_chmap(&buffer->audio_buffer, i, (chan_map >> i * 4) & 0xf); + + audio_buffer_set_hw_params_configured(&buffer->audio_buffer); + + cd->multi_endpoint_buffer = buffer; + + return 0; +} + +__cold enum sof_ipc_stream_direction + get_gateway_direction(enum ipc4_connector_node_id_type node_id_type) +{ + assert_can_be_cold(); + + /* WARNING: simple "% 2" formula that was used before does not work for all + * interfaces: at least it does not work for IPC gateway. But it may also + * does not work for other not yet supported interfaces. And so additional + * cases might be required here in future. + */ + switch (node_id_type) { + /* from DSP to host */ + case ipc4_ipc_output_class: + return SOF_IPC_STREAM_CAPTURE; + /* from host to DSP */ + case ipc4_ipc_input_class: + return SOF_IPC_STREAM_PLAYBACK; + default: + return node_id_type % 2; + } +} + +/* In sof normal format conversion path, sample size should be equal + * to container size except format of S24_LE. In ipc4 case, sample + * size can be different with container size. This function is used to + * check conversion mode. + */ +static bool use_no_container_convert_function(enum sof_ipc_frame in, + enum sof_ipc_frame valid_in_bits, + enum sof_ipc_frame out, + enum sof_ipc_frame valid_out_bits) +{ + /* valid sample size is equal to container size, go normal path */ + if (in == valid_in_bits && out == valid_out_bits) { + if (in == SOF_IPC_FRAME_S24_3LE || out == SOF_IPC_FRAME_S24_3LE) + return false; + + return true; + } + + return false; +} + +static bool is_remapping_chmap(uint32_t chmap, size_t out_channel_count) +{ + size_t i; + + assert(out_channel_count <= 8); + + for (i = 0; i < out_channel_count; i++) { + if ((chmap & 0xf) != i) + return true; + chmap >>= 4; + } + + return false; +} + +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, + uint32_t chmap) +{ + 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); + audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, &out, &out_valid, + out_fmt->s_type); + + /* use MSB sample type to select conversion function if the data is enter or exit dsp. + * In playback case, host input and dai output and in capture case, host output and + * dai input. + */ + if (in_fmt->s_type == IPC4_TYPE_MSB_INTEGER && in_valid == SOF_IPC_FRAME_S24_4LE) { + switch (type) { + case ipc4_gtw_host: + if (dir == ipc4_playback) + in_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + case ipc4_gtw_alh: + case ipc4_gtw_link: + case ipc4_gtw_ssp: + case ipc4_gtw_dmic: + if (dir == ipc4_capture) + in_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + default: + break; + } + } + + if (out_fmt->s_type == IPC4_TYPE_MSB_INTEGER && out_valid == SOF_IPC_FRAME_S24_4LE) { + switch (type) { + case ipc4_gtw_host: + if (dir == ipc4_capture) + out_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + case ipc4_gtw_alh: + case ipc4_gtw_link: + case ipc4_gtw_ssp: + case ipc4_gtw_dmic: + if (dir == ipc4_playback) + out_valid = SOF_IPC_FRAME_S24_4LE_MSB; + break; + default: + break; + } + } + + if (in_fmt->channels_count != out_fmt->channels_count || + is_remapping_chmap(chmap, out_fmt->channels_count)) { + if (in_valid == SOF_IPC_FRAME_S16_LE && in == SOF_IPC_FRAME_S32_LE) + in = SOF_IPC_FRAME_S16_4LE; + if (out_valid == SOF_IPC_FRAME_S16_LE && out == SOF_IPC_FRAME_S32_LE) + out = SOF_IPC_FRAME_S16_4LE; + + if (in_valid == SOF_IPC_FRAME_S24_4LE && in == SOF_IPC_FRAME_S32_LE) + in = in_valid; + if (out_valid == SOF_IPC_FRAME_S24_4LE && out == SOF_IPC_FRAME_S32_LE) + out = out_valid; + + return pcm_get_remap_function(in, out); + } + + /* check container & sample size */ + if (use_no_container_convert_function(in, in_valid, out, out_valid)) + return pcm_get_conversion_function(in, out); + else + return pcm_get_conversion_vc_function(in, in_valid, out, out_valid, type, dir); +} diff --git a/src/audio/copier/copier_hifi.c b/src/audio/copier/copier_hifi.c new file mode 100644 index 000000000000..14c91b632f5b --- /dev/null +++ b/src/audio/copier/copier_hifi.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> +#include "copier.h" +#include <sof/common.h> + +#if SOF_USE_HIFI(3, COPIER) || SOF_USE_HIFI(4, COPIER) || SOF_USE_HIFI(5, COPIER) + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component.h> +#include <sof/lib/memory.h> +#include <module/module/base.h> +#include <stddef.h> +#include <errno.h> +#include <stdint.h> +#include <xtensa/tie/xt_hifi3.h> +#include "copier_gain.h" + +LOG_MODULE_REGISTER(copier_hifi, CONFIG_SOF_LOG_LEVEL); + +int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, + struct comp_buffer *sink, int frame) +{ + int i; + int n; + int nmax; + int m; + ae_int32x2 sample; + ae_valign uu = AE_ZALIGN64(); + ae_valign su = AE_ZALIGN64(); + int remaining_samples = frame * audio_stream_get_channels(&sink->stream); + uint32_t bytes = frame * audio_stream_frame_bytes(&sink->stream); + uint32_t *dst = audio_stream_rewind_wptr_by_bytes(&sink->stream, bytes); + ae_int32x2 *in = (ae_int32x2 *)dst; + ae_int32x2 *out = (ae_int32x2 *)dst; + + /* only support attenuation in format of 32bit */ + 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; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + while (remaining_samples) { + nmax = audio_stream_samples_without_wrap_s32(&sink->stream, dst); + in = (ae_int32x2 *)dst; + out = (ae_int32x2 *)dst; + uu = AE_LA64_PP(in); + n = MIN(remaining_samples, nmax); + m = n >> 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(sample, uu, in); + sample = AE_SRAA32(sample, cd->attenuation); + AE_SA32X2_IP(sample, su, out); + } + AE_SA64POS_FP(su, out); + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + sample = AE_SRAA32(sample, cd->attenuation); + AE_S32_L_IP(sample, (ae_int32 *)out, sizeof(ae_int32)); + } + remaining_samples -= n; + dst = audio_stream_wrap(&sink->stream, dst + n); + } + + return 0; + default: + comp_err(dev, "unsupported format %d for attenuation", + audio_stream_get_frm_fmt(&sink->stream)); + return -EINVAL; + } +} + +__cold void copier_gain_set_basic_params(struct comp_dev *dev, + struct copier_gain_params *gain_params, + struct ipc4_base_module_cfg *ipc4_cfg) +{ + assert_can_be_cold(); + + /* Set default gain coefficients */ + for (int i = 0; i < ARRAY_SIZE(gain_params->gain_coeffs); ++i) + gain_params->gain_coeffs[i] = AE_MOVF16X4_FROMINT64(UNITY_GAIN_4X_Q10); + + gain_params->step_f16 = AE_ZERO16(); + gain_params->init_gain = AE_ZERO16(); + + /* Set channels count */ + gain_params->channels_count = ipc4_cfg->audio_fmt.channels_count; +} + +__cold int copier_gain_set_fade_params(struct comp_dev *dev, struct copier_gain_params *gain_params, + struct ipc4_base_module_cfg *ipc4_cfg, + uint32_t fade_period, uint32_t frames) +{ + uint16_t init_gain[MAX_GAIN_COEFFS_CNT]; + uint16_t step_i64_to_i16; + ae_f16 step_f16; + + assert_can_be_cold(); + + /* For backward compatibility add a case with default fade transition. + * Backward compatibility is referring to clock_on_delay in DMIC blob. + */ + if (fade_period == GAIN_DEFAULT_FADE_PERIOD) { + /* Set fade transition delay to default value*/ + if (ipc4_cfg->audio_fmt.sampling_frequency > IPC4_FS_16000HZ) + gain_params->fade_sg_length = frames * GAIN_DEFAULT_HQ_TRANS_MS; + else + gain_params->fade_sg_length = frames * GAIN_DEFAULT_LQ_TRANS_MS; + } else if (fade_period == GAIN_ZERO_TRANS_MS) { + /* Special case for GAIN_ZERO_TRANS_MS to support zero fade in transition time */ + gain_params->fade_sg_length = 0; + return 0; + } else { + gain_params->fade_sg_length = frames * fade_period; + } + + /* High precision step for fade-in calculation, keeps accurate precision */ + gain_params->step_i64 = INT64_MAX / gain_params->fade_sg_length; + step_i64_to_i16 = gain_params->step_i64 >> I64_TO_I16_SHIFT; + + step_f16 = step_i64_to_i16 * (MAX_GAIN_COEFFS_CNT / gain_params->channels_count); + + /* Lower precision step for HIFI SIMD fade-in calculation */ + gain_params->step_f16 = step_f16; + + /* Initialization gain for HIFI SIMD addition, depends on channel configuration */ + for (int i = 0; i < MAX_GAIN_COEFFS_CNT; i++) + init_gain[i] = (i / gain_params->channels_count) * step_i64_to_i16; + + int ret = memcpy_s(&gain_params->init_gain, sizeof(gain_params->init_gain), init_gain, + sizeof(init_gain)); + if (ret) + comp_err(dev, "memcpy_s failed with error code %d", ret); + + return ret; +} + +static inline ae_int16x4 copier_load_slots_and_gain16(ae_int16x4 **addr, + ae_valign *align_in, + const ae_int16x4 gains) +{ + ae_int16x4 d16_1 = AE_ZERO16(); + ae_int32x2 d32_1 = AE_ZERO32(); + ae_int32x2 d32_2 = AE_ZERO32(); + + AE_LA16X4_IC(d16_1, align_in[0], addr[0]); + AE_MUL16X4(d32_1, d32_2, d16_1, gains); + + /* Saturate if exists by moving to Q31 */ + d32_1 = AE_SLAA32S(d32_1, Q10_TO_Q31_SHIFT); + d32_2 = AE_SLAA32S(d32_2, Q10_TO_Q31_SHIFT); + + /* Returns desired samples selection */ + return AE_TRUNC16X4F32(d32_1, d32_2); +} + +static inline void copier_load_slots_and_gain32(ae_int32x2 **addr, ae_valign *align_in, + const ae_int16x4 gains, ae_int32x2 *out_d32_h, + ae_int32x2 *out_d32_l) +{ + ae_int32x2 d32tmp_h = AE_ZERO32(); + ae_int32x2 d32tmp_l = AE_ZERO32(); + + AE_LA32X2_IC(d32tmp_h, align_in[0], addr[0]); + AE_LA32X2_IC(d32tmp_l, align_in[0], addr[0]); + + /* Apply gains */ + d32tmp_h = AE_MULFP32X16X2RAS_H(d32tmp_h, gains); + d32tmp_l = AE_MULFP32X16X2RAS_L(d32tmp_l, gains); + + /* Gain is Q10 but treated in AE_MULFP32X16 as Q15, + * so we need to compensate by shifting with saturation + */ + *out_d32_h = AE_SLAA32S(d32tmp_h, Q10_TO_Q15_SHIFT); + *out_d32_l = AE_SLAA32S(d32tmp_l, Q10_TO_Q15_SHIFT); +} + +int copier_gain_input16(struct comp_buffer *buff, enum copier_gain_state state, + enum copier_gain_envelope_dir dir, + struct copier_gain_params *gain_params, uint32_t frames) +{ + uint16_t *dst = audio_stream_get_rptr(&buff->stream); + const int nch = audio_stream_get_channels(&buff->stream); + int samples = frames * nch; + const ae_int16x4 gain_i16 = gain_params->gain_coeffs[0]; + ae_valign align_in = AE_ZALIGN64(); + ae_valign align_out = AE_ZALIGN64(); + ae_f16x4 gain_env = AE_ZERO16(); + ae_int16x4 *out_ptr; + ae_int16x4 *in_ptr; + ae_int16x4 d_r; + ae_int16x4 d16_1; + int rest, n, nmax; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s16(&buff->stream, dst); + out_ptr = (ae_int16x4 *)(dst); + in_ptr = (ae_int16x4 *)(dst); + nmax = MIN(samples, nmax); + rest = nmax & 0x3; + + AE_LA16X4POS_PC(align_in, in_ptr); + + switch (state) { + case STATIC_GAIN: + for (n = 0; n < (nmax >> 2); n++) { + d16_1 = copier_load_slots_and_gain16(&in_ptr, &align_in, gain_i16); + AE_SA16X4_IC(d16_1, align_out, out_ptr); + } + break; + case MUTE: + d16_1 = AE_ZERO16(); + for (size_t n = 0; n < (nmax >> 2); n++) + AE_SA16X4_IC(d16_1, align_out, out_ptr); + break; + case TRANS_GAIN: + gain_env = (int16_t)(gain_params->gain_env >> I64_TO_I16_SHIFT); + gain_env = AE_ADD16S(gain_env, gain_params->init_gain); + for (n = 0; n < (nmax >> 2); n++) { + /* static gain part */ + if (!gain_params->unity_gain) + d16_1 = copier_load_slots_and_gain16(&in_ptr, &align_in, + gain_i16); + else + AE_LA16X4_IC(d16_1, align_in, in_ptr); + + /* quadratic fade-in part */ + d16_1 = AE_MULFP16X4S(d16_1, gain_env); + d16_1 = AE_MULFP16X4S(d16_1, gain_env); + + AE_SA16X4_IC(d16_1, align_out, out_ptr); + if (dir == GAIN_ADD) + gain_env = AE_ADD16S(gain_env, gain_params->step_f16); + else + gain_env = AE_SUB16S(gain_env, gain_params->step_f16); + } + break; + } + + /* Process rest samples */ + AE_SA64POS_FP(align_out, out_ptr); + if (rest) { + switch (state) { + case STATIC_GAIN: + d_r = copier_load_slots_and_gain16(&in_ptr, &align_in, gain_i16); + break; + case MUTE: + d_r = AE_ZERO16(); + break; + case TRANS_GAIN: + if (!gain_params->unity_gain) + d_r = copier_load_slots_and_gain16(&in_ptr, &align_in, + gain_i16); + else + AE_LA16X4_IC(d_r, align_in, in_ptr); + + d_r = AE_MULFP16X4S(d_r, gain_env); + d_r = AE_MULFP16X4S(d_r, gain_env); + break; + } + + AE_S16_0_IP(AE_MOVAD16_3(d_r), (ae_int16 *)(out_ptr), sizeof(uint16_t)); + if (rest > 1) { + AE_S16_0_IP(AE_MOVAD16_2(d_r), (ae_int16 *)(out_ptr), + sizeof(uint16_t)); + if (rest > 2) + AE_S16_0_IP(AE_MOVAD16_1(d_r), (ae_int16 *)(out_ptr), 0); + } + } + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + + if (state == MUTE) { + gain_params->silence_sg_count += frames; + } else if (state == TRANS_GAIN) { + gain_params->fade_in_sg_count += frames; + if (dir == GAIN_ADD) + gain_params->gain_env += gain_params->step_i64 * frames; + else + gain_params->gain_env -= gain_params->step_i64 * frames; + } + return 0; +} + +int copier_gain_input32(struct comp_buffer *buff, enum copier_gain_state state, + enum copier_gain_envelope_dir dir, + struct copier_gain_params *gain_params, uint32_t frames) +{ + uint32_t *dst = audio_stream_get_rptr(&buff->stream); + const int nch = audio_stream_get_channels(&buff->stream); + int samples = frames * nch; + ae_int16x4 gain_i16 = gain_params->gain_coeffs[0]; + ae_valign align_in = AE_ZALIGN64(); + ae_valign align_out = AE_ZALIGN64(); + ae_int32x2 d32_h = AE_ZERO32(); + ae_int32x2 d32_l = AE_ZERO32(); + ae_int32x2 r_d32_h = AE_ZERO32(); + ae_int32x2 r_d32_l = AE_ZERO32(); + ae_f16x4 gain_env = AE_ZERO16(); + ae_int32x2 *out_ptr; + ae_int32x2 *in_ptr; + int rest, n, nmax; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s32(&buff->stream, dst); + out_ptr = (ae_int32x2 *)(dst); + in_ptr = (ae_int32x2 *)(dst); + nmax = MIN(samples, nmax); + rest = nmax & 0x3; + + /* Align input pointer access */ + AE_LA32X2POS_PC(align_in, in_ptr); + + switch (state) { + case STATIC_GAIN: + for (n = 0; n < (nmax >> 2); n++) { + copier_load_slots_and_gain32(&in_ptr, &align_in, gain_i16, + &d32_h, &d32_l); + AE_SA32X2_IC(d32_h, align_out, out_ptr); + AE_SA32X2_IC(d32_l, align_out, out_ptr); + } + break; + case MUTE: + d32_l = AE_ZERO32(); + for (size_t n = 0; n < (nmax >> 2); n++) { + AE_SA32X2_IC(d32_l, align_out, out_ptr); + AE_SA32X2_IC(d32_l, align_out, out_ptr); + } + break; + case TRANS_GAIN: + gain_env = (int16_t)(gain_params->gain_env >> I64_TO_I16_SHIFT); + gain_env = AE_ADD16S(gain_env, gain_params->init_gain); + for (n = 0; n < (nmax >> 2); n++) { + /* static gain part */ + if (!gain_params->unity_gain) { + copier_load_slots_and_gain32(&in_ptr, &align_in, gain_i16, + &d32_h, &d32_l); + } else { + AE_LA32X2_IC(d32_h, align_in, in_ptr); + AE_LA32X2_IC(d32_l, align_in, in_ptr); + } + /* quadratic fade-in part */ + d32_h = AE_MULFP32X16X2RAS_H(d32_h, gain_env); + d32_h = AE_MULFP32X16X2RAS_H(d32_h, gain_env); + d32_l = AE_MULFP32X16X2RAS_L(d32_l, gain_env); + d32_l = AE_MULFP32X16X2RAS_L(d32_l, gain_env); + AE_SA32X2_IC(d32_h, align_out, out_ptr); + AE_SA32X2_IC(d32_l, align_out, out_ptr); + + if (dir == GAIN_ADD) + gain_env = AE_ADD16S(gain_env, gain_params->step_f16); + else + gain_env = AE_SUB16S(gain_env, gain_params->step_f16); + } + break; + default: + return -EINVAL; + } + + AE_SA64POS_FP(align_out, out_ptr); + if (rest) { + switch (state) { + case STATIC_GAIN: + copier_load_slots_and_gain32(&in_ptr, &align_in, gain_i16, + &r_d32_h, &r_d32_l); + break; + case MUTE: + break; + case TRANS_GAIN: + if (!gain_params->unity_gain) { + copier_load_slots_and_gain32(&in_ptr, &align_in, gain_i16, + &r_d32_h, &r_d32_l); + } else { + AE_LA32X2_IC(r_d32_h, align_in, in_ptr); + AE_LA32X2_IC(r_d32_l, align_in, in_ptr); + } + r_d32_h = AE_MULFP32X16X2RAS_H(r_d32_h, gain_env); + r_d32_h = AE_MULFP32X16X2RAS_H(r_d32_h, gain_env); + r_d32_l = AE_MULFP32X16X2RAS_L(r_d32_l, gain_env); + r_d32_l = AE_MULFP32X16X2RAS_L(r_d32_l, gain_env); + break; + } + + if (rest > 1) { + AE_SA32X2_IC(r_d32_h, align_out, out_ptr); + AE_SA64POS_FP(align_out, out_ptr); + + if (rest > 2) { + ae_int32 tmp = AE_MOVAD32_H(r_d32_l); + + AE_S32_L_XC(tmp, (ae_int32 *)out_ptr, 0); + } + } else { + ae_int32 tmp = AE_MOVAD32_H(r_d32_h); + + AE_S32_L_XC(tmp, (ae_int32 *)out_ptr, 0); + } + } + samples -= nmax; + dst = audio_stream_wrap(&buff->stream, dst + nmax); + } + + if (state == MUTE) { + gain_params->silence_sg_count += frames; + } else if (state == TRANS_GAIN) { + gain_params->fade_in_sg_count += frames; + if (dir == GAIN_ADD) + gain_params->gain_env += gain_params->step_i64 * frames; + else + gain_params->gain_env -= gain_params->step_i64 * frames; + } + + return 0; +} + +bool copier_is_unity_gain(struct copier_gain_params *gain_params) +{ + ae_int16x4 gain_coeffs = AE_MOVF16X4_FROMINT64(UNITY_GAIN_4X_Q10); + xtbool4 unity_gain_check = AE_EQ16(gain_params->gain_coeffs[0], gain_coeffs); + + return XT_ALL4(unity_gain_check) ? true : false; +} + +#endif diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c new file mode 100644 index 000000000000..fe17a49328b9 --- /dev/null +++ b/src/audio/copier/copier_host.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +#include <sof/audio/component_ext.h> +#include <sof/lib/memory.h> +#include <sof/tlv.h> +#include <sof/trace/trace.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "copier.h" +#include "host_copier.h" + +LOG_MODULE_DECLARE(copier, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION + +/* NOTE: The code that modifies and checks the contents of the list can be executed on different + * cores. But since adding and removing modules is done exclusively via IPC, and we never add or + * remove more than one module, these functions do not require synchronization. + */ +struct fpi_sync_group { + uint32_t id; + uint32_t period; + uint32_t ref_count; + struct list_item item; +}; + +static struct list_item group_list_head = LIST_INIT(group_list_head); + +__cold static struct fpi_sync_group *find_group_by_id(uint32_t id) +{ + struct list_item *item; + + assert_can_be_cold(); + + list_for_item(item, &group_list_head) { + struct fpi_sync_group *group = list_item(item, struct fpi_sync_group, item); + + if (group->id == id) + return group; + } + + return NULL; +} + +__cold static int add_to_fpi_sync_group(struct comp_dev *parent_dev, + struct host_data *hd, + struct ipc4_copier_sync_group *sync_group) +{ + struct fpi_sync_group *group = find_group_by_id(sync_group->group_id); + struct processing_module *mod = comp_mod(parent_dev); + + assert_can_be_cold(); + + if (group) { + if (group->period != sync_group->fpi_update_period_usec) { + comp_err(parent_dev, "incorrect period %u for group %u (currently %u)", + group->id, group->period, sync_group->fpi_update_period_usec); + return -EINVAL; + } + + group->ref_count++; + } else { + group = mod_alloc_ext(mod, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*group), 0); + if (!group) { + comp_err(parent_dev, "Failed to alloc memory for new group"); + return -ENOMEM; + } + memset(group, 0, sizeof(*group)); + + group->id = sync_group->group_id; + group->period = sync_group->fpi_update_period_usec; + group->ref_count = 1; + list_item_append(&group->item, &group_list_head); + } + + hd->is_grouped = true; + hd->group_id = group->id; + hd->period_in_cycles = k_us_to_cyc_ceil64(group->period); + comp_dbg(parent_dev, "gtw added to group %u with period %u", group->id, group->period); + return 0; +} + +__cold static void delete_from_fpi_sync_group(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + struct fpi_sync_group *group = find_group_by_id(cd->hd->group_id); + + assert_can_be_cold(); + + if (!group) + return; + + group->ref_count--; + if (group->ref_count == 0) { + list_item_del(&group->item); + mod_free(mod, group); + } +} +#endif + +/* Playback only */ +__cold static int init_pipeline_reg(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct ipc4_pipeline_registers pipe_reg; + uint32_t gateway_id; + + assert_can_be_cold(); + + gateway_id = cd->config.gtw_cfg.node_id.f.v_index; + if (gateway_id >= IPC4_MAX_PIPELINE_REG_SLOTS) { + comp_err(dev, "gateway_id %u out of array bounds.", gateway_id); + return -EINVAL; + } + + /* pipeline position is stored in memory windows 0 at the following offset + * please check struct ipc4_fw_registers definition. The number of + * pipeline reg depends on the host dma count for playback + */ + cd->pipeline_reg_offset = offsetof(struct ipc4_fw_registers, pipeline_regs); + cd->pipeline_reg_offset += gateway_id * sizeof(struct ipc4_pipeline_registers); + + pipe_reg.stream_start_offset = (uint64_t)-1; + pipe_reg.stream_end_offset = (uint64_t)-1; + mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg, sizeof(pipe_reg)); + return 0; +} + +/* if copier is linked to host gateway, it will manage host dma. + * Sof host component can support this case so copier reuses host + * component to support host gateway. + */ +__cold int copier_host_create(struct processing_module *mod, + const struct ipc4_copier_module_cfg *copier_cfg, + struct pipeline *pipeline) +{ + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_ipc_config *config = &dev->ipc_config; + struct ipc_config_host ipc_host; + struct host_data *hd; + int dir = cd->direction; + int ret; + enum sof_ipc_frame in_frame_fmt, out_frame_fmt; + enum sof_ipc_frame in_valid_fmt, out_valid_fmt; + + assert_can_be_cold(); + + config->type = SOF_COMP_HOST; + cd->gtw_type = ipc4_gtw_host; + + ret = audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth, + copier_cfg->base.audio_fmt.valid_bit_depth, + &in_frame_fmt, &in_valid_fmt, + copier_cfg->base.audio_fmt.s_type); + if (ret) { + comp_err(dev, "failed with input format: depth %d, valid %d, type %d", + copier_cfg->base.audio_fmt.depth, + copier_cfg->base.audio_fmt.valid_bit_depth, + copier_cfg->base.audio_fmt.s_type); + return ret; + } + + ret = audio_stream_fmt_conversion(copier_cfg->out_fmt.depth, + copier_cfg->out_fmt.valid_bit_depth, + &out_frame_fmt, &out_valid_fmt, + copier_cfg->out_fmt.s_type); + if (ret) { + comp_err(dev, "failed with output format: depth %d, valid %d, type %d", + copier_cfg->out_fmt.depth, copier_cfg->out_fmt.valid_bit_depth, + copier_cfg->out_fmt.s_type); + return ret; + } + + memset(&ipc_host, 0, sizeof(ipc_host)); + ipc_host.direction = dir; + ipc_host.dma_buffer_size = copier_cfg->gtw_cfg.dma_buffer_size; + ipc_host.feature_mask = copier_cfg->copier_feature_mask; + + hd = mod_zalloc(mod, sizeof(*hd)); + if (!hd) + return -ENOMEM; + + ret = host_common_new(hd, dev, &ipc_host, config->id); + if (ret < 0) { + comp_err(dev, "copier: host new failed with exit"); + goto e_data; + } +#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION + /* Size of a configuration without optional parameters. */ + const uint32_t basic_size = sizeof(*copier_cfg) + + (copier_cfg->gtw_cfg.config_length - 1) * sizeof(uint32_t); + /* Additional data size */ + const uint32_t tlv_buff_size = config->ipc_config_size - basic_size; + const uint32_t min_tlv_size = sizeof(struct ipc4_copier_sync_group) + 2 * sizeof(uint32_t); + + if (tlv_buff_size >= min_tlv_size) { + const uint32_t tlv_addr = (uint32_t)copier_cfg + basic_size; + uint32_t value_size = 0; + void *value_ptr = NULL; + + tlv_value_get((void *)tlv_addr, tlv_buff_size, HDA_SYNC_FPI_UPDATE_GROUP, + &value_ptr, &value_size); + + if (value_ptr) { + struct ipc4_copier_sync_group *sync_group; + + if (value_size != sizeof(struct ipc4_copier_sync_group)) { + ret = -EINVAL; + goto e_conv; + } + + sync_group = (struct ipc4_copier_sync_group *)((void *)value_ptr); + + ret = add_to_fpi_sync_group(dev, hd, sync_group); + if (ret < 0) + goto e_conv; + } + } +#endif + + cd->converter[IPC4_COPIER_GATEWAY_PIN] = + get_converter_func(&copier_cfg->base.audio_fmt, + &copier_cfg->out_fmt, + ipc4_gtw_host, IPC4_DIRECTION(dir), DUMMY_CHMAP); + if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { + comp_err(dev, "failed to get converter for host, dir %d", dir); + ret = -EINVAL; + goto e_conv; + } + + cd->endpoint_num++; + cd->hd = hd; + + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + config->frame_fmt = in_frame_fmt; + pipeline->source_comp = dev; + ret = init_pipeline_reg(dev); + if (ret) + goto e_conv; + + /* set max sink count for playback */ + mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; + } else { + config->frame_fmt = out_frame_fmt; + pipeline->sink_comp = dev; + } + + return 0; + +e_conv: + host_common_free(hd); +e_data: + mod_free(mod, hd); + + return ret; +} + +__cold void copier_host_free(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + +#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION + if (cd->hd->is_grouped) + delete_from_fpi_sync_group(mod); +#endif + host_common_free(cd->hd); + mod_free(mod, cd->hd); +} + +/* This is called by DMA driver every time when DMA completes its current + * transfer between host and DSP. + */ +void copier_host_dma_cb(struct comp_dev *dev, size_t bytes) +{ + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + int ret, frames; + + comp_dbg(dev, "%p", dev); + + /* update position */ + host_common_update(cd->hd, dev, bytes); + + /* callback for one shot copy */ + if (cd->hd->copy_type == COMP_COPY_ONE_SHOT) + host_common_one_shot(cd->hd, bytes); + + /* Apply attenuation since copier copy missed this with host device + * remove. Attenuation has to be applied in HOST Copier only with + * playback scenario. + */ + if (cd->attenuation && dev->direction == SOF_IPC_STREAM_PLAYBACK) { + frames = bytes / audio_stream_frame_bytes(&cd->hd->dma_buffer->stream); + + ret = apply_attenuation(dev, cd, cd->hd->local_buffer, frames); + if (ret < 0) + comp_dbg(dev, "apply attenuation failed! %d", ret); + + buffer_stream_writeback(cd->hd->local_buffer, bytes); + } +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->mic_priv) + mic_privacy_process(dev, cd->mic_priv, cd->hd->local_buffer, bytes); +#endif +} + +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_host_dma_cb(arg, bytes); +} + +int copier_host_params(struct copier_data *cd, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + int ret; + + component_set_nearest_period_frames(dev, params->rate); + ret = host_common_params(cd->hd, dev, params, + copier_notifier_cb); + + cd->hd->process = cd->converter[IPC4_COPIER_GATEWAY_PIN]; + + return ret; +} diff --git a/src/audio/copier/copier_ipcgtw.c b/src/audio/copier/copier_ipcgtw.c new file mode 100644 index 000000000000..ed365c1e50d8 --- /dev/null +++ b/src/audio/copier/copier_ipcgtw.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 Intel Corporation. All rights reserved. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component_ext.h> +#include <sof/trace/trace.h> +#include <sof/lib/memory.h> +#include <sof/ut.h> +#include <rtos/init.h> +#include "copier.h" +#include "ipcgtw_copier.h" + +LOG_MODULE_REGISTER(ipcgtw, CONFIG_SOF_LOG_LEVEL); + +/* List of existing IPC gateways */ +static struct list_item ipcgtw_list_head = LIST_INIT(ipcgtw_list_head); + +static struct comp_dev *find_ipcgtw_by_node_id(union ipc4_connector_node_id node_id) +{ + struct list_item *item; + + list_for_item(item, &ipcgtw_list_head) { + struct ipcgtw_data *data = list_item(item, struct ipcgtw_data, item); + + if (data->node_id.dw == node_id.dw) + return data->dev; + } + + return NULL; +} + +static inline void audio_stream_copy_bytes_from_linear(const void *linear_source, + struct audio_stream *sink, + unsigned int bytes) +{ + const uint8_t *src = (const uint8_t *)linear_source; + uint8_t *snk = audio_stream_wrap(sink, audio_stream_get_wptr(sink)); + size_t bytes_snk, bytes_copied; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + bytes_copied = MIN(bytes, bytes_snk); + memcpy_s(snk, bytes_copied, src, bytes_copied); + bytes -= bytes_copied; + src += bytes_copied; + snk = audio_stream_wrap(sink, snk + bytes_copied); + } +} + +static inline +void audio_stream_copy_bytes_to_linear(const struct audio_stream *source, + void *linear_sink, unsigned int bytes) +{ + 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; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + bytes_copied = MIN(bytes, bytes_src); + memcpy_s(snk, bytes_copied, src, bytes_copied); + bytes -= bytes_copied; + src = audio_stream_wrap(source, src + bytes_copied); + snk += bytes_copied; + } +} + +static inline struct comp_buffer *get_buffer(struct comp_dev *dev) +{ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + if (list_is_empty(&dev->bsink_list)) + return NULL; + return comp_dev_get_first_data_consumer(dev); + } + + assert(dev->direction == SOF_IPC_STREAM_CAPTURE); + + if (list_is_empty(&dev->bsource_list)) + return NULL; + return comp_dev_get_first_data_producer(dev); +} + +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; + struct comp_buffer *buf; + uint32_t data_size; + struct ipc4_ipc_gateway_cmd_data_reply *out; + + 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) + return -ENODEV; + + comp_dbg(dev, "%x %x", + cmd->primary.dat, cmd->extension.dat); + + buf = get_buffer(dev); + + if (!buf) { + /* NOTE: this func is called from IPC processing task and can be potentially + * called before pipeline start even before buffer has been attached. In such + * case do not report error but return 0 bytes available for GET_DATA and + * 0 bytes free for SET_DATA. + */ + comp_warn(dev, "no buffer found"); + } + + out = (struct ipc4_ipc_gateway_cmd_data_reply *)reply_payload; + + switch (cmd->primary.r.cmd) { + case IPC4_IPCGWCMD_GET_DATA: + if (buf) { + data_size = MIN(cmd->extension.r.data_size, SOF_IPC_MSG_MAX_SIZE - 4); + data_size = MIN(data_size, audio_stream_get_avail_bytes(&buf->stream)); + buffer_stream_invalidate(buf, data_size); + audio_stream_copy_bytes_to_linear(&buf->stream, out->payload, data_size); + comp_update_buffer_consume(buf, data_size); + out->u.size_avail = audio_stream_get_avail_bytes(&buf->stream); + *reply_payload_size = data_size + 4; + } else { + out->u.size_avail = 0; + *reply_payload_size = 4; + } + break; + + case IPC4_IPCGWCMD_SET_DATA: + if (buf) { + data_size = MIN(cmd->extension.r.data_size, + audio_stream_get_free_bytes(&buf->stream)); + dcache_invalidate_region((__sparse_force void __sparse_cache *) + MAILBOX_HOSTBOX_BASE, + data_size + + offsetof(struct ipc4_ipc_gateway_cmd_data, + payload)); + audio_stream_copy_bytes_from_linear(in->payload, &buf->stream, + data_size); + buffer_stream_writeback(buf, data_size); + comp_update_buffer_produce(buf, data_size); + out->u.size_consumed = data_size; + *reply_payload_size = 4; + } else { + out->u.size_consumed = 0; + *reply_payload_size = 4; + } + break; + + case IPC4_IPCGWCMD_FLUSH_DATA: + *reply_payload_size = 0; + if (buf) + audio_stream_reset(&buf->stream); + break; + + default: + comp_err(dev, "unexpected cmd: %u", + (unsigned int)cmd->primary.r.cmd); + return -EINVAL; + } + + return 0; +} + +int copier_ipcgtw_params(struct ipcgtw_data *ipcgtw_data, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_buffer *buf; + int err; + + comp_dbg(dev, "ipcgtw_params()"); + + buf = get_buffer(dev); + if (!buf) { + comp_err(dev, "no buffer found"); + return -EINVAL; + } + + /* resize buffer to size specified in IPC gateway config blob */ + err = buffer_set_size(buf, ipcgtw_data->buf_size, 0); + + if (err < 0) { + comp_err(dev, "failed to resize buffer to %u bytes", + ipcgtw_data->buf_size); + return err; + } + + return 0; +} + +void copier_ipcgtw_reset(struct comp_dev *dev) +{ + struct comp_buffer *buf = get_buffer(dev); + + if (buf) { + audio_stream_reset(&buf->stream); + } else { + comp_warn(dev, "no buffer found"); + } +} + +__cold int copier_ipcgtw_create(struct processing_module *mod, + const struct ipc4_copier_module_cfg *copier, + struct pipeline *pipeline) +{ + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_ipc_config *config = &dev->ipc_config; + struct ipcgtw_data *ipcgtw_data; + const struct ipc4_copier_gateway_cfg *gtw_cfg; + const struct ipc4_ipc_gateway_config_blob *blob; + int ret; + + assert_can_be_cold(); + + gtw_cfg = &copier->gtw_cfg; + if (!gtw_cfg->config_length) { + comp_err(dev, "empty ipc4_gateway_config_data"); + return -EINVAL; + } + + cd->ipc_gtw = true; + + /* The IPC gateway is treated as a host gateway */ + config->type = SOF_COMP_HOST; + cd->gtw_type = ipc4_gtw_host; + + ipcgtw_data = mod_zalloc(mod, sizeof(*ipcgtw_data)); + if (!ipcgtw_data) + return -ENOMEM; + + 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; + + /* The buffer connected to the IPC gateway will be resized later in ipcgtw_params() + * to the size specified in the IPC gateway blob. + */ + comp_dbg(dev, "buffer_size: %u", blob->buffer_size); + ipcgtw_data->buf_size = blob->buffer_size; + + cd->converter[IPC4_COPIER_GATEWAY_PIN] = + get_converter_func(&copier->base.audio_fmt, + &copier->out_fmt, + ipc4_gtw_host, IPC4_DIRECTION(cd->direction), DUMMY_CHMAP); + if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { + comp_err(dev, "failed to get converter for IPC gateway, dir %d", + cd->direction); + ret = -EINVAL; + goto e_ipcgtw; + } + + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + cd->bsource_buffer = false; + pipeline->source_comp = dev; + } else { + cd->bsource_buffer = true; + pipeline->sink_comp = dev; + } + + list_item_append(&ipcgtw_data->item, &ipcgtw_list_head); + cd->ipcgtw_data = ipcgtw_data; + cd->endpoint_num++; + + return 0; + +e_ipcgtw: + mod_free(mod, ipcgtw_data); + return ret; +} + +__cold void copier_ipcgtw_free(struct processing_module *mod) +{ + struct copier_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + list_item_del(&cd->ipcgtw_data->item); + mod_free(mod, cd->ipcgtw_data); +} diff --git a/src/audio/copier/dai_copier.h b/src/audio/copier/dai_copier.h new file mode 100644 index 000000000000..481b06b4bc58 --- /dev/null +++ b/src/audio/copier/dai_copier.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian <baofeng.tian@intel.com> + */ + +/** + * \file audio/dai_copier.h + * \brief dai copier shared header file + * \authors Baofeng Tian <baofeng.tian@intel.com> + */ + +#ifndef __SOF_LIB_DAI_COPIER_H__ +#define __SOF_LIB_DAI_COPIER_H__ + +struct ipc_config_dai; +struct comp_dev; +struct dai_data; +int dai_common_new(struct dai_data *dd, struct comp_dev *dev, + const struct ipc_config_dai *dai_cfg); + +void dai_common_free(struct dai_data *dd); + +int dai_common_config_prepare(struct dai_data *dd, struct comp_dev *dev); + +int dai_common_prepare(struct dai_data *dd, struct comp_dev *dev); + +void dai_common_reset(struct dai_data *dd, struct comp_dev *dev); + +int dai_common_trigger(struct dai_data *dd, struct comp_dev *dev, int cmd); + +int dai_common_position(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_posn *posn); + +int dai_common_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params); + +int dai_common_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter); + +int dai_common_ts_config_op(struct dai_data *dd, struct comp_dev *dev); + +int dai_common_ts_start(struct dai_data *dd, struct comp_dev *dev); + +int dai_common_ts_stop(struct dai_data *dd, struct comp_dev *dev); + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +int dai_common_ts_get(struct dai_data *dd, struct comp_dev *dev, struct dai_ts_data *tsd); +#else +int dai_common_ts_get(struct dai_data *dd, struct comp_dev *dev, struct timestamp_data *tsd); +#endif + +int dai_common_get_hw_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir); + +#if CONFIG_LIBRARY +static inline int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev, + struct comp_buffer *multi_endpoint_buffer, + int num_endpoints) +{ + return 0; +} + +static inline int dai_zephyr_unbind(struct dai_data *dd, struct comp_dev *dev, void *data) +{ + return 0; +} +#else +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, struct bind_info *unbind_data); +#endif + + +struct ipc4_copier_module_cfg; +struct copier_data; +int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, + const struct ipc4_copier_module_cfg *copier, + struct pipeline *pipeline); + +void copier_dai_free(struct processing_module *mod); + +int copier_dai_prepare(struct comp_dev *dev, struct copier_data *cd); + +void copier_dai_adjust_params(const struct copier_data *cd, + struct ipc4_audio_format *in_fmt, + struct ipc4_audio_format *out_fmt); + +int copier_dai_params(struct copier_data *cd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dai_index); + +void copier_dai_reset(struct copier_data *cd, struct comp_dev *dev); + +int copier_dai_trigger(struct copier_data *cd, struct comp_dev *dev, int cmd); +#endif /* __SOF_LIB_DAI_COPIER_H__ */ diff --git a/src/audio/copier/host_copier.h b/src/audio/copier/host_copier.h new file mode 100644 index 000000000000..2bc8904e1258 --- /dev/null +++ b/src/audio/copier/host_copier.h @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian <baofeng.tian@intel.com> + */ + +/** + * \file audio/host_copier.h + * \brief host copier shared header file + * \authors Baofeng Tian <baofeng.tian@intel.com> + */ + +#ifndef __SOF_HOST_COPIER_H__ +#define __SOF_HOST_COPIER_H__ + +#include <sof/audio/component_ext.h> +#include <sof/audio/pcm_converter.h> +#include <sof/lib/dma.h> +#include <sof/audio/ipc-config.h> +#include <ipc/stream.h> +#include <sof/lib/notifier.h> +#include "copier.h" + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS +struct io_perf_data_item; +#endif + +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, copy_callback_t cb); + +/** + * \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 */ +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + struct sof_dma *dma; + int chan_index; +#else + struct dma *dma; + struct dma_chan_data *chan; +#endif + struct dma_sg_config config; +#ifdef __ZEPHYR__ + struct dma_config z_config; +#endif + struct comp_dev *cb_dev; + + 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; + uint64_t nobytes_last_logged; /**< uptime, when "no bytes" was last logged */ + unsigned int n_skipped; /**< number of "no bytes" skipped */ + 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; + + size_t partial_size; /**< add up DMA updates for deep buffer */ + + /* 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 */ +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + bool xrun_notification_sent; +#endif + uint32_t dma_buffer_size; /* dma buffer size */ +#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION + bool is_grouped; + uint8_t group_id; + uint64_t next_sync; + uint64_t period_in_cycles; +#endif +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + struct io_perf_data_item *io_perf_host_byte_count; +#endif +}; + +int host_common_new(struct host_data *hd, struct comp_dev *dev, + const struct ipc_config_host *ipc_host, uint32_t config_id); +void host_common_free(struct host_data *hd); +int host_common_prepare(struct host_data *hd); +void host_common_reset(struct host_data *hd, uint16_t state); +int host_common_trigger(struct host_data *hd, struct comp_dev *dev, int cmd); +int host_common_params(struct host_data *hd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, notifier_callback_t cb); +/* copy and process stream data from source to sink buffers */ +static inline int host_common_copy(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) +{ + return hd->copy(hd, dev, cb); +} +void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t bytes); +void host_common_one_shot(struct host_data *hd, uint32_t bytes); +int copier_host_create(struct processing_module *mod, + const struct ipc4_copier_module_cfg *copier_cfg, + struct pipeline *pipeline); +void copier_host_free(struct processing_module *mod); +int copier_host_params(struct copier_data *cd, struct comp_dev *dev, + struct sof_ipc_stream_params *params); +void copier_host_dma_cb(struct comp_dev *dev, size_t bytes); + +#endif /* __SOF_HOST_COPIER_H__ */ diff --git a/src/audio/copier/ipcgtw_copier.h b/src/audio/copier/ipcgtw_copier.h new file mode 100644 index 000000000000..a9ea82914d4e --- /dev/null +++ b/src/audio/copier/ipcgtw_copier.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian <baofeng.tian@intel.com> + */ + +/** + * \file audio/ipcgtw_copier.h + * \brief ipcgtw copier shared header file + * \authors Baofeng Tian <baofeng.tian@intel.com> + */ + +#ifndef __SOF_IPCGTW_COPIER_H__ +#define __SOF_IPCGTW_COPIER_H__ + +#include <sof/audio/component_ext.h> +#include <ipc4/gateway.h> +#include <sof/list.h> +#include <ipc/stream.h> +#include "copier.h" + +/* 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_create(struct processing_module *mod, + const struct ipc4_copier_module_cfg *copier, struct pipeline *pipeline); + +#if CONFIG_IPC4_GATEWAY +void copier_ipcgtw_free(struct processing_module *mod); +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); +#else +static inline void copier_ipcgtw_free(struct processing_module *mod) {} +static inline void copier_ipcgtw_reset(struct comp_dev *dev) {} +static inline int copier_ipcgtw_params(struct ipcgtw_data *ipcgtw_data, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + return 0; +} +#endif +#endif /* __SOF_IPCGTW_COPIER_H__ */ diff --git a/src/audio/crossover/CMakeLists.txt b/src/audio/crossover/CMakeLists.txt new file mode 100644 index 000000000000..cd24cc33eb27 --- /dev/null +++ b/src/audio/crossover/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_CROSSOVER STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/crossover_llext) + add_dependencies(app crossover) + return() +endif() + +add_local_sources(sof crossover.c) +add_local_sources(sof crossover_generic.c) +if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof crossover_ipc3.c) +elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof crossover_ipc4.c) +endif() diff --git a/src/audio/crossover/Kconfig b/src/audio/crossover/Kconfig new file mode 100644 index 000000000000..9e56fa3ab6d7 --- /dev/null +++ b/src/audio/crossover/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_CROSSOVER + tristate "Crossover Filter component" + select COMP_BLOB + select MATH_IIR_DF2T + default m if LIBRARY_DEFAULT_MODULAR + help + Select for Crossover Filter component. A crossover can be used to + split a signal into two or more frequency ranges, so that the outputs + can be sent to drivers that are designed for those ranges. diff --git a/src/audio/crossover/README.md b/src/audio/crossover/README.md new file mode 100644 index 000000000000..1e0e180178a9 --- /dev/null +++ b/src/audio/crossover/README.md @@ -0,0 +1,24 @@ +# Crossover Architecture + +This directory contains the Crossover filter component. + +## Overview + +The Crossover splits an audio signal into multiple frequency bands (e.g., Low, Mid, High) so they can be processed or routed independently (like to a woofer and a tweeter). + +## Architecture Diagram + +```mermaid +graph LR + In[Wideband Audio In] --> Cross[Crossover Split] + Cross --> OutLow[Low Frequency Out] + Cross --> OutHigh[High Frequency Out] +``` + +## Configuration and Scripts + +- **Kconfig**: Selects the Crossover Filter (`COMP_CROSSOVER`), which splits signals into driver-specific frequencies. Also automatically selects `COMP_BLOB` and `MATH_IIR_DF2T` math functions for its internal filters. +- **CMakeLists.txt**: Handles modular builds (`llext`). Selects `crossover.c` and generic implementations, and chooses the correct IPC file (`crossover_ipc3.c` or `crossover_ipc4.c`) based on the active IPC major version. +- **crossover.toml**: Topology parameters for the Crossover module. For IPC4, it sets `init_config = 1` so that `base_cfg_ext` is appended to the IPC payload, which is required up-front to identify output pin indices. Defines UUID, pins, and memory requirements. +- **Topology (.conf)**: `tools/topology/topology2/include/components/crossover.conf` defines the `crossover` widget object. It sets basic widget requirements and defaults to type `effect` with UUID `d1:9a:8c:94:6a:80:31:41:ad:6c:b2:bd:a9:e3:5a:9f`. +- **MATLAB Tuning (`tune/`)**: The `tune` directory holds MATLAB/Octave scripts (like `sof_example_crossover.m`) that convert mathematical frequency split parameters (e.g., 200 Hz, 1000 Hz, 3000 Hz cutoffs) into binary, ALSA, and `.conf` payloads suitable for 2-way, 3-way, or 4-way driver crossover configurations. diff --git a/src/audio/crossover/crossover.c b/src/audio/crossover/crossover.c new file mode 100644 index 000000000000..5c1dca7cc9aa --- /dev/null +++ b/src/audio/crossover/crossover.c @@ -0,0 +1,639 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <module/crossover/crossover_common.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/math/iir_df1.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <user/eq.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <limits.h> + +#include "crossover_user.h" +#include "crossover.h" + +LOG_MODULE_REGISTER(crossover, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(crossover); + +/** + * \brief Reset the state (coefficients and delay) of the crossover filter + * across all channels + */ +static void crossover_reset_state(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + int i; + + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + crossover_reset_state_ch(mod, &cd->state[i]); +} + +/** + * \brief Returns the index i such that assign_sink[i] = pipe_id. + * + * The assign_sink array in the configuration maps to the pipeline ids. + * + * \return the position at which pipe_id is found in config->assign_sink. + * -EINVAL if not found. + */ +int crossover_get_stream_index(struct processing_module *mod, + struct sof_crossover_config *config, uint32_t pipe_id) +{ + int i; + uint32_t *assign_sink = config->assign_sink; + + for (i = 0; i < config->num_sinks; i++) + if (assign_sink[i] == pipe_id) + return i; + + comp_err(mod->dev, "error: couldn't find any assignment for connected pipeline %u", + pipe_id); + + return -EINVAL; +} + +/* + * \brief Aligns the sinks with their respective assignments + * in the configuration. + * + * Refer to sof/src/include/sof/crossover.h for more information on assigning + * sinks to an output. + * + * \param[out] sinks array where the sinks are assigned + * \return number of sinks assigned. This number should be equal to + * config->num_sinks if no errors were found. + */ +static int crossover_assign_sinks(struct processing_module *mod, + struct output_stream_buffer *output_buffers, + struct output_stream_buffer **assigned_obufs, + bool *enabled) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_crossover_config *config = cd->config; + struct comp_dev *dev = mod->dev; + struct comp_buffer *sink; + int num_sinks = 0; + int i; + int j = 0; + + comp_dev_for_each_consumer(dev, sink) { + unsigned int sink_id, state; + + sink_id = crossover_get_sink_id(cd, buffer_pipeline_id(sink), j); + state = comp_buffer_get_sink_state(sink); + if (state != dev->state) { + j++; + continue; + } + + /* If no config is set, then assign the sinks in order */ + if (!config) { + assigned_obufs[num_sinks++] = &output_buffers[j]; + enabled[j++] = true; + continue; + } + + i = crossover_get_stream_index(mod, config, sink_id); + + /* If this sink buffer is not assigned + * in the configuration. + */ + if (i < 0) { + comp_err(dev, + "could not find sink %d in config", + sink_id); + break; + } + + if (assigned_obufs[i]) { + comp_err(dev, + "multiple sinks with id %d are assigned", + sink_id); + break; + } + + assigned_obufs[i] = &output_buffers[j]; + enabled[j++] = true; + num_sinks++; + } + + return num_sinks; +} + +/** + * \brief Sets the state of a single LR4 filter. + * + * An LR4 filter is built by cascading two biquads in series. + * + * \param coef struct containing the coefficients of a butterworth + * high/low pass filter. + * \param[out] lr4 initialized struct + */ +static int crossover_init_coef_lr4(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, + struct iir_state_df1 *lr4) +{ + int ret; + + /* Ensure the LR4 can be processed with the simplified 4th order IIR */ + if (CROSSOVER_LR4_NUM_BIQUADS != SOF_IIR_DF1_4TH_NUM_BIQUADS) + return -EINVAL; + + /* Only one set of coefficients is stored in config for both biquads + * in series due to identity. To maintain the structure of + * iir_state_df1, it requires two copies of coefficients in a row. + */ + lr4->coef = mod_zalloc(mod, sizeof(struct sof_eq_iir_biquad) * 2); + if (!lr4->coef) + return -ENOMEM; + + /* coefficients of the first biquad */ + ret = memcpy_s(lr4->coef, sizeof(struct sof_eq_iir_biquad), + coef, sizeof(struct sof_eq_iir_biquad)); + assert(!ret); + + /* coefficients of the second biquad */ + ret = memcpy_s(lr4->coef + SOF_EQ_IIR_NBIQUAD, + sizeof(struct sof_eq_iir_biquad), + coef, sizeof(struct sof_eq_iir_biquad)); + assert(!ret); + + /* LR4 filters are two 2nd order filters, so only need 4 delay slots + * delay[0..1] -> state for first biquad + * delay[2..3] -> state for second biquad + */ + lr4->delay = mod_zalloc(mod, sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4); + if (!lr4->delay) + return -ENOMEM; + + lr4->biquads = CROSSOVER_LR4_NUM_BIQUADS; + lr4->biquads_in_series = CROSSOVER_LR4_NUM_BIQUADS; + + return 0; +} + +/** + * \brief Initializes the crossover coefficients for one channel + */ +int crossover_init_coef_ch(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, + struct crossover_state *ch_state, + int32_t num_sinks) +{ + int32_t i; + int32_t j = 0; + int32_t num_lr4s = num_sinks == CROSSOVER_2WAY_NUM_SINKS ? 1 : 3; + int err; + + for (i = 0; i < num_lr4s; i++) { + /* Get the low pass coefficients */ + err = crossover_init_coef_lr4(mod, &coef[j], + &ch_state->lowpass[i]); + if (err < 0) + return -EINVAL; + /* Get the high pass coefficients */ + err = crossover_init_coef_lr4(mod, &coef[j + 1], + &ch_state->highpass[i]); + if (err < 0) + return -EINVAL; + j += 2; + } + + return 0; +} + +/** + * \brief Initializes the coefficients of the crossover filter + * and assign them to the first nch channels. + * + * \param nch number of channels in the audio stream. + */ +static int crossover_init_coef(struct processing_module *mod, int nch) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_eq_iir_biquad *crossover; + struct sof_crossover_config *config = cd->config; + int ch, err; + + if (!config) { + comp_err(mod->dev, "no config is set"); + return -EINVAL; + } + + /* Sanity checks */ + if (nch > PLATFORM_MAX_CHANNELS) { + comp_err(mod->dev, "invalid channels count (%i)", nch); + return -EINVAL; + } + + comp_info(mod->dev, "initializing %i-way crossover", + config->num_sinks); + + /* Collect the coef array and assign it to every channel */ + crossover = config->coef; + for (ch = 0; ch < nch; ch++) { + err = crossover_init_coef_ch(mod, crossover, &cd->state[ch], + config->num_sinks); + /* Free all previously allocated blocks in case of an error */ + if (err < 0) { + comp_err(mod->dev, "could not assign coefficients to ch %d", + ch); + crossover_reset_state(mod); + return err; + } + } + + return 0; +} + +/** + * \brief Setup the state, coefficients and processing functions for crossover. + */ +static int crossover_setup(struct processing_module *mod, int nch) +{ + int ret = 0; + + /* Reset any previous state */ + crossover_reset_state(mod); + + /* Assign LR4 coefficients from config */ + ret = crossover_init_coef(mod, nch); + + return ret; +} + +/** + * \brief Creates a Crossover Filter component. + * \return Pointer to Crossover Filter component device. + */ +static int crossover_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct comp_data *cd; + int ret; + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + + /* Handler for configuration data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "comp_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto cd_fail; + } + + ret = crossover_output_pin_init(mod); + if (ret < 0) { + comp_err(dev, "failed."); + goto cd_fail; + } + + crossover_reset_state(mod); + return 0; + +cd_fail: + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); + return ret; +} + +/** + * \brief Frees Crossover Filter component. + */ +static int crossover_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + mod_data_blob_handler_free(mod, cd->model_handler); + + crossover_reset_state(mod); + + mod_free(mod, cd); + return 0; +} + +/** + * \brief Verifies that the config is formatted correctly. + * + * The function can only be called after the buffers have been initialized. + */ +static int crossover_validate_config(struct processing_module *mod, + struct sof_crossover_config *config) +{ + struct comp_dev *dev = mod->dev; + uint32_t size = config->size; + int32_t num_assigned_sinks; + + if (size > SOF_CROSSOVER_MAX_SIZE || !size) { + comp_err(dev, "size %d is invalid", size); + return -EINVAL; + } + + if (config->num_sinks > SOF_CROSSOVER_MAX_STREAMS || + config->num_sinks < 2) { + comp_err(dev, "invalid num_sinks %i, expected number between 2 and %i", + config->num_sinks, SOF_CROSSOVER_MAX_STREAMS); + return -EINVAL; + } + + /* Align the crossover's sinks, to their respective configuration in + * the config. + */ + num_assigned_sinks = crossover_check_sink_assign(mod, config); + + /* Config is invalid if the number of assigned sinks + * is different than what is configured. + */ + if (num_assigned_sinks != config->num_sinks) { + comp_err(dev, "number of assigned sinks %d, expected from config %d", + num_assigned_sinks, config->num_sinks); + return -EINVAL; + } + + return 0; +} + +/* used to pass standard and bespoke commands (with data) to component */ +static int crossover_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_data *cd = module_get_private_data(mod); + int ret; + + comp_info(mod->dev, "entry"); + + ret = crossover_check_config(mod, fragment); + if (ret < 0) + return ret; + + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); +} + +static int crossover_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + int ret; + + comp_info(mod->dev, "entry"); + + ret = crossover_check_config(mod, fragment); + if (ret < 0) + return ret; + + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +/** + * \brief Copies and processes stream data. + * \param[in,out] dev Crossover Filter base component device. + * \return Error code. + */ +static int crossover_process_audio_stream(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers) +{ + struct output_stream_buffer *assigned_obufs[SOF_CROSSOVER_MAX_STREAMS] = { NULL }; + bool enabled_buffers[PLATFORM_MAX_STREAMS] = { false }; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct audio_stream *source = input_buffers[0].data; + uint32_t num_sinks; + uint32_t num_assigned_sinks = 0; + /* The frames count to process from module adapter applies for source buffer and + * all sink buffers. The function module_single_source_setup() checks the frames + * avail/free from all source and sink combinations. + */ + uint32_t frames = input_buffers[0].size; + uint32_t frame_bytes = audio_stream_frame_bytes(input_buffers[0].data); + uint32_t processed_bytes; + int ret; + int i; + + comp_dbg(dev, "entry"); + + /* 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(mod, audio_stream_get_channels(source)); + if (ret < 0) { + comp_err(dev, "failed Crossover setup"); + return ret; + } + } + + /* Use the assign_sink array from the config to route + * the output to the corresponding sinks. + * It is possible for an assigned sink to be in a different + * state than the component. Therefore not all sinks are guaranteed + * to be assigned: sink[i] can be NULL, 0 <= i <= config->num_sinks + */ + num_assigned_sinks = crossover_assign_sinks(mod, output_buffers, assigned_obufs, + enabled_buffers); + if (cd->config && num_assigned_sinks != cd->config->num_sinks) + comp_dbg(dev, "crossover_copy(), number of assigned sinks (%i) does not match number of sinks in config (%i).", + num_assigned_sinks, cd->config->num_sinks); + + /* If no config is set then assign the number of sinks to the number + * of sinks that were assigned. + */ + if (cd->config) + num_sinks = cd->config->num_sinks; + else + num_sinks = num_assigned_sinks; + + /* Process crossover */ + if (!frames) + return -ENODATA; + + cd->crossover_process(cd, input_buffers, assigned_obufs, num_sinks, frames); + + processed_bytes = frames * frame_bytes; + mod->input_buffers[0].consumed = processed_bytes; + for (i = 0; i < num_output_buffers; i++) { + if (enabled_buffers[i]) + mod->output_buffers[i].size = processed_bytes; + } + + return 0; +} + +/** + * \brief Prepares Crossover Filter component for processing. + * \param[in,out] dev Crossover Filter base component device. + * \return Error code. + */ +static int crossover_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *source, *sink; + size_t data_size; + int channels; + + comp_info(dev, "entry"); + + source = comp_dev_get_first_data_producer(dev); + if (!source) { + comp_err(dev, "no source buffer"); + return -ENOTCONN; + } + + crossover_params(mod); + + /* Crossover has a variable number of sinks */ + mod->max_sinks = SOF_CROSSOVER_MAX_STREAMS; + + /* Get source data format */ + cd->source_format = audio_stream_get_frm_fmt(&source->stream); + channels = audio_stream_get_channels(&source->stream); + + /* Validate frame format and buffer size of sinks */ + comp_dev_for_each_consumer(dev, sink) { + if (cd->source_format != audio_stream_get_frm_fmt(&sink->stream)) { + comp_err(dev, "Source fmt %d and sink fmt %d are different.", + cd->source_format, audio_stream_get_frm_fmt(&sink->stream)); + return -EINVAL; + } + } + + comp_info(dev, "source_format=%d, sink_formats=%d, nch=%d", + cd->source_format, cd->source_format, channels); + + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + + /* Initialize Crossover */ + if (cd->config && + (!data_size || crossover_validate_config(mod, cd->config) < 0)) { + /* If the configuration is invalid fail the prepare */ + comp_err(dev, "invalid binary config format"); + return -EINVAL; + } + + if (cd->config) { + int ret = crossover_setup(mod, channels); + + if (ret < 0) { + comp_err(dev, "setup failed"); + return ret; + } + + cd->crossover_process = crossover_find_proc_func(cd->source_format); + if (!cd->crossover_process) { + comp_err(dev, "No processing function matching frame_fmt %i", + cd->source_format); + return -EINVAL; + } + + cd->crossover_split = crossover_find_split_func(cd->config->num_sinks); + if (!cd->crossover_split) { + comp_err(dev, "No split function matching num_sinks %i", + cd->config->num_sinks); + return -EINVAL; + } + } else { + comp_info(dev, "setting crossover to passthrough mode"); + + cd->crossover_process = crossover_find_proc_func_pass(cd->source_format); + if (!cd->crossover_process) { + comp_err(dev, "No passthrough function matching frame_fmt %i", + cd->source_format); + return -EINVAL; + } + } + + return 0; +} + +/** + * \brief Resets Crossover Filter component. + * \param[in,out] dev Crossover Filter base component device. + * \return Error code. + */ +static int crossover_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + crossover_reset_state(mod); + + cd->crossover_process = NULL; + cd->crossover_split = NULL; + + return 0; +} + +/** \brief Crossover Filter component definition. */ +static const struct module_interface crossover_interface = { + .init = crossover_init, + .prepare = crossover_prepare, + .process_audio_stream = crossover_process_audio_stream, + .set_configuration = crossover_set_config, + .get_configuration = crossover_get_config, + .reset = crossover_reset, + .free = crossover_free +}; + +#if CONFIG_COMP_CROSSOVER_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("XOVER", &crossover_interface, 1, SOF_REG_UUID(crossover), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(crossover_tr, SOF_UUID(crossover_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(crossover_interface, crossover_uuid, crossover_tr); +SOF_MODULE_INIT(crossover, sys_comp_module_crossover_interface_init); + +#endif diff --git a/src/audio/crossover/crossover.h b/src/audio/crossover/crossover.h new file mode 100644 index 000000000000..2312a1d53857 --- /dev/null +++ b/src/audio/crossover/crossover.h @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Sebastiano Carlucci <scarlucci@google.com> + */ +#ifndef __SOF_AUDIO_CROSSOVER_CROSSOVER_H__ +#define __SOF_AUDIO_CROSSOVER_CROSSOVER_H__ + +#include <sof/audio/module_adapter/module/module_interface.h> +#include <sof/math/iir_df1.h> +#include <module/crossover/crossover_common.h> +#include <sof/platform.h> +#include <stdint.h> + +#include "crossover_user.h" + +#define CROSSOVER_LR4_NUM_BIQUADS 2 + +struct comp_buffer; +struct comp_dev; + +/** + * The Crossover filter will have from 2 to 4 outputs. + * Diagram of a 4-way Crossover filter (6 LR4 Filters). + * + * o---- LR4 LO-PASS --> y1(n) + * | + * o--- LR4 LO-PASS --o + * | | + * | o--- LR4 HI-PASS --> y2(n) + * x(n) --- o + * | o--- LR4 LO-PASS --> y3(n) + * | | + * o--- LR4 HI-PASS --o + * | + * o--- LR4 HI-PASS --> y4(n) + * + * Refer to include/user/crossover.h for diagrams of 2-way and 3-way crossovers + * The low and high pass LR4 filters have opposite phase responses, causing + * the intermediary outputs to be out of phase by 180 degrees. + * For 2-way and 3-way, the phases of the signals need to be synchronized. + * + * Each LR4 is made of two butterworth filters in series with the same params. + * + * x(n) --> BIQUAD --> z(n) --> BIQUAD --> y(n) + * + * In total, we keep track of the state of at most 6 IIRs each made of two + * biquads in series. + * + */ + +struct comp_data; + +typedef void (*crossover_process)(struct comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsinks[], + int32_t num_sinks, + uint32_t frames); + +/* Crossover component private data */ +struct comp_data { + /**< filter state */ + struct crossover_state state[PLATFORM_MAX_CHANNELS]; +#if CONFIG_IPC_MAJOR_4 + uint32_t output_pin_index[SOF_CROSSOVER_MAX_STREAMS]; + uint32_t num_output_pins; +#endif + struct comp_data_blob_handler *model_handler; + struct sof_crossover_config *config; /**< pointer to setup blob */ + enum sof_ipc_frame source_format; /**< source frame format */ + crossover_process crossover_process; /**< processing function */ + crossover_split crossover_split; /**< split function */ +}; + +struct crossover_proc_fnmap { + enum sof_ipc_frame frame_fmt; + crossover_process crossover_proc_func; +}; + +extern const struct crossover_proc_fnmap crossover_proc_fnmap[]; +extern const struct crossover_proc_fnmap crossover_proc_fnmap_pass[]; +extern const size_t crossover_proc_fncount; + +/** + * \brief Returns Crossover processing function. + */ +static inline crossover_process + crossover_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < crossover_proc_fncount; i++) + if (src_fmt == crossover_proc_fnmap[i].frame_fmt) + return crossover_proc_fnmap[i].crossover_proc_func; + + return NULL; +} + +/** + * \brief Returns Crossover passthrough functions. + */ +static inline crossover_process + crossover_find_proc_func_pass(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < crossover_proc_fncount; i++) + if (src_fmt == crossover_proc_fnmap_pass[i].frame_fmt) + return crossover_proc_fnmap_pass[i].crossover_proc_func; + + return NULL; +} + +extern const crossover_split crossover_split_fnmap[]; +extern const size_t crossover_split_fncount; + +/* + * \brief Runs input in through the LR4 filter and returns it's output. + */ +static inline int32_t crossover_generic_process_lr4(int32_t in, + struct iir_state_df1 *lr4) +{ + /* Cascade two biquads with same coefficients in series. */ + return iir_df1_4th(lr4, in); +} + +static inline void crossover_free_config(struct sof_crossover_config **config) +{ + rfree(*config); + *config = NULL; +} + +int crossover_get_sink_id(struct comp_data *cd, uint32_t pipeline_id, uint32_t index); +int crossover_output_pin_init(struct processing_module *mod); +int crossover_check_sink_assign(struct processing_module *mod, + struct sof_crossover_config *config); +int crossover_check_config(struct processing_module *mod, const uint8_t *fragment); +void crossover_params(struct processing_module *mod); +int crossover_get_stream_index(struct processing_module *mod, + struct sof_crossover_config *config, uint32_t pipe_id); + +#endif // __SOF_AUDIO_CROSSOVER_CROSSOVER_H__ diff --git a/src/audio/crossover/crossover.toml b/src/audio/crossover/crossover.toml new file mode 100644 index 000000000000..fead1e8e22d2 --- /dev/null +++ b/src/audio/crossover/crossover.toml @@ -0,0 +1,24 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Crossover module config + REM # Note: Crossover has init_config set to 1 to let kernel know that the base_cfg_ext needs to + REM # be appended to the IPC payload. The Extension is needed to know the output pin indices. + [[module.entry]] + name = "XOVER" + uuid = UUIDREG_STR_CROSSOVER + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + init_config = "1" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/crossover/crossover_generic.c b/src/audio/crossover/crossover_generic.c new file mode 100644 index 000000000000..028018934816 --- /dev/null +++ b/src/audio/crossover/crossover_generic.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <ipc/stream.h> +#include <sof/audio/module_adapter/module/module_interface.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> +#include <stdint.h> + +#include "crossover.h" + +/* + * \brief Splits x into two based on the coefficients set in the lp + * and hp filters. The output of the lp is in y1, the output of + * the hp is in y2. + * + * As a side effect, this function mutates the delay values of both + * filters. + */ +static inline void crossover_generic_lr4_split(struct iir_state_df1 *lp, + struct iir_state_df1 *hp, + int32_t x, int32_t *y1, + int32_t *y2) +{ + *y1 = crossover_generic_process_lr4(x, lp); + *y2 = crossover_generic_process_lr4(x, hp); +} + +/* + * \brief Splits input signal into two and merges it back to it's + * original form. + * + * With 3-way crossovers, one output goes through only one LR4 filter, + * whereas the other two go through two LR4 filters. This causes the signals + * to be out of phase. We need to pass the signal through another set of LR4 + * filters to align back the phase. + */ +static inline void crossover_generic_lr4_merge(struct iir_state_df1 *lp, + struct iir_state_df1 *hp, + int32_t x, int32_t *y) +{ + int32_t z1, z2; + + z1 = crossover_generic_process_lr4(x, lp); + z2 = crossover_generic_process_lr4(x, hp); + *y = sat_int32(((int64_t)z1) + z2); +} + +static void crossover_generic_split_2way(int32_t in, + int32_t out[], + struct crossover_state *state) +{ + crossover_generic_lr4_split(&state->lowpass[0], &state->highpass[0], + in, &out[0], &out[1]); +} + +static void crossover_generic_split_3way(int32_t in, + int32_t out[], + struct crossover_state *state) +{ + int32_t z1, z2; + + crossover_generic_lr4_split(&state->lowpass[0], &state->highpass[0], + in, &z1, &z2); + /* Realign the phase of z1 */ + crossover_generic_lr4_merge(&state->lowpass[1], &state->highpass[1], + z1, &out[0]); + crossover_generic_lr4_split(&state->lowpass[2], &state->highpass[2], + z2, &out[1], &out[2]); +} + +static void crossover_generic_split_4way(int32_t in, + int32_t out[], + struct crossover_state *state) +{ + int32_t z1, z2; + + crossover_generic_lr4_split(&state->lowpass[1], &state->highpass[1], + in, &z1, &z2); + crossover_generic_lr4_split(&state->lowpass[0], &state->highpass[0], + z1, &out[0], &out[1]); + crossover_generic_lr4_split(&state->lowpass[2], &state->highpass[2], + z2, &out[2], &out[3]); +} + +static void crossover_default_pass(struct comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer **bsinks, + int32_t num_sinks, + uint32_t frames) +{ + const struct audio_stream *source_stream = bsource->data; + uint32_t samples = audio_stream_get_channels(source_stream) * frames; + int i; + + for (i = 0; i < num_sinks; i++) { + if (!bsinks[i]) + continue; + audio_stream_copy(source_stream, 0, bsinks[i]->data, 0, samples); + } +} + +#if CONFIG_FORMAT_S16LE +static void crossover_s16_default(struct comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer **bsinks, + int32_t num_sinks, + uint32_t frames) +{ + struct crossover_state *state; + const struct audio_stream *source_stream = bsource->data; + struct audio_stream *sink_stream; + int16_t *x, *y; + int ch, i, j; + int idx; + int nch = audio_stream_get_channels(source_stream); + int32_t out[num_sinks]; + + for (ch = 0; ch < nch; ch++) { + idx = ch; + state = &cd->state[ch]; + for (i = 0; i < frames; i++) { + x = audio_stream_read_frag_s16(source_stream, idx); + cd->crossover_split(*x << 16, out, state); + + for (j = 0; j < num_sinks; j++) { + if (!bsinks[j]) + continue; + sink_stream = bsinks[j]->data; + y = audio_stream_write_frag_s16(sink_stream, + idx); + *y = sat_int16(Q_SHIFT_RND(out[j], 31, 15)); + } + + idx += nch; + } + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void crossover_s24_default(struct comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer **bsinks, + int32_t num_sinks, + uint32_t frames) +{ + struct crossover_state *state; + const struct audio_stream *source_stream = bsource->data; + struct audio_stream *sink_stream; + int32_t *x, *y; + int ch, i, j; + int idx; + int nch = audio_stream_get_channels(source_stream); + int32_t out[num_sinks]; + + for (ch = 0; ch < nch; ch++) { + idx = ch; + state = &cd->state[ch]; + for (i = 0; i < frames; i++) { + x = audio_stream_read_frag_s32(source_stream, idx); + cd->crossover_split(*x << 8, out, state); + + for (j = 0; j < num_sinks; j++) { + if (!bsinks[j]) + continue; + sink_stream = bsinks[j]->data; + y = audio_stream_write_frag_s32(sink_stream, + idx); + *y = sat_int24(Q_SHIFT_RND(out[j], 31, 23)); + } + + idx += nch; + } + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief Processes audio frames with a crossover filter for s32 format. + * + * This function divides audio data from an input stream into multiple output + * streams based on a crossover filter. It reads the input audio data, applies + * the crossover filter, and writes the processed audio data to active output + * streams. + * + * \param cd Pointer to the component data structure which holds the crossover state. + * \param bsource Pointer to the input stream buffer structure. + * \param bsinks Array of pointers to output stream buffer structures. + * \param num_sinks Number of output stream buffers in the bsinks array. + * \param frames Number of audio frames to process. + */ +static void crossover_s32_default(struct comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer **bsinks, + int32_t num_sinks, + uint32_t frames) +{ + /* Array to hold active sink streams; initialized to null */ + struct audio_stream *sink_stream[SOF_CROSSOVER_MAX_STREAMS] = { NULL }; + struct crossover_state *state; + /* Source stream to read audio data from */ + const struct audio_stream *source_stream = bsource->data; + int32_t *x, *y; + int ch, i, j; + int idx; + /* Counter for active sink streams */ + int active_sinks = 0; + /* Number of channels in the source stream */ + int nch = audio_stream_get_channels(source_stream); + /* Output buffer for processed data */ + int32_t out[num_sinks]; + + /* Identify active sinks, avoid processing null sinks later */ + for (j = 0; j < num_sinks; j++) { + if (bsinks[j]) + sink_stream[active_sinks++] = bsinks[j]->data; + } + + /* Process for each channel */ + /* Loop through each channel in the source stream */ + for (ch = 0; ch < nch; ch++) { + /* Set current crossover state for this channel */ + state = &cd->state[ch]; + /* Iterate over frames */ + /* Loop through each frame */ + for (i = 0, idx = ch; i < frames; i++, idx += nch) { + /* Read source */ + /* Read the current audio frame for the channel */ + x = audio_stream_read_frag_s32(source_stream, idx); + /* Apply the crossover split logic to the audio data */ + cd->crossover_split(*x, out, state); + + /* Write output to active sinks */ + /* Write processed output to active sinks */ + for (j = 0; j < active_sinks; j++) { + /* Write processed data to sink */ + y = audio_stream_write_frag_s32(sink_stream[j], idx); + *y = out[j]; + } + + } + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct crossover_proc_fnmap crossover_proc_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, crossover_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, crossover_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, crossover_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const struct crossover_proc_fnmap crossover_proc_fnmap_pass[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, crossover_default_pass }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, crossover_default_pass }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, crossover_default_pass }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t crossover_proc_fncount = ARRAY_SIZE(crossover_proc_fnmap); + +const crossover_split crossover_split_fnmap[] = { + crossover_generic_split_2way, + crossover_generic_split_3way, + crossover_generic_split_4way, +}; + +const size_t crossover_split_fncount = ARRAY_SIZE(crossover_split_fnmap); diff --git a/src/audio/crossover/crossover_ipc3.c b/src/audio/crossover/crossover_ipc3.c new file mode 100644 index 000000000000..48f56ac3cced --- /dev/null +++ b/src/audio/crossover/crossover_ipc3.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <module/module/base.h> +#include <sof/trace/trace.h> +#include <sof/audio/buffer.h> +#include <ipc/control.h> +#include <sof/common.h> +#include <sof/list.h> +#include <errno.h> + +#include "crossover_user.h" +#include "crossover.h" + +LOG_MODULE_DECLARE(crossover, CONFIG_SOF_LOG_LEVEL); + +int crossover_get_sink_id(struct comp_data *cd, uint32_t pipeline_id, uint32_t index) +{ + return pipeline_id; +} + +int crossover_output_pin_init(struct processing_module *mod) +{ + return 0; +} + +/** + * \brief Check sink streams configuration for matching pipeline IDs + */ +int crossover_check_sink_assign(struct processing_module *mod, + struct sof_crossover_config *config) +{ + struct comp_dev *dev = mod->dev; + struct comp_buffer *sink; + int num_assigned_sinks = 0; + uint8_t assigned_sinks[SOF_CROSSOVER_MAX_STREAMS] = {0}; + int i; + + comp_dev_for_each_consumer(dev, sink) { + unsigned int pipeline_id; + + pipeline_id = buffer_pipeline_id(sink); + + i = crossover_get_stream_index(mod, config, pipeline_id); + if (i < 0) { + comp_warn(dev, "could not assign sink %d", + pipeline_id); + break; + } + + if (assigned_sinks[i]) { + comp_warn(dev, "multiple sinks from pipeline %d are assigned", + pipeline_id); + break; + } + + assigned_sinks[i] = true; + num_assigned_sinks++; + } + + return num_assigned_sinks; +} + +int crossover_check_config(struct processing_module *mod, const uint8_t *fragment) +{ + /* TODO: This check seems to work only for IPC3, FW crash happens from reject from + * topology embedded blob. + */ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) { + comp_err(mod->dev, "crossover_set/get_config(), invalid command"); + return -EINVAL; + } + + return 0; +} + +/** + * \brief IPC4 specific component prepare, updates source and sink buffers formats from base_cfg + */ +void crossover_params(struct processing_module *mod) +{ +} diff --git a/src/audio/crossover/crossover_ipc4.c b/src/audio/crossover/crossover_ipc4.c new file mode 100644 index 000000000000..3e0beffeeeb1 --- /dev/null +++ b/src/audio/crossover/crossover_ipc4.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <module/ipc4/base-config.h> +#include <sof/audio/component.h> +#include <module/module/base.h> +#include <sof/trace/trace.h> +#include <sof/audio/buffer.h> +#include <sof/common.h> +#include <sof/list.h> +#include <ipc/stream.h> +#include <errno.h> + +#include "crossover_user.h" +#include "crossover.h" + +LOG_MODULE_DECLARE(crossover, CONFIG_SOF_LOG_LEVEL); + +int crossover_get_sink_id(struct comp_data *cd, uint32_t pipeline_id, uint32_t index) +{ + return cd->output_pin_index[index]; +} + +/* Note: Crossover needs to have in the rimage manifest the init_config set to 1 to let + * kernel know that the base_cfg_ext needs to be appended to the IPC payload. The + * Extension is needed to know the output pin indices. + */ +static int crossover_init_output_pins(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + const struct ipc4_base_module_extended_cfg *base_cfg = mod->priv.cfg.init_data; + uint16_t num_input_pins = base_cfg->base_cfg_ext.nb_input_pins; + uint16_t num_output_pins = base_cfg->base_cfg_ext.nb_output_pins; + struct ipc4_input_pin_format *input_pin; + struct ipc4_output_pin_format *output_pin; + int i; + + comp_dbg(dev, "Number of input pins %u, output pins %u", num_input_pins, num_output_pins); + + if (num_input_pins != 1 || num_output_pins > SOF_CROSSOVER_MAX_STREAMS) { + comp_err(dev, "Illegal number of pins %u %u", num_input_pins, num_output_pins); + return -EINVAL; + } + + input_pin = (struct ipc4_input_pin_format *)base_cfg->base_cfg_ext.pin_formats; + output_pin = (struct ipc4_output_pin_format *)(input_pin + 1); + cd->num_output_pins = num_output_pins; + comp_dbg(dev, "input pin index = %u", input_pin->pin_index); + for (i = 0; i < num_output_pins; i++) { + comp_dbg(dev, "output pin %d index = %u", i, output_pin[i].pin_index); + cd->output_pin_index[i] = output_pin[i].pin_index; + } + + return 0; +} + +int crossover_output_pin_init(struct processing_module *mod) +{ + return crossover_init_output_pins(mod); +} + +/** + * \brief Check sink streams configuration for matching pin index for output pins + */ +int crossover_check_sink_assign(struct processing_module *mod, + struct sof_crossover_config *config) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint32_t pin_index; + int num_assigned_sinks = 0; + int i, j; + uint8_t assigned_sinks[SOF_CROSSOVER_MAX_STREAMS] = {0}; + + for (j = 0; j < cd->num_output_pins; j++) { + pin_index = cd->output_pin_index[j]; + i = crossover_get_stream_index(mod, config, pin_index); + if (i < 0) { + comp_warn(dev, "could not assign sink %u", + pin_index); + break; + } + + if (assigned_sinks[i]) { + comp_warn(dev, "multiple sinks from pin %u are assigned", + pin_index); + break; + } + + assigned_sinks[i] = true; + num_assigned_sinks++; + } + + return num_assigned_sinks; +} + +int crossover_check_config(struct processing_module *mod, const uint8_t *fragment) +{ + return 0; +} + +/** + * \brief IPC4 specific component prepare, updates source and sink buffers formats from base_cfg + */ +void crossover_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + /* First producer verified by the caller */ + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); + + comp_dev_for_each_consumer(dev, sinkb) { + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); + } +} diff --git a/src/audio/crossover/crossover_user.h b/src/audio/crossover/crossover_user.h new file mode 100644 index 000000000000..5f6ba2b14044 --- /dev/null +++ b/src/audio/crossover/crossover_user.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Sebastiano Carlucci <scarlucci@google.com> + */ + +#ifndef __USER_CROSSOVER_H__ +#define __USER_CROSSOVER_H__ + +#include <stdint.h> +#include <user/eq.h> +#include <module/crossover/crossover_common.h> + +/* Maximum number allowed in configuration blob */ +#define SOF_CROSSOVER_MAX_SIZE 1024 + + /* crossover_configuration + * uint32_t number_of_sinks <= 4 + * 1=passthrough, n=n-way cossover. + * uint32_t assign_sinks[SOF_CROSSOVER_MAX_STREAMS] + * Mapping between sink positions and the sink's pipeline id. To assign + * output j to sink i, set: assign_sinks[j] = i. Refer to the diagrams + * below for more information on the sink outputs. + * + * 4-way: + * o---- LR4 LP0 --> LOW assign_sink[0] + * | + * o--- LR4 LP1 --o + * | | + * | o---- LR4 HP0 --> MID_LOW assign_sink[1] + * x(n) --- o + * | o---- LR4 LP2 --> MID_HIGH assign_sink[2] + * | | + * o--- LR4 HP1 --o + * | + * o---- LR4 HP2 --> HIGH assign_sink[3] + * + * Merging is necessary for 3way to adjsut the phase of the + * outputs. + * 3-way: + * o---- LR4 LP1 --o + * | | + * o--- LR4 LP0 --o +-> LOW assign_sink[0] + * | | | + * | o---- LR4 HP1 --o + * x(n) --- o + * | o---- LR4 LP2 -----> MID assign_sink[1] + * | | + * o--- LR4 HP0 --o + * | + * o---- LR4 HP2 -----> HIGH assign_sink[2] + * + * 2-way: + * o--- LR4 LP0 ---> LOW assign_sink[0] + * | + * x(n) --- o + * | + * o--- LR4 HP0 ---> HIGH assign_sink[1] + * + * struct sof_eq_iir_biquad coef[(num_sinks - 1)*2] + * The coefficients data for the LR4s. Depending on many + * sinks are set, the number entries of this field can vary. + * Each entry of the array defines the coefficients for one biquad + * of the LR4 filter. The order the coefficients are assigned is: + * [LR4 LP0, LR4 HP0, LR4 LP1, LR4 HP1, LR4 LP2, LR4 HP2]. + * coef[0] = coefficients of LR4 LP0... + * coef[1] = coefficients of LR4 HP0... + * ... + * + * Since an LR4 is two biquads in series with same coefficients, + * the config takes the coefficients for one biquad and + * assigns it to both biquads of the LR4. + * + * <1st Low Pass LR4> + * int32_t coef_a2 Q2.30 format + * int32_t coef_a1 Q2.30 format + * int32_t coef_b2 Q2.30 format + * int32_t coef_b1 Q2.30 format + * int32_t coef_b0 Q2.30 format + * int32_t output_shift number of right shift (nve for left) + * int32_t output_gain Q2.14 format + * <1nd High Pass LR4> + * ... + * <2nd Low Pass LR4> + * <2nd High Pass LR4> + * ... + * ... At most 3 Low Pass LR4s and 3 High Pass LR4s ... + * + */ +struct sof_crossover_config { + uint32_t size; + uint32_t num_sinks; + + /* reserved */ + uint32_t reserved[4]; + + uint32_t assign_sink[SOF_CROSSOVER_MAX_STREAMS]; + struct sof_eq_iir_biquad coef[]; +}; + +#endif // __USER_CROSSOVER_H__ diff --git a/src/audio/crossover/llext/CMakeLists.txt b/src/audio/crossover/llext/CMakeLists.txt new file mode 100644 index 000000000000..b4b6e9def9b1 --- /dev/null +++ b/src/audio/crossover/llext/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("crossover" + SOURCES ../crossover.c + ../crossover_generic.c + ../crossover_ipc4.c + LIB openmodules +) diff --git a/src/audio/crossover/llext/llext.toml.h b/src/audio/crossover/llext/llext.toml.h new file mode 100644 index 000000000000..f4134dd7e27e --- /dev/null +++ b/src/audio/crossover/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../crossover.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/crossover/tune/sof_crossover_build_blob.m b/src/audio/crossover/tune/sof_crossover_build_blob.m new file mode 100644 index 000000000000..17f1c2c60fc5 --- /dev/null +++ b/src/audio/crossover/tune/sof_crossover_build_blob.m @@ -0,0 +1,60 @@ +function blob8 = sof_crossover_build_blob(blob_struct, endian, ipc_ver) + +if nargin < 2 + endian = 'little'; +end + +if nargin < 3 + ipc_ver = 3; +end + +%% Shift values for little/big endian +switch lower(endian) + case 'little' + sh = [0 -8 -16 -24]; + case 'big' + sh = [-24 -16 -8 0]; + otherwise + error('Unknown endiannes'); +end + +%% Build Blob +% refer to sof/src/include/user/crossover.h for the config struct. +data_size = 4 * (2 + 4 + 4 + numel(blob_struct.all_coef)); +[abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver); + +blob_size = data_size + abi_size; +blob8 = uint8(zeros(1, blob_size)); + +% Pack Blob data +% Insert ABI Header +blob8(1:abi_size) = abi_bytes; +j = abi_size + 1; + +% Insert Data +blob8(j:j+3) = word2byte(data_size, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.num_sinks, sh); j=j+4; +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved + +for i=1:4 + blob8(j:j+3) = word2byte(blob_struct.assign_sinks(i), sh); + j=j+4; +end + +for i=1:length(blob_struct.all_coef) + blob8(j:j+3) = word2byte(blob_struct.all_coef(i), sh); + j=j+4; +end + +end + +function bytes = word2byte(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/crossover/tune/sof_crossover_coef_quant.m b/src/audio/crossover/tune/sof_crossover_coef_quant.m new file mode 100644 index 000000000000..b53a92c0885d --- /dev/null +++ b/src/audio/crossover/tune/sof_crossover_coef_quant.m @@ -0,0 +1,28 @@ +function crossover_quant = sof_crossover_coef_quant(lowpass, highpass); + +bits_iir = 32; % Q2.30 +qf_iir = 30; + +if length(lowpass) ~= length(highpass) + error("length of lowpass and highpass array do not match"); +end + +n = length(lowpass); +crossover_quant.lp_coef = cell(1,n); +crossover_quant.hp_coef = cell(1,n); +for i = 1:n + lp = lowpass(i); + hp = highpass(i); + lp_a = sof_eq_coef_quant(-lp.a(3:-1:2), bits_iir, qf_iir); + lp_b = sof_eq_coef_quant(lp.b(3:-1:1), bits_iir, qf_iir); + hp_a = sof_eq_coef_quant(-hp.a(3:-1:2), bits_iir, qf_iir); + hp_b = sof_eq_coef_quant(hp.b(3:-1:1), bits_iir, qf_iir); + + crossover_quant.lp_coef(i) = [lp_a lp_b 0 16384]; + crossover_quant.hp_coef(i) = [hp_a hp_b 0 16384]; +end + +crossover_quant.lp_coef = cell2mat(crossover_quant.lp_coef); +crossover_quant.hp_coef = cell2mat(crossover_quant.hp_coef); + +end diff --git a/src/audio/crossover/tune/sof_crossover_gen_coefs.m b/src/audio/crossover/tune/sof_crossover_gen_coefs.m new file mode 100644 index 000000000000..ba53dbdb69d7 --- /dev/null +++ b/src/audio/crossover/tune/sof_crossover_gen_coefs.m @@ -0,0 +1,113 @@ +function crossover = sof_crossover_gen_coefs(fs, fc_low, fc_mid, fc_high) + +switch nargin + case 2, crossover = crossover_generate_2way(fs, fc_low); + case 3, crossover = crossover_generate_3way(fs, fc_low, fc_mid); + case 4, crossover = crossover_generate_4way(fs, fc_low, fc_mid, fc_high); + otherwise, error("Invalid number of arguments"); +end + +end + +function crossover_2way = crossover_generate_2way(fs, fc) + crossover_2way.lp = [lp_iir(fs, fc, 0)]; + crossover_2way.hp = [hp_iir(fs, fc, 0)]; +end + +function crossover_3way = crossover_generate_3way(fs, fc_low, fc_high) + % Duplicate one set of coefficients. The duplicate set will be used to merge back the + % output that is out of phase. + crossover_3way.lp = [lp_iir(fs, fc_low, 0) lp_iir(fs, fc_high, 0) lp_iir(fs, fc_high, 0)]; + crossover_3way.hp = [hp_iir(fs, fc_low, 0) hp_iir(fs, fc_high, 0) hp_iir(fs, fc_high, 0)]; +end + +function crossover_4way = crossover_generate_4way(fs, fc_low, fc_mid, fc_high) + crossover_4way.lp = [lp_iir(fs, fc_low, 0) lp_iir(fs, fc_mid, 0) lp_iir(fs, fc_high, 0)]; + crossover_4way.hp = [hp_iir(fs, fc_low, 0) hp_iir(fs, fc_mid, 0) hp_iir(fs, fc_high, 0)]; +end + +% Generate the a,b coefficients for a second order +% low pass butterworth filter +function lp = lp_iir(fs, fc, gain_db) +[lp.b, lp.a] = low_pass_2nd_resonance(fc, 0, fs); +end + +% Generate the a,b coefficients for a second order +% low pass butterworth filter +function hp = hp_iir(fs, fc, gain_db) +[hp.b, hp.a] = high_pass_2nd_resonance(fc, 0, fs); +end + +function [b, a] = high_pass_2nd_resonance(f, resonance, fs) + cutoff = f/(fs/2); + % Limit cutoff to 0 to 1. + cutoff = max(0.0, min(cutoff, 1.0)); + + if cutoff == 1 || cutoff == 0 + % When cutoff is one, the z-transform is 0. + % When cutoff is zero, we need to be careful because the above + % gives a quadratic divided by the same quadratic, with poles + % and zeros on the unit circle in the same place. When cutoff + % is zero, the z-transform is 1. + + b = [1 - cutoff, 0, 0]; + a = [1, 0, 0]; + return; + end + + % Compute biquad coefficients for highpass filter + resonance = max(0.0, resonance); % can't go negative + g = 10.0^(0.05 * resonance); + d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); + + theta = pi * cutoff; + sn = 0.5 * d * sin(theta); + beta = 0.5 * (1 - sn) / (1 + sn); + gamma = (0.5 + beta) * cos(theta); + alpha = 0.25 * (0.5 + beta + gamma); + + b0 = 2 * alpha; + b1 = 2 * -2 * alpha; + b2 = 2 * alpha; + a1 = 2 * -gamma; + a2 = 2 * beta; + + b = [b0, b1, b2]; + a = [1.0, a1, a2]; +end + +function [b, a] = low_pass_2nd_resonance(f, resonance, fs) + cutoff = f/(fs/2); + % Limit cutoff to 0 to 1. + cutoff = max(0.0, min(cutoff, 1.0)); + + if cutoff == 1 || cutoff == 0 + % When cutoff is 1, the z-transform is 1. + % When cutoff is zero, nothing gets through the filter, so set + % coefficients up correctly. + + b = [cutoff, 0, 0]; + a = [1, 0, 0]; + return; + end + + % Compute biquad coefficients for lowpass filter + resonance = max(0.0, resonance); % can't go negative + g = 10.0^(0.05 * resonance); + d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); + + theta = pi * cutoff; + sn = 0.5 * d * sin(theta); + beta = 0.5 * (1 - sn) / (1 + sn); + gamma = (0.5 + beta) * cos(theta); + alpha = 0.25 * (0.5 + beta - gamma); + + b0 = 2 * alpha; + b1 = 2 * 2 * alpha; + b2 = 2 * alpha; + a1 = 2 * -gamma; + a2 = 2 * beta; + + b = [b0, b1, b2]; + a = [1.0, a1, a2]; +end diff --git a/src/audio/crossover/tune/sof_crossover_generate_config.m b/src/audio/crossover/tune/sof_crossover_generate_config.m new file mode 100644 index 000000000000..bfb60fa795f0 --- /dev/null +++ b/src/audio/crossover/tune/sof_crossover_generate_config.m @@ -0,0 +1,20 @@ +function config = sof_crossover_generate_config(crossover_bqs, num_sinks, assign_sinks); + +config.num_sinks = num_sinks; +config.assign_sinks = assign_sinks; +% Interleave the coefficients for the low and high pass filters +% For 2 way crossover we have 1 pair of LR4s. +% For 3,4 way crossover we have 3 pair of LR4s. +if num_sinks == 2 + n = 1; +else + n = 3; +end +j = 1; +k = 1; +for i = 1:n + config.all_coef(k:k+6) = crossover_bqs.lp_coef(j:j+6); k = k+7; + config.all_coef(k:k+6) = crossover_bqs.hp_coef(j:j+6); k = k+7; + j = j+7; +end +end diff --git a/src/audio/crossover/tune/sof_crossover_paths.m b/src/audio/crossover/tune/sof_crossover_paths.m new file mode 100644 index 000000000000..eba41c93768f --- /dev/null +++ b/src/audio/crossover/tune/sof_crossover_paths.m @@ -0,0 +1,21 @@ +function sof_crossover_paths(enable) + +% sof_crossover_paths(enable) +% enable - set to true to enable needed search path +% set to false to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + + common = '../../../../tools/tune/common'; + eq = '../../eq_iir/tune'; + if enable + addpath(common); + addpath(eq); + else + rmpath(common); + rmpath(eq); + end +end diff --git a/src/audio/crossover/tune/sof_crossover_plot_freq.m b/src/audio/crossover/tune/sof_crossover_plot_freq.m new file mode 100644 index 000000000000..0d1b242baea2 --- /dev/null +++ b/src/audio/crossover/tune/sof_crossover_plot_freq.m @@ -0,0 +1,113 @@ +function sof_crossover_plot_freq(lp, hp, fs, num_sinks); +% Plot the transfer function of each sink. We need to reconstruct a filter +% that represents the path the samples go through for each sinks. +% Example 4-way crossover: +% +% o---- LR4 LO-PASS --> y1(n) +% | +% o--- LR4 LO-PASS --o +% | | +% | o--- LR4 HI-PASS --> y2(n) +% x(n) --- o +% | o--- LR4 LO-PASS --> y3(n) +% | | +% o--- LR4 HI-PASS --o +% | +% o--- LR4 HI-PASS --> y4(n) +% +% Then to plot the transferfn for y1 we would create a filter such as: +% x(n) ---> LR4 LO-PASS --> LR4 LO-PASS --> y1(n) + +figure; + +f = linspace(1, fs/2, 500); + +if num_sinks == 2 + h1 = cascade_bqs_fr(f, fs, lp(1), lp(1)); + h2 = cascade_bqs_fr(f, fs, hp(1), hp(1)); + + subplot(2 ,1, 2) + freqz_plot(f, h1) + subplot(2, 1, 1) + plot_mag_resp(f, h1, h2) +end + +if num_sinks == 3 + % First LR4 Low Pass Filters + h1 = cascade_bqs_fr(f, fs, lp(1), lp(1)); + % Second LR4 Filters + tmp = cascade_bqs_fr(f, fs, lp(2), lp(2)); + tmp2 = cascade_bqs_fr(f, fs, hp(2), hp(2)); + % Merge the second LR4 Filters + tmp = tmp + tmp2; + % Cascade the First LR4 and the result of the previous merge + h1 = h1.*tmp; + + h2 = cascade_bqs_fr(f, fs, hp(1), hp(1), lp(3), lp(3)); + h3 = cascade_bqs_fr(f, fs, hp(1), hp(1), hp(3), hp(3)); + + subplot(2, 1, 2) + plot_phase_resp(f, h1, h2, h3) + subplot(2, 1, 1) + plot_mag_resp(f, h1, h2, h3) +end + +if num_sinks == 4 + h1 = cascade_bqs_fr(f, fs, lp(2), lp(2), lp(1), lp(1)); + h2 = cascade_bqs_fr(f, fs, lp(2), lp(2), hp(1), hp(1)); + h3 = cascade_bqs_fr(f, fs, hp(2), hp(2), lp(3), lp(3)); + h4 = cascade_bqs_fr(f, fs, hp(2), hp(2), hp(3), hp(3)); + + subplot(2, 1, 2) + plot_phase_resp(f, h1, h2, h3, h4) + subplot(2, 1, 1) + plot_mag_resp(f, h1, h2, h3, h4) +end +end + +function [h12, w] = cascade_bqs_fr(f, fs, varargin) +bq1 = varargin{1}; +bq2 = varargin{2}; +[h1, w1] = freqz(bq1.b, bq1.a, f, fs); +[h2, w2] = freqz(bq2.b, bq2.a, f, fs); +h12 = h1.*h2; +for i=3:length(varargin) + bq = varargin{i}; + [h1, w] = freqz(bq.b, bq.a, f, fs); + h12 = h12.*h1; +end +end + +function plot_phase_resp(f,varargin) +n = length(varargin); +labels = cellstr(n); +hold on +grid on +for i=1:n + h = varargin{i}; + semilogx(f, unwrap(arg(h)) * 180 / pi) + labels(i) = sprintf("out%d", i); +end +legend(labels, 'Location', 'NorthEast') +xlabel('Frequency (Hz)'); +ylabel('Phase Shift (degrees)'); +tstr = "Crossover Filter Phase Response"; +title(tstr); +end + +function plot_mag_resp(f,varargin) +n = length(varargin); +labels = cellstr(n); +hold on +grid on +for i=1:n + h = varargin{i}; + semilogx(f,20*log10(h)) + labels(i) = sprintf("out%d", i); +end +legend(labels, 'Location', 'NorthEast') +xlabel('Frequency (Hz)'); +ylabel('Magnitude (dB)'); +tstr = "Crossover Filter Magnitude Response"; +title(tstr); +end diff --git a/src/audio/crossover/tune/sof_example_crossover.m b/src/audio/crossover/tune/sof_example_crossover.m new file mode 100644 index 000000000000..6d642122aab6 --- /dev/null +++ b/src/audio/crossover/tune/sof_example_crossover.m @@ -0,0 +1,123 @@ +function sof_example_crossover() + +% Sampling Frequency and Frequency cut-offs for crossover +cr.fs = 48e3; +cr.fc_low = 200; +cr.fc_med = 1000; +cr.fc_high = 3000; + +% 2 way crossover, pipeline IDs of sinks are 1 and 2 (IPC3) +% and component output pins 0 and 1 (IPC4) +cr.num_sinks = 2; +cr.sinks = [1 2]; +export_crossover(cr); +cr.sinks = [0 1]; +export_crossover(cr); + +% 3 way crossover, pipeline IDs of sinks are 1 - 3 +cr.num_sinks = 3; +cr.sinks = [1 2 3]; +export_crossover(cr); +cr.sinks = [0 1 2]; +export_crossover(cr); + +% 4 way crossover, pipeline IDs of sinks are 1 - 4 +cr.num_sinks = 4; +cr.sinks = [1 2 3 4]; +export_crossover(cr); +cr.sinks = [0 1 2 3]; +export_crossover(cr); + +end + +function export_crossover(cr) + +sof_crossover_paths(true); + +endian = "little"; +sof_tools = '../../../../tools'; +tpath1 = fullfile(sof_tools, 'topology/topology1/m4/crossover'); +tpath2 = fullfile(sof_tools, 'topology/topology2/include/components/crossover'); +ctlpath3 = fullfile(sof_tools, 'ctl/ipc3/crossover'); +ctlpath4 = fullfile(sof_tools, 'ctl/ipc4/crossover'); + +str_way = sprintf('%dway', cr.num_sinks); +str_freq = get_str_freq(cr); +str_pid = get_str_pid(cr); + +% Set the parameters here +tplg1_fn = sprintf('%s/coef_%s_%s_%s.m4', tpath1, str_way, str_freq, str_pid); % Control Bytes File +tplg2_fn = sprintf('%s/coef_%s_%s_%s.conf', tpath2, str_way, str_freq, str_pid); +% Use those files with sof-ctl to update the component's configuration +blob3_fn = sprintf('%s/coef_%dway.bin', ctlpath3, cr.num_sinks); % Blob binary file +alsa3_fn = sprintf('%s/coef_%dway.txt', ctlpath3, cr.num_sinks); % ALSA CSV format file +blob4_fn = sprintf('%s/coef_%dway.bin', ctlpath4, cr.num_sinks); % Blob binary file +alsa4_fn = sprintf('%s/coef_%dway.txt', ctlpath4, cr.num_sinks); % ALSA CSV format file + +% This array is an example on how to assign a buffer from pipeline 1 to output 0, +% buffer from pipeline 2 to output 1, etc... +% Refer to sof/src/include/user/crossover.h for more information on assigning +% buffers to outputs. +assign_sinks = zeros(1, 4); +assign_sinks(1:cr.num_sinks) = cr.sinks; + +% Generate zeros, poles and gain for crossover with the given frequencies +switch cr.num_sinks + case 2 + crossover = sof_crossover_gen_coefs(cr.fs, cr.fc_low); % 2 way crossover + case 3 + crossover = sof_crossover_gen_coefs(cr.fs, cr.fc_low, cr.fc_med); % 3 way crossover + case 4 + crossover = sof_crossover_gen_coefs(cr.fs, cr.fc_low, cr.fc_med, cr.fc_high); % 4 way crossover + otherwise + error('Illegal number of sinks %d\n', num_sinks); +end + +% Convert the [a,b] coefficients to values usable with SOF +crossover_bqs = sof_crossover_coef_quant(crossover.lp, crossover.hp); + +% Convert coefficients to sof_crossover_config struct +config = sof_crossover_generate_config(crossover_bqs, cr.num_sinks, assign_sinks); + +% Convert struct to binary blob +blob8 = sof_crossover_build_blob(config, endian, 3); +blob8_ipc4 = sof_crossover_build_blob(config, endian, 4); + +% Generate output files + +sof_tplg_write(tplg1_fn, blob8, "CROSSOVER"); +sof_tplg2_write(tplg2_fn, blob8_ipc4, "crossover_config", 'Exported Control Bytes'); +sof_ucm_blob_write(blob3_fn, blob8); +sof_ucm_blob_write(blob4_fn, blob8_ipc4); +sof_alsactl_write(alsa3_fn, blob8); +sof_alsactl_write(alsa4_fn, blob8_ipc4); + +% Plot Magnitude and Phase Response of each sink +sof_crossover_plot_freq(crossover.lp, crossover.hp, cr.fs, cr.num_sinks); + +sof_crossover_paths(false); +end + +% Frequencies part for filename +function str = get_str_freq(cr) + +switch cr.num_sinks + case 2 + str = sprintf('%d_%d', cr.fs, cr.fc_low); + case 3 + str = sprintf('%d_%d_%d', cr.fs, cr.fc_low, cr.fc_med); + case 4 + str = sprintf('%d_%d_%d_%d', cr.fs, cr.fc_low, cr.fc_med, cr.fc_high); +end + +end + +% Pipeline IDs part of filename +function str = get_str_pid(cr) + +str = sprintf('%d', cr.sinks(1)); +for i = 2:cr.num_sinks + str = sprintf('%s_%d', str, cr.sinks(i)); +end + +end diff --git a/src/audio/dai-legacy.c b/src/audio/dai-legacy.c new file mode 100644 index 000000000000..655fa94afb86 --- /dev/null +++ b/src/audio/dai-legacy.c @@ -0,0 +1,1142 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/msg.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/dai.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include "copier/dai_copier.h" + +static const struct comp_driver comp_dai; + +LOG_MODULE_REGISTER(dai_comp, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dai); + +#if CONFIG_COMP_DAI_GROUP + +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) +{ + struct comp_dev *dev = arg; + struct dai_data *dd = comp_get_drvdata(dev); + struct dai_group *group = dd->group; + + /* Atomic context set by the last DAI to receive trigger command */ + group->trigger_ret = dai_comp_trigger_internal(dd, dev, group->trigger_cmd); +} + +/* Assign DAI to a group */ +int dai_assign_group(struct dai_data *dd, struct comp_dev *dev, uint32_t group_id) +{ + if (dd->group) { + if (dd->group->group_id != group_id) { + comp_err(dev, "DAI already in group %d, requested %d", + dd->group->group_id, group_id); + return -EINVAL; + } + + /* No need to re-assign to the same group, do nothing */ + return 0; + } + + dd->group = dai_group_get(group_id, DAI_CREAT); + if (!dd->group) { + comp_err(dev, "failed to assign group %d", + group_id); + return -EINVAL; + } + + comp_dbg(dev, "group %d num %d", + group_id, dd->group->num_dais); + + /* Register for the atomic trigger event */ + notifier_register(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER, + dai_atomic_trigger, 0); + + return 0; +} +#endif +/* this is called by DMA driver every time descriptor has completed */ +static void dai_dma_cb(void *arg, enum notify_id type, void *data) +{ + struct dma_cb_data *next = data; + struct comp_dev *dev = arg; + struct dai_data *dd = comp_get_drvdata(dev); + uint32_t bytes = next->elem.size; + int ret; + + comp_dbg(dev, "entry"); + + next->status = SOF_DMA_CB_STATUS_RELOAD; + + /* stop dma copy for pause/stop/xrun */ + if (dev->state != COMP_STATE_ACTIVE || dd->xrun) { + /* stop the DAI */ + dai_trigger(dd->dai, COMP_TRIGGER_STOP, dev->direction); + + /* tell DMA not to reload */ + next->status = SOF_DMA_CB_STATUS_END; + } + + /* 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(dd->dma_buffer); + + return; + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer, + dd->process, bytes, DUMMY_CHMAP); + } else { + ret = dma_buffer_copy_from(dd->dma_buffer, dd->local_buffer, + dd->process, bytes, DUMMY_CHMAP); + } + + /* assert dma_buffer_copy succeed */ + if (ret < 0) { + struct comp_buffer *source_c, *sink_c; + + source_c = dev->direction == SOF_IPC_STREAM_PLAYBACK ? + dd->local_buffer : dd->dma_buffer; + sink_c = dev->direction == SOF_IPC_STREAM_PLAYBACK ? + dd->dma_buffer : dd->local_buffer; + comp_err(dev, "dma buffer copy failed, dir %d bytes %d avail %d free %d", + dev->direction, bytes, + audio_stream_get_avail_samples(&source_c->stream) * + audio_stream_frame_bytes(&source_c->stream), + audio_stream_get_free_samples(&sink_c->stream) * + audio_stream_frame_bytes(&sink_c->stream)); + } else { + /* update host position (in bytes offset) for drivers */ + dd->total_data_processed += bytes; + } +} + +int dai_common_new(struct dai_data *dd, struct comp_dev *dev, const struct ipc_config_dai *dai) +{ + uint32_t dir, caps, dma_dev; + + dd->dai = dai_get(dai->type, dai->dai_index, DAI_CREAT); + if (!dd->dai) { + comp_cl_err(&comp_dai, "dai_get() failed to create DAI."); + return -ENODEV; + } + dd->dai->dd = dd; + dd->ipc_config = *dai; + + /* request GP LP DMA with shared access privilege */ + dir = dai->direction == SOF_IPC_STREAM_PLAYBACK ? + DMA_DIR_MEM_TO_DEV : DMA_DIR_DEV_TO_MEM; + + caps = dai_get_info(dd->dai, DAI_INFO_DMA_CAPS); + dma_dev = dai_get_info(dd->dai, DAI_INFO_DMA_DEV); + + dd->dma = dma_get(dir, caps, dma_dev, DMA_ACCESS_SHARED); + if (!dd->dma) { + comp_cl_err(&comp_dai, "dma_get() failed to get shared access to DMA."); + 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_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*dd)); + if (!dd) { + comp_free_device(dev); + return NULL; + } + + comp_set_drvdata(dev, dd); + + ret = dai_common_new(dd, dev, dai); + if (ret < 0) + goto error; + + dev->state = COMP_STATE_READY; + return dev; + +error: + rfree(dd); + comp_free_device(dev); + return NULL; +} + +void dai_common_free(struct dai_data *dd) +{ + if (dd->group) + dai_group_put(dd->group); + + if (dd->chan) { + dd->chan->dev_data = NULL; + dma_channel_put_legacy(dd->chan); + } + + dma_put(dd->dma); + + 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_common_free(dd); + + rfree(dd); + comp_free_device(dev); +} + +int dai_common_get_hw_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir) +{ + int ret; + + comp_dbg(dev, "dai_hw_params()"); + + /* fetching hw dai stream params */ + ret = dai_get_hw_params(dd->dai, params, dir); + if (ret < 0) { + comp_err(dev, "dai_get_hw_params failed ret %d", + ret); + return ret; + } + + /* dai_comp_get_hw_params() function fetches hardware dai parameters, + * which then are propagating back through the pipeline, so that any + * component can convert specific stream parameter. Here, we overwrite + * frame_fmt hardware parameter as DAI component is able to convert + * stream with different frame_fmt's (using pcm converter) + */ + params->frame_fmt = dev->ipc_config.frame_fmt; + + 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_common_get_hw_params(dd, dev, params, dir); +} + +static int dai_comp_hw_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct dai_data *dd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "entry"); + + /* configure hw dai stream params */ + ret = dai_hw_params(dd->dai, params); + if (ret < 0) { + comp_err(dev, "dai_hw_params failed ret %d", + ret); + return ret; + } + + return 0; +} + +static int dai_verify_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct sof_ipc_stream_params hw_params; + int ret; + + ret = dai_common_get_hw_params(dd, dev, &hw_params, params->direction); + if (ret < 0) + return ret; + + /* checks whether pcm parameters match hardware DAI parameter set + * during dai_set_config(). If hardware parameter is equal to 0, it + * means that it can vary, so any value is acceptable. We do not check + * format parameter, because DAI is able to change format using + * pcm_converter functions. + */ + if (hw_params.rate && hw_params.rate != params->rate) { + comp_err(dev, "pcm rate parameter %d does not match hardware rate %d", + params->rate, hw_params.rate); + return -EINVAL; + } + + if (hw_params.channels && hw_params.channels != params->channels) { + comp_err(dev, "pcm channels parameter %d does not match hardware channels %d", + params->channels, hw_params.channels); + return -EINVAL; + } + + /* set component period frames */ + component_set_nearest_period_frames(dev, params->rate); + + return 0; +} + +/* set component audio SSP and DMA configuration */ +static int dai_playback_params(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; + uint32_t local_fmt = audio_stream_get_frm_fmt(&dd->local_buffer->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dd->dma_buffer->stream); + uint32_t fifo; + int err = 0; + + /* set processing function */ + 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); + return -EINVAL; + } + + /* set up DMA configuration */ + config->direction = DMA_DIR_MEM_TO_DEV; + config->src_width = get_sample_bytes(dma_fmt); + config->dest_width = config->src_width; + config->cyclic = 1; + config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); + config->dest_dev = dai_get_handshake(dd->dai, dev->direction, + dd->stream_id); + config->is_scheduling_source = comp_is_scheduling_source(dev); + config->period = dev->pipeline->period; + + comp_info(dev, "dest_dev = %d stream_id = %d src_width = %d dest_width = %d", + config->dest_dev, dd->stream_id, + config->src_width, config->dest_width); + + if (!config->elem_array.elems) { + fifo = dai_get_fifo(dd->dai, dev->direction, + dd->stream_id); + + comp_info(dev, "fifo 0x%x", fifo); + + err = dma_sg_alloc(NULL, &config->elem_array, SOF_MEM_FLAG_USER, + config->direction, + period_count, + period_bytes, + (uintptr_t)(audio_stream_get_addr(&dd->dma_buffer->stream)), + fifo); + if (err < 0) + comp_err(dev, "dma_sg_alloc() for period_count %d period_bytes %d failed with err = %d", + period_count, period_bytes, err); + } + + return err; +} + +static int dai_capture_params(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; + uint32_t local_fmt = audio_stream_get_frm_fmt(&dd->local_buffer->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dd->dma_buffer->stream); + uint32_t fifo; + int err = 0; + + /* set processing function */ + dd->process = pcm_get_conversion_function(dma_fmt, local_fmt); + + if (!dd->process) { + comp_err(dev, "converter function NULL: local fmt %d dma fmt %d\n", + local_fmt, dma_fmt); + return -EINVAL; + } + + /* set up DMA configuration */ + config->direction = DMA_DIR_DEV_TO_MEM; + config->cyclic = 1; + config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); + config->src_dev = dai_get_handshake(dd->dai, dev->direction, + dd->stream_id); + config->is_scheduling_source = comp_is_scheduling_source(dev); + config->period = dev->pipeline->period; + + /* TODO: Make this code platform-specific or move it driver callback */ + if (dai_get_info(dd->dai, DAI_INFO_TYPE) == SOF_DAI_INTEL_DMIC) { + /* For DMIC the DMA src and dest widths should always be 4 bytes + * due to 32 bit FIFO packer. Setting width to 2 bytes for + * 16 bit format would result in recording at double rate. + */ + config->src_width = 4; + config->dest_width = 4; + } else { + config->src_width = get_sample_bytes(dma_fmt); + config->dest_width = config->src_width; + } + + comp_info(dev, "src_dev = %d stream_id = %d src_width = %d dest_width = %d", + config->src_dev, dd->stream_id, + config->src_width, config->dest_width); + + if (!config->elem_array.elems) { + fifo = dai_get_fifo(dd->dai, dev->direction, + dd->stream_id); + + comp_info(dev, "fifo 0x%x", fifo); + + err = dma_sg_alloc(NULL, &config->elem_array, SOF_MEM_FLAG_USER, + config->direction, + period_count, + period_bytes, + (uintptr_t)(audio_stream_get_addr(&dd->dma_buffer->stream)), + fifo); + if (err < 0) + comp_err(dev, "dma_sg_alloc() for period_count %d period_bytes %d failed with err = %d", + period_count, period_bytes, err); + } + + return err; +} + +int dai_common_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct sof_ipc_stream_params hw_params = *params; + uint32_t frame_size; + uint32_t period_count; + uint32_t period_bytes; + uint32_t buffer_size; + uint32_t addr_align; + uint32_t align; + int err; + + comp_dbg(dev, "dai_params()"); + + /* configure dai_data first */ + err = ipc_dai_data_config(dd, dev); + if (err < 0) + return err; + + err = dai_verify_params(dd, dev, params); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return -EINVAL; + } + + /* params verification passed, so now configure hw dai stream params */ + err = dai_comp_hw_params(dev, params); + if (err < 0) { + comp_err(dev, "dai_comp_hw_params failed err %d", err); + return err; + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dd->local_buffer = comp_dev_get_first_data_producer(dev); + else + dd->local_buffer = comp_dev_get_first_data_consumer(dev); + + /* check if already configured */ + if (dev->state == COMP_STATE_PREPARE) { + comp_info(dev, "dai_params() component has been already configured."); + return 0; + } + + /* can set params on only init state */ + if (dev->state != COMP_STATE_READY) { + comp_err(dev, "Component is in state %d, expected COMP_STATE_READY.", + dev->state); + return -EINVAL; + } + + err = dma_get_attribute_legacy(dd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (err < 0) { + comp_err(dev, "could not get dma buffer address alignment, err = %d", + err); + return err; + } + + err = dma_get_attribute_legacy(dd->dma, DMA_ATTR_BUFFER_ALIGNMENT, &align); + if (err < 0 || !align) { + comp_err(dev, "could not get valid dma buffer alignment, err = %d, align = %u", + err, align); + return -EINVAL; + } + + err = dma_get_attribute_legacy(dd->dma, DMA_ATTR_BUFFER_PERIOD_COUNT, + &period_count); + if (err < 0 || !period_count) { + comp_err(dev, "could not get valid dma buffer period count, err = %d, period_count = %u", + err, period_count); + return -EINVAL; + } + + /* calculate frame size */ + frame_size = get_frame_bytes(dev->ipc_config.frame_fmt, + audio_stream_get_channels(&dd->local_buffer->stream)); + + /* calculate period size */ + period_bytes = dev->frames * frame_size; + if (!period_bytes) { + comp_err(dev, "invalid period_bytes."); + return -EINVAL; + } + + dd->period_bytes = period_bytes; + + /* calculate DMA buffer size */ + period_count = MAX(period_count, + SOF_DIV_ROUND_UP(dd->ipc_config.dma_buffer_size, period_bytes)); + buffer_size = ALIGN_UP(period_count * period_bytes, align); + + /* alloc DMA buffer or change its size if exists */ + if (dd->dma_buffer) { + err = buffer_set_size(dd->dma_buffer, buffer_size, addr_align); + + if (err < 0) { + comp_err(dev, "buffer_set_size() failed, buffer_size = %u", + buffer_size); + return err; + } + } else { + dd->dma_buffer = buffer_alloc(NULL, buffer_size, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + addr_align, BUFFER_USAGE_NOT_SHARED); + if (!dd->dma_buffer) { + comp_err(dev, "failed to alloc dma buffer"); + return -ENOMEM; + } + + /* + * dma_buffer should reffer to hardware dai parameters. + * Here, we overwrite frame_fmt hardware parameter as DAI + * component is able to convert stream with different + * frame_fmt's (using pcm converter). + */ + hw_params.frame_fmt = dev->ipc_config.frame_fmt; + buffer_set_params(dd->dma_buffer, &hw_params, + BUFFER_UPDATE_FORCE); + } + + return dev->direction == SOF_IPC_STREAM_PLAYBACK ? + dai_playback_params(dev, period_bytes, period_count) : + dai_capture_params(dev, period_bytes, period_count); +} + +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, "entry"); + + return dai_common_params(dd, dev, params); +} + +int dai_common_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, "Component is in active state."); + return 0; + } + + if (!dd->dai_spec_config) { + comp_err(dev, "dai specific config is not set yet!"); + return -EINVAL; + } + + if (dd->chan) { + comp_info(dev, "dma channel index %d already configured", + dd->chan->index); + return 0; + } + + channel = dai_config_dma_channel(dd, dev, dd->dai_spec_config); + comp_info(dev, "channel = %d", channel); + + /* do nothing for asking for channel free, for compatibility. */ + if (channel == DMA_CHAN_INVALID) { + comp_err(dev, "dai_config is not set yet!"); + return -EINVAL; + } + + /* allocate DMA channel */ + dd->chan = dma_channel_get_legacy(dd->dma, channel); + if (!dd->chan) { + comp_err(dev, "dma_channel_get() failed"); + dd->chan = NULL; + return -EIO; + } + + dd->chan->dev_data = dd; + + comp_info(dev, "new configured dma channel index %d", + dd->chan->index); + + /* setup callback */ + notifier_register(dev, dd->chan, NOTIFIER_ID_DMA_COPY, + dai_dma_cb, 0); + + return 0; +} + +int dai_common_prepare(struct dai_data *dd, struct comp_dev *dev) +{ + int ret; + + dd->total_data_processed = 0; + + if (!dd->chan) { + comp_err(dev, "Missing dd->chan."); + comp_set_state(dev, COMP_TRIGGER_RESET); + return -EINVAL; + } + + if (!dd->config.elem_array.elems) { + comp_err(dev, "Missing dd->config.elem_array.elems."); + comp_set_state(dev, COMP_TRIGGER_RESET); + return -EINVAL; + } + + /* clear dma buffer to avoid pop noise */ + buffer_zero(dd->dma_buffer); + + /* dma reconfig not required if XRUN handling */ + if (dd->xrun) { + /* after prepare, we have recovered from xrun */ + dd->xrun = 0; + return 0; + } + + ret = dma_set_config_legacy(dd->chan, &dd->config); + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + return ret; +} + +static int dai_prepare(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + int ret; + + comp_info(dev, "entry"); + + ret = dai_common_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_common_prepare(dd, dev); +} + +void dai_common_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(dd, dev); + + dma_sg_free(NULL, &config->elem_array); + + if (dd->dma_buffer) { + buffer_free(dd->dma_buffer); + dd->dma_buffer = NULL; + } + + dd->wallclock = 0; + dd->total_data_processed = 0; + dd->xrun = 0; +} + +static int dai_reset(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + + dai_common_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 dai_data *dd, struct comp_dev *dev, int cmd) +{ + int ret; + + comp_dbg(dev, "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, "START"); + + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun == 0) { + ret = dma_start_legacy(dd->chan); + if (ret < 0) + return ret; + /* start the DAI */ + dai_trigger(dd->dai, cmd, dev->direction); + } else { + dd->xrun = 0; + } + + platform_dai_wallclock(dev, &dd->wallclock); + break; + case COMP_TRIGGER_RELEASE: + /* before release, we clear the buffer data to 0s, + * then there is no history data sent out after release. + * this is only supported at capture mode. + */ + if (dev->direction == SOF_IPC_STREAM_CAPTURE) { + buffer_zero(dd->dma_buffer); + } + + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun == 0) { + /* recover valid start position */ + ret = dma_release_legacy(dd->chan); + if (ret < 0) + return ret; + + /* start the DAI */ + dai_trigger(dd->dai, cmd, dev->direction); + ret = dma_start_legacy(dd->chan); + if (ret < 0) + return ret; + } else { + dd->xrun = 0; + } + + platform_dai_wallclock(dev, &dd->wallclock); + break; + case COMP_TRIGGER_XRUN: + comp_info(dev, "XRUN"); + dd->xrun = 1; + + COMPILER_FALLTHROUGH; + case COMP_TRIGGER_STOP: + comp_dbg(dev, "STOP"); +/* + * Some platforms cannot just simple disable + * DMA channel during the transfer, + * because it will hang the whole DMA controller. + * Therefore, stop the DMA first and let the DAI + * drain the FIFO in order to stop the channel + * as soon as possible. + */ +#if CONFIG_DMA_SUSPEND_DRAIN + ret = dma_stop_legacy(dd->chan); + dai_trigger(dd->dai, cmd, dev->direction); +#else + dai_trigger(dd->dai, cmd, dev->direction); + ret = dma_stop_legacy(dd->chan); +#endif + break; + case COMP_TRIGGER_PAUSE: + comp_dbg(dev, "PAUSE"); + ret = dma_pause_legacy(dd->chan); + dai_trigger(dd->dai, cmd, dev->direction); + break; + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun) + dd->xrun = 0; + else + dai_trigger(dd->dai, cmd, dev->direction); + break; + } + + return ret; +} + +int dai_common_trigger(struct dai_data *dd, struct comp_dev *dev, int cmd) +{ + 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, "non-atomic trigger"); + return dai_comp_trigger_internal(dd, dev, cmd); + } + + /* DAI is grouped, so only trigger when the entire group is ready */ + + if (!group->trigger_counter) { + /* First DAI to receive the trigger command, + * prepare for atomic trigger + */ + comp_dbg(dev, "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, "already processing atomic trigger"); + ret = -EAGAIN; + } else { + /* Count down the number of remaining DAIs required + * to receive the trigger command before atomic trigger + * takes place + */ + group->trigger_counter--; + comp_dbg(dev, "trigger counter %d, group %d", + group->trigger_counter, group->group_id); + + if (!group->trigger_counter) { + /* The counter has reached 0, which means + * all DAIs have received the same trigger command + * and we may begin the actual trigger process + * synchronously. + */ + + irq_local_disable(irq_flags); + notifier_event(group, NOTIFIER_ID_DAI_TRIGGER, + BIT(cpu_get_id()), NULL, 0); + irq_local_enable(irq_flags); + + /* return error of last trigger */ + ret = group->trigger_ret; + } + } + + return ret; +} + +static int dai_comp_trigger(struct comp_dev *dev, int cmd) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_common_trigger(dd, dev, cmd); +} + +/* report xrun occurrence */ +static void dai_report_xrun(struct comp_dev *dev, uint32_t bytes) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + comp_err(dev, "underrun due to no data available"); + comp_underrun(dev, dd->local_buffer, bytes); + } else { + comp_err(dev, "overrun due to no space available"); + comp_overrun(dev, dd->local_buffer, bytes); + } +} + +/* copy and process stream data from source to sink buffers */ +int dai_common_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter) +{ + uint32_t dma_fmt; + uint32_t sampling; + uint32_t avail_bytes = 0; + uint32_t free_bytes = 0; + uint32_t copy_bytes = 0; + uint32_t src_samples; + uint32_t sink_samples; + uint32_t samples; + int ret; + + /* get data sizes from DMA */ + ret = dma_get_data_size_legacy(dd->chan, &avail_bytes, &free_bytes); + if (ret < 0) { + dai_report_xrun(dev, 0); + return ret; + } + + dma_fmt = audio_stream_get_frm_fmt(&dd->dma_buffer->stream); + sampling = get_sample_bytes(dma_fmt); + + /* calculate minimum size to copy */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + src_samples = audio_stream_get_avail_samples(&dd->local_buffer->stream); + sink_samples = free_bytes / sampling; + samples = MIN(src_samples, sink_samples); + } else { + src_samples = avail_bytes / sampling; + sink_samples = audio_stream_get_free_samples(&dd->local_buffer->stream); + samples = MIN(src_samples, sink_samples); + } + + /* limit bytes per copy to one period for the whole pipeline + * in order to avoid high load spike + */ + samples = MIN(samples, dd->period_bytes / sampling); + + copy_bytes = samples * sampling; + + comp_dbg(dev, "dir: %d copy_bytes= 0x%x, frames= %d", + dev->direction, copy_bytes, + samples / audio_stream_get_channels(&dd->local_buffer->stream)); + + /* Check possibility of glitch occurrence */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK && + copy_bytes + avail_bytes < dd->period_bytes) + comp_warn(dev, "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, "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, "nothing to copy"); + return 0; + } + + if (dd->dai->drv->ops.copy) + dd->dai->drv->ops.copy(dd->dai); + + ret = dma_copy_legacy(dd->chan, copy_bytes, 0); + if (ret < 0) { + dai_report_xrun(dev, copy_bytes); + return ret; + } + + 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, "entry"); + + /* + * 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_common_copy(dd, dev, NULL); +} + +/** + * \brief Get DAI parameters and configure timestamping + * \param[in, out] dev DAI device. + * \return Error code. + * + * This function retrieves various DAI parameters such as type, direction, index, and DMA + * controller information those are needed when configuring HW timestamping. Note that + * DAI must be prepared before this function is used (for DMA information). If not, an error + * is returned. + */ +int dai_common_ts_config_op(struct dai_data *dd, struct comp_dev *dev) +{ + struct timestamp_cfg *cfg = &dd->ts_config; + struct ipc_config_dai *dai = &dd->ipc_config; + + comp_dbg(dev, "dai_ts_config()"); + if (!dd->chan) { + comp_err(dev, "dai_ts_config(), No DMA channel information"); + return -EINVAL; + } + + cfg->type = dd->dai->drv->type; + cfg->direction = dai->direction; + cfg->index = dd->dai->index; + cfg->dma_id = dd->dma->plat_data.id; + cfg->dma_chan_index = dd->chan->index; + cfg->dma_chan_count = dd->dma->plat_data.channels; + if (!dd->dai->drv->ts_ops.ts_config) + return -ENXIO; + + return dd->dai->drv->ts_ops.ts_config(dd->dai, cfg); +} + +static int dai_ts_config(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_common_ts_config_op(dd, dev); +} + +int dai_common_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_start(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + return dai_common_ts_start(dd, dev); +} + +int dai_common_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_stop(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + return dai_common_ts_stop(dd, dev); +} + +int dai_common_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, "entry"); + + return dai_common_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); + uint64_t ret = 0; + bool source = dev->direction == SOF_IPC_STREAM_CAPTURE; + + /* Return value only if direction and stream number match. + * The dai supports only one stream. + */ + if (stream_no == 0 && source == input) + ret = dd->total_data_processed; + + return ret; +} + +DECLARE_TR_CTX(dai_comp_tr, SOF_UUID(dai_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_dai = { + .type = SOF_COMP_DAI, + .uid = SOF_RT_UUID(dai_uuid), + .tctx = &dai_comp_tr, + .ops = { + .create = dai_new, + .free = dai_free, + .params = dai_params, + .dai_get_hw_params = dai_comp_get_hw_params, + .trigger = dai_comp_trigger, + .copy = dai_copy, + .prepare = dai_prepare, + .reset = dai_reset, + .dai_config = dai_config, + .position = dai_position, + .dai_ts_config = dai_ts_config, + .dai_ts_start = dai_ts_start, + .dai_ts_stop = dai_ts_stop, + .dai_ts_get = dai_ts_get, + .get_total_data_processed = dai_get_processed_data, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_dai_info = { + .drv = &comp_dai, +}; + +UT_STATIC void sys_comp_dai_init(void) +{ + comp_register(platform_shared_get(&comp_dai_info, + sizeof(comp_dai_info))); +} + +DECLARE_MODULE(sys_comp_dai_init); +SOF_MODULE_INIT(dai, sys_comp_dai_init); diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c new file mode 100644 index 000000000000..454132de150e --- /dev/null +++ b/src/audio/dai-zephyr.c @@ -0,0 +1,2039 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <module/module/base.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/lib/dma.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/dai.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE +#include <ipc4/notification.h> +#endif + +#include "copier/copier.h" +#include "copier/dai_copier.h" +#include "copier/copier_gain.h" + +#include <zephyr/device.h> +#include <zephyr/drivers/dai.h> + +#include <sof/debug/telemetry/performance_monitor.h> + +/* note: if this macro is not defined + * then that means the HOST and the DSP + * have the same view of the address space. + */ +#ifndef local_to_host +#define local_to_host(addr) (addr) +#endif /* local_to_host */ + +static const struct comp_driver comp_dai; + +LOG_MODULE_REGISTER(dai_comp, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dai); + +#if CONFIG_COMP_DAI_GROUP + +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) +{ + struct comp_dev *dev = arg; + struct dai_data *dd = comp_get_drvdata(dev); + struct dai_group *group = dd->group; + + /* Atomic context set by the last DAI to receive trigger command */ + group->trigger_ret = dai_comp_trigger_internal(dd, dev, group->trigger_cmd); +} + +/* Assign DAI to a group */ +__cold int dai_assign_group(struct dai_data *dd, struct comp_dev *dev, uint32_t group_id) +{ + assert_can_be_cold(); + + if (dd->group) { + if (dd->group->group_id != group_id) { + comp_err(dev, "DAI already in group %d, requested %d", + dd->group->group_id, group_id); + return -EINVAL; + } + + /* No need to re-assign to the same group, do nothing */ + return 0; + } + + dd->group = dai_group_get(group_id, DAI_CREAT); + if (!dd->group) { + comp_err(dev, "failed to assign group %d", + group_id); + return -EINVAL; + } + + comp_dbg(dev, "group %d num %d", + group_id, dd->group->num_dais); + + /* Register for the atomic trigger event */ + notifier_register(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER, + dai_atomic_trigger, 0); + + return 0; +} +#endif + +static int dai_trigger_op(struct dai *dai, int cmd, int direction) +{ + const struct device *dev = dai->dev; + enum dai_trigger_cmd zephyr_cmd; + + switch (cmd) { + case COMP_TRIGGER_STOP: + zephyr_cmd = DAI_TRIGGER_STOP; + break; + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + zephyr_cmd = DAI_TRIGGER_START; + break; + case COMP_TRIGGER_PAUSE: + zephyr_cmd = DAI_TRIGGER_PAUSE; + break; + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + zephyr_cmd = DAI_TRIGGER_PRE_START; + break; + default: + return -EINVAL; + } + + return dai_trigger(dev, direction, zephyr_cmd); +} + +/* called from src/ipc/ipc3/handler.c and src/ipc/ipc4/dai.c */ +__cold int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config, size_t size) +{ + const struct device *dev = dai->dev; + const struct sof_ipc_dai_config *sof_cfg = spec_config; + struct dai_config cfg = {0}; + const void *cfg_params; + size_t dai_cfg_size = size; + bool is_blob; + + assert_can_be_cold(); + + cfg.dai_index = common_config->dai_index; + is_blob = common_config->is_config_blob; + cfg.format = common_config->format; + cfg.options = is_blob ? 0 : sof_cfg->flags; + cfg.rate = common_config->sampling_frequency; + + switch (common_config->type) { + 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); + /* Store tdm slot group index*/ + cfg.tdm_slot_group = common_config->dai_index & 0xF; + break; + case SOF_DAI_INTEL_ALH: + cfg.type = is_blob ? DAI_INTEL_ALH_NHLT : DAI_INTEL_ALH; + cfg_params = is_blob ? spec_config : &sof_cfg->alh; + break; + 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; + cfg_params = is_blob ? spec_config : &sof_cfg->hda; + break; + case SOF_DAI_IMX_SAI: + cfg.type = DAI_IMX_SAI; + cfg_params = &sof_cfg->sai; + break; + case SOF_DAI_IMX_ESAI: + cfg.type = DAI_IMX_ESAI; + cfg_params = &sof_cfg->esai; + break; + case SOF_DAI_IMX_MICFIL: + cfg.type = DAI_IMX_MICFIL; + cfg_params = &sof_cfg->micfil; + break; + case SOF_DAI_AMD_SDW: + cfg.type = DAI_AMD_SDW; + cfg_params = &sof_cfg->acpsdw; + break; + case SOF_DAI_INTEL_UAOL: + cfg.type = DAI_INTEL_UAOL; + cfg.channels = common_config->gtw_fmt->channels_count; + /* + * FIXME: The spec says HW expects container size here, not valid_bit_depth. + * However, tests fail if container size is used and work fine with + * valid_bit_depth. Needs investigation. Perhaps tests have a bug? + */ + cfg.word_size = common_config->gtw_fmt->valid_bit_depth; + cfg_params = spec_config; + dai_set_link_hda_config(&cfg.link_config, common_config, spec_config); + break; + default: + return -EINVAL; + } + + if (!is_blob) { + if (size < SOF_DAI_CONFIG_HW_SPEC_OFFSET) + return -EINVAL; + + dai_cfg_size -= SOF_DAI_CONFIG_HW_SPEC_OFFSET; + } + + return dai_config_set(dev, &cfg, cfg_params, dai_cfg_size); +} + +/* called from ipc/ipc3/dai.c */ +int dai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + k_spinlock_key_t key = k_spin_lock(&dai->lock); + const struct dai_properties *props = dai_get_properties(dai->dev, direction, + stream_id); + int hs_id = props->dma_hs_id; + + k_spin_unlock(&dai->lock, key); + + return hs_id; +} + +/* called from ipc/ipc3/dai.c and ipc/ipc4/dai.c */ +int dai_get_fifo_depth(struct dai *dai, int direction) +{ + const struct dai_properties *props; + k_spinlock_key_t key; + int fifo_depth; + + if (!dai) + return 0; + + key = k_spin_lock(&dai->lock); + props = dai_get_properties(dai->dev, direction, 0); + fifo_depth = props->fifo_depth; + k_spin_unlock(&dai->lock, key); + + return fifo_depth; +} + +int dai_get_stream_id(struct dai *dai, int direction) +{ + k_spinlock_key_t key = k_spin_lock(&dai->lock); + const struct dai_properties *props = dai_get_properties(dai->dev, direction, 0); + int stream_id = props->stream_id; + + k_spin_unlock(&dai->lock, key); + + return stream_id; +} + +static int dai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + k_spinlock_key_t key = k_spin_lock(&dai->lock); + const struct dai_properties *props = dai_get_properties(dai->dev, direction, + stream_id); + int fifo_address = props->fifo_address; + + k_spin_unlock(&dai->lock, key); + + return fifo_address; +} + +/* this is called by DMA driver every time descriptor has completed */ +static enum sof_dma_cb_status +dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, + pcm_converter_func *converter) +{ + enum sof_dma_cb_status dma_status = SOF_DMA_CB_STATUS_RELOAD; + int ret; + + comp_dbg(dev, "entry"); + + /* 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); + + /* tell DMA not to reload */ + dma_status = SOF_DMA_CB_STATUS_END; + } + + /* 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(dd->dma_buffer); + + return dma_status; + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { +#if CONFIG_IPC_MAJOR_4 + /* + * copy from local buffer to all sinks that are not gateway buffers + * using the right PCM converter function. + */ + struct comp_buffer *sink; + + comp_dev_for_each_consumer(dev, sink) { + struct comp_dev *sink_dev; + int j; + + if (sink == dd->dma_buffer) + continue; + + sink_dev = comp_buffer_get_sink_component(sink); + + j = IPC4_SRC_QUEUE_ID(buf_get_id(sink)); + + 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; + continue; + } + + if (!converter[j]) { + comp_err(dev, "No PCM converter for sink queue %d\n", j); + ret = -EINVAL; + continue; + } + + if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE && + audio_buffer_hw_params_configured(&sink->audio_buffer)) { + ret = stream_copy_from_no_consume(dev, dd->local_buffer, sink, + converter[j], bytes, dd->chmap); + } + } +#endif + ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer, + dd->process, bytes, dd->chmap); + } else { + audio_stream_invalidate(&dd->dma_buffer->stream, bytes); + /* + * The PCM converter functions used during DMA buffer copy can never fail, + * so no need to check the return value of stream_copy_from_no_consume(). + */ + + ret = stream_copy_from_no_consume(dev, dd->dma_buffer, dd->local_buffer, + dd->process, bytes, dd->chmap); +#if CONFIG_IPC_MAJOR_4 + /* Apply gain to the local buffer */ + if (dd->ipc_config.apply_gain) { + ret = copier_gain_input(dev, dd->local_buffer, dd->gain_data, + GAIN_ADD, bytes); + if (ret) + comp_err(dev, "copier_gain_input() failed err=%d", ret); + buffer_stream_writeback(dd->local_buffer, bytes); + } + + /* 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 + */ + struct comp_buffer *sink; + + comp_dev_for_each_consumer(dev, sink) { + struct comp_dev *sink_dev; + int j; + + /* this has been handled above already */ + if (sink == dd->local_buffer) + continue; + + sink_dev = comp_buffer_get_sink_component(sink); + + j = IPC4_SRC_QUEUE_ID(buf_get_id(sink)); + + 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; + continue; + } + + if (!converter[j]) { + comp_err(dev, "No PCM converter for sink queue %d\n", j); + ret = -EINVAL; + continue; + } + + if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE && + audio_buffer_hw_params_configured(&sink->audio_buffer)) + ret = stream_copy_from_no_consume(dev, dd->dma_buffer, + sink, converter[j], + bytes, dd->chmap); + } + } +#endif + audio_stream_consume(&dd->dma_buffer->stream, bytes); + } + + /* assert dma_buffer_copy succeed */ + if (ret < 0) { + struct comp_buffer *source_c, *sink_c; + + source_c = dev->direction == SOF_IPC_STREAM_PLAYBACK ? + dd->local_buffer : dd->dma_buffer; + sink_c = dev->direction == SOF_IPC_STREAM_PLAYBACK ? + dd->dma_buffer : dd->local_buffer; + comp_err(dev, "dma buffer copy failed, dir %d bytes %d avail %d free %d", + dev->direction, bytes, + audio_stream_get_avail_samples(&source_c->stream) * + audio_stream_frame_bytes(&source_c->stream), + audio_stream_get_free_samples(&sink_c->stream) * + audio_stream_frame_bytes(&sink_c->stream)); + } else { + /* update host position (in bytes offset) for drivers */ + dd->total_data_processed += bytes; + } +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Increment performance counters */ + io_perf_monitor_update_data(dd->io_perf_dai_byte_count, bytes); +#endif + + return dma_status; +} + +/* this is called by DMA driver every time descriptor has completed */ +static enum sof_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) +{ + enum sof_dma_cb_status dma_status = SOF_DMA_CB_STATUS_RELOAD; + uint32_t i, bytes; + + comp_dbg(dev, "entry"); + + /* 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); + + /* tell DMA not to reload */ + dma_status = SOF_DMA_CB_STATUS_END; + } + + /* 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(dd->dma_buffer); + + return dma_status; + } + + bytes = frames * audio_stream_frame_bytes(&dd->dma_buffer->stream); + if (dev->direction == SOF_IPC_STREAM_CAPTURE) + audio_stream_invalidate(&dd->dma_buffer->stream, bytes); + + assert(dd->channel_copy); + + /* copy all channels one by one */ + for (i = 0; i < audio_stream_get_channels(&dd->dma_buffer->stream); i++) { + uint32_t multi_buf_channel = audio_buffer_get_chmap(&dd->dma_buffer->audio_buffer, + i); + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dd->channel_copy(&multi_endpoint_buffer->stream, multi_buf_channel, + &dd->dma_buffer->stream, i, frames); + else + dd->channel_copy(&dd->dma_buffer->stream, i, + &multi_endpoint_buffer->stream, multi_buf_channel, + frames); + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + audio_stream_writeback(&dd->dma_buffer->stream, bytes); + audio_stream_produce(&dd->dma_buffer->stream, bytes); + } else { + audio_stream_consume(&dd->dma_buffer->stream, bytes); + } + + /* update host position (in bytes offset) for drivers */ + dd->total_data_processed += bytes; + + return dma_status; +} + +__cold int dai_common_new(struct dai_data *dd, struct comp_dev *dev, + const struct ipc_config_dai *dai_cfg) +{ + uint32_t dir; + + assert_can_be_cold(); + + dd->dai = dai_get(dai_cfg->type, dai_cfg->dai_index, DAI_CREAT); + if (!dd->dai) { + comp_err(dev, "dai_get() failed to create DAI."); + return -ENODEV; + } + + dd->ipc_config = *dai_cfg; + + /* request GP LP DMA with shared access privilege */ + dir = dai_cfg->direction == SOF_IPC_STREAM_PLAYBACK ? + SOF_DMA_DIR_MEM_TO_DEV : SOF_DMA_DIR_DEV_TO_MEM; + + dd->chan_index = -EINVAL; + dd->dma = sof_dma_get(dir, dd->dai->dma_caps, dd->dai->dma_dev, SOF_DMA_ACCESS_SHARED); + if (!dd->dma) { + dai_put(dd->dai); + comp_err(dev, "dma_get() failed to get shared access to DMA."); + return -ENODEV; + } + + k_spinlock_init(&dd->dai->lock); + + dma_sg_init(&dd->config.elem_array); + dd->xrun = 0; + + /* I/O performance init, keep it last so the function does not reach this in case + * of return on error, so that we do not waste a slot + */ +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + enum io_perf_data_item_id perf_type; + enum io_perf_data_item_dir perf_dir; + + switch (dai_cfg->type) { + case SOF_DAI_INTEL_SSP: + perf_type = IO_PERF_I2S_ID; + break; + case SOF_DAI_INTEL_ALH: + perf_type = IO_PERF_SOUND_WIRE_ID; + break; + case SOF_DAI_INTEL_DMIC: + perf_type = IO_PERF_DMIC_ID; + break; + case SOF_DAI_INTEL_HDA: + perf_type = IO_PERF_HDA_ID; + break; + + default: + perf_type = IO_PERF_INVALID_ID; + comp_warn(dev, "Unsupported DAI type"); + } + if (dai_cfg->direction == SOF_IPC_STREAM_PLAYBACK) + perf_dir = IO_PERF_OUTPUT_DIRECTION; + else + perf_dir = IO_PERF_INPUT_DIRECTION; + + /* ignore perf meas init on case of other dai types */ + if (perf_type != IO_PERF_INVALID_ID) { + struct io_perf_data_item init_data = {perf_type, + dai_cfg->dai_index, + perf_dir, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 }; + io_perf_monitor_init_data(&dd->io_perf_dai_byte_count, &init_data); + } +#endif + + return 0; +} + +__cold 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; + + assert_can_be_cold(); + + 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_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*dd)); + if (!dd) + goto e_data; + + comp_set_drvdata(dev, dd); + + ret = dai_common_new(dd, dev, dai_cfg); + if (ret < 0) + goto error; + + dd->chmap = DUMMY_CHMAP; + + dev->state = COMP_STATE_READY; + + return dev; + +error: + rfree(dd); +e_data: + comp_free_device(dev); + return NULL; +} + +__cold void dai_common_free(struct dai_data *dd) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + io_perf_monitor_release_slot(dd->io_perf_dai_byte_count); +#endif + + if (dd->group) + dai_group_put(dd->group); + + if (dd->chan_index >= 0) { + sof_dma_release_channel(dd->dma, dd->chan_index); + dd->chan_index = -EINVAL; + } + + sof_dma_put(dd->dma); + + dai_release_llp_slot(dd); + + dai_put(dd->dai); + + rfree(dd->dai_spec_config); +} + +__cold static void dai_free(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + assert_can_be_cold(); + + if (dd->group) + notifier_unregister(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER); + + dai_common_free(dd); + + rfree(dd); + comp_free_device(dev); +} + +int dai_common_get_hw_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir) +{ + struct dai_config cfg; + int ret; + + comp_dbg(dev, "entry"); + + ret = dai_config_get(dd->dai->dev, &cfg, dir); + if (ret) + return ret; + + params->rate = cfg.rate; + params->buffer_fmt = 0; + params->channels = cfg.channels; + + /* dai_comp_get_hw_params() function fetches hardware dai parameters, + * which then are propagating back through the pipeline, so that any + * component can convert specific stream parameter. Here, we overwrite + * frame_fmt hardware parameter as DAI component is able to convert + * stream with different frame_fmt's (using pcm converter) + */ + params->frame_fmt = dev->ipc_config.frame_fmt; + + return ret; +} + +__cold 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); + + assert_can_be_cold(); + + return dai_common_get_hw_params(dd, dev, params, dir); +} + +static int dai_verify_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct sof_ipc_stream_params hw_params; + int ret; + + memset(&hw_params, 0, sizeof(hw_params)); + + ret = dai_common_get_hw_params(dd, dev, &hw_params, params->direction); + if (ret < 0) { + comp_err(dev, "failed ret %d", ret); + return ret; + } + + /* checks whether pcm parameters match hardware DAI parameter set + * during dai_set_config(). If hardware parameter is equal to 0, it + * means that it can vary, so any value is acceptable. We do not check + * format parameter, because DAI is able to change format using + * pcm_converter functions. + */ + if (hw_params.rate && hw_params.rate != params->rate) { + comp_err(dev, "pcm rate parameter %d does not match hardware rate %d", + params->rate, hw_params.rate); + return -EINVAL; + } + + if (hw_params.channels && hw_params.channels != params->channels) { + comp_err(dev, "pcm channels parameter %d does not match hardware channels %d", + params->channels, hw_params.channels); + return -EINVAL; + } + + /* set component period frames */ + component_set_nearest_period_frames(dev, params->rate); + + return 0; +} + +static int dai_get_dma_slot(struct dai_data *dd, struct comp_dev *dev, uint32_t *slot) +{ + struct dai_config cfg; + int ret; + int hs; + + ret = dai_config_get(dd->dai->dev, &cfg, dev->direction); + if (ret < 0) { + comp_err(dev, "failed to fetch DAI configuration"); + return ret; + } + + hs = dai_get_handshake(dd->dai, dev->direction, dd->stream_id); + if (ret < 0) { + comp_err(dev, "failed to fetch DAI handshake"); + return ret; + } + + switch (cfg.type) { + case DAI_IMX_SAI: + case DAI_IMX_ESAI: + case DAI_IMX_MICFIL: + *slot = (hs & GENMASK(15, 8)) >> 8; + break; + default: + *slot = hs; + break; + } + + return 0; +} + +static int dai_set_sg_config(struct dai_data *dd, struct comp_dev *dev, uint32_t period_bytes, + uint32_t period_count) +{ + struct dma_sg_config *config = &dd->config; + uint32_t local_fmt = audio_stream_get_frm_fmt(&dd->local_buffer->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dd->dma_buffer->stream); + uint32_t fifo, max_block_count, buf_size; + int err = 0; + + /* set up DMA configuration */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + dd->process = pcm_get_conversion_function(local_fmt, dma_fmt); + config->direction = SOF_DMA_DIR_MEM_TO_DEV; + err = dai_get_dma_slot(dd, dev, &config->dest_dev); + if (err < 0) + return err; + } else { + dd->process = pcm_get_conversion_function(dma_fmt, local_fmt); + config->direction = SOF_DMA_DIR_DEV_TO_MEM; + err = dai_get_dma_slot(dd, dev, &config->src_dev); + if (err < 0) + return err; + } + + if (!dd->process) { + comp_err(dev, "converter NULL: local fmt %d dma fmt %d\n", + local_fmt, dma_fmt); + return -EINVAL; + } + + if (dd->dai->type == SOF_DAI_INTEL_DMIC) { + /* For DMIC the DMA src and dest widths should always be 4 bytes + * due to 32 bit FIFO packer. Setting width to 2 bytes for + * 16 bit format would result in recording at double rate. + */ + config->src_width = 4; + config->dest_width = 4; + } else { + config->src_width = get_sample_bytes(dma_fmt); + config->dest_width = config->src_width; + } + + config->cyclic = 1; + config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); + config->is_scheduling_source = comp_is_scheduling_source(dev); + config->period = dev->pipeline->period; + + comp_dbg(dev, "dest_dev = %d stream_id = %d src_width = %d dest_width = %d", + config->dest_dev, dd->stream_id, config->src_width, config->dest_width); + + if (!config->elem_array.elems) { + fifo = dai_get_fifo(dd->dai, dev->direction, dd->stream_id); + + comp_dbg(dev, "fifo 0x%x", fifo); + + err = sof_dma_get_attribute(dd->dma, DMA_ATTR_MAX_BLOCK_COUNT, &max_block_count); + if (err < 0) { + comp_err(dev, "can't get max block count, err = %d", + err); + goto out; + } + + if (!max_block_count) { + comp_err(dev, "invalid max-block-count of zero"); + goto out; + } + + if (max_block_count < period_count) { + comp_dbg(dev, "unsupported period count %d", + period_count); + buf_size = period_count * period_bytes; + do { + if (IS_ALIGNED(buf_size, max_block_count)) { + period_count = max_block_count; + period_bytes = buf_size / period_count; + break; + } else { + comp_warn(dev, "alignment error for buf_size = %d, block count = %d", + buf_size, max_block_count); + } + } while (--max_block_count > 0); + } + + err = dma_sg_alloc(NULL, &config->elem_array, SOF_MEM_FLAG_USER, + config->direction, + period_count, + period_bytes, + (uintptr_t)audio_stream_get_addr(&dd->dma_buffer->stream), + fifo); + if (err < 0) { + comp_err(dev, "sg alloc failed period_count %d period_bytes %d err = %d", + period_count, period_bytes, err); + return err; + } + } +out: + return err; +} + +static int dai_set_dma_config(struct dai_data *dd, struct comp_dev *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; + int i; + + comp_dbg(dev, "entry"); + + dma_cfg = rmalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, + sizeof(struct dma_config)); + if (!dma_cfg) { + comp_err(dev, "dma_cfg allocation failed"); + return -ENOMEM; + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dma_cfg->channel_direction = MEMORY_TO_PERIPHERAL; + else + dma_cfg->channel_direction = PERIPHERAL_TO_MEMORY; + + dma_cfg->source_data_size = config->src_width; + dma_cfg->dest_data_size = config->dest_width; + + if (config->burst_elems) + dma_cfg->source_burst_length = config->burst_elems; + else + dma_cfg->source_burst_length = 8; + + dma_cfg->dest_burst_length = dma_cfg->source_burst_length; + dma_cfg->cyclic = config->cyclic; + dma_cfg->user_data = NULL; + dma_cfg->dma_callback = NULL; + dma_cfg->block_count = config->elem_array.count; + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dma_cfg->dma_slot = config->dest_dev; + else + dma_cfg->dma_slot = config->src_dev; + + dma_block_cfg = rballoc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, + sizeof(struct dma_block_config) * dma_cfg->block_count); + if (!dma_block_cfg) { + rfree(dma_cfg); + comp_err(dev, "dma_block_config allocation failed"); + return -ENOMEM; + } + + dma_cfg->head_block = dma_block_cfg; + for (i = 0; i < dma_cfg->block_count; i++) { + dma_block_cfg->dest_scatter_en = config->scatter; + dma_block_cfg->block_size = config->elem_array.elems[i].size; + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + dma_block_cfg->source_address = + local_to_host(config->elem_array.elems[i].src); + dma_block_cfg->dest_address = + config->elem_array.elems[i].dest; + dma_block_cfg->source_addr_adj = DMA_ADDR_ADJ_DECREMENT; + dma_block_cfg->dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; + } else { + dma_block_cfg->source_address = + config->elem_array.elems[i].src; + dma_block_cfg->dest_address = + local_to_host(config->elem_array.elems[i].dest); + dma_block_cfg->source_addr_adj = DMA_ADDR_ADJ_INCREMENT; + dma_block_cfg->dest_addr_adj = DMA_ADDR_ADJ_DECREMENT; + } + prev = dma_block_cfg; + prev->next_block = ++dma_block_cfg; + } + if (prev) + prev->next_block = dma_cfg->head_block; + + dd->z_config = dma_cfg; + + return 0; +} + +static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev, + const struct sof_ipc_stream_params *params, + uint32_t *pb, uint32_t *pc) +{ + struct sof_ipc_stream_params hw_params = *params; + uint32_t frame_size; + uint32_t period_count; + uint32_t period_bytes; + uint32_t buffer_size; + uint32_t buffer_size_preferred; + uint32_t addr_align; + uint32_t align; + int err; + + comp_dbg(dev, "entry"); + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dd->local_buffer = comp_dev_get_first_data_producer(dev); + else + dd->local_buffer = comp_dev_get_first_data_consumer(dev); + + /* check if already configured */ + if (dev->state == COMP_STATE_PREPARE) { + comp_info(dev, "component has been already configured."); + return 0; + } + + /* can set params on only init state */ + if (dev->state != COMP_STATE_READY) { + comp_err(dev, "comp state %d, expected COMP_STATE_READY.", + dev->state); + return -EINVAL; + } + + err = sof_dma_get_attribute(dd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, &addr_align); + if (err < 0) { + comp_err(dev, "can't get dma buffer addr align, err = %d", + err); + return err; + } + + err = sof_dma_get_attribute(dd->dma, DMA_ATTR_BUFFER_SIZE_ALIGNMENT, &align); + if (err < 0 || !align) { + comp_err(dev, "no valid dma align, err = %d, align = %u", + err, align); + return -EINVAL; + } + + /* calculate frame size */ + 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, "invalid period_bytes."); + return -EINVAL; + } + + dd->period_bytes = period_bytes; + *pb = period_bytes; + + /* calculate DMA buffer size */ + period_count = dd->dma->plat_data.period_count; + +#if CONFIG_IPC_MAJOR_4 + struct ipc4_copier_module_cfg *copier_cfg = dd->dai_spec_config; + uint32_t dma_buff_length_periods; + + /* copier ibs/obs is set to size of one period */ + if (dev->direction == SOF_IPC_STREAM_CAPTURE) + dma_buff_length_periods = dd->ipc_config.dma_buffer_size / copier_cfg->base.ibs; + else + dma_buff_length_periods = dd->ipc_config.dma_buffer_size / copier_cfg->base.obs; + + period_count = MAX(period_count, dma_buff_length_periods); +#else + period_count = MAX(period_count, + SOF_DIV_ROUND_UP(dd->ipc_config.dma_buffer_size, period_bytes)); +#endif /* CONFIG_IPC_MAJOR_4 */ + + if (!period_count) { + comp_err(dev, "no valid dma buffer period count"); + return -EINVAL; + } + buffer_size = ALIGN_UP(period_count * period_bytes, align); + period_count = MAX(period_count, + SOF_DIV_ROUND_UP(dd->ipc_config.dma_buffer_size, period_bytes)); + buffer_size_preferred = ALIGN_UP(period_count * period_bytes, align); + + /* alloc DMA buffer or change its size if exists */ + if (dd->dma_buffer) { + err = buffer_set_size_range(dd->dma_buffer, buffer_size_preferred, buffer_size, + addr_align); + + if (err < 0) { + comp_err(dev, "buffer_size = %u failed", buffer_size); + return err; + } + } else { + dd->dma_buffer = buffer_alloc_range(NULL, buffer_size_preferred, buffer_size, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + addr_align, BUFFER_USAGE_NOT_SHARED); + if (!dd->dma_buffer) { + comp_err(dev, "failed to alloc dma buffer"); + return -ENOMEM; + } + + /* + * dma_buffer should reffer to hardware dai parameters. + * Here, we overwrite frame_fmt hardware parameter as DAI + * component is able to convert stream with different + * frame_fmt's (using pcm converter). + */ + hw_params.frame_fmt = dev->ipc_config.frame_fmt; + buffer_set_params(dd->dma_buffer, &hw_params, BUFFER_UPDATE_FORCE); + } + + *pc = audio_stream_get_size(&dd->dma_buffer->stream) / period_bytes; + dd->fast_mode = dd->ipc_config.feature_mask & BIT(IPC4_COPIER_FAST_MODE); + return 0; +} + +int dai_common_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *base_cfg_params) +{ + struct sof_ipc_stream_params params = *base_cfg_params; + struct sof_ipc_stream_params hw_params; + struct dma_sg_config *config = &dd->config; + uint32_t period_bytes = 0; + uint32_t period_count = 0; + int err = 0; + + comp_dbg(dev, "dai_zephyr_params()"); + + /* configure dai_data first */ + err = ipc_dai_data_config(dd, dev); + if (err < 0) { + comp_err(dev, "ipc dai data config failed."); + return err; + } + + /* When the hardware is able to return a valid number of DMA buffer audio channels + * (e.g., extracted from a blob), give the returned number of channels higher precedence + * over the number supplied via the base config params. + */ + memset(&hw_params, 0, sizeof(hw_params)); + err = dai_common_get_hw_params(dd, dev, &hw_params, params.direction); + if (err < 0) { + comp_err(dev, "dai_common_get_hw_params() failed: %d", err); + return err; + } + + if (hw_params.channels != 0 && hw_params.channels != params.channels) { + params.channels = hw_params.channels; + comp_info(dev, "Replacing %d base config channels with %d hw params channels.", + base_cfg_params->channels, params.channels); + } + + err = dai_verify_params(dd, dev, ¶ms); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return -EINVAL; + } + + err = dai_set_dma_buffer(dd, dev, ¶ms, &period_bytes, &period_count); + if (err < 0) { + comp_err(dev, "alloc dma buffer failed."); + goto out; + } + + err = dai_set_sg_config(dd, dev, period_bytes, period_count); + if (err < 0) { + comp_err(dev, "set sg config failed."); + goto out; + } + + err = dai_set_dma_config(dd, dev); + if (err < 0) + comp_err(dev, "set dma config failed."); +out: + /* + * Make sure to free all allocated items, all functions + * can be called with null pointer. + */ + if (err < 0) { + buffer_free(dd->dma_buffer); + dd->dma_buffer = NULL; + dma_sg_free(NULL, &config->elem_array); + rfree(dd->z_config); + dd->z_config = NULL; + } + + return err; +} + +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, "entry"); + + return dai_common_params(dd, dev, params); +} + +int dai_common_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, "Component is in active state."); + return 0; + } + + if (!dd->dai_spec_config) { + comp_err(dev, "dai specific config is not set yet!"); + return -EINVAL; + } + + if (dd->chan_index >= 0) { + comp_info(dev, "dma channel index %d already configured", + dd->chan_index); + return 0; + } + + channel = dai_config_dma_channel(dd, dev, dd->dai_spec_config); + comp_dbg(dev, "channel = %d", channel); + + /* do nothing for asking for channel free, for compatibility. */ + if (channel == SOF_DMA_CHAN_INVALID) { + comp_err(dev, "dai_config is not set yet!"); + return -EINVAL; + } + + /* get DMA channel */ + dd->chan_index = sof_dma_request_channel(dd->dma, channel); + if (dd->chan_index < 0) { + comp_err(dev, "dma_request_channel() failed ch %d ret %d", channel, dd->chan_index); + return dd->chan_index; + } + + comp_dbg(dev, "new configured dma channel index %d", + dd->chan_index); + + return 0; +} + +int dai_common_prepare(struct dai_data *dd, struct comp_dev *dev) +{ + int ret; + + dd->total_data_processed = 0; + + if (dd->chan_index < 0) { + comp_err(dev, "Missing dd->chan_index."); + comp_set_state(dev, COMP_TRIGGER_RESET); + return -EINVAL; + } + + if (!dd->config.elem_array.elems) { + comp_err(dev, "Missing dd->config.elem_array.elems."); + comp_set_state(dev, COMP_TRIGGER_RESET); + return -EINVAL; + } + + /* clear dma buffer to avoid pop noise */ + buffer_zero(dd->dma_buffer); + + /* dma reconfig not required if XRUN handling */ + if (dd->xrun) { + /* after prepare, we have recovered from xrun */ + dd->xrun = 0; + return 0; + } + + ret = sof_dma_config(dd->dma, dd->chan_index, dd->z_config); + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + return ret; +} + +static int dai_prepare(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "entry"); + + ret = dai_common_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_common_prepare(dd, dev); +} + +void dai_common_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(dd, dev); + + dma_sg_free(NULL, &config->elem_array); + if (dd->z_config) { + rfree(dd->z_config->head_block); + rfree(dd->z_config); + dd->z_config = NULL; + } + + if (dd->dma_buffer) { + buffer_free(dd->dma_buffer); + dd->dma_buffer = NULL; + } + + dd->wallclock = 0; + dd->total_data_processed = 0; + dd->xrun = 0; +} + +static int dai_reset(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + dai_common_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 dai_data *dd, struct comp_dev *dev, int cmd) +{ + int ret = 0; + + comp_dbg(dev, "command = %u", cmd); + +#ifdef CONFIG_IPC_MAJOR_3 + if (dev->state == comp_get_requested_state(cmd)) + return PPL_STATUS_PATH_STOP; +#endif /* CONFIG_IPC_MAJOR_3 */ + + switch (cmd) { + case COMP_TRIGGER_START: + comp_dbg(dev, "START"); + + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun == 0) { + ret = sof_dma_start(dd->dma, dd->chan_index); + if (ret < 0) + return ret; + + /* start the DAI */ + dai_trigger_op(dd->dai, cmd, dev->direction); + } else { + dd->xrun = 0; + } + + platform_dai_wallclock(dev, &dd->wallclock); + break; + case COMP_TRIGGER_RELEASE: + /* before release, we clear the buffer data to 0s, + * then there is no history data sent out after release. + * this is only supported at capture mode. + */ + if (dev->direction == SOF_IPC_STREAM_CAPTURE) { + buffer_zero(dd->dma_buffer); + } + + /* DMA driver and SOF's view of the DMA buffer's + * read and write cursors must be the same to + * avoid scenarios in which the DMA driver + * reports false "free" and "pending" values, thus + * leading to the DMA copying stale data due to + * dma_status() stopping dai_common_copy() from + * updating the data. + * + * Only applies to non HD-DMA links as HD-DMA read/write pointer + * is not reset during stop/config/start + */ + if (!(dd->dai->dma_caps & SOF_DMA_CAP_HDA)) + audio_stream_reset(&dd->dma_buffer->stream); + + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun == 0) { + /* recover valid start position */ + ret = sof_dma_stop(dd->dma, dd->chan_index); + if (ret < 0) + return ret; + + /* dma_config needed after stop */ + ret = sof_dma_config(dd->dma, dd->chan_index, dd->z_config); + if (ret < 0) + return ret; + + ret = sof_dma_start(dd->dma, dd->chan_index); + if (ret < 0) + return ret; + + /* start the DAI */ + dai_trigger_op(dd->dai, cmd, dev->direction); + } else { + dd->xrun = 0; + } + + platform_dai_wallclock(dev, &dd->wallclock); + break; + case COMP_TRIGGER_XRUN: + comp_info(dev, "XRUN"); + dd->xrun = 1; + + COMPILER_FALLTHROUGH; + case COMP_TRIGGER_STOP: + comp_dbg(dev, "STOP"); +/* + * Some platforms cannot just simple disable + * DMA channel during the transfer, + * because it will hang the whole DMA controller. + * Therefore, stop the DMA first and let the DAI + * drain the FIFO in order to stop the channel + * as soon as possible. + */ +#if CONFIG_COMP_DAI_STOP_TRIGGER_ORDER_REVERSE + ret = sof_dma_stop(dd->dma, dd->chan_index); + dai_trigger_op(dd->dai, cmd, dev->direction); +#else + dai_trigger_op(dd->dai, cmd, dev->direction); + ret = sof_dma_stop(dd->dma, dd->chan_index); + if (ret) { + comp_warn(dev, "dma was stopped earlier"); + ret = 0; + } +#endif + break; + case COMP_TRIGGER_PAUSE: + comp_dbg(dev, "PAUSE"); +#if CONFIG_COMP_DAI_STOP_TRIGGER_ORDER_REVERSE + ret = sof_dma_suspend(dd->dma, dd->chan_index); + dai_trigger_op(dd->dai, cmd, dev->direction); +#else + dai_trigger_op(dd->dai, cmd, dev->direction); + ret = sof_dma_suspend(dd->dma, dd->chan_index); +#endif + break; + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + /* only start the DAI if we are not XRUN handling */ + if (dd->xrun) + dd->xrun = 0; + else + dai_trigger_op(dd->dai, cmd, dev->direction); + break; + } + +#ifdef CONFIG_IPC_MAJOR_3 + /* TODO: investigate why making this IPC version-agnostic + * breaks some Intel tests and check if doing so would be + * possible (or even make sense) on Intel platforms. + * + * See issue #8920 for details. + */ + if (!ret) + return comp_set_state(dev, cmd); +#endif /* CONFIG_IPC_MAJOR_3 */ + + return ret; +} + +int dai_common_trigger(struct dai_data *dd, struct comp_dev *dev, int cmd) +{ + 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, "non-atomic trigger"); + return dai_comp_trigger_internal(dd, dev, cmd); + } + + /* DAI is grouped, so only trigger when the entire group is ready */ + + if (!group->trigger_counter) { + /* First DAI to receive the trigger command, + * prepare for atomic trigger + */ + comp_dbg(dev, "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, "already processing atomic trigger"); + ret = -EAGAIN; + } else { + /* Count down the number of remaining DAIs required + * to receive the trigger command before atomic trigger + * takes place + */ + group->trigger_counter--; + comp_dbg(dev, "trigger counter %d, group %d", + group->trigger_counter, group->group_id); + + if (!group->trigger_counter) { + /* The counter has reached 0, which means + * all DAIs have received the same trigger command + * and we may begin the actual trigger process + * synchronously. + */ + + irq_local_disable(irq_flags); + notifier_event(group, NOTIFIER_ID_DAI_TRIGGER, + NOTIFIER_TARGET_CORE_LOCAL, NULL, 0); + irq_local_enable(irq_flags); + + /* return error of last trigger */ + ret = group->trigger_ret; + } + } + + return ret; +} + +static int dai_comp_trigger(struct comp_dev *dev, int cmd) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_common_trigger(dd, dev, cmd); +} + +/** + * Get status from the DMA driver. + * + * After status call, a check for xrun condition is done and + * depending on configuration, a xrun report is optionally sent. + * See also xrun reporting done in dai_report_reload_xrun(). + */ +static int dai_get_status(struct comp_dev *dev, struct dai_data *dd, struct dma_status *stat) +{ + int ret = sof_dma_get_status(dd->dma, dd->chan_index, stat); +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + if (ret == -EPIPE && !dd->xrun_notification_sent) { + dd->xrun_notification_sent = send_copier_gateway_xrun_notif_msg + (dev->pipeline->pipeline_id, dev->direction); + } else if (!ret) { + dd->xrun_notification_sent = false; + } +#endif + return ret; +} + +/** + * Report xrun occurrence after DAI DMA driver reports + * an error for a reload attempt of 'bytes' of data. + * + * See also xrun detection done in dai_get_status(). + */ +static void dai_report_reload_xrun(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes) +{ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + comp_err(dev, "underrun due to no data available"); + comp_underrun(dev, dd->local_buffer, bytes); + } else { + comp_err(dev, "overrun due to no space available"); + comp_overrun(dev, dd->local_buffer, bytes); + } +} + +/* 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) +{ + 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; + + frame_bytes = audio_stream_frame_bytes(&dd[0]->dma_buffer->stream); + + 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 = dai_get_status(dev, dd[i], &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, "dma_get_status() underrun occurred, endpoint: %d ret = %u", + i, ret); + else + comp_dbg(dev, "dma_get_status() overrun occurred, enpdoint: %d ret = %u", + i, ret); + break; + default: + return ret; + } + + if (dd[i]->dma->plat_data.caps & SOF_DMA_CAP_HDA) + audio_stream_sync_to_hw(&dd[i]->dma_buffer->stream, &stat); + + avail_bytes = MIN(avail_bytes, stat.pending_length); + free_bytes = MIN(free_bytes, stat.free); + } + + /* calculate minimum size to copy */ + if (direction == SOF_IPC_STREAM_PLAYBACK) { + src_frames = audio_stream_get_avail_frames(&multi_endpoint_buffer->stream); + sink_frames = free_bytes / frame_bytes; + } else { + src_frames = avail_bytes / frame_bytes; + sink_frames = audio_stream_get_free_frames(&multi_endpoint_buffer->stream); + } + + 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. + */ + if (!(dd[0]->ipc_config.feature_mask & BIT(IPC4_COPIER_FAST_MODE))) + frames = MIN(frames, dev->frames); + comp_dbg(dev, "dir: %d copy frames= 0x%x", + dev->direction, frames); + + /* return if nothing to copy */ + if (!frames) { +#if CONFIG_DAI_VERBOSE_GLITCH_WARNINGS + comp_warn(dev, "nothing to copy, src_frames: %u, sink_frames: %u", + src_frames, sink_frames); +#endif + + for (i = 0; i < num_endpoints; i++) { + ret = sof_dma_reload(dd[i]->dma, dd[i]->chan_index, 0); + if (ret < 0) { + dai_report_reload_xrun(dd[i], dev, 0); + return ret; + } + } + + return 0; + } + + if (direction == SOF_IPC_STREAM_PLAYBACK) { + frame_bytes = audio_stream_frame_bytes(&multi_endpoint_buffer->stream); + buffer_stream_invalidate(multi_endpoint_buffer, frames * frame_bytes); + } + + for (i = 0; i < num_endpoints; i++) { + enum sof_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 trigger copy failed"); + + status = dai_dma_multi_endpoint_cb(dd[i], dev, frames, multi_endpoint_buffer); + if (status == SOF_DMA_CB_STATUS_END) + sof_dma_stop(dd[i]->dma, dd[i]->chan_index); + + copy_bytes = frames * audio_stream_frame_bytes(&dd[i]->dma_buffer->stream); + ret = sof_dma_reload(dd[i]->dma, dd[i]->chan_index, copy_bytes); + if (ret < 0) { + dai_report_reload_xrun(dd[i], dev, copy_bytes); + return ret; + } + + dai_dma_position_update(dd[i], dev); + } + + frame_bytes = audio_stream_frame_bytes(&multi_endpoint_buffer->stream); + if (direction == SOF_IPC_STREAM_PLAYBACK) { + comp_update_buffer_consume(multi_endpoint_buffer, frames * frame_bytes); + } else { + buffer_stream_writeback(multi_endpoint_buffer, frames * frame_bytes); + comp_update_buffer_produce(multi_endpoint_buffer, frames * frame_bytes); + } + + return 0; +} + +static void set_new_local_buffer(struct dai_data *dd, struct comp_dev *dev) +{ + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dd->dma_buffer->stream); + uint32_t local_fmt; + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dd->local_buffer = comp_dev_get_first_data_producer(dev); + else + dd->local_buffer = comp_dev_get_first_data_consumer(dev); + + local_fmt = audio_stream_get_frm_fmt(&dd->local_buffer->stream); + + 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 */ +int dai_common_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter) +{ + struct dma_status stat; + uint32_t avail_bytes; + uint32_t free_bytes; + uint32_t copy_bytes; + uint32_t src_frames; + uint32_t sink_frames = 0; + uint32_t frames = UINT32_MAX; + int ret; + + /* get data sizes from DMA */ + ret = dai_get_status(dev, dd, &stat); + switch (ret) { + case 0: + break; + case -EPIPE: + /* DMA status can return -EPIPE and current status content if xrun occurs */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + comp_dbg(dev, "dma_get_status() underrun occurred, ret = %d", + ret); + else + comp_dbg(dev, "dma_get_status() overrun occurred, ret = %d", + ret); + break; + default: + return ret; + } + + /* HDA DMA Write and Read Position registers are not cleared by hardware on + * dma_stop() or dma_start(). However, the dma_buffer is recreated after a reset + * with its w_ptr and r_ptr set to NULL. The w_ptr and r_ptr must be kept in sync + * with the hardware DMA Write and Read Positions. + * Other types of DMA clear their hardware Read/Write Positions upon dma_stop() + * or dma_start(). Additionally, some DMAs, such as GPDMA, do not populate + * dma_status::write_position and read_position. Therefore, synchronization is + * done here only for HDA DMA. + */ + if (dd->dma->plat_data.caps & SOF_DMA_CAP_HDA) + audio_stream_sync_to_hw(&dd->dma_buffer->stream, &stat); + + avail_bytes = stat.pending_length; + free_bytes = stat.free; + + /* handle module runtime unbind */ + if (!dd->local_buffer) { + set_new_local_buffer(dd, dev); + + if (!dd->local_buffer) { + comp_warn(dev, "local buffer unbound, cannot copy"); + return 0; + } + } + + assert(audio_stream_get_channels(&dd->dma_buffer->stream)); + assert(audio_stream_get_channels(&dd->local_buffer->stream)); + + /* calculate minimum size to copy */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + src_frames = audio_stream_get_avail_frames(&dd->local_buffer->stream); + sink_frames = free_bytes / audio_stream_frame_bytes(&dd->dma_buffer->stream); + frames = MIN(src_frames, sink_frames); + + /* + * In the case of playback DAI's with multiple sink buffers, compute the + * minimum number of frames based on the DMA avail_bytes and the free + * samples in all active sink buffers. + */ + struct comp_buffer *sink; + + comp_dev_for_each_consumer(dev, sink) { + struct comp_dev *sink_dev; + + sink_dev = comp_buffer_get_sink_component(sink); + + if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE && + audio_buffer_hw_params_configured(&sink->audio_buffer)) { + sink_frames = + audio_stream_get_free_frames(&sink->stream); + frames = MIN(frames, sink_frames); + } + } + } else { + src_frames = avail_bytes / audio_stream_frame_bytes(&dd->dma_buffer->stream); + + /* + * 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) { + sink_frames = audio_stream_get_free_frames(&dd->local_buffer->stream); + frames = sink_frames; + } 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. + */ + struct comp_buffer *sink; + + comp_dev_for_each_consumer(dev, sink) { + struct comp_dev *sink_dev; + + sink_dev = comp_buffer_get_sink_component(sink); + + if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE && + audio_buffer_hw_params_configured(&sink->audio_buffer)) { + sink_frames = + audio_stream_get_free_frames(&sink->stream); + frames = MIN(frames, sink_frames); + } + } + } + + frames = MIN(frames, src_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 + */ + if (!dd->fast_mode) + frames = MIN(frames, dev->frames); + + copy_bytes = frames * audio_stream_frame_bytes(&dd->dma_buffer->stream); + + comp_dbg(dev, "dir: %d copy_bytes= 0x%x", + dev->direction, copy_bytes); + +#if CONFIG_DAI_VERBOSE_GLITCH_WARNINGS + /* Check possibility of glitch occurrence */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK && + copy_bytes + avail_bytes < dd->period_bytes) + comp_warn(dev, "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, "Copy_bytes %d + free bytes %d < period bytes %d, possible glitch", + copy_bytes, free_bytes, dd->period_bytes); +#endif + + /* return if nothing to copy */ + if (!copy_bytes) { +#if CONFIG_DAI_VERBOSE_GLITCH_WARNINGS + comp_warn(dev, "nothing to copy, src_frames: %u, sink_frames: %u", + src_frames, sink_frames); +#endif + sof_dma_reload(dd->dma, dd->chan_index, 0); + 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 trigger copy failed"); + + if (dai_dma_cb(dd, dev, copy_bytes, converter) == SOF_DMA_CB_STATUS_END) + sof_dma_stop(dd->dma, dd->chan_index); + + ret = sof_dma_reload(dd->dma, dd->chan_index, copy_bytes); + if (ret < 0) { + dai_report_reload_xrun(dd, dev, copy_bytes); + return ret; + } + + 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_common_copy(dd, dev, NULL); +} + +/** + * \brief Get DAI parameters and configure timestamping + * \param[in, out] dev DAI device. + * \return Error code. + * + * This function retrieves various DAI parameters such as type, direction, index, and DMA + * controller information those are needed when configuring HW timestamping. Note that + * DAI must be prepared before this function is used (for DMA information). If not, an error + * is returned. + */ +int dai_common_ts_config_op(struct dai_data *dd, struct comp_dev *dev) +{ + struct ipc_config_dai *dai = &dd->ipc_config; + struct dai_ts_cfg *cfg = &dd->ts_config; + + comp_dbg(dev, "dai_ts_config()"); + if (dd->chan_index < 0) { + comp_err(dev, "No DMA channel information"); + return -EINVAL; + } + + switch (dai->type) { + case SOF_DAI_INTEL_SSP: + cfg->type = DAI_INTEL_SSP; + break; + case SOF_DAI_INTEL_ALH: + cfg->type = DAI_INTEL_ALH; + break; + case SOF_DAI_INTEL_DMIC: + cfg->type = DAI_INTEL_DMIC; + break; + default: + comp_err(dev, "not supported dai type"); + return -EINVAL; + } + + cfg->direction = dai->direction; + cfg->index = dd->dai->index; + cfg->dma_id = dd->dma->plat_data.id; + cfg->dma_chan_index = dd->chan_index; + cfg->dma_chan_count = dd->dma->plat_data.channels; + + return dai_ts_config(dd->dai->dev, cfg); +} + +static int dai_ts_config_op(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_common_ts_config_op(dd, dev); +} + +int dai_common_ts_start(struct dai_data *dd, struct comp_dev *dev) +{ + return dai_ts_start(dd->dai->dev, (struct dai_ts_cfg *)&dd->ts_config); +} + +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_common_ts_start(dd, dev); +} + +int dai_common_ts_get(struct dai_data *dd, struct comp_dev *dev, struct dai_ts_data *tsd) +{ + struct dai_ts_cfg *cfg = (struct dai_ts_cfg *)&dd->ts_config; + + return dai_ts_get(dd->dai->dev, cfg, tsd); +} + +static int dai_ts_get_op(struct comp_dev *dev, struct dai_ts_data *tsd) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_ts_get()"); + + return dai_common_ts_get(dd, dev, tsd); +} + +int dai_common_ts_stop(struct dai_data *dd, struct comp_dev *dev) +{ + return dai_ts_stop(dd->dai->dev, (struct dai_ts_cfg *)&dd->ts_config); +} + +static int dai_ts_stop_op(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_ts_stop()"); + + return dai_common_ts_stop(dd, dev); +} + +uint32_t dai_get_init_delay_ms(struct dai *dai) +{ + const struct dai_properties *props; + k_spinlock_key_t key; + uint32_t init_delay; + + if (!dai) + return 0; + + key = k_spin_lock(&dai->lock); + props = dai_get_properties(dai->dev, 0, 0); + init_delay = props->reg_init_delay; + k_spin_unlock(&dai->lock, key); + + return init_delay; +} + +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); + uint64_t ret = 0; + bool source = dev->direction == SOF_IPC_STREAM_CAPTURE; + + /* Return value only if direction and stream number match. + * The dai supports only one stream. + */ + if (stream_no == 0 && source == input) + ret = dd->total_data_processed; + + return ret; +} + +#ifdef CONFIG_IPC_MAJOR_4 +__cold +int dai_zephyr_unbind(struct dai_data *dd, struct comp_dev *dev, struct bind_info *unbind_data) +{ + struct ipc4_module_bind_unbind *bu; + int buf_id; + + assert_can_be_cold(); + + bu = unbind_data->ipc4_data; + buf_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue); + + if (dd && dd->local_buffer) { + if (buf_get_id(dd->local_buffer) == buf_id) { + comp_dbg(dev, "local_buffer %x unbound", buf_id); + dd->local_buffer = NULL; + } + } + + return 0; +} +#endif /* CONFIG_IPC_MAJOR_4 */ + +DECLARE_TR_CTX(dai_comp_tr, SOF_UUID(dai_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_dai = { + .type = SOF_COMP_DAI, + .uid = SOF_RT_UUID(dai_uuid), + .tctx = &dai_comp_tr, + .ops = { + .create = dai_new, + .free = dai_free, + .params = dai_params, + .dai_get_hw_params = dai_comp_get_hw_params, + .trigger = dai_comp_trigger, + .copy = dai_copy, + .prepare = dai_prepare, + .reset = dai_reset, + .position = dai_position, + .dai_config = dai_config, + .dai_ts_config = dai_ts_config_op, + .dai_ts_start = dai_ts_start_op, + .dai_ts_stop = dai_ts_stop_op, + .dai_ts_get = dai_ts_get_op, + .get_total_data_processed = dai_get_processed_data, +}, +}; + +static SHARED_DATA struct comp_driver_info comp_dai_info = { + .drv = &comp_dai, +}; + +UT_STATIC void sys_comp_dai_init(void) +{ + comp_register(platform_shared_get(&comp_dai_info, sizeof(comp_dai_info))); +} + +DECLARE_MODULE(sys_comp_dai_init); +SOF_MODULE_INIT(dai, sys_comp_dai_init); diff --git a/src/audio/dai.c b/src/audio/dai.c deleted file mode 100644 index 2a28df4de723..000000000000 --- a/src/audio/dai.c +++ /dev/null @@ -1,913 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component_ext.h> -#include <sof/audio/format.h> -#include <sof/audio/pcm_converter.h> -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/edma.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -static const struct comp_driver comp_dai; - -/* c2b00d27-ffbc-4150-a51a-245c79c5e54b */ -DECLARE_SOF_UUID("dai", dai_comp_uuid, 0xc2b00d27, 0xffbc, 0x4150, - 0xa5, 0x1a, 0x24, 0x5c, 0x79, 0xc5, 0xe5, 0x4b); - -struct dai_data { - /* local DMA config */ - struct dma_chan_data *chan; - uint32_t stream_id; - struct dma_sg_config config; - struct comp_buffer *dma_buffer; - struct comp_buffer *local_buffer; - struct timestamp_cfg ts_config; - struct dai *dai; - struct dma *dma; - enum sof_ipc_frame frame_fmt; - int xrun; /* true if we are doing xrun recovery */ - - pcm_converter_func process; /* processing function */ - - uint32_t dai_pos_blks; /* position in bytes (nearest block) */ - uint64_t start_position; /* position on start */ - - /* host can read back this value without IPC */ - uint64_t *dai_pos; - - uint64_t wallclock; /* wall clock at stream start */ -}; - -/* this is called by DMA driver every time descriptor has completed */ -static void dai_dma_cb(void *arg, enum notify_id type, void *data) -{ - struct dma_cb_data *next = data; - struct comp_dev *dev = arg; - struct dai_data *dd = comp_get_drvdata(dev); - uint32_t bytes = next->elem.size; - uint32_t sink_bytes; - uint32_t samples = bytes / get_sample_bytes(dd->frame_fmt); - void *buffer_ptr; - - comp_dbg(dev, "dai_dma_cb()"); - - next->status = DMA_CB_STATUS_RELOAD; - - /* stop dma copy for pause/stop/xrun */ - if (dev->state != COMP_STATE_ACTIVE || dd->xrun) { - /* stop the DAI */ - dai_trigger(dd->dai, COMP_TRIGGER_STOP, dev->direction); - - /* tell DMA not to reload */ - next->status = DMA_CB_STATUS_END; - } - - /* 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(dd->dma_buffer); - - return; - } - - sink_bytes = samples * - audio_stream_sample_bytes(&dd->local_buffer->stream); - - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - dma_buffer_copy_to(dd->local_buffer, sink_bytes, - dd->dma_buffer, bytes, - dd->process, samples); - - buffer_ptr = dd->local_buffer->stream.r_ptr; - } else { - dma_buffer_copy_from(dd->dma_buffer, bytes, dd->local_buffer, - sink_bytes, dd->process, samples); - - buffer_ptr = dd->local_buffer->stream.w_ptr; - } - - /* update host position (in bytes offset) for drivers */ - dev->position += bytes; - if (dd->dai_pos) { - dd->dai_pos_blks += bytes; - *dd->dai_pos = dd->dai_pos_blks + - (char *)buffer_ptr - - (char *)dd->dma_buffer->stream.addr; - } -} - -static struct comp_dev *dai_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct comp_dev *dev; - struct sof_ipc_comp_dai *dai; - struct sof_ipc_comp_dai *ipc_dai = (struct sof_ipc_comp_dai *)comp; - struct dai_data *dd; - uint32_t dir, caps, dma_dev; - int ret; - - comp_cl_dbg(&comp_dai, "dai_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_dai)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_dai); - - dai = COMP_GET_IPC(dev, sof_ipc_comp_dai); - ret = memcpy_s(dai, sizeof(*dai), ipc_dai, - sizeof(struct sof_ipc_comp_dai)); - assert(!ret); - - dd = rzalloc(SOF_MEM_ZONE_RUNTIME, 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() error: dai_get() failed to create DAI."); - goto error; - } - - /* request GP LP DMA with shared access privilege */ - dir = dai->direction == SOF_IPC_STREAM_PLAYBACK ? - DMA_DIR_MEM_TO_DEV : DMA_DIR_DEV_TO_MEM; - - caps = dai_get_info(dd->dai, DAI_INFO_DMA_CAPS); - dma_dev = dai_get_info(dd->dai, DAI_INFO_DMA_DEV); - - dd->dma = dma_get(dir, caps, dma_dev, DMA_ACCESS_SHARED); - if (!dd->dma) { - comp_cl_err(&comp_dai, "dai_new() error: dma_get() failed to get shared access to DMA."); - goto error; - } - - dma_sg_init(&dd->config.elem_array); - dd->frame_fmt = ipc_dai->config.frame_fmt; - dd->dai_pos = NULL; - dd->dai_pos_blks = 0; - dd->xrun = 0; - dd->chan = NULL; - - dev->state = COMP_STATE_READY; - return dev; - -error: - rfree(dd); - rfree(dev); - return NULL; -} - -static void dai_free(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - if (dd->chan) { - notifier_unregister(dev, dd->chan, NOTIFIER_ID_DMA_COPY); - dma_channel_put(dd->chan); - } - - dma_put(dd->dma); - - dai_put(dd->dai); - - rfree(dd); - rfree(dev); -} - -static inline 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); - int ret = 0; - - comp_dbg(dev, "dai_hw_params()"); - - /* fetching hw dai stream params */ - ret = dai_get_hw_params(dd->dai, params, dir); - if (ret < 0) { - comp_err(dev, "dai_comp_get_hw_params() error: dai_get_hw_params failed"); - return ret; - } - - /* dai_comp_get_hw_params() function fetches hardware dai parameters, - * which then are propagating back through the pipeline, so that any - * component can convert specific stream parameter. Here, we overwrite - * frame_fmt hardware parameter as DAI component is able to convert - * stream with different frame_fmt's (using pcm converter) - */ - if (dd->frame_fmt) - params->frame_fmt = dd->frame_fmt; - - return 0; -} - -static int dai_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct sof_ipc_stream_params hw_params; - - dai_comp_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 - * means that it can vary, so any value is acceptable. We do not check - * format parameter, because DAI is able to change format using - * pcm_converter functions. - */ - if (hw_params.rate && hw_params.rate != params->rate) { - comp_err(dev, "dai_verify_params() error: pcm rate parameter does not match hardware rate"); - return -EINVAL; - } - - if (hw_params.channels && hw_params.channels != params->channels) { - comp_err(dev, "dai_verify_params() error: pcm channels parameter does not match hardware channels"); - return -EINVAL; - } - - /* set component period frames */ - component_set_period_frames(dev, params->rate); - - return 0; -} - -/* set component audio SSP and DMA configuration */ -static int dai_playback_params(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; - uint32_t local_fmt = dd->local_buffer->stream.frame_fmt; - uint32_t fifo; - int err; - - /* set processing function */ - dd->process = pcm_get_conversion_function(local_fmt, dd->frame_fmt); - - /* set up DMA configuration */ - config->direction = DMA_DIR_MEM_TO_DEV; - config->src_width = get_sample_bytes(dd->frame_fmt); - config->dest_width = config->src_width; - config->cyclic = 1; - config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); - config->dest_dev = dai_get_handshake(dd->dai, dev->direction, - dd->stream_id); - config->is_scheduling_source = comp_is_scheduling_source(dev); - config->period = dev->pipeline->ipc_pipe.period; - - comp_info(dev, "dai_playback_params() dest_dev = %d stream_id = %d src_width = %d dest_width = %d", - config->dest_dev, dd->stream_id, - config->src_width, config->dest_width); - - if (!config->elem_array.elems) { - fifo = dai_get_fifo(dd->dai, dev->direction, - dd->stream_id); - - comp_info(dev, "dai_playback_params() fifo %X", fifo); - - err = dma_sg_alloc(&config->elem_array, SOF_MEM_ZONE_RUNTIME, - config->direction, - period_count, - period_bytes, - (uintptr_t)(dd->dma_buffer->stream.addr), - fifo); - if (err < 0) { - comp_err(dev, "dai_playback_params() error: dma_sg_alloc() failed with err = %d", - err); - return err; - } - } - - return 0; -} - -static int dai_capture_params(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; - uint32_t local_fmt = dd->local_buffer->stream.frame_fmt; - uint32_t fifo; - int err; - - /* set processing function */ - dd->process = pcm_get_conversion_function(dd->frame_fmt, local_fmt); - - /* set up DMA configuration */ - config->direction = DMA_DIR_DEV_TO_MEM; - config->cyclic = 1; - config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); - config->src_dev = dai_get_handshake(dd->dai, dev->direction, - dd->stream_id); - config->is_scheduling_source = comp_is_scheduling_source(dev); - config->period = dev->pipeline->ipc_pipe.period; - - /* TODO: Make this code platform-specific or move it driver callback */ - if (dai_get_info(dd->dai, DAI_INFO_TYPE) == SOF_DAI_INTEL_DMIC) { - /* For DMIC the DMA src and dest widths should always be 4 bytes - * due to 32 bit FIFO packer. Setting width to 2 bytes for - * 16 bit format would result in recording at double rate. - */ - config->src_width = 4; - config->dest_width = 4; - } else { - config->src_width = get_sample_bytes(dd->frame_fmt); - config->dest_width = config->src_width; - } - - comp_info(dev, "dai_capture_params() src_dev = %d stream_id = %d src_width = %d dest_width = %d", - config->src_dev, dd->stream_id, - config->src_width, config->dest_width); - - if (!config->elem_array.elems) { - fifo = dai_get_fifo(dd->dai, dev->direction, - dd->stream_id); - - comp_info(dev, "dai_capture_params() fifo %X", fifo); - - err = dma_sg_alloc(&config->elem_array, SOF_MEM_ZONE_RUNTIME, - config->direction, - period_count, - period_bytes, - (uintptr_t)(dd->dma_buffer->stream.addr), - fifo); - if (err < 0) { - comp_err(dev, "dai_capture_params() error: dma_sg_alloc() failed with err = %d", - err); - return err; - } - } - - return 0; -} - -static int dai_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct dai_data *dd = comp_get_drvdata(dev); - uint32_t frame_size; - uint32_t period_count; - uint32_t period_bytes; - uint32_t buffer_size; - uint32_t addr_align; - uint32_t align; - int err; - - comp_dbg(dev, "dai_params()"); - - err = dai_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "dai_params(): pcm params verification failed."); - return -EINVAL; - } - - 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); - - /* check if already configured */ - if (dev->state == COMP_STATE_PREPARE) { - comp_info(dev, "dai_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() error: Component is not in init state."); - return -EINVAL; - } - - err = dma_get_attribute(dd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, - &addr_align); - if (err < 0) { - comp_err(dev, "dai_params() error: could not get dma buffer address alignment, err = %d", - err); - return err; - } - - err = dma_get_attribute(dd->dma, DMA_ATTR_BUFFER_ALIGNMENT, &align); - if (err < 0 || !align) { - comp_err(dev, "dai_params() error: could not get valid dma buffer alignment, err = %d, align = %u", - err, align); - return -EINVAL; - } - - err = dma_get_attribute(dd->dma, DMA_ATTR_BUFFER_PERIOD_COUNT, - &period_count); - if (err < 0 || !period_count) { - comp_err(dev, "dai_params() error: could not get valid dma buffer period count, err = %d, period_count = %u", - err, period_count); - return -EINVAL; - } - - /* calculate frame size */ - frame_size = get_frame_bytes(dd->frame_fmt, - dd->local_buffer->stream.channels); - - /* calculate period size */ - period_bytes = dev->frames * frame_size; - if (!period_bytes) { - comp_err(dev, "dai_params() error: invalid period_bytes."); - return -EINVAL; - } - - /* calculate DMA buffer size */ - buffer_size = ALIGN_UP(period_count * period_bytes, align); - - /* alloc DMA buffer or change its size if exists */ - if (dd->dma_buffer) { - err = buffer_set_size(dd->dma_buffer, buffer_size); - if (err < 0) { - comp_err(dev, "dai_params() error: buffer_set_size() failed, buffer_size = %u", - buffer_size); - return err; - } - } else { - dd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, - addr_align); - if (!dd->dma_buffer) { - comp_err(dev, "dai_params() error: failed to alloc dma buffer"); - return -ENOMEM; - } - } - - return dev->direction == SOF_IPC_STREAM_PLAYBACK ? - dai_playback_params(dev, period_bytes, period_count) : - dai_capture_params(dev, period_bytes, period_count); -} - -static int dai_prepare(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - int ret = 0; - - comp_dbg(dev, "dai_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; - - dev->position = 0; - - if (!dd->chan) { - comp_err(dev, "dai_prepare() error: Missing dd->chan."); - comp_set_state(dev, COMP_TRIGGER_RESET); - return -EINVAL; - } - - if (!dd->config.elem_array.elems) { - comp_err(dev, "dai_prepare() error: Missing dd->config.elem_array.elems."); - comp_set_state(dev, COMP_TRIGGER_RESET); - return -EINVAL; - } - - /* clear dma buffer to avoid pop noise */ - buffer_zero(dd->dma_buffer); - - /* dma reconfig not required if XRUN handling */ - if (dd->xrun) { - /* after prepare, we have recovered from xrun */ - dd->xrun = 0; - return ret; - } - - ret = dma_set_config(dd->chan, &dd->config); - if (ret < 0) - comp_set_state(dev, COMP_TRIGGER_RESET); - - return ret; -} - -static int dai_reset(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - struct dma_sg_config *config = &dd->config; - - comp_dbg(dev, "dai_reset()"); - - dma_sg_free(&config->elem_array); - - if (dd->dma_buffer) { - buffer_free(dd->dma_buffer); - dd->dma_buffer = NULL; - } - - dd->dai_pos_blks = 0; - if (dd->dai_pos) - *dd->dai_pos = 0; - dd->dai_pos = NULL; - dd->wallclock = 0; - dev->position = 0; - dd->xrun = 0; - comp_set_state(dev, COMP_TRIGGER_RESET); - - return 0; -} - -static void dai_update_start_position(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - /* update starting wallclock */ - platform_dai_wallclock(dev, &dd->wallclock); - - /* update start position */ - dd->start_position = dev->position; -} - -/* used to pass standard and bespoke command (with data) to component */ -static int dai_comp_trigger(struct comp_dev *dev, int cmd) -{ - struct dai_data *dd = comp_get_drvdata(dev); - int ret; - - comp_dbg(dev, "dai_comp_trigger(), 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(), START"); - - /* only start the DAI if we are not XRUN handling */ - if (dd->xrun == 0) { - /* start the DAI */ - dai_trigger(dd->dai, cmd, dev->direction); - ret = dma_start(dd->chan); - if (ret < 0) - return ret; - } else { - dd->xrun = 0; - } - - dai_update_start_position(dev); - break; - case COMP_TRIGGER_RELEASE: - /* before release, we clear the buffer data to 0s, - * then there is no history data sent out after release. - * this is only supported at capture mode. - */ - if (dev->direction == SOF_IPC_STREAM_CAPTURE) - buffer_zero(dd->dma_buffer); - - /* only start the DAI if we are not XRUN handling */ - if (dd->xrun == 0) { - /* recover valid start position */ - ret = dma_release(dd->chan); - if (ret < 0) - return ret; - - /* start the DAI */ - dai_trigger(dd->dai, cmd, dev->direction); - ret = dma_start(dd->chan); - if (ret < 0) - return ret; - } else { - dd->xrun = 0; - } - - dai_update_start_position(dev); - break; - case COMP_TRIGGER_XRUN: - comp_info(dev, "dai_comp_trigger(), XRUN"); - dd->xrun = 1; - - /* fallthrough */ - case COMP_TRIGGER_PAUSE: - case COMP_TRIGGER_STOP: - comp_dbg(dev, "dai_comp_trigger(), PAUSE/STOP"); - ret = dma_stop(dd->chan); - dai_trigger(dd->dai, cmd, dev->direction); - break; - default: - break; - } - - return ret; -} - -/* report xrun occurrence */ -static void dai_report_xrun(struct comp_dev *dev, uint32_t bytes) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - comp_err(dev, "dai_report_xrun() error: underrun due to no data available"); - comp_underrun(dev, dd->local_buffer, bytes); - } else { - comp_err(dev, "dai_report_xrun() error: overrun due to no data available"); - comp_overrun(dev, dd->local_buffer, bytes); - } -} - -/* copy and process stream data from source to sink buffers */ -static int dai_copy(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - uint32_t avail_bytes = 0; - uint32_t free_bytes = 0; - uint32_t copy_bytes = 0; - uint32_t src_samples; - uint32_t sink_samples; - int ret = 0; - uint32_t flags = 0; - - comp_dbg(dev, "dai_copy()"); - - /* get data sizes from DMA */ - ret = dma_get_data_size(dd->chan, &avail_bytes, &free_bytes); - if (ret < 0) { - dai_report_xrun(dev, 0); - return ret; - } - - buffer_lock(dd->local_buffer, &flags); - - /* calculate minimum size to copy */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - src_samples = dd->local_buffer->stream.avail / - audio_stream_sample_bytes(&dd->local_buffer->stream); - sink_samples = free_bytes / get_sample_bytes(dd->frame_fmt); - copy_bytes = MIN(src_samples, sink_samples) * - get_sample_bytes(dd->frame_fmt); - } else { - src_samples = avail_bytes / get_sample_bytes(dd->frame_fmt); - sink_samples = dd->local_buffer->stream.free / - audio_stream_sample_bytes(&dd->local_buffer->stream); - copy_bytes = MIN(src_samples, sink_samples) * - get_sample_bytes(dd->frame_fmt); - } - - buffer_unlock(dd->local_buffer, flags); - - comp_dbg(dev, "dai_copy(), copy_bytes = 0x%x", copy_bytes); - - /* return if it's not stream start */ - if (!copy_bytes && dd->start_position != dev->position) - return 0; - - ret = dma_copy(dd->chan, copy_bytes, 0); - if (ret < 0) { - dai_report_xrun(dev, copy_bytes); - return ret; - } - - return ret; -} - -static int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - /* TODO: improve accuracy by adding current DMA position */ - posn->dai_posn = dev->position; - - /* set stream start wallclock */ - posn->wallclock = dd->wallclock; - - return 0; -} - -static int dai_config(struct comp_dev *dev, struct sof_ipc_dai_config *config) -{ - struct sof_ipc_comp_config *dconfig = dev_comp_config(dev); - struct dai_data *dd = comp_get_drvdata(dev); - struct sof_ipc_comp_dai *dai = COMP_GET_IPC(dev, sof_ipc_comp_dai); - int channel = 0; - int handshake; - - comp_info(dev, "dai_config() dai %d.%d", - config->type, config->dai_index); - - /* cannot configure DAI while active */ - if (dev->state == COMP_STATE_ACTIVE) { - comp_err(dev, "dai_config() error: Component is in active state."); - return -EINVAL; - } - - switch (config->type) { - case SOF_DAI_INTEL_SSP: - /* set dma burst elems to slot number */ - dd->config.burst_elems = config->ssp.tdm_slots; - break; - case SOF_DAI_INTEL_DMIC: - comp_dbg(dev, "dai_config(), config->type = SOF_DAI_INTEL_DMIC"); - - /* We can use always the largest burst length. */ - dd->config.burst_elems = 8; - - comp_info(dev, "dai_config(), config->dmic.fifo_bits = %u config->dmic.num_pdm_active = %u", - config->dmic.fifo_bits, - config->dmic.num_pdm_active); - break; - case SOF_DAI_INTEL_HDA: - channel = config->hda.link_dma_ch; - comp_info(dev, "dai_config(), channel = %d", channel); - - /* - * For HDA DAIs, the driver sends the DAI_CONFIG IPC - * during every link hw_params and hw_free, apart from the - * the first DAI_CONFIG IPC sent during topology parsing. - * Free the channel that is currently in use before - * assigning the new one. - */ - if (dd->chan) { - dma_channel_put(dd->chan); - dd->chan = NULL; - } - break; - case SOF_DAI_INTEL_ALH: - /* SDW HW FIFO always requires 32bit MSB aligned sample data for - * all formats, such as 8/16/24/32 bits. - */ - dconfig->frame_fmt = SOF_IPC_FRAME_S32_LE; - dd->frame_fmt = dconfig->frame_fmt; - - dd->config.burst_elems = - dd->dai->plat_data.fifo[dai->direction].depth; - - /* As with HDA, the DMA channel is assigned in runtime, - * not during topology parsing. - */ - channel = config->alh.stream_id; - dd->stream_id = config->alh.stream_id; - comp_info(dev, "dai_config(), channel = %d", channel); - break; - case SOF_DAI_IMX_SAI: - handshake = dai_get_handshake(dd->dai, dai->direction, - dd->stream_id); - channel = EDMA_HS_GET_CHAN(handshake); - - dd->config.burst_elems = - dd->dai->plat_data.fifo[dai->direction].depth; - break; - case SOF_DAI_IMX_ESAI: - handshake = dai_get_handshake(dd->dai, dai->direction, - dd->stream_id); - channel = EDMA_HS_GET_CHAN(handshake); - - dd->config.burst_elems = - dd->dai->plat_data.fifo[dai->direction].depth; - break; - default: - /* other types of DAIs not handled for now */ - comp_err(dev, "dai_config() error: Unknown dai type"); - break; - } - - platform_shared_commit(dd->dai, sizeof(*dd->dai)); - - if (channel != DMA_CHAN_INVALID) { - if (dd->chan) - /* remove callback */ - notifier_unregister(dev, dd->chan, - NOTIFIER_ID_DMA_COPY); - else - /* get dma channel at first config only */ - dd->chan = dma_channel_get(dd->dma, channel); - - if (!dd->chan) { - comp_err(dev, "dai_config() error: dma_channel_get() failed"); - dd->chan = NULL; - return -EIO; - } - - /* setup callback */ - notifier_register(dev, dd->chan, NOTIFIER_ID_DMA_COPY, - dai_dma_cb); - } - - return dai_set_config(dd->dai, config); -} - -static int dai_ts_config(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - struct timestamp_cfg *cfg = &dd->ts_config; - struct sof_ipc_comp_dai *dai = COMP_GET_IPC(dev, sof_ipc_comp_dai); - - comp_dbg(dev, "dai_ts_config()"); - cfg->type = dd->dai->drv->type; - cfg->direction = dai->direction; - cfg->index = dd->dai->index; - cfg->dma_id = dd->dma->plat_data.id; - cfg->dma_chan_index = dd->chan->index; - cfg->dma_chan_count = dd->dma->plat_data.channels; - if (!dd->dai->drv->ts_ops.ts_config) - return -ENXIO; - - return dd->dai->drv->ts_ops.ts_config(dd->dai, cfg); -} - -static int dai_ts_start(struct comp_dev *dev) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - comp_dbg(dev, "dai_ts_start()"); - 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) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - comp_dbg(dev, "dai_ts_stop()"); - 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) -{ - struct dai_data *dd = comp_get_drvdata(dev); - - comp_dbg(dev, "dai_ts_get()"); - 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 const struct comp_driver comp_dai = { - .type = SOF_COMP_DAI, - .uid = SOF_UUID(dai_comp_uuid), - .ops = { - .new = dai_new, - .free = dai_free, - .params = dai_params, - .dai_get_hw_params = dai_comp_get_hw_params, - .trigger = dai_comp_trigger, - .copy = dai_copy, - .prepare = dai_prepare, - .reset = dai_reset, - .dai_config = dai_config, - .position = dai_position, - .dai_ts_config = dai_ts_config, - .dai_ts_start = dai_ts_start, - .dai_ts_stop = dai_ts_stop, - .dai_ts_get = dai_ts_get, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_dai_info = { - .drv = &comp_dai, -}; - -static void sys_comp_dai_init(void) -{ - comp_register(platform_shared_get(&comp_dai_info, - sizeof(comp_dai_info))); -} - -DECLARE_MODULE(sys_comp_dai_init); diff --git a/src/audio/data_blob.c b/src/audio/data_blob.c new file mode 100644 index 000000000000..399244106f95 --- /dev/null +++ b/src/audio/data_blob.c @@ -0,0 +1,667 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jyri Sarha <jyri.sarha@intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/sof.h> +#include <rtos/alloc.h> +#include <rtos/symbol.h> +#include <ipc/topology.h> +#include <ipc/control.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> + +LOG_MODULE_REGISTER(data_blob, CONFIG_SOF_LOG_LEVEL); + +/** \brief Struct handler for large component configs */ +struct comp_data_blob_handler { + struct comp_dev *dev; /**< audio component device */ + uint32_t data_size; /**< size of component's data blob */ + uint32_t new_data_size; /**< size of component's new data blob */ + void *data; /**< pointer to data blob */ + void *data_new; /**< pointer to new data blob */ + bool data_ready; /**< set when data blob is fully received */ + uint32_t data_pos; /**< indicates a data position in data + * sending/receiving process + */ + uint32_t single_blob:1; /**< Allocate only one blob. Module can not + * be active while reconfguring. + */ + void *(*alloc)(size_t size); /**< alternate allocator, maybe null */ + void (*free)(void *buf); /**< alternate free(), maybe null */ + + /** validator for new data, maybe null */ + int (*validator)(struct comp_dev *dev, void *new_data, uint32_t new_data_size); +}; + +static void comp_free_data_blob(struct comp_data_blob_handler *blob_handler) +{ + assert(blob_handler); + + if (!blob_handler->data) + return; + + blob_handler->free(blob_handler->data); + blob_handler->free(blob_handler->data_new); + blob_handler->data = NULL; + blob_handler->data_new = NULL; + blob_handler->data_size = 0; +} + +void comp_data_blob_set_validator(struct comp_data_blob_handler *blob_handler, + int (*validator)(struct comp_dev *dev, void *new_data, + uint32_t new_data_size)) +{ + assert(blob_handler); + + blob_handler->validator = validator; +} +EXPORT_SYMBOL(comp_data_blob_set_validator); + +void *comp_get_data_blob(struct comp_data_blob_handler *blob_handler, + size_t *size, uint32_t *crc) +{ + assert(blob_handler); + + comp_dbg(blob_handler->dev, "comp_get_data_blob()"); + + if (size) + *size = 0; + + /* Function returns new data blob if available */ + if (comp_is_new_data_blob_available(blob_handler)) { + comp_dbg(blob_handler->dev, "new data available"); + + /* Free "old" data blob and set data to data_new pointer */ + blob_handler->free(blob_handler->data); + blob_handler->data = blob_handler->data_new; + blob_handler->data_size = blob_handler->new_data_size; + + blob_handler->data_new = NULL; + blob_handler->data_ready = false; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + } + + /* If data is available we calculate crc32 when crc pointer is given */ + if (blob_handler->data) { + if (crc) + *crc = crc32(0, blob_handler->data, + blob_handler->data_size); + } else { + /* If blob_handler->data is equal to NULL and there is no new + * data blob it means that component hasn't got any config yet. + * Function returns NULL in that case. + */ + comp_warn(blob_handler->dev, "blob_handler->data is not set."); + } + + if (size) + *size = blob_handler->data_size; + + return blob_handler->data; +} +EXPORT_SYMBOL(comp_get_data_blob); + +bool comp_is_new_data_blob_available(struct comp_data_blob_handler + *blob_handler) +{ + assert(blob_handler); + + comp_dbg(blob_handler->dev, "entry"); + + /* New data blob is available when new data blob is allocated (data_new + * is not NULL), and the component has received all required chunks of data + * (data_ready is set to TRUE) + */ + if (blob_handler->data_new && blob_handler->data_ready) + return true; + + return false; +} +EXPORT_SYMBOL(comp_is_new_data_blob_available); + +bool comp_is_current_data_blob_valid(struct comp_data_blob_handler + *blob_handler) +{ + return !!blob_handler->data; +} +EXPORT_SYMBOL(comp_is_current_data_blob_valid); + +int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, + uint32_t size, const void *init_data) +{ + int ret; + + assert(blob_handler); + + comp_free_data_blob(blob_handler); + + if (!size) + return 0; + + /* Data blob allocation */ + blob_handler->data = blob_handler->alloc(size); + if (!blob_handler->data) { + comp_err(blob_handler->dev, "model->data allocation failed"); + return -ENOMEM; + } + + /* If init_data is given, data will be initialized with it. In other + * case, data will be set to zero. + */ + if (init_data) { + ret = memcpy_s(blob_handler->data, size, init_data, size); + assert(!ret); + } else { + bzero(blob_handler->data, size); + } + + blob_handler->data_new = NULL; + blob_handler->data_size = size; + blob_handler->new_data_size = 0; + blob_handler->validator = NULL; + + return 0; +} +EXPORT_SYMBOL(comp_init_data_blob); + +int comp_data_blob_set(struct comp_data_blob_handler *blob_handler, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment_in, size_t fragment_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 + int ret; + + if (!blob_handler) + return -EINVAL; + +#if CONFIG_IPC_MAJOR_3 + if (cdata->cmd != SOF_CTRL_CMD_BINARY) { + comp_err(blob_handler->dev, "illegal control command"); + return -EINVAL; + } +#endif + + comp_dbg(blob_handler->dev, "pos = %d, fragment size = %zu", + pos, fragment_size); + + /* Check that there is no work-in-progress previous request */ + if (blob_handler->data_new && + (pos == MODULE_CFG_FRAGMENT_FIRST || pos == MODULE_CFG_FRAGMENT_SINGLE)) { + comp_err(blob_handler->dev, "busy with previous request"); + return -EBUSY; + } + + /* In single blob mode the component can not be reconfigured if the component is active. + */ + if (blob_handler->single_blob && blob_handler->dev->state == COMP_STATE_ACTIVE) { + comp_err(blob_handler->dev, "on the fly updates forbidden in single blob mode"); + return -EBUSY; + } + + /* in case when the current package is the first, we should allocate + * memory for whole model data + */ + if (pos == MODULE_CFG_FRAGMENT_FIRST || pos == MODULE_CFG_FRAGMENT_SINGLE) { + /* in case when required model size is equal to zero we do not + * allocate memory and should just return 0. + * + * Set cmd with cdata->data->size equal to 0 is possible in + * following situation: + * 1. At first boot and topology parsing stage, the driver will + * read all initial values of DSP kcontrols via IPC. Driver send + * get_model() cmd to components. If we do not initialize + * component earlier driver will get "model" with size 0. + * 2. When resuming from runtime suspended, the driver will + * restore all pipelines and kcontrols, for the tlv binary + * kcontrols, it will call the set_model() with the cached value + * and size (0 if it is not updated by any actual end user + * sof-ctl settings) - basically driver will send set_model() + * command with size equal to 0. + */ + if (!fragment_size) + return 0; + + if (blob_handler->single_blob) { + if (data_offset_size != blob_handler->data_size) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } else { + blob_handler->data_new = blob_handler->data; + blob_handler->data = NULL; + } + } + + if (!blob_handler->data_new) { + blob_handler->data_new = blob_handler->alloc(data_offset_size); + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, "blob_handler->data_new allocation failed."); + return -ENOMEM; + } + } + + blob_handler->new_data_size = data_offset_size; + blob_handler->data_ready = false; + blob_handler->data_pos = 0; + } + + /* return an error in case when we do not have allocated memory for model data */ + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, "buffer not allocated"); + return -ENOMEM; + } + + ret = memcpy_s((char *)blob_handler->data_new + blob_handler->data_pos, + blob_handler->new_data_size - blob_handler->data_pos, + fragment, fragment_size); + if (ret) { + comp_err(blob_handler->dev, "failed to copy fragment"); + return ret; + } + + blob_handler->data_pos += fragment_size; + + if (pos == MODULE_CFG_FRAGMENT_SINGLE || pos == MODULE_CFG_FRAGMENT_LAST) { + comp_dbg(blob_handler->dev, "final package received"); + if (blob_handler->validator) { + comp_dbg(blob_handler->dev, "validating new data..."); + ret = blob_handler->validator(blob_handler->dev, blob_handler->data_new, + blob_handler->new_data_size); + if (ret < 0) { + comp_err(blob_handler->dev, "new data is invalid! discarding it..."); + blob_handler->free(blob_handler->data_new); + blob_handler->data_new = NULL; + return ret; + } + } + + /* If component state is READY we can omit old + * configuration immediately. When in playback/capture + * the new configuration presence is checked in copy(). + */ + if (blob_handler->dev->state == COMP_STATE_READY) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } + + /* If there is no existing configuration the received + * can be set to current immediately. It will be + * applied in prepare() when streaming starts. + */ + if (!blob_handler->data) { + blob_handler->data = blob_handler->data_new; + blob_handler->data_size = blob_handler->new_data_size; + + blob_handler->data_new = NULL; + + /* The new configuration has been applied */ + blob_handler->data_ready = false; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + } else { + /* The new configuration is ready to be applied */ + blob_handler->data_ready = true; + } + } + + return 0; +} + +int ipc4_comp_data_blob_set(struct comp_data_blob_handler *blob_handler, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + int ret; + int valid_data_size; + + assert(blob_handler); + + comp_dbg(blob_handler->dev, + "data_offset = %d", + data_offset); + + /* in case when the current package is the first, we should allocate + * memory for whole model data + */ + if (first_block) { + if (!data_offset) + return 0; + + if (blob_handler->single_blob) { + if (data_offset != blob_handler->data_size) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } else { + blob_handler->data_new = blob_handler->data; + blob_handler->data = NULL; + } + } + + if (!blob_handler->data_new) { + blob_handler->data_new = + blob_handler->alloc(data_offset); + + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, + "blob_handler allocation failed!"); + return -ENOMEM; + } + } + + blob_handler->new_data_size = data_offset; + blob_handler->data_ready = false; + blob_handler->data_pos = 0; + + valid_data_size = last_block ? data_offset : MAILBOX_DSPBOX_SIZE; + + ret = memcpy_s((char *)blob_handler->data_new, + valid_data_size, data, valid_data_size); + assert(!ret); + + blob_handler->data_pos += valid_data_size; + } else { + /* return an error in case when we do not have allocated memory for + * model data + */ + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, + "Buffer not allocated!"); + return -ENOMEM; + } + + if (blob_handler->data_pos != data_offset) { + comp_err(blob_handler->dev, + "Wrong data offset received!"); + return -EINVAL; + } + + valid_data_size = MAILBOX_DSPBOX_SIZE; + + if (last_block) + valid_data_size = blob_handler->new_data_size - data_offset; + + ret = memcpy_s((char *)blob_handler->data_new + data_offset, + valid_data_size, data, valid_data_size); + assert(!ret); + + blob_handler->data_pos += valid_data_size; + } + + if (last_block) { + comp_dbg(blob_handler->dev, + "final package received"); + + /* If component state is READY we can omit old + * configuration immediately. When in playback/capture + * the new configuration presence is checked in copy(). + */ + if (blob_handler->dev->state == COMP_STATE_READY) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } + + /* If there is no existing configuration the received + * can be set to current immediately. It will be + * applied in prepare() when streaming starts. + */ + if (!blob_handler->data) { + blob_handler->data = blob_handler->data_new; + blob_handler->data_size = blob_handler->new_data_size; + + blob_handler->data_new = NULL; + + /* The new configuration has been applied */ + blob_handler->data_ready = false; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + } else { + /* The new configuration is ready to be applied */ + blob_handler->data_ready = true; + } + } + + return 0; +} +EXPORT_SYMBOL(comp_data_blob_set); + +int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata) +{ + int ret = 0; + + assert(blob_handler); + + comp_dbg(blob_handler->dev, "msg_index = %d, num_elems = %d, remaining = %d ", + cdata->msg_index, cdata->num_elems, + cdata->elems_remaining); + + /* Check that there is no work-in-progress previous request */ + if (blob_handler->data_new && cdata->msg_index == 0) { + comp_err(blob_handler->dev, "busy with previous request"); + return -EBUSY; + } + + /* In single blob mode the component can not be reconfigured if + * the component is active. + */ + if (blob_handler->single_blob && + blob_handler->dev->state == COMP_STATE_ACTIVE) { + comp_err(blob_handler->dev, "on the fly updates forbidden in single blob mode"); + return -EBUSY; + } + + /* in case when the current package is the first, we should allocate + * memory for whole model data + */ + if (!cdata->msg_index) { + /* in case when required model size is equal to zero we do not + * allocate memory and should just return 0. + * + * Set cmd with cdata->data->size equal to 0 is possible in + * following situation: + * 1. At first boot and topology parsing stage, the driver will + * read all initial values of DSP kcontrols via IPC. Driver send + * get_model() cmd to components. If we do not initialize + * component earlier driver will get "model" with size 0. + * 2. When resuming from runtime suspended, the driver will + * restore all pipelines and kcontrols, for the tlv binary + * kcontrols, it will call the set_model() with the cached value + * and size (0 if it is not updated by any actual end user + * sof-ctl settings) - basically driver will send set_model() + * command with size equal to 0. + */ + if (!cdata->data->size) + return 0; + + if (blob_handler->single_blob) { + if (cdata->data->size != blob_handler->data_size) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } else { + blob_handler->data_new = blob_handler->data; + blob_handler->data = NULL; + } + } + + if (!blob_handler->data_new) { + blob_handler->data_new = + blob_handler->alloc(cdata->data->size); + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, "blob_handler->data_new allocation failed."); + return -ENOMEM; + } + } + + blob_handler->new_data_size = cdata->data->size; + blob_handler->data_ready = false; + blob_handler->data_pos = 0; + } + + /* return an error in case when we do not have allocated memory for + * model data + */ + if (!blob_handler->data_new) { + comp_err(blob_handler->dev, "buffer not allocated"); + return -ENOMEM; + } + + ret = memcpy_s((char *)blob_handler->data_new + blob_handler->data_pos, + blob_handler->new_data_size - blob_handler->data_pos, + cdata->data->data, cdata->num_elems); + assert(!ret); + + blob_handler->data_pos += cdata->num_elems; + + if (!cdata->elems_remaining) { + comp_dbg(blob_handler->dev, "final package received"); + + if (blob_handler->validator) { + comp_dbg(blob_handler->dev, "validating new data blob"); + ret = blob_handler->validator(blob_handler->dev, blob_handler->data_new, + blob_handler->new_data_size); + if (ret < 0) { + comp_err(blob_handler->dev, "new data blob invalid, discarding"); + blob_handler->free(blob_handler->data_new); + blob_handler->data_new = NULL; + return ret; + } + } + + /* If component state is READY we can omit old + * configuration immediately. When in playback/capture + * the new configuration presence is checked in copy(). + */ + if (blob_handler->dev->state == COMP_STATE_READY) { + blob_handler->free(blob_handler->data); + blob_handler->data = NULL; + } + + /* If there is no existing configuration the received + * can be set to current immediately. It will be + * applied in prepare() when streaming starts. + */ + if (!blob_handler->data) { + blob_handler->data = blob_handler->data_new; + blob_handler->data_size = blob_handler->new_data_size; + + blob_handler->data_new = NULL; + + /* The new configuration has been applied */ + blob_handler->data_ready = false; + blob_handler->new_data_size = 0; + blob_handler->data_pos = 0; + } else { + /* The new configuration is ready to be applied */ + blob_handler->data_ready = true; + } + } + + return 0; +} + +int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata, int size) +{ + int ret = 0; + + assert(blob_handler); + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) { + comp_err(blob_handler->dev, "comp_data_blob_set_cmd(), illegal control command"); + return -EINVAL; + } + + comp_dbg(blob_handler->dev, "msg_index = %d, num_elems = %d, remaining = %d ", + cdata->msg_index, cdata->num_elems, + cdata->elems_remaining); + + /* Copy back to user space */ + if (blob_handler->data) { + /* reset data_pos variable in case of copying first element */ + if (!cdata->msg_index) { + blob_handler->data_pos = 0; + comp_dbg(blob_handler->dev, "model data_size = 0x%x", + blob_handler->data_size); + } + + /* return an error in case of mismatch between num_elems and + * required size + */ + if (cdata->num_elems > size) { + comp_err(blob_handler->dev, "invalid cdata->num_elems %d", + cdata->num_elems); + return -EINVAL; + } + + /* copy required size of data */ + ret = memcpy_s(cdata->data->data, size, + (char *)blob_handler->data + blob_handler->data_pos, + cdata->num_elems); + assert(!ret); + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = blob_handler->data_size; + blob_handler->data_pos += cdata->num_elems; + } else { + comp_warn(blob_handler->dev, "model->data not allocated yet."); + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = 0; + } + + return ret; +} +EXPORT_SYMBOL(comp_data_blob_get_cmd); + +static void *default_alloc(size_t size) +{ + return rballoc(SOF_MEM_FLAG_USER, size); +} + +static void default_free(void *buf) +{ + rfree(buf); +} + +struct comp_data_blob_handler * +comp_data_blob_handler_new_ext(struct comp_dev *dev, bool single_blob, + void *(*alloc)(size_t size), + void (*free)(void *buf)) +{ + struct comp_data_blob_handler *handler; + + comp_dbg(dev, "entry"); + + handler = rzalloc(SOF_MEM_FLAG_USER, + sizeof(struct comp_data_blob_handler)); + + if (handler) { + handler->dev = dev; + handler->single_blob = single_blob; + handler->alloc = alloc ? alloc : default_alloc; + handler->free = free ? free : default_free; + } + + return handler; +} +EXPORT_SYMBOL(comp_data_blob_handler_new_ext); + +void comp_data_blob_handler_free(struct comp_data_blob_handler *blob_handler) +{ + if (!blob_handler) + return; + + comp_free_data_blob(blob_handler); + + rfree(blob_handler); +} +EXPORT_SYMBOL(comp_data_blob_handler_free); diff --git a/src/audio/dcblock/CMakeLists.txt b/src/audio/dcblock/CMakeLists.txt new file mode 100644 index 000000000000..7927b6913a42 --- /dev/null +++ b/src/audio/dcblock/CMakeLists.txt @@ -0,0 +1,16 @@ +if(CONFIG_COMP_DCBLOCK STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/dcblock_llext) + add_dependencies(app dcblock) + return() +endif() + +add_local_sources(sof dcblock.c) +add_local_sources(sof dcblock_generic.c) +add_local_sources(sof dcblock_hifi3.c) +add_local_sources(sof dcblock_hifi4.c) + +if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof dcblock_ipc3.c) +elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof dcblock_ipc4.c) +endif() diff --git a/src/audio/dcblock/Kconfig b/src/audio/dcblock/Kconfig new file mode 100644 index 000000000000..e67708ed9ad1 --- /dev/null +++ b/src/audio/dcblock/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_DCBLOCK + tristate "DC Blocking Filter component" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for DC Blocking Filter component. This component filters out + the DC offset which often originates from a microphone's output. + +choice + prompt "DC Blocking Filter HIFI level" + depends on COMP_DCBLOCK + default DCBLOCK_HIFI_MAX + +config DCBLOCK_HIFI_MAX + bool "Max level available in the toolchain" + +config DCBLOCK_HIFI_4 + bool "HIFI4 DCBLOCK" + +config DCBLOCK_HIFI_3 + bool "HIFI3 DCBLOCK" + +config DCBLOCK_HIFI_NONE + bool "Generic DCBLOCK, no HIFI" + +endchoice diff --git a/src/audio/dcblock/README.md b/src/audio/dcblock/README.md new file mode 100644 index 000000000000..4cbae3402540 --- /dev/null +++ b/src/audio/dcblock/README.md @@ -0,0 +1,23 @@ +# DC Block Architecture + +This directory contains the DC Blocking filter. + +## Overview + +The DC Blocker removes the DC offset (0 Hz component) from an audio signal, avoiding speaker damage and maximizing dynamic range. + +## Architecture Diagram + +```mermaid +graph LR + In[Audio Input] --> IIR[High-pass IIR Filter] + IIR --> Out[DC-Free Audio Output] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the DC Blocking Filter component (`COMP_DCBLOCK`) which filters out DC offsets often from a microphone's output. Includes selectable HIFI optimization levels (Max, HIFI4, HIFI3, Generic). +- **CMakeLists.txt**: Manages local build sources including generic and HIFI optimized versions (`dcblock_generic.c`, `dcblock_hifi3.c`, etc.) and determines the valid IPC abstraction (`dcblock_ipc3.c` vs `dcblock_ipc4.c`). Supports loadable extension generation via `llext`. +- **dcblock.toml**: Topology parameters for the DCBlock module. Defines UUID, pins, and memory limits for IPC integration. +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/dcblock.conf`, it defines the `dcblock` widget object for topology generation. It defaults to type `effect` with UUID `af:ef:09:b8:81:56:b1:42:9e:d6:04:bb:01:2d:d3:84` and enforces input/output pins configuration. +- **MATLAB Tuning (`tune/`)**: The included `.m` scripts (e.g., `sof_example_dcblock.m`) automatically determine the optimal R coefficients to achieve various high-pass cutoff frequencies (-3dB point) across supported sample rates (like 16kHz and 48kHz). These coefficients are then packed into configuration blobs. diff --git a/src/audio/dcblock/dcblock.c b/src/audio/dcblock/dcblock.c new file mode 100644 index 000000000000..5f0935a2bc29 --- /dev/null +++ b/src/audio/dcblock/dcblock.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "dcblock.h" + +LOG_MODULE_REGISTER(dcblock, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dcblock); + +/** + * \brief Sets the DC Blocking filter in pass through mode. + * The frequency response of a DCB filter is: + * H(z) = (1 - z^-1)/(1-Rz^-1). + * Setting R to 1 makes the filter act as a passthrough component. + */ +static void dcblock_set_passthrough(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + int i; + + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + cd->R_coeffs[i] = ONE_Q2_30; +} + +/** + * \brief Copy the DC Blocking filter coefficients from received + * configuration blob. + */ +static void dcblock_copy_coefficients(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + memcpy_s(cd->R_coeffs, sizeof(cd->R_coeffs), cd->config, sizeof(cd->R_coeffs)); +} + +/** + * \brief Initializes the state of the DC Blocking Filter + */ +static void dcblock_init_state(struct comp_data *cd) +{ + memset(cd->state, 0, sizeof(cd->state)); +} + +/** + * \brief Creates DC Blocking Filter component. + * \return success. + */ +static int dcblock_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct comp_data *cd; + + comp_info(dev, "entry"); + + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + cd->dcblock_func = NULL; + + /* component model data handler */ + cd->model_handler = comp_data_blob_handler_new(dev); + if (!cd->model_handler) { + comp_err(dev, "comp_data_blob_handler_new() failed."); + rfree(cd); + return -ENOMEM; + } + + return 0; +} + +/** + * \brief Frees DC Blocking Filter component. + * \param[in,out] dev DC Blocking Filter base component device. + */ +static int dcblock_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + comp_data_blob_handler_free(cd->model_handler); + rfree(cd); + return 0; +} + +/** + * \brief Handles incoming get commands for DC Blocking Filter component. + */ +static int dcblock_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + return dcblock_get_ipc_config(mod, fragment, fragment_size); +} + +/** + * \brief Handles incoming set commands for DC Blocking Filter component. + */ +static int dcblock_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) +{ + + return dcblock_set_ipc_config(mod, pos, data_offset_size, fragment, fragment_size); +} + +/** + * \brief Copies and processes stream data. + * \param[in,out] dev DC Blocking Filter module. + * \return Error code. + */ +static int dcblock_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 comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + uint32_t frames = input_buffers[0].size; + + comp_dbg(mod->dev, "entry"); + + cd->dcblock_func(cd, source, sink, frames); + + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frames); + return 0; +} + +/** + * \brief Prepares DC Blocking Filter component for processing. + * \param[in,out] dev DC Blocking Filter base component device. + * \return Error code. + */ +static int dcblock_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_buffer *sourceb, *sinkb; + struct comp_dev *dev = mod->dev; + size_t data_size; + + comp_info(dev, "entry"); + + /* DC Filter component will only ever have one source and sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + + dcblock_params(mod); + + /* get source data format */ + cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); + + /* get sink data format and period bytes */ + cd->sink_format = audio_stream_get_frm_fmt(&sinkb->stream); + + dcblock_init_state(cd); + cd->dcblock_func = dcblock_find_func(cd->source_format); + if (!cd->dcblock_func) { + comp_err(dev, "No processing function matching frames format"); + return -EINVAL; + } + + comp_info(mod->dev, "source_format=%d, sink_format=%d", + cd->source_format, cd->sink_format); + + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + if (cd->config && data_size > 0) + dcblock_copy_coefficients(mod); + else + dcblock_set_passthrough(mod); + + return 0; +} + +/** + * \brief Resets DC Blocking Filter component. + * \param[in,out] dev DC Blocking Filter base component device. + * \return Error code. + */ +static int dcblock_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + dcblock_init_state(cd); + + cd->dcblock_func = NULL; + + return 0; +} + +static const struct module_interface dcblock_interface = { + .init = dcblock_init, + .prepare = dcblock_prepare, + .process_audio_stream = dcblock_process, + .set_configuration = dcblock_set_config, + .get_configuration = dcblock_get_config, + .reset = dcblock_reset, + .free = dcblock_free, +}; + +#if CONFIG_COMP_DCBLOCK_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("DCBLOCK", &dcblock_interface, 1, SOF_REG_UUID(dcblock), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(dcblock_tr, SOF_UUID(dcblock_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(dcblock_interface, dcblock_uuid, dcblock_tr); +SOF_MODULE_INIT(dcblock, sys_comp_module_dcblock_interface_init); + +#endif diff --git a/src/audio/dcblock/dcblock.h b/src/audio/dcblock/dcblock.h new file mode 100644 index 000000000000..eaf09da22bf2 --- /dev/null +++ b/src/audio/dcblock/dcblock.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Sebastiano Carlucci <scarlucci@google.com> + */ + +#ifndef __SOF_AUDIO_DCBLOCK_DCBLOCK_H__ +#define __SOF_AUDIO_DCBLOCK_DCBLOCK_H__ + +#include <stdint.h> +#include <sof/platform.h> +#include <ipc/stream.h> +#include <sof/compiler_info.h> +#include <module/module/base.h> +#include <module/module/interface.h> + +struct audio_stream; +struct comp_dev; + +struct dcblock_state { + int32_t x_prev; /**< state variable referring to x[n-1] */ + int32_t y_prev; /**< state variable referring to y[n-1] */ +}; + +/** + * \brief Type definition for the processing function for the + * DC Blocking Filter. + */ + +struct comp_data; + +typedef void (*dcblock_func)(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames); + +/* DC Blocking Filter component private data */ +struct comp_data { + /**< filters state */ + struct dcblock_state state[PLATFORM_MAX_CHANNELS]; + + /** coefficients for the processing function */ + int32_t R_coeffs[PLATFORM_MAX_CHANNELS]; + + struct comp_data_blob_handler *model_handler; + int32_t *config; /**< pointer to setup blob */ + + enum sof_ipc_frame source_format; + enum sof_ipc_frame sink_format; + dcblock_func dcblock_func; /**< processing function */ +}; + +/** \brief DC Blocking Filter processing functions map item. */ +struct dcblock_func_map { + enum sof_ipc_frame src_fmt; /**< source frame format */ + dcblock_func func; /**< processing function */ +}; + +/** \brief Map of formats with dedicated processing functions. */ +extern const struct dcblock_func_map dcblock_fnmap[]; + +/** \brief Number of processing functions. */ +extern const size_t dcblock_fncount; + +/** + * \brief Retrieves a DC Blocking processing function matching + * the source buffer's frame format. + * \param src_fmt the frames' format of the source buffer + */ +static inline dcblock_func dcblock_find_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < dcblock_fncount; i++) { + if (src_fmt == dcblock_fnmap[i].src_fmt) + return dcblock_fnmap[i].func; + } + + return NULL; +} + +int dcblock_get_ipc_config(struct processing_module *mod, + uint8_t *fragment, size_t fragment_size); +int dcblock_set_ipc_config(struct processing_module *mod, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size); +void dcblock_params(struct processing_module *mod); + +#endif /* __SOF_AUDIO_DCBLOCK_DCBLOCK_H__ */ diff --git a/src/audio/dcblock/dcblock.toml b/src/audio/dcblock/dcblock.toml new file mode 100644 index 000000000000..c752fd13a279 --- /dev/null +++ b/src/audio/dcblock/dcblock.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # DCblock module config + [[module.entry]] + name = "DCBLOCK" + uuid = UUIDREG_STR_DCBLOCK + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/dcblock/dcblock_generic.c b/src/audio/dcblock/dcblock_generic.c new file mode 100644 index 000000000000..4ff5fa11315b --- /dev/null +++ b/src/audio/dcblock/dcblock_generic.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <stdint.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> + +#include "dcblock.h" + +#if SOF_USE_HIFI(NONE, DCBLOCK) + +LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL); + +/** + * + * Genereric processing function. Input is 32 bits. + * + */ +static int32_t dcblock_generic(struct dcblock_state *state, + int64_t R, int32_t x) +{ + /* + * R: Q2.30, y_prev: Q1.31 + * R * y_prev: Q3.61 + */ + int64_t out = ((int64_t)x) - state->x_prev + + Q_SHIFT_RND(R * state->y_prev, 61, 31); + + state->y_prev = sat_int32(out); + state->x_prev = x; + + return state->y_prev; +} + +#if CONFIG_FORMAT_S16LE +static void dcblock_s16_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + struct dcblock_state *state; + 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 = audio_stream_get_channels(source); + int samples = nch * frames; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s16(source, x); + n = MIN(samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, y); + n = MIN(n, nmax); + for (ch = 0; ch < nch; ch++) { + state = &cd->state[ch]; + R = cd->R_coeffs[ch]; + idx = ch; + for (i = 0; i < n; i += nch) { + tmp = dcblock_generic(state, R, x[idx] << 16); + y[idx] = sat_int16(Q_SHIFT_RND(tmp, 31, 15)); + idx += nch; + } + } + samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } + +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void dcblock_s24_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + struct dcblock_state *state; + 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 = audio_stream_get_channels(source); + int samples = nch * frames; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s24(source, x); + n = MIN(samples, nmax); + nmax = audio_stream_samples_without_wrap_s24(sink, y); + n = MIN(n, nmax); + for (ch = 0; ch < nch; ch++) { + state = &cd->state[ch]; + R = cd->R_coeffs[ch]; + idx = ch; + for (i = 0; i < n; i += nch) { + tmp = dcblock_generic(state, R, x[idx] << 8); + y[idx] = sat_int24(Q_SHIFT_RND(tmp, 31, 23)); + idx += nch; + } + } + samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } + +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void dcblock_s32_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + struct dcblock_state *state; + 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 = audio_stream_get_channels(source); + int samples = nch * frames; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s32(source, x); + n = MIN(samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, y); + n = MIN(n, nmax); + for (ch = 0; ch < nch; ch++) { + state = &cd->state[ch]; + R = cd->R_coeffs[ch]; + idx = ch; + for (i = 0; i < n; i += nch) { + y[idx] = dcblock_generic(state, R, x[idx]); + idx += nch; + } + } + samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct dcblock_func_map dcblock_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, dcblock_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, dcblock_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, dcblock_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap); +#endif diff --git a/src/audio/dcblock/dcblock_hifi3.c b/src/audio/dcblock/dcblock_hifi3.c new file mode 100644 index 000000000000..d49a1ccca986 --- /dev/null +++ b/src/audio/dcblock/dcblock_hifi3.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <stdint.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> + +#include "dcblock.h" + +#if SOF_USE_HIFI(3, DCBLOCK) + +#include <xtensa/tie/xt_hifi3.h> +LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL); + +static inline ae_int32x2 dcblock_cal(ae_int32x2 R, ae_int32x2 state_x, ae_int32x2 state_y, + ae_int32x2 sample) +{ + ae_int64 out, temp; + + /* R: Q2.30, y_prev: Q1.31 the result is Q2.62 */ + temp = AE_MULF32S_LL(R, state_y); + out = AE_SUB64(AE_MOVAD32_L(sample), AE_MOVAD32_L(state_x)); + /* shift out to 2.62 */ + out = AE_ADD64S(AE_SLAI64S(out, 31), temp); + /* shift out to 1.63 */ + return AE_ROUND32F64SSYM(AE_SLAI64S(out, 1)); +} + +/* Setup circular for component source */ +static inline void dcblock_set_circular(const struct audio_stream *source) +{ + /* Set source as circular buffer 0 */ + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); +} + +#if CONFIG_FORMAT_S16LE +static void dcblock_s16_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + 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 = audio_stream_get_channels(source); + const int inc = nch * sizeof(ae_int16); + int samples = nch * frames; + + dcblock_set_circular(source); + while (samples) { + n = audio_stream_samples_without_wrap_s16(sink, dst); + n = MIN(n, samples); + for (ch = 0; ch < nch; ch++) { + in = src + ch; + out = dst + ch; + state_x = cd->state[ch].x_prev; + state_y = cd->state[ch].y_prev; + R = cd->R_coeffs[ch]; + for (i = 0; i < n; i += nch) { + /* Load a 16 bit sample*/ + AE_L16_XC(in_sample, in, inc); + /* store the 16 bit sample to high 16bit of 32bit register*/ + sample = AE_CVT32X2F16_32(in_sample); + state_y = dcblock_cal(R, state_x, state_y, sample); + state_x = sample; + out_sample = AE_ROUND16X4F32SSYM(state_y, state_y); + AE_S16_0_XP(out_sample, out, inc); + } + cd->state[ch].x_prev = state_x; + cd->state[ch].y_prev = state_y; + } + samples -= n; + dst = audio_stream_wrap(sink, dst + n); + src = audio_stream_wrap(source, src + n); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void dcblock_s24_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + 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 = audio_stream_get_channels(source); + const int inc = nch * sizeof(ae_int32); + int samples = nch * frames; + + dcblock_set_circular(source); + while (samples) { + n = audio_stream_samples_without_wrap_s24(sink, dst); + n = MIN(n, samples); + for (ch = 0; ch < nch; ch++) { + in = src + ch; + out = dst + ch; + state_x = cd->state[ch].x_prev; + state_y = cd->state[ch].y_prev; + R = cd->R_coeffs[ch]; + for (i = 0; i < n; i += nch) { + AE_L32_XC(in_sample, in, inc); + in_sample = AE_SLAI32(in_sample, 8); + state_y = dcblock_cal(R, state_x, state_y, in_sample); + state_x = in_sample; + out_sample = AE_SRAI32R(state_y, 8); + out_sample = AE_SLAI32S(out_sample, 8); + out_sample = AE_SRAI32R(out_sample, 8); + AE_S32_L_XP(out_sample, out, inc); + } + cd->state[ch].x_prev = state_x; + cd->state[ch].y_prev = state_y; + } + samples -= n; + dst = audio_stream_wrap(sink, dst + n); + src = audio_stream_wrap(source, src + n); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void dcblock_s32_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + 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 = audio_stream_get_channels(source); + const int inc = nch * sizeof(ae_int32); + int samples = nch * frames; + + dcblock_set_circular(source); + while (samples) { + n = audio_stream_samples_without_wrap_s32(sink, dst); + n = MIN(n, samples); + for (ch = 0; ch < nch; ch++) { + in = src + ch; + out = dst + ch; + state_x = cd->state[ch].x_prev; + state_y = cd->state[ch].y_prev; + R = cd->R_coeffs[ch]; + for (i = 0; i < n; i += nch) { + AE_L32_XC(in_sample, in, inc); + state_y = dcblock_cal(R, state_x, state_y, in_sample); + state_x = in_sample; + AE_S32_L_XP(state_y, out, inc); + } + cd->state[ch].x_prev = state_x; + cd->state[ch].y_prev = state_y; + } + samples -= n; + dst = audio_stream_wrap(sink, dst + n); + src = audio_stream_wrap(source, src + n); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct dcblock_func_map dcblock_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, dcblock_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, dcblock_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, dcblock_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap); +#endif diff --git a/src/audio/dcblock/dcblock_hifi4.c b/src/audio/dcblock/dcblock_hifi4.c new file mode 100644 index 000000000000..f6ff06a55a63 --- /dev/null +++ b/src/audio/dcblock/dcblock_hifi4.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <stdint.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> + +#include "dcblock.h" + +#if SOF_USE_MIN_HIFI(4, DCBLOCK) + +#include <xtensa/tie/xt_hifi4.h> +LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL); + +static inline ae_int32x2 dcblock_cal(ae_int32x2 R, ae_int32x2 state_x, ae_int32x2 state_y, + ae_int32x2 sample) +{ + ae_int64 out, temp; + + /* R: Q2.30, y_prev: Q1.31 the result is Q2.62 */ + temp = AE_MULF32S_LL(R, state_y); + out = AE_SUB64(AE_MOVAD32_L(sample), AE_MOVAD32_L(state_x)); + /* shift out to 2.62 */ + out = AE_ADD64S(AE_SLAI64S(out, 31), temp); + /* shift out to 1.63 */ + return AE_ROUND32F64SSYM(AE_SLAI64S(out, 1)); +} + +/* Setup circular for component sink and source */ +static inline void dcblock_set_circular(const struct audio_stream *source, + const struct audio_stream *sink) +{ + /* Set source as circular buffer 0 */ + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); + + /* Set sink as circular buffer 1 */ + AE_SETCBEGIN1(audio_stream_get_addr(sink)); + AE_SETCEND1(audio_stream_get_end_addr(sink)); +} + +#if CONFIG_FORMAT_S16LE +static void dcblock_s16_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + ae_int16 *in; + ae_int16 *out; + ae_int32x2 R, state_x, state_y, sample; + ae_int16x4 in_sample, out_sample; + int ch, i; + 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 *)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]; + for (i = 0; i < frames; i++) { + /* Load a 16 bit sample*/ + AE_L16_XC(in_sample, in, inc); + /* store the 16 bit sample to high 16bit of 32bit register*/ + sample = AE_CVT32X2F16_32(in_sample); + state_y = dcblock_cal(R, state_x, state_y, sample); + state_x = sample; + out_sample = AE_ROUND16X4F32SSYM(state_y, state_y); + AE_S16_0_XC1(out_sample, out, inc); + } + cd->state[ch].x_prev = state_x; + cd->state[ch].y_prev = state_y; + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void dcblock_s24_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + ae_int32 *in; + ae_int32 *out; + ae_int32x2 R, state_x, state_y; + ae_int32x2 in_sample, out_sample; + int ch, i; + 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 *)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; + R = cd->R_coeffs[ch]; + for (i = 0; i < frames; i++) { + AE_L32_XC(in_sample, in, inc); + in_sample = AE_SLAI32(in_sample, 8); + state_y = dcblock_cal(R, state_x, state_y, in_sample); + state_x = in_sample; + out_sample = AE_SRAI32R(state_y, 8); + out_sample = AE_SLAI32S(out_sample, 8); + out_sample = AE_SRAI32R(out_sample, 8); + AE_S32_L_XC1(out_sample, out, inc); + } + cd->state[ch].x_prev = state_x; + cd->state[ch].y_prev = state_y; + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void dcblock_s32_default(struct comp_data *cd, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames) +{ + ae_int32 *in; + ae_int32 *out; + ae_int32x2 R, state_x, state_y; + ae_int32x2 in_sample; + int ch, i; + 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 *)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; + R = cd->R_coeffs[ch]; + for (i = 0; i < frames; i++) { + AE_L32_XC(in_sample, in, inc); + state_y = dcblock_cal(R, state_x, state_y, in_sample); + state_x = in_sample; + AE_S32_L_XC1(state_y, out, inc); + } + cd->state[ch].x_prev = state_x; + cd->state[ch].y_prev = state_y; + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct dcblock_func_map dcblock_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, dcblock_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, dcblock_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, dcblock_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap); +#endif diff --git a/src/audio/dcblock/dcblock_ipc3.c b/src/audio/dcblock/dcblock_ipc3.c new file mode 100644 index 000000000000..3c41eb83afad --- /dev/null +++ b/src/audio/dcblock/dcblock_ipc3.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/trace/trace.h> +#include <module/module/base.h> +#include <ipc/control.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <module/module/interface.h> +#include <ipc/stream.h> +#include <sof/audio/buffer.h> +#include <errno.h> + +#include "dcblock.h" + +LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL); + +/** + * \brief Handles incoming get commands for DC Blocking Filter component. + */ +int dcblock_get_ipc_config(struct processing_module *mod, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "dcblock_get_config()"); + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) { + comp_err(mod->dev, "dcblock_get_config(), invalid command"); + return -EINVAL; + } + + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +/** + * \brief Handles incoming set commands for DC Blocking Filter component. + */ +int dcblock_set_ipc_config(struct processing_module *mod, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "dcblock_set_config()"); + + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) { + comp_err(mod->dev, "dcblock_set_config(), invalid command %i", cdata->cmd); + return -EINVAL; + } + + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); +} + +void dcblock_params(struct processing_module *mod) +{ +} + diff --git a/src/audio/dcblock/dcblock_ipc4.c b/src/audio/dcblock/dcblock_ipc4.c new file mode 100644 index 000000000000..c375d11ec042 --- /dev/null +++ b/src/audio/dcblock/dcblock_ipc4.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Sebastiano Carlucci <scarlucci@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/trace/trace.h> +#include <module/module/base.h> +#include <ipc/control.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <module/module/interface.h> +#include <ipc/stream.h> +#include <sof/audio/buffer.h> +#include <module/ipc4/base-config.h> +#include <sof/list.h> +#include <errno.h> + +#include "dcblock.h" + +LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL); + +/** + * \brief Handles incoming get commands for DC Blocking Filter component. + */ +int dcblock_get_ipc_config(struct processing_module *mod, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +/** + * \brief Handles incoming set commands for DC Blocking Filter component. + */ +int dcblock_set_ipc_config(struct processing_module *mod, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); +} + +void dcblock_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + /* The caller has verified, that sink and source buffers are connected */ + + sinkb = comp_dev_get_first_data_consumer(dev); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); + + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); +} + diff --git a/src/audio/dcblock/llext/CMakeLists.txt b/src/audio/dcblock/llext/CMakeLists.txt new file mode 100644 index 000000000000..63a95013ab5f --- /dev/null +++ b/src/audio/dcblock/llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("dcblock" + SOURCES ../dcblock.c + ../dcblock_generic.c + ../dcblock_hifi3.c + ../dcblock_hifi4.c + ../dcblock_ipc4.c + LIB openmodules +) diff --git a/src/audio/dcblock/llext/llext.toml.h b/src/audio/dcblock/llext/llext.toml.h new file mode 100644 index 000000000000..ad7917a3d16b --- /dev/null +++ b/src/audio/dcblock/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../dcblock.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/dcblock/tune/README.md b/src/audio/dcblock/tune/README.md new file mode 100644 index 000000000000..37b05f411e7d --- /dev/null +++ b/src/audio/dcblock/tune/README.md @@ -0,0 +1,32 @@ +DC Blocking Filter Control Bytes Generator +======================================= + +This is a tool to generate the topology control bytes file (.m4) and configuration +files used by sof-ctl. See example_dcblock.m for reference on how to use it. + +The tools need GNU Octave version 4.0.0 or later with octave-signal +package. + +dcblock_build_blob.m +--------------- + +This script takes an array of floating point coefficients and the endianness. +Returns a blob used to configure the binary controls of the DC Blocking Filter +component. + +The blob can be passed to alsactl_write(), blob_write(), tplg_write() to generate +a CSV text, binary and topology file respectively. + +dcblock_plot_transferfn.m +--------------- + +This script takes the R coefficient and the sampling frequency to plot the +Frequency Response of the DCB filter H(z) = (1-1/z)/(1-R/z). + +dcblock_plot_stepfn.m +-------------- + +This script takes the R coefficient and the sampling frequency to plot the +Step Response of the DCB filter. It is useful to visualize how the DC component +of a signal reacts to the filter. + diff --git a/src/audio/dcblock/tune/sof_dcblock_build_blob.m b/src/audio/dcblock/tune/sof_dcblock_build_blob.m new file mode 100644 index 000000000000..41d0c1565ab3 --- /dev/null +++ b/src/audio/dcblock/tune/sof_dcblock_build_blob.m @@ -0,0 +1,54 @@ +function blob8 = sof_dcblock_build_blob(R_coeffs, endian, ipc_ver) + +%% Settings +qy_R = 30; + +if nargin < 2 + endian = 'little'; +end + +if nargin < 3 + ipc_ver = 3; +end + +%% Shift values for little/big endian +switch lower(endian) + case 'little' + sh = [0 -8 -16 -24]; + case 'big' + sh = [-24 -16 -8 0]; + otherwise + error('Unknown endiannes'); +end + +%% Convert R_coeffs from float to Q2.30 integers. +num_of_coeffs = length(R_coeffs); +R_coeffs = int32(R_coeffs * bitshift(1, qy_R) + 0.5); + +%% Build Blob +data_size = (num_of_coeffs)*4; +[abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver); + +blob_size = data_size + abi_size; +blob8 = uint8(zeros(1, blob_size)); + +% Pack Blob data +% Insert ABI Header +blob8(1:abi_size) = abi_bytes; +j = abi_size + 1; + +% Insert Data +for i=1:num_of_coeffs + blob8(j:j+3) = word2byte(R_coeffs(i), sh); + j=j+4; +end + +end + +function bytes = word2byte(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/dcblock/tune/sof_dcblock_paths.m b/src/audio/dcblock/tune/sof_dcblock_paths.m new file mode 100644 index 000000000000..fffb360511e4 --- /dev/null +++ b/src/audio/dcblock/tune/sof_dcblock_paths.m @@ -0,0 +1,18 @@ +function sof_dcblock_paths(enable) + +% dcblock_paths(enable) +% enable - set to true to enable needed search path +% set to false to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + + common = '../../../../tools/tune/common'; + if enable + addpath(common); + else + rmpath(common); + end +end diff --git a/src/audio/dcblock/tune/sof_dcblock_plot_stepfn.m b/src/audio/dcblock/tune/sof_dcblock_plot_stepfn.m new file mode 100644 index 000000000000..4a93f310eece --- /dev/null +++ b/src/audio/dcblock/tune/sof_dcblock_plot_stepfn.m @@ -0,0 +1,16 @@ +function sof_dcblock_plot_stepfn(R, fs) +% Plot the step response of a DC Blocking Filter +% For a DC Blocking filter: H(z) = (1-1/z)/(1 - R/z) +% Therefore the coefficients are b = [1 -1], a = [1 -R] +b = [1 -1]; +a = [1 -R]; + +t=((1:0.5*fs)-1)/fs; +plot(t, filter(b, a, ones(length(t), 1))) +grid on +xlabel('Samples'); +ylabel('Amplitude'); +tstr = sprintf("DC Blocking Filter Step Response, R = %i", R); +title(tstr); + +end diff --git a/src/audio/dcblock/tune/sof_dcblock_plot_transferfn.m b/src/audio/dcblock/tune/sof_dcblock_plot_transferfn.m new file mode 100644 index 000000000000..6c420a242ce2 --- /dev/null +++ b/src/audio/dcblock/tune/sof_dcblock_plot_transferfn.m @@ -0,0 +1,17 @@ +function sof_dcblock_plot_transferfn(R, fs) +% Plot the transfer function. +% For a DC Blocking filter: H(z) = (1-1/z)/(1 - R/z) +% Therefore the coefficients are b = [1 -1], a = [1 -R] +b = [1 -1]; +a = [1 -R]; + +f = linspace(1, fs/2, 500); + +semilogx(f, 20*log10(abs(freqz(b, a, f, fs)))); +grid on +xlabel('Frequency (Hz)'); +ylabel('Magnitude (dB)'); +tstr = sprintf("DC Blocking Filter Frequency Response, R = %i", R); +title(tstr); + +end diff --git a/src/audio/dcblock/tune/sof_example_dcblock.m b/src/audio/dcblock/tune/sof_example_dcblock.m new file mode 100644 index 000000000000..cf6d856656a3 --- /dev/null +++ b/src/audio/dcblock/tune/sof_example_dcblock.m @@ -0,0 +1,131 @@ +function sof_example_dcblock() + +% Default blob, about 150 Hz cut-off @ 48 kHz +prm.fc = []; +prm.fs = []; +prm.R_coeffs = [0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98, 0.98]; +prm.id = "default"; +dcblock_blob_calculate(prm) + +% Generate a set configuration blobs for 16 and 48 kHz rate +% The selected high-pass cut-off frequencies are in range 20 - 200 Hz: +% 20, 30, 40, 50, 80, 100, and 200 Hz +% +% Select for applications one that is best tradeoff between DC level +% settle time and the lowest frequency that should pass without +% much attenuation. Cut-off frequency by definition is the point where +% the attenuation is 3.01 dB. + +prm.R_coeffs = []; +for fs = [16e3 48e3] + for fc = [20 30 40 50 80 100 200] + prm.id = sprintf("%dhz_%dkhz", round(fc), round(fs / 1000)); + prm.fs = fs; + prm.fc = fc; + dcblock_blob_calculate(prm) + end +end + +end + +function dcblock_blob_calculate(prm) + +% Set the parameters here +sof_tools = '../../../../tools'; +sof_tplg = fullfile(sof_tools, 'topology'); +sof_ctl = fullfile(sof_tools, 'ctl'); +tplg1_fn = sprintf("%s/topology1/m4/dcblock_coef_%s.m4", sof_tplg, prm.id); % Control Bytes File +tplg2_fn = sprintf("%s/topology2/include/components/dcblock/%s.conf", sof_tplg, prm.id); +% Use those files with sof-ctl to update the component's configuration +blob3_fn = sprintf("%s/ipc3/dcblock/coef_%s.bin", sof_ctl, prm.id); % Blob binary file +alsa3_fn = sprintf("%s/ipc3/dcblock/coef_%s.txt", sof_ctl, prm.id); % ALSA CSV format file +blob4_fn = sprintf("%s/ipc4/dcblock/coef_%s.bin", sof_ctl, prm.id); % Blob binary file +alsa4_fn = sprintf("%s/ipc4/dcblock/coef_%s.txt", sof_ctl, prm.id); % ALSA CSV format file + +endian = "little"; + +if isempty(prm.fc) + R_coeffs = prm.R_coeffs; +else + channels = 8; + R = dcblock_rval_calculate(prm.fs, prm.fc); + R_coeffs = R * ones(1, channels); +end + +sof_dcblock_paths(true); + +blob8 = sof_dcblock_build_blob(R_coeffs, endian); +blob8_ipc4 = sof_dcblock_build_blob(R_coeffs, endian, 4); + +% Generate output files +sof_tplg_write(tplg1_fn, blob8, "DCBLOCK", ... + "Exported with script sof_example_dcblock.m", ... + "cd tools/tune/dcblock; octave sof_example_dcblock.m"); +sof_ucm_blob_write(blob3_fn, blob8); +sof_alsactl_write(alsa3_fn, blob8); + +sof_tplg2_write(tplg2_fn, blob8_ipc4, "dcblock_config", ... + "Exported with script sof_example_dcblock.m" , ... + "cd tools/tune/dcblock; octave sof_example_dcblock.m"); +sof_ucm_blob_write(blob4_fn, blob8_ipc4); +sof_alsactl_write(alsa4_fn, blob8_ipc4); + +% Plot Filter's Transfer Function and Step Response +% As an example, plot the graphs of the first coefficient +fs = 48e3; +sof_dcblock_plot_transferfn(R_coeffs(1), fs); +figure +sof_dcblock_plot_stepfn(R_coeffs(1), fs); + +sof_dcblock_paths(false); + +end + +% Finds with iterative search parameter R for given cutoff frequency +function R = dcblock_rval_calculate(fs, fc_target) + +if (fc_target / fs < 10 / 48e3 || fc_target / fs > 1000 / 48e3) + error("Illegal fc_target"); +end + +h_target = 1 / sqrt(2); % -3.01 dB +R = 0.5; +R_step = 0.005; +sign = 1; +w = 2 * pi * fc_target / fs; +j = sqrt(-1); +z = exp(j * w); + +% Iteration 0 +h = (1 - z^-1) / (1 - R * z^-1); +err_prev = (h_target - abs(h))^2; +R = R + sign * R_step; + +% Do more iterations +for n = 1 : 200 + h = (1 - z^-1) / (1 - R * z^-1); + err = (h_target - abs(h))^2; + if (err > err_prev) + sign = -sign; + R_step = R_step / 2; + end + R = R + sign * R_step; + err_prev = err; +end + +% Sane result? +if R < eps || R > 1 - eps + error("Calculate of R iteration failed"); +end + +% Sane high-pass function? +f = [1 fc_target fs/2]; +b = [ 1 -1 ]; a = [ 1 -R ]; +h = freqz(b, a, f, fs); +h_db = 20*log10(abs(h)); +err_hfc = abs(20*log10(1/sqrt(2)) - h_db(2)); +if err_hfc > 0.01 || h_db(1) > -10 || h_db(3) < 0 || h_db(3) > 1 + error("Failed high-pass response"); +end + +end diff --git a/src/audio/detect_test.c b/src/audio/detect_test.c deleted file mode 100644 index bfad2286ab71..000000000000 --- a/src/audio/detect_test.c +++ /dev/null @@ -1,813 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component.h> -#include <sof/audio/format.h> -#include <sof/audio/kpb.h> -#include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/wait.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/math/numbers.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <ipc/control.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <kernel/abi.h> -#include <user/detect_test.h> -#include <user/trace.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> - -#define ACTIVATION_DEFAULT_SHIFT 3 -#define ACTIVATION_DEFAULT_DIVIDER_S16 0.5 -#define ACTIVATION_DEFAULT_DIVIDER_S24 0.05 - -#define ACTIVATION_DEFAULT_THRESHOLD_S16 \ - ((int16_t)((INT16_MAX) * (ACTIVATION_DEFAULT_DIVIDER_S16))) -#define ACTIVATION_DEFAULT_THRESHOLD_S24 \ - ((int32_t)((INT24_MAXVALUE) * (ACTIVATION_DEFAULT_DIVIDER_S24))) -#define ACTIVATION_DEFAULT_THRESHOLD_S32 \ - ACTIVATION_DEFAULT_THRESHOLD_S24 - -#define INITIAL_MODEL_DATA_SIZE 64 - -/* default number of samples before detection is activated */ -#define KEYPHRASE_DEFAULT_PREAMBLE_LENGTH 0 - -static const struct comp_driver comp_keyword; - -/* eba8d51f-7827-47b5-82ee-de6e7743af67 */ -DECLARE_SOF_UUID("kd-test", keyword_uuid, 0xeba8d51f, 0x7827, 0x47b5, - 0x82, 0xee, 0xde, 0x6e, 0x77, 0x43, 0xaf, 0x67); - -struct model_data { - uint32_t data_size; - void *data; - uint32_t crc; - uint32_t data_pos; /**< current copy position for model data */ -}; - -struct comp_data { - struct sof_detect_test_config config; - struct model_data model; - int32_t activation; - uint32_t detected; - uint32_t detect_preamble; /**< current keyphrase preamble length */ - uint32_t keyphrase_samples; /**< keyphrase length in samples */ - uint32_t history_depth; /** defines draining size in bytes. */ - - uint16_t sample_valid_bytes; - struct kpb_event_data event_data; - struct kpb_client client_data; - - struct sof_ipc_comp_event event; - struct ipc_msg *msg; /**< host notification */ - - void (*detect_func)(struct comp_dev *dev, - const struct audio_stream *source, uint32_t frames); -}; - -static inline bool detector_is_sample_width_supported(enum sof_ipc_frame sf) -{ - bool ret; - - switch (sf) { -#if CONFIG_FORMAT_S16LE - case SOF_IPC_FRAME_S16_LE: - /* FALLTHRU */ -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - case SOF_IPC_FRAME_S24_4LE: - /* FALLTHRU */ -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - case SOF_IPC_FRAME_S32_LE: - /* FALLTHRU */ -#endif /* CONFIG_FORMAT_S32LE */ - ret = true; - break; - default: - ret = false; - break; - } - - return ret; -} - -static void notify_host(const struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "notify_host()"); - - ipc_msg_send(cd->msg, &cd->event, true); -} - -static void notify_kpb(const struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "notify_kpb(), preamble: %u", cd->detect_preamble); - - 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.history_depth = (cd->history_depth != 0) ? - cd->history_depth : - cd->config.history_depth; - cd->event_data.event_id = KPB_EVENT_BEGIN_DRAINING; - cd->event_data.client_data = &cd->client_data; - - notifier_event(dev, NOTIFIER_ID_KPB_CLIENT_EVT, - NOTIFIER_TARGET_CORE_ALL_MASK, &cd->event_data, - sizeof(cd->event_data)); -} - -static void detect_test_notify(const struct comp_dev *dev) -{ - notify_host(dev); - notify_kpb(dev); -} - -static void default_detect_test(struct comp_dev *dev, - const struct audio_stream *source, - uint32_t frames) -{ - struct comp_data *cd = comp_get_drvdata(dev); - void *src; - int32_t diff; - uint32_t count = frames; /**< Assuming single channel */ - uint32_t sample; - uint16_t valid_bits = cd->sample_valid_bytes * 8; - const int32_t activation_threshold = cd->config.activation_threshold; - uint32_t cycles_per_frame; /**< Clock cycles required per frame */ - - /* synthetic load */ - if (cd->config.load_mips) { - /* assuming count is a processing frame size in samples */ - cycles_per_frame = (cd->config.load_mips * 1000000 * count) - / source->rate; - idelay(cycles_per_frame); - } - - /* perform detection within current period */ - for (sample = 0; sample < count && !cd->detected; ++sample) { - src = (valid_bits == 16U) ? - audio_stream_read_frag_s16(source, sample) : - audio_stream_read_frag_s32(source, sample); - if (valid_bits > 16U) { - diff = abs(*(int32_t *)src) - abs(cd->activation); - } else { - diff = abs(*(int16_t *)src) - - abs((int16_t)cd->activation); - } - - diff >>= cd->config.activation_shift; - cd->activation += diff; - - if (cd->detect_preamble >= cd->keyphrase_samples) { - if (cd->activation >= activation_threshold) { - /* The algorithm shall use cd->history_depth - * to specify its draining size request. - * Zero value means default config value - * will be used. - */ - cd->history_depth = 0; - detect_test_notify(dev); - cd->detected = 1; - } - } else { - ++cd->detect_preamble; - } - } -} - -static void free_mem_load(struct comp_data *cd) -{ - if (!cd) { - comp_cl_err(&comp_keyword, "free_mem_load() error: invalid cd"); - return; - } - - if (cd->model.data) { - rfree(cd->model.data); - cd->model.data = NULL; - cd->model.data_size = 0; - cd->model.crc = 0; - cd->model.data_pos = 0; - } -} - -static int alloc_mem_load(struct comp_data *cd, uint32_t size) -{ - if (!size) - return 0; - - if (!cd) { - comp_cl_err(&comp_keyword, "alloc_mem_load() error: invalid cd"); - return -EINVAL; - } - - free_mem_load(cd); - - cd->model.data = rballoc(0, SOF_MEM_CAPS_RAM, size); - - if (!cd->model.data) { - comp_cl_err(&comp_keyword, "alloc_mem_load() alloc failed"); - return -ENOMEM; - } - - bzero(cd->model.data, size); - cd->model.data_size = size; - cd->model.data_pos = 0; - - return 0; -} - -static int test_keyword_get_threshold(struct comp_dev *dev, int sample_width) -{ - switch (sample_width) { -#if CONFIG_FORMAT_S16LE - case 16: - return ACTIVATION_DEFAULT_THRESHOLD_S16; -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - case 24: - return ACTIVATION_DEFAULT_THRESHOLD_S24; -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - case 32: - return ACTIVATION_DEFAULT_THRESHOLD_S32; -#endif /* CONFIG_FORMAT_S32LE */ - default: - comp_err(dev, "test_keyword_get_threshold(), unsupported sample width: %d", - sample_width); - return -EINVAL; - } -} - -static int test_keyword_apply_config(struct comp_dev *dev, - struct sof_detect_test_config *cfg) -{ - struct comp_data *cd = comp_get_drvdata(dev); - uint16_t sample_width; - int ret; - - ret = memcpy_s(&cd->config, sizeof(cd->config), cfg, - sizeof(struct sof_detect_test_config)); - assert(!ret); - - sample_width = cd->config.sample_width; - - if (!cd->config.activation_shift) - cd->config.activation_shift = ACTIVATION_DEFAULT_SHIFT; - - if (!cd->config.activation_threshold) { - cd->config.activation_threshold = - test_keyword_get_threshold(dev, sample_width); - } - - return 0; -} - -static struct comp_dev *test_keyword_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct comp_dev *dev; - struct sof_ipc_comp_process *keyword; - struct sof_ipc_comp_process *ipc_keyword = - (struct sof_ipc_comp_process *)comp; - struct comp_data *cd; - struct sof_detect_test_config *cfg; - int ret = 0; - size_t bs; - - comp_cl_info(&comp_keyword, "test_keyword_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_process)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_process); - - keyword = COMP_GET_IPC(dev, sof_ipc_comp_process); - ret = memcpy_s(keyword, sizeof(*keyword), ipc_keyword, - sizeof(struct sof_ipc_comp_process)); - assert(!ret); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - - if (!cd) - goto fail; - - /* using default processing function */ - cd->detect_func = default_detect_test; - - comp_set_drvdata(dev, cd); - - cfg = (struct sof_detect_test_config *)ipc_keyword->data; - bs = ipc_keyword->size; - - if (bs > 0) { - if (bs < sizeof(struct sof_detect_test_config)) { - comp_err(dev, "test_keyword_new() error: invalid data size"); - goto fail; - } - - if (test_keyword_apply_config(dev, cfg)) { - comp_err(dev, "test_keyword_new() error: failed to apply config"); - goto fail; - } - } - - ret = alloc_mem_load(cd, INITIAL_MODEL_DATA_SIZE); - if (ret < 0) { - comp_err(dev, "test_keyword_new() error: model data initial failed"); - goto fail; - } - - /* build component event */ - ipc_build_comp_event(&cd->event, comp->type, comp->id); - cd->event.event_type = SOF_CTRL_EVENT_KD; - cd->event.num_elems = 0; - - cd->msg = ipc_msg_init(cd->event.rhdr.hdr.cmd, sizeof(cd->event)); - if (!cd->msg) { - comp_err(dev, "test_keyword_new() error: ipc notification init failed"); - goto fail; - } - - dev->state = COMP_STATE_READY; - return dev; - -fail: - if (cd) - rfree(cd); - rfree(dev); - return NULL; -} - -static void test_keyword_free(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "test_keyword_free()"); - - ipc_msg_free(cd->msg); - free_mem_load(cd); - rfree(cd); - rfree(dev); -} - -static int test_keyword_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int ret; - - comp_dbg(dev, "test_keyword_verify_params()"); - - ret = comp_verify_params(dev, 0, params); - if (ret < 0) { - comp_err(dev, "test_keyword_verify_params() error: comp_verify_params() failed"); - return ret; - } - - return 0; -} - -/* set component audio stream parameters */ -static int test_keyword_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sourceb; - int err; - - /* Detector is used only in KPB topology. It always requires channels - * parameter set to 1. - */ - params->channels = 1; - - err = test_keyword_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "test_keyword_params(): pcm params verification failed."); - return -EINVAL; - } - - cd->sample_valid_bytes = params->sample_valid_bytes; - - /* keyword components will only ever have 1 source */ - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - - if (sourceb->stream.channels != 1) { - comp_err(dev, "test_keyword_params() error: only single-channel supported"); - return -EINVAL; - } - - if (!detector_is_sample_width_supported(sourceb->stream.frame_fmt)) { - comp_err(dev, "test_keyword_params() error: only 16-bit format supported"); - return -EINVAL; - } - - /* calculate the length of the preamble */ - if (cd->config.preamble_time) { - cd->keyphrase_samples = cd->config.preamble_time * - (sourceb->stream.rate / 1000); - } else { - cd->keyphrase_samples = KEYPHRASE_DEFAULT_PREAMBLE_LENGTH; - } - - return 0; -} - -static int test_keyword_set_config(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) -{ - struct sof_detect_test_config *cfg; - size_t bs; - - /* Copy new config, find size from header */ - cfg = (struct sof_detect_test_config *)cdata->data->data; - bs = cfg->size; - - comp_info(dev, "test_keyword_set_config(), blob size = %u", bs); - - if (bs != sizeof(struct sof_detect_test_config)) { - comp_err(dev, "test_keyword_set_config() error: invalid blob size"); - return -EINVAL; - } - - return test_keyword_apply_config(dev, cfg); -} - -static int test_keyword_set_model(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int ret = 0; - bool done = false; - - comp_dbg(dev, "keyword_ctrl_set_model() msg_index = %d, num_elems = %d, remaining = %d ", - cdata->msg_index, cdata->num_elems, - cdata->elems_remaining); - - if (!cdata->msg_index) { - ret = alloc_mem_load(cd, cdata->data->size); - if (ret < 0) - return ret; - } - - if (!cd->model.data) { - comp_err(dev, "keyword_ctrl_set_model() error: buffer not allocated"); - return -EINVAL; - } - - if (!cdata->elems_remaining) { - if (cdata->num_elems + cd->model.data_pos < - cd->model.data_size) { - comp_err(dev, "keyword_ctrl_set_model() error: not enough data to fill the buffer"); - - /* TODO: anything to do in such a situation? */ - - return -EINVAL; - } - - done = true; - comp_info(dev, "test_keyword_set_model() final packet received"); - } - - if (cdata->num_elems > - cd->model.data_size - cd->model.data_pos) { - comp_err(dev, "keyword_ctrl_set_model() error: too much data"); - return -EINVAL; - } - - ret = memcpy_s((char *)cd->model.data + cd->model.data_pos, - cd->model.data_size - cd->model.data_pos, - cdata->data->data, cdata->num_elems); - assert(!ret); - - cd->model.data_pos += cdata->num_elems; - - if (done) { - /* Set model data done, update crc value */ - cd->model.crc = crc32(0, cd->model.data, - cd->model.data_size); - comp_info(dev, "keyword_ctrl_set_model() done, memory_size = 0x%x, crc = 0x%08x", - cd->model.data_size, cd->model.crc); - } - return 0; -} - -static int test_keyword_ctrl_set_bin_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) -{ - int ret = 0; - - if (dev->state != COMP_STATE_READY) { - /* It is a valid request but currently this is not - * supported during playback/capture. The driver will - * re-send data in next resume when idle and the new - * configuration will be used when playback/capture - * starts. - */ - comp_err(dev, "keyword_ctrl_set_bin_data() error: driver is busy"); - return -EBUSY; - } - - switch (cdata->data->type) { - case SOF_DETECT_TEST_CONFIG: - ret = test_keyword_set_config(dev, cdata); - break; - case SOF_DETECT_TEST_MODEL: - ret = test_keyword_set_model(dev, cdata); - break; - default: - comp_err(dev, "keyword_ctrl_set_bin_data() error: unknown binary data type"); - break; - } - - return ret; -} - -static int test_keyword_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, "test_keyword_cmd_set_data() error: invalid version"); - return -EINVAL; - } - - switch (cdata->cmd) { - case SOF_CTRL_CMD_ENUM: - comp_info(dev, "test_keyword_cmd_set_data(), SOF_CTRL_CMD_ENUM"); - break; - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "test_keyword_cmd_set_data(), SOF_CTRL_CMD_BINARY"); - ret = test_keyword_ctrl_set_bin_data(dev, cdata); - break; - default: - comp_err(dev, "test_keyword_cmd_set_data() error: invalid cdata->cmd"); - ret = -EINVAL; - break; - } - - return ret; -} - -static int test_keyword_get_config(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int size) -{ - struct comp_data *cd = comp_get_drvdata(dev); - size_t bs; - int ret = 0; - - comp_info(dev, "test_keyword_get_config()"); - - /* Copy back to user space */ - bs = cd->config.size; - comp_info(dev, "value of block size: %u", bs); - - if (bs == 0 || bs > size) - return -EINVAL; - - ret = memcpy_s(cdata->data->data, size, &cd->config, bs); - assert(!ret); - - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = bs; - - return ret; -} - -static int test_keyword_get_model(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int size) -{ - struct comp_data *cd = comp_get_drvdata(dev); - size_t bs; - int ret = 0; - - comp_dbg(dev, "test_keyword_get_model() msg_index = %d, num_elems = %d, remaining = %d ", - cdata->msg_index, cdata->num_elems, - cdata->elems_remaining); - - /* Copy back to user space */ - if (cd->model.data) { - if (!cdata->msg_index) { - /* reset copy offset */ - cd->model.data_pos = 0; - comp_info(dev, "test_keyword_get_model() model data_size = 0x%x, crc = 0x%08x", - cd->model.data_size, cd->model.crc); - } - - bs = cdata->num_elems; - if (bs > size) { - comp_err(dev, "test_keyword_get_model() error: invalid size %d", - bs); - return -EINVAL; - } - - ret = memcpy_s(cdata->data->data, size, - (char *)cd->model.data + cd->model.data_pos, - bs); - assert(!ret); - - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = cd->model.data_size; - cd->model.data_pos += bs; - - } else { - comp_err(dev, "test_keyword_get_model() error: invalid cd->config"); - ret = -EINVAL; - } - - return ret; -} - -static int test_keyword_ctrl_get_bin_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, - int size) -{ - int ret = 0; - - switch (cdata->data->type) { - case SOF_DETECT_TEST_CONFIG: - ret = test_keyword_get_config(dev, cdata, size); - break; - case SOF_DETECT_TEST_MODEL: - ret = test_keyword_get_model(dev, cdata, size); - break; - default: - comp_err(dev, "test_keyword_ctrl_get_bin_data() error: unknown binary data type"); - break; - } - - return ret; -} - -static int test_keyword_ctrl_get_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int size) -{ - int ret = 0; - - comp_info(dev, "test_keyword_ctrl_get_data() size: %d", size); - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - ret = test_keyword_ctrl_get_bin_data(dev, cdata, size); - break; - default: - comp_err(dev, "test_keyword_ctrl_get_data() error: invalid cdata->cmd"); - return -EINVAL; - } - - return ret; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int test_keyword_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = data; - - comp_info(dev, "test_keyword_cmd()"); - - switch (cmd) { - case COMP_CMD_SET_DATA: - return test_keyword_ctrl_set_data(dev, cdata); - case COMP_CMD_GET_DATA: - return test_keyword_ctrl_get_data(dev, cdata, max_data_size); - default: - return -EINVAL; - } -} - -static int test_keyword_trigger(struct comp_dev *dev, int cmd) -{ - int ret; - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "test_keyword_trigger()"); - - ret = comp_set_state(dev, cmd); - if (ret) - return ret; - - if (cmd == COMP_TRIGGER_START || - cmd == COMP_TRIGGER_RELEASE) { - cd->detect_preamble = 0; - cd->detected = 0; - cd->activation = 0; - } - - return 0; -} - -/* process stream data from source buffer */ -static int test_keyword_copy(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source; - uint32_t frames; - uint32_t flags = 0; - - comp_dbg(dev, "test_keyword_copy()"); - - /* keyword components will only ever have 1 source */ - source = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); - - buffer_lock(source, &flags); - frames = source->stream.avail / - audio_stream_frame_bytes(&source->stream); - buffer_unlock(source, flags); - - /* copy and perform detection */ - buffer_invalidate(source, source->stream.avail); - cd->detect_func(dev, &source->stream, frames); - - /* calc new available */ - comp_update_buffer_consume(source, source->stream.avail); - - return 0; -} - -static int test_keyword_reset(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "test_keyword_reset()"); - - cd->activation = 0; - cd->detect_preamble = 0; - cd->detected = 0; - - return comp_set_state(dev, COMP_TRIGGER_RESET); -} - -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 = cd->config.sample_width; - - comp_info(dev, "test_keyword_prepare()"); - - if (valid_bits != sample_width) { - /* Default threshold value has to be changed - * according to host new format. - */ - cd->config.activation_threshold = - test_keyword_get_threshold(dev, valid_bits); - } - - return comp_set_state(dev, COMP_TRIGGER_PREPARE); -} - -static const struct comp_driver comp_keyword = { - .type = SOF_COMP_KEYWORD_DETECT, - .uid = SOF_UUID(keyword_uuid), - .ops = { - .new = test_keyword_new, - .free = test_keyword_free, - .params = test_keyword_params, - .cmd = test_keyword_cmd, - .trigger = test_keyword_trigger, - .copy = test_keyword_copy, - .prepare = test_keyword_prepare, - .reset = test_keyword_reset, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_keyword_info = { - .drv = &comp_keyword, -}; - -static void sys_comp_keyword_init(void) -{ - comp_register(platform_shared_get(&comp_keyword_info, - sizeof(comp_keyword_info))); -} - -DECLARE_MODULE(sys_comp_keyword_init); diff --git a/src/audio/drc/CMakeLists.txt b/src/audio/drc/CMakeLists.txt new file mode 100644 index 000000000000..883c32675b50 --- /dev/null +++ b/src/audio/drc/CMakeLists.txt @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_DRC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/drc_llext) + add_dependencies(app drc) +else() + add_local_sources(sof + drc.c + drc_generic.c + drc_hifi3.c + drc_hifi4.c + drc_math_generic.c + drc_math_hifi3.c + ) +endif() + +if(NOT CONFIG_COMP_DRC STREQUAL "n") + add_local_sources(sof drc_log.c) +endif() diff --git a/src/audio/drc/Kconfig b/src/audio/drc/Kconfig new file mode 100644 index 000000000000..9d061c41ea67 --- /dev/null +++ b/src/audio/drc/Kconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: BSD-3-Clause + +rsource "Kconfig.simd" + +config COMP_DRC + tristate "Dynamic Range Compressor component" + select CORDIC_FIXED + select MATH_LUT_SINE_FIXED + select NUMBERS_NORM + select MATH_EXP + select COMP_BLOB + default m if LIBRARY_DEFAULT_MODULAR + help + Select for Dynamic Range Compressor (DRC) component. A DRC can be used + to reduce the volume of loud sounds and amplify silent sounds thus + compressing an audio signal's dynamic range. + +config DRC_MAX_PRE_DELAY_FRAMES + depends on COMP_DRC + int "DRC max number of pre-delay frames" + default 512 + help + Determines the length of pre-delay frame buffers which are allocated + runtime on DRC setup. It requires to be a 2^N number. 512 is + suggested by inference to avoid memory waste and provide reasonable + length for pre-delay frames. diff --git a/src/audio/drc/Kconfig.simd b/src/audio/drc/Kconfig.simd new file mode 100644 index 000000000000..498758c4813d --- /dev/null +++ b/src/audio/drc/Kconfig.simd @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: BSD-3-Clause + +comment "DRC optimization level select" + +choice "DRC_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for DRC module" + depends on COMP_DRC + default DRC_HIFI_MAX + + config DRC_HIFI_MAX + prompt "SIMD will selected by toolchain pre-defined header" + bool + help + When this was selected, optimization level will be determined + by toolchain pre-defined macros in core isa header file. + + config DRC_HIFI_5 + prompt "choose HIFI5 intrinsic optimized DRC module" + bool + help + This option used to build HIFI5 optimized DRC code + + config DRC_HIFI_4 + prompt "choose HIFI4 intrinsic optimized DRC module" + bool + help + This option used to build HIFI4 optimized DRC code + + config DRC_HIFI_3 + prompt "choose HIFI3 intrinsic optimized DRC module" + bool + help + This option used to build HIFI3 intrinsic optimized DRC code + + config DRC_HIFI_NONE + prompt "choose generic C DRC module, no HIFI SIMD involved" + bool + help + This option used to build DRC generic code. +endchoice diff --git a/src/audio/drc/README.md b/src/audio/drc/README.md new file mode 100644 index 000000000000..a0a1eb8dd80a --- /dev/null +++ b/src/audio/drc/README.md @@ -0,0 +1,26 @@ +# Dynamic Range Compressor (DRC) Architecture + +This directory contains the DRC component. + +## Overview + +The Dynamic Range Compressor reduces the volume of loud sounds or amplifies quiet sounds by narrowing or "compressing" an audio signal's dynamic range. + +## Architecture Diagram + +```mermaid +graph TD + In[Audio Input] --> Det[Envelope Detector] + In --> Gain[Gain Element] + Det --> Calc[Gain Calculation] + Calc --> Gain + Gain --> Out[Audio Output] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the Dynamic Range Compressor component (`COMP_DRC`). It relies on various math features like `CORDIC_FIXED`, `MATH_LUT_SINE_FIXED`, and `MATH_EXP`. The maximum number of pre-delay frames is tunable via `DRC_MAX_PRE_DELAY_FRAMES` (defaults to 512). +- **CMakeLists.txt**: Manages local base sources and generic/HIFI specific files such as `drc_hifi4.c` and `drc_math_hifi3.c`. Adds logging capabilities if compiled in (`drc_log.c`). +- **drc.toml**: Topology parameters for the DRC module definition, exposing UUID and standard buffer sizes and processing capabilities. +- **Topology (.conf)**: `tools/topology/topology2/include/components/drc.conf` configures the `drc` widget object, providing switch controls by binding a mixer control to switch get/put handlers (`259`). Defaults to type `effect` with UUID `da:e4:6e:b3:6f:00:f9:47:a0:6d:fe:cb:e2:d8:b6:ce`. +- **MATLAB Tuning (`tune/`)**: Contains `.m` scripts (e.g., `sof_example_drc.m`) capable of tuning compressor parameters (threshold, knee, ratio, attack, release) and visualizing their gain reaction curves. The outputs are exported as `.conf` configurations, M4 macros, and ALSA `alsactl` payload blobs for preset instantiation defaults (e.g., speaker or DMIC presets). diff --git a/src/audio/drc/drc.c b/src/audio/drc/drc.c new file mode 100644 index 000000000000..71d93496b766 --- /dev/null +++ b/src/audio/drc/drc.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <module/module/llext.h> +#include <rtos/init.h> +#include <rtos/panic.h> +#include <rtos/string.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/ut.h> +#include <user/eq.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "drc.h" +#include "drc_algorithm.h" + +LOG_MODULE_DECLARE(drc, CONFIG_SOF_LOG_LEVEL); + +extern const struct sof_uuid drc_uuid; +extern struct tr_ctx drc_tr; + +/* Called from drc_setup() from drc_process(), so cannot be __cold */ +void drc_reset_state(struct processing_module *mod, struct drc_state *state) +{ + int i; + + mod_free(mod, state->pre_delay_buffers[0]); + for (i = 0; i < PLATFORM_MAX_CHANNELS; ++i) { + state->pre_delay_buffers[i] = NULL; + } + + state->detector_average = 0; + state->compressor_gain = Q_CONVERT_FLOAT(1.0f, 30); + + state->last_pre_delay_frames = DRC_DEFAULT_PRE_DELAY_FRAMES; + state->pre_delay_read_index = 0; + state->pre_delay_write_index = DRC_DEFAULT_PRE_DELAY_FRAMES; + + state->envelope_rate = 0; + state->scaled_desired_gain = 0; + + state->processed = 0; + + state->max_attack_compression_diff_db = INT32_MIN; +} + +int drc_init_pre_delay_buffers(struct processing_module *mod, + struct drc_state *state, + size_t sample_bytes, + int channels) +{ + size_t bytes_per_channel = sample_bytes * CONFIG_DRC_MAX_PRE_DELAY_FRAMES; + size_t bytes_total = bytes_per_channel * channels; + int i; + + /* Allocate pre-delay (lookahead) buffers */ + state->pre_delay_buffers[0] = mod_balloc(mod, bytes_total); + if (!state->pre_delay_buffers[0]) + return -ENOMEM; + + memset(state->pre_delay_buffers[0], 0, bytes_total); + + for (i = 1; i < channels; ++i) { + state->pre_delay_buffers[i] = + state->pre_delay_buffers[i - 1] + bytes_per_channel; + } + + return 0; +} + +int drc_set_pre_delay_time(struct drc_state *state, + int32_t pre_delay_time, + int32_t rate) +{ + int32_t pre_delay_frames; + + /* Re-configure look-ahead section pre-delay if delay time has changed. */ + pre_delay_frames = Q_MULTSR_32X32((int64_t)pre_delay_time, rate, 30, 0, 0); + if (pre_delay_frames < 0) + return -EINVAL; + pre_delay_frames = MIN(pre_delay_frames, CONFIG_DRC_MAX_PRE_DELAY_FRAMES - 1); + + /* Make pre_delay_frames multiplies of DIVISION_FRAMES. This way we + * won't split a division of samples into two blocks of memory, so it is + * easier to process. This may make the actual delay time slightly less + * than the specified value, but the difference is less than 1ms. */ + pre_delay_frames &= ~DRC_DIVISION_FRAMES_MASK; + + /* We need at least one division buffer, so the incoming data won't + * overwrite the output data */ + pre_delay_frames = MAX(pre_delay_frames, DRC_DIVISION_FRAMES); + + if (state->last_pre_delay_frames != pre_delay_frames) { + state->last_pre_delay_frames = pre_delay_frames; + state->pre_delay_read_index = 0; + state->pre_delay_write_index = pre_delay_frames; + } + return 0; +} + +/* Called from drc_process(), so cannot be __cold */ +static int drc_setup(struct processing_module *mod, uint16_t channels, uint32_t rate) +{ + struct drc_comp_data *cd = module_get_private_data(mod); + uint32_t sample_bytes = get_sample_bytes(cd->source_format); + int ret; + + /* Reset any previous state */ + drc_reset_state(mod, &cd->state); + + /* Allocate pre-delay buffers */ + ret = drc_init_pre_delay_buffers(mod, &cd->state, (size_t)sample_bytes, (int)channels); + if (ret < 0) + return ret; + + /* Set pre-dely time */ + return drc_set_pre_delay_time(&cd->state, cd->config->params.pre_delay_time, rate); +} + +/* + * End of DRC setup code. Next the standard component methods. + */ + +__cold static int drc_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct drc_comp_data *cd; + int ret; + + assert_can_be_cold(); + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + + /* Handler for configuration data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto cd_fail; + } + + drc_reset_state(mod, &cd->state); + + /* Initialize DRC to enabled. If defined by topology, a control may set + * enabled to false before prepare() or during streaming with the switch + * control from user space. + */ + cd->enabled = true; + cd->enable_switch = true; + return 0; + +cd_fail: + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); + return ret; +} + +__cold static int drc_free(struct processing_module *mod) +{ + struct drc_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); + return 0; +} + +__cold static int drc_set_config(struct processing_module *mod, uint32_t param_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 drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + comp_dbg(dev, "entry"); + +#if CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + if (ctl->id == SOF_DRC_CTRL_INDEX_ENABLE_SWITCH && + ctl->num_elems == SOF_DRC_NUM_ELEMS_ENABLE_SWITCH) { + cd->enable_switch = ctl->chanv[0].value; + comp_info(dev, "enable_switch = %d", cd->enable_switch); + } else { + comp_err(dev, "Illegal switch control id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + return -EINVAL; + } + + return 0; + + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "illegal control."); + return -EINVAL; + } +#endif + + comp_info(dev, "bytes control"); + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); +} + +__cold static int drc_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct drc_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + comp_info(mod->dev, "entry"); + + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +static int drc_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 drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + int frames = input_buffers[0].size; + int ret; + + comp_dbg(dev, "entry"); + + /* 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(mod, audio_stream_get_channels(source), + audio_stream_get_rate(source)); + if (ret < 0) { + comp_err(dev, "drc_copy(), failed DRC setup"); + return ret; + } + + /* If new configuration blob is received in pass-through mode, and it + * has params.enabled true, then find the DRC processing function. + */ + if (cd->drc_func == drc_default_pass && cd->config->params.enabled) + cd->drc_func = drc_find_proc_func(cd->source_format); + + /* If new configuration blob has params.enabled false, then it is safe + * to switch to pass-through mode. + */ + if (!cd->config->params.enabled) + cd->drc_func = drc_default_pass; + } + + /* Control pass-though in processing function with switch control */ + cd->enabled = cd->config && cd->config->params.enabled && cd->enable_switch; + + cd->drc_func(mod, source, sink, frames); + + /* calc new free and available */ + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frames); + return 0; +} + +#if CONFIG_IPC_MAJOR_4 +static void drc_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + /* The caller has verified, that sink and source buffers are connected */ + + sinkb = comp_dev_get_first_data_consumer(dev); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); + + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); +} +#endif /* CONFIG_IPC_MAJOR_4 */ + +static int drc_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct drc_comp_data *cd = module_get_private_data(mod); + struct comp_buffer *sourceb, *sinkb; + struct comp_dev *dev = mod->dev; + size_t data_size; + int channels; + int rate; + int ret; + + comp_info(dev, "entry"); + + /* DRC component will only ever have 1 source and 1 sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + +#if CONFIG_IPC_MAJOR_4 + drc_params(mod); +#endif + + /* get source data format */ + cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); + channels = audio_stream_get_channels(&sinkb->stream); + rate = audio_stream_get_rate(&sinkb->stream); + + /* Initialize DRC */ + comp_info(dev, "source_format=%d", cd->source_format); + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + if (cd->config && data_size > 0) { + ret = drc_setup(mod, channels, rate); + if (ret < 0) { + comp_err(dev, "error: drc_setup failed."); + return ret; + } + + cd->drc_func = drc_find_proc_func(cd->source_format); + if (!cd->drc_func) { + comp_err(dev, "No proc func"); + return -EINVAL; + } + + /* Params.enabled in the configuration blob is the master switch of DRC. + * The enable switch control does not have impact if this is not set to + * true. When false it is safe to use fast pass-through copy. A + * non-enabled blob can be used when same pipeline is used for both + * headphone and speaker where DRC should be off for headphone mode. + */ + if (!cd->config->params.enabled) + cd->drc_func = drc_default_pass; + } else { + /* Generic function for all formats */ + cd->drc_func = drc_default_pass; + } + + comp_info(dev, "DRC is configured."); + return 0; +} + +static int drc_reset(struct processing_module *mod) +{ + struct drc_comp_data *cd = module_get_private_data(mod); + + drc_reset_state(mod, &cd->state); + + return 0; +} + +static const struct module_interface drc_interface = { + .init = drc_init, + .prepare = drc_prepare, + .process_audio_stream = drc_process, + .set_configuration = drc_set_config, + .get_configuration = drc_get_config, + .reset = drc_reset, + .free = drc_free +}; + +#if CONFIG_COMP_DRC_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("DRC", &drc_interface, 1, SOF_REG_UUID(drc), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_MODULE_ADAPTER(drc_interface, drc_uuid, drc_tr); +SOF_MODULE_INIT(drc, sys_comp_module_drc_interface_init); + +#endif diff --git a/src/audio/drc/drc.h b/src/audio/drc/drc.h new file mode 100644 index 000000000000..5598d64c87de --- /dev/null +++ b/src/audio/drc/drc.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ +#ifndef __SOF_AUDIO_DRC_DRC_H__ +#define __SOF_AUDIO_DRC_DRC_H__ + +#include <stdint.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/platform.h> + +#include "drc_user.h" + +struct audio_stream; +struct comp_dev; + +/* Define CONFIG_DRC_MAX_PRE_DELAY_FRAMES for the build purposes without Kconfig, + * e.g. testbench. + * TODO: Use Kconfig on building the testbench. + */ +#ifdef CONFIG_LIBRARY +/* CONFIG_DRC_MAX_PRE_DELAY_FRAMES needs to be a 2^N number */ +#define CONFIG_DRC_MAX_PRE_DELAY_FRAMES 512 +#endif +#define DRC_MAX_PRE_DELAY_FRAMES_MASK (CONFIG_DRC_MAX_PRE_DELAY_FRAMES - 1) +#define DRC_DEFAULT_PRE_DELAY_FRAMES (CONFIG_DRC_MAX_PRE_DELAY_FRAMES >> 1) + +/* DRC_DIVISION_FRAMES needs to be a 2^N number */ +#define DRC_DIVISION_FRAMES 32 +#define DRC_DIVISION_FRAMES_MASK (DRC_DIVISION_FRAMES - 1) + +/* First switch control instance is zero (SOF_IPC4_SWITCH_CONTROL_PARAM_ID), and the + * control is common for all channels. + */ +#define SOF_DRC_CTRL_INDEX_ENABLE_SWITCH 0 +#define SOF_DRC_NUM_ELEMS_ENABLE_SWITCH 1 + +/* Stores the state of DRC */ +struct drc_state { + /* The detector_average is the target gain obtained by looking at the + * future samples in the lookahead buffer and applying the compression + * curve on them. compressor_gain is the gain applied to the current + * samples. compressor_gain moves towards detector_average with the + * speed envelope_rate which is calculated once for each division (32 + * frames). + */ + int32_t detector_average; /* Q2.30 */ + int32_t compressor_gain; /* Q2.30 */ + + /* Lookahead section. */ + int8_t *pre_delay_buffers[PLATFORM_MAX_CHANNELS]; + int32_t last_pre_delay_frames; /* integer */ + int32_t pre_delay_read_index; /* integer */ + int32_t pre_delay_write_index; /* integer */ + + /* envelope for the current division */ + int32_t envelope_rate; /* Q2.30 */ + int32_t scaled_desired_gain; /* Q2.30 */ + + int32_t processed; /* switch */ + + int32_t max_attack_compression_diff_db; /* Q8.24 */ +}; + +typedef void (*drc_func)(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames); + +/* DRC component private data */ +struct drc_comp_data { + struct drc_state state; /**< compressor state */ + struct comp_data_blob_handler *model_handler; + struct sof_drc_config *config; /**< pointer to setup blob */ + bool config_ready; /**< set when fully received */ + bool enabled; /**< control processing via blob and switch */ + bool enable_switch; /**< enable switch state */ + enum sof_ipc_frame source_format; /**< source frame format */ + drc_func drc_func; /**< processing function */ +}; + +struct drc_proc_fnmap { + enum sof_ipc_frame frame_fmt; + drc_func drc_proc_func; +}; + +extern const struct drc_proc_fnmap drc_proc_fnmap[]; +extern const size_t drc_proc_fncount; + +void drc_default_pass(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, uint32_t frames); +/** + * \brief Returns DRC processing function. + */ +static inline drc_func drc_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < drc_proc_fncount; i++) + if (src_fmt == drc_proc_fnmap[i].frame_fmt) + return drc_proc_fnmap[i].drc_proc_func; + + return NULL; +} + +#endif // __SOF_AUDIO_DRC_DRC_H__ diff --git a/src/audio/drc/drc.toml b/src/audio/drc/drc.toml new file mode 100644 index 000000000000..a131c7b75451 --- /dev/null +++ b/src/audio/drc/drc.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # DRC module config + [[module.entry]] + name = "DRC" + uuid = UUIDREG_STR_DRC + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/drc/drc_algorithm.h b/src/audio/drc/drc_algorithm.h new file mode 100644 index 000000000000..8d9d759eb3a8 --- /dev/null +++ b/src/audio/drc/drc_algorithm.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ +#ifndef __SOF_AUDIO_DRC_DRC_ALGORITHM_H__ +#define __SOF_AUDIO_DRC_DRC_ALGORITHM_H__ + +#include <stdint.h> +#include <sof/platform.h> + +#include "drc_user.h" +#include "drc.h" + +/* drc reset function */ +void drc_reset_state(struct processing_module *mod, struct drc_state *state); + +/* drc init functions */ +int drc_init_pre_delay_buffers(struct processing_module *mod, + struct drc_state *state, + size_t sample_bytes, + int channels); +int drc_set_pre_delay_time(struct drc_state *state, + int32_t pre_delay_time, + int32_t rate); + +/* drc process functions */ +void drc_update_detector_average(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch); +void drc_update_envelope(struct drc_state *state, const struct sof_drc_params *p); +void drc_compress_output(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch); + +#endif // __SOF_AUDIO_DRC_DRC_ALGORITHM_H__ diff --git a/src/audio/drc/drc_generic.c b/src/audio/drc/drc_generic.c new file mode 100644 index 000000000000..8ace19623045 --- /dev/null +++ b/src/audio/drc/drc_generic.c @@ -0,0 +1,790 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/numbers.h> +#include <sof/common.h> +#include <stdint.h> + +#include "drc.h" +#include "drc_algorithm.h" +#include "drc_math.h" + +#if SOF_USE_HIFI(NONE, DRC) + +#define ONE_Q20 Q_CONVERT_FLOAT(1.0f, 20) /* Q12.20 */ +#define ONE_Q21 Q_CONVERT_FLOAT(1.0f, 21) /* Q11.21 */ +#define ONE_Q30 Q_CONVERT_FLOAT(1.0f, 30) /* Q2.30 */ +#define TWELVE_Q21 Q_CONVERT_FLOAT(12.0f, 21) /* Q11.21 */ +#define HALF_Q24 Q_CONVERT_FLOAT(0.5f, 24) /* Q8.24 */ +#define NEG_TWO_DB_Q30 Q_CONVERT_FLOAT(0.7943282347242815f, 30) /* -2dB = 10^(-2/20); Q2.30 */ + +/* This is the knee part of the compression curve. Returns the output level + * given the input level x. */ +static int32_t knee_curveK(const struct sof_drc_params *p, int32_t x) +{ + int32_t knee_exp_gamma; + + /* The formula in knee_curveK is linear_threshold + + * (1 - expf(-k * (x - linear_threshold))) / k + * which simplifies to (alpha + beta * expf(gamma)) + * where alpha = linear_threshold + 1 / k + * beta = -expf(k * linear_threshold) / k + * gamma = -k * x + */ + knee_exp_gamma = sofm_exp_fixed(Q_MULTSR_32X32((int64_t)x, -p->K, 31, 20, 27)); /* Q12.20 */ + return p->knee_alpha + Q_MULTSR_32X32((int64_t)p->knee_beta, knee_exp_gamma, 24, 20, 24); +} + +/* Full compression curve with constant ratio after knee. Returns the ratio of + * output and input signal. */ +static int32_t volume_gain(const struct sof_drc_params *p, int32_t x) +{ + const int32_t knee_threshold = + sat_int32(Q_SHIFT_LEFT((int64_t)p->knee_threshold, 24, 31)); + const int32_t linear_threshold = + sat_int32(Q_SHIFT_LEFT((int64_t)p->linear_threshold, 30, 31)); + int32_t exp_knee; + int32_t y; + + if (x < knee_threshold) { + if (x < linear_threshold) + return ONE_Q30; + /* y = knee_curveK(x) / x */ + y = Q_MULTSR_32X32((int64_t)knee_curveK(p, x), drc_inv_fixed(x, 31, 20), + 24, 20, 30); + } else { + /* Constant ratio after knee. + * log(y/y0) = s * log(x/x0) + * => y = y0 * (x/x0)^s + * => y = [y0 * (1/x0)^s] * x^s + * => y = ratio_base * x^s + * => y/x = ratio_base * x^(s - 1) + * => y/x = ratio_base * e^(log(x) * (s - 1)) + */ + exp_knee = sofm_exp_fixed(Q_MULTSR_32X32((int64_t) + drc_log_fixed(Q_SHIFT_RND(x, 31, 26)), + (p->slope - ONE_Q30), + 26, 30, 27)); /* Q12.20 */ + y = Q_MULTSR_32X32((int64_t)p->ratio_base, exp_knee, 30, 20, 30); + } + + return y; +} + +/* Update detector_average from the last input division. */ +void drc_update_detector_average(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + int32_t detector_average = state->detector_average; /* Q2.30 */ + int32_t abs_input_array[DRC_DIVISION_FRAMES]; /* Q1.31 */ + int div_start, i, ch; + int16_t *sample16_p; /* for s16 format case */ + int32_t *sample32_p; /* for s24 and s32 format cases */ + int32_t sample; + int32_t gain; + int32_t gain_diff; + int is_release; + int32_t db_per_frame; + int32_t sat_release_rate; + + /* Calculate the start index of the last input division */ + if (state->pre_delay_write_index == 0) { + div_start = CONFIG_DRC_MAX_PRE_DELAY_FRAMES - DRC_DIVISION_FRAMES; + } else { + div_start = state->pre_delay_write_index - DRC_DIVISION_FRAMES; + } + + /* The max abs value across all channels for this frame */ + if (nbyte == 2) { /* 2 bytes per sample */ + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + abs_input_array[i] = 0; + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + div_start + i; + sample = Q_SHIFT_LEFT((int32_t)*sample16_p, 15, 31); + abs_input_array[i] = MAX(abs_input_array[i], ABS(sample)); + } + } + } else { /* 4 bytes per sample */ + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + abs_input_array[i] = 0; + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + div_start + i; + sample = *sample32_p; + abs_input_array[i] = MAX(abs_input_array[i], ABS(sample)); + } + } + } + + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + /* Compute compression amount from un-delayed signal */ + + /* Calculate shaped power on undelayed input. Put through + * shaping curve. This is linear up to the threshold, then + * enters a "knee" portion followed by the "ratio" portion. The + * transition from the threshold to the knee is smooth (1st + * derivative matched). The transition from the knee to the + * ratio portion is smooth (1st derivative matched). + */ + gain = volume_gain(p, abs_input_array[i]); /* Q2.30 */ + gain_diff = gain - detector_average; /* Q2.30 */ + is_release = (gain_diff > 0); + if (is_release) { + if (gain > NEG_TWO_DB_Q30) { + detector_average += + Q_MULTSR_32X32((int64_t)gain_diff, + p->sat_release_rate_at_neg_two_db, + 30, 30, 30); + } else { + db_per_frame = + Q_MULTSR_32X32((int64_t)drc_lin2db_fixed(Q_SHIFT_RND(gain, + 30, + 26)), + p->sat_release_frames_inv_neg, + 21, 30, 24); /* Q8.24 */ + sat_release_rate = + sofm_db2lin_fixed(db_per_frame) - ONE_Q20; /* Q12.20 */ + detector_average += Q_MULTSR_32X32((int64_t)gain_diff, + sat_release_rate, 30, 20, 30); + } + } else { + detector_average = gain; + } + + detector_average = MIN(detector_average, ONE_Q30); + } + + state->detector_average = detector_average; +} + +/* Updates the envelope_rate used for the next division */ +void drc_update_envelope(struct drc_state *state, const struct sof_drc_params *p) +{ + /* Calculate desired gain */ + + /* Pre-warp so we get desired_gain after sin() warp below. */ + int32_t scaled_desired_gain = drc_asin_fixed(state->detector_average); /* Q2.30 */ + + /* Deal with envelopes */ + + /* envelope_rate is the rate we slew from current compressor level to + * the desired level. The exact rate depends on if we're attacking or + * releasing and by how much. + */ + int32_t envelope_rate; + + int is_releasing = scaled_desired_gain > state->compressor_gain; + + /* compression_diff_db is the difference between current compression + * level and the desired level. */ + int is_bad_db = (state->compressor_gain == 0 || scaled_desired_gain == 0); + int32_t compression_diff_db = + drc_lin2db_fixed(Q_SHIFT_RND(state->compressor_gain, 30, 26)) - + drc_lin2db_fixed(Q_SHIFT_RND(scaled_desired_gain, 30, 26)); /* Q11.21 */ + + int32_t x, x2, x3, x4; + int32_t release_frames; + int32_t db_per_frame; + int32_t eff_atten_diff_db; + + if (is_releasing) { + /* Release mode - compression_diff_db should be negative dB */ + state->max_attack_compression_diff_db = INT32_MIN; + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = -ONE_Q21; + + /* Adaptive release - higher compression (lower + * compression_diff_db) releases faster. Contain within range: + * -12 -> 0 then scale to go from 0 -> 3 + */ + x = compression_diff_db; /* Q11.21 */ + x = MAX(-TWELVE_Q21, x); + x = MIN(0, x); + /* x = 0.25f * (x + 12) */ + x = Q_SHIFT_RND(x + TWELVE_Q21, 21, 19); + + /* Compute adaptive release curve using 4th order polynomial. + * Normal values for the polynomial coefficients would create a + * monotonically increasing function. + */ + x2 = Q_MULTSR_32X32((int64_t)x, x, 21, 21, 21); /* Q11.21 */ + x3 = Q_MULTSR_32X32((int64_t)x2, x, 21, 21, 21); /* Q11.21 */ + x4 = Q_MULTSR_32X32((int64_t)x2, x2, 21, 21, 21); /* Q11.21 */ + + release_frames = Q_MULTSR_32X32((int64_t)p->kE, x4, 12, 21, 12) + + Q_MULTSR_32X32((int64_t)p->kD, x3, 12, 21, 12) + + Q_MULTSR_32X32((int64_t)p->kC, x2, 12, 21, 12) + + Q_MULTSR_32X32((int64_t)p->kB, x, 12, 21, 12) + p->kA; + /* db_per_frame = kSpacingDb / release_frames */ + db_per_frame = drc_inv_fixed(release_frames, 12, 30); /* Q2.30 */ + db_per_frame = Q_MULTSR_32X32((int64_t)db_per_frame, p->kSpacingDb, 30, 0, 24); + envelope_rate = sofm_db2lin_fixed(db_per_frame); /* Q12.20 */ + } else { + int32_t sat32; + /* Attack mode - compression_diff_db should be positive dB */ + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = ONE_Q21; + + /* As long as we're still in attack mode, use a rate based off + * the largest compression_diff_db we've encountered so far. + */ + sat32 = sat_int32(Q_SHIFT_LEFT((int64_t)compression_diff_db, 21, 24)); + state->max_attack_compression_diff_db = + MAX(state->max_attack_compression_diff_db, sat32); + + eff_atten_diff_db = + MAX(HALF_Q24, state->max_attack_compression_diff_db); /* Q8.24 */ + + /* x = 0.25f / eff_atten_diff_db; + * => x = 1.0f / (eff_atten_diff_db << 2); + */ + x = drc_inv_fixed(eff_atten_diff_db, 22 /* Q8.24 << 2 */, 26); /* Q6.26 */ + envelope_rate = ONE_Q20 - drc_pow_fixed(x, p->one_over_attack_frames); /* Q12.20 */ + } + + state->envelope_rate = sat_int32(Q_SHIFT_LEFT((int64_t)envelope_rate, 20, 30)); + state->scaled_desired_gain = scaled_desired_gain; +} + +/* Calculate compress_gain from the envelope and apply total_gain to compress + * the next output division. */ +void drc_compress_output(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + const int div_start = state->pre_delay_read_index; + int count = DRC_DIVISION_FRAMES >> 2; + + int32_t c, base, r, r2, r4; /* Q2.30 */ + int32_t x[4]; /* Q2.30 */ + int32_t post_warp_compressor_gain; + int32_t total_gain; + + int i, j, ch, inc; + int16_t *sample16_p; /* for s16 format case */ + int32_t *sample32_p; /* for s24 and s32 format cases */ + int32_t sample; + int is_2byte = (nbyte == 2); /* otherwise is 4-bytes */ + + /* Exponential approach to desired gain. */ + if (state->envelope_rate < ONE_Q30) { + /* Attack - reduce gain to desired. */ + c = state->compressor_gain - state->scaled_desired_gain; + base = state->scaled_desired_gain; + r = ONE_Q30 - state->envelope_rate; + x[0] = Q_MULTSR_32X32((int64_t)c, r, 30, 30, 30); + for (j = 1; j < 4; j++) + x[j] = Q_MULTSR_32X32((int64_t)x[j - 1], r, 30, 30, 30); + r2 = Q_MULTSR_32X32((int64_t)r, r, 30, 30, 30); + r4 = Q_MULTSR_32X32((int64_t)r2, r2, 30, 30, 30); + + i = 0; + inc = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = + drc_sin_fixed(x[j] + base); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + total_gain = Q_MULTSR_32X32((int64_t)p->master_linear_gain, + post_warp_compressor_gain, + 24, 31, 24); /* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = (int32_t)*sample16_p; + *sample16_p = + sat_int16(Q_MULTSR_32X32((int64_t)sample, + total_gain, + 15, 24, 15)); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = Q_MULTSR_32X32((int64_t)x[j], r4, 30, 30, 30); + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = + drc_sin_fixed(x[j] + base); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + total_gain = Q_MULTSR_32X32((int64_t)p->master_linear_gain, + post_warp_compressor_gain, + 24, 31, 24); /* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = *sample32_p; + *sample32_p = + sat_int32(Q_MULTSR_32X32((int64_t)sample, + total_gain, + 31, 24, 31)); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = Q_MULTSR_32X32((int64_t)x[j], r4, 30, 30, 30); + } + } + + state->compressor_gain = x[3] + base; + } else { + /* Release - exponentially increase gain to 1.0 */ + c = state->compressor_gain; + r = state->envelope_rate; + x[0] = Q_MULTSR_32X32((int64_t)c, r, 30, 30, 30); + for (j = 1; j < 4; j++) + x[j] = Q_MULTSR_32X32((int64_t)x[j - 1], r, 30, 30, 30); + r2 = Q_MULTSR_32X32((int64_t)r, r, 30, 30, 30); + r4 = Q_MULTSR_32X32((int64_t)r2, r2, 30, 30, 30); + + i = 0; + inc = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + total_gain = Q_MULTSR_32X32((int64_t)p->master_linear_gain, + post_warp_compressor_gain, + 24, 31, 24); /* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = (int32_t)*sample16_p; + *sample16_p = + sat_int16(Q_MULTSR_32X32((int64_t)sample, + total_gain, + 15, 24, 15)); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = MIN(ONE_Q30, + Q_MULTSR_32X32((int64_t)x[j], r4, 30, 30, 30)); + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + total_gain = Q_MULTSR_32X32((int64_t)p->master_linear_gain, + post_warp_compressor_gain, + 24, 31, 24); /* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = *sample32_p; + *sample32_p = + sat_int32(Q_MULTSR_32X32((int64_t)sample, + total_gain, + 31, 24, 31)); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = MIN(ONE_Q30, + Q_MULTSR_32X32((int64_t)x[j], r4, 30, 30, 30)); + } + } + + state->compressor_gain = x[3]; + } +} + +#endif /* DRC_HIFI_NONE */ + +#if SOF_USE_HIFI(NONE, DRC) || SOF_USE_HIFI(3, DRC) +/* After one complete division of samples have been received (and one division of + * samples have been output), we calculate shaped power average + * (detector_average) from the input division, update envelope parameters from + * detector_average, then prepare the next output division by applying the + * envelope to compress the samples. + */ +static void drc_process_one_division(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + drc_update_detector_average(state, p, nbyte, nch); + drc_update_envelope(state, p); + drc_compress_output(state, p, nbyte, nch); +} + +void drc_default_pass(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, uint32_t frames) +{ + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); +} + +static inline void drc_pre_delay_index_inc(int *idx, int increment) +{ + *idx = (*idx + increment) & DRC_MAX_PRE_DELAY_FRAMES_MASK; +} + +#if CONFIG_FORMAT_S16LE +static void drc_delay_input_sample_s16(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int16_t **x, int16_t **y, int samples) +{ + int16_t *x1; + int16_t *y1; + int16_t *pd; + int pd_write_index, pd_read_index; + int nbuf, npcm, nfrm; + int ch; + int i; + int16_t *x0 = *x; + int16_t *y0 = *y; + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s16(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s16(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (int16_t *)state->pre_delay_buffers[ch]; + x1 = x0 + ch; + y1 = y0 + ch; + pd_write_index = state->pre_delay_write_index; + pd_read_index = state->pre_delay_read_index; + for (i = 0; i < nfrm; i++) { + *(pd + pd_write_index) = *x1; + *y1 = *(pd + pd_read_index); + drc_pre_delay_index_inc(&pd_write_index, 1); + drc_pre_delay_index_inc(&pd_read_index, 1); + x1 += nch; + y1 += nch; + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = x0; + *y = y0; +} + +static void drc_s16_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment_samples; + int fragment; + + if (!cd->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. + */ + drc_delay_input_sample_s16(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int16_t), nch); + state->processed = 1; + } + + while (samples) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment_samples = fragment * nch; + fragment_samples = MIN(samples, fragment_samples); + drc_delay_input_sample_s16(state, source, sink, &x, &y, fragment_samples); + samples -= fragment_samples; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int16_t), nch); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +static void drc_delay_input_sample_s32(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int32_t **x, int32_t **y, int samples) +{ + int32_t *x1; + int32_t *y1; + int32_t *pd; + int pd_write_index, pd_read_index; + int nbuf, npcm, nfrm; + int ch; + int i; + int32_t *x0 = *x; + int32_t *y0 = *y; + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s32(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s32(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (int32_t *)state->pre_delay_buffers[ch]; + x1 = x0 + ch; + y1 = y0 + ch; + pd_write_index = state->pre_delay_write_index; + pd_read_index = state->pre_delay_read_index; + for (i = 0; i < nfrm; i++) { + *(pd + pd_write_index) = *x1; + *y1 = *(pd + pd_read_index); + drc_pre_delay_index_inc(&pd_write_index, 1); + drc_pre_delay_index_inc(&pd_read_index, 1); + x1 += nch; + y1 += nch; + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = x0; + *y = y0; +} +#endif + +#if CONFIG_FORMAT_S24LE +static void drc_delay_input_sample_s24(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int32_t **x, int32_t **y, int samples) +{ + int32_t *x1; + int32_t *y1; + int32_t *pd; + int pd_write_index, pd_read_index; + int nbuf, npcm, nfrm; + int ch; + int i; + int32_t *x0 = *x; + int32_t *y0 = *y; + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s24(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s24(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (int32_t *)state->pre_delay_buffers[ch]; + x1 = x0 + ch; + y1 = y0 + ch; + pd_write_index = state->pre_delay_write_index; + pd_read_index = state->pre_delay_read_index; + for (i = 0; i < nfrm; i++) { + *(pd + pd_write_index) = *x1 << 8; + *y1 = sat_int24(Q_SHIFT_RND(*(pd + pd_read_index), 31, 23)); + drc_pre_delay_index_inc(&pd_write_index, 1); + drc_pre_delay_index_inc(&pd_read_index, 1); + x1 += nch; + y1 += nch; + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = x0; + *y = y0; +} + +static void drc_s24_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment_samples; + int fragment; + + if (!cd->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. Note: use 32 bit delay function. + */ + drc_delay_input_sample_s32(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int32_t), nch); + state->processed = 1; + } + + while (samples) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment_samples = fragment * nch; + fragment_samples = MIN(samples, fragment_samples); + + /* Use 24 bit delay function */ + drc_delay_input_sample_s24(state, source, sink, &x, &y, fragment_samples); + samples -= fragment_samples; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int32_t), nch); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void drc_s32_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment_samples; + int fragment; + + if (!cd->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. + */ + drc_delay_input_sample_s32(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int32_t), nch); + state->processed = 1; + } + + while (samples) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment_samples = fragment * nch; + fragment_samples = MIN(samples, fragment_samples); + drc_delay_input_sample_s32(state, source, sink, &x, &y, fragment_samples); + samples -= fragment_samples; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int32_t), nch); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct drc_proc_fnmap drc_proc_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, drc_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, drc_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, drc_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t drc_proc_fncount = ARRAY_SIZE(drc_proc_fnmap); +#endif diff --git a/src/audio/drc/drc_hifi3.c b/src/audio/drc/drc_hifi3.c new file mode 100644 index 000000000000..3a5d23c7d230 --- /dev/null +++ b/src/audio/drc/drc_hifi3.c @@ -0,0 +1,498 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/numbers.h> +#include <sof/common.h> +#include <stdint.h> + +#include "drc.h" +#include "drc_algorithm.h" +#include "drc_math.h" + +#if SOF_USE_HIFI(3, DRC) + +#include <xtensa/tie/xt_hifi3.h> + +#define ONE_Q20 1048576 /* Q_CONVERT_FLOAT(1.0f, 20) */ +#define ONE_Q21 2097152 /* Q_CONVERT_FLOAT(1.0f, 21) */ +#define ONE_Q30 1073741824 /* Q_CONVERT_FLOAT(1.0f, 30) */ +#define TWELVE_Q21 25165824 /* Q_CONVERT_FLOAT(12.0f, 21) */ +#define HALF_Q24 8388608 /* Q_CONVERT_FLOAT(0.5f, 24) */ +#define NEG_TWO_DB_Q30 852903424 /* Q_CONVERT_FLOAT(0.7943282347242815f, 30) */ + +/* This is the knee part of the compression curve. Returns the output level + * given the input level x. + */ +static int32_t knee_curveK(const struct sof_drc_params *p, int32_t x) +{ + ae_f32 gamma; /* Q5.27 */ + ae_f32 knee_exp_gamma; /* Q12.20 */ + ae_f32 knee_curve_k; /* Q8.24 */ + + /* The formula in knee_curveK is linear_threshold + + * (1 - expf(-k * (x - linear_threshold))) / k + * which simplifies to (alpha + beta * expf(gamma)) + * where alpha = linear_threshold + 1 / k + * beta = -expf(k * linear_threshold) / k + * gamma = -k * x + */ + gamma = drc_mult_lshift(x, -p->K, drc_get_lshift(31, 20, 27)); + knee_exp_gamma = sofm_exp_fixed(gamma); + knee_curve_k = drc_mult_lshift(p->knee_beta, knee_exp_gamma, drc_get_lshift(24, 20, 24)); + knee_curve_k = AE_ADD32(knee_curve_k, p->knee_alpha); + return knee_curve_k; +} + +/* Full compression curve with constant ratio after knee. Returns the ratio of + * output and input signal. + */ +static int32_t volume_gain(const struct sof_drc_params *p, int32_t x) +{ + const ae_f32 knee_threshold = AE_SLAI32S(p->knee_threshold, 7); /* Q8.24 -> Q1.31 */ + const ae_f32 linear_threshold = AE_SLAI32S(p->linear_threshold, 1); /* Q2.30 -> Q1.31 */ + ae_f32 exp_knee; /* Q12.20 */ + ae_f32 y; /* Q2.30 */ + ae_f32 tmp; + ae_f32 tmp2; + + if (x < (int32_t)knee_threshold) { + if (x < (int32_t)linear_threshold) + return ONE_Q30; + /* y = knee_curveK(x) / x */ + y = drc_mult_lshift(knee_curveK(p, x), drc_inv_fixed(x, 31, 20), + drc_get_lshift(24, 20, 30)); + } else { + /* Constant ratio after knee. + * log(y/y0) = s * log(x/x0) + * => y = y0 * (x/x0)^s + * => y = [y0 * (1/x0)^s] * x^s + * => y = ratio_base * x^s + * => y/x = ratio_base * x^(s - 1) + * => y/x = ratio_base * e^(log(x) * (s - 1)) + */ + tmp = AE_SRAI32R(x, 5); /* Q1.31 -> Q5.26 */ + tmp = drc_log_fixed(tmp); /* Q6.26 */ + tmp2 = AE_SUB32(p->slope, ONE_Q30); /* Q2.30 */ + exp_knee = sofm_exp_fixed(drc_mult_lshift(tmp, tmp2, drc_get_lshift(26, 30, 27))); + y = drc_mult_lshift(p->ratio_base, exp_knee, drc_get_lshift(30, 20, 30)); + } + + return y; +} + +/* Update detector_average from the last input division. */ +void drc_update_detector_average(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + ae_f32 detector_average = state->detector_average; /* Q2.30 */ + int32_t abs_input_array[DRC_DIVISION_FRAMES]; /* Q1.31 */ + int32_t *abs_input_array_p; + int div_start, i, ch; + int16_t *sample16_p; /* for s16 format case */ + int32_t *sample32_p; /* for s24 and s32 format cases */ + int32_t sample; + ae_f32 gain; + ae_f32 gain_diff; + ae_f32 db_per_frame; + ae_f32 sat_release_rate; + ae_f32 tmp; + int is_release; + + /* Calculate the start index of the last input division */ + if (state->pre_delay_write_index == 0) + div_start = CONFIG_DRC_MAX_PRE_DELAY_FRAMES - DRC_DIVISION_FRAMES; + else + div_start = state->pre_delay_write_index - DRC_DIVISION_FRAMES; + + /* The max abs value across all channels for this frame */ + memset(abs_input_array, 0, DRC_DIVISION_FRAMES * sizeof(int32_t)); + if (nbyte == 2) { /* 2 bytes per sample */ + for (ch = 0; ch < nch; ch++) { + abs_input_array_p = abs_input_array; + sample16_p = (int16_t *)state->pre_delay_buffers[ch] + div_start; + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + sample = (int32_t)*sample16_p << 16; + *abs_input_array_p = MAX(*abs_input_array_p, ABS(sample)); + abs_input_array_p++; + sample16_p++; + } + } + } else { /* 4 bytes per sample */ + for (ch = 0; ch < nch; ch++) { + abs_input_array_p = abs_input_array; + sample32_p = (int32_t *)state->pre_delay_buffers[ch] + div_start; + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + sample = *sample32_p; + *abs_input_array_p = MAX(*abs_input_array_p, ABS(sample)); + abs_input_array_p++; + sample32_p++; + } + } + } + + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + /* Compute compression amount from un-delayed signal */ + + /* Calculate shaped power on undelayed input. Put through + * shaping curve. This is linear up to the threshold, then + * enters a "knee" portion followed by the "ratio" portion. The + * transition from the threshold to the knee is smooth (1st + * derivative matched). The transition from the knee to the + * ratio portion is smooth (1st derivative matched). + */ + gain = volume_gain(p, abs_input_array[i]); /* Q2.30 */ + gain_diff = AE_SUB32(gain, detector_average); /* Q2.30 */ + is_release = ((int32_t)gain_diff > 0); + if (is_release) { + if ((int32_t)gain > NEG_TWO_DB_Q30) { + tmp = drc_mult_lshift(gain_diff, p->sat_release_rate_at_neg_two_db, + drc_get_lshift(30, 30, 30)); + } else { + gain = AE_SRAI32R(gain, 4); /* Q2.30 -> Q6.26 */ + db_per_frame = drc_mult_lshift(drc_lin2db_fixed(gain), + p->sat_release_frames_inv_neg, + drc_get_lshift(21, 30, 24)); + sat_release_rate = AE_SUB32(sofm_db2lin_fixed(db_per_frame), + ONE_Q20); + tmp = drc_mult_lshift(gain_diff, sat_release_rate, + drc_get_lshift(30, 20, 30)); + } + detector_average = AE_ADD32(detector_average, tmp); + } else { + detector_average = gain; + } + + detector_average = AE_MIN32(detector_average, ONE_Q30); + } + + state->detector_average = detector_average; +} + +/* Updates the envelope_rate used for the next division */ +void drc_update_envelope(struct drc_state *state, const struct sof_drc_params *p) +{ + /* Deal with envelopes */ + + /* envelope_rate is the rate we slew from current compressor level to + * the desired level. The exact rate depends on if we're attacking or + * releasing and by how much. + */ + ae_f32 envelope_rate; + + /* compression_diff_db is the difference between current compression + * level and the desired level. + */ + ae_f32 compression_diff_db; + ae_f32 x, x2, x3, x4; + ae_f64 release_frames_f64; + ae_f32 release_frames; + ae_f32 db_per_frame; + ae_f32 tmp; + ae_f32 tmp2; + int32_t scaled_desired_gain; + int32_t eff_atten_diff_db; + int32_t lshift; + int32_t is_releasing; + int32_t is_bad_db; + + /* Calculate desired gain */ + + /* Pre-warp so we get desired_gain after sin() warp below. */ + scaled_desired_gain = drc_asin_fixed(state->detector_average); /* Q2.30 */ + + is_releasing = scaled_desired_gain > state->compressor_gain; + is_bad_db = (state->compressor_gain == 0 || scaled_desired_gain == 0); + + tmp = AE_SRAI32R(state->compressor_gain, 4); /* Q2.30 -> Q6.26 */ + tmp2 = AE_SRAI32R(scaled_desired_gain, 4); /* Q2.30 -> Q6.26 */ + compression_diff_db = AE_SUB32(drc_lin2db_fixed(tmp), drc_lin2db_fixed(tmp2)); /* Q11.21 */ + + if (is_releasing) { + /* Release mode - compression_diff_db should be negative dB */ + state->max_attack_compression_diff_db = INT32_MIN; + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = -ONE_Q21; + + /* Adaptive release - higher compression (lower + * compression_diff_db) releases faster. Contain within range: + * -12 -> 0 then scale to go from 0 -> 3 + */ + x = compression_diff_db; /* Q11.21 */ + x = AE_MAX32(-TWELVE_Q21, x); + x = AE_MIN32(0, x); + /* x = 0.25f * (x + 12) */ + x = AE_SRAI32R(AE_ADD32(x, TWELVE_Q21), 2); /* Q11.21 -> Q13.19 */ + + /* Compute adaptive release curve using 4th order polynomial. + * Normal values for the polynomial coefficients would create a + * monotonically increasing function. + */ + lshift = drc_get_lshift(21, 21, 21); + x2 = drc_mult_lshift(x, x, lshift); /* Q11.21 */ + x3 = drc_mult_lshift(x2, x, lshift); /* Q11.21 */ + x4 = drc_mult_lshift(x2, x2, lshift); /* Q11.21 */ + + release_frames_f64 = AE_CVT48A32(p->kA); /* Q20.12 -> Q36.28 */ + release_frames_f64 = AE_SRAI64(release_frames_f64, 10); /* Q36.28 -> Q46.18 */ + AE_MULAF32R_LL(release_frames_f64, p->kB, x); /* Q20.12 * Q11.21 = Q46.18 */ + AE_MULAF32R_LL(release_frames_f64, p->kC, x2); + AE_MULAF32R_LL(release_frames_f64, p->kD, x3); + AE_MULAF32R_LL(release_frames_f64, p->kE, x4); + release_frames_f64 = AE_SLAI64S(release_frames_f64, 10); /* Q46.18 -> Q36.28 */ + release_frames = AE_ROUND32F48SSYM(release_frames_f64); /* Q36.28 -> Q20.12 */ + + /* db_per_frame = kSpacingDb / release_frames */ + db_per_frame = drc_inv_fixed(release_frames, 12, 30); /* Q2.30 */ + tmp = p->kSpacingDb << 16; /* Q16.16 */ + lshift = drc_get_lshift(30, 16, 24); + db_per_frame = drc_mult_lshift(db_per_frame, tmp, lshift); /* Q8.24 */ + envelope_rate = sofm_db2lin_fixed(db_per_frame); /* Q12.20 */ + } else { + /* Attack mode - compression_diff_db should be positive dB */ + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = ONE_Q21; + + /* As long as we're still in attack mode, use a rate based off + * the largest compression_diff_db we've encountered so far. + */ + tmp = AE_SLAI32S(compression_diff_db, 3); /* Q11.21 -> Q8.24 */ + state->max_attack_compression_diff_db = + AE_MAX32(state->max_attack_compression_diff_db, tmp); + + eff_atten_diff_db = + MAX(HALF_Q24, state->max_attack_compression_diff_db); /* Q8.24 */ + + /* x = 0.25f / eff_atten_diff_db; + * => x = 1.0f / (eff_atten_diff_db << 2); + */ + x = drc_inv_fixed(eff_atten_diff_db, 22 /* Q8.24 << 2 */, 26); /* Q6.26 */ + envelope_rate = AE_SUB32(ONE_Q20, + drc_pow_fixed(x, p->one_over_attack_frames)); /* Q12.20 */ + } + + tmp = AE_SLAI32S(envelope_rate, 10); /* Q12.20 -> Q2.30 */ + state->envelope_rate = tmp; + state->scaled_desired_gain = scaled_desired_gain; +} + +/* Calculate compress_gain from the envelope and apply total_gain to compress + * the next output division. + */ +void drc_compress_output(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + const int div_start = state->pre_delay_read_index; + const int count = DRC_DIVISION_FRAMES >> 2; + + ae_f32 x[4]; /* Q2.30 */ + ae_f32 c, base, r, r2, r4; /* Q2.30 */ + ae_f32 post_warp_compressor_gain; + ae_f32 total_gain; + ae_f32 tmp; + + int i, j, ch, inc; + int16_t *sample16_p; /* for s16 format case */ + int32_t *sample32_p; /* for s24 and s32 format cases */ + int32_t sample; + int32_t lshift; + int is_2byte = (nbyte == 2); /* otherwise is 4-bytes */ + + /* Exponential approach to desired gain. */ + if (state->envelope_rate < ONE_Q30) { + /* Attack - reduce gain to desired. */ + c = AE_SUB32(state->compressor_gain, state->scaled_desired_gain); + base = state->scaled_desired_gain; + r = AE_SUB32(ONE_Q30, state->envelope_rate); + lshift = drc_get_lshift(30, 30, 30); + x[0] = drc_mult_lshift(c, r, lshift); + for (j = 1; j < 4; j++) + x[j] = drc_mult_lshift(x[j - 1], r, lshift); + r2 = drc_mult_lshift(r, r, lshift); + r4 = drc_mult_lshift(r2, r2, lshift); + + i = 0; + inc = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + tmp = AE_ADD32(x[j], base); + post_warp_compressor_gain = drc_sin_fixed(tmp); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + lshift = drc_get_lshift(24, 31, 24); + total_gain = drc_mult_lshift(p->master_linear_gain, + post_warp_compressor_gain, + lshift); /* Q8.24 */ + + /* Apply final gain. */ + lshift = drc_get_lshift(15, 24, 15); + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = (int32_t)*sample16_p; + sample = drc_mult_lshift(sample, total_gain, + lshift); + *sample16_p = sat_int16(sample); + } + inc++; + } + + if (++i == count) + break; + + lshift = drc_get_lshift(30, 30, 30); + for (j = 0; j < 4; j++) + x[j] = drc_mult_lshift(x[j], r4, lshift); + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + tmp = AE_ADD32(x[j], base); + post_warp_compressor_gain = drc_sin_fixed(tmp); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + lshift = drc_get_lshift(24, 31, 24); + total_gain = drc_mult_lshift(p->master_linear_gain, + post_warp_compressor_gain, + lshift); /* Q8.24 */ + + /* Apply final gain. */ + lshift = drc_get_lshift(31, 24, 31); + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = *sample32_p; + sample = drc_mult_lshift(sample, total_gain, + lshift); + *sample32_p = sample; + } + inc++; + } + + if (++i == count) + break; + + lshift = drc_get_lshift(30, 30, 30); + for (j = 0; j < 4; j++) + x[j] = drc_mult_lshift(x[j], r4, lshift); + } + } + + tmp = AE_ADD32(x[3], base); + state->compressor_gain = tmp; + } else { + /* Release - exponentially increase gain to 1.0 */ + c = state->compressor_gain; + r = state->envelope_rate; + lshift = drc_get_lshift(30, 30, 30); + x[0] = drc_mult_lshift(c, r, lshift); + for (j = 1; j < 4; j++) + x[j] = drc_mult_lshift(x[j - 1], r, lshift); + r2 = drc_mult_lshift(r, r, lshift); + r4 = drc_mult_lshift(r2, r2, lshift); + + i = 0; + inc = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + lshift = drc_get_lshift(24, 31, 24); + total_gain = drc_mult_lshift(p->master_linear_gain, + post_warp_compressor_gain, + lshift); /* Q8.24 */ + + /* Apply final gain. */ + lshift = drc_get_lshift(15, 24, 15); + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = (int32_t)*sample16_p; + sample = drc_mult_lshift(sample, total_gain, + lshift); + *sample16_p = sat_int16(sample); + } + inc++; + } + + if (++i == count) + break; + + lshift = drc_get_lshift(30, 30, 30); + for (j = 0; j < 4; j++) { + tmp = drc_mult_lshift(x[j], r4, lshift); + x[j] = AE_MIN32(ONE_Q30, tmp); + } + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + lshift = drc_get_lshift(24, 31, 24); + total_gain = drc_mult_lshift(p->master_linear_gain, + post_warp_compressor_gain, + lshift); /* Q8.24 */ + + /* Apply final gain. */ + lshift = drc_get_lshift(31, 24, 31); + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + div_start + inc; + sample = *sample32_p; + sample = drc_mult_lshift(sample, total_gain, + lshift); + *sample32_p = sample; + } + inc++; + } + + if (++i == count) + break; + + lshift = drc_get_lshift(30, 30, 30); + for (j = 0; j < 4; j++) { + tmp = drc_mult_lshift(x[j], r4, lshift); + x[j] = AE_MIN32(ONE_Q30, tmp); + } + } + } + + state->compressor_gain = x[3]; + } +} + +#endif /* DRC_HIFI_3 */ diff --git a/src/audio/drc/drc_hifi4.c b/src/audio/drc/drc_hifi4.c new file mode 100644 index 000000000000..b2252058e885 --- /dev/null +++ b/src/audio/drc/drc_hifi4.c @@ -0,0 +1,920 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/numbers.h> +#include <sof/common.h> +#include <stdint.h> + +#include "drc.h" +#include "drc_algorithm.h" +#include "drc_math.h" + +#if SOF_USE_MIN_HIFI(4, DRC) + +#include <xtensa/tie/xt_hifi4.h> + +#define ONE_Q20 1048576 /* Q_CONVERT_FLOAT(1.0f, 20) */ +#define ONE_Q21 2097152 /* Q_CONVERT_FLOAT(1.0f, 21) */ +#define ONE_Q30 1073741824 /* Q_CONVERT_FLOAT(1.0f, 30) */ +#define TWELVE_Q21 25165824 /* Q_CONVERT_FLOAT(12.0f, 21) */ +#define HALF_Q24 8388608 /* Q_CONVERT_FLOAT(0.5f, 24) */ +#define NEG_TWO_DB_Q30 852903424 /* Q_CONVERT_FLOAT(0.7943282347242815f, 30) */ +#define LSHIFT_QX31_QY20_QZ27 7 /*drc_get_lshift(31, 20, 27)*/ +#define LSHIFT_QX24_QY20_QZ24 11 /*drc_get_lshift(24, 20, 24)*/ +#define LSHIFT_QX24_QY20_QZ30 17 /*drc_get_lshift(24, 20, 30)*/ +#define LSHIFT_QX30_QY20_QZ30 11 /*drc_get_lshift(30, 20, 30)*/ +#define LSHIFT_QX30_QY30_QZ30 1 /*drc_get_lshift(30, 30, 30)*/ +#define LSHIFT_QX26_QY30_QZ27 2 /*drc_get_lshift(26, 30, 27)*/ +#define LSHIFT_QX21_QY30_QZ24 4 /*drc_get_lshift(21, 30, 24)*/ +#define LSHIFT_QX21_QY21_QZ21 10 /*drc_get_lshift(21, 21, 21)*/ +#define LSHIFT_QX30_QY16_QZ24 9 /*drc_get_lshift(31, 16, 24)*/ +#define LSHIFT_QX15_QY24_QZ15 7 /*drc_get_lshift(15, 24, 15)*/ +#define LSHIFT_QX31_QY24_QZ31 7 /*drc_get_lshift(31, 24, 31)*/ + +/* This is the knee part of the compression curve. Returns the output level + * given the input level x. + */ +static inline void set_circular_buf0(void *buf, void *buf_end) +{ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); +} + +static inline void set_circular_buf1(void *buf, void *buf_end) +{ + AE_SETCBEGIN1(buf); + AE_SETCEND1(buf_end); +} + +static int32_t knee_curveK(const struct sof_drc_params *p, int32_t x) +{ + ae_f32 gamma; /* Q5.27 */ + ae_f32 knee_exp_gamma; /* Q12.20 */ + ae_f32 knee_curve_k; /* Q8.24 */ + + /* The formula in knee_curveK is linear_threshold + + * (1 - expf(-k * (x - linear_threshold))) / k + * which simplifies to (alpha + beta * expf(gamma)) + * where alpha = linear_threshold + 1 / k + * beta = -expf(k * linear_threshold) / k + * gamma = -k * x + */ + gamma = drc_mult_lshift(x, -p->K, LSHIFT_QX31_QY20_QZ27); + knee_exp_gamma = sofm_exp_fixed(gamma); + knee_curve_k = drc_mult_lshift(p->knee_beta, knee_exp_gamma, LSHIFT_QX24_QY20_QZ24); + knee_curve_k = AE_ADD32(knee_curve_k, p->knee_alpha); + return knee_curve_k; +} + +/* Full compression curve with constant ratio after knee. Returns the ratio of + * output and input signal. + */ +static int32_t volume_gain(const struct sof_drc_params *p, int32_t x) +{ + const ae_f32 knee_threshold = AE_SLAI32S(p->knee_threshold, 7); /* Q8.24 -> Q1.31 */ + const ae_f32 linear_threshold = AE_SLAI32S(p->linear_threshold, 1); /* Q2.30 -> Q1.31 */ + ae_f32 exp_knee; /* Q12.20 */ + ae_f32 y; /* Q2.30 */ + ae_f32 tmp; + ae_f32 tmp2; + + if (x < (int32_t)knee_threshold) { + if (x < (int32_t)linear_threshold) + return ONE_Q30; + /* y = knee_curveK(x) / x */ + y = drc_mult_lshift(knee_curveK(p, x), drc_inv_fixed(x, 31, 20), + LSHIFT_QX24_QY20_QZ30); + } else { + /* Constant ratio after knee. + * log(y/y0) = s * log(x/x0) + * => y = y0 * (x/x0)^s + * => y = [y0 * (1/x0)^s] * x^s + * => y = ratio_base * x^s + * => y/x = ratio_base * x^(s - 1) + * => y/x = ratio_base * e^(log(x) * (s - 1)) + */ + tmp = AE_SRAI32R(x, 5); /* Q1.31 -> Q5.26 */ + tmp = drc_log_fixed(tmp); /* Q6.26 */ + tmp2 = AE_SUB32(p->slope, ONE_Q30); /* Q2.30 */ + exp_knee = sofm_exp_fixed(drc_mult_lshift(tmp, tmp2, LSHIFT_QX26_QY30_QZ27)); + y = drc_mult_lshift(p->ratio_base, exp_knee, LSHIFT_QX30_QY20_QZ30); + } + + return y; +} + +/* Update detector_average from the last input division. */ +void drc_update_detector_average(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + ae_f32 detector_average = state->detector_average; /* Q2.30 */ + ae_int32 abs_input_array[DRC_DIVISION_FRAMES]; /* Q1.31 */ + ae_int32 *abs_input_array_p; + int div_start, i, ch; + ae_int16 *sample16_p; /* for s16 format case */ + ae_int32 *sample32_p; /* for s24 and s32 format cases */ + ae_int32x2 sample32; + ae_int32x2 temp; + ae_int16x4 sample16; + ae_f32 gain; + ae_f32 gain_diff; + ae_f32 db_per_frame; + ae_f32 sat_release_rate; + ae_f32 tmp; + int is_release; + + /* Calculate the start index of the last input division */ + if (state->pre_delay_write_index == 0) + div_start = CONFIG_DRC_MAX_PRE_DELAY_FRAMES - DRC_DIVISION_FRAMES; + else + div_start = state->pre_delay_write_index - DRC_DIVISION_FRAMES; + + /* The max abs value across all channels for this frame */ + memset(abs_input_array, 0, DRC_DIVISION_FRAMES * sizeof(int32_t)); + if (nbyte == 2) { /* 2 bytes per sample */ + for (ch = 0; ch < nch; ch++) { + abs_input_array_p = abs_input_array; + sample16_p = (ae_int16 *)state->pre_delay_buffers[ch] + div_start; + for (i = 0; i < DRC_DIVISION_FRAMES / 4; i++) { + AE_L16X4_XP(sample16, sample16_p, sizeof(ae_int16x4)); + + sample32 = AE_CVT32X2F16_32(sample16); + temp = AE_L32X2_I(abs_input_array_p, 0); + sample32 = AE_MAXABS32S(sample32, temp); + AE_S32X2_IP(sample32, abs_input_array_p, sizeof(ae_int32x2)); + + sample32 = AE_CVT32X2F16_10(sample16); + temp = AE_L32X2_I(abs_input_array_p, 0); + sample32 = AE_MAXABS32S(sample32, temp); + AE_S32X2_IP(sample32, abs_input_array_p, sizeof(ae_int32x2)); + } + } + } else { /* 4 bytes per sample */ + for (ch = 0; ch < nch; ch++) { + abs_input_array_p = abs_input_array; + sample32_p = (ae_int32 *)state->pre_delay_buffers[ch] + div_start; + for (i = 0; i < DRC_DIVISION_FRAMES / 2; i++) { + AE_L32X2_IP(sample32, sample32_p, sizeof(ae_int32x2)); + temp = AE_L32X2_I(abs_input_array_p, 0); + sample32 = AE_MAXABS32S(sample32, temp); + AE_S32X2_IP(sample32, abs_input_array_p, sizeof(ae_int32x2)); + } + } + } + + for (i = 0; i < DRC_DIVISION_FRAMES; i++) { + /* Compute compression amount from un-delayed signal */ + + /* Calculate shaped power on undelayed input. Put through + * shaping curve. This is linear up to the threshold, then + * enters a "knee" portion followed by the "ratio" portion. The + * transition from the threshold to the knee is smooth (1st + * derivative matched). The transition from the knee to the + * ratio portion is smooth (1st derivative matched). + */ + gain = volume_gain(p, abs_input_array[i]); /* Q2.30 */ + gain_diff = AE_SUB32(gain, detector_average); /* Q2.30 */ + is_release = ((int32_t)gain_diff > 0); + if (is_release) { + if ((int32_t)gain > NEG_TWO_DB_Q30) { + tmp = drc_mult_lshift(gain_diff, p->sat_release_rate_at_neg_two_db, + LSHIFT_QX30_QY30_QZ30); + } else { + gain = AE_SRAI32R(gain, 4); /* Q2.30 -> Q6.26 */ + db_per_frame = drc_mult_lshift(drc_lin2db_fixed(gain), + p->sat_release_frames_inv_neg, + LSHIFT_QX21_QY30_QZ24); + sat_release_rate = AE_SUB32(sofm_db2lin_fixed(db_per_frame), + ONE_Q20); + tmp = drc_mult_lshift(gain_diff, sat_release_rate, + LSHIFT_QX30_QY20_QZ30); + } + detector_average = AE_ADD32(detector_average, tmp); + } else { + detector_average = gain; + } + + detector_average = AE_MIN32(detector_average, ONE_Q30); + } + + state->detector_average = detector_average; +} + +/* Updates the envelope_rate used for the next division */ +void drc_update_envelope(struct drc_state *state, const struct sof_drc_params *p) +{ + /* Deal with envelopes */ + + /* envelope_rate is the rate we slew from current compressor level to + * the desired level. The exact rate depends on if we're attacking or + * releasing and by how much. + */ + ae_f32 envelope_rate; + + /* compression_diff_db is the difference between current compression + * level and the desired level. + */ + ae_f32 compression_diff_db; + ae_f32 x, x2, x3, x4; + ae_f64 release_frames_f64; + ae_f32 release_frames; + ae_f32 db_per_frame; + ae_f32 tmp; + ae_f32 tmp2; + int32_t scaled_desired_gain; + int32_t eff_atten_diff_db; + int32_t is_releasing; + int32_t is_bad_db; + + /* Calculate desired gain */ + + /* Pre-warp so we get desired_gain after sin() warp below. */ + scaled_desired_gain = drc_asin_fixed(state->detector_average); /* Q2.30 */ + + is_releasing = scaled_desired_gain > state->compressor_gain; + is_bad_db = (state->compressor_gain == 0 || scaled_desired_gain == 0); + + tmp = AE_SRAI32R(state->compressor_gain, 4); /* Q2.30 -> Q6.26 */ + tmp2 = AE_SRAI32R(scaled_desired_gain, 4); /* Q2.30 -> Q6.26 */ + compression_diff_db = AE_SUB32(drc_lin2db_fixed(tmp), drc_lin2db_fixed(tmp2)); /* Q11.21 */ + + if (is_releasing) { + /* Release mode - compression_diff_db should be negative dB */ + state->max_attack_compression_diff_db = INT32_MIN; + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = -ONE_Q21; + + /* Adaptive release - higher compression (lower + * compression_diff_db) releases faster. Contain within range: + * -12 -> 0 then scale to go from 0 -> 3 + */ + x = compression_diff_db; /* Q11.21 */ + x = AE_MAX32(-TWELVE_Q21, x); + x = AE_MIN32(0, x); + /* x = 0.25f * (x + 12) */ + x = AE_SRAI32R(AE_ADD32(x, TWELVE_Q21), 2); /* Q11.21 -> Q13.19 */ + + /* Compute adaptive release curve using 4th order polynomial. + * Normal values for the polynomial coefficients would create a + * monotonically increasing function. + */ + x2 = drc_mult_lshift(x, x, LSHIFT_QX21_QY21_QZ21); /* Q11.21 */ + x3 = drc_mult_lshift(x2, x, LSHIFT_QX21_QY21_QZ21); /* Q11.21 */ + x4 = drc_mult_lshift(x2, x2, LSHIFT_QX21_QY21_QZ21); /* Q11.21 */ + + release_frames_f64 = AE_CVT48A32(p->kA); /* Q20.12 -> Q36.28 */ + release_frames_f64 = AE_SRAI64(release_frames_f64, 10); /* Q36.28 -> Q46.18 */ + AE_MULAF32R_LL(release_frames_f64, p->kB, x); /* Q20.12 * Q11.21 = Q46.18 */ + AE_MULAF32R_LL(release_frames_f64, p->kC, x2); + AE_MULAF32R_LL(release_frames_f64, p->kD, x3); + AE_MULAF32R_LL(release_frames_f64, p->kE, x4); + release_frames_f64 = AE_SLAI64S(release_frames_f64, 10); /* Q46.18 -> Q36.28 */ + release_frames = AE_ROUND32F48SSYM(release_frames_f64); /* Q36.28 -> Q20.12 */ + + /* db_per_frame = kSpacingDb / release_frames */ + db_per_frame = drc_inv_fixed(release_frames, 12, 30); /* Q2.30 */ + tmp = p->kSpacingDb << 16; /* Q16.16 */ + /* Q8.24 */ + db_per_frame = drc_mult_lshift(db_per_frame, tmp, LSHIFT_QX30_QY16_QZ24); + envelope_rate = sofm_db2lin_fixed(db_per_frame); /* Q12.20 */ + } else { + /* Attack mode - compression_diff_db should be positive dB */ + + /* Fix gremlins. */ + if (is_bad_db) + compression_diff_db = ONE_Q21; + + /* As long as we're still in attack mode, use a rate based off + * the largest compression_diff_db we've encountered so far. + */ + tmp = AE_SLAI32S(compression_diff_db, 3); /* Q11.21 -> Q8.24 */ + state->max_attack_compression_diff_db = + AE_MAX32(state->max_attack_compression_diff_db, tmp); + + eff_atten_diff_db = + MAX(HALF_Q24, state->max_attack_compression_diff_db); /* Q8.24 */ + + /* x = 0.25f / eff_atten_diff_db; + * => x = 1.0f / (eff_atten_diff_db << 2); + */ + x = drc_inv_fixed(eff_atten_diff_db, 22 /* Q8.24 << 2 */, 26); /* Q6.26 */ + envelope_rate = AE_SUB32(ONE_Q20, + drc_pow_fixed(x, p->one_over_attack_frames)); /* Q12.20 */ + } + + tmp = AE_SLAI32S(envelope_rate, 10); /* Q12.20 -> Q2.30 */ + state->envelope_rate = tmp; + state->scaled_desired_gain = scaled_desired_gain; +} + +/* Calculate compress_gain from the envelope and apply total_gain to compress + * the next output division. + */ +void drc_compress_output(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + const int count = DRC_DIVISION_FRAMES >> 2; + ae_f32 x[4]; /* Q2.30 */ + ae_f32 c, base, r, r2, r4; /* Q2.30 */ + ae_f32 post_warp_compressor_gain; + ae_f32 total_gain; + int i, j, ch; + int inc = state->pre_delay_read_index; + int16_t *sample16_p; /* for s16 format case */ + int32_t *sample32_p; /* for s24 and s32 format cases */ + int32_t sample; + int is_2byte = (nbyte == 2); /* otherwise is 4-bytes */ + ae_f32 tmp; + ae_f64 tmp64; + ae_f32 master_linear_gain = p->master_linear_gain; + + /* Exponential approach to desired gain. */ + if (state->envelope_rate < ONE_Q30) { + /* Attack - reduce gain to desired. */ + c = AE_SUB32(state->compressor_gain, state->scaled_desired_gain); + base = state->scaled_desired_gain; + r = AE_SUB32(ONE_Q30, state->envelope_rate); + x[0] = drc_mult_lshift(c, r, LSHIFT_QX30_QY30_QZ30); + for (j = 1; j < 4; j++) + x[j] = drc_mult_lshift(x[j - 1], r, LSHIFT_QX30_QY30_QZ30); + r2 = drc_mult_lshift(r, r, LSHIFT_QX30_QY30_QZ30); + r4 = drc_mult_lshift(r2, r2, LSHIFT_QX30_QY30_QZ30); + + i = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + tmp = AE_ADD32(x[j], base); + post_warp_compressor_gain = drc_sin_fixed(tmp); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64); /* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + inc; + sample = (int32_t)*sample16_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX15_QY24_QZ15); + *sample16_p = sat_int16(sample); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + tmp = AE_ADD32(x[j], base); + post_warp_compressor_gain = drc_sin_fixed(tmp); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64);/* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + inc; + sample = *sample32_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX31_QY24_QZ31); + *sample32_p = sample; + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) + x[j] = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + } + } + + tmp = AE_ADD32(x[3], base); + state->compressor_gain = tmp; + } else { + /* Release - exponentially increase gain to 1.0 */ + c = state->compressor_gain; + r = state->envelope_rate; + x[0] = drc_mult_lshift(c, r, LSHIFT_QX30_QY30_QZ30); + for (j = 1; j < 4; j++) + x[j] = drc_mult_lshift(x[j - 1], r, LSHIFT_QX30_QY30_QZ30); + r2 = drc_mult_lshift(r, r, LSHIFT_QX30_QY30_QZ30); + r4 = drc_mult_lshift(r2, r2, LSHIFT_QX30_QY30_QZ30); + + i = 0; + if (is_2byte) { /* 2 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64);/* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample16_p = + (int16_t *)state->pre_delay_buffers[ch] + + inc; + sample = (int32_t)*sample16_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX15_QY24_QZ15); + *sample16_p = sat_int16(sample); + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) { + tmp = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + x[j] = AE_MIN32(ONE_Q30, tmp); + } + } + } else { /* 4 bytes per sample */ + while (1) { + for (j = 0; j < 4; j++) { + /* Warp pre-compression gain to smooth out sharp + * exponential transition points. + */ + post_warp_compressor_gain = drc_sin_fixed(x[j]); /* Q1.31 */ + + /* Calculate total gain using master gain. */ + tmp64 = AE_MULF32R_LL(master_linear_gain, + post_warp_compressor_gain); + total_gain = AE_ROUND32F48SSYM(tmp64);/* Q8.24 */ + + /* Apply final gain. */ + for (ch = 0; ch < nch; ch++) { + sample32_p = + (int32_t *)state->pre_delay_buffers[ch] + + inc; + sample = *sample32_p; + sample = drc_mult_lshift(sample, total_gain, + LSHIFT_QX31_QY24_QZ31); + *sample32_p = sample; + } + inc++; + } + + if (++i == count) + break; + + for (j = 0; j < 4; j++) { + tmp = drc_mult_lshift(x[j], r4, LSHIFT_QX30_QY30_QZ30); + x[j] = AE_MIN32(ONE_Q30, tmp); + } + } + } + + state->compressor_gain = x[3]; + } +} + +/* After one complete division of samples have been received (and one division of + * samples have been output), we calculate shaped power average + * (detector_average) from the input division, update envelope parameters from + * detector_average, then prepare the next output division by applying the + * envelope to compress the samples. + */ +static void drc_process_one_division(struct drc_state *state, + const struct sof_drc_params *p, + int nbyte, + int nch) +{ + drc_update_detector_average(state, p, nbyte, nch); + drc_update_envelope(state, p); + drc_compress_output(state, p, nbyte, nch); +} + +void drc_default_pass(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, uint32_t frames) +{ + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); +} + +static inline void drc_pre_delay_index_inc(int *idx, int increment) +{ + *idx = (*idx + increment) & DRC_MAX_PRE_DELAY_FRAMES_MASK; +} + +#if CONFIG_FORMAT_S16LE +static void drc_delay_input_sample_s16(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int16_t **x, int16_t **y, int samples) +{ + ae_int16 *x1; + ae_int16 *y1; + ae_int16 *pd; + ae_int16 *pd_r; + ae_int16 *pd_w; + int nbuf, npcm, nfrm; + int ch; + int i; + ae_int16 *x0 = (ae_int16 *)*x; + ae_int16 *y0 = (ae_int16 *)*y; + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + const int sample_inc = nch * sizeof(int16_t); + const int delay_inc = sizeof(int16_t); + ae_int16x4 sample; + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s16(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s16(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int16 *)state->pre_delay_buffers[ch]; + set_circular_buf0(pd, pd + CONFIG_DRC_MAX_PRE_DELAY_FRAMES); + x1 = x0 + ch; + y1 = y0 + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + for (i = 0; i < nfrm; i++) { + AE_L16_XP(sample, x1, sample_inc); + AE_S16_0_XC(sample, pd_w, delay_inc); + /*pop sample from delay buffer and store in output buffer*/ + AE_L16_XC(sample, pd_r, delay_inc); + AE_S16_0_XP(sample, y1, sample_inc); + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = (int16_t *)x0; + *y = (int16_t *)y0; +} + +static void drc_s16_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment; + ae_int16 *pd; + ae_int16 *pd_r; + ae_int16 *pd_w; + ae_int16 *x1; + ae_int16 *y1; + int i, ch; + ae_int16x4 sample; + const int sample_inc = nch * sizeof(ae_int16); + const int delay_inc = sizeof(ae_int16); + + if (!cd->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. + */ + drc_delay_input_sample_s16(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int16_t), nch); + state->processed = 1; + } + + set_circular_buf0(source->addr, source->end_addr); + set_circular_buf1(sink->addr, sink->end_addr); + + while (frames) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment = MIN(frames, fragment); + + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int16 *)state->pre_delay_buffers[ch]; + x1 = (ae_int16 *)x + ch; + y1 = (ae_int16 *)y + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + /* don't need to check the boundary of pre-delay because the + * state->pre_delay_write_index + frames will always be aligned with + * 32(DRC_DIVISION_FRAMES), and the pre-delay buffer size (a multiple + * of CONFIG_DRC_MAX_PRE_DELAY_FRAMES) will always be the multiple of + * DRC_DIVISION_FRAMES + */ + for (i = 0; i < fragment; i++) { + AE_L16_XC(sample, x1, sample_inc); + AE_S16_0_XP(sample, pd_w, delay_inc); + /*pop sample from delay buffer and store in output buffer*/ + AE_L16_XP(sample, pd_r, delay_inc); + AE_S16_0_XC1(sample, y1, sample_inc); + } + } + drc_pre_delay_index_inc(&state->pre_delay_write_index, fragment); + drc_pre_delay_index_inc(&state->pre_delay_read_index, fragment); + x = audio_stream_wrap(source, x + fragment * nch); + y = audio_stream_wrap(sink, y + fragment * nch); + frames -= fragment; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int16_t), nch); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +static void drc_delay_input_sample_s32(struct drc_state *state, + const struct audio_stream *source, + struct audio_stream *sink, + int32_t **x, int32_t **y, int samples) +{ + ae_int32 *x1; + ae_int32 *y1; + ae_int32 *pd_r; + ae_int32 *pd_w; + ae_int32 *pd; + int nbuf, npcm, nfrm; + int ch; + int i; + ae_int32 *x0 = (ae_int32 *)*x; + ae_int32 *y0 = (ae_int32 *)*y; + ae_int32x2 sample; + + int remaining_samples = samples; + int nch = audio_stream_get_channels(source); + const int sample_inc = nch * sizeof(int32_t); + const int delay_inc = sizeof(int32_t); + + while (remaining_samples) { + nbuf = audio_stream_samples_without_wrap_s32(source, x0); + npcm = MIN(remaining_samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s32(sink, y0); + npcm = MIN(npcm, nbuf); + nfrm = npcm / nch; + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int32 *)state->pre_delay_buffers[ch]; + set_circular_buf0(pd, pd + CONFIG_DRC_MAX_PRE_DELAY_FRAMES); + x1 = x0 + ch; + y1 = y0 + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + for (i = 0; i < nfrm; i++) { + /*store the input sample to delay buffer*/ + AE_L32_XP(sample, x1, sample_inc); + AE_S32_L_XC(sample, pd_w, delay_inc); + + /*pop sample from delay buffer and store in output buffer*/ + AE_L32_XC(sample, pd_r, delay_inc); + AE_S32_L_XP(sample, y1, sample_inc); + } + } + remaining_samples -= npcm; + x0 = audio_stream_wrap(source, x0 + npcm); + y0 = audio_stream_wrap(sink, y0 + npcm); + drc_pre_delay_index_inc(&state->pre_delay_write_index, nfrm); + drc_pre_delay_index_inc(&state->pre_delay_read_index, nfrm); + } + + *x = (int32_t *)x0; + *y = (int32_t *)y0; +} +#endif + +#if CONFIG_FORMAT_S24LE + +static void drc_s24_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + int samples = frames * nch; + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment; + ae_int32 *pd; + ae_int32 *pd_r; + ae_int32 *pd_w; + ae_int32 *x1; + ae_int32 *y1; + int i, ch; + ae_int32x2 sample; + const int sample_inc = nch * sizeof(int32_t); + const int delay_inc = sizeof(int32_t); + + if (!cd->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. Note: use 32 bit delay function. + */ + drc_delay_input_sample_s32(state, source, sink, &x, &y, samples); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int32_t), nch); + state->processed = 1; + } + + set_circular_buf0(source->addr, source->end_addr); + set_circular_buf1(sink->addr, sink->end_addr); + + while (frames) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment = MIN(frames, fragment); + + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int32 *)state->pre_delay_buffers[ch]; + x1 = (ae_int32 *)x + ch; + y1 = (ae_int32 *)y + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + /* don't need to check the boundary of pre-delay because the + * state->pre_delay_write_index + frames will always be aligned with + * 32(DRC_DIVISION_FRAMES), and the pre-delay buffer size (a multiple + * of CONFIG_DRC_MAX_PRE_DELAY_FRAMES) will always be the multiple of + * DRC_DIVISION_FRAMES + */ + for (i = 0; i < fragment; i++) { + /*store the input sample to delay buffer*/ + AE_L32_XC(sample, x1, sample_inc); + sample = AE_SLAI32(sample, 8); /*Q9.23 -> Q1.31*/ + AE_S32_L_XP(sample, pd_w, delay_inc); + + /*pop sample from delay buffer and store in output buffer*/ + AE_L32_XP(sample, pd_r, delay_inc); + sample = AE_SRAI32R(sample, 8); + sample = AE_SLAA32S(sample, 8); + sample = AE_SRAI32(sample, 8); + + AE_S32_L_XC1(sample, y1, sample_inc); + } + } + drc_pre_delay_index_inc(&state->pre_delay_write_index, fragment); + drc_pre_delay_index_inc(&state->pre_delay_read_index, fragment); + x = audio_stream_wrap(source, x + fragment * nch); + y = audio_stream_wrap(sink, y + fragment * nch); + frames -= fragment; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int32_t), nch); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void drc_s32_default(struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nch = audio_stream_get_channels(source); + struct drc_comp_data *cd = module_get_private_data(mod); + struct drc_state *state = &cd->state; + const struct sof_drc_params *p = &cd->config->params; /* Read-only */ + int fragment; + ae_int32 *pd; + ae_int32 *pd_r; + ae_int32 *pd_w; + ae_int32 *x1; + ae_int32 *y1; + int i, ch; + ae_int32x2 sample; + const int sample_inc = nch * sizeof(int32_t); + const int delay_inc = sizeof(int32_t); + + if (!cd->enabled) { + /* Delay the input sample only and don't do other processing. This is used when the + * DRC is disabled. We want to do this to match the processing delay of other bands + * in multi-band DRC kernel case. + */ + drc_delay_input_sample_s32(state, source, sink, &x, &y, frames * nch); + return; + } + + if (!state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, sizeof(int32_t), nch); + state->processed = 1; + } + + set_circular_buf0(source->addr, source->end_addr); + set_circular_buf1(sink->addr, sink->end_addr); + + while (frames) { + fragment = DRC_DIVISION_FRAMES - + (state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK); + fragment = MIN(frames, fragment); + + for (ch = 0; ch < nch; ++ch) { + pd = (ae_int32 *)state->pre_delay_buffers[ch]; + x1 = (ae_int32 *)x + ch; + y1 = (ae_int32 *)y + ch; + pd_r = pd + state->pre_delay_read_index; + pd_w = pd + state->pre_delay_write_index; + + /* don't need to check the boundary of pre-delay because the + * state->pre_delay_write_index + frames will always be aligned with + * 32(DRC_DIVISION_FRAMES), and the pre-delay buffer size (a multiple + * of CONFIG_DRC_MAX_PRE_DELAY_FRAMES) will always be the multiple of + * DRC_DIVISION_FRAMES + */ + for (i = 0; i < fragment; i++) { + /*store the input sample to delay buffer*/ + AE_L32_XC(sample, x1, sample_inc); + AE_S32_L_XP(sample, pd_w, delay_inc); + + /*pop sample from delay buffer and store in output buffer*/ + AE_L32_XP(sample, pd_r, delay_inc); + AE_S32_L_XC1(sample, y1, sample_inc); + } + } + drc_pre_delay_index_inc(&state->pre_delay_write_index, fragment); + drc_pre_delay_index_inc(&state->pre_delay_read_index, fragment); + x = audio_stream_wrap(source, x + fragment * nch); + y = audio_stream_wrap(sink, y + fragment * nch); + frames -= fragment; + + /* Process the input division (32 frames). */ + if ((state->pre_delay_write_index & DRC_DIVISION_FRAMES_MASK) == 0) + drc_process_one_division(state, p, sizeof(int32_t), nch); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct drc_proc_fnmap drc_proc_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, drc_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, drc_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, drc_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t drc_proc_fncount = ARRAY_SIZE(drc_proc_fnmap); + +#endif /* DRC_HIFI_4 */ diff --git a/src/audio/drc/drc_log.c b/src/audio/drc/drc_log.c new file mode 100644 index 000000000000..d2e0f1efe7ea --- /dev/null +++ b/src/audio/drc/drc_log.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. + +#include <rtos/symbol.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> +#include <user/trace.h> + +SOF_DEFINE_REG_UUID(drc); +LOG_MODULE_REGISTER(drc, CONFIG_SOF_LOG_LEVEL); +DECLARE_TR_CTX(drc_tr, SOF_UUID(drc_uuid), LOG_LEVEL_INFO); +EXPORT_SYMBOL(log_const_drc); +#ifdef CONFIG_LOG_RUNTIME_FILTERING +EXPORT_SYMBOL(log_dynamic_drc); +#endif diff --git a/src/audio/drc/drc_math.h b/src/audio/drc/drc_math.h new file mode 100644 index 000000000000..09e210262e7e --- /dev/null +++ b/src/audio/drc/drc_math.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ +#ifndef __SOF_AUDIO_DRC_DRC_MATH_H__ +#define __SOF_AUDIO_DRC_DRC_MATH_H__ + +#include <stddef.h> +#include <stdint.h> +#include <sof/audio/format.h> +#include <sof/math/numbers.h> +#include <sof/math/lut_trig.h> +#include <sof/math/trig.h> +#include <sof/common.h> + +/* Unmark this define to use cordic arc sine implementation. */ +/* #define DRC_USE_CORDIC_ASIN */ + +#if SOF_USE_MIN_HIFI(3, DRC) + +#include <xtensa/tie/xt_hifi3.h> + +#define PI_OVER_TWO_Q30 1686629713 /* Q_CONVERT_FLOAT(1.57079632679489661923, 30); pi/2 */ +#define TWO_OVER_PI_Q30 683565248 /* Q_CONVERT_FLOAT(0.63661977236758134, 30); 2/pi */ + +/* + * A substitutive function of Q_MULTSR_32X32(a, b, qa, qb, qy) in HIFI manners. + * + * In AE_MULF32R, it takes the multiplication of 1.31 and 1.31 to 17.47, which means it does + * right-shift 15 bits. Let's consider a is .qa, b is .qb, then tmp will be .(qa+qb-15) + * In AE_ROUND32F48SSYM, it rounds 17.47 to 1.31, equally right-shifts 16 bits. Let's consider the + * output is .qy, then tmp here needs to be .(qy+16) + * If we set the left-shift bit from the former tmp to the latter tmp as "lshift", then: + * (qa+qb-15) + lshift = (qy+16) + * lshift = qy-qa-qb+31 + */ +static inline int32_t drc_mult_lshift(int32_t a, int32_t b, int32_t lshift) +{ + ae_f64 tmp; + ae_f32 y; + + tmp = AE_MULF32R_LL(a, b); + tmp = AE_SLAA64S(tmp, lshift); + y = AE_ROUND32F48SSYM(tmp); + return y; +} + +static inline int32_t drc_get_lshift(int32_t qa, int32_t qb, int32_t qy) +{ + return qy - qa - qb + 31; +} + +/* + * Input is Q2.30: (-2.0, 2.0) + * Output range: (-1.0, 1.0); regulated to Q1.31: (-1.0, 1.0) + */ +static inline int32_t drc_sin_fixed(int32_t x) +{ + const int32_t lshift = drc_get_lshift(30, 30, 28); + int32_t denorm_x = drc_mult_lshift(x, PI_OVER_TWO_Q30, lshift); + + return sofm_lut_sin_fixed_16b(denorm_x) << 16; +} + +#ifdef DRC_USE_CORDIC_ASIN +/* + * Input is Q2.30; valid range: [-1.0, 1.0] + * Output range: [-1.0, 1.0]; regulated to Q2.30: (-2.0, 2.0) + */ +static inline int32_t drc_asin_fixed(int32_t x) +{ + const int32_t lshift = drc_get_lshift(30, 30, 30); + int32_t asin_val = asin_fixed_16b(x); /* Q2.14, [-pi/2, pi/2] */ + + return drc_mult_lshift(asin_val << 16, TWO_OVER_PI_Q30, lshift); +} +#endif /* DRC_USE_CORDIC_ASIN */ + +#else + +/* + * Input is Q2.30: (-2.0, 2.0) + * Output range: (-1.0, 1.0); regulated to Q1.31: (-1.0, 1.0) + */ +static inline int32_t drc_sin_fixed(int32_t x) +{ + const int32_t PI_OVER_TWO = Q_CONVERT_FLOAT(1.57079632679489661923, 30); + + return sofm_lut_sin_fixed_16b(Q_MULTSR_32X32((int64_t)x, PI_OVER_TWO, 30, 30, 28)) << 16; +} + +#ifdef DRC_USE_CORDIC_ASIN +/* + * Input is Q2.30; valid range: [-1.0, 1.0] + * Output range: [-1.0, 1.0]; regulated to Q2.30: (-2.0, 2.0) + */ +static inline int32_t drc_asin_fixed(int32_t x) +{ + const int32_t TWO_OVER_PI = Q_CONVERT_FLOAT(0.63661977236758134, 30); /* 2/pi */ + int32_t asin_val = asin_fixed_16b(x); /* Q2.14, [-pi/2, pi/2] */ + + return Q_MULTSR_32X32((int64_t)asin_val, TWO_OVER_PI, 14, 30, 30); +} +#endif /* DRC_USE_CORDIC_ASIN */ + +#endif /* DRC_HIFI_3/4 */ + +int32_t drc_lin2db_fixed(int32_t linear); /* Input:Q6.26 Output:Q11.21 */ +int32_t drc_log_fixed(int32_t x); /* Input:Q6.26 Output:Q6.26 */ +int32_t drc_pow_fixed(int32_t x, int32_t y); /* Input:Q6.26, Q2.30 Output:Q12.20 */ +int32_t drc_inv_fixed(int32_t x, int32_t precision_x, int32_t precision_y); + +#ifndef DRC_USE_CORDIC_ASIN +int32_t drc_asin_fixed(int32_t x); /* Input:Q2.30 Output:Q2.30 */ +#endif /* !DRC_USE_CORDIC_ASIN */ + +#endif // __SOF_AUDIO_DRC_DRC_MATH_H__ diff --git a/src/audio/drc/drc_math_generic.c b/src/audio/drc/drc_math_generic.c new file mode 100644 index 000000000000..f4e1f115fcad --- /dev/null +++ b/src/audio/drc/drc_math_generic.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/format.h> +#include <sof/math/decibels.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/numbers.h> +#include <sof/math/trig.h> +#include <sof/common.h> + +#include "drc_math.h" + +#define q_mult(a, b, qa, qb, qy) ((int32_t)Q_MULTSR_32X32((int64_t)(a), b, qa, qb, qy)) +#define q_multq(a, b, q) ((int32_t)Q_MULTSR_32X32((int64_t)(a), b, q, q, q)) + +#if SOF_USE_HIFI(NONE, DRC) + +/* + * Input depends on precision_x + * Output range [0.5, 1); regulated to Q2.30 + */ +static inline int32_t rexp_fixed(int32_t x, int32_t precision_x, int32_t *e) +{ + int32_t bit = 31 - norm_int32(x); + + *e = bit - precision_x; + + if (bit > 30) + return Q_SHIFT_RND(x, bit, 30); + if (bit < 30) + return Q_SHIFT_LEFT(x, bit, 30); + return x; +} + +/* + * Input is Q6.26: max 32.0 + * Output range ~ (-inf, 1.505); regulated to Q6.26: (-32.0, 32.0) + */ +static inline int32_t log10_fixed(int32_t x) +{ +#define qc 26 + /* Coefficients obtained from: + * fpminimax(log10(x), 5, [|SG...|], [1/2;sqrt(2)/2], absolute); + * max err ~= 6.088e-8 + */ + const int32_t ONE_OVER_SQRT2 = Q_CONVERT_FLOAT(0.70710678118654752f, 30); /* 1/sqrt(2) */ + const int32_t A5 = Q_CONVERT_FLOAT(1.131880283355712890625f, qc); + const int32_t A4 = Q_CONVERT_FLOAT(-4.258677959442138671875f, qc); + const int32_t A3 = Q_CONVERT_FLOAT(6.81631565093994140625f, qc); + const int32_t A2 = Q_CONVERT_FLOAT(-6.1185703277587890625f, qc); + const int32_t A1 = Q_CONVERT_FLOAT(3.6505267620086669921875f, qc); + const int32_t A0 = Q_CONVERT_FLOAT(-1.217894077301025390625f, qc); + const int32_t LOG10_2 = Q_CONVERT_FLOAT(0.301029995663981195214f, qc); + int32_t e; + int32_t exp; /* Q31.1 */ + int32_t x2, x4; /* Q2.30 */ + int32_t A5Xx, A3Xx; + + x = rexp_fixed(x, 26, &e); /* Q2.30 */ + exp = (int32_t)e << 1; /* Q_CONVERT_FLOAT(e, 1) */ + + if (x > ONE_OVER_SQRT2) { + x = q_mult(x, ONE_OVER_SQRT2, 30, 30, 30); + exp += 1; /* Q_CONVERT_FLOAT(0.5, 1) */ + } + + x2 = q_mult(x, x, 30, 30, 30); + x4 = q_mult(x2, x2, 30, 30, 30); + A5Xx = q_mult(A5, x, qc, 30, qc); + A3Xx = q_mult(A3, x, qc, 30, qc); + return q_mult((A5Xx + A4), x4, qc, 30, qc) + q_mult((A3Xx + A2), x2, qc, 30, qc) + + q_mult(A1, x, qc, 30, qc) + A0 + q_mult(exp, LOG10_2, 1, qc, qc); +#undef qc +} + +/* + * Input is Q6.26: max 32.0 + * Output range ~ (-inf, 30.1030); regulated to Q11.21: (-1024.0, 1024.0) + */ +int32_t drc_lin2db_fixed(int32_t linear) +{ + int32_t log10_linear; + + /* For negative or zero, just return a very small dB value. */ + if (linear <= 0) + return Q_CONVERT_FLOAT(-1000.0f, 21); + + log10_linear = log10_fixed(linear); /* Q6.26 */ + return q_mult(20, log10_linear, 0, 26, 21); +} + +/* + * Input is Q6.26: max 32.0 + * Output range ~ (-inf, 3.4657); regulated to Q6.26: (-32.0, 32.0) + */ +int32_t drc_log_fixed(int32_t x) +{ + const int32_t LOG10 = Q_CONVERT_FLOAT(2.3025850929940457f, 29); + int32_t log10_x; + + if (x <= 0) + return Q_CONVERT_FLOAT(-30.0f, 26); + + /* log(x) = log(10) * log10(x) */ + log10_x = log10_fixed(x); /* Q6.26 */ + return q_mult(LOG10, log10_x, 29, 26, 26); +} + +#ifndef DRC_USE_CORDIC_ASIN +/* + * Input is Q2.30; valid range: [-1.0, 1.0] + * Output range: [-1.0, 1.0]; regulated to Q2.30: (-2.0, 2.0) + */ +int32_t drc_asin_fixed(int32_t x) +{ +#define qcl 30 +#define qch 26 + /* Coefficients obtained from: + * If x <= 1/sqrt(2), then + * fpminimax(asin(x), [|1,3,5,7|], [|SG...|], [-1e-30;1/sqrt(2)], absolute) + * max err ~= 1.89936e-5 + * Else then + * fpminimax(asin(x), [|1,3,5,7|], [|SG...|], [1/sqrt(2);1], absolute) + * max err ~= 3.085226e-2 + */ + const int32_t TWO_OVER_PI = Q_CONVERT_FLOAT(0.63661977236758134f, qcl); /* 2/pi */ + const int32_t ONE_OVER_SQRT2 = Q_CONVERT_FLOAT(0.70710678118654752f, qcl); /* 1/sqrt(2) */ + const int32_t A7L = Q_CONVERT_FLOAT(0.1181826665997505187988281f, qcl); + const int32_t A5L = Q_CONVERT_FLOAT(4.0224377065896987915039062e-2f, qcl); + const int32_t A3L = Q_CONVERT_FLOAT(0.1721895635128021240234375f, qcl); + const int32_t A1L = Q_CONVERT_FLOAT(0.99977016448974609375f, qcl); + + const int32_t A7H = Q_CONVERT_FLOAT(14.12774658203125f, qch); + const int32_t A5H = Q_CONVERT_FLOAT(-30.1692714691162109375f, qch); + const int32_t A3H = Q_CONVERT_FLOAT(21.4760608673095703125f, qch); + const int32_t A1H = Q_CONVERT_FLOAT(-3.894591808319091796875f, qch); + + int32_t A7, A5, A3, A1, qc; + int32_t x2, x4; + int32_t A3Xx2, A7Xx2, asinx; + + if (ABS(x) <= ONE_OVER_SQRT2) { + A7 = A7L; + A5 = A5L; + A3 = A3L; + A1 = A1L; + qc = qcl; + } else { + A7 = A7H; + A5 = A5H; + A3 = A3H; + A1 = A1H; + qc = qch; + x = Q_SHIFT_RND(x, qcl, qch); /* Q6.26 */ + } + + x2 = q_multq(x, x, qc); + x4 = q_multq(x2, x2, qc); + + A3Xx2 = q_multq(A3, x2, qc); + A7Xx2 = q_multq(A7, x2, qc); + + asinx = q_multq(x, (q_multq(x4, (A7Xx2 + A5), qc) + A3Xx2 + A1), qc); + return q_mult(asinx, TWO_OVER_PI, qc, qcl, 30); +#undef qch +#undef qcl +} +#endif /* !DRC_USE_CORDIC_ASIN */ + +/* + * Input depends on precision_x + * Output depends on precision_y + */ +int32_t drc_inv_fixed(int32_t x, int32_t precision_x, int32_t precision_y) +{ +#define qc 25 + /* Coefficients obtained from: + * fpminimax(1/x, 5, [|SG...|], [sqrt(2)/2;1], absolute); + * max err ~= 1.00388e-6 + */ + const int32_t ONE_OVER_SQRT2 = Q_CONVERT_FLOAT(0.70710678118654752f, 30); /* 1/sqrt(2) */ + const int32_t SQRT2 = Q_CONVERT_FLOAT(1.4142135623730950488f, 30); /* sqrt(2) */ + const int32_t A5 = Q_CONVERT_FLOAT(-2.742647647857666015625f, qc); + const int32_t A4 = Q_CONVERT_FLOAT(14.01327800750732421875f, qc); + const int32_t A3 = Q_CONVERT_FLOAT(-29.74465179443359375f, qc); + const int32_t A2 = Q_CONVERT_FLOAT(33.57208251953125f, qc); + const int32_t A1 = Q_CONVERT_FLOAT(-21.25031280517578125f, qc); + const int32_t A0 = Q_CONVERT_FLOAT(7.152250766754150390625f, qc); + int32_t e; + int32_t precision_inv; + int32_t sqrt2_extracted = 0; + int32_t x2, x4; /* Q2.30 */ + int32_t A5Xx, A3Xx; + int32_t inv; + + x = rexp_fixed(x, precision_x, &e); /* Q2.30 */ + + if (ABS(x) < ONE_OVER_SQRT2) { + x = q_mult(x, SQRT2, 30, 30, 30); + sqrt2_extracted = 1; + } + + x2 = q_mult(x, x, 30, 30, 30); + x4 = q_mult(x2, x2, 30, 30, 30); + A5Xx = q_mult(A5, x, qc, 30, qc); + A3Xx = q_mult(A3, x, qc, 30, qc); + inv = q_mult((A5Xx + A4), x4, qc, 30, qc) + q_mult((A3Xx + A2), x2, qc, 30, qc) + + q_mult(A1, x, qc, 30, qc) + A0; + + if (sqrt2_extracted) + inv = q_mult(inv, SQRT2, qc, 30, qc); + + precision_inv = e + qc; + if (precision_inv > precision_y) + return Q_SHIFT_RND(inv, precision_inv, precision_y); + if (precision_inv < precision_y) + return sat_int32(Q_SHIFT_LEFT((int64_t)inv, precision_inv, precision_y)); + return inv; +#undef qc +} + +#endif /* DRC_HIFI_NONE */ + +/* + * Input x is Q6.26; valid range: (0.0, 32.0); x <= 0 is not supported + * y is Q2.30: (-2.0, 2.0) + * Output is Q12.20: max 2048.0 + */ +int32_t drc_pow_fixed(int32_t x, int32_t y) +{ + /* Negative or zero input x is not supported, just return 0. */ + if (x <= 0) + return 0; + + /* x^y = expf(y * log(x)) */ + return sofm_exp_fixed(q_mult(y, drc_log_fixed(x), 30, 26, 27)); +} + +#undef q_multq +#undef q_mult diff --git a/src/audio/drc/drc_math_hifi3.c b/src/audio/drc/drc_math_hifi3.c new file mode 100644 index 000000000000..700114188ec9 --- /dev/null +++ b/src/audio/drc/drc_math_hifi3.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/math/numbers.h> +#include <sof/common.h> +#include "drc_math.h" + +#if SOF_USE_MIN_HIFI(3, DRC) + +#include <xtensa/tie/xt_hifi3.h> + +#define ONE_OVER_SQRT2_Q30 759250112 /* Q_CONVERT_FLOAT(0.70710678118654752f, 30); 1/sqrt(2) */ +#define LOG10_FUNC_A5_Q26 75959200 /* Q_CONVERT_FLOAT(1.131880283355712890625f, 26) */ +#define LOG10_FUNC_A4_Q26 -285795039 /* Q_CONVERT_FLOAT(-4.258677959442138671875f, 26) */ +#define LOG10_FUNC_A3_Q26 457435200 /* Q_CONVERT_FLOAT(6.81631565093994140625f, 26) */ +#define LOG10_FUNC_A2_Q26 -410610303 /* Q_CONVERT_FLOAT(-6.1185703277587890625f, 26) */ +#define LOG10_FUNC_A1_Q26 244982704 /* Q_CONVERT_FLOAT(3.6505267620086669921875f, 26) */ +#define LOG10_FUNC_A0_Q26 -81731487 /* Q_CONVERT_FLOAT(-1.217894077301025390625f, 26) */ +#define HALF_Q25 16777216 /* Q_CONVERT_FLOAT(0.5, 25) */ +#define LOG10_2_Q26 20201782 /* Q_CONVERT_FLOAT(0.301029995663981195214f, 26) */ +#define NEG_1K_Q21 -2097151999 /* Q_CONVERT_FLOAT(-1000.0f, 21) */ +#define LOG_10_Q29 1236190976 /* Q_CONVERT_FLOAT(2.3025850929940457f, 29) */ +#define NEG_30_Q26 -2013265919 /* Q_CONVERT_FLOAT(-30.0f, 26) */ +#define ASIN_FUNC_A7L_Q30 126897672 /* Q_CONVERT_FLOAT(0.1181826665997505187988281f, 30) */ +#define ASIN_FUNC_A5L_Q30 43190596 /* Q_CONVERT_FLOAT(4.0224377065896987915039062e-2f, 30) */ +#define ASIN_FUNC_A3L_Q30 184887136 /* Q_CONVERT_FLOAT(0.1721895635128021240234375f, 30) */ +#define ASIN_FUNC_A1L_Q30 1073495040 /* Q_CONVERT_FLOAT(0.99977016448974609375f, 30) */ +#define ASIN_FUNC_A7H_Q26 948097024 /* Q_CONVERT_FLOAT(14.12774658203125f, 26) */ +#define ASIN_FUNC_A5H_Q26 -2024625535 /* Q_CONVERT_FLOAT(-30.1692714691162109375f, 26) */ +#define ASIN_FUNC_A3H_Q26 1441234048 /* Q_CONVERT_FLOAT(21.4760608673095703125f, 26) */ +#define ASIN_FUNC_A1H_Q26 -261361631 /* Q_CONVERT_FLOAT(-3.894591808319091796875f, 26) */ +#define SQRT2_Q30 1518500224 /* Q_CONVERT_FLOAT(1.4142135623730950488f, 30); sqrt(2) */ +#define INV_FUNC_A5_Q25 -92027983 /* Q_CONVERT_FLOAT(-2.742647647857666015625f, 25) */ +#define INV_FUNC_A4_Q25 470207584 /* Q_CONVERT_FLOAT(14.01327800750732421875f, 25) */ +#define INV_FUNC_A3_Q25 -998064895 /* Q_CONVERT_FLOAT(-29.74465179443359375f, 25) */ +#define INV_FUNC_A2_Q25 1126492160 /* Q_CONVERT_FLOAT(33.57208251953125f, 25) */ +#define INV_FUNC_A1_Q25 -713042175 /* Q_CONVERT_FLOAT(-21.25031280517578125f, 25) */ +#define INV_FUNC_A0_Q25 239989712 /* Q_CONVERT_FLOAT(7.152250766754150390625f, 25) */ +#define INV_FUNC_ONE_Q30 1073741824 /* Q_CONVERT_FLOAT(1, 30) */ +#define SHIFT_IDX_QX30_QY30_QZ30 1 /* drc_get_lshift(30, 30, 30) */ +#define SHIFT_IDX_QX26_QY30_QZ26 1 /* drc_get_lshift(26, 30, 26) */ +#define SHIFT_IDX_QX25_QY30_QZ25 1 /* drc_get_lshift(25, 30, 25) */ +#define SHIFT_IDX_QX29_QY26_QZ26 2 /* drc_get_lshift(29, 26, 26) */ +#define SHIFT_IDX_QX25_QY26_QZ26 6 /* drc_get_lshift(25, 26, 26) */ +#define DRC_TWENTY_Q26 1342177280 /* Q_CONVERT_FLOAT(20, 26) */ + +#define DRC_PACK_INT32X2_TO_UINT64(a, b) (((uint64_t)((int64_t)(a) & 0xffffffff) << 32) | \ + ((uint64_t)((int64_t)(b) & 0xffffffff))) + +static const uint64_t drc_inv_func_coefficients[] = { + DRC_PACK_INT32X2_TO_UINT64(INV_FUNC_A2_Q25, INV_FUNC_A5_Q25), + DRC_PACK_INT32X2_TO_UINT64(INV_FUNC_A1_Q25, INV_FUNC_A4_Q25), + DRC_PACK_INT32X2_TO_UINT64(INV_FUNC_A0_Q25, INV_FUNC_A3_Q25) +}; + +/* + * Input is Q6.26: max 32.0 + * Output range ~ (-inf, 1.505); regulated to Q6.26: (-32.0, 32.0) + */ +static inline ae_f32 log10_fixed(ae_f32 x) +{ + /* Coefficients obtained from: + * fpminimax(log10(x), 5, [|SG...|], [1/2;sqrt(2)/2], absolute); + * max err ~= 6.088e-8 + */ + int bit = 31 - AE_NSAZ32_L(x); + int32_t e = bit - 26; + ae_f32 exp; /* Q7.25 */ + ae_f32 acc; /* Q6.26 */ + ae_f32 tmp; /* Q6.26 */ + ae_f64 tmp64; + + /*Output range [0.5, 1); regulated to Q2.30 */ + x = AE_SRAA32(x, bit - 30); + exp = e << 25; /* Q_CONVERT_FLOAT(e, 25) */ + + if ((int32_t)x > (int32_t)ONE_OVER_SQRT2_Q30) { + tmp64 = AE_MULF32R_LL(x, ONE_OVER_SQRT2_Q30); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX30_QY30_QZ30); + x = AE_ROUND32F48SSYM(tmp64); + exp = AE_ADD32(exp, HALF_Q25); + } + + tmp64 = AE_MULF32R_LL(LOG10_FUNC_A5_Q26, x); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX26_QY30_QZ26); + acc = AE_ROUND32F48SSYM(tmp64); + acc = AE_ADD32(acc, LOG10_FUNC_A4_Q26); + tmp64 = AE_MULF32R_LL(acc, x); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX26_QY30_QZ26); + acc = AE_ROUND32F48SSYM(tmp64); + acc = AE_ADD32(acc, LOG10_FUNC_A3_Q26); + tmp64 = AE_MULF32R_LL(acc, x); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX26_QY30_QZ26); + acc = AE_ROUND32F48SSYM(tmp64); + acc = AE_ADD32(acc, LOG10_FUNC_A2_Q26); + tmp64 = AE_MULF32R_LL(acc, x); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX26_QY30_QZ26); + acc = AE_ROUND32F48SSYM(tmp64); + acc = AE_ADD32(acc, LOG10_FUNC_A1_Q26); + tmp64 = AE_MULF32R_LL(acc, x); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX26_QY30_QZ26); + acc = AE_ROUND32F48SSYM(tmp64); + acc = AE_ADD32(acc, LOG10_FUNC_A0_Q26); + tmp64 = AE_MULF32R_LL(exp, LOG10_2_Q26); + tmp64 = AE_SLAI64S(tmp64, SHIFT_IDX_QX25_QY26_QZ26); + tmp = AE_ROUND32F48SSYM(tmp64); + acc = AE_ADD32(acc, tmp); + + return acc; +} + +/* + * Input is Q6.26: max 32.0 + * Output range ~ (-inf, 30.1030); regulated to Q11.21: (-1024.0, 1024.0) + */ +int32_t drc_lin2db_fixed(int32_t linear) +{ + ae_f32 log10_linear; + ae_f64 tmp; + ae_f32 y; + + /* For negative or zero, just return a very small dB value. */ + if (linear <= 0) + return NEG_1K_Q21; + + log10_linear = log10_fixed(linear); /* Q6.26 */ + + tmp = AE_MULF32R_LL(DRC_TWENTY_Q26, log10_linear); + /*Don't need to do AE_SLAA64S since drc_get_lshift(26, 26, 21) = 0 */ + y = AE_ROUND32F48SSYM(tmp); + return AE_MOVAD32_L(y); +} + +/* + * Input is Q6.26: max 32.0 + * Output range ~ (-inf, 3.4657); regulated to Q6.26: (-32.0, 32.0) + */ +int32_t drc_log_fixed(int32_t x) +{ + ae_f32 log10_x; + ae_f64 tmp; + ae_f32 y; + + if (x <= 0) + return NEG_30_Q26; + + /* log(x) = log(10) * log10(x) */ + log10_x = log10_fixed(x); /* Q6.26 */ + tmp = AE_MULF32R_LL(LOG_10_Q29, log10_x); + tmp = AE_SLAI64S(tmp, SHIFT_IDX_QX29_QY26_QZ26); + y = AE_ROUND32F48SSYM(tmp); + return AE_MOVAD32_L(y); + } + +#ifndef DRC_USE_CORDIC_ASIN +/* + * Input is Q2.30; valid range: [-1.0, 1.0] + * Output range: [-1.0, 1.0]; regulated to Q2.30: (-2.0, 2.0) + */ +int32_t drc_asin_fixed(int32_t x) +{ + /* Coefficients obtained from: + * If x <= 1/sqrt(2), then + * fpminimax(asin(x), [|1,3,5,7|], [|SG...|], [-1e-30;1/sqrt(2)], absolute) + * max err ~= 1.89936e-5 + * Else then + * fpminimax(asin(x), [|1,3,5,7|], [|SG...|], [1/sqrt(2);1], absolute) + * max err ~= 3.085226e-2 + */ + int32_t lshift; + int32_t x_abs = AE_MOVAD32_L(AE_ABS32S(x)); + ae_f32 in2; /* Q2.30 */ + ae_f32 A7, A5, A3, A1; + int32_t qc; + ae_f32 acc; + ae_f64 tmp; + + tmp = AE_MULF32R_LL(x, x); + tmp = AE_SLAI64S(tmp, SHIFT_IDX_QX30_QY30_QZ30); + in2 = AE_ROUND32F48SSYM(tmp); + + if (x_abs <= ONE_OVER_SQRT2_Q30) { + A7 = ASIN_FUNC_A7L_Q30; + A5 = ASIN_FUNC_A5L_Q30; + A3 = ASIN_FUNC_A3L_Q30; + A1 = ASIN_FUNC_A1L_Q30; + qc = 30; + } else { + A7 = ASIN_FUNC_A7H_Q26; + A5 = ASIN_FUNC_A5H_Q26; + A3 = ASIN_FUNC_A3H_Q26; + A1 = ASIN_FUNC_A1H_Q26; + qc = 26; + } + + lshift = drc_get_lshift(qc, 30, qc); + tmp = AE_MULF32R_LL(A7, in2); + tmp = AE_SLAA64S(tmp, lshift); + acc = AE_ROUND32F48SSYM(tmp); + acc = AE_ADD32(acc, A5); + tmp = AE_MULF32R_LL(acc, in2); + tmp = AE_SLAA64S(tmp, lshift); + acc = AE_ROUND32F48SSYM(tmp); + acc = AE_ADD32(acc, A3); + tmp = AE_MULF32R_LL(acc, in2); + tmp = AE_SLAA64S(tmp, lshift); + acc = AE_ROUND32F48SSYM(tmp); + acc = AE_ADD32(acc, A1); + tmp = AE_MULF32R_LL(acc, x); + tmp = AE_SLAA64S(tmp, lshift); + acc = AE_ROUND32F48SSYM(tmp); + lshift = drc_get_lshift(qc, 30, 30); + tmp = AE_MULF32R_LL(acc, TWO_OVER_PI_Q30); + tmp = AE_SLAA64S(tmp, lshift); + acc = AE_ROUND32F48SSYM(tmp); + return AE_MOVAD32_L(acc); +} +#endif /* !DRC_USE_CORDIC_ASIN */ + +/* + * Input depends on precision_x + * Output depends on precision_y + */ +int32_t drc_inv_fixed(int32_t x, int32_t precision_x, int32_t precision_y) +{ + /* Coefficients obtained from: + * fpminimax(1/x, 5, [|SG...|], [sqrt(2)/2;1], absolute); + * max err ~= 1.00388e-6 + */ + __aligned(8) ae_f32 coef[2]; + ae_f64 tmp; + ae_f32x2 in; + ae_f32x2 p1p0; + ae_f32 acc; + ae_f32x2 *coefp; + int32_t in_abs; + int shift_input; + int shift_output; + int sqrt2_extracted = 0; + + /* Output range [0.5, 1); regulated to Q2.30 + * + * Note: input and output shift code was originally as more self-documenting + * bit = 31 - AE_NSAZ32_L(x); input_shift = bit - 30; + * e = bit - precision_x; precision_inv = e + 25; + * output_shift = precision_y - precision_inv; + */ + + shift_input = 1 - AE_NSAZ32_L(x); + shift_output = precision_y + precision_x - shift_input - 55; + in = AE_SRAA32(x, shift_input); + in_abs = AE_MOVAD32_L(AE_ABS32S(in)); + + if (in_abs < ONE_OVER_SQRT2_Q30) { + tmp = AE_MULF32R_LL(in, SQRT2_Q30); + tmp = AE_SLAI64S(tmp, SHIFT_IDX_QX30_QY30_QZ30); + in = AE_ROUND32F48SSYM(tmp); + sqrt2_extracted = 1; + } + + /* calculate p00(x) = a1 + a2 * x, p11(x) = a4 + a5 * x + * + * In Q25 coef * Q30 in 32 bit AE multiply the result is Q24 (25 + 30 + 1 - 32), + * so every multiply is shifted left by one to keep results as Q25. + */ + coefp = (ae_f32x2 *)drc_inv_func_coefficients; + p1p0 = AE_SLAI32S(AE_MULFP32X2RS(*coefp, in), SHIFT_IDX_QX25_QY30_QZ25); + coefp++; + p1p0 = AE_ADD32S(p1p0, *coefp); + + /* calculate p0(x) = a0 + p00(x) * x, p1(x) = a3 + p11(x) * x */ + p1p0 = AE_SLAI32S(AE_MULFP32X2RS(p1p0, in), SHIFT_IDX_QX25_QY30_QZ25); + coefp++; + p1p0 = AE_ADD32S(p1p0, *coefp); + + /* calculate p1(x) * x^3 + * + * Q30 * Q30 AE multiply gives Q61. shifting it low 32 bits as Q30 would + * need right shift by 31. For Q17,47 AE round instead it is shifted 16 bits + * less, so shift right by 15. + */ + acc = AE_ROUND32F48SASYM(AE_SRAA64(AE_MULF32S_HH(in, in), 15)); + acc = AE_ROUND32F48SASYM(AE_SRAA64(AE_MULF32S_HH(acc, in), 15)); + coef[1] = INV_FUNC_ONE_Q30; + coef[0] = acc; + p1p0 = AE_SLAI32S(AE_MULFP32X2RS(p1p0, *(ae_int32x2 *)coef), SHIFT_IDX_QX25_QY30_QZ25); + + /* calculate p(x) = p0(x) + p1(x) * x^3 + * p1p0.l holds p0(x) after multiply with one + * p1p0.h holds p1(x) * x^3 + */ + acc = AE_MOVAD32_L(AE_ADD32_HL_LH(p1p0, p1p0)); + + if (sqrt2_extracted) { + tmp = AE_MULF32R_LL(SQRT2_Q30, acc); + tmp = AE_SLAI64S(tmp, SHIFT_IDX_QX25_QY30_QZ25); + acc = AE_ROUND32F48SSYM(tmp); + } + + acc = AE_SLAA32S(acc, shift_output); + return AE_MOVAD32_L(acc); +} + +#endif /* DRC_HIFI_3/4 */ diff --git a/src/audio/drc/drc_user.h b/src/audio/drc/drc_user.h new file mode 100644 index 000000000000..d9940452a233 --- /dev/null +++ b/src/audio/drc/drc_user.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ +#ifndef __USER_DRC_H__ +#define __USER_DRC_H__ + +#include <stdint.h> + +/* Maximum number allowed in configuration blob */ +#define SOF_DRC_MAX_SIZE 1024 + +/* The parameters of the DRC compressor */ +struct sof_drc_params { + /* 1 to enable DRC, 0 to disable it */ + int32_t enabled; + + /* The value above which the compression starts, in dB */ + int32_t db_threshold; /* Q8.24 */ + + /* The value above which the knee region starts, in dB */ + int32_t db_knee; /* Q8.24 */ + + /* The input/output dB ratio after the knee region */ + int32_t ratio; /* Q8.24 */ + + /* The lookahead time for the compressor, in seconds */ + int32_t pre_delay_time; /* Q2.30 */ + + /* The input to output change below the threshold is 1:1 */ + int32_t linear_threshold; /* Q2.30 */ + + /* Inverse ratio */ + int32_t slope; /* Q2.30 */ + + /* Internal parameter for the knee portion of the curve. */ + int32_t K; /* Q12.20 */ + + /* Pre-calculated parameters */ + int32_t knee_alpha; /* Q8.24 */ + int32_t knee_beta; /* Q8.24 */ + int32_t knee_threshold; /* Q8.24 */ + int32_t ratio_base; /* Q2.30 */ + + int32_t master_linear_gain; /* Q8.24 */ + int32_t one_over_attack_frames; /* Q2.30 */ + int32_t sat_release_frames_inv_neg; /* Q2.30 */ + int32_t sat_release_rate_at_neg_two_db; /* Q2.30 */ + + /* The release frames coefficients */ + int32_t kSpacingDb; /* Q32.0 */ + int32_t kA; /* Q20.12 */ + int32_t kB; /* Q20.12 */ + int32_t kC; /* Q20.12 */ + int32_t kD; /* Q20.12 */ + int32_t kE; /* Q20.12 */ +} __attribute__((packed)); + +struct sof_drc_config { + uint32_t size; + + /* reserved */ + uint32_t reserved[4]; + + struct sof_drc_params params; +} __attribute__((packed)); + +#endif // __USER_DRC_H__ diff --git a/src/audio/drc/llext/CMakeLists.txt b/src/audio/drc/llext/CMakeLists.txt new file mode 100644 index 000000000000..d12e94790597 --- /dev/null +++ b/src/audio/drc/llext/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("drc" + SOURCES ../drc.c + ../drc_generic.c + ../drc_math_generic.c + ../drc_hifi3.c + ../drc_hifi4.c + ../drc_math_hifi3.c + LIB openmodules +) diff --git a/src/audio/drc/llext/llext.toml.h b/src/audio/drc/llext/llext.toml.h new file mode 100644 index 000000000000..89469d54fffb --- /dev/null +++ b/src/audio/drc/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../drc.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/drc/tune/sof_drc_build_blob.m b/src/audio/drc/tune/sof_drc_build_blob.m new file mode 100644 index 000000000000..72bd7288be16 --- /dev/null +++ b/src/audio/drc/tune/sof_drc_build_blob.m @@ -0,0 +1,73 @@ +function blob8 = sof_drc_build_blob(blob_struct, endian, ipc_ver) + +if nargin < 2 + endian = 'little' +end + +if nargin < 3 + ipc_ver = 3; +end + +%% Shift values for little/big endian +switch lower(endian) + case 'little' + sh = [0 -8 -16 -24]; + case 'big' + sh = [-24 -16 -8 0]; + otherwise + error('Unknown endiannes'); +end + +%% Build Blob +% refer to sof/src/include/user/drc.h for the config struct. +num_coefs = length(fieldnames(blob_struct)); +data_size = 4 * (1 + 4 + num_coefs); +[abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver); + +blob_size = data_size + abi_size; +blob8 = uint8(zeros(1, blob_size)); + +% Pack Blob data +% Insert ABI Header +blob8(1:abi_size) = abi_bytes; +j = abi_size + 1; + +% Insert Data +blob8(j:j+3) = word2byte(data_size, sh); j=j+4; +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved +blob8(j:j+3) = word2byte(0, sh); j=j+4; % Reserved + +blob8(j:j+3) = word2byte(blob_struct.enabled, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.db_threshold, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.db_knee, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.ratio, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.pre_delay_time, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.linear_threshold, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.slope, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.K, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.knee_alpha, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.knee_beta, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.knee_threshold, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.ratio_base, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.master_linear_gain, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.one_over_attack_frames, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.sat_release_frames_inv_neg, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.sat_release_rate_at_neg_two_db, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.kSpacingDb, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.kA, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.kB, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.kC, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.kD, sh); j=j+4; +blob8(j:j+3) = word2byte(blob_struct.kE, sh); j=j+4; + +end + +function bytes = word2byte(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/drc/tune/sof_drc_gen_coefs.m b/src/audio/drc/tune/sof_drc_gen_coefs.m new file mode 100644 index 000000000000..9cfa8b7019e2 --- /dev/null +++ b/src/audio/drc/tune/sof_drc_gen_coefs.m @@ -0,0 +1,120 @@ +function coefs = sof_drc_gen_coefs(params, sample_rate) + +if exist('OCTAVE_VERSION', 'builtin') + pkg load control; +end + +% Print out params +params + +coefs.enabled = params.enabled; + +% Calculate static curve coefficients +coefs.db_threshold = params.threshold; +coefs.db_knee = params.knee; +coefs.ratio = params.ratio; +coefs.pre_delay_time = params.pre_delay; +coefs.linear_threshold = db2mag(coefs.db_threshold); +coefs.slope = 1 / coefs.ratio; + +k = k_at_slope(coefs.db_threshold, coefs.db_knee, coefs.linear_threshold, coefs.slope); +coefs.K = k; +coefs.knee_alpha = coefs.linear_threshold + 1 / k; +coefs.knee_beta = -exp(k * coefs.linear_threshold) / k; +coefs.knee_threshold = db2mag(coefs.db_threshold + coefs.db_knee); + +y0 = knee_curve(coefs.linear_threshold, coefs.knee_threshold, k); +coefs.ratio_base = y0 * (coefs.knee_threshold ^ (-coefs.slope)); + +% Calculate makeup gain coefficients +full_range_makeup_gain = (1 / coefs.ratio_base) ^ 0.6; % Empirical/perceptual tuning +coefs.master_linear_gain = db2mag(params.post_gain) * full_range_makeup_gain; +coefs.master_linear_gain_db = 20*log10(coefs.master_linear_gain); + +% Calculate attack time coefficients +attack_time = max(0.001, params.attack); +coefs.one_over_attack_frames = 1 / (attack_time * sample_rate); + +% Calculate release time coefficients +release_frames = params.release * sample_rate; +sat_release_time = 0.0025; +sat_release_frames = sat_release_time * sample_rate; +coefs.sat_release_frames_inv_neg = -1 / sat_release_frames; +coefs.sat_release_rate_at_neg_two_db = db2mag(-2 * coefs.sat_release_frames_inv_neg) - 1; + +coefs.kSpacingDb = params.release_spacing; + +% Create a smooth function which passes through four points. +% Polynomial of the form y = a + b*x + c*x^2 + d*x^3 + e*x^4 +y = params.release_zone .* release_frames; + +% All of these coefficients were derived for 4th order polynomial curve fitting +% where the y values match the evenly spaced x values as follows: +% (y1 : x == 0, y2 : x == 1, y3 : x == 2, y4 : x == 3) +coefs.kA = 0.9999999999999998 * y(1) + 1.8432219684323923e-16 * y(2) ... + - 1.9373394351676423e-16 * y(3) + 8.824516011816245e-18 * y(4); +coefs.kB = -1.5788320352845888 * y(1) + 2.3305837032074286 * y(2) ... + - 0.9141194204840429 * y(3) + 0.1623677525612032 * y(4); +coefs.kC = 0.5334142869106424 * y(1) - 1.272736789213631 * y(2) ... + + 0.9258856042207512 * y(3) - 0.18656310191776226 * y(4); +coefs.kD = 0.08783463138207234 * y(1) - 0.1694162967925622 * y(2) ... + + 0.08588057951595272 * y(3) - 0.00429891410546283 * y(4); +coefs.kE = -0.042416883008123074 * y(1) + 0.1115693827987602 * y(2) ... + - 0.09764676325265872 * y(3) + 0.028494263462021576 * y(4); + +% Print out coefs +coefs + +end + + +function k = k_at_slope(db_threshold, db_knee, linear_threshold, desired_slope) + +% Approximate k given initial values +x = db2mag(db_threshold + db_knee); +min_k = 0.1; +max_k = 10000; +k = 5; + +for i = 1:15 + % A high value for k will more quickly asymptotically approach a slope of 0 + slope = slope_at(linear_threshold, x, k); + if slope < desired_slope + max_k = k; % k is too high + else + min_k = k; % k is too low + end + + % Re-calculate based on geometric mean + k = sqrt(min_k * max_k); +end + +end + + +function slope = slope_at(linear_threshold, x, k) + +if x < linear_threshold + slope = 1; +else + x2 = x * 1.001; + x_db = mag2db(x); + x2_db = mag2db(x2); + y_db = mag2db(knee_curve(linear_threshold, x, k)); + y2_db = mag2db(knee_curve(linear_threshold, x2, k)); + + slope = (y2_db - y_db) / (x2_db - x_db); +end + +end + + +function y = knee_curve(linear_threshold, x, k) + +if x < linear_threshold + y = x; +else + y = linear_threshold + (1 - exp(-k * (x - linear_threshold))) / k; +end + +end diff --git a/src/audio/drc/tune/sof_drc_generate_config.m b/src/audio/drc/tune/sof_drc_generate_config.m new file mode 100644 index 000000000000..780b6cf51e09 --- /dev/null +++ b/src/audio/drc/tune/sof_drc_generate_config.m @@ -0,0 +1,29 @@ +function config = sof_drc_generate_config(coefs); + +config.enabled = coefs.enabled; +config.db_threshold = sof_eq_coef_quant(coefs.db_threshold, 32, 24); % Q8.24 +config.db_knee = sof_eq_coef_quant(coefs.db_knee, 32, 24); % Q8.24 +config.ratio = sof_eq_coef_quant(coefs.ratio, 32, 24); % Q8.24 +config.pre_delay_time = sof_eq_coef_quant(coefs.pre_delay_time, 32, 30); % Q2.30 +config.linear_threshold = sof_eq_coef_quant(coefs.linear_threshold, 32, 30); % Q2.30 +config.slope = sof_eq_coef_quant(coefs.slope, 32, 30); % Q2.30 +config.K = sof_eq_coef_quant(coefs.K, 32, 20); % Q12.20 +config.knee_alpha = sof_eq_coef_quant(coefs.knee_alpha, 32, 24); % Q8.24 +config.knee_beta = sof_eq_coef_quant(coefs.knee_beta, 32, 24); % Q8.24 +config.knee_threshold = sof_eq_coef_quant(coefs.knee_threshold, 32, 24); % Q8.24 +config.ratio_base = sof_eq_coef_quant(coefs.ratio_base, 32, 30); % Q2.30 +config.master_linear_gain = sof_eq_coef_quant(coefs.master_linear_gain, 32, 24); % Q8.24 +config.one_over_attack_frames = sof_eq_coef_quant(coefs.one_over_attack_frames, 32, 30); % Q2.30 +config.sat_release_frames_inv_neg = sof_eq_coef_quant(coefs.sat_release_frames_inv_neg, 32, 30); % Q2.30 +config.sat_release_rate_at_neg_two_db = sof_eq_coef_quant(coefs.sat_release_rate_at_neg_two_db, 32, 30); % Q2.30 +config.kSpacingDb = coefs.kSpacingDb; +config.kA = sof_eq_coef_quant(coefs.kA, 32, 12); % Q20.12 +config.kB = sof_eq_coef_quant(coefs.kB, 32, 12); % Q20.12 +config.kC = sof_eq_coef_quant(coefs.kC, 32, 12); % Q20.12 +config.kD = sof_eq_coef_quant(coefs.kD, 32, 12); % Q20.12 +config.kE = sof_eq_coef_quant(coefs.kE, 32, 12); % Q20.12 + +% Print out config +config + +end diff --git a/src/audio/drc/tune/sof_drc_paths.m b/src/audio/drc/tune/sof_drc_paths.m new file mode 100644 index 000000000000..8bed8c8410f5 --- /dev/null +++ b/src/audio/drc/tune/sof_drc_paths.m @@ -0,0 +1,21 @@ +function sof_drc_paths(enable) + +% sof_drc_paths(enable) +% enable - set to 1 to enable needed search path +% set to 0 to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + + common = '../../../../tools/tune/common'; + eq = '../../eq_iir/tune'; + if enable + addpath(common); + addpath(eq); + else + rmpath(common); + rmpath(eq); + end +end diff --git a/src/audio/drc/tune/sof_drc_plot_db_curve.m b/src/audio/drc/tune/sof_drc_plot_db_curve.m new file mode 100644 index 000000000000..e44f5d4a102d --- /dev/null +++ b/src/audio/drc/tune/sof_drc_plot_db_curve.m @@ -0,0 +1,64 @@ +function sof_drc_plot_db_curve(coefs) + +if exist('OCTAVE_VERSION', 'builtin') + pkg load control; +end + +db_thres = coefs.db_threshold; +db_knee_thres = db_thres + coefs.db_knee; + +% Plot range of db_x determined by db_thres and db_knee_thres +db_x_center = (db_thres + db_knee_thres) / 2; +db_x_half_range = max(coefs.db_knee, 20); +db_x_start = db_x_center - db_x_half_range; +db_x_end = db_x_center + db_x_half_range; + +db_xs = linspace(db_x_start, db_x_end, 100); +db_ys = db_curve(coefs, db_xs); + +% Plot the x-y dB curve +plot(db_xs, db_ys, "b"); +hold on +grid on +% Plot the reference line: x = db_thres +plot([db_thres, db_thres], [db_ys(1), db_knee_thres], "g"); +hold on +% Plot the reference line: x = db_knee_thres +plot([db_knee_thres, db_knee_thres], [db_ys(1), db_knee_thres], "g"); +hold on +% Plot the reference line: y = x +plot([db_xs(1), db_knee_thres], [db_xs(1), db_knee_thres], "r"); +hold off +%pause(); + +end + +function db_ys = db_curve(coefs, db_xs) + +db_thres = coefs.db_threshold; +db_knee_thres = db_thres + coefs.db_knee; + +db_thres_y = db_knee_curve(coefs, db_thres); +db_knee_thres_y = db_knee_curve(coefs, db_knee_thres); + +for i = 1:100 + db_x = db_xs(i); + if db_x < db_thres + db_ys(i) = db_thres_y + (db_x - db_thres); + elseif db_x > db_knee_thres + db_ys(i) = db_knee_thres_y + coefs.slope * (db_x - db_knee_thres); + else + % Among knee curve + db_ys(i) = db_knee_curve(coefs, db_x); + end +end + +end + +function db_y = db_knee_curve(coefs, db_x); + +x = db2mag(db_x); +y = coefs.knee_alpha + coefs.knee_beta * exp(-coefs.K * x); +db_y = mag2db(y); + +end diff --git a/src/audio/drc/tune/sof_example_drc.m b/src/audio/drc/tune/sof_example_drc.m new file mode 100644 index 000000000000..febf320aad99 --- /dev/null +++ b/src/audio/drc/tune/sof_example_drc.m @@ -0,0 +1,95 @@ +function sof_example_drc() + +sof_drc_paths(true); + +% The parameters of the DRC compressor +% enabled: 1 to enable the compressor, 0 to disable it +params.enabled = 0; +% threshold: The value above which the compression starts, in dB +params.threshold = -24; +% knee: The value above which the knee region starts, in dB +params.knee = 30; +% ratio: The input/output dB ratio after the knee region +params.ratio = 12; +% attack: The time to reduce the gain by 10dB, in seconds +params.attack = 0.003; +% release: The time to increase the gain by 10dB, in seconds +params.release = 0.25; +% pre_delay: The lookahead time for the compressor, in seconds +params.pre_delay = 0.006; +% release_zone[4]: The adaptive release curve parameters +params.release_zone = [0.09 0.16 0.42 0.98]; +% release_spacing: The value of spacing per frame while releasing, in dB +params.release_spacing = 5; +% post_gain: The static boost value in output, in dB +params.post_gain = 0; + +% Export +drc_coefs_and_config_export(params, 'passthrough'); + +% Export enabled +params.enabled = 1; +drc_coefs_and_config_export(params, 'enabled'); + +% Export example configuration for a small speaker +params.enabled = 1; +params.threshold = -30; +params.knee = 20; +params.ratio = 10; +params.post_gain = 3; +drc_coefs_and_config_export(params, 'speaker_default'); + +% Export example configuration for DMIC capture +params.enabled = 1; +params.threshold = -35; +params.knee = 25; +params.ratio = 10; +params.post_gain = 0; +drc_coefs_and_config_export(params, 'dmic_default'); + +sof_drc_paths(false); + +end + +function drc_coefs_and_config_export(params, id) + +% Set the parameters here +sof_tools = '../../../../tools'; +sof_tplg = fullfile(sof_tools, 'topology'); +sof_ctl = fullfile(sof_tools, 'ctl'); +tplg1_fn = sprintf("%s/topology1/m4/drc_coef_%s.m4", sof_tplg, id); % Control Bytes File +tplg2_fn = sprintf("%s/topology2/include/components/drc/%s.conf", sof_tplg, id); % Control Bytes File +% Use those files with sof-ctl to update the component's configuration +blob3_fn = sprintf("%s/ipc3/drc_coef_%s.bin", sof_ctl, id); % Blob binary file +alsa3_fn = sprintf("%s/ipc3/drc_coef_%s.txt", sof_ctl, id); % ALSA CSV format file +blob4_fn = sprintf("%s/ipc4/drc/%s.bin", sof_ctl, id); % Blob binary file +alsa4_fn = sprintf("%s/ipc4/drc/%s.txt", sof_ctl, id); % ALSA CSV format file + +endian = "little"; +sample_rate = 48000; + +% Generate coefficients for DRC with the given parameters +coefs = sof_drc_gen_coefs(params, sample_rate); + +% Convert coefficients to sof_drc_config struct +config = sof_drc_generate_config(coefs); + +% Convert struct to binary blob +blob8 = sof_drc_build_blob(config, endian); +blob8_ipc4 = sof_drc_build_blob(config, endian, 4); + +% Generate output files +my_name = mfilename(); +drc_note = sprintf("Exported with script %s.m", my_name); +drc_howto = sprintf("cd tools/tune/drc; octave --no-window-system %s.m", my_name); +sof_tplg_write(tplg1_fn, blob8, "DRC", drc_note, drc_howto); +sof_tplg2_write(tplg2_fn, blob8_ipc4, "drc_config", drc_note, drc_howto); +sof_ucm_blob_write(blob3_fn, blob8); +sof_alsactl_write(alsa3_fn, blob8); +sof_ucm_blob_write(blob4_fn, blob8_ipc4); +sof_alsactl_write(alsa4_fn, blob8_ipc4); + +% Plot x-y response in dB +sof_drc_plot_db_curve(coefs); + +end diff --git a/src/audio/eq_fir/CMakeLists.txt b/src/audio/eq_fir/CMakeLists.txt index 2ca5290528ca..2c98126a1d86 100644 --- a/src/audio/eq_fir/CMakeLists.txt +++ b/src/audio/eq_fir/CMakeLists.txt @@ -1,3 +1,18 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof eq_fir.c fir_hifi2ep.c fir_hifi3.c fir.c) +if(CONFIG_COMP_FIR STREQUAL "m" AND DEFINED CONFIG_LLEXT) + + add_subdirectory(llext ${PROJECT_BINARY_DIR}/eq_fir_llext) + add_dependencies(app eq_fir) + +else() + + add_local_sources(sof eq_fir.c eq_fir_generic.c eq_fir_hifi2ep.c eq_fir_hifi3.c) + + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof eq_fir_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof eq_fir_ipc4.c) + endif() + +endif() diff --git a/src/audio/eq_fir/Kconfig b/src/audio/eq_fir/Kconfig new file mode 100644 index 000000000000..0ac2074e499b --- /dev/null +++ b/src/audio/eq_fir/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_FIR + tristate "FIR component" + select MATH_FIR + select COMP_BLOB + depends on COMP_MODULE_ADAPTER + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for FIR component. FIR performance can differ between DSP + ISA and compiler used. FIR will perform best when MAC instructions + are available in ISA and are used by the compiler. i.e. xt-xcc on + xtensa will generate MAC instructions but GCC on xtensa won't. + Filter tap count can be severely restricted to reduce FIR cycles + and FIR performance for DSP/compilers with no MAC support diff --git a/src/audio/eq_fir/README.md b/src/audio/eq_fir/README.md new file mode 100644 index 000000000000..24be526f6189 --- /dev/null +++ b/src/audio/eq_fir/README.md @@ -0,0 +1,24 @@ +# FIR Equalizer Architecture + +This directory contains the Finite Impulse Response (FIR) EQ component. + +## Overview + +FIR equalizers implement linear-phase (or minimal-phase) audio frequency shaping over a specified set of taps. + +## Architecture Diagram + +```mermaid +graph LR + In[Input Frame] --> FIR[FIR Filter Engine] + Coeffs[(Filter Coefficients)] --> FIR + FIR --> Out[Output Frame] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the FIR component (`COMP_FIR`), which automatically imports `MATH_FIR` and `COMP_BLOB`. Relies on compiler capabilities to leverage DSP MAC instructions for optimal performance. +- **CMakeLists.txt**: Integrates generic and architecture-specific (`eq_fir_hifi2ep.c`, `eq_fir_hifi3.c`) files into the build, picking the correct IPC wrapper (`ipc3` or `ipc4`), and supports `llext`. +- **eq_fir.toml**: Topology parameters for the EQFIR module, defining UUIDs, memory parameters (like 4096 bytes limits) and pin layouts. +- **Topology (.conf)**: Constrained by `tools/topology/topology2/include/components/eqfir.conf`, assigning it widget type `effect` and UUID `e7:0c:a9:43:a5:f3:df:41:ac:06:ba:98:65:1a:e6:a3`. +- **MATLAB Tuning (`tune/`)**: `sof_example_fir_eq.m` utilizes the Parks-McClellan (or related) algorithms to model loudness or mid-boost curves, iterating length variables to determine optimal FIR phase behaviors. It outputs quantized binary arrays containing the calculated taps necessary for topology population. diff --git a/src/audio/eq_fir/eq_fir.c b/src/audio/eq_fir/eq_fir.c index 611f089da01e..793a2294c647 100644 --- a/src/audio/eq_fir/eq_fir.c +++ b/src/audio/eq_fir/eq_fir.c @@ -8,247 +8,74 @@ #include <sof/audio/buffer.h> #include <sof/audio/component.h> -#include <sof/audio/eq_fir/fir_config.h> +#include <sof/audio/data_blob.h> #include <sof/audio/pipeline.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/ipc-config.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> #include <sof/lib/uuid.h> #include <sof/list.h> +#include <sof/math/fir_config.h> #include <sof/platform.h> -#include <sof/string.h> +#include <rtos/string.h> +#include <sof/ut.h> #include <sof/trace/trace.h> #include <ipc/control.h> #include <ipc/stream.h> #include <ipc/topology.h> #include <kernel/abi.h> #include <user/eq.h> +#include <user/fir.h> #include <user/trace.h> #include <errno.h> #include <stddef.h> #include <stdint.h> -#if FIR_GENERIC -#include <sof/audio/eq_fir/fir.h> -#endif - -#if FIR_HIFIEP -#include <sof/audio/eq_fir/fir_hifi2ep.h> -#endif - -#if FIR_HIFI3 -#include <sof/audio/eq_fir/fir_hifi3.h> -#endif - -static const struct comp_driver comp_eq_fir; - -/* 43a90ce7-f3a5-41df-ac06-ba98651ae6a3 */ -DECLARE_SOF_UUID("eq-fir", eq_fir_uuid, 0x43a90ce7, 0xf3a5, 0x41df, - 0xac, 0x06, 0xba, 0x98, 0x65, 0x1a, 0xe6, 0xa3); - -/* src component private data */ -struct comp_data { - struct fir_state_32x16 fir[PLATFORM_MAX_CHANNELS]; /**< filters state */ - struct sof_eq_fir_config *config; /**< pointer to setup blob */ - struct sof_eq_fir_config *config_new; /**< pointer to new setup */ - enum sof_ipc_frame source_format; /**< source frame format */ - enum sof_ipc_frame sink_format; /**< sink frame format */ - int32_t *fir_delay; /**< pointer to allocated RAM */ - size_t fir_delay_size; /**< allocated size */ - bool config_ready; /**< set when fully received */ - void (*eq_fir_func)(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch); -}; - -/* - * The optimized FIR functions variants need to be updated into function - * set_fir_func. - */ - -#if FIR_HIFI3 -#if CONFIG_FORMAT_S16LE -static inline void set_s16_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_2x_s16_hifi3; -} -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE -static inline void set_s24_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_2x_s24_hifi3; -} -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE -static inline void set_s32_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_2x_s32_hifi3; -} -#endif /* CONFIG_FORMAT_S32LE */ +#include "eq_fir.h" -#elif FIR_HIFIEP -#if CONFIG_FORMAT_S16LE -static inline void set_s16_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_2x_s16_hifiep; -} -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE -static inline void set_s24_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_2x_s24_hifiep; -} -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE -static inline void set_s32_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_2x_s32_hifiep; -} -#endif /* CONFIG_FORMAT_S32LE */ -#else -/* FIR_GENERIC */ -#if CONFIG_FORMAT_S16LE -static inline void set_s16_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_s16; -} -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE -static inline void set_s24_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_s24; -} -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE -static inline void set_s32_fir(struct comp_data *cd) -{ - cd->eq_fir_func = eq_fir_s32; -} -#endif /* CONFIG_FORMAT_S32LE */ -#endif +LOG_MODULE_REGISTER(eq_fir, CONFIG_SOF_LOG_LEVEL); -static inline int set_fir_func(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sourceb; - - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - - switch (sourceb->stream.frame_fmt) { -#if CONFIG_FORMAT_S16LE - case SOF_IPC_FRAME_S16_LE: - comp_info(dev, "set_fir_func(), SOF_IPC_FRAME_S16_LE"); - set_s16_fir(cd); - break; -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - case SOF_IPC_FRAME_S24_4LE: - comp_info(dev, "set_fir_func(), SOF_IPC_FRAME_S24_4LE"); - set_s24_fir(cd); - break; -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - case SOF_IPC_FRAME_S32_LE: - comp_info(dev, "set_fir_func(), SOF_IPC_FRAME_S32_LE"); - set_s32_fir(cd); - break; -#endif /* CONFIG_FORMAT_S32LE */ - default: - comp_err(dev, "set_fir_func(), invalid frame_fmt"); - return -EINVAL; - } - return 0; -} +SOF_DEFINE_REG_UUID(eq_fir); -/* Pass-trough functions to replace FIR core while not configured for +/* Pass-through functions to replace FIR core while not configured for * response. */ -#if CONFIG_FORMAT_S16LE -static void eq_fir_s16_passthrough(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch) +static void eq_fir_passthrough(struct fir_state_32x16 fir[], + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, + int frames) { - audio_stream_copy_s16(source, 0, sink, 0, frames * nch); -} -#endif /* CONFIG_FORMAT_S16LE */ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; -#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE -static void eq_fir_s32_passthrough(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch) -{ - audio_stream_copy_s32(source, 0, sink, 0, frames * nch); + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); } -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ - -/* Function to select pass-trough depending on PCM format */ -static inline int set_pass_func(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sourceb; - - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - - switch (sourceb->stream.frame_fmt) { -#if CONFIG_FORMAT_S16LE - case SOF_IPC_FRAME_S16_LE: - comp_info(dev, "set_pass_func(), SOF_IPC_FRAME_S16_LE"); - cd->eq_fir_func = eq_fir_s16_passthrough; - break; -#endif /* CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE - case SOF_IPC_FRAME_S24_4LE: - case SOF_IPC_FRAME_S32_LE: - comp_info(dev, "set_pass_func(), SOF_IPC_FRAME_S32_LE"); - cd->eq_fir_func = eq_fir_s32_passthrough; - break; -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ - default: - comp_err(dev, "set_pass_func() error: invalid dev->params.frame_fmt"); - return -EINVAL; - } - return 0; -} - -/* - * EQ control code is next. The processing is in fir_ C modules. - */ - -static void eq_fir_free_parameters(struct sof_eq_fir_config **config) -{ - rfree(*config); - *config = NULL; -} - -static void eq_fir_free_delaylines(struct comp_data *cd) +static void eq_fir_free_delaylines(struct processing_module *mod) { + struct comp_data *cd = module_get_private_data(mod); struct fir_state_32x16 *fir = cd->fir; int i = 0; /* Free the common buffer for all EQs and point then * each FIR channel delay line to NULL. */ - rfree(cd->fir_delay); + mod_free(mod, cd->fir_delay); cd->fir_delay = NULL; cd->fir_delay_size = 0; for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) fir[i].delay = NULL; } -static int eq_fir_init_coef(struct sof_eq_fir_config *config, +static int eq_fir_init_coef(struct comp_dev *dev, struct sof_eq_fir_config *config, struct fir_state_32x16 *fir, int nch) { - struct sof_eq_fir_coef_data *lookup[SOF_EQ_FIR_MAX_RESPONSES]; - struct sof_eq_fir_coef_data *eq; + struct sof_fir_coef_data *lookup[SOF_EQ_FIR_MAX_RESPONSES]; + struct sof_fir_coef_data *eq; int16_t *assign_response; int16_t *coef_data; size_t size_sum = 0; @@ -257,32 +84,44 @@ static int eq_fir_init_coef(struct sof_eq_fir_config *config, int j; int s; - comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), response assign for %u channels, %u responses", - config->channels_in_config, - config->number_of_responses); + /* If this function is called with fir==NULL, then it's supposed to validate the + * new configuration without actually altering it. + */ + if (!fir) { + /* Called from validate(), we shall find nch and assign it accordingly, + * as the parameter is not valid + */ + struct processing_module *mod = comp_mod(dev); + struct comp_data *cd = module_get_private_data(mod); + + nch = cd->nch; + } + + comp_info(dev, "%u responses, %u channels, stream %d channels", + config->number_of_responses, config->channels_in_config, nch); /* Sanity checks */ if (nch > PLATFORM_MAX_CHANNELS || config->channels_in_config > PLATFORM_MAX_CHANNELS || !config->channels_in_config) { - comp_cl_err(&comp_eq_fir, "eq_fir_init_coef(), invalid channels count"); + comp_err(dev, "invalid channels count"); return -EINVAL; } if (config->number_of_responses > SOF_EQ_FIR_MAX_RESPONSES) { - comp_cl_err(&comp_eq_fir, "eq_fir_init_coef(), # of resp exceeds max"); + comp_err(dev, "# of resp exceeds max"); return -EINVAL; } - /* Collect index of respose start positions in all_coefficients[] */ + /* Collect index of response start positions in all_coefficients[] */ j = 0; assign_response = ASSUME_ALIGNED(&config->data[0], 4); coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config], 4); for (i = 0; i < SOF_EQ_FIR_MAX_RESPONSES; i++) { if (i < config->number_of_responses) { - eq = (struct sof_eq_fir_coef_data *)&coef_data[j]; + eq = (struct sof_fir_coef_data *)&coef_data[j]; lookup[i] = eq; - j += SOF_EQ_FIR_COEF_NHEADER + coef_data[j]; + j += SOF_FIR_COEF_NHEADER + coef_data[j]; } else { lookup[i] = NULL; } @@ -303,15 +142,16 @@ static int eq_fir_init_coef(struct sof_eq_fir_config *config, /* Initialize EQ channel to bypass and continue with * next channel response. */ - comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), ch %d is set to bypass", - i); - fir_reset(&fir[i]); + if (fir) { + comp_info(dev, "ch %d is set to bypass", i); + fir_reset(&fir[i]); + } continue; } if (resp >= config->number_of_responses) { - comp_cl_err(&comp_eq_fir, "eq_fir_init_coef(), requested response %d exceeds what has been defined", - resp); + comp_err(dev, "requested response %d exceeds what has been defined", + resp); return -EINVAL; } @@ -321,22 +161,23 @@ static int eq_fir_init_coef(struct sof_eq_fir_config *config, if (s > 0) { size_sum += s; } else { - comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), FIR length %d is invalid", - eq->length); + comp_info(dev, "FIR length %d is invalid", eq->length); return -EINVAL; } #if defined FIR_MAX_LENGTH_BUILD_SPECIFIC - if (fir[i].taps * nch > FIR_MAX_LENGTH_BUILD_SPECIFIC) { - comp_cl_err(&comp_eq_fir, "Filter length %d exceeds limitation for build.", - fir[i].length); + if (eq->length * nch > FIR_MAX_LENGTH_BUILD_SPECIFIC) { + comp_err(dev, "Filter length %d exceeds limitation for build.", + eq->length); return -EINVAL; } #endif - fir_init_coef(&fir[i], eq); - comp_cl_info(&comp_eq_fir, "eq_fir_init_coef(), ch %d is set to response = %d", - i, resp); + if (fir) { + fir_init_coef(&fir[i], eq); + comp_info(dev, "ch %d is set to response = %d", + i, resp); + } } return size_sum; @@ -355,15 +196,20 @@ static void eq_fir_init_delay(struct fir_state_32x16 *fir, } } -static int eq_fir_setup(struct comp_data *cd, int nch) +static int eq_fir_setup(struct processing_module *mod, int nch) { + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; int delay_size; /* Free existing FIR channels data if it was allocated */ - eq_fir_free_delaylines(cd); + eq_fir_free_delaylines(mod); + + /* Update number of channels */ + cd->nch = nch; /* Set coefficients for each channel EQ from coefficient blob */ - delay_size = eq_fir_init_coef(cd->config, cd->fir, nch); + delay_size = eq_fir_init_coef(dev, cd->config, cd->fir, nch); if (delay_size < 0) return delay_size; /* Contains error code */ @@ -374,10 +220,9 @@ static int eq_fir_setup(struct comp_data *cd, int nch) return 0; /* Allocate all FIR channels data in a big chunk and clear it */ - cd->fir_delay = rballoc(0, SOF_MEM_CAPS_RAM, delay_size); + cd->fir_delay = mod_balloc(mod, delay_size); if (!cd->fir_delay) { - comp_cl_err(&comp_eq_fir, "eq_fir_setup(), delay allocation failed for size %d", - delay_size); + comp_err(dev, "delay allocation failed for size %d", delay_size); return -ENOMEM; } @@ -389,367 +234,120 @@ static int eq_fir_setup(struct comp_data *cd, int nch) return 0; } +static int eq_fir_validator(struct comp_dev *dev, void *new_data, uint32_t new_data_size) +{ + return eq_fir_init_coef(dev, new_data, NULL, -1); +} + /* * End of algorithm code. Next the standard component methods. */ -static struct comp_dev *eq_fir_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) +static int eq_fir_init(struct processing_module *mod) { - struct comp_dev *dev; - struct comp_data *cd; - struct sof_ipc_comp_process *fir; - struct sof_ipc_comp_process *ipc_fir - = (struct sof_ipc_comp_process *)comp; - size_t bs = ipc_fir->size; + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct comp_data *cd = NULL; int i; - int ret; - - comp_cl_info(&comp_eq_fir, "eq_fir_new()"); - /* Check first before proceeding with dev and cd that coefficients - * blob size is sane. - */ - if (bs > SOF_EQ_FIR_MAX_SIZE) { - comp_cl_err(&comp_eq_fir, "eq_fir_new() error: coefficients blob size = %u > SOF_EQ_FIR_MAX_SIZE", - bs); - return NULL; - } + comp_info(dev, "entry"); - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_process)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_process); - - fir = COMP_GET_IPC(dev, sof_ipc_comp_process); - ret = memcpy_s(fir, sizeof(*fir), ipc_fir, - sizeof(struct sof_ipc_comp_process)); - assert(!ret); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; cd->eq_fir_func = NULL; - cd->config = NULL; - cd->config_new = NULL; - cd->config_ready = false; cd->fir_delay = NULL; cd->fir_delay_size = 0; + cd->nch = -1; - /* Allocate and make a copy of the coefficients blob and reset FIR. If - * the EQ is configured later in run-time the size is zero. - */ - if (bs) { - cd->config = rballoc(0, SOF_MEM_CAPS_RAM, bs); - if (!cd->config) { - rfree(dev); - rfree(cd); - return NULL; - } - - ret = memcpy_s(cd->config, bs, ipc_fir->data, bs); - assert(!ret); - cd->config_ready = true; + /* component model data handler */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + mod_free(mod, cd); + return -ENOMEM; } + md->private = cd; + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) fir_reset(&cd->fir[i]); - dev->state = COMP_STATE_READY; - return dev; -} - -static void eq_fir_free(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "eq_fir_free()"); - - eq_fir_free_delaylines(cd); - eq_fir_free_parameters(&cd->config); - eq_fir_free_parameters(&cd->config_new); - - rfree(cd); - rfree(dev); -} - -static int eq_fir_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int ret; - - comp_dbg(dev, "eq_fir_verify_params()"); - - ret = comp_verify_params(dev, 0, params); - if (ret < 0) { - comp_err(dev, "eq_fir_verify_params() error: comp_verify_params() failed."); - return ret; - } - - return 0; -} - -/* set component audio stream parameters */ -static int eq_fir_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int err; - - comp_info(dev, "eq_fir_params()"); - - err = eq_fir_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "eq_fir_params(): pcm params verification failed."); - return -EINVAL; - } - - /* All configuration work is postponed to prepare(). */ return 0; } -static int fir_cmd_get_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int max_size) -{ - struct comp_data *cd = comp_get_drvdata(dev); - unsigned char *dst, *src; - size_t offset; - size_t bs; - int ret = 0; - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "fir_cmd_get_data(), SOF_CTRL_CMD_BINARY"); - - max_size -= sizeof(struct sof_ipc_ctrl_data) + - sizeof(struct sof_abi_hdr); - - /* Copy back to user space */ - if (cd->config) { - src = (unsigned char *)cd->config; - dst = (unsigned char *)cdata->data->data; - bs = cd->config->size; - cdata->elems_remaining = 0; - offset = 0; - if (bs > max_size) { - bs = (cdata->msg_index + 1) * max_size > bs ? - bs - cdata->msg_index * max_size : - max_size; - offset = cdata->msg_index * max_size; - cdata->elems_remaining = cd->config->size - - offset; - } - cdata->num_elems = bs; - comp_info(dev, "fir_cmd_get_data(), blob size %zu msg index %u max size %u offset %zu", - bs, cdata->msg_index, max_size, offset); - ret = memcpy_s(dst, ((struct sof_abi_hdr *) - (cdata->data))->size, src + offset, - bs); - assert(!ret); - - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = bs; - } else { - comp_err(dev, "fir_cmd_get_data() error: invalid cd->config"); - ret = -EINVAL; - } - break; - default: - comp_err(dev, "fir_cmd_get_data() error: invalid cdata->cmd"); - ret = -EINVAL; - break; - } - return ret; -} - -static int fir_cmd_set_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) +static int eq_fir_free(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); - unsigned char *dst, *src; - uint32_t offset; - int ret = 0; - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "fir_cmd_set_data(), SOF_CTRL_CMD_BINARY"); - - /* Check that there is no work-in-progress previous request */ - if (cd->config_new && cdata->msg_index == 0) { - comp_err(dev, "fir_cmd_set_data(), busy with previous request"); - return -EBUSY; - } - - /* Copy new config, find size from header */ - comp_info(dev, "fir_cmd_set_data(): blob size: %u msg_index %u", - cdata->num_elems + cdata->elems_remaining, - cdata->msg_index); - if (cdata->num_elems + cdata->elems_remaining > - SOF_EQ_FIR_MAX_SIZE) - return -EINVAL; - - if (cdata->msg_index == 0) { - /* Allocate buffer for copy of the blob. */ - cd->config_new = rballoc(0, SOF_MEM_CAPS_RAM, - cdata->num_elems + - cdata->elems_remaining); - - if (!cd->config_new) { - comp_err(dev, "fir_cmd_set_data() error: buffer allocation failed"); - return -EINVAL; - } + struct comp_data *cd = module_get_private_data(mod); - cd->config_ready = false; - offset = 0; - } else { - assert(cd->config_new); - offset = cd->config_new->size - cdata->elems_remaining - - cdata->num_elems; - } + comp_dbg(mod->dev, "entry"); - dst = (unsigned char *)cd->config_new; - src = (unsigned char *)cdata->data->data; + eq_fir_free_delaylines(mod); + mod_data_blob_handler_free(mod, cd->model_handler); - /* Just copy the configuration. The EQ will be initialized in - * prepare(). - */ - ret = memcpy_s(dst + offset, cdata->num_elems + - cdata->elems_remaining - offset, src, - cdata->num_elems); - assert(!ret); - - /* we can check data when elems_remaining == 0 */ - if (cdata->elems_remaining == 0) { - /* The new configuration is OK to be applied */ - cd->config_ready = true; - - /* If component state is READY we can omit old - * configuration immediately. When in playback/capture - * the new configuration presence is checked in copy(). - */ - if (dev->state == COMP_STATE_READY) - eq_fir_free_parameters(&cd->config); + mod_free(mod, cd); - /* If there is no existing configuration the received - * can be set to current immediately. It will be - * applied in prepare() when streaming starts. - */ - if (!cd->config) { - cd->config = cd->config_new; - cd->config_new = NULL; - } - } - break; - default: - comp_err(dev, "fir_cmd_set_data() error: invalid cdata->cmd"); - ret = -EINVAL; - break; - } - - return ret; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int eq_fir_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = data; - int ret = 0; - - comp_info(dev, "eq_fir_cmd()"); - - switch (cmd) { - case COMP_CMD_SET_DATA: - ret = fir_cmd_set_data(dev, cdata); - break; - case COMP_CMD_GET_DATA: - ret = fir_cmd_get_data(dev, cdata, max_data_size); - break; - default: - comp_err(dev, "eq_fir_cmd() error: invalid command"); - ret = -EINVAL; - } - - return ret; + return 0; } -static int eq_fir_trigger(struct comp_dev *dev, int cmd) +static int eq_fir_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) { - struct comp_data *cd = comp_get_drvdata(dev); + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_data *cd = module_get_private_data(mod); - comp_info(dev, "eq_fir_trigger()"); + comp_info(mod->dev, "entry"); - if (cmd == COMP_TRIGGER_START || cmd == COMP_TRIGGER_RELEASE) - assert(cd->eq_fir_func); - - return comp_set_state(dev, cmd); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); } -static void eq_fir_process(struct comp_dev *dev, struct comp_buffer *source, - struct comp_buffer *sink, int frames, - uint32_t source_bytes, uint32_t sink_bytes) +static int eq_fir_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_data *cd = comp_get_drvdata(dev); - - buffer_invalidate(source, source_bytes); + struct comp_data *cd = module_get_private_data(mod); - cd->eq_fir_func(cd->fir, &source->stream, &sink->stream, frames, - source->stream.channels); + comp_info(mod->dev, "entry"); - buffer_writeback(sink, sink_bytes); - - /* calc new free and available */ - comp_update_buffer_consume(source, source_bytes); - comp_update_buffer_produce(sink, sink_bytes); + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); } /* copy and process stream data from source to sink buffers */ -static int eq_fir_copy(struct comp_dev *dev) +static int eq_fir_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 comp_copy_limits cl; - struct comp_buffer *sourceb; - struct comp_buffer *sinkb; - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; + uint32_t frame_count = input_buffers[0].size; int ret; - int n; - uint32_t flags = 0; - - comp_dbg(dev, "eq_fir_copy()"); - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); + comp_dbg(mod->dev, "entry"); /* Check for changed configuration */ - if (cd->config_new && cd->config_ready) { - eq_fir_free_parameters(&cd->config); - cd->config = cd->config_new; - cd->config_new = NULL; - ret = eq_fir_setup(cd, sourceb->stream.channels); + 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, audio_stream_get_channels(source)); if (ret < 0) { - comp_err(dev, "eq_fir_copy(), failed FIR setup"); + comp_err(mod->dev, "failed FIR setup"); return ret; + } else if (cd->fir_delay_size) { + comp_dbg(mod->dev, "active"); + ret = set_fir_func(mod, audio_stream_get_frm_fmt(source)); + if (ret < 0) + return ret; + } else { + cd->eq_fir_func = eq_fir_passthrough; + comp_dbg(mod->dev, "pass-through"); } } - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - buffer_lock(sourceb, &flags); - buffer_lock(sinkb, &flags); - - /* Get source, sink, number of frames etc. to process. */ - comp_get_copy_limits(sourceb, sinkb, &cl); - - buffer_unlock(sinkb, flags); - buffer_unlock(sourceb, flags); - /* * Process only even number of frames with the FIR function. The * optimized filter function loads the successive input samples from @@ -758,116 +356,121 @@ static int eq_fir_copy(struct comp_dev *dev) * break the delay line alignment if called with odd number of frames * so it can't be used here. */ - if (cl.frames >= 2) { - n = (cl.frames >> 1) << 1; - /* Run EQ function */ - eq_fir_process(dev, sourceb, sinkb, n, - n * cl.source_frame_bytes, - n * cl.sink_frame_bytes); + frame_count &= ~0x1; + if (frame_count) { + cd->eq_fir_func(cd->fir, &input_buffers[0], &output_buffers[0], frame_count); + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frame_count); } return 0; } -static int eq_fir_prepare(struct comp_dev *dev) +static void eq_fir_set_alignment(struct audio_stream *source) { - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *sourceb; - struct comp_buffer *sinkb; - uint32_t sink_period_bytes; - int ret; + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; + const uint32_t frame_align_req = 2; /* Process multiples of 2 frames */ - comp_info(dev, "eq_fir_prepare()"); + audio_stream_set_align(byte_align, frame_align_req, source); +} - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; +static int eq_fir_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_buffer *sourceb, *sinkb; + struct comp_dev *dev = mod->dev; + int channels; + enum sof_ipc_frame frame_fmt; + int ret = 0; + size_t data_size; - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + comp_dbg(dev, "entry"); /* EQ component 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); - - /* get source data format */ - cd->source_format = sourceb->stream.frame_fmt; - - /* get sink data format and period bytes */ - cd->sink_format = sinkb->stream.frame_fmt; - sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, - dev->frames); - - if (sinkb->stream.size < config->periods_sink * sink_period_bytes) { - comp_err(dev, "eq_fir_prepare() error: sink buffer size is insufficient"); - ret = -ENOMEM; - goto err; + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; } - /* Initialize EQ */ - if (cd->config && cd->config_ready) { - ret = eq_fir_setup(cd, sourceb->stream.channels); - if (ret < 0) { - comp_err(dev, "eq_fir_prepare() error: eq_fir_setup failed."); - goto err; - } - - ret = set_fir_func(dev); + ret = eq_fir_params(mod); + if (ret < 0) { + comp_set_state(dev, COMP_TRIGGER_RESET); return ret; } - ret = set_pass_func(dev); - return ret; + eq_fir_set_alignment(&sourceb->stream); + channels = audio_stream_get_channels(&sinkb->stream); + frame_fmt = audio_stream_get_frm_fmt(&sourceb->stream); + + cd->eq_fir_func = eq_fir_passthrough; + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + if (cd->config && data_size > 0) { + ret = eq_fir_setup(mod, channels); + if (ret < 0) + comp_err(dev, "eq_fir_setup failed."); + else if (cd->fir_delay_size) + ret = set_fir_func(mod, frame_fmt); + else + comp_dbg(dev, "pass-through"); + } + + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + /* Ensure concurrent changes don't mess with the playback */ + comp_data_blob_set_validator(cd->model_handler, eq_fir_validator); -err: - comp_set_state(dev, COMP_TRIGGER_RESET); return ret; } -static int eq_fir_reset(struct comp_dev *dev) +static int eq_fir_reset(struct processing_module *mod) { int i; - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); - comp_info(dev, "eq_fir_reset()"); + comp_dbg(mod->dev, "entry"); - eq_fir_free_delaylines(cd); + comp_data_blob_set_validator(cd->model_handler, NULL); + + eq_fir_free_delaylines(mod); cd->eq_fir_func = NULL; for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) fir_reset(&cd->fir[i]); - comp_set_state(dev, COMP_TRIGGER_RESET); return 0; } -static const struct comp_driver comp_eq_fir = { - .type = SOF_COMP_EQ_FIR, - .uid = SOF_UUID(eq_fir_uuid), - .ops = { - .new = eq_fir_new, +static const struct module_interface eq_fir_interface = { + .init = eq_fir_init, .free = eq_fir_free, - .params = eq_fir_params, - .cmd = eq_fir_cmd, - .trigger = eq_fir_trigger, - .copy = eq_fir_copy, + .set_configuration = eq_fir_set_config, + .get_configuration = eq_fir_get_config, + .process_audio_stream = eq_fir_process, .prepare = eq_fir_prepare, .reset = eq_fir_reset, - }, }; -static SHARED_DATA struct comp_driver_info comp_eq_fir_info = { - .drv = &comp_eq_fir, -}; +#if CONFIG_COMP_FIR_MODULE +/* modular: llext dynamic link */ -static void sys_comp_eq_fir_init(void) -{ - comp_register(platform_shared_get(&comp_eq_fir_info, - sizeof(comp_eq_fir_info))); -} +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("EQFIR", &eq_fir_interface, 1, SOF_REG_UUID(eq_fir), 40); -DECLARE_MODULE(sys_comp_eq_fir_init); +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(eq_fir_tr, SOF_UUID(eq_fir_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(eq_fir_interface, eq_fir_uuid, eq_fir_tr); +SOF_MODULE_INIT(eq_fir, sys_comp_module_eq_fir_interface_init); + +#endif diff --git a/src/audio/eq_fir/eq_fir.h b/src/audio/eq_fir/eq_fir.h new file mode 100644 index 000000000000..921d39939d69 --- /dev/null +++ b/src/audio/eq_fir/eq_fir.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_EQ_FIR_EQ_FIR_H__ +#define __SOF_AUDIO_EQ_FIR_EQ_FIR_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/format.h> +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(NONE, FILTER) +#include <sof/math/fir_generic.h> +#endif +#if SOF_USE_HIFI(2, FILTER) +#include <sof/math/fir_hifi2ep.h> +#endif +#if SOF_USE_MIN_HIFI(3, FILTER) +#include <sof/math/fir_hifi3.h> +#endif +#include <user/fir.h> +#include <stdint.h> + +/** \brief Macros to convert without division bytes count to samples count */ +#define EQ_FIR_BYTES_TO_S16_SAMPLES(b) ((b) >> 1) +#define EQ_FIR_BYTES_TO_S32_SAMPLES(b) ((b) >> 2) + +/* fir component private data */ +struct comp_data { + struct fir_state_32x16 fir[PLATFORM_MAX_CHANNELS]; /**< filters state */ + struct comp_data_blob_handler *model_handler; + struct sof_eq_fir_config *config; + int32_t *fir_delay; /**< pointer to allocated RAM */ + size_t fir_delay_size; /**< allocated size */ + void (*eq_fir_func)(struct fir_state_32x16 fir[], + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, + int frames); + int nch; +}; + +#if CONFIG_FORMAT_S16LE +void eq_fir_s16(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); + +void eq_fir_2x_s16(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +void eq_fir_s24(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); + +void eq_fir_2x_s24(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +void eq_fir_s32(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); + +void eq_fir_2x_s32(struct fir_state_32x16 *fir, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif /* CONFIG_FORMAT_S32LE */ + +int set_fir_func(struct processing_module *mod, enum sof_ipc_frame fmt); + +int eq_fir_params(struct processing_module *mod); + +/* + * The optimized FIR functions variants need to be updated into function + * set_fir_func. + */ + +#if SOF_USE_MIN_HIFI(2, FILTER) +#if CONFIG_FORMAT_S16LE +static inline void set_s16_fir(struct comp_data *cd) +{ + cd->eq_fir_func = eq_fir_2x_s16; +} +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE +static inline void set_s24_fir(struct comp_data *cd) +{ + cd->eq_fir_func = eq_fir_2x_s24; +} +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE +static inline void set_s32_fir(struct comp_data *cd) +{ + cd->eq_fir_func = eq_fir_2x_s32; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#else +/* FIR_GENERIC */ +#if CONFIG_FORMAT_S16LE +static inline void set_s16_fir(struct comp_data *cd) +{ + cd->eq_fir_func = eq_fir_s16; +} +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE +static inline void set_s24_fir(struct comp_data *cd) +{ + cd->eq_fir_func = eq_fir_s24; +} +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE +static inline void set_s32_fir(struct comp_data *cd) +{ + cd->eq_fir_func = eq_fir_s32; +} +#endif /* CONFIG_FORMAT_S32LE */ +#endif + +#ifdef UNIT_TEST +void sys_comp_module_eq_fir_interface_init(void); +#endif + +#endif /* __SOF_AUDIO_EQ_FIR_EQ_FIR_H__ */ diff --git a/src/audio/eq_fir/eq_fir.toml b/src/audio/eq_fir/eq_fir.toml new file mode 100644 index 000000000000..514a0804bba7 --- /dev/null +++ b/src/audio/eq_fir/eq_fir.toml @@ -0,0 +1,25 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # eq fir module config + [[module.entry]] + name = "EQFIR" + uuid = UUIDREG_STR_EQ_FIR + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] + REM # identical for MTL and LNL + mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/eq_fir/eq_fir_generic.c b/src/audio/eq_fir/eq_fir_generic.c new file mode 100644 index 000000000000..d13757e29716 --- /dev/null +++ b/src/audio/eq_fir/eq_fir_generic.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(NONE, FILTER) + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/fir_generic.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "eq_fir.h" + +LOG_MODULE_DECLARE(eq_fir, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_FORMAT_S16LE +void eq_fir_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *filter; + int32_t z; + int16_t *x0, *y0; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); + int nmax, n, i, j; + int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + while (remaining_samples) { + nmax = EQ_FIR_BYTES_TO_S16_SAMPLES(audio_stream_bytes_without_wrap(source, x)); + n = MIN(remaining_samples, nmax); + nmax = EQ_FIR_BYTES_TO_S16_SAMPLES(audio_stream_bytes_without_wrap(sink, y)); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + filter = &fir[j]; + for (i = 0; i < n; i += nch) { + z = fir_32x16(filter, *x0 << 16); + *y0 = sat_int16(Q_SHIFT_RND(z, 31, 15)); + x0 += nch; + y0 += nch; + } + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +void eq_fir_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *filter; + int32_t z; + int32_t *x0, *y0; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nmax, n, i, j; + int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + while (remaining_samples) { + nmax = EQ_FIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x)); + n = MIN(remaining_samples, nmax); + nmax = EQ_FIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, y)); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + filter = &fir[j]; + for (i = 0; i < n; i += nch) { + z = fir_32x16(filter, *x0 << 8); + *y0 = sat_int24(Q_SHIFT_RND(z, 31, 23)); + x0 += nch; + y0 += nch; + } + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +void eq_fir_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *filter; + int32_t *x0, *y0; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int nmax, n, i, j; + int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + while (remaining_samples) { + nmax = EQ_FIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x)); + n = MIN(remaining_samples, nmax); + nmax = EQ_FIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, y)); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + filter = &fir[j]; + for (i = 0; i < n; i += nch) { + *y0 = fir_32x16(filter, *x0); + x0 += nch; + y0 += nch; + } + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#endif /* FILTER_HIFI_NONE */ diff --git a/src/audio/eq_fir/eq_fir_hifi2ep.c b/src/audio/eq_fir/eq_fir_hifi2ep.c new file mode 100644 index 000000000000..71b40edcee32 --- /dev/null +++ b/src/audio/eq_fir/eq_fir_hifi2ep.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(2, FILTER) + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/math/fir_hifi2ep.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi2.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "eq_fir.h" + +LOG_MODULE_DECLARE(eq_fir, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_FORMAT_S32LE +/* For even frame lengths use FIR filter that processes two sequential + * sample per call. + */ +void eq_fir_2x_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *f; + 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; + int32_t *y1; + int ch; + int i; + int rshift; + int lshift; + int nch = audio_stream_get_channels(source); + int inc = nch << 1; + + for (ch = 0; ch < nch; ch++) { + /* Get FIR instance and get shifts to e.g. apply mute + * without overhead. + */ + f = &fir[ch]; + fir_get_lrshifts(f, &lshift, &rshift); + + /* Setup circular buffer for FIR input data delay */ + fir_hifiep_setup_circular(f); + + x0 = src++; + y0 = snk++; + for (i = 0; i < (frames >> 1); i++) { + x1 = x0 + nch; + y1 = y0 + nch; + fir_32x16_2x(f, *x0, *x1, y0, y1, lshift, rshift); + x0 += inc; + y0 += inc; + } + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S24LE +void eq_fir_2x_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *f; + 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; + int32_t *y1; + int32_t z0; + int32_t z1; + int ch; + int i; + int rshift; + int lshift; + int nch = audio_stream_get_channels(source); + int inc = nch << 1; + + for (ch = 0; ch < nch; ch++) { + /* Get FIR instance and get shifts to e.g. apply mute + * without overhead. + */ + f = &fir[ch]; + fir_get_lrshifts(f, &lshift, &rshift); + + /* Setup circular buffer for FIR input data delay */ + fir_hifiep_setup_circular(f); + + x0 = src++; + y0 = snk++; + for (i = 0; i < (frames >> 1); i++) { + x1 = x0 + nch; + y1 = y0 + nch; + fir_32x16_2x(f, *x0 << 8, *x1 << 8, &z0, &z1, lshift, rshift); + *y0 = sat_int24(Q_SHIFT_RND(z0, 31, 23)); + *y1 = sat_int24(Q_SHIFT_RND(z1, 31, 23)); + x0 += inc; + y0 += inc; + } + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S16LE +void eq_fir_2x_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *f; + 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; + int16_t *y1; + int32_t z0; + int32_t z1; + int ch; + int i; + int rshift; + int lshift; + int nch = audio_stream_get_channels(source); + int inc = nch << 1; + + for (ch = 0; ch < nch; ch++) { + /* Get FIR instance and get shifts to e.g. apply mute + * without overhead. + */ + f = &fir[ch]; + fir_get_lrshifts(f, &lshift, &rshift); + + /* Setup circular buffer for FIR input data delay */ + fir_hifiep_setup_circular(f); + + x0 = src++; + y0 = snk++; + for (i = 0; i < (frames >> 1); i++) { + x1 = x0 + nch; + y1 = y0 + nch; + fir_32x16_2x(f, *x0 << 16, *x1 << 16, &z0, &z1, lshift, rshift); + *y0 = sat_int16(Q_SHIFT_RND(z0, 31, 15)); + *y1 = sat_int16(Q_SHIFT_RND(z1, 31, 15)); + x0 += inc; + y0 += inc; + } + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#endif /* FIR_HIFIEP */ diff --git a/src/audio/eq_fir/eq_fir_hifi3.c b/src/audio/eq_fir/eq_fir_hifi3.c new file mode 100644 index 000000000000..0d25851ea447 --- /dev/null +++ b/src/audio/eq_fir/eq_fir_hifi3.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_MIN_HIFI(3, FILTER) + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/fir_hifi3.h> +#include <user/fir.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi3.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "eq_fir.h" + +LOG_MODULE_DECLARE(eq_fir, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_FORMAT_S32LE +/* For even frame lengths use FIR filter that processes two sequential + * sample per call. + */ +void eq_fir_2x_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *f; + ae_int32x2 d0 = 0; + ae_int32x2 d1 = 0; + 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, n, nmax; + int rshift; + int lshift; + int shift; + int nch = audio_stream_get_channels(source); + int inc_nch_s = nch * sizeof(int32_t); + int inc_2nch_s = 2 * inc_nch_s; + 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); + + 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(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 */ + +#if CONFIG_FORMAT_S24LE +void eq_fir_2x_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *f; + ae_int32x2 d0 = 0; + ae_int32x2 d1 = 0; + ae_int32 z0; + ae_int32 z1; + 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, n, nmax; + int rshift; + int lshift; + int shift; + int nch = audio_stream_get_channels(source); + int inc_nch_s = nch * sizeof(int32_t); + 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); + + 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(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); + + /* 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 */ + +#if CONFIG_FORMAT_S16LE +void eq_fir_2x_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct fir_state_32x16 *f; + ae_int16x4 d0 = AE_ZERO16(); + ae_int16x4 d1 = AE_ZERO16(); + ae_int32 z0; + ae_int32 z1; + ae_int32 x0; + ae_int32 x1; + 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, n, nmax; + int rshift; + int lshift; + int shift; + int nch = audio_stream_get_channels(source); + int inc_nch_s = nch * sizeof(int16_t); + 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); + + 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(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 */ + 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 */ + +#endif /* FIR_HIFI3 */ diff --git a/src/audio/eq_fir/eq_fir_ipc3.c b/src/audio/eq_fir/eq_fir_ipc3.c new file mode 100644 index 000000000000..ecfd873ffd7f --- /dev/null +++ b/src/audio/eq_fir/eq_fir_ipc3.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc/stream.h> +#include <sof/audio/component.h> +#include <sof/trace/trace.h> +#include <errno.h> + +#include "eq_fir.h" + +LOG_MODULE_DECLARE(eq_fir, CONFIG_SOF_LOG_LEVEL); + +int set_fir_func(struct processing_module *mod, enum sof_ipc_frame fmt) +{ + struct comp_data *cd = module_get_private_data(mod); + + switch (fmt) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S16_LE"); + set_s16_fir(cd); + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S24_4LE"); + set_s24_fir(cd); + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S32_LE"); + set_s32_fir(cd); + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(mod->dev, "invalid frame_fmt"); + return -EINVAL; + } + return 0; +} + +int eq_fir_params(struct processing_module *mod) +{ + return 0; +} + diff --git a/src/audio/eq_fir/eq_fir_ipc4.c b/src/audio/eq_fir/eq_fir_ipc4.c new file mode 100644 index 000000000000..64ec2895e0dd --- /dev/null +++ b/src/audio/eq_fir/eq_fir_ipc4.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc/stream.h> +#include <sof/audio/component.h> +#include <sof/audio/buffer.h> +#include <sof/audio/audio_stream.h> +#include <sof/list.h> +#include <sof/trace/trace.h> +#include <errno.h> + +#include "eq_fir.h" + +LOG_MODULE_DECLARE(eq_fir, CONFIG_SOF_LOG_LEVEL); + +int set_fir_func(struct processing_module *mod, enum sof_ipc_frame fmt) +{ + struct comp_data *cd = module_get_private_data(mod); + unsigned int valid_bit_depth = mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth; + + comp_dbg(mod->dev, "valid_bit_depth %d", valid_bit_depth); + switch (valid_bit_depth) { +#if CONFIG_FORMAT_S16LE + case IPC4_DEPTH_16BIT: + set_s16_fir(cd); + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case IPC4_DEPTH_24BIT: + set_s24_fir(cd); + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case IPC4_DEPTH_32BIT: + set_s32_fir(cd); + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(mod->dev, "invalid valid_bith_depth"); + return -EINVAL; + } + return 0; +} + +int eq_fir_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + /* The caller has verified, that sink and source buffers are connected */ + + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); + + sinkb = comp_dev_get_first_data_consumer(dev); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); + + return 0; +} + diff --git a/src/audio/eq_fir/fir.c b/src/audio/eq_fir/fir.c deleted file mode 100644 index 449021ffd621..000000000000 --- a/src/audio/eq_fir/fir.c +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/eq_fir/fir_config.h> - -#if FIR_GENERIC - -#include <sof/common.h> -#include <sof/audio/buffer.h> -#include <sof/audio/eq_fir/fir.h> -#include <sof/audio/format.h> -#include <user/eq.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -/* - * EQ FIR algorithm code - */ - -void fir_reset(struct fir_state_32x16 *fir) -{ - fir->rwi = 0; - fir->length = 0; - fir->out_shift = 0; - fir->coef = NULL; - /* There may need to know the beginning of dynamic allocation after - * reset so omitting setting also fir->delay to NULL. - */ -} - -int fir_delay_size(struct sof_eq_fir_coef_data *config) -{ - /* Check for sane FIR length. The generic version does not - * have other constraints. - */ - if (config->length > SOF_EQ_FIR_MAX_LENGTH || config->length < 1) - return -EINVAL; - - return config->length * sizeof(int32_t); -} - -int fir_init_coef(struct fir_state_32x16 *fir, - struct sof_eq_fir_coef_data *config) -{ - fir->rwi = 0; - fir->length = (int)config->length; - fir->taps = fir->length; /* The same for generic C version */ - fir->out_shift = (int)config->out_shift; - fir->coef = ASSUME_ALIGNED(&config->coef[0], 4); - return 0; -} - -void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) -{ - fir->delay = *data; - *data += fir->length; /* Point to next delay line start */ -} - -#if CONFIG_FORMAT_S16LE -void eq_fir_s16(struct fir_state_32x16 fir[], const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *filter; - int16_t *x; - int16_t *y; - int32_t z; - int idx; - int ch; - int i; - - for (ch = 0; ch < nch; ch++) { - filter = &fir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s16(source, idx); - y = audio_stream_write_frag_s16(sink, idx); - z = fir_32x16(filter, *x << 16); - *y = sat_int16(Q_SHIFT_RND(z, 31, 15)); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S24LE -void eq_fir_s24(struct fir_state_32x16 fir[], const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *filter; - int32_t *x; - int32_t *y; - int32_t z; - int idx; - int ch; - int i; - - for (ch = 0; ch < nch; ch++) { - filter = &fir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s32(source, idx); - y = audio_stream_write_frag_s32(sink, idx); - z = fir_32x16(filter, *x << 8); - *y = sat_int24(Q_SHIFT_RND(z, 31, 23)); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S32LE -void eq_fir_s32(struct fir_state_32x16 fir[], const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *filter; - int32_t *x; - int32_t *y; - int idx; - int ch; - int i; - - for (ch = 0; ch < nch; ch++) { - filter = &fir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s32(source, idx); - y = audio_stream_write_frag_s32(sink, idx); - *y = fir_32x16(filter, *x); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S32LE */ - -#endif diff --git a/src/audio/eq_fir/fir_hifi2ep.c b/src/audio/eq_fir/fir_hifi2ep.c deleted file mode 100644 index ab6473b319c0..000000000000 --- a/src/audio/eq_fir/fir_hifi2ep.c +++ /dev/null @@ -1,328 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -#include <sof/audio/eq_fir/fir_config.h> - -#if FIR_HIFIEP - -#include <sof/audio/buffer.h> -#include <sof/audio/eq_fir/fir_hifi2ep.h> -#include <sof/audio/format.h> -#include <user/eq.h> -#include <xtensa/config/defs.h> -#include <xtensa/tie/xt_hifi2.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -/* - * EQ FIR algorithm code - */ - -void fir_reset(struct fir_state_32x16 *fir) -{ - fir->taps = 0; - fir->length = 0; - fir->out_shift = 0; - fir->coef = NULL; - /* There may need to know the beginning of dynamic allocation after - * reset so omitting setting also fir->delay to NULL. - */ -} - -int fir_delay_size(struct sof_eq_fir_coef_data *config) -{ - /* Check FIR tap count for implementation specific constraints */ - if (config->length > SOF_EQ_FIR_MAX_LENGTH || config->length < 4) - return -EINVAL; - - if (config->length & 0x3) - return -EINVAL; - - /* The dual sample version needs one more delay entry. To preserve - * align for 64 bits need to add two. - */ - return (config->length + 2) * sizeof(int32_t); -} - -int fir_init_coef(struct fir_state_32x16 *fir, - struct sof_eq_fir_coef_data *config) -{ - /* The length is taps plus two since the filter computes two - * samples per call. Length plus one would be minimum but the add - * must be even. The even length is needed for 64 bit loads from delay - * lines with 32 bit samples. - */ - fir->taps = (int)config->length; - fir->length = fir->taps + 2; - fir->out_shift = (int)config->out_shift; - fir->coef = (ae_p16x2s *)&config->coef[0]; - return 0; -} - -void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) -{ - fir->delay = (ae_p24f *) *data; - fir->delay_end = fir->delay + fir->length; - fir->rwp = (ae_p24x2f *)(fir->delay + fir->length - 1); - *data += fir->length; /* Point to next delay line start */ -} - -void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, - int *rshift) -{ - *lshift = (fir->out_shift < 0) ? -fir->out_shift : 0; - *rshift = (fir->out_shift > 0) ? fir->out_shift : 0; -} - -#if CONFIG_FORMAT_S32LE -/* For even frame lengths use FIR filter that processes two sequential - * sample per call. - */ -void eq_fir_2x_s32_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch) -{ - struct fir_state_32x16 *f; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; - int32_t *x0; - int32_t *y0; - int32_t *x1; - int32_t *y1; - int ch; - int i; - int rshift; - int lshift; - int inc = nch << 1; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - - /* Setup circular buffer for FIR input data delay */ - fir_hifiep_setup_circular(f); - - x0 = src++; - y0 = snk++; - for (i = 0; i < (frames >> 1); i++) { - x1 = x0 + nch; - y1 = y0 + nch; - fir_32x16_2x_hifiep(f, *x0, *x1, y0, y1, - lshift, rshift); - x0 += inc; - y0 += inc; - } - } -} - -/* FIR for any number of frames */ -void eq_fir_s32_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; - int32_t *x; - int32_t *y; - int ch; - int i; - int rshift; - int lshift; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - - /* Setup circular buffer for FIR input data delay */ - fir_hifiep_setup_circular(f); - - x = src++; - y = snk++; - for (i = 0; i < frames; i++) { - fir_32x16_hifiep(f, *x, y, lshift, rshift); - x += nch; - y += nch; - } - } -} -#endif /* CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S24LE -void eq_fir_2x_s24_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; - int32_t *x0; - int32_t *y0; - int32_t *x1; - int32_t *y1; - int32_t z0; - int32_t z1; - int ch; - int i; - int rshift; - int lshift; - int inc = nch << 1; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - - /* Setup circular buffer for FIR input data delay */ - fir_hifiep_setup_circular(f); - - x0 = src++; - y0 = snk++; - for (i = 0; i < (frames >> 1); i++) { - x1 = x0 + nch; - y1 = y0 + nch; - fir_32x16_2x_hifiep(f, *x0 << 8, *x1 << 8, &z0, &z1, - lshift, rshift); - *y0 = sat_int24(Q_SHIFT_RND(z0, 31, 23)); - *y1 = sat_int24(Q_SHIFT_RND(z1, 31, 23)); - x0 += inc; - y0 += inc; - } - } -} - -/* FIR for any number of frames */ -void eq_fir_s24_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; - int32_t *x; - int32_t *y; - int32_t z; - int ch; - int i; - int rshift; - int lshift; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - - /* Setup circular buffer for FIR input data delay */ - fir_hifiep_setup_circular(f); - - x = src++; - y = snk++; - for (i = 0; i < frames; i++) { - fir_32x16_hifiep(f, *x << 8, &z, lshift, rshift); - *y = sat_int24(Q_SHIFT_RND(z, 31, 23)); - x += nch; - y += nch; - } - } -} -#endif /* CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S16LE -void eq_fir_2x_s16_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - int16_t *src = (int16_t *)source->r_ptr; - int16_t *snk = (int16_t *)sink->w_ptr; - int16_t *x0; - int16_t *y0; - int16_t *x1; - int16_t *y1; - int32_t z0; - int32_t z1; - int ch; - int i; - int rshift; - int lshift; - int inc = nch << 1; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - - /* Setup circular buffer for FIR input data delay */ - fir_hifiep_setup_circular(f); - - x0 = src++; - y0 = snk++; - for (i = 0; i < (frames >> 1); i++) { - x1 = x0 + nch; - y1 = y0 + nch; - fir_32x16_2x_hifiep(f, *x0 << 16, *x1 << 16, &z0, &z1, - lshift, rshift); - *y0 = sat_int16(Q_SHIFT_RND(z0, 31, 15)); - *y1 = sat_int16(Q_SHIFT_RND(z1, 31, 15)); - x0 += inc; - y0 += inc; - } - } -} - -/* FIR for any number of frames */ -void eq_fir_s16_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - int16_t *src = (int16_t *)source->r_ptr; - int16_t *snk = (int16_t *)sink->w_ptr; - int16_t *x; - int16_t *y; - int32_t z; - int ch; - int i; - int rshift; - int lshift; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - - /* Setup circular buffer for FIR input data delay */ - fir_hifiep_setup_circular(f); - - x = src++; - y = snk++; - for (i = 0; i < frames; i++) { - fir_32x16_hifiep(f, *x << 16, &z, lshift, rshift); - *y = sat_int16(Q_SHIFT_RND(z, 31, 15)); - x += nch; - y += nch; - } - } -} -#endif /* CONFIG_FORMAT_S16LE */ - -#endif diff --git a/src/audio/eq_fir/fir_hifi3.c b/src/audio/eq_fir/fir_hifi3.c deleted file mode 100644 index 88170ea2ce5a..000000000000 --- a/src/audio/eq_fir/fir_hifi3.c +++ /dev/null @@ -1,459 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -#include <sof/audio/eq_fir/fir_config.h> - -#if FIR_HIFI3 - -#include <sof/audio/buffer.h> -#include <sof/audio/eq_fir/fir_hifi3.h> -#include <user/eq.h> -#include <xtensa/config/defs.h> -#include <xtensa/tie/xt_hifi3.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -/* - * EQ FIR algorithm code - */ - -void fir_reset(struct fir_state_32x16 *fir) -{ - fir->taps = 0; - fir->length = 0; - fir->out_shift = 0; - fir->coef = NULL; - /* There may need to know the beginning of dynamic allocation after - * reset so omitting setting also fir->delay to NULL. - */ -} - -int fir_delay_size(struct sof_eq_fir_coef_data *config) -{ - /* Check FIR tap count for implementation specific constraints */ - if (config->length > SOF_EQ_FIR_MAX_LENGTH || config->length < 4) - return -EINVAL; - - /* The optimization requires the tap count to be multiple of four */ - if (config->length & 0x3) - return -EINVAL; - - /* The dual sample version needs one more delay entry. To preserve - * align for 64 bits need to add two. - */ - return (config->length + 2) * sizeof(int32_t); -} - -int fir_init_coef(struct fir_state_32x16 *fir, - struct sof_eq_fir_coef_data *config) -{ - /* The length is taps plus two since the filter computes two - * samples per call. Length plus one would be minimum but the add - * must be even. The even length is needed for 64 bit loads from delay - * lines with 32 bit samples. - */ - fir->taps = (int)config->length; - fir->length = fir->taps + 2; - fir->out_shift = (int)config->out_shift; - fir->coef = (ae_f16x4 *)&config->coef[0]; - return 0; -} - -void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) -{ - fir->delay = (ae_int32 *) *data; - fir->delay_end = fir->delay + fir->length; - fir->rwp = (ae_int32 *)(fir->delay + fir->length - 1); - *data += fir->length; /* Point to next delay line start */ -} - -void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, - int *rshift) -{ - *lshift = (fir->out_shift < 0) ? -fir->out_shift : 0; - *rshift = (fir->out_shift > 0) ? fir->out_shift : 0; -} - -#if CONFIG_FORMAT_S32LE -/* For even frame lengths use FIR filter that processes two sequential - * sample per call. - */ -void eq_fir_2x_s32_hifi3(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - 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 *x; - ae_int32 *y0; - ae_int32 *y1; - int ch; - int i; - int rshift; - int lshift; - int shift; - 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 */ - 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); - } - } -} - -/* FIR for any number of frames */ -void eq_fir_s32_hifi3(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - ae_int32x2 in = 0; - ae_int32 out; - ae_int32 *x; - ae_int32 *y; - ae_int32 *src = (ae_int32 *)source->r_ptr; - ae_int32 *snk = (ae_int32 *)sink->w_ptr; - int ch; - int i; - int rshift; - int lshift; - int shift; - int inc = nch * sizeof(int32_t); - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - 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_L32_XC(in, src, sizeof(int32_t)); - - /* Copy snk to y and advance snk to next channel with - * dummy load. - */ - fir_comp_setup_circular(sink); - y = snk; - AE_L32_XC(in, snk, sizeof(int32_t)); - - for (i = 0; i < frames; i++) { - /* Load input sample */ - fir_comp_setup_circular(source); - AE_L32_XC(in, x, inc); - - /* Compute FIR */ - fir_core_setup_circular(f); - fir_32x16_hifi3(f, in, &out, shift); - - /* Store output sample */ - fir_comp_setup_circular(sink); - AE_S32_L_XC((ae_int32x2)out, y, inc); - } - } -} -#endif /* CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S24LE -void eq_fir_2x_s24_hifi3(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - ae_int32x2 d0 = 0; - 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 *x; - ae_int32 *y; - int ch; - int i; - int rshift; - int lshift; - int shift; - 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 */ - 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); - d1 = AE_SRAI32R(z1, 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); - } - } -} - -void eq_fir_s24_hifi3(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - ae_int32 in; - ae_int32 out; - ae_int32x2 d = 0; - ae_int32 *x; - ae_int32 *y; - ae_int32 *src = (ae_int32 *)source->r_ptr; - ae_int32 *snk = (ae_int32 *)sink->w_ptr; - int ch; - int i; - int rshift; - int lshift; - int shift; - int inc = nch * sizeof(int32_t); - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - 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_L32_XC(d, src, sizeof(int32_t)); - - /* Copy snk to y and advance snk to next channel with - * dummy load. - */ - fir_comp_setup_circular(sink); - y = snk; - AE_L32_XC(d, snk, sizeof(int32_t)); - - for (i = 0; i < frames; i++) { - /* Load input sample and convert with shift left - * to Q1.31 compatible format. - */ - fir_comp_setup_circular(source); - AE_L32_XC(d, x, inc); - in = AE_SLAA32(d, 8); - - /* Compute FIR */ - fir_core_setup_circular(f); - fir_32x16_hifi3(f, in, &out, shift); - - /* Round to Q1.23 and store output sample */ - fir_comp_setup_circular(sink); - d = AE_SRAI32R(out, 8); - AE_S32_L_XC(d, y, inc); - } - } -} -#endif /* CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S16LE -void eq_fir_2x_s16_hifi3(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - ae_int16x4 d0 = AE_ZERO16(); - ae_int16x4 d1 = AE_ZERO16(); - ae_int32 z0; - 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 *x; - ae_int16 *y; - int ch; - int i; - int rshift; - int lshift; - int shift; - 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 */ - 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); - - /* 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); - } - } -} - -void eq_fir_s16_hifi3(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch) -{ - struct fir_state_32x16 *f; - ae_f16x4 d = AE_ZERO16(); - ae_int32 in; - ae_int32 out; - ae_int16 *x; - ae_int16 *y; - ae_int16 *src = (ae_int16 *)source->r_ptr; - ae_int16 *snk = (ae_int16 *)sink->w_ptr; - int ch; - int i; - int rshift; - int lshift; - int shift; - int inc = nch * sizeof(int16_t); - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts to e.g. apply mute - * without overhead. - */ - 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(d, src, sizeof(int16_t)); - - /* Copy snk to y and advance snk to next channel with - * dummy load. - */ - fir_comp_setup_circular(sink); - y = snk; - AE_L16_XC(d, snk, sizeof(int16_t)); - - for (i = 0; i < frames; i++) { - /* Load input sample and convert to Q1.31 */ - fir_comp_setup_circular(source); - AE_L16_XC(d, x, inc); - in = AE_CVT32X2F16_32(d); - - /* Compute FIR */ - fir_core_setup_circular(f); - fir_32x16_hifi3(f, in, &out, shift); - - /* Round to Q1.15 and store output sample */ - fir_comp_setup_circular(sink); - d = AE_ROUND16X4F32SSYM(out, out); - AE_S16_0_XC(d, y, inc); - } - } -} -#endif /* CONFIG_FORMAT_S16LE */ -#endif diff --git a/src/audio/eq_fir/llext/CMakeLists.txt b/src/audio/eq_fir/llext/CMakeLists.txt new file mode 100644 index 000000000000..df4b3a16c89e --- /dev/null +++ b/src/audio/eq_fir/llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("eq_fir" + SOURCES ../eq_fir_hifi3.c + ../eq_fir_hifi2ep.c + ../eq_fir_generic.c + ../eq_fir.c + ../eq_fir_ipc4.c + LIB openmodules +) diff --git a/src/audio/eq_fir/llext/llext.toml.h b/src/audio/eq_fir/llext/llext.toml.h new file mode 100644 index 000000000000..4a73c827c860 --- /dev/null +++ b/src/audio/eq_fir/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../eq_fir.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/eq_iir/CMakeLists.txt b/src/audio/eq_iir/CMakeLists.txt index 04f5c4262ef2..33c50df17df8 100644 --- a/src/audio/eq_iir/CMakeLists.txt +++ b/src/audio/eq_iir/CMakeLists.txt @@ -1,3 +1,18 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof eq_iir.c iir.c iir_generic.c iir_hifi3.c) +if(CONFIG_COMP_IIR STREQUAL "m" AND DEFINED CONFIG_LLEXT) + + add_subdirectory(llext ${PROJECT_BINARY_DIR}/eq_iir_llext) + add_dependencies(app eq_iir) + +else() + + add_local_sources(sof eq_iir.c eq_iir_generic.c) + + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof eq_iir_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof eq_iir_ipc4.c) + endif() + +endif() diff --git a/src/audio/eq_iir/Kconfig b/src/audio/eq_iir/Kconfig new file mode 100644 index 000000000000..11433d27cfb3 --- /dev/null +++ b/src/audio/eq_iir/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_IIR + tristate "IIR component" + select COMP_BLOB + default m if LIBRARY_DEFAULT_MODULAR + default y + depends on COMP_MODULE_ADAPTER + select MATH_IIR_DF1 + help + Select for IIR component diff --git a/src/audio/eq_iir/README.md b/src/audio/eq_iir/README.md new file mode 100644 index 000000000000..6af07ceae354 --- /dev/null +++ b/src/audio/eq_iir/README.md @@ -0,0 +1,24 @@ +# IIR Equalizer Architecture + +This directory contains the Infinite Impulse Response (IIR) EQ component. + +## Overview + +IIR equalizers provide frequency shaping (like parametric EQs, shelves, high/low passes) typically using arrays of biquad filters. + +## Architecture Diagram + +```mermaid +graph LR + In[Input Frame] --> IIR[Biquad Cascade] + Coeffs[(Biquad Coefficients)] --> IIR + IIR --> Out[Output Frame] +``` + +## Configuration and Scripts + +- **Kconfig**: Activates the IIR component (`COMP_IIR`), selecting `MATH_IIR_DF1` and depending on the module adapter. +- **CMakeLists.txt**: Compiles generic logic (`eq_iir_generic.c`) and IPC-specific files depending on the Zephyr IPC configuration. +- **eq_iir.toml**: Topology parameters tailored by platform. Defines custom `mod_cfg` arrays with varying constraints based on `CONFIG_METEORLAKE` versus `CONFIG_LUNARLAKE` and ACE SOCs. +- **Topology (.conf)**: Dictated by `tools/topology/topology2/include/components/eqiir.conf`, representing an `effect` widget object with UUID `e6:c0:50:51:f9:27:c8:4e:83:51:c7:05:b6:42:d1:2f`. +- **MATLAB Tuning (`tune/`)**: `sof_example_iir_eq.m` and associated scripts can design parametric biquad presets (e.g., loudness, bass boost, bandpass, flat). These scripts compute the IIR coefficients, calculate precise scaling values, quantize mathematically, and bundle the permutations into binaries and configuration fragments suitable for SOF IPC messages. diff --git a/src/audio/eq_iir/eq_iir.c b/src/audio/eq_iir/eq_iir.c index 3dcb0e3bff74..016c2c8caf82 100644 --- a/src/audio/eq_iir/eq_iir.c +++ b/src/audio/eq_iir/eq_iir.c @@ -1,26 +1,28 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2017 Intel Corporation. All rights reserved. +// Copyright(c) 2017-2022 Intel Corporation. All rights reserved. // // Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> // Liam Girdwood <liam.r.girdwood@linux.intel.com> // Keyon Jie <yang.jie@linux.intel.com> +#include "eq_iir.h" #include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/data_blob.h> #include <sof/audio/buffer.h> -#include <sof/audio/eq_iir/eq_iir.h> -#include <sof/audio/eq_iir/iir.h> #include <sof/audio/format.h> #include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> #include <sof/lib/uuid.h> #include <sof/list.h> #include <sof/platform.h> -#include <sof/string.h> +#include <rtos/string.h> +#include <sof/ut.h> #include <sof/trace/trace.h> #include <ipc/control.h> #include <ipc/stream.h> @@ -31,938 +33,219 @@ #include <stddef.h> #include <stdint.h> -static const struct comp_driver comp_eq_iir; - -/* 5150c0e6-27f9-4ec8-8351-c705b642d12f */ -DECLARE_SOF_UUID("eq-iir", eq_iir_uuid, 0x5150c0e6, 0x27f9, 0x4ec8, - 0x83, 0x51, 0xc7, 0x05, 0xb6, 0x42, 0xd1, 0x2f); - -/* IIR component private data */ -struct comp_data { - struct iir_state_df2t iir[PLATFORM_MAX_CHANNELS]; /**< filters state */ - struct sof_eq_iir_config *config; /**< pointer to setup blob */ - struct sof_eq_iir_config *config_new; /**< pointer to new setup */ - enum sof_ipc_frame source_format; /**< source frame format */ - enum sof_ipc_frame sink_format; /**< sink frame format */ - int64_t *iir_delay; /**< pointer to allocated RAM */ - size_t iir_delay_size; /**< allocated size */ - eq_iir_func eq_iir_func; /**< processing function */ -}; +LOG_MODULE_REGISTER(eq_iir, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(eq_iir); -#if CONFIG_FORMAT_S16LE /* - * EQ IIR algorithm code + * End of EQ setup code. Next the standard component methods. */ - -static void eq_iir_s16_default(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) - -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct iir_state_df2t *filter; - int16_t *x; - int16_t *y; - int32_t z; - int ch; - int i; - int idx; - int nch = source->channels; - - for (ch = 0; ch < nch; ch++) { - filter = &cd->iir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s16(source, idx); - y = audio_stream_write_frag_s16(sink, idx); - z = iir_df2t(filter, *x << 16); - *y = sat_int16(Q_SHIFT_RND(z, 31, 15)); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S24LE -static void eq_iir_s24_default(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) - -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct iir_state_df2t *filter; - int32_t *x; - int32_t *y; - int32_t z; - int idx; - int ch; - int i; - int nch = source->channels; - - for (ch = 0; ch < nch; ch++) { - filter = &cd->iir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s32(source, idx); - y = audio_stream_write_frag_s32(sink, idx); - z = iir_df2t(filter, *x << 8); - *y = sat_int24(Q_SHIFT_RND(z, 31, 23)); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S32LE -static void eq_iir_s32_default(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) - -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct iir_state_df2t *filter; - int32_t *x; - int32_t *y; - int idx; - int ch; - int i; - int nch = source->channels; - - for (ch = 0; ch < nch; ch++) { - filter = &cd->iir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s32(source, idx); - y = audio_stream_write_frag_s32(sink, idx); - *y = iir_df2t(filter, *x); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S16LE -static void eq_iir_s32_16_default(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) - -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct iir_state_df2t *filter; - int32_t *x; - int16_t *y; - int32_t z; - int idx; - int ch; - int i; - int nch = source->channels; - - for (ch = 0; ch < nch; ch++) { - filter = &cd->iir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s32(source, idx); - y = audio_stream_write_frag_s16(sink, idx); - z = iir_df2t(filter, *x); - *y = sat_int16(Q_SHIFT_RND(z, 31, 15)); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S24LE -static void eq_iir_s32_24_default(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) - -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct iir_state_df2t *filter; - int32_t *x; - int32_t *y; - int32_t z; - int idx; - int ch; - int i; - int nch = source->channels; - - for (ch = 0; ch < nch; ch++) { - filter = &cd->iir[ch]; - idx = ch; - for (i = 0; i < frames; i++) { - x = audio_stream_read_frag_s32(source, idx); - y = audio_stream_write_frag_s32(sink, idx); - z = iir_df2t(filter, *x); - *y = sat_int24(Q_SHIFT_RND(z, 31, 23)); - idx += nch; - } - } -} -#endif /* CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S16LE -static void eq_iir_s16_pass(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) -{ - audio_stream_copy_s16(source, 0, sink, 0, frames * source->channels); -} -#endif /* CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE -static void eq_iir_s32_pass(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) -{ - audio_stream_copy_s32(source, 0, sink, 0, frames * source->channels); -} -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE -static void eq_iir_s32_s16_pass(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) -{ - int32_t *x; - int16_t *y; - int i; - int n = frames * source->channels; - - for (i = 0; i < n; i++) { - x = audio_stream_read_frag_s32(source, i); - y = audio_stream_write_frag_s16(sink, i); - *y = sat_int16(Q_SHIFT_RND(*x, 31, 15)); - } -} -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE -static void eq_iir_s32_s24_pass(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames) +static int eq_iir_init(struct processing_module *mod) { - int32_t *x; - int32_t *y; + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct comp_data *cd; int i; - int n = frames * source->channels; - - for (i = 0; i < n; i++) { - x = audio_stream_read_frag_s32(source, i); - y = audio_stream_write_frag_s16(sink, i); - *y = sat_int24(Q_SHIFT_RND(*x, 31, 23)); - } -} -#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ - -const struct eq_iir_func_map fm_configured[] = { -#if CONFIG_FORMAT_S16LE - {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s16_default}, -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE - {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, NULL}, - {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, NULL}, - -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE - {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, NULL}, - {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s32_16_default}, -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S24LE - {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s24_default}, -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE - {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, NULL}, - {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s32_24_default}, -#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S32LE - {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, eq_iir_s32_default}, -#endif /* CONFIG_FORMAT_S32LE */ -}; -const struct eq_iir_func_map fm_passthrough[] = { -#if CONFIG_FORMAT_S16LE - {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s16_pass}, -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE - {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, NULL}, - {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, NULL}, - -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE*/ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE - {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, NULL}, - {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s32_s16_pass}, -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE*/ -#if CONFIG_FORMAT_S24LE - {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s32_pass}, -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE - {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, NULL}, - {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s32_s24_pass}, -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, eq_iir_s32_pass}, -#endif /* CONFIG_FORMAT_S32LE */ -}; + comp_info(dev, "entry"); -static eq_iir_func eq_iir_find_func(enum sof_ipc_frame source_format, - enum sof_ipc_frame sink_format, - const struct eq_iir_func_map *map, - int n) -{ - int i; + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; - /* Find suitable processing function from map. */ - for (i = 0; i < n; i++) { - if ((uint8_t)source_format != map[i].source) - continue; - if ((uint8_t)sink_format != map[i].sink) - continue; + md->private = cd; - return map[i].func; + /* component model data handler */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + mod_free(mod, cd); + return -ENOMEM; } - return NULL; -} - -static void eq_iir_free_parameters(struct sof_eq_iir_config **config) -{ - rfree(*config); - *config = NULL; -} - -static void eq_iir_free_delaylines(struct comp_data *cd) -{ - struct iir_state_df2t *iir = cd->iir; - int i = 0; - - /* Free the common buffer for all EQs and point then - * each IIR channel delay line to NULL. - */ - rfree(cd->iir_delay); - cd->iir_delay = NULL; - cd->iir_delay_size = 0; for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - iir[i].delay = NULL; -} + iir_reset_df1(&cd->iir[i]); -static int eq_iir_init_coef(struct sof_eq_iir_config *config, - struct iir_state_df2t *iir, int nch) -{ - struct sof_eq_iir_header_df2t *lookup[SOF_EQ_IIR_MAX_RESPONSES]; - struct sof_eq_iir_header_df2t *eq; - int32_t *assign_response; - int32_t *coef_data; - int size_sum = 0; - int resp = 0; - int i; - int j; - int s; - - comp_cl_info(&comp_eq_iir, "eq_iir_init_coef(), response assign for %u channels, %u responses", - config->channels_in_config, - config->number_of_responses); - - /* Sanity checks */ - if (nch > PLATFORM_MAX_CHANNELS || - config->channels_in_config > PLATFORM_MAX_CHANNELS || - !config->channels_in_config) { - comp_cl_err(&comp_eq_iir, "eq_iir_init_coef(), invalid channels count"); - return -EINVAL; - } - if (config->number_of_responses > SOF_EQ_IIR_MAX_RESPONSES) { - comp_cl_err(&comp_eq_iir, "eq_iir_init_coef(), # of resp exceeds max"); - return -EINVAL; - } - - /* Collect index of response start positions in all_coefficients[] */ - j = 0; - assign_response = ASSUME_ALIGNED(&config->data[0], 4); - coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config], - 4); - for (i = 0; i < SOF_EQ_IIR_MAX_RESPONSES; i++) { - if (i < config->number_of_responses) { - eq = (struct sof_eq_iir_header_df2t *)&coef_data[j]; - lookup[i] = eq; - j += SOF_EQ_IIR_NHEADER_DF2T - + SOF_EQ_IIR_NBIQUAD_DF2T * eq->num_sections; - } else { - lookup[i] = NULL; - } - } - - /* Initialize 1st phase */ - for (i = 0; i < nch; i++) { - /* Check for not reading past blob response to channel assign - * map. The previous channel response is assigned for any - * additional channels in the stream. It allows to use single - * channel configuration to setup multi channel equalization - * with the same response. - */ - if (i < config->channels_in_config) - resp = assign_response[i]; - - if (resp < 0) { - /* Initialize EQ channel to bypass and continue with - * next channel response. - */ - comp_cl_err(&comp_eq_iir, "eq_iir_init_coef(), ch %d is set to bypass", - i); - iir_reset_df2t(&iir[i]); - continue; - } - - if (resp >= config->number_of_responses) { - comp_cl_info(&comp_eq_iir, "eq_iir_init_coef(), requested response %d exceeds defined", - resp); - return -EINVAL; - } - - /* Initialize EQ coefficients */ - eq = lookup[resp]; - s = iir_delay_size_df2t(eq); - if (s > 0) { - size_sum += s; - } else { - comp_cl_info(&comp_eq_iir, "eq_iir_init_coef(), sections count %d exceeds max", - eq->num_sections); - return -EINVAL; - } - - iir_init_coef_df2t(&iir[i], eq); - comp_cl_info(&comp_eq_iir, "eq_iir_init_coef(), ch %d is set to response %d", - i, resp); - } - - return size_sum; -} - -static void eq_iir_init_delay(struct iir_state_df2t *iir, - int64_t *delay_start, int nch) -{ - int64_t *delay = delay_start; - int i; - - /* Initialize second phase to set EQ delay lines pointers. A - * bypass mode filter is indicated by biquads count of zero. - */ - for (i = 0; i < nch; i++) { - if (iir[i].biquads > 0) - iir_init_delay_df2t(&iir[i], &delay); - } + return 0; } -static int eq_iir_setup(struct comp_data *cd, int nch) +static int eq_iir_free(struct processing_module *mod) { - int delay_size; - - /* Free existing IIR channels data if it was allocated */ - eq_iir_free_delaylines(cd); - - /* Set coefficients for each channel EQ from coefficient blob */ - delay_size = eq_iir_init_coef(cd->config, cd->iir, nch); - if (delay_size < 0) - return delay_size; /* Contains error code */ - - /* If all channels were set to bypass there's no need to - * allocate delay. Just return with success. - */ - if (!delay_size) - return 0; - - /* Allocate all IIR channels data in a big chunk and clear it */ - cd->iir_delay = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - delay_size); - if (!cd->iir_delay) { - comp_cl_err(&comp_eq_iir, "eq_iir_setup(), delay allocation fail"); - return -ENOMEM; - } + struct comp_data *cd = module_get_private_data(mod); - memset(cd->iir_delay, 0, delay_size); - cd->iir_delay_size = delay_size; + eq_iir_free_delaylines(mod); + mod_data_blob_handler_free(mod, cd->model_handler); - /* Assign delay line to each channel EQ */ - eq_iir_init_delay(cd->iir, cd->iir_delay, nch); + mod_free(mod, cd); return 0; } -/* - * End of EQ setup code. Next the standard component methods. - */ -static struct comp_dev *eq_iir_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) +/* used to pass standard and bespoke commands (with data) to component */ +static int eq_iir_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; - struct comp_data *cd; - struct sof_ipc_comp_process *iir; - struct sof_ipc_comp_process *ipc_iir = - (struct sof_ipc_comp_process *)comp; - size_t bs = ipc_iir->size; - int i; - int ret; - - comp_cl_info(&comp_eq_iir, "eq_iir_new()"); - - /* Check first before proceeding with dev and cd that coefficients - * blob size is sane. - */ - if (bs > SOF_EQ_IIR_MAX_SIZE) { - comp_cl_err(&comp_eq_iir, "eq_iir_new(), coefficients blob size %u exceeds maximum", - bs); - return NULL; - } + struct comp_data *cd = module_get_private_data(mod); - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_process)); - if (!dev) - return NULL; - dev->drv = drv; + comp_info(mod->dev, "entry"); - dev->size = COMP_SIZE(struct sof_ipc_comp_process); - - iir = COMP_GET_IPC(dev, sof_ipc_comp_process); - ret = memcpy_s(iir, sizeof(*iir), ipc_iir, - sizeof(struct sof_ipc_comp_process)); - assert(!ret); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); - - cd->eq_iir_func = NULL; - cd->iir_delay = NULL; - cd->iir_delay_size = 0; - cd->config = NULL; - cd->config_new = NULL; - - /* Allocate and make a copy of the coefficients blob and reset IIR. If - * the EQ is configured later in run-time the size is zero. - */ - if (bs) { - cd->config = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - bs); - if (!cd->config) { - rfree(dev); - rfree(cd); - return NULL; - } - - ret = memcpy_s(cd->config, bs, ipc_iir->data, bs); - assert(!ret); - } - - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - iir_reset_df2t(&cd->iir[i]); - - dev->state = COMP_STATE_READY; - return dev; + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); } -static void eq_iir_free(struct comp_dev *dev) +static int eq_iir_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) { - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "eq_iir_free()"); + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_data *cd = module_get_private_data(mod); - eq_iir_free_delaylines(cd); - eq_iir_free_parameters(&cd->config); - eq_iir_free_parameters(&cd->config_new); + comp_info(mod->dev, "entry"); - rfree(cd); - rfree(dev); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); } -static int eq_iir_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) +static int eq_iir_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 comp_buffer *sourceb; - struct comp_buffer *sinkb; - uint32_t buffer_flag; + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + uint32_t frame_count = input_buffers[0].size; int ret; - comp_dbg(dev, "eq_iir_verify_params()"); - - /* EQ component 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); - - /* we check whether we can support frame_fmt conversion (whether we have - * such conversion function) due to source and sink buffer frame_fmt's. - * If not, we will overwrite sink (playback) and source (capture) with - * pcm frame_fmt and will not make any conversion (sink and source - * frame_fmt will be equal). - */ - buffer_flag = eq_iir_find_func(sourceb->stream.frame_fmt, - sinkb->stream.frame_fmt, fm_configured, - ARRAY_SIZE(fm_configured)) ? - BUFF_PARAMS_FRAME_FMT : 0; - - ret = comp_verify_params(dev, buffer_flag, params); - if (ret < 0) { - comp_err(dev, "eq_iir_verify_params() error: comp_verify_params() failed."); - return ret; + /* 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, audio_stream_get_frm_fmt(source), + audio_stream_get_frm_fmt(sink), + audio_stream_get_channels(source)); + if (ret) + return ret; } - return 0; -} - -/* set component audio stream parameters */ -static int eq_iir_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int err; - - comp_info(dev, "eq_iir_params()"); - - err = eq_iir_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "eq_iir_params(): pcm params verification failed."); - return -EINVAL; + if (frame_count) { + cd->eq_iir_func(mod, &input_buffers[0], &output_buffers[0], frame_count); + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frame_count); } - - /* All configuration work is postponed to prepare(). */ return 0; } -static int iir_cmd_get_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int max_size) +/** + * \brief Set EQ IIR frames alignment limit. + * \param[in,out] source Structure pointer of source. + * \param[in,out] sink Structure pointer of sink. + */ +static void eq_iir_set_alignment(struct audio_stream *source, + struct audio_stream *sink) { - struct comp_data *cd = comp_get_drvdata(dev); - - size_t bs; - int ret = 0; + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; + const uint32_t frame_align_req = 2; - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "iir_cmd_get_data(), SOF_CTRL_CMD_BINARY"); - - /* Copy back to user space */ - if (cd->config) { - bs = cd->config->size; - comp_info(dev, "iir_cmd_set_data(), size %u", - bs); - if (bs > SOF_EQ_IIR_MAX_SIZE || bs == 0 || - bs > max_size) - return -EINVAL; - ret = memcpy_s(cdata->data->data, - ((struct sof_abi_hdr *) - (cdata->data))->size, cd->config, bs); - assert(!ret); - - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = bs; - } else { - comp_err(dev, "iir_cmd_get_data(), no config"); - ret = -EINVAL; - } - break; - default: - comp_err(dev, "iir_cmd_get_data(), invalid command"); - ret = -EINVAL; - break; - } - return ret; + audio_stream_set_align(byte_align, frame_align_req, source); + audio_stream_set_align(byte_align, frame_align_req, sink); } -static int iir_cmd_set_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) +static int eq_iir_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_eq_iir_config *request; - size_t bs; + struct comp_data *cd = module_get_private_data(mod); + struct comp_buffer *sourceb, *sinkb; + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame source_format; + enum sof_ipc_frame sink_format; + size_t data_size; + int channels; int ret = 0; - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - comp_info(dev, "iir_cmd_set_data(), SOF_CTRL_CMD_BINARY"); - - /* Find size from header */ - request = (struct sof_eq_iir_config *)cdata->data->data; - bs = request->size; - if (bs > SOF_EQ_IIR_MAX_SIZE || bs == 0) { - comp_err(dev, "iir_cmd_set_data(), size %d is invalid", - bs); - return -EINVAL; - } - - /* Check that there is no work-in-progress previous request */ - if (cd->config_new) { - comp_err(dev, "iir_cmd_set_data(), busy with previous"); - return -EBUSY; - } - - /* Allocate and make a copy of the blob and setup IIR */ - cd->config_new = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, - SOF_MEM_CAPS_RAM, bs); - if (!cd->config_new) { - comp_err(dev, "iir_cmd_set_data(), alloc fail"); - return -EINVAL; - } - - /* Copy the configuration. If the component state is ready - * the EQ will initialize in prepare(). - */ - ret = memcpy_s(cd->config_new, bs, cdata->data->data, bs); - assert(!ret); - - /* If component state is READY we can omit old configuration - * immediately. When in playback/capture the new configuration - * presence is checked in copy(). - */ - if (dev->state == COMP_STATE_READY) - eq_iir_free_parameters(&cd->config); - - /* If there is no existing configuration the received can - * be set to current immediately. It will be applied in - * prepare() when streaming starts. - */ - if (!cd->config) { - cd->config = cd->config_new; - cd->config_new = NULL; - } - - break; - default: - comp_err(dev, "iir_cmd_set_data(), invalid command"); - ret = -EINVAL; - break; - } - - return ret; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int eq_iir_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = data; - int ret = 0; + comp_dbg(dev, "entry"); - comp_info(dev, "eq_iir_cmd()"); - - switch (cmd) { - case COMP_CMD_SET_DATA: - ret = iir_cmd_set_data(dev, cdata); - break; - case COMP_CMD_GET_DATA: - ret = iir_cmd_get_data(dev, cdata, max_data_size); - break; - default: - comp_err(dev, "eq_iir_cmd(), invalid command"); - ret = -EINVAL; + /* EQ component will only ever have 1 source and 1 sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; } - return ret; -} - -static int eq_iir_trigger(struct comp_dev *dev, int cmd) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "eq_iir_trigger()"); - - if (cmd == COMP_TRIGGER_START || cmd == COMP_TRIGGER_RELEASE) - assert(cd->eq_iir_func); - - return comp_set_state(dev, cmd); -} - -static void eq_iir_process(struct comp_dev *dev, struct comp_buffer *source, - struct comp_buffer *sink, int frames, - uint32_t source_bytes, uint32_t sink_bytes) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - buffer_invalidate(source, source_bytes); - - cd->eq_iir_func(dev, &source->stream, &sink->stream, frames); + ret = eq_iir_prepare_sub(mod); + if (ret < 0) + return ret; - buffer_writeback(sink, sink_bytes); + eq_iir_set_alignment(&sourceb->stream, &sinkb->stream); - /* calc new free and available */ - comp_update_buffer_consume(source, source_bytes); - comp_update_buffer_produce(sink, sink_bytes); -} + /* get source and sink data format */ + channels = audio_stream_get_channels(&sinkb->stream); + source_format = audio_stream_get_frm_fmt(&sourceb->stream); + sink_format = audio_stream_get_frm_fmt(&sinkb->stream); -/* copy and process stream data from source to sink buffers */ -static int eq_iir_copy(struct comp_dev *dev) -{ - struct comp_copy_limits cl; - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sourceb; - struct comp_buffer *sinkb; - int ret; - uint32_t flags = 0; + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); - comp_dbg(dev, "eq_iir_copy()"); + /* Initialize EQ */ + comp_info(dev, "source_format=%d, sink_format=%d", + source_format, sink_format); - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); + eq_iir_set_passthrough_func(cd, source_format, sink_format); - /* Check for changed configuration */ - if (cd->config_new) { - eq_iir_free_parameters(&cd->config); - cd->config = cd->config_new; - cd->config_new = NULL; - ret = eq_iir_setup(cd, sourceb->stream.channels); - if (ret < 0) { - comp_err(dev, "eq_iir_copy(), failed IIR setup"); + /* Initialize EQ */ + if (cd->config && data_size > 0) { + ret = eq_iir_new_blob(mod, source_format, sink_format, channels); + if (ret) return ret; - } } - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - buffer_lock(sourceb, &flags); - buffer_lock(sinkb, &flags); - - /* Get source, sink, number of frames etc. to process. */ - comp_get_copy_limits(sourceb, sinkb, &cl); - - buffer_unlock(sinkb, flags); - buffer_unlock(sourceb, flags); - - /* Run EQ function */ - eq_iir_process(dev, sourceb, sinkb, cl.frames, cl.source_bytes, - cl.sink_bytes); - - return 0; -} - -static int eq_iir_prepare(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *sourceb; - struct comp_buffer *sinkb; - uint32_t sink_period_bytes; - int ret; - - comp_info(dev, "eq_iir_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; - - /* EQ component 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); - - /* get source data format */ - cd->source_format = sourceb->stream.frame_fmt; - - /* get sink data format and period bytes */ - cd->sink_format = sinkb->stream.frame_fmt; - sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, - dev->frames); - - if (sinkb->stream.size < config->periods_sink * sink_period_bytes) { - comp_err(dev, "eq_iir_prepare(), sink buffer size %d is insufficient", - sinkb->stream.size); - ret = -ENOMEM; - goto err; - } - - /* Initialize EQ */ - comp_info(dev, "eq_iir_prepare(), source_format=%d, sink_format=%d", - cd->source_format, cd->sink_format); - if (cd->config) { - ret = eq_iir_setup(cd, sourceb->stream.channels); - if (ret < 0) { - comp_err(dev, "eq_iir_prepare(), setup failed."); - goto err; - } - cd->eq_iir_func = eq_iir_find_func(cd->source_format, - cd->sink_format, - fm_configured, - ARRAY_SIZE(fm_configured)); - if (!cd->eq_iir_func) { - comp_err(dev, "eq_iir_prepare(), No proc func"); - ret = -EINVAL; - goto err; - } - comp_info(dev, "eq_iir_prepare(), IIR is configured."); - } else { - cd->eq_iir_func = eq_iir_find_func(cd->source_format, - cd->sink_format, - fm_passthrough, - ARRAY_SIZE(fm_passthrough)); - if (!cd->eq_iir_func) { - comp_err(dev, "eq_iir_prepare(), No pass func"); - ret = -EINVAL; - goto err; - } - comp_info(dev, "eq_iir_prepare(), pass-through mode."); + if (!cd->eq_iir_func) { + comp_err(dev, "No processing function found"); + ret = -EINVAL; } - return 0; -err: - comp_set_state(dev, COMP_TRIGGER_RESET); return ret; } -static int eq_iir_reset(struct comp_dev *dev) +static int eq_iir_reset(struct processing_module *mod) { + struct comp_data *cd = module_get_private_data(mod); int i; - struct comp_data *cd = comp_get_drvdata(dev); - comp_info(dev, "eq_iir_reset()"); - - eq_iir_free_delaylines(cd); + eq_iir_free_delaylines(mod); cd->eq_iir_func = NULL; for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - iir_reset_df2t(&cd->iir[i]); + iir_reset_df1(&cd->iir[i]); - comp_set_state(dev, COMP_TRIGGER_RESET); return 0; } -static const struct comp_driver comp_eq_iir = { - .type = SOF_COMP_EQ_IIR, - .uid = SOF_UUID(eq_iir_uuid), - .ops = { - .new = eq_iir_new, - .free = eq_iir_free, - .params = eq_iir_params, - .cmd = eq_iir_cmd, - .trigger = eq_iir_trigger, - .copy = eq_iir_copy, - .prepare = eq_iir_prepare, - .reset = eq_iir_reset, - }, +static const struct module_interface eq_iir_interface = { + .init = eq_iir_init, + .prepare = eq_iir_prepare, + .process_audio_stream = eq_iir_process, + .set_configuration = eq_iir_set_config, + .get_configuration = eq_iir_get_config, + .reset = eq_iir_reset, + .free = eq_iir_free }; -static SHARED_DATA struct comp_driver_info comp_eq_iir_info = { - .drv = &comp_eq_iir, -}; +#if CONFIG_COMP_IIR_MODULE +/* modular: llext dynamic link */ -static void sys_comp_eq_iir_init(void) -{ - comp_register(platform_shared_get(&comp_eq_iir_info, - sizeof(comp_eq_iir_info))); -} +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("EQIIR", &eq_iir_interface, 1, SOF_REG_UUID(eq_iir), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(eq_iir_tr, SOF_UUID(eq_iir_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(eq_iir_interface, eq_iir_uuid, eq_iir_tr); +SOF_MODULE_INIT(eq_iir, sys_comp_module_eq_iir_interface_init); -DECLARE_MODULE(sys_comp_eq_iir_init); +#endif diff --git a/src/audio/eq_iir/eq_iir.h b/src/audio/eq_iir/eq_iir.h new file mode 100644 index 000000000000..12d888d66594 --- /dev/null +++ b/src/audio/eq_iir/eq_iir.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_EQ_IIR_EQ_IIR_H__ +#define __SOF_AUDIO_EQ_IIR_EQ_IIR_H__ + +#include <stdint.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/iir_df2t.h> +#include <sof/math/iir_df1.h> + +/** \brief Macros to convert without division bytes count to samples count */ +#define EQ_IIR_BYTES_TO_S16_SAMPLES(b) ((b) >> 1) +#define EQ_IIR_BYTES_TO_S32_SAMPLES(b) ((b) >> 2) + +struct audio_stream; +struct comp_dev; + +/** \brief Type definition for processing function select return value. */ +typedef void (*eq_iir_func)(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames); + +/** \brief IIR EQ processing functions map item. */ +struct eq_iir_func_map { + uint8_t source; /**< source frame format */ + uint8_t sink; /**< sink frame format */ + eq_iir_func func; /**< processing function */ +}; + +/* IIR component private data */ +struct comp_data { + struct iir_state_df1 iir[PLATFORM_MAX_CHANNELS]; /**< filters state */ + struct comp_data_blob_handler *model_handler; + struct sof_eq_iir_config *config; + int32_t *iir_delay; /**< pointer to allocated RAM */ + size_t iir_delay_size; /**< allocated size */ + eq_iir_func eq_iir_func; /**< processing function */ +}; + +#ifdef UNIT_TEST +void sys_comp_module_eq_iir_interface_init(void); +#endif + +void eq_iir_s16_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames); + +void eq_iir_s24_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames); + +void eq_iir_s32_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames); + +int eq_iir_new_blob(struct processing_module *mod, enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format, int channels); + +void eq_iir_set_passthrough_func(struct comp_data *cd, + enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format); + +int eq_iir_prepare_sub(struct processing_module *mod); + +void eq_iir_pass(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames); + +int eq_iir_setup(struct processing_module *mod, int nch); + +void eq_iir_free_delaylines(struct processing_module *mod); +#endif /* __SOF_AUDIO_EQ_IIR_EQ_IIR_H__ */ diff --git a/src/audio/eq_iir/eq_iir.toml b/src/audio/eq_iir/eq_iir.toml new file mode 100644 index 000000000000..a9933bffc9fb --- /dev/null +++ b/src/audio/eq_iir/eq_iir.toml @@ -0,0 +1,31 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # eq iir module config + [[module.entry]] + name = "EQIIR" + uuid = UUIDREG_STR_EQ_IIR + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 1000, 0, + 0, 0, 0, 0, 4096, 20663000, 768, 768, 0, 20663, 0, + 0, 0, 0, 0, 4096, 11357000, 384, 384, 0, 11357, 0] +#elif defined(CONFIG_LUNARLAKE) || defined(CONFIG_SOC_ACE30) || \ + defined(CONFIG_SOC_ACE40) + mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 0, 0] +#endif + + index = __COUNTER__ diff --git a/src/audio/eq_iir/eq_iir_generic.c b/src/audio/eq_iir/eq_iir_generic.c new file mode 100644 index 000000000000..fd3485a28eca --- /dev/null +++ b/src/audio/eq_iir/eq_iir_generic.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017-2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include "eq_iir.h" +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/iir_df1.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/eq.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(eq_iir, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_FORMAT_S16LE +void eq_iir_s16_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct iir_state_df1 *filter; + int16_t *x0; + int16_t *y0; + int16_t *x; + int16_t *y; + int nmax; + int n1; + int n2; + int i; + int j; + int n; + const int nch = audio_stream_get_channels(source); + const int samples = frames * nch; + int processed = 0; + + 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; + n2 = audio_stream_bytes_without_wrap(sink, y) >> 1; + n = MIN(n1, n2); + n = MIN(n, nmax); + for (i = 0; i < nch; i++) { + x0 = x + i; + y0 = y + i; + filter = &cd->iir[i]; + for (j = 0; j < n; j += nch) { + *y0 = iir_df1_s16(filter, *x0); + x0 += nch; + y0 += nch; + } + } + processed += n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + +void eq_iir_s24_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct iir_state_df1 *filter; + int32_t *x0; + int32_t *y0; + int32_t *x; + int32_t *y; + int nmax; + int n1; + int n2; + int i; + int j; + int n; + const int nch = audio_stream_get_channels(source); + const int samples = frames * nch; + int processed = 0; + + 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; + n2 = audio_stream_bytes_without_wrap(sink, y) >> 2; + n = MIN(n1, n2); + n = MIN(n, nmax); + for (i = 0; i < nch; i++) { + x0 = x + i; + y0 = y + i; + filter = &cd->iir[i]; + for (j = 0; j < n; j += nch) { + *y0 = iir_df1_s24(filter, *x0); + x0 += nch; + y0 += nch; + } + } + processed += n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + +void eq_iir_s32_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct iir_state_df1 *filter; + int32_t *x0; + int32_t *y0; + int32_t *x; + int32_t *y; + int nmax; + int n1; + int n2; + int i; + int j; + int n; + const int nch = audio_stream_get_channels(source); + const int samples = frames * nch; + int processed = 0; + + 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; + n2 = audio_stream_bytes_without_wrap(sink, y) >> 2; + n = MIN(n1, n2); + n = MIN(n, nmax); + for (i = 0; i < nch; i++) { + x0 = x + i; + y0 = y + i; + filter = &cd->iir[i]; + for (j = 0; j < n; j += nch) { + *y0 = iir_df1(filter, *x0); + x0 += nch; + y0 += nch; + } + } + processed += n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +static int eq_iir_init_coef(struct processing_module *mod, int nch) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_eq_iir_config *config = cd->config; + struct iir_state_df1 *iir = cd->iir; + struct sof_eq_iir_header *lookup[SOF_EQ_IIR_MAX_RESPONSES]; + struct sof_eq_iir_header *eq; + int32_t *assign_response; + int32_t *coef_data; + int size_sum = 0; + int resp = 0; + int i; + int j; + int s; + + comp_info(mod->dev, "%u responses, %u channels, stream %d channels", + config->number_of_responses, config->channels_in_config, nch); + + /* Sanity checks */ + if (nch > PLATFORM_MAX_CHANNELS || + config->channels_in_config > PLATFORM_MAX_CHANNELS || + !config->channels_in_config) { + comp_err(mod->dev, "invalid channels count"); + return -EINVAL; + } + if (config->number_of_responses > SOF_EQ_IIR_MAX_RESPONSES) { + comp_err(mod->dev, "# of resp exceeds max"); + return -EINVAL; + } + + /* Collect index of response start positions in all_coefficients[] */ + j = 0; + assign_response = ASSUME_ALIGNED(&config->data[0], 4); + coef_data = ASSUME_ALIGNED(&config->data[config->channels_in_config], + 4); + for (i = 0; i < SOF_EQ_IIR_MAX_RESPONSES; i++) { + if (i < config->number_of_responses) { + eq = (struct sof_eq_iir_header *)&coef_data[j]; + lookup[i] = eq; + j += SOF_EQ_IIR_NHEADER + + SOF_EQ_IIR_NBIQUAD * eq->num_sections; + } else { + lookup[i] = NULL; + } + } + + /* Initialize 1st phase */ + for (i = 0; i < nch; i++) { + /* Check for not reading past blob response to channel assign + * map. The previous channel response is assigned for any + * additional channels in the stream. It allows to use single + * channel configuration to setup multi channel equalization + * with the same response. + */ + if (i < config->channels_in_config) + resp = assign_response[i]; + + if (resp < 0) { + /* Initialize EQ channel to bypass and continue with + * next channel response. + */ + comp_info(mod->dev, "ch %d is set to bypass", i); + iir_reset_df1(&iir[i]); + continue; + } + + if (resp >= config->number_of_responses) { + comp_err(mod->dev, "requested response %d exceeds defined", + resp); + return -EINVAL; + } + + /* Initialize EQ coefficients */ + eq = lookup[resp]; + s = iir_delay_size_df1(eq); + if (s > 0) { + size_sum += s; + } else { + comp_err(mod->dev, "sections count %d exceeds max", + eq->num_sections); + return -EINVAL; + } + + iir_init_coef_df1(&iir[i], eq); + comp_info(mod->dev, "ch %d is set to response %d", i, resp); + } + + return size_sum; +} + +static void eq_iir_init_delay(struct iir_state_df1 *iir, + int32_t *delay_start, int nch) +{ + int32_t *delay = delay_start; + int i; + + /* Initialize second phase to set EQ delay lines pointers. A + * bypass mode filter is indicated by biquads count of zero. + */ + for (i = 0; i < nch; i++) { + if (iir[i].biquads > 0) + iir_init_delay_df1(&iir[i], &delay); + } +} + +void eq_iir_free_delaylines(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct iir_state_df1 *iir = cd->iir; + int i = 0; + + /* Free the common buffer for all EQs and point then + * each IIR channel delay line to NULL. + */ + mod_free(mod, cd->iir_delay); + cd->iir_delay = NULL; + cd->iir_delay_size = 0; + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + iir[i].delay = NULL; +} + +void eq_iir_pass(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); +} + +int eq_iir_setup(struct processing_module *mod, int nch) +{ + struct comp_data *cd = module_get_private_data(mod); + int delay_size; + + /* Free existing IIR channels data if it was allocated */ + eq_iir_free_delaylines(mod); + + /* Set coefficients for each channel EQ from coefficient blob */ + delay_size = eq_iir_init_coef(mod, nch); + if (delay_size < 0) + return delay_size; /* Contains error code */ + + /* If all channels were set to bypass there's no need to + * allocate delay. Just return with success. + */ + if (!delay_size) + return 0; + + /* Allocate all IIR channels data in a big chunk and clear it */ + cd->iir_delay = mod_zalloc(mod, delay_size); + if (!cd->iir_delay) { + comp_err(mod->dev, "delay allocation fail"); + return -ENOMEM; + } + + cd->iir_delay_size = delay_size; + + /* Assign delay line to each channel EQ */ + eq_iir_init_delay(cd->iir, cd->iir_delay, nch); + return 0; +} + diff --git a/src/audio/eq_iir/eq_iir_ipc3.c b/src/audio/eq_iir/eq_iir_ipc3.c new file mode 100644 index 000000000000..69b27d64c3e7 --- /dev/null +++ b/src/audio/eq_iir/eq_iir_ipc3.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017-2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include "eq_iir.h" +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/iir_df1.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/eq.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(eq_iir, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S16LE +static void eq_iir_s32_16_default(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct iir_state_df1 *filter; + int32_t *x0; + int16_t *y0; + int32_t *x; + int16_t *y; + int nmax; + int n1; + int n2; + int i; + int j; + int n; + const int nch = audio_stream_get_channels(source); + const int samples = frames * nch; + int processed = 0; + + 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 */ + n2 = audio_stream_bytes_without_wrap(sink, y) >> 1; /* divide 2 */ + n = MIN(n1, n2); + n = MIN(n, nmax); + for (i = 0; i < nch; i++) { + x0 = x + i; + y0 = y + i; + filter = &cd->iir[i]; + for (j = 0; j < n; j += nch) { + *y0 = iir_df1_s32_s16(filter, *x0); + x0 += nch; + y0 += nch; + } + } + processed += n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S24LE +static void eq_iir_s32_24_default(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct iir_state_df1 *filter; + int32_t *x0; + int32_t *y0; + int32_t *x; + int32_t *y; + int nmax; + int n1; + int n2; + int i; + int j; + int n; + const int nch = audio_stream_get_channels(source); + const int samples = frames * nch; + int processed = 0; + + 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; + n2 = audio_stream_bytes_without_wrap(sink, y) >> 2; + n = MIN(n1, n2); + n = MIN(n, nmax); + for (i = 0; i < nch; i++) { + x0 = x + i; + y0 = y + i; + filter = &cd->iir[i]; + for (j = 0; j < n; j += nch) { + *y0 = iir_df1_s32_s24(filter, *x0); + x0 += nch; + y0 += nch; + } + } + processed += n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE +static void eq_iir_s32_s16_pass(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 * audio_stream_get_channels(source); + + while (remaining_samples) { + nmax = EQ_IIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x)); + n = MIN(remaining_samples, nmax); + nmax = EQ_IIR_BYTES_TO_S16_SAMPLES(audio_stream_bytes_without_wrap(sink, y)); + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *y = sat_int16(Q_SHIFT_RND(*x, 31, 15)); + x++; + y++; + } + remaining_samples -= n; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE +static void eq_iir_s32_s24_pass(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 * audio_stream_get_channels(source); + + while (remaining_samples) { + nmax = EQ_IIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x)); + n = MIN(remaining_samples, nmax); + nmax = EQ_IIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, y)); + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *y = sat_int24(Q_SHIFT_RND(*x, 31, 23)); + x++; + y++; + } + remaining_samples -= n; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ + +const struct eq_iir_func_map fm_configured[] = { +#if CONFIG_FORMAT_S16LE + {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s16_default}, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE + {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, NULL}, + {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, NULL}, + +#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, NULL}, + {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s32_16_default}, +#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ +#if CONFIG_FORMAT_S24LE + {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s24_default}, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, NULL}, + {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s32_24_default}, +#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ +#if CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, eq_iir_s32_default}, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const struct eq_iir_func_map fm_passthrough[] = { +#if CONFIG_FORMAT_S16LE + {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, eq_iir_pass}, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE + {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, NULL}, + {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, NULL}, + +#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE*/ +#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, NULL}, + {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, eq_iir_s32_s16_pass}, +#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE*/ +#if CONFIG_FORMAT_S24LE + {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, eq_iir_pass}, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, NULL}, + {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, eq_iir_s32_s24_pass}, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, eq_iir_pass}, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +static eq_iir_func eq_iir_find_func(enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format, + const struct eq_iir_func_map *map, + int n) +{ + int i; + + /* Find suitable processing function from map. */ + for (i = 0; i < n; i++) { + if ((uint8_t)source_format != map[i].source) + continue; + if ((uint8_t)sink_format != map[i].sink) + continue; + + return map[i].func; + } + + return NULL; +} + +static int eq_iir_verify_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_buffer *sourceb, *sinkb; + uint32_t buffer_flag; + int ret; + + comp_dbg(dev, "entry"); + + /* The caller has verified, that sink and source buffers are connected */ + + /* EQ component will only ever have 1 source and 1 sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + + /* we check whether we can support frame_fmt conversion (whether we have + * such conversion function) due to source and sink buffer frame_fmt's. + * If not, we will overwrite sink (playback) and source (capture) with + * pcm frame_fmt and will not make any conversion (sink and source + * frame_fmt will be equal). + */ + buffer_flag = eq_iir_find_func(audio_stream_get_frm_fmt(&sourceb->stream), + audio_stream_get_frm_fmt(&sinkb->stream), fm_configured, + ARRAY_SIZE(fm_configured)) ? + BUFF_PARAMS_FRAME_FMT : 0; + + ret = comp_verify_params(dev, buffer_flag, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params() failed."); + return ret; + } + + return 0; +} + +int eq_iir_new_blob(struct processing_module *mod, enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format, int channels) +{ + struct comp_data *cd = module_get_private_data(mod); + int ret; + + ret = eq_iir_setup(mod, channels); + if (ret < 0) { + comp_err(mod->dev, "failed IIR setup"); + return ret; + } else if (cd->iir_delay_size) { + comp_dbg(mod->dev, "active"); + cd->eq_iir_func = eq_iir_find_func(source_format, sink_format, fm_configured, + ARRAY_SIZE(fm_configured)); + } else { + comp_dbg(mod->dev, "pass-through"); + cd->eq_iir_func = eq_iir_find_func(source_format, sink_format, fm_passthrough, + ARRAY_SIZE(fm_passthrough)); + } + + return 0; +} + +void eq_iir_set_passthrough_func(struct comp_data *cd, + enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format) +{ + cd->eq_iir_func = eq_iir_find_func(source_format, sink_format, fm_passthrough, + ARRAY_SIZE(fm_passthrough)); +} + +int eq_iir_prepare_sub(struct processing_module *mod) +{ + return eq_iir_verify_params(mod->dev, mod->stream_params); +} diff --git a/src/audio/eq_iir/eq_iir_ipc4.c b/src/audio/eq_iir/eq_iir_ipc4.c new file mode 100644 index 000000000000..c19d7f2650fa --- /dev/null +++ b/src/audio/eq_iir/eq_iir_ipc4.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017-2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include "eq_iir.h" +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/iir_df1.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/eq.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(eq_iir, CONFIG_SOF_LOG_LEVEL); + +/* + * In early days of SOF the preference for pipelines was 16 bits to save RAM in platforms + * like Baytrail. However in microphone paths if there was need to digitally boost the gain + * the quality was bad in topologies where capture DAI was 16 bit and we applied with volume + * or IIR about 20 dB gain. In practice a 16 bit word got left shifted by some bit positions + * that effectively made signal like 12 bits. We could achieve a lot better quality by + * capturing codec and DAI with 24 or 32bits and applying the gain in IIR for the larger word + * length. Then all 16 bits in the pipelines after DAI and IIR had signal. The IIR was chosen for + * format conversion because it also canceled the sometimes large DC component + * (and some lowest non-audible frequencies) in signal. + * It gave the headroom for signal for amplification. + + * If IPC4 systems ever need the memory save small 16 bit capture paths + * the format conversion could be brought back. + */ + +static eq_iir_func eq_iir_find_func(struct processing_module *mod) +{ + unsigned int valid_bit_depth = mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth; + + comp_dbg(mod->dev, "valid_bit_depth %d", valid_bit_depth); + switch (valid_bit_depth) { +#if CONFIG_FORMAT_S16LE + case IPC4_DEPTH_16BIT: + return eq_iir_s16_default; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case IPC4_DEPTH_24BIT: + return eq_iir_s24_default; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case IPC4_DEPTH_32BIT: + return eq_iir_s32_default; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(mod->dev, "set_fir_func(), invalid valid_bith_depth"); + } + return NULL; +} + +int eq_iir_new_blob(struct processing_module *mod, enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format, int channels) +{ + struct comp_data *cd = module_get_private_data(mod); + int ret; + + ret = eq_iir_setup(mod, channels); + if (ret < 0) { + comp_err(mod->dev, "failed IIR setup"); + return ret; + } else if (cd->iir_delay_size) { + comp_dbg(mod->dev, "active"); + cd->eq_iir_func = eq_iir_find_func(mod); + } else { + comp_dbg(mod->dev, "pass-through"); + cd->eq_iir_func = eq_iir_pass; + } + + return 0; +} + +static int eq_iir_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct sof_ipc_stream_params comp_params; + struct comp_dev *dev = mod->dev; + struct comp_buffer *sinkb; + enum sof_ipc_frame valid_fmt, frame_fmt; + int i; + + comp_dbg(dev, "entry"); + comp_params = *params; + comp_params.channels = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + comp_params.rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; + comp_params.buffer_fmt = mod->priv.cfg.base_cfg.audio_fmt.interleaving_style; + + 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); + + comp_params.frame_fmt = valid_fmt; + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + comp_params.chmap[i] = (mod->priv.cfg.base_cfg.audio_fmt.ch_map >> i * 4) & 0xf; + + component_set_nearest_period_frames(dev, comp_params.rate); + + /* The caller has verified, that sink and source buffers are connected */ + sinkb = comp_dev_get_first_data_consumer(dev); + return buffer_set_params(sinkb, &comp_params, true); +} + +void eq_iir_set_passthrough_func(struct comp_data *cd, + enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format) +{ + cd->eq_iir_func = eq_iir_pass; +} + +int eq_iir_prepare_sub(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + int ret = 0; + + ret = eq_iir_params(mod); + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + return ret; +} + diff --git a/src/audio/eq_iir/iir.c b/src/audio/eq_iir/iir.c deleted file mode 100644 index 5ee8b92e6b96..000000000000 --- a/src/audio/eq_iir/iir.c +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/common.h> -#include <sof/audio/eq_iir/iir.h> -#include <sof/audio/format.h> -#include <user/eq.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -int iir_delay_size_df2t(struct sof_eq_iir_header_df2t *config) -{ - int n = config->num_sections; /* One section uses two unit delays */ - - if (n > SOF_EQ_IIR_DF2T_BIQUADS_MAX || n < 1) - return -EINVAL; - - return 2 * n * sizeof(int64_t); -} - -int iir_init_coef_df2t(struct iir_state_df2t *iir, - struct sof_eq_iir_header_df2t *config) -{ - iir->biquads = config->num_sections; - iir->biquads_in_series = config->num_sections_in_series; - iir->coef = ASSUME_ALIGNED(config->biquads, 4); - - return 0; -} - -void iir_init_delay_df2t(struct iir_state_df2t *iir, int64_t **delay) -{ - /* Set delay line of this IIR */ - iir->delay = *delay; - - /* Point to next IIR delay line start. The DF2T biquad uses two - * memory elements. - */ - *delay += 2 * iir->biquads; -} - -void iir_reset_df2t(struct iir_state_df2t *iir) -{ - iir->biquads = 0; - iir->biquads_in_series = 0; - iir->coef = NULL; - /* Note: May need to know the beginning of dynamic allocation after so - * omitting setting iir->delay to NULL. - */ -} - diff --git a/src/audio/eq_iir/iir_generic.c b/src/audio/eq_iir/iir_generic.c deleted file mode 100644 index 9dd47508533f..000000000000 --- a/src/audio/eq_iir/iir_generic.c +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/eq_iir/iir.h> -#include <sof/audio/format.h> -#include <user/eq.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -#if IIR_GENERIC - -/* - * Direct form II transposed second order filter block (biquad) - * - * +----+ +---+ +-------+ - * X(z) ---o--->| b0 |---> + -------------o--->| g |--->| shift |---> Y(z) - * | +----+ ^ | +---+ +-------+ - * | | | - * | +------+ | - * | | z^-1 | | - * | +------+ | - * | ^ | - * | +----+ | +----+ | - * o--->| b1 |---> + <---| a1 |---o - * | +----+ ^ +----+ | - * | | | - * | +------+ | - * | | z^-1 | | - * | +------+ | - * | ^ | - * | +----+ | +----+ | - * o--->| b2 |---> + <---| a2 |---+ - * +----+ +----+ - * - */ - -/* Series DF2T IIR */ - -/* 32 bit data, 32 bit coefficients and 64 bit state variables */ - -int32_t iir_df2t(struct iir_state_df2t *iir, int32_t x) -{ - int32_t in; - int32_t tmp; - int64_t acc; - int32_t out = 0; - int i; - int j; - int d = 0; /* Index to delays */ - int c = 0; /* Index to coefficient a2 */ - - /* Bypass is set with number of biquads set to zero. */ - if (!iir->biquads) - return x; - - /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ - in = x; - for (j = 0; j < iir->biquads; j += iir->biquads_in_series) { - for (i = 0; i < iir->biquads_in_series; i++) { - /* Compute output: Delay is Q3.61 - * Q2.30 x Q1.31 -> Q3.61 - * Shift Q3.61 to Q3.31 with rounding - */ - acc = ((int64_t)iir->coef[c + 4]) * in + iir->delay[d]; - tmp = (int32_t)Q_SHIFT_RND(acc, 61, 31); - - /* Compute first delay */ - acc = iir->delay[d + 1]; - acc += ((int64_t)iir->coef[c + 3]) * in; /* Coef b1 */ - acc += ((int64_t)iir->coef[c + 1]) * tmp; /* Coef a1 */ - iir->delay[d] = acc; - - /* Compute second delay */ - acc = ((int64_t)iir->coef[c + 2]) * in; /* Coef b2 */ - acc += ((int64_t)iir->coef[c]) * tmp; /* Coef a2 */ - iir->delay[d + 1] = acc; - - /* Apply gain Q2.14 x Q1.31 -> Q3.45 */ - acc = ((int64_t)iir->coef[c + 6]) * tmp; /* Gain */ - - /* Apply biquad output shift right parameter - * simultaneously with Q3.45 to Q3.31 conversion. Then - * saturate to 32 bits Q1.31 and prepare for next - * biquad. - */ - acc = Q_SHIFT_RND(acc, 45 + iir->coef[c + 5], 31); - in = sat_int32(acc); - - /* Proceed to next biquad coefficients and delay - * lines. - */ - c += SOF_EQ_IIR_NBIQUAD_DF2T; - d += IIR_DF2T_NUM_DELAYS; - } - /* Output of previous section is in variable in */ - out = sat_int32((int64_t)out + in); - } - return out; -} - -#endif - diff --git a/src/audio/eq_iir/iir_hifi3.c b/src/audio/eq_iir/iir_hifi3.c deleted file mode 100644 index 597fa006bccb..000000000000 --- a/src/audio/eq_iir/iir_hifi3.c +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <stdint.h> -#include <stddef.h> -#include <errno.h> -#include <sof/audio/format.h> -#include <sof/audio/eq_iir/iir.h> -#include <user/eq.h> - -#if IIR_HIFI3 - -#include <xtensa/tie/xt_hifi3.h> - -/* - * Direct form II transposed second order filter block (biquad) - * - * +----+ +---+ +-------+ - * X(z) ---o--->| b0 |---> + -------------o--->| g |--->| shift |---> Y(z) - * | +----+ ^ | +---+ +-------+ - * | | | - * | +------+ | - * | | z^-1 | | - * | +------+ | - * | ^ | - * | +----+ | +----+ | - * o--->| b1 |---> + <---| a1 |---o - * | +----+ ^ +----+ | - * | | | - * | +------+ | - * | | z^-1 | | - * | +------+ | - * | ^ | - * | +----+ | +----+ | - * o--->| b2 |---> + <---| a2 |---+ - * +----+ +----+ - * - */ - -/* Series DF2T IIR */ - -/* 32 bit data, 32 bit coefficients and 64 bit state variables */ - -int32_t iir_df2t(struct iir_state_df2t *iir, int32_t x) -{ - ae_f64 acc; - ae_valign align; - ae_f32x2 coef_a2a1; - ae_f32x2 coef_b2b1; - ae_f32x2 coef_b0shift; - ae_f32x2 gain; - ae_f32 in; - ae_f32 tmp; - ae_f32x2 *coefp; - ae_f64 *delayp; - ae_f32 out = 0; - int i; - int j; - int shift; - int nseries = iir->biquads_in_series; - - /* Bypass is set with number of biquads set to zero. */ - if (!iir->biquads) - return x; - - /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ - coefp = (ae_f32x2 *)&iir->coef[0]; - delayp = (ae_f64 *)&iir->delay[0]; - in = x; - for (j = 0; j < iir->biquads; j += nseries) { - for (i = 0; i < nseries; i++) { - /* Compute output: Delay is kept Q17.47 while multiply - * instruction gives Q2.30 x Q1.31 -> Q18.46. Need to - * shift delay line values right by one for same align - * as MAC. Store to delay line need to be shifted left - * by one similarly. - */ - align = AE_LA64_PP(coefp); - AE_LA32X2_IP(coef_a2a1, align, coefp); - AE_LA32X2_IP(coef_b2b1, align, coefp); - AE_LA32X2_IP(coef_b0shift, align, coefp); - AE_LA32X2_IP(gain, align, coefp); - - acc = AE_SRAI64(*delayp, 1); /* Convert d0 to Q18.46 */ - delayp++; /* Point to d1 */ - AE_MULAF32R_HH(acc, coef_b0shift, in); /* Coef b0 */ - acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ - tmp = AE_ROUND32F48SSYM(acc); /* Rount to Q1.31 */ - - /* Compute 1st delay d0 */ - acc = AE_SRAI64(*delayp, 1); /* Convert d1 to Q18.46 */ - delayp--; /* Point to d0 */ - AE_MULAF32R_LL(acc, coef_b2b1, in); /* Coef b1 */ - AE_MULAF32R_LL(acc, coef_a2a1, tmp); /* Coef a1 */ - acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ - *delayp = acc; /* Store d0 */ - delayp++; /* Point to d1 */ - - /* Compute delay d1 */ - acc = AE_MULF32R_HH(coef_b2b1, in); /* Coef b2 */ - AE_MULAF32R_HH(acc, coef_a2a1, tmp); /* Coef a2 */ - acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ - *delayp = acc; /* Store d1 */ - - /* Apply gain Q18.14 x Q1.31 -> Q34.30 */ - acc = AE_MULF32R_HH(gain, tmp); /* Gain */ - acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ - - /* Apply biquad output shift right parameter and then - * round and saturate to 32 bits Q1.31. - */ - shift = AE_SEL32_LL(coef_b0shift, coef_b0shift); - acc = AE_SRAA64(acc, shift); - in = AE_ROUND32F48SSYM(acc); - - /* Proceed to next biquad coefficients and delay - * lines. The coefp needs rewind by one int32_t - * due to odd number of words in coefficient block. - */ - delayp++; - coefp = (ae_f32x2 *)((int32_t *)coefp - 1); - } - /* Output of previous section is in variable in */ - out = AE_F32_ADDS_F32(out, in); - } - return out; -} - -#endif diff --git a/src/audio/eq_iir/llext/CMakeLists.txt b/src/audio/eq_iir/llext/CMakeLists.txt new file mode 100644 index 000000000000..9b5d956e82b0 --- /dev/null +++ b/src/audio/eq_iir/llext/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("eq_iir" + SOURCES ../eq_iir.c + ../eq_iir_ipc4.c + ../eq_iir_generic.c + LIB openmodules +) diff --git a/src/audio/eq_iir/llext/llext.toml.h b/src/audio/eq_iir/llext/llext.toml.h new file mode 100644 index 000000000000..a5c40c9c2a2a --- /dev/null +++ b/src/audio/eq_iir/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../eq_iir.toml" + +[module] +count = __COUNTER__ diff --git a/tools/tune/eq/GUI_README.md b/src/audio/eq_iir/tune/SOF_GUI_README.md similarity index 100% rename from tools/tune/eq/GUI_README.md rename to src/audio/eq_iir/tune/SOF_GUI_README.md diff --git a/tools/tune/eq/mls_play_config.txt b/src/audio/eq_iir/tune/mls_play_config.txt similarity index 100% rename from tools/tune/eq/mls_play_config.txt rename to src/audio/eq_iir/tune/mls_play_config.txt diff --git a/tools/tune/eq/mls_rec_config.txt b/src/audio/eq_iir/tune/mls_rec_config.txt similarity index 100% rename from tools/tune/eq/mls_rec_config.txt rename to src/audio/eq_iir/tune/mls_rec_config.txt diff --git a/src/audio/eq_iir/tune/sof_cmocka_data_eq_fir.m b/src/audio/eq_iir/tune/sof_cmocka_data_eq_fir.m new file mode 100644 index 000000000000..fd9e4a91f797 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_cmocka_data_eq_fir.m @@ -0,0 +1,111 @@ +% Create a chirp waveform and export test EQ coefficients and reference output +% +% Usage: +% cmocka_data_eq_fir() + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2021, Intel Corporation. All rights reserved. + +function sof_cmocka_data_eq_fir() + +sof_eq_paths(true); + +% Output files and paths +sof_cmocka = '../../../../test/cmocka'; + +chirp_fn = fullfile(sof_cmocka, 'include/cmocka_chirp_2ch.h'); +ref_fn = fullfile(sof_cmocka, 'src/audio/eq_fir/cmocka_fir_ref.h'); +coef_fn = fullfile(sof_cmocka, 'src/audio/eq_fir/cmocka_fir_coef_2ch.h'); + +% Input data +fs = 48e3; +t = 100e-3; +scale = 2^31; +[x, yi] = get_chirp(fs, t); +sof_export_c_int32t(chirp_fn, 'chirp_2ch', 'CHIRP_2CH_LENGTH',yi) + +% Compute a test EQ +eq = test_response(coef_fn, 'fir_coef_2ch', fs); + +% Filter input data +ref(:,1) = filter(eq.b_fir, 1, x(:,1)); +ref(:,2) = filter(eq.b_fir, 1, x(:,2)); +refi = scale_saturate(ref, scale); +sof_export_c_int32t(ref_fn, 'fir_ref_2ch', 'FIR_REF_2CH_LENGTH', refi) + +figure; +plot(yi/scale) +grid on; + +figure; +plot(ref) +grid on; + +figure; +plot(refi / scale) +grid on; + +sof_eq_paths(false); + +end + + +function xi = scale_saturate(x, scale) + +imax = scale - 1; +imin = -scale; +xi = round(scale * x); +xi = min(xi, imax); +xi = max(xi, imin); + +end + +function [x, yi] = get_chirp(fs, t_chirp) + +channels = 2; +f0 = 100; +f1 = 20e3; +a = 1 + 1e-5; % Ensure max and min int values are produced +scale = 2^31; +imax = scale - 1; +imin = -scale; + +n = round(fs * t_chirp); +t = (0:(n - 1)) / fs; +x(:, 1) = a * chirp(t, f0, t_chirp, f1, 'logarithmic', 0); +x(:, 2) = a * chirp(t, f0, t_chirp, f1, 'logarithmic', 90); +x = min(x, 1.0); +x = max(x, -1.0); +yi = scale_saturate(x, scale); + +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = test_response(fn, vn, fs) + +%% Get EQ +sof_ctl = '../../../../tools/ctl'; +blob_fn = fullfile(sof_ctl, 'ipc3/eq_fir_loudness.txt'); +eq = sof_eq_blob_plot(blob_fn, 'fir', fs, [], 0); + +%% Quantize and pack filter coefficients plus shifts etc. +bq = sof_eq_fir_blob_quant(eq.b_fir); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Same response for L and R +num_responses = 1; % One response +bm = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq); + +%% Pack and write file +bp = sof_eq_fir_blob_pack(bm); +sof_export_c_eq_uint32t(fn, bp, vn, 0); + +end diff --git a/src/audio/eq_iir/tune/sof_cmocka_data_eq_iir.m b/src/audio/eq_iir/tune/sof_cmocka_data_eq_iir.m new file mode 100644 index 000000000000..6c9b3732f283 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_cmocka_data_eq_iir.m @@ -0,0 +1,128 @@ +% Create a chirp waveform and export test EQ coefficients and reference output +% +% Usage: +% cmocka_data_eq_iir() + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2021, Intel Corporation. All rights reserved. + +function sof_cmocka_data_eq_iir() + +sof_eq_paths(true); + +% Output files and paths +sof_cmocka = '../../../../test/cmocka'; +chirp_fn = fullfile(sof_cmocka, 'include/cmocka_chirp_2ch.h'); +ref_fn = fullfile(sof_cmocka, 'src/audio/eq_iir/cmocka_chirp_iir_ref_2ch.h'); +coef_fn = fullfile(sof_cmocka, 'src/audio/eq_iir/cmocka_iir_coef_2ch.h'); + +% Input data +fs = 48e3; +t = 100e-3; +scale = 2^31; +[x, yi] = get_chirp(fs, t); +sof_export_c_int32t(chirp_fn, 'chirp_2ch', 'CHIRP_2CH_LENGTH',yi) + +% Compute a test EQ +eq = test_response(coef_fn, 'iir_coef_2ch', fs); + +% Filter input data +[b, a] = zp2tf(eq.p_z, eq.p_p, eq.p_k); +ref(:,1) = filter(b, a, x(:,1)); +ref(:,2) = filter(b, a, x(:,2)); +[b, a] = zp2tf(eq.p_z, eq.p_p, eq.p_k); +refi = scale_saturate(ref, scale); +sof_export_c_int32t(ref_fn, 'chirp_iir_ref_2ch', 'CHIRP_IIR_REF_2CH_LENGTH', refi) + +figure; +plot(yi/scale) +grid on; + +figure; +plot(ref) +grid on; + +figure; +plot(refi / scale) +grid on; + +sof_eq_paths(false); + +end + + +function xi = scale_saturate(x, scale) + +imax = scale - 1; +imin = -scale; +xi = round(scale * x); +xi = min(xi, imax); +xi = max(xi, imin); + +end + +function [x, yi] = get_chirp(fs, t_chirp) + +channels = 2; +f0 = 100; +f1 = 20e3; +a = 1 + 1e-5; % Ensure max and min int values are produced +scale = 2^31; +imax = scale - 1; +imin = -scale; + +n = round(fs * t_chirp); +t = (0:(n - 1)) / fs; +x(:, 1) = a * chirp(t, f0, t_chirp, f1, 'logarithmic', 0); +x(:, 2) = a * chirp(t, f0, t_chirp, f1, 'logarithmic', 90); +x = min(x, 1.0); +x = max(x, -1.0); +yi = scale_saturate(x, scale); + +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = test_response(fn, vn, fs) + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 1; + +%% Parametric EQ +eq.peq = [ ... + eq.PEQ_HP2 100 0 0 ; ... + eq.PEQ_LS2 1000 +6 0 ; ... + eq.PEQ_PN2 3000 +6 1.0 ; ... + eq.PEQ_LP2 15000 0 0 ; ... + ]; + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +%% Quantize and pack filter coefficients plus shifts etc. +bq = sof_eq_iir_blob_quant(eq.p_z, eq.p_p, eq.p_k); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Same response for L and R +num_responses = 1; % One response +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq); + +%% Pack and write file +bp = sof_eq_iir_blob_pack(bm); +sof_export_c_eq_uint32t(fn, bp, vn, 0); + +end diff --git a/src/audio/eq_iir/tune/sof_eq_align.m b/src/audio/eq_iir/tune/sof_eq_align.m new file mode 100644 index 000000000000..dd22e8166b42 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_align.m @@ -0,0 +1,52 @@ +function [am, offs, p] = sof_eq_align(f, m, f_align, m_align) + +%% [am, offs, p] = eq_align(f, m, f_align, m_align) +% +% Move by adding/subtracting an offset to frequency response +% curve to cross desired frequency and magnitude, usually 997 Hz, 0 dB +% +% Input +% f - frequencies +% m - magnitude response +% +% Output +% am - aligned magnitude resposne +% offs - offset (gain) in decibels used +% p - index of f_align in f +% + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +p = find(f < f_align, 1, 'last')+1; +offs = m_align-m(p); +am = m+offs; + +end diff --git a/src/audio/eq_iir/tune/sof_eq_blob_plot.m b/src/audio/eq_iir/tune/sof_eq_blob_plot.m new file mode 100644 index 000000000000..369c311fc96f --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_blob_plot.m @@ -0,0 +1,159 @@ +function eq = sof_eq_blob_plot(blobfn, eqtype, fs, f, doplot) + +% eq = sof_eq_blob_plot(blobfn, eqtype, fs, f, doplot) +% +% Plot frequency response of IIR or FIR EQ coefficients blob +% +% Inputs +% blobfn - filename of the blob +% eqtype - 'iir' or 'fir', if omitted done via string search from blobfn +% fs - sample rate, defaults to 48 kHz if omitted +% f - frequency vector +% doplot - 0 or 1, don't plot if 0 +% +% Output +% eq.f - frequency vector +% eq.m - magnitude response +% eq.gd - group delay +% eq.b_fir - FIR coefficients +% eq.b - IIR numerator coefficients +% eq.a - IIR denominator coefficients +% +% Examples +% sof_eq_blob_plot('../../topology/topology1/m4/eq_iir_coef_loudness.m4', 'iir'); +% sof_eq_blob_plot('../../ctl/eq_fir_mid.bin', 'fir'); +% sof_eq_blob_plot('../../ctl/eq_iir_bassboost.txt', 'iir'); + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2025, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Handle input parameters +if nargin < 2 + if strfind(blobfn, '_fir') + eqtype = 'FIR'; + else + eqtype = 'IIR'; + end +end + +if nargin < 3 + fs = 48e3; +end + +if nargin < 4 || isempty(f) + eq.f = logspace(log10(10),log10(fs/2), 1000); + f_single = []; +else + % Freqz() needs two frequency points or more + if length(f) < 2 + f_single = 1; + eq.f = [f f]; + else + f_single = 0; + eq.f = f; + end +end + +if nargin < 5 + doplot = 1; +end + +%% Read blob as 32 bit integers +blob = sof_eq_blob_read(blobfn); + +%% Group delay with grpdelay() is not working in Octave +do_group_delay = ~exist('OCTAVE_VERSION', 'builtin'); + +%% Decode and compute response +eq.m = []; +eq.gd = []; +switch lower(eqtype) + case 'fir' + hd = sof_eq_fir_blob_decode(blob); + eq.m = zeros(length(eq.f), hd.channels_in_config); + for i = 1:hd.channels_in_config + decoded_eq = sof_eq_fir_blob_decode(blob, hd.assign_response(i)); + eq.b_fir = decoded_eq.b; + eq.b = 1; + eq.a = 1; + h = freqz(eq.b_fir, 1, eq.f, fs); + eq.m(:,i) = 20*log10(abs(h)); + if do_group_delay + gd = grpdelay(eq.b_fir, 1, eq.f, fs) / fs; + eq.gd(:,i) = gd; + end + end + + case 'iir' + hd = sof_eq_iir_blob_decode(blob); + eq.m = zeros(length(eq.f), hd.channels_in_config); + for i = 1:hd.channels_in_config + decoded_eq = sof_eq_iir_blob_decode(blob, hd.assign_response(i)); + eq.b = decoded_eq.b; + eq.a = decoded_eq.a; + h = freqz(eq.b, eq.a, eq.f, fs); + eq.m(:,i) = 20*log10(abs(h)); + if do_group_delay + gd = grpdelay(eq.b, eq.a, eq.f, fs) / fs; + eq.gd(:,i) = gd; + end + end +end + +%% Optional plots +if doplot + eq.fh(1) = figure; + semilogx(eq.f, eq.m); + ymin = max(min(min(eq.m)), -60); + ymax = max(max(eq.m)); + axis([10 round(fs/2/10)*10 ymin-3 ymax+3 ]); + grid on; + channel_legends(hd.channels_in_config); + xlabel('Frequency (Hz)'); + ylabel('Amplitude (dB)'); + title(blobfn, 'Interpreter', 'None'); + + if do_group_delay + eq.fh(2) = figure; + semilogx(eq.f, eq.gd * 1e6); + ax = axis(); + axis([10 round(fs/2/10)*10 ax(3:4) ]); + grid on; + channel_legends(hd.channels_in_config); + xlabel('Frequency (Hz)'); + ylabel('Group delay (us)'); + title(blobfn, 'Interpreter', 'None'); + end +end + +%% Trim avay the duplicated frequency point +if f_single + eq.f = eq.f(1); + eq.m = eq.m(1, :); + if do_group_delay + eq.gd = eq.gd(1, :); + end +end + +end + +%% Helper functions +function channel_legends(n) + +switch n + case 2 + legend('ch1', 'ch2'); + case 4 + legend('ch1', 'ch2', 'ch3', 'ch4'); + case 6 + legend('ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6'); + case 8 + legend('ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8'); + otherwise + error('Illegal number of channels found'); +end + +end diff --git a/src/audio/eq_iir/tune/sof_eq_blob_read.m b/src/audio/eq_iir/tune/sof_eq_blob_read.m new file mode 100644 index 000000000000..424e8c74ad93 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_blob_read.m @@ -0,0 +1,78 @@ +function blob = sof_eq_blob_read(blobfn, fntype) + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020-2025, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Use file suffix as type +if nargin < 2 + idx = strfind(blobfn, '.'); + fntype = blobfn(idx(end)+1:end); +end + +%% Read the file +add_tlv_header = false; +switch lower(fntype) + case 'bin' + fh = fopen(blobfn, 'rb'); + tmp = fread(fh, inf, 'uint32'); + fclose(fh); + case 'txt' + fh = fopen(blobfn, 'r'); + tmp = fscanf(fh, '%u,', Inf); + fclose(fh); + case 'm4' + % The blobs in topology are without TLV header. For simplicity + % add to beginning two 32 bit words (zeros) to be compatible + % with other blob formats. + tmp = get_parse_m4(blobfn); + add_tlv_header = true; + otherwise + error('Illegal file type, please give fntype argument'); + +end + +if add_tlv_header + blob = uint32([0 0 tmp']'); +else + blob = uint32(tmp); +end + +end + +%% Parse m4 topology blob +function blob = get_parse_m4(blobfn) + +fh = fopen(blobfn, 'r'); + +% Ignore two lines from beginning +ln = fgets(fh); +ln = fgets(fh); + +% Loop until end of file +n = 1; +ln = fgets(fh); +while ln ~= -1 + idx = strfind(ln, '0x'); + for i = 1:length(idx) + bytes(n) = hex2dec(ln(idx(i)+2:idx(i)+3)); + n = n + 1; + end + ln = fgets(fh); +end +fclose(fh); + +% Convert to 32 bit +n32 = round(length(bytes)/4); +blob = zeros(n32, 1); +for i = 1:n32 + i8 = (i - 1)*4 + 1; + blob(i) = bytes(i8) * 2^0 ... + + bytes(i8 + 1) * 2^8 ... + + bytes(i8 + 2) * 2^16 ... + + bytes(i8 + 3) * 2^24; +end + +end diff --git a/src/audio/eq_iir/tune/sof_eq_coef_quant.m b/src/audio/eq_iir/tune/sof_eq_coef_quant.m new file mode 100644 index 000000000000..b8995bf65a5a --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_coef_quant.m @@ -0,0 +1,50 @@ +function qc = sof_eq_coef_quant(c, bits, qf) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +scale = 2^qf; +cmax = 2^(bits-1)-1; +cmin = -2^(bits-1); +qc = int64(round(c*scale)); +idx = find(qc > cmax); +if ~isempty(idx) + fprintf('Warning: Max. value of Q format is exceeded: %d (%d)\n', ... + qc(idx(1)), cmax); + qc(idx) = cmax; +end +idx = find(qc < cmin); +if ~isempty(idx) + fprintf('Warning: Min. value of Q format is exceeded: %d (%d)\n', ... + qc(idx(1)), cmin); + qc(idx) = cmin; +end + +end diff --git a/src/audio/eq_iir/tune/sof_eq_compute.m b/src/audio/eq_iir/tune/sof_eq_compute.m new file mode 100644 index 000000000000..8ebd20a8d29d --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_compute.m @@ -0,0 +1,462 @@ +function eq = sof_eq_compute( eq ) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +%% Sanity checks +if eq.enable_iir == 0 && eq.enable_fir == 0 + fprintf('Warning: Nothing to do. Please enable FIR or IIR!\n'); +end + +%% Extrapolate response to 0..fs/2, convert to logaritmic grid, and smooth +% with 1/N octave filter +eq = preprocess_responses(eq); + +%% Define target (e.g. speaker) response as parametric filter. This could also +% be numerical data interpolated to the grid. +if length(eq.parametric_target_response) > 0 + [eq.t_z, eq.t_p, eq.t_k] = sof_eq_define_parametric_eq( ... + eq.parametric_target_response, eq.fs); + eq.t_db = sof_eq_compute_response(eq.t_z, eq.t_p, eq.t_k, eq.f, eq.fs); +end + +if isempty(eq.t_db) + fprintf('Warning: No target response is defined.\n'); +end + +%% Align responses at some frequency and dB +[eq.m_db_s, offs] = sof_eq_align(eq.f, eq.m_db_s, eq.f_align, eq.db_align); +eq.raw_m_db = eq.raw_m_db + offs; +eq.m_db = eq.m_db + offs; +eq.t_db = sof_eq_align(eq.f, eq.t_db, eq.f_align, eq.db_align); + +%% Error to equalize = target - raw response, apply 1/N octave smoothing to +% soften the EQ shape +eq.err_db = eq.t_db - eq.m_db; +[eq.err_db_s, eq.logsmooth_noct] = logsmooth(eq.f, eq.err_db, eq.logsmooth_eq); + +%% Parametric IIR EQ definition +if eq.enable_iir + [eq.p_z, eq.p_p, eq.p_k] = sof_eq_define_parametric_eq(eq.peq, eq.fs); + if max(length(eq.p_z), length(eq.p_p)) > 2*eq.iir_biquads_max + error('Maximum number of IIR biquads is exceeded'); + end +else + [eq.p_z, eq.p_p, eq.p_k] = tf2zp(1, 1); +end +[eq.iir_eq_db, eq.iir_eq_ph, eq.iir_eq_gd] = sof_eq_compute_response(eq.p_z, ... + eq.p_p, eq.p_k, eq.f, eq.fs); + + +%% FIR EQ computation +% Find remaining responses error ater IIR for FIR to handle +if eq.fir_compensate_iir + eq.err2_db = eq.err_db_s-eq.iir_eq_db; +else + eq.err2_db = eq.err_db_s; +end + +if eq.enable_fir + [eq.t_fir_db, eq.fmin_fir, eq.fmax_fir] = ... + get_fir_target(eq.f, eq.err2_db, eq.fmin_fir, eq.fmax_fir, ... + eq.amin_fir, eq.amax_fir, eq.logsmooth_noct, eq.fir_autoband); + + if eq.fir_minph + eq.b_fir = compute_minph_fir(eq.f, eq.t_fir_db, ... + eq.fir_length, eq.fs, eq.fir_beta); + else + eq.b_fir = compute_linph_fir(eq.f, eq.t_fir_db, ... + eq.fir_length, eq.fs, eq.fir_beta); + end +else + eq.b_fir = 1; + eq.tfirdb = zeros(1,length(eq.f)); +end + +%% Update all responses +eq = sof_eq_compute_tot_response(eq); + +%% Normalize +eq = sof_eq_norm(eq); + +end + +function eq = preprocess_responses(eq) +%% Usually too narrow measurement without the lowest and highest frequencies +[f0, m0, gd0] = fix_response_dcnyquist_mult(eq.raw_f, eq.raw_m_db, ... + eq.raw_gd_s, eq.fs); + +%% Create dense logarithmic frequency grid, then average possible multiple +% measurements +[eq.f, eq.m_db, eq.gd_s, eq.num_responses] = map_to_logfreq_mult(f0, m0, ... + gd0, 1, eq.fs/2, eq.np_fine); + +%% Smooth response with 1/N octave filter for plotting +eq.m_db_s = logsmooth(eq.f, eq.m_db, eq.logsmooth_plot); + +if length(eq.target_m_db) > 0 + % Use target_m_db as dummy group delay, ignore other than magnitude + [f0, m0, ~] = fix_response_dcnyquist_mult(eq.target_f, ... + eq.target_m_db, [], eq.fs); + [~, eq.t_db, ~, ~] = map_to_logfreq_mult(f0, m0, [], 1, ... + eq.fs/2, eq.np_fine); +end +end + + +function [f_hz, m_db, gd_s] = fix_response_dcnyquist(f_hz0, m_db0, gd_s0, fs) +%% Append DC and Fs/2 if missing +f_hz = f_hz0; +m_db = m_db0; +gd_s = gd_s0; +if min(f_hz) > 0 + f_hz = [0 f_hz]; + m_db = [m_db(1) m_db]; % DC the same as 1st measured point + if length(gd_s) > 0 + gd_s = [gd_s(1) gd_s]; % DC the same as 1st measured point + end +end +if max(f_hz) < fs/2 + f_hz = [f_hz fs/2]; + m_db = [m_db m_db(end)]; % Fs/2 the same as last measured point + if length(gd_s) > 0 + gd_s = [gd_s gd_s(end)]; % Fs/2 the same as last measured point + end +end +end + +function [f_hz, m_db, gd_s] = fix_response_dcnyquist_mult(f_hz0, m_db0, ... + gd_s0, fs) + +if iscolumn(f_hz0) + f_hz0 = f_hz0.'; +end +if iscolumn(m_db0) + m_db0 = m_db0.'; +end +if iscolumn(gd_s0) + gd_s0 = gd_s0.'; +end + +s1 = size(f_hz0); +s2 = size(m_db0); +s3 = size(gd_s0); + +if s1(1) == 0 + error('Frequencies vector is empty'); +end +if (s1(1) ~= s2(1)) + error('There must be equal number of frequency and magnitude data'); +end +if (s1(2) ~= s2(2)) + error('There must be equal number of points in frequency, magnitude, and group delay data'); +end +if sum(s3) == 0 + gd_s0 = zeros(s2(1),s2(2)); +end +for i=1:s1(1) + [f_hz(i,:), m_db(i,:), gd_s(i,:)] = fix_response_dcnyquist(... + f_hz0(i,:), m_db0(i,:), gd_s0(i,:), fs); +end + +end + +function [f_hz, m_db, gd_s] = map_to_logfreq(f_hz0, m_db0, gd_s0, f1, f2, np) +%% Create logarithmic frequency vector and interpolate +f_hz = logspace(log10(f1),log10(f2), np); +m_db = interp1(f_hz0, m_db0, f_hz); +gd_s = interp1(f_hz0, gd_s0, f_hz); +m_db(end) = m_db(end-1); % Fix NaN in the end +gd_s(end) = gd_s(end-1); % Fix NaN in the end +end + +function [f_hz, mm_db, mgd_s, num] = map_to_logfreq_mult(f_hz0, m_db0, ... + gd_s0, f1, f2, np) + +s1 = size(f_hz0); +s2 = size(m_db0); +s3 = size(gd_s0); +if (s1(1) ~= s2(1)) + error('There must be equal number of frequency and magnitude data sets'); +end +if (s1(2) ~= s2(2)) + error('There must be equal number of points in frequency and magnitude data'); +end +num = s1(1); +if sum(s3) == 0 + gd_s0 = zeros(s2(1),s2(2)); +end +for i=1:num + [f_hz, m_db(i,:), gd_s(i,:)] = map_to_logfreq(f_hz0(i,:), ... + m_db0(i,:), gd_s0(i,:), f1, f2, np); +end + +if num > 1 + mm_db = mean(m_db); + mgd_s = mean(gd_s); +else + mm_db = m_db; + mgd_s = gd_s; +end +end + +function [ms_db, noct] = logsmooth(f, m_db, c) + +%% Create a 1/N octave smoothing filter +ind1 = find(f < 1000); +ind2 = find(f < 2000); +noct = ind2(end)-ind1(end); +n = 2*round(c*noct/2); +b_smooth = ones(1,n)*1/n; + +%% Smooth the response +tmp = filter(b_smooth, 1, m_db); +ms_db = [tmp(n/2+1:end) linspace(tmp(end), m_db(end), n/2)]; +ms_db(1:n) = ones(1,n)*ms_db(n); +end + +function [m_db, fmin_fir, fmax_fir] = get_fir_target(fhz, err2db, fmin_fir, ... + fmax_fir, amin_fir, amax_fir, noct, auto) + + +%% Find maximum in 1-6 kHz band +idx = find(fhz > 1e3, 1, 'first') - 1; +m_db = err2db - err2db(idx); +if auto + cf = [1e3 6e3]; + ind1 = find(fhz < cf(2)); + ind2 = find(fhz(ind1) > cf(1)); + ipeak = find(m_db(ind2) == max(m_db(ind2))) + ind2(1); + ind1 = find(fhz < cf(1)); + ind2 = find(m_db(ind1) > m_db(ipeak)); + if length(ind2) > 0 + fmin_fir = fhz(ind2(end)); + end + ind1 = find(fhz > cf(2)); + ind2 = find(m_db(ind1) > m_db(ipeak)) + ind1(1); + if length(ind2) > 0 + fmax_fir = fhz(ind2(1)); + end +end + +%% Find FIR target response +ind1 = find(fhz < fmin_fir); +ind2 = find(fhz > fmax_fir); +p1 = ind1(end)+1; +if length(ind2) > 0 + p2 = ind2(1)-1; +else + p2 = length(fhz); +end +m_db(ind1) = m_db(p1); +m_db(ind2) = m_db(p2); +ind = find(m_db > amax_fir); +m_db(ind) = amax_fir; +ind = find(m_db < amin_fir); +m_db(ind) = amin_fir; + +%% Smooth high frequency corner with spline +nn = round(noct/8); +x = [p2-nn p2-nn+1 p2+nn-1 p2+nn]; +if max(x) < length(m_db) + y = m_db(x); + xx = p2-nn:p2+nn; + yy = spline(x, y, xx); + m_db(p2-nn:p2+nn) = yy; +end + +%% Smooth low frequency corner with spline +nn = round(noct/8); +x = [p1-nn p1-nn+1 p1+nn-1 p1+nn]; +if min(x) > 0 + y = m_db(x); + xx = p1-nn:p1+nn; + yy = spline(x, y, xx); + m_db(p1-nn:p1+nn) = yy; +end + +end + +function b = compute_linph_fir(f_hz, m_db, taps, fs, beta) +if nargin < 5 + beta = 4; +end +if mod(taps,2) == 0 + fprintf('Warning: Even FIR length requested.\n'); +end +n_fft = 2*2^ceil(log(taps)/log(2)); +n_half = n_fft/2+1; +f_fft = linspace(0, fs/2, n_half); +m_lin = 10.^(m_db/20); +if f_hz(1) > 0 + f_hz = [0 f_hz]; + m_lin = [m_lin(1) m_lin]; +end +a_half = interp1(f_hz, m_lin, f_fft, 'linear'); +a = [a_half conj(a_half(end-1:-1:2))]; +h = real(fftshift(ifft(a))); +b0 = h(n_half-floor((taps-1)/2):n_half+floor((taps-1)/2)); +win = kaiser(length(b0), beta)'; +b = b0 .* win; +if length(b) < taps + % Append to even length + b = [b 0]; +end +end + +function b_fir = compute_minph_fir(f, m_db, fir_length, fs, beta) + +%% Design double length H^2 FIR +n = 2*fir_length+1; +m_lin2 = (10.^(m_db/20)).^2; +m_db2 = 20*log10(m_lin2); +blin = compute_linph_fir(f, m_db2, n, fs, beta); + +%% Find zeros inside unit circle +myeps = 1e-3; +hdzeros = roots(blin); +ind1 = find( abs(hdzeros) < (1-myeps) ); +minzeros = hdzeros(ind1); + +%% Find double zeros at unit circle +ind2 = find( abs(hdzeros) > (1-myeps) ); +outzeros = hdzeros(ind2); +ind3 = find( abs(outzeros) < (1+myeps) ); +circlezeros = outzeros(ind3); + +%% Get half of the unit circle zeros +if isempty(circlezeros) + %% We are fine ... +else + %% Eliminate double zeros + cangle = angle(circlezeros); + [sorted_cangle, ind] = sort(cangle); + sorted_czeros = circlezeros(ind); + pos = find(angle(sorted_czeros) > 0); + neg = find(angle(sorted_czeros) < 0); + pos_czeros = sorted_czeros(pos); + neg_czeros = sorted_czeros(neg(end:-1:1)); + h1 = []; + for i = 1:2:length(pos_czeros)-1 + x=mean(angle(pos_czeros(i:i+1))); + h1 = [h1' complex(cos(x),sin(x))]'; + end + h2 = []; + for i = 1:2:length(neg_czeros)-1; + x=mean(angle(neg_czeros(i:i+1))); + h2 = [h2' complex(cos(x),sin(x))]'; + end + halfcirclezeros = [h1' h2']'; + if length(halfcirclezeros)*2 < length(circlezeros)-0.1 + %% Replace the last zero pair + halfcirclezeros = [halfcirclezeros' complex(-1, 0)]'; + end + minzeros = [ minzeros' halfcirclezeros' ]'; +end + +%% Convert to transfer function +bmin = mypoly(minzeros); + +%% Scale peak in passhz to max m_db +hmin = freqz(bmin, 1, 512, fs); +b_fir = 10^(max(m_db)/20)*bmin/max(abs(hmin)); + +end + +function tf = mypoly( upolyroots ) + +% Sort roots to increasing angle to ensure more consistent behavior +aa = abs(angle(upolyroots)); +[sa, ind] = sort(aa); +polyroots = upolyroots(ind); + +n = length(polyroots); +n1 = 16; % do not change, hardwired to 16 code below + +if n < (2*n1+1) + % No need to split + tf = poly(polyroots); +else + % Split roots evenly to 16 poly computations + % The fist polys will rpb+1 roots and the rest + % rpb roots to compute + rpb = floor(n/n1); + rem = mod(n,n1); + i1 = zeros(1,n1); + i2 = zeros(1,n1); + i1(1) = 1; + for i = 1:n1-1; + if rem > 0 + i2(i) = i1(i)+rpb; + rem = rem-1; + else + i2(i) = i1(i)+rpb-1; + end + i1(i+1) = i2(i)+1; + end + i2(n1) = n; + tf101 = poly(polyroots(i1(1):i2(1))); + tf102 = poly(polyroots(i1(2):i2(2))); + tf103 = poly(polyroots(i1(3):i2(3))); + tf104 = poly(polyroots(i1(4):i2(4))); + tf105 = poly(polyroots(i1(5):i2(5))); + tf106 = poly(polyroots(i1(6):i2(6))); + tf107 = poly(polyroots(i1(7):i2(7))); + tf108 = poly(polyroots(i1(8):i2(8))); + tf109 = poly(polyroots(i1(9):i2(9))); + tf110 = poly(polyroots(i1(10):i2(10))); + tf111 = poly(polyroots(i1(11):i2(11))); + tf112 = poly(polyroots(i1(12):i2(12))); + tf113 = poly(polyroots(i1(13):i2(13))); + tf114 = poly(polyroots(i1(14):i2(14))); + tf115 = poly(polyroots(i1(15):i2(15))); + tf116 = poly(polyroots(i1(16):i2(16))); + % Combine coefficients with convolution + tf21 = conv(tf101, tf116); + tf22 = conv(tf102, tf115); + tf23 = conv(tf103, tf114); + tf24 = conv(tf104, tf113); + tf25 = conv(tf105, tf112); + tf26 = conv(tf106, tf111); + tf27 = conv(tf107, tf110); + tf28 = conv(tf108, tf109); + tf31 = conv(tf21, tf28); + tf32 = conv(tf22, tf27); + tf33 = conv(tf23, tf26); + tf34 = conv(tf24, tf25); + tf41 = conv(tf31, tf34); + tf42 = conv(tf32, tf33); + tf = conv(tf41, tf42); + + % Ensure the tf coefficients are real if rounding issues + tf = real(tf); +end + +end diff --git a/src/audio/eq_iir/tune/sof_eq_compute_response.m b/src/audio/eq_iir/tune/sof_eq_compute_response.m new file mode 100644 index 000000000000..178cf9ab5c09 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_compute_response.m @@ -0,0 +1,72 @@ +function [m, ph, gd] = sof_eq_compute_response(z, p, k, f, fs) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +switch nargin + case 3 + b = z; % 1st arg + f = p; % 2nd arg + fs = k; % 3rd arg + h = freqz(b, 1, f, fs); + m = 20*log10(abs(h)); + ph = 180/pi*angle(h); + + if length(b) == 1 + gd = zeros(1, length(f)); + else + if exist('OCTAVE_VERSION', 'builtin') + % grpdelay() has some issue so better to not show a plot + gd = NaN * zeros(1, length(f)); + else + gd = 1/fs*grpdelay(b, 1, f, fs); + end + end + case 5 + [b, a] = zp2tf(z, p, k); + h = freqz(b, a, f, fs); + m = 20*log10(abs(h)); + ph = 180/pi*angle(h); + + if length(z) == 0 && length(p) == 0 + gd = zeros(1, length(f)); + else + if exist('OCTAVE_VERSION', 'builtin') + % grpdelay() has some issue so better to not show a plot + gd = NaN * zeros(1, length(f)); + else + gd = 1/fs*grpdelay(b, a, f, fs); + end + end + otherwise + error('Incorrect input parameters'); +end + +end diff --git a/src/audio/eq_iir/tune/sof_eq_compute_tot_response.m b/src/audio/eq_iir/tune/sof_eq_compute_tot_response.m new file mode 100644 index 000000000000..391de4310633 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_compute_tot_response.m @@ -0,0 +1,50 @@ +function eq = sof_eq_compute_tot_response(eq) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +% FIR response and combined IIR+FIR EQ +[eq.iir_eq_db, eq.iir_eq_ph, eq.iir_eq_gd] = sof_eq_compute_response(eq.p_z, eq.p_p, eq.p_k, eq.f, eq.fs); +[eq.fir_eq_db, eq.fir_eq_ph, eq.fir_eq_gd] = sof_eq_compute_response(eq.b_fir, eq.f, eq.fs); +eq.tot_eq_db = eq.iir_eq_db + eq.fir_eq_db; +eq.tot_eq_gd = eq.iir_eq_gd + eq.fir_eq_gd; + +% Simulated equalized result +eq.m_eqd = eq.m_db + eq.tot_eq_db; % Simulated response +eq.m_eqd_s = eq.m_db_s + eq.tot_eq_db; % Smoothed simulated response +eq.gd_eqd = eq.gd_s' + eq.tot_eq_gd; + +% Align +[eq.m_eqd_s, adjust, p] = sof_eq_align(eq.f, eq.m_eqd_s, eq.f_align, eq.db_align); +eq.m_eqd = eq.m_eqd + adjust; +eq.m_eq_loss = eq.tot_eq_db(p); +eq.m_eqd_abs = eq.m_db_abs+eq.m_eq_loss; + +end diff --git a/src/audio/eq_iir/tune/sof_eq_defaults.m b/src/audio/eq_iir/tune/sof_eq_defaults.m new file mode 100644 index 000000000000..c9f4f5f27cee --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_defaults.m @@ -0,0 +1,117 @@ +function p = sof_eq_defaults + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +% Misc +p.plot_figs = 0; +p.fn = 'configuration.txt'; +p.fs = 48e3; +p.f_align = 997; +p.db_align = 0; +p.logsmooth_plot = 1/3; % Smooth over 1/3 octaves +p.logsmooth_eq = 1/3; % Smooth over 1/3 octaves +p.np_fine = 5000; % 5000 point design grid + +% Parametric EQ IDs +p.PEQ_HP1 = 1; p.PEQ_HP2 = 2; p.PEQ_LP1 = 3; p.PEQ_LP2 = 4; +p.PEQ_LS1 = 5; p.PEQ_LS2 = 6; p.PEQ_HS1 = 7; p.PEQ_HS2 = 8; +p.PEQ_PN2 = 9; p.PEQ_LP4 = 10; p.PEQ_HP4 = 11; p.PEQ_LP2G = 12; +p.PEQ_HP2G = 13; p.PEQ_BP2 = 14; p.PEQ_NC2 = 15; p.PEQ_LS2G = 16; +p.PEQ_HS2G = 17; + +% FIR constraints +p.fmin_fir = 200; % +p.fmax_fir = 15e3; % +p.amax_fir = 20; +p.amin_fir = -20; +p.fir_beta = 8; +p.fir_length = 63; +p.fir_minph = 0; % 0 = linear phase, 1 = minimum phase +% Adjust fmin_fir, fmax_fir automatically for least gain loss in FIR +p.fir_autoband = 1; +p.enable_fir = 0; + +% IIR conf +p.iir_biquads_max = 8; +p.enable_iir = 0; + +% Initialize other fields those are computed later to allow use of struct +% arrays +p.raw_f = [10 100e3]; +p.raw_m_db = [0 0]; +p.raw_gd_s = []; +p.f = []; +p.m_db = []; +p.gd_s = []; +p.num_responses = 0; +p.m_db_s = []; +p.gd_s_s = []; +p.logsmooth_noct = 0; +p.t_z = []; +p.t_p = []; +p.t_k = []; +p.t_db = []; +p.m_db_abs = 0; +p.m_db_offs = 0; +p.raw_m_noalign_db = []; +p.err_db = []; +p.p_z = []; +p.p_p = []; +p.p_k = []; +p.iir_eq_db = []; +p.iir_eq_ph = []; +p.iir_eq_gd = []; +p.err2_db = []; +p.t_fir_db = []; +p.b_fir = []; +p.fir_eq_db = []; +p.fir_eq_ph = []; +p.fir_eq_gd = []; +p.tot_eq_db = []; +p.tot_eq_gd = []; +p.m_eqd = []; +p.gd_eqd = []; +p.m_eq_loss = 0; +p.m_eqd_abs = 0; +p.sim_m_db = []; +p.parametric_target_response = []; +p.target_f = [10 100e3]; +p.target_m_db = [0 0]; +p.fir_compensate_iir = 1; +p.p_fmin = 10; +p.p_fmax = 30e3; +p.name = ''; +p.iir_norm_type = 'loudness'; % loudness/peak/1k +p.iir_norm_offs_db = 0; +p.fir_norm_type = 'loudness'; % loudness/peak/1k +p.fir_norm_offs_db = 0; + +end diff --git a/src/audio/eq_iir/tune/sof_eq_define_parametric_eq.m b/src/audio/eq_iir/tune/sof_eq_define_parametric_eq.m new file mode 100644 index 000000000000..5e40f96f050e --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_define_parametric_eq.m @@ -0,0 +1,395 @@ +function [z, p, k] = sof_eq_define_parametric_eq(peq, fs) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +% Parametric types +PEQ_HP1 = 1; PEQ_HP2 = 2; PEQ_LP1 = 3; PEQ_LP2 = 4; +PEQ_LS1 = 5; PEQ_LS2 = 6; PEQ_HS1 = 7; PEQ_HS2 = 8; +PEQ_PN2 = 9; PEQ_LP4 = 10; PEQ_HP4 = 11; PEQ_LP2G= 12; +PEQ_HP2G = 13; PEQ_BP2 = 14; PEQ_NC2 = 15; PEQ_LS2G = 16; +PEQ_HS2G = 17; + +sp = size(peq); +z = []; +p = []; +k = 1; +for i=1:sp(1) + type = peq(i,1); + f = peq(i,2); + g = peq(i,3); + Q = peq(i,4); + if f < fs/2 + a0 = []; + b0 = []; + z0 = []; + p0 = []; + k0 = []; + switch peq(i,1) + case PEQ_HP1, [z0, p0, k0] = butter(1, 2*f/fs, 'high'); + case PEQ_HP2, [z0, p0, k0] = butter(2, 2*f/fs, 'high'); + case PEQ_HP4, [z0, p0, k0] = butter(4, 2*f/fs, 'high'); + case PEQ_LP1, [z0, p0, k0] = butter(1, 2*f/fs); + case PEQ_LP2, [z0, p0, k0] = butter(2, 2*f/fs); + case PEQ_LP4, [z0, p0, k0] = butter(4, 2*f/fs); + case PEQ_LS1, [b0, a0] = low_shelf_1st(f, g, fs); + case PEQ_LS2, [b0, a0] = low_shelf_2nd(f, g, fs); + case PEQ_HS1, [b0, a0] = high_shelf_1st(f, g, fs); + case PEQ_HS2, [b0, a0] = high_shelf_2nd(f, g, fs); + case PEQ_PN2, [b0, a0] = peak_2nd(f, g, Q, fs); + case PEQ_HP2G, [b0, a0] = high_pass_2nd_reasonance(f, Q, fs); + case PEQ_LP2G, [b0, a0] = low_pass_2nd_reasonance(f, Q, fs); + case PEQ_BP2, [b0, a0] = band_pass_2nd(f, Q, fs); + case PEQ_NC2, [b0, a0] = notch_2nd(f, Q, fs); + case PEQ_LS2G, [b0, a0] = low_shelf_2nd_google(f, g, fs); + case PEQ_HS2G, [b0, a0] = high_shelf_2nd_google(f, g, fs); + otherwise + error('Unknown parametric EQ type'); + end + if ~isempty(a0) + [z0, p0, k0] = tf2zp(b0, a0); + end + if ~isempty(k0) + z = [z ; z0(:)]; + p = [p ; p0(:)]; + k = k * k0; + end + end +end +end + +function [b, a] = low_shelf_1st(fhz, gdb, fs) +zw = 2*pi*fhz; +w = wmap(zw, fs); +glin = 10^(gdb/20); +bs = [1 glin*w]; +as = [1 w]; +[b, a] = my_bilinear(bs, as, fs); +end + +function [b, a] = low_shelf_2nd(fhz, gdb, fs) +zw = 2*pi*fhz; +w = wmap(zw, fs); +glin = 10^(gdb/20); +bs = [1 w*sqrt(2*glin) glin*w^2]; +as = [1 w*sqrt(2) w^2]; +[b, a] = my_bilinear(bs, as, fs); +end + +function [b, a] = high_shelf_1st(fhz, gdb, fs) +zw = 2*pi*fhz; +w = wmap(zw, fs); +glin = 10^(gdb/20); +bs = [glin w]; +as = [1 w]; +[b, a] = my_bilinear(bs, as, fs); +end + +function [b, a] = high_shelf_2nd(fhz, gdb, fs) +zw = 2*pi*fhz; +w = wmap(zw, fs); +glin = 10^(gdb/20); +bs = [glin w*sqrt(2*glin) w^2]; +as = [1 w*sqrt(2) w^2]; +[b, a] = my_bilinear(bs, as, fs); +end + + +function [b, a] = peak_2nd(fhz, gdb, Q, fs) + % Reference http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt + A = 10^(gdb/40); % Square root of linear gain + wc = 2*pi*fhz/fs; + + if Q <= 0 + % To fix gui edge cases, comment from CRAS code: + % When Q = 0, the above formulas have problems. If we + % look at the z-transform, we can see that the limit + % as Q->0 is A^2, so set the filter that way. + b = [A * A, 0, 0]; + a = [1, 0, 0]; + return; + end + + alpha = sin(wc)/(2*Q); + b0 = 1 + alpha * A; + b1 = -2 * cos(wc); + b2 = 1 - alpha * A; + a0 = 1 + alpha / A; + a1 = -2 * cos(wc); + a2 = 1 - alpha / A; + b = [b0 / a0 b1 / a0 b2 / a0]; + a = [1 a1 / a0 a2 / a0]; +end + +function [b, a] = high_pass_2nd_reasonance(f, resonance, fs) + cutoff = f/(fs/2); + % Limit cutoff to 0 to 1. + cutoff = max(0.0, min(cutoff, 1.0)); + + if cutoff == 1 || cutoff == 0 + % When cutoff is one, the z-transform is 0. + % When cutoff is zero, we need to be careful because the above + % gives a quadratic divided by the same quadratic, with poles + % and zeros on the unit circle in the same place. When cutoff + % is zero, the z-transform is 1. + + b = [1 - cutoff, 0, 0]; + a = [1, 0, 0]; + return; + end + + % Compute biquad coefficients for highpass filter + resonance = max(0.0, resonance); % can't go negative + g = 10.0^(0.05 * resonance); + d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); + + theta = pi * cutoff; + sn = 0.5 * d * sin(theta); + beta = 0.5 * (1 - sn) / (1 + sn); + gamma = (0.5 + beta) * cos(theta); + alpha = 0.25 * (0.5 + beta + gamma); + + b0 = 2 * alpha; + b1 = 2 * -2 * alpha; + b2 = 2 * alpha; + a1 = 2 * -gamma; + a2 = 2 * beta; + + b = [b0, b1, b2]; + a = [1.0, a1, a2]; +end + +function [b, a] = low_pass_2nd_reasonance(f, resonance, fs) + cutoff = f/(fs/2); + % Limit cutoff to 0 to 1. + cutoff = max(0.0, min(cutoff, 1.0)); + + if cutoff == 1 || cutoff == 0 + % When cutoff is 1, the z-transform is 1. + % When cutoff is zero, nothing gets through the filter, so set + % coefficients up correctly. + + b = [cutoff, 0, 0]; + a = [1, 0, 0]; + return; + end + + % Compute biquad coefficients for lowpass filter + resonance = max(0.0, resonance); % can't go negative + g = 10.0^(0.05 * resonance); + d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); + + theta = pi * cutoff; + sn = 0.5 * d * sin(theta); + beta = 0.5 * (1 - sn) / (1 + sn); + gamma = (0.5 + beta) * cos(theta); + alpha = 0.25 * (0.5 + beta - gamma); + + b0 = 2 * alpha; + b1 = 2 * 2 * alpha; + b2 = 2 * alpha; + a1 = 2 * -gamma; + a2 = 2 * beta; + + b = [b0, b1, b2]; + a = [1.0, a1, a2]; +end + +function [b, a] = band_pass_2nd(f, Q, fs) + frequency = f/(fs/2); + % No negative frequencies allowed. + frequency = max(0.0, frequency); + + % Don't let Q go negative, which causes an unstable filter. + Q = max(0.0, Q); + + if frequency <= 0 || frequency >= 1 + % When the cutoff is zero, the z-transform approaches 0, if Q + % > 0. When both Q and cutoff are zero, the z-transform is + % pretty much undefined. What should we do in this case? + % For now, just make the filter 0. When the cutoff is 1, the + % z-transform also approaches 0. + b = [0, 0, 0]; + a = [1, 0, 0]; + return; + end + if (Q <= 0) + % When Q = 0, the above formulas have problems. If we + % look at the z-transform, we can see that the limit + % as Q->0 is 1, so set the filter that way. + b = [1, 0, 0]; + a = [1, 0, 0]; + return; + end + + w0 = pi * frequency; + alpha = sin(w0) / (2 * Q); + k = cos(w0); + + b0 = alpha; + b1 = 0; + b2 = -alpha; + a0 = 1 + alpha; + a1 = -2 * k; + a2 = 1 - alpha; + b = [b0 / a0 b1 / a0 b2 / a0]; + a = [1 a1 / a0 a2 / a0]; +end + +function [b, a] = notch_2nd(f, Q, fs) + frequency = f/(fs/2); + % Clip frequencies to between 0 and 1, inclusive. + frequency = max(0.0, min(frequency, 1.0)); + + % Don't let Q go negative, which causes an unstable filter. + Q = max(0.0, Q); + + if frequency <= 0 || frequency >= 1 + % When frequency is 0 or 1, the z-transform is 1. + b = [1, 0, 0]; + a = [1, 0, 0]; + return; + end + if Q <= 0 + % When Q = 0, the above formulas have problems. If we + % look at the z-transform, we can see that the limit + % as Q->0 is 0, so set the filter that way. + b = [0, 0, 0]; + a = [1, 0, 0]; + return; + end + + w0 = pi * frequency; + alpha = sin(w0) / (2 * Q); + k = cos(w0); + + b0 = 1; + b1 = -2 * k; + b2 = 1; + a0 = 1 + alpha; + a1 = -2 * k; + a2 = 1 - alpha; + + b = [b0 / a0 b1 / a0 b2 / a0]; + a = [1 a1 / a0 a2 / a0]; +end + +function [b, a] = low_shelf_2nd_google(f, db_gain, fs) + frequency = f/(fs/2); + % Clip frequencies to between 0 and 1, inclusive. + frequency = max(0.0, min(frequency, 1.0)); + + A = 10.0^(db_gain / 40); + + if (frequency == 1) + % The z-transform is a constant gain. + b = [A * A, 0, 0]; + a = [1, 0, 0]; + return; + end + if (frequency <= 0) + % When frequency is 0, the z-transform is 1. + b = [1, 0, 0]; + a = [1, 0, 0]; + return; + end + + w0 = pi * frequency; + S = 1; % filter slope (1 is max value) + alpha = 0.5 * sin(w0) * ... + sqrt((A + 1 / A) * (1 / S - 1) + 2); + k = cos(w0); + k2 = 2 * sqrt(A) * alpha; + a_plus_one = A + 1; + a_minus_one = A - 1; + + b0 = A * (a_plus_one - a_minus_one * k + k2); + b1 = 2 * A * (a_minus_one - a_plus_one * k); + b2 = A * (a_plus_one - a_minus_one * k - k2); + a0 = a_plus_one + a_minus_one * k + k2; + a1 = -2 * (a_minus_one + a_plus_one * k); + a2 = a_plus_one + a_minus_one * k - k2; + + b = [b0 / a0 b1 / a0 b2 / a0]; + a = [1 a1 / a0 a2 / a0]; +end + +function [b, a] = high_shelf_2nd_google(f, db_gain, fs) + frequency = f/(fs/2); + % Clip frequencies to between 0 and 1, inclusive. + frequency = max(0.0, min(frequency, 1.0)); + + A = 10.0^(db_gain / 40); + + if (frequency == 1) + % The z-transform is 1. + b = [1, 0, 0]; + a = [1, 0, 0]; + return; + end + if (frequency <= 0) + % When frequency = 0, the filter is just a gain, A^2. + b = [A * A, 0, 0]; + a = [1, 0, 0]; + return; + end + + w0 = pi * frequency; + S = 1; % filter slope (1 is max value) + alpha = 0.5 * sin(w0) * ... + sqrt((A + 1 / A) * (1 / S - 1) + 2); + k = cos(w0); + k2 = 2 * sqrt(A) * alpha; + a_plus_one = A + 1; + a_minus_one = A - 1; + + b0 = A * (a_plus_one + a_minus_one * k + k2); + b1 = -2 * A * (a_minus_one + a_plus_one * k); + b2 = A * (a_plus_one + a_minus_one * k - k2); + a0 = a_plus_one - a_minus_one * k + k2; + a1 = 2 * (a_minus_one - a_plus_one * k); + a2 = a_plus_one - a_minus_one * k - k2; + + b = [b0 / a0 b1 / a0 b2 / a0]; + a = [1 a1 / a0 a2 / a0]; +end + +function [b, a] = my_bilinear(sb, sa, fs) +if exist('OCTAVE_VERSION', 'builtin') + [b, a] = bilinear(sb, sa, 1/fs); +else + [b, a] = bilinear(sb, sa, fs); +end +end + +function sw = wmap(w, fs) +t = 1/fs; +sw = 2/t*tan(w*t/2); +end diff --git a/src/audio/eq_iir/tune/sof_eq_deploy_to_dut.m b/src/audio/eq_iir/tune/sof_eq_deploy_to_dut.m new file mode 100644 index 000000000000..7453fba8a840 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_deploy_to_dut.m @@ -0,0 +1,27 @@ +function status = sof_eq_deploy_to_dut(target, temp_file) +% deploy eq over ssh to a given dut with sof-eqctl +% the end target is expected to be some sort of unix system with sof-eqctl +% already installed. The system should also have ssh keys installed to prevent +% the toolchain from logging in + +ip = target.ip; +user = target.user; +dev = target.device; +ctrl = target.control; + +if isunix() || ismac() + transfer_template = "scp %s %s@%s:/tmp/sof-eq-config.txt"; + config_template = "ssh -t %s@%s sof-eqctl -Dhw:%d -n %d -s /tmp/sof-eq-config.txt"; + transfer_command = sprintf(transfer_template, temp_file, user, ip); + config_command = sprintf(config_template, user, ip, dev, ctrl); + command = sprintf("%s && %s", transfer_command, config_command); +endif + +if ispc() + % TODO +endif + +[status, output] = system(command); +disp(output); +end + diff --git a/src/audio/eq_iir/tune/sof_eq_fir_blob_decode.m b/src/audio/eq_iir/tune/sof_eq_fir_blob_decode.m new file mode 100644 index 000000000000..4d0ecbe52725 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_fir_blob_decode.m @@ -0,0 +1,121 @@ +function eq = sof_eq_fir_blob_decode(blob, resp_n) + +%% Decode a FIR EQ binary blob +% +% eq = eq_fir_blob_decode(blob, resp_n, fs, do_plot) +% +% blob - EQ setup blob 16 bit data vector +% resp_n - index of response to decode +% fs - sample rate, optional +% do_plot - set to 1 for frequency response plot, optional +% +% Returned struct fields +% b - FIR coefficients +% a - Always returns 1 with FIR +% channels_in_config - numbers of channels in blob +% assign_response - vector of EQ indexes assigned to channels +% size - length in bytes +% +% To decode a FIR blob, try first +% eq_blob_plot('../../topology/topology1/m4/eq_fir_coef_loudness.m4', 'fir'); +% eq_blob_plot('../../ctl/eq_fir_loudness.bin', 'fir'); +% eq_blob_plot('../../ctl/eq_fir_loudness.txt', 'fir'); + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 2 + verbose = 1; + resp_n = []; +else + verbose = 0; +end + +%% Get ABI information +[abi_bytes, nbytes_abi] = sof_get_abi(0); + +%% Defaults +eq.b = []; +eq.a = []; +eq.channels_in_config = 0; +eq.number_of_responses = 0; +eq.assign_response = []; + +%% Convert to 16 bits +blob16 = zeros(1, length(blob)*2); +for i = 1:length(blob) + i16 = 2*(i - 1) + 1; + blob16(i16) = bitand(blob(i), 65535); + blob16(i16 + 1) = bitshift(blob(i), -16); +end +blob16 = signedint(double(blob16), 16); + +%% Decode +abi = nbytes_abi / 2; +eq.size = blob16(abi + 1) + 65536*blob16(abi + 2); +eq.channels_in_config = blob16(abi + 3); +eq.number_of_responses = blob16(abi + 4); +reserved1 = blob16(abi + 5); +reserved2 = blob16(abi + 6); +reserved3 = blob16(abi + 7); +reserved4 = blob16(abi + 8); +reserved5 = blob16(abi + 9); +reserved6 = blob16(abi + 10); +reserved7 = blob16(abi + 11); +reserved8 = blob16(abi + 12); +eq.assign_response = blob16(abi + 13:abi + 13 + eq.channels_in_config-1); + +if verbose + fprintf('Blob size = %d\n', eq.size); + fprintf('Channels in config = %d\n', eq.channels_in_config); + fprintf('Number of responses = %d\n', eq.number_of_responses); + fprintf('Assign responses ='); + for i=1:length(eq.assign_response) + fprintf(' %d', eq.assign_response(i)); + end + fprintf('\n'); +end + +% Just header request +if isempty(resp_n) + eq.b = []; + eq.a = []; + return +end + +% Handle pass-through +if resp_n < 0 + eq.b = 1; + eq.a = 1; +end + +% Normal filter taps retrieve +if resp_n > eq.number_of_responses-1; + error('Request of non-available response'); +end + +n_blob_header = 12; +n_fir_header = 10; +b16 = blob16(abi + n_blob_header + eq.channels_in_config + 1:end); +j = 1; +for i=1:eq.number_of_responses + filter_length = b16(j); + output_shift = double(b16(j+1)); + if i-1 == resp_n + bi = b16(j+n_fir_header:j+n_fir_header+filter_length-1); + eq.b = 2^(-output_shift)*bi/32768; + end + j = j+filter_length+n_fir_header; +end +eq.a = 1; + +end + +function y = signedint(x, bits) +y = x; +idx = find(x > 2^(bits-1)-1); +y(idx) = x(idx)-2^bits; +end diff --git a/src/audio/eq_iir/tune/sof_eq_fir_blob_merge.m b/src/audio/eq_iir/tune/sof_eq_fir_blob_merge.m new file mode 100644 index 000000000000..705518c5f70d --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_fir_blob_merge.m @@ -0,0 +1,50 @@ +function bs = sof_eq_fir_blob_merge(channels_in_config, ... + number_of_responses_defined, assign_response, all_coefficients); + +%% Merge equalizer definition into a struct used by successive blob making +% functions. +% +% bs = sof_eq_fir_blob_merge(channels_in_config, number_of_responses_defined, ... +% assign_response, all_coefficients); +% + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +if length(assign_response) ~= channels_in_config + error("Incorrect length in EQ assign vector!"); +end + +bs.channels_in_config = channels_in_config; +bs.number_of_responses_defined = number_of_responses_defined; +bs.assign_response = assign_response; +bs.all_coefficients = all_coefficients; + +end diff --git a/src/audio/eq_iir/tune/sof_eq_fir_blob_pack.m b/src/audio/eq_iir/tune/sof_eq_fir_blob_pack.m new file mode 100644 index 000000000000..66bd3142fc55 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_fir_blob_pack.m @@ -0,0 +1,125 @@ +function blob8 = sof_eq_fir_blob_pack(bs, ipc_ver, endian) + +%% Pack equalizer struct to bytes +% +% blob8 = sof_eq_fir_blob_pack(bs, ipc_ver, endian) +% bs - blob struct +% ipc_ver - optional, use 3 or 4. Default is 3. +% endian - optional, use 'little' or 'big'. Defaults to little. +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2016 Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 2 + ipc_ver = 3; +end + +if nargin < 3 + endian = 'little'; +end + +%% Endianness of blob +switch lower(endian) + case 'little' + sh16 = [0 -8]; + sh32 = [0 -8 -16 -24]; + case 'big' + sh16 = [-8 0]; + sh32 = [-24 -16 -8 0]; + otherwise + error('Unknown endianness'); +end + +%% Channels count must be even +if mod(bs.channels_in_config, 2) > 0 + error("Channels # must be even"); +end + +%% Channels count and assign vector length must be the same +if bs.channels_in_config ~= length( bs.assign_response) + error("Channels # and response assign length must match"); +end + +%% Coefficients vector length must be multiple of 4 +len = length(bs.all_coefficients); +len_no_header = len - 10 * bs.number_of_responses_defined; +if mod(len_no_header, 4) > 0 + error("Coefficient data vector length must be multiple of 4"); +end + +%% Header format is +% uint32_t size; +% uint16_t channels_in_config; +% uint16_t number_of_responses; +% uint32_t reserved[4]; +% int16_t data[]; + +%% Pack as 16 bits +nh16 = 12+bs.channels_in_config; +h16 = zeros(1, nh16, 'int16'); +nc16 = length(bs.all_coefficients); +nb16 = ceil((nh16+nc16)/2)*2; +h16(1) = 2 * nb16; +h16(2) = 0; +h16(3) = bs.channels_in_config; +h16(4) = bs.number_of_responses_defined; +h16(5) = 0; +h16(6) = 0; +h16(7) = 0; +h16(8) = 0; +h16(9) = 0; +h16(10) = 0; +h16(11) = 0; +h16(12) = 0; +for i=1:bs.channels_in_config + h16(12+i) = bs.assign_response(i); +end + +%% Merge header and coefficients, make even number of int16 to make it +% multiple of int32 +blob16 = zeros(1,nb16, 'int16'); +blob16(1:nh16) = h16; +blob16(nh16+1:nh16+nc16) = int16(bs.all_coefficients); + +%% Pack as 8 bits +nbytes_data = nb16 * 2; + +%% Get ABI information +[abi_bytes, nbytes_abi] = sof_get_abi(nbytes_data, ipc_ver); + +%% Initialize uint8 array with correct size +nbytes = nbytes_abi + nbytes_data; +blob8 = zeros(1, nbytes, 'uint8'); + +%% Inset ABI header +blob8(1:nbytes_abi) = abi_bytes; +j = nbytes_abi + 1; + +%% Component data +for i = 1:length(blob16) + blob8(j:j+1) = w16b(blob16(i), sh16); + j = j+2; +end + +%% Done +fprintf('Blob size is %d bytes.\n', nbytes); + +end + +function bytes = w16b(word, sh) +bytes = uint8(zeros(1,2)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +end + +function bytes = w32b(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/eq_iir/tune/sof_eq_fir_blob_quant.m b/src/audio/eq_iir/tune/sof_eq_fir_blob_quant.m new file mode 100644 index 000000000000..1c8350ca738f --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_fir_blob_quant.m @@ -0,0 +1,94 @@ +function fbr = sof_eq_fir_blob_quant(b, bits, strip_trailing_zeros) + +%% Quantize FIR coefficients and return vector with length, +% out shift, and coefficients to be used in the setup blob. +% +% fbr = sof_eq_fir_blob_resp(b, bits) +% b - FIR coefficients +% bits - optional number of bits, defaults to 16 +% +% fbr - vector with length, in shift, out shift, and quantized coefficients +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +b = (b(:))'; + +if nargin < 3 + strip_trailing_zeros = 1; +end + +if nargin < 2 + bits = 16; +end + +%% Quantize +[bq, shift] = sof_eq_fir_quantize(b, bits); + +%% Check trailing zeros +nf = length(bq); +nz = nf; +while bq(nz) == 0 + nz = nz - 1; +end +if nz < nf && strip_trailing_zeros + nb = nz + 1; + fprintf(1, 'Note: Filter length was reduced '); + fprintf(1, 'to %d -> %d due to trailing zeros.\n', nf, nb); + bq = bq(1:nb); +else + nb = nf; +end + +%% Make length multiple of four (optimized FIR core) +mod4 = mod(nb, 4); +if mod4 > 0 + pad = zeros(1,4-mod4); + bqp = [bq pad]; + nnew = length(bqp); + fprintf(1,'Note: Filter length was %d, padded length into %d.\n', ... + nb, nnew); +else + fprintf(1,'Note: Filter length is %d\n', nb); + nnew = nb; + bqp = bq; +end + +%% Pack data into FIR coefficient format +% int16_t length +% int16_t out_shift +% uint32_t reserved[4] +% int16_t coef[] +fbr = [nnew shift 0 0 0 0 0 0 0 0 bqp]; + +end + +function [bq, shift] = sof_eq_fir_quantize(b, bits) + +% [bq, shift] = eq_fir_quantize(b, bits) +% +% Inputs +% b - FIR coefficients +% bits - number bits for 2s complement coefficient +% +% Outputs +% bq - quantized coefficients +% shift - shift right parameter to apply after FIR computation to +% compensate for coefficients scaling +% + +scale = 2^(bits-1); + +%% Output shift for coefficients +m = max(abs(b)); +shift = -ceil(log(m+1/scale)/log(2)); +bsr = b*2^shift; + +%% Quantize to Q1.bits-1 format, e.g. Q1.15 for 16 bits +bq = sof_eq_coef_quant(bsr, bits, bits-1); + +end diff --git a/src/audio/eq_iir/tune/sof_eq_iir_blob_decode.m b/src/audio/eq_iir/tune/sof_eq_iir_blob_decode.m new file mode 100644 index 000000000000..f54c88f63eb5 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_iir_blob_decode.m @@ -0,0 +1,122 @@ +function eq = sof_eq_iir_blob_decode(ublob, resp_n) + +%% Decode an IIR EQ binary blob +% +% eq = eq_fir_decode_blob(blobfn, resp_n) +% +% blob - EQ setup blob 32 bit data vector +% resp_n - index of response to decode +% fs - sample rate, optional +% do_plot - set to 1 for frequency response plot, optional +% +% Returned struct fields +% b - numerator coefficients +% a - denominator coefficients +% channels_in_config - numbers of channels in blob +% assign response - vector of EQ indexes assigned to channels +% +% To decode a IIR blob, try iirst +% eq_blob_plot('../../topology/topology1/m4/eq_iir_coef_loudness.m4', 'iir'); +% eq_blob_plot('../../ctl/eq_iir_loudness.bin', 'iir'); +% eq_blob_plot('../../ctl/eq_iir_loudness.txt', 'iir'); + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 2 + verbose = 1; + resp_n = []; +else + verbose = 0; +end + +%% Get ABI information +[abi_bytes, nbytes_abi] = sof_get_abi(0); + +%% Defaults +eq.b = []; +eq.a = []; +eq.channels_in_config = 0; +eq.number_of_responses = 0; +eq.assign_response = []; + +%% Decode +blob = double(ublob); +abi = nbytes_abi / 4; +eq.size = blob(abi + 1); +eq.channels_in_config = blob(abi + 2); +eq.number_of_responses = blob(abi + 3); +reserved1 = blob(abi + 4); +reserved2 = blob(abi + 5); +reserved3 = blob(abi + 6); +reserved4 = blob(abi + 7); +eq.assign_response = signedint(blob(abi + 8:abi + 8 + eq.channels_in_config - 1), 32); + +if verbose + fprintf('Blob size = %d\n', eq.size); + fprintf('Channels in config = %d\n', eq.channels_in_config); + fprintf('Number of responses = %d\n', eq.number_of_responses); + fprintf('Assign responses ='); + for i=1:length(eq.assign_response) + fprintf(' %d', eq.assign_response(i)); + end + fprintf('\n'); +end + +% Just header request +if isempty(resp_n) + eq.b = []; + eq.a = []; + return +end + +% Handle pass-through +if resp_n < 0 + eq.b = 1; + eq.a = 1; +end + +% Normal filter taps retrieve +if resp_n > eq.number_of_responses-1; + error('Request of non-available response'); +end + +n_blob_header = 7; +n_iir_header = 6; +n_iir_section = 7; + +j = abi + n_blob_header + eq.channels_in_config + 1; +eq.b = 1.0; +eq.a = 1.0; +for i=1:eq.number_of_responses + num_sections = blob(j); + section_length = num_sections * n_iir_section + n_iir_header; + if i-1 == resp_n + k = j + n_iir_header; + for j=1:num_sections + ai = signedint(blob(k+1:-1:k),32)'; + bi = signedint(blob(k+4:-1:k+2),32)'; + shifti = signedint(blob(k+5),32); + gaini = signedint(blob(k+6),16); + b0 = bi/2^30; + a0 = [1 -(ai/2^30)]; + gain = gaini/2^14; + b0 = b0 * 2^(-shifti) * gain; + eq.b = conv(eq.b, b0); + eq.a = conv(eq.a, a0); + k = k + n_iir_section; + end + end + j = j+section_length; +end + +end + +function y = signedint(x, bits) +y = x; +idx = find(x > 2^(bits-1)-1); +y(idx) = x(idx)-2^bits; +end diff --git a/src/audio/eq_iir/tune/sof_eq_iir_blob_merge.m b/src/audio/eq_iir/tune/sof_eq_iir_blob_merge.m new file mode 100644 index 000000000000..006ed83501c7 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_iir_blob_merge.m @@ -0,0 +1,52 @@ +function bs = sof_eq_iir_blob_merge(channels_in_config, ... + number_of_responses_defined, ... + assign_response, ... + all_coefficients); + +%% Merge equalizer definition into a struct used by successive blob making +% functions. +% +% bs = eq_iir_blob_merge(channels_in_config, number_of_responses_defined, ... +% assign_response, all_coefficients); +% + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +if length(assign_response) ~= channels_in_config + error("Assign response does not match channels count!"); +end + +bs.channels_in_config = channels_in_config; +bs.number_of_responses_defined = number_of_responses_defined; +bs.assign_response = assign_response; +bs.all_coefficients = all_coefficients; + +end diff --git a/src/audio/eq_iir/tune/sof_eq_iir_blob_pack.m b/src/audio/eq_iir/tune/sof_eq_iir_blob_pack.m new file mode 100644 index 000000000000..829a07e81843 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_iir_blob_pack.m @@ -0,0 +1,85 @@ +function blob8 = sof_eq_iir_blob_pack(bs, ipc_ver, endian) + +%% Pack equalizer struct to bytes +% +% blob8 = sof_eq_iir_blob_pack(bs, endian) +% bs - blob struct +% ipc_ver - optional, use 3 or 4. Default is 3. +% endian - optional, use 'little' or 'big'. Defaults to little. +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2016 Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 2 + ipc_ver = 3; +end + +if nargin < 3 + endian = 'little'; +end + +%% Channels count and assign vector lengths must be the same +if bs.channels_in_config ~= length( bs.assign_response) + error("Channels # and response assign length must match"); +end + +%% Shift values for little/big endian +switch lower(endian) + case 'little' + sh = [0 -8 -16 -24]; + case 'big' + sh = [-24 -16 -8 0]; + otherwise + error('Unknown endiannes'); +end + +%% Pack as 8 bits, header +nbytes_head = (7+bs.channels_in_config)*4; +nbytes_coef = length(bs.all_coefficients)*4; +nbytes_data = nbytes_head + nbytes_coef; + +%% Get ABI information +[abi_bytes, nbytes_abi] = sof_get_abi(nbytes_data, ipc_ver); + +%% Initialize correct size uint8 array +nbytes = nbytes_abi + nbytes_data; +blob8 = uint8(zeros(1,nbytes)); + +%% Insert ABI header +blob8(1:nbytes_abi) = abi_bytes; +j = nbytes_abi + 1; + +%% Component data +blob8(j:j+3) = w2b(nbytes_data, sh); j=j+4; +blob8(j:j+3) = w2b(bs.channels_in_config, sh); j=j+4; +blob8(j:j+3) = w2b(bs.number_of_responses_defined, sh); j=j+4; +blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved +blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved +blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved +blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved + +for i=1:bs.channels_in_config + blob8(j:j+3) = w2b(int32(bs.assign_response(i)), sh); + j=j+4; +end + +%% Pack coefficients +for i=1:length(bs.all_coefficients) + blob8(j:j+3) = w2b(int32(bs.all_coefficients(i)), sh); + j=j+4; +end +fprintf('Blob size is %d bytes.\n', nbytes); + +end + +function bytes = w2b(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/eq_iir/tune/sof_eq_iir_blob_quant.m b/src/audio/eq_iir/tune/sof_eq_iir_blob_quant.m new file mode 100644 index 000000000000..8cbb71602722 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_iir_blob_quant.m @@ -0,0 +1,144 @@ +function iir_resp = sof_eq_iir_blob_quant(eq_z, eq_p, eq_k) + +%% Convert IIR coefficients to 2nd order sections and quantize +% +% iir_resp = sof_eq_iir_blob_quant(z, p, k) +% +% z - zeros +% p - poles +% k - gain +% +% iir_resp - vector to setup an IIR equalizer with number of sections, shifts, +% and quantized coefficients +% + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +%% Settings +bits_iir = 32; % Q2.30 +qf_iir = 30; +bits_gain = 16; % Q2.14 +qf_gain = 14; +scale_max = -6; % dB, scale biquads peak gain to this +plot_pz = 0; +plot_fr = 0; + +%% Convert IIR to 2nd order sections +% This a simple implementation of zp2sos() function. It is not used here due +% to utilization of rather strong scaling and resulting low SNR with the +% available word length in EQ in SOF. This poles and zeros allocation to +% biquads is base only in ascending sort of angular frequency. +sz = length(eq_z); +sp = length(eq_p); +sk = length(eq_k); +nb = max(sz, sp)/2; +az = angle(eq_z); +ap = angle(eq_p); +[~, iz] = sort(abs(az)); +[~, ip] = sort(abs(ap)); +eq_z = eq_z(iz); +eq_p = eq_p(ip); +sos = zeros(nb, 6); +for i = 1:nb + j = 2*(i-1)+1; + if i == 1 + [b, a] = zp2tf(eq_z(j:j+1), eq_p(j:j+1), eq_k); + else + [b, a] = zp2tf(eq_z(j:j+1), eq_p(j:j+1), 1); + end + sos(i,1:3) = b; + sos(i,4:6) = a; +end +gain = 1; + +%% Convert 2nd order sections to SOF parameters format and scale the biquads +% with criteria below (Gain max -6 dB at any frequency). Then calculate +% scaling shifts and finally gain multiplier for output. +sz = size(sos); +nbr_sections = sz(1); +n_section_header = 6; % Two plus reserved[4] in ABI +n_section = 7; +iir_resp = int32(zeros(1,n_section_header+nbr_sections*n_section)); +iir_resp(1) = nbr_sections; +iir_resp(2) = nbr_sections; % Note: All sections in series + +scale_max_lin = 10^(scale_max/20); +for n=1:nbr_sections + b = sos(n,1:3); + a = sos(n,4:6); + if plot_pz + figure + zplane(b,a); + tstr = sprintf('SOS %d poles and zeros', n); + title(tstr); + end + + np = 1024; + [h, w] = freqz(b, a, np); + hm = max(abs(h)); + scale = scale_max_lin/hm; + gain_remain = 1/scale; + gain = gain*gain_remain; + b = b * scale; + ma = max(abs(a)); + mb = max(abs(b)); + if plot_fr + figure + [h, w] = freqz(b, a, np); + plot(w, 20*log10(abs(h))); grid on; + xlabel('Frequency (w)'); + ylabel('Magnitude (dB)'); + tstr = sprintf('SOS %d frequency response', n); + title(tstr); + end + + %% Apply remaining gain at last section output + if n == nbr_sections + section_shift = -fix(log(gain)/log(2)); + section_gain= gain/2^(-section_shift); + else + section_shift = 0; + section_gain = 1; + end + + %% Note: Invert sign of a! + %% Note: a(1) is omitted, it's always 1 + m = n_section_header+(n-1)*n_section+1; + iir_resp(m:m+1) = sof_eq_coef_quant(-a(3:-1:2), bits_iir, qf_iir); + iir_resp(m+2:m+4) = sof_eq_coef_quant( b(3:-1:1), bits_iir, qf_iir); + iir_resp(m+5) = section_shift; + iir_resp(m+6) = sof_eq_coef_quant( section_gain, bits_gain, qf_gain); + + %fprintf('sec=%d, shift=%d, gain=%f\n', n, section_shift, section_gain); + +end + +end diff --git a/src/audio/eq_iir/tune/sof_eq_load_dsp_ini.m b/src/audio/eq_iir/tune/sof_eq_load_dsp_ini.m new file mode 100644 index 000000000000..d252f5c7827b --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_load_dsp_ini.m @@ -0,0 +1,110 @@ +function sof_eq_load_dsp_ini(h, evnt) + +udata = get(h, "userdata"); +EQ = udata.EQ; +preamble_offset = 4; +config_size = 4; +n_channels = 2; +eq = sof_eq_defaults(); + +[name, path, idx] = uigetfile("*.ini"); +if name == 0 + % cancelled + return; +endif + +% load file +f = fopen(strcat(path, name)); + +% locate eq2 section +do + l = fgets(f); +until strcmp(l, "[eq2]\n") || l == -1 + +if l == -1 + errordlg("eq2 section not found.\n Please check input file."); + return; +endif + +config = []; + +% load config +do + line = fgets(f); + if line == -1 + break; + endif + [v, count] = sscanf(line, "input_%d = %d"); + if count == 2 + config = [config, [v(1); v(2)]]; + endif +until strcmp("\n", line) + +fclose(f); + +% push config to GUI + +% set all fields to off, we will run the callback at the end to avoid graphics flicker +for channel = 1:2 + for i = 1:8 + enable_switch = EQ(i, channel).enable_switch; + set(enable_switch, "value", 0); + endfor +endfor + + % cras type (+1 since its 0 index); sof type +cras_filter2sof_filter = [ ... + -1, ... % none + eq.PEQ_LP2G, ... + eq.PEQ_HP2G, ... + eq.PEQ_BP2, ... + eq.PEQ_LS2G, ... + eq.PEQ_HS2G, ... + eq.PEQ_PN2, ... + eq.PEQ_NC2, ... + -1, ... % allpass, not implemented in audio-tuning or in SOF +]; + +config_item2field_name = { + "type", + "freq", + "Q", + "gain", +}; + +for r = config + index = r(1) - preamble_offset; + config_index = idivide(index, config_size * n_channels, "floor") + 1; + config_item = rem(index, config_size) + 1; + channel = rem(idivide(index, config_size, "floor"), n_channels) + 1; + field_name = config_item2field_name{config_item}; + filter = EQ(config_index, channel); + section = getfield(filter, field_name); + + if strcmp(field_name, "type") && cras_filter2sof_filter(r(2) + 1) == -1 + % invalid filter, skip + continue; + endif + + if strcmp(field_name, "type") + % no need to run this callback since it will get called when we run the + % enable_switch callback at the end + set(section.dropdown, "value", cras_filter2sof_filter(r(2) + 1)); + set(filter.enable_switch, "value", 1); + else + set(section.edit, "string", num2str(r(2))); + % run callback to update slider value + func = get(section.edit, "callback"); + func(section.edit, 0); + endif +endfor + +% now that all values are set lets update eveyone's visibility +for channel = 1:2 + for i = 1:8 + enable_switch = EQ(i, channel).enable_switch; + func = get(enable_switch, "callback"); + func(enable_switch, 0); + endfor +endfor +end diff --git a/src/audio/eq_iir/tune/sof_eq_norm.m b/src/audio/eq_iir/tune/sof_eq_norm.m new file mode 100644 index 000000000000..abcaf4e39246 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_norm.m @@ -0,0 +1,117 @@ +function eq = sof_eq_norm(eq) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +%% Normalize loudness of EQ by computing weighted average of linear +% response. Find scale need to make the average one. +w_lin = level_norm_fweight(eq.f); +m_lin_fir = 10.^(eq.fir_eq_db/20); +m_lin_iir = 10.^(eq.iir_eq_db/20); +i1k = find(eq.f > 1e3, 1, 'first') - 1; +m_max_fir = max(eq.fir_eq_db); +m_max_iir = max(eq.iir_eq_db); +sens_fir = sum(m_lin_fir.*w_lin)/sum(w_lin); +sens_iir = sum(m_lin_iir.*w_lin)/sum(w_lin); +g_offs_iir = 10^(eq.iir_norm_offs_db/20); +g_offs_fir = 10^(eq.fir_norm_offs_db/20); + +%% Determine scaling gain +switch lower(eq.iir_norm_type) + case 'loudness' + g_iir = 1/sens_iir; + case '1k' + g_iir = 1/m_lin_iir(i1k); + case 'peak' + g_iir = 10^(-m_max_iir/20); + otherwise + error('Requested IIR normalization is not supported'); +end +switch lower(eq.fir_norm_type) + case 'loudness' + g_fir = 1/sens_fir; + case '1k' + g_fir = 1/m_lin_fir(i1k); + case 'peak' + g_fir = 10^(-m_max_fir/20); + otherwise + error('Requested FIR normalization is not supported'); +end + +%% Adjust FIR and IIR gains if enabled +if eq.enable_fir + eq.b_fir = eq.b_fir * g_fir * g_offs_fir; +end +if eq.enable_iir + eq.p_k = eq.p_k * g_iir * g_offs_iir; +end + +%% Re-compute response after adjusting gain +eq = sof_eq_compute_tot_response(eq); + +end + +function m_lin = level_norm_fweight(f) + +%% w_lin = level_norm_fweight(f) +% +% Provides frequency weight that is useful in normalization of +% loudness of effect like equalizers. The weight consists of pink noise +% like spectral shape that attenuates higher frequencies 3 dB per +% octave. The low frequencies are shaped by 2nd order high-pass +% response at 20 Hz and higher frequencies by 3rd order low-pass at 20 +% kHz. +% +% Note: This weight may have similarity with a standard defined test signal +% characteristic for evaluating music player output levels but this is not +% an implementation of it. This weight may help in avoiding a designed EQ to +% exceed safe playback levels in othervise compliant device. +% +% Input f - frequencies vector in Hz +% +% Output w_lin - weight curve, aligned to peak of 1.0 in the requested f +% + +[z_hp, p_hp] = butter(2, 22.4,'high','s'); +[z_lp, p_lp] = butter(3, 22.4e3,'s'); +z_bp = conv(z_hp, z_lp); +p_bp = conv(p_hp, p_lp); +h = freqs(z_bp, p_bp, f); +m0 = 20*log10(abs(h)); +noct = log(max(f)/min(f))/log(2); +att = 3*noct; +nf = length(f); +w = zeros(1,nf); +w = w - linspace(0,att,nf); +m = m0 + w; +m = m-max(m); +m_lin = 10.^(m/20); + +end diff --git a/src/audio/eq_iir/tune/sof_eq_paths.m b/src/audio/eq_iir/tune/sof_eq_paths.m new file mode 100644 index 000000000000..359451926fe9 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_paths.m @@ -0,0 +1,18 @@ +function sof_eq_paths(enable) + +% sof_eq_paths(enable) +% enable - set to 1 to enable needed search path +% set to 0 to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + + common = '../../../../tools/tune/common'; + if enable + addpath(common); + else + rmpath(common); + end +end diff --git a/src/audio/eq_iir/tune/sof_eq_plot.m b/src/audio/eq_iir/tune/sof_eq_plot.m new file mode 100644 index 000000000000..4a11cf25c25f --- /dev/null +++ b/src/audio/eq_iir/tune/sof_eq_plot.m @@ -0,0 +1,190 @@ +function sof_eq_plot(eq, fn) + +%% +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +if nargin < 2 + fn = 1; +end + +%% Raw measured response +if length(eq.raw_m_db) > 2 + % Raw without EQ + fh=figure(fn); fn = fn+1; + f1 = min(eq.raw_f); + f2 = max(eq.raw_f); + i1 = find(eq.f > f1, 1, 'first') - 1; + i2 = find(eq.f > f2, 1, 'first') - 1; + idx = i1:i2; + semilogx(eq.f(idx), eq.m_db(idx), eq.f(idx), eq.m_db_s(idx)); + grid on; + ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 20)]); + legend('Raw','Smoothed'); + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + tstr = sprintf('Imported frequency response: %s', eq.name); + title(tstr); + + % Simulated with EQ + fh=figure(fn); fn = fn+1; + semilogx(eq.f(idx), eq.m_eqd(idx), eq.f(idx), eq.m_eqd_s(idx)); + grid on; + ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 20)]); + legend('Raw','Smoothed'); + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + tstr = sprintf('Simulated frequency response: %s', eq.name); + title(tstr); +end + +%% Filter responses +fh=figure(fn); fn = fn+1; +i1k = find(eq.f > 1e3, 1, 'first') - 1; +offs_tot = -eq.tot_eq_db(i1k); +offs_fir = -eq.fir_eq_db(i1k); +offs_iir = -eq.iir_eq_db(i1k); +if eq.enable_fir && eq.enable_iir + semilogx(eq.f, eq.err_db_s, eq.f, eq.tot_eq_db + offs_tot, ... + eq.f, eq.iir_eq_db + offs_iir, '--',... + eq.f, eq.fir_eq_db + offs_fir, '--'); + legend('Target', 'Combined', 'IIR', 'FIR', 'Location', 'NorthWest'); + eq.diff_db = eq.tot_eq_db + offs_tot - eq.err_db_s; +end +if eq.enable_fir && eq.enable_iir == 0 + semilogx(eq.f, eq.err_db_s, eq.f, eq.fir_eq_db + offs_fir); + legend('Target', 'FIR', 'Location', 'NorthWest'); + eq.diff_db = eq.fir_eq_db + offs_fir - eq.err_db_s; +end +if eq.enable_fir == 0 && eq.enable_iir + semilogx(eq.f, eq.err_db_s, eq.f, eq.iir_eq_db + offs_iir); + legend('Target', 'IIR', 'Location', 'NorthWest'); + eq.diff_db = eq.iir_eq_db + offs_iir - eq.err_db_s; +end +grid on; +ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 40)]); +xlabel('Frequency (Hz)'); +ylabel('Magnitude (dB)'); +tstr = sprintf('Filter target vs. achieved response: %s', eq.name); +title(tstr); + +fh=figure(fn); fn = fn+1; +semilogx(eq.f, eq.diff_db) +grid on; +ax=axis; axis([eq.p_fmin eq.p_fmax -5 5]); +xlabel('Frequency (Hz)'); +ylabel('Magnitude (dB)'); +tstr = sprintf('Response difference mean abs %.4f dB: %s', mean(abs(eq.diff_db)), eq.name); +title(tstr); + +%% FIR filter +if length(eq.b_fir) > 1 + % Response + fh=figure(fn); fn = fn+1; + semilogx(eq.f, eq.fir_eq_db); + grid on; + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + ax = axis; axis([eq.p_fmin eq.p_fmax max(ax(3:4), -40)]); + tstr = sprintf('FIR filter absolute response: %s', eq.name); + title(tstr); + + % Impulse response / coefficients + fh=figure(fn); fn = fn+1; + stem(eq.b_fir); + grid on; + xlabel('Coefficient #'); + ylabel('Coefficient value'); + tstr = sprintf('FIR filter impulse response: %s', eq.name); + title(tstr); + +end + +%% IIR filter +if length(eq.p_z) > 1 || length(eq.p_p) > 1 + % Response + fh=figure(fn); fn = fn+1; + semilogx(eq.f, eq.iir_eq_db); + grid on; + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + ax = axis; axis([eq.p_fmin eq.p_fmax max(ax(3:4), -40)]); + tstr = sprintf('IIR filter absolute response: %s', eq.name); + title(tstr); + + % Polar + fh=figure(fn); fn = fn+1; + zplane(eq.p_z, eq.p_p); + grid on; + tstr = sprintf('IIR zeros and poles: %s', eq.name); + title(tstr); + + % Impulse + ti = 50e-3; + x = zeros(1, ti * round(eq.fs)); + x(1) = 1; + sos = zp2sos(eq.p_z, eq.p_p, eq.p_k); + y = sosfilt(sos, x); + fh=figure(fn); fn = fn+1; + t = (0:(length(x)-1)) / eq.fs; + plot(t, y); + grid on; + xlabel('Time (s)'); + ylabel('Sample value'); + tstr = sprintf('IIR filter impulse response: %s', eq.name); + title(tstr); +end + +%% Group delay +if ~exist('OCTAVE_VERSION', 'builtin') + % Skip plot if running in Octave due to incorrect result + fh=figure(fn); fn = fn+1; + if eq.enable_fir && eq.enable_iir + semilogx(eq.f, eq.tot_eq_gd * 1e3, ... + eq.f, eq.fir_eq_gd * 1e3, '--', ... + eq.f, eq.iir_eq_gd * 1e3, '--'); + legend('Combined','FIR','IIR'); + end + if eq.enable_fir && eq.enable_iir == 0 + semilogx(eq.f, eq.fir_eq_gd * 1e3); + legend('FIR'); + end + if eq.enable_fir == 0 && eq.enable_iir + semilogx(eq.f, eq.iir_eq_gd * 1e3); + legend('IIR'); + end + grid on; + xlabel('Frequency (Hz)'); + ylabel('Group delay (ms)'); + ax = axis; axis([eq.p_fmin eq.p_fmax ax(3:4)]); + tstr = sprintf('Filter group delay: %s', eq.name); + title(tstr); +end + +end diff --git a/src/audio/eq_iir/tune/sof_example_fir_eq.m b/src/audio/eq_iir/tune/sof_example_fir_eq.m new file mode 100644 index 000000000000..a1e47396ce7e --- /dev/null +++ b/src/audio/eq_iir/tune/sof_example_fir_eq.m @@ -0,0 +1,252 @@ +%% Design demo EQs and bundle them to parameter block + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function sof_example_fir_eq() + +%% Common definitions +fs = 48e3; +sof_tools = '../../../../tools'; +sof_ctl = fullfile(sof_tools, 'ctl'); +sof_tplg = fullfile(sof_tools, 'topology'); +fn.cpath3 = fullfile(sof_ctl, 'ipc3/eq_fir'); +fn.cpath4 = fullfile(sof_ctl, 'ipc4/eq_fir'); +fn.tpath1 = fullfile(sof_tplg, 'topology1/m4'); +fn.tpath2 = fullfile(sof_tplg, 'topology2/include/components/eqfir'); +fn.priv = 'DEF_EQFIR_PRIV'; + +sof_eq_paths(1); + +%% ------------------- +%% Example 1: Loudness +%% ------------------- +fn.bin = 'loudness.bin'; +fn.txt = 'loudness.txt'; +fn.tplg1 = 'eq_fir_coef_loudness.m4'; +fn.tplg2 = 'loudness.conf'; +comment = 'Loudness effect, created with example_fir_eq.m'; + +%% Design FIR loudness equalizer +eq_loud = loudness_fir_eq(fs); + +%% Define a passthru EQ with one tap +b_pass = 1; + +%% Quantize filter coefficients for both equalizers +bq_pass = sof_eq_fir_blob_quant(b_pass); +bq_loud = sof_eq_fir_blob_quant(eq_loud.b_fir); + +%% Build blob +channels_in_config = 4; % Setup max 4 channels EQ +assign_response = [1 1 1 1]; % Switch to response #1 +num_responses = 2; % Two responses pass, loud +bm = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [ bq_pass bq_loud ]); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment); + +%% ------------------- +%% Example 2: Mid boost +%% ------------------- +fn.bin = 'mid.bin'; +fn.txt = 'mid.txt'; +fn.tplg1 = 'eq_fir_coef_mid.m4'; +fn.tplg2 = 'midboost.conf'; +comment = 'Mid boost, created with example_fir_eq.m'; + +%% Define mid frequencies boost EQ +eq_mid = midboost_fir_eq(fs); + +%% Quantize filter coefficients for both equalizers +bq_pass = sof_eq_fir_blob_quant(eq_mid.b_fir); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % One response: pass +bm = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_pass); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment); + +%% ------------------- +%% Example 3: Flat EQ +%% ------------------- +fn.bin = 'flat.bin'; +fn.txt = 'flat.txt'; +fn.tplg1 = 'eq_fir_coef_flat.m4'; +fn.tplg2 = 'flat.conf'; +comment = 'Flat response, created with example_fir_eq.m'; + +%% Define a passthru EQ with one tap +b_pass = 1; + +%% Quantize filter coefficients for both equalizers +bq_pass = sof_eq_fir_blob_quant(b_pass); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % One response: pass +bm = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_pass); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment); + +%% -------------------------- +%% Example 4: Pass-through EQ +%% -------------------------- +fn.bin = 'pass.bin'; +fn.txt = 'pass.txt'; +fn.tplg1 = 'eq_fir_coef_pass.m4'; +fn.tplg2 = 'passthrough.conf'; +comment = 'Pass-through response, created with example_fir_eq.m'; + +%% Define a passthru EQ with one tap +b_pass = 1; + +%% Quantize filter coefficients for both equalizers +bq_pass = sof_eq_fir_blob_quant(b_pass); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [-1 -1]; % Switch to response #0 +num_responses = 1; % One response: pass +bm = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_pass); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment); + + +%% -------------------------- +%% Done. +%% -------------------------- + +sof_eq_paths(0); + +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = loudness_fir_eq(fs) + +%% Derived from Fletcher-Munson curves for 80 and 60 phon +f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ... + 68,72,76,81,85,90,96,102,108,114,121,128,136,144,153,162,171, ... + 182,192,204,216,229,243,257,273,289,306,324,344,364,386,409, ... + 434,460,487,516,547,580,614,651,690,731,775,821,870,922,977, ... + 1036,1098,1163,1233,1307,1385,1467,1555,1648,1747,1851,1962, ... + 2079,2203,2335,2474,2622,2779,2945,3121,3308,3505,3715,3937, ... + 4172,4421,4686,4966,5263,5577,5910,6264,6638,7035,7455,7901, ... + 8373,8873,9404,9966,10561,11193,11861,12570,13322,14118,14962, ... + 15856,16803,17808,18872,20000]; + +m = [ 0.00,-0.13,-0.27,-0.39,-0.52,-0.64,-0.77,-0.89,-1.02,-1.16, ... + -1.31,-1.46,-1.61,-1.76,-1.91,-2.07,-2.24,-2.43,-2.64,-2.85, ... + -3.04,-3.21,-3.35,-3.48,-3.62,-3.78,-3.96,-4.16,-4.35,-4.54, ... + -4.72,-4.90,-5.08,-5.26,-5.45,-5.64,-5.83,-6.02,-6.19,-6.37, ... + -6.57,-6.77,-6.98,-7.19,-7.40,-7.58,-7.76,-7.92,-8.08,-8.25, ... + -8.43,-8.60,-8.76,-8.92,-9.08,-9.23,-9.38,-9.54,-9.69,-9.84, ... + -9.97,-10.09,-10.18,-10.26,-10.33,-10.38,-10.43,-10.48,-10.54, ... + -10.61,-10.70,-10.78,-10.85,-10.91,-10.95,-10.98,-11.02, ... + -11.05,-11.07,-11.10,-11.11,-11.11,-11.10,-11.10,-11.11, ... + -11.14,-11.17,-11.20,-11.21,-11.22,-11.21,-11.20,-11.20, ... + -11.21,-11.21,-11.20,-11.17,-11.11,-11.02,-10.91,-10.78, ... + -10.63,-10.46,-10.25,-10.00,-9.72,-9.39,-9.02,-8.62,-8.19, ... + -7.73,-7.25,-6.75,-6.25,-5.75,-5.28,-4.87,-4.54,-4.33,-4.30]; + +%% Design EQ +eq = sof_eq_defaults(); +eq.fs = fs; +eq.target_f = f; % Set EQ frequency response target: frequencies Hz +eq.target_m_db = m; % Set EQ frequency response target: magnitudues dB +eq.fir_norm_type = 'loudness'; % Normalize criteria can be loudness/peak/1k +eq.fir_norm_offs_db = 0; % Offset in dB to normalize + +eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one +eq.fir_beta = 4.0; % Use with care, low value can corrupt +eq.fir_length = 250; % Long filter (test large IPC messages) +eq.fir_autoband = 0; % Select manually frequency limits +eq.fmin_fir = 100; % Equalization starts from 100 Hz +eq.fmax_fir = 20e3; % Equalization ends at 20 kHz +eq.fir_minph = 0; % Check result carefully if 1 is used, 0 is safe +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + +function eq = midboost_fir_eq(fs) + +eq = sof_eq_defaults(); + +eq.parametric_target_response = [ ... + eq.PEQ_LS2 1200 -12 NaN ; ... + eq.PEQ_HS2 7000 -12 NaN ; ... + ]; + +%% Design EQ +eq.fs = fs; +eq.fir_norm_type = 'peak'; % Can be loudness/peak/1k to select normalize criteria +eq.fir_norm_offs_db = 0; % E.g. -1 would leave 1 dB headroom if used with peak + +eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one +eq.fir_beta = 3.5; % Use with care, low value can corrupt +eq.fir_length = 39; % At limit of xtensa-gcc build speed +eq.fir_autoband = 0; % Select manually frequency limits +eq.fmin_fir = 100; % Equalization starts from 100 Hz +eq.fmax_fir = 20e3; % Equalization ends at 20 kHz +eq.fir_minph = 1; % If no linear phase required can test with 1 +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + +% Pack and write file common function for all exports +function sof_eq_pack_export(bm, fn, note) + +howto = 'cd src/audio/eq_iir/tune; octave --no-window-system sof_example_fir_eq.m'; +bp = sof_eq_fir_blob_pack(bm, 3); % IPC3 +if ~isempty(fn.bin) + sof_ucm_blob_write(fullfile(fn.cpath3, fn.bin), bp); +end +if ~isempty(fn.txt) + sof_alsactl_write(fullfile(fn.cpath3, fn.txt), bp); +end +if ~isempty(fn.tplg1) + sof_tplg_write(fullfile(fn.tpath1, fn.tplg1), bp, fn.priv, note, howto); +end + +bp = sof_eq_fir_blob_pack(bm, 4); % IPC4 +if ~isempty(fn.bin) + sof_ucm_blob_write(fullfile(fn.cpath4, fn.bin), bp); +end +if ~isempty(fn.txt) + sof_alsactl_write(fullfile(fn.cpath4, fn.txt), bp); +end +if ~isempty(fn.tplg2) + sof_tplg2_write(fullfile(fn.tpath2, fn.tplg2), bp, 'fir_eq', note, howto); +end + +end diff --git a/src/audio/eq_iir/tune/sof_example_iir_bandsplit.m b/src/audio/eq_iir/tune/sof_example_iir_bandsplit.m new file mode 100644 index 000000000000..37a34342c678 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_example_iir_bandsplit.m @@ -0,0 +1,143 @@ +%% Design effect EQs and bundle them to parameter block + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function sof_example_iir_bandsplit() + +%% Common definitions +fs = 48e3; +sof_tools = '../../../../tools'; +tpath = fullfile(sof_tools, 'topology/topology1/m4'); +cpath = fullfile(sof_tools, 'ctl/ipc3/eq_iir'); +priv = 'DEF_EQIIR_PRIV'; + +sof_eq_paths(1); + +%% -------------------------------------------------- +%% Example: Band-split 2ch to 4ch low and high bands +%% -------------------------------------------------- +blob_fn = fullfile(cpath, 'bandsplit.bin'); +alsa_fn = fullfile(cpath, 'bandsplit.txt'); +tplg_fn = fullfile(tpath, 'eq_iir_bandsplit.m4'); +comment = 'Bandsplit, created with example_iir_bandsplit.m'; + +%% Design IIR loudness equalizer +eq_lo = lo_band_iir(fs); +eq_hi = hi_band_iir(fs); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_lo = sof_eq_iir_blob_quant(eq_lo.p_z, eq_lo.p_p, eq_lo.p_k); +bq_hi = sof_eq_iir_blob_quant(eq_hi.p_z, eq_hi.p_p, eq_hi.p_k); + +%% Build blob +channels_in_config = 4; % Setup max 4 channels EQ +assign_response = [0 0 1 1]; % Order: lo, lo, hi, hi +num_responses = 2; % Two responses: lo, hi +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_lo bq_hi]); + +%% Pack and write file +sof_eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, priv, comment) + +%% ------------------------------------ +%% Done. +%% ------------------------------------ + +sof_eq_paths(0); +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = lo_band_iir(fs) + + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 0; + +%% Manually setup low-shelf and high shelf parametric equalizers +% +% Parametric EQs are PEQ_HP1, PEQ_HP2, PEQ_LP1, PEQ_LP2, PEQ_LS1, +% PEQ_LS2, PEQ_HS1, PEQ_HS2 = 8, PEQ_PN2, PEQ_LP4, and PEQ_HP4. +% +% Parametric EQs take as second argument the cutoff frequency in Hz +% and as second argument a dB value (or NaN when not applicable) . The +% Third argument is a Q-value (or NaN when not applicable). + +% Low-pass at 2 kHz, add a high-pass at 80 Hz for a small woofer +eq.peq = [ ... + eq.PEQ_HP2 80 NaN NaN ; ... + eq.PEQ_LP2 2000 NaN NaN ; ... + ]; + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + +function eq = hi_band_iir(fs) + + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 0; + +%% Manually setup low-shelf and high shelf parametric equalizers +% +% Parametric EQs are PEQ_HP1, PEQ_HP2, PEQ_LP1, PEQ_LP2, PEQ_LS1, +% PEQ_LS2, PEQ_HS1, PEQ_HS2 = 8, PEQ_PN2, PEQ_LP4, and PEQ_HP4. +% +% Parametric EQs take as second argument the cutoff frequency in Hz +% and as second argument a dB value (or NaN when not applicable) . The +% Third argument is a Q-value (or NaN when not applicable). + +% High-pass at 2 kHz for a tweeter +eq.peq = [ ... + eq.PEQ_HP2 2000 NaN NaN ; ... + ]; + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + + + +% Pack and write file common function for all exports +function sof_eq_pack_export(bm, bin_fn, ascii_fn, tplg_fn, priv, note) + +bp = sof_eq_iir_blob_pack(bm); + +if ~isempty(bin_fn) + sof_ucm_blob_write(bin_fn, bp); +end + +if ~isempty(ascii_fn) + sof_alsactl_write(ascii_fn, bp); +end + +if ~isempty(tplg_fn) + sof_tplg_write(tplg_fn, bp, priv, note); +end + +end diff --git a/src/audio/eq_iir/tune/sof_example_iir_eq.m b/src/audio/eq_iir/tune/sof_example_iir_eq.m new file mode 100644 index 000000000000..eef0f2751300 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_example_iir_eq.m @@ -0,0 +1,380 @@ +%% Design effect EQs and bundle them to parameter block + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2026, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function sof_example_iir_eq() + +%% Common definitions +fs = 48e3; +sof_tools = '../../../../tools'; +sof_ctl = fullfile(sof_tools, 'ctl'); +sof_tplg = fullfile(sof_tools, 'topology'); +fn.cpath3 = fullfile(sof_ctl, 'ipc3/eq_iir'); +fn.cpath4 = fullfile(sof_ctl, 'ipc4/eq_iir'); +fn.tpath1 = fullfile(sof_tplg, 'topology1/m4'); +fn.tpath2 = fullfile(sof_tplg, 'topology2/include/components/eqiir'); +fn.priv = 'DEF_EQIIR_PRIV'; + +sof_eq_paths(1); + +%% ------------------- +%% Example 1: Loudness +%% ------------------- +fn.bin = 'loudness.bin'; +fn.txt = 'loudness.txt'; +fn.tplg1 = 'eq_iir_coef_loudness.m4'; +fn.tplg2 = 'loudness.conf'; +comment = 'Loudness effect, created with sof_example_iir_eq.m'; + +%% Design IIR loudness equalizer +eq_loud = loudness_iir_eq(fs); + +%% Define a passthru IIR EQ equalizer +[z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_pass = sof_eq_iir_blob_quant(z_pass, p_pass, k_pass); +bq_loud = sof_eq_iir_blob_quant(eq_loud.p_z, eq_loud.p_p, eq_loud.p_k); + +%% Build blob +channels_in_config = 4; % Setup max 4 channels EQ +assign_response = [1 1 1 1]; % Switch to response #1 +num_responses = 2; % Two responses: pass, loud +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_pass bq_loud]); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment) + +%% ------------------------------------ +%% Example 2: Bass boost +%% ------------------------------------ +fn.bin = 'bassboost.bin'; +fn.txt = 'bassboost.txt'; +fn.tplg1 = 'eq_iir_coef_bassboost.m4'; +fn.tplg2 = 'bassboost.conf'; +comment = 'Bass boost, created with sof_example_iir_eq.m'; + +%% Design IIR bass boost equalizer +eq_bass = bassboost_iir_eq(fs); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_bass = sof_eq_iir_blob_quant(eq_bass.p_z, eq_bass.p_p, eq_bass.p_k); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % One responses: bass +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_bass); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment) + +%% ------------------------------------ +%% Example 3: Band-pass +%% ------------------------------------ +fn.bin = 'bandpass.bin'; +fn.txt = 'bandpass.txt'; +fn.tplg1 = 'eq_iir_coef_bandpass.m4'; +fn.tplg2 = 'bandpass.conf'; +comment = 'Band-pass, created with sof_example_iir_eq.m'; + +%% Design IIR bass boost equalizer +eq_band = bandpass_iir_eq(fs); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_band = sof_eq_iir_blob_quant(eq_band.p_z, eq_band.p_p, eq_band.p_k); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % One responses: bandpass +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_band); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment) + +%% ------------------- +%% Example 4: Flat IIR +%% ------------------- +fn.bin = 'flat.bin'; +fn.txt = 'flat.txt'; +fn.tplg1 = 'eq_iir_coef_flat.m4'; +fn.tplg2 = 'flat.conf'; +comment = 'Flat response, created with sof_example_iir_eq.m'; + +%% Define a passthru IIR EQ equalizer +[z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_pass = sof_eq_iir_blob_quant(z_pass, p_pass, k_pass); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % One responses: pass +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_pass); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment) + +%% --------------------------- +%% Example 5: Pass-through IIR +%% --------------------------- +fn.bin = 'pass.bin'; +fn.txt = 'pass.txt'; +fn.tplg1 = 'eq_iir_coef_pass.m4'; +fn.tplg2 = 'passthrough.conf'; +comment = 'Pass-through, created with sof_example_iir_eq.m'; + +%% Define a passthru IIR EQ equalizer +[z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); + +%% Quantize and pack filter coefficients plus shifts etc. +bq_pass = sof_eq_iir_blob_quant(z_pass, p_pass, k_pass); + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [-1 -1]; % Switch to passthrough +num_responses = 1; % One responses: pass +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_pass); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment) + +%% ------------------------------------ +%% Example 6: 20/30/40/50 Hz high-pass +%% ------------------------------------ + +fs_list = [16e3 48e3]; +fc_list = [20 30 40 50 100]; +g_list = [0 16 20 30 40]; +for i = 1:length(fs_list) + for j = 1:length(fc_list); + for k = 1:length(g_list); + fs = fs_list(i); + fc = fc_list(j); + g = g_list(k); + fsk = round(fs/1e3); + fn.tplg1 = sprintf('eq_iir_coef_highpass_%dhz_%ddb_%dkhz.m4', ... + fc, g, fsk); + fn.tplg2 = sprintf('highpass_%dhz_%ddb_%dkhz.conf', fc, g, fsk); + fn.txt = sprintf('highpass_%dhz_%ddb_%dkhz.txt', fc, g, fsk); + comment = sprintf('%d Hz second order high-pass, gain %d dB, created with sof_example_iir_eq.m', ... + fc, g); + fn.bin = sprintf('highpass_%dhz_%ddb_%dkhz.bin', fc, g, fsk); + + %% Design IIR high-pass + eq_hp = hp_iir_eq(fs, fc, g); + + %% Quantize and pack filter coefficients plus shifts etc. + bq_hp = sof_eq_iir_blob_quant(eq_hp.p_z, eq_hp.p_p, eq_hp.p_k); + + %% Build blob + channels_in_config = 2; % Setup max 2 channels EQ + assign_response = [0 0]; % Switch to response #0 + num_responses = 1; % One responses: hp + bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq_hp); + + %% Pack and write file + sof_eq_pack_export(bm, fn, comment) + end + end +end + +%% ------------------------------------------------------------------ +%% Example 7: Merge previous desigs to single blob for use as presets +%% ------------------------------------------------------------------ + +fn.bin = 'bundle.bin'; +fn.txt = 'bundle.txt'; +fn.tplg1 = 'eq_iir_bundle.m4'; +fn.tplg2 = 'bundle.conf'; +comment = 'Bundle of responses flat/loud/bass/band/high, created with sof_example_iir_eq.m'; + +%% Build blob +channels_in_config = 2; % Setup max 2 channels EQ +assign_response = [ 2 2 ]; % Switch to response id 2, bass boost +num_responses = 5; % 5 responses: flat, loudness, bass boost, bandpass, highpass +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_pass bq_loud bq_bass bq_band bq_hp]); + +%% Pack and write file +sof_eq_pack_export(bm, fn, comment) + +%% ------------------------------------ +%% Done. +%% ------------------------------------ + +sof_eq_paths(0); + +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = loudness_iir_eq(fs) + +%% Derived from Fletcher-Munson curves for 80 and 60 phon +f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ... + 68,72,76,81,85,90,96,102,108,114,121,128,136,144,153,162,171, ... + 182,192,204,216,229,243,257,273,289,306,324,344,364,386,409, ... + 434,460,487,516,547,580,614,651,690,731,775,821,870,922,977, ... + 1036,1098,1163,1233,1307,1385,1467,1555,1648,1747,1851,1962, ... + 2079,2203,2335,2474,2622,2779,2945,3121,3308,3505,3715,3937, ... + 4172,4421,4686,4966,5263,5577,5910,6264,6638,7035,7455,7901, ... + 8373,8873,9404,9966,10561,11193,11861,12570,13322,14118,14962, ... + 15856,16803,17808,18872,20000]; + +m = [ 0.00,-0.13,-0.27,-0.39,-0.52,-0.64,-0.77,-0.89,-1.02,-1.16, ... + -1.31,-1.46,-1.61,-1.76,-1.91,-2.07,-2.24,-2.43,-2.64,-2.85, ... + -3.04,-3.21,-3.35,-3.48,-3.62,-3.78,-3.96,-4.16,-4.35,-4.54, ... + -4.72,-4.90,-5.08,-5.26,-5.45,-5.64,-5.83,-6.02,-6.19,-6.37, ... + -6.57,-6.77,-6.98,-7.19,-7.40,-7.58,-7.76,-7.92,-8.08,-8.25, ... + -8.43,-8.60,-8.76,-8.92,-9.08,-9.23,-9.38,-9.54,-9.69,-9.84, ... + -9.97,-10.09,-10.18,-10.26,-10.33,-10.38,-10.43,-10.48,-10.54, ... + -10.61,-10.70,-10.78,-10.85,-10.91,-10.95,-10.98,-11.02, ... + -11.05,-11.07,-11.10,-11.11,-11.11,-11.10,-11.10,-11.11, ... + -11.14,-11.17,-11.20,-11.21,-11.22,-11.21,-11.20,-11.20, ... + -11.21,-11.21,-11.20,-11.17,-11.11,-11.02,-10.91,-10.78, ... + -10.63,-10.46,-10.25,-10.00,-9.72,-9.39,-9.02,-8.62,-8.19, ... + -7.73,-7.25,-6.75,-6.25,-5.75,-5.28,-4.87,-4.54,-4.33,-4.30]; + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.target_f = f; +eq.target_m_db = m; +eq.enable_iir = 1; +eq.iir_norm_type = 'loudness'; +eq.iir_norm_offs_db = 0; + +%% Manually setup low-shelf and high shelf parametric equalizers +% +% Parametric EQs are PEQ_HP1, PEQ_HP2, PEQ_LP1, PEQ_LP2, PEQ_LS1, +% PEQ_LS2, PEQ_HS1, PEQ_HS2 = 8, PEQ_PN2, PEQ_LP4, and PEQ_HP4. +% +% Parametric EQs take as second argument the cutoff frequency in Hz +% and as second argument a dB value (or NaN when not applicable) . The +% Third argument is a Q-value (or NaN when not applicable). +eq.peq = [ ... + eq.PEQ_LS1 40 +2 NaN ; ... + eq.PEQ_LS1 80 +3 NaN ; ... + eq.PEQ_LS1 200 +3 NaN ; ... + eq.PEQ_LS1 400 +3 NaN ; ... + eq.PEQ_HS2 13000 +7 NaN ; ... + ]; + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + +function eq = hp_iir_eq(fs, fc, gain_db) + +% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = '1k'; +eq.iir_norm_offs_db = gain_db; + +% Design +eq.peq = [ eq.PEQ_HP2 fc NaN NaN ]; +eq = sof_eq_compute(eq); +sof_eq_plot(eq); + +end + +function eq = bassboost_iir_eq(fs) + +% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'loudness'; +eq.iir_norm_offs_db = 0; + +% Design +eq.peq = [ ... + eq.PEQ_HP2 30 NaN NaN ; ... + eq.PEQ_LS2 200 +10 NaN ; ... + ]; +eq = sof_eq_compute(eq); +sof_eq_plot(eq); + +end + +function eq = bandpass_iir_eq(fs) + +% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'loudness'; +eq.iir_norm_offs_db = 0; + +% Design EQ +eq.peq = [ ... + eq.PEQ_HP2 500 NaN NaN ; ... + eq.PEQ_LP2 5000 NaN NaN ; ... + ]; +eq = sof_eq_compute(eq); +sof_eq_plot(eq); + +end + +% Pack and write file common function for all exports +function sof_eq_pack_export(bm, fn, note) + +howto = 'cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m'; +bp = sof_eq_iir_blob_pack(bm, 3); % IPC3 +if ~isempty(fn.bin) + sof_ucm_blob_write(fullfile(fn.cpath3, fn.bin), bp); +end +if ~isempty(fn.txt) + sof_alsactl_write(fullfile(fn.cpath3, fn.txt), bp); +end +if ~isempty(fn.tplg1) + sof_tplg_write(fullfile(fn.tpath1, fn.tplg1), bp, fn.priv, note, howto); +end + +bp = sof_eq_iir_blob_pack(bm, 4); % IPC4 +if ~isempty(fn.bin) + sof_ucm_blob_write(fullfile(fn.cpath4, fn.bin), bp); +end +if ~isempty(fn.txt) + sof_alsactl_write(fullfile(fn.cpath4, fn.txt), bp); +end +if ~isempty(fn.tplg2) + sof_tplg2_write(fullfile(fn.tpath2, fn.tplg2), bp, 'iir_eq', note, howto); +end + +end diff --git a/src/audio/eq_iir/tune/sof_example_lr4.m b/src/audio/eq_iir/tune/sof_example_lr4.m new file mode 100644 index 000000000000..d38111da6b98 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_example_lr4.m @@ -0,0 +1,183 @@ +% sof_example_lr4 - Design 4th order Linkwitz–Riley filter bank +% +% This script is run without arguments. It creates IIR equalizer +% blobs for crossover filter bank for 2-way speaker and four +% channels stream. The exported configurations are Linkwitz-Riley +% 4th order with crossover frequency at 2 kHz. The filters are +% in order: +% - low, high, low, high +% - low, low, high, high +% - high, high, low, low +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2025, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function sof_example_lr4() + +%% Common definitions +fs = 48e3; +fc = 2e3; +sof_tools = '../../../../tools'; +tpath = fullfile(sof_tools, 'topology/topology2/include/components/eqiir'); +cpath = fullfile(sof_tools, 'ctl/ipc4/eq_iir'); + +sof_eq_paths(1); + +%% -------------------------------------------------- +%% Example: Band-split 2ch to 4ch low and high bands +%% -------------------------------------------------- +design_name = sprintf('xover_lr4_%dhz_lhlh_%dkhz', fc, round(fs/1000)); +blob_fn = fullfile(cpath, [design_name '.bin']); +alsa_fn = fullfile(cpath, [design_name '.txt']); +tplg_fn = fullfile(tpath, [design_name '.conf']); +comment = 'LR4 filter bank coefficients'; +howto = 'cd src/audio/eq_iir/tune; octave sof_example_lr4.m'; + +% Design low-pass and high-pass filters +eq_lo = lo_band_iir(fs, fc); +eq_hi = hi_band_iir(fs, fc); + +% Quantize and pack filter coefficients plus shifts etc. +bq_lo = sof_eq_iir_blob_quant(eq_lo.p_z, eq_lo.p_p, eq_lo.p_k); +bq_hi = sof_eq_iir_blob_quant(eq_hi.p_z, eq_hi.p_p, eq_hi.p_k); + +% Build blob +channels_in_config = 4; % Setup max 4 channels EQ +assign_response = [0 1 0 1]; % Order: lo, hi, lo, hi +num_responses = 2; % Two responses: lo, hi +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_lo bq_hi]); + +% Pack and write file +sof_eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, comment, howto) + +%% -------------------------------------------------- +%% Example: Same but filters order is lo, lo, hi, hi +%% -------------------------------------------------- + +design_name = sprintf('xover_lr4_%dhz_llhh_%dkhz', fc, round(fs/1000)); +blob_fn = fullfile(cpath, [design_name '.bin']); +alsa_fn = fullfile(cpath, [design_name '.txt']); +tplg_fn = fullfile(tpath, [design_name '.conf']); + +assign_response = [0 0 1 1]; +num_responses = 2; +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_lo bq_hi]); + +% Pack and write file +sof_eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, comment, howto) + +%% -------------------------------------------------- +%% Example: Same but filters order is hi, hi, lo, lo +%% -------------------------------------------------- + +design_name = sprintf('xover_lr4_%dhz_hhll_%dkhz', fc, round(fs/1000)); +blob_fn = fullfile(cpath, [design_name '.bin']); +alsa_fn = fullfile(cpath, [design_name '.txt']); +tplg_fn = fullfile(tpath, [design_name '.conf']); + +assign_response = [1 1 0 0]; +num_responses = 2; +bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_lo bq_hi]); + +% Pack and write file +sof_eq_pack_export(bm, blob_fn, alsa_fn, tplg_fn, comment, howto) + +%% ------------------------------------ +%% Done. +%% ------------------------------------ + +sof_eq_paths(0); +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = lo_band_iir(fs, fc) + + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 0; + +% Parametric EQs are PEQ_HP1, PEQ_HP2, PEQ_LP1, PEQ_LP2, PEQ_LS1, +% PEQ_LS2, PEQ_HS1, PEQ_HS2 = 8, PEQ_PN2, PEQ_LP4, and PEQ_HP4. +% +% Parametric EQs take as second argument the cutoff frequency in Hz +% and as second argument a dB value (can use 0 for LP2). The +% Third argument is a Q-value (can use 0 for LP2). + +% Two 2nd order butterworth low-pass filters for 4th order Linkwitz–Riley +eq.peq = [ ... + eq.PEQ_LP2 fc 0 0 ; ... + eq.PEQ_LP2 fc 0 0 ; ... + ]; + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + +function eq = hi_band_iir(fs, fc) + + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.iir_norm_type = 'peak'; +eq.iir_norm_offs_db = 0; + +% Two 2nd order high-pass filters for 4th order Linkwitz–Riley +eq.peq = [ ... + eq.PEQ_HP2 fc 0 0 ; ... + eq.PEQ_HP2 fc 0 0 ; ... + ]; + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq); + +end + + + +% Pack and write file common function for all exports +function sof_eq_pack_export(bm, bin_fn, ascii_fn, tplg_fn, note, howto) + +bp = sof_eq_iir_blob_pack(bm, 4); % IPC4 + +if ~isempty(bin_fn) + sof_ucm_blob_write(bin_fn, bp); +end + +if ~isempty(ascii_fn) + sof_alsactl_write(ascii_fn, bp); +end + +if ~isempty(tplg_fn) + sof_tplg2_write(tplg_fn, bp, 'IIR', note, howto); +end + +end diff --git a/src/audio/eq_iir/tune/sof_example_spk_eq.m b/src/audio/eq_iir/tune/sof_example_spk_eq.m new file mode 100644 index 000000000000..3a91ae04db6a --- /dev/null +++ b/src/audio/eq_iir/tune/sof_example_spk_eq.m @@ -0,0 +1,174 @@ +function sof_example_spk_eq() + +%% Design an example speaker equalizer with the provided sample data +% This equalizer by default uses a FIR and IIR components those should be +% both in the speaker pipeline. +% +% Note that IIR should be first since the included band-pass response provides +% signal headroom. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Defaults +fs = 48e3; +sof_tools = '../../../../tools'; +sof_ctl = fullfile(sof_tools, 'ctl'); +sof_tplg = fullfile(sof_tools, 'topology'); + +iir.cpath3 = fullfile(sof_ctl, 'ipc3/eq_iir'); +iir.cpath4 = fullfile(sof_ctl, 'ipc4/eq_iir'); +fir.cpath3 = fullfile(sof_ctl, 'ipc3/eq_fir'); +fir.cpath4 = fullfile(sof_ctl, 'ipc4/eq_fir'); +fn.tpath1 = fullfile(sof_tplg, 'topology1/m4'); +fir.tpath2 = fullfile(sof_tplg, 'topology2/include/components/eqfir'); +iir.tpath2 = fullfile(sof_tplg, 'topology2/include/components/eqiir'); +iir.priv = 'DEF_EQIIR_PRIV'; +fir.priv = 'DEF_EQFIR_PRIV'; +iir.comment = 'Speaker FIR+IIR EQ created with example_spk_eq.m'; +fir.comment = 'Speaker FIR+IIR EQ created with example_spk_eq.m'; +howto = 'cd src/audio/eq_iir/tune; octave --no-window-system sof_example_spk_eq.m'; + +%% File names +fir.txt = 'spk.txt'; +fir.bin = 'spk.bin'; +fir.tplg1 = 'eq_fir_coef_spk.m4'; +fir.tplg2 = 'example_speaker.conf'; +iir.txt = 'spk.txt'; +iir.bin = 'spk.bin'; +iir.tplg1 = 'eq_iir_coef_spk.m4'; +iir.tplg2 = 'example_speaker.conf'; + +sof_eq_paths(1); + +%% Get defaults for equalizer design +eq = sof_eq_defaults(); + +%% Settings for this EQ +eq.fs = fs; % Default sample rate in SOF +eq.enable_fir = 1; % Try enabling and disabling FIR part +eq.enable_iir = 1; % Try enabling and disabling IIR part +eq.iir_norm_type = 'peak'; % Scale filters to have peak at 0 dB +eq.iir_norm_offs_db = 0; % Can be used to control gain +eq.fir_norm_type = 'peak'; % Scale filters to have peak at 0 dB +eq.fir_norm_offs_db = 0; % Can be used to control gain +eq.p_fmin = 100; % With this data start plots from 100 Hz +eq.p_fmax = 20e3; % and end to 20 kHz. + +%% Get acousticial frequency response measurement data. This is +% a quite typical response for a miniature speaker. Alternatively +% the response could be read from spreadsheet column format that is +% commonly supported by audio measurement equipment. Then extract +% the frequency and magnitude columns. E.g. +% +% data = xlsread('spkr.xlsx', 1, 'A5:B78'); +% eq.raw_f = data(:,1); +% eq.raw_m_db = data(:,2); + +eq.raw_f = [ ... + 298.533, 316.232, 334.971, 354.813, 375.838, 398.106, ... + 421.699, 446.685, 473.153, 501.186, 530.887, 562.342, ... + 595.663, 630.958, 668.345, 707.946, 749.895, 794.329, ... + 841.397, 891.252, 944.062, 1000, 1059.26, 1122.02, ... + 1188.5, 1258.93, 1333.52, 1412.54, 1496.24, 1584.9, ... + 1678.81, 1778.28, 1883.65, 1995.27, 2113.49, 2238.72, ... + 2371.38, 2511.89, 2660.73, 2818.39, 2985.39, 3162.28, ... + 3349.66, 3548.14, 3758.38, 3981.08, 4216.97, 4466.84, ... + 4731.52, 5011.88, 5308.85, 5623.42, 5956.63, 6309.58, ... + 6683.45, 7079.47, 7498.95, 7943.3, 8413.97, 8912.52, ... + 9440.62, 10000, 10592.6, 11220.2, 11885, 12589.3, ... + 13335.2, 14125.4, 14962.4, 15849, 16788.1, 17782.8, ... + 18836.5, 19952.7 ... +]; + +eq.raw_m_db = [ ... + 58.1704, 60.074, 60.4541, 61.3079, 62.8198, 64.3749, ... + 65.1556, 66.512, 67.5916, 68.6344, 69.9276, 70.7658, ... + 71.1125, 72.0627, 73.5348, 75.4887, 77.3088, 79.1541, ... + 80.9627, 82.0607, 81.943, 81.2228, 81.9497, 83.1848, ... + 84.3375, 85.4993, 86.4642, 87.1179, 87.4424, 87.53, ... + 85.7425, 85.0095, 82.9405, 82.9242, 82.7327, 83.6423, ... + 83.2839, 82.4201, 84.1403, 84.6485, 83.9274, 83.3366, ... + 83.3005, 84.2598, 85.1544, 86.015, 86.6519, 87.2118, ... + 87.5498, 88.1742, 88.5215, 88.3801, 89.8762, 91.4418, ... + 93.1845, 94.3355, 95.0918, 95.0258, 94.0337, 91.1068, ... + 88.7303, 87.4853, 86.2916, 83.037, 79.8056, 78.2022, ... + 76.0341, 74.5674, 69.2288, 56.1308, 68.697, 69.687, ... + 68.0005, 64.698 ... +]; + +%% With parametric IIR EQ try to place peaking EQ at +% resonant frequencies 1.4 kHz and 7.5 kHz. The gain +% and Q values were experimented manually. Additionally +% The lowest and highest frequeciens below and above speaker +% capability are attenuated with high-pass and low-pass +% filtering. +if eq.enable_iir; + eq.peq = [ ... + eq.PEQ_HP2 100 NaN NaN; ... + eq.PEQ_PN2 1480 -7 2.0; ... + eq.PEQ_PN2 7600 -11 1.3; ... + eq.PEQ_LP2 14500 NaN NaN; ... + ]; +end + +%% With FIR EQ try to flatten frequency response within +% 1 - 13 kHz frequency band. +if eq.enable_fir + eq.fir_minph = 1; + eq.fir_beta = 4; + eq.fir_length = 63; + eq.fir_autoband = 0; + eq.fmin_fir = 900; + eq.fmax_fir = 10700; +end + +%% Design EQ +eq = sof_eq_compute(eq); + +%% Plot +sof_eq_plot(eq, 1); + +%% Export FIR part +channels_in_config = 2; % Identical two speakers +assign_response = [0 0]; % Switch to response #0 +num_responses = 1; % Single response +if eq.enable_fir + bq_fir = sof_eq_fir_blob_quant(eq.b_fir); + bm_fir = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [ bq_fir ]); + bp_fir = sof_eq_fir_blob_pack(bm_fir, 3); % IPC3 + sof_alsactl_write(fullfile(fir.cpath3, fir.txt), bp_fir); + sof_ucm_blob_write(fullfile(fir.cpath3, fir.bin), bp_fir); + sof_tplg_write(fullfile(fn.tpath1, fir.tplg1), bp_fir, fir.priv, fir.comment, howto); + bp_fir = sof_eq_fir_blob_pack(bm_fir, 4); % IPC4 + sof_alsactl_write(fullfile(fir.cpath4, fir.txt), bp_fir); + sof_ucm_blob_write(fullfile(fir.cpath4, fir.bin), bp_fir); + sof_tplg2_write(fullfile(fir.tpath2, fir.tplg2), bp_fir, 'eq_fir', fir.comment, howto); +end + +%% Export IIR part +if eq.enable_iir + bq_iir = sof_eq_iir_blob_quant(eq.p_z, eq.p_p, eq.p_k); + bm_iir = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [ bq_iir ]); + bp_iir = sof_eq_iir_blob_pack(bm_iir, 3); % IPC3 + sof_alsactl_write(fullfile(iir.cpath3, iir.txt), bp_iir); + sof_ucm_blob_write(fullfile(iir.cpath3, iir.bin), bp_iir); + sof_tplg_write(fullfile(fn.tpath1, iir.tplg1), bp_iir, iir.priv, iir.comment, howto); + bp_iir = sof_eq_iir_blob_pack(bm_iir, 4); % IPC4 + sof_alsactl_write(fullfile(iir.cpath4, iir.txt), bp_iir); + sof_ucm_blob_write(fullfile(iir.cpath4, iir.bin), bp_iir); + sof_tplg2_write(fullfile(iir.tpath2, iir.tplg2), bp_iir, 'eq_iir', iir.comment, howto); +end + +sof_eq_paths(0); + +end diff --git a/src/audio/eq_iir/tune/sof_export_c_eq_uint32t.m b/src/audio/eq_iir/tune/sof_export_c_eq_uint32t.m new file mode 100644 index 000000000000..c7c26437b458 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_export_c_eq_uint32t.m @@ -0,0 +1,102 @@ +function sof_export_c_eq_uint32t(fn, blob8, vn, justeq, howto) + +% sof_export_c_eq_uint32t(fn, blob8, vn) +% +% Export 8-bit blob data as C int32_t vector in hexadecimal +% +% fn - filename for export +% blob8 - blob data from EQ design +% vn - variable name +% justeq - export just the EQ wihtout ABI headers for direct use in FW +% howto - add a comment how the header file was created + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2021-2025, Intel Corporation. + + % Write blob + fh = fopen(fn, 'w'); + if fh < 0 + fprintf(1, 'Error: Could not open file: %s\n', fn); + error("Failed."); + end + + year = datestr(now, 'yyyy'); + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s Intel Corporation.\n', year); + fprintf(fh, ' */\n'); + fprintf(fh, '\n'); + + if nargin == 5 + fprintf(fh, '/* Created %s with command:\n', datestr(now, 'yyyy-mm-dd')); + fprintf(fh, ' * %s\n */\n\n', howto); + end + + fprintf(fh, '#include <stdint.h>\n\n'); + + % Drop 8 bytes TLV header + blob8 = blob8(9:end); + + % Pad blob length to multiple of four bytes + n_orig = length(blob8); + n_new = ceil(n_orig/4); + blob8_new = zeros(1, n_new*4); + blob8_new(1:n_orig) = blob8; + + %% Convert to 32 bit + blob32 = zeros(1, n_new, 'uint32'); + k = 2.^[0 8 16 24]; + for i=1:n_new + j = (i-1)*4; + blob32(i) = blob8_new(j+1)*k(1) + blob8_new(j+2)*k(2) ... + + blob8_new(j+3)*k(3) + blob8_new(j+4)*k(4); + end + + % Omit all headers if requested + if justeq + blob32 = blob32(18:end); + n_new = length(blob32); + end + + numbers_in_line = 4; + full_lines = floor(n_new/numbers_in_line); + numbers_remain = n_new - numbers_in_line * full_lines; + + n = 1; + fprintf(fh, 'static const uint32_t %s[%d] = {\n', vn, n_new); + for i = 1:full_lines + fprintf(fh, '\t'); + for j = 1:numbers_in_line + fprintf(fh, '0x%08x', blob32(n)); + if n < n_new + fprintf(fh, ','); + end + if j < numbers_in_line + fprintf(fh, ' '); + else + fprintf(fh, '\n'); + end + n = n + 1; + end + end + + if numbers_remain + fprintf(fh, '\t'); + for j = 1:numbers_remain + fprintf(fh, '0x%08x', blob32(n)); + if n < n_new + fprintf(fh, ','); + end + if j < numbers_remain + fprintf(fh, ' '); + else + fprintf(fh, '\n'); + end + n = n + 1; + end + end + + fprintf(fh, '};\n'); + fclose(fh); +end diff --git a/src/audio/eq_iir/tune/sof_export_c_int32t.m b/src/audio/eq_iir/tune/sof_export_c_int32t.m new file mode 100644 index 000000000000..e24d60dd976a --- /dev/null +++ b/src/audio/eq_iir/tune/sof_export_c_int32t.m @@ -0,0 +1,88 @@ +% Export to C header filer int32_t data +% +% Usage: +% sof_export_c_int32t(fn, vn, ln, x) +% Inputs: +% fn - filename for header file +% vn - variable name +% ln - name for defined LENGTH +% x - matrix of data + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2021, Intel Corporation. All rights reserved. + +function sof_export_c_int32t(fn, vn, ln, x) + +% Write blob +blob32 = interleave(x); +count = length(blob32); +fh = fopen(fn, 'w'); +if fh < 0 + fprintf(1, 'Error: Could not open file: %s\n', fn); + error("Failed."); +end + +numbers_in_line = 6; +full_lines = floor(count/numbers_in_line); +numbers_remain = count - numbers_in_line * full_lines; + +year = datestr(now, 'yyyy'); +fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); +fprintf(fh, ' *\n'); +fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', year); +fprintf(fh, ' */\n\n'); +fprintf(fh, '#define %s %d\n\n', ln, count); + +n = 1; +fprintf(fh, 'int32_t %s[%s] = {\n', vn, ln); +for i = 1:full_lines + fprintf(fh, '\t'); + for j = 1:numbers_in_line + fprintf(fh, '%dLL', blob32(n)); + if n < count + fprintf(fh, ','); + end + if j < numbers_in_line + fprintf(fh, ' '); + else + fprintf(fh, '\n'); + end + n = n + 1; + end +end + +if numbers_remain + fprintf(fh, '\t'); + for j = 1:numbers_remain + fprintf(fh, '%dLL', blob32(n)); + if n < count + fprintf(fh, ','); + end + if j < numbers_remain + fprintf(fh, ' '); + else + fprintf(fh, '\n'); + end + n = n + 1; + end +end + +fprintf(fh, '};\n'); +fclose(fh); +end + +function y = interleave(x) + +sx = size(x); +samples = sx(1); +channels = sx(2); +if sx(2) > 1 + y = zeros(samples * channels, 1); + for i = 1:channels + y(i:channels:end) = x(:, i); + end +else + y = x; +end +end diff --git a/src/audio/eq_iir/tune/sof_gui.m b/src/audio/eq_iir/tune/sof_gui.m new file mode 100644 index 000000000000..e783c4c2ec22 --- /dev/null +++ b/src/audio/eq_iir/tune/sof_gui.m @@ -0,0 +1,506 @@ +function sof_gui() + pkg load signal; + clear; + EQ = []; + Fs = get_config().Fs; + nyquist_f = Fs/2; + fn = 1; + % create figure and panel on it + fn = figure(fn, "toolbar", "none", "menubar", "none", 'Position', [200 200 1500 700]); fn = fn + 1; + EQ_right = uipanel ("title", "EQ Right", "position", [0, 0, 1, 0.5]); + EQ_left = uipanel ("title", "EQ Left", "position", [0, 0.5, 1, 0.5]); + main_panes = [struct("pane", EQ_left); struct("pane", EQ_right)]; + + % UI panel relative position table + positions = [ + [0 0 0.25 0.5 ] + [0.25 0 0.5 0.5 ] + [0.5 0 0.75 0.5 ] + [0.75 0 1 0.5 ] + [0 0.5 0.25 1 ] + [0.25 0.5 0.5 1 ] + [0.5 0.5 0.75 1 ] + [0.75 0.5 1 1 ] + ]; + + fn = figure(fn); fn = fn + 1; + h = [0 0]; + w = [1 nyquist_f]; + n_octaves = 10; + subplot(2, 1, 1); + main_panes(1).plot = plot(log2(w), h, "linewidth", 4); + % Range set to match http://audio-tuning.appspot.com/ + axis([log2(nyquist_f / (2 ^ n_octaves)), log2(nyquist_f), -24, 18]); + grid on; + subplot(2, 1, 2); + main_panes(2).plot = plot(log2(w), h, "linewidth", 4); + % Range set to match http://audio-tuning.appspot.com/ + axis([log2(nyquist_f / (2 ^ n_octaves)), log2(nyquist_f), -24, 18]); + grid on; + % TODO add ability to switch between octaves and log(Hz) + for c = 1:2 + for i = 1:length(positions) + EQ = initialize_biquad(i, c, positions(i, 1:end), main_panes, Fs, EQ); + endfor + endfor + % octave is silly and doesn't support references so we have to re-write the + % control matrix so the callbacks have access without using globals + for c = 1:2 + for i = 1:length(positions) + update_control_elements(EQ(i, c), EQ); + endfor + endfor + fn = figure(fn, "toolbar", "none", "menubar", "none", 'Position', [200 200 300 220]); fn = fn + 1; + menu_window = struct(); + menu_window.ip_box = uicontrol( ... + "style", "edit", ... + "position", [120 190 180 30]); + menu_window.ip_label = uicontrol( ... + "style", "text", + "string", "DUT IP:", ... + "position", [0 190 120 30]); + menu_window.user_box = uicontrol( ... + "style", "edit", ... + "position", [120 160 180 30]); + menu_window.user_label = uicontrol( ... + "style", "text", + "string", "DUT User:", ... + "position", [0 160 120 30]); + menu_window.device_box = uicontrol( ... + "style", "edit", ... + "position", [120 130 180 30]); + menu_window.device_label = uicontrol( ... + "style", "text", + "string", "Device Num:", ... + "position", [0 130 120 30]); + menu_window.alsa_box = uicontrol( ... + "style", "edit", ... + "position", [120 100 180 30]); + menu_window.alsa_label = uicontrol( ... + "style", "text", + "string", "ALSA Ctl Num:", ... + "position", [0 100 120 30]); + menu_window.upload = uicontrol( ... + "style", "pushbutton", ... + 'string', 'Push config to DUT', ... + "callback", @push_config, ... + "position", [0 50 300 50], ... + "userdata", struct("menu_window", menu_window, "EQ", EQ)); + menu_window.load_dsp = uicontrol( ... + "style", "pushbutton", ... + 'string', 'Load dsp.ini', ... + "callback", @sof_eq_load_dsp_ini, ... + "position", [0 0 300 50], ... + "userdata", struct("EQ", EQ)); +end + +function conf = get_config() + % since octave has no definitive way to have constants we are going to hack a + % struct into behaving like one + conf = struct( ... + "Fs", 48000 ... + ); +end + +function set_udata_field(h, field, value) + udata = get(h, "userdata"); + udata = setfield(udata, field, value); + set(h, "userdata", udata); +end + +function peq = build_peq(channel, EQ) + peq = []; + for i = 1:8 + biquad = EQ(i, channel); + if get(biquad.enable_switch, "value") == 1 + type = get(biquad.type.dropdown, "value"); + freq = str2num(get(biquad.freq.edit, "string")); + Q = str2double(get(biquad.Q.edit, "string")); + gain = str2double(get(biquad.gain.edit, "string")); + % dropdown maps straight to filter index + % filter only uses needed arguments, all others will be ignored + peq = [peq; type, freq, gain, Q]; + endif + endfor +end + +function update_plot(channel, main_panes, EQ) + Fs = get_config().Fs; + nyquist_f = Fs / 2; + pl = main_panes(channel).plot; + spectrum_size = 1000; + n = logspace(log10(1), log10(nyquist_f), spectrum_size); + peq = build_peq(channel, EQ); + [z p k] = sof_eq_define_parametric_eq(peq, Fs); + % octave gets angry when you pile up poles and zeros + [num den] = zp2tf(z, p, k); + [h, w] = freqz(num,den, n, Fs); + h = 20*log10(h); + set(pl, "YData", h, "XData", log2(w)); +end + +function set_section_visibility(section, visible) + for [control, control_name] = section + set(control, "visible", visible); + endfor +end + +function dropdown_callback(h, event) + udata = get(h, "userdata"); + EQ = udata.EQ; + biquad = EQ(udata.index, udata.channel); + eq = sof_eq_defaults(); + switch (get(h, "value")) + case eq.PEQ_HP1 + % highpass 1st order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_HP2 + % highpass 2nd order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_LP1 + % lowpass 1st order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_LP2 + % lowpass 2nd order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_LS1 + % lowshelf 1st order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "on"); + case eq.PEQ_LS2 + % lowhelf 2nd order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "on"); + case eq.PEQ_HS1 + % highshelf 1st order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "on"); + case eq.PEQ_HS2 + % highshelf 2nd order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "on"); + case eq.PEQ_PN2 + % peaking + set_section_visibility(biquad.Q, "on"); + set_section_visibility(biquad.gain, "on"); + case eq.PEQ_LP4 + % lowpass 4th order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_HP4 + % highpass 4th order + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_LP2G + % lowpass 2nd order with resonnance + set_section_visibility(biquad.Q, "on"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_HP2G + % highpass 2nd order with resonnance + set_section_visibility(biquad.Q, "on"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_BP2 + % bandpass + set_section_visibility(biquad.Q, "on"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_NC2 + % notch + set_section_visibility(biquad.Q, "on"); + set_section_visibility(biquad.gain, "off"); + case eq.PEQ_LS2G + % lowshelf, CRAS implementation + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "on"); + case eq.PEQ_HS2G + % highshelf, CRAS implementation + set_section_visibility(biquad.Q, "off"); + set_section_visibility(biquad.gain, "on"); + endswitch + update_plot(udata.channel, udata.main_panes, EQ); +end + +function enable_callback(h, event) + off = get(h, "value") == 0; + if off + visible = "off"; + else + visible = "on"; + endif + udata = get(h, "userdata"); + EQ = udata.EQ; + biquad = EQ(udata.index, udata.channel); + for [section, section_name] = biquad + if strcmp(section_name, "enable_switch") || strcmp(section_name, "pane") + continue + endif + set_section_visibility(section, visible); + endfor + if !off + dropdown_callback(biquad.type.dropdown,0); + endif + update_plot(udata.channel, udata.main_panes, EQ); +end + +function slider_callback(h, event) + udata = get(h, "userdata"); + EQ = udata.EQ; + editbox = getfield(EQ(udata.index, udata.channel), udata.prefix).edit; + val = get(h, "value"); + if udata.is_log + val = 0.1*2^val; + endif + set(editbox, "string", num2str(val)); + update_plot(udata.channel, udata.main_panes, EQ); +end + +function edit_callback(h, event) + udata = get(h, "userdata"); + EQ = udata.EQ; + slider = getfield(EQ(udata.index, udata.channel), udata.prefix).slider; + val = str2num(get(h, "string")); + if udata.is_log && val != 0 + val = log2(val/0.1); + end + set(slider, "value", val); + update_plot(udata.channel, udata.main_panes, EQ); +end + +function EQ = initialize_biquad(index, channel, position, main_panes, Fs, EQ) + nyquist_f = Fs / 2; + % this string matches the order defined in eq.PEQ_*, do not change the order + eq_strings = {"highpass 1st order", "highpass 2nd order", ... + "lowpass 1st order", "lowpass 2nd order", "lowshelf 1st order", ... + "lowshelf 2nd order", "highshelf 1st order", "highshelf 2nd order", ... + "peaking 2nd order", "lowpass 4th order", "highpass 4th order", ... + "lowpass 2nd order (Google)", "highpass 2nd order (Google)", ... + "bandpass 2nd order", "notch 2nd order", "lowshelf 2nd order (Google)", ... + "highshelf 2nd order (Google)"}; + eq = sof_eq_defaults(); + % UI panels, we have to use absolute positioning + % + % +-------+-----------+-------+--+--+--+--+--+----------+ + % | Label | Dropdown | | | | | | | checkbox | + % +-------+-----------+-------+--+--+--+--+--+----------+ + % | Label | input box | label | slider | + % +-------+-----------+-------+-------------------------+ + % | Label | input box | label | slider | + % +-------+-----------+-------+-------------------------+ + % | Label | input box | label | slider | + % +-------+-----------+-------+-------------------------+ + + EQ(index, channel).pane = uipanel ("parent", main_panes(channel).pane, "position", position); + p = EQ(index, channel).pane; + % octave is silly and doesn't let one position controls relatively inside a uipanel + EQ(index, channel).gain.label = uicontrol( ... + "style", "text", ... + "parent", p, ... + "position", [0 10 40 30], ... + "visible", "off", ... + "string", "Gain"); + EQ(index, channel).gain.edit = uicontrol( ... + "style", "edit", ... + "parent", p, ... + "position", [40 10 90 30], ... + "string", "0", ... + "userdata", struct( ... + "index", index, ... + "channel", channel, ... + "prefix", "gain", ... + "is_log", false, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @edit_callback); + EQ(index, channel).gain.units = uicontrol( ... + "style", "text", ... + "parent", p, ... + "string", "dB", ... + "visible", "off", ... + "position", [140 10 17 30]); + EQ(index, channel).gain.slider = uicontrol( ... + "style", "slider", ... + "parent", p, ... + "position", [160 10 200 30], ... + "min", -40, ... + "max", 40, ... + "userdata", struct( + "index", index, ... + "channel", channel, ... + "prefix", "gain", ... + "is_log", false, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @slider_callback); + + EQ(index, channel).Q.label = uicontrol( ... + "style", "text", ... + "parent", p, ... + "position", [0 50 50 30], ... + "visible", "off", ... + "string", "Q"); + EQ(index, channel).Q.edit = uicontrol( ... + "style", "edit", ... + "parent", p, ... + "position", [40 50 90 30], ... + "string", "1", ... + "userdata", struct( ... + "index", index, ... + "channel", channel, ... + "prefix", "Q", ... + "is_log", true, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @edit_callback); + EQ(index, channel).Q.slider = uicontrol( ... + "style", "slider", ... + "parent", p, ... + "position", [160 50 200 30], ... + "min", 0, ... + "max", log2(1000/0.1), ... + "value", log2(1/0.1), ... + "userdata", struct( + "index", index, ... + "channel", channel, ... + "prefix", "Q", ... + "is_log", true, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @slider_callback); + + EQ(index, channel).freq.label = uicontrol( ... + "style", "text", ... + "parent", p, ... + "position", [0 90 40 30], ... + "visible", "off", ... + "string", "Freq"); + EQ(index, channel).freq.edit = uicontrol( ... + "style", "edit", ... + "parent", p, ... + "position", [40 90 90 30], ... + "string", "350", ... + "userdata", struct( ... + "index", index, ... + "channel", channel, ... + "prefix", "freq", ... + "is_log", true, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @edit_callback); + EQ(index, channel).freq.units = uicontrol( ... + "style", "text", ... + "parent", p, ... + "position", [140 90 17 30], ... + "visible", "off", ... + "string", "Hz"); + EQ(index, channel).freq.slider = uicontrol( ... + "style", "slider", ... + "parent", p, ... + "position", [160 90 200 30], ... + "min", 1, ... + "max", log2(nyquist_f/0.1), ... + "value", log2(350/0.1), ... + "userdata", struct( + "index", index, ... + "channel", channel, ... + "prefix", "freq", ... + "is_log", true, ... + "EQ", EQ, ..., + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @slider_callback); + + EQ(index, channel).type.label = uicontrol( ... + "style", "text", ... + "parent", p, ... + "position", [0 130 40 30], ... + "visible", "off", ... + "string", "Type"); + EQ(index, channel).type.dropdown = uicontrol( ... + "style", "popupmenu", ... + "parent", p, ... + "position", [40 130 240 30], ... + "string", eq_strings, ... + "value", eq.PEQ_PN2, ... + "userdata", struct( ... + "index", index, ... + "channel", channel, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "visible", "off", ... + "callback", @dropdown_callback); + EQ(index, channel).enable_switch = uicontrol( ... + "style", "checkbox", ... + "parent", p, ... + "position", [350 130 30 30], ... + "value", 0, ... + "userdata", struct( + "index", index, ... + "channel", channel, ... + "EQ", EQ, ... + "main_panes", main_panes), ... + "callback", @enable_callback); +end + +function push_config(h, evnt) + udata = get(h, "userdata"); + window = udata.menu_window; + EQ = udata.EQ; + ip = get(window.ip_box, "string"); + user = get(window.user_box, "string"); + device = str2num(get(window.device_box, "string")); + alsa_num = str2num(get(window.alsa_box, "string")); + target = struct("ip", ip, "user", user, "device", device, "control", alsa_num); + + temp_file = tempname(); + + eq_left = sof_eq_defaults(); + eq_left.enable_iir = 1; + eq_left.peq = build_peq(1, EQ); + eq_left.iir_norm_type = 'peak'; + eq_left.iir_norm_offs_db = 0; + eq_left.fs = get_config().Fs; + + eq_right = sof_eq_defaults(); + eq_right.enable_iir = 1; + eq_right.peq = build_peq(2, EQ); + eq_right.iir_norm_type = 'peak'; + eq_right.iir_norm_offs_db = 0; + eq_right.fs = get_config().Fs; + + eq_left = sof_eq_compute(eq_left); + eq_right = sof_eq_compute(eq_right); + + bq_left = sof_eq_iir_blob_quant(eq_left.p_z, eq_left.p_p, eq_left.p_k); + bq_right = sof_eq_iir_blob_quant(eq_right.p_z, eq_right.p_p, eq_right.p_k); + + channels_in_config = 2; + assign_response = [0 1]; + num_responses = 2; + bm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + [bq_left bq_right]); + + bp = sof_eq_iir_blob_pack(bm); + sof_eq_alsactl_write(temp_file, bp); + sof_eq_deploy_to_dut(target, temp_file); +end + +function update_control_elements(section, EQ) + set_udata_field(section.gain.edit, "EQ", EQ); + set_udata_field(section.gain.slider, "EQ", EQ); + set_udata_field(section.Q.edit, "EQ", EQ); + set_udata_field(section.Q.slider, "EQ", EQ); + set_udata_field(section.freq.edit, "EQ", EQ); + set_udata_field(section.freq.slider, "EQ", EQ); + set_udata_field(section.type.dropdown, "EQ", EQ); + set_udata_field(section.enable_switch, "EQ", EQ); +end diff --git a/src/audio/eq_iir/tune/sof_mls_freq_resp.m b/src/audio/eq_iir/tune/sof_mls_freq_resp.m new file mode 100644 index 000000000000..a30864d93a3b --- /dev/null +++ b/src/audio/eq_iir/tune/sof_mls_freq_resp.m @@ -0,0 +1,433 @@ +function [f, m_db] = sof_mls_freq_resp(id) +%% Measure frequency response with MLS test signal +% +% [f, m] = mls_freq_resp(id) +% +% Input parameters +% id - A string identifier for test case. An id 'selftest' is for special +% usage. It calculates response of filtered MLS signal and computes +% the measurement vs. known. Deviation is reported as error. It can +% be useful if the internal MLS measurement parameters are adjusted. +% +% Output parameters +% f - Frequency vector in Hz +% m - Measured magnitude responses in dB +% +% Configuration (edit these): +% mls_play_config.txt +% mls_rec_config.txt +% +% The script will return also a text CSV format file with name mls-<id>.txt. +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2018-2025, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Settings +np = 1024; % Number of frequency points to use +f_lo = 100; % Lower frequency limit for analysis +f_hi = 20e3; % Upper frequency limit for analysis +t_tot = 10e-3; % MLS analysis window length in s +t_mls_s = 1.0; % MLS test signal length in s +a_mls_db = -10; % MLS test signal amplitude in dB +fs = 48e3; % Sample rate in Hz +bits = 16; % Audio format to use (bits) +fmt = 'S16_LE'; % Audio format to use (ALSA) +dir = '/tmp'; % Directory for temporary files +capture_level_max_db = -1; % Expected max. level +capture_level_min_db = -30; % Expacted min. level + +%% Get device identifier to use +if nargin < 1 + id = 'unknown'; +end + +if strcmp(id, 'selftest') + selftest = 1; + % Just some simulated speaker response to use as self test case + stb = [ 0.341762453, -0.915611126, 0.482465118, ... + 1.017612317, -1.722527013, 0.711608745, ... + 0.630608859, -0.813609935, 0.267690582, ]; + sta = [ 1.000000000, -3.931695128, 6.630812276, ... + -6.339248735, 3.800407709, -1.559376698, ... + 0.619626250, -0.317702349, 0.097453451, ]; +else + selftest = 0; +end +measfn = sprintf('mls-%s.wav', id); +csvfn = sprintf('mls-%s.txt', id); + +%% Paths +addpath('../../../../tools/test/audio/test_utils'); + +%% MLS +n_mls = round(fs*t_mls_s); +mls = 10^(a_mls_db/20) * (2 * mlsp12(1, n_mls) - 1); +mlsfn = 'mls-ref.wav'; +audiowrite(mlsfn, mls, fs); + +%% Chip markers and parameters for find sync +[x1, m1] = sync_chirp(fs, 'up'); +[x2, m2] = sync_chirp(fs, 'down'); +fnd.fs = fs; % Sample rate +fnd.sm = 5; % Max seek from start +fnd.em = 5; % Max seek from end +fnd.idle_t = 2; % max idle in start or end +fnd.mark_t = m1.t; % Marker length +fnd.nf = 1; % One signal (amplitude) +fnd.na = 1; % One signal (frequency) +fnd.tl = t_mls_s; % Length of signal +fnd.mt = 0.1; % Threshold length to issue error +fnd.is = 0; % Ignore from start +fnd.ie = 0; % Ignore from end + +%% Merge markers and MLS +z = zeros(n_mls + m1.n + m2.n, 1); +i1 = m1.n + 1; +i2 = m1.n + n_mls; +z(1:i1 - 1) = x1; +z(i1:i2) = mls; +z(i2 + 1:end) = x2; + +%% Get config +rec_cfg = meas_remote_rec_config(fs, fmt); +play_cfg = meas_remote_play_config; + +%% Capture MLS from all playback channel at time +mixfn = 'mlsmix.wav'; +recfn = 'recch.wav'; +y = []; +if selftest + labels = cell(play_cfg.nch * rec_cfg.nch + 1, 1); + labels(end) = 'Reference'; +else + labels = cell(play_cfg.nch * rec_cfg.nch, 1); +end +label_idx = 1; +for i=1:play_cfg.nch + fprintf('\n'); + fprintf('Measure playback channel %d\n', i); + pstr=sprintf('p%d', i); + if selftest + tz =zeros(2*fs+length(z), 1); % Pad 2s + tz(fs:fs+length(z)-1) = z; + t = filter(stb, sta, tz); % Filter with test response + r = t(:) * ones(1, rec_cfg.nch); % Copy to all channels + else + x = zeros(length(z), play_cfg.nch); + x(:,i) = z; + mixdfn = sprintf('%s/%s', dir, mixfn); + audiowrite(mixdfn, x, fs, 'BitsPerSample', bits); + copy_playback(mixdfn, play_cfg); + tcap = floor(6 + t_mls_s); % Capture for MLS +6s + remote_capture(recfn, rec_cfg, tcap); + pause(1); + remote_play(mixfn, play_cfg); + pause(5); + r = get_recording(recfn, rec_cfg); + end + for j = 1:rec_cfg.nch + labels(label_idx) = sprintf('p%d-r%d', i, j); + label_idx = label_idx + 1; + end + [d, nt] = find_test_signal(r(:,1), fnd); + figure; + sr = size(r); + ts = (0:sr(1)-1)/fs; + plot(ts, r(:,1)); + grid on; + xlabel('Time (s)'); + ylabel('Sample value'); + if isempty(d) + title('Captured audio test waveform'); + fprintf(1, 'Error: check the plot for skew in capture/playback.\n'); + f = []; + m_db = []; + return + else + si = d:d + nt; + hold on + plot(ts(si), r(si), 'g'); + hold off + end + for j = 1:rec_cfg.nch + y(:, rec_cfg.nch*(i-1) + j) = r(d:d + nt -1, j); + end + m = 20*log10(max(abs(r))); + fprintf('Peak levels for capture channels (dB):'); + for j = 1:rec_cfg.nch + fprintf(' %5.1f', m(j)); + end + fprintf('\n'); + if max(m) > capture_level_max_db + fprintf('Warning: The recording level is too loud.\n'); + end + if min(m) < capture_level_min_db + fprintf('Warning: The recording level is too silent.\n'); + end + +end +audiowrite(measfn, y, fs, 'BitsPerSample', bits); +fprintf('\n'); +fprintf('Done.\n'); + +[f, m_db, b] = mls_calc_resp(csvfn, mlsfn, measfn, t_tot, np, f_lo, f_hi); + +[f, m_db] = apply_mic_calibration(f, m_db, rec_cfg); + +figure +idx = find(f>1e3, 1, 'first') - 1; +m_db_align = m_db - m_db(idx); +semilogx(f, m_db_align); +ax=axis(); axis([f_lo f_hi ax(3:4)]); +grid on; +xlabel('Frequency (Hz)'); +ylabel('Magnitude (dB)'); + +if selftest + title('Measured vs. reference response'); + h = freqz(stb, sta, f, fs); + ref_db = 20*log10(abs(h)); + ref_db_align = ref_db - ref_db(idx); + hold on; + plot(f, ref_db_align, 'r--'); + hold off; +end + +legend(labels); + +if selftest + idx = find(f < f_hi); + idx = find(f(idx) > f_lo); + m_lin = 10.^(m_db_align(idx)/20); + ref_lin = 10.^(ref_db_align(idx)/20); + err_lin = m_lin - ref_lin; + e_rms = sqrt(mean(err_lin.^2)); + e_db = 20*log10(e_rms); + figure; + semilogx(f(idx), 20*log10(abs(err_lin))) + grid on; + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + title('Observed Error in self test'); + if e_db < -30 + fprintf('Passed self test. '); + else + fprintf('Failed self test. '); + end + fprintf('Response RMS error is %4.1f dB.\n', e_db); +end + +rmpath('../../../../tools/test/audio/test_utils'); + +end + +function copy_playback(fn, cfg) + if cfg.ssh + cmd = sprintf('scp %s %s:%s/', fn, cfg.user, cfg.dir); + fprintf('Remote copy: %s\n', cmd); + system(cmd); + else + %cmd = sprintf('cp %s %s/', fn, cfg.dir); + %fprintf('Local copy: %s\n', cmd); + end +end + +function y = get_recording(fn, cfg) + if cfg.ssh + cmd = sprintf('scp %s:%s/%s %s', cfg.user, cfg.dir, fn, fn); + fprintf('Remote copy: %s\n', cmd); + else + cmd = sprintf('cp %s/%s %s', cfg.dir, fn, fn); + fprintf('Local copy: %s\n', cmd); + end + system(cmd); + y = audioread(fn); + delete(fn); +end + +function remote_play(fn, cfg) + if cfg.ssh + cmd = sprintf('ssh %s aplay -D%s %s/%s', cfg.user, cfg.dev, cfg.dir, fn); + fprintf('Remote play: %s\n', cmd); + else + cmd = sprintf('aplay -D%s %s/%s', cfg.dev, cfg.dir, fn); + fprintf('Local play: %s\n', cmd); + end + system(cmd); +end + +function remote_capture(fn, cfg, t) + if cfg.ssh + cmd = sprintf('ssh %s arecord -q -D%s %s -d %d %s/%s &', ... + cfg.user, cfg.dev, cfg.fmt, t, cfg.dir, fn); + fprintf('Remote capture: %s\n', cmd); + else + cmd = sprintf('arecord -q -D%s %s -d %d %s/%s &', ... + cfg.dev, cfg.fmt, t, cfg.dir, fn); + fprintf('Local capture: %s\n', cmd); + end + system(cmd); +end + +function play = meas_remote_play_config() + play = get_config('mls_play_config.txt', 'play'); + fprintf('\nThe settings for remote playback are\n'); + fprintf('Use ssh : %d\n', play.ssh); + fprintf('User : %s\n', play.user); + fprintf('Directory : %s\n', play.dir); + fprintf('Device : %s\n', play.dev); + fprintf('Channels : %d\n', play.nch); +end + +function rec = meas_remote_rec_config(fs, fmt) + rec = get_config('mls_rec_config.txt', 'rec'); + rec.fmt = sprintf('-t wav -c %d -f %s -r %d', ... + rec.nch, fmt, fs); + + fprintf('\nThe settings for remote capture are\n'); + fprintf('Use ssh : %d\n', rec.ssh); + fprintf('User : %s\n', rec.user); + fprintf('Directory : %s\n', rec.dir); + fprintf('Device : %s\n', rec.dev); + fprintf('format : %s\n', rec.fmt); + fprintf('Channels : %d\n', rec.nch); + fprintf('Calibration Data : %s\n', rec.cal); + + if ~isempty(rec.cal) + if exist(rec.cal, 'file') + [rec.cf, rec.cm, rec.sens, rec.cs] = get_calibration(rec.cal); + else + error('The calibration file does not exist'); + end + else + rec.cf = []; + rec.cm = []; + rec.sens = []; + rec.cs = ''; + end +end + +% The syntax of ASCII text calibration data is such that first line is +% text string sometimes within "" or text line about Sensitivity. Such +% lines are read and stored to description text. The sensitivty is extracted +% and printed if success but currently it is not utilized by the code. +% +% The next lines are <frequency Hz> <magnitude decibels> for +% measurement data for microphone. If there are more than two numbers +% per line the other than two first columns are ignored. This code +% applies inverse of calibration data for measured response calibration. + +function [f, m, sens, desc] = get_calibration(fn) + fh = fopen(fn, 'r'); + if fh < 0 + error('Cannot open calibration data file'); + end + n = 1; + f = []; + m = []; + sens =[]; + desc = ''; + str = fgets(fh); + idx = strfind(str, '"'); + while length(idx) > 0 + line = str(idx(1)+1:idx(2)-1); + desc = sprintf('%s%s ', desc, line); + str = fgets(fh); + idx = strfind(str, '"'); + end + if length(strfind(str, 'Sens')) + desc = str; + str = fgets(fh); + end + while str ~= -1 + d=sscanf(str,'%f'); + f(n) = d(1); + m(n) = d(2); + n = n + 1; + str = fgets(fh); + end + + % Strip possible linefeed from description end + if double(desc(end)) == 10 + desc = desc(1:end-1); + end + fprintf('Calibration Info : %s\n', desc); + i1 = strfind(desc, 'Sens Factor ='); + i2 = strfind(desc, 'dB'); + if length(i1) == 1 && length(i2) == 1 + sens = sscanf(desc(i1+13:i2-1), '%f'); + fprintf('Calibration Sens : %6.2f dB\n', sens); + end + + fprintf('Calibration range: %.2f .. %.2f Hz\n', min(f), max(f)); + fprintf('Calibration range: %.2f .. %.2f dB\n', min(m), max(m)); + + figure; + semilogx(f, m); + grid on; + title(desc); + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); +end + +function [x, seed] = mlsp12(seed, n) + +% Based on book Numerical Recipes in C, chapter 7.4 Generation of +% random bits method II p. 298-299 example and 12 bit primitive +% polynomial (12, 6, 4, 1, 0) + + x = zeros(1,n); + ib1 = 2^(1-1); + ib4 = 2^(4-1); + ib6 = 2^(6-1); + ib12 = 2^(12-1); + mask = ib1 + ib4 + ib6 + ib12; + + for i = 1:n + if bitand(seed, ib12) + seed = bitor(bitxor(seed, mask) * 2 , ib1); + x(i) = 1; + else + seed = seed * 2; + x(i) = 0; + end + end +end + +%% Calibration apply function +% Resample microphone calibration data into used grid and +% then subtract calibration response from measured +% response. + +function [cal_f, cal_m_db] = apply_mic_calibration(f, m_db, rec) + + if length(rec.cm) > 0 + if ~isvector(rec.cm) + error('Calibration can be for one channel only'); + end + mic_m_db = interp1(rec.cf, rec.cm, f, 'linear'); + nans = isnan(mic_m_db); + idx = find(nans == 0); + cal_f = f(idx); + cal_db = mic_m_db(idx); + s = size(m_db); + for i = 1:s(2) + cal_m_db(:,i) = m_db(idx,i) - cal_db(:); + end + else + cal_m_db = m_db; + cal_f = f; + end + +end + +function ret = get_config(fn, var) + s = fileread(fn); + eval(s); + cmd = sprintf('ret = %s;', var); + eval(cmd); +end diff --git a/src/audio/google/CMakeLists.txt b/src/audio/google/CMakeLists.txt new file mode 100644 index 000000000000..fa55c9f39a2e --- /dev/null +++ b/src/audio/google/CMakeLists.txt @@ -0,0 +1,125 @@ +# SPDX-License-Identifier: BSD-3-Clause + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + set(THIRD_PARTY ${SOF_ROOT_SOURCE_DIRECTORY}/third_party) + if(CONFIG_IPC_MAJOR_3) + set(ipc_suffix ipc3) + elseif(CONFIG_IPC_MAJOR_4) + set(ipc_suffix ipc4) + endif() + + zephyr_library_sources_ifdef(CONFIG_COMP_GOOGLE_HOTWORD_DETECT + google_hotword_detect.c + ) + + if(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext_rtc + ${PROJECT_BINARY_DIR}/google_rtc_audio_processing_llext) + add_dependencies(app google_rtc_audio_processing) + elseif(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) + zephyr_library_sources(google_rtc_audio_processing.c) + + zephyr_library_sources_ifdef(CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK + google_rtc_audio_processing_mock.c + ) + + if(NOT CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK) + zephyr_include_directories(${THIRD_PARTY}/include) + target_link_directories(SOF INTERFACE ${THIRD_PARTY}/lib) + target_link_libraries(SOF INTERFACE google_rtc_audio_processing) + target_link_libraries(SOF INTERFACE c++) + target_link_libraries(SOF INTERFACE c++abi) + target_link_libraries(SOF INTERFACE m) + target_link_libraries(SOF INTERFACE c) + target_link_libraries(SOF INTERFACE gcc) + endif() + endif() + + if(CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext_ctc + ${PROJECT_BINARY_DIR}/google_ctc_audio_processing_llext) + add_dependencies(app google_ctc_audio_processing) + elseif(CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING) + zephyr_library_sources( + google_ctc_audio_processing.c + google_ctc_audio_processing_${ipc_suffix}.c + ) + zephyr_library_sources_ifdef(CONFIG_GOOGLE_CTC_AUDIO_PROCESSING_MOCK + google_ctc_audio_processing_mock.c + ) + + if(NOT CONFIG_GOOGLE_CTC_AUDIO_PROCESSING_MOCK) + zephyr_include_directories(${THIRD_PARTY}/include) + target_link_directories(SOF INTERFACE ${THIRD_PARTY}/lib) + target_link_libraries(SOF INTERFACE google_ctc_audio_processing) + target_link_libraries(SOF INTERFACE c++) + target_link_libraries(SOF INTERFACE c++abi) + target_link_libraries(SOF INTERFACE m) + target_link_libraries(SOF INTERFACE c) + target_link_libraries(SOF INTERFACE gcc) + endif() + endif() + + return() +endif() + +### Library build rules ### +if(CONFIG_LIBRARY_STATIC) + if(CONFIG_COMP_GOOGLE_HOTWORD_DETECT) + add_local_sources(sof + google_hotword_detect.c + ) + target_link_libraries(sof PRIVATE libhifi3_google_hotword_dsp_api.a) + target_link_libraries(sof PRIVATE c) + target_link_libraries(sof PRIVATE m) + endif() + + if(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) + target_include_directories(sof PRIVATE ${CMAKE_SOURCE_DIR}/third_party/include) + add_local_sources(sof + google_rtc_audio_processing.c + ) + if(CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK) + add_local_sources(sof + google_rtc_audio_processing_mock.c + ) + else() + message(INFO "Link with google_rtc_audio_processing") + target_link_directories(sof PRIVATE ${CMAKE_SOURCE_DIR}/third_party/lib) + target_link_libraries(sof PRIVATE google_rtc_audio_processing) + target_link_libraries(sof PRIVATE c++) + target_link_libraries(sof PRIVATE c++abi) + target_link_libraries(sof PRIVATE m) + target_link_libraries(sof PRIVATE c) + endif() + endif() + + if(CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING) + target_include_directories(sof PRIVATE ${CMAKE_SOURCE_DIR}/third_party/include) + add_local_sources(sof + google_ctc_audio_processing.c + ) + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof google_ctc_audio_processing_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof google_ctc_audio_processing_ipc4.c) + endif() + if(CONFIG_GOOGLE_CTC_AUDIO_PROCESSING_MOCK) + add_local_sources(sof + google_ctc_audio_processing_mock.c + ) + else() + message(INFO "Link with google_ctc_audio_processing") + target_link_directories(sof PRIVATE ${CMAKE_SOURCE_DIR}/third_party/lib) + target_link_libraries(sof PRIVATE google_ctc_audio_processing) + target_link_libraries(sof PRIVATE c++) + target_link_libraries(sof PRIVATE c++abi) + target_link_libraries(sof PRIVATE m) + target_link_libraries(sof PRIVATE c) + endif() + endif() + return() +endif() + diff --git a/src/audio/google/Kconfig b/src/audio/google/Kconfig new file mode 100644 index 000000000000..61d1608b6891 --- /dev/null +++ b/src/audio/google/Kconfig @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "Google components" + +config COMP_GOOGLE_HOTWORD_DETECT + bool "Google hotword detector component" + select COMP_BLOB + help + Select for Google hotword detector component. It uses the Google + hotword library to do keyword detection. A language model needs to + be set using the byte control 'Hotword Model' before running the + detector. + +config COMP_GOOGLE_RTC_AUDIO_PROCESSING + tristate "Google Real Time Communication Audio processing" + select COMP_BLOB + help + Select for Google real-time communication audio processing. It + uses the Google real-time audio processing library to perform + echo-cancelling and other processing. + This component takes raw microphones input and playback reference + and outputs an echo-free microphone signal. + +if COMP_GOOGLE_RTC_AUDIO_PROCESSING + +config COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ + int "Sample rate for Google Real Time Communication Audio processing" + default 48000 + help + Sets the sample rate for the memory buffer for the Google real-time + communication audio processing. + +config COMP_GOOGLE_RTC_AUDIO_PROCESSING_CHANNEL_MAX + int "Max number of AEC channels" + default 2 + help + Sets the maximum number source/sink processing channels Google Real + Time Communication Audio Processing will use for. This is a + computation and memory budget tunable. Channel counts are + retrieved at runtime, but channels higher than this number + are ignored (on input) or cleared (output). + + +config COMP_GOOGLE_RTC_AUDIO_REFERENCE_CHANNEL_MAX + int "Max number of AEC reference channels" + default 2 + help + Sets the maximum number source/sink reference channels Google Real + Time Communication Audio Processing will use for. This is a + computation and memory budget tunable. Channel counts are + retrieved at runtime, but channels higher than this number + are ignored + +config COMP_GOOGLE_RTC_AUDIO_PROCESSING_MEMORY_BUFFER_SIZE_KB + int "Memory buffer size for Google Real Time Communication Audio processing" + default 200 + help + Sets the size of the memory buffer for the Google real-time + communication audio processing. + +config COMP_GOOGLE_RTC_AUDIO_PROCESSING_ECHO_PATH_DELAY_MS + int "Echo path delay for Google Real Time Communication Audio processing" + default 44 + help + Sets the echo path delay to use for the Google real-time communication + audio processing. + +config COMP_GOOGLE_RTC_AUDIO_PROCESSING_MIC_HEADROOM_LINEAR + int "Microphone headroom for Google Real Time Communication Audio processing" + default 4 + help + Sets the microphone headroom for the Google real-time communication audio + processing. + +config GOOGLE_RTC_AUDIO_PROCESSING_MOCK + bool "Google Real Time Communication Audio processing mock" + default y if COMP_STUBS + help + Mock Google real-time communication audio processing. + It allows for compilation check and basic audio flow checking. + +endif # COMP_GOOGLE_RTC_AUDIO_PROCESSING + +config COMP_GOOGLE_CTC_AUDIO_PROCESSING + tristate "Google Crosstalk Cancellation Audio processing" + select COMP_BLOB + select GOOGLE_CTC_AUDIO_PROCESSING_MOCK if COMP_STUBS + select STATIC_INIT_GNU if ZEPHYR_SOF_MODULE + depends on ZEPHYR_SOF_MODULE + help + Select for Google crosstalk cancellation audio processing. It + uses the Google real-time audio processing library to perform + crosstalk cancellation. + +config GOOGLE_CTC_AUDIO_PROCESSING_MOCK + bool "Google Crosstalk Cancellation Audio processing mock" + default y if COMP_STUBS + depends on COMP_GOOGLE_CTC_AUDIO_PROCESSING + help + Mock Google crosstalk cancellation audio processing. + It allows for compilation check and basic audio flow checking. + +endmenu diff --git a/src/audio/google/README.md b/src/audio/google/README.md new file mode 100644 index 000000000000..feb5ce615b0a --- /dev/null +++ b/src/audio/google/README.md @@ -0,0 +1,10 @@ +# Google Custom Components Architecture + +This directory houses components specific to Google integrations, such as specialized wake-word or hotword engines. + +## Configuration and Scripts + +- **Kconfig**: Exposes menus for Google components, including `COMP_GOOGLE_HOTWORD_DETECT` (engine for hotword detection), `COMP_GOOGLE_RTC_AUDIO_PROCESSING` (acoustic echo cancellation with tunable memory size, sample rates, max channels, and reference max channels), and `COMP_GOOGLE_CTC_AUDIO_PROCESSING` (crosstalk cancellation). It also exposes mock definitions for CI testing (`COMP_STUBS`). +- **CMakeLists.txt**: Conditionally links external static libraries (`libhifi3_google_hotword_dsp_api.a`, `google_rtc_audio_processing`, `google_ctc_audio_processing`) from `third_party` tools. Defines Zephyr and non-Zephyr build pipelines. +- **google_rtc_audio_processing.toml / google_ctc_audio_processing.toml**: Specify topology module configurations for `RTC_AEC` and `CTC` models respectively with pinning mappings (like DMIC pins and playback references). +- **Topology (.conf)**: Incorporates `tools/topology/topology2/include/components/ctc.conf` (defaults to UUID `bc:1b:0e:bf:6a:dc:fe:45:bc:90:25:54:cb:13:7a:b4`) and `google-rtc-aec.conf` (defaults to UUID `a6:a0:80:b7:9f:26:6f:46:b4:77:23:df:a0:5a:f7:58`) with strict audio format channel maps (e.g. 2ch vs 4ch mappings). diff --git a/src/audio/google/google_ctc_audio_processing.c b/src/audio/google/google_ctc_audio_processing.c new file mode 100644 index 000000000000..0ee37abd24d5 --- /dev/null +++ b/src/audio/google/google_ctc_audio_processing.c @@ -0,0 +1,482 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Google LLC. +// +// Author: Eddy Hsu <eddyhsu@google.com> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <rtos/init.h> + +#include <google_ctc_audio_processing.h> + +#include "google_ctc_audio_processing.h" + +LOG_MODULE_REGISTER(google_ctc_audio_processing, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(google_ctc_audio_processing); + +// TODO(eddyhsu): Share these utils function with RTC. +static inline float clamp_rescale(float max_val, float x) +{ + float min = -1.0f; + float max = 1.0f - 1.0f / max_val; + + return max_val * (x < min ? min : (x > max ? max : x)); +} + +static inline int16_t convert_float_to_int16(float data) +{ + return (int16_t)clamp_rescale(-(float)SHRT_MIN, data); +} + +static inline float convert_int16_to_float(int16_t data) +{ + float scale = -(float)SHRT_MIN; + + return (1.0f / scale) * data; +} + +static inline int32_t convert_float_to_int32(float data) +{ + return (int32_t)clamp_rescale(-(float)INT_MIN, data); +} + +static inline float convert_int32_to_float(int32_t data) +{ + float scale = -(float)INT_MIN; + + return (1.0f / scale) * data; +} + +static const int kChunkFrames = 48; +static const int kMaxChannels = 2; + +static void ctc_passthrough(const struct audio_stream *source, + struct audio_stream *sink, + struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames) +{ + int n_ch = audio_stream_get_channels(source); + int samples = frames * n_ch; + + audio_stream_copy(source, 0, sink, 0, samples); + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frames); +} + +#if CONFIG_FORMAT_S16LE +static void ctc_s16_default(struct google_ctc_audio_processing_comp_data *cd, + const struct audio_stream *source, + struct audio_stream *sink, + struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames) +{ + int n_ch = audio_stream_get_channels(source); + int samples = frames * n_ch; + + int16_t *src = audio_stream_get_rptr(source); + int16_t *dest = audio_stream_get_wptr(sink); + + int samples_to_process = MIN(samples, audio_stream_samples_without_wrap_s16(source, src)); + int samples_to_written = MIN(samples, audio_stream_samples_without_wrap_s16(sink, dest)); + int written_samples = 0; + + if (!cd->enabled) { + ctc_passthrough(source, sink, input_buffers, output_buffers, frames); + return; + } + + // writes previous processed samples to the output. + while (cd->next_avail_output_samples < cd->chunk_frames * n_ch && + written_samples < samples_to_written) { + dest[written_samples++] = + convert_float_to_int16(cd->output[cd->next_avail_output_samples]); + cd->next_avail_output_samples++; + } + for (int i = 0; i < samples_to_process; ++i) { + cd->input[cd->input_samples++] = convert_int16_to_float(src[i]); + if (cd->input_samples == cd->chunk_frames * n_ch) { + GoogleCtcAudioProcessingProcess(cd->state, cd->input, cd->output, + cd->chunk_frames, n_ch); + cd->input_samples = 0; + cd->next_avail_output_samples = 0; + // writes processed samples to the output. + while (cd->next_avail_output_samples < cd->chunk_frames * n_ch && + written_samples < samples_to_written) { + dest[written_samples++] = + convert_float_to_int16(cd->output[cd->next_avail_output_samples]); + cd->next_avail_output_samples++; + } + } + } + if (written_samples > 0) { + dest = audio_stream_wrap(sink, dest + written_samples); + output_buffers->size += audio_stream_frame_bytes(sink) * written_samples / n_ch; + } + src = audio_stream_wrap(source, src + samples_to_process); + input_buffers->consumed += audio_stream_frame_bytes(source) * samples_to_process / n_ch; +} +#endif + +#if CONFIG_FORMAT_S24LE +static void ctc_s24_default(struct google_ctc_audio_processing_comp_data *cd, + const struct audio_stream *source, + struct audio_stream *sink, + struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames) +{ + int n_ch = audio_stream_get_channels(source); + int samples = frames * n_ch; + + int32_t *src = audio_stream_get_rptr(source); + int32_t *dest = audio_stream_get_wptr(sink); + + int samples_to_process = MIN(samples, audio_stream_samples_without_wrap_s24(source, src)); + int samples_to_written = MIN(samples, audio_stream_samples_without_wrap_s24(sink, dest)); + int written_samples = 0; + + if (!cd->enabled) { + ctc_passthrough(source, sink, input_buffers, output_buffers, frames); + return; + } + + // writes previous processed samples to the output. + while (cd->next_avail_output_samples < cd->chunk_frames * n_ch && + written_samples < samples_to_written) { + dest[written_samples++] = + convert_float_to_int32(cd->output[cd->next_avail_output_samples]); + cd->next_avail_output_samples++; + } + for (int i = 0; i < samples_to_process; ++i) { + cd->input[cd->input_samples++] = convert_int32_to_float(src[i]); + if (cd->input_samples == cd->chunk_frames * n_ch) { + GoogleCtcAudioProcessingProcess(cd->state, cd->input, cd->output, + cd->chunk_frames, n_ch); + cd->input_samples = 0; + cd->next_avail_output_samples = 0; + // writes processed samples to the output. + while (cd->next_avail_output_samples < cd->chunk_frames * n_ch && + written_samples < samples_to_written) { + dest[written_samples++] = + convert_float_to_int32(cd->output[cd->next_avail_output_samples]); + cd->next_avail_output_samples++; + } + } + } + if (written_samples > 0) { + dest = audio_stream_wrap(sink, dest + written_samples); + output_buffers->size += audio_stream_frame_bytes(sink) * written_samples / n_ch; + } + src = audio_stream_wrap(source, src + samples_to_process); + input_buffers->consumed += audio_stream_frame_bytes(source) * samples_to_process / n_ch; +} +#endif + +#if CONFIG_FORMAT_S32LE +static void ctc_s32_default(struct google_ctc_audio_processing_comp_data *cd, + const struct audio_stream *source, + struct audio_stream *sink, + struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames) +{ + int n_ch = audio_stream_get_channels(source); + int samples = frames * n_ch; + + int32_t *src = audio_stream_get_rptr(source); + int32_t *dest = audio_stream_get_wptr(sink); + + int samples_to_process = MIN(samples, audio_stream_samples_without_wrap_s32(source, src)); + int samples_to_written = MIN(samples, audio_stream_samples_without_wrap_s32(sink, dest)); + int written_samples = 0; + + if (!cd->enabled) { + ctc_passthrough(source, sink, input_buffers, output_buffers, frames); + return; + } + + // writes previous processed samples to the output. + while (cd->next_avail_output_samples < cd->chunk_frames * n_ch && + written_samples < samples_to_written) { + dest[written_samples++] = + convert_float_to_int32(cd->output[cd->next_avail_output_samples]); + cd->next_avail_output_samples++; + } + for (int i = 0; i < samples_to_process; ++i) { + cd->input[cd->input_samples++] = convert_int32_to_float(src[i]); + if (cd->input_samples == cd->chunk_frames * n_ch) { + GoogleCtcAudioProcessingProcess(cd->state, cd->input, cd->output, + cd->chunk_frames, n_ch); + cd->input_samples = 0; + cd->next_avail_output_samples = 0; + // writes processed samples to the output. + while (cd->next_avail_output_samples < cd->chunk_frames * n_ch && + written_samples < samples_to_written) { + dest[written_samples++] = + convert_float_to_int32(cd->output[cd->next_avail_output_samples]); + cd->next_avail_output_samples++; + } + } + } + if (written_samples > 0) { + dest = audio_stream_wrap(sink, dest + written_samples); + output_buffers->size += audio_stream_frame_bytes(sink) * written_samples / n_ch; + } + src = audio_stream_wrap(source, src + samples_to_process); + input_buffers->consumed += audio_stream_frame_bytes(source) * samples_to_process / n_ch; +} +#endif + +static int ctc_free(struct processing_module *mod) +{ + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + if (cd) { + mod_free(mod, cd->input); + mod_free(mod, cd->output); + GoogleCtcAudioProcessingFree(cd->state); + mod_data_blob_handler_free(mod, cd->tuning_handler); + mod_free(mod, cd); + module_set_private_data(mod, NULL); + } + + return 0; +} + +static int ctc_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct google_ctc_audio_processing_comp_data *cd; + int buf_size; + + comp_info(dev, "entry"); + + /* Create private component data */ + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) { + comp_err(dev, "Failed to create component data"); + ctc_free(mod); + return -ENOMEM; + } + + module_set_private_data(mod, cd); + + cd->chunk_frames = kChunkFrames; + buf_size = cd->chunk_frames * sizeof(cd->input[0]) * kMaxChannels; + + cd->input = mod_balloc(mod, buf_size); + if (!cd->input) { + comp_err(dev, "Failed to allocate input buffer"); + ctc_free(mod); + return -ENOMEM; + } + cd->output = mod_balloc(mod, buf_size); + if (!cd->output) { + comp_err(dev, "Failed to allocate output buffer"); + ctc_free(mod); + return -ENOMEM; + } + + cd->tuning_handler = mod_data_blob_handler_new(mod); + if (!cd->tuning_handler) { + comp_err(dev, "Failed to create tuning handler"); + ctc_free(mod); + return -ENOMEM; + } + + cd->enabled = true; + + comp_dbg(dev, "Ready"); + + return 0; +} + +static int google_ctc_audio_processing_reconfigure(struct processing_module *mod) +{ + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint8_t *config; + size_t size; + int ret; + + comp_dbg(dev, "entry"); + + config = comp_get_data_blob(cd->tuning_handler, &size, NULL); + if (size == 0) { + /* No data to be handled */ + return 0; + } + + if (!config) { + comp_err(dev, "Tuning config not set"); + return -EINVAL; + } + + comp_info(dev, "New tuning config %p (%zu bytes)", + config, size); + + cd->reconfigure = false; + comp_info(dev, + "Applying config of size %zu bytes", + size); + ret = GoogleCtcAudioProcessingReconfigure(cd->state, config, size); + if (ret) { + comp_err(dev, "GoogleCtcAudioProcessingReconfigure failed: %d", + ret); + return ret; + } + return 0; +} + +static int ctc_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *source; + int num_channels; + uint8_t *config; + int config_size; + + comp_info(mod->dev, "entry"); + + source = comp_dev_get_first_data_producer(dev); + if (!source) { + comp_err(dev, "no source buffer"); + return -ENOTCONN; + } + + switch (audio_stream_get_frm_fmt(&source->stream)) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + cd->ctc_func = ctc_s16_default; + break; +#endif +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + cd->ctc_func = ctc_s24_default; + break; +#endif +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + cd->ctc_func = ctc_s32_default; + break; +#endif + default: + comp_err(mod->dev, "invalid frame_fmt"); + return -EINVAL; + } + + num_channels = audio_stream_get_channels(&source->stream); + if (num_channels > kMaxChannels) { + comp_err(mod->dev, "invalid number of channels"); + return -EINVAL; + } + cd->next_avail_output_samples = cd->chunk_frames * num_channels; + + config = comp_get_data_blob(cd->tuning_handler, &config_size, NULL); + + if (config_size != CTC_BLOB_CONFIG_SIZE) { + comp_info(mod->dev, "config_size not expected: %d", config_size); + config = NULL; + config_size = 0; + } + cd->state = GoogleCtcAudioProcessingCreateWithConfig(cd->chunk_frames, + audio_stream_get_rate(&source->stream), + config, + config_size); + if (!cd->state) { + comp_err(mod->dev, "failed to create CTC"); + return -ENOMEM; + } + + return 0; +} + +static int ctc_reset(struct processing_module *mod) +{ + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + size_t buf_size = cd->chunk_frames * sizeof(cd->input[0]) * kMaxChannels; + + comp_info(mod->dev, "entry"); + + GoogleCtcAudioProcessingFree(cd->state); + cd->state = NULL; + cd->ctc_func = NULL; + cd->input_samples = 0; + cd->next_avail_output_samples = 0; + memset(cd->input, 0, buf_size); + memset(cd->output, 0, buf_size); + return 0; +} + +static int ctc_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 google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + uint32_t frames = input_buffers[0].size; + + int ret; + + comp_dbg(mod->dev, "entry"); + + if (cd->reconfigure) { + ret = google_ctc_audio_processing_reconfigure(mod); + if (ret) + return ret; + } + + cd->ctc_func(cd, source, sink, &input_buffers[0], &output_buffers[0], frames); + return 0; +} + +static const struct module_interface google_ctc_audio_processing_interface = { + .init = ctc_init, + .free = ctc_free, + .process_audio_stream = ctc_process, + .prepare = ctc_prepare, + .set_configuration = ctc_set_config, + .get_configuration = ctc_get_config, + .reset = ctc_reset, +}; + +#if CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("CTC", &google_ctc_audio_processing_interface, + 1, SOF_REG_UUID(google_ctc_audio_processing), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(google_ctc_audio_processing_tr, SOF_UUID(google_ctc_audio_processing_uuid), + LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(google_ctc_audio_processing_interface, + google_ctc_audio_processing_uuid, google_ctc_audio_processing_tr); +SOF_MODULE_INIT(google_ctc_audio_processing, + sys_comp_module_google_ctc_audio_processing_interface_init); + +#endif diff --git a/src/audio/google/google_ctc_audio_processing.h b/src/audio/google/google_ctc_audio_processing.h new file mode 100644 index 000000000000..df537c3dc51e --- /dev/null +++ b/src/audio/google/google_ctc_audio_processing.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Google LLC. + * + * Author: Eddy Hsu <eddyhsu@google.com> + */ +#ifndef __SOF_AUDIO_GOOGLE_GOOGLE_CTC_AUDIO_PROCESSING_H__ +#define __SOF_AUDIO_GOOGLE_GOOGLE_CTC_AUDIO_PROCESSING_H__ + +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <rtos/init.h> + +#include <google_ctc_audio_processing.h> + +struct google_ctc_audio_processing_comp_data; + +typedef void (*ctc_func)(struct google_ctc_audio_processing_comp_data *cd, + const struct audio_stream *source, + struct audio_stream *sink, + struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames); + +struct google_ctc_audio_processing_comp_data { + float *input; + float *output; + uint32_t input_samples; + uint32_t next_avail_output_samples; + uint32_t chunk_frames; + GoogleCtcAudioProcessingState *state; + struct comp_data_blob_handler *tuning_handler; + bool enabled; + bool reconfigure; + ctc_func ctc_func; +}; + +struct google_ctc_config { + /* size of the whole ctc config */ + uint32_t size; + + /* reserved */ + uint32_t reserved[4]; + + uint32_t data[]; +} __packed; + +#define CTC_BLOB_DATA_SIZE 4100 +#define CTC_BLOB_CONFIG_SIZE (sizeof(struct google_ctc_config) + CTC_BLOB_DATA_SIZE) + +int ctc_set_config(struct processing_module *mod, uint32_t param_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); + +int ctc_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); + +#endif // __SOF_AUDIO_GOOGLE_GOOGLE_CTC_AUDIO_PROCESSING_H__ diff --git a/src/audio/google/google_ctc_audio_processing.toml b/src/audio/google/google_ctc_audio_processing.toml new file mode 100644 index 000000000000..4bea054225fc --- /dev/null +++ b/src/audio/google/google_ctc_audio_processing.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # CTC module config + [[module.entry]] + name = "CTC" + uuid = UUIDREG_STR_GOOGLE_CTC_AUDIO_PROCESSING + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/google/google_ctc_audio_processing_ipc3.c b/src/audio/google/google_ctc_audio_processing_ipc3.c new file mode 100644 index 000000000000..8f6594203420 --- /dev/null +++ b/src/audio/google/google_ctc_audio_processing_ipc3.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Google LLC. +// +// Author: Eddy Hsu <eddyhsu@google.com> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <rtos/init.h> + +#include "google_ctc_audio_processing.h" + +LOG_MODULE_DECLARE(google_ctc_audio_processing, CONFIG_SOF_LOG_LEVEL); + +int ctc_set_config(struct processing_module *mod, uint32_t param_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 sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + int ret; + struct google_ctc_config *config; + int size; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + ret = comp_data_blob_set_cmd(cd->tuning_handler, cdata); + if (ret) + return ret; + if (comp_is_new_data_blob_available(cd->tuning_handler)) { + config = comp_get_data_blob(cd->tuning_handler, &size, NULL); + if (size != CTC_BLOB_CONFIG_SIZE) { + comp_err(mod->dev, + "Invalid config size = %d", + size); + return -EINVAL; + } + if (config->size != CTC_BLOB_CONFIG_SIZE) { + comp_err(mod->dev, + "Invalid config->size = %d", + config->size); + return -EINVAL; + } + cd->reconfigure = true; + } + return 0; + case SOF_CTRL_CMD_SWITCH: + if (cdata->num_elems == 1) { + cd->enabled = cdata->chanv[0].value; + comp_info(mod->dev, "enabled = %d", + cd->enabled); + return 0; + } + comp_err(mod->dev, + "Illegal num_elems = %d", + cdata->num_elems); + return -EINVAL; + default: + comp_err(mod->dev, + "Only binary and switch controls supported %d", + cdata->cmd); + return -EINVAL; + } +} + +int ctc_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "%u", cdata->cmd); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return comp_data_blob_get_cmd(cd->tuning_handler, cdata, fragment_size); + case SOF_CTRL_CMD_SWITCH: + return comp_data_blob_get_cmd(cd->tuning_handler, cdata, fragment_size); + default: + return -EINVAL; + } +} diff --git a/src/audio/google/google_ctc_audio_processing_ipc4.c b/src/audio/google/google_ctc_audio_processing_ipc4.c new file mode 100644 index 000000000000..fa5f265e9d0f --- /dev/null +++ b/src/audio/google/google_ctc_audio_processing_ipc4.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Google LLC. +// +// Author: Eddy Hsu <eddyhsu@google.com> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <rtos/init.h> + +#include "google_ctc_audio_processing.h" + +LOG_MODULE_DECLARE(google_ctc_audio_processing, CONFIG_SOF_LOG_LEVEL); + +int ctc_set_config(struct processing_module *mod, uint32_t param_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 sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + int ret; + struct google_ctc_config *config; + int size; + + switch (param_id) { + case 0: + break; + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + if (ctl->id == 0 && ctl->num_elems == 1) { + cd->enabled = ctl->chanv[0].value; + comp_info(mod->dev, "enabled = %d", cd->enabled); + return 0; + } + comp_err(mod->dev, "Illegal control id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + return -EINVAL; + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + default: + comp_err(mod->dev, "Only binary and switch controls supported"); + return -EINVAL; + } + + ret = comp_data_blob_set(cd->tuning_handler, pos, data_offset_size, + fragment, fragment_size); + if (ret) + return ret; + + if (comp_is_new_data_blob_available(cd->tuning_handler)) { + config = comp_get_data_blob(cd->tuning_handler, &size, NULL); + if (size != CTC_BLOB_CONFIG_SIZE) { + comp_err(mod->dev, + "Invalid config size = %d", + size); + return -EINVAL; + } + if (config->size != CTC_BLOB_CONFIG_SIZE) { + comp_err(mod->dev, + "Invalid config->size = %d", + config->size); + return -EINVAL; + } + cd->reconfigure = true; + } + + return 0; +} + +int ctc_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct google_ctc_audio_processing_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "%u", cdata->cmd); + + return comp_data_blob_get_cmd(cd->tuning_handler, cdata, fragment_size); +} diff --git a/src/audio/google/google_ctc_audio_processing_mock.c b/src/audio/google/google_ctc_audio_processing_mock.c new file mode 100644 index 000000000000..f3f004d38ebb --- /dev/null +++ b/src/audio/google/google_ctc_audio_processing_mock.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Google LLC. +// +// Author: Eddy Hsu <eddyhsu@google.com> +#include "google_ctc_audio_processing.h" + +#include <rtos/alloc.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "ipc/topology.h" + +struct GoogleCtcAudioProcessingState { +}; + +GoogleCtcAudioProcessingState *GoogleCtcAudioProcessingCreate(void) +{ + struct GoogleCtcAudioProcessingState *s = + rballoc(SOF_MEM_FLAG_USER, sizeof(GoogleCtcAudioProcessingState)); + if (!s) + return NULL; + + return s; +} + +GoogleCtcAudioProcessingState *GoogleCtcAudioProcessingCreateWithConfig(int chunk_size, + int sample_rate, + const uint8_t *config, + int config_size) +{ + struct GoogleCtcAudioProcessingState *s = + rballoc(SOF_MEM_FLAG_USER, sizeof(GoogleCtcAudioProcessingState)); + if (!s) + return NULL; + + return s; +} + +void GoogleCtcAudioProcessingFree(GoogleCtcAudioProcessingState *state) +{ + rfree(state); +} + +void GoogleCtcAudioProcessingProcess(GoogleCtcAudioProcessingState *state, + const float *src, float *dest, + int num_frames, int num_channels) +{ + memcpy_s(dest, sizeof(float) * num_frames * num_channels, + src, sizeof(float) * num_frames * num_channels); +} + +int GoogleCtcAudioProcessingReconfigure(GoogleCtcAudioProcessingState *state, + const uint8_t *config, int config_size) +{ + return 0; +} diff --git a/src/audio/google/google_hotword_detect.c b/src/audio/google/google_hotword_detect.c new file mode 100644 index 000000000000..f7cf44f026fd --- /dev/null +++ b/src/audio/google/google_hotword_detect.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Ben Zhang <benzh@chromium.org> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/kpb.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/notifier.h> +#include <rtos/wait.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <kernel/abi.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +#include <hotword_dsp_api.h> + +/* IPC blob types */ +#define GOOGLE_HOTWORD_DETECT_MODEL 0 + +static const struct comp_driver ghd_driver; + +LOG_MODULE_REGISTER(google_hotword_detect, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(google_hotword); + +struct comp_data { + struct comp_data_blob_handler *model_handler; + struct kpb_event_data event_data; + struct kpb_client client_data; + + struct ipc_msg *msg; + + int detected; + size_t history_bytes; + struct sof_ipc_comp_event event; +}; + +static void notify_host(const struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + ipc_msg_send(cd->msg, &cd->event, true); +} + +static void notify_kpb(const struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + cd->client_data.r_ptr = NULL; + cd->client_data.sink = NULL; + cd->client_data.id = 0; + cd->event_data.event_id = KPB_EVENT_BEGIN_DRAINING; + cd->event_data.client_data = &cd->client_data; + + notifier_event(dev, NOTIFIER_ID_KPB_CLIENT_EVT, + NOTIFIER_TARGET_CORE_ALL_MASK, &cd->event_data, + sizeof(cd->event_data)); +} + +static struct comp_dev *ghd_create(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(drv, "ghd_create()"); + + /* Create component device with an effect processing component */ + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + + dev->ipc_config = *config; + + /* Create private component data */ + cd = rzalloc(SOF_MEM_FLAG_USER, + sizeof(*cd)); + if (!cd) + goto fail; + comp_set_drvdata(dev, cd); + + /* Build component event */ + ipc_build_comp_event(&cd->event, dev->ipc_config.type, dev->ipc_config.id); + cd->event.event_type = SOF_CTRL_EVENT_KD; + cd->event.num_elems = 0; + + cd->msg = ipc_msg_init(cd->event.rhdr.hdr.cmd, cd->event.rhdr.hdr.size); + if (!cd->msg) { + comp_err(dev, "ipc_msg_init failed"); + goto cd_fail; + } + + /* Create component model data handler */ + cd->model_handler = comp_data_blob_handler_new(dev); + if (!cd->model_handler) { + comp_err(dev, "comp_data_blob_handler_new failed"); + goto cd_fail; + } + + dev->state = COMP_STATE_READY; + comp_dbg(dev, "Ready"); + return dev; + +cd_fail: + comp_data_blob_handler_free(cd->model_handler); + ipc_msg_free(cd->msg); + rfree(cd); +fail: + comp_free_device(dev); + return NULL; +} + +static void ghd_free(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + comp_data_blob_handler_free(cd->model_handler); + ipc_msg_free(cd->msg); + rfree(cd); + comp_free_device(dev); +} + +static int ghd_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_buffer *sourceb; + int ret; + + /* Detector is used only in KPB topology. It always requires channels + * parameter set to 1. + */ + params->channels = 1; + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params failed."); + return -EINVAL; + } + + /* This detector component will only ever have 1 source */ + sourceb = comp_dev_get_first_data_producer(dev); + + if (audio_stream_get_channels(sourceb->stream) != 1) { + comp_err(dev, "Only single-channel supported"); + ret = -EINVAL; + } else if (audio_stream_get_frm_fmt(&sourceb->stream) != SOF_IPC_FRAME_S16_LE) { + comp_err(dev, "Only S16_LE supported"); + ret = -EINVAL; + } else if (sourceb->stream.rate != KPB_SAMPLNG_FREQUENCY) { + comp_err(dev, "Only 16KHz supported"); + ret = -EINVAL; + } + + return ret; +} + +static int ghd_setup_model(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + void *model; + size_t size; + int ret; + + /* Avoid the CRC calculation since it takes too long and causes XRUN. + * + * TODO: Add it back when there is support for running it in a low + * priority background task. + */ + model = comp_get_data_blob(cd->model_handler, &size, NULL); + if (!model || !size) { + comp_err(dev, "Model not set"); + return -EINVAL; + } + comp_info(dev, "Model: data=0x%08x, size=%zu", + (uint32_t)model, size); + + comp_info(dev, "GoogleHotwordVersion %d", + GoogleHotwordVersion()); + + ret = GoogleHotwordDspInit(model); + cd->detected = 0; + cd->history_bytes = 0; + if (ret != 1) { + comp_err(dev, "GoogleHotwordDSPInit failed: %d", ret); + return -EINVAL; + } + + return 0; +} + +#if CONFIG_IPC_MAJOR_3 +static int ghd_ctrl_set_bin_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int ret; + + switch (cdata->data->type) { + case GOOGLE_HOTWORD_DETECT_MODEL: + ret = comp_data_blob_set_cmd(cd->model_handler, cdata); + comp_dbg(dev, "comp_data_blob_set_cmd=%d", + ret); + return ret; + default: + comp_err(dev, "Unknown cdata->data->type %d", + cdata->data->type); + return -EINVAL; + } +} + +static int ghd_ctrl_set_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return ghd_ctrl_set_bin_data(dev, cdata); + default: + comp_err(dev, "Only binary controls supported %d", + cdata->cmd); + return -EINVAL; + } +} + +static int ghd_ctrl_get_bin_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, + int max_data_size) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int ret; + + switch (cdata->data->type) { + case GOOGLE_HOTWORD_DETECT_MODEL: + ret = comp_data_blob_get_cmd(cd->model_handler, + cdata, + max_data_size); + comp_dbg(dev, "comp_data_blob_get_cmd=%d, size=%d", + ret, max_data_size); + return ret; + default: + comp_err(dev, "Unknown cdata->data->type %d", + cdata->data->type); + return -EINVAL; + } +} + +static int ghd_ctrl_get_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, + int max_data_size) +{ + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return ghd_ctrl_get_bin_data(dev, cdata, max_data_size); + default: + comp_err(dev, "Only binary controls supported %d", + cdata->cmd); + return -EINVAL; + } +} + +static int ghd_cmd(struct comp_dev *dev, int cmd, void *data, + int max_data_size) +{ + struct sof_ipc_ctrl_data *cdata = data; + + comp_dbg(dev, "%d", cmd); + + switch (cmd) { + case COMP_CMD_SET_DATA: + return ghd_ctrl_set_data(dev, cdata); + case COMP_CMD_GET_DATA: + return ghd_ctrl_get_data(dev, cdata, max_data_size); + default: + comp_err(dev, "Unknown cmd %d", cmd); + return -EINVAL; + } +} +#endif + +static int ghd_trigger(struct comp_dev *dev, int cmd) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "%d", cmd); + + if (cmd == COMP_TRIGGER_START || cmd == COMP_TRIGGER_RELEASE) { + cd->detected = 0; + cd->history_bytes = 0; + GoogleHotwordDspReset(); + } + + return comp_set_state(dev, cmd); +} + +static void ghd_detect(struct comp_dev *dev, + struct audio_stream *stream, + const void *samples, + uint32_t bytes) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int preamble_length_ms = 0; + uint32_t sample_bytes; + int ret; + + if (cd->detected) + return; + + /* Assuming 1 channel, verified in ghd_params. + * + * TODO Make the logic multi channel safe when new hotword library can + * utilize multi channel data for detection. + */ + sample_bytes = audio_stream_sample_bytes(stream); + + if (cd->history_bytes < + KPB_MAX_BUFF_TIME * KPB_SAMPLES_PER_MS * sample_bytes) { + cd->history_bytes += bytes; + } + + comp_dbg(dev, "GoogleHotwordDspProcess(0x%x, %u)", + (uint32_t)samples, bytes / sample_bytes); + ret = GoogleHotwordDspProcess(samples, bytes / sample_bytes, + &preamble_length_ms); + if (ret == 1) { + cd->detected = 1; + + /* The current version of GoogleHotwordDspProcess always + * reports 2000ms preamble. Clamp this by the actual history + * length so KPB doesn't complain not enough data to drain when + * the hotword is detected right after pcm device open. + */ + cd->client_data.drain_req = + MIN((size_t)preamble_length_ms, + (cd->history_bytes / sample_bytes) / + KPB_SAMPLES_PER_MS); + + /* drain_req is actually in ms. See kpb_init_draining. */ + comp_info(dev, "Hotword detected %dms", + cd->client_data.drain_req); + notify_host(dev); + notify_kpb(dev); + } +} + +static int ghd_copy(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *source; + struct audio_stream *stream; + uint32_t bytes, tail_bytes, head_bytes = 0; + int ret; + + /* Check for new model */ + if (comp_is_new_data_blob_available(cd->model_handler)) { + comp_dbg(dev, "Switch to new model"); + ret = ghd_setup_model(dev); + if (ret) + return ret; + } + + /* keyword components will only ever have 1 source */ + source = comp_dev_get_first_data_producer(dev); + stream = &sourceb->stream; + + bytes = audio_stream_get_avail_bytes(stream); + + comp_dbg(dev, "avail_bytes %u", bytes); + comp_dbg(dev, "buffer begin/r_ptr/end [0x%x 0x%x 0x%x]", + (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(sourceb, bytes); + + 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, audio_stream_get_rptr(stream), tail_bytes); + if (head_bytes) + ghd_detect(dev, stream, audio_stream_get_addr(stream), head_bytes); + + /* calc new available */ + comp_update_buffer_consume(sourceb, bytes); + + return 0; +} + +static int ghd_reset(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + cd->detected = 0; + cd->history_bytes = 0; + GoogleHotwordDspReset(); + + return comp_set_state(dev, COMP_TRIGGER_RESET); +} + +static int ghd_prepare(struct comp_dev *dev) +{ + int ret; + + comp_dbg(dev, "entry"); + + ret = ghd_setup_model(dev); + if (ret) + return ret; + + return comp_set_state(dev, COMP_TRIGGER_PREPARE); +} + +DECLARE_TR_CTX(ghd_tr, SOF_UUID(ghd_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver ghd_driver = { + .type = SOF_COMP_KEYWORD_DETECT, + .uid = SOF_RT_UUID(ghd_uuid), + .tctx = &ghd_tr, + .ops = { + .create = ghd_create, + .free = ghd_free, + .params = ghd_params, +#if CONFIG_IPC_MAJOR_3 + .cmd = ghd_cmd, +#endif + .trigger = ghd_trigger, + .copy = ghd_copy, + .prepare = ghd_prepare, + .reset = ghd_reset, + }, +}; + +static SHARED_DATA struct comp_driver_info ghd_driver_info = { + .drv = &ghd_driver, +}; + +UT_STATIC void sys_comp_ghd_init(void) +{ + comp_register(platform_shared_get(&ghd_driver_info, + sizeof(ghd_driver_info))); +} + +DECLARE_MODULE(sys_comp_ghd_init); +SOF_MODULE_INIT(ghd, sys_comp_ghd_init); diff --git a/src/audio/google/google_rtc_audio_processing.c b/src/audio/google/google_rtc_audio_processing.c new file mode 100644 index 000000000000..7c50bca874c5 --- /dev/null +++ b/src/audio/google/google_rtc_audio_processing.c @@ -0,0 +1,870 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Google LLC. +// +// Author: Lionel Koenig <lionelk@google.com> +#include <errno.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/aec.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/kpb.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <user/trace.h> + +/* Zephyr provides uncached memory for static variables on SMP, but we + * are single-core component and know we can safely use the cache for + * AEC work. XTOS SOF is cached by default, so stub the Zephyr API. + */ +#ifdef __ZEPHYR__ +#include <zephyr/cache.h> +#else +#define sys_cache_cached_ptr_get(p) (p) +#define ALWAYS_INLINE inline __attribute__((always_inline)) +#endif + +#include <google_rtc_audio_processing.h> +#include <google_rtc_audio_processing_platform.h> +#include <google_rtc_audio_processing_sof_message_reader.h> + +#define GOOGLE_RTC_AUDIO_PROCESSING_FREQENCY_TO_PERIOD_FRAMES 100 +#define GOOGLE_RTC_NUM_INPUT_PINS 2 + +LOG_MODULE_REGISTER(google_rtc_audio_processing, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(google_rtc_audio_processing); + +static __aligned(PLATFORM_DCACHE_ALIGN) +uint8_t aec_mem_blob[CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_MEMORY_BUFFER_SIZE_KB * 1024]; + +#define NUM_FRAMES (CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ \ + / GOOGLE_RTC_AUDIO_PROCESSING_FREQENCY_TO_PERIOD_FRAMES) +#define CHAN_MAX CONFIG_COMP_GOOGLE_RTC_AUDIO_REFERENCE_CHANNEL_MAX + +static __aligned(PLATFORM_DCACHE_ALIGN) +float refoutbuf[CHAN_MAX][NUM_FRAMES]; + +static __aligned(PLATFORM_DCACHE_ALIGN) +float micbuf[CHAN_MAX][NUM_FRAMES]; + +struct google_rtc_audio_processing_comp_data { + uint32_t num_frames; + int num_aec_reference_channels; + int num_capture_channels; + GoogleRtcAudioProcessingState *state; + float *raw_mic_buffers[CHAN_MAX]; + float *refout_buffers[CHAN_MAX]; + int buffered_frames; + struct comp_data_blob_handler *tuning_handler; + bool reconfigure; + bool last_ref_ok; + int aec_reference_source; + int raw_microphone_source; +#ifdef CONFIG_IPC_MAJOR_3 + struct comp_buffer *ref_comp_buffer; +#endif + int ref_framesz; + int cap_framesz; + void (*mic_copy)(struct sof_source *src, int frames, float **dst_bufs, int frame0); + void (*ref_copy)(struct sof_source *src, int frames, float **dst_bufs, int frame0); + void (*out_copy)(struct sof_sink *dst, int frames, float **src_bufs); +}; + +/* The underlying API is not sparse-aware, so rather than try to + * finesse the conversions everywhere the buffers touch, turn checking + * off when we computed the cached address + */ +static void *cached_ptr(void *p) +{ + return (__sparse_force void *) sys_cache_cached_ptr_get(p); +} + +void *GoogleRtcMalloc(size_t size) +{ + return rballoc(SOF_MEM_FLAG_USER, size); +} + +void GoogleRtcFree(void *ptr) +{ + return rfree(ptr); +} + +static ALWAYS_INLINE float clamp_rescale(float max_val, float x) +{ + float min = -1.0f; + float max = 1.0f - 1.0f / max_val; + + return max_val * (x < min ? min : (x > max ? max : x)); +} + +static ALWAYS_INLINE float s16_to_float(const char *ptr) +{ + float scale = -(float)SHRT_MIN; + float x = *(int16_t *)ptr; + + return (1.0f / scale) * x; +} + +static ALWAYS_INLINE void float_to_s16(float x, char *dst) +{ + *(int16_t *)dst = (int16_t)clamp_rescale(-(float)SHRT_MIN, x); +} + +static ALWAYS_INLINE float s32_to_float(const char *ptr) +{ + float scale = -(float)INT_MIN; + float x = *(int32_t *)ptr; + + return (1.0f / scale) * x; +} + +static ALWAYS_INLINE void float_to_s32(float x, char *dst) +{ + *(int32_t *)dst = (int16_t)clamp_rescale(-(float)INT_MIN, x); +} + +static ALWAYS_INLINE void source_to_float(struct sof_source *src, float **dst_bufs, + float (*cvt_fn)(const char *), + int sample_sz, int frame0, int frames) +{ + size_t chan = source_get_channels(src); + size_t bytes = frames * chan * sample_sz; + int i, c, err, ndst = MIN(chan, CHAN_MAX); + const char *buf, *bufstart, *bufend; + float *dst[CHAN_MAX]; + size_t bufsz; + + for (i = 0; i < ndst; i++) + dst[i] = &dst_bufs[i][frame0]; + + err = source_get_data(src, bytes, (void *)&buf, (void *)&bufstart, &bufsz); + assert(err == 0); + bufend = &bufstart[bufsz]; + + while (frames) { + size_t n = MIN(frames, (bufsz - (buf - bufstart)) / (chan * sample_sz)); + + for (i = 0; i < n; i++) { + for (c = 0; c < ndst; c++) { + *dst[c]++ = cvt_fn(buf); + buf += sample_sz; + } + buf += sample_sz * (chan - ndst); /* skip unused channels */ + } + frames -= n; + if (buf >= bufend) + buf = bufstart; + } + source_release_data(src, bytes); +} + +static ALWAYS_INLINE void float_to_sink(struct sof_sink *dst, float **src_bufs, + void (*cvt_fn)(float, char *), + int sample_sz, int frames) +{ + size_t chan = sink_get_channels(dst); + size_t bytes = frames * chan * sample_sz; + int i, c, err, nsrc = MIN(chan, CHAN_MAX); + char *buf, *bufstart, *bufend; + float *src[CHAN_MAX]; + size_t bufsz; + + for (i = 0; i < nsrc; i++) + src[i] = &src_bufs[i][0]; + + err = sink_get_buffer(dst, bytes, (void *)&buf, (void *)&bufstart, &bufsz); + assert(err == 0); + bufend = &bufstart[bufsz]; + + while (frames) { + size_t n = MIN(frames, (bufsz - (buf - bufstart)) / (chan * sample_sz)); + + for (i = 0; i < n; i++) { + for (c = 0; c < nsrc; c++) { + cvt_fn(*src[c]++, buf); + buf += sample_sz; + } + buf += sample_sz * (chan - nsrc); /* skip unused channels */ + } + frames -= n; + if (buf >= bufend) + buf = bufstart; + } + sink_commit_buffer(dst, bytes); +} + +static void source_copy16(struct sof_source *src, int frames, float **dst_bufs, int frame0) +{ + source_to_float(src, dst_bufs, s16_to_float, sizeof(int16_t), frame0, frames); +} + +static void source_copy32(struct sof_source *src, int frames, float **dst_bufs, int frame0) +{ + source_to_float(src, dst_bufs, s32_to_float, sizeof(int32_t), frame0, frames); +} + +static void sink_copy16(struct sof_sink *dst, int frames, float **src_bufs) +{ + float_to_sink(dst, src_bufs, float_to_s16, sizeof(int16_t), frames); +} + +static void sink_copy32(struct sof_sink *dst, int frames, float **src_bufs) +{ + float_to_sink(dst, src_bufs, float_to_s32, sizeof(int32_t), frames); +} + +static int google_rtc_audio_processing_reconfigure(struct processing_module *mod) +{ + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint8_t *config; + size_t size; + int ret; + + comp_dbg(dev, "entry"); + + if (!comp_is_current_data_blob_valid(cd->tuning_handler) && + !comp_is_new_data_blob_available(cd->tuning_handler)) { + /* + * The data blob hasn't been available once so far. + * + * This looks redundant since the same check will be done in + * comp_get_data_blob() below. But without this early return, + * hundreds of warn message lines are produced per second by + * comp_get_data_blob() calls until the data blob is arrived. + */ + return 0; + } + + config = comp_get_data_blob(cd->tuning_handler, &size, NULL); + if (size == 0) { + /* No data to be handled */ + return 0; + } + + if (!config) { + comp_err(dev, "Tuning config not set"); + return -EINVAL; + } + + comp_info(dev, "New tuning config %p (%zu bytes)", + config, size); + + cd->reconfigure = false; + + uint8_t *google_rtc_audio_processing_config; + size_t google_rtc_audio_processing_config_size; + int num_capture_input_channels; + int num_capture_output_channels; + float aec_reference_delay; + float mic_gain; + bool google_rtc_audio_processing_config_present; + bool num_capture_input_channels_present; + bool num_capture_output_channels_present; + bool aec_reference_delay_present; + bool mic_gain_present; + + GoogleRtcAudioProcessingParseSofConfigMessage(config, size, + &google_rtc_audio_processing_config, + &google_rtc_audio_processing_config_size, + &num_capture_input_channels, + &num_capture_output_channels, + &aec_reference_delay, + &mic_gain, + &google_rtc_audio_processing_config_present, + &num_capture_input_channels_present, + &num_capture_output_channels_present, + &aec_reference_delay_present, + &mic_gain_present); + + if (google_rtc_audio_processing_config_present) { + comp_info(dev, + "Applying config of size %zu bytes", + google_rtc_audio_processing_config_size); + + ret = GoogleRtcAudioProcessingReconfigure(cd->state, + google_rtc_audio_processing_config, + google_rtc_audio_processing_config_size); + if (ret) { + comp_err(dev, "GoogleRtcAudioProcessingReconfigure failed: %d", + ret); + return ret; + } + } + + if (num_capture_input_channels_present || num_capture_output_channels_present) { + if (num_capture_input_channels_present && num_capture_output_channels_present) { + if (num_capture_input_channels != num_capture_output_channels) { + comp_err(dev, "GoogleRtcAudioProcessingReconfigure failed: unsupported channel counts"); + return -EINVAL; + } + cd->num_capture_channels = num_capture_input_channels; + } else if (num_capture_input_channels_present) { + cd->num_capture_channels = num_capture_output_channels; + } else { + cd->num_capture_channels = num_capture_output_channels; + } + comp_info(dev, + "Applying num capture channels %d", + cd->num_capture_channels); + + + ret = GoogleRtcAudioProcessingSetStreamFormats(cd->state, + CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ, + cd->num_capture_channels, + cd->num_capture_channels, + CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ, + cd->num_aec_reference_channels); + + if (ret) { + comp_err(dev, "GoogleRtcAudioProcessingSetStreamFormats failed: %d", + ret); + return ret; + } + } + + if (aec_reference_delay_present || mic_gain_present) { + float *capture_headroom_linear_use = NULL; + float *echo_path_delay_ms_use = NULL; + + if (mic_gain_present) { + capture_headroom_linear_use = &mic_gain; + + /* Logging of linear headroom, using integer workaround to the broken printout of floats */ + comp_info(dev, + "Applying capture linear headroom: %d.%d", + (int)mic_gain, (int)(100 * mic_gain) - 100 * ((int)mic_gain)); + } + if (aec_reference_delay_present) { + echo_path_delay_ms_use = &aec_reference_delay; + + /* Logging of delay, using integer workaround to the broken printout of floats */ + comp_info(dev, + "Applying aec reference delay: %d.%d", + (int)aec_reference_delay, + (int)(100 * aec_reference_delay) - + 100 * ((int)aec_reference_delay)); + } + + ret = GoogleRtcAudioProcessingParameters(cd->state, + capture_headroom_linear_use, + echo_path_delay_ms_use); + + if (ret) { + comp_err(dev, "GoogleRtcAudioProcessingParameters failed: %d", + ret); + return ret; + } + } + + return 0; +} + +#if CONFIG_IPC_MAJOR_3 +static int google_rtc_audio_processing_cmd_set_data(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + int ret; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + ret = comp_data_blob_set_cmd(cd->tuning_handler, cdata); + if (ret) + return ret; + /* Accept the new blob immediately so that userspace can write + * the control in quick succession without error. + * This ensures the last successful control write from userspace + * before prepare/copy is applied. + * The config blob is not referenced after reconfigure() returns + * so it is safe to call comp_get_data_blob here which frees the + * old blob. This assumes cmd() and prepare()/copy() cannot run + * concurrently which is the case when there is no preemption. + */ + if (comp_is_new_data_blob_available(cd->tuning_handler)) { + comp_get_data_blob(cd->tuning_handler, NULL, NULL); + cd->reconfigure = true; + } + return 0; + default: + comp_err(mod->dev, + "Only binary controls supported %d", + cdata->cmd); + return -EINVAL; + } +} + +static int google_rtc_audio_processing_cmd_get_data(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata, + size_t max_data_size) +{ + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "%u", cdata->cmd); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return comp_data_blob_get_cmd(cd->tuning_handler, cdata, max_data_size); + default: + comp_err(mod->dev, + "Only binary controls supported %d", + cdata->cmd); + return -EINVAL; + } +} +#endif + +static int google_rtc_audio_processing_set_config(struct processing_module *mod, uint32_t param_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) +{ +#if CONFIG_IPC_MAJOR_4 + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + int ret; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(mod->dev, "Only binary controls supported"); + return -EINVAL; + } + + ret = comp_data_blob_set(cd->tuning_handler, pos, data_offset_size, + fragment, fragment_size); + if (ret) + return ret; + + /* Accept the new blob immediately so that userspace can write + * the control in quick succession without error. + * This ensures the last successful control write from userspace + * before prepare/copy is applied. + * The config blob is not referenced after reconfigure() returns + * so it is safe to call comp_get_data_blob here which frees the + * old blob. This assumes cmd() and prepare()/copy() cannot run + * concurrently which is the case when there is no preemption. + * + * Note from review: A race condition is possible and should be + * further investigated and fixed. + */ + if (comp_is_new_data_blob_available(cd->tuning_handler)) { + comp_get_data_blob(cd->tuning_handler, NULL, NULL); + cd->reconfigure = true; + } + + return 0; +#elif CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + return google_rtc_audio_processing_cmd_set_data(mod, cdata); +#endif +} + +static int google_rtc_audio_processing_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ +#if CONFIG_IPC_MAJOR_4 + comp_err(mod->dev, "Not supported"); + return -EINVAL; +#elif CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + return google_rtc_audio_processing_cmd_get_data(mod, cdata, fragment_size); +#endif +} + +static int google_rtc_audio_processing_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct google_rtc_audio_processing_comp_data *cd; + int ret, i; + + comp_info(dev, "entry"); + + /* Create private component data */ + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) { + ret = -ENOMEM; + goto fail; + } + + md->private = cd; + + cd->tuning_handler = mod_data_blob_handler_new(mod); + if (!cd->tuning_handler) { + ret = -ENOMEM; + goto fail; + } + + cd->num_aec_reference_channels = CONFIG_COMP_GOOGLE_RTC_AUDIO_REFERENCE_CHANNEL_MAX; + cd->num_capture_channels = CONFIG_COMP_GOOGLE_RTC_AUDIO_REFERENCE_CHANNEL_MAX; + cd->num_frames = NUM_FRAMES; + + /* Giant blob of scratch memory. */ + GoogleRtcAudioProcessingAttachMemoryBuffer(cached_ptr(&aec_mem_blob[0]), + sizeof(aec_mem_blob)); + + cd->state = GoogleRtcAudioProcessingCreateWithConfig(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ, + cd->num_capture_channels, + cd->num_capture_channels, + CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ, + cd->num_aec_reference_channels, + /*config=*/NULL, /*config_size=*/0); + + if (!cd->state) { + comp_err(dev, "Failed to initialized GoogleRtcAudioProcessing"); + ret = -EINVAL; + goto fail; + } + + float capture_headroom_linear = CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_MIC_HEADROOM_LINEAR; + float echo_path_delay_ms = CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_ECHO_PATH_DELAY_MS; + ret = GoogleRtcAudioProcessingParameters(cd->state, + &capture_headroom_linear, + &echo_path_delay_ms); + + if (ret < 0) { + comp_err(dev, "Failed to apply GoogleRtcAudioProcessingParameters"); + goto fail; + } + + for (i = 0; i < CHAN_MAX; i++) { + cd->raw_mic_buffers[i] = cached_ptr(&micbuf[i][0]); + cd->refout_buffers[i] = cached_ptr(&refoutbuf[i][0]); + } + + cd->buffered_frames = 0; + + /* comp_is_new_data_blob_available always returns false for the first + * control write with non-empty config. The first non-empty write may + * happen after prepare (e.g. during copy). Default to true so that + * copy keeps checking until a non-empty config is applied. + */ + cd->reconfigure = true; + + /* Mic and reference, needed for audio stream type copy module client */ + mod->max_sources = 2; + + comp_dbg(dev, "Ready"); + return 0; + +fail: + comp_err(dev, "Failed"); + if (cd) { + if (cd->state) { + GoogleRtcAudioProcessingFree(cd->state); + } + GoogleRtcAudioProcessingDetachMemoryBuffer(); + mod_data_blob_handler_free(mod, cd->tuning_handler); + mod_free(mod, cd); + } + + return ret; +} + +static int google_rtc_audio_processing_free(struct processing_module *mod) +{ + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + GoogleRtcAudioProcessingFree(cd->state); + cd->state = NULL; + GoogleRtcAudioProcessingDetachMemoryBuffer(); + mod_data_blob_handler_free(mod, cd->tuning_handler); + mod_free(mod, cd); + return 0; +} + +static int google_rtc_audio_processing_prepare(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + int ret = 0; + + comp_info(dev, "entry"); + + if (num_of_sources != 2 || num_of_sinks != 1) { + comp_err(dev, "Invalid source/sink count"); + return -EINVAL; + } + + /* The mic is the source that is on the same pipeline as the sink */ + cd->aec_reference_source = + source_get_pipeline_id(sources[0]) == sink_get_pipeline_id(sinks[0]); + cd->raw_microphone_source = cd->aec_reference_source ? 0 : 1; + +#ifdef CONFIG_IPC_MAJOR_3 + /* Don't need the ref buffer on IPC4 as pipelines are always + * activated in tandem; also the API is deprecated + */ + cd->ref_comp_buffer = comp_dev_get_first_data_producer(dev); + if (cd->aec_reference_source == 1) + cd->ref_comp_buffer = comp_dev_get_next_data_producer(dev, cd->ref_comp_buffer); +#endif + +#ifdef CONFIG_IPC_MAJOR_4 + /* Workaround: nothing in the framework sets up the stream for + * the reference source correctly from topology input, so we + * have to do it here. Input pin "1" is just a magic number + * that must match the input_pin_index token in a format + * record from our topology. + */ + ipc4_update_source_format(sources[cd->aec_reference_source], + &mod->priv.cfg.input_pins[1].audio_fmt); +#endif + + /* Validate channel, format and rate on each of our three inputs */ + int ref_fmt = source_get_frm_fmt(sources[cd->aec_reference_source]); + int ref_chan = source_get_channels(sources[cd->aec_reference_source]); + int ref_rate = source_get_rate(sources[cd->aec_reference_source]); + + int mic_fmt = source_get_frm_fmt(sources[cd->raw_microphone_source]); + int mic_chan = source_get_channels(sources[cd->raw_microphone_source]); + int mic_rate = source_get_rate(sources[cd->raw_microphone_source]); + + int out_fmt = sink_get_frm_fmt(sinks[0]); + int out_chan = sink_get_channels(sinks[0]); + int out_rate = sink_get_rate(sinks[0]); + + cd->ref_framesz = source_get_frame_bytes(sources[cd->aec_reference_source]); + cd->cap_framesz = sink_get_frame_bytes(sinks[0]); + + cd->num_aec_reference_channels = MIN(ref_chan, CHAN_MAX); + cd->num_capture_channels = MIN(mic_chan, CHAN_MAX); + + /* Too many channels is a soft failure, AEC treats only the first N */ + if (mic_chan > CHAN_MAX) + comp_warn(dev, "Too many mic channels: %d, truncating to %d", + mic_chan, CHAN_MAX); + if (ref_chan > CHAN_MAX) + comp_warn(dev, "Too many ref channels: %d, truncating to %d", + ref_chan, CHAN_MAX); + + if (out_chan != mic_chan) { + comp_err(dev, "Input/output mic channel mismatch"); + ret = -EINVAL; + } + + if (ref_rate != mic_rate || ref_rate != out_rate || + ref_rate != CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ) { + comp_err(dev, "Incorrect source/sink sample rate, expect %d\n", + CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ); + ret = -EINVAL; + } + + if (mic_fmt != out_fmt) { + comp_err(dev, "Mismatched in/out frame format"); + ret = -EINVAL; + } + + if ((mic_fmt != SOF_IPC_FRAME_S32_LE && mic_fmt != SOF_IPC_FRAME_S16_LE) || + (ref_fmt != SOF_IPC_FRAME_S32_LE && ref_fmt != SOF_IPC_FRAME_S16_LE)) { + comp_err(dev, "Unsupported sample format"); + ret = -EINVAL; + } + +#ifdef CONFIG_IPC_MAJOR_4 + int ref_bufsz = source_get_min_available(sources[cd->aec_reference_source]); + int mic_bufsz = source_get_min_available(sources[cd->raw_microphone_source]); + int out_bufsz = sink_get_min_free_space(sinks[0]); + + if (mic_bufsz > cd->num_frames * cd->cap_framesz) { + comp_err(dev, "Mic IBS %d >1 AEC block, needless delay!", mic_bufsz); + ret = -EINVAL; + } + + if (ref_bufsz > cd->num_frames * cd->ref_framesz) { + comp_err(dev, "Ref IBS %d >1 one AEC block, needless delay!", ref_bufsz); + ret = -EINVAL; + } + + if (out_bufsz < cd->num_frames * cd->cap_framesz) { + comp_err(dev, "Capture OBS %d too small, must fit 1 AEC block", out_bufsz); + ret = -EINVAL; + } +#endif + + if (ret < 0) + return ret; + + cd->mic_copy = mic_fmt == SOF_IPC_FRAME_S16_LE ? source_copy16 : source_copy32; + cd->ref_copy = ref_fmt == SOF_IPC_FRAME_S16_LE ? source_copy16 : source_copy32; + cd->out_copy = out_fmt == SOF_IPC_FRAME_S16_LE ? sink_copy16 : sink_copy32; + + cd->last_ref_ok = false; + + ret = GoogleRtcAudioProcessingSetStreamFormats(cd->state, mic_rate, + cd->num_capture_channels, + cd->num_capture_channels, + ref_rate, cd->num_aec_reference_channels); + + /* Blobs sent during COMP_STATE_READY is assigned to blob_handler->data + * directly, so comp_is_new_data_blob_available always returns false. + */ + if (ret == 0) + ret = google_rtc_audio_processing_reconfigure(mod); + + return ret; +} + +static int trigger_handler(struct processing_module *mod, int cmd) +{ +#ifdef CONFIG_IPC_MAJOR_3 + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + + /* Ignore and halt propagation if we get a trigger from the + * playback pipeline: not for us. (Never happens on IPC4) + */ + if (cd->ref_comp_buffer->audio_buffer.walking) + return PPL_STATUS_PATH_STOP; +#endif + + /* Note: not module_adapter_set_state(). With IPC4 those are + * identical, but IPC3 has some odd-looking logic that + * validates that no sources are active when receiving a + * PRE_START command, which obviously breaks for our reference + * stream if playback was already running when our pipeline + * started + */ + return comp_set_state(mod->dev, cmd); +} + +static int google_rtc_audio_processing_reset(struct processing_module *mod) +{ + comp_dbg(mod->dev, "entry"); + return 0; +} + +static inline void execute_aec(struct google_rtc_audio_processing_comp_data *cd) +{ + /* Note that reference input and mic output share the same + * buffer for efficiency + */ + GoogleRtcAudioProcessingAnalyzeRender_float32(cd->state, + (const float **)cd->refout_buffers); + GoogleRtcAudioProcessingProcessCapture_float32(cd->state, + (const float **)cd->raw_mic_buffers, + cd->refout_buffers); + cd->buffered_frames = 0; +} + +static bool ref_stream_active(struct google_rtc_audio_processing_comp_data *cd) +{ +#ifdef CONFIG_IPC_MAJOR_3 + return (comp_buffer_get_source_state(cd->ref_comp_buffer) == COMP_STATE_ACTIVE); +#else + return true; +#endif +} + +static int mod_process(struct processing_module *mod, struct sof_source **sources, + int num_of_sources, struct sof_sink **sinks, int num_of_sinks) +{ + struct google_rtc_audio_processing_comp_data *cd = module_get_private_data(mod); + + if (cd->reconfigure) + google_rtc_audio_processing_reconfigure(mod); + + struct sof_source *mic = sources[cd->raw_microphone_source]; + struct sof_source *ref = sources[cd->aec_reference_source]; + struct sof_sink *out = sinks[0]; + bool ref_ok = ref_stream_active(cd); + + /* Clear the buffer if the reference pipeline shuts off */ + if (!ref_ok && cd->last_ref_ok) + bzero(cached_ptr(refoutbuf), sizeof(refoutbuf)); + + int fmic = source_get_data_frames_available(mic); + int fref = source_get_data_frames_available(ref); + int frames = ref_ok ? MIN(fmic, fref) : fmic; + int n, frames_rem; + + for (frames_rem = frames; frames_rem; frames_rem -= n) { + n = MIN(frames_rem, cd->num_frames - cd->buffered_frames); + + cd->mic_copy(mic, n, cd->raw_mic_buffers, cd->buffered_frames); + + if (ref_ok) + cd->ref_copy(ref, n, cd->refout_buffers, cd->buffered_frames); + + cd->buffered_frames += n; + + if (cd->buffered_frames >= cd->num_frames) { + if (sink_get_free_size(out) < cd->num_frames * cd->cap_framesz) { + comp_warn(mod->dev, "AEC sink backed up!"); + break; + } + + execute_aec(cd); + cd->out_copy(out, cd->num_frames, cd->refout_buffers); + } + } + cd->last_ref_ok = ref_ok; + return 0; +} + +static const struct module_interface google_rtc_audio_processing_interface = { + .init = google_rtc_audio_processing_init, + .free = google_rtc_audio_processing_free, + .process = mod_process, + .prepare = google_rtc_audio_processing_prepare, + .set_configuration = google_rtc_audio_processing_set_config, + .get_configuration = google_rtc_audio_processing_get_config, + .trigger = trigger_handler, + .reset = google_rtc_audio_processing_reset, +}; + +#if CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("RTC_AEC", &google_rtc_audio_processing_interface, + 7, SOF_REG_UUID(google_rtc_audio_processing), 1); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(google_rtc_audio_processing_tr, SOF_UUID(google_rtc_audio_processing_uuid), + LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(google_rtc_audio_processing_interface, + google_rtc_audio_processing_uuid, google_rtc_audio_processing_tr); +SOF_MODULE_INIT(google_rtc_audio_processing, + sys_comp_module_google_rtc_audio_processing_interface_init); + +#endif diff --git a/src/audio/google/google_rtc_audio_processing.toml b/src/audio/google/google_rtc_audio_processing.toml new file mode 100644 index 000000000000..931452d0a7fc --- /dev/null +++ b/src/audio/google/google_rtc_audio_processing.toml @@ -0,0 +1,25 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "1" +#endif + + [[module.entry]] + name = "RTC_AEC" + uuid = UUIDREG_STR_GOOGLE_RTC_AUDIO_PROCESSING + REM # bit #i = 1 means core #i is allowed. + affinity_mask = "0x7" + instance_count = "1" + domain_types = "1" + load_type = LOAD_TYPE + module_type = "10" + init_config = "1" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0x8, 0x2, 0x2, 0x1, + 0, 0, 0x8, 0x2, 0x2, 0x4, + 1, 0, 0x8, 0x2, 0x2, 0x1] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/google/google_rtc_audio_processing_mock.c b/src/audio/google/google_rtc_audio_processing_mock.c new file mode 100644 index 000000000000..b931c3a85c7a --- /dev/null +++ b/src/audio/google/google_rtc_audio_processing_mock.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Google LLC. +// +// Author: Lionel Koenig <lionelk@google.com> +#include <google_rtc_audio_processing.h> +#include <google_rtc_audio_processing_sof_message_reader.h> + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include <sof/audio/format.h> +#include <sof/math/numbers.h> + +#include <rtos/alloc.h> +#include <ipc/topology.h> + +#define GOOGLE_RTC_AUDIO_PROCESSING_FREQENCY_TO_PERIOD_FRAMES 100 +#define GOOGLE_RTC_AUDIO_PROCESSING_MS_PER_SECOND 1000 + +struct GoogleRtcAudioProcessingState { + int num_capture_channels; + int num_aec_reference_channels; + int num_output_channels; + int num_frames; + float *aec_reference; +}; + +static int SetFormats(GoogleRtcAudioProcessingState *const state, + int capture_sample_rate_hz, + int num_capture_input_channels, + int num_capture_output_channels, + int render_sample_rate_hz, + int num_render_channels) +{ + state->num_capture_channels = num_capture_input_channels; + state->num_output_channels = num_capture_output_channels; + state->num_frames = capture_sample_rate_hz / + GOOGLE_RTC_AUDIO_PROCESSING_FREQENCY_TO_PERIOD_FRAMES; + + state->num_aec_reference_channels = num_render_channels; + rfree(state->aec_reference); + state->aec_reference = rballoc(SOF_MEM_FLAG_USER, + sizeof(state->aec_reference[0]) * + state->num_frames * + state->num_aec_reference_channels); + if (!state->aec_reference) + return -ENOMEM; + return 0; +} + +void GoogleRtcAudioProcessingAttachMemoryBuffer(uint8_t *const buffer, + int buffer_size) +{ +} + +void GoogleRtcAudioProcessingDetachMemoryBuffer(void) +{ +} + +GoogleRtcAudioProcessingState *GoogleRtcAudioProcessingCreateWithConfig(int capture_sample_rate_hz, + int num_capture_input_channels, + int num_capture_output_channels, + int render_sample_rate_hz, + int num_render_channels, + const uint8_t *const config, + int config_size) +{ + int err; + struct GoogleRtcAudioProcessingState *s = + rballoc(SOF_MEM_FLAG_USER, sizeof(GoogleRtcAudioProcessingState)); + if (!s) + return NULL; + + s->aec_reference = NULL; + err = SetFormats(s, + capture_sample_rate_hz, + num_capture_input_channels, + num_capture_output_channels, + render_sample_rate_hz, + num_render_channels); + + if (err) { + rfree(s); + return NULL; + } + return s; +} + +GoogleRtcAudioProcessingState *GoogleRtcAudioProcessingCreate(void) +{ + return GoogleRtcAudioProcessingCreateWithConfig(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ, + 1, + 1, + CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ, + 2, + NULL, + 0); +} + +void GoogleRtcAudioProcessingFree(GoogleRtcAudioProcessingState *state) +{ + if (state != NULL) { + rfree(state->aec_reference); + rfree(state); + } +} + +int GoogleRtcAudioProcessingSetStreamFormats(GoogleRtcAudioProcessingState *const state, + int capture_sample_rate_hz, + int num_capture_input_channels, + int num_capture_output_channels, + int render_sample_rate_hz, + int num_render_channels) +{ + SetFormats(state, + capture_sample_rate_hz, + num_capture_input_channels, + num_capture_output_channels, + render_sample_rate_hz, + num_render_channels); + return 0; +} + +int GoogleRtcAudioProcessingParameters(GoogleRtcAudioProcessingState *const state, + float *capture_headroom_linear, + float *echo_path_delay_ms) +{ + return 0; +} + +int GoogleRtcAudioProcessingGetFramesizeInMs(GoogleRtcAudioProcessingState *state) +{ + return state->num_frames * + GOOGLE_RTC_AUDIO_PROCESSING_MS_PER_SECOND / + CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING_SAMPLE_RATE_HZ; +} + +int GoogleRtcAudioProcessingReconfigure(GoogleRtcAudioProcessingState *const state, + const uint8_t *const config, + int config_size) +{ + return 0; +} + +int GoogleRtcAudioProcessingProcessCapture_float32(GoogleRtcAudioProcessingState *const state, + const float *const *src, + float * const *dest) +{ + float *ref = state->aec_reference; + float **mic = (float **)src; + int n, chan; + + for (chan = 0; chan < state->num_output_channels; chan++) { + for (n = 0; n < state->num_frames; ++n) { + float mic_save = mic[chan][n]; /* allow same in/out buffer */ + + if (chan < state->num_aec_reference_channels) + dest[chan][n] = mic_save + ref[n + (chan * state->num_frames)]; + else + dest[chan][n] = mic_save; + } + } + return 0; +} + +int GoogleRtcAudioProcessingAnalyzeRender_float32(GoogleRtcAudioProcessingState *const state, + const float *const *data) +{ + const size_t buffer_size = + sizeof(state->aec_reference[0]) + * state->num_frames; + int channel; + + for (channel = 0; channel < state->num_aec_reference_channels; channel++) { + memcpy_s(&state->aec_reference[channel * state->num_frames], buffer_size, + data[channel], buffer_size); + } + + return 0; +} + +void GoogleRtcAudioProcessingParseSofConfigMessage(uint8_t *message, + size_t message_size, + uint8_t **google_rtc_audio_processing_config, + size_t *google_rtc_audio_processing_config_size, + int *num_capture_input_channels, + int *num_capture_output_channels, + float *aec_reference_delay, + float *mic_gain, + bool *google_rtc_audio_processing_config_present, + bool *num_capture_input_channels_present, + bool *num_capture_output_channels_present, + bool *aec_reference_delay_present, + bool *mic_gain_present) +{ + *google_rtc_audio_processing_config = NULL; + *google_rtc_audio_processing_config_size = 0; + *num_capture_input_channels = 1; + *num_capture_output_channels = 1; + *aec_reference_delay = 0; + *mic_gain = 1; + *google_rtc_audio_processing_config_present = false; + *num_capture_input_channels_present = false; + *num_capture_output_channels_present = false; + *aec_reference_delay_present = false; + *mic_gain_present = false; +} diff --git a/src/audio/google/llext_ctc/CMakeLists.txt b/src/audio/google/llext_ctc/CMakeLists.txt new file mode 100644 index 000000000000..440e0fbe6ad2 --- /dev/null +++ b/src/audio/google/llext_ctc/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_GOOGLE_CTC_AUDIO_PROCESSING_MOCK) +sof_llext_build("google_ctc_audio_processing" + SOURCES ../google_ctc_audio_processing.c + ../google_ctc_audio_processing_ipc4.c + ../google_ctc_audio_processing_mock.c +) +target_include_directories(google_ctc_audio_processing_llext_lib PRIVATE + "${sof_top_dir}/third_party/include" +) +else() +message(FATAL_ERROR "Add library linking support in src/audio/google/llext_ctc/CMakeLists.txt") +endif() diff --git a/src/audio/google/llext_ctc/llext.toml.h b/src/audio/google/llext_ctc/llext.toml.h new file mode 100644 index 000000000000..242d5588e491 --- /dev/null +++ b/src/audio/google/llext_ctc/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../google_ctc_audio_processing.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/google/llext_rtc/CMakeLists.txt b/src/audio/google/llext_rtc/CMakeLists.txt new file mode 100644 index 000000000000..0847fbc8bc57 --- /dev/null +++ b/src/audio/google/llext_rtc/CMakeLists.txt @@ -0,0 +1,11 @@ +if(CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK) +sof_llext_build("google_rtc_audio_processing" + SOURCES ../google_rtc_audio_processing.c + ../google_rtc_audio_processing_mock.c +) +target_include_directories(google_rtc_audio_processing_llext_lib PRIVATE + "${sof_top_dir}/third_party/include" +) +else() +message(FATAL_ERROR "Add library linking support in src/audio/google/llext/CMakeLists.txt") +endif() diff --git a/src/audio/google/llext_rtc/llext.toml.h b/src/audio/google/llext_rtc/llext.toml.h new file mode 100644 index 000000000000..9a397eb44a0f --- /dev/null +++ b/src/audio/google/llext_rtc/llext.toml.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../google_rtc_audio_processing.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/host-legacy.c b/src/audio/host-legacy.c new file mode 100644 index 000000000000..3d62e271f518 --- /dev/null +++ b/src/audio/host-legacy.c @@ -0,0 +1,1070 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pcm_converter.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <sof/debug/telemetry/performance_monitor.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include "copier/host_copier.h" + +static const struct comp_driver comp_host; + +LOG_MODULE_REGISTER(host, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(host); + +static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) +{ + if (!hc->elem_array.elems || !hc->elem_array.count) + return NULL; + if (++hc->current == hc->elem_array.count) + hc->current = 0; + return hc->elem_array.elems + hc->current; +} + +static uint32_t host_dma_get_split(struct host_data *hd, uint32_t bytes) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + uint32_t split_src = 0; + uint32_t split_dst = 0; + + if (local_elem->src + bytes > hd->source->current_end) + split_src = bytes - + (hd->source->current_end - local_elem->src); + + if (local_elem->dest + bytes > hd->sink->current_end) + split_dst = bytes - + (hd->sink->current_end - local_elem->dest); + + /* get max split, so the current copy will be minimum */ + return MAX(split_src, split_dst); +} + +#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) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + int ret = 0; + + local_elem->size = bytes; + + /* reconfigure transfer */ + ret = dma_set_config_legacy(hd->chan, &hd->config); + if (ret < 0) { + comp_err(dev, "dma_set_config() failed, ret = %d", + ret); + return ret; + } + + ret = dma_copy_legacy(hd->chan, bytes, DMA_COPY_ONE_SHOT | DMA_COPY_BLOCKING); + if (ret < 0) { + comp_err(dev, "dma_copy() failed, ret = %d", + ret); + return ret; + } + + return ret; +} + +/** + * Calculates bytes to be copied in one shot mode. + * @param dev Host component device. + * @return Bytes to be copied. + */ +static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd, struct comp_dev *dev) +{ + uint32_t copy_bytes; + + /* calculate minimum size to copy */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + copy_bytes = audio_stream_get_free_bytes(&hd->local_buffer->stream); + else + copy_bytes = audio_stream_get_avail_bytes(&hd->local_buffer->stream); + + /* 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); +} + +/** + * Performs copy operation for host component working in one shot mode. + * It means DMA needs to be reconfigured after every transfer. + * @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, copy_callback_t cb) +{ + uint32_t copy_bytes = 0; + uint32_t split_value = 0; + int ret = 0; + + comp_dbg(dev, "entry"); + + copy_bytes = host_get_copy_bytes_one_shot(hd, dev); + if (!copy_bytes) { + comp_info(dev, "no bytes to copy"); + return ret; + } + + while (copy_bytes) { + /* get split value */ + split_value = host_dma_get_split(hd, copy_bytes); + copy_bytes -= split_value; + + ret = host_dma_set_config_and_copy(hd, dev, copy_bytes); + if (ret < 0) + return ret; + + /* update copy bytes */ + copy_bytes = split_value; + } + + return ret; +} + +#else /* CONFIG_FORCE_DMA_COPY_WHOLE_BLOCK */ + +/** + * Calculates bytes to be copied in one shot mode. + * @param dev Host component device. + * @return Bytes to be copied. + */ +static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd, struct comp_dev *dev) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + uint32_t copy_bytes; + uint32_t split_value; + + /* calculate minimum size to copy */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + copy_bytes = audio_stream_get_free_bytes(&hd->local_buffer->stream); + else + copy_bytes = audio_stream_get_avail_bytes(&hd->local_buffer->stream); + + /* copy_bytes should be aligned to minimum possible chunk of + * data to be copied by dma. + */ + copy_bytes = ALIGN_DOWN(copy_bytes, hd->dma_copy_align); + + split_value = host_dma_get_split(hd, copy_bytes); + if (!IS_ENABLED(CONFIG_DISABLE_DESCRIPTOR_SPLIT) && split_value) + copy_bytes -= split_value; + + local_elem->size = copy_bytes; + + return copy_bytes; +} + +/** + * Performs copy operation for host component working in one shot mode. + * It means DMA needs to be reconfigured after every transfer. + * @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, copy_callback_t cb) +{ + uint32_t copy_bytes = 0; + int ret = 0; + + comp_dbg(dev, "entry"); + + copy_bytes = host_get_copy_bytes_one_shot(hd, dev); + if (!copy_bytes) { + comp_info(dev, "no bytes to copy"); + return ret; + } + + /* reconfigure transfer */ + ret = dma_set_config_legacy(hd->chan, &hd->config); + if (ret < 0) { + comp_err(dev, "dma_set_config() failed, ret = %u", ret); + return ret; + } + + ret = dma_copy_legacy(hd->chan, copy_bytes, DMA_COPY_ONE_SHOT); + if (ret < 0) { + comp_err(dev, "dma_copy() failed, ret = %u", ret); + return ret; + } + + return ret; +} +#endif + +void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t bytes) +{ + struct comp_buffer *source; + struct comp_buffer *sink; + int ret; + bool update_mailbox = false; + bool send_ipc = false; + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + source = hd->dma_buffer; + sink = hd->local_buffer; + ret = dma_buffer_copy_from(source, sink, hd->process, bytes, DUMMY_CHMAP); + } else { + source = hd->local_buffer; + sink = hd->dma_buffer; + ret = dma_buffer_copy_to(source, sink, hd->process, bytes, DUMMY_CHMAP); + } + + /* assert dma_buffer_copy succeed */ + if (ret < 0) + comp_err(dev, "dma buffer copy failed, dir %d bytes %d avail %d free %d", + dev->direction, bytes, + audio_stream_get_avail_samples(&source->stream) * + audio_stream_frame_bytes(&source->stream), + audio_stream_get_free_samples(&sink->stream) * + audio_stream_frame_bytes(&sink->stream)); + + if (ret < 0) + return; + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + io_perf_monitor_update_data(hd->io_perf_host_byte_count, bytes); +#endif + + hd->total_data_processed += bytes; + + /* new local period, update host buffer position blks + * local_pos is queried by the ops.position() API + */ + hd->local_pos += bytes; + + /* buffer overlap, hardcode host buffer size at the moment */ + if (hd->local_pos >= hd->host_size) +#if CONFIG_WRAP_ACTUAL_POSITION + hd->local_pos %= hd->host_size; +#else + hd->local_pos = 0; +#endif + if (hd->cont_update_posn) + update_mailbox = true; + + /* Don't send stream position if no_stream_position == 1 */ + if (!hd->no_stream_position) { + hd->report_pos += bytes; + + /* host_period_bytes is set to zero to disable position update + * by IPC for FW version before 3.11, so send IPC message to + * driver according to this condition and report_pos. + */ + if (hd->host_period_bytes != 0 && + hd->report_pos >= hd->host_period_bytes) { + hd->report_pos = 0; + + /* send timestamped position to host + * (updates position first, by calling ops.position()) + */ + update_mailbox = true; + send_ipc = true; + } + } + + if (update_mailbox) { + pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); + mailbox_stream_write(dev->pipeline->posn_offset, + &hd->posn, sizeof(hd->posn)); + if (send_ipc) + ipc_msg_send(hd->msg, &hd->posn, false); + } +} + +/* The host memory is not guaranteed to be continuous and also not guaranteed + * to have a period/buffer size that is a multiple of the DSP period size. + * 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. + */ +void host_common_one_shot(struct host_data *hd, uint32_t bytes) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + struct dma_sg_elem *source_elem; + struct dma_sg_elem *sink_elem; + + /* update src and dest positions and check for overflow */ + local_elem->src += bytes; + local_elem->dest += bytes; + + if (local_elem->src == hd->source->current_end) { + /* end of element, so use next */ + source_elem = next_buffer(hd->source); + if (source_elem) { + hd->source->current_end = source_elem->src + + source_elem->size; + local_elem->src = source_elem->src; + } + } + + if (local_elem->dest == hd->sink->current_end) { + /* end of element, so use next */ + sink_elem = next_buffer(hd->sink); + if (sink_elem) { + hd->sink->current_end = sink_elem->dest + + sink_elem->size; + local_elem->dest = sink_elem->dest; + } + } +} + +/* This is called by DMA driver every time when DMA completes its current + * transfer between host and DSP. + */ +static void host_dma_cb(void *arg, enum notify_id type, void *data) +{ + 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_dbg(dev, "%p", &comp_host); + + /* update position */ + host_common_update(hd, dev, bytes); + + /* callback for one shot copy */ + if (hd->copy_type == COMP_COPY_ONE_SHOT) + host_common_one_shot(hd, bytes); +} + +/** + * Calculates bytes to be copied in normal mode. + * @param dev Host component device. + * @return Bytes to be copied. + */ +static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev *dev) +{ + uint32_t avail_bytes = 0; + uint32_t free_bytes = 0; + uint32_t copy_bytes = 0; + int ret; + + /* get data sizes from DMA */ + ret = dma_get_data_size_legacy(hd->chan, &avail_bytes, &free_bytes); + if (ret < 0) { + comp_err(dev, "dma_get_data_size() failed, ret = %u", + ret); + /* return 0 copy_bytes in case of error to skip DMA copy */ + return 0; + } + + /* calculate minimum size to copy */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + /* limit bytes per copy to one period for the whole pipeline + * in order to avoid high load spike + */ + free_bytes = audio_stream_get_free_bytes(&hd->local_buffer->stream); + copy_bytes = MIN(hd->period_bytes, MIN(avail_bytes, free_bytes)); + if (!copy_bytes) + comp_info(dev, "no bytes to copy, %d free in buffer, %d available in DMA", + free_bytes, avail_bytes); + } else { + avail_bytes = audio_stream_get_avail_bytes(&hd->local_buffer->stream); + copy_bytes = MIN(avail_bytes, free_bytes); + if (!copy_bytes) + comp_info(dev, "no bytes to copy, %d avail in buffer, %d free in DMA", + avail_bytes, free_bytes); + } + + /* 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); +} + +/** + * Performs copy operation for host component working in normal mode. + * It means DMA works continuously and doesn't need reconfiguration. + * @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, copy_callback_t cb) +{ + uint32_t copy_bytes = 0; + uint32_t flags = 0; + int ret; + + comp_dbg(dev, "entry"); + + if (hd->copy_type == COMP_COPY_BLOCKING) + flags |= DMA_COPY_BLOCKING; + + copy_bytes = host_get_copy_bytes_normal(hd, dev); + if (!copy_bytes) + return 0; + + ret = dma_copy_legacy(hd->chan, copy_bytes, flags); + if (ret < 0) + comp_err(dev, "dma_copy() failed, ret = %u", ret); + + return ret; +} + +static int create_local_elems(struct host_data *hd, struct comp_dev *dev, uint32_t buffer_count, + uint32_t buffer_bytes) +{ + struct dma_sg_elem_array *elem_array; + uint32_t dir; + int err; + + dir = dev->direction == SOF_IPC_STREAM_PLAYBACK ? + DMA_DIR_HMEM_TO_LMEM : DMA_DIR_LMEM_TO_HMEM; + + /* if host buffer set we need to allocate local buffer */ + if (hd->host.elem_array.count) { + elem_array = &hd->local.elem_array; + + /* config buffer will be used as proxy */ + err = dma_sg_alloc(NULL, &hd->config.elem_array, SOF_MEM_FLAG_USER, + dir, 1, 0, 0, 0); + if (err < 0) { + comp_err(dev, "dma_sg_alloc() failed"); + return err; + } + } else { + elem_array = &hd->config.elem_array; + } + + err = dma_sg_alloc(NULL, elem_array, SOF_MEM_FLAG_USER, dir, buffer_count, + buffer_bytes, + (uintptr_t)(audio_stream_get_addr(&hd->dma_buffer->stream)), 0); + if (err < 0) { + comp_err(dev, "dma_sg_alloc() failed"); + return err; + } + + 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_common_trigger(struct host_data *hd, struct comp_dev *dev, int cmd) +{ + 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 0; + + if (!hd->chan) { + comp_err(dev, "no dma channel configured"); + return -EINVAL; + } + + switch (cmd) { + case COMP_TRIGGER_START: + ret = dma_start_legacy(hd->chan); + if (ret < 0) + comp_err(dev, "dma_start() failed, ret = %u", + ret); + break; + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_XRUN: + ret = dma_stop_legacy(hd->chan); + if (ret < 0) + comp_err(dev, "dma stop failed: %d", + ret); + break; + default: + ret = 0; + break; + } + + return ret; +} + +static int host_trigger(struct comp_dev *dev, int cmd) +{ + struct host_data *hd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "entry"); + + ret = comp_set_state(dev, cmd); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return host_common_trigger(hd, dev, cmd); +} + +int host_common_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; + + hd->dma = dma_get(dir, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); + if (!hd->dma) { + comp_err(dev, "dma_get() returned NULL"); + return -ENODEV; + } + + /* init buffer elems */ + dma_sg_init(&hd->config.elem_array); + dma_sg_init(&hd->host.elem_array); + dma_sg_init(&hd->local.elem_array); + + 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, "ipc_msg_init failed"); + dma_put(hd->dma); + return -ENOMEM; + } + hd->chan = NULL; + hd->copy_type = COMP_COPY_NORMAL; + + return 0; +} + +static struct comp_dev *host_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + 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()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + hd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*hd)); + if (!hd) + goto e_data; + + comp_set_drvdata(dev, hd); + + ret = host_common_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: + comp_free_device(dev); + return NULL; +} + +void host_common_free(struct host_data *hd) +{ +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Check for NULL just in case the params() step is omitted */ + if (hd->io_perf_host_byte_count) { + io_perf_monitor_release_slot(hd->io_perf_host_byte_count); + hd->io_perf_host_byte_count = NULL; + } +#endif + + dma_put(hd->dma); + + ipc_msg_free(hd->msg); + dma_sg_free(NULL, &hd->config.elem_array); +} + +static void host_free(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + host_common_free(hd); + rfree(hd); + comp_free_device(dev); +} + +static int host_elements_reset(struct host_data *hd, struct comp_dev *dev) +{ + 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 */ + source_elem = hd->source->elem_array.elems; + if (source_elem) { + hd->source->current = 0; + hd->source->current_end = source_elem->src + source_elem->size; + } + + /* setup elem to point to first sink elem */ + sink_elem = hd->sink->elem_array.elems; + if (sink_elem) { + hd->sink->current = 0; + hd->sink->current_end = sink_elem->dest + sink_elem->size; + } + + /* local element */ + if (source_elem && sink_elem) { + local_elem = hd->config.elem_array.elems; + local_elem->dest = sink_elem->dest; + local_elem->size = + dev->direction == SOF_IPC_STREAM_PLAYBACK ? + sink_elem->size : source_elem->size; + local_elem->src = source_elem->src; + } + + return 0; +} + +static int host_verify_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + int ret; + + comp_dbg(dev, "entry"); + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params() failed"); + return ret; + } + + return 0; +} + +/* configure the DMA params and descriptors for host buffer IO */ +int host_common_params(struct host_data *hd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, notifier_callback_t cb) +{ + struct dma_sg_config *config = &hd->config; + uint32_t period_count; + uint32_t period_bytes; + uint32_t buffer_size; + uint32_t addr_align; + uint32_t align; + int err; + + /* host params always installed by pipeline IPC */ + hd->host_size = params->buffer.size; + hd->stream_tag = params->stream_tag; + hd->no_stream_position = params->no_stream_position; + hd->host_period_bytes = params->host_period_bytes; + hd->cont_update_posn = params->cont_update_posn; + + /* retrieve DMA buffer address alignment */ + err = dma_get_attribute_legacy(hd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (err < 0) { + comp_err(dev, "could not get dma buffer address alignment, err = %d", + err); + return err; + } + + /* retrieve DMA buffer size alignment */ + err = dma_get_attribute_legacy(hd->dma, DMA_ATTR_BUFFER_ALIGNMENT, &align); + if (err < 0 || !align) { + comp_err(dev, "could not get valid dma buffer alignment, err = %d, align = %u", + err, align); + return -EINVAL; + } + + /* retrieve DMA buffer period count */ + err = dma_get_attribute_legacy(hd->dma, DMA_ATTR_BUFFER_PERIOD_COUNT, + &period_count); + if (err < 0 || !period_count) { + comp_err(dev, "could not get valid dma buffer period count, err = %d, period_count = %u", + err, period_count); + return -EINVAL; + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + hd->local_buffer = comp_dev_get_first_data_consumer(dev); + else + hd->local_buffer = comp_dev_get_first_data_producer(dev); + + if (!hd->local_buffer) { + comp_err(dev, "no local buffer found"); + return -EINVAL; + } + + period_bytes = dev->frames * + audio_stream_frame_bytes(&hd->local_buffer->stream); + + if (!period_bytes) { + comp_err(dev, "invalid period_bytes"); + err = -EINVAL; + goto out; + } + + /* determine source and sink buffer elements */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + config->direction = DMA_DIR_HMEM_TO_LMEM; + hd->source = &hd->host; + hd->sink = &hd->local; + } else { + config->direction = DMA_DIR_LMEM_TO_HMEM; + hd->source = &hd->local; + hd->sink = &hd->host; + } + + /* TODO: should be taken from DMA */ + if (hd->host.elem_array.count) { + period_bytes *= period_count; + period_count = 1; + } + + /* calculate DMA buffer size */ + buffer_size = ALIGN_UP(period_bytes, align) * period_count; + buffer_size = MAX(buffer_size, ALIGN_UP(hd->ipc_host.dma_buffer_size, align)); + + /* alloc DMA buffer or change its size if exists */ + /* + * Host DMA buffer cannot be shared. So we actually don't need to lock, + * but we have to write back caches after we finish anyway + */ + if (hd->dma_buffer) { + err = buffer_set_size(hd->dma_buffer, buffer_size, addr_align); + if (err < 0) { + comp_err(dev, "buffer_set_size() failed, buffer_size = %u", + buffer_size); + goto out; + } + } else { + hd->dma_buffer = buffer_alloc(NULL, buffer_size, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + addr_align, BUFFER_USAGE_NOT_SHARED); + if (!hd->dma_buffer) { + comp_err(dev, "failed to alloc dma buffer"); + err = -ENOMEM; + goto out; + } + + buffer_set_params(hd->dma_buffer, params, BUFFER_UPDATE_FORCE); + } + + /* create SG DMA elems for local DMA buffer */ + err = create_local_elems(hd, dev, period_count, buffer_size / period_count); + if (err < 0) + goto out; + + /* set up DMA configuration - copy in sample bytes. */ + config->src_width = audio_stream_sample_bytes(&hd->local_buffer->stream); + config->dest_width = audio_stream_sample_bytes(&hd->local_buffer->stream); + config->cyclic = 0; + config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); + config->is_scheduling_source = comp_is_scheduling_source(dev); + config->period = dev->pipeline->period; + + host_elements_reset(hd, dev); + + hd->stream_tag -= 1; + /* get DMA channel from DMAC + * note: stream_tag is ignored by dw-dma + */ + hd->chan = dma_channel_get_legacy(hd->dma, hd->stream_tag); + if (!hd->chan) { + comp_err(dev, "hd->chan is NULL"); + err = -ENODEV; + goto out; + } + + err = dma_set_config_legacy(hd->chan, &hd->config); + if (err < 0) { + comp_err(dev, "dma_set_config() failed"); + dma_channel_put_legacy(hd->chan); + hd->chan = NULL; + goto out; + } + + err = dma_get_attribute_legacy(hd->dma, DMA_ATTR_COPY_ALIGNMENT, + &hd->dma_copy_align); + + if (err < 0) { + comp_err(dev, "dma_get_attribute()"); + + goto out; + } + + /* minimal copied data shouldn't be less than alignment */ + hd->period_bytes = ALIGN_UP(period_bytes, hd->dma_copy_align); + + /* 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(audio_stream_get_frm_fmt(&hd->local_buffer->stream), + audio_stream_get_frm_fmt(&hd->local_buffer->stream)); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + if (!hd->io_perf_host_byte_count) { + /* On the Host side, unlike the DAI side, the port direction values (INPUT/OUTPUT) + * match the stream direction enum values (CAPTURE/PLAYBACK), so we can directly + * use params->direction here. + */ + struct io_perf_data_item init_data = { + IO_PERF_HDA_ID, + hd->chan->index, + params->direction, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 + }; + + io_perf_monitor_init_data(&hd->io_perf_host_byte_count, &init_data); + } +#endif + +out: + + 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_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct host_data *hd = comp_get_drvdata(dev); + int err; + + comp_dbg(dev, "entry"); + + err = host_verify_params(dev, params); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return err; + } + + return host_common_params(hd, dev, params, NULL); +} + +int host_common_prepare(struct host_data *hd) +{ + buffer_zero(hd->dma_buffer); + return 0; +} + +static int host_prepare(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "entry"); + + 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_common_prepare(hd); +} + +static int host_position(struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) +{ + struct host_data *hd = comp_get_drvdata(dev); + + /* TODO: improve accuracy by adding current DMA position */ + posn->host_posn = hd->local_pos; + + return 0; +} + +void host_common_reset(struct host_data *hd, uint16_t state) +{ + if (hd->chan) { + dma_stop_delayed_legacy(hd->chan); + + /* remove callback */ + notifier_unregister(hd->cb_dev, hd->chan, NOTIFIER_ID_DMA_COPY); + + dma_channel_put_legacy(hd->chan); + hd->chan = NULL; + } + + /* free all DMA elements */ + dma_sg_free(NULL, &hd->host.elem_array); + dma_sg_free(NULL, &hd->local.elem_array); + dma_sg_free(NULL, &hd->config.elem_array); + + /* It's safe that cleaning out `hd->config` after `dma_sg_free` for config.elem_array */ + memset(&hd->config, 0, sizeof(hd->config)); + + /* free DMA buffer */ + if (hd->dma_buffer) { + buffer_free(hd->dma_buffer); + hd->dma_buffer = NULL; + } + + /* 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, "entry"); + + host_common_reset(hd, dev->state); + dev->state = COMP_STATE_READY; + + return 0; +} + +static int host_copy(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + + if (dev->state != COMP_STATE_ACTIVE) + return 0; + + return host_common_copy(hd, dev, NULL); +} + +static int host_get_attribute(struct comp_dev *dev, uint32_t type, + void *value) +{ + struct host_data *hd = comp_get_drvdata(dev); + + switch (type) { + case COMP_ATTR_COPY_TYPE: + *(enum comp_copy_type *)value = hd->copy_type; + break; + case COMP_ATTR_COPY_DIR: + *(uint32_t *)value = hd->ipc_host.direction; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int host_set_attribute(struct comp_dev *dev, uint32_t type, + void *value) +{ + struct host_data *hd = comp_get_drvdata(dev); + + switch (type) { + case COMP_ATTR_COPY_TYPE: + hd->copy_type = *(enum comp_copy_type *)value; + break; + case COMP_ATTR_HOST_BUFFER: + hd->host.elem_array = *(struct dma_sg_elem_array *)value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static uint64_t host_get_processed_data(struct comp_dev *dev, uint32_t stream_no, bool input) +{ + struct host_data *hd = comp_get_drvdata(dev); + uint64_t ret = 0; + bool source = dev->direction == SOF_IPC_STREAM_PLAYBACK; + + /* Return value only if direction and stream number match. + * The host supports only one stream. + */ + if (stream_no == 0 && source == input) + ret = hd->total_data_processed; + + return ret; +} + +DECLARE_TR_CTX(host_tr, SOF_UUID(host_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_host = { + .type = SOF_COMP_HOST, + .uid = SOF_RT_UUID(host_uuid), + .tctx = &host_tr, + .ops = { + .create = host_new, + .free = host_free, + .params = host_params, + .reset = host_reset, + .trigger = host_trigger, + .copy = host_copy, + .prepare = host_prepare, + .position = host_position, + .get_attribute = host_get_attribute, + .set_attribute = host_set_attribute, + .get_total_data_processed = host_get_processed_data, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_host_info = { + .drv = &comp_host, +}; + +UT_STATIC void sys_comp_host_init(void) +{ + comp_register(platform_shared_get(&comp_host_info, + sizeof(comp_host_info))); +} + +DECLARE_MODULE(sys_comp_host_init); +SOF_MODULE_INIT(host, sys_comp_host_init); diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c new file mode 100644 index 000000000000..59dd1f09b234 --- /dev/null +++ b/src/audio/host-zephyr.c @@ -0,0 +1,1316 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pcm_converter.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <sof/debug/telemetry/performance_monitor.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE +#include <ipc4/notification.h> +#endif + +#include "copier/copier.h" +#include "copier/host_copier.h" + +static const struct comp_driver comp_host; + +LOG_MODULE_REGISTER(host_comp, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(host); + +static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) +{ + if (!hc->elem_array.elems || !hc->elem_array.count) + return NULL; + if (++hc->current == hc->elem_array.count) + hc->current = 0; + return hc->elem_array.elems + hc->current; +} + +static uint32_t host_dma_get_split(struct host_data *hd, uint32_t bytes) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + uint32_t split_src = 0; + uint32_t split_dst = 0; + + if (local_elem->src + bytes > hd->source->current_end) + split_src = bytes - + (hd->source->current_end - local_elem->src); + + if (local_elem->dest + bytes > hd->sink->current_end) + split_dst = bytes - + (hd->sink->current_end - local_elem->dest); + + /* get max split, so the current copy will be minimum */ + return MAX(split_src, split_dst); +} + +#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, + copy_callback_t cb) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + int ret; + + local_elem->size = bytes; + + /* reconfigure transfer */ + ret = sof_dma_config(hd->dma, hd->chan_index, &hd->z_config); + if (ret < 0) { + comp_err(dev, "dma_config() failed, ret = %d", + ret); + return ret; + } + + cb(dev, bytes); + + ret = sof_dma_reload(hd->dma, hd->chan_index, bytes); + if (ret < 0) { + comp_err(dev, "dma_reload() failed, ret = %d", + ret); + return ret; + } + + return ret; +} + +/** + * Calculates bytes to be copied in one shot mode. + * @param dev Host component device. + * @return Bytes to be copied. + */ +static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd) +{ + struct comp_buffer *buffer = hd->local_buffer; + uint32_t copy_bytes; + + /* calculate minimum size to copy */ + if (hd->ipc_host.direction == SOF_IPC_STREAM_PLAYBACK) + copy_bytes = audio_stream_get_free_bytes(&buffer->stream); + else + copy_bytes = audio_stream_get_avail_bytes(&buffer->stream); + + /* 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); +} + +/** + * Performs copy operation for host component working in one shot mode. + * It means DMA needs to be reconfigured after every transfer. + * @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, copy_callback_t cb) +{ + uint32_t copy_bytes; + uint32_t split_value; + int ret = 0; + + comp_dbg(dev, "entry"); + + copy_bytes = host_get_copy_bytes_one_shot(hd); + if (!copy_bytes) { + comp_info(dev, "no bytes to copy"); + return ret; + } + + while (copy_bytes) { + /* get split value */ + split_value = host_dma_get_split(hd, copy_bytes); + copy_bytes -= split_value; + + ret = host_dma_set_config_and_copy(hd, dev, copy_bytes, cb); + if (ret < 0) + return ret; + + /* update copy bytes */ + copy_bytes = split_value; + } + + return ret; +} + +#else /* CONFIG_FORCE_DMA_COPY_WHOLE_BLOCK */ + +/** + * Calculates bytes to be copied in one shot mode. + * @param dev Host component device. + * @return Bytes to be copied. + */ +static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + struct comp_buffer *buffer = hd->local_buffer; + uint32_t copy_bytes; + uint32_t split_value; + + /* calculate minimum size to copy */ + if (hd->ipc_host.direction == SOF_IPC_STREAM_PLAYBACK) + copy_bytes = audio_stream_get_free_bytes(&buffer->stream); + else + copy_bytes = audio_stream_get_avail_bytes(&buffer->stream); + + /* copy_bytes should be aligned to minimum possible chunk of + * data to be copied by dma. + */ + copy_bytes = ALIGN_DOWN(copy_bytes, hd->dma_copy_align); + + split_value = host_dma_get_split(hd, copy_bytes); + if (split_value) + copy_bytes -= split_value; + + local_elem->size = copy_bytes; + + return copy_bytes; +} + +/** + * Performs copy operation for host component working in one shot mode. + * It means DMA needs to be reconfigured after every transfer. + * @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, copy_callback_t cb) +{ + uint32_t copy_bytes; + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + int ret = 0; + + comp_dbg(dev, "entry"); + + copy_bytes = host_get_copy_bytes_one_shot(hd); + if (!copy_bytes) { + comp_info(dev, "no bytes to copy"); + return ret; + } + + /* SRC/DEST addresses have changed so the DMAC needs + * to be re-configured. + */ + hd->z_config.head_block->source_address = local_elem->src; + hd->z_config.head_block->dest_address = local_elem->dest; + hd->z_config.head_block->block_size = local_elem->size; + + /* reconfigure transfer */ + ret = sof_dma_config(hd->dma, hd->chan_index, &hd->z_config); + if (ret < 0) { + comp_err(dev, "dma_config() failed, ret = %d", ret); + return ret; + } + + cb(dev, copy_bytes); + + ret = sof_dma_reload(hd->dma, hd->chan_index, copy_bytes); + if (ret < 0) + comp_err(dev, "dma_reload() failed, ret = %d", ret); + + return ret; +} +#endif + +void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t bytes) +{ + struct comp_buffer *source; + struct comp_buffer *sink; + int ret; + bool update_mailbox = false; + bool send_ipc = false; + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + source = hd->dma_buffer; + sink = hd->local_buffer; + ret = dma_buffer_copy_from(source, sink, hd->process, bytes, DUMMY_CHMAP); + } else { + source = hd->local_buffer; + sink = hd->dma_buffer; + ret = dma_buffer_copy_to(source, sink, hd->process, bytes, DUMMY_CHMAP); + } + + if (ret < 0) { + comp_err(dev, "copy failed, dir %d bytes %d return: %d", + dev->direction, bytes, ret); + return; + } + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + io_perf_monitor_update_data(hd->io_perf_host_byte_count, bytes); +#endif + + hd->total_data_processed += bytes; + + /* new local period, update host buffer position blks + * local_pos is queried by the ops.position() API + */ + hd->local_pos += bytes; + + /* buffer overlap, hardcode host buffer size at the moment */ + if (hd->local_pos >= hd->host_size) +#if CONFIG_WRAP_ACTUAL_POSITION + hd->local_pos %= hd->host_size; +#else + hd->local_pos = 0; +#endif + if (hd->cont_update_posn) + update_mailbox = true; + + /* Don't send stream position if no_stream_position == 1 */ + if (!hd->no_stream_position) { + hd->report_pos += bytes; + + /* host_period_bytes is set to zero to disable position update + * by IPC for FW version before 3.11, so send IPC message to + * driver according to this condition and report_pos. + */ + if (hd->host_period_bytes != 0 && + hd->report_pos >= hd->host_period_bytes) { + hd->report_pos = 0; + + /* send timestamped position to host + * (updates position first, by calling ops.position()) + */ + update_mailbox = true; + send_ipc = true; + } + } + + if (update_mailbox) { + pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); + mailbox_stream_write(dev->pipeline->posn_offset, + &hd->posn, sizeof(hd->posn)); + if (send_ipc) + ipc_msg_send(hd->msg, &hd->posn, false); + } +} + +/* The host memory is not guaranteed to be continuous and also not guaranteed + * to have a period/buffer size that is a multiple of the DSP period size. + * 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. + */ +void host_common_one_shot(struct host_data *hd, uint32_t bytes) +{ + struct dma_sg_elem *local_elem = hd->config.elem_array.elems; + struct dma_sg_elem *source_elem; + struct dma_sg_elem *sink_elem; + + /* update src and dest positions and check for overflow */ + local_elem->src += bytes; + local_elem->dest += bytes; + + if (local_elem->src == hd->source->current_end) { + /* end of element, so use next */ + source_elem = next_buffer(hd->source); + if (source_elem) { + hd->source->current_end = source_elem->src + + source_elem->size; + local_elem->src = source_elem->src; + } + } + + if (local_elem->dest == hd->sink->current_end) { + /* end of element, so use next */ + sink_elem = next_buffer(hd->sink); + if (sink_elem) { + hd->sink->current_end = sink_elem->dest + + sink_elem->size; + local_elem->dest = sink_elem->dest; + } + } +} + +/* This is called by DMA driver every time when DMA completes its current + * transfer between host and DSP. + */ +static void host_dma_cb(struct comp_dev *dev, size_t bytes) +{ + struct host_data *hd = comp_get_drvdata(dev); + + comp_cl_dbg(&comp_host, "%p", &comp_host); + + /* update position */ + host_common_update(hd, dev, bytes); + + /* callback for one shot copy */ + if (hd->copy_type == COMP_COPY_ONE_SHOT) + host_common_one_shot(hd, bytes); +} + +/* get status from dma and check for xrun */ +static int host_get_status(struct comp_dev *dev, struct host_data *hd, struct dma_status *stat) +{ + int ret = sof_dma_get_status(hd->dma, hd->chan_index, stat); +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + if (ret == -EPIPE && !hd->xrun_notification_sent) { + hd->xrun_notification_sent = send_copier_gateway_xrun_notif_msg + (dev->pipeline->pipeline_id, dev->direction); + } else if (!ret) { + hd->xrun_notification_sent = false; + } +#endif + return ret; +} + +/* Minimum time between 2 consecutive "no bytes to copy" messages in milliseconds */ +#define SOF_MIN_NO_BYTES_INTERVAL_MS 20 + +static inline bool host_handle_eos(struct host_data *hd, struct comp_dev *dev, + uint32_t avail_samples) +{ + struct sof_audio_buffer *buffer = &hd->local_buffer->audio_buffer; + enum sof_audio_buffer_state state = audio_buffer_get_state(buffer); + + if (!dev->pipeline->expect_eos) + return false; + + if (!avail_samples) { + /* EOS is detected, so we need to set the sink + * state to AUDIOBUF_STATE_END_OF_STREAM. + */ + if (state != AUDIOBUF_STATE_END_OF_STREAM) { + audio_buffer_set_eos(buffer); + comp_info(dev, "- EOS detected"); + } + return true; + } + + if (state == AUDIOBUF_STATE_END_OF_STREAM) + comp_warn(dev, "Data available after reporting end of stream!"); + + return false; +} + +/** + * Calculates bytes to be copied in normal mode. + * @param dev Host component device. + * @return Bytes to be copied. + */ +static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev *dev) +{ + struct comp_buffer *buffer = hd->local_buffer; + 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 = host_get_status(dev, hd, &dma_stat); + if (ret < 0) { + comp_err(dev, "dma_get_status() failed, ret = %d", + ret); + /* return 0 copy_bytes in case of error to skip DMA copy */ + return 0; + } + + /* HDA DMA Write and Read Position registers are not cleared by hardware on + * dma_stop() or dma_start(). However, the dma_buffer is recreated after a reset + * with its w_ptr and r_ptr set to NULL. The w_ptr and r_ptr must be kept in sync + * with the hardware DMA Write and Read Positions. + * Other types of DMA clear their hardware Read/Write Positions upon dma_stop() + * or dma_start(). Additionally, some DMAs, such as GPDMA, do not populate + * dma_status::write_position and read_position. Therefore, synchronization is + * done here only for HDA DMA. + * + * For deep buffers, dma_reload() is called less frequently than consume/produce + * on dma_buffer. Replicate the hardware state of the DMA buffer to the dma_buffer + * struct only when no consume/produce operations on dma_buffer have been called + * since the last dma_reload() (hence hd->partial_size == 0 check here). + */ + if ((hd->dma->plat_data.caps & SOF_DMA_CAP_HDA) && hd->partial_size == 0) + audio_stream_sync_to_hw(&hd->dma_buffer->stream, &dma_stat); + + dma_sample_bytes = hd->config.src_width; + + /* calculate minimum size to copy */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + avail_samples = (dma_stat.pending_length - hd->partial_size) / dma_sample_bytes; + free_samples = audio_stream_get_free_samples(&buffer->stream); + + if (host_handle_eos(hd, dev, avail_samples)) + return 0; + } else { + avail_samples = audio_stream_get_avail_samples(&buffer->stream); + free_samples = (dma_stat.free - hd->partial_size) / dma_sample_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))) { + const uint64_t now = k_uptime_get(); + const uint64_t delta = now - hd->nobytes_last_logged; + const bool reset_skipped = delta > SOF_MIN_NO_BYTES_INTERVAL_MS; + + dma_copy_bytes = MIN(hd->period_bytes, dma_copy_bytes); + + if (hd->n_skipped > 1 && (dma_copy_bytes || reset_skipped)) { + comp_warn(dev, + "Skipped %u no-bytes events in last %llu ms, bytes %u", + hd->n_skipped - 1, delta, dma_copy_bytes); + hd->n_skipped = 0; + } + + if (!dma_copy_bytes) { + if (!hd->n_skipped || reset_skipped) { + hd->nobytes_last_logged = now; + hd->n_skipped = 0; + comp_warn(dev, + "no bytes to copy, available samples: %u, free_samples: %u", + avail_samples, free_samples); + } + hd->n_skipped++; + } + } + + /* dma_copy_bytes should be aligned to minimum possible chunk of + * data to be copied by dma. + * + * FIXME: WARNING: For some frame sizes, this can lead to a split first and/or last frame: + * one part of the frame is processed during one LL cycle, while the remaining portion + * is processed in the subsequent LL cycle. This could be a problem for components + * that assume the first sample in the buffer belongs to the first channel. Even + * if such components consume full frames, they could be bound on a fly as additional + * copier sinks or additional mixin sources or sinks, causing them to start processing + * from the wrong channel. + */ + return ALIGN_DOWN(dma_copy_bytes, hd->dma_copy_align); +} + +#if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION +static inline bool stream_sync(struct host_data *hd, struct comp_dev *dev) +{ + if (!hd->is_grouped) + return true; + + uint64_t current_time = k_cycle_get_64(); + + if (current_time >= hd->next_sync) { + hd->next_sync = current_time + hd->period_in_cycles; + comp_dbg(dev, "hd(%p) next sync = %llu", hd, hd->next_sync); + return true; + } + + return false; +} +#else +static inline bool stream_sync(struct host_data *hd, struct comp_dev *dev) +{ + return true; +} +#endif + +/** + * Performs copy operation for host component working in normal mode. + * It means DMA works continuously and doesn't need reconfiguration. + * @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, copy_callback_t cb) +{ + uint32_t copy_bytes; + const unsigned int threshold = +#if CONFIG_HOST_DMA_RELOAD_DELAY_ENABLE + CONFIG_HOST_DMA_RELOAD_THRESHOLD + +#endif + 0; + int ret = 0; + + comp_dbg(dev, "entry"); + + copy_bytes = host_get_copy_bytes_normal(hd, dev); + if (!copy_bytes) { + if (hd->partial_size != 0) { + if (stream_sync(hd, dev)) { + ret = sof_dma_reload(hd->dma, hd->chan_index, + hd->partial_size); + if (ret < 0) + comp_err(dev, "dma_reload() failed, ret = %d", ret); + + hd->partial_size = 0; + } + } + + return 0; + } + + cb(dev, copy_bytes); + + hd->partial_size += copy_bytes; + + /* + * On large buffers we don't need to reload DMA on every period. When + * CONFIG_HOST_DMA_RELOAD_DELAY_ENABLE is selected on buffers, larger + * than 8 periods, only do that when the threshold is reached, while + * also adding a 2ms safety margin. + */ + if (!IS_ENABLED(CONFIG_HOST_DMA_RELOAD_DELAY_ENABLE) || + hd->dma_buffer_size < hd->period_bytes << 3 || + hd->dma_buffer_size - hd->partial_size <= + (2 + threshold) * hd->period_bytes) { + if (stream_sync(hd, dev)) { + ret = sof_dma_reload(hd->dma, hd->chan_index, + hd->partial_size); + if (ret < 0) + comp_err(dev, "dma_reload() failed, ret = %d", ret); + + hd->partial_size = 0; + } + } + return ret; +} + +static int create_local_elems(struct host_data *hd, struct comp_dev *dev, + uint32_t buffer_count, uint32_t buffer_bytes, + uint32_t direction) +{ + struct dma_sg_elem_array *elem_array; + uint32_t dir; + int err; + + dir = direction == SOF_IPC_STREAM_PLAYBACK ? + SOF_DMA_DIR_HMEM_TO_LMEM : SOF_DMA_DIR_LMEM_TO_HMEM; + + /* if host buffer set we need to allocate local buffer */ + if (hd->host.elem_array.count) { + elem_array = &hd->local.elem_array; + + /* config buffer will be used as proxy */ + err = dma_sg_alloc(NULL, &hd->config.elem_array, SOF_MEM_FLAG_USER, + dir, 1, 0, 0, 0); + if (err < 0) { + comp_err(dev, "dma_sg_alloc() failed"); + return err; + } + } else { + elem_array = &hd->config.elem_array; + } + + err = dma_sg_alloc(NULL, elem_array, SOF_MEM_FLAG_USER, dir, buffer_count, + buffer_bytes, + (uintptr_t)audio_stream_get_addr(&hd->dma_buffer->stream), 0); + if (err < 0) { + comp_err(dev, "dma_sg_alloc() failed"); + return err; + } + + 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_common_trigger(struct host_data *hd, struct comp_dev *dev, int cmd) +{ + int ret = 0; + + /* 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; + + if (hd->chan_index < 0) { + comp_err(dev, "no dma channel configured"); + return -EINVAL; + } + + switch (cmd) { + case COMP_TRIGGER_START: + hd->partial_size = 0; + ret = sof_dma_start(hd->dma, hd->chan_index); + if (ret < 0) + comp_err(dev, "dma_start() failed, ret = %d", + ret); + break; + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_XRUN: + ret = sof_dma_stop(hd->dma, hd->chan_index); + if (ret < 0) + comp_err(dev, "dma stop failed: %d", + ret); + break; + default: + break; + } + + return ret; +} + +static int host_trigger(struct comp_dev *dev, int cmd) +{ + struct host_data *hd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "entry"); + + ret = comp_set_state(dev, cmd); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return host_common_trigger(hd, dev, cmd); +} + +__cold int host_common_new(struct host_data *hd, struct comp_dev *dev, + const struct ipc_config_host *ipc_host, uint32_t config_id) +{ + uint32_t dir; + + assert_can_be_cold(); + + hd->ipc_host = *ipc_host; + /* request HDA DMA with shared access privilege */ + dir = hd->ipc_host.direction == SOF_IPC_STREAM_PLAYBACK ? + SOF_DMA_DIR_HMEM_TO_LMEM : SOF_DMA_DIR_LMEM_TO_HMEM; + + hd->dma = sof_dma_get(dir, 0, SOF_DMA_DEV_HOST, SOF_DMA_ACCESS_SHARED); + if (!hd->dma) { + comp_err(dev, "dma_get() returned NULL"); + return -ENODEV; + } + + /* init buffer elems */ + dma_sg_init(&hd->config.elem_array); + dma_sg_init(&hd->host.elem_array); + dma_sg_init(&hd->local.elem_array); + + ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, config_id); + + hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, sizeof(hd->posn)); + if (!hd->msg) { + comp_err(dev, "ipc_msg_init failed"); + sof_dma_put(hd->dma); + return -ENOMEM; + } + hd->chan_index = -EINVAL; + hd->copy_type = COMP_COPY_NORMAL; + + return 0; +} + +__cold static struct comp_dev *host_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev; + struct host_data *hd; + const struct ipc_config_host *ipc_host = spec; + int ret; + + assert_can_be_cold(); + + comp_cl_dbg(&comp_host, "host_new()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + hd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*hd)); + if (!hd) + goto e_data; + + hd->nobytes_last_logged = k_uptime_get(); + comp_set_drvdata(dev, hd); + + ret = host_common_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: + comp_free_device(dev); + return NULL; +} + +__cold void host_common_free(struct host_data *hd) +{ + assert_can_be_cold(); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Check for NULL just in case the params() step is omitted */ + if (hd->io_perf_host_byte_count) { + io_perf_monitor_release_slot(hd->io_perf_host_byte_count); + hd->io_perf_host_byte_count = NULL; + } +#endif + + /* release DMA channel if not already done by reset */ + if (hd->chan_index >= 0) { + sof_dma_stop(hd->dma, hd->chan_index); + sof_dma_release_channel(hd->dma, hd->chan_index); + hd->chan_index = -EINVAL; + } + + sof_dma_put(hd->dma); + + ipc_msg_free(hd->msg); + dma_sg_free(NULL, &hd->config.elem_array); +} + +__cold static void host_free(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + + assert_can_be_cold(); + + comp_dbg(dev, "entry"); + host_common_free(hd); + rfree(hd); + comp_free_device(dev); +} + +static int host_elements_reset(struct host_data *hd, int direction) +{ + 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 */ + source_elem = hd->source->elem_array.elems; + if (source_elem) { + hd->source->current = 0; + hd->source->current_end = source_elem->src + source_elem->size; + } + + /* setup elem to point to first sink elem */ + sink_elem = hd->sink->elem_array.elems; + if (sink_elem) { + hd->sink->current = 0; + hd->sink->current_end = sink_elem->dest + sink_elem->size; + } + + /* local element */ + if (source_elem && sink_elem) { + local_elem = hd->config.elem_array.elems; + local_elem->dest = sink_elem->dest; + local_elem->size = + direction == SOF_IPC_STREAM_PLAYBACK ? + sink_elem->size : source_elem->size; + local_elem->src = source_elem->src; + } + + return 0; +} + +static int host_verify_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + int ret; + + comp_dbg(dev, "entry"); + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params() failed"); + return ret; + } + + return 0; +} + +/* configure the DMA params and descriptors for host buffer IO */ +int host_common_params(struct host_data *hd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, notifier_callback_t cb) +{ + struct dma_sg_config *config = &hd->config; + struct dma_sg_elem *sg_elem; + struct dma_config *dma_cfg = &hd->z_config; + struct dma_block_config *dma_block_cfg; + uint32_t period_count; + uint32_t period_bytes; + uint32_t buffer_size; + uint32_t buffer_size_preferred; + uint32_t addr_align; + uint32_t align; + int i, err; + bool is_scheduling_source = dev == dev->pipeline->sched_comp; + uint32_t round_up_size; + + /* host params always installed by pipeline IPC */ + hd->host_size = params->buffer.size; + hd->stream_tag = params->stream_tag; + hd->no_stream_position = params->no_stream_position; + hd->host_period_bytes = params->host_period_bytes; + hd->cont_update_posn = params->cont_update_posn; + + /* retrieve DMA buffer address alignment */ + err = sof_dma_get_attribute(hd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (err < 0) { + comp_err(dev, "could not get dma buffer address alignment, err = %d", + err); + return err; + } + + /* retrieve DMA buffer size alignment */ + err = sof_dma_get_attribute(hd->dma, DMA_ATTR_BUFFER_SIZE_ALIGNMENT, &align); + if (err < 0 || !align) { + comp_err(dev, "could not get valid dma buffer alignment, err = %d, align = %u", + err, align); + return -EINVAL; + } + + /* retrieve DMA buffer period count */ + period_count = hd->dma->plat_data.period_count; + if (!period_count) { + comp_err(dev, "could not get valid dma buffer period count"); + return -EINVAL; + } + + if (params->direction == SOF_IPC_STREAM_PLAYBACK) + hd->local_buffer = comp_dev_get_first_data_consumer(dev); + else + hd->local_buffer = comp_dev_get_first_data_producer(dev); + + if (!hd->local_buffer) { + comp_err(dev, "no local buffer found"); + return -EINVAL; + } + + period_bytes = dev->frames * get_frame_bytes(params->frame_fmt, params->channels); + + if (!period_bytes) { + comp_err(dev, "invalid period_bytes"); + return -EINVAL; + } + + /* determine source and sink buffer elements */ + if (params->direction == SOF_IPC_STREAM_PLAYBACK) { + config->direction = SOF_DMA_DIR_HMEM_TO_LMEM; + hd->source = &hd->host; + hd->sink = &hd->local; + } else { + config->direction = SOF_DMA_DIR_LMEM_TO_HMEM; + hd->source = &hd->local; + hd->sink = &hd->host; + } + + /* TODO: should be taken from DMA */ + if (hd->host.elem_array.count) { + period_bytes *= period_count; + period_count = 1; + } + + /* calculate DMA buffer size */ + round_up_size = (params->frame_fmt == SOF_IPC_FRAME_S24_3LE) ? (3 * align) : align; + buffer_size = ROUND_UP(period_bytes, round_up_size) * period_count; + buffer_size_preferred = buffer_size; + if (hd->ipc_host.dma_buffer_size != 0) + buffer_size_preferred = ROUND_UP(hd->ipc_host.dma_buffer_size, buffer_size); + + /* alloc DMA buffer or change its size if exists */ + /* + * Host DMA buffer cannot be shared. So we actually don't need to lock, + * but we have to write back caches after we finish anywae + */ + if (hd->dma_buffer) { + err = buffer_set_size_range(hd->dma_buffer, buffer_size_preferred, buffer_size, + addr_align); + if (err < 0) { + comp_err(dev, "buffer_set_size() failed, buffer_size = %u", + buffer_size); + return err; + } + } else { + /* allocate not shared buffer */ + hd->dma_buffer = buffer_alloc_range(NULL, buffer_size_preferred, buffer_size, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + addr_align, BUFFER_USAGE_NOT_SHARED); + if (!hd->dma_buffer) { + comp_err(dev, "failed to alloc dma buffer"); + return -ENOMEM; + } + + buffer_set_params(hd->dma_buffer, params, BUFFER_UPDATE_FORCE); + + /* set processing function */ + if (params->direction == SOF_IPC_STREAM_CAPTURE) + hd->process = pcm_get_conversion_function( + audio_stream_get_frm_fmt(&hd->local_buffer->stream), + audio_stream_get_frm_fmt(&hd->dma_buffer->stream)); + else + hd->process = pcm_get_conversion_function( + audio_stream_get_frm_fmt(&hd->dma_buffer->stream), + audio_stream_get_frm_fmt(&hd->local_buffer->stream)); + + config->src_width = audio_stream_sample_bytes(&hd->dma_buffer->stream); + config->dest_width = config->src_width; + hd->dma_buffer_size = audio_stream_get_size(&hd->dma_buffer->stream); + } + buffer_size = audio_stream_get_size(&hd->dma_buffer->stream); + + /* create SG DMA elems for local DMA buffer */ + err = create_local_elems(hd, dev, period_count, buffer_size / period_count, + params->direction); + if (err < 0) + return err; + + /* set up DMA configuration - copy in sample bytes. */ + config->cyclic = 0; + config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); + config->is_scheduling_source = is_scheduling_source; + config->period = dev->pipeline->period; + + host_elements_reset(hd, params->direction); + + hd->stream_tag -= 1; + uint32_t hda_chan = hd->stream_tag; + /* get DMA channel from DMAC + * note: stream_tag is ignored by dw-dma + */ + hd->chan_index = sof_dma_request_channel(hd->dma, hda_chan); + if (hd->chan_index < 0) { + comp_err(dev, "requested channel %d is busy", hda_chan); + return -ENODEV; + } + + uint32_t buffer_addr = 0; + uint32_t buffer_bytes = 0; + uint32_t addr; + + memset(dma_cfg, 0, sizeof(*dma_cfg)); + + dma_block_cfg = rzalloc(SOF_MEM_FLAG_USER, + sizeof(*dma_block_cfg)); + + if (!dma_block_cfg) { + comp_err(dev, "dma_block_config allocation failed"); + err = -ENOMEM; + goto err_release_channel; + } + + dma_cfg->block_count = 1; + dma_cfg->source_data_size = config->src_width; + dma_cfg->dest_data_size = config->dest_width; + dma_cfg->head_block = dma_block_cfg; + + for (i = 0; i < config->elem_array.count; i++) { + sg_elem = config->elem_array.elems + i; + + if (config->direction == SOF_DMA_DIR_HMEM_TO_LMEM || + config->direction == SOF_DMA_DIR_DEV_TO_MEM) + addr = sg_elem->dest; + else + addr = sg_elem->src; + + buffer_bytes += sg_elem->size; + + if (buffer_addr == 0) + buffer_addr = addr; + } + + dma_block_cfg->block_size = buffer_bytes; + + switch (config->direction) { + case SOF_DMA_DIR_LMEM_TO_HMEM: + dma_cfg->channel_direction = MEMORY_TO_HOST; + dma_block_cfg->source_address = buffer_addr; + dma_block_cfg->dest_address = hd->config.elem_array.elems[0].dest; + break; + case SOF_DMA_DIR_HMEM_TO_LMEM: + dma_cfg->channel_direction = HOST_TO_MEMORY; + dma_block_cfg->dest_address = buffer_addr; + dma_block_cfg->source_address = hd->config.elem_array.elems[0].src; + break; + } + + err = sof_dma_config(hd->dma, hd->chan_index, dma_cfg); + if (err < 0) { + comp_err(dev, "dma_config() failed"); + goto err_free_block_cfg; + } + + err = sof_dma_get_attribute(hd->dma, DMA_ATTR_COPY_ALIGNMENT, + &hd->dma_copy_align); + + if (err < 0) { + comp_err(dev, "dma_get_attribute() failed"); + goto err_free_block_cfg; + } + + /* minimal copied data shouldn't be less than alignment */ + if (params->frame_fmt != SOF_IPC_FRAME_S24_3LE) + hd->period_bytes = ALIGN_UP(period_bytes, hd->dma_copy_align); + else + hd->period_bytes = period_bytes; + + /* set copy function */ + hd->copy = hd->copy_type == COMP_COPY_ONE_SHOT ? host_copy_one_shot : + host_copy_normal; + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + if (!hd->io_perf_host_byte_count) { + /* On the Host side, unlike the DAI side, the port direction values (INPUT/OUTPUT) + * match the stream direction enum values (CAPTURE/PLAYBACK), so we can directly + * use params->direction here. + */ + struct io_perf_data_item init_data = { + IO_PERF_HDA_ID, + hd->chan_index, + params->direction, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 + }; + io_perf_monitor_init_data(&hd->io_perf_host_byte_count, &init_data); + } +#endif + + return 0; + +err_free_block_cfg: + dma_cfg->head_block = NULL; + rfree(dma_block_cfg); +err_release_channel: + sof_dma_release_channel(hd->dma, hd->chan_index); + hd->chan_index = -EINVAL; + + return err; +} + +static int host_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct host_data *hd = comp_get_drvdata(dev); + int err; + + comp_dbg(dev, "entry"); + + err = host_verify_params(dev, params); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return err; + } + + return host_common_params(hd, dev, params, NULL); +} + +int host_common_prepare(struct host_data *hd) +{ + buffer_zero(hd->dma_buffer); + return 0; +} + +static int host_prepare(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "entry"); + + 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_common_prepare(hd); +} + +static int host_position(struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) +{ + struct host_data *hd = comp_get_drvdata(dev); + + /* TODO: improve accuracy by adding current DMA position */ + posn->host_posn = hd->local_pos; + + return 0; +} + +void host_common_reset(struct host_data *hd, uint16_t state) +{ + if (hd->chan_index >= 0) { + sof_dma_stop(hd->dma, hd->chan_index); + sof_dma_release_channel(hd->dma, hd->chan_index); + hd->chan_index = -EINVAL; + } + + /* free all DMA elements */ + dma_sg_free(NULL, &hd->host.elem_array); + dma_sg_free(NULL, &hd->local.elem_array); + dma_sg_free(NULL, &hd->config.elem_array); + + /* free DMA buffer */ + if (hd->dma_buffer) { + buffer_free(hd->dma_buffer); + hd->dma_buffer = NULL; + } + + /* free DMA block configuration */ + if (hd->z_config.head_block) + rfree(hd->z_config.head_block); + + /* 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, "entry"); + + host_common_reset(hd, dev->state); + dev->state = COMP_STATE_READY; + + return 0; +} + +static int host_copy(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + + if (dev->state != COMP_STATE_ACTIVE) + return 0; + + return host_common_copy(hd, dev, host_dma_cb); +} + +__cold static int host_get_attribute(struct comp_dev *dev, uint32_t type, + void *value) +{ + struct host_data *hd = comp_get_drvdata(dev); + + assert_can_be_cold(); + + switch (type) { + case COMP_ATTR_COPY_TYPE: + *(enum comp_copy_type *)value = hd->copy_type; + break; + case COMP_ATTR_COPY_DIR: + *(uint32_t *)value = hd->ipc_host.direction; + break; + default: + return -EINVAL; + } + + return 0; +} + +__cold static int host_set_attribute(struct comp_dev *dev, uint32_t type, + void *value) +{ + struct host_data *hd = comp_get_drvdata(dev); + + assert_can_be_cold(); + + switch (type) { + case COMP_ATTR_COPY_TYPE: + hd->copy_type = *(enum comp_copy_type *)value; + break; + case COMP_ATTR_HOST_BUFFER: + hd->host.elem_array = *(struct dma_sg_elem_array *)value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static uint64_t host_get_processed_data(struct comp_dev *dev, uint32_t stream_no, bool input) +{ + struct host_data *hd = comp_get_drvdata(dev); + uint64_t ret = 0; + bool source = dev->direction == SOF_IPC_STREAM_PLAYBACK; + + /* Return value only if direction and stream number match. + * The host supports only one stream. + */ + if (stream_no == 0 && source == input) + ret = hd->total_data_processed; + + return ret; +} + +DECLARE_TR_CTX(host_tr, SOF_UUID(host_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_host = { + .type = SOF_COMP_HOST, + .uid = SOF_RT_UUID(host_uuid), + .tctx = &host_tr, + .ops = { + .create = host_new, + .free = host_free, + .params = host_params, + .reset = host_reset, + .trigger = host_trigger, + .copy = host_copy, + .prepare = host_prepare, + .position = host_position, + .get_attribute = host_get_attribute, + .set_attribute = host_set_attribute, + .get_total_data_processed = host_get_processed_data, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_host_info = { + .drv = &comp_host, +}; + +UT_STATIC void sys_comp_host_init(void) +{ + comp_register(platform_shared_get(&comp_host_info, + sizeof(comp_host_info))); +} + +DECLARE_MODULE(sys_comp_host_init); +SOF_MODULE_INIT(host, sys_comp_host_init); diff --git a/src/audio/host.c b/src/audio/host.c deleted file mode 100644 index f4903e486dbe..000000000000 --- a/src/audio/host.c +++ /dev/null @@ -1,851 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component_ext.h> -#include <sof/audio/pcm_converter.h> -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dma.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/math/numbers.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -static const struct comp_driver comp_host; - -/* 8b9d100c-6d78-418f-90a3-e0e805d0852b */ -DECLARE_SOF_UUID("host", host_uuid, 0x8b9d100c, 0x6d78, 0x418f, - 0x90, 0xa3, 0xe0, 0xe8, 0x05, 0xd0, 0x85, 0x2b); - -/** - * \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 */ - - /* 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 - */ - - pcm_converter_func process; /**< processing function */ - - /* 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) - return NULL; - if (++hc->current == hc->elem_array.count) - hc->current = 0; - return hc->elem_array.elems + hc->current; -} - -static uint32_t host_dma_get_split(struct host_data *hd, uint32_t bytes) -{ - struct dma_sg_elem *local_elem = hd->config.elem_array.elems; - uint32_t split_src = 0; - uint32_t split_dst = 0; - - if (local_elem->src + bytes > hd->source->current_end) - split_src = bytes - - (hd->source->current_end - local_elem->src); - - if (local_elem->dest + bytes > hd->sink->current_end) - split_dst = bytes - - (hd->sink->current_end - local_elem->dest); - - /* get max split, so the current copy will be minimum */ - return MAX(split_src, split_dst); -} - -static void host_update_position(struct comp_dev *dev, uint32_t bytes) -{ - struct host_data *hd = comp_get_drvdata(dev); - uint32_t samples; - - samples = bytes / audio_stream_sample_bytes(&hd->local_buffer->stream); - - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) - dma_buffer_copy_from(hd->dma_buffer, bytes, - hd->local_buffer, bytes, - hd->process, samples); - else - dma_buffer_copy_to(hd->local_buffer, bytes, - hd->dma_buffer, bytes, - hd->process, samples); - - dev->position += bytes; - - /* new local period, update host buffer position blks - * local_pos is queried by the ops.position() API - */ - hd->local_pos += bytes; - - /* buffer overlap, hardcode host buffer size at the moment */ - if (hd->local_pos >= hd->host_size) - hd->local_pos = 0; - - /* Don't send stream position if no_stream_position == 1 */ - if (!hd->no_stream_position) { - hd->report_pos += bytes; - - /* host_period_bytes is set to zero to disable position update - * by IPC for FW version before 3.11, so send IPC message to - * driver according to this condition and report_pos. - */ - if (hd->host_period_bytes != 0 && - hd->report_pos >= hd->host_period_bytes) { - hd->report_pos = 0; - - /* send timestamped position to host - * (updates position first, by calling ops.position()) - */ - pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); - mailbox_stream_write(dev->pipeline->posn_offset, - &hd->posn, sizeof(hd->posn)); - ipc_msg_send(hd->msg, &hd->posn, false); - } - } -} - -/* The host memory is not guaranteed to be continuous and also not guaranteed - * to have a period/buffer size that is a multiple of the DSP period size. - * 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) -{ - 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; - - /* update src and dest positions and check for overflow */ - local_elem->src += bytes; - local_elem->dest += bytes; - - if (local_elem->src == hd->source->current_end) { - /* end of element, so use next */ - source_elem = next_buffer(hd->source); - if (source_elem) { - hd->source->current_end = source_elem->src + - source_elem->size; - local_elem->src = source_elem->src; - } - } - - if (local_elem->dest == hd->sink->current_end) { - /* end of element, so use next */ - sink_elem = next_buffer(hd->sink); - if (sink_elem) { - hd->sink->current_end = sink_elem->dest + - sink_elem->size; - local_elem->dest = sink_elem->dest; - } - } -} - -/* This is called by DMA driver every time when DMA completes its current - * transfer between host and DSP. - */ -static void host_dma_cb(void *arg, enum notify_id type, void *data) -{ - 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", (uintptr_t)&comp_host); - - /* update position */ - host_update_position(dev, bytes); - - /* callback for one shot copy */ - if (hd->copy_type == COMP_COPY_ONE_SHOT) - host_one_shot_cb(dev, bytes); -} - -static int create_local_elems(struct comp_dev *dev, uint32_t buffer_count, - uint32_t buffer_bytes) -{ - struct host_data *hd = comp_get_drvdata(dev); - struct dma_sg_elem_array *elem_array; - uint32_t dir; - int err; - - dir = dev->direction == SOF_IPC_STREAM_PLAYBACK ? - DMA_DIR_HMEM_TO_LMEM : DMA_DIR_LMEM_TO_HMEM; - - /* if host buffer set we need to allocate local buffer */ - if (hd->host.elem_array.count) { - elem_array = &hd->local.elem_array; - - /* config buffer will be used as proxy */ - err = dma_sg_alloc(&hd->config.elem_array, SOF_MEM_ZONE_RUNTIME, - dir, 1, 0, 0, 0); - if (err < 0) { - comp_err(dev, "create_local_elems() error: dma_sg_alloc() failed"); - return err; - } - } else { - elem_array = &hd->config.elem_array; - } - - err = dma_sg_alloc(elem_array, SOF_MEM_ZONE_RUNTIME, dir, buffer_count, - buffer_bytes, - (uintptr_t)(hd->dma_buffer->stream.addr), 0); - if (err < 0) { - comp_err(dev, "create_local_elems() error: dma_sg_alloc() failed"); - return err; - } - - 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. - */ -static int host_trigger(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; - } - - /* 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; - - if (!hd->chan) { - comp_err(dev, "host_trigger() error: no dma channel configured"); - return -EINVAL; - } - - switch (cmd) { - case COMP_TRIGGER_START: - ret = dma_start(hd->chan); - if (ret < 0) - comp_err(dev, "host_trigger() error: dma_start() failed, ret = %u", - ret); - break; - case COMP_TRIGGER_STOP: - case COMP_TRIGGER_XRUN: - ret = dma_stop(hd->chan); - if (ret < 0) - comp_err(dev, "host_trigger(): dma stop failed: %d", - ret); - break; - default: - break; - } - - return ret; -} - -static struct comp_dev *host_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct sof_ipc_comp_host *ipc_host = (struct sof_ipc_comp_host *)comp; - struct sof_ipc_comp_host *host; - struct comp_dev *dev; - struct host_data *hd; - uint32_t dir; - int ret; - - comp_cl_dbg(&comp_host, "host_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_host)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_host); - - host = COMP_GET_IPC(dev, sof_ipc_comp_host); - ret = memcpy_s(host, sizeof(*host), - ipc_host, sizeof(struct sof_ipc_comp_host)); - assert(!ret); - - hd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*hd)); - if (!hd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, hd); - - /* request HDA DMA with shared access privilege */ - dir = ipc_host->direction == SOF_IPC_STREAM_PLAYBACK ? - DMA_DIR_HMEM_TO_LMEM : DMA_DIR_LMEM_TO_HMEM; - - hd->dma = dma_get(dir, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); - if (!hd->dma) { - comp_err(dev, "host_new() error: dma_get() returned NULL"); - rfree(hd); - rfree(dev); - return NULL; - } - - /* init buffer elems */ - dma_sg_init(&hd->config.elem_array); - dma_sg_init(&hd->host.elem_array); - dma_sg_init(&hd->local.elem_array); - - ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, comp->id); - - hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, sizeof(hd->posn)); - if (!hd->msg) { - comp_err(dev, "host_new() error: ipc_msg_init failed"); - dma_put(hd->dma); - rfree(hd); - rfree(dev); - return NULL; - } - - hd->chan = NULL; - hd->copy_type = COMP_COPY_NORMAL; - dev->state = COMP_STATE_READY; - - return dev; -} - -static void host_free(struct comp_dev *dev) -{ - struct host_data *hd = comp_get_drvdata(dev); - - comp_info(dev, "host_free()"); - - dma_put(hd->dma); - - ipc_msg_free(hd->msg); - dma_sg_free(&hd->config.elem_array); - rfree(hd); - rfree(dev); -} - -static int host_elements_reset(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 *local_elem; - - /* setup elem to point to first source elem */ - source_elem = hd->source->elem_array.elems; - if (source_elem) { - hd->source->current = 0; - hd->source->current_end = source_elem->src + source_elem->size; - } - - /* setup elem to point to first sink elem */ - sink_elem = hd->sink->elem_array.elems; - if (sink_elem) { - hd->sink->current = 0; - hd->sink->current_end = sink_elem->dest + sink_elem->size; - } - - /* local element */ - if (source_elem && sink_elem) { - local_elem = hd->config.elem_array.elems; - local_elem->dest = sink_elem->dest; - local_elem->size = - dev->direction == SOF_IPC_STREAM_PLAYBACK ? - sink_elem->size : source_elem->size; - local_elem->src = source_elem->src; - } - - return 0; -} - -static int host_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int ret; - - comp_dbg(dev, "host_verify_params()"); - - ret = comp_verify_params(dev, 0, params); - if (ret < 0) { - comp_err(dev, "host_verify_params() error: comp_verify_params() failed"); - return ret; - } - - return 0; -} - -/* configure the DMA params and descriptors for host buffer IO */ -static int host_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct host_data *hd = comp_get_drvdata(dev); - struct dma_sg_config *config = &hd->config; - uint32_t period_count; - uint32_t period_bytes; - uint32_t buffer_size; - uint32_t addr_align; - uint32_t align; - int err; - - comp_dbg(dev, "host_params()"); - - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) - hd->local_buffer = list_first_item(&dev->bsink_list, - struct comp_buffer, - source_list); - else - hd->local_buffer = list_first_item(&dev->bsource_list, - struct comp_buffer, - sink_list); - - 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; - hd->no_stream_position = params->no_stream_position; - hd->host_period_bytes = params->host_period_bytes; - - /* retrieve DMA buffer address alignment */ - err = dma_get_attribute(hd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, - &addr_align); - if (err < 0) { - comp_err(dev, "host_params() error: could not get dma buffer address alignment, err = %d", - err); - return err; - } - - /* retrieve DMA buffer size alignment */ - err = dma_get_attribute(hd->dma, DMA_ATTR_BUFFER_ALIGNMENT, &align); - if (err < 0 || !align) { - comp_err(dev, "host_params() error: could not get valid dma buffer alignment, err = %d, align = %u", - err, align); - return -EINVAL; - } - - /* retrieve DMA buffer period count */ - err = dma_get_attribute(hd->dma, DMA_ATTR_BUFFER_PERIOD_COUNT, - &period_count); - if (err < 0 || !period_count) { - comp_err(dev, "host_params() error: could not get valid dma buffer period count, err = %d, period_count = %u", - err, period_count); - return -EINVAL; - } - - period_bytes = dev->frames * - audio_stream_frame_bytes(&hd->local_buffer->stream); - - if (!period_bytes) { - comp_err(dev, "host_params() error: invalid period_bytes"); - return -EINVAL; - } - - /* determine source and sink buffer elements */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - config->direction = DMA_DIR_HMEM_TO_LMEM; - hd->source = &hd->host; - hd->sink = &hd->local; - } else { - config->direction = DMA_DIR_LMEM_TO_HMEM; - hd->source = &hd->local; - hd->sink = &hd->host; - } - - /* TODO: should be taken from DMA */ - if (hd->host.elem_array.count) { - period_bytes *= period_count; - period_count = 1; - } - - /* calculate DMA buffer size */ - buffer_size = ALIGN_UP(period_count * period_bytes, align); - - /* alloc DMA buffer or change its size if exists */ - if (hd->dma_buffer) { - err = buffer_set_size(hd->dma_buffer, buffer_size); - if (err < 0) { - comp_err(dev, "host_params() error: buffer_set_size() failed, buffer_size = %u", - buffer_size); - return err; - } - } else { - hd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, - addr_align); - if (!hd->dma_buffer) { - comp_err(dev, "host_params() error: failed to alloc dma buffer"); - return -ENOMEM; - } - } - - /* create SG DMA elems for local DMA buffer */ - err = create_local_elems(dev, period_count, buffer_size / period_count); - if (err < 0) - return err; - - /* set up DMA configuration - copy in sample bytes. */ - config->src_width = - audio_stream_sample_bytes(&hd->local_buffer->stream); - config->dest_width = - audio_stream_sample_bytes(&hd->local_buffer->stream); - config->cyclic = 0; - config->irq_disabled = pipeline_is_timer_driven(dev->pipeline); - config->is_scheduling_source = comp_is_scheduling_source(dev); - config->period = dev->pipeline->ipc_pipe.period; - - host_elements_reset(dev); - - hd->stream_tag -= 1; - /* get DMA channel from DMAC - * note: stream_tag is ignored by dw-dma - */ - hd->chan = dma_channel_get(hd->dma, hd->stream_tag); - if (!hd->chan) { - comp_err(dev, "host_params() error: hd->chan is NULL"); - return -ENODEV; - } - - err = dma_set_config(hd->chan, &hd->config); - if (err < 0) { - comp_err(dev, "host_params() error: dma_set_config() failed"); - dma_channel_put(hd->chan); - hd->chan = NULL; - return err; - } - - err = dma_get_attribute(hd->dma, DMA_ATTR_COPY_ALIGNMENT, - &hd->dma_copy_align); - - if (err < 0) { - comp_err(dev, "host_params() error: dma_get_attribute()"); - - return err; - } - - /* set up callback */ - notifier_register(dev, hd->chan, NOTIFIER_ID_DMA_COPY, host_dma_cb); - - /* set processing function */ - hd->process = - pcm_get_conversion_function(hd->local_buffer->stream.frame_fmt, - hd->local_buffer->stream.frame_fmt); - - return 0; -} - -static int host_prepare(struct comp_dev *dev) -{ - struct host_data *hd = comp_get_drvdata(dev); - int ret; - - comp_dbg(dev, "host_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; - - hd->local_pos = 0; - hd->report_pos = 0; - dev->position = 0; - - return 0; -} - -static int host_pointer_reset(struct comp_dev *dev) -{ - struct host_data *hd = comp_get_drvdata(dev); - - /* reset buffer pointers */ - hd->local_pos = 0; - hd->report_pos = 0; - dev->position = 0; - - return 0; -} - -static int host_position(struct comp_dev *dev, - struct sof_ipc_stream_posn *posn) -{ - struct host_data *hd = comp_get_drvdata(dev); - - /* TODO: improve accuracy by adding current DMA position */ - posn->host_posn = hd->local_pos; - - return 0; -} - -static int host_reset(struct comp_dev *dev) -{ - struct host_data *hd = comp_get_drvdata(dev); - - comp_dbg(dev, "host_reset()"); - - if (hd->chan) { - /* remove callback */ - notifier_unregister(dev, hd->chan, NOTIFIER_ID_DMA_COPY); - dma_channel_put(hd->chan); - } - - /* free all DMA elements */ - dma_sg_free(&hd->host.elem_array); - dma_sg_free(&hd->local.elem_array); - dma_sg_free(&hd->config.elem_array); - - /* free DMA buffer */ - if (hd->dma_buffer) { - buffer_free(hd->dma_buffer); - hd->dma_buffer = NULL; - } - - /* reset dma channel as we have put it */ - hd->chan = NULL; - - host_pointer_reset(dev); - hd->copy_type = COMP_COPY_NORMAL; - hd->source = NULL; - hd->sink = NULL; - dev->state = COMP_STATE_READY; - - return 0; -} - -static uint32_t host_buffer_get_copy_bytes(struct comp_dev *dev) -{ - struct host_data *hd = comp_get_drvdata(dev); - struct dma_sg_elem *local_elem = hd->config.elem_array.elems; - uint32_t avail_bytes = 0; - uint32_t free_bytes = 0; - uint32_t copy_bytes = 0; - uint32_t split_value; - int ret; - uint32_t flags = 0; - - if (hd->copy_type == COMP_COPY_ONE_SHOT) { - buffer_lock(hd->local_buffer, &flags); - - /* calculate minimum size to copy */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) - copy_bytes = hd->local_buffer->stream.free; - else - copy_bytes = hd->local_buffer->stream.avail; - - buffer_unlock(hd->local_buffer, flags); - - /* copy_bytes should be aligned to minimum possible chunk of - * data to be copied by dma. - */ - copy_bytes = ALIGN_DOWN(copy_bytes, hd->dma_copy_align); - - split_value = host_dma_get_split(hd, copy_bytes); - if (split_value) - copy_bytes -= split_value; - - local_elem->size = copy_bytes; - } else { - /* get data sizes from DMA */ - ret = dma_get_data_size(hd->chan, &avail_bytes, - &free_bytes); - if (ret < 0) { - comp_cl_err(&comp_host, "host_buffer_cb() error: dma_get_data_size() failed, ret = %u", - ret); - return 0; - } - - buffer_lock(hd->local_buffer, &flags); - - /* calculate minimum size to copy */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) - copy_bytes = MIN(avail_bytes, - hd->local_buffer->stream.free); - else - copy_bytes = MIN(hd->local_buffer->stream.avail, - free_bytes); - - buffer_unlock(hd->local_buffer, flags); - - /* copy_bytes should be aligned to minimum possible chunk of - * data to be copied by dma. - */ - copy_bytes = ALIGN_DOWN(copy_bytes, hd->dma_copy_align); - } - - return copy_bytes; -} - -/* 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); - uint32_t copy_bytes = 0; - uint32_t flags = 0; - int ret = 0; - - comp_dbg(dev, "host_copy()"); - - if (dev->state != COMP_STATE_ACTIVE) - return 0; - - if (hd->copy_type == COMP_COPY_BLOCKING) - flags |= DMA_COPY_BLOCKING; - else if (hd->copy_type == COMP_COPY_ONE_SHOT) - flags |= DMA_COPY_ONE_SHOT; - - /* update first transfer manually */ - if (!dev->position && flags & COMP_COPY_ONE_SHOT) - host_one_shot_cb(dev, hd->dma_buffer->stream.size); - - copy_bytes = host_buffer_get_copy_bytes(dev); - if (!copy_bytes) { - comp_info(dev, "host_copy(): no bytes to copy"); - return ret; - } - - /* reconfigure transfer */ - ret = dma_set_config(hd->chan, &hd->config); - if (ret < 0) { - comp_cl_err(&comp_host, "host_copy() error: dma_set_config() failed, ret = %u", - ret); - return ret; - } - - ret = dma_copy(hd->chan, copy_bytes, flags); - if (ret < 0) { - comp_cl_err(&comp_host, "host_copy() error: dma_copy() failed, ret = %u", - ret); - return ret; - } - - return ret; -} - -static int host_set_attribute(struct comp_dev *dev, uint32_t type, - void *value) -{ - struct host_data *hd = comp_get_drvdata(dev); - - switch (type) { - case COMP_ATTR_COPY_TYPE: - hd->copy_type = *(enum comp_copy_type *)value; - break; - case COMP_ATTR_HOST_BUFFER: - hd->host.elem_array = *(struct dma_sg_elem_array *)value; - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct comp_driver comp_host = { - .type = SOF_COMP_HOST, - .uid = SOF_UUID(host_uuid), - .ops = { - .new = host_new, - .free = host_free, - .params = host_params, - .reset = host_reset, - .trigger = host_trigger, - .copy = host_copy, - .prepare = host_prepare, - .position = host_position, - .set_attribute = host_set_attribute, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_host_info = { - .drv = &comp_host, -}; - -static void sys_comp_host_init(void) -{ - comp_register(platform_shared_get(&comp_host_info, - sizeof(comp_host_info))); -} - -DECLARE_MODULE(sys_comp_host_init); diff --git a/src/audio/igo_nr/CMakeLists.txt b/src/audio/igo_nr/CMakeLists.txt new file mode 100644 index 000000000000..f0fee994d82f --- /dev/null +++ b/src/audio/igo_nr/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_IGO_NR STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/igo_nr_llext) + add_dependencies(app igo_nr) + return() +endif() + +add_local_sources(sof igo_nr.c) + +if (CONFIG_COMP_IGO_NR_STUB) + add_local_sources(sof igo_nr_stub.c) + +else() + is_zephyr(zephyr) + if(zephyr) ### Zephyr ### + zephyr_library_import(IGOChrome ${CMAKE_CURRENT_LIST_DIR}/libigonr.a) + else() + sof_add_static_library(IGOChrome ${CMAKE_CURRENT_LIST_DIR}/libigonr.a) + endif() + +endif() diff --git a/src/audio/igo_nr/Kconfig b/src/audio/igo_nr/Kconfig new file mode 100644 index 000000000000..d584df40cb67 --- /dev/null +++ b/src/audio/igo_nr/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_IGO_NR + tristate "IGO NR component" + select COMP_BLOB + select COMP_IGO_NR_STUB if COMP_STUBS + help + This option enables Intelligo non-speech noise reduction. The feature links to a proprietary + binary libigonr.a that currently is supported on different Xtensa DSP platforms. Please email + info@intelli-go.com for any questions about the binary. + +config COMP_IGO_NR_STUB + bool "IGO NR component" + select COMP_BLOB + depends on COMP_IGO_NR + help + This option builds the IGO adapter with a stub library, it should only be used for + testing or CI purposes. diff --git a/src/audio/igo_nr/LICENSE b/src/audio/igo_nr/LICENSE new file mode 100644 index 000000000000..1b8c36f18605 --- /dev/null +++ b/src/audio/igo_nr/LICENSE @@ -0,0 +1 @@ +The AI Noise Reduction Software contained herein is the proprietary intellectual property of British Cayman Islands Intelligo Technology, Inc. All rights reserved. Customer who desires to obtain more information or the license to incorporate this Software into their systems and/or devices may contact Intelligo at info@intelli-go.com. \ No newline at end of file diff --git a/src/audio/igo_nr/README.md b/src/audio/igo_nr/README.md new file mode 100644 index 000000000000..3ab01a6a9cbc --- /dev/null +++ b/src/audio/igo_nr/README.md @@ -0,0 +1,14 @@ +# Intelligo Noise Reduction (IGO NR) Architecture + +This directory contains integration for the Intelligo Noise Reduction algorithms. + +## Overview + +IGO NR is an advanced noise suppression engine targeting microphone input paths to improve speech intelligibility. + +## Configuration and Scripts + +- **Kconfig**: Enables the Intelligo non-speech noise reduction component (`COMP_IGO_NR`), which utilizes a proprietary binary `libigonr.a`. Also provides a `COMP_IGO_NR_STUB` option for testing/CI environments that links a stub library instead of the proprietary binary. +- **CMakeLists.txt**: Handles the build integration. It either links the stub (`igo_nr_stub.c`) or the actual binary (`libigonr.a`) based on the Kconfig selection. Supports Zephyr integration module loading and standard external library compilation (`llext`). +- **igo_nr.toml**: Defines the topology parameters for the module (UUID, module_type, pin configuration, and processing constraints configured under `mod_cfg`). +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/igo_nr.conf`, it defines the `igo_nr` widget object for topology generation. Included with mixer controls binding get/put operations (`259`) and defaults to UUID `bc:e2:6a:69:77:28:eb:11:ad:c1:02:42:ac:12:00:02` (type `effect`). diff --git a/src/audio/igo_nr/igo_nr.c b/src/audio/igo_nr/igo_nr.c new file mode 100644 index 000000000000..e398af7d964b --- /dev/null +++ b/src/audio/igo_nr/igo_nr.c @@ -0,0 +1,905 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intelligo Technology Inc. All rights reserved. +// +// Author: Fu-Yun TSUO <fy.tsuo@intelli-go.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/igo_nr.h> +#include <user/trace.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/igo_nr/igo_nr_comp.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/header.h> +#endif + +#define SOF_IGO_NR_MAX_SIZE 4096 /* Max size for coef data in bytes */ + +enum IGO_NR_ENUM { + IGO_NR_ONOFF_SWITCH = 0, + IGO_NR_ENUM_LAST, +}; + +LOG_MODULE_REGISTER(igo_nr, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(igo_nr); + +static void igo_nr_lib_process(struct comp_data *cd) +{ + /* Pass through the active channel if + * 1) It's not enabled, or + * 2) hw parameter is not valid. + */ + if (!cd->process_enable[cd->config.active_channel_idx] || + cd->invalid_param || + cd->config.igo_params.nr_bypass == 1) { + memcpy_s(cd->out, IGO_FRAME_SIZE * sizeof(int16_t), + cd->in, IGO_FRAME_SIZE * sizeof(int16_t)); + } else { + IgoLibProcess(cd->p_handle, + &cd->igo_stream_data_in, + &cd->igo_stream_data_ref, + &cd->igo_stream_data_out); + } +} + +#if CONFIG_FORMAT_S16LE +static int igo_nr_capture_s16(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames) +{ + int16_t *x, *y1, *y2; + int16_t *x_start, *y_start, *x_end, *y_end; + int16_t sample; + size_t x_size, y_size; + size_t request_size = frames * source_get_frame_bytes(source); + int sink_samples_without_wrap; + int samples_without_wrap; + int samples_left; + int ret; + int nch = source_get_channels(source); + int i, j, k; + +#if CONFIG_DEBUG + int32_t dbg_en = cd->config.igo_params.dump_data == 1 && nch > 1; + int32_t dbg_ch_idx; + + /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ + if (cd->config.active_channel_idx >= nch) + dbg_ch_idx = 0; + else + dbg_ch_idx = cd->config.active_channel_idx + 1; + +#endif + + ret = source_get_data(source, request_size, (void const **)&x, + (void const **)&x_start, &x_size); + if (ret) + return ret; + + ret = sink_get_buffer(sink, request_size, (void **)&y1, (void **)&y_start, &y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + y2 = y1; + x_end = x_start + x_size; + y_end = y_start + y_size; + + /* Deinterleave the source buffer and keeps the active channel data as input. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + samples_without_wrap = x_end - x; + samples_without_wrap = MIN(samples_left, samples_without_wrap); + sink_samples_without_wrap = y_end - y1; + samples_without_wrap = MIN(samples_without_wrap, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + sample = *x; + if (k == cd->config.active_channel_idx) + cd->in[i] = sample; + else + *y1 = sample; + + x++; + y1++; + } + i++; + } + + x = cir_buf_wrap(x, x_start, x_end); + y1 = cir_buf_wrap(y1, y_start, y_end); + samples_left -= samples_without_wrap; + } + + igo_nr_lib_process(cd); + + /* Interleave write the processed data into active output channel. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + sink_samples_without_wrap = y_end - y2; + samples_without_wrap = MIN(samples_left, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + *y2 = cd->out[i]; +#if CONFIG_DEBUG + if (dbg_en && k == dbg_ch_idx) + *y2 = cd->in[i]; +#endif + y2++; + } + i++; + } + + y2 = cir_buf_wrap(y2, y_start, y_end); + samples_left -= samples_without_wrap; + } + + source_release_data(source, request_size); + sink_commit_buffer(sink, request_size); + return 0; +} +#endif + +#if CONFIG_FORMAT_S24LE +static int igo_nr_capture_s24(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames) +{ + int32_t *x, *y1, *y2; + int32_t *x_start, *y_start, *x_end, *y_end; + size_t x_size, y_size; + size_t request_size = frames * source_get_frame_bytes(source); + int sink_samples_without_wrap; + int samples_without_wrap; + int samples_left; + int ret; + int nch = source_get_channels(source); + int i, j, k; + +#if CONFIG_DEBUG + int32_t dbg_en = cd->config.igo_params.dump_data == 1 && nch > 1; + int32_t dbg_ch_idx; + + /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ + if (cd->config.active_channel_idx >= nch) + dbg_ch_idx = 0; + else + dbg_ch_idx = cd->config.active_channel_idx + 1; + +#endif + + ret = source_get_data(source, request_size, (void const **)&x, + (void const **)&x_start, &x_size); + if (ret) + return ret; + + ret = sink_get_buffer(sink, request_size, (void **)&y1, (void **)&y_start, &y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + y2 = y1; + x_end = x_start + x_size; + y_end = y_start + y_size; + + /* Deinterleave the source buffer and keeps the active channel data as input. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + samples_without_wrap = x_end - x; + samples_without_wrap = MIN(samples_left, samples_without_wrap); + sink_samples_without_wrap = y_end - y1; + samples_without_wrap = MIN(samples_without_wrap, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + cd->in[i] = sat_int16(Q_SHIFT_RND(*x, 23, 15)); + else + *y1 = *x; + + x++; + y1++; + } + i++; + } + + x = cir_buf_wrap(x, x_start, x_end); + y1 = cir_buf_wrap(y1, y_start, y_end); + samples_left -= samples_without_wrap; + } + + igo_nr_lib_process(cd); + + /* Interleave write the processed data into active output channel. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + sink_samples_without_wrap = y_end - y2; + samples_without_wrap = MIN(samples_left, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + *y2 = cd->out[i] << 8; +#if CONFIG_DEBUG + if (dbg_en && k == dbg_ch_idx) + *y2 = cd->in[i] << 8; +#endif + y2++; + } + i++; + } + + y2 = cir_buf_wrap(y2, y_start, y_end); + samples_left -= samples_without_wrap; + } + + source_release_data(source, request_size); + sink_commit_buffer(sink, request_size); + return 0; +} +#endif + +#if CONFIG_FORMAT_S32LE +static int igo_nr_capture_s32(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames) +{ + int32_t *x, *y1, *y2; + int32_t *x_start, *y_start, *x_end, *y_end; + size_t x_size, y_size; + size_t request_size = frames * source_get_frame_bytes(source); + int sink_samples_without_wrap; + int samples_without_wrap; + int samples_left; + int ret; + int nch = source_get_channels(source); + int i, j, k; + +#if CONFIG_DEBUG + int32_t dbg_en = cd->config.igo_params.dump_data == 1 && nch > 1; + int32_t dbg_ch_idx; + + /* Under DEBUG mode, overwrite the next channel with input interleavedly. */ + if (cd->config.active_channel_idx >= nch) + dbg_ch_idx = 0; + else + dbg_ch_idx = cd->config.active_channel_idx + 1; + +#endif + + ret = source_get_data(source, request_size, (void const **)&x, + (void const **)&x_start, &x_size); + if (ret) + return ret; + + ret = sink_get_buffer(sink, request_size, (void **)&y1, (void **)&y_start, &y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + y2 = y1; + x_end = x_start + x_size; + y_end = y_start + y_size; + + /* Deinterleave the source buffer and keeps the active channel data as input. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + samples_without_wrap = x_end - x; + samples_without_wrap = MIN(samples_left, samples_without_wrap); + sink_samples_without_wrap = y_end - y1; + samples_without_wrap = MIN(samples_without_wrap, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + cd->in[i] = sat_int16(Q_SHIFT_RND(*x, 31, 15)); + else + *y1 = *x; + + x++; + y1++; + } + i++; + } + + x = cir_buf_wrap(x, x_start, x_end); + y1 = cir_buf_wrap(y1, y_start, y_end); + samples_left -= samples_without_wrap; + } + + igo_nr_lib_process(cd); + + /* Interleave write the processed data into active output channel. */ + i = 0; + samples_left = nch * frames; + while (samples_left) { + sink_samples_without_wrap = y_end - y2; + samples_without_wrap = MIN(samples_left, sink_samples_without_wrap); + for (j = 0; j < samples_without_wrap; j += nch) { + for (k = 0; k < nch; k++) { + if (k == cd->config.active_channel_idx) + *y2 = cd->out[i] << 16; +#if CONFIG_DEBUG + if (dbg_en && k == dbg_ch_idx) + *y2 = cd->in[i] << 16; +#endif + y2++; + } + i++; + } + + y2 = cir_buf_wrap(y2, y_start, y_end); + samples_left -= samples_without_wrap; + } + + source_release_data(source, request_size); + sink_commit_buffer(sink, request_size); + return 0; +} +#endif + +static inline int32_t set_capture_func(struct processing_module *mod, struct sof_source *source) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + /* The igo_nr supports S16_LE data. Format converter is needed. */ + switch (source_get_frm_fmt(source)) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + comp_info(dev, "SOF_IPC_FRAME_S16_LE"); + cd->igo_nr_func = igo_nr_capture_s16; + break; +#endif +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + comp_info(dev, "SOF_IPC_FRAME_S24_4LE"); + cd->igo_nr_func = igo_nr_capture_s24; + break; +#endif +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + comp_info(dev, "SOF_IPC_FRAME_S32_LE"); + cd->igo_nr_func = igo_nr_capture_s32; + break; +#endif + default: + comp_err(dev, "invalid frame_fmt"); + return -EINVAL; + } + return 0; +} + +static int igo_nr_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *cfg = &md->cfg; + struct comp_data *cd; + size_t bs = cfg->size; + int32_t ret; + + comp_info(dev, "entry"); + + /* Check first that configuration blob size is sane */ + if (bs > SOF_IGO_NR_MAX_SIZE) { + comp_err(dev, "error: configuration blob size = %u > %d", + bs, SOF_IGO_NR_MAX_SIZE); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + ret = IgoLibGetInfo(&cd->igo_lib_info); + if (ret != IGO_RET_OK) { + comp_err(dev, "IgoLibGetInfo() Failed."); + ret = -EINVAL; + goto cd_fail; + } + + cd->p_handle = mod_balloc(mod, cd->igo_lib_info.handle_size); + if (!cd->p_handle) { + comp_err(dev, "igo_handle memory mod_balloc error for size %d", + cd->igo_lib_info.handle_size); + ret = -ENOMEM; + goto cd_fail; + } + + /* Handler for configuration data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto cd_fail2; + } + + /* Get configuration data */ + ret = comp_init_data_blob(cd->model_handler, bs, cfg->data); + if (ret < 0) { + comp_err(dev, "comp_init_data_blob() failed."); + ret = -ENOMEM; + goto cd_fail3; + } + + /* update downstream (playback) or upstream (capture) buffer parameters */ + mod->verify_params_flags = BUFF_PARAMS_RATE; + comp_info(dev, "igo_nr created"); + return 0; + +cd_fail3: + mod_data_blob_handler_free(mod, cd->model_handler); + +cd_fail2: + mod_free(mod, cd->p_handle); + +cd_fail: + mod_free(mod, cd); + return ret; +} + +static int igo_nr_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + mod_data_blob_handler_free(mod, cd->model_handler); + + mod_free(mod, cd->p_handle); + mod_free(mod, cd); + return 0; +} + +/* check component audio stream parameters */ +static int32_t igo_nr_check_params(struct processing_module *mod, struct sof_source *source, + struct sof_sink *sink) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_info(dev, "entry"); + + /* set source/sink_frames/rate */ + cd->source_rate = source_get_rate(source); + cd->sink_rate = sink_get_rate(sink); + + if (source_get_channels(source) != sink_get_channels(sink)) { + comp_err(dev, "mismatch source/sink stream channels"); + cd->invalid_param = true; + } + + if (!cd->sink_rate) { + comp_err(dev, "zero sink rate"); + return -EINVAL; + } + + /* The igo_nr supports sample rate 48000 only. */ + switch (cd->source_rate) { + case 48000: + comp_info(dev, "sample rate = 48000"); + cd->invalid_param = false; + break; + default: + comp_err(dev, "invalid sample rate"); + cd->invalid_param = true; + } + + return cd->invalid_param ? -EINVAL : 0; +} + +static int32_t igo_nr_check_config_validity(struct comp_dev *dev, + struct comp_data *cd) +{ + struct sof_igo_nr_config *p_config = comp_get_data_blob(cd->model_handler, NULL, NULL); + + if (!p_config) { + comp_err(dev, "error: invalid cd->model_handler"); + return -EINVAL; + } else if (p_config->active_channel_idx >= SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "error: invalid active_channel_idxs"); + return -EINVAL; + } else { + return 0; + } +} + +static inline void igo_nr_set_chan_process(struct comp_data *cd, int32_t chan) +{ + if (!cd->process_enable[chan]) + cd->process_enable[chan] = true; +} + +static inline void igo_nr_set_chan_passthrough(struct comp_data *cd, int32_t chan) +{ + if (cd->process_enable[chan]) { + cd->process_enable[chan] = false; + IgoLibInit(cd->p_handle, &cd->igo_lib_config, &cd->config.igo_params); + } +} + +static int igo_nr_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct comp_dev *dev = mod->dev; + +#if CONFIG_IPC_MAJOR_3 + struct comp_data *cd = module_get_private_data(mod); + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + int j; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "SOF_CTRL_CMD_BINARY"); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); + case SOF_CTRL_CMD_SWITCH: + for (j = 0; j < cdata->num_elems; j++) { + cdata->chanv[j].channel = j; + cdata->chanv[j].value = cd->process_enable[j]; + comp_info(dev, "channel = %u, value = %u", + cdata->chanv[j].channel, + cdata->chanv[j].value); + } + return 0; + default: + comp_err(dev, "igo_nr_cmd_get_config() error: invalid cdata->cmd %d", cdata->cmd); + return -EINVAL; + } + +#elif CONFIG_IPC_MAJOR_4 + comp_err(dev, "igo_nr_cmd_get_config() error: not supported"); + return -EINVAL; +#endif +} + +static int32_t igo_nr_set_chan(struct processing_module *mod, void *data) +{ +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = data; +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *cdata = data; +#endif + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint32_t val; + int32_t ch; + int32_t j; + + for (j = 0; j < cdata->num_elems; j++) { + ch = cdata->chanv[j].channel; + val = cdata->chanv[j].value; + comp_info(dev, "igo_nr_cmd_set_value(), channel = %d, value = %u", ch, val); + if (ch < 0 || ch >= SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "igo_nr_cmd_set_value(), illegal channel = %d", ch); + return -EINVAL; + } + + if (val) + igo_nr_set_chan_process(cd, ch); + else + igo_nr_set_chan_passthrough(cd, ch); + } + + return 0; +} + +static int igo_nr_set_config(struct processing_module *mod, uint32_t param_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_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + comp_info(dev, "entry"); + +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "igo_nr_cmd_set_config(), SOF_CTRL_CMD_BINARY"); + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); + if (ret >= 0) + ret = igo_nr_check_config_validity(dev, cd); + + return ret; + case SOF_CTRL_CMD_SWITCH: + comp_dbg(dev, "igo_nr_cmd_set_config(), SOF_CTRL_CMD_SWITCH, cdata->comp_id = %u", + cdata->comp_id); + return igo_nr_set_chan(mod, cdata); + + default: + comp_err(dev, "igo_nr_cmd_set_config() error: invalid cdata->cmd"); + return -EINVAL; + } +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + comp_info(dev, "igo_nr_cmd_set_config(), SOF_IPC4_SWITCH_CONTROL_PARAM_ID"); + return igo_nr_set_chan(mod, ctl); + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "illegal control."); + return -EINVAL; + } + + comp_info(dev, "igo_nr_cmd_set_config(), bytes"); + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, fragment_size); + if (ret >= 0) + ret = igo_nr_check_config_validity(dev, cd); + + return ret; +#endif +} + +static void igo_nr_print_config(struct processing_module *mod) +{ + struct comp_data __maybe_unused *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, " igo_params_ver %d", + cd->config.igo_params.igo_params_ver); + comp_dbg(dev, " dump_data %d", + cd->config.igo_params.dump_data); + comp_dbg(dev, " nr_bypass %d", + cd->config.igo_params.nr_bypass); + comp_dbg(dev, " nr_mode1_en %d", + cd->config.igo_params.nr_mode1_en); + comp_dbg(dev, " nr_mode3_en %d", + cd->config.igo_params.nr_mode3_en); + comp_dbg(dev, " nr_ul_enable %d", + cd->config.igo_params.nr_ul_enable); + comp_dbg(dev, " agc_gain %d", + cd->config.igo_params.agc_gain); + comp_dbg(dev, " nr_voice_str %d", + cd->config.igo_params.nr_voice_str); + comp_dbg(dev, " nr_level %d", + cd->config.igo_params.nr_level); + comp_dbg(dev, " nr_mode1_floor %d", + cd->config.igo_params.nr_mode1_floor); + comp_dbg(dev, " nr_mode1_od %d", + cd->config.igo_params.nr_mode1_od); + comp_dbg(dev, " nr_mode1_pp_param7 %d", + cd->config.igo_params.nr_mode1_pp_param7); + comp_dbg(dev, " nr_mode1_pp_param8 %d", + cd->config.igo_params.nr_mode1_pp_param8); + comp_dbg(dev, " nr_mode1_pp_param10 %d", + cd->config.igo_params.nr_mode1_pp_param10); + comp_dbg(dev, " nr_mode3_floor %d", + cd->config.igo_params.nr_mode3_floor); + comp_dbg(dev, " nr_mode1_pp_param53 %d", + cd->config.igo_params.nr_mode1_pp_param53); + comp_dbg(dev, " active_channel_idx %d", + cd->config.active_channel_idx); + +} + +static void igo_nr_set_igo_params(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_igo_nr_config *p_config = comp_get_data_blob(cd->model_handler, NULL, NULL); + struct comp_dev *dev = mod->dev; + + comp_info(dev, "entry"); + igo_nr_check_config_validity(dev, cd); + + if (p_config) { + comp_info(dev, "New config detected."); + cd->config = *p_config; + igo_nr_print_config(mod); + } +} + +/* copy and process stream data from source to sink buffers */ +static int igo_nr_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + struct sof_source *source = sources[0]; + struct sof_sink *sink = sinks[0]; + int ret; + + comp_dbg(dev, "igo_nr_copy()"); + + /* Process only when frames count is enough. */ + if (source_get_data_frames_available(source) < IGO_FRAME_SIZE || + sink_get_free_frames(sink) < IGO_FRAME_SIZE) { + comp_warn(dev, "No data to process."); + return 0; + } + + /* Check for changed configuration */ + if (comp_is_new_data_blob_available(cd->model_handler)) + igo_nr_set_igo_params(mod); + + ret = cd->igo_nr_func(cd, source, sink, IGO_FRAME_SIZE); + if (ret) + comp_err(dev, "Failed process."); + + return ret; +} + +static void igo_nr_lib_init(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + cd->igo_lib_config.algo_name = "igo_nr"; + cd->igo_lib_config.in_ch_num = 1; + cd->igo_lib_config.ref_ch_num = 0; + cd->igo_lib_config.out_ch_num = 1; + IgoLibInit(cd->p_handle, &cd->igo_lib_config, &cd->config.igo_params); + + cd->igo_stream_data_in.data = cd->in; + cd->igo_stream_data_in.data_width = IGO_DATA_16BIT; + cd->igo_stream_data_in.sample_num = IGO_FRAME_SIZE; + cd->igo_stream_data_in.sampling_rate = 48000; + + cd->igo_stream_data_ref.data = NULL; + cd->igo_stream_data_ref.data_width = 0; + cd->igo_stream_data_ref.sample_num = 0; + cd->igo_stream_data_ref.sampling_rate = 0; + + cd->igo_stream_data_out.data = cd->out; + cd->igo_stream_data_out.data_width = IGO_DATA_16BIT; + cd->igo_stream_data_out.sample_num = IGO_FRAME_SIZE; + cd->igo_stream_data_out.sampling_rate = 48000; +} + +#if CONFIG_IPC_MAJOR_4 +static int igo_nr_ipc4_params(struct processing_module *mod, struct sof_source *source, + struct sof_sink *sink) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + int ret; + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + ret = source_set_params(source, params, true); + if (ret) + return ret; + + return sink_set_params(sink, params, true); +} +#endif /* CONFIG_IPC_MAJOR_4 */ + +static int32_t igo_nr_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + struct sof_source *source = sources[0]; + struct sof_sink *sink = sinks[0]; + int ret; + + comp_dbg(dev, "entry"); + + if (!source || !sink) { + comp_err(dev, "no source or sink"); + return -ENOTCONN; + } + +#if CONFIG_IPC_MAJOR_4 + ret = igo_nr_ipc4_params(mod, source, sink); + if (ret) { + comp_err(dev, "Failed to set source or and sink parameters."); + return ret; + } +#endif + + ret = igo_nr_check_params(mod, source, sink); + if (ret) + return ret; + + source_set_alignment_constants(source, SOF_FRAME_BYTE_ALIGN, IGO_FRAME_SIZE); + + igo_nr_set_igo_params(mod); + + igo_nr_lib_init(mod); + + comp_dbg(dev, "post igo_nr_lib_init"); + igo_nr_print_config(mod); + + /* Clear in/out buffers */ + memset(cd->in, 0, IGO_NR_IN_BUF_LENGTH * sizeof(int16_t)); + memset(cd->out, 0, IGO_NR_OUT_BUF_LENGTH * sizeof(int16_t)); + + /* Default NR on + * + * Note: There is a race condition with this switch control set and kernel set + * ALSA switch control if such is defined in topology. This set overrides kernel + * SOF driver set for control since it happens just after component init. The + * user needs to re-apply the control to get expected operation. The owner of + * this component should check if this is desired operation. A possible fix would + * be set here only if kernel has not applied the switch control. + */ + cd->process_enable[cd->config.active_channel_idx] = true; + + return set_capture_func(mod, source); +} + +static int igo_nr_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + cd->igo_nr_func = NULL; + + cd->source_rate = 0; + cd->sink_rate = 0; + cd->invalid_param = false; + + return 0; +} + +static const struct module_interface igo_nr_interface = { + .init = igo_nr_init, + .prepare = igo_nr_prepare, + .process = igo_nr_process, + .set_configuration = igo_nr_set_config, + .get_configuration = igo_nr_get_config, + .reset = igo_nr_reset, + .free = igo_nr_free +}; + +#if CONFIG_COMP_IGO_NR_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("IGO_NR", &igo_nr_interface, 1, SOF_REG_UUID(igo_nr), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(igo_nr_tr, SOF_UUID(igo_nr_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(igo_nr_interface, igo_nr_uuid, igo_nr_tr); +SOF_MODULE_INIT(igo_nr, sys_comp_module_igo_nr_interface_init); + +#endif diff --git a/src/audio/igo_nr/igo_nr.toml b/src/audio/igo_nr/igo_nr.toml new file mode 100644 index 000000000000..723066425f83 --- /dev/null +++ b/src/audio/igo_nr/igo_nr.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # IGO_NR module config + [[module.entry]] + name = "IGO_NR" + uuid = UUIDREG_STR_IGO_NR + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/igo_nr/igo_nr_stub.c b/src/audio/igo_nr/igo_nr_stub.c new file mode 100644 index 000000000000..ae027f6ef7f4 --- /dev/null +++ b/src/audio/igo_nr/igo_nr_stub.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Google LLC. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org> + +#include <sof/audio/igo_nr/igo_nr_comp.h> + +/* Set handle_size to Just something instead of 0 from rzalloc() of + * component data to avoid rballoc() in igo_nr_init() to fail. + */ +#define IGO_NR_STUB_HANDLE_SIZE 42 + +enum IgoRet IgoLibGetInfo(struct IgoLibInfo *info) +{ + info->handle_size = IGO_NR_STUB_HANDLE_SIZE; + + return IGO_RET_OK; +} + +enum IgoRet IgoLibInit(void *handle, + const struct IgoLibConfig *config, + void *param) +{ + return IGO_RET_OK; +} + +enum IgoRet IgoLibProcess(void *handle, + const struct IgoStreamData *in, + const struct IgoStreamData *ref, + const struct IgoStreamData *out) +{ + return IGO_RET_OK; +} diff --git a/src/audio/igo_nr/llext/CMakeLists.txt b/src/audio/igo_nr/llext/CMakeLists.txt new file mode 100644 index 000000000000..2e974cae7945 --- /dev/null +++ b/src/audio/igo_nr/llext/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_DTS_CODEC_STUB) +sof_llext_build("igo_nr" + SOURCES ../igo_nr.c + ../igo_nr_stub.c +) +target_include_directories(igo_nr_llext_lib PRIVATE + "../../../../third_party/include" +) +else() +message(FATAL_ERROR "Add library linking support in src/audio/codec/igo_nr/llext/CMakeLists.txt") +endif() diff --git a/src/audio/igo_nr/llext/llext.toml.h b/src/audio/igo_nr/llext/llext.toml.h new file mode 100644 index 000000000000..b7a3322dc906 --- /dev/null +++ b/src/audio/igo_nr/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../igo_nr.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/kpb.c b/src/audio/kpb.c index 34ea8f066d35..9dca05630da1 100644 --- a/src/audio/kpb.c +++ b/src/audio/kpb.c @@ -18,14 +18,15 @@ #include <sof/audio/component_ext.h> #include <sof/audio/pipeline.h> #include <sof/audio/kpb.h> +#include <sof/audio/ipc-config.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ #include <sof/lib/pm_runtime.h> #include <sof/lib/uuid.h> #include <sof/list.h> @@ -33,145 +34,486 @@ #include <sof/platform.h> #include <sof/schedule/edf_schedule.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/string.h> +#include <rtos/task.h> +#include <rtos/string.h> #include <sof/ut.h> #include <ipc/topology.h> +#include <ipc4/module.h> +#include <ipc4/kpb.h> #include <user/kpb.h> #include <user/trace.h> #include <errno.h> +#include <limits.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> +#if CONFIG_AMS +#include <sof/lib/ams.h> +#include <sof/lib/ams_msg.h> +#include <ipc4/ams_helpers.h> +#else +#include <sof/lib/notifier.h> +#endif + +#ifdef KPB_HIFI3 +#include <xtensa/tie/xt_hifi3.h> +#endif static const struct comp_driver comp_kpb; -/* d8218443-5ff3-4a4c-b388-6cfe07b9562e */ -DECLARE_SOF_UUID("kpb", kpb_uuid, 0xd8218443, 0x5ff3, 0x4a4c, - 0xb3, 0x88, 0x6c, 0xfe, 0x07, 0xb9, 0x56, 0x2e); +LOG_MODULE_REGISTER(kpb, CONFIG_SOF_LOG_LEVEL); +#if CONFIG_IPC_MAJOR_4 +SOF_DEFINE_REG_UUID(kpb4); +#define KPB_UUID kpb4_uuid +#else +SOF_DEFINE_REG_UUID(kpb); +#define KPB_UUID kpb_uuid +#endif -/* e50057a5-8b27-4db4-bd79-9a639cee5f50 */ -DECLARE_SOF_UUID("kpb-task", kpb_task_uuid, 0xe50057a5, 0x8b27, 0x4db4, - 0xbd, 0x79, 0x9a, 0x63, 0x9c, 0xee, 0x5f, 0x50); +SOF_DEFINE_REG_UUID(kpb_task); /* KPB private data, runtime data */ struct comp_data { - uint64_t state_log; /**< keeps record of KPB recent states */ enum kpb_state state; /**< current state of KPB component */ - uint32_t kpb_no_of_clients; /**< number of registered clients */ - struct kpb_client clients[KPB_MAX_NO_OF_CLIENTS]; + uint32_t state_log; /**< keeps record of KPB recent states */ +#ifndef __ZEPHYR__ + struct k_spinlock lock; /**< locking mechanism for read pointer calculations */ + k_spinlock_key_t key; +#else + struct k_mutex lock; +#endif + struct sof_kpb_config config; /**< component configuration data */ + struct history_data hd; /** data related to history buffer */ struct task draining_task; + struct draining_data draining_task_data; + struct kpb_client clients[KPB_MAX_NO_OF_CLIENTS]; + struct comp_buffer *sel_sink; /**< real time sink (channel selector)*/ + struct comp_buffer *host_sink; /**< draining sink (client) */ + uint32_t kpb_no_of_clients; /**< number of registered clients */ uint32_t source_period_bytes; /**< source number of period bytes */ uint32_t sink_period_bytes; /**< sink number of period bytes */ - struct sof_kpb_config config; /**< component configuration data */ - struct comp_buffer *sel_sink; /**< real time sink (channel selector )*/ - struct comp_buffer *host_sink; /**< draining sink (client) */ - struct hb *history_buffer; /**< internal history buffer */ - size_t buffered_data; /**< keeps info about amount of buffered data */ - struct dd draining_task_data; - size_t buffer_size; /**< size of internal history buffer */ size_t host_buffer_size; /**< size of host buffer */ size_t host_period_size; /**< size of history period */ bool sync_draining_mode; /**< should we synchronize draining with * host? */ - spinlock_t lock; /**< locking mechanism for read pointer calculations */ + enum comp_copy_type force_copy_type; /**< should we force copy_type on kpb sink? */ +#ifdef CONFIG_IPC_MAJOR_4 + struct ipc4_kpb_module_cfg ipc4_cfg; +#endif /* CONFIG_IPC_MAJOR_4 */ + uint32_t num_of_sel_mic; + uint32_t num_of_in_channels; + uint32_t offsets[KPB_MAX_MICSEL_CHANNELS]; + struct kpb_micselector_config mic_sel; + struct kpb_fmt_dev_list fmt_device_list; + struct fast_mode_task fmt; + +#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, const struct comp_buffer *source, size_t size); static size_t kpb_allocate_history_buffer(struct comp_data *kpb, size_t hb_size_req); -static void kpb_clear_history_buffer(struct hb *buff); -static void kpb_free_history_buffer(struct hb *buff); +static void kpb_clear_history_buffer(struct history_buffer *buff); +static void kpb_free_history_buffer(struct history_buffer *buff); static inline bool kpb_is_sample_width_supported(uint32_t sampling_width); static void kpb_copy_samples(struct comp_buffer *sink, struct comp_buffer *source, size_t size, - size_t sample_width); + size_t sample_width, uint32_t channels); static void kpb_drain_samples(void *source, struct audio_stream *sink, size_t size, size_t sample_width); static void kpb_buffer_samples(const struct audio_stream *source, - uint32_t start, void *sink, size_t size, + int offset, void *sink, size_t size, size_t sample_width); -static void kpb_reset_history_buffer(struct hb *buff); +static void kpb_reset_history_buffer(struct history_buffer *buff); static inline bool validate_host_params(struct comp_dev *dev, size_t host_period_size, size_t host_buffer_size, size_t hb_size_req); static inline void kpb_change_state(struct comp_data *kpb, enum kpb_state state); +#ifdef CONFIG_IPC_MAJOR_4 +/* KpbFastModeTaskModulesList Namespace */ +static inline int alloc_fmt_module_list_item(struct kpb_fmt_dev_list *fmt_device_list, + struct comp_dev *mi_ptr, struct comp_dev ***item); +static int clear_fmt_modules_list(struct kpb_fmt_dev_list *fmt_device_list, + uint32_t outpin_idx); +static int prepare_fmt_modules_list(struct comp_dev *kpb_dev, uint32_t outpin_idx, + const struct kpb_task_params *modules_to_prepare); +/* FMT Namespace */ +static int register_modules_list(struct fast_mode_task *fmt, + struct device_list *new_list, size_t list_idx); +static int unregister_modules_list(struct fast_mode_task *fmt, + struct device_list *list_to_remove, size_t list_idx); +/* Devicelist */ +static int devicelist_push(struct device_list *devlist, struct comp_dev **dev); +static void devicelist_reset(struct device_list *devlist, bool remove_items); +#endif static uint64_t kpb_task_deadline(void *data) { +#ifndef __ZEPHYR__ return SOF_TASK_DEADLINE_ALMOST_IDLE; +#else + struct draining_data *dd = (struct draining_data *)data; + uint64_t now; + + if (dd->next_copy_time == 0) + return 0; /* run immediately */ + + now = sof_cycle_get_64(); + return dd->next_copy_time > now ? + k_uptime_ticks() + k_cyc_to_ticks_near64(dd->next_copy_time - now) : 0; +#endif +} + +#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, "entry"); + + kpb_init_draining(dev, cli_data); +} + +#endif /* CONFIG_AMS */ + +#ifdef __ZEPHYR__ + +static void kpb_lock(struct comp_data *kpb) +{ + k_mutex_lock(&kpb->lock, K_FOREVER); +} + +static void kpb_unlock(struct comp_data *kpb) +{ + k_mutex_unlock(&kpb->lock); +} + +static void kpb_lock_init(struct comp_data *kpb) +{ + k_mutex_init(&kpb->lock); +} + +#else /* __ZEPHYR__ */ + +static void kpb_lock(struct comp_data *kpb) +{ + kpb->key = k_spin_lock(&kpb->lock); +} + +static void kpb_unlock(struct comp_data *kpb) +{ + k_spin_unlock(&kpb->lock, kpb->key); +} + +static void kpb_lock_init(struct comp_data *kpb) +{ + k_spinlock_init(&kpb->lock); +} + +#endif /* __ZEPHYR__ */ + +#if CONFIG_IPC_MAJOR_4 +/** + * \brief Set and verify ipc params. + * \param[in] dev - component device pointer. + * \param[in] ipc_config - ipc config pointer. + * \return: none. + */ +static int kpb_set_verify_ipc_params(struct comp_dev *dev, + const struct ipc4_kpb_module_cfg *ipc_config) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + + kpb->config.channels = ipc_config->base_cfg.audio_fmt.channels_count; + kpb->config.sampling_freq = + ipc_config->base_cfg.audio_fmt.sampling_frequency; + kpb->config.sampling_width = + ipc_config->base_cfg.audio_fmt.valid_bit_depth; + kpb->ipc4_cfg.base_cfg = ipc_config->base_cfg; + + /* Initialize sinks */ + kpb->sel_sink = NULL; + kpb->host_sink = NULL; + + if (!kpb_is_sample_width_supported(kpb->config.sampling_width)) { + comp_err(dev, "requested sampling width not supported"); + return -EINVAL; + } + + if (kpb->config.channels > KPB_MAX_SUPPORTED_CHANNELS) { + comp_err(dev, "no of channels exceeded the limit"); + return -EINVAL; + } + + if (kpb->config.sampling_freq != KPB_SAMPLNG_FREQUENCY) { + comp_err(dev, "requested sampling frequency not supported"); + return -EINVAL; + } + + return 0; +} + +/** + * \brief Set KPB component stream params. + * \param[in] dev - component device pointer. + * \param[in] params - sof ipc stream params pointer. + * \return: none. + */ +static void kpb_set_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + enum sof_ipc_frame frame_fmt, valid_fmt; + + comp_dbg(dev, "entry"); + + memset_s(params, sizeof(*params), 0, sizeof(*params)); + params->channels = kpb->ipc4_cfg.base_cfg.audio_fmt.channels_count; + params->rate = kpb->ipc4_cfg.base_cfg.audio_fmt.sampling_frequency; + params->sample_container_bytes = kpb->ipc4_cfg.base_cfg.audio_fmt.depth / 8; + params->sample_valid_bytes = + kpb->ipc4_cfg.base_cfg.audio_fmt.valid_bit_depth / 8; + params->buffer_fmt = kpb->ipc4_cfg.base_cfg.audio_fmt.interleaving_style; + params->buffer.size = kpb->ipc4_cfg.base_cfg.ibs * KPB_MAX_BUFF_TIME * params->channels; + + params->host_period_bytes = params->channels * + params->sample_container_bytes * + (params->rate / 1000); + + audio_stream_fmt_conversion(kpb->ipc4_cfg.base_cfg.audio_fmt.depth, + kpb->ipc4_cfg.base_cfg.audio_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + kpb->ipc4_cfg.base_cfg.audio_fmt.s_type); + + params->frame_fmt = valid_fmt; +} + +/** + * \brief Set KPB component stream params. + * \param[in] dev - component device pointer. + * \param[in] type - sof ipc stream params pointer. + * \param[in] value - ipc4 base module config pointer. + * \return: none. + */ +static int kpb_get_attribute(struct comp_dev *dev, + uint32_t type, + void *value) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + + switch (type) { + case COMP_ATTR_BASE_CONFIG: + *(struct ipc4_base_module_cfg *)value = kpb->ipc4_cfg.base_cfg; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * \brief Initialize KPB sinks when binding. + * \param[in] dev - component device pointer. + * \param[in] bind_data - bind/unbind data. + * \return: none. + */ +static int kpb_bind(struct comp_dev *dev, struct bind_info *bind_data) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + struct ipc4_module_bind_unbind *bu; + int buf_id; + int ret = 0; + + comp_dbg(dev, "entry"); + + bu = bind_data->ipc4_data; + buf_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue); + + /* We're assuming here that KPB Real Time sink (kpb->sel_sink) is + * always connected to input pin of Detector pipeline so during IPC4 + * Bind operation both src_queue and dst_queue will have id = 0 + * (Detector/MicSel has one input pin). To properly connect KPB sink + * with Detector source we're looking for buffer with id=0. + */ + struct comp_buffer *sink; + + comp_dev_for_each_consumer(dev, sink) { + int sink_buf_id; + + if (!comp_buffer_get_sink_component(sink)) { + ret = -EINVAL; + break; + } + + sink_buf_id = buf_get_id(sink); + + if (sink_buf_id == buf_id) { + if (sink_buf_id == 0) + kpb->sel_sink = sink; + else + kpb->host_sink = sink; + } + } + + return ret; +} + +/** + * \brief Reset KPB sinks when unbinding. + * \param[in] dev - component device pointer. + * \param[in] data - ipc4 bind/unbind data. + * \return: none. + */ +static int kpb_unbind(struct comp_dev *dev, struct bind_info *unbind_data) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + struct ipc4_module_bind_unbind *bu; + int buf_id; + + comp_dbg(dev, "entry"); + + bu = unbind_data->ipc4_data; + buf_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue); + + /* Reset sinks when unbinding */ + if (buf_id == 0) + kpb->sel_sink = NULL; + else + kpb->host_sink = NULL; + + /* Clear fmt config */ + return clear_fmt_modules_list(&kpb->fmt_device_list, bu->extension.r.src_queue); } +#else /* CONFIG_IPC_MAJOR_4 */ /** + * \brief Set and verify ipc params. + * \param[in] dev - component device pointer. + * \param[in] ipc_config - ipc config pointer type. + * \return: none. + */ +static int kpb_set_verify_ipc_params(struct comp_dev *dev, + const struct ipc_config_process *ipc_config) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + int ret; + + ret = memcpy_s(&kpb->config, sizeof(kpb->config), ipc_config->data, + ipc_config->size); + + if (ret) { + comp_err(dev, "cannot memcpy_s %d bytes into sof_kpb_config (%zu)\n", + ipc_config->size, sizeof(kpb->config)); + return -EINVAL; + } + + /* Initialize sinks */ + kpb->sel_sink = NULL; + kpb->host_sink = NULL; + + if (!kpb_is_sample_width_supported(kpb->config.sampling_width)) { + comp_err(dev, "requested sampling width not supported"); + return -EINVAL; + } + + if (kpb->config.channels > KPB_MAX_SUPPORTED_CHANNELS) { + comp_err(dev, "no of channels exceeded the limit"); + return -EINVAL; + } + + if (kpb->config.sampling_freq != KPB_SAMPLNG_FREQUENCY) { + comp_err(dev, "requested sampling frequency not supported"); + return -EINVAL; + } + + return 0; +} + +static void kpb_set_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{} +#endif /* CONFIG_IPC_MAJOR_4 */ + +static int kpb_params(struct comp_dev *dev, struct sof_ipc_stream_params *params); + +/* * \brief Create a key phrase buffer component. - * \param[in] comp - generic ipc component pointer. + * \param[in] config - generic ipc component pointer. * * \return: a pointer to newly created KPB component. */ static struct comp_dev *kpb_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) + const struct comp_ipc_config *config, + const void *spec) { - struct sof_ipc_comp_process *ipc_process = - (struct sof_ipc_comp_process *)comp; +#if CONFIG_IPC_MAJOR_4 + const struct ipc4_kpb_module_cfg *ipc_process = spec; + size_t ipc_config_size = sizeof(*ipc_process); + size_t kpb_config_size = sizeof(struct ipc4_kpb_module_cfg); +#else + const struct ipc_config_process *ipc_process = spec; + size_t ipc_config_size = ipc_process->size; + size_t kpb_config_size = sizeof(struct sof_kpb_config); +#endif struct task_ops ops = { .run = kpb_draining_task, .get_deadline = kpb_task_deadline, }; - size_t bs = ipc_process->size; + struct comp_dev *dev; struct comp_data *kpb; int ret; comp_cl_info(&comp_kpb, "kpb_new()"); - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_process)); - if (!dev) + /* make sure data size is not bigger than config space */ + if (ipc_config_size > kpb_config_size) { + comp_cl_err(&comp_kpb, "ipc config size %zu too big", + ipc_config_size); return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_process); + } - ret = memcpy_s(COMP_GET_IPC(dev, sof_ipc_comp_process), - sizeof(struct sof_ipc_comp_process), - comp, sizeof(struct sof_ipc_comp_process)); - assert(!ret); + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; - kpb = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*kpb)); + kpb = rzalloc(SOF_MEM_FLAG_USER, sizeof(*kpb)); if (!kpb) { - rfree(dev); + comp_free_device(dev); return NULL; } comp_set_drvdata(dev, kpb); - ret = memcpy_s(&kpb->config, sizeof(kpb->config), ipc_process->data, - bs); - assert(!ret); - - if (!kpb_is_sample_width_supported(kpb->config.sampling_width)) { - comp_err(dev, "kpb_new() error: requested sampling width not supported"); - return NULL; - } - - if (kpb->config.channels > KPB_MAX_SUPPORTED_CHANNELS) { - comp_err(dev, "kpb_new() error: no of channels exceeded the limit"); + ret = kpb_set_verify_ipc_params(dev, ipc_process); + if (ret) { + comp_free_device(dev); return NULL; } - if (kpb->config.sampling_freq != KPB_SAMPLNG_FREQUENCY) { - comp_err(dev, "kpb_new() error: requested sampling frequency not supported"); - return NULL; - } + kpb_lock_init(kpb); /* Initialize draining task */ schedule_task_init_edf(&kpb->draining_task, /* task structure */ @@ -182,14 +524,31 @@ static struct comp_dev *kpb_new(const struct comp_driver *drv, 0); /* no flags */ /* Init basic component data */ - kpb->history_buffer = NULL; + kpb->hd.c_hb = NULL; kpb->kpb_no_of_clients = 0; kpb->state_log = 0; +#ifdef CONFIG_KPB_FORCE_COPY_TYPE_NORMAL + kpb->force_copy_type = COMP_COPY_NORMAL; +#else + kpb->force_copy_type = COMP_COPY_INVALID; /* do not change kpb sink copy type */ +#endif + /* Kpb has been created successfully */ dev->state = COMP_STATE_READY; kpb_change_state(kpb, KPB_STATE_CREATED); +#if CONFIG_IPC_MAJOR_4 + struct sof_ipc_stream_params params; + + /* retrieve params from the base config for IPC4 */ + ret = kpb_params(dev, ¶ms); + if (ret < 0) { + comp_free_device(dev); + return NULL; + } +#endif + return dev; } @@ -202,30 +561,29 @@ static struct comp_dev *kpb_new(const struct comp_driver *drv, static size_t kpb_allocate_history_buffer(struct comp_data *kpb, size_t hb_size_req) { - struct hb *history_buffer; - struct hb *new_hb = NULL; + struct history_buffer *hb; + struct history_buffer *new_hb = NULL; /*! Total allocation size */ size_t hb_size = hb_size_req; /*! Current allocation size */ size_t ca_size = hb_size; /*! Memory caps priorites for history buffer */ - int hb_mcp[KPB_NO_OF_MEM_POOLS] = {SOF_MEM_CAPS_LP, SOF_MEM_CAPS_HP, - SOF_MEM_CAPS_RAM }; + int hb_mcp[KPB_NO_OF_MEM_POOLS] = {SOF_MEM_FLAG_USER | SOF_MEM_FLAG_LOW_POWER, SOF_MEM_FLAG_USER}; void *new_mem_block = NULL; size_t temp_ca_size; int i = 0; size_t allocated_size = 0; - comp_cl_info(&comp_kpb, "kpb_allocate_history_buffer()"); + comp_cl_info(&comp_kpb, "entry"); /* Initialize history buffer */ - kpb->history_buffer = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(struct hb)); - if (!kpb->history_buffer) + kpb->hd.c_hb = rzalloc(SOF_MEM_FLAG_USER, + sizeof(struct history_buffer)); + if (!kpb->hd.c_hb) return 0; - kpb->history_buffer->next = kpb->history_buffer; - kpb->history_buffer->prev = kpb->history_buffer; - history_buffer = kpb->history_buffer; + kpb->hd.c_hb->next = kpb->hd.c_hb; + kpb->hd.c_hb->prev = kpb->hd.c_hb; + hb = kpb->hd.c_hb; /* Allocate history buffer/s. KPB history buffer has a size of * KPB_MAX_BUFFER_SIZE, since there is no single memory block @@ -236,39 +594,38 @@ static size_t kpb_allocate_history_buffer(struct comp_data *kpb, /* Try to allocate ca_size (current allocation size). At first * attempt it will be equal to hb_size (history buffer size). */ - new_mem_block = rballoc(0, hb_mcp[i], ca_size); + new_mem_block = rballoc(hb_mcp[i], ca_size); if (new_mem_block) { /* We managed to allocate a block of ca_size. * Now we initialize it. */ - comp_cl_info(&comp_kpb, "kpb new memory block: %d", + comp_cl_info(&comp_kpb, "kpb new memory block: %zu", ca_size); allocated_size += ca_size; - history_buffer->start_addr = new_mem_block; - history_buffer->end_addr = (char *)new_mem_block + + hb->start_addr = new_mem_block; + hb->end_addr = (char *)new_mem_block + ca_size; - history_buffer->w_ptr = new_mem_block; - history_buffer->r_ptr = new_mem_block; - history_buffer->state = KPB_BUFFER_FREE; + hb->w_ptr = new_mem_block; + hb->r_ptr = new_mem_block; + hb->state = KPB_BUFFER_FREE; hb_size -= ca_size; - history_buffer->next = kpb->history_buffer; + hb->next = kpb->hd.c_hb; /* Do we need another buffer? */ if (hb_size > 0) { /* Yes, we still need at least one more buffer. * Let's first create new container for it. */ - new_hb = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, - SOF_MEM_CAPS_RAM, - sizeof(struct hb)); + new_hb = rzalloc(SOF_MEM_FLAG_USER, + sizeof(struct history_buffer)); if (!new_hb) return 0; - history_buffer->next = new_hb; - new_hb->next = kpb->history_buffer; + hb->next = new_hb; + new_hb->next = kpb->hd.c_hb; new_hb->state = KPB_BUFFER_OFF; - new_hb->prev = history_buffer; - history_buffer = new_hb; - kpb->history_buffer->prev = new_hb; + new_hb->prev = hb; + hb = new_hb; + kpb->hd.c_hb->prev = new_hb; ca_size = hb_size; i++; } @@ -291,7 +648,7 @@ static size_t kpb_allocate_history_buffer(struct comp_data *kpb, } } - comp_cl_info(&comp_kpb, "kpb_allocate_history_buffer(): allocated %d bytes", + comp_cl_info(&comp_kpb, "allocated %zu bytes for history buffer", allocated_size); return allocated_size; @@ -303,12 +660,12 @@ static size_t kpb_allocate_history_buffer(struct comp_data *kpb, * * \return none. */ -static void kpb_free_history_buffer(struct hb *buff) +static void kpb_free_history_buffer(struct history_buffer *buff) { - struct hb *_buff; - struct hb *first_buff = buff; + struct history_buffer *_buff; + struct history_buffer *first_buff = buff; - comp_cl_info(&comp_kpb, "kpb_free_history_buffer()"); + comp_cl_info(&comp_kpb, "entry"); if (!buff) return; @@ -335,15 +692,25 @@ static void kpb_free(struct comp_dev *dev) { struct comp_data *kpb = comp_get_drvdata(dev); - comp_info(dev, "kpb_free()"); + comp_info(dev, "entry"); + +#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, "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->history_buffer); - kpb->history_buffer = NULL; - kpb->buffer_size = 0; + kpb_free_history_buffer(kpb->hd.c_hb); + kpb->hd.c_hb = NULL; + kpb->hd.buffer_size = 0; /* remove scheduling */ schedule_task_free(&kpb->draining_task); @@ -353,7 +720,7 @@ static void kpb_free(struct comp_dev *dev) /* Free KPB */ rfree(kpb); - rfree(dev); + comp_free_device(dev); } /** @@ -364,21 +731,21 @@ static void kpb_free(struct comp_dev *dev) */ static int kpb_trigger(struct comp_dev *dev, int cmd) { - comp_info(dev, "kpb_trigger()"); + comp_info(dev, "entry"); return comp_set_state(dev, cmd); } -static int kbp_verify_params(struct comp_dev *dev, +static int kpb_verify_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { int ret; - comp_dbg(dev, "kbp_verify_params()"); + comp_dbg(dev, "entry"); ret = comp_verify_params(dev, 0, params); if (ret < 0) { - comp_err(dev, "kpb_verify_params() error: comp_verify_params() failed"); + comp_err(dev, "comp_verify_params() failed"); return ret; } @@ -398,13 +765,15 @@ static int kpb_params(struct comp_dev *dev, int err; if (dev->state == COMP_STATE_PREPARE) { - comp_err(dev, "kpb_params(): kpb has been already configured."); + comp_err(dev, "kpb has been already configured."); return PPL_STATUS_PATH_STOP; } - err = kbp_verify_params(dev, params); + kpb_set_params(dev, params); + + err = kpb_verify_params(dev, params); if (err < 0) { - comp_err(dev, "kpb_params(): pcm params verification failed"); + comp_err(dev, "pcm params verification failed"); return -EINVAL; } @@ -412,6 +781,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; } @@ -426,17 +799,25 @@ static int kpb_params(struct comp_dev *dev, static int kpb_prepare(struct comp_dev *dev) { struct comp_data *kpb = comp_get_drvdata(dev); + struct sof_ipc_stream_params params; int ret = 0; int i; - struct list_item *blist; - struct comp_buffer *sink; - size_t hb_size_req = KPB_MAX_BUFFER_SIZE(kpb->config.sampling_width); + size_t hb_size_req = KPB_MAX_BUFFER_SIZE(kpb->config.sampling_width, kpb->config.channels); + + comp_dbg(dev, "entry"); - comp_info(dev, "kpb_prepare()"); + /* retrieve the params from the base_cfg and update the source/sink buffer params */ + kpb_set_params(dev, ¶ms); + + ret = kpb_verify_params(dev, ¶ms); + if (ret < 0) { + comp_err(dev, "pcm params verification failed"); + return -EINVAL; + } if (kpb->state == KPB_STATE_RESETTING || kpb->state == KPB_STATE_RESET_FINISHING) { - comp_cl_err(&comp_kpb, "kpb_prepare() error: can not prepare KPB due to ongoing reset, state log %x", + comp_cl_err(&comp_kpb, "can not prepare KPB due to ongoing reset, state log %x", kpb->state_log); return -EBUSY; } @@ -450,7 +831,6 @@ static int kpb_prepare(struct comp_dev *dev) if (!validate_host_params(dev, kpb->host_period_size, kpb->host_buffer_size, hb_size_req)) { - comp_cl_err(&comp_kpb, "kpb_prepare() error: wrong host params."); return -EINVAL; } @@ -458,32 +838,31 @@ static int kpb_prepare(struct comp_dev *dev) /* Init private data */ kpb->kpb_no_of_clients = 0; - kpb->buffered_data = 0; - kpb->sel_sink = NULL; - kpb->host_sink = NULL; + kpb->hd.buffered = 0; - if (kpb->history_buffer && kpb->buffer_size < hb_size_req) { + if (kpb->hd.c_hb && kpb->hd.buffer_size < hb_size_req) { /* Host params has changed, we need to allocate new buffer */ - kpb_free_history_buffer(kpb->history_buffer); - kpb->history_buffer = NULL; + kpb_free_history_buffer(kpb->hd.c_hb); + kpb->hd.c_hb = NULL; } - if (!kpb->history_buffer) { + if (!kpb->hd.c_hb) { /* Allocate history buffer */ - kpb->buffer_size = kpb_allocate_history_buffer(kpb, - hb_size_req); + kpb->hd.buffer_size = kpb_allocate_history_buffer(kpb, + hb_size_req); /* Have we allocated what we requested? */ - if (kpb->buffer_size < hb_size_req) { - comp_cl_err(&comp_kpb, "kpb_prepare() error: failed to allocate space for KPB buffer"); - kpb_free_history_buffer(kpb->history_buffer); - kpb->history_buffer = NULL; - kpb->buffer_size = 0; + if (kpb->hd.buffer_size < hb_size_req) { + comp_cl_err(&comp_kpb, "failed to allocate space for KPB buffer"); + kpb_free_history_buffer(kpb->hd.c_hb); + kpb->hd.c_hb = NULL; + kpb->hd.buffer_size = 0; return -EINVAL; } } /* Init history buffer */ - kpb_reset_history_buffer(kpb->history_buffer); + kpb_reset_history_buffer(kpb->hd.c_hb); + kpb->hd.free = kpb->hd.buffer_size; /* Initialize clients data */ for (i = 0; i < KPB_MAX_NO_OF_CLIENTS; i++) { @@ -491,49 +870,86 @@ 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); + kpb_event_handler, 0); +#endif /* CONFIG_AMS */ + if (ret < 0) { - kpb_free_history_buffer(kpb->history_buffer); - kpb->history_buffer = NULL; + kpb_free_history_buffer(kpb->hd.c_hb); + kpb->hd.c_hb = NULL; return -ENOMEM; } +#ifndef CONFIG_IPC_MAJOR_4 /* Search for KPB related sinks. * NOTE! We assume here that channel selector component device * is connected to the KPB sinks as well as host device. */ - list_for_item(blist, &dev->bsink_list) { - sink = container_of(blist, struct comp_buffer, source_list); + struct comp_buffer *sink; - if (!sink->sink) { + comp_dev_for_each_consumer(dev, sink) { + enum sof_comp_type type; + + if (!comp_buffer_get_sink_component(sink)) { ret = -EINVAL; break; } - if (dev_comp_type(sink->sink) == SOF_COMP_SELECTOR) { + type = dev_comp_type(comp_buffer_get_sink_component(sink)); + + switch (type) { + case SOF_COMP_SELECTOR: /* We found proper real time sink */ kpb->sel_sink = sink; - } else if (dev_comp_type(sink->sink) == SOF_COMP_HOST) { + break; + case SOF_COMP_HOST: /* We found proper host sink */ kpb->host_sink = sink; + break; + default: + break; + } + } +#else + /* Update number of sel_sink channels. + * If OBS is not equal to IBS it means that KPB will work in micselector mode. + */ + if (kpb->ipc4_cfg.base_cfg.ibs != kpb->ipc4_cfg.base_cfg.obs) { + uint32_t sink_id; + + struct comp_buffer *sink; + + comp_dev_for_each_consumer(dev, sink) { + sink_id = buf_get_id(sink); + + if (sink_id == 0) + audio_stream_set_channels(&sink->stream, kpb->num_of_sel_mic); + else + audio_stream_set_channels(&sink->stream, kpb->config.channels); } } +#endif /* CONFIG_IPC_MAJOR_4 */ - if (!kpb->sel_sink || !kpb->host_sink) { - comp_info(dev, "kpb_prepare() error: could not find sinks: sel_sink %d host_sink %d", - (uint32_t)kpb->sel_sink, (uint32_t)kpb->host_sink); + if (!kpb->sel_sink) { + comp_err(dev, "could not find sink: sel_sink %p", + kpb->sel_sink); ret = -EIO; } - /* Disallow sync_draining_mode for now */ - kpb->sync_draining_mode = false; + kpb->sync_draining_mode = true; kpb_change_state(kpb, KPB_STATE_RUN); return ret; } +#if CONFIG_IPC_MAJOR_3 /** * \brief Used to pass standard and bespoke commands (with data) to component. * \param[in,out] dev - Volume base component device. @@ -544,10 +960,9 @@ static int kpb_prepare(struct comp_dev *dev) static int kpb_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) { - int ret = 0; - - return ret; + return 0; } +#endif /** * \brief Resets KPB component. @@ -558,8 +973,9 @@ static int kpb_reset(struct comp_dev *dev) { struct comp_data *kpb = comp_get_drvdata(dev); int ret = 0; + int i; - comp_cl_info(&comp_kpb, "kpb_reset(): resetting from state %d, state log %x", + comp_cl_info(&comp_kpb, "resetting from state %d, state log %x", kpb->state, kpb->state_log); switch (kpb->state) { @@ -577,17 +993,28 @@ static int kpb_reset(struct comp_dev *dev) ret = comp_set_state(dev, COMP_TRIGGER_RESET); break; default: - kpb->buffered_data = 0; + kpb->hd.buffered = 0; + kpb->sel_sink = NULL; + kpb->host_sink = NULL; + kpb->host_buffer_size = 0; + kpb->host_period_size = 0; + + for (i = 0; i < KPB_MAX_NO_OF_CLIENTS; i++) { + kpb->clients[i].state = KPB_CLIENT_UNREGISTERED; + kpb->clients[i].r_ptr = NULL; + } - if (kpb->history_buffer) { + if (kpb->hd.c_hb) { /* Reset history buffer - zero its data, reset pointers * and states. */ - kpb_reset_history_buffer(kpb->history_buffer); + 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); @@ -598,6 +1025,168 @@ static int kpb_reset(struct comp_dev *dev) return ret; } +#ifdef KPB_HIFI3 +#if CONFIG_FORMAT_S16LE +static void kpb_micselect_copy16(struct comp_buffer *sink, + struct comp_buffer *source, size_t size, + uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets) +{ + struct audio_stream *istream = &source->stream; + struct audio_stream *ostream = &sink->stream; + uint16_t ch; + size_t i; + + 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 = 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); + const size_t samples_per_chan = size / (sizeof(uint16_t) * micsel_channels); + ae_int16 *out_ptr; + + for (ch = 0; ch < micsel_channels; ch++) { + const ae_int16 *input_data = (const ae_int16 *)(in_ptr) + offsets[ch]; + + 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); + AE_S16_0_XC(d16, out_ptr, out_offset); + } + } +} +#endif +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +static void kpb_micselect_copy32(struct comp_buffer *sink, + struct comp_buffer *source, size_t size, + uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets) +{ + struct audio_stream *istream = &source->stream; + struct audio_stream *ostream = &sink->stream; + uint16_t ch; + size_t i; + + 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 = 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); + const size_t samples_per_chan = size / (sizeof(uint32_t) * micsel_channels); + ae_int32 *out_ptr; + + for (ch = 0; ch < micsel_channels; ch++) { + const ae_int32 *input_data = (const ae_int32 *)(in_ptr) + offsets[ch]; + + 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); + AE_S32_L_XC(d32, out_ptr, out_offset); + } + } +} +#endif +#else +static void kpb_micselect_copy16(struct comp_buffer *sink, + struct comp_buffer *source, size_t size, + uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets) +{ + struct audio_stream *istream = &source->stream; + struct audio_stream *ostream = &sink->stream; + + buffer_stream_invalidate(source, size); + size_t out_samples; + uint16_t ch; + + const int16_t *in_data; + int16_t *out_data; + const uint32_t samples_per_chan = size / (sizeof(uint16_t) * micsel_channels); + + for (ch = 0; ch < micsel_channels; ch++) { + out_samples = 0; + 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 *)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]]; + out_samples += micsel_channels; + } + } +} + +static void kpb_micselect_copy32(struct comp_buffer *sink, + struct comp_buffer *source, size_t size, + uint32_t in_channels, uint32_t micsel_channels, uint32_t *offsets) +{ + struct audio_stream *istream = &source->stream; + struct audio_stream *ostream = &sink->stream; + + buffer_stream_invalidate(source, size); + size_t out_samples; + uint16_t ch; + const int32_t *in_data; + int32_t *out_data; + const uint32_t samples_per_chan = size / (sizeof(uint32_t) * micsel_channels); + + for (ch = 0; ch < micsel_channels; ch++) { + out_samples = 0; + 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 *)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]]; + out_samples += micsel_channels; + } + } +} +#endif +static void kpb_micselect_copy(struct comp_dev *dev, struct comp_buffer *sink_c, + struct comp_buffer *source_c, size_t copy_bytes, + uint32_t channels) +{ + struct comp_data *kpb = comp_get_drvdata(dev); + size_t sample_width = kpb->config.sampling_width; + uint32_t *offsets = kpb->offsets; + + switch (sample_width) { +#if CONFIG_FORMAT_S16LE + case 16: + kpb_micselect_copy16(sink_c, source_c, copy_bytes, + channels, kpb->num_of_sel_mic, offsets); + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE + case 24: + kpb_micselect_copy32(sink_c, source_c, copy_bytes, + channels, kpb->num_of_sel_mic, offsets); + break; + case 32: + kpb_micselect_copy32(sink_c, source_c, copy_bytes, + channels, kpb->num_of_sel_mic, offsets); + break; +#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + default: + comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); + return; + } +} /** * \brief Copy real time input stream into sink buffer, * and in the same time buffers that input for @@ -613,108 +1202,149 @@ static int kpb_copy(struct comp_dev *dev) { int ret = 0; struct comp_data *kpb = comp_get_drvdata(dev); - struct comp_buffer *source = NULL; - struct comp_buffer *sink = NULL; - size_t copy_bytes = 0; + struct comp_buffer *source, *sink; + size_t copy_bytes = 0, produced_bytes = 0; size_t sample_width = kpb->config.sampling_width; - uint32_t hb_free_space; - uint32_t flags = 0; + struct draining_data *dd = &kpb->draining_task_data; + uint32_t avail_bytes; + uint32_t channels = kpb->config.channels; - comp_dbg(dev, "kpb_copy()"); + comp_dbg(dev, "entry"); - /* Get source and sink buffers */ - source = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); + if (list_is_empty(&dev->bsource_list)) { + comp_err(dev, "no source."); + return -EINVAL; + } - buffer_lock(source, &flags); + /* Get source and sink buffers */ + source = comp_dev_get_first_data_producer(dev); /* Validate source */ - if (!source || !source->stream.r_ptr) { - comp_err(dev, "kpb_copy(): invalid source pointers."); + if (!audio_stream_get_rptr(&source->stream)) { + comp_err(dev, "invalid source pointers."); ret = -EINVAL; - buffer_unlock(source, flags); - goto out; + return ret; } - buffer_unlock(source, flags); - switch (kpb->state) { case KPB_STATE_RUN: /* In normal RUN state we simply copy to our sink. */ sink = kpb->sel_sink; + ret = PPL_STATUS_PATH_STOP; + + if (!sink) { + comp_err(dev, "no sink."); + ret = -EINVAL; + break; + } - buffer_lock(sink, &flags); + /* Discard data if sink is not active */ + if (comp_buffer_get_sink_component(sink)->state != COMP_STATE_ACTIVE) { + copy_bytes = audio_stream_get_avail_bytes(&source->stream); + comp_update_buffer_consume(source, copy_bytes); + comp_dbg(dev, "KD not active, dropping %zu bytes...", copy_bytes); + break; + } /* Validate sink */ - if (!sink || !sink->stream.w_ptr) { - comp_err(dev, "kpb_copy(): invalid selector sink pointers."); + if (!audio_stream_get_wptr(&sink->stream)) { + comp_err(dev, "invalid selector sink pointers."); ret = -EINVAL; - buffer_unlock(sink, flags); - goto out; + break; } - buffer_unlock(sink, flags); - - copy_bytes = MIN(sink->stream.free, source->stream.avail); + copy_bytes = audio_stream_get_copy_bytes(&source->stream, &sink->stream); if (!copy_bytes) { - comp_err(dev, "kpb_copy() error: nothing to copy sink->free %d source->avail %d", - sink->stream.free, source->stream.avail); + comp_err(dev, "nothing to copy sink->free %u source->avail %u", + audio_stream_get_free_bytes(&sink->stream), + audio_stream_get_avail_bytes(&source->stream)); ret = PPL_STATUS_PATH_STOP; - goto out; + break; } - kpb_copy_samples(sink, source, copy_bytes, sample_width); - + if (kpb->num_of_sel_mic == 0) { + kpb_copy_samples(sink, source, copy_bytes, sample_width, channels); + } else { + uint32_t avail = audio_stream_get_avail_bytes(&source->stream); + uint32_t free = audio_stream_get_free_bytes(&sink->stream); + + copy_bytes = MIN(avail, free * channels / kpb->num_of_sel_mic); + copy_bytes = ROUND_DOWN(copy_bytes, (sample_width >> 3) * channels); + unsigned int total_bytes_per_sample = + (sample_width >> 3) * kpb->num_of_sel_mic; + + produced_bytes = copy_bytes * kpb->num_of_sel_mic / channels; + produced_bytes = ROUND_DOWN(produced_bytes, total_bytes_per_sample); + if (!copy_bytes) { + comp_err(dev, "nothing to copy sink->free %u source->avail %u", + free, + avail); + ret = PPL_STATUS_PATH_STOP; + break; + } + kpb_micselect_copy(dev, sink, source, produced_bytes, channels); + } /* Buffer source data internally in history buffer for future * use by clients. */ - if (source->stream.avail <= kpb->buffer_size) { + if (copy_bytes <= kpb->hd.buffer_size) { ret = kpb_buffer_data(dev, source, copy_bytes); + if (ret) { - comp_err(dev, "kpb_copy(): internal buffering failed."); - goto out; + comp_err(dev, "internal buffering failed."); + break; } - if (kpb->buffered_data < kpb->buffer_size) { - hb_free_space = kpb->buffer_size - - kpb->buffered_data; + ret = PPL_STATUS_PATH_STOP; - kpb->buffered_data += - MIN(copy_bytes, hb_free_space); - } + /* Update buffered size. NOTE! We only record buffered + * data up to the size of history buffer. + */ + kpb->hd.buffered += MIN(kpb->hd.buffer_size - + kpb->hd.buffered, + copy_bytes); } else { - comp_err(dev, "kpb_copy(): too much data to buffer."); + comp_err(dev, "too much data to buffer."); } - comp_update_buffer_produce(sink, copy_bytes); + if (kpb->num_of_sel_mic == 0) + comp_update_buffer_produce(sink, copy_bytes); + else + comp_update_buffer_produce(sink, produced_bytes); + comp_update_buffer_consume(source, copy_bytes); - ret = 0; break; case KPB_STATE_HOST_COPY: /* In host copy state we only copy to host buffer. */ sink = kpb->host_sink; - buffer_lock(sink, &flags); + if (!sink) { + comp_err(dev, "no sink."); + ret = -EINVAL; + break; + } /* Validate sink */ - if (!sink || !sink->stream.w_ptr) { - comp_err(dev, "kpb_copy(): invalid host sink pointers."); + if (!audio_stream_get_wptr(&sink->stream)) { + comp_err(dev, "invalid host sink pointers."); ret = -EINVAL; - buffer_unlock(sink, flags); - goto out; + break; } - buffer_unlock(sink, flags); - - copy_bytes = MIN(sink->stream.free, source->stream.avail); + copy_bytes = audio_stream_get_copy_bytes(&source->stream, &sink->stream); if (!copy_bytes) { - comp_err(dev, "kpb_copy() error: nothing to copy sink->free %d source->avail %d", - sink->stream.free, source->stream.avail); - ret = PPL_STATUS_PATH_STOP; - goto out; + comp_err(dev, "nothing to copy sink->free %u source->avail %u", + audio_stream_get_free_bytes(&sink->stream), + audio_stream_get_avail_bytes(&source->stream)); + /* NOTE! We should stop further pipeline copy due to + * no data availability however due to HW bug + * (no HOST DMA IRQs) we need to call host copy + * anyway so it can update its pointers. + */ + break; } - kpb_copy_samples(sink, source, copy_bytes, sample_width); + kpb_copy_samples(sink, source, copy_bytes, sample_width, channels); comp_update_buffer_produce(sink, copy_bytes); comp_update_buffer_consume(source, copy_bytes); @@ -725,31 +1355,35 @@ static int kpb_copy(struct comp_dev *dev) /* In draining and init draining we only buffer data in * the internal history buffer. */ - if (source->stream.avail <= kpb->buffer_size) { - buffer_invalidate(source, source->stream.avail); - ret = kpb_buffer_data(dev, source, - source->stream.avail); + avail_bytes = audio_stream_get_avail_bytes(&source->stream); + copy_bytes = MIN(avail_bytes, kpb->hd.free); + ret = PPL_STATUS_PATH_STOP; + if (copy_bytes) { + buffer_stream_invalidate(source, copy_bytes); + ret = kpb_buffer_data(dev, source, copy_bytes); + dd->buffered_while_draining += copy_bytes; + kpb->hd.free -= copy_bytes; + if (ret) { - comp_err(dev, "kpb_copy(): internal buffering failed."); - goto out; + comp_err(dev, "internal buffering failed."); + break; } - comp_update_buffer_consume(source, - source->stream.avail); + comp_update_buffer_consume(source, copy_bytes); } else { - comp_err(dev, "kpb_copy(): too much data to buffer."); + comp_warn(dev, "buffering skipped (no data to copy, avail %u, free %zu", + audio_stream_get_avail_bytes(&source->stream), + kpb->hd.free); } - ret = PPL_STATUS_PATH_STOP; break; default: - comp_cl_err(&comp_kpb, "kpb_copy(): wrong state (state %d, state log %x)", + comp_cl_err(&comp_kpb, "wrong state (state %d, state log %x)", kpb->state, kpb->state_log); ret = -EIO; break; } -out: return ret; } @@ -757,8 +1391,8 @@ static int kpb_copy(struct comp_dev *dev) * \brief Buffer real time data stream in * the internal buffer. * - * \param[in] kpb - KPB component data pointer. - * \param[in] source pointer to the buffer source. + * \param[in] dev - KPB component data pointer. + * \param[in] source - pointer to the buffer source. * */ static int kpb_buffer_data(struct comp_dev *dev, @@ -768,16 +1402,14 @@ static int kpb_buffer_data(struct comp_dev *dev, size_t size_to_copy = size; size_t space_avail; struct comp_data *kpb = comp_get_drvdata(dev); - struct hb *buff = kpb->history_buffer; + struct history_buffer *buff = kpb->hd.c_hb; uint32_t offset = 0; uint64_t timeout = 0; uint64_t current_time; enum kpb_state state_preserved = kpb->state; - struct dd *draining_data = &kpb->draining_task_data; size_t sample_width = kpb->config.sampling_width; - struct timer *timer = timer_get(); - comp_dbg(dev, "kpb_buffer_data()"); + comp_dbg(dev, "entry"); /* We are allowed to buffer data in internal history buffer * only in KPB_STATE_RUN, KPB_STATE_DRAINING or KPB_STATE_INIT_DRAINING @@ -786,18 +1418,14 @@ static int kpb_buffer_data(struct comp_dev *dev, if (kpb->state != KPB_STATE_RUN && kpb->state != KPB_STATE_DRAINING && kpb->state != KPB_STATE_INIT_DRAINING) { - comp_err(dev, "kpb_buffer_data() error: wrong state! (current state %d, state log %x)", + comp_err(dev, "wrong state! (current state %d, state log %x)", kpb->state, kpb->state_log); return PPL_STATUS_PATH_STOP; } - if (kpb->state == KPB_STATE_DRAINING) - draining_data->buffered_while_draining += size_to_copy; - kpb_change_state(kpb, KPB_STATE_BUFFERING); - timeout = platform_timer_get(timer) + - clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); + timeout = sof_cycle_get_64() + k_ms_to_cyc_ceil64(1); /* Let's store audio stream data in internal history buffer */ while (size_to_copy) { /* Reset was requested, it's time to stop buffering and finish @@ -810,16 +1438,24 @@ static int kpb_buffer_data(struct comp_dev *dev, } /* Are we stuck in buffering? */ - current_time = platform_timer_get(timer); + current_time = sof_cycle_get_64(); if (timeout < current_time) { - comp_err(dev, "kpb_buffer_data(): timeout of %d [ms] (current state %d, state log %x)", - current_time - timeout, kpb->state, - kpb->state_log); + timeout = k_cyc_to_ms_near64(current_time - timeout); + if (timeout <= UINT_MAX) + comp_err(dev, + "timeout of %u [ms] (current state %d, state log %x)", + (unsigned int)(timeout), kpb->state, + kpb->state_log); + else + comp_err(dev, + "timeout > %u [ms] (current state %d, state log %x)", + UINT_MAX, kpb->state, + kpb->state_log); return -ETIME; } /* Check how much space there is in current write buffer */ - space_avail = (uint32_t)buff->end_addr - (uint32_t)buff->w_ptr; + space_avail = (uintptr_t)buff->end_addr - (uintptr_t)buff->w_ptr; if (size_to_copy > space_avail) { /* We have more data to copy than available space @@ -866,7 +1502,7 @@ static int kpb_buffer_data(struct comp_dev *dev, * we will know right away what is the current * write buffer */ - kpb->history_buffer = buff; + kpb->hd.c_hb = buff; } /* Mark buffer as FREE */ buff->state = KPB_BUFFER_FREE; @@ -877,6 +1513,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. @@ -891,7 +1528,7 @@ static void kpb_event_handler(void *arg, enum notify_id type, void *event_data) struct kpb_event_data *evd = event_data; struct kpb_client *cli = evd->client_data; - comp_info(dev, "kpb_event_handler(): received event with ID: %d ", + comp_info(dev, "received event with ID: %d ", evd->event_id); switch (evd->event_id) { @@ -908,7 +1545,7 @@ static void kpb_event_handler(void *arg, enum notify_id type, void *event_data) /*TODO*/ break; default: - comp_err(dev, "kpb_cmd() error: unsupported command"); + comp_err(dev, "unsupported command"); break; } } @@ -916,7 +1553,7 @@ static void kpb_event_handler(void *arg, enum notify_id type, void *event_data) /** * \brief Register clients in the system. * - * \param[in] dev - kpb device component pointer. + * \param[in] kpb - kpb device component pointer. * \param[in] cli - pointer to KPB client's data. * * \return integer representing either: @@ -927,26 +1564,26 @@ static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli) { int ret = 0; - comp_cl_info(&comp_kpb, "kpb_register_client()"); + comp_cl_info(&comp_kpb, "entry"); if (!cli) { - comp_cl_err(&comp_kpb, "kpb_register_client() error: no client data"); + comp_cl_err(&comp_kpb, "no client data"); return -EINVAL; } /* Do we have a room for a new client? */ if (kpb->kpb_no_of_clients >= KPB_MAX_NO_OF_CLIENTS || cli->id >= KPB_MAX_NO_OF_CLIENTS) { - comp_cl_err(&comp_kpb, "kpb_register_client() error: no free room for client = %u ", + comp_cl_err(&comp_kpb, "no free room for client = %u", cli->id); ret = -EINVAL; } else if (kpb->clients[cli->id].state != KPB_CLIENT_UNREGISTERED) { - comp_cl_err(&comp_kpb, "kpb_register_client() error: client = %u already registered", + comp_cl_err(&comp_kpb, "client = %u already registered", cli->id); ret = -EINVAL; } else { /* Client accepted, let's store his data */ kpb->clients[cli->id].id = cli->id; - kpb->clients[cli->id].history_depth = cli->history_depth; + kpb->clients[cli->id].drain_req = cli->drain_req; kpb->clients[cli->id].sink = cli->sink; kpb->clients[cli->id].r_ptr = NULL; kpb->clients[cli->id].state = KPB_CLIENT_BUFFERING; @@ -956,80 +1593,84 @@ static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli) return ret; } +#endif /* CONFIG_AMS */ /** * \brief Prepare history buffer for draining. * - * \param[in] kpb - kpb component data. + * \param[in] dev - kpb component data. * \param[in] cli - client's data. * */ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli) { struct comp_data *kpb = comp_get_drvdata(dev); - bool is_sink_ready = (kpb->host_sink->sink->state == COMP_STATE_ACTIVE); + bool is_sink_ready = (comp_buffer_get_sink_state(kpb->host_sink) == COMP_STATE_ACTIVE); size_t sample_width = kpb->config.sampling_width; - size_t history_depth = cli->history_depth * kpb->config.channels * + size_t drain_req = cli->drain_req * kpb->config.channels * (kpb->config.sampling_freq / 1000) * (KPB_SAMPLE_CONTAINER_SIZE(sample_width) / 8); - struct hb *buff = kpb->history_buffer; - struct hb *first_buff = buff; + struct history_buffer *buff = kpb->hd.c_hb; + struct history_buffer *first_buff = buff; size_t buffered = 0; size_t local_buffered; - enum comp_copy_type copy_type = COMP_COPY_NORMAL; size_t drain_interval; size_t host_period_size = kpb->host_period_size; - size_t ticks_per_ms = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); size_t bytes_per_ms = KPB_SAMPLES_PER_MS * (KPB_SAMPLE_CONTAINER_SIZE(sample_width) / 8) * kpb->config.channels; size_t period_bytes_limit; - uint32_t flags; - comp_info(dev, "kpb_init_draining(): requested draining of %d [ms] from history buffer", - cli->history_depth); + comp_info(dev, "requested draining of %d [ms] from history buffer", + cli->drain_req); if (kpb->state != KPB_STATE_RUN) { - comp_err(dev, "kpb_init_draining() error: wrong KPB state"); + comp_err(dev, "wrong KPB state"); } else if (cli->id > KPB_MAX_NO_OF_CLIENTS) { - comp_err(dev, "kpb_init_draining() error: wrong client id"); + comp_err(dev, "wrong client id"); /* TODO: check also if client is registered */ } else if (!is_sink_ready) { - comp_err(dev, "kpb_init_draining() error: sink not ready for draining"); - } else if (kpb->buffered_data < history_depth || - kpb->buffer_size < history_depth) { - comp_cl_err(&comp_kpb, "kpb_init_draining() error: not enough data in history buffer"); + comp_err(dev, "sink not ready for draining"); + } else if (kpb->hd.buffered < drain_req || + cli->drain_req > KPB_MAX_DRAINING_REQ) { + comp_cl_err(&comp_kpb, "not enough data in history buffer"); } else { /* Draining accepted, find proper buffer to start reading * At this point we are guaranteed that there is enough data * in the history buffer. All we have to do now is to calculate * read pointer from which we will start draining. */ - spin_lock_irq(&kpb->lock, flags); + kpb_lock(kpb); kpb_change_state(kpb, KPB_STATE_INIT_DRAINING); + /* Set history buffer size so new data won't overwrite those + * staged for draining. + */ + kpb->hd.free = kpb->hd.buffer_size - drain_req; + + /* Find buffer to start draining from */ do { /* Calculate how much data we have stored in * current buffer. */ buff->r_ptr = buff->start_addr; if (buff->state == KPB_BUFFER_FREE) { - local_buffered = (uint32_t)buff->w_ptr - - (uint32_t)buff->start_addr; + local_buffered = (uintptr_t)buff->w_ptr - + (uintptr_t)buff->start_addr; buffered += local_buffered; } else if (buff->state == KPB_BUFFER_FULL) { - local_buffered = (uint32_t)buff->end_addr - - (uint32_t)buff->start_addr; + local_buffered = (uintptr_t)buff->end_addr - + (uintptr_t)buff->start_addr; buffered += local_buffered; } else { - comp_err(dev, "kpb_init_draining() error: incorrect buffer label"); + comp_err(dev, "incorrect buffer label"); } /* Check if this is already sufficient to start draining * if not, go to previous buffer and continue * calculations. */ - if (history_depth > buffered) { + if (drain_req > buffered) { if (buff->prev == first_buff) { /* We went full circle and still don't * have sufficient data for draining. @@ -1039,24 +1680,25 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli) * and buffer's end address. */ buff = buff->prev; - buffered += (uint32_t)buff->end_addr - - (uint32_t)buff->w_ptr; + buffered += (uintptr_t)buff->end_addr - + (uintptr_t)buff->w_ptr; buff->r_ptr = (char *)buff->w_ptr + - (buffered - history_depth); + (buffered - drain_req); break; } buff = buff->prev; - } else if (history_depth == buffered) { + } else if (drain_req == buffered) { buff->r_ptr = buff->start_addr; break; } else { buff->r_ptr = (char *)buff->start_addr + - (buffered - history_depth); + (buffered - drain_req); break; } } while (buff != first_buff); - spin_unlock_irq(&kpb->lock, flags); + + kpb_unlock(kpb); /* Should we drain in synchronized mode (sync_draining_mode)? * Note! We have already verified host params during @@ -1067,43 +1709,109 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli) * shall take place. This time will be used to * synchronize us with application interrupts. */ - drain_interval = ((host_period_size / bytes_per_ms) * - ticks_per_ms) / + drain_interval = k_ms_to_cyc_ceil64(host_period_size / bytes_per_ms) / KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE; period_bytes_limit = host_period_size; - comp_info(dev, "kpb_init_draining(): sync_draining_mode selected with interval %d [uS].", - drain_interval * 1000 / ticks_per_ms); + comp_info(dev, "sync_draining_mode selected with interval %u [uS].", + (unsigned int)k_cyc_to_us_near64(drain_interval)); } else { /* Unlimited draining */ drain_interval = 0; period_bytes_limit = 0; - comp_info(dev, "kpb_init_draining: unlimited draining speed selected."); + comp_info(dev, "unlimited draining speed selected."); } - comp_info(dev, "kpb_init_draining(), schedule draining task"); + comp_info(dev, "schedule draining task"); /* Add one-time draining task into the scheduler. */ kpb->draining_task_data.sink = kpb->host_sink; - kpb->draining_task_data.history_buffer = buff; - kpb->draining_task_data.history_depth = history_depth; + kpb->draining_task_data.hb = buff; + kpb->draining_task_data.drain_req = drain_req; + kpb->draining_task_data.drained = 0; kpb->draining_task_data.sample_width = sample_width; kpb->draining_task_data.drain_interval = drain_interval; + kpb->draining_task_data.period_copy_start = 0; kpb->draining_task_data.pb_limit = period_bytes_limit; + kpb->draining_task_data.period_bytes = 0; + kpb->draining_task_data.next_copy_time = 0; kpb->draining_task_data.dev = dev; kpb->draining_task_data.sync_mode_on = kpb->sync_draining_mode; + kpb->draining_task_data.task_iteration = 0; + kpb->draining_task_data.prev_adjustment_time = 0; + kpb->draining_task_data.prev_adjustment_drained = 0; - /* Set host-sink copy mode to blocking */ - comp_set_attribute(kpb->host_sink->sink, COMP_ATTR_COPY_TYPE, - ©_type); + /* save current sink copy type */ + comp_get_attribute(comp_buffer_get_sink_component(kpb->host_sink), + COMP_ATTR_COPY_TYPE, &kpb->draining_task_data.copy_type); + + if (kpb->force_copy_type != COMP_COPY_INVALID) + comp_set_attribute(comp_buffer_get_sink_component(kpb->host_sink), + COMP_ATTR_COPY_TYPE, &kpb->force_copy_type); /* Pause selector copy. */ - kpb->sel_sink->sink->state = COMP_STATE_PAUSED; + comp_buffer_get_sink_component(kpb->sel_sink)->state = COMP_STATE_PAUSED; + + if (!pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_PRIMARY_CORE_ID)) + pm_runtime_disable(PM_RUNTIME_DSP, PLATFORM_PRIMARY_CORE_ID); + + comp_info(dev, "Scheduling draining task"); + + /* Change KPB internal state to DRAINING */ + kpb_change_state(kpb, KPB_STATE_DRAINING); + + kpb->draining_task_data.draining_time_start = sof_cycle_get_64(); /* Schedule draining task */ schedule_task(&kpb->draining_task, 0, 0); } } +static void adjust_drain_interval(struct comp_data *kpb, struct draining_data *dd) +{ + uint64_t now; /* timestamp in wall-clock cycles */ + + /* readjast drain_interval every 32 task iterations */ + if (dd->task_iteration++ % 32) + return; + + now = sof_cycle_get_64(); + + if (dd->prev_adjustment_time) { + size_t drained; + size_t elapsed; + size_t actual_pace, optimal_pace; + size_t pipeline_period; + + drained = dd->drained - dd->prev_adjustment_drained; + elapsed = now - dd->prev_adjustment_time; + assert(elapsed); + /* average drained bytes per second */ + actual_pace = (size_t)k_ms_to_cyc_ceil64(1000) / elapsed * drained; + + pipeline_period = KPB_SAMPLES_PER_MS * + (KPB_SAMPLE_CONTAINER_SIZE(dd->sample_width) / 8) * kpb->config.channels; + /* desired draining pace in bytes per second */ + optimal_pace = pipeline_period * KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE * 1000; + + /* just in case to prevent div by 0 if draining is stuck (e.g. because of host) */ + if (actual_pace) { + if (actual_pace < optimal_pace) { + dd->drain_interval /= optimal_pace / actual_pace; + dd->drain_interval -= dd->drain_interval / 8; + } else if (actual_pace > optimal_pace) { + dd->drain_interval *= actual_pace / optimal_pace; + dd->drain_interval += dd->drain_interval / 8; + } + /* the above algorithm will get stuck if the drain_interval is below 8 */ + if (dd->drain_interval < 8) + dd->drain_interval = 8; + } + } + + dd->prev_adjustment_time = now; + dd->prev_adjustment_drained = dd->drained; +} + /** * \brief Draining task. * @@ -1114,144 +1822,240 @@ static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli) */ static enum task_state kpb_draining_task(void *arg) { - struct dd *draining_data = (struct dd *)arg; + struct draining_data *draining_data = (struct draining_data *)arg; struct comp_buffer *sink = draining_data->sink; - struct hb *buff = draining_data->history_buffer; - size_t history_depth = draining_data->history_depth; + struct history_buffer *buff = draining_data->hb; size_t sample_width = draining_data->sample_width; - size_t size_to_read; + size_t avail; size_t size_to_copy; - bool move_buffer = false; - uint32_t drained = 0; - uint64_t draining_time_start = 0; - uint64_t draining_time_end = 0; - enum comp_copy_type copy_type = COMP_COPY_NORMAL; - uint64_t drain_interval = draining_data->drain_interval; - uint64_t next_copy_time = 0; - uint64_t current_time = 0; - size_t period_bytes = 0; + uint64_t draining_time_end; + uint64_t draining_time_ms; size_t period_bytes_limit = draining_data->pb_limit; - struct timer *timer = timer_get(); - size_t period_copy_start = platform_timer_get(timer); - size_t time_taken = 0; size_t *rt_stream_update = &draining_data->buffered_while_draining; struct comp_data *kpb = comp_get_drvdata(draining_data->dev); - bool sync_mode_on = &draining_data->sync_mode_on; - - comp_cl_info(&comp_kpb, "kpb_draining_task(), start."); + bool sync_mode_on = draining_data->sync_mode_on; + + /* + * WORKAROUND: The code below accesses KPB sink buffer and calls comp_copy() on + * component connected to sink. EDF task thread has preemptible low priority and + * so can be preempted by LL thread. This could result in broken state of sink buffer + * or component connected to sink. + * Hence k_sched_lock() is used temporary to block LL from preempting EDF task thread. + */ +#ifdef __ZEPHYR__ + k_sched_lock(); +#endif - pm_runtime_disable(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); + comp_cl_dbg(&comp_kpb, "entry"); - /* Change KPB internal state to DRAINING */ - kpb_change_state(kpb, KPB_STATE_DRAINING); + /* Have we received reset request? */ + if (kpb->state == KPB_STATE_RESETTING) { + kpb_change_state(kpb, KPB_STATE_RESET_FINISHING); + kpb_reset(draining_data->dev); + draining_data->drain_req = 0; + goto out; + } - draining_time_start = platform_timer_get(timer); + adjust_drain_interval(kpb, draining_data); - while (history_depth > 0) { - /* Have we received reset request? */ - if (kpb->state == KPB_STATE_RESETTING) { - kpb_change_state(kpb, KPB_STATE_RESET_FINISHING); - kpb_reset(draining_data->dev); - goto out; - } + if (draining_data->drain_req > 0) { /* Are we ready to drain further or host still need some time * to read the data already provided? */ - if (sync_mode_on && - next_copy_time > platform_timer_get(timer)) { - period_bytes = 0; - period_copy_start = platform_timer_get(timer); - continue; - } else if (next_copy_time == 0) { - period_copy_start = platform_timer_get(timer); + if (sync_mode_on && draining_data->next_copy_time > sof_cycle_get_64()) { + /* Restore original EDF thread priority */ +#ifdef __ZEPHYR__ + k_sched_unlock(); +#endif + return SOF_TASK_STATE_RESCHEDULE; } - size_to_read = (uint32_t)buff->end_addr - (uint32_t)buff->r_ptr; - - if (size_to_read > sink->stream.free) { - if (sink->stream.free >= history_depth) - size_to_copy = history_depth; - else - size_to_copy = sink->stream.free; - } else { - if (size_to_read > history_depth) { - size_to_copy = history_depth; - } else { - size_to_copy = size_to_read; - move_buffer = true; - } + if (draining_data->period_copy_start == 0) { + /* starting new draining period */ + draining_data->period_copy_start = sof_cycle_get_64(); + draining_data->period_bytes = 0; } + avail = (uintptr_t)buff->end_addr - (uintptr_t)buff->r_ptr; + size_to_copy = MIN(avail, + MIN(draining_data->drain_req, + audio_stream_get_free_bytes(&sink->stream))); + kpb_drain_samples(buff->r_ptr, &sink->stream, size_to_copy, sample_width); buff->r_ptr = (char *)buff->r_ptr + (uint32_t)size_to_copy; - history_depth -= size_to_copy; - drained += size_to_copy; - period_bytes += size_to_copy; - - if (move_buffer) { + draining_data->drain_req -= size_to_copy; + draining_data->drained += size_to_copy; + draining_data->period_bytes += size_to_copy; + kpb->hd.free += MIN(kpb->hd.buffer_size - + kpb->hd.free, size_to_copy); + + /* no data left in the current buffer -- switch to the next buffer */ + if (size_to_copy == avail) { buff->r_ptr = buff->start_addr; - buff = buff->next; - move_buffer = false; + draining_data->hb = buff->next; } if (size_to_copy) { comp_update_buffer_produce(sink, size_to_copy); - comp_copy(sink->sink); + comp_copy(comp_buffer_get_sink_component(sink)); + } else if (!audio_stream_get_free_bytes(&sink->stream)) { + /* There is no free space in sink buffer. + * Call .copy() on sink component so it can + * process its data further. + */ + comp_copy(comp_buffer_get_sink_component(sink)); } - if (sync_mode_on && period_bytes >= period_bytes_limit) { - current_time = platform_timer_get(timer); - time_taken = current_time - period_copy_start; - next_copy_time = current_time + drain_interval - - time_taken; + if (sync_mode_on && draining_data->period_bytes >= period_bytes_limit) { + draining_data->next_copy_time = draining_data->period_copy_start + + draining_data->drain_interval; + draining_data->period_copy_start = 0; + } else { + draining_data->next_copy_time = 0; } - if (history_depth == 0) { + if (draining_data->drain_req == 0) { /* We have finished draining of requested data however * while we were draining real time stream could provided * new data which needs to be copy to host. */ - comp_cl_info(&comp_kpb, "kpb: update history_depth by %d", + comp_cl_info(&comp_kpb, "kpb: update drain_req by %zu", *rt_stream_update); - history_depth += *rt_stream_update; + kpb_lock(kpb); + draining_data->drain_req += *rt_stream_update; *rt_stream_update = 0; + if (!draining_data->drain_req && kpb->state == KPB_STATE_DRAINING) { + /* Draining is done. Now switch KPB to copy real time + * stream to client's sink. This state is called + * "draining on demand" + * Note! If KPB state changed during draining due to + * i.e reset request we should not change that state. + */ + kpb_change_state(kpb, KPB_STATE_HOST_COPY); + } + kpb_unlock(kpb); } } -out: - draining_time_end = platform_timer_get(timer); - /* Draining is done. Now switch KPB to copy real time stream - * to client's sink. This state is called "draining on demand" - * Note! If KPB state changed during draining due to i.e reset request - * we should not change that state. - */ - if (kpb->state == KPB_STATE_DRAINING) - kpb_change_state(kpb, KPB_STATE_HOST_COPY); +out: + if (draining_data->drain_req > 0) { + /* Restore original EDF thread priority */ +#ifdef __ZEPHYR__ + k_sched_unlock(); +#endif - /* Reset host-sink copy mode back to unblocking */ - comp_set_attribute(sink->sink, COMP_ATTR_COPY_TYPE, ©_type); + /* continue drainig on next task iteration */ + return SOF_TASK_STATE_RESCHEDULE; + } - comp_cl_info(&comp_kpb, "KPB: kpb_draining_task(), done. %u drained in %d ms", - drained, - (draining_time_end - draining_time_start) - / clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1)); + /* finished drainig */ + draining_time_end = sof_cycle_get_64(); - /* If traces are disabled, prevent compile error from unused - * variables. + /* Reset host-sink copy mode back to its pre-draining value. + * kpb->host_sink is NULL after a reset or unbind. */ - (void)(draining_time_end - draining_time_start); - - pm_runtime_enable(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); + if (kpb->host_sink) + comp_set_attribute(comp_buffer_get_sink_component(kpb->host_sink), + COMP_ATTR_COPY_TYPE, + &kpb->draining_task_data.copy_type); + else + comp_cl_err(&comp_kpb, "Failed to restore host copy mode!"); + + draining_time_ms = k_cyc_to_ms_near64(draining_time_end - + draining_data->draining_time_start); + if (draining_time_ms <= UINT_MAX) + comp_cl_info(&comp_kpb, "KPB: done. %zu drained in %u ms", + draining_data->drained, (unsigned int)draining_time_ms); + else + comp_cl_info(&comp_kpb, "KPB: done. %zu drained in > %u ms", + draining_data->drained, UINT_MAX); + + /* Restore original EDF thread priority */ +#ifdef __ZEPHYR__ + k_sched_unlock(); +#endif return SOF_TASK_STATE_COMPLETED; } +#ifdef KPB_HIFI3 +static void kpb_convert_24b_to_32b(const void *linear_source, int ioffset, + struct audio_stream *sink, int ooffset, + unsigned int n_samples) +{ + 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 *)audio_stream_get_wptr(sink) + + ooffset * ssize); + ae_int32x2 *buf_end; + ae_int32x2 *buf; + + 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); + AE_SETCEND0(buf_end); + out_ptr = (ae_int32x2 *)out; + + ae_valign align_in = AE_LA64_PP(in); + int i = 0; + ae_int24x2 d24 = AE_ZERO24(); + + if (!IS_ALIGNED((uintptr_t)out_ptr, 8)) { + AE_LA24_IP(d24, align_in, in); + ae_int32x2 d320 = d24; + int higher = AE_MOVAD32_H(d320); + *(ae_int32 *)(out_ptr) = higher << 8; + out_ptr = (ae_int32x2 *)(out + 4); + ++i; + } + /* process two samples in single iteration to increase performance */ + while (i < (int)n_samples - 1) { + AE_LA24X2_IP(d24, align_in, in); + ae_int32x2 d320 = d24; + + d320 = AE_SLAI32(d320, 8); + AE_S32X2_XC(d320, out_ptr, 8); + i += 2; + } + if (i != (int)n_samples) { + AE_LA24X2_IP(d24, align_in, in); + ae_int32x2 d320 = d24; + int higher = AE_MOVAD32_H(d320); + *(ae_int32 *)(out_ptr) = higher << 8; + } +} +#else +static void kpb_convert_24b_to_32b(const void *source, int ioffset, + struct audio_stream *sink, + int ooffset, unsigned int samples) +{ + int ssize = audio_stream_sample_bytes(sink); + uint8_t *src = (uint8_t *)source + ioffset * 3; + int32_t *dst = audio_stream_wrap(sink, (uint8_t *)audio_stream_get_wptr(sink) + + ooffset * ssize); + int processed; + int nmax, i, n; + + for (processed = 0; processed < samples; processed += n) { + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = KPB_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, dst)); + n = MIN(n, nmax); + for (i = 0; i < n; i += 1) { + *dst = (src[2] << 16) | (src[1] << 8) | src[0]; + dst++; + src += 3; + } + } +} +#endif /** * \brief Drain data samples safe, according to configuration. * - * \param[in] dev - kpb component device pointer * \param[in] sink - pointer to sink buffer. * \param[in] source - pointer to source buffer. * \param[in] size - requested copy size in bytes. @@ -1261,84 +2065,136 @@ static enum task_state kpb_draining_task(void *arg) static void kpb_drain_samples(void *source, struct audio_stream *sink, size_t size, size_t sample_width) { -#if CONFIG_FORMAT_S16LE || CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE - void *dst; - void *src = source; -#endif - size_t i; - size_t j = 0; - size_t channel; - size_t frames = KPB_BYTES_TO_FRAMES(size, sample_width); + unsigned int samples; - for (i = 0; i < frames; i++) { - for (channel = 0; channel < KPB_NUM_OF_CHANNELS; channel++) { - switch (sample_width) { + switch (sample_width) { #if CONFIG_FORMAT_S16LE - case 16: - dst = audio_stream_write_frag_s16(sink, j); - *((int16_t *)dst) = *((int16_t *)src); - src = ((int16_t *)src) + 1; - break; + case 16: + samples = KPB_BYTES_TO_S16_SAMPLES(size); + audio_stream_copy_from_linear(source, 0, sink, 0, samples); + break; #endif /* CONFIG_FORMAT_S16LE */ #if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE - case 24: - case 32: - dst = audio_stream_write_frag_s32(sink, j); - *((int32_t *)dst) = *((int32_t *)src); - src = ((int32_t *)src) + 1; - break; + case 24: + samples = size / ((sample_width >> 3) * audio_stream_get_channels(sink)); + kpb_convert_24b_to_32b(source, 0, sink, 0, samples); + break; + case 32: + samples = KPB_BYTES_TO_S32_SAMPLES(size); + audio_stream_copy_from_linear(source, 0, sink, 0, samples); + break; #endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ - default: - comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); - return; - } - j++; - } + default: + comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); + return; } } +#ifdef KPB_HIFI3 +static void kpb_convert_32b_to_24b(const struct audio_stream *source, int ioffset, + 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 *)audio_stream_get_rptr(source) + + ioffset * ssize); + uint8_t *out = (uint8_t *)linear_sink + ooffset * ssize; + + const ae_f24x2 *sin = (const ae_f24x2 *)in; + ae_f24x2 *sout = (ae_f24x2 *)out; + + ae_f24x2 vs = AE_ZERO24(); + ae_valign align_out = AE_ZALIGN64(); + + if (!IS_ALIGNED((uintptr_t)sin, 8)) { + AE_L32F24_XC(vs, (const ae_f24 *)sin, 4); + AE_SA24_IP(vs, align_out, sout); + n_samples--; + } + + unsigned int size = n_samples >> 1; + size_t i; + + for (i = 0; i < size; i++) { + AE_L32X2F24_XC(vs, sin, 8); + AE_SA24X2_IP(vs, align_out, sout); + } + AE_SA64POS_FP(align_out, sout); + + if (n_samples & 1) { + AE_L32X2F24_XC(vs, sin, 4); + ae_f24 tmp = AE_MOVAD32_H(AE_MOVINT24X2_FROMF24X2(vs)); + + AE_SA24_IP(tmp, align_out, sout); + AE_SA64POS_FP(align_out, sout); + } +} +#else +static void kpb_convert_32b_to_24b(const struct audio_stream *source, int ioffset, + void *sink, int ooffset, unsigned int samples) +{ + int ssize = audio_stream_sample_bytes(source); + 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; + + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + n = samples - processed; + nmax = KPB_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, src)); + n = MIN(n, nmax); + for (i = 0; i < n; i += 1) { + dst[0] = *src & 0xFF; + dst[1] = (*src >> 8) & 0xFF; + dst[2] = (*src >> 16) & 0xFF; + dst += 3; + src++; + } + } +} +#endif /** * \brief Buffers data samples safe, according to configuration. * \param[in,out] source Pointer to source buffer. - * \param[in] start Start offset of source buffer in bytes. + * \param[in] offset Start offset of source buffer in bytes. * \param[in,out] sink Pointer to sink buffer. * \param[in] size Requested copy size in bytes. * \param[in] sample_width Sample size. */ static void kpb_buffer_samples(const struct audio_stream *source, - uint32_t start, void *sink, size_t size, + int offset, void *sink, size_t size, size_t sample_width) { - void *src; - void *dst = sink; - size_t i; - size_t j = start / - (sample_width == 16 ? sizeof(int16_t) : sizeof(int32_t)); - size_t channel; - size_t frames = KPB_BYTES_TO_FRAMES(size, sample_width); - - for (i = 0; i < frames; i++) { - for (channel = 0; channel < KPB_NUM_OF_CHANNELS; channel++) { - switch (sample_width) { - case 16: - src = audio_stream_read_frag_s16(source, j); - *((int16_t *)dst) = *((int16_t *)src); - dst = ((int16_t *)dst) + 1; - break; + unsigned int samples_count; + int samples_offset; + + switch (sample_width) { +#if CONFIG_FORMAT_S16LE + case 16: + samples_count = KPB_BYTES_TO_S16_SAMPLES(size); + samples_offset = KPB_BYTES_TO_S16_SAMPLES(offset); + audio_stream_copy_to_linear(source, samples_offset, + sink, 0, samples_count); + break; +#endif #if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE - case 24: - case 32: - src = audio_stream_read_frag_s32(source, j); - *((int32_t *)dst) = *((int32_t *)src); - dst = ((int32_t *)dst) + 1; - break; -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE*/ - default: - comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); - return; - } - j++; - } + case 24: + 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; + case 32: + samples_count = KPB_BYTES_TO_S32_SAMPLES(size); + samples_offset = KPB_BYTES_TO_S32_SAMPLES(offset); + audio_stream_copy_to_linear(source, samples_offset, + sink, 0, samples_count); + break; +#endif + default: + comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); + return; } } @@ -1348,17 +2204,17 @@ static void kpb_buffer_samples(const struct audio_stream *source, * * \return: none. */ -static void kpb_clear_history_buffer(struct hb *buff) +static void kpb_clear_history_buffer(struct history_buffer *buff) { - struct hb *first_buff = buff; + struct history_buffer *first_buff = buff; void *start_addr; size_t size; - comp_cl_info(&comp_kpb, "kpb_clear_history_buffer()"); + comp_cl_info(&comp_kpb, "entry"); do { start_addr = buff->start_addr; - size = (uint32_t)buff->end_addr - (uint32_t)start_addr; + size = (uintptr_t)buff->end_addr - (uintptr_t)start_addr; bzero(start_addr, size); @@ -1392,10 +2248,71 @@ static inline bool kpb_is_sample_width_supported(uint32_t sampling_width) return ret; } +#ifdef KPB_HIFI3 +static void kpb_copy_24b_in_32b(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, + uint32_t n_samples) +{ + int ssize = audio_stream_sample_bytes(source); /* src fmt == sink fmt */ + 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; + ae_int32x2 vs = AE_ZERO32(); + + if (!IS_ALIGNED((uintptr_t)sin, 8)) { + AE_L32_IP(vs, (const ae_int32 *)sin, 4); + AE_S32_L_IP(vs, (ae_int32 *)sout, 4); + n_samples--; + } + ae_valign align_out = AE_ZALIGN64(); + size_t size = n_samples >> 1; + size_t i; + + for (i = 0; i < size; i++) { + AE_L32X2_IP(vs, sin, 8); + AE_SA32X2_IP(vs, align_out, sout); + } + AE_SA64POS_FP(align_out, sout); + if (n_samples & 1) { + vs = AE_L32_I((const ae_int32 *)sin, 0); + AE_S32_L_I(vs, (ae_int32 *)sout, 0); + } +} +#else +static void kpb_copy_24b_in_32b(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = KPB_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, src)); + n = MIN(n, nmax); + nmax = KPB_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(sink, dst)); + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src << 8; + src++; + dst++; + } + } +} +#endif /** * \brief Copy data samples safe, according to configuration. * - * \param[in] dev - kpb component device pointer * \param[in] sink - pointer to sink buffer. * \param[in] source - pointer to source buffer. * \param[in] size - requested copy size in bytes. @@ -1404,49 +2321,34 @@ static inline bool kpb_is_sample_width_supported(uint32_t sampling_width) */ static void kpb_copy_samples(struct comp_buffer *sink, struct comp_buffer *source, size_t size, - size_t sample_width) + size_t sample_width, uint32_t channels) { -#if CONFIG_FORMAT_S16LE || CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE - void *dst; - void *src; -#endif - size_t i; - size_t j = 0; - size_t channel; - size_t frames = KPB_BYTES_TO_FRAMES(size, sample_width); struct audio_stream *istream = &source->stream; struct audio_stream *ostream = &sink->stream; + unsigned int samples; - buffer_invalidate(source, size); - - for (i = 0; i < frames; i++) { - for (channel = 0; channel < KPB_NUM_OF_CHANNELS; channel++) { - switch (sample_width) { + buffer_stream_invalidate(source, size); + switch (sample_width) { #if CONFIG_FORMAT_S16LE - case 16: - dst = audio_stream_write_frag_s16(ostream, j); - src = audio_stream_read_frag_s16(istream, j); - *((int16_t *)dst) = *((int16_t *)src); - break; -#endif /* CONFIG_FORMAT_S16LE */ + case 16: + audio_stream_copy(istream, 0, ostream, 0, KPB_BYTES_TO_S16_SAMPLES(size)); + break; +#endif #if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE - case 24: - /* FALLTHROUGH */ - case 32: - dst = audio_stream_write_frag_s32(ostream, j); - src = audio_stream_read_frag_s32(istream, j); - *((int32_t *)dst) = *((int32_t *)src); - break; -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE*/ - default: - comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); - return; - } - j++; - } + case 24: + samples = size / ((sample_width >> 3) * channels); + kpb_copy_24b_in_32b(istream, 0, ostream, 0, samples); + break; + case 32: + audio_stream_copy(istream, 0, ostream, 0, KPB_BYTES_TO_S32_SAMPLES(size)); + break; +#endif + default: + comp_cl_err(&comp_kpb, "KPB: An attempt to copy not supported format!"); + return; } - buffer_writeback(sink, size); + buffer_stream_writeback(sink, size); } /** @@ -1455,11 +2357,11 @@ static void kpb_copy_samples(struct comp_buffer *sink, * * \return none. */ -static void kpb_reset_history_buffer(struct hb *buff) +static void kpb_reset_history_buffer(struct history_buffer *buff) { - struct hb *first_buff = buff; + struct history_buffer *first_buff = buff; - comp_cl_info(&comp_kpb, "kpb_reset_history_buffer()"); + comp_cl_info(&comp_kpb, "entry"); if (!buff) return; @@ -1495,18 +2397,22 @@ static inline bool validate_host_params(struct comp_dev *dev, size_t bytes_per_ms = KPB_SAMPLES_PER_MS * (KPB_SAMPLE_CONTAINER_SIZE(sample_width) / 8) * kpb->config.channels; - size_t pipeline_period_size = (dev->pipeline->ipc_pipe.period / 1000) + size_t pipeline_period_size = (dev->pipeline->period / 1000) * bytes_per_ms; if (!host_period_size || !host_buffer_size) { /* Wrong host params */ + comp_err(dev, "kpb: host_period_size (%zu) cannot be 0 and host_buffer_size (%zu) cannot be 0", + host_period_size, host_buffer_size); return false; - } else if (HOST_BUFFER_MIN_SIZE(hb_size_req) > + } else if (HOST_BUFFER_MIN_SIZE(hb_size_req, kpb->config.channels) > host_buffer_size) { /* Host buffer size is too small - history data * may get overwritten. */ - return false; + comp_warn(dev, "kpb: host_buffer_size (%zu) must be at least %zu", + host_buffer_size, + HOST_BUFFER_MIN_SIZE(hb_size_req, kpb->config.channels)); } else if (kpb->sync_draining_mode) { /* Sync draining allowed. Check if we can perform draining * with current settings. @@ -1518,8 +2424,13 @@ static inline bool validate_host_params(struct comp_dev *dev, * of buffered data. */ if ((host_period_size / KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE) < - pipeline_period_size) + pipeline_period_size) { + comp_err(dev, "kpb: host_period_size (%zu) must be at least %d * %zu", + host_period_size, + KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE, + pipeline_period_size); return false; + } } return true; @@ -1535,24 +2446,259 @@ static inline bool validate_host_params(struct comp_dev *dev, static inline void kpb_change_state(struct comp_data *kpb, enum kpb_state state) { - comp_cl_dbg(&comp_kpb, "kpb_change_state(): from %d to %d", + comp_cl_dbg(&comp_kpb, "change state from %d to %d", kpb->state, state); kpb->state = state; kpb->state_log = (kpb->state_log << 4) | state; } +static int kpb_set_micselect(struct comp_dev *dev, const void *data, + int max_data_size) +{ + const struct kpb_micselector_config *mic_sel = data; + struct comp_data *kpb = comp_get_drvdata(dev); + const size_t mic_cnt = kpb->config.channels - KPB_REFERENCE_SUPPORT_CHANNELS; + const uint8_t valid_mask = KPB_COUNT_TO_BITMASK(mic_cnt); + size_t i; + + if ((valid_mask & mic_sel->mask) == 0) { + comp_err(dev, "error: invalid micselector bit mask"); + return -EINVAL; + } + /* selected mics counter */ + size_t num_of_sel_mic = 0; + + for (i = 0; i < mic_cnt; i++) { + if (KPB_IS_BIT_SET(mic_sel->mask, i)) { + kpb->offsets[num_of_sel_mic] = i; + num_of_sel_mic++; + } + } + kpb->num_of_sel_mic = num_of_sel_mic; + kpb->num_of_in_channels = kpb->config.channels; + kpb->mic_sel.mask = mic_sel->mask; + return 0; +} + +#ifdef CONFIG_IPC_MAJOR_4 + +static int devicelist_push(struct device_list *devlist, struct comp_dev **dev) +{ + if (devlist->count != DEVICE_LIST_SIZE) { + devlist->devs[devlist->count] = dev; + devlist->count++; + return 0; + } + return -EINVAL; +} + +static void devicelist_reset(struct device_list *devlist, bool remove_items) +{ + /* clear items */ + if (remove_items) { + for (int i = 0; i < devlist->count; i++) + *devlist->devs[i] = NULL; + } + /* zero the pointers */ + for (int i = 0; i < devlist->count; i++) + devlist->devs[i] = NULL; + + devlist->count = 0; +} + +static inline int alloc_fmt_module_list_item(struct kpb_fmt_dev_list *fmt_device_list, + struct comp_dev *mi_ptr, struct comp_dev ***item) +{ + /* -1 means we did not find the slot yet */ + int first_empty_slot_idx = -1; + + for (size_t module_slot_idx = 0; module_slot_idx < FAST_MODE_TASK_MAX_MODULES_COUNT; + ++module_slot_idx){ + /* check if module already added */ + if (fmt_device_list->modules_list_item[module_slot_idx] == mi_ptr) + return -EINVAL; + /* finding first available empty slot */ + if (first_empty_slot_idx < 0 && + !fmt_device_list->modules_list_item[module_slot_idx]) + first_empty_slot_idx = module_slot_idx; + } + /* add item to first available empty slot */ + if (first_empty_slot_idx >= 0) { + fmt_device_list->modules_list_item[first_empty_slot_idx] = mi_ptr; + *item = &fmt_device_list->modules_list_item[first_empty_slot_idx]; + return 0; + } + return -ENOMEM; +} + +static int prepare_fmt_modules_list(struct comp_dev *kpb_dev, + uint32_t outpin_idx, + const struct kpb_task_params *modules_to_prepare) +{ + int ret; + struct comp_dev *dev; + struct kpb_fmt_dev_list *fmt_device_list = + &((struct comp_data *)comp_get_drvdata(kpb_dev))->fmt_device_list; + + fmt_device_list->kpb_list_item[outpin_idx] = kpb_dev; + ret = devicelist_push(&fmt_device_list->device_list[outpin_idx], + &fmt_device_list->kpb_list_item[outpin_idx]); + if (ret < 0) + return ret; + + for (size_t mod_idx = 0; mod_idx < modules_to_prepare->number_of_modules; ++mod_idx) { + uint32_t comp_id = IPC4_COMP_ID(modules_to_prepare->dev_ids[mod_idx].module_id, + modules_to_prepare->dev_ids[mod_idx].instance_id); + + dev = ipc4_get_comp_dev(comp_id); + if (!dev) + return -EINVAL; + + struct comp_dev **new_list_item_ptr; + + ret = alloc_fmt_module_list_item(fmt_device_list, dev, &new_list_item_ptr); + if (ret < 0) + return ret; + *new_list_item_ptr = dev; + ret = devicelist_push(&fmt_device_list->device_list[outpin_idx], + new_list_item_ptr); + if (ret < 0) + return ret; + } + return 0; +} + +static int clear_fmt_modules_list(struct kpb_fmt_dev_list *fmt_device_list, + uint32_t outpin_idx) +{ + if (outpin_idx >= KPB_MAX_SINK_CNT) + return -EINVAL; + + devicelist_reset(&fmt_device_list->device_list[outpin_idx], true); + return 0; +} + +static int unregister_modules_list(struct fast_mode_task *fmt, + struct device_list *list_to_remove, size_t list_idx) +{ + if (list_to_remove == fmt->device_list[list_idx]) { + fmt->device_list[list_idx] = NULL; + return 0; + } + if (!fmt->device_list[list_idx]) { + /* Nothing to do here */ + return 0; + } + return -EINVAL; +} + +/* Comment from Old FW, may be outdated: + * Important: function below should be called only from within critical section + * (Goto KPB for more details) + */ +static int register_modules_list(struct fast_mode_task *fmt, + struct device_list *new_list, size_t list_idx) +{ + if (list_idx >= ARRAY_SIZE(fmt->device_list)) + return -EINVAL; + + /* Check if slot is free */ + if (!fmt->device_list[list_idx]) { + fmt->device_list[list_idx] = new_list; + return 0; + } + if (new_list == fmt->device_list[list_idx]) { + /* Already registered. */ + return 0; + } + /* was ADSP_ALREADY_IN_USE */ + return -EINVAL; +} + +static int configure_fast_mode_task(struct comp_dev *kpb_dev, const struct kpb_task_params *cfg, + size_t pin) +{ + if (pin >= KPB_MAX_SINK_CNT || pin == REALTIME_PIN_ID || !cfg) + return -EINVAL; + + struct comp_data *priv_data = (struct comp_data *)comp_get_drvdata(kpb_dev); + int ret = unregister_modules_list(&priv_data->fmt, + &priv_data->fmt_device_list.device_list[pin], + pin); + if (ret) + return -EINVAL; + + ret = clear_fmt_modules_list(&priv_data->fmt_device_list, pin); + if (ret) + return -EINVAL; + + /* When modules count IS 0 we only need to remove modules from Fast Mode. */ + if (cfg->number_of_modules > 0) { + ret = prepare_fmt_modules_list(kpb_dev, pin, cfg); + if (!ret) + ret = register_modules_list(&priv_data->fmt, + &priv_data->fmt_device_list.device_list[pin], + pin); + } + return ret; +} +#endif + +static int kpb_set_large_config(struct comp_dev *dev, uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + /* We can use extended param id for both extended and standard param id */ + union ipc4_extended_param_id extended_param_id; + + comp_info(dev, "entry"); + + extended_param_id.full = param_id; + + switch (extended_param_id.part.parameter_type) { +#ifdef CONFIG_IPC_MAJOR_4 + case KP_BUF_CFG_FM_MODULE: { + /* Modules count equals 0 is a special case in which we want to clear list for + * given pin. Reference FW also allowed for cfg/data to be NULL, but this is no + * longer the case. + */ + const struct kpb_task_params *cfg = (struct kpb_task_params *)data; + uint32_t outpin_id = extended_param_id.part.parameter_instance; + + return configure_fast_mode_task(dev, cfg, outpin_id); + } +#endif + case KP_BUF_CLIENT_MIC_SELECT: + return kpb_set_micselect(dev, data, data_offset); + default: + return -EINVAL; + } +} + +DECLARE_TR_CTX(kpb_tr, SOF_UUID(KPB_UUID), LOG_LEVEL_INFO); + static const struct comp_driver comp_kpb = { .type = SOF_COMP_KPB, - .uid = SOF_UUID(kpb_uuid), + .uid = SOF_RT_UUID(KPB_UUID), + .tctx = &kpb_tr, .ops = { - .new = kpb_new, - .free = kpb_free, - .cmd = kpb_cmd, - .trigger = kpb_trigger, - .copy = kpb_copy, - .prepare = kpb_prepare, - .reset = kpb_reset, - .params = kpb_params, + .create = kpb_new, + .free = kpb_free, + .trigger = kpb_trigger, + .copy = kpb_copy, + .prepare = kpb_prepare, + .reset = kpb_reset, + .params = kpb_params, + .set_large_config = kpb_set_large_config, +#if CONFIG_IPC_MAJOR_4 + .get_attribute = kpb_get_attribute, + .bind = kpb_bind, + .unbind = kpb_unbind, +#elif CONFIG_IPC_MAJOR_3 + .cmd = kpb_cmd, +#endif /* CONFIG_IPC_MAJOR_4 */ }, }; @@ -1567,3 +2713,4 @@ UT_STATIC void sys_comp_kpb_init(void) } DECLARE_MODULE(sys_comp_kpb_init); +SOF_MODULE_INIT(kpb, sys_comp_kpb_init); diff --git a/src/audio/kpb.toml b/src/audio/kpb.toml new file mode 100644 index 000000000000..e384632c1be8 --- /dev/null +++ b/src/audio/kpb.toml @@ -0,0 +1,19 @@ + [[module.entry]] + name = "KPB" + uuid = UUIDREG_STR_KPB4 + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0xB" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # 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, 14400, 1114000, 16, 16, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/level_multiplier/CMakeLists.txt b/src/audio/level_multiplier/CMakeLists.txt new file mode 100644 index 000000000000..1805c56a0bce --- /dev/null +++ b/src/audio/level_multiplier/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_LEVEL_MULTIPLIER STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/level_multiplier_llext) + add_dependencies(app level_multiplier) +else() + add_local_sources(sof level_multiplier.c) + add_local_sources(sof level_multiplier-generic.c) + add_local_sources(sof level_multiplier-hifi3.c) + add_local_sources(sof level_multiplier-hifi5.c) + + if(CONFIG_IPC_MAJOR_4) + add_local_sources(sof level_multiplier-ipc4.c) + endif() +endif() diff --git a/src/audio/level_multiplier/Kconfig b/src/audio/level_multiplier/Kconfig new file mode 100644 index 000000000000..cc8a79632cd7 --- /dev/null +++ b/src/audio/level_multiplier/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_LEVEL_MULTIPLIER + tristate "Level multiplier component" + default y + help + Select for Level multiplier component. This component + applies a fixed gain to audio. The amount of gain + is configured in the bytes control that is typically + set in boot time from topology. It can e.g. increase + capture sensitivity of voice applications by 20 dB + compared to media capture. diff --git a/src/audio/level_multiplier/README.md b/src/audio/level_multiplier/README.md new file mode 100644 index 000000000000..278b895d099c --- /dev/null +++ b/src/audio/level_multiplier/README.md @@ -0,0 +1,14 @@ +# Level Multiplier Architecture + +This directory contains the Level Multiplier component. + +## Overview + +Applies simple digital gain/attenuation (multiplication) to an audio signal stream. + +## Configuration and Scripts + +- **Kconfig**: Enables the Level multiplier component (`COMP_LEVEL_MULTIPLIER`). This applies a configured fixed gain to an audio stream, typically to increase capture sensitivity of voice applications compared to media capture. +- **CMakeLists.txt**: Manages local base sources and optimized implementations (`level_multiplier-generic.c`, `level_multiplier-hifi3.c`, `level_multiplier-hifi5.c`). Includes the IPC version 4 wrapper (`level_multiplier-ipc4.c`) when `CONFIG_IPC_MAJOR_4` is present, and supports `llext`. +- **level_multiplier.toml**: Holds topology module entry parameters including UUIDs, standard pin layouts, and `mod_cfg` limits. +- **Topology (.conf)**: `tools/topology/topology2/include/components/level_multiplier.conf` configures the `level_multiplier` widget object. It specifies `num_input_pins` and `num_output_pins` mapping and defaults to type `effect` with UUID `56:74:39:30:61:46:44:46:97:e5:39:a9:e5:ab:17:78`. diff --git a/src/audio/level_multiplier/level_multiplier-generic.c b/src/audio/level_multiplier/level_multiplier-generic.c new file mode 100644 index 000000000000..554a5f7f49c6 --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier-generic.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <stdint.h> +#include "level_multiplier.h" + +#define LEVEL_MULTIPLIER_S16_SHIFT Q_SHIFT_BITS_32(15, LEVEL_MULTIPLIER_QXY_Y, 15) +#define LEVEL_MULTIPLIER_S24_SHIFT Q_SHIFT_BITS_64(23, LEVEL_MULTIPLIER_QXY_Y, 23) +#define LEVEL_MULTIPLIER_S32_SHIFT Q_SHIFT_BITS_64(31, LEVEL_MULTIPLIER_QXY_Y, 31) + +#if SOF_USE_HIFI(NONE, VOLUME) + +#if CONFIG_FORMAT_S16LE +/** + * level_multiplier_s16() - Process S16_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 16-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s16(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + const int32_t gain = cd->gain; + int16_t const *x, *x_start, *x_end; + int16_t *y, *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int i; + + ret = source_get_data_s16(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s16(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x; + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + for (i = 0; i < samples_without_wrap; i++) { + *y = q_multsr_sat_32x32_16(*x, gain, LEVEL_MULTIPLIER_S16_SHIFT); + x++; + y++; + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= x_end) ? x - x_size : x; + y = (y >= y_end) ? y - y_size : y; + + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +/** + * level_multiplier_s24() - Process S24_4LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 24-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s24(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + const int32_t gain = cd->gain; + int32_t const *x, *x_start, *x_end; + int32_t *y, *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int i; + + ret = source_get_data_s32(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x; + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + for (i = 0; i < samples_without_wrap; i++) { + *y = q_multsr_sat_32x32_24(sign_extend_s24(*x), gain, + LEVEL_MULTIPLIER_S24_SHIFT); + x++; + y++; + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= x_end) ? x - x_size : x; + y = (y >= y_end) ? y - y_size : y; + + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * level_multiplier_s32() - Process S32_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 32-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s32(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + const int32_t gain = cd->gain; + int32_t const *x, *x_start, *x_end; + int32_t *y, *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int i; + + ret = source_get_data_s32(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x; + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + for (i = 0; i < samples_without_wrap; i++) { + *y = q_multsr_sat_32x32(*x, gain, LEVEL_MULTIPLIER_S32_SHIFT); + x++; + y++; + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= x_end) ? x - x_size : x; + y = (y >= y_end) ? y - y_size : y; + + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S32LE */ + +/* This struct array defines the used processing functions for + * the PCM formats + */ +const struct level_multiplier_proc_fnmap level_multiplier_proc_fnmap[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, level_multiplier_s16 }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, level_multiplier_s24 }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, level_multiplier_s32 }, +#endif +}; + +/** + * level_multiplier_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +level_multiplier_func level_multiplier_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < ARRAY_SIZE(level_multiplier_proc_fnmap); i++) + if (src_fmt == level_multiplier_proc_fnmap[i].frame_fmt) + return level_multiplier_proc_fnmap[i].level_multiplier_proc_func; + + return NULL; +} + +#endif /* SOF_USE_HIFI(NONE, VOLUME) */ diff --git a/src/audio/level_multiplier/level_multiplier-hifi3.c b/src/audio/level_multiplier/level_multiplier-hifi3.c new file mode 100644 index 000000000000..077476254c0e --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier-hifi3.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <stdint.h> +#include "level_multiplier.h" + +#define LEVEL_MULTIPLIER_S32_SHIFT 8 /* See explanation from level_multiplier_s32() */ + +#if SOF_USE_HIFI(3, VOLUME) || SOF_USE_HIFI(4, VOLUME) + +#include <xtensa/tie/xt_hifi3.h> + +#if CONFIG_FORMAT_S16LE +/** + * level_multiplier_s16() - Process S16_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 16-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s16(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + ae_valign x_align; + ae_valign y_align = AE_ZALIGN64(); + ae_f32x2 samples0; + ae_f32x2 samples1; + const ae_f32x2 gain = cd->gain; + ae_f16x4 samples; + ae_f16x4 const *x; + ae_f16x4 *y; + int16_t const *x_start, *x_end; + int16_t *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int n, i; + + ret = source_get_data_s16(source, bytes, (const int16_t **)&x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s16(sink, bytes, (int16_t **)&y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - (int16_t *)x; + samples_without_wrap = y_end - (int16_t *)y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + x_align = AE_LA64_PP(x); + + /* Process with 64 bit loads and stores */ + n = samples_without_wrap >> 2; + for (i = 0; i < n; i++) { + AE_LA16X4_IP(samples, x_align, x); + + /* Multiply the input sample */ + samples0 = AE_MULFP32X16X2RS_H(gain, samples); + samples1 = AE_MULFP32X16X2RS_L(gain, samples); + + /* Q9.23 to Q1.31 */ + samples0 = AE_SLAI32S(samples0, 8); + samples1 = AE_SLAI32S(samples1, 8); + + /* To Q1.15 */ + samples = AE_ROUND16X4F32SSYM(samples0, samples1); + AE_SA16X4_IP(samples, y_align, y); + } + + AE_SA64POS_FP(y_align, y); + n = samples_without_wrap - (n << 2); + for (i = 0; i < n; i++) { + AE_L16_IP(samples, (ae_f16 *)x, sizeof(ae_f16)); + samples0 = AE_MULFP32X16X2RS_H(gain, samples); + samples0 = AE_SLAI32S(samples0, 8); + samples = AE_ROUND16X4F32SSYM(samples0, samples0); + AE_S16_0_IP(samples, (ae_f16 *)y, sizeof(ae_f16)); + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= (ae_f16x4 *)x_end) ? x - x_size : x; + y = (y >= (ae_f16x4 *)y_end) ? y - y_size : y; + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +/** + * level_multiplier_s24() - Process S24_4LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 24-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s24(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + ae_valign x_align; + ae_valign y_align = AE_ZALIGN64(); + const ae_f32x2 gain = cd->gain; + ae_f32x2 samples; + ae_f32x2 const *x; + ae_f32x2 *y; + int32_t const *x_start, *x_end; + int32_t *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int n, i; + + ret = source_get_data_s32(source, bytes, (const int32_t **)&x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, (int32_t **)&y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - (int32_t *)x; + samples_without_wrap = y_end - (int32_t *)y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + x_align = AE_LA64_PP(x); + + /* Process with 64 bit loads and stores */ + n = samples_without_wrap >> 1; + for (i = 0; i < n; i++) { + AE_LA32X2_IP(samples, x_align, x); + samples = AE_MULFP32X2RS(gain, AE_SLAI32(samples, 8)); + samples = AE_SLAI32S(samples, 8); + samples = AE_SRAI32(samples, 8); + AE_SA32X2_IP(samples, y_align, y); + } + + AE_SA64POS_FP(y_align, y); + if (samples_without_wrap - (n << 1)) { + AE_L32_IP(samples, (ae_f32 *)x, sizeof(ae_f32)); + samples = AE_MULFP32X2RS(gain, AE_SLAI32(samples, 8)); + samples = AE_SLAI32S(samples, 8); + samples = AE_SRAI32(samples, 8); + AE_S32_L_IP(samples, (ae_f32 *)y, sizeof(ae_f32)); + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= (ae_f32x2 *)x_end) ? x - x_size : x; + y = (y >= (ae_f32x2 *)y_end) ? y - y_size : y; + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * level_multiplier_s32() - Process S32_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 32-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s32(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + ae_valign x_align; + ae_valign y_align = AE_ZALIGN64(); + ae_f64 mult0; + ae_f64 mult1; + const ae_f32x2 gain = cd->gain; + ae_f32x2 samples; + ae_f32x2 const *x; + ae_f32x2 *y; + int32_t const *x_start, *x_end; + int32_t *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int n, i; + + ret = source_get_data_s32(source, bytes, (const int32_t **)&x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, (int32_t **)&y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - (int32_t *)x; + samples_without_wrap = y_end - (int32_t *)y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + x_align = AE_LA64_PP(x); + + /* Process with 64 bit loads and stores */ + n = samples_without_wrap >> 1; + for (i = 0; i < n; i++) { + AE_LA32X2_IP(samples, x_align, x); + /* Q31 gain would give Q47, then Q23 gain gives Q39, need to shift + * the product left by 8 to get Q47 for round instruction. + */ + mult0 = AE_MULF32R_HH(gain, samples); + mult1 = AE_MULF32R_LL(gain, samples); + mult0 = AE_SLAI64(mult0, LEVEL_MULTIPLIER_S32_SHIFT); + mult1 = AE_SLAI64(mult1, LEVEL_MULTIPLIER_S32_SHIFT); + samples = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ + AE_SA32X2_IP(samples, y_align, y); + } + + AE_SA64POS_FP(y_align, y); + if (samples_without_wrap - (n << 1)) { + AE_L32_IP(samples, (ae_f32 *)x, sizeof(ae_f32)); + mult0 = AE_MULF32R_HH(gain, samples); + mult0 = AE_SLAI64(mult0, LEVEL_MULTIPLIER_S32_SHIFT); + samples = AE_ROUND32F48SSYM(mult0); + AE_S32_L_IP(samples, (ae_f32 *)y, sizeof(ae_f32)); + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= (ae_f32x2 *)x_end) ? x - x_size : x; + y = (y >= (ae_f32x2 *)y_end) ? y - y_size : y; + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S32LE */ + +/* This struct array defines the used processing functions for + * the PCM formats + */ +const struct level_multiplier_proc_fnmap level_multiplier_proc_fnmap[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, level_multiplier_s16 }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, level_multiplier_s24 }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, level_multiplier_s32 }, +#endif +}; + +/** + * level_multiplier_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +level_multiplier_func level_multiplier_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < ARRAY_SIZE(level_multiplier_proc_fnmap); i++) + if (src_fmt == level_multiplier_proc_fnmap[i].frame_fmt) + return level_multiplier_proc_fnmap[i].level_multiplier_proc_func; + + return NULL; +} + +#endif /* SOF_USE_HIFI(3, VOLUME) || SOF_USE_HIFI(4, VOLUME) */ diff --git a/src/audio/level_multiplier/level_multiplier-hifi5.c b/src/audio/level_multiplier/level_multiplier-hifi5.c new file mode 100644 index 000000000000..91f52ade4767 --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier-hifi5.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <stdint.h> +#include "level_multiplier.h" + +#define LEVEL_MULTIPLIER_S32_SHIFT 8 /* See explanation from level_multiplier_s32() */ + +#if SOF_USE_MIN_HIFI(5, VOLUME) + +#include <xtensa/tie/xt_hifi3.h> + +#if CONFIG_FORMAT_S16LE +/** + * level_multiplier_s16() - Process S16_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 16-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s16(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + ae_valignx2 x_align; + ae_valignx2 y_align = AE_ZALIGN128(); + ae_f32x2 tmp0; + ae_f32x2 tmp1; + const ae_f32x2 gain = cd->gain; + ae_f16x4 samples0; + ae_f16x4 samples1; + ae_int16x8 const *x; + ae_int16x8 *y; + int16_t const *x_start, *x_end; + int16_t *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int n, i; + + ret = source_get_data_s16(source, bytes, (const int16_t **)&x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s16(sink, bytes, (int16_t **)&y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - (int16_t *)x; + samples_without_wrap = y_end - (int16_t *)y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + x_align = AE_LA128_PP(x); + + /* Process with 128 bit loads and stores */ + n = samples_without_wrap >> 3; + for (i = 0; i < n; i++) { + AE_LA16X4X2_IP(samples0, samples1, x_align, x); + + AE_MULF2P32X16X4RS(tmp0, tmp1, gain, gain, samples0); + /* Q9.23 to Q1.31 */ + tmp0 = AE_SLAI32S(tmp0, 8); + tmp1 = AE_SLAI32S(tmp1, 8); + samples0 = AE_ROUND16X4F32SSYM(tmp0, tmp1); + + AE_MULF2P32X16X4RS(tmp0, tmp1, gain, gain, samples1); + /* Q9.23 to Q1.31 */ + tmp0 = AE_SLAI32S(tmp0, 8); + tmp1 = AE_SLAI32S(tmp1, 8); + samples1 = AE_ROUND16X4F32SSYM(tmp0, tmp1); + + AE_SA16X4X2_IP(samples0, samples1, y_align, y); + } + + AE_SA128POS_FP(y_align, y); + n = samples_without_wrap - (n << 3); + for (i = 0; i < n; i++) { + AE_L16_IP(samples0, (ae_f16 *)x, sizeof(ae_f16)); + tmp0 = AE_MULFP32X16X2RS_H(gain, samples0); + tmp0 = AE_SLAI32S(tmp0, 8); + samples0 = AE_ROUND16X4F32SSYM(tmp0, tmp0); + AE_S16_0_IP(samples0, (ae_f16 *)y, sizeof(ae_f16)); + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= (ae_int16x8 *)x_end) ? x - x_size : x; + y = (y >= (ae_int16x8 *)y_end) ? y - y_size : y; + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +/** + * level_multiplier_s24() - Process S24_4LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 24-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s24(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + ae_valignx2 x_align; + ae_valignx2 y_align = AE_ZALIGN128(); + const ae_f32x2 gain = cd->gain; + ae_f32x2 samples0; + ae_f32x2 samples1; + ae_f32x2 tmp0; + ae_f32x2 tmp1; + ae_int32x4 const *x; + ae_int32x4 *y; + int32_t const *x_start, *x_end; + int32_t *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int n, i; + + ret = source_get_data_s32(source, bytes, (const int32_t **)&x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, (int32_t **)&y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - (int32_t *)x; + samples_without_wrap = y_end - (int32_t *)y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + x_align = AE_LA128_PP(x); + + /* Process with 64 bit loads and stores */ + n = samples_without_wrap >> 2; + for (i = 0; i < n; i++) { + AE_LA32X2X2_IP(samples0, samples1, x_align, x); + AE_MULF2P32X4RS(tmp0, tmp1, gain, gain, + AE_SLAI32(samples0, 8), + AE_SLAI32(samples1, 8)); + samples0 = AE_SRAI32(AE_SLAI32S(tmp0, 8), 8); + samples1 = AE_SRAI32(AE_SLAI32S(tmp1, 8), 8); + AE_SA32X2X2_IP(samples0, samples1, y_align, y); + } + + AE_SA128POS_FP(y_align, y); + n = samples_without_wrap - (n << 2); + for (i = 0; i < n; i++) { + AE_L32_IP(samples0, (ae_f32 *)x, sizeof(ae_f32)); + samples0 = AE_MULFP32X2RS(gain, AE_SLAI32(samples0, 8)); + samples0 = AE_SRAI32(AE_SLAI32S(samples0, 8), 8); + AE_S32_L_IP(samples0, (ae_f32 *)y, sizeof(ae_f32)); + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= (ae_int32x4 *)x_end) ? x - x_size : x; + y = (y >= (ae_int32x4 *)y_end) ? y - y_size : y; + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * level_multiplier_s32() - Process S32_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 32-bit signed integer PCM formats. The + * audio samples are copied from source to sink with gain defined in cd->gain. + * + * Return: Value zero for success, otherwise an error code. + */ +static int level_multiplier_s32(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + ae_valignx2 x_align; + ae_valignx2 y_align = AE_ZALIGN128(); + ae_f64 mult0; + ae_f64 mult1; + const ae_f32x2 gain = cd->gain; + ae_f32x2 samples0; + ae_f32x2 samples1; + ae_int32x4 const *x; + ae_int32x4 *y; + int32_t const *x_start, *x_end; + int32_t *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int remaining_samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int n, i; + + ret = source_get_data_s32(source, bytes, (const int32_t **)&x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, (int32_t **)&y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (remaining_samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - (int32_t *)x; + samples_without_wrap = y_end - (int32_t *)y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, remaining_samples); + x_align = AE_LA128_PP(x); + + /* Process with 64 bit loads and stores */ + n = samples_without_wrap >> 2; + for (i = 0; i < n; i++) { + AE_LA32X2X2_IP(samples0, samples1, x_align, x); + + AE_MULF32X2R_HH_LL(mult0, mult1, gain, samples0); + mult0 = AE_SLAI64(mult0, LEVEL_MULTIPLIER_S32_SHIFT); + mult1 = AE_SLAI64(mult1, LEVEL_MULTIPLIER_S32_SHIFT); + samples0 = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ + + AE_MULF32X2R_HH_LL(mult0, mult1, gain, samples1); + mult0 = AE_SLAI64(mult0, LEVEL_MULTIPLIER_S32_SHIFT); + mult1 = AE_SLAI64(mult1, LEVEL_MULTIPLIER_S32_SHIFT); + samples1 = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ + + AE_SA32X2X2_IP(samples0, samples1, y_align, y); + } + + AE_SA128POS_FP(y_align, y); + n = samples_without_wrap - (n << 2); + for (i = 0; i < n; i++) { + AE_L32_IP(samples0, (ae_f32 *)x, sizeof(ae_f32)); + mult0 = AE_MULF32R_HH(gain, samples0); + mult0 = AE_SLAI64(mult0, LEVEL_MULTIPLIER_S32_SHIFT); + samples0 = AE_ROUND32F48SSYM(mult0); + AE_S32_L_IP(samples0, (ae_f32 *)y, sizeof(ae_f32)); + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= (ae_int32x4 *)x_end) ? x - x_size : x; + y = (y >= (ae_int32x4 *)y_end) ? y - y_size : y; + remaining_samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S32LE */ + +/* This struct array defines the used processing functions for + * the PCM formats + */ +const struct level_multiplier_proc_fnmap level_multiplier_proc_fnmap[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, level_multiplier_s16 }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, level_multiplier_s24 }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, level_multiplier_s32 }, +#endif +}; + +/** + * level_multiplier_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +level_multiplier_func level_multiplier_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < ARRAY_SIZE(level_multiplier_proc_fnmap); i++) + if (src_fmt == level_multiplier_proc_fnmap[i].frame_fmt) + return level_multiplier_proc_fnmap[i].level_multiplier_proc_func; + + return NULL; +} + +#endif /* SOF_USE_MIN_HIFI(5, VOLUME) */ diff --git a/src/audio/level_multiplier/level_multiplier-ipc4.c b/src/audio/level_multiplier/level_multiplier-ipc4.c new file mode 100644 index 000000000000..02289d844f63 --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier-ipc4.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include "level_multiplier.h" + +LOG_MODULE_DECLARE(level_multiplier, CONFIG_SOF_LOG_LEVEL); + +/* IPC4 controls handler */ +__cold int level_multiplier_set_config(struct processing_module *mod, + uint32_t param_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 level_multiplier_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "Illegal control param_id %d.", param_id); + return -EINVAL; + } + + if (fragment_size != sizeof(int32_t)) { + comp_err(dev, "Illegal fragment size %d.", fragment_size); + return -EINVAL; + } + + memcpy_s(&cd->gain, sizeof(int32_t), fragment, sizeof(int32_t)); + comp_dbg(mod->dev, "Gain set to %d", cd->gain); + return 0; +} diff --git a/src/audio/level_multiplier/level_multiplier.c b/src/audio/level_multiplier/level_multiplier.c new file mode 100644 index 000000000000..4fca482ced72 --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <rtos/init.h> +#include "level_multiplier.h" + +/* UUID identifies the components. Use e.g. command uuidgen from package + * uuid-runtime, add it to uuid-registry.txt in SOF top level. + */ +SOF_DEFINE_REG_UUID(level_multiplier); + +/* Creates logging data for the component */ +LOG_MODULE_REGISTER(level_multiplier, CONFIG_SOF_LOG_LEVEL); + +/** + * level_multiplier_init() - Initialize the level_multiplier component. + * @mod: Pointer to module data. + * + * This function is called when the instance is created. The + * macro __cold informs that the code that is non-critical + * is loaded to slower but large DRAM. + * + * Return: Zero if success, otherwise error code. + */ +__cold static int level_multiplier_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct level_multiplier_comp_data *cd; + + comp_info(dev, "entry"); + + cd = mod_alloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + cd->gain = LEVEL_MULTIPLIER_GAIN_ONE; + return 0; +} + +/** + * level_multiplier_process() - The audio data processing function. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * This is the processing function that is called for scheduled + * pipelines. The processing is controlled by the enable switch. + * + * Return: Zero if success, otherwise error code. + */ +static int level_multiplier_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_source *source = sources[0]; /* One input */ + struct sof_sink *sink = sinks[0]; /* One output */ + int frames = source_get_data_frames_available(source); + int sink_frames = sink_get_free_frames(sink); + + comp_dbg(dev, "entry"); + + frames = MIN(frames, sink_frames); + frames = MIN(frames, dev->frames); + if (cd->gain != LEVEL_MULTIPLIER_GAIN_ONE) + /* Process the data with the requested gain. */ + return cd->level_multiplier_func(mod, source, sink, frames); + + /* Just copy from source to sink. */ + source_to_sink_copy(source, sink, true, frames * cd->frame_bytes); + return 0; +} + +/** + * level_multiplier_prepare() - Prepare the component for processing. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * Function prepare is called just before the pipeline is started. In + * this case the audio format parameters are for better code performance + * saved to component data to avoid to find out them in process. The + * processing function pointer is set to process the current audio format. + * + * Return: Value zero if success, otherwise error code. + */ +static int level_multiplier_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame source_format; + + comp_dbg(dev, "entry"); + + /* The processing example in this component supports one input and one + * output. Generally there can be more. + */ + if (num_of_sources != 1 || num_of_sinks != 1) + return -EINVAL; + + /* get source data format */ + cd->frame_bytes = source_get_frame_bytes(sources[0]); + cd->channels = source_get_channels(sources[0]); + source_format = source_get_frm_fmt(sources[0]); + + cd->level_multiplier_func = level_multiplier_find_proc_func(source_format); + if (!cd->level_multiplier_func) { + comp_err(dev, "No processing function found for format %d.", + source_format); + return -EINVAL; + } + + return 0; +} + +/** + * level_multiplier_reset() - Reset the component. + * @mod: Pointer to module data. + * + * The component reset is called when pipeline is stopped. The reset + * should return the component to same state as init. + * + * Return: Value zero, always success. + */ +static int level_multiplier_reset(struct processing_module *mod) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + memset(cd, 0, sizeof(*cd)); + cd->gain = LEVEL_MULTIPLIER_GAIN_ONE; + return 0; +} + +/** + * level_multiplier_free() - Free dynamic allocations. + * @mod: Pointer to module data. + * + * Component free is called when the pipelines are deleted. All + * dynamic allocations need to be freed here. The macro __cold + * instructs the build to locate this performance wise non-critical + * function to large and slower DRAM. + * + * Return: Value zero, always success. + */ +__cold static int level_multiplier_free(struct processing_module *mod) +{ + struct level_multiplier_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + comp_dbg(mod->dev, "entry"); + mod_free(mod, cd); + return 0; +} + +/* This defines the module operations */ +static const struct module_interface level_multiplier_interface = { + .init = level_multiplier_init, + .prepare = level_multiplier_prepare, + .process = level_multiplier_process, + .set_configuration = level_multiplier_set_config, + .reset = level_multiplier_reset, + .free = level_multiplier_free +}; + +/* This controls build of the module. If COMP_MODULE is selected in kconfig + * this is build as dynamically loadable module. + */ +#if CONFIG_COMP_LEVEL_MULTIPLIER_MODULE + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +SOF_LLEXT_MOD_ENTRY(level_multiplier, &level_multiplier_interface); + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("LEVEL_MULTIPLIER", level_multiplier_llext_entry, 1, + SOF_REG_UUID(level_multiplier), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(level_multiplier_tr, SOF_UUID(level_multiplier_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(level_multiplier_interface, level_multiplier_uuid, level_multiplier_tr); +SOF_MODULE_INIT(level_multiplier, sys_comp_module_level_multiplier_interface_init); + +#endif diff --git a/src/audio/level_multiplier/level_multiplier.h b/src/audio/level_multiplier/level_multiplier.h new file mode 100644 index 000000000000..e6df98c68c61 --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + */ +#ifndef __SOF_AUDIO_LEVEL_MULTIPLIER_H__ +#define __SOF_AUDIO_LEVEL_MULTIPLIER_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <stdbool.h> +#include <stdint.h> + +/** \brief Level multiplier gain Qx.y integer x number of bits including sign bit. + * With Q8.23 format the gain range is -138.47 to +48.17 dB. + */ +#define LEVEL_MULTIPLIER_QXY_X 9 + +/** \brief Level multiplier gain Qx.y fractional y number of bits. */ +#define LEVEL_MULTIPLIER_QXY_Y 23 + +/** \brief Level multiplier unity gain */ +#define LEVEL_MULTIPLIER_GAIN_ONE (1 << LEVEL_MULTIPLIER_QXY_Y) + +/** + * struct level_multiplier_func - Function call pointer for process function + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + */ +typedef int (*level_multiplier_func)(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames); + +/* Level_Multiplier component private data */ + +/** + * struct level_multiplier_comp_data + * @level_multiplier_func: Pointer to used processing function. + * @gain: Applied gain in linear Q9.23 format + * @source_format: Source samples format. + * @frame_bytes: Number of bytes in an audio frame. + * @channels: Channels count. + * @enable: Control processing on/off, on - reorder channels + */ +struct level_multiplier_comp_data { + level_multiplier_func level_multiplier_func; + int32_t gain; + int source_format; + int frame_bytes; + int channels; +}; + +/** + * struct level_multiplier_proc_fnmap - processing functions for frame formats + * @frame_fmt: Current frame format + * @level_multiplier_proc_func: Function pointer for the suitable processing function + */ +struct level_multiplier_proc_fnmap { + enum sof_ipc_frame frame_fmt; + level_multiplier_func level_multiplier_proc_func; +}; + +/** + * level_multiplier_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +level_multiplier_func level_multiplier_find_proc_func(enum sof_ipc_frame src_fmt); + +/** + * level_multiplier_set_config() - Handle controls set + * @mod: Pointer to module data. + * @param_id: Id to know control type, used to know ALSA control type. + * @pos: Position of the fragment in the large message. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * @response_size: Size of response. + * + * This function handles the real-time controls. The ALSA controls have the + * param_id set to indicate the control type. The control ID, from topology, + * is used to separate the controls instances of same type. In control payload + * the num_elems defines to how many channels the control is applied to. + * + * Return: Zero if success, otherwise error code. + */ + +#if CONFIG_IPC_MAJOR_3 +static inline int level_multiplier_set_config(struct processing_module *mod, + uint32_t param_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) +{ + /* No controls implementation for IPC3, add level_multiplier-ipc3.c + * handler if need. + */ + return 0; +} +#else +int level_multiplier_set_config(struct processing_module *mod, + uint32_t param_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); +#endif + +#endif // __SOF_AUDIO_LEVEL_MULTIPLIER_H__ diff --git a/src/audio/level_multiplier/level_multiplier.toml b/src/audio/level_multiplier/level_multiplier.toml new file mode 100644 index 000000000000..6eafd4efa8d7 --- /dev/null +++ b/src/audio/level_multiplier/level_multiplier.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Level Multiplier module config + [[module.entry]] + name = "LVLMULT" + uuid = UUIDREG_STR_LEVEL_MULTIPLIER + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/level_multiplier/llext/CMakeLists.txt b/src/audio/level_multiplier/llext/CMakeLists.txt new file mode 100644 index 000000000000..49d91bc6a7ce --- /dev/null +++ b/src/audio/level_multiplier/llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("level_multiplier" + SOURCES ../level_multiplier.c + ../level_multiplier-generic.c + ../level_multiplier-hifi3.c + ../level_multiplier-hifi5.c + ../level_multiplier-ipc4.c + LIB openmodules +) diff --git a/src/audio/level_multiplier/llext/llext.toml.h b/src/audio/level_multiplier/llext/llext.toml.h new file mode 100644 index 000000000000..019909d20697 --- /dev/null +++ b/src/audio/level_multiplier/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../level_multiplier.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/level_multiplier/tune/sof_level_multiplier_blobs.m b/src/audio/level_multiplier/tune/sof_level_multiplier_blobs.m new file mode 100644 index 000000000000..7312bae25444 --- /dev/null +++ b/src/audio/level_multiplier/tune/sof_level_multiplier_blobs.m @@ -0,0 +1,83 @@ +% Export configuration blobs for Level Multiplier +% +% This script creates configuration blobs for the Level Multiplier +% component to apply gains -40, -30, -20, -10, 0, 10, 20, 30, 40 dB. +% Run the script interactively from Octave shell with just command: +% +% sof_level_multiplier_blobs +% +% There are no arguments for the function. Or from SOF level directory +% with command: +% +% cd src/audio/level_multiplier/tune; octave sof_level_multiplier_blobs.m +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2025, Intel Corporation. + +function sof_level_multiplier_blobs() + + % Set the parameters here + sof_tools = '../../../../tools'; + sof_tplg = fullfile(sof_tools, 'topology/topology2'); + sof_tplg_level_multiplier = fullfile(sof_tplg, 'include/components/level_multiplier'); + sof_ctl_level_multiplier = fullfile(sof_tools, 'ctl/ipc4/level_multiplier'); + + sof_level_multiplier_paths(true); + + for param = -40:10:40 + gain_value = sof_level_multiplier_db2lin(param); + blob8 = sof_level_multiplier_build_blob(gain_value); + tplg2_fn = sprintf("%s/gain_%d_db.conf", sof_tplg_level_multiplier, param); + sof_tplg2_write(tplg2_fn, blob8, "level_multiplier_config", ... + "Exported with script sof_level_multiplier_blobs.m" , ... + "cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m"); + ctl_fn = sprintf("%s/gain_%d_db.txt", sof_ctl_level_multiplier, param); + sof_alsactl_write(ctl_fn, blob8); + end + + sof_level_multiplier_paths(false); +end + +function lin_value = sof_level_multiplier_db2lin(db) + scale = 2^23; + lin_value = int32(10^(db/20) * scale); +end + +function sof_level_multiplier_paths(enable) + + common = '../../../../tools/tune/common'; + if enable + addpath(common); + else + rmpath(common); + end +end + +function blob8 = sof_level_multiplier_build_blob(param_values) + + blob_type = 0; + blob_param_id = 1; + data_length = length(param_values); + data_size = 4 * data_length; + ipc_ver = 4; + [abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver, blob_type, blob_param_id); + blob_size = data_size + abi_size; + blob8 = uint8(zeros(1, blob_size)); + blob8(1:abi_size) = abi_bytes; + j = abi_size + 1; + for i = 1:data_length + blob8(j:j+3) = word2byte(param_values(i)); + j=j+4; + end +end + +function bytes = word2byte(word) + sh = [0 -8 -16 -24]; + bytes = uint8(zeros(1,4)); + bytes(1) = bitand(bitshift(word, sh(1)), 255); + bytes(2) = bitand(bitshift(word, sh(2)), 255); + bytes(3) = bitand(bitshift(word, sh(3)), 255); + bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/mfcc/CMakeLists.txt b/src/audio/mfcc/CMakeLists.txt new file mode 100644 index 000000000000..f8af79d1ca8a --- /dev/null +++ b/src/audio/mfcc/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_MFCC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/mfcc_llext) + add_dependencies(app mfcc) +else() + add_local_sources(sof mfcc.c mfcc_setup.c mfcc_common.c mfcc_generic.c mfcc_hifi4.c mfcc_hifi3.c) +endif() diff --git a/src/audio/mfcc/Kconfig b/src/audio/mfcc/Kconfig new file mode 100644 index 000000000000..f56cadb40de2 --- /dev/null +++ b/src/audio/mfcc/Kconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MFCC + tristate "MFCC component" + depends on COMP_MODULE_ADAPTER + select CORDIC_FIXED + select MATH_32BIT_FFT + select MATH_32BIT_MEL_FILTERBANK + select MATH_AUDITORY + select MATH_DCT + select MATH_DECIBELS + select MATH_FFT + select MATH_MATRIX + select MATH_WINDOW + select NATURAL_LOGARITHM_FIXED + select NUMBERS_NORM + select SQRT_FIXED + default m if LIBRARY_DEFAULT_MODULAR + default y + help + This option enables build of a Mel-frequency cepstral coefficients + (MFCC) audio features extractor component. It converts the input + audio stream into encoded audio data for cepstral coefficients. + The characteristic of the audio features are defined in the binary + control blob. Directory tools/tune/mfcc contains a tool to create + the configurations. diff --git a/src/audio/mfcc/README.md b/src/audio/mfcc/README.md new file mode 100644 index 000000000000..31f9c331e545 --- /dev/null +++ b/src/audio/mfcc/README.md @@ -0,0 +1,25 @@ +# MFCC Feature Extraction Architecture + +This directory contains the Mel-Frequency Cepstral Coefficients (MFCC) feature extractor. + +## Overview + +MFCC extracts audio features commonly used as inputs for machine learning models, such as wake-word detection or speech recognition. + +## Architecture Diagram + +```mermaid +graph LR + In[Audio Frame] --> Win[Windowing] + Win --> FFT[FFT] + FFT --> Mel[Mel Filterbank] + Mel --> DCT[DCT] + DCT --> Out[MFCC Output Features] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the MFCC component (`COMP_MFCC`) which selects necessary math libraries (`MATH_FFT`, `MATH_DCT`, `MATH_16BIT_MEL_FILTERBANK`, etc.). Depends on `COMP_MODULE_ADAPTER`. +- **CMakeLists.txt**: Compiles generic, common, and HIFI implementations (`mfcc_hifi3.c`, `mfcc_hifi4.c`). Provides support for Zephyr loadable extensions (`llext`). +- **mfcc.toml**: Specifies the topology configuration for the MFCC module (UUID, affinity, memory parameters, and pin formats). +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/mfcc.conf`, configuring a `mfcc` widget object of type `effect` with UUID `73:a7:10:db:a4:1a:ea:4c:a2:1f:2d:57:a5:c9:82:eb`. diff --git a/src/audio/mfcc/llext/CMakeLists.txt b/src/audio/mfcc/llext/CMakeLists.txt new file mode 100644 index 000000000000..688342751d75 --- /dev/null +++ b/src/audio/mfcc/llext/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("mfcc" + SOURCES ../mfcc.c + ../mfcc_setup.c + ../mfcc_common.c + ../mfcc_generic.c + ../mfcc_hifi3.c + ../mfcc_hifi4.c + LIB openmodules +) diff --git a/src/audio/mfcc/llext/llext.toml.h b/src/audio/mfcc/llext/llext.toml.h new file mode 100644 index 000000000000..0d358af2a041 --- /dev/null +++ b/src/audio/mfcc/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../mfcc.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/mfcc/mfcc.c b/src/audio/mfcc/mfcc.c new file mode 100644 index 000000000000..ea09d919009b --- /dev/null +++ b/src/audio/mfcc/mfcc.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/mfcc/mfcc_comp.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/mfcc.h> +#include <user/trace.h> +#include <rtos/init.h> +#include <rtos/string.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(mfcc, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(mfcc); + +__cold_rodata const struct mfcc_func_map mfcc_fm[] = { +#if CONFIG_FORMAT_S16LE + {SOF_IPC_FRAME_S16_LE, mfcc_s16_default}, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + {SOF_IPC_FRAME_S24_4LE, mfcc_s24_default}, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S32_LE, mfcc_s32_default}, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +static mfcc_func mfcc_find_func(enum sof_ipc_frame source_format, + enum sof_ipc_frame sink_format, + const struct mfcc_func_map *map, + int n) +{ + int i; + + /* Find suitable processing function from map. */ + for (i = 0; i < n; i++) { + if (source_format == map[i].source) + return map[i].func; + } + + return NULL; +} + +/* + * End of MFCC setup code. Next the standard component methods. + */ + +static int mfcc_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct mfcc_comp_data *cd = NULL; + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + /* Handler for configuration data */ + md->private = cd; + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "comp_data_blob_handler_new() failed."); + mod_free(mod, cd); + return -ENOMEM; + } + + return 0; +} + +static int mfcc_free(struct processing_module *mod) +{ + struct mfcc_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + mod_data_blob_handler_free(mod, cd->model_handler); + mfcc_free_buffers(mod); + mod_free(mod, cd); + return 0; +} + +static int mfcc_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct mfcc_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +static int mfcc_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 mfcc_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); +} + +static int mfcc_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 mfcc_comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers->data; + struct audio_stream *sink = output_buffers->data; + int frames = input_buffers->size; + + comp_dbg(mod->dev, "start"); + + frames = MIN(frames, cd->max_frames); + cd->mfcc_func(mod, input_buffers, output_buffers, frames); + + /* TODO: use module_update_buffer_position() from #6194 */ + input_buffers->consumed += audio_stream_frame_bytes(source) * frames; + output_buffers->size += audio_stream_frame_bytes(sink) * frames; + comp_dbg(mod->dev, "done"); + return 0; +} + +static int mfcc_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct mfcc_comp_data *cd = module_get_private_data(mod); + struct comp_buffer *sourceb; + struct comp_buffer *sinkb; + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame source_format; + enum sof_ipc_frame sink_format; + size_t data_size; + int ret; + + comp_info(dev, "entry"); + + /* MFCC component will only ever have 1 source and 1 sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink"); + return -ENOTCONN; + } + + /* get source data format */ + source_format = audio_stream_get_frm_fmt(&sourceb->stream); + + /* get sink data format and period bytes */ + sink_format = audio_stream_get_frm_fmt(&sinkb->stream); + comp_info(dev, "source_format = %d, sink_format = %d", source_format, sink_format); + + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + + /* Initialize MFCC, max_frames is set to dev->frames + 4 */ + if (cd->config && data_size > 0) { + ret = mfcc_setup(mod, dev->frames + 4, audio_stream_get_rate(&sourceb->stream), + audio_stream_get_channels(&sourceb->stream)); + if (ret < 0) { + comp_err(dev, "setup failed."); + goto err; + } + } + + cd->mfcc_func = mfcc_find_func(source_format, sink_format, mfcc_fm, ARRAY_SIZE(mfcc_fm)); + if (!cd->mfcc_func) { + comp_err(dev, "No proc func"); + ret = -EINVAL; + goto err; + } + + return 0; + +err: + comp_set_state(dev, COMP_TRIGGER_RESET); + return ret; +} + +static int mfcc_reset(struct processing_module *mod) +{ + struct mfcc_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + /* Reset to similar state as init() */ + cd->mfcc_func = NULL; + return 0; +} + +static const struct module_interface mfcc_interface = { + .init = mfcc_init, + .free = mfcc_free, + .set_configuration = mfcc_set_config, + .get_configuration = mfcc_get_config, + .process_audio_stream = mfcc_process, + .prepare = mfcc_prepare, + .reset = mfcc_reset, +}; + +#if CONFIG_COMP_MFCC_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("MFCC", &mfcc_interface, 1, SOF_REG_UUID(mfcc), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(mfcc_tr, SOF_UUID(mfcc_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(mfcc_interface, mfcc_uuid, mfcc_tr); +SOF_MODULE_INIT(mfcc, sys_comp_module_mfcc_interface_init); + +#endif diff --git a/src/audio/mfcc/mfcc.toml b/src/audio/mfcc/mfcc.toml new file mode 100644 index 000000000000..9cc6291840de --- /dev/null +++ b/src/audio/mfcc/mfcc.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + +REM # MFCC module config +[[module.entry]] +name = "MFCC" +uuid = UUIDREG_STR_MFCC +affinity_mask = "0x1" +instance_count = "40" +domain_types = "0" +load_type = LOAD_TYPE +module_type = "9" +auto_start = "0" +sched_caps = [1, 0x00008000] +REM # pin = [dir, type, sample rate, size, container, channel-cfg] +pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] +REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + +index = __COUNTER__ diff --git a/src/audio/mfcc/mfcc_common.c b/src/audio/mfcc/mfcc_common.c new file mode 100644 index 000000000000..1079864e9259 --- /dev/null +++ b/src/audio/mfcc/mfcc_common.c @@ -0,0 +1,511 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023-2026 Intel Corporation. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <sof/audio/mfcc/mfcc_comp.h> + +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/format.h> +#include <sof/math/auditory.h> +#include <sof/math/fft.h> +#include <sof/math/matrix.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> +#include <user/mfcc.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(mfcc_common, CONFIG_SOF_LOG_LEVEL); + +/* + * The main processing function for MFCC + */ + +static int mfcc_stft_process(const struct comp_dev *dev, struct mfcc_comp_data *cd) +{ + struct sof_mfcc_config *config = cd->config; + struct mfcc_state *state = &cd->state; + struct mfcc_buffer *buf = &state->buf; + struct mfcc_fft *fft = &state->fft; + int mel_scale_shift; + int input_shift; + int j; + int m; + int cc_count = 0; + int64_t s; + int32_t mel_value; + int32_t peak; + int32_t clamp_value; + + /* Phase 1, wait until whole fft_size is filled with valid data. This way + * first output cepstral coefficients originate from streamed data and not + * from buffers with zero data. + */ + comp_dbg(dev, "avail = %d", buf->s_avail); + if (state->waiting_fill) { + if (buf->s_avail < fft->fft_size) + return 0; + + state->waiting_fill = false; + } + + /* Phase 2, move first prev_size data to previous data buffer, remove + * samples from input buffer. + */ + if (!state->prev_samples_valid) { + mfcc_fill_prev_samples(buf, state->prev_data, state->prev_data_size); + state->prev_samples_valid = true; + } + + /* Check if enough samples in buffer for one FFT hop */ + m = buf->s_avail / fft->fft_hop_size; + if (m > 0) { + /* Clear FFT input buffer because it has been used as scratch */ + bzero(fft->fft_buf, fft->fft_buffer_size); + + /* Copy data to FFT input buffer from overlap buffer and from new samples buffer */ + mfcc_fill_fft_buffer(state); + + /* TODO: remove_dc_offset */ + + /* TODO: use_energy & raw_energy */ + + input_shift = 0; + + /* Window function */ + mfcc_apply_window(state, input_shift); + + /* TODO: use_energy & !raw_energy */ + + /* The FFT out buffer needs to be cleared to avoid to corrupt + * the output. TODO: check moving it to FFT lib. + */ + bzero(fft->fft_out, fft->fft_buffer_size); + + /* Compute FFT */ + fft_execute_32(fft->fft_plan, false); + + /* Initialize 16-bit Mel log spectrum buffer in Q9.7. The Mel values + * are converted from Q9.23 to Q9.7 for DCT matrix multiplication. + */ + mat_init_16b(state->mel_spectra, 1, state->dct.num_in, 7); /* Q9.7 */ + + /* Compensate FFT lib scaling to Mel log values, e.g. for 512 long FFT + * the fft_plan->len is 9. The scaling is 1/512. Subtract from input_shift it + * to add the missing "gain". + */ + mel_scale_shift = input_shift - fft->fft_plan->len; + psy_apply_mel_filterbank_32(&state->melfb, fft->fft_out, state->power_spectra, + state->mel_log_32, mel_scale_shift); + + if (state->mel_only) { + /* In Mel-only mode output Mel log spectra directly */ + cc_count += state->dct.num_in; + + /* Find peak mel value and track state->mmax in Q9.23 */ + if (config->dynamic_mmax) { + peak = state->mel_log_32[0]; + for (j = 1; j < state->dct.num_in; j++) { + if (state->mel_log_32[j] > peak) + peak = state->mel_log_32[j]; + } + + /* Jump to peak immediately if higher, decay otherwise */ + if (peak > state->mmax) { + state->mmax = peak; + } else { + /* Q9.23 * Q1.15, result Q9.23. The coefficient is small + * so no need for saturation. + */ + s = (int64_t)peak - state->mmax; + state->mmax += + Q_MULTSR_32X32(s, config->mmax_coef, 23, 15, 23); + } + } + + /* Clamp Mel values lower than mmax - top_db, add offset, and scale. + * Config top_db and mel_offset are Q9.7, shift to Q9.23. + */ + clamp_value = state->mmax - ((int32_t)config->top_db << 16); + for (j = 0; j < state->dct.num_in; j++) { + mel_value = state->mel_log_32[j]; + if (mel_value < clamp_value) + mel_value = clamp_value; + + /* Q9.23 * Q4.12, result Q9.23 */ + s = (int64_t)mel_value + ((int32_t)config->mel_offset << 16); + state->mel_log_32[j] = + sat_int32(Q_MULTSR_32X32(s, config->mel_scale, 23, 12, 23)); + } + + /* Store Q9.7 version in mel_spectra for s16 output mode */ + for (j = 0; j < state->dct.num_in; j++) + state->mel_spectra->data[j] = + sat_int16(state->mel_log_32[j] >> 16); + + /* Enable this to check mmax decay */ + comp_dbg(dev, "state->mmax = %d", state->mmax); + } else { + /* Convert Q9.23 to Q9.7 for 16-bit DCT */ + for (j = 0; j < state->dct.num_in; j++) + state->mel_spectra->data[j] = + sat_int16(state->mel_log_32[j] >> 16); + + /* Multiply Mel spectra with DCT matrix to get cepstral coefficients */ + mat_init_16b(state->cepstral_coef, 1, state->dct.num_out, 7); /* Q9.7 */ + mat_multiply(state->mel_spectra, state->dct.matrix, state->cepstral_coef); + + /* Apply cepstral lifter */ + if (state->lifter.cepstral_lifter != 0) { + mat_multiply_elementwise(state->cepstral_coef, state->lifter.matrix, + state->cepstral_coef); + } + + cc_count += state->dct.num_out; + } + } + + return cc_count; +} + +void mfcc_fill_fft_buffer(struct mfcc_state *state) +{ + struct mfcc_buffer *buf = &state->buf; + struct mfcc_fft *fft = &state->fft; + int32_t *d = &fft->fft_buf[fft->fft_fill_start_idx].real; + const int fft_elem_inc = sizeof(fft->fft_buf[0]) / sizeof(int32_t); + int16_t *prev = state->prev_data; + int16_t *prev_end = prev + state->prev_data_size; + int16_t *r = buf->r_ptr; + int copied; + int nmax; + int n; + int j; + + /* Copy overlapped samples from state buffer. The fft_buf has been + * cleared by caller so imaginary part remains zero. + */ + while (prev < prev_end) { + *d = *prev++; + d += fft_elem_inc; + } + + /* Copy hop size of new data from circular buffer */ + for (copied = 0; copied < fft->fft_hop_size; copied += n) { + nmax = fft->fft_hop_size - copied; + n = mfcc_buffer_samples_without_wrap(buf, r); + n = MIN(n, nmax); + for (j = 0; j < n; j++) { + *d = *r++; + d += fft_elem_inc; + } + r = mfcc_buffer_wrap(buf, r); + } + + buf->s_avail -= copied; + buf->s_free += copied; + buf->r_ptr = r; + + /* Copy for next time data back to overlap buffer */ + d = (int32_t *)&fft->fft_buf[fft->fft_fill_start_idx + fft->fft_hop_size].real; + prev = state->prev_data; + while (prev < prev_end) { + *prev++ = *d; + d += fft_elem_inc; + } +} + +#if CONFIG_FORMAT_S16LE +static int16_t *mfcc_sink_copy_zero_s16(const struct audio_stream *sink, int16_t *w_ptr, + int samples) +{ + int copied; + int nmax; + int n; + + for (copied = 0; copied < samples; copied += n) { + nmax = samples - copied; + n = audio_stream_samples_without_wrap_s16(sink, w_ptr); + n = MIN(n, nmax); + memset(w_ptr, 0, n * sizeof(int16_t)); + w_ptr = audio_stream_wrap(sink, w_ptr + n); + } + + return w_ptr; +} + +static int16_t *mfcc_sink_copy_data_s16(const struct audio_stream *sink, int16_t *w_ptr, + int samples, int16_t *r_ptr) +{ + int copied; + int nmax; + int n; + + for (copied = 0; copied < samples; copied += n) { + nmax = samples - copied; + n = audio_stream_samples_without_wrap_s16(sink, w_ptr); + n = MIN(n, nmax); + /* Not using memcpy_s() due to speed need */ + memcpy(w_ptr, r_ptr, n * sizeof(int16_t)); + w_ptr = audio_stream_wrap(sink, w_ptr + n); + r_ptr += n; + } + + return w_ptr; +} + +void mfcc_s16_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *sink = bsink->data; + struct mfcc_comp_data *cd = module_get_private_data(mod); + struct mfcc_state *state = &cd->state; + struct mfcc_buffer *buf = &cd->state.buf; + uint32_t magic = MFCC_MAGIC; + int16_t *w_ptr = audio_stream_get_wptr(sink); + const int num_magic = 2; + int num_ceps; + int sink_samples; + int to_copy; + + /* Get samples from source buffer */ + mfcc_source_copy_s16(bsource, buf, &state->emph, frames, state->source_channel); + + /* Run STFT and processing after FFT: Mel auditory filter and DCT. */ + num_ceps = mfcc_stft_process(mod->dev, cd); + + /* If new output produced, set up pointer into scratch data and mark magic pending */ + if (num_ceps > 0) { + if (state->mel_only) + state->out_data_ptr = state->mel_spectra->data; + else + state->out_data_ptr = state->cepstral_coef->data; + + state->out_remain = num_ceps; + state->magic_pending = true; + } + + /* Write to sink, limited by period size */ + sink_samples = frames * audio_stream_get_channels(sink); + + /* Write magic word first if pending */ + if (state->magic_pending && sink_samples >= num_magic) { + w_ptr = mfcc_sink_copy_data_s16(sink, w_ptr, num_magic, (int16_t *)&magic); + sink_samples -= num_magic; + state->magic_pending = false; + } + + /* Write cepstral/mel data from scratch buffer */ + to_copy = MIN(state->out_remain, sink_samples); + if (to_copy > 0) { + w_ptr = mfcc_sink_copy_data_s16(sink, w_ptr, to_copy, state->out_data_ptr); + state->out_data_ptr += to_copy; + state->out_remain -= to_copy; + sink_samples -= to_copy; + } + + /* Zero-fill remaining sink samples */ + w_ptr = mfcc_sink_copy_zero_s16(sink, w_ptr, sink_samples); +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +static int32_t *mfcc_sink_copy_zero_s32(const struct audio_stream *sink, int32_t *w_ptr, + int samples) +{ + int copied; + int nmax; + int n; + + for (copied = 0; copied < samples; copied += n) { + nmax = samples - copied; + n = audio_stream_samples_without_wrap_s32(sink, w_ptr); + n = MIN(n, nmax); + memset(w_ptr, 0, n * sizeof(int32_t)); + w_ptr = audio_stream_wrap(sink, w_ptr + n); + } + + return w_ptr; +} + +static int32_t *mfcc_sink_copy_data_s32(const struct audio_stream *sink, int32_t *w_ptr, + int samples, int32_t *r_ptr) +{ + int copied; + int nmax; + int n; + + for (copied = 0; copied < samples; copied += n) { + nmax = samples - copied; + n = audio_stream_samples_without_wrap_s32(sink, w_ptr); + n = MIN(n, nmax); + /* Not using memcpy_s() due to speed need */ + memcpy(w_ptr, r_ptr, n * sizeof(int32_t)); + w_ptr = audio_stream_wrap(sink, w_ptr + n); + r_ptr += n; + } + + return w_ptr; +} +#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S24LE +void mfcc_s24_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *sink = bsink->data; + struct mfcc_comp_data *cd = module_get_private_data(mod); + struct mfcc_state *state = &cd->state; + struct mfcc_buffer *buf = &cd->state.buf; + uint32_t magic = MFCC_MAGIC; + int32_t *w_ptr = audio_stream_get_wptr(sink); + const int num_magic = 1; /* one int32_t word for magic */ + int num_ceps; + int sink_samples; + int remain_s32; + int to_copy; + int k; + + /* Get samples from source buffer */ + mfcc_source_copy_s24(bsource, buf, &state->emph, frames, state->source_channel); + + /* Run STFT and processing after FFT */ + num_ceps = mfcc_stft_process(mod->dev, cd); + + /* If new output produced, set up pointer into scratch data */ + if (num_ceps > 0) { + if (state->mel_only) { + /* Convert mel_log_32 from Q9.23 to Q9.15 in-place */ + for (k = 0; k < num_ceps; k++) + state->mel_log_32[k] >>= 8; + + state->out_data_ptr_32 = state->mel_log_32; + } else { + state->out_data_ptr = state->cepstral_coef->data; + } + + state->out_remain = num_ceps; + state->magic_pending = true; + } + + /* Write to sink, limited by period size */ + sink_samples = frames * audio_stream_get_channels(sink); + + /* Write magic word first if pending */ + if (state->magic_pending && sink_samples >= num_magic) { + w_ptr = mfcc_sink_copy_data_s32(sink, w_ptr, num_magic, (int32_t *)&magic); + sink_samples -= num_magic; + state->magic_pending = false; + } + + if (state->mel_only) { + /* Write 32-bit mel data Q9.15, one value per int32_t */ + to_copy = MIN(state->out_remain, sink_samples); + if (to_copy > 0) { + w_ptr = mfcc_sink_copy_data_s32(sink, w_ptr, to_copy, + state->out_data_ptr_32); + state->out_data_ptr_32 += to_copy; + state->out_remain -= to_copy; + sink_samples -= to_copy; + } + } else { + /* Write cepstral data packed as int32_t from scratch buffer */ + remain_s32 = (state->out_remain + 1) / 2; + to_copy = MIN(remain_s32, sink_samples); + if (to_copy > 0) { + w_ptr = mfcc_sink_copy_data_s32(sink, w_ptr, to_copy, + (int32_t *)state->out_data_ptr); + state->out_data_ptr += to_copy * 2; + state->out_remain -= to_copy * 2; + if (state->out_remain < 0) + state->out_remain = 0; + + sink_samples -= to_copy; + } + } + + /* Zero-fill remaining sink samples */ + w_ptr = mfcc_sink_copy_zero_s32(sink, w_ptr, sink_samples); +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +void mfcc_s32_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *sink = bsink->data; + struct mfcc_comp_data *cd = module_get_private_data(mod); + struct mfcc_state *state = &cd->state; + struct mfcc_buffer *buf = &cd->state.buf; + uint32_t magic = MFCC_MAGIC; + int32_t *w_ptr = audio_stream_get_wptr(sink); + const int num_magic = 1; /* one int32_t word for magic */ + int num_ceps; + int sink_samples; + int remain_s32; + int to_copy; + + /* Get samples from source buffer */ + mfcc_source_copy_s32(bsource, buf, &state->emph, frames, state->source_channel); + + /* Run STFT and processing after FFT */ + num_ceps = mfcc_stft_process(mod->dev, cd); + + /* If new output produced, set up pointer into scratch data */ + if (num_ceps > 0) { + if (state->mel_only) { + state->out_data_ptr_32 = state->mel_log_32; + } else { + state->out_data_ptr = state->cepstral_coef->data; + } + + state->out_remain = num_ceps; + state->magic_pending = true; + } + + /* Write to sink, limited by period size */ + sink_samples = frames * audio_stream_get_channels(sink); + + /* Write magic word first if pending */ + if (state->magic_pending && sink_samples >= num_magic) { + w_ptr = mfcc_sink_copy_data_s32(sink, w_ptr, num_magic, (int32_t *)&magic); + sink_samples -= num_magic; + state->magic_pending = false; + } + + if (state->mel_only) { + /* Write 32-bit mel data Q9.23, one value per int32_t */ + to_copy = MIN(state->out_remain, sink_samples); + if (to_copy > 0) { + w_ptr = mfcc_sink_copy_data_s32(sink, w_ptr, to_copy, + state->out_data_ptr_32); + state->out_data_ptr_32 += to_copy; + state->out_remain -= to_copy; + sink_samples -= to_copy; + } + } else { + /* Write cepstral data packed as int32_t from scratch buffer */ + remain_s32 = (state->out_remain + 1) / 2; + to_copy = MIN(remain_s32, sink_samples); + if (to_copy > 0) { + w_ptr = mfcc_sink_copy_data_s32(sink, w_ptr, to_copy, + (int32_t *)state->out_data_ptr); + state->out_data_ptr += to_copy * 2; + state->out_remain -= to_copy * 2; + if (state->out_remain < 0) + state->out_remain = 0; + + sink_samples -= to_copy; + } + } + + /* Zero-fill remaining sink samples */ + w_ptr = mfcc_sink_copy_zero_s32(sink, w_ptr, sink_samples); +} +#endif /* CONFIG_FORMAT_S32LE */ diff --git a/src/audio/mfcc/mfcc_generic.c b/src/audio/mfcc/mfcc_generic.c new file mode 100644 index 000000000000..73ac49272ed4 --- /dev/null +++ b/src/audio/mfcc/mfcc_generic.c @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/mfcc/mfcc_comp.h> +#ifdef MFCC_GENERIC + +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/matrix.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> +#include <user/mfcc.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* + * MFCC algorithm code + */ + +void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data, + int prev_data_length) +{ + /* Fill prev_data from input buffer */ + int16_t *r = buf->r_ptr; + int16_t *p = prev_data; + int copied; + int nmax; + int n; + + for (copied = 0; copied < prev_data_length; copied += n) { + nmax = prev_data_length - copied; + n = mfcc_buffer_samples_without_wrap(buf, r); + n = MIN(n, nmax); + memcpy(p, r, sizeof(int16_t) * n); /* Not using memcpy_s() due to speed need */ + p += n; + r += n; + r = mfcc_buffer_wrap(buf, r); + } + + buf->s_avail -= copied; + buf->s_free += copied; + buf->r_ptr = r; +} + +void mfcc_apply_window(struct mfcc_state *state, int input_shift) +{ + struct mfcc_fft *fft = &state->fft; + int j; + int i = fft->fft_fill_start_idx; + + /* TODO: Use proper multiply and saturate function to make sure no overflows */ + int s = input_shift + 1; /* To convert 16 -> 32 with Q1.15 x Q1.15 -> Q30 -> Q31 */ + + for (j = 0; j < fft->fft_size; j++) + fft->fft_buf[i + j].real = (fft->fft_buf[i + j].real * state->window[j]) << s; +} + +#if CONFIG_FORMAT_S16LE +void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int32_t s; + int16_t *x0; + int16_t *x = audio_stream_get_rptr(source); + int16_t *w = buf->w_ptr; + int copied; + int nmax; + int n1; + int n2; + int n; + int i; + 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. + */ + for (copied = 0; copied < frames; copied += n) { + nmax = frames - copied; + n1 = audio_stream_frames_without_wrap(source, x); + n2 = mfcc_buffer_samples_without_wrap(buf, w); + n = MIN(n1, n2); + n = MIN(n, nmax); + x0 = x + source_channel; + for (i = 0; i < n; i++) { + if (emph->enable) { + /* Q1.15 x Q1.15 -> Q2.30 */ + s = (int32_t)emph->delay * emph->coef + Q_SHIFT_LEFT(*x0, 15, 30); + *w = sat_int16(Q_SHIFT_RND(s, 30, 15)); + emph->delay = *x0; + } else { + *w = *x0; + } + x0 += num_channels; + w++; + } + + x = audio_stream_wrap(source, x + n * audio_stream_get_channels(source)); + w = mfcc_buffer_wrap(buf, w); + } + buf->s_avail += copied; + buf->s_free -= copied; + buf->w_ptr = w; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + +void mfcc_source_copy_s24(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int32_t tmp, s; + int32_t *x0; + int32_t *x = audio_stream_get_rptr(source); + int16_t *w = buf->w_ptr; + int copied; + int nmax; + int n1; + int n2; + int n; + int i; + 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. + * S24_4LE data is in 32-bit container, shift left by 8 to Q1.31, + * then convert to Q1.15 with rounding. + */ + for (copied = 0; copied < frames; copied += n) { + nmax = frames - copied; + n1 = audio_stream_frames_without_wrap(source, x); + n2 = mfcc_buffer_samples_without_wrap(buf, w); + n = MIN(n1, n2); + n = MIN(n, nmax); + x0 = x + source_channel; + for (i = 0; i < n; i++) { + if (emph->enable) { + /* Convert to Q1.31, ignore highest byte */ + s = (int32_t)((uint32_t)*x0 << 8); + /* Q1.15 x Q1.15 -> Q2.30 */ + tmp = (int32_t)emph->delay * emph->coef + Q_SHIFT(s, 31, 30); + *w = sat_int16(Q_SHIFT_RND(tmp, 30, 15)); + emph->delay = sat_int16(Q_SHIFT_RND(s, 31, 15)); + } else { + /* Convert to Q1.31, ignore highest byte */ + s = (int32_t)((uint32_t)*x0 << 8); + *w = sat_int16(Q_SHIFT_RND(s, 31, 15)); + } + x0 += num_channels; + w++; + } + + x = audio_stream_wrap(source, x + n * audio_stream_get_channels(source)); + w = mfcc_buffer_wrap(buf, w); + } + buf->s_avail += copied; + buf->s_free -= copied; + buf->w_ptr = w; +} + +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + +void mfcc_source_copy_s32(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int32_t s; + int32_t *x0; + int32_t *x = audio_stream_get_rptr(source); + int16_t *w = buf->w_ptr; + int copied; + int nmax; + int n1; + int n2; + int n; + int i; + 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. + * S32 data is in 32-bit container, shift right by 16 to get 16-bit. + */ + for (copied = 0; copied < frames; copied += n) { + nmax = frames - copied; + n1 = audio_stream_frames_without_wrap(source, x); + n2 = mfcc_buffer_samples_without_wrap(buf, w); + n = MIN(n1, n2); + n = MIN(n, nmax); + x0 = x + source_channel; + for (i = 0; i < n; i++) { + if (emph->enable) { + /* Q1.15 x Q1.15 -> Q2.30 */ + s = (int32_t)emph->delay * emph->coef + Q_SHIFT(*x0, 31, 30); + *w = sat_int16(Q_SHIFT_RND(s, 30, 15)); + emph->delay = sat_int16(Q_SHIFT_RND(*x0, 31, 15)); + } else { + *w = sat_int16(Q_SHIFT_RND(*x0, 31, 15)); + } + x0 += num_channels; + w++; + } + + x = audio_stream_wrap(source, x + n * audio_stream_get_channels(source)); + w = mfcc_buffer_wrap(buf, w); + } + buf->s_avail += copied; + buf->s_free -= copied; + buf->w_ptr = w; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#endif /* MFCC_GENERIC */ diff --git a/src/audio/mfcc/mfcc_hifi3.c b/src/audio/mfcc/mfcc_hifi3.c new file mode 100644 index 000000000000..80c384ad6c64 --- /dev/null +++ b/src/audio/mfcc/mfcc_hifi3.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023-2026 Intel Corporation. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <sof/audio/mfcc/mfcc_comp.h> + +#ifdef MFCC_HIFI3 + +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/matrix.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> +#include <user/mfcc.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <xtensa/tie/xt_hifi3.h> + +/* Setup circular for buffer 0 */ +static inline void set_circular_buf0(const void *start, const void *end) +{ + AE_SETCBEGIN0(start); + AE_SETCEND0(end); +} + +/* + * MFCC algorithm code + */ + +#if CONFIG_FORMAT_S16LE +void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int copied; + int nmax; + int n; + int i; + int num_channels = audio_stream_get_channels(source); + ae_int16 *in; + ae_int16 *x = (ae_int16 *)audio_stream_get_rptr(source); + ae_int16 *out = (ae_int16 *)buf->w_ptr; + ae_int16x4 sample; + ae_int32x2 temp; + ae_int16x4 coef = emph->coef; + ae_int16x4 delay; + const int in_inc = sizeof(ae_int16) * num_channels; + + /* Copy from source to pre-buffer for FFT. + * The pre-emphasis filter is done in this step. + */ + for (copied = 0; copied < frames; copied += n) { + nmax = frames - copied; + n = audio_stream_frames_without_wrap(source, x); + n = MIN(n, nmax); + nmax = mfcc_buffer_samples_without_wrap(buf, (int16_t *)out); + n = MIN(n, nmax); + in = x + source_channel; + if (emph->enable) { + delay = emph->delay; + for (i = 0; i < n; i++) { + AE_L16_XP(sample, in, in_inc); + /* Q1.15 -> Q1.31 */ + temp = AE_CVT32X2F16_10(sample); + AE_MULAF16SS_00(temp, delay, coef); + delay = sample; + sample = AE_ROUND16X4F32SSYM(temp, temp); + /* 2 = sizeof(ae_int16)*/ + AE_S16_0_IP(sample, out, 2); + } + emph->delay = delay; + + } else { + for (i = 0; i < n; i++) { + AE_L16_XP(sample, in, in_inc); + /* 2 = sizeof(ae_int16)*/ + AE_S16_0_IP(sample, out, 2); + } + } + + x = audio_stream_wrap(source, x + n * num_channels); + out = (ae_int16 *)mfcc_buffer_wrap(buf, (int16_t *)out); + } + buf->s_avail += copied; + buf->s_free -= copied; + buf->w_ptr = (int16_t *)out; +} +#endif /* CONFIG_FORMAT_S16LE */ + +void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data, + int prev_data_length) +{ + /* Fill prev_data from input buffer */ + ae_int32 *out = (ae_int32 *)prev_data; + ae_int32 *in = (ae_int32 *)buf->r_ptr; + ae_int32x2 in_sample; + ae_int16x4 sample; + const int inc = sizeof(ae_int32); + int n = prev_data_length >> 1; + int i; + + /* Set buf as circular buffer 0 */ + set_circular_buf0(buf->addr, buf->end_addr); + + /* very strange this align load is unexpected + * so use load a 32bit to replace 16x4 align load. + */ + for (i = 0; i < n; i++) { + AE_L32_XC(in_sample, in, inc); + /* sizeof(ae_int32) = 4 */ + AE_S32_L_IP(in_sample, out, 4); + } + if (prev_data_length & 0x01) { + AE_L16_XC(sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_S16_0_IP(sample, (ae_int16 *)out, sizeof(ae_int16)); + } + + buf->s_avail -= prev_data_length; + buf->s_free += prev_data_length; + buf->r_ptr = (void *)in; /* int16_t pointer but direct cast is not possible */ +} + +void mfcc_apply_window(struct mfcc_state *state, int input_shift) +{ + struct mfcc_fft *fft = &state->fft; + const int fft_inc = sizeof(fft->fft_buf[0]); + ae_int16 *win_in = (ae_int16 *)state->window; + const int win_inc = sizeof(ae_int16); + ae_int32x2 temp; + ae_int16x4 win; + int j; + + ae_int32 *fft_in = (ae_int32 *)&fft->fft_buf[fft->fft_fill_start_idx].real; + ae_int32x2 sample; + + for (j = 0; j < fft->fft_size; j++) { + AE_L32_IP(sample, fft_in, 0); + AE_L16_XP(win, win_in, win_inc); + /* Data is 16-bit in 32-bit container, shift to Q1.31 for fractional multiply */ + sample = AE_SLAI32S(sample, 16); + temp = AE_MULFP32X16X2RS_L(sample, win); + temp = AE_SLAA32S(temp, input_shift); + AE_S32_L_XP(temp, fft_in, fft_inc); + } +} + +#if CONFIG_FORMAT_S24LE +void mfcc_source_copy_s24(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int copied; + int nmax; + int n; + int i; + int num_channels = audio_stream_get_channels(source); + ae_int32 *in; + ae_int32 *x = (ae_int32 *)audio_stream_get_rptr(source); + ae_int16 *out = (ae_int16 *)buf->w_ptr; + ae_int32x2 sample32; + ae_int16x4 sample; + ae_int32x2 temp; + ae_int16x4 coef = emph->coef; + ae_int16x4 delay; + const int in_inc = sizeof(ae_int32) * num_channels; + + for (copied = 0; copied < frames; copied += n) { + nmax = frames - copied; + n = audio_stream_frames_without_wrap(source, x); + n = MIN(n, nmax); + nmax = mfcc_buffer_samples_without_wrap(buf, (int16_t *)out); + n = MIN(n, nmax); + in = x + source_channel; + if (emph->enable) { + delay = emph->delay; + for (i = 0; i < n; i++) { + AE_L32_XP(sample32, in, in_inc); + /* Shift left by 8 to sign-extend to Q1.31 */ + sample32 = AE_SLAI32(sample32, 8); + /* Then shift right by 16 to get 16-bit */ + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + /* Q1.15 -> Q1.31 */ + temp = AE_CVT32X2F16_10(sample); + AE_MULAF16SS_00(temp, delay, coef); + delay = sample; + sample = AE_ROUND16X4F32SSYM(temp, temp); + AE_S16_0_IP(sample, out, 2); + } + emph->delay = delay; + } else { + for (i = 0; i < n; i++) { + AE_L32_XP(sample32, in, in_inc); + /* Shift left by 8 to sign-extend to Q1.31 */ + sample32 = AE_SLAI32(sample32, 8); + /* Then shift right by 16 to get 16-bit */ + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + AE_S16_0_IP(sample, out, 2); + } + } + + x = audio_stream_wrap(source, x + n * num_channels); + out = (ae_int16 *)mfcc_buffer_wrap(buf, (int16_t *)out); + } + buf->s_avail += copied; + buf->s_free -= copied; + buf->w_ptr = (int16_t *)out; +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +void mfcc_source_copy_s32(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int copied; + int nmax; + int n; + int i; + int num_channels = audio_stream_get_channels(source); + ae_int32 *in; + ae_int32 *x = (ae_int32 *)audio_stream_get_rptr(source); + ae_int16 *out = (ae_int16 *)buf->w_ptr; + ae_int32x2 sample32; + ae_int16x4 sample; + ae_int32x2 temp; + ae_int16x4 coef = emph->coef; + ae_int16x4 delay; + const int in_inc = sizeof(ae_int32) * num_channels; + + for (copied = 0; copied < frames; copied += n) { + nmax = frames - copied; + n = audio_stream_frames_without_wrap(source, x); + n = MIN(n, nmax); + nmax = mfcc_buffer_samples_without_wrap(buf, (int16_t *)out); + n = MIN(n, nmax); + in = x + source_channel; + if (emph->enable) { + delay = emph->delay; + for (i = 0; i < n; i++) { + AE_L32_XP(sample32, in, in_inc); + /* S32: shift right by 16 to get 16-bit */ + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + /* Q1.15 -> Q1.31 */ + temp = AE_CVT32X2F16_10(sample); + AE_MULAF16SS_00(temp, delay, coef); + delay = sample; + sample = AE_ROUND16X4F32SSYM(temp, temp); + AE_S16_0_IP(sample, out, 2); + } + emph->delay = delay; + } else { + for (i = 0; i < n; i++) { + AE_L32_XP(sample32, in, in_inc); + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + AE_S16_0_IP(sample, out, 2); + } + } + + x = audio_stream_wrap(source, x + n * num_channels); + out = (ae_int16 *)mfcc_buffer_wrap(buf, (int16_t *)out); + } + buf->s_avail += copied; + buf->s_free -= copied; + buf->w_ptr = (int16_t *)out; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#endif /* MFCC_HIFI3 */ diff --git a/src/audio/mfcc/mfcc_hifi4.c b/src/audio/mfcc/mfcc_hifi4.c new file mode 100644 index 000000000000..63986870793b --- /dev/null +++ b/src/audio/mfcc/mfcc_hifi4.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023-2026 Intel Corporation. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <sof/audio/mfcc/mfcc_comp.h> + +#ifdef MFCC_HIFI4 + +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/matrix.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> +#include <user/mfcc.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <xtensa/tie/xt_hifi4.h> + +/* Setup circular buffer 0 */ +static inline void set_circular_buf0(const void *start, const void *end) +{ + AE_SETCBEGIN0(start); + AE_SETCEND0(end); +} + +/* Setup circular for buffer 1 */ +static inline void set_circular_buf1(const void *start, const void *end) +{ + AE_SETCBEGIN1(start); + AE_SETCEND1(end); +} + +/* + * MFCC algorithm code + */ + +#if CONFIG_FORMAT_S16LE +void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int num_channels = audio_stream_get_channels(source); + ae_int16 *in = (ae_int16 *)source->r_ptr + source_channel; + ae_int16 *out = (ae_int16 *)buf->w_ptr; + ae_int16x4 sample; + ae_int32x2 temp; + ae_int16x4 coef; + ae_int16x4 delay; + const int in_inc = sizeof(ae_int16) * num_channels; + const int out_inc = sizeof(ae_int16); + int i; + + set_circular_buf1(buf->addr, buf->end_addr); + set_circular_buf0(source->addr, source->end_addr); + + /* Copy from source to pre-buffer for FFT. + * The pre-emphasis filter is done in this step. + */ + if (emph->enable) { + delay = emph->delay; + coef = emph->coef; + for (i = 0; i < frames; i++) { + AE_L16_XC(sample, in, in_inc); + + /* Q1.15 -> Q1.31 */ + temp = AE_CVT32X2F16_10(sample); + AE_MULAF16SS_00(temp, delay, coef); + delay = sample; + sample = AE_ROUND16X4F32SSYM(temp, temp); + AE_S16_0_XC1(sample, out, out_inc); + } + emph->delay = delay; + } else { + for (i = 0; i < frames; i++) { + AE_L16_XC(sample, in, in_inc); + AE_S16_0_XC1(sample, out, out_inc); + } + } + + buf->s_avail += frames; + buf->s_free -= frames; + buf->w_ptr = (int16_t *)out; +} +#endif /* CONFIG_FORMAT_S16LE */ + +void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data, + int prev_data_length) +{ + /* Fill prev_data from input buffer */ + ae_int32 *out = (ae_int32 *)prev_data; + ae_int32 *in = (ae_int32 *)buf->r_ptr; + ae_int32x2 in_sample; + ae_int16x4 sample; + const int inc = sizeof(ae_int32); + int n = prev_data_length >> 1; + int i; + + /* Set buf as circular buffer 0 */ + set_circular_buf0(buf->addr, buf->end_addr); + + /* very strange this align load is unexpected + * so use load a 32bit to replace 16x4 align load. + */ + for (i = 0; i < n; i++) { + AE_L32_XC(in_sample, in, inc); + /* sizeof(ae_int32) = 4 */ + AE_S32_L_IP(in_sample, out, 4); + } + if (prev_data_length & 0x01) { + AE_L16_XC(sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_S16_0_IP(sample, (ae_int16 *)out, sizeof(ae_int16)); + } + + buf->s_avail -= prev_data_length; + buf->s_free += prev_data_length; + buf->r_ptr = (int16_t *)in; +} + +void mfcc_apply_window(struct mfcc_state *state, int input_shift) +{ + struct mfcc_fft *fft = &state->fft; + const int fft_inc = sizeof(fft->fft_buf[0]); + ae_int16 *win_in = (ae_int16 *)state->window; + const int win_inc = sizeof(ae_int16); + ae_int32x2 temp; + ae_int16x4 win; + int j; + + ae_int32 *fft_in = (ae_int32 *)&fft->fft_buf[fft->fft_fill_start_idx].real; + ae_int32x2 sample; + + for (j = 0; j < fft->fft_size; j++) { + AE_L32_IP(sample, fft_in, 0); + AE_L16_XP(win, win_in, win_inc); + /* Data is 16-bit in 32-bit container, shift to Q1.31 for fractional multiply */ + sample = AE_SLAI32S(sample, 16); + temp = AE_MULFP32X16X2RS_L(sample, win); + temp = AE_SLAA32S(temp, input_shift); + AE_S32_L_XP(temp, fft_in, fft_inc); + } +} + +#if CONFIG_FORMAT_S24LE +void mfcc_source_copy_s24(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int num_channels = audio_stream_get_channels(source); + ae_int32 *in = (ae_int32 *)source->r_ptr + source_channel; + ae_int16 *out = (ae_int16 *)buf->w_ptr; + ae_int32x2 sample32; + ae_int16x4 sample; + ae_int32x2 temp; + ae_int16x4 coef; + ae_int16x4 delay; + const int in_inc = sizeof(ae_int32) * num_channels; + const int out_inc = sizeof(ae_int16); + int i; + + set_circular_buf1(buf->addr, buf->end_addr); + set_circular_buf0(source->addr, source->end_addr); + + if (emph->enable) { + delay = emph->delay; + coef = emph->coef; + for (i = 0; i < frames; i++) { + AE_L32_XC(sample32, in, in_inc); + /* Shift left by 8 to sign-extend to Q1.31 */ + sample32 = AE_SLAI32(sample32, 8); + /* Then shift right by 16 to get 16-bit */ + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + /* Q1.15 -> Q1.31 */ + temp = AE_CVT32X2F16_10(sample); + AE_MULAF16SS_00(temp, delay, coef); + delay = sample; + sample = AE_ROUND16X4F32SSYM(temp, temp); + AE_S16_0_XC1(sample, out, out_inc); + } + emph->delay = delay; + } else { + for (i = 0; i < frames; i++) { + AE_L32_XC(sample32, in, in_inc); + /* Shift left by 8 to sign-extend to Q1.31 */ + sample32 = AE_SLAI32(sample32, 8); + /* Then shift right by 16 to get 16-bit */ + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + AE_S16_0_XC1(sample, out, out_inc); + } + } + + buf->s_avail += frames; + buf->s_free -= frames; + buf->w_ptr = (int16_t *)out; +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +void mfcc_source_copy_s32(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel) +{ + struct audio_stream *source = bsource->data; + int num_channels = audio_stream_get_channels(source); + ae_int32 *in = (ae_int32 *)source->r_ptr + source_channel; + ae_int16 *out = (ae_int16 *)buf->w_ptr; + ae_int32x2 sample32; + ae_int16x4 sample; + ae_int32x2 temp; + ae_int16x4 coef; + ae_int16x4 delay; + const int in_inc = sizeof(ae_int32) * num_channels; + const int out_inc = sizeof(ae_int16); + int i; + + set_circular_buf1(buf->addr, buf->end_addr); + set_circular_buf0(source->addr, source->end_addr); + + if (emph->enable) { + delay = emph->delay; + coef = emph->coef; + for (i = 0; i < frames; i++) { + AE_L32_XC(sample32, in, in_inc); + /* S32: shift right by 16 to get 16-bit */ + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + /* Q1.15 -> Q1.31 */ + temp = AE_CVT32X2F16_10(sample); + AE_MULAF16SS_00(temp, delay, coef); + delay = sample; + sample = AE_ROUND16X4F32SSYM(temp, temp); + AE_S16_0_XC1(sample, out, out_inc); + } + emph->delay = delay; + } else { + for (i = 0; i < frames; i++) { + AE_L32_XC(sample32, in, in_inc); + sample32 = AE_SRAI32(sample32, 16); + sample = AE_SAT16X4(sample32, sample32); + AE_S16_0_XC1(sample, out, out_inc); + } + } + + buf->s_avail += frames; + buf->s_free -= frames; + buf->w_ptr = (int16_t *)out; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#endif /* MFCC_HIFI4 */ diff --git a/src/audio/mfcc/mfcc_setup.c b/src/audio/mfcc/mfcc_setup.c new file mode 100644 index 000000000000..1cad4b2b984e --- /dev/null +++ b/src/audio/mfcc/mfcc_setup.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/mfcc/mfcc_comp.h> +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> +#include <user/mfcc.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* Definitions for cepstral lifter */ +#define PI_Q23 Q_CONVERT_FLOAT(3.1415926536, 23) +#define TWO_PI_Q23 Q_CONVERT_FLOAT(6.2831853072, 23) +#define ONE_Q9 Q_CONVERT_FLOAT(1, 9) + +LOG_MODULE_REGISTER(mfcc_setup, CONFIG_SOF_LOG_LEVEL); + +static void mfcc_init_buffer(struct mfcc_buffer *buf, int16_t *base, int size) +{ + buf->addr = base; + buf->end_addr = base + size; + buf->r_ptr = base; + buf->w_ptr = base; + buf->s_free = size; + buf->s_avail = 0; + buf->s_length = size; +} + +static int mfcc_get_window(struct mfcc_state *state, enum sof_mfcc_fft_window_type name) +{ + struct mfcc_fft *fft = &state->fft; + + switch (name) { + case MFCC_RECTANGULAR_WINDOW: + win_rectangular_16b(state->window, fft->fft_size); + return 0; + case MFCC_BLACKMAN_WINDOW: + win_blackman_16b(state->window, fft->fft_size, MFCC_BLACKMAN_A0); + return 0; + case MFCC_HAMMING_WINDOW: + win_hamming_16b(state->window, fft->fft_size); + return 0; + case MFCC_HANN_WINDOW: + win_hann_16b(state->window, fft->fft_size); + return 0; + case MFCC_POVEY_WINDOW: + win_povey_16b(state->window, fft->fft_size); + return 0; + default: + return -EINVAL; + } +} + +/* The function returns a vector for multiplying the cepstral coefficients when + * cepstral lifter option is enabled. The cepstral lifter value is Q7.9, e.g. 22.0. + * The output vector is Q7.9 also and is size (1, num_ceps). + * + * The lifter function is + * coef[i] = 1.0 + 0.5 * lifter * sin(pi * i / lifter), i = 0 to num_ceps-1 + */ + +static int mfcc_get_cepstral_lifter(struct processing_module *mod, struct mfcc_cepstral_lifter *cl) +{ + int32_t inv_cepstral_lifter; + int32_t val; + int32_t sin; + int i; + + if (cl->num_ceps > DCT_MATRIX_SIZE_MAX) + return -EINVAL; + + cl->matrix = mod_mat_matrix_alloc_16b(mod, 1, cl->num_ceps, 9); /* Use Q7.9 */ + if (!cl->matrix) + return -ENOMEM; + + inv_cepstral_lifter = (1 << 30) / cl->cepstral_lifter; /* Q2.30 / Q7.9 -> Q1.21 */ + + for (i = 0; i < cl->num_ceps; i++) { + val = Q_MULTSR_32X32((int64_t)inv_cepstral_lifter, PI_Q23 * i, 21, 23, 23); + val %= TWO_PI_Q23; + sin = sin_fixed_32b(Q_SHIFT_LEFT(val, 23, 28)); /* Q4.28 -> Q1.31 */ + /* Val is Q7.9 make 0.5 multiply with additional shift */ + val = Q_MULTSR_32X32((int64_t)sin, cl->cepstral_lifter, 31, 9, 9 - 1); + val += ONE_Q9; + mat_set_scalar_16b(cl->matrix, 0, i, sat_int16(val)); + } + + return 0; +} + +/* TODO mfcc setup needs to use the config blob, not hard coded parameters. + * Also this is a too long function. Split to STFT, Mel filter, etc. parts. + */ +int mfcc_setup(struct processing_module *mod, int max_frames, int sample_rate, int channels) +{ + struct mfcc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_mfcc_config *config = cd->config; + struct mfcc_state *state = &cd->state; + struct mfcc_fft *fft = &state->fft; + struct psy_mel_filterbank *fb = &state->melfb; + struct dct_plan_16 *dct = &state->dct; + int ret; + + comp_dbg(dev, "entry"); + + /* Check size */ + if (config->size != sizeof(struct sof_mfcc_config)) { + comp_err(dev, "Illegal configuration size %d.", config->size); + return -EINVAL; + } + + /* Check currently hard-coded features to match configuration request */ + if (!config->round_to_power_of_two || !config->snip_edges || + config->subtract_mean || config->use_energy) { + comp_err(dev, "Can't change currently hard-coded features"); + return -EINVAL; + } + + if (config->sample_frequency != sample_rate) { + comp_err(dev, "Config sample_frequency does not match stream"); + return -EINVAL; + } + + cd->max_frames = max_frames; + state->sample_rate = sample_rate; + state->low_freq = config->low_freq; + state->high_freq = (config->high_freq == 0) ? (sample_rate >> 1) : config->high_freq; + if (state->low_freq > state->high_freq) { + comp_err(dev, "Config high_freq must be larger than low_freq"); + return -EINVAL; + } + + if (config->channel >= channels || (config->channel < 0 && channels != 1)) { + comp_err(dev, "Illegal source_channel %d for stream channels %d", config->channel, + channels); + return -EINVAL; + } + + if (config->channel < 0) + state->source_channel = 0; + else + state->source_channel = config->channel; + + state->mmax = (int32_t)config->mmax_init << 16; /* Q9.7 -> Q9.23 */ + state->emph.enable = config->preemphasis_coefficient > 0; + state->emph.coef = -config->preemphasis_coefficient; /* Negate config parameter */ + fft->fft_size = config->frame_length; + fft->fft_padded_size = 1 << (31 - norm_int32(fft->fft_size)); /* Round up to nearest 2^N */ + fft->fft_hop_size = config->frame_shift; + fft->half_fft_size = (fft->fft_padded_size >> 1) + 1; + + comp_info(dev, "emphasis = %d, fft_size = %d, fft_padded_size = %d, fft_hop_size = %d", + config->preemphasis_coefficient, + fft->fft_size, fft->fft_padded_size, fft->fft_hop_size); + + /* Calculated parameters */ + state->prev_data_size = fft->fft_size - fft->fft_hop_size; + state->buffer_size = fft->fft_size + max_frames; + + /* Allocate buffer input samples and overlap buffer */ + state->sample_buffers_size = sizeof(int16_t) * + (state->buffer_size + state->prev_data_size + fft->fft_size); + + comp_info(dev, "buffer_size = %d, prev_size = %d", + state->buffer_size, state->prev_data_size); + + state->buffers = mod_zalloc(mod, state->sample_buffers_size); + if (!state->buffers) { + comp_err(dev, "Failed buffer allocate"); + ret = -ENOMEM; + goto exit; + } + + mfcc_init_buffer(&state->buf, state->buffers, state->buffer_size); + state->prev_data = state->buffers + state->buffer_size; + state->window = state->prev_data + state->prev_data_size; + + /* Allocate buffers for FFT input and output data */ + fft->fft_buffer_size = fft->fft_padded_size * sizeof(struct icomplex32); + fft->fft_buf = mod_zalloc(mod, fft->fft_buffer_size); + if (!fft->fft_buf) { + comp_err(dev, "Failed FFT buffer allocate"); + ret = -ENOMEM; + goto free_buffers; + } + + fft->fft_out = mod_zalloc(mod, fft->fft_buffer_size); + if (!fft->fft_out) { + comp_err(dev, "Failed FFT output allocate"); + ret = -ENOMEM; + goto free_fft_buf; + } + + fft->fft_fill_start_idx = 0; /* From config pad_type */ + + /* Setup FFT */ + fft->fft_plan = mod_fft_plan_new(mod, fft->fft_buf, fft->fft_out, fft->fft_padded_size, + MFCC_FFT_BITS); + if (!fft->fft_plan) { + comp_err(dev, "Failed FFT init"); + ret = -EINVAL; + goto free_fft_out; + } + + comp_info(dev, "window = %d, num_mel_bins = %d, num_ceps = %d, norm = %d", + config->window, config->num_mel_bins, config->num_ceps, config->norm); + comp_info(dev, "low_freq = %d, high_freq = %d", + state->low_freq, state->high_freq); + + /* Setup window */ + ret = mfcc_get_window(state, config->window); + if (ret < 0) { + comp_err(dev, "Failed Window function"); + goto free_fft_plan; + } + + /* Setup Mel auditory filterbank. FFT input and output buffers are used + * as scratch in Mel filterbank initialization. Filterbank get function will + * return error if not sufficient size. + */ + fb->samplerate = sample_rate; + fb->start_freq = state->low_freq; + fb->end_freq = state->high_freq; + fb->mel_bins = config->num_mel_bins; + fb->slaney_normalize = config->norm == MFCC_MEL_NORM_SLANEY; /* True if slaney */ + fb->mel_log_scale = (enum psy_mel_log_scale)((int)config->mel_log); /* LOG, LOG10 or DB */ + fb->fft_bins = fft->fft_padded_size; + fb->half_fft_bins = (fft->fft_padded_size >> 1) + 1; + fb->scratch_data1 = (int16_t *)fft->fft_buf; + fb->scratch_data2 = (int16_t *)fft->fft_out; + fb->scratch_length1 = fft->fft_buffer_size / sizeof(int16_t); + fb->scratch_length2 = fft->fft_buffer_size / sizeof(int16_t); + ret = mod_psy_get_mel_filterbank(mod, fb); + if (ret < 0) { + comp_err(dev, "Failed Mel filterbank"); + goto free_fft_plan; + } + + /* Setup DCT and cepstral lifter only when num_ceps > 0. + * When num_ceps is zero, skip DCT/lifter and output Mel + * log spectra directly. + */ + if (config->num_ceps > 0) { + dct->num_in = config->num_mel_bins; + dct->num_out = config->num_ceps; + dct->type = (enum dct_type)config->dct; + dct->ortho = true; + ret = mod_dct_initialize_16(mod, dct); + if (ret < 0) { + comp_err(dev, "Failed DCT init"); + goto free_melfb_data; + } + + state->lifter.num_ceps = config->num_ceps; + state->lifter.cepstral_lifter = config->cepstral_lifter; /* Q7.9 max 64.0*/ + ret = mfcc_get_cepstral_lifter(mod, &state->lifter); + if (ret < 0) { + comp_err(dev, "Failed cepstral lifter"); + goto free_dct_matrix; + } + + state->mel_only = false; + } else { + comp_info(dev, "num_ceps is 0, Mel log spectra output mode"); + dct->num_in = config->num_mel_bins; + dct->num_out = 0; + dct->matrix = NULL; + state->lifter.matrix = NULL; + state->mel_only = true; + } + + /* Scratch overlay during runtime + * + * +------------------------------------------------------------+ + * | 1. fft_buf[], 32 bits, size x 8, e.g. 512 -> 4096 bytes | + * +-------------------------------------+----------------------+ + * | 3. power_spectra[], | 6. mel_log_32[], | + * | 32 bits, e.g. x257 -> 1028 bytes | 32 bits, e.g. x80 | + * | | 320 bytes | + * +-------------------------------------+----------------------+ + * + * +---------------------------------------------------------------------------------+ + * | 2. fft_out[], 32 bits, size x 8, e.g. 512 -> 4096 bytes | + * +----------------------------------+----------------------------------+-----------+ + * | 4. mel_spectra[], | 5. cepstral_coef[], | + * | 16 bits, e.g. x23 -> 46 bytes | 16 bits, e.g. 13x -> 26 bytes | + * +----------------------------------+----------------------------------+ + * + */ + + /* Use FFT buffer as scratch for later computed data */ + state->power_spectra = (int32_t *)&fft->fft_buf[0]; + state->mel_log_32 = &state->power_spectra[fft->half_fft_size]; + + /* Check that mel_log_32 fits in the remaining fft_buf scratch space */ + int mel_log_32_space = (int)(fft->fft_buffer_size / sizeof(int32_t)) - fft->half_fft_size; + + if (config->num_mel_bins > mel_log_32_space) { + comp_err(dev, "num_mel_bins %d exceeds mel_log_32 scratch space %d", + config->num_mel_bins, mel_log_32_space); + ret = -EINVAL; + goto free_lifter; + } + + state->mel_spectra = (struct mat_matrix_16b *)&fft->fft_out[0]; + if (!state->mel_only) { + state->cepstral_coef = + (struct mat_matrix_16b *)&state->mel_spectra->data[state->dct.num_in]; + } else { + state->cepstral_coef = NULL; + } + + /* Allocate output buffer for multi-period output. Size allows for + * current output data plus leftover from previous period. + */ + int max_out_per_hop = state->mel_only ? dct->num_in : dct->num_out; + + /* Check that output data can be drained within the periods spanned by one + * FFT hop. Each hop consumes fft_hop_size input samples and produces + * max_out_per_hop + 2 (magic) int16_t output values. The sink provides at + * least fft_hop_size * channels int16_t samples per hop (worst case s16). + * If output exceeds this, data accumulates and will eventually overflow. + */ + int out_per_hop = max_out_per_hop + 2; + int sink_per_hop = fft->fft_hop_size * channels; + + if (out_per_hop > sink_per_hop) { + comp_err(dev, "Output %d int16 per hop exceeds sink capacity %d (hop %d x ch %d)", + out_per_hop, sink_per_hop, fft->fft_hop_size, channels); + ret = -EINVAL; + goto free_lifter; + } + + /* Set initial state for STFT */ + state->waiting_fill = true; + state->prev_samples_valid = false; + state->magic_pending = false; + state->out_data_ptr = NULL; + state->out_data_ptr_32 = NULL; + state->out_remain = 0; + + comp_dbg(dev, "done"); + return 0; + +free_lifter: + mod_free(mod, state->lifter.matrix); + +free_dct_matrix: + mod_free(mod, state->dct.matrix); + +free_melfb_data: + mod_free(mod, fb->data); + +free_fft_plan: + mod_fft_plan_free(mod, fft->fft_plan); + +free_fft_out: + mod_free(mod, fft->fft_out); + +free_fft_buf: + mod_free(mod, fft->fft_buf); + +free_buffers: + mod_free(mod, state->buffers); + +exit: + return ret; +} + +void mfcc_free_buffers(struct processing_module *mod) +{ + struct mfcc_comp_data *cd = module_get_private_data(mod); + + mod_fft_plan_free(mod, cd->state.fft.fft_plan); + mod_free(mod, cd->state.fft.fft_buf); + mod_free(mod, cd->state.fft.fft_out); + mod_free(mod, cd->state.buffers); + mod_free(mod, cd->state.melfb.data); + mod_free(mod, cd->state.dct.matrix); + mod_free(mod, cd->state.lifter.matrix); +} diff --git a/src/audio/mfcc/tune/README.txt b/src/audio/mfcc/tune/README.txt new file mode 100644 index 000000000000..a0c3189e81a3 --- /dev/null +++ b/src/audio/mfcc/tune/README.txt @@ -0,0 +1,52 @@ +This directory contains a tool to create configuration blob for SOF +MFCC component. It's simply run in Matlab or Octave with command +"setup_mfcc". The MFCC configuration parameters can be edited from the +script. + +The configuration can be test run with testbench. First the test topologies +need to be created with "scripts/build-tools.sh -t". Next the testbench +is build with "scripts/rebuild-testbench.sh". + +Once the previous steps are done, a sample wav file can be processed +with script run_mfcc.sh. The script converts the input to raw 16 kHz +stereo format and runs the testbench for S16, S24, and S32 bit depths, +producing both cepstral coefficient (MFCC) and Mel spectrogram outputs. + +./run_mfcc.sh /usr/share/sounds/alsa/Front_Center.wav + +Output files from host testbench: + mfcc_s16.raw, mfcc_s24.raw, mfcc_s32.raw - cepstral coefficients + mel_s16.raw, mel_s24.raw, mel_s32.raw - Mel spectrogram + +If the XTENSA_PATH environment variable is set, the script also runs +the Xtensa build of the testbench (via xt-run) and produces additional +output files prefixed with "xt_": + xt_mfcc_s16.raw, xt_mfcc_s24.raw, xt_mfcc_s32.raw + xt_mel_s16.raw, xt_mel_s24.raw, xt_mel_s32.raw + +All output files can be decoded and plotted at once in Matlab or Octave +with the decode_all.m script: + +decode_all + +This calls decode_ceps for each MFCC file (13 cepstral coefficients) and +decode_mel for each Mel file (80 Mel bins), plotting spectrograms for all +files that exist including the Xtensa variants. + +Individual files can also be decoded manually: + +[ceps, t, n] = decode_ceps('mfcc_s16.raw', 13); + +In the above it's known from configuration script that MFCC was set up to +output 13 cepstral coefficients from each FFT -> Mel -> DCT -> Cepstral +coefficients computation run. + +The 80 bands Mel output can be visualized with command: + +[mel, t, n] = decode_mel('mel_s16.raw', 80); + +Other kind of signals have quite big visual difference in audio features. Try +e.g. other sound files found in computer. + +./run_mfcc.sh /usr/share/sounds/gnome/default/alerts/bark.ogg +./run_mfcc.sh /usr/share/sounds/gnome/default/alerts/sonar.ogg diff --git a/src/audio/mfcc/tune/decode_all.m b/src/audio/mfcc/tune/decode_all.m new file mode 100644 index 000000000000..d5b60289b4cf --- /dev/null +++ b/src/audio/mfcc/tune/decode_all.m @@ -0,0 +1,39 @@ +% decode_all.m - Decode all MFCC and Mel raw output files from run_mfcc.sh +% +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2026 Intel Corporation. + +num_ceps = 13; +num_mel = 80; + +% MFCC cepstral output files +ceps_files = {'mfcc_s16.raw', 'mfcc_s24.raw', 'mfcc_s32.raw'}; + +% Mel output files with corresponding format +mel_files = {'mel_s16.raw', 'mel_s24.raw', 'mel_s32.raw'}; +mel_fmts = {'s16', 's24', 's32'}; + +% Xtensa prefixed variants +xt_ceps_files = {'xt_mfcc_s16.raw', 'xt_mfcc_s24.raw', 'xt_mfcc_s32.raw'}; +xt_mel_files = {'xt_mel_s16.raw', 'xt_mel_s24.raw', 'xt_mel_s32.raw'}; + +all_ceps_files = [ceps_files, xt_ceps_files]; +all_mel_files = [mel_files, xt_mel_files]; +all_mel_fmts = [mel_fmts, mel_fmts]; + +for i = 1:length(all_ceps_files) + fn = all_ceps_files{i}; + if exist(fn, 'file') + fprintf('Decoding MFCC ceps: %s\n', fn); + [ceps, t, n] = decode_ceps(fn, num_ceps); + end +end + +for i = 1:length(all_mel_files) + fn = all_mel_files{i}; + fmt = all_mel_fmts{i}; + if exist(fn, 'file') + fprintf('Decoding Mel: %s\n', fn); + [mel, t, n] = decode_mel(fn, num_mel, fmt); + end +end diff --git a/src/audio/mfcc/tune/decode_ceps.m b/src/audio/mfcc/tune/decode_ceps.m new file mode 100644 index 000000000000..a63677fa3731 --- /dev/null +++ b/src/audio/mfcc/tune/decode_ceps.m @@ -0,0 +1,93 @@ +% [ceps, t, n] = decode_ceps(fn, num_ceps, num_channels) +% +% Input +% fn - File with MFCC data in .raw or .wav format +% num_ceps - number of cepstral coefficients per frame +% num_channels - needed for .raw format, omit for .wav +% +% Outputs +% ceps - cepstral coefficients +% t - time vector for plotting +% n - ceps 1..num_ceps vector for plotting + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function [ceps, t, n] = decode_ceps(fn, num_ceps, num_channels) + +if nargin < 3 + num_channels = 1; +end + +% MFCC stream +fs = 16e3; +qformat = 7; +magic = [25443 28006]; % ASCII 'mfcc' as int16 + +% Load output data +[data, num_channels] = get_file(fn, num_channels); + +idx1 = find(data == magic(1)); +idx = []; +for i = 1:length(idx1) + if data(idx1(i) + 1) == magic(2) + idx = [idx idx1(i)]; + end +end + +if isempty(idx) + error('No magic value markers found from stream'); +end + +period_ceps = idx(2)-idx(1); +num_frames = length(idx); +t_ceps = period_ceps / num_channels / fs; +t = (0:num_frames -1) * t_ceps; +n = 1:num_ceps; + +ceps = zeros(num_ceps, num_frames); +for i = 1:num_frames + i1 = idx(i) + 2; + i2 = i1 + num_ceps - 1; + ceps(:,i) = data(i1:i2) / 2^qformat; +end + +figure; +surf(t, n, ceps, 'EdgeColor', 'none'); +colormap(jet); +view(45, 60) +tstr = sprintf('SOF MFCC cepstral coefficients (%s)', fn); +title(tstr, 'Interpreter', 'None'); +xlabel('Time (s)'); +ylabel('Cepstral coef #'); + +end + +function [data, num_channels] = get_file(fn, num_channels) + +[~, ~, ext] = fileparts(fn); + +switch lower(ext) + case '.raw' + fh = fopen(fn, 'r'); + data = fread(fh, 'int16'); + fclose(fh); + case '.wav' + tmp = audioread(fn, 'native'); + t = whos('tmp'); + if ~strcmp(t.class, 'int16'); + error('Only 16-bit wav file format is supported'); + end + s = size(tmp); + num_channels = s(2); + if num_channels > 1 + data = int16(zeros(prod(s), 1)); + for i = 1:num_channels + data(i:num_channels:end) = tmp(:, i); + end + end + otherwise + error('Unknown audio format'); +end + +end diff --git a/src/audio/mfcc/tune/decode_mel.m b/src/audio/mfcc/tune/decode_mel.m new file mode 100644 index 000000000000..f6a723aa2040 --- /dev/null +++ b/src/audio/mfcc/tune/decode_mel.m @@ -0,0 +1,145 @@ +% [mel, t, n] = decode_mel(fn, num_mel, fmt, num_channels) +% +% Input +% fn - File with Mel data in .raw or .wav format +% num_mel - number of Mel coefficients per frame +% fmt - format of the Mel data ('s16', 's24', 's32') +% num_channels - needed for .raw format, omit for .wav +% +% Outputs +% mel - Mel coefficients +% t - time vector for plotting +% n - mel 1..num_mel vector for plotting + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2026 Intel Corporation. + +function [mel, t, n] = decode_mel(fn, num_mel, fmt, num_channels) + +if nargin < 3 + fmt = 's16'; +end +if nargin < 4 + num_channels = 1; +end + +% MFCC stream +fs = 16e3; + +switch fmt + case 's16' + qformat = 7; + magic = [25443 28006]; % ASCII 'mfcc' as two int16 + num_magic = 2; + case 's24' + qformat = 15; + magic = int32(1835426659); % 0x6D666363 as int32 + num_magic = 1; + case 's32' + qformat = 23; + magic = int32(1835426659); % 0x6D666363 as int32 + num_magic = 1; + otherwise + error("Use 's16', 's24', or 's32' as format."); +end + +% Load output data +[data, num_channels] = get_file(fn, num_channels, fmt); + +if strcmp(fmt, 's16') + idx1 = find(data == magic(1)); + idx = []; + for i = 1:length(idx1) + next_word = idx1(i) + 1; + if next_word <= length(data) + if data(next_word) == magic(2) + idx = [idx idx1(i)]; + end + end + end +else + idx = find(data == magic); +end + +if isempty(idx) + error('No magic value markers found from stream'); +end + +period_mel = idx(2)-idx(1); +num_frames = length(idx); + +% Last frame can be incomplete due to span over multiple periods +last = idx(end) + num_mel - 1; +if (last > length(data)) + num_frames = num_frames - 1; +end + +t_mel = period_mel / num_channels / fs; +t = (0:num_frames -1) * t_mel; +n = 1:num_mel; + +mel = zeros(num_mel, num_frames); +for i = 1:num_frames + i1 = idx(i) + num_magic; + i2 = i1 + num_mel - 1; + mel(:,i) = double(data(i1:i2)) / 2^qformat; +end + +figure; +imagesc(t, n, mel); +axis xy; +colormap(jet); +colorbar; +tstr = sprintf('SOF MFCC Mel coefficients (%s)', fn); +title(tstr, 'Interpreter', 'None'); +xlabel('Time (s)'); +ylabel('Mel coef #'); + +end + +function [data, num_channels] = get_file(fn, num_channels, fmt) + +[~, ~, ext] = fileparts(fn); + +switch fmt + case 's16' + read_fmt = 'int16'; + case {'s24', 's32'} + read_fmt = 'int32'; + otherwise + error("Use 's16', 's24', or 's32' as format."); +end + +switch lower(ext) + case '.raw' + fh = fopen(fn, 'r'); + data = fread(fh, read_fmt); + fclose(fh); + case '.wav' + tmp = audioread(fn, 'native'); + t = whos('tmp'); + switch fmt + case 's16' + if ~strcmp(t.class, 'int16') + error('Expected 16-bit wav for s16 format'); + end + case {'s24', 's32'} + if ~strcmp(t.class, 'int32') + error('Expected 32-bit wav for %s format', fmt); + end + end + s = size(tmp); + num_channels = s(2); + if num_channels > 1 + data = zeros(prod(s), 1, t.class); + for i = 1:num_channels + data(i:num_channels:end) = tmp(:, i); + end + else + data = tmp; + end + otherwise + error('Unknown audio format'); +end + +end diff --git a/src/audio/mfcc/tune/run_mfcc.sh b/src/audio/mfcc/tune/run_mfcc.sh new file mode 100755 index 000000000000..e3c309fbc03e --- /dev/null +++ b/src/audio/mfcc/tune/run_mfcc.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022-2026 Intel Corporation. All rights reserved. + +set -e + +RAW_INPUT_S16=in_s16.raw +RAW_INPUT_S24=in_s24.raw +RAW_INPUT_S32=in_s32.raw + +VALGRIND="valgrind --leak-check=full" +#VALGRIND="" +TESTBENCH=$SOF_WORKSPACE/sof/tools/testbench/build_testbench/install/bin/sof-testbench4 +TESTBENCH_RUN="$VALGRIND $TESTBENCH" + +convert_input() { + sox -R --encoding signed-integer "$1" -L -r 16000 -c 2 -b 16 "$RAW_INPUT_S16" + sox -R --no-dither --encoding signed-integer -L -r 16000 -c 2 -b 16 \ + "$RAW_INPUT_S16" -b 32 "$RAW_INPUT_S32" + sox -R --no-dither --encoding signed-integer -L -r 16000 -c 2 -b 16 \ + "$RAW_INPUT_S16" -b 32 "$RAW_INPUT_S24" vol 0.003906250000 +} + +run_testbench() { + local tplg_base="$1" + local out_s16="$2" + local out_s24="$3" + local out_s32="$4" + local label="$5" + local tplg_s16="${SOF_WORKSPACE}/sof/tools/build_tools/topology/topology2/development/${tplg_base}16.tplg" + local tplg_s24="${SOF_WORKSPACE}/sof/tools/build_tools/topology/topology2/development/${tplg_base}24.tplg" + local tplg_s32="${SOF_WORKSPACE}/sof/tools/build_tools/topology/topology2/development/${tplg_base}32.tplg" + + $TESTBENCH_RUN -r 16000 -c 2 -b S16_LE -p 3,4 -t "$tplg_s16" -i "$RAW_INPUT_S16" -o "$out_s16" + $TESTBENCH_RUN -r 16000 -c 2 -b S24_LE -p 3,4 -t "$tplg_s24" -i "$RAW_INPUT_S24" -o "$out_s24" + $TESTBENCH_RUN -r 16000 -c 2 -b S32_LE -p 3,4 -t "$tplg_s32" -i "$RAW_INPUT_S32" -o "$out_s32" + + echo ---------------------------------------------------------------------------------- + echo "The ${label} data was output to file ${out_s16}, ${out_s24}, ${out_s32}" + echo ---------------------------------------------------------------------------------- +} + +main() { + convert_input "$1" + run_testbench "sof-hda-benchmark-mfcc" mfcc_s16.raw mfcc_s24.raw mfcc_s32.raw "MFCC" + run_testbench "sof-hda-benchmark-mfccmel" mel_s16.raw mel_s24.raw mel_s32.raw "MFCC Mel" + + if [ -n "$XTENSA_PATH" ]; then + TESTBENCH_RUN="$XTENSA_PATH/xt-run $SOF_WORKSPACE/sof/tools/testbench/build_xt_testbench/sof-testbench4" + run_testbench "sof-hda-benchmark-mfcc" xt_mfcc_s16.raw xt_mfcc_s24.raw xt_mfcc_s32.raw "Xtensa MFCC" + run_testbench "sof-hda-benchmark-mfccmel" xt_mel_s16.raw xt_mel_s24.raw xt_mel_s32.raw "Xtensa MFCC Mel" + fi +} + +main "$@" diff --git a/src/audio/mfcc/tune/setup_mfcc.m b/src/audio/mfcc/tune/setup_mfcc.m new file mode 100644 index 000000000000..bd2b3f11e60b --- /dev/null +++ b/src/audio/mfcc/tune/setup_mfcc.m @@ -0,0 +1,287 @@ +% setup_mfcc() +% +% Create binary configuration blobs for the MFCC component. +% The hex data is written to files in directory +% tools/topology/topology2/include/components/mfcc. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2018-2026, Intel Corporation. + +function setup_mfcc() + + gen_cfg.tplg_ver = 2; + gen_cfg.ipc_ver = 4; + gen_cfg.tools_path = '../../../../tools/'; + gen_cfg.mfcc_conf_path = [gen_cfg.tools_path 'topology/topology2/include/components/mfcc/']; + + % Default blob + setup = get_mfcc_default_config(); + setup.tplg_fn = 'default.conf'; + export_mfcc_setup(gen_cfg, setup); + + % Blob for mel spectrogram data + setup = get_mel_spectrogram_config(); + setup.tplg_fn = 'mel80.conf'; + export_mfcc_setup(gen_cfg, setup); + +end + +function cfg = get_mfcc_default_config() + cfg.blackman_coef = 0.42; + cfg.cepstral_lifter = 22.0; + cfg.channel = 0; % -1 expect mono, 0 left, 1 right ... + cfg.dither = 0.0; % no support + cfg.energy_floor = 1.0; + cfg.frame_length = 25.0; % ms + cfg.frame_shift = 10.0; % ms + cfg.high_freq = 0.0; % 0 is Nyquist + cfg.htk_compat = false; % no support + cfg.low_freq = 20.0; % Hz + cfg.num_ceps = 13; + cfg.min_duration = 0.0; % no support + cfg.norm = 'none'; % Use none or slaney + cfg.num_mel_bins = 23; + cfg.preemphasis_coefficient = 0; % disable + cfg.raw_energy = true; + cfg.remove_dc_offset = true; + cfg.round_to_power_of_two = true; % must be true + cfg.sample_frequency = 16000; + cfg.snip_edges = true; % must be true + cfg.subtract_mean = false; % must be false + cfg.use_energy = false; + cfg.vtln_high = -500.0; % no support + cfg.vtln_low = 100.0; % no support + cfg.vtln_warp = 1.0; % must be 1.0 (vocal tract length normalization) + cfg.window_type = 'hamming'; + cfg.mel_log = 'log'; % Set to 'db' for librosa, set to 'log10' for matlab + cfg.pmin = 5e-10; % Set to 1e-10 for librosa + cfg.top_db = 200; % Set to 80 for librosa + cfg.mel_offset = 0; % For mel_only mode, no impact with num_ceps > 0 + cfg.mel_scale = 0; % same + cfg.mmax_init = 0; % same + cfg.mmax_coef = 0; % same + cfg.dynamic_mmax = false; % same +end + +function cfg = get_mel_spectrogram_config() + cfg.blackman_coef = 0; + cfg.cepstral_lifter = 0; + cfg.channel = 0; + cfg.dither = 0; + cfg.energy_floor = 1.0; + cfg.frame_length = 25.0; % 400 samples at 16 kHz + cfg.frame_shift = 10.0; % 160 samples at 16 kHz + cfg.high_freq = 8000; + cfg.htk_compat = false; + cfg.low_freq = 0; + cfg.num_ceps = 0; % Mel-only mode, no DCT + cfg.min_duration = 0; + cfg.norm = 'slaney'; + cfg.num_mel_bins = 80; + cfg.preemphasis_coefficient = 0; + cfg.raw_energy = false; + cfg.remove_dc_offset = false; + cfg.round_to_power_of_two = true; + cfg.sample_frequency = 16000; + cfg.snip_edges = true; + cfg.subtract_mean = false; + cfg.use_energy = false; + cfg.vtln_high = 0; + cfg.vtln_low = 0; + cfg.vtln_warp = 1.0; + cfg.window_type = 'hann'; + cfg.mel_log = 'log10'; + cfg.pmin = 1e-10; + cfg.top_db = 8; % applied for log10, would be 80 dB clamp for decibels as 10*log10() + cfg.mel_offset = 4.0; % For whisper like Mel scale and normalize + cfg.mel_scale = 0.25; % For whisper like Mel scale and normalize + cfg.mmax_init = 0; % Initial value max Mel value, data clamp is mmax - top_db + cfg.mmax_coef = 0; % Dynamic max Mel value decay coefficient (zero lock to found max) + cfg.dynamic_mmax = true; +end + +function export_mfcc_setup(gen_cfg, cfg) + +%% Use blob tool from EQ +addpath([gen_cfg.tools_path 'tune/common']); + +%% Blob size, size plus reserved(8) + current parameters +nbytes_data = 104; + +%% Little endian +sh32 = [0 -8 -16 -24]; +sh16 = [0 -8]; + +%% Get ABI information +[abi_bytes, nbytes_abi] = sof_get_abi(nbytes_data, gen_cfg.ipc_ver); + +%% Initialize correct size uint8 array +nbytes = nbytes_abi + nbytes_data; +b8 = uint8(zeros(1,nbytes)); + +%% Insert ABI header +fprintf(1, 'MFCC blob size is %d, ABI header is %d, data is %d\n',nbytes, nbytes_abi, nbytes_data); +b8(1:nbytes_abi) = abi_bytes; +j = nbytes_abi + 1; + +%% Apply default MFCC configuration, first struct header and reserved, then data +[b8, j] = add_w32b(nbytes_data, b8, j); + +v = q_convert(cfg.mel_offset, 7); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.mel_scale, 12); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.mmax_init, 7); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.mmax_coef, 15); [b8, j] = add_w16b(v, b8, j); + +% Reserved +for i = 1:6 + [b8, j] = add_w32b(0, b8, j); +end + +v = q_convert(cfg.sample_frequency, 0); [b8, j] = add_w32b(v, b8, j); +v = q_convert(cfg.pmin, 31); [b8, j] = add_w32b(v, b8, j); +v = get_mel_log_value(cfg.mel_log); [b8, j] = add_w32b(v, b8, j); % enum mel_log +v = get_norm_value(cfg.norm); [b8, j] = add_w32b(v, b8, j); % enum norm +v = 0; [b8, j] = add_w32b(v, b8, j); % enum pad +v = get_window(cfg); [b8, j] = add_w32b(v, b8, j); % enum window +v = 1; [b8, j] = add_w32b(v, b8, j); % enum dct type +v = q_convert(cfg.blackman_coef, 15); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.cepstral_lifter, 9); [b8, j] = add_w16b(v, b8, j); +v = cfg.channel; [b8, j] = add_w16b(v, b8, j); +v = cfg.dither; [b8, j] = add_w16b(v, b8, j); +v = round(cfg.frame_length/1000 * cfg.sample_frequency); [b8, j] = add_w16b(v, b8, j); +v = round(cfg.frame_shift/1000 * cfg.sample_frequency); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.high_freq, 0); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.low_freq, 0); [b8, j] = add_w16b(v, b8, j); +v = cfg.num_ceps; [b8, j] = add_w16b(v, b8, j); +v = cfg.num_mel_bins; [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.preemphasis_coefficient, 15); [b8, j] = add_w16b(v, b8, j); +v = q_convert(cfg.top_db, 7); [b8, j] = add_w16b(v, b8, j); +v = 0; [b8, j] = add_w16b(v, b8, j); % vtln_high Qx.y TBD +v = 0; [b8, j] = add_w16b(v, b8, j); % vtln_low Qx.y TBD +v = 0; [b8, j] = add_w16b(v, b8, j); % vtln_warp Qx.y TBD +v = cfg.htk_compat; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.raw_energy; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.remove_dc_offset; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.round_to_power_of_two; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.snip_edges; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.subtract_mean; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.use_energy; [b8, j] = add_w8b(v, b8, j); % bool +v = cfg.dynamic_mmax; [b8, j] = add_w8b(v, b8, j); % bool + +%% Export +tplg_fn = [gen_cfg.mfcc_conf_path cfg.tplg_fn]; +switch gen_cfg.tplg_ver + case 1 + sof_tplg_write(tplg_fn, b8, "DEF_MFCC_PRIV", ... + "Exported with script setup_mfcc.m", ... + "cd src/audio/mfcc/tune; octave setup_mfcc.m"); + case 2 + sof_tplg2_write(tplg_fn, b8, "mfcc_config", ... + "Exported MFCC configuration", ... + "cd src/audio/mfcc/tune; octave setup_mfcc.m"); + otherwise + error("Illegal tplg_ver, use 1 for topology v1 or 2 topology v2."); +end + +rmpath([gen_cfg.tools_path 'tune/common']); + +end + +%% Helper functions + +function n = get_window(cfg) + switch lower(cfg.window_type) + case 'rectangular' + n = 0; + case 'blackman' + n = 1; + case 'hamming' + n = 2; + case 'hann' + n = 3; + case 'povey' + n = 4; + otherwise + error('Unknown window type'); + end +end + +function n = get_mel_log_value(mel_log) + switch lower(mel_log) + case 'log' + n = 0; + case 'log10' + n = 1; + case 'db' + n = 2; + otherwise + error('Unknown mel_log type'); + end +end + +function n = get_norm_value(norm) + switch lower(norm) + case 'none' + n = 0; + case 'slaney' + n = 1; + otherwise + error('Unknown norm type'); + end +end + +function bytes = w8b(word) +bytes = uint8(zeros(1,1)); +bytes(1) = bitand(word, 255); +end + +function bytes = w16b(word) +sh = [0 -8]; +bytes = uint8(zeros(1,2)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +end + +function bytes = w32b(word) +sh = [0 -8 -16 -24]; +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end + +function n = q_convert(val, q) +n = round(val * 2^q); +end + +function [blob8, j] = add_w8b(v, blob8, j) +if j > length(blob8) + error('Blob size is not sufficient'); +end +blob8(j) = w8b(v); +j = j + 1; +end + +function [blob8, j] = add_w16b(v, blob8, j) +if j + 1 > length(blob8) + error('Blob size is not sufficient'); +end +if v < 0 + v = 2^16 + v; +end +blob8(j : j + 1) = w16b(v); +j = j + 2; +end + +function [blob8, j] = add_w32b(v, blob8, j) +if j + 3 > length(blob8) + error('Blob size is not sufficient'); +end +if v < 0 + v = 2^32 + v; +end +blob8(j : j + 3) = w32b(v); +j = j + 4; +end diff --git a/src/audio/mic_privacy_manager/CMakeLists.txt b/src/audio/mic_privacy_manager/CMakeLists.txt new file mode 100644 index 000000000000..b4ae270f7669 --- /dev/null +++ b/src/audio/mic_privacy_manager/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof mic_privacy_manager_intel.c) diff --git a/src/audio/mic_privacy_manager/README.md b/src/audio/mic_privacy_manager/README.md new file mode 100644 index 000000000000..8d85f43e1a2b --- /dev/null +++ b/src/audio/mic_privacy_manager/README.md @@ -0,0 +1,11 @@ +# Microphone Privacy Manager Architecture + +This directory contains the Mic Privacy Manager. + +## Overview + +Provides a secure mechanism to optionally mute the microphone paths deeply inside the DSP, ensuring user privacy regardless of host OS behavior. + +## Configuration and Scripts + +- **CMakeLists.txt**: Simply builds the Intel-specific privacy implementation (`mic_privacy_manager_intel.c`). Currently, there is no generic or separate module wrapper defined within the scope of this directory. diff --git a/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c new file mode 100644 index 000000000000..5120c2ab4b59 --- /dev/null +++ b/src/audio/mic_privacy_manager/mic_privacy_manager_intel.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. + +#include "sof/audio/mic_privacy_manager.h" + +#include <zephyr/device.h> +#include <zephyr/drivers/mic_privacy/intel/mic_privacy.h> +#include <zephyr/logging/log.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/buffer.h> +#include <sof/audio/mic_privacy_manager.h> + +const struct device *mic_priv_dev; + +static struct mic_privacy_api_funcs *mic_privacy_api; +static enum mic_privacy_policy mic_privacy_policy; + +#define LOG_DOMAIN mic_priv + +LOG_MODULE_REGISTER(LOG_DOMAIN); + +void handle_dmic_irq(void const *self, int a, int b) +{ + LOG_DBG("mic_privacy DMIC IRQ"); + + if (mic_privacy_api->get_dmic_irq_status()) { + uint32_t mic_disable_status = mic_privacy_api->get_dmic_mic_disable_status(); + struct mic_privacy_settings settings; + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + mic_privacy_api->clear_dmic_irq_status(); + } +} + +void handle_fw_managed_irq(void const *dev) +{ + LOG_DBG("mic_privacy FW Managed IRQ"); + + uint32_t mic_disable_status = mic_privacy_api->get_fw_managed_mic_disable_status(); + struct mic_privacy_settings settings; + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + + if (mic_disable_status) + mic_privacy_api->set_fw_mic_disable_status(true); + else + mic_privacy_api->set_fw_mic_disable_status(false); + + mic_privacy_api->clear_fw_managed_irq(); +} + +static void enable_fw_managed_irq(bool enable_irq) +{ + if (enable_irq) + mic_privacy_api->enable_fw_managed_irq(true, handle_fw_managed_irq); + else + mic_privacy_api->enable_fw_managed_irq(false, NULL); +} + +void mic_privacy_enable_dmic_irq(bool enable_irq) +{ + /* Only proceed if we have a valid device and API */ + if (!mic_priv_dev || !mic_privacy_api) { + LOG_ERR("mic_privacy device or API not initialized"); + return; + } + + if (mic_privacy_api->get_policy() == MIC_PRIVACY_HW_MANAGED) { + if (enable_irq) { + mic_privacy_api->enable_dmic_irq(true, handle_dmic_irq); + + /* Check current status immediately to handle any transitions during D3 */ + if (mic_privacy_api->get_dmic_irq_status()) { + struct mic_privacy_settings settings; + uint32_t mic_disable_status = + mic_privacy_api->get_dmic_mic_disable_status(); + + mic_privacy_fill_settings(&settings, mic_disable_status); + mic_privacy_propagate_settings(&settings); + mic_privacy_api->clear_dmic_irq_status(); + } + } else { + mic_privacy_api->enable_dmic_irq(false, NULL); + } + } +} + +int mic_privacy_manager_init(void) +{ + mic_priv_dev = DEVICE_DT_GET(DT_NODELABEL(mic_privacy)); + + if (!mic_priv_dev) + return -EINVAL; + + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; + mic_privacy_policy = mic_privacy_api->get_policy(); + + if (mic_privacy_policy == MIC_PRIVACY_FW_MANAGED) { + LOG_INF("mic_privacy init FW_MANAGED mode"); + mic_privacy_api->set_fw_managed_mode(true); + enable_fw_managed_irq(true); + } + + return 0; +} + +int mic_privacy_manager_get_policy(void) +{ + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; + + return mic_privacy_api->get_policy(); +} + +uint32_t mic_privacy_get_policy_register(void) +{ + if (!mic_priv_dev) + return 0; + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; + + return mic_privacy_api->get_privacy_policy_register_raw_value(); +} + +void mic_privacy_propagate_settings(struct mic_privacy_settings *settings) +{ + notifier_event(mic_priv_dev, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, + NOTIFIER_TARGET_CORE_ALL_MASK, settings, + sizeof(struct mic_privacy_settings)); +} + +uint32_t mic_privacy_get_dma_zeroing_wait_time(void) +{ + return (uint32_t)mic_privacy_api->get_dma_data_zeroing_wait_time(); +} + +uint32_t mic_privacy_get_privacy_mask(void) +{ + if (mic_privacy_policy == MIC_PRIVACY_HW_MANAGED) + return mic_privacy_api->get_dma_data_zeroing_link_select(); + + /* hardcoded for FW_MANAGED */ + return 0xFFFFFFFF; +} + +void mic_privacy_fill_settings(struct mic_privacy_settings *settings, uint32_t mic_disable_status) +{ + if (!settings) { + LOG_ERR("Invalid mic_privacy_settings pointer"); + return; + } + + settings->mic_privacy_mode = mic_privacy_policy; + settings->mic_privacy_state = mic_disable_status; + settings->privacy_mask_bits.value = mic_privacy_get_privacy_mask(); + settings->max_ramp_time = mic_privacy_get_dma_zeroing_wait_time(); + + LOG_DBG("mic_privacy_mode = %d, mic_disable_status = %d, \ + privacy_mask = %x, max_ramp_time_in_ms = %d", + settings->mic_privacy_mode, + settings->mic_privacy_state, + settings->privacy_mask_bits.value, + settings->max_ramp_time); +} + +void mic_privacy_set_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t mic_disable_status) +{ + if (mic_privacy_policy == MIC_PRIVACY_HW_MANAGED) { + if (mic_disable_status != 0) + mic_priv_data->mic_privacy_state = MIC_PRIV_MUTED; + else + mic_priv_data->mic_privacy_state = MIC_PRIV_UNMUTED; + } else if (mic_privacy_policy == MIC_PRIVACY_FW_MANAGED) { + if (mic_disable_status != 0) { + LOG_DBG("MUTED"); + mic_priv_data->mic_privacy_state = MIC_PRIV_MUTED; + mic_priv_data->dma_data_zeroing = true; + mic_privacy_api->set_fw_mic_disable_status(true); + } else { + LOG_DBG("UNMUTED"); + mic_priv_data->mic_privacy_state = MIC_PRIV_UNMUTED; + mic_priv_data->dma_data_zeroing = false; + mic_privacy_api->set_fw_mic_disable_status(false); + } + } +} + +void mic_privacy_update_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t hw_mic_disable_status) +{ + switch (mic_privacy_policy) { + case MIC_PRIVACY_HW_MANAGED: + mic_privacy_set_gtw_mic_state(mic_priv_data, hw_mic_disable_status); + break; + case MIC_PRIVACY_FW_MANAGED: + mic_privacy_set_gtw_mic_state(mic_priv_data, + mic_privacy_api->get_fw_managed_mic_disable_status()); + break; + default: + break; + } +} + +void mic_privacy_process(struct comp_dev *dev, struct mic_privacy_data *mic_priv, + struct comp_buffer *buffer, uint32_t copy_samples) +{ + uint32_t sg_size_in_bytes; + + sg_size_in_bytes = audio_stream_frame_bytes(&buffer->stream); + uint32_t one_ms_in_bytes = sg_size_in_bytes * (buffer->stream.runtime_stream_params.rate / 1000); + uint32_t copy_bytes = copy_samples * audio_stream_sample_bytes(&buffer->stream); + + switch (mic_priv->mic_privacy_state) { + case MIC_PRIV_UNMUTED: + break; + case MIC_PRIV_MUTED: + buffer_zero(buffer); + break; + case MIC_PRIV_FADE_IN: + if (mic_priv->fade_in_out_bytes == 0) { + /* start addition */ + mic_priv->mic_priv_gain_params.fade_in_sg_count = 0; + mic_priv->mic_priv_gain_params.gain_env = 0; + } + mic_priv->fade_in_out_bytes += copy_bytes; + if (mic_priv->fade_in_out_bytes > one_ms_in_bytes * mic_priv->max_ramp_time_in_ms) { + mic_priv->mic_privacy_state = MIC_PRIV_UNMUTED; + mic_priv->fade_in_out_bytes = 0; + } + + if (mic_priv->max_ramp_time_in_ms > 0) + copier_gain_input(dev, buffer, &mic_priv->mic_priv_gain_params, GAIN_ADD, copy_bytes); + break; + case MIC_PRIV_FADE_OUT: + if (mic_priv->fade_in_out_bytes == 0) { + /* start subtraction */ + mic_priv->mic_priv_gain_params.fade_in_sg_count = 0; + mic_priv->mic_priv_gain_params.gain_env = INT64_MAX; + } + mic_priv->fade_in_out_bytes += copy_bytes; + if (mic_priv->fade_in_out_bytes > one_ms_in_bytes * mic_priv->max_ramp_time_in_ms) { + mic_priv->mic_privacy_state = MIC_PRIV_MUTED; + mic_priv->fade_in_out_bytes = 0; + buffer_zero(buffer); + } + if (mic_priv->max_ramp_time_in_ms > 0) + copier_gain_input(dev, buffer, &mic_priv->mic_priv_gain_params, GAIN_SUBTRACT, copy_bytes); + break; + default: + LOG_ERR("invalid state %x", mic_priv->mic_privacy_state); + break; + } +} + +uint32_t mic_privacy_get_mic_disable_status(void) +{ + if (!mic_priv_dev) { + LOG_ERR("mic_privacy device not initialized"); + return 0; + } + + mic_privacy_api = (struct mic_privacy_api_funcs *)mic_priv_dev->api; + if (mic_privacy_api->get_policy() == MIC_PRIVACY_FW_MANAGED) + return mic_privacy_api->get_fw_managed_mic_disable_status(); + + return mic_privacy_api->get_dmic_mic_disable_status(); +} diff --git a/src/audio/mixer.c b/src/audio/mixer.c deleted file mode 100644 index f4e5268311c6..000000000000 --- a/src/audio/mixer.c +++ /dev/null @@ -1,466 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component.h> -#include <sof/audio/format.h> -#include <sof/audio/mixer.h> -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/math/numbers.h> -#include <sof/platform.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <sof/ut.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <stddef.h> -#include <stdint.h> - -static const struct comp_driver comp_mixer; - -/* bc06c037-12aa-417c-9a97-89282e321a76 */ -DECLARE_SOF_UUID("mixer", mixer_uuid, 0xbc06c037, 0x12aa, 0x417c, - 0x9a, 0x97, 0x89, 0x28, 0x2e, 0x32, 0x1a, 0x76); - -/* mixer component private data */ -struct mixer_data { - void (*mix_func)(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream **sources, uint32_t count, - uint32_t frames); -}; - -#if CONFIG_FORMAT_S16LE -/* Mix n 16 bit PCM source streams to one sink stream */ -static void mix_n_s16(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream **sources, uint32_t num_sources, - uint32_t frames) -{ - int16_t *src; - int16_t *dest; - int32_t val; - int i; - int j; - int channel; - uint32_t frag = 0; - - for (i = 0; i < frames; i++) { - for (channel = 0; channel < sink->channels; channel++) { - val = 0; - - for (j = 0; j < num_sources; j++) { - src = audio_stream_read_frag_s16(sources[j], - frag); - val += *src; - } - - dest = audio_stream_write_frag_s16(sink, frag); - - /* Saturate to 16 bits */ - *dest = sat_int16(val); - - frag++; - } - } -} -#endif /* CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE -/* Mix n 32 bit PCM source streams to one sink stream */ -static void mix_n_s32(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream **sources, uint32_t num_sources, - uint32_t frames) -{ - int32_t *src; - int32_t *dest; - int64_t val; - int i; - int j; - int channel; - uint32_t frag = 0; - - for (i = 0; i < frames; i++) { - for (channel = 0; channel < sink->channels; channel++) { - val = 0; - - for (j = 0; j < num_sources; j++) { - src = audio_stream_read_frag_s32(sources[j], - frag); - val += *src; - } - - dest = audio_stream_write_frag_s32(sink, frag); - - /* Saturate to 32 bits */ - *dest = sat_int32(val); - - frag++; - } - } -} -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ - -static struct comp_dev *mixer_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct comp_dev *dev; - struct sof_ipc_comp_mixer *mixer; - struct sof_ipc_comp_mixer *ipc_mixer = - (struct sof_ipc_comp_mixer *)comp; - struct mixer_data *md; - int ret; - - comp_cl_dbg(&comp_mixer, "mixer_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_mixer)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_mixer); - - mixer = COMP_GET_IPC(dev, sof_ipc_comp_mixer); - - ret = memcpy_s(mixer, sizeof(*mixer), ipc_mixer, - sizeof(struct sof_ipc_comp_mixer)); - assert(!ret); - - md = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*md)); - if (!md) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, md); - dev->state = COMP_STATE_READY; - return dev; -} - -static void mixer_free(struct comp_dev *dev) -{ - struct mixer_data *md = comp_get_drvdata(dev); - - comp_dbg(dev, "mixer_free()"); - - rfree(md); - rfree(dev); -} - -static int mixer_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int ret; - - comp_dbg(dev, "mixer_verify_params()"); - - ret = comp_verify_params(dev, BUFF_PARAMS_CHANNELS, params); - if (ret < 0) { - comp_err(dev, "mixer_verify_params() error: comp_verify_params() failed."); - return ret; - } - - return 0; -} -/* set component audio stream parameters */ -static int mixer_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *sinkb; - uint32_t period_bytes; - int err; - - comp_dbg(dev, "mixer_params()"); - - err = mixer_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "mixer_params(): pcm params verification failed."); - return -EINVAL; - } - - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - /* calculate period size based on config */ - period_bytes = dev->frames * audio_stream_frame_bytes(&sinkb->stream); - if (period_bytes == 0) { - comp_err(dev, "mixer_params() error: period_bytes = 0"); - return -EINVAL; - } - - if (sinkb->stream.size < config->periods_sink * period_bytes) { - comp_err(dev, "mixer_params() error: sink buffer size is insufficient"); - return -ENOMEM; - } - - return 0; -} - -static int mixer_source_status_count(struct comp_dev *mixer, uint32_t status) -{ - struct comp_buffer *source; - struct list_item *blist; - int count = 0; - - /* count source with state == status */ - list_for_item(blist, &mixer->bsource_list) { - source = container_of(blist, struct comp_buffer, sink_list); - if (source->source->state == status) - count++; - } - - return count; -} - -static inline int mixer_sink_status(struct comp_dev *mixer) -{ - struct comp_buffer *sink; - - sink = list_first_item(&mixer->bsink_list, struct comp_buffer, - source_list); - return sink->sink->state; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int mixer_trigger(struct comp_dev *dev, int cmd) -{ - int dir = dev->pipeline->source_comp->direction; - int ret; - - comp_dbg(dev, "mixer_trigger()"); - - ret = comp_set_state(dev, cmd); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - - /* nothing else to check for capture streams */ - if (dir == SOF_IPC_STREAM_CAPTURE) - return ret; - - /* don't stop mixer if at least one source is active */ - if (mixer_source_status_count(dev, COMP_STATE_ACTIVE) && - (cmd == COMP_TRIGGER_PAUSE || cmd == COMP_TRIGGER_STOP)) { - dev->state = COMP_STATE_ACTIVE; - ret = PPL_STATUS_PATH_STOP; - /* don't stop mixer if at least one source is paused */ - } else if (mixer_source_status_count(dev, COMP_STATE_PAUSED) && - cmd == COMP_TRIGGER_STOP) { - dev->state = COMP_STATE_PAUSED; - ret = PPL_STATUS_PATH_STOP; - } - - return ret; -} - -/* - * Mix N source PCM streams to one sink PCM stream. Frames copied is constant. - */ -static int mixer_copy(struct comp_dev *dev) -{ - struct mixer_data *md = comp_get_drvdata(dev); - struct comp_buffer *sink; - struct comp_buffer *sources[PLATFORM_MAX_STREAMS]; - const struct audio_stream *sources_stream[PLATFORM_MAX_STREAMS]; - struct comp_buffer *source; - struct list_item *blist; - int32_t i = 0; - int32_t num_mix_sources = 0; - uint32_t frames = INT32_MAX; - uint32_t source_bytes; - uint32_t sink_bytes; - uint32_t flags = 0; - - comp_dbg(dev, "mixer_copy()"); - - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - /* calculate the highest runtime component status - * between input streams - */ - list_for_item(blist, &dev->bsource_list) { - source = container_of(blist, struct comp_buffer, sink_list); - - /* only mix the sources with the same state with mixer */ - if (source->source->state == dev->state) { - sources[num_mix_sources] = source; - sources_stream[num_mix_sources] = &source->stream; - num_mix_sources++; - } - - /* too many sources ? */ - if (num_mix_sources == PLATFORM_MAX_STREAMS - 1) - return 0; - } - - /* don't have any work if all sources are inactive */ - if (num_mix_sources == 0) - return 0; - - buffer_lock(sink, &flags); - - /* check for underruns */ - for (i = 0; i < num_mix_sources; i++) { - buffer_lock(sources[i], &flags); - frames = MIN(frames, - audio_stream_avail_frames(sources_stream[i], - &sink->stream)); - buffer_unlock(sources[i], flags); - } - - buffer_unlock(sink, flags); - - /* Every source has the same format, so calculate bytes based - * on the first one. - */ - source_bytes = frames * audio_stream_frame_bytes(sources_stream[0]); - sink_bytes = frames * audio_stream_frame_bytes(&sink->stream); - - comp_dbg(dev, "mixer_copy(), source_bytes = 0x%x, sink_bytes = 0x%x", - source_bytes, sink_bytes); - - /* mix streams */ - for (i = num_mix_sources - 1; i >= 0; i--) - buffer_invalidate(sources[i], source_bytes); - md->mix_func(dev, &sink->stream, sources_stream, num_mix_sources, - frames); - buffer_writeback(sink, sink_bytes); - - /* update source buffer pointers */ - for (i = num_mix_sources - 1; i >= 0; i--) - comp_update_buffer_consume(sources[i], source_bytes); - - /* update sink buffer pointer */ - comp_update_buffer_produce(sink, sink_bytes); - - return 0; -} - -static int mixer_reset(struct comp_dev *dev) -{ - struct list_item *blist; - struct comp_buffer *source; - - comp_dbg(dev, "mixer_reset()"); - - list_for_item(blist, &dev->bsource_list) { - source = container_of(blist, struct comp_buffer, sink_list); - /* only mix the sources with the same state with mixer*/ - if (source->source->state > COMP_STATE_READY) - /* should not reset the downstream components */ - return 1; - } - - comp_set_state(dev, COMP_TRIGGER_RESET); - return 0; -} - -/* - * Prepare the mixer. The mixer may already be running at this point with other - * sources. Make sure we only prepare the "prepared" source streams and not - * the active or inactive sources. - * - * We should also make sure that we propagate the prepare call to downstream - * if downstream is not currently active. - */ -static int mixer_prepare(struct comp_dev *dev) -{ - struct mixer_data *md = comp_get_drvdata(dev); - struct list_item *blist; - struct comp_buffer *source; - struct comp_buffer *sink; - int downstream = 0; - int ret; - - comp_dbg(dev, "mixer_prepare()"); - - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - /* does mixer already have active source streams ? */ - if (dev->state != COMP_STATE_ACTIVE) { - /* currently inactive so setup mixer */ - switch (sink->stream.frame_fmt) { -#if CONFIG_FORMAT_S16LE - case SOF_IPC_FRAME_S16_LE: - md->mix_func = mix_n_s16; - break; -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - case SOF_IPC_FRAME_S24_4LE: - md->mix_func = mix_n_s32; - break; -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - case SOF_IPC_FRAME_S32_LE: - md->mix_func = mix_n_s32; - break; -#endif /* CONFIG_FORMAT_S32LE */ - default: - comp_err(dev, "unsupported data format"); - return -EINVAL; - } - - 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; - } - - /* check each mixer source state */ - list_for_item(blist, &dev->bsource_list) { - source = container_of(blist, struct comp_buffer, sink_list); - - /* only prepare downstream if we have no active sources */ - if (source->source->state == COMP_STATE_PAUSED || - source->source->state == COMP_STATE_ACTIVE) { - downstream = 1; - } - } - - /* prepare downstream */ - return downstream; -} - -static const struct comp_driver comp_mixer = { - .type = SOF_COMP_MIXER, - .uid = SOF_UUID(mixer_uuid), - .ops = { - .new = mixer_new, - .free = mixer_free, - .params = mixer_params, - .prepare = mixer_prepare, - .trigger = mixer_trigger, - .copy = mixer_copy, - .reset = mixer_reset, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_mixer_info = { - .drv = &comp_mixer, -}; - -UT_STATIC void sys_comp_mixer_init(void) -{ - comp_register(platform_shared_get(&comp_mixer_info, - sizeof(comp_mixer_info))); -} - -DECLARE_MODULE(sys_comp_mixer_init); diff --git a/src/audio/mixer/CMakeLists.txt b/src/audio/mixer/CMakeLists.txt new file mode 100644 index 000000000000..5adedc1e5e7a --- /dev/null +++ b/src/audio/mixer/CMakeLists.txt @@ -0,0 +1,2 @@ +add_local_sources(sof mixer.c mixer_generic.c mixer_hifi3.c) + diff --git a/src/audio/mixer/Kconfig b/src/audio/mixer/Kconfig new file mode 100644 index 000000000000..74560108d600 --- /dev/null +++ b/src/audio/mixer/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MIXER + bool "Mixer component" + depends on IPC_MAJOR_3 + default y + help + Select for Mixer component diff --git a/src/audio/mixer/README.md b/src/audio/mixer/README.md new file mode 100644 index 000000000000..eef844d0313c --- /dev/null +++ b/src/audio/mixer/README.md @@ -0,0 +1,22 @@ +# Mixer Architecture + +This directory contains the Mixer component. + +## Overview + +The Mixer adds together multiple input audio streams into a single output stream, applying required scaling or saturation logic. + +## Architecture Diagram + +```mermaid +graph TD + In1[Source 1] --> Mix[Mixer Core] + In2[Source 2] --> Mix + InN[Source N] --> Mix + Mix --> Out[Mixed Output] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the Mixer component (`COMP_MIXER`), which inherently depends on the older IPC framework `IPC_MAJOR_3`. +- **CMakeLists.txt**: Manages local base sources and optimized implementations (`mixer_generic.c`, `mixer_hifi3.c`) alongside the core `mixer.c`. diff --git a/src/audio/mixer/mixer.c b/src/audio/mixer/mixer.c new file mode 100644 index 000000000000..26023bb6a570 --- /dev/null +++ b/src/audio/mixer/mixer.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/base-config.h> +#include <user/trace.h> +#include <stddef.h> +#include <stdint.h> + +#include "mixer.h" + +LOG_MODULE_REGISTER(mixer, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(mixer); + +static int mixer_init(struct processing_module *mod) +{ + struct module_data *mod_data = &mod->priv; + struct comp_dev *dev = mod->dev; + struct mixer_data *md; + + comp_dbg(dev, "entry"); + + md = mod_zalloc(mod, sizeof(*md)); + if (!md) + return -ENOMEM; + + mod_data->private = md; + mod->verify_params_flags = BUFF_PARAMS_CHANNELS; + mod->no_pause = true; + mod->max_sources = MIXER_MAX_SOURCES; + + return 0; +} + +static int mixer_free(struct processing_module *mod) +{ + struct mixer_data *md = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + mod_free(mod, md); + + return 0; +} + +/* + * Mix N source PCM streams to one sink PCM stream. Frames copied is constant. + */ +static int mixer_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 mixer_data *md = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + const struct audio_stream *sources_stream[PLATFORM_MAX_STREAMS]; + int sources_indices[PLATFORM_MAX_STREAMS]; + int32_t i = 0, j = 0; + uint32_t frames = INT32_MAX; + /* Redundant, but helps the compiler */ + uint32_t source_bytes = 0; + uint32_t sink_bytes; + int active_input_buffers = 0; + + comp_dbg(dev, "%d", num_input_buffers); + + /* too many sources ? */ + if (num_input_buffers >= PLATFORM_MAX_STREAMS) + return -EINVAL; + + /* check for underruns */ + for (i = 0; i < num_input_buffers; i++) { + uint32_t avail_frames; + + avail_frames = audio_stream_avail_frames_aligned(mod->input_buffers[i].data, + mod->output_buffers[0].data); + + /* if one source is inactive, skip it */ + if (avail_frames == 0) + continue; + + active_input_buffers++; + frames = MIN(frames, avail_frames); + } + + if (!active_input_buffers) { + /* + * Generate silence when sources are inactive. When + * sources change to active, additionally keep + * generating silence until at least one of the + * sources start to have data available (frames!=0). + */ + sink_bytes = dev->frames * audio_stream_frame_bytes(mod->output_buffers[0].data); + if (!audio_stream_set_zero(mod->output_buffers[0].data, sink_bytes)) + mod->output_buffers[0].size = sink_bytes; + + return 0; + } + + /* Every source has the same format, so calculate bytes based on the first one */ + source_bytes = frames * audio_stream_frame_bytes(mod->input_buffers[0].data); + + sink_bytes = frames * audio_stream_frame_bytes(mod->output_buffers[0].data); + + comp_dbg(dev, "source_bytes = 0x%x, sink_bytes = 0x%x", + source_bytes, sink_bytes); + + /* mix streams */ + for (i = 0; i < num_input_buffers; i++) { + uint32_t avail_frames; + + avail_frames = audio_stream_avail_frames_aligned(mod->input_buffers[i].data, + mod->output_buffers[0].data); + + /* if one source is inactive, skip it */ + if (avail_frames == 0) + continue; + + sources_indices[j] = i; + sources_stream[j++] = mod->input_buffers[i].data; + } + + if (j) + md->mix_func(dev, mod->output_buffers[0].data, sources_stream, j, frames); + mod->output_buffers[0].size = sink_bytes; + + /* update source buffer consumed bytes */ + for (i = 0; i < j; i++) + mod->input_buffers[sources_indices[i]].consumed = source_bytes; + + return 0; +} + +static int mixer_reset(struct processing_module *mod) +{ + struct mixer_data *md = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int dir = dev->pipeline->source_comp->direction; + + comp_dbg(dev, "entry"); + + if (dir == SOF_IPC_STREAM_PLAYBACK) { + struct comp_buffer *source; + + comp_dev_for_each_producer(dev, source) { + /* FIXME: this is racy and implicitly protected by serialised IPCs */ + bool stop = false; + + if (comp_buffer_get_source_state(source) > COMP_STATE_READY) + stop = true; + + /* only mix the sources with the same state with mixer */ + if (stop) + /* should not reset the downstream components */ + return PPL_STATUS_PATH_STOP; + } + } + + md->mix_func = NULL; + + return 0; +} + +/* init and calculate the aligned setting for available frames and free frames retrieve*/ +static inline void mixer_set_frame_alignment(struct audio_stream *source) +{ + + /* Xtensa intrinsics ask for 8-byte aligned. 5.1 format SSE audio + * requires 16-byte aligned. Note: The SOF_FRAME_BYTE_ALIGN is the + * same value 16 with HiFi5. + */ + const uint32_t byte_align = audio_stream_get_channels(source) == 6 ? + MIXER_HIFI_FRAME_BYTE_ALIGN_6CH : SOF_FRAME_BYTE_ALIGN; + + /* There is no limit for frame number, so set it as default (1). */ + const uint32_t frame_align_req = SOF_FRAME_COUNT_ALIGN; + + audio_stream_set_align(byte_align, frame_align_req, source); +} + +static int mixer_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct mixer_data *md = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sink; + + sink = comp_dev_get_first_data_consumer(dev); + if (!sink) { + comp_err(dev, "no sink"); + return -ENOTCONN; + } + + md->mix_func = mixer_get_processing_function(dev, sink); + + /* No need to set sink align constraints, set constraints for each + * source next. The sink align will follow to common source alignment. + */ + + /* check each mixer source state */ + struct comp_buffer *source; + + comp_dev_for_each_producer(dev, source) { + bool stop; + + /* + * FIXME: this is intrinsically racy. One of mixer sources can + * run on a different core and can enter PAUSED or ACTIVE right + * after we have checked it here. We should set a flag or a + * status to inform any other connected pipelines that we're + * preparing the mixer, so they shouldn't touch it until we're + * done. + */ + mixer_set_frame_alignment(&source->stream); + stop = comp_buffer_get_source_state(source) == COMP_STATE_PAUSED || + comp_buffer_get_source_state(source) == COMP_STATE_ACTIVE; + + /* only prepare downstream if we have no active sources */ + if (stop) + return PPL_STATUS_PATH_STOP; + } + + /* prepare downstream */ + return 0; +} + +static const struct module_interface mixer_interface = { + .init = mixer_init, + .prepare = mixer_prepare, + .process_audio_stream = mixer_process, + .reset = mixer_reset, + .free = mixer_free, +}; + +DECLARE_TR_CTX(mixer_tr, SOF_UUID(mixer_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(mixer_interface, mixer_uuid, mixer_tr); +SOF_MODULE_INIT(mixer, sys_comp_module_mixer_interface_init); diff --git a/src/audio/mixer/mixer.h b/src/audio/mixer/mixer.h new file mode 100644 index 000000000000..875ddcbb26fe --- /dev/null +++ b/src/audio/mixer/mixer.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_MIXER_H__ +#define __SOF_AUDIO_MIXER_H__ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/platform.h> +#include <stddef.h> +#include <stdint.h> + +#ifdef UNIT_TEST +void sys_comp_module_mixer_interface_init(void); +#endif + +#define MIXER_GENERIC + +#if defined(__XCC__) +#include <xtensa/config/core-isa.h> + +#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4 +#undef MIXER_GENERIC +#endif + +#endif + +#define MIXER_MAX_SOURCES 2 + +/* Xtensa HiFi optimized version needs this for 5.1ch */ +#define MIXER_HIFI_FRAME_BYTE_ALIGN_6CH 16 + +/* mixer component private data */ +struct mixer_data { + void (*mix_func)(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t count, + uint32_t frames); +}; + +/** + * \brief mixer processing function interface + */ +typedef void (*mixer_func)(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames); + +/** \brief Volume processing functions map. */ +struct mixer_func_map { + enum sof_ipc_frame frame_fmt; /**< frame format */ + mixer_func func; /**< volume processing function */ +}; + +/** \brief Map of formats with dedicated processing functions. */ +extern const struct mixer_func_map mixer_func_map[]; + +/** \brief Number of processing functions. */ +extern const size_t mixer_func_count; + +/** + * \brief Retrievies mixer processing function. + * \param[in,out] dev Mixer base component device. + * \param[in] sinkb Sink buffer to match against + */ +static inline mixer_func mixer_get_processing_function(struct comp_dev *dev, + struct comp_buffer *sinkb) +{ + int i; + + /* map the volume function for source and sink buffers */ + for (i = 0; i < mixer_func_count; i++) { + if (audio_stream_get_frm_fmt(&sinkb->stream) != mixer_func_map[i].frame_fmt) + continue; + + return mixer_func_map[i].func; + } + + return NULL; +} + +#endif /* __SOF_AUDIO_MIXER_H__ */ diff --git a/src/audio/mixer/mixer_generic.c b/src/audio/mixer/mixer_generic.c new file mode 100644 index 000000000000..2b1b50501187 --- /dev/null +++ b/src/audio/mixer/mixer_generic.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> + +#include <sof/common.h> + +#include "mixer.h" + +#ifdef MIXER_GENERIC + +#if CONFIG_FORMAT_S16LE +/* Mix n 16 bit PCM source streams to one sink stream */ +static void mix_n_s16(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames) +{ + int16_t *src[PLATFORM_MAX_CHANNELS]; + int16_t *dest; + int32_t val; + int nmax; + int i, j, n, ns; + int processed = 0; + int nch = audio_stream_get_channels(sink); + int samples = frames * nch; + + dest = audio_stream_get_wptr(sink); + for (j = 0; j < num_sources; j++) + src[j] = audio_stream_get_rptr(sources[j]); + + while (processed < samples) { + nmax = samples - processed; + n = audio_stream_samples_without_wrap_s16(sink, dest); + n = MIN(n, nmax); + for (i = 0; i < num_sources; i++) { + ns = audio_stream_samples_without_wrap_s16(sources[i], src[i]); + n = MIN(n, ns); + } + for (i = 0; i < n; i++) { + val = 0; + for (j = 0; j < num_sources; j++) { + val += *src[j]; + src[j]++; + } + + /* Saturate to 16 bits */ + *dest = sat_int16(val); + dest++; + } + processed += n; + dest = audio_stream_wrap(sink, dest); + for (i = 0; i < num_sources; i++) + src[i] = audio_stream_wrap(sources[i], src[i]); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +/* Mix n 24 bit PCM source streams to one sink stream */ +static void mix_n_s24(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames) +{ + int32_t *src[PLATFORM_MAX_CHANNELS]; + int32_t *dest; + int32_t val; + int32_t x; + int nmax; + int i, j, n, ns; + int processed = 0; + int nch = audio_stream_get_channels(sink); + int samples = frames * nch; + + dest = audio_stream_get_wptr(sink); + for (j = 0; j < num_sources; j++) + src[j] = audio_stream_get_rptr(sources[j]); + + while (processed < samples) { + nmax = samples - processed; + n = audio_stream_samples_without_wrap_s24(sink, dest); + n = MIN(n, nmax); + for (i = 0; i < num_sources; i++) { + ns = audio_stream_samples_without_wrap_s24(sources[i], src[i]); + n = MIN(n, ns); + } + for (i = 0; i < n; i++) { + val = 0; + for (j = 0; j < num_sources; j++) { + x = *src[j] << 8; + val += x >> 8; /* Sign extend */ + src[j]++; + } + + /* Saturate to 24 bits */ + *dest = sat_int24(val); + dest++; + } + processed += n; + dest = audio_stream_wrap(sink, dest); + for (i = 0; i < num_sources; i++) + src[i] = audio_stream_wrap(sources[i], src[i]); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/* Mix n 32 bit PCM source streams to one sink stream */ +static void mix_n_s32(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames) +{ + int32_t *src[PLATFORM_MAX_CHANNELS]; + int32_t *dest; + int64_t val; + int nmax; + int i, j, n, ns; + int processed = 0; + int nch = audio_stream_get_channels(sink); + int samples = frames * nch; + + dest = audio_stream_get_wptr(sink); + for (j = 0; j < num_sources; j++) + src[j] = audio_stream_get_rptr(sources[j]); + + while (processed < samples) { + nmax = samples - processed; + n = audio_stream_samples_without_wrap_s32(sink, dest); + n = MIN(n, nmax); + for (i = 0; i < num_sources; i++) { + ns = audio_stream_samples_without_wrap_s32(sources[i], src[i]); + n = MIN(n, ns); + } + for (i = 0; i < n; i++) { + val = 0; + for (j = 0; j < num_sources; j++) { + val += *src[j]; + src[j]++; + } + + /* Saturate to 32 bits */ + *dest = sat_int32(val); + dest++; + } + processed += n; + dest = audio_stream_wrap(sink, dest); + for (i = 0; i < num_sources; i++) + src[i] = audio_stream_wrap(sources[i], src[i]); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct mixer_func_map mixer_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, mix_n_s16 }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, mix_n_s24 }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, mix_n_s32 }, +#endif +}; + +const size_t mixer_func_count = ARRAY_SIZE(mixer_func_map); + +#endif diff --git a/src/audio/mixer/mixer_hifi3.c b/src/audio/mixer/mixer_hifi3.c new file mode 100644 index 000000000000..0d774208655e --- /dev/null +++ b/src/audio/mixer/mixer_hifi3.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> + +#include <sof/common.h> + +#include "mixer.h" + +#if __XCC__ && (XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4) + +#include <xtensa/tie/xt_hifi3.h> + +#if CONFIG_FORMAT_S16LE +/* Mix n 16 bit PCM source streams to one sink stream */ +static void mix_n_s16(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames) +{ + ae_int16x4 * in[PLATFORM_MAX_CHANNELS]; + ae_int16x4 *out = audio_stream_get_wptr(sink); + ae_int16x4 sample = AE_ZERO16(); + ae_int16x4 res = AE_ZERO16(); + ae_int32x2 val1; + ae_int32x2 val2; + ae_int32x2 sample_1; + ae_int32x2 sample_2; + unsigned int n, m, nmax, i, j, left_samples; + 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 (left_samples = samples; left_samples; left_samples -= n) { + out = audio_stream_wrap(sink, out); + nmax = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(left_samples, nmax); + for (j = 0; j < num_sources; j++) { + in[j] = audio_stream_wrap(sources[j], in[j]); + nmax = audio_stream_samples_without_wrap_s16(sources[j], in[j]); + n = MIN(n, nmax); + } + m = n >> 2; + + for (i = 0; i < m; i++) { + val1 = AE_ZERO32(); + val2 = AE_ZERO32(); + for (j = 0; j < num_sources; j++) { + /* load four 16 bit samples, 8 is sizeof(ae_int16x4) */ + AE_L16X4_IP(sample, in[j], 8); + sample_1 = AE_SEXT32X2D16_32(sample); + sample_2 = AE_SEXT32X2D16_10(sample); + val1 = AE_ADD32S(val1, sample_1); + val2 = AE_ADD32S(val2, sample_2); + } + /*Saturate to 16 bits */ + val1 = AE_SRAA32S(AE_SLAA32S(val1, 16), 16); + val2 = AE_SRAA32S(AE_SLAA32S(val2, 16), 16); + + /* truncate the LSB 16bit of four 32-bit signed elements*/ + res = AE_CVT16X4(val1, val2); + + /* store four 16 bit samples, 8 is sizeof(ae_int16x4) */ + AE_S16X4_IP(res, out, 8); + } + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +/* Mix n 24 bit PCM source streams to one sink stream */ +static void mix_n_s24(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames) +{ + ae_int32x2 *in[PLATFORM_MAX_CHANNELS]; + 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 * audio_stream_get_channels(sink); + + for (j = 0; j < num_sources; j++) + in[j] = audio_stream_get_rptr(sources[j]); + + for (left_samples = samples; left_samples; left_samples -= n) { + out = audio_stream_wrap(sink, out); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(left_samples, nmax); + for (j = 0; j < num_sources; j++) { + in[j] = audio_stream_wrap(sources[j], in[j]); + nmax = audio_stream_samples_without_wrap_s32(sources[j], in[j]); + n = MIN(n, nmax); + } + m = n >> 1; + for (i = 0; i < m; i++) { + val = AE_ZERO32(); + for (j = 0; j < num_sources; j++) { + /* load two 32 bit samples, 8 is sizeof(ae_int32x2) */ + AE_L32X2_IP(sample, in[j], 8); + /* Sign extend */ + sample = AE_SRAA32RS(AE_SLAI32(sample, 8), 8); + val = AE_ADD32S(val, sample); + } + /*Saturate to 24 bits */ + val = AE_SRAA32S(AE_SLAA32S(val, 8), 8); + + /* store two 32 bit samples, 8 is sizeof(ae_int32x2) */ + AE_S32X2_IP(val, out, 8); + } + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/* Mix n 32 bit PCM source streams to one sink stream */ +static void mix_n_s32(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t num_sources, + uint32_t frames) +{ + ae_q32s * in[PLATFORM_MAX_CHANNELS]; + 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 * audio_stream_get_channels(sink); + + for (j = 0; j < num_sources; j++) + in[j] = audio_stream_get_rptr(sources[j]); + + for (left_samples = samples; left_samples; left_samples -= n) { + out = audio_stream_wrap(sink, out); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(left_samples, nmax); + for (j = 0; j < num_sources; j++) { + in[j] = audio_stream_wrap(sources[j], in[j] + m); + nmax = audio_stream_samples_without_wrap_s32(sources[j], in[j]); + n = MIN(n, nmax); + } + /*record the processed samples for next address iteration */ + m = n; + for (i = 0; i < m; i++) { + val = AE_ZERO64(); + for (j = 0; j < num_sources; j++) { + /* load one 32 bit sample */ + sample = AE_L32M_X(in[j], i * sizeof(ae_q32s)); + val = AE_ADD64S(val, sample); + } + /*Saturate to 32 bits */ + res = AE_ROUND32X2F48SSYM(val, val); + + /* store one 32 bit samples */ + AE_S32_L_IP(res, out, sizeof(ae_int32)); + } + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct mixer_func_map mixer_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, mix_n_s16 }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, mix_n_s24 }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, mix_n_s32 }, +#endif +}; + +const size_t mixer_func_count = ARRAY_SIZE(mixer_func_map); + +#endif diff --git a/src/audio/mixin_mixout/CMakeLists.txt b/src/audio/mixin_mixout/CMakeLists.txt new file mode 100644 index 000000000000..11eccf85f499 --- /dev/null +++ b/src/audio/mixin_mixout/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_MIXIN_MIXOUT STREQUAL "m" AND DEFINED CONFIG_LLEXT) + + add_subdirectory(llext ${PROJECT_BINARY_DIR}/mixin_mixout_llext) + add_dependencies(app mixin_mixout) + +else() + + add_local_sources(sof mixin_mixout.c mixin_mixout_generic.c mixin_mixout_hifi3.c mixin_mixout_hifi5.c) + +endif() diff --git a/src/audio/mixin_mixout/Kconfig b/src/audio/mixin_mixout/Kconfig new file mode 100644 index 000000000000..73016a667bd7 --- /dev/null +++ b/src/audio/mixin_mixout/Kconfig @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MIXIN_MIXOUT + tristate "Mixin_mixout component" + depends on IPC_MAJOR_4 + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for Mixin_mixout component + +choice "MIXIN_MIXOUT_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for MIXIN_MIXOUT module" + depends on COMP_MIXIN_MIXOUT + default MIXIN_MIXOUT_HIFI_MAX + + config MIXIN_MIXOUT_HIFI_MAX + prompt "Max HiFi level available in the toolchain" + bool + help + When this was selected, optimization level will be determined + by toolchain. + + config MIXIN_MIXOUT_HIFI_5 + prompt "choose HIFI4 intrinsic optimized MIXIN_MIXOUT module" + bool + help + This option used to build HIFI4 optimized MIXIN_MIXOUT code + + config MIXIN_MIXOUT_HIFI_4 + prompt "choose HIFI4 intrinsic optimized MIXIN_MIXOUT module" + bool + help + This option used to build HIFI4 optimized MIXIN_MIXOUT code + + config MIXIN_MIXOUT_HIFI_3 + prompt "choose HIFI3 intrinsic optimized MIXIN_MIXOUT module" + bool + help + This option used to build HIFI3 intrinsic optimized MIXIN_MIXOUT code + + config MIXIN_MIXOUT_HIFI_NONE + prompt "choose generic C MIXIN_MIXOUT module, no HIFI SIMD involved" + bool + help + This option used to build MIXIN_MIXOUT generic code. +endchoice diff --git a/src/audio/mixin_mixout/README.md b/src/audio/mixin_mixout/README.md new file mode 100644 index 000000000000..a73b39e7655b --- /dev/null +++ b/src/audio/mixin_mixout/README.md @@ -0,0 +1,14 @@ +# Mix-In / Mix-Out Architecture + +This directory provides specialized Mix-in and Mix-out instances. + +## Overview + +These components typically act as routing endpoints to inject or extract specific streams in/out of an ongoing audio mix. + +## Configuration and Scripts + +- **Kconfig**: Compiles the Mixin_mixout component (`COMP_MIXIN_MIXOUT`), which depends on the modern `IPC_MAJOR_4`. Allows choosing SIMD optimization logic explicitly. +- **CMakeLists.txt**: Integrates generic, HIFI3, and HIFI5 specialized processing source files. Fully supports modular execution via `llext`. +- **mixin_mixout.toml**: Extensive configuration separating `MIXIN` and `MIXOUT` instances. Configures UUIDs, domain types, and highly localized `mod_cfg` arrays adapted for `CONFIG_METEORLAKE`, `CONFIG_LUNARLAKE`, and ACE SOCs. +- **Topology (.conf)**: Uses `tools/topology/topology2/include/components/mixin.conf` (type `mixer` with `mix_type` `"mix_in"`, defaulting to UUID `b2:6e:65:39:71:3b:49:40:8d:3f:f9:2c:d5:c4:3c:09`, supporting 3 output pins) and `mixout.conf` (type `mixer` with `mix_type` `"mix_out"`, defaulting to UUID `5a:50:56:3c:d7:24:8f:41:bd:dc:c1:f5:a3:ac:2a:e0`, mapping to 8 input pins). Both force a 32-bit depth processing format. diff --git a/src/audio/mixin_mixout/llext/CMakeLists.txt b/src/audio/mixin_mixout/llext/CMakeLists.txt new file mode 100644 index 000000000000..300130fbe82e --- /dev/null +++ b/src/audio/mixin_mixout/llext/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("mixin_mixout" + SOURCES ../mixin_mixout.c + ../mixin_mixout_hifi3.c + ../mixin_mixout_hifi5.c + ../mixin_mixout_generic.c + LIB openmodules +) diff --git a/src/audio/mixin_mixout/llext/llext.toml.h b/src/audio/mixin_mixout/llext/llext.toml.h new file mode 100644 index 000000000000..bfadd2c55a96 --- /dev/null +++ b/src/audio/mixin_mixout/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../mixin_mixout.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/mixin_mixout/mixin_mixout.c b/src/audio/mixin_mixout/mixin_mixout.c new file mode 100644 index 000000000000..81dfb20e143e --- /dev/null +++ b/src/audio/mixin_mixout/mixin_mixout.c @@ -0,0 +1,1053 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <sof/compiler_attributes.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/base-config.h> +#include <ipc4/notification.h> +#include <user/trace.h> +#include <stddef.h> +#include <stdint.h> + +#include "mixin_mixout.h" + +LOG_MODULE_REGISTER(mixin_mixout, CONFIG_SOF_LOG_LEVEL); + +/* mixin 39656eb2-3b71-4049-8d3f-f92cd5c43c09 */ +SOF_DEFINE_REG_UUID(mixin); + +/* mixout 3c56505a-24d7-418f-bddc-c1f5a3ac2ae0 */ +SOF_DEFINE_REG_UUID(mixout); + +#define MIXIN_MAX_SINKS IPC4_MIXIN_MODULE_MAX_OUTPUT_QUEUES +#define MIXOUT_MAX_SOURCES IPC4_MIXOUT_MODULE_MAX_INPUT_QUEUES + +/* + * Unfortunately, if we have to support a topology with a single mixin + * connected to multiple mixouts, we cannot use simple implementation as in + * mixer component. We either need to use intermediate buffer between mixin and + * mixout, or use a more complex implementation as described below. + * + * This implementation does not use buffer between mixin and mixout. Mixed + * data is written directly to mixout sink buffer. Most of the mixing is done + * by mixins in mixin_process(). Simply speaking, if no data present in mixout + * sink -- mixin just copies its source data to mixout sink. If mixout sink + * has some data (written there previously by some other mixin) -- mixin reads + * data from mixout sink, mixes it with its source data and writes back to + * mixout sink. + * + * Such implementation has less buffer reads/writes than simple implementation + * using intermediate buffer between mixin and mixout. + */ + +struct mixin_sink_config { + enum ipc4_mixer_mode mixer_mode; + uint32_t output_channel_count; + uint32_t output_channel_map; + /* Gain as described in struct ipc4_mixer_mode_sink_config */ + uint16_t gain; +}; + +/* mixin component private data */ +struct mixin_data { + mix_func mix; + mix_func gain_mix; + struct mixin_sink_config sink_config[MIXIN_MAX_SINKS]; +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + uint32_t last_reported_underrun; + uint32_t underrun_notification_period; + uint32_t eos_delay_periods; + bool eos_delay_configured; +#endif +}; + +/* + * Mixin calls "consume" on its source data but never calls "produce" -- that one is called + * by mixout for its sink data. So between mixin_process() and mixout_process() a number of + * consumed (in mixin) yet not produced (in mixout) frames should be stored for each mixin + * and mixout pair. + */ +struct pending_frames { + struct comp_dev *mixin; + uint32_t frames; +}; + +/* mixout component private data */ +struct mixout_data { + /* number of currently mixed frames in mixout sink buffer */ + uint32_t mixed_frames; + + /* + * Source data is consumed by mixins in mixin_process() but sink data cannot be + * immediately produced. Sink data is produced by mixout in mixout_process() after + * ensuring all connected mixins have mixed their data into mixout sink buffer. + * So for each connected mixin, mixout keeps knowledge of data already consumed + * by mixin but not yet produced in mixout. + */ + struct pending_frames pending_frames[MIXOUT_MAX_SOURCES]; + + /* + * When several mixins are connected to one mixout (a typical case) mixout sink + * buffer is acquired (via sink_get_buffer() call) in mixin_process() of first + * mixin. Other connected mixins just use a pointer to the buffer stored below. + * The buffer is released (committed by sink_commit_buffer() call) in mixout_process(). + */ + struct cir_buf_ptr acquired_buf; + uint32_t acquired_buf_free_frames; +}; + +/* NULL is also a valid mixin argument: in such case the function returns first unused entry */ +static struct pending_frames *get_mixin_pending_frames(struct mixout_data *mixout_data, + const struct comp_dev *mixin) +{ + int i; + + for (i = 0; i < MIXOUT_MAX_SOURCES; i++) + if (mixout_data->pending_frames[i].mixin == mixin) + return &mixout_data->pending_frames[i]; + + return NULL; +} + +static int mixin_init(struct processing_module *mod) +{ + struct module_data *mod_data = &mod->priv; + struct comp_dev *dev = mod->dev; + struct mixin_data *md; + int i; + + comp_dbg(dev, "entry"); + + md = mod_zalloc(mod, sizeof(*md)); + if (!md) + return -ENOMEM; + + mod_data->private = md; +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + md->underrun_notification_period = MIXIN_MODULE_DEFAULT_UNDERRUN_NOTIFICATION_PERIOD; +#endif + + for (i = 0; i < MIXIN_MAX_SINKS; i++) { + md->sink_config[i].mixer_mode = IPC4_MIXER_NORMAL_MODE; + md->sink_config[i].gain = IPC4_MIXIN_UNITY_GAIN; + } + + mod->skip_src_buffer_invalidate = true; + + mod->max_sinks = MIXIN_MAX_SINKS; + return 0; +} + +static int mixout_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct mixout_data *mo_data; + + comp_dbg(dev, "entry"); + + mo_data = mod_zalloc(mod, sizeof(*mo_data)); + if (!mo_data) + return -ENOMEM; + + mod->priv.private = mo_data; + + mod->skip_sink_buffer_writeback = true; + + mod->max_sources = MIXOUT_MAX_SOURCES; + return 0; +} + +static int mixin_free(struct processing_module *mod) +{ + struct mixin_data *md = module_get_private_data(mod); + + mod_free(mod, md); + + return 0; +} + +static int mixout_free(struct processing_module *mod) +{ + mod_free(mod, module_get_private_data(mod)); + + return 0; +} + +static int mix(struct comp_dev *dev, const struct mixin_data *mixin_data, + uint16_t sink_index, struct cir_buf_ptr *sink, + uint32_t start_sample, uint32_t mixed_samples, + const struct cir_buf_ptr *source, uint32_t sample_count) +{ + const struct mixin_sink_config *sink_config; + + if (sink_index >= MIXIN_MAX_SINKS) { + comp_err(dev, "Sink index out of range: %u, max sinks count: %u", + (uint32_t)sink_index, MIXIN_MAX_SINKS); + return -EINVAL; + } + + sink_config = &mixin_data->sink_config[sink_index]; + + if (sink_config->gain == IPC4_MIXIN_UNITY_GAIN) { + mixin_data->mix(sink, start_sample, mixed_samples, + source, sample_count, sink_config->gain); + } else { + mixin_data->gain_mix(sink, start_sample, mixed_samples, + source, sample_count, sink_config->gain); + } + + return 0; +} + +/* mix silence into stream, i.e. set not yet mixed data in stream to zero */ +static void silence(struct cir_buf_ptr *stream, uint32_t start_offset, + uint32_t mixed_bytes, uint32_t size) +{ + uint32_t skip_mixed_bytes; + uint8_t *ptr; + int n; + + assert(mixed_bytes >= start_offset); + skip_mixed_bytes = mixed_bytes - start_offset; + + if (size <= skip_mixed_bytes) + return; + + size -= skip_mixed_bytes; + ptr = (uint8_t *)stream->ptr + mixed_bytes; + + while (size) { + ptr = cir_buf_wrap(ptr, stream->buf_start, stream->buf_end); + n = MIN((uint8_t *)stream->buf_end - ptr, size); + memset(ptr, 0, n); + size -= n; + ptr += n; + } +} + +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE +static void mixin_check_notify_underrun(struct comp_dev *dev, struct mixin_data *mixin_data, + enum sof_audio_buffer_state state, + size_t source_avail, size_t sinks_free) +{ + const bool eos_detected = state == AUDIOBUF_STATE_END_OF_STREAM_FLUSH || + state == AUDIOBUF_STATE_END_OF_STREAM; + + mixin_data->last_reported_underrun++; + + if (!source_avail || eos_detected) { + if (eos_detected) { + if (mixin_data->eos_delay_configured) { + mixin_data->eos_delay_periods--; + } else { + pipeline_get_dai_comp_latency(dev->pipeline->pipeline_id, + &mixin_data->eos_delay_periods); + mixin_data->eos_delay_configured = true; + } + } + + if ((!eos_detected && mixin_data->last_reported_underrun >= + mixin_data->underrun_notification_period) || + (eos_detected && mixin_data->eos_delay_periods == 0)) { + mixin_data->last_reported_underrun = 0; + + send_mixer_underrun_notif_msg(dev->ipc_config.id, eos_detected, + source_avail, sinks_free); + } + } +} +#endif + +/* Most of the mixing is done here on mixin side. mixin mixes its source data + * into each connected mixout sink buffer. Basically, if mixout sink buffer has + * no data, mixin copies its source data into mixout sink buffer. If mixout sink + * buffer has some data (written there by other mixin), mixin reads mixout sink + * buffer data, mixes it with its source data and writes back to mixout sink + * buffer. So after all mixin mixin_process() calls, mixout sink buffer contains + * mixed data. Every mixin calls xxx_consume() on its processed source data, but + * they do not call xxx_produce(). That is done on mixout side in mixout_process(). + * + * Since there is no garantie that mixout processing is done in time we have + * to account for a possibility having not yet produced data in mixout sink + * buffer that was written there on previous run(s) of mixin_process(). So for each + * mixin <--> mixout pair we track consumed yet not produced (pending_frames) data + * amount. That value is also used in mixout_process() to calculate how many data + * was actually mixed and so xxx_produce() is called for that amount. + */ +static int mixin_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct mixin_data *mixin_data = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint32_t source_avail_frames, sinks_free_frames; + struct processing_module *active_mixouts[MIXIN_MAX_SINKS]; + uint16_t sinks_ids[MIXIN_MAX_SINKS]; + struct pending_frames *pending_frames; + uint32_t bytes_to_consume = 0; + uint32_t frames_to_copy; + size_t frame_bytes; + int i, ret; + struct cir_buf_ptr source_ptr; + + comp_dbg(dev, "entry"); + + source_avail_frames = source_get_data_frames_available(sources[0]); + sinks_free_frames = INT32_MAX; + + if (num_of_sinks > MIXIN_MAX_SINKS) { + comp_err(dev, "Invalid output sink count %d", + num_of_sinks); + return -EINVAL; + } + + /* first, let's find out how many frames can be now processed -- + * it is a minimal value among frames available in source buffer + * and frames free in each connected mixout sink buffer. + */ + for (i = 0; i < num_of_sinks; i++) { + struct comp_buffer *unused_in_between_buf; + struct comp_dev *mixout; + struct sof_sink *mixout_sink; + struct mixout_data *mixout_data; + struct processing_module *mixout_mod; + uint32_t free_frames; + + /* WORKAROUND: since mixin is always connected to mixout, we can safely assume + * mixin sink interface is implemented via comp_buffer. This is, of course, + * not the case for other modules. + * TODO: find out a solution to reach mixout without knowledge of mixin + * sof_sink implementation. + */ + /* unused buffer between mixin and mixout */ + unused_in_between_buf = comp_buffer_get_from_sink(sinks[i]); + mixout = comp_buffer_get_sink_component(unused_in_between_buf); + + /* Skip non-active mixout like it is not connected so it does not + * block other possibly connected mixouts. In addition, non-active + * mixouts might have their sink buffer/interface not yet configured. + */ + if (mixout->state != COMP_STATE_ACTIVE) { + active_mixouts[i] = NULL; + continue; + } + + mixout_mod = comp_mod(mixout); + active_mixouts[i] = mixout_mod; + mixout_sink = mixout_mod->sinks[0]; + + /* mixout might be created on another pipeline. Its sink stream params are usually + * configured in .prepare(). It is possible that such .prepare() was not yet called + * for mixout pipeline. Hence the check above if mixout state is active. However, + * let's just in case check here if sink stream params are really configured as + * proceeding with unconfigured sink will lead to hard to debug bugs. + * Unconfigured stream params are filled with zeros. + * TODO: introduce something like sink_is_configured() ? + */ + if (!mixout_sink || sink_get_channels(mixout_sink) == 0) { + comp_err(dev, "mixout sink not configured!"); + return -EINVAL; + } + + sinks_ids[i] = IPC4_SRC_QUEUE_ID(buf_get_id(unused_in_between_buf)); + + mixout_data = module_get_private_data(mixout_mod); + pending_frames = get_mixin_pending_frames(mixout_data, dev); + if (!pending_frames) { + comp_err(dev, "No source info"); + return -EINVAL; + } + + /* In theory, though unlikely, mixout sink can be connected to some module on + * another core. In this case free space in mixout sink buffer can suddenly increase + * (data consumed on another core) after the buffer was already acquired. Let's only + * access free space that was at the moment of acquiring the buffer. + */ + free_frames = mixout_data->acquired_buf.ptr ? + mixout_data->acquired_buf_free_frames : + sink_get_free_frames(mixout_sink); + + /* mixout sink buffer may still have not yet produced data -- data + * consumed and written there by mixin on previous mixin_process() run. + * We do NOT want to overwrite that data. + */ + assert(free_frames >= pending_frames->frames); + sinks_free_frames = MIN(sinks_free_frames, free_frames - pending_frames->frames); + } + + if (sinks_free_frames == 0 || sinks_free_frames == INT32_MAX) + return 0; + +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + frame_bytes = source_get_frame_bytes(sources[0]); + const size_t min_frames = MIN(dev->frames, sinks_free_frames); + + mixin_check_notify_underrun(dev, mixin_data, source_get_state(sources[0]), + source_avail_frames * frame_bytes, + min_frames * frame_bytes); +#endif + + if (source_avail_frames > 0) { + size_t buf_size; + + frames_to_copy = MIN(source_avail_frames, sinks_free_frames); + bytes_to_consume = frames_to_copy * source_get_frame_bytes(sources[0]); + + source_get_data(sources[0], bytes_to_consume, (const void **)&source_ptr.ptr, + (const void **)&source_ptr.buf_start, &buf_size); + source_ptr.buf_end = (uint8_t *)source_ptr.buf_start + buf_size; + } else { + /* if source does not produce any data -- do NOT block mixing but generate + * silence as that source output. + * + * here frames_to_copy is silence size. + * + * FIXME: does not work properly for freq like 44.1 kHz. + */ + frames_to_copy = MIN(dev->frames, sinks_free_frames); + } + + /* iterate over all connected mixouts and mix source data into each mixout sink buffer */ + for (i = 0; i < num_of_sinks; i++) { + struct mixout_data *mixout_data; + struct processing_module *mixout_mod; + uint32_t start_frame; + + mixout_mod = active_mixouts[i]; + if (!mixout_mod) + continue; + + mixout_data = module_get_private_data(mixout_mod); + pending_frames = get_mixin_pending_frames(mixout_data, dev); + if (!pending_frames) { + comp_err(dev, "No source info"); + return -EINVAL; + } + + /* Skip data from previous run(s) not yet produced in mixout_process(). + * Normally start_frame would be 0 unless mixout pipeline has serious + * performance problems with processing data on time in mixout. + */ + start_frame = pending_frames->frames; + + /* mixout sink buffer is acquired here by its first connected mixin and is + * released in mixout_process(). Other connected mixins just use a pointer + * stored in mixout_data->acquired_buf. + */ + if (!mixout_data->acquired_buf.ptr) { + struct sof_sink *sink = mixout_mod->sinks[0]; + size_t free_bytes = sink_get_free_size(sink); + size_t buf_size; + + sink_get_buffer(sink, free_bytes, &mixout_data->acquired_buf.ptr, + &mixout_data->acquired_buf.buf_start, &buf_size); + mixout_data->acquired_buf.buf_end = + (uint8_t *)mixout_data->acquired_buf.buf_start + buf_size; + mixout_data->acquired_buf_free_frames = + free_bytes / sink_get_frame_bytes(sink); + } + + /* if source does not produce any data but mixin is in active state -- generate + * silence instead of that source data + */ + if (source_avail_frames == 0) { + frame_bytes = sink_get_frame_bytes(mixout_mod->sinks[0]); + + /* generate silence */ + silence(&mixout_data->acquired_buf, start_frame * frame_bytes, + mixout_data->mixed_frames * frame_bytes, + frames_to_copy * frame_bytes); + } else { + uint32_t channel_count = sink_get_channels(mixout_mod->sinks[0]); + + /* basically, if sink buffer has no data -- copy source data there, if + * sink buffer has some data (written by another mixin) mix that data + * with source data. + */ + ret = mix(dev, mixin_data, sinks_ids[i], &mixout_data->acquired_buf, + start_frame * channel_count, + mixout_data->mixed_frames * channel_count, + &source_ptr, frames_to_copy * channel_count); + if (ret < 0) + return ret; + } + + pending_frames->frames += frames_to_copy; + + if (frames_to_copy + start_frame > mixout_data->mixed_frames) + mixout_data->mixed_frames = frames_to_copy + start_frame; + } + + if (bytes_to_consume) + source_release_data(sources[0], bytes_to_consume); + + return 0; +} + +/* mixout just commits its sink buffer with data already mixed by mixins */ +static int mixout_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct mixout_data *md; + uint32_t frames_to_produce = INT32_MAX; + uint32_t bytes_to_produce; + struct pending_frames *pending_frames; + int i; + + comp_dbg(dev, "entry"); + + md = module_get_private_data(mod); + + /* iterate over all connected mixins to find minimal value of frames they consumed + * (i.e., mixed into mixout sink buffer). That is the amount that can/should be + * produced now. + */ + for (i = 0; i < num_of_sources; i++) { + struct comp_buffer *unused_in_between_buf; + struct comp_dev *mixin; + + /* WORKAROUND: since mixin is always connected to mixout, we can safely assume + * mixout source interface is implemented via comp_buffer. This is, of course, + * not the case for other modules. + * TODO: find out a solution to reach mixin without knowledge of mixout + * sof_source implementation. + */ + unused_in_between_buf = comp_buffer_get_from_source(sources[i]); + mixin = comp_buffer_get_source_component(unused_in_between_buf); + + pending_frames = get_mixin_pending_frames(md, mixin); + if (!pending_frames) + continue; + + if (mixin->state == COMP_STATE_ACTIVE || pending_frames->frames) + frames_to_produce = MIN(frames_to_produce, pending_frames->frames); + } + + if (frames_to_produce > 0 && frames_to_produce < INT32_MAX) { + for (i = 0; i < num_of_sources; i++) { + struct comp_buffer *unused_in_between_buf; + struct comp_dev *mixin; + + unused_in_between_buf = comp_buffer_get_from_source(sources[i]); + mixin = comp_buffer_get_source_component(unused_in_between_buf); + + pending_frames = get_mixin_pending_frames(md, mixin); + if (!pending_frames) + continue; + + if (pending_frames->frames >= frames_to_produce) + pending_frames->frames -= frames_to_produce; + else + pending_frames->frames = 0; + } + + assert(md->mixed_frames >= frames_to_produce); + md->mixed_frames -= frames_to_produce; + + bytes_to_produce = frames_to_produce * sink_get_frame_bytes(sinks[0]); + } else { + /* FIXME: does not work properly for freq like 44.1 kHz */ + bytes_to_produce = dev->frames * sink_get_frame_bytes(sinks[0]); + bytes_to_produce = MIN(bytes_to_produce, sink_get_free_size(sinks[0])); + + if (!md->acquired_buf.ptr) { + size_t buf_size; + + sink_get_buffer(sinks[0], bytes_to_produce, &md->acquired_buf.ptr, + &md->acquired_buf.buf_start, &buf_size); + md->acquired_buf.buf_end = (uint8_t *)md->acquired_buf.buf_start + buf_size; + } + + cir_buf_set_zero(md->acquired_buf.ptr, md->acquired_buf.buf_start, + md->acquired_buf.buf_end, bytes_to_produce); + } + + sink_commit_buffer(sinks[0], bytes_to_produce); + md->acquired_buf.ptr = NULL; + + return 0; +} + +static int mixin_reset(struct processing_module *mod) +{ + struct mixin_data *mixin_data = module_get_private_data(mod); + + mixin_data->mix = NULL; + mixin_data->gain_mix = NULL; + + return 0; +} + +static int mixout_reset(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + + /* FIXME: move this to module_adapter_reset() */ + if (dev->pipeline->source_comp->direction == SOF_IPC_STREAM_PLAYBACK) { + int i; + + for (i = 0; i < mod->num_of_sources; i++) { + const struct comp_buffer *source_buf; + bool stop; + + /* WORKAROUND: since mixin is always connected to mixout, we can safely + * assume mixout source interface is implemented via comp_buffer. This is, + * of course, not the case for other modules. + * TODO: find out a solution to reach mixin without knowledge of mixout + * sof_source implementation. + */ + source_buf = comp_buffer_get_from_source(mod->sources[i]); + stop = (dev->pipeline == + comp_buffer_get_source_component(source_buf)->pipeline && + comp_buffer_get_source_state(source_buf) > COMP_STATE_PAUSED); + + if (stop) + /* should not reset the downstream components */ + return PPL_STATUS_PATH_STOP; + } + } + + return 0; +} + +/* params are derived from base config for ipc4 path */ +static int mixin_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + int i; + int ret; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + + /* Buffers between mixins and mixouts are not used (mixin writes data directly to mixout + * sink). But, anyway, let's setup these buffers properly just in case. + */ + + /* FIXME: there are 2 problems with the loop below: + * + * (1) struct sof_audio_stream_params contains two frame format members: frame_fmt + * and valid_sample_fmt both of type enum sof_ipc_frame. That is excessive as + * enum sof_ipc_frame describes both container and sample size and so having one + * variable of this type is enough. frame_fmt is set by comp_verify_params(), however, + * valid_sample_fmt does not. Hence valid_sample_fmt is set below in a loop. If mess + * with having both frame_fmt and valid_sample_fmt in SOF is solved when this loop can + * be removed. + * + * (2) comp_verify_params() setup sink buffers for playback pipeline and source buffers + * for capture pipelines. So in case problem (1) is solved the loop is only needed if + * mixin is on capture pipeline and mixout is in playback pipeline. Such topology seems + * makes not much sense and probably never used. In all other cases comp_verify_params() + * will be sufficient to setup buffers and so the loop below may be removed. + */ + for (i = 0; i < mod->num_of_sinks; i++) { + enum sof_ipc_frame frame_fmt, valid_fmt; + + sink_set_channels(mod->sinks[i], mod->priv.cfg.base_cfg.audio_fmt.channels_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, + &frame_fmt, &valid_fmt, + mod->priv.cfg.base_cfg.audio_fmt.s_type); + + sink_set_frm_fmt(mod->sinks[i], frame_fmt); + sink_set_valid_fmt(mod->sinks[i], valid_fmt); + } + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params() failed!"); + return -EINVAL; + } + + return 0; +} + +/* + * Prepare the mixer. The mixer may already be running at this point with other + * sources. Make sure we only prepare the "prepared" source streams and not + * the active or inactive sources. + * + * We should also make sure that we propagate the prepare call to downstream + * if downstream is not currently active. + */ +static int mixin_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct mixin_data *md = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame fmt; + int ret; + + comp_info(dev, "entry"); +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + md->eos_delay_configured = false; +#endif + + ret = mixin_params(mod); + if (ret < 0) + return ret; + + fmt = sink_get_valid_fmt(sinks[0]); + + /* currently inactive so setup mixer */ + switch (fmt) { + case SOF_IPC_FRAME_S16_LE: + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + mixin_get_processing_functions(fmt, &md->mix, &md->gain_mix); + break; + default: + comp_err(dev, "unsupported data format %d", fmt); + return -EINVAL; + } + + if (!md->mix || !md->gain_mix) { + comp_err(dev, "have not found suitable processing functions"); + return -EINVAL; + } + + return 0; +} + +static int mixout_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame frame_fmt, valid_fmt; + int ret; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params() failed!"); + return -EINVAL; + } + + /* FIXME: the code below could/should be removed once mess with having both frame_fmt + * and valid_sample_fmt is solved (see comment in mixin_params()). + */ + + /* 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, + &frame_fmt, &valid_fmt, + mod->priv.cfg.base_cfg.audio_fmt.s_type); + + sink_set_valid_fmt(mod->sinks[0], valid_fmt); + + return 0; +} + +static int mixout_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct mixout_data *md; + int ret, i; + + ret = mixout_params(mod); + if (ret < 0) + return ret; + + comp_dbg(dev, "entry"); + + /* + * Since mixout sink buffer stream is reset on .prepare(), let's + * reset counters for not yet produced frames in that buffer. + */ + md = module_get_private_data(mod); + md->mixed_frames = 0; + + for (i = 0; i < MIXOUT_MAX_SOURCES; i++) + md->pending_frames[i].frames = 0; + + return 0; +} + +static int mixout_bind(struct processing_module *mod, struct bind_info *bind_data) +{ + struct ipc4_module_bind_unbind *bu; + struct comp_dev *mixin; + struct pending_frames *pending_frames; + int src_id; + struct mixout_data *mixout_data; + + bu = bind_data->ipc4_data; + src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); + + /* we are only interested in bind for mixin -> mixout pair */ + if (mod->dev->ipc_config.id == src_id) + return 0; + + mixin = ipc4_get_comp_dev(src_id); + if (!mixin) { + comp_err(mod->dev, "no mixin with ID %d found", src_id); + return -EINVAL; + } + + mixout_data = module_get_private_data(mod); + + pending_frames = get_mixin_pending_frames(mixout_data, mixin); + /* + * this should never happen as pending_frames info for a particular mixin and mixout pair + * should have been already cleared in mixout_unbind() + */ + if (pending_frames) { + pending_frames->mixin = NULL; + pending_frames->frames = 0; + } + + /* find an empty slot in the pending_frames array */ + pending_frames = get_mixin_pending_frames(mixout_data, NULL); + if (!pending_frames) { + /* no free slot in pending_frames array */ + comp_err(mod->dev, "Too many inputs!"); + return -ENOMEM; + } + + pending_frames->frames = 0; + pending_frames->mixin = mixin; + + return 0; +} + +static int mixout_unbind(struct processing_module *mod, struct bind_info *unbind_data) +{ + struct ipc4_module_bind_unbind *bu; + struct comp_dev *mixin; + struct pending_frames *pending_frames; + int src_id; + struct mixout_data *mixout_data; + + comp_dbg(mod->dev, "entry"); + + bu = unbind_data->ipc4_data; + src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); + + /* we are only interested in unbind for mixin -> mixout pair */ + if (mod->dev->ipc_config.id == src_id) + return 0; + + mixin = ipc4_get_comp_dev(src_id); + if (!mixin) { + comp_err(mod->dev, "no mixin with ID %d found", src_id); + return -EINVAL; + } + + mixout_data = module_get_private_data(mod); + + /* remove mixin from pending_frames array */ + pending_frames = get_mixin_pending_frames(mixout_data, mixin); + if (pending_frames) { + pending_frames->mixin = NULL; + pending_frames->frames = 0; + } + + return 0; +} + +static int mixin_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 mixin_data *mixin_data = module_get_private_data(mod); + const struct ipc4_mixer_mode_config *cfg; + struct comp_dev *dev = mod->dev; + int i; + uint32_t sink_index; + uint16_t gain; + + if (config_id != IPC4_MIXER_MODE) { + comp_err(dev, "unsupported param ID: %u", config_id); + return -EINVAL; + } + + if (!(pos & MODULE_CFG_FRAGMENT_SINGLE)) { + comp_err(dev, "data is expected to be sent as one chunk"); + return -EINVAL; + } + + /* for a single chunk data, data_offset_size is size */ + if (data_offset_size < sizeof(struct ipc4_mixer_mode_config)) { + comp_err(dev, "too small data size: %u", data_offset_size); + return -EINVAL; + } + + if (data_offset_size > SOF_IPC_MSG_MAX_SIZE) { + comp_err(dev, "too large data size: %u", data_offset_size); + return -EINVAL; + } + + cfg = (const struct ipc4_mixer_mode_config *)fragment; + + if (cfg->mixer_mode_config_count < 1 || cfg->mixer_mode_config_count > MIXIN_MAX_SINKS) { + comp_err(dev, "invalid mixer_mode_config_count: %u", + cfg->mixer_mode_config_count); + return -EINVAL; + } + + if (sizeof(struct ipc4_mixer_mode_config) + + (cfg->mixer_mode_config_count - 1) * sizeof(struct ipc4_mixer_mode_sink_config) > + data_offset_size) { + comp_err(dev, "unexpected data size: %u", data_offset_size); + return -EINVAL; + } + + for (i = 0; i < cfg->mixer_mode_config_count; i++) { + sink_index = cfg->mixer_mode_sink_configs[i].output_queue_id; + if (sink_index >= MIXIN_MAX_SINKS) { + comp_err(dev, "invalid sink index: %u", sink_index); + return -EINVAL; + } + + gain = cfg->mixer_mode_sink_configs[i].gain; + if (gain > IPC4_MIXIN_UNITY_GAIN) + gain = IPC4_MIXIN_UNITY_GAIN; + mixin_data->sink_config[sink_index].gain = gain; + + comp_dbg(dev, "gain 0x%x will be applied for sink %u", + gain, sink_index); + + if (cfg->mixer_mode_sink_configs[i].mixer_mode == + IPC4_MIXER_CHANNEL_REMAPPING_MODE) { + uint32_t channel_count = + cfg->mixer_mode_sink_configs[i].output_channel_count; + if (channel_count < 1 || channel_count > 8) { + comp_err(dev, "Invalid output_channel_count %u for sink %u", + channel_count, sink_index); + return -EINVAL; + } + + mixin_data->sink_config[sink_index].output_channel_count = channel_count; + mixin_data->sink_config[sink_index].output_channel_map = + cfg->mixer_mode_sink_configs[i].output_channel_map; + + comp_dbg(dev, "output_channel_count: %u, chmap: 0x%x for sink: %u", + channel_count, + mixin_data->sink_config[sink_index].output_channel_map, + sink_index); + } + + mixin_data->sink_config[sink_index].mixer_mode = + cfg->mixer_mode_sink_configs[i].mixer_mode; + } + + return 0; +} + +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE +static int mixin_set_config_param(struct processing_module *mod, uint32_t param_id_data) +{ + struct mixin_data *mixin_data = module_get_private_data(mod); + union config_param_id_data cfg; + + cfg.dw = param_id_data; + + if (cfg.f.id == IPC4_MIXER_UNDERRUN_NOTIF_PERIOD) { + if (cfg.f.data16 < MIXIN_MODULE_MIN_UNDERRUN_NOTIFICATION_PERIOD) + return -EINVAL; + + mixin_data->underrun_notification_period = cfg.f.data16; + return 0; + } + return -EINVAL; +} + +static int mixin_get_config_param(struct processing_module *mod, uint32_t *param_id_data) +{ + struct mixin_data *mixin_data = module_get_private_data(mod); + union config_param_id_data cfg; + + cfg.dw = *param_id_data; + + if (cfg.f.id == IPC4_MIXER_UNDERRUN_NOTIF_PERIOD) { + cfg.f.data16 = mixin_data->underrun_notification_period; + *param_id_data = cfg.dw; + return 0; + } + return -EINVAL; +} +#endif + +static const struct module_interface mixin_interface = { + .init = mixin_init, + .prepare = mixin_prepare, + .process = mixin_process, + .set_configuration = mixin_set_config, +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + .set_config_param = mixin_set_config_param, + .get_config_param = mixin_get_config_param, +#endif + .reset = mixin_reset, + .free = mixin_free +}; + +static const struct module_interface mixout_interface = { + .init = mixout_init, + .prepare = mixout_prepare, + .process = mixout_process, + .reset = mixout_reset, + .free = mixout_free, + .bind = mixout_bind, + .unbind = mixout_unbind +}; + +#if CONFIG_COMP_MIXIN_MIXOUT_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = +{ + SOF_LLEXT_MODULE_MANIFEST("MIXIN", &mixin_interface, 1, SOF_REG_UUID(mixin), 30), + SOF_LLEXT_MODULE_MANIFEST("MIXOUT", &mixout_interface, 1, SOF_REG_UUID(mixout), 30), +}; + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(mixin_tr, SOF_UUID(mixin_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(mixin_interface, mixin_uuid, mixin_tr); +SOF_MODULE_INIT(mixin, sys_comp_module_mixin_interface_init); + +DECLARE_TR_CTX(mixout_tr, SOF_UUID(mixout_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(mixout_interface, mixout_uuid, mixout_tr); +SOF_MODULE_INIT(mixout, sys_comp_module_mixout_interface_init); + +#endif diff --git a/src/audio/mixin_mixout/mixin_mixout.h b/src/audio/mixin_mixout/mixin_mixout.h new file mode 100644 index 000000000000..97aa0e12cdab --- /dev/null +++ b/src/audio/mixin_mixout/mixin_mixout.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/mixin_mixout.h + * \brief IPC4 mixin/mixout definitions. + */ + +#ifndef __SOF_IPC4_MIXIN_MIXOUT_H__ +#define __SOF_IPC4_MIXIN_MIXOUT_H__ + +#include <stdint.h> +#include <rtos/bit.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/platform.h> +#include <stddef.h> + +enum ipc4_mixin_config_param { + /* config_param param id to set/get underrun notification period. */ + IPC4_MIXER_UNDERRUN_NOTIF_PERIOD = 0, + /* large_config_set param id for ipc4_mixer_mode_config */ + IPC4_MIXER_MODE = 1 +}; + +/* Number of supported output pins (sinks) */ +#define IPC4_MIXIN_MODULE_MAX_OUTPUT_QUEUES 3 + +/* Number of supported input pins that are mixed together */ +#define IPC4_MIXOUT_MODULE_MAX_INPUT_QUEUES 8 + +/* Each mixin instance by default has set default notification + * period to avoid notification flooding. + */ +#define MIXIN_MODULE_DEFAULT_UNDERRUN_NOTIFICATION_PERIOD 10 +#define MIXIN_MODULE_MIN_UNDERRUN_NOTIFICATION_PERIOD 1 +#define MIXIN_MODULE_MAX_UNDERRUN_NOTIFICATION_PERIOD 65535 + +enum ipc4_mixer_mode { + /* Normal mode, just mixing */ + IPC4_MIXER_NORMAL_MODE = 0, + + /* Mixing with channel remapping */ + IPC4_MIXER_CHANNEL_REMAPPING_MODE = 1, +}; + +struct ipc4_mixer_mode_sink_config { + /* Index of output queue (aka sink) this config is for, + * range from 0 to IPC4_MIXIN_MODULE_MAX_OUTPUT_QUEUES - 1 + */ + uint32_t output_queue_id; + + /* Operational mode for given output queue index. enum ipc4_mixer_mode */ + uint32_t mixer_mode; + + /* These two below are used in channel remapping mode. */ + uint32_t output_channel_count; + + /* Output channel map for given output queue index. Each nibble (where nibble index is + * equivalent for output channel index) contains source channel index. Value 0xF in nibble + * means that output channel cannot be modified. + */ + uint32_t output_channel_map; + + /* Gain to be applied to input signal. Valid range: 0x0..0x400 (0.0 <= gain <= 1.0). Values + * greater than 0x400 are treated as 0x400 (unity gain). To apply gain, multiply sample + * by "gain" and divide by 1024. + */ + uint16_t gain; + uint16_t reserved; +} __packed __aligned(4); + +#define IPC4_MIXIN_GAIN_SHIFT 10 +#define IPC4_MIXIN_UNITY_GAIN BIT(IPC4_MIXIN_GAIN_SHIFT) + +/* Payload for large_config_set IPC4_MIXER_MODE param id */ +struct ipc4_mixer_mode_config { + /* Total number of given ipc4_mixer_mode_sink_config. Size of passed structure is + * determined by this number. + */ + uint32_t mixer_mode_config_count; + + /* Array of settings for sinks, size is mixer_mode_config_count. */ + struct ipc4_mixer_mode_sink_config mixer_mode_sink_configs[1]; +} __packed __aligned(4); + +/* Pointer to data in circular buffer together with buffer boundaries */ +struct cir_buf_ptr { + void *buf_start; + void *buf_end; + void *ptr; +}; + +/** + * \brief mixin processing function interface + */ +typedef void (*mix_func)(struct cir_buf_ptr *sink, int32_t start_sample, + int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain); + +/** + * @brief mixin processing functions map. + */ +struct mix_func_map { + uint16_t frame_fmt; /* frame format */ + mix_func mix; /* faster mixing func without gain support */ + mix_func gain_mix; /* slower mixing func with gain support */ +}; + +extern const struct mix_func_map mix_func_map[]; +extern const size_t mix_count; +/** + * \brief Retrievies mixin processing function. + * \param[in] fmt stream PCM frame format + */ +static inline bool mixin_get_processing_functions(int fmt, mix_func *mix, mix_func *gain_mix) +{ + int i; + + *mix = NULL; + *gain_mix = NULL; + + /* map mixin processing function for source and sink buffers */ + for (i = 0; i < mix_count; i++) { + if (fmt == mix_func_map[i].frame_fmt) { + *mix = mix_func_map[i].mix; + *gain_mix = mix_func_map[i].gain_mix; + return true; + } + } + + return false; +} + +#endif /* __SOF_IPC4_MIXIN_MIXOUT_H__ */ diff --git a/src/audio/mixin_mixout/mixin_mixout.toml b/src/audio/mixin_mixout/mixin_mixout.toml new file mode 100644 index 000000000000..16edc0567aa3 --- /dev/null +++ b/src/audio/mixin_mixout/mixin_mixout.toml @@ -0,0 +1,88 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "MIXIN" + uuid = UUIDREG_STR_MIXIN + affinity_mask = "0x1" + instance_count = "30" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "1" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 1, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 1, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 1, 0, 0xfeef, 0xc, 0x8, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 296, 4996000, 384, 384, 0, 4996, 0, + 1, 0, 0, 0, 296, 2652000, 384, 384, 0, 2652, 0, + 2, 0, 0, 0, 296, 2928000, 512, 512, 0, 2928, 0, + 3, 0, 0, 0, 296, 2572000, 128, 128, 0, 2572, 0, + 4, 0, 0, 0, 296, 3760000, 1536, 1536, 0, 3760, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 296, 2336000, 384, 384, 0, 2336, 0, + 1, 0, 0, 0, 296, 2344000, 384, 384, 0, 2344, 0, + 2, 0, 0, 0, 296, 2448000, 512, 512, 0, 2448, 0, + 3, 0, 0, 0, 296, 2160000, 128, 128, 0, 2160, 0, + 4, 0, 0, 0, 296, 3268000, 1536, 1536, 0, 3268, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 296, 5091000, 384, 384, 0, 5091, 0, + 1, 0, 0, 0, 296, 5111000, 384, 384, 0, 5111, 0, + 2, 0, 0, 0, 296, 5195000, 512, 512, 0, 5195, 0, + 3, 0, 0, 0, 296, 5219000, 128, 128, 0, 5219, 0, + 4, 0, 0, 0, 296, 5631000, 1536, 1536, 0, 5631, 0] +#endif + + index = __COUNTER__ + + [[module.entry]] + name = "MIXOUT" + uuid = UUIDREG_STR_MIXOUT + affinity_mask = "0x1" + instance_count = "30" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "2" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 0, 0, 0xfeef, 0xc, 0x8, 0x45ff, + 1, 0, 0xfeef, 0xc, 0x8, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 520, 2280000, 384, 384, 0, 2280, 0, + 1, 0, 0, 0, 520, 1988000, 384, 384, 0, 1988, 0, + 2, 0, 0, 0, 520, 7631000, 512, 512, 0, 7631, 0, + 3, 0, 0, 0, 520, 1953000, 128, 128, 0, 1953, 0, + 4, 0, 0, 0, 520, 2301000, 1536, 1536, 0, 2301, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 520, 2280000, 384, 384, 0, 0, 0, + 1, 0, 0, 0, 520, 1988000, 384, 384, 0, 0, 0, + 2, 0, 0, 0, 520, 7631000, 512, 512, 0, 0, 0, + 3, 0, 0, 0, 520, 1953000, 128, 128, 0, 0, 0, + 4, 0, 0, 0, 520, 2301000, 1536, 1536, 0, 0, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 520, 3999000, 384, 384, 0, 3999, 0, + 1, 0, 0, 0, 520, 3999000, 384, 384, 0, 3999, 0, + 2, 0, 0, 0, 520, 4055000, 512, 512, 0, 4055, 0, + 3, 0, 0, 0, 520, 3987000, 128, 128, 0, 3987, 0, + 4, 0, 0, 0, 520, 2273000, 1536, 1536, 0, 2273, 0] +#endif + + index = __COUNTER__ diff --git a/src/audio/mixin_mixout/mixin_mixout_generic.c b/src/audio/mixin_mixout/mixin_mixout_generic.c new file mode 100644 index 000000000000..5443ee5a5f49 --- /dev/null +++ b/src/audio/mixin_mixout/mixin_mixout_generic.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> + +#include <sof/common.h> +#include <rtos/string.h> + +#include "mixin_mixout.h" + +#if SOF_USE_HIFI(NONE, MIXIN_MIXOUT) + +#if CONFIG_FORMAT_S16LE +static void mix_s16(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int32_t samples_to_mix, samples_to_copy, left_samples; + int32_t n, nmax, i; + + /* cir_buf_wrap() is required and is done below in a loop */ + int16_t *dst = (int16_t *)sink->ptr + start_sample; + int16_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = mixed_samples - start_sample; + samples_to_mix = MIN(samples_to_mix, sample_count); + samples_to_copy = sample_count - samples_to_mix; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int16_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int16_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int16(*dst + *src++); + dst++; + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + nmax = (int16_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int16_t *)sink->buf_end - dst; + n = MIN(n, nmax); + memcpy_s(dst, n * sizeof(int16_t), src, n * sizeof(int16_t)); + dst += n; + src += n; + } +} + +static void mix_s16_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int32_t samples_to_mix, samples_to_copy, left_samples; + int32_t n, nmax, i; + + /* cir_buf_wrap() is required and is done below in a loop */ + int16_t *dst = (int16_t *)sink->ptr + start_sample; + int16_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = mixed_samples - start_sample; + samples_to_mix = MIN(samples_to_mix, sample_count); + samples_to_copy = sample_count - samples_to_mix; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int16_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int16_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int16((int32_t)*dst + + q_mults_16x16(*src, gain, IPC4_MIXIN_GAIN_SHIFT)); + src++; + dst++; + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + nmax = (int16_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int16_t *)sink->buf_end - dst; + n = MIN(n, nmax); + + for (i = 0; i < n; i++) { + *dst = q_mults_16x16(*src, gain, IPC4_MIXIN_GAIN_SHIFT); + src++; + dst++; + } + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int32_t samples_to_mix, samples_to_copy, left_samples; + int32_t n, nmax, i; + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = mixed_samples - start_sample; + samples_to_mix = MIN(samples_to_mix, sample_count); + samples_to_copy = sample_count - samples_to_mix; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int24(sign_extend_s24(*dst) + sign_extend_s24(*src++)); + dst++; + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + memcpy_s(dst, n * sizeof(int32_t), src, n * sizeof(int32_t)); + dst += n; + src += n; + } +} + +static void mix_s24_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int32_t samples_to_mix, samples_to_copy, left_samples; + int32_t n, nmax, i; + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = mixed_samples - start_sample; + samples_to_mix = MIN(samples_to_mix, sample_count); + samples_to_copy = sample_count - samples_to_mix; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int24(sign_extend_s24(*dst) + + (int32_t)q_mults_32x32(sign_extend_s24(*src), + gain, IPC4_MIXIN_GAIN_SHIFT)); + src++; + dst++; + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = q_mults_32x32(sign_extend_s24(*src), gain, IPC4_MIXIN_GAIN_SHIFT); + src++; + dst++; + } + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void mix_s32(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int32_t samples_to_mix, samples_to_copy, left_samples; + int32_t n, nmax, i; + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = mixed_samples - start_sample; + samples_to_mix = MIN(samples_to_mix, sample_count); + samples_to_copy = sample_count - samples_to_mix; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int32((int64_t)*dst + (int64_t)*src++); + dst++; + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + memcpy_s(dst, n * sizeof(int32_t), src, n * sizeof(int32_t)); + dst += n; + src += n; + } +} + +static void mix_s32_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int32_t samples_to_mix, samples_to_copy, left_samples; + int32_t n, nmax, i; + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = mixed_samples - start_sample; + samples_to_mix = MIN(samples_to_mix, sample_count); + samples_to_copy = sample_count - samples_to_mix; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int32((int64_t)*dst + + q_mults_32x32(*src, gain, IPC4_MIXIN_GAIN_SHIFT)); + src++; + dst++; + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = MIN(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = q_mults_32x32(*src, gain, IPC4_MIXIN_GAIN_SHIFT); + src++; + dst++; + } + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +__cold_rodata const struct mix_func_map mix_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, mix_s16, mix_s16_gain }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, mix_s24, mix_s24_gain }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, mix_s32, mix_s32_gain } +#endif +}; + +const size_t mix_count = ARRAY_SIZE(mix_func_map); + +#endif diff --git a/src/audio/mixin_mixout/mixin_mixout_hifi3.c b/src/audio/mixin_mixout/mixin_mixout_hifi3.c new file mode 100644 index 000000000000..40962339dbce --- /dev/null +++ b/src/audio/mixin_mixout/mixin_mixout_hifi3.c @@ -0,0 +1,577 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> + +#include <sof/common.h> + +#include "mixin_mixout.h" + +#if SOF_USE_HIFI(3, MIXIN_MIXOUT) || SOF_USE_HIFI(4, MIXIN_MIXOUT) + +#include <xtensa/tie/xt_hifi3.h> + +#if CONFIG_FORMAT_S16LE +static void mix_s16(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int16x4 in_sample; + ae_int16x4 out_sample; + ae_int16x4 *in; + ae_int16x4 *out; + ae_valign inu; + ae_valign outu1; + ae_valign outu2 = AE_ZALIGN64(); + /* cir_buf_wrap() is required and is done below in a loop */ + ae_int16 *dst = (ae_int16 *)sink->ptr + start_sample; + ae_int16 *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN_32_signed(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int16x4 *)src; + out = (ae_int16x4 *)dst; + inu = AE_LA64_PP(in); + outu1 = AE_LA64_PP(out); + m = n >> 2; + left = n & 0x03; + /* process 4 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4_IP(in_sample, inu, in); + AE_LA16X4_IP(out_sample, outu1, out); + out--; + out_sample = AE_ADD16S(in_sample, out_sample); + AE_SA16X4_IP(out_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_L16_IP(out_sample, (ae_int16 *)out, 0); + out_sample = AE_ADD16S(in_sample, out_sample); + AE_S16_0_IP(out_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int16x4 *)src; + out = (ae_int16x4 *)dst; + inu = AE_LA64_PP(in); + m = n >> 2; + left = n & 0x03; + /* process 4 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4_IP(in_sample, inu, in); + AE_SA16X4_IP(in_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_S16_0_IP(in_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } +} + +static void mix_s16_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int16x4 in_sample; + ae_int16x4 out_sample; + ae_int16x4 *in; + ae_int16x4 *out; + ae_valign inu; + ae_valign outu1; + ae_valign outu2 = AE_ZALIGN64(); + /* cir_buf_wrap() is required and is done below in a loop */ + ae_int16 *dst = (ae_int16 *)sink->ptr + start_sample; + ae_int16 *src = source->ptr; + ae_f16x4 gain_vec; + + /* this func does not support unity gain as 1 cannot be represented as Q1.15 value */ + assert(gain < IPC4_MIXIN_UNITY_GAIN); + + gain_vec = AE_L16_I((ae_int16 *)&gain, 0); + gain_vec = AE_SLAI16S(gain_vec, 5); /* convert to Q1.15 */ + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN_32_signed(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int16x4 *)src; + out = (ae_int16x4 *)dst; + inu = AE_LA64_PP(in); + outu1 = AE_LA64_PP(out); + m = n >> 2; + left = n & 0x03; + /* process 4 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4_IP(in_sample, inu, in); + /* apply gain to in_sample */ + in_sample = AE_MULFP16X4S(in_sample, gain_vec); + AE_LA16X4_IP(out_sample, outu1, out); + out--; + out_sample = AE_ADD16S(in_sample, out_sample); + AE_SA16X4_IP(out_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + in_sample = AE_MULFP16X4S(in_sample, gain_vec); + AE_L16_IP(out_sample, (ae_int16 *)out, 0); + out_sample = AE_ADD16S(in_sample, out_sample); + AE_S16_0_IP(out_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int16x4 *)src; + out = (ae_int16x4 *)dst; + inu = AE_LA64_PP(in); + m = n >> 2; + left = n & 0x03; + /* process 4 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4_IP(in_sample, inu, in); + in_sample = AE_MULFP16X4S(in_sample, gain_vec); + AE_SA16X4_IP(in_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + in_sample = AE_MULFP16X4S(in_sample, gain_vec); + AE_S16_0_IP(in_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample; + ae_int32x2 out_sample; + ae_int32x2 *in; + ae_int32x2 *out; + ae_valign inu; + ae_valign outu1; + ae_valign outu2 = AE_ZALIGN64(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN_32_signed(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + outu1 = AE_LA64_PP(out); + m = n >> 1; + left = n & 1; + /* process 2 samples per time */ + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + AE_LA32X2_IP(out_sample, outu1, out); + out--; + /* sign extent in_sample as AE_ADD24S expects Q9.23 arguments */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + /* out_sample is already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); + AE_SA32X2_IP(out_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + out_sample = AE_ADD24S(in_sample, out_sample); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + m = n >> 1; + left = n & 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + AE_SA32X2_IP(in_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} + +static void mix_s24_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample; + ae_int32x2 out_sample; + ae_int32x2 *in; + ae_int32x2 *out; + ae_valign inu; + ae_valign outu1; + ae_valign outu2 = AE_ZALIGN64(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + ae_f24x2 gain_vec; + ae_int32 gain32 = (ae_int32)gain; + + /* this func does not support unity gain as 1 cannot be represented as Q1.23 value */ + assert(gain < IPC4_MIXIN_UNITY_GAIN); + + gain_vec = AE_MOVF24X2_FROMINT32X2(AE_L32_I(&gain32, 0)); + gain_vec = AE_SLAI24S(gain_vec, 13); /* convert to Q1.23 */ + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN_32_signed(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + outu1 = AE_LA64_PP(out); + m = n >> 1; + left = n & 1; + /* process 2 samples per time */ + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + AE_LA32X2_IP(out_sample, outu1, out); + out--; + /* out samples are already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); + AE_SA32X2_IP(out_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + /* out samples are already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + m = n >> 1; + left = n & 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + AE_SA32X2_IP(in_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} + +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void mix_s32(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample; + ae_int32x2 out_sample; + ae_int32x2 *in; + ae_int32x2 *out; + ae_valign inu; + ae_valign outu1; + ae_valign outu2 = AE_ZALIGN64(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN_32_signed(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + outu1 = AE_LA64_PP(out); + m = n >> 1; + left = n & 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + AE_LA32X2_IP(out_sample, outu1, out); + out--; + out_sample = AE_ADD32S(in_sample, out_sample); + AE_SA32X2_IP(out_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + out_sample = AE_ADD32S(in_sample, out_sample); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + m = n >> 1; + left = n & 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + AE_SA32X2_IP(in_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} + +static void mix_s32_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample; + ae_int32x2 out_sample; + ae_int32x2 *in; + ae_int32x2 *out; + ae_valign inu; + ae_valign outu1; + ae_valign outu2 = AE_ZALIGN64(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + ae_f16x4 gain_vec; + + /* this func does not support unity gain as 1 cannot be represented as Q1.15 value */ + assert(gain < IPC4_MIXIN_UNITY_GAIN); + + gain_vec = AE_L16_I((ae_int16 *)&gain, 0); + gain_vec = AE_SLAI16S(gain_vec, 5); /* convert to Q1.15 */ + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN_32_signed(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + outu1 = AE_LA64_PP(out); + m = n >> 1; + left = n & 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + AE_LA32X2_IP(out_sample, outu1, out); + out--; + AE_MULAFP32X16X2RS_L(out_sample, in_sample, gain_vec); + AE_SA32X2_IP(out_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + AE_MULAFP32X16X2RS_L(out_sample, in_sample, gain_vec); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN_32_signed(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN_32_signed(n, nmax); + in = (ae_int32x2 *)src; + out = (ae_int32x2 *)dst; + inu = AE_LA64_PP(in); + m = n >> 1; + left = n & 1; + for (i = 0; i < m; i++) { + AE_LA32X2_IP(in_sample, inu, in); + in_sample = AE_MULFP32X16X2RS_L(in_sample, gain_vec); + AE_SA32X2_IP(in_sample, outu2, out); + } + AE_SA64POS_FP(outu2, out); + + /* process the left sample to avoid memory access overrun */ + if (left) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + in_sample = AE_MULFP32X16X2RS_L(in_sample, gain_vec); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} + +#endif /* CONFIG_FORMAT_S32LE */ + +__cold_rodata const struct mix_func_map mix_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, mix_s16, mix_s16_gain }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, mix_s24, mix_s24_gain }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, mix_s32, mix_s32_gain } +#endif +}; + +const size_t mix_count = ARRAY_SIZE(mix_func_map); + +#endif diff --git a/src/audio/mixin_mixout/mixin_mixout_hifi5.c b/src/audio/mixin_mixout/mixin_mixout_hifi5.c new file mode 100644 index 000000000000..7e42e0f8d376 --- /dev/null +++ b/src/audio/mixin_mixout/mixin_mixout_hifi5.c @@ -0,0 +1,584 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <xiaoyuan.song@intel.com> + +#include <sof/common.h> + +#include "mixin_mixout.h" + +#if SOF_USE_HIFI(5, MIXIN_MIXOUT) + +#if CONFIG_FORMAT_S16LE +static void mix_s16(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int16x4 in_sample, in_sample1; + ae_int16x4 out_sample, out_sample1; + ae_int16x8 *in; + ae_int16x8 *out; + ae_valignx2 inu; + ae_valignx2 outu1; + ae_valignx2 outu2 = AE_ZALIGN128(); + /* cir_buf_wrap() is required and is done below in a loop */ + ae_int16 *dst = (ae_int16 *)sink->ptr + start_sample; + ae_int16 *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN32(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int16x8 *)src; + out = (ae_int16x8 *)dst; + inu = AE_LA128_PP(in); + outu1 = AE_LA128_PP(out); + m = n >> 3; + left = n & 0x07; + /* process 8 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + AE_LA16X4X2_IP(out_sample, out_sample1, outu1, out); + out--; + out_sample = AE_ADD16S(in_sample, out_sample); + out_sample1 = AE_ADD16S(in_sample1, out_sample1); + AE_SA16X4X2_IP(out_sample, out_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples that less than 8 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_L16_IP(out_sample, (ae_int16 *)out, 0); + out_sample = AE_ADD16S(in_sample, out_sample); + AE_S16_0_IP(out_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int16x8 *)src; + out = (ae_int16x8 *)dst; + inu = AE_LA128_PP(in); + m = n >> 3; + left = n & 0x07; + /* process 8 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + AE_SA16X4X2_IP(in_sample, in_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples that less than 8 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_S16_0_IP(in_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } +} + +static void mix_s16_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int16x4 in_sample, in_sample1; + ae_int16x4 out_sample, out_sample1; + ae_int16x8 *in; + ae_int16x8 *out; + ae_valignx2 inu; + ae_valignx2 outu1; + ae_valignx2 outu2 = AE_ZALIGN128(); + /* cir_buf_wrap() is required and is done below in a loop */ + ae_int16 *dst = (ae_int16 *)sink->ptr + start_sample; + ae_int16 *src = source->ptr; + ae_f16x4 gain_vec; + + /* this func does not support unity gain as 1 cannot be represented as Q1.15 value */ + assert(gain < IPC4_MIXIN_UNITY_GAIN); + + gain_vec = AE_L16_I((ae_int16 *)&gain, 0); + gain_vec = AE_SLAI16S(gain_vec, 5); /* convert to Q1.15 */ + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN32(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int16x8 *)src; + out = (ae_int16x8 *)dst; + inu = AE_LA128_PP(in); + outu1 = AE_LA128_PP(out); + m = n >> 3; + left = n & 0x07; + /* process 8 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + AE_LA16X4X2_IP(out_sample, out_sample1, outu1, out); + out--; + in_sample = AE_MULFP16X4RS(in_sample, gain_vec); + in_sample1 = AE_MULFP16X4RS(in_sample1, gain_vec); + out_sample = AE_ADD16S(in_sample, out_sample); + out_sample1 = AE_ADD16S(in_sample1, out_sample1); + AE_SA16X4X2_IP(out_sample, out_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples that less than 8 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + AE_L16_IP(out_sample, (ae_int16 *)out, 0); + in_sample = AE_MULFP16X4RS(in_sample, gain_vec); + out_sample = AE_ADD16S(in_sample, out_sample); + AE_S16_0_IP(out_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (ae_int16 *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (ae_int16 *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int16x8 *)src; + out = (ae_int16x8 *)dst; + inu = AE_LA128_PP(in); + m = n >> 3; + left = n & 0x07; + /* process 8 samples per loop */ + for (i = 0; i < m; i++) { + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + in_sample = AE_MULFP16X4RS(in_sample, gain_vec); + in_sample1 = AE_MULFP16X4RS(in_sample1, gain_vec); + AE_SA16X4X2_IP(in_sample, in_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples that less than 8 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + AE_L16_IP(in_sample, (ae_int16 *)in, sizeof(ae_int16)); + in_sample = AE_MULFP16X4RS(in_sample, gain_vec); + AE_S16_0_IP(in_sample, (ae_int16 *)out, sizeof(ae_int16)); + } + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void mix_s24(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x4 *in; + ae_int32x4 *out; + ae_valignx2 inu; + ae_valignx2 outu1; + ae_valignx2 outu2 = AE_ZALIGN128(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN32(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + outu1 = AE_LA128_PP(out); + m = n >> 2; + left = n & 3; + /* process 4 samples per time */ + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + AE_LA32X2X2_IP(out_sample, out_sample1, outu1, out); + out--; + /* sign extent in samples as AE_ADD24S expects Q9.23 arguments */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + in_sample1 = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample1), 0); + /* out samples are already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); + out_sample1 = AE_ADD24S(in_sample1, out_sample1); + AE_SA32X2X2_IP(out_sample, out_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + out_sample = AE_ADD24S(in_sample, out_sample); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + m = n >> 2; + left = n & 3; + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + in_sample1 = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample1), 0); + AE_SA32X2X2_IP(in_sample, in_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + /* sign extension */ + in_sample = AE_SLAI24S(AE_MOVF24X2_FROMINT32X2(in_sample), 0); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} + +static void mix_s24_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x4 *in; + ae_int32x4 *out; + ae_valignx2 inu; + ae_valignx2 outu1; + ae_valignx2 outu2 = AE_ZALIGN128(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + ae_f24x2 gain_vec; + ae_int32 gain32 = (ae_int32)gain; + + /* this func does not support unity gain as 1 cannot be represented as Q1.23 value */ + assert(gain < IPC4_MIXIN_UNITY_GAIN); + + gain_vec = AE_MOVF24X2_FROMINT32X2(AE_L32_I(&gain32, 0)); + gain_vec = AE_SLAI24S(gain_vec, 13); /* convert to Q1.23 */ + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN32(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + outu1 = AE_LA128_PP(out); + m = n >> 2; + left = n & 3; + /* process 4 samples per time */ + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + AE_LA32X2X2_IP(out_sample, out_sample1, outu1, out); + out--; + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + in_sample1 = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample1), gain_vec); + /* out samples are already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); + out_sample1 = AE_ADD24S(in_sample1, out_sample1); + AE_SA32X2X2_IP(out_sample, out_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + /* out samples are already sign extended by other mixin in a loop below */ + out_sample = AE_ADD24S(in_sample, out_sample); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + m = n >> 2; + left = n & 3; + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + in_sample1 = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample1), gain_vec); + AE_SA32X2X2_IP(in_sample, in_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + in_sample = AE_MULFP24X2R(AE_MOVF24X2_FROMINT32X2(in_sample), gain_vec); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void mix_s32(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x4 *in; + ae_int32x4 *out; + ae_valignx2 inu; + ae_valignx2 outu1; + ae_valignx2 outu2 = AE_ZALIGN128(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN32(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + outu1 = AE_LA128_PP(out); + m = n >> 2; + left = n & 3; + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + AE_LA32X2X2_IP(out_sample, out_sample1, outu1, out); + out--; + out_sample = AE_ADD32S(in_sample, out_sample); + out_sample1 = AE_ADD32S(in_sample1, out_sample1); + AE_SA32X2X2_IP(out_sample, out_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + out_sample = AE_ADD32S(in_sample, out_sample); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + m = n >> 2; + left = n & 3; + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + AE_SA32X2X2_IP(in_sample, in_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} + +static void mix_s32_gain(struct cir_buf_ptr *sink, int32_t start_sample, int32_t mixed_samples, + const struct cir_buf_ptr *source, + int32_t sample_count, uint16_t gain) +{ + int samples_to_mix, samples_to_copy, left_samples; + int n, nmax, i, m, left; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x4 *in; + ae_int32x4 *out; + ae_valignx2 inu; + ae_valignx2 outu1; + ae_valignx2 outu2 = AE_ZALIGN128(); + /* cir_buf_wrap() is required and is done below in a loop */ + int32_t *dst = (int32_t *)sink->ptr + start_sample; + int32_t *src = source->ptr; + ae_f16x4 gain_vec; + + /* this func does not support unity gain as 1 cannot be represented as Q1.15 value */ + assert(gain < IPC4_MIXIN_UNITY_GAIN); + + gain_vec = AE_L16_I((ae_int16 *)&gain, 0); + gain_vec = AE_SLAI16S(gain_vec, 5); /* convert to Q1.15 */ + + assert(mixed_samples >= start_sample); + samples_to_mix = AE_MIN32(mixed_samples - start_sample, sample_count); + samples_to_copy = sample_count - samples_to_mix; + n = 0; + + for (left_samples = samples_to_mix; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + outu1 = AE_LA128_PP(out); + m = n >> 2; + left = n & 3; + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + AE_LA32X2X2_IP(out_sample, out_sample1, outu1, out); + out--; + AE_MULAFP32X16X2RS_L(out_sample, in_sample, gain_vec); + AE_MULAFP32X16X2RS_L(out_sample1, in_sample1, gain_vec); + AE_SA32X2X2_IP(out_sample, out_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_L32_IP(out_sample, (ae_int32 *)out, 0); + AE_MULAFP32X16X2RS_L(out_sample, in_sample, gain_vec); + AE_S32_L_IP(out_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } + + for (left_samples = samples_to_copy; left_samples > 0; left_samples -= n) { + src = cir_buf_wrap(src + n, source->buf_start, source->buf_end); + dst = cir_buf_wrap(dst + n, sink->buf_start, sink->buf_end); + /* calculate the remaining samples*/ + nmax = (int32_t *)source->buf_end - src; + n = AE_MIN32(left_samples, nmax); + nmax = (int32_t *)sink->buf_end - dst; + n = AE_MIN32(n, nmax); + in = (ae_int32x4 *)src; + out = (ae_int32x4 *)dst; + inu = AE_LA128_PP(in); + m = n >> 2; + left = n & 3; + for (i = 0; i < m; i++) { + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + in_sample = AE_MULFP32X16X2RS_L(in_sample, gain_vec); + in_sample1 = AE_MULFP32X16X2RS_L(in_sample1, gain_vec); + AE_SA32X2X2_IP(in_sample, in_sample1, outu2, out); + } + AE_SA128POS_FP(outu2, out); + /* process the left samples to avoid memory access overrun */ + for (i = 0; i < left; i++) { + AE_L32_IP(in_sample, (ae_int32 *)in, sizeof(ae_int32)); + in_sample = AE_MULFP32X16X2RS_L(in_sample, gain_vec); + AE_S32_L_IP(in_sample, (ae_int32 *)out, sizeof(ae_int32)); + } + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +/* TODO: implement mixing functions with gain support!*/ +__cold_rodata const struct mix_func_map mix_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, mix_s16, mix_s16_gain }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, mix_s24, mix_s24_gain }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, mix_s32, mix_s32_gain } +#endif +}; + +const size_t mix_count = ARRAY_SIZE(mix_func_map); + +#endif diff --git a/src/audio/module_adapter/CMakeLists.txt b/src/audio/module_adapter/CMakeLists.txt new file mode 100644 index 000000000000..c4b4a43e99e5 --- /dev/null +++ b/src/audio/module_adapter/CMakeLists.txt @@ -0,0 +1,180 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof module_adapter.c module_adapter_ipc3.c module/generic.c) +elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof module_adapter.c module_adapter_ipc4.c module/generic.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + # modules and codecs in alphabetical order +if (CONFIG_IPC_MAJOR_3) + zephyr_library_sources_ifdef(CONFIG_CADENCE_CODEC module/cadence.c module/cadence_ipc3.c) +elseif (CONFIG_IPC_MAJOR_4) + zephyr_include_directories(${sof_top_dir}/src/include/sof/audio/cadence) + zephyr_library_sources_ifdef(CONFIG_CADENCE_CODEC module/cadence.c module/cadence_ipc4.c) +endif() + + if (CONFIG_CADENCE_CODEC_AAC_DEC) + zephyr_library_import(xa_aac_dec ${CONFIG_CADENCE_CODEC_AAC_DEC_LIB}) + endif() + + if (CONFIG_CADENCE_CODEC_VORBIS_DEC) + zephyr_library_import(xa_vorbis_dec ${CONFIG_CADENCE_CODEC_VORBIS_DEC_LIB}) + endif() + + if (CONFIG_CADENCE_CODEC_MP3_DEC) + zephyr_library_import(xa_mp3_dec ${CONFIG_CADENCE_CODEC_MP3_DEC_LIB}) + endif() + + if (CONFIG_CADENCE_CODEC_MP3_ENC) + zephyr_library_import(xa_mp3_enc ${CONFIG_CADENCE_CODEC_MP3_ENC_LIB}) + endif() + + if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING) + if(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(module/dolby/llext + ${PROJECT_BINARY_DIR}/dolby_dax_audio_processing_llext) + add_dependencies(app dolby_dax_audio_processing) + else() + zephyr_library_sources( + module/dolby/dax.c + module/dolby/dax_instance_manager.c + ) + if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK) + zephyr_library_sources( + module/dolby/dax_mock.c + ) + else() + target_link_libraries(SOF INTERFACE m) + target_link_libraries(SOF INTERFACE c) + zephyr_library_import(dax_effect + ${sof_top_dir}/third_party/lib/libdax.a) + endif() + endif() + endif() + + zephyr_include_directories_ifdef(CONFIG_LIBRARY_MANAGER + ${SOF_SRC_PATH}/include/sof/audio/module_adapter/iadk/ + ${SOF_SRC_PATH}/include/sof/audio/module_adapter/library/ + ) + + zephyr_library_sources_ifdef(CONFIG_LIBRARY_MANAGER + library/native_system_agent.c + ) + + zephyr_library_sources_ifdef(CONFIG_INTEL_MODULES + module/modules.c + iadk/module_initial_settings_concrete.cpp + iadk/iadk_module_adapter.cpp + iadk/system_agent.cpp + library/native_system_service.c + ) + + zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_PROXY + library/userspace_proxy.c + library/userspace_proxy_user.c + ) + + zephyr_library_sources_ifdef(CONFIG_PASSTHROUGH_CODEC + module/passthrough.c + ) + + if(CONFIG_WAVES_CODEC) + set(WAVES_DIR module/waves) + if(CONFIG_WAVES_CODEC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(${WAVES_DIR}/llext ${PROJECT_BINARY_DIR}/waves_llext) + add_dependencies(app waves) + else() + zephyr_library_sources(${WAVES_DIR}/waves.c) + if(CONFIG_WAVES_CODEC_STUB) + zephyr_library_sources_ifdef(CONFIG_WAVES_CODEC_STUB + ${WAVES_DIR}/maxx_stub.c) + else() + zephyr_library_import(waves_codec + ${sof_top_dir}/third_party/lib/libMaxxChrome.a) + endif() + endif() + endif() + + return() +endif() + +if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) + if(CONFIG_CADENCE_CODEC) + add_local_sources(sof module/cadence.c) + + if(CONFIG_CADENCE_CODEC_WRAPPER) + sof_add_static_library(codec_wrapper_lib ${CONFIG_CADENCE_CODEC_WRAPPER_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_AAC_DEC) + sof_add_static_library(xa_aac_dec ${CONFIG_CADENCE_CODEC_AAC_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_BSAC_DEC) + sof_add_static_library(xa_bsac_dec ${CONFIG_CADENCE_CODEC_BSAC_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_DAB_DEC) + sof_add_static_library(xa_dab_dec ${CONFIG_CADENCE_CODEC_DAB_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_DRM_DEC) + sof_add_static_library(xa_drm_dec ${CONFIG_CADENCE_CODEC_DRM_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_MP3_DEC) + sof_add_static_library(xa_mp3_dec ${CONFIG_CADENCE_CODEC_MP3_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_MP3_ENC) + sof_add_static_library(xa_mp3_enc ${CONFIG_CADENCE_CODEC_MP3_ENC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_SBC_DEC) + sof_add_static_library(xa_sbc_dec ${CONFIG_CADENCE_CODEC_SBC_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_VORBIS_DEC) + sof_add_static_library(xa_vorbis_dec ${CONFIG_CADENCE_CODEC_VORBIS_DEC_LIB}) + endif() + + if(CONFIG_CADENCE_CODEC_SRC_PP) + sof_add_static_library(xa_src_pp ${CONFIG_CADENCE_CODEC_SRC_PP_LIB}) + endif() + + endif() + + if(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING) + target_include_directories(sof PRIVATE ${PROJECT_SOURCE_DIR}/third_party/include) + add_local_sources(sof module/dolby/dax.c) + add_local_sources(sof module/dolby/dax_instance_manager.c) + if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK) + add_local_sources(sof module/dolby/dax_mock.c) + else() + target_link_libraries(sof PRIVATE m) + target_link_libraries(sof PRIVATE c) + sof_add_static_library(dax_effect + ${PROJECT_SOURCE_DIR}/third_party/lib/libdax.a) + endif() + endif() + + if(CONFIG_PASSTHROUGH_CODEC) + add_local_sources(sof module/passthrough.c) + endif() + + if(CONFIG_WAVES_CODEC) + add_local_sources(sof module/waves/waves.c) + if (CONFIG_WAVES_CODEC_STUB) + add_local_sources(sof module/waves/maxx_stub.c) + else() + sof_add_static_library(MaxxChrome ${CMAKE_CURRENT_LIST_DIR}/lib/release/libMaxxChrome.a) + endif() + # folder with Waves API must be among include directories + endif() + + return() +endif() diff --git a/src/audio/module_adapter/Kconfig b/src/audio/module_adapter/Kconfig new file mode 100644 index 000000000000..a9f88dd1f2ad --- /dev/null +++ b/src/audio/module_adapter/Kconfig @@ -0,0 +1,224 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "Processing modules" + visible if COMP_MODULE_ADAPTER + + config MODULE_MEMORY_API_CONTAINER_CHUNK_SIZE + int "Number of memory containers to allocate at once" + default 16 + help + The per module resource containers are allocated in + chunks. The unused containers are kept in free + list. When the free list is empty the amount of + containers to allocate at once is selected by this + config option. + + config MODULE_MEMORY_API_DEBUG + bool "Turn on memory API thread safety checks" + default y if DEBUG + help + The Module Memory API structures are not protected + by locks. This is because the initialization, + allocation, and freeing of resources should always + be done in the same thread. This option adds an + assert to make sure no other thread makes such + operations. + + config CADENCE_CODEC + bool "Cadence codec" + help + Select for codecs which conforms to the Cadence API. + This will cause codec adapter component to include header + files specific to CADENCE base codecs. + +if CADENCE_CODEC + config CADENCE_CODEC_WRAPPER + bool 'Cadence codec wrapper' + help + Select for cadence_codec_api wrapper function that will allow + users to call into codecs which conforms to the Cadence API without + explicitly knowing/using the entry function symbol name. + + if CADENCE_CODEC_WRAPPER + config CADENCE_CODEC_WRAPPER_LIB + string "Cadence codec wrapper library name" + help + This option is a string and takes the full name of the codec wrapper library binary. + endif + + config CADENCE_CODEC_AAC_DEC + bool "Cadence AAC decoder" + help + Select for Cadence AAC decoder support. + This will cause Cadence codec to include Cadence AAC library + api symbol. + + if CADENCE_CODEC_AAC_DEC + config CADENCE_CODEC_AAC_DEC_LIB + string "Cadence AAC decoder library name" + help + This option is a string and takes the full name of the AAC decoder library binary. + endif + + config CADENCE_CODEC_BSAC_DEC + bool "Cadence BSAC decoder" + help + Select for Cadence BSAC decoder support. + This will cause Cadence codec to include Cadence BSAC library + api symbol. + + if CADENCE_CODEC_BSAC_DEC + config CADENCE_CODEC_BSAC_DEC_LIB + string "Cadence BSAC decoder library name" + help + This option is a string and takes the full name of the BSAC decoder library + endif + + config CADENCE_CODEC_DAB_DEC + bool "Cadence DAB decoder" + help + Select for Cadence DAB decoder support. + This will cause Cadence codec to include Cadence DAB library + api symbol. + + if CADENCE_CODEC_DAB_DEC + config CADENCE_CODEC_DAB_DEC_LIB + string "Cadence DAB decoder library name" + help + This option is a string and takes the full name of the DAB library binary. + endif + + config CADENCE_CODEC_DRM_DEC + bool "Cadence DRM decoder" + help + Select for Cadence DRM decoder support. + This will cause Cadence codec to include Cadence DRM library + api symbol. + + if CADENCE_CODEC_DRM_DEC + config CADENCE_CODEC_DRM_DEC_LIB + string "Cadence DRM decoder library name" + help + This option is a string and takes the full name of the DRM library binary. + endif + + config CADENCE_CODEC_MP3_DEC + bool "Cadence MP3 decoder" + help + Select for Cadence MP3 decoder support. + This will cause Cadence codec to include Cadence MP3 library + api symbol. + + if CADENCE_CODEC_MP3_DEC + config CADENCE_CODEC_MP3_DEC_LIB + string "Cadence MP3 decoder library name" + help + This option is a string and takes the full name of the MP3 library binary. + endif + + config CADENCE_CODEC_MP3_ENC + bool "Cadence MP3 encoder" + help + Select for Cadence MP3 encoder support. + This will cause Cadence codec to include Cadence MP3 library + api symbol. + + if CADENCE_CODEC_MP3_ENC + config CADENCE_CODEC_MP3_ENC_LIB + string "Cadence MP3 encoder library name" + help + This option is a string and takes the full name of the MP3 library binary. + endif + + config CADENCE_CODEC_SBC_DEC + bool "Cadence SBC decoder" + help + Select for Cadence SBC decoder support. + This will cause Cadence codec to include Cadence SBC library + api symbol. + + if CADENCE_CODEC_SBC_DEC + config CADENCE_CODEC_SBC_DEC_LIB + string "Cadence SBC decoder library name" + help + This option is a string and takes the full name of the SBC library binary. + endif + + + config CADENCE_CODEC_VORBIS_DEC + bool "Cadence VORBIS decoder" + help + Select for Cadence VORBIS decoder support. + This will cause Cadence codec to include Cadence VORBIS library + api symbol. + + if CADENCE_CODEC_VORBIS_DEC + config CADENCE_CODEC_VORBIS_DEC_LIB + string "Cadence VORBIS decoder library name" + help + This option is a string and takes the full name of the VORBIS library binary. + endif + + config CADENCE_CODEC_SRC_PP + bool "Cadence SRC polyphase" + help + Select for Cadence SRC polyphase support. + This will cause Cadence codec to include Cadence SRC library + api symbol. + + if CADENCE_CODEC_SRC_PP + config CADENCE_CODEC_SRC_PP_LIB + string "Cadence SRC polyphase library name" + help + This option is a string and takes the full name of the SRC library binary. + endif + +endif # Cadence + + config COMP_DOLBY_DAX_AUDIO_PROCESSING + tristate "Dolby DAX audio processing component" + help + Select to include Dolby DAX component. Dolby DAX component implements DAX API. + API definition together with pre-compiled library is shared by Dolby. + If library is not provided, COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK must be true, + then the input will be copied to the output. + + config COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK + bool "Dolby DAX audio processing component mock" + default y if COMP_STUBS + depends on COMP_DOLBY_DAX_AUDIO_PROCESSING + help + Mock DAX audio processing. It allows for compilation check and basic audio + flow checking. + + config PASSTHROUGH_CODEC + bool "Passthrough codec" + help + Select for a passthrough API codec implementation. + This will cause codec adapter component to include header + files specific to PASSTHROUGH base codecs. + + config WAVES_CODEC + tristate "Waves codec" + help + Select to include Waves codec. Waves codec implements MaxxEffect API. + API definition together with pre-compiled library is shared by Waves Audio Ltd. + If library is not provided will result in compilation error. + For more information, contact consumer@waves.com. + + config WAVES_CODEC_STUB + bool "Waves codec stub" + depends on WAVES_CODEC != "n" + default y if COMP_STUBS + help + Select to build the waves codec with a stub file. This should only be used for + testing or CI. + + config INTEL_MODULES + bool "Intel modules" + depends on LIBRARY_MANAGER + help + Select for a Intel modules API implementation. + This will cause module adapter component to include IADK module + codec code. It will work only when LIBRARY_MANAGER is enabled. +endmenu diff --git a/src/audio/module_adapter/README.md b/src/audio/module_adapter/README.md new file mode 100644 index 000000000000..c642c46096bd --- /dev/null +++ b/src/audio/module_adapter/README.md @@ -0,0 +1,115 @@ +# Module Adapter Architecture + +This directory contains the Module Adapter. + +## Overview + +The Module Adapter is a crucial piece of the IPC4 pipeline, allowing the core SOF graph mechanism to interact with 3rd party processing modules (like Windows APOs or customized vendor DSP engines) through a generic wrapper format. + +## Creation and Teardown Flow + +The Module Adapter wraps an external DSP processing component and translates standard SOF pipeline calls (like `comp_new`, `comp_free`, `comp_trigger`) into an interface the external module natively understands (`ops->init`, `ops->free`, `ops->reset`, etc.). + +```mermaid +sequenceDiagram + participant Pipe as Pipeline + participant ModAd as Module Adapter (module_adapter_new) + participant Mod as Processing Module + participant Ext as External DSP Module (e.g., Windows APO) + + Pipe->>ModAd: comp_new() + activate ModAd + ModAd->>ModAd: Allocates comp_dev & struct processing_module + ModAd->>ModAd: module_adapter_dp_heap_new() (If DP domain) + ModAd->>ModAd: pipeline_comp_dp_task_init() (Spins up Zephyr thread if DP) + ModAd->>Mod: module_init() + Mod->>Ext: ops->init(mod) + Ext-->>ModAd: Init OK + ModAd-->>Pipe: Component READY + deactivate ModAd + + Note over Pipe,Ext: ... Audio Streaming ... + + Pipe->>ModAd: comp_free() + activate ModAd + ModAd->>Mod: module_free() + Mod->>Ext: ops->free(mod) + ModAd->>ModAd: schedule_task_free() (terminates thread) + ModAd->>ModAd: mod_free_all() (cleans up objpool and heap) + ModAd-->>Pipe: Component Destroyed + deactivate ModAd +``` + +## Configuration and Binding Flow + +Connection establishes buffer relationships (`comp_buffer`) connecting the component sources and sinks to the rest of the generic pipeline graph. + +```mermaid +sequenceDiagram + participant Pipe as Pipeline + participant ModAd as Module Adapter + participant Mod as Processing Module + + Pipe->>ModAd: comp_bind() / comp_unbind() + activate ModAd + ModAd->>Mod: module_bind() / module_unbind() + ModAd->>ModAd: module_update_source_buffer_params() + ModAd-->>Pipe: Bind successfully mapped + deactivate ModAd + + Pipe->>ModAd: comp_prepare() + activate ModAd + ModAd->>ModAd: Calculate chunks (period bytes, deep_buff_bytes) + ModAd->>Mod: module_prepare() + Mod-->>ModAd: External DSP prepared internal states + ModAd-->>Pipe: Prepared (Buffer formats synced) + deactivate ModAd +``` + +## Processing Flow (DP and LL Execution) + +To unify components operating directly in interrupt boundaries (DMA Low Latency (LL)) with heavy computational blocks executing asynchronously in Zephyr RTOS threads (Data Processing (DP)), the wrapper intercepts `comp_copy()`. + +### Low Latency (LL) Execution + +For LL modules, processing is fully synchronous within the pipeline tick: + +1. `comp_copy()` invokes `module_adapter_copy()`. +2. Data is fetched directly into `module_process_legacy()` or `module_process_sink_src()`. +3. `ops->process()` consumes upstream arrays and produces downstream arrays. + +### Data Processing (DP) Execution + +For DP modules, a discrete Zephyr thread manages execution asynchronously: + +```mermaid +sequenceDiagram + participant Sched as LL Scheduler + participant ModAd as Module Adapter (comp_copy) + participant DP as DP Thread (dp_task_run) + participant Mod as Processing Module (Ops) + + Sched->>ModAd: comp_copy() + activate ModAd + ModAd->>ModAd: Checks source data & sink free space + ModAd->>DP: Wakeup background thread (module_adapter_process_dp) + ModAd-->>Sched: Returns (No computation done yet) + deactivate ModAd + + activate DP + DP->>Mod: module_process_sink_src() + Mod->>Mod: ops->process(sources, sinks) + Mod-->>DP: Computation Complete + DP->>Sched: Signals data is ready + deactivate DP +``` + +## Error Handling and Memory Sandboxing + +* **Sandboxing (`mod_balloc_align`, `z_impl_mod_fast_get`, `z_impl_mod_free`)**: Since third-party DSP code is treated as semi-untrusted in memory lifetimes, module allocations grab slices from a dedicated component `dp_heap_user` heap instead of the global system heap (`mod_heap_info`). The wrapper automatically prunes leaked objects (`mod_free_all(mod)`) during teardown by keeping an `objpool` of all resource containers. +* **Reset Propagation**: Re-initializations via `COMP_TRIGGER_STOP` map down to `module_reset()` clearing the runtime state of the nested DSP module back to `MODULE_INITIALIZED`. + +## Configuration and Scripts + +* **Kconfig**: Highly customizable environment for "Processing modules" (`COMP_MODULE_ADAPTER`). Provides options for memory allocations, CADENCE codecs (AAC, BSAC, DAB, DRM, MP3, SBC, VORBIS, and their associated libraries), Dolby DAX Audio processing hooks (with stub support), Waves MaxxEffect codec support, and Intel module loaders. +* **CMakeLists.txt**: Handles the sprawling linkage process for the enabled processing modules. Links the core IPC abstraction layers (`module_adapter_ipc3.c` vs `module_adapter_ipc4.c`), external static libraries directly (e.g., `libdax.a`, `libMaxxChrome.a`, arbitrary CADENCE libraries), and includes custom Zephyr build options for `IADK` and `LIBRARY_MANAGER` systems. diff --git a/src/audio/module_adapter/iadk/README.md b/src/audio/module_adapter/iadk/README.md new file mode 100644 index 000000000000..d04ea1924bd8 --- /dev/null +++ b/src/audio/module_adapter/iadk/README.md @@ -0,0 +1,85 @@ +# Intel Audio Development Kit (`module_adapter/iadk`) + +The `iadk` directory provides the Module Adapter implementation for external 3rd-party audio algorithms developed using the **Intel Audio Development Kit (IADK)**. + +Unlike the native SOF `module_interface` API (written primarily in C), the IADK modules are object-oriented C++ classes that derive from `intel_adsp::ProcessingModuleInterface`. The SOF `IadkModuleAdapter` acts as a C++ to C "glue layer" that wraps these IADK methods so they can be natively plugged into the SOF `module_adapter` pipeline without modification to the module's pre-compiled binary. + +## Architecture and Class Hierarchy + +The system defines an `IadkModuleAdapter` class which internally holds an instance of the 3rd-party `ProcessingModuleInterface`. + +```mermaid +classDiagram + class SOF_ModuleAdapter { + +init + +process + +bind + } + + class iadk_wrapper { + iadk_wrapper_process + iadk_wrapper_init + } + + class IadkModuleAdapter { + -processing_module_ + +IadkModuleAdapter_Init + +IadkModuleAdapter_Process + +IadkModuleAdapter_SetConfiguration + } + + class ProcessingModuleInterface { + +Init + +Process + +SetConfiguration + +Reset + } + + class IADK_3rdParty_Algorithm { + +Init + +Process + } + + SOF_ModuleAdapter --> iadk_wrapper : C Function Pointers + iadk_wrapper --> IadkModuleAdapter : Instantiates and Wraps + IadkModuleAdapter --> ProcessingModuleInterface : Polymorphic Interface + ProcessingModuleInterface <|-- IADK_3rdParty_Algorithm : Inherits +``` + +## System Agent and Instantiation Flow + +Because the actual module resides in an external binary, it requires a "System Agent" to correctly instantiate the C++ objects during the component's `init` phase. + +1. The OS host driver sends an IPC `INIT_INSTANCE` command for the module. +2. The `system_agent_start()` function intercepts this, invokes the dynamic module's `create_instance` entry point (which invokes a `ModuleFactory`). +3. The `SystemAgent` deduces the pin count (interfaces) and initial pipeline configurations using `ModuleInitialSettingsConcrete`. +4. The factory allocates the concrete algorithm and checks it back into SOF through `SystemAgent::CheckIn`. + +```mermaid +sequenceDiagram + participant IPC + participant SA + participant Fac + participant Mod + + IPC->>SA: Trigger Mod Creation + SA->>Fac: CI invokes create_instance + Fac->>Fac: Deduce BaseModuleCfgExt + Fac->>Mod: operator new instantiate + + Fac->>SA: SystemAgent CheckIn Module + SA->>Adp: Create new IadkModuleAdapter Module + + SA-->>IPC: Return CPP adapter to C Pipeline +``` + +## Data Buffer Translation + +A significant task of `IadkModuleAdapter_Process` is converting SOF's underlying buffer formats to IADK's `InputStreamBuffer` and `OutputStreamBuffer` structures. + +Instead of letting the module directly touch the SOF `comp_buffer` (which could change with SOF version updates), the adapter uses the abstraction APIs (`source_get_data` / `sink_get_buffer`) and wraps them: + +1. Request raw continuous memory pointers from `source_get_data()`. +2. Construct an `intel_adsp::InputStreamBuffer` pointing to that continuous memory chunk. +3. Call the IADK `processing_module_.Process()`. +4. Release precisely the amount of consumed data using `source_release_data()`. diff --git a/src/audio/module_adapter/iadk/iadk_module_adapter.cpp b/src/audio/module_adapter/iadk/iadk_module_adapter.cpp new file mode 100644 index 000000000000..f940f08fad4b --- /dev/null +++ b/src/audio/module_adapter/iadk/iadk_module_adapter.cpp @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@linux.intel.com> + +#include <iadk_module_adapter.h> +#include <system_error.h> +#include <errno.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef intel_adsp::ProcessingModuleInterface::ErrorCode::Type IntelErrorCode; + +namespace dsp_fw +{ + + IadkModuleAdapter::IadkModuleAdapter(intel_adsp::ProcessingModuleInterface& processing_module, + void *comp_dev_instance, + uint32_t module_id, + uint32_t instance_id, + uint32_t core_id, + size_t module_size) + :processing_module_(processing_module) +{ +} + +int IadkModuleAdapter::IadkModuleAdapter_Init(void) +{ + return processing_module_.Init(); +} + +int IadkModuleAdapter::IadkModuleAdapter_Prepare(void) +{ + return 0; +} + +int IadkModuleAdapter::IadkModuleAdapter_Process(struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + int ret = 0; + + if ((num_of_sources > 0) && (num_of_sinks > 0)) { + intel_adsp::InputStreamBuffer input_stream_buffers[INPUT_PIN_COUNT]; + intel_adsp::OutputStreamBuffer output_stream_buffers[OUTPUT_PIN_COUNT]; + for (int i = 0; i < (int)num_of_sources; i++) { + uint8_t *input, *input_start; + size_t input_end, i_size; + + intel_adsp::InputStreamFlags flags = {}; + i_size = source_get_data_available(sources[i]); + ret = source_get_data(sources[i], i_size, (const void **)&input, + (const void **)&input_start, &input_end); + if (ret != 0) + return ret; + + const intel_adsp::InputStreamBuffer isb_data( + (uint8_t *)input, i_size, flags); + new (&input_stream_buffers[i]) intel_adsp::InputStreamBuffer(isb_data); + } + + for (int i = 0; i < num_of_sinks; i++) { + uint8_t *output, *output_start; + size_t output_end, o_size; + + o_size = sink_get_free_size(sinks[i]); + ret = sink_get_buffer(sinks[i], o_size, (void **)&output, + (void **)&output_start, &output_end); + if (ret != 0) + return ret; + + const intel_adsp::OutputStreamBuffer osb_data( + (uint8_t *)output, o_size); + new (&output_stream_buffers[i]) intel_adsp::OutputStreamBuffer(osb_data); + } + + uint32_t iadk_ret = + processing_module_.Process(input_stream_buffers, output_stream_buffers); + + /* IADK modules returns uint32_t return code. Convert to failure if Process + * not successful. + */ + if (iadk_ret != 0) + ret = -ENODATA; + + for (int i = 0; i < num_of_sources; i++) { + source_release_data(sources[i], input_stream_buffers[i].size); + } + + for (int i = 0; i < num_of_sinks; i++) { + sink_commit_buffer(sinks[i], output_stream_buffers[i].size); + } + } + return ret; +} + + +AdspErrorCode +IadkModuleAdapter::IadkModuleAdapter_SetConfiguration(uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, + const uint8_t *fragment_buffer, + size_t fragment_size, + uint8_t *response, + size_t &response_size) +{ + intel_adsp::ConfigurationFragmentPosition fragment_position = + (intel_adsp::ConfigurationFragmentPosition::Enum) pos; + + return processing_module_.SetConfiguration(config_id, fragment_position, + data_offset_size, fragment_buffer, + fragment_size, response, response_size); +} + +AdspErrorCode +IadkModuleAdapter::IadkModuleAdapter_GetConfiguration(uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t &data_offset_size, + uint8_t *fragment_buffer, + size_t &fragment_size) +{ + intel_adsp::ConfigurationFragmentPosition fragment_position = + (intel_adsp::ConfigurationFragmentPosition::Enum) pos; + + return processing_module_.GetConfiguration(config_id, fragment_position, + data_offset_size, fragment_buffer, + fragment_size); +} + + +void IadkModuleAdapter::IadkModuleAdapter_SetProcessingMode(enum module_processing_mode sof_mode) +{ + intel_adsp::ProcessingMode mode; + sof_mode == MODULE_PROCESSING_NORMAL ? + (mode = intel_adsp::ProcessingMode::NORMAL) : + (mode = intel_adsp::ProcessingMode::BYPASS); + processing_module_.SetProcessingMode(mode); +} + + +void IadkModuleAdapter::IadkModuleAdapter_Reset(void) +{ + processing_module_.Reset(); +} + +enum module_processing_mode IadkModuleAdapter::IadkModuleAdapter_GetProcessingMode(void) +{ + enum module_processing_mode sof_mode; + intel_adsp::ProcessingMode mode = processing_module_.GetProcessingMode(); + mode == intel_adsp::ProcessingMode::NORMAL ? + (sof_mode = MODULE_PROCESSING_NORMAL) : (sof_mode = MODULE_PROCESSING_BYPASS); + return sof_mode; +} + +/* C wrappers for C++ ProcessingModuleInterface() methods. */ +int IadkModuleAdapter::IadkModuleAdapter_Free(void) +{ + return processing_module_.Delete(); +} + + +int iadk_wrapper_init(void *md) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_Init(); +} + +int iadk_wrapper_prepare(void *md) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_Prepare(); +} + +int iadk_wrapper_set_processing_mode(void *md, + enum module_processing_mode mode) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + mod_adp->IadkModuleAdapter_SetProcessingMode(mode); + return 0; +} + +enum module_processing_mode iadk_wrapper_get_processing_mode(void *md) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_GetProcessingMode(); +} + +int iadk_wrapper_reset(void *md) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + mod_adp->IadkModuleAdapter_Reset(); + return 0; +} + +int iadk_wrapper_free(void *md) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_Free(); +} + +int iadk_wrapper_set_configuration(void *md, 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 IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_SetConfiguration(config_id, pos, + data_offset_size, + fragment, fragment_size, + response, response_size); +} + +int iadk_wrapper_get_configuration(void *md, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t *data_offset_size, + uint8_t *fragment, size_t *fragment_size) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_GetConfiguration(config_id, pos, + *data_offset_size, + fragment, + *fragment_size); +} + +int iadk_wrapper_process(void *md, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct IadkModuleAdapter *mod_adp = (struct IadkModuleAdapter *) md; + return mod_adp->IadkModuleAdapter_Process(sources, num_of_sources, + sinks, num_of_sinks); +} + +} /* namespace dsp_fw */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#ifdef __cplusplus +void* operator new(size_t size, intel_adsp::InputStreamBuffer* placeholder) throw() +{ + return placeholder; +} + +void* operator new(size_t size, intel_adsp::OutputStreamBuffer* placeholder) throw() +{ + return placeholder; +} +#endif + diff --git a/src/audio/module_adapter/iadk/module_initial_settings_concrete.cpp b/src/audio/module_adapter/iadk/module_initial_settings_concrete.cpp new file mode 100644 index 000000000000..82e1e02f5e96 --- /dev/null +++ b/src/audio/module_adapter/iadk/module_initial_settings_concrete.cpp @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@linux.intel.com> + +#include <adsp_stddef.h> +#include <module_initial_settings_concrete.h> + +extern "C" { +int memcpy_s(void * dst, size_t maxlen, const void * src, size_t len); +} /* extern "C" */ + +using namespace intel_adsp; + +namespace dsp_fw +{ + +#pragma pack(4) /* this directive is useless when compiling for xtensa but it highlights */ + /* the packing requirement. */ +struct CompoundCfg +{ + BaseModuleCfg cfg; + BaseModuleCfgExt cfg_ext; +}; +#pragma pack() + + +/*! \brief Initializes a new ModuleInitialSettingsConcrete instance given an */ +/* INIT_INSTANCE IPC message blob */ +ModuleInitialSettingsConcrete::ModuleInitialSettingsConcrete(DwordArray const &cfg_ipc_msg) : + cfg_(NULL), cfg_ext_(NULL) +{ + const size_t ipc_msg_size = + reinterpret_cast<DwordArray const&>(cfg_ipc_msg).size() * sizeof(uint32_t); + + if (ipc_msg_size < sizeof(BaseModuleCfg)) { + /* unexpected INIT_INSTANCE message size. Simply return as message + * is unparsable. + */ + return; + } + + if (ipc_msg_size > sizeof(CompoundCfg) - + sizeof(InputPinFormat) - sizeof(OutputPinFormat)) { + + /* INIT_INSTANCE message seems to be compound message */ + /* It shall contain BaseModuleCfg + BaseModuleCfgExt + */ + /* optionally some InputPinFormat[] + OutputPinFormat[] data */ + CompoundCfg const * unvalidated_compound_cfg = cfg_ipc_msg.dataAs<CompoundCfg>(); + if (!unvalidated_compound_cfg) + return; + + const size_t computed_msg_size = + sizeof(CompoundCfg) - + /* CompoundCfg already contains one InputPinFormat and + * one InputPinFormat + */ + (sizeof(InputPinFormat) + sizeof(OutputPinFormat)) + + unvalidated_compound_cfg->cfg_ext.nb_input_pins*sizeof(InputPinFormat) + + unvalidated_compound_cfg->cfg_ext.nb_output_pins*sizeof(InputPinFormat); + + /* check size consistency */ + if (ipc_msg_size != computed_msg_size) { + /* unexpected INIT_INSTANCE message size. Simply return as message + * is unparsable. + */ + return; + } + + /* looks like a valid compound config message has been found */ + cfg_ = &unvalidated_compound_cfg->cfg; + cfg_ext_ = &unvalidated_compound_cfg->cfg_ext; + } + else if (ipc_msg_size == sizeof(BaseModuleCfg)) { + /* INIT_INSTANCE message seems to be the legacy one */ + cfg_ = cfg_ipc_msg.dataAs<BaseModuleCfg>(); + } +} + +void ModuleInitialSettingsConcrete::DeduceBaseModuleCfgExt(size_t in_pins_count, + size_t out_pins_count) +{ + if (!cfg_ext_) { + /* BaseModuleCfgExt data was not part of the INIT_INSTANCE IPC message */ + /* We need to create it on-the-fly */ + tmp_cfg_ext_.tlv.nb_input_pins = in_pins_count; + tmp_cfg_ext_.tlv.nb_output_pins = out_pins_count; + + InputPinFormat* input_pins = tmp_cfg_ext_.tlv.input_pins; + /* InputPinFormat data are all identically initialized based on audio format + * available in the BaseModuleCfg data. + */ + for (size_t i = 0 ; i < in_pins_count ; i++) { + /* Initialize all input pins with same audio format */ + input_pins[i].ibs = cfg_->ibs; + input_pins[i].pin_index = i; + memcpy_s(&input_pins[i].audio_fmt, + sizeof(input_pins[i].audio_fmt), + &cfg_->audio_fmt, + sizeof(AudioFormat)); + } + + OutputPinFormat* output_pins = + reinterpret_cast<OutputPinFormat*>(&input_pins[in_pins_count]); + for (size_t i = 0 ; i < out_pins_count ; i++) { + /* Initialize all pins obs with same obs value */ + output_pins[i].obs = cfg_->obs; + output_pins[i].pin_index = i; + memcpy_s(&output_pins[i].audio_fmt, + sizeof(output_pins[i].audio_fmt), + &cfg_->audio_fmt, + sizeof(AudioFormat)); + } + + /* a valid BaseModuleCfgExt has been created on-the-fly */ + cfg_ext_ = reinterpret_cast<BaseModuleCfgExt const*>(&tmp_cfg_ext_); + } +} + +void const* ModuleInitialSettingsConcrete::GetUntypedItem(ModuleInitialSettingsKey key, + size_t &length) +{ + void const* array = NULL; + length = 0; + + switch(key) + { + case intel_adsp::LEGACY_STRUCT: + length = 1; + array = cfg_; + break; + + case intel_adsp::IN_PINS_FORMAT: + length = cfg_ext_->nb_input_pins; + array = &cfg_ext_->input_pins[0]; + break; + + case intel_adsp::OUT_PINS_FORMAT: + length = cfg_ext_->nb_output_pins; + /* output_pins array follows the input_pins array in BaseModuleCfgExt + * struct layout + */ + array = reinterpret_cast<OutputPinFormat const*> + (&cfg_ext_->input_pins[cfg_ext_->nb_input_pins]); + break; + + default: + break; + } + return array; +} + +} /* namespace dsp_fw */ diff --git a/src/audio/module_adapter/iadk/system_agent.cpp b/src/audio/module_adapter/iadk/system_agent.cpp new file mode 100644 index 000000000000..caed8cf65860 --- /dev/null +++ b/src/audio/module_adapter/iadk/system_agent.cpp @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@linux.intel.com> + +/* + * SOF System Agent - register IADK Loadable Library in SOF infrastructure. + */ + +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <rtos/string.h> +#include <rtos/userspace_helper.h> +#include <utilities/array.h> +#include <module/iadk/adsp_error_code.h> +#include <system_service.h> +#include <system_agent_interface.h> +#include <module_initial_settings_concrete.h> +#include <iadk_module_adapter.h> +#include <system_agent.h> +#include <sof/audio/module_adapter/library/native_system_service.h> +#include <sof/audio/module_adapter/library/native_system_agent.h> + +using namespace intel_adsp; +using namespace intel_adsp::system; +using namespace dsp_fw; + +void* operator new(size_t size, intel_adsp::ModuleHandle *placeholder) throw() +{ + return placeholder; +} + +namespace intel_adsp +{ +namespace system +{ + +/* Structure storing handles to system service operations */ +const APP_TASK_DATA AdspSystemService SystemAgent::system_service_ = { + native_system_service_log_message, + native_system_service_safe_memcpy, + native_system_service_safe_memmove, + native_system_service_vec_memset, + native_system_service_create_notification, + native_system_service_send_notif_msg, + native_system_service_get_interface, +}; + +SystemAgent::SystemAgent(uint32_t module_id, + uint32_t instance_id, + uint32_t core_id, + uint32_t log_handle) : + log_handle_(log_handle), + core_id_(core_id), + module_id_(module_id), + instance_id_(instance_id), + module_handle_(NULL), + module_size_(0) +{} + +void SystemAgent::CheckIn(ProcessingModuleInterface& processing_module, + ModuleHandle &module_handle, + LogHandle *&log_handle) +{ + module_handle_ = &module_handle; + /* Initializes the ModuleAdapter into the ModuleHandle */ + IadkModuleAdapter* module_adapter = + new (module_handle_)IadkModuleAdapter(processing_module, + NULL, + module_id_, + instance_id_, + core_id_, + module_size_ + ); + (void)module_adapter; + log_handle = reinterpret_cast<LogHandle*>(log_handle_); +} + +int SystemAgent::CheckIn(ProcessingModuleFactoryInterface& module_factory, + ModulePlaceholder *module_placeholder, + size_t processing_module_size, + uint32_t core_id, + const void *obfuscated_mod_cfg, + void *obfuscated_parent_ppl, + void **obfuscated_modinst_p) +{ + IoPinsInfo pins_info; + const dsp_fw::DwordArray& cfg_ipc_msg = + *reinterpret_cast<const dsp_fw::DwordArray*>(obfuscated_mod_cfg); + ModuleInitialSettingsConcrete settings(cfg_ipc_msg); + + ProcessingModulePrerequisites prerequisites; + module_factory.GetPrerequisites(prerequisites); + + /* Note: If module has no output pins, it requires HungryRTSink */ + /* to terminate parent Pipeline */ + const bool hungry_rt_sink_required = prerequisites.output_pins_count == 0; + if (hungry_rt_sink_required) prerequisites.output_pins_count = 1; + + if ((prerequisites.input_pins_count < 1) || + (prerequisites.input_pins_count > INPUT_PIN_COUNT) || + (prerequisites.output_pins_count < 1) || + (prerequisites.output_pins_count > OUTPUT_PIN_COUNT)) + return -1; + + /* Deduce BaseModuleCfgExt if it was not part of the INIT_INSTANCE IPC message */ + settings.DeduceBaseModuleCfgExt(prerequisites.input_pins_count, + prerequisites.output_pins_count); + + module_factory.Create(*this, module_placeholder, ModuleInitialSettings(settings), pins_info); + IadkModuleAdapter& module_adapter = *reinterpret_cast<IadkModuleAdapter*>(module_handle_); + *obfuscated_modinst_p = &module_adapter; + reinterpret_cast<intel_adsp::ProcessingModuleInterface*>(module_placeholder)->Init(); + return 0; +} + +} /* namespace system */ +} /* namespace intel_adsp */ + +/* The create_instance_f is a function call type known in IADK module. The module entry_point + * points to this type of function which starts module creation. + */ +typedef int (*create_instance_f)(uint32_t module_id, uint32_t instance_id, uint32_t core_id, + void *mod_cfg, void *parent_ppl, void **mod_ptr); + +int system_agent_start(const struct system_agent_params *params, + const void **adapter) +{ + uint32_t ret; + SystemAgent system_agent(params->module_id, params->instance_id, params->core_id, + params->log_handle); + void* system_agent_p = reinterpret_cast<void*>(&system_agent); + + create_instance_f ci = (create_instance_f)(params->entry_point); + ret = ci(params->module_id, params->instance_id, params->core_id, params->mod_cfg, NULL, + &system_agent_p); + + IadkModuleAdapter* module_adapter = reinterpret_cast<IadkModuleAdapter*>(system_agent_p); + *adapter = module_adapter; + return ret; +} + +extern "C" void __cxa_pure_virtual() __attribute__((weak)); + +void __cxa_pure_virtual() +{ +} + diff --git a/src/audio/module_adapter/library/README.md b/src/audio/module_adapter/library/README.md new file mode 100644 index 000000000000..3dd9aee14f7c --- /dev/null +++ b/src/audio/module_adapter/library/README.md @@ -0,0 +1,80 @@ +# Loadable Library & Userspace Proxy (`module_adapter/library`) + +The `library` directory within the module adapter manages the lifecycle and execution isolation for dynamically loaded algorithms, often referred to as "LLEXT modules" or "Userspace Modules". + +It acts as a secure intermediary layer between the native SOF/Zephyr kernel execution mode (supervisor mode) and the 3rd-party module running in an isolated user-mode context. By relying on Zephyr's Userspace mechanisms (`k_mem_domain`, `K_USER` threads), a faulting or misbehaving loadable extension cannot crash the entire firmware. + +## Architecture & Userspace Sandbox + +The Userspace Proxy architecture involves: + +- **`struct userspace_context`**: This encapsulates the memory domain (`k_mem_domain`) mapped exclusively for this module (code, rodata, BSS, and private heap memory). +- **`user_work_item`**: A Zephyr `k_work_user` mechanism. IPC configuration commands and data processing calls are packaged into a work item and executed safely inside the memory boundaries via `userspace_proxy_worker_handler`. + +```mermaid +graph TD + subgraph SOF Supervisor Domain + P["Pipeline DP Scheduler"] + MADP["Module Adapter Context"] + PROXY["Userspace Proxy (userspace_proxy_invoke)"] + end + + subgraph Zephyr Userspace Domain + SYSAGENT["LLEXT System Agent"] + HANDLER["Worker Handler (userspace_proxy_handle_request)"] + MOD["External Loadable Module (struct module_interface)"] + end + + P -->|Triggers process| MADP + MADP -->|Invokes Proxy| PROXY + + PROXY -->|Packages params & k_work| HANDLER + + HANDLER -->|Safe Call Context| MOD + SYSAGENT -.->|Bootstraps| MOD + + style SOF Supervisor Domain fill:#1d2951,stroke:#333 + style Zephyr Userspace Domain fill:#2e0b1a,stroke:#333 +``` + +## State Transitions & IPC Handling + +IPC messages arriving from the host (e.g. `SET_CONF`, `GET_CONF`, `MODULE_INIT`, `MODULE_BIND`) first hit the Module Adapter running in Supervisor Mode. The adapter checks its configuration and invokes the Userspace Proxy. The proxy performs the following context switch: + +```mermaid +sequenceDiagram + participant IPC as SOF IPC Task + participant MA as Module Adapter + participant Proxy as Userspace Proxy + participant Worker as Zephyr k_work_user Thread + participant UserMod as LLEXT Module + + IPC->>MA: IPC SET_CONF config_id + MA->>Proxy: userspace_proxy_set_configuration + + note over Proxy: 1. Package proxy params + note over Proxy: 2. Add Mailbox memory to `k_mem_domain` + note over Proxy: 3. Post `k_work_user` / event + + Proxy->>Worker: Context Switch -> User Mode + + Worker->>UserMod: module_interface set_configuration + + note over UserMod: Parse config payload safely + + UserMod-->>Worker: Return status + Worker-->>Proxy: Signal Task Done + + note over Proxy: Remove Mailbox memory from domain + + Proxy-->>MA: Return execution + MA-->>IPC: Send Reply/Status to Host +``` + +### Memory Domain Adjustments + +A crucial aspect of the userspace proxy is dynamic memory permission elevation: + +- Normally, the userspace module can only access its own `heap`, `data`, and `bss` partitions. +- When an IPC like `GET_CONF` requests large IPC buffers, the proxy temporarily adds the hardware `MAILBOX_HOSTBOX` into the module's `k_mem_domain` using `k_mem_domain_add_partition()`. +- Once the userspace thread returns, that hardware window is immediately removed from the memory domain to minimize the vulnerability window. diff --git a/src/audio/module_adapter/library/native_system_agent.c b/src/audio/module_adapter/library/native_system_agent.c new file mode 100644 index 000000000000..b93405b8bd27 --- /dev/null +++ b/src/audio/module_adapter/library/native_system_agent.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ + +#include <stdbool.h> +#include <stdint.h> +#include <utilities/array.h> +#include <native_system_agent.h> + +/* The create_instance_f is a function call type known in module. The module entry_point + * points to this type of function which starts module creation. + */ + +typedef void* (*native_create_instance_f)(void *mod_cfg, void *parent_ppl, + void **mod_ptr); + +struct native_system_agent native_sys_agent; + +int native_system_agent_start(const struct system_agent_params *params, + const void **iface) +{ + native_sys_agent.module_id = params->module_id; + native_sys_agent.instance_id = params->instance_id; + native_sys_agent.core_id = params->core_id; + native_sys_agent.log_handle = params->log_handle; + const void *ret; + + void *system_agent_p = &native_sys_agent; + + native_create_instance_f ci = (native_create_instance_f)params->entry_point; + + ret = ci(params->mod_cfg, NULL, &system_agent_p); + if (!ret) + return -EINVAL; + + *iface = ret; + return 0; +} diff --git a/src/audio/module_adapter/library/native_system_service.c b/src/audio/module_adapter/library/native_system_service.c new file mode 100644 index 000000000000..1c4688e885d0 --- /dev/null +++ b/src/audio/module_adapter/library/native_system_service.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ +/* + * Native System Service interface for ADSP loadable library. + */ + +#include <errno.h> +#include <stdbool.h> +#include <sof/common.h> +#include <rtos/sof.h> +#include <rtos/string.h> +#include <ipc4/notification.h> +#include <sof/ipc/msg.h> +#include <native_system_service.h> +#include <sof/lib_manager.h> +#include <module/module/logger.h> +#include <rtos/userspace_helper.h> + +#define RSIZE_MAX 0x7FFFFFFF + + /*! Module log level priority to sof log level conversion array */ +const int log_priority_map[L_MAX] = { + /*! Critical message. */ + [L_CRITICAL] = LOG_LEVEL_CRITICAL, + /*! Error message. */ + [L_ERROR] = LOG_LEVEL_ERROR, + /*! High importance log level. */ + [L_HIGH] = LOG_LEVEL_ERROR, + /*! Warning message. */ + [L_WARNING] = LOG_LEVEL_WARNING, + /*! Medium importance log level. */ + [L_MEDIUM] = LOG_LEVEL_WARNING, + /*! Low importance log level. */ + [L_LOW] = LOG_LEVEL_INFO, + /*! Information. */ + [L_INFO] = LOG_LEVEL_INFO, + /*! Verbose message. */ + [L_VERBOSE] = LOG_LEVEL_VERBOSE, + [L_DEBUG] = LOG_LEVEL_DEBUG +}; + +static int log_priority_to_sof_level(enum log_priority log_priority) +{ + if ((uint32_t)log_priority >= L_DEBUG) + return LOG_LEVEL_DEBUG; + + return log_priority_map[log_priority]; +} + +void native_system_service_log_message(enum log_priority log_priority, uint32_t log_entry, + struct log_handle const *log_handle, uint32_t param1, + uint32_t param2, uint32_t param3, uint32_t param4) +{ + log_priority_to_sof_level(log_priority); + uint32_t argc = (log_entry & 0x7); + /* TODO: Need to call here function like _log_sofdict, since we do not have format */ + /* passed from library */ + /* This function could be finished when cAVS/ACE logging formats support will be */ + /* added to SOF.*/ + switch (argc) { + case 1: + break; + + case 2: + break; + + case 3: + break; + + case 4: + break; + + default: + break; + } +} + +AdspErrorCode native_system_service_safe_memcpy(void *RESTRICT dst, size_t maxlen, + const void *RESTRICT src, + size_t len) +{ + return (AdspErrorCode) memcpy_s(dst, maxlen, src, len); +} + +AdspErrorCode native_system_service_safe_memmove(void *dst, size_t maxlen, const void *src, + size_t len) +{ + if (dst == NULL || maxlen > RSIZE_MAX) + return ADSP_INVALID_PARAMETERS; + + if (src == NULL || len > maxlen) { + memset(dst, 0, maxlen); + return ADSP_INVALID_PARAMETERS; + } + + if (len != 0) { + /* TODO: now it is memcopy. Finally it will be remap maybe? + * Fix it when memory management API will be available. + * memmove(dst, src, len); + */ + memcpy_s(dst, maxlen, src, len); + } + return ADSP_NO_ERROR; +} + +void *native_system_service_vec_memset(void *dst, int c, size_t len) +{ + /* TODO: Currently simple memset. Should be changed. */ + memset(dst, c, len); + return dst; +} + +AdspErrorCode native_system_service_create_notification(struct notification_params *params, + uint8_t *notification_buffer, + uint32_t notification_buffer_size, + struct notification_handle **handle) +{ + if ((params == NULL) || (notification_buffer == NULL) + || (notification_buffer_size <= 0) || (handle == NULL)) + return ADSP_INVALID_PARAMETERS; + + union ipc4_notification_header header; + + header.r.notif_type = params->type; + header.r._reserved_0 = params->user_val_1; + header.r.type = SOF_IPC4_GLB_NOTIFICATION; + header.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + header.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + struct ipc_msg *msg = lib_notif_msg_init((uint32_t)header.dat, notification_buffer_size); + + if (msg) { + *handle = (struct notification_handle *)msg; + params->payload = msg->tx_data; + } + + return ADSP_NO_ERROR; +} + + +AdspErrorCode native_system_service_send_notif_msg(enum notification_target notification_target, + struct notification_handle *message, + uint32_t actual_payload_size) +{ + if ((message == NULL) || (actual_payload_size == 0)) + return ADSP_INVALID_PARAMETERS; + + struct ipc_msg *msg = (struct ipc_msg *)message; + + lib_notif_msg_send(msg); + return ADSP_NO_ERROR; +} + +AdspErrorCode native_system_service_get_interface(enum interface_id id, + struct system_service_iface **iface) +{ + if (id < 0) + return ADSP_INVALID_PARAMETERS; + return ADSP_NO_ERROR; +} + +const APP_TASK_DATA struct native_system_service native_system_service = { + .basic = { + .log_message = native_system_service_log_message, + .safe_memcpy = native_system_service_safe_memcpy, + .safe_memmove = native_system_service_safe_memmove, + .vec_memset = native_system_service_vec_memset, + .notification_create = native_system_service_create_notification, + .notification_send = native_system_service_send_notif_msg, + .get_interface = native_system_service_get_interface + } +}; diff --git a/src/audio/module_adapter/library/userspace_proxy.c b/src/audio/module_adapter/library/userspace_proxy.c new file mode 100644 index 000000000000..4154bad3781d --- /dev/null +++ b/src/audio/module_adapter/library/userspace_proxy.c @@ -0,0 +1,907 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> +// Author: Adrian Warecki <adrian.warecki@intel.com> + +/** + * \file audio/module_adapter/library/userspace_proxy.c + * \brief Userspace proxy. Acts as an intermediary between SOF and a userspace module. + * \brief Responsible for preparing the memory domain required for userspace execution + * \brief and forwarding API calls. The proxy invokes corresponding module methods + * \brief in userspace context. Enables execution of any module implementing module_interface + * \brief as a userspace module. + * \authors Adrian Warecki + */ + +#include <sof/common.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/memory.h> +#include <rtos/string.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <sof/lib_manager.h> +#include <sof/audio/component.h> +#include <sof/schedule/dp_schedule.h> +#include <rtos/userspace_helper.h> +#include <utilities/array.h> +#include <zephyr/sys/sem.h> +#include <sof/audio/module_adapter/module/generic.h> + +#include <sof/audio/module_adapter/library/userspace_proxy.h> +#include <sof/audio/module_adapter/library/userspace_proxy_user.h> +#include <rimage/sof/user/manifest.h> + + /* Assume that all the code runs in supervisor mode and don't make system calls. */ +#define __ZEPHYR_SUPERVISOR__ + +LOG_MODULE_REGISTER(userspace_proxy, CONFIG_SOF_LOG_LEVEL); + +/* 6f6b6f4b-6f73-7466-20e1e62b9779f003 */ +SOF_DEFINE_REG_UUID(userspace_proxy); + +DECLARE_TR_CTX(userspace_proxy_tr, SOF_UUID(userspace_proxy_uuid), LOG_LEVEL_INFO); + +static const struct module_interface userspace_proxy_interface; + +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) +#include <sof/audio/module_adapter/iadk/system_agent.h> +#include <sof/schedule/dp_schedule.h> + +static inline int user_worker_get(void) +{ + return 0; +} + +static inline void user_worker_put(void) { } + +struct k_work_user *userspace_proxy_register_ipc_handler(struct processing_module *mod, + struct k_event *event) +{ + struct userspace_context * const user_ctx = mod->user_ctx; + + if (user_ctx) { + tr_dbg(&userspace_proxy_tr, "Set DP event %p for module %p", + (void *)event, (void *)mod); + assert(user_ctx->work_item); + + user_ctx->dp_event = event; + user_ctx->work_item->event = event; + + return &user_ctx->work_item->work_item; + } + + return NULL; +} +#else +/* IPC requests targeting userspace modules are handled through a user work queue. + * Each userspace module provides its own work item that carries the IPC request parameters. + * The worker thread is switched into the module's memory domain and receives the work item. + * It invokes the appropriate module function in userspace context and writes the operation + * result back into the work item. + * + * There is only a single work queue, which is shared by all userspace modules. It is created + * dynamically when needed. Because SOF uses a single dedicated thread for handling IPC, there + * is no need to perform any additional serialization when accessing the worker. + */ +struct user_worker { + k_tid_t thread_id; /* ipc worker thread ID */ + uint32_t reference_count; /* module reference count */ + void *stack_ptr; /* pointer to worker stack */ + struct k_work_user_q work_queue; + struct k_event event; +}; + +static struct user_worker worker; + +static int user_worker_get(void) +{ + if (worker.reference_count) { + worker.reference_count++; + return 0; + } + + worker.stack_ptr = user_stack_allocate(CONFIG_SOF_USERSPACE_PROXY_WORKER_STACK_SIZE, + K_USER); + if (!worker.stack_ptr) { + tr_err(&userspace_proxy_tr, "Userspace worker stack allocation failed."); + return -ENOMEM; + } + + k_event_init(&worker.event); + k_work_user_queue_start(&worker.work_queue, worker.stack_ptr, + CONFIG_SOF_USERSPACE_PROXY_WORKER_STACK_SIZE, 0, NULL); + + worker.thread_id = k_work_user_queue_thread_get(&worker.work_queue); + + k_thread_access_grant(worker.thread_id, &worker.event); + + worker.reference_count++; + return 0; +} + +static void user_worker_put(void) +{ + /* Module removed so decrement counter */ + worker.reference_count--; + + /* Free worker resources if no more active user space modules */ + if (worker.reference_count == 0) { + k_thread_abort(worker.thread_id); + user_stack_free(worker.stack_ptr); + } +} +#endif + +static int user_work_item_init(struct userspace_context *user_ctx, struct k_heap *user_heap) +{ + struct user_work_item *work_item = NULL; + int ret; + + ret = user_worker_get(); + if (ret) + return ret; + + /* We have only a single userspace IPC worker. It handles requests for all userspace + * modules, which may run on different cores. Because the worker processes work items + * coming from any core, the work item must be allocated in coherent memory. + */ + work_item = sof_heap_alloc(user_heap, SOF_MEM_FLAG_COHERENT, sizeof(*work_item), 0); + if (!work_item) { + user_worker_put(); + return -ENOMEM; + } + + k_work_user_init(&work_item->work_item, userspace_proxy_worker_handler); + +#if !IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + work_item->event = &worker.event; +#endif + work_item->params.context = user_ctx; + user_ctx->work_item = work_item; + + return 0; +} + +static void user_work_item_free(struct userspace_context *user_ctx, struct k_heap *user_heap) +{ + sof_heap_free(user_heap, user_ctx->work_item); + user_worker_put(); +} + +static inline struct module_params *user_work_get_params(struct userspace_context *user_ctx) +{ + return &user_ctx->work_item->params; +} + +BUILD_ASSERT(IS_ALIGNED(MAILBOX_HOSTBOX_BASE, CONFIG_MMU_PAGE_SIZE), + "MAILBOX_HOSTBOX_BASE is not page aligned"); + +BUILD_ASSERT(IS_ALIGNED(MAILBOX_HOSTBOX_SIZE, CONFIG_MMU_PAGE_SIZE), + "MAILBOX_HOSTBOX_SIZE is not page aligned"); + +static int userspace_proxy_invoke(struct userspace_context *user_ctx, uint32_t cmd, + bool ipc_payload_access) +{ +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + struct k_event * const event = user_ctx->dp_event; +#else + struct k_event * const event = &worker.event; +#endif + struct module_params *params = user_work_get_params(user_ctx); + const uintptr_t ipc_req_buf = (uintptr_t)MAILBOX_HOSTBOX_BASE; + struct k_mem_partition ipc_part = { + .start = ipc_req_buf, + .size = MAILBOX_HOSTBOX_SIZE, + .attr = user_get_partition_attr(ipc_req_buf) | K_MEM_PARTITION_P_RO_U_RO, + }; + int ret = 0, ret2; + + params->cmd = cmd; + + if (ipc_payload_access) { + ret = k_mem_domain_add_partition(user_ctx->comp_dom, &ipc_part); + if (ret < 0) { + tr_err(&userspace_proxy_tr, "Add mailbox to domain error: %d", ret); + return ret; + } + } + +#if !IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + /* Switch worker thread to module memory domain */ + ret = k_mem_domain_add_thread(user_ctx->comp_dom, worker.thread_id); + if (ret < 0) { + tr_err(&userspace_proxy_tr, "Failed to switch memory domain, error: %d", ret); + goto done; + } + +#ifdef CONFIG_SCHED_CPU_MASK + /* Pin worker thread to the same core as the module */ + ret = k_thread_cpu_pin(worker.thread_id, cpu_get_id()); + if (ret < 0) { + tr_err(&userspace_proxy_tr, "Failed to pin cpu, error: %d", ret); + goto done; + } +#endif + + ret = k_work_user_submit_to_queue(&worker.work_queue, &user_ctx->work_item->work_item); + if (ret < 0) { + tr_err(&userspace_proxy_tr, "Submit to queue error: %d", ret); + goto done; + } +#else + assert(event); + k_event_post(event, DP_TASK_EVENT_IPC); +#endif + + /* Timeout value is aligned with the ipc_wait_for_compound_msg function */ + if (!k_event_wait_safe(event, DP_TASK_EVENT_IPC_DONE, false, + Z_TIMEOUT_US(250 * 20))) { + tr_err(&userspace_proxy_tr, "IPC processing timedout."); + ret = -ETIMEDOUT; + } + +done: + if (ipc_payload_access) { + ret2 = k_mem_domain_remove_partition(user_ctx->comp_dom, &ipc_part); + if (ret2 < 0) { + tr_err(&userspace_proxy_tr, "Mailbox remove from domain error: %d", ret); + + if (!ret) + ret = ret2; + } + } + + return ret; +} + +extern struct k_mem_partition common_partition; + +static int userspace_proxy_memory_init(struct userspace_context *user_ctx, + const struct comp_driver *drv) +{ + /* Add module private heap to memory partitions */ + struct k_mem_partition heap_part = { .attr = K_MEM_PARTITION_P_RW_U_RW }; + struct sys_heap *heap = &drv->user_heap->heap; + + k_mem_region_align(&heap_part.start, &heap_part.size, + POINTER_TO_UINT(heap->init_mem), + heap->init_bytes, CONFIG_MM_DRV_PAGE_SIZE); + + tr_dbg(&userspace_proxy_tr, "Heap partition %#lx + %zx, attr = %u", + heap_part.start, heap_part.size, heap_part.attr); + +#if !defined(CONFIG_XTENSA_MMU_DOUBLE_MAP) && defined(CONFIG_SOF_ZEPHYR_HEAP_CACHED) +#define HEAP_PART_CACHED + /* Add cached module private heap to memory partitions */ + struct k_mem_partition heap_cached_part = { + .attr = K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB + }; + + k_mem_region_align(&heap_cached_part.start, &heap_cached_part.size, + POINTER_TO_UINT(sys_cache_cached_ptr_get(heap->init_mem)), + heap->init_bytes, CONFIG_MM_DRV_PAGE_SIZE); + + tr_dbg(&userspace_proxy_tr, "Cached heap partition %#lx + %zx, attr = %u", + heap_cached_part.start, heap_cached_part.size, heap_cached_part.attr); +#endif + + struct k_mem_partition *parts_ptr[] = { + /* The common partition contains sof components accessible to the userspace module. + * These include ops structures marked with APP_TASK_DATA. + */ + &common_partition, +#ifdef HEAP_PART_CACHED + &heap_cached_part, +#endif + &heap_part + }; + + tr_dbg(&userspace_proxy_tr, "Common partition %#lx + %zx, attr = %u", + common_partition.start, common_partition.size, common_partition.attr); + + return k_mem_domain_init(user_ctx->comp_dom, ARRAY_SIZE(parts_ptr), parts_ptr); +} + +static int userspace_proxy_add_sections(struct userspace_context *user_ctx, uint32_t instance_id, + const struct sof_man_module *const mod) +{ + struct k_mem_partition mem_partition; + void *va_base; + int idx, ret; + + for (idx = 0; idx < ARRAY_SIZE(mod->segment); ++idx) { + if (!mod->segment[idx].flags.r.load) + continue; + + if (mod->segment[idx].flags.r.code) + mem_partition.attr = K_MEM_PARTITION_P_RX_U_RX; + else if (!mod->segment[idx].flags.r.readonly) + mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW; + else + mem_partition.attr = K_MEM_PARTITION_P_RO_U_RO; + + mem_partition.start = mod->segment[idx].v_base_addr; + mem_partition.size = mod->segment[idx].flags.r.length * CONFIG_MM_DRV_PAGE_SIZE; + mem_partition.attr |= user_get_partition_attr(mem_partition.start); + + ret = k_mem_domain_add_partition(user_ctx->comp_dom, &mem_partition); + + tr_dbg(&userspace_proxy_tr, "Add mod partition %#lx + %zx, attr = %u, ret = %d", + mem_partition.start, mem_partition.size, mem_partition.attr, ret); + + if (ret < 0) + return ret; + } + + lib_manager_get_instance_bss_address(instance_id, mod, &va_base, &mem_partition.size); + mem_partition.start = POINTER_TO_UINT(va_base); + mem_partition.attr = user_get_partition_attr(mem_partition.start) | + K_MEM_PARTITION_P_RW_U_RW; + ret = k_mem_domain_add_partition(user_ctx->comp_dom, &mem_partition); + + tr_dbg(&userspace_proxy_tr, "Add bss partition %#lx + %zx, attr = %u, ret = %d", + mem_partition.start, mem_partition.size, mem_partition.attr, ret); + + return ret; +} + +static int userspace_proxy_start_agent(struct userspace_context *user_ctx, + system_agent_start_fn start_fn, + const struct system_agent_params *agent_params, + const void **agent_interface) +{ + const byte_array_t * const mod_cfg = (byte_array_t *)agent_params->mod_cfg; + struct module_params *params = user_work_get_params(user_ctx); + + params->ext.agent.start_fn = start_fn; + + /* Start the system agent, if provided. */ + if (start_fn) { + params->ext.agent.params = *agent_params; + params->ext.agent.params.mod_cfg = ¶ms->ext.agent.mod_cfg; + params->ext.agent.mod_cfg = *mod_cfg; + + /* In case of processing modules ipc in the DP thread, the agent will be started in + * the init function. At this point the DP thread does not exist yet. + */ +#if !IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + int ret = userspace_proxy_invoke(user_ctx, USER_PROXY_MOD_CMD_AGENT_START, true); + + if (ret) + return ret; + + *agent_interface = params->ext.agent.out_interface; + return params->status; +#endif + } + return 0; +} + +int userspace_proxy_create(struct userspace_context **user_ctx, const struct comp_driver *drv, + const struct sof_man_module *manifest, system_agent_start_fn start_fn, + const struct system_agent_params *agent_params, + const void **agent_interface, const struct module_interface **ops) +{ + struct userspace_context *context; + struct k_mem_domain *domain; + int ret; + + tr_dbg(&userspace_proxy_tr, "userspace create"); + + context = k_heap_alloc(drv->user_heap, sizeof(struct userspace_context), K_FOREVER); + if (!context) + return -ENOMEM; + + context->dp_event = NULL; + + /* Allocate memory domain struct */ + domain = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*domain)); + if (!domain) { + ret = -ENOMEM; + goto error; + } + context->comp_dom = domain; + + ret = userspace_proxy_memory_init(context, drv); + if (ret) + goto error_dom; + + ret = userspace_proxy_add_sections(context, agent_params->instance_id, manifest); + if (ret) + goto error_dom; + + ret = user_work_item_init(context, drv->user_heap); + if (ret) + goto error_dom; + + ret = userspace_proxy_start_agent(context, start_fn, agent_params, agent_interface); + if (ret) { + tr_err(&userspace_proxy_tr, "System agent failed with error %d.", ret); + goto error_work_item; + } + + *user_ctx = context; + + /* Store a pointer to the module's interface. For the LMDK modules, the agent places a + * pointer to the module interface at the address specified by agent_interface. Since this + * points to ops, the assignment of the module interface used by this proxy must occur + * after the agent has been started. For other module types, the ops parameter points to a + * valid module interface. + */ + context->interface = *ops; + + /* All calls to the module interface must pass through the proxy. Set up our own interface. + */ + *ops = &userspace_proxy_interface; + + return 0; + +error_work_item: + user_work_item_free(context, drv->user_heap); +error_dom: + rfree(domain); +error: + k_heap_free(drv->user_heap, context); + return ret; +} + +void userspace_proxy_destroy(const struct comp_driver *drv, struct userspace_context *user_ctx) +{ + tr_dbg(&userspace_proxy_tr, "userspace proxy destroy"); + user_work_item_free(user_ctx, drv->user_heap); + rfree(user_ctx->comp_dom); + k_heap_free(drv->user_heap, user_ctx); +} + +/** + * Copy parameters to user worker accessible space. + * Queue module init() operation and return its result. + * Module init() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_init(struct processing_module *mod) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + /* Start the system agent, if provided. Params is already filled by + * the userspace_proxy_start_agent function. + */ + if (params->ext.agent.start_fn) { + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_AGENT_START, true); + if (ret) + return ret; + + if (params->ext.agent.start_fn == system_agent_start) + module_set_private_data(mod, (void *)params->ext.agent.out_interface); + else + mod->user_ctx->interface = params->ext.agent.out_interface; + } +#endif + + params->mod = mod; + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_INIT, true); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module prepare() operation and return its result. + * Module prepare() code is performed in user workqueue. + * + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->prepare) + return 0; + + params->ext.proc.sources = sources; + params->ext.proc.num_of_sources = num_of_sources; + params->ext.proc.sinks = sinks; + params->ext.proc.num_of_sinks = num_of_sinks; + + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_PREPARE, false); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Forward processing request to the module's process() implementation. + * + * It is invoked by the DP thread running in userspace, so no + * additional queuing or context switching is performed here. + * + * @param mod Pointer to the processing module instance. + * @param sources Array of input sources for the module. + * @param num_of_sources Number of input sources. + * @param sinks Array of output sinks for the module. + * @param num_of_sinks Number of output sinks. + * + * @return 0 on success, negative error code on failure. + */ +static int userspace_proxy_process(struct processing_module *mod, struct sof_source **sources, + int num_of_sources, struct sof_sink **sinks, int num_of_sinks) +{ + return mod->user_ctx->interface->process(mod, sources, num_of_sources, sinks, num_of_sinks); +} + +/** + * Copy parameters to user worker accessible space. + * Queue module reset() operation and return its result. + * Module reset() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_reset(struct processing_module *mod) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + if (!mod->user_ctx->interface->reset) + return 0; + + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_RESET, false); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module free() operation and return its result. + * Module free() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_free(struct processing_module *mod) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret = 0; + + comp_dbg(mod->dev, "start"); + + if (mod->user_ctx->interface->free) { + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_FREE, false); + if (ret) + return ret; + ret = params->status; + } + + /* Destroy workqueue if this was last active userspace module */ + userspace_proxy_destroy(mod->dev->drv, mod->user_ctx); + mod->user_ctx = NULL; + + /* Return status from module code operation. */ + return ret; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module set_configuration() operation and return its result. + * Module set_configuration() code is performed in user workqueue. + * + * @param[in] mod - struct processing_module pointer + * @param[in] config_id - Configuration ID + * @param[in] pos - position of the fragment in the large message + * @param[in] data_offset_size: size of the whole configuration if it is the first fragment or the + * only fragment. Otherwise, it is the offset of the fragment in the whole + * configuration. + * @param[in] fragment: configuration fragment buffer + * @param[in] fragment_size: size of @fragment + * @params[in] response: optional response buffer to fill + * @params[in] response_size: size of @response + * + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, const uint8_t *fragment, + size_t fragment_size, uint8_t *response, + size_t response_size) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->set_configuration) + return 0; + + params->ext.set_conf.config_id = config_id; + params->ext.set_conf.pos = pos; + params->ext.set_conf.data_off_size = data_offset_size; + params->ext.set_conf.fragment = fragment; + params->ext.set_conf.fragment_size = fragment_size; + params->ext.set_conf.response = response; + params->ext.set_conf.response_size = response_size; + + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_SET_CONF, true); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module get_configuration() operation and return its result. + * Module get_configuration() code is performed in user workqueue. + * + * @param[in] mod - struct processing_module pointer + * @param[in] config_id - Configuration ID + * @param[in] data_offset_size: size of the whole configuration if it is the first fragment or the + * only fragment. Otherwise, it is the offset of the fragment in the whole + * configuration. + * @param[in] fragment: configuration fragment buffer + * @param[in] fragment_size: size of @fragment + * + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_get_configuration(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, + size_t fragment_size) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + struct k_mem_domain *domain = mod->user_ctx->comp_dom; + const uintptr_t ipc_resp_buf = POINTER_TO_UINT(ipc_get()->comp_data); + + /* Memory partition exposing the IPC response buffer. This buffer is allocated + * by the IPC driver and contains the payload of IPC replies sent to the host. + */ + struct k_mem_partition ipc_resp_part = { + .start = ipc_resp_buf, + .size = SOF_IPC_MSG_MAX_SIZE, + .attr = user_get_partition_attr(ipc_resp_buf) | K_MEM_PARTITION_P_RW_U_RW, + }; + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->get_configuration) + return -EIO; + + params->ext.get_conf.config_id = config_id; + params->ext.get_conf.data_off_size = data_offset_size; + params->ext.get_conf.fragment = fragment; + params->ext.get_conf.fragment_size = fragment_size; + + ret = k_mem_domain_add_partition(domain, &ipc_resp_part); + if (ret < 0) { + comp_err(mod->dev, "add response buffer to domain error: %d", ret); + return ret; + } + + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_GET_CONF, true); + + k_mem_domain_remove_partition(domain, &ipc_resp_part); + + /* Return status from module code operation. */ + return ret ? ret : params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module set_processing_mode() operation and return its result. + * Module set_processing_mode() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @param mode - processing mode to be set. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_set_processing_mode(struct processing_module *mod, + enum module_processing_mode mode) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->set_processing_mode) + return 0; + + params->ext.proc_mode.mode = mode; + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_SET_PROCMOD, false); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module get_processing_mode() operation and return its result. + * Module get_processing_mode() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @return processing mode. + */ +static +enum module_processing_mode userspace_proxy_get_processing_mode(struct processing_module *mod) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->get_processing_mode) + return -EIO; + + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_GET_PROCMOD, false); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->ext.proc_mode.mode; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module is_ready_to_process() operation and return its result. + * Module is_ready_to_process() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @return true if the module is ready to process + */ +static bool userspace_proxy_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->is_ready_to_process) + return generic_module_is_ready_to_process(mod, sources, num_of_sources, sinks, + num_of_sinks); + + params->ext.proc.sources = sources; + params->ext.proc.num_of_sources = num_of_sources; + params->ext.proc.sinks = sinks; + params->ext.proc.num_of_sinks = num_of_sinks; + + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_PROC_READY, false); + if (ret) + return generic_module_is_ready_to_process(mod, sources, num_of_sources, sinks, + num_of_sinks); + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module bind() operation and return its result. + * Module bind() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @param bind_data - pointer to bind_info structure. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_bind(struct processing_module *mod, struct bind_info *bind_data) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->bind) + return 0; + + params->ext.bind_data = bind_data; + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_BIND, false); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module unbind() operation and return its result. + * Module unbind() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @param unbind_data - pointer to bind_info structure. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_unbind(struct processing_module *mod, struct bind_info *unbind_data) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret; + + comp_dbg(mod->dev, "start"); + + if (!mod->user_ctx->interface->unbind) + return 0; + + params->ext.bind_data = unbind_data; + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_UNBIND, false); + if (ret) + return ret; + + /* Return status from module code operation. */ + return params->status; +} + +/** + * Copy parameters to user worker accessible space. + * Queue module trigger() operation and return its result. + * Module trigger() code is performed in user workqueue. + * + * @param mod - pointer to processing module structure. + * @return 0 for success, error otherwise. + */ +static int userspace_proxy_trigger(struct processing_module *mod, int cmd) +{ + struct module_params *params = user_work_get_params(mod->user_ctx); + int ret = 0; + + comp_dbg(mod->dev, "start"); + + if (mod->user_ctx->interface->trigger) { + params->ext.trigger_data = cmd; + ret = userspace_proxy_invoke(mod->user_ctx, USER_PROXY_MOD_CMD_TRIGGER, false); + if (ret) + return ret; + ret = params->status; + } + + if (!ret) + ret = module_adapter_set_state(mod, mod->dev, cmd); + + /* Return status from module code operation. */ + return ret; +} + +/* Userspace Proxy Module API */ +APP_TASK_DATA static const struct module_interface userspace_proxy_interface = { + .init = userspace_proxy_init, + .is_ready_to_process = userspace_proxy_is_ready_to_process, + .prepare = userspace_proxy_prepare, + .process = userspace_proxy_process, + .set_configuration = userspace_proxy_set_configuration, + .get_configuration = userspace_proxy_get_configuration, + .set_processing_mode = userspace_proxy_set_processing_mode, + .get_processing_mode = userspace_proxy_get_processing_mode, + .reset = userspace_proxy_reset, + .free = userspace_proxy_free, + .bind = userspace_proxy_bind, + .unbind = userspace_proxy_unbind, + .trigger = userspace_proxy_trigger, +}; diff --git a/src/audio/module_adapter/library/userspace_proxy_user.c b/src/audio/module_adapter/library/userspace_proxy_user.c new file mode 100644 index 000000000000..105c9841318f --- /dev/null +++ b/src/audio/module_adapter/library/userspace_proxy_user.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Adrian Warecki <adrian.warecki@intel.com> + +/** + * \file audio/module_adapter/library/userspace_proxy_user.c + * \brief Userspace proxy functions executed only in userspace context. + * \authors Adrian Warecki + */ + +/* Assume that all the code runs in user mode and unconditionally makes system calls. */ +#define __ZEPHYR_USER__ + +#include <sof/common.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include <sof/audio/component.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/audio/module_adapter/module/generic.h> + +#include <sof/audio/module_adapter/library/userspace_proxy.h> +#include <sof/audio/module_adapter/library/userspace_proxy_user.h> + +void userspace_proxy_handle_request(struct processing_module *mod, struct module_params *params) +{ + const struct module_interface *ops = params->context->interface; + + switch (params->cmd) { + case USER_PROXY_MOD_CMD_AGENT_START: + params->status = params->ext.agent.start_fn(¶ms->ext.agent.params, + ¶ms->ext.agent.out_interface); + break; + + case USER_PROXY_MOD_CMD_INIT: + params->status = ops->init(params->mod); + break; + + case USER_PROXY_MOD_CMD_PREPARE: + params->status = ops->prepare(params->mod, params->ext.proc.sources, + params->ext.proc.num_of_sources, + params->ext.proc.sinks, + params->ext.proc.num_of_sinks); + break; + + case USER_PROXY_MOD_CMD_PROC_READY: + params->status = ops->is_ready_to_process(params->mod, + params->ext.proc.sources, + params->ext.proc.num_of_sources, + params->ext.proc.sinks, + params->ext.proc.num_of_sinks); + break; + + case USER_PROXY_MOD_CMD_BIND: + params->status = ops->bind(params->mod, params->ext.bind_data); + break; + + case USER_PROXY_MOD_CMD_UNBIND: + params->status = ops->unbind(params->mod, params->ext.bind_data); + break; + + case USER_PROXY_MOD_CMD_RESET: + params->status = ops->reset(params->mod); + break; + + case USER_PROXY_MOD_CMD_FREE: + params->status = ops->free(params->mod); + break; + + case USER_PROXY_MOD_CMD_SET_CONF: + params->status = ops->set_configuration(params->mod, + params->ext.set_conf.config_id, + params->ext.set_conf.pos, + params->ext.set_conf.data_off_size, + params->ext.set_conf.fragment, + params->ext.set_conf.fragment_size, + params->ext.set_conf.response, + params->ext.set_conf.response_size); + break; + + case USER_PROXY_MOD_CMD_GET_CONF: + params->status = ops->get_configuration(params->mod, + params->ext.get_conf.config_id, + params->ext.get_conf.data_off_size, + params->ext.get_conf.fragment, + params->ext.get_conf.fragment_size); + break; + + case USER_PROXY_MOD_CMD_SET_PROCMOD: + params->status = ops->set_processing_mode(params->mod, + params->ext.proc_mode.mode); + break; + + case USER_PROXY_MOD_CMD_GET_PROCMOD: + params->ext.proc_mode.mode = ops->get_processing_mode(params->mod); + break; + + case USER_PROXY_MOD_CMD_TRIGGER: + params->status = ops->trigger(params->mod, params->ext.trigger_data); + break; + + default: + params->status = -EINVAL; + break; + } +} + +void userspace_proxy_worker_handler(struct k_work_user *work_item) +{ + struct user_work_item *user_work_item = CONTAINER_OF(work_item, struct user_work_item, + work_item); + struct module_params *params = &user_work_item->params; + + userspace_proxy_handle_request(params->mod, params); + k_event_post(user_work_item->event, DP_TASK_EVENT_IPC_DONE); +} diff --git a/src/audio/module_adapter/module/README.md b/src/audio/module_adapter/module/README.md new file mode 100644 index 000000000000..4586f060f37d --- /dev/null +++ b/src/audio/module_adapter/module/README.md @@ -0,0 +1,88 @@ +# Module Implementing Interfaces (`module_adapter/module`) + +The `module` directory contains the concrete `module_interface` implementations that bridge the core SOF Component API with various audio processing algorithms. These adapters translate the generic initialization, parameter configuration, and process loop calls into the specific operational sequences required by different module frameworks. + +The directory primarily houses three distinct module adapters: + +1. **Generic Core Adapter (`generic.c`)** +2. **Modules (IADK/Shim) Adapter (`modules.c`)** +3. **Cadence DSP Codec Adapter (`cadence.c`, `cadence_ipc4.c`)** + +## 1. Generic Core Adapter (`generic.c`) + +The Generic adapter provides the default runtime container for typical native SOF processing modules (e.g., volume, eq, src). + +It implements the full `struct module_interface` contract: + +* **Memory Management**: It intercepts memory allocation mappings using `mod_balloc_align` and tracks memory requests in a module-specific resource pool (`module_resource`). When the module goes out of scope, the framework garbage-collects any leaked allocations automatically via `mod_free_all()`. +* **Configuration Handling**: Manages large blob configuration messages across multiple IPC fragments (`module_set_configuration`). It allocates memory for `runtime_params` until the blob is fully assembled, then triggers the underlying algorithm with the completed struct. +* **State Machine Enforcement**: It wraps `process_audio_stream` and `process_raw_data` calls to verify the module is in either `MODULE_IDLE` or `MODULE_PROCESSING` states before execution. + +## 2. Modules (IADK Shim) Adapter (`modules.c`) + +The `modules.c` base is an extension adapter designed specifically to run Intel Audio Development Kit (IADK) 3rd party algorithms. + +Unlike the generic modules, the IADK modules are object-oriented C++ architectures linked into a separate library (`module_adapter/iadk`). This file acts as the primary C entry point wrapper. + +* It utilizes the `iadk_wrapper_*` C-bridge functions to invoke methods on the C++ `intel_adsp::ProcessingModuleInterface` classes. +* It exposes the standard `DECLARE_MODULE_ADAPTER(processing_module_adapter_interface)` that is bound to the SOF pipeline. + +## 3. Cadence Codec Adapter (`cadence.c`) + +This is a highly specialized adapter used for integrating Xtensa Audio (XA) codecs from Cadence (e.g., MP3, AAC, Vorbis, SBC, DAB). + +The `cadence.c` implementation maps the standard SOF pipeline controls into the Cadence memory buffer management and synchronous execution models. + +```mermaid +graph TD + subgraph SOF Initialization + INIT["cadence_codec_init"] + CONFIG["cadence_configure_codec_params"] + RESOLVE["cadence_codec_resolve_api"] + end + + subgraph Cadence Library Init XA API + MEMTABS["cadence_codec_init_memory_tables"] + GETSIZE["XA_API_CMD_GET_MEM_INFO_SIZE"] + SETPTR["XA_API_CMD_SET_MEM_PTR"] + end + + subgraph Data Processing Loop + PROC["cadence_codec_process_data"] + FILL["XA_API_CMD_SET_INPUT_BYTES"] + EXEC["XA_API_CMD_EXECUTE"] + GETOUT["XA_API_CMD_GET_OUTPUT_BYTES"] + end + + INIT --> RESOLVE + RESOLVE --> CONFIG + CONFIG --> MEMTABS + + MEMTABS -. Iterates Memory Types .-> GETSIZE + GETSIZE -. Assigns Buffers .-> SETPTR + + SETPTR ==>|Pipeline Trigger| PROC + + PROC --> FILL + FILL --> EXEC + EXEC --> GETOUT +``` + +### Cadence Memory Tables + +Unlike standard modules that directly read from a `sof_source` API, Cadence codecs require their memory isolated exclusively into exact predefined chunks categorized by "type". `cadence_codec_init_memory_tables` iterates through the codec's hardware definition to construct these memory areas: + +* `XA_MEMTYPE_INPUT` +* `XA_MEMTYPE_OUTPUT` +* `XA_MEMTYPE_SCRATCH` +* `XA_MEMTYPE_PERSIST` + +The SOF adapter allocates tracking structures via `mod_alloc_align` for each of these mandatory regions prior to audio playback. + +### Execution Wrapper + +During `cadence_codec_process()`, the adapter: + +1. Performs `source_get_data` and mechanically copies audio bytes into the isolated `XA_MEMTYPE_INPUT` buffer. +2. Invokes the Xtensa Audio codec API (`XA_API_CMD_EXECUTE`). +3. Reads the produced byte count and copies them back out from `XA_MEMTYPE_OUTPUT` into the `sof_sink`. diff --git a/src/audio/module_adapter/module/cadence.c b/src/audio/module_adapter/module/cadence.c new file mode 100644 index 000000000000..78a9c68b8afa --- /dev/null +++ b/src/audio/module_adapter/module/cadence.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 - 2026 Intel Corporation. All rights reserved. +// + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/cadence.h> +#include <ipc/compress_params.h> +#include <rtos/init.h> + +LOG_MODULE_REGISTER(cadence_codec, CONFIG_SOF_LOG_LEVEL); + +/*****************************************************************************/ +/* Cadence API functions array */ +/*****************************************************************************/ +struct cadence_api cadence_api_table[] = { +#ifdef CONFIG_CADENCE_CODEC_WRAPPER + { + .id = CADENCE_CODEC_WRAPPER_ID, + .api = cadence_api_function + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_AAC_DEC + { + .id = CADENCE_CODEC_AAC_DEC_ID, + .api = xa_aac_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_BSAC_DEC + { + .id = CADENCE_CODEC_BSAC_DEC_ID, + .api = xa_bsac_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_DAB_DEC + { + .id = CADENCE_CODEC_DAB_DEC_ID, + .api = xa_dabplus_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_DRM_DEC + { + .id = CADENCE_CODEC_DRM_DEC_ID, + .api = xa_drm_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_MP3_DEC + { + .id = CADENCE_CODEC_MP3_DEC_ID, + .api = xa_mp3_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_MP3_ENC + { + .id = CADENCE_CODEC_MP3_ENC_ID, + .api = xa_mp3_enc, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_SBC_DEC + { + .id = CADENCE_CODEC_SBC_DEC_ID, + .api = xa_sbc_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_VORBIS_DEC + { + .id = CADENCE_CODEC_VORBIS_DEC_ID, + .api = xa_vorbis_dec, + }, +#endif +#ifdef CONFIG_CADENCE_CODEC_SRC_PP + { + .id = CADENCE_CODEC_SRC_PP_ID, + .api = xa_src_pp, + }, +#endif +}; + +static int cadence_codec_get_api_id(uint32_t compress_id, uint32_t direction) +{ + /* convert compress id to SOF cadence SOF id */ + switch (compress_id) { + case SND_AUDIOCODEC_MP3: + if (direction == SOF_IPC_STREAM_PLAYBACK) + return CADENCE_CODEC_MP3_DEC_ID; + + return CADENCE_CODEC_MP3_ENC_ID; + case SND_AUDIOCODEC_AAC: + return CADENCE_CODEC_AAC_DEC_ID; + case SND_AUDIOCODEC_VORBIS: + return CADENCE_CODEC_VORBIS_DEC_ID; + default: + return -EINVAL; + } +} + +void cadence_codec_free_memory_tables(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + int i; + + if (cd->mem_to_be_freed) + for (i = 0; i < cd->mem_to_be_freed_len; i++) + mod_free(mod, cd->mem_to_be_freed[i]); + + mod_free(mod, cd->mem_to_be_freed); + cd->mem_to_be_freed = NULL; + cd->mem_to_be_freed_len = 0; +} + +int cadence_codec_init_memory_tables(struct processing_module *mod) +{ + int ret, no_mem_tables, i, mem_type, mem_size, mem_alignment; + void *ptr, *scratch, *persistent; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct cadence_codec_data *cd = codec->private; + + scratch = NULL; + persistent = NULL; + + /* Calculate the size of all memory blocks required */ + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, + NULL, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to calculate memory blocks size", + ret); + return ret; + } + + /* Get number of memory tables */ + API_CALL(cd, XA_API_CMD_GET_N_MEMTABS, 0, &no_mem_tables, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to get number of memory tables", + ret); + return ret; + } + + cd->mem_to_be_freed = mod_zalloc(mod, no_mem_tables * sizeof(*cd->mem_to_be_freed)); + if (!cd->mem_to_be_freed) + return -ENOMEM; + cd->mem_to_be_freed_len = no_mem_tables; + + /* Initialize each memory table */ + for (i = 0; i < no_mem_tables; i++) { + /* Get type of memory - it specifies how the memory will be used */ + API_CALL(cd, XA_API_CMD_GET_MEM_INFO_TYPE, i, &mem_type, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to get mem. type info of id %d out of %d", + ret, i, no_mem_tables); + goto err; + } + /* Get size of memory needed for memory allocation for this + * particular memory type. + */ + API_CALL(cd, XA_API_CMD_GET_MEM_INFO_SIZE, i, &mem_size, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to get mem. size for mem. type %d", + ret, mem_type); + goto err; + } + /* Get alignment constrains */ + API_CALL(cd, XA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &mem_alignment, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to get mem. alignment of mem. type %d", + ret, mem_type); + goto err; + } + /* Allocate memory for this type, taking alignment into account */ + ptr = mod_alloc_align(mod, mem_size, mem_alignment); + if (!ptr) { + comp_err(dev, "error %x: failed to allocate memory for %d", + ret, mem_type); + ret = -EINVAL; + goto err; + } + cd->mem_to_be_freed[i] = ptr; + /* Finally, provide this memory for codec */ + API_CALL(cd, XA_API_CMD_SET_MEM_PTR, i, ptr, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to set memory pointer for %d", + ret, mem_type); + goto err; + } + + switch ((unsigned int)mem_type) { + case XA_MEMTYPE_SCRATCH: + scratch = ptr; + break; + case XA_MEMTYPE_PERSIST: + persistent = ptr; + break; + case XA_MEMTYPE_INPUT: + codec->mpd.in_buff = ptr; + codec->mpd.in_buff_size = mem_size; + break; + case XA_MEMTYPE_OUTPUT: + codec->mpd.out_buff = ptr; + codec->mpd.out_buff_size = mem_size; + break; + default: + comp_err(dev, "error %x: unrecognized memory type!", + mem_type); + ret = -EINVAL; + goto err; + } + + comp_dbg(dev, "allocated memory of %d bytes and alignment %d for mem. type %d", + mem_size, mem_alignment, mem_type); + } + + return 0; +err: + cadence_codec_free_memory_tables(mod); + + return ret; +} + +size_t cadence_api_table_size(void) +{ + return ARRAY_SIZE(cadence_api_table); +} + +int cadence_codec_get_samples(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "start"); + + switch (cd->api_id) { + case CADENCE_CODEC_WRAPPER_ID: + return 0; + case CADENCE_CODEC_MP3_DEC_ID: + /* MPEG-1 Layer 3 */ + return 1152; + case CADENCE_CODEC_AAC_DEC_ID: + return 1024; + default: + break; + } + + return 0; +} + +int cadence_codec_init_process(struct processing_module *mod) +{ + int ret; + struct module_data *codec = &mod->priv; + struct cadence_codec_data *cd = codec->private; + struct comp_dev *dev = mod->dev; + + codec->mpd.eos_reached = false; + codec->mpd.eos_notification_sent = false; + + API_CALL(cd, XA_API_CMD_SET_INPUT_BYTES, 0, &codec->mpd.avail, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to set size of input data", + ret); + return ret; + } + + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_PROCESS, NULL, ret); + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "error %x: failed to initialize codec", + ret); + return ret; + } else if (ret != LIB_NO_ERROR) { + /* for SOF with native Zephyr, the first chunk of data will be + * 0s since data is first transferred from host to the next + * component and **then** from Linux to host. Because of this, the + * above API call will return `...NONFATAL_NEXT_SYNC_NOT_FOUND` + * since the API seems to expect useful data in the first chunk. + * To avoid this, print a warning if the above call returns + * a non-fatal error and let the init process continue. Next + * chunk will contain the useful data. + */ + comp_warn(dev, "returned non-fatal error: 0x%x", + ret); + } + + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_DONE_QUERY, + &codec->mpd.init_done, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to get lib init status", + ret); + return ret; + } + + API_CALL(cd, XA_API_CMD_GET_CURIDX_INPUT_BUF, 0, &codec->mpd.consumed, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: could not get consumed bytes", + ret); + return ret; + } + + return 0; +} + +int cadence_codec_free(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + + mod_free(mod, cd->setup_cfg.data); + + cadence_codec_free_memory_tables(mod); + mod_free(mod, cd->mem_tabs); + + mod_free(mod, cd->self); + mod_free(mod, cd); + return 0; +} + +int cadence_codec_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, const uint8_t *fragment, + size_t fragment_size, uint8_t *response, size_t response_size) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + int ret; + + ret = module_set_configuration(mod, config_id, pos, data_offset_size, fragment, + fragment_size, response, response_size); + if (ret < 0) + return ret; + + /* return if more fragments are expected or if the module is not prepared */ + if ((pos != MODULE_CFG_FRAGMENT_LAST && pos != MODULE_CFG_FRAGMENT_SINGLE) || + md->state < MODULE_IDLE) + return 0; + + /* whole configuration received, apply it now */ + ret = cadence_codec_apply_config(mod); + if (ret) { + comp_err(dev, "runtime config apply failed with error %x: ", ret); + return ret; + } + + comp_dbg(dev, "config applied"); + + return 0; +} + +int cadence_codec_apply_params(struct processing_module *mod, int size, void *data) +{ + struct module_data *codec = &mod->priv; + struct comp_dev *dev = mod->dev; + struct cadence_codec_data *cd = codec->private; + struct module_param *param; + uint16_t param_id; + uint16_t codec_id; + int ret; + + /* Read parameters stored in `data` - it may keep plenty of + * parameters. The `size` variable is equal to param->size * count, + * where count is number of parameters stored in `data`. + */ + while (size > 0) { + param = data; + comp_dbg(dev, "cadence_codec_apply_config() applying param %d value %d", + param->id, param->data[0]); + + param_id = param->id & 0xFF; + codec_id = param->id >> 16; + + /* if the parameter is not for current codec skip it! */ + if (codec_id && codec_id != cd->api_id) { + /* Obtain next parameter */ + data = (char *)data + param->size; + size -= param->size; + continue; + } + + /* Set read parameter */ + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, param_id, + param->data, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply parameter: %d value: %d error: %#x", + param->id, *(int32_t *)param->data, ret); + + return ret; + } + comp_warn(dev, "applied parameter %d value %d with return code: %#x", + param->id, *(int32_t *)param->data, ret); + } + /* Obtain next parameter, it starts right after the preceding one */ + data = (char *)data + param->size; + size -= param->size; + } + + return 0; +} + +int cadence_init_codec_object(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct cadence_codec_data *cd = module_get_private_data(mod); + uint32_t obj_size; + + ret = cadence_codec_resolve_api(mod); + if (ret < 0) + return ret; + + /* Obtain codec name */ + API_CALL(cd, XA_API_CMD_GET_LIB_ID_STRINGS, + XA_CMD_TYPE_LIB_NAME, cd->name, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "failed to get lib name error: %x: ", ret); + return ret; + } + /* Get codec object size */ + API_CALL(cd, XA_API_CMD_GET_API_SIZE, 0, &obj_size, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "failed to get lib object size error %x:", ret); + return ret; + } + /* Allocate space for codec object */ + cd->self = mod_balloc(mod, obj_size); + if (!cd->self) { + comp_err(dev, "failed to allocate space for lib object"); + return -ENOMEM; + } + + comp_dbg(dev, "allocated %d bytes for lib object", obj_size); + + /* Set all params to their default values */ + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, + NULL, ret); + if (ret != LIB_NO_ERROR) { + mod_free(mod, cd->self); + return ret; + } + + return 0; +} + +int cadence_codec_resolve_api_with_id(struct processing_module *mod, uint32_t codec_id, + uint32_t direction) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint32_t api_id; + uint32_t n_apis = cadence_api_table_size(); + xa_codec_func_t *api = NULL; + int i; + + api_id = cadence_codec_get_api_id(codec_id, direction); + if (api_id < 0) + return api_id; + + /* Find and assign API function */ + for (i = 0; i < n_apis; i++) { + if (cadence_api_table[i].id == api_id) { + api = cadence_api_table[i].api; + break; + } + } + + /* Verify API assignment */ + if (!api) { + comp_err(dev, "could not find API function for id %x", + api_id); + return -EINVAL; + } + cd->api = api; + cd->api_id = api_id; + + return 0; +} + +static void cadence_store_api_error_code(struct comp_dev *dev, + XA_ERRORCODE *api_error_code, + int ret, const char *cmd_name) +{ + if (!api_error_code) + return; + + if (*api_error_code && *api_error_code != ret) + comp_dbg(dev, "overwriting api error code at %s: old %#x new %#x", + cmd_name, *api_error_code, ret); + + *api_error_code = ret; +} + +int cadence_codec_process_data(struct processing_module *mod, + XA_ERRORCODE *api_error_code) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct module_data *codec = &mod->priv; + struct comp_dev *dev = mod->dev; + uint32_t done = 0; + int ret; + + if (api_error_code) + *api_error_code = 0; + + if (codec->mpd.eos_reached) { + codec->mpd.produced = 0; + codec->mpd.consumed = 0; + + return 0; + } + + if (dev->pipeline->expect_eos) { + /* Signal that the stream is expected to end anytime soon */ + API_CALL(cd, XA_API_CMD_INPUT_OVER, 0, NULL, ret); + if (ret != LIB_NO_ERROR) { + if (api_error_code) + *api_error_code = ret; + + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "input_over failed with error: %x", ret); + return ret; + } + } + } + + API_CALL(cd, XA_API_CMD_SET_INPUT_BYTES, 0, &codec->mpd.avail, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "failed to set size of input data with error: %x:", ret); + return ret; + } + + API_CALL(cd, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DO_EXECUTE, NULL, ret); + if (ret != LIB_NO_ERROR) { + cadence_store_api_error_code(dev, api_error_code, ret, + "XA_API_CMD_EXECUTE_DO_EXECUTE"); + + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "processing failed with error: %x", ret); + return ret; + } + } + + API_CALL(cd, XA_API_CMD_EXECUTE, XA_CMD_TYPE_DONE_QUERY, &done, ret); + if (ret != LIB_NO_ERROR) { + cadence_store_api_error_code(dev, api_error_code, ret, + "XA_API_CMD_EXECUTE_DONE_QUERY"); + + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "done query failed with error: %x", ret); + return ret; + } + } + + API_CALL(cd, XA_API_CMD_GET_OUTPUT_BYTES, 0, &codec->mpd.produced, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "could not get produced bytes, error %x:", + ret); + return ret; + } + + API_CALL(cd, XA_API_CMD_GET_CURIDX_INPUT_BUF, 0, &codec->mpd.consumed, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "could not get consumed bytes, error: %x", ret); + return ret; + } + + if (dev->pipeline->expect_eos) { + /* + * AAC decoder cannot signal DONE, check if it stopped + * producing data when EOS is expected + */ + if (cd->api_id == CADENCE_CODEC_AAC_DEC_ID && !codec->mpd.produced) + done = true; + + if (done) + codec->mpd.eos_reached = true; + } + + return 0; +} diff --git a/src/audio/module_adapter/module/cadence.toml b/src/audio/module_adapter/module/cadence.toml new file mode 100644 index 000000000000..4c0466196577 --- /dev/null +++ b/src/audio/module_adapter/module/cadence.toml @@ -0,0 +1,22 @@ + REM # Cadence module config + [[module.entry]] + name = "CADENCE" + uuid = UUIDREG_STR_CADENCE_CODEC + affinity_mask = "0x3" + instance_count = "1" + domain_types = "0" + load_type = "0" + init_config = "1" + module_type = "31" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/module_adapter/module/cadence_ipc3.c b/src/audio/module_adapter/module/cadence_ipc3.c new file mode 100644 index 000000000000..d1711e79f800 --- /dev/null +++ b/src/audio/module_adapter/module/cadence_ipc3.c @@ -0,0 +1,317 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + +/* + * \file cadence.c + * \brief Cadence Codec API + * \author Marcin Rajwa <marcin.rajwa@linux.intel.com> + * + */ + +#include <ipc/compress_params.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/cadence.h> +#include <rtos/init.h> + +SOF_DEFINE_REG_UUID(cadence_codec); +LOG_MODULE_DECLARE(cadence_codec, CONFIG_SOF_LOG_LEVEL); +DECLARE_TR_CTX(cadence_codec_tr, SOF_UUID(cadence_codec_uuid), LOG_LEVEL_INFO); + +int cadence_codec_resolve_api(struct processing_module *mod) +{ + int ret; + struct snd_codec codec_params; + uint32_t codec_id = DEFAULT_CODEC_ID; + + if (mod->stream_params->ext_data_length) { + ret = memcpy_s(&codec_params, mod->stream_params->ext_data_length, + (uint8_t *)mod->stream_params + sizeof(*mod->stream_params), + mod->stream_params->ext_data_length); + if (ret < 0) + return ret; + + codec_id = codec_params.id; + } + + /* IPC3 only supports playback */ + return cadence_codec_resolve_api_with_id(mod, codec_id, mod->stream_params->direction); +} + +static int cadence_codec_init(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + struct cadence_codec_data *cd; + struct comp_dev *dev = mod->dev; + struct module_config *setup_cfg; + int ret; + + comp_dbg(dev, "cadence_codec_init() start"); + + cd = mod_zalloc(mod, sizeof(struct cadence_codec_data)); + if (!cd) { + comp_err(dev, "failed to allocate memory for cadence codec data"); + return -ENOMEM; + } + + codec->private = cd; + codec->mpd.init_done = 0; + + /* copy the setup config only for the first init */ + if (codec->state == MODULE_DISABLED && codec->cfg.avail) { + setup_cfg = &cd->setup_cfg; + + /* allocate memory for set up config */ + setup_cfg->data = mod_alloc(mod, codec->cfg.size); + if (!setup_cfg->data) { + comp_err(dev, "failed to alloc setup config"); + ret = -ENOMEM; + goto free; + } + + /* copy the setup config */ + setup_cfg->size = codec->cfg.size; + ret = memcpy_s(setup_cfg->data, setup_cfg->size, + codec->cfg.init_data, setup_cfg->size); + if (ret) { + comp_err(dev, "failed to copy setup config %d", ret); + goto free_cfg; + } + setup_cfg->avail = true; + } + + comp_dbg(dev, "cadence_codec_init() done"); + + return 0; + +free_cfg: + mod_free(mod, setup_cfg->data); +free: + mod_free(mod, cd); + return ret; +} + +int cadence_codec_apply_config(struct processing_module *mod) +{ + int size; + struct module_config *cfg; + void *data; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct cadence_codec_data *cd = codec->private; + + comp_dbg(dev, "cadence_codec_apply_config() start"); + + cfg = &codec->cfg; + + /* use setup config if no runtime config available. This will be true during reset */ + if (!cfg->avail) + cfg = &cd->setup_cfg; + + data = cfg->data; + size = cfg->size; + + if (!cfg->avail || !size) { + comp_err(dev, "cadence_codec_apply_config() error: no config available"); + return -EIO; + } + + return cadence_codec_apply_params(mod, size, data); +} + +static int cadence_codec_deep_buff_allowed(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + + switch (cd->api_id) { + case CADENCE_CODEC_MP3_ENC_ID: + return 0; + default: + return 1; + } +} + +static int cadence_codec_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + int ret = 0, mem_tabs_size; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct cadence_codec_data *cd = codec->private; + + comp_dbg(dev, "cadence_codec_prepare() start"); + + ret = cadence_init_codec_object(mod); + if (ret) + return ret; + + ret = cadence_codec_apply_config(mod); + if (ret) { + comp_err(dev, "cadence_codec_prepare() error %x: failed to apply config", + ret); + return ret; + } + + /* Allocate memory for the codec */ + API_CALL(cd, XA_API_CMD_GET_MEMTABS_SIZE, 0, &mem_tabs_size, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "cadence_codec_prepare() error %x: failed to get memtabs size", + ret); + return ret; + } + + cd->mem_tabs = mod_alloc(mod, mem_tabs_size); + if (!cd->mem_tabs) { + comp_err(dev, "cadence_codec_prepare() error: failed to allocate space for memtabs"); + return -ENOMEM; + } + + comp_dbg(dev, "allocated %d bytes for memtabs", mem_tabs_size); + + API_CALL(cd, XA_API_CMD_SET_MEMTABS_PTR, 0, cd->mem_tabs, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "cadence_codec_prepare() error %x: failed to set memtabs", + ret); + goto free; + } + + ret = cadence_codec_init_memory_tables(mod); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "cadence_codec_prepare() error %x: failed to init memory tables", + ret); + goto free; + } + /* Check init done status. Note, it may happen that init_done flag will return + * false value, this is normal since some codec variants needs input in order to + * fully finish initialization. That's why at codec_adapter_copy() we call + * codec_init_process() base on result obtained below. + */ +#ifdef CONFIG_CADENCE_CODEC_WRAPPER + /* TODO: remove the "#ifdef CONFIG_CADENCE_CODEC_WRAPPER" once cadence fixes the bug + * in the init/prepare sequence. Basically below API_CALL shall return 1 for + * PCM streams and 0 for compress ones. As it turns out currently it returns 1 + * in both cases so in turn compress stream won't finish its prepare during first copy + * in codec_adapter_copy(). + */ + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_DONE_QUERY, + &codec->mpd.init_done, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "cadence_codec_init_process() error %x: failed to get lib init status", + ret); + return ret; + } +#endif + comp_dbg(dev, "cadence_codec_prepare() done"); + return 0; +free: + mod_free(mod, cd->mem_tabs); + return ret; +} + +static int +cadence_codec_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 comp_buffer *local_buff; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + 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; + int ret; + + if (!cadence_codec_deep_buff_allowed(mod)) + mod->deep_buff_bytes = 0; + + /* Proceed only if we have enough data to fill the module buffer completely */ + if (input_buffers[0].size < codec->mpd.in_buff_size) { + comp_dbg(dev, "not enough data to process"); + return -ENODATA; + } + + if (!codec->mpd.init_done) { + memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, input_buffers[0].data, + codec->mpd.in_buff_size); + codec->mpd.avail = codec->mpd.in_buff_size; + + ret = cadence_codec_init_process(mod); + if (ret) + return ret; + + remaining -= codec->mpd.consumed; + input_buffers[0].consumed = codec->mpd.consumed; + } + + /* do not proceed with processing if not enough free space left in the local buffer */ + local_buff = list_first_item(&mod->raw_data_buffers_list, struct comp_buffer, buffers_list); + free_bytes = audio_stream_get_free(&local_buff->stream); + if (free_bytes < output_bytes) + return -ENOSPC; + + /* Proceed only if we have enough data to fill the module buffer completely */ + if (remaining < codec->mpd.in_buff_size) + return -ENODATA; + + memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, + (uint8_t *)input_buffers[0].data + input_buffers[0].consumed, + codec->mpd.in_buff_size); + codec->mpd.avail = codec->mpd.in_buff_size; + + comp_dbg(dev, "cadence_codec_process() start"); + + ret = cadence_codec_process_data(mod, NULL); + if (ret) + return ret; + + /* update consumed with the number of samples consumed during init */ + input_buffers[0].consumed += codec->mpd.consumed; + codec->mpd.consumed = input_buffers[0].consumed; + + /* copy the produced samples into the output buffer */ + memcpy_s(output_buffers[0].data, codec->mpd.produced, codec->mpd.out_buff, + codec->mpd.produced); + output_buffers[0].size = codec->mpd.produced; + + comp_dbg(dev, "cadence_codec_process() done"); + + return 0; +} + +static int cadence_codec_reset(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + struct cadence_codec_data *cd = codec->private; + int ret; + + cadence_codec_free_memory_tables(mod); + mod_free(mod, cd->mem_tabs); + + /* reset to default params */ + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, NULL, ret); + if (ret != LIB_NO_ERROR) + return ret; + + codec->mpd.init_done = 0; + + mod_free(mod, cd->self); + cd->self = NULL; + + return ret; +} + +static const struct module_interface cadence_codec_interface = { + .init = cadence_codec_init, + .prepare = cadence_codec_prepare, + .process_raw_data = cadence_codec_process, + .set_configuration = cadence_codec_set_configuration, + .reset = cadence_codec_reset, + .free = cadence_codec_free +}; + +DECLARE_MODULE_ADAPTER(cadence_codec_interface, cadence_codec_uuid, cadence_codec_tr); +SOF_MODULE_INIT(cadence_codec, sys_comp_module_cadence_codec_interface_init); diff --git a/src/audio/module_adapter/module/cadence_ipc4.c b/src/audio/module_adapter/module/cadence_ipc4.c new file mode 100644 index 000000000000..9621d8ab0f1d --- /dev/null +++ b/src/audio/module_adapter/module/cadence_ipc4.c @@ -0,0 +1,582 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025-2026 Intel Corporation. All rights reserved. +// + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/cadence.h> +#include <sof/audio/cadence/mp3_dec/xa_mp3_dec_api.h> +#include <sof/audio/cadence/mp3_enc/xa_mp3_enc_api.h> +#include <sof/audio/cadence/aac_dec/xa_aac_dec_api.h> +#include <sof/ipc/msg.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <ipc/compress_params.h> +#include <ipc4/notification.h> +#include <rtos/init.h> + +SOF_DEFINE_REG_UUID(cadence_codec); +LOG_MODULE_DECLARE(cadence_codec, CONFIG_SOF_LOG_LEVEL); +DECLARE_TR_CTX(cadence_codec_tr, SOF_UUID(cadence_codec_uuid), LOG_LEVEL_INFO); + +int cadence_codec_resolve_api(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct module_config *setup_cfg = &cd->setup_cfg; + struct snd_codec *codec_params; + uint32_t codec_id = DEFAULT_CODEC_ID; + + /* update codec_id if setup_cfg is available */ + if (setup_cfg->avail) { + codec_params = (struct snd_codec *)cd->setup_cfg.data; + codec_id = codec_params->id; + } + + return cadence_codec_resolve_api_with_id(mod, codec_id, cd->direction); +} + +static int cadence_configure_mp3_dec_params(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int word_size; + int ret; + + /* Cadence module only supports 16bit or 24 bits for word size */ + switch (cd->base_cfg.audio_fmt.depth) { + case IPC4_DEPTH_16BIT: + word_size = 16; + break; + case IPC4_DEPTH_24BIT: + case IPC4_DEPTH_32BIT: + word_size = 24; + break; + default: + comp_err(dev, "Unsupported bit depth: %d", cd->base_cfg.audio_fmt.depth); + return -EINVAL; + } + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_MP3DEC_CONFIG_PARAM_PCM_WDSZ, + (void *)&word_size, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config param word size: error: %#x", ret); + return ret; + } + comp_warn(dev, "applied param word size return code: %#x", ret); + } + + return 0; +} + +static int cadence_configure_mp3_enc_params(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int word_size = 16; + int ret; + + /* + * Cadence encoder only supports 16-bit word size. Make sure the topology is set up + * correctly + */ + switch (cd->base_cfg.audio_fmt.depth) { + case IPC4_DEPTH_24BIT: + case IPC4_DEPTH_32BIT: + comp_err(dev, "Unsupported bit depth: %d for MP3 encoder", + cd->base_cfg.audio_fmt.depth); + return -EINVAL; + default: + break; + } + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_MP3ENC_CONFIG_PARAM_PCM_WDSZ, + (void *)&word_size, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config param word size: error: %#x", ret); + return ret; + } + comp_warn(dev, "applied param word size return code: %#x", ret); + } + + int num_channels = cd->base_cfg.audio_fmt.channels_count; + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_MP3ENC_CONFIG_PARAM_NUM_CHANNELS, + (void *)&num_channels, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config num_channels: error: %#x", ret); + return ret; + } + } + + int sampling_freq = cd->base_cfg.audio_fmt.sampling_frequency; + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_MP3ENC_CONFIG_PARAM_SAMP_FREQ, + (void *)&sampling_freq, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config sampling_frequency: error: %#x", ret); + return ret; + } + } + + int bitrate = CADENCE_MP3_ENCODER_DEFAULT_BITRATE; + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_MP3ENC_CONFIG_PARAM_BITRATE, + (void *)&bitrate, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config bitrate: error: %#x", ret); + return ret; + } + } + + return 0; +} + +static int cadence_configure_aac_dec_params(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + struct module_config *setup_cfg = &cd->setup_cfg; + struct comp_dev *dev = mod->dev; + struct snd_codec *codec_params; + int bitstream_format = XA_AACDEC_EBITSTREAM_TYPE_AAC_ADTS; + int word_size; + int ret; + + /* check bitstream format. Only MPEG-4 ADTS supported for now */ + if (setup_cfg->avail) { + codec_params = (struct snd_codec *)cd->setup_cfg.data; + if (codec_params->format != SND_AUDIOSTREAMFORMAT_MP4ADTS) { + comp_err(dev, "Unsupported AAC format: %d", codec_params->format); + return -EINVAL; + } + } else { + comp_err(dev, "No setup config available for AAC decoder"); + return -EINVAL; + } + + /* AAC decoder module only supports 16bit or 24 bits for word size */ + switch (cd->base_cfg.audio_fmt.depth) { + case IPC4_DEPTH_16BIT: + word_size = 16; + break; + case IPC4_DEPTH_24BIT: + case IPC4_DEPTH_32BIT: + word_size = 24; + break; + default: + comp_err(dev, "Unsupported bit depth: %d", cd->base_cfg.audio_fmt.depth); + return -EINVAL; + } + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_AACDEC_CONFIG_PARAM_PCM_WDSZ, + (void *)&word_size, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config param word size: error: %#x", ret); + return ret; + } + comp_warn(dev, "applied param word size return code: %#x", ret); + } + + API_CALL(cd, XA_API_CMD_SET_CONFIG_PARAM, XA_AACDEC_CONFIG_PARAM_EXTERNALBSFORMAT, + (void *)&bitstream_format, ret); + if (ret != LIB_NO_ERROR) { + if (LIB_IS_FATAL_ERROR(ret)) { + comp_err(dev, "failed to apply config param bitstream format: error: %#x", + ret); + return ret; + } + comp_warn(dev, "applied param bitstream format return code: %#x", ret); + } + + return 0; +} + +static int cadence_configure_codec_params(struct processing_module *mod) +{ + struct cadence_codec_data *cd = module_get_private_data(mod); + + switch (cd->api_id) { + case CADENCE_CODEC_MP3_DEC_ID: + return cadence_configure_mp3_dec_params(mod); + case CADENCE_CODEC_MP3_ENC_ID: + return cadence_configure_mp3_enc_params(mod); + case CADENCE_CODEC_AAC_DEC_ID: + return cadence_configure_aac_dec_params(mod); + case CADENCE_CODEC_VORBIS_DEC_ID: + /* No configuration needed for Vorbis */ + return 0; + default: + break; + } + + comp_err(mod->dev, "Unsupported codec API ID: %u", cd->api_id); + return -EINVAL; +} + +static int cadence_codec_init(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + struct module_config *cfg = &codec->cfg; + struct module_ext_init_data *ext_data = cfg->ext_data; + struct module_config *setup_cfg = NULL; + struct cadence_codec_data *cd; + struct comp_dev *dev = mod->dev; + int mem_tabs_size; + int ret; + + comp_dbg(dev, "cadence_codec_init() start"); + + cd = mod_zalloc(mod, sizeof(struct cadence_codec_data)); + if (!cd) { + comp_err(dev, "failed to allocate memory for cadence codec data"); + return -ENOMEM; + } + + codec->private = cd; + memcpy_s(&cd->base_cfg, sizeof(cd->base_cfg), &cfg->base_cfg, sizeof(cd->base_cfg)); + + codec->mpd.init_done = 0; + + /* copy the setup config only for the first init */ + if (codec->state == MODULE_DISABLED && ext_data->module_data_size > 0) { + int size = ext_data->module_data_size; + uint8_t *init_bytes; + + setup_cfg = &cd->setup_cfg; + + /* allocate memory for set up config (codec params) */ + setup_cfg->data = mod_alloc(mod, size); + if (!setup_cfg->data) { + comp_err(dev, "failed to alloc setup config"); + ret = -ENOMEM; + goto free_cd; + } + + setup_cfg->size = size; + ret = memcpy_s(setup_cfg->data, size, ext_data->module_data, size); + if (ret) { + comp_err(dev, "failed to copy setup config %d", ret); + goto free_cfg; + } + setup_cfg->avail = true; + codec->cfg.avail = false; + + /* direction follows the codec params in init data */ + init_bytes = (uint8_t *)ext_data->module_data; + cd->direction = *(uint32_t *)(init_bytes + sizeof(struct snd_codec)); + + comp_info(dev, "codec direction set to %u", cd->direction); + } + + ret = cadence_init_codec_object(mod); + if (ret) + goto free_cfg; + + ret = cadence_configure_codec_params(mod); + if (ret) + goto free_cfg; + + /* Allocate memory for the codec */ + API_CALL(cd, XA_API_CMD_GET_MEMTABS_SIZE, 0, &mem_tabs_size, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to get memtabs size", ret); + goto free_cfg; + } + + cd->mem_tabs = mod_alloc(mod, mem_tabs_size); + if (!cd->mem_tabs) { + comp_err(dev, "failed to allocate space for memtabs"); + goto free_cfg; + } + + comp_dbg(dev, "allocated %d bytes for memtabs", mem_tabs_size); + + API_CALL(cd, XA_API_CMD_SET_MEMTABS_PTR, 0, cd->mem_tabs, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to set memtabs", ret); + goto free; + } + + ret = cadence_codec_init_memory_tables(mod); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "error %x: failed to init memory tables", ret); + goto free; + } + + comp_dbg(dev, "cadence_codec_init() done"); + + return 0; +free: + mod_free(mod, cd->mem_tabs); +free_cfg: + if (setup_cfg) + mod_free(mod, setup_cfg->data); +free_cd: + mod_free(mod, cd); + + return ret; +} + +int cadence_codec_apply_config(struct processing_module *mod) +{ + int size; + struct module_config *cfg; + void *data; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + + cfg = &codec->cfg; + + /* this will be true during prepare if there's no config available after init */ + if (!cfg->avail) + return 0; + + data = cfg->data; + size = cfg->size; + + if (!size) { + comp_err(dev, "error: no data available in config to apply"); + return -EIO; + } + + return cadence_codec_apply_params(mod, size, data); +} + +static int cadence_codec_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + int ret = 0; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + + comp_dbg(dev, "cadence_codec_prepare() start"); + + ret = cadence_codec_apply_config(mod); + if (ret) { + comp_err(dev, "failed to apply config error %x:", ret); + return ret; + } + + /* Check init done status. Note, it may happen that init_done flag will return + * false value, this is normal since some codec variants needs input in order to + * fully finish initialization. That's why at codec_adapter_copy() we call + * codec_init_process() base on result obtained below. + */ +#ifdef CONFIG_CADENCE_CODEC_WRAPPER + /* TODO: remove the "#ifdef CONFIG_CADENCE_CODEC_WRAPPER" once cadence fixes the bug + * in the init/prepare sequence. Basically below API_CALL shall return 1 for + * PCM streams and 0 for compress ones. As it turns out currently it returns 1 + * in both cases so in turn compress stream won't finish its prepare during first copy + * in codec_adapter_copy(). + */ + API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_DONE_QUERY, + &codec->mpd.init_done, ret); + if (ret != LIB_NO_ERROR) { + comp_err(dev, "failed to get lib init status error %x:", ret); + return ret; + } +#endif + + /* set the period based on the minimum required input data size */ + dev->period = 1000000ULL * codec->mpd.in_buff_size / + (source_get_frame_bytes(sources[0]) * source_get_rate(sources[0])); + comp_dbg(dev, "period set to %u usec", dev->period); + + /* align down period to LL cycle time */ + dev->period /= LL_TIMER_PERIOD_US; + dev->period *= LL_TIMER_PERIOD_US; + + comp_dbg(dev, "cadence_codec_prepare() done"); + return 0; +} + +static void cadence_copy_data_from_buffer(void *dest, const void *buffer_ptr, size_t bytes_to_copy, + size_t buffer_size, uint8_t const *buffer_start) +{ + size_t bytes_to_end = (size_t)((uint8_t *)buffer_start + + buffer_size - (uint8_t *)buffer_ptr); + + if (bytes_to_end >= bytes_to_copy) { + /* No wrap, copy directly */ + memcpy_s(dest, bytes_to_copy, buffer_ptr, bytes_to_copy); + return; + } + + /* Wrap occurs, copy in two parts */ + memcpy_s(dest, bytes_to_end, buffer_ptr, bytes_to_end); + memcpy_s((uint8_t *)dest + bytes_to_end, bytes_to_copy - bytes_to_end, + buffer_start, bytes_to_copy - bytes_to_end); +} + +static int cadence_codec_process(struct processing_module *mod, struct sof_source **sources, + int num_of_sources, struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + size_t in_size = source_get_data_available(sources[0]); + size_t out_space = sink_get_free_size(sinks[0]); + uint8_t const *source_buffer_start; + int consumed_during_init = 0; + uint32_t remaining = in_size; + const void *src_ptr; + size_t src_bytes; + int ret; + + if (!codec->mpd.init_done) { + /* Acquire data from the source buffer */ + ret = source_get_data(sources[0], codec->mpd.in_buff_size, &src_ptr, + (const void **)&source_buffer_start, &src_bytes); + if (ret) { + comp_err(dev, "cannot get data from source buffer"); + return ret; + } + + cadence_copy_data_from_buffer(codec->mpd.in_buff, src_ptr, codec->mpd.in_buff_size, + src_bytes, source_buffer_start); + + codec->mpd.avail = codec->mpd.in_buff_size; + ret = cadence_codec_init_process(mod); + if (ret) + return ret; + + remaining -= codec->mpd.consumed; + source_release_data(sources[0], codec->mpd.consumed); + consumed_during_init = codec->mpd.consumed; + } + + codec->mpd.consumed = 0; + + /* Proceed only if we have enough data to fill the module buffer completely */ + if (remaining < codec->mpd.in_buff_size) + return -ENODATA; + + /* Acquire data from the source buffer */ + ret = source_get_data(sources[0], codec->mpd.in_buff_size, &src_ptr, + (const void **)&source_buffer_start, &src_bytes); + + cadence_copy_data_from_buffer(codec->mpd.in_buff, src_ptr, codec->mpd.in_buff_size, + src_bytes, source_buffer_start); + codec->mpd.avail = codec->mpd.in_buff_size; + + comp_dbg(dev, "cadence_codec_process() start"); + + ret = cadence_codec_process_data(mod, NULL); + if (ret) { + source_release_data(sources[0], 0); + return ret; + } + + if (codec->mpd.eos_reached && !codec->mpd.eos_notification_sent) { + struct ipc_msg msg_proto; + struct comp_ipc_config *ipc_config = &dev->ipc_config; + union ipc4_notification_header *primary = + (union ipc4_notification_header *)&msg_proto.header; + struct sof_ipc4_notify_module_data *msg_module_data; + struct ipc_msg *msg; + + memset_s(&msg_proto, sizeof(msg_proto), 0, sizeof(msg_proto)); + primary->r.notif_type = SOF_IPC4_MODULE_NOTIFICATION; + primary->r.type = SOF_IPC4_GLB_NOTIFICATION; + primary->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + primary->r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg = ipc_msg_w_ext_init(msg_proto.header, msg_proto.extension, + sizeof(*msg_module_data)); + if (msg) { + msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data; + msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id); + msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id); + msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL; + msg_module_data->event_data_size = 0; + + ipc_msg_send(msg, NULL, false); + codec->mpd.eos_notification_sent = true; + } + + /* Set EOS for the sink as we are not going to produce more data */ + audio_buffer_set_eos(sof_audio_buffer_from_sink(sinks[0])); + } + + /* do not proceed if not enough free space left */ + if (out_space < codec->mpd.produced) { + source_release_data(sources[0], 0); + return -ENOSPC; + } + + void *sink_ptr; + size_t sink_bytes; + uint8_t const *sink_buffer_start; + + ret = sink_get_buffer(sinks[0], codec->mpd.produced, &sink_ptr, + (void **)&sink_buffer_start, &sink_bytes); + if (ret) { + comp_err(dev, "cannot get sink buffer"); + return ret; + } + + /* Copy the produced samples into the output buffer */ + size_t bytes_to_end = (size_t)((uint8_t *)sink_buffer_start + + sink_bytes - (uint8_t *)sink_ptr); + + if (bytes_to_end >= codec->mpd.produced) { + /* No wrap, copy directly */ + memcpy_s(sink_ptr, codec->mpd.produced, codec->mpd.out_buff, + codec->mpd.produced); + } else { + /* Wrap occurs, copy in two parts */ + memcpy_s(sink_ptr, bytes_to_end, codec->mpd.out_buff, bytes_to_end); + memcpy_s((uint8_t *)sink_buffer_start, codec->mpd.produced - bytes_to_end, + (uint8_t *)codec->mpd.out_buff + bytes_to_end, + codec->mpd.produced - bytes_to_end); + } + + source_release_data(sources[0], codec->mpd.consumed); + sink_commit_buffer(sinks[0], codec->mpd.produced); + + /* reset produced and consumed */ + codec->mpd.consumed = 0; + codec->mpd.produced = 0; + + comp_dbg(dev, "cadence_codec_process() done"); + + return 0; +} + +static int cadence_codec_reset(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + + codec->mpd.init_done = 0; + + return 0; +} + +static bool cadence_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct module_data *codec = &mod->priv; + + if (source_get_data_available(sources[0]) < codec->mpd.in_buff_size || + sink_get_free_size(sinks[0]) < codec->mpd.out_buff_size) + return false; + + return true; +} + +static const struct module_interface cadence_codec_interface = { + .init = cadence_codec_init, + .prepare = cadence_codec_prepare, + .process = cadence_codec_process, + .set_configuration = cadence_codec_set_configuration, + .reset = cadence_codec_reset, + .free = cadence_codec_free, + .is_ready_to_process = cadence_is_ready_to_process, +}; + +DECLARE_MODULE_ADAPTER(cadence_codec_interface, cadence_codec_uuid, cadence_codec_tr); +SOF_MODULE_INIT(cadence_codec, sys_comp_module_cadence_codec_interface_init); diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c new file mode 100644 index 000000000000..984bd2c11680 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -0,0 +1,976 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE +// +// Copyright(c) 2025 Dolby Laboratories. All rights reserved. +// +// Author: Jun Lai <jun.lai@dolby.com> +// + +#include <rtos/atomic.h> +#include <rtos/init.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/compiler_attributes.h> + +#include "dax.h" + +LOG_MODULE_REGISTER(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); + +#define MAX_PARAMS_STR_BUFFER_SIZE 1536 +#define DAX_ENABLE_MASK 0x1 +#define DAX_PROFILE_MASK 0x2 +#define DAX_DEVICE_MASK 0x4 +#define DAX_CP_MASK 0x8 +#define DAX_VOLUME_MASK 0x10 +#define DAX_CTC_MASK 0x20 +#define DAX_PROCESSING_MASK 0x10000 +#define DAX_RESET_MASK 0x20000 +#define DAX_FREE_MASK 0x40000 + +#define DAX_SWITCH_ENABLE_CONTROL_ID 0 +#define DAX_SWITCH_CP_CONTROL_ID 1 +#define DAX_SWITCH_CTC_CONTROL_ID 2 +#define DAX_ENUM_PROFILE_CONTROL_ID 0 +#define DAX_ENUM_DEVICE_CONTROL_ID 1 + +enum dax_flag_opt_mode { + DAX_FLAG_READ = 0, + DAX_FLAG_SET, + DAX_FLAG_CLEAR, + DAX_FLAG_READ_AND_CLEAR, +}; + +static int32_t flag_process(struct dax_adapter_data *adapter_data, + uint32_t flag, + enum dax_flag_opt_mode opt_mode) +{ +#ifdef __ZEPHYR__ + int32_t bit = ffs(flag) - 1; + + switch (opt_mode) { + case DAX_FLAG_READ: + return atomic_test_bit(&adapter_data->proc_flags, bit); + case DAX_FLAG_SET: + atomic_set_bit(&adapter_data->proc_flags, bit); + break; + case DAX_FLAG_CLEAR: + atomic_clear_bit(&adapter_data->proc_flags, bit); + break; + case DAX_FLAG_READ_AND_CLEAR: + return atomic_test_and_clear_bit(&adapter_data->proc_flags, bit); + default: + break; + } +#else + /* Non-Zephyr builds run single-threaded (no DP mode), there is no synchronous problem */ + int32_t old_flags = atomic_read(&adapter_data->proc_flags); + + switch (opt_mode) { + case DAX_FLAG_READ: + return (old_flags & flag) != 0; + case DAX_FLAG_SET: + atomic_set(&adapter_data->proc_flags, old_flags | flag); + break; + case DAX_FLAG_CLEAR: + atomic_set(&adapter_data->proc_flags, old_flags & ~flag); + break; + case DAX_FLAG_READ_AND_CLEAR: + atomic_set(&adapter_data->proc_flags, old_flags & ~flag); + return (old_flags & flag) != 0; + default: + break; + } +#endif + return 0; +} + +static int itostr(int num, char *str) +{ + int index = 0, digit_count = 0; + int temp; + + if (num < 0) { + str[0] = '-'; + index = 1; + num = -num; + } + + if (num == 0) { + str[index] = '0'; + str[index + 1] = '\0'; + return index + 1; + } + + temp = num; + while (temp > 0) { + temp /= 10; + digit_count++; + } + + temp = index + digit_count - 1; + while (num > 0) { + str[temp] = (num % 10) + '0'; + num /= 10; + temp--; + } + + str[index + digit_count] = '\0'; + return index + digit_count; +} + +static const char *get_params_str(const void *val, uint32_t val_sz) +{ + static char params_str[MAX_PARAMS_STR_BUFFER_SIZE + 16]; + const int32_t *param_val = (const int32_t *)val; + const uint32_t param_sz = val_sz >> 2; + uint32_t offset = 0; + + for (uint32_t i = 0; i < param_sz && offset < MAX_PARAMS_STR_BUFFER_SIZE; i++) { + offset += itostr(param_val[i], params_str + offset); + params_str[offset] = ','; + offset++; + params_str[offset] = '\0'; + } + return ¶ms_str[0]; +} + +static int sof_to_dax_frame_fmt(enum sof_ipc_frame sof_frame_fmt) +{ + switch (sof_frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + return DAX_FMT_SHORT_16; + case SOF_IPC_FRAME_S32_LE: + return DAX_FMT_INT; + case SOF_IPC_FRAME_FLOAT: + return DAX_FMT_FLOAT; + default: + return DAX_FMT_UNSUPPORTED; + } +} + +static int sof_to_dax_sample_rate(uint32_t rate) +{ + switch (rate) { + case 48000: + return rate; + default: + return DAX_RATE_UNSUPPORTED; + } +} + +static int sof_to_dax_channels(uint32_t channels) +{ + switch (channels) { + case 2: + case 6 /* 5.1 */: + case 8 /* 7.1 */: + return channels; + default: + return DAX_CHANNLES_UNSUPPORTED; + } +} + +static int sof_to_dax_buffer_layout(enum sof_ipc_buffer_format sof_buf_fmt) +{ + switch (sof_buf_fmt) { + case SOF_IPC_BUFFER_INTERLEAVED: + return DAX_BUFFER_LAYOUT_INTERLEAVED; + case SOF_IPC_BUFFER_NONINTERLEAVED: + return DAX_BUFFER_LAYOUT_NONINTERLEAVED; + default: + return DAX_BUFFER_LAYOUT_UNSUPPORTED; + } +} + +void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff) +{ + if (dax_buff->addr) { + mod_free(mod, dax_buff->addr); + dax_buff->addr = NULL; + } + dax_buff->size = 0; + dax_buff->avail = 0; + dax_buff->free = 0; +} + +int dax_buffer_alloc(struct processing_module *mod, + struct dax_buffer *dax_buff, uint32_t bytes) +{ + dax_buffer_release(mod, dax_buff); + dax_buff->addr = mod_balloc(mod, bytes); + if (!dax_buff->addr) + dax_buff->addr = mod_zalloc(mod, bytes); + if (!dax_buff->addr) + return -ENOMEM; + + dax_buff->size = bytes; + dax_buff->avail = 0; + dax_buff->free = bytes; + return 0; +} + +/* After reading from buffer */ +static void dax_buffer_consume(struct dax_buffer *dax_buff, uint32_t bytes) +{ + uint8_t *buf = (uint8_t *)dax_buff->addr; + uint32_t copy_bytes; + + bytes = MIN(bytes, dax_buff->avail); + copy_bytes = dax_buff->avail - bytes; + for (int i = 0; i < copy_bytes; i++) + buf[i] = buf[bytes + i]; + dax_buff->avail = copy_bytes; + dax_buff->free = dax_buff->size - dax_buff->avail; +} + +/* After writing to buffer */ +static void dax_buffer_produce(struct dax_buffer *dax_buff, uint32_t bytes) +{ + dax_buff->avail += bytes; + dax_buff->avail = MIN(dax_buff->avail, dax_buff->size); + dax_buff->free = dax_buff->size - dax_buff->avail; +} + +static bool is_enabled(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + return dax_ctx->enable && dax_ctx->p_dax; +} + +static int set_tuning_file(struct processing_module *mod, void *value, uint32_t size) +{ + int ret = 0; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + if (dax_buffer_alloc(mod, &dax_ctx->tuning_file_buffer, size) != 0) { + comp_err(dev, "allocate %u bytes failed for tuning file", size); + ret = -ENOMEM; + } else { + memcpy_s(dax_ctx->tuning_file_buffer.addr, + dax_ctx->tuning_file_buffer.free, + value, + size); + } + + comp_info(dev, "allocated: tuning %u, ret %d", dax_ctx->tuning_file_buffer.size, ret); + return ret; +} + +static int set_enable(struct processing_module *mod, int32_t enable) +{ + int ret; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + ret = dax_set_enable(enable, dax_ctx); + comp_info(mod->dev, "set dax enable %d, ret %d", enable, ret); + return ret; +} + +static int set_volume(struct processing_module *mod, int32_t abs_volume) +{ + int ret; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + ret = dax_set_volume(abs_volume, dax_ctx); + comp_info(mod->dev, "set volume %d, ret %d", abs_volume, ret); + return ret; +} + +static int set_device(struct processing_module *mod, int32_t out_device) +{ + int ret; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + ret = dax_set_device(out_device, dax_ctx); + comp_info(mod->dev, "set device %d, ret %d", out_device, ret); + return ret; +} + +static int set_crosstalk_cancellation_enable(struct processing_module *mod, int32_t enable) +{ + int ret; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + ret = dax_set_ctc_enable(enable, dax_ctx); + comp_info(mod->dev, "set ctc enable %d, ret %d", enable, ret); + return ret; +} + +static int update_params_from_buffer(struct processing_module *mod, void *params, uint32_t size); + +static int set_profile(struct processing_module *mod, int32_t profile_id) +{ + int ret = -EINVAL; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + uint32_t params_sz = 0; + void *params; + + params = dax_find_params(DAX_PARAM_ID_PROFILE, profile_id, ¶ms_sz, dax_ctx); + if (params) + ret = update_params_from_buffer(mod, params, params_sz); + comp_info(dev, "switched to profile %d, ret %d", profile_id, ret); + return ret; +} + +static int set_tuning_device(struct processing_module *mod, int32_t tuning_device) +{ + int ret = -EINVAL; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + uint32_t params_sz = 0; + void *params; + + params = dax_find_params(DAX_PARAM_ID_TUNING_DEVICE, tuning_device, ¶ms_sz, dax_ctx); + if (params) + ret = update_params_from_buffer(mod, params, params_sz); + comp_info(dev, "switched to tuning device %d, ret %d", tuning_device, ret); + return ret; +} + +static int set_content_processing_enable(struct processing_module *mod, int32_t enable) +{ + int ret = -EINVAL; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + uint32_t params_sz = 0; + void *params; + + params = dax_find_params(DAX_PARAM_ID_CP_ENABLE, enable, ¶ms_sz, dax_ctx); + if (params) + ret = update_params_from_buffer(mod, params, params_sz); + comp_info(dev, "set content processing enable %d, ret %d", enable, ret); + return ret; +} + +static int dax_set_param_wrapper(struct processing_module *mod, + uint32_t id, void *value, uint32_t size) +{ + int ret = 0; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + int32_t tmp_val; + + switch (id) { + case DAX_PARAM_ID_TUNING_FILE: + set_tuning_file(mod, value, size); + break; + case DAX_PARAM_ID_ENABLE: + tmp_val = *((int32_t *)value); + tmp_val = !!tmp_val; + if (dax_ctx->enable != tmp_val) { + dax_ctx->enable = tmp_val; + flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_SET); + } + break; + case DAX_PARAM_ID_ABSOLUTE_VOLUME: + dax_ctx->volume = *((int32_t *)value); + flag_process(adapter_data, DAX_VOLUME_MASK, DAX_FLAG_SET); + break; + case DAX_PARAM_ID_OUT_DEVICE: + tmp_val = *((int32_t *)value); + if (dax_ctx->out_device != tmp_val) { + dax_ctx->out_device = tmp_val; + flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_SET); + } + break; + case DAX_PARAM_ID_PROFILE: + tmp_val = *((int32_t *)value); + if (dax_ctx->profile != tmp_val) { + dax_ctx->profile = tmp_val; + flag_process(adapter_data, DAX_PROFILE_MASK, DAX_FLAG_SET); + } + break; + case DAX_PARAM_ID_CP_ENABLE: + tmp_val = *((int32_t *)value); + tmp_val = !!tmp_val; + if (dax_ctx->content_processing_enable != tmp_val) { + dax_ctx->content_processing_enable = tmp_val; + flag_process(adapter_data, DAX_CP_MASK, DAX_FLAG_SET); + } + break; + case DAX_PARAM_ID_CTC_ENABLE: + tmp_val = *((int32_t *)value); + tmp_val = !!tmp_val; + if (dax_ctx->ctc_enable != tmp_val) { + dax_ctx->ctc_enable = tmp_val; + flag_process(adapter_data, DAX_CTC_MASK, DAX_FLAG_SET); + } + break; + case DAX_PARAM_ID_ENDPOINT: + if (dax_ctx->endpoint == *((int32_t *)value)) { + ret = update_params_from_buffer(mod, (uint8_t *)value + 4, size - 4); + comp_info(dev, "switched to endpoint %d, ret %d", dax_ctx->endpoint, ret); + } + break; + default: + ret = dax_set_param(id, (void *)(value), size, dax_ctx); + comp_info(dev, "dax_set_param: ret %d, id %#x, size %u, value %s", + ret, id, size >> 2, get_params_str(value, size)); + break; + } + + return ret; +} + +static int update_params_from_buffer(struct processing_module *mod, void *data, uint32_t data_size) +{ + struct comp_dev *dev = mod->dev; + struct module_param *param; + void *pos = data; + const uint32_t param_header_size = 8; + uint32_t param_data_size; + + for (uint32_t i = 0; i < data_size;) { + param = (struct module_param *)(pos); + if (param->size < param_header_size || + param->size > data_size - i || + (param->size & 0x03) != 0) { + comp_err(dev, "invalid param %#x, param size %u, pos %u", + param->id, param->size, i); + return -EINVAL; + } + + if (param->size > param_header_size) { + param_data_size = param->size - param_header_size; + dax_set_param_wrapper(mod, param->id, (void *)(param->data), + param_data_size); + } + + pos = (void *)((uint8_t *)(pos) + param->size); + i += param->size; + } + + return 0; +} + +static void check_and_update_settings(struct processing_module *mod) +{ + int ret; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + /* ret equals to 0 mean a new creation or destruction of dax instance */ + ret = dax_check_and_update_instance(mod); + if (ret == 0) { + if (is_enabled(mod) /* A new creation */) { + /* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */ + flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_SET); + } else if (!dax_ctx->p_dax /* A new destruction */) { + set_enable(mod, 0); + comp_info(mod->dev, "falling back to pass-through mode."); + } + } + + if (flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_READ_AND_CLEAR)) { + set_enable(mod, dax_ctx->enable); + if (is_enabled(mod)) { + flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_SET); + flag_process(adapter_data, DAX_VOLUME_MASK, DAX_FLAG_SET); + } + return; + } + + if (!is_enabled(mod)) + return; + + if (flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_READ_AND_CLEAR)) { + set_device(mod, dax_ctx->out_device); + set_tuning_device(mod, dax_ctx->tuning_device); + flag_process(adapter_data, DAX_PROFILE_MASK, DAX_FLAG_SET); + return; + } + if (flag_process(adapter_data, DAX_CTC_MASK, DAX_FLAG_READ_AND_CLEAR)) { + set_crosstalk_cancellation_enable(mod, dax_ctx->ctc_enable); + flag_process(adapter_data, DAX_PROFILE_MASK, DAX_FLAG_SET); + return; + } + if (flag_process(adapter_data, DAX_PROFILE_MASK, DAX_FLAG_READ_AND_CLEAR)) { + set_profile(mod, dax_ctx->profile); + if (!dax_ctx->content_processing_enable) + flag_process(adapter_data, DAX_CP_MASK, DAX_FLAG_SET); + return; + } + if (flag_process(adapter_data, DAX_CP_MASK, DAX_FLAG_READ_AND_CLEAR)) { + set_content_processing_enable(mod, dax_ctx->content_processing_enable); + return; + } + if (flag_process(adapter_data, DAX_VOLUME_MASK, DAX_FLAG_READ_AND_CLEAR)) + set_volume(mod, dax_ctx->volume); +} + +static int sof_dax_reset(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx; + + /* dax instance will be established on prepare(), and destroyed on reset() */ + if (adapter_data) { + dax_ctx = &adapter_data->dax_ctx; + if (flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_READ)) { + flag_process(adapter_data, DAX_RESET_MASK, DAX_FLAG_SET); + } else { + dax_unregister_user(mod); + dax_buffer_release(mod, &dax_ctx->input_buffer); + dax_buffer_release(mod, &dax_ctx->output_buffer); + } + } + + return 0; +} + +static int sof_dax_free(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx; + + if (adapter_data) { + dax_ctx = &adapter_data->dax_ctx; + if (flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_READ)) { + flag_process(adapter_data, DAX_FREE_MASK, DAX_FLAG_SET); + } else { + sof_dax_reset(mod); + dax_buffer_release(mod, &dax_ctx->tuning_file_buffer); + mod_data_blob_handler_free(mod, dax_ctx->blob_handler); + dax_ctx->blob_handler = NULL; + mod_free(mod, adapter_data); + module_set_private_data(mod, NULL); + } + } + return 0; +} + +static void check_and_update_state(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + + if (!adapter_data) + return; + + if (flag_process(adapter_data, DAX_FREE_MASK, DAX_FLAG_READ_AND_CLEAR)) + sof_dax_free(mod); + else if (flag_process(adapter_data, DAX_RESET_MASK, DAX_FLAG_READ_AND_CLEAR)) + sof_dax_reset(mod); +} + +static int sof_dax_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *md = &mod->priv; + struct dax_adapter_data *adapter_data; + struct sof_dax *dax_ctx; + + md->private = mod_zalloc(mod, sizeof(struct dax_adapter_data)); + if (!md->private) { + comp_err(dev, "failed to allocate %u bytes for initialization", + sizeof(struct sof_dax)); + return -ENOMEM; + } + + adapter_data = module_get_private_data(mod); + adapter_data->comp_id = dev->ipc_config.id; + adapter_data->priority = DAX_USER_PRIORITY_DEFAULT; + dax_ctx = &adapter_data->dax_ctx; + dax_ctx->enable = 0; + dax_ctx->profile = 0; + dax_ctx->out_device = 0; + dax_ctx->ctc_enable = 1; + dax_ctx->content_processing_enable = 1; + dax_ctx->volume = 1 << 23; + dax_ctx->update_flags = 0; + + dax_ctx->blob_handler = mod_data_blob_handler_new(mod); + if (!dax_ctx->blob_handler) { + comp_err(dev, "create blob handler failed"); + mod_free(mod, adapter_data); + module_set_private_data(mod, NULL); + return -ENOMEM; + } + + dax_instance_manager_init(); + + return 0; +} + +static int check_media_format(struct processing_module *mod) +{ + int ret = 0; + struct comp_dev *dev = mod->dev; + struct comp_buffer *source = comp_dev_get_first_data_producer(dev); + struct comp_buffer *sink = comp_dev_get_first_data_consumer(dev); + const struct audio_stream *src_stream = &source->stream; + const struct audio_stream *sink_stream = &sink->stream; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + if (audio_stream_get_frm_fmt(src_stream) != audio_stream_get_frm_fmt(sink_stream) || + sof_to_dax_frame_fmt(audio_stream_get_frm_fmt(src_stream)) == DAX_FMT_UNSUPPORTED) { + comp_err(dev, "unsupported format, source %d, sink %d", + audio_stream_get_frm_fmt(src_stream), + audio_stream_get_frm_fmt(sink_stream)); + ret = -EINVAL; + } + + if (audio_stream_get_rate(src_stream) != audio_stream_get_rate(sink_stream) || + sof_to_dax_sample_rate(audio_stream_get_rate(src_stream)) == DAX_RATE_UNSUPPORTED) { + comp_err(dev, "unsupported sample rate, source %d, sink %d", + audio_stream_get_rate(src_stream), audio_stream_get_rate(sink_stream)); + ret = -EINVAL; + } + + if (audio_stream_get_channels(sink_stream) != 2 || + sof_to_dax_channels(audio_stream_get_channels(src_stream)) == + DAX_CHANNLES_UNSUPPORTED) { + comp_err(dev, "unsupported number of channels, source %d, sink %d", + audio_stream_get_channels(src_stream), + audio_stream_get_channels(sink_stream)); + ret = -EINVAL; + } + + if (audio_stream_get_buffer_fmt(src_stream) != audio_stream_get_buffer_fmt(sink_stream) || + sof_to_dax_buffer_layout(audio_stream_get_buffer_fmt(src_stream)) == + DAX_BUFFER_LAYOUT_UNSUPPORTED) { + comp_err(dev, "unsupported buffer layout %d", + audio_stream_get_buffer_fmt(src_stream)); + ret = -EINVAL; + } + + if (ret != 0) + return ret; + + dax_ctx->input_media_format.data_format = + sof_to_dax_frame_fmt(audio_stream_get_frm_fmt(src_stream)); + dax_ctx->input_media_format.sampling_rate = + sof_to_dax_sample_rate(audio_stream_get_rate(src_stream)); + dax_ctx->input_media_format.num_channels = + sof_to_dax_channels(audio_stream_get_channels(src_stream)); + dax_ctx->input_media_format.layout = + sof_to_dax_buffer_layout(audio_stream_get_buffer_fmt(src_stream)); + dax_ctx->input_media_format.bytes_per_sample = audio_stream_sample_bytes(src_stream); + + dax_ctx->output_media_format.data_format = + sof_to_dax_frame_fmt(audio_stream_get_frm_fmt(sink_stream)); + dax_ctx->output_media_format.sampling_rate = + sof_to_dax_sample_rate(audio_stream_get_rate(sink_stream)); + dax_ctx->output_media_format.num_channels = + sof_to_dax_channels(audio_stream_get_channels(sink_stream)); + dax_ctx->output_media_format.layout = + sof_to_dax_buffer_layout(audio_stream_get_buffer_fmt(sink_stream)); + dax_ctx->output_media_format.bytes_per_sample = audio_stream_sample_bytes(sink_stream); + + comp_info(dev, "format %d, sample rate %d, channels %d, data format %d", + dax_ctx->input_media_format.data_format, + dax_ctx->input_media_format.sampling_rate, + dax_ctx->input_media_format.num_channels, + dax_ctx->input_media_format.data_format); + return 0; +} + +static int sof_dax_prepare(struct processing_module *mod, struct sof_source **sources, + int num_of_sources, struct sof_sink **sinks, int num_of_sinks) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + uint32_t ibs, obs; + + if (num_of_sources != 1 || num_of_sinks != 1) { + comp_err(dev, "unsupported number of buffers, in %d, out %d", + num_of_sources, num_of_sinks); + return -EINVAL; + } + + ret = check_media_format(mod); + if (ret != 0) + return ret; + + dax_ctx->sof_period_bytes = dev->frames * + dax_ctx->output_media_format.num_channels * + dax_ctx->output_media_format.bytes_per_sample; + dax_ctx->period_bytes = dax_query_period_frames(dax_ctx) * + dax_ctx->output_media_format.num_channels * + dax_ctx->output_media_format.bytes_per_sample; + dax_ctx->period_us = 1000000 * dax_ctx->period_bytes / + (dax_ctx->output_media_format.bytes_per_sample * + dax_ctx->output_media_format.num_channels * + dax_ctx->output_media_format.sampling_rate); + + ibs = (dax_query_period_frames(dax_ctx) + dev->frames) * + dax_ctx->input_media_format.num_channels * + dax_ctx->input_media_format.bytes_per_sample; + obs = dax_ctx->period_bytes + dax_ctx->sof_period_bytes; + if (dax_buffer_alloc(mod, &dax_ctx->input_buffer, ibs) != 0) { + comp_err(dev, "allocate %u bytes failed for input", ibs); + ret = -ENOMEM; + goto err; + } + if (dax_buffer_alloc(mod, &dax_ctx->output_buffer, obs) != 0) { + comp_err(dev, "allocate %u bytes failed for output", obs); + ret = -ENOMEM; + goto err; + } + memset(dax_ctx->output_buffer.addr, 0, dax_ctx->output_buffer.size); + dax_buffer_produce(&dax_ctx->output_buffer, dax_ctx->output_buffer.size); + comp_info(dev, "allocated: ibs %u, obs %u", ibs, obs); + + dax_register_user(mod); + dax_check_and_update_instance(mod); + + return 0; + +err: + dax_buffer_release(mod, &dax_ctx->input_buffer); + dax_buffer_release(mod, &dax_ctx->output_buffer); + return ret; +} + +static int sof_dax_process(struct processing_module *mod, struct sof_source **sources, + int num_of_sources, struct sof_sink **sinks, int num_of_sinks) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + struct sof_source *source = sources[0]; + struct sof_sink *sink = sinks[0]; + uint8_t *buf, *bufstart, *bufend, *dax_buf; + size_t bufsz; + struct dax_buffer *dax_input_buffer = &dax_ctx->input_buffer; + struct dax_buffer *dax_output_buffer = &dax_ctx->output_buffer; + uint32_t consumed_bytes, processed_bytes, produced_bytes; + + flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_SET); + + if (!adapter_data) { + comp_err(mod->dev, "invalid adapter data"); + return -EINVAL; + } + + /* source stream -> internal input buffer */ + consumed_bytes = MIN(source_get_data_available(source), dax_input_buffer->free); + source_get_data(source, consumed_bytes, (void *)&buf, (void *)&bufstart, &bufsz); + bufend = &bufstart[bufsz]; + dax_buf = (uint8_t *)(dax_input_buffer->addr); + cir_buf_copy(buf, bufstart, bufend, + dax_buf + dax_input_buffer->avail, + dax_buf, + dax_buf + dax_input_buffer->size, + consumed_bytes); + dax_buffer_produce(dax_input_buffer, consumed_bytes); + source_release_data(source, consumed_bytes); + + check_and_update_settings(mod); + + /* internal input buffer -> internal output buffer */ + processed_bytes = dax_process(dax_ctx); + dax_buffer_consume(dax_input_buffer, processed_bytes); + dax_buffer_produce(dax_output_buffer, processed_bytes); + + /* internal output buffer -> sink stream */ + produced_bytes = MIN(dax_output_buffer->avail, sink_get_free_size(sink)); + if (produced_bytes > 0) { + sink_get_buffer(sink, produced_bytes, (void *)&buf, (void *)&bufstart, &bufsz); + bufend = &bufstart[bufsz]; + dax_buf = (uint8_t *)(dax_output_buffer->addr); + cir_buf_copy(dax_buf, dax_buf, dax_buf + dax_output_buffer->size, + buf, bufstart, bufend, produced_bytes); + dax_buffer_consume(dax_output_buffer, produced_bytes); + sink_commit_buffer(sink, produced_bytes); + } + flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_CLEAR); + check_and_update_state(mod); + + return 0; +} + +static int sof_dax_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, const uint8_t *fragment, + size_t fragment_size, + uint8_t *response, size_t response_size) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + int32_t dax_param_id = 0; + int32_t val; + + if (fragment_size == 0) + return 0; + +#if CONFIG_IPC_MAJOR_4 + const struct sof_ipc4_control_msg_payload *ctl = NULL; + + switch (config_id) { + case 0: /* IPC4_VOLUME */ + /* ipc4_peak_volume_config::target_volume */ + val = ((const int32_t *)fragment)[1]; + val = sat_int32(Q_SHIFT_RND((int64_t)val, 31, 23)); + dax_param_id = DAX_PARAM_ID_ABSOLUTE_VOLUME; + break; + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + ctl = (const struct sof_ipc4_control_msg_payload *)fragment; + if (ctl->num_elems != 1) + return -EINVAL; + + val = ctl->chanv[0].value; + switch (ctl->id) { + case DAX_SWITCH_ENABLE_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_ENABLE; + break; + case DAX_SWITCH_CP_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_CP_ENABLE; + break; + case DAX_SWITCH_CTC_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_CTC_ENABLE; + break; + default: + comp_err(dev, "unknown switch control %d", ctl->id); + return -EINVAL; + } + break; + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + ctl = (const struct sof_ipc4_control_msg_payload *)fragment; + if (ctl->num_elems != 1) + return -EINVAL; + + val = ctl->chanv[0].value; + switch (ctl->id) { + case DAX_ENUM_PROFILE_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_PROFILE; + break; + case DAX_ENUM_DEVICE_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_OUT_DEVICE; + break; + default: + comp_err(dev, "unknown enum control %d", ctl->id); + return -EINVAL; + } + break; + default: + break; + } +#else + struct sof_ipc_ctrl_data *ctl = (struct sof_ipc_ctrl_data *)fragment; + + switch (ctl->cmd) { + case SOF_CTRL_CMD_VOLUME: + val = ctl->chanv[0].value; + dax_param_id = DAX_PARAM_ID_ABSOLUTE_VOLUME; + break; + case SOF_CTRL_CMD_SWITCH: + if (ctl->num_elems != 1) + return -EINVAL; + + val = ctl->chanv[0].value; + switch (ctl->index) { + case DAX_SWITCH_ENABLE_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_ENABLE; + break; + case DAX_SWITCH_CP_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_CP_ENABLE; + break; + case DAX_SWITCH_CTC_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_CTC_ENABLE; + break; + default: + comp_err(dev, "unknown switch control %d", ctl->index); + return -EINVAL; + } + break; + case SOF_CTRL_CMD_ENUM: + if (ctl->num_elems != 1) + return -EINVAL; + + val = ctl->chanv[0].value; + switch (ctl->index) { + case DAX_ENUM_PROFILE_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_PROFILE; + break; + case DAX_ENUM_DEVICE_CONTROL_ID: + dax_param_id = DAX_PARAM_ID_OUT_DEVICE; + break; + default: + comp_err(dev, "unknown enum control %d", ctl->index); + return -EINVAL; + } + break; + default: + break; + } +#endif + + if (dax_param_id == 0) { + ret = comp_data_blob_set(dax_ctx->blob_handler, pos, + data_offset_size, fragment, fragment_size); + if (ret == 0 && (pos == MODULE_CFG_FRAGMENT_LAST || + pos == MODULE_CFG_FRAGMENT_SINGLE)) { + void *data = NULL; + size_t data_size = 0; + + data = comp_get_data_blob(dax_ctx->blob_handler, &data_size, NULL); + if (data && data_size > 0) + update_params_from_buffer(mod, data, data_size); + } + } else { + ret = dax_set_param_wrapper(mod, dax_param_id, &val, sizeof(val)); + } + return ret; +} + +static const struct module_interface dolby_dax_audio_processing_interface = { + .init = sof_dax_init, + .prepare = sof_dax_prepare, + .process = sof_dax_process, + .set_configuration = sof_dax_set_configuration, + .reset = sof_dax_reset, + .free = sof_dax_free, +}; + +#if CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest main_manifest __section(".module") __used = { + .module = { + .name = "DAX", + .uuid = SOF_REG_UUID(dolby_dax_audio_processing), + .entry_point = (uint32_t)(&dolby_dax_audio_processing_interface), + .instance_max_count = DAX_MAX_INSTANCE, + .type = { + .load_type = SOF_MAN_MOD_TYPE_LLEXT, + .domain_dp = 1, + }, + .affinity_mask = 7, + } +}; + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(dolby_dax_audio_processing_tr, SOF_UUID(dolby_dax_audio_processing_uuid), + LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(dolby_dax_audio_processing_interface, dolby_dax_audio_processing_uuid, + dolby_dax_audio_processing_tr); +SOF_MODULE_INIT(dolby_dax_audio_processing, + sys_comp_module_dolby_dax_audio_processing_interface_init); + +#endif diff --git a/src/audio/module_adapter/module/dolby/dax.h b/src/audio/module_adapter/module/dolby/dax.h new file mode 100644 index 000000000000..da0419fa3766 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE + * + * Copyright(c) 2025 Dolby Laboratories. All rights reserved. + * + * Author: Jun Lai <jun.lai@dolby.com> + */ + +#include <sof/audio/module_adapter/module/generic.h> +#include <dax_inf.h> + +#define DAX_USER_ID_INVALID 0 +#define DAX_MAX_INSTANCE 2 + +enum dax_user_priority { + DAX_USER_PRIORITY_DEFAULT = 0, + DAX_USER_PRIORITY_P0 = 0, + DAX_USER_PRIORITY_P1 = 1, /* Highest priority */ +}; + +struct dax_adapter_data { + struct sof_dax dax_ctx; + atomic_t proc_flags; + uint32_t comp_id; + int32_t priority; +}; + +/** + * @brief Release memory used by a DAX buffer. + * + * @param[in] mod Pointer to the processing module. + * @param[in,out] dax_buff Pointer to the DAX buffer to release. + */ +void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff); + +/** + * @brief Allocate memory for a DAX buffer. + * + * @param[in] mod Pointer to the processing module. + * @param[in,out] dax_buff Pointer to the DAX buffer to allocate. + * @param[in] bytes Number of bytes to allocate. + * + * @return 0 on success, negative error code on failure. + */ +int dax_buffer_alloc(struct processing_module *mod, struct dax_buffer *dax_buff, uint32_t bytes); + +/** + * @brief Initialize global DAX instance manager state. + */ +void dax_instance_manager_init(void); + +/** + * @brief Register the current module as a DAX instance user. + * + * @param[in] mod Pointer to the processing module. + * + * @return 0 on success, negative error code on failure. + */ +int dax_register_user(struct processing_module *mod); + +/** + * @brief Unregister the current module from DAX instance user management. + * + * @param[in] mod Pointer to the processing module. + * + * @return 0 on success, negative error code on failure. + */ +int dax_unregister_user(struct processing_module *mod); + +/** + * @brief Reconcile DAX instance allocation based on user priority. + * + * @param[in] mod Pointer to the processing module. + * + * @return 0 on success, negative error code on failure. + */ +int dax_check_and_update_instance(struct processing_module *mod); diff --git a/src/audio/module_adapter/module/dolby/dax.toml b/src/audio/module_adapter/module/dolby/dax.toml new file mode 100644 index 000000000000..e57f29c8c792 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax.toml @@ -0,0 +1,25 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # DAX module config + [[module.entry]] + name = "DAX" + uuid = "40F66C8B-5AA5-4345-8919-53EC431AAA98" + affinity_mask = "0x7" + instance_count = "2" + domain_types = "1" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # see struct fw_pin_description + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0x400, 0x8, 0x8, 0x4404] + + REM # see struct sof_man_mod_config + REM # 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, 4096, 135000000, 1024, 1024, 0, 675000, 0] + + index = __COUNTER__ diff --git a/src/audio/module_adapter/module/dolby/dax_instance_manager.c b/src/audio/module_adapter/module/dolby/dax_instance_manager.c new file mode 100644 index 000000000000..36ef4f052757 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax_instance_manager.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE +// +// Copyright(c) 2026 Dolby Laboratories. All rights reserved. +// +// Author: Jun Lai <jun.lai@dolby.com> +// + +#include <stdbool.h> + +#include <rtos/spinlock.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/compiler_attributes.h> + +#include "dax.h" + +LOG_MODULE_DECLARE(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL); + +/* A DAX user refers to a DAX component, i.e., the processing_module + * object. When a DAX user intends to process audio data, it first needs + * to create a DAX instance. However, when multiple DAX users coexist + * in the system simultaneously, each DAX user will request its own DAX instance. + * Under limited memory resources, users that make later requests may fail to + * allocate the required memory. To address this, each DAX user is assigned a + * priority level, ensuring that higher-priority users are always granted + * instance resources first, regardless of the order in which the requests + * were made. + * + * The specific priority value will be automatically assigned in the dax_register_user + * function based on the configuration of the DAX component. + */ +struct dax_user { + uint32_t id; /* Component ID */ + enum dax_user_priority priority; + bool allocated; /* Whether the instance memory has been allocated */ +}; + +struct dax_instance_manager { + struct dax_user users[DAX_MAX_INSTANCE]; + + /* The maximum count of DAX instances that can be allocated simultaneously, + * determined by the system memory resource + */ + int32_t available_inst_cnt; + + struct k_spinlock lock; + bool initialized; +}; + +static struct dax_instance_manager inst_mgr; + +static void update_alloc_state_l(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + struct dax_user *user = NULL; + + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id == adapter_data->comp_id) { + user = &inst_mgr.users[i]; + break; + } + } + + if (!user) + return; + + if (dax_ctx->p_dax && dax_ctx->persist_buffer.addr && dax_ctx->scratch_buffer.addr) + user->allocated = true; + else + user->allocated = false; +} + +static int destroy_instance(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + if (!dax_ctx->p_dax) + return -EFAULT; + + /* free internal dax instance data and set dax_ctx->p_dax to NULL */ + dax_free(dax_ctx); + dax_buffer_release(mod, &dax_ctx->persist_buffer); + dax_buffer_release(mod, &dax_ctx->scratch_buffer); + comp_info(mod->dev, "freed instance"); + + return 0; +} + +static int establish_instance(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + uint32_t persist_sz; + uint32_t scratch_sz; + + if (dax_ctx->p_dax && dax_ctx->persist_buffer.addr && dax_ctx->scratch_buffer.addr) + return -EEXIST; + + if (dax_ctx->persist_buffer.addr || dax_ctx->scratch_buffer.addr) + destroy_instance(mod); + + persist_sz = dax_query_persist_memory(dax_ctx); + if (dax_buffer_alloc(mod, &dax_ctx->persist_buffer, persist_sz) != 0) { + comp_err(dev, "allocate %u bytes failed for persist", persist_sz); + ret = -ENOMEM; + goto err; + } + scratch_sz = dax_query_scratch_memory(dax_ctx); + if (dax_buffer_alloc(mod, &dax_ctx->scratch_buffer, scratch_sz) != 0) { + comp_err(dev, "allocate %u bytes failed for scratch", scratch_sz); + ret = -ENOMEM; + goto err; + } + ret = dax_init(dax_ctx); + if (ret != 0) { + comp_err(dev, "dax instance initialization failed, ret %d", ret); + goto err; + } + + comp_info(dev, "allocated: persist %u, scratch %u. version: %s", + persist_sz, scratch_sz, dax_get_version()); + return 0; + +err: + destroy_instance(mod); + return ret; +} + +static bool check_priority_l(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct dax_user *user = NULL; + int32_t allocated_cnt = 0; + + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id == adapter_data->comp_id) { + user = &inst_mgr.users[i]; + break; + } + } + + /* If the current module (user) is not existing in user manager, + * instance memory allocation is not allowed. + */ + if (!user) + return false; + + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].priority > user->priority && !inst_mgr.users[i].allocated) + return false; + if (inst_mgr.users[i].allocated) + allocated_cnt++; + } + + /* Resource is exhausted */ + if (!user->allocated && allocated_cnt >= inst_mgr.available_inst_cnt) + return false; + + return true; +} + +void dax_instance_manager_init(void) +{ + if (!inst_mgr.initialized) { + k_spinlock_init(&inst_mgr.lock); + /* Assume memory source is sufficient for maximum instances at the beginning */ + inst_mgr.available_inst_cnt = DAX_MAX_INSTANCE; + inst_mgr.initialized = true; + } +} + +int dax_register_user(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + struct dax_user *user = NULL; + k_spinlock_key_t key; + + key = k_spin_lock(&inst_mgr.lock); + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (!user && inst_mgr.users[i].id == DAX_USER_ID_INVALID) + user = &inst_mgr.users[i]; + + if (inst_mgr.users[i].id == adapter_data->comp_id) { + k_spin_unlock(&inst_mgr.lock, key); + return -EEXIST; + } + } + + if (!user) { + k_spin_unlock(&inst_mgr.lock, key); + return -ENOSPC; + } + + user->id = adapter_data->comp_id; + if (dax_ctx->out_device == DAX_DEVICE_SPEAKER) { + /* If the current component's output device is a speaker, it is assigned + * the highest priority. + */ + user->priority = DAX_USER_PRIORITY_P1; + } else if (dax_ctx->out_device == DAX_DEVICE_HEADPHONE) { + user->priority = DAX_USER_PRIORITY_P0; + } else { + user->priority = DAX_USER_PRIORITY_DEFAULT; + } + adapter_data->priority = user->priority; + + if (dax_ctx->p_dax && dax_ctx->persist_buffer.addr && dax_ctx->scratch_buffer.addr) + user->allocated = true; + else + user->allocated = false; + + k_spin_unlock(&inst_mgr.lock, key); + + comp_info(mod->dev, "added user %#x, priority %d", + adapter_data->comp_id, adapter_data->priority); + return 0; +} + +int dax_unregister_user(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct dax_user *user = NULL; + k_spinlock_key_t key; + + key = k_spin_lock(&inst_mgr.lock); + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id == adapter_data->comp_id) { + user = &inst_mgr.users[i]; + break; + } + } + + if (!user) { + k_spin_unlock(&inst_mgr.lock, key); + return -EINVAL; + } + k_spin_unlock(&inst_mgr.lock, key); + + destroy_instance(mod); + adapter_data->priority = DAX_USER_PRIORITY_DEFAULT; + + key = k_spin_lock(&inst_mgr.lock); + user->id = DAX_USER_ID_INVALID; + user->priority = DAX_USER_PRIORITY_DEFAULT; + user->allocated = false; + k_spin_unlock(&inst_mgr.lock, key); + + comp_info(mod->dev, "removed user %#x", adapter_data->comp_id); + return 0; +} + +int dax_check_and_update_instance(struct processing_module *mod) +{ + k_spinlock_key_t key; + bool has_priority; + int ret = 0; + + key = k_spin_lock(&inst_mgr.lock); + /* Check whether any user that has higher priority is waiting for allocating instance + * memory (allocated == false), if is, current user should release its instance memory + * to make sure the higher priority user can allocate memory successfully. + */ + has_priority = check_priority_l(mod); + k_spin_unlock(&inst_mgr.lock, key); + + /* This section of logic do not need lock protection because + * it does not involve access to any shared resources. `has_priority` + * may be stale when using in if condition but it is OK, `update_alloc_state_l` + * will synchronize instance state which will be used in the next check phase. + */ + if (has_priority) + ret = establish_instance(mod); + else + ret = destroy_instance(mod); + + key = k_spin_lock(&inst_mgr.lock); + update_alloc_state_l(mod); + + /* Auto detect and update the available memory count */ + if (ret == -ENOMEM) { + inst_mgr.available_inst_cnt = 0; + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id != DAX_USER_ID_INVALID && + inst_mgr.users[i].allocated) { + inst_mgr.available_inst_cnt++; + } + } + } + k_spin_unlock(&inst_mgr.lock, key); + return ret; +} diff --git a/src/audio/module_adapter/module/dolby/dax_mock.c b/src/audio/module_adapter/module/dolby/dax_mock.c new file mode 100644 index 000000000000..c8889699a7e8 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax_mock.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE +// +// Copyright(c) 2025 Dolby Laboratories. All rights reserved. +// +// Author: Jun Lai <jun.lai@dolby.com> +// + +#include <dax_inf.h> +#include <rtos/string.h> + +#define PLACEHOLDER_BUF_SZ 8 + +uint32_t dax_query_persist_memory(struct sof_dax *dax_ctx) +{ + return PLACEHOLDER_BUF_SZ; +} + +uint32_t dax_query_scratch_memory(struct sof_dax *dax_ctx) +{ + return PLACEHOLDER_BUF_SZ; +} + +uint32_t dax_query_period_frames(struct sof_dax *dax_ctx) +{ + return 256; +} + +int dax_free(struct sof_dax *dax_ctx) +{ + return 0; +} + +int dax_init(struct sof_dax *dax_ctx) +{ + return 0; +} + +int dax_process(struct sof_dax *dax_ctx) +{ + uint32_t peroid_bytes = dax_query_period_frames(dax_ctx) * + dax_ctx->input_media_format.num_channels * + dax_ctx->input_media_format.bytes_per_sample; + + if (dax_ctx->input_buffer.avail < peroid_bytes || + dax_ctx->output_buffer.free < peroid_bytes) { + return 0; + } + memcpy_s((uint8_t *)dax_ctx->output_buffer.addr + dax_ctx->output_buffer.avail, + dax_ctx->output_buffer.free, + dax_ctx->input_buffer.addr, + peroid_bytes); + return peroid_bytes; +} + +int dax_set_param(uint32_t id, const void *val, uint32_t val_sz, struct sof_dax *dax_ctx) +{ + return 0; +} + +int dax_set_enable(int32_t enable, struct sof_dax *dax_ctx) +{ + return 0; +} + +int dax_set_volume(int32_t pregain, struct sof_dax *dax_ctx) +{ + return 0; +} + +int dax_set_device(int32_t out_device, struct sof_dax *dax_ctx) +{ + return 0; +} + +int dax_set_ctc_enable(int32_t enable, struct sof_dax *dax_ctx) +{ + return 0; +} + +const char *dax_get_version(void) +{ + return ""; +} + +void *dax_find_params(uint32_t query_id, + int32_t query_val, + uint32_t *query_sz, + struct sof_dax *dax_ctx) +{ + return NULL; +} diff --git a/src/audio/module_adapter/module/dolby/llext-wrap.c b/src/audio/module_adapter/module/dolby/llext-wrap.c new file mode 100644 index 000000000000..30c7be24e22b --- /dev/null +++ b/src/audio/module_adapter/module/dolby/llext-wrap.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. + +#include <stdint.h> +#include <errno.h> +#include <assert.h> +#include <rtos/symbol.h> + +/* + * Stubs that are needed for linkage of some applications or libraries + * that come from porting userspace code. Anyone porting should + * make sure that any code does not depend on working copies of these + * reentrant functions. We will fail for any caller. + */ + +struct stat; +struct _reent; + +size_t _read_r(struct _reent *ptr, int fd, char *buf, size_t cnt) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +size_t _write_r(struct _reent *ptr, int fd, char *buf, size_t cnt) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) +{ + errno = -ENOTSUP; + return NULL; +} + +int _lseek_r(struct _reent *ptr, int fd, int pos, int whence) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _kill_r(struct _reent *ptr, int pid, int sig) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _getpid_r(struct _reent *ptr) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _close_r(struct _reent *ptr, int fd) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +void _exit(int status) +{ + assert(0); + while (1) { + /* spin forever */ + } + /* NOTREACHED */ +} diff --git a/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt b/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt new file mode 100644 index 000000000000..377373ddc5b5 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright(c) 2025 Dolby Laboratories. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK) + sof_llext_build("dolby_dax_audio_processing" + SOURCES ../dax.c + ../dax_instance_manager.c + ../dax_mock.c + INCLUDES ${sof_top_dir}/third_party/include + ) +else() + sof_llext_build("dolby_dax_audio_processing" + SOURCES ../dax.c ../dax_instance_manager.c ../llext-wrap.c + INCLUDES ${sof_top_dir}/third_party/include + LIBS_PATH ${sof_top_dir}/third_party/lib/ + LIBS dax m c gcc + ) +endif() diff --git a/src/audio/module_adapter/module/dolby/llext/llext.toml.h b/src/audio/module_adapter/module/dolby/llext/llext.toml.h new file mode 100644 index 000000000000..74f92b85fb81 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/llext/llext.toml.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Dolby Laboratories. All rights reserved. + */ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../dax.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c new file mode 100644 index 000000000000..2989bceb160b --- /dev/null +++ b/src/audio/module_adapter/module/generic.c @@ -0,0 +1,956 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + +/* + * \file generic.c + * \brief Generic Codec API + * \author Marcin Rajwa <marcin.rajwa@linux.intel.com> + * + */ + +#include <rtos/symbol.h> +#include <sof/compiler_attributes.h> +#include <sof/objpool.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/data_blob.h> +#include <sof/lib/fast-get.h> +#include <sof/lib/vregion.h> +#include <sof/schedule/dp_schedule.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/header.h> +#include <ipc4/module.h> +#include <ipc4/pipeline.h> +#endif + +/* The __ZEPHYR__ condition is to keep cmocka tests working */ +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) +#define MEM_API_CHECK_THREAD(res) do { \ + if ((res)->rsrc_mngr != k_current_get()) \ + LOG_WRN("mngr %p != cur %p", (res)->rsrc_mngr, k_current_get()); \ +} while (0) +#else +#define MEM_API_CHECK_THREAD(res) +#endif + +LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); + +int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) +{ + int ret; + struct module_config *dst; + /* loadable module must use module adapter */ + struct processing_module *mod = comp_mod(dev); + struct module_data *md = &mod->priv; + + comp_dbg(dev, "entry"); + + if (!cfg || !size) { + comp_err(dev, "wrong input params! dev %zx, cfg %zx size %zu", + (size_t)dev, (size_t)cfg, size); + return -EINVAL; + } + + dst = &md->cfg; + + if (!dst->data) { + /* No space for config available yet, allocate now */ + dst->data = rballoc(SOF_MEM_FLAG_USER, size); + } else if (dst->size != size) { + /* The size allocated for previous config doesn't match the new one. + * Free old container and allocate new one. + */ + rfree(dst->data); + dst->data = rballoc(SOF_MEM_FLAG_USER, size); + } + if (!dst->data) { + comp_err(dev, "failed to allocate space for setup config."); + return -ENOMEM; + } + + ret = memcpy_s(dst->data, size, cfg, size); + assert(!ret); + + /* Config loaded, mark it as valid */ + dst->size = size; + dst->avail = true; + + comp_dbg(dev, "done"); + return ret; +} + +void mod_resource_init(struct processing_module *mod) +{ + struct module_resources *res = &mod->priv.resources; + + /* Init memory list */ + list_init(&res->objpool.list); + res->objpool.heap = res->alloc->heap; + res->objpool.vreg = res->alloc->vreg; + res->heap_usage = 0; + res->heap_high_water_mark = 0; +} + +int module_init(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + const struct module_interface *const interface = dev->drv->adapter_ops; + + comp_dbg(dev, "entry"); + +#if CONFIG_IPC_MAJOR_3 + if (mod->priv.state == MODULE_INITIALIZED) + return 0; + if (mod->priv.state > MODULE_INITIALIZED) + return -EPERM; +#endif + if (!interface) { + comp_err(dev, "module interface not defined"); + return -EIO; + } + + /* check interface, there must be one and only one of processing procedure */ + if (!interface->init || + (!!interface->process + !!interface->process_audio_stream + + !!interface->process_raw_data < 1)) { + comp_err(dev, "comp is missing mandatory interfaces"); + return -EIO; + } + +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) + mod->priv.resources.rsrc_mngr = k_current_get(); +#endif + /* Now we can proceed with module specific initialization */ +#if CONFIG_SOF_USERSPACE_APPLICATION + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) + ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_INIT_INSTANCE, NULL); + else +#endif + ret = interface->init(mod); + + if (ret) { + comp_err(dev, "error %d: module specific init failed", ret); + mod_free_all(mod); + return ret; + } + + comp_dbg(dev, "done"); +#if CONFIG_IPC_MAJOR_3 + mod->priv.state = MODULE_INITIALIZED; +#endif + + return 0; +} + +static struct module_resource *container_get(struct processing_module *mod) +{ + return objpool_alloc(&mod->priv.resources.objpool, sizeof(struct module_resource), 0); +} + +static void container_put(struct processing_module *mod, struct module_resource *container) +{ + objpool_free(&mod->priv.resources.objpool, container); +} + +#if CONFIG_USERSPACE +void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start) +{ + struct module_resources *res = &mod->priv.resources; + + if (res->alloc->vreg) { + vregion_mem_info(res->alloc->vreg, size, start); + } else if (res->alloc->heap) { + if (size) + *size = res->alloc->heap->heap.init_bytes; + + if (start) + *start = (uintptr_t)res->alloc->heap->heap.init_mem; + } +} +#endif + +/** + * Allocates aligned buffer memory block for module. + * @param mod Pointer to the module this memory block is allocated for. + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + * + * The allocated memory is automatically freed when the module is + * unloaded. The back-end, rballoc(), always aligns the memory to + * PLATFORM_DCACHE_ALIGN at the minimum. + */ +void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment) +{ + struct module_resources *res = &mod->priv.resources; + struct module_resource *container; + + MEM_API_CHECK_THREAD(res); + + container = container_get(mod); + if (!container) + return NULL; + + if (!size) { + comp_err(mod->dev, "requested allocation of 0 bytes."); + container_put(mod, container); + return NULL; + } + + /* Allocate buffer memory for module */ + void *ptr = sof_heap_alloc(res->alloc->heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_LARGE_BUFFER, + size, alignment); + + if (!ptr) { + comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.", + size, alignment, dev_comp_id(mod->dev)); + container_put(mod, container); + return NULL; + } + /* Store reference to allocated memory */ + container->ptr = ptr; + container->size = size; + container->type = MOD_RES_HEAP; + + res->heap_usage += size; + if (res->heap_usage > res->heap_high_water_mark) + res->heap_high_water_mark = res->heap_usage; + + return ptr; +} +EXPORT_SYMBOL(mod_balloc_align); + +/** + * Allocates aligned memory block with flags for module. + * @param mod Pointer to the module this memory block is allocated for. + * @param flags Allocator flags. + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + * + * The allocated memory is automatically freed when the module is unloaded. + */ +void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, + size_t alignment) +{ + struct module_resources *res = &mod->priv.resources; + struct module_resource *container; + + MEM_API_CHECK_THREAD(res); + + container = container_get(mod); + if (!container) + return NULL; + + if (!size) { + comp_err(mod->dev, "requested allocation of 0 bytes."); + container_put(mod, container); + return NULL; + } + + /* Allocate memory for module */ + void *ptr; + + if (!res->alloc->vreg) + ptr = sof_heap_alloc(res->alloc->heap, flags, size, alignment); + else if (flags & SOF_MEM_FLAG_COHERENT) + ptr = vregion_alloc_coherent_align(res->alloc->vreg, VREGION_MEM_TYPE_INTERIM, + size, alignment); + else + ptr = vregion_alloc_align(res->alloc->vreg, VREGION_MEM_TYPE_INTERIM, + size, alignment); + + if (!ptr) { + comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.", + size, alignment, dev_comp_id(mod->dev)); + container_put(mod, container); + return NULL; + } + /* Store reference to allocated memory */ + container->ptr = ptr; + container->size = size; + container->type = MOD_RES_HEAP; + + res->heap_usage += size; + if (res->heap_usage > res->heap_high_water_mark) + res->heap_high_water_mark = res->heap_usage; + + return ptr; +} +EXPORT_SYMBOL(z_impl_mod_alloc_ext); + +/** + * Creates a blob handler and releases it when the module is unloaded + * @param mod Pointer to module this memory block is allocated for. + * @return Pointer to the created data blob handler + * + * Like comp_data_blob_handler_new() but the handler is automatically freed. + */ +#if CONFIG_COMP_BLOB +struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod) +{ + struct module_resources * __maybe_unused res = &mod->priv.resources; + struct comp_data_blob_handler *bhp; + struct module_resource *container; + + MEM_API_CHECK_THREAD(res); + + container = container_get(mod); + if (!container) + return NULL; + + bhp = comp_data_blob_handler_new_ext(mod->dev, false, NULL, NULL); + if (!bhp) { + container_put(mod, container); + return NULL; + } + + container->bhp = bhp; + container->size = 0; + container->type = MOD_RES_BLOB_HANDLER; + + return bhp; +} +EXPORT_SYMBOL(mod_data_blob_handler_new); +#endif + +/** + * Make a module associated shared SRAM copy of DRAM read-only data. + * @param mod Pointer to module this copy is allocated for. + * @return Pointer to the SRAM copy. + * + * Like fast_get() but the handler is automatically freed. + */ +#if CONFIG_FAST_GET +const void *z_impl_mod_fast_get(struct processing_module *mod, const void * const dram_ptr, + size_t size) +{ + struct module_resources *res = &mod->priv.resources; + struct module_resource *container; + const void *ptr; + + MEM_API_CHECK_THREAD(res); + + container = container_get(mod); + if (!container) + return NULL; + + ptr = fast_get(res->alloc, dram_ptr, size); + if (!ptr) { + container_put(mod, container); + return NULL; + } + + container->sram_ptr = ptr; + container->size = 0; + container->type = MOD_RES_FAST_GET; + + return ptr; +} +EXPORT_SYMBOL(z_impl_mod_fast_get); +#endif + +static int free_contents(struct processing_module *mod, struct module_resource *container) +{ + struct module_resources *res = &mod->priv.resources; +#if CONFIG_FAST_GET + struct k_mem_domain *mdom; +#endif + + switch (container->type) { + case MOD_RES_HEAP: + if (res->alloc->vreg) + vregion_free(res->alloc->vreg, container->ptr); + else + sof_heap_free(res->alloc->heap, container->ptr); + res->heap_usage -= container->size; + return 0; +#if CONFIG_COMP_BLOB + case MOD_RES_BLOB_HANDLER: + comp_data_blob_handler_free(container->bhp); + return 0; +#endif +#if CONFIG_FAST_GET + case MOD_RES_FAST_GET: +#if CONFIG_USERSPACE + mdom = mod->mdom; +#else + mdom = NULL; +#endif + fast_put(res->alloc, mdom, container->sram_ptr); + return 0; +#endif + default: + comp_err(mod->dev, "Unknown resource type: %d", container->type); + } + return -EINVAL; +} + +struct mod_res_cb_arg { + struct processing_module *mod; + const void *ptr; +}; + +static bool mod_res_free(void *data, void *arg) +{ + struct mod_res_cb_arg *cb_arg = arg; + struct module_resource *container = data; + + if (cb_arg->ptr && container->ptr != cb_arg->ptr) + return false; + + int ret = free_contents(cb_arg->mod, container); + + if (ret < 0) + comp_err(cb_arg->mod->dev, "Cannot free allocation %p", cb_arg->ptr); + + container_put(cb_arg->mod, container); + + /* cb_arg->ptr == NULL means, that we're freeing all. Continue iterating */ + return !!cb_arg->ptr; +} + +/** + * Frees the memory block removes it from module's book keeping. + * @param mod Pointer to module this memory block was allocated for. + * @param ptr Pointer to the memory block. + */ +int z_impl_mod_free(struct processing_module *mod, const void *ptr) +{ + struct module_resources *res = &mod->priv.resources; + + MEM_API_CHECK_THREAD(res); + if (!ptr) + return 0; + + /* Find which container holds this memory */ + struct mod_res_cb_arg cb_arg = {mod, ptr}; + int ret = objpool_iterate(&res->objpool, mod_res_free, &cb_arg); + + if (ret < 0) + comp_err(mod->dev, "error: could not find memory pointed by %p", ptr); + + return ret; +} +EXPORT_SYMBOL(z_impl_mod_free); + +#ifdef CONFIG_USERSPACE +#include <zephyr/internal/syscall_handler.h> + +#if CONFIG_FAST_GET +const void *z_vrfy_mod_fast_get(struct processing_module *mod, const void * const dram_ptr, + size_t size) +{ + size_t h_size = 0; + uintptr_t h_start; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod))); + mod_heap_info(mod, &h_size, &h_start); + if (h_size) + K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size)); + K_OOPS(K_SYSCALL_MEMORY_READ(dram_ptr, size)); + + return z_impl_mod_fast_get(mod, dram_ptr, size); +} +#include <zephyr/syscalls/mod_fast_get_mrsh.c> +#endif + +void *z_vrfy_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, + size_t alignment) +{ + size_t h_size = 0; + uintptr_t h_start; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod))); + mod_heap_info(mod, &h_size, &h_start); + if (h_size) + K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size)); + + return z_impl_mod_alloc_ext(mod, flags, size, alignment); +} +#include <zephyr/syscalls/mod_alloc_ext_mrsh.c> + +int z_vrfy_mod_free(struct processing_module *mod, const void *ptr) +{ + size_t h_size = 0; + uintptr_t h_start; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod))); + mod_heap_info(mod, &h_size, &h_start); + if (h_size) + K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size)); + + return z_impl_mod_free(mod, ptr); +} +#include <zephyr/syscalls/mod_free_mrsh.c> +#endif + +#if CONFIG_COMP_BLOB +void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh) +{ + mod_free(mod, (void *)dbh); +} +EXPORT_SYMBOL(mod_data_blob_handler_free); +#endif + +#if CONFIG_FAST_GET +void mod_fast_put(struct processing_module *mod, const void *sram_ptr) +{ + mod_free(mod, sram_ptr); +} +EXPORT_SYMBOL(mod_fast_put); +#endif + +int module_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + const struct module_interface *const ops = dev->drv->adapter_ops; + + comp_dbg(dev, "entry"); + +#if CONFIG_IPC_MAJOR_3 + if (mod->priv.state == MODULE_IDLE) + return 0; + if (mod->priv.state < MODULE_INITIALIZED) + return -EPERM; +#endif + if (ops->prepare) { + int ret; + +#if CONFIG_SOF_USERSPACE_APPLICATION + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + const union scheduler_dp_thread_ipc_param param = { + .pipeline_state = { + .trigger_cmd = COMP_TRIGGER_PREPARE, + .state = SOF_IPC4_PIPELINE_STATE_RUNNING, + .n_sources = num_of_sources, + .sources = sources, + .n_sinks = num_of_sinks, + .sinks = sinks, + }, + }; + ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, ¶m); + } else +#endif + ret = ops->prepare(mod, sources, num_of_sources, sinks, num_of_sinks); + + if (ret) { + comp_err(dev, "error %d: module specific prepare failed", ret); + return ret; + } + } + + /* After prepare is done we no longer need runtime configuration + * as it has been applied during the procedure - it is safe to + * free it. + */ + rfree(md->cfg.data); + + md->cfg.avail = false; + md->cfg.data = NULL; + +#if CONFIG_IPC_MAJOR_3 + md->state = MODULE_IDLE; +#endif + comp_dbg(dev, "done"); + + return 0; +} + +int module_process_legacy(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 comp_dev *dev = mod->dev; + const struct module_interface *const ops = dev->drv->adapter_ops; + int ret; + + comp_dbg(dev, "entry"); + +#if CONFIG_IPC_MAJOR_3 + struct module_data *md = &mod->priv; + + if (md->state != MODULE_IDLE) { + comp_err(dev, "wrong state %d", md->state); + return -EPERM; + } + + /* set state to processing */ + md->state = MODULE_PROCESSING; +#endif + if (IS_PROCESSING_MODE_AUDIO_STREAM(mod)) + ret = ops->process_audio_stream(mod, input_buffers, num_input_buffers, + output_buffers, num_output_buffers); + else if (IS_PROCESSING_MODE_RAW_DATA(mod)) + ret = ops->process_raw_data(mod, input_buffers, num_input_buffers, + output_buffers, num_output_buffers); + else + ret = -EOPNOTSUPP; + + if (ret && ret != -ENOSPC && ret != -ENODATA) { + comp_err(dev, "error %d", ret); + return ret; + } + + comp_dbg(dev, "done"); + +#if CONFIG_IPC_MAJOR_3 + /* reset state to idle */ + md->state = MODULE_IDLE; +#endif + return 0; +} + +int module_process_sink_src(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) + +{ + struct comp_dev *dev = mod->dev; + const struct module_interface *const ops = dev->drv->adapter_ops; + int ret; + + comp_dbg(dev, "entry"); + +#if CONFIG_IPC_MAJOR_3 + struct module_data *md = &mod->priv; + if (md->state != MODULE_IDLE) { + comp_err(dev, "wrong state %d", md->state); + return -EPERM; + } + + /* set state to processing */ + md->state = MODULE_PROCESSING; +#endif + assert(ops->process); + ret = ops->process(mod, sources, num_of_sources, sinks, num_of_sinks); + + if (ret && ret != -ENOSPC && ret != -ENODATA) { + comp_err(dev, "error %d", ret); + return ret; + } + + comp_dbg(dev, "done"); + +#if CONFIG_IPC_MAJOR_3 + /* reset state to idle */ + md->state = MODULE_IDLE; +#endif + return 0; +} + +int module_reset(struct processing_module *mod) +{ + int ret; + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + struct module_data *md = &mod->priv; + +#if CONFIG_IPC_MAJOR_3 + /* if the module was never prepared, no need to reset */ + if (md->state < MODULE_IDLE) + return 0; +#endif + + /* cancel task if DP task*/ + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP && mod->dev->task && + !IS_ENABLED(CONFIG_SOF_USERSPACE_APPLICATION) && + !IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD)) + schedule_task_cancel(mod->dev->task); + + if (ops->reset) { +#if CONFIG_SOF_USERSPACE_APPLICATION + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + const union scheduler_dp_thread_ipc_param param = { + .pipeline_state.trigger_cmd = COMP_TRIGGER_STOP, + }; + ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, ¶m); + } else +#endif + ret = ops->reset(mod); + + if (ret) { + if (ret != PPL_STATUS_PATH_STOP) + comp_err(mod->dev, + "error %d: module specific reset() failed", ret); + return ret; + } + } + + md->cfg.avail = false; + md->cfg.size = 0; + rfree(md->cfg.data); + md->cfg.data = NULL; + +#if CONFIG_IPC_MAJOR_3 + /* + * reset the state to allow the module's prepare callback to be invoked again for the + * subsequent triggers + */ + md->state = MODULE_INITIALIZED; +#endif + return 0; +} + +/** + * Frees all the resources registered for this module + * @param mod Pointer to module that should have its resource freed. + * + * This function is called automatically when the module is unloaded. + */ +void mod_free_all(struct processing_module *mod) +{ + struct module_resources *res = &mod->priv.resources; + + MEM_API_CHECK_THREAD(res); + + /* Free all contents found in used containers */ + struct mod_res_cb_arg cb_arg = {mod, NULL}; + + objpool_iterate(&res->objpool, mod_res_free, &cb_arg); + objpool_prune(&res->objpool); + + /* Make sure resource lists and accounting are reset */ + mod_resource_init(mod); +} + +int module_free(struct processing_module *mod) +{ + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + struct module_data *md = &mod->priv; + int ret = 0; + + if (ops->free && (mod->dev->ipc_config.proc_domain != COMP_PROCESSING_DOMAIN_DP || + !IS_ENABLED(CONFIG_SOF_USERSPACE_APPLICATION))) { + ret = ops->free(mod); + if (ret) + comp_warn(mod->dev, "error: %d", ret); + } + + /* Free all memory shared by module_adapter & module */ + md->cfg.avail = false; + md->cfg.size = 0; + rfree(md->cfg.data); + md->cfg.data = NULL; + if (md->runtime_params) { + rfree(md->runtime_params); + md->runtime_params = NULL; + } +#if CONFIG_IPC_MAJOR_3 + md->state = MODULE_DISABLED; +#endif + return ret; +} + +/* + * \brief Set module configuration - Common method to assemble large configuration message + * \param[in] mod - struct processing_module pointer + * \param[in] config_id - Configuration ID + * \param[in] pos - position of the fragment in the large message + * \param[in] data_offset_size: size of the whole configuration if it is the first fragment or the + * only fragment. Otherwise, it is the offset of the fragment in the + * whole configuration. + * \param[in] fragment: configuration fragment buffer + * \param[in] fragment_size: size of @fragment + * \params[in] response: optional response buffer to fill + * \params[in] response_size: size of @response + * + * \return: 0 upon success or error upon failure + */ +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_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; + uint8_t *dst; + int ret; + + switch (pos) { + case MODULE_CFG_FRAGMENT_FIRST: + case MODULE_CFG_FRAGMENT_SINGLE: + /* + * verify input params & allocate memory for the config blob when the first + * fragment arrives + */ + md->new_cfg_size = data_offset_size; + + /* Check that there is no previous request in progress */ + if (md->runtime_params) { + comp_err(dev, "error: busy with previous request"); + return -EBUSY; + } + + if (!md->new_cfg_size) + return 0; + + if (md->new_cfg_size > CONFIG_MODULE_MAX_BLOB_SIZE) { + comp_err(dev, "error: blob size is too big cfg size %zu, allowed %d", + md->new_cfg_size, CONFIG_MODULE_MAX_BLOB_SIZE); + return -EINVAL; + } + + /* Allocate buffer for new params */ + md->runtime_params = rballoc(SOF_MEM_FLAG_USER, md->new_cfg_size); + if (!md->runtime_params) { + comp_err(dev, "space allocation for new params failed"); + return -ENOMEM; + } + + memset(md->runtime_params, 0, md->new_cfg_size); + break; + default: + if (!md->runtime_params) { + comp_err(dev, "error: no memory available for runtime params in consecutive load"); + return -EIO; + } + + /* set offset for intermediate and last fragments */ + offset = data_offset_size; + break; + } + + dst = (uint8_t *)md->runtime_params + offset; + + ret = memcpy_s(dst, md->new_cfg_size - offset, fragment, fragment_size); + if (ret < 0) { + comp_err(dev, "error: %d failed to copy fragment", ret); + return ret; + } + + /* return as more fragments of config data expected */ + if (pos == MODULE_CFG_FRAGMENT_MIDDLE || pos == MODULE_CFG_FRAGMENT_FIRST) + return 0; + + /* config fully copied, now load it */ + ret = module_load_config(dev, md->runtime_params, md->new_cfg_size); + if (ret) + comp_err(dev, "error %d: config failed", ret); + else + comp_dbg(dev, "config load successful"); + + md->new_cfg_size = 0; + + if (md->runtime_params) + rfree(md->runtime_params); + md->runtime_params = NULL; + + return ret; +} +EXPORT_SYMBOL(module_set_configuration); + +int module_bind(struct processing_module *mod, struct bind_info *bind_data) +{ + int ret; + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + switch (bind_data->bind_type) { + case COMP_BIND_TYPE_SINK: + ret = sink_bind(bind_data->sink, mod); + break; + case COMP_BIND_TYPE_SOURCE: + ret = source_bind(bind_data->source, mod); + break; + default: + ret = -EINVAL; + } + if (ret) + return ret; + + if (ops->bind) { +#if CONFIG_SOF_USERSPACE_APPLICATION + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + const union scheduler_dp_thread_ipc_param param = { + .bind_data = bind_data, + }; + ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_BIND, ¶m); + } else +#endif + ret = ops->bind(mod, bind_data); + } + + return ret; +} + +int module_unbind(struct processing_module *mod, struct bind_info *unbind_data) +{ + int ret; + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + switch (unbind_data->bind_type) { + case COMP_BIND_TYPE_SINK: + ret = sink_unbind(unbind_data->sink); + break; + case COMP_BIND_TYPE_SOURCE: + ret = source_unbind(unbind_data->source); + break; + default: + ret = -EINVAL; + } + if (ret) + return ret; + + if (ops->unbind) { +#if CONFIG_SOF_USERSPACE_APPLICATION + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + const union scheduler_dp_thread_ipc_param param = { + .bind_data = unbind_data, + }; + ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_UNBIND, ¶m); + } else +#endif + ret = ops->unbind(mod, unbind_data); + } + + return ret; +} + +void module_update_buffer_position(struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames) +{ + struct audio_stream *source = input_buffers->data; + struct audio_stream *sink = output_buffers->data; + + input_buffers->consumed += audio_stream_frame_bytes(source) * frames; + output_buffers->size += audio_stream_frame_bytes(sink) * frames; +} +EXPORT_SYMBOL(module_update_buffer_position); + +uint32_t module_get_deadline(struct processing_module *mod) +{ + uint32_t deadline; + + /* LL modules have no deadline - it is always "now" */ + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + return 0; + + /* startup condition - set deadline to "unknown" */ + if (mod->dp_startup_delay) + return UINT32_MAX / 2; + + deadline = UINT32_MAX; + /* calculate the shortest LFT for all sinks */ + for (size_t i = 0; i < mod->num_of_sinks; i++) { + uint32_t sink_lft = sink_get_last_feeding_time(mod->sinks[i]); + + deadline = MIN(deadline, sink_lft); + } + + return deadline; +} diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c new file mode 100644 index 000000000000..589a25e33887 --- /dev/null +++ b/src/audio/module_adapter/module/modules.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@linux.intel.com> + */ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/modules.h> +#include <rtos/userspace_helper.h> +#include <utilities/array.h> +#include <iadk_module_adapter.h> +#include <sof/lib_manager.h> +#include <sof/audio/module_adapter/module/module_interface.h> + +/* Intel module adapter is an extension to SOF module adapter component that allows to integrate + * modules developed under IADK (Intel Audio Development Kit) Framework. IADK modules uses uniform + * set of interfaces and are linked into separate library. These modules are loaded in runtime + * through library_manager and then after registration into SOF component infrastructure are + * interfaced through module adapter API. + * + * There is variety of modules developed under IADK Framework by 3rd party vendors. The assumption + * here is to integrate these modules with SOF infrastructure without modules code modifications. + * Another assumption is that the 3rd party modules should be loaded in runtime without need + * of rebuild the base firmware. + * Therefore C++ function, structures and variables definition are here kept with original form from + * IADK Framework. This provides binary compatibility for already developed 3rd party modules. + * + * Since IADK modules uses ProcessingModuleInterface to control/data transfer and AdspSystemService + * to use base FW services from internal module code, there is a communication shim layer defined + * in intel directory. + * + * Since ProcessingModuleInterface consists of virtual functions, there are C++ -> C iadk_wrappers + * defined to access the interface calls from SOF code. + * + * There are three entities in intel module adapter package: + * - System Agent - A mediator to allow the custom module to interact with the base SOF FW. + * It calls IADK module entry point and provides all necessary information to + * connect both sides of ProcessingModuleInterface and System Service. + * - System Service - exposes of SOF base FW services to the module. + * - Processing Module Adapter - SOF base FW side of ProcessingModuleInterface API + */ + +LOG_MODULE_REGISTER(sof_modules, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(modules); + +/** + * \brief modules_init. + * \param[in] mod - processing module pointer. + * + * \return: zero on success + * error code on failure + */ +static int modules_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + const struct ipc4_base_module_cfg *src_cfg = &md->cfg.base_cfg; + + /* At this point module resources are allocated and it is moved to L2 memory. */ + comp_info(dev, "entry"); + + md->mpd.in_buff_size = src_cfg->ibs; + md->mpd.out_buff_size = src_cfg->obs; + + mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; + return iadk_wrapper_init(module_get_private_data(mod)); +} + +/** + * \brief modules_prepare. + * \param[in] mod - processing module pointer. + * + * \return: zero on success + * error code on failure + * + * \note: We use ipc4_base_module_cfg since this is only what we know about module + * configuration. Its internal structure is proprietary to the module implementation. + * There is one assumption - all IADK modules utilize IPC4 protocol. + */ +static int modules_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + + comp_info(dev, "entry"); + + return iadk_wrapper_prepare(module_get_private_data(mod)); +} + +static int modules_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + return iadk_wrapper_process(module_get_private_data(mod), sources, + num_of_sources, sinks, num_of_sinks); +} + +/** + * \brief modules_free. + * \param[in] mod - processing module pointer. + * + * \return: zero on success + * error code on failure + */ +static int modules_free(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + int ret; + + comp_info(dev, "entry"); + ret = iadk_wrapper_free(module_get_private_data(mod)); + if (ret) + comp_err(dev, "iadk_wrapper_free failed with error: %d", ret); + + return ret; +} + +/* + * \brief modules_set_configuration - Common method to assemble large configuration message + * \param[in] mod - struct processing_module pointer + * \param[in] config_id - Configuration ID + * \param[in] pos - position of the fragment in the large message + * \param[in] data_offset_size: size of the whole configuration if it is the first fragment or the + * only fragment. Otherwise, it is the offset of the fragment in the whole + * configuration. + * \param[in] fragment: configuration fragment buffer + * \param[in] fragment_size: size of @fragment + * \params[in] response: optional response buffer to fill + * \params[in] response_size: size of @response + * + * \return: 0 upon success or error upon failure + */ +static int modules_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, const uint8_t *fragment, + size_t fragment_size, uint8_t *response, + size_t response_size) +{ + return iadk_wrapper_set_configuration(module_get_private_data(mod), config_id, pos, + data_offset_size, fragment, fragment_size, + response, response_size); +} + +/* + * \brief modules_get_configuration - Common method to retrieve module configuration + * \param[in] mod - struct processing_module pointer + * \param[in] config_id - Configuration ID + * \param[in] pos - position of the fragment in the large message + * \param[in] data_offset_size: size of the whole configuration if it is the first fragment or the + * only fragment. Otherwise, it is the offset of the fragment in the whole configuration. + * \param[in] fragment: configuration fragment buffer + * \param[in] fragment_size: size of @fragment + * + * \return: 0 upon success or error upon failure + */ +static int modules_get_configuration(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, + size_t fragment_size) +{ + return iadk_wrapper_get_configuration(module_get_private_data(mod), config_id, + MODULE_CFG_FRAGMENT_SINGLE, data_offset_size, + fragment, &fragment_size); +} + +/** + * \brief Sets the processing mode for the module. + * \param[in] mod - struct processing_module pointer + * \param[in] mode - module processing mode to be set + * + * \return: 0 upon success or error upon failure + */ +static int modules_set_processing_mode(struct processing_module *mod, + enum module_processing_mode mode) +{ + return iadk_wrapper_set_processing_mode(module_get_private_data(mod), mode); +} + +/** + * \brief Gets the processing mode actually set for the module. + * \param[in] mod - struct processing_module pointer + * + * \return: enum - module processing mode value + */ +static enum module_processing_mode modules_get_processing_mode(struct processing_module *mod) +{ + return iadk_wrapper_get_processing_mode(module_get_private_data(mod)); +} + +/** + * \brief Upon call to this method the ADSP system requires the module to reset its + * internal state into a well-known initial value. + * \param[in] mod - struct processing_module pointer + * + * \return: 0 upon success or error upon failure + */ +static int modules_reset(struct processing_module *mod) +{ + return iadk_wrapper_reset(module_get_private_data(mod)); +} + +/* Processing Module Adapter API*/ +APP_TASK_DATA const struct module_interface processing_module_adapter_interface = { + .init = modules_init, + .prepare = modules_prepare, + .process = modules_process, + .set_processing_mode = modules_set_processing_mode, + .get_processing_mode = modules_get_processing_mode, + .set_configuration = modules_set_configuration, + .get_configuration = modules_get_configuration, + .reset = modules_reset, + .free = modules_free, +}; diff --git a/src/audio/module_adapter/module/passthrough.c b/src/audio/module_adapter/module/passthrough.c new file mode 100644 index 000000000000..4a0a8eb2a655 --- /dev/null +++ b/src/audio/module_adapter/module/passthrough.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2020 NXP +// +// Author: Daniel Baluta <daniel.baluta@nxp.com> +// +// Passthrough codec implementation to demonstrate Codec Adapter API + +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/init.h> + +LOG_MODULE_REGISTER(passthrough, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(passthrough); + +static int passthrough_codec_init(struct processing_module *mod) +{ + comp_info(mod->dev, "entry"); + return 0; +} + +static int passthrough_codec_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct comp_buffer *source = comp_dev_get_first_data_producer(dev); + + comp_info(dev, "entry"); + + mod->period_bytes = audio_stream_period_bytes(&source->stream, dev->frames); + + codec->mpd.in_buff = rballoc(SOF_MEM_FLAG_USER, mod->period_bytes); + if (!codec->mpd.in_buff) { + comp_err(dev, "Failed to alloc in_buff"); + return -ENOMEM; + } + codec->mpd.in_buff_size = mod->period_bytes; + + codec->mpd.out_buff = rballoc(SOF_MEM_FLAG_USER, mod->period_bytes); + if (!codec->mpd.out_buff) { + comp_err(dev, "Failed to alloc out_buff"); + rfree(codec->mpd.in_buff); + return -ENOMEM; + } + codec->mpd.out_buff_size = mod->period_bytes; + + return 0; +} + +static int passthrough_codec_init_process(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + codec->mpd.produced = 0; + codec->mpd.consumed = 0; + codec->mpd.init_done = 1; + + return 0; +} + +static int passthrough_codec_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + const void *src_ptr, *src_buf_start; + void *snk_ptr, *snk_buf_start; + size_t src_buf_size, snk_buf_size; + size_t n_bytes = codec->mpd.in_buff_size; + size_t size_to_wrap; + int err; + + comp_dbg(dev, "entry"); + + /* Proceed only if we have enough data to fill the module buffer completely */ + if (source_get_data_available(sources[0]) < n_bytes) { + comp_dbg(dev, "not enough data to process"); + return -ENODATA; + } + + if (!codec->mpd.init_done) + passthrough_codec_init_process(mod); + + err = source_get_data(sources[0], n_bytes, &src_ptr, &src_buf_start, &src_buf_size); + if (err) + return err; + + /* src_buf_size is the total ring buffer size; handle wrap when copying to in_buff */ + size_to_wrap = (const uint8_t *)src_buf_start + src_buf_size - (const uint8_t *)src_ptr; + if (n_bytes <= size_to_wrap) { + memcpy_s(codec->mpd.in_buff, n_bytes, src_ptr, n_bytes); + } else { + memcpy_s(codec->mpd.in_buff, n_bytes, src_ptr, size_to_wrap); + memcpy_s((uint8_t *)codec->mpd.in_buff + size_to_wrap, n_bytes - size_to_wrap, + src_buf_start, n_bytes - size_to_wrap); + } + source_release_data(sources[0], n_bytes); + + memcpy_s(codec->mpd.out_buff, codec->mpd.out_buff_size, codec->mpd.in_buff, n_bytes); + + err = sink_get_buffer(sinks[0], n_bytes, &snk_ptr, &snk_buf_start, &snk_buf_size); + if (err) + return err; + + /* snk_buf_size is the total ring buffer size; handle wrap when copying from out_buff */ + size_to_wrap = (uint8_t *)snk_buf_start + snk_buf_size - (uint8_t *)snk_ptr; + if (n_bytes <= size_to_wrap) { + memcpy_s(snk_ptr, n_bytes, codec->mpd.out_buff, n_bytes); + } else { + memcpy_s(snk_ptr, n_bytes, codec->mpd.out_buff, size_to_wrap); + memcpy_s(snk_buf_start, n_bytes - size_to_wrap, + (const uint8_t *)codec->mpd.out_buff + size_to_wrap, + n_bytes - size_to_wrap); + } + sink_commit_buffer(sinks[0], n_bytes); + + return 0; +} + +static int passthrough_codec_reset(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + + comp_info(mod->dev, "entry"); + + rfree(codec->mpd.in_buff); + rfree(codec->mpd.out_buff); + return 0; +} + +static int passthrough_codec_free(struct processing_module *mod) +{ + comp_info(mod->dev, "entry"); + + /* Nothing to do */ + return 0; +} + +static const struct module_interface passthrough_interface = { + .init = passthrough_codec_init, + .prepare = passthrough_codec_prepare, + .process = passthrough_codec_process, + .reset = passthrough_codec_reset, + .free = passthrough_codec_free +}; + +DECLARE_TR_CTX(passthrough_tr, SOF_UUID(passthrough_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(passthrough_interface, passthrough_uuid, passthrough_tr); +SOF_MODULE_INIT(passthrough, sys_comp_module_passthrough_interface_init); diff --git a/src/audio/module_adapter/module/waves/llext/CMakeLists.txt b/src/audio/module_adapter/module/waves/llext/CMakeLists.txt new file mode 100644 index 000000000000..63104b8d71a0 --- /dev/null +++ b/src/audio/module_adapter/module/waves/llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_WAVES_CODEC_STUB) +sof_llext_build("waves" + SOURCES ../waves.c + ../maxx_stub.c +) +else() +message(FATAL_ERROR "Add library linking support in src/audio/module_adapter/module/waves/llext/CMakeLists.txt") +endif() diff --git a/src/audio/module_adapter/module/waves/llext/llext.toml.h b/src/audio/module_adapter/module/waves/llext/llext.toml.h new file mode 100644 index 000000000000..af98b94af57d --- /dev/null +++ b/src/audio/module_adapter/module/waves/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../waves.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/module_adapter/module/waves/maxx_stub.c b/src/audio/module_adapter/module/waves/maxx_stub.c new file mode 100644 index 000000000000..fb9e59734194 --- /dev/null +++ b/src/audio/module_adapter/module/waves/maxx_stub.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Google Inc LLC. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org> +// + +#include <sof/audio/MaxxEffect/Initialize/MaxxEffect_Initialize.h> +#include <sof/audio/MaxxEffect/Process/MaxxEffect_Process.h> +#include <sof/audio/MaxxEffect/Process/MaxxEffect_Reset.h> +#include <sof/audio/MaxxEffect/Control/RPC/MaxxEffect_RPC_Server.h> +#include <sof/audio/MaxxEffect/Control/Direct/MaxxEffect_Revision.h> + +MaxxStatus_t MaxxEffect_GetMessageMaxSize( + MaxxEffect_t* effect, + uint32_t* requestBytes, + uint32_t* responseBytes) +{ + return 0; +} + +MaxxStatus_t MaxxEffect_Process( + MaxxEffect_t* effect, + MaxxStream_t* const inputStreams[], + MaxxStream_t* const outputStreams[]) +{ + return 0; +} + +MaxxStatus_t MaxxEffect_Reset( + MaxxEffect_t* effect) +{ + return 0; +} + +MaxxStatus_t MaxxEffect_GetEffectSize( + uint32_t* bytes) +{ + return 0; +} + +MaxxStatus_t MaxxEffect_Initialize( + MaxxEffect_t* effect, + MaxxStreamFormat_t* const inputFormats[], + uint32_t inputFormatsCount, + MaxxStreamFormat_t* const outputFormats[], + uint32_t outputFormatsCount) +{ + return 0; +} + +MaxxStatus_t MaxxEffect_Message( + MaxxEffect_t* effect, + const void* request, + uint32_t requestBytes, + void* response, + uint32_t* responseBytes) +{ + return 0; +} + +MaxxStatus_t MaxxEffect_Revision_Get( + MaxxEffect_t* effect, + const char** revision, + uint32_t* bytes) +{ + return 0; +} diff --git a/src/audio/module_adapter/module/waves/waves.c b/src/audio/module_adapter/module/waves/waves.c new file mode 100644 index 000000000000..6616527d2308 --- /dev/null +++ b/src/audio/module_adapter/module/waves/waves.c @@ -0,0 +1,926 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Waves Audio Ltd. All rights reserved. +// +// Author: Oleksandr Strelchenko <oleksandr.strelchenko@waves.com> +// + +#include <rtos/init.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/debug/debug.h> +#include <sof/compiler_attributes.h> +#include <sof/audio/MaxxEffect/Initialize/MaxxEffect_Initialize.h> +#include <sof/audio/MaxxEffect/Process/MaxxEffect_Process.h> +#include <sof/audio/MaxxEffect/Process/MaxxEffect_Reset.h> +#include <sof/audio/MaxxEffect/Control/RPC/MaxxEffect_RPC_Server.h> +#include <sof/audio/MaxxEffect/Control/Direct/MaxxEffect_Revision.h> + +#define MAX_CONFIG_SIZE_BYTES (8192) +#define NUM_IO_STREAMS (1) + +SOF_DEFINE_REG_UUID(waves); + +LOG_MODULE_REGISTER(waves, CONFIG_SOF_LOG_LEVEL); + +struct waves_codec_data { + uint32_t sample_rate; + uint32_t buffer_bytes; + uint32_t buffer_samples; + uint32_t sample_size_in_bytes; + uint64_t reserved; + + MaxxEffect_t *effect; + uint32_t effect_size; + MaxxStreamFormat_t i_format; + MaxxStreamFormat_t o_format; + MaxxStream_t i_stream; + MaxxStream_t o_stream; + MaxxBuffer_t i_buffer; + MaxxBuffer_t o_buffer; + uint32_t response_max_bytes; + uint32_t request_max_bytes; + void *response; + uint32_t config_blob_size; + void *config_blob; + bool initialized; +}; + +enum waves_codec_params { + PARAM_NOP = 0, + PARAM_MESSAGE = 1, + PARAM_REVISION = 2 +}; + +/* convert MaxxBuffer_Format_t to number of bytes it requires */ +static int32_t sample_format_convert_to_bytes(MaxxBuffer_Format_t format) +{ + int32_t res; + + switch (format) { + case MAXX_BUFFER_FORMAT_Q1_15: + res = sizeof(uint16_t); + break; + case MAXX_BUFFER_FORMAT_Q1_23: + res = 3; /* 3 bytes */ + break; + case MAXX_BUFFER_FORMAT_Q9_23: + COMPILER_FALLTHROUGH; + case MAXX_BUFFER_FORMAT_Q1_31: + COMPILER_FALLTHROUGH; + case MAXX_BUFFER_FORMAT_Q5_27: + res = sizeof(uint32_t); + break; + case MAXX_BUFFER_FORMAT_FLOAT: + res = sizeof(float); + break; + default: + res = -EINVAL; + break; + } + return res; +} + +/* convert enum sof_ipc_frame to MaxxBuffer_Format_t */ +static MaxxBuffer_Format_t format_convert_sof_to_me(enum sof_ipc_frame format) +{ + MaxxBuffer_Format_t res; + + switch (format) { + case SOF_IPC_FRAME_S16_LE: + res = MAXX_BUFFER_FORMAT_Q1_15; + break; + case SOF_IPC_FRAME_S24_4LE: + res = MAXX_BUFFER_FORMAT_Q9_23; + break; + case SOF_IPC_FRAME_S32_LE: + res = MAXX_BUFFER_FORMAT_Q1_31; + break; + case SOF_IPC_FRAME_FLOAT: + res = MAXX_BUFFER_FORMAT_FLOAT; + break; + default: + res = -EINVAL; + break; + } + return res; +} + +/* convert sof frame format to MaxxBuffer_Layout_t */ +static MaxxBuffer_Layout_t layout_convert_sof_to_me(uint32_t layout) +{ + MaxxBuffer_Layout_t res; + + switch (layout) { + case SOF_IPC_BUFFER_INTERLEAVED: + res = MAXX_BUFFER_LAYOUT_INTERLEAVED; + break; + case SOF_IPC_BUFFER_NONINTERLEAVED: + res = MAXX_BUFFER_LAYOUT_DEINTERLEAVED; + break; + default: + res = -EINVAL; + break; + } + return res; +} + +/* check if sample format supported by codec */ +static bool format_is_supported(enum sof_ipc_frame format) +{ + bool supported; + + switch (format) { + case SOF_IPC_FRAME_S16_LE: + COMPILER_FALLTHROUGH; + case SOF_IPC_FRAME_S24_4LE: + COMPILER_FALLTHROUGH; + case SOF_IPC_FRAME_S32_LE: + supported = true; + break; + case SOF_IPC_FRAME_FLOAT: + COMPILER_FALLTHROUGH; + default: + supported = false; + break; + } + return supported; +} + +/* check if buffer layout supported by codec */ +static bool layout_is_supported(uint32_t layout) +{ + bool supported; + + switch (layout) { + case SOF_IPC_BUFFER_INTERLEAVED: + supported = true; + break; + case SOF_IPC_BUFFER_NONINTERLEAVED: + COMPILER_FALLTHROUGH; + default: + supported = false; + break; + } + return supported; +} + +/* check if sample rate supported by codec */ +static bool rate_is_supported(uint32_t rate) +{ + bool supported; + + switch (rate) { + case 44100: + COMPILER_FALLTHROUGH; + case 48000: + supported = true; + break; + default: + supported = false; + break; + } + return supported; +} + +/* allocate memory for MaxxEffect object */ +static int waves_effect_allocate(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + MaxxStatus_t status; + + comp_dbg(dev, "start"); + + status = MaxxEffect_GetEffectSize(&waves_codec->effect_size); + if (status) { + comp_err(dev, "MaxxEffect_GetEffectSize returned %d", + status); + return -EINVAL; + } + + waves_codec->effect = (MaxxEffect_t *)mod_alloc_align(mod, + waves_codec->effect_size, 16); + + if (!waves_codec->effect) { + comp_err(dev, "failed to allocate %d bytes for effect", + waves_codec->effect_size); + return -ENOMEM; + } + + comp_dbg(dev, "allocated %d bytes for effect", + waves_codec->effect_size); + + return 0; +} + +/* checks if sink/source parameters fit MaxxEffect */ +static int waves_effect_check(struct comp_dev *dev) +{ + struct comp_buffer *sink = comp_dev_get_first_data_consumer(dev); + struct comp_buffer *source = comp_dev_get_first_data_producer(dev); + const struct audio_stream *src_fmt = &source->stream; + const struct audio_stream *snk_fmt = &sink->stream; + + /* Init sink & source buffers */ + comp_dbg(dev, "start"); + + if (!source || !sink) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + + /* todo use fallback to comp_verify_params when ready */ + + /* resampling not supported */ + if (audio_stream_get_rate(src_fmt) != audio_stream_get_rate(snk_fmt)) { + comp_err(dev, "source %d sink %d rate mismatch", + audio_stream_get_rate(src_fmt), audio_stream_get_rate(snk_fmt)); + return -EINVAL; + } + + /* upmix/downmix not supported */ + if (audio_stream_get_channels(src_fmt) != audio_stream_get_channels(snk_fmt)) { + comp_err(dev, "source %d sink %d channels mismatch", + audio_stream_get_channels(src_fmt), audio_stream_get_channels(snk_fmt)); + return -EINVAL; + } + + /* different frame format not supported */ + if (audio_stream_get_frm_fmt(src_fmt) != audio_stream_get_frm_fmt(snk_fmt)) { + comp_err(dev, "source %d sink %d sample format mismatch", + audio_stream_get_frm_fmt(src_fmt), audio_stream_get_frm_fmt(snk_fmt)); + return -EINVAL; + } + + /* different interleaving is not supported */ + if (audio_stream_get_buffer_fmt(src_fmt) != audio_stream_get_buffer_fmt(snk_fmt)) { + comp_err(dev, "source %d sink %d buffer format mismatch", + audio_stream_get_buffer_fmt(src_fmt), audio_stream_get_buffer_fmt(snk_fmt)); + return -EINVAL; + } + + if (!format_is_supported(audio_stream_get_frm_fmt(src_fmt))) { + comp_err(dev, "float samples not supported"); + return -EINVAL; + } + + if (!layout_is_supported(audio_stream_get_buffer_fmt(src_fmt))) { + comp_err(dev, "non interleaved format not supported"); + return -EINVAL; + } + + if (!rate_is_supported(audio_stream_get_rate(src_fmt))) { + comp_err(dev, "rate %d not supported", + audio_stream_get_rate(src_fmt)); + return -EINVAL; + } + + if (audio_stream_get_channels(src_fmt) != 2) { + comp_err(dev, "channels %d not supported", + audio_stream_get_channels(src_fmt)); + return -EINVAL; + } + + comp_dbg(dev, "done"); + return 0; +} + +/* initializes MaxxEffect based on stream parameters */ +static int waves_effect_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct comp_buffer *source = comp_dev_get_first_data_producer(dev); + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + const struct audio_stream *src_fmt = &source->stream; + MaxxStatus_t status; + MaxxBuffer_Format_t sample_format; + MaxxBuffer_Layout_t buffer_format; + int32_t sample_bytes; + MaxxStreamFormat_t *i_formats[NUM_IO_STREAMS] = { &waves_codec->i_format }; + MaxxStreamFormat_t *o_formats[NUM_IO_STREAMS] = { &waves_codec->o_format }; + + comp_dbg(dev, "start"); + + sample_format = format_convert_sof_to_me(audio_stream_get_frm_fmt(src_fmt)); + if (sample_format < 0) { + comp_err(dev, "sof sample format %d not supported", + audio_stream_get_frm_fmt(src_fmt)); + return -EINVAL; + } + + buffer_format = layout_convert_sof_to_me(audio_stream_get_buffer_fmt(src_fmt)); + if (buffer_format < 0) { + comp_err(dev, "sof buffer format %d not supported", + audio_stream_get_buffer_fmt(src_fmt)); + return -EINVAL; + } + + sample_bytes = sample_format_convert_to_bytes(sample_format); + if (sample_bytes < 0) { + comp_err(dev, "sample_format %d not supported", + sample_format); + return -EINVAL; + } + + waves_codec->request_max_bytes = 0; + waves_codec->i_buffer = 0; + waves_codec->o_buffer = 0; + + 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; + + waves_codec->sample_size_in_bytes = sample_bytes; + /* Prepare a buffer for 1 period worth of data + * dev->pipeline->period stands for the scheduling period in us + */ + 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 + comp_info(dev, "rate %d, channels %d", waves_codec->i_format.sampleRate, + waves_codec->i_format.numChannels); + + comp_info(dev, "format %d, layout %d, frame %d", + waves_codec->i_format.samplesFormat, waves_codec->i_format.samplesLayout, + waves_codec->buffer_samples); + + status = MaxxEffect_Initialize(waves_codec->effect, i_formats, 1, o_formats, 1); + + if (status) { + comp_err(dev, "MaxxEffect_Initialize returned %d", status); + return -EINVAL; + } + waves_codec->initialized = true; + + comp_dbg(dev, "done"); + return 0; +} + +/* allocate additional buffers for MaxxEffect */ +static int waves_effect_buffers(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + int ret; + void *i_buffer = NULL, *o_buffer = NULL; + + comp_dbg(dev, "start"); + + i_buffer = mod_alloc_align(mod, waves_codec->buffer_bytes, 16); + if (!i_buffer) { + comp_err(dev, "failed to allocate %d bytes for i_buffer", + waves_codec->buffer_bytes); + ret = -ENOMEM; + goto err; + } + + o_buffer = mod_alloc_align(mod, waves_codec->buffer_bytes, 16); + if (!o_buffer) { + comp_err(dev, "failed to allocate %d bytes for o_buffer", + waves_codec->buffer_bytes); + ret = -ENOMEM; + goto err; + } + + waves_codec->i_buffer = i_buffer; + waves_codec->o_buffer = o_buffer; + codec->mpd.in_buff = waves_codec->i_buffer; + codec->mpd.in_buff_size = waves_codec->buffer_bytes; + codec->mpd.out_buff = waves_codec->o_buffer; + codec->mpd.out_buff_size = waves_codec->buffer_bytes; + + comp_dbg(dev, "in_buff_size %d, out_buff_size %d", + codec->mpd.in_buff_size, codec->mpd.out_buff_size); + + comp_dbg(dev, "done"); + return 0; + +err: + if (i_buffer) + mod_free(mod, i_buffer); + if (o_buffer) + mod_free(mod, o_buffer); + return ret; +} + +/* get MaxxEffect revision */ +static int waves_effect_revision(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + struct comp_dev *dev = mod->dev; + const char *revision = NULL; + uint32_t revision_len; + MaxxStatus_t status; + + comp_info(dev, "start"); + + status = MaxxEffect_Revision_Get(waves_codec->effect, &revision, &revision_len); + + if (status) { + comp_err(dev, "MaxxEffect_Revision_Get returned %d", + status); + return -EINVAL; + } + +#if CONFIG_TRACEV + if (revision_len) { + const uint32_t *ptr = (uint32_t *)revision; + uint32_t len = revision_len / sizeof(uint32_t); + uint32_t idx = 0; + + /* get requests from codec_adapter are not supported + * printing strings is not supported + * so dumping revision string to trace log as ascii values + * if simply write a for loop here then depending on trace filtering settings + * some parts of revision might not be printed - this is highly unwanted + */ + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + dump_hex(ptr, idx, len); + } +#endif + + comp_info(dev, "done"); + return 0; +} + +/* cache config blob*/ +static int waves_effect_save_config_blob_to_cache(struct processing_module *mod, + void *data, uint32_t size) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + + comp_info(dev, "start"); + + /* release old cached config blob*/ + if (waves_codec->config_blob && size != waves_codec->config_blob_size) { + comp_info(dev, "release blob"); + mod_free(mod, waves_codec->config_blob); + waves_codec->config_blob = NULL; + waves_codec->config_blob_size = 0; + } + + if (!waves_codec->config_blob) { + waves_codec->config_blob = mod_alloc_align(mod, size, 16); + if (!waves_codec->config_blob) { + comp_err(dev, + "failed to allocate %d bytes for config blob", + size); + return -ENOMEM; + } + waves_codec->config_blob_size = size; + } + + int ret = memcpy_s(waves_codec->config_blob, waves_codec->config_blob_size, + data, size); + if (ret) { + comp_err(dev, + "failed to copy config blob %d", + ret); + mod_free(mod, waves_codec->config_blob); + waves_codec->config_blob = NULL; + waves_codec->config_blob_size = 0; + return ret; + } + + comp_dbg(dev, "done"); + return 0; +} + +/* apply MaxxEffect message */ +static int waves_effect_message(struct processing_module *mod, void *data, uint32_t size) +{ + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + struct comp_dev *dev = mod->dev; + MaxxStatus_t status; + uint32_t response_size = 0; + + if (waves_codec->initialized) { + comp_info(dev, "start data %p size %d", data, size); + + status = MaxxEffect_Message(waves_codec->effect, data, size, + waves_codec->response, &response_size); + + if (status) { + comp_err(dev, "MaxxEffect_Message returned %d", + status); + return -EINVAL; + } + } + +#if CONFIG_TRACEV + /* at time of writing codec adapter does not support getting something from codec + * so response is stored to internal structure and dumped into trace messages + */ + if (response_size) { + uint32_t idx; + uint32_t len = response_size / sizeof(uint32_t); + const uint32_t *ptr = (uint32_t *)waves_codec->response; + + for (idx = 0; idx < len; ) + dump_hex(ptr, idx, len); + } +#endif + + return 0; +} + +/* apply config blob */ +static int waves_effect_apply_config_blob_from_cache(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + + comp_info(dev, "entry"); + + if (waves_codec->config_blob) { + return waves_effect_message(mod, waves_codec->config_blob, + waves_codec->config_blob_size); + } + return 0; +} + +static int waves_effect_handle_param_message(struct processing_module *mod, + void *data, uint32_t size) +{ + int ret = waves_effect_save_config_blob_to_cache(mod, data, size); + + if (!ret) + ret = waves_effect_apply_config_blob_from_cache(mod); + + return ret; +} + +/* apply codec config */ +static int waves_effect_apply_config(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct module_param *param; + struct module_config *cfg; + uint32_t index; + uint32_t param_number = 0; + int ret = 0; + + comp_info(dev, "start"); + + cfg = &codec->cfg; + + comp_info(dev, "config %p, size %d, avail %d", + cfg->data, cfg->size, cfg->avail); + + if (!cfg->data) { + ret = waves_effect_apply_config_blob_from_cache(mod); + if (ret) { + comp_err(dev, "error %x: apply cache fail", + ret); + return ret; + } + } + + if (cfg->size > MAX_CONFIG_SIZE_BYTES) { + comp_err(dev, "provided config is too big, size %d", + cfg->size); + return -EINVAL; + } + + /* incoming data in cfg->data is arranged according to struct module_param + * there migh be more than one struct module_param inside cfg->data, glued back to back + */ + const uint32_t header_size = sizeof(param->size) + sizeof(param->id); + for (index = 0; index < cfg->size && (!ret); param_number++) { + uint32_t param_data_size; + + param = (struct module_param *)((char *)cfg->data + index); + param_data_size = param->size - sizeof(param->size) - sizeof(param->id); + + comp_info(dev, "param num %d id %d size %d", + param_number, param->id, param->size); + + if ((param->size <= header_size) || (param->size > MAX_CONFIG_SIZE_BYTES)) { + comp_err(dev, "invalid module_param size: %d", + param->size); + return -EINVAL; + } + + if ((index + param->size) > cfg->size) { + comp_err(dev, "module_param size: %d exceeds cfg buffer size: %d", + param->size, cfg->size); + return -EINVAL; + } + + switch (param->id) { + case PARAM_NOP: + comp_info(dev, "NOP"); + break; + case PARAM_MESSAGE: + ret = waves_effect_handle_param_message(mod, param->data, param_data_size); + break; + case PARAM_REVISION: + ret = waves_effect_revision(mod); + break; + default: + ret = -EINVAL; + break; + } + + index += param->size; + } + + if (ret) { + comp_err(dev, "failed %d", ret); + return ret; + } + + comp_dbg(dev, "done"); + return 0; +} + +static int waves_codec_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec; + int ret = 0; + void *response = NULL; + + comp_dbg(dev, "start"); + + waves_codec = mod_alloc_align(mod, sizeof(struct waves_codec_data), 16); + if (!waves_codec) { + comp_err(dev, "failed to allocate %d bytes for waves_codec_data", + sizeof(struct waves_codec_data)); + ret = -ENOMEM; + } else { + memset(waves_codec, 0, sizeof(struct waves_codec_data)); + codec->private = waves_codec; + ret = waves_effect_allocate(mod); + if (ret) + codec->private = NULL; + } + + if (ret) { + comp_err(dev, "failed %d", ret); + return ret; + } + + ret = MaxxEffect_GetMessageMaxSize(waves_codec->effect, &waves_codec->request_max_bytes, + &waves_codec->response_max_bytes); + + if (ret) { + comp_err(dev, "MaxxEffect_GetMessageMaxSize returned %d", ret); + return -EINVAL; + } + + response = mod_alloc_align(mod, waves_codec->response_max_bytes, 16); + if (!response) { + comp_err(dev, "failed to allocate %d bytes for response", + waves_codec->response_max_bytes); + return -ENOMEM; + } + waves_codec->response = response; + waves_codec->initialized = false; + + comp_dbg(dev, "done"); + return ret; +} + +static int waves_codec_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + int ret; + + comp_dbg(dev, "start"); + + ret = waves_effect_check(dev); + if (ret) + goto error; + + ret = waves_effect_init(mod); + if (ret) + goto error; + + ret = waves_effect_buffers(mod); + if (ret) + goto error; + + ret = waves_effect_apply_config(mod); + if (ret) + goto error; + + comp_dbg(dev, "done"); + return 0; + +error: + comp_err(dev, "failed %d", ret); + return ret; +} + +static int waves_codec_init_process(struct processing_module *mod) +{ + struct module_data *codec = &mod->priv; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + codec->mpd.produced = 0; + codec->mpd.consumed = 0; + codec->mpd.init_done = 1; + + return 0; +} + +static int +waves_codec_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) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + + /* Proceed only if we have enough data to fill the module buffer completely */ + if (input_buffers[0].size < codec->mpd.in_buff_size) { + comp_dbg(dev, "not enough data to process"); + return -ENODATA; + } + + if (!codec->mpd.init_done) + waves_codec_init_process(mod); + + memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, + input_buffers[0].data, codec->mpd.in_buff_size); + codec->mpd.avail = codec->mpd.in_buff_size; + + comp_dbg(dev, "start"); + + MaxxStream_t *i_streams[NUM_IO_STREAMS] = { &waves_codec->i_stream }; + MaxxStream_t *o_streams[NUM_IO_STREAMS] = { &waves_codec->o_stream }; + MaxxStatus_t status; + uint32_t num_input_samples = waves_codec->buffer_samples; + + /* here input buffer should always be filled up as requested + * since no one updates it`s size except code in prepare. + * on the other hand there is available/produced counters in mpd, check them anyways + */ + if (codec->mpd.avail != waves_codec->buffer_bytes) { + comp_warn(dev, "input buffer %d is not full %d", + codec->mpd.avail, waves_codec->buffer_bytes); + num_input_samples = codec->mpd.avail / + (waves_codec->sample_size_in_bytes * waves_codec->i_format.numChannels); + } + + waves_codec->i_stream.buffersArray = &waves_codec->i_buffer; + waves_codec->i_stream.numAvailableSamples = num_input_samples; + waves_codec->i_stream.numProcessedSamples = 0; + waves_codec->i_stream.maxNumSamples = waves_codec->buffer_samples; + + waves_codec->o_stream.buffersArray = &waves_codec->o_buffer; + waves_codec->o_stream.numAvailableSamples = 0; + waves_codec->o_stream.numProcessedSamples = 0; + waves_codec->o_stream.maxNumSamples = waves_codec->buffer_samples; + + status = MaxxEffect_Process(waves_codec->effect, i_streams, o_streams); + if (status) { + comp_err(dev, "MaxxEffect_Process returned %d", status); + ret = -EINVAL; + } else { + codec->mpd.produced = waves_codec->o_stream.numAvailableSamples * + waves_codec->o_format.numChannels * waves_codec->sample_size_in_bytes; + codec->mpd.consumed = codec->mpd.produced; + input_buffers[0].consumed = codec->mpd.consumed; + ret = 0; + /* copy the produced samples into the output buffer */ + memcpy_s(output_buffers[0].data, codec->mpd.produced, codec->mpd.out_buff, + codec->mpd.produced); + output_buffers[0].size = codec->mpd.produced; + } + + if (ret) + comp_err(dev, "failed %d", ret); + + comp_dbg(dev, "done"); + return ret; +} + +static int waves_codec_reset(struct processing_module *mod) +{ + MaxxStatus_t status; + int ret = 0; + struct comp_dev *dev = mod->dev; + struct module_data *codec = &mod->priv; + struct waves_codec_data *waves_codec = codec->private; + + comp_info(dev, "start"); + + status = MaxxEffect_Reset(waves_codec->effect); + if (status) { + comp_err(dev, "MaxxEffect_Reset returned %d", status); + ret = -EINVAL; + } + + if (ret) + comp_err(dev, "failed %d", ret); + + if (codec->mpd.in_buff) + mod_free(mod, codec->mpd.in_buff); + + if (codec->mpd.out_buff) + mod_free(mod, codec->mpd.out_buff); + + waves_codec->initialized = false; + comp_dbg(dev, "done"); + return ret; +} + +static int waves_codec_free(struct processing_module *mod) +{ + comp_dbg(mod->dev, "entry"); + return 0; +} + +static int +waves_codec_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + int ret; + + ret = module_set_configuration(mod, config_id, pos, data_offset_size, fragment, + fragment_size, response, response_size); + if (ret < 0) + return ret; + + /* return if more fragments are expected or if the module is not prepared */ + if ((pos != MODULE_CFG_FRAGMENT_LAST && pos != MODULE_CFG_FRAGMENT_SINGLE) || + md->state < MODULE_INITIALIZED) + return 0; + + /* whole configuration received, apply it now */ + ret = waves_effect_apply_config(mod); + if (ret) { + comp_err(dev, "error %x: runtime config apply failed", + ret); + return ret; + } + + comp_dbg(dev, "config applied"); + + return 0; +} + +static const struct module_interface waves_interface = { + .init = waves_codec_init, + .prepare = waves_codec_prepare, + .process_raw_data = waves_codec_process, + .set_configuration = waves_codec_set_configuration, + .reset = waves_codec_reset, + .free = waves_codec_free +}; + +#if CONFIG_WAVES_CODEC_MODULE && CONFIG_WAVES_CODEC_STUB +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("WAVES", &waves_interface, 7, SOF_REG_UUID(waves), 8); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(waves_tr, SOF_UUID(waves_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(waves_interface, waves_uuid, waves_tr); +SOF_MODULE_INIT(waves, sys_comp_module_waves_interface_init); + +#endif diff --git a/src/audio/module_adapter/module/waves/waves.toml b/src/audio/module_adapter/module/waves/waves.toml new file mode 100644 index 000000000000..3d13fe01994b --- /dev/null +++ b/src/audio/module_adapter/module/waves/waves.toml @@ -0,0 +1,24 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # waves module config + [[module.entry]] + name = "WAVES" + uuid = UUIDREG_STR_WAVES + affinity_mask = "0x1" + instance_count = "4" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "13" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c new file mode 100644 index 000000000000..658aa5e6e583 --- /dev/null +++ b/src/audio/module_adapter/module_adapter.c @@ -0,0 +1,1613 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + +/** + * \file + * \brief Module Adapter: Processing component aimed to work with external module libraries + * \author Marcin Rajwa <marcin.rajwa@linux.intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/audio_buffer.h> +#include <sof/audio/pipeline.h> +#include <sof/lib/vregion.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/common.h> +#include <sof/platform.h> +#include <sof/ut.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/base_fw.h> +#include <ipc4/header.h> +#include <ipc4/module.h> +#endif +#include <rtos/interrupt.h> +#include <rtos/kernel.h> +#include <limits.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(module_adapter, CONFIG_SOF_LOG_LEVEL); + +/* + * \brief Create a module adapter component. + * \param[in] drv - component driver pointer. + * \param[in] config - component ipc descriptor pointer. + * \param[in] spec - passdowned data from driver. + * \param[in] mod_priv - Pointer to private data for processing module. + * + * \return: a pointer to newly created module adapter component on success. NULL on error. + */ +struct comp_dev *module_adapter_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, const void *spec) +{ + return module_adapter_new_ext(drv, config, spec, NULL, NULL); +} + +#if CONFIG_MM_DRV +#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE +#else +#include <sof/platform.h> +#define PAGE_SZ HOST_PAGE_SIZE +#endif + +static struct vregion *module_adapter_dp_heap_new(const struct comp_ipc_config *config, + size_t *heap_size) +{ + /* src-lite with 8 channels has been seen allocating 14k in one go */ + /* FIXME: the size will be derived from configuration */ + const size_t buf_size = 28 * 1024; + + /* + * A 1-to-1 replacement of the original heap implementation would be to + * have "lifetime size" equal to 0. But (1) this is invalid for + * vregion_create() and (2) we gradually move objects, that are simple + * to move to the lifetime buffer. Make it 4k for the beginning. + */ + return vregion_create(4096, buf_size - 4096); +} + +static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv, + const struct comp_ipc_config *config) +{ + struct k_heap *mod_heap; + struct vregion *mod_vreg; + struct processing_module *mod; + struct comp_dev *dev; + /* + * For DP shared modules the struct processing_module object must be + * accessible from all cores. Unfortunately at this point there's no + * information of components the module will be bound to. So we need to + * allocate shared memory for each DP module. + * To be removed when pipeline 2.0 is ready. + */ + uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ? + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER; + size_t heap_size; + + if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_USERSPACE) && + !IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) { + mod_vreg = module_adapter_dp_heap_new(config, &heap_size); + if (!mod_vreg) { + comp_cl_err(drv, "Failed to allocate DP module heap / vregion"); + return NULL; + } + mod_heap = NULL; + } else { + mod_heap = drv->user_heap; + heap_size = 0; + mod_vreg = NULL; + } + + if (!mod_vreg) + mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0); + else if (flags & SOF_MEM_FLAG_COHERENT) + mod = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod)); + else + mod = vregion_alloc(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*mod)); + + if (!mod) { + comp_cl_err(drv, "failed to allocate memory for module"); + goto emod; + } + + struct mod_alloc_ctx *alloc = rmalloc(flags, sizeof(*alloc)); + + if (!alloc) + goto ealloc; + + memset(mod, 0, sizeof(*mod)); + alloc->heap = mod_heap; + alloc->vreg = mod_vreg; + mod->priv.resources.alloc = alloc; + mod_resource_init(mod); + + /* + * Would be difficult to optimize the allocation to use cache. Only if + * the whole currently active topology is running on the primary core, + * then it can be cached. Effectively it can be only cached in + * single-core configurations. + */ + if (mod_vreg) + dev = vregion_alloc_coherent(mod_vreg, VREGION_MEM_TYPE_LIFETIME, sizeof(*dev)); + else + dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0); + + if (!dev) { + comp_cl_err(drv, "failed to allocate memory for comp_dev"); + goto edev; + } + + memset(dev, 0, sizeof(*dev)); + comp_init(drv, dev, sizeof(*dev)); + dev->ipc_config = *config; + mod->dev = dev; + dev->mod = mod; + + return mod; + +edev: + rfree(alloc); +ealloc: + if (mod_vreg) + vregion_free(mod_vreg, mod); + else + sof_heap_free(mod_heap, mod); +emod: + vregion_put(mod_vreg); + + return NULL; +} + +static void module_adapter_mem_free(struct processing_module *mod) +{ + struct mod_alloc_ctx *alloc = mod->priv.resources.alloc; + struct k_heap *mod_heap = alloc->heap; + + /* + * In principle it shouldn't even be needed to free individual objects + * on the module heap since we're freeing the heap itself too + */ +#if CONFIG_IPC_MAJOR_4 + sof_heap_free(mod_heap, mod->priv.cfg.input_pins); +#endif + if (alloc->vreg) { + struct vregion *mod_vreg = alloc->vreg; + + vregion_free(mod_vreg, mod->dev); + vregion_free(mod_vreg, mod); + if (!vregion_put(mod_vreg)) + rfree(alloc); + } else { + sof_heap_free(mod_heap, mod->dev); + sof_heap_free(mod_heap, mod); + rfree(alloc); + } +} + +/* + * \brief Create a module adapter component. + * \param[in] drv - component driver pointer. + * \param[in] config - component ipc descriptor pointer. + * \param[in] const_spec - passdowned data from driver. + * \param[in] mod_priv - Pointer to private data for processing module. + * + * \return: a pointer to newly created module adapter component on success. NULL on error. + * + * Note: Use the ext version if you need to set the module's private data before calling + * the create method. + */ +struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *const_spec, void *mod_priv, + struct userspace_context *user_ctx) +{ + int ret; + struct module_config *dst; + const struct module_interface *const interface = drv->adapter_ops; + struct ipc_config_process spec = + *((const struct ipc_config_process *) const_spec); +#if CONFIG_IPC_MAJOR_4 + struct module_ext_init_data ext_data = { 0 }; +#endif + comp_cl_dbg(drv, "start"); + + if (!config) { + comp_cl_err(drv, "NULL config! drv = %p", drv); + return NULL; + } +#if CONFIG_IPC_MAJOR_4 + if (config->ipc_extended_init) { + ret = module_ext_init_decode(drv, &ext_data, &spec); + if (ret != 0) + return NULL; + } +#endif + + struct processing_module *mod = module_adapter_mem_alloc(drv, config); + + if (!mod) + return NULL; + + module_set_private_data(mod, mod_priv); + list_init(&mod->raw_data_buffers_list); +#if CONFIG_USERSPACE + mod->user_ctx = user_ctx; +#endif /* CONFIG_USERSPACE */ + + struct comp_dev *dev = mod->dev; + +#if CONFIG_ZEPHYR_DP_SCHEDULER + /* create a task for DP processing */ + if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* All data allocated, create a thread */ + ret = pipeline_comp_dp_task_init(dev); + if (ret) { + comp_cl_err(drv, "DP task creation failed with error %d.", ret); + goto err; + } + } +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + + dst = &mod->priv.cfg; + /* + * NOTE: dst->ext_data points to stack variable and contains + * pointers to IPC payload mailbox, so its only valid in + * functions that called from this function. This why + * the pointer is set NULL before this function exits. + */ +#if CONFIG_IPC_MAJOR_4 + dst->ext_data = &ext_data; +#endif + ret = module_adapter_init_data(dev, dst, config, &spec); + if (ret) { + comp_err(dev, "%d: module init data failed", + ret); + goto err; + } + + /* Modules must modify them if they support more than 1 source/sink */ + mod->max_sources = 1; + mod->max_sinks = 1; + + /* The order of preference */ + if (interface->process) + mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; + else if (interface->process_audio_stream) + mod->proc_type = MODULE_PROCESS_TYPE_STREAM; + else if (interface->process_raw_data) + mod->proc_type = MODULE_PROCESS_TYPE_RAW; + else + goto err; + +#if CONFIG_IPC_MAJOR_4 + struct ipc_comp_dev *ipc_pipe; + struct ipc *ipc = ipc_get(); + + /* set the pipeline pointer if ipc_pipe is valid */ + ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, config->pipeline_id, + IPC_COMP_IGNORE_REMOTE); + if (ipc_pipe) { + dev->pipeline = ipc_pipe->pipeline; + + /* LL modules have the same period as the pipeline */ + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + dev->period = ipc_pipe->pipeline->period; + } +#endif + + /* Init processing module */ + ret = module_init(mod); + if (ret) { + comp_err(dev, "%d: module initialization failed", + ret); + goto err; + } + + module_adapter_reset_data(dst); + + dev->state = COMP_STATE_READY; + +#if CONFIG_IPC_MAJOR_4 + struct sof_ipc_stream_params params; + + /* + * retrieve the stream params based on the module base cfg. There's no need to initialize + * params here because it will be filled in based on the module base_cfg. + */ + ret = module_adapter_params(dev, ¶ms); + if (ret) { + comp_err(dev, "%d: module params failed", ret); + goto err; + } + + /* set component period frames */ + component_set_nearest_period_frames(dev, params.rate); +#endif + +#if CONFIG_IPC_MAJOR_4 + dst->ext_data = NULL; +#endif + comp_dbg(dev, "done"); + return dev; + +err: +#if CONFIG_ZEPHYR_DP_SCHEDULER + if (dev->task) + schedule_task_free(dev->task); +#endif + module_adapter_mem_free(mod); + return NULL; +} + +#if CONFIG_ZEPHYR_DP_SCHEDULER +static void module_adapter_calculate_dp_period(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + unsigned int period = UINT32_MAX; + + for (int i = 0; i < mod->num_of_sinks; i++) { + /* calculate time required the module to provide OBS data portion - a period + * use 64bit integers to avoid overflows + */ + unsigned int sink_period = 1000000ULL * sink_get_min_free_space(mod->sinks[i]) / + (sink_get_frame_bytes(mod->sinks[i]) * + sink_get_rate(mod->sinks[i])); + /* note the minimal period for the module */ + if (period > sink_period) + period = sink_period; + + } + + dev->period = period; +} +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + +/* + * \brief Prepare the module + * \param[in] dev - component device pointer. + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_prepare(struct comp_dev *dev) +{ + int ret; + struct processing_module *mod = comp_mod(dev); + struct module_data *md = &mod->priv; + struct comp_buffer *sink; + struct list_item *blist, *_blist; + uint32_t buff_periods; + uint32_t buff_size; /* size of local buffer */ + int memory_flags; + int i = 0; + + comp_dbg(dev, "start"); +#if CONFIG_IPC_MAJOR_4 + /* allocate stream_params and retrieve the params from the basecfg if needed */ + if (!mod->stream_params) { + struct sof_ipc_stream_params params; + + ret = module_adapter_params(dev, ¶ms); + if (ret) { + comp_err(dev, "module_adapter_new() %d: module params failed", ret); + return ret; + } + } +#endif + /* Prepare module */ + if (IS_PROCESSING_MODE_SINK_SOURCE(mod)) + ret = module_adapter_sink_src_prepare(dev); + + else if ((IS_PROCESSING_MODE_RAW_DATA(mod) || IS_PROCESSING_MODE_AUDIO_STREAM(mod)) && + mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + ret = module_prepare(mod, NULL, 0, NULL, 0); + + else + ret = -EINVAL; + + if (ret) { + if (ret != PPL_STATUS_PATH_STOP) + comp_err(dev, "error %d: module prepare failed", ret); + return ret; + } + +#if CONFIG_ZEPHYR_DP_SCHEDULER + /* set the period for the DP module unless it has already been calculated by the + * module itself during prepare + * It may happen i.e. for modules like phrase detect that do not produce audio data + * but events and therefore don't have any deadline for processing + * Second example is a module with variable data rate on output (like MPEG encoder) + */ + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* calculate DP period if a module didn't */ + if (!dev->period) + module_adapter_calculate_dp_period(dev); + + if (dev->period < LL_TIMER_PERIOD_US) { + comp_err(dev, "DP Module period too short (%u us), must be at least 1LL cycle (%llu us)", + dev->period, LL_TIMER_PERIOD_US); + return -EINVAL; + } + + /* align down period to LL cycle time */ + dev->period /= LL_TIMER_PERIOD_US; + dev->period *= LL_TIMER_PERIOD_US; + comp_info(dev, "DP Module period set to %u us", dev->period); + } +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + + /* + * check if the component is already active. This could happen in the case of mixer when + * one of the sources is already active + */ + if (dev->state == COMP_STATE_ACTIVE) + return PPL_STATUS_PATH_STOP; + + /* Are we already prepared? */ + ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) { + comp_warn(dev, "module has already been prepared"); + return PPL_STATUS_PATH_STOP; + } + + /* nothing more to do for HOST/DAI type modules */ + if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) + return 0; + + mod->deep_buff_bytes = 0; + + /* Get period_bytes first on prepare(). At this point the stream parameter from sink buffer + * shall be settled, provided that the pipeline is built correctly (bind IPC received). + * Hence check for NULL. + */ + sink = comp_dev_get_first_data_consumer(dev); + if (!sink) { + comp_err(dev, "no sink present on period size calculation"); + return -EINVAL; + } + + mod->period_bytes = audio_stream_period_bytes(&sink->stream, dev->frames); + comp_dbg(dev, "got period_bytes = %u", mod->period_bytes); + + /* no more to do for sink/source mode */ + if (IS_PROCESSING_MODE_SINK_SOURCE(mod)) + return 0; + + /* compute number of input buffers */ + mod->num_of_sources = 0; + list_for_item(blist, &dev->bsource_list) + mod->num_of_sources++; + + /* compute number of output buffers */ + mod->num_of_sinks = 0; + list_for_item(blist, &dev->bsink_list) + mod->num_of_sinks++; + + if (!mod->num_of_sources && !mod->num_of_sinks) { + comp_err(dev, "no source and sink buffers connected!"); + return -EINVAL; + } + if (mod->num_of_sources > CONFIG_MODULE_MAX_CONNECTIONS || + mod->num_of_sinks > CONFIG_MODULE_MAX_CONNECTIONS) { + comp_err(dev, "too many connected sinks %d or sources %d!", + mod->num_of_sinks, mod->num_of_sources); + return -EINVAL; + } + + if (mod->num_of_sources > mod->max_sources || + mod->num_of_sinks > mod->max_sinks) { + comp_err(dev, "connected sources %d (max %d) or sinks %d (max %d) exceed module capacity", + mod->num_of_sources, mod->max_sources, + mod->num_of_sinks, mod->max_sinks); + return -EINVAL; + } + + /* check processing mode */ + if (IS_PROCESSING_MODE_AUDIO_STREAM(mod) && mod->max_sources > 1 && mod->max_sinks > 1) { + comp_err(dev, "Invalid use of simple_copy"); + return -EINVAL; + } + + module_adapter_check_data(mod, dev, sink); + + memory_flags = user_get_buffer_memory_region(dev->drv); + /* allocate memory for input buffers */ + if (mod->max_sources) { + mod->input_buffers = + rzalloc(memory_flags, sizeof(*mod->input_buffers) * mod->max_sources); + if (!mod->input_buffers) { + comp_err(dev, "failed to allocate input buffers"); + return -ENOMEM; + } + } else { + mod->input_buffers = NULL; + } + + /* allocate memory for output buffers */ + if (mod->max_sinks) { + mod->output_buffers = + rzalloc(memory_flags, sizeof(*mod->output_buffers) * mod->max_sinks); + if (!mod->output_buffers) { + comp_err(dev, "failed to allocate output buffers"); + ret = -ENOMEM; + goto in_out_free; + } + } else { + mod->output_buffers = NULL; + } + + /* + * no need to allocate intermediate sink buffers if the module produces only period bytes + * every period and has only 1 input and 1 output buffer + */ + if (!IS_PROCESSING_MODE_RAW_DATA(mod)) + return 0; + + /* Module is prepared, now we need to configure processing settings. + * If module internal buffer is not equal to natural multiple of pipeline + * buffer we have a situation where module adapter have to deep buffer certain amount + * of samples on its start (typically few periods) in order to regularly + * generate output once started (same situation happens for compress streams + * as well). + */ + if (md->mpd.in_buff_size > mod->period_bytes) { + buff_periods = (md->mpd.in_buff_size % mod->period_bytes) ? + (md->mpd.in_buff_size / mod->period_bytes) + 2 : + (md->mpd.in_buff_size / mod->period_bytes) + 1; + } else { + buff_periods = (mod->period_bytes % md->mpd.in_buff_size) ? + (mod->period_bytes / md->mpd.in_buff_size) + 2 : + (mod->period_bytes / md->mpd.in_buff_size) + 1; + } + + /* + * deep_buffer_bytes is a measure of how many bytes we need to send to the DAI before + * the module starts producing samples. In a normal copy() walk it might be possible that + * the first period_bytes copied to input_buffer might not be enough for the processing + * to begin. So, in order to prevent the DAI from starving, it needs to be fed zeroes until + * the module starts processing and generating output samples. + */ + if (md->mpd.in_buff_size != mod->period_bytes) + mod->deep_buff_bytes = MIN(mod->period_bytes, md->mpd.in_buff_size) * buff_periods; + + if (md->mpd.out_buff_size > mod->period_bytes) { + buff_periods = (md->mpd.out_buff_size % mod->period_bytes) ? + (md->mpd.out_buff_size / mod->period_bytes) + 2 : + (md->mpd.out_buff_size / mod->period_bytes) + 1; + } else { + buff_periods = (mod->period_bytes % md->mpd.out_buff_size) ? + (mod->period_bytes / md->mpd.out_buff_size) + 2 : + (mod->period_bytes / md->mpd.out_buff_size) + 1; + } + + /* + * It is possible that the module process() will produce more data than period_bytes but + * the DAI can consume only period_bytes every period. So, the local buffer needs to be + * large enough to save the produced output samples. + */ + buff_size = MAX(mod->period_bytes, md->mpd.out_buff_size) * buff_periods; + mod->output_buffer_size = buff_size; + + /* allocate memory for input buffer data */ + size_t size = MAX(mod->deep_buff_bytes, mod->period_bytes); + + list_for_item(blist, &dev->bsource_list) { + mod->input_buffers[i].data = rballoc(memory_flags, size); + if (!mod->input_buffers[i].data) { + comp_err(mod->dev, "Failed to alloc input buffer data"); + ret = -ENOMEM; + goto in_data_free; + } + i++; + } + + /* allocate memory for output buffer data */ + i = 0; + list_for_item(blist, &dev->bsink_list) { + mod->output_buffers[i].data = rballoc(memory_flags, md->mpd.out_buff_size); + if (!mod->output_buffers[i].data) { + comp_err(mod->dev, "Failed to alloc output buffer data"); + ret = -ENOMEM; + goto out_data_free; + } + i++; + } + + /* allocate buffer for all sinks */ + if (list_is_empty(&mod->raw_data_buffers_list)) { + for (i = 0; i < mod->num_of_sinks; i++) { + /* allocate not shared buffer */ + struct comp_buffer *buffer = buffer_alloc(md->resources.alloc, + buff_size, memory_flags, + PLATFORM_DCACHE_ALIGN, + BUFFER_USAGE_NOT_SHARED); + uint32_t flags; + + if (!buffer) { + comp_err(dev, "failed to allocate local buffer"); + ret = -ENOMEM; + goto free; + } + + vregion_get(md->resources.alloc->vreg); + + irq_local_disable(flags); + list_item_prepend(&buffer->buffers_list, &mod->raw_data_buffers_list); + irq_local_enable(flags); + + buffer_set_params(buffer, mod->stream_params, BUFFER_UPDATE_FORCE); + audio_buffer_reset(&buffer->audio_buffer); + } + } else { + list_for_item(blist, &mod->raw_data_buffers_list) { + struct comp_buffer *buffer = container_of(blist, struct comp_buffer, + buffers_list); + + ret = buffer_set_size(buffer, buff_size, 0); + if (ret < 0) { + comp_err(dev, "buffer_set_size() failed, buff_size = %u", + buff_size); + goto free; + } + + buffer_set_params(buffer, mod->stream_params, BUFFER_UPDATE_FORCE); + audio_buffer_reset(&buffer->audio_buffer); + } + } + + comp_dbg(dev, "done"); + + return 0; + +free: + list_for_item_safe(blist, _blist, &mod->raw_data_buffers_list) { + struct comp_buffer *buffer = container_of(blist, struct comp_buffer, + buffers_list); + uint32_t flags; + + irq_local_disable(flags); + list_item_del(&buffer->buffers_list); + irq_local_enable(flags); + buffer_free(buffer); + } + +out_data_free: + for (i = 0; i < mod->num_of_sinks; i++) + rfree(mod->output_buffers[i].data); + +in_data_free: + for (i = 0; i < mod->num_of_sources; i++) + rfree(mod->input_buffers[i].data); + +in_out_free: + rfree(mod->output_buffers); + mod->output_buffers = NULL; + rfree(mod->input_buffers); + mod->input_buffers = NULL; + return ret; +} + +int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +{ + int ret; + struct processing_module *mod = comp_mod(dev); + + module_adapter_set_params(mod, params); + +#if CONFIG_IPC_MAJOR_3 + ret = comp_verify_params(dev, mod->verify_params_flags, params); + if (ret < 0) { + comp_err(dev, "comp_verify_params() failed."); + return ret; + } +#endif + + /* allocate stream_params each time */ + mod_free(mod, mod->stream_params); + + mod->stream_params = mod_alloc(mod, sizeof(*mod->stream_params) + params->ext_data_length); + if (!mod->stream_params) + return -ENOMEM; + + ret = memcpy_s(mod->stream_params, sizeof(struct sof_ipc_stream_params), + params, sizeof(struct sof_ipc_stream_params)); + if (ret < 0) + return ret; + + if (params->ext_data_length) { + ret = memcpy_s((uint8_t *)mod->stream_params->data, + params->ext_data_length, + (uint8_t *)params->data, + params->ext_data_length); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * Function to copy from source buffer to the module buffer + * @source: source audio buffer stream + * @buff: pointer to the module input buffer + * @buff_size: size of the module input buffer + * @bytes: number of bytes available in the source buffer + */ +static void ca_copy_from_source_to_module(const struct audio_stream *source, + void *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, + 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, 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 *)audio_stream_get_rptr(source) + head_size), + MIN(buff_size, tail_size)); +} + +/* + * Function to copy processed samples from the module buffer to sink buffer + * @sink: sink audio buffer stream + * @buff: pointer to the module output buffer + * @bytes: number of bytes available in the module output buffer + */ +static void ca_copy_from_module_to_sink(const struct audio_stream *sink, + void *buff, size_t bytes) +{ + /* head_size - free space until end of sink buffer */ + 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 + */ + uint32_t tail_size = bytes - head_size; + + /* copy "head_size" samples to sink buffer */ + 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 *)audio_stream_get_wptr(sink) + head_size), + (__sparse_force char *)buff + head_size, + MIN(audio_stream_get_size(sink), tail_size)); +} + +/** + * \brief Generate zero samples of "bytes" size for the sink. + * \param[in] sink - a pointer to sink buffer. + * \param[in] bytes - number of zero bytes to produce. + * + * \return: none. + */ +static void generate_zeroes(struct comp_buffer *sink, uint32_t bytes) +{ + uint32_t tmp, copy_bytes = bytes; + void *ptr; + + while (copy_bytes) { + 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; + copy_bytes -= tmp; + } + comp_update_buffer_produce(sink, bytes); +} + +static void module_copy_samples(struct comp_dev *dev, struct comp_buffer *src_buffer, + struct comp_buffer *sink_buffer, uint32_t produced) +{ + struct processing_module *mod = comp_mod(dev); + struct comp_copy_limits cl; + uint32_t copy_bytes; + + if (mod->deep_buff_bytes) { + if (mod->deep_buff_bytes >= audio_stream_get_avail_bytes(&src_buffer->stream)) { + generate_zeroes(sink_buffer, mod->period_bytes); + return; + } + + comp_dbg(dev, "deep buffering has ended after gathering %d bytes of processed data", + audio_stream_get_avail_bytes(&src_buffer->stream)); + mod->deep_buff_bytes = 0; + } else if (!produced) { + comp_dbg(dev, "nothing processed in this call"); + /* + * No data produced anything in this period but there still be data in the buffer + * to copy to sink + */ + if (audio_stream_get_avail_bytes(&src_buffer->stream) < mod->period_bytes) + return; + } + + comp_get_copy_limits(src_buffer, sink_buffer, &cl); + copy_bytes = cl.frames * cl.source_frame_bytes; + if (!copy_bytes) + return; + audio_stream_copy(&src_buffer->stream, 0, &sink_buffer->stream, 0, + copy_bytes / mod->stream_params->sample_container_bytes); + buffer_stream_writeback(sink_buffer, copy_bytes); + + comp_update_buffer_produce(sink_buffer, copy_bytes); + comp_update_buffer_consume(src_buffer, copy_bytes); +} + +static void module_adapter_process_output(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct comp_buffer *sink; + struct list_item *blist; + int i = 0; + + /* + * copy all produced output samples to output buffers. This loop will do nothing when + * there are no samples produced. + */ + list_for_item(blist, &mod->raw_data_buffers_list) { + if (mod->output_buffers[i].size > 0) { + struct comp_buffer *buffer; + + buffer = container_of(blist, struct comp_buffer, buffers_list); + + ca_copy_from_module_to_sink(&buffer->stream, mod->output_buffers[i].data, + mod->output_buffers[i].size); + audio_stream_produce(&buffer->stream, mod->output_buffers[i].size); + } + i++; + } + + /* copy from all output local buffers to sink buffers */ + i = 0; + comp_dev_for_each_consumer(dev, sink) { + int j = 0; + + list_for_item(blist, &mod->raw_data_buffers_list) { + if (i == j) { + struct comp_buffer *source; + + source = container_of(blist, struct comp_buffer, buffers_list); + module_copy_samples(dev, source, sink, + mod->output_buffers[i].size); + + mod->output_buffers[i].size = 0; + break; + } + j++; + } + i++; + } + + mod->total_data_produced += mod->output_buffers[0].size; +} + +static uint32_t module_single_sink_setup(struct comp_dev *dev, + struct comp_buffer **source, + struct comp_buffer **sinks) +{ + struct processing_module *mod = comp_mod(dev); + struct list_item *blist; + uint32_t num_input_buffers; + uint32_t frames; + int i = 0; + + list_for_item(blist, &dev->bsource_list) { + frames = audio_stream_avail_frames_aligned(&source[i]->stream, + &sinks[0]->stream); + + if (!mod->skip_src_buffer_invalidate) { + uint32_t source_frame_bytes; + + source_frame_bytes = audio_stream_frame_bytes(&source[i]->stream); + buffer_stream_invalidate(source[i], frames * source_frame_bytes); + } + + /* + * note that the size is in number of frames not the number of + * bytes + */ + mod->input_buffers[i].size = frames; + mod->input_buffers[i].consumed = 0; + + mod->input_buffers[i].data = &source[i]->stream; + i++; + } + + num_input_buffers = i; + + mod->output_buffers[0].size = 0; + mod->output_buffers[0].data = &sinks[0]->stream; + + return num_input_buffers; +} + +static uint32_t module_single_source_setup(struct comp_dev *dev, + struct comp_buffer **source, + struct comp_buffer **sinks) +{ + struct processing_module *mod = comp_mod(dev); + struct list_item *blist; + uint32_t min_frames = UINT32_MAX; + uint32_t num_output_buffers; + uint32_t source_frame_bytes; + int i = 0; + + source_frame_bytes = audio_stream_frame_bytes(&source[0]->stream); + if (list_is_empty(&dev->bsink_list)) { + min_frames = audio_stream_get_avail_frames(&source[0]->stream); + } else { + uint32_t frames; + + list_for_item(blist, &dev->bsink_list) { + frames = audio_stream_avail_frames_aligned(&source[0]->stream, + &sinks[i]->stream); + + min_frames = MIN(min_frames, frames); + + mod->output_buffers[i].size = 0; + mod->output_buffers[i].data = &sinks[i]->stream; + i++; + } + } + + num_output_buffers = i; + + if (!mod->skip_src_buffer_invalidate) + buffer_stream_invalidate(source[0], min_frames * source_frame_bytes); + + /* note that the size is in number of frames not the number of bytes */ + mod->input_buffers[0].size = min_frames; + mod->input_buffers[0].consumed = 0; + mod->input_buffers[0].data = &source[0]->stream; + + return num_output_buffers; +} + +static int module_adapter_audio_stream_copy_1to1(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + uint32_t num_output_buffers = 0; + uint32_t frames; + int ret; + + frames = audio_stream_avail_frames_aligned(&mod->source_comp_buffer->stream, + &mod->sink_comp_buffer->stream); + mod->input_buffers[0].size = frames; + mod->input_buffers[0].consumed = 0; + mod->input_buffers[0].data = &mod->source_comp_buffer->stream; + mod->output_buffers[0].size = 0; + mod->output_buffers[0].data = &mod->sink_comp_buffer->stream; + + if (!mod->skip_src_buffer_invalidate) { /* TODO: add mod->is_multi_core && optimization */ + /* moved bytes to its own variable to fix checkpatch */ + uint32_t bytes = + frames * audio_stream_frame_bytes(&mod->source_comp_buffer->stream); + buffer_stream_invalidate(mod->source_comp_buffer, + bytes); + } + + /* Note: Source buffer state is not checked to enable mixout to generate zero + * PCM codes when source is not active. + */ + if (comp_buffer_get_sink_state(mod->sink_comp_buffer) == dev->state) + num_output_buffers = 1; + + ret = module_process_legacy(mod, mod->input_buffers, 1, + mod->output_buffers, num_output_buffers); + + /* consume from the input buffer */ + mod->total_data_consumed += mod->input_buffers[0].consumed; + if (mod->input_buffers[0].consumed) + audio_stream_consume(&mod->source_comp_buffer->stream, + mod->input_buffers[0].consumed); + + /* produce data into the output buffer */ + mod->total_data_produced += mod->output_buffers[0].size; + if (!mod->skip_sink_buffer_writeback) /* TODO: add mod->is_multi_core && optimization */ + buffer_stream_writeback(mod->sink_comp_buffer, mod->output_buffers[0].size); + + if (mod->output_buffers[0].size) + comp_update_buffer_produce(mod->sink_comp_buffer, mod->output_buffers[0].size); + + return ret; +} + +static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) +{ + struct comp_buffer *sources[PLATFORM_MAX_STREAMS]; + struct comp_buffer *sinks[PLATFORM_MAX_STREAMS]; + struct comp_buffer *sink; + struct comp_buffer *source; + struct processing_module *mod = comp_mod(dev); + uint32_t num_input_buffers, num_output_buffers; + int ret, i; + + /* handle special case of HOST/DAI type components */ + if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) + return module_process_endpoint(mod, NULL, 0, NULL, 0); + + if (mod->stream_copy_single_to_single) + return module_adapter_audio_stream_copy_1to1(dev); + + /* acquire all sink and source buffers */ + i = 0; + comp_dev_for_each_consumer(dev, sink) + sinks[i++] = sink; + num_output_buffers = i; + if (num_output_buffers > mod->max_sinks) { + comp_err(dev, "Invalid number of sinks %d\n", num_output_buffers); + return -EINVAL; + } + + i = 0; + comp_dev_for_each_producer(dev, source) + sources[i++] = source; + num_input_buffers = i; + if (num_input_buffers > mod->max_sources) { + comp_err(dev, "Invalid number of sources %d\n", num_input_buffers); + return -EINVAL; + } + + /* setup active input/output buffers for processing */ + if (num_output_buffers == 1) { + module_single_sink_setup(dev, sources, sinks); + if (comp_buffer_get_sink_state(sinks[0]) != dev->state) + num_output_buffers = 0; + } else if (num_input_buffers == 1) { + module_single_source_setup(dev, sources, sinks); + if (comp_buffer_get_source_state(sources[0]) != dev->state) { + num_input_buffers = 0; + } + } else { + ret = -EINVAL; + goto out; + } + + ret = module_process_legacy(mod, mod->input_buffers, num_input_buffers, + mod->output_buffers, num_output_buffers); + if (ret) { + if (ret != -ENOSPC && ret != -ENODATA) { + comp_err(dev, "failed with error: %d", ret); + goto out; + } + + ret = 0; + } + + /* consume from all active input buffers */ + for (i = 0; i < num_input_buffers; i++) { + struct comp_buffer *src = + container_of(mod->input_buffers[i].data, struct comp_buffer, stream); + + if (mod->input_buffers[i].consumed) + audio_stream_consume(&src->stream, 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 */ + for (i = 0; i < num_input_buffers; i++) { + mod->input_buffers[i].size = 0; + mod->input_buffers[i].consumed = 0; + } + + /* produce data into all active output buffers */ + for (i = 0; i < num_output_buffers; i++) { + struct comp_buffer *sink = + container_of(mod->output_buffers[i].data, struct comp_buffer, stream); + + if (!mod->skip_sink_buffer_writeback) + buffer_stream_writeback(sink, mod->output_buffers[i].size); + if (mod->output_buffers[i].size) + comp_update_buffer_produce(sink, mod->output_buffers[i].size); + } + + mod->total_data_produced += mod->output_buffers[0].size; + + /* release all sink buffers */ + for (i = 0; i < num_output_buffers; i++) { + mod->output_buffers[i].size = 0; + } + + return 0; +out: + for (i = 0; i < num_output_buffers; i++) { + mod->output_buffers[i].size = 0; + } + + for (i = 0; i < num_input_buffers; i++) { + mod->input_buffers[i].size = 0; + mod->input_buffers[i].consumed = 0; + } + + return ret; +} + +#if CONFIG_PIPELINE_2_0 +static int module_adapter_copy_ring_buffers(struct comp_dev *dev) +{ + /* + * copy data from component audio streams to ring_buffer + * DP module processing itself will take place in DP thread + * This is an adapter, to be removed when pipeline2.0 is ready + */ + struct processing_module *mod = comp_mod(dev); + struct comp_buffer *buffer; + int err; + + comp_dev_for_each_producer(dev, buffer) { + /* input - we need to copy data from audio_stream (as source) + * to ring_buffer (as sink) + */ + err = audio_buffer_sync_secondary_buffer(&buffer->audio_buffer, UINT_MAX); + + if (err) { + comp_err(dev, "LL to DP copy error status: %d", err); + return err; + } + } + + if (mod->dp_startup_delay) + return 0; + + comp_dev_for_each_consumer(dev, buffer) { + /* output - we need to copy data from ring_buffer (as source) + * to audio_stream (as sink) + * + * a trick is needed there: + * DP may produce a huge chunk of output data (i.e. 10 LL cycles), and the + * following module should be able to consume it in 1 cycle chunks, one by one + * + * unfortunately LL modules are designed to drain input buffer + * That leads to issues when DP provide huge data portion + * + * FIX: copy only the following module's IBS in each LL cycle + */ + struct sof_source *following_mod_data_source = + audio_buffer_get_source(&buffer->audio_buffer); + + err = audio_buffer_sync_secondary_buffer + (&buffer->audio_buffer, + source_get_min_available(following_mod_data_source)); + + if (err) { + comp_err(dev, "DP to LL copy error status: %d", err); + return err; + } + } + return 0; +} +#else /* CONFIG_PIPELINE_2_0 */ +static inline int module_adapter_copy_ring_buffers(struct comp_dev *dev) +{ + return -ENOTSUP; +} +#endif /* CONFIG_PIPELINE_2_0 */ + +static int module_adapter_sink_source_copy(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + int ret; + int i = 0; + + comp_dbg(dev, "start"); + + /* reset number of processed bytes */ + for (i = 0; i < mod->num_of_sources; i++) + source_reset_num_of_processed_bytes(mod->sources[i]); + + for (i = 0; i < mod->num_of_sinks; i++) + sink_reset_num_of_processed_bytes(mod->sinks[i]); + + ret = module_process_sink_src(mod, mod->sources, mod->num_of_sources, + mod->sinks, mod->num_of_sinks); + + if (ret) + comp_err(dev, "process failed with error: %d", ret); + + /* count number of processed data. To be removed in pipeline 2.0 */ + for (i = 0; i < mod->num_of_sources; i++) + mod->total_data_consumed += source_get_num_of_processed_bytes(mod->sources[i]); + + for (i = 0; i < mod->num_of_sinks; i++) + mod->total_data_produced += sink_get_num_of_processed_bytes(mod->sinks[i]); + + comp_dbg(dev, "done"); + + return ret; +} + +static int module_adapter_raw_data_type_copy(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct module_data *md = &mod->priv; + struct comp_buffer *source, *sink; + struct list_item *blist; + size_t size = MAX(mod->deep_buff_bytes, mod->period_bytes); + uint32_t min_free_frames = UINT_MAX; + int ret, i = 0; + + comp_dbg(dev, "start"); + + list_for_item(blist, &mod->raw_data_buffers_list) { + sink = container_of(blist, struct comp_buffer, buffers_list); + + min_free_frames = MIN(min_free_frames, + audio_stream_get_free_frames(&sink->stream)); + } + + /* copy source samples into input buffer */ + comp_dev_for_each_producer(dev, source) { + uint32_t bytes_to_process; + int frames, source_frame_bytes; + + /* check if the source dev is in the same state as the dev */ + if (comp_buffer_get_source_state(source) != dev->state) + continue; + + frames = MIN(min_free_frames, + audio_stream_get_avail_frames(&source->stream)); + source_frame_bytes = audio_stream_frame_bytes(&source->stream); + + bytes_to_process = MIN(frames * source_frame_bytes, md->mpd.in_buff_size); + + buffer_stream_invalidate(source, bytes_to_process); + mod->input_buffers[i].size = bytes_to_process; + mod->input_buffers[i].consumed = 0; + + ca_copy_from_source_to_module(&source->stream, mod->input_buffers[i].data, + md->mpd.in_buff_size, bytes_to_process); + i++; + } + + ret = module_process_legacy(mod, mod->input_buffers, mod->num_of_sources, + mod->output_buffers, mod->num_of_sinks); + if (ret) { + if (ret != -ENOSPC && ret != -ENODATA) { + comp_err(dev, "%d: module processing failed", ret); + goto out; + } + + ret = 0; + } + + i = 0; + /* consume from all input buffers */ + comp_dev_for_each_producer(dev, source) { + comp_update_buffer_consume(source, mod->input_buffers[i].consumed); + + 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); + + comp_dbg(dev, "done"); + + return 0; + +out: + for (i = 0; i < mod->num_of_sinks; i++) + mod->output_buffers[i].size = 0; + + for (i = 0; i < mod->num_of_sources; i++) { + bzero((__sparse_force void *)mod->input_buffers[i].data, size); + mod->input_buffers[i].size = 0; + mod->input_buffers[i].consumed = 0; + } + comp_dbg(dev, "error %x", ret); + return ret; +} + +int module_adapter_copy(struct comp_dev *dev) +{ + comp_dbg(dev, "start"); + + struct processing_module *mod = comp_mod(dev); + + if (IS_PROCESSING_MODE_AUDIO_STREAM(mod)) + return module_adapter_audio_stream_type_copy(dev); + + if (IS_PROCESSING_MODE_RAW_DATA(mod)) + return module_adapter_raw_data_type_copy(dev); + + if (IS_PROCESSING_MODE_SINK_SOURCE(mod)) { + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) + return module_adapter_copy_ring_buffers(dev); + else + return module_adapter_sink_source_copy(dev); + + } + + comp_err(dev, "unknown processing_data_type"); + return -EINVAL; +} + +int module_adapter_trigger(struct comp_dev *dev, int cmd) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + comp_dbg(dev, "cmd %d", cmd); + + /* handle host/DAI gateway modules separately */ + if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) + return interface->endpoint_ops->trigger(dev, cmd); + + /* + * If the module doesn't support pause, keep it active along with the rest of the + * downstream modules + */ + if (cmd == COMP_TRIGGER_PAUSE && mod->no_pause) { + dev->state = COMP_STATE_ACTIVE; + return PPL_STATUS_PATH_STOP; + } + + if (interface->trigger) { +#if CONFIG_SOF_USERSPACE_APPLICATION + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* Process DP module's trigger */ + const union scheduler_dp_thread_ipc_param param = { + .pipeline_state.trigger_cmd = cmd, + }; + return scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, + ¶m); + } +#endif + return interface->trigger(mod, cmd); + } + + return module_adapter_set_state(mod, dev, cmd); +} + +int module_adapter_reset(struct comp_dev *dev) +{ + int ret, i; + struct processing_module *mod = comp_mod(dev); + struct list_item *blist; + + comp_dbg(dev, "resetting"); + + ret = module_reset(mod); + if (ret) { + if (ret != PPL_STATUS_PATH_STOP) + comp_err(dev, "failed with error: %d", ret); + return ret; + } + + if (IS_PROCESSING_MODE_RAW_DATA(mod)) { + for (i = 0; i < mod->num_of_sinks; i++) + rfree((__sparse_force void *)mod->output_buffers[i].data); + for (i = 0; i < mod->num_of_sources; i++) + rfree((__sparse_force void *)mod->input_buffers[i].data); + } + + if (IS_PROCESSING_MODE_RAW_DATA(mod) || IS_PROCESSING_MODE_AUDIO_STREAM(mod)) { + rfree(mod->output_buffers); + rfree(mod->input_buffers); + + mod->num_of_sources = 0; + mod->num_of_sinks = 0; + } + + mod->total_data_consumed = 0; + mod->total_data_produced = 0; + + list_for_item(blist, &mod->raw_data_buffers_list) { + struct comp_buffer *buffer = container_of(blist, struct comp_buffer, + buffers_list); + buffer_zero(buffer); + } + + mod_free(mod, mod->stream_params); + mod->stream_params = NULL; + + comp_dbg(dev, "done"); + + return comp_set_state(dev, COMP_TRIGGER_RESET); +} + +void module_adapter_free(struct comp_dev *dev) +{ + int ret; + struct processing_module *mod = comp_mod(dev); + struct list_item *blist, *_blist; + + comp_dbg(dev, "start"); + +#if CONFIG_SOF_USERSPACE_APPLICATION + if (dev->task) + /* + * Run DP module's .free() method in its thread context. + * Unlike with other IPCs we first run module's .free() in + * thread context, then cancel the thread, and then execute + * final clean up + */ + scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_DELETE_INSTANCE, NULL); +#endif + + ret = module_free(mod); + if (ret) + comp_err(dev, "failed with error: %d", ret); + + if (dev->task) + schedule_task_free(dev->task); + + list_for_item_safe(blist, _blist, &mod->raw_data_buffers_list) { + struct comp_buffer *buffer = container_of(blist, struct comp_buffer, + buffers_list); + uint32_t flags; + + irq_local_disable(flags); + list_item_del(&buffer->buffers_list); + irq_local_enable(flags); + buffer_free(buffer); + } + + mod_free(mod, mod->stream_params); + mod_free_all(mod); + + module_adapter_mem_free(mod); +} + +size_t module_adapter_heap_usage(struct processing_module *mod, size_t *hwm) +{ + struct module_resources *res = &mod->priv.resources; + + if (hwm) + *hwm = res->heap_high_water_mark; + + return res->heap_usage; +} + +/* + * \brief Get DAI hw params + * \param[in] dev - component device pointer + * \param[in] params - pointer to stream params + * \param[in] dir - stream direction + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->dai_get_hw_params) + return interface->endpoint_ops->dai_get_hw_params(dev, params, dir); + + return -EOPNOTSUPP; +} + +/* + * \brief Get stream position + * \param[in] dev - component device pointer + * \param[in] posn - pointer to stream position + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->position) + return interface->endpoint_ops->position(dev, posn); + + return -EOPNOTSUPP; +} + +/* + * \brief DAI timestamp configure + * \param[in] dev - component device pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_config_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->dai_ts_config) + return interface->endpoint_ops->dai_ts_config(dev); + + return -EOPNOTSUPP; +} + +/* + * \brief DAI timestamp start + * \param[in] dev - component device pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_start_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->dai_ts_start) + return interface->endpoint_ops->dai_ts_start(dev); + + return -EOPNOTSUPP; +} + +/* + * \brief DAI timestamp stop + * \param[in] dev - component device pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_stop_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->dai_ts_stop) + return interface->endpoint_ops->dai_ts_stop(dev); + + return -EOPNOTSUPP; +} + +/* + * \brief Get DAI timestamp + * \param[in] dev - component device pointer + * \param[in] tsd - Timestamp data pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +int module_adapter_ts_get_op(struct comp_dev *dev, struct dai_ts_data *tsd) +#else +int module_adapter_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd) +#endif +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->dai_ts_get) + return interface->endpoint_ops->dai_ts_get(dev, tsd); + + return -EOPNOTSUPP; +} diff --git a/src/audio/module_adapter/module_adapter_ipc3.c b/src/audio/module_adapter/module_adapter_ipc3.c new file mode 100644 index 000000000000..74c8f02afa2f --- /dev/null +++ b/src/audio/module_adapter/module_adapter_ipc3.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +/** + * \file + * \brief Module Adapter ipc3: module adapter ipc3 specific code + * \author Baofeng Tian <baofeng.tian@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/platform.h> +#include <sof/ut.h> +#include <rtos/interrupt.h> +#include <limits.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); + +/* + * \module adapter data initialize. + * \param[in] dev - device. + * \param[in] config - component ipc descriptor pointer. + * \param[in] dst - module adapter config data. + * \param[in] spec - passdowned data from driver. + * + * \return: 0 - no error; < 0, error happened. + */ +int module_adapter_init_data(struct comp_dev *dev, + struct module_config *dst, + const struct comp_ipc_config *config, + const void *spec) +{ + int ret; + + const unsigned char *data = NULL; + uint32_t size = 0; + + switch (config->type) { + case SOF_COMP_VOLUME: + { + const struct ipc_config_volume *ipc_volume = spec; + + size = sizeof(*ipc_volume); + data = spec; + break; + } + case SOF_COMP_SRC: + { + const struct ipc_config_src *ipc_src = spec; + + size = sizeof(*ipc_src); + data = spec; + break; + } + case SOF_COMP_ASRC: + { + const struct ipc_config_asrc *ipc_asrc = spec; + + size = sizeof(*ipc_asrc); + data = spec; + break; + } + case SOF_COMP_MIXER: + break; + case SOF_COMP_EQ_IIR: + case SOF_COMP_EQ_FIR: + case SOF_COMP_KEYWORD_DETECT: + case SOF_COMP_KPB: + case SOF_COMP_SELECTOR: + case SOF_COMP_DEMUX: + case SOF_COMP_MUX: + case SOF_COMP_DCBLOCK: + case SOF_COMP_SMART_AMP: + case SOF_COMP_MODULE_ADAPTER: + case SOF_COMP_FILEREAD: + case SOF_COMP_FILEWRITE: + case SOF_COMP_NONE: + { + const struct ipc_config_process *ipc_module_adapter = spec; + + size = ipc_module_adapter->size; + data = ipc_module_adapter->data; + break; + } + default: + comp_err(dev, "unsupported comp type %d", config->type); + return -EINVAL; + } + + /* Copy initial config */ + if (size) { + ret = module_load_config(dev, data, size); + if (ret < 0) { + comp_err(dev, "error %d: config loading has failed.", + ret); + return ret; + } + dst->init_data = dst->data; + } + + return 0; +} + +void module_adapter_reset_data(struct module_config *dst) +{ +} + +void module_adapter_check_data(struct processing_module *mod, struct comp_dev *dev, + struct comp_buffer *sink) +{ + /* Check if audio stream client has only one source and one sink buffer to use a + * simplified copy function. + */ + if (IS_PROCESSING_MODE_AUDIO_STREAM(mod) && mod->num_of_sources == 1 && + mod->num_of_sinks == 1) { + mod->source_comp_buffer = comp_dev_get_first_data_producer(dev); + mod->sink_comp_buffer = sink; + mod->stream_copy_single_to_single = true; + } +} + +void module_adapter_set_params(struct processing_module *mod, struct sof_ipc_stream_params *params) +{ +} + +static int module_source_state_count(struct comp_dev *dev, uint32_t state) +{ + int count = 0; + struct comp_buffer *source; + + /* count source with state == status */ + comp_dev_for_each_producer(dev, source) + /* + * FIXME: this is racy, state can be changed by another core. + * This is implicitly protected by serialised IPCs. Even when + * IPCs are processed in the pipeline thread, the next IPC will + * not be sent until the thread has processed and replied to the + * current one. + */ + if (comp_buffer_get_source_state(source) == state) + count++; + + return count; +} + +int module_adapter_set_state(struct processing_module *mod, struct comp_dev *dev, + int cmd) +{ + if (mod->num_of_sources > 1) { + bool sources_active; + int ret; + + sources_active = module_source_state_count(dev, COMP_STATE_ACTIVE) || + module_source_state_count(dev, COMP_STATE_PAUSED); + + /* don't stop/start module if one of the sources is active/paused */ + if ((cmd == COMP_TRIGGER_STOP || cmd == COMP_TRIGGER_PRE_START) && sources_active) { + dev->state = COMP_STATE_ACTIVE; + return PPL_STATUS_PATH_STOP; + } + + ret = comp_set_state(dev, cmd); + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return ret; + } + + return comp_set_state(dev, cmd); +} + +static int module_adapter_get_set_params(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, + bool set) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + enum module_cfg_fragment_position pos; + uint32_t data_offset_size; + static uint32_t size; + + comp_dbg(dev, "num_of_elem %d, elem remain %d msg_index %u", + cdata->num_elems, cdata->elems_remaining, cdata->msg_index); + + /* set the fragment position, data offset and config data size */ + if (!cdata->msg_index) { + size = cdata->num_elems + cdata->elems_remaining; + data_offset_size = size; + if (cdata->elems_remaining) + pos = MODULE_CFG_FRAGMENT_FIRST; + else + pos = MODULE_CFG_FRAGMENT_SINGLE; + } else { + data_offset_size = size - (cdata->num_elems + cdata->elems_remaining); + if (cdata->elems_remaining) + pos = MODULE_CFG_FRAGMENT_MIDDLE; + else + pos = MODULE_CFG_FRAGMENT_LAST; + } + + if (set) { + /* + * The type member in struct sof_abi_hdr is used for component's specific blob type + * for IPC3, just like it is used for component's specific blob param_id for IPC4. + */ + if (interface->set_configuration) + return interface->set_configuration(mod, cdata->data[0].type, pos, + data_offset_size, + (const uint8_t *)cdata, + cdata->num_elems, NULL, 0); + + comp_warn(dev, "no configuration op set for %d", + dev_comp_id(dev)); + return 0; + } + + if (interface->get_configuration) + return interface->get_configuration(mod, pos, &data_offset_size, + (uint8_t *)cdata, cdata->num_elems); + + comp_err(dev, "no configuration op get for %d", + dev_comp_id(dev)); + return -EIO; /* non-implemented error */ +} + +static int module_adapter_ctrl_get_set_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, + bool set) +{ + int ret; + struct processing_module __maybe_unused *mod = comp_mod(dev); + + comp_dbg(dev, "module_adapter_ctrl_set_data() start, state %d, cmd %d", + mod->priv.state, cdata->cmd); + + /* Check version from ABI header */ + if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { + comp_err(dev, "ABI mismatch!"); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_err(dev, "set enum is not implemented"); + ret = -EIO; + break; + case SOF_CTRL_CMD_BINARY: + ret = module_adapter_get_set_params(dev, cdata, set); + break; + default: + comp_err(dev, "module_adapter_ctrl_set_data error: unknown set data command"); + ret = -EINVAL; + break; + } + + return ret; +} + +/* Used to pass standard and bespoke commands (with data) to component */ +int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) +{ + struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + int ret = 0; + + comp_dbg(dev, "%d start", cmd); + + switch (cmd) { + case COMP_CMD_SET_DATA: + ret = module_adapter_ctrl_get_set_data(dev, cdata, true); + break; + case COMP_CMD_GET_DATA: + ret = module_adapter_ctrl_get_set_data(dev, cdata, false); + break; + case COMP_CMD_SET_VALUE: + /* + * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored + * anyway. Also, pass the 0 as the fragment size as it is not relevant for the + * SET_VALUE command. + */ + if (interface->set_configuration) + ret = interface->set_configuration(mod, 0, + MODULE_CFG_FRAGMENT_SINGLE, 0, + (const uint8_t *)cdata, 0, NULL, + 0); + break; + case COMP_CMD_GET_VALUE: + /* + * Return error if getter is not implemented. Otherwise, the host will suppose + * the GET_VALUE command is successful, but the received cdata is not filled. + */ + ret = -EIO; + + /* + * IPC3 does not use config_id, so pass 0 for config ID as it will be ignored + * anyway. Also, pass the 0 as the fragment size and data offset as they are not + * relevant for the GET_VALUE command. + */ + if (interface->get_configuration) + ret = interface->get_configuration(mod, 0, 0, (uint8_t *)cdata, 0); + break; + default: + comp_err(dev, "error: unknown command"); + ret = -EINVAL; + break; + } + + comp_dbg(dev, "done"); + return ret; +} + +int module_adapter_sink_src_prepare(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct comp_buffer *sink_buffer; + struct comp_buffer *source_buffer; + int i; + + /* acquire all sink and source buffers, get handlers to sink/source API */ + i = 0; + comp_dev_for_each_consumer(dev, sink_buffer) { + mod->sinks[i] = audio_buffer_get_sink(&sink_buffer->audio_buffer); + i++; + } + mod->num_of_sinks = i; + + i = 0; + comp_dev_for_each_producer(dev, source_buffer) { + mod->sources[i] = audio_buffer_get_source(&source_buffer->audio_buffer); + i++; + } + mod->num_of_sources = i; + + /* Prepare module */ + return module_prepare(mod, mod->sources, mod->num_of_sources, mod->sinks, + mod->num_of_sinks); +} diff --git a/src/audio/module_adapter/module_adapter_ipc4.c b/src/audio/module_adapter/module_adapter_ipc4.c new file mode 100644 index 000000000000..74d39559a004 --- /dev/null +++ b/src/audio/module_adapter/module_adapter_ipc4.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +/** + * \file + * \brief Module Adapter ipc4: module adapter ipc4 specific code + * \author Baofeng Tian <baofeng.tian@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/lib/mailbox.h> +#include <sof/platform.h> +#include <sof/ut.h> +#include <rtos/interrupt.h> +#include <rtos/symbol.h> +#include <ipc4/base_fw.h> +#include <limits.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); + +int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init_data *ext_data, + struct ipc_config_process *spec) +{ + const struct ipc4_module_init_ext_init *ext_init; + const struct ipc4_module_init_ext_object *obj; + bool last_object; + size_t consumed; + + assert(drv->type == SOF_COMP_MODULE_ADAPTER); + + /* Validate size before dereferencing ext_init pointer */ + if (spec->size < sizeof(*ext_init)) { + comp_cl_err(drv, "Size too small for ext init %u < %zu", + spec->size, sizeof(*ext_init)); + return -EINVAL; + } + + ext_init = (const struct ipc4_module_init_ext_init *)spec->data; + last_object = !ext_init->data_obj_array; + /* TODO: Handle ext_init->gna_used and ext_init->rtos_domain here */ + /* Get the first obj struct right after ext_init struct */ + obj = (const struct ipc4_module_init_ext_object *)(ext_init + 1); + while (!last_object) { + const struct ipc4_module_init_ext_object *next_obj; + + /* Check if there is space for the object header */ + if ((unsigned char *)(obj + 1) - spec->data > spec->size) { + comp_cl_err(drv, "ext init obj overflow, %u > %u", + (unsigned char *)(obj + 1) - spec->data, spec->size); + return -EINVAL; + } + /* Calculate would be next object position and check if current object fits */ + next_obj = (const struct ipc4_module_init_ext_object *) + (((uint32_t *) (obj + 1)) + obj->object_words); + if ((unsigned char *)next_obj - spec->data > spec->size) { + comp_cl_err(drv, "ext init object array overflow, %u > %u", + (unsigned char *)obj - spec->data, spec->size); + return -EINVAL; + } + switch (obj->object_id) { + case IPC4_MOD_INIT_DATA_ID_DP_DATA: + { + /* Get dp_data struct that follows the obj struct */ + const struct ipc4_module_init_ext_obj_dp_data *dp_data = + (const struct ipc4_module_init_ext_obj_dp_data *)(obj + 1); + + if (obj->object_words * sizeof(uint32_t) < sizeof(*dp_data)) { + comp_cl_warn(drv, "dp_data object too small %zu < %zu", + obj->object_words * sizeof(uint32_t), + sizeof(*dp_data)); + break; + } + ext_data->dp_data = dp_data; + comp_cl_info(drv, + "init_ext_obj_dp_data domain %u stack %u interim %u lifetime %u shared %u", + dp_data->domain_id, dp_data->stack_bytes, + dp_data->interim_heap_bytes, dp_data->lifetime_heap_bytes, + dp_data->shared_bytes); + break; + } + case IPC4_MOD_INIT_DATA_ID_MODULE_DATA: + { + /* + * set the module init_data. Modules must copy/save this in their init + * callbacks if they need this to be persistent + */ + ext_data->module_data = (const void *)(obj + 1); + ext_data->module_data_size = obj->object_words * sizeof(uint32_t); + comp_cl_info(drv, "module init data size %u bytes", + ext_data->module_data_size); + break; + } + default: + comp_cl_info(drv, "Unknown ext init object id %u of %u words", + obj->object_id, obj->object_words); + } + /* Read the last object flag from obj header */ + last_object = obj->last_object; + /* Move to next object */ + obj = next_obj; + } + + /* + * Remove decoded ext_init payload from spec. + * consumed <= spec->size is guaranteed here: + * - no-loop path: consumed == sizeof(*ext_init) <= spec->size (validated above) + * - loop path: in-loop bounds checks (obj/next_obj vs spec->size) ensure + * obj never advances past spec->data + spec->size + */ + consumed = (unsigned char *)obj - spec->data; + assert(consumed <= spec->size); + + spec->size -= consumed; + spec->data = (const unsigned char *)obj; + + return 0; +} + +/* + * \module adapter data initialize. + * \param[in] dev - device. + * \param[in] config - component ipc descriptor pointer. + * \param[in] dst - module adapter config data. + * \param[in] spec - passdowned data from driver. + * + * \return: 0 - no error; < 0, error happened. + */ +int module_adapter_init_data(struct comp_dev *dev, + struct module_config *dst, + const struct comp_ipc_config *config, + const void *spec) +{ + const struct ipc4_base_module_extended_cfg *cfg; + const struct ipc_config_process *args = spec; + size_t cfgsz = args->size; + + assert(dev->drv->type == SOF_COMP_MODULE_ADAPTER); + cfg = (const struct ipc4_base_module_extended_cfg *)args->data; + + if (cfg == NULL) + return -EINVAL; + if (cfgsz > MAILBOX_HOSTBOX_SIZE || cfgsz < sizeof(cfg->base_cfg)) { + comp_err(dev, "invalid config size %zu", cfgsz); + return -EINVAL; + } + + dst->base_cfg = cfg->base_cfg; + dst->size = cfgsz; + + if (cfgsz >= sizeof(*cfg)) { + int n_in = cfg->base_cfg_ext.nb_input_pins; + int n_out = cfg->base_cfg_ext.nb_output_pins; + size_t pinsz = (n_in * sizeof(*dst->input_pins)) + + (n_out * sizeof(*dst->output_pins)); + + if (cfgsz == (sizeof(*cfg) + pinsz)) { + if (n_in > IPC4_MAX_SRC_QUEUE || n_out > IPC4_MAX_DST_QUEUE) + return -EINVAL; + + dst->nb_input_pins = n_in; + dst->nb_output_pins = n_out; + dst->input_pins = sof_heap_alloc(dev->mod->priv.resources.alloc->heap, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + pinsz, 0); + if (!dst->input_pins) + return -ENOMEM; + + dst->output_pins = (void *)&dst->input_pins[n_in]; + memcpy_s(dst->input_pins, pinsz, + &cfg->base_cfg_ext.pin_formats[0], pinsz); + } + } + + /* Assume legacy API if module data was not found in ext_init payload */ + if (!config->ipc_extended_init || !dst->ext_data->module_data) { + dst->init_data = cfg; /* legacy API */ + dst->avail = true; + } + + return 0; +} + +void module_adapter_reset_data(struct module_config *dst) +{ + dst->init_data = NULL; +} + +void module_adapter_check_data(struct processing_module *mod, struct comp_dev *dev, + struct comp_buffer *sink) +{ +} + +void module_adapter_set_params(struct processing_module *mod, struct sof_ipc_stream_params *params) +{ + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); +} + +int module_adapter_set_state(struct processing_module *mod, struct comp_dev *dev, + int cmd) +{ + return comp_set_state(dev, cmd); +} +EXPORT_SYMBOL(module_adapter_set_state); + +int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, + bool last_block, uint32_t data_offset_size, const char *data) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + struct module_data *md = &mod->priv; + enum module_cfg_fragment_position pos; + size_t fragment_size; + + /* set fragment position */ + pos = first_last_block_to_frag_pos(first_block, last_block); + + switch (pos) { + case MODULE_CFG_FRAGMENT_SINGLE: + fragment_size = data_offset_size; + break; + case MODULE_CFG_FRAGMENT_MIDDLE: + fragment_size = MAILBOX_DSPBOX_SIZE; + break; + case MODULE_CFG_FRAGMENT_FIRST: + md->new_cfg_size = data_offset_size; + fragment_size = MAILBOX_DSPBOX_SIZE; + break; + case MODULE_CFG_FRAGMENT_LAST: + fragment_size = md->new_cfg_size - data_offset_size; + break; + default: + comp_err(dev, "invalid fragment position"); + return -EINVAL; + } + + if (interface->set_configuration) + return interface->set_configuration(mod, param_id, pos, data_offset_size, + (const uint8_t *)data, fragment_size, + NULL, 0); + return 0; +} + +int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, + bool last_block, uint32_t *data_offset_size, char *data) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + struct module_data *md = &mod->priv; + size_t fragment_size; + + /* set fragment size */ + if (first_block) { + if (last_block) + fragment_size = md->cfg.size; + else + fragment_size = SOF_IPC_MSG_MAX_SIZE; + } else { + if (!last_block) + fragment_size = SOF_IPC_MSG_MAX_SIZE; + else + fragment_size = md->cfg.size - *data_offset_size; + } + + if (interface->get_configuration) + return interface->get_configuration(mod, param_id, data_offset_size, + (uint8_t *)data, fragment_size); + /* + * Return error if getter is not implemented. Otherwise, the host will suppose + * the GET_VALUE command is successful, but the received cdata is not filled. + */ + return -EIO; +} + +int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + switch (type) { + case COMP_ATTR_BASE_CONFIG: + memcpy_s(value, sizeof(struct ipc4_base_module_cfg), + &mod->priv.cfg.base_cfg, sizeof(mod->priv.cfg.base_cfg)); + break; + case COMP_ATTR_IPC4_CONFIG: + if (interface->get_config_param) + return interface->get_config_param(mod, (uint32_t *)value); + return -ENOEXEC; + default: + return -EINVAL; + } + + return 0; +} + +int module_adapter_set_attribute(struct comp_dev *dev, uint32_t type, void *value) +{ + struct processing_module *mod = comp_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + switch (type) { + case COMP_ATTR_IPC4_CONFIG: + if (interface->set_config_param) + return interface->set_config_param(mod, *(uint32_t *)value); + return -ENOEXEC; + default: + return -EINVAL; + } + + return 0; +} + +static bool module_adapter_multi_sink_source_prepare(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + struct comp_buffer *sink_buffer; + struct comp_buffer *source_buffer; + int i; + + /* acquire all sink and source buffers, get handlers to sink/source API */ + i = 0; + comp_dev_for_each_consumer(dev, sink_buffer) { + mod->sinks[i] = audio_buffer_get_sink(&sink_buffer->audio_buffer); + i++; + } + mod->num_of_sinks = i; + + i = 0; + comp_dev_for_each_producer(dev, source_buffer) { + mod->sources[i] = audio_buffer_get_source(&source_buffer->audio_buffer); + i++; + } + mod->num_of_sources = i; + + comp_dbg(dev, "num_sources=%d num_sinks=%d", mod->num_of_sinks, mod->num_of_sources); + + if (mod->num_of_sinks != 1 || mod->num_of_sources != 1) + return true; + + /* re-assign the source/sink modules */ + mod->sink_comp_buffer = comp_dev_get_first_data_consumer(dev); + mod->source_comp_buffer = comp_dev_get_first_data_producer(dev); + + return false; +} + +static int module_update_source_buffer_params(struct processing_module *mod, + struct bind_info *bind_data) +{ + struct module_config *dst = &mod->priv.cfg; + struct sof_ipc_stream_params params; + struct comp_buffer *buffer; + int dst_queue_id = bind_data->ipc4_data->extension.r.dst_queue; + + /* only update buffer params for sink components */ + if (bind_data->bind_type != COMP_BIND_TYPE_SOURCE) + return 0; + + comp_dev_for_each_producer(mod->dev, buffer) { + if (IPC4_SINK_QUEUE_ID(buffer->stream.runtime_stream_params.id) != dst_queue_id) + continue; + + /* use base_cfg params for pin 0 or if base config extn is missing */ + if (!dst_queue_id || dst_queue_id >= dst->nb_input_pins) { + buffer_set_params(buffer, mod->stream_params, BUFFER_UPDATE_FORCE); + return 0; + } + + /* otherwise use the respective input pin audio format */ + ipc4_audio_format_to_stream_params(&dst->input_pins[dst_queue_id].audio_fmt, + ¶ms); + buffer_set_params(buffer, ¶ms, BUFFER_UPDATE_FORCE); + return 0; + } + + return 0; +} + +int module_adapter_bind(struct comp_dev *dev, struct bind_info *bind_data) +{ + struct processing_module *mod = comp_mod(dev); + int ret; + + ret = module_update_source_buffer_params(mod, bind_data); + if (ret < 0) + return ret; + + ret = module_bind(mod, bind_data); + if (ret < 0) + return ret; + + mod->stream_copy_single_to_single = !module_adapter_multi_sink_source_prepare(dev); + + return 0; +} + +int module_adapter_unbind(struct comp_dev *dev, struct bind_info *unbind_data) +{ + struct processing_module *mod = comp_mod(dev); + int ret; + + ret = module_unbind(mod, unbind_data); + if (ret < 0) + return ret; + + mod->stream_copy_single_to_single = !module_adapter_multi_sink_source_prepare(dev); + + 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_mod(dev); + const struct module_interface *const interface = mod->dev->drv->adapter_ops; + + if (interface->endpoint_ops && interface->endpoint_ops->get_total_data_processed) + return interface->endpoint_ops->get_total_data_processed(dev, stream_no, input); + + if (input) + return mod->total_data_produced; + else + return mod->total_data_consumed; +} + +int module_adapter_sink_src_prepare(struct comp_dev *dev) +{ + struct processing_module *mod = comp_mod(dev); + + /* Prepare module */ + return module_prepare(mod, mod->sources, mod->num_of_sources, + mod->sinks, mod->num_of_sinks); +} diff --git a/src/audio/multiband_drc/CMakeLists.txt b/src/audio/multiband_drc/CMakeLists.txt new file mode 100644 index 000000000000..0651cb9884e6 --- /dev/null +++ b/src/audio/multiband_drc/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_MULTIBAND_DRC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/multiband_drc_llext) + add_dependencies(app multiband_drc) +else() + add_local_sources(sof multiband_drc.c) + add_local_sources(sof multiband_drc_generic.c) + + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof multiband_drc_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof multiband_drc_ipc4.c) + endif() +endif() diff --git a/src/audio/multiband_drc/Kconfig b/src/audio/multiband_drc/Kconfig new file mode 100644 index 000000000000..07a67573cf24 --- /dev/null +++ b/src/audio/multiband_drc/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MULTIBAND_DRC + depends on COMP_IIR && COMP_CROSSOVER && COMP_DRC + tristate "Multiband Dynamic Range Compressor component" + select CORDIC_FIXED + select COMP_BLOB + default m if LIBRARY_DEFAULT_MODULAR + help + Select for Multiband Dynamic Range Compressor (DRC) component. It + consists of Emphasis Equalizer, n-way Crossover Filter, per-band DRC, + and Deemphasis Equalizer. diff --git a/src/audio/multiband_drc/README.md b/src/audio/multiband_drc/README.md new file mode 100644 index 000000000000..2a86e93ddbb6 --- /dev/null +++ b/src/audio/multiband_drc/README.md @@ -0,0 +1,27 @@ +# Multi-Band DRC Architecture + +This directory contains the Multi-Band Dynamic Range Compressor. + +## Overview + +Splits the audio into several discrete frequency bands (e.g., bass, mids, treble) and applies a separate instance of DRC to each band before remixing them. + +## Architecture Diagram + +```mermaid +graph LR + In[Audio Input] --> Splitter[Band Splitter] + Splitter --> DRC1[DRC Band 1] + Splitter --> DRC2[DRC Band 2] + DRC1 --> Sum[Mixer] + DRC2 --> Sum + Sum --> Out[Audio Output] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the Multiband Dynamic Range Compressor component (`COMP_MULTIBAND_DRC`). Has explicit dependencies on standard equalizers and filters: `COMP_IIR && COMP_CROSSOVER && COMP_DRC`. +- **CMakeLists.txt**: Compiles `multiband_drc.c` and generic versions, wrapping with IPC specifics (`multiband_drc_ipc3.c` or `multiband_drc_ipc4.c`). Supports Zephyr loadable extensions (`llext`). +- **multiband_drc.toml**: Defines module topology constraints and mapping (UUID `UUIDREG_STR_MULTIBAND_DRC`, module type 9). +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/multiband_drc.conf`, configuring the `multiband_drc` widget object of type `effect` (UUID `56:22:9f:0d:4f:8e:b3:47:84:48:23:9a:33:4f:11:91`). Utilizes an internal switch control for `fc`. +- **MATLAB Tuning (`tune/`)**: Features `sof_example_multiband_drc.m` to generate the complex configuration structures necessary to bind multiple EQs, crossovers, and compressors together. The scripts output the aggregated `.m4`, binary `.bin`, and ALSA `.txt` blobs which define parameter blocks for each individual sub-system active within the multiband processor. diff --git a/src/audio/multiband_drc/llext/CMakeLists.txt b/src/audio/multiband_drc/llext/CMakeLists.txt new file mode 100644 index 000000000000..dbafe5164220 --- /dev/null +++ b/src/audio/multiband_drc/llext/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("multiband_drc" + SOURCES ../multiband_drc.c + ../multiband_drc_generic.c + ../multiband_drc_ipc4.c + LIB openmodules +) diff --git a/src/audio/multiband_drc/llext/llext.toml.h b/src/audio/multiband_drc/llext/llext.toml.h new file mode 100644 index 000000000000..7d5ce873eeb0 --- /dev/null +++ b/src/audio/multiband_drc/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../multiband_drc.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c new file mode 100644 index 000000000000..84a079134ea1 --- /dev/null +++ b/src/audio/multiband_drc/multiband_drc.c @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <module/crossover/crossover_common.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <rtos/panic.h> +#include <rtos/string.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/ut.h> +#include <user/eq.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "../drc/drc_algorithm.h" +#include "multiband_drc.h" + +LOG_MODULE_REGISTER(multiband_drc, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(multiband_drc); + +/* Called from multiband_drc_setup() from multiband_drc_process(), so cannot be __cold */ +static void multiband_drc_reset_state(struct processing_module *mod, + struct multiband_drc_state *state) +{ + int i; + + /* Reset emphasis eq-iir state */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + multiband_drc_iir_reset_state_ch(mod, &state->emphasis[i]); + + /* Reset crossover state */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + crossover_reset_state_ch(mod, &state->crossover[i]); + + /* Reset drc kernel state */ + for (i = 0; i < SOF_MULTIBAND_DRC_MAX_BANDS; i++) + drc_reset_state(mod, &state->drc[i]); + + /* Reset deemphasis eq-iir state */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + multiband_drc_iir_reset_state_ch(mod, &state->deemphasis[i]); +} + +static int multiband_drc_eq_init_coef_ch(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, + struct iir_state_df1 *eq) +{ + int ret; + + /* Ensure the LR4 can be processed with the simplified 4th order IIR */ + if (SOF_EMP_DEEMP_BIQUADS != SOF_IIR_DF1_4TH_NUM_BIQUADS) + return -EINVAL; + + eq->coef = mod_zalloc(mod, sizeof(struct sof_eq_iir_biquad) * SOF_EMP_DEEMP_BIQUADS); + if (!eq->coef) + return -ENOMEM; + + /* Coefficients of the first biquad and second biquad */ + ret = memcpy_s(eq->coef, sizeof(struct sof_eq_iir_biquad) * SOF_EMP_DEEMP_BIQUADS, + coef, sizeof(struct sof_eq_iir_biquad) * SOF_EMP_DEEMP_BIQUADS); + assert(!ret); + + /* EQ filters are two 2nd order filters, so only need 4 delay slots + * delay[0..1] -> state for first biquad + * delay[2..3] -> state for second biquad + */ + eq->delay = mod_zalloc(mod, sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4); + if (!eq->delay) + return -ENOMEM; + + eq->biquads = SOF_EMP_DEEMP_BIQUADS; + eq->biquads_in_series = SOF_EMP_DEEMP_BIQUADS; + + return 0; +} + +static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, uint32_t rate) +{ + struct comp_dev *dev = mod->dev; + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct sof_eq_iir_biquad *crossover; + struct sof_eq_iir_biquad *emphasis; + struct sof_eq_iir_biquad *deemphasis; + struct sof_multiband_drc_config *config = cd->config; + struct multiband_drc_state *state = &cd->state; + uint32_t sample_bytes = get_sample_bytes(cd->source_format); + int i, ch, ret, num_bands; + + if (!config) { + comp_err(dev, "no config is set"); + return -EINVAL; + } + + num_bands = config->num_bands; + + /* Sanity checks */ + if (nch > PLATFORM_MAX_CHANNELS) { + comp_err(dev, + "invalid channels count(%i)", nch); + return -EINVAL; + } + if (config->num_bands > SOF_MULTIBAND_DRC_MAX_BANDS) { + comp_err(dev, "invalid bands count(%i)", + config->num_bands); + return -EINVAL; + } + + comp_info(dev, "initializing %i-way crossover", + config->num_bands); + + /* Crossover: determine the split function */ + cd->crossover_split = crossover_find_split_func(config->num_bands); + if (!cd->crossover_split) { + comp_err(dev, "No crossover_split for band count(%i)", + config->num_bands); + return -EINVAL; + } + + /* Crossover: collect the coef array and assign it to every channel */ + crossover = config->crossover_coef; + for (ch = 0; ch < nch; ch++) { + ret = crossover_init_coef_ch(mod, crossover, &state->crossover[ch], + config->num_bands); + /* Free all previously allocated blocks in case of an error */ + if (ret < 0) { + comp_err(dev, + "could not assign coeffs to ch %d", ch); + goto err; + } + } + + comp_info(dev, "initializing emphasis_eq"); + + /* Emphasis: collect the coef array and assign it to every channel */ + emphasis = config->emp_coef; + for (ch = 0; ch < nch; ch++) { + ret = multiband_drc_eq_init_coef_ch(mod, emphasis, &state->emphasis[ch]); + /* Free all previously allocated blocks in case of an error */ + if (ret < 0) { + comp_err(dev, "could not assign coeffs to ch %d", + ch); + goto err; + } + } + + comp_info(dev, "initializing deemphasis_eq"); + + /* Deemphasis: collect the coef array and assign it to every channel */ + deemphasis = config->deemp_coef; + for (ch = 0; ch < nch; ch++) { + ret = multiband_drc_eq_init_coef_ch(mod, deemphasis, &state->deemphasis[ch]); + /* Free all previously allocated blocks in case of an error */ + if (ret < 0) { + comp_err(dev, "could not assign coeffs to ch %d", + ch); + goto err; + } + } + + /* Allocate all DRC pre-delay buffers and set delay time with band number */ + for (i = 0; i < num_bands; i++) { + comp_info(dev, "initializing drc band %d", i); + + ret = drc_init_pre_delay_buffers(mod, &state->drc[i], + (size_t)sample_bytes, (int)nch); + if (ret < 0) { + comp_err(dev, + "could not init pre delay buffers"); + goto err; + } + + ret = drc_set_pre_delay_time(&state->drc[i], + cd->config->drc_coef[i].pre_delay_time, rate); + if (ret < 0) { + comp_err(dev, "could not set pre delay time"); + goto err; + } + } + + return 0; + +err: + multiband_drc_reset_state(mod, state); + return ret; +} + +/* Called from multiband_drc_process(), so cannot be __cold */ +static int multiband_drc_setup(struct processing_module *mod, int16_t channels, + uint32_t rate) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + + /* Reset any previous state */ + multiband_drc_reset_state(mod, &cd->state); + + /* Setup Crossover, Emphasis EQ, Deemphasis EQ, and DRC */ + return multiband_drc_init_coef(mod, channels, rate); +} + +/* + * End of Multiband DRC setup code. Next the standard component methods. + */ + +static int multiband_drc_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct multiband_drc_comp_data *cd; + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + cd->multiband_drc_func = NULL; + cd->crossover_split = NULL; + /* Initialize to enabled is a workaround for IPC4 kernel version 6.6 and + * before where the processing is never enabled via switch control. New + * kernel sends the IPC4 switch control and sets this to desired state + * before prepare. + */ + multiband_drc_process_enable(&cd->process_enabled); + + /* Handler for configuration data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "comp_data_blob_handler_new() failed."); + mod_free(mod, cd); + return -ENOMEM; + } + + multiband_drc_reset_state(mod, &cd->state); + + return 0; +} + +__cold static int multiband_drc_free(struct processing_module *mod) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + comp_info(mod->dev, "entry"); + + mod_data_blob_handler_free(mod, cd->model_handler); + + mod_free(mod, cd); + return 0; +} + +__cold static int multiband_drc_set_config(struct processing_module *mod, uint32_t param_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; + + assert_can_be_cold(); + + comp_dbg(dev, "entry"); + + return multiband_drc_set_ipc_config(mod, param_id, + fragment, pos, data_offset_size, fragment_size); +} + +__cold static int multiband_drc_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + assert_can_be_cold(); + + comp_dbg(mod->dev, "entry"); + + return multiband_drc_get_ipc_config(mod, cdata, fragment_size); +} + +static int multiband_drc_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 multiband_drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + int frames = input_buffers[0].size; + int ret; + + comp_dbg(dev, "entry"); + + /* 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(mod, (int16_t)audio_stream_get_channels(sink), + audio_stream_get_rate(sink)); + if (ret < 0) { + comp_err(dev, "failed DRC setup"); + return ret; + } + } + + if (cd->process_enabled) + cd->multiband_drc_func(mod, source, sink, frames); + else + multiband_drc_default_pass(mod, source, sink, frames); + + /* calc new free and available */ + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frames); + return 0; +} + +static int multiband_drc_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sourceb; + size_t data_size; + int channels; + int rate; + int ret = 0; + + comp_info(dev, "entry"); + + ret = multiband_drc_params(mod); + if (ret < 0) + return ret; + + /* DRC component will only ever have 1 source and 1 sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + if (!sourceb) { + comp_err(dev, "no source buffer"); + return -ENOTCONN; + } + + /* get source data format */ + cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); + channels = audio_stream_get_channels(&sourceb->stream); + rate = audio_stream_get_rate(&sourceb->stream); + + /* Initialize DRC */ + comp_dbg(dev, "source_format=%d, sink_format=%d", + cd->source_format, cd->source_format); + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + if (cd->config && data_size > 0) { + ret = multiband_drc_setup(mod, channels, rate); + if (ret < 0) { + comp_err(dev, "error: multiband_drc_setup failed."); + return ret; + } + } + + cd->multiband_drc_func = multiband_drc_find_proc_func(cd->source_format); + if (!cd->multiband_drc_func) { + comp_err(dev, "No proc func"); + return -EINVAL; + } + + return ret; +} + +static int multiband_drc_reset(struct processing_module *mod) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + multiband_drc_reset_state(mod, &cd->state); + + cd->source_format = 0; + cd->multiband_drc_func = NULL; + cd->crossover_split = NULL; + + return 0; +} + +static const struct module_interface multiband_drc_interface = { + .init = multiband_drc_init, + .prepare = multiband_drc_prepare, + .process_audio_stream = multiband_drc_process, + .set_configuration = multiband_drc_set_config, + .get_configuration = multiband_drc_get_config, + .reset = multiband_drc_reset, + .free = multiband_drc_free +}; + +#if CONFIG_COMP_MULTIBAND_DRC_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("MB_DRC", &multiband_drc_interface, 1, + SOF_REG_UUID(multiband_drc), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(multiband_drc_tr, SOF_UUID(multiband_drc_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(multiband_drc_interface, multiband_drc_uuid, multiband_drc_tr); +SOF_MODULE_INIT(multiband_drc, sys_comp_module_multiband_drc_interface_init); + +#endif diff --git a/src/audio/multiband_drc/multiband_drc.h b/src/audio/multiband_drc/multiband_drc.h new file mode 100644 index 000000000000..6a99fda55cef --- /dev/null +++ b/src/audio/multiband_drc/multiband_drc.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ +#ifndef __SOF_AUDIO_MULTIBAND_DRC_MULTIBAND_DRC_H__ +#define __SOF_AUDIO_MULTIBAND_DRC_MULTIBAND_DRC_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <module/crossover/crossover_common.h> +#include <sof/math/iir_df1.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/platform.h> +#include <stdint.h> + +#include "../drc/drc.h" +#include "user/multiband_drc.h" + +/** + * Stores the state of the sub-components in Multiband DRC + */ +struct multiband_drc_state { + struct iir_state_df1 emphasis[PLATFORM_MAX_CHANNELS]; + struct crossover_state crossover[PLATFORM_MAX_CHANNELS]; + struct drc_state drc[SOF_MULTIBAND_DRC_MAX_BANDS]; + struct iir_state_df1 deemphasis[PLATFORM_MAX_CHANNELS]; +}; + +typedef void (*multiband_drc_func)(const struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames); + +/* Multiband DRC component private data */ +struct multiband_drc_comp_data { + struct multiband_drc_state state; /**< compressor state */ + struct comp_data_blob_handler *model_handler; + struct sof_multiband_drc_config *config; /**< pointer to setup blob */ + bool config_ready; /**< set when fully received */ + enum sof_ipc_frame source_format; /**< source frame format */ + bool process_enabled; /**< true if component is enabled */ + multiband_drc_func multiband_drc_func; /**< processing function */ + crossover_split crossover_split; /**< crossover n-way split func */ +}; + +struct multiband_drc_proc_fnmap { + enum sof_ipc_frame frame_fmt; + multiband_drc_func multiband_drc_proc_func; +}; + +extern const struct multiband_drc_proc_fnmap multiband_drc_proc_fnmap[]; +extern const struct multiband_drc_proc_fnmap multiband_drc_proc_fnmap_pass[]; +extern const size_t multiband_drc_proc_fncount; + +void multiband_drc_default_pass(const struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames); + +/** + * \brief Returns Multiband DRC processing function. + */ +static inline multiband_drc_func multiband_drc_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < multiband_drc_proc_fncount; i++) + if (src_fmt == multiband_drc_proc_fnmap[i].frame_fmt) + return multiband_drc_proc_fnmap[i].multiband_drc_proc_func; + + return NULL; +} + +/** + * \brief Returns Multiband DRC passthrough functions. + */ +static inline multiband_drc_func multiband_drc_find_proc_func_pass(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < drc_proc_fncount; i++) + if (src_fmt == multiband_drc_proc_fnmap_pass[i].frame_fmt) + return multiband_drc_proc_fnmap_pass[i].multiband_drc_proc_func; + + return NULL; +} + +static inline void multiband_drc_iir_reset_state_ch(struct processing_module *mod, + struct iir_state_df1 *iir) +{ + mod_free(mod, iir->coef); + mod_free(mod, iir->delay); + + iir->coef = NULL; + iir->delay = NULL; +} + +void multiband_drc_process_enable(bool *process_enabled); +int multiband_drc_set_ipc_config(struct processing_module *mod, uint32_t param_id, + const uint8_t *fragment, enum module_cfg_fragment_position pos, + uint32_t data_offset_size, size_t fragment_size); +int multiband_drc_get_ipc_config(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata, + size_t fragment_size); +int multiband_drc_params(struct processing_module *mod); + +#ifdef UNIT_TEST +void sys_comp_module_multiband_drc_interface_init(void); +#endif + +#endif // __SOF_AUDIO_MULTIBAND_DRC_MULTIBAND_DRC_H__ diff --git a/src/audio/multiband_drc/multiband_drc.toml b/src/audio/multiband_drc/multiband_drc.toml new file mode 100644 index 000000000000..5ac07295d4a1 --- /dev/null +++ b/src/audio/multiband_drc/multiband_drc.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Multiband-DRC module config + [[module.entry]] + name = "MB_DRC" + uuid = UUIDREG_STR_MULTIBAND_DRC + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/multiband_drc/multiband_drc_generic.c b/src/audio/multiband_drc/multiband_drc_generic.c new file mode 100644 index 000000000000..bd64f5012fc8 --- /dev/null +++ b/src/audio/multiband_drc/multiband_drc_generic.c @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <stdint.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> + +#include "multiband_drc.h" +#include "../drc/drc_algorithm.h" + +void multiband_drc_default_pass(const struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t 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, + crossover_split split_func, + int32_t *buf_src, + int32_t *buf_sink, + int enable_emp, + int nch, + int nband) +{ + struct iir_state_df1 *emp_s; + struct crossover_state *crossover_s; + int32_t *buf_sink_band; + int ch, band; + int32_t emp_out; + int32_t crossover_out[nband]; + + for (ch = 0; ch < nch; ch++) { + emp_s = &state->emphasis[ch]; + crossover_s = &state->crossover[ch]; + + if (enable_emp) + emp_out = iir_df1_4th(emp_s, *buf_src); + else + emp_out = *buf_src; + + split_func(emp_out, crossover_out, crossover_s); + buf_sink_band = buf_sink; + for (band = 0; band < nband; band++) { + *buf_sink_band = crossover_out[band]; + buf_sink_band += PLATFORM_MAX_CHANNELS; + } + + buf_src++; + buf_sink++; + } +} + +#if CONFIG_FORMAT_S16LE +static void multiband_drc_s16_process_drc(struct drc_state *state, + const struct sof_drc_params *p, + int32_t *buf_src, + int32_t *buf_sink, + int nch) +{ + int16_t *pd_write; + int16_t *pd_read; + int ch; + int pd_write_index; + int pd_read_index; + + if (p->enabled && !state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, 2, nch); + state->processed = 1; + } + + pd_write_index = state->pre_delay_write_index; + pd_read_index = state->pre_delay_read_index; + + for (ch = 0; ch < nch; ++ch) { + pd_write = (int16_t *)state->pre_delay_buffers[ch] + pd_write_index; + pd_read = (int16_t *)state->pre_delay_buffers[ch] + pd_read_index; + *pd_write = sat_int16(Q_SHIFT_RND(*buf_src, 31, 15)); + *buf_sink = *pd_read << 16; + + buf_src++; + buf_sink++; + } + + pd_write_index = (pd_write_index + 1) & DRC_MAX_PRE_DELAY_FRAMES_MASK; + pd_read_index = (pd_read_index + 1) & DRC_MAX_PRE_DELAY_FRAMES_MASK; + state->pre_delay_write_index = pd_write_index; + state->pre_delay_read_index = pd_read_index; + + /* Only perform delay frames by early return here if not enabled */ + if (!p->enabled) + return; + + /* Process the input division (32 frames). */ + if (!(pd_write_index & DRC_DIVISION_FRAMES_MASK)) { + drc_update_detector_average(state, p, 2, nch); + drc_update_envelope(state, p); + drc_compress_output(state, p, 2, nch); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +static void multiband_drc_s32_process_drc(struct drc_state *state, + const struct sof_drc_params *p, + int32_t *buf_src, + int32_t *buf_sink, + int nch) +{ + int32_t *pd_write; + int32_t *pd_read; + int ch; + int pd_write_index; + int pd_read_index; + + if (p->enabled && !state->processed) { + drc_update_envelope(state, p); + drc_compress_output(state, p, 4, nch); + state->processed = 1; + } + + pd_write_index = state->pre_delay_write_index; + pd_read_index = state->pre_delay_read_index; + + for (ch = 0; ch < nch; ++ch) { + pd_write = (int32_t *)state->pre_delay_buffers[ch] + pd_write_index; + pd_read = (int32_t *)state->pre_delay_buffers[ch] + pd_read_index; + *pd_write = *buf_src; + *buf_sink = *pd_read; + + buf_src++; + buf_sink++; + } + + pd_write_index = (pd_write_index + 1) & DRC_MAX_PRE_DELAY_FRAMES_MASK; + pd_read_index = (pd_read_index + 1) & DRC_MAX_PRE_DELAY_FRAMES_MASK; + state->pre_delay_write_index = pd_write_index; + state->pre_delay_read_index = pd_read_index; + + /* Only perform delay frames by early return here if not enabled */ + if (!p->enabled) + return; + + /* Process the input division (32 frames). */ + if (!(pd_write_index & DRC_DIVISION_FRAMES_MASK)) { + drc_update_detector_average(state, p, 4, nch); + drc_update_envelope(state, p); + drc_compress_output(state, p, 4, nch); + } +} +#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + +static void multiband_drc_process_deemp(struct multiband_drc_state *state, + int32_t *buf_src, + int32_t *buf_sink, + int enable_deemp, + int nch, + int nband) +{ + struct iir_state_df1 *deemp_s; + int32_t *buf_src_band; + int ch, band; + int32_t mix_out; + + for (ch = 0; ch < nch; ch++) { + deemp_s = &state->deemphasis[ch]; + + buf_src_band = buf_src; + mix_out = 0; + for (band = 0; band < nband; band++) { + mix_out = sat_int32((int64_t)mix_out + *buf_src_band); + buf_src_band += PLATFORM_MAX_CHANNELS; + } + + if (enable_deemp) + *buf_sink = iir_df1_4th(deemp_s, mix_out); + else + *buf_sink = mix_out; + + buf_src++; + buf_sink++; + } +} + + /* This graph illustrates the buffers declared in the following default functions, as the example + * of a 3-band Multiband DRC: + * + * :buf_src[nch] :buf_drc_sink[nch*nband] + * : : + * : o-[]-> DRC0 -[]--o + * : | : : | + * : 3-WAY | : : | + * source -[]-> EQ EMP --> CROSSOVER --o-[]-> DRC1 -[]-(+)--> EQ DEEMP -[]-> sink + * | : : | : + * | : : | : + * o-[]-> DRC2 -[]--o : + * : : + * :buf_drc_src[nch*nband] :buf_sink[nch] + */ +#if CONFIG_FORMAT_S16LE +static void multiband_drc_s16_default(const struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct multiband_drc_state *state = &cd->state; + int32_t buf_src[PLATFORM_MAX_CHANNELS]; + int32_t buf_sink[PLATFORM_MAX_CHANNELS]; + int32_t buf_drc_src[PLATFORM_MAX_CHANNELS * SOF_MULTIBAND_DRC_MAX_BANDS]; + 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 = 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 = audio_stream_get_channels(source); + int nband = cd->config->num_bands; + int enable_emp_deemp = cd->config->enable_emp_deemp; + int samples = frames * nch; + + while (samples) { + nbuf = audio_stream_samples_without_wrap_s16(source, x); + npcm = MIN(samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s16(sink, y); + npcm = MIN(npcm, nbuf); + for (i = 0; i < npcm; i += nch) { + for (ch = 0; ch < nch; ch++) { + buf_src[ch] = *x << 16; + x++; + } + + multiband_drc_process_emp_crossover(state, cd->crossover_split, + buf_src, buf_drc_src, + enable_emp_deemp, nch, nband); + + band_buf_drc_src = buf_drc_src; + band_buf_drc_sink = buf_drc_sink; + for (band = 0; band < nband; ++band) { + multiband_drc_s16_process_drc(&state->drc[band], + &cd->config->drc_coef[band], + band_buf_drc_src, band_buf_drc_sink, + nch); + band_buf_drc_src += PLATFORM_MAX_CHANNELS; + band_buf_drc_sink += PLATFORM_MAX_CHANNELS; + } + + multiband_drc_process_deemp(state, buf_drc_sink, buf_sink, + enable_emp_deemp, nch, nband); + + for (ch = 0; ch < nch; ch++) { + *y = sat_int16(Q_SHIFT_RND(buf_sink[ch], 31, 15)); + y++; + } + } + samples -= npcm; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void multiband_drc_s24_default(const struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct multiband_drc_state *state = &cd->state; + int32_t buf_src[PLATFORM_MAX_CHANNELS]; + int32_t buf_sink[PLATFORM_MAX_CHANNELS]; + int32_t buf_drc_src[PLATFORM_MAX_CHANNELS * SOF_MULTIBAND_DRC_MAX_BANDS]; + 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 = 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 = audio_stream_get_channels(source); + int nband = cd->config->num_bands; + int enable_emp_deemp = cd->config->enable_emp_deemp; + int samples = frames * nch; + + while (samples) { + nbuf = audio_stream_samples_without_wrap_s24(source, x); + npcm = MIN(samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s24(sink, y); + npcm = MIN(npcm, nbuf); + for (i = 0; i < npcm; i += nch) { + for (ch = 0; ch < nch; ch++) { + buf_src[ch] = *x << 8; + x++; + } + + multiband_drc_process_emp_crossover(state, cd->crossover_split, + buf_src, buf_drc_src, + enable_emp_deemp, nch, nband); + + band_buf_drc_src = buf_drc_src; + band_buf_drc_sink = buf_drc_sink; + for (band = 0; band < nband; ++band) { + multiband_drc_s32_process_drc(&state->drc[band], + &cd->config->drc_coef[band], + band_buf_drc_src, band_buf_drc_sink, + nch); + band_buf_drc_src += PLATFORM_MAX_CHANNELS; + band_buf_drc_sink += PLATFORM_MAX_CHANNELS; + } + + multiband_drc_process_deemp(state, buf_drc_sink, buf_sink, + enable_emp_deemp, nch, nband); + + for (ch = 0; ch < nch; ch++) { + *y = sat_int24(Q_SHIFT_RND(buf_sink[ch], 31, 23)); + y++; + } + } + samples -= npcm; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void multiband_drc_s32_default(const struct processing_module *mod, + const struct audio_stream *source, + struct audio_stream *sink, + uint32_t frames) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct multiband_drc_state *state = &cd->state; + int32_t buf_src[PLATFORM_MAX_CHANNELS]; + int32_t buf_sink[PLATFORM_MAX_CHANNELS]; + int32_t buf_drc_src[PLATFORM_MAX_CHANNELS * SOF_MULTIBAND_DRC_MAX_BANDS]; + 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 = 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 = audio_stream_get_channels(source); + int nband = cd->config->num_bands; + int enable_emp_deemp = cd->config->enable_emp_deemp; + int samples = frames * nch; + + while (samples) { + nbuf = audio_stream_samples_without_wrap_s32(source, x); + npcm = MIN(samples, nbuf); + nbuf = audio_stream_samples_without_wrap_s32(sink, y); + npcm = MIN(npcm, nbuf); + for (i = 0; i < npcm; i += nch) { + for (ch = 0; ch < nch; ch++) { + buf_src[ch] = *x; + x++; + } + + multiband_drc_process_emp_crossover(state, cd->crossover_split, + buf_src, buf_drc_src, + enable_emp_deemp, nch, nband); + + band_buf_drc_src = buf_drc_src; + band_buf_drc_sink = buf_drc_sink; + for (band = 0; band < nband; ++band) { + multiband_drc_s32_process_drc(&state->drc[band], + &cd->config->drc_coef[band], + band_buf_drc_src, band_buf_drc_sink, + nch); + band_buf_drc_src += PLATFORM_MAX_CHANNELS; + band_buf_drc_sink += PLATFORM_MAX_CHANNELS; + } + + multiband_drc_process_deemp(state, buf_drc_sink, buf_sink, + enable_emp_deemp, nch, nband); + + for (ch = 0; ch < nch; ch++) { + *y = buf_sink[ch]; + y++; + } + } + samples -= npcm; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +const struct multiband_drc_proc_fnmap multiband_drc_proc_fnmap[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, multiband_drc_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, multiband_drc_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, multiband_drc_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const struct multiband_drc_proc_fnmap multiband_drc_proc_fnmap_pass[] = { +/* { SOURCE_FORMAT , PROCESSING FUNCTION } */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, multiband_drc_default_pass }, +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, multiband_drc_default_pass }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, multiband_drc_default_pass }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t multiband_drc_proc_fncount = ARRAY_SIZE(multiband_drc_proc_fnmap); diff --git a/src/audio/multiband_drc/multiband_drc_ipc3.c b/src/audio/multiband_drc/multiband_drc_ipc3.c new file mode 100644 index 000000000000..04aa4fc33e40 --- /dev/null +++ b/src/audio/multiband_drc/multiband_drc_ipc3.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/module_interface.h> +#include <module/module/base.h> +#include <ipc/control.h> +#include <sof/trace/trace.h> +#include <sof/audio/component.h> +#include <module/module/interface.h> +#include <sof/audio/data_blob.h> + +#include "multiband_drc.h" + +LOG_MODULE_DECLARE(multiband_drc, CONFIG_SOF_LOG_LEVEL); + +void multiband_drc_process_enable(bool *process_enabled) +{ + *process_enabled = false; +} + +static int multiband_drc_cmd_set_value(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_dev *dev = mod->dev; + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_SWITCH: + comp_dbg(dev, "multiband_drc_SOF_CTRL_CMD_SWITCH"); + if (cdata->num_elems == 1) { + cd->process_enabled = cdata->chanv[0].value; + comp_info(dev, "process_enabled = %d", + cd->process_enabled); + return 0; + } + } + + comp_err(mod->dev, "cmd_set_value() error: invalid cdata->cmd"); + return -EINVAL; +} + +int multiband_drc_set_ipc_config(struct processing_module *mod, uint32_t param_id, + const uint8_t *fragment, enum module_cfg_fragment_position pos, + uint32_t data_offset_size, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) + return multiband_drc_cmd_set_value(mod, cdata); + + comp_dbg(dev, "multiband_drc_set_config(), SOF_CTRL_CMD_BINARY"); + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); +} + +static int multiband_drc_cmd_get_value(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_dev *dev = mod->dev; + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + int j; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_SWITCH: + comp_dbg(dev, "SOF_CTRL_CMD_SWITCH"); + for (j = 0; j < cdata->num_elems; j++) + cdata->chanv[j].value = cd->process_enabled; + if (cdata->num_elems == 1) + return 0; + + comp_warn(dev, "warn: num_elems should be 1, got %d", + cdata->num_elems); + return 0; + } + + comp_err(dev, "tdfb_cmd_get_value() error: invalid cdata->cmd"); + return -EINVAL; +} + +int multiband_drc_get_ipc_config(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata, + size_t fragment_size) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) + return multiband_drc_cmd_get_value(mod, cdata); + + comp_dbg(mod->dev, "SOF_CTRL_CMD_BINARY"); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +int multiband_drc_params(struct processing_module *mod) +{ + return 0; +} + diff --git a/src/audio/multiband_drc/multiband_drc_ipc4.c b/src/audio/multiband_drc/multiband_drc_ipc4.c new file mode 100644 index 000000000000..ac2a7a7426aa --- /dev/null +++ b/src/audio/multiband_drc/multiband_drc_ipc4.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google LLC. All rights reserved. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/module_interface.h> +#include <sof/trace/trace.h> +#include <module/module/base.h> +#include <module/module/interface.h> +#include <sof/audio/component.h> +#include <ipc4/header.h> +#include <sof/audio/data_blob.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <sof/audio/buffer.h> +#include <sof/audio/audio_stream.h> +#include <sof/lib/memory.h> +#include <sof/list.h> + +#include "multiband_drc.h" + +LOG_MODULE_DECLARE(multiband_drc, CONFIG_SOF_LOG_LEVEL); + +void multiband_drc_process_enable(bool *process_enabled) +{ + *process_enabled = true; +} + +__cold int multiband_drc_set_ipc_config(struct processing_module *mod, uint32_t param_id, + const uint8_t *fragment, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, size_t fragment_size) +{ + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + comp_dbg(dev, "SOF_IPC4_SWITCH_CONTROL_PARAM_ID id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + + if (ctl->id == 0 && ctl->num_elems == 1) { + cd->process_enabled = ctl->chanv[0].value; + comp_info(dev, "process_enabled = %d", cd->process_enabled); + } else { + comp_err(dev, "Illegal control id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + return -EINVAL; + } + + return 0; + + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "illegal control."); + return -EINVAL; + } + + comp_dbg(mod->dev, "SOF_CTRL_CMD_BINARY"); + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); +} + +__cold int multiband_drc_get_ipc_config(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata, size_t fragment_size) +{ + struct multiband_drc_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "SOF_CTRL_CMD_BINARY"); + + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +int multiband_drc_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct sof_ipc_stream_params comp_params; + struct comp_dev *dev = mod->dev; + struct comp_buffer *sinkb; + enum sof_ipc_frame valid_fmt, frame_fmt; + int i; + + comp_dbg(dev, "entry"); + + comp_params = *params; + comp_params.channels = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + comp_params.rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; + comp_params.buffer_fmt = mod->priv.cfg.base_cfg.audio_fmt.interleaving_style; + + 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); + + comp_params.frame_fmt = frame_fmt; + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + comp_params.chmap[i] = (mod->priv.cfg.base_cfg.audio_fmt.ch_map >> i * 4) & 0xf; + + component_set_nearest_period_frames(dev, comp_params.rate); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sinkb) { + comp_err(dev, "no sink buffer"); + return -ENOTCONN; + } + + return buffer_set_params(sinkb, &comp_params, true); +} + diff --git a/src/audio/multiband_drc/tune/sof_crossover_gen_quant_coefs.m b/src/audio/multiband_drc/tune/sof_crossover_gen_quant_coefs.m new file mode 100644 index 000000000000..df00c2de3df4 --- /dev/null +++ b/src/audio/multiband_drc/tune/sof_crossover_gen_quant_coefs.m @@ -0,0 +1,58 @@ +function crossover_coefs = sof_crossover_gen_quant_coefs(num_bands, sample_rate, + fc_low, fc_med, fc_high); + +% De-normalize cutoff frequencies in respect to nyquist (half of sample rate) +fc_low = fc_low * sample_rate / 2; +fc_med = fc_med * sample_rate / 2; +fc_high = fc_high * sample_rate / 2; + +filter_len = 3; +crossover.lp = cell(1:filter_len); +crossover.hp = cell(1:filter_len); +% Generate zeros, poles and gain for crossover with the given frequencies +% Extend the length of lp and hp to 3 (filter_len) by flat_filter if necessary +if (num_bands == 1) + % Pass-through + crossover.lp = [flat_filter() flat_filter() flat_filter()]; + crossover.hp = [flat_filter() flat_filter() flat_filter()]; +elseif (num_bands == 2) + % 2-way crossover + crossover = sof_crossover_gen_coefs(sample_rate, fc_low); + crossover.lp = [crossover.lp(1) flat_filter() flat_filter()]; + crossover.hp = [crossover.hp(1) flat_filter() flat_filter()]; +elseif (num_bands == 3) + % 3-way crossover + crossover = sof_crossover_gen_coefs(sample_rate, fc_low, fc_med); +else % (num_bands == 4) + % 4-way crossover + crossover = sof_crossover_gen_coefs(sample_rate, fc_low, fc_med, fc_high); +end + +assert(length(crossover.lp) == filter_len && length(crossover.hp) == filter_len); + +% Print crossover +for i = 1:filter_len + crossover.lp(i) + crossover.hp(i) +end + +% Convert the [a,b] coefficients to values usable with SOF +crossover_bqs = sof_crossover_coef_quant(crossover.lp, crossover.hp); + +j = 1; +k = 1; +for i = 1:filter_len + crossover_coefs(k:k+6) = crossover_bqs.lp_coef(j:j+6); k = k + 7; + crossover_coefs(k:k+6) = crossover_bqs.hp_coef(j:j+6); k = k + 7; + j = j + 7; +end + +end + +function flat = flat_filter(); + +% Flat response y[n] = x[n] (only b0=1.0) +flat.b = [1.0, 0, 0]; +flat.a = [0, 0, 0]; + +end diff --git a/src/audio/multiband_drc/tune/sof_drc_gen_quant_coefs.m b/src/audio/multiband_drc/tune/sof_drc_gen_quant_coefs.m new file mode 100644 index 000000000000..681c34147568 --- /dev/null +++ b/src/audio/multiband_drc/tune/sof_drc_gen_quant_coefs.m @@ -0,0 +1,8 @@ +function drc_coefs = sof_drc_gen_quant_coefs(num_bands, sample_rate, params); + +for i = 1:num_bands + coefs = sof_drc_gen_coefs(params(i), sample_rate); + drc_coefs(i) = sof_drc_generate_config(coefs); +end + +end diff --git a/src/audio/multiband_drc/tune/sof_example_multiband_drc.m b/src/audio/multiband_drc/tune/sof_example_multiband_drc.m new file mode 100644 index 000000000000..9ebd3ef56b97 --- /dev/null +++ b/src/audio/multiband_drc/tune/sof_example_multiband_drc.m @@ -0,0 +1,129 @@ +function sof_example_multiband_drc() + +rz1 = [0.09 0.16 0.42 0.98]; + +prm.name = "default"; +prm.sample_rate = 48000; +prm.enable_emp_deemp = 1; +prm.stage_gain = 0.01; +prm.stage_ratio = 2 +prm.num_bands = 3; +prm.enable_bands = [ 1 2 3 0 ]; +prm.band_lower_freq = [ 0 2000 8000 16000 ]; +prm.threshold = [ -30 -30 -30 -30 ]; +prm.knee = [ 20 20 20 20 ]; +prm.ratio = [ 10 10 10 10 ]; +prm.attack = [ 0.003 0.003 0.003 0.003 ]; +prm.release = [ 0.2 0.2 0.2 0.2 ]; +prm.pre_delay = [ 0.006 0.006 0.006 0.006 ]; +prm.release_spacing = [ 5 5 5 5 ]; +prm.post_gain = [ 0 0 0 0 ]; +prm.release_zone = [ rz1' rz1' rz1' rz1']; +export_multiband_drc(prm) + +prm.name = "passthrough"; +prm.sample_rate = 48000; +prm.enable_emp_deemp = 0; +prm.num_bands = 2; +prm.enable_bands = [0 0 0 0]; +export_multiband_drc(prm) + +end + +function export_multiband_drc(prm) + +sof_multiband_drc_paths(true); + +% Set the parameters here +sof_tools = '../../../../tools'; +tplg1_fn = sprintf("%s/topology/topology1/m4/multiband_drc_coef_%s.m4", sof_tools, prm.name); % Control Bytes File +tplg2_fn = sprintf("%s/topology/topology2/include/components/multiband_drc/%s.conf", sof_tools, prm.name); % Control Bytes File +% Use those files with sof-ctl to update the component's configuration +blob3_fn = sprintf("%s/ctl/ipc3/multiband_drc/%s.bin", sof_tools, prm.name); % Blob binary file +alsa3_fn = sprintf("%s/ctl/ipc3/multiband_drc/%s.txt", sof_tools, prm.name); % ALSA CSV format file +blob4_fn = sprintf("%s/ctl/ipc4/multiband_drc/%s.bin", sof_tools, prm.name); % Blob binary file +alsa4_fn = sprintf("%s/ctl/ipc4/multiband_drc/%s.txt", sof_tools, prm.name); % ALSA CSV format file + +endian = "little"; + +sample_rate = prm.sample_rate; +nyquist = sample_rate / 2; + +% Number of bands, valid values: 1,2,3,4 +num_bands = prm.num_bands; + +% 1 to enable Emphasis/Deemphasis filter, 0 to disable it +enable_emp_deemp = prm.enable_emp_deemp; + +% The parameters of Emphasis IIR filter +% stage_gain: The gain of each emphasis filter stage +iir_params.stage_gain = prm.stage_gain; +% stage_ratio: The frequency ratio for each emphasis filter stage to the +% previous stage +iir_params.stage_ratio = prm.stage_ratio; +% anchor: The frequency of the first emphasis filter, in normalized frequency +% (in [0, 1], relative to half of the sample rate) +iir_params.anchor = 15000 / nyquist; + +% The parameters of the DRC compressor +% enabled: 1 to enable the compressor, 0 to disable it +% threshold: The value above which the compression starts, in dB +% knee: The value above which the knee region starts, in dB +% ratio: The input/output dB ratio after the knee region +% attack: The time to reduce the gain by 10dB, in seconds +% release: The time to increase the gain by 10dB, in seconds +% pre_delay: The lookahead time for the compressor, in seconds +% release_zone[4]: The adaptive release curve parameters +% release_spacing: The value of spacing per frame while releasing, in dB +% post_gain: The static boost value in output, in dB +% band_lower_freq: The lower frequency of the band, in normalized frequency +% (in [0, 1], relative to half of the sample rate) + +for i = 1:4 + % Band n DRC parameter, (only valid if num_bands >= i) + drc_params(i).enabled = prm.enable_bands(i); + drc_params(i).threshold = prm.threshold(i); + drc_params(i).knee = prm.knee(i); + drc_params(i).ratio = prm.ratio(i); + drc_params(i).attack = prm.attack(i); + drc_params(i).release = prm.release(i); + drc_params(i).pre_delay = prm.pre_delay(i); + drc_params(i).release_zone = prm.release_zone(:, i)'; + drc_params(i).release_spacing = prm.release_spacing(i); + drc_params(i).post_gain = prm.post_gain(i); + drc_params(i).band_lower_freq = prm.band_lower_freq(i) / nyquist; +end + +% Generate Emphasis/Deemphasis IIR filter quantized coefs struct from parameters + +[emp_coefs, deemp_coefs] = sof_iir_gen_quant_coefs(iir_params, sample_rate, enable_emp_deemp); + +% Generate Crossover quantized coefs struct from parameters +crossover_coefs = sof_crossover_gen_quant_coefs(num_bands, sample_rate, ... + drc_params(2).band_lower_freq, ... + drc_params(3).band_lower_freq, ... + drc_params(4).band_lower_freq); + +% Generate DRC quantized coefs struct from parameters +drc_coefs = sof_drc_gen_quant_coefs(num_bands, sample_rate, drc_params); + +% Generate output files + +% Convert quantized coefs structs to binary blob +blob8 = sof_multiband_drc_build_blob(num_bands, enable_emp_deemp, emp_coefs, ... + deemp_coefs, crossover_coefs, drc_coefs, ... + endian, 3); +blob8_ipc4 = sof_multiband_drc_build_blob(num_bands, enable_emp_deemp, emp_coefs, ... + deemp_coefs, crossover_coefs, drc_coefs, ... + endian, 4); + +sof_tplg_write(tplg1_fn, blob8, "MULTIBAND_DRC"); +sof_tplg2_write(tplg2_fn, blob8_ipc4, "multiband_drc_config", "Exported with script sof_example_multiband_drc.m"); +sof_ucm_blob_write(blob3_fn, blob8); +sof_alsactl_write(alsa3_fn, blob8); +sof_ucm_blob_write(blob4_fn, blob8_ipc4); +sof_alsactl_write(alsa4_fn, blob8_ipc4); + +sof_multiband_drc_paths(false); + +end diff --git a/src/audio/multiband_drc/tune/sof_iir_gen_quant_coefs.m b/src/audio/multiband_drc/tune/sof_iir_gen_quant_coefs.m new file mode 100644 index 000000000000..946434e2172f --- /dev/null +++ b/src/audio/multiband_drc/tune/sof_iir_gen_quant_coefs.m @@ -0,0 +1,158 @@ +function [emp_coefs, deemp_coefs] = sof_iir_gen_quant_coefs(params, sample_rate, enable) + +stage_gain = params.stage_gain; +stage_ratio = params.stage_ratio; +anchor_freq = params.anchor; + +emp = cell(1, 2); +deemp = cell(1, 2); +% Generate the coefficients of (de)emphasis for the 1-st stage of biquads +[emp(1), deemp(1)] = emp_deemp_stage_biquad(stage_gain, anchor_freq, ... + anchor_freq / stage_ratio); + +anchor_freq = anchor_freq / (stage_ratio * stage_ratio); + +% Generate the coefficients of (de)emphasis for the 2-nd stage of biquads +[emp(2), deemp(2)] = emp_deemp_stage_biquad(stage_gain, anchor_freq, ... + anchor_freq / stage_ratio); + +% Adjust the stage gain (push gains to the last stage) of emphasis filter +[emp(1), emp(2)] = stage_gain_adjust(emp(1), emp(2)); + +% Plot emp and deemp +if enable + plot_emp_deem(emp, deemp, sample_rate); +end + +% Convert the coefficients to values usable with SOF +emp_coefs = iir_coef_quant(emp); +deemp_coefs = iir_coef_quant(deemp); + +end + +function [emp, deemp] = emp_deemp_stage_biquad(gain, f1, f2) + +[z1, p1] = emp_stage_roots(gain, f1); +[z2, p2] = emp_stage_roots(gain, f2); + +b0 = 1; +b1 = -(z1 + z2); +b2 = z1 * z2; +a0 = 1; +a1 = -(p1 + p2); +a2 = p1 * p2; + +% Gain compensation to make 0dB at 0Hz +% For emphasis filter, alpha should be > 1. Record the alpha gain and then we +% will do the stage gain adjustment afterwards. +alpha = (a0 + a1 + a2) / (b0 + b1 + b2); + +% [ a2 a1 b2 b1 b0 shift gain] +emp = [-a2, -a1, b2, b1, b0, 0, alpha]; + +% For deemphasis filter, beta should be < 1. Multiply beta directly to b coeffs +% to have a healthy scaling of biquads internally. +beta = (b0 + b1 + b2) / (a0 + a1 + a2); + +% [ a2 a1 b2 b1 b0 shift gain] +deemp = [-b2, -b1, a2 * beta, a1 * beta, a0 * beta, 0, 1.0]; + +end + +function [zero, pole] = emp_stage_roots(gain, normalized_freq) + +gk = 1 - gain / 20; +f1 = normalized_freq * gk; +f2 = normalized_freq / gk; +zero = exp(-f1 * pi); +pole = exp(-f2 * pi); + +end + +function quant_coefs = iir_coef_quant(coefs) + +bits_iir = 32; % Q2.30 +qf_iir = 30; + +bits_gain = 16; % Q2.14 +qf_gain = 14; + +quant_coefs = cell(1, 2); +for i = 1:length(coefs) + coef = cell2mat(coefs(i)); + quant_ab = sof_eq_coef_quant(coef(1:5), bits_iir, qf_iir); + quant_gain = sof_eq_coef_quant(coef(7), bits_gain, qf_gain); + quant_coefs(i) = [quant_ab coef(6) quant_gain]; +end + +quant_coefs = cell2mat(quant_coefs); + +end + +function [bq1, bq2] = stage_gain_adjust(prev_bq1, prev_bq2) + +prev_bq1 = cell2mat(prev_bq1); +prev_bq2 = cell2mat(prev_bq2); + +[rshift, gain] = decompose_gain(prev_bq1(7) * prev_bq2(7)); +bq1 = [prev_bq1(1:5) 0 1.0]; +bq2 = [prev_bq2(1:5) rshift gain]; + +end + +function [rshift, gain] = decompose_gain(prev_gain) + +max_abs_val = 2; % Q2.14 +rshift = 0; +gain = prev_gain; + +while (abs(gain) >= max_abs_val) + gain = gain / 2; + rshift = rshift - 1; % left-shift in shift stage +end + +end + +function plot_emp_deem(emp, deemp, fs) + +f = logspace(log10(10), log10(fs/2), 100); + +[eb1, ea1] = get_biquad(cell2mat(emp(1))); +[eb2, ea2] = get_biquad(cell2mat(emp(2))); +eb = conv(eb1, eb2); +ea = conv(ea1, ea2); +he = freqz(eb, ea, f, fs); + +[db1, da1] = get_biquad(cell2mat(deemp(1))); +[db2, da2] = get_biquad(cell2mat(deemp(2))); +db = conv(db1, db2); +da = conv(da1, da2); +hd = freqz(db, da, f, fs); +hed = he .* hd; + +figure +subplot(3,1,1); +semilogx(f, 20*log10(he)); +grid on; +ylabel('Emp (dB)'); +title('Emphasis, de-emphasis responses'); +subplot(3,1,2); +semilogx(f, 20*log10(hd)); +grid on; +ylabel('De-emp (dB)'); +subplot(3,1,3); +semilogx(f, 20*log10(hed)); +grid on; +ylabel('Combined (dB)') +xlabel('Frequency (Hz)'); + +end + +function [b, a] = get_biquad(bq) + + a = [1 -bq(2:-1:1)]; + b = [bq(5:-1:3)]; + shift = bq(6); + gain = bq(7) * 2^(-shift); + b = b * gain; +end diff --git a/src/audio/multiband_drc/tune/sof_multiband_drc_build_blob.m b/src/audio/multiband_drc/tune/sof_multiband_drc_build_blob.m new file mode 100644 index 000000000000..520c38e9a2e4 --- /dev/null +++ b/src/audio/multiband_drc/tune/sof_multiband_drc_build_blob.m @@ -0,0 +1,90 @@ +function blob8 = sof_multiband_drc_build_blob(num_bands, enable_emp_deemp, + emp_coefs, deemp_coefs, + crossover_coefs, drc_coefs, + endian, ipc_ver) + +if nargin < 7 + endian = 'little' +end + +if nargin < 8 + ipc_ver = 3; +end + +%% Shift values for little/big endian +switch lower(endian) + case 'little' + sh = [0 -8 -16 -24]; + case 'big' + sh = [-24 -16 -8 0]; + otherwise + error('Unknown endiannes'); +end + +%% Build Blob +% refer to sof/src/include/user/multiband_drc.h for the config struct. +emp_data_num = numel(emp_coefs); +deemp_data_num = numel(deemp_coefs); +crossover_data_num = numel(crossover_coefs); +drc_data_num = numel(fieldnames(drc_coefs(1))) * length(drc_coefs); +data_size = 4 * (1 + 1 + 1 + 8 + emp_data_num + deemp_data_num + crossover_data_num + drc_data_num); +[abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver); + +blob_size = data_size + abi_size; +blob8 = uint8(zeros(1, blob_size)); + +% Pack Blob data +% Insert ABI Header +blob8(1:abi_size) = abi_bytes; +j = abi_size + 1; + +% Insert Data +blob8(j:j+3) = word2byte(data_size, sh); j=j+4; % size +blob8(j:j+3) = word2byte(num_bands, sh); j=j+4; % num_bands +blob8(j:j+3) = word2byte(enable_emp_deemp, sh); j=j+4; % enable_emp_deemp +for i = 1:8 + blob8(j:j+3) = word2byte(0, sh); j=j+4; % reserved +end +for i = 1:length(emp_coefs) + blob8(j:j+3) = word2byte(emp_coefs(i), sh); j=j+4; % emp_coef +end +for i = 1:length(deemp_coefs) + blob8(j:j+3) = word2byte(deemp_coefs(i), sh); j=j+4; % deemp_coef +end +for i = 1:length(crossover_coefs) + blob8(j:j+3) = word2byte(crossover_coefs(i), sh); j=j+4; % crossover_coef +end +for i = 1:length(drc_coefs) % drc_coef + blob8(j:j+3) = word2byte(drc_coefs(i).enabled, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).db_threshold, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).db_knee, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).ratio, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).pre_delay_time, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).linear_threshold, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).slope, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).K, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).knee_alpha, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).knee_beta, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).knee_threshold, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).ratio_base, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).master_linear_gain, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).one_over_attack_frames, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).sat_release_frames_inv_neg, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).sat_release_rate_at_neg_two_db, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).kSpacingDb, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).kA, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).kB, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).kC, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).kD, sh); j=j+4; + blob8(j:j+3) = word2byte(drc_coefs(i).kE, sh); j=j+4; +end + +end + +function bytes = word2byte(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/multiband_drc/tune/sof_multiband_drc_paths.m b/src/audio/multiband_drc/tune/sof_multiband_drc_paths.m new file mode 100644 index 000000000000..477aebc4c023 --- /dev/null +++ b/src/audio/multiband_drc/tune/sof_multiband_drc_paths.m @@ -0,0 +1,27 @@ +function sof_multiband_drc_paths(enable) + +% sof_multiband_drc_paths(enable) +% enable - set to true to enable needed search path +% set to false to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + + common = '../../../../tools/tune/common'; + crossover = '../../crossover/tune'; + drc = '../../drc/tune'; + eq = '../../eq_iir/tune'; + if enable + addpath(common); + addpath(crossover); + addpath(drc); + addpath(eq); + else + rmpath(common); + rmpath(crossover); + rmpath(drc); + rmpath(eq); + end +end diff --git a/src/audio/multiband_drc/user/multiband_drc.h b/src/audio/multiband_drc/user/multiband_drc.h new file mode 100644 index 000000000000..ef07c33a00fd --- /dev/null +++ b/src/audio/multiband_drc/user/multiband_drc.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Google LLC. All rights reserved. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ + +#ifndef __USER_MULTIBAND_DRC_H__ +#define __USER_MULTIBAND_DRC_H__ + +#include <stdint.h> +#include <user/eq.h> +#include <module/crossover/crossover_common.h> + +#include "../../drc/drc_user.h" + +/* Maximum number of frequency band for Multiband DRC */ +#define SOF_MULTIBAND_DRC_MAX_BANDS SOF_CROSSOVER_MAX_STREAMS + +/* Maximum number of Crossover LR4 highpass and lowpass filters */ +#define SOF_CROSSOVER_MAX_LR4 ((SOF_CROSSOVER_MAX_STREAMS - 1) * 2) + +/* The number of biquads (and biquads in series) of (De)Emphasis Equalizer */ +#define SOF_EMP_DEEMP_BIQUADS 2 + +/* Maximum number allowed of IPC configuration blob size */ +#define SOF_MULTIBAND_DRC_MAX_BLOB_SIZE 1024 + + /* multiband_drc configuration + * Multiband DRC is a single-source-single-sink compound component which + * consists of 4 stages: Emphasis Equalizer, Crossover Filter (from 1-band + * to 4-band), DRC (per band), and Deemphasis Equalizer of summed stream. + * + * The following graph illustrates a 3-band Multiband DRC component: + * + * low + * o----> DRC0 ----o + * | | + * 3-WAY |mid | + * x(n) --> EQ EMP --> CROSSOVER --o----> DRC1 ---(+)--> EQ DEEMP --> y(n) + * | | + * |high | + * o----> DRC2 ----o + * + * uint32_t num_bands <= 4 + * Determines the number of frequency bands, the choice of n-way + * Crossover, and the number of DRC components. + * uint32_t enable_emp_deemp + * 1=enable Emphasis and Deemphasis Equalizer; 0=disable (passthrough) + * struct sof_eq_iir_biquad emp_coef[2] + * The coefficient data for Emphasis Equalizer, which is a cascade of 2 + * biquad filters. + * struct sof_eq_iir_biquad deemp_coef[2] + * The coefficient data for Deemphasis Equalizer, which is a cascade of + * 2 biquad filters. + * struct sof_eq_iir_biquad crossover_coef[6] + * The coefficient data for Crossover LR4 filters. Please refer + * src/include/user/crossover.h for details. Zeros will be filled if + * the entries are useless. For example, when 2-way crossover is used: + * struct sof_drc_params drc_coef[num_bands] + * The parameter data for DRC per band, the number entries of this may + * vary. Please refer src/include/user/drc.h for details. + * + */ +struct sof_multiband_drc_config { + uint32_t size; + uint32_t num_bands; + uint32_t enable_emp_deemp; + + /* reserved */ + uint32_t reserved[8]; + + /* config of emphasis eq-iir */ + struct sof_eq_iir_biquad emp_coef[SOF_EMP_DEEMP_BIQUADS]; + + /* config of deemphasis eq-iir */ + struct sof_eq_iir_biquad deemp_coef[SOF_EMP_DEEMP_BIQUADS]; + + /* config of crossover */ + struct sof_eq_iir_biquad crossover_coef[SOF_CROSSOVER_MAX_LR4]; + + /* config of multi-band drc */ + struct sof_drc_params drc_coef[]; +}; + +#endif // __USER_MULTIBAND_DRC_H__ diff --git a/src/audio/mux/CMakeLists.txt b/src/audio/mux/CMakeLists.txt index ff6bec28fa75..e8872dfd41d4 100644 --- a/src/audio/mux/CMakeLists.txt +++ b/src/audio/mux/CMakeLists.txt @@ -1,3 +1,14 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof mux.c mux_generic.c) +if(CONFIG_COMP_MUX STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/mux_llext) + add_dependencies(app mux) +else() + add_local_sources(sof mux.c mux_generic.c) + + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof mux_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof mux_ipc4.c) + endif() +endif() diff --git a/src/audio/mux/Kconfig b/src/audio/mux/Kconfig new file mode 100644 index 000000000000..953e65ad59db --- /dev/null +++ b/src/audio/mux/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_MUX + tristate "MUX component" + select COMP_BLOB + depends on COMP_MODULE_ADAPTER + default y + help + Select for MUX component diff --git a/src/audio/mux/README.md b/src/audio/mux/README.md new file mode 100644 index 000000000000..97a5a3905b5e --- /dev/null +++ b/src/audio/mux/README.md @@ -0,0 +1,23 @@ +# Multiplexer/Demultiplexer Architecture + +This directory contains the Mux/Demux component. + +## Overview + +Selects between multiple audio paths, routing N inputs to 1 output, or 1 input to N outputs. + +## Architecture Diagram + +```mermaid +graph LR + In1[Path A] --> Mux[Path Selector] + In2[Path B] --> Mux + Mux --> Out[Selected Path] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the MUX component (`COMP_MUX`), relying on the standard `COMP_MODULE_ADAPTER`. +- **CMakeLists.txt**: Manages `mux.c` and generic code paths alongside IPC abstraction interfaces (`mux_ipc3.c`, `mux_ipc4.c`). Supports `llext` modular integration. +- **mux.toml**: Topology settings defining UUID `UUIDREG_STR_MUX4` and accommodating up to 15 concurrent instances with multiple 10-channel I/O pins. +- **Topology (.conf)**: Found at `tools/topology/topology2/include/components/muxdemux.conf`, which declares a `muxdemux` widget object. Provides flexible process typing such as `DEMUX` with type `effect` (UUID `68:68:b2:c4:30:14:0e:47:a0:89:15:d1:c7:7f:85:1a`). diff --git a/src/audio/mux/llext/CMakeLists.txt b/src/audio/mux/llext/CMakeLists.txt new file mode 100644 index 000000000000..d23b29f5588d --- /dev/null +++ b/src/audio/mux/llext/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("mux" + SOURCES ../mux.c + ../mux_generic.c + ../mux_ipc4.c + LIB openmodules +) diff --git a/src/audio/mux/llext/llext.toml.h b/src/audio/mux/llext/llext.toml.h new file mode 100644 index 000000000000..27a629e46f78 --- /dev/null +++ b/src/audio/mux/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../mux.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/mux/mux.c b/src/audio/mux/mux.c index 25c5ea4f547a..965faaf8037e 100644 --- a/src/audio/mux/mux.c +++ b/src/audio/mux/mux.c @@ -5,22 +5,18 @@ // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> // Artur Kloniecki <arturx.kloniecki@linux.intel.com> -#include <config.h> - -#if CONFIG_COMP_MUX - +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/component.h> -#include <sof/audio/mux.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/ipc-config.h> #include <sof/common.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> #include <sof/lib/uuid.h> #include <sof/list.h> #include <sof/math/numbers.h> #include <sof/platform.h> -#include <sof/string.h> -#include <sof/trace/preproc.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <sof/ut.h> #include <ipc/control.h> @@ -30,536 +26,464 @@ #include <stddef.h> #include <stdint.h> -static const struct comp_driver comp_mux; +#include "mux.h" -/* c4b26868-1430-470e-a089-15d1c77f851a */ -DECLARE_SOF_UUID("mux", mux_uuid, 0xc4b26868, 0x1430, 0x470e, - 0xa0, 0x89, 0x15, 0xd1, 0xc7, 0x7f, 0x85, 0x1a); +LOG_MODULE_REGISTER(muxdemux, CONFIG_SOF_LOG_LEVEL); -static int mux_set_values(struct comp_dev *dev, struct comp_data *cd, - struct sof_mux_config *cfg) +/* + * Check that we are not configuring routing matrix for mixing. + * + * In mux case this means, that muxed streams' configuration matrices don't + * have 1's in corresponding matrix indices. Also single stream matrix can't + * have 1's in same column as that corresponds to mixing also. + */ +bool mux_mix_check(struct sof_mux_config *cfg) { - uint8_t i; - uint8_t j; - - /* check if number of streams configured doesn't exceed maximum */ - if (cfg->num_streams > MUX_MAX_STREAMS) { - comp_cl_err(&comp_mux, "mux_set_values() error: configured number of streams (%u) exceeds maximum = " - META_QUOTE(MUX_MAX_STREAMS), cfg->num_streams); - return -EINVAL; - } - - /* check if all streams configured have distinct IDs */ - for (i = 0; i < cfg->num_streams; i++) { - for (j = i + 1; j < cfg->num_streams; j++) { - if (cfg->streams[i].pipeline_id == - cfg->streams[j].pipeline_id) { - comp_cl_err(&comp_mux, "mux_set_values() error: multiple configured streams have same pipeline ID = %u", - cfg->streams[i].pipeline_id); - return -EINVAL; + bool channel_set; + int i; + int j; + int k; + + /* check for single matrix mixing, i.e multiple column bits are not set */ + for (i = 0 ; i < cfg->num_streams; i++) { + for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { + channel_set = false; + for (k = 0 ; k < PLATFORM_MAX_CHANNELS; k++) { + if (cfg->streams[i].mask[k] & (1 << j)) { + if (!channel_set) + channel_set = true; + else + return true; + } } } } - /* check if number of channels per stream doesn't exceed maximum */ - for (i = 0; i < cfg->num_streams; i++) { - if (cfg->streams[i].num_channels > PLATFORM_MAX_CHANNELS) { - comp_cl_err(&comp_mux, "mux_set_values() error: configured number of channels for stream %u exceeds platform maximum = " - META_QUOTE(PLATFORM_MAX_CHANNELS), i); - return -EINVAL; + /* check for inter matrix mixing, i.e corresponding bits are not set */ + for (i = 0 ; i < PLATFORM_MAX_CHANNELS; i++) { + for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { + channel_set = false; + for (k = 0 ; k < cfg->num_streams; k++) { + if (cfg->streams[k].mask[i] & (1 << j)) { + if (!channel_set) + channel_set = true; + else + return true; + } + } } } - cd->config.num_channels = cfg->num_channels; - cd->config.frame_format = cfg->frame_format; - - for (i = 0; i < cfg->num_streams; i++) { - cd->config.streams[i].num_channels = cfg->streams[i].num_channels; - cd->config.streams[i].pipeline_id = cfg->streams[i].pipeline_id; - for (j = 0; j < cfg->streams[i].num_channels; j++) - cd->config.streams[i].mask[j] = cfg->streams[i].mask[j]; - } - - if (dev->comp.type == SOF_COMP_MUX) - cd->mux = mux_get_processing_function(dev); - else - cd->demux = demux_get_processing_function(dev); - - return 0; + return false; } -static struct comp_dev *mux_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) +static int mux_demux_common_init(struct processing_module *mod, enum sof_comp_type type) { - struct sof_ipc_comp_process *ipc_process = - (struct sof_ipc_comp_process *)comp; - size_t bs = ipc_process->size; - struct comp_dev *dev; + struct module_data *module_data = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *cfg = &module_data->cfg; struct comp_data *cd; int ret; - comp_cl_info(&comp_mux, "mux_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_process)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_process); + comp_dbg(dev, "mux_init()"); - memcpy_s(COMP_GET_IPC(dev, sof_ipc_comp_process), - sizeof(struct sof_ipc_comp_process), - comp, sizeof(struct sof_ipc_comp_process)); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*cd) + MUX_MAX_STREAMS * sizeof(struct mux_stream_data)); - if (!cd) { - rfree(dev); - return NULL; + if (cfg->size > MUX_BLOB_MAX_SIZE) { + comp_err(dev, "blob size %zu exceeds %zu", + cfg->size, MUX_BLOB_MAX_SIZE); + return -EINVAL; } - comp_set_drvdata(dev, cd); + cd = mod_zalloc(mod, sizeof(*cd) + MUX_BLOB_STREAMS_SIZE); + if (!cd) + return -ENOMEM; - memcpy_s(&cd->config, sizeof(struct sof_mux_config) + - MUX_MAX_STREAMS * sizeof(struct mux_stream_data), - ipc_process->data, bs); - - /* verification of initial parameters */ - ret = mux_set_values(dev, cd, &cd->config); + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto err; + } + module_data->private = cd; + ret = comp_init_data_blob(cd->model_handler, cfg->size, cfg->init_data); if (ret < 0) { - rfree(cd); - rfree(dev); - return NULL; + comp_err(dev, "module data blob initialization failed."); + goto err_init; } - dev->state = COMP_STATE_READY; - return dev; + mod->verify_params_flags = BUFF_PARAMS_CHANNELS; + mod->no_pause = true; + cd->comp_type = type; + return 0; + +err_init: + mod_data_blob_handler_free(mod, cd->model_handler); + +err: + mod_free(mod, cd); + return ret; } -static void mux_free(struct comp_dev *dev) +static int mux_init(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); + mod->max_sources = MUX_MAX_STREAMS; - comp_info(dev, "mux_free()"); - - rfree(cd); - rfree(dev); + return mux_demux_common_init(mod, SOF_COMP_MUX); } -static uint8_t get_stream_index(struct comp_data *cd, uint32_t pipe_id) +static int mux_free(struct processing_module *mod) { - int i; + struct comp_data *cd = module_get_private_data(mod); - for (i = 0; i < MUX_MAX_STREAMS; i++) - if (cd->config.streams[i].pipeline_id == pipe_id) - return i; - - comp_cl_err(&comp_mux, "get_stream_index() error: couldn't find configuration for connected pipeline %u", - pipe_id); + comp_dbg(mod->dev, "entry"); + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); return 0; } -static int mux_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) +static int get_stream_index(struct comp_dev *dev, struct comp_data *cd, uint32_t pipe_id) { - int ret; + int idx; - comp_dbg(dev, "mux_verify_params()"); + for (idx = 0; idx < MUX_MAX_STREAMS; idx++) + if (cd->config.streams[idx].pipeline_id == pipe_id) + return idx; - ret = comp_verify_params(dev, BUFF_PARAMS_CHANNELS, params); - if (ret < 0) { - comp_err(dev, "mux_verify_params() error: comp_verify_params() failed."); - return ret; - } - - return 0; + comp_err(dev, "couldn't find configuration for connected pipeline %u", + pipe_id); + return -EINVAL; } -/* set component audio stream parameters */ -static int mux_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) +static void mux_prepare_active_look_up(struct comp_data *cd, + struct audio_stream *sink, + const struct audio_stream **sources) { - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sinkb; - int err; + const struct audio_stream *source; + int elem; + int active_elem = 0; + + /* init pointers */ + for (elem = 0; elem < cd->lookup[0].num_elems; elem++) { + source = sources[cd->lookup[0].copy_elem[elem].stream_id]; + if (!source) + continue; - comp_info(dev, "mux_params()"); + 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; - err = mux_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "mux_fir_params(): pcm params verification failed."); - return -EINVAL; + cd->active_lookup.copy_elem[active_elem] = cd->lookup[0].copy_elem[elem]; + active_elem++; } - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - cd->config.num_channels = sinkb->stream.channels; - cd->config.frame_format = sinkb->stream.frame_fmt; - - return 0; + cd->active_lookup.num_elems = active_elem; } -static int mux_ctrl_set_cmd(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) +#if !CONFIG_COMP_MUX_MODULE +static int demux_init(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_mux_config *cfg; - int ret = 0; - - comp_info(dev, "mux_ctrl_set_cmd(), cdata->cmd = 0x%08x", - cdata->cmd); - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - cfg = (struct sof_mux_config *) - ASSUME_ALIGNED(cdata->data->data, 4); - - ret = mux_set_values(dev, cd, cfg); - break; - default: - comp_err(dev, "mux_ctrl_set_cmd() error: invalid cdata->cmd = 0x%08x", - cdata->cmd); - ret = -EINVAL; - break; - } + mod->max_sinks = MUX_MAX_STREAMS; - return ret; + return mux_demux_common_init(mod, SOF_COMP_DEMUX); } -static int mux_ctrl_get_cmd(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int size) +static struct mux_look_up *get_lookup_table(struct comp_dev *dev, struct comp_data *cd, + uint32_t pipe_id) { - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_mux_config *cfg = &cd->config; - uint32_t reply_size; - int ret = 0; - - comp_cl_info(&comp_mux, "mux_ctrl_get_cmd(), cdata->cmd = 0x%08x", - cdata->cmd); - - switch (cdata->cmd) { - case SOF_CTRL_CMD_BINARY: - /* calculate config size */ - reply_size = sizeof(struct sof_mux_config) + cfg->num_streams * - sizeof(struct mux_stream_data); - - /* copy back to user space */ - assert(!memcpy_s(cdata->data->data, ((struct sof_abi_hdr *) - (cdata->data))->size, cfg, reply_size)); - - cdata->data->abi = SOF_ABI_VERSION; - cdata->data->size = reply_size; - break; - default: - comp_cl_err(&comp_mux, "mux_ctrl_set_cmd() error: invalid cdata->cmd = 0x%08x", - cdata->cmd); - ret = -EINVAL; - break; - } + int i; - return ret; + for (i = 0; i < MUX_MAX_STREAMS; i++) + if (cd->config.streams[i].pipeline_id == pipe_id) + return &cd->lookup[i]; + + comp_err(dev, "couldn't find configuration for connected pipeline %u", + pipe_id); + return 0; } -/* used to pass standard and bespoke commands (with data) to component */ -static int mux_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) +static void demux_prepare_active_look_up(struct comp_data *cd, + struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *look_up) { - struct sof_ipc_ctrl_data *cdata = data; + int elem; + int active_elem = 0; - comp_info(dev, "mux_cmd() cmd = 0x%08x", cmd); + /* init pointers */ + for (elem = 0; elem < look_up->num_elems; elem++) { + 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; - switch (cmd) { - case COMP_CMD_SET_DATA: - return mux_ctrl_set_cmd(dev, cdata); - case COMP_CMD_GET_DATA: - return mux_ctrl_get_cmd(dev, cdata, max_data_size); - default: - return -EINVAL; + cd->active_lookup.copy_elem[active_elem] = look_up->copy_elem[elem]; + active_elem++; } + + cd->active_lookup.num_elems = active_elem; } /* process and copy stream data from source to sink buffers */ -static int demux_copy(struct comp_dev *dev) +static int demux_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 comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; struct comp_buffer *sink; - struct comp_buffer *sinks[MUX_MAX_STREAMS] = { NULL }; - struct list_item *clist; - uint32_t num_sinks = 0; - uint32_t i = 0; - uint32_t frames = -1; - uint32_t source_bytes; - uint32_t avail; - uint32_t sinks_bytes[MUX_MAX_STREAMS] = { 0 }; - uint32_t flags = 0; - - comp_dbg(dev, "demux_copy()"); - - if (!cd->demux) { - comp_err(dev, "demux_copy() error: no demux processing function for component."); - comp_set_state(dev, COMP_TRIGGER_RESET); - return -EINVAL; - } - - // align sink streams with their respective configurations - list_for_item(clist, &dev->bsink_list) { - sink = container_of(clist, struct comp_buffer, source_list); - if (sink->sink->state == dev->state) { - num_sinks++; - i = get_stream_index(cd, sink->pipeline_id); - sinks[i] = sink; - } - } - - /* if there are no sinks active */ - if (num_sinks == 0) - return 0; + struct audio_stream *sinks_stream[MUX_MAX_STREAMS] = { NULL }; + struct mux_look_up *look_ups[MUX_MAX_STREAMS] = { NULL }; + int frames; + int sink_bytes; + int source_bytes; + int i; - source = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); + comp_dbg(dev, "entry"); - buffer_lock(source, &flags); + /* align sink streams with their respective configurations */ + comp_dev_for_each_consumer(dev, sink) { + if (comp_buffer_get_sink_state(sink) == dev->state) { + i = get_stream_index(dev, cd, buffer_pipeline_id(sink)); + /* return if index wrong */ + if (i < 0) { + return i; + } - /* check if source is active */ - if (source->source->state != dev->state) { - buffer_unlock(source, flags); - return 0; + look_ups[i] = get_lookup_table(dev, cd, buffer_pipeline_id(sink)); + sinks_stream[i] = &sink->stream; + } } - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sinks[i]) - continue; - buffer_lock(sinks[i], &flags); - avail = audio_stream_avail_frames(&source->stream, - &sinks[i]->stream); - frames = MIN(frames, avail); - buffer_unlock(sinks[i], flags); - } + /* if there are no sinks active, then sinks[] is also empty */ + if (num_output_buffers == 0) + return 0; - buffer_unlock(source, flags); - - source_bytes = frames * audio_stream_frame_bytes(&source->stream); - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sinks[i]) - continue; - sinks_bytes[i] = frames * - audio_stream_frame_bytes(&sinks[i]->stream); - } + frames = input_buffers[0].size; + source_bytes = frames * audio_stream_frame_bytes(mod->input_buffers[0].data); + sink_bytes = frames * audio_stream_frame_bytes(mod->output_buffers[0].data); /* produce output, one sink at a time */ - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sinks[i]) - continue; - - buffer_invalidate(source, source_bytes); - cd->demux(dev, &sinks[i]->stream, &source->stream, frames, - &cd->config.streams[i]); - buffer_writeback(sinks[i], sinks_bytes[i]); + for (i = 0; i < num_output_buffers; i++) { + if (sinks_stream[i]) { + demux_prepare_active_look_up(cd, sinks_stream[i], + input_buffers[0].data, look_ups[i]); + cd->demux(dev, sinks_stream[i], input_buffers[0].data, + frames, &cd->active_lookup); + } + mod->output_buffers[i].size = sink_bytes; } - /* update components */ - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sinks[i]) - continue; - comp_update_buffer_produce(sinks[i], sinks_bytes[i]); + /* Update consumed */ + mod->input_buffers[0].consumed = source_bytes; + return 0; +} + +static int demux_trigger(struct processing_module *mod, int cmd) +{ + /* Check for cross-pipeline sinks: in general foreign + * pipelines won't be started synchronously with ours (it's + * under control of host software), so output can't be + * guaranteed not to overflow. Always set the + * overrun_permitted flag. These sink components are assumed + * responsible for flushing/synchronizing the stream + * themselves. + */ + if (cmd == COMP_TRIGGER_PRE_START) { + struct comp_buffer *b; + + comp_dev_for_each_producer(mod->dev, b) { + if (comp_buffer_get_sink_component(b)->pipeline != mod->dev->pipeline) + audio_stream_set_overrun(&b->stream, true); + } } - comp_update_buffer_consume(source, source_bytes); - return 0; + return module_adapter_set_state(mod, mod->dev, cmd); } +#endif /* process and copy stream data from source to sink buffers */ -static int mux_copy(struct comp_dev *dev) +static int mux_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 comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sink; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; struct comp_buffer *source; - struct comp_buffer *sources[MUX_MAX_STREAMS] = { NULL }; const struct audio_stream *sources_stream[MUX_MAX_STREAMS] = { NULL }; - struct list_item *clist; - uint32_t num_sources = 0; - uint32_t i = 0; - uint32_t frames = -1; - uint32_t sources_bytes[MUX_MAX_STREAMS] = { 0 }; - uint32_t sink_bytes; - uint32_t flags = 0; - - comp_dbg(dev, "mux_copy()"); - - if (!cd->mux) { - comp_err(dev, "mux_copy() error: no mux processing function for component."); - comp_set_state(dev, COMP_TRIGGER_RESET); - return -EINVAL; - } + int frames = 0; + int sink_bytes; + int i, j; + + comp_dbg(dev, "entry"); /* align source streams with their respective configurations */ - list_for_item(clist, &dev->bsource_list) { - source = container_of(clist, struct comp_buffer, sink_list); - buffer_lock(source, &flags); - if (source->source->state == dev->state) { - num_sources++; - i = get_stream_index(cd, source->pipeline_id); - sources[i] = source; + j = 0; + comp_dev_for_each_producer(dev, source) { + if (comp_buffer_get_source_state(source) == dev->state) { + if (frames) + frames = MIN(frames, input_buffers[j].size); + else + frames = input_buffers[j].size; + + i = get_stream_index(dev, cd, buffer_pipeline_id(source)); + /* return if index wrong */ + if (i < 0) { + return i; + } + sources_stream[i] = &source->stream; - } else { - buffer_unlock(source, flags); } + j++; } /* check if there are any sources active */ - if (num_sources == 0) + if (num_input_buffers == 0) return 0; - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - buffer_lock(sink, &flags); + sink_bytes = frames * audio_stream_frame_bytes(mod->output_buffers[0].data); + mux_prepare_active_look_up(cd, output_buffers[0].data, &sources_stream[0]); - /* check if sink is active */ - if (sink->sink->state != dev->state) { - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sources[i]) - continue; - buffer_unlock(sources[i], flags); - } - - buffer_unlock(sink, flags); - return 0; + /* produce output */ + cd->mux(dev, output_buffers[0].data, &sources_stream[0], frames, &cd->active_lookup); + + /* Update consumed per source using each source's own frame size */ + j = 0; + comp_dev_for_each_producer(dev, source) { + if (comp_buffer_get_source_state(source) == dev->state) + mod->input_buffers[j].consumed = + frames * audio_stream_frame_bytes(mod->input_buffers[j].data); + j++; } + mod->output_buffers[0].size = sink_bytes; + return 0; +} - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sources[i]) - continue; - frames = MIN(frames, - audio_stream_avail_frames(sources_stream[i], - &sink->stream)); - buffer_unlock(sources[i], flags); - } +static int mux_reset(struct processing_module *mod) +{ + struct comp_buffer *source; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int dir = dev->pipeline->source_comp->direction; - buffer_unlock(sink, flags); + comp_dbg(dev, "entry"); - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sources[i]) - continue; - sources_bytes[i] = frames * - audio_stream_frame_bytes(sources_stream[i]); - buffer_invalidate(sources[i], sources_bytes[i]); - } - sink_bytes = frames * audio_stream_frame_bytes(&sink->stream); + if (dir == SOF_IPC_STREAM_PLAYBACK) { + comp_dev_for_each_producer(dev, source) { + int state = comp_buffer_get_source_state(source); - /* produce output */ - cd->mux(dev, &sink->stream, &sources_stream[0], frames, - &cd->config.streams[0]); - buffer_writeback(sink, sink_bytes); - - /* update components */ - comp_update_buffer_produce(sink, sink_bytes); - for (i = 0; i < MUX_MAX_STREAMS; i++) { - if (!sources[i]) - continue; - comp_update_buffer_consume(sources[i], sources_bytes[i]); + /* only mux the sources with the same state with mux */ + if (state > COMP_STATE_READY) + /* should not reset the downstream components */ + return PPL_STATUS_PATH_STOP; + } } + cd->mux = NULL; + cd->demux = NULL; return 0; } -static int mux_reset(struct comp_dev *dev) -{ - comp_info(dev, "mux_reset()"); - - return comp_set_state(dev, COMP_TRIGGER_RESET); -} - -static int mux_prepare(struct comp_dev *dev) +static int mux_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct comp_data *cd = comp_get_drvdata(dev); + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); int ret; - comp_info(dev, "mux_prepare()"); + comp_dbg(dev, "entry"); + + ret = mux_params(mod); + if (ret < 0) + return ret; - if (dev->comp.type == SOF_COMP_MUX) - cd->mux = mux_get_processing_function(dev); + if (cd->comp_type == SOF_COMP_MUX) + cd->mux = mux_get_processing_function(mod); else - cd->demux = demux_get_processing_function(dev); + cd->demux = demux_get_processing_function(mod); if (!cd->mux && !cd->demux) { - comp_err(dev, "mux_prepare() error: Invalid configuration, couldn't find suitable processing function."); + comp_err(dev, "Invalid configuration, couldn't find suitable processing function."); return -EINVAL; } - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret) { - comp_info(dev, "mux_prepare() comp_set_state() returned non-zero."); - return ret; - } - + /* prepare downstream */ return 0; } -static int mux_trigger(struct comp_dev *dev, int cmd) +static int mux_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) { - int ret = 0; + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_data *cd = module_get_private_data(mod); - comp_info(dev, "mux_trigger(), command = %u", cmd); + comp_dbg(mod->dev, "entry"); - ret = comp_set_state(dev, cmd); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} - if (ret == COMP_STATUS_STATE_ALREADY_SET) - ret = PPL_STATUS_PATH_STOP; +static int mux_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_data *cd = module_get_private_data(mod); - return ret; + comp_dbg(mod->dev, "entry"); + + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); } -static const struct comp_driver comp_mux = { - .type = SOF_COMP_MUX, - .ops = { - .new = mux_new, - .free = mux_free, - .params = mux_params, - .cmd = mux_cmd, - .copy = mux_copy, - .prepare = mux_prepare, - .reset = mux_reset, - .trigger = mux_trigger, - }, +static const struct module_interface mux_interface = { + .init = mux_init, + .set_configuration = mux_set_config, + .get_configuration = mux_get_config, + .prepare = mux_prepare, + .process_audio_stream = mux_process, + .reset = mux_reset, + .free = mux_free, }; -static SHARED_DATA struct comp_driver_info comp_mux_info = { - .drv = &comp_mux, +#if !CONFIG_COMP_MUX_MODULE +static const struct module_interface demux_interface = { + .init = demux_init, + .set_configuration = mux_set_config, + .get_configuration = mux_get_config, + .prepare = mux_prepare, + .process_audio_stream = demux_process, + .trigger = demux_trigger, + .reset = mux_reset, + .free = mux_free, }; - -static const struct comp_driver comp_demux = { - .type = SOF_COMP_DEMUX, - .uid = SOF_UUID(mux_uuid), - .ops = { - .new = mux_new, - .free = mux_free, - .params = mux_params, - .cmd = mux_cmd, - .copy = demux_copy, - .prepare = mux_prepare, - .reset = mux_reset, - .trigger = mux_trigger, - }, +#endif + +#if CONFIG_COMP_MUX_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { + SOF_LLEXT_MODULE_MANIFEST("MUX", &mux_interface, 1, SOF_REG_UUID(mux4), 15), + /* + * The demux entry is removed because mtl.toml doesn't have an entry + * for it. Once that is fixed, the manifest line below can be + * re-activated: + * SOF_LLEXT_MODULE_MANIFEST("DEMUX", demux_llext_entry, 1, SOF_REG_UUID(demux), 15), + */ }; -static SHARED_DATA struct comp_driver_info comp_demux_info = { - .drv = &comp_demux, -}; +SOF_LLEXT_BUILDINFO; -UT_STATIC void sys_comp_mux_init(void) -{ - comp_register(platform_shared_get(&comp_mux_info, - sizeof(comp_mux_info))); - comp_register(platform_shared_get(&comp_demux_info, - sizeof(comp_demux_info))); -} +#else + +DECLARE_MODULE_ADAPTER(mux_interface, MUX_UUID, mux_tr); +SOF_MODULE_INIT(mux, sys_comp_module_mux_interface_init); -DECLARE_MODULE(sys_comp_mux_init); +DECLARE_MODULE_ADAPTER(demux_interface, demux_uuid, demux_tr); +SOF_MODULE_INIT(demux, sys_comp_module_demux_interface_init); -#endif /* CONFIG_COMP_MUX */ +#endif diff --git a/src/audio/mux/mux.h b/src/audio/mux/mux.h new file mode 100644 index 000000000000..0fb11d8300b5 --- /dev/null +++ b/src/audio/mux/mux.h @@ -0,0 +1,236 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com> + */ + +/** + * \file include/sof/audio/mux.h + * \brief Multiplexer component header file + * \authors Artur Kloniecki <arturx.kloniecki@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_MUX_H__ +#define __SOF_AUDIO_MUX_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/common.h> +#include <sof/platform.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <sof/lib/uuid.h> +#include <user/trace.h> +#include <module/module/base.h> +#include <stdint.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/base-config.h> +#endif +struct comp_buffer; +struct comp_dev; + +/** \brief Supported streams count. */ +#if CONFIG_IPC_MAJOR_3 +#define MUX_MAX_STREAMS 4 +#else +#define MUX_MAX_STREAMS 2 +#endif +#define BASE_CFG_QUEUED_ID 0 +/** guard against invalid amount of streams defined */ +STATIC_ASSERT(MUX_MAX_STREAMS < PLATFORM_MAX_STREAMS, + unsupported_amount_of_streams_for_mux); + +struct mux_copy_elem { + uint32_t stream_id; + uint32_t in_ch; + uint32_t out_ch; + + void *dest; + void *src; + + uint32_t dest_inc; + uint32_t src_inc; +}; + +struct mux_look_up { + uint32_t num_elems; + struct mux_copy_elem copy_elem[PLATFORM_MAX_CHANNELS]; +}; + +struct mux_stream_data { + uint32_t pipeline_id; + uint8_t num_channels_deprecated; /* deprecated in ABI 3.15 */ + uint8_t mask[PLATFORM_MAX_CHANNELS]; + + uint8_t reserved1[8 - PLATFORM_MAX_CHANNELS]; // padding for extra channels + uint8_t reserved2[3]; // padding to ensure proper alignment of following instances +} __attribute__((packed, aligned(4))); + +typedef void(*demux_func)(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream *source, uint32_t frames, + struct mux_look_up *look_up); +typedef void(*mux_func)(struct comp_dev *dev, struct audio_stream *sink, + const struct audio_stream **sources, uint32_t frames, + struct mux_look_up *look_up); + +/** + * \brief Mux/Demux component config structure. + * + * The multiplexer/demultiplexer component copies its input audio channels + * into output audio channels according to a specific routing matrix. + * Multiplexer has multiple input audio streams and a single audio output + * stream. Demultiplexer has a single input stream and multiple output streams. + * + * Struct sof_mux_config includes array of mux_stream_data struct elements - + * streams[]. Each element of streams[] array refers to streams on "many" side + * of mux/demux component i.e. input streams for mux and output streams for + * demux. + * + * Struct mux_stream_data consists mask[] array. + * In the mux case, one mask[] element per input channel - each mask shows, to + * which output channel data should be copied. + * In the demux case, one mask[] element per output channel - each mask shows, + * from which input channel data should be taken. + * + * Mux example: + * Assuming that below mask array refers to x input stream: + * mask[] = { 0b00000001, + * 0b00000100 } + * it means that: + * - first input channel of stream x (mask[0]) will be copied to first output + * channel (0b00000001 & BIT(0)); + * - second input channel of stream x (mask[1]) will be copied to third output + * channel (0b00000100 & BIT(2)). + * + * Demux example: + * Assuming that below mask array refers to x output stream: + * mask[] = { 0b00000001, + * 0b00000100 } + * it means that: + * - first input channel (0b00000001 & BIT(0)) will be copied to first output + * (mask[0]) channel of stream x; + * - third input channel (0b00000100 & BIT(2)) will be copied to second output + * (mask[1]) channel of stream x. + */ +struct sof_mux_config { + uint16_t frame_format_deprecated; /* deprecated in ABI 3.15 */ + uint16_t num_channels_deprecated; /* deprecated in ABI 3.15 */ + uint16_t num_streams; + + uint16_t reserved; // padding to ensure proper alignment + + struct mux_stream_data streams[]; +} __attribute__((packed, aligned(4))); + +#if CONFIG_IPC_MAJOR_4 +/** + * \brief MUX module configuration in IPC4. + * + * This module output map is statically defined by the adapter (shim) as: + * - Input pin 0 channel "x" ("x" = 0.."M", "M" <=3) to output channel "x", + * where "M" is number of channels on input pin 0, + * - Input pin 1 (reference) channel "y" (y = 0..1) to output channel "M"+1+"y". + * + * If input pin 0 is not connected, module will not produce any output. + * If input pin 1 (know also as reference pin) is not connected then module will + * in output (for time slot meant for pin 1) generate zeros. + * + * Setting masks for streams is done according to the order of pins and channels. + * First the first input stream, then the reference. + * For example, for base config 2-channel and reference 2-channel, masks + * should look like: mask[] = { 0b00000001, 0b00000010 } for the first + * stream and mask[] = { 0b00000100, 0b00001000 } for the second + * (reference) + * +---+ +---+ + * | 0 |---------> | 0 | + * INPUT +---+ +---+ + * STREAM 0 | 1 |---------> | 1 | + * +---+ +---+ OUTPUT + * +----> | 2 | STREAM + * +---+ | +---+ + * | 0 |----+ +-> | 3 | + * INPUT +---+ | +---+ + * STREAM 1 | 1 |-------+ + * +---+ + */ +struct mux_data { + struct ipc4_base_module_cfg base_cfg; + //! Reference pin format. + struct ipc4_audio_format reference_format; + //! Output pin format. + struct ipc4_audio_format output_format; +}; +#endif + +struct comp_data { +#if CONFIG_IPC_MAJOR_4 + struct mux_data md; +#endif + union { + mux_func mux; + demux_func demux; + }; + + struct mux_look_up lookup[MUX_MAX_STREAMS]; + struct mux_look_up active_lookup; + struct comp_data_blob_handler *model_handler; + enum sof_comp_type comp_type; + struct sof_mux_config config; /* Keep last due to flexible array member in end */ +}; + +struct comp_func_map { + uint16_t frame_format; + mux_func mux_proc_func; + demux_func demux_proc_func; +}; + +extern const struct comp_func_map mux_func_map[]; + +void mux_prepare_look_up_table(struct processing_module *mod); +void demux_prepare_look_up_table(struct processing_module *mod); + +mux_func mux_get_processing_function(struct processing_module *mod); +demux_func demux_get_processing_function(struct processing_module *mod); + +#ifdef UNIT_TEST + +#if CONFIG_FORMAT_S16LE +int32_t calc_sample_s16le(const struct audio_stream *source, + uint32_t offset, uint8_t mask); +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE +int32_t calc_sample_s24le(const struct audio_stream *source, + uint32_t offset, uint8_t mask); +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE +int64_t calc_sample_s32le(const struct audio_stream *source, + uint32_t offset, uint8_t mask); +#endif /* CONFIG_FORMAT_S32LE */ + +void sys_comp_module_mux_interface_init(void); +void sys_comp_module_demux_interface_init(void); + +#endif /* UNIT_TEST */ + +#define MUX_BLOB_STREAMS_SIZE (MUX_MAX_STREAMS * sizeof(struct mux_stream_data)) +#ifdef CONFIG_IPC_MAJOR_4 +#define MUX_BLOB_MAX_SIZE (sizeof(struct mux_data)) +#else +#define MUX_BLOB_MAX_SIZE (sizeof(struct sof_mux_config) + MUX_BLOB_STREAMS_SIZE) +#endif + +extern const struct sof_uuid demux_uuid; +extern struct tr_ctx mux_tr; +extern struct tr_ctx demux_tr; + +bool mux_mix_check(struct sof_mux_config *cfg); +int mux_params(struct processing_module *mod); + +#ifdef CONFIG_IPC_MAJOR_4 +#define MUX_UUID mux4_uuid +#else +#define MUX_UUID mux_uuid +#endif +extern const struct sof_uuid MUX_UUID; + +#endif /* __SOF_AUDIO_MUX_H__ */ diff --git a/src/audio/mux/mux.toml b/src/audio/mux/mux.toml new file mode 100644 index 000000000000..f42b294850df --- /dev/null +++ b/src/audio/mux/mux.toml @@ -0,0 +1,24 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "MUX" + uuid = UUIDREG_STR_MUX4 + affinity_mask = "0x1" + instance_count = "15" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "6" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # 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, 280, 460700, 16, 16, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/mux/mux_generic.c b/src/audio/mux/mux_generic.c index 32803cc9dcbe..20d21afdffb1 100644 --- a/src/audio/mux/mux_generic.c +++ b/src/audio/mux/mux_generic.c @@ -4,405 +4,557 @@ // // Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com> -#include <config.h> - #if CONFIG_COMP_MUX +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/buffer.h> #include <sof/audio/component.h> #include <sof/audio/format.h> -#include <sof/audio/mux.h> -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/common.h> #include <ipc/stream.h> #include <stddef.h> #include <stdint.h> +#include "mux.h" + +LOG_MODULE_DECLARE(muxdemux, CONFIG_SOF_LOG_LEVEL); + +static void mux_check_for_wrap(struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) +{ + const struct audio_stream *source; + uint32_t elem; + + /* check sources and destinations for wrap */ + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + lookup->copy_elem[elem].dest = + audio_stream_wrap(sink, lookup->copy_elem[elem].dest); + lookup->copy_elem[elem].src = + audio_stream_wrap(source, lookup->copy_elem[elem].src); + } +} + +static void demux_check_for_wrap(struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) +{ + uint32_t elem; + + /* check sources and destinations for wrap */ + for (elem = 0; elem < lookup->num_elems; elem++) { + lookup->copy_elem[elem].dest = + audio_stream_wrap(sink, lookup->copy_elem[elem].dest); + lookup->copy_elem[elem].src = + audio_stream_wrap(source, lookup->copy_elem[elem].src); + } +} + #if CONFIG_FORMAT_S16LE -/* - * \brief Fetch 16b samples from source buffer and perform routing operations - * based on mask provided. - * \param[in,out] source Source buffer. - * \param[in] num_ch Number of channels in source buffer. - * \param[in] offset Offset in source buffer. - * \param[in] mask Routing bitmask for calculating output sample. - */ -UT_STATIC inline int32_t calc_sample_s16le(const struct audio_stream *source, - uint8_t num_ch, uint32_t offset, - uint8_t mask) + +static uint32_t demux_calc_frames_without_wrap_s16(struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) { - int32_t sample = 0; - int16_t *src; - int8_t in_ch; + uint32_t frames; + uint32_t min_frames; + void *ptr; - if (mask == 0) - return 0; + /* for demux we process each source buffer separately - dest/src for + * each copy_elem refers to the same sink/source buffer, so min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int16_t *)lookup->copy_elem[0].dest - + lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); - for (in_ch = 0; in_ch < num_ch; in_ch++) { - if (mask & BIT(in_ch)) { - src = audio_stream_read_frag_s16(source, - offset + in_ch); - sample += *src; - } + ptr = (int16_t *)lookup->copy_elem[0].src - + lookup->copy_elem[0].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; + + return min_frames; +} + +static uint32_t mux_calc_frames_without_wrap_s16(struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) +{ + const struct audio_stream *source; + uint32_t frames; + uint32_t min_frames; + uint32_t elem; + void *ptr; + + /* dest pointer for all copy_elems in lookup refers to the same + * sink buffer (mux has one sink buffer), so dest min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int16_t *)lookup->copy_elem[0].dest - + lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); + + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + + ptr = (int16_t *)lookup->copy_elem[elem].src - + lookup->copy_elem[elem].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; } - return sample; + return min_frames; } -/* \brief Demuxing 16 bit streams. - * - * Source stream is routed to sink with regard to routing bitmasks from - * mux_stream_data structure. Each bitmask describes composition of single - * output channel. +static void mux_init_look_up_pointers_s16(struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) +{ + const struct audio_stream *source; + uint32_t elem; + + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + + lookup->copy_elem[elem].src = (int16_t *)audio_stream_get_rptr(source) + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); + + lookup->copy_elem[elem].dest = (int16_t *)audio_stream_get_wptr(sink) + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); + } +} + +static void demux_init_look_up_pointers_s16(struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) +{ + uint32_t elem; + + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + lookup->copy_elem[elem].src = (int16_t *)audio_stream_get_rptr(source) + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); + + lookup->copy_elem[elem].dest = (int16_t *)audio_stream_get_wptr(sink) + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); + } +} + +/** + * Source stream are routed to sinks with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * \param[in,out] dev Demux base component device. - * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. - * \param[in] frames Number of frames to process. - * \param[in] data Parameters describing channel count and routing. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void demux_s16le(const struct comp_dev *dev, struct audio_stream *sink, +static void demux_s16le(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data) + struct mux_look_up *lookup) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t sample; + uint32_t i; + int16_t *src; int16_t *dst; - uint32_t dst_idx; - uint8_t i; - uint8_t out_ch; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < data->num_channels; out_ch++) { - sample = calc_sample_s16le(source, - cd->config.num_channels, - i * cd->config.num_channels, - data->mask[out_ch]); - - /* saturate to 16 bits */ - dst_idx = i * data->num_channels + out_ch; - dst = audio_stream_write_frag_s16(sink, dst_idx); - *dst = sat_int16(sample); + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "entry"); + + if (!lookup || !lookup->num_elems) + return; + + demux_init_look_up_pointers_s16(sink, source, lookup); + + while (frames) { + frames_without_wrap = + demux_calc_frames_without_wrap_s16(sink, source, lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int16_t *)lookup->copy_elem[elem].src; + dst = (int16_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; + } } + + demux_check_for_wrap(sink, source, lookup); + + frames -= frames_without_wrap; } } -/* \brief Muxing 16 bit streams. +/** + * Source streams are routed to sink with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * Source streams are routed to sink with regard to routing bitmasks from - * mux_stream_data structures array. Each source stream has bitmask for each - * of it's channels describing to which channels of output stream it - * contributes. - * - * \param[in,out] dev Demux base component device. - * \param[in,out] sink Destination buffer. - * \param[in,out] sources Array of source buffers. - * \param[in] frames Number of frames to process. - * \param[in] data Array of parameters describing channel count and routing for - * each stream. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void mux_s16le(const struct comp_dev *dev, struct audio_stream *sink, +static void mux_s16le(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data) + struct mux_look_up *lookup) { - struct comp_data *cd = comp_get_drvdata(dev); - const struct audio_stream *source; - uint8_t i; - uint8_t j; - uint8_t out_ch; + uint32_t i; + int16_t *src; int16_t *dst; - uint32_t dst_idx; - int32_t sample; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < cd->config.num_channels; out_ch++) { - sample = 0; - - for (j = 0; j < MUX_MAX_STREAMS; j++) { - source = sources[j]; - if (!source) - continue; - - sample += calc_sample_s16le(source, - data[j].num_channels, - i * data[j].num_channels, - data[j].mask[out_ch]); + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "entry"); + + if (!lookup || !lookup->num_elems) + return; + + mux_init_look_up_pointers_s16(sink, sources, lookup); + + while (frames) { + frames_without_wrap = + mux_calc_frames_without_wrap_s16(sink, sources, lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int16_t *)lookup->copy_elem[elem].src; + dst = (int16_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; } - dst_idx = i * data->num_channels + out_ch; - dst = audio_stream_write_frag_s16(sink, dst_idx); - *dst = sat_int16(sample); } + + mux_check_for_wrap(sink, sources, lookup); + + frames -= frames_without_wrap; } } #endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE -/* - * \brief Fetch 24b samples from source buffer and perform routing operations - * based on mask provided. - * \param[in,out] source Source buffer. - * \param[in] num_ch Number of channels in source buffer. - * \param[in] offset Offset in source buffer. - * \param[in] mask Routing bitmask for calculating output sample. - */ -UT_STATIC inline int32_t calc_sample_s24le(const struct audio_stream *source, - uint8_t num_ch, uint32_t offset, - uint8_t mask) +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE + +static uint32_t mux_calc_frames_without_wrap_s32(struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) { - int32_t sample = 0; - int32_t *src; - int8_t in_ch; + const struct audio_stream *source; + uint32_t frames; + uint32_t min_frames; + uint32_t elem; + void *ptr; - if (mask == 0) - return 0; + /* dest pointer for all copy_elems in lookup refers to the same + * sink buffer (mux has one sink buffer), so dest min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int32_t *)lookup->copy_elem[0].dest - lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); - for (in_ch = 0; in_ch < num_ch; in_ch++) { - if (mask & BIT(in_ch)) { - src = audio_stream_read_frag_s32(source, - offset + in_ch); - sample += sign_extend_s24(*src); - } + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + + ptr = (int32_t *)lookup->copy_elem[elem].src - lookup->copy_elem[elem].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; } - return sample; + return min_frames; } -/* \brief Demuxing 24 bit streams. - * - * Source stream is routed to sink with regard to routing bitmasks from - * mux_stream_data structure. Each bitmask describes composition of single - * output channel. - * - * \param[in,out] dev Demux base component device. - * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. - * \param[in] frames Number of frames to process. - * \param[in] data Parameters describing channel count and routing. - */ -static void demux_s24le(const struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data) +static uint32_t demux_calc_frames_without_wrap_s32(struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t sample; - int32_t *dst; - uint32_t dst_idx; - uint8_t i; - uint8_t out_ch; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < data->num_channels; out_ch++) { - sample = calc_sample_s24le(source, - cd->config.num_channels, - i * cd->config.num_channels, - data->mask[out_ch]); - - /* saturate to 24 bits */ - dst_idx = i * data->num_channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int24(sample); - } - } + uint32_t frames; + uint32_t min_frames; + void *ptr; + + /* for demux we process each source buffer separately - dest/src for + * each copy_elem refers to the same sink/source buffer, so min_frames + * calculation based only on lookup table first element is sufficient. + */ + ptr = (int32_t *)lookup->copy_elem[0].dest - lookup->copy_elem[0].out_ch; + min_frames = audio_stream_frames_without_wrap(sink, ptr); + + ptr = (int32_t *)lookup->copy_elem[0].src - lookup->copy_elem[0].in_ch; + frames = audio_stream_frames_without_wrap(source, ptr); + + min_frames = (frames < min_frames) ? frames : min_frames; + + return min_frames; } -/* \brief Muxing 24 bit streams. - * - * Source streams are routed to sink with regard to routing bitmasks from - * mux_stream_data structures array. Each source stream has bitmask for each - * of it's channels describing to which channels of output stream it - * contributes. - * - * \param[in,out] dev Demux base component device. - * \param[in,out] sink Destination buffer. - * \param[in,out] sources Array of source buffers. - * \param[in] frames Number of frames to process. - * \param[in] data Array of parameters describing channel count and routing for - * each stream. - */ -static void mux_s24le(const struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data) +static void mux_init_look_up_pointers_s32(struct audio_stream *sink, + const struct audio_stream **sources, + struct mux_look_up *lookup) { - struct comp_data *cd = comp_get_drvdata(dev); const struct audio_stream *source; - uint8_t i; - uint8_t j; - uint8_t out_ch; - int32_t *dst; - uint32_t dst_idx; - int32_t sample; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < cd->config.num_channels; out_ch++) { - sample = 0; - for (j = 0; j < MUX_MAX_STREAMS; j++) { - source = sources[j]; - if (!source) - continue; - - sample += calc_sample_s24le(source, - data[j].num_channels, - i * data[j].num_channels, - data[j].mask[out_ch]); - } - dst_idx = i * data->num_channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int24(sample); - } + uint32_t elem; + + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + source = sources[lookup->copy_elem[elem].stream_id]; + + lookup->copy_elem[elem].src = (int32_t *)audio_stream_get_rptr(source) + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); + + lookup->copy_elem[elem].dest = (int32_t *)audio_stream_get_wptr(sink) + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); } } -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE -/* - * \brief Fetch 32b samples from source buffer and perform routing operations - * based on mask provided. - * \param[in,out] source Source buffer. - * \param[in] num_ch Number of channels in source buffer. - * \param[in] offset Offset in source buffer. - * \param[in] mask Routing bitmask for calculating output sample. - */ -UT_STATIC inline int64_t calc_sample_s32le(const struct audio_stream *source, - uint8_t num_ch, uint32_t offset, - uint8_t mask) +static void demux_init_look_up_pointers_s32(struct audio_stream *sink, + const struct audio_stream *source, + struct mux_look_up *lookup) { - int64_t sample = 0; - int32_t *src; - int8_t in_ch; + uint32_t elem; - if (mask == 0) - return 0; + /* init pointers */ + for (elem = 0; elem < lookup->num_elems; elem++) { + lookup->copy_elem[elem].src = (int32_t *)audio_stream_get_rptr(source) + + lookup->copy_elem[elem].in_ch; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); - for (in_ch = 0; in_ch < num_ch; in_ch++) { - if (mask & BIT(in_ch)) { - src = audio_stream_read_frag_s32(source, - offset + in_ch); - sample += *src; - } + lookup->copy_elem[elem].dest = (int32_t *)audio_stream_get_wptr(sink) + + lookup->copy_elem[elem].out_ch; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); } - - return sample; } -/* \brief Demuxing 32 bit streams. +/** + * Source stream are routed to sinks with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * Source stream is routed to sink with regard to routing bitmasks from - * mux_stream_data structure. Each bitmask describes composition of single - * output channel. - * - * \param[in,out] dev Demux base component device. - * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. - * \param[in] frames Number of frames to process. - * \param[in] data Parameters describing channel count and routing. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void demux_s32le(const struct comp_dev *dev, struct audio_stream *sink, +static void demux_s32le(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data) + struct mux_look_up *lookup) { - struct comp_data *cd = comp_get_drvdata(dev); - int64_t sample; + uint32_t i; + int32_t *src; int32_t *dst; - uint32_t dst_idx; - uint8_t i; - uint8_t out_ch; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < data->num_channels; out_ch++) { - sample = calc_sample_s32le(source, - cd->config.num_channels, - i * cd->config.num_channels, - data->mask[out_ch]); - - /* saturate to 32 bits */ - dst_idx = i * data->num_channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int32(sample); + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "entry"); + + if (!lookup || !lookup->num_elems) + return; + + demux_init_look_up_pointers_s32(sink, source, lookup); + + while (frames) { + frames_without_wrap = + demux_calc_frames_without_wrap_s32(sink, source, lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int32_t *)lookup->copy_elem[elem].src; + dst = (int32_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; + } } + + demux_check_for_wrap(sink, source, lookup); + + frames -= frames_without_wrap; } } -/* \brief Muxing 32 bit streams. +/** + * Source streams are routed to sink with regard to look up table based on + * routing bitmasks from mux_stream_data structures array. Each sink channel + * has it's own lookup[].copy_elem describing source and sink fragment of + * memory featured in copying. * - * Source streams are routed to sink with regard to routing bitmasks from - * mux_stream_data structures array. Each source stream has bitmask for each - * of it's channels describing to which channels of output stream it - * contributes. - * - * \param[in,out] dev Demux base component device. - * \param[in,out] sink Destination buffer. - * \param[in,out] sources Array of source buffers. - * \param[in] frames Number of frames to process. - * \param[in] data Array of parameters describing channel count and routing for - * each stream. + * @param[in] dev Component device + * @param[in,out] sink Destination buffer. + * @param[in,out] sources Array of source buffers. + * @param[in] frames Number of frames to process. + * @param[in] lookup mux look up table. */ -static void mux_s32le(const struct comp_dev *dev, struct audio_stream *sink, +static void mux_s32le(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data) + struct mux_look_up *lookup) { - struct comp_data *cd = comp_get_drvdata(dev); - const struct audio_stream *source; - uint8_t i; - uint8_t j; - uint8_t out_ch; + uint32_t i; + int32_t *src; int32_t *dst; - uint32_t dst_idx; - int64_t sample; - - for (i = 0; i < frames; i++) { - for (out_ch = 0; out_ch < cd->config.num_channels; out_ch++) { - sample = 0; - for (j = 0; j < MUX_MAX_STREAMS; j++) { - source = sources[j]; - if (!source) - continue; - - sample += calc_sample_s32le(source, - data[j].num_channels, - i * data[j].num_channels, - data[j].mask[out_ch]); + uint32_t elem; + uint32_t frames_without_wrap; + + comp_dbg(dev, "entry"); + + if (!lookup || !lookup->num_elems) + return; + + mux_init_look_up_pointers_s32(sink, sources, lookup); + + while (frames) { + frames_without_wrap = + mux_calc_frames_without_wrap_s32(sink, sources, lookup); + + frames_without_wrap = MIN(frames, frames_without_wrap); + + for (i = 0; i < frames_without_wrap; i++) { + for (elem = 0; elem < lookup->num_elems; elem++) { + src = (int32_t *)lookup->copy_elem[elem].src; + dst = (int32_t *)lookup->copy_elem[elem].dest; + *dst = *src; + lookup->copy_elem[elem].src = src + + lookup->copy_elem[elem].src_inc; + lookup->copy_elem[elem].dest = dst + + lookup->copy_elem[elem].dest_inc; } - dst_idx = i * data->num_channels + out_ch; - dst = audio_stream_write_frag_s32(sink, dst_idx); - *dst = sat_int32(sample); } + + mux_check_for_wrap(sink, sources, lookup); + + frames -= frames_without_wrap; } } -#endif /* CONFIG_FORMAT_S32LE */ +#endif /* CONFIG_FORMAT_S24LE CONFIG_FORMAT_S32LE */ const struct comp_func_map mux_func_map[] = { #if CONFIG_FORMAT_S16LE { SOF_IPC_FRAME_S16_LE, &mux_s16le, &demux_s16le }, #endif #if CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S24_4LE, &mux_s24le, &demux_s24le }, + { SOF_IPC_FRAME_S24_4LE, &mux_s32le, &demux_s32le }, #endif #if CONFIG_FORMAT_S32LE { SOF_IPC_FRAME_S32_LE, &mux_s32le, &demux_s32le }, #endif }; -mux_func mux_get_processing_function(struct comp_dev *dev) +void mux_prepare_look_up_table(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); - uint8_t i; + struct comp_data *cd = module_get_private_data(mod); + uint32_t i; + uint32_t j; + uint32_t k; + uint32_t idx = 0; + + /* Prepare look up table */ + for (i = 0; i < cd->config.num_streams; i++) { + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) { + for (k = 0; k < PLATFORM_MAX_CHANNELS; k++) { + if (cd->config.streams[i].mask[j] & BIT(k)) { + /* MUX component has only one sink */ + cd->lookup[0].copy_elem[idx].in_ch = j; + cd->lookup[0].copy_elem[idx].out_ch = k; + cd->lookup[0].copy_elem[idx].stream_id = i; + cd->lookup[0].num_elems = ++idx; + } + } + } + } +} + +void demux_prepare_look_up_table(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + uint32_t i; + uint32_t j; + uint32_t k; + uint32_t idx; + + /* Prepare look up table */ + for (i = 0; i < cd->config.num_streams; i++) { + idx = 0; + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) { + for (k = 0; k < PLATFORM_MAX_CHANNELS; k++) { + if (cd->config.streams[i].mask[j] & BIT(k)) { + /* DEMUX component has only one source */ + cd->lookup[i].copy_elem[idx].in_ch = k; + cd->lookup[i].copy_elem[idx].out_ch = j; + cd->lookup[i].copy_elem[idx].stream_id = i; + cd->lookup[i].num_elems = ++idx; + } + } + } + } +} + +mux_func mux_get_processing_function(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct comp_buffer *sinkb; + uint32_t i; + + if (list_is_empty(&dev->bsink_list)) + return NULL; + + sinkb = comp_dev_get_first_data_consumer(dev); for (i = 0; i < ARRAY_SIZE(mux_func_map); i++) { - if (cd->config.frame_format == mux_func_map[i].frame_format) + enum sof_ipc_frame fmt = audio_stream_get_frm_fmt(&sinkb->stream); + + + if (fmt == mux_func_map[i].frame_format) return mux_func_map[i].mux_proc_func; } return NULL; } -demux_func demux_get_processing_function(struct comp_dev *dev) +demux_func demux_get_processing_function(struct processing_module *mod) { - struct comp_data *cd = comp_get_drvdata(dev); - uint8_t i; + struct comp_dev *dev = mod->dev; + struct comp_buffer *sourceb; + uint32_t i; + + if (list_is_empty(&dev->bsource_list)) + return NULL; + + sourceb = comp_dev_get_first_data_producer(dev); for (i = 0; i < ARRAY_SIZE(mux_func_map); i++) { - if (cd->config.frame_format == mux_func_map[i].frame_format) + enum sof_ipc_frame fmt = audio_stream_get_frm_fmt(&sourceb->stream); + + if (fmt == mux_func_map[i].frame_format) return mux_func_map[i].demux_proc_func; } diff --git a/src/audio/mux/mux_ipc3.c b/src/audio/mux/mux_ipc3.c new file mode 100644 index 000000000000..fb00030b5814 --- /dev/null +++ b/src/audio/mux/mux_ipc3.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Artur Kloniecki <arturx.kloniecki@linux.intel.com> + +#if CONFIG_COMP_MUX + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <module/module/base.h> +#include <sof/trace/trace.h> +#include <rtos/string_macro.h> +#include <sof/lib/uuid.h> +#include <sof/common.h> +#include <sof/platform.h> +#include <ipc/topology.h> +#include <errno.h> + +#include "mux.h" + +LOG_MODULE_DECLARE(muxdemux, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(mux); + +DECLARE_TR_CTX(mux_tr, SOF_UUID(mux_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(demux); + +DECLARE_TR_CTX(demux_tr, SOF_UUID(demux_uuid), LOG_LEVEL_INFO); + +static int mux_set_values(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_mux_config *cfg = &cd->config; + unsigned int i; + unsigned int j; + + comp_dbg(dev, "entry"); + + /* check if number of streams configured doesn't exceed maximum */ + if (cfg->num_streams > MUX_MAX_STREAMS) { + comp_err(dev, "configured number of streams (%u) exceeds maximum = " + STRINGIFY(MUX_MAX_STREAMS), cfg->num_streams); + return -EINVAL; + } + + /* check if all streams configured have distinct IDs */ + for (i = 0; i < cfg->num_streams; i++) { + for (j = i + 1; j < cfg->num_streams; j++) { + if (cfg->streams[i].pipeline_id == + cfg->streams[j].pipeline_id) { + comp_err(dev, "multiple configured streams have same pipeline ID = %u", + cfg->streams[i].pipeline_id); + return -EINVAL; + } + } + } + + for (i = 0; i < cfg->num_streams; i++) { + for (j = 0 ; j < PLATFORM_MAX_CHANNELS; j++) { + if (popcount(cfg->streams[i].mask[j]) > 1) { + comp_err(dev, "mux component is not able to mix channels"); + return -EINVAL; + } + } + } + + if (cd->comp_type == SOF_COMP_MUX) { + if (mux_mix_check(cfg)) + comp_err(dev, "mux component is not able to mix channels"); + } + + for (i = 0; i < cfg->num_streams; i++) { + cd->config.streams[i].pipeline_id = cfg->streams[i].pipeline_id; + for (j = 0; j < PLATFORM_MAX_CHANNELS; j++) + cd->config.streams[i].mask[j] = cfg->streams[i].mask[j]; + } + + cd->config.num_streams = cfg->num_streams; + + if (cd->comp_type == SOF_COMP_MUX) + mux_prepare_look_up_table(mod); + else + demux_prepare_look_up_table(mod); + + if (dev->state > COMP_STATE_INIT) { + if (cd->comp_type == SOF_COMP_MUX) + cd->mux = mux_get_processing_function(mod); + else + cd->demux = demux_get_processing_function(mod); + } + + return 0; +} + +int mux_params(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_mux_config *config; + size_t blob_size; + + config = comp_get_data_blob(cd->model_handler, &blob_size, NULL); + if (blob_size > MUX_BLOB_MAX_SIZE) { + comp_err(mod->dev, "illegal blob size %zu", blob_size); + return -EINVAL; + } + + memcpy_s(&cd->config, MUX_BLOB_MAX_SIZE, config, blob_size); + + return mux_set_values(mod); +} +#endif /* CONFIG_COMP_MUX */ diff --git a/src/audio/mux/mux_ipc4.c b/src/audio/mux/mux_ipc4.c new file mode 100644 index 000000000000..dc6877059f57 --- /dev/null +++ b/src/audio/mux/mux_ipc4.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Artur Kloniecki <arturx.kloniecki@linux.intel.com> + +#if CONFIG_COMP_MUX + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/component.h> +#include <sof/audio/buffer.h> +#include <sof/audio/data_blob.h> +#include <sof/trace/trace.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <ipc/stream.h> +#include <module/module/base.h> +#include <module/ipc4/base-config.h> +#include <errno.h> + +#include "mux.h" + +LOG_MODULE_DECLARE(muxdemux, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(mux4); + +DECLARE_TR_CTX(mux_tr, SOF_UUID(mux4_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(demux); + +DECLARE_TR_CTX(demux_tr, SOF_UUID(demux_uuid), LOG_LEVEL_INFO); + +static int build_config(struct processing_module *mod, struct mux_data *cfg) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + int mask = 1; + int i; + + cd->config.num_streams = MUX_MAX_STREAMS; + + /* clear masks */ + for (i = 0; i < cd->config.num_streams; i++) + memset(cd->config.streams[i].mask, 0, sizeof(cd->config.streams[i].mask)); + + /* Setting masks for streams */ + for (i = 0; i < cfg->base_cfg.audio_fmt.channels_count; i++) { + cd->config.streams[0].mask[i] = mask; + mask <<= 1; + } + + for (i = 0; i < cfg->reference_format.channels_count; i++) { + cd->config.streams[1].mask[i] = mask; + mask <<= 1; + } + + /* validation of matrix mixing */ + if (mux_mix_check(&cd->config)) { + comp_err(dev, "mux component is not able to mix channels"); + return -EINVAL; + } + return 0; +} + +/* In ipc4 case param is figured out by module config so we need to first + * set up param then verify param. BTW for IPC3 path, the param is sent by + * host driver. + */ +static void set_mux_params(struct processing_module *mod, struct mux_data *cfg) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sink, *source; + int j; + + params->direction = dev->direction; + params->channels = cfg->base_cfg.audio_fmt.channels_count; + params->rate = cfg->base_cfg.audio_fmt.sampling_frequency; + params->sample_container_bytes = cfg->base_cfg.audio_fmt.depth / 8; + params->sample_valid_bytes = cfg->base_cfg.audio_fmt.valid_bit_depth / 8; + params->buffer_fmt = cfg->base_cfg.audio_fmt.interleaving_style; + params->buffer.size = cfg->base_cfg.ibs; + params->no_stream_position = 1; + + /* There are two input pins and one output pin in the mux. + * For the first input we assign parameters from base_cfg, + * for the second from reference_format + * and for sink output_format. + */ + + /* update sink format */ + if (!list_is_empty(&dev->bsink_list)) { + sink = comp_dev_get_first_data_consumer(dev); + + if (!audio_buffer_hw_params_configured(&sink->audio_buffer)) { + ipc4_update_buffer_format(sink, &cfg->output_format); + params->frame_fmt = audio_stream_get_frm_fmt(&sink->stream); + } + } + + /* update each source format */ + if (!list_is_empty(&dev->bsource_list)) { + struct ipc4_audio_format *audio_fmt; + + comp_dev_for_each_producer(dev, source) { + j = IPC4_SINK_QUEUE_ID(buf_get_id(source)); + cd->config.streams[j].pipeline_id = buffer_pipeline_id(source); + if (j == BASE_CFG_QUEUED_ID) + audio_fmt = &cfg->base_cfg.audio_fmt; + else + audio_fmt = &cfg->reference_format; + + ipc4_update_buffer_format(source, audio_fmt); + } + } + + mux_prepare_look_up_table(mod); +} + +int mux_params(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct mux_data *cfg; + size_t blob_size; + int ret; + + cfg = comp_get_data_blob(cd->model_handler, &blob_size, NULL); + if (!cfg || blob_size > MUX_BLOB_MAX_SIZE) { + comp_err(mod->dev, "illegal blob size %zu", blob_size); + return -EINVAL; + } + + ret = build_config(mod, cfg); + if (ret < 0) + return ret; + + set_mux_params(mod, cfg); + + return ret; +} +#endif /* CONFIG_COMP_MUX */ diff --git a/src/audio/nxp/CMakeLists.txt b/src/audio/nxp/CMakeLists.txt new file mode 100644 index 000000000000..967f2f019164 --- /dev/null +++ b/src/audio/nxp/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_NXP_EAP) + + zephyr_include_directories(${sof_top_dir}/eap_sdk) + zephyr_include_directories(${sof_top_dir}/third_party) + + zephyr_library_sources(eap.c) + + if(CONFIG_COMP_NXP_EAP_STUB) + zephyr_library_sources(eap_stub.c) + else() + zephyr_library_import(EAPLibrary + ${sof_top_dir}/eap_sdk/EAP_Library/libEAP16_3_0_13_FP1_RT600.a) + endif() + +endif() diff --git a/src/audio/nxp/Kconfig b/src/audio/nxp/Kconfig new file mode 100644 index 000000000000..45a9a15f80ef --- /dev/null +++ b/src/audio/nxp/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_NXP_EAP + tristate "NXP EAP Component" + help + Select for NXP Essential Audio Processing Component. + The EAP is a bundle of audio processing blocks for enhancing the tonal + and spatial perception of sound in audio applications. + +config COMP_NXP_EAP_STUB + tristate "NXP EAP Component stub" + depends on COMP_NXP_EAP + help + Select for NXP EAP stub support. diff --git a/src/audio/nxp/README.md b/src/audio/nxp/README.md new file mode 100644 index 000000000000..b8a59e0256aa --- /dev/null +++ b/src/audio/nxp/README.md @@ -0,0 +1,10 @@ +# NXP Specific Components Architecture + +## Overview + +This directory contains DSP components tailored for NXP hardware acceleration or special features. + +## Configuration and Scripts + +- **Kconfig**: Manages the proprietary NXP Essential Audio Processing blocks (`COMP_NXP_EAP`), aiming to enhance tonal and spatial audio perception. Also supports testing through a stub mechanism (`COMP_NXP_EAP_STUB`). +- **CMakeLists.txt**: Configures external NXP SDK directories and intelligently links the `eap.c` wrapper either against the stub logic or the authentic `libEAP16_3_0_13_FP1_RT600.a` static library blob. diff --git a/src/audio/nxp/eap.c b/src/audio/nxp/eap.c new file mode 100644 index 000000000000..3e596a5cf85d --- /dev/null +++ b/src/audio/nxp/eap.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2025 NXP +// +// Author: Daniel Baluta <daniel.baluta@nxp.com> + +#include <rtos/panic.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <rtos/string.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/dai.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <module/module/interface.h> +#include <zephyr/logging/log.h> + +#include <sof/audio/nxp/eap/eap_lib_defines.h> +#include <nxp/eap/EAP_Includes/EAP16.h> +#include <sof/audio/nxp/eap/EAP_Parameter_presets.h> + +LOG_MODULE_REGISTER(nxp_eap, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(nxp_eap); +DECLARE_TR_CTX(nxp_eap_tr, SOF_UUID(nxp_eap_uuid), LOG_LEVEL_INFO); + +#define NXP_EAP_DEFAULT_MAX_BLOCK_SIZE 480 + +struct nxp_eap_data { + LVM_Handle_t instance; + LVM_MemTab_t mem_tab; + LVM_InstParams_t inst_params; + LVM_ControlParams_t ctrl_params; + int sample_rate; + int channels; + int frame_bytes; + int audio_time_ms; + uint32_t buffer_bytes; +}; + +struct nxp_eap_preset_params { + char *name; + LVM_ControlParams_t *params; +}; + +struct nxp_eap_preset_params nxp_eap_effect_presets[] = { + { + .name = "AllEffectsOff", + .params = (LVM_ControlParams_t *)&ControlParamSet_allEffectOff, + }, + { + .name = "AutoVolumeLeveler", + .params = (LVM_ControlParams_t *)&ControlParamSet_autoVolumeLeveler, + }, + { + .name = "ConcertSound", + .params = (LVM_ControlParams_t *)&ControlParamSet_concertSound, + }, + { + .name = "LoudnessMaximiser", + .params = (LVM_ControlParams_t *)&ControlParamSet_loudnessMaximiser, + }, + { + .name = "MusicEnhancer", + .params = (LVM_ControlParams_t *)&ControlParamSet_musicEnhancerRmsLimiter, + }, + { + .name = "VoiceEnhancer", + .params = (LVM_ControlParams_t *)&ControlParamSet_voiceEnhancer, + } +}; + +static int nxp_eap_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct nxp_eap_data *eap; + LVM_VersionInfo_st info; + LVM_ReturnStatus_en lvm_ret; + int ret = 0; + + LVM_GetVersionInfo(&info); + + tr_info(mod->dev, "NXP EAP library, platform: %s version:%s", + info.pPlatform, info.pVersionNumber); + + eap = mod_alloc(mod, sizeof(*eap)); + if (!eap) { + comp_err(dev, "failed to allocate module private data"); + return -ENOMEM; + } + + module_set_private_data(mod, eap); + + memcpy(&eap->inst_params, &InstParams_allEffectOff, sizeof(eap->inst_params)); + + lvm_ret = LVM_GetMemoryTable(LVM_NULL, &eap->mem_tab, &eap->inst_params); + if (lvm_ret != LVM_SUCCESS) { + comp_err(dev, "failed to get memory table %d", lvm_ret); + mod_free(mod, eap); + return -EINVAL; + } + + /* mark all pBaseAddress with NULL so that would be easier to implement cleanup */ + for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) + eap->mem_tab.Region[i].pBaseAddress = NULL; + + for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) { + eap->mem_tab.Region[i].pBaseAddress = mod_balloc(mod, eap->mem_tab.Region[i].Size); + if (!eap->mem_tab.Region[i].pBaseAddress) { + comp_err(dev, "failed to allocate memory for region %d", i); + ret = -ENOMEM; + goto free_mem; + } + } + + lvm_ret = LVM_GetInstanceHandle(&eap->instance, &eap->mem_tab, &eap->inst_params); + if (lvm_ret != LVM_SUCCESS) { + comp_err(dev, "failed to get instance handle err: %d", lvm_ret); + ret = -EINVAL; + goto free_mem; + } + + /* default parameters, no effects */ + memcpy(&eap->ctrl_params, &ControlParamSet_allEffectOff, sizeof(eap->ctrl_params)); + + return 0; + +free_mem: + for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) { + if (eap->mem_tab.Region[i].pBaseAddress) { + mod_free(mod, eap->mem_tab.Region[i].pBaseAddress); + eap->mem_tab.Region[i].pBaseAddress = NULL; + } + } + mod_free(mod, eap); + return ret; +} + +static int nxp_eap_free(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct nxp_eap_data *eap = module_get_private_data(mod); + + comp_dbg(dev, "entry"); + + for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) { + if (eap->mem_tab.Region[i].pBaseAddress) { + mod_free(mod, eap->mem_tab.Region[i].pBaseAddress); + eap->mem_tab.Region[i].pBaseAddress = NULL; + } + } + mod_free(mod, eap); + + return 0; +} + +static int nxp_eap_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_dev *dev = mod->dev; + struct module_data *md = &mod->priv; + struct nxp_eap_data *eap = module_get_private_data(mod); + struct comp_buffer *source = comp_dev_get_first_data_producer(dev); + const struct audio_stream *stream; + + comp_dbg(dev, "entry"); + + stream = &source->stream; + eap->sample_rate = audio_stream_get_rate(stream); + eap->channels = audio_stream_get_channels(stream); + eap->frame_bytes = audio_stream_frame_bytes(stream); + eap->audio_time_ms = 0; + + /* total bytes needed to be in the input buffer to be processed + * by the EAP library + */ + eap->buffer_bytes = NXP_EAP_DEFAULT_MAX_BLOCK_SIZE; + + md->mpd.in_buff = mod_balloc_align(mod, eap->buffer_bytes, 32); + if (!md->mpd.in_buff) + return -ENOMEM; + + md->mpd.out_buff = mod_balloc_align(mod, eap->buffer_bytes, 32); + if (!md->mpd.out_buff) { + mod_free(mod, md->mpd.in_buff); + return -ENOMEM; + } + + md->mpd.in_buff_size = eap->buffer_bytes; + md->mpd.out_buff_size = eap->buffer_bytes; + + return 0; +} + +static int nxp_eap_reset(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *md = &mod->priv; + + comp_dbg(dev, "entry"); + + if (md->mpd.in_buff) { + mod_free(mod, md->mpd.in_buff); + md->mpd.in_buff = NULL; + md->mpd.in_buff_size = 0; + } + + if (md->mpd.out_buff) { + mod_free(mod, md->mpd.out_buff); + md->mpd.out_buff = NULL; + md->mpd.out_buff_size = 0; + } + + return 0; +} + +static int nxp_eap_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 comp_dev *dev = mod->dev; + struct module_data *eap = &mod->priv; + struct nxp_eap_data *eap_data = module_get_private_data(mod); + LVM_INT16 *buffer_table[2]; + LVM_ReturnStatus_en ret; + + comp_dbg(dev, "entry"); + + /* we need to input buffer to be completely full to be able to process it */ + if (input_buffers[0].size < eap->mpd.in_buff_size) + return -ENODATA; + + memcpy_s(eap->mpd.in_buff, eap->mpd.in_buff_size, + (uint8_t *)input_buffers[0].data + input_buffers[0].consumed, + eap->mpd.in_buff_size); + eap->mpd.avail = eap->mpd.in_buff_size; + + buffer_table[0] = eap->mpd.out_buff; + buffer_table[1] = LVM_NULL; + + eap_data->audio_time_ms += eap->mpd.avail / (eap_data->sample_rate / 1000); + + ret = LVM_Process(eap_data->instance, (LVM_INT16 *)eap->mpd.in_buff, + (LVM_INT16 **)buffer_table, eap->mpd.avail / eap_data->frame_bytes, + eap_data->audio_time_ms); + if (ret != LVM_SUCCESS) { + comp_err(dev, "failed with error %d", ret); + return -EIO; + } + + eap->mpd.produced = eap->mpd.in_buff_size; + eap->mpd.consumed = eap->mpd.in_buff_size; + + input_buffers[0].consumed = eap->mpd.consumed; + + /* copy produced samples to output buffer */ + memcpy_s(output_buffers[0].data, eap->mpd.produced, eap->mpd.out_buff, eap->mpd.produced); + output_buffers[0].size = eap->mpd.produced; + + return 0; +} + +static int nxp_eap_cmd_set_value(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata) +{ + int index; + LVM_ReturnStatus_en ret; + struct comp_dev *dev = mod->dev; + struct nxp_eap_data *eap = module_get_private_data(mod); + + index = cdata->chanv[0].value; + + if (index >= ARRAY_SIZE(nxp_eap_effect_presets)) { + comp_info(dev, "invalid index (%d), config not changed", + index); + } else { + memcpy(&eap->ctrl_params, nxp_eap_effect_presets[index].params, + sizeof(eap->ctrl_params)); + comp_info(dev, "New config set to %s", nxp_eap_effect_presets[index].name); + } + + ret = LVM_SetControlParameters(eap->instance, &eap->ctrl_params); + if (ret != LVM_SUCCESS) { + comp_err(dev, "LVM_SetControlParameters failed with error %d", ret); + return -EIO; + } + return 0; +} + +static int nxp_eap_set_config(struct processing_module *mod, uint32_t param_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 sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + comp_dbg(dev, "entry"); + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) + return nxp_eap_cmd_set_value(mod, cdata); + + comp_err(dev, "nxp_set_config() binary config not supported"); + return -EINVAL; +} + +static int nxp_eap_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + return 0; +} + +static const struct module_interface nxp_eap_interface = { + .init = nxp_eap_init, + .prepare = nxp_eap_prepare, + .process_raw_data = nxp_eap_process, + .set_configuration = nxp_eap_set_config, + .get_configuration = nxp_eap_get_config, + .reset = nxp_eap_reset, + .free = nxp_eap_free, +}; + +DECLARE_MODULE_ADAPTER(nxp_eap_interface, nxp_eap_uuid, nxp_eap_tr); +SOF_MODULE_INIT(nxp_eap, sys_comp_module_nxp_eap_interface_init); diff --git a/src/audio/nxp/eap_stub.c b/src/audio/nxp/eap_stub.c new file mode 100644 index 000000000000..568bb9745b17 --- /dev/null +++ b/src/audio/nxp/eap_stub.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2025 NXP + + +#include <sof/audio/nxp/eap/eap_lib_defines.h> +#include <nxp/eap/EAP_Includes/EAP16.h> + +LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st *pVersion) +{ + return LVM_SUCCESS; +} + +LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t *phInstance, + LVM_MemTab_t *pMemoryTable, + LVM_InstParams_t *pInstParams) +{ + return LVM_SUCCESS; +}; + +LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t hInstance, LVM_MemTab_t *pMemoryTable, + LVM_InstParams_t *pInstParams) +{ + return LVM_SUCCESS; +} + +LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance, const LVM_INT16 *pInData, + LVM_INT16 **pOutData, LVM_UINT16 NumSamples, + LVM_UINT32 AudioTime) +{ + return LVM_SUCCESS; +} + +LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance, LVM_ControlParams_t *pParams) +{ + return LVM_SUCCESS; +} diff --git a/src/audio/pcm_converter/CMakeLists.txt b/src/audio/pcm_converter/CMakeLists.txt index 8100bec72125..4f09a5a779c7 100644 --- a/src/audio/pcm_converter/CMakeLists.txt +++ b/src/audio/pcm_converter/CMakeLists.txt @@ -1,3 +1,10 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof pcm_converter_generic.c pcm_converter_hifi3.c) +add_local_sources(sof + pcm_converter.c + pcm_converter_generic.c + pcm_converter_hifi3.c) + +if(CONFIG_PCM_REMAPPING_CONVERTERS) + add_local_sources(sof pcm_remap.c) +endif() diff --git a/src/audio/pcm_converter/README.md b/src/audio/pcm_converter/README.md new file mode 100644 index 000000000000..d9fd8152383a --- /dev/null +++ b/src/audio/pcm_converter/README.md @@ -0,0 +1,11 @@ +# PCM Format Converter Architecture + +This directory provides PCM format conversion. + +## Overview + +Handles conversions like 16-bit to 24-bit, interleaved to non-interleaved, and other basic PCM layout translations. + +## Configuration and Scripts + +- **CMakeLists.txt**: Organizes standard and highly performant HIFI implementations (`pcm_converter.c`, `pcm_converter_generic.c`, `pcm_converter_hifi3.c`). Includes optional support for `pcm_remap.c` dependent on the `CONFIG_PCM_REMAPPING_CONVERTERS` flag. diff --git a/src/audio/pcm_converter/pcm_converter.c b/src/audio/pcm_converter/pcm_converter.c new file mode 100644 index 000000000000..b489cc6e664b --- /dev/null +++ b/src/audio/pcm_converter/pcm_converter.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +/** + * \file audio/pcm_converter/pcm_converter.c + * \brief PCM converter common functions + * \authors Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#include <sof/compiler_attributes.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/pcm_converter.h> +#include <rtos/panic.h> + +int pcm_convert_as_linear(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, + uint32_t samples, pcm_converter_lin_func converter) +{ + const int s_size_in = audio_stream_sample_bytes(source); + 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, audio_stream_get_rptr(source), ioffset, + s_size_in); + char *w_ptr = audio_stream_get_frag(sink, audio_stream_get_wptr(sink), ooffset, + s_size_out); + int i = 0; + int chunk; + int N1, N2; + + /* assert enough avail/free samples in source and sink buffer */ + if (audio_stream_get_avail_samples(source) < samples + ioffset) + return -EINVAL; + if (audio_stream_get_free_samples(sink) < samples + ooffset) + return -EINVAL; + + while (i < samples) { + /* calculate chunk size */ + /* "">> log2_s_size" is equal "/ s_size" here */ + N1 = audio_stream_bytes_without_wrap(source, r_ptr) >> + log2_s_size_in; + N2 = audio_stream_bytes_without_wrap(sink, w_ptr) >> + log2_s_size_out; + chunk = MIN(N1, N2); + chunk = MIN(chunk, samples - i); + + /* run conversion on linear memory region */ + converter(r_ptr, w_ptr, chunk); + + /* move pointers */ + r_ptr = audio_stream_wrap(source, r_ptr + chunk * s_size_in); + w_ptr = audio_stream_wrap(sink, w_ptr + chunk * s_size_out); + i += chunk; + } + + return samples; +} + +int just_copy(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return audio_stream_copy(source, ioffset, sink, ooffset, samples); +} diff --git a/src/audio/pcm_converter/pcm_converter_generic.c b/src/audio/pcm_converter/pcm_converter_generic.c index 6fc06a4dc925..fe96e6d1f124 100644 --- a/src/audio/pcm_converter/pcm_converter_generic.c +++ b/src/audio/pcm_converter/pcm_converter_generic.c @@ -1,165 +1,1106 @@ // SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ /** * \file audio/pcm_converter/pcm_converter_generic.c * \brief PCM converter generic processing implementation * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> + * \authors Karol Trzcinski <karolx.trzcinski@linux.intel.com> + * \authors Adrian Warecki <adrian.warecki@intel.com> */ #include <sof/audio/pcm_converter.h> +#include <sof/audio/audio_stream.h> #ifdef PCM_CONVERTER_GENERIC #include <sof/audio/buffer.h> #include <sof/audio/format.h> +#include <sof/math/a_law.h> +#include <sof/math/mu_law.h> +#include <rtos/bit.h> #include <sof/common.h> +#include <sof/compiler_attributes.h> #include <ipc/stream.h> -#include <config.h> + #include <stddef.h> #include <stdint.h> -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE +#define BYTES_TO_U8_SAMPLES 0 +#define BYTES_TO_S16_SAMPLES 1 +#define BYTES_TO_S32_SAMPLES 2 + +#if CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE +static int pcm_convert_u8_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + uint8_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + uint32_t processed; + uint32_t nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_U8_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = (INT8_MIN + *src) << 24; + src++; + dst++; + } + } + + return samples; +} + +static int pcm_convert_s32_to_u8(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + uint8_t *dst = audio_stream_get_wptr(sink); + uint32_t processed; + uint32_t nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_U8_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int8(Q_SHIFT_RND(*src, 24, 0)) - INT8_MIN; + src++; + dst++; + } + } + + return samples; +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ -static void pcm_convert_s16_to_s24(const struct audio_stream *source, +#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE +static int pcm_convert_alaw_to_s32(const struct audio_stream *source, uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - uint32_t buff_frag = 0; - int16_t *src; - int32_t *dst; - uint32_t i; + const uint8_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + uint32_t processed; + uint32_t nmax, i, n; - for (i = 0; i < samples; i++) { - src = audio_stream_read_frag_s16(source, buff_frag + ioffset); - dst = audio_stream_write_frag_s32(sink, buff_frag + ooffset); - *dst = *src << 8; - buff_frag++; + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, (void *)src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_U8_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sofm_a_law_decode(*src) << 16; + src++; + dst++; + } } + + return samples; } -static void pcm_convert_s24_to_s16(const struct audio_stream *source, +static int pcm_convert_s32_to_alaw(const struct audio_stream *source, uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - uint32_t buff_frag = 0; - int32_t *src; - int16_t *dst; - uint32_t i; + const int32_t *src = audio_stream_get_rptr(source); + uint8_t *dst = audio_stream_get_wptr(sink); + uint32_t processed; + uint32_t nmax, i, n; - for (i = 0; i < samples; i++) { - src = audio_stream_read_frag_s32(source, buff_frag + ioffset); - dst = audio_stream_write_frag_s16(sink, buff_frag + ooffset); - *dst = sat_int16(Q_SHIFT_RND(sign_extend_s24(*src), 23, 15)); - buff_frag++; + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, (void *)src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_U8_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sofm_a_law_encode(*src >> 16); + src++; + dst++; + } } + + return samples; } +#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_MU_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE +static int pcm_convert_mulaw_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + const uint8_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + uint32_t processed; + uint32_t nmax, i, n; -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, (void *)src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_U8_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sofm_mu_law_decode(*src) << 16; + src++; + dst++; + } + } -static void pcm_convert_s16_to_s32(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) + return samples; +} + +static int pcm_convert_s32_to_mulaw(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - uint32_t buff_frag = 0; - int16_t *src; - int32_t *dst; - uint32_t i; + const int32_t *src = audio_stream_get_rptr(source); + uint8_t *dst = audio_stream_get_wptr(sink); + uint32_t processed; + uint32_t nmax, i, n; - for (i = 0; i < samples; i++) { - src = audio_stream_read_frag_s16(source, buff_frag + ioffset); - dst = audio_stream_write_frag_s32(sink, buff_frag + ooffset); - *dst = *src << 16; - buff_frag++; + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, (void *)src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_U8_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sofm_mu_law_encode(*src >> 16); + src++; + dst++; + } } + + return samples; } +#endif /* CONFIG_PCM_CONVERTER_FORMAT_MU_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ -static void pcm_convert_s32_to_s16(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +#if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE + +static int pcm_convert_s16_to_s24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - uint32_t buff_frag = 0; - int32_t *src; - int16_t *dst; - uint32_t i; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; - for (i = 0; i < samples; i++) { - src = audio_stream_read_frag_s32(source, buff_frag + ioffset); - dst = audio_stream_write_frag_s16(sink, buff_frag + ooffset); - *dst = sat_int16(Q_SHIFT_RND(*src, 31, 15)); - buff_frag++; + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src << 8; + src++; + dst++; + } } + + return samples; } -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ +static int pcm_convert_s24_to_s16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int16(Q_SHIFT_RND(sign_extend_s24(*src), 23, 15)); + src++; + dst++; + } + } -static void pcm_convert_s24_to_s32(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) + return samples; +} + +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ + +#if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE + +static int pcm_convert_s16_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - uint32_t buff_frag = 0; - int32_t *src; - int32_t *dst; - uint32_t i; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; - for (i = 0; i < samples; i++) { - src = audio_stream_read_frag_s32(source, buff_frag + ioffset); - dst = audio_stream_write_frag_s32(sink, buff_frag + ooffset); - *dst = *src << 8; - buff_frag++; + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src << 16; + src++; + dst++; + } } + + return samples; } -static void pcm_convert_s32_to_s24(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static int pcm_convert_s32_to_s16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - uint32_t buff_frag = 0; - int32_t *src; - int32_t *dst; - uint32_t i; + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; - for (i = 0; i < samples; i++) { - src = audio_stream_read_frag_s32(source, buff_frag + ioffset); - dst = audio_stream_write_frag_s32(sink, buff_frag + ooffset); - *dst = sat_int24(Q_SHIFT_RND(*src, 31, 23)); - buff_frag++; + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int16(Q_SHIFT_RND(*src, 31, 15)); + src++; + dst++; + } } + + return samples; +} + +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ + +#if CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE + +static int pcm_convert_s24_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src << 8; + src++; + dst++; + } + } + + return samples; +} + +static int pcm_convert_s32_to_s24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int24(Q_SHIFT_RND(*src, 31, 23)); + src++; + dst++; + } + } + + return samples; +} + +static int pcm_convert_s32_to_s24_be(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_samples_without_wrap_s32(source, src); + n = MIN(n, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, dst); + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int24(Q_SHIFT_RND(*src, 31, 23)) << 8; + src++; + dst++; + } + } + + return samples; +} + +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ + +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && (CONFIG_PCM_CONVERTER_FORMAT_S16LE || CONFIG_PCM_CONVERTER_FORMAT_S24LE || CONFIG_PCM_CONVERTER_FORMAT_S32LE) +/* + * IEEE 754 binary32 float format: + * + * S|EEEEEEEE|MMMMMMMMMMMMMMMMMMMMMMM| + * 31|30 23|22 0| + * + * S - sign bit + * E - exponent number, base 2 + * M - mantissa, unsigned Q1.22 value where integer portion is always set +*/ + +/** + * shift d value left (for positive a) or right (for negative a) + * and take care about overflows + */ +static inline int32_t _pcm_shift(int32_t d, int32_t a) +{ + int64_t dd = d; + + if (a > 32) + a = 32; + else if (a < -32) + a = -32; + + dd = a >= 0 ? dd << a : dd >> -a; + if (dd > INT32_MAX) + dd = INT32_MAX; + + return (int32_t)dd; +} + +/** + * Calculate absolute value of s32 number without using code branching. + * XOR number with sign bit (stretched in 32 bits) (+1 for for negative numbers) + */ +#define PCM_ABS32(x) (((x) ^ ((int32_t)(x) >> 31)) + ((uint32_t)(x) >> 31)) + +/** + * \brief convert float number to fixed point + * + * Do not relay on compiler built-in float<=>int conversion in generic + * implementation, because "floating types float, double, and long double whose + * radix is not specified by the C standard but is usually two" + * ~https://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html + * + * \param src integer number to convert, it is int32_t to omit software float + * operations library inclusion by compiler, when in whole topology + * only external component needs float input. + * \param pow additional exponent component, + * number of fractional bits in fixed point value. + * Use '0' for normal conversion to integers + * \return (int32_t)src * 2**pow + */ +static int32_t _pcm_convert_f_to_i(int32_t src, int32_t pow) +{ + int32_t exponent, mantissa, dst; + + exponent = (src >> 23); + exponent = (exponent & 0xFF) + pow - 127; /* exponential */ + mantissa = BIT(23) | (MASK(22, 0) & src); /* mantisa + 1.0 [Q9.22] */ + /* calculate power */ + dst = _pcm_shift(mantissa, exponent - 23); + /* add 0.5 to round correctly but assert it doesn't lead to overflow */ + if (exponent - 22 < 9 || (src & BIT(31)) == BIT(31)) + dst += _pcm_shift(mantissa, exponent - 22) & 1; + /* copy sign to dst */ + dst = (dst ^ (src >> 31)) + (int)((unsigned int)src >> 31); + + return dst; +} + +/** + * \brief convert fixed number to float + * + * Do not relay on compiler built-in float<=>int conversion in generic + * implementation, because "floating types float, double, and long double whose + * radix is not specified by the C standard but is usually two" + * ~https://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html + * + * \param src integer number to convert + * \param pow additional exponent component + * number of fractional bits in fixed point value. + * Use '0' for normal conversion to float + * \return (float)(src * 2**pow), return type is int32_t to omit software float + * operations library inclusion by compiler, when in whole topology + * only external component needs float input + */ +static int32_t _pcm_convert_i_to_f(int32_t src, int32_t pow) +{ + int sign, mantissa, exponent, dst, abs_clz; + + if (src == 0) + return 0; + + sign = src & BIT(31); + abs_clz = clz(PCM_ABS32(src)); + exponent = (127 + 31 - abs_clz - pow) & 0xFF; + mantissa = PCM_ABS32(src); + mantissa = _pcm_shift(mantissa, 23 - 31 + abs_clz) & MASK(22, 0); + dst = sign | (exponent << 23) | mantissa; + + return dst; +} + +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && (CONFIG_PCM_CONVERTER_FORMAT_S16LE || CONFIG_PCM_CONVERTER_FORMAT_S24LE || CONFIG_PCM_CONVERTER_FORMAT_S32LE) */ + +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE +static void pcm_convert_s16_to_f_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const int16_t *src = psrc; + int32_t *dst = pdst; /* float */ + int i; + + /* s16 is in format Q1.15 so during */ + /* conversion subtract 15 from exponent */ + for (i = 0; i < samples; i++) + dst[i] = _pcm_convert_i_to_f(src[i], 15); +} + +static void pcm_convert_f_to_s16_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const int32_t *src = psrc; /* float */ + int16_t *dst = pdst; + int i; + + /* s16 is in format Q1.15 so during */ + /* conversion add 15 from exponent */ + for (i = 0; i < samples; i++) + dst[i] = sat_int16(_pcm_convert_f_to_i(src[i], 15)); +} + +static int pcm_convert_s16_to_f(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_s16_to_f_lin); +} + +static int pcm_convert_f_to_s16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_f_to_s16_lin); +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ + +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE +static void pcm_convert_s24_to_f_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const int32_t *src = psrc; + int32_t *dst = pdst; /* float */ + int i; + + /* s24 is in format Q1.23 so during */ + /* conversion subtract 23 to exponent */ + for (i = 0; i < samples; i++) + dst[i] = _pcm_convert_i_to_f(sign_extend_s24(src[i]), 23); +} + +static void pcm_convert_f_to_s24_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const int32_t *src = psrc; /* float */ + int32_t *dst = pdst; + int i; + + /* s24 is in format Q1.23 so during */ + /* conversion add 23 to exponent */ + for (i = 0; i < samples; i++) + dst[i] = sat_int24(_pcm_convert_f_to_i(src[i], 23)); +} + +static int pcm_convert_s24_to_f(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_s24_to_f_lin); +} + +static int pcm_convert_f_to_s24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_f_to_s24_lin); +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ + +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE +static void pcm_convert_s32_to_f_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const int32_t *src = psrc; + int32_t *dst = pdst; /* float */ + int i; + + /* s32 is in format Q1.31 so during */ + /* conversion subtract 31 to exponent */ + for (i = 0; i < samples; i++) + dst[i] = _pcm_convert_i_to_f(src[i], 31); } -#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ +static void pcm_convert_f_to_s32_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const int32_t *src = psrc; /* float */ + int32_t *dst = pdst; + int i; + + /* s32 is in format Q1.31 so during */ + /* conversion add 31 to exponent */ + for (i = 0; i < samples; i++) + dst[i] = _pcm_convert_f_to_i(src[i], 31); +} + +static int pcm_convert_s32_to_f(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_s32_to_f_lin); +} + +static int pcm_convert_f_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_f_to_s32_lin); +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ const struct pcm_func_map pcm_func_map[] = { -#if CONFIG_FORMAT_S16LE - { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, audio_stream_copy_s16 }, -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, audio_stream_copy_s32 }, -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, audio_stream_copy_s32 }, -#endif /* CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE +#if CONFIG_PCM_CONVERTER_FORMAT_U8 + { SOF_IPC_FRAME_U8, SOF_IPC_FRAME_U8, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 */ +#if CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_U8, SOF_IPC_FRAME_S32_LE, pcm_convert_u8_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_U8, pcm_convert_s32_to_u8 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW + { SOF_IPC_FRAME_A_LAW, SOF_IPC_FRAME_A_LAW, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW */ +#if CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_A_LAW, SOF_IPC_FRAME_S32_LE, pcm_convert_alaw_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_A_LAW, pcm_convert_s32_to_alaw }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_MU_LAW + { SOF_IPC_FRAME_MU_LAW, SOF_IPC_FRAME_MU_LAW, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_MU_LAW */ +#if CONFIG_PCM_CONVERTER_FORMAT_MU_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_MU_LAW, SOF_IPC_FRAME_S32_LE, pcm_convert_mulaw_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_MU_LAW, pcm_convert_s32_to_mulaw }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_A_LAW && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24_3LE + { SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_3LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24_3LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, pcm_convert_s16_to_s24 }, { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, pcm_convert_s24_to_s16 }, -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, pcm_convert_s16_to_s32 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, pcm_convert_s32_to_s16 }, -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, pcm_convert_s24_to_s32 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, pcm_convert_s32_to_s24 }, -#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_FLOAT, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_FLOAT, pcm_convert_s16_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S16_LE, pcm_convert_f_to_s16 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_FLOAT, pcm_convert_s24_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S24_4LE, pcm_convert_f_to_s24 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_FLOAT, pcm_convert_s32_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, pcm_convert_f_to_s32 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ }; const size_t pcm_func_count = ARRAY_SIZE(pcm_func_map); +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32 +static int pcm_convert_s16_c16_to_s16_c32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src; + src++; + dst++; + } + } + + return samples; +} + +static int pcm_convert_s16_c32_to_s16_c16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src & 0xffff; + src++; + dst++; + } + } + + return samples; +} +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32 +static int pcm_convert_s16_c32_to_s32_c32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src << 16; + src++; + dst++; + } + } + + return samples; +} + +static int pcm_convert_s32_c32_to_s16_c32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int16(Q_SHIFT_RND(*src, 31, 15)); + src++; + dst++; + } + } + + return samples; +} +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32 +static int pcm_convert_s16_c32_to_s24_c32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = *src << 8; + src++; + dst++; + } + } + + return samples; +} + +static int pcm_convert_s24_c32_to_s16_c32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + *dst = sat_int16(Q_SHIFT_RND(sign_extend_s24(*src & 0xffffff), 23, 15)); + src++; + dst++; + } + } + + return samples; +} +#endif + +#if CONFIG_PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32 +static int pcm_convert_s24_c24_to_s24_c32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + uint8_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset * 3; + dst += ooffset; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) / 3; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + for (i = 0; i < n; i += 1) { + *dst = (*(src + 2) << 24) | (*(src + 1) << 16) | (*(src + 0) << 8); + *dst >>= 8; + dst++; + src += 3; + } + } + + return samples; +} + +static int pcm_convert_s24_c32_to_s24_c24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + uint8_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i, n; + + src += ioffset; + dst += ooffset * 3; + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) / 3; + n = MIN(n, nmax); + for (i = 0; i < n; i += 1) { + *dst = *src & 0xFF; + dst++; + *dst = (*src >> 8) & 0xFF; + dst++; + *dst = (*src >> 16) & 0xFF; + dst++; + src++; + } + } + + return samples; +} + +/* 2x24bit samples are packed into 3x16bit samples for hda link dma */ +static int pcm_convert_s24_c32_to_s24_c24_link_gtw(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, + uint32_t chmap) +{ + int32_t *src = audio_stream_get_rptr(source); + uint16_t *dst = audio_stream_get_wptr(sink); + int processed; + int nmax, i = 0, n = 0; + + src += ioffset; + assert(ooffset == 0); + for (processed = 0; processed < samples; processed += n) { + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + n = samples - processed; + nmax = audio_stream_bytes_without_wrap(source, src) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dst) / 3; + n = MIN(n, nmax); + for (i = 0; i < n; i += 2) { + *dst = (*src >> 8) & 0xFFFF; + dst++; + *dst = (*src & 0xFF << 8) | ((*(src + 1) >> 16) & 0xFF); + dst++; + *dst = *(src + 1) & 0xFFFF; + dst++; + src += 2; + } + } + + /* odd n */ + if (i > n) { + *dst = (*src >> 8) & 0xFFFF; + dst++; + *dst = (*src & 0xFF << 8); + } + + return samples; +} + +#endif + +const struct pcm_func_vc_map pcm_func_vc_map[] = { +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32 + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s16_c16_to_s16_c32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s16_c32_to_s16_c16 }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32 + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + pcm_convert_s16_c32_to_s32_c32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s32_c32_to_s16_c32 }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32 + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, + pcm_convert_s16_c32_to_s24_c32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s24_c32_to_s16_c32 }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_U8, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_U8, + just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_U8 && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#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, + just_copy}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + 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, + pcm_convert_s32_to_s24 }, +#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, + pcm_convert_s16_to_s24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, + 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, SOF_IPC_FRAME_S24_4LE, + pcm_convert_s24_c24_to_s24_c32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_4LE, + pcm_convert_s24_c32_to_s24_c24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_3LE, + pcm_convert_s24_c32_to_s24_c24_link_gtw }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32 + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + just_copy }, +#endif + +#if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB && 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_MSB, pcm_convert_s24_to_s32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, pcm_convert_s32_to_s24}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE_MSB, just_copy}, +#endif + +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE_MSB, pcm_convert_s32_to_s24_be}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S32_LE, just_copy}, +#endif + +#if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB && 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_MSB, pcm_convert_s16_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S16_LE, + SOF_IPC_FRAME_S16_LE, pcm_convert_s32_to_s16 }, +#endif + +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_FLOAT, + SOF_IPC_FRAME_FLOAT, pcm_convert_s24_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, pcm_convert_f_to_s24 }, +#endif +}; + +const size_t pcm_func_vc_count = ARRAY_SIZE(pcm_func_vc_map); + #endif diff --git a/src/audio/pcm_converter/pcm_converter_hifi3.c b/src/audio/pcm_converter/pcm_converter_hifi3.c index 5a1df73b2f5b..2b6ca607415d 100644 --- a/src/audio/pcm_converter/pcm_converter_hifi3.c +++ b/src/audio/pcm_converter/pcm_converter_hifi3.c @@ -8,6 +8,7 @@ * \file audio/pcm_converter/pcm_converter_hifi3.c * \brief PCM converter HiFi3 processing implementation * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> + * \authors Karol Trzcinski <karolx.trzcinski@linux.intel.com> */ #include <sof/audio/pcm_converter.h> @@ -16,23 +17,18 @@ #include <sof/audio/buffer.h> #include <sof/common.h> +#include <sof/compiler_attributes.h> #include <ipc/stream.h> #include <xtensa/tie/xt_hifi3.h> -#include <config.h> + #include <stddef.h> #include <stdint.h> -/** - * \brief Sets buffer to be circular using HiFi3 functions. - * \param[in,out] buffer Circular buffer. - */ -static void pcm_converter_setup_circular(const struct audio_stream *source) -{ - AE_SETCBEGIN0(source->addr); - AE_SETCEND0(source->end_addr); -} +#if XCHAL_HAVE_FP +#include <xtensa/tie/xt_FP.h> +#endif -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE +#if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE /** * \brief HiFi3 enabled PCM conversion from 16 bit to 24 bit. @@ -40,84 +36,55 @@ static void pcm_converter_setup_circular(const struct audio_stream *source) * \param[in,out] sink Destination buffer. * \param[in] samples Number of samples to process. */ -static void pcm_convert_s16_to_s24(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static int pcm_convert_s16_to_s24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - ae_int16 *in = audio_stream_read_frag(source, ioffset, sizeof(int16_t)); - ae_int32 *out = audio_stream_write_frag(sink, ooffset, sizeof(int32_t)); ae_int16x4 sample = AE_ZERO16(); - ae_valign align_out = AE_ZALIGN64(); - ae_int16x4 *in16x4; - ae_int32x2 *out32x2; - int i = 0; - - /* nothing to do */ - if (!samples) - return; - - /* required alignment for AE_L16X4_XC */ - while (!IS_ALIGNED((uintptr_t)in, 8)) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load one 16 bit sample */ - AE_L16_XC(sample, in, sizeof(ae_int16)); - - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); - - /* shift right and store one 32 bit sample */ - AE_S32_L_XC(AE_SRAI32(AE_CVT32X2F16_32(sample), 8), out, - sizeof(ae_int32)); - - if (++i == samples) - return; + uint32_t nmax, i, n, m, left, left_samples; + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + 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); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 2; + left = n & 0x03; + inu = AE_LA64_PP(in); + + for (i = 0; i < m; i++) { + /* load four 16 bit samples */ + AE_LA16X4_IP(sample, inu, in); + /* shift right and store four 32 bit samples */ + AE_SA32X2_IP(AE_SRAI32(AE_CVT32X2F16_32(sample), 8), outu, out); + AE_SA32X2_IP(AE_SRAI32(AE_CVT32X2F16_10(sample), 8), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + /* load one 16 bit samples */ + AE_L16_IP(sample, (ae_int16 *)in, sizeof(ae_int16)); + + /* shift right and store one 32 bit sample */ + AE_S32_L_IP(AE_SRAI32(AE_CVT32X2F16_32(sample), 8), (ae_int32 *)out, + sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } - in16x4 = (ae_int16x4 *)in; - out32x2 = (ae_int32x2 *)out; - - /* main loop processes 4 samples at a time */ - while (samples >= 3 && i < samples - 3) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load four 16 bit samples */ - AE_L16X4_XC(sample, in16x4, sizeof(ae_int16x4)); - - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); - - /* shift right and store four 32 bit samples */ - AE_SA32X2_IC(AE_SRAI32(AE_CVT32X2F16_32(sample), 8), align_out, - out32x2); - AE_SA32X2_IC(AE_SRAI32(AE_CVT32X2F16_10(sample), 8), align_out, - out32x2); - - i += 4; - } - - /* flush align_out register to memory */ - AE_SA64POS_FC(align_out, out32x2); - - in = (ae_int16 *)in16x4; - out = (ae_int32 *)out32x2; - - while (i++ != samples) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load one 16 bit sample */ - AE_L16_XC(sample, in, sizeof(ae_int16)); - - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); - - /* shift right and store one 32 bit sample */ - AE_S32_L_XC(AE_SRAI32(AE_CVT32X2F16_32(sample), 8), out, - sizeof(ae_int32)); - } + return samples; } /** @@ -141,492 +108,1181 @@ static ae_int32x2 pcm_shift_s24_to_s16(ae_int32x2 sample) * \param[in,out] source Source buffer. * \param[in,out] sink Destination buffer. * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. */ -static void pcm_convert_s24_to_s16(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static int pcm_convert_s24_to_s16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - ae_int32x2 *in = audio_stream_read_frag(source, ioffset, - sizeof(int32_t)); - ae_int16x4 *out = audio_stream_write_frag(sink, ooffset, - sizeof(int16_t)); ae_int16x4 sample = AE_ZERO16(); ae_int32x2 sample_1 = AE_ZERO32(); ae_int32x2 sample_2 = AE_ZERO32(); - ae_valign align_out = AE_ZALIGN64(); - int i = 0; - int leftover; - - /* nothing to do */ - if (!samples) - return; - - /* required alignment for AE_L32X2_XC */ - if (!IS_ALIGNED((uintptr_t)in, 8)) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load one 32 bit sample */ - AE_L32_XC(sample_1, (ae_int32 *)in, sizeof(ae_int32)); - - /* shift and round */ - sample_1 = pcm_shift_s24_to_s16(sample_1); - sample = AE_MOVINT16X4_FROMINT32X2(sample_1); + uint32_t nmax, i, n, m, left, left_samples; + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + 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); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(n, nmax); + m = n >> 2; + left = n & 0x03; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load four 32 bit samples */ + AE_LA32X2_IP(sample_1, inu, in); + AE_LA32X2_IP(sample_2, inu, in); + + sample_1 = pcm_shift_s24_to_s16(sample_1); + sample_2 = pcm_shift_s24_to_s16(sample_2); + + /* store four 16 bit samples */ + sample = AE_CVT16X4(sample_1, sample_2); + AE_SA16X4_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + /* load one 32 bit sample */ + AE_L32_IP(sample_1, (ae_int32 *)in, sizeof(ae_int32)); + + /* shift and round */ + sample_1 = pcm_shift_s24_to_s16(sample_1); + sample = AE_MOVINT16X4_FROMINT32X2(sample_1); + + /* store one 16 bit sample */ + AE_S16_0_IP(AE_MOVAD16_0(sample), (ae_int16 *)out, + sizeof(ae_int16)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + return samples; +} - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ - /* store one 16 bit sample */ - AE_S16_0_XC(AE_MOVAD16_0(sample), (ae_int16 *)out, - sizeof(ae_int16)); +#if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE - samples--; +/** + * \brief HiFi3 enabled PCM conversion from 16 bit to 32 bit. + * \param[in,out] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_s16_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign outu = AE_ZALIGN64(); + + ae_int16x4 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 2; + left = n & 0x03; + + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load four 16 bit samples */ + AE_LA16X4_IP(sample, inu, in); + /* shift left and store four 32 bit samples */ + AE_SA32X2_IP(AE_CVT32X2F16_32(sample), outu, out); + AE_SA32X2_IP(AE_CVT32X2F16_10(sample), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + /* load one 16 bit samples */ + AE_L16_IP(sample, (ae_int16 *)in, sizeof(ae_int16)); + + /* store one 32 bit sample */ + AE_S32_L_IP(AE_CVT32X2F16_32(sample), (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } + return samples; +} - /* main loop processes 4 samples at a time */ - while (samples >= 3 && i < samples - 3) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load four 32 bit samples */ - AE_L32X2_XC(sample_1, in, sizeof(ae_int32x2)); - AE_L32X2_XC(sample_2, in, sizeof(ae_int32x2)); +/** + * \brief HiFi3 enabled PCM conversion from 32 bit to 16 bit. + * \param[in,out] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_s32_to_s16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + uint32_t nmax, i, n, m, left, left_samples; + ae_valign outu = AE_ZALIGN64(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int16x4 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(n, nmax); + m = n >> 2; + left = n & 0x3; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load four 32 bit samples */ + AE_LA32X2_IP(sample_1, inu, in); + AE_LA32X2_IP(sample_2, inu, in); + /* shift and round */ + sample = AE_ROUND16X4F32SSYM(sample_1, sample_2); + /* store four 16 bit samples */ + AE_SA16X4_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + /* load one 32 bit samples */ + AE_L32_IP(sample_1, (ae_int32 *)in, sizeof(ae_int32)); + /* shift and round */ + sample = AE_ROUND16X4F32SSYM(sample_1, sample_1); + /* store one 16 bit sample */ + AE_S16_0_IP(AE_MOVAD16_0(sample), (ae_int16 *)out, + sizeof(ae_int16)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + return samples; +} - /* shift and round */ - sample_1 = pcm_shift_s24_to_s16(sample_1); - sample_2 = pcm_shift_s24_to_s16(sample_2); +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ - /* store four 16 bit samples */ - sample = AE_CVT16X4(sample_1, sample_2); - AE_SA16X4_IC(sample, align_out, out); +#if CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE - i += 4; +/** + * \brief HiFi3 enabled PCM conversion from 24 bit to 32 bit. + * \param[in,out] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_s24_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + /* shift left and store two 32 bit samples */ + AE_SA32X2_IP(AE_SLAI32(sample, 8), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_S32_L_IP(AE_SLAI32(sample, 8), (ae_int32 *)out, + sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } - /* flush align_out register to memory */ - AE_SA64POS_FC(align_out, out); - - leftover = samples - i; + return samples; +} - while (leftover) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +/** + * \brief HiFi3 enabled PCM shift from 32 bit to 24 bit. + * \param[in] sample Input sample. + * \return Shifted sample. + */ +static ae_int32x2 pcm_shift_s32_to_s24(ae_int32x2 sample) +{ + /* shift with saturation and rounding */ + sample = AE_SRAI32R(sample, 8); + sample = AE_SLAI32S(sample, 8); + sample = AE_SRAI32(sample, 8); - /* load two 32 bit samples */ - AE_L32X2_XC(sample_1, in, sizeof(ae_int32x2)); + return sample; +} - /* shift and round */ - sample_1 = pcm_shift_s24_to_s16(sample_1); - sample = AE_MOVINT16X4_FROMINT32X2(sample_1); +/** + * \brief HiFi3 enabled PCM conversion from 32 bit to 24 bit. + * \param[in,out] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_s32_to_s24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + sample = pcm_shift_s32_to_s24(sample); + AE_SA32X2_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + /* load one 32 bit sample */ + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + /* shift right and store one 32 bit sample */ + sample = pcm_shift_s32_to_s24(sample); + AE_S32_L_IP(sample, (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + return samples; +} - /* store one 16 bit sample */ - AE_S16_0_XC(AE_MOVAD16_2(sample), (ae_int16 *)out, - sizeof(ae_int16)); +static int pcm_convert_s32_to_s24_be(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + /* shift with saturation and rounding */ + sample = AE_SRAA32RS(sample, 8); + sample = AE_SLAI32S(sample, 8); + AE_SA32X2_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + /* load one 32 bit sample */ + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + /* shift with saturation and rounding and store one 32 bit sample */ + sample = AE_SRAA32RS(sample, 8); + sample = AE_SLAI32S(sample, 8); + AE_S32_L_IP(sample, (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* no more samples to process */ - if (leftover == 1) - return; + return samples; +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ - /* store one 16 bit sample */ - AE_S16_0_XC(AE_MOVAD16_0(sample), (ae_int16 *)out, - sizeof(ae_int16)); +#if XCHAL_HAVE_FP - leftover -= 2; - } +static inline int _round_s(xtfloat x) +{ +#if defined(XT_ROUND_S) + return XT_ROUND_S(x, 15); +#else + return XT_TRUNC_S(XT_FIROUND_S(x), 15); +#endif } -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE /** - * \brief HiFi3 enabled PCM conversion from 16 bit to 32 bit. - * \param[in,out] source Source buffer. - * \param[in,out] sink Destination buffer. + * \brief HiFi3 enabled PCM conversion from 16 bit to IEEE-754 float. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. * \param[in] samples Number of samples to process. */ -static void pcm_convert_s16_to_s32(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static void pcm_convert_s16_to_f_lin(const void *psrc, void *pdst, + uint32_t samples) { - ae_int16 *in = audio_stream_read_frag(source, ioffset, - sizeof(int16_t)); - ae_int32 *out = audio_stream_write_frag(sink, ooffset, - sizeof(int32_t)); + const ae_int16 *in = psrc; + xtfloat *out = pdst; ae_int16x4 sample = AE_ZERO16(); - ae_valign align_out = AE_ZALIGN64(); - ae_int16x4 *in16x4; - ae_int32x2 *out32x2; + xtfloat fl; int i = 0; - /* nothing to do */ - if (!samples) - return; - - /* required alignment for AE_L16X4_XC */ - while (!IS_ALIGNED((uintptr_t)in, 8)) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - + while (i < samples) { /* load one 16 bit sample */ AE_L16_XC(sample, in, sizeof(ae_int16)); - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + /* run conversion */ + fl = XT_FLOAT_S((ae_int16)sample, 15); - /* store one 32 bit sample */ - AE_S32_L_XC(AE_CVT32X2F16_32(sample), out, sizeof(ae_int32)); + /* store one float sample */ + /* need address align to 32 bits */ + XT_xtfloat_storeip(fl, out, sizeof(fl)); - if (++i == samples) - return; + ++i; } +} - in16x4 = (ae_int16x4 *)in; - out32x2 = (ae_int32x2 *)out; - - /* main loop processes 4 samples at a time */ - while (samples >= 3 && i < samples - 3) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +/** + * \brief HiFi3 enabled PCM conversion from IEEE-754 float to 16 bit. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. + * \param[in] samples Number of samples to process. + */ +static void pcm_convert_f_to_s16_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const xtfloat *in = psrc; + ae_int16x4 *out = pdst; + xtfloat x; + int y; + int i = 0; - /* load four 16 bit samples */ - AE_L16X4_XC(sample, in16x4, sizeof(ae_int16x4)); + while (i < samples) { + /* load one 32 bit sample */ + XT_xtfloat_loadip(x, in, sizeof(x)); - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + /* shift and round */ + y = _round_s(x); - /* store two 32 bit samples */ - AE_SA32X2_IC(AE_CVT32X2F16_32(sample), align_out, out32x2); - AE_SA32X2_IC(AE_CVT32X2F16_10(sample), align_out, out32x2); + /* store one 16 bit sample */ + AE_S16_0_IP(y, (ae_int16 *)out, sizeof(ae_int16)); - i += 4; + ++i; } +} + +/** + * \brief HiFi3 enabled PCM conversion from 16 bit to IEEE-754 float. + * \param[in] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_s16_to_f(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_s16_to_f_lin); +} - /* flush align_out register to memory */ - AE_SA64POS_FC(align_out, out32x2); +/** + * \brief HiFi3 enabled PCM conversion from IEEE-754 float to 16 bit. + * \param[in] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_f_to_s16(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_f_to_s16_lin); +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ - in = (ae_int16 *)in16x4; - out = (ae_int32 *)out32x2; +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE - while (i++ != samples) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +/** + * \brief HiFi3 enabled PCM conversion from 24 bit to IEEE-754 float. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. + * \param[in] samples Number of samples to process. + */ +static void pcm_convert_s24_to_f_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const ae_int32 *in = psrc; + xtfloat *out = pdst; + ae_int32x2 sample = AE_ZERO32(); + xtfloat fl; + const xtfloat ratio = (xtfloat)(1.f / (1 << (23 - 15))); + int i = 0; - /* load one 16 bit sample */ - AE_L16_XC(sample, in, sizeof(ae_int16)); + while (i < samples) { + /* load one 24 bit sample */ + AE_L32_XC(sample, in, sizeof(*in)); - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + /* extend sign */ + sample = AE_SRAI32(AE_SLAI32(sample, 8), 8); + /* run conversion */ + fl = XT_FLOAT_S(sample, 15); + fl = fl * ratio; - /* store one 32 bit sample */ - AE_S32_L_XC(AE_CVT32X2F16_32(sample), out, sizeof(ae_int32)); + /* store one 32 bit float sample */ + /* need address align to 32 bits */ + XT_xtfloat_storeip(fl, out, sizeof(fl)); + + ++i; } } /** - * \brief HiFi3 enabled PCM conversion from 32 bit to 16 bit. - * \param[in,out] source Source buffer. - * \param[in,out] sink Destination buffer. + * \brief HiFi3 enabled PCM conversion from IEEE-754 float to 24 bit. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. * \param[in] samples Number of samples to process. */ -static void pcm_convert_s32_to_s16(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static void pcm_convert_f_to_s24_lin(const void *psrc, void *pdst, + uint32_t samples) { - ae_int32x2 *in = audio_stream_read_frag(source, ioffset, - sizeof(int32_t)); - ae_int16x4 *out = audio_stream_write_frag(sink, ooffset, - sizeof(int16_t)); - ae_int16x4 sample = AE_ZERO16(); - ae_int32x2 sample_1 = AE_ZERO32(); - ae_int32x2 sample_2 = AE_ZERO32(); - ae_valign align_out = AE_ZALIGN64(); + const xtfloat *in = psrc; + ae_int32 *out = pdst; + xtfloat x; + ae_int32x2 y1; int i = 0; - int leftover; - - /* nothing to do */ - if (!samples) - return; - - /* required alignment for AE_L32X2_XC */ - if (!IS_ALIGNED((uintptr_t)in, 8)) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); + const xtfloat ratio = (xtfloat)(1 << (23 - 15)); + while (i < samples) { /* load one 32 bit sample */ - AE_L32_XC(sample_1, (ae_int32 *)in, sizeof(ae_int32)); + /* need address align to 32 bits */ + XT_xtfloat_loadxp(x, in, sizeof(x)); /* shift and round */ - sample = AE_ROUND16X4F32SSYM(sample_1, sample_1); + x = x * ratio; + y1 = _round_s(x); - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + y1 = AE_SAT24S((ae_f32x2)y1); - /* store one 16 bit sample */ - AE_S16_0_XC(AE_MOVAD16_0(sample), (ae_int16 *)out, - sizeof(ae_int16)); + /* store one 24 bit sample in 32 bit memory size */ + AE_S32_L_IP(y1, (ae_int32 *)out, sizeof(*out)); - samples--; + ++i; } +} - /* main loop processes 4 samples at a time */ - while (samples >= 3 && i < samples - 3) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +/** + * \brief HiFi3 enabled PCM conversion from 24 bit to IEEE-754 float. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_s24_to_f(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_s24_to_f_lin); +} - /* load four 32 bit samples */ - AE_L32X2_XC(sample_1, in, sizeof(ae_int32x2)); - AE_L32X2_XC(sample_2, in, sizeof(ae_int32x2)); +/** + * \brief HiFi3 enabled PCM conversion from IEEE-754 float to 24 bit. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_f_to_s24(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_f_to_s24_lin); +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_24LE */ - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE - /* shift and round */ - sample = AE_ROUND16X4F32SSYM(sample_1, sample_2); +/** + * \brief HiFi3 enabled PCM conversion from 32 bit to IEEE-754 float. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. + * \param[in] samples Number of samples to process. + */ +static void pcm_convert_s32_to_f_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const ae_int32 *in = psrc; + xtfloat *out = pdst; + ae_int32x2 sample = AE_ZERO32(); + xtfloat fl; + const xtfloat ratio = (xtfloat)(1.f / (1ul << (31 - 15))); + int i = 0; - /* store four 16 bit samples */ - AE_SA16X4_IC(sample, align_out, out); + while (i < samples) { + /* load one 32 bit sample */ + AE_L32_XC(sample, in, sizeof(*in)); - i += 4; - } + /* run conversion */ + fl = XT_FLOAT_S(sample, 15); + fl = fl * ratio; - /* flush align_out register to memory */ - AE_SA64POS_FC(align_out, out); + /* store one 32 bit float sample */ + /* need address align to 32 bits */ + XT_xtfloat_storeip(fl, out, sizeof(fl)); - leftover = samples - i; + ++i; + } +} - while (leftover) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +/** + * \brief HiFi3 enabled PCM conversion from IEEE-754 float to 32 bit. + * \param[in] psrc source linear buffer. + * \param[out] pdst destination linear buffer. + * \param[in] samples Number of samples to process. + */ +static void pcm_convert_f_to_s32_lin(const void *psrc, void *pdst, + uint32_t samples) +{ + const xtfloat *in = psrc; + ae_int32 *out = pdst; + xtfloat x; + ae_int32x2 y1; + int i = 0; + const xtfloat ratio = (xtfloat)(1ul << (31 - 15)); - /* load two 32 bit samples */ - AE_L32X2_XC(sample_1, in, sizeof(ae_int32x2)); + while (i < samples) { + /* load one 32 bit sample */ + /* need address align to 32 bits */ + XT_xtfloat_loadxp(x, in, sizeof(x)); /* shift and round */ - sample = AE_ROUND16X4F32SSYM(sample_1, sample_1); - - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); - - /* store one 16 bit sample */ - AE_S16_0_XC(AE_MOVAD16_1(sample), (ae_int16 *)out, - sizeof(ae_int16)); - - /* no more samples to process */ - if (leftover == 1) - return; + x = x * ratio; + y1 = _round_s(x); - /* store one 16 bit sample */ - AE_S16_0_XC(AE_MOVAD16_0(sample), (ae_int16 *)out, - sizeof(ae_int16)); + /* store one 32 bit sample */ + AE_S32_L_IP(y1, (ae_int32 *)out, sizeof(*out)); - leftover -= 2; + ++i; } } -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE - /** - * \brief HiFi3 enabled PCM conversion from 24 bit to 32 bit. - * \param[in,out] source Source buffer. + * \brief HiFi3 enabled PCM conversion from 32 bit to IEEE-754 float. + * \param[in] source Source buffer. * \param[in,out] sink Destination buffer. * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. */ -static void pcm_convert_s24_to_s32(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static int pcm_convert_s32_to_f(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - ae_int32x2 *in = audio_stream_read_frag(source, ioffset, - sizeof(int32_t)); - ae_int32x2 *out = audio_stream_write_frag(sink, ooffset, - sizeof(int32_t)); - ae_int32x2 sample = AE_ZERO32(); - ae_valign align_out = AE_ZALIGN64(); - int i; - - /* nothing to do */ - if (!samples) - return; - - /* required alignment for AE_L32X2_XC */ - if (!IS_ALIGNED((uintptr_t)in, 8)) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load one 32 bit sample */ - AE_L32_XC(sample, (ae_int32 *)in, sizeof(ae_int32)); + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_s32_to_f_lin); +} - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); +/** + * \brief HiFi3 enabled PCM conversion from IEEE-754 float to 32 bit. + * \param[in] source Source buffer. + * \param[in,out] sink Destination buffer. + * \param[in] samples Number of samples to process. + * \return error code or number of processed samples. + */ +static int pcm_convert_f_to_s32(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + return pcm_convert_as_linear(source, ioffset, sink, ooffset, samples, + pcm_convert_f_to_s32_lin); +} +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_32LE */ +#endif /* XCHAL_HAVE_FP */ - /* shift left and store one 32 bit sample */ - AE_S32_L_XC(AE_SLAI32(sample, 8), (ae_int32 *)out, - sizeof(ae_int32)); +const struct pcm_func_map pcm_func_map[] = { +#if CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24_3LE + { SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_3LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24_3LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, pcm_convert_s16_to_s24 }, + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, pcm_convert_s24_to_s16 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, pcm_convert_s16_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, pcm_convert_s32_to_s16 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, pcm_convert_s24_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, pcm_convert_s32_to_s24 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ +#if XCHAL_HAVE_FP +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_FLOAT, just_copy }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_FLOAT, pcm_convert_s16_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S16_LE, pcm_convert_f_to_s16 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S16LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_FLOAT, pcm_convert_s24_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S24_4LE, pcm_convert_f_to_s24 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_FLOAT, pcm_convert_s32_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, pcm_convert_f_to_s32 }, +#endif /* CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ +#endif /* XCHAL_HAVE_FP */ +}; +const size_t pcm_func_count = ARRAY_SIZE(pcm_func_map); - samples--; +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32 +static int pcm_convert_s16_c16_to_s16_c32(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign outu = AE_ZALIGN64(); + + ae_int16x4 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 2; + left = n & 0x03; + + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load four 16 bit samples */ + AE_LA16X4_IP(sample, inu, in); + /* shift right and store four 32 bit samples */ + AE_SA32X2_IP(AE_SEXT32X2D16_32(sample), outu, out); + AE_SA32X2_IP(AE_SEXT32X2D16_10(sample), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + /* load one 16 bit samples */ + AE_L16_IP(sample, (ae_int16 *)in, sizeof(ae_int16)); + + /* store one 32 bit sample */ + AE_S32_L_IP(AE_SEXT32X2D16_32(sample), (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } + return samples; +} - /* main loop processes 2 samples at a time */ - for (i = 0; i < samples / 2; i++) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load two 32 bit samples */ - AE_L32X2_XC(sample, in, sizeof(ae_int32x2)); +static int pcm_convert_s16_c32_to_s16_c16(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + uint32_t nmax, i, n, m, left, left_samples; + ae_valign outu = AE_ZALIGN64(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int16x4 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(n, nmax); + m = n >> 2; + left = n & 0x3; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load four 32 bit samples */ + AE_LA32X2_IP(sample_1, inu, in); + AE_LA32X2_IP(sample_2, inu, in); + + /* truncate the LSB 16bit of four 32-bit signed elements*/ + sample = AE_CVT16X4(sample_1, sample_2); + + /* store four 16 bit samples */ + AE_SA16X4_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left samples that less than 4 + * one by one to avoid memory access overrun + */ + for (i = 0; i < left ; i++) { + /* load one 32 bit samples */ + AE_L32_IP(sample_1, (ae_int32 *)in, sizeof(ae_int32)); + /* shift and round */ + sample = AE_CVT16X4(sample_1, sample_1); + /* store one 16 bit sample */ + AE_S16_0_IP(AE_MOVAD16_0(sample), (ae_int16 *)out, sizeof(ae_int16)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + return samples; +} +#endif - /* shift left and store two 32 bit samples */ - AE_SA32X2_IC(AE_SLAI32(sample, 8), align_out, out); +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32 +static int pcm_convert_s16_c32_to_s32_c32(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + /* shift left and store two 32 bit samples */ + AE_SA32X2_IP(AE_SLAI32(sample, 16), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_S32_L_IP(AE_SLAI32(sample, 16), (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } - /* flush align_out register to memory */ - AE_SA64POS_FC(align_out, out); - - /* no more samples to process */ - if (!(samples % 2)) - return; + return samples; +} - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +static int pcm_convert_s32_c32_to_s16_c32(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + /* shift right and store two 32 bit samples */ + AE_SA32X2_IP(AE_SRAA32RS(sample, 16), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_S32_L_IP(AE_SRAA32RS(sample, 16), (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* load one 32 bit sample */ - AE_L32_XC(sample, (ae_int32 *)in, 0); + return samples; +} +#endif - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32 +static int pcm_convert_s16_c32_to_s24_c32(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + /* shift left and store two 32 bit samples */ + AE_SA32X2_IP(AE_SLAI32(sample, 8), outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + AE_S32_L_IP(AE_SLAI32(sample, 8), (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* shift left and store one 32 bit sample */ - AE_S32_L_XC(AE_SLAI32(sample, 8), (ae_int32 *)out, 0); + return samples; } -/** - * \brief HiFi3 enabled PCM shift from 32 bit to 24 bit. - * \param[in] sample Input sample. - * \return Shifted sample. - */ -static ae_int32x2 pcm_shift_s32_to_s24(ae_int32x2 sample) +static ae_int32x2 pcm_shift_s24_c32_to_s16(ae_int32x2 sample) { - /* shift with saturation and rounding */ - sample = AE_SRAI32R(sample, 8); + /*get the lsb 24bit,sign_extend_s24 */ + sample = AE_MOVINT24X2_FROMF32X2(sample); sample = AE_SLAI32S(sample, 8); - sample = AE_SRAI32(sample, 8); + sample = AE_SRAA32RS(sample, 8); + /* Q_SHIFT_RND */ + sample = AE_SRAA32RS(sample, 8); return sample; } -/** - * \brief HiFi3 enabled PCM conversion from 32 bit to 24 bit. - * \param[in,out] source Source buffer. - * \param[in,out] sink Destination buffer. - * \param[in] samples Number of samples to process. - */ -static void pcm_convert_s32_to_s24(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +static int pcm_convert_s24_c32_to_s16_c32(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) { - ae_int32x2 *in = audio_stream_read_frag(source, ioffset, - sizeof(int32_t)); - ae_int32x2 *out = audio_stream_write_frag(sink, ooffset, - sizeof(int32_t)); + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); - ae_valign align_out = AE_ZALIGN64(); - int i; - - /* nothing to do */ - if (!samples) - return; - - /* required alignment for AE_L32X2_XC */ - if (!IS_ALIGNED((uintptr_t)in, 8)) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); - - /* load one 32 bit sample */ - AE_L32_XC(sample, (ae_int32 *)in, sizeof(ae_int32)); - - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); - - /* shift right and store one 32 bit sample */ - sample = pcm_shift_s32_to_s24(sample); - AE_S32_L_XC(sample, (ae_int32 *)out, sizeof(ae_int32)); - - samples--; + uint32_t nmax, i, n, m, left_samples; + ae_valign outu = AE_ZALIGN64(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + sample = pcm_shift_s24_c32_to_s16(sample); + /* shift left and store two 32 bit samples */ + AE_SA32X2_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + sample = pcm_shift_s24_c32_to_s16(sample); + AE_S32_L_IP(sample, (ae_int32 *)out, sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } - /* main loop processes 2 samples at a time */ - for (i = 0; i < samples / 2; i++) { - /* set source as circular buffer */ - pcm_converter_setup_circular(source); + return samples; +} +#endif - /* load two 32 bit samples */ - AE_L32X2_XC(sample, in, sizeof(ae_int32x2)); +#if CONFIG_PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32 +static int pcm_convert_s24_c24_to_s24_c32(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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; + ae_valign outu = AE_ZALIGN64(); + ae_valign inu = AE_ZALIGN64(); + + ae_int24x2 *in = audio_stream_wrap(source, src + ioffset * 3); + ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_bytes_without_wrap(source, in) / 3; + n = MIN(left_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA24X2_IP(sample24, inu, in); + sample = AE_MOVINT32_FROMINT24X2(sample24); + /* shift left and store two 32 bit samples */ + AE_SA32X2_IP(sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_LA24_IP(sample24, inu, in); + sample = AE_MOVINT32_FROMINT24X2(sample24); + AE_S32_L_IP(sample, (ae_int32 *)out, + sizeof(ae_int32)); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); + return samples; +} - /* shift right and store two 32 bit samples */ - sample = pcm_shift_s32_to_s24(sample); - AE_SA32X2_IC(sample, align_out, out); +static int pcm_convert_s24_c32_to_s24_c24(const struct audio_stream *source, + uint32_t ioffset, + struct audio_stream *sink, + uint32_t ooffset, uint32_t samples, uint32_t chmap) +{ + 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; + ae_valign outu = AE_ZALIGN64(); + ae_valign inu = AE_ZALIGN64(); + + ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); + ae_int24x2 *out = audio_stream_wrap(sink, dst + ooffset * 3); + + for (left_samples = samples; left_samples; left_samples -= n) { + nmax = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(left_samples, nmax); + nmax = audio_stream_bytes_without_wrap(sink, out) / 3; + n = MIN(n, nmax); + m = n >> 1; + inu = AE_LA64_PP(in); + for (i = 0; i < m; i++) { + /* load 2 32 bit samples */ + AE_LA32X2_IP(sample, inu, in); + sample24 = AE_MOVINT24X2_FROMF32X2(sample); + AE_SA24X2_IP(sample24, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* process the left 1 sample to avoid memory access overrun */ + if (n & 0x01) { + AE_L32_IP(sample, (ae_int32 *)in, sizeof(ae_int32)); + sample24 = AE_MOVINT24X2_FROMF32X2(sample); + AE_SA24_IP(sample24, outu, out); + } + + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } - /* flush align_out register to memory */ - AE_SA64POS_FC(align_out, out); - - /* no more samples to process */ - if (!(samples % 2)) - return; + return samples; +} - /* set source as circular buffer */ - pcm_converter_setup_circular(source); +/* Haven't implement the pcm_convert_s24_c32_to_s24_c24_link_gtw since there are some + * errors in that function. Need to wait for the function to be corrected and verified. + */ +#endif - /* load one 32 bit sample */ - AE_L32_XC(sample, (ae_int32 *)in, 0); +const struct pcm_func_vc_map pcm_func_vc_map[] = { +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32 + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s16_c16_to_s16_c32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s16_c32_to_s16_c16 }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32 + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + pcm_convert_s16_c32_to_s32_c32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s32_c32_to_s16_c32 }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32 + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, + pcm_convert_s16_c32_to_s24_c32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + pcm_convert_s24_c32_to_s16_c32 }, +#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, + just_copy}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + 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, + pcm_convert_s32_to_s24 }, +#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, + pcm_convert_s16_to_s24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, + 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, SOF_IPC_FRAME_S24_4LE, + pcm_convert_s24_c24_to_s24_c32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_4LE, + pcm_convert_s24_c32_to_s24_c24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_3LE, + pcm_convert_s24_c32_to_s24_c24_link_gtw }, +#endif +#if CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32 + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, + just_copy }, +#endif - /* set sink as circular buffer */ - pcm_converter_setup_circular(sink); +#if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB && 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_MSB, pcm_convert_s24_to_s32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, pcm_convert_s32_to_s24}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE_MSB, just_copy}, +#endif - /* shift right and store one 32 bit sample */ - sample = pcm_shift_s32_to_s24(sample); - AE_S32_L_XC(sample, (ae_int32 *)out, 0); -} +#if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE_MSB, pcm_convert_s32_to_s24_be}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S32_LE, just_copy}, +#endif -#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB && 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_MSB, pcm_convert_s16_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S16_LE, + SOF_IPC_FRAME_S16_LE, pcm_convert_s32_to_s16 }, +#endif -const struct pcm_func_map pcm_func_map[] = { -#if CONFIG_FORMAT_S16LE - { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, audio_stream_copy_s16 }, -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, audio_stream_copy_s32 }, -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, audio_stream_copy_s32 }, -#endif /* CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, pcm_convert_s16_to_s24 }, - { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, pcm_convert_s24_to_s16 }, -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE - { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, pcm_convert_s16_to_s32 }, - { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, pcm_convert_s32_to_s16 }, -#endif /* CONFIG_FORMAT_S16LE && CONFIG_FORMAT_S32LE */ -#if CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE - { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, pcm_convert_s24_to_s32 }, - { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, pcm_convert_s32_to_s24 }, -#endif /* CONFIG_FORMAT_S24LE && CONFIG_FORMAT_S32LE */ +#if CONFIG_PCM_CONVERTER_FORMAT_FLOAT && CONFIG_PCM_CONVERTER_FORMAT_S24LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_FLOAT, + SOF_IPC_FRAME_FLOAT, pcm_convert_s24_to_f }, + { SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, pcm_convert_f_to_s24 }, +#endif }; -const size_t pcm_func_count = ARRAY_SIZE(pcm_func_map); +const size_t pcm_func_vc_count = ARRAY_SIZE(pcm_func_vc_map); #endif diff --git a/src/audio/pcm_converter/pcm_remap.c b/src/audio/pcm_converter/pcm_remap.c new file mode 100644 index 000000000000..9204b21ee8ab --- /dev/null +++ b/src/audio/pcm_converter/pcm_remap.c @@ -0,0 +1,477 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * (c) 2024 Intel Corporation. All rights reserved. + */ + +#include <sof/audio/pcm_converter.h> +#include <sof/audio/audio_stream.h> + +static void mute_channel_c16(struct audio_stream *stream, int channel, int frames) +{ + int num_channels = audio_stream_get_channels(stream); + int16_t *ptr = (int16_t *)audio_stream_get_wptr(stream) + channel; + + while (frames) { + int samples_wo_wrap, n, i; + + ptr = audio_stream_wrap(stream, ptr); + + samples_wo_wrap = audio_stream_samples_without_wrap_s16(stream, ptr); + n = SOF_DIV_ROUND_UP(samples_wo_wrap, num_channels); + n = MIN(n, frames); + + for (i = 0; i < n; i++) { + *ptr = 0; + ptr += num_channels; + } + + frames -= n; + } +} + +static void mute_channel_c32(struct audio_stream *stream, int channel, int frames) +{ + int num_channels = audio_stream_get_channels(stream); + int32_t *ptr = (int32_t *)audio_stream_get_wptr(stream) + channel; + + while (frames) { + int samples_wo_wrap, n, i; + + ptr = audio_stream_wrap(stream, ptr); + + samples_wo_wrap = audio_stream_samples_without_wrap_s32(stream, ptr); + n = SOF_DIV_ROUND_UP(samples_wo_wrap, num_channels); + n = MIN(n, frames); + + for (i = 0; i < n; i++) { + *ptr = 0; + ptr += num_channels; + } + + frames -= n; + } +} + +static int remap_c16(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + int src_channel, sink_channel; + int num_src_channels = audio_stream_get_channels(source); + int num_sink_channels = audio_stream_get_channels(sink); + int frames = source_samples / num_src_channels; + + for (sink_channel = 0; sink_channel < num_sink_channels; sink_channel++) { + int16_t *src, *dst; + int frames_left; + + src_channel = chmap & 0xf; + chmap >>= 4; + + if (src_channel == 0xf) { + mute_channel_c16(sink, sink_channel, frames); + continue; + } + + assert(src_channel < num_src_channels); + + src = (int16_t *)audio_stream_get_rptr(source) + src_channel; + dst = (int16_t *)audio_stream_get_wptr(sink) + sink_channel; + + frames_left = frames; + + while (frames_left) { + int src_samples_wo_wrap, dst_samples_wo_wrap; + int src_loops, dst_loops, n, i; + + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + + src_samples_wo_wrap = audio_stream_samples_without_wrap_s16(source, src); + src_loops = SOF_DIV_ROUND_UP(src_samples_wo_wrap, num_src_channels); + + dst_samples_wo_wrap = audio_stream_samples_without_wrap_s16(sink, dst); + dst_loops = SOF_DIV_ROUND_UP(dst_samples_wo_wrap, num_sink_channels); + + n = MIN(src_loops, dst_loops); + n = MIN(n, frames_left); + + for (i = 0; i < n; i++) { + *dst = *src; + src += num_src_channels; + dst += num_sink_channels; + } + + frames_left -= n; + } + } + + return source_samples; +} + +static inline int remap_c32_left_shift(const struct audio_stream *source, + struct audio_stream *sink, + uint32_t source_samples, uint32_t chmap, + int shift) +{ + int src_channel, sink_channel; + int num_src_channels = audio_stream_get_channels(source); + int num_sink_channels = audio_stream_get_channels(sink); + int frames = source_samples / num_src_channels; + + for (sink_channel = 0; sink_channel < num_sink_channels; sink_channel++) { + int32_t *src, *dst; + int frames_left; + + src_channel = chmap & 0xf; + chmap >>= 4; + + if (src_channel == 0xf) { + mute_channel_c32(sink, sink_channel, frames); + continue; + } + + assert(src_channel < num_src_channels); + + src = (int32_t *)audio_stream_get_rptr(source) + src_channel; + dst = (int32_t *)audio_stream_get_wptr(sink) + sink_channel; + + frames_left = frames; + + while (frames_left) { + int src_samples_wo_wrap, dst_samples_wo_wrap; + int src_loops, dst_loops, n, i; + + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + + src_samples_wo_wrap = audio_stream_samples_without_wrap_s32(source, src); + src_loops = SOF_DIV_ROUND_UP(src_samples_wo_wrap, num_src_channels); + + dst_samples_wo_wrap = audio_stream_samples_without_wrap_s32(sink, dst); + dst_loops = SOF_DIV_ROUND_UP(dst_samples_wo_wrap, num_sink_channels); + + n = MIN(src_loops, dst_loops); + n = MIN(n, frames_left); + + for (i = 0; i < n; i++) { + *dst = *src << shift; + src += num_src_channels; + dst += num_sink_channels; + } + + frames_left -= n; + } + } + + return source_samples; +} + +static inline int remap_c32_right_shift(const struct audio_stream *source, + struct audio_stream *sink, + uint32_t source_samples, uint32_t chmap, + int shift) +{ + int src_channel, sink_channel; + int num_src_channels = audio_stream_get_channels(source); + int num_sink_channels = audio_stream_get_channels(sink); + int frames = source_samples / num_src_channels; + + for (sink_channel = 0; sink_channel < num_sink_channels; sink_channel++) { + int32_t *src, *dst; + int frames_left; + + src_channel = chmap & 0xf; + chmap >>= 4; + + if (src_channel == 0xf) { + mute_channel_c32(sink, sink_channel, frames); + continue; + } + + assert(src_channel < num_src_channels); + + src = (int32_t *)audio_stream_get_rptr(source) + src_channel; + dst = (int32_t *)audio_stream_get_wptr(sink) + sink_channel; + + frames_left = frames; + + while (frames_left) { + int src_samples_wo_wrap, dst_samples_wo_wrap; + int src_loops, dst_loops, n, i; + + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + + src_samples_wo_wrap = audio_stream_samples_without_wrap_s32(source, src); + src_loops = SOF_DIV_ROUND_UP(src_samples_wo_wrap, num_src_channels); + + dst_samples_wo_wrap = audio_stream_samples_without_wrap_s32(sink, dst); + dst_loops = SOF_DIV_ROUND_UP(dst_samples_wo_wrap, num_sink_channels); + + n = MIN(src_loops, dst_loops); + n = MIN(n, frames_left); + + for (i = 0; i < n; i++) { + *dst = *src >> shift; + src += num_src_channels; + dst += num_sink_channels; + } + + frames_left -= n; + } + } + + return source_samples; +} + +static inline int remap_c16_to_c32(const struct audio_stream *source, + struct audio_stream *sink, + uint32_t source_samples, uint32_t chmap, + int shift) +{ + int src_channel, sink_channel; + int num_src_channels = audio_stream_get_channels(source); + int num_sink_channels = audio_stream_get_channels(sink); + int frames = source_samples / num_src_channels; + + for (sink_channel = 0; sink_channel < num_sink_channels; sink_channel++) { + int16_t *src; + int32_t *dst; + int frames_left; + + src_channel = chmap & 0xf; + chmap >>= 4; + + if (src_channel == 0xf) { + mute_channel_c32(sink, sink_channel, frames); + continue; + } + + assert(src_channel < num_src_channels); + + src = (int16_t *)audio_stream_get_rptr(source) + src_channel; + dst = (int32_t *)audio_stream_get_wptr(sink) + sink_channel; + + frames_left = frames; + + while (frames_left) { + int src_samples_wo_wrap, dst_samples_wo_wrap; + int src_loops, dst_loops, n, i; + + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + + src_samples_wo_wrap = audio_stream_samples_without_wrap_s16(source, src); + src_loops = SOF_DIV_ROUND_UP(src_samples_wo_wrap, num_src_channels); + + dst_samples_wo_wrap = audio_stream_samples_without_wrap_s32(sink, dst); + dst_loops = SOF_DIV_ROUND_UP(dst_samples_wo_wrap, num_sink_channels); + + n = MIN(src_loops, dst_loops); + n = MIN(n, frames_left); + + for (i = 0; i < n; i++) { + *dst = (int32_t)*src << shift; + src += num_src_channels; + dst += num_sink_channels; + } + + frames_left -= n; + } + } + + return source_samples; +} + +static inline int remap_c32_to_c16(const struct audio_stream *source, + struct audio_stream *sink, + uint32_t source_samples, uint32_t chmap, + int shift) +{ + int src_channel, sink_channel; + int num_src_channels = audio_stream_get_channels(source); + int num_sink_channels = audio_stream_get_channels(sink); + int frames = source_samples / num_src_channels; + + for (sink_channel = 0; sink_channel < num_sink_channels; sink_channel++) { + int32_t *src; + int16_t *dst; + int frames_left; + + src_channel = chmap & 0xf; + chmap >>= 4; + + if (src_channel == 0xf) { + mute_channel_c16(sink, sink_channel, frames); + continue; + } + + assert(src_channel < num_src_channels); + + src = (int32_t *)audio_stream_get_rptr(source) + src_channel; + dst = (int16_t *)audio_stream_get_wptr(sink) + sink_channel; + + frames_left = frames; + + while (frames_left) { + int src_samples_wo_wrap, dst_samples_wo_wrap; + int src_loops, dst_loops, n, i; + + src = audio_stream_wrap(source, src); + dst = audio_stream_wrap(sink, dst); + + src_samples_wo_wrap = audio_stream_samples_without_wrap_s32(source, src); + src_loops = SOF_DIV_ROUND_UP(src_samples_wo_wrap, num_src_channels); + + dst_samples_wo_wrap = audio_stream_samples_without_wrap_s16(sink, dst); + dst_loops = SOF_DIV_ROUND_UP(dst_samples_wo_wrap, num_sink_channels); + + n = MIN(src_loops, dst_loops); + n = MIN(n, frames_left); + + for (i = 0; i < n; i++) { + *dst = *src >> shift; + src += num_src_channels; + dst += num_sink_channels; + } + + frames_left -= n; + } + } + + return source_samples; +} + +static int remap_c32(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_left_shift(source, sink, source_samples, chmap, 0); +} + +static int remap_c32_to_c16_right_shift_16(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_to_c16(source, sink, source_samples, chmap, 16); +} + +static int remap_c16_to_c32_left_shift_16(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c16_to_c32(source, sink, source_samples, chmap, 16); +} + +static int remap_c32_to_c16_right_shift_8(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_to_c16(source, sink, source_samples, chmap, 8); +} + +static int remap_c16_to_c32_left_shift_8(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c16_to_c32(source, sink, source_samples, chmap, 8); +} + +static int remap_c32_right_shift_8(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_right_shift(source, sink, source_samples, chmap, 8); +} + +static int remap_c32_left_shift_8(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_left_shift(source, sink, source_samples, chmap, 8); +} + +static int remap_c32_right_shift_16(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_right_shift(source, sink, source_samples, chmap, 16); +} + +static int remap_c32_left_shift_16(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_left_shift(source, sink, source_samples, chmap, 16); +} + +static int remap_c32_to_c16_no_shift(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c32_to_c16(source, sink, source_samples, chmap, 0); +} + +static int remap_c16_to_c32_no_shift(const struct audio_stream *source, uint32_t dummy1, + struct audio_stream *sink, uint32_t dummy2, + uint32_t source_samples, uint32_t chmap) +{ + return remap_c16_to_c32(source, sink, source_samples, chmap, 0); +} + +/* Unfortunately, all these nice "if"s were commented out to suppress + * CI "defined but not used" warnings. + */ +const struct pcm_func_map pcm_remap_func_map[] = { +/* #if CONFIG_PCM_CONVERTER_FORMAT_S16LE */ + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, remap_c16}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24_4LE */ + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, remap_c16_to_c32_left_shift_8}, + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, remap_c32_to_c16_right_shift_8}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB */ + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE_MSB, remap_c16_to_c32_left_shift_16}, + { SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S16_LE, remap_c32_to_c16_right_shift_16}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, remap_c16_to_c32_left_shift_16}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, remap_c32_to_c16_right_shift_16}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S16LE && CONFIG_PCM_CONVERTER_FORMAT_S16_4LE */ + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_4LE, remap_c16_to_c32_no_shift}, + { SOF_IPC_FRAME_S16_4LE, SOF_IPC_FRAME_S16_LE, remap_c32_to_c16_no_shift}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE */ + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, remap_c32}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE && CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB */ + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE_MSB, remap_c32_left_shift_8}, + { SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S24_4LE, remap_c32_right_shift_8}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, remap_c32_left_shift_8}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, remap_c32_right_shift_8}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE && CONFIG_PCM_CONVERTER_FORMAT_S16_4LE */ + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_4LE, remap_c32_right_shift_8}, + { SOF_IPC_FRAME_S16_4LE, SOF_IPC_FRAME_S24_4LE, remap_c32_left_shift_8}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S24_4LE_MSB && CONFIG_PCM_CONVERTER_FORMAT_S32LE */ + { SOF_IPC_FRAME_S24_4LE_MSB, SOF_IPC_FRAME_S32_LE, remap_c32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE_MSB, remap_c32}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S32LE */ + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, remap_c32}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S16_4LE */ + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_4LE, remap_c32_right_shift_16}, + { SOF_IPC_FRAME_S16_4LE, SOF_IPC_FRAME_S32_LE, remap_c32_left_shift_16}, +/* #endif */ +/* #if CONFIG_PCM_CONVERTER_FORMAT_S16_4LE */ + { SOF_IPC_FRAME_S16_4LE, SOF_IPC_FRAME_S16_4LE, remap_c32}, +/* #endif */ +}; + +const size_t pcm_remap_func_count = ARRAY_SIZE(pcm_remap_func_map); diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c deleted file mode 100644 index 7b86fc30d421..000000000000 --- a/src/audio/pipeline.c +++ /dev/null @@ -1,1000 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component_ext.h> -#include <sof/audio/pipeline.h> -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/math/numbers.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <sof/string.h> -#include <ipc/header.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -/* generic pipeline data used by pipeline_comp_* functions */ -struct pipeline_data { - struct comp_dev *start; - struct sof_ipc_pcm_params *params; - struct sof_ipc_stream_posn *posn; - struct pipeline *p; - int cmd; -}; - -/* f11818eb-e92e-4082-82a3-dc54c604ebb3 */ -DECLARE_SOF_UUID("pipe-task", pipe_task_uuid, 0xf11818eb, 0xe92e, 0x4082, - 0x82, 0xa3, 0xdc, 0x54, 0xc6, 0x04, 0xeb, 0xb3); - -static SHARED_DATA struct pipeline_posn pipeline_posn; - -void pipeline_posn_init(struct sof *sof) -{ - sof->pipeline_posn = platform_shared_get(&pipeline_posn, - sizeof(pipeline_posn)); - spinlock_init(&sof->pipeline_posn->lock); - platform_shared_commit(sof->pipeline_posn, sizeof(*sof->pipeline_posn)); -} - -static enum task_state pipeline_task(void *arg); - -/* create new pipeline - returns pipeline id or negative error */ -struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc, - struct comp_dev *cd) -{ - struct sof_ipc_stream_posn posn; - struct pipeline *p; - int ret; - - pipe_cl_info("pipeline_new()"); - - /* allocate new pipeline */ - p = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*p)); - if (!p) { - pipe_cl_err("pipeline_new() error: Out of Memory"); - return NULL; - } - - /* init pipeline */ - p->sched_comp = cd; - p->status = COMP_STATE_INIT; - - ret = pipeline_posn_offset_get(&p->posn_offset); - if (ret < 0) { - pipe_cl_err("pipeline_new() error: pipeline_posn_offset_get failed %d", - ret); - rfree(p); - return NULL; - } - - ret = memcpy_s(&p->ipc_pipe, sizeof(p->ipc_pipe), - pipe_desc, sizeof(*pipe_desc)); - assert(!ret); - - /* just for retrieving valid ipc_msg header */ - ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN, - p->ipc_pipe.comp_id); - - p->msg = ipc_msg_init(posn.rhdr.hdr.cmd, sizeof(posn)); - if (!p->msg) { - pipe_cl_err("pipeline_new() error: ipc_msg_init failed"); - rfree(p); - return NULL; - } - - return p; -} - -int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer, - int dir) -{ - uint32_t flags; - - pipe_cl_info("pipeline: connect comp %d and buffer %d", - dev_comp_id(comp), buffer->id); - - irq_local_disable(flags); - list_item_prepend(buffer_comp_list(buffer, dir), - comp_buffer_list(comp, dir)); - buffer_set_comp(buffer, comp, dir); - irq_local_enable(flags); - - return 0; -} - -/* Generic method for walking the graph upstream or downstream. - * It requires function pointer for recursion. - */ -static int pipeline_for_each_comp(struct comp_dev *current, - int (*func)(struct comp_dev *, - struct comp_buffer *, void *, - int), - void *data, - void (*buff_func)(struct comp_buffer *, - void *), - void *buff_data, - int dir) -{ - struct list_item *buffer_list = comp_buffer_list(current, dir); - struct list_item *clist; - struct comp_buffer *buffer; - struct comp_dev *buffer_comp; - int err = 0; - - /* run this operation further */ - list_for_item(clist, buffer_list) { - buffer = buffer_from_list(clist, struct comp_buffer, dir); - - /* execute operation on buffer */ - if (buff_func) - buff_func(buffer, buff_data); - - buffer_comp = buffer_get_comp(buffer, dir); - - /* don't go further if this component is not connected */ - if (!buffer_comp) - continue; - - /* continue further */ - if (func) { - err = func(buffer_comp, buffer, data, dir); - if (err < 0) - break; - } - } - - return err; -} - -static int pipeline_comp_complete(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - - pipe_dbg(ppl_data->p, "pipeline_comp_complete(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - if (!comp_is_single_pipeline(current, ppl_data->start)) { - pipe_dbg(ppl_data->p, "pipeline_comp_complete(), current is from another pipeline"); - return 0; - } - - /* complete component init */ - current->pipeline = ppl_data->p; - current->period = ppl_data->p->ipc_pipe.period; - current->priority = ppl_data->p->ipc_pipe.priority; - - pipeline_for_each_comp(current, &pipeline_comp_complete, data, - NULL, NULL, dir); - - return 0; -} - -int pipeline_complete(struct pipeline *p, struct comp_dev *source, - struct comp_dev *sink) -{ - struct pipeline_data data; - - pipe_info(p, "pipeline_complete()"); - - /* check whether pipeline is already completed */ - if (p->status != COMP_STATE_INIT) { - pipe_err(p, "pipeline_complete() error: Pipeline already completed"); - return -EINVAL; - } - - data.start = source; - data.p = p; - - /* now walk downstream from source component and - * complete component task and pipeline initialization - */ - pipeline_comp_complete(source, NULL, &data, PPL_DIR_DOWNSTREAM); - - p->source_comp = source; - p->sink_comp = sink; - p->status = COMP_STATE_READY; - - /* show heap status */ - heap_trace_all(0); - - return 0; -} - -static int pipeline_comp_free(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - uint32_t flags; - - pipe_cl_dbg("pipeline_comp_free(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - if (!comp_is_single_pipeline(current, ppl_data->start)) { - pipe_cl_dbg("pipeline_comp_free(), current is from another pipeline"); - return 0; - } - - /* complete component free */ - current->pipeline = NULL; - - pipeline_for_each_comp(current, &pipeline_comp_free, data, - NULL, NULL, dir); - - /* disconnect source from buffer */ - irq_local_disable(flags); - list_item_del(comp_buffer_list(current, dir)); - irq_local_enable(flags); - - return 0; -} - -/* pipelines must be inactive */ -int pipeline_free(struct pipeline *p) -{ - struct pipeline_data data; - - pipe_info(p, "pipeline_free()"); - - /* make sure we are not in use */ - if (p->source_comp) { - if (p->source_comp->state > COMP_STATE_READY) { - pipe_err(p, "pipeline_free() error: Pipeline in use, %u, %u", - dev_comp_id(p->source_comp), - p->source_comp->state); - return -EBUSY; - } - - data.start = p->source_comp; - - /* disconnect components */ - pipeline_comp_free(p->source_comp, NULL, &data, - PPL_DIR_DOWNSTREAM); - } - - /* remove from any scheduling */ - if (p->pipe_task) { - schedule_task_free(p->pipe_task); - rfree(p->pipe_task); - } - - ipc_msg_free(p->msg); - - pipeline_posn_offset_put(p->posn_offset); - - /* now free the pipeline */ - rfree(p); - - /* show heap status */ - heap_trace_all(0); - - return 0; -} - -/* save params changes made by component */ -static void pipeline_update_buffer_pcm_params(struct comp_buffer *buffer, - void *data) -{ - struct sof_ipc_stream_params *params = data; - 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; - for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) - params->chmap[i] = buffer->chmap[i]; -} - -/* fetch hardware stream parameters from DAI and propagate them to the remaining - * buffers in pipeline. - */ -static int pipeline_comp_hw_params(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - int ret = 0; - uint32_t flags = 0; - - pipe_cl_dbg("pipeline_comp_hw_params(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - pipeline_for_each_comp(current, &pipeline_comp_hw_params, data, NULL, - NULL, dir); - - /* Fetch hardware stream parameters from DAI component */ - if (dev_comp_type(current) == SOF_COMP_DAI) { - ret = comp_dai_get_hw_params(current, - &ppl_data->params->params, dir); - if (ret < 0) { - pipe_cl_err("pipeline_find_dai_comp(): comp_dai_get_hw_params() error."); - return ret; - } - } - - /* set buffer parameters */ - if (calling_buf) { - buffer_lock(calling_buf, &flags); - buffer_set_params(calling_buf, &ppl_data->params->params, - BUFFER_UPDATE_IF_UNSET); - buffer_unlock(calling_buf, flags); - } - - return ret; -} - -static int pipeline_comp_params(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - int stream_direction = ppl_data->params->params.direction; - int end_type; - int err = 0; - - pipe_cl_dbg("pipeline_comp_params(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - if (!comp_is_single_pipeline(current, ppl_data->start)) { - /* If pipeline connected to the starting one is in improper - * direction (CAPTURE towards DAI, PLAYBACK towards HOST), - * stop propagation of parameters not to override their config. - * Direction param of the pipeline can not be trusted at this - * point, as it might not be configured yet, hence checking - * for endpoint component type. - */ - end_type = comp_get_endpoint_type(current->pipeline->sink_comp); - if (stream_direction == SOF_IPC_STREAM_PLAYBACK) { - if (end_type == COMP_ENDPOINT_HOST || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - - if (stream_direction == SOF_IPC_STREAM_CAPTURE) { - if (end_type == COMP_ENDPOINT_DAI || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - } - - /* don't do any params if current is running */ - if (current->state == COMP_STATE_ACTIVE) - return 0; - - /* set comp direction */ - current->direction = ppl_data->params->params.direction; - - err = comp_params(current, &ppl_data->params->params); - if (err < 0 || err == PPL_STATUS_PATH_STOP) - return err; - - return pipeline_for_each_comp(current, &pipeline_comp_params, data, - &pipeline_update_buffer_pcm_params, - &ppl_data->params->params, - dir); -} - -/* Send pipeline component params from host to endpoints. - * Params always start at host (PCM) and go downstream for playback and - * upstream for capture. - * - * Playback params can be re-written by upstream components. e.g. upstream SRC - * can change sample rate for all downstream components regardless of sample - * rate from host. - * - * Capture params can be re-written by downstream components. - * - * Params are always modified in the direction of host PCM to DAI. - */ -int pipeline_params(struct pipeline *p, struct comp_dev *host, - struct sof_ipc_pcm_params *params) -{ - struct sof_ipc_pcm_params hw_params; - struct pipeline_data data; - int dir = params->params.direction; - int ret; - - pipe_info(p, "pipe params dir %d frame_fmt %d buffer_fmt %d rate %d", - params->params.direction, params->params.frame_fmt, - params->params.buffer_fmt, params->params.rate); - pipe_info(p, "pipe params stream_tag %d channels %d sample_valid_bytes %d sample_container_bytes %d", - params->params.stream_tag, params->params.channels, - params->params.sample_valid_bytes, - params->params.sample_container_bytes); - - /* settin hw params */ - data.start = host; - data.params = &hw_params; - - ret = pipeline_comp_hw_params(data.start, NULL, &data, dir); - if (ret < 0) { - pipe_cl_err("pipeline_prepare() error: ret = %d, dev->comp.id = %u", - ret, dev_comp_id(host)); - return ret; - } - - /* setting pcm params */ - data.params = params; - data.start = host; - - ret = pipeline_comp_params(host, NULL, &data, params->params.direction); - if (ret < 0) { - pipe_cl_err("pipeline_params() error: ret = %d, host->comp.id = %u", - ret, dev_comp_id(host)); - } - - return ret; -} - -static struct task *pipeline_task_init(struct pipeline *p, uint32_t type, - enum task_state (*func)(void *data)) -{ - struct pipeline_task *task = NULL; - - task = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*task)); - if (!task) - return NULL; - - if (schedule_task_init_ll(&task->task, SOF_UUID(pipe_task_uuid), type, - p->ipc_pipe.priority, func, - p, p->ipc_pipe.core, 0) < 0) { - rfree(task); - return NULL; - } - - task->sched_comp = p->sched_comp; - task->registrable = p == p->sched_comp->pipeline; - - return &task->task; -} - -static int pipeline_comp_task_init(struct pipeline *p) -{ - uint32_t type; - - /* initialize task if necessary */ - if (!p->pipe_task) { - /* right now we always consider pipeline as a low latency - * component, but it may change in the future - */ - type = pipeline_is_timer_driven(p) ? SOF_SCHEDULE_LL_TIMER : - SOF_SCHEDULE_LL_DMA; - - p->pipe_task = pipeline_task_init(p, type, pipeline_task); - if (!p->pipe_task) { - pipe_cl_err("pipeline_prepare() error: task init failed"); - return -ENOMEM; - } - } - - return 0; -} - -static int pipeline_comp_prepare(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - int err = 0; - struct pipeline_data *ppl_data = data; - int stream_direction = dir; - int end_type; - - pipe_cl_dbg("pipeline_comp_prepare(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - if (!comp_is_single_pipeline(current, ppl_data->start)) { - /* If pipeline connected to the starting one is in improper - * direction (CAPTURE towards DAI, PLAYBACK towards HOST), - * stop propagation. Direction param of the pipeline can not be - * trusted at this point, as it might not be configured yet, - * hence checking for endpoint component type. - */ - end_type = comp_get_endpoint_type(current->pipeline->sink_comp); - if (stream_direction == SOF_IPC_STREAM_PLAYBACK) { - if (end_type == COMP_ENDPOINT_HOST || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - - if (stream_direction == SOF_IPC_STREAM_CAPTURE) { - if (end_type == COMP_ENDPOINT_DAI || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - } - - err = pipeline_comp_task_init(current->pipeline); - if (err < 0) - return err; - - err = comp_prepare(current); - if (err < 0 || err == PPL_STATUS_PATH_STOP) - return err; - - return pipeline_for_each_comp(current, &pipeline_comp_prepare, data, - &buffer_reset_pos, NULL, dir); -} - -/* prepare the pipeline for usage */ -int pipeline_prepare(struct pipeline *p, struct comp_dev *dev) -{ - struct pipeline_data ppl_data; - int ret = 0; - - pipe_info(p, "pipe prepare"); - - ppl_data.start = dev; - - ret = pipeline_comp_prepare(dev, NULL, &ppl_data, dev->direction); - if (ret < 0) { - pipe_cl_err("pipeline_prepare() error: ret = %d, dev->comp.id = %u", - ret, dev_comp_id(dev)); - return ret; - } - - p->status = COMP_STATE_PREPARE; - - return ret; -} - -static void pipeline_comp_trigger_sched_comp(struct pipeline *p, - struct comp_dev *comp, int cmd) -{ - /* only required by the scheduling component or sink component - * on pipeline without one - */ - if (p->sched_comp != comp && - (p == p->sched_comp->pipeline || p->sink_comp != comp)) - return; - - switch (cmd) { - case COMP_TRIGGER_PAUSE: - case COMP_TRIGGER_STOP: - case COMP_TRIGGER_XRUN: - pipeline_schedule_cancel(p); - p->status = COMP_STATE_PAUSED; - break; - case COMP_TRIGGER_RELEASE: - case COMP_TRIGGER_START: - pipeline_schedule_copy(p, 0); - p->xrun_bytes = 0; - p->status = COMP_STATE_ACTIVE; - break; - case COMP_TRIGGER_SUSPEND: - case COMP_TRIGGER_RESUME: - default: - break; - } -} - -static int pipeline_comp_trigger(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - int is_single_ppl = comp_is_single_pipeline(current, ppl_data->start); - int is_same_sched = - pipeline_is_same_sched_comp(current->pipeline, - ppl_data->start->pipeline); - int err; - - pipe_cl_dbg("pipeline_comp_trigger(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - /* trigger should propagate to the connected pipelines, - * which need to be scheduled together - */ - if (!is_single_ppl && !is_same_sched) { - pipe_dbg(current->pipeline, "pipeline_comp_trigger(), current is from another pipeline"); - return 0; - } - - /* send command to the component and update pipeline state */ - err = comp_trigger(current, ppl_data->cmd); - if (err < 0 || err == PPL_STATUS_PATH_STOP) - return err; - - pipeline_comp_trigger_sched_comp(current->pipeline, current, - ppl_data->cmd); - - return pipeline_for_each_comp(current, &pipeline_comp_trigger, data, - NULL, NULL, dir); -} - -/* - * trigger handler for pipelines in xrun, used for recovery from host only. - * return values: - * 0 -- success, further trigger in caller needed. - * PPL_STATUS_PATH_STOP -- done, no more further trigger needed. - * minus -- failed, caller should return failure. - */ -static int pipeline_xrun_handle_trigger(struct pipeline *p, int cmd) -{ - int ret = 0; - - /* it is expected in paused status for xrun pipeline */ - if (!p->xrun_bytes || p->status != COMP_STATE_PAUSED) - return 0; - - /* in xrun, handle start/stop trigger */ - switch (cmd) { - case COMP_TRIGGER_START: - /* in xrun, prepare before trigger start needed */ - pipe_info(p, "in xrun, prepare it first"); - /* prepare the pipeline */ - ret = pipeline_prepare(p, p->source_comp); - if (ret < 0) { - pipe_err(p, "prepare error: ret = %d", ret); - return ret; - } - /* now ready for start, clear xrun_bytes */ - p->xrun_bytes = 0; - break; - case COMP_TRIGGER_STOP: - /* in xrun, suppose pipeline is already stopped, ignore it */ - pipe_info(p, "already stopped in xrun"); - /* no more further trigger stop needed */ - ret = PPL_STATUS_PATH_STOP; - break; - default: - break; - } - - return ret; -} - -/* trigger pipeline */ -int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) -{ - struct pipeline_data data; - int ret; - - pipe_info(p, "pipe trigger cmd %d", cmd); - - /* handle pipeline global checks before going into each components */ - if (p->xrun_bytes) { - ret = pipeline_xrun_handle_trigger(p, cmd); - if (ret < 0) { - pipe_err(p, "xrun handle error: ret = %d", ret); - return ret; - } else if (ret == PPL_STATUS_PATH_STOP) - /* no further action needed*/ - return 0; - } - - data.start = host; - data.cmd = cmd; - - ret = pipeline_comp_trigger(host, NULL, &data, host->direction); - if (ret < 0) { - pipe_cl_err("pipeline_trigger() error: ret = %d, host->comp.id = %u, cmd = %d", - ret, dev_comp_id(host), cmd); - } - - return ret; -} - -static int pipeline_comp_reset(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline *p = data; - int stream_direction = dir; - int end_type; - int err = 0; - - pipe_cl_dbg("pipeline_comp_reset(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - if (!comp_is_single_pipeline(current, p->source_comp)) { - /* If pipeline connected to the starting one is in improper - * direction (CAPTURE towards DAI, PLAYBACK towards HOST), - * stop propagation. Direction param of the pipeline can not be - * trusted at this point, as it might not be configured yet, - * hence checking for endpoint component type. - */ - end_type = comp_get_endpoint_type(current->pipeline->sink_comp); - if (stream_direction == SOF_IPC_STREAM_PLAYBACK) { - if (end_type == COMP_ENDPOINT_HOST || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - - if (stream_direction == SOF_IPC_STREAM_CAPTURE) { - if (end_type == COMP_ENDPOINT_DAI || - end_type == COMP_ENDPOINT_NODE) - return 0; - } - } - - err = comp_reset(current); - if (err < 0 || err == PPL_STATUS_PATH_STOP) - return err; - - return pipeline_for_each_comp(current, &pipeline_comp_reset, data, - buffer_reset_params, NULL, dir); -} - -/* reset the whole pipeline */ -int pipeline_reset(struct pipeline *p, struct comp_dev *host) -{ - int ret = 0; - - pipe_info(p, "pipe reset"); - - ret = pipeline_comp_reset(host, NULL, p, host->direction); - if (ret < 0) { - pipe_cl_err("pipeline_reset() error: ret = %d, host->comp.id = %u", - ret, dev_comp_id(host)); - } - - return ret; -} - -static int pipeline_comp_copy(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - int is_single_ppl = comp_is_single_pipeline(current, ppl_data->start); - int err; - - pipe_cl_dbg("pipeline_comp_copy(), current->comp.id = %u, dir = %u", - dev_comp_id(current), dir); - - if (!is_single_ppl) { - pipe_cl_dbg("pipeline_comp_copy(), current is from another pipeline and can't be scheduled together"); - return 0; - } - - if (!comp_is_active(current)) { - pipe_cl_dbg("pipeline_comp_copy(), current is not active"); - return 0; - } - - /* copy to downstream immediately */ - if (dir == PPL_DIR_DOWNSTREAM) { - err = comp_copy(current); - if (err < 0 || err == PPL_STATUS_PATH_STOP) - return err; - } - - err = pipeline_for_each_comp(current, &pipeline_comp_copy, - data, NULL, NULL, dir); - if (err < 0 || err == PPL_STATUS_PATH_STOP) - return err; - - if (dir == PPL_DIR_UPSTREAM) - err = comp_copy(current); - - return err; -} - -/* Copy data across all pipeline components. - * For capture pipelines it always starts from source component - * and continues downstream and for playback pipelines it first - * copies sink component itself and then goes upstream. - */ -static int pipeline_copy(struct pipeline *p) -{ - struct pipeline_data data; - struct comp_dev *start; - uint32_t dir; - int ret = 0; - - if (p->source_comp->direction == SOF_IPC_STREAM_PLAYBACK) { - dir = PPL_DIR_UPSTREAM; - start = p->sink_comp; - } else { - dir = PPL_DIR_DOWNSTREAM; - start = p->source_comp; - } - - data.start = start; - data.p = p; - - ret = pipeline_comp_copy(start, NULL, &data, dir); - if (ret < 0) - pipe_cl_err("pipeline_copy() error: ret = %d, start->comp.id = %u, dir = %u", - ret, dev_comp_id(start), dir); - - return ret; -} - -/* Walk the graph to active components in any pipeline to find - * the first active DAI and return it's timestamp. - */ -static int pipeline_comp_timestamp(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - - if (!comp_is_active(current)) { - pipe_cl_dbg("pipeline_comp_timestamp(), current is not active"); - return 0; - } - - /* is component a DAI endpoint? */ - if (current != ppl_data->start && - (dev_comp_type(current) == SOF_COMP_DAI || - dev_comp_type(current) == SOF_COMP_SG_DAI)) { - platform_dai_timestamp(current, ppl_data->posn); - return -1; - } - - return pipeline_for_each_comp(current, &pipeline_comp_timestamp, data, - NULL, NULL, dir); -} - -/* Get the timestamps for host and first active DAI found. */ -void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host, - struct sof_ipc_stream_posn *posn) -{ - struct pipeline_data data; - - platform_host_timestamp(host, posn); - - data.start = host; - data.posn = posn; - - pipeline_comp_timestamp(host, NULL, &data, host->direction); - - /* set timestamp resolution */ - posn->timestamp_ns = p->ipc_pipe.period * 1000; -} - -static int pipeline_comp_xrun(struct comp_dev *current, - struct comp_buffer *calling_buf, void *data, - int dir) -{ - struct pipeline_data *ppl_data = data; - - if (dev_comp_type(current) == SOF_COMP_HOST) { - /* get host timestamps */ - platform_host_timestamp(current, ppl_data->posn); - - /* send XRUN to host */ - mailbox_stream_write(ppl_data->p->posn_offset, ppl_data->posn, - sizeof(*ppl_data->posn)); - ipc_msg_send(ppl_data->p->msg, ppl_data->posn, true); - } - - return pipeline_for_each_comp(current, &pipeline_comp_xrun, data, NULL, - NULL, dir); -} - -/* Send an XRUN to each host for this component. */ -void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, - int32_t bytes) -{ - struct pipeline_data data; - struct sof_ipc_stream_posn posn; - int ret; - - /* don't flood host */ - if (p->xrun_bytes) - return; - - /* only send when we are running */ - if (dev->state != COMP_STATE_ACTIVE) - return; - - /* notify all pipeline comps we are in XRUN, and stop copying */ - ret = pipeline_trigger(p, p->source_comp, COMP_TRIGGER_XRUN); - if (ret < 0) - pipe_err(p, "pipeline_xrun() error: Pipelines notification about XRUN failed, ret = %d", - ret); - - memset(&posn, 0, sizeof(posn)); - ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN, - dev_comp_id(dev)); - p->xrun_bytes = bytes; - posn.xrun_size = bytes; - posn.xrun_comp_id = dev_comp_id(dev); - data.posn = &posn; - data.p = p; - - pipeline_comp_xrun(dev, NULL, &data, dev->direction); -} - -#if NO_XRUN_RECOVERY -/* recover the pipeline from a XRUN condition */ -static int pipeline_xrun_recover(struct pipeline *p) -{ - return -EINVAL; -} - -#else -/* recover the pipeline from a XRUN condition */ -static int pipeline_xrun_recover(struct pipeline *p) -{ - int ret; - - pipe_err(p, "pipeline_xrun_recover()"); - - /* prepare the pipeline */ - ret = pipeline_prepare(p, p->source_comp); - if (ret < 0) { - pipe_err(p, "pipeline_xrun_recover() error: pipeline_prepare() failed, ret = %d", - ret); - return ret; - } - - /* reset xrun status as we already in prepared */ - p->xrun_bytes = 0; - - /* restart pipeline comps */ - ret = pipeline_trigger(p, p->source_comp, COMP_TRIGGER_START); - if (ret < 0) { - pipe_err(p, "pipeline_xrun_recover() error: pipeline_trigger() failed, ret = %d", - ret); - return ret; - } - - return 0; -} -#endif - -/* notify pipeline that this component requires buffers emptied/filled */ -void pipeline_schedule_copy(struct pipeline *p, uint64_t start) -{ - schedule_task(p->pipe_task, start, p->ipc_pipe.period); -} - -void pipeline_schedule_cancel(struct pipeline *p) -{ - schedule_task_cancel(p->pipe_task); -} - -static enum task_state pipeline_task(void *arg) -{ - struct pipeline *p = arg; - int err; - - pipe_dbg(p, "pipeline_task()"); - - /* are we in xrun ? */ - if (p->xrun_bytes) { - /* try to recover */ - err = pipeline_xrun_recover(p); - if (err < 0) - /* skip copy if still in xrun */ - return SOF_TASK_STATE_COMPLETED; - } - - err = pipeline_copy(p); - if (err < 0) { - /* try to recover */ - err = pipeline_xrun_recover(p); - if (err < 0) { - pipe_err(p, "pipeline_task(): xrun recover failed! pipeline will be stopped!"); - /* failed - host will stop this pipeline */ - return SOF_TASK_STATE_COMPLETED; - } - } - - pipe_cl_dbg("pipeline_task() sched"); - - return SOF_TASK_STATE_RESCHEDULE; -} diff --git a/src/audio/pipeline/CMakeLists.txt b/src/audio/pipeline/CMakeLists.txt new file mode 100644 index 000000000000..cb26dc3214bd --- /dev/null +++ b/src/audio/pipeline/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + pipeline-graph.c + pipeline-stream.c + pipeline-params.c + pipeline-xrun.c + pipeline-schedule.c +) diff --git a/src/audio/pipeline/README.md b/src/audio/pipeline/README.md new file mode 100644 index 000000000000..4e530bdc1463 --- /dev/null +++ b/src/audio/pipeline/README.md @@ -0,0 +1,245 @@ +# Pipeline Engine Architecture + +This directory contains the core graph/pipeline logic. + +## Overview + +The Pipeline engine is the heart of the SOF processing architecture. It links `components` together using `buffers`, and provides scheduling execution entities (tasks) to repeatedly trigger these component graphs. + +## Architecture Diagram + +```mermaid +graph TD + Host[Host Topology] -.-> Manager[Pipeline Manager] + Manager --> Buf1[Buffer] + Manager --> CompA[Component] + Manager --> Sched[Task Scheduler] + Sched --> CompA +``` + +## State Machine + +The pipeline progresses through various states (`COMP_STATE_INIT`, `COMP_STATE_READY`, `COMP_STATE_ACTIVE`, etc.) largely directed by `comp_trigger()` commands cascaded down the graph. + +```mermaid +stateDiagram-v2 + [*] --> INIT : pipeline_new() + INIT --> READY : pipeline_complete() + READY --> PRE_ACTIVE : COMP_TRIGGER_PRE_START + PRE_ACTIVE --> ACTIVE : COMP_TRIGGER_START + ACTIVE --> PAUSED : COMP_TRIGGER_PAUSE + PAUSED --> ACTIVE : COMP_TRIGGER_RELEASE / START + ACTIVE --> SUSPEND : COMP_TRIGGER_SUSPEND + SUSPEND --> ACTIVE : COMP_TRIGGER_RESUME + ACTIVE --> PRE_ACTIVE : COMP_TRIGGER_PRE_RELEASE + ACTIVE --> READY : COMP_TRIGGER_STOP + ACTIVE --> XRUN_PAUSED : COMP_TRIGGER_XRUN + XRUN_PAUSED --> READY : pipeline_xrun_recover() +``` + +## Processing Flow (LL and DP Modes) + +Execution within the SOF pipeline is divided between two primary timing domains depending on the component's `proc_domain` property. + +1. **Low Latency (LL) Domain:** + * **Driven By:** DMA interrupts or precise timers. + * **Execution:** A single cooperative scheduler task (`pipeline_task`) iterates over the entire connected graph. + * **Process:** The pipeline scheduler invokes `pipeline_copy()` which calls `comp_copy()` on the source or sink, and then recursively relies on `pipeline_for_each_comp` to pull or push data through the graph synchronously within that single timeslice. + +2. **Data Processing (DP) Domain:** + * **Driven By:** A Zephyr-based discrete RTOS thread (`CONFIG_ZEPHYR_DP_SCHEDULER`). + * **Execution:** Modules that require extensive computation (especially those leveraging the `module_adapter`) are spun off into their own isolated threads using `pipeline_comp_dp_task_init()`. + * **Process:** Instead of synchronous execution alongside the DMA, they consume and produce data (`module_process_sink_src`) with their own stack (`TASK_DP_STACK_SIZE`), relying on inter-component buffers and thread synchronization to pass chunks back to the LL domain when ready. + +```mermaid +sequenceDiagram + participant DMA + participant Sched as LL Scheduler (pipeline_task) + participant Source as Source Component (e.g., Host Interface) + participant Buffer as Internal Buffer + participant Filter as Filter Component (e.g., EQ) + participant Sink as Sink Component (e.g., DAI) + + DMA->>Sched: Interrupt / Timer Tick + activate Sched + Sched->>Source: pipeline_copy() -> comp_copy() + Source-->>Buffer: Copies PCM Data to Buffer + Sched->>Filter: pipeline_for_each_comp() -> comp_copy() + Filter->>Buffer: Reads PCM Data + Filter-->>Buffer: Writes Processed Data + Sched->>Sink: pipeline_for_each_comp() -> comp_copy() + Sink->>Buffer: Reads Processed Data + Sink-->>Sink: Transmits to Audio Hardware + deactivate Sched +``` + +### Mixed LL and DP Execution + +```mermaid +sequenceDiagram + participant DMA + participant Sched as LL Scheduler (pipeline_task) + participant DPThread as DP Thread (dp_task_run) + participant CompLL as LL Component + participant CompDP as DP Component + + DMA->>Sched: Interrupt / Timer Tick + activate Sched + Sched->>CompLL: pipeline_copy() -> comp_copy() + CompLL-->>Sched: Data Produced into Buffer + Sched->>DPThread: Wakeup (Buffer Data Available) + deactivate Sched + + activate DPThread + DPThread->>CompDP: module_process_sink_src() + CompDP-->>DPThread: Computations finished + DPThread->>Sched: Notification (Data Ready) + deactivate DPThread +``` + +## Control and Configuration Flows + +The lifecycle of a pipeline graph involves several discrete initialization and connection steps orchestrated by IPC topology commands before streaming begins. + +1. **Creation (`pipeline_new`)**: Instantiates the `struct pipeline` object, associates the memory heap, and grabs a mailbox offset for IPC position tracking. +2. **Connection (`pipeline_connect` / `pipeline_disconnect`)**: Establishes the directional edges of the graph by attaching a `comp_buffer` between a source and sink `comp_dev`. It updates the component's internal buffer lists. +3. **Completion (`pipeline_complete`)**: Validates the graph structure. It recursively walks the entire chain from source to sink (`pipeline_for_each_comp`), verifying consistency (e.g., ensuring components aren't part of mismatched pipelines unless properly handled), and transitions the pipeline state to `COMP_STATE_READY`. +4. **Parameter Propagation (`pipeline_params`, `pipeline_prepare`)**: Triggered prior to streaming, `pipeline_prepare()` walks the graph to finalize PCM formats, period sizes, and hardware configurations (like iterating over the audio buffers to `audio_buffer_reset_params`). +5. **Teardown (`pipeline_free`)**: When a stream is closed, after all `comp_dev` objects internal to the pipeline are halted and detached, `pipeline_free` cleans up the `pipe_task` scheduler footprint, IPC messages, and unlinks memory allocations freeing the `struct pipeline` entirely. + +### Creation and Teardown Flow + +```mermaid +sequenceDiagram + participant Host + participant Sched as LL Scheduler + participant Pipe as Pipeline + participant Source as Source Component + + Host->>Pipe: pipeline_new() + activate Pipe + Pipe-->>Pipe: Allocates struct pipeline & gets Mailbox Offset + + Host->>Source: comp_new() (Creates Components) + + Host->>Pipe: pipeline_connect() + Pipe-->>Pipe: Links comp_buffers internally + + Host->>Pipe: pipeline_complete() + Pipe->>Source: pipeline_for_each_comp() + Source-->>Pipe: Graph validates + Pipe-->>Host: Status: COMP_STATE_READY + + Note over Host,Pipe: ... Active Audio Streaming ... + + Host->>Pipe: pipeline_free() + Pipe->>Sched: schedule_task_free(pipe_task) + Pipe-->>Pipe: sof_heap_free() (Frees tracking structs) + Pipe-->>Host: Pipeline Extinguished + deactivate Pipe +``` + +### Triggering Flow + +Triggering is fundamentally responsible for transitioning graph states (`COMP_STATE_ACTIVE`, `COMP_STATE_PAUSED`, etc). A trigger (like `COMP_TRIGGER_START` or `COMP_TRIGGER_STOP`) commands an underlying state change and pushes the `pipeline_task` into the `schedule_task` queue. + +```mermaid +sequenceDiagram + participant Host + participant PPL as Pipeline (pipeline_trigger) + participant Sched as LL Scheduler (pipeline_task) + participant Source as Source Component + participant Sink as Sink Component + + Host->>PPL: pipeline_trigger(COMP_TRIGGER_START) + activate PPL + PPL->>Source: pipeline_for_each_comp(COMP_TRIGGER_START) + Source->>Sink: comp_trigger(COMP_TRIGGER_START) + Sink-->>PPL: State -> COMP_STATE_ACTIVE + + PPL->>Sched: pipeline_schedule_copy() + Sched-->>Sched: Adds `pipe_task` to active scheduler + PPL-->>Host: Trigger successful + deactivate PPL + + Note over PPL,Sched: Pipeline repeatedly scheduled via DMA or Timers + + Host->>PPL: pipeline_trigger(COMP_TRIGGER_STOP) + activate PPL + PPL->>Sched: pipeline_schedule_cancel() + Sched-->>Sched: Removes `pipe_task` from active scheduler + PPL->>Source: pipeline_for_each_comp(COMP_TRIGGER_STOP) + Source->>Sink: comp_trigger(COMP_TRIGGER_STOP) + Sink-->>PPL: State -> COMP_STATE_PAUSED / READY + PPL-->>Host: Trigger successful + deactivate PPL +``` + +```mermaid +sequenceDiagram + participant Host + participant Pipe as Pipeline (pipeline_complete) + participant Source as Source Component + participant Sink as Sink Component + participant Buf as Buffer + + Host->>Pipe: ipc_pipeline_complete() + activate Pipe + Pipe->>Source: pipeline_for_each_comp(PPL_DIR_DOWNSTREAM) + Source->>Buf: buffer_set_comp() + Buf->>Sink: comp_is_single_pipeline() + Sink-->>Pipe: Pipeline graph linked + Pipe-->>Host: Status: COMP_STATE_READY + deactivate Pipe + + Host->>Pipe: ipc_comp_prepare() + activate Pipe + Pipe->>Source: pipeline_prepare() + Source->>Buf: audio_buffer_reset_params() + Buf->>Sink: comp_prepare() + Sink-->>Pipe: Prepared formats + Pipe-->>Host: Prepared + deactivate Pipe +``` + +## Error Handling (XRUNs) + +Overruns (host writes too fast/firmware reads too slow) and underruns (host reads too fast/firmware writes too slow) are tracked continuously. + +1. **Detection**: Components directly hooked to interfaces (like a host IPC component or a hardware DAI) monitor their `comp_copy` status. If they detect starvation or overflow, they trigger an XRUN event. +2. **Propagation (`pipeline_xrun`)**: The pipeline immediately invokes a broadcast `pipeline_trigger(..., COMP_TRIGGER_XRUN)` forcing all internal components to drop to a halted `XRUN_PAUSED` state. In older IPC3 topologies, it additionally signals the host via mailbox offsets (`ipc_build_stream_posn`). +3. **Recovery (`pipeline_xrun_handle_trigger` / `pipeline_xrun_recover`)**: By default, the `pipeline_task` scheduler will intercept the `xrun_bytes` flag. Unless `NO_XRUN_RECOVERY` is defined, the firmware attempts self-healing: + * It resets the pipeline downstream of the source (`pipeline_reset`). + * It prepares it again (`pipeline_prepare`). + * It issues an internal `COMP_TRIGGER_START` to restart data flow automatically without host intervention. + +```mermaid +sequenceDiagram + participant DAI as Hardware Interface + participant Comp as Connected Component + participant PPL as Pipeline (pipeline_xrun) + participant Sched as LL Scheduler (pipeline_task) + participant Host as Host Interface + + DAI-->>Comp: Overflow/Underrun Detected + activate Comp + Comp->>PPL: pipeline_xrun() + PPL->>Comp: pipeline_trigger(COMP_TRIGGER_XRUN) + PPL-->>Host: Mailbox XRUN position (IPC3) + deactivate Comp + + Note over PPL,Sched: Pipeline halts (XRUN_PAUSED) + + Sched->>PPL: intercepts xrun_bytes > 0 + activate Sched + Sched->>PPL: pipeline_xrun_recover() + PPL->>Comp: pipeline_reset() + PPL->>Comp: pipeline_prepare() + PPL->>Comp: pipeline_trigger(COMP_TRIGGER_START) + PPL-->>Sched: Recovered (xrun_bytes = 0) + deactivate Sched +``` + +## Configuration and Scripts + +* **CMakeLists.txt**: Straightforward build configuration integrating the fundamental internal execution blocks of the SOF graph: `pipeline-graph.c`, `pipeline-stream.c`, `pipeline-params.c`, `pipeline-xrun.c`, and `pipeline-schedule.c`. diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c new file mode 100644 index 000000000000..47d5d0127fd0 --- /dev/null +++ b/src/audio/pipeline/pipeline-graph.c @@ -0,0 +1,578 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <rtos/interrupt.h> +#include <rtos/symbol.h> +#include <rtos/alloc.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/uuid.h> +#include <sof/compiler_attributes.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> +#include <rtos/clk.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/module.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(pipe, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(pipe); + +DECLARE_TR_CTX(pipe_tr, SOF_UUID(pipe_uuid), LOG_LEVEL_INFO); + +/* number of pipeline stream metadata objects we export in mailbox */ +#define PPL_POSN_OFFSETS \ + (MAILBOX_STREAM_SIZE / sizeof(struct sof_ipc_stream_posn)) + +/* lookup table to determine busy/free pipeline metadata objects */ +struct pipeline_posn { + bool posn_offset[PPL_POSN_OFFSETS]; /**< available offsets */ + struct k_spinlock lock; /**< lock mechanism */ +}; +/* the pipeline position lookup table */ +static SHARED_DATA struct pipeline_posn pipeline_posn_shared; + +/** + * \brief Retrieves pipeline position structure. + * \return Pointer to pipeline position structure. + */ +static inline struct pipeline_posn *pipeline_posn_get(void) +{ + return sof_get()->pipeline_posn; +} + +/** + * \brief Retrieves first free pipeline position offset. + * \param[in,out] posn_offset Pipeline position offset to be set. + * \return Error code. + */ +static inline int pipeline_posn_offset_get(uint32_t *posn_offset) +{ + struct pipeline_posn *pipeline_posn = pipeline_posn_get(); + int ret = -EINVAL; + uint32_t i; + k_spinlock_key_t key; + + key = k_spin_lock(&pipeline_posn->lock); + + for (i = 0; i < PPL_POSN_OFFSETS; ++i) { + if (!pipeline_posn->posn_offset[i]) { + *posn_offset = i * sizeof(struct sof_ipc_stream_posn); + pipeline_posn->posn_offset[i] = true; + ret = 0; + break; + } + } + + + k_spin_unlock(&pipeline_posn->lock, key); + + return ret; +} + +/** + * \brief Frees pipeline position offset. + * \param[in] posn_offset Pipeline position offset to be freed. + */ +static inline void pipeline_posn_offset_put(uint32_t posn_offset) +{ + struct pipeline_posn *pipeline_posn = pipeline_posn_get(); + int i = posn_offset / sizeof(struct sof_ipc_stream_posn); + k_spinlock_key_t key; + + key = k_spin_lock(&pipeline_posn->lock); + + pipeline_posn->posn_offset[i] = false; + + k_spin_unlock(&pipeline_posn->lock, key); +} + +void pipeline_posn_init(struct sof *sof) +{ + sof->pipeline_posn = platform_shared_get(&pipeline_posn_shared, + sizeof(pipeline_posn_shared)); + k_spinlock_init(&sof->pipeline_posn->lock); +} + +/* create new pipeline - returns pipeline id or negative error */ +struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority, + uint32_t comp_id, struct create_pipeline_params *pparams) +{ + struct sof_ipc_stream_posn posn; + struct pipeline *p; + int ret; + + pipe_cl_info("pipeline new pipe_id %d priority %d", + pipeline_id, priority); + + /* show heap status */ + heap_trace_all(0); + + /* allocate new pipeline */ + p = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*p), 0); + if (!p) { + pipe_cl_err("Out of Memory"); + return NULL; + } + + memset(p, 0, sizeof(*p)); + + /* init pipeline */ + p->heap = heap; + p->comp_id = comp_id; + p->priority = priority; + p->pipeline_id = pipeline_id; + p->status = COMP_STATE_INIT; + p->trigger.cmd = COMP_TRIGGER_NO_ACTION; + ret = memcpy_s(&p->tctx, sizeof(struct tr_ctx), &pipe_tr, + sizeof(struct tr_ctx)); + if (ret < 0) { + pipe_err(p, "failed to copy trace settings"); + goto free; + } + + ret = pipeline_posn_offset_get(&p->posn_offset); + if (ret < 0) { + pipe_err(p, "pipeline_posn_offset_get failed %d", + ret); + goto free; + } + + /* just for retrieving valid ipc_msg header */ + ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN, p->comp_id); + + if (posn.rhdr.hdr.size) { + p->msg = ipc_msg_init(posn.rhdr.hdr.cmd, posn.rhdr.hdr.size); + if (!p->msg) { + pipe_err(p, "ipc_msg_init failed"); + goto free; + } + } + + return p; +free: + sof_heap_free(heap, p); + return NULL; +} + +static void buffer_set_comp(struct comp_buffer *buffer, struct comp_dev *comp, + int dir) +{ + if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) + comp_buffer_set_source_component(buffer, comp); + else + comp_buffer_set_sink_component(buffer, comp); +} + +#ifdef CONFIG_SOF_USERSPACE_LL +#define PPL_LOCK_DECLARE +#define PPL_LOCK() do { \ + int ret = sys_mutex_lock(&comp->list_mutex, K_FOREVER); \ + assert(ret == 0); \ + } while (0) +#define PPL_UNLOCK() do { \ + int ret = sys_mutex_unlock(&comp->list_mutex); \ + assert(ret == 0); \ + } while (0) +#else +#define PPL_LOCK_DECLARE uint32_t flags +#define PPL_LOCK() irq_local_disable(flags) +#define PPL_UNLOCK() irq_local_enable(flags) +#endif + +int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer, + int dir) +{ + struct list_item *comp_list; + PPL_LOCK_DECLARE; + + if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) + comp_info(comp, "connect buffer %d as sink", buf_get_id(buffer)); + else + comp_info(comp, "connect buffer %d as source", buf_get_id(buffer)); + + PPL_LOCK(); + + comp_list = comp_buffer_list(comp, dir); + buffer_attach(buffer, comp_list, dir); + buffer_set_comp(buffer, comp, dir); + + PPL_UNLOCK(); + + return 0; +} + +void pipeline_disconnect(struct comp_dev *comp, struct comp_buffer *buffer, int dir) +{ + struct list_item *comp_list; + PPL_LOCK_DECLARE; + + if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) + comp_dbg(comp, "disconnect buffer %d as sink", buf_get_id(buffer)); + else + comp_dbg(comp, "disconnect buffer %d as source", buf_get_id(buffer)); + + PPL_LOCK(); + + comp_list = comp_buffer_list(comp, dir); + buffer_detach(buffer, comp_list, dir); + buffer_set_comp(buffer, NULL, dir); + + PPL_UNLOCK(); +} + +/* pipelines must be inactive */ +int pipeline_free(struct pipeline *p) +{ + pipe_dbg(p, "entry"); + + /* + * pipeline_free should always be called only after all the widgets in the pipeline have + * been freed. + */ + + /* remove from any scheduling */ + if (p->pipe_task) { +#if !CONFIG_LIBRARY || UNIT_TEST + schedule_task_free(p->pipe_task); +#endif + sof_heap_free(p->heap, p->pipe_task); + } + + ipc_msg_free(p->msg); + + pipeline_posn_offset_put(p->posn_offset); + + /* now free the pipeline */ + sof_heap_free(p->heap, p); + + /* show heap status */ + heap_trace_all(0); + + return 0; +} + +static int pipeline_comp_complete(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + + pipe_dbg(ppl_data->p, "current->comp.id = 0x%x, dir = %u", + dev_comp_id(current), dir); + + if (!comp_is_single_pipeline(current, ppl_data->start)) { + pipe_dbg(ppl_data->p, "current is from another pipeline"); + return 0; + } + + /* complete component init */ + current->pipeline = ppl_data->p; + /* LL module has its period always eq period of the pipeline + * DP period is set to 0 as sink format may not yet been set + * It will be calculated during module prepare operation + * either by the module or to default value based on module's OBS + */ + if (current->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + current->period = ppl_data->p->period; + + current->priority = ppl_data->p->priority; + + return pipeline_for_each_comp(current, ctx, dir); +} + +int pipeline_complete(struct pipeline *p, struct comp_dev *source, + struct comp_dev *sink) +{ + struct pipeline_data data; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_complete, + .comp_data = &data, + }; + +#if !UNIT_TEST && !CONFIG_LIBRARY && CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + int __maybe_unused freq = clock_get_freq(cpu_get_id()); +#else + int __maybe_unused freq = 0; +#endif + int ret; + + pipe_dbg(p, "pipeline complete, clock freq %dHz", freq); + + /* check whether pipeline is already completed */ + if (p->status != COMP_STATE_INIT) { + pipe_err(p, "Pipeline already completed"); + return -EINVAL; + } + + data.start = source; + data.p = p; + + /* now walk downstream from source component and + * complete component task and pipeline initialization + */ + ret = walk_ctx.comp_func(source, NULL, &walk_ctx, PPL_DIR_DOWNSTREAM); + + p->source_comp = source; + p->sink_comp = sink; + p->status = COMP_STATE_READY; + + /* show heap status */ + heap_trace_all(0); + + return ret; +} + +static int pipeline_comp_reset(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline *p = ctx->comp_data; + struct pipeline *p_current = current->pipeline; + int is_same_sched = pipeline_is_same_sched_comp(p_current, p); + int is_single_ppl; + int err; + + pipe_dbg(p_current, "current->comp.id = 0x%x, dir = %u", + dev_comp_id(current), dir); + + if (!p->source_comp) { + pipe_err(p, "source_comp is NULL"); + return -EINVAL; + } + + is_single_ppl = comp_is_single_pipeline(current, p->source_comp); + + /* + * Reset should propagate to the connected pipelines, which need to be + * scheduled together, except for IPC4, where each pipeline receives + * commands from the host separately + */ + if (!is_single_ppl && IPC4_MOD_ID(current->ipc_config.id)) + return 0; + + /* Propagate reset across pipelines only in the same direction + * and with the same scheduling behavior + */ + if (!is_single_ppl && !is_same_sched && !comp_same_dir(current, dir)) + return 0; + + /* 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, "component is in active state, try to stop it"); + err = comp_trigger(current, COMP_TRIGGER_STOP); + if (err) + pipe_err(current->pipeline, "failed to recover"); + } + + err = comp_reset(current); + if (err < 0 || err == PPL_STATUS_PATH_STOP) + return err; + + return pipeline_for_each_comp(current, ctx, dir); +} + +static inline void buffer_reset_params(struct comp_buffer *buffer, void *data) +{ + audio_buffer_reset_params(&buffer->audio_buffer); +} + +/* reset the whole pipeline */ +int pipeline_reset(struct pipeline *p, struct comp_dev *host) +{ + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_reset, + .comp_data = p, + .buff_func = buffer_reset_params, + .skip_incomplete = true, + }; + int ret; + + pipe_dbg(p, "pipe reset"); + + ret = walk_ctx.comp_func(host, NULL, &walk_ctx, host->direction); + if (ret < 0) { + pipe_err(p, "ret = %d, host->comp.id = 0x%x", + ret, dev_comp_id(host)); + } else { + /* pipeline is reset to default state */ + p->status = COMP_STATE_READY; + } + + return ret; +} + +/* Generic method for walking the graph upstream or downstream. + * It requires function pointer for recursion. + */ +int pipeline_for_each_comp(struct comp_dev *current, + struct pipeline_walk_context *ctx, int dir) +{ + struct list_item *buffer_list = comp_buffer_list(current, dir); + struct list_item *clist; + + /* run this operation further */ + list_for_item(clist, buffer_list) { + struct comp_buffer *buffer = buffer_from_list(clist, dir); + struct comp_dev *buffer_comp; + int err = 0; + + if (ctx->incoming == buffer) + continue; + + /* don't go back to the buffer which already walked */ + + if (buffer->audio_buffer.walking) + continue; + + buffer_comp = buffer_get_comp(buffer, dir); + + /* execute operation on buffer */ + if (ctx->buff_func) + ctx->buff_func(buffer, ctx->buff_data); + + /* don't go further if this component is not connected */ + if (buffer_comp && + (!ctx->skip_incomplete || buffer_comp->pipeline) && + ctx->comp_func) { + buffer->audio_buffer.walking = true; + + err = ctx->comp_func(buffer_comp, buffer, + ctx, dir); + + buffer->audio_buffer.walking = false; + } + + if (err < 0 || err == PPL_STATUS_PATH_STOP) + return err; + } + + return 0; +} + +/* visit connected pipeline to find the dai comp */ +struct comp_dev *pipeline_get_dai_comp(uint32_t pipeline_id, int dir) +{ + struct ipc_comp_dev *crt; + struct ipc *ipc = ipc_get(); + + crt = ipc_get_ppl_comp(ipc, pipeline_id, dir); + while (crt) { + struct comp_buffer *buffer; + struct comp_dev *comp; + struct list_item *blist = comp_buffer_list(crt->cd, dir); + + /* if buffer list is empty then we have found a DAI */ + if (list_is_empty(blist)) + return crt->cd; + + buffer = buffer_from_list(blist->next, dir); + comp = buffer_get_comp(buffer, dir); + + /* buffer_comp is in another pipeline and it is not complete */ + if (!comp->pipeline) + return NULL; + + crt = ipc_get_ppl_comp(ipc, comp->pipeline->pipeline_id, dir); + } + + return NULL; +} + +#if CONFIG_IPC_MAJOR_4 +/* Playback only: visit connected pipeline to find the dai comp and latency. + * This function walks down through a pipelines chain looking for the target dai component. + * Calculates the delay of each pipeline by determining the number of buffered blocks. + */ +struct comp_dev *pipeline_get_dai_comp_latency(uint32_t pipeline_id, uint32_t *latency) +{ + struct ipc_comp_dev *ipc_sink; + struct ipc_comp_dev *ipc_source; + struct comp_dev *source; + struct ipc *ipc = ipc_get(); + + *latency = 0; + + /* Walks through the ipc component list and get source endpoint component of the given + * pipeline. + */ + ipc_source = ipc_get_ppl_src_comp(ipc, pipeline_id); + if (!ipc_source) + return NULL; + source = ipc_source->cd; + + /* Walks through the ipc component list and get sink endpoint component of the given + * pipeline. This function returns the first sink. We assume that dai is connected to pin 0. + */ + ipc_sink = ipc_get_ppl_sink_comp(ipc, pipeline_id); + while (ipc_sink) { + struct comp_buffer *buffer; + uint64_t input_data, output_data; + struct ipc4_base_module_cfg input_base_cfg = {.ibs = 0}; + struct ipc4_base_module_cfg output_base_cfg = {.obs = 0}; + int ret; + + /* Calculate pipeline latency */ + input_data = comp_get_total_data_processed(source, 0, true); + output_data = comp_get_total_data_processed(ipc_sink->cd, 0, false); + + ret = comp_get_attribute(source, COMP_ATTR_BASE_CONFIG, &input_base_cfg); + if (ret < 0) + return NULL; + + ret = comp_get_attribute(ipc_sink->cd, COMP_ATTR_BASE_CONFIG, &output_base_cfg); + if (ret < 0) + return NULL; + + if (input_data && output_data && input_base_cfg.ibs && output_base_cfg.obs) + *latency += input_data / input_base_cfg.ibs - + output_data / output_base_cfg.obs; + + /* If the component doesn't have a sink buffer, it can be a dai. */ + if (list_is_empty(&ipc_sink->cd->bsink_list)) + return dev_comp_type(ipc_sink->cd) == SOF_COMP_DAI ? ipc_sink->cd : NULL; + + /* Get a component connected to our sink buffer - hop to a next pipeline */ + buffer = buffer_from_list(comp_buffer_list(ipc_sink->cd, PPL_DIR_DOWNSTREAM)->next, + PPL_DIR_DOWNSTREAM); + source = buffer_get_comp(buffer, PPL_DIR_DOWNSTREAM); + + /* buffer_comp is in another pipeline and it is not complete */ + if (!source || !source->pipeline) + return NULL; + + /* As pipeline data is allocated in cached space, continue calculation for next + * connected pipeline only if that pipeline is on same core. + * This is a workaround, the real solution would be to use something like + * process_on_core() to continue calculation on required core. However, as this + * "latency feature" seems never used anyway, this workaround could be enough. + */ + if (!cpu_is_me(source->ipc_config.core)) + return NULL; + + /* Get a next sink component */ + ipc_sink = ipc_get_ppl_sink_comp(ipc, source->pipeline->pipeline_id); + } + + return NULL; +} +EXPORT_SYMBOL(pipeline_get_dai_comp_latency); + +#endif diff --git a/src/audio/pipeline/pipeline-params.c b/src/audio/pipeline/pipeline-params.c new file mode 100644 index 000000000000..16273e0897d4 --- /dev/null +++ b/src/audio/pipeline/pipeline-params.c @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/lib/mm_heap.h> +#include <sof/compiler_attributes.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/error_status.h> +#include <ipc4/module.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(pipe, CONFIG_SOF_LOG_LEVEL); + +static int pipeline_comp_params_neg(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, + int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + int err = 0; + + pipe_dbg(current->pipeline, "current->comp.id = 0x%x, dir = %u", + dev_comp_id(current), dir); + + /* check if 'current' is already configured */ + switch (current->state) { + case COMP_STATE_INIT: + case COMP_STATE_READY: + /* + * Negotiation only happen when the current component has > 1 + * source or sink, we are propagating the params to branched + * buffers, and the subsequent component's .params() or .prepare() + * should be responsible for calibrating if needed. For example, + * a component who has different channels input/output buffers + * should explicitly configure the channels of the branched buffers. + */ + err = buffer_set_params(calling_buf, &ppl_data->params->params, + BUFFER_UPDATE_FORCE); + break; + default: + /* return 0 if params matches */ + if (!buffer_params_match(calling_buf, + &ppl_data->params->params, + BUFF_PARAMS_FRAME_FMT | + BUFF_PARAMS_RATE)) { + /* + * parameters conflict with an active pipeline, + * drop an error and reject the .params() command. + */ + pipe_err(current->pipeline, + "params conflict with existing active pipeline!"); + err = -EINVAL; + } + } + return err; +} + +static int pipeline_comp_params(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + struct pipeline_walk_context param_neg_ctx = { + .comp_func = pipeline_comp_params_neg, + .comp_data = ppl_data, + .incoming = calling_buf, + .skip_incomplete = true, + }; + int stream_direction = ppl_data->params->params.direction; + int err; + + pipe_dbg(current->pipeline, "current->comp.id = 0x%x, dir = %u", + dev_comp_id(current), dir); + + /* Don't propagate to pipelines in the opposite direction */ + if (!comp_is_single_pipeline(current, ppl_data->start) && + !comp_same_dir(current, stream_direction)) + return 0; + + /* don't do any params if current is running */ + if (current->state == COMP_STATE_ACTIVE) + return 0; + + /* do params negotiation with other branches(opposite direction) */ + err = pipeline_for_each_comp(current, ¶m_neg_ctx, !dir); + if (err < 0 || err == PPL_STATUS_PATH_STOP) + return err; + + /* set comp direction */ + current->direction = ppl_data->params->params.direction; + + err = comp_params(current, &ppl_data->params->params); + if (err < 0 || err == PPL_STATUS_PATH_STOP) + return err; + + return pipeline_for_each_comp(current, ctx, dir); +} + +/* save params changes made by component */ +static void pipeline_update_buffer_pcm_params(struct comp_buffer *buffer, + void *data) +{ + struct sof_ipc_stream_params *params = data; + int i; + + params->buffer_fmt = audio_stream_get_buffer_fmt(&buffer->stream); + 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] = audio_buffer_get_chmap(&buffer->audio_buffer, i); +} + +/* fetch hardware stream parameters from DAI */ +static int pipeline_comp_hw_params(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + int ret; + + pipe_dbg(current->pipeline, "current->comp.id = 0x%x, dir = %u", + dev_comp_id(current), dir); + + ret = pipeline_for_each_comp(current, ctx, dir); + if (ret < 0) + return ret; + + /* Fetch hardware stream parameters from DAI component */ + if (dev_comp_type(current) == SOF_COMP_DAI) { + ret = comp_dai_get_hw_params(current, + &ppl_data->params->params, dir); + if (ret < 0) { + pipe_err(current->pipeline, + "failed getting DAI parameters: %d", + ret); + return ret; + } + } + + return ret; +} + +/* propagate hw_params to buffers in pipeline. */ +static int pipeline_comp_hw_params_buf(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + int ret; + + ret = pipeline_for_each_comp(current, ctx, dir); + if (ret < 0) + return ret; + /* set buffer parameters */ + if (calling_buf) { + ret = buffer_set_params(calling_buf, &ppl_data->params->params, + BUFFER_UPDATE_IF_UNSET); + if (ret < 0) + pipe_err(current->pipeline, + "buffer_set_params(): %d", ret); + } + + return ret; +} + +/* Send pipeline component params from host to endpoints. + * Params always start at host (PCM) and go downstream for playback and + * upstream for capture. + * + * Playback params can be re-written by upstream components. e.g. upstream SRC + * can change sample rate for all downstream components regardless of sample + * rate from host. + * + * Capture params can be re-written by downstream components. + * + * Params are always modified in the direction of host PCM to DAI. + */ +int pipeline_params(struct pipeline *p, struct comp_dev *host, + struct sof_ipc_pcm_params *params) +{ + struct sof_ipc_pcm_params hw_params; + struct pipeline_data data = { + .start = host, + .params = &hw_params, + }; + struct pipeline_walk_context hw_param_ctx = { + .comp_func = pipeline_comp_hw_params, + .comp_data = &data, + .skip_incomplete = true, + }; + struct pipeline_walk_context buf_param_ctx = { + .comp_func = pipeline_comp_hw_params_buf, + .comp_data = &data, + .skip_incomplete = true, + }; + struct pipeline_walk_context param_ctx = { + .comp_func = pipeline_comp_params, + .comp_data = &data, + .buff_func = pipeline_update_buffer_pcm_params, + .buff_data = ¶ms->params, + .skip_incomplete = true, + }; + int dir = params->params.direction; + int ret; + + pipe_info(p, "pipe params dir %d frame_fmt %d buffer_fmt %d rate %d", + params->params.direction, params->params.frame_fmt, + params->params.buffer_fmt, params->params.rate); + pipe_info(p, "pipe params stream_tag %d channels %d sample_valid_bytes %d sample_container_bytes %d", + params->params.stream_tag, params->params.channels, + params->params.sample_valid_bytes, + params->params.sample_container_bytes); + + ret = hw_param_ctx.comp_func(host, NULL, &hw_param_ctx, dir); + if (ret < 0) { + pipe_err(p, "ret = %d, dev->comp.id = 0x%x", + ret, dev_comp_id(host)); + return ret; + } + + ret = buf_param_ctx.comp_func(host, NULL, &buf_param_ctx, dir); + if (ret < 0) { + pipe_err(p, "ret = %d, dev->comp.id = 0x%x", + ret, dev_comp_id(host)); + return ret; + } + + /* setting pcm params */ + data.params = params; + data.start = host; + + ret = param_ctx.comp_func(host, NULL, ¶m_ctx, dir); + if (ret < 0) { + pipe_err(p, "ret = %d, host->comp.id = 0x%x", + ret, dev_comp_id(host)); + } + +#if CONFIG_DEBUG_HEAP + /* show heap status update with this pipeline run */ + heap_trace_all(0); +#endif + return ret; +} + +static int pipeline_comp_prepare(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + int err; + + pipe_dbg(current->pipeline, "current->comp.id = 0x%x, dir = %u", + dev_comp_id(current), dir); + + if (!comp_is_single_pipeline(current, ppl_data->start)) { + /* ipc4 module is only prepared in its parent pipeline */ + if (IPC4_MOD_ID(current->ipc_config.id)) + return 0; + + /* Propagate prepare only to pipelines in the same direction */ + if (!comp_same_dir(current, dir)) + return 0; + } + + if (current->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) { + /* init a task for LL module, DP task has been created in during init_instance */ + err = pipeline_comp_ll_task_init(current->pipeline); + if (err < 0) + return err; + } + + err = comp_prepare(current); + if (err < 0 || err == PPL_STATUS_PATH_STOP) + return err; + + return pipeline_for_each_comp(current, ctx, dir); +} + +static void buffer_reset_pos(struct comp_buffer *buffer, void *data) +{ + audio_buffer_reset(&buffer->audio_buffer); +} + +/* prepare the pipeline for usage */ +int pipeline_prepare(struct pipeline *p, struct comp_dev *dev) +{ + struct pipeline_data ppl_data; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_prepare, + .comp_data = &ppl_data, + .buff_func = buffer_reset_pos, + .skip_incomplete = true, + }; + int ret; + + pipe_dbg(p, "pipe prepare"); + + ppl_data.start = dev; + + ret = walk_ctx.comp_func(dev, NULL, &walk_ctx, dev->direction); + if (ret < 0) { + pipe_err(p, "ret = %d, dev->comp.id = 0x%x", + ret, dev_comp_id(dev)); + return ret; + } + + p->status = COMP_STATE_PREPARE; + + return ret; +} diff --git a/src/audio/pipeline/pipeline-schedule.c b/src/audio/pipeline/pipeline-schedule.c new file mode 100644 index 000000000000..45fd1eed639c --- /dev/null +++ b/src/audio/pipeline/pipeline-schedule.c @@ -0,0 +1,452 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <rtos/alloc.h> +#include <rtos/interrupt.h> +#include <sof/lib/agent.h> +#include <sof/list.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/schedule.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/module.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <sof/audio/module_adapter/module/generic.h> + +LOG_MODULE_DECLARE(pipe, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(pipe_task); + +#if CONFIG_ZEPHYR_DP_SCHEDULER + +SOF_DEFINE_REG_UUID(dp_task); + +/** + * current static stack size for each DP component + * TODO: to be taken from module manifest + */ +#define TASK_DP_STACK_SIZE CONFIG_SOF_STACK_SIZE + +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + +static void pipeline_schedule_cancel(struct pipeline *p) +{ + schedule_task_cancel(p->pipe_task); + + /* enable system agent panic, when there are no longer + * DMA driven pipelines + */ + sa_set_panic_on_delay(true); +} + +static enum task_state pipeline_task_cmd(struct pipeline *p, + struct sof_ipc_reply *reply) +{ + struct comp_dev *host = p->trigger.host; + int err, cmd = p->trigger.cmd; + + if (!host) { + int ret; + + p->trigger.cmd = COMP_TRIGGER_NO_ACTION; + + switch (cmd) { + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_PAUSE: + /* if the trigger was aborted, keep the task running */ + if (p->trigger.aborted) { + ret = SOF_TASK_STATE_RUNNING; + break; + } + + /* + * if there's a trigger pending, keep the task running until it is executed + */ + if (p->trigger.pending) + ret = SOF_TASK_STATE_RUNNING; + else + ret = SOF_TASK_STATE_COMPLETED; + break; + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + if (p->status == COMP_STATE_ACTIVE) { + ret = SOF_TASK_STATE_RUNNING; + break; + } + p->status = COMP_STATE_ACTIVE; + COMPILER_FALLTHROUGH; + default: + ret = SOF_TASK_STATE_RESCHEDULE; + break; + } + + p->trigger.aborted = false; + return ret; + } + + err = pipeline_trigger_run(p, host, cmd); + if (err < 0) { + pipe_err(p, "failed to trigger components: %d", err); + reply->error = err; + err = SOF_TASK_STATE_COMPLETED; + } else { + switch (cmd) { + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + p->status = COMP_STATE_ACTIVE; + break; + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + p->status = COMP_STATE_PRE_ACTIVE; + break; + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_PAUSE: + p->status = COMP_STATE_PAUSED; + } + + if (err == PPL_STATUS_PATH_STOP) { + /* comp_trigger() interrupted trigger propagation or an xrun occurred */ + if (p->trigger.aborted && p->status == COMP_STATE_PAUSED) { + p->status = COMP_STATE_ACTIVE; + /* + * the pipeline aborted a STOP or a PAUSE + * command, proceed with copying + */ + err = SOF_TASK_STATE_RUNNING; + } else { + err = SOF_TASK_STATE_COMPLETED; + } + } else if (p->trigger.cmd != cmd) { + /* PRE stage completed */ + if (p->trigger.delay) + return SOF_TASK_STATE_RESCHEDULE; + /* No delay: the final stage has already run too */ + err = SOF_TASK_STATE_RESCHEDULE; + } else if (p->status == COMP_STATE_PAUSED) { + /* reset the pipeline components for IPC4 after the STOP trigger */ + if (cmd == COMP_TRIGGER_STOP && IPC4_MOD_ID(host->ipc_config.id)) { + err = pipeline_reset(host->pipeline, host); + if (err < 0) + reply->error = err; + } + err = SOF_TASK_STATE_COMPLETED; + } else { + p->status = COMP_STATE_ACTIVE; + err = SOF_TASK_STATE_RUNNING; + } + } + + p->trigger.cmd = COMP_TRIGGER_NO_ACTION; + + ipc_msg_reply(reply); + + return err; +} + +static enum task_state pipeline_task(void *arg) +{ + struct sof_ipc_reply reply = { + .hdr.cmd = SOF_IPC_GLB_REPLY, + .hdr.size = sizeof(reply), + }; + struct pipeline *p = arg; + int err; + + pipe_dbg(p, "entry"); + + /* are we in xrun ? */ + if (p->xrun_bytes) { + /* + * This happens when one of the connected pipelines runs into an xrun even before + * this pipeline task gets a chance to run. But the host is still waiting for a + * trigger IPC response. So, send an error response to prevent it from getting + * timed out. No point triggering the pipeline in this case. It will be stopped + * anyway by the host. + */ + if (p->trigger.cmd != COMP_TRIGGER_NO_ACTION) { + struct sof_ipc_reply reply = { + .hdr.cmd = SOF_IPC_GLB_REPLY, + .hdr.size = sizeof(reply), + .error = -EPIPE, + }; + + p->trigger.cmd = COMP_TRIGGER_NO_ACTION; + + ipc_msg_reply(&reply); + } + + /* try to recover */ + err = pipeline_xrun_recover(p); + if (err < 0) + /* skip copy if still in xrun */ + return SOF_TASK_STATE_COMPLETED; + } + + if (p->trigger.delay) { + p->trigger.delay--; + return SOF_TASK_STATE_RESCHEDULE; + } + + if (p->trigger.cmd != COMP_TRIGGER_NO_ACTION) { + /* Process an offloaded command */ + err = pipeline_task_cmd(p, &reply); + if (err != SOF_TASK_STATE_RUNNING) + return err; + } + + if (p->status == COMP_STATE_PAUSED) + /* + * One of pipelines, being stopped, but not the one, that + * triggers all components + */ + return SOF_TASK_STATE_COMPLETED; + + /* + * The first execution of the pipeline task above has triggered all + * pipeline components. Subsequent iterations actually perform data + * copying below. + */ + err = pipeline_copy(p); + if (err < 0) { + /* try to recover */ + err = pipeline_xrun_recover(p); + if (err < 0) { + pipe_err(p, "xrun recovery failed! pipeline is stopped."); + /* failed - host will stop this pipeline */ + return SOF_TASK_STATE_COMPLETED; + } + } + + pipe_dbg(p, "sched"); + + return SOF_TASK_STATE_RESCHEDULE; +} + +static struct task *pipeline_task_init(struct pipeline *p, uint32_t type) +{ + struct pipeline_task *task = NULL; + + task = sof_heap_alloc(p->heap, SOF_MEM_FLAG_USER, + sizeof(*task), 0); + if (!task) + return NULL; + + memset(task, 0, sizeof(*task)); + + if (schedule_task_init_ll(&task->task, SOF_UUID(pipe_task_uuid), type, + p->priority, pipeline_task, + p, p->core, 0) < 0) { + sof_heap_free(p->heap, task); + return NULL; + } + + task->sched_comp = p->sched_comp; + task->registrable = p == p->sched_comp->pipeline; + + return &task->task; +} + +void pipeline_schedule_config(struct pipeline *p, uint32_t sched_id, + uint32_t core, uint32_t period, + uint32_t period_mips, uint32_t frames_per_sched, + uint32_t time_domain) +{ + p->sched_id = sched_id; + p->core = core; + p->period = period; + p->period_mips = period_mips; + p->frames_per_sched = frames_per_sched; + p->time_domain = time_domain; +} + +/* trigger connected pipelines: either immediately or schedule them */ +void pipeline_schedule_triggered(struct pipeline_walk_context *ctx, + int cmd) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + struct list_item *tlist; + struct pipeline *p; + uint32_t flags; + + /* + * Interrupts have to be disabled while adding tasks to or removing them + * from the scheduler list. Without that scheduling can begin + * immediately before all pipelines achieved a consistent state. + */ + irq_local_disable(flags); + + switch (cmd) { + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + list_for_item(tlist, &ctx->pipelines) { + p = container_of(tlist, struct pipeline, list); + if (pipeline_is_timer_driven(p) && + p->status != COMP_STATE_PAUSED) { + /* + * Paused pipelines have their tasks stopped + * already, use a running pipeline to trigger + * components. + */ + p->trigger.cmd = cmd; + p->trigger.pending = true; + p->trigger.host = ppl_data->start; + ppl_data->start = NULL; + } else { + pipeline_schedule_cancel(p); + p->status = COMP_STATE_PAUSED; + } + } + break; + case COMP_TRIGGER_PRE_RELEASE: + case COMP_TRIGGER_PRE_START: + list_for_item(tlist, &ctx->pipelines) { + p = container_of(tlist, struct pipeline, list); + p->xrun_bytes = 0; + if (pipeline_is_timer_driven(p)) { + /* + * Use the first of connected pipelines to + * trigger, mark all other connected pipelines + * active immediately. + */ + p->trigger.cmd = cmd; + p->trigger.pending = true; + p->trigger.host = ppl_data->start; + ppl_data->start = NULL; + } else { + p->status = COMP_STATE_ACTIVE; + } + pipeline_schedule_copy(p, 0); + } + break; + case COMP_TRIGGER_XRUN: + list_for_item(tlist, &ctx->pipelines) { + p = container_of(tlist, struct pipeline, list); + if (!p->xrun_bytes) + /* + * the exact number of xrun bytes is unused, + * just make it non-0 + */ + p->xrun_bytes = 1; + } + } + + irq_local_enable(flags); +} + +int pipeline_comp_ll_task_init(struct pipeline *p) +{ + uint32_t type; + + /* initialize task if necessary */ + if (!p->pipe_task) { + /* right now we always consider pipeline as a low latency + * component, but it may change in the future + */ + type = pipeline_is_timer_driven(p) ? SOF_SCHEDULE_LL_TIMER : + SOF_SCHEDULE_LL_DMA; + + p->pipe_task = pipeline_task_init(p, type); + if (!p->pipe_task) { + pipe_err(p, "task init failed"); + return -ENOMEM; + } + } + + return 0; +} + +#if CONFIG_ZEPHYR_DP_SCHEDULER +static enum task_state dp_task_run(void *data) +{ + struct processing_module *mod = data; + + int ret = module_process_sink_src(mod, mod->sources, mod->num_of_sources, + mod->sinks, mod->num_of_sinks); + if (ret) + pipeline_comp_copy_error_notify(mod->dev, ret); + + return SOF_TASK_STATE_RESCHEDULE; +} + +int pipeline_comp_dp_task_init(struct comp_dev *comp) +{ + /* DP tasks are guaranteed to have a module_adapter */ + struct processing_module *mod = comp_mod(comp); + struct task_ops ops = { + .run = dp_task_run, + .get_deadline = NULL, + .complete = NULL + }; + + if (comp->task) + return 0; + +#if CONFIG_SOF_USERSPACE_PROXY + unsigned int flags = mod->user_ctx ? K_USER : 0; +#else + unsigned int flags = IS_ENABLED(CONFIG_USERSPACE) ? K_USER : 0; +#endif + + return scheduler_dp_task_init(&comp->task, SOF_UUID(dp_task_uuid), &ops, mod, + comp->ipc_config.core, TASK_DP_STACK_SIZE, flags); +} +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + +void pipeline_comp_trigger_sched_comp(struct pipeline *p, + struct comp_dev *comp, + struct pipeline_walk_context *ctx) +{ + /* only required by the scheduling component or sink component + * on pipeline without one + */ + if (dev_comp_id(p->sched_comp) != dev_comp_id(comp) && + (pipeline_id(p) == pipeline_id(p->sched_comp->pipeline) || + dev_comp_id(p->sink_comp) != dev_comp_id(comp))) + return; + + /* add for later schedule */ + list_item_append(&p->list, &ctx->pipelines); +} + +/* notify pipeline that this component requires buffers emptied/filled */ +void pipeline_schedule_copy(struct pipeline *p, uint64_t start) +{ + /* disable system agent panic for DMA driven pipelines */ + if (!pipeline_is_timer_driven(p)) + sa_set_panic_on_delay(false); + + /* + * With connected pipelines some pipelines can be re-used for multiple + * streams. E.g. if playback pipelines A and B are connected on a mixer, + * belonging to pipeline C, leading to a DAI, if A is already streaming, + * when we attempt to start B, we don't need to schedule pipeline C - + * it's already running. + */ + if (task_is_active(p->pipe_task)) + return; + + if (p->sched_next && task_is_active(p->sched_next->pipe_task)) + schedule_task_before(p->pipe_task, start, p->period, + p->sched_next->pipe_task); + else if (p->sched_prev && task_is_active(p->sched_prev->pipe_task)) + schedule_task_after(p->pipe_task, start, p->period, + p->sched_prev->pipe_task); + else + schedule_task(p->pipe_task, start, p->period); +} diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c new file mode 100644 index 000000000000..8bfdfc182912 --- /dev/null +++ b/src/audio/pipeline/pipeline-stream.c @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/lib/dai.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <rtos/interrupt.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> +#include <rtos/clk.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/module.h> +#include <rtos/kernel.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/lib/cpu-clk-manager.h> + +#ifdef CONFIG_IPC_MAJOR_4 +#include <ipc4/notification.h> +#endif + +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <sof/audio/module_adapter/module/generic.h> + +#include "../audio/copier/copier.h" + +LOG_MODULE_DECLARE(pipe, CONFIG_SOF_LOG_LEVEL); + +/* + * Check whether pipeline is incapable of acquiring data for capture. + * + * If capture START/RELEASE trigger originated on dailess pipeline and reached + * inactive pipeline as it's source, then we indicate that it's blocked. + * + * @param rsrc - component from remote pipeline serving as source to relevant + * pipeline + * @param ctx - trigger walk context + * @param dir - trigger direction + */ +static inline bool +pipeline_should_report_enodata_on_trigger(struct comp_dev *rsrc, + struct pipeline_walk_context *ctx, + int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + struct comp_dev *pipe_source = ppl_data->start->pipeline->source_comp; + + /* In IPC3, FW propagates triggers to connected pipelines, so + * it can have determistic logic to conclude no data is + * available. + * In IPC4, host controls state of each pipeline separately, + * so FW cannot reliably detect case of no data based on + * observing state of src->pipeline here. + */ +#if CONFIG_IPC_MAJOR_4 + return false; +#endif + + /* only applies to capture pipelines */ + if (dir != SOF_IPC_STREAM_CAPTURE) + return false; + + /* only applicable on trigger start/release */ + if (ppl_data->cmd != COMP_TRIGGER_START && + ppl_data->cmd != COMP_TRIGGER_RELEASE) + return false; + + /* only applies for dailess pipelines */ + if (pipe_source && dev_comp_type(pipe_source) == SOF_COMP_DAI) + return false; + + /* source pipeline may not be active since priority is not higher than current one */ + if (rsrc->pipeline->priority <= ppl_data->start->pipeline->priority) + return false; + + /* if component on which we depend to provide data is inactive, then the + * pipeline has no means of providing data + */ + if (rsrc->state != COMP_STATE_ACTIVE) + return true; + + return false; +} + +void pipeline_comp_copy_error_notify(const struct comp_dev *component, int err) +{ +#ifdef CONFIG_IPC_MAJOR_4 + send_process_data_error_notif_msg(component->ipc_config.id, err); +#endif +} + +static int pipeline_comp_copy(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + bool is_single_ppl = comp_is_single_pipeline(current, ppl_data->start); + int err; + + pipe_dbg(current->pipeline, "current->comp.id = %u, dir = %u", + dev_comp_id(current), dir); + + if (!is_single_ppl) { + pipe_dbg(current->pipeline, + "current is from another pipeline and can't be scheduled together"); + return 0; + } + + if (!comp_is_active(current)) { + pipe_dbg(current->pipeline, "current is not active"); + return 0; + } + + /* copy to downstream immediately */ + if (dir == PPL_DIR_DOWNSTREAM) { + err = comp_copy(current); + if (err < 0) { + pipeline_comp_copy_error_notify(current, err); + return err; + } + if (err == PPL_STATUS_PATH_STOP) + return err; + } + + err = pipeline_for_each_comp(current, ctx, dir); + if (err < 0 || err == PPL_STATUS_PATH_STOP) + return err; + + if (dir == PPL_DIR_UPSTREAM) { + err = comp_copy(current); + if (err < 0) + pipeline_comp_copy_error_notify(current, err); + } + + return err; +} + +/* Copy data across all pipeline components. + * For capture pipelines it always starts from source component + * and continues downstream and for playback pipelines it first + * copies sink component itself and then goes upstream. + */ +int pipeline_copy(struct pipeline *p) +{ + struct pipeline_data data; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_copy, + .comp_data = &data, + .skip_incomplete = true, + }; + struct comp_dev *start; + uint32_t dir; + int ret; + + if (p->source_comp->direction == SOF_IPC_STREAM_PLAYBACK) { + dir = PPL_DIR_UPSTREAM; + start = p->sink_comp; + } else { + dir = PPL_DIR_DOWNSTREAM; + start = p->source_comp; + } + + data.start = start; + data.p = p; + + ret = walk_ctx.comp_func(start, NULL, &walk_ctx, dir); + if (ret < 0) + pipe_err(p, "ret = %d, start->comp.id = %u, dir = %u", + ret, dev_comp_id(start), dir); + + return ret; +} + +#if CONFIG_LIBRARY && !CONFIG_LIBRARY_STATIC +/* trigger pipeline immediately in IPC context. TODO: Add support for XRUN */ +int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) +{ + int ret; + + pipe_info(p, "pipe trigger cmd %d", cmd); + + p->trigger.aborted = false; + + ret = pipeline_trigger_run(p, host, cmd); + if (ret < 0) + return ret; + + switch (cmd) { + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_START: + case COMP_TRIGGER_PRE_RELEASE: + p->status = COMP_STATE_ACTIVE; + break; + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_PAUSE: + p->status = COMP_STATE_PAUSED; + break; + default: + break; + } + + return 0; +} + +#else /* CONFIG_LIBRARY */ + +/* only collect scheduling components */ +static int pipeline_comp_list(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + bool is_single_ppl = comp_is_single_pipeline(current, ppl_data->start); + bool is_same_sched = pipeline_is_same_sched_comp(current->pipeline, + ppl_data->start->pipeline); + + /* + * We walk connected pipelines only if they have the same scheduling + * component and we aren't using IPC4. With IPC4 each pipeline receives + * commands separately so we don't need to trigger them together + */ + if (!is_single_ppl && (!is_same_sched || IPC4_MOD_ID(current->ipc_config.id))) { + pipe_dbg(current->pipeline, + "current is from another pipeline"); + return 0; + } + + /* Add scheduling components to the list */ + pipeline_comp_trigger_sched_comp(current->pipeline, current, ctx); + + return pipeline_for_each_comp(current, ctx, dir); +} + +/* build a list of connected pipelines' scheduling components and trigger them */ +static int pipeline_trigger_list(struct pipeline *p, struct comp_dev *host, int cmd) +{ + struct pipeline_data data = { + .start = host, + .cmd = cmd, + }; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_list, + .comp_data = &data, + .skip_incomplete = true, + }; + int ret; + + list_init(&walk_ctx.pipelines); + + ret = walk_ctx.comp_func(host, NULL, &walk_ctx, host->direction); + if (ret < 0) { + pipe_err(p, "ret = %d, host->comp.id = %u, cmd = %d", + ret, dev_comp_id(host), cmd); + } else { + if (cmd == COMP_TRIGGER_PRE_START) { + struct list_item *list; + struct pipeline *current, *upstream = NULL; + + /* Make sure the first pipeline has the highest priority */ + list_for_item(list, &walk_ctx.pipelines) { + current = list_item(list, struct pipeline, list); + + if (current->sched_comp->direction == SOF_IPC_STREAM_PLAYBACK) { + current->sched_prev = upstream; + if (upstream) + upstream->sched_next = current; + } else { + current->sched_next = upstream; + if (upstream) + upstream->sched_prev = current; + } + + upstream = current; + } + } + pipeline_schedule_triggered(&walk_ctx, cmd); + } + + return ret; +} + +static void pipeline_trigger_xrun(struct pipeline *p, struct comp_dev **host) +{ + /* + * XRUN can happen on a pipeline, not directly attached to the host, + * find the original one + */ + do { + /* Check the opposite direction */ + int dir = (*host)->direction == PPL_DIR_DOWNSTREAM ? PPL_DIR_UPSTREAM : + PPL_DIR_DOWNSTREAM; + struct list_item *buffer_list = comp_buffer_list(*host, dir); + struct list_item *clist; + bool found = false; + + if (list_is_empty(buffer_list)) + /* Reached the original host */ + break; + + list_for_item(clist, buffer_list) { + struct comp_buffer *buffer = buffer_from_list(clist, dir); + struct comp_dev *buffer_comp = buffer_get_comp(buffer, dir); + + switch (buffer_comp->pipeline->status) { + case COMP_STATE_ACTIVE: + case COMP_STATE_PREPARE: + found = true; + break; + } + + if (found) { + *host = (*host)->direction == PPL_DIR_DOWNSTREAM ? + buffer_comp->pipeline->source_comp : + buffer_comp->pipeline->sink_comp; + break; + } + } + + if (!found) { + /* No active pipeline found! Should never occur. */ + pipe_err(p, "No active pipeline found to link to pipeline %u!", + (*host)->pipeline->pipeline_id); + break; + } + } while (true); +} + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL +static struct ipc4_base_module_cfg *ipc4_get_base_cfg(struct comp_dev *comp) +{ + if (comp->drv->type != SOF_COMP_MODULE_ADAPTER) + return comp_get_drvdata(comp); + + struct processing_module *mod = comp_mod(comp); + struct module_data *md = &mod->priv; + + return &md->cfg.base_cfg; +} + +static void pipeline_cps_rebalance(struct pipeline *p, bool starting) +{ + unsigned int core_kcps[CONFIG_CORE_COUNT]; + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + struct list_item *clist; + const unsigned int clk_max_khz = CLK_MAX_CPU_HZ / 1000; + + for (unsigned int i = 0; i < CONFIG_CORE_COUNT; i++) + core_kcps[i] = i == PLATFORM_PRIMARY_CORE_ID ? PRIMARY_CORE_BASE_CPS_USAGE : + SECONDARY_CORE_BASE_CPS_USAGE; + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + struct comp_dev *comp = icd->cd; + + /* + * When a pipeline is started, its components have state PREPARE, when + * a pipeline is terminated, its components still have state ACTIVE + */ + if ((comp->state == COMP_STATE_ACTIVE && + (starting || comp->pipeline != p)) || + ((comp->state == COMP_STATE_PREPARE || comp->state == COMP_STATE_PAUSED) && + starting && comp->pipeline == p)) { + struct ipc4_base_module_cfg *cd = ipc4_get_base_cfg(comp); + + if (cd->cpc && core_kcps[icd->core] < clk_max_khz) + core_kcps[icd->core] += cd->cpc; + else + core_kcps[icd->core] = clk_max_khz; + } + } + + for (int i = 0; i < arch_num_cpus(); i++) { + int delta_kcps = core_kcps[i] - core_kcps_get(i); + + tr_dbg(pipe, "Proposed KCPS consumption: %d, core: %d, delta: %d", + core_kcps[i], i, delta_kcps); + if (delta_kcps) + core_kcps_adjust(i, delta_kcps); + } +} +#endif /* CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL */ + +/* trigger pipeline in IPC context */ +int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd) +{ + int ret; +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + bool trigger_first = false; + uint32_t flags = 0; +#endif + pipe_info(p, "pipe trigger cmd %d", cmd); + + p->trigger.aborted = false; + + switch (cmd) { + case COMP_TRIGGER_PAUSE: +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + trigger_first = true; + COMPILER_FALLTHROUGH; +#endif + case COMP_TRIGGER_STOP: + if (p->status == COMP_STATE_PAUSED || p->xrun_bytes) { + /* The task isn't running, trigger inline */ + ret = pipeline_trigger_run(p, host, cmd); + return ret < 0 ? ret : 0; + } + + COMPILER_FALLTHROUGH; + case COMP_TRIGGER_XRUN: + if (cmd == COMP_TRIGGER_XRUN) + pipeline_trigger_xrun(p, &host); + + COMPILER_FALLTHROUGH; + case COMP_TRIGGER_PRE_RELEASE: + case COMP_TRIGGER_PRE_START: + /* Add all connected pipelines to the list and trigger them all */ +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + flags = irq_lock(); + /* setup walking ctx for removing consumption */ + if (!trigger_first) + pipeline_cps_rebalance(p, true); +#endif + ret = pipeline_trigger_list(p, host, cmd); + if (ret < 0) { +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + irq_unlock(flags); +#endif + return ret; + } +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + if (trigger_first) + pipeline_cps_rebalance(p, false); + irq_unlock(flags); +#endif + /* IPC response will be sent from the task, unless it was paused */ + return PPL_STATUS_SCHEDULED; + } + + return 0; +} +#endif /* CONFIG_LIBRARY */ + +/* Runs in IPC or in pipeline task context */ +static int pipeline_comp_trigger(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + bool is_single_ppl = comp_is_single_pipeline(current, ppl_data->start); + bool is_same_sched; + int err; + + pipe_dbg(current->pipeline, + "current->comp.id = %u, dir = %u", + dev_comp_id(current), dir); + + switch (ppl_data->cmd) { + case COMP_TRIGGER_PRE_RELEASE: + case COMP_TRIGGER_PRE_START: + if (comp_get_endpoint_type(current) == COMP_ENDPOINT_DAI) { + /* + * Initialization delay is only used with SSP, where we + * don't use more than one DAI per copier + */ + struct dai_data *dd; +#if CONFIG_IPC_MAJOR_3 + dd = comp_get_drvdata(current); +#elif CONFIG_IPC_MAJOR_4 + struct processing_module *mod = comp_mod(current); + struct copier_data *cd = module_get_private_data(mod); + + dd = cd->dd[0]; +#else +#error Unknown IPC major version +#endif + ppl_data->delay_ms = dai_get_init_delay_ms(dd->dai); + } + break; + default: + return -EINVAL; + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_RELEASE: + case COMP_TRIGGER_START: + break; + } + + is_same_sched = pipeline_is_same_sched_comp(current->pipeline, + ppl_data->start->pipeline); + + /* trigger should propagate to the connected pipelines, + * which need to be scheduled together + * + * IPC4 has a SET_PIPELINE_STATE for each pipeline, so FW + * should not propagate triggers on its own. + * IPC3 has commands only for graph edges, so propagation is + * needed in many cases. + */ + if (!is_single_ppl && (!is_same_sched || IS_ENABLED(CONFIG_IPC_MAJOR_4))) { + pipe_dbg(current->pipeline, + "current is from another pipeline"); + + if (pipeline_should_report_enodata_on_trigger(current, ctx, dir)) + return -ENODATA; + + return 0; + } + + current->pipeline->trigger.pending = false; + + /* send command to the component and update pipeline state */ + err = comp_trigger(current, ppl_data->cmd); + switch (err) { + case 0: + break; + case PPL_STATUS_PATH_STOP: + current->pipeline->trigger.aborted = true; + COMPILER_FALLTHROUGH; + case PPL_STATUS_PATH_TERMINATE: + return PPL_STATUS_PATH_STOP; + default: + return err; + } + + switch (ppl_data->cmd) { + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + if (pipeline_is_timer_driven(current->pipeline)) + current->pipeline->status = COMP_STATE_PAUSED; + } + + /* + * Add scheduling components to the list. This is only needed for + * asynchronous flows. + */ + if (!pipeline_is_timer_driven(current->pipeline)) + pipeline_comp_trigger_sched_comp(current->pipeline, current, ctx); + + return pipeline_for_each_comp(current, ctx, dir); +} + +/* actually execute pipeline trigger, including components: either in IPC or in task context */ +int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd) +{ + struct pipeline_data data = { + .start = host, + .cmd = cmd, + }; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_trigger, + .comp_data = &data, + .skip_incomplete = true, + }; + int ret; + + pipe_dbg(p, "execute trigger cmd %d on pipe %u", cmd, p->pipeline_id); + + list_init(&walk_ctx.pipelines); + p->trigger.aborted = false; + + /* handle pipeline global checks before going into each components */ + if (p->xrun_bytes) { + ret = pipeline_xrun_handle_trigger(p, cmd); + if (ret < 0) { + pipe_err(p, "xrun handle: ret = %d", ret); + return ret; + } + + if (ret == PPL_STATUS_PATH_STOP) + /* no further action needed*/ + return pipeline_is_timer_driven(p); + } + + ret = walk_ctx.comp_func(host, NULL, &walk_ctx, host->direction); + if (ret < 0) { + pipe_err(p, "ret = %d, host->comp.id = %u, cmd = %d", + ret, dev_comp_id(host), cmd); + goto out; + } + + switch (cmd) { + case COMP_TRIGGER_PRE_START: + data.cmd = COMP_TRIGGER_START; + break; + case COMP_TRIGGER_PRE_RELEASE: + data.cmd = COMP_TRIGGER_RELEASE; + } + + if (data.cmd != cmd) { + if (data.delay_ms && pipeline_is_timer_driven(p)) { + /* The task will skip .delay periods before processing the next command */ + p->trigger.delay = (data.delay_ms * 1000 + p->period - 1) / p->period; + p->trigger.cmd = data.cmd; + + return 0; + } + + list_init(&walk_ctx.pipelines); + + if (data.delay_ms) + k_msleep(data.delay_ms); + + ret = walk_ctx.comp_func(host, NULL, &walk_ctx, host->direction); + if (ret < 0) + pipe_err(p, "ret = %d, host->comp.id = %u, cmd = %d", + ret, dev_comp_id(host), cmd); + else if (ret == PPL_STATUS_PATH_STOP) + ret = 0; + + if (pipeline_is_timer_driven(p)) + return ret; + } + +out: + /* + * When called from the pipeline task, pipeline_comp_trigger() will not + * add pipelines to the list, so pipeline_schedule_triggered() will have + * no effect. + */ + pipeline_schedule_triggered(&walk_ctx, cmd); + + return ret; +} + +/* Get the timestamps for host and first active DAI found. */ +void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + struct comp_dev *dai; + + platform_host_timestamp(host, posn); + + if (host->direction == SOF_IPC_STREAM_PLAYBACK) + dai = pipeline_get_dai_comp(host->pipeline->pipeline_id, PPL_DIR_DOWNSTREAM); + else + dai = pipeline_get_dai_comp(host->pipeline->pipeline_id, PPL_DIR_UPSTREAM); + + if (!dai) { + pipe_dbg(p, "DAI position update failed"); + return; + } + + platform_dai_timestamp(dai, posn); + + /* set timestamp resolution */ + posn->timestamp_ns = p->period * 1000; +} diff --git a/src/audio/pipeline/pipeline-xrun.c b/src/audio/pipeline/pipeline-xrun.c new file mode 100644 index 000000000000..c535ddbb84a1 --- /dev/null +++ b/src/audio/pipeline/pipeline-xrun.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(pipe, CONFIG_SOF_LOG_LEVEL); + +/* + * This flag disables firmware-side xrun recovery. + * It should remain enabled in the situation when the + * recovery is delegated to the outside of firmware. + */ +#define NO_XRUN_RECOVERY 1 + +#if CONFIG_IPC_MAJOR_3 + +/* This function always returns success */ +static int pipeline_comp_xrun(struct comp_dev *current, + struct comp_buffer *calling_buf, + struct pipeline_walk_context *ctx, int dir) +{ + struct pipeline_data *ppl_data = ctx->comp_data; + + if (dev_comp_type(current) == SOF_COMP_HOST) { + /* get host timestamps */ + platform_host_timestamp(current, ppl_data->posn); + + /* send XRUN to host */ + mailbox_stream_write(ppl_data->p->posn_offset, ppl_data->posn, + sizeof(*ppl_data->posn)); + ipc_msg_send(ppl_data->p->msg, ppl_data->posn, true); + } + + return pipeline_for_each_comp(current, ctx, dir); +} + +#endif /* CONFIG_IPC_MAJOR_3 */ + +#if NO_XRUN_RECOVERY +/* recover the pipeline from a XRUN condition */ +int pipeline_xrun_recover(struct pipeline *p) +{ + pipeline_reset(p, p->source_comp); + return -EINVAL; +} + +#else +/* recover the pipeline from a XRUN condition */ +int pipeline_xrun_recover(struct pipeline *p) +{ + int ret; + + pipe_err(p, "entry"); + + /* prepare the pipeline */ + ret = pipeline_prepare(p, p->source_comp); + if (ret < 0) { + pipe_err(p, "pipeline_prepare() failed, ret = %d", + ret); + return ret; + } + + /* reset xrun status as we already in prepared */ + p->xrun_bytes = 0; + + /* restart pipeline comps */ + ret = pipeline_trigger(p, p->source_comp, COMP_TRIGGER_START); + if (ret < 0) { + pipe_err(p, "pipeline_trigger() failed, ret = %d", + ret); + return ret; + } + + return 0; +} +#endif + +int pipeline_xrun_set_limit(struct pipeline *p, uint32_t xrun_limit_usecs) +{ + /* TODO: these could be validated against min/max permissible values */ + p->xrun_limit_usecs = xrun_limit_usecs; + return 0; +} + +/* + * trigger handler for pipelines in xrun, used for recovery from host only. + * return values: + * 0 -- success, further trigger in caller needed. + * PPL_STATUS_PATH_STOP -- done, no more further trigger needed. + * minus -- failed, caller should return failure. + */ +int pipeline_xrun_handle_trigger(struct pipeline *p, int cmd) +{ + int ret = 0; + + /* it is expected in paused status for xrun pipeline */ + if (!p->xrun_bytes || p->status != COMP_STATE_PAUSED) + return 0; + + /* in xrun, handle start/stop trigger */ + switch (cmd) { + case COMP_TRIGGER_START: + /* in xrun, prepare before trigger start needed */ + pipe_info(p, "in xrun, prepare it first"); + /* prepare the pipeline */ + ret = pipeline_prepare(p, p->source_comp); + if (ret < 0) { + pipe_err(p, "prepare: ret = %d", ret); + return ret; + } + /* now ready for start, clear xrun_bytes */ + p->xrun_bytes = 0; + break; + case COMP_TRIGGER_STOP: + /* in xrun, suppose pipeline is already stopped, ignore it */ + pipe_info(p, "already stopped in xrun"); + /* no more further trigger stop needed */ + ret = PPL_STATUS_PATH_STOP; + break; + } + + return ret; +} + +/* Send an XRUN to each host for this component. */ +void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, + int32_t bytes) +{ +#if CONFIG_IPC_MAJOR_3 + struct pipeline_data data; + struct pipeline_walk_context walk_ctx = { + .comp_func = pipeline_comp_xrun, + .comp_data = &data, + .skip_incomplete = true, + }; + struct sof_ipc_stream_posn posn; +#endif + int ret; + + /* don't flood host */ + if (p->xrun_bytes) + return; + + /* only send when we are running */ + if (dev->state != COMP_STATE_ACTIVE) + return; + + /* notify all pipeline comps we are in XRUN, and stop copying */ + ret = pipeline_trigger(p, p->source_comp, COMP_TRIGGER_XRUN); + if (ret < 0) + pipe_err(p, "Pipelines notification about XRUN failed, ret = %d", + ret); + + /* + * The IPC position info reporting via window2 is only + * used for IPC3 and e.g. in IPC4 this is conflicting + * with the debug window usages (logging, debug, ..) + */ +#if CONFIG_IPC_MAJOR_3 + memset(&posn, 0, sizeof(posn)); + ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN, + dev_comp_id(dev)); + p->xrun_bytes = bytes; + posn.xrun_size = bytes; + posn.xrun_comp_id = dev_comp_id(dev); + data.posn = &posn; + data.p = p; + + walk_ctx.comp_func(dev, NULL, &walk_ctx, dev->direction); +#endif +} diff --git a/src/audio/pipeline_static.c b/src/audio/pipeline_static.c deleted file mode 100644 index a3e352be5195..000000000000 --- a/src/audio/pipeline_static.c +++ /dev/null @@ -1,439 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.comel.com> - -/* - * Static pipeline definition. This will be the default platform pipeline - * definition if no pipeline is specified by driver topology. - */ - -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/drivers/ipc.h> -#include <sof/schedule/task.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <stdint.h> - -/* 2 * 32 bit*/ -#define PLATFORM_INT_FRAME_SIZE 8 -/* 2 * 16 bit*/ -#define PLATFORM_HOST_FRAME_SIZE 4 -/* 2 * 24 (32) bit*/ -#define PLATFORM_DAI_FRAME_SIZE 8 - -/* Platform Host DMA buffer config - these should align with DMA engine */ -#define PLAT_HOST_PERIOD_FRAMES 48 /* must be multiple of DMA burst size */ -#define PLAT_HOST_PERIODS 2 /* give enough latency for DMA refill */ - -/* Platform Dev DMA buffer config - these should align with DMA engine */ -#define PLAT_DAI_PERIOD_FRAMES 48 /* Must be multiple of DMA+DEV burst size */ -#define PLAT_DAI_PERIODS 2 /* give enough latency for DMA refill */ -#define PLAT_DAI_SCHED 1000 /* scheduling time in usecs */ - -/* Platform internal buffer config - these should align with DMA engine */ -#define PLAT_INT_PERIOD_FRAMES 48 /* must be multiple of DMA+DEV burst size */ -#define PLAT_INT_PERIODS 2 /* give enough latency for DMA refill */ - -/* default static pipeline SSP port - not used for dynamic pipes */ -#define PLATFORM_SSP_PORT 2 - -/* default SSP stream format - need aligned with codec setting*/ -#define PLATFORM_SSP_STREAM_FORMAT SOF_IPC_FRAME_S24_4LE - -/* - * Static Buffer Convenience Constructors. - */ -#define SPIPE_BUFFER(bid, bsize) \ - {.comp.id = bid, .size = bsize} -#define SPIPE_COMP_CONNECT(source, sink) \ - {.source_id = source, .sink_id = sink} - -/* - * Static Component Convenience Constructors. - */ -#define SPIPE_COMP(cid, ctype, csize) \ - {.id = cid, .type = ctype, .hdr.size = sizeof(struct csize)} -#define SPIPE_HOST(scomp, hno_irq, hdmac, hchan, hconfig) \ - {.comp = scomp, .no_irq = hno_irq} -#define SPIPE_DAI(scomp, ddai_type, ddai_idx, ddmac, dchan, dconfig) \ - {.comp = scomp, .type = ddai_type, .dai_index = ddai_idx} -#define SPIPE_VOL(scomp, vmin, vmax) \ - {.comp = scomp, .min_value = vmin, .max_value = vmax} -#define SPIPE_MIX(scomp) {.comp = scomp} -#define SPIPE_SRC(scomp) {.comp = scomp} -#define SPIPE_TONE(scomp) {.comp = scomp} - -/* - * Static Pipeline Convenience Constructor - */ -#define SPIPE_PIPE(pid, pcore, pperiod, ppriority) \ - {.pipeline_id = pid, .core = pcore, .period = pperiod, \ - .priority = ppriority} -#define SPIPE_PIPE_CONNECT(psource, bsource, bid, psink, bsink) \ - {.pipeline_source_id = psource, .comp_source_id = bsource, \ - .buffer_id = bid, .pipeline_sink_id = psink, .comp_sink_id = bsink} - -/* - * Static pipeline container and constructor - */ - -struct scomps { - struct sof_ipc_comp *comps; - uint32_t num_comps; -}; - -#define SCOMP(ccomps) \ - {.comps = (struct sof_ipc_comp *)(ccomps), \ - .num_comps = ARRAY_SIZE(ccomps)} - -struct spipe { - struct scomps *scomps; - uint32_t num_scomps; - struct sof_ipc_buffer *buffer; - uint32_t num_buffers; - struct sof_ipc_pipe_comp_connect *connect; - uint32_t num_connections; -}; - -#define SPIPE(ncomp, sbuffer, sconnect) \ - {.scomps = ncomp, .num_scomps = ARRAY_SIZE(ncomp), \ - .buffer = sbuffer, .num_buffers = ARRAY_SIZE(sbuffer), \ - .connect = sconnect, .num_connections = ARRAY_SIZE(sconnect)} - -/* - * Components used in static pipeline 0. - */ - -static struct sof_ipc_comp_host host_p0[] = { - /* ID = 0 */ - SPIPE_HOST(SPIPE_COMP(0, SOF_COMP_HOST, sof_ipc_comp_host), 0, 0, 1, 0), - /* ID = 2 */ - SPIPE_HOST(SPIPE_COMP(2, SOF_COMP_HOST, sof_ipc_comp_host), 0, 0, 2, 0), - /* ID = 9 */ - SPIPE_HOST(SPIPE_COMP(9, SOF_COMP_HOST, sof_ipc_comp_host), 0, 0, 3, 0), -}; - -static struct sof_ipc_comp_volume volume_p0[] = { - /* ID = 1 */ - SPIPE_VOL(SPIPE_COMP(1, SOF_COMP_VOLUME, sof_ipc_comp_volume), 0, - 0xffffffff), - /* ID = 3 */ - SPIPE_VOL(SPIPE_COMP(3, SOF_COMP_VOLUME, sof_ipc_comp_volume), 0, - 0xffffffff), - /* ID = 5 */ - SPIPE_VOL(SPIPE_COMP(5, SOF_COMP_VOLUME, sof_ipc_comp_volume), 0, - 0xffffffff), - /* ID = 8 */ - SPIPE_VOL(SPIPE_COMP(8, SOF_COMP_VOLUME, sof_ipc_comp_volume), 0, - 0xffffffff), -}; - -static struct sof_ipc_comp_dai dai_p0[] = { - SPIPE_DAI(SPIPE_COMP(6, SOF_COMP_DAI, sof_ipc_comp_dai), - SOF_DAI_INTEL_SSP, PLATFORM_SSP_PORT, 1, 0, 0), /* ID = 6 */ - SPIPE_DAI(SPIPE_COMP(7, SOF_COMP_DAI, sof_ipc_comp_dai), - SOF_DAI_INTEL_SSP, PLATFORM_SSP_PORT, 1, 1, 0), /* ID = 7 */ -}; - -static struct sof_ipc_comp_mixer mixer_p0[] = { - /* ID = 4 */ - SPIPE_MIX(SPIPE_COMP(4, SOF_COMP_MIXER, sof_ipc_comp_mixer)), -}; - -static struct scomps pipe0_scomps[] = { - SCOMP(host_p0), - SCOMP(volume_p0), - SCOMP(dai_p0), - SCOMP(mixer_p0), -}; - -/* - * Components used in static pipeline 1. - */ - -static struct sof_ipc_comp_host host_p1[] = { - /* ID = 10 */ - SPIPE_HOST(SPIPE_COMP(10, SOF_COMP_HOST, sof_ipc_comp_host), 0, 0, 4, - 0), -}; - -static struct sof_ipc_comp_volume volume_p1[] = { - /* ID = 12 */ - SPIPE_VOL(SPIPE_COMP(12, SOF_COMP_VOLUME, sof_ipc_comp_volume), 0, - 0xffffffff), -}; - -static struct sof_ipc_comp_src src_p1[] = { - /* ID = 11 */ - SPIPE_SRC(SPIPE_COMP(11, SOF_COMP_SRC, sof_ipc_comp_src)), -}; - -static struct scomps pipe1_scomps[] = { - SCOMP(host_p1), - SCOMP(volume_p1), - SCOMP(src_p1), -}; - -/* - * Components used in static pipeline 2. - */ - -static struct sof_ipc_comp_tone tone_p2[] = { - /* ID = 13 */ - SPIPE_TONE(SPIPE_COMP(13, SOF_COMP_HOST, sof_ipc_comp_tone)), -}; - -static struct sof_ipc_comp_volume volume_p2[] = { - /* ID = 15 */ - SPIPE_VOL(SPIPE_COMP(15, SOF_COMP_VOLUME, sof_ipc_comp_volume), 0, - 0xffffffff), -}; - -static struct sof_ipc_comp_src src_p2[] = { - /* ID = 14 */ - SPIPE_SRC(SPIPE_COMP(14, SOF_COMP_SRC, sof_ipc_comp_src)), -}; - -static struct scomps pipe2_scomps[] = { - SCOMP(tone_p2), - SCOMP(volume_p2), - SCOMP(src_p2), -}; - -/* Host facing buffer */ -#define HOST_PERIOD_SIZE \ - (PLAT_HOST_PERIOD_FRAMES * PLATFORM_HOST_FRAME_SIZE) - -/* Device facing buffer */ -#define DAI_PERIOD_SIZE \ - (PLAT_DAI_PERIOD_FRAMES * PLATFORM_DAI_FRAME_SIZE) - -/* Internal buffer */ -#define INT_PERIOD_SIZE \ - (PLAT_INT_PERIOD_FRAMES * PLATFORM_INT_FRAME_SIZE) - -/* - * Buffers used in static pipeline 0. - */ -static struct sof_ipc_buffer buffer0[] = { - /* B0 - LL Playback - PCM 0 Host0 -> Volume1 */ - SPIPE_BUFFER(0, HOST_PERIOD_SIZE * 2), - - /* B1 - LL Playback - PCM 1 - Host2 -> Volume3 */ - SPIPE_BUFFER(1, HOST_PERIOD_SIZE * 2), - - /* B2 Volume1 -> Mixer4 */ - SPIPE_BUFFER(2, INT_PERIOD_SIZE * 1), - - /* B3 Volume3 -> Mixer4 */ - SPIPE_BUFFER(3, INT_PERIOD_SIZE * 1), - - /* B4 Mixer4 -> Volume 5 */ - SPIPE_BUFFER(4, INT_PERIOD_SIZE * 1), - - /* B5 - DAI Playback - Volume5 -> DAI6 */ - SPIPE_BUFFER(5, DAI_PERIOD_SIZE * 2), - - /* B6 - DAI Capture - DAI7 - > Volume8 */ - SPIPE_BUFFER(6, DAI_PERIOD_SIZE * 2), - - /* B7 - PCM0 - Capture LL - Volume8 -> Host9 */ - SPIPE_BUFFER(7, HOST_PERIOD_SIZE * 1), -}; - -/* - * Buffers used in static pipeline 1. - */ -static struct sof_ipc_buffer buffer1[] = { - /* B8 - Playback - PCM 3 - Host10 -> SRC11 */ - SPIPE_BUFFER(8, HOST_PERIOD_SIZE * 16), - - /* B9 SRC11 -> Volume12 */ - SPIPE_BUFFER(9, INT_PERIOD_SIZE * 2), - - /* B10 Volume12 -> Mixer4 */ - SPIPE_BUFFER(10, INT_PERIOD_SIZE * 2), -}; - -/* - * Buffers used in static pipeline 2. - */ -static struct sof_ipc_buffer buffer2[] = { - /* B11 - tone13 -> SRC14 */ - SPIPE_BUFFER(11, HOST_PERIOD_SIZE * 16), - - /* B12 SRC14 -> Volume15 */ - SPIPE_BUFFER(12, INT_PERIOD_SIZE * 2), - - /* B13 Volume15 -> Mixer4 */ - SPIPE_BUFFER(13, INT_PERIOD_SIZE * 2), -}; - -/* - * Pipeline 0 - * - * Two Low Latency PCMs mixed into single SSP output. - * - * host PCM0(0)-B0->volume(1)-B2--+ - * |--mixer(4) --B4--> volume(5) --B5--> SSPx(6) - * host PCM1(2)-B1->volume(3)-B3--+ - * | - * pipeline 1 >-----+ - * | - * pipeline 2 >-----+ - * - * host PCM0(9) <--B7-- volume(8) <--B6-- SSPx(7) - * - * - * Pipeline 1 - * - * One PCM with SRC that is a Mixer 4 source - * - * host PCM2(10) --B8 --> SRC(11) --B9--> volume(12) --B10 --> Pipeline 0 - * - * - * Pipeline 2 - * - * Test Pipeline - * - * tone(13) --- B11 ---> SRC(14) --B12---> volume(15) --B13 ---> Pipeline 0 - */ - -/* pipeline 0 component/buffer connections */ -static struct sof_ipc_pipe_comp_connect c_connect0[] = { - SPIPE_COMP_CONNECT(0, 1), /* Host0 -> B0 -> Volume1 */ - SPIPE_COMP_CONNECT(2, 3), /* Host2 -> B1 -> Volume3 */ - SPIPE_COMP_CONNECT(1, 4), /* Volume1 -> B2 -> Mixer4 */ - SPIPE_COMP_CONNECT(3, 4), /* Volume3 -> B3 -> Mixer4 */ - SPIPE_COMP_CONNECT(4, 5), /* Mixer4 -> B4 -> Volume5 */ - SPIPE_COMP_CONNECT(5, 6), /* Volume5 -> B5 -> DAI6 */ - SPIPE_COMP_CONNECT(7, 8), /* DAI7 -> B6 -> Volume8 */ - SPIPE_COMP_CONNECT(8, 9), /* Volume8 -> B7 -> host9 */ -}; - -/* pipeline 1 component/buffer connections */ -static struct sof_ipc_pipe_comp_connect c_connect1[] = { - SPIPE_COMP_CONNECT(10, 11), /* Host10 -> B8 -> SRC11 */ - SPIPE_COMP_CONNECT(11, 12), /* SRC11 -> B9 -> Volume12 */ -}; - -/* pipeline 2 component/buffer connections */ -static struct sof_ipc_pipe_comp_connect c_connect2[] = { - SPIPE_COMP_CONNECT(13, 14), /* tone13 -> B11 -> SRC14 */ - SPIPE_COMP_CONNECT(14, 15), /* SRC14 -> B12 -> Volume15 */ -}; - -/* pipeline connections to other pipelines */ -//static struct sof_ipc_pipe_pipe_connect p_connect[] = { -// /* p1 volume12 -> B10 -> p0 Mixer4 */ -// SPIPE_PIPE_CONNECT(1, 12, 10, 0, 4), -// /* p2 Volume15 -> B13 -> p0 Mixer4 */ -// SPIPE_PIPE_CONNECT(2, 15, 13, 0, 4), -//}; - -/* the static pipelines */ -static struct spipe spipe[] = { - SPIPE(pipe0_scomps, buffer0, c_connect0), - SPIPE(pipe1_scomps, buffer1, c_connect1), - SPIPE(pipe2_scomps, buffer2, c_connect2), -}; - -/* pipelines */ -struct sof_ipc_pipe_new pipeline[] = { - SPIPE_PIPE(0, 0, 1000, SOF_TASK_PRI_HIGH),/* high pri - 1ms period */ -// SPIPE_PIPE(1, 0, 4000, SOF_TASK_PRI_MED),/* med pri - 4ms period */ -// SPIPE_PIPE(2, 0, 5000, SOF_TASK_PRI_LOW),/* low pri - 5ms period */ -}; - -int init_static_pipeline(struct ipc *ipc) -{ - struct scomps *sc; - struct sof_ipc_comp *c; - int i; - int j; - int k; - int ret; - - /* create the pipelines */ - for (i = 0; i < ARRAY_SIZE(pipeline); i++) { - - /* create the pipeline */ - ret = ipc_pipeline_new(ipc, &pipeline[i]); - if (ret < 0) - goto error; - - sc = spipe[i].scomps; - - /* register components for this pipeline */ - for (j = 0; j < spipe[i].num_scomps; j++) { - - /* all pipeline components have same header */ - c = sc[j].comps; - - for (k = 0; k < sc[j].num_comps; k++) { - - ret = ipc_comp_new(ipc, c); - if (ret < 0) - goto error; - - /* next component - sizes not constant */ - c = (struct sof_ipc_comp *) - ((char *)c + c->hdr.size); - } - } - - /* register buffers for this pipeline */ - for (j = 0; j < spipe[i].num_buffers; j++) { - ret = ipc_buffer_new(ipc, &spipe[i].buffer[j]); - if (ret < 0) - goto error; - } - - /* connect components in this pipeline */ - for (j = 0; j < spipe[i].num_connections; j++) { - ret = ipc_comp_connect(ipc, &spipe[i].connect[j]); - if (ret < 0) - goto error; - } - } - -#if 0 - /* connect the pipelines */ - for (i = 0; i < ARRAY_SIZE(p_connect); i++) { - ret = ipc_pipe_connect(ipc, &p_connect[i]); - if (ret < 0) - goto error; - } -#endif - /* pipelines now ready for params, prepare and cmds */ - return 0; - -error: - pipe_cl_err("init_static_pipeline() error"); - - for (i = 0; i < ARRAY_SIZE(pipeline); i++) { - - /* free pipeline */ - ipc_pipeline_free(ipc, pipeline[i].pipeline_id); - - /* free components */ - for (j = 0; j < spipe[i].num_scomps; j++) { - sc = spipe[i].scomps; - for (k = 0; k < sc->num_comps; k++) - ipc_comp_free(ipc, - spipe[i].scomps[j].comps[k].id); - } - - /* free buffers */ - for (j = 0; j < spipe[i].num_buffers; j++) - ipc_buffer_free(ipc, spipe[i].buffer[j].comp.id); - } - - return ret; -} diff --git a/src/audio/rtnr/CMakeLists.txt b/src/audio/rtnr/CMakeLists.txt new file mode 100644 index 000000000000..e3bc38d1f51c --- /dev/null +++ b/src/audio/rtnr/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_RTNR STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/rtnr_llext) + add_dependencies(app rtnr) + return() +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + zephyr_library_sources(rtnr.c) + zephyr_library_sources_ifdef(CONFIG_COMP_RTNR_STUB rtnr_stub.c) + +else() ### library, e.g. testbench or plugin ### + + add_local_sources(sof rtnr.c) + if (CONFIG_COMP_RTNR_STUB) + add_local_sources(sof rtnr_stub.c) + endif() + +endif() diff --git a/src/audio/rtnr/Kconfig b/src/audio/rtnr/Kconfig new file mode 100644 index 000000000000..0b872ffb44e8 --- /dev/null +++ b/src/audio/rtnr/Kconfig @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_RTNR + tristate "RTNR component" + select COMP_BLOB + select COMP_RTNR_STUB if COMP_STUBS + help + Select for Realtek noise reduction/suppression(NR/NS) component. + Noise Suppression technology reduces stationary and transient noises in + single-channel speech signals, which increases the signal-to-noise ratio, + improves speech intelligibility and reduces listening fatigue. It estimates + ambient noise and signal levels and then passes or attenuates the signals + according to improve signal-to-noise ratios. The feature links to a + proprietary binary libSOF_RTK_MA_API.a, libSuite_rename.a, libNet.a and libPreset.a. + Please contact antz0525@realtek.com for any question about the binary. + +config COMP_RTNR_STUB + bool "RTNR component stub" + select COMP_BLOB + depends on COMP_RTNR + help + Stub out the RTNR library for testing and CI purposes. diff --git a/src/audio/rtnr/README.md b/src/audio/rtnr/README.md new file mode 100644 index 000000000000..2dd6d718f15f --- /dev/null +++ b/src/audio/rtnr/README.md @@ -0,0 +1,13 @@ +# Real-Time Noise Reduction (RTNR) Architecture + +This directory houses the RTNR component. + +## Overview + +Reduces steady-state or transient background noise from an input signal path in real time. + +## Configuration and Scripts + +- **Kconfig**: Dictates the build behavior for the Realtek noise reduction and suppression components (`COMP_RTNR`). The feature depends heavily on specific, proprietary Realtek libraries (`libSOF_RTK_MA_API.a`, etc.). Configures stubs (`COMP_RTNR_STUB`) to circumvent library unavailability during testing and CI logic runs. +- **CMakeLists.txt**: Injects `rtnr.c` directly into Zephyr builds and gracefully falls back to Zephyr external libraries handling. Offers thorough `llext` generation and cleanly wraps stub testing modules `rtnr_stub.c`. +- **rtnr.toml**: Defines topology properties for the loadable RTNR logic (UUID binding, generic pinning setups). diff --git a/src/audio/rtnr/llext/CMakeLists.txt b/src/audio/rtnr/llext/CMakeLists.txt new file mode 100644 index 000000000000..3d028ace0adf --- /dev/null +++ b/src/audio/rtnr/llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_COMP_RTNR_STUB) +sof_llext_build("rtnr" + SOURCES ../rtnr.c + ../rtnr_stub.c +) +else() +message(FATAL_ERROR "Add library linking support in src/audio/rtnr/llext/CMakeFiles.txt") +endif() diff --git a/src/audio/rtnr/llext/llext.toml.h b/src/audio/rtnr/llext/llext.toml.h new file mode 100644 index 000000000000..f1eca55c0a61 --- /dev/null +++ b/src/audio/rtnr/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../rtnr.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/rtnr/rtklib/mt8195/CMakeLists.txt b/src/audio/rtnr/rtklib/mt8195/CMakeLists.txt new file mode 100644 index 000000000000..c23f031d038d --- /dev/null +++ b/src/audio/rtnr/rtklib/mt8195/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +sof_add_static_library(SOF_RTK_MA_API libSOF_RTK_MA_API.a) +sof_add_static_library(Suite_MaLtFP libSuite_MaLtFP.a) +sof_add_static_library(Preset libPreset.a) +sof_add_static_library(utils libutils.a) + + diff --git a/src/audio/rtnr/rtklib/mt8195/README.txt b/src/audio/rtnr/rtklib/mt8195/README.txt new file mode 100644 index 000000000000..01f94e66b510 --- /dev/null +++ b/src/audio/rtnr/rtklib/mt8195/README.txt @@ -0,0 +1 @@ +Put libSOF_RTK_MA_API.a, libSuite_MaLtFP.a, libPreset.a and libutils.a here. diff --git a/src/audio/rtnr/rtklib/tgl/CMakeLists.txt b/src/audio/rtnr/rtklib/tgl/CMakeLists.txt new file mode 100644 index 000000000000..aacab40dff66 --- /dev/null +++ b/src/audio/rtnr/rtklib/tgl/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +sof_add_static_library(SOF_RTK_MA_API libSOF_RTK_MA_API.a) +sof_add_static_library(Suite_MaLtFP libSuite_MaLtFP.a) +sof_add_static_library(Preset libPreset.a) +sof_add_static_library(utils libutils.a) + diff --git a/src/audio/rtnr/rtklib/tgl/README.txt b/src/audio/rtnr/rtklib/tgl/README.txt new file mode 100644 index 000000000000..01f94e66b510 --- /dev/null +++ b/src/audio/rtnr/rtklib/tgl/README.txt @@ -0,0 +1 @@ +Put libSOF_RTK_MA_API.a, libSuite_MaLtFP.a, libPreset.a and libutils.a here. diff --git a/src/audio/rtnr/rtnr.c b/src/audio/rtnr/rtnr.c new file mode 100644 index 000000000000..45ff62a60f8d --- /dev/null +++ b/src/audio/rtnr/rtnr.c @@ -0,0 +1,893 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. + * + * Author: Ming Jen Tai <mingjen_tai@realtek.com> + */ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/rtnr/rtnr.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include <sof/audio/rtnr/rtklib/include/RTK_MA_API.h> + +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/header.h> +#endif + +#define MicNum 2 +#define SpkNum 2 + +#define RTNR_BLK_LENGTH 4 /* Must be power of 2 */ +#define RTNR_BLK_LENGTH_MASK (RTNR_BLK_LENGTH - 1) + +/* RTNR configuration & data */ +#define SOF_RTNR_CONFIG 0 +#define SOF_RTNR_DATA 1 + +/* ID for RTNR data */ +#define RTNR_DATA_ID_PRESET 12345678 + +/** \brief RTNR processing functions map item. */ +struct rtnr_func_map { + enum sof_ipc_frame fmt; /**< source frame format */ + rtnr_func func; /**< processing function */ +}; + +LOG_MODULE_REGISTER(rtnr, CONFIG_SOF_LOG_LEVEL); + +/* UUID 5c7ca334-e15d-11eb-ba80-0242ac130004 */ +SOF_DEFINE_REG_UUID(rtnr); + +DECLARE_TR_CTX(rtnr_tr, SOF_UUID(rtnr_uuid), LOG_LEVEL_INFO); + +/* Generic processing */ + +/* Static functions */ +static int rtnr_set_config_bytes(struct processing_module *mod, + const unsigned char *data, uint32_t size); + +/* Called by the processing library for debugging purpose */ +void rtnr_printf(int a, int b, int c, int d, int e) +{ + switch (a) { + case 0xa: + tr_info(&rtnr_tr, "1st=%08x, 2nd=%08x, 3rd=%08x, 4st=%08x", + b, c, d, e); + break; + + case 0xb: + tr_info(&rtnr_tr, "1st=%08x, 2nd=%08x, 3rd=%08x, 4st=%08x", + b, c, d, e); + break; + + case 0xc: + tr_warn(&rtnr_tr, "1st=%08x, 2nd=%08x, 3rd=%08x, 4st=%08x", + b, c, d, e); + break; + + case 0xd: + tr_dbg(&rtnr_tr, "1st=%08x, 2nd=%08x, 3rd=%08x, 4st=%08x", + b, c, d, e); + break; + + case 0xe: + tr_err(&rtnr_tr, "1st=%08x, 2nd=%08x, 3rd=%08x, 4st=%08x", + b, c, d, e); + break; + + default: + break; + } +} + +void *rtk_rballoc(unsigned int flags, unsigned int caps, unsigned int bytes) +{ + return rballoc(flags, bytes); +} + +void rtk_rfree(void *ptr) +{ + rfree(ptr); +} + +#if CONFIG_FORMAT_S16LE + +static void rtnr_s16_default(struct processing_module *mod, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames) +{ + struct comp_data *cd = module_get_private_data(mod); + + RTKMA_API_S16_Default(cd->rtk_agl, sources, sink, frames, + 0, 0, 0, + 0, 0); +} + +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + +static void rtnr_s24_default(struct processing_module *mod, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames) +{ + struct comp_data *cd = module_get_private_data(mod); + + RTKMA_API_S24_Default(cd->rtk_agl, sources, sink, frames, + 0, 0, 0, + 0, 0); +} + +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + +static void rtnr_s32_default(struct processing_module *mod, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames) +{ + struct comp_data *cd = module_get_private_data(mod); + + RTKMA_API_S32_Default(cd->rtk_agl, sources, sink, frames, + 0, 0, 0, + 0, 0); +} + +#endif /* CONFIG_FORMAT_S32LE */ + +/* Processing functions table */ +/* + * These functions copy data from source stream to internal queue before + * processing, and output data from inter queue to sink stream after + * processing. + */ +const struct rtnr_func_map rtnr_fnmap[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, rtnr_s16_default }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, rtnr_s24_default }, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, rtnr_s32_default }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +const size_t rtnr_fncount = ARRAY_SIZE(rtnr_fnmap); + +/** + * \brief Retrieves an RTNR processing function matching + * the source buffer's frame format. + * \param fmt the frames' format of the source and sink buffers + */ +static rtnr_func rtnr_find_func(enum sof_ipc_frame fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < rtnr_fncount; i++) { + if (fmt == rtnr_fnmap[i].fmt) + return rtnr_fnmap[i].func; + } + + return NULL; +} + +static inline void rtnr_set_process_sample_rate(struct processing_module *mod, uint32_t sample_rate) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + cd->process_sample_rate = sample_rate; +} + +static int32_t rtnr_check_config_validity(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "sample_rate:%d enabled: %d", + cd->config.params.sample_rate, cd->config.params.enabled); + + if ((cd->config.params.sample_rate != 48000) && + (cd->config.params.sample_rate != 16000)) { + comp_err(dev, "invalid sample_rate:%d", + cd->config.params.sample_rate); + return -EINVAL; + } + + rtnr_set_process_sample_rate(mod, cd->config.params.sample_rate); + + return 0; +} + +static int rtnr_init(struct processing_module *mod) +{ + struct module_data *mod_data = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *ipc_rtnr = &mod_data->cfg; + struct comp_data *cd; + size_t bs = ipc_rtnr->size; + int ret; + + comp_info(dev, "rtnr_new()"); + + /* Check first before proceeding with dev and cd that coefficients + * blob size is sane. + */ + if (bs > SOF_RTNR_MAX_SIZE) { + comp_err(dev, "rtnr_new(), error: configuration blob size = %u > %d", + bs, SOF_RTNR_MAX_SIZE); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + mod_data->private = cd; + + cd->process_enable = true; + + /* Handler for component data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto cd_fail; + } + + ret = comp_init_data_blob(cd->model_handler, bs, ipc_rtnr->data); + if (ret < 0) { + comp_err(dev, "comp_init_data_blob() failed with error: %d", ret); + goto cd_fail; + } + + /* Component defaults */ + cd->source_channel = 0; + + cd->rtk_agl = RTKMA_API_Context_Create(cd->process_sample_rate); + if (cd->rtk_agl == 0) { + comp_err(dev, "RTKMA_API_Context_Create failed."); + ret = -EINVAL; + goto cd_fail; + } + comp_info(dev, "RTKMA_API_Context_Create succeeded."); + + /* comp_is_new_data_blob_available always returns false for the first + * control write with non-empty config. The first non-empty write may + * happen after prepare (e.g. during copy). Default to true so that + * copy keeps checking until a non-empty config is applied. + */ + cd->reconfigure = true; + + /* Done. */ + return 0; + +cd_fail: + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); + return ret; +} + +static int rtnr_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + mod_data_blob_handler_free(mod, cd->model_handler); + + RTKMA_API_Context_Free(cd->rtk_agl); + + mod_free(mod, cd); + return 0; +} + +/* Check component audio stream parameters */ +static int rtnr_check_params(struct processing_module *mod, struct audio_stream *source, + struct audio_stream *sink) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + bool channels_valid; + + comp_info(dev, "entry"); + + /* set source/sink_frames/rate */ + cd->source_rate = audio_stream_get_rate(source); + cd->sink_rate = audio_stream_get_rate(sink); + cd->sources_stream[0].rate = audio_stream_get_rate(source); + cd->sink_stream.rate = audio_stream_get_rate(sink); + channels_valid = audio_stream_get_channels(source) == audio_stream_get_channels(sink); + + if (!cd->sink_rate) { + comp_err(dev, "rtnr_nr_params(), zero sink rate"); + return -EINVAL; + } + + /* Currently support 16kHz sample rate only. */ + switch (cd->source_rate) { + case 16000: + comp_info(dev, "rtnr_params(), sample rate = 16000 kHz"); + break; + case 48000: + comp_info(dev, "rtnr_params(), sample rate = 48000 kHz"); + break; + default: + comp_err(dev, "rtnr_nr_params(), invalid sample rate(%d kHz)", + cd->source_rate); + return -EINVAL; + } + + if (!channels_valid) { + comp_err(dev, "rtnr_params(), source/sink stream must have same channels"); + return -EINVAL; + } + + /* set source/sink stream channels */ + cd->sources_stream[0].channels = audio_stream_get_channels(source); + cd->sink_stream.channels = audio_stream_get_channels(sink); + + /* set source/sink stream overrun/underrun permitted */ + cd->sources_stream[0].overrun_permitted = audio_stream_get_overrun(source); + cd->sink_stream.overrun_permitted = audio_stream_get_overrun(sink); + cd->sources_stream[0].underrun_permitted = audio_stream_get_underrun(source); + cd->sink_stream.underrun_permitted = audio_stream_get_underrun(sink); + + return 0; +} + +#if CONFIG_IPC_MAJOR_3 +static int rtnr_get_comp_config(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata, + int max_data_size) +{ + struct comp_data *cd = module_get_private_data(mod); + int ret; + + if (sizeof(cd->config) > max_data_size) + return -EINVAL; + + ret = memcpy_s(cdata->data->data, max_data_size, &cd->config, sizeof(cd->config)); + if (ret) + return ret; + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = sizeof(cd->config); + return 0; +} + +static int rtnr_get_comp_data(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata, + int max_data_size) +{ + struct comp_data *cd = module_get_private_data(mod); + uint8_t *config; + size_t size; + int ret; + + config = comp_get_data_blob(cd->model_handler, &size, NULL); + + if (size > max_data_size || size < 0) + return -EINVAL; + + if (size > 0) { + ret = memcpy_s(cdata->data->data, + max_data_size, + config, + size); + comp_info(mod->dev, "size= %d, ret = %d", + size, ret); + if (ret) + return ret; + } + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = size; + + return 0; +} + +static int rtnr_get_bin_data(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata, + int max_data_size) +{ + struct comp_dev *dev = mod->dev; + + if (!dev) + return -ENODEV; + + comp_err(dev, "type = %u, index = %u, size = %d", + cdata->data->type, cdata->msg_index, cdata->num_elems); + + switch (cdata->data->type) { + case SOF_RTNR_CONFIG: + comp_err(dev, "SOF_RTNR_CONFIG"); + return rtnr_get_comp_config(mod, cdata, max_data_size); + case SOF_RTNR_DATA: + comp_err(dev, "SOF_RTNR_DATA"); + return rtnr_get_comp_data(mod, cdata, max_data_size); + default: + comp_err(dev, "unknown binary data type"); + return -EINVAL; + } +} +#endif + +static int rtnr_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct comp_dev *dev = mod->dev; + +#if CONFIG_IPC_MAJOR_4 + comp_err(dev, "Not supported, should not happen"); + return -EINVAL; + +#elif CONFIG_IPC_MAJOR_3 + struct comp_data *cd = module_get_private_data(mod); + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + int j; + + comp_dbg(dev, "entry"); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return rtnr_get_bin_data(mod, cdata, fragment_size); + + case SOF_CTRL_CMD_SWITCH: + for (j = 0; j < cdata->num_elems; j++) { + cdata->chanv[j].channel = j; + cdata->chanv[j].value = cd->process_enable; + comp_dbg(dev, "rtnr_cmd_get_value(), channel = %u, value = %u", + cdata->chanv[j].channel, + cdata->chanv[j].value); + } + break; + default: + comp_err(dev, "rtnr_cmd_get_data() error: invalid command %d", cdata->cmd); + return -EINVAL; + } +#endif /* CONFIG_IPC_MAJOR_3 */ + + return 0; +} + +static int rtnr_reconfigure(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint8_t *config; + size_t size; + + comp_dbg(dev, "entry"); + + if (!comp_is_current_data_blob_valid(cd->model_handler) && + !comp_is_new_data_blob_available(cd->model_handler)) { + /* + * The data blob hasn't been available once so far. + * + * This looks redundant since the same check will be done in + * comp_get_data_blob() below. But without this early return, + * hundreds of warn message lines are produced per second by + * comp_get_data_blob() calls until the data blob is arrived. + */ + return 0; + } + + config = comp_get_data_blob(cd->model_handler, &size, NULL); + comp_dbg(dev, "size: %d", size); + + if (size == 0) { + /* No data to be handled */ + return 0; + } + + if (!config) { + comp_err(dev, "Config not set"); + return -EINVAL; + } + + comp_info(dev, "New data applied %p (%zu bytes)", + config, size); + + cd->reconfigure = false; + + RTKMA_API_Set(cd->rtk_agl, config, size, RTNR_DATA_ID_PRESET); + + return 0; +} + +static int rtnr_set_config_bytes(struct processing_module *mod, + const unsigned char *data, uint32_t size) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + /* + * The received data could be the combined blob of the control + * widgets defined in the topology, or the config received by + * SOF_CTRL_CMD_BINARY. In either case we just have to check if + * the whole config data is received. + */ + if (size < sizeof(cd->config)) { + comp_err(dev, "invalid size %u", + size); + return -EINVAL; + } + + ret = memcpy_s(&cd->config, + sizeof(cd->config), + data, + sizeof(cd->config)); + + comp_info(dev, + "sample_rate = %u, enabled=%d", + cd->config.params.sample_rate, + cd->config.params.enabled); + + return ret; +} + +static int32_t rtnr_set_value(struct processing_module *mod, void *ctl_data) +{ +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = ctl_data; +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *cdata = ctl_data; +#endif + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + uint32_t val = 0; + int32_t j; + + for (j = 0; j < cdata->num_elems; j++) { + val |= cdata->chanv[j].value; + comp_dbg(dev, "value = %u", val); + } + + if (val) { + comp_info(dev, "enabled"); + cd->process_enable = true; + } else { + comp_info(dev, "passthrough"); + cd->process_enable = false; + } + + return 0; +} + +static int rtnr_set_config(struct processing_module *mod, uint32_t param_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_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + if (dev->state < COMP_STATE_READY) { + comp_err(dev, "driver in init!"); + return -EBUSY; + } + + switch (cdata->data->type) { + case SOF_RTNR_CONFIG: + return rtnr_set_config_bytes(mod, (unsigned char *)cdata->data->data, + cdata->data->size); + case SOF_RTNR_DATA: + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); + if (ret) + return ret; + /* Accept the new blob immediately so that userspace can write + * the control in quick succession without error. + * This ensures the last successful control write from userspace + * before prepare/copy is applied. + * The config blob is not referenced after reconfigure() returns + * so it is safe to call comp_get_data_blob here which frees the + * old blob. This assumes cmd() and prepare()/copy() cannot run + * concurrently which is the case when there is no preemption. + */ + if (comp_is_new_data_blob_available(cd->model_handler)) { + comp_dbg(dev, "new data blob available"); + comp_get_data_blob(cd->model_handler, NULL, NULL); + cd->reconfigure = true; + } + return 0; + } + + comp_err(dev, "unknown binary data type"); + return -EINVAL; + + case SOF_CTRL_CMD_SWITCH: + comp_dbg(dev, "rtnr_cmd_set_config(), SOF_CTRL_CMD_SWITCH"); + return rtnr_set_value(mod, cdata); + } + + comp_err(dev, "error: invalid command %d", cdata->cmd); + return -EINVAL; + +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + comp_dbg(dev, "SOF_IPC4_SWITCH_CONTROL_PARAM_ID"); + return rtnr_set_value(mod, ctl); + case SOF_RTNR_CONFIG: + comp_dbg(dev, "SOF_RTNR_CONFIG"); + if (dev->state < COMP_STATE_READY) { + comp_err(dev, "driver in init!"); + return -EBUSY; + } + + return rtnr_set_config_bytes(mod, fragment, fragment_size); + case SOF_RTNR_DATA: + comp_dbg(dev, "SOF_RTNR_DATA"); + if (dev->state < COMP_STATE_READY) { + comp_err(dev, "driver in init!"); + return -EBUSY; + } + + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); + if (ret) + return ret; + /* Accept the new blob immediately so that userspace can write + * the control in quick succession without error. + * This ensures the last successful control write from userspace + * before prepare/copy is applied. + * The config blob is not referenced after reconfigure() returns + * so it is safe to call comp_get_data_blob here which frees the + * old blob. This assumes cmd() and prepare()/copy() cannot run + * concurrently which is the case when there is no preemption. + */ + if (comp_is_new_data_blob_available(cd->model_handler)) { + comp_dbg(dev, "rtnr_set_bin_data(), new data blob available"); + comp_get_data_blob(cd->model_handler, NULL, NULL); + cd->reconfigure = true; + } + return 0; + } + + comp_err(dev, "error: invalid param_id = %d", param_id); + return -EINVAL; +#endif +} + +void rtnr_copy_from_sof_stream(struct audio_stream_rtnr *dst, struct audio_stream *src) +{ + + 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); +} + +void rtnr_copy_to_sof_stream(struct audio_stream *dst, struct audio_stream_rtnr *src) +{ + 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 */ +static int rtnr_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 comp_dev *dev = mod->dev; + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + int frames = input_buffers[0].size; + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream_rtnr *sources_stream[RTNR_MAX_SOURCES]; + struct audio_stream_rtnr *sink_stream = &cd->sink_stream; + int32_t i; + int ret; + + if (cd->reconfigure) { + ret = rtnr_reconfigure(mod); + if (ret) + return ret; + } + + for (i = 0; i < RTNR_MAX_SOURCES; ++i) + sources_stream[i] = &cd->sources_stream[i]; + + comp_dbg(dev, "rtnr_copy()"); + + /* put empty data into output queue*/ + RTKMA_API_First_Copy(cd->rtk_agl, cd->source_rate, audio_stream_get_channels(source)); + + if (!frames) + return 0; + + comp_dbg(dev, "rtnr_copy() frames = %d", frames); + if (cd->process_enable) { + /* Run processing function */ + + /* copy required data from sof audio stream to RTNR audio stream */ + rtnr_copy_from_sof_stream(sources_stream[0], source); + rtnr_copy_from_sof_stream(sink_stream, sink); + + /* + * Processing function uses an array of pointers to source streams + * as parameter. + */ + cd->rtnr_func(mod, sources_stream, sink_stream, frames); + + /* + * real process function of rtnr, consume/produce data from internal queue + * instead of component buffer + */ + RTKMA_API_Process(cd->rtk_agl, 0, cd->source_rate, MicNum); + + /* copy required data from RTNR audio stream to sof audio stream */ + rtnr_copy_to_sof_stream(source, sources_stream[0]); + rtnr_copy_to_sof_stream(sink, sink_stream); + + } else { + comp_dbg(dev, "rtnr_copy() passthrough"); + + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); + } + + /* Track consume and produce */ + module_update_buffer_position(&input_buffers[0], &output_buffers[0], frames); + return 0; +} + +#if CONFIG_IPC_MAJOR_4 +static void rtnr_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + /* The caller has checked validity of source and sink buffers */ + + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); + + sinkb = comp_dev_get_first_data_consumer(dev); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); +} +#endif + +static int rtnr_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sourceb, *sinkb; + int ret; + + comp_dbg(dev, "entry"); + + sinkb = comp_dev_get_first_data_consumer(dev); + sourceb = comp_dev_get_first_data_producer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + +#if CONFIG_IPC_MAJOR_4 + rtnr_params(mod); +#endif + + /* Check config */ + ret = rtnr_check_config_validity(mod); + if (ret < 0) { + comp_err(dev, "rtnr_check_config_validity() failed."); + goto err; + } + + /* Initialize RTNR */ + + /* Get sink data format */ + cd->sink_format = audio_stream_get_frm_fmt(&sinkb->stream); + cd->sink_stream.frame_fmt = audio_stream_get_frm_fmt(&sinkb->stream); + ret = rtnr_check_params(mod, &sourceb->stream, &sinkb->stream); + if (ret) + goto err; + + /* Check source and sink PCM format and get processing function */ + comp_info(dev, "sink_format=%d", cd->sink_format); + cd->rtnr_func = rtnr_find_func(cd->sink_format); + if (!cd->rtnr_func) { + comp_err(dev, "No suitable processing function found."); + ret = -EINVAL; + goto err; + } + + /* Clear in/out buffers */ + RTKMA_API_Prepare(cd->rtk_agl); + + /* Blobs sent during COMP_STATE_READY is assigned to blob_handler->data + * directly, so comp_is_new_data_blob_available always returns false. + */ + return rtnr_reconfigure(mod); + +err: + return ret; +} + +static int rtnr_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + cd->sink_format = 0; + cd->rtnr_func = NULL; + cd->source_rate = 0; + cd->sink_rate = 0; + + return 0; +} + +static const struct module_interface rtnr_interface = { + .init = rtnr_init, + .prepare = rtnr_prepare, + .process_audio_stream = rtnr_process, + .set_configuration = rtnr_set_config, + .get_configuration = rtnr_get_config, + .reset = rtnr_reset, + .free = rtnr_free +}; + +#if CONFIG_COMP_RTNR_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("RTNR", &rtnr_interface, 1, SOF_REG_UUID(rtnr), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_MODULE_ADAPTER(rtnr_interface, rtnr_uuid, rtnr_tr); +SOF_MODULE_INIT(rtnr, sys_comp_module_rtnr_interface_init); + +#endif diff --git a/src/audio/rtnr/rtnr.toml b/src/audio/rtnr/rtnr.toml new file mode 100644 index 000000000000..7281f2b72ee0 --- /dev/null +++ b/src/audio/rtnr/rtnr.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # RTNR module config + [[module.entry]] + name = "RTNR" + uuid = UUIDREG_STR_RTNR + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/rtnr/rtnr_stub.c b/src/audio/rtnr/rtnr_stub.c new file mode 100644 index 000000000000..a825396ece3f --- /dev/null +++ b/src/audio/rtnr/rtnr_stub.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Google LLC. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org.com> +// + +#include <sof/audio/rtnr/rtklib/include/RTK_MA_API.h> +#include <sof/audio/audio_stream.h> +#include <rtos/alloc.h> + +#define RTNR_STUB_CONTEXT_SIZE 42 /* Just some random size to allocate */ + +void RTKMA_API_S16_Default(void *Context, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames, + _Bool ref_active, int in_idx, int ref_idx, + int ref_32bits, int ref_shift) +{ + struct audio_stream sof_source; + struct audio_stream sof_sink; + + rtnr_copy_to_sof_stream(&sof_source, sources[0]); + rtnr_copy_to_sof_stream(&sof_sink, sink); + audio_stream_copy(&sof_source, 0, &sof_sink, 0, + frames * audio_stream_get_channels(&sof_sink)); + rtnr_copy_from_sof_stream(sources[0], &sof_source); + rtnr_copy_from_sof_stream(sink, &sof_sink); +} + +void RTKMA_API_S24_Default(void *Context, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames, + _Bool ref_active, int in_idx, int ref_idx, + int ref_32bits, int ref_shift) +{ + struct audio_stream sof_source; + struct audio_stream sof_sink; + + rtnr_copy_to_sof_stream(&sof_source, sources[0]); + rtnr_copy_to_sof_stream(&sof_sink, sink); + audio_stream_copy(&sof_source, 0, &sof_sink, 0, + frames * audio_stream_get_channels(&sof_sink)); + rtnr_copy_from_sof_stream(sources[0], &sof_source); + rtnr_copy_from_sof_stream(sink, &sof_sink); +} + +void RTKMA_API_S32_Default(void *Context, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames, + _Bool ref_active, int in_idx, int ref_idx, + int ref_32bits, int ref_shift) +{ + struct audio_stream sof_source; + struct audio_stream sof_sink; + + rtnr_copy_to_sof_stream(&sof_source, sources[0]); + rtnr_copy_to_sof_stream(&sof_sink, sink); + audio_stream_copy(&sof_source, 0, &sof_sink, 0, + frames * audio_stream_get_channels(&sof_sink)); + rtnr_copy_from_sof_stream(sources[0], &sof_source); + rtnr_copy_from_sof_stream(sink, &sof_sink); +} + +void RTKMA_API_First_Copy(void *Context, int SampleRate, int MicCh) +{} + +void RTKMA_API_Process(void *Context, _Bool has_ref, int SampleRate, int MicCh) +{} + +void RTKMA_API_Prepare(void *Context) +{} + +void *RTKMA_API_Context_Create(int sample_rate) +{ + /* Allocate something, to avoid return NULL and cause error + * in check of success of this. + */ + return rzalloc(SOF_MEM_FLAG_USER, RTNR_STUB_CONTEXT_SIZE); +} + +void RTKMA_API_Context_Free(void *Context) +{ + rfree(Context); +} + +int RTKMA_API_Parameter_Size(void *Context, unsigned int IDs) +{ + return 0; +} + +int RTKMA_API_Set(void *Context, const void *pParameters, int size, unsigned int IDs) +{ + return 0; +} diff --git a/src/audio/selector/CMakeLists.txt b/src/audio/selector/CMakeLists.txt index 1c7e9a43ad44..d3d96e00b829 100644 --- a/src/audio/selector/CMakeLists.txt +++ b/src/audio/selector/CMakeLists.txt @@ -1,3 +1,9 @@ # SPDX-License-Identifier: BSD-3-Clause +if(CONFIG_COMP_SEL STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/selector_llext) + add_dependencies(app selector) + return() +endif() + add_local_sources(sof selector_generic.c selector.c) diff --git a/src/audio/selector/Kconfig b/src/audio/selector/Kconfig new file mode 100644 index 000000000000..636330dabe1f --- /dev/null +++ b/src/audio/selector/Kconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_SEL + tristate "Channel selector component" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for SEL component diff --git a/src/audio/selector/README.md b/src/audio/selector/README.md new file mode 100644 index 000000000000..54f09e2ba876 --- /dev/null +++ b/src/audio/selector/README.md @@ -0,0 +1,14 @@ +# Channel Selector Architecture + +This directory contains the Channel Selector component. + +## Overview + +Given a multi-channel stream (e.g., 8-channel microphone array), the channel selector component isolates specific channels (e.g., channels 1 and 2) to pass forward while dropping the rest. + +## Configuration and Scripts + +- **Kconfig**: Enables the selector component (`COMP_SEL`). +- **CMakeLists.txt**: Compiles `selector.c` and `selector_generic.c`, and natively supports Zephyr environment modules (`llext`). +- **selector.toml**: Includes topology parameters under `MICSEL`, using UUID `UUIDREG_STR_SELECTOR4` and limits up to 8 instances, with distinct `mod_cfg` limits depending on chipset architectures (Meteor Lake, Lunar Lake, ACE). +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/micsel.conf`, which defines a `micsel` widget of type `effect` (UUID `c1:92:fe:32:17:1e:c2:4f:97:58:c7:f3:54:2e:98:0a`). diff --git a/src/audio/selector/llext/CMakeLists.txt b/src/audio/selector/llext/CMakeLists.txt new file mode 100644 index 000000000000..460b547e64c6 --- /dev/null +++ b/src/audio/selector/llext/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("selector" + SOURCES ../selector.c + ../selector_generic.c + LIB openmodules +) diff --git a/src/audio/selector/llext/llext.toml.h b/src/audio/selector/llext/llext.toml.h new file mode 100644 index 000000000000..1fdbcd4f9f05 --- /dev/null +++ b/src/audio/selector/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../selector.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/selector/selector.c b/src/audio/selector/selector.c index a88d748f5f35..6afc92d8bdfc 100644 --- a/src/audio/selector/selector.c +++ b/src/audio/selector/selector.c @@ -5,7 +5,7 @@ // Author: Lech Betlej <lech.betlej@linux.intel.com> /** - * \file audio/selector.c + * \file * \brief Audio channel selection component. In case 1 output channel is * \brief selected in topology the component provides the selected channel on * \brief output. In case 2 or 4 channels are selected on output the component @@ -16,14 +16,16 @@ #include <sof/audio/component.h> #include <sof/audio/pipeline.h> #include <sof/audio/selector.h> +#include <sof/audio/ipc-config.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ #include <sof/lib/uuid.h> #include <sof/list.h> -#include <sof/string.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <sof/ut.h> #include <ipc/control.h> @@ -35,85 +37,28 @@ #include <stddef.h> #include <stdint.h> -static const struct comp_driver comp_selector; - -/* 55a88ed5-3d18-46ca-88f1-0ee6eae9930f */ -DECLARE_SOF_UUID("selector", selector_uuid, 0x55a88ed5, 0x3d18, 0x46ca, - 0x88, 0xf1, 0x0e, 0xe6, 0xea, 0xe9, 0x93, 0x0f); - -/** - * \brief Creates selector component. - * \param[in,out] data Selector base component device. - * \return Pointer to selector base component device. - */ -static struct comp_dev *selector_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct sof_ipc_comp_process *ipc_process = - (struct sof_ipc_comp_process *)comp; - size_t bs = ipc_process->size; - struct comp_dev *dev; - struct comp_data *cd; - int ret; - - comp_cl_info(&comp_selector, "selector_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_process)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_process); - - ret = memcpy_s(COMP_GET_IPC(dev, sof_ipc_comp_process), - sizeof(struct sof_ipc_comp_process), comp, - sizeof(struct sof_ipc_comp_process)); - assert(!ret); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); - - ret = memcpy_s(&cd->config, sizeof(cd->config), ipc_process->data, bs); - assert(!ret); +#if CONFIG_IPC_MAJOR_4 +#define SEL_MAX_CONFIG_BLOB_SIZE (SEL_MAX_NUM_CONFIGS * sizeof(struct ipc4_selector_coeffs_config)) +#endif - dev->state = COMP_STATE_READY; - return dev; -} +LOG_MODULE_REGISTER(selector, CONFIG_SOF_LOG_LEVEL); -/** - * \brief Frees selector component. - * \param[in,out] dev Selector base component device. - */ -static void selector_free(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); +#if CONFIG_IPC_MAJOR_3 +static const struct comp_driver comp_selector; - comp_info(dev, "selector_free()"); - - rfree(cd); - rfree(dev); -} +SOF_DEFINE_REG_UUID(selector); static int selector_verify_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *buffer; - struct comp_buffer *sinkb; + struct comp_buffer *buffer, *sinkb; uint32_t in_channels; uint32_t out_channels; - uint32_t flags = 0; - comp_dbg(dev, "selector_verify_params()"); + comp_dbg(dev, "entry"); - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); + sinkb = comp_dev_get_first_data_consumer(dev); /* check whether params->channels (received from driver) are equal to * cd->config.in_channels_count (PLAYBACK) or @@ -123,45 +68,39 @@ static int selector_verify_params(struct comp_dev *dev, */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { /* fetch sink buffer for playback */ - buffer = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); + buffer = comp_dev_get_first_data_consumer(dev); if (cd->config.in_channels_count && cd->config.in_channels_count != params->channels) { - comp_err(dev, "selector_verify_params() error: src in_channels_count does not match pcm channels"); + comp_err(dev, "src in_channels_count does not match pcm channels"); return -EINVAL; } in_channels = cd->config.in_channels_count; - buffer_lock(buffer, &flags); - /* if cd->config.out_channels_count are equal to 0 * (it can vary), we set params->channels to sink buffer - * channels, which were previosly set in + * channels, which were previously set in * pipeline_comp_hw_params() */ out_channels = cd->config.out_channels_count ? - cd->config.out_channels_count : buffer->stream.channels; + cd->config.out_channels_count : audio_stream_get_channels(&buffer->stream); params->channels = out_channels; } else { /* fetch source buffer for capture */ - buffer = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); + buffer = comp_dev_get_first_data_producer(dev); if (cd->config.out_channels_count && cd->config.out_channels_count != params->channels) { - comp_err(dev, "selector_verify_params() error: src in_channels_count does not match pcm channels"); + comp_err(dev, "src in_channels_count does not match pcm channels"); return -EINVAL; } out_channels = cd->config.out_channels_count; - buffer_lock(buffer, &flags); - /* if cd->config.in_channels_count are equal to 0 * (it can vary), we set params->channels to source buffer - * channels, which were previosly set in + * channels, which were previously set in * pipeline_comp_hw_params() */ in_channels = cd->config.in_channels_count ? - cd->config.in_channels_count : buffer->stream.channels; + cd->config.in_channels_count : audio_stream_get_channels(&buffer->stream); params->channels = in_channels; } @@ -169,9 +108,7 @@ static int selector_verify_params(struct comp_dev *dev, buffer_set_params(buffer, params, BUFFER_UPDATE_FORCE); /* set component period frames */ - component_set_period_frames(dev, sinkb->stream.rate); - - buffer_unlock(buffer, flags); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&sinkb->stream)); /* verify input channels */ switch (in_channels) { @@ -179,8 +116,7 @@ static int selector_verify_params(struct comp_dev *dev, case SEL_SOURCE_4CH: break; default: - comp_err(dev, "selector_verify_params() error: in_channels = %u" - , in_channels); + comp_err(dev, "in_channels = %u", in_channels); return -EINVAL; } @@ -192,19 +128,19 @@ static int selector_verify_params(struct comp_dev *dev, case SEL_SINK_4CH: /* verify proper channels for passthrough mode */ if (in_channels != out_channels) { - comp_err(dev, "selector_verify_params() error: in_channels = %u, out_channels = %u" + comp_err(dev, "in_channels = %u, out_channels = %u" , in_channels, out_channels); return -EINVAL; } break; default: - comp_err(dev, "selector_verify_params() error: out_channels = %u" + comp_err(dev, "out_channels = %u" , out_channels); return -EINVAL; } - if (cd->config.sel_channel > (SEL_SOURCE_4CH - 1)) { - comp_err(dev, "selector_verify_params() error: ch_idx = %u" + if (cd->config.sel_channel > (params->channels - 1)) { + comp_err(dev, "ch_idx = %u" , cd->config.sel_channel); return -EINVAL; } @@ -212,6 +148,56 @@ static int selector_verify_params(struct comp_dev *dev, return 0; } +static struct comp_dev *selector_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + const struct ipc_config_process *ipc_process = spec; + size_t bs = ipc_process->size; + struct comp_dev *dev; + struct comp_data *cd; + int ret; + + comp_cl_dbg(&comp_selector, "selector_new()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) { + comp_free_device(dev); + return NULL; + } + + comp_set_drvdata(dev, cd); + + ret = memcpy_s(&cd->config, sizeof(cd->config), ipc_process->data, bs); + if (ret) { + rfree(cd); + comp_free_device(dev); + return NULL; + } + + dev->state = COMP_STATE_READY; + return dev; +} + +/** + * \brief Frees selector component. + * \param[in,out] dev Selector base component device. + */ +static void selector_free(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "entry"); + + rfree(cd); + comp_free_device(dev); +} + /** * \brief Sets selector component audio stream parameters. * \param[in,out] dev Selector base component device. @@ -224,11 +210,11 @@ static int selector_params(struct comp_dev *dev, { int err; - comp_info(dev, "selector_params()"); + comp_dbg(dev, "entry"); err = selector_verify_params(dev, params); if (err < 0) { - comp_err(dev, "selector_params(): pcm params verification failed."); + comp_err(dev, "pcm params verification failed."); return -EINVAL; } @@ -250,10 +236,10 @@ static int selector_ctrl_set_data(struct comp_dev *dev, switch (cdata->cmd) { case SOF_CTRL_CMD_BINARY: - comp_info(dev, "selector_ctrl_set_data(), SOF_CTRL_CMD_BINARY"); + comp_dbg(dev, "SOF_CTRL_CMD_BINARY"); cfg = (struct sof_sel_config *) - ASSUME_ALIGNED(cdata->data->data, 4); + ASSUME_ALIGNED(&cdata->data->data, 4); /* Just set the configuration */ cd->config.in_channels_count = cfg->in_channels_count; @@ -261,7 +247,7 @@ static int selector_ctrl_set_data(struct comp_dev *dev, cd->config.sel_channel = cfg->sel_channel; break; default: - comp_err(dev, "selector_ctrl_set_cmd() error: invalid cdata->cmd = %u", + comp_err(dev, "invalid cdata->cmd = %u", cdata->cmd); ret = -EINVAL; break; @@ -286,11 +272,13 @@ static int selector_ctrl_get_data(struct comp_dev *dev, switch (cdata->cmd) { case SOF_CTRL_CMD_BINARY: - comp_info(dev, "selector_ctrl_get_data(), SOF_CTRL_CMD_BINARY"); + comp_dbg(dev, "SOF_CTRL_CMD_BINARY"); + if (size < sizeof(cd->config)) + return -EINVAL; /* Copy back to user space */ - ret = memcpy_s(cdata->data->data, ((struct sof_abi_hdr *) - (cdata->data))->size, &cd->config, + ret = memcpy_s(cdata->data->data, + size, &cd->config, sizeof(cd->config)); assert(!ret); @@ -299,7 +287,7 @@ static int selector_ctrl_get_data(struct comp_dev *dev, break; default: - comp_err(dev, "selector_ctrl_get_data() error: invalid cdata->cmd"); + comp_err(dev, "invalid cdata->cmd"); ret = -EINVAL; break; } @@ -318,10 +306,10 @@ static int selector_ctrl_get_data(struct comp_dev *dev, static int selector_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) { - struct sof_ipc_ctrl_data *cdata = data; + struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); int ret = 0; - comp_info(dev, "selector_cmd()"); + comp_dbg(dev, "entry"); switch (cmd) { case COMP_CMD_SET_DATA: @@ -331,13 +319,13 @@ static int selector_cmd(struct comp_dev *dev, int cmd, void *data, ret = selector_ctrl_get_data(dev, cdata, max_data_size); break; case COMP_CMD_SET_VALUE: - comp_info(dev, "selector_cmd(), COMP_CMD_SET_VALUE"); + comp_dbg(dev, "COMP_CMD_SET_VALUE"); break; case COMP_CMD_GET_VALUE: - comp_info(dev, "selector_cmd(), COMP_CMD_GET_VALUE"); + comp_dbg(dev, "COMP_CMD_GET_VALUE"); break; default: - comp_err(dev, "selector_cmd() error: invalid command"); + comp_err(dev, "invalid command"); ret = -EINVAL; } @@ -353,21 +341,28 @@ static int selector_cmd(struct comp_dev *dev, int cmd, void *data, static int selector_trigger(struct comp_dev *dev, int cmd) { struct comp_buffer *sourceb; + enum sof_comp_type type; int ret; - comp_info(dev, "selector_trigger()"); + comp_dbg(dev, "entry"); - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); + sourceb = comp_dev_get_first_data_producer(dev); + if (!sourceb) { + comp_err(dev, "source disconnected"); + return -ENODEV; + } ret = comp_set_state(dev, cmd); + if (ret == COMP_STATUS_STATE_ALREADY_SET) + ret = 0; /* TODO: remove in the future after adding support for case when * kpb_init_draining() and kpb_draining_task() are interrupted by * new pipeline_task() */ - return dev_comp_type(sourceb->source) == SOF_COMP_KPB ? - PPL_STATUS_PATH_STOP : ret; + type = dev_comp_type(comp_buffer_get_source_component(sourceb)); + + return type == SOF_COMP_KPB ? PPL_STATUS_PATH_TERMINATE : ret; } /** @@ -378,38 +373,31 @@ static int selector_trigger(struct comp_dev *dev, int cmd) static int selector_copy(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sink; - struct comp_buffer *source; + struct comp_buffer *sink, *source; uint32_t frames; uint32_t source_bytes; uint32_t sink_bytes; - uint32_t flags = 0; - comp_dbg(dev, "selector_copy()"); + comp_dbg(dev, "entry"); /* selector component will have 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 = comp_dev_get_first_data_producer(dev); + sink = comp_dev_get_first_data_consumer(dev); - buffer_lock(source, &flags); - buffer_lock(sink, &flags); + if (!audio_stream_get_avail(&source->stream)) + return PPL_STATUS_PATH_STOP; frames = audio_stream_avail_frames(&source->stream, &sink->stream); source_bytes = frames * audio_stream_frame_bytes(&source->stream); sink_bytes = frames * audio_stream_frame_bytes(&sink->stream); - buffer_unlock(sink, flags); - buffer_unlock(source, flags); - - comp_dbg(dev, "selector_copy(), source_bytes = 0x%x, sink_bytes = 0x%x", + comp_dbg(dev, "source_bytes = 0x%x, sink_bytes = 0x%x", source_bytes, sink_bytes); /* copy selected channels from in to out */ - buffer_invalidate(source, source_bytes); + buffer_stream_invalidate(source, source_bytes); cd->sel_func(dev, &sink->stream, &source->stream, frames); - buffer_writeback(sink, sink_bytes); + buffer_stream_writeback(sink, sink_bytes); /* calculate new free and available */ comp_update_buffer_produce(sink, sink_bytes); @@ -426,12 +414,11 @@ static int selector_copy(struct comp_dev *dev) static int selector_prepare(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sinkb; - struct comp_buffer *sourceb; - struct sof_ipc_comp_config *config = dev_comp_config(dev); + struct comp_buffer *sinkb, *sourceb; + size_t sink_size; int ret; - comp_info(dev, "selector_prepare()"); + comp_dbg(dev, "entry"); ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); if (ret < 0) @@ -441,46 +428,49 @@ static int selector_prepare(struct comp_dev *dev) return PPL_STATUS_PATH_STOP; /* selector component will 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 = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } /* get source data format and period bytes */ - cd->source_format = sourceb->stream.frame_fmt; - cd->source_period_bytes = - audio_stream_period_bytes(&sourceb->stream, dev->frames); + cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); + cd->source_period_bytes = audio_stream_period_bytes(&sourceb->stream, dev->frames); /* get sink data format and period bytes */ - cd->sink_format = sinkb->stream.frame_fmt; - cd->sink_period_bytes = - audio_stream_period_bytes(&sinkb->stream, dev->frames); + cd->sink_format = audio_stream_get_frm_fmt(&sinkb->stream); + cd->sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, dev->frames); /* There is an assumption that sink component will report out * proper number of channels [1] for selector to actually * reduce channel count between source and sink */ - comp_info(dev, "selector_prepare(): sourceb->schannels = %u", - sourceb->stream.channels); - comp_info(dev, "selector_prepare(): sinkb->channels = %u", - sinkb->stream.channels); + comp_dbg(dev, "sourceb->schannels = %u", + audio_stream_get_channels(&sourceb->stream)); + comp_dbg(dev, "sinkb->channels = %u", + audio_stream_get_channels(&sinkb->stream)); + + sink_size = audio_stream_get_size(&sinkb->stream); - if (sinkb->stream.size < config->periods_sink * cd->sink_period_bytes) { - comp_err(dev, "selector_prepare() error: sink buffer size is insufficient"); + if (sink_size < cd->sink_period_bytes) { + comp_err(dev, "sink buffer size %zu is insufficient < %d", + sink_size, cd->sink_period_bytes); ret = -ENOMEM; goto err; } /* validate */ if (cd->sink_period_bytes == 0) { - comp_err(dev, "selector_prepare() error: cd->sink_period_bytes = 0, dev->frames = %u", + comp_err(dev, "cd->sink_period_bytes = 0, dev->frames = %u", dev->frames); ret = -EINVAL; goto err; } if (cd->source_period_bytes == 0) { - comp_err(dev, "selector_prepare() error: cd->source_period_bytes = 0, dev->frames = %u", + comp_err(dev, "cd->source_period_bytes = 0, dev->frames = %u", dev->frames); ret = -EINVAL; goto err; @@ -488,7 +478,7 @@ static int selector_prepare(struct comp_dev *dev) cd->sel_func = sel_get_processing_function(dev); if (!cd->sel_func) { - comp_err(dev, "selector_prepare() error: invalid cd->sel_func, cd->source_format = %u, cd->sink_format = %u, cd->out_channels_count = %u", + comp_err(dev, "invalid cd->sel_func, cd->source_format = %u, cd->sink_format = %u, cd->out_channels_count = %u", cd->source_format, cd->sink_format, cd->config.out_channels_count); ret = -EINVAL; @@ -510,20 +500,28 @@ static int selector_prepare(struct comp_dev *dev) static int selector_reset(struct comp_dev *dev) { int ret; + struct comp_data *cd = comp_get_drvdata(dev); - comp_info(dev, "selector_reset()"); + comp_dbg(dev, "entry"); + + cd->source_period_bytes = 0; + cd->sink_period_bytes = 0; + cd->sel_func = NULL; ret = comp_set_state(dev, COMP_TRIGGER_RESET); return ret; } +DECLARE_TR_CTX(selector_tr, SOF_UUID(selector_uuid), LOG_LEVEL_INFO); + /** \brief Selector component definition. */ static const struct comp_driver comp_selector = { .type = SOF_COMP_SELECTOR, - .uid = SOF_UUID(selector_uuid), + .uid = SOF_RT_UUID(selector_uuid), + .tctx = &selector_tr, .ops = { - .new = selector_new, + .create = selector_new, .free = selector_free, .params = selector_params, .cmd = selector_cmd, @@ -546,3 +544,566 @@ UT_STATIC void sys_comp_selector_init(void) } DECLARE_MODULE(sys_comp_selector_init); +SOF_MODULE_INIT(selector, sys_comp_selector_init); + +#else + +SOF_DEFINE_REG_UUID(selector4); + +static void build_config(struct comp_data *cd, struct module_config *cfg) +{ + 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; + + if (cd->sel_ipc4_cfg.init_payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT) + out_fmt = &sel_cfg->pin_cfg.out_pin.audio_fmt; + else + out_fmt = &sel_cfg->output_format; + + audio_stream_fmt_conversion(cfg->base_cfg.audio_fmt.depth, + cfg->base_cfg.audio_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + cfg->base_cfg.audio_fmt.s_type); + cd->source_format = frame_fmt; + + audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, out_fmt->s_type); + cd->sink_format = frame_fmt; + + cd->config.in_channels_count = cfg->base_cfg.audio_fmt.channels_count; + cd->config.out_channels_count = out_fmt->channels_count; + + /* Build default coefficient array (unity Q10 on diagonal, i.e. pass-through mode) */ + memset(&cd->coeffs_config, 0, sizeof(cd->coeffs_config)); + for (i = 0; i < MIN(SEL_SOURCE_CHANNELS_MAX, SEL_SINK_CHANNELS_MAX); i++) + cd->coeffs_config.coeffs[i][i] = SEL_COEF_ONE_Q10; +} + +static int selector_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct module_config *cfg = &md->cfg; + const struct ipc4_base_module_extended_cfg *init_cfg_ext; + const struct sof_selector_avs_ipc4_config *init_cfg_out_fmt; + enum ipc4_selector_init_payload_fmt payload_fmt; + struct comp_data *cd; + size_t base_cfg_size; + size_t bs[2]; + int ret; + + comp_dbg(mod->dev, "entry"); + + init_cfg_ext = cfg->init_data; + init_cfg_out_fmt = cfg->init_data; + base_cfg_size = sizeof(struct ipc4_base_module_cfg); + bs[0] = ipc4_calc_base_module_cfg_ext_size(SEL_NUM_IN_PIN_FMTS, + SEL_NUM_OUT_PIN_FMTS); + bs[1] = sizeof(struct ipc4_audio_format); + + if (cfg->size == base_cfg_size + bs[0]) { + payload_fmt = IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT; + + if (init_cfg_ext->base_cfg_ext.nb_input_pins != SEL_NUM_IN_PIN_FMTS || + init_cfg_ext->base_cfg_ext.nb_output_pins != SEL_NUM_OUT_PIN_FMTS) { + comp_err(mod->dev, "Invalid pin configuration"); + return -EINVAL; + } + } else if (cfg->size == base_cfg_size + bs[1]) { + payload_fmt = IPC4_SEL_INIT_PAYLOAD_BASE_WITH_OUT_FMT; + } else { + comp_err(mod->dev, "Invalid configuration size"); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + cd->sel_ipc4_cfg.init_payload_fmt = payload_fmt; + md->private = cd; + + if (payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT) { + size_t size = sizeof(struct sof_selector_ipc4_pin_config); + + ret = memcpy_s(&cd->sel_ipc4_cfg.pin_cfg, size, + init_cfg_ext->base_cfg_ext.pin_formats, size); + } else { + ret = memcpy_s(&cd->sel_ipc4_cfg.output_format, bs[1], + &init_cfg_out_fmt->output_format, bs[1]); + } + assert(!ret); + + build_config(cd, cfg); + + return 0; +} + +static void set_selector_params(struct processing_module *mod, + struct sof_ipc_stream_params *params) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + const struct sof_selector_ipc4_config *sel_cfg = &cd->sel_ipc4_cfg; + const struct ipc4_audio_format *out_fmt = NULL; + struct comp_buffer *src_buf; + int i; + + if (cd->sel_ipc4_cfg.init_payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT) + out_fmt = &sel_cfg->pin_cfg.out_pin.audio_fmt; + else + out_fmt = &sel_cfg->output_format; + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + params->channels = cd->config.in_channels_count; + else + params->channels = cd->config.out_channels_count; + + params->rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; + params->frame_fmt = cd->source_format; + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + params->chmap[i] = (out_fmt->ch_map >> i * 4) & 0xf; + + /* update each sink format */ + struct comp_buffer *sink_buf; + + comp_dev_for_each_consumer(dev, sink_buf) { + ipc4_update_buffer_format(sink_buf, out_fmt); + audio_stream_set_channels(&sink_buf->stream, params->channels); + audio_stream_set_rate(&sink_buf->stream, params->rate); + } + + /* update the source format + * used only for rare cases where two pipelines are connected by a shared + * buffer and 2 copiers, this will set source format only for shared buffers + * for a short time when the second pipeline already started + * and the first one is not ready yet along with sink buffers params + */ + src_buf = comp_dev_get_first_data_producer(dev); + + if (!audio_buffer_hw_params_configured(&src_buf->audio_buffer)) + ipc4_update_buffer_format(src_buf, &mod->priv.cfg.base_cfg.audio_fmt); +} + +static int selector_verify_params(struct processing_module *mod, + struct sof_ipc_stream_params *params) +{ + struct comp_dev *dev = mod->dev; + struct comp_data *cd = module_get_private_data(mod); + struct comp_buffer *buffer; + uint32_t in_channels = cd->config.in_channels_count; + uint32_t out_channels = cd->config.out_channels_count; + + comp_dbg(dev, "entry"); + + /* verify input channels */ + if (in_channels == 0 || in_channels > SEL_SOURCE_CHANNELS_MAX) { + comp_err(dev, "in_channels = %u", in_channels); + return -EINVAL; + } + + /* verify output channels */ + if (out_channels == 0 || out_channels > SEL_SINK_CHANNELS_MAX) { + comp_err(dev, "out_channels = %u", out_channels); + return -EINVAL; + } + + /* apply input/output channels count according to stream direction */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + params->channels = out_channels; + buffer = comp_dev_get_first_data_consumer(dev); + } else { + params->channels = in_channels; + buffer = comp_dev_get_first_data_producer(dev); + } + buffer_set_params(buffer, params, BUFFER_UPDATE_FORCE); + + /* set component period frames */ + buffer = comp_dev_get_first_data_consumer(dev); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&buffer->stream)); + + return 0; +} + +/** + * \brief Frees selector component. + * \param[in,out] mod Selector base module device. + */ +static int selector_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + mod_free(mod, cd->multi_coeffs_config); + mod_free(mod, cd); + + return 0; +} + +/** + * \brief Sets selector component audio stream parameters. + * \param[in,out] mod Selector base module device. + * \return Error code. + * + * All done in prepare since we need to know source and sink component params. + */ +static int selector_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + int err; + + comp_dbg(mod->dev, "entry"); + + set_selector_params(mod, params); + + err = selector_verify_params(mod, params); + if (err < 0) { + comp_err(mod->dev, "pcm params verification failed."); + return -EINVAL; + } + + return 0; +} + +static int selector_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_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int n; + + if (config_id == IPC4_SELECTOR_COEFFS_CONFIG_ID) { + if (data_offset_size > SEL_MAX_CONFIG_BLOB_SIZE || + fragment_size < data_offset_size || + pos != MODULE_CFG_FRAGMENT_SINGLE) { + comp_err(dev, "Failure with data_offset_size %u fragment_size %u pos %u", + data_offset_size, (uint32_t)fragment_size, (uint32_t)pos); + return -EINVAL; + } + + /* The size must be N times the coefficient vectors size of one channels + * up/down mix profile. + */ + n = data_offset_size / sizeof(struct ipc4_selector_coeffs_config); + if (n < 1 || data_offset_size != n * sizeof(struct ipc4_selector_coeffs_config)) { + comp_err(dev, "Invalid configuration size."); + return -EINVAL; + } + + cd->num_configs = n; + if (cd->multi_coeffs_config && cd->multi_coeffs_config_size < data_offset_size) { + /* Configuration exist but the allocation is too small to write over. */ + mod_free(mod, cd->multi_coeffs_config); + cd->multi_coeffs_config = NULL; + } + + if (!cd->multi_coeffs_config) { + cd->multi_coeffs_config_size = data_offset_size; + cd->multi_coeffs_config = mod_alloc(mod, cd->multi_coeffs_config_size); + if (!cd->multi_coeffs_config) { + comp_err(dev, "Failed to allocate configuration blob."); + return -ENOMEM; + } + } + + /* Copy the configuration and notify for need to re-configure. If for + * some reason the memcpy_s() would return an error (it can't because + * of the previous checks), the partial or incorrect blob would remain + * allocated but be freed later in module error handling and ending. + */ + cd->new_config = true; + return memcpy_s(cd->multi_coeffs_config, cd->multi_coeffs_config_size, + fragment, data_offset_size); + } + + return -EINVAL; +} + +static int selector_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, size_t fragment_size) +{ + /* ToDo: add support */ + return 0; +} + +/** + * \brief Loop the array of mix coefficients sets and find a set with matching channels + * in and out count. + * \param[in] cd Selector component data. + * \param[in] source_channels Number of channels in source. + * \param[in] sink_channels Number of channels in sink. + * + * \return Pointer to the matching ipc4_selector_coeffs_config if found, or NULL if + * no matching configuration exists. + */ +static struct ipc4_selector_coeffs_config *selector_config_array_search(struct comp_data *cd, + int source_channels, + int sink_channels) +{ + struct ipc4_selector_coeffs_config *found = NULL; + int i; + + for (i = 0; i < cd->num_configs; i++) { + if (cd->multi_coeffs_config[i].source_channels_count == source_channels && + cd->multi_coeffs_config[i].sink_channels_count == sink_channels) { + found = &cd->multi_coeffs_config[i]; + break; + } + } + + return found; +} + +/** + * \brief Get mix coefficients set from configuration blob with multiple coefficients sets. + * Also activate more efficient pass-through copy mode if the coefficients indicate 1:1 + * copy from source to sink. + * \param[in,out] mod Selector base module device. + * \param[in] source_channels Number of channels in source. + * \param[in] sink_channels Number of channels in sink. + * + * \return Error code. + */ +static int selector_find_coefficients(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct ipc4_selector_coeffs_config *config; + uint32_t source_channels = cd->config.in_channels_count; + uint32_t sink_channels = cd->config.out_channels_count; + int16_t coef; + int ret, i, j; + + /* In set_config() the blob is copied to cd->multi_coeffs_config. A legacy blob contains a + * single set of mix coefficients without channels information. A new blob with multiple + * configurations has the source and sink channels count information. If there has been no + * set_config(), then the cd->coeffs_config has been initialized in set_selector_params() + * to mix with coefficients SEL_COEF_ONE_Q10 for matching input and output channels. + */ + if (cd->multi_coeffs_config) { + if (cd->num_configs > 1) { + config = selector_config_array_search(cd, source_channels, sink_channels); + /* If not found, check if pass-through mix is defined for the max + * channels count (8). + */ + if (!config && source_channels == sink_channels) + config = selector_config_array_search(cd, SEL_SOURCE_CHANNELS_MAX, + SEL_SINK_CHANNELS_MAX); + + if (!config) { + comp_err(dev, "No mix coefficients found for %u to %u channels.", + source_channels, sink_channels); + return -EINVAL; + } + } else { + config = cd->multi_coeffs_config; + } + + ret = memcpy_s(&cd->coeffs_config, sizeof(struct ipc4_selector_coeffs_config), + config, sizeof(*config)); + if (ret) + return ret; + } + + /* The pass-through copy function can be used if coefficients are a unit matrix for + * 1:1 stream copy. + */ + if (source_channels == sink_channels) { + cd->passthrough = true; + for (i = 0; i < sink_channels; i++) { + for (j = 0; j < source_channels; j++) { + coef = cd->coeffs_config.coeffs[i][j]; + if ((i == j && coef != SEL_COEF_ONE_Q10) || (i != j && coef != 0)) { + cd->passthrough = false; + break; + } + } + } + } else { + cd->passthrough = false; + } + + if (cd->passthrough) + comp_info(dev, "Passthrough mode."); + else + comp_info(dev, "Using coefficients for %u to %u channels.", + source_channels, sink_channels); + + return 0; +} + +/** + * \brief Copies and processes stream data. + * \param[in,out] mod Selector base module device. + * \return Error code. + */ +static int selector_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 audio_stream *source; + struct audio_stream *sink; + struct comp_data *cd = module_get_private_data(mod); + uint32_t avail_frames = input_buffers[0].size; + int ret; + + comp_dbg(mod->dev, "entry"); + + if (cd->new_config) { + cd->new_config = false; + ret = selector_find_coefficients(mod); + if (ret) + return ret; + } + + if (cd->passthrough) { + source = input_buffers->data; + sink = output_buffers->data; + audio_stream_copy(source, 0, sink, 0, avail_frames * cd->config.in_channels_count); + module_update_buffer_position(input_buffers, output_buffers, avail_frames); + return 0; + } + + if (avail_frames) + /* copy selected channels from in to out */ + cd->sel_func(mod, input_buffers, output_buffers, avail_frames); + + return 0; +} + +/** + * \brief Prepares selector component for processing. + * \param[in,out] mod Selector base module device. + * \return Error code. + */ +static int selector_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct comp_buffer *sinkb, *sourceb; + size_t sink_size; + int ret; + + comp_dbg(dev, "entry"); + + ret = selector_params(mod); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + /* selector component will have 1 source and 1 sink buffer */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + + audio_stream_set_align(SOF_FRAME_BYTE_ALIGN, SOF_FRAME_COUNT_ALIGN, &sourceb->stream); + + /* get source data format and period bytes */ + cd->source_format = audio_stream_get_frm_fmt(&sourceb->stream); + cd->source_period_bytes = audio_stream_period_bytes(&sourceb->stream, dev->frames); + + /* get sink data format and period bytes */ + cd->sink_format = audio_stream_get_frm_fmt(&sinkb->stream); + cd->sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, dev->frames); + sink_size = audio_stream_get_size(&sinkb->stream); + md->mpd.in_buff_size = cd->source_period_bytes; + md->mpd.out_buff_size = cd->sink_period_bytes; + + if (sink_size < cd->sink_period_bytes) { + comp_err(dev, "sink buffer size %d is insufficient < %d", + sink_size, cd->sink_period_bytes); + return -ENOMEM; + } + + /* validate */ + if (cd->sink_period_bytes == 0) { + comp_err(dev, "cd->sink_period_bytes = 0, dev->frames = %u", + dev->frames); + return -EINVAL; + } + + if (cd->source_period_bytes == 0) { + comp_err(dev, "cd->source_period_bytes = 0, dev->frames = %u", + dev->frames); + return -EINVAL; + } + + cd->sel_func = sel_get_processing_function(mod); + if (!cd->sel_func) { + comp_err(dev, "invalid cd->sel_func, cd->source_format = %u, cd->sink_format = %u, cd->out_channels_count = %u", + cd->source_format, cd->sink_format, + cd->config.out_channels_count); + return -EINVAL; + } + + if (cd->new_config) { + cd->new_config = false; + return selector_find_coefficients(mod); + } + + return 0; +} + +/** + * \brief Resets selector component. + * \param[in,out] dev Selector base component device. + * \return Error code. + */ +static int selector_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + cd->source_period_bytes = 0; + cd->sink_period_bytes = 0; + cd->sel_func = NULL; + cd->num_configs = 0; + cd->passthrough = false; + cd->new_config = false; + return 0; +} + +/** \brief Selector component definition. */ +static const struct module_interface selector_interface = { + .init = selector_init, + .prepare = selector_prepare, + .process_audio_stream = selector_process, + .set_configuration = selector_set_config, + .get_configuration = selector_get_config, + .reset = selector_reset, + .free = selector_free +}; + +#if CONFIG_COMP_SEL_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("MICSEL", &selector_interface, 1, SOF_REG_UUID(selector4), 8); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(selector_tr, SOF_UUID(selector4_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(selector_interface, selector4_uuid, selector_tr); +SOF_MODULE_INIT(selector, sys_comp_module_selector_interface_init); + +#endif + +#endif diff --git a/src/audio/selector/selector.toml b/src/audio/selector/selector.toml new file mode 100644 index 000000000000..3c984a00fd45 --- /dev/null +++ b/src/audio/selector/selector.toml @@ -0,0 +1,61 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "MICSEL" + uuid = UUIDREG_STR_SELECTOR4 + affinity_mask = "0x1" + instance_count = "8" + domain_types = "0" + load_type = LOAD_TYPE + init_config = "1" + module_type = "0xC" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xe, 0xa, 0x45ff, 1, 0, 0xfeef, 0xe, 0xa, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 960, 488500, 16, 16, 0, 0, 0, + 1, 0, 0, 0, 960, 964500, 16, 16, 0, 0, 0, + 2, 0, 0, 0, 960, 2003000, 16, 16, 0, 0, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 216, 2338000, 384, 192, 0, 2338, 0, + 1, 0, 0, 0, 216, 3634000, 384, 384, 0, 3634, 0, + 2, 0, 0, 0, 216, 4524000, 576, 384, 0, 4524, 0, + 3, 0, 0, 0, 216, 4786000, 768, 384, 0, 4786, 0, + 4, 0, 0, 0, 216, 2914000, 768, 192, 0, 2914, 0, + 5, 0, 0, 0, 216, 3372000, 960, 192, 0, 3372, 0, + 6, 0, 0, 0, 216, 3516000, 1152, 192, 0, 3516, 0, + 7, 0, 0, 0, 216, 4066000, 1536, 192, 0, 4066, 0, + 8, 0, 0, 0, 216, 3058000, 192, 384, 0, 3058, 0, + 9, 0, 0, 0, 216, 5676000, 960, 384, 0, 5676, 0, + 10, 0, 0, 0, 216, 5964000, 1152, 384, 0, 5964, 0, + 11, 0, 0, 0, 216, 7090000, 1536, 384, 0, 7090, 0, + 12, 0, 0, 0, 216, 7090000, 192, 1152, 0, 7090, 0, + 13, 0, 0, 0, 216, 8818000, 384, 1152, 0, 8818, 0, + 14, 0, 0, 0, 216, 12274000, 768, 1152, 0, 12274, 0, + 15, 0, 0, 0, 216, 19186000, 1536, 1152, 0, 19186, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 216, 2952000, 384, 192, 0, 2952, 0, + 1, 0, 0, 0, 216, 4720000, 384, 384, 0, 4720, 0, + 2, 0, 0, 0, 216, 5705000, 576, 384, 0, 5705, 0, + 3, 0, 0, 0, 216, 6640000, 768, 384, 0, 6640, 0, + 4, 0, 0, 0, 216, 3910000, 768, 192, 0, 3910, 0, + 5, 0, 0, 0, 216, 4421000, 960, 192, 0, 4421, 0, + 6, 0, 0, 0, 216, 4899000, 1152, 192, 0, 4899, 0, + 7, 0, 0, 0, 216, 5832000, 1536, 192, 0, 5832, 0, + 8, 0, 0, 0, 216, 3768000, 192, 384, 0, 3768, 0, + 9, 0, 0, 0, 216, 7625000, 960, 384, 0, 7625, 0, + 10, 0, 0, 0, 216, 8595000, 1152, 384, 0, 8595, 0, + 11, 0, 0, 0, 216, 10488000, 1536, 384, 0, 10488, 0, + 12, 0, 0, 0, 216, 8952000, 192, 1152, 0, 8952, 0, + 13, 0, 0, 0, 216, 11832000, 384, 1152, 0, 11832, 0, + 14, 0, 0, 0, 216, 17592000, 768, 1152, 0, 17592, 0, + 15, 0, 0, 0, 216, 30172000, 1536, 1152, 0, 30172, 0] +#endif + + index = __COUNTER__ diff --git a/src/audio/selector/selector_generic.c b/src/audio/selector/selector_generic.c index 0560df5b03b0..5b4d8d8f5edd 100644 --- a/src/audio/selector/selector_generic.c +++ b/src/audio/selector/selector_generic.c @@ -5,19 +5,26 @@ // Author: Lech Betlej <lech.betlej@linux.intel.com> /** - * \file audio/selector_generic.c + * \file * \brief Audio channel selector / extractor - generic processing functions * \authors Lech Betlej <lech.betlej@linux.intel.com> */ #include <sof/audio/buffer.h> #include <sof/audio/component.h> +#include <sof/audio/format.h> #include <sof/audio/selector.h> #include <sof/common.h> #include <ipc/stream.h> #include <stddef.h> #include <stdint.h> +LOG_MODULE_DECLARE(selector, CONFIG_SOF_LOG_LEVEL); + +#define BYTES_TO_S16_SAMPLES 1 +#define BYTES_TO_S32_SAMPLES 2 + +#if CONFIG_IPC_MAJOR_3 #if CONFIG_FORMAT_S16LE /** * \brief Channel selection for 16 bit, 1 channel data format. @@ -30,16 +37,32 @@ static void sel_s16le_1ch(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - int16_t *src; - int16_t *dest; - uint32_t i; - uint32_t j = 0; - uint32_t nch = cd->config.in_channels_count; - - for (i = cd->config.sel_channel; i < frames * nch; i += nch) { - src = audio_stream_read_frag_s16(source, i); - dest = audio_stream_write_frag_s16(sink, j++); - *dest = *src; + 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 = audio_stream_get_channels(source); + const unsigned int sel_channel = cd->config.sel_channel; /* 0 to nch - 1 */ + + while (processed < frames) { + n = frames - processed; + nmax = audio_stream_bytes_without_wrap(source, src) / source_frame_bytes; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dest) >> BYTES_TO_S16_SAMPLES; + n = MIN(n, nmax); + src_ch = src + sel_channel; + for (i = 0; i < n; i++) { + *dest = *src_ch; + src_ch += nch; + dest++; + } + src = audio_stream_wrap(source, src + nch * n); + dest = audio_stream_wrap(sink, dest); + processed += n; } } @@ -53,21 +76,23 @@ static void sel_s16le_1ch(struct comp_dev *dev, struct audio_stream *sink, static void sel_s16le_nch(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames) { - struct comp_data *cd = comp_get_drvdata(dev); - int16_t *src; - int16_t *dest; - uint32_t i; - uint32_t j = 0; - uint32_t channel; - - for (i = 0; i < frames; i++) { - for (channel = 0; channel < cd->config.in_channels_count; - channel++) { - src = audio_stream_read_frag_s16(source, j); - dest = audio_stream_write_frag_s16(sink, j); - *dest = *src; - j++; - } + int8_t *src = audio_stream_get_rptr(source); + int8_t *dst = audio_stream_get_wptr(sink); + int bmax; + int b; + int bytes_copied = 0; + const int bytes_total = frames * audio_stream_frame_bytes(source); + + while (bytes_copied < bytes_total) { + b = bytes_total - bytes_copied; + bmax = audio_stream_bytes_without_wrap(source, src); + b = MIN(b, bmax); + bmax = audio_stream_bytes_without_wrap(sink, dst); + b = MIN(b, bmax); + memcpy_s(dst, b, src, b); + src = audio_stream_wrap(source, src + b); + dst = audio_stream_wrap(sink, dst + b); + bytes_copied += b; } } #endif /* CONFIG_FORMAT_S16LE */ @@ -84,16 +109,32 @@ static void sel_s32le_1ch(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - int32_t *src; - int32_t *dest; - uint32_t i; - uint32_t j = 0; - uint32_t nch = cd->config.in_channels_count; - - for (i = cd->config.sel_channel; i < frames * nch; i += nch) { - src = audio_stream_read_frag_s32(source, i); - dest = audio_stream_write_frag_s32(sink, j++); - *dest = *src; + 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 = audio_stream_get_channels(source); + const unsigned int sel_channel = cd->config.sel_channel; /* 0 to nch - 1 */ + + while (processed < frames) { + n = frames - processed; + nmax = audio_stream_bytes_without_wrap(source, src) / source_frame_bytes; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dest) >> BYTES_TO_S32_SAMPLES; + n = MIN(n, nmax); + src_ch = src + sel_channel; + for (i = 0; i < n; i++) { + *dest = *src_ch; + src_ch += nch; + dest++; + } + src = audio_stream_wrap(source, src + nch * n); + dest = audio_stream_wrap(sink, dest); + processed += n; } } @@ -107,26 +148,246 @@ static void sel_s32le_1ch(struct comp_dev *dev, struct audio_stream *sink, static void sel_s32le_nch(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t *src; - int32_t *dest; - uint32_t i; - uint32_t j = 0; - uint32_t channel; - - for (i = 0; i < frames; i++) { - for (channel = 0; channel < cd->config.in_channels_count; - channel++) { - src = audio_stream_read_frag_s32(source, j); - dest = audio_stream_write_frag_s32(sink, j); - *dest = *src; - j++; - } + int8_t *src = audio_stream_get_rptr(source); + int8_t *dst = audio_stream_get_wptr(sink); + int bmax; + int b; + int bytes_copied = 0; + const int bytes_total = frames * audio_stream_frame_bytes(source); + + while (bytes_copied < bytes_total) { + b = bytes_total - bytes_copied; + bmax = audio_stream_bytes_without_wrap(source, src); + b = MIN(b, bmax); + bmax = audio_stream_bytes_without_wrap(sink, dst); + b = MIN(b, bmax); + memcpy_s(dst, b, src, b); + src = audio_stream_wrap(source, src + b); + dst = audio_stream_wrap(sink, dst + b); + bytes_copied += b; } } #endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ +#else +#if CONFIG_FORMAT_S16LE +/** + * \brief Mixing routine for 16-bit, m channel input x n channel output single frame. + * \param[out] dst Sink buffer. + * \param[in] dst_channels Number of sink channels. + * \param[in] src Source data. + * \param[in] src_channels Number of source channels. + * \param[in] coeffs_config IPC4 micsel config with Q10 coefficients. + */ +static void process_frame_s16le(int16_t dst[], int dst_channels, + int16_t src[], int src_channels, + struct ipc4_selector_coeffs_config *coeffs_config) +{ + int32_t accum; + int i, j; + + for (i = 0; i < dst_channels; i++) { + accum = 0; + for (j = 0; j < src_channels; j++) + accum += (int32_t)src[j] * (int32_t)coeffs_config->coeffs[i][j]; + + /* shift out 10 LSbits with rounding to get 16-bit result */ + dst[i] = sat_int16((accum + (1 << 9)) >> 10); + } +} + +/** + * \brief Channel selection for 16-bit, m channel input x n channel output data format. + * \param[in] mod Selector base module device. + * \param[in,out] bsource Source buffer. + * \param[in,out] bsink Sink buffer. + * \param[in] frames Number of frames to process. + */ +static void sel_s16le(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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, 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; + nmax = audio_stream_bytes_without_wrap(source, src) / source_frame_bytes; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dest) / sink_frame_bytes; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + process_frame_s16le(dest, n_chan_sink, src, n_chan_source, + &cd->coeffs_config); + src += audio_stream_get_channels(source); + dest += audio_stream_get_channels(sink); + } + src = audio_stream_wrap(source, src); + dest = audio_stream_wrap(sink, dest); + processed += n; + } + + module_update_buffer_position(bsource, bsink, frames); +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +/** + * \brief Mixing routine for 24-bit, m channel input x n channel output single frame. + * \param[out] dst Sink buffer. + * \param[in] dst_channels Number of sink channels. + * \param[in] src Source data. + * \param[in] src_channels Number of source channels. + * \param[in] coeffs_config IPC4 micsel config with Q10 coefficients. + */ +static void process_frame_s24le(int32_t dst[], int dst_channels, + int32_t src[], int src_channels, + struct ipc4_selector_coeffs_config *coeffs_config) +{ + int64_t accum; + int i, j; + + for (i = 0; i < dst_channels; i++) { + accum = 0; + for (j = 0; j < src_channels; j++) + accum += (int64_t)src[j] * (int64_t)coeffs_config->coeffs[i][j]; + + /* accum is Q1.23 * Q6.10 --> Q7.33, shift right by 10 and + * saturate to get Q1.23. + */ + dst[i] = sat_int24((accum + (1 << 9)) >> 10); + } +} + +/** + * \brief Channel selection for 24-bit, m channel input x n channel output data format. + * \param[in] mod Selector base module device. + * \param[in,out] bsource Source buffer. + * \param[in,out] bsink Sink buffer. + * \param[in] frames Number of frames to process. + */ +static void sel_s24le(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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, 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; + nmax = audio_stream_bytes_without_wrap(source, src) / source_frame_bytes; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dest) / sink_frame_bytes; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + process_frame_s24le(dest, n_chan_sink, src, n_chan_source, + &cd->coeffs_config); + src += audio_stream_get_channels(source); + dest += audio_stream_get_channels(sink); + } + src = audio_stream_wrap(source, src); + dest = audio_stream_wrap(sink, dest); + processed += n; + } + + module_update_buffer_position(bsource, bsink, frames); +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief Mixing routine for 32-bit, m channel input x n channel output single frame. + * \param[out] dst Sink buffer. + * \param[in] dst_channels Number of sink channels. + * \param[in] src Source data. + * \param[in] src_channels Number of source channels. + * \param[in] coeffs_config IPC4 micsel config with Q10 coefficients. + */ +static void process_frame_s32le(int32_t dst[], int dst_channels, + int32_t src[], int src_channels, + struct ipc4_selector_coeffs_config *coeffs_config) +{ + int64_t accum; + int i, j; + + for (i = 0; i < dst_channels; i++) { + accum = 0; + for (j = 0; j < src_channels; j++) + accum += (int64_t)src[j] * (int64_t)coeffs_config->coeffs[i][j]; + + /* shift out 10 LSbits with rounding to get 32-bit result */ + dst[i] = sat_int32((accum + (1 << 9)) >> 10); + } +} + +/** + * \brief Channel selection for 32-bit, m channel input x n channel output data format. + * \param[in] mod Selector base module device. + * \param[in,out] bsource Source buffer. + * \param[in,out] bsink Sink buffer. + * \param[in] frames Number of frames to process. + */ +static void sel_s32le(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames) +{ + struct comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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, 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; + nmax = audio_stream_bytes_without_wrap(source, src) / source_frame_bytes; + n = MIN(n, nmax); + nmax = audio_stream_bytes_without_wrap(sink, dest) / sink_frame_bytes; + n = MIN(n, nmax); + for (i = 0; i < n; i++) { + process_frame_s32le(dest, n_chan_sink, src, n_chan_source, + &cd->coeffs_config); + src += audio_stream_get_channels(source); + dest += audio_stream_get_channels(sink); + } + src = audio_stream_wrap(source, src); + dest = audio_stream_wrap(sink, dest); + processed += n; + } + + module_update_buffer_position(bsource, bsink, frames); +} +#endif /* CONFIG_FORMAT_S32LE */ +#endif + const struct comp_func_map func_table[] = { +#if CONFIG_IPC_MAJOR_3 #if CONFIG_FORMAT_S16LE {SOF_IPC_FRAME_S16_LE, 1, sel_s16le_1ch}, {SOF_IPC_FRAME_S16_LE, 2, sel_s16le_nch}, @@ -142,8 +403,20 @@ const struct comp_func_map func_table[] = { {SOF_IPC_FRAME_S32_LE, 2, sel_s32le_nch}, {SOF_IPC_FRAME_S32_LE, 4, sel_s32le_nch}, #endif /* CONFIG_FORMAT_S32LE */ +#else +#if CONFIG_FORMAT_S16LE + {SOF_IPC_FRAME_S16_LE, 0, sel_s16le}, +#endif +#if CONFIG_FORMAT_S24LE + {SOF_IPC_FRAME_S24_4LE, 0, sel_s24le}, +#endif +#if CONFIG_FORMAT_S32LE + {SOF_IPC_FRAME_S32_LE, 0, sel_s32le}, +#endif +#endif }; +#if CONFIG_IPC_MAJOR_3 sel_func sel_get_processing_function(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); @@ -162,3 +435,21 @@ sel_func sel_get_processing_function(struct comp_dev *dev) return NULL; } +#else +sel_func sel_get_processing_function(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + int i; + + /* map the channel selection function for source and sink buffers */ + for (i = 0; i < ARRAY_SIZE(func_table); i++) { + if (cd->source_format != func_table[i].source) + continue; + + /* TODO: add additional criteria as needed */ + return func_table[i].sel_func; + } + + return NULL; +} +#endif diff --git a/src/audio/selector/tune/sof_selector_blobs.m b/src/audio/selector/tune/sof_selector_blobs.m new file mode 100644 index 000000000000..1b370d4030de --- /dev/null +++ b/src/audio/selector/tune/sof_selector_blobs.m @@ -0,0 +1,261 @@ +% sof_selector_blobs - export configuration blobs for Selector +% +% This script is run without arguments. It exports a number of +% configuration blobs for selector/micsel component. The first +% category of blobs are for upmix and downmix between mono to +% 7.1 channel audio formats. +% +% The second category is for duplicating stereo to four channels +% for 2-way speaker crossover filter. +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2025-2026, Intel Corporation. + +function sof_selector_blobs() + + % See ITU-R BS.775-4 for mix coefficient values + sof_selector_paths(true); + + % Values of enum ipc4_channel_config + IPC4_CHANNEL_CONFIG_MONO = 0; + IPC4_CHANNEL_CONFIG_STEREO = 1; + IPC4_CHANNEL_CONFIG_QUATRO = 5; + IPC4_CHANNEL_CONFIG_5_POINT_1 = 8; + IPC4_CHANNEL_CONFIG_7_POINT_1 = 12; + + % Matrix for 1:1 pass-through + sel.ch_count = [8 8]; % Number of channels + sel.ch_config = [IPC4_CHANNEL_CONFIG_7_POINT_1 IPC4_CHANNEL_CONFIG_7_POINT_1]; + sel.coeffs = diag(ones(8, 1)); + passthrough_pack8 = write_blob(sel, "passthrough"); + + % Stereo to mono downmix + sel.ch_count = [2 1]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_STEREO IPC4_CHANNEL_CONFIG_MONO]; + sel.coeffs = zeros(8,8); + sel.coeffs(1, 1) = 0.7071; + sel.coeffs(1, 2) = 0.7071; + stereo_to_mono_pack8 = write_blob(sel, "downmix_stereo_to_mono"); + + % 5.1 to stereo downmix + sel.ch_count = [6 2]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_5_POINT_1 IPC4_CHANNEL_CONFIG_STEREO]; + fl = 1; fr = 2; fc = 3; lfe = 4; sl = 5; sr = 6; + m = zeros(8,8); + m(1, fl) = 1.0000; m(1, fr) = 0.0000; m(1, fc) = 0.7071; m(1, sl) = 0.7071; m(1, sr) = 0.0000; + m(2, fl) = 0.0000; m(2, fr) = 1.0000; m(2, fc) = 0.7071; m(2, sl) = 0.0000; m(2, sr) = 0.7071; + sel.coeffs = m; + sel.coeffs(1, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to left + sel.coeffs(2, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to right + sixch_to_stereo_pack8 = write_blob(sel, "downmix_51_to_stereo_with_lfe"); + + % 5.1 to mono downmix + sel.ch_count = [6 1]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_5_POINT_1 IPC4_CHANNEL_CONFIG_MONO]; + fl = 1; fr = 2; fc = 3; lfe = 4; sl = 5; sr = 6; + m = zeros(8,8); + m(1, fl) = 0.7071; m(1, fr) = 0.7071; m(1, fc) = 1.0000; m(1, sl) = 0.5000; m(1, sr) = 0.5000; + sel.coeffs = m; + sel.coeffs(1, lfe) = 10^(+10/20); + sixch_to_mono_pack8 = write_blob(sel, "downmix_51_to_mono_with_lfe"); + + % 7.1 to 5.1 downmix + sel.ch_count = [8 6]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_7_POINT_1 IPC4_CHANNEL_CONFIG_5_POINT_1]; + fl8 = 1; fr8 = 2; fc8 = 3; lfe8 = 4; bl8 = 5; br8 = 6; sl8 = 7; sr8 = 8; + fl6 = 1; fr6 = 2; fc6 = 3; lfe6 = 4; sl6 = 5; sr6 = 6; + m = zeros(8,8); + m(fl6, fl8) = 1; + m(fr6, fr8) = 1; + m(fc6, fc8) = 1; + m(sl6, sl8) = 1; + m(sr6, sr8) = 1; + m(sl6, bl8) = 1; + m(sr6, br8) = 1; + m(lfe6, lfe8) = 1; + sel.coeffs = m; + eightch_to_sixch_pack8 = write_blob(sel, "downmix_71_to_51"); + + % 7.1 to stereo downmix + sel.ch_count = [8 2]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_7_POINT_1 IPC4_CHANNEL_CONFIG_STEREO]; + fl = 1; fr = 2; fc = 3; lfe = 4; bl = 5; br = 6; sl = 7; sr = 8; + m = zeros(8,8); + m(1, fl) = 1.0000; m(1, fr) = 0.0000; m(1, fc) = 0.7071; m(1, sl) = 0.7071; m(1, sr) = 0.0000; m(1, bl) = 0.7071; m(1, br) = 0.0000; + m(2, fl) = 0.0000; m(2, fr) = 1.0000; m(2, fc) = 0.7071; m(2, sl) = 0.0000; m(2, sr) = 0.7071; m(2, bl) = 0.0000; m(2, br) = 0.7071; + sel.coeffs = m; + sel.coeffs(1, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to left + sel.coeffs(2, lfe) = 10^(+4/20); % +10 dB, attenuate by -6 dB to right + eightch_to_stereo_pack8 = write_blob(sel, "downmix_71_to_stereo_with_lfe"); + + % 7.1 to mono downmix + sel.ch_count = [8 1]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_7_POINT_1 IPC4_CHANNEL_CONFIG_MONO]; + fl = 1; fc = 3; fr = 2; sr = 8; br = 6; bl = 5; sl = 7; lfe = 4; + m = zeros(8,8); + m(1, fl) = 0.7071; m(1, fr) = 0.7071; m(1, fc) = 1.0000; m(1, sl) = 0.5000; m(1, sr) = 0.5000; m(1, bl) = 0.5000; m(1, br) = 0.5000; + sel.coeffs = m; + m(1, lfe) = 10^(+19/20); % +10 dB + eightch_to_mono_pack8 = write_blob(sel, "downmix_71_to_mono_with_lfe"); + + % mono to stereo upmix + sel.ch_count = [1 2]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_MONO IPC4_CHANNEL_CONFIG_STEREO]; + sel.coeffs = zeros(8,8); + sel.coeffs(1, 1) = 10^(-3/20); + sel.coeffs(2, 1) = 10^(-3/20); + mono_to_stereo_pack8 = write_blob(sel, "upmix_mono_to_stereo"); + + % mono to 5.1 / 7.1 upmix + sel.ch_count = [1 6]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_MONO IPC4_CHANNEL_CONFIG_5_POINT_1]; + fc = 3; + sel.coeffs = zeros(8,8); + sel.coeffs(fc, 1) = 1; + mono_to_sixch_pack8 = write_blob(sel, "upmix_mono_to_51"); + sel.ch_count = [1 8]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_MONO IPC4_CHANNEL_CONFIG_7_POINT_1]; + mono_to_eightch_pack8 = write_blob(sel, "upmix_mono_to_71"); + + % stereo to 5.1 / 7.1 upmix + sel.ch_count = [2 6]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_STEREO IPC4_CHANNEL_CONFIG_5_POINT_1]; + fl = 1; fr = 2; + sel.coeffs = zeros(8,8); + sel.coeffs(fl, 1) = 1; + sel.coeffs(fr, 2) = 1; + stereo_to_sixch_pack8 = write_blob(sel, "upmix_stereo_to_51"); + sel.ch_count = [2 8]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_STEREO IPC4_CHANNEL_CONFIG_7_POINT_1]; + stereo_to_eightch_pack8 = write_blob(sel, "upmix_stereo_to_71"); + + % For blob format with multiple up/down-mix profiles, intended + % for playback decoder offload conversions. + multi_pack8 = [passthrough_pack8 mono_to_stereo_pack8 sixch_to_stereo_pack8 eightch_to_stereo_pack8]; + write_8bit_packed(multi_pack8, 'stereo_endpoint_playback_updownmix'); + + % Stereo to L,L,R,R + sel.ch_count = [2 4]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_STEREO IPC4_CHANNEL_CONFIG_QUATRO]; + sel.coeffs = [ 1 0 0 0 0 0 0 0 ; ... + 1 0 0 0 0 0 0 0 ; ... + 0 1 0 0 0 0 0 0 ; ... + 0 1 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ]; + write_blob(sel, "xover_selector_lr_to_llrr"); + + % Stereo to R,R,L,L + sel.ch_count = [2 4]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_STEREO IPC4_CHANNEL_CONFIG_QUATRO]; + sel.coeffs = [ 0 1 0 0 0 0 0 0 ; ... + 0 1 0 0 0 0 0 0 ; ... + 1 0 0 0 0 0 0 0 ; ... + 1 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ]; + write_blob(sel, "xover_selector_lr_to_rrll"); + + % Stereo to L,R,L,R + sel.ch_count = [2 4]; + sel.ch_config = [IPC4_CHANNEL_CONFIG_STEREO IPC4_CHANNEL_CONFIG_QUATRO]; + sel.coeffs = [ 1 0 0 0 0 0 0 0 ; ... + 0 1 0 0 0 0 0 0 ; ... + 1 0 0 0 0 0 0 0 ; ... + 0 1 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ; ... + 0 0 0 0 0 0 0 0 ]; + write_blob(sel, "xover_selector_lr_to_lrlr"); + + sof_selector_paths(false); +end + +function pack8 = write_blob(sel, blobname) + pack8 = pack_selector_config(sel); + pack8_copy = pack8; + pack8_copy(1:4) = uint8([0 0 0 0]); + write_8bit_packed(pack8_copy, blobname); +end + +function write_8bit_packed(pack8, blobname) + blob8 = sof_selector_build_blob(pack8); + str_config = "selector_config"; + str_exported = "Exported with script sof_selector_blobs.m"; + str_howto = "cd tools/tune/selector; octave sof_selector_blobs.m"; + sof_tools = '../../../../tools'; + sof_tplg = fullfile(sof_tools, 'topology'); + sof_tplg_selector = fullfile(sof_tplg, 'topology2/include/components/micsel'); + tplg2_fn = sprintf("%s/%s.conf", sof_tplg_selector, blobname); + sof_check_create_dir(tplg2_fn); + sof_tplg2_write(tplg2_fn, blob8, str_config, str_exported, str_howto); +end + +function pack8 = pack_selector_config(sel) + + sum_coefs = sum(sel.coeffs, 2)'; + max_sum_coef = max(sum_coefs); + if max_sum_coef > 1 + scale = 1 / max_sum_coef; + else + scale = 1; + end + + sel.coeffs = scale .* sel.coeffs'; + coeffs_vec = reshape(sel.coeffs, 1, []); % convert to row vector + coeffs_q10 = int16(round(coeffs_vec .* 1024)); % Q6.10 + pack8 = uint8(zeros(1, 2 * length(coeffs_q10) + 4)); + + % header + j = 1; + pack8(j:j + 1) = uint8(sel.ch_count); + j = j + 2; + pack8(j:j + 1) = uint8(sel.ch_config); + j = j + 2; + + % coeffs matrix + for i = 1:length(coeffs_q10) + pack8(j:j+1) = int16_to_byte(coeffs_q10(i)); + j = j + 2; + end + + end + +function sof_selector_paths(enable) + + common = '../../../../tools/tune/common'; + if enable + addpath(common); + else + rmpath(common); + end +end + +function blob8 = sof_selector_build_blob(pack8) + + blob_type = 0; + blob_param_id = 0; % IPC4_SELECTOR_COEFFS_CONFIG_ID + data_size = length(pack8); + ipc_ver = 4; + [abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver, blob_type, blob_param_id); + blob_size = data_size + abi_size; + blob8 = uint8(zeros(1, blob_size)); + blob8(1:abi_size) = abi_bytes; + j = abi_size + 1; + + blob8(j:j+data_size-1) = pack8; +end + +function bytes = int16_to_byte(word) + sh = [0 -8]; + bytes = uint8(zeros(1,2)); + bytes(1) = bitand(bitshift(word, sh(1)), 255); + bytes(2) = bitand(bitshift(word, sh(2)), 255); +end diff --git a/src/audio/sink_api_helper.c b/src/audio/sink_api_helper.c new file mode 100644 index 000000000000..5d25474ac6b8 --- /dev/null +++ b/src/audio/sink_api_helper.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include <sof/audio/sink_api.h> +#include <sof/audio/audio_stream.h> + +/* This file contains private sink API functions intended for use only by the sof. */ + +void sink_init(struct sof_sink *sink, const struct sink_ops *ops, + struct sof_audio_stream_params *audio_stream_params) +{ + sink->ops = ops; + sink->audio_stream_params = audio_stream_params; +} + +size_t sink_get_num_of_processed_bytes(struct sof_sink *sink) +{ + return sink->num_of_bytes_processed; +} + +void sink_reset_num_of_processed_bytes(struct sof_sink *sink) +{ + sink->num_of_bytes_processed = 0; +} + +bool sink_get_overrun(struct sof_sink *sink) +{ + return sink->audio_stream_params->overrun_permitted; +} + +void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space) +{ + sink->min_free_space = min_free_space; +} diff --git a/src/audio/sink_source_utils.c b/src/audio/sink_source_utils.c new file mode 100644 index 000000000000..1fb86df386c2 --- /dev/null +++ b/src/audio/sink_source_utils.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// + +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <rtos/string.h> +#include <rtos/symbol.h> +#include <sof/math/numbers.h> +#include <limits.h> + +int source_to_sink_copy(struct sof_source *source, + struct sof_sink *sink, bool free, size_t size) +{ + uint8_t const *src_ptr; + uint8_t const *src_begin; + uint8_t const *src_end; + uint8_t *dst_ptr; + uint8_t *dst_begin; + uint8_t *dst_end; + size_t src_size, dst_size; + int ret; + + if (!size) + return 0; + if (size > source_get_data_available(source)) + return -EFBIG; + if (size > sink_get_free_size(sink)) + return -ENOSPC; + + ret = source_get_data(source, size, + (void const **)&src_ptr, + (void const **)&src_begin, + &src_size); + if (ret) + return ret; + + ret = sink_get_buffer(sink, size, + (void **)&dst_ptr, + (void **)&dst_begin, + &dst_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + + src_end = src_begin + src_size; + dst_end = dst_begin + dst_size; + while (size) { + uint32_t src_to_buf_overlap = (uintptr_t)src_end - (uintptr_t)src_ptr; + uint32_t dst_to_buf_overlap = (uintptr_t)dst_end - (uintptr_t)dst_ptr; + uint32_t to_copy = MIN(src_to_buf_overlap, dst_to_buf_overlap); + + to_copy = MIN(to_copy, size); + ret = memcpy_s(dst_ptr, dst_to_buf_overlap, src_ptr, to_copy); + assert(!ret); + + size -= to_copy; + src_ptr += to_copy; + dst_ptr += to_copy; + if (to_copy == src_to_buf_overlap) + src_ptr = src_begin; + if (to_copy == dst_to_buf_overlap) + dst_ptr = dst_begin; + } + + source_release_data(source, free ? INT_MAX : 0); + sink_commit_buffer(sink, INT_MAX); + return 0; +} +EXPORT_SYMBOL(source_to_sink_copy); + +int sink_fill_with_silence(struct sof_sink *sink, size_t size) +{ + uint8_t *dst_ptr; + uint8_t *dst_begin; + uint8_t *dst_end; + size_t dst_size; + int ret; + + if (!size) + return 0; + if (size > sink_get_free_size(sink)) + return -ENOSPC; + + ret = sink_get_buffer(sink, size, (void **)&dst_ptr, (void **)&dst_begin, &dst_size); + if (ret) + return ret; + + dst_end = dst_begin + dst_size; + while (size) { + uint32_t dst_to_buf_overlap = (uintptr_t)dst_end - (uintptr_t)dst_ptr; + uint32_t to_fill = MIN(dst_to_buf_overlap, size); + + ret = memset_s(dst_ptr, dst_to_buf_overlap, 0, to_fill); + assert(!ret); + + size -= to_fill; + dst_ptr += to_fill; + if (to_fill == dst_to_buf_overlap) + dst_ptr = dst_begin; + } + + sink_commit_buffer(sink, INT_MAX); + return 0; +} +EXPORT_SYMBOL(sink_fill_with_silence); + +int source_drop_data(struct sof_source *source, size_t size) +{ + uint8_t const *src_ptr; + uint8_t const *src_begin; + size_t src_size; + int ret; + + if (!size) + return 0; + if (size > source_get_data_available(source)) + return -EFBIG; + + ret = source_get_data(source, size, + (void const **)&src_ptr, + (void const **)&src_begin, + &src_size); + if (ret) + return ret; + + source_release_data(source, INT_MAX); + return 0; +} +EXPORT_SYMBOL(source_drop_data); diff --git a/src/audio/smart_amp/CMakeLists.txt b/src/audio/smart_amp/CMakeLists.txt new file mode 100644 index 000000000000..cb4eac564634 --- /dev/null +++ b/src/audio/smart_amp/CMakeLists.txt @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof smart_amp.c smart_amp_generic.c) + +if(CONFIG_MAXIM_DSM) + add_local_sources(sof smart_amp_maxim_dsm.c) + if(CONFIG_MAXIM_DSM_STUB) + add_local_sources(sof maxim_dsm_stub.c) + endif() +else() + add_local_sources(sof smart_amp_passthru.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + if(CONFIG_MAXIM_DSM) + if(NOT CONFIG_MAXIM_DSM_STUB) + zephyr_library_import(dsm ${CMAKE_CURRENT_LIST_DIR}/lib/release/dsm_lib/libdsm.a) + endif() + + zephyr_include_directories(CONFIG_MAXIM_DSM ${CMAKE_CURRENT_LIST_DIR}/include/dsm_api/inc/) + endif() + +endif() diff --git a/src/audio/smart_amp/Kconfig b/src/audio/smart_amp/Kconfig new file mode 100644 index 000000000000..51564f99eebc --- /dev/null +++ b/src/audio/smart_amp/Kconfig @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_SMART_AMP + bool "Smart Amplifier component" + help + Select for Smart Amp component. This component protect the speaker + from overheating and excursion violation. This consists of two parts + which are feedforward processing block running on playback thread + and feedback processing block running on capture thread with amp + current and voltage feedback. The internal design of this component + depends on the applied Amplifier HW solution, which should be provided + by the solution supplier respectively. + +if COMP_SMART_AMP + +choice + prompt "Smart Amplifier solution applied" + default PASSTHRU_AMP + help + The selection for Smart Amplifier component implementation + will depend on the Amplifier solution supplier. It is fair + to treat the supported solutions as mutually exclusive ones. + There should be no more than one solution selected per build + config. When Smart Amplifier is present but no solution is + supported, the passthrough mode will be applied as default. + + config PASSTHRU_AMP + bool "Stream Passthrough" + help + The default option as the passthrough mode while no other + solution is applied. While selected, the feed-forward input + frames will be passed to output after channel remapping. No + gain or latency will be produced. In the meanwhile, the + feedback input frames will be consumed but dropped directly. + + config MAXIM_DSM + bool "Maxim DSM solution" + select MAXIM_DSM_STUB if COMP_STUBS + help + Select to apply Maxim DSM(Dynamic Speaker Management) solution + for Smart Amplifier. As the third-party supply, the + pre-compiled library provided by Maxim will be required for + building the FW binary with this option enabled. The library + itself should be statically linked with the SoF FW binary image. + +endchoice + + config MAXIM_DSM_STUB + bool "Maxim DSM solution" + depends on MAXIM_DSM + help + Select to build the Maxim DSM adapter with a stub library. This + should only be used for CI and testing. + +endif diff --git a/src/audio/smart_amp/README.md b/src/audio/smart_amp/README.md new file mode 100644 index 000000000000..848d7abd7b15 --- /dev/null +++ b/src/audio/smart_amp/README.md @@ -0,0 +1,23 @@ +# Smart Amplifier Architecture + +This directory contains the Smart Amp Component. + +## Overview + +Uses predictive speaker models and real-time Current/Voltage (I/V) feedback to push speakers louder without causing thermal damage or physical over-excursion. + +## Architecture Diagram + +```mermaid +graph LR + In[Audio Input] --> Proc[Protection Algorithm] + FB[I/V Sense Input] --> Proc + Model[(Speaker Parameters)] --> Proc + Proc --> Out[Safe Audio Output] +``` + +## Configuration and Scripts + +- **Kconfig**: Enables the Smart Amplifier component (`COMP_SMART_AMP`). Features selectable architectures depending on third-party supply (defaults to `PASSTHRU_AMP`, or optionally `MAXIM_DSM` utilizing `libdsm.a`). Includes stubs for CI (`MAXIM_DSM_STUB`). +- **CMakeLists.txt**: Manages standard smart amp implementations (`smart_amp.c`, `smart_amp_generic.c`) and vendor-specific paths (`smart_amp_maxim_dsm.c`, `smart_amp_passthru.c`). Uses `zephyr_library_import` to link the Maxim SDK libraries. +- **Topology (.conf)**: Configured in `tools/topology/topology2/include/components/smart_amp.conf`, declaring a `smart_amp` effect component with UUID `1e:96:7a:16:e4:8a:ea:11:89:f1:00:0c:29:ce:16:35` (matching the test module) and hardcoding default configuration payloads into ALSA controls (`tlv_read`/`extctl`). diff --git a/src/audio/smart_amp/include/dsm_api/inc/dsm_api_public.h b/src/audio/smart_amp/include/dsm_api/inc/dsm_api_public.h new file mode 100644 index 000000000000..30ab34995f61 --- /dev/null +++ b/src/audio/smart_amp/include/dsm_api/inc/dsm_api_public.h @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Maxim Integrated All rights reserved. + * + * Author: Ryan Lee <ryans.lee@maximintegrated.com> + */ +#ifndef _DSM_API_PUBLIC_H_ +#define _DSM_API_PUBLIC_H_ + +#define DSM_CH_MASK(cmd_id) ((cmd_id) & 0x00FFFFFF) +#define DSM_CH1_BITMASK 0x1000000 +#define DSM_CH2_BITMASK 0x2000000 +#define DSM_SET_STEREO_CMD_ID(cmd_id) (DSM_CH_MASK(cmd_id) | 0x03000000) +#define DSM_SET_CMD_ID(cmd_id) DSM_SET_STEREO_CMD_ID(cmd_id) + +#define DSM_DEFAULT_NUM_CHANNEL 2 +#define DSM_DEFAULT_SAMPLE_RATE 48000 +#define DSM_DEFAULT_NUM_EQ 8 +#define DSM_DEFAULT_MAX_NUM_PARAM 250 + +#define DSM_GET_PARAM_SZ_PAYLOAD (1 + DSM_DEFAULT_NUM_CHANNEL) +#define DSM_SET_PARAM_SZ_PAYLOAD (DSM_DEFAULT_NUM_CHANNEL * 2 + 1) + +#define DSM_API_GET_MAXIMUM_CMD_ID 0 + +enum dsm_getparam_payload_index { + DSM_GET_ID_IDX = 0, + DSM_GET_CH1_IDX, + DSM_GET_CH2_IDX, + DSM_GET_IDX_MAX +}; + +enum dsm_setparam_payload_index { + DSM_SET_ID_IDX = 0, + DSM_SET_VALUE_IDX, + DSM_SET_IDX_MAX +}; + +struct dsm_api_memory_size_ext_t { + int isamplingrate; + int ichannels; + int *ipcircbuffersizebytes; + int omemsizerequestedbytes; + int numeqfilters; +}; + +struct dsm_api_init_ext_t { + int isamplingrate; + int ichannels; + int off_framesizesamples; + int ofb_framesizesamples; + int *ipcircbuffersizebytes; + int *ipdelayedsamples; + int isamplebitwidth; +}; + +enum DSM_API_MESSAGE { + DSM_API_OK = 0, + DSM_API_MSG_NULL_MODULE_HANDLER = 1 << 1, + DSM_API_MSG_NULL_PARAM_POINTER = 1 << 2, + DSM_API_MSG_NULL_INPUT_BUFFER_POINTER = 1 << 3, + DSM_API_MSG_NULL_OUTPUT_BUFFER_POINTER = 1 << 4, + DSM_API_MSG_INVALID_CMD_ID = 1 << 5, + DSM_API_MSG_INVALID_PARAM = 1 << 6, + DSM_API_MSG_INVALID_PARAMS_NUM = 1 << 7, + DSM_API_MSG_INVALID_SAMPLING_RATE = 1 << 8, + DSM_API_MSG_NOT_IMPLEMENTED = 1 << 9, + DSM_API_MSG_INVALID_MEMORY = 1 << 10, + DSM_API_MSG_ZERO_I = 1 << 11, + DSM_API_MSG_ZERO_V = 1 << 12, + DSM_API_MSG_MIN_RDC_BEYOND_THRESHOLD = 1 << 13, + DSM_API_MSG_MAX_RDC_BEYOND_THRESHOLD = 1 << 14, + DSM_API_MISMATCHED_SETGET_CMD = 1 << 15, + DSM_API_MSG_IV_DATA_WARNING = 1 << 16, + DSM_API_MSG_COIL_TEMPERATURE_WARNING = 1 << 17, + DSM_API_MSG_EXCURSION_WARNING = 1 << 18, + DSM_API_MSG_WRONG_COMMAND_TYPE = 1 << 19, + DSM_API_MSG_COMMAND_OBSOLETE = 1 << 20, + DSM_API_MSG_INSUFFICIENT_INPUT_DATA = 1 << 21, + DSM_API_MSG_FF_NOT_START = 1 << 22, + DSM_API_MSG_INVALID +}; + +#define DSM_API_ADAPTIVE_PARAM_START 0x10 +#define DSM_API_ADAPTIVE_PARAM_END 0x14 + +/******************************************************************************* + * dsm_api_get_mem() + * + * Description: + * This function returns the size of data memory which is required by DSM module + * and must be called before any other DSM API functions. + * The DSP framework should be responsible for allocating memory for + * DSM module. + * + * Input: + * iparamsize: the size of the data structure dsm_api_memory_size_ext_t. + * + * Output: + * N/A + * + * I/O: + * iopMemParam: the address of data structure dsm_api_memory_size_ext_t + * which contains input and output arguments. + * + * Returns: + * DSM_API_OK: successful + * Otherwise: error code + * + *******************************************************************************/ +enum DSM_API_MESSAGE dsm_api_get_mem(struct dsm_api_memory_size_ext_t *iopmmemparam, + int iparamsize); + +/******************************************************************************* + * dsm_api_init() + * + * Description: + * This function is used to initialize DSM module and must be called after + * dsm_api_get_mem() and before all other DSM API functions. + * + * Inputs: + * ipmodulehandler: + * the handler of DSM module which is allocated by framework caller. + * iparamsize: the size of the data structure dsm_api_init_ext_t. + * + * Outputs: + * N/A + * + * I/O: + * iopparamstruct: the address of a data structure dsm_api_init_ext_t + * which contains input and output arguments. + * + * Returns: + * DSM_API_OK: successful + * Otherwise: error code + * + *******************************************************************************/ +enum DSM_API_MESSAGE dsm_api_init(void *ipmodulehandler, + struct dsm_api_init_ext_t *iopparamstruct, + int iparamsize); + +/******************************************************************************* + * dsm_api_ff_processs() + * + * Description: + * This function is used to process the input audio PCM DSM data. + * + * Inputs: + * ipmodulehandler: + * the handler of DSM module which is allocated by framework caller. + * ichannelmask: the low 8-bits indicate which channels should be executed. + * 0: default channels setting, mono or stereo + * 1: L channel + * 2: R channel + * 3: L and R channels + * -1: place input L channel onto output R channel + * -2: place input R channel onto output L channel + * -3: switch L and R channel + * ibufferorg: the input buffer which contains 16-bit audio PCM input data. + * The multi-channel input PCM data are ordered in the format below: + * +-----------------------+ ... +-------------------------+ + * | one frame samples | ... | one frame samples | + * +-----------------------+ ... +-------------------------+ + * 1st channel ... N-th channel + * + * Outputs: + * obufferorg: the output buffer which contains the 16-bit PCM data processed by DSM. + * The multi-channel output PCM data are ordered in the format below: + * +-----------------------+ ... +-------------------------+ + * | one frame samples | ... | one frame samples | + * +-----------------------+ ... +-------------------------+ + * 1st channel ... N-th channel + * opnrsamples: the address of a variable which contains the number of samples + * in output buffer. + * + * I/O: + * ipnrsamples: the number of audio PCM samples to be processed, in 32-bit + * long integer. + * The returned value indicates how many samples of input data are + * not used in the input buffer. In this case, DSP framework should + * send back the remaining data in next process. + * + * Returns: + * DSM_API_OK: successful + * Otherwise: error codes + * + *******************************************************************************/ +enum DSM_API_MESSAGE dsm_api_ff_process(void *ipmodulehandler, + int channelmask, + short *ibufferorg, + int *ipnrsamples, + short *obufferorg, + int *opnrsamples); + +/******************************************************************************* + * dsm_api_fb_processs() + * + * Description: + * This function is used to process current(I) and voltage(V) feedback data. + * + * Inputs: + * ipmodulehandler: + * the handler of DSM module which is allocated by framework caller. + * ichannelmask: the low 8-bits indicate which channels should be executed. + * 0: default channels setting, mono or stereo + * 1: L channel + * 2: R channel + * 3: L and R channels + * -1: place input L channel onto output R channel + * -2: place input R channel onto output L channel + * -3: switch L and R channel + * icurrbuffer: the input buffer which contains I data. + * The multi-channel I data are ordered in the format below: + * +-----------------------+ ... +-------------------------+ + * | one frame samples | ... | one frame samples | + * +-----------------------+ ... +-------------------------+ + * 1st channel ... N-th channel + * ivoltbuffer: the input buffer which contains V data. + * The multi-channel V data are ordered in the format below: + * +-----------------------+ ... +-------------------------+ + * | one frame samples | ... | one frame samples | + * +-----------------------+ ... +-------------------------+ + * 1st channel ... N-th channel + * + * I/O: + * iopnrsamples: the address of a variable which contains number of I/V data to + * be processed. + * The returned value indicates how many samples of I/V data are + * not used in the I/V buffer. In this case, DSP framework should send + * back the remaining I and V data in next process. + * + * Outputs: + * N/A + * + * Returns: + * DSM_API_OK: successful + * Otherwise: error code + * + *******************************************************************************/ +enum DSM_API_MESSAGE dsm_api_fb_process(void *ipmodulehandler, + int ichannelmask, + short *icurrbuffer, + short *ivoltbuffer, + int *iopnrsamples); + +/******************************************************************************* + * dsm_api_set_params() + * + * Description: + * This function is used to set a serial of DSM parameters in one call. + * + * Inputs: + * ipmodulehandler: + * the handler of DSM module which is allocated by framework caller. + * icommandnumber: the number of commands. The total memory size of this + * input argument + * = (cmdNum * 2) * sizeof(int) bytes. + * ipparamsbuffer: the buffer of input parameters which are stored in the format below. + * The parameters should be set separately for each channel. + * ipValue memory map: + * ---+-----------+------------------- + * | cmd_1 | 32-bits integer command + * +-----------+ + * | param_1 | 32-bits data + * ---+-----------+------------------- + * | ... | + * | ... | + * | ... | + * ---+-----------+------------------- + * | cmd_N | 32-bits integer command + * +-----------+ + * | param_N | N-th 32-bit data + * ---+-----------+------------------- + * Total: N parameters + * + * Outputs: + * N/A. + * + * Returns: + * DSM_API_OK: successful + * Otherwise: error code + * + *******************************************************************************/ +enum DSM_API_MESSAGE dsm_api_set_params(void *ipmodulehandler, + int icommandnumber, void *ipparamsbuffer); + +/******************************************************************************* + * dsm_api_get_paramss() + * + * Description: + * This function is used to get a serial of DSM parameters in one call. + * + * Inputs: + * ipmodulehandler: + * the handler of DSM module which is allocated by framework caller. + * icommandnumber: the number of parameters. The total memory size of this + * input argument + * = cmdNum * (1 + channel_number) ) * sizeof(int) bytes + * + * Outputs: + * opparams: the buffer of the output parameters which are stored in the format below. + * opParams memory map: + * -----+-------------+----------------------------- + * | cmd_1 | 32-bits integer command Id + * +-------------+ + * | param_1_1 | 32-bits data of channel 1\ + * +-------------+ \ + * + ...... + -> parameters of N channels + * +-------------+ / + * | param_1_C | 32-bits data of channel N/ + * -----+-------------+----------------------------- + * + ...... + + * + ...... + + * + ...... + + * -----+-------------+----------------------------- + * + cmd_M + 32-bits integer command Id + * +-------------+ + * | param_M_1 | 32-bits data of channel 1\ + * +-------------+ \ + * + ...... + -> parameters of N channels + * +-------------+ / + * | param_M_C | 32-bits data of channel N/ + * -----+-------------+------------------------------ + * Total: M parameters of N channels + * + * Exception: the parameter sizes of the commands + * DSM_API_GET_FIRMWARE_BUILD_TIME = 88, //C string + * DSM_API_GET_FIRMWARE_BUILD_DATE = 89, //C string + * DSM_API_GET_FIRMWARE_VERSION = 90, //C string + * DSM_API_GET_CHIPSET_MODEL = 91, //C string + * are DSM_MAX_STRING_PARAM_SIZE (=32) bytes rather than 4 bytes of + * 32-bits data because these parameters are in the format C string. + * + * Returns: + * DSM_API_OK: successful + * Otherwise: error code + * + *******************************************************************************/ +enum DSM_API_MESSAGE dsm_api_get_params(void *ipmodulehandler, + int icommandnumber, void *opparams); + +#endif diff --git a/src/audio/smart_amp/lib/release/README.md b/src/audio/smart_amp/lib/release/README.md new file mode 100644 index 000000000000..a1711867fa7a --- /dev/null +++ b/src/audio/smart_amp/lib/release/README.md @@ -0,0 +1,7 @@ +# Smart Amp External Library Release + +To build FW binary including Smart Amp applying the third-party solution, the +pre-compiled library should be placed under this directory in local environment. + +The library itself should be statically linked with the SoF FW binary image, as +the configuration has been stated in src/audio/smart_amp/CMakeLists.txt diff --git a/src/audio/smart_amp/maxim_dsm_stub.c b/src/audio/smart_amp/maxim_dsm_stub.c new file mode 100644 index 000000000000..025db661c62d --- /dev/null +++ b/src/audio/smart_amp/maxim_dsm_stub.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Google LLC. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org> +// + +#include "dsm_api_public.h" + +enum DSM_API_MESSAGE dsm_api_get_mem(struct dsm_api_memory_size_ext_t *iopmmemparam, + int iparamsize) +{ + return DSM_API_OK; +} + +enum DSM_API_MESSAGE dsm_api_init(void *ipmodulehandler, + struct dsm_api_init_ext_t *iopparamstruct, + int iparamsize) +{ + return DSM_API_OK; +} + +enum DSM_API_MESSAGE dsm_api_ff_process(void *ipmodulehandler, + int channelmask, + short *ibufferorg, + int *ipnrsamples, + short *obufferorg, + int *opnrsamples) +{ + return DSM_API_OK; +} + +enum DSM_API_MESSAGE dsm_api_fb_process(void *ipmodulehandler, + int ichannelmask, + short *icurrbuffer, + short *ivoltbuffer, + int *iopnrsamples) +{ + return DSM_API_OK; +} + +enum DSM_API_MESSAGE dsm_api_set_params(void *ipmodulehandler, + int icommandnumber, void *ipparamsbuffer) +{ + return DSM_API_OK; +} + +enum DSM_API_MESSAGE dsm_api_get_params(void *ipmodulehandler, + int icommandnumber, void *opparams) +{ + return DSM_API_OK; +} diff --git a/src/audio/smart_amp/smart_amp.c b/src/audio/smart_amp/smart_amp.c new file mode 100644 index 000000000000..f82e3d2f7360 --- /dev/null +++ b/src/audio/smart_amp/smart_amp.c @@ -0,0 +1,819 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Maxim Integrated All rights reserved. +// +// Author: Ryan Lee <ryans.lee@maximintegrated.com> +// +// Copyright(c) 2023 Google LLC. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sys/types.h> + +#include <rtos/init.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/trace/trace.h> +#include <sof/ipc/msg.h> +#include <sof/ut.h> +#include <user/smart_amp.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/smart_amp/smart_amp.h> + +/* NOTE: this code builds itself with one of two distinct UUIDs + * depending on configuration! + */ +#if CONFIG_MAXIM_DSM +SOF_DEFINE_REG_UUID(maxim_dsm); +#define UUID_SYM maxim_dsm_uuid + +#else /* Passthrough */ +SOF_DEFINE_REG_UUID(passthru_smart_amp); +#define UUID_SYM passthru_smart_amp_uuid + +#endif + +LOG_MODULE_REGISTER(smart_amp, CONFIG_SOF_LOG_LEVEL); + +/* Amp configuration & model calibration data for tuning/debug */ +#define SOF_SMART_AMP_CONFIG 0 +#define SOF_SMART_AMP_MODEL 1 + +struct smart_amp_data { + struct processing_module *mod; + struct sof_smart_amp_config config; + struct comp_buffer *source_buf; /**< stream source buffer */ + struct comp_buffer *feedback_buf; /**< feedback source buffer */ + struct comp_buffer *sink_buf; /**< sink buffer */ + + smart_amp_src_func ff_get_frame; /**< function to get stream source */ + smart_amp_src_func fb_get_frame; /**< function to get feedback source */ + smart_amp_sink_func ff_set_frame; /**< function to set sink */ + struct smart_amp_mod_stream ff_mod; /**< feed-forward buffer for mod */ + struct smart_amp_mod_stream fb_mod; /**< feedback buffer for mod */ + struct smart_amp_mod_stream out_mod; /**< output buffer for mod */ + + struct smart_amp_buf mod_mems[MOD_MEMBLK_MAX]; /**< memory blocks for mod */ + + struct smart_amp_mod_data_base *mod_data; /**< inner model data */ +}; + +/* smart_amp_free_mod_memories will be called promptly once getting error on + * internal functions. That is, it may be called multiple times by the hierarchical + * model when an error occurs in the lower function and propagates level-wise to + * the function on top. Always set the pointer to NULL after freed to avoid the + * double-freeing error. + */ +static inline void smart_amp_free_mod_memories(struct smart_amp_data *sad) +{ + /* sof -> mod feed-forward data re-mapping and format conversion */ + mod_free(sad->mod, sad->ff_mod.buf.data); + sad->ff_mod.buf.data = NULL; + /* sof -> mod feedback data re-mapping and format conversion */ + mod_free(sad->mod, sad->fb_mod.buf.data); + sad->fb_mod.buf.data = NULL; + /* mod -> sof processed data format conversion */ + mod_free(sad->mod, sad->out_mod.buf.data); + sad->out_mod.buf.data = NULL; + + /* mem block for mod private data usage */ + mod_free(sad->mod, sad->mod_mems[MOD_MEMBLK_PRIVATE].data); + sad->mod_mems[MOD_MEMBLK_PRIVATE].data = NULL; + /* mem block for mod audio frame data usage */ + mod_free(sad->mod, sad->mod_mems[MOD_MEMBLK_FRAME].data); + sad->mod_mems[MOD_MEMBLK_FRAME].data = NULL; + /* mem block for mod parameter blob usage */ + mod_free(sad->mod, sad->mod_mems[MOD_MEMBLK_PARAM].data); + sad->mod_mems[MOD_MEMBLK_PARAM].data = NULL; + + /* inner model data struct */ + mod_free(sad->mod, sad->mod_data); + sad->mod_data = NULL; +} + +static inline int smart_amp_buf_alloc(struct processing_module *mod, + struct smart_amp_buf *buf, size_t size) +{ + buf->data = mod_alloc(mod, size); + if (!buf->data) + return -ENOMEM; + buf->size = size; + return 0; +} + +static ssize_t smart_amp_alloc_mod_memblk(struct smart_amp_data *sad, + enum smart_amp_mod_memblk blk) +{ + struct smart_amp_mod_data_base *smod = sad->mod_data; + int ret; + size_t size; + + /* query the required size from inner model. */ + ret = smod->mod_ops->query_memblk_size(smod, blk); + if (ret < 0) + goto error; + + /* no memory required */ + if (ret == 0) + return 0; + + /* allocate the memory block when returned size > 0. */ + size = ret; + ret = smart_amp_buf_alloc(sad->mod, &sad->mod_mems[blk], size); + if (ret < 0) + goto error; + + /* provide the memory block information to inner model. */ + ret = smod->mod_ops->set_memblk(smod, blk, &sad->mod_mems[blk]); + if (ret < 0) + goto error; + + return size; + +error: + smart_amp_free_mod_memories(sad); + return ret; +} + +static int smart_amp_alloc_data_buffers(struct comp_dev *dev, + struct smart_amp_data *sad) +{ + size_t total_size; + int ret; + size_t size; + + /* sof -> mod feed-forward data re-mapping and format conversion */ + size = SMART_AMP_FF_BUF_DB_SZ * sizeof(int32_t); + ret = smart_amp_buf_alloc(sad->mod, &sad->ff_mod.buf, size); + if (ret < 0) + goto error; + total_size = size; + + /* sof -> mod feedback data re-mapping and format conversion */ + size = SMART_AMP_FB_BUF_DB_SZ * sizeof(int32_t); + ret = smart_amp_buf_alloc(sad->mod, &sad->fb_mod.buf, size); + if (ret < 0) + goto error; + total_size += size; + + /* mod -> sof processed data format conversion */ + size = SMART_AMP_FF_BUF_DB_SZ * sizeof(int32_t); + ret = smart_amp_buf_alloc(sad->mod, &sad->out_mod.buf, size); + if (ret < 0) + goto error; + total_size += size; + + comp_dbg(dev, "used data buffer %zu bytes", total_size); + return 0; + +error: + smart_amp_free_mod_memories(sad); + return ret; +} + +static int smart_amp_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_config *mcfg = &mod->priv.cfg; + struct smart_amp_data *sad; + struct sof_smart_amp_config *cfg; + size_t bs; + int ret; + + /* Allocate smart_amp_data using module API */ + sad = mod_zalloc(mod, sizeof(*sad)); + if (!sad) + return -ENOMEM; + + mod->priv.private = sad; + sad->mod = mod; + + /* Copy config blob if present */ + if (mcfg->avail && mcfg->init_data && mcfg->size >= sizeof(struct sof_smart_amp_config)) { + cfg = (struct sof_smart_amp_config *)mcfg->init_data; + bs = mcfg->size; + memcpy_s(&sad->config, sizeof(struct sof_smart_amp_config), cfg, bs); + } + + /* allocate inner model data struct */ + sad->mod_data = mod_data_create(dev); + if (!sad->mod_data) { + comp_err(dev, "failed to allocate inner model data"); + ret = -ENOMEM; + goto error; + } + + /* allocate stream buffers for mod */ + ret = smart_amp_alloc_data_buffers(dev, sad); + if (ret) { + comp_err(dev, "failed to allocate data buffers, ret:%d", ret); + goto error; + } + + /* (before init) allocate mem block for mod private data usage */ + ret = smart_amp_alloc_mod_memblk(sad, MOD_MEMBLK_PRIVATE); + if (ret < 0) { + comp_err(dev, "failed to allocate mod private, ret:%d", ret); + goto error; + } + comp_dbg(dev, "used mod private buffer %d bytes", ret); + + /* init model */ + ret = sad->mod_data->mod_ops->init(sad->mod_data); + if (ret) { + comp_err(dev, "failed to init inner model, ret:%d", ret); + goto error; + } + + /* (after init) allocate mem block for mod audio frame data usage */ + ret = smart_amp_alloc_mod_memblk(sad, MOD_MEMBLK_FRAME); + if (ret < 0) { + comp_err(dev, "failed to allocate mod buffer, ret:%d", ret); + goto error; + } + comp_dbg(dev, "used mod data buffer %d bytes", ret); + + /* (after init) allocate mem block for mod parameter blob usage */ + ret = smart_amp_alloc_mod_memblk(sad, MOD_MEMBLK_PARAM); + if (ret < 0) { + comp_err(dev, "failed to allocate mod config, ret:%d", ret); + goto error; + } + comp_dbg(dev, "used mod config buffer %d bytes", ret); + + return 0; +error: + smart_amp_free_mod_memories(sad); + mod_free(mod, sad); + return ret; +} + +static int smart_amp_set_config(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct sof_smart_amp_config *cfg; + struct comp_dev *dev = mod->dev; + size_t bs; + + /* Copy new config, find size from header */ + cfg = (struct sof_smart_amp_config *) + ASSUME_ALIGNED(&cdata->data->data, sizeof(uint32_t)); + bs = cfg->size; + + comp_dbg(dev, "actual blob size = %zu, expected blob size = %zu", + bs, sizeof(struct sof_smart_amp_config)); + + if (bs != sizeof(struct sof_smart_amp_config)) { + comp_err(dev, "invalid blob size, actual blob size = %zu, expected blob size = %zu", + bs, sizeof(struct sof_smart_amp_config)); + return -EINVAL; + } + + memcpy_s(&sad->config, sizeof(struct sof_smart_amp_config), cfg, + sizeof(struct sof_smart_amp_config)); + + return 0; +} + +static int smart_amp_get_config(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata, int size) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + size_t bs; + int ret = 0; + + /* Copy back to user space */ + bs = sad->config.size; + + comp_dbg(dev, "actual blob size = %zu, expected blob size = %zu", + bs, sizeof(struct sof_smart_amp_config)); + + if (bs == 0 || bs > size) + return -EINVAL; + + ret = memcpy_s(cdata->data->data, size, &sad->config, bs); + assert(!ret); + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = bs; + + return ret; +} + +static int smart_amp_ctrl_get_bin_data(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata, + int size) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct smart_amp_mod_data_base *smod; + struct comp_dev *dev = mod->dev; + int ret = 0; + + assert(sad); + smod = sad->mod_data; + + switch (cdata->data->type) { + case SOF_SMART_AMP_CONFIG: + ret = smart_amp_get_config(mod, cdata, size); + break; + case SOF_SMART_AMP_MODEL: + ret = smod->mod_ops->get_config(smod, cdata, size); + if (ret < 0) { + comp_err(dev, "failed to read inner model!"); + return ret; + } + break; + default: + comp_err(dev, "unknown binary data type"); + break; + } + + return ret; +} + +static int smart_amp_get_configuration(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "config_id %u size: %zu", config_id, fragment_size); + +#if CONFIG_IPC_MAJOR_3 + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return smart_amp_ctrl_get_bin_data(mod, cdata, fragment_size); + default: + comp_err(dev, "invalid cdata->cmd"); + } +#elif CONFIG_IPC_MAJOR_4 + return smart_amp_ctrl_get_bin_data(mod, cdata, fragment_size); +#endif + return -EINVAL; +} + +static int smart_amp_ctrl_set_bin_data(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct smart_amp_mod_data_base *smod; + struct comp_dev *dev = mod->dev; + int ret = 0; + + assert(sad); + smod = sad->mod_data; + + if (dev->state < COMP_STATE_READY) { + comp_err(dev, "driver in init!"); + return -EBUSY; + } + + switch (cdata->data->type) { + case SOF_SMART_AMP_CONFIG: + ret = smart_amp_set_config(mod, cdata); + break; + case SOF_SMART_AMP_MODEL: + ret = smod->mod_ops->set_config(smod, cdata); + if (ret < 0) { + comp_err(dev, "failed to write inner model!"); + return ret; + } + break; + default: + comp_err(dev, "unknown binary data type"); + break; + } + + return ret; +} + +static int smart_amp_ctrl_set_data(struct processing_module *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_dev *dev = mod->dev; + int ret = 0; + + /* Check version from ABI header */ + if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { + comp_err(dev, "invalid version"); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + comp_dbg(dev, "SOF_CTRL_CMD_BINARY"); + ret = smart_amp_ctrl_set_bin_data(mod, cdata); + break; + default: + comp_err(dev, "invalid cdata->cmd"); + ret = -EINVAL; + break; + } + + return ret; +} + +static int smart_amp_set_configuration(struct processing_module *mod, + uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, + uint8_t *response, size_t response_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct comp_dev *dev = mod->dev; + + comp_info(dev, "config_id %u size %zu", config_id, response_size); + +#if CONFIG_IPC_MAJOR_3 + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "SOF_CTRL_CMD_BINARY"); + return smart_amp_ctrl_set_data(mod, cdata); + default: + comp_err(dev, "unknown cmd %d", cdata->cmd); + } +#elif CONFIG_IPC_MAJOR_4 + return smart_amp_ctrl_set_data(mod, cdata); +#endif + 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, "entry"); + if (!sad) + return 0; + + smart_amp_free_mod_memories(sad); + + mod_free(mod, sad); + mod->priv.private = NULL; + + return 0; +} + +#if CONFIG_IPC_MAJOR_4 +static void smart_amp_ipc4_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); + + sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); +} +#endif /* CONFIG_IPC_MAJOR_4 */ + +static int smart_amp_trigger(struct processing_module *mod, int cmd) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret = 0; + + comp_dbg(dev, "command = %u", cmd); + + ret = comp_set_state(dev, cmd); + + switch (cmd) { + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + if (sad->feedback_buf) { + buffer_zero(sad->feedback_buf); + } + break; + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + break; + default: + break; + } + + return ret; +} + +static int smart_amp_ff_process(struct processing_module *mod, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames, const int8_t *chan_map) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct smart_amp_mod_data_base *smod = sad->mod_data; + struct comp_dev *dev = mod->dev; + int ret; + + sad->ff_mod.consumed = 0; + sad->out_mod.produced = 0; + + if (frames == 0) { + comp_warn(dev, "feed forward frame size zero warning."); + return 0; + } + + if (frames > SMART_AMP_FF_BUF_DB_SZ) { + comp_err(dev, "feed forward frame size overflow: %u", frames); + sad->ff_mod.consumed = frames; + return -EINVAL; + } + + sad->ff_get_frame(&sad->ff_mod, frames, source, chan_map); + + ret = smod->mod_ops->ff_proc(smod, frames, &sad->ff_mod, &sad->out_mod); + if (ret) { + comp_err(dev, "feed forward inner model process error"); + return ret; + } + + sad->ff_set_frame(&sad->out_mod, sad->out_mod.produced, sink); + + return 0; +} + +static int smart_amp_fb_process(struct processing_module *mod, + const struct audio_stream *source, + uint32_t frames, const int8_t *chan_map) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct smart_amp_mod_data_base *smod = sad->mod_data; + struct comp_dev *dev = mod->dev; + int ret; + + sad->fb_mod.consumed = 0; + + if (frames == 0) { + comp_warn(dev, "feedback frame size zero warning."); + return 0; + } + + if (frames > SMART_AMP_FB_BUF_DB_SZ) { + comp_err(dev, "feedback frame size overflow: %u", frames); + sad->fb_mod.consumed = frames; + return -EINVAL; + } + + sad->fb_get_frame(&sad->fb_mod, frames, source, chan_map); + + ret = smod->mod_ops->fb_proc(smod, frames, &sad->fb_mod); + if (ret) { + comp_err(dev, "feedback inner model process error"); + return ret; + } + + return 0; +} + +static int smart_amp_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *source_buf = sad->source_buf; + struct comp_buffer *sink_buf = comp_buffer_get_from_sink(sinks[0]); + uint32_t avail_passthrough_frames; + uint32_t avail_feedback_frames; + uint32_t avail_frames; + uint32_t source_bytes; + uint32_t sink_bytes; + uint32_t feedback_bytes; + + comp_dbg(dev, "%d sources %d sinks", num_of_sources, num_of_sinks); + + /* available bytes and samples calculation */ + avail_passthrough_frames = audio_stream_avail_frames(&source_buf->stream, + &sink_buf->stream); + + avail_frames = avail_passthrough_frames; + + if (sad->feedback_buf) { + struct comp_buffer *feedback_buf = sad->feedback_buf; + + if (comp_get_state(feedback_buf->source) == dev->state) { + /* feedback */ + avail_feedback_frames = + audio_stream_get_avail_frames(&feedback_buf->stream); + + avail_feedback_frames = MIN(avail_passthrough_frames, + avail_feedback_frames); + + feedback_bytes = avail_feedback_frames * + audio_stream_frame_bytes(&feedback_buf->stream); + + comp_dbg(dev, "processing %u feedback frames (avail_passthrough_frames: %u)", + avail_feedback_frames, avail_passthrough_frames); + + /* perform buffer writeback after source_buf process */ + buffer_stream_invalidate(feedback_buf, feedback_bytes); + smart_amp_fb_process(mod, &feedback_buf->stream, + avail_feedback_frames, + sad->config.feedback_ch_map); + + comp_dbg(dev, "consumed %u feedback frames", + sad->fb_mod.consumed); + if (sad->fb_mod.consumed < avail_feedback_frames) { + feedback_bytes = sad->fb_mod.consumed * + audio_stream_frame_bytes(&feedback_buf->stream); + } + + comp_update_buffer_consume(feedback_buf, feedback_bytes); + } + } + + /* process data */ + source_bytes = avail_frames * audio_stream_frame_bytes(&source_buf->stream); + + buffer_stream_invalidate(source_buf, source_bytes); + smart_amp_ff_process(mod, &source_buf->stream, &sink_buf->stream, + avail_frames, sad->config.source_ch_map); + + comp_dbg(dev, "processing %u feed forward frames (consumed: %u, produced: %u)", + avail_frames, sad->ff_mod.consumed, sad->out_mod.produced); + if (sad->ff_mod.consumed < avail_frames) + source_bytes = sad->ff_mod.consumed * audio_stream_frame_bytes(&source_buf->stream); + + sink_bytes = sad->out_mod.produced * audio_stream_frame_bytes(&sink_buf->stream); + buffer_stream_writeback(sink_buf, sink_bytes); + + /* source/sink buffer pointers update */ + comp_update_buffer_consume(source_buf, source_bytes); + comp_update_buffer_produce(sink_buf, sink_bytes); + + return 0; +} + +static int smart_amp_reset(struct processing_module *mod) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct smart_amp_mod_data_base *smod = sad->mod_data; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + sad->ff_get_frame = NULL; + sad->fb_get_frame = NULL; + sad->ff_set_frame = NULL; + + /* reset inner model */ + return smod->mod_ops->reset(smod); +} + +/* supported formats: {SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE} + * which are enumerated as 0, 1, and 2. Simply check if supported while fmt <= 2. + */ +static inline bool is_supported_fmt(uint16_t fmt) +{ + return fmt <= SOF_IPC_FRAME_S32_LE; +} + +static int smart_amp_resolve_mod_fmt(struct processing_module *mod, uint32_t least_req_depth) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct smart_amp_mod_data_base *smod = sad->mod_data; + struct comp_dev *dev = mod->dev; + const uint16_t *mod_fmts; + int num_mod_fmts; + int ret; + int i; + + /* get supported formats from mod */ + ret = smod->mod_ops->get_supported_fmts(smod, &mod_fmts, &num_mod_fmts); + if (ret) { + comp_err(dev, "failed to get supported formats"); + return ret; + } + + for (i = 0; i < num_mod_fmts; i++) { + if (get_sample_bitdepth(mod_fmts[i]) >= least_req_depth && + is_supported_fmt(mod_fmts[i])) { + /* set frame format to inner model */ + comp_dbg(dev, "set mod format to %u", + mod_fmts[i]); + ret = smod->mod_ops->set_fmt(smod, mod_fmts[i]); + if (ret) { + comp_err(dev, + "failed setting format %u", + mod_fmts[i]); + return ret; + } + /* return the resolved format for later settings. */ + return mod_fmts[i]; + } + } + + comp_err(dev, "failed to resolve the frame format for mod"); + return -EINVAL; +} + +static int smart_amp_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint16_t ff_src_fmt, fb_src_fmt, resolved_mod_fmt; + uint32_t least_req_depth; + int ret, i; + + comp_dbg(dev, "%d sources %d sinks", num_of_sources, num_of_sinks); +#if CONFIG_IPC_MAJOR_4 + smart_amp_ipc4_params(mod); +#endif + + /* In module API, state is managed by the framework, so no comp_set_state needed */ + for (i = 0; i < num_of_sources; i++) { + /* NOTE: This should not work in module based environment: + * sources[i]->bound_module->dev->ipc_config.type == SOF_COMP_DEMUX + * So let's check which one of the sources is from a capture stream. + * The code is not tested and may not work. + */ + if (sources[i]->bound_module->dev->direction == SOF_IPC_STREAM_CAPTURE) + sad->feedback_buf = comp_buffer_get_from_source(sources[i]); + else + sad->source_buf = comp_buffer_get_from_source(sources[i]); + } + + /* sink buffer */ + sad->sink_buf = comp_buffer_get_from_sink(sinks[0]); + if (!sad->sink_buf) { + comp_err(dev, "no sink buffer"); + return -ENOTCONN; + } + + /* get frame format and channels param of stream and feedback source */ + ff_src_fmt = audio_stream_get_frm_fmt(&sad->source_buf->stream); + sad->ff_mod.channels = MIN(SMART_AMP_FF_MAX_CH_NUM, + audio_stream_get_channels(&sad->source_buf->stream)); + sad->out_mod.channels = sad->ff_mod.channels; + + /* the least bitdepth required for inner model, which should not be lower than the bitdepth + * for input samples of feed-forward, and feedback if exists. + */ + least_req_depth = get_sample_bitdepth(ff_src_fmt); + if (sad->feedback_buf) { + /* forward set channels and rate param to feedback source */ + audio_stream_set_channels(&sad->feedback_buf->stream, + sad->config.feedback_channels); + audio_stream_set_rate(&sad->feedback_buf->stream, + audio_stream_get_rate(&sad->source_buf->stream)); + fb_src_fmt = audio_stream_get_frm_fmt(&sad->feedback_buf->stream); + sad->fb_mod.channels = MIN(SMART_AMP_FB_MAX_CH_NUM, + audio_stream_get_channels(&sad->feedback_buf->stream)); + least_req_depth = MAX(least_req_depth, get_sample_bitdepth(fb_src_fmt)); + } + + /* resolve the frame format for inner model. The return value will be the applied format + * or the negative error code. + */ + ret = smart_amp_resolve_mod_fmt(mod, least_req_depth); + if (ret < 0) + return ret; + + resolved_mod_fmt = ret; + + /* set format to mod buffers and get the corresponding src/sink function of channel + * remapping and format conversion. + */ + sad->ff_mod.frame_fmt = resolved_mod_fmt; + sad->out_mod.frame_fmt = resolved_mod_fmt; + sad->ff_get_frame = smart_amp_get_src_func(ff_src_fmt, sad->ff_mod.frame_fmt); + sad->ff_set_frame = smart_amp_get_sink_func(ff_src_fmt, sad->out_mod.frame_fmt); + comp_dbg(dev, "ff mod buffer channels:%u fmt_conv:%u -> %u", + sad->ff_mod.channels, ff_src_fmt, sad->ff_mod.frame_fmt); + comp_dbg(dev, "output mod buffer channels:%u fmt_conv:%u -> %u", + sad->out_mod.channels, sad->out_mod.frame_fmt, ff_src_fmt); + + if (sad->feedback_buf) { + sad->fb_mod.frame_fmt = resolved_mod_fmt; + sad->fb_get_frame = smart_amp_get_src_func(fb_src_fmt, sad->fb_mod.frame_fmt); + comp_dbg(dev, "fb mod buffer channels:%u fmt_conv:%u -> %u", + sad->fb_mod.channels, fb_src_fmt, sad->fb_mod.frame_fmt); + } + + return 0; +} + +static struct module_interface smart_amp_interface = { + .init = smart_amp_init, + .prepare = smart_amp_prepare, + .process = smart_amp_process, + .set_configuration = smart_amp_set_configuration, + .get_configuration = smart_amp_get_configuration, + .reset = smart_amp_reset, + .free = smart_amp_free, + .trigger = smart_amp_trigger, +}; + +DECLARE_TR_CTX(smart_amp_comp_tr, SOF_UUID(UUID_SYM), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(smart_amp_interface, UUID_SYM, smart_amp_comp_tr); +SOF_MODULE_INIT(smart_amp, sys_comp_module_smart_amp_interface_init); diff --git a/src/audio/smart_amp/smart_amp_generic.c b/src/audio/smart_amp/smart_amp_generic.c new file mode 100644 index 000000000000..91223eb398bd --- /dev/null +++ b/src/audio/smart_amp/smart_amp_generic.c @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Maxim Integrated All rights reserved. +// +// Author: Ryan Lee <ryans.lee@maximintegrated.com> +// +// Copyright(c) 2023 Google LLC. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <stdint.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/smart_amp/smart_amp.h> + +static void remap_s32_to_s32(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map) +{ + int num_samples_remaining; + int nmax, n, ch, i; + int n_mod = 0; + int src_ch = audio_stream_get_channels(src); + int32_t *src_ptr_base = audio_stream_get_rptr(src); + int32_t *mod_ptr_base = (int32_t *)src_mod->buf.data; + int32_t *src_ptr; + int32_t *mod_ptr; + + /* clean up dst buffer to make sure all 0s on the unmapped channel */ + bzero(mod_ptr_base, src_mod->buf.size); + + num_samples_remaining = frames * src_ch; + while (num_samples_remaining) { + nmax = audio_stream_samples_without_wrap_s32(src, src_ptr_base); + n = MIN(num_samples_remaining, nmax); + + for (ch = 0; ch < src_mod->channels; ch++) { + if (chan_map[ch] == -1) + continue; + + mod_ptr = mod_ptr_base + ch; + src_ptr = src_ptr_base + chan_map[ch]; + n_mod = 0; + for (i = 0; i < n; i += src_ch) { + *mod_ptr = *src_ptr; + mod_ptr += src_mod->channels; + src_ptr += src_ch; + n_mod += src_mod->channels; + } + } + /* update base pointers by forwarding (n / src_ch) frames */ + mod_ptr_base += n_mod; + src_ptr_base += n; + + num_samples_remaining -= n; + src_ptr_base = audio_stream_wrap(src, src_ptr_base); + } +} + +static void remap_s24_to_s24(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map) +{ + remap_s32_to_s32(src_mod, frames, src, chan_map); +} + +static void remap_s24_to_s32(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map) +{ + int i; + int n_mod = frames * src_mod->channels; + int32_t *mod_ptr = (int32_t *)src_mod->buf.data; + + remap_s32_to_s32(src_mod, frames, src, chan_map); + + /* one loop for in-place lshift (s24-to-s32) after remapping */ + for (i = 0; i < n_mod; i++) { + *mod_ptr = *mod_ptr << 8; + mod_ptr++; + } +} + +static void remap_s16_to_s16(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map) +{ + int num_samples_remaining; + int nmax, n, ch, i; + int n_mod = 0; + int src_ch = audio_stream_get_channels(src); + int16_t *src_ptr_base = audio_stream_get_rptr(src); + int16_t *mod_ptr_base = (int16_t *)src_mod->buf.data; + int16_t *src_ptr; + int16_t *mod_ptr; + + /* clean up mod buffer (dst) to keep all-0 data on the unmapped channel */ + bzero(mod_ptr_base, src_mod->buf.size); + + num_samples_remaining = frames * src_ch; + while (num_samples_remaining) { + nmax = audio_stream_samples_without_wrap_s16(src, src_ptr_base); + n = MIN(num_samples_remaining, nmax); + + for (ch = 0; ch < src_mod->channels; ch++) { + if (chan_map[ch] == -1) + continue; + + mod_ptr = mod_ptr_base + ch; + src_ptr = src_ptr_base + chan_map[ch]; + n_mod = 0; + for (i = 0; i < n; i += src_ch) { + *mod_ptr = *src_ptr; + mod_ptr += src_mod->channels; + src_ptr += src_ch; + n_mod += src_mod->channels; + } + } + /* update base pointers by forwarding (n / src_ch) frames */ + mod_ptr_base += n_mod; + src_ptr_base += n; + + num_samples_remaining -= n; + src_ptr_base = audio_stream_wrap(src, src_ptr_base); + } +} + +static void remap_s16_to_b32(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map, int lshift) +{ + int num_samples_remaining; + int nmax, n, ch, i; + int n_mod = 0; + int src_ch = audio_stream_get_channels(src); + int16_t *src_ptr_base = audio_stream_get_rptr(src); + int32_t *mod_ptr_base = (int32_t *)src_mod->buf.data; + int16_t *src_ptr; + int32_t *mod_ptr; + + /* clean up dst buffer to make sure all 0s on the unmapped channel */ + bzero(mod_ptr_base, src_mod->buf.size); + + num_samples_remaining = frames * src_ch; + while (num_samples_remaining) { + nmax = audio_stream_samples_without_wrap_s16(src, src_ptr_base); + n = MIN(num_samples_remaining, nmax); + + for (ch = 0; ch < src_mod->channels; ch++) { + if (chan_map[ch] == -1) + continue; + + mod_ptr = mod_ptr_base + ch; + src_ptr = src_ptr_base + chan_map[ch]; + n_mod = 0; + for (i = 0; i < n; i += src_ch) { + *mod_ptr = (int32_t)*src_ptr << lshift; + mod_ptr += src_mod->channels; + src_ptr += src_ch; + n_mod += src_mod->channels; + } + } + /* update base pointers by forwarding (n / src_ch) frames */ + mod_ptr_base += n_mod; + src_ptr_base += n; + + num_samples_remaining -= n; + src_ptr_base = audio_stream_wrap(src, src_ptr_base); + } +} + +static void remap_s16_to_s24(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map) +{ + remap_s16_to_b32(src_mod, frames, src, chan_map, 8 /* lshift */); +} + +static void remap_s16_to_s32(struct smart_amp_mod_stream *src_mod, uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map) +{ + remap_s16_to_b32(src_mod, frames, src, chan_map, 16 /* lshift */); +} + +static void feed_s32_to_s32(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink) +{ + int num_samples_remaining; + int nmax, n, ch, i; + int sink_ch = audio_stream_get_channels(sink); + int feed_channels = MIN(sink_ch, sink_mod->channels); + int32_t *sink_ptr = audio_stream_get_wptr(sink); + int32_t *mod_ptr = (int32_t *)sink_mod->buf.data; + + num_samples_remaining = frames * sink_ch; + while (num_samples_remaining) { + nmax = audio_stream_samples_without_wrap_s32(sink, sink_ptr); + n = MIN(num_samples_remaining, nmax); + + for (i = 0; i < n; i += sink_ch) { + for (ch = 0; ch < feed_channels; ch++) + *(sink_ptr + ch) = *(mod_ptr + ch); + + sink_ptr += sink_ch; + mod_ptr += sink_mod->channels; + } + + num_samples_remaining -= n; + sink_ptr = audio_stream_wrap(sink, sink_ptr); + } +} + +static void feed_s24_to_s24(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink) +{ + feed_s32_to_s32(sink_mod, frames, sink); +} + +static void feed_s32_to_s24(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink) +{ + int i; + int n_mod = frames * sink_mod->channels; + int32_t *mod_ptr = (int32_t *)sink_mod->buf.data; + + /* one loop for in-place rshift (s32-to-s24) before feeding */ + for (i = 0; i < n_mod; i++) { + *mod_ptr = sat_int24(Q_SHIFT_RND(*mod_ptr, 31, 23)); + mod_ptr++; + } + + feed_s32_to_s32(sink_mod, frames, sink); +} + +static void feed_s16_to_s16(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink) +{ + int num_samples_remaining; + int nmax, n, ch, i; + int sink_ch = audio_stream_get_channels(sink); + int feed_channels = MIN(sink_ch, sink_mod->channels); + int16_t *sink_ptr = audio_stream_get_wptr(sink); + int16_t *mod_ptr = (int16_t *)sink_mod->buf.data; + + num_samples_remaining = frames * sink_ch; + while (num_samples_remaining) { + nmax = audio_stream_samples_without_wrap_s16(sink, sink_ptr); + n = MIN(num_samples_remaining, nmax); + + for (i = 0; i < n; i += sink_ch) { + for (ch = 0; ch < feed_channels; ch++) + *(sink_ptr + ch) = *(mod_ptr + ch); + + sink_ptr += sink_ch; + mod_ptr += sink_mod->channels; + } + + num_samples_remaining -= n; + sink_ptr = audio_stream_wrap(sink, sink_ptr); + } +} + +static void feed_b32_to_s16(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink, int mod_fbits) +{ + int num_samples_remaining; + int nmax, n, ch, i; + int sink_ch = audio_stream_get_channels(sink); + int feed_channels = MIN(sink_ch, sink_mod->channels); + int16_t *sink_ptr = audio_stream_get_wptr(sink); + int32_t *mod_ptr = (int32_t *)sink_mod->buf.data; + + num_samples_remaining = frames * sink_ch; + while (num_samples_remaining) { + nmax = audio_stream_samples_without_wrap_s16(sink, sink_ptr); + n = MIN(num_samples_remaining, nmax); + + for (i = 0; i < n; i += sink_ch) { + for (ch = 0; ch < feed_channels; ch++) { + *(sink_ptr + ch) = sat_int16(Q_SHIFT_RND(*(mod_ptr + ch), + mod_fbits, 15)); + } + sink_ptr += sink_ch; + mod_ptr += sink_mod->channels; + } + + num_samples_remaining -= n; + sink_ptr = audio_stream_wrap(sink, sink_ptr); + } +} + +static void feed_s24_to_s16(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink) +{ + feed_b32_to_s16(sink_mod, frames, sink, 23 /* mod_fbits */); +} + +static void feed_s32_to_s16(const struct smart_amp_mod_stream *sink_mod, uint32_t frames, + const struct audio_stream __sparse_cache *sink) +{ + feed_b32_to_s16(sink_mod, frames, sink, 31 /* mod_fbits */); +} + +const struct smart_amp_func_map src_sink_func_map[] = { + /* { comp_fmt, mod_fmt, src_func, sink_func } + * cases are valid only if comp_fmt <= mod_fmt + */ +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, &remap_s16_to_s16, &feed_s16_to_s16 }, + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, &remap_s16_to_s24, &feed_s24_to_s16 }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, &remap_s16_to_s32, &feed_s32_to_s16 }, +#endif /* CONFIG_FORMAT_S32LE */ +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, &remap_s24_to_s24, &feed_s24_to_s24 }, + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, &remap_s24_to_s32, &feed_s32_to_s24 }, +#endif /* CONFIG_FORMAT_S32LE */ +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, &remap_s32_to_s32, &feed_s32_to_s32 }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +smart_amp_src_func smart_amp_get_src_func(uint16_t comp_fmt, uint16_t mod_fmt) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(src_sink_func_map); i++) { + if (comp_fmt == src_sink_func_map[i].comp_fmt && + mod_fmt == src_sink_func_map[i].mod_fmt) + return src_sink_func_map[i].src_func; + } + + return NULL; +} + +smart_amp_sink_func smart_amp_get_sink_func(uint16_t comp_fmt, uint16_t mod_fmt) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(src_sink_func_map); i++) { + if (comp_fmt == src_sink_func_map[i].comp_fmt && + mod_fmt == src_sink_func_map[i].mod_fmt) + return src_sink_func_map[i].sink_func; + } + + return NULL; +} diff --git a/src/audio/smart_amp/smart_amp_maxim_dsm.c b/src/audio/smart_amp/smart_amp_maxim_dsm.c new file mode 100644 index 000000000000..b9289861aa8d --- /dev/null +++ b/src/audio/smart_amp/smart_amp_maxim_dsm.c @@ -0,0 +1,850 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Maxim Integrated All rights reserved. +// +// Author: Ryan Lee <ryans.lee@maximintegrated.com> + +#include <sof/audio/component.h> +#include <sof/trace/trace.h> +#include <sof/ipc/msg.h> +#include <sof/ut.h> + +#include <sof/audio/channel_map.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <ipc/channel_map.h> +#include <stdint.h> +#include <stdlib.h> +#include <sof/audio/smart_amp/smart_amp.h> +#include "dsm_api_public.h" + +LOG_MODULE_DECLARE(smart_amp, CONFIG_SOF_LOG_LEVEL); + +/* Maxim DSM(Dynamic Speaker Management) process buffer size */ +#define DSM_FRM_SZ 48 +#define DSM_FF_BUF_SZ (DSM_FRM_SZ * SMART_AMP_FF_MAX_CH_NUM) +#define DSM_FB_BUF_SZ (DSM_FRM_SZ * SMART_AMP_FB_MAX_CH_NUM) + +#define DSM_FF_BUF_DB_SZ (DSM_FF_BUF_SZ * SMART_AMP_FF_MAX_CH_NUM) +#define DSM_FB_BUF_DB_SZ (DSM_FB_BUF_SZ * SMART_AMP_FB_MAX_CH_NUM) + +/* DSM parameter table structure + * +--------------+-----------------+---------------------------------+ + * | ID (4 bytes) | VALUE (4 bytes) | 1st channel : | + * | | | 8 bytes per single parameter | + * +--------------+-----------------+---------------------------------+ + * | ... | ... | Repeat N times for N parameters | + * +--------------+-----------------+---------------------------------+ + * | ID (4 bytes) | VALUE (4 bytes) | 2nd channel : | + * | | | 8 bytes per single parameter | + * +--------------+-----------------+---------------------------------+ + * | ... | ... | Repeat N times for N parameters | + * +--------------+-----------------+---------------------------------+ + */ +enum dsm_param { + DSM_PARAM_ID = 0, + DSM_PARAM_VALUE, + DSM_PARAM_MAX +}; + +#define DSM_SINGLE_PARAM_SZ (DSM_PARAM_MAX * SMART_AMP_FF_MAX_CH_NUM) + +static const int supported_fmt_count = 3; +static const uint16_t supported_fmts[] = { + SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE +}; + +union maxim_dsm_buf { + int16_t *buf16; + int32_t *buf32; +}; + +struct maxim_dsm_ff_buf_struct_t { + int32_t *buf; + int avail; +}; + +struct maxim_dsm_fb_buf_struct_t { + int32_t *buf; + int avail; + int rdy; +}; + +struct smart_amp_buf_struct_t { + /* buffer : feed forward process input */ + int32_t *input; + /* buffer : feed forward process output */ + int32_t *output; + /* buffer : feedback voltage */ + int32_t *voltage; + /* buffer : feedback current */ + int32_t *current; + /* buffer : feed forward variable length -> fixed length */ + struct maxim_dsm_ff_buf_struct_t ff; + /* buffer : feed forward variable length <- fixed length */ + struct maxim_dsm_ff_buf_struct_t ff_out; + /* buffer : feedback variable length -> fixed length */ + struct maxim_dsm_fb_buf_struct_t fb; +}; + +struct param_buf_struct_t { + int id; + int value; +}; + +struct smart_amp_caldata { + uint32_t data_size; /* size of component's model data */ + void *data; /* model data pointer */ + uint32_t data_pos; /* data position for read/write */ +}; + +struct smart_amp_param_struct_t { + struct param_buf_struct_t param; /* variable to keep last parameter ID/value */ + struct smart_amp_caldata caldata; /* model data buffer */ + int pos; /* data position for read/write */ + int max_param; /* keep max number of DSM parameters */ +}; + +/* self-declared inner model data struct */ +struct smart_amp_mod_struct_t { + struct smart_amp_mod_data_base base; + struct smart_amp_buf_struct_t buf; + void *dsmhandle; + /* DSM variables for the initialization */ + int delayedsamples[SMART_AMP_FF_MAX_CH_NUM << 2]; + int circularbuffersize[SMART_AMP_FF_MAX_CH_NUM << 2]; + /* Number of samples of feed forward and feedback frame */ + int ff_fr_sz_samples; + int fb_fr_sz_samples; + int channelmask; + /* Number of channels of DSM */ + int nchannels; + /* Number of samples of feed forward channel */ + int ifsamples; + /* Number of samples of feedback channel */ + int ibsamples; + /* Number of processed samples */ + int ofsamples; + /* Channel bit dempth */ + int bitwidth; + struct smart_amp_param_struct_t param; +}; + +static int maxim_dsm_init(struct smart_amp_mod_struct_t *hspk) +{ + const struct comp_dev *dev = hspk->base.dev; + int *circularbuffersize = hspk->circularbuffersize; + int *delayedsamples = hspk->delayedsamples; + struct dsm_api_init_ext_t initparam; + enum DSM_API_MESSAGE retcode; + + initparam.isamplebitwidth = hspk->bitwidth; + initparam.ichannels = DSM_DEFAULT_NUM_CHANNEL; + initparam.ipcircbuffersizebytes = circularbuffersize; + initparam.ipdelayedsamples = delayedsamples; + initparam.isamplingrate = DSM_DEFAULT_SAMPLE_RATE; + + if (!hspk->dsmhandle) { + comp_err(dev, "[DSM] Initialization failed: dsmhandle not allocated"); + return -EINVAL; + } + + retcode = dsm_api_init(hspk->dsmhandle, &initparam, + sizeof(struct dsm_api_init_ext_t)); + if (retcode != DSM_API_OK) { + goto exit; + } else { + hspk->ff_fr_sz_samples = + initparam.off_framesizesamples; + hspk->fb_fr_sz_samples = + initparam.ofb_framesizesamples; + hspk->channelmask = 0; + hspk->nchannels = initparam.ichannels; + hspk->ifsamples = hspk->ff_fr_sz_samples + * initparam.ichannels; + hspk->ibsamples = hspk->fb_fr_sz_samples + * initparam.ichannels; + } + + comp_dbg(dev, "[DSM] Initialization completed. (module:%p, dsm:%p)", + (uintptr_t)hspk, + (uintptr_t)hspk->dsmhandle); + + return 0; +exit: + comp_err(dev, "[DSM] Initialization failed. ret:%d", retcode); + return (int)retcode; +} + +static int maxim_dsm_get_num_param(struct smart_amp_mod_struct_t *hspk) +{ + enum DSM_API_MESSAGE retcode; + int cmdblock[DSM_GET_PARAM_SZ_PAYLOAD]; + + /* Get number of parameters */ + cmdblock[DSM_GET_ID_IDX] = DSM_SET_CMD_ID(DSM_API_GET_MAXIMUM_CMD_ID); + retcode = dsm_api_get_params(hspk->dsmhandle, 1, (void *)cmdblock); + if (retcode != DSM_API_OK) + return 0; + + return MIN(DSM_DEFAULT_MAX_NUM_PARAM, cmdblock[DSM_GET_CH1_IDX]); +} + +static int maxim_dsm_get_handle_size(struct smart_amp_mod_struct_t *hspk) +{ + enum DSM_API_MESSAGE retcode; + struct dsm_api_memory_size_ext_t memsize; + int *circularbuffersize = hspk->circularbuffersize; + + memsize.ichannels = DSM_DEFAULT_NUM_CHANNEL; + memsize.ipcircbuffersizebytes = circularbuffersize; + memsize.isamplingrate = DSM_DEFAULT_SAMPLE_RATE; + memsize.omemsizerequestedbytes = 0; + memsize.numeqfilters = DSM_DEFAULT_NUM_EQ; + retcode = dsm_api_get_mem(&memsize, + sizeof(struct dsm_api_memory_size_ext_t)); + if (retcode != DSM_API_OK) + return 0; + + return memsize.omemsizerequestedbytes; +} + +static int maxim_dsm_flush(struct smart_amp_mod_struct_t *hspk) +{ + const struct comp_dev *dev = hspk->base.dev; + + memset(hspk->buf.input, 0, DSM_FF_BUF_SZ * sizeof(int32_t)); + memset(hspk->buf.output, 0, DSM_FF_BUF_SZ * sizeof(int32_t)); + memset(hspk->buf.voltage, 0, DSM_FF_BUF_SZ * sizeof(int32_t)); + memset(hspk->buf.current, 0, DSM_FF_BUF_SZ * sizeof(int32_t)); + + memset(hspk->buf.ff.buf, 0, DSM_FF_BUF_DB_SZ * sizeof(int32_t)); + memset(hspk->buf.ff_out.buf, 0, DSM_FF_BUF_DB_SZ * sizeof(int32_t)); + memset(hspk->buf.fb.buf, 0, DSM_FB_BUF_DB_SZ * sizeof(int32_t)); + + hspk->buf.ff.avail = DSM_FF_BUF_SZ; + hspk->buf.ff_out.avail = 0; + hspk->buf.fb.avail = 0; + + comp_dbg(dev, "[DSM] Reset (handle:%p)", hspk); + + return 0; +} + +static int maxim_dsm_get_all_param(struct smart_amp_mod_struct_t *hspk) +{ + struct smart_amp_caldata *caldata = &hspk->param.caldata; + int32_t *db = (int32_t *)caldata->data; + enum DSM_API_MESSAGE retcode; + int cmdblock[DSM_GET_PARAM_SZ_PAYLOAD]; + int num_param = hspk->param.max_param; + int idx; + + for (idx = 0 ; idx < num_param ; idx++) { + /* Read all DSM parameters - Please refer to the API header file + * for more details about get_params() usage info. + */ + cmdblock[DSM_GET_ID_IDX] = DSM_SET_CMD_ID(idx); + retcode = dsm_api_get_params(hspk->dsmhandle, 1, (void *)cmdblock); + if (retcode != DSM_API_OK) { + /* set zero if the parameter is not readable */ + cmdblock[DSM_GET_CH1_IDX] = 0; + cmdblock[DSM_GET_CH2_IDX] = 0; + } + + /* fill the data for the 1st channel 4 byte ID + 4 byte value */ + db[idx * DSM_PARAM_MAX + DSM_PARAM_ID] = DSM_CH1_BITMASK | idx; + db[idx * DSM_PARAM_MAX + DSM_PARAM_VALUE] = cmdblock[DSM_GET_CH1_IDX]; + /* fill the data for the 2nd channel 4 byte ID + 4 byte value + * 2nd channel data have offset for num_param * DSM_PARAM_MAX + */ + db[(idx + num_param) * DSM_PARAM_MAX + DSM_PARAM_ID] = DSM_CH2_BITMASK | idx; + db[(idx + num_param) * DSM_PARAM_MAX + DSM_PARAM_VALUE] = cmdblock[DSM_GET_CH2_IDX]; + } + + return 0; +} + +static int maxim_dsm_get_volatile_param(struct smart_amp_mod_struct_t *hspk, + const struct comp_dev *dev) +{ + struct smart_amp_caldata *caldata = &hspk->param.caldata; + int32_t *db = (int32_t *)caldata->data; + enum DSM_API_MESSAGE retcode; + int cmdblock[DSM_GET_PARAM_SZ_PAYLOAD]; + int num_param = hspk->param.max_param; + int idx; + + /* Update all volatile parameter values */ + for (idx = DSM_API_ADAPTIVE_PARAM_START ; idx <= DSM_API_ADAPTIVE_PARAM_END ; idx++) { + cmdblock[0] = DSM_SET_CMD_ID(idx); + retcode = dsm_api_get_params(hspk->dsmhandle, 1, (void *)cmdblock); + if (retcode != DSM_API_OK) + return -EINVAL; + + /* fill the data for the 1st channel 4 byte ID + 4 byte value */ + db[idx * DSM_PARAM_MAX + DSM_PARAM_ID] = DSM_CH1_BITMASK | idx; + db[idx * DSM_PARAM_MAX + DSM_PARAM_VALUE] = cmdblock[DSM_GET_CH1_IDX]; + /* fill the data for the 2nd channel 4 byte ID + 4 byte value + * 2nd channel data have offset for num_param * DSM_PARAM_MAX + */ + db[(idx + num_param) * DSM_PARAM_MAX + DSM_PARAM_ID] = DSM_CH2_BITMASK | idx; + db[(idx + num_param) * DSM_PARAM_MAX + DSM_PARAM_VALUE] = cmdblock[DSM_GET_CH2_IDX]; + } + + return 0; +} + +static int maxim_dsm_get_param(struct smart_amp_mod_struct_t *hspk, + struct sof_ipc_ctrl_data *cdata, int size) +{ + const struct comp_dev *dev = hspk->base.dev; + struct smart_amp_caldata *caldata = &hspk->param.caldata; + size_t bs; + int ret; + + if (caldata->data) { + /* reset data_pos variable in case of copying first element */ + if (!cdata->msg_index) { + caldata->data_pos = 0; + /* update volatile parameters */ + ret = maxim_dsm_get_volatile_param(hspk, dev); + if (ret) + return -EINVAL; + } + + bs = cdata->num_elems; + + /* return an error in case of mismatch between num_elems and + * required size + */ + if (bs > size) { + comp_err(dev, "[DSM] invalid size %d", bs); + return -EINVAL; + } + + /* copy required size of data */ + ret = memcpy_s(cdata->data->data, size, + (char *)caldata->data + caldata->data_pos, + bs); + + assert(!ret); + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = caldata->data_size; + caldata->data_pos += bs; + } else { + comp_warn(dev, "[DSM] caldata->data not allocated yet."); + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = 0; + } + return 0; +} + +static int maxim_dsm_set_param(struct smart_amp_mod_struct_t *hspk, + struct sof_ipc_ctrl_data *cdata) +{ + const struct comp_dev *dev = hspk->base.dev; + struct smart_amp_param_struct_t *param = &hspk->param; + struct smart_amp_caldata *caldata = &hspk->param.caldata; + /* Model database */ + int32_t *db = (int32_t *)caldata->data; + /* Payload buffer */ + uint32_t *wparam = (uint32_t *)ASSUME_ALIGNED(&cdata->data->data, 4); + /* number of parameters to read */ + int num_param = (cdata->num_elems >> 2); + int idx, id, ch; + + if (!cdata->msg_index) { + /* reset variables for the first set_param frame is arrived */ + param->pos = 0; /* number of received parameters */ + param->param.id = 0; /* variable to keep last parameter ID */ + param->param.value = 0; /* variable to keep last parameter value */ + } + + for (idx = 0 ; idx < num_param ; idx++) { + /* Single DSM parameter consists of ID and value field (total 8 bytes) + * It is even number aligned, but actual payload could be odd number. + * Actual setparam operation is performed when both ID and value are + * ready + */ + if (param->pos % 2 == 0) { + /* even field is ID */ + param->param.id = wparam[idx]; + } else { + /* odd field is value */ + int value[DSM_SET_PARAM_SZ_PAYLOAD]; + enum DSM_API_MESSAGE retcode; + + param->param.value = wparam[idx]; + value[DSM_SET_ID_IDX] = param->param.id; + value[DSM_SET_VALUE_IDX] = param->param.value; + + id = DSM_CH_MASK(param->param.id); + ch = (param->param.id & DSM_CH1_BITMASK) ? 0 : 1; + + /* 2nd channel has (hspk->param.max_param * DSM_PARAM_MAX) sized offset */ + db[(id + ch * hspk->param.max_param) * DSM_PARAM_MAX + DSM_PARAM_VALUE] = + param->param.value; + + /* More detailed information about set_params() function is available + * in the api header file + */ + retcode = dsm_api_set_params(hspk->dsmhandle, 1, value); + if (retcode != DSM_API_OK) { + comp_err(dev, "[DSM] write failure. (id:%x, ret:%x)", + id, retcode); + return -EINVAL; + } + } + param->pos++; + } + + return 0; +} + +static int maxim_dsm_restore_param(struct smart_amp_mod_struct_t *hspk) +{ + const struct comp_dev *dev = hspk->base.dev; + struct smart_amp_caldata *caldata = &hspk->param.caldata; + int32_t *db = (int32_t *)caldata->data; + int num_param = hspk->param.max_param; + int value[DSM_SET_PARAM_SZ_PAYLOAD]; + enum DSM_API_MESSAGE retcode; + int idx; + + /* Restore parameter values in db to the DSM component */ + for (idx = 0 ; (idx < num_param << 1) ; idx++) { + value[DSM_SET_ID_IDX] = db[idx * DSM_PARAM_MAX + DSM_PARAM_ID]; + value[DSM_SET_VALUE_IDX] = db[idx * DSM_PARAM_MAX + DSM_PARAM_VALUE]; + + retcode = dsm_api_set_params(hspk->dsmhandle, 1, value); + if (retcode != DSM_API_OK) { + comp_err(dev, "[DSM] write failure. (id:%x, ret:%x)", + value[DSM_SET_ID_IDX], retcode); + return -EINVAL; + } + } + return 0; +} + +/** + * mod_ops implementation. + */ + +static int maxim_dsm_get_config(struct smart_amp_mod_data_base *mod, + struct sof_ipc_ctrl_data *cdata, uint32_t size) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + + return maxim_dsm_get_param(hspk, cdata, size); +} + +static int maxim_dsm_set_config(struct smart_amp_mod_data_base *mod, + struct sof_ipc_ctrl_data *cdata) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + + return maxim_dsm_set_param(hspk, cdata); +} + +static int maxim_dsm_ff_proc(struct smart_amp_mod_data_base *mod, + uint32_t frames, + struct smart_amp_mod_stream *in, + struct smart_amp_mod_stream *out) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + union maxim_dsm_buf buf, buf_out; + int16_t *input = (int16_t *)hspk->buf.input; + int16_t *output = (int16_t *)hspk->buf.output; + int32_t *input32 = hspk->buf.input; + int32_t *output32 = hspk->buf.output; + int *w_ptr = &hspk->buf.ff.avail; + int *r_ptr = &hspk->buf.ff_out.avail; + bool is_16bit = (in->frame_fmt == SOF_IPC_FRAME_S16_LE); + int szsample = (is_16bit ? 2 : 4); + int nsamples = frames * in->channels; + int remain; + int idx; + int ret = 0; + + buf.buf16 = (int16_t *)hspk->buf.ff.buf; + buf.buf32 = (int32_t *)hspk->buf.ff.buf; + buf_out.buf16 = (int16_t *)hspk->buf.ff_out.buf; + buf_out.buf32 = (int32_t *)hspk->buf.ff_out.buf; + + /* Report all frames consumed even if buffer overflow to prevent source + * congestion. Same for frames produced to keep the stream rolling. + */ + in->consumed = frames; + out->produced = frames; + + /* Current pointer(w_ptr) + number of input frames(nsamples) + * must be smaller than buffer size limit + */ + if (*w_ptr + nsamples <= DSM_FF_BUF_DB_SZ) { + if (is_16bit) + memcpy_s(&buf.buf16[*w_ptr], nsamples * szsample, + in->buf.data, nsamples * szsample); + else + memcpy_s(&buf.buf32[*w_ptr], nsamples * szsample, + in->buf.data, nsamples * szsample); + *w_ptr += nsamples; + } else { + comp_warn(mod->dev, + "[DSM] Feed Forward buffer overflow. (w_ptr : %d + %d > %d)", + *w_ptr, nsamples, DSM_FF_BUF_DB_SZ); + ret = -EOVERFLOW; + goto error; + } + + /* Run DSM Feedforward process if the buffer is ready */ + if (*w_ptr >= DSM_FF_BUF_SZ) { + if (is_16bit) { + /* Buffer ordering for DSM : LRLR... -> LL...RR... */ + for (idx = 0; idx < DSM_FRM_SZ; idx++) { + input[idx] = (buf.buf16[2 * idx]); + input[idx + DSM_FRM_SZ] = + (buf.buf16[2 * idx + 1]); + } + } else { + for (idx = 0; idx < DSM_FRM_SZ; idx++) { + input32[idx] = buf.buf32[2 * idx]; + input32[idx + DSM_FRM_SZ] = + buf.buf32[2 * idx + 1]; + } + } + + remain = (*w_ptr - DSM_FF_BUF_SZ); + if (remain) { + if (is_16bit) + memcpy_s(&buf.buf16[0], remain * szsample, + &buf.buf16[DSM_FF_BUF_SZ], + remain * szsample); + else + memcpy_s(&buf.buf32[0], remain * szsample, + &buf.buf32[DSM_FF_BUF_SZ], + remain * szsample); + } + *w_ptr -= DSM_FF_BUF_SZ; + + hspk->ifsamples = hspk->nchannels * hspk->ff_fr_sz_samples; + dsm_api_ff_process(hspk->dsmhandle, hspk->channelmask, + input, &hspk->ifsamples, + output, &hspk->ofsamples); + + if (is_16bit) { + for (idx = 0; idx < DSM_FRM_SZ; idx++) { + /* Buffer re-ordering LR/LR/LR */ + buf_out.buf16[*r_ptr + 2 * idx] = (output[idx]); + buf_out.buf16[*r_ptr + 2 * idx + 1] = + output[idx + DSM_FRM_SZ]; + } + } else { + dsm_api_ff_process(hspk->dsmhandle, hspk->channelmask, + (short *)input32, &hspk->ifsamples, + (short *)output32, &hspk->ofsamples); + for (idx = 0; idx < DSM_FRM_SZ; idx++) { + buf_out.buf32[*r_ptr + 2 * idx] = output32[idx]; + buf_out.buf32[*r_ptr + 2 * idx + 1] = + output32[idx + DSM_FRM_SZ]; + } + } + + *r_ptr += DSM_FF_BUF_SZ; + } + + /* Output buffer preparation */ + if (*r_ptr >= nsamples) { + if (is_16bit) + memcpy_s(out->buf.data, nsamples * szsample, + buf_out.buf16, nsamples * szsample); + else + memcpy_s(out->buf.data, nsamples * szsample, + buf_out.buf32, nsamples * szsample); + + remain = (*r_ptr - nsamples); + if (remain) { + if (is_16bit) + memcpy_s(&buf_out.buf16[0], remain * szsample, + &buf_out.buf16[nsamples], + remain * szsample); + else + memcpy_s(&buf_out.buf32[0], remain * szsample, + &buf_out.buf32[nsamples], + remain * szsample); + } + *r_ptr -= nsamples; + return ret; + } + /* else { */ + comp_err(mod->dev, "[DSM] DSM FF process underrun. r_ptr : %d", *r_ptr); + ret = -ENODATA; + +error: + /* TODO(Maxim): undefined behavior when buffer overflow in previous code. + * It leads to early return and no sample written to output + * buffer. However the sink buffer will still writeback + * avail_frames data copied from output buffer. + */ + /* set all-zero output when buffer overflow or process underrun. */ + memset_s(out->buf.data, out->buf.size, 0, nsamples * szsample); + return ret; +} + +static int maxim_dsm_fb_proc(struct smart_amp_mod_data_base *mod, + uint32_t frames, + struct smart_amp_mod_stream *in) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + union maxim_dsm_buf buf; + int *w_ptr = &hspk->buf.fb.avail; + int16_t *v = (int16_t *)hspk->buf.voltage; + int16_t *i = (int16_t *)hspk->buf.current; + int32_t *v32 = hspk->buf.voltage; + int32_t *i32 = hspk->buf.current; + bool is_16bit = (in->frame_fmt == SOF_IPC_FRAME_S16_LE); + int szsample = (is_16bit ? 2 : 4); + int nsamples = frames * in->channels; + int remain; + int idx; + + buf.buf16 = (int16_t *)hspk->buf.fb.buf; + buf.buf32 = hspk->buf.fb.buf; + + /* Set all frames consumed even if buffer overflow to prevent source + * congestion. + */ + in->consumed = frames; + + /* Current pointer(w_ptr) + number of input frames(nsamples) + * must be smaller than buffer size limit + */ + if (*w_ptr + nsamples <= DSM_FB_BUF_DB_SZ) { + if (is_16bit) + memcpy_s(&buf.buf16[*w_ptr], nsamples * szsample, + in->buf.data, nsamples * szsample); + else + memcpy_s(&buf.buf32[*w_ptr], nsamples * szsample, + in->buf.data, nsamples * szsample); + *w_ptr += nsamples; + } else { + comp_warn(mod->dev, "[DSM] Feedback buffer overflow. w_ptr : %d", + *w_ptr); + return -EOVERFLOW; + } + + /* Run DSM Feedback process if the buffer is ready */ + if (*w_ptr >= DSM_FB_BUF_SZ) { + if (is_16bit) { + for (idx = 0; idx < DSM_FRM_SZ; idx++) { + /* Buffer ordering for DSM : VIVI... -> VV... II...*/ + v[idx] = buf.buf16[4 * idx]; + i[idx] = buf.buf16[4 * idx + 1]; + v[idx + DSM_FRM_SZ] = buf.buf16[4 * idx + 2]; + i[idx + DSM_FRM_SZ] = buf.buf16[4 * idx + 3]; + } + } else { + for (idx = 0; idx < DSM_FRM_SZ; idx++) { + v[idx] = buf.buf32[4 * idx]; + i[idx] = buf.buf32[4 * idx + 1]; + v[idx + DSM_FRM_SZ] = + buf.buf32[4 * idx + 2]; + i[idx + DSM_FRM_SZ] = + buf.buf32[4 * idx + 3]; + } + } + + remain = (*w_ptr - DSM_FB_BUF_SZ); + if (remain) { + if (is_16bit) + memcpy_s(&buf.buf16[0], remain * szsample, + &buf.buf16[DSM_FB_BUF_SZ], + remain * szsample); + else + memcpy_s(&buf.buf32[0], remain * szsample, + &buf.buf32[DSM_FB_BUF_SZ], + remain * szsample); + } + *w_ptr -= DSM_FB_BUF_SZ; + + hspk->ibsamples = hspk->fb_fr_sz_samples * hspk->nchannels; + if (is_16bit) + dsm_api_fb_process(hspk->dsmhandle, + hspk->channelmask, + i, v, &hspk->ibsamples); + else + dsm_api_fb_process(hspk->dsmhandle, + hspk->channelmask, + (short *)i32, (short *)v32, &hspk->ibsamples); + } + return 0; +} + +static int maxim_dsm_preinit(struct smart_amp_mod_data_base *mod) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + + /* Bitwidth information is not available. Use 16bit as default. + * Re-initialize in the prepare function if ncessary + */ + hspk->bitwidth = 16; + return maxim_dsm_init(hspk); +} + +static int maxim_dsm_query_memblk_size(struct smart_amp_mod_data_base *mod, + enum smart_amp_mod_memblk blk) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + int ret; + + switch (blk) { + case MOD_MEMBLK_PRIVATE: + /* Memory size for private data block - dsmhandle */ + ret = maxim_dsm_get_handle_size(hspk); + if (ret <= 0) + comp_err(mod->dev, "[DSM] Get handle size error"); + break; + case MOD_MEMBLK_FRAME: + /* Memory size for frame buffer block - smart_amp_buf_struct_t */ + /* smart_amp_buf_struct_t -> input, output, voltage, current */ + ret = 4 * DSM_FF_BUF_SZ * sizeof(int32_t); + /* smart_amp_buf_struct_t -> ff, ff_out, fb */ + ret += 2 * DSM_FF_BUF_DB_SZ * sizeof(int32_t) + DSM_FB_BUF_DB_SZ * sizeof(int32_t); + break; + case MOD_MEMBLK_PARAM: + /* Memory size for param blob block - caldata */ + /* Get the max. number of parameter to allocate memory for model data */ + ret = maxim_dsm_get_num_param(hspk); + if (ret < 0) { + comp_err(mod->dev, "[DSM] Get parameter size error"); + return -EINVAL; + } + hspk->param.max_param = ret; + ret = hspk->param.max_param * DSM_SINGLE_PARAM_SZ * sizeof(int32_t); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int maxim_dsm_set_memblk(struct smart_amp_mod_data_base *mod, + enum smart_amp_mod_memblk blk, + struct smart_amp_buf *buf) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + int32_t *mem_ptr; + + switch (blk) { + case MOD_MEMBLK_PRIVATE: + /* Assign memory to private data */ + hspk->dsmhandle = buf->data; + bzero(hspk->dsmhandle, buf->size); + break; + case MOD_MEMBLK_FRAME: + /* Assign memory to frame buffers */ + mem_ptr = (int32_t *)buf->data; + hspk->buf.input = mem_ptr; + mem_ptr += DSM_FF_BUF_SZ; + hspk->buf.output = mem_ptr; + mem_ptr += DSM_FF_BUF_SZ; + hspk->buf.voltage = mem_ptr; + mem_ptr += DSM_FF_BUF_SZ; + hspk->buf.current = mem_ptr; + mem_ptr += DSM_FF_BUF_SZ; + hspk->buf.ff.buf = mem_ptr; + mem_ptr += DSM_FF_BUF_DB_SZ; + hspk->buf.ff_out.buf = mem_ptr; + mem_ptr += DSM_FF_BUF_DB_SZ; + hspk->buf.fb.buf = mem_ptr; + break; + case MOD_MEMBLK_PARAM: + /* Assign memory to config caldata */ + hspk->param.caldata.data = buf->data; + hspk->param.caldata.data_size = buf->size; + bzero(hspk->param.caldata.data, hspk->param.caldata.data_size); + hspk->param.caldata.data_pos = 0; + + /* update full parameter values */ + if (maxim_dsm_get_all_param(hspk) < 0) + return -EINVAL; + break; + default: + return -EINVAL; + } + return 0; +} + +static int maxim_dsm_get_supported_fmts(struct smart_amp_mod_data_base *mod, + const uint16_t **mod_fmts, int *num_mod_fmts) +{ + *num_mod_fmts = supported_fmt_count; + *mod_fmts = supported_fmts; + return 0; +} + +static int maxim_dsm_set_fmt(struct smart_amp_mod_data_base *mod, uint16_t mod_fmt) +{ + struct smart_amp_mod_struct_t *hspk = (struct smart_amp_mod_struct_t *)mod; + int ret; + + comp_dbg(mod->dev, "[DSM] smart_amp_mod_set_fmt(): %u", mod_fmt); + + hspk->bitwidth = get_sample_bitdepth(mod_fmt); + + ret = maxim_dsm_init(hspk); + if (ret) { + comp_err(mod->dev, "[DSM] Re-initialization error."); + goto error; + } + ret = maxim_dsm_restore_param(hspk); + if (ret) { + comp_err(mod->dev, "[DSM] Restoration error."); + goto error; + } + +error: + maxim_dsm_flush(hspk); + return ret; +} + +static int maxim_dsm_reset(struct smart_amp_mod_data_base *mod) +{ + /* no-op for reset */ + return 0; +} + +static const struct inner_model_ops maxim_dsm_ops = { + .init = maxim_dsm_preinit, + .query_memblk_size = maxim_dsm_query_memblk_size, + .set_memblk = maxim_dsm_set_memblk, + .get_supported_fmts = maxim_dsm_get_supported_fmts, + .set_fmt = maxim_dsm_set_fmt, + .ff_proc = maxim_dsm_ff_proc, + .fb_proc = maxim_dsm_fb_proc, + .set_config = maxim_dsm_set_config, + .get_config = maxim_dsm_get_config, + .reset = maxim_dsm_reset +}; + +/** + * mod_data_create() implementation. + */ + +struct smart_amp_mod_data_base *mod_data_create(const struct comp_dev *dev) +{ + struct smart_amp_mod_struct_t *hspk; + + hspk = rzalloc(SOF_MEM_FLAG_USER, sizeof(*hspk)); + if (!hspk) + return NULL; + + hspk->base.dev = dev; + hspk->base.mod_ops = &maxim_dsm_ops; + return &hspk->base; +} diff --git a/src/audio/smart_amp/smart_amp_passthru.c b/src/audio/smart_amp/smart_amp_passthru.c new file mode 100644 index 000000000000..53084345d6d1 --- /dev/null +++ b/src/audio/smart_amp/smart_amp_passthru.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Google LLC. +// +// Author: Pin-chih Lin <johnylin@google.com> + +#include <sof/audio/component.h> +#include <sof/trace/trace.h> +#include <sof/ipc/msg.h> + +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <sof/common.h> +#include <stdint.h> +#include <stdlib.h> +#include <sof/audio/smart_amp/smart_amp.h> + +LOG_MODULE_DECLARE(smart_amp, CONFIG_SOF_LOG_LEVEL); + +/* self-declared inner model data struct */ +struct passthru_mod_data { + struct smart_amp_mod_data_base base; + uint16_t ff_fmt; + uint16_t fb_fmt; +}; + +static const int supported_fmt_count = 3; +static const uint16_t supported_fmts[] = { + SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE +}; + +/** + * mod ops implementation. + */ + +static int passthru_mod_init(struct smart_amp_mod_data_base *mod) +{ + comp_info(mod->dev, "[PassThru Amp] init"); + return 0; +} + +static int passthru_mod_query_memblk_size(struct smart_amp_mod_data_base *mod, + enum smart_amp_mod_memblk blk) +{ + return 0; +} + +static int passthru_mod_set_memblk(struct smart_amp_mod_data_base *mod, + enum smart_amp_mod_memblk blk, + struct smart_amp_buf *buf) +{ + return 0; +} + +static int passthru_mod_get_supported_fmts(struct smart_amp_mod_data_base *mod, + const uint16_t **mod_fmts, int *num_mod_fmts) +{ + *num_mod_fmts = supported_fmt_count; + *mod_fmts = supported_fmts; + return 0; +} + +static int passthru_mod_set_fmt(struct smart_amp_mod_data_base *mod, uint16_t mod_fmt) +{ + struct passthru_mod_data *pmd = (struct passthru_mod_data *)mod; + + comp_info(mod->dev, "[PassThru Amp] set fmt:%u", mod_fmt); + pmd->ff_fmt = mod_fmt; + pmd->fb_fmt = mod_fmt; + return 0; +} + +static int passthru_mod_ff_proc(struct smart_amp_mod_data_base *mod, + uint32_t frames, + struct smart_amp_mod_stream *in, + struct smart_amp_mod_stream *out) +{ + struct passthru_mod_data *pmd = (struct passthru_mod_data *)mod; + bool is_16bit = (pmd->ff_fmt == SOF_IPC_FRAME_S16_LE); + uint32_t szsample = (is_16bit ? 2 : 4); + uint32_t size = frames * in->channels * szsample; + + comp_dbg(mod->dev, "[PassThru Amp] bypass %u frames", frames); + + /* passthrough all frames */ + memcpy_s(out->buf.data, out->buf.size, in->buf.data, size); + in->consumed = frames; + out->produced = frames; + return 0; +} + +static int passthru_mod_fb_proc(struct smart_amp_mod_data_base *mod, + uint32_t frames, + struct smart_amp_mod_stream *in) +{ + in->consumed = frames; + return 0; +} + +static int passthru_mod_get_config(struct smart_amp_mod_data_base *mod, + struct sof_ipc_ctrl_data *cdata, uint32_t size) +{ + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = 0; + return 0; +} + +static int passthru_mod_set_config(struct smart_amp_mod_data_base *mod, + struct sof_ipc_ctrl_data *cdata) +{ + return 0; +} + +static int passthru_mod_reset(struct smart_amp_mod_data_base *mod) +{ + comp_info(mod->dev, "[PassThru Amp] reset"); + return 0; +} + +static const struct inner_model_ops passthru_mod_ops = { + .init = passthru_mod_init, + .query_memblk_size = passthru_mod_query_memblk_size, + .set_memblk = passthru_mod_set_memblk, + .get_supported_fmts = passthru_mod_get_supported_fmts, + .set_fmt = passthru_mod_set_fmt, + .ff_proc = passthru_mod_ff_proc, + .fb_proc = passthru_mod_fb_proc, + .set_config = passthru_mod_set_config, + .get_config = passthru_mod_get_config, + .reset = passthru_mod_reset +}; + +/** + * mod_data_create() implementation. + */ + +struct smart_amp_mod_data_base *mod_data_create(const struct comp_dev *dev) +{ + struct passthru_mod_data *mod; + + mod = rzalloc(SOF_MEM_FLAG_USER, sizeof(*mod)); + if (!mod) + return NULL; + + mod->base.dev = dev; + mod->base.mod_ops = &passthru_mod_ops; + return &mod->base; +} diff --git a/src/audio/sound_dose/CMakeLists.txt b/src/audio/sound_dose/CMakeLists.txt new file mode 100644 index 000000000000..d6cd9c10b798 --- /dev/null +++ b/src/audio/sound_dose/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_SOUND_DOSE STREQUAL "m") + add_subdirectory(llext ${PROJECT_BINARY_DIR}/sound_dose_llext) + add_dependencies(app sound_dose) +else() + add_local_sources(sof sound_dose.c) + add_local_sources(sof sound_dose-generic.c) + add_local_sources(sof sound_dose-ipc4.c) +endif() diff --git a/src/audio/sound_dose/Kconfig b/src/audio/sound_dose/Kconfig new file mode 100644 index 000000000000..a15e9a2b724a --- /dev/null +++ b/src/audio/sound_dose/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_SOUND_DOSE + tristate "Sound Dose module" + default m if LIBRARY_DEFAULT_MODULAR + depends on COMP_MODULE_ADAPTER + depends on IPC_MAJOR_4 + select MATH_IIR + select MATH_IIR_DF1 + select MATH_EXP + help + Select this for Sound Dose SOF module. The purpose is + to calculate for audio playback MEL values (momentary + sound exposure level) to provide to user space the data + to compute the sound dose CSD as defined in EN 50332-3. diff --git a/src/audio/sound_dose/README.md b/src/audio/sound_dose/README.md new file mode 100644 index 000000000000..0436da7b886d --- /dev/null +++ b/src/audio/sound_dose/README.md @@ -0,0 +1,14 @@ +# Sound Dose Architecture + +This directory contains the Sound Dose component. + +## Overview + +Monitors the acoustic energy output to headphones over time, ensuring it complies with regulations governing maximum cumulative sound exposure (to protect user hearing). + +## Configuration and Scripts + +- **Kconfig**: Dictates the Sound Dose component (`COMP_SOUND_DOSE`) with prerequisites on `IPC_MAJOR_4` and `COMP_MODULE_ADAPTER`, plus mathematical modules (`MATH_EXP`, `MATH_IIR`). +- **CMakeLists.txt**: Compiles generic operations (`sound_dose-generic.c`, `sound_dose.c`) alongside their IPC wrappers (`sound_dose-ipc4.c`), offering full `llext` enablement. +- **sound_dose.toml**: Contains topology descriptors, declaring UUID `UUIDREG_STR_SOUND_DOSE` and standard memory allocation bounds. +- **Topology (.conf)**: Extracted from `tools/topology/topology2/include/components/sound_dose.conf`, configuring a `sound_dose` widget of type `effect` (UUID `7c:9d:3f:a4:75:ea:d5:44:94:2d:96:79:91:a3:38:09`). diff --git a/src/audio/sound_dose/llext/CMakeLists.txt b/src/audio/sound_dose/llext/CMakeLists.txt new file mode 100644 index 000000000000..705280b08648 --- /dev/null +++ b/src/audio/sound_dose/llext/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("sound_dose" + SOURCES ../sound_dose.c + ../sound_dose-generic.c + ../sound_dose-ipc4.c + LIB openmodules +) diff --git a/src/audio/sound_dose/llext/llext.toml.h b/src/audio/sound_dose/llext/llext.toml.h new file mode 100644 index 000000000000..b5bc25562bd2 --- /dev/null +++ b/src/audio/sound_dose/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../sound_dose.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/sound_dose/sound_dose-generic.c b/src/audio/sound_dose/sound_dose-generic.c new file mode 100644 index 000000000000..fb5f63fc844a --- /dev/null +++ b/src/audio/sound_dose/sound_dose-generic.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <sof/math/log.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> +#include <stdbool.h> +#include <stdint.h> + +#include "sound_dose.h" + +LOG_MODULE_DECLARE(sound_dose, CONFIG_SOF_LOG_LEVEL); + +static void sound_dose_calculate_mel(const struct processing_module *mod, int frames) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + uint64_t energy_sum; + uint32_t log_arg; + int32_t tmp; + int ch; + + cd->frames_count += frames; + if (cd->frames_count < cd->report_count) + return; + + cd->frames_count = 0; + energy_sum = 0; + for (ch = 0; ch < cd->channels; ch++) { + energy_sum += cd->energy[ch]; + cd->energy[ch] = 0; + } + + /* Log2 argument is Q32.0 unsigned, log2 returns Q16.16 signed. + * Energy is Qx.30, so the argument 2^30 times scaled. Also to keep + * argument within uint32_t range, need to scale it down by 19. + * To compensate these, need to add 19 (Q16.16) and subtract 30 (Q16.16) + * from logarithm value. + */ + log_arg = (uint32_t)(energy_sum >> SOUND_DOSE_ENERGY_SHIFT); + log_arg = MAX(log_arg, 1); + tmp = base2_logarithm(log_arg); + tmp += SOUND_DOSE_LOG_FIXED_OFFSET; /* Compensate Q2.30 and energy shift */ + tmp += cd->log_offset_for_mean; /* logarithm subtract for mean */ + tmp = Q_MULTSR_32X32((int64_t)tmp, SOUND_DOSE_TEN_OVER_LOG2_10_Q29, + SOUND_DOSE_LOGOFFS_Q, SOUND_DOSE_LOGMULT_Q, SOUND_DOSE_LOGOFFS_Q); + cd->level_dbfs = tmp + SOUND_DOSE_WEIGHT_FILTERS_OFFS_Q16 + SOUND_DOSE_DFBS_OFFS_Q16; + + /* If stereo sum channel level values and subtract 3 dB, to generalize + * For stereo or more subtract -1.5 dB per channel. + */ + if (cd->channels > 1) + cd->level_dbfs += cd->channels * SOUND_DOSE_MEL_CHANNELS_SUM_FIX; + + sound_dose_report_mel(mod); +} + +#if CONFIG_FORMAT_S16LE + +/** + * sound_dose_s16() - Process S16_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 16-bit signed integer PCM formats. The + * audio samples in every frame are re-order to channels order defined in + * component data channel_map[]. + * + * Return: Value zero for success, otherwise an error code. + */ +static int sound_dose_s16(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct iir_state_df1 *iir; + int32_t weighted; + int16_t sample; + int16_t const *x0, *x, *x_start, *x_end; + int16_t *y0, *y, *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int ch; + int i; + const int channels = cd->channels; + + /* Get pointer to source data in circular buffer, get buffer start and size to + * check for wrap. The size in bytes is converted to number of s16 samples to + * control the samples process loop. If the number of bytes requested is not + * possible, an error is returned. + */ + ret = source_get_data_s16(source, bytes, &x0, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s16(sink, bytes, &y0, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x0; + samples_without_wrap = y_end - y0; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, samples); + for (ch = 0; ch < cd->channels; ch++) { + iir = &cd->iir[ch]; + x = x0++; + y = y0++; + for (i = 0; i < samples_without_wrap; i += channels) { + sample = sat_int16(Q_MULTSR_32X32((int64_t)cd->gain, *x, + SOUND_DOSE_GAIN_Q, + SOUND_DOSE_S16_Q, + SOUND_DOSE_S16_Q)); + *y = sample; + x += channels; + y += channels; + weighted = iir_df1(iir, ((int32_t)sample) << 16) >> 16; + + /* Update sound dose, energy is Q1.15 * Q1.15 --> Q2.30 */ + cd->energy[ch] += weighted * weighted; + } + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x0 += samples_without_wrap; + y0 += samples_without_wrap; + x0 = (x0 >= x_end) ? x0 - x_size : x0; + y0 = (y0 >= y_end) ? y0 - y_size : y0; + + /* Update processed samples count for next loop iteration. */ + samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + + sound_dose_calculate_mel(mod, frames); + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S32LE || CONFIG_FORMAT_S24LE + +/** + * sound_dose_s32() - Process S32_LE or S24_4LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * Processing function for signed integer 32-bit PCM formats. The same + * function works for s24 and s32 formats since the samples values are + * not modified in computation. The audio samples in every frame are + * re-order to channels order defined in component data channel_map[]. + * + * Return: Value zero for success, otherwise an error code. + */ +static int sound_dose_s32(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct iir_state_df1 *iir; + int32_t sample; + int32_t const *x0, *x, *x_start, *x_end; + int32_t *y0, *y, *y_start, *y_end; + int32_t weighted; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int ch; + int i; + const int channels = cd->channels; + + /* Get pointer to source data in circular buffer, get buffer start and size to + * check for wrap. The size in bytes is converted to number of s32 samples to + * control the samples process loop. If the number of bytes requested is not + * possible, an error is returned. + */ + ret = source_get_data_s32(source, bytes, &x0, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, &y0, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x0; + samples_without_wrap = y_end - y0; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, samples); + for (ch = 0; ch < cd->channels; ch++) { + iir = &cd->iir[ch]; + x = x0++; + y = y0++; + for (i = 0; i < samples_without_wrap; i += channels) { + sample = sat_int32(Q_MULTSR_32X32((int64_t)cd->gain, *x, + SOUND_DOSE_GAIN_Q, + SOUND_DOSE_S32_Q, + SOUND_DOSE_S32_Q)); + *y = sample; + x += channels; + y += channels; + weighted = iir_df1(iir, sample) >> 16; + + /* Update sound dose, energy is Q1.15 * Q1.15 --> Q2.30 */ + cd->energy[ch] += weighted * weighted; + } + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x0 += samples_without_wrap; + y0 += samples_without_wrap; + x0 = (x0 >= x_end) ? x0 - x_size : x0; + y0 = (y0 >= y_end) ? y0 - y_size : y0; + + /* Update processed samples count for next loop iteration. */ + samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + + sound_dose_calculate_mel(mod, frames); + return 0; +} +#endif /* CONFIG_FORMAT_S32LE || CONFIG_FORMAT_S24LE */ + +/* This struct array defines the used processing functions for + * the PCM formats + */ +const struct sound_dose_proc_fnmap sound_dose_proc_fnmap[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, sound_dose_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, sound_dose_s32}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, sound_dose_s32}, +#endif +}; + +/** + * sound_dose_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +sound_dose_func sound_dose_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < ARRAY_SIZE(sound_dose_proc_fnmap); i++) + if (src_fmt == sound_dose_proc_fnmap[i].frame_fmt) + return sound_dose_proc_fnmap[i].sound_dose_proc_func; + + return NULL; +} diff --git a/src/audio/sound_dose/sound_dose-ipc4.c b/src/audio/sound_dose/sound_dose-ipc4.c new file mode 100644 index 000000000000..fd3a8151e984 --- /dev/null +++ b/src/audio/sound_dose/sound_dose-ipc4.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc4/base-config.h> +#include <ipc4/header.h> +#include <ipc4/module.h> +#include <ipc4/notification.h> + +#include "sound_dose.h" + +LOG_MODULE_DECLARE(sound_dose, CONFIG_SOF_LOG_LEVEL); + +static struct ipc_msg *sound_dose_notification_init(struct processing_module *mod, + uint32_t control_type_param_id, + uint32_t control_id) +{ + struct ipc_msg msg_proto; + struct comp_dev *dev = mod->dev; + struct comp_ipc_config *ipc_config = &dev->ipc_config; + union ipc4_notification_header *primary = + (union ipc4_notification_header *)&msg_proto.header; + struct sof_ipc4_notify_module_data *msg_module_data; + struct sof_ipc4_control_msg_payload *msg_payload; + struct ipc_msg *msg; + + /* Clear header, extension, and other ipc_msg members */ + memset_s(&msg_proto, sizeof(msg_proto), 0, sizeof(msg_proto)); + primary->r.notif_type = SOF_IPC4_MODULE_NOTIFICATION; + primary->r.type = SOF_IPC4_GLB_NOTIFICATION; + primary->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + primary->r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg = ipc_msg_w_ext_init(msg_proto.header, msg_proto.extension, + sizeof(struct sof_ipc4_notify_module_data) + + sizeof(struct sof_ipc4_control_msg_payload)); + if (!msg) + return NULL; + + msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data; + msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id); + msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id); + msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL | + control_type_param_id; + msg_module_data->event_data_size = sizeof(struct sof_ipc4_control_msg_payload); + msg_payload = (struct sof_ipc4_control_msg_payload *)msg_module_data->event_data; + msg_payload->id = control_id; + msg_payload->num_elems = 0; + comp_dbg(dev, "instance_id = 0x%08x, module_id = 0x%08x", + msg_module_data->instance_id, msg_module_data->module_id); + return msg; +} + +int sound_dose_ipc_notification_init(struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + + cd->msg = sound_dose_notification_init(mod, SOF_IPC4_BYTES_CONTROL_PARAM_ID, + SOF_SOUND_DOSE_PAYLOAD_PARAM_ID); + if (!cd->msg) { + comp_err(mod->dev, "Failed to initialize control notification."); + return -ENOMEM; + } + + return 0; +} + +void sound_dose_send_ipc_notification(const struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + + ipc_msg_send(cd->msg, cd->msg->tx_data, false); +} + +/* This function handles the set_config() commands. The controls have the next purpose: + * - SOF_SOUND_DOSE_SETUP_PARAM_ID sets the acoustical sensitivity of the DAC, headphone + * amplifier and assumed worst-case loud headphones. E.g. 0 dBFS equals 100 dBSPL. The + * sensitivity is for max user volume. + * -SOF_SOUND_DOSE_VOLUME_PARAM_ID is set to new decibels value if volume is adjusted + * down from user maximum. + * - SOF_SOUND_DOSE_GAIN_PARAM_ID is normally set to 0 decibels value. If the user's + * listening is exceeding the safe MSD threshold the user's volume can be forced down + * with this gain. The bytes control is not visible in the mixer, so there is no simple + * way for user to force volume up with alsamixer or amixer utililities. The gain + * should be restored to 0 dB after the MSD value looks again safe. + * E.g. setting -10 dB value lowers user's listening volume with -10 dB and also lower + * the reported MEL values by -10 dB. + * + * These controls can be used as preferred by the MEL->MSD algorithm in user space. The + * controls offset the reported MEL values. The same offset can be also done in user + * space. And could use codec volume instead of SOF_SOUND_DOSE_GAIN_PARAM_ID if preferred. + */ +__cold static int +_sound_dose_set_config(struct processing_module *mod, uint32_t param_id, + uint32_t control_id, const void *data, uint32_t data_size) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct sound_dose_setup_config *new_setup; + struct sound_dose_volume_config *new_volume; + struct sound_dose_gain_config *new_gain; + struct comp_dev *dev = mod->dev; + uint8_t *dest; + size_t dest_size; + + assert_can_be_cold(); + + if (param_id != SOF_IPC4_BYTES_CONTROL_PARAM_ID) { + comp_warn(dev, "Not supported control type: %u", param_id); + return 0; + } + + comp_dbg(dev, "param_id = %u, control_id: %u", param_id, control_id); + + switch (control_id) { + case SOF_SOUND_DOSE_SETUP_PARAM_ID: + dest_size = sizeof(struct sound_dose_setup_config); + dest = (uint8_t *)&cd->setup; + break; + case SOF_SOUND_DOSE_VOLUME_PARAM_ID: + dest_size = sizeof(struct sound_dose_volume_config); + dest = (uint8_t *)&cd->vol; + break; + case SOF_SOUND_DOSE_GAIN_PARAM_ID: + dest_size = sizeof(struct sound_dose_gain_config); + dest = (uint8_t *)&cd->att; + break; + case SOF_SOUND_DOSE_PAYLOAD_PARAM_ID: + return 0; /* Just return, no need to set the audio feature data */ + default: + comp_warn(dev, "Ignored illegal control_id: %u", control_id); + return 0; + } + + if (data_size != dest_size) { + comp_err(dev, "Illegal fragment_size %u for %u:%u", + data_size, param_id, control_id); + return -EINVAL; + } + + switch (control_id) { + case SOF_SOUND_DOSE_SETUP_PARAM_ID: + new_setup = (struct sound_dose_setup_config *)data; + if (new_setup->sens_dbfs_dbspl < SOF_SOUND_DOSE_SENS_MIN_DB || + new_setup->sens_dbfs_dbspl > SOF_SOUND_DOSE_SENS_MAX_DB) { + comp_err(dev, "Illegal sensitivity = %d", new_setup->sens_dbfs_dbspl); + return -EINVAL; + } + break; + case SOF_SOUND_DOSE_VOLUME_PARAM_ID: + new_volume = (struct sound_dose_volume_config *)data; + if (new_volume->volume_offset < SOF_SOUND_DOSE_VOLUME_MIN_DB || + new_volume->volume_offset > SOF_SOUND_DOSE_VOLUME_MAX_DB) { + comp_err(dev, "Illegal volume = %d", new_volume->volume_offset); + return -EINVAL; + } + break; + case SOF_SOUND_DOSE_GAIN_PARAM_ID: + new_gain = (struct sound_dose_gain_config *)data; + if (new_gain->gain < SOF_SOUND_DOSE_GAIN_MIN_DB || + new_gain->gain > SOF_SOUND_DOSE_GAIN_MAX_DB) { + comp_err(dev, "Illegal gain = %d", new_gain->gain); + return -EINVAL; + } + cd->gain_update = true; + break; + } + + memcpy_s(dest, dest_size, data, data_size); + return 0; +} + +/* This function is the main set_config() handler. The two variants of bytes control + * are handled. The case where param_id is set to SOF_IPC4_BYTES_CONTROL_PARAM_ID + * with header sof_ipc4_control_msg_payload has the benefit of being able to pass + * the id of the control. It is useful when there are multiple instances of + * bytes control. The legacy case is where control instances are identified with + * param_id value. The first format with header must be used when a control supports + * a notification to user space. The legacy works only for simple set control usage. + */ +__cold int sound_dose_set_config(struct processing_module *mod, + uint32_t param_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) +{ + int ret; + + assert_can_be_cold(); + + if (!fragment_size) { + comp_warn(mod->dev, "Zero fragment size for param_id %d", param_id); + return 0; + } + + if (param_id == SOF_IPC4_BYTES_CONTROL_PARAM_ID) { + struct sof_ipc4_control_msg_payload *msg_payload; + + msg_payload = (struct sof_ipc4_control_msg_payload *)fragment; + + ret = _sound_dose_set_config(mod, param_id, msg_payload->id, + msg_payload->data, msg_payload->num_elems); + } else { + ret = _sound_dose_set_config(mod, SOF_IPC4_BYTES_CONTROL_PARAM_ID, + param_id, fragment, fragment_size); + } + + return ret; +} + +/* This function copies the data for get_config() request by the driver. Only + * the SOF_SOUND_DOSE_PAYLOAD_PARAM_ID as control_id is supported. The audio + * feature payload for sound_dose is copied to the recipient. + */ +__cold static int +_sound_dose_get_config(struct processing_module *mod, uint32_t param_id, + uint32_t control_id, uint32_t *size_out, + uint8_t *data, size_t data_size) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + size_t payload_size; + + assert_can_be_cold(); + + if (param_id != SOF_IPC4_BYTES_CONTROL_PARAM_ID) { + comp_warn(dev, "Not supported control type: %u", param_id); + return 0; + } + + comp_dbg(dev, "param_id = %u, control_id: %u", param_id, control_id); + + if (control_id != SOF_SOUND_DOSE_PAYLOAD_PARAM_ID) { + comp_warn(dev, "Ignored get config control_id: %u", control_id); + memset(data, 0, data_size); + *size_out = 0; + return 0; + } + + payload_size = cd->abi->size; + memcpy_s(data, data_size, cd->abi->data, payload_size); + *size_out = payload_size; + + return 0; +} + +/* This is the main get_config() handler. As in set_config() case, the no-header + * way is legacy. The response get_config() after notify must use the + * sof_ipc4_control_msg_payload header. + */ +__cold int sound_dose_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + int ret; + + assert_can_be_cold(); + + if (!fragment_size) { + comp_warn(mod->dev, "Zero fragment size for param_id %d", param_id); + return 0; + } + + if (param_id == SOF_IPC4_BYTES_CONTROL_PARAM_ID) { + struct sof_ipc4_control_msg_payload *msg_payload; + + /* Note: msg_payload will get overwrite as fragment. */ + msg_payload = (struct sof_ipc4_control_msg_payload *)fragment; + ret = _sound_dose_get_config(mod, param_id, msg_payload->id, + data_offset_size, fragment, + fragment_size); + } else { + ret = _sound_dose_get_config(mod, SOF_IPC4_BYTES_CONTROL_PARAM_ID, + param_id, data_offset_size, + fragment, fragment_size); + } + + return ret; +} diff --git a/src/audio/sound_dose/sound_dose.c b/src/audio/sound_dose/sound_dose.c new file mode 100644 index 000000000000..c28b55baee4d --- /dev/null +++ b/src/audio/sound_dose/sound_dose.c @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/format.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <sof/ipc/msg.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/iir_df1.h> +#include <kernel/abi.h> +#include <kernel/header.h> +#include <rtos/init.h> +#include <user/eq.h> +#include <user/sound_dose.h> +#include "sound_dose.h" +#include "sound_dose_iir_44k.h" +#include "sound_dose_iir_48k.h" + +/* UUID identifies the components. Use e.g. command uuidgen from package + * uuid-runtime, add it to uuid-registry.txt in SOF top level. + */ +SOF_DEFINE_REG_UUID(sound_dose); + +/* Creates logging data for the component */ +LOG_MODULE_REGISTER(sound_dose, CONFIG_SOF_LOG_LEVEL); + +void sound_dose_report_mel(const struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + uint64_t tmp_h, tmp_l; + + cd->dose->current_sens_dbfs_dbspl = cd->setup.sens_dbfs_dbspl; + cd->dose->current_volume_offset = cd->vol.volume_offset; + cd->dose->current_gain = cd->att.gain; + cd->dose->dbfs_value = (int32_t)(((int64_t)cd->level_dbfs * 100) >> 16); + cd->dose->mel_value = cd->dose->dbfs_value + + cd->setup.sens_dbfs_dbspl + + cd->vol.volume_offset; + /* Multiply in two 32x32 -> 64 bits parts and do sum of the parts + * including the shift from Q26 to Q0. The simplified 96 bits + * equation would be time = ((tmp_h << 32) + tmp_l) >> 26. + */ + tmp_l = (cd->total_frames_count & 0xffffffff) * cd->rate_to_us_coef; + tmp_h = (cd->total_frames_count >> 32) * cd->rate_to_us_coef; + cd->feature->stream_time_us = (tmp_l >> 26) + ((tmp_h & ((1LL << 32) - 1)) << 6); +#if SOUND_DOSE_DEBUG + comp_info(mod->dev, "Time %d dBFS %d MEL %d", + (int32_t)(cd->feature->stream_time_us / 1000000), + cd->dose->dbfs_value, cd->dose->mel_value); +#endif + + sound_dose_send_ipc_notification(mod); +} + +int sound_dose_filters_init(struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct sof_eq_iir_config *iir_config; + struct sof_eq_iir_header *iir_coef; + struct comp_dev *dev = mod->dev; + struct sof_abi_hdr *blob; + size_t iir_size, alloc_size; + int32_t *data; + int i; + + /* Initialize FIR */ + switch (cd->rate) { + case 48000: + blob = (struct sof_abi_hdr *)sound_dose_iir_48k; + iir_config = (struct sof_eq_iir_config *)blob->data; + cd->log_offset_for_mean = SOUND_DOSE_LOG2_INV_48K_Q16; + cd->rate_to_us_coef = SOUND_DOSE_1M_OVER_48K_Q26; + break; + case 44100: + blob = (struct sof_abi_hdr *)sound_dose_iir_44k; + iir_config = (struct sof_eq_iir_config *)blob->data; + cd->log_offset_for_mean = SOUND_DOSE_LOG2_INV_44K_Q16; + cd->rate_to_us_coef = SOUND_DOSE_1M_OVER_44K_Q26; + break; + default: + /* TODO: 96 kHz and 192 kHz with integer decimation factor. The A-weight is not + * defined above 20 kHz, so high frequency energy is not needed. Also it will + * help keep the module load reasonable. + */ + comp_err(dev, "error: unsupported sample rate %d", cd->rate); + return -EINVAL; + } + + /* Apply the first responses in the blobs */ + iir_coef = (struct sof_eq_iir_header *)&iir_config->data[iir_config->channels_in_config]; + iir_size = iir_delay_size_df1(iir_coef); + alloc_size = cd->channels * iir_size; + cd->delay_lines = rzalloc(SOF_MEM_FLAG_USER, alloc_size); + if (!cd->delay_lines) { + comp_err(dev, "Failed to allocate memory for weighting filters."); + return -ENOMEM; + } + + data = cd->delay_lines; + for (i = 0; i < cd->channels; i++) { + iir_init_coef_df1(&cd->iir[i], iir_coef); + iir_init_delay_df1(&cd->iir[i], &data); + cd->energy[i] = 0; + } + + cd->report_count = cd->rate; /* report every 1s, for 48k frames */ + return 0; +} + +void sound_dose_filters_free(struct sound_dose_comp_data *cd) +{ + rfree(cd->delay_lines); +} + +__cold static void sound_dose_setup_init(struct sound_dose_comp_data *cd) +{ + cd->setup.sens_dbfs_dbspl = 0; /* 0 dbFS is 100 dB */ + cd->vol.volume_offset = 0; /* Assume max vol */ + cd->att.gain = 0; /* No attenuation, 0 dB */ + cd->gain = SOUND_DOSE_GAIN_ONE_Q30; + cd->new_gain = SOUND_DOSE_GAIN_ONE_Q30; +} + +static int sound_dose_audio_feature_init(struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + size_t alloc_size = sizeof(struct sof_abi_hdr) + + sizeof(struct sof_audio_feature) + + sizeof(struct sof_sound_dose); + + cd->abi = rzalloc(SOF_MEM_FLAG_USER, alloc_size); + if (!cd->abi) { + comp_err(mod->dev, "Failed to allocate audio feature data."); + return -ENOMEM; + } + + cd->abi->magic = SOF_IPC4_ABI_MAGIC; + cd->abi->abi = SOF_ABI_VERSION; + cd->abi->size = sizeof(struct sof_audio_feature) + sizeof(struct sof_sound_dose); + cd->feature = (struct sof_audio_feature *)cd->abi->data; + cd->feature->data_size = sizeof(struct sof_sound_dose); + cd->feature->type = SOF_AUDIO_FEATURE_SOUND_DOSE_MEL; + cd->feature->num_audio_features = 1; /* Single MEL value in audio feature data */ + cd->dose = (struct sof_sound_dose *)cd->feature->data; + return 0; +} + +/** + * sound_dose_init() - Initialize the component. + * @mod: Pointer to module data. + * + * This function is called when the instance is created. The + * macro __cold informs that the code that is non-critical + * is loaded to slower but large DRAM. + * + * Return: Zero if success, otherwise error code. + */ +__cold static int sound_dose_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct sound_dose_comp_data *cd; + int ret; + + comp_info(dev, "Initialize"); + + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) { + comp_err(dev, "Failed to allocate component data."); + return -ENOMEM; + } + + md->private = cd; + + sound_dose_setup_init(cd); + ret = sound_dose_audio_feature_init(mod); + if (ret) { + rfree(cd); + return ret; + } + + ret = sound_dose_ipc_notification_init(mod); + if (ret) { + rfree(cd->abi); + rfree(cd); + } + + return ret; +} + +/** + * sound_dose_process() - The audio data processing function. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * This is the processing function that is called for scheduled + * pipelines. The processing is controlled by the enable switch. + * + * Return: Zero if success, otherwise error code. + */ +static int sound_dose_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct sof_source *source = sources[0]; /* One input in this example */ + struct sof_sink *sink = sinks[0]; /* One output in this example */ + struct comp_dev *dev = mod->dev; + int32_t arg; + int frames = source_get_data_frames_available(source); + int sink_frames = sink_get_free_frames(sink); + + comp_dbg(dev, "entry"); + + if (cd->gain_update) { + /* Convert dB * 100 to Q8.24 */ + arg = (int32_t)cd->att.gain * SOUND_DOSE_ONE_OVER_100_Q24; + + /* Calculate linear value as Q12.20 and convert to Q2.30 */ + cd->new_gain = Q_SHIFT_LEFT(sofm_db2lin_fixed(arg), 20, 30); + cd->gain_update = false; + } + + if (cd->new_gain < cd->gain) { + cd->gain = Q_MULTSR_32X32((int64_t)cd->gain, SOUND_DOSE_GAIN_DOWN_Q30, 30, 30, 30); + cd->gain = MAX(cd->gain, cd->new_gain); + } else if (cd->new_gain > cd->gain) { + cd->gain = Q_MULTSR_32X32((int64_t)cd->gain, SOUND_DOSE_GAIN_UP_Q30, 30, 30, 30); + cd->gain = MIN(cd->gain, SOUND_DOSE_GAIN_ONE_Q30); + } + + frames = MIN(frames, sink_frames); + cd->total_frames_count += frames; + return cd->sound_dose_func(mod, source, sink, frames); +} + +/** + * sound_dose_prepare() - Prepare the component for processing. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * Function prepare is called just before the pipeline is started. In + * this case the audio format parameters are for better code performance + * saved to component data to avoid to find out them in process. The + * processing function pointer is set to process the current audio format. + * + * Return: Value zero if success, otherwise error code. + */ +static int sound_dose_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame source_format; + + comp_dbg(dev, "entry"); + + /* The processing example in this component supports one input and one + * output. Generally there can be more. + */ + if (num_of_sources != 1 || num_of_sinks != 1) + return -EINVAL; + + /* get source data format */ + cd->frame_bytes = source_get_frame_bytes(sources[0]); + cd->channels = source_get_channels(sources[0]); + source_format = source_get_frm_fmt(sources[0]); + cd->rate = source_get_rate(sources[0]); + + cd->sound_dose_func = sound_dose_find_proc_func(source_format); + if (!cd->sound_dose_func) { + comp_err(dev, "No processing function found for format %d.", + source_format); + return -EINVAL; + } + + return sound_dose_filters_init(mod); +} + +/** + * sound_dose_reset() - Reset the component. + * @mod: Pointer to module data. + * + * The component reset is called when pipeline is stopped. The reset + * should return the component to same state as init. + * + * Return: Value zero, always success. + */ +static int sound_dose_reset(struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + sound_dose_setup_init(cd); + return 0; +} + +/** + * sound_dose_free() - Free dynamic allocations. + * @mod: Pointer to module data. + * + * Component free is called when the pipelines are deleted. All + * dynamic allocations need to be freed here. The macro __cold + * instructs the build to locate this performance wise non-critical + * function to large and slower DRAM. + * + * Return: Value zero, always success. + */ +__cold static int sound_dose_free(struct processing_module *mod) +{ + struct sound_dose_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + comp_dbg(mod->dev, "entry"); + + sound_dose_filters_free(cd); + ipc_msg_free(cd->msg); + rfree(cd->abi); + rfree(cd); + return 0; +} + +/* This defines the module operations */ +static const struct module_interface sound_dose_interface = { + .init = sound_dose_init, + .prepare = sound_dose_prepare, + .process = sound_dose_process, + .set_configuration = sound_dose_set_config, + .get_configuration = sound_dose_get_config, + .reset = sound_dose_reset, + .free = sound_dose_free +}; + +/* This controls build of the module. If COMP_MODULE is selected in kconfig + * this is build as dynamically loadable module. + */ +#if CONFIG_COMP_SOUND_DOSE_MODULE + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("SNDDOSE", &sound_dose_interface, 1, + SOF_REG_UUID(sound_dose), 4); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(sound_dose_tr, SOF_UUID(sound_dose_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(sound_dose_interface, sound_dose_uuid, sound_dose_tr); +SOF_MODULE_INIT(sound_dose, sys_comp_module_sound_dose_interface_init); + +#endif diff --git a/src/audio/sound_dose/sound_dose.h b/src/audio/sound_dose/sound_dose.h new file mode 100644 index 000000000000..0366d1dc9b35 --- /dev/null +++ b/src/audio/sound_dose/sound_dose.h @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + */ +#ifndef __SOF_AUDIO_SOUND_DOSE_H__ +#define __SOF_AUDIO_SOUND_DOSE_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/iir_df1.h> +#include <user/sound_dose.h> +#include <stdbool.h> +#include <stdint.h> + +#define SOUND_DOSE_DEBUG 0 + +#define SOUND_DOSE_1M_OVER_44K_Q26 1521742948 /* int32(1000/44.1 * 2^26) */ +#define SOUND_DOSE_1M_OVER_48K_Q26 1398101333 /* int32(1000/48 * 2^26) */ +#define SOUND_DOSE_ONE_OVER_100_Q24 167772 /* int32(0.01*2^24) */ +#define SOUND_DOSE_GAIN_ONE_Q30 1073741824 /* int32(2^30) */ +#define SOUND_DOSE_GAIN_UP_Q30 1079940603 /* int32(10^(+0.05/20)*2^30) */ +#define SOUND_DOSE_GAIN_DOWN_Q30 1067578625 /* int32(10^(-0.05/20)*2^30) */ +#define SOUND_DOSE_LOG2_INV_44K_Q16 -1011122 /* int32(log2(1/44.1e3) * 2^16) */ +#define SOUND_DOSE_LOG2_INV_48K_Q16 -1019134 /* int32(log2(1/48e3) * 2^16) */ +#define SOUND_DOSE_TEN_OVER_LOG2_10_Q29 1616142483 /* int32(10 / log2(10) * 2^29) */ +#define SOUND_DOSE_WEIGHT_FILTERS_OFFS_Q16 196608 /* int32(3 * 2^16) */ +#define SOUND_DOSE_DFBS_OFFS_Q16 197263 /* int32(3.01 * 2^16) */ +#define SOUND_DOSE_MEL_CHANNELS_SUM_FIX -98304 /* int32(-1.5 * 2^16) */ +#define SOUND_DOSE_ENERGY_SHIFT 19 /* Scale shift for 1s energy */ +#define SOUND_DOSE_LOG_FIXED_OFFSET (65536 * (SOUND_DOSE_ENERGY_SHIFT - 30)) + +#define SOUND_DOSE_S16_Q 15 /* Q1.15 samples */ +#define SOUND_DOSE_S32_Q 31 /* Q1.31 samples */ +#define SOUND_DOSE_GAIN_Q 30 /* Q2.30 gain */ +#define SOUND_DOSE_LOGOFFS_Q 16 /* see SOUND_DOSE_LOG2_INV_48K_Q16 */ +#define SOUND_DOSE_LOGMULT_Q 29 /* see SOUND_DOSE_TEN_OVER_LOG2_10_Q29 */ + +/** + * struct sound_dose_func - Function call pointer for process function + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + */ +typedef int (*sound_dose_func)(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames); + +/* Sound Dose component private data */ + +/** + * struct sound_dose_comp_data + * @sound_dose_func: Pointer to used processing function. + * @channels_order[]: Vector with desired sink channels order. + * @source_format: Source samples format. + * @frame_bytes: Number of bytes in an audio frame. + * @channels: Channels count. + * @enable: Control processing on/off, on - reorder channels + */ +struct sound_dose_comp_data { + struct iir_state_df1 iir[PLATFORM_MAX_CHANNELS]; + struct sound_dose_setup_config setup; + struct sound_dose_volume_config vol; + struct sound_dose_gain_config att; + struct sof_abi_hdr *abi; + struct sof_audio_feature *feature; + struct sof_sound_dose *dose; + struct ipc_msg *msg; + sound_dose_func sound_dose_func; + int64_t energy[PLATFORM_MAX_CHANNELS]; + int64_t total_frames_count; + int32_t log_offset_for_mean; + int32_t rate_to_us_coef; + int32_t *delay_lines; + int32_t level_dbfs; + int32_t new_gain; + int32_t gain; + bool gain_update; + int report_count; + int frames_count; + int frame_bytes; + int channels; + int rate; +}; + +/** + * struct sound_dose_proc_fnmap - processing functions for frame formats + * @frame_fmt: Current frame format + * @sound_dose_proc_func: Function pointer for the suitable processing function + */ +struct sound_dose_proc_fnmap { + enum sof_ipc_frame frame_fmt; + sound_dose_func sound_dose_proc_func; +}; + +/** + * sound_dose_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +sound_dose_func sound_dose_find_proc_func(enum sof_ipc_frame src_fmt); + +/** + * sound_dose_set_config() - Handle controls set request + * @mod: Pointer to module data. + * @param_id: Id to know control type, used to know ALSA control type. + * @pos: Position of the fragment in the large message. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * @response_size: Size of response. + * + * This function handles the real-time controls. The ALSA controls have the + * param_id set to indicate the control type. The control ID, from topology, + * is used to separate the controls instances of same type. In control payload + * the num_elems defines to how many channels the control is applied to. + * + * Return: Zero if success, otherwise error code. + */ +int sound_dose_set_config(struct processing_module *mod, + uint32_t param_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); + +/** + * sound_dose_get_config() - Handle controls get request + * @mod: Pointer to module data. + * @config_id: Configuration ID. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * + * This function is used for controls get. + * + * Return: Zero if success, otherwise error code. + */ +int sound_dose_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); + +void sound_dose_filters_free(struct sound_dose_comp_data *cd); +int sound_dose_filters_init(struct processing_module *mod); +void sound_dose_report_mel(const struct processing_module *mod); +int sound_dose_ipc_notification_init(struct processing_module *mod); +void sound_dose_send_ipc_notification(const struct processing_module *mod); + +#endif /* __SOF_AUDIO_SOUND_DOSE_H__ */ diff --git a/src/audio/sound_dose/sound_dose.toml b/src/audio/sound_dose/sound_dose.toml new file mode 100644 index 000000000000..95f58ae27e05 --- /dev/null +++ b/src/audio/sound_dose/sound_dose.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Sound Dose component module config + [[module.entry]] + name = "SNDDOSE" + uuid = UUIDREG_STR_SOUND_DOSE + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/sound_dose/sound_dose_iir_44k.h b/src/audio/sound_dose/sound_dose_iir_44k.h new file mode 100644 index 000000000000..d6fbf665f4eb --- /dev/null +++ b/src/audio/sound_dose/sound_dose_iir_44k.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 2025-08-15 with command: + * cd src/audio/sound_dose/tune + * octave --quiet --no-window-system sof_sound_dose_time_domain_filters.m + */ + +#include <stdint.h> + +static const uint32_t sound_dose_iir_44k[51] = { + 0x34464f53, 0x00000000, 0x000000ac, 0x0301d001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x000000ac, 0x00000002, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000004, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xc04a8747, + 0x7fb56455, 0x2000c3eb, 0xbffe782a, 0x2000c3eb, + 0x00000000, 0x00004000, 0xc5d5ada3, 0x7a174530, + 0x1e9ac221, 0xc2ca7bbd, 0x1e9ac221, 0x00000000, + 0x00004000, 0xc382c10f, 0x7c63e3c7, 0x1e4cf2c0, + 0xc1d9d144, 0x1fe2eeaa, 0x00000000, 0x00004000, + 0xfe0cb792, 0xe92a46fc, 0x02d2f1b4, 0x10d57d25, + 0x18d70df1, 0xfffffffd, 0x000067d8 +}; diff --git a/src/audio/sound_dose/sound_dose_iir_48k.h b/src/audio/sound_dose/sound_dose_iir_48k.h new file mode 100644 index 000000000000..6dca9af5e4b8 --- /dev/null +++ b/src/audio/sound_dose/sound_dose_iir_48k.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 2025-08-15 with command: + * cd src/audio/sound_dose/tune + * octave --quiet --no-window-system sof_sound_dose_time_domain_filters.m + */ + +#include <stdint.h> + +static const uint32_t sound_dose_iir_48k[51] = { + 0x34464f53, 0x00000000, 0x000000ac, 0x0301d001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x000000ac, 0x00000002, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000004, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xc0447c54, + 0x7fbb7275, 0x200247f9, 0xbffb700e, 0x200247f9, + 0x00000000, 0x00004000, 0xc56175ce, 0x7a8e6600, + 0x1eb83f18, 0xc28f81d0, 0x1eb83f18, 0x00000000, + 0x00004000, 0xc33b9ba4, 0x7caef0cf, 0x1e6ee6bd, + 0xc1b48ddf, 0x1fe4bfc4, 0x00000000, 0x00004000, + 0xff729f84, 0xf3612432, 0x01acb380, 0x0cd1120d, + 0x182fcd24, 0xfffffffd, 0x000067e0 +}; diff --git a/src/audio/sound_dose/tune/sof_sound_dose_blobs.m b/src/audio/sound_dose/tune/sof_sound_dose_blobs.m new file mode 100644 index 000000000000..7670303c2770 --- /dev/null +++ b/src/audio/sound_dose/tune/sof_sound_dose_blobs.m @@ -0,0 +1,95 @@ +% Export configuration blobs for Sound Dose + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2025, Intel Corporation. + +function sof_sound_dose_blobs() + + % Common definitions + sof_tools = '../../../../tools'; + sof_tplg = fullfile(sof_tools, 'topology'); + fn.tpath = fullfile(sof_tplg, 'topology2/include/components/sound_dose'); + str_comp = "sound_dose_config"; + str_comment = "Exported with script sof_sound_dose_blobs.m"; + str_howto = "cd src/audio/sound_dose/tune; octave sof_sound_dose_blobs.m"; + bytes_control_param_id = 202; + + % Set the parameters here + sof_tools = '../../../../tools'; + sof_tplg = fullfile(sof_tools, 'topology'); + sof_tplg_sound_dose = fullfile(sof_tplg, 'topology2/include/components/sound_dose'); + sof_ctl_sound_dose = fullfile(sof_tools, 'ctl/ipc4/sound_dose'); + + sof_sound_dose_paths(true); + + blob8 = sof_sound_dose_build_blob([10000 0], 0); + tplg2_fn = sprintf("%s/setup_sens_100db.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + sof_alsactl_write([sof_ctl_sound_dose "/setup_sens_100db.txt"], blob8); + + blob8 = sof_sound_dose_build_blob([0 0], 0); + tplg2_fn = sprintf("%s/setup_sens_0db.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + sof_alsactl_write([sof_ctl_sound_dose "/setup_sens_0db.txt"], blob8); + + blob8 = sof_sound_dose_build_blob([0 0], 1); + tplg2_fn = sprintf("%s/setup_vol_0db.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + sof_alsactl_write([sof_ctl_sound_dose "/setup_vol_0db.txt"], blob8); + + blob8 = sof_sound_dose_build_blob([-1000 0], 1); + tplg2_fn = sprintf("%s/setup_vol_-10db.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + sof_alsactl_write([sof_ctl_sound_dose "/setup_vol_-10db.txt"], blob8); + + blob8 = sof_sound_dose_build_blob([-1000 0], 2); + tplg2_fn = sprintf("%s/setup_gain_-10db.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + sof_alsactl_write([sof_ctl_sound_dose "/setup_gain_-10db.txt"], blob8); + + blob8 = sof_sound_dose_build_blob([0 0], 2); + tplg2_fn = sprintf("%s/setup_gain_0db.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + sof_alsactl_write([sof_ctl_sound_dose "/setup_gain_0db.txt"], blob8); + + blob8 = sof_sound_dose_build_blob([], bytes_control_param_id); + tplg2_fn = sprintf("%s/setup_data_init.conf", sof_tplg_sound_dose); + sof_tplg2_write(tplg2_fn, blob8, str_comp, str_comment, str_howto); + + sof_sound_dose_paths(false); +end + +function sof_sound_dose_paths(enable) + + common = '../../../../tools/tune/common'; + if enable + addpath(common); + else + rmpath(common); + end +end + +function blob8 = sof_sound_dose_build_blob(param_values, blob_param_id) + + blob_type = 0; + data_length = length(param_values); + data_size = 2 * data_length; + ipc_ver = 4; + [abi_bytes, abi_size] = sof_get_abi(data_size, ipc_ver, blob_type, blob_param_id); + blob_size = data_size + abi_size; + blob8 = uint8(zeros(1, blob_size)); + blob8(1:abi_size) = abi_bytes; + j = abi_size + 1; + for i = 1:data_length + blob8(j:j+1) = short2byte(int16(param_values(i))); + j=j+2; + end +end + +function bytes = short2byte(word) + sh = [0 -8]; + bytes = uint8(zeros(1,2)); + bytes(1) = bitand(bitshift(word, sh(1)), 255); + bytes(2) = bitand(bitshift(word, sh(2)), 255); +end diff --git a/src/audio/sound_dose/tune/sof_sound_dose_ref.m b/src/audio/sound_dose/tune/sof_sound_dose_ref.m new file mode 100644 index 000000000000..dc15ab9f3567 --- /dev/null +++ b/src/audio/sound_dose/tune/sof_sound_dose_ref.m @@ -0,0 +1,69 @@ +% Compute MEL every 1s +tc = 1.0; + +% Load sound clip +sound_clip = "/usr/share/sounds/alsa/Front_Right.wav"; +[x1, fs] = audioread(sound_clip); +if size(x1, 2) == 1 + x1 = repmat(x1, 1, 2); +end +sx = size(x1); +num_frames = sx(1); +num_channels = sx(2); + +% load A-weight filters +load sof_sound_dose_time_domain_filters.mat + +% Filter with IIR, FIR +x2 = filter(b_iir, a_iir, x1); +x3 = filter(b_fir, 1, x2); + +%figure +%plot(x1) + +%figure +%plot(x3) + +% compute RMS level in 1s chunks +np = 1; +nc = tc * fs; +num_chunks = floor(num_frames/nc); +l_dbfs_all = zeros(num_chunks, num_channels); +mel_all = zeros(num_chunks, 1); + +dbfs_offs = 3.01; +dbfs_offs_weight_filters = 3; +i1 = 1; +for n = 1:num_chunks + sum = 0; + i2 = i1 + nc - 1; + for ch = 1:num_channels + y = x3(i1:i2, ch); + sum = sum + mean(y.^2); + l_dbfs = 20*log10(sqrt(mean(y.^2))) + dbfs_offs + dbfs_offs_weight_filters; + l_dbfs_all(np, ch) = l_dbfs; + end + mel = 10*log10(sum) + dbfs_offs_weight_filters; + if num_channels > 1 + mel = mel - 1.5 * num_channels; + end + mel_all(np) = mel; + i1 = i1 + nc; + np = np + 1; +end + +figure(1) +plot(l_dbfs_all) +grid on +xlabel('Time (s)'); +ylabel('Level (dBSFS)'); + +figure(2) +plot(mel_all) +grid on +xlabel('Time (s)'); +ylabel('MEL (dB)'); + +mel_all + +mel_all_rnd = round(mel_all) diff --git a/src/audio/sound_dose/tune/sof_sound_dose_time_domain_filters.m b/src/audio/sound_dose/tune/sof_sound_dose_time_domain_filters.m new file mode 100644 index 000000000000..26e2b2e00fa5 --- /dev/null +++ b/src/audio/sound_dose/tune/sof_sound_dose_time_domain_filters.m @@ -0,0 +1,163 @@ +% Export time domain IIR and FIR filter to apply A-weight for sound dose. +% +% Usage: +% sof_sound_dose_time_domain_filters() + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2025, Intel Corporation. + +function sof_sound_dose_time_domain_filters(fs) + + if exist('OCTAVE_VERSION', 'builtin') + pkg load signal; + end + + sof_sound_dose_time_domain_filters_for_rate(48e3); + sof_sound_dose_time_domain_filters_for_rate(44.1e3); + +end + +function sof_sound_dose_time_domain_filters_for_rate(fs) + + sof_sound_dose = '../../sound_dose'; + sof_ctl = '../../../../tools/ctl'; + sound_dose_paths(true); + + + fs_str = sprintf('%dk', round(fs/1000)); + fir_str = sprintf('sound_dose_fir_%s', fs_str); + iir_str = sprintf('sound_dose_iir_%s', fs_str); + prm.fir_coef_fn = fullfile(sof_sound_dose, [fir_str '.h']); + prm.iir_coef_fn = fullfile(sof_sound_dose, [iir_str '.h']); + prm.fir_blob_fn = fullfile(sof_ctl, ['ipc4/eq_fir/' fir_str '.txt']); + prm.iir_blob_fn = fullfile(sof_ctl, ['ipc4/eq_iir/' iir_str '.txt']); + prm.fir_blob_vn = fir_str; + prm.iir_blob_vn = iir_str; + prm.ipc_ver = 4; + eq = sound_dose_filters(fs); + export_filters(eq, prm); + + sound_dose_paths(false); +end + +function export_filters(eq, prm) + + b_fir = 1; + b_iir = 1; + a_iir = 1; + howto = 'cd src/audio/sound_dose/tune; octave --quiet --no-window-system sof_sound_dose_time_domain_filters.m'; + + % Export FIR + if eq.enable_fir + bq = sof_eq_fir_blob_quant(eq.b_fir); + channels_in_config = 2; % Setup max 2 channels EQ + assign_response = [0 0]; % Same response for L and R + num_responses = 1; % One response + bm = sof_eq_fir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq); + bp = sof_eq_fir_blob_pack(bm, prm.ipc_ver); + sof_export_c_eq_uint32t(prm.fir_coef_fn, bp, prm.fir_blob_vn, 0, howto); + sof_alsactl_write(prm.fir_blob_fn, bp); + b_fir = eq.b_fir; + end + + % Export IIR + if eq.enable_iir + coefq = sof_eq_iir_blob_quant(eq.p_z, eq.p_p, eq.p_k); + channels_in_config = 2; % Setup max 2 channels EQ + assign_response = [0 0]; % Same response for L and R + num_responses = 1; % One response + coefm = sof_eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + coefq); + coefp = sof_eq_iir_blob_pack(coefm, prm.ipc_ver); + sof_export_c_eq_uint32t(prm.iir_coef_fn, coefp, prm.iir_blob_vn, 0, howto); + sof_alsactl_write(prm.iir_blob_fn, coefp); + [b_iir, a_iir] = zp2tf( eq.p_z, eq.p_p, eq.p_k); + end + + % Export mat file + save sof_sound_dose_time_domain_filters.mat b_fir b_iir a_iir; + +end + +function eq = sound_dose_filters(fs) + + np = 200; + f_hi = 0.95 * fs/2; + fv = logspace(log10(10), log10(f_hi), np); + ref_a_weight = func_a_weight_db(fv); + + eq = sof_eq_defaults(); + eq.fs = fs; + eq.enable_fir = 0; + eq.enable_iir = 1; + eq.iir_norm_type = '1k'; % At 1 kHz -3 dB + eq.iir_norm_offs_db = -3; + eq.fir_norm_type = '1k'; % At 1 kHz 0 dB, total -3 dB gain to avoid clip + eq.fir_norm_offs_db = 0; + eq.p_fmin = 10; + eq.p_fmax = 30e3; + + eq.fir_minph = 1; + eq.fir_beta = 4; + eq.fir_length = 31; + eq.fir_autoband = 0; + eq.fmin_fir = 300; + eq.fmax_fir = f_hi; + + eq.raw_f = fv; + eq.raw_m_db = zeros(1, length(fv)); + eq.target_f = fv; + eq.target_m_db = ref_a_weight; + + eq.peq = [ ... + eq.PEQ_HP1 12 0 0; ... + eq.PEQ_HP1 20 0 0; ... + eq.PEQ_HP2 280 0 0; ... + eq.PEQ_PN2 245 -5.45 0.5; ... + eq.PEQ_HS1 13000 -3 0; ... + eq.PEQ_HS1 14000 -3 0; ... + ]; + + eq = sof_eq_compute(eq); + sof_eq_plot(eq, 1); + figure(3); + axis([10 20e3 -60 10]); + + +end + +% See https://en.wikipedia.org/wiki/A-weighting +% IEC 61672-1:2013 Electroacoustics - Sound level meters, +% Part 1: Specifications. IEC. 2013. + +function a_weight = func_a_weight_db(fv) + a_weight = 20*log10(func_ra(fv)) - 20*log10(func_ra(1000)); +end + +function y = func_ra(f) + f2 = f.^2; + f4 = f.^4; + c1 = 12194^2; + c2 = 20.6^2; + c3 = 107.7^2; + c4 = 737.9^2; + c5 = 12194^2; + y = c1 * f4 ./ ((f2 + c2).*sqrt((f2 + c3).*(f2 + c4).*(f2 + c5))); +end + +function sound_dose_paths(enable) + switch enable + case true + addpath('../../eq_iir/tune'); + addpath('../../../../tools/tune/common'); + case false + rmpath('../../eq_iir/tune'); + rmpath('../../../../tools/tune/common'); + end +end diff --git a/src/audio/source_api_helper.c b/src/audio/source_api_helper.c new file mode 100644 index 000000000000..a6dc56249ee3 --- /dev/null +++ b/src/audio/source_api_helper.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include <rtos/symbol.h> + +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/audio_stream.h> + +/* This file contains private source API functions intended for use only by the sof. */ + +void source_init(struct sof_source *source, const struct source_ops *ops, + struct sof_audio_stream_params *audio_stream_params) +{ + source->ops = ops; + source->requested_read_frag_size = 0; + source->audio_stream_params = audio_stream_params; +} + +size_t source_get_num_of_processed_bytes(struct sof_source *source) +{ + return source->num_of_bytes_processed; +} + +void source_reset_num_of_processed_bytes(struct sof_source *source) +{ + source->num_of_bytes_processed = 0; +} + +bool source_get_underrun(struct sof_source *source) +{ + return source->audio_stream_params->underrun_permitted; +} + +int source_set_frm_fmt(struct sof_source *source, enum sof_ipc_frame frm_fmt) +{ + source->audio_stream_params->frame_fmt = frm_fmt; + if (source->ops->on_audio_format_set) + return source->ops->on_audio_format_set(source); + return 0; +} + +int source_set_valid_fmt(struct sof_source *source, + enum sof_ipc_frame valid_sample_fmt) +{ + source->audio_stream_params->valid_sample_fmt = valid_sample_fmt; + if (source->ops->on_audio_format_set) + return source->ops->on_audio_format_set(source); + return 0; +} + +int source_set_rate(struct sof_source *source, unsigned int rate) +{ + source->audio_stream_params->rate = rate; + if (source->ops->on_audio_format_set) + return source->ops->on_audio_format_set(source); + return 0; +} + +int source_set_channels(struct sof_source *source, unsigned int channels) +{ + source->audio_stream_params->channels = channels; + if (source->ops->on_audio_format_set) + return source->ops->on_audio_format_set(source); + return 0; +} + +int source_set_buffer_fmt(struct sof_source *source, uint32_t buffer_fmt) +{ + source->audio_stream_params->buffer_fmt = buffer_fmt; + if (source->ops->on_audio_format_set) + return source->ops->on_audio_format_set(source); + return 0; +} + +int source_set_underrun(struct sof_source *source, bool underrun_permitted) +{ + source->audio_stream_params->underrun_permitted = underrun_permitted; + if (source->ops->on_audio_format_set) + return source->ops->on_audio_format_set(source); + return 0; +} + +int source_set_params(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update) +{ + if (source->ops->audio_set_ipc_params) + return source->ops->audio_set_ipc_params(source, params, force_update); + return 0; +} + +int source_set_alignment_constants(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req) +{ + if (source->ops->set_alignment_constants) + return source->ops->set_alignment_constants(source, byte_align, frame_align_req); + return 0; +} +EXPORT_SYMBOL(source_set_alignment_constants); + +void source_set_min_available(struct sof_source *source, size_t min_available) +{ + source->min_available = min_available; +} diff --git a/src/audio/src/CMakeLists.txt b/src/audio/src/CMakeLists.txt index 859ac0f8c389..6def00db23ac 100644 --- a/src/audio/src/CMakeLists.txt +++ b/src/audio/src/CMakeLists.txt @@ -1,3 +1,31 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof src_generic.c src_hifi2ep.c src_hifi3.c src.c) +set(base_files src_generic.c src_hifi2ep.c src_hifi3.c src_hifi4.c src_hifi5.c src_common.c src.c) + +if(CONFIG_IPC_MAJOR_3) + list(APPEND base_files src_ipc3.c) +elseif(CONFIG_IPC_MAJOR_4) + list(APPEND base_files src_ipc4.c) +endif() + +sof_list_append_ifdef(CONFIG_COMP_SRC_LITE base_files src_lite.c) + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + if(CONFIG_COMP_SRC STREQUAL "m" AND DEFINED CONFIG_LLEXT) + + add_subdirectory(llext ${PROJECT_BINARY_DIR}/src_llext) + add_dependencies(app src) + + else() + + zephyr_library_sources(${base_files}) + + endif() + +else() ### library, e.g. testbench or plugin ### + + add_local_sources(sof ${base_files}) + +endif() diff --git a/src/audio/src/Kconfig b/src/audio/src/Kconfig new file mode 100644 index 000000000000..0b08e6358a98 --- /dev/null +++ b/src/audio/src/Kconfig @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_SRC + tristate "SRC component" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for SRC component + +if COMP_SRC + +config COMP_SRC_LITE + bool "SRC_LITE component" + default y + help + Select for SRC_LITE component + which only supports a subset of conversions + supported by the SRC module: + 48 -> 16kHz + 44.1 -> 16 kHz + 32 -> 16 kHz + 44.1 -> 48 + +choice + prompt "SRC coefficient set" + default COMP_SRC_STD + +config COMP_SRC_STD + bool "Full conversions support and high quality" + help + This coefficients set supports a large number of conversions + with 8 - 192 kHz input and 8 - 48 kHz output. The coefficients + are 32 bits for high conversion quality. The coefficients + storage consume 79 kB. The runtime needs 8 kB. Use this if there + is critical quality usage for SRC like music via headphones and + need high sample rates. + +config COMP_SRC_SMALL + bool "Smaller conversions support and high quality" + help + This coefficients set supports a small number of conversions + with 8 - 48 kHz input and output. The coefficients are 32 bits + for high conversion quality. The coefficients storage consumes + 30 kB RAM. Runtime needs 4 kB. Use this if there is critical + quality usage for SRC like music via headphones. + +config COMP_SRC_TINY + bool "Reduced conversions support and reduced quality" + help + This coefficients set supports a minimum number of conversions + with 8 - 48 kHz input and output. The coefficients are 16 bits + that restricts the possible stop-attenuation and could cause + some audible aliasing. The bandwidth of the filters is restricted + so the full 20 kHz band is not met even if sample rate would + allow. The coefficients storage consumes 5 kB RAM. The runtime + needs 6 kB. Use this to save RAM for other applications when SRC + has no critical usage or when only need with lower quality + endpoint like miniature speakers. + +config COMP_SRC_IPC4_FULL_MATRIX + bool "Full IPC4 conversions matrix support and high quality" + help + This coefficients set supports a large number of conversions + with 8 - 192 kHz input 8 - 192 kHz output. The 32 bits coefficients + storate consumes 241 kB. The runtime needs 9 kB. Use this to + make the full conversions set available for IPC4 build. + +endchoice + +endif # SRC diff --git a/src/audio/src/README.md b/src/audio/src/README.md new file mode 100644 index 000000000000..0cb434a67b81 --- /dev/null +++ b/src/audio/src/README.md @@ -0,0 +1,23 @@ +# Synchronous Sample Rate Converter (SRC) Architecture + +This directory contains the Synchronous SRC implementation. + +## Overview + +Converts sample rates by an exact, locked integer or fractional ratio (e.g., 48 kHz to 44.1 kHz) using a polyphase filter bank. + +## Architecture Diagram + +```mermaid +graph LR + In[48kHz Stream] --> SRC[Polyphase FIR Interpolator] + SRC --> Out[44.1kHz Stream] +``` + +## Configuration and Scripts + +- **Kconfig**: Extensive options for `COMP_SRC`, determining conversion quality targets and memory consumption limitations: standard (`COMP_SRC_STD`), small (`COMP_SRC_SMALL`), and tiny (`COMP_SRC_TINY`) filter sets. Alternatively targets IPC4 full conversions (`COMP_SRC_IPC4_FULL_MATRIX`), and supports lite conversions (`COMP_SRC_LITE`). +- **CMakeLists.txt**: Wraps numerous internal source implementations spanning multiple SIMD platforms (`src_hifi2ep.c`, `src_hifi3.c`, `src_hifi4.c`, `src_hifi5.c`) and connects the required IPC APIs. Allows Zephyr out-of-tree loader configurations (`llext`). +- **src.toml**: Declares massive topology limits under `mod_cfg` per chipset to enforce correct processing behavior of varied rate conversions internally, specifying `UUIDREG_STR_SRC4` and `UUIDREG_STR_SRC_LITE`. +- **Topology (.conf)**: Instantiated via `tools/topology/topology2/include/components/src.conf`, utilizing `rate_in` and `rate_out` attributes to specify integer transformations. Associates as a `src` widget type with UUID `8d:b2:1b:e6:9a:14:1f:4c:b7:09:46:82:3e:f5:f5:ae`. +- **MATLAB Tuning (`tune/`)**: Houses heavily comprehensive scripts like `sof_src_generate.m` which compute optimal polyphase filter bank coefficients for a massive grid of supported input-to-output fractional sample rate conversions. The scripts export these fixed-point (or float) arrays as C header data structs (`.h` code outputs) allowing the DSP to pull static transition parameters depending on memory (`std`, `small`, `tiny`, `lite`) profiles. diff --git a/src/audio/src/coef/src_ipc4_int32_10_21_2500_5000.h b/src/audio/src/coef/src_ipc4_int32_10_21_2500_5000.h new file mode 100644 index 000000000000..074af07daf32 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_10_21_2500_5000.h @@ -0,0 +1,498 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_10_21_2500_5000_fir[480] = { + 176197, + 283398, + -489527, + -1821639, + -1156496, + 3142738, + 6762013, + 1697341, + -11560205, + -16941391, + 1452480, + 31488694, + 32966571, + -15694696, + -71033604, + -52666902, + 55453402, + 144352064, + 70253645, + -157675395, + -301516818, + -73509483, + 558369423, + 1252507466, + 1533177266, + 1194724679, + 484381332, + -117062054, + -300184352, + -133364194, + 86661924, + 141013127, + 42870699, + -59257156, + -67617496, + -9267377, + 35151480, + 29042793, + -1411917, + -17351349, + -10232073, + 2708516, + 6677010, + 2616196, + -1394049, + -1724907, + -362839, + 300058, + 201940, + 256988, + -624247, + -1898029, + -876780, + 3667032, + 6752740, + 588268, + -12811499, + -16267141, + 4463078, + 33634398, + 30216866, + -22229882, + -73655303, + -45055879, + 67886944, + 145921379, + 52084480, + -181205046, + -298896261, + -25562800, + 633113160, + 1305904039, + 1526559602, + 1133006335, + 411650473, + -156072904, + -295144684, + -108606649, + 101188812, + 136027215, + 30306194, + -64787578, + -63487727, + -3027016, + 36770437, + 26344701, + -4099492, + -17506633, + -8850165, + 3614040, + 6505689, + 2095382, + -1589404, + -1611382, + -245576, + 307873, + 226954, + 220037, + -765292, + -1950559, + -555670, + 4180499, + 6642143, + -608914, + -13962587, + -15322302, + 7585430, + 35433635, + 26911510, + -28788517, + -75408915, + -36478723, + 79998275, + 145615764, + 32302983, + -203610153, + -292106013, + 26585818, + 708094115, + 1354495128, + 1513377630, + 1067830104, + 340657180, + -190439356, + -286669418, + -83726882, + 113742085, + 129532074, + 17919682, + -69234520, + -58730748, + 2953442, + 37829921, + 23443418, + -6583677, + -17419867, + -7436922, + 4408187, + 6256742, + 1587589, + -1743204, + -1484578, + -138819, + 307834, + 250353, + 171898, + -910641, + -1975809, + -194714, + 4674057, + 6424263, + -1882405, + -14990136, + -14104180, + 10781566, + 36842628, + 23067905, + -35281777, + -76229168, + -27005602, + 91610677, + 143349348, + 11085194, + -224543429, + -280961710, + 82700465, + 782781645, + 1397896950, + 1493737530, + 999696049, + 271856409, + -220103564, + -275052373, + -59034845, + 124257691, + 121678225, + 5861682, + -72589391, + -53437323, + 8607891, + 38343593, + 20388213, + -8842121, + -17106335, + -6013876, + 5087211, + 5939409, + 1099359, + -1856709, + -1347920, + -43345, + 300987, + 271177, + 112098, + -1057974, + -1970531, + 203723, + 5138235, + 6094402, + -3218443, + -15871205, + -12613935, + 14010354, + 37820850, + 18711860, + -41617468, + -76060474, + -16721964, + 102545927, + 139057646, + -11366276, + -243656940, + -265314169, + 142502819, + 856637711, + 1435764962, + 1467797255, + 929121819, + 205673922, + -245051946, + -260605873, + -34823501, + 132699315, + 112626562, + -5728073, + -74858124, + -47701145, + 13877640, + 38331774, + 17227934, + -10856778, + -16583615, + -4601394, + 5649285, + 5563302, + 636433, + -1931725, + -1204689, + 40364, + 288409, + 288409, + 40364, + -1204689, + -1931725, + 636433, + 5563302, + 5649285, + -4601394, + -16583615, + -10856778, + 17227934, + 38331774, + 13877640, + -47701145, + -74858124, + -5728073, + 112626562, + 132699315, + -34823501, + -260605873, + -245051946, + 205673922, + 929121819, + 1467797255, + 1435764962, + 856637711, + 142502819, + -265314169, + -243656940, + -11366276, + 139057646, + 102545927, + -16721964, + -76060474, + -41617468, + 18711860, + 37820850, + 14010354, + -12613935, + -15871205, + -3218443, + 6094402, + 5138235, + 203723, + -1970531, + -1057974, + 112098, + 271177, + 300987, + -43345, + -1347920, + -1856709, + 1099359, + 5939409, + 5087211, + -6013876, + -17106335, + -8842121, + 20388213, + 38343593, + 8607891, + -53437323, + -72589391, + 5861682, + 121678225, + 124257691, + -59034845, + -275052373, + -220103564, + 271856409, + 999696049, + 1493737530, + 1397896950, + 782781645, + 82700465, + -280961710, + -224543429, + 11085194, + 143349348, + 91610677, + -27005602, + -76229168, + -35281777, + 23067905, + 36842628, + 10781566, + -14104180, + -14990136, + -1882405, + 6424263, + 4674057, + -194714, + -1975809, + -910641, + 171898, + 250353, + 307834, + -138819, + -1484578, + -1743204, + 1587589, + 6256742, + 4408187, + -7436922, + -17419867, + -6583677, + 23443418, + 37829921, + 2953442, + -58730748, + -69234520, + 17919682, + 129532074, + 113742085, + -83726882, + -286669418, + -190439356, + 340657180, + 1067830104, + 1513377630, + 1354495128, + 708094115, + 26585818, + -292106013, + -203610153, + 32302983, + 145615764, + 79998275, + -36478723, + -75408915, + -28788517, + 26911510, + 35433635, + 7585430, + -15322302, + -13962587, + -608914, + 6642143, + 4180499, + -555670, + -1950559, + -765292, + 220037, + 226954, + 307873, + -245576, + -1611382, + -1589404, + 2095382, + 6505689, + 3614040, + -8850165, + -17506633, + -4099492, + 26344701, + 36770437, + -3027016, + -63487727, + -64787578, + 30306194, + 136027215, + 101188812, + -108606649, + -295144684, + -156072904, + 411650473, + 1133006335, + 1526559602, + 1305904039, + 633113160, + -25562800, + -298896261, + -181205046, + 52084480, + 145921379, + 67886944, + -45055879, + -73655303, + -22229882, + 30216866, + 33634398, + 4463078, + -16267141, + -12811499, + 588268, + 6752740, + 3667032, + -876780, + -1898029, + -624247, + 256988, + 201940, + 300058, + -362839, + -1724907, + -1394049, + 2616196, + 6677010, + 2708516, + -10232073, + -17351349, + -1411917, + 29042793, + 35151480, + -9267377, + -67617496, + -59257156, + 42870699, + 141013127, + 86661924, + -133364194, + -300184352, + -117062054, + 484381332, + 1194724679, + 1533177266, + 1252507466, + 558369423, + -73509483, + -301516818, + -157675395, + 70253645, + 144352064, + 55453402, + -52666902, + -71033604, + -15694696, + 32966571, + 31488694, + 1452480, + -16941391, + -11560205, + 1697341, + 6762013, + 3142738, + -1156496, + -1821639, + -489527, + 283398, + 176197 + +}; + +static const struct src_stage src_int32_10_21_2500_5000 = { + 2, 1, 10, 48, 480, 21, 10, 0, 1, + src_int32_10_21_2500_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_10_21_3455_5000.h b/src/audio/src/coef/src_ipc4_int32_10_21_3455_5000.h new file mode 100644 index 000000000000..38678a2a6353 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_10_21_3455_5000.h @@ -0,0 +1,658 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_10_21_3455_5000_fir[640] = { + 110400, + 517669, + 162088, + -1205989, + -1437565, + 1280033, + 3832651, + 742762, + -6106089, + -5975118, + 5381366, + 13511288, + 1742753, + -19162764, + -16597205, + 15978007, + 35454582, + 2650868, + -48151071, + -37980243, + 40119482, + 81245894, + 1953532, + -111953995, + -82945345, + 99866670, + 194422772, + -5582211, + -316252292, + -250813167, + 432875309, + 1338277735, + 1728052828, + 1259448419, + 343139976, + -285825482, + -293873810, + 26084360, + 197124426, + 80394484, + -94901281, + -104502780, + 14297807, + 82252332, + 31749802, + -42972684, + -44673234, + 7970195, + 35651564, + 12340365, + -18524735, + -17611426, + 3789717, + 13458510, + 4029198, + -6565485, + -5539589, + 1346027, + 3765746, + 919505, + -1545826, + -1069965, + 257311, + 491669, + 151401, + 535500, + 54120, + -1330763, + -1294776, + 1642049, + 3836055, + 92057, + -6597316, + -5252979, + 6705438, + 13337711, + -420079, + -20455080, + -14317470, + 19484675, + 34660630, + -2898800, + -50950071, + -32191215, + 48105669, + 78864546, + -10839958, + -117816781, + -69189701, + 118439203, + 188394330, + -38670532, + -334649851, + -208997645, + 525169888, + 1411574938, + 1718740562, + 1175835107, + 256678778, + -314021572, + -268055637, + 55913519, + 196591133, + 60360060, + -104931677, + -95634111, + 26011175, + 81912107, + 23142941, + -47114310, + -40594907, + 12981189, + 35269086, + 8635368, + -20081810, + -15836342, + 5692018, + 13189816, + 2672484, + -7020493, + -4911043, + 1894218, + 3640128, + 566617, + -1619998, + -926033, + 339051, + 458866, + 195111, + 543862, + -65512, + -1440914, + -1117661, + 1998979, + 3772054, + -597177, + -7000705, + -4405157, + 7977274, + 12930808, + -2666798, + -21456126, + -11710461, + 22796625, + 33261625, + -8594262, + -53000562, + -25674863, + 55563565, + 75101736, + -23887567, + -121940141, + -53793622, + 135776295, + 178995349, + -72724622, + -348552435, + -160470174, + 619265382, + 1478639065, + 1700207749, + 1088224370, + 174155793, + -335464877, + -239358569, + 83534059, + 192959734, + 40097309, + -112944972, + -85535631, + 36927793, + 80274029, + 14444337, + -50366328, + -36001565, + 17613468, + 34333473, + 4925478, + -21256922, + -13875118, + 7424403, + 12718795, + 1333816, + -7338997, + -4234083, + 2381050, + 3461342, + 227015, + -1661116, + -777445, + 406894, + 420650, + 240696, + 541549, + -195388, + -1533111, + -907101, + 2343927, + 3637760, + -1314843, + -7304614, + -3440247, + 9172547, + 12287346, + -4962661, + -22137358, + -8807614, + 25851076, + 31259377, + -14345609, + -54243003, + -18514833, + 62352326, + 69973415, + -36983526, + -124196156, + -36948438, + 151549067, + 166232652, + -107253008, + -357480636, + -105401064, + 714368035, + 1538824501, + 1672636733, + 997432132, + 96177626, + -350292611, + -208355266, + 108622663, + 186408443, + 19931717, + -118884152, + -74408189, + 46899790, + 77406045, + 5796242, + -52705511, + -30984191, + 21805152, + 32879144, + 1271006, + -22045247, + -11766977, + 8965442, + 12061828, + 34482, + -7522211, + -3522487, + 2801624, + 3235548, + -94238, + -1670748, + -627305, + 460741, + 378408, + 287187, + 527491, + -333751, + -1604131, + -664683, + 2669790, + 3431406, + -2049786, + -7498582, + -2369318, + 10267163, + 11408046, + -7270656, + -22474571, + -5646577, + 28587306, + 28665905, + -20058906, + -54629317, + -10808229, + 68337521, + 63518509, + -49914393, + -124482810, + -18875614, + 165440894, + 150165468, + -141734179, + -360996871, + -44039515, + 809657196, + 1591548555, + 1636298320, + 904294295, + 23287548, + -358712191, + -175622607, + 130906567, + 177152746, + 175716, + -122726496, + -62462269, + 55799026, + 73393560, + -2664448, + -54124076, + -25637627, + 25503589, + 30947761, + -2270797, + -22448481, + -9552046, + 10297737, + 11237696, + -1205834, + -7573572, + -2789937, + 3152444, + 2969378, + -392718, + -1650937, + -478519, + 500787, + 333492, + 333492, + 500787, + -478519, + -1650937, + -392718, + 2969378, + 3152444, + -2789937, + -7573572, + -1205834, + 11237696, + 10297737, + -9552046, + -22448481, + -2270797, + 30947761, + 25503589, + -25637627, + -54124076, + -2664448, + 73393560, + 55799026, + -62462269, + -122726496, + 175716, + 177152746, + 130906567, + -175622607, + -358712191, + 23287548, + 904294295, + 1636298320, + 1591548555, + 809657196, + -44039515, + -360996871, + -141734179, + 150165468, + 165440894, + -18875614, + -124482810, + -49914393, + 63518509, + 68337521, + -10808229, + -54629317, + -20058906, + 28665905, + 28587306, + -5646577, + -22474571, + -7270656, + 11408046, + 10267163, + -2369318, + -7498582, + -2049786, + 3431406, + 2669790, + -664683, + -1604131, + -333751, + 527491, + 287187, + 378408, + 460741, + -627305, + -1670748, + -94238, + 3235548, + 2801624, + -3522487, + -7522211, + 34482, + 12061828, + 8965442, + -11766977, + -22045247, + 1271006, + 32879144, + 21805152, + -30984191, + -52705511, + 5796242, + 77406045, + 46899790, + -74408189, + -118884152, + 19931717, + 186408443, + 108622663, + -208355266, + -350292611, + 96177626, + 997432132, + 1672636733, + 1538824501, + 714368035, + -105401064, + -357480636, + -107253008, + 166232652, + 151549067, + -36948438, + -124196156, + -36983526, + 69973415, + 62352326, + -18514833, + -54243003, + -14345609, + 31259377, + 25851076, + -8807614, + -22137358, + -4962661, + 12287346, + 9172547, + -3440247, + -7304614, + -1314843, + 3637760, + 2343927, + -907101, + -1533111, + -195388, + 541549, + 240696, + 420650, + 406894, + -777445, + -1661116, + 227015, + 3461342, + 2381050, + -4234083, + -7338997, + 1333816, + 12718795, + 7424403, + -13875118, + -21256922, + 4925478, + 34333473, + 17613468, + -36001565, + -50366328, + 14444337, + 80274029, + 36927793, + -85535631, + -112944972, + 40097309, + 192959734, + 83534059, + -239358569, + -335464877, + 174155793, + 1088224370, + 1700207749, + 1478639065, + 619265382, + -160470174, + -348552435, + -72724622, + 178995349, + 135776295, + -53793622, + -121940141, + -23887567, + 75101736, + 55563565, + -25674863, + -53000562, + -8594262, + 33261625, + 22796625, + -11710461, + -21456126, + -2666798, + 12930808, + 7977274, + -4405157, + -7000705, + -597177, + 3772054, + 1998979, + -1117661, + -1440914, + -65512, + 543862, + 195111, + 458866, + 339051, + -926033, + -1619998, + 566617, + 3640128, + 1894218, + -4911043, + -7020493, + 2672484, + 13189816, + 5692018, + -15836342, + -20081810, + 8635368, + 35269086, + 12981189, + -40594907, + -47114310, + 23142941, + 81912107, + 26011175, + -95634111, + -104931677, + 60360060, + 196591133, + 55913519, + -268055637, + -314021572, + 256678778, + 1175835107, + 1718740562, + 1411574938, + 525169888, + -208997645, + -334649851, + -38670532, + 188394330, + 118439203, + -69189701, + -117816781, + -10839958, + 78864546, + 48105669, + -32191215, + -50950071, + -2898800, + 34660630, + 19484675, + -14317470, + -20455080, + -420079, + 13337711, + 6705438, + -5252979, + -6597316, + 92057, + 3836055, + 1642049, + -1294776, + -1330763, + 54120, + 535500, + 151401, + 491669, + 257311, + -1069965, + -1545826, + 919505, + 3765746, + 1346027, + -5539589, + -6565485, + 4029198, + 13458510, + 3789717, + -17611426, + -18524735, + 12340365, + 35651564, + 7970195, + -44673234, + -42972684, + 31749802, + 82252332, + 14297807, + -104502780, + -94901281, + 80394484, + 197124426, + 26084360, + -293873810, + -285825482, + 343139976, + 1259448419, + 1728052828, + 1338277735, + 432875309, + -250813167, + -316252292, + -5582211, + 194422772, + 99866670, + -82945345, + -111953995, + 1953532, + 81245894, + 40119482, + -37980243, + -48151071, + 2650868, + 35454582, + 15978007, + -16597205, + -19162764, + 1742753, + 13511288, + 5381366, + -5975118, + -6106089, + 742762, + 3832651, + 1280033, + -1437565, + -1205989, + 162088, + 517669, + 110400 + +}; + +static const struct src_stage src_int32_10_21_3455_5000 = { + 2, 1, 10, 64, 640, 21, 10, 0, 1, + src_int32_10_21_3455_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_10_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_10_21_4535_5000.h new file mode 100644 index 000000000000..96a242482b97 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_10_21_4535_5000.h @@ -0,0 +1,2338 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_10_21_4535_5000_fir[2320] = { + 26554, + 22041, + -35569, + -47074, + 37007, + 81421, + -24863, + -121825, + -6805, + 161885, + 62569, + -192041, + -144106, + 200178, + 248685, + -172932, + -367932, + 97662, + 487186, + 35027, + -585725, + -228481, + 638098, + 477319, + -616641, + -765314, + 495131, + 1064351, + -253299, + -1334901, + -118238, + 1528350, + 613273, + -1591310, + -1206266, + 1471793, + 1850352, + -1126828, + -2477800, + 530798, + 3003446, + 316475, + -3331328, + -1383043, + 3364348, + 2600748, + -3016381, + -3864842, + 2225773, + 5038154, + -968824, + -5960215, + -728455, + 6461233, + 2782095, + -6380163, + -5047114, + 5585501, + 7321036, + -3996843, + -9354767, + 1604859, + 10870943, + 1512900, + -11588963, + -5182865, + 11255090, + 9135126, + -9675150, + -13013406, + 6746756, + 16395905, + -2487572, + -18826523, + -2943886, + 19854781, + 9238082, + -19081696, + -15937372, + 16207922, + 22453385, + -11079868, + -28098929, + 3729320, + 32133022, + 5597626, + -33816201, + -16425713, + 32471934, + 28051770, + -27548998, + -39562310, + 18679077, + 49865349, + -5723778, + -57731432, + -11194325, + 61834972, + 31681198, + -60781054, + -55084924, + 53091824, + 80536286, + -37102064, + -107020261, + 10649939, + 133488971, + 29742665, + -159052823, + -91195104, + 183397853, + 192494052, + -208201957, + -404759537, + 246721549, + 1405393887, + 1948489334, + 1298161373, + 143650683, + -418162766, + -162885853, + 213943071, + 159651500, + -112959056, + -147398153, + 49676672, + 129692411, + -6499688, + -108556637, + -23206369, + 85612947, + 42619377, + -62305048, + -53673301, + 39916892, + 57850808, + -19538703, + -56487722, + 2025542, + 50878218, + 12034193, + -42289346, + -22332929, + 31933352, + 28838248, + -20923088, + -31767985, + 10225443, + 31548888, + -622153, + -28763173, + -7316332, + 24088197, + 13241055, + -18234769, + -17018289, + 11889356, + 18708183, + -5664679, + -18531170, + 62049, + 16825951, + 4552544, + -14003432, + -7958035, + 10500914, + 10074376, + -6740473, + -10947086, + 3094649, + 10723063, + 138441, + -9620986, + -2749574, + 7899724, + 4622565, + -5827964, + -5729175, + 3657732, + 6116596, + -1603752, + -5889820, + -170237, + 5191382, + 1557954, + -4180886, + -2510322, + 3016374, + 3029600, + -1839126, + -3159417, + 762866, + 2972421, + 132248, + -2557224, + -801066, + 2006156, + 1230952, + -1404964, + -1436341, + 825233, + 1451479, + -319841, + -1322474, + -78617, + 1099678, + 356837, + -831198, + -517852, + 558052, + 576862, + -311195, + -556572, + 110389, + 482699, + 35340, + -380155, + -126053, + 270228, + 168516, + -168886, + -173560, + 86184, + 153561, + -26584, + -120361, + -10057, + 83796, + 27127, + -50892, + -29801, + 25674, + 28964, + 17745, + -40835, + -42094, + 46482, + 77242, + -39645, + -120782, + 13713, + 167070, + 36999, + -207015, + -115700, + 228465, + 221474, + -217309, + -347822, + 159314, + 481700, + -42604, + -603372, + -139442, + 687342, + 385250, + -704521, + -682502, + 625637, + 1006524, + -425683, + -1320085, + 89028, + 1575026, + 385439, + -1715950, + -979837, + 1685954, + 1654327, + -1434090, + -2346438, + 923936, + 2973304, + -142352, + -3437209, + -892713, + 3634426, + 2126606, + -3466929, + -3465766, + 2856083, + 4779931, + -1756992, + -5909414, + 171829, + 6677548, + 1839669, + -6907842, + -4154398, + 6444663, + 6586337, + -5175690, + -8894394, + 3053849, + 10798052, + -116116, + -12000458, + -3503449, + 12217628, + 7568881, + -11211619, + -11747549, + 8824736, + 15626515, + -5011332, + -18739998, + -136419, + 20606779, + 6372260, + -20775214, + -13291966, + 18872470, + 20343797, + -14653845, + -26853962, + 8047627, + 32066329, + 808959, + -35194092, + -11546565, + 35479643, + 23555982, + -32257699, + -35996831, + 25015850, + 47821377, + -13446229, + -57809238, + -2518079, + 64604742, + 22688195, + -66742506, + -46632746, + 62635377, + 73727904, + -50473577, + -103260323, + 27918207, + 134623975, + 8726212, + -167738751, + -66896756, + 204178733, + 166153204, + -251549311, + -381892299, + 355672269, + 1505937184, + 1935285293, + 1185493264, + 47404677, + -422480896, + -116541983, + 230283865, + 133500854, + -131834331, + -133081066, + 68157093, + 123365555, + -23190255, + -107878344, + -9073915, + 88883154, + 31442388, + -68165309, + -45577914, + 47239207, + 52747829, + -27386945, + -54116963, + 9645001, + 50851090, + 5218789, + -44131861, + -16720255, + 35128666, + 24658462, + -24951630, + -29097584, + 14600414, + 30332156, + -4918444, + -28838911, + -3441224, + 25219741, + 10034822, + -20141013, + -14630309, + 14274487, + 17193995, + -8244563, + -17863611, + 2585668, + 16911253, + 2287659, + -14700296, + -6096825, + 11640583, + 8701575, + -8145961, + -10090159, + 4597588, + 10359682, + -1315531, + -9689696, + -1459862, + 8312350, + 3576471, + -6482354, + -4969418, + 4449592, + 5652063, + -2436622, + -5701050, + 622478, + 5237750, + 866598, + -4408502, + -1959682, + 3365796, + 2637776, + -2252163, + -2925814, + 1187944, + 2881671, + -263568, + -2583818, + -463660, + 2119157, + 968693, + -1572315, + -1254635, + 1017268, + 1346438, + -511786, + -1283494, + 94783, + 1112166, + 213692, + -879115, + -410352, + 626020, + 505101, + -386028, + -516729, + 181999, + 468536, + -26371, + -384415, + -77679, + 285796, + 134204, + -189625, + -152041, + 107414, + 142356, + -45240, + -116496, + 4469, + 84382, + 17061, + -53514, + -23674, + 28599, + 30873, + 12850, + -45460, + -36013, + 55333, + 71285, + -54088, + -117174, + 34563, + 168918, + 9955, + -218079, + -84168, + 252705, + 189027, + -258205, + -320066, + 219005, + 466145, + -120943, + -608918, + -45798, + 723350, + 283536, + -779482, + -584171, + 745529, + 927007, + -592182, + -1277886, + 297782, + 1590072, + 146174, + -1807239, + -729919, + 1868642, + 1421531, + -1716278, + -2165112, + 1303518, + 2881786, + -604366, + -3474022, + -377751, + 3833471, + 1602937, + -3852042, + -2990821, + 3435514, + 4420752, + -2518469, + -5737046, + 1078948, + 6759654, + 849002, + -7300037, + -3166859, + 7181333, + 5708983, + -6261260, + -8247231, + 4455582, + 10503585, + -1759564, + -12170794, + -1735333, + 12940104, + 5832193, + -12534226, + -10229007, + 10742854, + 14530175, + -7457389, + -18269635, + 2701185, + 20944971, + 3348372, + -22060642, + -10349224, + 21177315, + 17797902, + -17963391, + -25047994, + 12244221, + 31343689, + -4044355, + -35866717, + -6381390, + 37793445, + 18531344, + -36357435, + -31656589, + 30911680, + 44776319, + -20983806, + -56705587, + 6316986, + 66088063, + 13111435, + -71420142, + -37103215, + 71041183, + 65298892, + -63039250, + -97312802, + 44955653, + 133017027, + -12971155, + -173200934, + -40478872, + 221471825, + 135238694, + -291976471, + -349306932, + 469454555, + 1598605011, + 1909038446, + 1068692757, + -41186150, + -418208675, + -70086194, + 241402080, + 105534466, + -147532265, + -116452082, + 84849711, + 114686929, + -39096913, + -105038187, + 5007907, + 90309455, + 19795999, + -72566976, + -36671249, + 53512454, + 46642927, + -34586762, + -50680257, + 16982278, + 49796149, + -1627610, + -45062127, + -10828581, + 37580257, + 20022668, + -28434631, + -25865228, + 18636568, + 28513667, + -9073183, + -28330337, + 465974, + 25829981, + 6656409, + -21621293, + -11969209, + 16347761, + 15346404, + -10632675, + -16840960, + 5032452, + 16653443, + -1359, + -15092772, + -4130624, + 12533309, + 7166403, + -9372407, + -9037715, + 5992091, + 9790378, + -2727747, + -9561576, + -154271, + 8552334, + 2469300, + -6998412, + -4117473, + 5142575, + 5078388, + -3210682, + -5399092, + 1393336, + 5177583, + 165987, + -4544152, + -1376159, + 3642761, + 2197530, + -2614339, + -2636049, + 1583382, + 2733835, + -648672, + -2557770, + -121606, + 2187675, + 690638, + -1705390, + -1050274, + 1185790, + 1215793, + -690335, + -1219179, + 263411, + 1101945, + 68679, + -908408, + -296475, + 680077, + 424464, + -451613, + -467214, + 248479, + 445184, + -86231, + -380800, + -28828, + 295213, + 98003, + -206002, + -128001, + 125890, + 128579, + -62424, + -110384, + 18425, + 83227, + 7023, + -54934, + -17330, + 30788, + 32209, + 7436, + -49317, + -28916, + 63347, + 63615, + -67874, + -110997, + 55314, + 167293, + -18037, + -224897, + -50089, + 272294, + 151895, + -294688, + -285072, + 275454, + 440633, + -198383, + -602008, + 50607, + 745127, + 174100, + -839742, + -472074, + 852154, + 827072, + -749268, + -1208727, + 503752, + 1572682, + -99778, + -1862794, + -461301, + 2015643, + 1156218, + -1967242, + -1936851, + 1661564, + 2729942, + -1060127, + -3440108, + 151597, + 3956496, + 1039856, + -4163014, + -2448816, + 3951577, + 3966775, + -3237339, + -5445231, + 1974401, + 6704346, + -170162, + -7547212, + -2103671, + 7779100, + 4705393, + -7230342, + -7424548, + 5780883, + 9991265, + -3383974, + -12094021, + 86219, + 13405321, + 3958870, + -13613795, + -8486323, + 12460320, + 13126084, + -9774983, + -17421301, + 5511225, + 20858423, + 226678, + -22907750, + -7166385, + 23071858, + 14863457, + -20938299, + -22712400, + 16232167, + 29973324, + -8863829, + -35813181, + -1032752, + 39358870, + 13074901, + -39757953, + -26621769, + 36241255, + 40780955, + -28180434, + -54428823, + 15132446, + 66238165, + 3138652, + -74700676, + -26675183, + 78120342, + 55395030, + -74528971, + -89258632, + 61410608, + 128641263, + -34924770, + -175241993, + -12410581, + 234804786, + 100168405, + -328536739, + -306881263, + 586929948, + 1682295416, + 1870068913, + 949094234, + -121415674, + -405946140, + -24395297, + 247283933, + 76356582, + -159833506, + -97898119, + 99462907, + 103877877, + -53916489, + -100131079, + 18757441, + 89891852, + 7921293, + -75441958, + -27143585, + 58623788, + 39671691, + -41000760, + -46259465, + 23892485, + 47746166, + -8366377, + -45071123, + -4779905, + 39246287, + 15029247, + -31307186, + -22141906, + 22255634, + 26136124, + -13003706, + -27253424, + 4325894, + 25911604, + 3175842, + -22649750, + -9091473, + 18070218, + 13206020, + -12782528, + -15487354, + 7353615, + 16061082, + -2267932, + -15175908, + -2100278, + 13163474, + 5501567, + -10396783, + -7813049, + 7251033, + 9028805, + -4070047, + -9241289, + 1140594, + 8616665, + 1324130, + -7367201, + -3191611, + 5723750, + 4408421, + -3910930, + -4991367, + 2126983, + 5013358, + -529581, + -4586206, + -771974, + 3842564, + 1718390, + -2918974, + -2296721, + 1941560, + 2532670, + -1015409, + -2480336, + 218101, + 2210955, + 402650, + -1801999, + -827738, + 1327746, + 1062587, + -852085, + -1131240, + 423927, + 1069604, + -75231, + -918808, + -178643, + 719383, + 336755, + -506798, + -409223, + 308585, + 413308, + -143065, + -369555, + 19496, + 298431, + 60695, + -217793, + -101993, + 141311, + 112585, + -77829, + -102220, + 31545, + 80417, + -2779, + -55170, + -10913, + 32230, + 32911, + 1596, + -52286, + -20917, + 70320, + 54334, + -80691, + -102301, + 75528, + 162133, + -46417, + -227217, + -14110, + 286710, + 110740, + -325902, + -243405, + 327421, + 405484, + -273301, + -582539, + 147832, + 751954, + 59059, + -883794, + -348282, + 943082, + 708431, + -893549, + -1113595, + 702652, + 1522707, + -347461, + -1880935, + -179227, + 2123415, + 863372, + -2181386, + -1665691, + 1990430, + 2520077, + -1500200, + -3335237, + 684660, + 4000013, + 448414, + -4392553, + -1850042, + 4392931, + 3426174, + -3898375, + -5038559, + 2839713, + 6511196, + -1197276, + -7642699, + -985770, + 8224219, + 3594747, + -8061862, + -6441323, + 7001835, + 9269309, + -4955921, + -11769183, + 1924498, + 13601171, + 1985847, + -14425831, + -6552905, + 13940041, + 11439922, + -11915481, + -16208647, + 8235999, + 20344774, + -2929978, + -23294969, + -3806153, + 24513396, + 11596623, + -23514511, + -19889677, + 19927931, + 27976767, + -13550674, + -35027199, + 4391985, + 40136158, + 7293535, + -42382297, + -20987596, + 40889416, + 35906019, + -34885166, + -51011302, + 23748069, + 65034837, + -7031857, + -76497689, + -15548366, + 83708035, + 44194393, + -84689814, + -79222885, + 76936194, + 121525012, + -56694720, + -173727518, + 16792232, + 243765753, + 61456106, + -360303676, + -254630312, + 706884469, + 1756006541, + 1818851046, + 828044579, + -192709487, + -386386642, + 19705853, + 248013056, + 46575513, + -168590321, + -77834185, + 111752408, + 91197371, + -67373060, + -93291430, + 31904268, + 87667225, + -3939603, + -76753743, + -17195126, + 62485174, + 31985455, + -46509020, + -40955317, + 30240990, + 44753620, + -14862566, + -44168524, + 1301885, + 40101218, + 9782804, + -33517377, + -18007820, + 25388551, + 23253118, + -16632694, + -25635485, + 8060898, + 25468061, + -335463, + -23209919, + -6057426, + 19410370, + 10818987, + -14652906, + -13833399, + 9503389, + 15149425, + -4466394, + -14951066, + -47527, + 13520935, + 3742074, + -11200389, + -6442709, + 8350313, + 8092368, + -5315980, + -8737339, + 2398627, + 8505920, + 164562, + -7582860, + -2211396, + 6182598, + 3656815, + -4524028, + -4487355, + 2808998, + 4749634, + -1206081, + -4534948, + -159616, + 3962120, + 1210550, + -3160634, + -1915348, + 2255719, + 2282965, + -1356603, + -2353793, + 548616, + 2189173, + 110704, + -1860724, + -591806, + 1440666, + 890278, + -994025, + -1021842, + 573214, + 1016170, + -215140, + -910436, + -59317, + 743411, + 243884, + -550664, + -344098, + 361225, + 373733, + -195784, + -351077, + 66325, + 295529, + 23066, + -224874, + -74601, + 153444, + 94762, + -91192, + -92235, + 43585, + 76066, + -12152, + -54266, + -4561, + 32930, + 32930, + -4561, + -54266, + -12152, + 76066, + 43585, + -92235, + -91192, + 94762, + 153444, + -74601, + -224874, + 23066, + 295529, + 66325, + -351077, + -195784, + 373733, + 361225, + -344098, + -550664, + 243884, + 743411, + -59317, + -910436, + -215140, + 1016170, + 573214, + -1021842, + -994025, + 890278, + 1440666, + -591806, + -1860724, + 110704, + 2189173, + 548616, + -2353793, + -1356603, + 2282965, + 2255719, + -1915348, + -3160634, + 1210550, + 3962120, + -159616, + -4534948, + -1206081, + 4749634, + 2808998, + -4487355, + -4524028, + 3656815, + 6182598, + -2211396, + -7582860, + 164562, + 8505920, + 2398627, + -8737339, + -5315980, + 8092368, + 8350313, + -6442709, + -11200389, + 3742074, + 13520935, + -47527, + -14951066, + -4466394, + 15149425, + 9503389, + -13833399, + -14652906, + 10818987, + 19410370, + -6057426, + -23209919, + -335463, + 25468061, + 8060898, + -25635485, + -16632694, + 23253118, + 25388551, + -18007820, + -33517377, + 9782804, + 40101218, + 1301885, + -44168524, + -14862566, + 44753620, + 30240990, + -40955317, + -46509020, + 31985455, + 62485174, + -17195126, + -76753743, + -3939603, + 87667225, + 31904268, + -93291430, + -67373060, + 91197371, + 111752408, + -77834185, + -168590321, + 46575513, + 248013056, + 19705853, + -386386642, + -192709487, + 828044579, + 1818851046, + 1756006541, + 706884469, + -254630312, + -360303676, + 61456106, + 243765753, + 16792232, + -173727518, + -56694720, + 121525012, + 76936194, + -79222885, + -84689814, + 44194393, + 83708035, + -15548366, + -76497689, + -7031857, + 65034837, + 23748069, + -51011302, + -34885166, + 35906019, + 40889416, + -20987596, + -42382297, + 7293535, + 40136158, + 4391985, + -35027199, + -13550674, + 27976767, + 19927931, + -19889677, + -23514511, + 11596623, + 24513396, + -3806153, + -23294969, + -2929978, + 20344774, + 8235999, + -16208647, + -11915481, + 11439922, + 13940041, + -6552905, + -14425831, + 1985847, + 13601171, + 1924498, + -11769183, + -4955921, + 9269309, + 7001835, + -6441323, + -8061862, + 3594747, + 8224219, + -985770, + -7642699, + -1197276, + 6511196, + 2839713, + -5038559, + -3898375, + 3426174, + 4392931, + -1850042, + -4392553, + 448414, + 4000013, + 684660, + -3335237, + -1500200, + 2520077, + 1990430, + -1665691, + -2181386, + 863372, + 2123415, + -179227, + -1880935, + -347461, + 1522707, + 702652, + -1113595, + -893549, + 708431, + 943082, + -348282, + -883794, + 59059, + 751954, + 147832, + -582539, + -273301, + 405484, + 327421, + -243405, + -325902, + 110740, + 286710, + -14110, + -227217, + -46417, + 162133, + 75528, + -102301, + -80691, + 54334, + 70320, + -20917, + -52286, + 1596, + 32911, + 32230, + -10913, + -55170, + -2779, + 80417, + 31545, + -102220, + -77829, + 112585, + 141311, + -101993, + -217793, + 60695, + 298431, + 19496, + -369555, + -143065, + 413308, + 308585, + -409223, + -506798, + 336755, + 719383, + -178643, + -918808, + -75231, + 1069604, + 423927, + -1131240, + -852085, + 1062587, + 1327746, + -827738, + -1801999, + 402650, + 2210955, + 218101, + -2480336, + -1015409, + 2532670, + 1941560, + -2296721, + -2918974, + 1718390, + 3842564, + -771974, + -4586206, + -529581, + 5013358, + 2126983, + -4991367, + -3910930, + 4408421, + 5723750, + -3191611, + -7367201, + 1324130, + 8616665, + 1140594, + -9241289, + -4070047, + 9028805, + 7251033, + -7813049, + -10396783, + 5501567, + 13163474, + -2100278, + -15175908, + -2267932, + 16061082, + 7353615, + -15487354, + -12782528, + 13206020, + 18070218, + -9091473, + -22649750, + 3175842, + 25911604, + 4325894, + -27253424, + -13003706, + 26136124, + 22255634, + -22141906, + -31307186, + 15029247, + 39246287, + -4779905, + -45071123, + -8366377, + 47746166, + 23892485, + -46259465, + -41000760, + 39671691, + 58623788, + -27143585, + -75441958, + 7921293, + 89891852, + 18757441, + -100131079, + -53916489, + 103877877, + 99462907, + -97898119, + -159833506, + 76356582, + 247283933, + -24395297, + -405946140, + -121415674, + 949094234, + 1870068913, + 1682295416, + 586929948, + -306881263, + -328536739, + 100168405, + 234804786, + -12410581, + -175241993, + -34924770, + 128641263, + 61410608, + -89258632, + -74528971, + 55395030, + 78120342, + -26675183, + -74700676, + 3138652, + 66238165, + 15132446, + -54428823, + -28180434, + 40780955, + 36241255, + -26621769, + -39757953, + 13074901, + 39358870, + -1032752, + -35813181, + -8863829, + 29973324, + 16232167, + -22712400, + -20938299, + 14863457, + 23071858, + -7166385, + -22907750, + 226678, + 20858423, + 5511225, + -17421301, + -9774983, + 13126084, + 12460320, + -8486323, + -13613795, + 3958870, + 13405321, + 86219, + -12094021, + -3383974, + 9991265, + 5780883, + -7424548, + -7230342, + 4705393, + 7779100, + -2103671, + -7547212, + -170162, + 6704346, + 1974401, + -5445231, + -3237339, + 3966775, + 3951577, + -2448816, + -4163014, + 1039856, + 3956496, + 151597, + -3440108, + -1060127, + 2729942, + 1661564, + -1936851, + -1967242, + 1156218, + 2015643, + -461301, + -1862794, + -99778, + 1572682, + 503752, + -1208727, + -749268, + 827072, + 852154, + -472074, + -839742, + 174100, + 745127, + 50607, + -602008, + -198383, + 440633, + 275454, + -285072, + -294688, + 151895, + 272294, + -50089, + -224897, + -18037, + 167293, + 55314, + -110997, + -67874, + 63615, + 63347, + -28916, + -49317, + 7436, + 32209, + 30788, + -17330, + -54934, + 7023, + 83227, + 18425, + -110384, + -62424, + 128579, + 125890, + -128001, + -206002, + 98003, + 295213, + -28828, + -380800, + -86231, + 445184, + 248479, + -467214, + -451613, + 424464, + 680077, + -296475, + -908408, + 68679, + 1101945, + 263411, + -1219179, + -690335, + 1215793, + 1185790, + -1050274, + -1705390, + 690638, + 2187675, + -121606, + -2557770, + -648672, + 2733835, + 1583382, + -2636049, + -2614339, + 2197530, + 3642761, + -1376159, + -4544152, + 165987, + 5177583, + 1393336, + -5399092, + -3210682, + 5078388, + 5142575, + -4117473, + -6998412, + 2469300, + 8552334, + -154271, + -9561576, + -2727747, + 9790378, + 5992091, + -9037715, + -9372407, + 7166403, + 12533309, + -4130624, + -15092772, + -1359, + 16653443, + 5032452, + -16840960, + -10632675, + 15346404, + 16347761, + -11969209, + -21621293, + 6656409, + 25829981, + 465974, + -28330337, + -9073183, + 28513667, + 18636568, + -25865228, + -28434631, + 20022668, + 37580257, + -10828581, + -45062127, + -1627610, + 49796149, + 16982278, + -50680257, + -34586762, + 46642927, + 53512454, + -36671249, + -72566976, + 19795999, + 90309455, + 5007907, + -105038187, + -39096913, + 114686929, + 84849711, + -116452082, + -147532265, + 105534466, + 241402080, + -70086194, + -418208675, + -41186150, + 1068692757, + 1909038446, + 1598605011, + 469454555, + -349306932, + -291976471, + 135238694, + 221471825, + -40478872, + -173200934, + -12971155, + 133017027, + 44955653, + -97312802, + -63039250, + 65298892, + 71041183, + -37103215, + -71420142, + 13111435, + 66088063, + 6316986, + -56705587, + -20983806, + 44776319, + 30911680, + -31656589, + -36357435, + 18531344, + 37793445, + -6381390, + -35866717, + -4044355, + 31343689, + 12244221, + -25047994, + -17963391, + 17797902, + 21177315, + -10349224, + -22060642, + 3348372, + 20944971, + 2701185, + -18269635, + -7457389, + 14530175, + 10742854, + -10229007, + -12534226, + 5832193, + 12940104, + -1735333, + -12170794, + -1759564, + 10503585, + 4455582, + -8247231, + -6261260, + 5708983, + 7181333, + -3166859, + -7300037, + 849002, + 6759654, + 1078948, + -5737046, + -2518469, + 4420752, + 3435514, + -2990821, + -3852042, + 1602937, + 3833471, + -377751, + -3474022, + -604366, + 2881786, + 1303518, + -2165112, + -1716278, + 1421531, + 1868642, + -729919, + -1807239, + 146174, + 1590072, + 297782, + -1277886, + -592182, + 927007, + 745529, + -584171, + -779482, + 283536, + 723350, + -45798, + -608918, + -120943, + 466145, + 219005, + -320066, + -258205, + 189027, + 252705, + -84168, + -218079, + 9955, + 168918, + 34563, + -117174, + -54088, + 71285, + 55333, + -36013, + -45460, + 12850, + 30873, + 28599, + -23674, + -53514, + 17061, + 84382, + 4469, + -116496, + -45240, + 142356, + 107414, + -152041, + -189625, + 134204, + 285796, + -77679, + -384415, + -26371, + 468536, + 181999, + -516729, + -386028, + 505101, + 626020, + -410352, + -879115, + 213692, + 1112166, + 94783, + -1283494, + -511786, + 1346438, + 1017268, + -1254635, + -1572315, + 968693, + 2119157, + -463660, + -2583818, + -263568, + 2881671, + 1187944, + -2925814, + -2252163, + 2637776, + 3365796, + -1959682, + -4408502, + 866598, + 5237750, + 622478, + -5701050, + -2436622, + 5652063, + 4449592, + -4969418, + -6482354, + 3576471, + 8312350, + -1459862, + -9689696, + -1315531, + 10359682, + 4597588, + -10090159, + -8145961, + 8701575, + 11640583, + -6096825, + -14700296, + 2287659, + 16911253, + 2585668, + -17863611, + -8244563, + 17193995, + 14274487, + -14630309, + -20141013, + 10034822, + 25219741, + -3441224, + -28838911, + -4918444, + 30332156, + 14600414, + -29097584, + -24951630, + 24658462, + 35128666, + -16720255, + -44131861, + 5218789, + 50851090, + 9645001, + -54116963, + -27386945, + 52747829, + 47239207, + -45577914, + -68165309, + 31442388, + 88883154, + -9073915, + -107878344, + -23190255, + 123365555, + 68157093, + -133081066, + -131834331, + 133500854, + 230283865, + -116541983, + -422480896, + 47404677, + 1185493264, + 1935285293, + 1505937184, + 355672269, + -381892299, + -251549311, + 166153204, + 204178733, + -66896756, + -167738751, + 8726212, + 134623975, + 27918207, + -103260323, + -50473577, + 73727904, + 62635377, + -46632746, + -66742506, + 22688195, + 64604742, + -2518079, + -57809238, + -13446229, + 47821377, + 25015850, + -35996831, + -32257699, + 23555982, + 35479643, + -11546565, + -35194092, + 808959, + 32066329, + 8047627, + -26853962, + -14653845, + 20343797, + 18872470, + -13291966, + -20775214, + 6372260, + 20606779, + -136419, + -18739998, + -5011332, + 15626515, + 8824736, + -11747549, + -11211619, + 7568881, + 12217628, + -3503449, + -12000458, + -116116, + 10798052, + 3053849, + -8894394, + -5175690, + 6586337, + 6444663, + -4154398, + -6907842, + 1839669, + 6677548, + 171829, + -5909414, + -1756992, + 4779931, + 2856083, + -3465766, + -3466929, + 2126606, + 3634426, + -892713, + -3437209, + -142352, + 2973304, + 923936, + -2346438, + -1434090, + 1654327, + 1685954, + -979837, + -1715950, + 385439, + 1575026, + 89028, + -1320085, + -425683, + 1006524, + 625637, + -682502, + -704521, + 385250, + 687342, + -139442, + -603372, + -42604, + 481700, + 159314, + -347822, + -217309, + 221474, + 228465, + -115700, + -207015, + 36999, + 167070, + 13713, + -120782, + -39645, + 77242, + 46482, + -42094, + -40835, + 17745, + 28964, + 25674, + -29801, + -50892, + 27127, + 83796, + -10057, + -120361, + -26584, + 153561, + 86184, + -173560, + -168886, + 168516, + 270228, + -126053, + -380155, + 35340, + 482699, + 110389, + -556572, + -311195, + 576862, + 558052, + -517852, + -831198, + 356837, + 1099678, + -78617, + -1322474, + -319841, + 1451479, + 825233, + -1436341, + -1404964, + 1230952, + 2006156, + -801066, + -2557224, + 132248, + 2972421, + 762866, + -3159417, + -1839126, + 3029600, + 3016374, + -2510322, + -4180886, + 1557954, + 5191382, + -170237, + -5889820, + -1603752, + 6116596, + 3657732, + -5729175, + -5827964, + 4622565, + 7899724, + -2749574, + -9620986, + 138441, + 10723063, + 3094649, + -10947086, + -6740473, + 10074376, + 10500914, + -7958035, + -14003432, + 4552544, + 16825951, + 62049, + -18531170, + -5664679, + 18708183, + 11889356, + -17018289, + -18234769, + 13241055, + 24088197, + -7316332, + -28763173, + -622153, + 31548888, + 10225443, + -31767985, + -20923088, + 28838248, + 31933352, + -22332929, + -42289346, + 12034193, + 50878218, + 2025542, + -56487722, + -19538703, + 57850808, + 39916892, + -53673301, + -62305048, + 42619377, + 85612947, + -23206369, + -108556637, + -6499688, + 129692411, + 49676672, + -147398153, + -112959056, + 159651500, + 213943071, + -162885853, + -418162766, + 143650683, + 1298161373, + 1948489334, + 1405393887, + 246721549, + -404759537, + -208201957, + 192494052, + 183397853, + -91195104, + -159052823, + 29742665, + 133488971, + 10649939, + -107020261, + -37102064, + 80536286, + 53091824, + -55084924, + -60781054, + 31681198, + 61834972, + -11194325, + -57731432, + -5723778, + 49865349, + 18679077, + -39562310, + -27548998, + 28051770, + 32471934, + -16425713, + -33816201, + 5597626, + 32133022, + 3729320, + -28098929, + -11079868, + 22453385, + 16207922, + -15937372, + -19081696, + 9238082, + 19854781, + -2943886, + -18826523, + -2487572, + 16395905, + 6746756, + -13013406, + -9675150, + 9135126, + 11255090, + -5182865, + -11588963, + 1512900, + 10870943, + 1604859, + -9354767, + -3996843, + 7321036, + 5585501, + -5047114, + -6380163, + 2782095, + 6461233, + -728455, + -5960215, + -968824, + 5038154, + 2225773, + -3864842, + -3016381, + 2600748, + 3364348, + -1383043, + -3331328, + 316475, + 3003446, + 530798, + -2477800, + -1126828, + 1850352, + 1471793, + -1206266, + -1591310, + 613273, + 1528350, + -118238, + -1334901, + -253299, + 1064351, + 495131, + -765314, + -616641, + 477319, + 638098, + -228481, + -585725, + 35027, + 487186, + 97662, + -367932, + -172932, + 248685, + 200178, + -144106, + -192041, + 62569, + 161885, + -6805, + -121825, + -24863, + 81421, + 37007, + -47074, + -35569, + 22041, + 26554 + +}; + +static const struct src_stage src_int32_10_21_4535_5000 = { + 2, 1, 10, 232, 2320, 21, 10, 0, 1, + src_int32_10_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_10_9_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_10_9_4535_5000.h new file mode 100644 index 000000000000..83ca193c21a0 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_10_9_4535_5000.h @@ -0,0 +1,1098 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_10_9_4535_5000_fir[1080] = { + -35695, + 60551, + -91611, + 127992, + -167857, + 208256, + -245001, + 272608, + -284300, + 272121, + -227140, + 139768, + -206, + -201017, + 472382, + -820650, + 1250059, + -1761496, + 2351686, + -3012419, + 3729884, + -4484142, + 5248784, + -5990824, + 6670847, + -7243451, + 7657989, + -7859614, + 7790618, + -7392034, + 6605458, + -5375041, + 3649564, + -1384542, + -1455760, + 4896487, + -8950616, + 13617776, + -18883533, + 24719280, + -31082829, + 37919854, + -45166383, + 52752629, + -60608709, + 68673272, + -76907097, + 85316225, + -93995379, + 103219960, + -113672506, + 127122628, + -149188825, + 209524374, + 2039998499, + -2431429, + -47041174, + 62993752, + -69589201, + 71896873, + -71686913, + 69780636, + -66646963, + 62601319, + -57883749, + 52692748, + -47200566, + 41560064, + -35907490, + 30363276, + -25031944, + 20001718, + -15344170, + 11114107, + -7349781, + 4073484, + -1292515, + -999509, + 2821046, + -4200793, + 5175697, + -5788889, + 6087628, + -6121309, + 5939625, + -5590913, + 5120751, + -4570812, + 3978011, + -3373932, + 2784533, + -2230113, + 1725494, + -1280403, + 899998, + -585508, + 334926, + -143740, + 5642, + 86805, + -141559, + 166588, + -169454, + 156993, + -135102, + 108625, + -81310, + 55852, + -34062, + 59868, + -94067, + 136723, + -187047, + 243167, + -301934, + 358761, + -407528, + 440562, + -448722, + 421591, + -347796, + 215462, + -12783, + -271270, + 646151, + -1118852, + 1692975, + -2367785, + 3137307, + -3989501, + 4905568, + -5859440, + 6817493, + -7738525, + 8574033, + -9268794, + 9761779, + -9987366, + 9876837, + -9360120, + 8367701, + -6832641, + 4692598, + -1891736, + -1617604, + 5873608, + -10904271, + 16727442, + -23351927, + 30780041, + -39012203, + 48054552, + -57931362, + 68705534, + -80513864, + 93631599, + -108600717, + 126513302, + -149731425, + 184115219, + -248465620, + 450597483, + 1979385290, + -177235756, + 49505658, + -2404746, + -21667805, + 35589802, + -43892574, + 48610538, + -50822812, + 51182216, + -50129769, + 47991993, + -45028482, + 41456245, + -37462393, + 33210697, + -28844847, + 24489952, + -20253169, + 16223974, + -12474402, + 9059430, + -6017612, + 3372006, + -1131389, + -708255, + 2162030, + -3254268, + 4016576, + -4485865, + 4702424, + -4708115, + 4544723, + -4252519, + 3869071, + -3428305, + 2959837, + -2488566, + 2034514, + -1612885, + 1234314, + -905265, + 628552, + -403924, + 228699, + -98383, + 7281, + 50960, + -82873, + 94777, + -92473, + 81029, + -64658, + 46660, + -28855, + 53367, + -87820, + 133257, + -190033, + 257551, + -334004, + 416130, + -499012, + 575941, + -638355, + 675896, + -676578, + 627097, + -513282, + 320703, + -35401, + -355239, + 861526, + -1490422, + 2244476, + -3120768, + 4109917, + -5195213, + 6351906, + -7546725, + 8737652, + -9873992, + 10896769, + -11739441, + 12328945, + -12587023, + 12431807, + -11779568, + 10546560, + -8650821, + 6013800, + -2561611, + -1774311, + 7057459, + -13347840, + 20705519, + -29197100, + 38906798, + -49955028, + 62530071, + -76944093, + 93738125, + -113894891, + 139317637, + -174070619, + 228319133, + -335766321, + 710555800, + 1861404153, + -309456656, + 133161652, + -63474546, + 25787764, + -2352146, + -13226519, + 23832572, + -30979205, + 35558723, + -38152219, + 39172579, + -38935882, + 37698982, + -35679858, + 33068721, + -30033964, + 26725194, + -23274632, + 19797667, + -16393029, + 13142903, + -10113138, + 7353699, + -4899370, + 2770762, + -975576, + -489902, + 1639129, + -2493519, + 3080614, + -3432266, + 3582904, + -3567931, + 3422297, + -3179287, + 2869541, + -2520321, + 2155015, + -1792879, + 1448988, + -1134377, + 856325, + -618770, + 422792, + -267156, + 148856, + -63651, + 6565, + 27685, + -44315, + 48190, + -43613, + 34198, + -20196, + 41148, + -72790, + 117083, + -175535, + 248914, + -336950, + 438027, + -548896, + 664417, + -777375, + 878375, + -955850, + 996197, + -984069, + 902819, + -735109, + 463686, + -72297, + -453266, + 1124025, + -1946619, + 2922101, + -4044775, + 5301125, + -6668904, + 8116429, + -9602119, + 11074337, + -12471548, + 13722796, + -14748520, + 15461647, + -15768935, + 15572465, + -14771182, + 13262317, + -10942494, + 7708248, + -3455571, + -1922063, + 8537987, + -16520282, + 26025546, + -37262461, + 50532678, + -66304368, + 85352162, + -109044996, + 140003552, + -183835054, + 254789941, + -401977006, + 977532911, + 1692338571, + -396485800, + 198253641, + -115320439, + 68721764, + -38574213, + 17539228, + -2275128, + -8968504, + 17212166, + -23107543, + 27106572, + -29547090, + 30698630, + -30787736, + 30012102, + -28548373, + 26556240, + -24180368, + 21551095, + -18784476, + 15982068, + -13230689, + 10602320, + -8154247, + 5929476, + -3957453, + 2255057, + -827848, + -328492, + 1226580, + -1885666, + 2329966, + -2587029, + 2686210, + -2657287, + 2529256, + -2329338, + 2082203, + -1809417, + 1529105, + -1255821, + 1000588, + -771093, + 572003, + -405359, + 271036, + -167212, + 90844, + -38106, + 4790, + 13360, + -20380, + 19881, + -8572, + 23885, + -49735, + 88867, + -143843, + 216773, + -308995, + 420725, + -550710, + 695872, + -851006, + 1008527, + -1158306, + 1287628, + -1381285, + 1421822, + -1389971, + 1265255, + -1026778, + 654188, + -128788, + -565228, + 1439458, + -2499933, + 3745780, + -5167954, + 6748105, + -8457628, + 10256954, + -12095129, + 13909693, + -15626890, + 17162189, + -18421092, + 19300151, + -19688104, + 19466981, + -18512964, + 16696719, + -13882775, + 9927331, + -4673566, + -2057100, + 10480374, + -20875758, + 33633505, + -49340198, + 68943663, + -94096522, + 127952220, + -177304520, + 259756757, + -438633575, + 1238715604, + 1481110482, + -438566736, + 241021040, + -154105773, + 103655272, + -70002634, + 45719262, + -27388380, + 13219210, + -2175862, + -6393264, + 12931208, + -17762559, + 21142284, + -23283099, + 24371030, + -24574123, + 24047103, + -22933556, + 21366641, + -19468962, + 17352012, + -15115477, + 12846601, + -10619721, + 8496073, + -6523889, + 4738810, + -3164598, + 1814107, + -690485, + -211474, + 903852, + -1404103, + 1733549, + -1915952, + 1976192, + -1939102, + 1828481, + -1666300, + 1472111, + -1262661, + 1051685, + -849876, + 665001, + -502127, + 363943, + -251140, + 162813, + -96877, + 50456, + -20244, + 2806, + 5170, + 5170, + 2806, + -20244, + 50456, + -96877, + 162813, + -251140, + 363943, + -502127, + 665001, + -849876, + 1051685, + -1262661, + 1472111, + -1666300, + 1828481, + -1939102, + 1976192, + -1915952, + 1733549, + -1404103, + 903852, + -211474, + -690485, + 1814107, + -3164598, + 4738810, + -6523889, + 8496073, + -10619721, + 12846601, + -15115477, + 17352012, + -19468962, + 21366641, + -22933556, + 24047103, + -24574123, + 24371030, + -23283099, + 21142284, + -17762559, + 12931208, + -6393264, + -2175862, + 13219210, + -27388380, + 45719262, + -70002634, + 103655272, + -154105773, + 241021040, + -438566736, + 1481110482, + 1238715604, + -438633575, + 259756757, + -177304520, + 127952220, + -94096522, + 68943663, + -49340198, + 33633505, + -20875758, + 10480374, + -2057100, + -4673566, + 9927331, + -13882775, + 16696719, + -18512964, + 19466981, + -19688104, + 19300151, + -18421092, + 17162189, + -15626890, + 13909693, + -12095129, + 10256954, + -8457628, + 6748105, + -5167954, + 3745780, + -2499933, + 1439458, + -565228, + -128788, + 654188, + -1026778, + 1265255, + -1389971, + 1421822, + -1381285, + 1287628, + -1158306, + 1008527, + -851006, + 695872, + -550710, + 420725, + -308995, + 216773, + -143843, + 88867, + -49735, + 23885, + -8572, + 19881, + -20380, + 13360, + 4790, + -38106, + 90844, + -167212, + 271036, + -405359, + 572003, + -771093, + 1000588, + -1255821, + 1529105, + -1809417, + 2082203, + -2329338, + 2529256, + -2657287, + 2686210, + -2587029, + 2329966, + -1885666, + 1226580, + -328492, + -827848, + 2255057, + -3957453, + 5929476, + -8154247, + 10602320, + -13230689, + 15982068, + -18784476, + 21551095, + -24180368, + 26556240, + -28548373, + 30012102, + -30787736, + 30698630, + -29547090, + 27106572, + -23107543, + 17212166, + -8968504, + -2275128, + 17539228, + -38574213, + 68721764, + -115320439, + 198253641, + -396485800, + 1692338571, + 977532911, + -401977006, + 254789941, + -183835054, + 140003552, + -109044996, + 85352162, + -66304368, + 50532678, + -37262461, + 26025546, + -16520282, + 8537987, + -1922063, + -3455571, + 7708248, + -10942494, + 13262317, + -14771182, + 15572465, + -15768935, + 15461647, + -14748520, + 13722796, + -12471548, + 11074337, + -9602119, + 8116429, + -6668904, + 5301125, + -4044775, + 2922101, + -1946619, + 1124025, + -453266, + -72297, + 463686, + -735109, + 902819, + -984069, + 996197, + -955850, + 878375, + -777375, + 664417, + -548896, + 438027, + -336950, + 248914, + -175535, + 117083, + -72790, + 41148, + -20196, + 34198, + -43613, + 48190, + -44315, + 27685, + 6565, + -63651, + 148856, + -267156, + 422792, + -618770, + 856325, + -1134377, + 1448988, + -1792879, + 2155015, + -2520321, + 2869541, + -3179287, + 3422297, + -3567931, + 3582904, + -3432266, + 3080614, + -2493519, + 1639129, + -489902, + -975576, + 2770762, + -4899370, + 7353699, + -10113138, + 13142903, + -16393029, + 19797667, + -23274632, + 26725194, + -30033964, + 33068721, + -35679858, + 37698982, + -38935882, + 39172579, + -38152219, + 35558723, + -30979205, + 23832572, + -13226519, + -2352146, + 25787764, + -63474546, + 133161652, + -309456656, + 1861404153, + 710555800, + -335766321, + 228319133, + -174070619, + 139317637, + -113894891, + 93738125, + -76944093, + 62530071, + -49955028, + 38906798, + -29197100, + 20705519, + -13347840, + 7057459, + -1774311, + -2561611, + 6013800, + -8650821, + 10546560, + -11779568, + 12431807, + -12587023, + 12328945, + -11739441, + 10896769, + -9873992, + 8737652, + -7546725, + 6351906, + -5195213, + 4109917, + -3120768, + 2244476, + -1490422, + 861526, + -355239, + -35401, + 320703, + -513282, + 627097, + -676578, + 675896, + -638355, + 575941, + -499012, + 416130, + -334004, + 257551, + -190033, + 133257, + -87820, + 53367, + -28855, + 46660, + -64658, + 81029, + -92473, + 94777, + -82873, + 50960, + 7281, + -98383, + 228699, + -403924, + 628552, + -905265, + 1234314, + -1612885, + 2034514, + -2488566, + 2959837, + -3428305, + 3869071, + -4252519, + 4544723, + -4708115, + 4702424, + -4485865, + 4016576, + -3254268, + 2162030, + -708255, + -1131389, + 3372006, + -6017612, + 9059430, + -12474402, + 16223974, + -20253169, + 24489952, + -28844847, + 33210697, + -37462393, + 41456245, + -45028482, + 47991993, + -50129769, + 51182216, + -50822812, + 48610538, + -43892574, + 35589802, + -21667805, + -2404746, + 49505658, + -177235756, + 1979385290, + 450597483, + -248465620, + 184115219, + -149731425, + 126513302, + -108600717, + 93631599, + -80513864, + 68705534, + -57931362, + 48054552, + -39012203, + 30780041, + -23351927, + 16727442, + -10904271, + 5873608, + -1617604, + -1891736, + 4692598, + -6832641, + 8367701, + -9360120, + 9876837, + -9987366, + 9761779, + -9268794, + 8574033, + -7738525, + 6817493, + -5859440, + 4905568, + -3989501, + 3137307, + -2367785, + 1692975, + -1118852, + 646151, + -271270, + -12783, + 215462, + -347796, + 421591, + -448722, + 440562, + -407528, + 358761, + -301934, + 243167, + -187047, + 136723, + -94067, + 59868, + -34062, + 55852, + -81310, + 108625, + -135102, + 156993, + -169454, + 166588, + -141559, + 86805, + 5642, + -143740, + 334926, + -585508, + 899998, + -1280403, + 1725494, + -2230113, + 2784533, + -3373932, + 3978011, + -4570812, + 5120751, + -5590913, + 5939625, + -6121309, + 6087628, + -5788889, + 5175697, + -4200793, + 2821046, + -999509, + -1292515, + 4073484, + -7349781, + 11114107, + -15344170, + 20001718, + -25031944, + 30363276, + -35907490, + 41560064, + -47200566, + 52692748, + -57883749, + 62601319, + -66646963, + 69780636, + -71686913, + 71896873, + -69589201, + 62993752, + -47041174, + -2431429, + 2039998499, + 209524374, + -149188825, + 127122628, + -113672506, + 103219960, + -93995379, + 85316225, + -76907097, + 68673272, + -60608709, + 52752629, + -45166383, + 37919854, + -31082829, + 24719280, + -18883533, + 13617776, + -8950616, + 4896487, + -1455760, + -1384542, + 3649564, + -5375041, + 6605458, + -7392034, + 7790618, + -7859614, + 7657989, + -7243451, + 6670847, + -5990824, + 5248784, + -4484142, + 3729884, + -3012419, + 2351686, + -1761496, + 1250059, + -820650, + 472382, + -201017, + -206, + 139768, + -227140, + 272121, + -284300, + 272608, + -245001, + 208256, + -167857, + 127992, + -91611, + 60551, + -35695 + +}; + +static const struct src_stage src_int32_10_9_4535_5000 = { + 8, 9, 10, 108, 1080, 9, 10, 0, 0, + src_int32_10_9_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_16_21_4319_5000.h b/src/audio/src/coef/src_ipc4_int32_16_21_4319_5000.h new file mode 100644 index 000000000000..3fec8272839d --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_16_21_4319_5000.h @@ -0,0 +1,1490 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_16_21_4319_5000_fir[1472] = { + 69743, + -28255, + -123867, + 279225, + -226838, + -142072, + 622543, + -739488, + 138464, + 945737, + -1634223, + 1023648, + 878742, + -2756585, + 2761408, + -140382, + -3600500, + 5326124, + -2709804, + -3275068, + 8188561, + -7179336, + -634689, + 10168471, + -13300203, + 5412670, + 9456696, + -19915603, + 15481290, + 3825200, + -24785075, + 29298153, + -9089156, + -24517771, + 45458799, + -31781997, + -14236639, + 61431600, + -68223662, + 14764766, + 73627180, + -131824041, + 90947625, + 75520213, + -327492174, + 585406486, + 1523536424, + 493312985, + -328864451, + 102332517, + 69285119, + -127203698, + 82977247, + 2140698, + -61839805, + 64027958, + -21813706, + -25643354, + 44710450, + -28509306, + -4159222, + 27080260, + -26270765, + 7206196, + 12968194, + -19851274, + 11372821, + 3276338, + -12483525, + 10952980, + -2118093, + -6186416, + 8260789, + -4109501, + -1874443, + 5064652, + -3944452, + 413312, + 2432450, + -2811905, + 1168336, + 765788, + -1570656, + 1054776, + -11566, + -661980, + 640681, + -205708, + -178056, + 269613, + -140137, + -10292, + 76282, + -46674, + -104231, + 283546, + -272909, + -73333, + 591332, + -804559, + 289982, + 814985, + -1666962, + 1267413, + 565133, + -2645574, + 3042752, + -702477, + -3178907, + 5487613, + -3506993, + -2361548, + 7954135, + -8047695, + 885206, + 9171931, + -13868538, + 7475327, + 7326401, + -19590392, + 17727743, + 319924, + -22792004, + 30974359, + -13913843, + -19985772, + 45327729, + -37395459, + -6254089, + 57584233, + -73389805, + 27362766, + 62608264, + -133973150, + 111540313, + 46021350, + -319450439, + 678073834, + 1513663140, + 402736465, + -323953371, + 126082678, + 46991880, + -120265216, + 90518799, + -10267617, + -54383288, + 65345110, + -28846174, + -19105974, + 43110431, + -31891381, + 779286, + 24371310, + -27227659, + 10399372, + 10240876, + -19404327, + 13040888, + 1108750, + -11438091, + 11513584, + -3536885, + -5090187, + 8172145, + -4850059, + -1017768, + 4710103, + -4205577, + 948040, + 2063234, + -2811653, + 1428831, + 499170, + -1478254, + 1140543, + -157226, + -573913, + 645803, + -263165, + -127627, + 255119, + -152870, + 6869, + 81620, + -65175, + -81480, + 282263, + -315223, + -711, + 547258, + -855512, + 439993, + 664555, + -1667445, + 1491898, + 233186, + -2479858, + 3269917, + -1262028, + -2686494, + 5544061, + -4249602, + -1385551, + 7559364, + -8772345, + 2412298, + 7979595, + -14173524, + 9422691, + 5020538, + -18876265, + 19659594, + -3242730, + -20323216, + 32068117, + -18537241, + -14993907, + 44306248, + -42365540, + 1984607, + 52538905, + -77214099, + 39688365, + 50095589, + -133540999, + 130629800, + 14275732, + -304433447, + 770345567, + 1494032032, + 314581580, + -313217603, + 146463224, + 24504731, + -111200866, + 96149409, + -22227342, + -46016940, + 65379831, + -35207640, + -12301995, + 40702470, + -34607764, + 5630931, + 21230682, + -27644865, + 13345731, + 7355141, + -18588982, + 14432306, + -1047707, + -10187618, + 11842930, + -4864643, + -3913555, + 7927049, + -5484030, + -156747, + 4271060, + -4380399, + 1453815, + 1661749, + -2757026, + 1655824, + 229178, + -1359524, + 1201976, + -295799, + -477316, + 638216, + -313526, + -76607, + 236232, + -161974, + 22919, + 85552, + -83361, + -55944, + 275165, + -352771, + 74456, + 490798, + -890902, + 585451, + 496931, + -1634854, + 1692182, + -110926, + -2261531, + 3437277, + -1807923, + -2131615, + 5492395, + -4922007, + -365208, + 7009290, + -9336650, + 3916676, + 6611803, + -14205099, + 11214783, + 2581731, + -17781485, + 21234355, + -6793763, + -17420162, + 32549475, + -22865831, + -9632979, + 42400594, + -46584716, + 10322629, + 46372930, + -79596115, + 51495356, + 36297140, + -130463833, + 147796485, + -19217659, + -282222379, + 861238563, + 1464872407, + 229703033, + -297179737, + 163237485, + 2250527, + -100237574, + 99804980, + -33518837, + -36917958, + 64153496, + -40786631, + -5366620, + 37545184, + -36615882, + 10303337, + 17725234, + -27522069, + 15991889, + 4369054, + -17426378, + 15524261, + -3151492, + -8759430, + 11938259, + -6077129, + -2680610, + 7532882, + -6000987, + 691867, + 3757591, + -4467182, + 1921408, + 1236444, + -2650256, + 1845663, + -38864, + -1217428, + 1238514, + -424781, + -374327, + 618473, + -356044, + -26025, + 213513, + -167438, + 37586, + 87891, + -100821, + -28028, + 262156, + -384604, + 150729, + 422696, + -909554, + 723318, + 315005, + -1569013, + 1863707, + -460652, + -1993776, + 3540273, + -2329098, + -1524024, + 5331617, + -5509686, + 680158, + 6312105, + -9726858, + 5368399, + 5092667, + -13958422, + 12814064, + 55854, + -16321908, + 22415923, + -10263399, + -14133399, + 32400037, + -26810483, + -4002375, + 39634382, + -49958407, + 18598601, + 39186808, + -80461520, + 62542395, + 21450599, + -124726595, + 162642618, + -53906822, + -252690887, + 949769031, + 1426524222, + 148894952, + -276416855, + 176241065, + -19361168, + -87631891, + 101460101, + -43939536, + -27274276, + 61711264, + -45488493, + 1564520, + 33710737, + -37887436, + 14708926, + 13927907, + -26869394, + 18291032, + 1341779, + -15944063, + 16300070, + -5162712, + -7183875, + 11801386, + -7152727, + -1416139, + 6999788, + -6392955, + 1511864, + 3181019, + -4465933, + 2342517, + 796061, + -2494537, + 1995500, + -299796, + -1055308, + 1250099, + -541924, + -267145, + 587346, + -390153, + 23136, + 187573, + -169324, + 50644, + 88476, + -117139, + 1794, + 243258, + -409859, + 226599, + 343956, + -910597, + 850621, + 122035, + -1470404, + 2002383, + -809178, + -1680831, + 3575532, + -2814756, + -874701, + 5062872, + -5999530, + 1730393, + 5479037, + -9932421, + 6738077, + 3449658, + -13434047, + 14186218, + -2508828, + -14520784, + 23175375, + -13582442, + -10521740, + 31613489, + -30288259, + 1791751, + 36048404, + -52407024, + 26649645, + 31102687, + -79764006, + 72597734, + 5819505, + -116364509, + 174800213, + -89193914, + -215809321, + 1034965630, + 1379433348, + 72881271, + -251550493, + 185382107, + -39944909, + -73664536, + 101127684, + -53307442, + -17280803, + 58120803, + -49236938, + 8357980, + 29283241, + -38408741, + 18766535, + 9916227, + -25707052, + 20203726, + -1667576, + -14175364, + 16749412, + -7043862, + -5493690, + 11438596, + -8072818, + -145132, + 6340435, + -6654520, + 2287877, + 2553685, + -4378370, + 2709908, + 349450, + -2293949, + 2103332, + -548717, + -876814, + 1237162, + -645275, + -157990, + 545809, + -415475, + 69957, + 159066, + -167768, + 61913, + 87180, + -131901, + 32986, + 218619, + -427774, + 300514, + 255829, + -893491, + 964520, + -78417, + -1340179, + 2104678, + -1149561, + -1327920, + 3540952, + -3254592, + -195668, + 4689457, + -6380127, + 2764895, + 4524184, + -9946253, + 7997464, + 1713111, + -12637994, + 15300870, + -5062569, + -12408406, + 23491647, + -16683642, + -6651220, + 30195898, + -33224133, + 7638444, + 31700101, + -53867756, + 34314533, + 22262377, + -77486718, + 81443878, + -10311145, + -105463787, + 183938663, + -124443357, + -171647569, + 1115882538, + 1324145366, + 2307237, + -223236158, + 190640355, + -59145590, + -58634631, + 98857894, + -61464162, + -7135592, + 53470627, + -51975205, + 14885024, + 24356970, + -38180775, + 22402889, + 5770743, + -24064809, + 21698569, + -4601105, + -12158666, + 16868440, + -8760520, + -3723331, + 10860451, + -8822096, + 1107704, + 5569725, + -6782893, + 3005669, + 1888685, + -4207853, + 3017532, + -94599, + -2053358, + 2168017, + -781079, + -685827, + 1200602, + -733205, + -49051, + 495008, + -431817, + 113603, + 128670, + -162967, + 71261, + 83907, + -144707, + 64956, + 188512, + -437710, + 370909, + 159797, + -858045, + 1062365, + -282546, + -1180148, + 2167702, + -1474866, + -941174, + 3435775, + -3639001, + 500239, + 4216800, + -6642017, + 3763015, + 3464282, + -9764928, + 9120032, + -84320, + -11581719, + 16132247, + -7555095, + -10021622, + 23352060, + -19503043, + -2593905, + 28165777, + -35552567, + 13424049, + 26662700, + -54296064, + 41436835, + 12824953, + -73643143, + 88882050, + -26639812, + -92161407, + 189771914, + -158990764, + -120376486, + 1191612261, + 1261297996, + -62267839, + -192152563, + 192065080, + -76643968, + -42853740, + 94736406, + -68277437, + 2963980, + 47868052, + -53666839, + 21024028, + 19034385, + -37218941, + 25553902, + 1573432, + -21981279, + 22752689, + -7403205, + -9936587, + 16659750, + -10281965, + -1908274, + 10081520, + -9388808, + 2318421, + 4704466, + -6777915, + 3652391, + 1199604, + -3959287, + 3260626, + -527528, + -1778301, + 2189281, + -992762, + -486374, + 1141757, + -804435, + 57548, + 436239, + -439172, + 153333, + 97072, + -155178, + 78604, + 78604, + -155178, + 97072, + 153333, + -439172, + 436239, + 57548, + -804435, + 1141757, + -486374, + -992762, + 2189281, + -1778301, + -527528, + 3260626, + -3959287, + 1199604, + 3652391, + -6777915, + 4704466, + 2318421, + -9388808, + 10081520, + -1908274, + -10281965, + 16659750, + -9936587, + -7403205, + 22752689, + -21981279, + 1573432, + 25553902, + -37218941, + 19034385, + 21024028, + -53666839, + 47868052, + 2963980, + -68277437, + 94736406, + -42853740, + -76643968, + 192065080, + -192152563, + -62267839, + 1261297996, + 1191612261, + -120376486, + -158990764, + 189771914, + -92161407, + -26639812, + 88882050, + -73643143, + 12824953, + 41436835, + -54296064, + 26662700, + 13424049, + -35552567, + 28165777, + -2593905, + -19503043, + 23352060, + -10021622, + -7555095, + 16132247, + -11581719, + -84320, + 9120032, + -9764928, + 3464282, + 3763015, + -6642017, + 4216800, + 500239, + -3639001, + 3435775, + -941174, + -1474866, + 2167702, + -1180148, + -282546, + 1062365, + -858045, + 159797, + 370909, + -437710, + 188512, + 64956, + -144707, + 83907, + 71261, + -162967, + 128670, + 113603, + -431817, + 495008, + -49051, + -733205, + 1200602, + -685827, + -781079, + 2168017, + -2053358, + -94599, + 3017532, + -4207853, + 1888685, + 3005669, + -6782893, + 5569725, + 1107704, + -8822096, + 10860451, + -3723331, + -8760520, + 16868440, + -12158666, + -4601105, + 21698569, + -24064809, + 5770743, + 22402889, + -38180775, + 24356970, + 14885024, + -51975205, + 53470627, + -7135592, + -61464162, + 98857894, + -58634631, + -59145590, + 190640355, + -223236158, + 2307237, + 1324145366, + 1115882538, + -171647569, + -124443357, + 183938663, + -105463787, + -10311145, + 81443878, + -77486718, + 22262377, + 34314533, + -53867756, + 31700101, + 7638444, + -33224133, + 30195898, + -6651220, + -16683642, + 23491647, + -12408406, + -5062569, + 15300870, + -12637994, + 1713111, + 7997464, + -9946253, + 4524184, + 2764895, + -6380127, + 4689457, + -195668, + -3254592, + 3540952, + -1327920, + -1149561, + 2104678, + -1340179, + -78417, + 964520, + -893491, + 255829, + 300514, + -427774, + 218619, + 32986, + -131901, + 87180, + 61913, + -167768, + 159066, + 69957, + -415475, + 545809, + -157990, + -645275, + 1237162, + -876814, + -548717, + 2103332, + -2293949, + 349450, + 2709908, + -4378370, + 2553685, + 2287877, + -6654520, + 6340435, + -145132, + -8072818, + 11438596, + -5493690, + -7043862, + 16749412, + -14175364, + -1667576, + 20203726, + -25707052, + 9916227, + 18766535, + -38408741, + 29283241, + 8357980, + -49236938, + 58120803, + -17280803, + -53307442, + 101127684, + -73664536, + -39944909, + 185382107, + -251550493, + 72881271, + 1379433348, + 1034965630, + -215809321, + -89193914, + 174800213, + -116364509, + 5819505, + 72597734, + -79764006, + 31102687, + 26649645, + -52407024, + 36048404, + 1791751, + -30288259, + 31613489, + -10521740, + -13582442, + 23175375, + -14520784, + -2508828, + 14186218, + -13434047, + 3449658, + 6738077, + -9932421, + 5479037, + 1730393, + -5999530, + 5062872, + -874701, + -2814756, + 3575532, + -1680831, + -809178, + 2002383, + -1470404, + 122035, + 850621, + -910597, + 343956, + 226599, + -409859, + 243258, + 1794, + -117139, + 88476, + 50644, + -169324, + 187573, + 23136, + -390153, + 587346, + -267145, + -541924, + 1250099, + -1055308, + -299796, + 1995500, + -2494537, + 796061, + 2342517, + -4465933, + 3181019, + 1511864, + -6392955, + 6999788, + -1416139, + -7152727, + 11801386, + -7183875, + -5162712, + 16300070, + -15944063, + 1341779, + 18291032, + -26869394, + 13927907, + 14708926, + -37887436, + 33710737, + 1564520, + -45488493, + 61711264, + -27274276, + -43939536, + 101460101, + -87631891, + -19361168, + 176241065, + -276416855, + 148894952, + 1426524222, + 949769031, + -252690887, + -53906822, + 162642618, + -124726595, + 21450599, + 62542395, + -80461520, + 39186808, + 18598601, + -49958407, + 39634382, + -4002375, + -26810483, + 32400037, + -14133399, + -10263399, + 22415923, + -16321908, + 55854, + 12814064, + -13958422, + 5092667, + 5368399, + -9726858, + 6312105, + 680158, + -5509686, + 5331617, + -1524024, + -2329098, + 3540273, + -1993776, + -460652, + 1863707, + -1569013, + 315005, + 723318, + -909554, + 422696, + 150729, + -384604, + 262156, + -28028, + -100821, + 87891, + 37586, + -167438, + 213513, + -26025, + -356044, + 618473, + -374327, + -424781, + 1238514, + -1217428, + -38864, + 1845663, + -2650256, + 1236444, + 1921408, + -4467182, + 3757591, + 691867, + -6000987, + 7532882, + -2680610, + -6077129, + 11938259, + -8759430, + -3151492, + 15524261, + -17426378, + 4369054, + 15991889, + -27522069, + 17725234, + 10303337, + -36615882, + 37545184, + -5366620, + -40786631, + 64153496, + -36917958, + -33518837, + 99804980, + -100237574, + 2250527, + 163237485, + -297179737, + 229703033, + 1464872407, + 861238563, + -282222379, + -19217659, + 147796485, + -130463833, + 36297140, + 51495356, + -79596115, + 46372930, + 10322629, + -46584716, + 42400594, + -9632979, + -22865831, + 32549475, + -17420162, + -6793763, + 21234355, + -17781485, + 2581731, + 11214783, + -14205099, + 6611803, + 3916676, + -9336650, + 7009290, + -365208, + -4922007, + 5492395, + -2131615, + -1807923, + 3437277, + -2261531, + -110926, + 1692182, + -1634854, + 496931, + 585451, + -890902, + 490798, + 74456, + -352771, + 275165, + -55944, + -83361, + 85552, + 22919, + -161974, + 236232, + -76607, + -313526, + 638216, + -477316, + -295799, + 1201976, + -1359524, + 229178, + 1655824, + -2757026, + 1661749, + 1453815, + -4380399, + 4271060, + -156747, + -5484030, + 7927049, + -3913555, + -4864643, + 11842930, + -10187618, + -1047707, + 14432306, + -18588982, + 7355141, + 13345731, + -27644865, + 21230682, + 5630931, + -34607764, + 40702470, + -12301995, + -35207640, + 65379831, + -46016940, + -22227342, + 96149409, + -111200866, + 24504731, + 146463224, + -313217603, + 314581580, + 1494032032, + 770345567, + -304433447, + 14275732, + 130629800, + -133540999, + 50095589, + 39688365, + -77214099, + 52538905, + 1984607, + -42365540, + 44306248, + -14993907, + -18537241, + 32068117, + -20323216, + -3242730, + 19659594, + -18876265, + 5020538, + 9422691, + -14173524, + 7979595, + 2412298, + -8772345, + 7559364, + -1385551, + -4249602, + 5544061, + -2686494, + -1262028, + 3269917, + -2479858, + 233186, + 1491898, + -1667445, + 664555, + 439993, + -855512, + 547258, + -711, + -315223, + 282263, + -81480, + -65175, + 81620, + 6869, + -152870, + 255119, + -127627, + -263165, + 645803, + -573913, + -157226, + 1140543, + -1478254, + 499170, + 1428831, + -2811653, + 2063234, + 948040, + -4205577, + 4710103, + -1017768, + -4850059, + 8172145, + -5090187, + -3536885, + 11513584, + -11438091, + 1108750, + 13040888, + -19404327, + 10240876, + 10399372, + -27227659, + 24371310, + 779286, + -31891381, + 43110431, + -19105974, + -28846174, + 65345110, + -54383288, + -10267617, + 90518799, + -120265216, + 46991880, + 126082678, + -323953371, + 402736465, + 1513663140, + 678073834, + -319450439, + 46021350, + 111540313, + -133973150, + 62608264, + 27362766, + -73389805, + 57584233, + -6254089, + -37395459, + 45327729, + -19985772, + -13913843, + 30974359, + -22792004, + 319924, + 17727743, + -19590392, + 7326401, + 7475327, + -13868538, + 9171931, + 885206, + -8047695, + 7954135, + -2361548, + -3506993, + 5487613, + -3178907, + -702477, + 3042752, + -2645574, + 565133, + 1267413, + -1666962, + 814985, + 289982, + -804559, + 591332, + -73333, + -272909, + 283546, + -104231, + -46674, + 76282, + -10292, + -140137, + 269613, + -178056, + -205708, + 640681, + -661980, + -11566, + 1054776, + -1570656, + 765788, + 1168336, + -2811905, + 2432450, + 413312, + -3944452, + 5064652, + -1874443, + -4109501, + 8260789, + -6186416, + -2118093, + 10952980, + -12483525, + 3276338, + 11372821, + -19851274, + 12968194, + 7206196, + -26270765, + 27080260, + -4159222, + -28509306, + 44710450, + -25643354, + -21813706, + 64027958, + -61839805, + 2140698, + 82977247, + -127203698, + 69285119, + 102332517, + -328864451, + 493312985, + 1523536424, + 585406486, + -327492174, + 75520213, + 90947625, + -131824041, + 73627180, + 14764766, + -68223662, + 61431600, + -14236639, + -31781997, + 45458799, + -24517771, + -9089156, + 29298153, + -24785075, + 3825200, + 15481290, + -19915603, + 9456696, + 5412670, + -13300203, + 10168471, + -634689, + -7179336, + 8188561, + -3275068, + -2709804, + 5326124, + -3600500, + -140382, + 2761408, + -2756585, + 878742, + 1023648, + -1634223, + 945737, + 138464, + -739488, + 622543, + -142072, + -226838, + 279225, + -123867, + -28255, + 69743 + +}; + +static const struct src_stage src_int32_16_21_4319_5000 = { + 17, 13, 16, 92, 1472, 21, 16, 0, 0, + src_int32_16_21_4319_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_16_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_16_21_4535_5000.h new file mode 100644 index 000000000000..816a41276149 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_16_21_4535_5000.h @@ -0,0 +1,2066 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_16_21_4535_5000_fir[2048] = { + 66387, + -68365, + -7975, + 136343, + -214865, + 132911, + 119132, + -389975, + 438757, + -122923, + -429393, + 828925, + -674441, + -99073, + 1049270, + -1439838, + 773191, + 718822, + -2055760, + 2109591, + -491857, + -1934203, + 3434867, + -2590106, + -489952, + 3894252, + -5020683, + 2484911, + 2521661, + -6621792, + 6445772, + -1266323, + -5907199, + 9934198, + -7114746, + -1678474, + 10818940, + -13377253, + 6200970, + 6991002, + -17223048, + 16176583, + -2639876, + -15319458, + 24843154, + -17179406, + -4967622, + 27430927, + -33190776, + 14667419, + 18807835, + -44740280, + 41705282, + -5570450, + -43712802, + 71445565, + -50172969, + -18479665, + 96941792, + -126990568, + 61008442, + 108115273, + -337882355, + 565469635, + 1558804125, + 469507748, + -334458898, + 132825574, + 37212050, + -117679328, + 102612256, + -31153014, + -40168655, + 69670990, + -49437233, + 2486071, + 36873768, + -45604773, + 23801730, + 9448110, + -31130147, + 29339803, + -8986671, + -13968864, + 24385955, + -17489313, + 357371, + 14412024, + -17643845, + 8994589, + 4148096, + -12607048, + 11630972, + -3304245, + -5849629, + 9786875, + -6793438, + -83526, + 5774244, + -6806495, + 3298840, + 1714595, + -4747829, + 4203503, + -1077867, + -2149208, + 3392544, + -2239334, + -101600, + 1897722, + -2118038, + 956950, + 547329, + -1364458, + 1135882, + -254572, + -563551, + 819425, + -499801, + -38057, + 395343, + -401688, + 161279, + 95850, + -203154, + 147275, + -25886, + -56994, + 66498, + -78756, + 10766, + 122184, + -222435, + 168232, + 73416, + -369885, + 474079, + -207093, + -348657, + 821507, + -773526, + 61297, + 939541, + -1486868, + 986843, + 462161, + -1950302, + 2281295, + -877653, + -1585105, + 3407323, + -2983779, + 115656, + 3501272, + -5194076, + 3213709, + 1683578, + -6299363, + 6993080, + -2436566, + -4890235, + 9879894, + -8248000, + -1006, + 9777064, + -13881970, + 8148397, + 4823755, + -16445792, + 17628596, + -5614051, + -12813972, + 24797247, + -20072539, + -804112, + 24940455, + -34595627, + 19646423, + 13370206, + -42949812, + 45745705, + -13623073, + -37009358, + 71784073, + -59322461, + -5179785, + 89151450, + -133932248, + 84324738, + 80081034, + -334435403, + 662397449, + 1548239836, + 375530678, + -324645315, + 153878137, + 13415800, + -106243454, + 106096112, + -42958386, + -29524696, + 66518332, + -54081541, + 10384140, + 31358651, + -45537089, + 28256247, + 4096633, + -28462582, + 30634745, + -12781526, + -10509142, + 23440083, + -19283078, + 3316812, + 12373810, + -17703302, + 10795639, + 2032413, + -11589699, + 12199126, + -4845953, + -4479673, + 9443093, + -7532445, + 1087736, + 4993505, + -6851326, + 4000094, + 918859, + -4382261, + 4423814, + -1636411, + -1670636, + 3282153, + -2494927, + 285151, + 1650566, + -2136526, + 1172007, + 314029, + -1262729, + 1198018, + -402134, + -443325, + 793527, + -558661, + 45767, + 344899, + -404985, + 199088, + 57852, + -187662, + 154858, + -42626, + -44920, + 65170, + -87900, + 29968, + 104992, + -225579, + 201024, + 24994, + -341634, + 500389, + -288804, + -259051, + 796990, + -858537, + 223315, + 808552, + -1504104, + 1183685, + 191956, + -1803172, + 2408706, + -1250996, + -1198594, + 3309524, + -3321519, + 726762, + 3031560, + -5263219, + 3885547, + 801037, + -5844203, + 7403533, + -3570150, + -3761912, + 9622865, + -9224775, + 1694387, + 8524231, + -14108096, + 9949452, + 2535474, + -15324296, + 18735160, + -8504118, + -10020594, + 24243928, + -22585795, + 3420325, + 21912948, + -35308703, + 24280658, + 7594666, + -40258527, + 48902288, + -21507313, + -29449402, + 70656801, + -67415568, + 8487832, + 79352120, + -138300380, + 106674762, + 49133364, + -323721951, + 759238249, + 1527240287, + 284509629, + -308996500, + 171018928, + -9914760, + -92963114, + 107371160, + -53676116, + -18465387, + 62072256, + -57567731, + 17966764, + 25279812, + -44549883, + 32087729, + -1277429, + -25248640, + 31296167, + -16277823, + -6872800, + 22029705, + -20668312, + 6178953, + 10105973, + -17403902, + 12359772, + -102610, + -10348362, + 12514451, + -6273275, + -3033736, + 8911942, + -8110878, + 2223877, + 4120604, + -6756996, + 4612119, + 114124, + -3932523, + 4551841, + -2154649, + -1164578, + 3106852, + -2696492, + 660610, + 1373648, + -2111510, + 1359997, + 78138, + -1137151, + 1234841, + -538909, + -316376, + 752076, + -605013, + 126870, + 288610, + -399999, + 231899, + 19719, + -168815, + 159043, + -57890, + -32423, + 62365, + -95549, + 49235, + 85033, + -224100, + 230531, + -25192, + -305615, + 516936, + -366308, + -162250, + 755546, + -927450, + 383667, + 658636, + -1490687, + 1359389, + -86445, + -1616763, + 2488552, + -1604035, + -782085, + 3142519, + -3595650, + 1330901, + 2493776, + -5225401, + 4485962, + -108407, + -5264088, + 7667154, + -4643452, + -2544094, + 9166157, + -10023394, + 3373208, + 7083843, + -14048092, + 11565782, + 171699, + -13877942, + 19470098, + -11250134, + -6993437, + 23189216, + -24663812, + 7620018, + 18404417, + -35307729, + 28471500, + 1595187, + -36710264, + 51099097, + -29059861, + -21174658, + 68063347, + -74268638, + 22251908, + 67697610, + -139936962, + 127575513, + 15755021, + -305438558, + 854919354, + 1496061653, + 197355336, + -288131413, + 184075309, + -32337033, + -78147479, + 106459236, + -63112248, + -7219540, + 56442010, + -59842147, + 25085386, + 18766959, + -42674178, + 35226056, + -6565269, + -21559249, + 31317489, + -19408016, + -3135214, + 20188132, + -21621172, + 8886874, + 7656745, + -16755367, + 13657759, + -2213556, + -8910489, + 12573213, + -7558525, + -1541905, + 8206211, + -8518795, + 3302284, + 3174268, + -6527028, + 5123577, + -683206, + -3408759, + 4586153, + -2622604, + -641647, + 2871068, + -2840697, + 1017333, + 1073016, + -2044155, + 1517531, + -155522, + -990666, + 1246042, + -662318, + -185404, + 696215, + -638170, + 203661, + 227752, + -387029, + 259170, + -17767, + -147101, + 159855, + -71416, + -19782, + 58073, + -101475, + 68159, + 62640, + -217892, + 256043, + -76138, + -262391, + 523154, + -437908, + -60111, + 697699, + -978541, + 539014, + 492555, + -1446380, + 1509997, + -367440, + -1394310, + 2518486, + -1929226, + -343712, + 2908796, + -3799704, + 1915589, + 1898086, + -5080072, + 5001785, + -1026438, + -4569444, + 7776863, + -5633815, + -1260719, + 8516934, + -10625592, + 5000932, + 5483389, + -13700192, + 12962411, + -2220014, + -12132957, + 19814561, + -13794481, + -3791954, + 21649435, + -26259535, + 11708887, + 14481306, + -34584755, + 32128243, + -4508343, + -32366873, + 52278769, + -36121923, + -12343478, + 64033096, + -79719949, + 35833884, + 54382521, + -138734255, + 146556461, + -19504816, + -279381595, + 948363084, + 1455083534, + 114906353, + -262721760, + 192956244, + -53438986, + -62128081, + 103424866, + -71101885, + 3984138, + 49758878, + -60876211, + 31602750, + 11956904, + -39958528, + 37615897, + -11661040, + -17474162, + 30705130, + -22112668, + 626975, + 17957054, + -22126804, + 11387357, + 5077536, + -15774384, + 14666053, + -4257946, + -7307228, + 12376910, + -8677189, + -34877, + 7342087, + -8749816, + 4301769, + 2174494, + -6167654, + 5525301, + -1457074, + -2822489, + 4527238, + -3031450, + -112656, + 2580398, + -2925419, + 1348364, + 755108, + -1936468, + 1641895, + -382251, + -826594, + 1231838, + -770099, + -53142, + 627360, + -657730, + 274674, + 163665, + -366530, + 280487, + -53860, + -123047, + 157386, + -82987, + -7267, + 52320, + -105481, + 86322, + 38209, + -206947, + 276918, + -126801, + -212690, + 518680, + -501990, + 45359, + 624326, + -1010418, + 686058, + 313453, + -1371579, + 1631998, + -645289, + -1139841, + 2497158, + -2219486, + 107825, + 2612245, + -3928564, + 2468581, + 1255975, + -4828883, + 5421416, + -1934349, + -3773166, + 7728653, + -6520028, + 62667, + 7686383, + -11016928, + 6543710, + 3753919, + -13068502, + 14108497, + -4591047, + -10121942, + 19757486, + -16083071, + -479774, + 19650990, + -27335266, + 15602195, + 10219246, + -33146484, + 35170039, + -10592487, + -27307186, + 52403924, + -42542500, + -3127870, + 58625094, + -83633341, + 48953360, + 39639284, + -134638196, + 163168888, + -56037654, + -245452984, + 1038501734, + 1404803435, + 37918558, + -233480100, + 197651108, + -72846013, + -45251901, + 98373127, + -77511916, + 14921575, + 42173226, + -60666633, + 37395506, + 4990720, + -36467827, + 39217653, + -16463956, + -13080251, + 29478244, + -24341565, + 4337425, + 15385608, + -22179551, + 13631922, + 2421865, + -14484201, + 15367215, + -6195083, + -5572751, + 11932189, + -9608385, + 1456675, + 6338787, + -8801217, + 5202980, + 1142137, + -5687654, + 5810455, + -2192093, + -2186356, + 4377465, + -3373669, + 411600, + 2241474, + -2949772, + 1647363, + 426620, + -1791244, + 1731089, + -597567, + -648555, + 1192959, + -860348, + 77705, + 547163, + -663575, + 338590, + 97725, + -339101, + 295568, + -87859, + -97216, + 151794, + -92435, + 4864, + 45164, + -107402, + 103310, + 12192, + -191355, + 292592, + -176114, + -157392, + 503366, + -557065, + 152045, + 536642, + -1022065, + 821615, + 124798, + -1267316, + 1722421, + -914225, + -858103, + 2424253, + -2468354, + 563439, + 2258102, + -3978591, + 2978122, + 580025, + -4475675, + 5735094, + -2813416, + -2890384, + 7521706, + -7282775, + 1399415, + 6689523, + -11187125, + 7969072, + 1929455, + -12162978, + 14978002, + -6892704, + -7883274, + 19295908, + -18066484, + 2876552, + 17229933, + -27863528, + 19218290, + 5701613, + -31014289, + 37527658, + -16532736, + -21625618, + 51458183, + -48181565, + 6289781, + 51927324, + -85901417, + 61333686, + 23734382, + -127650862, + 176995077, + -93183996, + -203664402, + 1124292532, + 1345829549, + -32943962, + -201147569, + 198227155, + -90226923, + -27874312, + 91446768, + -82243067, + 25377717, + 33851217, + -59235129, + 42356498, + -1989143, + -32281808, + 40008077, + -20880269, + -8469677, + 27668194, + -26054639, + 7921632, + 12529308, + -21782976, + 15577761, + -255749, + -12914084, + 15750202, + -7986863, + -3743533, + 11250661, + -10335249, + 2902719, + 5218140, + -8673941, + 5988772, + 98473, + -5098152, + 5974648, + -2873848, + -1513860, + 4141017, + -3643194, + 920566, + 1861817, + -2914105, + 1908735, + 94362, + -1611996, + 1783858, + -797292, + -460391, + 1130623, + -931552, + 204508, + 457474, + -655867, + 394265, + 31316, + -305467, + 304266, + -119129, + -70191, + 143298, + -99641, + 16375, + 36698, + -107116, + 118720, + -14911, + -171311, + 302596, + -223015, + -97517, + 477288, + -601799, + 257762, + 436180, + -1012863, + 942682, + -69686, + -1135247, + 1778893, + -1168573, + -554478, + 2300509, + -2670125, + 1013828, + 1852857, + -3947716, + 3433200, + -116331, + -4026432, + 5935109, + -3645287, + -1938174, + 7158447, + -7905052, + 2722308, + 5544945, + -11130320, + 9246608, + 46318, + -10999280, + 15550273, + -9077204, + -5460379, + 18435099, + -19701029, + 6208883, + 14431326, + -27827740, + 22480309, + 1017914, + -28223949, + 39145032, + -22206025, + -15430437, + 49446772, + -52913058, + 15720261, + 44055396, + -86448205, + 72707575, + 6963832, + -117831915, + 187657196, + -130242727, + -154139849, + 1204732349, + 1278871952, + -97116523, + -166481442, + 194825711, + -105298980, + -10352025, + 82822645, + -85231250, + 35150649, + 24971258, + -56627637, + 46396701, + -8841739, + -27493264, + 39980551, + -24825079, + -3737975, + 25317792, + -27222665, + 11308417, + 9448862, + -20949695, + 17188546, + -2900896, + -11098670, + 15810526, + -9598516, + -1857587, + 10348608, + -10845235, + 4274467, + 4004114, + -8372543, + 6644533, + -935237, + -4412360, + 6015992, + -3489179, + -819069, + 3823779, + -3835507, + 1404137, + 1449671, + -2819981, + 2127725, + -234879, + -1402875, + 1799705, + -977632, + -266087, + 1046501, + -982614, + 324772, + 360300, + -635044, + 440746, + -34202, + -266464, + 306569, + -147106, + -42562, + 132167, + -104540, + 27049, + 27049, + -104540, + 132167, + -42562, + -147106, + 306569, + -266464, + -34202, + 440746, + -635044, + 360300, + 324772, + -982614, + 1046501, + -266087, + -977632, + 1799705, + -1402875, + -234879, + 2127725, + -2819981, + 1449671, + 1404137, + -3835507, + 3823779, + -819069, + -3489179, + 6015992, + -4412360, + -935237, + 6644533, + -8372543, + 4004114, + 4274467, + -10845235, + 10348608, + -1857587, + -9598516, + 15810526, + -11098670, + -2900896, + 17188546, + -20949695, + 9448862, + 11308417, + -27222665, + 25317792, + -3737975, + -24825079, + 39980551, + -27493264, + -8841739, + 46396701, + -56627637, + 24971258, + 35150649, + -85231250, + 82822645, + -10352025, + -105298980, + 194825711, + -166481442, + -97116523, + 1278871952, + 1204732349, + -154139849, + -130242727, + 187657196, + -117831915, + 6963832, + 72707575, + -86448205, + 44055396, + 15720261, + -52913058, + 49446772, + -15430437, + -22206025, + 39145032, + -28223949, + 1017914, + 22480309, + -27827740, + 14431326, + 6208883, + -19701029, + 18435099, + -5460379, + -9077204, + 15550273, + -10999280, + 46318, + 9246608, + -11130320, + 5544945, + 2722308, + -7905052, + 7158447, + -1938174, + -3645287, + 5935109, + -4026432, + -116331, + 3433200, + -3947716, + 1852857, + 1013828, + -2670125, + 2300509, + -554478, + -1168573, + 1778893, + -1135247, + -69686, + 942682, + -1012863, + 436180, + 257762, + -601799, + 477288, + -97517, + -223015, + 302596, + -171311, + -14911, + 118720, + -107116, + 36698, + 16375, + -99641, + 143298, + -70191, + -119129, + 304266, + -305467, + 31316, + 394265, + -655867, + 457474, + 204508, + -931552, + 1130623, + -460391, + -797292, + 1783858, + -1611996, + 94362, + 1908735, + -2914105, + 1861817, + 920566, + -3643194, + 4141017, + -1513860, + -2873848, + 5974648, + -5098152, + 98473, + 5988772, + -8673941, + 5218140, + 2902719, + -10335249, + 11250661, + -3743533, + -7986863, + 15750202, + -12914084, + -255749, + 15577761, + -21782976, + 12529308, + 7921632, + -26054639, + 27668194, + -8469677, + -20880269, + 40008077, + -32281808, + -1989143, + 42356498, + -59235129, + 33851217, + 25377717, + -82243067, + 91446768, + -27874312, + -90226923, + 198227155, + -201147569, + -32943962, + 1345829549, + 1124292532, + -203664402, + -93183996, + 176995077, + -127650862, + 23734382, + 61333686, + -85901417, + 51927324, + 6289781, + -48181565, + 51458183, + -21625618, + -16532736, + 37527658, + -31014289, + 5701613, + 19218290, + -27863528, + 17229933, + 2876552, + -18066484, + 19295908, + -7883274, + -6892704, + 14978002, + -12162978, + 1929455, + 7969072, + -11187125, + 6689523, + 1399415, + -7282775, + 7521706, + -2890384, + -2813416, + 5735094, + -4475675, + 580025, + 2978122, + -3978591, + 2258102, + 563439, + -2468354, + 2424253, + -858103, + -914225, + 1722421, + -1267316, + 124798, + 821615, + -1022065, + 536642, + 152045, + -557065, + 503366, + -157392, + -176114, + 292592, + -191355, + 12192, + 103310, + -107402, + 45164, + 4864, + -92435, + 151794, + -97216, + -87859, + 295568, + -339101, + 97725, + 338590, + -663575, + 547163, + 77705, + -860348, + 1192959, + -648555, + -597567, + 1731089, + -1791244, + 426620, + 1647363, + -2949772, + 2241474, + 411600, + -3373669, + 4377465, + -2186356, + -2192093, + 5810455, + -5687654, + 1142137, + 5202980, + -8801217, + 6338787, + 1456675, + -9608385, + 11932189, + -5572751, + -6195083, + 15367215, + -14484201, + 2421865, + 13631922, + -22179551, + 15385608, + 4337425, + -24341565, + 29478244, + -13080251, + -16463956, + 39217653, + -36467827, + 4990720, + 37395506, + -60666633, + 42173226, + 14921575, + -77511916, + 98373127, + -45251901, + -72846013, + 197651108, + -233480100, + 37918558, + 1404803435, + 1038501734, + -245452984, + -56037654, + 163168888, + -134638196, + 39639284, + 48953360, + -83633341, + 58625094, + -3127870, + -42542500, + 52403924, + -27307186, + -10592487, + 35170039, + -33146484, + 10219246, + 15602195, + -27335266, + 19650990, + -479774, + -16083071, + 19757486, + -10121942, + -4591047, + 14108497, + -13068502, + 3753919, + 6543710, + -11016928, + 7686383, + 62667, + -6520028, + 7728653, + -3773166, + -1934349, + 5421416, + -4828883, + 1255975, + 2468581, + -3928564, + 2612245, + 107825, + -2219486, + 2497158, + -1139841, + -645289, + 1631998, + -1371579, + 313453, + 686058, + -1010418, + 624326, + 45359, + -501990, + 518680, + -212690, + -126801, + 276918, + -206947, + 38209, + 86322, + -105481, + 52320, + -7267, + -82987, + 157386, + -123047, + -53860, + 280487, + -366530, + 163665, + 274674, + -657730, + 627360, + -53142, + -770099, + 1231838, + -826594, + -382251, + 1641895, + -1936468, + 755108, + 1348364, + -2925419, + 2580398, + -112656, + -3031450, + 4527238, + -2822489, + -1457074, + 5525301, + -6167654, + 2174494, + 4301769, + -8749816, + 7342087, + -34877, + -8677189, + 12376910, + -7307228, + -4257946, + 14666053, + -15774384, + 5077536, + 11387357, + -22126804, + 17957054, + 626975, + -22112668, + 30705130, + -17474162, + -11661040, + 37615897, + -39958528, + 11956904, + 31602750, + -60876211, + 49758878, + 3984138, + -71101885, + 103424866, + -62128081, + -53438986, + 192956244, + -262721760, + 114906353, + 1455083534, + 948363084, + -279381595, + -19504816, + 146556461, + -138734255, + 54382521, + 35833884, + -79719949, + 64033096, + -12343478, + -36121923, + 52278769, + -32366873, + -4508343, + 32128243, + -34584755, + 14481306, + 11708887, + -26259535, + 21649435, + -3791954, + -13794481, + 19814561, + -12132957, + -2220014, + 12962411, + -13700192, + 5483389, + 5000932, + -10625592, + 8516934, + -1260719, + -5633815, + 7776863, + -4569444, + -1026438, + 5001785, + -5080072, + 1898086, + 1915589, + -3799704, + 2908796, + -343712, + -1929226, + 2518486, + -1394310, + -367440, + 1509997, + -1446380, + 492555, + 539014, + -978541, + 697699, + -60111, + -437908, + 523154, + -262391, + -76138, + 256043, + -217892, + 62640, + 68159, + -101475, + 58073, + -19782, + -71416, + 159855, + -147101, + -17767, + 259170, + -387029, + 227752, + 203661, + -638170, + 696215, + -185404, + -662318, + 1246042, + -990666, + -155522, + 1517531, + -2044155, + 1073016, + 1017333, + -2840697, + 2871068, + -641647, + -2622604, + 4586153, + -3408759, + -683206, + 5123577, + -6527028, + 3174268, + 3302284, + -8518795, + 8206211, + -1541905, + -7558525, + 12573213, + -8910489, + -2213556, + 13657759, + -16755367, + 7656745, + 8886874, + -21621172, + 20188132, + -3135214, + -19408016, + 31317489, + -21559249, + -6565269, + 35226056, + -42674178, + 18766959, + 25085386, + -59842147, + 56442010, + -7219540, + -63112248, + 106459236, + -78147479, + -32337033, + 184075309, + -288131413, + 197355336, + 1496061653, + 854919354, + -305438558, + 15755021, + 127575513, + -139936962, + 67697610, + 22251908, + -74268638, + 68063347, + -21174658, + -29059861, + 51099097, + -36710264, + 1595187, + 28471500, + -35307729, + 18404417, + 7620018, + -24663812, + 23189216, + -6993437, + -11250134, + 19470098, + -13877942, + 171699, + 11565782, + -14048092, + 7083843, + 3373208, + -10023394, + 9166157, + -2544094, + -4643452, + 7667154, + -5264088, + -108407, + 4485962, + -5225401, + 2493776, + 1330901, + -3595650, + 3142519, + -782085, + -1604035, + 2488552, + -1616763, + -86445, + 1359389, + -1490687, + 658636, + 383667, + -927450, + 755546, + -162250, + -366308, + 516936, + -305615, + -25192, + 230531, + -224100, + 85033, + 49235, + -95549, + 62365, + -32423, + -57890, + 159043, + -168815, + 19719, + 231899, + -399999, + 288610, + 126870, + -605013, + 752076, + -316376, + -538909, + 1234841, + -1137151, + 78138, + 1359997, + -2111510, + 1373648, + 660610, + -2696492, + 3106852, + -1164578, + -2154649, + 4551841, + -3932523, + 114124, + 4612119, + -6756996, + 4120604, + 2223877, + -8110878, + 8911942, + -3033736, + -6273275, + 12514451, + -10348362, + -102610, + 12359772, + -17403902, + 10105973, + 6178953, + -20668312, + 22029705, + -6872800, + -16277823, + 31296167, + -25248640, + -1277429, + 32087729, + -44549883, + 25279812, + 17966764, + -57567731, + 62072256, + -18465387, + -53676116, + 107371160, + -92963114, + -9914760, + 171018928, + -308996500, + 284509629, + 1527240287, + 759238249, + -323721951, + 49133364, + 106674762, + -138300380, + 79352120, + 8487832, + -67415568, + 70656801, + -29449402, + -21507313, + 48902288, + -40258527, + 7594666, + 24280658, + -35308703, + 21912948, + 3420325, + -22585795, + 24243928, + -10020594, + -8504118, + 18735160, + -15324296, + 2535474, + 9949452, + -14108096, + 8524231, + 1694387, + -9224775, + 9622865, + -3761912, + -3570150, + 7403533, + -5844203, + 801037, + 3885547, + -5263219, + 3031560, + 726762, + -3321519, + 3309524, + -1198594, + -1250996, + 2408706, + -1803172, + 191956, + 1183685, + -1504104, + 808552, + 223315, + -858537, + 796990, + -259051, + -288804, + 500389, + -341634, + 24994, + 201024, + -225579, + 104992, + 29968, + -87900, + 65170, + -44920, + -42626, + 154858, + -187662, + 57852, + 199088, + -404985, + 344899, + 45767, + -558661, + 793527, + -443325, + -402134, + 1198018, + -1262729, + 314029, + 1172007, + -2136526, + 1650566, + 285151, + -2494927, + 3282153, + -1670636, + -1636411, + 4423814, + -4382261, + 918859, + 4000094, + -6851326, + 4993505, + 1087736, + -7532445, + 9443093, + -4479673, + -4845953, + 12199126, + -11589699, + 2032413, + 10795639, + -17703302, + 12373810, + 3316812, + -19283078, + 23440083, + -10509142, + -12781526, + 30634745, + -28462582, + 4096633, + 28256247, + -45537089, + 31358651, + 10384140, + -54081541, + 66518332, + -29524696, + -42958386, + 106096112, + -106243454, + 13415800, + 153878137, + -324645315, + 375530678, + 1548239836, + 662397449, + -334435403, + 80081034, + 84324738, + -133932248, + 89151450, + -5179785, + -59322461, + 71784073, + -37009358, + -13623073, + 45745705, + -42949812, + 13370206, + 19646423, + -34595627, + 24940455, + -804112, + -20072539, + 24797247, + -12813972, + -5614051, + 17628596, + -16445792, + 4823755, + 8148397, + -13881970, + 9777064, + -1006, + -8248000, + 9879894, + -4890235, + -2436566, + 6993080, + -6299363, + 1683578, + 3213709, + -5194076, + 3501272, + 115656, + -2983779, + 3407323, + -1585105, + -877653, + 2281295, + -1950302, + 462161, + 986843, + -1486868, + 939541, + 61297, + -773526, + 821507, + -348657, + -207093, + 474079, + -369885, + 73416, + 168232, + -222435, + 122184, + 10766, + -78756, + 66498, + -56994, + -25886, + 147275, + -203154, + 95850, + 161279, + -401688, + 395343, + -38057, + -499801, + 819425, + -563551, + -254572, + 1135882, + -1364458, + 547329, + 956950, + -2118038, + 1897722, + -101600, + -2239334, + 3392544, + -2149208, + -1077867, + 4203503, + -4747829, + 1714595, + 3298840, + -6806495, + 5774244, + -83526, + -6793438, + 9786875, + -5849629, + -3304245, + 11630972, + -12607048, + 4148096, + 8994589, + -17643845, + 14412024, + 357371, + -17489313, + 24385955, + -13968864, + -8986671, + 29339803, + -31130147, + 9448110, + 23801730, + -45604773, + 36873768, + 2486071, + -49437233, + 69670990, + -40168655, + -31153014, + 102612256, + -117679328, + 37212050, + 132825574, + -334458898, + 469507748, + 1558804125, + 565469635, + -337882355, + 108115273, + 61008442, + -126990568, + 96941792, + -18479665, + -50172969, + 71445565, + -43712802, + -5570450, + 41705282, + -44740280, + 18807835, + 14667419, + -33190776, + 27430927, + -4967622, + -17179406, + 24843154, + -15319458, + -2639876, + 16176583, + -17223048, + 6991002, + 6200970, + -13377253, + 10818940, + -1678474, + -7114746, + 9934198, + -5907199, + -1266323, + 6445772, + -6621792, + 2521661, + 2484911, + -5020683, + 3894252, + -489952, + -2590106, + 3434867, + -1934203, + -491857, + 2109591, + -2055760, + 718822, + 773191, + -1439838, + 1049270, + -99073, + -674441, + 828925, + -429393, + -122923, + 438757, + -389975, + 119132, + 132911, + -214865, + 136343, + -7975, + -68365, + 66387 + +}; + +static const struct src_stage src_int32_16_21_4535_5000 = { + 17, 13, 16, 128, 2048, 21, 16, 0, 0, + src_int32_16_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_16_7_4082_5000.h b/src/audio/src/coef/src_ipc4_int32_16_7_4082_5000.h new file mode 100644 index 000000000000..b4b00eb4d21e --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_16_7_4082_5000.h @@ -0,0 +1,914 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_16_7_4082_5000_fir[896] = { + -71000, + 181977, + -339747, + 514730, + -642937, + 623137, + -323239, + -401654, + 1679004, + -3578587, + 6067334, + -8966927, + 11923457, + -14398381, + 15688234, + -14976743, + 11417821, + -4241994, + -7126799, + 22961410, + -43148370, + 67151258, + -94039786, + 122607578, + -151628250, + 180432616, + -210773274, + 259076840, + 1947647635, + 130626618, + -154773011, + 151454781, + -137592690, + 117980232, + -95457731, + 72242420, + -50138040, + 30524524, + -14320909, + 1977209, + 6490183, + -11422722, + 13415829, + -13203199, + 11545845, + -9139682, + 6550799, + -4182013, + 2269009, + -900187, + 51848, + 370353, + -491710, + 436451, + -306522, + 171648, + -70391, + 186699, + -363701, + 580541, + -781081, + 867879, + -704724, + 130932, + 1011139, + -2836467, + 5369772, + -8497053, + 11925446, + -15161363, + 17515632, + -18141219, + 16104105, + -10481793, + 477487, + 14467885, + -34588463, + 59758444, + -89545448, + 123416467, + -161265407, + 204885044, + -263646258, + 396589889, + 1926989848, + 13074551, + -97466614, + 119030754, + -119746955, + 109794340, + -93839528, + 74931699, + -55376953, + 36942076, + -20888343, + 7980349, + 1482651, + -7601390, + 10782113, + -11625678, + 10815575, + -9019043, + 6811876, + -4632457, + 2765338, + -1350191, + 408865, + 117992, + -332957, + 348995, + -265778, + 156553, + -66816, + 185114, + -376845, + 630823, + -900728, + 1095966, + -1080198, + 681363, + 284415, + -1975021, + 4473717, + -7735938, + 11540417, + -15454927, + 18826485, + -20803307, + 20391227, + -16541123, + 8256800, + 5294461, + -24693937, + 50240728, + -82031755, + 120260434, + -166033295, + 223823441, + -311544383, + 541078368, + 1886070430, + -92030629, + -40604412, + 84295618, + -98774996, + 98411930, + -89318831, + 75196551, + -58743989, + 42040184, + -26637610, + 13583591, + -3444858, + -3640262, + 7879962, + -9726386, + 9766112, + -8617928, + 6849605, + -4920993, + 3155750, + -1739318, + 737227, + -125894, + -172188, + 255762, + -219399, + 137634, + -60055, + 176703, + -377913, + 662869, + -996802, + 1298925, + -1436896, + 1232166, + -479495, + -1018242, + 3401808, + -6699180, + 10769263, + -15256074, + 19564074, + -22863466, + 24130242, + -22219677, + 15964472, + -4280175, + -13749340, + 38847723, + -71653933, + 113114569, + -165597181, + 236383192, + -352640165, + 690243965, + 1825672611, + -183453915, + 14175215, + 48405294, + -75432700, + 84283041, + -82116040, + 73090848, + -60179759, + 45690692, + -31407662, + 18620253, + -8138988, + 332045, + 4808243, + -7574379, + 8440053, + -7957754, + 6670155, + -5044161, + 3431835, + -2057663, + 1027729, + -353910, + -14688, + 160137, + -169329, + 115892, + -50001, + 161166, + -365990, + 674444, + -1064760, + 1468720, + -1762114, + 1765144, + -1256862, + 5885, + 2183210, + -5411885, + 9625506, + -14557182, + 19688753, + -24239046, + 27186119, + -27324414, + 23349995, + -13957432, + -2080248, + 25895842, + -58663209, + 102080062, + -159773708, + 241854815, + -385173729, + 841624335, + 1746948752, + -260293225, + 65382741, + 12502206, + -50522718, + 67929338, + -72529145, + 68741262, + -59686950, + 47814099, + -35072225, + 22945638, + -12457623, + 4189906, + 1668516, + -5244769, + 6887504, + -7067492, + 6286392, + -5003883, + 3589146, + -2297983, + 1272785, + -559529, + 134647, + 65383, + -117502, + 92344, + -36677, + 138445, + -340558, + 663886, + -1100774, + 1598045, + -2043641, + 2261948, + -2022614, + 1066167, + 852875, + -3908144, + 8135225, + -13366687, + 19179704, + -24867415, + 29442480, + -31675976, + 30167005, + -23427936, + 9956137, + 11759943, + -43401531, + 87384951, + -148542032, + 239711822, + -407500085, + 992644605, + 1651393997, + -321990304, + 111709328, + -22317434, + -24868698, + 49925999, + -60922406, + 62341466, + -57328720, + 48380871, + -37542933, + 26441066, + -16274103, + 7814591, + -1438255, + -2816172, + 5164266, + -5982509, + 5717246, + -4807217, + 3627190, + -2455827, + 1466599, + -737263, + 271450, + -25465, + -65776, + 67985, + -20251, + 108749, + -301551, + 630207, + -1101903, + 1680608, + -2270190, + 2704687, + -2751118, + 2129123, + -549425, + -2230196, + 6336583, + -11709266, + 18036125, + -24708519, + 30805842, + -35114838, + 36181334, + -32381215, + 21981657, + -3137108, + -26293266, + 69380930, + -132050403, + 229634432, + -418134912, + 1140672290, + 1540812181, + -368333231, + 152052889, + -55033849, + 710301, + 30882490, + -47713286, + 54144393, + -53225231, + 47411163, + -38771192, + 29016978, + -19480834, + 11097842, + -4414887, + -368113, + 3329895, + -4743244, + 4986914, + -4465947, + 3549299, + -2529561, + 1605283, + -882790, + 391997, + -109689, + -15871, + 43753, + -1038, + 72570, + -249380, + 573162, + -1066243, + 1711393, + -2431816, + 3076542, + -3417010, + 3160005, + -1980242, + -427294, + 4278931, + -9625492, + 16277805, + -23746773, + 31209235, + -37506956, + 41178875, + -40515667, + 33608789, + -18336679, + -7834068, + 48536196, + -110617832, + 211528341, + -415797633, + 1283074330, + 1417274836, + -399450590, + 185537861, + -84730643, + 25424456, + 11422824, + -33358072, + 44452849, + -47548486, + 44972980, + -38748748, + 30615045, + -21992213, + 13945033, + -7170959, + 2021526, + 1445691, + -3393764, + 4123908, + -3996045, + 3362376, + -2520312, + 1686888, + -993042, + 493300, + -184956, + 30680, + 20500, + 20500, + 30680, + -184956, + 493300, + -993042, + 1686888, + -2520312, + 3362376, + -3996045, + 4123908, + -3393764, + 1445691, + 2021526, + -7170959, + 13945033, + -21992213, + 30615045, + -38748748, + 44972980, + -47548486, + 44452849, + -33358072, + 11422824, + 25424456, + -84730643, + 185537861, + -399450590, + 1417274836, + 1283074330, + -415797633, + 211528341, + -110617832, + 48536196, + -7834068, + -18336679, + 33608789, + -40515667, + 41178875, + -37506956, + 31209235, + -23746773, + 16277805, + -9625492, + 4278931, + -427294, + -1980242, + 3160005, + -3417010, + 3076542, + -2431816, + 1711393, + -1066243, + 573162, + -249380, + 72570, + -1038, + 43753, + -15871, + -109689, + 391997, + -882790, + 1605283, + -2529561, + 3549299, + -4465947, + 4986914, + -4743244, + 3329895, + -368113, + -4414887, + 11097842, + -19480834, + 29016978, + -38771192, + 47411163, + -53225231, + 54144393, + -47713286, + 30882490, + 710301, + -55033849, + 152052889, + -368333231, + 1540812181, + 1140672290, + -418134912, + 229634432, + -132050403, + 69380930, + -26293266, + -3137108, + 21981657, + -32381215, + 36181334, + -35114838, + 30805842, + -24708519, + 18036125, + -11709266, + 6336583, + -2230196, + -549425, + 2129123, + -2751118, + 2704687, + -2270190, + 1680608, + -1101903, + 630207, + -301551, + 108749, + -20251, + 67985, + -65776, + -25465, + 271450, + -737263, + 1466599, + -2455827, + 3627190, + -4807217, + 5717246, + -5982509, + 5164266, + -2816172, + -1438255, + 7814591, + -16274103, + 26441066, + -37542933, + 48380871, + -57328720, + 62341466, + -60922406, + 49925999, + -24868698, + -22317434, + 111709328, + -321990304, + 1651393997, + 992644605, + -407500085, + 239711822, + -148542032, + 87384951, + -43401531, + 11759943, + 9956137, + -23427936, + 30167005, + -31675976, + 29442480, + -24867415, + 19179704, + -13366687, + 8135225, + -3908144, + 852875, + 1066167, + -2022614, + 2261948, + -2043641, + 1598045, + -1100774, + 663886, + -340558, + 138445, + -36677, + 92344, + -117502, + 65383, + 134647, + -559529, + 1272785, + -2297983, + 3589146, + -5003883, + 6286392, + -7067492, + 6887504, + -5244769, + 1668516, + 4189906, + -12457623, + 22945638, + -35072225, + 47814099, + -59686950, + 68741262, + -72529145, + 67929338, + -50522718, + 12502206, + 65382741, + -260293225, + 1746948752, + 841624335, + -385173729, + 241854815, + -159773708, + 102080062, + -58663209, + 25895842, + -2080248, + -13957432, + 23349995, + -27324414, + 27186119, + -24239046, + 19688753, + -14557182, + 9625506, + -5411885, + 2183210, + 5885, + -1256862, + 1765144, + -1762114, + 1468720, + -1064760, + 674444, + -365990, + 161166, + -50001, + 115892, + -169329, + 160137, + -14688, + -353910, + 1027729, + -2057663, + 3431835, + -5044161, + 6670155, + -7957754, + 8440053, + -7574379, + 4808243, + 332045, + -8138988, + 18620253, + -31407662, + 45690692, + -60179759, + 73090848, + -82116040, + 84283041, + -75432700, + 48405294, + 14175215, + -183453915, + 1825672611, + 690243965, + -352640165, + 236383192, + -165597181, + 113114569, + -71653933, + 38847723, + -13749340, + -4280175, + 15964472, + -22219677, + 24130242, + -22863466, + 19564074, + -15256074, + 10769263, + -6699180, + 3401808, + -1018242, + -479495, + 1232166, + -1436896, + 1298925, + -996802, + 662869, + -377913, + 176703, + -60055, + 137634, + -219399, + 255762, + -172188, + -125894, + 737227, + -1739318, + 3155750, + -4920993, + 6849605, + -8617928, + 9766112, + -9726386, + 7879962, + -3640262, + -3444858, + 13583591, + -26637610, + 42040184, + -58743989, + 75196551, + -89318831, + 98411930, + -98774996, + 84295618, + -40604412, + -92030629, + 1886070430, + 541078368, + -311544383, + 223823441, + -166033295, + 120260434, + -82031755, + 50240728, + -24693937, + 5294461, + 8256800, + -16541123, + 20391227, + -20803307, + 18826485, + -15454927, + 11540417, + -7735938, + 4473717, + -1975021, + 284415, + 681363, + -1080198, + 1095966, + -900728, + 630823, + -376845, + 185114, + -66816, + 156553, + -265778, + 348995, + -332957, + 117992, + 408865, + -1350191, + 2765338, + -4632457, + 6811876, + -9019043, + 10815575, + -11625678, + 10782113, + -7601390, + 1482651, + 7980349, + -20888343, + 36942076, + -55376953, + 74931699, + -93839528, + 109794340, + -119746955, + 119030754, + -97466614, + 13074551, + 1926989848, + 396589889, + -263646258, + 204885044, + -161265407, + 123416467, + -89545448, + 59758444, + -34588463, + 14467885, + 477487, + -10481793, + 16104105, + -18141219, + 17515632, + -15161363, + 11925446, + -8497053, + 5369772, + -2836467, + 1011139, + 130932, + -704724, + 867879, + -781081, + 580541, + -363701, + 186699, + -70391, + 171648, + -306522, + 436451, + -491710, + 370353, + 51848, + -900187, + 2269009, + -4182013, + 6550799, + -9139682, + 11545845, + -13203199, + 13415829, + -11422722, + 6490183, + 1977209, + -14320909, + 30524524, + -50138040, + 72242420, + -95457731, + 117980232, + -137592690, + 151454781, + -154773011, + 130626618, + 1947647635, + 259076840, + -210773274, + 180432616, + -151628250, + 122607578, + -94039786, + 67151258, + -43148370, + 22961410, + -7126799, + -4241994, + 11417821, + -14976743, + 15688234, + -14398381, + 11923457, + -8966927, + 6067334, + -3578587, + 1679004, + -401654, + -323239, + 623137, + -642937, + 514730, + -339747, + 181977, + -71000 + +}; + +static const struct src_stage src_int32_16_7_4082_5000 = { + 3, 7, 16, 56, 896, 7, 16, 0, 0, + src_int32_16_7_4082_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_2_2268_5000.h b/src/audio/src/coef/src_ipc4_int32_1_2_2268_5000.h new file mode 100644 index 000000000000..8ac49de99916 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_2_2268_5000.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_2268_5000_fir[36] = { + 1065827, + -37924, + -4976218, + -6930718, + 4279551, + 21769810, + 16870789, + -24264128, + -59858104, + -22375073, + 82035869, + 129391394, + -840158, + -230528780, + -263826821, + 146723259, + 884581891, + 1474403183, + 1474403183, + 884581891, + 146723259, + -263826821, + -230528780, + -840158, + 129391394, + 82035869, + -22375073, + -59858104, + -24264128, + 16870789, + 21769810, + 4279551, + -6930718, + -4976218, + -37924, + 1065827 + +}; + +static const struct src_stage src_int32_1_2_2268_5000 = { + 1, 0, 1, 36, 36, 2, 1, 0, 1, + src_int32_1_2_2268_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_2_2500_5000.h b/src/audio/src/coef/src_ipc4_int32_1_2_2500_5000.h new file mode 100644 index 000000000000..99ac5b22e7f4 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_2_2500_5000.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_2500_5000_fir[40] = { + -879692, + 460291, + 4237437, + 3956471, + -6093558, + -15785611, + -4442365, + 26033472, + 34997100, + -10844043, + -71022878, + -51916314, + 66653219, + 151087631, + 38864919, + -218002245, + -297189224, + 101966883, + 879379751, + 1516022404, + 1516022404, + 879379751, + 101966883, + -297189224, + -218002245, + 38864919, + 151087631, + 66653219, + -51916314, + -71022878, + -10844043, + 34997100, + 26033472, + -4442365, + -15785611, + -6093558, + 3956471, + 4237437, + 460291, + -879692 + +}; + +static const struct src_stage src_int32_1_2_2500_5000 = { + 1, 0, 1, 40, 40, 2, 1, 0, 1, + src_int32_1_2_2500_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_2_2721_5000.h b/src/audio/src/coef/src_ipc4_int32_1_2_2721_5000.h new file mode 100644 index 000000000000..cbaa50a52342 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_2_2721_5000.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_2721_5000_fir[44] = { + 776925, + -535235, + -3522824, + -2444452, + 5917358, + 11269101, + -867107, + -22071386, + -18949580, + 20828497, + 50471960, + 10939725, + -71198097, + -79917279, + 41805826, + 162982902, + 78340788, + -197899192, + -324285843, + 57614628, + 871924302, + 1556302633, + 1556302633, + 871924302, + 57614628, + -324285843, + -197899192, + 78340788, + 162982902, + 41805826, + -79917279, + -71198097, + 10939725, + 50471960, + 20828497, + -18949580, + -22071386, + -867107, + 11269101, + 5917358, + -2444452, + -3522824, + -535235, + 776925 + +}; + +static const struct src_stage src_int32_1_2_2721_5000 = { + 1, 0, 1, 44, 44, 2, 1, 0, 1, + src_int32_1_2_2721_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_2_3401_5000.h b/src/audio/src/coef/src_ipc4_int32_1_2_3401_5000.h new file mode 100644 index 000000000000..147fdc0258b8 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_2_3401_5000.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_3401_5000_fir[60] = { + 483288, + -83413, + -1522435, + -938206, + 2636503, + 3681228, + -2450750, + -8114060, + -1045017, + 12628842, + 9520768, + -13717683, + -22790928, + 6658192, + 37370618, + 12635584, + -45920069, + -45019652, + 38158895, + 85685863, + -3107032, + -122755134, + -68634449, + 136670038, + 185878247, + -95907401, + -373310419, + -84065810, + 830120456, + 1674737585, + 1674737585, + 830120456, + -84065810, + -373310419, + -95907401, + 185878247, + 136670038, + -68634449, + -122755134, + -3107032, + 85685863, + 38158895, + -45019652, + -45920069, + 12635584, + 37370618, + 6658192, + -22790928, + -13717683, + 9520768, + 12628842, + -1045017, + -8114060, + -2450750, + 3681228, + 2636503, + -938206, + -1522435, + -83413, + 483288 + +}; + +static const struct src_stage src_int32_1_2_3401_5000 = { + 1, 0, 1, 60, 60, 2, 1, 0, 1, + src_int32_1_2_3401_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_2_3887_5000.h b/src/audio/src/coef/src_ipc4_int32_1_2_3887_5000.h new file mode 100644 index 000000000000..5e3fb20738a0 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_2_3887_5000.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_3887_5000_fir[84] = { + 488732, + -7737, + -1049640, + -480672, + 1654700, + 1551531, + -1998132, + -3286585, + 1634033, + 5554715, + -54239, + -7926978, + -3173634, + 9645492, + 8225873, + -9675800, + -14835521, + 6857625, + 22145090, + -146638, + -28646177, + -11084667, + 32239598, + 26738727, + -30422902, + -45736325, + 20574564, + 65858143, + -258704, + -83689620, + -32584447, + 94583414, + 79805611, + -92335107, + -144142149, + 67556625, + 233227412, + -336805, + -377316523, + -184860995, + 786654445, + 1756537314, + 1756537314, + 786654445, + -184860995, + -377316523, + -336805, + 233227412, + 67556625, + -144142149, + -92335107, + 79805611, + 94583414, + -32584447, + -83689620, + -258704, + 65858143, + 20574564, + -45736325, + -30422902, + 26738727, + 32239598, + -11084667, + -28646177, + -146638, + 22145090, + 6857625, + -14835521, + -9675800, + 8225873, + 9645492, + -3173634, + -7926978, + -54239, + 5554715, + 1634033, + -3286585, + -1998132, + 1551531, + 1654700, + -480672, + -1049640, + -7737, + 488732 + +}; + +static const struct src_stage src_int32_1_2_3887_5000 = { + 1, 0, 1, 84, 84, 2, 1, 0, 1, + src_int32_1_2_3887_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_2_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_1_2_4535_5000.h new file mode 100644 index 000000000000..f9a2d9e1ed55 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_2_4535_5000.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_4535_5000_fir[192] = { + -215107, + -43725, + 301513, + 112783, + -392680, + -217153, + 481408, + 362073, + -558370, + -551376, + 612196, + 786886, + -629703, + -1067814, + 596275, + 1390179, + -496400, + -1746306, + 314363, + 2124419, + -35075, + -2508384, + -354975, + 2877622, + 866679, + -3207226, + -1507215, + 3468317, + 2278940, + -3628632, + -3178326, + 3653367, + 4194987, + -3506257, + -5310846, + 3150891, + 6499495, + -2552210, + -7725804, + 1678175, + 8945799, + -501532, + -10106851, + -998364, + 11148187, + 2833747, + -12001726, + -5006707, + 12593223, + 7507600, + -12843685, + -10313656, + 12671011, + 13387835, + -11991777, + -16677958, + 10723077, + 20116119, + -8784292, + -23618380, + 6098649, + 27084650, + -2594385, + -30398678, + -1794713, + 33427929, + 7129695, + -36023066, + -13468167, + 38016538, + 20867983, + -39219511, + -29393852, + 39415841, + 39128533, + -38350872, + -50191507, + 35710943, + 62770710, + -31085683, + -77178576, + 23896443, + 93957014, + -13253147, + -114090197, + -2355533, + 139483332, + 25812595, + -174203100, + -63511615, + 228417736, + 133202247, + -335834511, + -309495855, + 710609576, + 1861497547, + 1861497547, + 710609576, + -309495855, + -335834511, + 133202247, + 228417736, + -63511615, + -174203100, + 25812595, + 139483332, + -2355533, + -114090197, + -13253147, + 93957014, + 23896443, + -77178576, + -31085683, + 62770710, + 35710943, + -50191507, + -38350872, + 39128533, + 39415841, + -29393852, + -39219511, + 20867983, + 38016538, + -13468167, + -36023066, + 7129695, + 33427929, + -1794713, + -30398678, + -2594385, + 27084650, + 6098649, + -23618380, + -8784292, + 20116119, + 10723077, + -16677958, + -11991777, + 13387835, + 12671011, + -10313656, + -12843685, + 7507600, + 12593223, + -5006707, + -12001726, + 2833747, + 11148187, + -998364, + -10106851, + -501532, + 8945799, + 1678175, + -7725804, + -2552210, + 6499495, + 3150891, + -5310846, + -3506257, + 4194987, + 3653367, + -3178326, + -3628632, + 2278940, + 3468317, + -1507215, + -3207226, + 866679, + 2877622, + -354975, + -2508384, + -35075, + 2124419, + 314363, + -1746306, + -496400, + 1390179, + 596275, + -1067814, + -629703, + 786886, + 612196, + -551376, + -558370, + 362073, + 481408, + -217153, + -392680, + 112783, + 301513, + -43725, + -215107 + +}; + +static const struct src_stage src_int32_1_2_4535_5000 = { + 1, 0, 1, 192, 192, 2, 1, 0, 1, + src_int32_1_2_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_3_2268_5000.h b/src/audio/src/coef/src_ipc4_int32_1_3_2268_5000.h new file mode 100644 index 000000000000..8c088177f4f0 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_3_2268_5000.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_3_2268_5000_fir[52] = { + 856478, + -618891, + -4156030, + -7632810, + -6818565, + 1656056, + 16118818, + 27894919, + 24749076, + -411480, + -40481660, + -72304526, + -66986467, + -9640846, + 82715496, + 159386491, + 157990435, + 43550535, + -155941521, + -341868521, + -378168860, + -155895577, + 341322420, + 1007548608, + 1642469336, + 2029634383, + 2029634383, + 1642469336, + 1007548608, + 341322420, + -155895577, + -378168860, + -341868521, + -155941521, + 43550535, + 157990435, + 159386491, + 82715496, + -9640846, + -66986467, + -72304526, + -40481660, + -411480, + 24749076, + 27894919, + 16118818, + 1656056, + -6818565, + -7632810, + -4156030, + -618891, + 856478 + +}; + +static const struct src_stage src_int32_1_3_2268_5000 = { + 1, 0, 1, 52, 52, 3, 1, 0, 2, + src_int32_1_3_2268_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_3_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_1_3_4535_5000.h new file mode 100644 index 000000000000..d13e60802e5a --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_3_4535_5000.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_3_4535_5000_fir[260] = { + -76785, + 87265, + 208768, + 143311, + -91428, + -291261, + -237325, + 74523, + 379517, + 361661, + -28240, + -466882, + -517592, + -56163, + 544523, + 704317, + 187358, + -601461, + -918470, + -373348, + 624747, + 1153692, + 620778, + -599799, + -1400284, + -934187, + 510895, + 1644990, + 1315237, + -341829, + -1870928, + -1761941, + 76723, + 2057715, + 2267958, + 299041, + -2181780, + -2821960, + -797771, + 2216900, + 3407156, + 1428358, + -2134954, + -4000973, + -2195140, + 1906879, + 4574965, + 3096789, + -1503824, + -5094947, + -4125273, + 898460, + 5521388, + 5264939, + -66412, + -5810072, + -6491765, + -1012233, + 5913000, + 7772827, + 2351404, + -5779529, + -9065995, + -3957556, + 5357703, + 10319889, + 5828281, + -4595720, + -11474083, + -7951066, + 3443473, + 12459524, + 10302239, + -1854065, + -13199130, + -12846149, + -214774, + 13608457, + 15534559, + 2799523, + -13596308, + -18306256, + -5930062, + 13065077, + 21086791, + 9629415, + -11910557, + -23788232, + -13914258, + 10020744, + 26308687, + 18796483, + -7273010, + -28531232, + -24286296, + 3528546, + 30321589, + 30397571, + 1377742, + -31523426, + -37156789, + -7655160, + 31949227, + 44618015, + 15589261, + -31362703, + -52888891, + -25600885, + 29444353, + 62178457, + 38360881, + -25720991, + -72892462, + -55030816, + 19410514, + 85844434, + 77824887, + -9039792, + -102793355, + -111534471, + -8665166, + 128114385, + 168709269, + 42966778, + -175928536, + -295557039, + -134844775, + 328546725, + 908616507, + 1308982144, + 1308982144, + 908616507, + 328546725, + -134844775, + -295557039, + -175928536, + 42966778, + 168709269, + 128114385, + -8665166, + -111534471, + -102793355, + -9039792, + 77824887, + 85844434, + 19410514, + -55030816, + -72892462, + -25720991, + 38360881, + 62178457, + 29444353, + -25600885, + -52888891, + -31362703, + 15589261, + 44618015, + 31949227, + -7655160, + -37156789, + -31523426, + 1377742, + 30397571, + 30321589, + 3528546, + -24286296, + -28531232, + -7273010, + 18796483, + 26308687, + 10020744, + -13914258, + -23788232, + -11910557, + 9629415, + 21086791, + 13065077, + -5930062, + -18306256, + -13596308, + 2799523, + 15534559, + 13608457, + -214774, + -12846149, + -13199130, + -1854065, + 10302239, + 12459524, + 3443473, + -7951066, + -11474083, + -4595720, + 5828281, + 10319889, + 5357703, + -3957556, + -9065995, + -5779529, + 2351404, + 7772827, + 5913000, + -1012233, + -6491765, + -5810072, + -66412, + 5264939, + 5521388, + 898460, + -4125273, + -5094947, + -1503824, + 3096789, + 4574965, + 1906879, + -2195140, + -4000973, + -2134954, + 1428358, + 3407156, + 2216900, + -797771, + -2821960, + -2181780, + 299041, + 2267958, + 2057715, + 76723, + -1761941, + -1870928, + -341829, + 1315237, + 1644990, + 510895, + -934187, + -1400284, + -599799, + 620778, + 1153692, + 624747, + -373348, + -918470, + -601461, + 187358, + 704317, + 544523, + -56163, + -517592, + -466882, + -28240, + 361661, + 379517, + 74523, + -237325, + -291261, + -91428, + 143311, + 208768, + 87265, + -76785 + +}; + +static const struct src_stage src_int32_1_3_4535_5000 = { + 1, 0, 1, 260, 260, 3, 1, 0, 1, + src_int32_1_3_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_4_1512_5000.h b/src/audio/src/coef/src_ipc4_int32_1_4_1512_5000.h new file mode 100644 index 000000000000..fa07fd026a7d --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_4_1512_5000.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_4_1512_5000_fir[52] = { + 740488, + -111252, + -2633435, + -6735884, + -11195687, + -13616262, + -11012690, + -1023972, + 16558462, + 38533507, + 57994984, + 65518799, + 51906082, + 11944874, + -51911760, + -127334308, + -192579065, + -220169940, + -183352843, + -63854654, + 141210867, + 415517370, + 724354420, + 1020448166, + 1253648120, + 1382122910, + 1382122910, + 1253648120, + 1020448166, + 724354420, + 415517370, + 141210867, + -63854654, + -183352843, + -220169940, + -192579065, + -127334308, + -51911760, + 11944874, + 51906082, + 65518799, + 57994984, + 38533507, + 16558462, + -1023972, + -11012690, + -13616262, + -11195687, + -6735884, + -2633435, + -111252, + 740488 + +}; + +static const struct src_stage src_int32_1_4_1512_5000 = { + 1, 0, 1, 52, 52, 4, 1, 0, 2, + src_int32_1_4_1512_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_4_2268_5000.h b/src/audio/src/coef/src_ipc4_int32_1_4_2268_5000.h new file mode 100644 index 000000000000..b65fec0b639b --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_4_2268_5000.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_4_2268_5000_fir[60] = { + -1265010, + -1300023, + 42822, + 3109879, + 7266626, + 10678204, + 10716856, + 5057661, + -6842471, + -22524966, + -36328631, + -40730932, + -29172521, + 439006, + 42945561, + 85397568, + 109745573, + 98640017, + 42867564, + -52102133, + -163243125, + -252756038, + -276759404, + -198009096, + 1005375, + 308925926, + 683904209, + 1060916279, + 1366611903, + 1537730619, + 1537730619, + 1366611903, + 1060916279, + 683904209, + 308925926, + 1005375, + -198009096, + -276759404, + -252756038, + -163243125, + -52102133, + 42867564, + 98640017, + 109745573, + 85397568, + 42945561, + 439006, + -29172521, + -40730932, + -36328631, + -22524966, + -6842471, + 5057661, + 10716856, + 10678204, + 7266626, + 3109879, + 42822, + -1300023, + -1265010 + +}; + +static const struct src_stage src_int32_1_4_2268_5000 = { + 1, 0, 1, 60, 60, 4, 1, 0, 2, + src_int32_1_4_2268_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_4_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_1_4_4535_5000.h new file mode 100644 index 000000000000..07aae148bd91 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_4_4535_5000.h @@ -0,0 +1,350 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_4_4535_5000_fir[332] = { + -246503, + -173077, + 24381, + 252177, + 377027, + 301219, + 30356, + -310151, + -529423, + -475213, + -132489, + 344481, + 696707, + 697984, + 293999, + -339844, + -868103, + -969329, + -526081, + 278813, + 1028786, + 1285068, + 838131, + -142520, + -1159828, + -1636277, + -1236621, + -88441, + 1238401, + 2008652, + 1723920, + 432889, + -1238256, + -2382056, + -2297124, + -907740, + 1130496, + 2730331, + 2946947, + 1526538, + -884654, + -3021392, + -3656755, + -2297885, + 470054, + 3217664, + 4401807, + 3223848, + 142559, + -3276881, + -5148778, + -4298406, + -979184, + 3153252, + 5855610, + 5506027, + 2060568, + -2798987, + -6471750, + -6820446, + -3400132, + 2166155, + 6938799, + 8203726, + 5001896, + -1208821, + -7191580, + -9605671, + -6858499, + -114593, + 7159633, + 10963628, + 8949389, + 1838821, + -6769068, + -12202718, + -11239274, + -3989221, + 5944756, + 13236507, + 13676901, + 6579293, + -4612736, + -13968065, + -16194199, + -9608367, + 2702763, + 14291375, + 18705810, + 13059530, + -150839, + -14092967, + -21108977, + -16897884, + -3098411, + 13253629, + 23283705, + 21069184, + 7089696, + -11649964, + -25093054, + -25498856, + -11855544, + 9155499, + 26383293, + 30091367, + 17415555, + -5640914, + -26983525, + -34729804, + -23776689, + 972800, + 26704174, + 39275432, + 30934966, + 4989964, + -25333334, + -43566765, + -38879109, + -12403623, + 22629406, + 47417420, + 47596961, + 21453102, + -18307251, + -50611382, + -57086157, + -32375935, + 12012944, + 52893248, + 67371776, + 45504524, + -3277549, + -53948650, + -78536488, + -61342992, + -8569783, + 53364854, + 90775153, + 80714356, + 24573661, + -50548636, + -104502205, + -105064566, + -46519201, + 44543066, + 120586810, + 137159554, + 77804433, + -33571919, + -140945845, + -182932703, + -125865579, + 13702399, + 170365384, + 257548631, + 210729619, + 26276478, + -224136854, + -413843251, + -410883356, + -137302800, + 388026441, + 1043749476, + 1643018293, + 2000102871, + 2000102871, + 1643018293, + 1043749476, + 388026441, + -137302800, + -410883356, + -413843251, + -224136854, + 26276478, + 210729619, + 257548631, + 170365384, + 13702399, + -125865579, + -182932703, + -140945845, + -33571919, + 77804433, + 137159554, + 120586810, + 44543066, + -46519201, + -105064566, + -104502205, + -50548636, + 24573661, + 80714356, + 90775153, + 53364854, + -8569783, + -61342992, + -78536488, + -53948650, + -3277549, + 45504524, + 67371776, + 52893248, + 12012944, + -32375935, + -57086157, + -50611382, + -18307251, + 21453102, + 47596961, + 47417420, + 22629406, + -12403623, + -38879109, + -43566765, + -25333334, + 4989964, + 30934966, + 39275432, + 26704174, + 972800, + -23776689, + -34729804, + -26983525, + -5640914, + 17415555, + 30091367, + 26383293, + 9155499, + -11855544, + -25498856, + -25093054, + -11649964, + 7089696, + 21069184, + 23283705, + 13253629, + -3098411, + -16897884, + -21108977, + -14092967, + -150839, + 13059530, + 18705810, + 14291375, + 2702763, + -9608367, + -16194199, + -13968065, + -4612736, + 6579293, + 13676901, + 13236507, + 5944756, + -3989221, + -11239274, + -12202718, + -6769068, + 1838821, + 8949389, + 10963628, + 7159633, + -114593, + -6858499, + -9605671, + -7191580, + -1208821, + 5001896, + 8203726, + 6938799, + 2166155, + -3400132, + -6820446, + -6471750, + -2798987, + 2060568, + 5506027, + 5855610, + 3153252, + -979184, + -4298406, + -5148778, + -3276881, + 142559, + 3223848, + 4401807, + 3217664, + 470054, + -2297885, + -3656755, + -3021392, + -884654, + 1526538, + 2946947, + 2730331, + 1130496, + -907740, + -2297124, + -2382056, + -1238256, + 432889, + 1723920, + 2008652, + 1238401, + -88441, + -1236621, + -1636277, + -1159828, + -142520, + 838131, + 1285068, + 1028786, + 278813, + -526081, + -969329, + -868103, + -339844, + 293999, + 697984, + 696707, + 344481, + -132489, + -475213, + -529423, + -310151, + 30356, + 301219, + 377027, + 252177, + 24381, + -173077, + -246503 + +}; + +static const struct src_stage src_int32_1_4_4535_5000 = { + 1, 0, 1, 332, 332, 4, 1, 0, 2, + src_int32_1_4_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_1_6_1134_5000.h b/src/audio/src/coef/src_ipc4_int32_1_6_1134_5000.h new file mode 100644 index 000000000000..9e20a2f4ffed --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_1_6_1134_5000.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_6_1134_5000_fir[68] = { + -2393808, + -3445469, + -3907601, + -3162834, + -592531, + 4265214, + 11534891, + 20833185, + 31148750, + 40812354, + 47589891, + 48915133, + 42256782, + 25588647, + -2093376, + -40283739, + -86595435, + -136587507, + -183858208, + -220439457, + -237487389, + -226218223, + -178995243, + -90438502, + 41589680, + 215268956, + 424497505, + 659040825, + 905175263, + 1146784177, + 1366802025, + 1548850271, + 1678876871, + 1746603493, + 1746603493, + 1678876871, + 1548850271, + 1366802025, + 1146784177, + 905175263, + 659040825, + 424497505, + 215268956, + 41589680, + -90438502, + -178995243, + -226218223, + -237487389, + -220439457, + -183858208, + -136587507, + -86595435, + -40283739, + -2093376, + 25588647, + 42256782, + 48915133, + 47589891, + 40812354, + 31148750, + 20833185, + 11534891, + 4265214, + -592531, + -3162834, + -3907601, + -3445469, + -2393808 + +}; + +static const struct src_stage src_int32_1_6_1134_5000 = { + 1, 0, 1, 68, 68, 6, 1, 0, 3, + src_int32_1_6_1134_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_20_21_1250_5000.h b/src/audio/src/coef/src_ipc4_int32_20_21_1250_5000.h new file mode 100644 index 000000000000..83409ba4cda2 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_20_21_1250_5000.h @@ -0,0 +1,338 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_1250_5000_fir[320] = { + 134710, + 1035873, + -9174506, + 3254060, + 57810592, + -88005063, + -143444475, + 641574554, + 1277866655, + 589381984, + -158566396, + -75502200, + 57643382, + 717921, + -8455000, + 1117437, + 178901, + 918686, + -9857309, + 6001455, + 57355502, + -100513261, + -125686439, + 693510525, + 1273767662, + 537218180, + -171105540, + -63126885, + 56901319, + -1596043, + -7711998, + 1166890, + 230158, + 762547, + -10489344, + 8945528, + 56234279, + -112896214, + -105256653, + 744900240, + 1265596079, + 485362120, + -181131884, + -50992284, + 55634710, + -3680424, + -6957736, + 1187855, + 288377, + 564393, + -11055804, + 12067940, + 54407460, + -125015764, + -82138107, + 795451914, + 1253404488, + 434084379, + -188730873, + -39201961, + 53895987, + -5531148, + -6203405, + 1183986, + 353246, + 321515, + -11541296, + 15346522, + 51840708, + -136727085, + -56333212, + 844873857, + 1237271212, + 383645227, + -194002144, + -27849438, + 51738985, + -7147272, + -5459088, + 1158912, + 424226, + 31644, + -11930004, + 18755255, + 48505557, + -147879690, + -27864429, + 892876709, + 1217299656, + 334292840, + -197058169, + -17017871, + 49218259, + -8530750, + -4733723, + 1116170, + 500527, + -306956, + -12205883, + 22264298, + 44380132, + -158318551, + 3225254, + 939175705, + 1193617447, + 286261651, + -198022819, + -6779854, + 46388428, + -9686185, + -4035077, + 1059161, + 581093, + -695399, + -12352866, + 25840065, + 39449846, + -167885303, + 36872023, + 983492906, + 1166375368, + 239770846, + -197029888, + 2802676, + 43303560, + -10620564, + -3369752, + 991105, + 664592, + -1134087, + -12355093, + 29445361, + 33708048, + -176419538, + 72991113, + 1025559415, + 1135746104, + 195023021, + -194221561, + 11678415, + 40016605, + -11342982, + -2743196, + 915002, + 749400, + -1622625, + -12197157, + 33039563, + 27156629, + -183760172, + 111476871, + 1065117527, + 1101922813, + 152203006, + -189746877, + 19806570, + 36578872, + -11864360, + -2159738, + 833605, + 833605, + -2159738, + -11864360, + 36578872, + 19806570, + -189746877, + 152203006, + 1101922813, + 1065117527, + 111476871, + -183760172, + 27156629, + 33039563, + -12197157, + -1622625, + 749400, + 915002, + -2743196, + -11342982, + 40016605, + 11678415, + -194221561, + 195023021, + 1135746104, + 1025559415, + 72991113, + -176419538, + 33708048, + 29445361, + -12355093, + -1134087, + 664592, + 991105, + -3369752, + -10620564, + 43303560, + 2802676, + -197029888, + 239770846, + 1166375368, + 983492906, + 36872023, + -167885303, + 39449846, + 25840065, + -12352866, + -695399, + 581093, + 1059161, + -4035077, + -9686185, + 46388428, + -6779854, + -198022819, + 286261651, + 1193617447, + 939175705, + 3225254, + -158318551, + 44380132, + 22264298, + -12205883, + -306956, + 500527, + 1116170, + -4733723, + -8530750, + 49218259, + -17017871, + -197058169, + 334292840, + 1217299656, + 892876709, + -27864429, + -147879690, + 48505557, + 18755255, + -11930004, + 31644, + 424226, + 1158912, + -5459088, + -7147272, + 51738985, + -27849438, + -194002144, + 383645227, + 1237271212, + 844873857, + -56333212, + -136727085, + 51840708, + 15346522, + -11541296, + 321515, + 353246, + 1183986, + -6203405, + -5531148, + 53895987, + -39201961, + -188730873, + 434084379, + 1253404488, + 795451914, + -82138107, + -125015764, + 54407460, + 12067940, + -11055804, + 564393, + 288377, + 1187855, + -6957736, + -3680424, + 55634710, + -50992284, + -181131884, + 485362120, + 1265596079, + 744900240, + -105256653, + -112896214, + 56234279, + 8945528, + -10489344, + 762547, + 230158, + 1166890, + -7711998, + -1596043, + 56901319, + -63126885, + -171105540, + 537218180, + 1273767662, + 693510525, + -125686439, + -100513261, + 57355502, + 6001455, + -9857309, + 918686, + 178901, + 1117437, + -8455000, + 717921, + 57643382, + -75502200, + -158566396, + 589381984, + 1277866655, + 641574554, + -143444475, + -88005063, + 57810592, + 3254060, + -9174506, + 1035873, + 134710 + +}; + +static const struct src_stage src_int32_20_21_1250_5000 = { + 1, 1, 20, 16, 320, 21, 20, 0, 0, + src_int32_20_21_1250_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_20_21_2500_5000.h b/src/audio/src/coef/src_ipc4_int32_20_21_2500_5000.h new file mode 100644 index 000000000000..d2f606331586 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_20_21_2500_5000.h @@ -0,0 +1,578 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_2500_5000_fir[560] = { + -5217, + -381011, + 1487277, + -1690900, + -2689840, + 12331080, + -17806571, + 1976049, + 40826925, + -81879606, + 60543056, + 73708682, + -307850958, + 561160322, + 1533115988, + 487060887, + -306822452, + 91076688, + 46915636, + -78187169, + 43712565, + -1931276, + -15874974, + 12298891, + -3291738, + -1287661, + 1382937, + -390774, + -17588, + -362655, + 1577955, + -2100730, + -2009370, + 12193372, + -19594189, + 6039578, + 37269743, + -84638938, + 73946416, + 54556008, + -304853844, + 635957075, + 1526538845, + 414158608, + -302006692, + 106525654, + 33244906, + -73646092, + 45917204, + -5638268, + -13831959, + 12106423, + -3811576, + -896328, + 1267711, + -392704, + -32583, + -335032, + 1652192, + -2511335, + -1255216, + 11878075, + -21205675, + 10211009, + 33059988, + -86389665, + 86940418, + 33781184, + -297622812, + 710935536, + 1513436879, + 342933211, + -293668877, + 119949784, + 19705004, + -68348375, + 47440642, + -9105381, + -11710025, + 11764988, + -4247236, + -521679, + 1144321, + -387635, + -50199, + -297585, + 1707246, + -2916470, + -433682, + 11379637, + -22609759, + 14438357, + 28226280, + -87066606, + 99337405, + 11574093, + -285982618, + 785568879, + 1493914213, + 273840219, + -282097608, + 131271964, + 6461555, + -62392089, + 48291564, + -12297981, + -9541176, + 11287342, + -4597922, + -167909, + 1015398, + -376443, + -70363, + -249889, + 1740470, + -3309520, + 447531, + 10694852, + -23776544, + 18666512, + 22806900, + -86616182, + 110949669, + -11849136, + -269793780, + 859323773, + 1468125768, + 207307162, + -267601290, + 140443531, + -6330063, + -55879877, + 48487068, + -15186604, + -7356499, + 10687436, + -4864093, + 161390, + 883445, + -360033, + -92929, + -191675, + 1749360, + -3683587, + 1379349, + 9823024, + -24678000, + 22837871, + 16849669, + -84997582, + 121591844, + -36247582, + -248954971, + 931665220, + 1436275752, + 143730103, + -250504416, + 147443730, + -18526264, + -48917466, + 48052105, + -17747119, + -5185789, + 9980150, + -5047384, + 463243, + 750803, + -339317, + -117669, + -122851, + 1731614, + -4031581, + 2351388, + 8766114, + -25288452, + 26893025, + 10411693, + -82183813, + 131083353, + -61357316, + -223405061, + 1002061451, + 1398615679, + 83470546, + -231143775, + 152278872, + -29996589, + -41612182, + 47018825, + -19960824, + -3057198, + 9181043, + -5150508, + 735300, + 619630, + -315194, + -144273, + -43518, + 1685185, + -4346315, + 3352030, + 7528852, + -25585054, + 30771504, + 3558967, + -78162606, + 139250888, + -86893508, + -193124782, + 1069988842, + 1355441931, + 26852715, + -209864628, + 154981202, + -40624841, + -34071510, + 45425868, + -21814461, + -996927, + 8306090, + -5177160, + 975824, + 491876, + -288539, + -172346, + 46012, + 1608337, + -4620620, + 4368522, + 6118815, + -25548254, + 34412575, + -3634151, + -72937156, + 145930896, + -112552824, + -158137997, + 1134936791, + 1307092888, + -25838740, + -187016893, + 155607513, + -50309997, + -26401698, + 43317584, + -23300151, + 971037, + 7371443, + -5131896, + 1183680, + 369265, + -260183, + -201410, + 145204, + 1499697, + -4847452, + 5387111, + 4546465, + -25162225, + 37756064, + -11085604, + -66526700, + 150972026, + -138016120, + -118512538, + 1196412508, + 1253945671, + -74360608, + -162951380, + 154237520, + -58966894, + -18706433, + 40743221, + -24415264, + 2825145, + 6393184, + -5020018, + 1358309, + 253291, + -230902, + -230902, + 253291, + 1358309, + -5020018, + 6393184, + 2825145, + -24415264, + 40743221, + -18706433, + -58966894, + 154237520, + -162951380, + -74360608, + 1253945671, + 1196412508, + -118512538, + -138016120, + 150972026, + -66526700, + -11085604, + 37756064, + -25162225, + 4546465, + 5387111, + -4847452, + 1499697, + 145204, + -201410, + -260183, + 369265, + 1183680, + -5131896, + 7371443, + 971037, + -23300151, + 43317584, + -26401698, + -50309997, + 155607513, + -187016893, + -25838740, + 1307092888, + 1134936791, + -158137997, + -112552824, + 145930896, + -72937156, + -3634151, + 34412575, + -25548254, + 6118815, + 4368522, + -4620620, + 1608337, + 46012, + -172346, + -288539, + 491876, + 975824, + -5177160, + 8306090, + -996927, + -21814461, + 45425868, + -34071510, + -40624841, + 154981202, + -209864628, + 26852715, + 1355441931, + 1069988842, + -193124782, + -86893508, + 139250888, + -78162606, + 3558967, + 30771504, + -25585054, + 7528852, + 3352030, + -4346315, + 1685185, + -43518, + -144273, + -315194, + 619630, + 735300, + -5150508, + 9181043, + -3057198, + -19960824, + 47018825, + -41612182, + -29996589, + 152278872, + -231143775, + 83470546, + 1398615679, + 1002061451, + -223405061, + -61357316, + 131083353, + -82183813, + 10411693, + 26893025, + -25288452, + 8766114, + 2351388, + -4031581, + 1731614, + -122851, + -117669, + -339317, + 750803, + 463243, + -5047384, + 9980150, + -5185789, + -17747119, + 48052105, + -48917466, + -18526264, + 147443730, + -250504416, + 143730103, + 1436275752, + 931665220, + -248954971, + -36247582, + 121591844, + -84997582, + 16849669, + 22837871, + -24678000, + 9823024, + 1379349, + -3683587, + 1749360, + -191675, + -92929, + -360033, + 883445, + 161390, + -4864093, + 10687436, + -7356499, + -15186604, + 48487068, + -55879877, + -6330063, + 140443531, + -267601290, + 207307162, + 1468125768, + 859323773, + -269793780, + -11849136, + 110949669, + -86616182, + 22806900, + 18666512, + -23776544, + 10694852, + 447531, + -3309520, + 1740470, + -249889, + -70363, + -376443, + 1015398, + -167909, + -4597922, + 11287342, + -9541176, + -12297981, + 48291564, + -62392089, + 6461555, + 131271964, + -282097608, + 273840219, + 1493914213, + 785568879, + -285982618, + 11574093, + 99337405, + -87066606, + 28226280, + 14438357, + -22609759, + 11379637, + -433682, + -2916470, + 1707246, + -297585, + -50199, + -387635, + 1144321, + -521679, + -4247236, + 11764988, + -11710025, + -9105381, + 47440642, + -68348375, + 19705004, + 119949784, + -293668877, + 342933211, + 1513436879, + 710935536, + -297622812, + 33781184, + 86940418, + -86389665, + 33059988, + 10211009, + -21205675, + 11878075, + -1255216, + -2511335, + 1652192, + -335032, + -32583, + -392704, + 1267711, + -896328, + -3811576, + 12106423, + -13831959, + -5638268, + 45917204, + -73646092, + 33244906, + 106525654, + -302006692, + 414158608, + 1526538845, + 635957075, + -304853844, + 54556008, + 73946416, + -84638938, + 37269743, + 6039578, + -19594189, + 12193372, + -2009370, + -2100730, + 1577955, + -362655, + -17588, + -390774, + 1382937, + -1287661, + -3291738, + 12298891, + -15874974, + -1931276, + 43712565, + -78187169, + 46915636, + 91076688, + -306822452, + 487060887, + 1533115988, + 561160322, + -307850958, + 73708682, + 60543056, + -81879606, + 40826925, + 1976049, + -17806571, + 12331080, + -2689840, + -1690900, + 1487277, + -381011, + -5217 + +}; + +static const struct src_stage src_int32_20_21_2500_5000 = { + 1, 1, 20, 28, 560, 21, 20, 0, 0, + src_int32_20_21_2500_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_20_21_3125_5000.h b/src/audio/src/coef/src_ipc4_int32_20_21_3125_5000.h new file mode 100644 index 000000000000..8465b979b4ce --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_20_21_3125_5000.h @@ -0,0 +1,658 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_3125_5000_fir[640] = { + 81905, + -392860, + 605436, + 300103, + -3389413, + 8014282, + -10208077, + 3564589, + 16012885, + -43514692, + 61128982, + -42872462, + -31996397, + 163558261, + -325254357, + 481892944, + 1660757494, + 397250675, + -310525371, + 172858105, + -46841667, + -31806158, + 56625130, + -44127246, + 18774985, + 1041917, + -8903567, + 7769313, + -3624056, + 564329, + 469229, + -355162, + 85040, + -427192, + 743071, + 11542, + -3084775, + 8144080, + -11414371, + 6142167, + 12890575, + -42207257, + 64857380, + -53682850, + -16096415, + 151346135, + -335823373, + 568337876, + 1652465793, + 315050248, + -292061980, + 179233448, + -60453939, + -20656226, + 51439973, + -44061041, + 21149217, + -1389895, + -7525299, + 7418834, + -3789037, + 801552, + 336669, + -315167, + 86071, + -457054, + 879706, + -298067, + -2710984, + 8150442, + -12498431, + 8736273, + 9442493, + -40199062, + 67724765, + -64062781, + 657562, + 136276469, + -341837441, + 655914744, + 1635958368, + 235893058, + -270314485, + 182713163, + -72679127, + -9590248, + 45674542, + -43341832, + 23114876, + -3697776, + -6097764, + 6973685, + -3885791, + 1009725, + 209742, + -273889, + 84635, + -481329, + 1012734, + -624841, + -2270106, + 8026717, + -13437095, + 11306623, + 5709579, + -37494934, + 69655788, + -73838034, + 18044538, + 118447422, + -342937782, + 743927943, + 1611386328, + 160337003, + -245751918, + 183365304, + -83388708, + 1231202, + 39435012, + -42004270, + 24658259, + -5851928, + -4645104, + 6445650, + -3916774, + 1187420, + 90180, + -232277, + 80393, + -498911, + 1139409, + -964328, + -1765470, + 7768056, + -14208471, + 13811592, + 1738878, + -34110732, + 70586835, + -82837355, + 35825759, + 98000917, + -338807128, + 831664027, + 1578974237, + 88891325, + -218855969, + 181294725, + -92480682, + 11656683, + 32830936, + -40091065, + 25772608, + -7826160, + -3190746, + 5847224, + -3885363, + 1333816, + -20548, + -191192, + 73044, + -508727, + 1256887, + -1311555, + -1201681, + 7371588, + -14792360, + 16208834, + -2416972, + -30073492, + 70467421, + -90895161, + 53747579, + 75122412, + -329174645, + 918399033, + 1539017619, + 22012098, + -190114896, + 176640304, + -99880123, + 21545811, + 25973489, + -37652047, + 26457952, + -9598138, + -1757068, + 5191374, + -3795748, + 1448671, + -121251, + -151407, + 62330, + -509762, + 1362269, + -1661081, + -584611, + 6836567, + -15170657, + 18455927, + -6700351, + -25421424, + 69261432, + -97854234, + 71544640, + 50040091, + -313820417, + 1003405995, + 1491879688, + -39901629, + -160017532, + 169571790, + -105539320, + 30770951, + 18973747, + -34743154, + 26720841, + -11149579, + -365090, + 4491309, + -3652821, + 1532290, + -211009, + -113590, + 48054, + -501092, + 1452661, + -2007061, + 78628, + 6164492, + -15327749, + 20511054, + -11049386, + -20203711, + 66948187, + -103568398, + 88943327, + 23023457, + -292579406, + 1085962581, + 1437987328, + -96510959, + -129047423, + 160286353, + -109437537, + 39218672, + 11941028, + -31425365, + 26574003, + -12466362, + 965793, + 3760256, + -3462053, + 1585483, + -289176, + -78303, + 30087, + -481903, + 1525219, + -2343333, + 779736, + 5359191, + -15250880, + 22333702, + -15398762, + -14480148, + 63523293, + -107905107, + 105665464, + -5618654, + -265344842, + 1165358739, + 1377826384, + -147539552, + -97677201, + 149004868, + -111580385, + 46790943, + 4981314, + -27763590, + 26035900, + -13538574, + 2218043, + 3011245, + -3229370, + 1609524, + -355368, + -46001, + 8381, + -451524, + 1577214, + -2663499, + 1509303, + 4426880, + -14930484, + 23885362, + -19680621, + -8320591, + 58999292, + -110747924, + 121432192, + -35540636, + -232070994, + 1240904285, + 1311936316, + -192775258, + -66363236, + 135968007, + -111998838, + 53406057, + -1804227, + -23825546, + 25130232, + -14360490, + 3376169, + 2256909, + -2961030, + 1606091, + -409451, + -17027, + -17027, + -409451, + 1606091, + -2961030, + 2256909, + 3376169, + -14360490, + 25130232, + -23825546, + -1804227, + 53406057, + -111998838, + 135968007, + -66363236, + -192775258, + 1311936316, + 1240904285, + -232070994, + -35540636, + 121432192, + -110747924, + 58999292, + -8320591, + -19680621, + 23885362, + -14930484, + 4426880, + 1509303, + -2663499, + 1577214, + -451524, + 8381, + -46001, + -355368, + 1609524, + -3229370, + 3011245, + 2218043, + -13538574, + 26035900, + -27763590, + 4981314, + 46790943, + -111580385, + 149004868, + -97677201, + -147539552, + 1377826384, + 1165358739, + -265344842, + -5618654, + 105665464, + -107905107, + 63523293, + -14480148, + -15398762, + 22333702, + -15250880, + 5359191, + 779736, + -2343333, + 1525219, + -481903, + 30087, + -78303, + -289176, + 1585483, + -3462053, + 3760256, + 965793, + -12466362, + 26574003, + -31425365, + 11941028, + 39218672, + -109437537, + 160286353, + -129047423, + -96510959, + 1437987328, + 1085962581, + -292579406, + 23023457, + 88943327, + -103568398, + 66948187, + -20203711, + -11049386, + 20511054, + -15327749, + 6164492, + 78628, + -2007061, + 1452661, + -501092, + 48054, + -113590, + -211009, + 1532290, + -3652821, + 4491309, + -365090, + -11149579, + 26720841, + -34743154, + 18973747, + 30770951, + -105539320, + 169571790, + -160017532, + -39901629, + 1491879688, + 1003405995, + -313820417, + 50040091, + 71544640, + -97854234, + 69261432, + -25421424, + -6700351, + 18455927, + -15170657, + 6836567, + -584611, + -1661081, + 1362269, + -509762, + 62330, + -151407, + -121251, + 1448671, + -3795748, + 5191374, + -1757068, + -9598138, + 26457952, + -37652047, + 25973489, + 21545811, + -99880123, + 176640304, + -190114896, + 22012098, + 1539017619, + 918399033, + -329174645, + 75122412, + 53747579, + -90895161, + 70467421, + -30073492, + -2416972, + 16208834, + -14792360, + 7371588, + -1201681, + -1311555, + 1256887, + -508727, + 73044, + -191192, + -20548, + 1333816, + -3885363, + 5847224, + -3190746, + -7826160, + 25772608, + -40091065, + 32830936, + 11656683, + -92480682, + 181294725, + -218855969, + 88891325, + 1578974237, + 831664027, + -338807128, + 98000917, + 35825759, + -82837355, + 70586835, + -34110732, + 1738878, + 13811592, + -14208471, + 7768056, + -1765470, + -964328, + 1139409, + -498911, + 80393, + -232277, + 90180, + 1187420, + -3916774, + 6445650, + -4645104, + -5851928, + 24658259, + -42004270, + 39435012, + 1231202, + -83388708, + 183365304, + -245751918, + 160337003, + 1611386328, + 743927943, + -342937782, + 118447422, + 18044538, + -73838034, + 69655788, + -37494934, + 5709579, + 11306623, + -13437095, + 8026717, + -2270106, + -624841, + 1012734, + -481329, + 84635, + -273889, + 209742, + 1009725, + -3885791, + 6973685, + -6097764, + -3697776, + 23114876, + -43341832, + 45674542, + -9590248, + -72679127, + 182713163, + -270314485, + 235893058, + 1635958368, + 655914744, + -341837441, + 136276469, + 657562, + -64062781, + 67724765, + -40199062, + 9442493, + 8736273, + -12498431, + 8150442, + -2710984, + -298067, + 879706, + -457054, + 86071, + -315167, + 336669, + 801552, + -3789037, + 7418834, + -7525299, + -1389895, + 21149217, + -44061041, + 51439973, + -20656226, + -60453939, + 179233448, + -292061980, + 315050248, + 1652465793, + 568337876, + -335823373, + 151346135, + -16096415, + -53682850, + 64857380, + -42207257, + 12890575, + 6142167, + -11414371, + 8144080, + -3084775, + 11542, + 743071, + -427192, + 85040, + -355162, + 469229, + 564329, + -3624056, + 7769313, + -8903567, + 1041917, + 18774985, + -44127246, + 56625130, + -31806158, + -46841667, + 172858105, + -310525371, + 397250675, + 1660757494, + 481892944, + -325254357, + 163558261, + -31996397, + -42872462, + 61128982, + -43514692, + 16012885, + 3564589, + -10208077, + 8014282, + -3389413, + 300103, + 605436, + -392860, + 81905 + +}; + +static const struct src_stage src_int32_20_21_3125_5000 = { + 1, 1, 20, 32, 640, 21, 20, 0, 0, + src_int32_20_21_3125_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_20_21_4167_5000.h b/src/audio/src/coef/src_ipc4_int32_20_21_4167_5000.h new file mode 100644 index 000000000000..efd2acc0b5d3 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_20_21_4167_5000.h @@ -0,0 +1,1218 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_4167_5000_fir[1200] = { + 54594, + -184742, + 399571, + -658518, + 861269, + -851629, + 446851, + 506433, + -2057748, + 4077609, + -6206641, + 7855337, + -8274384, + 6701021, + -2566737, + -4269788, + 13317348, + -23333796, + 32346120, + -37837888, + 37098628, + -27690412, + 7951641, + 22564477, + -62823233, + 110306567, + -161354961, + 211990326, + -259927731, + 314839940, + 1873379169, + 215491521, + -221514039, + 197320210, + -159656245, + 115973574, + -72096251, + 32736308, + -1246683, + -20590936, + 32566108, + -35809536, + 32387034, + -24807635, + 15544221, + -6650474, + -472699, + 5145742, + -7333833, + 7470380, + -6237460, + 4357194, + -2433974, + 867412, + 164426, + -667587, + 764968, + -624055, + 398759, + -195416, + 43238, + -169492, + 392350, + -681472, + 944507, + -1025690, + 729890, + 124716, + -1631247, + 3712230, + -6055926, + 8098799, + -9077562, + 8161302, + -4654454, + -1760919, + 10794317, + -21388236, + 31688761, + -39182884, + 41007303, + -34393248, + 17172429, + 11761004, + -52154438, + 102399786, + -160019741, + 223130608, + -295370812, + 418757223, + 1861619486, + 121585995, + -180938977, + 179507723, + -155038512, + 119348862, + -79830871, + 42099624, + -10251559, + -13234422, + 27505465, + -33147847, + 31821757, + -25790751, + 17438761, + -8860838, + 1588279, + 3526614, + -6276554, + 6954395, + -6150700, + 4547922, + -2754212, + 1201447, + -112058, + -477407, + 657946, + -579247, + 390334, + -201577, + 29845, + -149700, + 376823, + -691937, + 1012509, + -1185987, + 1008030, + -270937, + -1161328, + 3265862, + -5785257, + 8192781, + -9724911, + 9496601, + -6695788, + 830718, + 8017650, + -18999306, + 30416262, + -39806607, + 44206546, + -40564824, + 26241059, + 518202, + -40261822, + 92348363, + -155588638, + 230403614, + -327043027, + 526291365, + 1838233518, + 33909370, + -139008627, + 158982186, + -147666218, + 120423629, + -85915825, + 50495962, + -18898756, + -5762762, + 22020590, + -29913804, + 30671712, + -26273686, + 18971697, + -10862747, + 3578220, + 1875337, + -5124938, + 6320082, + -5950842, + 4648489, + -3013960, + 1503024, + -377556, + -284919, + 542664, + -525409, + 374846, + -203377, + 14563, + -125502, + 352878, + -689145, + 1063324, + -1328876, + 1275675, + -673253, + -655878, + 2745008, + -5396895, + 8131995, + -10200560, + 10678701, + -8650757, + 3457234, + 5035520, + -16204346, + 28541675, + -39684190, + 46622712, + -46078140, + 34982496, + -10959499, + -27344081, + 80289871, + -148055257, + 233529472, + -354165424, + 636423647, + 1803486252, + -46849040, + -96514102, + 136206154, + -137749135, + 119231396, + -90272589, + 57787842, + -27033714, + 1682545, + 16221460, + -26178009, + 28968884, + -26256525, + 20121089, + -12622717, + 5461241, + 223559, + -3902664, + 5582075, + -5644391, + 4659328, + -3209989, + 1767405, + -627390, + -93863, + 421648, + -463978, + 352963, + -201054, + -2404, + -97141, + 320572, + -672562, + 1095269, + -1450932, + 1527256, + -1074609, + -123700, + 2157782, + -4895429, + 7914013, + -10491594, + 11681732, + -10480224, + 6069141, + 1900938, + -13049127, + 26089763, + -38804517, + 48195713, + -50816364, + 43224598, + -22459158, + -13623498, + 66402779, + -137470394, + 232292687, + -375992636, + 748080991, + 1757770673, + -120103823, + -54220251, + 111666487, + -125537444, + 115846443, + -92856159, + 63860911, + -34514241, + 8963019, + 10221979, + -22019205, + 26755036, + -25748721, + 20872599, + -14112450, + 7204187, + -1397725, + -2634224, + 4756631, + -5239706, + 4582556, + -3340364, + 1990703, + -857332, + 92177, + 297437, + -396477, + 325444, + -194916, + -20795, + -64964, + 280142, + -641914, + 1106971, + -1549019, + 1757343, + -1467174, + 425643, + 1513795, + -4287747, + 7539382, + -10588362, + 12482714, + -12146666, + 8616266, + -1329175, + -9587143, + 23096739, + -37170682, + 48880400, + -54675231, + 50801423, + -33763162, + 657710, + 50904117, + -123942708, + 226548060, + -391824943, + 860149209, + 1701602449, + -185379114, + -12855047, + 85865265, + -111316230, + 110381542, + -93655196, + 68625615, + -41212929, + 15945727, + 4137778, + -17522647, + 24080750, + -24768753, + 21219619, + -15309269, + 8777198, + -2958742, + -1344442, + 3861278, + -4746799, + 4421894, + -3404446, + 2169922, + -1063669, + 269841, + 172533, + -324482, + 293125, + -185334, + -40296, + -29423, + 232004, + -597202, + 1097413, + -1620370, + 1960751, + -1843059, + 981991, + 824008, + -3582957, + 7011678, + -10484737, + 13062065, + -13614929, + 11048699, + -4594994, + -5878719, + 19609779, + -34800188, + 48647691, + -57565250, + 57556476, + -44653234, + 15241499, + 34046389, + -107638369, + 216225613, + -401019933, + 971486988, + 1635612957, + -242312616, + 26900199, + 59310696, + -95399505, + 102985046, + -92691547, + 72018383, + -47019248, + 22505664, + -1915969, + -12778403, + 21004326, + -23343608, + 21163255, + -16196435, + 10154208, + -4431474, + -58002, + 2914456, + -4177101, + 4182550, + -3402871, + 2302996, + -1243257, + 436046, + 49357, + -249587, + 256896, + -172730, + -60542, + 8932, + 176755, + -538709, + 1065963, + -1662649, + 2132656, + -2194468, + 1534767, + 100550, + -2792264, + 6337511, + -10178310, + 13404047, + -14852948, + 13317758, + -7834890, + -1989998, + 15686329, + -31724868, + 47485411, + -59413665, + 63345852, + -54914520, + 29858480, + 16113757, + -88779677, + 201334405, + -403003567, + 1080940394, + 1560540773, + -290657966, + 64419659, + 32508179, + -78123858, + 93837402, + -90019176, + 74002314, + -51841294, + 28527933, + -7826693, + -7879576, + 17590546, + -21508126, + 20712157, + -16763344, + 11313356, + -5790153, + 1201022, + 1935151, + -3543211, + 3871086, + -3337504, + 2388796, + -1393563, + 588038, + -69801, + -173374, + 217681, + -157562, + -81126, + 49456, + 115172, + -467013, + 1012402, + -1674014, + 2268700, + -2513853, + 2073175, + -643486, + -1928801, + 5526464, + -9670520, + 13497145, + -15832425, + 15376940, + -10986568, + 2008229, + 11393185, + -27990537, + 45398827, + -60166142, + 68041182, + -64339706, + 44232705, + -2582445, + -67642645, + 181965160, + -397280467, + 1187357703, + 1477221730, + -330285416, + 99140735, + 5951662, + -59841867, + 83147155, + -85722523, + 74567353, + -55607159, + 33909718, + -13486484, + -2920514, + 13909349, + -19304197, + 19882216, + -17005614, + 12237320, + -7011698, + 2409601, + 942519, + -2858634, + 3495257, + -3211363, + 2427126, + -1512698, + 723433, + -182819, + -97380, + 176415, + -140318, + -101602, + 91422, + 48197, + -382983, + 936946, + -1653174, + 2365092, + -2794071, + 2586402, + -1394272, + -1007428, + 4590974, + -8966707, + 13334382, + -16529450, + 17182859, + -13988247, + 6041776, + 6805397, + -23656373, + 42410862, + -59788137, + 71532363, + -72733058, + 58086684, + -21708792, + -44553560, + 158291627, + -383443269, + 1289604341, + 1386577715, + -361180867, + 130570623, + -19884572, + -40915379, + 71146531, + -79914342, + 73729971, + -58265907, + 38561977, + -18794026, + 2004981, + 10034428, + -16779853, + 18696132, + -16925041, + 12913544, + -8076095, + 3546163, + -44478, + -2137498, + 3063832, + -3028536, + 2418698, + -1599426, + 840253, + -287775, + -23068, + 134028, + -121498, + -121498, + 134028, + -23068, + -287775, + 840253, + -1599426, + 2418698, + -3028536, + 3063832, + -2137498, + -44478, + 3546163, + -8076095, + 12913544, + -16925041, + 18696132, + -16779853, + 10034428, + 2004981, + -18794026, + 38561977, + -58265907, + 73729971, + -79914342, + 71146531, + -40915379, + -19884572, + 130570623, + -361180867, + 1386577715, + 1289604341, + -383443269, + 158291627, + -44553560, + -21708792, + 58086684, + -72733058, + 71532363, + -59788137, + 42410862, + -23656373, + 6805397, + 6041776, + -13988247, + 17182859, + -16529450, + 13334382, + -8966707, + 4590974, + -1007428, + -1394272, + 2586402, + -2794071, + 2365092, + -1653174, + 936946, + -382983, + 48197, + 91422, + -101602, + -140318, + 176415, + -97380, + -182819, + 723433, + -1512698, + 2427126, + -3211363, + 3495257, + -2858634, + 942519, + 2409601, + -7011698, + 12237320, + -17005614, + 19882216, + -19304197, + 13909349, + -2920514, + -13486484, + 33909718, + -55607159, + 74567353, + -85722523, + 83147155, + -59841867, + 5951662, + 99140735, + -330285416, + 1477221730, + 1187357703, + -397280467, + 181965160, + -67642645, + -2582445, + 44232705, + -64339706, + 68041182, + -60166142, + 45398827, + -27990537, + 11393185, + 2008229, + -10986568, + 15376940, + -15832425, + 13497145, + -9670520, + 5526464, + -1928801, + -643486, + 2073175, + -2513853, + 2268700, + -1674014, + 1012402, + -467013, + 115172, + 49456, + -81126, + -157562, + 217681, + -173374, + -69801, + 588038, + -1393563, + 2388796, + -3337504, + 3871086, + -3543211, + 1935151, + 1201022, + -5790153, + 11313356, + -16763344, + 20712157, + -21508126, + 17590546, + -7879576, + -7826693, + 28527933, + -51841294, + 74002314, + -90019176, + 93837402, + -78123858, + 32508179, + 64419659, + -290657966, + 1560540773, + 1080940394, + -403003567, + 201334405, + -88779677, + 16113757, + 29858480, + -54914520, + 63345852, + -59413665, + 47485411, + -31724868, + 15686329, + -1989998, + -7834890, + 13317758, + -14852948, + 13404047, + -10178310, + 6337511, + -2792264, + 100550, + 1534767, + -2194468, + 2132656, + -1662649, + 1065963, + -538709, + 176755, + 8932, + -60542, + -172730, + 256896, + -249587, + 49357, + 436046, + -1243257, + 2302996, + -3402871, + 4182550, + -4177101, + 2914456, + -58002, + -4431474, + 10154208, + -16196435, + 21163255, + -23343608, + 21004326, + -12778403, + -1915969, + 22505664, + -47019248, + 72018383, + -92691547, + 102985046, + -95399505, + 59310696, + 26900199, + -242312616, + 1635612957, + 971486988, + -401019933, + 216225613, + -107638369, + 34046389, + 15241499, + -44653234, + 57556476, + -57565250, + 48647691, + -34800188, + 19609779, + -5878719, + -4594994, + 11048699, + -13614929, + 13062065, + -10484737, + 7011678, + -3582957, + 824008, + 981991, + -1843059, + 1960751, + -1620370, + 1097413, + -597202, + 232004, + -29423, + -40296, + -185334, + 293125, + -324482, + 172533, + 269841, + -1063669, + 2169922, + -3404446, + 4421894, + -4746799, + 3861278, + -1344442, + -2958742, + 8777198, + -15309269, + 21219619, + -24768753, + 24080750, + -17522647, + 4137778, + 15945727, + -41212929, + 68625615, + -93655196, + 110381542, + -111316230, + 85865265, + -12855047, + -185379114, + 1701602449, + 860149209, + -391824943, + 226548060, + -123942708, + 50904117, + 657710, + -33763162, + 50801423, + -54675231, + 48880400, + -37170682, + 23096739, + -9587143, + -1329175, + 8616266, + -12146666, + 12482714, + -10588362, + 7539382, + -4287747, + 1513795, + 425643, + -1467174, + 1757343, + -1549019, + 1106971, + -641914, + 280142, + -64964, + -20795, + -194916, + 325444, + -396477, + 297437, + 92177, + -857332, + 1990703, + -3340364, + 4582556, + -5239706, + 4756631, + -2634224, + -1397725, + 7204187, + -14112450, + 20872599, + -25748721, + 26755036, + -22019205, + 10221979, + 8963019, + -34514241, + 63860911, + -92856159, + 115846443, + -125537444, + 111666487, + -54220251, + -120103823, + 1757770673, + 748080991, + -375992636, + 232292687, + -137470394, + 66402779, + -13623498, + -22459158, + 43224598, + -50816364, + 48195713, + -38804517, + 26089763, + -13049127, + 1900938, + 6069141, + -10480224, + 11681732, + -10491594, + 7914013, + -4895429, + 2157782, + -123700, + -1074609, + 1527256, + -1450932, + 1095269, + -672562, + 320572, + -97141, + -2404, + -201054, + 352963, + -463978, + 421648, + -93863, + -627390, + 1767405, + -3209989, + 4659328, + -5644391, + 5582075, + -3902664, + 223559, + 5461241, + -12622717, + 20121089, + -26256525, + 28968884, + -26178009, + 16221460, + 1682545, + -27033714, + 57787842, + -90272589, + 119231396, + -137749135, + 136206154, + -96514102, + -46849040, + 1803486252, + 636423647, + -354165424, + 233529472, + -148055257, + 80289871, + -27344081, + -10959499, + 34982496, + -46078140, + 46622712, + -39684190, + 28541675, + -16204346, + 5035520, + 3457234, + -8650757, + 10678701, + -10200560, + 8131995, + -5396895, + 2745008, + -655878, + -673253, + 1275675, + -1328876, + 1063324, + -689145, + 352878, + -125502, + 14563, + -203377, + 374846, + -525409, + 542664, + -284919, + -377556, + 1503024, + -3013960, + 4648489, + -5950842, + 6320082, + -5124938, + 1875337, + 3578220, + -10862747, + 18971697, + -26273686, + 30671712, + -29913804, + 22020590, + -5762762, + -18898756, + 50495962, + -85915825, + 120423629, + -147666218, + 158982186, + -139008627, + 33909370, + 1838233518, + 526291365, + -327043027, + 230403614, + -155588638, + 92348363, + -40261822, + 518202, + 26241059, + -40564824, + 44206546, + -39806607, + 30416262, + -18999306, + 8017650, + 830718, + -6695788, + 9496601, + -9724911, + 8192781, + -5785257, + 3265862, + -1161328, + -270937, + 1008030, + -1185987, + 1012509, + -691937, + 376823, + -149700, + 29845, + -201577, + 390334, + -579247, + 657946, + -477407, + -112058, + 1201447, + -2754212, + 4547922, + -6150700, + 6954395, + -6276554, + 3526614, + 1588279, + -8860838, + 17438761, + -25790751, + 31821757, + -33147847, + 27505465, + -13234422, + -10251559, + 42099624, + -79830871, + 119348862, + -155038512, + 179507723, + -180938977, + 121585995, + 1861619486, + 418757223, + -295370812, + 223130608, + -160019741, + 102399786, + -52154438, + 11761004, + 17172429, + -34393248, + 41007303, + -39182884, + 31688761, + -21388236, + 10794317, + -1760919, + -4654454, + 8161302, + -9077562, + 8098799, + -6055926, + 3712230, + -1631247, + 124716, + 729890, + -1025690, + 944507, + -681472, + 392350, + -169492, + 43238, + -195416, + 398759, + -624055, + 764968, + -667587, + 164426, + 867412, + -2433974, + 4357194, + -6237460, + 7470380, + -7333833, + 5145742, + -472699, + -6650474, + 15544221, + -24807635, + 32387034, + -35809536, + 32566108, + -20590936, + -1246683, + 32736308, + -72096251, + 115973574, + -159656245, + 197320210, + -221514039, + 215491521, + 1873379169, + 314839940, + -259927731, + 211990326, + -161354961, + 110306567, + -62823233, + 22564477, + 7951641, + -27690412, + 37098628, + -37837888, + 32346120, + -23333796, + 13317348, + -4269788, + -2566737, + 6701021, + -8274384, + 7855337, + -6206641, + 4077609, + -2057748, + 506433, + 446851, + -851629, + 861269, + -658518, + 399571, + -184742, + 54594 + +}; + +static const struct src_stage src_int32_20_21_4167_5000 = { + 1, 1, 20, 60, 1200, 21, 20, 0, 0, + src_int32_20_21_4167_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_20_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_20_21_4535_5000.h new file mode 100644 index 000000000000..243140a639c8 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_20_21_4535_5000.h @@ -0,0 +1,2098 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_4535_5000_fir[2080] = { + -39854, + 85177, + -146854, + 218512, + -288255, + 338859, + -349054, + 295979, + -158741, + -77232, + 415530, + -844476, + 1333987, + -1834373, + 2277766, + -2582598, + 2661257, + -2430579, + 1824368, + -806718, + -615487, + 2382701, + -4377306, + 6424264, + -8298956, + 9742663, + -10485271, + 10273887, + -8905114, + 6257990, + -2324078, + -2768993, + 8744018, + -15173568, + 21494021, + -27034738, + 31061331, + -32830381, + 31651530, + -26951707, + 18335523, + -5635679, + -11052459, + 31357092, + -54641037, + 80040775, + -106537646, + 133071725, + -158734991, + 183191518, + -208096950, + 246688265, + 1948458148, + 143629506, + -162799620, + 159465870, + -147096194, + 129278850, + -108058847, + 85078580, + -61796609, + 39503916, + -19288560, + 1994075, + 11810959, + -21844883, + 28104254, + -30835443, + 30489790, + -27667075, + 23052921, + -17355953, + 11250081, + -5326411, + 57951, + 4221157, + -7321729, + 9192162, + -9899974, + 9605402, + -8530626, + 6928144, + -5051456, + 3130585, + -1354090, + -141645, + 1275939, + -2021002, + 2394151, + -2446745, + 2251640, + -1890778, + 1444292, + -982056, + 558179, + -208509, + -49160, + 212769, + -292270, + 305275, + -272760, + 215379, + -150727, + 91730, + -32410, + 76529, + -139741, + 217163, + -298176, + 366273, + -399969, + 374937, + -267361, + 58265, + 261609, + -687018, + 1194325, + -1739313, + 2257495, + -2667478, + 2877662, + -2796104, + 2342921, + -1464115, + 145284, + 1576595, + -3605246, + 5782822, + -7894693, + 9682086, + -10862549, + 11157283, + -10323419, + 8188484, + -4683596, + -128356, + 6033289, + -12658510, + 19479671, + -25843202, + 31003837, + -34175202, + 34589859, + -31563846, + 24559670, + -13241183, + -2486491, + 22458699, + -46261704, + 73280797, + -102802442, + 134211587, + -167411896, + 203956577, + -251428588, + 355628516, + 1935253108, + 47397065, + -116477290, + 133340519, + -132801656, + 122964308, + -107375398, + 88320405, + -67602033, + 46744978, + -27032764, + 9493775, + 5121154, + -16351974, + 24026220, + -28237516, + 29307257, + -27733134, + 24129464, + -19164887, + 13502851, + -7749701, + 2414037, + 2120340, + -5607082, + 7936160, + -9120807, + 9275313, + -8587001, + 7285881, + -5615229, + 3805826, + -2055850, + 517535, + 709145, + -1576286, + 2082488, + -2263439, + 2180370, + -1908012, + 1523504, + -1097321, + 686871, + -332987, + 59137, + 127091, + -230910, + 266361, + -252163, + 207965, + -151393, + 96135, + -23875, + 65886, + -129425, + 211219, + -302158, + 386783, + -443812, + 447907, + -372748, + 195260, + 99382, + -512573, + 1027681, + -1606918, + 2190509, + -2698864, + 3038172, + -3109443, + 2820540, + -2100241, + 912903, + 728067, + -2749905, + 5015321, + -7324106, + 9422658, + -11021763, + 11822093, + -11545841, + 9972013, + -6972101, + 2542358, + 3171212, + -9858778, + 17046364, + -24111047, + 30311934, + -34835560, + 36852648, + -35581603, + 30352812, + -20666794, + 6238551, + 12980308, + -36811741, + 64908628, + -96888560, + 132617783, + -172871930, + 221238913, + -291843296, + 469402094, + 1909004308, + -41178970, + -70045444, + 105403611, + -116201578, + 114306528, + -104540366, + 89729519, + -71959811, + 52946331, + -34134949, + 16713553, + -1596902, + -10588190, + 19505510, + -25095424, + 27543941, + -27237364, + 24706779, + -20567566, + 15459321, + -9991193, + 4696756, + -1259, + -3797289, + 6533203, + -8165692, + 8761255, + -8468960, + 7491958, + -6058545, + 4395652, + -2707027, + 1157549, + 135716, + -1105933, + 1733229, + -2037108, + 2066108, + -1886364, + 1570544, + -1188329, + 799258, + -448272, + 163979, + 40741, + -166331, + 223045, + -227026, + 196553, + -148948, + 98387, + -14383, + 53397, + -116013, + 200664, + -299949, + 399782, + -479503, + 513240, + -472650, + 330950, + -67954, + -324435, + 837027, + -1439301, + 2077450, + -2675297, + 3138668, + -3363420, + 3246858, + -2701761, + 1671712, + -146018, + -1827797, + 4135986, + -6596951, + 8967428, + -10957220, + 12252318, + -12545255, + 11570528, + -9142036, + 5188843, + 214749, + -6828683, + 14239531, + -21868092, + 28993150, + -34790731, + 38386379, + -38916312, + 35591662, + -27758677, + 14946480, + 3107619, + -26468303, + 55068779, + -88876111, + 128263020, + -174917596, + 234566248, + -328394503, + 586870605, + 1870031961, + -121392759, + -24380456, + 76258887, + -97682414, + 103526575, + -99648713, + 89306418, + -74802875, + 57996690, + -40459771, + 23510939, + -8207191, + -4672960, + 14638217, + -21478381, + 25241487, + -26195533, + 24778265, + -21539743, + 17082923, + -12007389, + 6860662, + -2100470, + -1930007, + 5013293, + -7055914, + 8075717, + -8180909, + 7543995, + -6373888, + 4889184, + -3295081, + 1765688, + -432643, + -619828, + 1353997, + -1772986, + 1911841, + -1826908, + 1585007, + -1253670, + 893364, + -552208, + 263309, + -44512, + -99921, + 176324, + -197989, + 181502, + -143552, + 98526, + -4101, + 39258, + -99683, + 185575, + -291423, + 404806, + -506102, + 569409, + -564881, + 462501, + -237040, + -126243, + 625882, + -1239336, + 1919917, + -2596428, + 3176207, + -3551979, + 3612420, + -3255870, + 2406034, + -1028056, + -857010, + 3161506, + -5726303, + 8323494, + -10667749, + 12436585, + -13298809, + 12949361, + -11147773, + 7756722, + -2776620, + -3627806, + 11112708, + -19154903, + 27067902, + -34034172, + 39151849, + -41492271, + 40162833, + -34367965, + 23459230, + -6963126, + -15429329, + 43937927, + -78889186, + 121175047, + -173414225, + 243526674, + -360155811, + 706820075, + 1818810555, + -192670221, + 19693322, + 46514050, + -77658574, + 90882966, + -92834683, + 87088245, + -76095495, + 61809374, + -45889207, + 29753645, + -14577394, + 1272529, + 9526415, + -17464479, + 22452014, + -24634295, + 24347626, + -22066128, + 18344203, + -13759799, + 8863187, + -4135031, + -43656, + 3408475, + -5815659, + 7234519, + -7730646, + 7442761, + -6556425, + 5277626, + -3808913, + 2330056, + -984490, + -128042, + 952910, + -1476995, + 1721324, + -1731466, + 1567155, + -1292475, + 967625, + -642909, + 355225, + -126960, + -33077, + 127237, + -165754, + 163233, + -135420, + 96637, + 6783, + 23708, + -80681, + 166133, + -276580, + 401544, + -522841, + 615043, + -647370, + 587109, + -404414, + 78095, + 398249, + -1010612, + 1720453, + -2463040, + 3149098, + -3670323, + 3908891, + -3750571, + 3100491, + -1900063, + 143153, + 2110717, + -4728330, + 7501898, + -10156773, + 12368435, + -13788441, + 14077973, + -12946564, + 10192662, + -5742089, + -319833, + 7726519, + -16022075, + 24569209, + -32573810, + 39125116, + -43248426, + 43965261, + -40353846, + 31600455, + -17028986, + -3909831, + 31721858, + -67094175, + 111437278, + -168294239, + 247778367, + -386236543, + 827976921, + 1755961955, + -254574444, + 61415291, + 16769387, + -56563771, + 76665854, + -84268470, + 83147476, + -75833560, + 64323717, + -50324714, + 35322108, + -20581519, + 7127790, + 4276041, + -13139019, + 19236953, + -22590538, + 23428685, + -22140611, + 19221339, + -15215671, + 10665473, + -6064435, + 1823369, + 1752167, + -4471485, + 6256457, + -7129166, + 7192124, + -6604075, + 5554426, + -4239070, + 2839803, + -1508873, + 359386, + 538413, + -1155614, + 1498987, + -1602562, + 1517903, + -1304434, + 1020907, + -718797, + 438017, + -204991, + 32832, + 76845, + -131071, + 142221, + -124816, + 92843, + 18056, + 7026, + -59320, + 142614, + -255558, + 389854, + -529137, + 648961, + -718204, + 702061, + -566587, + 284471, + 158538, + -757368, + 1482504, + -2277053, + 3056954, + -3715031, + 4129242, + -4174927, + 3740326, + -2744033, + 1152548, + 1004243, + -3621999, + 6517450, + -9432290, + 12046506, + -14001294, + 14930624, + -14499447, + 12445476, + -8620752, + 3028708, + 4147515, + -12529303, + 21542151, + -30432032, + 38298160, + -44139783, + 46912407, + -45586530, + 39199141, + -26884353, + 7862210, + 18651793, + -53697193, + 99188324, + -159560237, + 247058310, + -405797087, + 949025001, + 1682246385, + -306808936, + 100098992, + -12393183, + -34842213, + 61190712, + -74152227, + 77589940, + -74044213, + 65505957, + -53688971, + 40111751, + -26102370, + 12775467, + -1005291, + -8592719, + 15665713, + -20110536, + 22045010, + -21766290, + 19700512, + -16348594, + 12233124, + -7850732, + 3633476, + 78465, + -3051762, + 5162885, + -6390402, + 6798933, + -6517515, + 5715374, + -4577917, + 3285329, + -1995548, + 832643, + 119097, + -815739, + 1249837, + -1443358, + 1438789, + -1289786, + 1052524, + -778626, + 510195, + -277116, + 96487, + 26210, + -94718, + 118984, + -112049, + 87303, + 29486, + -10472, + -35972, + 115389, + -228626, + 369764, + -524612, + 670202, + -775673, + 804787, + -720112, + 488664, + -88515, + -484421, + 1210362, + -2041497, + 2900722, + -3684150, + 4267912, + -4519299, + 4311716, + -3542312, + 2150599, + -135904, + -2428716, + 5388463, + -8506759, + 11474618, + -13930040, + 15486947, + -15772084, + 14467193, + -11352853, + 6349775, + 446874, + -8744250, + 18043071, + -27645379, + 36679211, + -44138496, + 48934187, + -49950026, + 46093148, + -36325092, + 19650277, + 4980124, + -38940686, + 84620442, + -147286796, + 241189847, + -418063762, + 1068623493, + 1598551418, + -349218701, + 135140993, + -40420422, + -12939782, + 44791640, + -62715510, + 70552194, + -70784871, + 65349555, + -55927178, + 44034915, + -31033812, + 18103663, + -6210477, + -3919813, + 11814191, + -17248915, + 20229328, + -20955315, + 19776098, + -17138969, + 13536851, + -9459271, + 5350628, + -1578556, + -1586077, + 3977257, + -5530906, + 6272844, + -6300133, + 5758660, + -4819767, + 3658463, + -2435174, + 1282344, + -296472, + -464538, + 979347, + -1257578, + 1331927, + -1249306, + 1062244, + -821502, + 570517, + -342004, + 156648, + -23631, + -57485, + 94069, + -97460, + 80207, + 40829, + -28442, + -11067, + 84919, + -196184, + 341482, + -509106, + 678043, + -818310, + 892924, + -861655, + 686423, + -337943, + -197070, + 909094, + -1760469, + 2682682, + -3577252, + 4320945, + -4775569, + 4802064, + -4277965, + 3116714, + -1286763, + -1171916, + 4136419, + -7396895, + 10661751, + -13573091, + 15732425, + -16735513, + 16214069, + -13881017, + 9575189, + -3301012, + -4741256, + 14138546, + -24263951, + 34292761, + -43234634, + 49978587, + -53344664, + 52132624, + -45152708, + 31213982, + -9024334, + -23099231, + 67976880, + -131620944, + 230088915, + -422342968, + 1185425332, + 1505879159, + -381789143, + 166028171, + -66797302, + 8704623, + 27814447, + -50210272, + 62198342, + -66141662, + 63874985, + -57007881, + 47022429, + -35282789, + 23008144, + -11235082, + 783879, + 7763177, + -14067465, + 18022778, + -19728550, + 19450701, + -17574334, + 14553016, + -10859365, + 6941058, + -3185528, + -104618, + 2724626, + -4569483, + 5626090, + -5957929, + 5684884, + -4960975, + 3952610, + -2819491, + 1699715, + -699930, + -109298, + 693333, + -1049427, + 1199963, + -1184280, + 1050286, + -846893, + 618011, + -398498, + 212173, + -71682, + -20158, + 68041, + -81416, + 71771, + 51829, + -46514, + 14919, + 51749, + -158763, + 305390, + -482684, + 672029, + -844924, + 964364, + -988072, + 873552, + -584645, + 99002, + 584442, + -1439064, + 2406417, + -3395465, + 4286087, + -4937316, + 5200276, + -4935130, + 4030704, + -2424880, + 123390, + 2785564, + -6123377, + 9621917, + -12934687, + 15658748, + -17366793, + 17647532, + -16151446, + 12638023, + -7020015, + -599882, + 9904132, + -20350529, + 31179239, + -41436578, + 50012935, + -55689327, + 57183210, + -53178455, + 42313881, + -23081496, + -6474632, + 49548170, + -112781260, + 213768796, + -418034365, + 1298095920, + 1405331822, + -404642854, + 192343283, + -91055575, + 29667414, + 10609625, + -36905479, + 52716337, + -60227297, + 61128970, + -56923326, + 49024791, + -38771053, + 27394358, + -15979422, + 5422911, + 3596663, + -10633818, + 15473990, + -18115061, + 18735017, + -17649542, + 15264051, + -12024874, + 8373926, + -4710460, + 1362444, + 1431119, + -3526788, + 4873206, + -5499358, + 5497010, + -4999981, + 4162865, + -3141476, + 2076760, + -1083284, + 242723, + 397839, + -823492, + 1046004, + -1096471, + 1017303, + -854635, + 651982, + -445640, + 262047, + -117010, + 16497, + 41470, + -64303, + 62229, + 62229, + -64303, + 41470, + 16497, + -117010, + 262047, + -445640, + 651982, + -854635, + 1017303, + -1096471, + 1046004, + -823492, + 397839, + 242723, + -1083284, + 2076760, + -3141476, + 4162865, + -4999981, + 5497010, + -5499358, + 4873206, + -3526788, + 1431119, + 1362444, + -4710460, + 8373926, + -12024874, + 15264051, + -17649542, + 18735017, + -18115061, + 15473990, + -10633818, + 3596663, + 5422911, + -15979422, + 27394358, + -38771053, + 49024791, + -56923326, + 61128970, + -60227297, + 52716337, + -36905479, + 10609625, + 29667414, + -91055575, + 192343283, + -404642854, + 1405331822, + 1298095920, + -418034365, + 213768796, + -112781260, + 49548170, + -6474632, + -23081496, + 42313881, + -53178455, + 57183210, + -55689327, + 50012935, + -41436578, + 31179239, + -20350529, + 9904132, + -599882, + -7020015, + 12638023, + -16151446, + 17647532, + -17366793, + 15658748, + -12934687, + 9621917, + -6123377, + 2785564, + 123390, + -2424880, + 4030704, + -4935130, + 5200276, + -4937316, + 4286087, + -3395465, + 2406417, + -1439064, + 584442, + 99002, + -584645, + 873552, + -988072, + 964364, + -844924, + 672029, + -482684, + 305390, + -158763, + 51749, + 14919, + -46514, + 51829, + 71771, + -81416, + 68041, + -20158, + -71682, + 212173, + -398498, + 618011, + -846893, + 1050286, + -1184280, + 1199963, + -1049427, + 693333, + -109298, + -699930, + 1699715, + -2819491, + 3952610, + -4960975, + 5684884, + -5957929, + 5626090, + -4569483, + 2724626, + -104618, + -3185528, + 6941058, + -10859365, + 14553016, + -17574334, + 19450701, + -19728550, + 18022778, + -14067465, + 7763177, + 783879, + -11235082, + 23008144, + -35282789, + 47022429, + -57007881, + 63874985, + -66141662, + 62198342, + -50210272, + 27814447, + 8704623, + -66797302, + 166028171, + -381789143, + 1505879159, + 1185425332, + -422342968, + 230088915, + -131620944, + 67976880, + -23099231, + -9024334, + 31213982, + -45152708, + 52132624, + -53344664, + 49978587, + -43234634, + 34292761, + -24263951, + 14138546, + -4741256, + -3301012, + 9575189, + -13881017, + 16214069, + -16735513, + 15732425, + -13573091, + 10661751, + -7396895, + 4136419, + -1171916, + -1286763, + 3116714, + -4277965, + 4802064, + -4775569, + 4320945, + -3577252, + 2682682, + -1760469, + 909094, + -197070, + -337943, + 686423, + -861655, + 892924, + -818310, + 678043, + -509106, + 341482, + -196184, + 84919, + -11067, + -28442, + 40829, + 80207, + -97460, + 94069, + -57485, + -23631, + 156648, + -342004, + 570517, + -821502, + 1062244, + -1249306, + 1331927, + -1257578, + 979347, + -464538, + -296472, + 1282344, + -2435174, + 3658463, + -4819767, + 5758660, + -6300133, + 6272844, + -5530906, + 3977257, + -1586077, + -1578556, + 5350628, + -9459271, + 13536851, + -17138969, + 19776098, + -20955315, + 20229328, + -17248915, + 11814191, + -3919813, + -6210477, + 18103663, + -31033812, + 44034915, + -55927178, + 65349555, + -70784871, + 70552194, + -62715510, + 44791640, + -12939782, + -40420422, + 135140993, + -349218701, + 1598551418, + 1068623493, + -418063762, + 241189847, + -147286796, + 84620442, + -38940686, + 4980124, + 19650277, + -36325092, + 46093148, + -49950026, + 48934187, + -44138496, + 36679211, + -27645379, + 18043071, + -8744250, + 446874, + 6349775, + -11352853, + 14467193, + -15772084, + 15486947, + -13930040, + 11474618, + -8506759, + 5388463, + -2428716, + -135904, + 2150599, + -3542312, + 4311716, + -4519299, + 4267912, + -3684150, + 2900722, + -2041497, + 1210362, + -484421, + -88515, + 488664, + -720112, + 804787, + -775673, + 670202, + -524612, + 369764, + -228626, + 115389, + -35972, + -10472, + 29486, + 87303, + -112049, + 118984, + -94718, + 26210, + 96487, + -277116, + 510195, + -778626, + 1052524, + -1289786, + 1438789, + -1443358, + 1249837, + -815739, + 119097, + 832643, + -1995548, + 3285329, + -4577917, + 5715374, + -6517515, + 6798933, + -6390402, + 5162885, + -3051762, + 78465, + 3633476, + -7850732, + 12233124, + -16348594, + 19700512, + -21766290, + 22045010, + -20110536, + 15665713, + -8592719, + -1005291, + 12775467, + -26102370, + 40111751, + -53688971, + 65505957, + -74044213, + 77589940, + -74152227, + 61190712, + -34842213, + -12393183, + 100098992, + -306808936, + 1682246385, + 949025001, + -405797087, + 247058310, + -159560237, + 99188324, + -53697193, + 18651793, + 7862210, + -26884353, + 39199141, + -45586530, + 46912407, + -44139783, + 38298160, + -30432032, + 21542151, + -12529303, + 4147515, + 3028708, + -8620752, + 12445476, + -14499447, + 14930624, + -14001294, + 12046506, + -9432290, + 6517450, + -3621999, + 1004243, + 1152548, + -2744033, + 3740326, + -4174927, + 4129242, + -3715031, + 3056954, + -2277053, + 1482504, + -757368, + 158538, + 284471, + -566587, + 702061, + -718204, + 648961, + -529137, + 389854, + -255558, + 142614, + -59320, + 7026, + 18056, + 92843, + -124816, + 142221, + -131071, + 76845, + 32832, + -204991, + 438017, + -718797, + 1020907, + -1304434, + 1517903, + -1602562, + 1498987, + -1155614, + 538413, + 359386, + -1508873, + 2839803, + -4239070, + 5554426, + -6604075, + 7192124, + -7129166, + 6256457, + -4471485, + 1752167, + 1823369, + -6064435, + 10665473, + -15215671, + 19221339, + -22140611, + 23428685, + -22590538, + 19236953, + -13139019, + 4276041, + 7127790, + -20581519, + 35322108, + -50324714, + 64323717, + -75833560, + 83147476, + -84268470, + 76665854, + -56563771, + 16769387, + 61415291, + -254574444, + 1755961955, + 827976921, + -386236543, + 247778367, + -168294239, + 111437278, + -67094175, + 31721858, + -3909831, + -17028986, + 31600455, + -40353846, + 43965261, + -43248426, + 39125116, + -32573810, + 24569209, + -16022075, + 7726519, + -319833, + -5742089, + 10192662, + -12946564, + 14077973, + -13788441, + 12368435, + -10156773, + 7501898, + -4728330, + 2110717, + 143153, + -1900063, + 3100491, + -3750571, + 3908891, + -3670323, + 3149098, + -2463040, + 1720453, + -1010612, + 398249, + 78095, + -404414, + 587109, + -647370, + 615043, + -522841, + 401544, + -276580, + 166133, + -80681, + 23708, + 6783, + 96637, + -135420, + 163233, + -165754, + 127237, + -33077, + -126960, + 355225, + -642909, + 967625, + -1292475, + 1567155, + -1731466, + 1721324, + -1476995, + 952910, + -128042, + -984490, + 2330056, + -3808913, + 5277626, + -6556425, + 7442761, + -7730646, + 7234519, + -5815659, + 3408475, + -43656, + -4135031, + 8863187, + -13759799, + 18344203, + -22066128, + 24347626, + -24634295, + 22452014, + -17464479, + 9526415, + 1272529, + -14577394, + 29753645, + -45889207, + 61809374, + -76095495, + 87088245, + -92834683, + 90882966, + -77658574, + 46514050, + 19693322, + -192670221, + 1818810555, + 706820075, + -360155811, + 243526674, + -173414225, + 121175047, + -78889186, + 43937927, + -15429329, + -6963126, + 23459230, + -34367965, + 40162833, + -41492271, + 39151849, + -34034172, + 27067902, + -19154903, + 11112708, + -3627806, + -2776620, + 7756722, + -11147773, + 12949361, + -13298809, + 12436585, + -10667749, + 8323494, + -5726303, + 3161506, + -857010, + -1028056, + 2406034, + -3255870, + 3612420, + -3551979, + 3176207, + -2596428, + 1919917, + -1239336, + 625882, + -126243, + -237040, + 462501, + -564881, + 569409, + -506102, + 404806, + -291423, + 185575, + -99683, + 39258, + -4101, + 98526, + -143552, + 181502, + -197989, + 176324, + -99921, + -44512, + 263309, + -552208, + 893364, + -1253670, + 1585007, + -1826908, + 1911841, + -1772986, + 1353997, + -619828, + -432643, + 1765688, + -3295081, + 4889184, + -6373888, + 7543995, + -8180909, + 8075717, + -7055914, + 5013293, + -1930007, + -2100470, + 6860662, + -12007389, + 17082923, + -21539743, + 24778265, + -26195533, + 25241487, + -21478381, + 14638217, + -4672960, + -8207191, + 23510939, + -40459771, + 57996690, + -74802875, + 89306418, + -99648713, + 103526575, + -97682414, + 76258887, + -24380456, + -121392759, + 1870031961, + 586870605, + -328394503, + 234566248, + -174917596, + 128263020, + -88876111, + 55068779, + -26468303, + 3107619, + 14946480, + -27758677, + 35591662, + -38916312, + 38386379, + -34790731, + 28993150, + -21868092, + 14239531, + -6828683, + 214749, + 5188843, + -9142036, + 11570528, + -12545255, + 12252318, + -10957220, + 8967428, + -6596951, + 4135986, + -1827797, + -146018, + 1671712, + -2701761, + 3246858, + -3363420, + 3138668, + -2675297, + 2077450, + -1439301, + 837027, + -324435, + -67954, + 330950, + -472650, + 513240, + -479503, + 399782, + -299949, + 200664, + -116013, + 53397, + -14383, + 98387, + -148948, + 196553, + -227026, + 223045, + -166331, + 40741, + 163979, + -448272, + 799258, + -1188329, + 1570544, + -1886364, + 2066108, + -2037108, + 1733229, + -1105933, + 135716, + 1157549, + -2707027, + 4395652, + -6058545, + 7491958, + -8468960, + 8761255, + -8165692, + 6533203, + -3797289, + -1259, + 4696756, + -9991193, + 15459321, + -20567566, + 24706779, + -27237364, + 27543941, + -25095424, + 19505510, + -10588190, + -1596902, + 16713553, + -34134949, + 52946331, + -71959811, + 89729519, + -104540366, + 114306528, + -116201578, + 105403611, + -70045444, + -41178970, + 1909004308, + 469402094, + -291843296, + 221238913, + -172871930, + 132617783, + -96888560, + 64908628, + -36811741, + 12980308, + 6238551, + -20666794, + 30352812, + -35581603, + 36852648, + -34835560, + 30311934, + -24111047, + 17046364, + -9858778, + 3171212, + 2542358, + -6972101, + 9972013, + -11545841, + 11822093, + -11021763, + 9422658, + -7324106, + 5015321, + -2749905, + 728067, + 912903, + -2100241, + 2820540, + -3109443, + 3038172, + -2698864, + 2190509, + -1606918, + 1027681, + -512573, + 99382, + 195260, + -372748, + 447907, + -443812, + 386783, + -302158, + 211219, + -129425, + 65886, + -23875, + 96135, + -151393, + 207965, + -252163, + 266361, + -230910, + 127091, + 59137, + -332987, + 686871, + -1097321, + 1523504, + -1908012, + 2180370, + -2263439, + 2082488, + -1576286, + 709145, + 517535, + -2055850, + 3805826, + -5615229, + 7285881, + -8587001, + 9275313, + -9120807, + 7936160, + -5607082, + 2120340, + 2414037, + -7749701, + 13502851, + -19164887, + 24129464, + -27733134, + 29307257, + -28237516, + 24026220, + -16351974, + 5121154, + 9493775, + -27032764, + 46744978, + -67602033, + 88320405, + -107375398, + 122964308, + -132801656, + 133340519, + -116477290, + 47397065, + 1935253108, + 355628516, + -251428588, + 203956577, + -167411896, + 134211587, + -102802442, + 73280797, + -46261704, + 22458699, + -2486491, + -13241183, + 24559670, + -31563846, + 34589859, + -34175202, + 31003837, + -25843202, + 19479671, + -12658510, + 6033289, + -128356, + -4683596, + 8188484, + -10323419, + 11157283, + -10862549, + 9682086, + -7894693, + 5782822, + -3605246, + 1576595, + 145284, + -1464115, + 2342921, + -2796104, + 2877662, + -2667478, + 2257495, + -1739313, + 1194325, + -687018, + 261609, + 58265, + -267361, + 374937, + -399969, + 366273, + -298176, + 217163, + -139741, + 76529, + -32410, + 91730, + -150727, + 215379, + -272760, + 305275, + -292270, + 212769, + -49160, + -208509, + 558179, + -982056, + 1444292, + -1890778, + 2251640, + -2446745, + 2394151, + -2021002, + 1275939, + -141645, + -1354090, + 3130585, + -5051456, + 6928144, + -8530626, + 9605402, + -9899974, + 9192162, + -7321729, + 4221157, + 57951, + -5326411, + 11250081, + -17355953, + 23052921, + -27667075, + 30489790, + -30835443, + 28104254, + -21844883, + 11810959, + 1994075, + -19288560, + 39503916, + -61796609, + 85078580, + -108058847, + 129278850, + -147096194, + 159465870, + -162799620, + 143629506, + 1948458148, + 246688265, + -208096950, + 183191518, + -158734991, + 133071725, + -106537646, + 80040775, + -54641037, + 31357092, + -11052459, + -5635679, + 18335523, + -26951707, + 31651530, + -32830381, + 31061331, + -27034738, + 21494021, + -15173568, + 8744018, + -2768993, + -2324078, + 6257990, + -8905114, + 10273887, + -10485271, + 9742663, + -8298956, + 6424264, + -4377306, + 2382701, + -615487, + -806718, + 1824368, + -2430579, + 2661257, + -2582598, + 2277766, + -1834373, + 1333987, + -844476, + 415530, + -77232, + -158741, + 295979, + -349054, + 338859, + -288255, + 218512, + -146854, + 85177, + -39854 + +}; + +static const struct src_stage src_int32_20_21_4535_5000 = { + 1, 1, 20, 104, 2080, 21, 20, 0, 0, + src_int32_20_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_20_7_2976_5000.h b/src/audio/src/coef/src_ipc4_int32_20_7_2976_5000.h new file mode 100644 index 000000000000..86c446340c58 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_20_7_2976_5000.h @@ -0,0 +1,578 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_7_2976_5000_fir[560] = { + -33375, + 393038, + -1331352, + 2236287, + -898805, + -5812585, + 18986736, + -33499847, + 35947516, + -8170814, + -63287260, + 176522751, + -310720523, + 442180903, + 1711694068, + 353993224, + -290350552, + 180270704, + -74534277, + 2022464, + 30044882, + -31643328, + 19437786, + -6899204, + -77131, + 1858153, + -1232523, + 388456, + -28069, + 389310, + -1414209, + 2604289, + -1760879, + -4561564, + 18190988, + -34885431, + 41516357, + -18662745, + -50519575, + 169702624, + -327200903, + 532825494, + 1702576427, + 268957573, + -266606902, + 181026213, + -84146749, + 11767762, + 23916900, + -29367167, + 19553922, + -7812579, + 692823, + 1477233, + -1120973, + 376608, + -20062, + 376310, + -1477881, + 2954451, + -2650547, + -3158417, + 17046244, + -35754419, + 46643841, + -29292836, + -36374498, + 159774925, + -339301349, + 625189353, + 1684430750, + 187719413, + -240023731, + 178910378, + -92040808, + 20928854, + 17671107, + -26727198, + 19349983, + -8547266, + 1401328, + 1100396, + -999920, + 358589, + -9147, + 353187, + -1519261, + 3278821, + -3553665, + -1618822, + 15554045, + -36067824, + 51225140, + -39891619, + -21023601, + 146751018, + -346564260, + 718500067, + 1657435176, + 110868135, + -211146089, + 174082211, + -98162722, + 29384265, + 11412423, + -23782671, + 18845372, + -9101134, + 2040327, + 733943, + -872489, + 335517, + 4820, + 319239, + -1535423, + 3569347, + -4454928, + 38229, + 13722031, + -35794310, + 55160040, + -50283082, + -4665157, + 130690860, + -348571727, + 811958746, + 1621854245, + 38931425, + -180522621, + 166734766, + -102488549, + 37028620, + 5241565, + -20595128, + 18063511, + -9475220, + 2603470, + 383532, + -741662, + 308502, + 21906, + 273938, + -1523699, + 3818021, + -5338084, + 1790595, + 11564114, + -34911077, + 58354830, + -60287300, + 12477937, + 111704181, + -344952123, + 904748746, + 1578035732, + -27629515, + -148698434, + 157090918, + -105023356, + 43773691, + -746421, + -17227284, + 17031246, + -9673537, + 3086124, + 54113, + -610224, + 278626, + 42091, + 216965, + -1481758, + 4017043, + -6186173, + 3613201, + 9100547, + -33404639, + 60724145, + -69723239, + 30160708, + 89951002, + -335386271, + 996044714, + 1526406500, + -88423859, + -116208218, + 145398856, + -105800003, + 49549125, + -6463461, + -13741941, + 15778232, + -9702850, + 3485352, + -250105, + -480729, + 246918, + 65261, + 148234, + -1407678, + 4158985, + -6981801, + 5478334, + 6357882, + -31271476, + 62192761, + -78411681, + 48119102, + 65641433, + -319613071, + 1085021852, + 1467467411, + -143134100, + -83569701, + 131927386, + -104877552, + 54302856, + -11829599, + -10200942, + 14336295, + -9572398, + 3799853, + -525689, + -355465, + 214336, + 91197, + 67922, + -1300026, + 4236959, + -7707433, + 7355991, + 3368814, + -28518544, + 62697276, + -86178242, + 66073393, + 39034752, + -297434512, + 1170865263, + 1401787381, + -191518045, + -51277535, + 116961093, + -102339328, + 58001216, + -16773953, + -6664196, + 12738788, + -9293608, + 4029891, + -769982, + -236431, + 181752, + 119572, + -23515, + -1157921, + 4244790, + -8345709, + 9214293, + 171909, + -25163621, + 62187679, + -92856426, + 83731971, + 10437748, + -268719986, + 1252779279, + 1329996635, + -233409832, + -19797662, + 100795454, + -98290669, + 60628738, + -21235495, + -3188774, + 11019951, + -8879771, + 4177184, + -981103, + -125321, + 149942, + 149942, + -125321, + -981103, + 4177184, + -8879771, + 11019951, + -3188774, + -21235495, + 60628738, + -98290669, + 100795454, + -19797662, + -233409832, + 1329996635, + 1252779279, + -268719986, + 10437748, + 83731971, + -92856426, + 62187679, + -25163621, + 171909, + 9214293, + -8345709, + 4244790, + -1157921, + -23515, + 119572, + 181752, + -236431, + -769982, + 4029891, + -9293608, + 12738788, + -6664196, + -16773953, + 58001216, + -102339328, + 116961093, + -51277535, + -191518045, + 1401787381, + 1170865263, + -297434512, + 39034752, + 66073393, + -86178242, + 62697276, + -28518544, + 3368814, + 7355991, + -7707433, + 4236959, + -1300026, + 67922, + 91197, + 214336, + -355465, + -525689, + 3799853, + -9572398, + 14336295, + -10200942, + -11829599, + 54302856, + -104877552, + 131927386, + -83569701, + -143134100, + 1467467411, + 1085021852, + -319613071, + 65641433, + 48119102, + -78411681, + 62192761, + -31271476, + 6357882, + 5478334, + -6981801, + 4158985, + -1407678, + 148234, + 65261, + 246918, + -480729, + -250105, + 3485352, + -9702850, + 15778232, + -13741941, + -6463461, + 49549125, + -105800003, + 145398856, + -116208218, + -88423859, + 1526406500, + 996044714, + -335386271, + 89951002, + 30160708, + -69723239, + 60724145, + -33404639, + 9100547, + 3613201, + -6186173, + 4017043, + -1481758, + 216965, + 42091, + 278626, + -610224, + 54113, + 3086124, + -9673537, + 17031246, + -17227284, + -746421, + 43773691, + -105023356, + 157090918, + -148698434, + -27629515, + 1578035732, + 904748746, + -344952123, + 111704181, + 12477937, + -60287300, + 58354830, + -34911077, + 11564114, + 1790595, + -5338084, + 3818021, + -1523699, + 273938, + 21906, + 308502, + -741662, + 383532, + 2603470, + -9475220, + 18063511, + -20595128, + 5241565, + 37028620, + -102488549, + 166734766, + -180522621, + 38931425, + 1621854245, + 811958746, + -348571727, + 130690860, + -4665157, + -50283082, + 55160040, + -35794310, + 13722031, + 38229, + -4454928, + 3569347, + -1535423, + 319239, + 4820, + 335517, + -872489, + 733943, + 2040327, + -9101134, + 18845372, + -23782671, + 11412423, + 29384265, + -98162722, + 174082211, + -211146089, + 110868135, + 1657435176, + 718500067, + -346564260, + 146751018, + -21023601, + -39891619, + 51225140, + -36067824, + 15554045, + -1618822, + -3553665, + 3278821, + -1519261, + 353187, + -9147, + 358589, + -999920, + 1100396, + 1401328, + -8547266, + 19349983, + -26727198, + 17671107, + 20928854, + -92040808, + 178910378, + -240023731, + 187719413, + 1684430750, + 625189353, + -339301349, + 159774925, + -36374498, + -29292836, + 46643841, + -35754419, + 17046244, + -3158417, + -2650547, + 2954451, + -1477881, + 376310, + -20062, + 376608, + -1120973, + 1477233, + 692823, + -7812579, + 19553922, + -29367167, + 23916900, + 11767762, + -84146749, + 181026213, + -266606902, + 268957573, + 1702576427, + 532825494, + -327200903, + 169702624, + -50519575, + -18662745, + 41516357, + -34885431, + 18190988, + -4561564, + -1760879, + 2604289, + -1414209, + 389310, + -28069, + 388456, + -1232523, + 1858153, + -77131, + -6899204, + 19437786, + -31643328, + 30044882, + 2022464, + -74534277, + 180270704, + -290350552, + 353993224, + 1711694068, + 442180903, + -310720523, + 176522751, + -63287260, + -8170814, + 35947516, + -33499847, + 18986736, + -5812585, + -898805, + 2236287, + -1331352, + 393038, + -33375 + +}; + +static const struct src_stage src_int32_20_7_2976_5000 = { + 1, 3, 20, 28, 560, 7, 20, 0, 0, + src_int32_20_7_2976_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_10_2500_5000.h b/src/audio/src/coef/src_ipc4_int32_21_10_2500_5000.h new file mode 100644 index 000000000000..43a6b47e3354 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_10_2500_5000.h @@ -0,0 +1,522 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_10_2500_5000_fir[504] = { + 7704, + 568453, + -2657822, + 4766949, + -739405, + -16365208, + 42490807, + -52344623, + 6322387, + 121176514, + -311834407, + 509333054, + 1609715705, + 432921499, + -302974575, + 132444478, + -6182611, + -45712752, + 41446187, + -17810947, + 716210, + 4102230, + -2535989, + 596232, + 26112, + 526002, + -2748939, + 5412660, + -2279930, + -14609914, + 43009139, + -58583544, + 19314760, + 107750776, + -317062459, + 587047468, + 1602779187, + 358316955, + -290789985, + 141513067, + -18061759, + -38791522, + 39914305, + -18944209, + 2072025, + 3429356, + -2387933, + 610456, + 48610, + 467940, + -2804982, + 6028020, + -3888277, + -12552603, + 42967599, + -64326542, + 32643399, + 92238195, + -318375371, + 665538602, + 1588961873, + 285997265, + -275607461, + 148369295, + -29190455, + -31683753, + 37938848, + -19766501, + 3315438, + 2758559, + -2218199, + 612379, + 75220, + 393534, + -2821817, + 6601344, + -5545287, + -10205569, + 42338778, + -69472695, + 46146009, + 74739431, + -315517155, + 744262942, + 1568374659, + 216409962, + -257769657, + 153027759, + -39458975, + -24490171, + 35567360, + -20283504, + 4436183, + 2099338, + -2031310, + 603355, + 105858, + 302300, + -2795622, + 7120770, + -7229897, + -7585935, + 41102128, + -73924608, + 59650765, + 55384924, + -308262697, + 822664432, + 1541182515, + 149968630, + -237631016, + 155529332, + -48773260, + -17308178, + 32850419, + -20504787, + 5426344, + 1460357, + -1831686, + 584810, + 140321, + 194031, + -2722981, + 7574436, + -8919343, + -4715655, + 39244576, + -77589900, + 72978159, + 34334601, + -296421016, + 900179510, + 1507602861, + 87049666, + -215553721, + 155939580, + -57055468, + -10230707, + 29840809, + -20443466, + 6280333, + 849377, + -1623588, + 558200, + 178284, + 68828, + -2600972, + 7950668, + -10589407, + -1621451, + 36761065, + -80382681, + 85943021, + 11777215, + -279838233, + 976242261, + 1467903427, + 27989468, + -191903667, + 154346966, + -64244296, + -3345188, + 26592698, + -20115841, + 6994835, + 273193, + -1411054, + 524986, + 219287, + -72870, + -2427260, + 8238180, + -12214698, + 1665325, + 33655004, + -82225013, + 98356696, + -12070667, + -258400221, + 1050289660, + 1422399613, + -26917934, + -167046507, + 150860829, + -70295081, + 3267368, + 23160843, + -19541003, + 7568721, + -262402, + -1197853, + 486605, + 262738, + -230265, + -2200180, + 8426275, + -13768958, + 5108909, + 29938618, + -83048316, + 110029352, + -36966045, + -232034876, + 1121766836, + 1371451404, + -77422762, + -141343816, + 145609198, + -75179686, + 9533164, + 19599810, + -18740413, + 8002934, + -752638, + -987440, + 444443, + 307905, + -402182, + -1918817, + 8505059, + -15225415, + 8669411, + 25633191, + -82794712, + 120772392, + -62641219, + -200714015, + 1190132305, + 1315459841, + -123320903, + -115149411, + 138736468, + -78886170, + 15386278, + 15963244, + -17737486, + 8300356, + -1193774, + -782927, + 399810, + 353927, + -587056, + -1583082, + 8465644, + -16557149, + 12303181, + 20769192, + -81418272, + 130400957, + -88805858, + -164454829, + 1254863113, + 1254863113, + -164454829, + -88805858, + 130400957, + -81418272, + 20769192, + 12303181, + -16557149, + 8465644, + -1583082, + -587056, + 353927, + 399810, + -782927, + -1193774, + 8300356, + -17737486, + 15963244, + 15386278, + -78886170, + 138736468, + -115149411, + -123320903, + 1315459841, + 1190132305, + -200714015, + -62641219, + 120772392, + -82794712, + 25633191, + 8669411, + -15225415, + 8505059, + -1918817, + -402182, + 307905, + 444443, + -987440, + -752638, + 8002934, + -18740413, + 19599810, + 9533164, + -75179686, + 145609198, + -141343816, + -77422762, + 1371451404, + 1121766836, + -232034876, + -36966045, + 110029352, + -83048316, + 29938618, + 5108909, + -13768958, + 8426275, + -2200180, + -230265, + 262738, + 486605, + -1197853, + -262402, + 7568721, + -19541003, + 23160843, + 3267368, + -70295081, + 150860829, + -167046507, + -26917934, + 1422399613, + 1050289660, + -258400221, + -12070667, + 98356696, + -82225013, + 33655004, + 1665325, + -12214698, + 8238180, + -2427260, + -72870, + 219287, + 524986, + -1411054, + 273193, + 6994835, + -20115841, + 26592698, + -3345188, + -64244296, + 154346966, + -191903667, + 27989468, + 1467903427, + 976242261, + -279838233, + 11777215, + 85943021, + -80382681, + 36761065, + -1621451, + -10589407, + 7950668, + -2600972, + 68828, + 178284, + 558200, + -1623588, + 849377, + 6280333, + -20443466, + 29840809, + -10230707, + -57055468, + 155939580, + -215553721, + 87049666, + 1507602861, + 900179510, + -296421016, + 34334601, + 72978159, + -77589900, + 39244576, + -4715655, + -8919343, + 7574436, + -2722981, + 194031, + 140321, + 584810, + -1831686, + 1460357, + 5426344, + -20504787, + 32850419, + -17308178, + -48773260, + 155529332, + -237631016, + 149968630, + 1541182515, + 822664432, + -308262697, + 55384924, + 59650765, + -73924608, + 41102128, + -7585935, + -7229897, + 7120770, + -2795622, + 302300, + 105858, + 603355, + -2031310, + 2099338, + 4436183, + -20283504, + 35567360, + -24490171, + -39458975, + 153027759, + -257769657, + 216409962, + 1568374659, + 744262942, + -315517155, + 74739431, + 46146009, + -69472695, + 42338778, + -10205569, + -5545287, + 6601344, + -2821817, + 393534, + 75220, + 612379, + -2218199, + 2758559, + 3315438, + -19766501, + 37938848, + -31683753, + -29190455, + 148369295, + -275607461, + 285997265, + 1588961873, + 665538602, + -318375371, + 92238195, + 32643399, + -64326542, + 42967599, + -12552603, + -3888277, + 6028020, + -2804982, + 467940, + 48610, + 610456, + -2387933, + 3429356, + 2072025, + -18944209, + 39914305, + -38791522, + -18061759, + 141513067, + -290789985, + 358316955, + 1602779187, + 587047468, + -317062459, + 107750776, + 19314760, + -58583544, + 43009139, + -14609914, + -2279930, + 5412660, + -2748939, + 526002, + 26112, + 596232, + -2535989, + 4102230, + 716210, + -17810947, + 41446187, + -45712752, + -6182611, + 132444478, + -302974575, + 432921499, + 1609715705, + 509333054, + -311834407, + 121176514, + 6322387, + -52344623, + 42490807, + -16365208, + -739405, + 4766949, + -2657822, + 568453, + 7704 + +}; + +static const struct src_stage src_int32_21_10_2500_5000 = { + 9, 19, 21, 24, 504, 10, 21, 0, 0, + src_int32_21_10_2500_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_10_3455_5000.h b/src/audio/src/coef/src_ipc4_int32_21_10_3455_5000.h new file mode 100644 index 000000000000..d0188db84fca --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_10_3455_5000.h @@ -0,0 +1,774 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_10_3455_5000_fir[756] = { + -37222, + 240677, + -698458, + 1295354, + -1520654, + 429897, + 3067002, + -9532219, + 18105899, + -25790886, + 27415463, + -16623253, + -12163314, + 61374389, + -128484472, + 205846119, + -283409543, + 360907869, + 1814511418, + 270014725, + -253154661, + 198961588, + -132733783, + 69932459, + -20861951, + -9974463, + 23479387, + -24223348, + 18095222, + -10238142, + 3879123, + -180107, + -1178099, + 1154723, + -663476, + 240534, + -33409, + 235832, + -723258, + 1422313, + -1856452, + 1063380, + 2166218, + -8637242, + 17814748, + -26984771, + 31027371, + -23207483, + -2994836, + 51536950, + -121978029, + 209612046, + -310603720, + 455217434, + 1804747492, + 183236233, + -220441079, + 189183485, + -134732845, + 77114270, + -28965918, + -3369698, + 19292781, + -22320037, + 17793780, + -10750905, + 4593061, + -757648, + -834908, + 1003690, + -619701, + 235879, + -27800, + 225591, + -736589, + 1532374, + -2179151, + 1710496, + 1188246, + -7560717, + 17215410, + -27772093, + 34244491, + -29616248, + 6507093, + 40540919, + -113243634, + 210074356, + -334148373, + 552192374, + 1785315489, + 101210816, + -185875974, + 176772172, + -134523372, + 82847634, + -36363604, + 3086458, + 14931003, + -20123027, + 17216991, + -11069745, + 5201335, + -1294709, + -496890, + 845511, + -568581, + 227238, + -20298, + 209626, + -737289, + 1622422, + -2482294, + 2360680, + 146408, + -6313555, + 16306513, + -28125645, + 37000492, + -35738091, + 16196413, + 28529734, + -102347244, + 207092306, + -353475931, + 651036571, + 1756405969, + 24510918, + -150063794, + 162018289, + -132180182, + 87085474, + -42958003, + 9294989, + 10469862, + -17677752, + 16384224, + -11197118, + 5698539, + -1784336, + -169455, + 683368, + -511600, + 215173, + -10848, + 187706, + -724360, + 1689516, + -2759420, + 3002796, + -944288, + -4910025, + 15091877, + -28024571, + 39234587, + -41462836, + 25919500, + 15667864, + -89391740, + 200573165, + -368048039, + 750917213, + 1718301950, + -46362281, + -113598611, + 145237423, + -127809008, + 89805818, + -48667841, + 15163870, + 5984363, + -15032155, + 15318331, + -11138541, + 6081346, + -2220705, + 142463, + 520315, + -450239, + 200270, + 557, + 159709, + -696998, + 1730957, + -3004183, + 3625309, + -2067328, + -3367632, + 13580636, + -27454936, + 40892727, + -46683456, + 35517460, + 2138792, + -74516508, + 190475370, + -377363339, + 850973738, + 1671375565, + -110983200, + -77056797, + 126764588, + -121543907, + 91011406, + -53428408, + 20609349, + 1547523, + -12235819, + 14045152, + -10902375, + 6348475, + -2599170, + 434458, + 359234, + -385955, + 183120, + 13872, + 125635, + -654622, + 1744354, + -3210472, + 4216472, + -3204927, + -1706951, + 11787276, + -26410196, + 41928718, + -51297945, + 44828577, + -11857367, + -57896436, + 176811044, + -380964959, + 950327206, + 1616083665, + -169005202, + -40990131, + 106948586, + -113544311, + 90728914, + -57192105, + 25557044, + -2770760, + -9339100, + 12592978, + -10499579, + 6500626, + -2916284, + 702711, + 202791, + -320151, + 164307, + 28994, + 85613, + -596901, + 1727686, + -3372538, + 4764523, + -4338273, + 48617, + 9731583, + -24891553, + 42305245, + -55211163, + 53690884, + -26106592, + -39740329, + 159647817, + -378447587, + 1048090004, + 1552962440, + -220162919, + -5919416, + 86146346, + -103991775, + 89007823, + -59928703, + 29942857, + -6904742, + -6392278, + 10991998, + -9943426, + 6540384, + -3169804, + 944019, + 53401, + -254153, + 144400, + 45762, + 39913, + -523780, + 1679367, + -3485112, + 5257896, + -5447822, + 1873127, + 7438493, + -22908203, + 41994780, + -58336619, + 61944804, + -40383980, + -20288740, + 139109907, + -369464048, + 1143375755, + 1482621115, + -264273543, + 27671327, + 64717324, + -93086474, + 85918967, + -61625312, + 33713706, + -10793771, + -3444734, + 9273729, + -9249187, + 6472090, + -3358668, + 1155818, + -86799, + -189193, + 123935, + 63954, + -11053, + -435498, + 1598292, + -3543532, + 5685432, + -6513599, + 3738445, + 4937857, + -20477440, + 40980351, + -60598173, + 69435845, + -54457039, + 188751, + 115378433, + -353731267, + 1235309305, + 1405734814, + -301237074, + 59340010, + 43018035, + -81043531, + 81552779, + -62286079, + 36828039, + -14383110, + -544172, + 7470451, + -8433804, + 6301697, + -3482960, + 1336199, + -215975, + -126386, + 103412, + 83285, + -66722, + -332607, + 1483899, + -3543852, + 6036596, + -7515534, + 5614645, + 2264105, + -17624642, + 39256162, + -61931614, + 76017279, + -68089207, + 21396795, + 88690923, + -331035549, + 1323036671, + 1323036671, + -331035549, + 88690923, + 21396795, + -68089207, + 76017279, + -61931614, + 39256162, + -17624642, + 2264105, + 5614645, + -7515534, + 6036596, + -3543852, + 1483899, + -332607, + -66722, + 83285, + 103412, + -126386, + -215975, + 1336199, + -3482960, + 6301697, + -8433804, + 7470451, + -544172, + -14383110, + 36828039, + -62286079, + 81552779, + -81043531, + 43018035, + 59340010, + -301237074, + 1405734814, + 1235309305, + -353731267, + 115378433, + 188751, + -54457039, + 69435845, + -60598173, + 40980351, + -20477440, + 4937857, + 3738445, + -6513599, + 5685432, + -3543532, + 1598292, + -435498, + -11053, + 63954, + 123935, + -189193, + -86799, + 1155818, + -3358668, + 6472090, + -9249187, + 9273729, + -3444734, + -10793771, + 33713706, + -61625312, + 85918967, + -93086474, + 64717324, + 27671327, + -264273543, + 1482621115, + 1143375755, + -369464048, + 139109907, + -20288740, + -40383980, + 61944804, + -58336619, + 41994780, + -22908203, + 7438493, + 1873127, + -5447822, + 5257896, + -3485112, + 1679367, + -523780, + 39913, + 45762, + 144400, + -254153, + 53401, + 944019, + -3169804, + 6540384, + -9943426, + 10991998, + -6392278, + -6904742, + 29942857, + -59928703, + 89007823, + -103991775, + 86146346, + -5919416, + -220162919, + 1552962440, + 1048090004, + -378447587, + 159647817, + -39740329, + -26106592, + 53690884, + -55211163, + 42305245, + -24891553, + 9731583, + 48617, + -4338273, + 4764523, + -3372538, + 1727686, + -596901, + 85613, + 28994, + 164307, + -320151, + 202791, + 702711, + -2916284, + 6500626, + -10499579, + 12592978, + -9339100, + -2770760, + 25557044, + -57192105, + 90728914, + -113544311, + 106948586, + -40990131, + -169005202, + 1616083665, + 950327206, + -380964959, + 176811044, + -57896436, + -11857367, + 44828577, + -51297945, + 41928718, + -26410196, + 11787276, + -1706951, + -3204927, + 4216472, + -3210472, + 1744354, + -654622, + 125635, + 13872, + 183120, + -385955, + 359234, + 434458, + -2599170, + 6348475, + -10902375, + 14045152, + -12235819, + 1547523, + 20609349, + -53428408, + 91011406, + -121543907, + 126764588, + -77056797, + -110983200, + 1671375565, + 850973738, + -377363339, + 190475370, + -74516508, + 2138792, + 35517460, + -46683456, + 40892727, + -27454936, + 13580636, + -3367632, + -2067328, + 3625309, + -3004183, + 1730957, + -696998, + 159709, + 557, + 200270, + -450239, + 520315, + 142463, + -2220705, + 6081346, + -11138541, + 15318331, + -15032155, + 5984363, + 15163870, + -48667841, + 89805818, + -127809008, + 145237423, + -113598611, + -46362281, + 1718301950, + 750917213, + -368048039, + 200573165, + -89391740, + 15667864, + 25919500, + -41462836, + 39234587, + -28024571, + 15091877, + -4910025, + -944288, + 3002796, + -2759420, + 1689516, + -724360, + 187706, + -10848, + 215173, + -511600, + 683368, + -169455, + -1784336, + 5698539, + -11197118, + 16384224, + -17677752, + 10469862, + 9294989, + -42958003, + 87085474, + -132180182, + 162018289, + -150063794, + 24510918, + 1756405969, + 651036571, + -353475931, + 207092306, + -102347244, + 28529734, + 16196413, + -35738091, + 37000492, + -28125645, + 16306513, + -6313555, + 146408, + 2360680, + -2482294, + 1622422, + -737289, + 209626, + -20298, + 227238, + -568581, + 845511, + -496890, + -1294709, + 5201335, + -11069745, + 17216991, + -20123027, + 14931003, + 3086458, + -36363604, + 82847634, + -134523372, + 176772172, + -185875974, + 101210816, + 1785315489, + 552192374, + -334148373, + 210074356, + -113243634, + 40540919, + 6507093, + -29616248, + 34244491, + -27772093, + 17215410, + -7560717, + 1188246, + 1710496, + -2179151, + 1532374, + -736589, + 225591, + -27800, + 235879, + -619701, + 1003690, + -834908, + -757648, + 4593061, + -10750905, + 17793780, + -22320037, + 19292781, + -3369698, + -28965918, + 77114270, + -134732845, + 189183485, + -220441079, + 183236233, + 1804747492, + 455217434, + -310603720, + 209612046, + -121978029, + 51536950, + -2994836, + -23207483, + 31027371, + -26984771, + 17814748, + -8637242, + 2166218, + 1063380, + -1856452, + 1422313, + -723258, + 235832, + -33409, + 240534, + -663476, + 1154723, + -1178099, + -180107, + 3879123, + -10238142, + 18095222, + -24223348, + 23479387, + -9974463, + -20861951, + 69932459, + -132733783, + 198961588, + -253154661, + 270014725, + 1814511418, + 360907869, + -283409543, + 205846119, + -128484472, + 61374389, + -12163314, + -16623253, + 27415463, + -25790886, + 18105899, + -9532219, + 3067002, + 429897, + -1520654, + 1295354, + -698458, + 240677, + -37222 + +}; + +static const struct src_stage src_int32_21_10_3455_5000 = { + 9, 19, 21, 36, 756, 10, 21, 0, 0, + src_int32_21_10_3455_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_10_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_21_10_4535_5000.h new file mode 100644 index 000000000000..ae0134902654 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_10_4535_5000.h @@ -0,0 +1,2538 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_10_4535_5000_fir[2520] = { + -9118, + 18975, + -33943, + 54995, + -82872, + 117940, + -160017, + 208211, + -260758, + 314870, + -366630, + 410924, + -441439, + 450730, + -430383, + 371259, + -263850, + 98722, + 132945, + -438734, + 824309, + -1292697, + 1843551, + -2472440, + 3170208, + -3922412, + 4708916, + -5503651, + 6274581, + -6983906, + 7588524, + -8040750, + 8289310, + -8280580, + 7960060, + -7274037, + 6171399, + -4605531, + 2536230, + 68426, + -3230355, + 6959945, + -11254831, + 16099031, + -21462525, + 27301333, + -33558159, + 40163669, + -47038478, + 54095977, + -61246224, + 68401344, + -75483374, + 82436638, + -89249612, + 95999411, + -102958583, + 110910940, + -122417498, + 150847617, + 2045911189, + 49780144, + -73621046, + 80248920, + -81860709, + 80991261, + -78546322, + 74971518, + -70545219, + 65474691, + -59932830, + 54073176, + -48035924, + 41949879, + -35932535, + 30089335, + -24512682, + 19280987, + -14457960, + 10092229, + -6217334, + 2852120, + -1507, + -2342407, + 4198937, + -5597186, + 6574250, + -7173336, + 7441861, + -7429598, + 7186929, + -6763260, + 6205635, + -5557590, + 4858247, + -4141680, + 3436522, + -2765827, + 2147143, + -1592781, + 1110238, + -702741, + 369878, + -108272, + -87728, + 225385, + -312941, + 359062, + -372358, + 360991, + -332379, + 292994, + -248238, + 202406, + -158707, + 119346, + -85637, + 58144, + -36838, + 21255, + -7306, + 16178, + -30212, + 50580, + -78288, + 114035, + -158034, + 209839, + -268163, + 330703, + -394003, + 453342, + -502690, + 534726, + -540945, + 511857, + -437290, + 306793, + -110148, + -162027, + 517596, + -962164, + 1498300, + -2124761, + 2835751, + -3620254, + 4461484, + -5336481, + 6215905, + -7064056, + 7839131, + -8493768, + 8975841, + -9229545, + 9196718, + -8818396, + 8036540, + -6795894, + 5045895, + -2742572, + -149660, + 3656398, + -7791931, + 12558310, + -17944908, + 23928587, + -30474615, + 37538511, + -45069090, + 53013156, + -61322623, + 69965578, + -78944317, + 88327006, + -98308610, + 109342326, + -122466910, + 140298062, + -171094579, + 259079969, + 2032047900, + -43250443, + -25626202, + 48951185, + -59630005, + 64650558, + -66441211, + 66105259, + -64249240, + 61261552, + -57423293, + 52957334, + -48051453, + 42869503, + -37556682, + 32241806, + -27038074, + 22043130, + -17338894, + 12991427, + -9050995, + 5552410, + -2515680, + -53021, + 2160103, + -3823061, + 5068793, + -5931788, + 6452263, + -6674298, + 6644047, + -6408073, + 6011846, + -5498459, + 4907568, + -4274584, + 3630113, + -2999644, + 2403456, + -1856735, + 1369870, + -948877, + 595939, + -310013, + 87467, + 77274, + -191113, + 261712, + -296989, + 304696, + -292082, + 265646, + -230971, + 192638, + -154216, + 118294, + -86579, + 60004, + -38871, + 22993, + -5223, + 12903, + -25695, + 44950, + -71926, + 107644, + -152715, + 207155, + -270184, + 340038, + -413795, + 487225, + -554705, + 609184, + -642235, + 644200, + -604438, + 511680, + -354497, + 121876, + 196112, + -607564, + 1117941, + -1729242, + 2439182, + -3240424, + 4119895, + -5058234, + 6029414, + -7000564, + 7932042, + -8777759, + 9485789, + -9999254, + 10257483, + -10197416, + 9755216, + -8868046, + 7475942, + -5523696, + 2962686, + 247478, + -4137568, + 8727767, + -14027221, + 20034312, + -26737841, + 34119439, + -42157660, + 50834529, + -60145903, + 70118252, + -80837078, + 92498366, + -105509982, + 120714202, + -139949475, + 167775440, + -218690379, + 373484823, + 2004490579, + -127502505, + 20700565, + 17649282, + -36734413, + 47329816, + -53200605, + 56036934, + -56740477, + 55862794, + -53782090, + 50782941, + -47095015, + 42912684, + -38405103, + 33721291, + -28992551, + 24333477, + -19842305, + 15601004, + -11675391, + 8115400, + -4955608, + 2216030, + 96804, + -1988514, + 3475331, + -4582399, + 5341977, + -5791612, + 5972340, + -5926966, + 5698492, + -5328710, + 4857015, + -4319438, + 3747932, + -3169891, + 2607895, + -2079684, + 1598300, + -1172404, + 806706, + -502491, + 258201, + -70038, + -67440, + 160751, + -216973, + 243302, + -246677, + 233496, + -209412, + 179201, + -146713, + 114872, + -85735, + 60580, + -40030, + 24177, + -2901, + 9198, + -20456, + 38182, + -63864, + 98832, + -144087, + 200111, + -266658, + 342544, + -425443, + 511710, + -596242, + 672402, + -732010, + 765430, + -761759, + 709123, + -595099, + 407244, + -133744, + -235855, + 709826, + -1293399, + 1987880, + -2789790, + 3690065, + -4673366, + 5717526, + -6793195, + 7863703, + -8885177, + 9806942, + -10572189, + 11118950, + -11381313, + 11290902, + -10778526, + 9775971, + -8217845, + 6043392, + -3198157, + -364601, + 4682911, + -9785662, + 15692977, + -22417658, + 29968145, + -38353622, + 47592365, + -57725285, + 68838349, + -81101339, + 94839178, + -110674337, + 129842769, + -154999660, + 192724794, + -264216655, + 492961394, + 1963575278, + -202372670, + 64559625, + -13044396, + -13643811, + 29394079, + -39109004, + 44986732, + -48186374, + 49401891, + -49095748, + 47605457, + -45196074, + 42087366, + -38468225, + 34504302, + -30341941, + 26110069, + -21921015, + 17870807, + -14039323, + 10490474, + -7272584, + 4418997, + -1948953, + -131267, + 1826983, + -3153553, + 4134693, + -4800714, + 5186748, + -5331018, + 5273216, + -5053011, + 4708748, + -4276361, + 3788500, + -3273900, + 2756979, + -2257647, + 1791321, + -1369109, + 998128, + -681946, + 421085, + -213580, + 55542, + 58286, + -134015, + 178149, + -197184, + 197296, + -184094, + 162454, + -136429, + 109215, + -83175, + 59904, + -40326, + 24808, + -378, + 5125, + -14582, + 30383, + -54222, + 87716, + -132243, + 188750, + -257535, + 338024, + -428544, + 526111, + -626253, + 722882, + -808230, + 872875, + -905865, + 894953, + -826956, + 688240, + -465315, + 145560, + 281972, + -825670, + 1490435, + -2276753, + 3179790, + -4188566, + 5285259, + -6444657, + 7633825, + -8812015, + 9930830, + -10934686, + 11761559, + -12344008, + 12610471, + -12486767, + 11897767, + -10769164, + 9029228, + -6610463, + 3451013, + 504338, + -5303770, + 10988900, + -17596486, + 25161891, + -33725139, + 43340976, + -54095447, + 66133757, + -79709080, + 95273371, + -113660418, + 136495403, + -167249178, + 214556666, + -306674243, + 616314266, + 1909799957, + -267401520, + 105229120, + -42547469, + 9179109, + 11213508, + -24463145, + 33191258, + -38773129, + 42022165, + -43470857, + 43499967, + -42402809, + 40418955, + -37752439, + 34581653, + -31064631, + 27341731, + -23536873, + 19758020, + -16097336, + 12631285, + -9420841, + 6511896, + -3935914, + 1710856, + 157656, + -1674966, + 2855832, + -3722774, + 4304365, + -4633519, + 4745847, + -4678120, + 4466884, + -4147254, + 3751922, + -3310383, + 2848388, + -2387607, + 1945501, + -1535381, + 1166608, + -844936, + 572939, + -350503, + 175353, + -43580, + -49851, + 110629, + -144690, + 157866, + -155614, + 142816, + -123644, + 101500, + -79004, + 58031, + -39786, + 24898, + 2298, + 758, + -8173, + 21683, + -43155, + 74466, + -117351, + 173207, + -242879, + 326424, + -422862, + 529939, + -643909, + 759361, + -869097, + 964101, + -1033587, + 1065176, + -1045181, + 959030, + -791818, + 528983, + -157098, + -335247, + 956486, + -1711094, + 2598600, + -3612647, + 4740149, + -5960576, + 7245425, + -8557917, + 9852934, + -11077249, + 12170039, + -13063694, + 13684897, + -13955954, + 13796310, + -13124198, + 11858317, + -9919428, + 7231738, + -3723869, + -670781, + 6014620, + -12367789, + 19792092, + -28357914, + 38155854, + -49316118, + 62041478, + -76665588, + 93762427, + -114368608, + 140484582, + -176376258, + 232722490, + -345069028, + 742268771, + 1843817253, + -322277026, + 142074313, + -70317600, + 31287626, + -6843986, + -9565913, + 20898574, + -28701719, + 33883668, + -37031693, + 38559458, + -38780953, + 37949632, + -36279815, + 33958513, + -31151885, + 28008602, + -24661449, + 21227963, + -17810585, + 14496656, + -11358454, + 8453384, + -5824403, + 3500702, + -1498643, + -177067, + 1532005, + -2580509, + 3344068, + -3849671, + 4128173, + -4212735, + 4137387, + -3935736, + 3639863, + -3279433, + 2881004, + -2467559, + 2058241, + -1668275, + 1309061, + -988405, + 710858, + -478140, + 289618, + -142792, + 33792, + 42158, + -90319, + 116074, + -124623, + 120755, + -108681, + 91941, + -73355, + 55041, + -38454, + 24469, + 5075, + -3822, + -1348, + 12237, + -30852, + 59301, + -99642, + 153704, + -222871, + 307836, + -408341, + 522915, + -648623, + 780845, + -913105, + 1036971, + -1142047, + 1216062, + -1245093, + 1213914, + -1106485, + 906576, + -598521, + 168094, + 396538, + -1103786, + 1957590, + -2956385, + 4092125, + -5349414, + 6704795, + -8126229, + 9572817, + -10994785, + 12333757, + -13523322, + 14489890, + -15153812, + 15430718, + -15233006, + 14471407, + -13056500, + 10900025, + -7915822, + 4020130, + 869087, + -6834273, + 13962595, + -22353629, + 32132372, + -43471159, + 56627239, + -72009811, + 90306730, + -112743664, + 141672549, + -182113131, + 246726263, + -378428225, + 869487749, + 1766425016, + -366835690, + 174555259, + -95861533, + 52259272, + -24419940, + 5279767, + 8363086, + -18183682, + 25159764, + -29917516, + 32892753, + -34412284, + 34737333, + -34087501, + 32654166, + -30607903, + 28102430, + -25276514, + 22254721, + -19147562, + 16051368, + -13048151, + 10205572, + -7577118, + 5202532, + -3108505, + 1309621, + 190471, + -1397706, + 2326116, + -2996269, + 3433686, + -3667288, + 3727931, + -3647055, + 3455502, + -3182510, + 2854914, + -2496540, + 2127816, + -1765565, + 1422979, + -1109738, + 832262, + -594055, + 396114, + -237387, + 115229, + -25860, + -35212, + 72819, + -91806, + 96777, + -91902, + 80784, + -66390, + 51032, + -36387, + 23555, + 7896, + -8524, + 5765, + 2219, + -17536, + 42485, + -79414, + 130555, + -197808, + 282498, + -385105, + 504979, + -640063, + 786631, + -939064, + 1089694, + -1228717, + 1344222, + -1422323, + 1447438, + -1402698, + 1270514, + -1033277, + 674196, + -178248, + -466782, + 1269206, + -2232322, + 3353331, + -4622326, + 6021407, + -7523965, + 9094177, + -10686759, + 12246983, + -13710997, + 15006437, + -16053311, + 16765128, + -17050213, + 16813113, + -15956000, + 14379901, + -11985568, + 8673721, + -4344289, + -1105888, + 7787696, + -15828048, + 25384066, + -36667142, + 49984528, + -65814036, + 84946162, + -108776606, + 139975093, + -184252646, + 256135570, + -405816708, + 996589445, + 1678554765, + -401061416, + 202232688, + -118742985, + 71703484, + -41172211, + 19776943, + -4159627, + -7436739, + 16033487, + -22279603, + 26622143, + -29392805, + 30854422, + -31226831, + 30701482, + -29449609, + 27626635, + -25374316, + 22821587, + -20084664, + 17266815, + -14458027, + 11734756, + -9159854, + 6782729, + -4639783, + 2755106, + -1141426, + -198732, + 1271723, + -2091335, + 2677286, + -3053717, + 3247720, + -3287962, + 3203440, + -3022393, + 2771392, + -2474630, + 2153400, + -1825777, + 1506464, + -1206807, + 934949, + -696086, + 492814, + -325527, + 192847, + -92053, + 19498, + 29009, + -57869, + 71416, + -73694, + 68302, + -58292, + 46124, + -33659, + 22198, + 10700, + -13252, + 13022, + -8178, + -3457, + 24325, + -57027, + 104155, + -168098, + 250794, + -353461, + 476294, + -618167, + 776329, + -946143, + 1120861, + -1291480, + 1446685, + -1572906, + 1654509, + -1674129, + 1613154, + -1452364, + 1172716, + -756269, + 187213, + 547007, + -1454531, + 2537906, + -3792960, + 5207757, + -6761700, + 8424810, + -10157241, + 11909053, + -13620274, + 15221244, + -16633261, + 17769473, + -18535982, + 18833079, + -18556495, + 17598529, + -15848835, + 13194600, + -9519710, + 4702342, + 1389911, + -8908805, + 18040523, + -29031455, + 42233048, + -58182890, + 77759911, + -102505720, + 135364335, + -182653872, + 260591782, + -426353104, + 1122166277, + 1581258243, + -425082159, + 224772040, + -138589297, + 89268473, + -56781413, + 33640433, + -16417930, + 3319647, + 6693752, + -14278061, + 19880786, + -23830670, + 26386087, + -27762148, + 28146130, + -27706196, + 26596127, + -24957646, + 22921316, + -20606603, + 18121524, + -15562138, + 13012068, + -10542177, + 8210466, + -6062236, + 4130525, + -2436815, + 991969, + 202621, + -1153743, + 1874967, + -2385208, + 2707288, + -2866555, + 2889600, + -2803107, + 2632863, + -2402940, + 2135072, + -1848210, + 1558265, + -1278010, + 1017129, + -782391, + 577922, + -405540, + 265144, + -155114, + 72710, + -14455, + -23529, + 45221, + -54465, + 54786, + -49261, + 40446, + -30351, + 20448, + 13423, + -17902, + 20275, + -18744, + 11113, + 5166, + -32892, + 74976, + -134254, + 213248, + -313898, + 437252, + -583145, + 749874, + -933882, + 1129490, + -1328679, + 1520965, + -1693366, + 1830510, + -1914876, + 1927190, + -1846990, + 1653343, + -1325720, + 845001, + -194601, + -638338, + 1661707, + -2877200, + 4279136, + -5853394, + 7576491, + -9414872, + 11324435, + -13250334, + 15127056, + -16878808, + 18420150, + -19656878, + 20487053, + -20802085, + 20487729, + -19424778, + 17489173, + -14551122, + 10472618, + -5102434, + -1732931, + 10244930, + -20709959, + 33516620, + -49251672, + 68865483, + -94016625, + 127870473, + -177246565, + 259819200, + -439225396, + 1244804179, + 1475692283, + -439164426, + 241945638, + -155096735, + 104647206, + -70956786, + 46602308, + -28169099, + 13868686, + -2668517, + -6078512, + 12809900, + -17843871, + 21428495, + -23769375, + 25045527, + -25418417, + 25036902, + -24039676, + 22556182, + -20706632, + 18601525, + -16340973, + 14014006, + -11697998, + 9458297, + -7348122, + 5408722, + -3669831, + 2150371, + -859387, + -202828, + 1043476, + -1675913, + 2118270, + -2392100, + 2521080, + -2529826, + 2442833, + -2283577, + 2073797, + -1832938, + 1577793, + -1322291, + 1077454, + -851475, + 649908, + -475946, + 330752, + -213824, + 123375, + -56698, + 10510, + 18744, + -34634, + 40542, + -39511, + 34144, + -26556, + 18361, + 15998, + -22372, + 27368, + -29263, + 25880, + -14619, + -7469, + 43561, + -96888, + 170516, + -267077, + 388463, + -535486, + 707534, + -902215, + 1115044, + -1339157, + 1565118, + -1780799, + 1971398, + -2119586, + 2205808, + -2208755, + 2106005, + -1874828, + 1493150, + -940650, + 199970, + 742011, + -1892870, + 3253348, + -4816137, + 6564777, + -8472733, + 10502684, + -12606061, + 14722870, + -16781790, + 18700561, + -20386609, + 21737851, + -22643603, + 22985412, + -22637653, + 21467574, + -19334377, + 16086735, + -11557757, + 5555835, + 2151304, + -11864240, + 24000578, + -39184040, + 58416928, + -83441403, + 117582403, + -168034378, + 253632979, + -443705768, + 1363102232, + 1363102232, + -443705768, + 253632979, + -168034378, + 117582403, + -83441403, + 58416928, + -39184040, + 24000578, + -11864240, + 2151304, + 5555835, + -11557757, + 16086735, + -19334377, + 21467574, + -22637653, + 22985412, + -22643603, + 21737851, + -20386609, + 18700561, + -16781790, + 14722870, + -12606061, + 10502684, + -8472733, + 6564777, + -4816137, + 3253348, + -1892870, + 742011, + 199970, + -940650, + 1493150, + -1874828, + 2106005, + -2208755, + 2205808, + -2119586, + 1971398, + -1780799, + 1565118, + -1339157, + 1115044, + -902215, + 707534, + -535486, + 388463, + -267077, + 170516, + -96888, + 43561, + -7469, + -14619, + 25880, + -29263, + 27368, + -22372, + 15998, + 18361, + -26556, + 34144, + -39511, + 40542, + -34634, + 18744, + 10510, + -56698, + 123375, + -213824, + 330752, + -475946, + 649908, + -851475, + 1077454, + -1322291, + 1577793, + -1832938, + 2073797, + -2283577, + 2442833, + -2529826, + 2521080, + -2392100, + 2118270, + -1675913, + 1043476, + -202828, + -859387, + 2150371, + -3669831, + 5408722, + -7348122, + 9458297, + -11697998, + 14014006, + -16340973, + 18601525, + -20706632, + 22556182, + -24039676, + 25036902, + -25418417, + 25045527, + -23769375, + 21428495, + -17843871, + 12809900, + -6078512, + -2668517, + 13868686, + -28169099, + 46602308, + -70956786, + 104647206, + -155096735, + 241945638, + -439164426, + 1475692283, + 1244804179, + -439225396, + 259819200, + -177246565, + 127870473, + -94016625, + 68865483, + -49251672, + 33516620, + -20709959, + 10244930, + -1732931, + -5102434, + 10472618, + -14551122, + 17489173, + -19424778, + 20487729, + -20802085, + 20487053, + -19656878, + 18420150, + -16878808, + 15127056, + -13250334, + 11324435, + -9414872, + 7576491, + -5853394, + 4279136, + -2877200, + 1661707, + -638338, + -194601, + 845001, + -1325720, + 1653343, + -1846990, + 1927190, + -1914876, + 1830510, + -1693366, + 1520965, + -1328679, + 1129490, + -933882, + 749874, + -583145, + 437252, + -313898, + 213248, + -134254, + 74976, + -32892, + 5166, + 11113, + -18744, + 20275, + -17902, + 13423, + 20448, + -30351, + 40446, + -49261, + 54786, + -54465, + 45221, + -23529, + -14455, + 72710, + -155114, + 265144, + -405540, + 577922, + -782391, + 1017129, + -1278010, + 1558265, + -1848210, + 2135072, + -2402940, + 2632863, + -2803107, + 2889600, + -2866555, + 2707288, + -2385208, + 1874967, + -1153743, + 202621, + 991969, + -2436815, + 4130525, + -6062236, + 8210466, + -10542177, + 13012068, + -15562138, + 18121524, + -20606603, + 22921316, + -24957646, + 26596127, + -27706196, + 28146130, + -27762148, + 26386087, + -23830670, + 19880786, + -14278061, + 6693752, + 3319647, + -16417930, + 33640433, + -56781413, + 89268473, + -138589297, + 224772040, + -425082159, + 1581258243, + 1122166277, + -426353104, + 260591782, + -182653872, + 135364335, + -102505720, + 77759911, + -58182890, + 42233048, + -29031455, + 18040523, + -8908805, + 1389911, + 4702342, + -9519710, + 13194600, + -15848835, + 17598529, + -18556495, + 18833079, + -18535982, + 17769473, + -16633261, + 15221244, + -13620274, + 11909053, + -10157241, + 8424810, + -6761700, + 5207757, + -3792960, + 2537906, + -1454531, + 547007, + 187213, + -756269, + 1172716, + -1452364, + 1613154, + -1674129, + 1654509, + -1572906, + 1446685, + -1291480, + 1120861, + -946143, + 776329, + -618167, + 476294, + -353461, + 250794, + -168098, + 104155, + -57027, + 24325, + -3457, + -8178, + 13022, + -13252, + 10700, + 22198, + -33659, + 46124, + -58292, + 68302, + -73694, + 71416, + -57869, + 29009, + 19498, + -92053, + 192847, + -325527, + 492814, + -696086, + 934949, + -1206807, + 1506464, + -1825777, + 2153400, + -2474630, + 2771392, + -3022393, + 3203440, + -3287962, + 3247720, + -3053717, + 2677286, + -2091335, + 1271723, + -198732, + -1141426, + 2755106, + -4639783, + 6782729, + -9159854, + 11734756, + -14458027, + 17266815, + -20084664, + 22821587, + -25374316, + 27626635, + -29449609, + 30701482, + -31226831, + 30854422, + -29392805, + 26622143, + -22279603, + 16033487, + -7436739, + -4159627, + 19776943, + -41172211, + 71703484, + -118742985, + 202232688, + -401061416, + 1678554765, + 996589445, + -405816708, + 256135570, + -184252646, + 139975093, + -108776606, + 84946162, + -65814036, + 49984528, + -36667142, + 25384066, + -15828048, + 7787696, + -1105888, + -4344289, + 8673721, + -11985568, + 14379901, + -15956000, + 16813113, + -17050213, + 16765128, + -16053311, + 15006437, + -13710997, + 12246983, + -10686759, + 9094177, + -7523965, + 6021407, + -4622326, + 3353331, + -2232322, + 1269206, + -466782, + -178248, + 674196, + -1033277, + 1270514, + -1402698, + 1447438, + -1422323, + 1344222, + -1228717, + 1089694, + -939064, + 786631, + -640063, + 504979, + -385105, + 282498, + -197808, + 130555, + -79414, + 42485, + -17536, + 2219, + 5765, + -8524, + 7896, + 23555, + -36387, + 51032, + -66390, + 80784, + -91902, + 96777, + -91806, + 72819, + -35212, + -25860, + 115229, + -237387, + 396114, + -594055, + 832262, + -1109738, + 1422979, + -1765565, + 2127816, + -2496540, + 2854914, + -3182510, + 3455502, + -3647055, + 3727931, + -3667288, + 3433686, + -2996269, + 2326116, + -1397706, + 190471, + 1309621, + -3108505, + 5202532, + -7577118, + 10205572, + -13048151, + 16051368, + -19147562, + 22254721, + -25276514, + 28102430, + -30607903, + 32654166, + -34087501, + 34737333, + -34412284, + 32892753, + -29917516, + 25159764, + -18183682, + 8363086, + 5279767, + -24419940, + 52259272, + -95861533, + 174555259, + -366835690, + 1766425016, + 869487749, + -378428225, + 246726263, + -182113131, + 141672549, + -112743664, + 90306730, + -72009811, + 56627239, + -43471159, + 32132372, + -22353629, + 13962595, + -6834273, + 869087, + 4020130, + -7915822, + 10900025, + -13056500, + 14471407, + -15233006, + 15430718, + -15153812, + 14489890, + -13523322, + 12333757, + -10994785, + 9572817, + -8126229, + 6704795, + -5349414, + 4092125, + -2956385, + 1957590, + -1103786, + 396538, + 168094, + -598521, + 906576, + -1106485, + 1213914, + -1245093, + 1216062, + -1142047, + 1036971, + -913105, + 780845, + -648623, + 522915, + -408341, + 307836, + -222871, + 153704, + -99642, + 59301, + -30852, + 12237, + -1348, + -3822, + 5075, + 24469, + -38454, + 55041, + -73355, + 91941, + -108681, + 120755, + -124623, + 116074, + -90319, + 42158, + 33792, + -142792, + 289618, + -478140, + 710858, + -988405, + 1309061, + -1668275, + 2058241, + -2467559, + 2881004, + -3279433, + 3639863, + -3935736, + 4137387, + -4212735, + 4128173, + -3849671, + 3344068, + -2580509, + 1532005, + -177067, + -1498643, + 3500702, + -5824403, + 8453384, + -11358454, + 14496656, + -17810585, + 21227963, + -24661449, + 28008602, + -31151885, + 33958513, + -36279815, + 37949632, + -38780953, + 38559458, + -37031693, + 33883668, + -28701719, + 20898574, + -9565913, + -6843986, + 31287626, + -70317600, + 142074313, + -322277026, + 1843817253, + 742268771, + -345069028, + 232722490, + -176376258, + 140484582, + -114368608, + 93762427, + -76665588, + 62041478, + -49316118, + 38155854, + -28357914, + 19792092, + -12367789, + 6014620, + -670781, + -3723869, + 7231738, + -9919428, + 11858317, + -13124198, + 13796310, + -13955954, + 13684897, + -13063694, + 12170039, + -11077249, + 9852934, + -8557917, + 7245425, + -5960576, + 4740149, + -3612647, + 2598600, + -1711094, + 956486, + -335247, + -157098, + 528983, + -791818, + 959030, + -1045181, + 1065176, + -1033587, + 964101, + -869097, + 759361, + -643909, + 529939, + -422862, + 326424, + -242879, + 173207, + -117351, + 74466, + -43155, + 21683, + -8173, + 758, + 2298, + 24898, + -39786, + 58031, + -79004, + 101500, + -123644, + 142816, + -155614, + 157866, + -144690, + 110629, + -49851, + -43580, + 175353, + -350503, + 572939, + -844936, + 1166608, + -1535381, + 1945501, + -2387607, + 2848388, + -3310383, + 3751922, + -4147254, + 4466884, + -4678120, + 4745847, + -4633519, + 4304365, + -3722774, + 2855832, + -1674966, + 157656, + 1710856, + -3935914, + 6511896, + -9420841, + 12631285, + -16097336, + 19758020, + -23536873, + 27341731, + -31064631, + 34581653, + -37752439, + 40418955, + -42402809, + 43499967, + -43470857, + 42022165, + -38773129, + 33191258, + -24463145, + 11213508, + 9179109, + -42547469, + 105229120, + -267401520, + 1909799957, + 616314266, + -306674243, + 214556666, + -167249178, + 136495403, + -113660418, + 95273371, + -79709080, + 66133757, + -54095447, + 43340976, + -33725139, + 25161891, + -17596486, + 10988900, + -5303770, + 504338, + 3451013, + -6610463, + 9029228, + -10769164, + 11897767, + -12486767, + 12610471, + -12344008, + 11761559, + -10934686, + 9930830, + -8812015, + 7633825, + -6444657, + 5285259, + -4188566, + 3179790, + -2276753, + 1490435, + -825670, + 281972, + 145560, + -465315, + 688240, + -826956, + 894953, + -905865, + 872875, + -808230, + 722882, + -626253, + 526111, + -428544, + 338024, + -257535, + 188750, + -132243, + 87716, + -54222, + 30383, + -14582, + 5125, + -378, + 24808, + -40326, + 59904, + -83175, + 109215, + -136429, + 162454, + -184094, + 197296, + -197184, + 178149, + -134015, + 58286, + 55542, + -213580, + 421085, + -681946, + 998128, + -1369109, + 1791321, + -2257647, + 2756979, + -3273900, + 3788500, + -4276361, + 4708748, + -5053011, + 5273216, + -5331018, + 5186748, + -4800714, + 4134693, + -3153553, + 1826983, + -131267, + -1948953, + 4418997, + -7272584, + 10490474, + -14039323, + 17870807, + -21921015, + 26110069, + -30341941, + 34504302, + -38468225, + 42087366, + -45196074, + 47605457, + -49095748, + 49401891, + -48186374, + 44986732, + -39109004, + 29394079, + -13643811, + -13044396, + 64559625, + -202372670, + 1963575278, + 492961394, + -264216655, + 192724794, + -154999660, + 129842769, + -110674337, + 94839178, + -81101339, + 68838349, + -57725285, + 47592365, + -38353622, + 29968145, + -22417658, + 15692977, + -9785662, + 4682911, + -364601, + -3198157, + 6043392, + -8217845, + 9775971, + -10778526, + 11290902, + -11381313, + 11118950, + -10572189, + 9806942, + -8885177, + 7863703, + -6793195, + 5717526, + -4673366, + 3690065, + -2789790, + 1987880, + -1293399, + 709826, + -235855, + -133744, + 407244, + -595099, + 709123, + -761759, + 765430, + -732010, + 672402, + -596242, + 511710, + -425443, + 342544, + -266658, + 200111, + -144087, + 98832, + -63864, + 38182, + -20456, + 9198, + -2901, + 24177, + -40030, + 60580, + -85735, + 114872, + -146713, + 179201, + -209412, + 233496, + -246677, + 243302, + -216973, + 160751, + -67440, + -70038, + 258201, + -502491, + 806706, + -1172404, + 1598300, + -2079684, + 2607895, + -3169891, + 3747932, + -4319438, + 4857015, + -5328710, + 5698492, + -5926966, + 5972340, + -5791612, + 5341977, + -4582399, + 3475331, + -1988514, + 96804, + 2216030, + -4955608, + 8115400, + -11675391, + 15601004, + -19842305, + 24333477, + -28992551, + 33721291, + -38405103, + 42912684, + -47095015, + 50782941, + -53782090, + 55862794, + -56740477, + 56036934, + -53200605, + 47329816, + -36734413, + 17649282, + 20700565, + -127502505, + 2004490579, + 373484823, + -218690379, + 167775440, + -139949475, + 120714202, + -105509982, + 92498366, + -80837078, + 70118252, + -60145903, + 50834529, + -42157660, + 34119439, + -26737841, + 20034312, + -14027221, + 8727767, + -4137568, + 247478, + 2962686, + -5523696, + 7475942, + -8868046, + 9755216, + -10197416, + 10257483, + -9999254, + 9485789, + -8777759, + 7932042, + -7000564, + 6029414, + -5058234, + 4119895, + -3240424, + 2439182, + -1729242, + 1117941, + -607564, + 196112, + 121876, + -354497, + 511680, + -604438, + 644200, + -642235, + 609184, + -554705, + 487225, + -413795, + 340038, + -270184, + 207155, + -152715, + 107644, + -71926, + 44950, + -25695, + 12903, + -5223, + 22993, + -38871, + 60004, + -86579, + 118294, + -154216, + 192638, + -230971, + 265646, + -292082, + 304696, + -296989, + 261712, + -191113, + 77274, + 87467, + -310013, + 595939, + -948877, + 1369870, + -1856735, + 2403456, + -2999644, + 3630113, + -4274584, + 4907568, + -5498459, + 6011846, + -6408073, + 6644047, + -6674298, + 6452263, + -5931788, + 5068793, + -3823061, + 2160103, + -53021, + -2515680, + 5552410, + -9050995, + 12991427, + -17338894, + 22043130, + -27038074, + 32241806, + -37556682, + 42869503, + -48051453, + 52957334, + -57423293, + 61261552, + -64249240, + 66105259, + -66441211, + 64650558, + -59630005, + 48951185, + -25626202, + -43250443, + 2032047900, + 259079969, + -171094579, + 140298062, + -122466910, + 109342326, + -98308610, + 88327006, + -78944317, + 69965578, + -61322623, + 53013156, + -45069090, + 37538511, + -30474615, + 23928587, + -17944908, + 12558310, + -7791931, + 3656398, + -149660, + -2742572, + 5045895, + -6795894, + 8036540, + -8818396, + 9196718, + -9229545, + 8975841, + -8493768, + 7839131, + -7064056, + 6215905, + -5336481, + 4461484, + -3620254, + 2835751, + -2124761, + 1498300, + -962164, + 517596, + -162027, + -110148, + 306793, + -437290, + 511857, + -540945, + 534726, + -502690, + 453342, + -394003, + 330703, + -268163, + 209839, + -158034, + 114035, + -78288, + 50580, + -30212, + 16178, + -7306, + 21255, + -36838, + 58144, + -85637, + 119346, + -158707, + 202406, + -248238, + 292994, + -332379, + 360991, + -372358, + 359062, + -312941, + 225385, + -87728, + -108272, + 369878, + -702741, + 1110238, + -1592781, + 2147143, + -2765827, + 3436522, + -4141680, + 4858247, + -5557590, + 6205635, + -6763260, + 7186929, + -7429598, + 7441861, + -7173336, + 6574250, + -5597186, + 4198937, + -2342407, + -1507, + 2852120, + -6217334, + 10092229, + -14457960, + 19280987, + -24512682, + 30089335, + -35932535, + 41949879, + -48035924, + 54073176, + -59932830, + 65474691, + -70545219, + 74971518, + -78546322, + 80991261, + -81860709, + 80248920, + -73621046, + 49780144, + 2045911189, + 150847617, + -122417498, + 110910940, + -102958583, + 95999411, + -89249612, + 82436638, + -75483374, + 68401344, + -61246224, + 54095977, + -47038478, + 40163669, + -33558159, + 27301333, + -21462525, + 16099031, + -11254831, + 6959945, + -3230355, + 68426, + 2536230, + -4605531, + 6171399, + -7274037, + 7960060, + -8280580, + 8289310, + -8040750, + 7588524, + -6983906, + 6274581, + -5503651, + 4708916, + -3922412, + 3170208, + -2472440, + 1843551, + -1292697, + 824309, + -438734, + 132945, + 98722, + -263850, + 371259, + -430383, + 450730, + -441439, + 410924, + -366630, + 314870, + -260758, + 208211, + -160017, + 117940, + -82872, + 54995, + -33943, + 18975, + -9118 + +}; + +static const struct src_stage src_int32_21_10_4535_5000 = { + 9, 19, 21, 120, 2520, 10, 21, 0, 0, + src_int32_21_10_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_16_4319_5000.h b/src/audio/src/coef/src_ipc4_int32_21_16_4319_5000.h new file mode 100644 index 000000000000..fd8d48b9b1ef --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_16_4319_5000.h @@ -0,0 +1,1614 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_16_4319_5000_fir[1596] = { + -50136, + 105527, + -181643, + 273767, + -370546, + 452739, + -492719, + 455060, + -298466, + -20800, + 543985, + -1303606, + 2316267, + -3575139, + 5042812, + -6645386, + 8268666, + -9757263, + 10917264, + -11522850, + 11326924, + -10075426, + 7524601, + -3460108, + -2283466, + 9804349, + -19118353, + 30148435, + -42720670, + 56568151, + -71344292, + 86647632, + -102062496, + 117227465, + -131969693, + 146649758, + -163455919, + 195460608, + 1999639672, + 95676054, + -117160251, + 119581826, + -115382123, + 107427387, + -97018691, + 85033984, + -72192230, + 59121304, + -46369025, + 34396879, + -23570529, + 14152927, + -6302486, + 77060, + 4556530, + -7708351, + 9547939, + -10285150, + 10150859, + -9378942, + 8190749, + -6782899, + 5318901, + -3924671, + 2687707, + -1659390, + 859676, + -283364, + -92907, + 303693, + -388428, + 386227, + -332042, + 254258, + -173642, + 103406, + -49012, + 105542, + -186283, + 288505, + -402968, + 512338, + -590279, + 601539, + -503375, + 248496, + 210374, + -914434, + 1891557, + -3148358, + 4662306, + -6374692, + 8185369, + -9950140, + 11481545, + -12553572, + 12910502, + -12279729, + 10387938, + -6979656, + 1836750, + 5202846, + -14229144, + 25249007, + -38182311, + 52868091, + -69084561, + 86589884, + -105199040, + 124937087, + -146392741, + 171738560, + -208826248, + 301535426, + 1986682749, + 3028921, + -70811749, + 91104223, + -96999140, + 95768196, + -90199729, + 81808113, + -71634190, + 60495419, + -49069783, + 37921472, + -27505749, + 18168062, + -10144043, + 3563226, + 1542601, + -5226639, + 7610857, + -8867572, + 9200335, + -8825512, + 7955839, + -6786897, + 5487130, + -4191654, + 2999742, + -1975590, + 1151718, + -534257, + 109289, + 150516, + -279636, + 314322, + -288422, + 230551, + -162589, + 99337, + -46700, + 103332, + -187305, + 297978, + -428430, + 563600, + -678950, + 740068, + -703535, + 519331, + -134945, + -498869, + 1420891, + -2651258, + 4182955, + -5973784, + 7939743, + -9950725, + 11829390, + -13353868, + 14264645, + -14275614, + 13088873, + -10412336, + 5978842, + 435019, + -8992500, + 19785236, + -32829776, + 48076138, + -65434663, + 84833096, + -106330755, + 130360314, + -158314075, + 194297009, + -252373651, + 412950151, + 1960920376, + -81746345, + -25245209, + 61794025, + -77214189, + 82511565, + -81769112, + 77059062, + -69702893, + 60681523, + -50784431, + 40664329, + -30855176, + 21776785, + -13736354, + 6931711, + -1458260, + -2679947, + 5555493, + -7300285, + 8086980, + -8110530, + 7571132, + -6659645, + 5546214, + -4372494, + 3247515, + -2246908, + 1414970, + -768880, + 304276, + -1442, + -168593, + 238601, + -240723, + 203279, + -148846, + 93510, + -43166, + 98817, + -184522, + 301778, + -446169, + 605220, + -756690, + 867660, + -894834, + 786359, + -485385, + -64576, + 912645, + -2092297, + 3612383, + -5448251, + 7533854, + -9755841, + 11950516, + -13904463, + 15359321, + -16020863, + 15572098, + -13689621, + 10061948, + -4408066, + -3506079, + 13856029, + -26755911, + 42269456, + -60443679, + 81382222, + -105397135, + 133341118, + -167435579, + 213802714, + -293188812, + 528662376, + 1922653383, + -158035772, + 18754012, + 32225459, + -56437212, + 67943965, + -71918069, + 70903557, + -66456917, + 59693636, + -51494011, + 42583451, + -33562235, + 24914986, + -17013449, + 10119048, + -4388213, + -118471, + 3423364, + -5615898, + 6834904, + -7250467, + 7046606, + -6405911, + 5497004, + -4465335, + 3427512, + -2469030, + 1644967, + -983063, + 488446, + -149254, + -57533, + 160666, + -190025, + 173122, + -132810, + 86144, + -38404, + 91969, + -177817, + 299604, + -455548, + 636051, + -821617, + 981466, + -1073236, + 1044179, + -834110, + 380246, + 376106, + -1481316, + 2960162, + -4806241, + 6972964, + -9366113, + 11838943, + -14190692, + 16169147, + -17477556, + 17785782, + -16745065, + 14005229, + -9232595, + 2126203, + 7570808, + -20069013, + 35546194, + -54187629, + 76275276, + -102376604, + 133767224, + -173504825, + 229772504, + -330364552, + 647550271, + 1872327768, + -225351771, + 60460653, + 2959779, + -35086679, + 52370769, + -60861425, + 63483314, + -61979181, + 57568160, + -51199201, + 43653318, + -35583533, + 27528528, + -19916364, + 13066158, + -7191616, + 2408038, + 1256854, + -3848791, + 5470524, + -6264336, + 6394779, + -6032835, + 5342443, + -4470066, + 3537609, + -2638691, + 1837988, + -1173131, + 658490, + -290156, + 51379, + 82112, + -137429, + 140793, + -114910, + 77478, + -32435, + 82805, + -167149, + 291263, + -456085, + 655125, + -872055, + 1078837, + -1234859, + 1287450, + -1174164, + 827011, + -178690, + -829378, + 2237651, + -4058347, + 6265479, + -8786012, + 11493172, + -14202865, + 16673958, + -18612889, + 19682641, + -19515631, + 17729455, + -13943807, + 7796113, + 1047516, + -12890945, + 28023886, + -46768417, + 69583162, + -97287671, + 131573202, + -176320994, + 241772420, + -363010001, + 768426526, + 1810528484, + -283337122, + 99218982, + -25464370, + -13581656, + 36110132, + -48833101, + 54961926, + -56374977, + 54362851, + -49920024, + 43865153, + -36889517, + 29574157, + -22394185, + 15719438, + -9816064, + 4851223, + -901614, + -2034420, + 4022017, + -5173283, + 5630430, + -5549743, + 5087459, + -4388290, + 3577080, + -2753712, + 1991117, + -1335964, + 811462, + -421591, + 156080, + 4496, + -84038, + 107019, + -95592, + 67764, + -25312, + 71398, + -152562, + 276683, + -447457, + 661686, + -906567, + 1157385, + -1376061, + 1510993, + -1498610, + 1266915, + -741142, + -148568, + 1457806, + -3217436, + 5422839, + -8023831, + 10916290, + -13936531, + 16859281, + -19399886, + 21220928, + -21942979, + 21158579, + -18447835, + 13393163, + -5589565, + -5354949, + 19837454, + -38312268, + 61408863, + -90189329, + 126742735, + -175739990, + 249427133, + -390264861, + 890053399, + 1737971303, + -331767016, + 134450889, + -52539934, + 7665968, + 19486749, + -36081332, + 45521382, + -49769609, + 50155399, + -47695193, + 43226850, + -37464857, + 31020188, + -24404922, + 18031718, + -12213362, + 7165047, + -3010409, + -208614, + 2518742, + -4000144, + 4770264, + -4967935, + 4738843, + -4223259, + 3546588, + -2813026, + 2102278, + -1469050, + 944820, + -541258, + 254651, + -70692, + -30929, + 72527, + -75310, + 57265, + -17117, + 57870, + -134185, + 255919, + -429521, + 655204, + -923999, + 1215032, + -1493513, + 1709897, + -1800666, + 1691106, + -1300286, + 548227, + 634955, + -2298436, + 4459341, + -7091586, + 10115983, + -13392647, + 16716703, + -19818020, + 22365337, + -23974675, + 24221271, + -22653562, + 18806738, + -12212156, + 2396785, + 11136845, + -28967663, + 51886004, + -81180700, + 119310006, + -171678627, + 252428616, + -411313524, + 1011158663, + 1655492889, + -370549136, + 165662533, + -77799634, + 28258940, + 2825612, + -22863692, + 35358288, + -42305686, + 45041638, + -44581091, + 41762598, + -37308540, + 31846959, + -25916198, + 19963083, + -14340398, + 9306644, + -5029480, + 1593128, + 990659, + -2768969, + 3832566, + -4300422, + 4305074, + -3979777, + 3448142, + -2816670, + 2170259, + -1570515, + 1056471, + -647148, + 345350, + -142059, + 20863, + 38030, + -54519, + 46245, + -7965, + 42398, + -112229, + 229158, + -402317, + 635400, + -923507, + 1250064, + -1584283, + 1879632, + -2073843, + 2090855, + -1845003, + 1247557, + -215463, + -1318082, + 3391906, + -6004839, + 9104452, + -12577642, + 16244128, + -19853703, + 23087783, + -25565303, + 26852386, + -26474434, + 23928257, + -18690427, + 10215765, + 2084332, + -18902807, + 41176791, + -70399890, + 109360162, + -164117799, + 250543891, + -425398828, + 1130452224, + 1564039215, + -399721803, + 192449463, + -100823241, + 47821674, + -13554117, + -9442044, + 24679875, + -34140121, + 39133444, + -40650444, + 39512185, + -36433695, + 32047045, + -26905737, + 21481547, + -16159902, + 11237109, + -6921112, + 3336316, + -532268, + -1504541, + 2836808, + -3561650, + 3796130, + -3664080, + 3285030, + -2765764, + 2194716, + -1639146, + 1144799, + -737578, + 426641, + -208332, + 70366, + 4213, + -33662, + 34965, + 2003, + 25210, + -86993, + 196714, + -366078, + 602255, + -904583, + 1261178, + -1645894, + 2016139, + -2312086, + 2457735, + -2364239, + 1935665, + -1077183, + -294609, + 2239790, + -4782445, + 7898246, + -11503375, + 15445914, + -19500661, + 23368059, + -26677455, + 28994321, + -29830228, + 28653328, + -24895516, + 17950001, + -7148452, + -8302678, + 29469367, + -58022084, + 97028817, + -153104543, + 243621713, + -431835220, + 1246643157, + 1464652508, + -419450254, + 214500170, + -121243834, + 66006724, + -29345001, + 3922521, + 13699868, + -25440906, + 32556348, + -35990683, + 36530013, + -34867147, + 31625232, + -27361663, + 22563561, + -17641089, + 12922188, + -8650621, + 4988126, + -2020652, + -231882, + 1803259, + -2767191, + 3223263, + -3283685, + 3061728, + -2662463, + 2176160, + -1674398, + 1208685, + -811211, + 497216, + -268379, + 116689, + -28279, + -13162, + 23676, + 12616, + 6582, + -58858, + 159034, + -321227, + 556019, + -867078, + 1247514, + -1676392, + 2115929, + -2509897, + 2783795, + -2847222, + 2598755, + -1933420, + 752576, + 1024242, + -3446239, + 6518008, + -10186982, + 14332878, + -18760159, + 23194345, + -27282580, + 30598257, + -32648708, + 32883849, + -30702057, + 25446923, + -16383722, + 2634294, + 16974626, + -44256896, + 82500596, + -138752946, + 231598039, + -430021119, + 1358456924, + 1358456924, + -430021119, + 231598039, + -138752946, + 82500596, + -44256896, + 16974626, + 2634294, + -16383722, + 25446923, + -30702057, + 32883849, + -32648708, + 30598257, + -27282580, + 23194345, + -18760159, + 14332878, + -10186982, + 6518008, + -3446239, + 1024242, + 752576, + -1933420, + 2598755, + -2847222, + 2783795, + -2509897, + 2115929, + -1676392, + 1247514, + -867078, + 556019, + -321227, + 159034, + -58858, + 6582, + 12616, + 23676, + -13162, + -28279, + 116689, + -268379, + 497216, + -811211, + 1208685, + -1674398, + 2176160, + -2662463, + 3061728, + -3283685, + 3223263, + -2767191, + 1803259, + -231882, + -2020652, + 4988126, + -8650621, + 12922188, + -17641089, + 22563561, + -27361663, + 31625232, + -34867147, + 36530013, + -35990683, + 32556348, + -25440906, + 13699868, + 3922521, + -29345001, + 66006724, + -121243834, + 214500170, + -419450254, + 1464652508, + 1246643157, + -431835220, + 243621713, + -153104543, + 97028817, + -58022084, + 29469367, + -8302678, + -7148452, + 17950001, + -24895516, + 28653328, + -29830228, + 28994321, + -26677455, + 23368059, + -19500661, + 15445914, + -11503375, + 7898246, + -4782445, + 2239790, + -294609, + -1077183, + 1935665, + -2364239, + 2457735, + -2312086, + 2016139, + -1645894, + 1261178, + -904583, + 602255, + -366078, + 196714, + -86993, + 25210, + 2003, + 34965, + -33662, + 4213, + 70366, + -208332, + 426641, + -737578, + 1144799, + -1639146, + 2194716, + -2765764, + 3285030, + -3664080, + 3796130, + -3561650, + 2836808, + -1504541, + -532268, + 3336316, + -6921112, + 11237109, + -16159902, + 21481547, + -26905737, + 32047045, + -36433695, + 39512185, + -40650444, + 39133444, + -34140121, + 24679875, + -9442044, + -13554117, + 47821674, + -100823241, + 192449463, + -399721803, + 1564039215, + 1130452224, + -425398828, + 250543891, + -164117799, + 109360162, + -70399890, + 41176791, + -18902807, + 2084332, + 10215765, + -18690427, + 23928257, + -26474434, + 26852386, + -25565303, + 23087783, + -19853703, + 16244128, + -12577642, + 9104452, + -6004839, + 3391906, + -1318082, + -215463, + 1247557, + -1845003, + 2090855, + -2073843, + 1879632, + -1584283, + 1250064, + -923507, + 635400, + -402317, + 229158, + -112229, + 42398, + -7965, + 46245, + -54519, + 38030, + 20863, + -142059, + 345350, + -647148, + 1056471, + -1570515, + 2170259, + -2816670, + 3448142, + -3979777, + 4305074, + -4300422, + 3832566, + -2768969, + 990659, + 1593128, + -5029480, + 9306644, + -14340398, + 19963083, + -25916198, + 31846959, + -37308540, + 41762598, + -44581091, + 45041638, + -42305686, + 35358288, + -22863692, + 2825612, + 28258940, + -77799634, + 165662533, + -370549136, + 1655492889, + 1011158663, + -411313524, + 252428616, + -171678627, + 119310006, + -81180700, + 51886004, + -28967663, + 11136845, + 2396785, + -12212156, + 18806738, + -22653562, + 24221271, + -23974675, + 22365337, + -19818020, + 16716703, + -13392647, + 10115983, + -7091586, + 4459341, + -2298436, + 634955, + 548227, + -1300286, + 1691106, + -1800666, + 1709897, + -1493513, + 1215032, + -923999, + 655204, + -429521, + 255919, + -134185, + 57870, + -17117, + 57265, + -75310, + 72527, + -30929, + -70692, + 254651, + -541258, + 944820, + -1469050, + 2102278, + -2813026, + 3546588, + -4223259, + 4738843, + -4967935, + 4770264, + -4000144, + 2518742, + -208614, + -3010409, + 7165047, + -12213362, + 18031718, + -24404922, + 31020188, + -37464857, + 43226850, + -47695193, + 50155399, + -49769609, + 45521382, + -36081332, + 19486749, + 7665968, + -52539934, + 134450889, + -331767016, + 1737971303, + 890053399, + -390264861, + 249427133, + -175739990, + 126742735, + -90189329, + 61408863, + -38312268, + 19837454, + -5354949, + -5589565, + 13393163, + -18447835, + 21158579, + -21942979, + 21220928, + -19399886, + 16859281, + -13936531, + 10916290, + -8023831, + 5422839, + -3217436, + 1457806, + -148568, + -741142, + 1266915, + -1498610, + 1510993, + -1376061, + 1157385, + -906567, + 661686, + -447457, + 276683, + -152562, + 71398, + -25312, + 67764, + -95592, + 107019, + -84038, + 4496, + 156080, + -421591, + 811462, + -1335964, + 1991117, + -2753712, + 3577080, + -4388290, + 5087459, + -5549743, + 5630430, + -5173283, + 4022017, + -2034420, + -901614, + 4851223, + -9816064, + 15719438, + -22394185, + 29574157, + -36889517, + 43865153, + -49920024, + 54362851, + -56374977, + 54961926, + -48833101, + 36110132, + -13581656, + -25464370, + 99218982, + -283337122, + 1810528484, + 768426526, + -363010001, + 241772420, + -176320994, + 131573202, + -97287671, + 69583162, + -46768417, + 28023886, + -12890945, + 1047516, + 7796113, + -13943807, + 17729455, + -19515631, + 19682641, + -18612889, + 16673958, + -14202865, + 11493172, + -8786012, + 6265479, + -4058347, + 2237651, + -829378, + -178690, + 827011, + -1174164, + 1287450, + -1234859, + 1078837, + -872055, + 655125, + -456085, + 291263, + -167149, + 82805, + -32435, + 77478, + -114910, + 140793, + -137429, + 82112, + 51379, + -290156, + 658490, + -1173131, + 1837988, + -2638691, + 3537609, + -4470066, + 5342443, + -6032835, + 6394779, + -6264336, + 5470524, + -3848791, + 1256854, + 2408038, + -7191616, + 13066158, + -19916364, + 27528528, + -35583533, + 43653318, + -51199201, + 57568160, + -61979181, + 63483314, + -60861425, + 52370769, + -35086679, + 2959779, + 60460653, + -225351771, + 1872327768, + 647550271, + -330364552, + 229772504, + -173504825, + 133767224, + -102376604, + 76275276, + -54187629, + 35546194, + -20069013, + 7570808, + 2126203, + -9232595, + 14005229, + -16745065, + 17785782, + -17477556, + 16169147, + -14190692, + 11838943, + -9366113, + 6972964, + -4806241, + 2960162, + -1481316, + 376106, + 380246, + -834110, + 1044179, + -1073236, + 981466, + -821617, + 636051, + -455548, + 299604, + -177817, + 91969, + -38404, + 86144, + -132810, + 173122, + -190025, + 160666, + -57533, + -149254, + 488446, + -983063, + 1644967, + -2469030, + 3427512, + -4465335, + 5497004, + -6405911, + 7046606, + -7250467, + 6834904, + -5615898, + 3423364, + -118471, + -4388213, + 10119048, + -17013449, + 24914986, + -33562235, + 42583451, + -51494011, + 59693636, + -66456917, + 70903557, + -71918069, + 67943965, + -56437212, + 32225459, + 18754012, + -158035772, + 1922653383, + 528662376, + -293188812, + 213802714, + -167435579, + 133341118, + -105397135, + 81382222, + -60443679, + 42269456, + -26755911, + 13856029, + -3506079, + -4408066, + 10061948, + -13689621, + 15572098, + -16020863, + 15359321, + -13904463, + 11950516, + -9755841, + 7533854, + -5448251, + 3612383, + -2092297, + 912645, + -64576, + -485385, + 786359, + -894834, + 867660, + -756690, + 605220, + -446169, + 301778, + -184522, + 98817, + -43166, + 93510, + -148846, + 203279, + -240723, + 238601, + -168593, + -1442, + 304276, + -768880, + 1414970, + -2246908, + 3247515, + -4372494, + 5546214, + -6659645, + 7571132, + -8110530, + 8086980, + -7300285, + 5555493, + -2679947, + -1458260, + 6931711, + -13736354, + 21776785, + -30855176, + 40664329, + -50784431, + 60681523, + -69702893, + 77059062, + -81769112, + 82511565, + -77214189, + 61794025, + -25245209, + -81746345, + 1960920376, + 412950151, + -252373651, + 194297009, + -158314075, + 130360314, + -106330755, + 84833096, + -65434663, + 48076138, + -32829776, + 19785236, + -8992500, + 435019, + 5978842, + -10412336, + 13088873, + -14275614, + 14264645, + -13353868, + 11829390, + -9950725, + 7939743, + -5973784, + 4182955, + -2651258, + 1420891, + -498869, + -134945, + 519331, + -703535, + 740068, + -678950, + 563600, + -428430, + 297978, + -187305, + 103332, + -46700, + 99337, + -162589, + 230551, + -288422, + 314322, + -279636, + 150516, + 109289, + -534257, + 1151718, + -1975590, + 2999742, + -4191654, + 5487130, + -6786897, + 7955839, + -8825512, + 9200335, + -8867572, + 7610857, + -5226639, + 1542601, + 3563226, + -10144043, + 18168062, + -27505749, + 37921472, + -49069783, + 60495419, + -71634190, + 81808113, + -90199729, + 95768196, + -96999140, + 91104223, + -70811749, + 3028921, + 1986682749, + 301535426, + -208826248, + 171738560, + -146392741, + 124937087, + -105199040, + 86589884, + -69084561, + 52868091, + -38182311, + 25249007, + -14229144, + 5202846, + 1836750, + -6979656, + 10387938, + -12279729, + 12910502, + -12553572, + 11481545, + -9950140, + 8185369, + -6374692, + 4662306, + -3148358, + 1891557, + -914434, + 210374, + 248496, + -503375, + 601539, + -590279, + 512338, + -402968, + 288505, + -186283, + 105542, + -49012, + 103406, + -173642, + 254258, + -332042, + 386227, + -388428, + 303693, + -92907, + -283364, + 859676, + -1659390, + 2687707, + -3924671, + 5318901, + -6782899, + 8190749, + -9378942, + 10150859, + -10285150, + 9547939, + -7708351, + 4556530, + 77060, + -6302486, + 14152927, + -23570529, + 34396879, + -46369025, + 59121304, + -72192230, + 85033984, + -97018691, + 107427387, + -115382123, + 119581826, + -117160251, + 95676054, + 1999639672, + 195460608, + -163455919, + 146649758, + -131969693, + 117227465, + -102062496, + 86647632, + -71344292, + 56568151, + -42720670, + 30148435, + -19118353, + 9804349, + -2283466, + -3460108, + 7524601, + -10075426, + 11326924, + -11522850, + 10917264, + -9757263, + 8268666, + -6645386, + 5042812, + -3575139, + 2316267, + -1303606, + 543985, + -20800, + -298466, + 455060, + -492719, + 452739, + -370546, + 273767, + -181643, + 105527, + -50136 + +}; + +static const struct src_stage src_int32_21_16_4319_5000 = { + 3, 4, 21, 76, 1596, 16, 21, 0, 0, + src_int32_21_16_4319_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_16_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_21_16_4535_5000.h new file mode 100644 index 000000000000..7308ab4368ae --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_16_4535_5000.h @@ -0,0 +1,2454 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_16_4535_5000_fir[2436] = { + -15208, + 29050, + -48628, + 74549, + -106994, + 145545, + -189014, + 235283, + -281165, + 322309, + -353158, + 366976, + -355960, + 311445, + -224208, + 84880, + 115544, + -385110, + 730225, + -1154931, + 1660149, + -2242936, + 2895784, + -3606007, + 4355252, + -5119183, + 5867360, + -6563369, + 7165194, + -7625879, + 7894463, + -7917187, + 7638949, + -7004975, + 5962663, + -4463526, + 2465182, + 66691, + -3156526, + 6817230, + -11048851, + 15837594, + -21155300, + 26959432, + -33193646, + 39789021, + -46666020, + 53737323, + -60911749, + 68099712, + -75221153, + 82218013, + -89076218, + 95870291, + -102870277, + 110857698, + -122391611, + 150839845, + 2045911288, + 49777322, + -73604718, + 80209153, + -81788802, + 80880225, + -78391268, + 74769949, + -70297191, + 65182859, + -59602351, + 53711503, + -47652476, + 41555624, + -35539493, + 29710042, + -24159623, + 18966043, + -14191887, + 9884190, + -6074518, + 2779452, + -1464, + -2269858, + 4056300, + -5389281, + 6307962, + -6857287, + 7086014, + -7044817, + 6784527, + -6354540, + 5801463, + -5168002, + 4492117, + -3806457, + 3138049, + -2508237, + 1932836, + -1422478, + 983105, + -616569, + 321306, + -93042, + -74504, + 188951, + -258643, + 292111, + -297628, + 282859, + -254605, + 218644, + -179655, + 141217, + -105867, + 75207, + -50041, + 30525, + -13673, + 26879, + -46127, + 72299, + -105916, + 146960, + -194686, + 247442, + -302503, + 355935, + -402515, + 435707, + -447721, + 429666, + -371806, + 263920, + -95778, + -142288, + 458712, + -859959, + 1349734, + -1928181, + 2591098, + -3329209, + 4127549, + -4964984, + 5813917, + -6640222, + 7403427, + -8057168, + 8549937, + -8826106, + 8827227, + -8493576, + 7765895, + -6587291, + 4905199, + -2673368, + -146257, + 3581818, + -7650116, + 12355561, + -17689620, + 23630886, + -30145909, + 37190975, + -44715114, + 52664774, + -60990963, + 69660348, + -78673366, + 88095967, + -98120662, + 109198070, + -122364378, + 140232853, + -171060123, + 259067894, + 2032047499, + -43247758, + -25620247, + 48926156, + -59576376, + 64560231, + -66307962, + 65925094, + -64020636, + 60985576, + -57103595, + 52600006, + -47664776, + 42463583, + -37143002, + 31832716, + -26646238, + 21680967, + -17018034, + 12722210, + -8842038, + 5410256, + -2444549, + -51372, + 2086407, + -3680460, + 4862648, + -5669407, + 6142546, + -6327334, + 6270673, + -6019423, + 5618911, + -5111675, + 4536453, + -3927433, + 3313772, + -2719352, + 2162776, + -1657559, + 1212494, + -832143, + 517425, + -266261, + 74238, + 64741, + -157841, + 212744, + -237173, + 238507, + -223478, + 197969, + -166892, + 134143, + -102624, + 74313, + -50377, + 31305, + -11742, + 24029, + -42549, + 68451, + -102590, + 145352, + -196459, + 254763, + -318059, + 382918, + -444555, + 496766, + -531929, + 541103, + -514222, + 440409, + -308399, + 107077, + 173874, + -543236, + 1007454, + -1569784, + 2229445, + -2980794, + 3812582, + -4707331, + 5640864, + -6582052, + 7492794, + -8328257, + 9037421, + -9563898, + 9847051, + -9823375, + 9428115, + -8597058, + 7268459, + -5384991, + 2895656, + 242457, + -4062682, + 8587684, + -13828901, + 19786698, + -26451462, + 33805934, + -41829240, + 50503416, + -59823762, + 69815645, + -80562981, + 92259752, + -105311509, + 120558016, + -139835135, + 167699979, + -218648487, + 373469158, + 2004489199, + -127493870, + 20695531, + 17639975, + -36700597, + 47262437, + -53092221, + 55882131, + -56536179, + 55608461, + -53479786, + 50437281, + -46712978, + 42503317, + -37979129, + 33290634, + -28569804, + 23931356, + -19473088, + 15276007, + -11404488, + 7906625, + -4814839, + 2146779, + 93487, + -1914031, + 3333417, + -4378905, + 5084568, + -5489404, + 5635480, + -5566201, + 5324722, + -4952565, + 4488465, + -3967459, + 3420232, + -2872709, + 2345884, + -1855861, + 1414082, + -1027700, + 700076, + -431342, + 219020, + -58640, + -55659, + 130568, + -173118, + 190256, + -188517, + 173773, + -151071, + 124543, + -97395, + 71937, + -49672, + 31404, + -9437, + 20529, + -37931, + 63033, + -97016, + 140671, + -194194, + 256976, + -327382, + 402558, + -478261, + 548745, + -606711, + 643340, + -648437, + 610675, + -517965, + 357954, + -118627, + -210965, + 639904, + -1174527, + 1817520, + -2567021, + 3415757, + -4350289, + 5350378, + -6388544, + 7429841, + -8431887, + 9345182, + -10113712, + 10675860, + -10965601, + 10913951, + -10450638, + 9505920, + -8012488, + 5907354, + -3133613, + -358039, + 4608190, + -9648169, + 15500298, + -22179240, + 29694863, + -38057274, + 47285122, + -57419120, + 68544477, + -80829687, + 94597921, + -110469523, + 129678044, + -154876120, + 192640957, + -264168575, + 492942897, + 1963572480, + -202357771, + 64543212, + -13037306, + -13630958, + 29351448, + -39028077, + 44860776, + -48010816, + 49174591, + -48817145, + 47278595, + -44826494, + 41682882, + -38038587, + 34060773, + -29896802, + 25676083, + -21510868, + 17496568, + -13711932, + 10219297, + -7065041, + 4280285, + -1881885, + -126330, + 1752076, + -3012958, + 3934693, + -4549271, + 4893124, + -5005361, + 4926119, + -4695088, + 4350226, + -3926716, + 3456146, + -2965951, + 2479078, + -2013876, + 1584182, + -1199576, + 865765, + -585070, + 356975, + -178705, + 45806, + 47304, + -106831, + 139165, + -150516, + 146632, + -132591, + 112683, + -90346, + 68177, + -47978, + 30850, + -6790, + 16429, + -32330, + 56106, + -89244, + 132929, + -187838, + 253915, + -330138, + 414293, + -502770, + 590399, + -670351, + 734111, + -771550, + 771112, + -720121, + 605210, + -412894, + 130249, + 254288, + -750036, + 1363133, + -2095566, + 2944224, + -3900012, + 4947070, + -6062152, + 7214198, + -8364151, + 9465042, + -10462368, + 11294773, + -11895029, + 12191296, + -12108623, + 11570640, + -10501360, + 8827010, + -6477763, + 3389247, + 496338, + -5229713, + 10854869, + -17410664, + 24934177, + -33466687, + 43063672, + -53811343, + 65854499, + -79445355, + 95034398, + -113453514, + 136325644, + -167119172, + 214466446, + -306621301, + 616293714, + 1909795360, + -267380191, + 105201176, + -42523640, + 9170263, + 11196943, + -24411735, + 33097079, + -38630199, + 41826782, + -43221824, + 43198697, + -42053295, + 40027622, + -37327875, + 34134242, + -30606100, + 26884640, + -23094069, + 19342089, + -15720070, + 12303198, + -9150747, + 6306577, + -3799886, + 1646237, + 151166, + -1599997, + 2717161, + -3527059, + 4059800, + -4349452, + 4432360, + -4345602, + 4125614, + -3807019, + 3421677, + -2997972, + 2560329, + -2128959, + 1719798, + -1344637, + 1011395, + -724511, + 485420, + -293079, + 144511, + -35340, + -39703, + 86332, + -110316, + 117165, + -111896, + 98864, + -81676, + 63156, + -45369, + 29686, + -3840, + 11790, + -25831, + 47768, + -79372, + 122204, + -177417, + 245517, + -326124, + 417715, + -517391, + 620671, + -721336, + 811344, + -880839, + 918263, + -910592, + 843709, + -702905, + 473523, + -141724, + -304639, + 875063, + -1575384, + 2406750, + -3364635, + 4437914, + -5608079, + 6848617, + -8124608, + 9392587, + -10600672, + 11689015, + -12590540, + 13231988, + -13535224, + 13418758, + -12799421, + 11594089, + -9721363, + 7103028, + -3665148, + -661474, + 5941746, + -12238107, + 19614336, + -28142379, + 37913910, + -49059662, + 61782362, + -76415051, + 93530553, + -114163842, + 140313332, + -176242591, + 232627953, + -345012594, + 742246935, + 1843810551, + -322249261, + 142034944, + -70277042, + 31256786, + -6833689, + -9545499, + 20838484, + -28594674, + 33724473, + -36817537, + 38290092, + -38458744, + 37579489, + -35868995, + 33516319, + -30689259, + 27537656, + -24194941, + 20778749, + -17391076, + 14118309, + -11031305, + 8185664, + -5622242, + 3367930, + -1436700, + -169111, + 1457330, + -2444337, + 3153370, + -3612813, + 3854525, + -3912258, + 3820211, + -3611764, + 3318412, + -2968918, + 2588689, + -2199376, + 1818679, + -1460345, + 1134325, + -847068, + 601910, + -399542, + 238504, + -115701, + 26889, + 32864, + -68780, + 86029, + -89464, + 83425, + -71612, + 57021, + -41935, + 27964, + -639, + 6690, + -18537, + 38148, + -67544, + 108640, + -163047, + 231833, + -315273, + 412578, + -521626, + 638721, + -758385, + 873216, + -973827, + 1048887, + -1085284, + 1068419, + -982642, + 811838, + -540143, + 152798, + 362895, + -1016538, + 1813561, + -2754133, + 3832134, + -5034204, + 6338950, + -7716331, + 9127289, + -10523638, + 11848257, + -13035587, + 14012430, + -14699034, + 15010420, + -14857884, + 14150599, + -12797186, + 10707116, + -7791738, + 3964696, + 858627, + -6763122, + 13838152, + -22185132, + 31930455, + -43247332, + 56393333, + -71777398, + 90086566, + -112545159, + 141503316, + -181978617, + 246629497, + -378369684, + 869465373, + 1766415993, + -366801653, + 174504829, + -95804612, + 52206599, + -24382530, + 5268327, + 8338721, + -18115073, + 25040323, + -29742869, + 32660991, + -34124099, + 34396023, + -33698850, + 32226210, + -30150587, + 27627182, + -24795751, + 21781319, + -18694309, + 15630437, + -12670602, + 9880923, + -7312991, + 5004391, + -2979502, + 1250542, + 181152, + -1323674, + 2192982, + -2811257, + 3205273, + -3404809, + 3441168, + -3345833, + 3149314, + -2880176, + 2564294, + -2224319, + 1879347, + -1544790, + 1232415, + -950528, + 704284, + -496073, + 325966, + -192191, + 91604, + -20138, + -26783, + 53894, + -65795, + 66725, + -60402, + 49935, + -37779, + 25747, + 2755, + 1219, + -10576, + 27407, + -53951, + 92443, + -144927, + 213021, + -297660, + 398810, + -515182, + 643945, + -780483, + 918185, + -1048327, + 1160033, + -1240361, + 1274517, + -1246213, + 1138178, + -932824, + 613049, + -163175, + -430011, + 1176145, + -2080138, + 3141035, + -4350945, + 5694065, + -7145881, + 8672566, + -10230634, + 11766874, + -13218583, + 14514116, + -15573718, + 16310629, + -16632395, + 16442297, + -15640795, + 14126834, + -11798801, + 8554867, + -4292352, + -1094457, + 7718819, + -15709728, + 25225994, + -36480222, + 49780340, + -65604264, + 84742022, + -108588292, + 139811275, + -184120048, + 256038642, + -405757420, + 996567225, + 1678543306, + -401021446, + 202171825, + -118670431, + 71629603, + -41107997, + 19733438, + -4147349, + -7408354, + 15956582, + -22148321, + 26432953, + -29144707, + 30549036, + -30868354, + 30296526, + -29006928, + 27156747, + -24889056, + 22333596, + -19606858, + 16811843, + -14037758, + 11359807, + -8839186, + 6523333, + -4446455, + 2630331, + -1085363, + -188167, + 1198670, + -1961737, + 2498563, + -2834397, + 2997043, + -3015484, + 2918641, + -2734320, + 2488348, + -2203915, + 1901123, + -1596728, + 1304059, + -1033101, + 790703, + -580889, + 405242, + -263334, + 153167, + -71611, + 14812, + 21440, + -41404, + 49138, + -48311, + 42077, + -33015, + 23104, + 6276, + -4518, + -2092, + 15736, + -38826, + 73881, + -123342, + 189353, + -273500, + 376517, + -497980, + 635995, + -786904, + 945033, + -1102500, + 1249104, + -1372335, + 1457494, + -1487972, + 1445679, + -1311633, + 1066709, + -692534, + 172515, + 507037, + -1355717, + 2377804, + -3571077, + 4925695, + -6423207, + 8035746, + -9725444, + 11444107, + -13133188, + 14724060, + -16138595, + 17290015, + -18083982, + 18419837, + -18191883, + 17290564, + -15603336, + 13014935, + -9406660, + 4654082, + 1377712, + -8842762, + 17929200, + -28884937, + 42062439, + -57999763, + 77575726, + -102331257, + 135209156, + -182525845, + 260496693, + -426294377, + 1122144839, + 1581244342, + -425036766, + 224701631, + -138502193, + 89174467, + -56691266, + 33565313, + -16368834, + 3306830, + 6661313, + -14193141, + 19738294, + -23627935, + 26123015, + -27441264, + 27772495, + -27287199, + 26141172, + -24477751, + 22428643, + -20113940, + 17641752, + -15107696, + 12594463, + -10171536, + 7895165, + -5808621, + 3942727, + -2316668, + 939034, + 190939, + -1081991, + 1749363, + -2213308, + 2497612, + -2628199, + 2631845, + -2535051, + 2363083, + -2139208, + 1884125, + -1615589, + 1348214, + -1093448, + 859682, + -652475, + 474875, + -327789, + 210393, + -120540, + 55170, + -10668, + -16806, + 31050, + -35612, + 33636, + -27767, + 20112, + 9851, + -10410, + 6751, + 3351, + -22442, + 53277, + -98654, + 161207, + -243150, + 345982, + -470165, + 614786, + -777236, + 952897, + -1134895, + 1313918, + -1478138, + 1613246, + -1702642, + 1727767, + -1668610, + 1504385, + -1214369, + 778886, + -180430, + -595124, + 1557252, + -2709498, + 4048228, + -5561481, + 7227963, + -9016232, + 10884130, + -12778486, + 14635115, + -16379118, + 17925478, + -19179899, + 20039825, + -20395546, + 20131229, + -19125679, + 17252533, + -14379483, + 10365909, + -5057998, + -1720191, + 10182287, + -20606486, + 33382734, + -49098608, + 68704727, + -93859334, + 127726915, + -177125603, + 259727845, + -439168457, + 1244784066, + 1475676049, + -439114292, + 241866815, + -154996505, + 104534603, + -70842132, + 46496681, + -28083767, + 13814526, + -2655452, + -6042023, + 12717305, + -17690874, + 21213291, + -23492768, + 24710924, + -25031696, + 24606168, + -23574917, + 22068842, + -20209119, + 18106697, + -15861600, + 13562257, + -11284961, + 9093571, + -7039475, + 5161847, + -3488201, + 2035192, + -809659, + -190169, + 973328, + -1554713, + 1953653, + -2192525, + 2295449, + -2287104, + 2191703, + -2032126, + 1829256, + -1601485, + 1364412, + -1130705, + 910114, + -709610, + 533628, + -384378, + 262207, + -165988, + 93498, + -41784, + 7494, + 12844, + -22586, + 24804, + -22163, + 16851, + 13403, + -16334, + 15779, + -9508, + -5107, + 31008, + -71300, + 129063, + -207105, + 307668, + -432102, + 580510, + -751390, + 941288, + -1144487, + 1352757, + -1555195, + 1738174, + -1885429, + 1978300, + -1996138, + 1916894, + -1717884, + 1376718, + -872389, + 186480, + 695534, + -1782941, + 3078443, + -4576864, + 6263963, + -8115419, + 10096009, + -12159062, + 14246174, + -16287232, + 18200733, + -19894358, + 21265759, + -22203458, + 22587715, + -22291165, + 21178940, + -19107851, + 15924003, + -11457882, + 5515334, + 2138270, + -11805560, + 23905781, + -39063807, + 58282550, + -83304201, + 117453153, + -167922766, + 253547104, + -443651737, + 1363083889, + 1363083889, + -443651737, + 253547104, + -167922766, + 117453153, + -83304201, + 58282550, + -39063807, + 23905781, + -11805560, + 2138270, + 5515334, + -11457882, + 15924003, + -19107851, + 21178940, + -22291165, + 22587715, + -22203458, + 21265759, + -19894358, + 18200733, + -16287232, + 14246174, + -12159062, + 10096009, + -8115419, + 6263963, + -4576864, + 3078443, + -1782941, + 695534, + 186480, + -872389, + 1376718, + -1717884, + 1916894, + -1996138, + 1978300, + -1885429, + 1738174, + -1555195, + 1352757, + -1144487, + 941288, + -751390, + 580510, + -432102, + 307668, + -207105, + 129063, + -71300, + 31008, + -5107, + -9508, + 15779, + -16334, + 13403, + 16851, + -22163, + 24804, + -22586, + 12844, + 7494, + -41784, + 93498, + -165988, + 262207, + -384378, + 533628, + -709610, + 910114, + -1130705, + 1364412, + -1601485, + 1829256, + -2032126, + 2191703, + -2287104, + 2295449, + -2192525, + 1953653, + -1554713, + 973328, + -190169, + -809659, + 2035192, + -3488201, + 5161847, + -7039475, + 9093571, + -11284961, + 13562257, + -15861600, + 18106697, + -20209119, + 22068842, + -23574917, + 24606168, + -25031696, + 24710924, + -23492768, + 21213291, + -17690874, + 12717305, + -6042023, + -2655452, + 13814526, + -28083767, + 46496681, + -70842132, + 104534603, + -154996505, + 241866815, + -439114292, + 1475676049, + 1244784066, + -439168457, + 259727845, + -177125603, + 127726915, + -93859334, + 68704727, + -49098608, + 33382734, + -20606486, + 10182287, + -1720191, + -5057998, + 10365909, + -14379483, + 17252533, + -19125679, + 20131229, + -20395546, + 20039825, + -19179899, + 17925478, + -16379118, + 14635115, + -12778486, + 10884130, + -9016232, + 7227963, + -5561481, + 4048228, + -2709498, + 1557252, + -595124, + -180430, + 778886, + -1214369, + 1504385, + -1668610, + 1727767, + -1702642, + 1613246, + -1478138, + 1313918, + -1134895, + 952897, + -777236, + 614786, + -470165, + 345982, + -243150, + 161207, + -98654, + 53277, + -22442, + 3351, + 6751, + -10410, + 9851, + 20112, + -27767, + 33636, + -35612, + 31050, + -16806, + -10668, + 55170, + -120540, + 210393, + -327789, + 474875, + -652475, + 859682, + -1093448, + 1348214, + -1615589, + 1884125, + -2139208, + 2363083, + -2535051, + 2631845, + -2628199, + 2497612, + -2213308, + 1749363, + -1081991, + 190939, + 939034, + -2316668, + 3942727, + -5808621, + 7895165, + -10171536, + 12594463, + -15107696, + 17641752, + -20113940, + 22428643, + -24477751, + 26141172, + -27287199, + 27772495, + -27441264, + 26123015, + -23627935, + 19738294, + -14193141, + 6661313, + 3306830, + -16368834, + 33565313, + -56691266, + 89174467, + -138502193, + 224701631, + -425036766, + 1581244342, + 1122144839, + -426294377, + 260496693, + -182525845, + 135209156, + -102331257, + 77575726, + -57999763, + 42062439, + -28884937, + 17929200, + -8842762, + 1377712, + 4654082, + -9406660, + 13014935, + -15603336, + 17290564, + -18191883, + 18419837, + -18083982, + 17290015, + -16138595, + 14724060, + -13133188, + 11444107, + -9725444, + 8035746, + -6423207, + 4925695, + -3571077, + 2377804, + -1355717, + 507037, + 172515, + -692534, + 1066709, + -1311633, + 1445679, + -1487972, + 1457494, + -1372335, + 1249104, + -1102500, + 945033, + -786904, + 635995, + -497980, + 376517, + -273500, + 189353, + -123342, + 73881, + -38826, + 15736, + -2092, + -4518, + 6276, + 23104, + -33015, + 42077, + -48311, + 49138, + -41404, + 21440, + 14812, + -71611, + 153167, + -263334, + 405242, + -580889, + 790703, + -1033101, + 1304059, + -1596728, + 1901123, + -2203915, + 2488348, + -2734320, + 2918641, + -3015484, + 2997043, + -2834397, + 2498563, + -1961737, + 1198670, + -188167, + -1085363, + 2630331, + -4446455, + 6523333, + -8839186, + 11359807, + -14037758, + 16811843, + -19606858, + 22333596, + -24889056, + 27156747, + -29006928, + 30296526, + -30868354, + 30549036, + -29144707, + 26432953, + -22148321, + 15956582, + -7408354, + -4147349, + 19733438, + -41107997, + 71629603, + -118670431, + 202171825, + -401021446, + 1678543306, + 996567225, + -405757420, + 256038642, + -184120048, + 139811275, + -108588292, + 84742022, + -65604264, + 49780340, + -36480222, + 25225994, + -15709728, + 7718819, + -1094457, + -4292352, + 8554867, + -11798801, + 14126834, + -15640795, + 16442297, + -16632395, + 16310629, + -15573718, + 14514116, + -13218583, + 11766874, + -10230634, + 8672566, + -7145881, + 5694065, + -4350945, + 3141035, + -2080138, + 1176145, + -430011, + -163175, + 613049, + -932824, + 1138178, + -1246213, + 1274517, + -1240361, + 1160033, + -1048327, + 918185, + -780483, + 643945, + -515182, + 398810, + -297660, + 213021, + -144927, + 92443, + -53951, + 27407, + -10576, + 1219, + 2755, + 25747, + -37779, + 49935, + -60402, + 66725, + -65795, + 53894, + -26783, + -20138, + 91604, + -192191, + 325966, + -496073, + 704284, + -950528, + 1232415, + -1544790, + 1879347, + -2224319, + 2564294, + -2880176, + 3149314, + -3345833, + 3441168, + -3404809, + 3205273, + -2811257, + 2192982, + -1323674, + 181152, + 1250542, + -2979502, + 5004391, + -7312991, + 9880923, + -12670602, + 15630437, + -18694309, + 21781319, + -24795751, + 27627182, + -30150587, + 32226210, + -33698850, + 34396023, + -34124099, + 32660991, + -29742869, + 25040323, + -18115073, + 8338721, + 5268327, + -24382530, + 52206599, + -95804612, + 174504829, + -366801653, + 1766415993, + 869465373, + -378369684, + 246629497, + -181978617, + 141503316, + -112545159, + 90086566, + -71777398, + 56393333, + -43247332, + 31930455, + -22185132, + 13838152, + -6763122, + 858627, + 3964696, + -7791738, + 10707116, + -12797186, + 14150599, + -14857884, + 15010420, + -14699034, + 14012430, + -13035587, + 11848257, + -10523638, + 9127289, + -7716331, + 6338950, + -5034204, + 3832134, + -2754133, + 1813561, + -1016538, + 362895, + 152798, + -540143, + 811838, + -982642, + 1068419, + -1085284, + 1048887, + -973827, + 873216, + -758385, + 638721, + -521626, + 412578, + -315273, + 231833, + -163047, + 108640, + -67544, + 38148, + -18537, + 6690, + -639, + 27964, + -41935, + 57021, + -71612, + 83425, + -89464, + 86029, + -68780, + 32864, + 26889, + -115701, + 238504, + -399542, + 601910, + -847068, + 1134325, + -1460345, + 1818679, + -2199376, + 2588689, + -2968918, + 3318412, + -3611764, + 3820211, + -3912258, + 3854525, + -3612813, + 3153370, + -2444337, + 1457330, + -169111, + -1436700, + 3367930, + -5622242, + 8185664, + -11031305, + 14118309, + -17391076, + 20778749, + -24194941, + 27537656, + -30689259, + 33516319, + -35868995, + 37579489, + -38458744, + 38290092, + -36817537, + 33724473, + -28594674, + 20838484, + -9545499, + -6833689, + 31256786, + -70277042, + 142034944, + -322249261, + 1843810551, + 742246935, + -345012594, + 232627953, + -176242591, + 140313332, + -114163842, + 93530553, + -76415051, + 61782362, + -49059662, + 37913910, + -28142379, + 19614336, + -12238107, + 5941746, + -661474, + -3665148, + 7103028, + -9721363, + 11594089, + -12799421, + 13418758, + -13535224, + 13231988, + -12590540, + 11689015, + -10600672, + 9392587, + -8124608, + 6848617, + -5608079, + 4437914, + -3364635, + 2406750, + -1575384, + 875063, + -304639, + -141724, + 473523, + -702905, + 843709, + -910592, + 918263, + -880839, + 811344, + -721336, + 620671, + -517391, + 417715, + -326124, + 245517, + -177417, + 122204, + -79372, + 47768, + -25831, + 11790, + -3840, + 29686, + -45369, + 63156, + -81676, + 98864, + -111896, + 117165, + -110316, + 86332, + -39703, + -35340, + 144511, + -293079, + 485420, + -724511, + 1011395, + -1344637, + 1719798, + -2128959, + 2560329, + -2997972, + 3421677, + -3807019, + 4125614, + -4345602, + 4432360, + -4349452, + 4059800, + -3527059, + 2717161, + -1599997, + 151166, + 1646237, + -3799886, + 6306577, + -9150747, + 12303198, + -15720070, + 19342089, + -23094069, + 26884640, + -30606100, + 34134242, + -37327875, + 40027622, + -42053295, + 43198697, + -43221824, + 41826782, + -38630199, + 33097079, + -24411735, + 11196943, + 9170263, + -42523640, + 105201176, + -267380191, + 1909795360, + 616293714, + -306621301, + 214466446, + -167119172, + 136325644, + -113453514, + 95034398, + -79445355, + 65854499, + -53811343, + 43063672, + -33466687, + 24934177, + -17410664, + 10854869, + -5229713, + 496338, + 3389247, + -6477763, + 8827010, + -10501360, + 11570640, + -12108623, + 12191296, + -11895029, + 11294773, + -10462368, + 9465042, + -8364151, + 7214198, + -6062152, + 4947070, + -3900012, + 2944224, + -2095566, + 1363133, + -750036, + 254288, + 130249, + -412894, + 605210, + -720121, + 771112, + -771550, + 734111, + -670351, + 590399, + -502770, + 414293, + -330138, + 253915, + -187838, + 132929, + -89244, + 56106, + -32330, + 16429, + -6790, + 30850, + -47978, + 68177, + -90346, + 112683, + -132591, + 146632, + -150516, + 139165, + -106831, + 47304, + 45806, + -178705, + 356975, + -585070, + 865765, + -1199576, + 1584182, + -2013876, + 2479078, + -2965951, + 3456146, + -3926716, + 4350226, + -4695088, + 4926119, + -5005361, + 4893124, + -4549271, + 3934693, + -3012958, + 1752076, + -126330, + -1881885, + 4280285, + -7065041, + 10219297, + -13711932, + 17496568, + -21510868, + 25676083, + -29896802, + 34060773, + -38038587, + 41682882, + -44826494, + 47278595, + -48817145, + 49174591, + -48010816, + 44860776, + -39028077, + 29351448, + -13630958, + -13037306, + 64543212, + -202357771, + 1963572480, + 492942897, + -264168575, + 192640957, + -154876120, + 129678044, + -110469523, + 94597921, + -80829687, + 68544477, + -57419120, + 47285122, + -38057274, + 29694863, + -22179240, + 15500298, + -9648169, + 4608190, + -358039, + -3133613, + 5907354, + -8012488, + 9505920, + -10450638, + 10913951, + -10965601, + 10675860, + -10113712, + 9345182, + -8431887, + 7429841, + -6388544, + 5350378, + -4350289, + 3415757, + -2567021, + 1817520, + -1174527, + 639904, + -210965, + -118627, + 357954, + -517965, + 610675, + -648437, + 643340, + -606711, + 548745, + -478261, + 402558, + -327382, + 256976, + -194194, + 140671, + -97016, + 63033, + -37931, + 20529, + -9437, + 31404, + -49672, + 71937, + -97395, + 124543, + -151071, + 173773, + -188517, + 190256, + -173118, + 130568, + -55659, + -58640, + 219020, + -431342, + 700076, + -1027700, + 1414082, + -1855861, + 2345884, + -2872709, + 3420232, + -3967459, + 4488465, + -4952565, + 5324722, + -5566201, + 5635480, + -5489404, + 5084568, + -4378905, + 3333417, + -1914031, + 93487, + 2146779, + -4814839, + 7906625, + -11404488, + 15276007, + -19473088, + 23931356, + -28569804, + 33290634, + -37979129, + 42503317, + -46712978, + 50437281, + -53479786, + 55608461, + -56536179, + 55882131, + -53092221, + 47262437, + -36700597, + 17639975, + 20695531, + -127493870, + 2004489199, + 373469158, + -218648487, + 167699979, + -139835135, + 120558016, + -105311509, + 92259752, + -80562981, + 69815645, + -59823762, + 50503416, + -41829240, + 33805934, + -26451462, + 19786698, + -13828901, + 8587684, + -4062682, + 242457, + 2895656, + -5384991, + 7268459, + -8597058, + 9428115, + -9823375, + 9847051, + -9563898, + 9037421, + -8328257, + 7492794, + -6582052, + 5640864, + -4707331, + 3812582, + -2980794, + 2229445, + -1569784, + 1007454, + -543236, + 173874, + 107077, + -308399, + 440409, + -514222, + 541103, + -531929, + 496766, + -444555, + 382918, + -318059, + 254763, + -196459, + 145352, + -102590, + 68451, + -42549, + 24029, + -11742, + 31305, + -50377, + 74313, + -102624, + 134143, + -166892, + 197969, + -223478, + 238507, + -237173, + 212744, + -157841, + 64741, + 74238, + -266261, + 517425, + -832143, + 1212494, + -1657559, + 2162776, + -2719352, + 3313772, + -3927433, + 4536453, + -5111675, + 5618911, + -6019423, + 6270673, + -6327334, + 6142546, + -5669407, + 4862648, + -3680460, + 2086407, + -51372, + -2444549, + 5410256, + -8842038, + 12722210, + -17018034, + 21680967, + -26646238, + 31832716, + -37143002, + 42463583, + -47664776, + 52600006, + -57103595, + 60985576, + -64020636, + 65925094, + -66307962, + 64560231, + -59576376, + 48926156, + -25620247, + -43247758, + 2032047499, + 259067894, + -171060123, + 140232853, + -122364378, + 109198070, + -98120662, + 88095967, + -78673366, + 69660348, + -60990963, + 52664774, + -44715114, + 37190975, + -30145909, + 23630886, + -17689620, + 12355561, + -7650116, + 3581818, + -146257, + -2673368, + 4905199, + -6587291, + 7765895, + -8493576, + 8827227, + -8826106, + 8549937, + -8057168, + 7403427, + -6640222, + 5813917, + -4964984, + 4127549, + -3329209, + 2591098, + -1928181, + 1349734, + -859959, + 458712, + -142288, + -95778, + 263920, + -371806, + 429666, + -447721, + 435707, + -402515, + 355935, + -302503, + 247442, + -194686, + 146960, + -105916, + 72299, + -46127, + 26879, + -13673, + 30525, + -50041, + 75207, + -105867, + 141217, + -179655, + 218644, + -254605, + 282859, + -297628, + 292111, + -258643, + 188951, + -74504, + -93042, + 321306, + -616569, + 983105, + -1422478, + 1932836, + -2508237, + 3138049, + -3806457, + 4492117, + -5168002, + 5801463, + -6354540, + 6784527, + -7044817, + 7086014, + -6857287, + 6307962, + -5389281, + 4056300, + -2269858, + -1464, + 2779452, + -6074518, + 9884190, + -14191887, + 18966043, + -24159623, + 29710042, + -35539493, + 41555624, + -47652476, + 53711503, + -59602351, + 65182859, + -70297191, + 74769949, + -78391268, + 80880225, + -81788802, + 80209153, + -73604718, + 49777322, + 2045911288, + 150839845, + -122391611, + 110857698, + -102870277, + 95870291, + -89076218, + 82218013, + -75221153, + 68099712, + -60911749, + 53737323, + -46666020, + 39789021, + -33193646, + 26959432, + -21155300, + 15837594, + -11048851, + 6817230, + -3156526, + 66691, + 2465182, + -4463526, + 5962663, + -7004975, + 7638949, + -7917187, + 7894463, + -7625879, + 7165194, + -6563369, + 5867360, + -5119183, + 4355252, + -3606007, + 2895784, + -2242936, + 1660149, + -1154931, + 730225, + -385110, + 115544, + 84880, + -224208, + 311445, + -355960, + 366976, + -353158, + 322309, + -281165, + 235283, + -189014, + 145545, + -106994, + 74549, + -48628, + 29050, + -15208 + +}; + +static const struct src_stage src_int32_21_16_4535_5000 = { + 3, 4, 21, 116, 2436, 16, 21, 0, 0, + src_int32_21_16_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_20_1250_5000.h b/src/audio/src/coef/src_ipc4_int32_21_20_1250_5000.h new file mode 100644 index 000000000000..4ce048243ecc --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_20_1250_5000.h @@ -0,0 +1,438 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_20_1250_5000_fir[420] = { + 94664, + -1133291, + 202774, + 10371754, + -18748586, + -16954822, + 91498254, + -69100815, + -200269725, + 635113012, + 1341698665, + 580418185, + -213162896, + -53592000, + 88996292, + -20636276, + -16488280, + 10342472, + -192427, + -1012764, + 98889, + -1253750, + 638741, + 10286393, + -20973416, + -12871941, + 93241545, + -84811772, + -184611687, + 689636983, + 1337559401, + 525833150, + -223350997, + -38414886, + 85799491, + -23903400, + -14217910, + 10207613, + -545859, + -893973, + 99722, + -1372125, + 1113821, + 10078007, + -23136062, + -8405529, + 94166458, + -100586588, + -166146226, + 743705417, + 1329305518, + 471632636, + -230910124, + -23689602, + 81974995, + -26748152, + -11961398, + 9976777, + -857126, + -778506, + 96491, + -1486201, + 1625677, + 9739045, + -25208739, + -3578563, + 94218209, + -116279069, + -144848856, + 797031547, + 1316986116, + 418083630, + -235931624, + -9526246, + 77592462, + -29167165, + -9741003, + 9659943, + -1126401, + -667729, + 88520, + -1593579, + 2171264, + 9262951, + -27162839, + 1580856, + 93347733, + -131736020, + -120713857, + 849328500, + 1300674388, + 365443644, + -238520949, + 3975609, + 72723275, + -31161535, + -7577188, + 9267332, + -1354373, + -562789, + 75140, + -1691694, + 2746809, + 8644305, + -28969200, + 7039521, + 91512457, + -146798248, + -93754842, + 900311302, + 1280467062, + 313959071, + -238796429, + 16727297, + 67439771, + -32736568, + -5488501, + 8809271, + -1542201, + -464614, + 55710, + -1777842, + 3347803, + 7878980, + -30598400, + 12759186, + 88677046, + -161301654, + -64005174, + 949698894, + 1256483677, + 263863658, + -236887971, + 28651334, + 61814494, + -33901494, + -3491494, + 8296060, + -1691451, + -373926, + 29623, + -1849205, + 3968996, + 6964276, + -32021072, + 18696691, + 84814111, + -175078405, + -31518243, + 997216126, + 1228865689, + 215377091, + -232935703, + 39681587, + 55919493, + -34669157, + -1600663, + 7737856, + -1804053, + -291243, + -3667, + -1902886, + 4604409, + 5899057, + -33208241, + 24804151, + 79904876, + -187958180, + 3632423, + 1042595742, + 1197775406, + 168703718, + -227088572, + 49763329, + 49825640, + -35055689, + 171577, + 7144562, + -1882235, + -216895, + -44637, + -1935946, + 5247354, + 4683875, + -34131665, + 31029193, + 73939788, + -199769475, + 41353194, + 1085580303, + 1163394784, + 124031405, + -219502906, + 58853202, + 43602004, + -35080155, + 1814906, + 6525728, + -1928475, + -151039, + -93669, + -1945442, + 5890462, + 3321077, + -34764197, + 37315266, + 66919070, + -210340965, + 81530541, + 1125924067, + 1125924067, + 81530541, + -210340965, + 66919070, + 37315266, + -34764197, + 3321077, + 5890462, + -1945442, + -93669, + -151039, + -1928475, + 6525728, + 1814906, + -35080155, + 43602004, + 58853202, + -219502906, + 124031405, + 1163394784, + 1085580303, + 41353194, + -199769475, + 73939788, + 31029193, + -34131665, + 4683875, + 5247354, + -1935946, + -44637, + -216895, + -1882235, + 7144562, + 171577, + -35055689, + 49825640, + 49763329, + -227088572, + 168703718, + 1197775406, + 1042595742, + 3632423, + -187958180, + 79904876, + 24804151, + -33208241, + 5899057, + 4604409, + -1902886, + -3667, + -291243, + -1804053, + 7737856, + -1600663, + -34669157, + 55919493, + 39681587, + -232935703, + 215377091, + 1228865689, + 997216126, + -31518243, + -175078405, + 84814111, + 18696691, + -32021072, + 6964276, + 3968996, + -1849205, + 29623, + -373926, + -1691451, + 8296060, + -3491494, + -33901494, + 61814494, + 28651334, + -236887971, + 263863658, + 1256483677, + 949698894, + -64005174, + -161301654, + 88677046, + 12759186, + -30598400, + 7878980, + 3347803, + -1777842, + 55710, + -464614, + -1542201, + 8809271, + -5488501, + -32736568, + 67439771, + 16727297, + -238796429, + 313959071, + 1280467062, + 900311302, + -93754842, + -146798248, + 91512457, + 7039521, + -28969200, + 8644305, + 2746809, + -1691694, + 75140, + -562789, + -1354373, + 9267332, + -7577188, + -31161535, + 72723275, + 3975609, + -238520949, + 365443644, + 1300674388, + 849328500, + -120713857, + -131736020, + 93347733, + 1580856, + -27162839, + 9262951, + 2171264, + -1593579, + 88520, + -667729, + -1126401, + 9659943, + -9741003, + -29167165, + 77592462, + -9526246, + -235931624, + 418083630, + 1316986116, + 797031547, + -144848856, + -116279069, + 94218209, + -3578563, + -25208739, + 9739045, + 1625677, + -1486201, + 96491, + -778506, + -857126, + 9976777, + -11961398, + -26748152, + 81974995, + -23689602, + -230910124, + 471632636, + 1329305518, + 743705417, + -166146226, + -100586588, + 94166458, + -8405529, + -23136062, + 10078007, + 1113821, + -1372125, + 99722, + -893973, + -545859, + 10207613, + -14217910, + -23903400, + 85799491, + -38414886, + -223350997, + 525833150, + 1337559401, + 689636983, + -184611687, + -84811772, + 93241545, + -12871941, + -20973416, + 10286393, + 638741, + -1253750, + 98889, + -1012764, + -192427, + 10342472, + -16488280, + -20636276, + 88996292, + -53592000, + -213162896, + 580418185, + 1341698665, + 635113012, + -200269725, + -69100815, + 91498254, + -16954822, + -18748586, + 10371754, + 202774, + -1133291, + 94664 + +}; + +static const struct src_stage src_int32_21_20_1250_5000 = { + 19, 20, 21, 20, 420, 20, 21, 0, 0, + src_int32_21_20_1250_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_20_2500_5000.h b/src/audio/src/coef/src_ipc4_int32_21_20_2500_5000.h new file mode 100644 index 000000000000..acdf97328a05 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_20_2500_5000.h @@ -0,0 +1,522 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_20_2500_5000_fir[504] = { + 8116, + 587965, + -2725209, + 4857984, + -749985, + -16537335, + 42808738, + -52609661, + 6342446, + 121388861, + -312072739, + 509426813, + 1609712937, + 433009251, + -303217544, + 132684198, + -6202714, + -45948904, + 41761678, + -18001165, + 726604, + 4181634, + -2601173, + 617025, + 27463, + 543777, + -2817692, + 5514641, + -2312097, + -14761237, + 43325430, + -58874229, + 19374534, + 107933496, + -317293140, + 587145127, + 1602777847, + 358396576, + -291034401, + 141777489, + -18121935, + -38995948, + 40223368, + -19149632, + 2102521, + 3496637, + -2450160, + 632090, + 51048, + 483510, + -2874187, + 6140070, + -3942365, + -12680625, + 43278129, + -64639272, + 32741912, + 92389477, + -318595605, + 665638117, + 1588963352, + 286066651, + -275850005, + 148655364, + -29290077, + -31854050, + 38237642, + -19984111, + 3364921, + 2813413, + -2276805, + 634437, + 78888, + 406431, + -2890498, + 6722402, + -5621336, + -10308053, + 42639447, + -69803559, + 46281772, + 74857927, + -315724403, + 744362363, + 1568380274, + 216467075, + -258006926, + 153332075, + -39596886, + -24624406, + 35852242, + -20510198, + 4503323, + 2141648, + -2085725, + 625452, + 110885, + 312058, + -2862749, + 7249596, + -7327644, + -7660934, + 41388909, + -74269435, + 59821798, + 55469761, + -308454706, + 822761945, + 1541193477, + 150011537, + -237859579, + 155848192, + -48947788, + -17404908, + 33117986, + -20737419, + 5509621, + 1490188, + -1881439, + 606592, + 146822, + 200201, + -2787484, + 7709623, + -9038218, + -4761552, + 39513574, + -77944316, + 73182024, + 34385383, + -296595850, + 900273463, + 1507620244, + 87076582, + -215770168, + 156269033, + -57264447, + -10288996, + 30087945, + -20678894, + 6378064, + 866962, + -1668307, + 579351, + 186350, + 70985, + -2661758, + 8090655, + -10728529, + -1636986, + 37008573, + -80742169, + 86176857, + 11794025, + -279994291, + 976331195, + 1467928133, + 27998794, + -192104663, + 154682859, + -64485098, + -3364615, + 26816612, + -20350969, + 7105202, + 278926, + -1450467, + 545231, + 228987, + -75119, + -2483226, + 8381268, + -12372875, + 1681029, + 33877553, + -82584974, + 98617260, + -12087281, + -258536251, + 1050372331, + 1422432351, + -26927573, + -167228847, + 151198869, + -70564649, + 3286706, + 23359097, + -19772820, + 7689804, + -267982, + -1231784, + 505711, + 274111, + -237271, + -2250230, + 8570648, + -13944702, + 5156327, + 30133032, + -83404132, + 110313068, + -37015084, + -232149991, + 1121842236, + 1371492665, + -77452483, + -141504477, + 145945013, + -75474578, + 9590660, + 19770351, + -18966037, + 8132740, + -768862, + -1015809, + 462216, + 320960, + -414243, + -1961882, + 8648805, + -15416948, + 8748598, + 25796632, + -83141809, + 121075405, + -62721255, + -200807687, + 1190199671, + 1315509880, + -123371537, + -115285601, + 139065665, + -79202606, + 15480824, + 16104422, + -17954196, + 8436849, + -1219856, + -805743, + 416104, + 368634, + -604410, + -1618137, + 8606778, + -16762420, + 12413765, + 20899204, + -81752187, + 130719185, + -88915065, + -164526891, + 1254921940, + 1254921940, + -164526891, + -88915065, + 130719185, + -81752187, + 20899204, + 12413765, + -16762420, + 8606778, + -1618137, + -604410, + 368634, + 416104, + -805743, + -1219856, + 8436849, + -17954196, + 16104422, + 15480824, + -79202606, + 139065665, + -115285601, + -123371537, + 1315509880, + 1190199671, + -200807687, + -62721255, + 121075405, + -83141809, + 25796632, + 8748598, + -15416948, + 8648805, + -1961882, + -414243, + 320960, + 462216, + -1015809, + -768862, + 8132740, + -18966037, + 19770351, + 9590660, + -75474578, + 145945013, + -141504477, + -77452483, + 1371492665, + 1121842236, + -232149991, + -37015084, + 110313068, + -83404132, + 30133032, + 5156327, + -13944702, + 8570648, + -2250230, + -237271, + 274111, + 505711, + -1231784, + -267982, + 7689804, + -19772820, + 23359097, + 3286706, + -70564649, + 151198869, + -167228847, + -26927573, + 1422432351, + 1050372331, + -258536251, + -12087281, + 98617260, + -82584974, + 33877553, + 1681029, + -12372875, + 8381268, + -2483226, + -75119, + 228987, + 545231, + -1450467, + 278926, + 7105202, + -20350969, + 26816612, + -3364615, + -64485098, + 154682859, + -192104663, + 27998794, + 1467928133, + 976331195, + -279994291, + 11794025, + 86176857, + -80742169, + 37008573, + -1636986, + -10728529, + 8090655, + -2661758, + 70985, + 186350, + 579351, + -1668307, + 866962, + 6378064, + -20678894, + 30087945, + -10288996, + -57264447, + 156269033, + -215770168, + 87076582, + 1507620244, + 900273463, + -296595850, + 34385383, + 73182024, + -77944316, + 39513574, + -4761552, + -9038218, + 7709623, + -2787484, + 200201, + 146822, + 606592, + -1881439, + 1490188, + 5509621, + -20737419, + 33117986, + -17404908, + -48947788, + 155848192, + -237859579, + 150011537, + 1541193477, + 822761945, + -308454706, + 55469761, + 59821798, + -74269435, + 41388909, + -7660934, + -7327644, + 7249596, + -2862749, + 312058, + 110885, + 625452, + -2085725, + 2141648, + 4503323, + -20510198, + 35852242, + -24624406, + -39596886, + 153332075, + -258006926, + 216467075, + 1568380274, + 744362363, + -315724403, + 74857927, + 46281772, + -69803559, + 42639447, + -10308053, + -5621336, + 6722402, + -2890498, + 406431, + 78888, + 634437, + -2276805, + 2813413, + 3364921, + -19984111, + 38237642, + -31854050, + -29290077, + 148655364, + -275850005, + 286066651, + 1588963352, + 665638117, + -318595605, + 92389477, + 32741912, + -64639272, + 43278129, + -12680625, + -3942365, + 6140070, + -2874187, + 483510, + 51048, + 632090, + -2450160, + 3496637, + 2102521, + -19149632, + 40223368, + -38995948, + -18121935, + 141777489, + -291034401, + 358396576, + 1602777847, + 587145127, + -317293140, + 107933496, + 19374534, + -58874229, + 43325430, + -14761237, + -2312097, + 5514641, + -2817692, + 543777, + 27463, + 617025, + -2601173, + 4181634, + 726604, + -18001165, + 41761678, + -45948904, + -6202714, + 132684198, + -303217544, + 433009251, + 1609712937, + 509426813, + -312072739, + 121388861, + 6342446, + -52609661, + 42808738, + -16537335, + -749985, + 4857984, + -2725209, + 587965, + 8116 + +}; + +static const struct src_stage src_int32_21_20_2500_5000 = { + 19, 20, 21, 24, 504, 20, 21, 0, 0, + src_int32_21_20_2500_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_20_3125_5000.h b/src/audio/src/coef/src_ipc4_int32_21_20_3125_5000.h new file mode 100644 index 000000000000..c37db1770a28 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_20_3125_5000.h @@ -0,0 +1,690 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_20_3125_5000_fir[672] = { + 4928, + 190845, + -929522, + 2251050, + -3286859, + 1975074, + 4195213, + -16160942, + 30726749, + -39159051, + 28680120, + 12662775, + -89439013, + 194107884, + -308226701, + 417611666, + 1743710362, + 331239336, + -285347536, + 194876029, + -99243415, + 23421656, + 20969333, + -35458356, + 30145574, + -17171294, + 5512756, + 1023264, + -2826232, + 2123471, + -937533, + 216515, + 16278, + 158323, + -904391, + 2349891, + -3721586, + 2945131, + 2750234, + -14855987, + 30854932, + -42391723, + 36220731, + 1336552, + -77911519, + 190338807, + -327631341, + 506532177, + 1735014751, + 248046980, + -259486043, + 192751261, + -107241730, + 33473419, + 13208643, + -31361312, + 29137012, + -17883637, + 6688412, + 103483, + -2348374, + 1971067, + -929613, + 235521, + 29584, + 118890, + -861177, + 2416328, + -4121682, + 3918653, + 1194992, + -13264664, + 30510659, + -45089406, + 43469360, + -10403814, + -64772687, + 183499902, + -343089382, + 597329768, + 1717702993, + 168621073, + -231148174, + 187877837, + -113379954, + 42693330, + 5515051, + -26943053, + 27732191, + -18299253, + 7710549, + -771660, + -1861755, + 1797912, + -907141, + 248165, + 44751, + 72626, + -799185, + 2447021, + -4478500, + 4880053, + -450788, + -11400099, + 29681146, + -47191048, + 50304499, + -22393573, + -50162376, + 173563831, + -354155150, + 689300556, + 1691933139, + 93497367, + -200847262, + 180432989, + -117632877, + 50973037, + -1999356, + -22280921, + 25967091, + -18423909, + 8570424, + -1590870, + -1374521, + 1608170, + -871650, + 254849, + 61619, + 19767, + -718014, + 2439037, + -4783633, + 5813160, + -2165029, + -9280298, + 28360740, + -48642680, + 56606816, + -34458532, + -34247460, + 160546769, + -360415478, + 781714869, + 1657940079, + 23156128, + -169097721, + 170623319, + -120003493, + 58221639, + -9228914, + -17453224, + 23881810, + -18267590, + 9262185, + -2344287, + -894372, + 1406012, + -824788, + 256056, + 79966, + -39294, + -617588, + 2389930, + -5029066, + 6701459, + -3923562, + -6928056, + 26551279, + -49398502, + 62261065, + -46417374, + -17220314, + 144509842, + -361495564, + 873824604, + 1616032942, + -41981918, + -136408889, + 158680923, + -120522017, + 64366450, + -16075751, + -12538013, + 21519805, + -17844175, + 9782847, + -3023572, + -428468, + 1195548, + -768276, + 252335, + 99502, + -103996, + -498186, + 2297810, + -5207340, + 7528348, + -5700421, + -4370788, + 24262342, + -49421888, + 67158001, + -58084158, + 703131, + 125559999, + -357064499, + 964870888, + 1566591687, + -101558910, + -103279095, + 144859290, + -119244552, + 69353482, + -22450990, + -7611917, + 18927100, + -17171069, + 10132202, + -3621965, + 16664, + 980760, + -703878, + 244285, + 119873, + -173610, + -360454, + 2161417, + -5311705, + 8277411, + -7468193, + -1640270, + 21511381, + -48686275, + 71196261, + -69270979, + 19285730, + 103850305, + -346840390, + 1054091938, + 1510062919, + -155282399, + -70190025, + 129429049, + -116251423, + 73147636, + -28275785, + -2749028, + 16151488, + -16268790, + 10312710, + -4134317, + 435200, + 765444, + -633360, + 232534, + 140662, + -247241, + -205428, + 1980179, + -5336276, + 8932696, + -9198397, + 1227688, + 18323746, + -47175934, + 74284185, + -79790731, + 38271851, + 79579630, + -330595010, + 1140731029, + 1446954979, + -202927107, + -37601434, + 112673620, + -111645220, + 75732602, + -33482161, + 1980128, + 13241738, + -15160529, + 10329336, + -4557093, + 822076, + 553153, + -558460, + 217729, + 161392, + -323827, + -34536, + 1754264, + -5276180, + 9479003, + -10861898, + 4193658, + 14732572, + -44886589, + 76341553, + -89459958, + 57390466, + 52991720, + -308157902, + 1224044487, + 1377832371, + -244335886, + -5946284, + 94884832, + -105548576, + 77110490, + -38013677, + 6509538, + 10246805, + -13871678, + 10189362, + -4888351, + 1173030, + 347156, + -480860, + 200517, + 181535, + -402153, + 150396, + 1484626, + -5127689, + 9902170, + -12429353, + 7215077, + 10778544, + -41825883, + 77301201, + -98101740, + 76358561, + 24373662, + -279419883, + 1303309602, + 1303309602, + -279419883, + 24373662, + 76358561, + -98101740, + 77301201, + -41825883, + 10778544, + 7215077, + -12429353, + 9902170, + -5127689, + 1484626, + 150396, + -402153, + 181535, + 200517, + -480860, + 347156, + 1173030, + -4888351, + 10189362, + -13871678, + 10246805, + 6509538, + -38013677, + 77110490, + -105548576, + 94884832, + -5946284, + -244335886, + 1377832371, + 1224044487, + -308157902, + 52991720, + 57390466, + -89459958, + 76341553, + -44886589, + 14732572, + 4193658, + -10861898, + 9479003, + -5276180, + 1754264, + -34536, + -323827, + 161392, + 217729, + -558460, + 553153, + 822076, + -4557093, + 10329336, + -15160529, + 13241738, + 1980128, + -33482161, + 75732602, + -111645220, + 112673620, + -37601434, + -202927107, + 1446954979, + 1140731029, + -330595010, + 79579630, + 38271851, + -79790731, + 74284185, + -47175934, + 18323746, + 1227688, + -9198397, + 8932696, + -5336276, + 1980179, + -205428, + -247241, + 140662, + 232534, + -633360, + 765444, + 435200, + -4134317, + 10312710, + -16268790, + 16151488, + -2749028, + -28275785, + 73147636, + -116251423, + 129429049, + -70190025, + -155282399, + 1510062919, + 1054091938, + -346840390, + 103850305, + 19285730, + -69270979, + 71196261, + -48686275, + 21511381, + -1640270, + -7468193, + 8277411, + -5311705, + 2161417, + -360454, + -173610, + 119873, + 244285, + -703878, + 980760, + 16664, + -3621965, + 10132202, + -17171069, + 18927100, + -7611917, + -22450990, + 69353482, + -119244552, + 144859290, + -103279095, + -101558910, + 1566591687, + 964870888, + -357064499, + 125559999, + 703131, + -58084158, + 67158001, + -49421888, + 24262342, + -4370788, + -5700421, + 7528348, + -5207340, + 2297810, + -498186, + -103996, + 99502, + 252335, + -768276, + 1195548, + -428468, + -3023572, + 9782847, + -17844175, + 21519805, + -12538013, + -16075751, + 64366450, + -120522017, + 158680923, + -136408889, + -41981918, + 1616032942, + 873824604, + -361495564, + 144509842, + -17220314, + -46417374, + 62261065, + -49398502, + 26551279, + -6928056, + -3923562, + 6701459, + -5029066, + 2389930, + -617588, + -39294, + 79966, + 256056, + -824788, + 1406012, + -894372, + -2344287, + 9262185, + -18267590, + 23881810, + -17453224, + -9228914, + 58221639, + -120003493, + 170623319, + -169097721, + 23156128, + 1657940079, + 781714869, + -360415478, + 160546769, + -34247460, + -34458532, + 56606816, + -48642680, + 28360740, + -9280298, + -2165029, + 5813160, + -4783633, + 2439037, + -718014, + 19767, + 61619, + 254849, + -871650, + 1608170, + -1374521, + -1590870, + 8570424, + -18423909, + 25967091, + -22280921, + -1999356, + 50973037, + -117632877, + 180432989, + -200847262, + 93497367, + 1691933139, + 689300556, + -354155150, + 173563831, + -50162376, + -22393573, + 50304499, + -47191048, + 29681146, + -11400099, + -450788, + 4880053, + -4478500, + 2447021, + -799185, + 72626, + 44751, + 248165, + -907141, + 1797912, + -1861755, + -771660, + 7710549, + -18299253, + 27732191, + -26943053, + 5515051, + 42693330, + -113379954, + 187877837, + -231148174, + 168621073, + 1717702993, + 597329768, + -343089382, + 183499902, + -64772687, + -10403814, + 43469360, + -45089406, + 30510659, + -13264664, + 1194992, + 3918653, + -4121682, + 2416328, + -861177, + 118890, + 29584, + 235521, + -929613, + 1971067, + -2348374, + 103483, + 6688412, + -17883637, + 29137012, + -31361312, + 13208643, + 33473419, + -107241730, + 192751261, + -259486043, + 248046980, + 1735014751, + 506532177, + -327631341, + 190338807, + -77911519, + 1336552, + 36220731, + -42391723, + 30854932, + -14855987, + 2750234, + 2945131, + -3721586, + 2349891, + -904391, + 158323, + 16278, + 216515, + -937533, + 2123471, + -2826232, + 1023264, + 5512756, + -17171294, + 30145574, + -35458356, + 20969333, + 23421656, + -99243415, + 194876029, + -285347536, + 331239336, + 1743710362, + 417611666, + -308226701, + 194107884, + -89439013, + 12662775, + 28680120, + -39159051, + 30726749, + -16160942, + 4195213, + 1975074, + -3286859, + 2251050, + -929522, + 190845, + 4928 + +}; + +static const struct src_stage src_int32_21_20_3125_5000 = { + 19, 20, 21, 32, 672, 20, 21, 0, 0, + src_int32_21_20_3125_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_20_4167_5000.h b/src/audio/src/coef/src_ipc4_int32_21_20_4167_5000.h new file mode 100644 index 000000000000..31c0a15809d3 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_20_4167_5000.h @@ -0,0 +1,1278 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_20_4167_5000_fir[1260] = { + -79259, + 176349, + -298364, + 416250, + -478529, + 411341, + -123820, + -480222, + 1484284, + -2936056, + 4821677, + -7041036, + 9388532, + -11543835, + 13076626, + -13467879, + 12148196, + -8551241, + 2177650, + 7337477, + -20162106, + 36219193, + -55162151, + 76382260, + -99056298, + 122247105, + -145092455, + 167221055, + -190126085, + 226299327, + 1966963362, + 127686471, + -146072317, + 143272983, + -132240061, + 116491759, + -98048896, + 78497683, + -59179213, + 41196332, + -25384081, + 12287102, + -2158509, + -5016776, + 9477259, + -11625137, + 11959647, + -11011686, + 9286795, + -7221651, + 5156786, + -3325805, + 1859186, + -799229, + 121835, + 239228, + -369427, + 354700, + -268420, + 164446, + -81481, + 185366, + -323891, + 472348, + -582606, + 581623, + -375120, + -142311, + 1070282, + -2479666, + 4385818, + -6721362, + 9312932, + -11866620, + 13966495, + -15089444, + 14637596, + -11987142, + 6549588, + 2161191, + -14464993, + 30464974, + -50022852, + 72773536, + -98199446, + 125806790, + -155526255, + 188799554, + -232752654, + 330624501, + 1954617994, + 35611454, + -101422410, + 117467011, + -117268800, + 108696666, + -95233652, + 79108501, + -62019267, + 45317045, + -30041552, + 16921441, + -6378391, + -1451664, + 6678131, + -9599932, + 10640961, + -10284452, + 9013447, + -7262963, + 5387261, + -3643275, + 2188988, + -1093863, + 357375, + 68618, + -257578, + 289120, + -234871, + 150078, + -82045, + 191113, + -344242, + 521618, + -679392, + 746660, + -627340, + 208500, + 624108, + -1963710, + 3855137, + -6265553, + 9057556, + -11969482, + 14607689, + -16454603, + 16894584, + -15257209, + 10874697, + -3147260, + -8392702, + 24029172, + -43838350, + 67711264, + -95455901, + 127052487, + -163278571, + 207522473, + -273105353, + 439744137, + 1930067252, + -49201656, + -56979950, + 90330929, + -100508957, + 99051667, + -90699239, + 78231540, + -63650426, + 48519345, + -34057238, + 21159292, + -10405081, + 2076813, + 3805585, + -7433673, + 9149265, + -9379785, + 8577320, + -7167360, + 5511281, + -3884337, + 2468704, + -1359276, + 578661, + -97301, + -145225, + 220953, + -198559, + 133693, + -80794, + 193255, + -358726, + 562762, + -766678, + 903020, + -875583, + 565780, + 153508, + -1396602, + 3237536, + -5679230, + 8623365, + -11845863, + 14982978, + -17532353, + 18871783, + -18296121, + 15069795, + -8489208, + -2054077, + 17021913, + -36706883, + 61263437, + -90838315, + 125906511, + -168129131, + 222938849, + -310334302, + 552658580, + 1893589230, + -126137813, + -13509895, + 62399094, + -82314702, + 87776327, + -84564325, + 75910923, + -64063870, + 50759447, + -37367179, + 24928273, + -14166626, + 5503259, + 914771, + -5169628, + 7515939, + -8318313, + 7990115, + -6939754, + 5529080, + -4046411, + 2694434, + -1591317, + 781961, + -255540, + -34535, + 151629, + -160339, + 115753, + -77600, + 191516, + -366741, + 594592, + -842360, + 1047324, + -1114872, + 922778, + -333083, + -787962, + 2542790, + -4970652, + 8014781, + -11493412, + 15079883, + -18296595, + 20526277, + -21041783, + 19052701, + -13763619, + 4435071, + 9566123, + -28746427, + 53525544, + -84394911, + 122334186, + -169905429, + 234641818, + -343599171, + 668298214, + 1845596354, + -194696929, + 28271706, + 34203034, + -63057154, + 75115296, + -76974793, + 72216750, + -63273606, + 52012278, + -39921697, + 28166020, + -17597294, + 8765359, + -1939836, + -2852082, + 5774404, + -7123183, + 7266129, + -6587433, + 5442887, + -4128475, + 2863405, + -1786591, + 964000, + -403360, + 72441, + 82536, + -121064, + 96728, + -72374, + 185689, + -367789, + 616056, + -904484, + 1176311, + -1340248, + 1272549, + -826688, + -148464, + 1782399, + -4150626, + 7239673, + -10914122, + 14891009, + -18726726, + 21820518, + -23436573, + 22743822, + -18868969, + 10954038, + 1795422, + -20092820, + 44619296, + -76209307, + 116345472, + -168487153, + 242277182, + -372082103, + 785536421, + 1786629802, + -254498108, + 67706995, + 6262351, + -43117319, + 61333299, + -68100524, + 67243320, + -61315803, + 52271618, + -41686086, + 30821184, + -20638702, + 11804993, + -4705439, + -525480, + 3959454, + -5819581, + 6421920, + -6119868, + 5256842, + -4131044, + 2973995, + -1942499, + 1122017, + -538318, + 173801, + 15002, + -81562, + 77080, + -65071, + 175643, + -361492, + 626268, + -951293, + 1286911, + -1546868, + 1608086, + -1317948, + 510348, + 969408, + -3232350, + 6309280, + -10114378, + 14414285, + -18808136, + 22723144, + -25428523, + 26067713, + -23705174, + 17379438, + -6148217, + -10897519, + 34690832, + -66399685, + 107995814, + -163809779, + 245551331, + -395000608, + 903203493, + 1717352196, + -305282132, + 104204445, + -20923913, + -22879007, + 46709882, + -58131797, + 61106942, + -58247726, + 51549889, + -42641001, + 32854202, + -23240777, + 14569248, + -7331883, + 1766408, + 2106573, + -4434209, + 5475950, + -5548486, + 4976867, + -4056125, + 3025735, + -2057269, + 1253794, + -658305, + 267827, + -49739, + -42625, + 57255, + -55691, + 161332, + -347606, + 624531, + -981265, + 1376312, + -1730101, + 1922454, + -1797293, + 1176259, + 118194, + -2231216, + 5238072, + -9104924, + 13653113, + -18532608, + 23209690, + -26972408, + 28954589, + -28175516, + 23587495, + -14117013, + -1325025, + 23908444, + -55117290, + 97386166, + -155867263, + 244238377, + -411620225, + 1020101305, + 1638538671, + -346912202, + 137245776, + -46885337, + -2721883, + 31533991, + -47275389, + 53943375, + -54146301, + 49877604, + -42782554, + 34237834, + -25362550, + 17011324, + -9772548, + 3981301, + 251253, + -2994755, + 4448196, + -4886406, + 4610513, + -3907134, + 3019278, + -2129960, + 1357685, + -761571, + 353011, + -110560, + -4993, + 37677, + -44286, + 142800, + -326035, + 610363, + -993162, + 1442022, + -1885629, + 2208927, + -2255124, + 1836607, + -755785, + -1164562, + 4043536, + -7900750, + 12616411, + -17898590, + 23263185, + -28030737, + 31341757, + -32188541, + 29456392, + -21960073, + 8449987, + 12459825, + -42544294, + 84662182, + -144713753, + 238186364, + -421266754, + 1135018540, + 1551066450, + -379372923, + 166391544, + -71187473, + 16985265, + 16098498, + -35750442, + 45904959, + -49106338, + 47302484, + -42122123, + 34957461, + -26972768, + 19091296, + -11985160, + 6079168, + -1571674, + -1529347, + 3359738, + -4148158, + 4166778, + -3688802, + 2956367, + -2160461, + 1432632, + -846749, + 428074, + -166461, + 30661, + 18737, + -30959, + 120185, + -296834, + 583510, + -986056, + 1481933, + -2009545, + 2461130, + -2682002, + 2478514, + -1636260, + -51380, + 2745904, + -6520890, + 11318546, + -16911357, + 22874614, + -28574603, + 33174931, + -35659894, + 34868617, + -29526197, + 18245787, + 548919, + -28891028, + 70012568, + -130464266, + 227322419, + -423337862, + 1246746250, + 1455903084, + -402767599, + 191285371, + -93438389, + 35890890, + 694767, + -23784190, + 37157486, + -43238454, + 43888271, + -40685880, + 35011139, + -28050306, + 20776746, + -13932505, + 8022945, + -3328677, + -66018, + 2232337, + -3349369, + 3655900, + -3407046, + 2839763, + -2149466, + 1478161, + -912870, + 491984, + -216584, + 63737, + 787, + -15865, + 93720, + -260223, + 543967, + -959363, + 1494375, + -2098434, + 2673169, + -3068830, + 3089134, + -2506450, + 1088013, + 1367826, + -4988135, + 9779170, + -15583036, + 22043234, + -28584387, + 34409418, + -38514045, + 39713267, + -36666736, + 27876889, + -11607607, + -14392642, + 53666609, + -113294307, + 211656746, + -417313879, + 1354093531, + 1354093531, + -417313879, + 211656746, + -113294307, + 53666609, + -14392642, + -11607607, + 27876889, + -36666736, + 39713267, + -38514045, + 34409418, + -28584387, + 22043234, + -15583036, + 9779170, + -4988135, + 1367826, + 1088013, + -2506450, + 3089134, + -3068830, + 2673169, + -2098434, + 1494375, + -959363, + 543967, + -260223, + 93720, + -15865, + 787, + 63737, + -216584, + 491984, + -912870, + 1478161, + -2149466, + 2839763, + -3407046, + 3655900, + -3349369, + 2232337, + -66018, + -3328677, + 8022945, + -13932505, + 20776746, + -28050306, + 35011139, + -40685880, + 43888271, + -43238454, + 37157486, + -23784190, + 694767, + 35890890, + -93438389, + 191285371, + -402767599, + 1455903084, + 1246746250, + -423337862, + 227322419, + -130464266, + 70012568, + -28891028, + 548919, + 18245787, + -29526197, + 34868617, + -35659894, + 33174931, + -28574603, + 22874614, + -16911357, + 11318546, + -6520890, + 2745904, + -51380, + -1636260, + 2478514, + -2682002, + 2461130, + -2009545, + 1481933, + -986056, + 583510, + -296834, + 120185, + -30959, + 18737, + 30661, + -166461, + 428074, + -846749, + 1432632, + -2160461, + 2956367, + -3688802, + 4166778, + -4148158, + 3359738, + -1529347, + -1571674, + 6079168, + -11985160, + 19091296, + -26972768, + 34957461, + -42122123, + 47302484, + -49106338, + 45904959, + -35750442, + 16098498, + 16985265, + -71187473, + 166391544, + -379372923, + 1551066450, + 1135018540, + -421266754, + 238186364, + -144713753, + 84662182, + -42544294, + 12459825, + 8449987, + -21960073, + 29456392, + -32188541, + 31341757, + -28030737, + 23263185, + -17898590, + 12616411, + -7900750, + 4043536, + -1164562, + -755785, + 1836607, + -2255124, + 2208927, + -1885629, + 1442022, + -993162, + 610363, + -326035, + 142800, + -44286, + 37677, + -4993, + -110560, + 353011, + -761571, + 1357685, + -2129960, + 3019278, + -3907134, + 4610513, + -4886406, + 4448196, + -2994755, + 251253, + 3981301, + -9772548, + 17011324, + -25362550, + 34237834, + -42782554, + 49877604, + -54146301, + 53943375, + -47275389, + 31533991, + -2721883, + -46885337, + 137245776, + -346912202, + 1638538671, + 1020101305, + -411620225, + 244238377, + -155867263, + 97386166, + -55117290, + 23908444, + -1325025, + -14117013, + 23587495, + -28175516, + 28954589, + -26972408, + 23209690, + -18532608, + 13653113, + -9104924, + 5238072, + -2231216, + 118194, + 1176259, + -1797293, + 1922454, + -1730101, + 1376312, + -981265, + 624531, + -347606, + 161332, + -55691, + 57255, + -42625, + -49739, + 267827, + -658305, + 1253794, + -2057269, + 3025735, + -4056125, + 4976867, + -5548486, + 5475950, + -4434209, + 2106573, + 1766408, + -7331883, + 14569248, + -23240777, + 32854202, + -42641001, + 51549889, + -58247726, + 61106942, + -58131797, + 46709882, + -22879007, + -20923913, + 104204445, + -305282132, + 1717352196, + 903203493, + -395000608, + 245551331, + -163809779, + 107995814, + -66399685, + 34690832, + -10897519, + -6148217, + 17379438, + -23705174, + 26067713, + -25428523, + 22723144, + -18808136, + 14414285, + -10114378, + 6309280, + -3232350, + 969408, + 510348, + -1317948, + 1608086, + -1546868, + 1286911, + -951293, + 626268, + -361492, + 175643, + -65071, + 77080, + -81562, + 15002, + 173801, + -538318, + 1122017, + -1942499, + 2973995, + -4131044, + 5256842, + -6119868, + 6421920, + -5819581, + 3959454, + -525480, + -4705439, + 11804993, + -20638702, + 30821184, + -41686086, + 52271618, + -61315803, + 67243320, + -68100524, + 61333299, + -43117319, + 6262351, + 67706995, + -254498108, + 1786629802, + 785536421, + -372082103, + 242277182, + -168487153, + 116345472, + -76209307, + 44619296, + -20092820, + 1795422, + 10954038, + -18868969, + 22743822, + -23436573, + 21820518, + -18726726, + 14891009, + -10914122, + 7239673, + -4150626, + 1782399, + -148464, + -826688, + 1272549, + -1340248, + 1176311, + -904484, + 616056, + -367789, + 185689, + -72374, + 96728, + -121064, + 82536, + 72441, + -403360, + 964000, + -1786591, + 2863405, + -4128475, + 5442887, + -6587433, + 7266129, + -7123183, + 5774404, + -2852082, + -1939836, + 8765359, + -17597294, + 28166020, + -39921697, + 52012278, + -63273606, + 72216750, + -76974793, + 75115296, + -63057154, + 34203034, + 28271706, + -194696929, + 1845596354, + 668298214, + -343599171, + 234641818, + -169905429, + 122334186, + -84394911, + 53525544, + -28746427, + 9566123, + 4435071, + -13763619, + 19052701, + -21041783, + 20526277, + -18296595, + 15079883, + -11493412, + 8014781, + -4970652, + 2542790, + -787962, + -333083, + 922778, + -1114872, + 1047324, + -842360, + 594592, + -366741, + 191516, + -77600, + 115753, + -160339, + 151629, + -34535, + -255540, + 781961, + -1591317, + 2694434, + -4046411, + 5529080, + -6939754, + 7990115, + -8318313, + 7515939, + -5169628, + 914771, + 5503259, + -14166626, + 24928273, + -37367179, + 50759447, + -64063870, + 75910923, + -84564325, + 87776327, + -82314702, + 62399094, + -13509895, + -126137813, + 1893589230, + 552658580, + -310334302, + 222938849, + -168129131, + 125906511, + -90838315, + 61263437, + -36706883, + 17021913, + -2054077, + -8489208, + 15069795, + -18296121, + 18871783, + -17532353, + 14982978, + -11845863, + 8623365, + -5679230, + 3237536, + -1396602, + 153508, + 565780, + -875583, + 903020, + -766678, + 562762, + -358726, + 193255, + -80794, + 133693, + -198559, + 220953, + -145225, + -97301, + 578661, + -1359276, + 2468704, + -3884337, + 5511281, + -7167360, + 8577320, + -9379785, + 9149265, + -7433673, + 3805585, + 2076813, + -10405081, + 21159292, + -34057238, + 48519345, + -63650426, + 78231540, + -90699239, + 99051667, + -100508957, + 90330929, + -56979950, + -49201656, + 1930067252, + 439744137, + -273105353, + 207522473, + -163278571, + 127052487, + -95455901, + 67711264, + -43838350, + 24029172, + -8392702, + -3147260, + 10874697, + -15257209, + 16894584, + -16454603, + 14607689, + -11969482, + 9057556, + -6265553, + 3855137, + -1963710, + 624108, + 208500, + -627340, + 746660, + -679392, + 521618, + -344242, + 191113, + -82045, + 150078, + -234871, + 289120, + -257578, + 68618, + 357375, + -1093863, + 2188988, + -3643275, + 5387261, + -7262963, + 9013447, + -10284452, + 10640961, + -9599932, + 6678131, + -1451664, + -6378391, + 16921441, + -30041552, + 45317045, + -62019267, + 79108501, + -95233652, + 108696666, + -117268800, + 117467011, + -101422410, + 35611454, + 1954617994, + 330624501, + -232752654, + 188799554, + -155526255, + 125806790, + -98199446, + 72773536, + -50022852, + 30464974, + -14464993, + 2161191, + 6549588, + -11987142, + 14637596, + -15089444, + 13966495, + -11866620, + 9312932, + -6721362, + 4385818, + -2479666, + 1070282, + -142311, + -375120, + 581623, + -582606, + 472348, + -323891, + 185366, + -81481, + 164446, + -268420, + 354700, + -369427, + 239228, + 121835, + -799229, + 1859186, + -3325805, + 5156786, + -7221651, + 9286795, + -11011686, + 11959647, + -11625137, + 9477259, + -5016776, + -2158509, + 12287102, + -25384081, + 41196332, + -59179213, + 78497683, + -98048896, + 116491759, + -132240061, + 143272983, + -146072317, + 127686471, + 1966963362, + 226299327, + -190126085, + 167221055, + -145092455, + 122247105, + -99056298, + 76382260, + -55162151, + 36219193, + -20162106, + 7337477, + 2177650, + -8551241, + 12148196, + -13467879, + 13076626, + -11543835, + 9388532, + -7041036, + 4821677, + -2936056, + 1484284, + -480222, + -123820, + 411341, + -478529, + 416250, + -298364, + 176349, + -79259 + +}; + +static const struct src_stage src_int32_21_20_4167_5000 = { + 19, 20, 21, 60, 1260, 20, 21, 0, 0, + src_int32_21_20_4167_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_20_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_21_20_4535_5000.h new file mode 100644 index 000000000000..c6a76782842e --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_20_4535_5000.h @@ -0,0 +1,2286 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_20_4535_5000_fir[2268] = { + -37260, + 62223, + -92794, + 127804, + -165106, + 201434, + -232305, + 251988, + -253547, + 228982, + -169476, + 65750, + 91473, + -310888, + 599947, + -964120, + 1406106, + -1925039, + 2515714, + -3167883, + 3865669, + -4587131, + 5304037, + -5981866, + 6580089, + -7052735, + 7349248, + -7415655, + 7195996, + -6634012, + 5675020, + -4267939, + 2367374, + 64304, + -3054988, + 6621048, + -10765830, + 15478533, + -20733532, + 26490251, + -32693631, + 39275294, + -46155476, + 53245866, + -60453570, + 67686652, + -74862174, + 81918813, + -88839003, + 95693725, + -102749602, + 110785033, + -122356402, + 150829476, + 2045915016, + 49773549, + -73582504, + 80154873, + -81690534, + 80728384, + -78179141, + 74494086, + -69957639, + 64783214, + -59149642, + 53215902, + -47126860, + 41015001, + -35000334, + 29189540, + -23674925, + 18533488, + -13826291, + 9598205, + -5878100, + 2679461, + -1406, + -2169932, + 3859738, + -5102628, + 5940627, + -6421087, + 6594638, + -6513230, + 6228334, + -5789366, + 5242347, + -4628857, + 3985268, + -3342271, + 2724669, + -2151438, + 1635985, + -1186605, + 807067, + -497298, + 254118, + -71993, + -56247, + 138726, + -183930, + 200202, + -195341, + 176304, + -149015, + 118267, + -87708, + 59897, + -37334, + 63318, + -96107, + 134969, + -178219, + 223042, + -265359, + 299745, + -319422, + 316345, + -281391, + 204660, + -75899, + -114965, + 377173, + -718399, + 1143945, + -1655893, + 2252262, + -2926205, + 3665284, + -4450893, + 5257842, + -6054173, + 6801232, + -7454020, + 7961852, + -8269319, + 8317550, + -8045747, + 7392949, + -6299983, + 4711518, + -2578149, + -141576, + 3479300, + -7455265, + 12077109, + -17339161, + 23222369, + -29695020, + 36714434, + -44229911, + 52187400, + -60536648, + 69242368, + -78302441, + 87779783, + -97863541, + 109000811, + -122224269, + 140143864, + -171013274, + 259051827, + 2032050519, + -43244160, + -25612144, + 48891991, + -59503083, + 64436705, + -66125660, + 65678519, + -63707669, + 60607641, + -56665647, + 52110351, + -47134723, + 41906954, + -36575522, + 31271313, + -26108293, + 21183548, + -16577148, + 12352117, + -8554650, + 5214650, + -2346624, + -49100, + 1984847, + -3483841, + 4578271, + -5307268, + 5714861, + -5847981, + 5754592, + -5481989, + 5075328, + -4576403, + 4022697, + -3446726, + 2875641, + -2331107, + 1829396, + -1381699, + 994583, + -670575, + 408823, + -205795, + 55976, + 47464, + -112062, + 145530, + -155313, + 148258, + -130360, + 106628, + -81015, + 56440, + -36590, + 63105, + -97510, + 139535, + -187993, + 240584, + -293718, + 342387, + -380107, + 398947, + -389653, + 341893, + -244626, + 86591, + 143080, + -454139, + 854410, + -1348915, + 1938970, + -2621294, + 3387177, + -4221746, + 5103388, + -6003373, + 6885714, + -7707300, + 8418333, + -8963077, + 9280914, + -9307699, + 8977383, + -8223838, + 6982845, + -5194147, + 2803474, + 235555, + -3959792, + 8395302, + -13556653, + 19446918, + -26058641, + 33376062, + -41379077, + 50049713, + -59382492, + 69401264, + -80187756, + 91933205, + -105039995, + 120344448, + -139678897, + 167597009, + -218591548, + 373448380, + 2004490832, + -127482277, + 20688679, + 17627270, + -36654379, + 47170290, + -52943936, + 55670265, + -56256484, + 55260157, + -53065659, + 49963606, + -46189276, + 41941954, + -37394775, + 32699621, + -27989411, + 23379044, + -18965745, + 14829221, + -11031893, + 7619340, + -4621036, + 2051390, + 88916, + -1811332, + 3137642, + -4098035, + 4729107, + -5071874, + 5169860, + -5067317, + 4807642, + -4432006, + 3978253, + -3480060, + 2966366, + -2461068, + 1982957, + -1545868, + 1159007, + -827425, + 552589, + -333017, + 164936, + -42930, + -39451, + 89145, + -113109, + 117941, + -109595, + 93192, + -72914, + 51973, + -35003, + 61531, + -96904, + 141320, + -194125, + 253585, + -316676, + 378912, + -434235, + 474983, + -491954, + 474585, + -411256, + 289724, + -97695, + -176490, + 543049, + -1009873, + 1581582, + -2258565, + 3036045, + -3903218, + 4842517, + -5829042, + 6830220, + -7805711, + 8707618, + -9480995, + 10064691, + -10392487, + 10394541, + -9999062, + 9134185, + -7729946, + 5720275, + -3044894, + -349023, + 4505574, + -9459425, + 15235905, + -21852212, + 29320151, + -37651076, + 46864131, + -56999743, + 68142063, + -80457814, + 94267764, + -110189339, + 129452806, + -154707316, + 192526569, + -264103248, + 492918454, + 1963572100, + -202337738, + 64520865, + -13027626, + -13613391, + 29293146, + -38917356, + 44688386, + -47770464, + 48863304, + -48435481, + 46830674, + -44319862, + 41128204, + -37449194, + 33452086, + -29285655, + 25079992, + -20947271, + 16982077, + -13261634, + 9846136, + -6779302, + 4089217, + -1789455, + -119522, + 1648737, + -2818900, + 3658502, + -4201871, + 4487258, + -4555016, + 4445930, + -4199739, + 3853890, + -3442542, + 2995830, + -2539394, + 2094143, + -1676257, + 1297373, + -964940, + 682690, + -451197, + 268485, + -130641, + 32414, + 32235, + -69640, + 86031, + -87204, + 78294, + -63621, + 46631, + -32563, + 58574, + -94228, + 140197, + -196382, + 261654, + -333624, + 408423, + -480542, + 542747, + -586067, + 599914, + -572314, + 490275, + -340302, + 109042, + 215939, + -645274, + 1186828, + -1844688, + 2618146, + -3500720, + 4479276, + -5533282, + 6634262, + -7745485, + 8821932, + -9810568, + 10650935, + -11276068, + 11613718, + -11587847, + 11120348, + -10132909, + 8548927, + -6295363, + 3304387, + 485352, + -5128053, + 10670957, + -17155782, + 24621949, + -33112439, + 42683711, + -53422189, + 65472102, + -79084338, + 94707369, + -113170475, + 136093529, + -166941543, + 214343362, + -306549395, + 616266675, + 1909792424, + -267351475, + 105163124, + -42491106, + 9158172, + 11174287, + -24341397, + 32968180, + -38434514, + 41559201, + -42880663, + 42785839, + -41574161, + 39490968, + -36745433, + 33520216, + -29976553, + 26256801, + -22485584, + 18770269, + -15201161, + 11851712, + -8778882, + 6023753, + -3612414, + 1557134, + 142212, + -1496517, + 2525659, + -3256647, + 3721738, + -3956615, + 3998661, + -3885405, + 3653156, + -3335873, + 2964280, + -2565232, + 2161325, + -1770740, + 1407292, + -1080654, + 796725, + -558104, + 364626, + -213943, + 102090, + -24035, + -25822, + 53221, + -63693, + 62284, + -53373, + 40565, + -29281, + 54239, + -89465, + 136099, + -194605, + 264493, + -344063, + 430146, + -517903, + 600669, + -669890, + 715161, + -724384, + 684070, + -579777, + 396706, + -120429, + -262244, + 762299, + -1387477, + 2141189, + -3021450, + 4019862, + -5120711, + 6300229, + -7526062, + 8757003, + -9943012, + 11025555, + -11938267, + 12607943, + -12955811, + 12899070, + -12352594, + 11230742, + -9449123, + 6926198, + -3584509, + -648697, + 5841753, + -12060234, + 19370612, + -27846961, + 37582406, + -48708384, + 61427551, + -76072092, + 93213245, + -113883735, + 140079185, + -176059969, + 232498993, + -344935980, + 742218361, + 1843804619, + -322211836, + 141981321, + -70221661, + 31214631, + -6819607, + -9517568, + 20756240, + -28448117, + 33506450, + -36524151, + 37920949, + -38017033, + 37071885, + -35305398, + 32909439, + -30054077, + 26890773, + -23553868, + 20161156, + -16814052, + 13597648, + -10580876, + 7816874, + -5343618, + 3184845, + -1351241, + -158128, + 1354203, + -2256190, + 2889761, + -3285253, + 3475936, + -3496398, + 3381101, + -3163133, + 2873192, + -2538805, + 2183790, + -1827953, + 1486989, + -1172583, + 892662, + -651774, + 451551, + -291234, + 168208, + -78534, + 17447, + 20203, + -39573, + 45527, + -42417, + 33934, + -25187, + 48563, + -82641, + 129018, + -188716, + 261906, + -347617, + 443456, + -545353, + 647355, + -741496, + 817763, + -864176, + 867005, + -811142, + 680617, + -459278, + 131611, + 316302, + -895736, + 1614196, + -2474273, + 3472519, + -4598397, + 5833365, + -7150136, + 8512179, + -9873484, + 11178638, + -12363230, + 13354574, + -14072747, + 14431905, + -14341805, + 13709454, + -12440769, + 10442089, + -7621339, + 3888603, + 844275, + -6665531, + 13667529, + -21954189, + 31653797, + -42940752, + 56073046, + -71459256, + 89785288, + -112273621, + 141271932, + -181794847, + 246497512, + -378290243, + 869436283, + 1766406750, + -366755724, + 174436128, + -95726884, + 52134601, + -24331364, + 5252674, + 8305372, + -18021138, + 24876742, + -29503605, + 32343377, + -33729026, + 33927952, + -33165655, + 31638860, + -29522685, + 26974378, + -24135076, + 21130458, + -18070855, + 15051160, + -12150769, + 9433701, + -6948955, + 4731163, + -2801521, + 1168992, + 168281, + -1221383, + 2008942, + -2555391, + 2889259, + -3041533, + 3044158, + -2928703, + 2725231, + -2461392, + 2161745, + -1847308, + 1535332, + -1239260, + 968871, + -730549, + 527672, + -361067, + 229503, + -130196, + 59298, + -12345, + -15355, + 28392, + -31004, + 26901, + -20330, + 41612, + -73830, + 119009, + -178723, + 253805, + -344047, + 447886, + -562112, + 681613, + -799174, + 905376, + -988595, + 1035134, + -1029507, + 954881, + -793680, + 528355, + -142302, + -379098, + 1047333, + -1869560, + 2847397, + -3975743, + 5241699, + -6623642, + 8090490, + -9601225, + 11104707, + -12539793, + 13835800, + -14913273, + 15685054, + -16057591, + 15932397, + -15207567, + 13779169, + -11542330, + 8391724, + -4221089, + -1078778, + 7624383, + -15547560, + 25009415, + -36224199, + 49500750, + -65317117, + 84462676, + -108330699, + 139587302, + -183938904, + 255906453, + -405677006, + 996538571, + 1678530575, + -400967457, + 202088896, + -118571348, + 71528612, + -41020169, + 19673911, + -4130543, + -7369490, + 15851254, + -21968464, + 26173676, + -28804584, + 30130223, + -30376546, + 29740733, + -28399106, + 26511291, + -24222185, + 21662663, + -18949616, + 16185706, + -13459091, + 10843279, + -8397211, + 6165626, + -4179721, + 2458093, + -1007934, + -173568, + 1097683, + -1782505, + 2251292, + -2530847, + 2649988, + -2638153, + 2524179, + -2335290, + 2096293, + -1828994, + 1551841, + -1279754, + 1024149, + -793104, + 591654, + -422177, + 284833, + -178035, + 98916, + -43771, + 8462, + 11243, + -19390, + 19632, + -14782, + 33486, + -63148, + 106192, + -164718, + 240216, + -333255, + 443144, + -567609, + 702486, + -841468, + 975921, + -1094812, + 1184749, + -1230171, + 1213708, + -1116696, + 919879, + -604269, + 152165, + 451713, + -1218991, + 2156363, + -3264318, + 4535911, + -5955664, + 7498619, + -9129621, + 10802869, + -12461759, + 14039061, + -15457408, + 16630100, + -17462166, + 17851614, + -17690760, + 16867487, + -15266219, + 12768324, + -9251550, + 4587892, + 1360988, + -8752246, + 17776675, + -28684254, + 41828833, + -57749093, + 77323691, + -102092616, + 134996999, + -182350955, + 260367029, + -426214767, + 1122117476, + 1581228098, + -424975399, + 224605677, + -138383233, + 89045961, + -56567967, + 33462526, + -16301634, + 3289281, + 6616886, + -14076798, + 19543013, + -23349994, + 25762225, + -27001025, + 27259680, + -26711885, + 25516214, + -23818240, + 21751258, + -19436247, + 16981468, + -14481963, + 12019161, + -9660670, + 7460355, + -5458699, + 3683485, + -2150732, + 865890, + 174790, + -982756, + 1575581, + -1975386, + 2207318, + -2298118, + 2274840, + -2163749, + 1989403, + -1773962, + 1536692, + -1293682, + 1057742, + -838466, + 642430, + -473499, + 333203, + -221167, + 135548, + -73465, + 31404, + -5568, + -7821, + 12291, + -8631, + 24311, + -50757, + 90750, + -146882, + 221283, + -315294, + 429125, + -561493, + 709278, + -867214, + 1027636, + -1180326, + 1312463, + -1408726, + 1451543, + -1421522, + 1298066, + -1060162, + 687346, + -160816, + -535331, + 1412781, + -2477650, + 3729141, + -5158287, + 6746808, + -8466173, + 10276890, + -12128079, + 13957354, + -15691031, + 17244642, + -18523735, + 19424883, + -19836811, + 19641487, + -18714969, + 16927724, + -14143987, + 10219557, + -4997076, + -1702732, + 10096460, + -20464763, + 33199413, + -48889092, + 68484754, + -93644185, + 127530653, + -176960373, + 259603288, + -439091317, + 1244758732, + 1475656427, + -439046464, + 241759377, + -154859611, + 104380670, + -70685310, + 46352150, + -27966968, + 13740370, + -2637559, + -5992031, + 12590404, + -17481119, + 20918145, + -23113268, + 24251671, + -24500688, + 24014471, + -22936194, + 21398773, + -19524739, + 17425677, + -15201522, + 12939900, + -10715648, + 8590590, + -6613613, + 4821044, + -3237342, + 1876038, + -740913, + -172661, + 876271, + -1386962, + 1725741, + -1916147, + 1982934, + -1950893, + 1843856, + -1683892, + 1490698, + -1281204, + 1069348, + -866032, + 679227, + -514191, + 373781, + -258824, + 168523, + -100868, + 53026, + -21706, + 3465, + 5036, + -1983, + 14243, + -36862, + 72927, + -125482, + 197261, + -290366, + 405911, + -543645, + 701567, + -875568, + 1059115, + -1243017, + 1415289, + -1561149, + 1663175, + -1701627, + 1654961, + -1500539, + 1215515, + -777907, + 167815, + 631253, + -1630968, + 2836753, + -4246384, + 5848691, + -7622395, + 9535165, + -11542921, + 13589433, + -15606228, + 17512815, + -19217200, + 20616642, + -21598550, + 22041389, + -21815391, + 20782774, + -18797056, + 15700817, + -11320955, + 5459828, + 2120412, + -11725190, + 23775984, + -38899235, + 58098675, + -83116534, + 117276457, + -167770316, + 253430038, + -443578583, + 1363061185, + 1363061185, + -443578583, + 253430038, + -167770316, + 117276457, + -83116534, + 58098675, + -38899235, + 23775984, + -11725190, + 2120412, + 5459828, + -11320955, + 15700817, + -18797056, + 20782774, + -21815391, + 22041389, + -21598550, + 20616642, + -19217200, + 17512815, + -15606228, + 13589433, + -11542921, + 9535165, + -7622395, + 5848691, + -4246384, + 2836753, + -1630968, + 631253, + 167815, + -777907, + 1215515, + -1500539, + 1654961, + -1701627, + 1663175, + -1561149, + 1415289, + -1243017, + 1059115, + -875568, + 701567, + -543645, + 405911, + -290366, + 197261, + -125482, + 72927, + -36862, + 14243, + -1983, + 5036, + 3465, + -21706, + 53026, + -100868, + 168523, + -258824, + 373781, + -514191, + 679227, + -866032, + 1069348, + -1281204, + 1490698, + -1683892, + 1843856, + -1950893, + 1982934, + -1916147, + 1725741, + -1386962, + 876271, + -172661, + -740913, + 1876038, + -3237342, + 4821044, + -6613613, + 8590590, + -10715648, + 12939900, + -15201522, + 17425677, + -19524739, + 21398773, + -22936194, + 24014471, + -24500688, + 24251671, + -23113268, + 20918145, + -17481119, + 12590404, + -5992031, + -2637559, + 13740370, + -27966968, + 46352150, + -70685310, + 104380670, + -154859611, + 241759377, + -439046464, + 1475656427, + 1244758732, + -439091317, + 259603288, + -176960373, + 127530653, + -93644185, + 68484754, + -48889092, + 33199413, + -20464763, + 10096460, + -1702732, + -4997076, + 10219557, + -14143987, + 16927724, + -18714969, + 19641487, + -19836811, + 19424883, + -18523735, + 17244642, + -15691031, + 13957354, + -12128079, + 10276890, + -8466173, + 6746808, + -5158287, + 3729141, + -2477650, + 1412781, + -535331, + -160816, + 687346, + -1060162, + 1298066, + -1421522, + 1451543, + -1408726, + 1312463, + -1180326, + 1027636, + -867214, + 709278, + -561493, + 429125, + -315294, + 221283, + -146882, + 90750, + -50757, + 24311, + -8631, + 12291, + -7821, + -5568, + 31404, + -73465, + 135548, + -221167, + 333203, + -473499, + 642430, + -838466, + 1057742, + -1293682, + 1536692, + -1773962, + 1989403, + -2163749, + 2274840, + -2298118, + 2207318, + -1975386, + 1575581, + -982756, + 174790, + 865890, + -2150732, + 3683485, + -5458699, + 7460355, + -9660670, + 12019161, + -14481963, + 16981468, + -19436247, + 21751258, + -23818240, + 25516214, + -26711885, + 27259680, + -27001025, + 25762225, + -23349994, + 19543013, + -14076798, + 6616886, + 3289281, + -16301634, + 33462526, + -56567967, + 89045961, + -138383233, + 224605677, + -424975399, + 1581228098, + 1122117476, + -426214767, + 260367029, + -182350955, + 134996999, + -102092616, + 77323691, + -57749093, + 41828833, + -28684254, + 17776675, + -8752246, + 1360988, + 4587892, + -9251550, + 12768324, + -15266219, + 16867487, + -17690760, + 17851614, + -17462166, + 16630100, + -15457408, + 14039061, + -12461759, + 10802869, + -9129621, + 7498619, + -5955664, + 4535911, + -3264318, + 2156363, + -1218991, + 451713, + 152165, + -604269, + 919879, + -1116696, + 1213708, + -1230171, + 1184749, + -1094812, + 975921, + -841468, + 702486, + -567609, + 443144, + -333255, + 240216, + -164718, + 106192, + -63148, + 33486, + -14782, + 19632, + -19390, + 11243, + 8462, + -43771, + 98916, + -178035, + 284833, + -422177, + 591654, + -793104, + 1024149, + -1279754, + 1551841, + -1828994, + 2096293, + -2335290, + 2524179, + -2638153, + 2649988, + -2530847, + 2251292, + -1782505, + 1097683, + -173568, + -1007934, + 2458093, + -4179721, + 6165626, + -8397211, + 10843279, + -13459091, + 16185706, + -18949616, + 21662663, + -24222185, + 26511291, + -28399106, + 29740733, + -30376546, + 30130223, + -28804584, + 26173676, + -21968464, + 15851254, + -7369490, + -4130543, + 19673911, + -41020169, + 71528612, + -118571348, + 202088896, + -400967457, + 1678530575, + 996538571, + -405677006, + 255906453, + -183938904, + 139587302, + -108330699, + 84462676, + -65317117, + 49500750, + -36224199, + 25009415, + -15547560, + 7624383, + -1078778, + -4221089, + 8391724, + -11542330, + 13779169, + -15207567, + 15932397, + -16057591, + 15685054, + -14913273, + 13835800, + -12539793, + 11104707, + -9601225, + 8090490, + -6623642, + 5241699, + -3975743, + 2847397, + -1869560, + 1047333, + -379098, + -142302, + 528355, + -793680, + 954881, + -1029507, + 1035134, + -988595, + 905376, + -799174, + 681613, + -562112, + 447886, + -344047, + 253805, + -178723, + 119009, + -73830, + 41612, + -20330, + 26901, + -31004, + 28392, + -15355, + -12345, + 59298, + -130196, + 229503, + -361067, + 527672, + -730549, + 968871, + -1239260, + 1535332, + -1847308, + 2161745, + -2461392, + 2725231, + -2928703, + 3044158, + -3041533, + 2889259, + -2555391, + 2008942, + -1221383, + 168281, + 1168992, + -2801521, + 4731163, + -6948955, + 9433701, + -12150769, + 15051160, + -18070855, + 21130458, + -24135076, + 26974378, + -29522685, + 31638860, + -33165655, + 33927952, + -33729026, + 32343377, + -29503605, + 24876742, + -18021138, + 8305372, + 5252674, + -24331364, + 52134601, + -95726884, + 174436128, + -366755724, + 1766406750, + 869436283, + -378290243, + 246497512, + -181794847, + 141271932, + -112273621, + 89785288, + -71459256, + 56073046, + -42940752, + 31653797, + -21954189, + 13667529, + -6665531, + 844275, + 3888603, + -7621339, + 10442089, + -12440769, + 13709454, + -14341805, + 14431905, + -14072747, + 13354574, + -12363230, + 11178638, + -9873484, + 8512179, + -7150136, + 5833365, + -4598397, + 3472519, + -2474273, + 1614196, + -895736, + 316302, + 131611, + -459278, + 680617, + -811142, + 867005, + -864176, + 817763, + -741496, + 647355, + -545353, + 443456, + -347617, + 261906, + -188716, + 129018, + -82641, + 48563, + -25187, + 33934, + -42417, + 45527, + -39573, + 20203, + 17447, + -78534, + 168208, + -291234, + 451551, + -651774, + 892662, + -1172583, + 1486989, + -1827953, + 2183790, + -2538805, + 2873192, + -3163133, + 3381101, + -3496398, + 3475936, + -3285253, + 2889761, + -2256190, + 1354203, + -158128, + -1351241, + 3184845, + -5343618, + 7816874, + -10580876, + 13597648, + -16814052, + 20161156, + -23553868, + 26890773, + -30054077, + 32909439, + -35305398, + 37071885, + -38017033, + 37920949, + -36524151, + 33506450, + -28448117, + 20756240, + -9517568, + -6819607, + 31214631, + -70221661, + 141981321, + -322211836, + 1843804619, + 742218361, + -344935980, + 232498993, + -176059969, + 140079185, + -113883735, + 93213245, + -76072092, + 61427551, + -48708384, + 37582406, + -27846961, + 19370612, + -12060234, + 5841753, + -648697, + -3584509, + 6926198, + -9449123, + 11230742, + -12352594, + 12899070, + -12955811, + 12607943, + -11938267, + 11025555, + -9943012, + 8757003, + -7526062, + 6300229, + -5120711, + 4019862, + -3021450, + 2141189, + -1387477, + 762299, + -262244, + -120429, + 396706, + -579777, + 684070, + -724384, + 715161, + -669890, + 600669, + -517903, + 430146, + -344063, + 264493, + -194605, + 136099, + -89465, + 54239, + -29281, + 40565, + -53373, + 62284, + -63693, + 53221, + -25822, + -24035, + 102090, + -213943, + 364626, + -558104, + 796725, + -1080654, + 1407292, + -1770740, + 2161325, + -2565232, + 2964280, + -3335873, + 3653156, + -3885405, + 3998661, + -3956615, + 3721738, + -3256647, + 2525659, + -1496517, + 142212, + 1557134, + -3612414, + 6023753, + -8778882, + 11851712, + -15201161, + 18770269, + -22485584, + 26256801, + -29976553, + 33520216, + -36745433, + 39490968, + -41574161, + 42785839, + -42880663, + 41559201, + -38434514, + 32968180, + -24341397, + 11174287, + 9158172, + -42491106, + 105163124, + -267351475, + 1909792424, + 616266675, + -306549395, + 214343362, + -166941543, + 136093529, + -113170475, + 94707369, + -79084338, + 65472102, + -53422189, + 42683711, + -33112439, + 24621949, + -17155782, + 10670957, + -5128053, + 485352, + 3304387, + -6295363, + 8548927, + -10132909, + 11120348, + -11587847, + 11613718, + -11276068, + 10650935, + -9810568, + 8821932, + -7745485, + 6634262, + -5533282, + 4479276, + -3500720, + 2618146, + -1844688, + 1186828, + -645274, + 215939, + 109042, + -340302, + 490275, + -572314, + 599914, + -586067, + 542747, + -480542, + 408423, + -333624, + 261654, + -196382, + 140197, + -94228, + 58574, + -32563, + 46631, + -63621, + 78294, + -87204, + 86031, + -69640, + 32235, + 32414, + -130641, + 268485, + -451197, + 682690, + -964940, + 1297373, + -1676257, + 2094143, + -2539394, + 2995830, + -3442542, + 3853890, + -4199739, + 4445930, + -4555016, + 4487258, + -4201871, + 3658502, + -2818900, + 1648737, + -119522, + -1789455, + 4089217, + -6779302, + 9846136, + -13261634, + 16982077, + -20947271, + 25079992, + -29285655, + 33452086, + -37449194, + 41128204, + -44319862, + 46830674, + -48435481, + 48863304, + -47770464, + 44688386, + -38917356, + 29293146, + -13613391, + -13027626, + 64520865, + -202337738, + 1963572100, + 492918454, + -264103248, + 192526569, + -154707316, + 129452806, + -110189339, + 94267764, + -80457814, + 68142063, + -56999743, + 46864131, + -37651076, + 29320151, + -21852212, + 15235905, + -9459425, + 4505574, + -349023, + -3044894, + 5720275, + -7729946, + 9134185, + -9999062, + 10394541, + -10392487, + 10064691, + -9480995, + 8707618, + -7805711, + 6830220, + -5829042, + 4842517, + -3903218, + 3036045, + -2258565, + 1581582, + -1009873, + 543049, + -176490, + -97695, + 289724, + -411256, + 474585, + -491954, + 474983, + -434235, + 378912, + -316676, + 253585, + -194125, + 141320, + -96904, + 61531, + -35003, + 51973, + -72914, + 93192, + -109595, + 117941, + -113109, + 89145, + -39451, + -42930, + 164936, + -333017, + 552589, + -827425, + 1159007, + -1545868, + 1982957, + -2461068, + 2966366, + -3480060, + 3978253, + -4432006, + 4807642, + -5067317, + 5169860, + -5071874, + 4729107, + -4098035, + 3137642, + -1811332, + 88916, + 2051390, + -4621036, + 7619340, + -11031893, + 14829221, + -18965745, + 23379044, + -27989411, + 32699621, + -37394775, + 41941954, + -46189276, + 49963606, + -53065659, + 55260157, + -56256484, + 55670265, + -52943936, + 47170290, + -36654379, + 17627270, + 20688679, + -127482277, + 2004490832, + 373448380, + -218591548, + 167597009, + -139678897, + 120344448, + -105039995, + 91933205, + -80187756, + 69401264, + -59382492, + 50049713, + -41379077, + 33376062, + -26058641, + 19446918, + -13556653, + 8395302, + -3959792, + 235555, + 2803474, + -5194147, + 6982845, + -8223838, + 8977383, + -9307699, + 9280914, + -8963077, + 8418333, + -7707300, + 6885714, + -6003373, + 5103388, + -4221746, + 3387177, + -2621294, + 1938970, + -1348915, + 854410, + -454139, + 143080, + 86591, + -244626, + 341893, + -389653, + 398947, + -380107, + 342387, + -293718, + 240584, + -187993, + 139535, + -97510, + 63105, + -36590, + 56440, + -81015, + 106628, + -130360, + 148258, + -155313, + 145530, + -112062, + 47464, + 55976, + -205795, + 408823, + -670575, + 994583, + -1381699, + 1829396, + -2331107, + 2875641, + -3446726, + 4022697, + -4576403, + 5075328, + -5481989, + 5754592, + -5847981, + 5714861, + -5307268, + 4578271, + -3483841, + 1984847, + -49100, + -2346624, + 5214650, + -8554650, + 12352117, + -16577148, + 21183548, + -26108293, + 31271313, + -36575522, + 41906954, + -47134723, + 52110351, + -56665647, + 60607641, + -63707669, + 65678519, + -66125660, + 64436705, + -59503083, + 48891991, + -25612144, + -43244160, + 2032050519, + 259051827, + -171013274, + 140143864, + -122224269, + 109000811, + -97863541, + 87779783, + -78302441, + 69242368, + -60536648, + 52187400, + -44229911, + 36714434, + -29695020, + 23222369, + -17339161, + 12077109, + -7455265, + 3479300, + -141576, + -2578149, + 4711518, + -6299983, + 7392949, + -8045747, + 8317550, + -8269319, + 7961852, + -7454020, + 6801232, + -6054173, + 5257842, + -4450893, + 3665284, + -2926205, + 2252262, + -1655893, + 1143945, + -718399, + 377173, + -114965, + -75899, + 204660, + -281391, + 316345, + -319422, + 299745, + -265359, + 223042, + -178219, + 134969, + -96107, + 63318, + -37334, + 59897, + -87708, + 118267, + -149015, + 176304, + -195341, + 200202, + -183930, + 138726, + -56247, + -71993, + 254118, + -497298, + 807067, + -1186605, + 1635985, + -2151438, + 2724669, + -3342271, + 3985268, + -4628857, + 5242347, + -5789366, + 6228334, + -6513230, + 6594638, + -6421087, + 5940627, + -5102628, + 3859738, + -2169932, + -1406, + 2679461, + -5878100, + 9598205, + -13826291, + 18533488, + -23674925, + 29189540, + -35000334, + 41015001, + -47126860, + 53215902, + -59149642, + 64783214, + -69957639, + 74494086, + -78179141, + 80728384, + -81690534, + 80154873, + -73582504, + 49773549, + 2045915016, + 150829476, + -122356402, + 110785033, + -102749602, + 95693725, + -88839003, + 81918813, + -74862174, + 67686652, + -60453570, + 53245866, + -46155476, + 39275294, + -32693631, + 26490251, + -20733532, + 15478533, + -10765830, + 6621048, + -3054988, + 64304, + 2367374, + -4267939, + 5675020, + -6634012, + 7195996, + -7415655, + 7349248, + -7052735, + 6580089, + -5981866, + 5304037, + -4587131, + 3865669, + -3167883, + 2515714, + -1925039, + 1406106, + -964120, + 599947, + -310888, + 91473, + 65750, + -169476, + 228982, + -253547, + 251988, + -232305, + 201434, + -165106, + 127804, + -92794, + 62223, + -37260 + +}; + +static const struct src_stage src_int32_21_20_4535_5000 = { + 19, 20, 21, 108, 2268, 20, 21, 0, 0, + src_int32_21_20_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_2_3239_5000.h b/src/audio/src/coef/src_ipc4_int32_21_2_3239_5000.h new file mode 100644 index 000000000000..3798885c991c --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_2_3239_5000.h @@ -0,0 +1,690 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_2_3239_5000_fir[672] = { + -35882, + 307961, + -974587, + 1786992, + -1707027, + -1031105, + 8000318, + -18851786, + 29555695, + -31904130, + 15353740, + 28811577, + -102551782, + 198057194, + -299651458, + 397994302, + 1768218431, + 310063911, + -274238794, + 196210625, + -110467558, + 38813781, + 7351410, + -27291795, + 27952050, + -19091390, + 8921874, + -1891068, + -1183279, + 1567319, + -921382, + 308312, + -30825, + 301229, + -1014760, + 1991545, + -2233969, + -108701, + 6905793, + -18299731, + 30751902, + -36180993, + 23396005, + 18006626, + -92735671, + 196865884, + -321734257, + 488774026, + 1759152556, + 225637498, + -246026159, + 191474275, + -116430823, + 47888510, + -490126, + -22426671, + 25981058, + -19027546, + 9663761, + -2678072, + -670988, + 1337156, + -857096, + 302917, + -23595, + 287561, + -1040047, + 2176312, + -2755306, + 864028, + 5648184, + -17430953, + 31505614, + -40042070, + 31352513, + 6540525, + -81102555, + 192527936, + -339974969, + 581704425, + 1741105968, + 145319348, + -215554184, + 184032087, + -120420275, + 55929241, + -8056544, + -17392443, + 23687032, + -18673659, + 10222425, + -3383294, + -177767, + 1101011, + -783733, + 292467, + -14072, + 266497, + -1048732, + 2336669, + -3261825, + 1873496, + 4240531, + -16246180, + 31787569, + -43410788, + 39094559, + -5429895, + -67766728, + 184977002, + -353885936, + 676049773, + 1714248015, + 69657718, + -183367347, + 174099964, + -122444762, + 62848668, + -15241586, + -12272464, + 21117655, + -18047147, + 10597379, + -3999662, + 289507, + 863210, + -703305, + 277692, + -2188, + 237694, + -1039281, + 2468124, + -3744039, + 2904805, + 2698955, + -14751329, + 31575001, + -46215681, + 46492364, + -17734500, + -52872801, + 174191711, + -363010814, + 771044748, + 1678830314, + -860104, + -150007200, + 161921582, + -122542149, + 68579396, + -21948426, + -7148473, + 18323103, + -17169003, + 10791079, + -4521891, + 724774, + 627823, + -617803, + 259343, + 12072, + 200942, + -1010389, + 2566410, + -4192338, + 3941933, + 1042530, + -12957626, + 30852249, + -48391712, + 53417094, + -30192052, + -36594567, + 160197705, + -366931097, + 865902343, + 1635183889, + -65811945, + -116005830, + 147763946, + -120777781, + 73074309, + -28090844, + -2099381, + 15355171, + -16063318, + 10808754, + -4946481, + 1122842, + 398614, + -529152, + 238174, + 28654, + 156179, + -961017, + 2627570, + -4597151, + 4967955, + -706908, + -10881635, + 29611286, + -49881552, + 59742928, + -42612656, + -19133394, + 143069084, + -365272322, + 959822116, + 1583715419, + -124844070, + -81879593, + 131912776, + -117242607, + 76306622, + -33594194, + 2799857, + 12266394, + -14756773, + 10658194, + -5271684, + 1479432, + 178994, + -439187, + 214924, + 47438, + 103511, + -890438, + 2648059, + -4949114, + 5965284, + -2525001, + -8545203, + 27852130, + -50636768, + 65349156, + -54800413, + -716150, + 122929230, + -357709871, + 1051998689, + 1524902633, + -177673650, + -48123231, + 114667776, + -112050972, + 78269619, + -38396169, + 7479269, + 9109194, + -13278110, + 10349518, + -5497449, + 1791196, + -28014, + -349622, + 190306, + 68232, + 43216, + -798269, + 2624826, + -5239251, + 6915940, + -4385168, + -5975313, + 25583153, + -50618910, + 70122252, + -66556264, + 18407311, + 99950986, + -343974293, + 1141630399, + 1459288919, + -224090354, + -15204418, + 96337862, + -105338146, + 78976102, + -42447345, + 11874779, + 5935063, + -11657591, + 9894901, + -5625335, + 2055720, + -219809, + -262026, + 164992, + 90766, + -24239, + -684505, + 2555403, + -5459144, + 7801836, + -6258943, + -3203851, + 22821248, + -49800485, + 73957919, + -77680967, + 37967105, + 74356166, + -323856051, + 1227927977, + 1387477199, + -263957053, + 16441194, + 77236422, + -97257613, + 78457553, + -45711510, + 15928999, + 2793786, + -9926454, + 9308285, + -5658409, + 2271514, + -394227, + -177808, + 139602, + 114696, + -98198, + -549548, + 2437988, + -5601118, + 8605078, + -8116374, + -267278, + 19591883, + -48165776, + 76763046, + -87978183, + 57676662, + 46414382, + -297209650, + 1310123171, + 1310123171, + -297209650, + 46414382, + 57676662, + -87978183, + 76763046, + -48165776, + 19591883, + -267278, + -8116374, + 8605078, + -5601118, + 2437988, + -549548, + -98198, + 114696, + 139602, + -177808, + -394227, + 2271514, + -5658409, + 9308285, + -9926454, + 2793786, + 15928999, + -45711510, + 78457553, + -97257613, + 77236422, + 16441194, + -263957053, + 1387477199, + 1227927977, + -323856051, + 74356166, + 37967105, + -77680967, + 73957919, + -49800485, + 22821248, + -3203851, + -6258943, + 7801836, + -5459144, + 2555403, + -684505, + -24239, + 90766, + 164992, + -262026, + -219809, + 2055720, + -5625335, + 9894901, + -11657591, + 5935063, + 11874779, + -42447345, + 78976102, + -105338146, + 96337862, + -15204418, + -224090354, + 1459288919, + 1141630399, + -343974293, + 99950986, + 18407311, + -66556264, + 70122252, + -50618910, + 25583153, + -5975313, + -4385168, + 6915940, + -5239251, + 2624826, + -798269, + 43216, + 68232, + 190306, + -349622, + -28014, + 1791196, + -5497449, + 10349518, + -13278110, + 9109194, + 7479269, + -38396169, + 78269619, + -112050972, + 114667776, + -48123231, + -177673650, + 1524902633, + 1051998689, + -357709871, + 122929230, + -716150, + -54800413, + 65349156, + -50636768, + 27852130, + -8545203, + -2525001, + 5965284, + -4949114, + 2648059, + -890438, + 103511, + 47438, + 214924, + -439187, + 178994, + 1479432, + -5271684, + 10658194, + -14756773, + 12266394, + 2799857, + -33594194, + 76306622, + -117242607, + 131912776, + -81879593, + -124844070, + 1583715419, + 959822116, + -365272322, + 143069084, + -19133394, + -42612656, + 59742928, + -49881552, + 29611286, + -10881635, + -706908, + 4967955, + -4597151, + 2627570, + -961017, + 156179, + 28654, + 238174, + -529152, + 398614, + 1122842, + -4946481, + 10808754, + -16063318, + 15355171, + -2099381, + -28090844, + 73074309, + -120777781, + 147763946, + -116005830, + -65811945, + 1635183889, + 865902343, + -366931097, + 160197705, + -36594567, + -30192052, + 53417094, + -48391712, + 30852249, + -12957626, + 1042530, + 3941933, + -4192338, + 2566410, + -1010389, + 200942, + 12072, + 259343, + -617803, + 627823, + 724774, + -4521891, + 10791079, + -17169003, + 18323103, + -7148473, + -21948426, + 68579396, + -122542149, + 161921582, + -150007200, + -860104, + 1678830314, + 771044748, + -363010814, + 174191711, + -52872801, + -17734500, + 46492364, + -46215681, + 31575001, + -14751329, + 2698955, + 2904805, + -3744039, + 2468124, + -1039281, + 237694, + -2188, + 277692, + -703305, + 863210, + 289507, + -3999662, + 10597379, + -18047147, + 21117655, + -12272464, + -15241586, + 62848668, + -122444762, + 174099964, + -183367347, + 69657718, + 1714248015, + 676049773, + -353885936, + 184977002, + -67766728, + -5429895, + 39094559, + -43410788, + 31787569, + -16246180, + 4240531, + 1873496, + -3261825, + 2336669, + -1048732, + 266497, + -14072, + 292467, + -783733, + 1101011, + -177767, + -3383294, + 10222425, + -18673659, + 23687032, + -17392443, + -8056544, + 55929241, + -120420275, + 184032087, + -215554184, + 145319348, + 1741105968, + 581704425, + -339974969, + 192527936, + -81102555, + 6540525, + 31352513, + -40042070, + 31505614, + -17430953, + 5648184, + 864028, + -2755306, + 2176312, + -1040047, + 287561, + -23595, + 302917, + -857096, + 1337156, + -670988, + -2678072, + 9663761, + -19027546, + 25981058, + -22426671, + -490126, + 47888510, + -116430823, + 191474275, + -246026159, + 225637498, + 1759152556, + 488774026, + -321734257, + 196865884, + -92735671, + 18006626, + 23396005, + -36180993, + 30751902, + -18299731, + 6905793, + -108701, + -2233969, + 1991545, + -1014760, + 301229, + -30825, + 308312, + -921382, + 1567319, + -1183279, + -1891068, + 8921874, + -19091390, + 27952050, + -27291795, + 7351410, + 38813781, + -110467558, + 196210625, + -274238794, + 310063911, + 1768218431, + 397994302, + -299651458, + 198057194, + -102551782, + 28811577, + 15353740, + -31904130, + 29555695, + -18851786, + 8000318, + -1031105, + -1707027, + 1786992, + -974587, + 307961, + -35882 + +}; + +static const struct src_stage src_int32_21_2_3239_5000 = { + 1, 11, 21, 32, 672, 2, 21, 0, 0, + src_int32_21_2_3239_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_32_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_21_32_4535_5000.h new file mode 100644 index 000000000000..4b2c8db312d0 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_32_4535_5000.h @@ -0,0 +1,3630 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_32_4535_5000_fir[3612] = { + -8897, + -11309, + 29648, + -9652, + -41056, + 55620, + 11220, + -95162, + 72022, + 71594, + -167953, + 52133, + 184703, + -236320, + -38094, + 348205, + -256713, + -229342, + 532796, + -169304, + -532536, + 674961, + 88294, + -920230, + 679031, + 557953, + -1311754, + 432656, + 1232360, + -1569452, + -163194, + 2028137, + -1512626, + -1153120, + 2770604, + -952600, + -2483474, + 3200103, + 253101, + -3968238, + 3006802, + 2135964, + -5278420, + 1894866, + 4555503, + -5966547, + -331102, + 7159819, + -5531673, + -3672441, + 9384587, + -3521138, + -7856375, + 10501644, + 344757, + -12291329, + 9718276, + 6047239, + -16074405, + 6315884, + 13168161, + -18056468, + -195267, + 20834933, + -16953123, + -9936875, + 27718234, + -11466914, + -22573029, + 32060499, + -351913, + -37300028, + 31652765, + 17722550, + -52938119, + 23510885, + 44903713, + -68153175, + 2329649, + 87102438, + -81946010, + -47462915, + 170384176, + -95822895, + -233595023, + 657884189, + 1343290801, + 603222507, + -250273260, + -74792831, + 168186946, + -58553882, + -73803497, + 89743643, + -5392173, + -65031967, + 48848215, + 18313973, + -52558445, + 21743724, + 28520305, + -38477601, + 3135002, + 30591345, + -24516872, + -8815757, + 27503352, + -12080980, + -15229293, + 21464654, + -2151240, + -17200090, + 14262034, + 4779329, + -15925525, + 7285240, + 8696327, + -12639007, + 1489350, + 9981659, + -8482450, + -2616619, + 9280264, + -4385660, + -4928511, + 7346677, + -988605, + -5657102, + 4902552, + 1379345, + -5208866, + 2529553, + 2666300, + -4062458, + 610919, + 3025944, + -2663740, + -677262, + 2727876, + -1354711, + -1334466, + 2071168, + -341931, + -1479656, + 1317225, + 299338, + -1288276, + 650421, + 595698, + -937196, + 167020, + 634234, + -567087, + -113462, + 521733, + -265281, + -223786, + 353483, + -66637, + -221171, + 195829, + 33632, + -163834, + 82118, + 62295, + -96157, + 18419, + 51737, + -43233, + -5933, + 28691, + -12795, + -10190, + -9669, + 30362, + -13378, + -38457, + 59086, + 3777, + -93296, + 81280, + 60253, + -170641, + 70456, + 171771, + -249585, + -8823, + 339769, + -287785, + -190927, + 539274, + -224298, + -492883, + 710169, + 7944, + -894956, + 757215, + 459639, + -1323881, + 563421, + 1135834, + -1646219, + 18572, + 1966847, + -1678973, + -939675, + 2789266, + -1221768, + -2279898, + 3347430, + -109692, + -3838360, + 3323357, + 1720688, + -5302006, + 2397374, + 4165922, + -6225626, + 333817, + 6908693, + -6090205, + -2922179, + 9407035, + -4400580, + -7157138, + 10932604, + -810194, + -11833331, + 10661253, + 4748193, + -16082867, + 7806670, + 11951503, + -18759554, + 1775069, + 20017875, + -18539251, + -7691002, + 27690801, + -14035696, + -20416742, + 33258425, + -3862242, + -35784949, + 34532519, + 13510476, + -52855193, + 28551783, + 40521779, + -70709756, + 10129894, + 83654198, + -89500103, + -35731956, + 171123956, + -116689736, + -213991817, + 712096564, + 1339366730, + 548373439, + -264038792, + -53775776, + 164585550, + -68922922, + -65151977, + 91566522, + -12969821, + -61379616, + 52325635, + 13007718, + -51723682, + 25540635, + 25164488, + -39310048, + 6568279, + 28865756, + -26232817, + -6105933, + 27049674, + -14105274, + -13383719, + 21902755, + -4075858, + -16198877, + 15224346, + 3210720, + -15638415, + 8451765, + 7604834, + -12874024, + 2613645, + 9377761, + -9030363, + -1695092, + 9095513, + -5055847, + -4286288, + 7468066, + -1632992, + -5300343, + 5204329, + 855412, + -5094282, + 2898170, + 2305007, + -4120463, + 960672, + 2826685, + -2819301, + -398213, + 2661652, + -1542782, + -1146152, + 2095721, + -516101, + -1377734, + 1389793, + 164659, + -1253760, + 736291, + 507997, + -945792, + 243450, + 588404, + -596292, + -57271, + 506238, + -298460, + -189317, + 355598, + -94210, + -204299, + 205076, + 15118, + -158344, + 91745, + 52192, + -96289, + 25312, + 47480, + -44977, + -2255, + 27504, + -14118, + -11436, + -7885, + 30817, + -17079, + -35450, + 62095, + -3851, + -90559, + 89975, + 48183, + -171853, + 88433, + 157121, + -260821, + 20927, + 328208, + -316703, + -150346, + 541055, + -277946, + -448423, + 739485, + -73337, + -861511, + 829507, + 356290, + -1324438, + 690454, + 1028390, + -1709161, + 201791, + 1887680, + -1831939, + -716159, + 2783500, + -1482343, + -2054621, + 3466419, + -474300, + -3673700, + 3613000, + 1287224, + -5279087, + 2882352, + 3736941, + -6431708, + 1000349, + 6595076, + -6598890, + -2141233, + 9346873, + -5247043, + -6390420, + 11270172, + -1965410, + -11268338, + 11516462, + 3399142, + -15949945, + 9238288, + 10621976, + -19302182, + 3742537, + 19019442, + -19972825, + -5362418, + 27419642, + -16498955, + -18065438, + 34172601, + -7365323, + -33943002, + 37132187, + 9142827, + -52306134, + 33390901, + 35736195, + -72672757, + 17941294, + 79417355, + -96390112, + -23449957, + 170363797, + -137212969, + -191469069, + 765597024, + 1331539245, + 493596668, + -274921210, + -32942669, + 159643419, + -78495662, + -56073888, + 92566917, + -20339604, + -57233801, + 55310665, + 7639287, + -50445217, + 29082154, + 21616368, + -39792810, + 9918387, + 26900649, + -27707506, + -3361496, + 26362776, + -15992880, + -11433315, + 22146651, + -5952510, + -15062499, + 16047522, + 1623967, + -15216454, + 9537068, + 6453779, + -12995040, + 3707945, + 8695767, + -9495825, + -764725, + 8832474, + -5677425, + -3610881, + 7523365, + -2258719, + -4899717, + 5458512, + 327709, + -4935994, + 3238773, + 1926235, + -4142017, + 1299360, + 2604264, + -2948992, + -117924, + 2572704, + -1715801, + -949418, + 2101742, + -684219, + -1264688, + 1449542, + 29809, + -1208615, + 814876, + 416741, + -946028, + 316939, + 537928, + -619953, + -1227, + 486498, + -328620, + -153627, + 354573, + -120584, + -185874, + 212392, + -3246, + -151553, + 100407, + 41808, + -95572, + 31847, + 42895, + -46284, + 1350, + 26106, + -15272, + -12622, + -5971, + 31003, + -20719, + -32053, + 64609, + -11596, + -86960, + 98022, + 35480, + -171554, + 105900, + 140859, + -269900, + 50897, + 313585, + -343183, + -107933, + 538068, + -329758, + -399495, + 762584, + -154838, + -820106, + 895206, + 248769, + -1313310, + 812596, + 910877, + -1757597, + 384857, + 1791180, + -1970059, + -484460, + 2753156, + -1731958, + -1809457, + 3555799, + -837523, + -3475445, + 3872978, + 839259, + -5209528, + 3345404, + 3272060, + -6582613, + 1662638, + 6221305, + -7052919, + -1336273, + 9204087, + -6052863, + -5562528, + 11510780, + -3110731, + -10600637, + 12275821, + 2011632, + -15675910, + 10597772, + 9190549, + -19678551, + 5689824, + 17847226, + -21240236, + -2971034, + 26905472, + -18834307, + -15538383, + 34792905, + -10830327, + -31787779, + 39426620, + 4656594, + -51291458, + 37983791, + 30584625, + -74018062, + 25695626, + 74417424, + -102544817, + -10712282, + 168072584, + -157209245, + -166050154, + 818123847, + 1319849527, + 439148107, + -282966954, + -12458066, + 153433421, + -87205756, + -46653964, + 92747749, + -27440403, + -52636028, + 57782511, + 2255933, + -48738185, + 32339633, + 17908419, + -39924406, + 13156740, + 24714908, + -28929778, + -606637, + 25450233, + -17728227, + -9395799, + 22195469, + -7765112, + -13801744, + 16725252, + 33049, + -14664181, + 10532178, + 5253596, + -13001720, + 4762875, + 7942137, + -9875298, + 166292, + 8493959, + -6245279, + -2908415, + 7512535, + -2860440, + -4459027, + 5663210, + -199124, + -4735699, + 3548587, + 1533428, + -4127205, + 1624106, + 2360805, + -3051883, + 161145, + 2461995, + -1872380, + -746057, + 2089338, + -844870, + -1141607, + 1496067, + -104030, + -1153339, + 885560, + 322765, + -937989, + 386874, + 483299, + -637927, + 54179, + 462736, + -355536, + -117045, + 350458, + -145545, + -166081, + 217740, + -21302, + -143542, + 108043, + 31241, + -94028, + 37970, + 38030, + -47152, + 4852, + 24515, + -16250, + -13734, + -3940, + 30911, + -24262, + -28288, + 66596, + -19391, + -82516, + 105334, + 22247, + -169722, + 122692, + 123106, + -276711, + 80823, + 295989, + -366958, + -64041, + 530282, + -379252, + -346482, + 779194, + -235841, + -771024, + 953665, + 137987, + -1290480, + 928723, + 784239, + -1790968, + 566153, + 1678046, + -2091989, + -246554, + 2698299, + -1968323, + -1546411, + 3614553, + -1196150, + -3245091, + 4100780, + 380632, + -5093607, + 3782296, + 2775122, + -6676629, + 2314824, + 5790264, + -7447928, + -514224, + 8979391, + -6810686, + -4680353, + 11651688, + -4236016, + -9835449, + 12932045, + 597622, + -15262277, + 11872709, + 7669158, + -19884284, + 7599678, + 16510395, + -22329243, + -537448, + 26151148, + -21020336, + -12856522, + 35111718, + -14226524, + -29335723, + 41393135, + 90130, + -49815758, + 42287715, + 25108323, + -74726654, + 33324282, + 68686881, + -107898122, + 2379962, + 164231075, + -176493486, + -137776527, + 869417772, + 1304359027, + 385278398, + -288238731, + 7520879, + 146037089, + -94995288, + -36978487, + 92118889, + -34214167, + -47631231, + 59725031, + -3095417, + -46621301, + 35287137, + 14074238, + -39706425, + 16255940, + 22329200, + -29890753, + 2134529, + 24321535, + -19297173, + -7289536, + 22050044, + -9498240, + -12428420, + 17252537, + -1548106, + -13987244, + 11428967, + 4015087, + -12894729, + 5769464, + 7123917, + -10166018, + 1089816, + 8083421, + -6754800, + -2185212, + 7436118, + -3433059, + -3982405, + 5816979, + -720484, + -4495450, + 3825126, + 1130123, + -4076429, + 1932176, + 2098601, + -3127284, + 436560, + 2330672, + -2011285, + -537904, + 2058778, + -996712, + -1009658, + 1529083, + -235695, + -1088514, + 947802, + 226918, + -921831, + 452681, + 425041, + -650118, + 108471, + 435210, + -379009, + -79903, + 343329, + -168892, + -145114, + 221102, + -38894, + -134401, + 114603, + 20586, + -91687, + 43638, + 32934, + -47583, + 8221, + 22750, + -17050, + -14758, + -1807, + 30533, + -27675, + -24180, + 68026, + -27167, + -77250, + 111835, + 8594, + -166348, + 138650, + 103998, + -281160, + 110440, + 275538, + -387782, + -19043, + 517709, + -425964, + -289808, + 789097, + -315623, + -714620, + 1004294, + 24889, + -1256038, + 1037751, + 649512, + -1808842, + 744063, + 1549134, + -2196515, + -4487, + 2619214, + -2189248, + -1267660, + 3641923, + -1546984, + -2984426, + 4294161, + -84694, + -4932010, + 4188995, + 2250279, + -6712536, + 2951096, + 5305360, + -7780048, + 317792, + 8674226, + -7513531, + -3751304, + 11691014, + -5331241, + -8978881, + 13478705, + -830622, + -14711795, + 13051350, + 6070604, + -19916477, + 9455067, + 15019625, + -23229093, + 1917235, + 25161656, + -23036786, + -10042309, + 35124009, + -17523553, + -26606011, + 43011734, + -4517173, + -47887703, + 46262040, + 19351821, + -74784837, + 40758863, + 62264991, + -112389689, + 15720651, + 158832319, + -194880144, + -106707744, + 919223564, + 1285149077, + 332231469, + -290814832, + 26845364, + 137543794, + -101815095, + -27134547, + 90696985, + -40606365, + -42267349, + 61126820, + -8368561, + -44116666, + 37901643, + 10148250, + -39143480, + 19190006, + 19765784, + -30583889, + 4838174, + 22987994, + -20687125, + -5133368, + 21712906, + -11137266, + -10955241, + 17625722, + -3105745, + -13192345, + 12220218, + 2749317, + -12675724, + 6719221, + 6248675, + -10366017, + 1997820, + 7604921, + -7201919, + -1447735, + 7295221, + -3971766, + -3474266, + 5918829, + -1231853, + -4217635, + 4066215, + 719926, + -3990405, + 2221003, + 1820091, + -3174754, + 705944, + 2180053, + -2131448, + -326821, + 2010485, + -1138495, + -870078, + 1548427, + -364055, + -1014798, + 1001141, + 130059, + -897781, + 513827, + 363703, + -656486, + 161185, + 404204, + -398877, + -42534, + 333289, + -190443, + -123171, + 222478, + -55876, + -124228, + 120046, + 9940, + -88584, + 48807, + 27658, + -47583, + 11430, + 20834, + -17670, + -15682, + 410, + 29865, + -30922, + -19760, + 68874, + -34854, + -71194, + 117452, + -5365, + -161440, + 153618, + 83686, + -283176, + 139478, + 252375, + -405435, + 26676, + 500403, + -469446, + -229933, + 792132, + -393465, + -651317, + 1046566, + -89546, + -1210176, + 1138651, + 507809, + -1810922, + 916986, + 1405445, + -2282566, + 239639, + 2516398, + -2392660, + -975538, + 3637425, + -1886874, + -2695518, + 4451163, + -552669, + -4725834, + 4561705, + 1701957, + -6689616, + 3565743, + 4770499, + -8045934, + 1152520, + 8290749, + -8154856, + -2783252, + 11627761, + -6386578, + -8037887, + 13910297, + -2260628, + -14028438, + 14122718, + 4408451, + -19773731, + 11239329, + 13387012, + -23930623, + 4371582, + 23944078, + -24864749, + -7119521, + 34827402, + -20691691, + -23620407, + 44265303, + -9125226, + -45520001, + 49868610, + 13362571, + -74184419, + 47931762, + 55197564, + -115965548, + 29199427, + 151881990, + -212184493, + -72921358, + 967291564, + 1262320384, + 280243128, + -290788352, + 45375824, + 128049883, + -107625016, + -17209302, + 88505227, + -46566409, + -36594881, + 61981264, + -13518416, + -41249546, + 40163213, + 6165398, + -38243155, + 21934589, + 17048309, + -31005025, + 7480958, + 21462633, + -21887134, + -2946452, + 21188236, + -12668475, + -9395711, + 17842522, + -4626404, + -12287174, + 12899681, + 1467522, + -12347328, + 7604206, + 5324424, + -10474128, + 2882469, + 7063086, + -7583137, + -702527, + 7091514, + -4472082, + -2939270, + 5968234, + -1728828, + -3904953, + 4270003, + 306476, + -3870149, + 2488208, + 1527839, + -3194097, + 966986, + 2011613, + -2231976, + -114680, + 1945038, + -1269068, + -724156, + 1554054, + -488017, + -932924, + 1045198, + 33047, + -866130, + 569826, + 299858, + -657040, + 211878, + 370033, + -415010, + -5268, + 320463, + -210031, + -100461, + 221884, + -72106, + -113129, + 124344, + -604, + -84761, + 53443, + 22251, + -47162, + 14456, + 18786, + -18109, + -16492, + 2694, + 28906, + -33969, + -15060, + 69120, + -42380, + -64389, + 122118, + -19508, + -155015, + 167446, + 62333, + -282705, + 167672, + 226671, + -419718, + 72719, + 478462, + -509277, + -167354, + 788196, + -468658, + -581603, + 1080022, + -204321, + -1153189, + 1230453, + 360318, + -1797047, + 1083352, + 1248117, + -2349226, + 483689, + 2390565, + -2576624, + -672515, + 3600852, + -2212741, + -2380702, + 4570133, + -1019189, + -4476573, + 4896902, + 1134819, + -6607664, + 4153207, + 4190051, + -8242803, + 1982630, + 7831820, + -8728617, + -1784464, + 11461825, + -7392489, + -7020206, + 14222295, + -3679832, + -13217370, + 15076710, + 2696905, + -19456178, + 12936315, + 11625982, + -24426351, + 6804019, + 22507553, + -26486840, + -4113059, + 34222212, + -23702116, + -20403090, + 45139783, + -13693576, + -42729324, + 53072103, + 7190565, + -72922842, + 54776762, + 47536661, + -118578649, + 42702525, + 143398632, + -228223924, + -36512698, + 1013379215, + 1235992398, + 229539732, + -288266323, + 62982720, + 117657768, + -112394061, + -7289245, + 85573067, + -52048040, + -30666427, + 62286548, + -18501394, + -38048128, + 42055145, + 2160840, + -37015908, + 24467170, + 14201592, + -31152401, + 10040236, + 19760061, + -22887981, + -748085, + 20481831, + -14079181, + -7764006, + 17902036, + -6097031, + -11280338, + 13462124, + 181006, + -11913106, + 8417096, + 4359559, + -10490001, + 3736179, + 6463068, + -7895557, + 43845, + 6827199, + -4929894, + -2382283, + 5965128, + -2207165, + -3560391, + 4434981, + -106588, + -3716971, + 2731618, + 1224507, + -3185369, + 1217472, + 1826972, + -2312152, + 96653, + 1863157, + -1387388, + -573226, + 1546043, + -606538, + -843687, + 1079679, + -63269, + -827236, + 620244, + 234091, + -651841, + 260128, + 333033, + -427313, + 31569, + 305002, + -227514, + -77194, + 219355, + -87455, + -101217, + 127478, + -10954, + -80265, + 57515, + 16766, + -46334, + 17274, + 16630, + -18371, + -17177, + 5024, + 27656, + -36784, + -10118, + 68750, + -49674, + -56882, + 125775, + -33713, + -147108, + 179996, + 40115, + -279717, + 194760, + 198622, + -430462, + 118682, + 452025, + -545061, + -102593, + 777250, + -540508, + -506029, + 1104277, + -318424, + -1085473, + 1312263, + 208289, + -1767196, + 1241634, + 1078422, + -2395743, + 725509, + 2242635, + -2739363, + -361176, + 3532276, + -2521606, + -2042557, + 4649741, + -1480134, + -4186114, + 5191368, + 553730, + -6466994, + 4708132, + 3568817, + -8368463, + 2800787, + 7300984, + -9229326, + -763527, + 11194009, + -8339809, + -5934301, + 14411194, + -5075684, + -12284912, + 15904190, + 950702, + -18965485, + 14530542, + 9751172, + -24710555, + 9193020, + 20863199, + -27887360, + -1048737, + 33311466, + -26527171, + -16980466, + 45624319, + -18181767, + -39536198, + 55840366, + 887931, + -71003276, + 61229621, + 39340238, + -120189381, + 56113642, + 133413809, + -242819263, + 2405475, + 1057252545, + 1206302562, + 180336922, + -283368769, + 79547253, + 106474991, + -116100512, + 2540507, + 81935883, + -57009668, + -24536213, + 62045620, + -23275766, + -34543246, + 43564089, + -1830363, + -35474962, + 26767245, + 11251398, + -31026655, + 12494242, + 17896335, + -23682246, + 1442458, + 19601034, + -15357835, + -6074839, + 17804737, + -7505089, + -10181276, + 13903371, + -1098956, + -11377524, + 9151245, + 3362774, + -10414089, + 4551687, + 5810494, + -8136903, + 784848, + 6504999, + -5341489, + -1808325, + 5909906, + -2662814, + -3187190, + 4559989, + -515655, + -3532459, + 2949286, + 912835, + -3148866, + 1455294, + 1627879, + -2371445, + 305338, + 1765703, + -1492527, + -418655, + 1524590, + -718633, + -747939, + 1104377, + -158050, + -781513, + 664697, + 167001, + -640999, + 305541, + 293564, + -435724, + 67659, + 287075, + -242764, + -53581, + 214941, + -101800, + -88610, + 129440, + -21023, + -75148, + 60998, + 11252, + -45116, + 19866, + 14389, + -18458, + -17726, + 7380, + 26119, + -39335, + -4972, + 67754, + -56666, + -48727, + 128373, + -47853, + -137765, + 191135, + 17217, + -274205, + 220485, + 168445, + -437527, + 164155, + 421273, + -576435, + -36199, + 759313, + -608343, + -425203, + 1119024, + -430840, + -1007525, + 1383262, + 53022, + -1721487, + 1390364, + 897749, + -2421534, + 962947, + 2073734, + -2879270, + -44200, + 3432055, + -2810617, + -1683887, + 4688996, + -1931403, + -3856719, + 5442224, + -36293, + -6268440, + 5225409, + 2911992, + -8421331, + 3599712, + 6702441, + -9652103, + 270719, + 10826013, + -9219830, + -4789288, + 14474551, + -6435759, + -11238495, + 16597076, + -815029, + -18304852, + 16007328, + 7778318, + -24779333, + 11517293, + 19024041, + -29052442, + 2046937, + 32100892, + -29140611, + -13380949, + 45711381, + -22549685, + -35964865, + 58144725, + -5491500, + -68434652, + 67228652, + 30671738, + -120766021, + 69314846, + 121972161, + -255796065, + 43703427, + 1098687605, + 1173405461, + 132838439, + -276227676, + 94961984, + 94613268, + -118731939, + 12196904, + 77634602, + -61414673, + -18259609, + 61266122, + -27802003, + -30768094, + 44680133, + -5773544, + -33636167, + 28816488, + 8224210, + -30630803, + 14822282, + 15888809, + -24264362, + 3606099, + 18554664, + -16494111, + -4343333, + 17552470, + -8838672, + -9000174, + 14220328, + -2361220, + -10745906, + 9800736, + 2342987, + -10247650, + 5322114, + 5111414, + -8305534, + 1514038, + 6128120, + -5703584, + -1222535, + 5803416, + -3091951, + -2788822, + 4644226, + -917177, + -3318463, + 3139507, + 595614, + -3085128, + 1678475, + 1416194, + -2409512, + 509570, + 1653663, + -1583683, + -261829, + 1490008, + -823380, + -646583, + 1119173, + -250484, + -729434, + 702861, + 99188, + -624674, + 347752, + 251999, + -440218, + 102695, + 266873, + -255680, + -29835, + 208710, + -115031, + -75429, + 130234, + -30727, + -69469, + 63874, + 5759, + -43528, + 22214, + 12085, + -18375, + -18128, + 9741, + 24302, + -41592, + 335, + 66128, + -63286, + -39986, + 129870, + -61802, + -127048, + 200743, + -6167, + -266180, + 244602, + 136383, + -440805, + 208730, + 386429, + -603069, + 31256, + 734468, + -671522, + -339785, + 1124037, + -540558, + -919933, + 1442721, + -104141, + -1660183, + 1528144, + 707600, + -2426197, + 1193873, + 1885180, + -2994930, + 275662, + 3300826, + -3077076, + -1307699, + 4687253, + -2368950, + -3491011, + 5646949, + -630115, + -6013352, + 5700228, + 2225118, + -8400458, + 4372245, + 6041015, + -9992721, + 1309260, + 10360432, + -10024382, + -3594864, + 14411012, + -7747870, + -10086595, + 17148419, + -2584885, + -17478995, + 17352929, + 5724119, + -24630648, + 13755974, + 17004900, + -29970192, + 5146988, + 30598892, + -31517846, + -9634735, + 45396861, + -26757916, + -32043099, + 59960274, + -11892639, + -65231657, + 72715282, + 21599631, + -120285141, + 82187510, + 109131363, + -266985911, + 87235026, + 1137471853, + 1137471853, + 87235026, + -266985911, + 109131363, + 82187510, + -120285141, + 21599631, + 72715282, + -65231657, + -11892639, + 59960274, + -32043099, + -26757916, + 45396861, + -9634735, + -31517846, + 30598892, + 5146988, + -29970192, + 17004900, + 13755974, + -24630648, + 5724119, + 17352929, + -17478995, + -2584885, + 17148419, + -10086595, + -7747870, + 14411012, + -3594864, + -10024382, + 10360432, + 1309260, + -9992721, + 6041015, + 4372245, + -8400458, + 2225118, + 5700228, + -6013352, + -630115, + 5646949, + -3491011, + -2368950, + 4687253, + -1307699, + -3077076, + 3300826, + 275662, + -2994930, + 1885180, + 1193873, + -2426197, + 707600, + 1528144, + -1660183, + -104141, + 1442721, + -919933, + -540558, + 1124037, + -339785, + -671522, + 734468, + 31256, + -603069, + 386429, + 208730, + -440805, + 136383, + 244602, + -266180, + -6167, + 200743, + -127048, + -61802, + 129870, + -39986, + -63286, + 66128, + 335, + -41592, + 24302, + 9741, + -18128, + -18375, + 12085, + 22214, + -43528, + 5759, + 63874, + -69469, + -30727, + 130234, + -75429, + -115031, + 208710, + -29835, + -255680, + 266873, + 102695, + -440218, + 251999, + 347752, + -624674, + 99188, + 702861, + -729434, + -250484, + 1119173, + -646583, + -823380, + 1490008, + -261829, + -1583683, + 1653663, + 509570, + -2409512, + 1416194, + 1678475, + -3085128, + 595614, + 3139507, + -3318463, + -917177, + 4644226, + -2788822, + -3091951, + 5803416, + -1222535, + -5703584, + 6128120, + 1514038, + -8305534, + 5111414, + 5322114, + -10247650, + 2342987, + 9800736, + -10745906, + -2361220, + 14220328, + -9000174, + -8838672, + 17552470, + -4343333, + -16494111, + 18554664, + 3606099, + -24264362, + 15888809, + 14822282, + -30630803, + 8224210, + 28816488, + -33636167, + -5773544, + 44680133, + -30768094, + -27802003, + 61266122, + -18259609, + -61414673, + 77634602, + 12196904, + -118731939, + 94613268, + 94961984, + -276227676, + 132838439, + 1173405461, + 1098687605, + 43703427, + -255796065, + 121972161, + 69314846, + -120766021, + 30671738, + 67228652, + -68434652, + -5491500, + 58144725, + -35964865, + -22549685, + 45711381, + -13380949, + -29140611, + 32100892, + 2046937, + -29052442, + 19024041, + 11517293, + -24779333, + 7778318, + 16007328, + -18304852, + -815029, + 16597076, + -11238495, + -6435759, + 14474551, + -4789288, + -9219830, + 10826013, + 270719, + -9652103, + 6702441, + 3599712, + -8421331, + 2911992, + 5225409, + -6268440, + -36293, + 5442224, + -3856719, + -1931403, + 4688996, + -1683887, + -2810617, + 3432055, + -44200, + -2879270, + 2073734, + 962947, + -2421534, + 897749, + 1390364, + -1721487, + 53022, + 1383262, + -1007525, + -430840, + 1119024, + -425203, + -608343, + 759313, + -36199, + -576435, + 421273, + 164155, + -437527, + 168445, + 220485, + -274205, + 17217, + 191135, + -137765, + -47853, + 128373, + -48727, + -56666, + 67754, + -4972, + -39335, + 26119, + 7380, + -17726, + -18458, + 14389, + 19866, + -45116, + 11252, + 60998, + -75148, + -21023, + 129440, + -88610, + -101800, + 214941, + -53581, + -242764, + 287075, + 67659, + -435724, + 293564, + 305541, + -640999, + 167001, + 664697, + -781513, + -158050, + 1104377, + -747939, + -718633, + 1524590, + -418655, + -1492527, + 1765703, + 305338, + -2371445, + 1627879, + 1455294, + -3148866, + 912835, + 2949286, + -3532459, + -515655, + 4559989, + -3187190, + -2662814, + 5909906, + -1808325, + -5341489, + 6504999, + 784848, + -8136903, + 5810494, + 4551687, + -10414089, + 3362774, + 9151245, + -11377524, + -1098956, + 13903371, + -10181276, + -7505089, + 17804737, + -6074839, + -15357835, + 19601034, + 1442458, + -23682246, + 17896335, + 12494242, + -31026655, + 11251398, + 26767245, + -35474962, + -1830363, + 43564089, + -34543246, + -23275766, + 62045620, + -24536213, + -57009668, + 81935883, + 2540507, + -116100512, + 106474991, + 79547253, + -283368769, + 180336922, + 1206302562, + 1057252545, + 2405475, + -242819263, + 133413809, + 56113642, + -120189381, + 39340238, + 61229621, + -71003276, + 887931, + 55840366, + -39536198, + -18181767, + 45624319, + -16980466, + -26527171, + 33311466, + -1048737, + -27887360, + 20863199, + 9193020, + -24710555, + 9751172, + 14530542, + -18965485, + 950702, + 15904190, + -12284912, + -5075684, + 14411194, + -5934301, + -8339809, + 11194009, + -763527, + -9229326, + 7300984, + 2800787, + -8368463, + 3568817, + 4708132, + -6466994, + 553730, + 5191368, + -4186114, + -1480134, + 4649741, + -2042557, + -2521606, + 3532276, + -361176, + -2739363, + 2242635, + 725509, + -2395743, + 1078422, + 1241634, + -1767196, + 208289, + 1312263, + -1085473, + -318424, + 1104277, + -506029, + -540508, + 777250, + -102593, + -545061, + 452025, + 118682, + -430462, + 198622, + 194760, + -279717, + 40115, + 179996, + -147108, + -33713, + 125775, + -56882, + -49674, + 68750, + -10118, + -36784, + 27656, + 5024, + -17177, + -18371, + 16630, + 17274, + -46334, + 16766, + 57515, + -80265, + -10954, + 127478, + -101217, + -87455, + 219355, + -77194, + -227514, + 305002, + 31569, + -427313, + 333033, + 260128, + -651841, + 234091, + 620244, + -827236, + -63269, + 1079679, + -843687, + -606538, + 1546043, + -573226, + -1387388, + 1863157, + 96653, + -2312152, + 1826972, + 1217472, + -3185369, + 1224507, + 2731618, + -3716971, + -106588, + 4434981, + -3560391, + -2207165, + 5965128, + -2382283, + -4929894, + 6827199, + 43845, + -7895557, + 6463068, + 3736179, + -10490001, + 4359559, + 8417096, + -11913106, + 181006, + 13462124, + -11280338, + -6097031, + 17902036, + -7764006, + -14079181, + 20481831, + -748085, + -22887981, + 19760061, + 10040236, + -31152401, + 14201592, + 24467170, + -37015908, + 2160840, + 42055145, + -38048128, + -18501394, + 62286548, + -30666427, + -52048040, + 85573067, + -7289245, + -112394061, + 117657768, + 62982720, + -288266323, + 229539732, + 1235992398, + 1013379215, + -36512698, + -228223924, + 143398632, + 42702525, + -118578649, + 47536661, + 54776762, + -72922842, + 7190565, + 53072103, + -42729324, + -13693576, + 45139783, + -20403090, + -23702116, + 34222212, + -4113059, + -26486840, + 22507553, + 6804019, + -24426351, + 11625982, + 12936315, + -19456178, + 2696905, + 15076710, + -13217370, + -3679832, + 14222295, + -7020206, + -7392489, + 11461825, + -1784464, + -8728617, + 7831820, + 1982630, + -8242803, + 4190051, + 4153207, + -6607664, + 1134819, + 4896902, + -4476573, + -1019189, + 4570133, + -2380702, + -2212741, + 3600852, + -672515, + -2576624, + 2390565, + 483689, + -2349226, + 1248117, + 1083352, + -1797047, + 360318, + 1230453, + -1153189, + -204321, + 1080022, + -581603, + -468658, + 788196, + -167354, + -509277, + 478462, + 72719, + -419718, + 226671, + 167672, + -282705, + 62333, + 167446, + -155015, + -19508, + 122118, + -64389, + -42380, + 69120, + -15060, + -33969, + 28906, + 2694, + -16492, + -18109, + 18786, + 14456, + -47162, + 22251, + 53443, + -84761, + -604, + 124344, + -113129, + -72106, + 221884, + -100461, + -210031, + 320463, + -5268, + -415010, + 370033, + 211878, + -657040, + 299858, + 569826, + -866130, + 33047, + 1045198, + -932924, + -488017, + 1554054, + -724156, + -1269068, + 1945038, + -114680, + -2231976, + 2011613, + 966986, + -3194097, + 1527839, + 2488208, + -3870149, + 306476, + 4270003, + -3904953, + -1728828, + 5968234, + -2939270, + -4472082, + 7091514, + -702527, + -7583137, + 7063086, + 2882469, + -10474128, + 5324424, + 7604206, + -12347328, + 1467522, + 12899681, + -12287174, + -4626404, + 17842522, + -9395711, + -12668475, + 21188236, + -2946452, + -21887134, + 21462633, + 7480958, + -31005025, + 17048309, + 21934589, + -38243155, + 6165398, + 40163213, + -41249546, + -13518416, + 61981264, + -36594881, + -46566409, + 88505227, + -17209302, + -107625016, + 128049883, + 45375824, + -290788352, + 280243128, + 1262320384, + 967291564, + -72921358, + -212184493, + 151881990, + 29199427, + -115965548, + 55197564, + 47931762, + -74184419, + 13362571, + 49868610, + -45520001, + -9125226, + 44265303, + -23620407, + -20691691, + 34827402, + -7119521, + -24864749, + 23944078, + 4371582, + -23930623, + 13387012, + 11239329, + -19773731, + 4408451, + 14122718, + -14028438, + -2260628, + 13910297, + -8037887, + -6386578, + 11627761, + -2783252, + -8154856, + 8290749, + 1152520, + -8045934, + 4770499, + 3565743, + -6689616, + 1701957, + 4561705, + -4725834, + -552669, + 4451163, + -2695518, + -1886874, + 3637425, + -975538, + -2392660, + 2516398, + 239639, + -2282566, + 1405445, + 916986, + -1810922, + 507809, + 1138651, + -1210176, + -89546, + 1046566, + -651317, + -393465, + 792132, + -229933, + -469446, + 500403, + 26676, + -405435, + 252375, + 139478, + -283176, + 83686, + 153618, + -161440, + -5365, + 117452, + -71194, + -34854, + 68874, + -19760, + -30922, + 29865, + 410, + -15682, + -17670, + 20834, + 11430, + -47583, + 27658, + 48807, + -88584, + 9940, + 120046, + -124228, + -55876, + 222478, + -123171, + -190443, + 333289, + -42534, + -398877, + 404204, + 161185, + -656486, + 363703, + 513827, + -897781, + 130059, + 1001141, + -1014798, + -364055, + 1548427, + -870078, + -1138495, + 2010485, + -326821, + -2131448, + 2180053, + 705944, + -3174754, + 1820091, + 2221003, + -3990405, + 719926, + 4066215, + -4217635, + -1231853, + 5918829, + -3474266, + -3971766, + 7295221, + -1447735, + -7201919, + 7604921, + 1997820, + -10366017, + 6248675, + 6719221, + -12675724, + 2749317, + 12220218, + -13192345, + -3105745, + 17625722, + -10955241, + -11137266, + 21712906, + -5133368, + -20687125, + 22987994, + 4838174, + -30583889, + 19765784, + 19190006, + -39143480, + 10148250, + 37901643, + -44116666, + -8368561, + 61126820, + -42267349, + -40606365, + 90696985, + -27134547, + -101815095, + 137543794, + 26845364, + -290814832, + 332231469, + 1285149077, + 919223564, + -106707744, + -194880144, + 158832319, + 15720651, + -112389689, + 62264991, + 40758863, + -74784837, + 19351821, + 46262040, + -47887703, + -4517173, + 43011734, + -26606011, + -17523553, + 35124009, + -10042309, + -23036786, + 25161656, + 1917235, + -23229093, + 15019625, + 9455067, + -19916477, + 6070604, + 13051350, + -14711795, + -830622, + 13478705, + -8978881, + -5331241, + 11691014, + -3751304, + -7513531, + 8674226, + 317792, + -7780048, + 5305360, + 2951096, + -6712536, + 2250279, + 4188995, + -4932010, + -84694, + 4294161, + -2984426, + -1546984, + 3641923, + -1267660, + -2189248, + 2619214, + -4487, + -2196515, + 1549134, + 744063, + -1808842, + 649512, + 1037751, + -1256038, + 24889, + 1004294, + -714620, + -315623, + 789097, + -289808, + -425964, + 517709, + -19043, + -387782, + 275538, + 110440, + -281160, + 103998, + 138650, + -166348, + 8594, + 111835, + -77250, + -27167, + 68026, + -24180, + -27675, + 30533, + -1807, + -14758, + -17050, + 22750, + 8221, + -47583, + 32934, + 43638, + -91687, + 20586, + 114603, + -134401, + -38894, + 221102, + -145114, + -168892, + 343329, + -79903, + -379009, + 435210, + 108471, + -650118, + 425041, + 452681, + -921831, + 226918, + 947802, + -1088514, + -235695, + 1529083, + -1009658, + -996712, + 2058778, + -537904, + -2011285, + 2330672, + 436560, + -3127284, + 2098601, + 1932176, + -4076429, + 1130123, + 3825126, + -4495450, + -720484, + 5816979, + -3982405, + -3433059, + 7436118, + -2185212, + -6754800, + 8083421, + 1089816, + -10166018, + 7123917, + 5769464, + -12894729, + 4015087, + 11428967, + -13987244, + -1548106, + 17252537, + -12428420, + -9498240, + 22050044, + -7289536, + -19297173, + 24321535, + 2134529, + -29890753, + 22329200, + 16255940, + -39706425, + 14074238, + 35287137, + -46621301, + -3095417, + 59725031, + -47631231, + -34214167, + 92118889, + -36978487, + -94995288, + 146037089, + 7520879, + -288238731, + 385278398, + 1304359027, + 869417772, + -137776527, + -176493486, + 164231075, + 2379962, + -107898122, + 68686881, + 33324282, + -74726654, + 25108323, + 42287715, + -49815758, + 90130, + 41393135, + -29335723, + -14226524, + 35111718, + -12856522, + -21020336, + 26151148, + -537448, + -22329243, + 16510395, + 7599678, + -19884284, + 7669158, + 11872709, + -15262277, + 597622, + 12932045, + -9835449, + -4236016, + 11651688, + -4680353, + -6810686, + 8979391, + -514224, + -7447928, + 5790264, + 2314824, + -6676629, + 2775122, + 3782296, + -5093607, + 380632, + 4100780, + -3245091, + -1196150, + 3614553, + -1546411, + -1968323, + 2698299, + -246554, + -2091989, + 1678046, + 566153, + -1790968, + 784239, + 928723, + -1290480, + 137987, + 953665, + -771024, + -235841, + 779194, + -346482, + -379252, + 530282, + -64041, + -366958, + 295989, + 80823, + -276711, + 123106, + 122692, + -169722, + 22247, + 105334, + -82516, + -19391, + 66596, + -28288, + -24262, + 30911, + -3940, + -13734, + -16250, + 24515, + 4852, + -47152, + 38030, + 37970, + -94028, + 31241, + 108043, + -143542, + -21302, + 217740, + -166081, + -145545, + 350458, + -117045, + -355536, + 462736, + 54179, + -637927, + 483299, + 386874, + -937989, + 322765, + 885560, + -1153339, + -104030, + 1496067, + -1141607, + -844870, + 2089338, + -746057, + -1872380, + 2461995, + 161145, + -3051883, + 2360805, + 1624106, + -4127205, + 1533428, + 3548587, + -4735699, + -199124, + 5663210, + -4459027, + -2860440, + 7512535, + -2908415, + -6245279, + 8493959, + 166292, + -9875298, + 7942137, + 4762875, + -13001720, + 5253596, + 10532178, + -14664181, + 33049, + 16725252, + -13801744, + -7765112, + 22195469, + -9395799, + -17728227, + 25450233, + -606637, + -28929778, + 24714908, + 13156740, + -39924406, + 17908419, + 32339633, + -48738185, + 2255933, + 57782511, + -52636028, + -27440403, + 92747749, + -46653964, + -87205756, + 153433421, + -12458066, + -282966954, + 439148107, + 1319849527, + 818123847, + -166050154, + -157209245, + 168072584, + -10712282, + -102544817, + 74417424, + 25695626, + -74018062, + 30584625, + 37983791, + -51291458, + 4656594, + 39426620, + -31787779, + -10830327, + 34792905, + -15538383, + -18834307, + 26905472, + -2971034, + -21240236, + 17847226, + 5689824, + -19678551, + 9190549, + 10597772, + -15675910, + 2011632, + 12275821, + -10600637, + -3110731, + 11510780, + -5562528, + -6052863, + 9204087, + -1336273, + -7052919, + 6221305, + 1662638, + -6582613, + 3272060, + 3345404, + -5209528, + 839259, + 3872978, + -3475445, + -837523, + 3555799, + -1809457, + -1731958, + 2753156, + -484460, + -1970059, + 1791180, + 384857, + -1757597, + 910877, + 812596, + -1313310, + 248769, + 895206, + -820106, + -154838, + 762584, + -399495, + -329758, + 538068, + -107933, + -343183, + 313585, + 50897, + -269900, + 140859, + 105900, + -171554, + 35480, + 98022, + -86960, + -11596, + 64609, + -32053, + -20719, + 31003, + -5971, + -12622, + -15272, + 26106, + 1350, + -46284, + 42895, + 31847, + -95572, + 41808, + 100407, + -151553, + -3246, + 212392, + -185874, + -120584, + 354573, + -153627, + -328620, + 486498, + -1227, + -619953, + 537928, + 316939, + -946028, + 416741, + 814876, + -1208615, + 29809, + 1449542, + -1264688, + -684219, + 2101742, + -949418, + -1715801, + 2572704, + -117924, + -2948992, + 2604264, + 1299360, + -4142017, + 1926235, + 3238773, + -4935994, + 327709, + 5458512, + -4899717, + -2258719, + 7523365, + -3610881, + -5677425, + 8832474, + -764725, + -9495825, + 8695767, + 3707945, + -12995040, + 6453779, + 9537068, + -15216454, + 1623967, + 16047522, + -15062499, + -5952510, + 22146651, + -11433315, + -15992880, + 26362776, + -3361496, + -27707506, + 26900649, + 9918387, + -39792810, + 21616368, + 29082154, + -50445217, + 7639287, + 55310665, + -57233801, + -20339604, + 92566917, + -56073888, + -78495662, + 159643419, + -32942669, + -274921210, + 493596668, + 1331539245, + 765597024, + -191469069, + -137212969, + 170363797, + -23449957, + -96390112, + 79417355, + 17941294, + -72672757, + 35736195, + 33390901, + -52306134, + 9142827, + 37132187, + -33943002, + -7365323, + 34172601, + -18065438, + -16498955, + 27419642, + -5362418, + -19972825, + 19019442, + 3742537, + -19302182, + 10621976, + 9238288, + -15949945, + 3399142, + 11516462, + -11268338, + -1965410, + 11270172, + -6390420, + -5247043, + 9346873, + -2141233, + -6598890, + 6595076, + 1000349, + -6431708, + 3736941, + 2882352, + -5279087, + 1287224, + 3613000, + -3673700, + -474300, + 3466419, + -2054621, + -1482343, + 2783500, + -716159, + -1831939, + 1887680, + 201791, + -1709161, + 1028390, + 690454, + -1324438, + 356290, + 829507, + -861511, + -73337, + 739485, + -448423, + -277946, + 541055, + -150346, + -316703, + 328208, + 20927, + -260821, + 157121, + 88433, + -171853, + 48183, + 89975, + -90559, + -3851, + 62095, + -35450, + -17079, + 30817, + -7885, + -11436, + -14118, + 27504, + -2255, + -44977, + 47480, + 25312, + -96289, + 52192, + 91745, + -158344, + 15118, + 205076, + -204299, + -94210, + 355598, + -189317, + -298460, + 506238, + -57271, + -596292, + 588404, + 243450, + -945792, + 507997, + 736291, + -1253760, + 164659, + 1389793, + -1377734, + -516101, + 2095721, + -1146152, + -1542782, + 2661652, + -398213, + -2819301, + 2826685, + 960672, + -4120463, + 2305007, + 2898170, + -5094282, + 855412, + 5204329, + -5300343, + -1632992, + 7468066, + -4286288, + -5055847, + 9095513, + -1695092, + -9030363, + 9377761, + 2613645, + -12874024, + 7604834, + 8451765, + -15638415, + 3210720, + 15224346, + -16198877, + -4075858, + 21902755, + -13383719, + -14105274, + 27049674, + -6105933, + -26232817, + 28865756, + 6568279, + -39310048, + 25164488, + 25540635, + -51723682, + 13007718, + 52325635, + -61379616, + -12969821, + 91566522, + -65151977, + -68922922, + 164585550, + -53775776, + -264038792, + 548373439, + 1339366730, + 712096564, + -213991817, + -116689736, + 171123956, + -35731956, + -89500103, + 83654198, + 10129894, + -70709756, + 40521779, + 28551783, + -52855193, + 13510476, + 34532519, + -35784949, + -3862242, + 33258425, + -20416742, + -14035696, + 27690801, + -7691002, + -18539251, + 20017875, + 1775069, + -18759554, + 11951503, + 7806670, + -16082867, + 4748193, + 10661253, + -11833331, + -810194, + 10932604, + -7157138, + -4400580, + 9407035, + -2922179, + -6090205, + 6908693, + 333817, + -6225626, + 4165922, + 2397374, + -5302006, + 1720688, + 3323357, + -3838360, + -109692, + 3347430, + -2279898, + -1221768, + 2789266, + -939675, + -1678973, + 1966847, + 18572, + -1646219, + 1135834, + 563421, + -1323881, + 459639, + 757215, + -894956, + 7944, + 710169, + -492883, + -224298, + 539274, + -190927, + -287785, + 339769, + -8823, + -249585, + 171771, + 70456, + -170641, + 60253, + 81280, + -93296, + 3777, + 59086, + -38457, + -13378, + 30362, + -9669, + -10190, + -12795, + 28691, + -5933, + -43233, + 51737, + 18419, + -96157, + 62295, + 82118, + -163834, + 33632, + 195829, + -221171, + -66637, + 353483, + -223786, + -265281, + 521733, + -113462, + -567087, + 634234, + 167020, + -937196, + 595698, + 650421, + -1288276, + 299338, + 1317225, + -1479656, + -341931, + 2071168, + -1334466, + -1354711, + 2727876, + -677262, + -2663740, + 3025944, + 610919, + -4062458, + 2666300, + 2529553, + -5208866, + 1379345, + 4902552, + -5657102, + -988605, + 7346677, + -4928511, + -4385660, + 9280264, + -2616619, + -8482450, + 9981659, + 1489350, + -12639007, + 8696327, + 7285240, + -15925525, + 4779329, + 14262034, + -17200090, + -2151240, + 21464654, + -15229293, + -12080980, + 27503352, + -8815757, + -24516872, + 30591345, + 3135002, + -38477601, + 28520305, + 21743724, + -52558445, + 18313973, + 48848215, + -65031967, + -5392173, + 89743643, + -73803497, + -58553882, + 168186946, + -74792831, + -250273260, + 603222507, + 1343290801, + 657884189, + -233595023, + -95822895, + 170384176, + -47462915, + -81946010, + 87102438, + 2329649, + -68153175, + 44903713, + 23510885, + -52938119, + 17722550, + 31652765, + -37300028, + -351913, + 32060499, + -22573029, + -11466914, + 27718234, + -9936875, + -16953123, + 20834933, + -195267, + -18056468, + 13168161, + 6315884, + -16074405, + 6047239, + 9718276, + -12291329, + 344757, + 10501644, + -7856375, + -3521138, + 9384587, + -3672441, + -5531673, + 7159819, + -331102, + -5966547, + 4555503, + 1894866, + -5278420, + 2135964, + 3006802, + -3968238, + 253101, + 3200103, + -2483474, + -952600, + 2770604, + -1153120, + -1512626, + 2028137, + -163194, + -1569452, + 1232360, + 432656, + -1311754, + 557953, + 679031, + -920230, + 88294, + 674961, + -532536, + -169304, + 532796, + -229342, + -256713, + 348205, + -38094, + -236320, + 184703, + 52133, + -167953, + 71594, + 72022, + -95162, + 11220, + 55620, + -41056, + -9652, + 29648, + -11309, + -8897 + +}; + +static const struct src_stage src_int32_21_32_4535_5000 = { + 3, 2, 21, 172, 3612, 32, 21, 0, 0, + src_int32_21_32_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_40_2381_5000.h b/src/audio/src/coef/src_ipc4_int32_21_40_2381_5000.h new file mode 100644 index 000000000000..c465a9ce6b14 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_40_2381_5000.h @@ -0,0 +1,942 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_40_2381_5000_fir[924] = { + 139084, + 174433, + -727541, + -1717301, + 357848, + 5255859, + 4720994, + -7195373, + -17215053, + -2212272, + 30820070, + 32700242, + -24779215, + -78974513, + -28896729, + 106682518, + 144261947, + -50493092, + -301201980, + -198499640, + 450419395, + 1289756653, + 1664140154, + 1255426635, + 410328862, + -216221134, + -294028244, + -37147679, + 147616094, + 100672599, + -34136673, + -78166380, + -21258577, + 34033358, + 29493379, + -3591918, + -17169127, + -6479219, + 5013596, + 5058779, + 161151, + -1714336, + -663435, + 189200, + 149505, + 157198, + -792505, + -1712703, + 562943, + 5440511, + 4398176, + -7910213, + -17197864, + -781282, + 32072750, + 31211609, + -28303438, + -79520527, + -23423462, + 112463220, + 140312109, + -64021458, + -307530556, + -179418135, + 491010629, + 1322959366, + 1662217798, + 1220040601, + 370808353, + -232578055, + -286057214, + -24024892, + 150377837, + 94459703, + -39130650, + -77105414, + -17753942, + 35210307, + 28099566, + -4916680, + -17062275, + -5764521, + 5275975, + 4850575, + -26706, + -1704213, + -600452, + 201587, + 159786, + 137417, + -858040, + -1700154, + 775933, + 5611428, + 4045274, + -8620878, + -17115548, + 697208, + 33244611, + 29568705, + -31818494, + -79795859, + -17730654, + 117988642, + 135765248, + -77691481, + -312967321, + -158984623, + 532031270, + 1354965544, + 1658377243, + 1183671718, + 331925060, + -247569252, + -277337816, + -11162699, + 152552361, + 88070143, + -43867170, + -75801572, + -14277364, + 36231023, + 26645584, + -6183328, + -16896850, + -5053952, + 5508246, + 4632549, + -205338, + -1687350, + -538841, + 211693, + 169828, + 115020, + -923840, + -1679284, + 996261, + 5767311, + 3662549, + -9324427, + -16966286, + 2219056, + 34328965, + 27773390, + -35311342, + -79792714, + -11833207, + 123232981, + 130622034, + -91460337, + -317466989, + -137210579, + 573408212, + 1385708196, + 1652626791, + 1146394833, + 293743896, + -261196943, + -267919877, + 1402716, + 154146689, + 81530224, + -48335918, + -74265434, + -10840492, + 37096014, + 25138411, + -7388944, + -16675357, + -4350078, + 5710641, + 4405990, + -374417, + -1664178, + -478825, + 219620, + 179524, + 89950, + -989582, + -1649745, + 1223309, + 5906871, + 3250399, + -10017843, + -16748466, + 3779829, + 35319263, + 25828138, + -38768690, + -79504115, + -5747109, + 128170800, + 124885181, + -105283767, + -320985790, + -114110967, + 615066711, + 1415122749, + 1644978869, + 1108286288, + 256327352, + -273466657, + -257853976, + 13637025, + 155169620, + 74866146, + -52527756, + -72508145, + -7454540, + 37806340, + 23585034, + -8530925, + -16400436, + -3655350, + 5883503, + 4172171, + -533671, + -1635133, + -420613, + 225479, + 188765, + 62163, + -1054924, + -1611215, + 1456403, + 6028841, + 2809355, + -10698050, + -16460691, + 5374812, + 36209133, + 23736049, + -42177036, + -78923946, + 510593, + 132777116, + 118559490, + -119116186, + -323481624, + -89704239, + 656930558, + 1443147210, + 1635449993, + 1069423721, + 219735361, + -284387179, + -247191281, + 25507821, + 155631656, + 68103921, + -56434733, + -70541366, + -4130259, + 38363599, + 21992412, + -9606985, + -16074849, + -2972104, + 6027283, + 3932347, + -682883, + -1600660, + -364387, + 229388, + 197435, + 31627, + -1119507, + -1563396, + 1694810, + 6131972, + 2340087, + -11361920, + -16101796, + 6999020, + 36992403, + 21500854, + -45522719, + -78046997, + 6921829, + 137027501, + 111651879, + -132910790, + -324914202, + -64012335, + 698922260, + 1469722336, + 1624060726, + 1029885865, + 184025174, + -293970472, + -235983399, + 36984673, + 155544937, + 61269286, + -60050081, + -68377220, + -877907, + 38769906, + 20367461, + -10615153, + -15701465, + -2302549, + 6142531, + 3687745, + -821891, + -1561208, + -310313, + 231467, + 205417, + -1675, + -1182957, + -1506022, + 1937742, + 6215052, + 1843409, + -12006283, + -15670859, + 8647207, + 37663133, + 19126912, + -48791959, + -76869002, + 13467548, + 140898179, + 104171405, + -146619670, + -325245191, + -37060672, + 740963223, + 1494791786, + 1610835623, + 989752348, + 149251239, + -302231610, + -224282222, + 48039180, + 154923154, + 54387625, + -63368215, + -66028236, + 2292779, + 39027869, + 18717021, + -11553772, + -15283246, + -1648765, + 6229894, + 3439563, + -950583, + -1517224, + -258535, + 231839, + 212588, + -37746, + -1244885, + -1438859, + 2184356, + 6276901, + 1320274, + -12627941, + -15167209, + 10313882, + 38215642, + 16619215, + -51970910, + -75386678, + 20127763, + 144366121, + 96129289, + -160193936, + -324438351, + -8878115, + 782973948, + 1518302270, + 1595803165, + 949103491, + 115465094, + -309188681, + -212139772, + 58645012, + 153781477, + 47483885, + -66384726, + -63507296, + 5372598, + 39140571, + 17047835, + -12421497, + -14823230, + -1012699, + 6290106, + 3188966, + -1068899, + -1469157, + -209177, + 230632, + 218823, + -76571, + -1304888, + -1361706, + 2433758, + 6316386, + 771782, + -13223678, + -14590439, + 11993321, + 38644539, + 13983385, + -55045705, + -73597760, + 26881598, + 147409141, + 87538926, + -173583838, + -322459675, + 20503052, + 824874215, + 1540203689, + 1578995681, + 908020105, + 82715264, + -314862702, + -199608052, + 68777945, + 152136468, + 40582505, + -69096365, + -60827580, + 8352913, + 39111546, + 15366528, + -13217290, + -14324523, + -396163, + 6323984, + 2937082, + -1176827, + -1417454, + -162343, + 227974, + 223994, + -118119, + -1362553, + -1274403, + 2684999, + 6332423, + 199174, + -13790276, + -13940417, + 13679583, + 38944750, + 11225664, + -58002512, + -71501034, + 33707341, + 150005994, + 78415893, + -186738900, + -319277513, + 51047171, + 866583287, + 1560449268, + 1560449268, + 866583287, + 51047171, + -319277513, + -186738900, + 78415893, + 150005994, + 33707341, + -71501034, + -58002512, + 11225664, + 38944750, + 13679583, + -13940417, + -13790276, + 199174, + 6332423, + 2684999, + -1274403, + -1362553, + -118119, + 223994, + 227974, + -162343, + -1417454, + -1176827, + 2937082, + 6323984, + -396163, + -14324523, + -13217290, + 15366528, + 39111546, + 8352913, + -60827580, + -69096365, + 40582505, + 152136468, + 68777945, + -199608052, + -314862702, + 82715264, + 908020105, + 1578995681, + 1540203689, + 824874215, + 20503052, + -322459675, + -173583838, + 87538926, + 147409141, + 26881598, + -73597760, + -55045705, + 13983385, + 38644539, + 11993321, + -14590439, + -13223678, + 771782, + 6316386, + 2433758, + -1361706, + -1304888, + -76571, + 218823, + 230632, + -209177, + -1469157, + -1068899, + 3188966, + 6290106, + -1012699, + -14823230, + -12421497, + 17047835, + 39140571, + 5372598, + -63507296, + -66384726, + 47483885, + 153781477, + 58645012, + -212139772, + -309188681, + 115465094, + 949103491, + 1595803165, + 1518302270, + 782973948, + -8878115, + -324438351, + -160193936, + 96129289, + 144366121, + 20127763, + -75386678, + -51970910, + 16619215, + 38215642, + 10313882, + -15167209, + -12627941, + 1320274, + 6276901, + 2184356, + -1438859, + -1244885, + -37746, + 212588, + 231839, + -258535, + -1517224, + -950583, + 3439563, + 6229894, + -1648765, + -15283246, + -11553772, + 18717021, + 39027869, + 2292779, + -66028236, + -63368215, + 54387625, + 154923154, + 48039180, + -224282222, + -302231610, + 149251239, + 989752348, + 1610835623, + 1494791786, + 740963223, + -37060672, + -325245191, + -146619670, + 104171405, + 140898179, + 13467548, + -76869002, + -48791959, + 19126912, + 37663133, + 8647207, + -15670859, + -12006283, + 1843409, + 6215052, + 1937742, + -1506022, + -1182957, + -1675, + 205417, + 231467, + -310313, + -1561208, + -821891, + 3687745, + 6142531, + -2302549, + -15701465, + -10615153, + 20367461, + 38769906, + -877907, + -68377220, + -60050081, + 61269286, + 155544937, + 36984673, + -235983399, + -293970472, + 184025174, + 1029885865, + 1624060726, + 1469722336, + 698922260, + -64012335, + -324914202, + -132910790, + 111651879, + 137027501, + 6921829, + -78046997, + -45522719, + 21500854, + 36992403, + 6999020, + -16101796, + -11361920, + 2340087, + 6131972, + 1694810, + -1563396, + -1119507, + 31627, + 197435, + 229388, + -364387, + -1600660, + -682883, + 3932347, + 6027283, + -2972104, + -16074849, + -9606985, + 21992412, + 38363599, + -4130259, + -70541366, + -56434733, + 68103921, + 155631656, + 25507821, + -247191281, + -284387179, + 219735361, + 1069423721, + 1635449993, + 1443147210, + 656930558, + -89704239, + -323481624, + -119116186, + 118559490, + 132777116, + 510593, + -78923946, + -42177036, + 23736049, + 36209133, + 5374812, + -16460691, + -10698050, + 2809355, + 6028841, + 1456403, + -1611215, + -1054924, + 62163, + 188765, + 225479, + -420613, + -1635133, + -533671, + 4172171, + 5883503, + -3655350, + -16400436, + -8530925, + 23585034, + 37806340, + -7454540, + -72508145, + -52527756, + 74866146, + 155169620, + 13637025, + -257853976, + -273466657, + 256327352, + 1108286288, + 1644978869, + 1415122749, + 615066711, + -114110967, + -320985790, + -105283767, + 124885181, + 128170800, + -5747109, + -79504115, + -38768690, + 25828138, + 35319263, + 3779829, + -16748466, + -10017843, + 3250399, + 5906871, + 1223309, + -1649745, + -989582, + 89950, + 179524, + 219620, + -478825, + -1664178, + -374417, + 4405990, + 5710641, + -4350078, + -16675357, + -7388944, + 25138411, + 37096014, + -10840492, + -74265434, + -48335918, + 81530224, + 154146689, + 1402716, + -267919877, + -261196943, + 293743896, + 1146394833, + 1652626791, + 1385708196, + 573408212, + -137210579, + -317466989, + -91460337, + 130622034, + 123232981, + -11833207, + -79792714, + -35311342, + 27773390, + 34328965, + 2219056, + -16966286, + -9324427, + 3662549, + 5767311, + 996261, + -1679284, + -923840, + 115020, + 169828, + 211693, + -538841, + -1687350, + -205338, + 4632549, + 5508246, + -5053952, + -16896850, + -6183328, + 26645584, + 36231023, + -14277364, + -75801572, + -43867170, + 88070143, + 152552361, + -11162699, + -277337816, + -247569252, + 331925060, + 1183671718, + 1658377243, + 1354965544, + 532031270, + -158984623, + -312967321, + -77691481, + 135765248, + 117988642, + -17730654, + -79795859, + -31818494, + 29568705, + 33244611, + 697208, + -17115548, + -8620878, + 4045274, + 5611428, + 775933, + -1700154, + -858040, + 137417, + 159786, + 201587, + -600452, + -1704213, + -26706, + 4850575, + 5275975, + -5764521, + -17062275, + -4916680, + 28099566, + 35210307, + -17753942, + -77105414, + -39130650, + 94459703, + 150377837, + -24024892, + -286057214, + -232578055, + 370808353, + 1220040601, + 1662217798, + 1322959366, + 491010629, + -179418135, + -307530556, + -64021458, + 140312109, + 112463220, + -23423462, + -79520527, + -28303438, + 31211609, + 32072750, + -781282, + -17197864, + -7910213, + 4398176, + 5440511, + 562943, + -1712703, + -792505, + 157198, + 149505, + 189200, + -663435, + -1714336, + 161151, + 5058779, + 5013596, + -6479219, + -17169127, + -3591918, + 29493379, + 34033358, + -21258577, + -78166380, + -34136673, + 100672599, + 147616094, + -37147679, + -294028244, + -216221134, + 410328862, + 1255426635, + 1664140154, + 1289756653, + 450419395, + -198499640, + -301201980, + -50493092, + 144261947, + 106682518, + -28896729, + -78974513, + -24779215, + 32700242, + 30820070, + -2212272, + -17215053, + -7195373, + 4720994, + 5255859, + 357848, + -1717301, + -727541, + 174433, + 139084 + +}; + +static const struct src_stage src_int32_21_40_2381_5000 = { + 19, 10, 21, 44, 924, 40, 21, 0, 1, + src_int32_21_40_2381_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_40_3968_5000.h b/src/audio/src/coef/src_ipc4_int32_21_40_3968_5000.h new file mode 100644 index 000000000000..1eca6eab5318 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_40_3968_5000.h @@ -0,0 +1,1697 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_40_3968_5000_fir[1680] = { + 150367, + 421440, + -262784, + -985237, + 269854, + 1875091, + -22201, + -3129329, + -684659, + 4728358, + 2102408, + -6567493, + -4512199, + 8431940, + 8197520, + -9977109, + -13409780, + 10716300, + 20330299, + -10015556, + -29033697, + 7091526, + 39458363, + -1001584, + -51389769, + -9396715, + 64461926, + 25565435, + -78181927, + -49598376, + 91984231, + 85028715, + -105331883, + -139114767, + 117932078, + 230724308, + -130422221, + -430062761, + 148819010, + 1386618304, + 2021685208, + 1330470346, + 98857072, + -431550204, + -107131031, + 236402403, + 104162415, + -145450284, + -96677329, + 91129844, + 86565015, + -55111019, + -74954436, + 30331038, + 62745906, + -13360321, + -50698790, + 2172394, + 39429472, + 4648416, + -29394543, + -8214148, + 20881167, + 9450768, + -14011323, + -9136788, + 8760348, + 7910949, + -4986913, + -6271781, + 2469845, + 4580045, + -946646, + -3068450, + 148898, + 1859130, + 169182, + -987010, + -211306, + 425976, + 171528, + 414278, + -314731, + -978093, + 372037, + 1881626, + -197384, + -3175385, + -413537, + 4855373, + 1717198, + -6835030, + -4006287, + 8918679, + 7584144, + -10779706, + -12731490, + 11945711, + 19669128, + -11790683, + -28521729, + 9530326, + 39288950, + -4210051, + -51830798, + -5337201, + 65875058, + 20612337, + -81057270, + -43765452, + 97013873, + 78414631, + -113587002, + -131976075, + 131360263, + 223763252, + -153654148, + -426345080, + 200525492, + 1441278560, + 2018325683, + 1272995580, + 50746073, + -430872893, + -83890624, + 240796946, + 90123967, + -150964646, + -87671635, + 96695113, + 80788080, + -60280215, + -71395142, + 34887814, + 60739187, + -17209491, + -49764339, + 5296507, + 39204891, + 2213230, + -29604423, + -6395808, + 21320481, + 8155955, + -14534218, + -8263527, + 9270589, + 7358884, + -5428565, + -5949889, + 2817978, + 4411606, + -1198352, + -2993387, + 315126, + 1834066, + 70509, + -983569, + -160565, + 427966, + 192799, + 404424, + -366867, + -965447, + 475218, + 1878452, + -375823, + -3206041, + -134502, + 4960004, + 1315867, + -7072508, + -3471237, + 9368112, + 6922551, + -11539916, + -11978775, + 13132247, + 18899483, + -13530192, + -27859249, + 11952445, + 38919589, + -7437271, + -52016579, + -1201017, + 66974485, + 15494275, + -83561626, + -37637306, + 101623599, + 71313352, + -121395638, + -124056393, + 144374613, + 215525853, + -176714358, + -420338492, + 253862880, + 1494293665, + 2011616752, + 1214357780, + 4584864, + -428102784, + -60808248, + 243913265, + 75889433, + -155644096, + -78364095, + 101704546, + 74686621, + -65084783, + -67525778, + 39215730, + 58455252, + -20926490, + -48594025, + 8355819, + 38788177, + -201989, + -29664247, + -4569841, + 21647565, + 6838756, + -14976987, + -7362201, + 9726497, + 6779029, + -5835487, + -5603909, + 3145402, + 4224294, + -1438705, + -2904843, + 475738, + 1800266, + -25699, + -975093, + -110818, + 427500, + 214045, + 391826, + -418899, + -947195, + 578866, + 1865334, + -556654, + -3220789, + 151159, + 5041263, + 900184, + -7278166, + -2909294, + 9777328, + 6215359, + -12253225, + -11154371, + 14269276, + 18023772, + -15224801, + -27047635, + 14345439, + 38349624, + -10667218, + -51943035, + 2991980, + 67750832, + 10234883, + -85677775, + -31240790, + 105784748, + 63753409, + -128712237, + -115382063, + 156903461, + 206024836, + -199488415, + -411991470, + 308710617, + 1545510172, + 2001578616, + 1154723033, + -39535521, + -423317950, + -37987959, + 245762473, + 61531173, + -159479099, + -68804752, + 106141151, + 68294989, + -69505604, + -63369339, + 43296123, + 55908795, + -24494452, + -47196540, + 11335901, + 38183804, + -2585453, + -29575662, + -2745472, + 21862319, + 5506079, + -15338576, + -6437759, + 10126633, + 6174758, + -6206217, + -5236020, + 3450844, + 4019434, + -1666714, + -2803571, + 630038, + 1758130, + -119003, + -961785, + -62306, + 424684, + 235124, + 376448, + -470529, + -923262, + 682432, + 1842083, + -738976, + -3219196, + 442097, + 5098265, + 472025, + -7450374, + -2322879, + 10143573, + 5465458, + -12915287, + -10261419, + 15350326, + 17044972, + -16865332, + -26089040, + 16696853, + 37579406, + -13883650, + -51607346, + 7221405, + 68196233, + 4858796, + -87390220, + -24604437, + 109470507, + 55765995, + -135492984, + -105983530, + 168876171, + 195279098, + -221860321, + -401259915, + 364941592, + 1594779173, + 1988241483, + 1094259154, + -81532102, + -416602185, + -15530263, + 246361315, + 47120885, + -162464327, + -59044145, + 109990966, + 61648512, + -73525687, + -58949955, + 47111788, + 53115638, + -27897455, + -45581602, + 14222893, + 37397125, + -4925680, + -29341039, + -931792, + 21965205, + 4164813, + -15618355, + -5495187, + 10469859, + 5549510, + -6539502, + -4848474, + 3733167, + 3798417, + -1881473, + -2690377, + 777379, + 1708096, + -208990, + -943870, + -15255, + 419629, + 255892, + 358269, + -521446, + -893604, + 785355, + 1808560, + -921862, + -3200905, + 736907, + 5130233, + 33364, + -7587650, + -1714580, + 10464273, + 4676003, + -13521957, + -9303456, + 16369117, + 15966628, + -18442759, + -24986390, + 18994284, + 36610302, + -17070197, + -51007975, + 11466442, + 68304383, + -608461, + -88685288, + -17758344, + 112656063, + 47384858, + -141696037, + -95895257, + 180223488, + 183313736, + -243712967, + -388107433, + 422422522, + 1641956825, + 1971645464, + 1033135110, + -121330157, + -408044613, + 6468236, + 245731993, + 32729279, + -164598616, + -49133062, + 113243082, + 54783311, + -77130232, + -54292756, + 50647034, + 50092632, + -31120591, + -43759892, + 17003569, + 36434337, + -7211550, + -28963446, + 862279, + 21957240, + 2821795, + -15816115, + -4539492, + 10755344, + 4906777, + -6834300, + -4443583, + 3991375, + 3562688, + -2082163, + -2566110, + 917165, + 1650630, + -295279, + -921588, + 30125, + 412459, + 276196, + 337284, + -571338, + -858206, + 887057, + 1764681, + -1104361, + -3165638, + 1034135, + 5136506, + -413731, + -7688663, + -1087145, + 10737042, + 3850403, + -14069307, + -8284403, + 17319601, + 14792838, + -19948256, + -23743379, + 21225443, + 35444700, + -20210435, + -50144697, + 15705939, + 68070595, + -6140596, + -89551218, + -10734039, + 115318757, + 38646163, + -147281763, + -85155625, + 190877881, + 170160052, + -264928581, + -372505574, + 481014364, + 1686904866, + 1951840421, + 971520434, + -158863400, + -397739267, + 27915154, + 243901963, + 18425772, + -165884915, + -39122292, + 115889661, + 47736111, + -80306669, + -49423742, + 53887753, + 46857569, + -34150025, + -41742991, + 19665398, + 35302438, + -9432356, + -28446631, + 2628040, + 21839986, + 1483774, + -15932065, + -3575668, + 10982560, + 4250083, + -7089781, + -4023705, + 4224612, + 3313741, + -2268054, + -2431658, + 1048856, + 1586227, + -377518, + -895201, + 73640, + 403304, + 295885, + 313504, + -619886, + -817086, + 986956, + 1710412, + -1285498, + -3113204, + 1332283, + 5116546, + -867111, + -7752248, + -443463, + 10959705, + 2992301, + -14553656, + -7208548, + 18195991, + 13528243, + -21373246, + -22364460, + 23378221, + 34086009, + -23287972, + -49018611, + 19918518, + 67491839, + -11710663, + -89978246, + -3564347, + 117438220, + 29588353, + -152212957, + -73806811, + 200773895, + 155855538, + -285389187, + -354434050, + 540572749, + 1729491098, + 1928885796, + 909584643, + -194074119, + -385784655, + 48722638, + 240903723, + 4278179, + -166330204, + -29062378, + 117925924, + 40544053, + -83044697, + -44369637, + 56821465, + 43429076, + -36973050, + -39543310, + 22196593, + 34009186, + -11577853, + -27794987, + 4357047, + 21615530, + 157378, + -15966820, + -2608677, + 11151283, + 3582964, + -7305331, + -3591234, + 4432167, + 3053105, + -2438510, + -2287942, + 1171964, + 1515406, + -455387, + -864980, + 115114, + 392303, + 314802, + 286962, + -666767, + -770294, + 1084460, + 1645778, + -1464285, + -3043497, + 1629818, + 5069939, + -1324554, + -7777414, + 213442, + 11130309, + 2105569, + -14971590, + -6080533, + 18992794, + 12178006, + -22709444, + -20854832, + 25440750, + 32538659, + -26286527, + -47632153, + 24082671, + 66566780, + -17291196, + -89958679, + 3716761, + 118996505, + 20251988, + -156455065, + -61894647, + 209848483, + 140443826, + -304977080, + -333880915, + 600948442, + 1769589865, + 1902850390, + 847496658, + -226913285, + -372283320, + 68807641, + 236774576, + -9647568, + -165945406, + -19003383, + 119350146, + 33244513, + -85336304, + -39157750, + 59437363, + 39826516, + -39578141, + -37174022, + 24586164, + 32563044, + -13638301, + -27013525, + 6041152, + 21286471, + -1150916, + -15921397, + -1643422, + 11261590, + 2908952, + -7480548, + -3148585, + 4613473, + 2782344, + -2592985, + -2135912, + 1286061, + 1438707, + -528598, + -831214, + 154388, + 379601, + 332789, + 257703, + -711660, + -717915, + 1178978, + 1570859, + -1639724, + -2956500, + 1925179, + 4996405, + -1783777, + -7763350, + 880426, + 11247137, + 1194283, + -15319982, + -4905333, + 19704850, + 10747797, + -23948910, + -19220425, + 27401469, + 30808086, + -29190021, + -45989099, + 28176874, + 65295803, + -22854334, + -89486955, + 11074317, + 119978208, + 10679581, + -159976383, + -49468459, + 218041344, + 123974614, + -323575294, + -310842726, + 661987823, + 1807082496, + 1873812119, + 785424232, + -257340626, + -357341382, + 88092178, + 231556374, + -23287705, + -164745272, + -8994653, + 120163611, + 25874909, + -87175776, + -33815839, + 61726343, + 36069882, + -41954994, + -34648981, + 26823962, + 30973135, + -15604509, + -26107843, + 7672543, + 20855894, + -2434814, + -15797202, + -684723, + 11313850, + 2231556, + -7615243, + -2698182, + 4768109, + 2503038, + -2731030, + -1976539, + 1390775, + 1356687, + -596898, + -794200, + 191322, + 365345, + 349689, + 225795, + -754244, + -660065, + 1269916, + 1485793, + -1810810, + -2852289, + 2216784, + 4895798, + -2242445, + -7709436, + 1554243, + 11308720, + 262707, + -15596016, + -3688234, + 20327355, + 9243772, + -25084085, + -17467877, + 29249185, + 28900719, + -31982651, + -44094565, + 32179691, + 63681032, + -28371961, + -88559701, + 18472523, + 120370577, + 915414, + -162748259, + -36580891, + 225295253, + 106503564, + -341068080, + -285324664, + 723533380, + 1841857730, + 1841857730, + 723533380, + -285324664, + -341068080, + 106503564, + 225295253, + -36580891, + -162748259, + 915414, + 120370577, + 18472523, + -88559701, + -28371961, + 63681032, + 32179691, + -44094565, + -31982651, + 28900719, + 29249185, + -17467877, + -25084085, + 9243772, + 20327355, + -3688234, + -15596016, + 262707, + 11308720, + 1554243, + -7709436, + -2242445, + 4895798, + 2216784, + -2852289, + -1810810, + 1485793, + 1269916, + -660065, + -754244, + 225795, + 349689, + 365345, + 191322, + -794200, + -596898, + 1356687, + 1390775, + -1976539, + -2731030, + 2503038, + 4768109, + -2698182, + -7615243, + 2231556, + 11313850, + -684723, + -15797202, + -2434814, + 20855894, + 7672543, + -26107843, + -15604509, + 30973135, + 26823962, + -34648981, + -41954994, + 36069882, + 61726343, + -33815839, + -87175776, + 25874909, + 120163611, + -8994653, + -164745272, + -23287705, + 231556374, + 88092178, + -357341382, + -257340626, + 785424232, + 1873812119, + 1807082496, + 661987823, + -310842726, + -323575294, + 123974614, + 218041344, + -49468459, + -159976383, + 10679581, + 119978208, + 11074317, + -89486955, + -22854334, + 65295803, + 28176874, + -45989099, + -29190021, + 30808086, + 27401469, + -19220425, + -23948910, + 10747797, + 19704850, + -4905333, + -15319982, + 1194283, + 11247137, + 880426, + -7763350, + -1783777, + 4996405, + 1925179, + -2956500, + -1639724, + 1570859, + 1178978, + -717915, + -711660, + 257703, + 332789, + 379601, + 154388, + -831214, + -528598, + 1438707, + 1286061, + -2135912, + -2592985, + 2782344, + 4613473, + -3148585, + -7480548, + 2908952, + 11261590, + -1643422, + -15921397, + -1150916, + 21286471, + 6041152, + -27013525, + -13638301, + 32563044, + 24586164, + -37174022, + -39578141, + 39826516, + 59437363, + -39157750, + -85336304, + 33244513, + 119350146, + -19003383, + -165945406, + -9647568, + 236774576, + 68807641, + -372283320, + -226913285, + 847496658, + 1902850390, + 1769589865, + 600948442, + -333880915, + -304977080, + 140443826, + 209848483, + -61894647, + -156455065, + 20251988, + 118996505, + 3716761, + -89958679, + -17291196, + 66566780, + 24082671, + -47632153, + -26286527, + 32538659, + 25440750, + -20854832, + -22709444, + 12178006, + 18992794, + -6080533, + -14971590, + 2105569, + 11130309, + 213442, + -7777414, + -1324554, + 5069939, + 1629818, + -3043497, + -1464285, + 1645778, + 1084460, + -770294, + -666767, + 286962, + 314802, + 392303, + 115114, + -864980, + -455387, + 1515406, + 1171964, + -2287942, + -2438510, + 3053105, + 4432167, + -3591234, + -7305331, + 3582964, + 11151283, + -2608677, + -15966820, + 157378, + 21615530, + 4357047, + -27794987, + -11577853, + 34009186, + 22196593, + -39543310, + -36973050, + 43429076, + 56821465, + -44369637, + -83044697, + 40544053, + 117925924, + -29062378, + -166330204, + 4278179, + 240903723, + 48722638, + -385784655, + -194074119, + 909584643, + 1928885796, + 1729491098, + 540572749, + -354434050, + -285389187, + 155855538, + 200773895, + -73806811, + -152212957, + 29588353, + 117438220, + -3564347, + -89978246, + -11710663, + 67491839, + 19918518, + -49018611, + -23287972, + 34086009, + 23378221, + -22364460, + -21373246, + 13528243, + 18195991, + -7208548, + -14553656, + 2992301, + 10959705, + -443463, + -7752248, + -867111, + 5116546, + 1332283, + -3113204, + -1285498, + 1710412, + 986956, + -817086, + -619886, + 313504, + 295885, + 403304, + 73640, + -895201, + -377518, + 1586227, + 1048856, + -2431658, + -2268054, + 3313741, + 4224612, + -4023705, + -7089781, + 4250083, + 10982560, + -3575668, + -15932065, + 1483774, + 21839986, + 2628040, + -28446631, + -9432356, + 35302438, + 19665398, + -41742991, + -34150025, + 46857569, + 53887753, + -49423742, + -80306669, + 47736111, + 115889661, + -39122292, + -165884915, + 18425772, + 243901963, + 27915154, + -397739267, + -158863400, + 971520434, + 1951840421, + 1686904866, + 481014364, + -372505574, + -264928581, + 170160052, + 190877881, + -85155625, + -147281763, + 38646163, + 115318757, + -10734039, + -89551218, + -6140596, + 68070595, + 15705939, + -50144697, + -20210435, + 35444700, + 21225443, + -23743379, + -19948256, + 14792838, + 17319601, + -8284403, + -14069307, + 3850403, + 10737042, + -1087145, + -7688663, + -413731, + 5136506, + 1034135, + -3165638, + -1104361, + 1764681, + 887057, + -858206, + -571338, + 337284, + 276196, + 412459, + 30125, + -921588, + -295279, + 1650630, + 917165, + -2566110, + -2082163, + 3562688, + 3991375, + -4443583, + -6834300, + 4906777, + 10755344, + -4539492, + -15816115, + 2821795, + 21957240, + 862279, + -28963446, + -7211550, + 36434337, + 17003569, + -43759892, + -31120591, + 50092632, + 50647034, + -54292756, + -77130232, + 54783311, + 113243082, + -49133062, + -164598616, + 32729279, + 245731993, + 6468236, + -408044613, + -121330157, + 1033135110, + 1971645464, + 1641956825, + 422422522, + -388107433, + -243712967, + 183313736, + 180223488, + -95895257, + -141696037, + 47384858, + 112656063, + -17758344, + -88685288, + -608461, + 68304383, + 11466442, + -51007975, + -17070197, + 36610302, + 18994284, + -24986390, + -18442759, + 15966628, + 16369117, + -9303456, + -13521957, + 4676003, + 10464273, + -1714580, + -7587650, + 33364, + 5130233, + 736907, + -3200905, + -921862, + 1808560, + 785355, + -893604, + -521446, + 358269, + 255892, + 419629, + -15255, + -943870, + -208990, + 1708096, + 777379, + -2690377, + -1881473, + 3798417, + 3733167, + -4848474, + -6539502, + 5549510, + 10469859, + -5495187, + -15618355, + 4164813, + 21965205, + -931792, + -29341039, + -4925680, + 37397125, + 14222893, + -45581602, + -27897455, + 53115638, + 47111788, + -58949955, + -73525687, + 61648512, + 109990966, + -59044145, + -162464327, + 47120885, + 246361315, + -15530263, + -416602185, + -81532102, + 1094259154, + 1988241483, + 1594779173, + 364941592, + -401259915, + -221860321, + 195279098, + 168876171, + -105983530, + -135492984, + 55765995, + 109470507, + -24604437, + -87390220, + 4858796, + 68196233, + 7221405, + -51607346, + -13883650, + 37579406, + 16696853, + -26089040, + -16865332, + 17044972, + 15350326, + -10261419, + -12915287, + 5465458, + 10143573, + -2322879, + -7450374, + 472025, + 5098265, + 442097, + -3219196, + -738976, + 1842083, + 682432, + -923262, + -470529, + 376448, + 235124, + 424684, + -62306, + -961785, + -119003, + 1758130, + 630038, + -2803571, + -1666714, + 4019434, + 3450844, + -5236020, + -6206217, + 6174758, + 10126633, + -6437759, + -15338576, + 5506079, + 21862319, + -2745472, + -29575662, + -2585453, + 38183804, + 11335901, + -47196540, + -24494452, + 55908795, + 43296123, + -63369339, + -69505604, + 68294989, + 106141151, + -68804752, + -159479099, + 61531173, + 245762473, + -37987959, + -423317950, + -39535521, + 1154723033, + 2001578616, + 1545510172, + 308710617, + -411991470, + -199488415, + 206024836, + 156903461, + -115382063, + -128712237, + 63753409, + 105784748, + -31240790, + -85677775, + 10234883, + 67750832, + 2991980, + -51943035, + -10667218, + 38349624, + 14345439, + -27047635, + -15224801, + 18023772, + 14269276, + -11154371, + -12253225, + 6215359, + 9777328, + -2909294, + -7278166, + 900184, + 5041263, + 151159, + -3220789, + -556654, + 1865334, + 578866, + -947195, + -418899, + 391826, + 214045, + 427500, + -110818, + -975093, + -25699, + 1800266, + 475738, + -2904843, + -1438705, + 4224294, + 3145402, + -5603909, + -5835487, + 6779029, + 9726497, + -7362201, + -14976987, + 6838756, + 21647565, + -4569841, + -29664247, + -201989, + 38788177, + 8355819, + -48594025, + -20926490, + 58455252, + 39215730, + -67525778, + -65084783, + 74686621, + 101704546, + -78364095, + -155644096, + 75889433, + 243913265, + -60808248, + -428102784, + 4584864, + 1214357780, + 2011616752, + 1494293665, + 253862880, + -420338492, + -176714358, + 215525853, + 144374613, + -124056393, + -121395638, + 71313352, + 101623599, + -37637306, + -83561626, + 15494275, + 66974485, + -1201017, + -52016579, + -7437271, + 38919589, + 11952445, + -27859249, + -13530192, + 18899483, + 13132247, + -11978775, + -11539916, + 6922551, + 9368112, + -3471237, + -7072508, + 1315867, + 4960004, + -134502, + -3206041, + -375823, + 1878452, + 475218, + -965447, + -366867, + 404424, + 192799, + 427966, + -160565, + -983569, + 70509, + 1834066, + 315126, + -2993387, + -1198352, + 4411606, + 2817978, + -5949889, + -5428565, + 7358884, + 9270589, + -8263527, + -14534218, + 8155955, + 21320481, + -6395808, + -29604423, + 2213230, + 39204891, + 5296507, + -49764339, + -17209491, + 60739187, + 34887814, + -71395142, + -60280215, + 80788080, + 96695113, + -87671635, + -150964646, + 90123967, + 240796946, + -83890624, + -430872893, + 50746073, + 1272995580, + 2018325683, + 1441278560, + 200525492, + -426345080, + -153654148, + 223763252, + 131360263, + -131976075, + -113587002, + 78414631, + 97013873, + -43765452, + -81057270, + 20612337, + 65875058, + -5337201, + -51830798, + -4210051, + 39288950, + 9530326, + -28521729, + -11790683, + 19669128, + 11945711, + -12731490, + -10779706, + 7584144, + 8918679, + -4006287, + -6835030, + 1717198, + 4855373, + -413537, + -3175385, + -197384, + 1881626, + 372037, + -978093, + -314731, + 414278, + 171528, + 425976, + -211306, + -987010, + 169182, + 1859130, + 148898, + -3068450, + -946646, + 4580045, + 2469845, + -6271781, + -4986913, + 7910949, + 8760348, + -9136788, + -14011323, + 9450768, + 20881167, + -8214148, + -29394543, + 4648416, + 39429472, + 2172394, + -50698790, + -13360321, + 62745906, + 30331038, + -74954436, + -55111019, + 86565015, + 91129844, + -96677329, + -145450284, + 104162415, + 236402403, + -107131031, + -431550204, + 98857072, + 1330470346, + 2021685208, + 1386618304, + 148819010, + -430062761, + -130422221, + 230724308, + 117932078, + -139114767, + -105331883, + 85028715, + 91984231, + -49598376, + -78181927, + 25565435, + 64461926, + -9396715, + -51389769, + -1001584, + 39458363, + 7091526, + -29033697, + -10015556, + 20330299, + 10716300, + -13409780, + -9977109, + 8197520, + 8431940, + -4512199, + -6567493, + 2102408, + 4728358, + -684659, + -3129329, + -22201, + 1875091, + 269854, + -985237, + -262784, + 421440, + 150367 + +}; + +static const struct src_stage src_int32_21_40_3968_5000 = { + 19, 10, 21, 80, 1680, 40, 21, 0, 1, + src_int32_21_40_3968_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_4_1080_5000.h b/src/audio/src/coef/src_ipc4_int32_21_4_1080_5000.h new file mode 100644 index 000000000000..e3c84132ecb0 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_4_1080_5000.h @@ -0,0 +1,354 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_4_1080_5000_fir[336] = { + 139978, + 2034094, + -10158575, + -2399407, + 65594367, + -78054609, + -164440347, + 635857299, + 1305291035, + 584017504, + -177848472, + -65165570, + 64543834, + -4899588, + -9196886, + 2056906, + 194398, + 1973196, + -11102078, + 347717, + 66058300, + -91059009, + -148504262, + 687525321, + 1301368330, + 532268865, + -188785365, + -52502258, + 62956238, + -7145752, + -8230080, + 2045970, + 258932, + 1869983, + -12013318, + 3331278, + 65888919, + -104060399, + -129999025, + 738754459, + 1293546362, + 480868341, + -197322348, + -40166495, + 60883275, + -9134101, + -7270145, + 2005649, + 333769, + 1720406, + -12877318, + 6537205, + 65043010, + -116933050, + -108899818, + 789275256, + 1281871830, + 430065213, + -203544304, + -28251109, + 58378150, + -10863927, + -6327919, + 1940271, + 418887, + 1520682, + -13678319, + 9947778, + 63481531, + -129544607, + -85198922, + 838817800, + 1266414334, + 380099460, + -207548558, + -16839591, + 55494944, + -12337408, + -5413053, + 1854066, + 514026, + 1267384, + -14399925, + 13541561, + 61170288, + -141756926, + -58906321, + 887113634, + 1247265837, + 331200228, + -209443693, + -6005851, + 52288013, + -13559374, + -4533985, + 1751106, + 618667, + 957528, + -15025258, + 17293393, + 58080592, + -153426984, + -30050169, + 933897681, + 1224539954, + 283584423, + -209348313, + 4185933, + 48811416, + -14537074, + -3697934, + 1635268, + 732005, + 588663, + -15537146, + 21174409, + 54189893, + -164407882, + 1322871, + 978910163, + 1198371081, + 237455411, + -207389749, + 13681370, + 45118377, + -15279913, + -2910908, + 1510186, + 852936, + 158966, + -15918314, + 25152116, + 49482397, + -174549918, + 35147445, + 1021898501, + 1168913364, + 193001855, + -203702750, + 22435811, + 41260791, + -15799196, + -2177732, + 1379219, + 980039, + -332670, + -16151602, + 29190504, + 43949636, + -183701725, + 71339467, + 1062619174, + 1136339523, + 150396688, + -198428139, + 30414228, + 37288766, + -16107857, + -1502085, + 1245430, + 1111565, + -886548, + -16220194, + 33250217, + 37591002, + -191711478, + 109796233, + 1100839530, + 1100839530, + 109796233, + -191711478, + 37591002, + 33250217, + -16220194, + -886548, + 1111565, + 1245430, + -1502085, + -16107857, + 37288766, + 30414228, + -198428139, + 150396688, + 1136339523, + 1062619174, + 71339467, + -183701725, + 43949636, + 29190504, + -16151602, + -332670, + 980039, + 1379219, + -2177732, + -15799196, + 41260791, + 22435811, + -203702750, + 193001855, + 1168913364, + 1021898501, + 35147445, + -174549918, + 49482397, + 25152116, + -15918314, + 158966, + 852936, + 1510186, + -2910908, + -15279913, + 45118377, + 13681370, + -207389749, + 237455411, + 1198371081, + 978910163, + 1322871, + -164407882, + 54189893, + 21174409, + -15537146, + 588663, + 732005, + 1635268, + -3697934, + -14537074, + 48811416, + 4185933, + -209348313, + 283584423, + 1224539954, + 933897681, + -30050169, + -153426984, + 58080592, + 17293393, + -15025258, + 957528, + 618667, + 1751106, + -4533985, + -13559374, + 52288013, + -6005851, + -209443693, + 331200228, + 1247265837, + 887113634, + -58906321, + -141756926, + 61170288, + 13541561, + -14399925, + 1267384, + 514026, + 1854066, + -5413053, + -12337408, + 55494944, + -16839591, + -207548558, + 380099460, + 1266414334, + 838817800, + -85198922, + -129544607, + 63481531, + 9947778, + -13678319, + 1520682, + 418887, + 1940271, + -6327919, + -10863927, + 58378150, + -28251109, + -203544304, + 430065213, + 1281871830, + 789275256, + -108899818, + -116933050, + 65043010, + 6537205, + -12877318, + 1720406, + 333769, + 2005649, + -7270145, + -9134101, + 60883275, + -40166495, + -197322348, + 480868341, + 1293546362, + 738754459, + -129999025, + -104060399, + 65888919, + 3331278, + -12013318, + 1869983, + 258932, + 2045970, + -8230080, + -7145752, + 62956238, + -52502258, + -188785365, + 532268865, + 1301368330, + 687525321, + -148504262, + -91059009, + 66058300, + 347717, + -11102078, + 1973196, + 194398, + 2056906, + -9196886, + -4899588, + 64543834, + -65165570, + -177848472, + 584017504, + 1305291035, + 635857299, + -164440347, + -78054609, + 65594367, + -2399407, + -10158575, + 2034094, + 139978 + +}; + +static const struct src_stage src_int32_21_4_1080_5000 = { + 3, 16, 21, 16, 336, 4, 21, 0, 0, + src_int32_21_4_1080_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_4_3239_5000.h b/src/audio/src/coef/src_ipc4_int32_21_4_3239_5000.h new file mode 100644 index 000000000000..c950787ac76e --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_4_3239_5000.h @@ -0,0 +1,690 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_4_3239_5000_fir[672] = { + -35812, + 307539, + -973534, + 1785434, + -1705820, + -1030516, + 7996659, + -18844984, + 29547453, + -31897444, + 15351413, + 28808586, + -102545049, + 198049966, + -299646669, + 397992769, + 1768218516, + 310062596, + -274234195, + 196203230, + -110460128, + 38809672, + 7350278, + -27285993, + 27944155, + -19084421, + 8917750, + -1889976, + -1182434, + 1565939, + -920376, + 307884, + -30766, + 300821, + -1013676, + 1989827, + -2232406, + -108640, + 6902670, + -18293206, + 30743437, + -36173520, + 23392518, + 18004793, + -92729731, + 196858929, + -321729361, + 488772325, + 1759152608, + 225636449, + -246021835, + 191466828, + -116422803, + 47883341, + -490049, + -22421835, + 25973625, + -19020519, + 9659245, + -2676511, + -670504, + 1335966, + -856151, + 302492, + -23551, + 287176, + -1038947, + 2174453, + -2753397, + 863544, + 5645657, + -17424811, + 31497053, + -40033919, + 31347918, + 6539872, + -81097487, + 192521357, + -339970050, + 581702606, + 1741105954, + 145318610, + -215550219, + 184024702, + -120411781, + 55923087, + -8055262, + -17388639, + 23680169, + -18666682, + 10217595, + -3381301, + -177638, + 1100022, + -782859, + 292051, + -14047, + 266145, + -1047635, + 2334692, + -3259588, + 1872458, + 4238654, + -16240522, + 31779043, + -43402080, + 39088925, + -5429364, + -67762598, + 184970889, + -353881073, + 676047885, + 1714247906, + 69657333, + -183363819, + 174092761, + -122435921, + 62841620, + -15239121, + -12269741, + 21111458, + -18040326, + 10592318, + -3997281, + 289294, + 862427, + -702513, + 277291, + -2184, + 237384, + -1038205, + 2466057, + -3741497, + 2903213, + 2697774, + -14746253, + 31566642, + -46206545, + 46485777, + -17732800, + -52869660, + 174186149, + -363006084, + 771042839, + 1678830083, + -860099, + -150004185, + 161914677, + -122533093, + 68571558, + -21944818, + -7146865, + 18317658, + -17162438, + 10785870, + -4519172, + 724235, + 627247, + -617099, + 258964, + 12051, + 200683, + -1009353, + 2564282, + -4189520, + 3939795, + 1042079, + -12953220, + 30844189, + -48382287, + 53409654, + -30189218, + -36592448, + 160192765, + -366926569, + 865900457, + 1635183513, + -65811519, + -116003396, + 147757455, + -120768649, + 73065800, + -28086152, + -2098902, + 15350551, + -16057105, + 10803480, + -4943476, + 1121999, + 398245, + -528543, + 237820, + 28605, + 155980, + -960042, + 2625413, + -4594091, + 4965289, + -706605, + -10877979, + 29603651, + -49871981, + 59734750, + -42608737, + -19132314, + 143064825, + -365268059, + 959820291, + 1583714878, + -124843199, + -81877801, + 131906809, + -117233539, + 76297569, + -33588493, + 2799209, + 12262656, + -14751000, + 10652938, + -5268449, + 1478311, + 178827, + -438676, + 214600, + 47359, + 103380, + -889543, + 2645907, + -4945854, + 5962116, + -2523932, + -8542366, + 27845044, + -50627197, + 65340364, + -54795478, + -716111, + 122925700, + -357705930, + 1051996963, + 1524901915, + -177672319, + -48122133, + 114662436, + -112042109, + 78260161, + -38389550, + 7477514, + 9106384, + -13272856, + 10344360, + -5494040, + 1789825, + -27987, + -349210, + 190015, + 68119, + 43162, + -797475, + 2622714, + -5235834, + 6912306, + -4383332, + -5973353, + 25576730, + -50609486, + 70112982, + -66550394, + 18406326, + 99948219, + -343970721, + 1141628801, + 1459288014, + -224088554, + -15204057, + 96333246, + -105329627, + 78966383, + -42439913, + 11871955, + 5933210, + -11652926, + 9889916, + -5621811, + 2054130, + -219600, + -261714, + 164736, + 90619, + -24209, + -683832, + 2553367, + -5455619, + 7797778, + -6256352, + -3202813, + 22815596, + -49791353, + 73948314, + -77674261, + 37965128, + 74354183, + -323852888, + 1227926532, + 1387476107, + -263954784, + 16440788, + 77232616, + -97249573, + 78447722, + -45703381, + 15925159, + 2792903, + -9922436, + 9303546, + -5654829, + 2269740, + -393847, + -177594, + 139382, + 114513, + -98078, + -549013, + 2436064, + -5597538, + 8600650, + -8113051, + -267193, + 19587096, + -48157078, + 76753252, + -87970750, + 57673740, + 46413191, + -297206924, + 1310121897, + 1310121897, + -297206924, + 46413191, + 57673740, + -87970750, + 76753252, + -48157078, + 19587096, + -267193, + -8113051, + 8600650, + -5597538, + 2436064, + -549013, + -98078, + 114513, + 139382, + -177594, + -393847, + 2269740, + -5654829, + 9303546, + -9922436, + 2792903, + 15925159, + -45703381, + 78447722, + -97249573, + 77232616, + 16440788, + -263954784, + 1387476107, + 1227926532, + -323852888, + 74354183, + 37965128, + -77674261, + 73948314, + -49791353, + 22815596, + -3202813, + -6256352, + 7797778, + -5455619, + 2553367, + -683832, + -24209, + 90619, + 164736, + -261714, + -219600, + 2054130, + -5621811, + 9889916, + -11652926, + 5933210, + 11871955, + -42439913, + 78966383, + -105329627, + 96333246, + -15204057, + -224088554, + 1459288014, + 1141628801, + -343970721, + 99948219, + 18406326, + -66550394, + 70112982, + -50609486, + 25576730, + -5973353, + -4383332, + 6912306, + -5235834, + 2622714, + -797475, + 43162, + 68119, + 190015, + -349210, + -27987, + 1789825, + -5494040, + 10344360, + -13272856, + 9106384, + 7477514, + -38389550, + 78260161, + -112042109, + 114662436, + -48122133, + -177672319, + 1524901915, + 1051996963, + -357705930, + 122925700, + -716111, + -54795478, + 65340364, + -50627197, + 27845044, + -8542366, + -2523932, + 5962116, + -4945854, + 2645907, + -889543, + 103380, + 47359, + 214600, + -438676, + 178827, + 1478311, + -5268449, + 10652938, + -14751000, + 12262656, + 2799209, + -33588493, + 76297569, + -117233539, + 131906809, + -81877801, + -124843199, + 1583714878, + 959820291, + -365268059, + 143064825, + -19132314, + -42608737, + 59734750, + -49871981, + 29603651, + -10877979, + -706605, + 4965289, + -4594091, + 2625413, + -960042, + 155980, + 28605, + 237820, + -528543, + 398245, + 1121999, + -4943476, + 10803480, + -16057105, + 15350551, + -2098902, + -28086152, + 73065800, + -120768649, + 147757455, + -116003396, + -65811519, + 1635183513, + 865900457, + -366926569, + 160192765, + -36592448, + -30189218, + 53409654, + -48382287, + 30844189, + -12953220, + 1042079, + 3939795, + -4189520, + 2564282, + -1009353, + 200683, + 12051, + 258964, + -617099, + 627247, + 724235, + -4519172, + 10785870, + -17162438, + 18317658, + -7146865, + -21944818, + 68571558, + -122533093, + 161914677, + -150004185, + -860099, + 1678830083, + 771042839, + -363006084, + 174186149, + -52869660, + -17732800, + 46485777, + -46206545, + 31566642, + -14746253, + 2697774, + 2903213, + -3741497, + 2466057, + -1038205, + 237384, + -2184, + 277291, + -702513, + 862427, + 289294, + -3997281, + 10592318, + -18040326, + 21111458, + -12269741, + -15239121, + 62841620, + -122435921, + 174092761, + -183363819, + 69657333, + 1714247906, + 676047885, + -353881073, + 184970889, + -67762598, + -5429364, + 39088925, + -43402080, + 31779043, + -16240522, + 4238654, + 1872458, + -3259588, + 2334692, + -1047635, + 266145, + -14047, + 292051, + -782859, + 1100022, + -177638, + -3381301, + 10217595, + -18666682, + 23680169, + -17388639, + -8055262, + 55923087, + -120411781, + 184024702, + -215550219, + 145318610, + 1741105954, + 581702606, + -339970050, + 192521357, + -81097487, + 6539872, + 31347918, + -40033919, + 31497053, + -17424811, + 5645657, + 863544, + -2753397, + 2174453, + -1038947, + 287176, + -23551, + 302492, + -856151, + 1335966, + -670504, + -2676511, + 9659245, + -19020519, + 25973625, + -22421835, + -490049, + 47883341, + -116422803, + 191466828, + -246021835, + 225636449, + 1759152608, + 488772325, + -321729361, + 196858929, + -92729731, + 18004793, + 23392518, + -36173520, + 30743437, + -18293206, + 6902670, + -108640, + -2232406, + 1989827, + -1013676, + 300821, + -30766, + 307884, + -920376, + 1565939, + -1182434, + -1889976, + 8917750, + -19084421, + 27944155, + -27285993, + 7350278, + 38809672, + -110460128, + 196203230, + -274234195, + 310062596, + 1768218516, + 397992769, + -299646669, + 198049966, + -102545049, + 28808586, + 15351413, + -31897444, + 29547453, + -18844984, + 7996659, + -1030516, + -1705820, + 1785434, + -973534, + 307539, + -35812 + +}; + +static const struct src_stage src_int32_21_4_3239_5000 = { + 3, 16, 21, 32, 672, 4, 21, 0, 0, + src_int32_21_4_3239_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_5_1728_5000.h b/src/audio/src/coef/src_ipc4_int32_21_5_1728_5000.h new file mode 100644 index 000000000000..2afa32a460e6 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_5_1728_5000.h @@ -0,0 +1,438 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_5_1728_5000_fir[420] = { + 99153, + 137369, + -3779111, + 9100494, + 1600955, + -43705956, + 77337928, + 1159381, + -255207445, + 594569601, + 1444182528, + 531503727, + -260824417, + 16914543, + 70191966, + -44377390, + 3935319, + 8071418, + -3726480, + 231113, + 125055, + 26110, + -3783502, + 10103107, + -922549, + -42486182, + 84021068, + -15499819, + -246399811, + 657919265, + 1439056539, + 469082410, + -263389602, + 31649579, + 62685183, + -44524963, + 6065958, + 7030594, + -3630888, + 307936, + 153724, + -103000, + -3734605, + 11063732, + -3617210, + -40698728, + 90139089, + -32931051, + -234283212, + 721182628, + 1428839406, + 407654388, + -263060606, + 45264728, + 54918192, + -44177726, + 7981657, + 5991793, + -3497751, + 368649, + 184816, + -250013, + -3627699, + 11966187, + -6461659, + -38329923, + 95590558, + -50986982, + -218761608, + 783983104, + 1413600517, + 347553804, + -260011815, + 57676787, + 46989178, + -43368722, + 9674495, + 4967727, + -3332528, + 414247, + 217872, + -414658, + -3458495, + 12793813, + -9431197, + -35372253, + 100276101, + -69505711, + -199762755, + 845940525, + 1393443211, + 289097804, + -254432332, + 68819168, + 38992951, + -42134378, + 11139744, + 3969956, + -3140643, + 445876, + 252311, + -596319, + -3223238, + 13529669, + -12497903, + -31824803, + 104099643, + -88311719, + -177239559, + 906674132, + 1368503901, + 232584323, + -246523844, + 78641787, + 31020069, + -40513897, + 12375723, + 3008825, + -2927407, + 464793, + 287435, + -794002, + -2918811, + 14156739, + -15630785, + -27693639, + 106969664, + -107216983, + -151171224, + 965805596, + 1338950903, + 178290072, + -236498438, + 87110794, + 23156049, + -38548641, + 13383629, + 2093407, + -2697948, + 472338, + 322422, + -1006320, + -2542839, + 14658170, + -18795981, + -22992125, + 108800467, + -126022261, + -121564197, + 1022962058, + 1304983011, + 126468738, + -224576375, + 94208149, + 15480683, + -36281534, + 14167343, + 1231481, + -2457153, + 469896, + 356336, + -1231473, + -2093785, + 15017507, + -21957012, + -17741177, + 109513435, + -144518532, + -88452878, + 1077779145, + 1266827806, + 77349425, + -210983863, + 99931056, + 8067439, + -33756464, + 14733203, + 429523, + -2209615, + 458875, + 388130, + -1467241, + -1571046, + 15218948, + -25075083, + -11969424, + 109038280, + -162488592, + -51900093, + 1129903950, + 1224739728, + 31135330, + -195950837, + 104291263, + 982965, + -31017717, + 15089777, + -307289, + -1959593, + 440673, + 416655, + -1710972, + -975041, + 15247607, + -28109431, + -5713299, + 107314245, + -179708780, + -11997322, + 1178997935, + 1178997935, + -11997322, + -179708780, + 107314245, + -5713299, + -28109431, + 15247607, + -975041, + -1710972, + 416655, + 440673, + -1959593, + -307289, + 15089777, + -31017717, + 982965, + 104291263, + -195950837, + 31135330, + 1224739728, + 1129903950, + -51900093, + -162488592, + 109038280, + -11969424, + -25075083, + 15218948, + -1571046, + -1467241, + 388130, + 458875, + -2209615, + 429523, + 14733203, + -33756464, + 8067439, + 99931056, + -210983863, + 77349425, + 1266827806, + 1077779145, + -88452878, + -144518532, + 109513435, + -17741177, + -21957012, + 15017507, + -2093785, + -1231473, + 356336, + 469896, + -2457153, + 1231481, + 14167343, + -36281534, + 15480683, + 94208149, + -224576375, + 126468738, + 1304983011, + 1022962058, + -121564197, + -126022261, + 108800467, + -22992125, + -18795981, + 14658170, + -2542839, + -1006320, + 322422, + 472338, + -2697948, + 2093407, + 13383629, + -38548641, + 23156049, + 87110794, + -236498438, + 178290072, + 1338950903, + 965805596, + -151171224, + -107216983, + 106969664, + -27693639, + -15630785, + 14156739, + -2918811, + -794002, + 287435, + 464793, + -2927407, + 3008825, + 12375723, + -40513897, + 31020069, + 78641787, + -246523844, + 232584323, + 1368503901, + 906674132, + -177239559, + -88311719, + 104099643, + -31824803, + -12497903, + 13529669, + -3223238, + -596319, + 252311, + 445876, + -3140643, + 3969956, + 11139744, + -42134378, + 38992951, + 68819168, + -254432332, + 289097804, + 1393443211, + 845940525, + -199762755, + -69505711, + 100276101, + -35372253, + -9431197, + 12793813, + -3458495, + -414658, + 217872, + 414247, + -3332528, + 4967727, + 9674495, + -43368722, + 46989178, + 57676787, + -260011815, + 347553804, + 1413600517, + 783983104, + -218761608, + -50986982, + 95590558, + -38329923, + -6461659, + 11966187, + -3627699, + -250013, + 184816, + 368649, + -3497751, + 5991793, + 7981657, + -44177726, + 54918192, + 45264728, + -263060606, + 407654388, + 1428839406, + 721182628, + -234283212, + -32931051, + 90139089, + -40698728, + -3617210, + 11063732, + -3734605, + -103000, + 153724, + 307936, + -3630888, + 7030594, + 6065958, + -44524963, + 62685183, + 31649579, + -263389602, + 469082410, + 1439056539, + 657919265, + -246399811, + -15499819, + 84021068, + -42486182, + -922549, + 10103107, + -3783502, + 26110, + 125055, + 231113, + -3726480, + 8071418, + 3935319, + -44377390, + 70191966, + 16914543, + -260824417, + 531503727, + 1444182528, + 594569601, + -255207445, + 1159381, + 77337928, + -43705956, + 1600955, + 9100494, + -3779111, + 137369, + 99153 + +}; + +static const struct src_stage src_int32_21_5_1728_5000 = { + 4, 17, 21, 20, 420, 5, 21, 0, 0, + src_int32_21_5_1728_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_5_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_21_5_4535_5000.h new file mode 100644 index 000000000000..16d3af828ad9 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_5_4535_5000.h @@ -0,0 +1,2202 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_5_4535_5000_fir[2184] = { + -46288, + 73523, + -104226, + 135885, + -164809, + 186051, + -193404, + 179495, + -135974, + 53824, + 76213, + -263097, + 514840, + -837775, + 1235756, + -1709336, + 2254947, + -2864135, + 3522898, + -4211167, + 4902488, + -5563933, + 6156289, + -6634538, + 6948662, + -7044741, + 6866371, + -6356339, + 5458522, + -4119960, + 2293010, + 62481, + -2977093, + 6469929, + -10546986, + 15199898, + -20405146, + 26123818, + -32301996, + 38871858, + -45753573, + 52858141, + -60091389, + 67359568, + -74577487, + 81681234, + -88650462, + 95553303, + -102653627, + 110727305, + -122328562, + 150821514, + 2045922260, + 49770641, + -73564931, + 80111748, + -81612379, + 80607629, + -78010546, + 74275051, + -69688376, + 64466777, + -58791816, + 52824947, + -46713137, + 40590495, + -34578096, + 28783082, + -23297598, + 18197877, + -13543646, + 9377953, + -5727446, + 2603100, + -1362, + -2094347, + 3711831, + -4888122, + 5667351, + -6098588, + 6233725, + -6125487, + 5825620, + -5383324, + 4843958, + -4248043, + 3630570, + -3020609, + 2441194, + -1909470, + 1437044, + -1030518, + 692143, + -420556, + 211559, + -58882, + -45082, + 108615, + -140102, + 147562, + -138290, + 118607, + -93720, + 67671, + -48354, + 78057, + -112915, + 150869, + -188656, + 221687, + -243996, + 248273, + -225997, + 167690, + -63287, + -97361, + 323871, + -624608, + 1005871, + -1471035, + 2019668, + -2646671, + 3341493, + -4087465, + 4861300, + -5632813, + 6364896, + -7013782, + 7529629, + -7857416, + 7938163, + -7710448, + 7112175, + -6082556, + 4564225, + -2505401, + -137985, + 3400316, + -7304572, + 11860993, + -17066252, + 22903268, + -29341817, + 36340156, + -43847916, + 51810749, + -60177489, + 68911363, + -78008260, + 87528706, + -97659170, + 108843930, + -122112840, + 140073176, + -170976246, + 259039542, + 2032057170, + -43241378, + -25605732, + 48864843, + -59444790, + 64338470, + -65980776, + 65482750, + -63459504, + 60308416, + -56319519, + 51724125, + -46717555, + 41469934, + -36131163, + 30832978, + -25689580, + 20797673, + -16236356, + 12067144, + -8334265, + 5065304, + -2272204, + -47381, + 1908446, + -3336748, + 4366772, + -5039607, + 5400830, + -5498459, + 5381055, + -5096025, + 4688165, + -4198486, + 3663329, + -3113777, + 2575348, + -2067957, + 1606105, + -1199266, + 852418, + -566694, + 340084, + -168166, + 44818, + 37117, + -85237, + 107079, + -109716, + 99463, + -81679, + 60677, + -49470, + 81116, + -119536, + 163170, + -209253, + 253651, + -290757, + 313471, + -313265, + 280380, + -204138, + 73382, + 122937, + -395071, + 751667, + -1198885, + 1739471, + -2371817, + 3089069, + -3878323, + 4719956, + -5587155, + 6445682, + -7253910, + 7963179, + -8518464, + 8859379, + -8921498, + 8637962, + -7941327, + 6765591, + -5048311, + 2732728, + 230236, + -3880204, + 8245963, + -13344617, + 19181472, + -25750886, + 33038399, + -41024628, + 49691703, + -59033616, + 69073083, + -79890144, + 91673886, + -104824175, + 120174595, + -139554644, + 167515224, + -218546566, + 373432573, + 2004496317, + -127473290, + 20683255, + 17617174, + -36617619, + 47097012, + -52826091, + 55502061, + -56034717, + 54984415, + -52738387, + 49590022, + -45777152, + 41501269, + -36937262, + 32238234, + -27537727, + 22950657, + -18573654, + 14485259, + -10746225, + 7400043, + -4473787, + 1979273, + 85478, + -1734522, + 2992081, + -3890504, + 4468191, + -4767534, + 4832968, + -4709176, + 4439504, + -4064635, + 3621527, + -3142640, + 2655447, + -2182214, + 1740019, + -1340990, + 992708, + -698749, + 459310, + -271879, + 131921, + -33531, + -29964, + 65478, + -79729, + 78901, + -68406, + 52734, + -49564, + 82572, + -123872, + 172442, + -226074, + 281178, + -332621, + 373653, + -395910, + 389541, + -343454, + 245699, + -83993, + -153621, + 477990, + -897968, + 1419457, + -2044407, + 2769837, + -3586900, + 4480067, + -5426465, + 6395437, + -7348356, + 8238730, + -9012639, + 9609497, + -9963154, + 10003303, + -9657159, + 8851359, + -7513993, + 5576670, + -2976516, + -342048, + 4425904, + -9312403, + 15029325, + -21595968, + 29025780, + -37331212, + 46531902, + -56668146, + 67823335, + -80162843, + 94005563, + -109966620, + 129273669, + -154573074, + 192435725, + -264051666, + 492899971, + 1963575893, + -202322171, + 64503169, + -13019933, + -13599419, + 29246783, + -38829367, + 44551532, + -47579904, + 48616887, + -48133890, + 46477438, + -43921215, + 40692820, + -36987799, + 32976968, + -28810111, + 24617726, + -20511781, + 16586067, + -12916462, + 9561346, + -6562249, + 3944796, + -1719957, + -114432, + 1571925, + -2675557, + 3455837, + -3948736, + 4193707, + -4231844, + 4104196, + -3850311, + 3507024, + -3107517, + 2680657, + -2250595, + 1836625, + -1453261, + 1110511, + -814297, + 566993, + -368026, + 214516, + -101912, + 24583, + 23635, + -48980, + 57390, + -54220, + 44050, + -48578, + 82325, + -125750, + 178393, + -238659, + 303577, + -368598, + 427457, + -472122, + 492843, + -478328, + 416060, + -292754, + 94965, + 190165, + -574036, + 1065619, + -1670424, + 2389437, + -3218087, + 4145287, + -5152602, + 6213603, + -7293463, + 8348815, + -9327940, + 10171274, + -10812266, + 11178555, + -11193454, + 10777677, + -9851235, + 8335423, + -6154756, + 3238723, + 476821, + -5048853, + 10527239, + -16956044, + 24376637, + -32833453, + 42383832, + -53114463, + 65169206, + -78797959, + 94447640, + -112945480, + 135908921, + -166800285, + 214245626, + -306492651, + 616246377, + 1909794064, + -267329113, + 105132981, + -42465248, + 9148555, + 11156271, + -24285502, + 32865857, + -38279379, + 41347399, + -42611103, + 42460286, + -41197193, + 39069785, + -36289539, + 33040999, + -29486768, + 25769994, + -22015494, + 18330216, + -14803476, + 11507221, + -8496471, + 5810030, + -3471492, + 1490529, + 135559, + -1420103, + 2385184, + -3059677, + 3477318, + -3674820, + 3690140, + -3560914, + 3323128, + -3010021, + 2651267, + -2272409, + 1894552, + -1534287, + 1203825, + -911292, + 661168, + -454807, + 291023, + -166689, + 77313, + -17591, + -18121, + 35401, + -39445, + 34838, + -46480, + 80311, + -125040, + 180793, + -246624, + 320248, + -397796, + 473623, + -540186, + 588031, + -605890, + 580917, + -499076, + 345684, + -106108, + -233399, + 684735, + -1256890, + 1954843, + -2778429, + 3721268, + -4769772, + 5902312, + -7088593, + 8289275, + -9455898, + 10531135, + -11449373, + 12137653, + -12516909, + 12503498, + -12010931, + 10951718, + -9239222, + 6789346, + -3521881, + -638741, + 5763604, + -11920825, + 19179100, + -27614281, + 37320744, + -48430585, + 61146484, + -75800022, + 92961223, + -113661063, + 139892958, + -175914745, + 232396605, + -344875557, + 742197100, + 1843803731, + -322182637, + 141938832, + -70177643, + 31181103, + -6808409, + -9495374, + 20690957, + -28331937, + 33333889, + -36292360, + 37629898, + -37669547, + 36673549, + -34864313, + 32435869, + -29559984, + 26389285, + -23058690, + 19685969, + -16371918, + 13200462, + -10238879, + 7538256, + -5134232, + 3048026, + -1287756, + -150021, + 1278579, + -2119190, + 2699240, + -3050375, + 3206728, + -3203297, + 3074510, + -2853006, + 2568671, + -2247920, + 1913236, + -1582940, + 1271179, + -988101, + 740179, + -530648, + 360017, + -226626, + 127197, + -57376, + 12216, + 13399, + -24409, + 25314, + -43260, + 76498, + -121667, + 179479, + -249669, + 330693, + -419446, + 511019, + -598519, + 672976, + -723367, + 736768, + -698663, + 593409, + -404865, + 117189, + 284237, + -811744, + 1474238, + -2276012, + 3215563, + -4284468, + 5466377, + -6736175, + 8059375, + -9391786, + 10679489, + -11859149, + 12858678, + -13598224, + 13991459, + -13947105, + 13370621, + -12165916, + 10236944, + -7488979, + 3829303, + 833057, + -6589034, + 13533441, + -21772271, + 31435406, + -42698280, + 55819310, + -71206857, + 89545986, + -112057753, + 141087901, + -181648715, + 246392737, + -378227634, + 869414877, + 1766403056, + -366719831, + 174381677, + -95665100, + 52077335, + -24290679, + 5240237, + 8278902, + -17946679, + 24747282, + -29314590, + 32092978, + -33418264, + 33560684, + -32748421, + 31180597, + -29034330, + 26468383, + -23624848, + 20629770, + -17593244, + 14609355, + -11756166, + 9095912, + -6675454, + 4527037, + -2669344, + 1108809, + 158845, + -1146925, + 1875978, + -2371993, + 2664639, + -2785604, + 2767089, + -2640492, + 2435319, + -2178328, + 1892920, + -1598766, + 1311654, + -1043530, + 802713, + -594229, + 420256, + -280614, + 173288, + -94946, + 41425, + -8163, + -9433, + 15690, + -38932, + 70897, + -115608, + 174364, + -247593, + 334533, + -432915, + 538675, + -645709, + 745718, + -828142, + 880237, + -887286, + 832987, + -699999, + 470670, + -127929, + -343683, + 956863, + -1720318, + 2637500, + -3705368, + 4913226, + -6241691, + 7661868, + -9134759, + 10610972, + -12030753, + 13324354, + -14412752, + 15208673, + -15617885, + 15540679, + -14873419, + 13510011, + -11343080, + 8264567, + -4165379, + -1066487, + 7550161, + -15419804, + 24838433, + -36021695, + 49279238, + -65089294, + 84240784, + -108125911, + 139409163, + -183794865, + 255801532, + -405613676, + 996517777, + 1678523914, + -400925203, + 202023152, + -118492584, + 71448286, + -40950333, + 19626615, + -4117205, + -7338686, + 15767902, + -21826393, + 25969290, + -28537075, + 29801646, + -29991748, + 29307153, + -27926444, + 26011077, + -23707265, + 21146633, + -18446224, + 15708266, + -13019930, + 10453239, + -8065239, + 5898461, + -3981689, + 2331024, + -951193, + -162945, + 1024749, + -1654085, + 2075606, + -2317090, + 2407895, + -2377569, + 2254657, + -2065728, + 1834632, + -1581987, + 1324893, + -1076843, + 847813, + -644507, + 470704, + -327692, + 214741, + -129595, + 68942, + -28856, + 5177, + 6174, + -33539, + 63554, + -106899, + 165438, + -240296, + 331518, + -437730, + 555799, + -680545, + 804509, + -917812, + 1008141, + -1060871, + 1059354, + -985378, + 819819, + -543465, + 138003, + 412839, + -1122048, + 1998011, + -3043181, + 4252780, + -5613602, + 7102971, + -8687914, + 10324605, + -11958106, + 13522447, + -14941047, + 16127458, + -16986400, + 17415004, + -17304173, + 16539891, + -15004274, + 12576083, + -9130272, + 4535996, + 1347841, + -8680930, + 17656250, + -28525509, + 41643739, + -57550198, + 77123483, + -101902888, + 134828258, + -182211894, + 260264130, + -426152121, + 1122097975, + 1581218430, + -424927308, + 224529590, + -138288662, + 88943751, + -56469929, + 33380861, + -16248301, + 3275373, + 6581730, + -13984906, + 19389090, + -23131418, + 25479206, + -26656622, + 26859687, + -26264573, + 25031969, + -23309095, + 21230366, + -18917298, + 16478100, + -14007192, + 11584846, + -9277056, + 7135692, + -5198982, + 3492288, + -2029170, + 812686, + 163131, + -911682, + 1452160, + -1807917, + 2004913, + -2070277, + 2031040, + -1913058, + 1740155, + -1533482, + 1311100, + -1087763, + 874897, + -680727, + 510544, + -367059, + 250827, + -160693, + 94254, + -48285, + 19130, + -3038, + -27148, + 54559, + -95633, + 152772, + -227785, + 321537, + -433583, + 561802, + -702048, + 847860, + -990243, + 1117566, + -1215584, + 1267631, + -1254978, + 1157392, + -953879, + 623610, + -147028, + -492918, + 1309429, + -2310453, + 3497282, + -4863205, + 6392279, + -8058273, + 9823858, + -11640064, + 13446071, + -15169315, + 16725949, + -18021584, + 18952284, + -19405702, + 19262204, + -18395789, + 16674486, + -13959833, + 10104795, + -4949182, + -1688974, + 10028690, + -20352648, + 33054152, + -48722842, + 68310007, + -93473130, + 127374553, + -176828999, + 259504459, + -439030668, + 1244741105, + 1475643843, + -438993245, + 241674165, + -154750777, + 104258236, + -70560620, + 46237323, + -27874276, + 13681601, + -2623401, + -5952550, + 12490390, + -17316185, + 20686649, + -22816422, + 23893508, + -24087890, + 23556075, + -22443187, + 20883607, + -19000777, + 16906616, + -14700809, + 12470179, + -10288255, + 8215131, + -6297625, + 4569774, + -3053627, + 1760310, + -691301, + -160126, + 807370, + -1268937, + 1566904, + -1725469, + 1769628, + -1724022, + 1611978, + -1454759, + 1271021, + -1076477, + 883759, + -702439, + 539194, + -398092, + 280941, + -187701, + 116908, + -66090, + 32163, + -11768, + -19851, + 44040, + -81960, + 136517, + -210177, + 304619, + -420351, + 556314, + -709494, + 874569, + -1043617, + 1205924, + -1347916, + 1453236, + -1503006, + 1476274, + -1350664, + 1103222, + -711462, + 154569, + 585250, + -1521333, + 2661070, + -4004439, + 5542609, + -7256680, + 9116628, + -11080496, + 13093884, + -15089762, + 16988610, + -18698874, + 20117680, + -21131728, + 21618214, + -21445589, + 20473857, + -18553984, + 15525783, + -11213298, + 5416086, + 2106311, + -11661604, + 23673126, + -38768638, + 57952598, + -82967324, + 117135919, + -167649110, + 253337170, + -443521124, + 1363045905, + 1363045905, + -443521124, + 253337170, + -167649110, + 117135919, + -82967324, + 57952598, + -38768638, + 23673126, + -11661604, + 2106311, + 5416086, + -11213298, + 15525783, + -18553984, + 20473857, + -21445589, + 21618214, + -21131728, + 20117680, + -18698874, + 16988610, + -15089762, + 13093884, + -11080496, + 9116628, + -7256680, + 5542609, + -4004439, + 2661070, + -1521333, + 585250, + 154569, + -711462, + 1103222, + -1350664, + 1476274, + -1503006, + 1453236, + -1347916, + 1205924, + -1043617, + 874569, + -709494, + 556314, + -420351, + 304619, + -210177, + 136517, + -81960, + 44040, + -19851, + -11768, + 32163, + -66090, + 116908, + -187701, + 280941, + -398092, + 539194, + -702439, + 883759, + -1076477, + 1271021, + -1454759, + 1611978, + -1724022, + 1769628, + -1725469, + 1566904, + -1268937, + 807370, + -160126, + -691301, + 1760310, + -3053627, + 4569774, + -6297625, + 8215131, + -10288255, + 12470179, + -14700809, + 16906616, + -19000777, + 20883607, + -22443187, + 23556075, + -24087890, + 23893508, + -22816422, + 20686649, + -17316185, + 12490390, + -5952550, + -2623401, + 13681601, + -27874276, + 46237323, + -70560620, + 104258236, + -154750777, + 241674165, + -438993245, + 1475643843, + 1244741105, + -439030668, + 259504459, + -176828999, + 127374553, + -93473130, + 68310007, + -48722842, + 33054152, + -20352648, + 10028690, + -1688974, + -4949182, + 10104795, + -13959833, + 16674486, + -18395789, + 19262204, + -19405702, + 18952284, + -18021584, + 16725949, + -15169315, + 13446071, + -11640064, + 9823858, + -8058273, + 6392279, + -4863205, + 3497282, + -2310453, + 1309429, + -492918, + -147028, + 623610, + -953879, + 1157392, + -1254978, + 1267631, + -1215584, + 1117566, + -990243, + 847860, + -702048, + 561802, + -433583, + 321537, + -227785, + 152772, + -95633, + 54559, + -27148, + -3038, + 19130, + -48285, + 94254, + -160693, + 250827, + -367059, + 510544, + -680727, + 874897, + -1087763, + 1311100, + -1533482, + 1740155, + -1913058, + 2031040, + -2070277, + 2004913, + -1807917, + 1452160, + -911682, + 163131, + 812686, + -2029170, + 3492288, + -5198982, + 7135692, + -9277056, + 11584846, + -14007192, + 16478100, + -18917298, + 21230366, + -23309095, + 25031969, + -26264573, + 26859687, + -26656622, + 25479206, + -23131418, + 19389090, + -13984906, + 6581730, + 3275373, + -16248301, + 33380861, + -56469929, + 88943751, + -138288662, + 224529590, + -424927308, + 1581218430, + 1122097975, + -426152121, + 260264130, + -182211894, + 134828258, + -101902888, + 77123483, + -57550198, + 41643739, + -28525509, + 17656250, + -8680930, + 1347841, + 4535996, + -9130272, + 12576083, + -15004274, + 16539891, + -17304173, + 17415004, + -16986400, + 16127458, + -14941047, + 13522447, + -11958106, + 10324605, + -8687914, + 7102971, + -5613602, + 4252780, + -3043181, + 1998011, + -1122048, + 412839, + 138003, + -543465, + 819819, + -985378, + 1059354, + -1060871, + 1008141, + -917812, + 804509, + -680545, + 555799, + -437730, + 331518, + -240296, + 165438, + -106899, + 63554, + -33539, + 6174, + 5177, + -28856, + 68942, + -129595, + 214741, + -327692, + 470704, + -644507, + 847813, + -1076843, + 1324893, + -1581987, + 1834632, + -2065728, + 2254657, + -2377569, + 2407895, + -2317090, + 2075606, + -1654085, + 1024749, + -162945, + -951193, + 2331024, + -3981689, + 5898461, + -8065239, + 10453239, + -13019930, + 15708266, + -18446224, + 21146633, + -23707265, + 26011077, + -27926444, + 29307153, + -29991748, + 29801646, + -28537075, + 25969290, + -21826393, + 15767902, + -7338686, + -4117205, + 19626615, + -40950333, + 71448286, + -118492584, + 202023152, + -400925203, + 1678523914, + 996517777, + -405613676, + 255801532, + -183794865, + 139409163, + -108125911, + 84240784, + -65089294, + 49279238, + -36021695, + 24838433, + -15419804, + 7550161, + -1066487, + -4165379, + 8264567, + -11343080, + 13510011, + -14873419, + 15540679, + -15617885, + 15208673, + -14412752, + 13324354, + -12030753, + 10610972, + -9134759, + 7661868, + -6241691, + 4913226, + -3705368, + 2637500, + -1720318, + 956863, + -343683, + -127929, + 470670, + -699999, + 832987, + -887286, + 880237, + -828142, + 745718, + -645709, + 538675, + -432915, + 334533, + -247593, + 174364, + -115608, + 70897, + -38932, + 15690, + -9433, + -8163, + 41425, + -94946, + 173288, + -280614, + 420256, + -594229, + 802713, + -1043530, + 1311654, + -1598766, + 1892920, + -2178328, + 2435319, + -2640492, + 2767089, + -2785604, + 2664639, + -2371993, + 1875978, + -1146925, + 158845, + 1108809, + -2669344, + 4527037, + -6675454, + 9095912, + -11756166, + 14609355, + -17593244, + 20629770, + -23624848, + 26468383, + -29034330, + 31180597, + -32748421, + 33560684, + -33418264, + 32092978, + -29314590, + 24747282, + -17946679, + 8278902, + 5240237, + -24290679, + 52077335, + -95665100, + 174381677, + -366719831, + 1766403056, + 869414877, + -378227634, + 246392737, + -181648715, + 141087901, + -112057753, + 89545986, + -71206857, + 55819310, + -42698280, + 31435406, + -21772271, + 13533441, + -6589034, + 833057, + 3829303, + -7488979, + 10236944, + -12165916, + 13370621, + -13947105, + 13991459, + -13598224, + 12858678, + -11859149, + 10679489, + -9391786, + 8059375, + -6736175, + 5466377, + -4284468, + 3215563, + -2276012, + 1474238, + -811744, + 284237, + 117189, + -404865, + 593409, + -698663, + 736768, + -723367, + 672976, + -598519, + 511019, + -419446, + 330693, + -249669, + 179479, + -121667, + 76498, + -43260, + 25314, + -24409, + 13399, + 12216, + -57376, + 127197, + -226626, + 360017, + -530648, + 740179, + -988101, + 1271179, + -1582940, + 1913236, + -2247920, + 2568671, + -2853006, + 3074510, + -3203297, + 3206728, + -3050375, + 2699240, + -2119190, + 1278579, + -150021, + -1287756, + 3048026, + -5134232, + 7538256, + -10238879, + 13200462, + -16371918, + 19685969, + -23058690, + 26389285, + -29559984, + 32435869, + -34864313, + 36673549, + -37669547, + 37629898, + -36292360, + 33333889, + -28331937, + 20690957, + -9495374, + -6808409, + 31181103, + -70177643, + 141938832, + -322182637, + 1843803731, + 742197100, + -344875557, + 232396605, + -175914745, + 139892958, + -113661063, + 92961223, + -75800022, + 61146484, + -48430585, + 37320744, + -27614281, + 19179100, + -11920825, + 5763604, + -638741, + -3521881, + 6789346, + -9239222, + 10951718, + -12010931, + 12503498, + -12516909, + 12137653, + -11449373, + 10531135, + -9455898, + 8289275, + -7088593, + 5902312, + -4769772, + 3721268, + -2778429, + 1954843, + -1256890, + 684735, + -233399, + -106108, + 345684, + -499076, + 580917, + -605890, + 588031, + -540186, + 473623, + -397796, + 320248, + -246624, + 180793, + -125040, + 80311, + -46480, + 34838, + -39445, + 35401, + -18121, + -17591, + 77313, + -166689, + 291023, + -454807, + 661168, + -911292, + 1203825, + -1534287, + 1894552, + -2272409, + 2651267, + -3010021, + 3323128, + -3560914, + 3690140, + -3674820, + 3477318, + -3059677, + 2385184, + -1420103, + 135559, + 1490529, + -3471492, + 5810030, + -8496471, + 11507221, + -14803476, + 18330216, + -22015494, + 25769994, + -29486768, + 33040999, + -36289539, + 39069785, + -41197193, + 42460286, + -42611103, + 41347399, + -38279379, + 32865857, + -24285502, + 11156271, + 9148555, + -42465248, + 105132981, + -267329113, + 1909794064, + 616246377, + -306492651, + 214245626, + -166800285, + 135908921, + -112945480, + 94447640, + -78797959, + 65169206, + -53114463, + 42383832, + -32833453, + 24376637, + -16956044, + 10527239, + -5048853, + 476821, + 3238723, + -6154756, + 8335423, + -9851235, + 10777677, + -11193454, + 11178555, + -10812266, + 10171274, + -9327940, + 8348815, + -7293463, + 6213603, + -5152602, + 4145287, + -3218087, + 2389437, + -1670424, + 1065619, + -574036, + 190165, + 94965, + -292754, + 416060, + -478328, + 492843, + -472122, + 427457, + -368598, + 303577, + -238659, + 178393, + -125750, + 82325, + -48578, + 44050, + -54220, + 57390, + -48980, + 23635, + 24583, + -101912, + 214516, + -368026, + 566993, + -814297, + 1110511, + -1453261, + 1836625, + -2250595, + 2680657, + -3107517, + 3507024, + -3850311, + 4104196, + -4231844, + 4193707, + -3948736, + 3455837, + -2675557, + 1571925, + -114432, + -1719957, + 3944796, + -6562249, + 9561346, + -12916462, + 16586067, + -20511781, + 24617726, + -28810111, + 32976968, + -36987799, + 40692820, + -43921215, + 46477438, + -48133890, + 48616887, + -47579904, + 44551532, + -38829367, + 29246783, + -13599419, + -13019933, + 64503169, + -202322171, + 1963575893, + 492899971, + -264051666, + 192435725, + -154573074, + 129273669, + -109966620, + 94005563, + -80162843, + 67823335, + -56668146, + 46531902, + -37331212, + 29025780, + -21595968, + 15029325, + -9312403, + 4425904, + -342048, + -2976516, + 5576670, + -7513993, + 8851359, + -9657159, + 10003303, + -9963154, + 9609497, + -9012639, + 8238730, + -7348356, + 6395437, + -5426465, + 4480067, + -3586900, + 2769837, + -2044407, + 1419457, + -897968, + 477990, + -153621, + -83993, + 245699, + -343454, + 389541, + -395910, + 373653, + -332621, + 281178, + -226074, + 172442, + -123872, + 82572, + -49564, + 52734, + -68406, + 78901, + -79729, + 65478, + -29964, + -33531, + 131921, + -271879, + 459310, + -698749, + 992708, + -1340990, + 1740019, + -2182214, + 2655447, + -3142640, + 3621527, + -4064635, + 4439504, + -4709176, + 4832968, + -4767534, + 4468191, + -3890504, + 2992081, + -1734522, + 85478, + 1979273, + -4473787, + 7400043, + -10746225, + 14485259, + -18573654, + 22950657, + -27537727, + 32238234, + -36937262, + 41501269, + -45777152, + 49590022, + -52738387, + 54984415, + -56034717, + 55502061, + -52826091, + 47097012, + -36617619, + 17617174, + 20683255, + -127473290, + 2004496317, + 373432573, + -218546566, + 167515224, + -139554644, + 120174595, + -104824175, + 91673886, + -79890144, + 69073083, + -59033616, + 49691703, + -41024628, + 33038399, + -25750886, + 19181472, + -13344617, + 8245963, + -3880204, + 230236, + 2732728, + -5048311, + 6765591, + -7941327, + 8637962, + -8921498, + 8859379, + -8518464, + 7963179, + -7253910, + 6445682, + -5587155, + 4719956, + -3878323, + 3089069, + -2371817, + 1739471, + -1198885, + 751667, + -395071, + 122937, + 73382, + -204138, + 280380, + -313265, + 313471, + -290757, + 253651, + -209253, + 163170, + -119536, + 81116, + -49470, + 60677, + -81679, + 99463, + -109716, + 107079, + -85237, + 37117, + 44818, + -168166, + 340084, + -566694, + 852418, + -1199266, + 1606105, + -2067957, + 2575348, + -3113777, + 3663329, + -4198486, + 4688165, + -5096025, + 5381055, + -5498459, + 5400830, + -5039607, + 4366772, + -3336748, + 1908446, + -47381, + -2272204, + 5065304, + -8334265, + 12067144, + -16236356, + 20797673, + -25689580, + 30832978, + -36131163, + 41469934, + -46717555, + 51724125, + -56319519, + 60308416, + -63459504, + 65482750, + -65980776, + 64338470, + -59444790, + 48864843, + -25605732, + -43241378, + 2032057170, + 259039542, + -170976246, + 140073176, + -122112840, + 108843930, + -97659170, + 87528706, + -78008260, + 68911363, + -60177489, + 51810749, + -43847916, + 36340156, + -29341817, + 22903268, + -17066252, + 11860993, + -7304572, + 3400316, + -137985, + -2505401, + 4564225, + -6082556, + 7112175, + -7710448, + 7938163, + -7857416, + 7529629, + -7013782, + 6364896, + -5632813, + 4861300, + -4087465, + 3341493, + -2646671, + 2019668, + -1471035, + 1005871, + -624608, + 323871, + -97361, + -63287, + 167690, + -225997, + 248273, + -243996, + 221687, + -188656, + 150869, + -112915, + 78057, + -48354, + 67671, + -93720, + 118607, + -138290, + 147562, + -140102, + 108615, + -45082, + -58882, + 211559, + -420556, + 692143, + -1030518, + 1437044, + -1909470, + 2441194, + -3020609, + 3630570, + -4248043, + 4843958, + -5383324, + 5825620, + -6125487, + 6233725, + -6098588, + 5667351, + -4888122, + 3711831, + -2094347, + -1362, + 2603100, + -5727446, + 9377953, + -13543646, + 18197877, + -23297598, + 28783082, + -34578096, + 40590495, + -46713137, + 52824947, + -58791816, + 64466777, + -69688376, + 74275051, + -78010546, + 80607629, + -81612379, + 80111748, + -73564931, + 49770641, + 2045922260, + 150821514, + -122328562, + 110727305, + -102653627, + 95553303, + -88650462, + 81681234, + -74577487, + 67359568, + -60091389, + 52858141, + -45753573, + 38871858, + -32301996, + 26123818, + -20405146, + 15199898, + -10546986, + 6469929, + -2977093, + 62481, + 2293010, + -4119960, + 5458522, + -6356339, + 6866371, + -7044741, + 6948662, + -6634538, + 6156289, + -5563933, + 4902488, + -4211167, + 3522898, + -2864135, + 2254947, + -1709336, + 1235756, + -837775, + 514840, + -263097, + 76213, + 53824, + -135974, + 179495, + -193404, + 186051, + -164809, + 135885, + -104226, + 73523, + -46288 + +}; + +static const struct src_stage src_int32_21_5_4535_5000 = { + 4, 17, 21, 104, 2184, 5, 21, 0, 0, + src_int32_21_5_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_80_3968_5000.h b/src/audio/src/coef/src_ipc4_int32_21_80_3968_5000.h new file mode 100644 index 000000000000..66ae1019b3f5 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_80_3968_5000.h @@ -0,0 +1,3377 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_80_3968_5000_fir[3360] = { + 146838, + 357465, + 426859, + 219317, + -251881, + -770248, + -993125, + -649031, + 246050, + 1299636, + 1882418, + 1470706, + 21094, + -1861644, + -3129659, + -2835812, + -754164, + 2297941, + 4710900, + 4883899, + 2203530, + -2364469, + -6516452, + -7712648, + -4647096, + 1728069, + 8326368, + 11343404, + 8362794, + 27220, + -9791399, + -15685505, + -13593926, + -3384336, + 10421422, + 20502848, + 20511093, + 8870412, + -9581044, + -25385237, + -29175616, + -17032845, + 6488128, + 29724411, + 39510006, + 28424422, + -204433, + -32689364, + -51280914, + -43614716, + -10404545, + 33185006, + 64099238, + 63259135, + 26789007, + -29755013, + -77440934, + -88291646, + -51026020, + 20330869, + 90691788, + 120407692, + 86623861, + -1550580, + -103223342, + -163348156, + -140795002, + -33297503, + 114530898, + 226975652, + 232281111, + 101992324, + -124606378, + -345267242, + -430652242, + -278563960, + 136162169, + 738984313, + 1372717440, + 1850114523, + 2021998788, + 1833424479, + 1344641075, + 708112494, + 111179297, + -291941249, + -431395141, + -336816756, + -112958590, + 110968558, + 235120540, + 223592705, + 107644297, + -39848013, + -143963642, + -162154054, + -98894605, + 3372676, + 89675634, + 120360823, + 87981002, + 16626654, + -53783791, + -88869821, + -75826305, + -27011183, + 29173421, + 64152498, + 63240658, + 31208901, + -12388039, + -44624655, + -50935177, + -31322357, + 1384234, + 29422111, + 39495620, + 28829789, + 5264992, + -17938582, + -29356369, + -24844318, + -8678932, + 9640961, + 20787068, + 20214356, + 9787472, + -4003579, + -13895378, + -15565847, + -9370306, + 498388, + 8644952, + 11326663, + 8065192, + 1389111, + -4885190, + -7749810, + -6368146, + -2134946, + 2387921, + 4941222, + 4636485, + 2152800, + -885726, + -2892469, + -3099104, + -1776979, + 107087, + 1516003, + 1874414, + 1254920, + 195395, + -679512, + -994037, + -749451, + -225936, + 236073, + 429165, + 349247, + 157482, + 365359, + 423894, + 201921, + -277961, + -790362, + -990870, + -617224, + 297114, + 1343265, + 1888071, + 1422923, + -65974, + -1944898, + -3156530, + -2774888, + -620237, + 2441637, + 4780040, + 4819785, + 2014582, + -2593103, + -6657812, + -7665364, + -4401059, + 2067689, + 8579151, + 11345928, + 8067833, + -447634, + -10203332, + -15786263, + -13273118, + -2756359, + 11046746, + 20767539, + 20207400, + 8083466, + -10477155, + -25897826, + -28957016, + -16099849, + 7710948, + 30587389, + 39474890, + 27384836, + -1802699, + -34023805, + -51564472, + -42543913, + -8395879, + 35131605, + 64882756, + 62281032, + 24356322, + -32478620, + -78968698, + -87599242, + -48186634, + 24033824, + 93307080, + 120304128, + 83442282, + -6507404, + -107455166, + -164346997, + -137424258, + -26649145, + 121336645, + 230107095, + 229120653, + 92784982, + -136246316, + -353405755, + -429355604, + -264571251, + 161588105, + 769932316, + 1400431804, + 1866093081, + 2021158519, + 1816035377, + 1316222828, + 677337162, + 86652793, + -304700832, + -431592487, + -328068432, + -101316711, + 119705639, + 237638866, + 219964758, + 100685932, + -46293516, + -146927929, + -160767661, + -94474995, + 8256538, + 92594737, + 120164595, + 85178705, + 12925775, + -56457051, + -89333768, + -74127355, + -24250663, + 31506896, + 64960527, + 62308543, + 29205930, + -14344043, + -45572838, + -50528071, + -29924691, + 2961379, + 30376916, + 39432061, + 27904842, + 4043074, + -18816103, + -29499294, + -24275930, + -7771990, + 10394258, + 21035168, + 19902592, + 9145753, + -4613369, + -14177235, + -15427581, + -8940652, + 965304, + 8914051, + 11295839, + 7796021, + 1051237, + -5115107, + -7776893, + -6213144, + -1904836, + 2567563, + 4991746, + 4556941, + 2006413, + -1014778, + -2944834, + -3064943, + -1691029, + 191907, + 1558785, + 1864100, + 1209192, + 145212, + -708645, + -993625, + -728012, + -200159, + 252177, + 430824, + 340724, + 168178, + 372908, + 420263, + 183899, + -304139, + -809753, + -987254, + -584114, + 348525, + 1385735, + 1891334, + 1372687, + -154017, + -2026617, + -3179638, + -2709731, + -484093, + 2583686, + 4843763, + 4748897, + 1821278, + -2820547, + -6791981, + -7607932, + -4147325, + 2407541, + 8823149, + 11334116, + 7760343, + -925598, + -10605513, + -15867854, + -12933217, + -2120377, + 11662592, + 21007931, + 19876182, + 7281007, + -11366095, + -26381249, + -28700597, + -15140593, + 8931913, + 31417438, + 39390008, + 26304400, + -3408616, + -35323806, + -51785114, + -41413214, + -6364406, + 37046080, + 65589773, + 61218895, + 21878112, + -35178474, + -80407143, + -86792749, + -45268654, + 27730896, + 95822983, + 120049235, + 80133942, + -11491889, + -111584109, + -165147822, + -133853922, + -19910275, + 128052462, + 232980762, + 225639614, + 83354936, + -147864483, + -361218304, + -427497456, + -249965956, + 187443345, + 800936034, + 1427764257, + 1881348240, + 2019478613, + 1797960154, + 1287483005, + 646678433, + 62595492, + -316840972, + -431252882, + -319036532, + -89694334, + 128195874, + 239836388, + 216098545, + 93664901, + -52627039, + -149685878, + -159192155, + -89970620, + 13095268, + 95378485, + 119820260, + 82288969, + 9232794, + -59043023, + -89683630, + -72346718, + -21476987, + 33786842, + 65682737, + 61304499, + 27178752, + -16270285, + -46458460, + -50060480, + -28498298, + 4525102, + 31287911, + 39319715, + 26950917, + 2823893, + -19664490, + -29604456, + -23680966, + -6861386, + 11129476, + 21255272, + 19568108, + 8497125, + -5213009, + -14439285, + -15271018, + -8503043, + 1427412, + 9169854, + 11251083, + 7519260, + 714866, + -5336626, + -7793948, + -6051701, + -1674435, + 2742272, + 5035473, + 4472421, + 1858982, + -1141182, + -2992883, + -3027261, + -1603921, + 275455, + 1599028, + 1851519, + 1162525, + 95561, + -736410, + -991911, + -705969, + -174583, + 267619, + 431846, + 331915, + 178908, + 380093, + 415956, + 165264, + -330382, + -828384, + -982260, + -549725, + 400219, + 1426972, + 1892173, + 1320032, + -242928, + -2106675, + -3198912, + -2640379, + -345886, + 2723888, + 4901932, + 4671262, + 1623825, + -3046499, + -6918724, + -7540335, + -3886153, + 2747196, + 9057980, + 11307870, + 7440616, + -1406092, + -10997357, + -15930031, + -12574516, + -1477139, + 12268114, + 21223548, + 19517668, + 6463941, + -12246694, + -26834705, + -28406435, + -14156117, + 10149472, + 32213305, + 39255154, + 25184215, + -5020213, + -36587521, + -51942177, + -40223673, + -4312532, + 38925834, + 66218936, + 60073537, + 19357196, + -37851051, + -81753914, + -85872452, + -42275212, + 31417437, + 98235703, + 119642297, + 76702064, + -16498050, + -115604288, + -165748100, + -130086768, + -13088403, + 134669299, + 235590630, + 221838820, + 73710932, + -159446820, + -368691058, + -425070464, + -234751459, + 213713679, + 831974841, + 1454695110, + 1895868616, + 2016960336, + 1779212239, + 1258442085, + 616156222, + 39019755, + -328360478, + -430385323, + -309735431, + -78104870, + 136431936, + 241713773, + 212001016, + 86590296, + -58841798, + -152235770, + -157430920, + -85387644, + 17883228, + 98024381, + 119329241, + 79315946, + 5552234, + -61539058, + -89919688, + -70487114, + -18693683, + 36010753, + 66318752, + 60230212, + 25130038, + -18164547, + -47280798, + -49533354, + -27045133, + 6073534, + 32154229, + 39159027, + 25969389, + 1608958, + -20482868, + -29671971, + -23060347, + -5948287, + 11845812, + 21447294, + 19211481, + 7842453, + -5801817, + -14681342, + -15096490, + -8058090, + 1884167, + 9412142, + 11192562, + 7235321, + 380411, + -5549536, + -7801043, + -5884080, + -1444041, + 2911872, + 5072411, + 4383081, + 1710706, + -1264801, + -3036603, + -2986146, + -1515780, + 357640, + 1636712, + 1836716, + 1114994, + 46499, + -762791, + -988916, + -683364, + -149241, + 282389, + 432242, + 322840, + 189657, + 386894, + 410967, + 146031, + -356653, + -846214, + -975874, + -514087, + 452129, + 1466906, + 1890555, + 1264999, + -332603, + -2184949, + -3214284, + -2566877, + -205773, + 2862044, + 4954418, + 4586913, + 1422437, + -3270656, + -7037812, + -7462572, + -3617812, + 3086217, + 9283269, + 11267107, + 7108964, + -1888522, + -11378290, + -15972572, + -12197331, + -827407, + 12862473, + 21413948, + 19132124, + 5633203, + -13117786, + -27257425, + -28074655, + -13147498, + 11362072, + 32973773, + 39070182, + 24025442, + -6635502, + -37813141, + -52035075, + -38976421, + -2242707, + 40768302, + 66768981, + 58845881, + 16796464, + -40492842, + -83006752, + -84838777, + -39209559, + 35088785, + 100541547, + 119082782, + 73150044, + -21519833, + -119509908, + -166145521, + -126125832, + -6191200, + 141178145, + 237930927, + 217719480, + 63862060, + -170979132, + -375810355, + -422067731, + -218931696, + 240384460, + 863027979, + 1481204920, + 1909643360, + 2013605585, + 1759805544, + 1229120698, + 585790223, + 15937455, + -339258704, + -428999197, + -300179605, + -66561535, + 144406866, + 243272051, + 207679327, + 79471192, + -64931210, + -154576147, + -155487542, + -80732284, + 22614878, + 100530111, + 118693134, + 76263863, + 1888573, + -63942633, + -90042366, + -68551341, + -15904267, + 38176205, + 66868307, + 59087448, + 23062470, + -20024661, + -48039210, + -48947714, + -25567173, + 7604837, + 32975066, + 38950500, + 24961659, + 399760, + -21270406, + -29701998, + -22415018, + -5033853, + 12542498, + 21611187, + 18833313, + 7182600, + -6379131, + -14903247, + -14904350, + -7606410, + 2335035, + 9640715, + 11120461, + 6944621, + 48279, + -5753642, + -7798254, + -5710550, + -1213944, + 3076193, + 5102579, + 4289085, + 1561782, + -1385508, + -3075983, + -2941690, + -1426734, + 438370, + 1671817, + 1819741, + 1066672, + -1915, + -787773, + -984667, + -660237, + -124163, + 296478, + 432025, + 313520, + 200407, + 393294, + 405288, + 126219, + -382916, + -863207, + -968082, + -477230, + 504189, + 1505465, + 1886450, + 1207630, + -422932, + -2261314, + -3225689, + -2489276, + -63916, + 2997953, + 5001096, + 4495895, + 1217337, + -3492712, + -7149024, + -7374653, + -3342585, + 3424167, + 9498652, + 11211762, + 6765714, + -2372292, + -11747744, + -15995276, + -11802005, + -171957, + 13444838, + 21578712, + 18719851, + 4789747, + -13978209, + -27648673, + -27705430, + -12115849, + 12568156, + 33697661, + 38835013, + 22829298, + -8252475, + -38998893, + -52063297, + -37672670, + -157414, + 42570946, + 67238734, + 57536958, + 14198874, + -43100352, + -84163503, + -83692296, + -36075053, + 38740263, + 102736929, + 118370343, + 69481452, + -26551122, + -123295270, + -166338006, + -121974408, + 773507, + 147570038, + 239996148, + 213283184, + 53817743, + -182447110, + -382562723, + -418482814, + -202511152, + 267440615, + 894074574, + 1507274497, + 1922662174, + 2009416884, + 1739754449, + 1199539614, + 555599895, + -6640024, + -349535543, + -427104267, + -290383610, + -55077343, + 152114075, + 244512613, + 203140834, + 72316640, + -70888896, + -156705817, + -153365796, + -76010799, + 27284787, + 102893549, + 117913701, + 73137017, + -1753760, + -66251357, + -90052221, + -66542277, + -13112244, + 40280864, + 67331243, + 57878045, + 20978738, + -21848518, + -48733140, + -48304649, + -24066416, + 9117203, + 33749677, + 38694693, + 23929152, + -802223, + -22026318, + -29694742, + -21745950, + -4119240, + 13218791, + 21746938, + 18434229, + 6518434, + -6944307, + -15104869, + -14694971, + -7148621, + 2779491, + 9855392, + 11034980, + 6647583, + -281129, + -5948760, + -7785672, + -5531383, + -984436, + 3235078, + 5126004, + 4190597, + 1412409, + -1503177, + -3111021, + -2893987, + -1336907, + 517558, + 1704331, + 1800642, + 1017636, + -49627, + -811344, + -979187, + -636628, + -99380, + 309880, + 431207, + 303975, + 211141, + 399272, + 398915, + 105843, + -409132, + -879324, + -958874, + -439184, + 556332, + 1542580, + 1879831, + 1147972, + -513804, + -2335649, + -3233070, + -2407632, + 79519, + 3131416, + 5041850, + 4398261, + 1008754, + -3712364, + -7252148, + -7276602, + -3060763, + 3760607, + 9703774, + 11141790, + 6411212, + -2856798, + -12105166, + -15997968, + -11388907, + 488423, + 14014387, + 21717456, + 18281187, + 3934553, + -14826805, + -28007749, + -27298982, + -11062323, + 13766162, + 34383828, + 38549626, + 21597053, + -9869114, + -40143043, + -52026411, + -36313709, + 1940827, + 44331266, + 67627117, + 56147907, + 11567447, + -45670110, + -85222120, + -82433723, + -32875160, + 42367191, + 104818379, + 117504819, + 65700023, + -31585744, + -126954783, + -166323711, + -117636049, + 7797744, + 153836072, + 241781058, + 208531909, + 43587733, + -193836340, + -388934893, + -414309728, + -185494863, + 294866654, + 925093649, + 1532884932, + 1934915316, + 2004397387, + 1719073795, + 1169719715, + 525604447, + -28701799, + -359191427, + -424710660, + -280362073, + -43665088, + 159547347, + 245437205, + 198393078, + 65135653, + -76708687, + -158623851, + -151069649, + -71229483, + 31887638, + 105112761, + 116992869, + 69939770, + -5370390, + -68462970, + -89949951, + -64462871, + -10321099, + 42322485, + 67707513, + 56603912, + 18881535, + -23634064, + -49362115, + -47605310, + -22544874, + 10608861, + 34477383, + 38392222, + 22873315, + -1995535, + -22749859, + -29650457, + -21054139, + -3205594, + 13873982, + 21854568, + 18014875, + 5850817, + -7496723, + -15286101, + -14468745, + -6685346, + 3217025, + 10056012, + 10936333, + 6344634, + -607418, + -6134719, + -7763398, + -5346857, + -755803, + 3388373, + 5142720, + 4087789, + 1262783, + -1617689, + -3141717, + -2843135, + -1246426, + 595119, + 1734244, + 1779474, + 967959, + -96582, + -833491, + -972504, + -612578, + -74922, + 322588, + 429803, + 294223, + 221840, + 404811, + 391843, + 84924, + -435265, + -894530, + -948240, + -399984, + 608487, + 1578180, + 1870676, + 1086076, + -605107, + -2407834, + -3236372, + -2322009, + 224363, + 3262238, + 5076567, + 4294074, + 796922, + -3929309, + -7346978, + -7168457, + -2772652, + 4095094, + 9898289, + 11057162, + 6045819, + -3341429, + -12450011, + -15980497, + -10958431, + 1152932, + 14570312, + 21829822, + 17816506, + 3068621, + -15662425, + -28333987, + -26855579, + -9988104, + 14954533, + 35031171, + 38214066, + 20330030, + -11483385, + -41243899, + -51924065, + -34900906, + 4049465, + 46046797, + 67933144, + 54679976, + 8905265, + -48198668, + -86180664, + -81063916, + -29613451, + 45964888, + 106782541, + 116486237, + 61809661, + -36617480, + -130482966, + -166101027, + -113114561, + 14873395, + 159967413, + 243280703, + 203468017, + 33182101, + -205132316, + -394913809, + -409542959, + -167888411, + 322646683, + 956064148, + 1558017604, + 1946393609, + 1998550872, + 1697778862, + 1139681985, + 495822821, + -50237497, + -368227321, + -421828854, + -270129675, + -32337338, + 166700847, + 246047920, + 193443777, + 57937198, + -82384629, + -160329584, + -148603248, + -66394659, + 36418231, + 107185997, + 115932725, + 66676541, + -8957003, + -70575345, + -89736384, + -62316142, + -7534297, + 44298914, + 67997175, + 55267030, + 16773556, + -25379307, + -49925746, + -46850914, + -21004574, + 12078076, + 35157565, + 38043757, + 21795617, + -3178737, + -23440333, + -29569437, + -20340599, + -2294056, + 14507391, + 21934136, + 17575918, + 5180615, + -8035775, + -15446866, + -14226080, + -6217212, + 3647139, + 10242431, + 10824751, + 6036206, + -930202, + -6311363, + -7731545, + -5157255, + -528328, + 3535937, + 5152772, + 3980836, + 1113098, + -1728930, + -3168080, + -2789235, + -1155415, + 670972, + 1761548, + 1756291, + 917715, + -142730, + -854208, + -964645, + -588127, + -50818, + 334598, + 427826, + 284285, + 232487, + 409892, + 384068, + 63480, + -461276, + -908787, + -936173, + -359667, + 660585, + 1612199, + 1858963, + 1021996, + -696725, + -2477750, + -3235544, + -2232474, + 370443, + 3390220, + 5105144, + 4183403, + 582083, + -4143243, + -7433321, + -7050267, + -2478565, + 4427186, + 10081864, + 10957870, + 5669916, + -3825572, + -12781746, + -15942734, + -10510995, + 1820759, + 15111811, + 21915486, + 17326216, + 2192971, + -16483930, + -28626762, + -26375542, + -8894412, + 16131711, + 35638632, + 37828440, + 19029606, + -13093245, + -42299811, + -51755986, + -33435702, + 6165920, + 47715116, + 68155930, + 53134515, + 6215468, + -50682609, + -87037309, + -79583880, + -26293595, + 49528679, + 108626184, + 115314813, + 57814429, + -41640067, + -133874458, + -165668590, + -108414006, + 21992216, + 165955310, + 244490417, + 198094257, + 22611234, + -216320456, + -400486650, + -404177470, + -149697927, + 350764418, + 986964948, + 1582654203, + 1957088449, + 1991881736, + 1675885364, + 1109447489, + 466273676, + -71237253, + -376644718, + -418469669, + -259701133, + -21106423, + 173569119, + 246347199, + 188300816, + 50730184, + -87910991, + -161822609, + -145970913, + -61512665, + 40871495, + 109111704, + 114735514, + 63351801, + -12509349, + -72586494, + -89412483, + -60105174, + -4755272, + 46208093, + 68200398, + 53869444, + 14657492, + -27082316, + -50423728, + -46042738, + -19447552, + 13523153, + 35789669, + 37650021, + 20697541, + -4350415, + -24097089, + -29452025, + -19606370, + -1385752, + 15118371, + 21985734, + 17118046, + 4508686, + -8560881, + -15587109, + -13967406, + -5744844, + 4069347, + 10414527, + 10700479, + 5722734, + -1249102, + -6478547, + -7690237, + -4962864, + -302289, + 3677636, + 5156210, + 3869914, + 963546, + -1836792, + -3190123, + -2732392, + -1063998, + 745039, + 1786241, + 1731150, + 866979, + -188020, + -873487, + -955640, + -563316, + -27094, + 345905, + 425291, + 274181, + 243064, + 414498, + 375588, + 41534, + -487126, + -922060, + -922667, + -318271, + 712555, + 1644570, + 1844676, + 955789, + -788543, + -2545278, + -3230542, + -2139102, + 517582, + 3515170, + 5127483, + 4066330, + 364487, + -4353865, + -7510990, + -6922098, + -2178827, + 4756438, + 10254175, + 10843923, + 5283898, + -4308608, + -13099852, + -15884578, + -10047042, + 2491082, + 15638099, + 21974154, + 16810761, + 1308643, + -17290188, + -28885482, + -25859235, + -7782500, + 17296143, + 36205195, + 37392921, + 17697208, + -14696647, + -43309179, + -51521981, + -31919615, + 8287587, + 49333846, + 68294685, + 51512984, + 3501249, + -53118552, + -87790345, + -77994760, + -22919356, + 53053899, + 110346206, + 113990955, + 53718547, + -46647210, + -137124026, + -165025276, + -103538693, + 29145838, + 171791099, + 245405832, + 192413767, + 11885818, + -227386117, + -405640837, + -398208709, + -130930084, + 379203192, + 1017774881, + 1606776744, + 1966991816, + 1984394995, + 1653409427, + 1079037354, + 436975377, + -91691727, + -384445637, + -414644248, + -249091193, + -9984423, + 180147091, + 246337817, + 182972236, + 43523456, + -93282266, + -163102781, + -143177136, + -56589856, + 45242484, + 110888515, + 113403634, + 59970069, + -16023247, + -74494565, + -88979341, + -57833111, + -1987432, + 48048058, + 68317454, + 52413262, + 12536028, + -28741226, + -50855839, + -45182118, + -17875856, + 14942435, + 36373204, + 37211789, + 19580591, + -5509175, + -24719522, + -29298603, + -18852506, + -481801, + 15706308, + 22009490, + 16641967, + 3835888, + -9071483, + -15706804, + -13693166, + -5268869, + 4483179, + 10572194, + 10563775, + 5404655, + -1563746, + -6636140, + -7639609, + -4763972, + -77962, + 3813344, + 5153095, + 3755206, + 814318, + -1941172, + -3207864, + -2672712, + -972299, + 817244, + 1808324, + 1704108, + 815825, + -232404, + -891325, + -945520, + -538186, + -3777, + 356506, + 422214, + 263930, + 253551, + 418611, + 366401, + 19107, + -512776, + -934316, + -907718, + -275836, + 764326, + 1675228, + 1827799, + 887517, + -880441, + -2610303, + -3221327, + -2041972, + 665601, + 3636895, + 5143495, + 3942944, + 144385, + -4560874, + -7579808, + -6784025, + -1873772, + 5082409, + 10414911, + 10715348, + 4888176, + -4789915, + -13403823, + -15805952, + -9567041, + 3163072, + 16148404, + 22005565, + 16270621, + 416694, + -18080082, + -29109599, + -25307074, + -6653650, + 18446282, + 36729889, + 36907742, + 16334309, + -16291535, + -44270448, + -51221942, + -30354236, + 10411838, + 50900654, + 68348722, + 49816943, + 765852, + -55503153, + -88438179, + -76297844, + -19494592, + 56535904, + 111939634, + 112515259, + 49526391, + -51632586, + -140226571, + -164170214, + -98493180, + 36325780, + 177466223, + 246022883, + 186430074, + 1016842, + -238314605, + -410364051, + -391632617, + -111592100, + 407945973, + 1048472752, + 1630367581, + 1976096277, + 1976096277, + 1630367581, + 1048472752, + 407945973, + -111592100, + -391632617, + -410364051, + -238314605, + 1016842, + 186430074, + 246022883, + 177466223, + 36325780, + -98493180, + -164170214, + -140226571, + -51632586, + 49526391, + 112515259, + 111939634, + 56535904, + -19494592, + -76297844, + -88438179, + -55503153, + 765852, + 49816943, + 68348722, + 50900654, + 10411838, + -30354236, + -51221942, + -44270448, + -16291535, + 16334309, + 36907742, + 36729889, + 18446282, + -6653650, + -25307074, + -29109599, + -18080082, + 416694, + 16270621, + 22005565, + 16148404, + 3163072, + -9567041, + -15805952, + -13403823, + -4789915, + 4888176, + 10715348, + 10414911, + 5082409, + -1873772, + -6784025, + -7579808, + -4560874, + 144385, + 3942944, + 5143495, + 3636895, + 665601, + -2041972, + -3221327, + -2610303, + -880441, + 887517, + 1827799, + 1675228, + 764326, + -275836, + -907718, + -934316, + -512776, + 19107, + 366401, + 418611, + 253551, + 263930, + 422214, + 356506, + -3777, + -538186, + -945520, + -891325, + -232404, + 815825, + 1704108, + 1808324, + 817244, + -972299, + -2672712, + -3207864, + -1941172, + 814318, + 3755206, + 5153095, + 3813344, + -77962, + -4763972, + -7639609, + -6636140, + -1563746, + 5404655, + 10563775, + 10572194, + 4483179, + -5268869, + -13693166, + -15706804, + -9071483, + 3835888, + 16641967, + 22009490, + 15706308, + -481801, + -18852506, + -29298603, + -24719522, + -5509175, + 19580591, + 37211789, + 36373204, + 14942435, + -17875856, + -45182118, + -50855839, + -28741226, + 12536028, + 52413262, + 68317454, + 48048058, + -1987432, + -57833111, + -88979341, + -74494565, + -16023247, + 59970069, + 113403634, + 110888515, + 45242484, + -56589856, + -143177136, + -163102781, + -93282266, + 43523456, + 182972236, + 246337817, + 180147091, + -9984423, + -249091193, + -414644248, + -384445637, + -91691727, + 436975377, + 1079037354, + 1653409427, + 1984394995, + 1966991816, + 1606776744, + 1017774881, + 379203192, + -130930084, + -398208709, + -405640837, + -227386117, + 11885818, + 192413767, + 245405832, + 171791099, + 29145838, + -103538693, + -165025276, + -137124026, + -46647210, + 53718547, + 113990955, + 110346206, + 53053899, + -22919356, + -77994760, + -87790345, + -53118552, + 3501249, + 51512984, + 68294685, + 49333846, + 8287587, + -31919615, + -51521981, + -43309179, + -14696647, + 17697208, + 37392921, + 36205195, + 17296143, + -7782500, + -25859235, + -28885482, + -17290188, + 1308643, + 16810761, + 21974154, + 15638099, + 2491082, + -10047042, + -15884578, + -13099852, + -4308608, + 5283898, + 10843923, + 10254175, + 4756438, + -2178827, + -6922098, + -7510990, + -4353865, + 364487, + 4066330, + 5127483, + 3515170, + 517582, + -2139102, + -3230542, + -2545278, + -788543, + 955789, + 1844676, + 1644570, + 712555, + -318271, + -922667, + -922060, + -487126, + 41534, + 375588, + 414498, + 243064, + 274181, + 425291, + 345905, + -27094, + -563316, + -955640, + -873487, + -188020, + 866979, + 1731150, + 1786241, + 745039, + -1063998, + -2732392, + -3190123, + -1836792, + 963546, + 3869914, + 5156210, + 3677636, + -302289, + -4962864, + -7690237, + -6478547, + -1249102, + 5722734, + 10700479, + 10414527, + 4069347, + -5744844, + -13967406, + -15587109, + -8560881, + 4508686, + 17118046, + 21985734, + 15118371, + -1385752, + -19606370, + -29452025, + -24097089, + -4350415, + 20697541, + 37650021, + 35789669, + 13523153, + -19447552, + -46042738, + -50423728, + -27082316, + 14657492, + 53869444, + 68200398, + 46208093, + -4755272, + -60105174, + -89412483, + -72586494, + -12509349, + 63351801, + 114735514, + 109111704, + 40871495, + -61512665, + -145970913, + -161822609, + -87910991, + 50730184, + 188300816, + 246347199, + 173569119, + -21106423, + -259701133, + -418469669, + -376644718, + -71237253, + 466273676, + 1109447489, + 1675885364, + 1991881736, + 1957088449, + 1582654203, + 986964948, + 350764418, + -149697927, + -404177470, + -400486650, + -216320456, + 22611234, + 198094257, + 244490417, + 165955310, + 21992216, + -108414006, + -165668590, + -133874458, + -41640067, + 57814429, + 115314813, + 108626184, + 49528679, + -26293595, + -79583880, + -87037309, + -50682609, + 6215468, + 53134515, + 68155930, + 47715116, + 6165920, + -33435702, + -51755986, + -42299811, + -13093245, + 19029606, + 37828440, + 35638632, + 16131711, + -8894412, + -26375542, + -28626762, + -16483930, + 2192971, + 17326216, + 21915486, + 15111811, + 1820759, + -10510995, + -15942734, + -12781746, + -3825572, + 5669916, + 10957870, + 10081864, + 4427186, + -2478565, + -7050267, + -7433321, + -4143243, + 582083, + 4183403, + 5105144, + 3390220, + 370443, + -2232474, + -3235544, + -2477750, + -696725, + 1021996, + 1858963, + 1612199, + 660585, + -359667, + -936173, + -908787, + -461276, + 63480, + 384068, + 409892, + 232487, + 284285, + 427826, + 334598, + -50818, + -588127, + -964645, + -854208, + -142730, + 917715, + 1756291, + 1761548, + 670972, + -1155415, + -2789235, + -3168080, + -1728930, + 1113098, + 3980836, + 5152772, + 3535937, + -528328, + -5157255, + -7731545, + -6311363, + -930202, + 6036206, + 10824751, + 10242431, + 3647139, + -6217212, + -14226080, + -15446866, + -8035775, + 5180615, + 17575918, + 21934136, + 14507391, + -2294056, + -20340599, + -29569437, + -23440333, + -3178737, + 21795617, + 38043757, + 35157565, + 12078076, + -21004574, + -46850914, + -49925746, + -25379307, + 16773556, + 55267030, + 67997175, + 44298914, + -7534297, + -62316142, + -89736384, + -70575345, + -8957003, + 66676541, + 115932725, + 107185997, + 36418231, + -66394659, + -148603248, + -160329584, + -82384629, + 57937198, + 193443777, + 246047920, + 166700847, + -32337338, + -270129675, + -421828854, + -368227321, + -50237497, + 495822821, + 1139681985, + 1697778862, + 1998550872, + 1946393609, + 1558017604, + 956064148, + 322646683, + -167888411, + -409542959, + -394913809, + -205132316, + 33182101, + 203468017, + 243280703, + 159967413, + 14873395, + -113114561, + -166101027, + -130482966, + -36617480, + 61809661, + 116486237, + 106782541, + 45964888, + -29613451, + -81063916, + -86180664, + -48198668, + 8905265, + 54679976, + 67933144, + 46046797, + 4049465, + -34900906, + -51924065, + -41243899, + -11483385, + 20330030, + 38214066, + 35031171, + 14954533, + -9988104, + -26855579, + -28333987, + -15662425, + 3068621, + 17816506, + 21829822, + 14570312, + 1152932, + -10958431, + -15980497, + -12450011, + -3341429, + 6045819, + 11057162, + 9898289, + 4095094, + -2772652, + -7168457, + -7346978, + -3929309, + 796922, + 4294074, + 5076567, + 3262238, + 224363, + -2322009, + -3236372, + -2407834, + -605107, + 1086076, + 1870676, + 1578180, + 608487, + -399984, + -948240, + -894530, + -435265, + 84924, + 391843, + 404811, + 221840, + 294223, + 429803, + 322588, + -74922, + -612578, + -972504, + -833491, + -96582, + 967959, + 1779474, + 1734244, + 595119, + -1246426, + -2843135, + -3141717, + -1617689, + 1262783, + 4087789, + 5142720, + 3388373, + -755803, + -5346857, + -7763398, + -6134719, + -607418, + 6344634, + 10936333, + 10056012, + 3217025, + -6685346, + -14468745, + -15286101, + -7496723, + 5850817, + 18014875, + 21854568, + 13873982, + -3205594, + -21054139, + -29650457, + -22749859, + -1995535, + 22873315, + 38392222, + 34477383, + 10608861, + -22544874, + -47605310, + -49362115, + -23634064, + 18881535, + 56603912, + 67707513, + 42322485, + -10321099, + -64462871, + -89949951, + -68462970, + -5370390, + 69939770, + 116992869, + 105112761, + 31887638, + -71229483, + -151069649, + -158623851, + -76708687, + 65135653, + 198393078, + 245437205, + 159547347, + -43665088, + -280362073, + -424710660, + -359191427, + -28701799, + 525604447, + 1169719715, + 1719073795, + 2004397387, + 1934915316, + 1532884932, + 925093649, + 294866654, + -185494863, + -414309728, + -388934893, + -193836340, + 43587733, + 208531909, + 241781058, + 153836072, + 7797744, + -117636049, + -166323711, + -126954783, + -31585744, + 65700023, + 117504819, + 104818379, + 42367191, + -32875160, + -82433723, + -85222120, + -45670110, + 11567447, + 56147907, + 67627117, + 44331266, + 1940827, + -36313709, + -52026411, + -40143043, + -9869114, + 21597053, + 38549626, + 34383828, + 13766162, + -11062323, + -27298982, + -28007749, + -14826805, + 3934553, + 18281187, + 21717456, + 14014387, + 488423, + -11388907, + -15997968, + -12105166, + -2856798, + 6411212, + 11141790, + 9703774, + 3760607, + -3060763, + -7276602, + -7252148, + -3712364, + 1008754, + 4398261, + 5041850, + 3131416, + 79519, + -2407632, + -3233070, + -2335649, + -513804, + 1147972, + 1879831, + 1542580, + 556332, + -439184, + -958874, + -879324, + -409132, + 105843, + 398915, + 399272, + 211141, + 303975, + 431207, + 309880, + -99380, + -636628, + -979187, + -811344, + -49627, + 1017636, + 1800642, + 1704331, + 517558, + -1336907, + -2893987, + -3111021, + -1503177, + 1412409, + 4190597, + 5126004, + 3235078, + -984436, + -5531383, + -7785672, + -5948760, + -281129, + 6647583, + 11034980, + 9855392, + 2779491, + -7148621, + -14694971, + -15104869, + -6944307, + 6518434, + 18434229, + 21746938, + 13218791, + -4119240, + -21745950, + -29694742, + -22026318, + -802223, + 23929152, + 38694693, + 33749677, + 9117203, + -24066416, + -48304649, + -48733140, + -21848518, + 20978738, + 57878045, + 67331243, + 40280864, + -13112244, + -66542277, + -90052221, + -66251357, + -1753760, + 73137017, + 117913701, + 102893549, + 27284787, + -76010799, + -153365796, + -156705817, + -70888896, + 72316640, + 203140834, + 244512613, + 152114075, + -55077343, + -290383610, + -427104267, + -349535543, + -6640024, + 555599895, + 1199539614, + 1739754449, + 2009416884, + 1922662174, + 1507274497, + 894074574, + 267440615, + -202511152, + -418482814, + -382562723, + -182447110, + 53817743, + 213283184, + 239996148, + 147570038, + 773507, + -121974408, + -166338006, + -123295270, + -26551122, + 69481452, + 118370343, + 102736929, + 38740263, + -36075053, + -83692296, + -84163503, + -43100352, + 14198874, + 57536958, + 67238734, + 42570946, + -157414, + -37672670, + -52063297, + -38998893, + -8252475, + 22829298, + 38835013, + 33697661, + 12568156, + -12115849, + -27705430, + -27648673, + -13978209, + 4789747, + 18719851, + 21578712, + 13444838, + -171957, + -11802005, + -15995276, + -11747744, + -2372292, + 6765714, + 11211762, + 9498652, + 3424167, + -3342585, + -7374653, + -7149024, + -3492712, + 1217337, + 4495895, + 5001096, + 2997953, + -63916, + -2489276, + -3225689, + -2261314, + -422932, + 1207630, + 1886450, + 1505465, + 504189, + -477230, + -968082, + -863207, + -382916, + 126219, + 405288, + 393294, + 200407, + 313520, + 432025, + 296478, + -124163, + -660237, + -984667, + -787773, + -1915, + 1066672, + 1819741, + 1671817, + 438370, + -1426734, + -2941690, + -3075983, + -1385508, + 1561782, + 4289085, + 5102579, + 3076193, + -1213944, + -5710550, + -7798254, + -5753642, + 48279, + 6944621, + 11120461, + 9640715, + 2335035, + -7606410, + -14904350, + -14903247, + -6379131, + 7182600, + 18833313, + 21611187, + 12542498, + -5033853, + -22415018, + -29701998, + -21270406, + 399760, + 24961659, + 38950500, + 32975066, + 7604837, + -25567173, + -48947714, + -48039210, + -20024661, + 23062470, + 59087448, + 66868307, + 38176205, + -15904267, + -68551341, + -90042366, + -63942633, + 1888573, + 76263863, + 118693134, + 100530111, + 22614878, + -80732284, + -155487542, + -154576147, + -64931210, + 79471192, + 207679327, + 243272051, + 144406866, + -66561535, + -300179605, + -428999197, + -339258704, + 15937455, + 585790223, + 1229120698, + 1759805544, + 2013605585, + 1909643360, + 1481204920, + 863027979, + 240384460, + -218931696, + -422067731, + -375810355, + -170979132, + 63862060, + 217719480, + 237930927, + 141178145, + -6191200, + -126125832, + -166145521, + -119509908, + -21519833, + 73150044, + 119082782, + 100541547, + 35088785, + -39209559, + -84838777, + -83006752, + -40492842, + 16796464, + 58845881, + 66768981, + 40768302, + -2242707, + -38976421, + -52035075, + -37813141, + -6635502, + 24025442, + 39070182, + 32973773, + 11362072, + -13147498, + -28074655, + -27257425, + -13117786, + 5633203, + 19132124, + 21413948, + 12862473, + -827407, + -12197331, + -15972572, + -11378290, + -1888522, + 7108964, + 11267107, + 9283269, + 3086217, + -3617812, + -7462572, + -7037812, + -3270656, + 1422437, + 4586913, + 4954418, + 2862044, + -205773, + -2566877, + -3214284, + -2184949, + -332603, + 1264999, + 1890555, + 1466906, + 452129, + -514087, + -975874, + -846214, + -356653, + 146031, + 410967, + 386894, + 189657, + 322840, + 432242, + 282389, + -149241, + -683364, + -988916, + -762791, + 46499, + 1114994, + 1836716, + 1636712, + 357640, + -1515780, + -2986146, + -3036603, + -1264801, + 1710706, + 4383081, + 5072411, + 2911872, + -1444041, + -5884080, + -7801043, + -5549536, + 380411, + 7235321, + 11192562, + 9412142, + 1884167, + -8058090, + -15096490, + -14681342, + -5801817, + 7842453, + 19211481, + 21447294, + 11845812, + -5948287, + -23060347, + -29671971, + -20482868, + 1608958, + 25969389, + 39159027, + 32154229, + 6073534, + -27045133, + -49533354, + -47280798, + -18164547, + 25130038, + 60230212, + 66318752, + 36010753, + -18693683, + -70487114, + -89919688, + -61539058, + 5552234, + 79315946, + 119329241, + 98024381, + 17883228, + -85387644, + -157430920, + -152235770, + -58841798, + 86590296, + 212001016, + 241713773, + 136431936, + -78104870, + -309735431, + -430385323, + -328360478, + 39019755, + 616156222, + 1258442085, + 1779212239, + 2016960336, + 1895868616, + 1454695110, + 831974841, + 213713679, + -234751459, + -425070464, + -368691058, + -159446820, + 73710932, + 221838820, + 235590630, + 134669299, + -13088403, + -130086768, + -165748100, + -115604288, + -16498050, + 76702064, + 119642297, + 98235703, + 31417437, + -42275212, + -85872452, + -81753914, + -37851051, + 19357196, + 60073537, + 66218936, + 38925834, + -4312532, + -40223673, + -51942177, + -36587521, + -5020213, + 25184215, + 39255154, + 32213305, + 10149472, + -14156117, + -28406435, + -26834705, + -12246694, + 6463941, + 19517668, + 21223548, + 12268114, + -1477139, + -12574516, + -15930031, + -10997357, + -1406092, + 7440616, + 11307870, + 9057980, + 2747196, + -3886153, + -7540335, + -6918724, + -3046499, + 1623825, + 4671262, + 4901932, + 2723888, + -345886, + -2640379, + -3198912, + -2106675, + -242928, + 1320032, + 1892173, + 1426972, + 400219, + -549725, + -982260, + -828384, + -330382, + 165264, + 415956, + 380093, + 178908, + 331915, + 431846, + 267619, + -174583, + -705969, + -991911, + -736410, + 95561, + 1162525, + 1851519, + 1599028, + 275455, + -1603921, + -3027261, + -2992883, + -1141182, + 1858982, + 4472421, + 5035473, + 2742272, + -1674435, + -6051701, + -7793948, + -5336626, + 714866, + 7519260, + 11251083, + 9169854, + 1427412, + -8503043, + -15271018, + -14439285, + -5213009, + 8497125, + 19568108, + 21255272, + 11129476, + -6861386, + -23680966, + -29604456, + -19664490, + 2823893, + 26950917, + 39319715, + 31287911, + 4525102, + -28498298, + -50060480, + -46458460, + -16270285, + 27178752, + 61304499, + 65682737, + 33786842, + -21476987, + -72346718, + -89683630, + -59043023, + 9232794, + 82288969, + 119820260, + 95378485, + 13095268, + -89970620, + -159192155, + -149685878, + -52627039, + 93664901, + 216098545, + 239836388, + 128195874, + -89694334, + -319036532, + -431252882, + -316840972, + 62595492, + 646678433, + 1287483005, + 1797960154, + 2019478613, + 1881348240, + 1427764257, + 800936034, + 187443345, + -249965956, + -427497456, + -361218304, + -147864483, + 83354936, + 225639614, + 232980762, + 128052462, + -19910275, + -133853922, + -165147822, + -111584109, + -11491889, + 80133942, + 120049235, + 95822983, + 27730896, + -45268654, + -86792749, + -80407143, + -35178474, + 21878112, + 61218895, + 65589773, + 37046080, + -6364406, + -41413214, + -51785114, + -35323806, + -3408616, + 26304400, + 39390008, + 31417438, + 8931913, + -15140593, + -28700597, + -26381249, + -11366095, + 7281007, + 19876182, + 21007931, + 11662592, + -2120377, + -12933217, + -15867854, + -10605513, + -925598, + 7760343, + 11334116, + 8823149, + 2407541, + -4147325, + -7607932, + -6791981, + -2820547, + 1821278, + 4748897, + 4843763, + 2583686, + -484093, + -2709731, + -3179638, + -2026617, + -154017, + 1372687, + 1891334, + 1385735, + 348525, + -584114, + -987254, + -809753, + -304139, + 183899, + 420263, + 372908, + 168178, + 340724, + 430824, + 252177, + -200159, + -728012, + -993625, + -708645, + 145212, + 1209192, + 1864100, + 1558785, + 191907, + -1691029, + -3064943, + -2944834, + -1014778, + 2006413, + 4556941, + 4991746, + 2567563, + -1904836, + -6213144, + -7776893, + -5115107, + 1051237, + 7796021, + 11295839, + 8914051, + 965304, + -8940652, + -15427581, + -14177235, + -4613369, + 9145753, + 19902592, + 21035168, + 10394258, + -7771990, + -24275930, + -29499294, + -18816103, + 4043074, + 27904842, + 39432061, + 30376916, + 2961379, + -29924691, + -50528071, + -45572838, + -14344043, + 29205930, + 62308543, + 64960527, + 31506896, + -24250663, + -74127355, + -89333768, + -56457051, + 12925775, + 85178705, + 120164595, + 92594737, + 8256538, + -94474995, + -160767661, + -146927929, + -46293516, + 100685932, + 219964758, + 237638866, + 119705639, + -101316711, + -328068432, + -431592487, + -304700832, + 86652793, + 677337162, + 1316222828, + 1816035377, + 2021158519, + 1866093081, + 1400431804, + 769932316, + 161588105, + -264571251, + -429355604, + -353405755, + -136246316, + 92784982, + 229120653, + 230107095, + 121336645, + -26649145, + -137424258, + -164346997, + -107455166, + -6507404, + 83442282, + 120304128, + 93307080, + 24033824, + -48186634, + -87599242, + -78968698, + -32478620, + 24356322, + 62281032, + 64882756, + 35131605, + -8395879, + -42543913, + -51564472, + -34023805, + -1802699, + 27384836, + 39474890, + 30587389, + 7710948, + -16099849, + -28957016, + -25897826, + -10477155, + 8083466, + 20207400, + 20767539, + 11046746, + -2756359, + -13273118, + -15786263, + -10203332, + -447634, + 8067833, + 11345928, + 8579151, + 2067689, + -4401059, + -7665364, + -6657812, + -2593103, + 2014582, + 4819785, + 4780040, + 2441637, + -620237, + -2774888, + -3156530, + -1944898, + -65974, + 1422923, + 1888071, + 1343265, + 297114, + -617224, + -990870, + -790362, + -277961, + 201921, + 423894, + 365359, + 157482, + 349247, + 429165, + 236073, + -225936, + -749451, + -994037, + -679512, + 195395, + 1254920, + 1874414, + 1516003, + 107087, + -1776979, + -3099104, + -2892469, + -885726, + 2152800, + 4636485, + 4941222, + 2387921, + -2134946, + -6368146, + -7749810, + -4885190, + 1389111, + 8065192, + 11326663, + 8644952, + 498388, + -9370306, + -15565847, + -13895378, + -4003579, + 9787472, + 20214356, + 20787068, + 9640961, + -8678932, + -24844318, + -29356369, + -17938582, + 5264992, + 28829789, + 39495620, + 29422111, + 1384234, + -31322357, + -50935177, + -44624655, + -12388039, + 31208901, + 63240658, + 64152498, + 29173421, + -27011183, + -75826305, + -88869821, + -53783791, + 16626654, + 87981002, + 120360823, + 89675634, + 3372676, + -98894605, + -162154054, + -143963642, + -39848013, + 107644297, + 223592705, + 235120540, + 110968558, + -112958590, + -336816756, + -431395141, + -291941249, + 111179297, + 708112494, + 1344641075, + 1833424479, + 2021998788, + 1850114523, + 1372717440, + 738984313, + 136162169, + -278563960, + -430652242, + -345267242, + -124606378, + 101992324, + 232281111, + 226975652, + 114530898, + -33297503, + -140795002, + -163348156, + -103223342, + -1550580, + 86623861, + 120407692, + 90691788, + 20330869, + -51026020, + -88291646, + -77440934, + -29755013, + 26789007, + 63259135, + 64099238, + 33185006, + -10404545, + -43614716, + -51280914, + -32689364, + -204433, + 28424422, + 39510006, + 29724411, + 6488128, + -17032845, + -29175616, + -25385237, + -9581044, + 8870412, + 20511093, + 20502848, + 10421422, + -3384336, + -13593926, + -15685505, + -9791399, + 27220, + 8362794, + 11343404, + 8326368, + 1728069, + -4647096, + -7712648, + -6516452, + -2364469, + 2203530, + 4883899, + 4710900, + 2297941, + -754164, + -2835812, + -3129659, + -1861644, + 21094, + 1470706, + 1882418, + 1299636, + 246050, + -649031, + -993125, + -770248, + -251881, + 219317, + 426859, + 357465, + 146838 + +}; + +static const struct src_stage src_int32_21_80_3968_5000 = { + 19, 5, 21, 160, 3360, 80, 21, 0, 2, + src_int32_21_80_3968_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_8_2160_5000.h b/src/audio/src/coef/src_ipc4_int32_21_8_2160_5000.h new file mode 100644 index 000000000000..4ef8945f6c8c --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_8_2160_5000.h @@ -0,0 +1,438 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_8_2160_5000_fir[420] = { + -42589, + 944576, + -2937872, + 172094, + 18043710, + -46596342, + 41082649, + 63773178, + -284701631, + 546503680, + 1536724447, + 476081165, + -282339868, + 76876325, + 31526227, + -43932167, + 18854108, + -887934, + -2533611, + 891007, + -38985, + 987667, + -3341738, + 1325274, + 16928845, + -48825950, + 50676720, + 49118454, + -283666025, + 617799522, + 1530574494, + 406972210, + -276813893, + 88357327, + 22121549, + -40892752, + 19370227, + -1847722, + -2135093, + 829280, + -31627, + 1017881, + -3738465, + 2562501, + 15502951, + -50563886, + 60187452, + 33005463, + -279021541, + 689511580, + 1518321494, + 339596549, + -268375507, + 98168063, + 12974759, + -37538763, + 19605515, + -2702148, + -1747797, + 761600, + -19975, + 1032782, + -4120753, + 3872641, + 13763433, + -51756192, + 69488150, + 15550309, + -270581170, + 761169698, + 1500058813, + 274350061, + -257292061, + 106282318, + 4183155, + -33931334, + 19576283, + -3447990, + -1376513, + 690027, + -3527, + 1029940, + -4480828, + 5242548, + 11711964, + -52352970, + 78447744, + -3108327, + -258185092, + 832294689, + 1475925378, + 211601689, + -243843279, + 112695022, + -4165562, + -30131246, + 19301302, + -4083831, + -1025330, + 616456, + 18162, + 1006979, + -4810528, + 6657109, + 9354744, + -52309306, + 86932240, + -22809669, + -241703149, + 902402500, + 1446104362, + 151690680, + -228318065, + 117421279, + -11993879, + -26198154, + 18801385, + -4609944, + -697625, + 542595, + 45461, + 961635, + -5101411, + 8099331, + 6702712, + -51586170, + 94806274, + -43371602, + -221037076, + 971008463, + 1410821430, + 94924161, + -211011300, + 120495208, + -19234903, + -22189874, + 18098964, + -5028163, + -396076, + 469950, + 78644, + 891810, + -5344866, + 9550453, + 3771696, + -50151281, + 101934773, + -64591700, + -196122471, + 1037631616, + 1370342600, + 41575067, + -192220692, + 121968619, + -25832646, + -18161724, + 17217680, + -5341735, + -122679, + 399822, + 117870, + 795631, + -5532249, + 10990108, + 582507, + -47979938, + 108184685, + -86248527, + -166930457, + 1101799027, + 1324971715, + -8119551, + -172243686, + 121909539, + -31742148, + -14165951, + 16181968, + -5555164, + 121225, + 333301, + 163162, + 671512, + -5655023, + 12396506, + -2839036, + -45055788, + 113426774, + -108103200, + -133469025, + 1163050093, + 1275047576, + -53959834, + -151374487, + 120400621, + -36929467, + -10251212, + 15016672, + -5674048, + 334908, + 271267, + 214394, + 518215, + -5704909, + 13746666, + -6462150, + -41371517, + 117537450, + -129901211, + -95784031, + 1220940750, + 1220940750, + -95784031, + -129901211, + 117537450, + -41371517, + -6462150, + 13746666, + -5704909, + 518215, + 214394, + 271267, + 334908, + -5674048, + 15016672, + -10251212, + -36929467, + 120400621, + -151374487, + -53959834, + 1275047576, + 1163050093, + -133469025, + -108103200, + 113426774, + -45055788, + -2839036, + 12396506, + -5655023, + 671512, + 163162, + 333301, + 121225, + -5555164, + 16181968, + -14165951, + -31742148, + 121909539, + -172243686, + -8119551, + 1324971715, + 1101799027, + -166930457, + -86248527, + 108184685, + -47979938, + 582507, + 10990108, + -5532249, + 795631, + 117870, + 399822, + -122679, + -5341735, + 17217680, + -18161724, + -25832646, + 121968619, + -192220692, + 41575067, + 1370342600, + 1037631616, + -196122471, + -64591700, + 101934773, + -50151281, + 3771696, + 9550453, + -5344866, + 891810, + 78644, + 469950, + -396076, + -5028163, + 18098964, + -22189874, + -19234903, + 120495208, + -211011300, + 94924161, + 1410821430, + 971008463, + -221037076, + -43371602, + 94806274, + -51586170, + 6702712, + 8099331, + -5101411, + 961635, + 45461, + 542595, + -697625, + -4609944, + 18801385, + -26198154, + -11993879, + 117421279, + -228318065, + 151690680, + 1446104362, + 902402500, + -241703149, + -22809669, + 86932240, + -52309306, + 9354744, + 6657109, + -4810528, + 1006979, + 18162, + 616456, + -1025330, + -4083831, + 19301302, + -30131246, + -4165562, + 112695022, + -243843279, + 211601689, + 1475925378, + 832294689, + -258185092, + -3108327, + 78447744, + -52352970, + 11711964, + 5242548, + -4480828, + 1029940, + -3527, + 690027, + -1376513, + -3447990, + 19576283, + -33931334, + 4183155, + 106282318, + -257292061, + 274350061, + 1500058813, + 761169698, + -270581170, + 15550309, + 69488150, + -51756192, + 13763433, + 3872641, + -4120753, + 1032782, + -19975, + 761600, + -1747797, + -2702148, + 19605515, + -37538763, + 12974759, + 98168063, + -268375507, + 339596549, + 1518321494, + 689511580, + -279021541, + 33005463, + 60187452, + -50563886, + 15502951, + 2562501, + -3738465, + 1017881, + -31627, + 829280, + -2135093, + -1847722, + 19370227, + -40892752, + 22121549, + 88357327, + -276813893, + 406972210, + 1530574494, + 617799522, + -283666025, + 49118454, + 50676720, + -48825950, + 16928845, + 1325274, + -3341738, + 987667, + -38985, + 891007, + -2533611, + -887934, + 18854108, + -43932167, + 31526227, + 76876325, + -282339868, + 476081165, + 1536724447, + 546503680, + -284701631, + 63773178, + 41082649, + -46596342, + 18043710, + 172094, + -2937872, + 944576, + -42589 + +}; + +static const struct src_stage src_int32_21_8_2160_5000 = { + 3, 8, 21, 20, 420, 8, 21, 0, 0, + src_int32_21_8_2160_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_8_3239_5000.h b/src/audio/src/coef/src_ipc4_int32_21_8_3239_5000.h new file mode 100644 index 000000000000..789b2b69d84c --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_8_3239_5000.h @@ -0,0 +1,690 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_8_3239_5000_fir[672] = { + -35144, + 303498, + -963439, + 1770481, + -1694226, + -1024852, + 7961456, + -18779506, + 29468078, + -31833030, + 15328989, + 28779751, + -102480136, + 197980256, + -299600475, + 397977985, + 1768219326, + 310049911, + -274189842, + 196131920, + -110388490, + 38770059, + 7339362, + -27230094, + 27868117, + -19017331, + 8878063, + -1879482, + -1174317, + 1552693, + -910732, + 303788, + -30206, + 296917, + -1003274, + 1973326, + -2217383, + -108049, + 6872612, + -18230386, + 30661906, + -36101519, + 23358911, + 17987124, + -92672451, + 196791860, + -321682140, + 488755921, + 1759153100, + 225626328, + -245980137, + 191395006, + -116345468, + 47833511, + -489310, + -22375240, + 25902042, + -18952870, + 9615790, + -2661495, + -665855, + 1324552, + -847084, + 298415, + -23132, + 283495, + -1028397, + 2156600, + -2735052, + 858895, + 5621340, + -17365673, + 31414597, + -39955384, + 31303629, + 6533581, + -81048619, + 192457901, + -339922602, + 581685064, + 1741105818, + 145311493, + -215511974, + 183953492, + -120329881, + 55863762, + -8042903, + -17351987, + 23614073, + -18599518, + 10171130, + -3362136, + -176394, + 1090529, + -774480, + 288063, + -13802, + 262774, + -1037106, + 2315714, + -3238087, + 1862482, + 4220596, + -16186052, + 31696926, + -43318174, + 39034623, + -5424245, + -67722777, + 184911940, + -353834169, + 676029678, + 1714246852, + 69653621, + -183329795, + 174023297, + -122350672, + 62773674, + -15215359, + -12243512, + 21051783, + -17974661, + 10543627, + -3974392, + 287248, + 854909, + -694913, + 273455, + -2146, + 234413, + -1027879, + 2446209, + -3717063, + 2887903, + 2686406, + -14697378, + 31486133, + -46118523, + 46422288, + -17716416, + -52839370, + 174132504, + -362960454, + 771024421, + 1678827849, + -860050, + -149975106, + 161848093, + -122445778, + 68496004, + -21910047, + -7131371, + 18265225, + -17099246, + 10735755, + -4493029, + 719061, + 621724, + -610351, + 255332, + 11849, + 198201, + -999417, + 2543847, + -4162433, + 3919235, + 1037736, + -12910797, + 30766550, + -48291475, + 53337947, + -30161890, + -36572016, + 160145117, + -366882889, + 865882254, + 1635179873, + -65807410, + -115979923, + 147694857, + -120680598, + 72983773, + -28040936, + -2094288, + 15306057, + -15997301, + 10752743, + -4914586, + 1113904, + 394703, + -522701, + 234439, + 28136, + 154074, + -950688, + 2604699, + -4564685, + 4939646, + -703693, + -10842777, + 29530113, + -49779758, + 59655923, + -42570957, + -19121905, + 143023752, + -365226943, + 959802693, + 1583709653, + -124834800, + -81860523, + 131849263, + -117146107, + 76210310, + -33533557, + 2792969, + 12226667, + -14695430, + 10602371, + -5237344, + 1467538, + 177221, + -433774, + 211506, + 46596, + 102131, + -880964, + 2625237, + -4914512, + 5931645, + -2513645, + -8515053, + 27776787, + -50534970, + 65255626, + -54747896, + -715732, + 122891657, + -357667918, + 1051980312, + 1524894974, + -177659472, + -48111552, + 114610946, + -111956655, + 78168995, + -38325767, + 7460614, + 9079324, + -13222282, + 10294733, + -5461272, + 1776651, + -27733, + -345265, + 187235, + 67042, + 42646, + -789862, + 2602427, + -5202987, + 6877347, + -4365663, + -5954483, + 25514865, + -50518673, + 70023635, + -66493811, + 18396829, + 99921537, + -343936271, + 1141613388, + 1459279283, + -224071184, + -15200576, + 96288735, + -105247491, + 78872700, + -42368292, + 11844753, + 5915360, + -11608018, + 9841963, + -5587940, + 2038860, + -217587, + -258725, + 162290, + 89209, + -23924, + -677370, + 2533812, + -5421737, + 7758753, + -6231413, + -3192818, + 22761145, + -49703355, + 73855729, + -77609611, + 37946063, + 74335061, + -323822374, + 1227912592, + 1387465571, + -263932902, + 16436872, + 77195912, + -97172055, + 78352954, + -45625049, + 15888168, + 2784397, + -9883763, + 9257956, + -5620412, + 2252699, + -390200, + -175543, + 137281, + 112760, + -96933, + -543878, + 2417592, + -5563124, + 8558057, + -8081072, + -266369, + 19540977, + -48073260, + 76658852, + -87899088, + 57645559, + 46401700, + -297180629, + 1310109603, + 1310109603, + -297180629, + 46401700, + 57645559, + -87899088, + 76658852, + -48073260, + 19540977, + -266369, + -8081072, + 8558057, + -5563124, + 2417592, + -543878, + -96933, + 112760, + 137281, + -175543, + -390200, + 2252699, + -5620412, + 9257956, + -9883763, + 2784397, + 15888168, + -45625049, + 78352954, + -97172055, + 77195912, + 16436872, + -263932902, + 1387465571, + 1227912592, + -323822374, + 74335061, + 37946063, + -77609611, + 73855729, + -49703355, + 22761145, + -3192818, + -6231413, + 7758753, + -5421737, + 2533812, + -677370, + -23924, + 89209, + 162290, + -258725, + -217587, + 2038860, + -5587940, + 9841963, + -11608018, + 5915360, + 11844753, + -42368292, + 78872700, + -105247491, + 96288735, + -15200576, + -224071184, + 1459279283, + 1141613388, + -343936271, + 99921537, + 18396829, + -66493811, + 70023635, + -50518673, + 25514865, + -5954483, + -4365663, + 6877347, + -5202987, + 2602427, + -789862, + 42646, + 67042, + 187235, + -345265, + -27733, + 1776651, + -5461272, + 10294733, + -13222282, + 9079324, + 7460614, + -38325767, + 78168995, + -111956655, + 114610946, + -48111552, + -177659472, + 1524894974, + 1051980312, + -357667918, + 122891657, + -715732, + -54747896, + 65255626, + -50534970, + 27776787, + -8515053, + -2513645, + 5931645, + -4914512, + 2625237, + -880964, + 102131, + 46596, + 211506, + -433774, + 177221, + 1467538, + -5237344, + 10602371, + -14695430, + 12226667, + 2792969, + -33533557, + 76210310, + -117146107, + 131849263, + -81860523, + -124834800, + 1583709653, + 959802693, + -365226943, + 143023752, + -19121905, + -42570957, + 59655923, + -49779758, + 29530113, + -10842777, + -703693, + 4939646, + -4564685, + 2604699, + -950688, + 154074, + 28136, + 234439, + -522701, + 394703, + 1113904, + -4914586, + 10752743, + -15997301, + 15306057, + -2094288, + -28040936, + 72983773, + -120680598, + 147694857, + -115979923, + -65807410, + 1635179873, + 865882254, + -366882889, + 160145117, + -36572016, + -30161890, + 53337947, + -48291475, + 30766550, + -12910797, + 1037736, + 3919235, + -4162433, + 2543847, + -999417, + 198201, + 11849, + 255332, + -610351, + 621724, + 719061, + -4493029, + 10735755, + -17099246, + 18265225, + -7131371, + -21910047, + 68496004, + -122445778, + 161848093, + -149975106, + -860050, + 1678827849, + 771024421, + -362960454, + 174132504, + -52839370, + -17716416, + 46422288, + -46118523, + 31486133, + -14697378, + 2686406, + 2887903, + -3717063, + 2446209, + -1027879, + 234413, + -2146, + 273455, + -694913, + 854909, + 287248, + -3974392, + 10543627, + -17974661, + 21051783, + -12243512, + -15215359, + 62773674, + -122350672, + 174023297, + -183329795, + 69653621, + 1714246852, + 676029678, + -353834169, + 184911940, + -67722777, + -5424245, + 39034623, + -43318174, + 31696926, + -16186052, + 4220596, + 1862482, + -3238087, + 2315714, + -1037106, + 262774, + -13802, + 288063, + -774480, + 1090529, + -176394, + -3362136, + 10171130, + -18599518, + 23614073, + -17351987, + -8042903, + 55863762, + -120329881, + 183953492, + -215511974, + 145311493, + 1741105818, + 581685064, + -339922602, + 192457901, + -81048619, + 6533581, + 31303629, + -39955384, + 31414597, + -17365673, + 5621340, + 858895, + -2735052, + 2156600, + -1028397, + 283495, + -23132, + 298415, + -847084, + 1324552, + -665855, + -2661495, + 9615790, + -18952870, + 25902042, + -22375240, + -489310, + 47833511, + -116345468, + 191395006, + -245980137, + 225626328, + 1759153100, + 488755921, + -321682140, + 196791860, + -92672451, + 17987124, + 23358911, + -36101519, + 30661906, + -18230386, + 6872612, + -108049, + -2217383, + 1973326, + -1003274, + 296917, + -30206, + 303788, + -910732, + 1552693, + -1174317, + -1879482, + 8878063, + -19017331, + 27868117, + -27230094, + 7339362, + 38770059, + -110388490, + 196131920, + -274189842, + 310049911, + 1768219326, + 397977985, + -299600475, + 197980256, + -102480136, + 28779751, + 15328989, + -31833030, + 29468078, + -18779506, + 7961456, + -1024852, + -1694226, + 1770481, + -963439, + 303498, + -35144 + +}; + +static const struct src_stage src_int32_21_8_3239_5000 = { + 3, 8, 21, 32, 672, 8, 21, 0, 0, + src_int32_21_8_3239_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_21_8_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_21_8_4535_5000.h new file mode 100644 index 000000000000..5855a0713328 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_21_8_4535_5000.h @@ -0,0 +1,2454 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_8_4535_5000_fir[2436] = { + -16754, + 31637, + -52542, + 80059, + -114320, + 154831, + -200293, + 248450, + -295949, + 338254, + -369612, + 383088, + -370693, + 323599, + -232458, + 87825, + 119321, + -396971, + 751401, + -1186444, + 1702740, + -2296991, + 2961280, + -3682464, + 4441713, + -5214208, + 5969050, + -6669406, + 7272913, + -7732356, + 7996625, + -8011930, + 7723272, + -7076111, + 6018203, + -4501538, + 2484308, + 67161, + -3176606, + 6856227, + -11105381, + 15909636, + -21240282, + 27054338, + -33295159, + 39893669, + -46770341, + 53838028, + -61005875, + 68184764, + -75295221, + 82279858, + -89125326, + 95906891, + -102895316, + 110872786, + -122398922, + 150841995, + 2045910427, + 49778105, + -73609331, + 80220423, + -81809191, + 80911698, + -78435180, + 74826966, + -70367245, + 65265141, + -59695343, + 53813044, + -47759862, + 41665733, + -35648934, + 29815311, + -24257266, + 19052814, + -14264895, + 9941024, + -6113352, + 2799113, + -1476, + -2289272, + 4094241, + -5444230, + 6377866, + -6939658, + 7178050, + -7143532, + 6886877, + -6457551, + 5902344, + -5264244, + 4581578, + -3887415, + 3209241, + -2568868, + 1982569, + -1461405, + 1011696, + -635612, + 331840, + -96279, + -77253, + 196346, + -269378, + 304972, + -311534, + 296893, + -268032, + 230917, + -190409, + 150256, + -113141, + 80787, + -54086, + 33258, + -15053, + 29260, + -49824, + 77622, + -113144, + 156306, + -206268, + 261249, + -318363, + 373493, + -421215, + 454783, + -466199, + 446387, + -385448, + 273049, + -98900, + -146657, + 471975, + -883355, + 1384259, + -1974512, + 2649524, + -3399578, + 4209231, + -5056850, + 5914348, + -6747138, + 7514341, + -8169266, + 8660176, + -8931327, + 8924288, + -8579480, + 7837929, + -6643145, + 4943084, + -2692101, + -147182, + 3602201, + -7689044, + 12411442, + -17760248, + 23713537, + -30237464, + 37288063, + -44814270, + 52762605, + -61084306, + 69746423, + -78749906, + 88161328, + -98173894, + 109238961, + -122393451, + 140251331, + -171069852, + 259071224, + 2032046786, + -43248504, + -25621930, + 48933250, + -59591582, + 64585833, + -66345696, + 65976053, + -64085198, + 61063380, + -57193544, + 52700316, + -47773052, + 42576934, + -37258172, + 31946236, + -26754586, + 21780729, + -17106057, + 12795742, + -8898844, + 5448708, + -2463687, + -51813, + 2106004, + -3718138, + 4916746, + -5737767, + 6222621, + -6416312, + 6365600, + -6117331, + 5716940, + -5207176, + 4627082, + -4011224, + 3389180, + -2785284, + 2218591, + -1703052, + 1247858, + -857918, + 534437, + -275550, + 76985, + 67281, + -164410, + 222137, + -248286, + 250375, + -235298, + 209115, + -176913, + 142758, + -109701, + 79848, + -54468, + 34123, + -12919, + 26146, + -45945, + 73472, + -109566, + 154566, + -208110, + 268935, + -334686, + 401753, + -465150, + 518453, + -553822, + 562101, + -533037, + 455600, + -318424, + 110356, + 178887, + -557973, + 1033148, + -1607390, + 2279563, + -3043604, + 3887792, + -4794148, + 5737983, + -6687673, + 7604657, + -8443714, + 9153517, + -9677484, + 9954902, + -9922328, + 9515200, + -8669637, + 7324342, + -5422547, + 2913895, + 243829, + -4083242, + 8626300, + -13883777, + 19855453, + -26531239, + 33893526, + -41921249, + 50596408, + -59914435, + 69900988, + -80640415, + 92327260, + -105367725, + 120602290, + -139867556, + 167721361, + -218660312, + 373473462, + 2004488776, + -127496274, + 20696954, + 17642613, + -36710185, + 47281534, + -53122912, + 55925914, + -56593873, + 55680157, + -53564832, + 50534304, + -46819941, + 42617615, + -38097704, + 33410119, + -28686679, + 24042104, + -19574356, + 15364755, + -11478117, + 7963084, + -4852703, + 2165300, + 94369, + -1933705, + 3370647, + -4431903, + 5151095, + -5566873, + 5721087, + -5657044, + 5417925, + -5045392, + 4578419, + -4052366, + 3498300, + -2942568, + 2406603, + -1906945, + 1455444, + -1059624, + 723158, + -446431, + 227147, + -60948, + -57982, + 136349, + -181252, + 199750, + -198517, + 183587, + -160171, + 132568, + -104134, + 77315, + -53723, + 34246, + -10376, + 22329, + -40945, + 67639, + -103590, + 149558, + -205675, + 271228, + -344446, + 422302, + -500354, + 572635, + -631611, + 668236, + -672097, + 631680, + -534756, + 368884, + -122038, + -216671, + 656176, + -1202579, + 1858254, + -2620943, + 3482926, + -4430262, + 5442191, + -6490712, + 7540379, + -8548363, + 9464790, + -10233371, + 10792331, + -11075612, + 11014338, + -10538480, + 9578673, + -8068104, + 5944379, + -3151261, + -359841, + 4628792, + -9686221, + 15553808, + -22245666, + 29771228, + -38140308, + 47371420, + -57505305, + 68627363, + -80906437, + 94666181, + -110527538, + 129724740, + -154911149, + 192664710, + -264182141, + 492947958, + 1963572477, + -202361927, + 64547853, + -13039316, + -13634603, + 29363530, + -39050992, + 44896397, + -48060389, + 49238661, + -48895516, + 47370331, + -44929957, + 41795801, + -38158164, + 34183810, + -30019846, + 25795584, + -21623339, + 17598741, + -13800893, + 10292613, + -7120852, + 4317374, + -1899709, + -127634, + 1771720, + -3049562, + 3986363, + -4613701, + 4967712, + -5087326, + 5012629, + -4783373, + 4437686, + -4011011, + 3535274, + -3038293, + 2543434, + -2069470, + 1630653, + -1236944, + 894390, + -605594, + 370258, + -185758, + 47723, + 49405, + -111865, + 146130, + -158524, + 154937, + -140603, + 119967, + -96620, + 73294, + -51909, + 33659, + -7460, + 17861, + -34888, + 60191, + -95271, + 141300, + -198909, + 267955, + -347295, + 434555, + -525929, + 616030, + -697787, + 762440, + -799622, + 797561, + -743398, + 623638, + -424730, + 133762, + 260734, + -767896, + 1393589, + -2139448, + 3001936, + -3971475, + 5031681, + -6158771, + 7321154, + -8479278, + 9585738, + -10585683, + 11417513, + -12013881, + 12302960, + -12209956, + 11658793, + -10573906, + 8882059, + -6514054, + 3406212, + 498544, + -5250212, + 10892098, + -17462444, + 24997817, + -33539112, + 43141569, + -53891326, + 65933271, + -79519870, + 95102015, + -113512123, + 136373768, + -167156034, + 214492005, + -306636233, + 616299310, + 1909795890, + -267386149, + 105209079, + -42530395, + 9172772, + 11201637, + -24426292, + 33123712, + -38670556, + 41881850, + -43291870, + 43283240, + -42151128, + 40136855, + -37446023, + 34258336, + -30732823, + 27010479, + -23215472, + 19455619, + -15822559, + 12391878, + -9223360, + 6361460, + -3836026, + 1663295, + 152868, + -1619508, + 2752973, + -3577189, + 4121899, + -4420917, + 4510456, + -4427579, + 4208820, + -3888998, + 3500254, + -3071314, + 2626991, + -2187902, + 1770393, + -1386644, + 1044931, + -749999, + 503533, + -304677, + 150576, + -36914, + -41579, + 90665, + -116202, + 123822, + -118679, + 105277, + -87368, + 67915, + -49103, + 32404, + -4217, + 12813, + -27866, + 51232, + -84713, + 129876, + -187841, + 259053, + -343023, + 438085, + -541157, + 647540, + -750776, + 842566, + -912799, + 949670, + -939943, + 869325, + -722996, + 486256, + -145307, + -311872, + 894555, + -1608270, + 2453777, + -3426088, + 4513566, + -5697158, + 6949798, + -8236037, + 9511917, + -10725143, + 11815541, + -12715829, + 13352673, + -13648000, + 13520525, + -12887421, + 11666035, + -9775542, + 7138387, + -3681344, + -664050, + 5961991, + -12274249, + 19664020, + -28202785, + 37981882, + -49131868, + 61855458, + -76485845, + 93596166, + -114221849, + 140361880, + -176280491, + 232654733, + -345028504, + 742252845, + 1843811707, + -322257028, + 142046080, + -70288539, + 31265530, + -6836607, + -9551279, + 20855476, + -28624896, + 33769337, + -36877766, + 38365674, + -38548922, + 37682792, + -35983300, + 33638945, + -30817091, + 27667285, + -24322816, + 20901337, + -17505015, + 14220549, + -11119233, + 8257207, + -5675937, + 3402966, + -1452933, + -171181, + 1476608, + -2479202, + 3201770, + -3672374, + 3922663, + -3986298, + 3897500, + -3689779, + 3394849, + -3041767, + 2656288, + -2260445, + 1872336, + -1506097, + 1172044, + -876951, + 624433, + -415398, + 248543, + -120867, + 28163, + 34519, + -72461, + 90931, + -94904, + 88854, + -76620, + 61334, + -45402, + 30539, + -701, + 7267, + -19991, + 40904, + -72074, + 115438, + -172597, + 244576, + -331563, + 432640, + -545519, + 666294, + -789250, + 906725, + -1009061, + 1084661, + -1120166, + 1100765, + -1010648, + 833605, + -553756, + 156415, + 370953, + -1037693, + 1848885, + -2804272, + 3897241, + -5113895, + 6432275, + -7821781, + 9242821, + -10646733, + 11976002, + -13164777, + 14139694, + -14820970, + 15123738, + -14959550, + 14237971, + -12868134, + 10760122, + -7825969, + 3980045, + 861534, + -6782954, + 13872940, + -22232361, + 31987188, + -43310357, + 56459323, + -71843076, + 90148869, + -112601394, + 141551293, + -182016757, + 246656905, + -378386180, + 869471384, + 1766417841, + -366811186, + 174519097, + -95820749, + 52221534, + -24393131, + 5271566, + 8345610, + -18134442, + 25073981, + -29791982, + 32726014, + -34204744, + 34491266, + -33806971, + 32344868, + -30276930, + 27757970, + -24927506, + 21910480, + -18817384, + 15744155, + -12772050, + 9967655, + -7383123, + 5056661, + -3013299, + 1265907, + 183557, + -1342621, + 2226758, + -2857759, + 3262120, + -3469453, + 3511008, + -3418328, + 3222076, + -2951058, + 2631453, + -2286261, + 1934954, + -1593326, + 1273510, + -984155, + 730712, + -515815, + 339725, + -200797, + 95957, + -21155, + -28220, + 56975, + -69809, + 71081, + -64642, + 53727, + -40917, + 28131, + 3022, + 1324, + -11402, + 29380, + -57557, + 98209, + -153390, + 224695, + -312995, + 418148, + -538712, + 671666, + -812158, + 953321, + -1086150, + 1199487, + -1280115, + 1312993, + -1281628, + 1168606, + -956265, + 627516, + -166788, + -438932, + 1198981, + -2117884, + 3194224, + -4419585, + 5777603, + -7243184, + 8781936, + -10349845, + 11893241, + -13349053, + 14645380, + -15702342, + 16433200, + -16745660, + 16543311, + -15727053, + 14196384, + -11850334, + 8587783, + -4306785, + -1097644, + 7738076, + -15742896, + 25270413, + -36532860, + 49837951, + -65663548, + 84799794, + -108641643, + 139857718, + -184157644, + 256066093, + -405774118, + 996573140, + 1678545883, + -401032652, + 202189048, + -118691000, + 71650551, + -41126194, + 19745754, + -4150820, + -7416366, + 15978251, + -22185235, + 26486026, + -29214126, + 30634242, + -30968065, + 30408789, + -29129206, + 27286035, + -25022016, + 22466708, + -19736570, + 16934728, + -14150654, + 11459948, + -8924305, + 6591740, + -4497087, + 2662770, + -1099824, + -190870, + 1217196, + -1994296, + 2543022, + -2888383, + 3058061, + -3081022, + 2986278, + -2801814, + 2553709, + -2265467, + 1957536, + -1647037, + 1347666, + -1069752, + 820457, + -604071, + 422395, + -275159, + 160467, + -75236, + 15610, + 22669, + -43938, + 52357, + -51714, + 45286, + -35770, + 25257, + 6880, + -4904, + -2255, + 16864, + -41413, + 78474, + -130522, + 199699, + -287549, + 394721, + -520661, + 663296, + -818751, + 981096, + -1142166, + 1291468, + -1416193, + 1501367, + -1530135, + 1484214, + -1344495, + 1091805, + -707819, + 176083, + 516850, + -1380237, + 2417935, + -3627222, + 4997707, + -6510354, + 8136710, + -9838336, + 11566524, + -13262286, + 14856658, + -16271298, + 17419349, + -18206543, + 18532434, + -18291682, + 17375217, + -15671087, + 13064700, + -9438081, + 4667538, + 1381123, + -8861278, + 17960486, + -28926201, + 42110580, + -58051521, + 77627854, + -102380686, + 135253151, + -182562144, + 260523620, + -426310907, + 1122150481, + 1581247653, + -425049504, + 224721559, + -138526888, + 89201120, + -56716811, + 33586578, + -16382714, + 3310447, + 6670453, + -14217017, + 19778262, + -23684654, + 26196405, + -27530505, + 27876058, + -27402914, + 26266327, + -24609214, + 22563002, + -20247654, + 17771302, + -15229740, + 12705965, + -10269890, + 7978288, + -5875019, + 3991533, + -2347649, + 952571, + 193900, + -1100009, + 1780593, + -2255600, + 2548622, + -2685497, + 2693022, + -2597813, + 2425337, + -2199127, + 1940194, + -1666638, + 1393426, + -1132350, + 892121, + -678587, + 495032, + -342551, + 220449, + -126661, + 58149, + -11281, + -17837, + 33091, + -38130, + 36211, + -30095, + 21997, + 10792, + -11295, + 7274, + 3591, + -23932, + 56579, + -104379, + 169989, + -255604, + 362663, + -491518, + 641103, + -808604, + 989158, + -1175612, + 1358354, + -1525244, + 1661669, + -1750749, + 1773686, + -1710291, + 1539673, + -1241089, + 794943, + -183911, + -605853, + 1583447, + -2751952, + 4107204, + -5636666, + 7318440, + -9120491, + 11000096, + -12903583, + 14766352, + -16513204, + 18058950, + -19309264, + 20161710, + -20506845, + 20229243, + -19208237, + 17318091, + -14427195, + 10395665, + -5070425, + -1723763, + 10199893, + -20635630, + 33420516, + -49141872, + 68750226, + -93903899, + 127767616, + -177159899, + 259753712, + -439184473, + 1244789281, + 1475680066, + -439128373, + 241889128, + -155024921, + 104566529, + -70874619, + 46526580, + -28107890, + 13829812, + -2659133, + -6052281, + 12743274, + -17733672, + 21273318, + -23569683, + 24803653, + -25138478, + 24724638, + -23702208, + 22201717, + -20344117, + 18240279, + -15990305, + 13682841, + -11394533, + 9189694, + -7120253, + 5225982, + -3535017, + 2064634, + -822259, + -193346, + 990761, + -1584516, + 1993679, + -2240472, + 2348967, + -2343897, + 2249611, + -2089211, + 1883849, + -1652233, + 1410296, + -1171045, + 944553, + -738089, + 556343, + -401736, + 274776, + -174440, + 98561, + -44194, + 7955, + 13691, + -24188, + 26711, + -24030, + 18440, + 14675, + -17716, + 16996, + -10185, + -5445, + 32923, + -75425, + 136074, + -217682, + 322459, + -451671, + 605289, + -781630, + 977007, + -1185434, + 1398378, + -1604616, + 1790197, + -1938547, + 2030724, + -2045853, + 1961722, + -1755567, + 1405012, + -889165, + 189831, + 707195, + -1810782, + 3123134, + -4638514, + 6342083, + -8208902, + 10203153, + -12277608, + 14373381, + -16419977, + 18335631, + -20027896, + 21394449, + -22323982, + 22697076, + -22386820, + 21258916, + -19170831, + 15969388, + -11485817, + 5526692, + 2141934, + -11822090, + 23932534, + -39097794, + 58320586, + -83343076, + 117489798, + -167954410, + 253571416, + -443666924, + 1363088553, + 1363088553, + -443666924, + 253571416, + -167954410, + 117489798, + -83343076, + 58320586, + -39097794, + 23932534, + -11822090, + 2141934, + 5526692, + -11485817, + 15969388, + -19170831, + 21258916, + -22386820, + 22697076, + -22323982, + 21394449, + -20027896, + 18335631, + -16419977, + 14373381, + -12277608, + 10203153, + -8208902, + 6342083, + -4638514, + 3123134, + -1810782, + 707195, + 189831, + -889165, + 1405012, + -1755567, + 1961722, + -2045853, + 2030724, + -1938547, + 1790197, + -1604616, + 1398378, + -1185434, + 977007, + -781630, + 605289, + -451671, + 322459, + -217682, + 136074, + -75425, + 32923, + -5445, + -10185, + 16996, + -17716, + 14675, + 18440, + -24030, + 26711, + -24188, + 13691, + 7955, + -44194, + 98561, + -174440, + 274776, + -401736, + 556343, + -738089, + 944553, + -1171045, + 1410296, + -1652233, + 1883849, + -2089211, + 2249611, + -2343897, + 2348967, + -2240472, + 1993679, + -1584516, + 990761, + -193346, + -822259, + 2064634, + -3535017, + 5225982, + -7120253, + 9189694, + -11394533, + 13682841, + -15990305, + 18240279, + -20344117, + 22201717, + -23702208, + 24724638, + -25138478, + 24803653, + -23569683, + 21273318, + -17733672, + 12743274, + -6052281, + -2659133, + 13829812, + -28107890, + 46526580, + -70874619, + 104566529, + -155024921, + 241889128, + -439128373, + 1475680066, + 1244789281, + -439184473, + 259753712, + -177159899, + 127767616, + -93903899, + 68750226, + -49141872, + 33420516, + -20635630, + 10199893, + -1723763, + -5070425, + 10395665, + -14427195, + 17318091, + -19208237, + 20229243, + -20506845, + 20161710, + -19309264, + 18058950, + -16513204, + 14766352, + -12903583, + 11000096, + -9120491, + 7318440, + -5636666, + 4107204, + -2751952, + 1583447, + -605853, + -183911, + 794943, + -1241089, + 1539673, + -1710291, + 1773686, + -1750749, + 1661669, + -1525244, + 1358354, + -1175612, + 989158, + -808604, + 641103, + -491518, + 362663, + -255604, + 169989, + -104379, + 56579, + -23932, + 3591, + 7274, + -11295, + 10792, + 21997, + -30095, + 36211, + -38130, + 33091, + -17837, + -11281, + 58149, + -126661, + 220449, + -342551, + 495032, + -678587, + 892121, + -1132350, + 1393426, + -1666638, + 1940194, + -2199127, + 2425337, + -2597813, + 2693022, + -2685497, + 2548622, + -2255600, + 1780593, + -1100009, + 193900, + 952571, + -2347649, + 3991533, + -5875019, + 7978288, + -10269890, + 12705965, + -15229740, + 17771302, + -20247654, + 22563002, + -24609214, + 26266327, + -27402914, + 27876058, + -27530505, + 26196405, + -23684654, + 19778262, + -14217017, + 6670453, + 3310447, + -16382714, + 33586578, + -56716811, + 89201120, + -138526888, + 224721559, + -425049504, + 1581247653, + 1122150481, + -426310907, + 260523620, + -182562144, + 135253151, + -102380686, + 77627854, + -58051521, + 42110580, + -28926201, + 17960486, + -8861278, + 1381123, + 4667538, + -9438081, + 13064700, + -15671087, + 17375217, + -18291682, + 18532434, + -18206543, + 17419349, + -16271298, + 14856658, + -13262286, + 11566524, + -9838336, + 8136710, + -6510354, + 4997707, + -3627222, + 2417935, + -1380237, + 516850, + 176083, + -707819, + 1091805, + -1344495, + 1484214, + -1530135, + 1501367, + -1416193, + 1291468, + -1142166, + 981096, + -818751, + 663296, + -520661, + 394721, + -287549, + 199699, + -130522, + 78474, + -41413, + 16864, + -2255, + -4904, + 6880, + 25257, + -35770, + 45286, + -51714, + 52357, + -43938, + 22669, + 15610, + -75236, + 160467, + -275159, + 422395, + -604071, + 820457, + -1069752, + 1347666, + -1647037, + 1957536, + -2265467, + 2553709, + -2801814, + 2986278, + -3081022, + 3058061, + -2888383, + 2543022, + -1994296, + 1217196, + -190870, + -1099824, + 2662770, + -4497087, + 6591740, + -8924305, + 11459948, + -14150654, + 16934728, + -19736570, + 22466708, + -25022016, + 27286035, + -29129206, + 30408789, + -30968065, + 30634242, + -29214126, + 26486026, + -22185235, + 15978251, + -7416366, + -4150820, + 19745754, + -41126194, + 71650551, + -118691000, + 202189048, + -401032652, + 1678545883, + 996573140, + -405774118, + 256066093, + -184157644, + 139857718, + -108641643, + 84799794, + -65663548, + 49837951, + -36532860, + 25270413, + -15742896, + 7738076, + -1097644, + -4306785, + 8587783, + -11850334, + 14196384, + -15727053, + 16543311, + -16745660, + 16433200, + -15702342, + 14645380, + -13349053, + 11893241, + -10349845, + 8781936, + -7243184, + 5777603, + -4419585, + 3194224, + -2117884, + 1198981, + -438932, + -166788, + 627516, + -956265, + 1168606, + -1281628, + 1312993, + -1280115, + 1199487, + -1086150, + 953321, + -812158, + 671666, + -538712, + 418148, + -312995, + 224695, + -153390, + 98209, + -57557, + 29380, + -11402, + 1324, + 3022, + 28131, + -40917, + 53727, + -64642, + 71081, + -69809, + 56975, + -28220, + -21155, + 95957, + -200797, + 339725, + -515815, + 730712, + -984155, + 1273510, + -1593326, + 1934954, + -2286261, + 2631453, + -2951058, + 3222076, + -3418328, + 3511008, + -3469453, + 3262120, + -2857759, + 2226758, + -1342621, + 183557, + 1265907, + -3013299, + 5056661, + -7383123, + 9967655, + -12772050, + 15744155, + -18817384, + 21910480, + -24927506, + 27757970, + -30276930, + 32344868, + -33806971, + 34491266, + -34204744, + 32726014, + -29791982, + 25073981, + -18134442, + 8345610, + 5271566, + -24393131, + 52221534, + -95820749, + 174519097, + -366811186, + 1766417841, + 869471384, + -378386180, + 246656905, + -182016757, + 141551293, + -112601394, + 90148869, + -71843076, + 56459323, + -43310357, + 31987188, + -22232361, + 13872940, + -6782954, + 861534, + 3980045, + -7825969, + 10760122, + -12868134, + 14237971, + -14959550, + 15123738, + -14820970, + 14139694, + -13164777, + 11976002, + -10646733, + 9242821, + -7821781, + 6432275, + -5113895, + 3897241, + -2804272, + 1848885, + -1037693, + 370953, + 156415, + -553756, + 833605, + -1010648, + 1100765, + -1120166, + 1084661, + -1009061, + 906725, + -789250, + 666294, + -545519, + 432640, + -331563, + 244576, + -172597, + 115438, + -72074, + 40904, + -19991, + 7267, + -701, + 30539, + -45402, + 61334, + -76620, + 88854, + -94904, + 90931, + -72461, + 34519, + 28163, + -120867, + 248543, + -415398, + 624433, + -876951, + 1172044, + -1506097, + 1872336, + -2260445, + 2656288, + -3041767, + 3394849, + -3689779, + 3897500, + -3986298, + 3922663, + -3672374, + 3201770, + -2479202, + 1476608, + -171181, + -1452933, + 3402966, + -5675937, + 8257207, + -11119233, + 14220549, + -17505015, + 20901337, + -24322816, + 27667285, + -30817091, + 33638945, + -35983300, + 37682792, + -38548922, + 38365674, + -36877766, + 33769337, + -28624896, + 20855476, + -9551279, + -6836607, + 31265530, + -70288539, + 142046080, + -322257028, + 1843811707, + 742252845, + -345028504, + 232654733, + -176280491, + 140361880, + -114221849, + 93596166, + -76485845, + 61855458, + -49131868, + 37981882, + -28202785, + 19664020, + -12274249, + 5961991, + -664050, + -3681344, + 7138387, + -9775542, + 11666035, + -12887421, + 13520525, + -13648000, + 13352673, + -12715829, + 11815541, + -10725143, + 9511917, + -8236037, + 6949798, + -5697158, + 4513566, + -3426088, + 2453777, + -1608270, + 894555, + -311872, + -145307, + 486256, + -722996, + 869325, + -939943, + 949670, + -912799, + 842566, + -750776, + 647540, + -541157, + 438085, + -343023, + 259053, + -187841, + 129876, + -84713, + 51232, + -27866, + 12813, + -4217, + 32404, + -49103, + 67915, + -87368, + 105277, + -118679, + 123822, + -116202, + 90665, + -41579, + -36914, + 150576, + -304677, + 503533, + -749999, + 1044931, + -1386644, + 1770393, + -2187902, + 2626991, + -3071314, + 3500254, + -3888998, + 4208820, + -4427579, + 4510456, + -4420917, + 4121899, + -3577189, + 2752973, + -1619508, + 152868, + 1663295, + -3836026, + 6361460, + -9223360, + 12391878, + -15822559, + 19455619, + -23215472, + 27010479, + -30732823, + 34258336, + -37446023, + 40136855, + -42151128, + 43283240, + -43291870, + 41881850, + -38670556, + 33123712, + -24426292, + 11201637, + 9172772, + -42530395, + 105209079, + -267386149, + 1909795890, + 616299310, + -306636233, + 214492005, + -167156034, + 136373768, + -113512123, + 95102015, + -79519870, + 65933271, + -53891326, + 43141569, + -33539112, + 24997817, + -17462444, + 10892098, + -5250212, + 498544, + 3406212, + -6514054, + 8882059, + -10573906, + 11658793, + -12209956, + 12302960, + -12013881, + 11417513, + -10585683, + 9585738, + -8479278, + 7321154, + -6158771, + 5031681, + -3971475, + 3001936, + -2139448, + 1393589, + -767896, + 260734, + 133762, + -424730, + 623638, + -743398, + 797561, + -799622, + 762440, + -697787, + 616030, + -525929, + 434555, + -347295, + 267955, + -198909, + 141300, + -95271, + 60191, + -34888, + 17861, + -7460, + 33659, + -51909, + 73294, + -96620, + 119967, + -140603, + 154937, + -158524, + 146130, + -111865, + 49405, + 47723, + -185758, + 370258, + -605594, + 894390, + -1236944, + 1630653, + -2069470, + 2543434, + -3038293, + 3535274, + -4011011, + 4437686, + -4783373, + 5012629, + -5087326, + 4967712, + -4613701, + 3986363, + -3049562, + 1771720, + -127634, + -1899709, + 4317374, + -7120852, + 10292613, + -13800893, + 17598741, + -21623339, + 25795584, + -30019846, + 34183810, + -38158164, + 41795801, + -44929957, + 47370331, + -48895516, + 49238661, + -48060389, + 44896397, + -39050992, + 29363530, + -13634603, + -13039316, + 64547853, + -202361927, + 1963572477, + 492947958, + -264182141, + 192664710, + -154911149, + 129724740, + -110527538, + 94666181, + -80906437, + 68627363, + -57505305, + 47371420, + -38140308, + 29771228, + -22245666, + 15553808, + -9686221, + 4628792, + -359841, + -3151261, + 5944379, + -8068104, + 9578673, + -10538480, + 11014338, + -11075612, + 10792331, + -10233371, + 9464790, + -8548363, + 7540379, + -6490712, + 5442191, + -4430262, + 3482926, + -2620943, + 1858254, + -1202579, + 656176, + -216671, + -122038, + 368884, + -534756, + 631680, + -672097, + 668236, + -631611, + 572635, + -500354, + 422302, + -344446, + 271228, + -205675, + 149558, + -103590, + 67639, + -40945, + 22329, + -10376, + 34246, + -53723, + 77315, + -104134, + 132568, + -160171, + 183587, + -198517, + 199750, + -181252, + 136349, + -57982, + -60948, + 227147, + -446431, + 723158, + -1059624, + 1455444, + -1906945, + 2406603, + -2942568, + 3498300, + -4052366, + 4578419, + -5045392, + 5417925, + -5657044, + 5721087, + -5566873, + 5151095, + -4431903, + 3370647, + -1933705, + 94369, + 2165300, + -4852703, + 7963084, + -11478117, + 15364755, + -19574356, + 24042104, + -28686679, + 33410119, + -38097704, + 42617615, + -46819941, + 50534304, + -53564832, + 55680157, + -56593873, + 55925914, + -53122912, + 47281534, + -36710185, + 17642613, + 20696954, + -127496274, + 2004488776, + 373473462, + -218660312, + 167721361, + -139867556, + 120602290, + -105367725, + 92327260, + -80640415, + 69900988, + -59914435, + 50596408, + -41921249, + 33893526, + -26531239, + 19855453, + -13883777, + 8626300, + -4083242, + 243829, + 2913895, + -5422547, + 7324342, + -8669637, + 9515200, + -9922328, + 9954902, + -9677484, + 9153517, + -8443714, + 7604657, + -6687673, + 5737983, + -4794148, + 3887792, + -3043604, + 2279563, + -1607390, + 1033148, + -557973, + 178887, + 110356, + -318424, + 455600, + -533037, + 562101, + -553822, + 518453, + -465150, + 401753, + -334686, + 268935, + -208110, + 154566, + -109566, + 73472, + -45945, + 26146, + -12919, + 34123, + -54468, + 79848, + -109701, + 142758, + -176913, + 209115, + -235298, + 250375, + -248286, + 222137, + -164410, + 67281, + 76985, + -275550, + 534437, + -857918, + 1247858, + -1703052, + 2218591, + -2785284, + 3389180, + -4011224, + 4627082, + -5207176, + 5716940, + -6117331, + 6365600, + -6416312, + 6222621, + -5737767, + 4916746, + -3718138, + 2106004, + -51813, + -2463687, + 5448708, + -8898844, + 12795742, + -17106057, + 21780729, + -26754586, + 31946236, + -37258172, + 42576934, + -47773052, + 52700316, + -57193544, + 61063380, + -64085198, + 65976053, + -66345696, + 64585833, + -59591582, + 48933250, + -25621930, + -43248504, + 2032046786, + 259071224, + -171069852, + 140251331, + -122393451, + 109238961, + -98173894, + 88161328, + -78749906, + 69746423, + -61084306, + 52762605, + -44814270, + 37288063, + -30237464, + 23713537, + -17760248, + 12411442, + -7689044, + 3602201, + -147182, + -2692101, + 4943084, + -6643145, + 7837929, + -8579480, + 8924288, + -8931327, + 8660176, + -8169266, + 7514341, + -6747138, + 5914348, + -5056850, + 4209231, + -3399578, + 2649524, + -1974512, + 1384259, + -883355, + 471975, + -146657, + -98900, + 273049, + -385448, + 446387, + -466199, + 454783, + -421215, + 373493, + -318363, + 261249, + -206268, + 156306, + -113144, + 77622, + -49824, + 29260, + -15053, + 33258, + -54086, + 80787, + -113141, + 150256, + -190409, + 230917, + -268032, + 296893, + -311534, + 304972, + -269378, + 196346, + -77253, + -96279, + 331840, + -635612, + 1011696, + -1461405, + 1982569, + -2568868, + 3209241, + -3887415, + 4581578, + -5264244, + 5902344, + -6457551, + 6886877, + -7143532, + 7178050, + -6939658, + 6377866, + -5444230, + 4094241, + -2289272, + -1476, + 2799113, + -6113352, + 9941024, + -14264895, + 19052814, + -24257266, + 29815311, + -35648934, + 41665733, + -47759862, + 53813044, + -59695343, + 65265141, + -70367245, + 74826966, + -78435180, + 80911698, + -81809191, + 80220423, + -73609331, + 49778105, + 2045910427, + 150841995, + -122398922, + 110872786, + -102895316, + 95906891, + -89125326, + 82279858, + -75295221, + 68184764, + -61005875, + 53838028, + -46770341, + 39893669, + -33295159, + 27054338, + -21240282, + 15909636, + -11105381, + 6856227, + -3176606, + 67161, + 2484308, + -4501538, + 6018203, + -7076111, + 7723272, + -8011930, + 7996625, + -7732356, + 7272913, + -6669406, + 5969050, + -5214208, + 4441713, + -3682464, + 2961280, + -2296991, + 1702740, + -1186444, + 751401, + -396971, + 119321, + 87825, + -232458, + 323599, + -370693, + 383088, + -369612, + 338254, + -295949, + 248450, + -200293, + 154831, + -114320, + 80059, + -52542, + 31637, + -16754 + +}; + +static const struct src_stage src_int32_21_8_4535_5000 = { + 3, 8, 21, 116, 2436, 8, 21, 0, 0, + src_int32_21_8_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_2_1_2268_5000.h b/src/audio/src/coef/src_ipc4_int32_2_1_2268_5000.h new file mode 100644 index 000000000000..9353a547baee --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_2_1_2268_5000.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_2268_5000_fir[48] = { + 179901, + -585106, + -849108, + 6757808, + -13863300, + 8132763, + 25424928, + -77295329, + 95239555, + -907014, + -271851188, + 889226553, + 1474972576, + 148945411, + -242428226, + 144331568, + -27262033, + -33601667, + 36380814, + -15519976, + -144295, + 3822340, + -1888676, + 265350, + 265350, + -1888676, + 3822340, + -144295, + -15519976, + 36380814, + -33601667, + -27262033, + 144331568, + -242428226, + 148945411, + 1474972576, + 889226553, + -271851188, + -907014, + 95239555, + -77295329, + 25424928, + 8132763, + -13863300, + 6757808, + -849108, + -585106, + 179901 + +}; + +static const struct src_stage src_int32_2_1_2268_5000 = { + 0, 1, 2, 24, 48, 1, 2, 0, 0, + src_int32_2_1_2268_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_2_1_2500_5000.h b/src/audio/src/coef/src_ipc4_int32_2_1_2500_5000.h new file mode 100644 index 000000000000..22fa881e337b --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_2_1_2500_5000.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_2500_5000_fir[40] = { + -879692, + 4237437, + -6093558, + -4442365, + 34997100, + -71022878, + 66653219, + 38864919, + -297189224, + 879379751, + 1516022404, + 101966883, + -218002245, + 151087631, + -51916314, + -10844043, + 26033472, + -15785611, + 3956471, + 460291, + 460291, + 3956471, + -15785611, + 26033472, + -10844043, + -51916314, + 151087631, + -218002245, + 101966883, + 1516022404, + 879379751, + -297189224, + 38864919, + 66653219, + -71022878, + 34997100, + -4442365, + -6093558, + 4237437, + -879692 + +}; + +static const struct src_stage src_int32_2_1_2500_5000 = { + 0, 1, 2, 20, 40, 1, 2, 0, 0, + src_int32_2_1_2500_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_2_1_2721_5000.h b/src/audio/src/coef/src_ipc4_int32_2_1_2721_5000.h new file mode 100644 index 000000000000..1eae05ae0bad --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_2_1_2721_5000.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_2721_5000_fir[48] = { + -197638, + 2396223, + -6798383, + 9193837, + -1178110, + -23457108, + 58362961, + -78248089, + 44242830, + 80687735, + -328040562, + 873463880, + 1556046848, + 57940613, + -201783941, + 169951987, + -86062815, + 12309824, + 24856589, + -28514053, + 16263064, + -4169058, + -1232873, + 1449887, + 1449887, + -1232873, + -4169058, + 16263064, + -28514053, + 24856589, + 12309824, + -86062815, + 169951987, + -201783941, + 57940613, + 1556046848, + 873463880, + -328040562, + 80687735, + 44242830, + -78248089, + 58362961, + -23457108, + -1178110, + 9193837, + -6798383, + 2396223, + -197638 + +}; + +static const struct src_stage src_int32_2_1_2721_5000 = { + 0, 1, 2, 24, 48, 1, 2, 0, 0, + src_int32_2_1_2721_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_2_1_3401_5000.h b/src/audio/src/coef/src_ipc4_int32_2_1_3401_5000.h new file mode 100644 index 000000000000..503925d74262 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_2_1_3401_5000.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_3401_5000_fir[72] = { + 32352, + 96988, + -688904, + 1954561, + -3679679, + 4897959, + -3857907, + -1466346, + 12277587, + -27563132, + 42999213, + -50810723, + 40945231, + -3254979, + -70599875, + 188662507, + -375522522, + 830975918, + 1674842581, + -84316100, + -96857864, + 139566684, + -127346532, + 90777968, + -49009209, + 14240605, + 7842241, + -17095237, + 16936474, + -12002238, + 6243404, + -1953989, + -247472, + 828538, + -610584, + 246132, + 246132, + -610584, + 828538, + -247472, + -1953989, + 6243404, + -12002238, + 16936474, + -17095237, + 7842241, + 14240605, + -49009209, + 90777968, + -127346532, + 139566684, + -96857864, + -84316100, + 1674842581, + 830975918, + -375522522, + 188662507, + -70599875, + -3254979, + 40945231, + -50810723, + 42999213, + -27563132, + 12277587, + -1466346, + -3857907, + 4897959, + -3679679, + 1954561, + -688904, + 96988, + 32352 + +}; + +static const struct src_stage src_int32_2_1_3401_5000 = { + 0, 1, 2, 36, 72, 1, 2, 0, 0, + src_int32_2_1_3401_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_2_1_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_2_1_4535_5000.h new file mode 100644 index 000000000000..418db95d9c0d --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_2_1_4535_5000.h @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_4535_5000_fir[240] = { + 2667, + 2962, + -15029, + 35644, + -66950, + 110953, + -169332, + 243207, + -332900, + 437689, + -555556, + 682979, + -814746, + 943835, + -1061374, + 1156689, + -1217458, + 1229983, + -1179592, + 1051155, + -829727, + 501299, + -53637, + -522814, + 1233986, + -2081244, + 3060483, + -4161305, + 5366314, + -6650576, + 7981280, + -9317634, + 10611006, + -11805355, + 12837919, + -13640176, + 14139054, + -14258329, + 13920185, + -13046846, + 11562195, + -9393268, + 6471498, + -2733523, + -1878633, + 7418307, + -13936262, + 21484678, + -30124018, + 39934404, + -51034412, + 63612836, + -77984681, + 94696011, + -114736521, + 140018019, + -174614471, + 228701521, + -335992675, + 710640514, + 1861419649, + -309562213, + 133310605, + -63623279, + 25891398, + -2366613, + -13342188, + 24114064, + -31454995, + 36248500, + -39065750, + 40309056, + -40283798, + 39236515, + -37375761, + 34883656, + -31922207, + 28636631, + -25156935, + 21598546, + -18062456, + 14635179, + -11388742, + 8380804, + -5654986, + 3241452, + -1157726, + -590247, + 2006849, + -3105376, + 3906512, + -4436757, + 4726840, + -4810191, + 4721495, + -4495388, + 4165312, + -3762555, + 3315496, + -2849051, + 2384323, + -1938443, + 1524582, + -1152116, + 826915, + -551728, + 326636, + -149541, + 16671, + 76931, + -136943, + 169356, + -180120, + 174858, + -158650, + 135883, + -110172, + 84331, + -60398, + 39699, + 39699, + -60398, + 84331, + -110172, + 135883, + -158650, + 174858, + -180120, + 169356, + -136943, + 76931, + 16671, + -149541, + 326636, + -551728, + 826915, + -1152116, + 1524582, + -1938443, + 2384323, + -2849051, + 3315496, + -3762555, + 4165312, + -4495388, + 4721495, + -4810191, + 4726840, + -4436757, + 3906512, + -3105376, + 2006849, + -590247, + -1157726, + 3241452, + -5654986, + 8380804, + -11388742, + 14635179, + -18062456, + 21598546, + -25156935, + 28636631, + -31922207, + 34883656, + -37375761, + 39236515, + -40283798, + 40309056, + -39065750, + 36248500, + -31454995, + 24114064, + -13342188, + -2366613, + 25891398, + -63623279, + 133310605, + -309562213, + 1861419649, + 710640514, + -335992675, + 228701521, + -174614471, + 140018019, + -114736521, + 94696011, + -77984681, + 63612836, + -51034412, + 39934404, + -30124018, + 21484678, + -13936262, + 7418307, + -1878633, + -2733523, + 6471498, + -9393268, + 11562195, + -13046846, + 13920185, + -14258329, + 14139054, + -13640176, + 12837919, + -11805355, + 10611006, + -9317634, + 7981280, + -6650576, + 5366314, + -4161305, + 3060483, + -2081244, + 1233986, + -522814, + -53637, + 501299, + -829727, + 1051155, + -1179592, + 1229983, + -1217458, + 1156689, + -1061374, + 943835, + -814746, + 682979, + -555556, + 437689, + -332900, + 243207, + -169332, + 110953, + -66950, + 35644, + -15029, + 2962, + 2667 + +}; + +static const struct src_stage src_int32_2_1_4535_5000 = { + 0, 1, 2, 120, 240, 1, 2, 0, 0, + src_int32_2_1_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_2_3_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_2_3_4535_5000.h new file mode 100644 index 000000000000..b4bcc5e5da9b --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_2_3_4535_5000.h @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_3_4535_5000_fir[264] = { + -93938, + -98991, + 260253, + -111110, + -282658, + 444629, + -32632, + -591077, + 615501, + 209882, + -1020683, + 689301, + 680483, + -1525896, + 553711, + 1418356, + -2008312, + 82004, + 2414393, + -2313987, + -843155, + 3589158, + -2242047, + -2298534, + 4777265, + -1566234, + -4285881, + 5722944, + -68684, + -6699685, + 6090173, + 2417253, + -9303020, + 5488315, + 5960590, + -11716274, + 3510944, + 10489290, + -13420758, + -218102, + 15756169, + -13774417, + -6001195, + 21317689, + -12029204, + -14039880, + 26523067, + -7326254, + -24445212, + 30497915, + 1384817, + -37324046, + 32074267, + 15641810, + -53040792, + 29515507, + 38437745, + -73011481, + 19435812, + 77903872, + -102872199, + -8670013, + 168775336, + -175974902, + -134868374, + 908730870, + 1309134037, + 328594535, + -295620392, + 42980640, + 128174662, + -111607880, + -9047801, + 85943502, + -55111322, + -25767624, + 62315551, + -25668444, + -31460430, + 44780278, + -7687326, + -31675128, + 30563820, + 3550329, + -28728837, + 18941748, + 10106741, + -24013938, + 9730030, + 13214873, + -18535817, + 2837807, + 13810846, + -13053418, + -1886447, + 12694584, + -8112799, + -4696340, + 10562706, + -4057485, + -5935935, + 7998012, + -1043594, + -6002401, + 5451000, + 932334, + -5299756, + 3229456, + 1993907, + -4195454, + 1502296, + 2339106, + -2987640, + 317745, + 2194885, + -1887194, + -367763, + 1778313, + -1015171, + -655498, + 1268670, + -413370, + -671001, + 792439, + -63798, + -536201, + 420676, + 87997, + -350221, + 176251, + 110488, + -179888, + -179888, + 110488, + 176251, + -350221, + 87997, + 420676, + -536201, + -63798, + 792439, + -671001, + -413370, + 1268670, + -655498, + -1015171, + 1778313, + -367763, + -1887194, + 2194885, + 317745, + -2987640, + 2339106, + 1502296, + -4195454, + 1993907, + 3229456, + -5299756, + 932334, + 5451000, + -6002401, + -1043594, + 7998012, + -5935935, + -4057485, + 10562706, + -4696340, + -8112799, + 12694584, + -1886447, + -13053418, + 13810846, + 2837807, + -18535817, + 13214873, + 9730030, + -24013938, + 10106741, + 18941748, + -28728837, + 3550329, + 30563820, + -31675128, + -7687326, + 44780278, + -31460430, + -25668444, + 62315551, + -25767624, + -55111322, + 85943502, + -9047801, + -111607880, + 128174662, + 42980640, + -295620392, + 328594535, + 1309134037, + 908730870, + -134868374, + -175974902, + 168775336, + -8670013, + -102872199, + 77903872, + 19435812, + -73011481, + 38437745, + 29515507, + -53040792, + 15641810, + 32074267, + -37324046, + 1384817, + 30497915, + -24445212, + -7326254, + 26523067, + -14039880, + -12029204, + 21317689, + -6001195, + -13774417, + 15756169, + -218102, + -13420758, + 10489290, + 3510944, + -11716274, + 5960590, + 5488315, + -9303020, + 2417253, + 6090173, + -6699685, + -68684, + 5722944, + -4285881, + -1566234, + 4777265, + -2298534, + -2242047, + 3589158, + -843155, + -2313987, + 2414393, + 82004, + -2008312, + 1418356, + 553711, + -1525896, + 680483, + 689301, + -1020683, + 209882, + 615501, + -591077, + -32632, + 444629, + -282658, + -111110, + 260253, + -98991, + -93938 + +}; + +static const struct src_stage src_int32_2_3_4535_5000 = { + 1, 1, 2, 132, 264, 3, 2, 0, 0, + src_int32_2_3_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_32_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_32_21_4535_5000.h new file mode 100644 index 000000000000..6e20c5d23123 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_32_21_4535_5000.h @@ -0,0 +1,3858 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_32_21_4535_5000_fir[3840] = { + -9755, + 20037, + -35510, + 57114, + -85539, + 121078, + -163460, + 211683, + -263860, + 317073, + -367273, + 409224, + -436508, + 441610, + -416089, + 350838, + -236445, + 63656, + 176084, + -490003, + 883322, + -1358535, + 1914689, + -2546691, + 3244679, + -3993496, + 4772312, + -5554417, + 6307227, + -6992531, + 7566982, + -7982865, + 8189120, + -8132611, + 7759626, + -7017554, + 5856710, + -4232224, + 2105955, + 551667, + -3759934, + 7526369, + -11845528, + 16698162, + -22050812, + 27855880, + -34052237, + 40566402, + -47314357, + 54204052, + -61138747, + 68021442, + -74761003, + 81281290, + -87536496, + 93541217, + -99441004, + 105718606, + -114015156, + 132941541, + 2046899622, + 66602126, + -81977543, + 85585861, + -85587395, + 83685820, + -80507556, + 76378552, + -71517607, + 66099041, + -60275949, + 54189075, + -47969753, + 41740222, + -35612789, + 29688561, + -24056139, + 18790497, + -13952169, + 9586815, + -5725198, + 2383577, + 435527, + -2742200, + 4557730, + -5912963, + 6846504, + -7402834, + 7630412, + -7579828, + 7302070, + -6846953, + 6261758, + -5590096, + 4871039, + -4138496, + 3420855, + -2740859, + 2115704, + -1557324, + 1072832, + -665080, + 333296, + -73774, + -119438, + 253861, + -337960, + 380583, + -390482, + 375929, + -344416, + 302462, + -255492, + 207801, + -162587, + 122028, + -87403, + 59240, + -37469, + 21584, + -8587, + 18257, + -33177, + 54425, + -82870, + 119028, + -162889, + 213742, + -270006, + 329072, + -387174, + 439310, + -479218, + 499428, + -491395, + 445735, + -352550, + 201868, + 15832, + -309003, + 684343, + -1146060, + 1695122, + -2328509, + 3038528, + -3812207, + 4630820, + -5469572, + 6297499, + -7077580, + 7767115, + -8318367, + 8679465, + -8795578, + 8610325, + -8067382, + 7112269, + -5694215, + 3768082, + -1296238, + -1749686, + 5387242, + -9621900, + 14446163, + -19839141, + 25766684, + -32182163, + 39028029, + -46238318, + 53742377, + -61470316, + 69361125, + -77375422, + 85517061, + -93873686, + 102702698, + -112642869, + 125349518, + -146071804, + 202437454, + 2040920553, + 3665864, + -50219533, + 65132180, + -71211315, + 73230683, + -72855508, + 70858001, + -67679039, + 63615426, + -58893491, + 53701008, + -48201681, + 42541661, + -36852187, + 31250333, + -25838881, + 20705865, + -15924126, + 11551047, + -7628574, + 4183576, + -1228552, + -1237339, + 3226955, + -4763610, + 5879339, + -6613058, + 7008674, + -7113230, + 6975138, + -6642542, + 6161880, + -5576655, + 4926455, + -4246216, + 3565750, + -2909506, + 2296561, + -1740806, + 1251300, + -832755, + 486122, + -209227, + -2562, + 155676, + -257723, + 316916, + -341584, + 339756, + -318842, + 285404, + -245007, + 202158, + -160303, + 121889, + -88461, + 60797, + -39047, + 22893, + -7291, + 16255, + -30484, + 51186, + -79405, + 115877, + -160855, + 213930, + -273842, + 338315, + -403902, + 465879, + -518195, + 553487, + -563181, + 537691, + -466717, + 339648, + -146072, + -123625, + 477569, + -921659, + 1458784, + -2088040, + 2803984, + -3595949, + 4447487, + -5335950, + 6232263, + -7100929, + 7900266, + -8582926, + 9096680, + -9385468, + 9390717, + -9052867, + 8313092, + -7115140, + 5407239, + -3143986, + 288144, + 3187762, + -7300122, + 12053316, + -17439283, + 23437709, + -30016996, + 37136188, + -44748173, + 52804641, + -61263655, + 70101518, + -79332261, + 89042050, + -99455732, + 111080862, + -125067226, + 144298116, + -177878863, + 274820508, + 2028993885, + -55644517, + -18991981, + 44537411, + -56444418, + 62273893, + -64653603, + 64773653, + -63283965, + 60596798, + -57007377, + 52747510, + -48011026, + 42966187, + -37761672, + 32529260, + -27384840, + 22428611, + -17744984, + 13402482, + -9453799, + 5936125, + -2871773, + 269112, + 1876214, + -3579822, + 4866931, + -5770576, + 6329755, + -6587576, + 6589466, + -6381492, + 6008853, + -5514568, + 4938397, + -4315997, + 3678341, + -3051362, + 2455845, + -1907506, + 1417259, + -991629, + 633265, + -341536, + 113161, + 57155, + -176102, + 251198, + -290275, + 301058, + -290810, + 266080, + -232529, + 194830, + -156651, + 120682, + -88720, + 61783, + -40240, + 23958, + -5877, + 14043, + -27446, + 47413, + -75158, + 111632, + -157353, + 212216, + -275301, + 344684, + -417268, + 488653, + -553049, + 603265, + -630771, + 625862, + -577916, + 475774, + -308213, + 64535, + 264756, + -687209, + 1207622, + -1827227, + 2542890, + -3346359, + 4223619, + -5154371, + 6111700, + -7061941, + 7964802, + -8773739, + 9436611, + -9896616, + 10093487, + -9964933, + 9448276, + -8482249, + 7008869, + -4975328, + 2335805, + 946899, + -4900005, + 9539788, + -14871158, + 20887905, + -27573848, + 34905137, + -42854139, + 51395615, + -60516428, + 70231160, + -80608413, + 91818213, + -104225104, + 118591910, + -136592947, + 162385816, + -209161388, + 349800015, + 2011182355, + -111131266, + 11465529, + 23978932, + -41419604, + 50916567, + -55979020, + 58183873, + -58375539, + 57073796, + -54637868, + 51340238, + -47402350, + 43012588, + -38335423, + 33515949, + -28681975, + 23944860, + -19399748, + 15125621, + -11185394, + 7626193, + -4479901, + 1763976, + 517440, + -2372166, + 3818418, + -4883094, + 5599968, + -6007858, + 6148828, + -6066481, + 5804393, + -5404732, + 4907084, + -4347520, + 3757896, + -3165403, + 2592342, + -2056108, + 1569368, + -1140390, + 773490, + -469574, + 226729, + -40836, + -93830, + 184027, + -237035, + 260205, + -260597, + 244693, + -218195, + 185908, + -151685, + 118436, + -88193, + 62202, + -41045, + 24776, + -4353, + 11636, + -24082, + 43130, + -70153, + 106313, + -152389, + 208587, + -274335, + 348081, + -427109, + 507381, + -583421, + 648272, + -693522, + 709427, + -685135, + 609026, + -469161, + 253840, + 47730, + -444692, + 943727, + -1548204, + 2257339, + -3065381, + 3960883, + -4926086, + 5936475, + -6960525, + 7959687, + -8888629, + 9695757, + -10324013, + 10711957, + -10795094, + 10507427, + -9783185, + 8558658, + -6774061, + 4375353, + -1315895, + -2442170, + 6926931, + -12156290, + 18138279, + -24872385, + 32352211, + -40570047, + 49524240, + -59231021, + 69743844, + -81186518, + 93813667, + -108130692, + 125158441, + -147104630, + 179437426, + -239639935, + 427065492, + 1987579580, + -162622486, + 40926138, + 3630263, + -26269887, + 39261957, + -46912163, + 51150832, + -53000986, + 53081195, + -51809282, + 49494718, + -46383827, + 42682955, + -38570585, + 34203615, + -29720490, + 25242624, + -20874964, + 16706180, + -12808789, + 9239385, + -6039090, + 3234254, + -837438, + -1151350, + 2743197, + -3958662, + 4826027, + -5379505, + 5657451, + -5700639, + 5550655, + -5248455, + 4833114, + -4340800, + 3803979, + -3250855, + 2705045, + -2185466, + 1706419, + -1277829, + 905635, + -592261, + 337170, + -137445, + -11632, + 116009, + -182352, + 217584, + -228499, + 221457, + -202160, + 175496, + -145471, + 115191, + -86901, + 62063, + -41466, + 25347, + -2730, + 9050, + -20415, + 38364, + -64419, + 99947, + -145984, + 203045, + -270916, + 348435, + -433292, + 521847, + -608989, + 688056, + -750826, + 787599, + -787385, + 738200, + -627483, + 442630, + -171632, + -196180, + 669321, + -1253285, + 1949657, + -2755252, + 3661304, + -4652764, + 5707742, + -6797138, + 7884490, + -8926078, + 9871305, + -10663357, + 11240147, + -11535531, + 11480755, + -11006100, + 10042659, + -8524167, + 6388806, + -3580862, + 52129, + 4237101, + -9317626, + 15211730, + -21934666, + 29497685, + -37913247, + 47203580, + -57414554, + 68638718, + -81055168, + 95003026, + -111128326, + 130710197, + -156493673, + 195282644, + -269032431, + 506288331, + 1958309467, + -209972840, + 69177047, + -16340257, + -11127283, + 27414545, + -37535934, + 43739933, + -47211161, + 48657566, + -48549745, + 47230183, + -44967150, + 41982648, + -38467274, + 34588128, + -30492909, + 26311898, + -22158829, + 18131206, + -14310448, + 10762067, + -7536011, + 4667245, + -2176600, + 71871, + 1650840, + -3005602, + 4014990, + -4708338, + 5119979, + -5287519, + 5250208, + -5047442, + 4717451, + -4296190, + 3816450, + -3307200, + 2793166, + -2294614, + 1827343, + -1402847, + 1028619, + -708575, + 443549, + -231839, + 69772, + 47749, + -126723, + 173588, + -194820, + 196603, + -184588, + 163707, + -138085, + 110993, + -84869, + 61379, + -41508, + 25673, + -1021, + 6304, + -16471, + 33147, + -57995, + 92573, + -138170, + 195610, + -265040, + 345702, + -435714, + 531870, + -629470, + 722205, + -802116, + 859630, + -883711, + 862112, + -781756, + 629231, + -391413, + 56186, + 386739, + -944942, + 1622383, + -2418482, + 3327248, + -4336485, + 5427136, + -6572788, + 7739394, + -8885237, + 9961162, + -10911091, + 11672834, + -12179166, + 12359165, + -12139757, + 11447420, + -10209964, + 8358301, + -5828101, + 2561186, + 1493467, + -6379345, + 12132853, + -18784972, + 26364616, + -34904482, + 44450730, + -55078860, + 66920333, + -80209056, + 95367687, + -113181235, + 135184764, + -164659296, + 209757541, + -297056103, + 587123604, + 1923525437, + -253064072, + 96020736, + -35770738, + 3878277, + 15479139, + -27934998, + 36019218, + -41060076, + 43844919, + -44890922, + 44569376, + -43167399, + 40920222, + -38028562, + 34668031, + -30994124, + 27144732, + -23241282, + 19389183, + -15677983, + 12181477, + -8957956, + 6050651, + -3488435, + 1286787, + 551005, + -2032432, + 3174192, + -4000512, + 4541425, + -4831065, + 4906012, + -4803776, + 4561418, + -4214369, + 3795463, + -3334182, + 2856139, + -2382769, + 1931226, + -1514461, + 1141452, + -817560, + 544974, + -323216, + 149677, + -20152, + -70647, + 128622, + -159876, + 170372, + -165656, + 150668, + -129612, + 105896, + -82131, + 60168, + -41181, + 25760, + 762, + 3420, + -12279, + 27519, + -50925, + 84239, + -128994, + 186319, + -256724, + 339863, + -434304, + 537306, + -644621, + 750353, + -846872, + 924818, + -973202, + 979618, + -930578, + 811977, + -609676, + 310211, + 98404, + -625786, + 1278248, + -2057836, + 2961401, + -3979723, + 5096758, + -6289024, + 7525200, + -8765941, + 9963971, + -11064443, + 12005603, + -12719729, + 13134340, + -13173636, + 12760103, + -11816236, + 10266256, + -8037747, + 5063036, + -1280185, + -3366650, + 8927739, + -15449598, + 22978662, + -31567728, + 41286705, + -52240413, + 64598648, + -78649082, + 94896062, + -114260449, + 138528209, + -171509518, + 222706022, + -323429438, + 669211988, + 1883409467, + -291805344, + 121276041, + -54506922, + 18620008, + 3559976, + -18195041, + 28058754, + -34604408, + 38688303, + -40867714, + 41538332, + -41002894, + 39507336, + -37260426, + 34444532, + -31221430, + 27735291, + -24114083, + 20470128, + -16900249, + 13485833, + -10292953, + 7372682, + -4761645, + 2482829, + -546643, + -1047792, + 2311181, + -3262462, + 3927131, + -4335568, + 4521390, + -4519902, + 4366682, + -4096339, + 3741465, + -3331801, + 2893622, + -2449339, + 2017309, + -1611817, + 1243242, + -918333, + 640608, + -410806, + 227400, + -87103, + -14620, + 83091, + -123992, + 143011, + -145551, + 136512, + -120144, + 99962, + -78725, + 58454, + -40496, + 25612, + 2603, + 420, + -7872, + 21519, + -43259, + 75004, + -118517, + 175227, + -246006, + 330928, + -429026, + 538050, + -654246, + 772182, + -884627, + 982516, + -1054999, + 1089616, + -1072585, + 989219, + -824483, + 563669, + -193188, + -298545, + 920153, + -1676309, + 2566749, + -3585327, + 4719164, + -5947933, + 7243322, + -8568716, + 9879137, + -11121454, + 12234890, + -13151816, + 13798821, + -14098029, + 13968601, + -13328374, + 12095522, + -10190147, + 7535642, + -4059659, + -305555, + 5623752, + -11956646, + 19367876, + -27930006, + 37736280, + -48920224, + 61688992, + -76382395, + 93583746, + -114345139, + 140695658, + -176962081, + 233981252, + -347874168, + 752181801, + 1838170949, + -326133398, + 144779108, + -72403305, + 32975282, + -8240152, + -8402015, + 19930010, + -27902981, + 33235399, + -36517932, + 38166124, + -38495008, + 37758628, + -36171680, + 33921484, + -31174528, + 28079890, + -24770876, + 21365659, + -17967441, + 14664431, + -11529861, + 8622158, + -5985339, + 3649657, + -1632522, + -60364, + 1433650, + -2500845, + 3282712, + -3805637, + 4099994, + -4198593, + 4135235, + -3943409, + 3655189, + -3300315, + 2905498, + -2493928, + 2084995, + -1694194, + 1333202, + -1010094, + 729672, + -493883, + 302283, + -152529, + 40867, + 37402, + -87494, + 114778, + -124467, + 121381, + -109781, + 93258, + -74695, + 56262, + -39470, + 25239, + 4486, + -2671, + -3285, + 15196, + -35056, + 64933, + -106810, + 162404, + -232946, + 318934, + -419876, + 534037, + -658194, + 787427, + -914972, + 1032134, + -1128300, + 1191062, + -1206457, + 1159341, + -1033906, + 814318, + -485491, + 33961, + 551146, + -1277105, + 2146555, + -3156496, + 4297344, + -5552119, + 6895781, + -8294777, + 9706831, + -11081000, + 12358019, + -13470945, + 14346076, + -14904133, + 15061650, + -14732511, + 13829538, + -12266029, + 9957089, + -6820561, + 2777338, + 2249300, + -8335781, + 15562468, + -24021166, + 33827799, + -45143688, + 58211969, + -73422396, + 91433629, + -113422889, + 141651802, + -180945296, + 243447040, + -370117263, + 835651130, + 1788045388, + -356012524, + 166384199, + -89324146, + 46826598, + -19820759, + 1358593, + 11705230, + -21016242, + 27536078, + -31881943, + 34484592, + -35667961, + 35691569, + -34773879, + 33105327, + -30855515, + 28177018, + -25207226, + 22069071, + -18871168, + 15707730, + -12658465, + 9788603, + -7149124, + 4777255, + -2697211, + 921199, + 549367, + -1722478, + 2614010, + -3246144, + 3645770, + -3842936, + 3869376, + -3757185, + 3537643, + -3240237, + 2891878, + -2516333, + 2133855, + -1761007, + 1410657, + -1092125, + 811453, + -571766, + 373703, + -215873, + 95333, + -8043, + -50710, + 85932, + -102603, + 105425, + -98630, + 85858, + -70088, + 53623, + -38120, + 24652, + 6396, + -5827, + 1444, + 8599, + -26380, + 54102, + -93957, + 147939, + -217629, + 303946, + -406885, + 525245, + -656362, + 795880, + -937558, + 1073150, + -1192373, + 1282976, + -1330936, + 1320778, + -1236051, + 1059923, + -775933, + 368843, + 174394, + -863607, + 1704333, + -2696758, + 3834699, + -5104687, + 6485189, + -7946022, + 9447995, + -10942806, + 12373230, + -13673598, + 14770562, + -15584131, + 16028933, + -16015642, + 15452479, + -14246680, + 12305779, + -9538508, + 5855070, + -1166410, + -4617986, + 11594563, + -19873648, + 29592957, + -40940402, + 54193326, + -69788669, + 88455946, + -111489903, + 141371328, + -183398825, + 250979157, + -389892917, + 919230043, + 1733292929, + -381434358, + 185964348, + -105144401, + 60062489, + -31084490, + 11002494, + 3456799, + -14005723, + 21641955, + -27002303, + 30528042, + -32548593, + 33326294, + -33081204, + 32005024, + -30268853, + 28027331, + -25420656, + 22575374, + -19604516, + 16607430, + -13669560, + 10862328, + -8243200, + 5856010, + -3731538, + 1888353, + -333890, + -934281, + 1927038, + -2662190, + 3162928, + -3456290, + 3571689, + -3539552, + 3390103, + -3152322, + 2853092, + -2516549, + 2163629, + -1811814, + 1475046, + -1163804, + 885308, + -643829, + 441071, + -276605, + 148315, + -52848, + -13968, + 56735, + -80163, + 88795, + -86803, + 77840, + -64957, + 50570, + -36467, + 23861, + 8315, + -9020, + 6275, + 1783, + -17298, + 42596, + -80056, + 131936, + -200156, + 286056, + -390119, + 511692, + -648700, + 797389, + -952100, + 1105111, + -1246558, + 1364454, + -1444834, + 1472025, + -1429068, + 1298274, + -1061936, + 703166, + -206840, + -439351, + 1243814, + -2209939, + 3335014, + -4609218, + 6014732, + -7525023, + 9104340, + -10707459, + 12279705, + -13757263, + 15067784, + -16131266, + 16861175, + -17165750, + 16949402, + -16114106, + 14560620, + -12189346, + 8900557, + -4593624, + -835297, + 7497929, + -15522212, + 25066542, + -36343930, + 49663770, + -65506873, + 84668259, + -108551136, + 139839272, + -184274377, + 256466592, + -406944515, + 1002522870, + 1674196741, + -402417494, + 203411881, + -119750545, + 72578373, + -41937914, + 20447306, + -4743380, + -6933500, + 15605928, + -21923374, + 26332935, + -29166108, + 30685406, + -31110315, + 30631958, + -29421314, + 27633641, + -25410646, + 22881332, + -20162106, + 17356537, + -14555023, + 11834517, + -9258433, + 6876797, + -4726652, + 2832735, + -1208407, + -143212, + 1227930, + -2059052, + 2655893, + -3042264, + 3245015, + -3292654, + 3214095, + -3037567, + 2789691, + -2494764, + 2174225, + -1846317, + 1525930, + -1224606, + 950672, + -709500, + 503841, + -334221, + 199364, + -96627, + 22412, + 27448, + -57352, + 71650, + -74415, + 69286, + -59359, + 47140, + -34534, + 22882, + 10224, + -12221, + 11168, + -5195, + -7886, + 30505, + -65213, + 114513, + -180654, + 265385, + -369679, + 493441, + -635207, + 791862, + -958382, + 1127640, + -1290277, + 1434675, + -1547047, + 1611655, + -1611174, + 1527205, + -1340942, + 1033977, + -589233, + -7993, + 768920, + -1700131, + 2802428, + -4069743, + 5488145, + -7035001, + 8678333, + -10376403, + 12077575, + -13720457, + 15234339, + -16539911, + 17550234, + -18171913, + 18306383, + -17851204, + 16701220, + -14749361, + 11886833, + -8002297, + 2979471, + 3307690, + -11003652, + 20286158, + -31391548, + 44658741, + -60608571, + 80095384, + -104620351, + 137051289, + -183536314, + 259812730, + -421026569, + 1085130532, + 1611061257, + -419006929, + 218638776, + -133041293, + 84277329, + -52292266, + 29613242, + -12824503, + 138351, + 9481707, + -16690916, + 21937552, + -25551809, + 27793763, + -28880195, + 28999825, + -28321905, + 27000871, + -25178637, + 22985480, + -20540122, + 17949415, + -15307879, + 12697295, + -10186438, + 7831057, + -5674102, + 3746234, + -2066592, + 643792, + 522881, + -1442140, + 2129273, + -2604680, + 2892430, + -3018876, + 3011385, + -2897192, + 2702434, + -2451359, + 2165720, + -1864362, + 1562991, + -1274104, + 1007059, + -768274, + 561515, + -388253, + 248058, + -139011, + 58115, + -1670, + -34378, + 54148, + -61585, + 60281, + -53352, + 43372, + -32344, + 21727, + 12104, + -15402, + 16077, + -12276, + 1779, + 17928, + -49546, + 95806, + -159267, + 242078, + -345698, + 470595, + -615934, + 779269, + -956262, + 1140441, + -1323039, + 1492909, + -1636563, + 1738329, + -1780666, + 1744617, + -1610432, + 1358332, + -969422, + 426718, + 283730, + -1171658, + 2241397, + -3490705, + 4909682, + -6479812, + 8173185, + -9951934, + 11767928, + -13562748, + 15267951, + -16805619, + 18089176, + -19024410, + 19510640, + -19441909, + 18708062, + -17195491, + 14787282, + -11362354, + 6793007, + -939972, + -6356487, + 15291914, + -26123945, + 39218141, + -55131011, + 74769245, + -99720106, + 133013836, + -181162165, + 260936430, + -431906599, + 1166652915, + 1544210289, + -431273337, + 231576876, + -144928208, + 95070804, + -62064156, + 38423769, + -20717466, + 7148289, + 3323342, + -11351690, + 17381646, + -21738804, + 24678250, + -26411970, + 27124498, + -26981779, + 26136004, + -24727997, + 22888124, + -20736347, + 18381828, + -15922356, + 13443792, + -11019644, + 8710865, + -6565910, + 4621064, + -2901050, + 1419877, + -181902, + -816945, + 1587815, + -2147538, + 2517211, + -2720821, + 2783955, + -2732634, + 2592285, + -2386900, + 2138358, + -1865943, + 1586036, + -1311976, + 1054065, + -819707, + 613643, + -438269, + 293996, + -179645, + 92836, + -30366, + -11443, + 36449, + -48433, + 50913, + -46999, + 39307, + -29926, + 20415, + 13937, + -18531, + 20960, + -19397, + 11614, + 4969, + -33182, + 75960, + -136158, + 216307, + -318344, + 443301, + -590984, + 759643, + -945666, + 1143299, + -1344445, + 1538527, + -1712472, + 1850813, + -1935938, + 1948495, + -1867950, + 1673318, + -1344037, + 860977, + -207559, + -629040, + 1656662, + -2876930, + 4284083, + -5863907, + 7592823, + -9437185, + 11352806, + -13284767, + 15167501, + -16925177, + 18472346, + -19714810, + 20550659, + -20871348, + 20562689, + -19505532, + 17575873, + -14643958, + 10571794, + -5208123, + -1620635, + 10126090, + -20584891, + 33386026, + -49116850, + 68728672, + -93881661, + 127744266, + -177143036, + 259773019, + -439366962, + 1246691259, + 1473985027, + -439312181, + 242177958, + -155336198, + 104879234, + -71176204, + 46806226, + -28355443, + 14035838, + -2815249, + -5953034, + 12706091, + -17761712, + 21367526, + -23728708, + 25023872, + -25414121, + 25048008, + -24063985, + 22591330, + -20750161, + 18650968, + -16393925, + 14068197, + -11751355, + 9508998, + -7394632, + 5449825, + -3704640, + 2178330, + -880257, + -188992, + 1036359, + -1674979, + 2122811, + -2401282, + 2533992, + -2545528, + 2460398, + -2302131, + 2092546, + -1851197, + 1594996, + -1338005, + 1091375, + -863427, + 659829, + -483875, + 336810, + -218194, + 126283, + -58394, + 11250, + 18711, + -35082, + 41273, + -40361, + 34988, + -27306, + 18962, + 15704, + -21578, + 25769, + -26495, + 21533, + -8262, + -16255, + 55137, + -111509, + 188269, + -287817, + 411747, + -560512, + 733079, + -926597, + 1136086, + -1354192, + 1571004, + -1773978, + 1947985, + -2075496, + 2136923, + -2111126, + 1976084, + -1709734, + 1290953, + -700663, + -76956, + 1053205, + -2233582, + 3616537, + -5192303, + 6941863, + -8836104, + 10835193, + -12888204, + 14933041, + -16896636, + 18695424, + -20236059, + 21416300, + -22125974, + 22247866, + -21658340, + 20227399, + -17817770, + 14282398, + -9459404, + 3162927, + 4832785, + -14820879, + 27210255, + -42613838, + 62019134, + -87144810, + 121270831, + -171483922, + 256275166, + -443206594, + 1324850554, + 1400741933, + -443242674, + 250413641, + -164203895, + 113632590, + -79557638, + 54692415, + -35674444, + 20742101, + -8880744, + -542457, + 7952513, + -13656348, + 17891769, + -20855208, + 22717698, + -23634023, + 23747745, + -23193694, + 22098894, + -20582545, + 18755472, + -16719336, + 14565804, + -12375806, + 10218991, + -8153426, + 6225571, + -4470541, + 2912636, + -1566121, + 436207, + 479801, + -1191250, + 1712824, + -2063220, + 2263861, + -2337697, + 2308110, + -2197970, + 2028850, + -1820403, + 1589926, + -1352079, + 1118762, + -899133, + 699735, + -524724, + 376161, + -254347, + 158180, + -85517, + 33507, + 1092, + -21651, + 31449, + -33505, + 30461, + -24513, + 17385, + 17385, + -24513, + 30461, + -33505, + 31449, + -21651, + 1092, + 33507, + -85517, + 158180, + -254347, + 376161, + -524724, + 699735, + -899133, + 1118762, + -1352079, + 1589926, + -1820403, + 2028850, + -2197970, + 2308110, + -2337697, + 2263861, + -2063220, + 1712824, + -1191250, + 479801, + 436207, + -1566121, + 2912636, + -4470541, + 6225571, + -8153426, + 10218991, + -12375806, + 14565804, + -16719336, + 18755472, + -20582545, + 22098894, + -23193694, + 23747745, + -23634023, + 22717698, + -20855208, + 17891769, + -13656348, + 7952513, + -542457, + -8880744, + 20742101, + -35674444, + 54692415, + -79557638, + 113632590, + -164203895, + 250413641, + -443242674, + 1400741933, + 1324850554, + -443206594, + 256275166, + -171483922, + 121270831, + -87144810, + 62019134, + -42613838, + 27210255, + -14820879, + 4832785, + 3162927, + -9459404, + 14282398, + -17817770, + 20227399, + -21658340, + 22247866, + -22125974, + 21416300, + -20236059, + 18695424, + -16896636, + 14933041, + -12888204, + 10835193, + -8836104, + 6941863, + -5192303, + 3616537, + -2233582, + 1053205, + -76956, + -700663, + 1290953, + -1709734, + 1976084, + -2111126, + 2136923, + -2075496, + 1947985, + -1773978, + 1571004, + -1354192, + 1136086, + -926597, + 733079, + -560512, + 411747, + -287817, + 188269, + -111509, + 55137, + -16255, + -8262, + 21533, + -26495, + 25769, + -21578, + 15704, + 18962, + -27306, + 34988, + -40361, + 41273, + -35082, + 18711, + 11250, + -58394, + 126283, + -218194, + 336810, + -483875, + 659829, + -863427, + 1091375, + -1338005, + 1594996, + -1851197, + 2092546, + -2302131, + 2460398, + -2545528, + 2533992, + -2401282, + 2122811, + -1674979, + 1036359, + -188992, + -880257, + 2178330, + -3704640, + 5449825, + -7394632, + 9508998, + -11751355, + 14068197, + -16393925, + 18650968, + -20750161, + 22591330, + -24063985, + 25048008, + -25414121, + 25023872, + -23728708, + 21367526, + -17761712, + 12706091, + -5953034, + -2815249, + 14035838, + -28355443, + 46806226, + -71176204, + 104879234, + -155336198, + 242177958, + -439312181, + 1473985027, + 1246691259, + -439366962, + 259773019, + -177143036, + 127744266, + -93881661, + 68728672, + -49116850, + 33386026, + -20584891, + 10126090, + -1620635, + -5208123, + 10571794, + -14643958, + 17575873, + -19505532, + 20562689, + -20871348, + 20550659, + -19714810, + 18472346, + -16925177, + 15167501, + -13284767, + 11352806, + -9437185, + 7592823, + -5863907, + 4284083, + -2876930, + 1656662, + -629040, + -207559, + 860977, + -1344037, + 1673318, + -1867950, + 1948495, + -1935938, + 1850813, + -1712472, + 1538527, + -1344445, + 1143299, + -945666, + 759643, + -590984, + 443301, + -318344, + 216307, + -136158, + 75960, + -33182, + 4969, + 11614, + -19397, + 20960, + -18531, + 13937, + 20415, + -29926, + 39307, + -46999, + 50913, + -48433, + 36449, + -11443, + -30366, + 92836, + -179645, + 293996, + -438269, + 613643, + -819707, + 1054065, + -1311976, + 1586036, + -1865943, + 2138358, + -2386900, + 2592285, + -2732634, + 2783955, + -2720821, + 2517211, + -2147538, + 1587815, + -816945, + -181902, + 1419877, + -2901050, + 4621064, + -6565910, + 8710865, + -11019644, + 13443792, + -15922356, + 18381828, + -20736347, + 22888124, + -24727997, + 26136004, + -26981779, + 27124498, + -26411970, + 24678250, + -21738804, + 17381646, + -11351690, + 3323342, + 7148289, + -20717466, + 38423769, + -62064156, + 95070804, + -144928208, + 231576876, + -431273337, + 1544210289, + 1166652915, + -431906599, + 260936430, + -181162165, + 133013836, + -99720106, + 74769245, + -55131011, + 39218141, + -26123945, + 15291914, + -6356487, + -939972, + 6793007, + -11362354, + 14787282, + -17195491, + 18708062, + -19441909, + 19510640, + -19024410, + 18089176, + -16805619, + 15267951, + -13562748, + 11767928, + -9951934, + 8173185, + -6479812, + 4909682, + -3490705, + 2241397, + -1171658, + 283730, + 426718, + -969422, + 1358332, + -1610432, + 1744617, + -1780666, + 1738329, + -1636563, + 1492909, + -1323039, + 1140441, + -956262, + 779269, + -615934, + 470595, + -345698, + 242078, + -159267, + 95806, + -49546, + 17928, + 1779, + -12276, + 16077, + -15402, + 12104, + 21727, + -32344, + 43372, + -53352, + 60281, + -61585, + 54148, + -34378, + -1670, + 58115, + -139011, + 248058, + -388253, + 561515, + -768274, + 1007059, + -1274104, + 1562991, + -1864362, + 2165720, + -2451359, + 2702434, + -2897192, + 3011385, + -3018876, + 2892430, + -2604680, + 2129273, + -1442140, + 522881, + 643792, + -2066592, + 3746234, + -5674102, + 7831057, + -10186438, + 12697295, + -15307879, + 17949415, + -20540122, + 22985480, + -25178637, + 27000871, + -28321905, + 28999825, + -28880195, + 27793763, + -25551809, + 21937552, + -16690916, + 9481707, + 138351, + -12824503, + 29613242, + -52292266, + 84277329, + -133041293, + 218638776, + -419006929, + 1611061257, + 1085130532, + -421026569, + 259812730, + -183536314, + 137051289, + -104620351, + 80095384, + -60608571, + 44658741, + -31391548, + 20286158, + -11003652, + 3307690, + 2979471, + -8002297, + 11886833, + -14749361, + 16701220, + -17851204, + 18306383, + -18171913, + 17550234, + -16539911, + 15234339, + -13720457, + 12077575, + -10376403, + 8678333, + -7035001, + 5488145, + -4069743, + 2802428, + -1700131, + 768920, + -7993, + -589233, + 1033977, + -1340942, + 1527205, + -1611174, + 1611655, + -1547047, + 1434675, + -1290277, + 1127640, + -958382, + 791862, + -635207, + 493441, + -369679, + 265385, + -180654, + 114513, + -65213, + 30505, + -7886, + -5195, + 11168, + -12221, + 10224, + 22882, + -34534, + 47140, + -59359, + 69286, + -74415, + 71650, + -57352, + 27448, + 22412, + -96627, + 199364, + -334221, + 503841, + -709500, + 950672, + -1224606, + 1525930, + -1846317, + 2174225, + -2494764, + 2789691, + -3037567, + 3214095, + -3292654, + 3245015, + -3042264, + 2655893, + -2059052, + 1227930, + -143212, + -1208407, + 2832735, + -4726652, + 6876797, + -9258433, + 11834517, + -14555023, + 17356537, + -20162106, + 22881332, + -25410646, + 27633641, + -29421314, + 30631958, + -31110315, + 30685406, + -29166108, + 26332935, + -21923374, + 15605928, + -6933500, + -4743380, + 20447306, + -41937914, + 72578373, + -119750545, + 203411881, + -402417494, + 1674196741, + 1002522870, + -406944515, + 256466592, + -184274377, + 139839272, + -108551136, + 84668259, + -65506873, + 49663770, + -36343930, + 25066542, + -15522212, + 7497929, + -835297, + -4593624, + 8900557, + -12189346, + 14560620, + -16114106, + 16949402, + -17165750, + 16861175, + -16131266, + 15067784, + -13757263, + 12279705, + -10707459, + 9104340, + -7525023, + 6014732, + -4609218, + 3335014, + -2209939, + 1243814, + -439351, + -206840, + 703166, + -1061936, + 1298274, + -1429068, + 1472025, + -1444834, + 1364454, + -1246558, + 1105111, + -952100, + 797389, + -648700, + 511692, + -390119, + 286056, + -200156, + 131936, + -80056, + 42596, + -17298, + 1783, + 6275, + -9020, + 8315, + 23861, + -36467, + 50570, + -64957, + 77840, + -86803, + 88795, + -80163, + 56735, + -13968, + -52848, + 148315, + -276605, + 441071, + -643829, + 885308, + -1163804, + 1475046, + -1811814, + 2163629, + -2516549, + 2853092, + -3152322, + 3390103, + -3539552, + 3571689, + -3456290, + 3162928, + -2662190, + 1927038, + -934281, + -333890, + 1888353, + -3731538, + 5856010, + -8243200, + 10862328, + -13669560, + 16607430, + -19604516, + 22575374, + -25420656, + 28027331, + -30268853, + 32005024, + -33081204, + 33326294, + -32548593, + 30528042, + -27002303, + 21641955, + -14005723, + 3456799, + 11002494, + -31084490, + 60062489, + -105144401, + 185964348, + -381434358, + 1733292929, + 919230043, + -389892917, + 250979157, + -183398825, + 141371328, + -111489903, + 88455946, + -69788669, + 54193326, + -40940402, + 29592957, + -19873648, + 11594563, + -4617986, + -1166410, + 5855070, + -9538508, + 12305779, + -14246680, + 15452479, + -16015642, + 16028933, + -15584131, + 14770562, + -13673598, + 12373230, + -10942806, + 9447995, + -7946022, + 6485189, + -5104687, + 3834699, + -2696758, + 1704333, + -863607, + 174394, + 368843, + -775933, + 1059923, + -1236051, + 1320778, + -1330936, + 1282976, + -1192373, + 1073150, + -937558, + 795880, + -656362, + 525245, + -406885, + 303946, + -217629, + 147939, + -93957, + 54102, + -26380, + 8599, + 1444, + -5827, + 6396, + 24652, + -38120, + 53623, + -70088, + 85858, + -98630, + 105425, + -102603, + 85932, + -50710, + -8043, + 95333, + -215873, + 373703, + -571766, + 811453, + -1092125, + 1410657, + -1761007, + 2133855, + -2516333, + 2891878, + -3240237, + 3537643, + -3757185, + 3869376, + -3842936, + 3645770, + -3246144, + 2614010, + -1722478, + 549367, + 921199, + -2697211, + 4777255, + -7149124, + 9788603, + -12658465, + 15707730, + -18871168, + 22069071, + -25207226, + 28177018, + -30855515, + 33105327, + -34773879, + 35691569, + -35667961, + 34484592, + -31881943, + 27536078, + -21016242, + 11705230, + 1358593, + -19820759, + 46826598, + -89324146, + 166384199, + -356012524, + 1788045388, + 835651130, + -370117263, + 243447040, + -180945296, + 141651802, + -113422889, + 91433629, + -73422396, + 58211969, + -45143688, + 33827799, + -24021166, + 15562468, + -8335781, + 2249300, + 2777338, + -6820561, + 9957089, + -12266029, + 13829538, + -14732511, + 15061650, + -14904133, + 14346076, + -13470945, + 12358019, + -11081000, + 9706831, + -8294777, + 6895781, + -5552119, + 4297344, + -3156496, + 2146555, + -1277105, + 551146, + 33961, + -485491, + 814318, + -1033906, + 1159341, + -1206457, + 1191062, + -1128300, + 1032134, + -914972, + 787427, + -658194, + 534037, + -419876, + 318934, + -232946, + 162404, + -106810, + 64933, + -35056, + 15196, + -3285, + -2671, + 4486, + 25239, + -39470, + 56262, + -74695, + 93258, + -109781, + 121381, + -124467, + 114778, + -87494, + 37402, + 40867, + -152529, + 302283, + -493883, + 729672, + -1010094, + 1333202, + -1694194, + 2084995, + -2493928, + 2905498, + -3300315, + 3655189, + -3943409, + 4135235, + -4198593, + 4099994, + -3805637, + 3282712, + -2500845, + 1433650, + -60364, + -1632522, + 3649657, + -5985339, + 8622158, + -11529861, + 14664431, + -17967441, + 21365659, + -24770876, + 28079890, + -31174528, + 33921484, + -36171680, + 37758628, + -38495008, + 38166124, + -36517932, + 33235399, + -27902981, + 19930010, + -8402015, + -8240152, + 32975282, + -72403305, + 144779108, + -326133398, + 1838170949, + 752181801, + -347874168, + 233981252, + -176962081, + 140695658, + -114345139, + 93583746, + -76382395, + 61688992, + -48920224, + 37736280, + -27930006, + 19367876, + -11956646, + 5623752, + -305555, + -4059659, + 7535642, + -10190147, + 12095522, + -13328374, + 13968601, + -14098029, + 13798821, + -13151816, + 12234890, + -11121454, + 9879137, + -8568716, + 7243322, + -5947933, + 4719164, + -3585327, + 2566749, + -1676309, + 920153, + -298545, + -193188, + 563669, + -824483, + 989219, + -1072585, + 1089616, + -1054999, + 982516, + -884627, + 772182, + -654246, + 538050, + -429026, + 330928, + -246006, + 175227, + -118517, + 75004, + -43259, + 21519, + -7872, + 420, + 2603, + 25612, + -40496, + 58454, + -78725, + 99962, + -120144, + 136512, + -145551, + 143011, + -123992, + 83091, + -14620, + -87103, + 227400, + -410806, + 640608, + -918333, + 1243242, + -1611817, + 2017309, + -2449339, + 2893622, + -3331801, + 3741465, + -4096339, + 4366682, + -4519902, + 4521390, + -4335568, + 3927131, + -3262462, + 2311181, + -1047792, + -546643, + 2482829, + -4761645, + 7372682, + -10292953, + 13485833, + -16900249, + 20470128, + -24114083, + 27735291, + -31221430, + 34444532, + -37260426, + 39507336, + -41002894, + 41538332, + -40867714, + 38688303, + -34604408, + 28058754, + -18195041, + 3559976, + 18620008, + -54506922, + 121276041, + -291805344, + 1883409467, + 669211988, + -323429438, + 222706022, + -171509518, + 138528209, + -114260449, + 94896062, + -78649082, + 64598648, + -52240413, + 41286705, + -31567728, + 22978662, + -15449598, + 8927739, + -3366650, + -1280185, + 5063036, + -8037747, + 10266256, + -11816236, + 12760103, + -13173636, + 13134340, + -12719729, + 12005603, + -11064443, + 9963971, + -8765941, + 7525200, + -6289024, + 5096758, + -3979723, + 2961401, + -2057836, + 1278248, + -625786, + 98404, + 310211, + -609676, + 811977, + -930578, + 979618, + -973202, + 924818, + -846872, + 750353, + -644621, + 537306, + -434304, + 339863, + -256724, + 186319, + -128994, + 84239, + -50925, + 27519, + -12279, + 3420, + 762, + 25760, + -41181, + 60168, + -82131, + 105896, + -129612, + 150668, + -165656, + 170372, + -159876, + 128622, + -70647, + -20152, + 149677, + -323216, + 544974, + -817560, + 1141452, + -1514461, + 1931226, + -2382769, + 2856139, + -3334182, + 3795463, + -4214369, + 4561418, + -4803776, + 4906012, + -4831065, + 4541425, + -4000512, + 3174192, + -2032432, + 551005, + 1286787, + -3488435, + 6050651, + -8957956, + 12181477, + -15677983, + 19389183, + -23241282, + 27144732, + -30994124, + 34668031, + -38028562, + 40920222, + -43167399, + 44569376, + -44890922, + 43844919, + -41060076, + 36019218, + -27934998, + 15479139, + 3878277, + -35770738, + 96020736, + -253064072, + 1923525437, + 587123604, + -297056103, + 209757541, + -164659296, + 135184764, + -113181235, + 95367687, + -80209056, + 66920333, + -55078860, + 44450730, + -34904482, + 26364616, + -18784972, + 12132853, + -6379345, + 1493467, + 2561186, + -5828101, + 8358301, + -10209964, + 11447420, + -12139757, + 12359165, + -12179166, + 11672834, + -10911091, + 9961162, + -8885237, + 7739394, + -6572788, + 5427136, + -4336485, + 3327248, + -2418482, + 1622383, + -944942, + 386739, + 56186, + -391413, + 629231, + -781756, + 862112, + -883711, + 859630, + -802116, + 722205, + -629470, + 531870, + -435714, + 345702, + -265040, + 195610, + -138170, + 92573, + -57995, + 33147, + -16471, + 6304, + -1021, + 25673, + -41508, + 61379, + -84869, + 110993, + -138085, + 163707, + -184588, + 196603, + -194820, + 173588, + -126723, + 47749, + 69772, + -231839, + 443549, + -708575, + 1028619, + -1402847, + 1827343, + -2294614, + 2793166, + -3307200, + 3816450, + -4296190, + 4717451, + -5047442, + 5250208, + -5287519, + 5119979, + -4708338, + 4014990, + -3005602, + 1650840, + 71871, + -2176600, + 4667245, + -7536011, + 10762067, + -14310448, + 18131206, + -22158829, + 26311898, + -30492909, + 34588128, + -38467274, + 41982648, + -44967150, + 47230183, + -48549745, + 48657566, + -47211161, + 43739933, + -37535934, + 27414545, + -11127283, + -16340257, + 69177047, + -209972840, + 1958309467, + 506288331, + -269032431, + 195282644, + -156493673, + 130710197, + -111128326, + 95003026, + -81055168, + 68638718, + -57414554, + 47203580, + -37913247, + 29497685, + -21934666, + 15211730, + -9317626, + 4237101, + 52129, + -3580862, + 6388806, + -8524167, + 10042659, + -11006100, + 11480755, + -11535531, + 11240147, + -10663357, + 9871305, + -8926078, + 7884490, + -6797138, + 5707742, + -4652764, + 3661304, + -2755252, + 1949657, + -1253285, + 669321, + -196180, + -171632, + 442630, + -627483, + 738200, + -787385, + 787599, + -750826, + 688056, + -608989, + 521847, + -433292, + 348435, + -270916, + 203045, + -145984, + 99947, + -64419, + 38364, + -20415, + 9050, + -2730, + 25347, + -41466, + 62063, + -86901, + 115191, + -145471, + 175496, + -202160, + 221457, + -228499, + 217584, + -182352, + 116009, + -11632, + -137445, + 337170, + -592261, + 905635, + -1277829, + 1706419, + -2185466, + 2705045, + -3250855, + 3803979, + -4340800, + 4833114, + -5248455, + 5550655, + -5700639, + 5657451, + -5379505, + 4826027, + -3958662, + 2743197, + -1151350, + -837438, + 3234254, + -6039090, + 9239385, + -12808789, + 16706180, + -20874964, + 25242624, + -29720490, + 34203615, + -38570585, + 42682955, + -46383827, + 49494718, + -51809282, + 53081195, + -53000986, + 51150832, + -46912163, + 39261957, + -26269887, + 3630263, + 40926138, + -162622486, + 1987579580, + 427065492, + -239639935, + 179437426, + -147104630, + 125158441, + -108130692, + 93813667, + -81186518, + 69743844, + -59231021, + 49524240, + -40570047, + 32352211, + -24872385, + 18138279, + -12156290, + 6926931, + -2442170, + -1315895, + 4375353, + -6774061, + 8558658, + -9783185, + 10507427, + -10795094, + 10711957, + -10324013, + 9695757, + -8888629, + 7959687, + -6960525, + 5936475, + -4926086, + 3960883, + -3065381, + 2257339, + -1548204, + 943727, + -444692, + 47730, + 253840, + -469161, + 609026, + -685135, + 709427, + -693522, + 648272, + -583421, + 507381, + -427109, + 348081, + -274335, + 208587, + -152389, + 106313, + -70153, + 43130, + -24082, + 11636, + -4353, + 24776, + -41045, + 62202, + -88193, + 118436, + -151685, + 185908, + -218195, + 244693, + -260597, + 260205, + -237035, + 184027, + -93830, + -40836, + 226729, + -469574, + 773490, + -1140390, + 1569368, + -2056108, + 2592342, + -3165403, + 3757896, + -4347520, + 4907084, + -5404732, + 5804393, + -6066481, + 6148828, + -6007858, + 5599968, + -4883094, + 3818418, + -2372166, + 517440, + 1763976, + -4479901, + 7626193, + -11185394, + 15125621, + -19399748, + 23944860, + -28681975, + 33515949, + -38335423, + 43012588, + -47402350, + 51340238, + -54637868, + 57073796, + -58375539, + 58183873, + -55979020, + 50916567, + -41419604, + 23978932, + 11465529, + -111131266, + 2011182355, + 349800015, + -209161388, + 162385816, + -136592947, + 118591910, + -104225104, + 91818213, + -80608413, + 70231160, + -60516428, + 51395615, + -42854139, + 34905137, + -27573848, + 20887905, + -14871158, + 9539788, + -4900005, + 946899, + 2335805, + -4975328, + 7008869, + -8482249, + 9448276, + -9964933, + 10093487, + -9896616, + 9436611, + -8773739, + 7964802, + -7061941, + 6111700, + -5154371, + 4223619, + -3346359, + 2542890, + -1827227, + 1207622, + -687209, + 264756, + 64535, + -308213, + 475774, + -577916, + 625862, + -630771, + 603265, + -553049, + 488653, + -417268, + 344684, + -275301, + 212216, + -157353, + 111632, + -75158, + 47413, + -27446, + 14043, + -5877, + 23958, + -40240, + 61783, + -88720, + 120682, + -156651, + 194830, + -232529, + 266080, + -290810, + 301058, + -290275, + 251198, + -176102, + 57155, + 113161, + -341536, + 633265, + -991629, + 1417259, + -1907506, + 2455845, + -3051362, + 3678341, + -4315997, + 4938397, + -5514568, + 6008853, + -6381492, + 6589466, + -6587576, + 6329755, + -5770576, + 4866931, + -3579822, + 1876214, + 269112, + -2871773, + 5936125, + -9453799, + 13402482, + -17744984, + 22428611, + -27384840, + 32529260, + -37761672, + 42966187, + -48011026, + 52747510, + -57007377, + 60596798, + -63283965, + 64773653, + -64653603, + 62273893, + -56444418, + 44537411, + -18991981, + -55644517, + 2028993885, + 274820508, + -177878863, + 144298116, + -125067226, + 111080862, + -99455732, + 89042050, + -79332261, + 70101518, + -61263655, + 52804641, + -44748173, + 37136188, + -30016996, + 23437709, + -17439283, + 12053316, + -7300122, + 3187762, + 288144, + -3143986, + 5407239, + -7115140, + 8313092, + -9052867, + 9390717, + -9385468, + 9096680, + -8582926, + 7900266, + -7100929, + 6232263, + -5335950, + 4447487, + -3595949, + 2803984, + -2088040, + 1458784, + -921659, + 477569, + -123625, + -146072, + 339648, + -466717, + 537691, + -563181, + 553487, + -518195, + 465879, + -403902, + 338315, + -273842, + 213930, + -160855, + 115877, + -79405, + 51186, + -30484, + 16255, + -7291, + 22893, + -39047, + 60797, + -88461, + 121889, + -160303, + 202158, + -245007, + 285404, + -318842, + 339756, + -341584, + 316916, + -257723, + 155676, + -2562, + -209227, + 486122, + -832755, + 1251300, + -1740806, + 2296561, + -2909506, + 3565750, + -4246216, + 4926455, + -5576655, + 6161880, + -6642542, + 6975138, + -7113230, + 7008674, + -6613058, + 5879339, + -4763610, + 3226955, + -1237339, + -1228552, + 4183576, + -7628574, + 11551047, + -15924126, + 20705865, + -25838881, + 31250333, + -36852187, + 42541661, + -48201681, + 53701008, + -58893491, + 63615426, + -67679039, + 70858001, + -72855508, + 73230683, + -71211315, + 65132180, + -50219533, + 3665864, + 2040920553, + 202437454, + -146071804, + 125349518, + -112642869, + 102702698, + -93873686, + 85517061, + -77375422, + 69361125, + -61470316, + 53742377, + -46238318, + 39028029, + -32182163, + 25766684, + -19839141, + 14446163, + -9621900, + 5387242, + -1749686, + -1296238, + 3768082, + -5694215, + 7112269, + -8067382, + 8610325, + -8795578, + 8679465, + -8318367, + 7767115, + -7077580, + 6297499, + -5469572, + 4630820, + -3812207, + 3038528, + -2328509, + 1695122, + -1146060, + 684343, + -309003, + 15832, + 201868, + -352550, + 445735, + -491395, + 499428, + -479218, + 439310, + -387174, + 329072, + -270006, + 213742, + -162889, + 119028, + -82870, + 54425, + -33177, + 18257, + -8587, + 21584, + -37469, + 59240, + -87403, + 122028, + -162587, + 207801, + -255492, + 302462, + -344416, + 375929, + -390482, + 380583, + -337960, + 253861, + -119438, + -73774, + 333296, + -665080, + 1072832, + -1557324, + 2115704, + -2740859, + 3420855, + -4138496, + 4871039, + -5590096, + 6261758, + -6846953, + 7302070, + -7579828, + 7630412, + -7402834, + 6846504, + -5912963, + 4557730, + -2742200, + 435527, + 2383577, + -5725198, + 9586815, + -13952169, + 18790497, + -24056139, + 29688561, + -35612789, + 41740222, + -47969753, + 54189075, + -60275949, + 66099041, + -71517607, + 76378552, + -80507556, + 83685820, + -85587395, + 85585861, + -81977543, + 66602126, + 2046899622, + 132941541, + -114015156, + 105718606, + -99441004, + 93541217, + -87536496, + 81281290, + -74761003, + 68021442, + -61138747, + 54204052, + -47314357, + 40566402, + -34052237, + 27855880, + -22050812, + 16698162, + -11845528, + 7526369, + -3759934, + 551667, + 2105955, + -4232224, + 5856710, + -7017554, + 7759626, + -8132611, + 8189120, + -7982865, + 7566982, + -6992531, + 6307227, + -5554417, + 4772312, + -3993496, + 3244679, + -2546691, + 1914689, + -1358535, + 883322, + -490003, + 176084, + 63656, + -236445, + 350838, + -416089, + 441610, + -436508, + 409224, + -367273, + 317073, + -263860, + 211683, + -163460, + 121078, + -85539, + 57114, + -35510, + 20037, + -9755 + +}; + +static const struct src_stage src_int32_32_21_4535_5000 = { + 19, 29, 32, 120, 3840, 21, 32, 0, 0, + src_int32_32_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_3_1_2268_5000.h b/src/audio/src/coef/src_ipc4_int32_3_1_2268_5000.h new file mode 100644 index 000000000000..734e68049ada --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_3_1_2268_5000.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_1_2268_5000_fir[72] = { + 148487, + -366788, + -1294441, + 6720648, + -11685212, + 2793292, + 31054730, + -74752061, + 74901983, + 36025656, + -295074818, + 761569860, + 1522245763, + 260024579, + -271138473, + 134164310, + -9075631, + -44280069, + 38072282, + -13179108, + -2293528, + 4631871, + -1953911, + 207956, + 297779, + -1314304, + 1178879, + 4726965, + -17416178, + 24251539, + -479885, + -65892536, + 139476928, + -126102342, + -120024679, + 1235055929, + 1235055929, + -120024679, + -126102342, + 139476928, + -65892536, + -479885, + 24251539, + -17416178, + 4726965, + 1178879, + -1314304, + 297779, + 207956, + -1953911, + 4631871, + -2293528, + -13179108, + 38072282, + -44280069, + -9075631, + 134164310, + -271138473, + 260024579, + 1522245763, + 761569860, + -295074818, + 36025656, + 74901983, + -74752061, + 31054730, + 2793292, + -11685212, + 6720648, + -1294441, + -366788, + 148487 + +}; + +static const struct src_stage src_int32_3_1_2268_5000 = { + 0, 1, 3, 24, 72, 1, 3, 0, 0, + src_int32_3_1_2268_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_3_1_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_3_1_4535_5000.h new file mode 100644 index 000000000000..fa1e6bb57859 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_3_1_4535_5000.h @@ -0,0 +1,354 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_1_4535_5000_fir[336] = { + -19074, + 36914, + -62611, + 97195, + -141200, + 194443, + -255803, + 323004, + -392424, + 458955, + -515918, + 555066, + -566688, + 539818, + -462579, + 322643, + -107823, + -193216, + 590158, + -1090145, + 1696858, + -2409581, + 3222304, + -4122914, + 5092508, + -6104893, + 7126294, + -8115334, + 9023291, + -9794662, + 10368033, + -10677258, + 10652898, + -10223900, + 9319442, + -7870875, + 5813664, + -3089216, + -353530, + 4556910, + -9553906, + 15368330, + -22016094, + 29508020, + -37854820, + 47075378, + -57210254, + 68344119, + -80644582, + 94433611, + -110330099, + 129565961, + -154792101, + 192583982, + -264135956, + 492930479, + 1963571228, + -202347703, + 64532067, + -13032486, + -13622216, + 29322436, + -38972979, + 44774978, + -47891168, + 49019590, + -48627040, + 47055406, + -44573947, + 41406259, + -37744505, + 33756899, + -29591520, + 25378133, + -21228967, + 17239042, + -13486362, + 10032212, + -6921659, + 4184318, + -1835414, + -122903, + 1700007, + -2915064, + 3795192, + -4373569, + 4687564, + -4776933, + 4682169, + -4443015, + 4097204, + -3679428, + 3220574, + -2747191, + 2281216, + -1839915, + 1436019, + -1078029, + 770646, + -515292, + 310692, + -153472, + 38746, + 39325, + -87041, + 110737, + -116437, + 109595, + -94921, + 76284, + -56679, + 38263, + 8424, + -5777, + -3380, + 21825, + -52590, + 98781, + -163350, + 248816, + -356932, + 488337, + -642180, + 815753, + -1004161, + 1200033, + -1393324, + 1571224, + -1718201, + 1816194, + -1844986, + 1782754, + -1606804, + 1294489, + -824281, + 176992, + 662912, + -1705934, + 2956149, + -4409869, + 6054390, + -7866907, + 9813635, + -11849181, + 13916209, + -15945404, + 17855745, + -19555054, + 20940764, + -21900823, + 22314579, + -22053455, + 20981125, + -18952750, + 15812680, + -11389616, + 5487673, + 2129374, + -11765537, + 23841162, + -38981895, + 58191045, + -83210816, + 117365222, + -167846876, + 253488767, + -443615130, + 1363071865, + 1363071865, + -443615130, + 253488767, + -167846876, + 117365222, + -83210816, + 58191045, + -38981895, + 23841162, + -11765537, + 2129374, + 5487673, + -11389616, + 15812680, + -18952750, + 20981125, + -22053455, + 22314579, + -21900823, + 20940764, + -19555054, + 17855745, + -15945404, + 13916209, + -11849181, + 9813635, + -7866907, + 6054390, + -4409869, + 2956149, + -1705934, + 662912, + 176992, + -824281, + 1294489, + -1606804, + 1782754, + -1844986, + 1816194, + -1718201, + 1571224, + -1393324, + 1200033, + -1004161, + 815753, + -642180, + 488337, + -356932, + 248816, + -163350, + 98781, + -52590, + 21825, + -3380, + -5777, + 8424, + 38263, + -56679, + 76284, + -94921, + 109595, + -116437, + 110737, + -87041, + 39325, + 38746, + -153472, + 310692, + -515292, + 770646, + -1078029, + 1436019, + -1839915, + 2281216, + -2747191, + 3220574, + -3679428, + 4097204, + -4443015, + 4682169, + -4776933, + 4687564, + -4373569, + 3795192, + -2915064, + 1700007, + -122903, + -1835414, + 4184318, + -6921659, + 10032212, + -13486362, + 17239042, + -21228967, + 25378133, + -29591520, + 33756899, + -37744505, + 41406259, + -44573947, + 47055406, + -48627040, + 49019590, + -47891168, + 44774978, + -38972979, + 29322436, + -13622216, + -13032486, + 64532067, + -202347703, + 1963571228, + 492930479, + -264135956, + 192583982, + -154792101, + 129565961, + -110330099, + 94433611, + -80644582, + 68344119, + -57210254, + 47075378, + -37854820, + 29508020, + -22016094, + 15368330, + -9553906, + 4556910, + -353530, + -3089216, + 5813664, + -7870875, + 9319442, + -10223900, + 10652898, + -10677258, + 10368033, + -9794662, + 9023291, + -8115334, + 7126294, + -6104893, + 5092508, + -4122914, + 3222304, + -2409581, + 1696858, + -1090145, + 590158, + -193216, + -107823, + 322643, + -462579, + 539818, + -566688, + 555066, + -515918, + 458955, + -392424, + 323004, + -255803, + 194443, + -141200, + 97195, + -62611, + 36914, + -19074 + +}; + +static const struct src_stage src_int32_3_1_4535_5000 = { + 0, 1, 3, 112, 336, 1, 3, 0, 0, + src_int32_3_1_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_3_2_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_3_2_4535_5000.h new file mode 100644 index 000000000000..e7b06f3442ac --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_3_2_4535_5000.h @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_2_4535_5000_fir[324] = { + -40556, + 70616, + -110283, + 159615, + -217734, + 282592, + -350775, + 417339, + -475724, + 517743, + -533682, + 512506, + -442202, + 310246, + -104205, + -187548, + 575015, + -1065670, + 1663523, + -2368172, + 3173886, + -4068786, + 5034148, + -6043893, + 7064296, + -8053959, + 8964075, + -9738998, + 10317122, + -10632071, + 10614148, + -10192031, + 9294631, + -7853043, + 5802500, + -3084210, + -353049, + 4551728, + -9544884, + 15356358, + -22002055, + 29492749, + -37839083, + 47059845, + -57195488, + 68330567, + -80632573, + 94423361, + -110321717, + 129559461, + -154787412, + 192580966, + -264134436, + 492930371, + 1963573486, + -202347380, + 64531515, + -13032225, + -13621721, + 29320733, + -38969626, + 44769556, + -47883299, + 49008953, + -48613394, + 47038612, + -44553988, + 41383262, + -37718752, + 33728839, + -29561771, + 25347473, + -21198324, + 17209463, + -13458984, + 10008218, + -6902229, + 4170582, + -1828390, + -122357, + 1691241, + -2897679, + 3769073, + -4338905, + 4644849, + -4726964, + 4626018, + -4381995, + 4032817, + -3613311, + 3154425, + -2682705, + 2220013, + -1783472, + 1385613, + -1034685, + 735101, + -487976, + 291715, + -142638, + 35573, + 35569, + -77291, + 96074, + -98032, + 88647, + -72600, + 53678, + -2290, + 16299, + -41842, + 82172, + -140433, + 219374, + -321012, + 446265, + -594567, + 763486, + -948373, + 1142070, + -1334691, + 1513526, + -1663076, + 1765244, + -1799707, + 1744470, + -1576614, + 1273215, + -812440, + 174771, + 655654, + -1689654, + 2931599, + -4378051, + 6016509, + -7824313, + 9767763, + -11801487, + 13868111, + -15898229, + 17810679, + -19513106, + 20902743, + -21867316, + 22285955, + -22029868, + 20962529, + -18938927, + 15803265, + -11384131, + 5485558, + 2128726, + -11762749, + 23836853, + -38976651, + 58185408, + -83205269, + 117360184, + -167842702, + 253485761, + -443613605, + 1363072811, + 1363072811, + -443613605, + 253485761, + -167842702, + 117360184, + -83205269, + 58185408, + -38976651, + 23836853, + -11762749, + 2128726, + 5485558, + -11384131, + 15803265, + -18938927, + 20962529, + -22029868, + 22285955, + -21867316, + 20902743, + -19513106, + 17810679, + -15898229, + 13868111, + -11801487, + 9767763, + -7824313, + 6016509, + -4378051, + 2931599, + -1689654, + 655654, + 174771, + -812440, + 1273215, + -1576614, + 1744470, + -1799707, + 1765244, + -1663076, + 1513526, + -1334691, + 1142070, + -948373, + 763486, + -594567, + 446265, + -321012, + 219374, + -140433, + 82172, + -41842, + 16299, + -2290, + 53678, + -72600, + 88647, + -98032, + 96074, + -77291, + 35569, + 35573, + -142638, + 291715, + -487976, + 735101, + -1034685, + 1385613, + -1783472, + 2220013, + -2682705, + 3154425, + -3613311, + 4032817, + -4381995, + 4626018, + -4726964, + 4644849, + -4338905, + 3769073, + -2897679, + 1691241, + -122357, + -1828390, + 4170582, + -6902229, + 10008218, + -13458984, + 17209463, + -21198324, + 25347473, + -29561771, + 33728839, + -37718752, + 41383262, + -44553988, + 47038612, + -48613394, + 49008953, + -47883299, + 44769556, + -38969626, + 29320733, + -13621721, + -13032225, + 64531515, + -202347380, + 1963573486, + 492930371, + -264134436, + 192580966, + -154787412, + 129559461, + -110321717, + 94423361, + -80632573, + 68330567, + -57195488, + 47059845, + -37839083, + 29492749, + -22002055, + 15356358, + -9544884, + 4551728, + -353049, + -3084210, + 5802500, + -7853043, + 9294631, + -10192031, + 10614148, + -10632071, + 10317122, + -9738998, + 8964075, + -8053959, + 7064296, + -6043893, + 5034148, + -4068786, + 3173886, + -2368172, + 1663523, + -1065670, + 575015, + -187548, + -104205, + 310246, + -442202, + 512506, + -533682, + 517743, + -475724, + 417339, + -350775, + 282592, + -217734, + 159615, + -110283, + 70616, + -40556 + +}; + +static const struct src_stage src_int32_3_2_4535_5000 = { + 1, 2, 3, 108, 324, 2, 3, 0, 0, + src_int32_3_2_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_3_4_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_3_4_4535_5000.h new file mode 100644 index 000000000000..9bcef1518a93 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_3_4_4535_5000.h @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_4_4535_5000_fir[360] = { + 77760, + 40171, + -209346, + 268623, + -83754, + -288396, + 565645, + -428842, + -171526, + 855717, + -1016352, + 313746, + 911128, + -1725457, + 1271000, + 433621, + -2251078, + 2622808, + -834492, + -2131719, + 4021242, + -2951386, + -870399, + 4834892, + -5618625, + 1860753, + 4254282, + -8094452, + 5980974, + 1523617, + -9241570, + 10805709, + -3740230, + -7741487, + 14981354, + -11223585, + -2454534, + 16607992, + -19687642, + 7151845, + 13548420, + -26914303, + 20620488, + 3840268, + -29828132, + 36273656, + -13967383, + -24640225, + 51158790, + -40881789, + -6482034, + 60949151, + -78795138, + 33542191, + 58523738, + -137471755, + 127930780, + 19720089, + -308236621, + 782819242, + 1500004125, + 291039308, + -310493011, + 158176817, + 10291798, + -105950006, + 103206313, + -35044694, + -38131925, + 68582962, + -46426544, + -2485345, + 40193831, + -43481010, + 16381694, + 17327450, + -33458422, + 23833482, + 752059, + -20937457, + 23440951, + -9274248, + -9154338, + 18383439, + -13409513, + -120349, + 11468263, + -13074862, + 5346615, + 4864464, + -10058903, + 7435092, + -96000, + -6078534, + 7000141, + -2930869, + -2439032, + 5162341, + -3837232, + 128991, + 2954163, + -3410716, + 1448483, + 1092990, + -2350879, + 1740387, + -91562, + -1235013, + 1412461, + -599492, + -403716, + 868891, + -627970, + 43043, + 390594, + -428467, + 174483, + 99717, + -201995, + 131033, + 139781, + -95260, + -93345, + 308758, + -334018, + 39101, + 438844, + -715080, + 437475, + 354652, + -1119258, + 1143852, + -153305, + -1291857, + 2044315, + -1231013, + -883471, + 2813267, + -2833816, + 433776, + 2930864, + -4616554, + 2791266, + 1802394, + -5899965, + 5940397, + -1024897, + -5762384, + 9133321, + -5594127, + -3272137, + 11139541, + -11301481, + 2173193, + 10439271, + -16780856, + 10481649, + 5579642, + -19976186, + 20580558, + -4382597, + -18403477, + 30293121, + -19475736, + -9506678, + 36377686, + -38581001, + 9135563, + 34529446, + -59476053, + 40340946, + 18546563, + -79183343, + 90769761, + -25244110, + -94560789, + 193357259, + -168185247, + -102991933, + 1232227468, + 1232227468, + -102991933, + -168185247, + 193357259, + -94560789, + -25244110, + 90769761, + -79183343, + 18546563, + 40340946, + -59476053, + 34529446, + 9135563, + -38581001, + 36377686, + -9506678, + -19475736, + 30293121, + -18403477, + -4382597, + 20580558, + -19976186, + 5579642, + 10481649, + -16780856, + 10439271, + 2173193, + -11301481, + 11139541, + -3272137, + -5594127, + 9133321, + -5762384, + -1024897, + 5940397, + -5899965, + 1802394, + 2791266, + -4616554, + 2930864, + 433776, + -2833816, + 2813267, + -883471, + -1231013, + 2044315, + -1291857, + -153305, + 1143852, + -1119258, + 354652, + 437475, + -715080, + 438844, + 39101, + -334018, + 308758, + -93345, + -95260, + 139781, + 131033, + -201995, + 99717, + 174483, + -428467, + 390594, + 43043, + -627970, + 868891, + -403716, + -599492, + 1412461, + -1235013, + -91562, + 1740387, + -2350879, + 1092990, + 1448483, + -3410716, + 2954163, + 128991, + -3837232, + 5162341, + -2439032, + -2930869, + 7000141, + -6078534, + -96000, + 7435092, + -10058903, + 4864464, + 5346615, + -13074862, + 11468263, + -120349, + -13409513, + 18383439, + -9154338, + -9274248, + 23440951, + -20937457, + 752059, + 23833482, + -33458422, + 17327450, + 16381694, + -43481010, + 40193831, + -2485345, + -46426544, + 68582962, + -38131925, + -35044694, + 103206313, + -105950006, + 10291798, + 158176817, + -310493011, + 291039308, + 1500004125, + 782819242, + -308236621, + 19720089, + 127930780, + -137471755, + 58523738, + 33542191, + -78795138, + 60949151, + -6482034, + -40881789, + 51158790, + -24640225, + -13967383, + 36273656, + -29828132, + 3840268, + 20620488, + -26914303, + 13548420, + 7151845, + -19687642, + 16607992, + -2454534, + -11223585, + 14981354, + -7741487, + -3740230, + 10805709, + -9241570, + 1523617, + 5980974, + -8094452, + 4254282, + 1860753, + -5618625, + 4834892, + -870399, + -2951386, + 4021242, + -2131719, + -834492, + 2622808, + -2251078, + 433621, + 1271000, + -1725457, + 911128, + 313746, + -1016352, + 855717, + -171526, + -428842, + 565645, + -288396, + -83754, + 268623, + -209346, + 40171, + 77760 + +}; + +static const struct src_stage src_int32_3_4_4535_5000 = { + 1, 1, 3, 120, 360, 4, 3, 0, 0, + src_int32_3_4_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_40_21_2381_5000.h b/src/audio/src/coef/src_ipc4_int32_40_21_2381_5000.h new file mode 100644 index 000000000000..b207869f84f8 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_40_21_2381_5000.h @@ -0,0 +1,978 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_40_21_2381_5000_fir[960] = { + 50137, + 248031, + -2186295, + 5352830, + -3978047, + -11090318, + 39707788, + -57579100, + 19662567, + 107814385, + -307529889, + 507418467, + 1584830600, + 468330845, + -304205621, + 114512274, + 13160800, + -54669435, + 39703362, + -12081341, + -3238429, + 5100549, + -2180662, + 277702, + 59770, + 214950, + -2182896, + 5594436, + -4728392, + -10028460, + 39568688, + -60355527, + 26251368, + 100566923, + -309873827, + 546841030, + 1583002821, + 429647750, + -299940898, + 120651487, + 6766512, + -51639981, + 39559160, + -12999958, + -2511965, + 4838999, + -2166445, + 304023, + 70168, + 178417, + -2170038, + 5823954, + -5486913, + -8897657, + 39282749, + -62985426, + 32905971, + 92781063, + -311199309, + 586527408, + 1579351201, + 391437068, + -294777207, + 126224972, + 499310, + -48504290, + 39279342, + -13844912, + -1800956, + 4569570, + -2144112, + 327066, + 81313, + 138404, + -2147318, + 6039967, + -6250942, + -7700115, + 38847118, + -65455718, + 39604415, + 84470060, + -311470091, + 626405103, + 1573883606, + 353764827, + -288757503, + 131227711, + -5622088, + -45275972, + 38868454, + -14615256, + -1107566, + 4293631, + -2114141, + 346914, + 93181, + 94902, + -2114358, + 6241057, + -7017702, + -6438362, + 38259424, + -67753583, + 46324071, + 75649255, + -310651944, + 666400413, + 1566611810, + 316695054, + -281926071, + 135656686, + -11579893, + -41968641, + 38331402, + -15310348, + -433823, + 4012527, + -2077028, + 363666, + 105739, + 47919, + -2070810, + 6425820, + -7784314, + -5115242, + 37517799, + -69866519, + 53041704, + 66336069, + -308712782, + 706438612, + 1557551461, + 280289624, + -274328376, + 139510850, + -17357293, + -38595867, + 37673425, + -15929846, + 218388, + 3727574, + -2033274, + 377429, + 118950, + -2519, + -2016360, + 6592863, + -8547805, + -3733917, + 36620898, + -71782390, + 59733543, + 56549995, + -305622782, + 746444127, + 1546722043, + 244608132, + -266010919, + 142791081, + -22938484, + -35171129, + 36900067, + -16473700, + 847325, + 3440053, + -1983388, + 388321, + 132767, + -56366, + -1950725, + 6740815, + -9305118, + -2297860, + 35567918, + -73489482, + 66375348, + 46312585, + -301354502, + 786340719, + 1534146821, + 209707759, + -257021091, + 145500143, + -28308702, + -31707770, + 36017146, + -16942144, + 1451396, + 3151207, + -1927885, + 396467, + 147136, + -113555, + -1873665, + 6868333, + -10053123, + -810854, + 34358612, + -74976553, + 72942489, + 35647424, + -295882994, + 826051674, + 1519852781, + 175643157, + -247407024, + 147642630, + -33454255, + -28218951, + 35030732, + -17335689, + 2029156, + 2862237, + -1867280, + 402001, + 161996, + -173998, + -1784977, + 6974109, + -10788622, + 723019, + 32993309, + -76232885, + 79410018, + 24580099, + -289185913, + 865499986, + 1503870559, + 142466329, + -237217444, + 149224915, + -38362541, + -24717608, + 33947112, + -17655110, + 2579309, + 2574297, + -1802086, + 405063, + 177279, + -237586, + -1684502, + 7056877, + -11508367, + 2299379, + 31472921, + -77248339, + 85752752, + 13138168, + -281243611, + 904608551, + 1486234359, + 110226530, + -226501521, + 150255086, + -43022075, + -21216411, + 32772764, + -17901438, + 3100711, + 2288494, + -1732817, + 405797, + 192908, + -304187, + -1572127, + 7115417, + -12209067, + 3913563, + 29798959, + -78013398, + 91945354, + 1351110, + -272039236, + 943300358, + 1466981863, + 78970168, + -215308729, + 150742887, + -47422494, + -17727725, + 31514329, + -18075947, + 3592366, + 2005885, + -1659977, + 404352, + 208800, + -373647, + -1447789, + 7148565, + -12887398, + 5560630, + 27973540, + -78519223, + 97962417, + -10749718, + -261558819, + 981498679, + 1446154131, + 48740716, + -203688694, + 150699644, + -51554579, + -14263574, + 30178580, + -18180146, + 4053429, + 1727468, + -1584065, + 400883, + 224861, + -445789, + -1311472, + 7155221, + -13540021, + 7235378, + 25999396, + -78757697, + 103778548, + -23131144, + -249791351, + 1019127263, + 1423795495, + 19578635, + -191691055, + 150138197, + -55410253, + -10835603, + 28772397, + -18215761, + 4483200, + 1454190, + -1505571, + 395542, + 240995, + -520413, + -1163216, + 7134351, + -14163590, + 8932350, + 23879876, + -78721470, + 109368462, + -35758239, + -236728857, + 1056110529, + 1399953437, + -8478698, + -179365319, + 149072825, + -58982586, + -7455048, + 27302733, + -18184728, + 4881128, + 1186937, + -1424973, + 388485, + 257095, + -597295, + -1003113, + 7084997, + -14754770, + 10645853, + 21618952, + -78404007, + 114707065, + -48594390, + -222366462, + 1092373757, + 1374678469, + -35397050, + -166760729, + 147519163, + -62265796, + -4132702, + 25776594, + -18089175, + 5246802, + 926534, + -1342735, + 379870, + 273047, + -676189, + -831312, + 7006285, + -15310245, + 12369975, + 19221218, + -77799628, + 119769550, + -61601377, + -206702445, + 1127843277, + 1348024000, + -61145383, + -153926120, + 145494125, + -65255242, + -878889, + 24201004, + -17931409, + 5579952, + 673748, + -1259309, + 369852, + 288734, + -756825, + -648022, + 6897429, + -15826734, + 14098594, + 16691888, + -76903548, + 124531486, + -74739451, + -189738290, + 1162446657, + 1320046192, + -85695898, + -140909793, + 143015817, + -67947413, + 2296562, + 22582984, + -17713905, + 5880446, + 429282, + -1175127, + 358586, + 304029, + -838911, + -453510, + 6757736, + -16301008, + 15825406, + 14036795, + -75711916, + 128968908, + -87967427, + -171478723, + 1196112891, + 1290803818, + -109024067, + -127759382, + 140103453, + -70339918, + 5384343, + 20929524, + -17439290, + 6148282, + 193777, + -1090609, + 346223, + 318800, + -922132, + -248102, + 6586616, + -16729902, + 17543933, + 11262380, + -74221848, + 133058417, + -101242778, + -151931746, + 1228772579, + 1260358106, + -131108657, + -114521732, + 136777266, + -72431466, + 8375685, + 19247556, + -17110327, + 6383588, + -32189, + -1006151, + 332912, + 332912, + -1006151, + -32189, + 6383588, + -17110327, + 19247556, + 8375685, + -72431466, + 136777266, + -114521732, + -131108657, + 1260358106, + 1228772579, + -151931746, + -101242778, + 133058417, + -74221848, + 11262380, + 17543933, + -16729902, + 6586616, + -248102, + -922132, + 318800, + 346223, + -1090609, + 193777, + 6148282, + -17439290, + 20929524, + 5384343, + -70339918, + 140103453, + -127759382, + -109024067, + 1290803818, + 1196112891, + -171478723, + -87967427, + 128968908, + -75711916, + 14036795, + 15825406, + -16301008, + 6757736, + -453510, + -838911, + 304029, + 358586, + -1175127, + 429282, + 5880446, + -17713905, + 22582984, + 2296562, + -67947413, + 143015817, + -140909793, + -85695898, + 1320046192, + 1162446657, + -189738290, + -74739451, + 124531486, + -76903548, + 16691888, + 14098594, + -15826734, + 6897429, + -648022, + -756825, + 288734, + 369852, + -1259309, + 673748, + 5579952, + -17931409, + 24201004, + -878889, + -65255242, + 145494125, + -153926120, + -61145383, + 1348024000, + 1127843277, + -206702445, + -61601377, + 119769550, + -77799628, + 19221218, + 12369975, + -15310245, + 7006285, + -831312, + -676189, + 273047, + 379870, + -1342735, + 926534, + 5246802, + -18089175, + 25776594, + -4132702, + -62265796, + 147519163, + -166760729, + -35397050, + 1374678469, + 1092373757, + -222366462, + -48594390, + 114707065, + -78404007, + 21618952, + 10645853, + -14754770, + 7084997, + -1003113, + -597295, + 257095, + 388485, + -1424973, + 1186937, + 4881128, + -18184728, + 27302733, + -7455048, + -58982586, + 149072825, + -179365319, + -8478698, + 1399953437, + 1056110529, + -236728857, + -35758239, + 109368462, + -78721470, + 23879876, + 8932350, + -14163590, + 7134351, + -1163216, + -520413, + 240995, + 395542, + -1505571, + 1454190, + 4483200, + -18215761, + 28772397, + -10835603, + -55410253, + 150138197, + -191691055, + 19578635, + 1423795495, + 1019127263, + -249791351, + -23131144, + 103778548, + -78757697, + 25999396, + 7235378, + -13540021, + 7155221, + -1311472, + -445789, + 224861, + 400883, + -1584065, + 1727468, + 4053429, + -18180146, + 30178580, + -14263574, + -51554579, + 150699644, + -203688694, + 48740716, + 1446154131, + 981498679, + -261558819, + -10749718, + 97962417, + -78519223, + 27973540, + 5560630, + -12887398, + 7148565, + -1447789, + -373647, + 208800, + 404352, + -1659977, + 2005885, + 3592366, + -18075947, + 31514329, + -17727725, + -47422494, + 150742887, + -215308729, + 78970168, + 1466981863, + 943300358, + -272039236, + 1351110, + 91945354, + -78013398, + 29798959, + 3913563, + -12209067, + 7115417, + -1572127, + -304187, + 192908, + 405797, + -1732817, + 2288494, + 3100711, + -17901438, + 32772764, + -21216411, + -43022075, + 150255086, + -226501521, + 110226530, + 1486234359, + 904608551, + -281243611, + 13138168, + 85752752, + -77248339, + 31472921, + 2299379, + -11508367, + 7056877, + -1684502, + -237586, + 177279, + 405063, + -1802086, + 2574297, + 2579309, + -17655110, + 33947112, + -24717608, + -38362541, + 149224915, + -237217444, + 142466329, + 1503870559, + 865499986, + -289185913, + 24580099, + 79410018, + -76232885, + 32993309, + 723019, + -10788622, + 6974109, + -1784977, + -173998, + 161996, + 402001, + -1867280, + 2862237, + 2029156, + -17335689, + 35030732, + -28218951, + -33454255, + 147642630, + -247407024, + 175643157, + 1519852781, + 826051674, + -295882994, + 35647424, + 72942489, + -74976553, + 34358612, + -810854, + -10053123, + 6868333, + -1873665, + -113555, + 147136, + 396467, + -1927885, + 3151207, + 1451396, + -16942144, + 36017146, + -31707770, + -28308702, + 145500143, + -257021091, + 209707759, + 1534146821, + 786340719, + -301354502, + 46312585, + 66375348, + -73489482, + 35567918, + -2297860, + -9305118, + 6740815, + -1950725, + -56366, + 132767, + 388321, + -1983388, + 3440053, + 847325, + -16473700, + 36900067, + -35171129, + -22938484, + 142791081, + -266010919, + 244608132, + 1546722043, + 746444127, + -305622782, + 56549995, + 59733543, + -71782390, + 36620898, + -3733917, + -8547805, + 6592863, + -2016360, + -2519, + 118950, + 377429, + -2033274, + 3727574, + 218388, + -15929846, + 37673425, + -38595867, + -17357293, + 139510850, + -274328376, + 280289624, + 1557551461, + 706438612, + -308712782, + 66336069, + 53041704, + -69866519, + 37517799, + -5115242, + -7784314, + 6425820, + -2070810, + 47919, + 105739, + 363666, + -2077028, + 4012527, + -433823, + -15310348, + 38331402, + -41968641, + -11579893, + 135656686, + -281926071, + 316695054, + 1566611810, + 666400413, + -310651944, + 75649255, + 46324071, + -67753583, + 38259424, + -6438362, + -7017702, + 6241057, + -2114358, + 94902, + 93181, + 346914, + -2114141, + 4293631, + -1107566, + -14615256, + 38868454, + -45275972, + -5622088, + 131227711, + -288757503, + 353764827, + 1573883606, + 626405103, + -311470091, + 84470060, + 39604415, + -65455718, + 38847118, + -7700115, + -6250942, + 6039967, + -2147318, + 138404, + 81313, + 327066, + -2144112, + 4569570, + -1800956, + -13844912, + 39279342, + -48504290, + 499310, + 126224972, + -294777207, + 391437068, + 1579351201, + 586527408, + -311199309, + 92781063, + 32905971, + -62985426, + 39282749, + -8897657, + -5486913, + 5823954, + -2170038, + 178417, + 70168, + 304023, + -2166445, + 4838999, + -2511965, + -12999958, + 39559160, + -51639981, + 6766512, + 120651487, + -299940898, + 429647750, + 1583002821, + 546841030, + -309873827, + 100566923, + 26251368, + -60355527, + 39568688, + -10028460, + -4728392, + 5594436, + -2182896, + 214950, + 59770, + 277702, + -2180662, + 5100549, + -3238429, + -12081341, + 39703362, + -54669435, + 13160800, + 114512274, + -304205621, + 468330845, + 1584830600, + 507418467, + -307529889, + 107814385, + 19662567, + -57579100, + 39707788, + -11090318, + -3978047, + 5352830, + -2186295, + 248031, + 50137 + +}; + +static const struct src_stage src_int32_40_21_2381_5000 = { + 11, 21, 40, 24, 960, 21, 40, 0, 0, + src_int32_40_21_2381_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_40_21_2976_5000.h b/src/audio/src/coef/src_ipc4_int32_40_21_2976_5000.h new file mode 100644 index 000000000000..514a6e4988fa --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_40_21_2976_5000.h @@ -0,0 +1,1138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_40_21_2976_5000_fir[1120] = { + -34235, + 389198, + -1297100, + 2126987, + -685014, + -6070654, + 19059125, + -32982798, + 34426517, + -5580366, + -66185528, + 177653856, + -305903382, + 419852215, + 1712550465, + 375748890, + -295710933, + 179524055, + -71804797, + -488765, + 31479135, + -32055730, + 19283172, + -6611299, + -276447, + 1939107, + -1248017, + 386918, + -32201, + 389482, + -1342427, + 2312836, + -1104409, + -5488391, + 18749616, + -33795498, + 37297481, + -10756456, + -60178032, + 175019243, + -315155081, + 464615162, + 1710267423, + 332392159, + -284642313, + 180639855, + -77021622, + 4499688, + 28468889, + -31020705, + 19422987, + -7109232, + 119887, + 1750109, + -1195582, + 382771, + -29544, + 387644, + -1383596, + 2495715, + -1533130, + -4865821, + 18353751, + -34487749, + 40078500, + -15997645, + -53798377, + 171612931, + -323402936, + 509947979, + 1705706956, + 289865989, + -272763353, + 181013909, + -81823660, + 9367127, + 25409298, + -29884438, + 19480121, + -7563567, + 502677, + 1560876, + -1140198, + 376890, + -26233, + 383564, + -1420206, + 2674667, + -1969585, + -4204468, + 17870985, + -35053841, + 42756129, + -21283876, + -47064458, + 167430449, + -330585565, + 555758368, + 1698880278, + 248251137, + -260140911, + 180661407, + -86200448, + 14096535, + 22313801, + -28653906, + 19456434, + -7973633, + 870716, + 1372264, + -1082264, + 369412, + -22238, + 377131, + -1451865, + 2848716, + -2412094, + -3506071, + 17301131, + -35488461, + 45317063, + -26594492, + -39995963, + 162470220, + -336643519, + 601951731, + 1689804171, + 207624940, + -246842636, + 179599965, + -90143413, + 18671793, + 19195694, + -27336318, + 19354078, + -8338966, + 1222898, + 1185091, + -1022177, + 360474, + -17533, + 368237, + -1478185, + 3016872, + -2858900, + -2772577, + 16644373, + -35786730, + 47748196, + -31908310, + -32614327, + 156733622, + -341519509, + 648431414, + 1678500931, + 168061132, + -232936742, + 177849514, + -93645864, + 23077731, + 16068084, + -25939077, + 19175481, + -8659305, + 1558223, + 1000139, + -960322, + 350214, + -12098, + 356787, + -1498790, + 3178139, + -3308166, + -2006144, + 15901269, + -35944231, + 50036679, + -37203697, + -24942688, + 150225053, + -345158621, + 695098975, + 1664998302, + 129629665, + -218491779, + 175432175, + -96702981, + 27300167, + 12943838, + -24469746, + 18923331, + -8934591, + 1875798, + 818152, + -897082, + 338772, + -5914, + 342692, + -1513316, + 3331514, + -3757990, + -1209134, + 15072763, + -35957039, + 52169980, + -42458648, + -17005826, + 142951970, + -347508527, + 741854445, + 1649329395, + 92396550, + -203576405, + 172372135, + -99311799, + 31325944, + 9835535, + -22936013, + 18600555, + -9164959, + 2174835, + 639833, + -832824, + 326285, + 1032, + 325875, + -1521414, + 3475995, + -4206402, + -384110, + 14160188, + -35821747, + 54135944, + -47650869, + -8830098, + 134924935, + -348519694, + 788596603, + 1631532586, + 56423700, + -188259166, + 168695512, + -101471185, + 35142965, + 6755419, + -21345654, + 18210305, + -9350732, + 2454653, + 465840, + -767909, + 312890, + 8748, + 306270, + -1522751, + 3610585, + -4651381, + 466173, + 13165271, + -35535494, + 55922848, + -52757862, + -443367, + 126157634, + -348145585, + 835223256, + 1611651404, + 21768802, + -172608271, + 164430218, + -103181800, + 38740220, + 3715361, + -19706502, + 17755935, + -9492417, + 2714680, + 296788, + -702682, + 298720, + 17237, + 283825, + -1517014, + 3734299, + -5090855, + 1338773, + 12090134, + -35095991, + 57519461, + -57757014, + 8125077, + 116666901, + -346342848, + 881631520, + 1589734398, + -11514812, + -156691381, + 159605820, + -104446067, + 42107808, + 726809, + -18026409, + 17240985, + -9590692, + 2954448, + 133245, + -637474, + 283906, + 26498, + 258498, + -1503914, + 3846165, + -5522712, + 2230567, + 10937293, + -34501540, + 58915103, + -62625685, + 16844607, + 106472716, + -343071506, + 927718109, + 1565834995, + -43378264, + -140575399, + 154253397, + -105268125, + 45236953, + -2199241, + -16313217, + 16669159, + -9646408, + 3173594, + -24266, + -572602, + 268577, + 36521, + 230265, + -1483184, + 3945232, + -5944809, + 3138264, + 9709662, + -33751053, + 60099698, + -67341298, + 25683349, + 95598204, + -338295131, + 973379626, + 1540011337, + -73777230, + -124326261, + 148405385, + -105653777, + 48120019, + -5052286, + -14574721, + 16044305, + -9660569, + 3371859, + -175273, + -508367, + 252856, + 47293, + 199114, + -1454583, + 4030575, + -6354980, + 4058412, + 8410544, + -32844079, + 61063828, + -71881439, + 34608283, + 84069614, + -331981009, + 1018512849, + 1512326113, + -102672013, + -108008741, + 142095438, + -105610437, + 50750521, + -7822348, + -12818642, + 15370397, + -9634332, + 3549085, + -319349, + -445052, + 236860, + 58794, + 165049, + -1417902, + 4101298, + -6751043, + 4987410, + 7043632, + -31780810, + 61798790, + -76223942, + 43585351, + 71916294, + -324100303, + 1063015032, + 1482846370, + -130027603, + -91686258, + 135358266, + -105147069, + 53123120, + -10500001, + -11052590, + 14651513, + -9568994, + 3705211, + -456118, + -382924, + 220705, + 70996, + 128093, + -1372961, + 4156543, + -7130814, + 5921520, + 5612996, + -30562099, + 62296644, + -80346992, + 52579570, + 59170650, + -314628193, + 1106784192, + 1451643310, + -155813731, + -75420693, + 128229491, + -104274119, + 55233630, + -13076402, + -9284043, + 13891816, + -9465983, + 3840274, + -585251, + -322230, + 204498, + 83865, + 88284, + -1319614, + 4195494, + -7492115, + 6856879, + 4123080, + -29189473, + 62550262, + -84229217, + 61555147, + 45868090, + -303544015, + 1149719405, + 1418792086, + -180004894, + -59272211, + 120745489, + -103003445, + 57079005, + -15543314, + -7520313, + 13095533, + -9326847, + 3954400, + -706467, + -263199, + 188342, + 97361, + 45677, + -1257751, + 4217380, + -7832780, + 7789515, + 2578689, + -27665137, + 62553375, + -87849783, + 70475607, + 32046968, + -290831385, + 1191721091, + 1384371577, + -202580376, + -43299097, + 112943238, + -101348246, + 58657334, + -17893125, + -5768518, + 12266936, + -9153246, + 4047809, + -819534, + -206041, + 172331, + 111437, + 348, + -1187298, + 4221483, + -8150672, + 8715357, + 984980, + -25991984, + 62300615, + -91188491, + 79303919, + 17748505, + -276478307, + 1232691307, + 1348464151, + -223524247, + -27557594, + 104860169, + -99322979, + 59967822, + -20118868, + -4035563, + 11410324, + -8946940, + 4120800, + -924267, + -150946, + 156556, + 126037, + -47610, + -1108221, + 4207142, + -8443690, + 9630257, + -652557, + -24173594, + 61787561, + -94225872, + 88002632, + 3016702, + -260477274, + 1272534029, + 1311155429, + -242825350, + -12101753, + 96534008, + -96943278, + 61010772, + -22214236, + -2328110, + 10530000, + -8709778, + 4173758, + -1020527, + -98085, + 141099, + 141099, + -98085, + -1020527, + 4173758, + -8709778, + 10530000, + -2328110, + -22214236, + 61010772, + -96943278, + 96534008, + -12101753, + -242825350, + 1311155429, + 1272534029, + -260477274, + 3016702, + 88002632, + -94225872, + 61787561, + -24173594, + -652557, + 9630257, + -8443690, + 4207142, + -1108221, + -47610, + 126037, + 156556, + -150946, + -924267, + 4120800, + -8946940, + 11410324, + -4035563, + -20118868, + 59967822, + -99322979, + 104860169, + -27557594, + -223524247, + 1348464151, + 1232691307, + -276478307, + 17748505, + 79303919, + -91188491, + 62300615, + -25991984, + 984980, + 8715357, + -8150672, + 4221483, + -1187298, + 348, + 111437, + 172331, + -206041, + -819534, + 4047809, + -9153246, + 12266936, + -5768518, + -17893125, + 58657334, + -101348246, + 112943238, + -43299097, + -202580376, + 1384371577, + 1191721091, + -290831385, + 32046968, + 70475607, + -87849783, + 62553375, + -27665137, + 2578689, + 7789515, + -7832780, + 4217380, + -1257751, + 45677, + 97361, + 188342, + -263199, + -706467, + 3954400, + -9326847, + 13095533, + -7520313, + -15543314, + 57079005, + -103003445, + 120745489, + -59272211, + -180004894, + 1418792086, + 1149719405, + -303544015, + 45868090, + 61555147, + -84229217, + 62550262, + -29189473, + 4123080, + 6856879, + -7492115, + 4195494, + -1319614, + 88284, + 83865, + 204498, + -322230, + -585251, + 3840274, + -9465983, + 13891816, + -9284043, + -13076402, + 55233630, + -104274119, + 128229491, + -75420693, + -155813731, + 1451643310, + 1106784192, + -314628193, + 59170650, + 52579570, + -80346992, + 62296644, + -30562099, + 5612996, + 5921520, + -7130814, + 4156543, + -1372961, + 128093, + 70996, + 220705, + -382924, + -456118, + 3705211, + -9568994, + 14651513, + -11052590, + -10500001, + 53123120, + -105147069, + 135358266, + -91686258, + -130027603, + 1482846370, + 1063015032, + -324100303, + 71916294, + 43585351, + -76223942, + 61798790, + -31780810, + 7043632, + 4987410, + -6751043, + 4101298, + -1417902, + 165049, + 58794, + 236860, + -445052, + -319349, + 3549085, + -9634332, + 15370397, + -12818642, + -7822348, + 50750521, + -105610437, + 142095438, + -108008741, + -102672013, + 1512326113, + 1018512849, + -331981009, + 84069614, + 34608283, + -71881439, + 61063828, + -32844079, + 8410544, + 4058412, + -6354980, + 4030575, + -1454583, + 199114, + 47293, + 252856, + -508367, + -175273, + 3371859, + -9660569, + 16044305, + -14574721, + -5052286, + 48120019, + -105653777, + 148405385, + -124326261, + -73777230, + 1540011337, + 973379626, + -338295131, + 95598204, + 25683349, + -67341298, + 60099698, + -33751053, + 9709662, + 3138264, + -5944809, + 3945232, + -1483184, + 230265, + 36521, + 268577, + -572602, + -24266, + 3173594, + -9646408, + 16669159, + -16313217, + -2199241, + 45236953, + -105268125, + 154253397, + -140575399, + -43378264, + 1565834995, + 927718109, + -343071506, + 106472716, + 16844607, + -62625685, + 58915103, + -34501540, + 10937293, + 2230567, + -5522712, + 3846165, + -1503914, + 258498, + 26498, + 283906, + -637474, + 133245, + 2954448, + -9590692, + 17240985, + -18026409, + 726809, + 42107808, + -104446067, + 159605820, + -156691381, + -11514812, + 1589734398, + 881631520, + -346342848, + 116666901, + 8125077, + -57757014, + 57519461, + -35095991, + 12090134, + 1338773, + -5090855, + 3734299, + -1517014, + 283825, + 17237, + 298720, + -702682, + 296788, + 2714680, + -9492417, + 17755935, + -19706502, + 3715361, + 38740220, + -103181800, + 164430218, + -172608271, + 21768802, + 1611651404, + 835223256, + -348145585, + 126157634, + -443367, + -52757862, + 55922848, + -35535494, + 13165271, + 466173, + -4651381, + 3610585, + -1522751, + 306270, + 8748, + 312890, + -767909, + 465840, + 2454653, + -9350732, + 18210305, + -21345654, + 6755419, + 35142965, + -101471185, + 168695512, + -188259166, + 56423700, + 1631532586, + 788596603, + -348519694, + 134924935, + -8830098, + -47650869, + 54135944, + -35821747, + 14160188, + -384110, + -4206402, + 3475995, + -1521414, + 325875, + 1032, + 326285, + -832824, + 639833, + 2174835, + -9164959, + 18600555, + -22936013, + 9835535, + 31325944, + -99311799, + 172372135, + -203576405, + 92396550, + 1649329395, + 741854445, + -347508527, + 142951970, + -17005826, + -42458648, + 52169980, + -35957039, + 15072763, + -1209134, + -3757990, + 3331514, + -1513316, + 342692, + -5914, + 338772, + -897082, + 818152, + 1875798, + -8934591, + 18923331, + -24469746, + 12943838, + 27300167, + -96702981, + 175432175, + -218491779, + 129629665, + 1664998302, + 695098975, + -345158621, + 150225053, + -24942688, + -37203697, + 50036679, + -35944231, + 15901269, + -2006144, + -3308166, + 3178139, + -1498790, + 356787, + -12098, + 350214, + -960322, + 1000139, + 1558223, + -8659305, + 19175481, + -25939077, + 16068084, + 23077731, + -93645864, + 177849514, + -232936742, + 168061132, + 1678500931, + 648431414, + -341519509, + 156733622, + -32614327, + -31908310, + 47748196, + -35786730, + 16644373, + -2772577, + -2858900, + 3016872, + -1478185, + 368237, + -17533, + 360474, + -1022177, + 1185091, + 1222898, + -8338966, + 19354078, + -27336318, + 19195694, + 18671793, + -90143413, + 179599965, + -246842636, + 207624940, + 1689804171, + 601951731, + -336643519, + 162470220, + -39995963, + -26594492, + 45317063, + -35488461, + 17301131, + -3506071, + -2412094, + 2848716, + -1451865, + 377131, + -22238, + 369412, + -1082264, + 1372264, + 870716, + -7973633, + 19456434, + -28653906, + 22313801, + 14096535, + -86200448, + 180661407, + -260140911, + 248251137, + 1698880278, + 555758368, + -330585565, + 167430449, + -47064458, + -21283876, + 42756129, + -35053841, + 17870985, + -4204468, + -1969585, + 2674667, + -1420206, + 383564, + -26233, + 376890, + -1140198, + 1560876, + 502677, + -7563567, + 19480121, + -29884438, + 25409298, + 9367127, + -81823660, + 181013909, + -272763353, + 289865989, + 1705706956, + 509947979, + -323402936, + 171612931, + -53798377, + -15997645, + 40078500, + -34487749, + 18353751, + -4865821, + -1533130, + 2495715, + -1383596, + 387644, + -29544, + 382771, + -1195582, + 1750109, + 119887, + -7109232, + 19422987, + -31020705, + 28468889, + 4499688, + -77021622, + 180639855, + -284642313, + 332392159, + 1710267423, + 464615162, + -315155081, + 175019243, + -60178032, + -10756456, + 37297481, + -33795498, + 18749616, + -5488391, + -1104409, + 2312836, + -1342427, + 389482, + -32201, + 386918, + -1248017, + 1939107, + -276447, + -6611299, + 19283172, + -32055730, + 31479135, + -488765, + -71804797, + 179524055, + -295710933, + 375748890, + 1712550465, + 419852215, + -305903382, + 177653856, + -66185528, + -5580366, + 34426517, + -32982798, + 19059125, + -6070654, + -685014, + 2126987, + -1297100, + 389198, + -34235 + +}; + +static const struct src_stage src_int32_40_21_2976_5000 = { + 11, 21, 40, 28, 1120, 21, 40, 0, 0, + src_int32_40_21_2976_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_40_21_3968_5000.h b/src/audio/src/coef/src_ipc4_int32_40_21_3968_5000.h new file mode 100644 index 000000000000..a37477890e24 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_40_21_3968_5000.h @@ -0,0 +1,2097 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_40_21_3968_5000_fir[2080] = { + -48704, + 156750, + -338114, + 571566, + -784641, + 842493, + -552783, + -306571, + 1934153, + -4430219, + 7711706, + -11435192, + 14949708, + -17300375, + 17297375, + -13653292, + 5177047, + 9002363, + -29220970, + 55118106, + -85570092, + 118753341, + -152365019, + 184061472, + -212458064, + 242107441, + 1925486150, + 191253069, + -191060749, + 173824151, + -148276162, + 118409495, + -87454042, + 58150467, + -32618168, + 12222387, + 2467145, + -11610002, + 15938850, + -16548479, + 14671658, + -11480155, + 7938821, + -4726311, + 2221350, + -541590, + -384980, + 737721, + -728612, + 547329, + -330917, + 156301, + -47686, + 156331, + -343725, + 593461, + -837936, + 945165, + -721004, + -65818, + 1632417, + -4107158, + 7442351, + -11331909, + 15155973, + -17974356, + 18584821, + -15651120, + 7890920, + 5701981, + -25639955, + 51775312, + -83234840, + 118506096, + -155750082, + 193563686, + -233352669, + 294395633, + 1922289783, + 141947540, + -169272581, + 162914350, + -143513777, + 117483785, + -88882667, + 60860841, + -35816705, + 15346941, + -225366, + -9531921, + 14516833, + -15723354, + 14324114, + -11467347, + 8123152, + -4994351, + 2492799, + -769790, + -218439, + 631426, + -670202, + 520938, + -322224, + 155019, + -46285, + 155010, + -347669, + 612833, + -888152, + 1045157, + -888784, + 179533, + 1317449, + -3758361, + 7131521, + -11170046, + 15288495, + -18566076, + 19793872, + -17592921, + 10595171, + 2336926, + -21891051, + 48135318, + -80454602, + 117661341, + -158404080, + 202270534, + -253632129, + 347996419, + 1915906653, + 94299327, + -147204409, + 151396741, + -138110938, + 115988156, + -89854227, + 63239390, + -38802880, + 18361546, + -2887293, + -7429777, + 13039138, + -14829994, + 13909686, + -11397600, + 8264379, + -5233417, + 2747389, + -990138, + -53980, + 524184, + -609766, + 492589, + -312126, + 152945, + -44489, + 152759, + -349870, + 629510, + -934951, + 1141894, + -1055247, + 428304, + 990642, + -3385215, + 6780205, + -10949636, + 15345667, + -19071551, + 20917526, + -19468295, + 13276110, + -1076627, + -17991200, + 44212991, + -77237982, + 116215523, + -160302912, + 210124446, + -273183871, + 402782731, + 1906355933, + 48410039, + -124965647, + 139337710, + -132103330, + 113937188, + -90369248, + 65278025, + -41564194, + 21252426, + -5505744, + -5314297, + 11513768, + -13873675, + 13431288, + -11272021, + 8362405, + -5442745, + 2984111, + -1201659, + 107604, + 416559, + -547663, + 462482, + -300723, + 150121, + -42288, + 149555, + -350262, + 643330, + -978008, + 1234802, + -1219510, + 679278, + 653473, + -2989250, + 6389610, + -10671013, + 15326241, + -19487184, + 21949125, + -21267059, + 15920010, + -4522079, + -13958285, + 40024772, + -73595852, + 114168012, + -161425803, + 217070850, + -291895631, + 458622056, + 1893666299, + 4374137, + -102663867, + 126805028, + -125529046, + 111347988, + -90430497, + 66970423, + -44089393, + 24006569, + -8068180, + -3196156, + 9948873, + -12859925, + 12892117, + -11091982, + 8417347, + -5621734, + 3202063, + -1403440, + 265548, + 309110, + -484252, + 430821, + -288118, + 146595, + -39675, + 145378, + -348784, + 654142, + -1017008, + 1323318, + -1380682, + 931207, + 307498, + -2572138, + 5961163, + -10334808, + 15229346, + -19809792, + 22882404, + -22979301, + 18513182, + -7982494, + -9811049, + 35588613, + -69541330, + 111521145, + -161755459, + 223058478, + -309655902, + 515376846, + 1877875821, + -37721330, + -80404401, + 113867517, + -118428368, + 108240077, + -90042940, + 68312043, + -46368519, + 26611779, + -10562480, + -1085921, + 8352704, + -11794489, + 12295633, + -10859108, + 8429542, + -5769943, + 3400453, + -1594632, + 419121, + 202380, + -419890, + 397814, + -274417, + 142413, + -36647, + 140215, + -345386, + 661809, + -1051649, + 1406890, + -1537873, + 1182813, + -45660, + -2135682, + 5496503, + -9941955, + 15054488, + -20036620, + 23711517, + -24595434, + 21042041, + -11440675, + -5569015, + 30923907, + -65089737, + 108280244, + -161278195, + 228039658, + -326354394, + 572904960, + 1859031833, + -77796948, + -58289955, + 100594717, + -110843548, + 104635267, + -89213691, + 69300124, + -48392936, + 29056735, + -12976993, + 1005998, + 6733573, + -10683307, + 11645540, + -10575272, + 8399535, + -5887094, + 3578601, + -1774457, + 567628, + 96900, + -354931, + 363671, + -259728, + 137628, + -33201, + 134057, + -340026, + 666205, + -1081649, + 1484979, + -1690196, + 1432801, + -404312, + -1681814, + 4997476, + -9493688, + 14801565, + -20165369, + 24431079, + -26106247, + 23493175, + -14879249, + -1252393, + 26051403, + -60258552, + 104453635, + -159984057, + 231970594, + -341882480, + 631060113, + 1837190756, + -115781143, + -36420239, + 87056554, + -102818579, + 100557524, + -87951956, + 69933684, + -50155367, + 31331031, + -15300592, + 3069397, + 5099812, + -9532471, + 10945763, + -10242573, + 8328074, + -5973070, + 3735939, + -1942207, + 710412, + -6820, + -289724, + 328600, + -244163, + 132290, + -29339, + 126902, + -332672, + 667220, + -1106741, + 1557065, + -1836772, + 1679859, + -766716, + -1212579, + 4466130, + -8991538, + 14470867, + -20194203, + 25036194, + -27502958, + 25853416, + -18280751, + 3118012, + 20993123, + -55067344, + 100052644, + -157866919, + 234811637, + -356133657, + 689692358, + 1812417904, + -151610343, + -14891622, + 73323015, + -94398959, + 96032829, + -86268964, + 70213501, + -51649908, + 33425221, + -17522724, + 5094331, + 3459728, + -8348200, + 10200428, + -9863330, + 8216107, + -6027912, + 3872016, + -2097248, + 846861, + -108286, + -224611, + 292810, + -227833, + 126454, + -25064, + 118753, + -323304, + 664758, + -1126680, + 1622648, + -1976737, + 1922670, + -1131080, + -730138, + 3904706, + -8437331, + 14063085, + -20121774, + 25522488, + -28777258, + 28109909, + -21627716, + 7520899, + 15772262, + -49537706, + 95091578, + -154924575, + 236527538, + -369003989, + 748648568, + 1784787240, + -185229117, + 6203206, + 59463825, + -85631456, + 91089024, + -84177883, + 70142095, + -52872049, + 35330855, + -19633458, + 7071156, + 1821563, + -7136806, + 9413835, + -9440064, + 8064772, + -6051820, + 3986493, + -2239021, + 976403, + -207028, + -159926, + 256510, + -210853, + 120173, + -20383, + 109619, + -311909, + 658743, + -1141242, + 1681252, + -2109244, + 2159915, + -1495575, + -236745, + 3315631, + -7833183, + 13579306, + -19947227, + 25886134, + -29921364, + 30250179, + -24902758, + 11934571, + 10413089, + -43693170, + 89587693, + -151158802, + 237087687, + -380392560, + 807772949, + 1754381120, + -216590282, + 26775544, + 45548128, + -76563867, + 85755657, + -81693743, + 69723691, + -53818677, + 37040512, + -21623523, + 8990578, + 193456, + -5904657, + 8590438, + -8975484, + 7875388, + -6045142, + 4079148, + -2367045, + 1098516, + -302601, + -95991, + 219902, + -193335, + 113504, + -15308, + 99515, + -298489, + 649112, + -1150225, + 1732428, + -2233469, + 2390280, + -1858343, + 265251, + 2701504, + -7181488, + 13021018, + -19670213, + 26123883, + -30928060, + 32262197, + -28088666, + 16337037, + 4940836, + -37559112, + 83561153, + -146575409, + 236466333, + -390201909, + 866907553, + 1721289991, + -245654973, + 46740973, + 31644176, + -67244773, + 80063813, + -78833334, + 68964184, + -54488078, + 38547824, + -23484353, + 10843691, + -1416600, + -4658152, + 7734816, + -8472467, + 7649449, + -6008381, + 4149872, + -2480918, + 1212722, + -394584, + -33120, + 183188, + -175391, + 106501, + -9851, + 88462, + -283054, + 635822, + -1153454, + 1775758, + -2348616, + 2612466, + -2217504, + 773425, + 2065090, + -6484916, + 12390104, + -19290899, + 26233081, + -31790743, + 34134450, + -31168486, + 20706122, + -618416, + -31162650, + 77034961, + -141184277, + 234642792, + -398338461, + 925892811, + 1685612071, + -272392685, + 66019630, + 17819031, + -57723300, + 74045952, + -75615106, + 67871089, + -54879932, + 39847496, + -25208115, + 12622021, + -3000797, + -3403680, + 6851653, + -7934048, + 7388607, + -5942179, + 4198669, + -2580316, + 1318597, + -482584, + 28390, + 146564, + -157133, + 99219, + -4029, + 76490, + -265627, + 618848, + -1150780, + 1810853, + -2453921, + 2825192, + -2571166, + 1285284, + 1409307, + -5746400, + 11688840, + -18809969, + 26211692, + -32503459, + 35855997, + -34125615, + 25019575, + -6237857, + -24532530, + 70034889, + -134999361, + 231601629, + -404712949, + 984568068, + 1647453001, + -296781284, + 84536450, + 4138274, + -48048874, + 67735726, + -72059059, + 66453487, + -54995295, + 40935321, + -26787747, + 14317563, + -4551544, + -2147595, + 5945712, + -7363397, + 7094672, + -5847321, + 4225654, + -2664994, + 1415764, + -566237, + 88253, + 110218, + -138671, + 91712, + 2139, + 63633, + -246243, + 598185, + -1142082, + 1837363, + -2548656, + 3027205, + -2917436, + 1798278, + 737211, + -4969124, + 10919885, + -18228631, + 26058318, + -33060944, + 37416538, + -36943880, + 29255180, + -11890071, + -17699005, + 62589389, + -128038693, + 227332821, + -409240821, + 1042772129, + 1606925460, + -318806982, + 102221398, + -9334279, + -38270980, + 61167807, + -68186628, + 64721965, + -54836585, + 41808191, + -28216980, + 15922812, + -6061506, + -896182, + 5021807, + -6763803, + 6769589, + -5724721, + 4231051, + -2734787, + 1503901, + -645209, + 146200, + 74336, + -120111, + 84036, + 8629, + 49931, + -224948, + 573848, + -1127267, + 1854973, + -2632137, + 3217285, + -3254428, + 2309814, + 51983, + -4156511, + 10086276, + -17548612, + 25772207, + -33458658, + 38806468, + -39607633, + 33390864, + -17547172, + -10693700, + 54729482, + -120324353, + 221831907, + -411842636, + 1100343807, + 1564148773, + -338464286, + 119009665, + -22536845, + -28438929, + 54377704, + -64020563, + 62688543, + -54407550, + 42464100, + -29490365, + 17430799, + -7523639, + 344376, + 4084784, + -6138657, + 6415436, + -5575421, + 4215189, + -2789610, + 1582735, + -719198, + 201978, + 39091, + -101558, + 76242, + 15415, + 35431, + -201802, + 545870, + -1106275, + 1863411, + -2703724, + 3394253, + -3580277, + 2817269, + -643083, + -3312209, + 9191414, + -16772161, + 25353272, + -33692811, + 40016933, + -42101827, + 37404813, + -23180929, + -3549475, + 46488648, + -111882425, + 215100101, + -412444444, + 1157122478, + 1519248480, + -355755914, + 134841847, + -35409925, + -18601615, + 47401581, + -59584801, + 60366606, + -53713241, + 42902139, + -30603284, + 18835120, + -8931219, + 1568023, + 3139489, + -5491432, + 6034405, + -5400581, + 4178500, + -2829453, + 1652050, + -787933, + 255353, + 4652, + -83113, + 68382, + 22468, + 20189, + -176875, + 514308, + -1079074, + 1862444, + -2762825, + 3556978, + -3893140, + 3318001, + -1344598, + -2440074, + 8239054, + -15902041, + 24802091, + -33760398, + 41039886, + -44412105, + 41275580, + -28762910, + 3699722, + 37902689, + -102742932, + 207144397, + -410978145, + 1212948633, + 1472355896, + -370692679, + 149664096, + -47896548, + -8807296, + 40276069, + -54904333, + 57770814, + -52759966, + 43122493, + -31551972, + 20129957, + -10277871, + 2768864, + 2190750, + -4825664, + 5628793, + -5201474, + 4121514, + -2854383, + 1711680, + -851176, + 306106, + -28822, + -64873, + 60505, + 29756, + 4262, + -150250, + 479237, + -1045667, + 1851887, + -2808905, + 3704383, + -4191217, + 3809364, + -2049094, + -1544153, + 7233288, + -14941521, + 24119920, + -33659217, + 41868132, + -46524872, + 44982201, + -34264615, + 11019012, + 29009591, + -92939755, + 197977643, + -407381835, + 1267664426, + 1423607641, + -383293344, + 163428248, + -59942498, + 896634, + 33038091, + -50005074, + 54917026, + -51555252, + 43126427, + -32333520, + 21310106, + -11557601, + 3941188, + 1243350, + -4144935, + 5200988, + -4979473, + 4044854, + -2864544, + 1761513, + -908724, + 354039, + -61183, + -46929, + 52659, + 37243, + -12282, + -122020, + 440753, + -1006089, + 1831600, + -2841486, + 3835451, + -4472752, + 4288720, + -2753039, + -628669, + 6178530, + -13894365, + 23308686, + -33387891, + 42495376, + -48427379, + 48504300, + -39657621, + 18372746, + 19849361, + -82510530, + 187618590, + -401600127, + 1321114227, + 1373145160, + -393584454, + 176091920, + -71496524, + 10463862, + 25724668, + -44913722, + 51822199, + -50107789, + 42916267, + -32945887, + 22370991, + -12764820, + 5079497, + 302002, + -3452855, + 4753454, + -4736047, + 3949234, + -2860150, + 1801489, + -960407, + 398975, + -92292, + -29371, + 44891, + 44891, + -29371, + -92292, + 398975, + -960407, + 1801489, + -2860150, + 3949234, + -4736047, + 4753454, + -3452855, + 302002, + 5079497, + -12764820, + 22370991, + -32945887, + 42916267, + -50107789, + 51822199, + -44913722, + 25724668, + 10463862, + -71496524, + 176091920, + -393584454, + 1373145160, + 1321114227, + -401600127, + 187618590, + -82510530, + 19849361, + 18372746, + -39657621, + 48504300, + -48427379, + 42495376, + -33387891, + 23308686, + -13894365, + 6178530, + -628669, + -2753039, + 4288720, + -4472752, + 3835451, + -2841486, + 1831600, + -1006089, + 440753, + -122020, + -12282, + 37243, + 52659, + -46929, + -61183, + 354039, + -908724, + 1761513, + -2864544, + 4044854, + -4979473, + 5200988, + -4144935, + 1243350, + 3941188, + -11557601, + 21310106, + -32333520, + 43126427, + -51555252, + 54917026, + -50005074, + 33038091, + 896634, + -59942498, + 163428248, + -383293344, + 1423607641, + 1267664426, + -407381835, + 197977643, + -92939755, + 29009591, + 11019012, + -34264615, + 44982201, + -46524872, + 41868132, + -33659217, + 24119920, + -14941521, + 7233288, + -1544153, + -2049094, + 3809364, + -4191217, + 3704383, + -2808905, + 1851887, + -1045667, + 479237, + -150250, + 4262, + 29756, + 60505, + -64873, + -28822, + 306106, + -851176, + 1711680, + -2854383, + 4121514, + -5201474, + 5628793, + -4825664, + 2190750, + 2768864, + -10277871, + 20129957, + -31551972, + 43122493, + -52759966, + 57770814, + -54904333, + 40276069, + -8807296, + -47896548, + 149664096, + -370692679, + 1472355896, + 1212948633, + -410978145, + 207144397, + -102742932, + 37902689, + 3699722, + -28762910, + 41275580, + -44412105, + 41039886, + -33760398, + 24802091, + -15902041, + 8239054, + -2440074, + -1344598, + 3318001, + -3893140, + 3556978, + -2762825, + 1862444, + -1079074, + 514308, + -176875, + 20189, + 22468, + 68382, + -83113, + 4652, + 255353, + -787933, + 1652050, + -2829453, + 4178500, + -5400581, + 6034405, + -5491432, + 3139489, + 1568023, + -8931219, + 18835120, + -30603284, + 42902139, + -53713241, + 60366606, + -59584801, + 47401581, + -18601615, + -35409925, + 134841847, + -355755914, + 1519248480, + 1157122478, + -412444444, + 215100101, + -111882425, + 46488648, + -3549475, + -23180929, + 37404813, + -42101827, + 40016933, + -33692811, + 25353272, + -16772161, + 9191414, + -3312209, + -643083, + 2817269, + -3580277, + 3394253, + -2703724, + 1863411, + -1106275, + 545870, + -201802, + 35431, + 15415, + 76242, + -101558, + 39091, + 201978, + -719198, + 1582735, + -2789610, + 4215189, + -5575421, + 6415436, + -6138657, + 4084784, + 344376, + -7523639, + 17430799, + -29490365, + 42464100, + -54407550, + 62688543, + -64020563, + 54377704, + -28438929, + -22536845, + 119009665, + -338464286, + 1564148773, + 1100343807, + -411842636, + 221831907, + -120324353, + 54729482, + -10693700, + -17547172, + 33390864, + -39607633, + 38806468, + -33458658, + 25772207, + -17548612, + 10086276, + -4156511, + 51983, + 2309814, + -3254428, + 3217285, + -2632137, + 1854973, + -1127267, + 573848, + -224948, + 49931, + 8629, + 84036, + -120111, + 74336, + 146200, + -645209, + 1503901, + -2734787, + 4231051, + -5724721, + 6769589, + -6763803, + 5021807, + -896182, + -6061506, + 15922812, + -28216980, + 41808191, + -54836585, + 64721965, + -68186628, + 61167807, + -38270980, + -9334279, + 102221398, + -318806982, + 1606925460, + 1042772129, + -409240821, + 227332821, + -128038693, + 62589389, + -17699005, + -11890071, + 29255180, + -36943880, + 37416538, + -33060944, + 26058318, + -18228631, + 10919885, + -4969124, + 737211, + 1798278, + -2917436, + 3027205, + -2548656, + 1837363, + -1142082, + 598185, + -246243, + 63633, + 2139, + 91712, + -138671, + 110218, + 88253, + -566237, + 1415764, + -2664994, + 4225654, + -5847321, + 7094672, + -7363397, + 5945712, + -2147595, + -4551544, + 14317563, + -26787747, + 40935321, + -54995295, + 66453487, + -72059059, + 67735726, + -48048874, + 4138274, + 84536450, + -296781284, + 1647453001, + 984568068, + -404712949, + 231601629, + -134999361, + 70034889, + -24532530, + -6237857, + 25019575, + -34125615, + 35855997, + -32503459, + 26211692, + -18809969, + 11688840, + -5746400, + 1409307, + 1285284, + -2571166, + 2825192, + -2453921, + 1810853, + -1150780, + 618848, + -265627, + 76490, + -4029, + 99219, + -157133, + 146564, + 28390, + -482584, + 1318597, + -2580316, + 4198669, + -5942179, + 7388607, + -7934048, + 6851653, + -3403680, + -3000797, + 12622021, + -25208115, + 39847496, + -54879932, + 67871089, + -75615106, + 74045952, + -57723300, + 17819031, + 66019630, + -272392685, + 1685612071, + 925892811, + -398338461, + 234642792, + -141184277, + 77034961, + -31162650, + -618416, + 20706122, + -31168486, + 34134450, + -31790743, + 26233081, + -19290899, + 12390104, + -6484916, + 2065090, + 773425, + -2217504, + 2612466, + -2348616, + 1775758, + -1153454, + 635822, + -283054, + 88462, + -9851, + 106501, + -175391, + 183188, + -33120, + -394584, + 1212722, + -2480918, + 4149872, + -6008381, + 7649449, + -8472467, + 7734816, + -4658152, + -1416600, + 10843691, + -23484353, + 38547824, + -54488078, + 68964184, + -78833334, + 80063813, + -67244773, + 31644176, + 46740973, + -245654973, + 1721289991, + 866907553, + -390201909, + 236466333, + -146575409, + 83561153, + -37559112, + 4940836, + 16337037, + -28088666, + 32262197, + -30928060, + 26123883, + -19670213, + 13021018, + -7181488, + 2701504, + 265251, + -1858343, + 2390280, + -2233469, + 1732428, + -1150225, + 649112, + -298489, + 99515, + -15308, + 113504, + -193335, + 219902, + -95991, + -302601, + 1098516, + -2367045, + 4079148, + -6045142, + 7875388, + -8975484, + 8590438, + -5904657, + 193456, + 8990578, + -21623523, + 37040512, + -53818677, + 69723691, + -81693743, + 85755657, + -76563867, + 45548128, + 26775544, + -216590282, + 1754381120, + 807772949, + -380392560, + 237087687, + -151158802, + 89587693, + -43693170, + 10413089, + 11934571, + -24902758, + 30250179, + -29921364, + 25886134, + -19947227, + 13579306, + -7833183, + 3315631, + -236745, + -1495575, + 2159915, + -2109244, + 1681252, + -1141242, + 658743, + -311909, + 109619, + -20383, + 120173, + -210853, + 256510, + -159926, + -207028, + 976403, + -2239021, + 3986493, + -6051820, + 8064772, + -9440064, + 9413835, + -7136806, + 1821563, + 7071156, + -19633458, + 35330855, + -52872049, + 70142095, + -84177883, + 91089024, + -85631456, + 59463825, + 6203206, + -185229117, + 1784787240, + 748648568, + -369003989, + 236527538, + -154924575, + 95091578, + -49537706, + 15772262, + 7520899, + -21627716, + 28109909, + -28777258, + 25522488, + -20121774, + 14063085, + -8437331, + 3904706, + -730138, + -1131080, + 1922670, + -1976737, + 1622648, + -1126680, + 664758, + -323304, + 118753, + -25064, + 126454, + -227833, + 292810, + -224611, + -108286, + 846861, + -2097248, + 3872016, + -6027912, + 8216107, + -9863330, + 10200428, + -8348200, + 3459728, + 5094331, + -17522724, + 33425221, + -51649908, + 70213501, + -86268964, + 96032829, + -94398959, + 73323015, + -14891622, + -151610343, + 1812417904, + 689692358, + -356133657, + 234811637, + -157866919, + 100052644, + -55067344, + 20993123, + 3118012, + -18280751, + 25853416, + -27502958, + 25036194, + -20194203, + 14470867, + -8991538, + 4466130, + -1212579, + -766716, + 1679859, + -1836772, + 1557065, + -1106741, + 667220, + -332672, + 126902, + -29339, + 132290, + -244163, + 328600, + -289724, + -6820, + 710412, + -1942207, + 3735939, + -5973070, + 8328074, + -10242573, + 10945763, + -9532471, + 5099812, + 3069397, + -15300592, + 31331031, + -50155367, + 69933684, + -87951956, + 100557524, + -102818579, + 87056554, + -36420239, + -115781143, + 1837190756, + 631060113, + -341882480, + 231970594, + -159984057, + 104453635, + -60258552, + 26051403, + -1252393, + -14879249, + 23493175, + -26106247, + 24431079, + -20165369, + 14801565, + -9493688, + 4997476, + -1681814, + -404312, + 1432801, + -1690196, + 1484979, + -1081649, + 666205, + -340026, + 134057, + -33201, + 137628, + -259728, + 363671, + -354931, + 96900, + 567628, + -1774457, + 3578601, + -5887094, + 8399535, + -10575272, + 11645540, + -10683307, + 6733573, + 1005998, + -12976993, + 29056735, + -48392936, + 69300124, + -89213691, + 104635267, + -110843548, + 100594717, + -58289955, + -77796948, + 1859031833, + 572904960, + -326354394, + 228039658, + -161278195, + 108280244, + -65089737, + 30923907, + -5569015, + -11440675, + 21042041, + -24595434, + 23711517, + -20036620, + 15054488, + -9941955, + 5496503, + -2135682, + -45660, + 1182813, + -1537873, + 1406890, + -1051649, + 661809, + -345386, + 140215, + -36647, + 142413, + -274417, + 397814, + -419890, + 202380, + 419121, + -1594632, + 3400453, + -5769943, + 8429542, + -10859108, + 12295633, + -11794489, + 8352704, + -1085921, + -10562480, + 26611779, + -46368519, + 68312043, + -90042940, + 108240077, + -118428368, + 113867517, + -80404401, + -37721330, + 1877875821, + 515376846, + -309655902, + 223058478, + -161755459, + 111521145, + -69541330, + 35588613, + -9811049, + -7982494, + 18513182, + -22979301, + 22882404, + -19809792, + 15229346, + -10334808, + 5961163, + -2572138, + 307498, + 931207, + -1380682, + 1323318, + -1017008, + 654142, + -348784, + 145378, + -39675, + 146595, + -288118, + 430821, + -484252, + 309110, + 265548, + -1403440, + 3202063, + -5621734, + 8417347, + -11091982, + 12892117, + -12859925, + 9948873, + -3196156, + -8068180, + 24006569, + -44089393, + 66970423, + -90430497, + 111347988, + -125529046, + 126805028, + -102663867, + 4374137, + 1893666299, + 458622056, + -291895631, + 217070850, + -161425803, + 114168012, + -73595852, + 40024772, + -13958285, + -4522079, + 15920010, + -21267059, + 21949125, + -19487184, + 15326241, + -10671013, + 6389610, + -2989250, + 653473, + 679278, + -1219510, + 1234802, + -978008, + 643330, + -350262, + 149555, + -42288, + 150121, + -300723, + 462482, + -547663, + 416559, + 107604, + -1201659, + 2984111, + -5442745, + 8362405, + -11272021, + 13431288, + -13873675, + 11513768, + -5314297, + -5505744, + 21252426, + -41564194, + 65278025, + -90369248, + 113937188, + -132103330, + 139337710, + -124965647, + 48410039, + 1906355933, + 402782731, + -273183871, + 210124446, + -160302912, + 116215523, + -77237982, + 44212991, + -17991200, + -1076627, + 13276110, + -19468295, + 20917526, + -19071551, + 15345667, + -10949636, + 6780205, + -3385215, + 990642, + 428304, + -1055247, + 1141894, + -934951, + 629510, + -349870, + 152759, + -44489, + 152945, + -312126, + 492589, + -609766, + 524184, + -53980, + -990138, + 2747389, + -5233417, + 8264379, + -11397600, + 13909686, + -14829994, + 13039138, + -7429777, + -2887293, + 18361546, + -38802880, + 63239390, + -89854227, + 115988156, + -138110938, + 151396741, + -147204409, + 94299327, + 1915906653, + 347996419, + -253632129, + 202270534, + -158404080, + 117661341, + -80454602, + 48135318, + -21891051, + 2336926, + 10595171, + -17592921, + 19793872, + -18566076, + 15288495, + -11170046, + 7131521, + -3758361, + 1317449, + 179533, + -888784, + 1045157, + -888152, + 612833, + -347669, + 155010, + -46285, + 155019, + -322224, + 520938, + -670202, + 631426, + -218439, + -769790, + 2492799, + -4994351, + 8123152, + -11467347, + 14324114, + -15723354, + 14516833, + -9531921, + -225366, + 15346941, + -35816705, + 60860841, + -88882667, + 117483785, + -143513777, + 162914350, + -169272581, + 141947540, + 1922289783, + 294395633, + -233352669, + 193563686, + -155750082, + 118506096, + -83234840, + 51775312, + -25639955, + 5701981, + 7890920, + -15651120, + 18584821, + -17974356, + 15155973, + -11331909, + 7442351, + -4107158, + 1632417, + -65818, + -721004, + 945165, + -837936, + 593461, + -343725, + 156331, + -47686, + 156301, + -330917, + 547329, + -728612, + 737721, + -384980, + -541590, + 2221350, + -4726311, + 7938821, + -11480155, + 14671658, + -16548479, + 15938850, + -11610002, + 2467145, + 12222387, + -32618168, + 58150467, + -87454042, + 118409495, + -148276162, + 173824151, + -191060749, + 191253069, + 1925486150, + 242107441, + -212458064, + 184061472, + -152365019, + 118753341, + -85570092, + 55118106, + -29220970, + 9002363, + 5177047, + -13653292, + 17297375, + -17300375, + 14949708, + -11435192, + 7711706, + -4430219, + 1934153, + -306571, + -552783, + 842493, + -784641, + 571566, + -338114, + 156750, + -48704 + +}; + +static const struct src_stage src_int32_40_21_3968_5000 = { + 11, 21, 40, 52, 2080, 21, 40, 0, 0, + src_int32_40_21_3968_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_40_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_40_21_4535_5000.h new file mode 100644 index 000000000000..e472f82c024f --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_40_21_4535_5000.h @@ -0,0 +1,4657 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_40_21_4535_5000_fir[4640] = { + -17358, + 32502, + -53608, + 81190, + -115290, + 155305, + -199820, + 246453, + -291729, + 331005, + -358441, + 367056, + -348863, + 295100, + -196566, + 44045, + 171156, + -456599, + 818033, + -1258669, + 1778436, + -2373265, + 3034421, + -3747934, + 4494169, + -5247567, + 5976600, + -6643964, + 7207030, + -7618573, + 7827765, + -7781443, + 7425599, + -6707081, + 5575444, + -3984893, + 1896243, + 721161, + -3887666, + 7611738, + -11888686, + 16699742, + -22011583, + 27776325, + -33932065, + 40403994, + -47106124, + 53943683, + -60816270, + 67621984, + -74262948, + 80653302, + -86732158, + 92488315, + -98017220, + 103685994, + -110787761, + 126156109, + 2047168391, + 73083649, + -85158443, + 87583119, + -86939464, + 84610238, + -81115659, + 76737477, + -71673616, + 66087803, + -60127521, + 53930417, + -47625970, + 41335105, + -35168940, + 29227284, + -23597195, + 18351795, + -13549446, + 9233348, + -5431572, + 2157523, + 589192, + -2821553, + 4563613, + -5848770, + 6717888, + -7217343, + 7397079, + -7308730, + 7003869, + -6532455, + 5941485, + -5273911, + 4567820, + -3855877, + 3165039, + -2516507, + 1925896, + -1403593, + 955257, + -582435, + 283244, + -53081, + -114664, + 227929, + -295366, + 325795, + -327754, + 309142, + -276967, + 237177, + -194589, + 152883, + -114666, + 81577, + -54429, + 33366, + -16561, + 31427, + -52459, + 80328, + -115263, + 156875, + -203982, + 254441, + -305005, + 351228, + -387414, + 406644, + -400888, + 361207, + -278064, + 141729, + 57204, + -327214, + 675170, + -1105598, + 1619915, + -2215670, + 2885837, + -3618177, + 4394735, + -5191499, + 5978258, + -6718700, + 7370758, + -7887239, + 8216727, + -8304755, + 8095232, + -7532085, + 6561066, + -5131682, + 3199163, + -726396, + -2314246, + 5939287, + -10152811, + 14945502, + -20294146, + 26161671, + -32497818, + 39240553, + -46318336, + 53653486, + -61167019, + 68785693, + -76452815, + 84146145, + -91910882, + 99928711, + -108686429, + 119479583, + -136446551, + 181265755, + 2043340170, + 22174678, + -59692024, + 71263583, + -75519343, + 76342681, + -75096509, + 72423815, + -68702107, + 64194150, + -59106696, + 53615528, + -47876457, + 42029923, + -36202553, + 30507266, + -25042771, + 19892920, + -15126166, + 10795289, + -6937466, + 3574703, + -714650, + -1648261, + 3531373, + -4962133, + 5976262, + -6615829, + 6927306, + -6959673, + 6762636, + -6385010, + 5873306, + -5270564, + 4615435, + -3941539, + 3277077, + -2644690, + 2061546, + -1539616, + 1086113, + -704045, + 392856, + -149109, + -32821, + 160080, + -240713, + 283111, + -295544, + 285782, + -260819, + 226683, + -188332, + 149635, + -113405, + 81497, + -54925, + 34018, + -15641, + 30141, + -50983, + 78988, + -114575, + 157571, + -207037, + 261080, + -316703, + 369680, + -414491, + 444319, + -451133, + 425866, + -358694, + 239422, + -57981, + -194984, + 527433, + -945187, + 1451150, + -2044515, + 2720008, + -3467197, + 4269918, + -5105842, + 5946252, + -6756030, + 7493908, + -8112988, + 8561545, + -8784113, + 8722819, + -8318967, + 7514797, + -6255384, + 4490599, + -2177059, + -720019, + 4225152, + -8351212, + 13098429, + -18453877, + 24391562, + -30873229, + 37850068, + -45265533, + 53059682, + -61175703, + 69569938, + -78228039, + 87193026, + -96618829, + 106885142, + -118882301, + 134871369, + -161998008, + 238276923, + 2035696625, + -26454257, + -34518018, + 54819639, + -63824057, + 67735480, + -68711741, + 67739468, + -65367712, + 61953950, + -57761531, + 53002526, + -47857679, + 42485831, + -37028184, + 31609982, + -26340927, + 21315045, + -16610435, + 12289112, + -8397104, + 4964862, + -2007999, + -471637, + 2484607, + -4052279, + 5205053, + -5980471, + 6421289, + -6573573, + 6484895, + -6202661, + 5772641, + -5237722, + 4636908, + -4004582, + 3370027, + -2757196, + 2184706, + -1666040, + 1209916, + -820778, + 499395, + -243510, + 48504, + 91941, + -185221, + 239257, + -262007, + 261071, + -243392, + 215043, + -181098, + 145590, + -111524, + 80956, + -55098, + 34459, + -14599, + 28649, + -49182, + 77171, + -113219, + 157377, + -208952, + 266316, + -326736, + 386235, + -439498, + 479848, + -499297, + 488697, + -437991, + 336572, + -173757, + -60636, + 375620, + -778289, + 1273023, + -1860672, + 2537754, + -3295711, + 4120263, + -4990901, + 5880562, + -6755527, + 7575555, + -8294308, + 8860040, + -9216583, + 9304604, + -9063099, + 8431107, + -7349558, + 5763227, + -3622681, + 886150, + 2478769, + -6493698, + 11168450, + -16500506, + 22475153, + -29066432, + 36239129, + -43952149, + 52163826, + -60840152, + 69967790, + -79575654, + 89773270, + -100825318, + 113313516, + -128541802, + 149769424, + -187302521, + 297045034, + 2024263503, + -72696724, + -9761504, + 38342697, + -51921452, + 58839818, + -62000080, + 62713428, + -61691600, + 59381975, + -56101526, + 52096565, + -47571237, + 42701558, + -37642296, + 32530166, + -27485136, + 22610802, + -17994403, + 13706790, + -9802543, + 6320348, + -3283664, + 701713, + 1429252, + -3124425, + 4408735, + -5315007, + 5882058, + -6152800, + 6172410, + -5986632, + 5640246, + -5175749, + 4632281, + -4044797, + 3443495, + -2853501, + 2294772, + -1782225, + 1326022, + -932016, + 602289, + -335766, + 128858, + 23896, + -129210, + 194491, + -227345, + 235163, + -224799, + 202337, + -172941, + 140782, + -109043, + 79967, + -54955, + 34692, + -13437, + 26953, + -47060, + 74878, + -111194, + 156282, + -209702, + 270101, + -335030, + 400780, + -462273, + 513009, + -545087, + 549328, + -515495, + 432625, + -289476, + 75088, + 220559, + -605799, + 1086475, + -1665095, + 2339998, + -3104555, + 3946461, + -4847145, + 5781360, + -6716974, + 7615007, + -8429934, + 9110277, + -9599481, + 9837071, + -9760072, + 9304645, + -8407896, + 7009792, + -5055102, + 2495283, + 709804, + -4590440, + 9166003, + -14444445, + 20422470, + -27086631, + 34415602, + -42384104, + 50969180, + -60160112, + 69974441, + -80484992, + 91868645, + -104502185, + 119172198, + -137604018, + 164082901, + -212218256, + 357417072, + 2009079295, + -116456715, + 14457362, + 21922865, + -39879650, + 49707935, + -55001714, + 57376355, + -57696691, + 56494747, + -54137877, + 50904404, + -47020213, + 42677182, + -38042555, + 33263600, + -28469769, + 23773565, + -19270816, + 15040760, + -11146182, + 7633745, + -4534591, + 1865235, + 371263, + -2183860, + 3591900, + -4623325, + 5312816, + -5699900, + 5827127, + -5738328, + 5477049, + -5085168, + 4601742, + -4062103, + 3497196, + -2933173, + 2391220, + -1887592, + 1433839, + -1037179, + 700989, + -425379, + 207799, + -43673, + -72998, + 149073, + -191765, + 208217, + -205158, + 188651, + -163918, + 135250, + -105986, + 78543, + -54502, + 34721, + -12160, + 25059, + -44623, + 72114, + -108500, + 154279, + -209267, + 272397, + -341516, + 413209, + -482663, + 543590, + -588221, + 607396, + -590752, + 527028, + -404482, + 211432, + 63101, + -428652, + 892500, + -1458807, + 2127752, + -2894682, + 3749341, + -4675211, + 5649007, + -6640370, + 7611800, + -8518847, + 9310586, + -9930385, + 10316965, + -10405719, + 10130279, + -9424262, + 8223147, + -6466197, + 4098341, + -1071905, + -2651916, + 7101991, + -12296738, + 18244355, + -24944046, + 32388587, + -40568784, + 49480700, + -59137260, + 69587242, + -80947762, + 93463482, + -107623957, + 124422261, + -146010513, + 177722526, + -236601758, + 419232110, + 1990195080, + -157648913, + 38023811, + 5648505, + -27766679, + 40392828, + -47758056, + 51760396, + -53407512, + 53310436, + -51883404, + 49434360, + -46209154, + 42414124, + -38227835, + 33807132, + -29290117, + 24797487, + -20433061, + 16283969, + -12420802, + 8897907, + -5753899, + 3012463, + -683424, + -1235917, + 2759229, + -3909439, + 4716911, + -5217590, + 5451164, + -5459325, + 5284147, + -4966659, + 4545624, + -4056551, + 3530958, + -2995880, + 2473603, + -1981628, + 1532822, + -1135722, + 794976, + -511866, + 284897, + -110392, + -16904, + 103265, + -155477, + 180396, + -184592, + 174073, + -154092, + 129036, + -102378, + 76699, + -53748, + 34549, + -10773, + 22974, + -41880, + 68887, + -105143, + 151366, + -207634, + 273172, + -346138, + 423429, + -500527, + 571392, + -628430, + 662549, + -663317, + 619233, + -518119, + 347629, + -95882, + -247813, + 692140, + -1242901, + 1902120, + -2667155, + 3529870, + -4475897, + 5484052, + -6525926, + 7565714, + -8560290, + 9459567, + -10207156, + 10741307, + -10996139, + 10903115, + -10392723, + 9396299, + -7847921, + 5686275, + -2856397, + -688855, + 4987714, + -10069001, + 15952411, + -22649868, + 30168378, + -38515002, + 47705023, + -57775206, + 68805736, + -80958111, + 94544779, + -110168020, + 129027735, + -153705677, + 190601085, + -260308573, + 482321861, + 1967674322, + -196198909, + 60828888, + -10394203, + -15650111, + 30947962, + -40311514, + 45898991, + -48850054, + 49848748, + -49352471, + 47696252, + -45144031, + 41915128, + -38198215, + 34158686, + -29942411, + 25677527, + -21475196, + 17429902, + -13619608, + 10105999, + -6934917, + 4137054, + -1728917, + -285943, + 1915469, + -3177465, + 4097829, + -4708732, + 5046803, + -5151364, + 5062796, + -4821056, + 4464398, + -4028316, + 3544724, + -3041383, + 2541556, + -2063888, + 1622483, + -1227145, + 883758, + -594769, + 359733, + -175892, + 38758, + 57329, + -118691, + 151865, + -163226, + 158696, + -143530, + 122184, + -98249, + 74453, + -52704, + 34182, + -9280, + 20706, + -38841, + 65208, + -101131, + 147547, + -204796, + 272403, + -348846, + 431358, + -515739, + 596231, + -665458, + 714448, + -732755, + 708701, + -629733, + 482909, + -255503, + -64279, + 486484, + -1018530, + 1664286, + -2423146, + 3289146, + -4250161, + 5287232, + -6374069, + 7476766, + -8553765, + 9556104, + -10427946, + 11107417, + -11527724, + 11618536, + -11307588, + 10522446, + -9192352, + 7250078, + -4633647, + 1287823, + 2834811, + -7773356, + 13558939, + -20216199, + 27766410, + -36232960, + 45650434, + -56079484, + 67631668, + -80512677, + 95102298, + -112114768, + 132955829, + -160637058, + 202633912, + -283193876, + 546511275, + 1941592615, + -232043374, + 82769853, + -26121668, + -3596706, + 21426965, + -32705242, + 39826682, + -44051618, + 46130804, + -46560893, + 45701338, + -43832202, + 41184244, + -37954978, + 34317273, + -30423845, + 26409473, + -22391980, + 18472624, + -14736261, + 11251535, + -8071224, + 5232825, + -2759409, + 660731, + 1065406, + -2431600, + 3459161, + -4176326, + 4616467, + -4816338, + 4814405, + -4649339, + 4358678, + -3977702, + 3538547, + -3069544, + 2594800, + -2133995, + 1702388, + -1310988, + 966880, + -673652, + 431908, + -239818, + 93681, + 11523, + -81621, + 122794, + -141192, + 142617, + -132301, + 114742, + -93631, + 71825, + -51380, + 33628, + -7688, + 18264, + -35517, + 61091, + -96478, + 142832, + -200755, + 270075, + -349605, + 436926, + -528184, + 617937, + -699067, + 762770, + -798646, + 794902, + -738678, + 616501, + -414865, + 120934, + 276654, + -786902, + 1415512, + -2163926, + 3028396, + -3999116, + 5059470, + -6185439, + 7345214, + -8499045, + 9599368, + -10591215, + 11412930, + -11997177, + 12272221, + -12163438, + 11595015, + -10491742, + 8780831, + -6393623, + 3267067, + 655198, + -5422371, + 11076877, + -17655988, + 25195199, + -33734200, + 43326832, + -54057534, + 66068996, + -79610621, + 95128646, + -113447741, + 136177148, + -166755690, + 213739369, + -305113114, + 611619158, + 1912037381, + -265130181, + 103750544, + -41453291, + 8327940, + 11883343, + -24982901, + 33578915, + -39040650, + 42179015, + -43525847, + 43462245, + -42282361, + 40226796, + -37500592, + 34282986, + -30732580, + 26989962, + -23178899, + 19406805, + -15764915, + 12328410, + -9156679, + 6293785, + -3769204, + 1598819, + 213832, + -1676097, + 2804592, + -3623483, + 4162717, + -4456280, + 4540525, + -4452629, + 4229207, + -3905136, + 3512594, + -3080323, + 2633139, + -2191643, + 1772161, + -1386840, + 1043920, + -748105, + 501039, + -301824, + 147561, + -33896, + -44476, + 93352, + -118620, + 125936, + -120476, + 106762, + -88558, + 68837, + -49791, + 32894, + -6004, + 15660, + -31923, + 56552, + -91201, + 137235, + -195518, + 266183, + -348387, + 440076, + -537763, + 636355, + -729033, + 807210, + -860589, + 877324, + -844317, + 747635, + -573065, + 306792, + 63808, + -549277, + 1157130, + -1890859, + 2748965, + -3724024, + 4801866, + -5960887, + 7171560, + -8396172, + 9588828, + -10695737, + 11655808, + -12401536, + 12860177, + -12955159, + 12607703, + -11738556, + 10269760, + -8126337, + 5237757, + -1539000, + -3028985, + 8519724, + -14982961, + 22468281, + -31031544, + 40745686, + -51718672, + 64123884, + -78253655, + 94619332, + -114153742, + 138665890, + -172016403, + 223839320, + -325922652, + 677458829, + 1879107517, + -295418482, + 123681704, + -56311834, + 20059730, + 2370183, + -17188414, + 27191831, + -33846579, + 38016952, + -40265760, + 40992891, + -40504484, + 39049344, + -36838696, + 34056997, + -30867753, + 27416498, + -23832188, + 20227751, + -16700244, + 13330935, + -10185457, + 7314167, + -4752753, + 2523112, + -634475, + -915237, + 2137875, + -3053414, + 3688225, + -4073352, + 4242843, + -4232179, + 4076859, + -3811165, + 3467139, + -3073777, + 2656461, + -2236600, + 1831486, + -1454338, + 1114495, + -817748, + 566765, + -361579, + 200107, + -78677, + -7468, + 63709, + -95644, + 108754, + -108131, + 98295, + -83065, + 65512, + -47951, + 31989, + -4235, + 12904, + -28074, + 51610, + -85320, + 130775, + -189098, + 260730, + -345177, + 440763, + -544392, + 651350, + -755153, + 847482, + -918197, + 955467, + -946025, + 875552, + -729202, + 492250, + -150876, + -306955, + 890535, + -1605399, + 2452313, + -3426291, + 4515696, + -5701471, + 6956545, + -8245460, + 9524250, + -10740610, + 11834355, + -12738189, + 13378759, + -13677972, + 13554513, + -12925517, + 11708279, + -9821908, + 7188765, + -3735515, + -606443, + 5901472, + -12211552, + 19600139, + -28139032, + 37919976, + -49074050, + 61804677, + -76446048, + 93572822, + -114222943, + 140400028, + -176378110, + 232859592, + -345480429, + 743838800, + 1842913003, + -322878734, + 142481275, + -70623774, + 31536394, + -7060127, + -9365719, + 20702070, + -28499647, + 33669202, + -36800203, + 38308397, + -38509767, + 37659644, + -35974065, + 33641545, + -30829477, + 27687455, + -24348850, + 20931421, + -17537472, + 14253865, + -11152081, + 8288461, + -5704682, + 3428505, + -1474779, + -153312, + 1462811, + -2469409, + 3195767, + -3669832, + 3923166, + -3989369, + 3902630, + -3696452, + 3402565, + -3050060, + 2664741, + -2268703, + 1880109, + -1513166, + 1178260, + -882229, + 628746, + -418769, + 251035, + -122574, + 29198, + 34033, + -72399, + 91174, + -95343, + 89396, + -77191, + 61875, + -45875, + 30922, + -2391, + 10009, + -23988, + 46287, + -78861, + 123478, + -181517, + 253728, + -339970, + 438958, + -548005, + 662802, + -777243, + 883320, + -971108, + 1028854, + -1043196, + 999506, + -882378, + 676258, + -366198, + -61272, + 617177, + -1309076, + 2140007, + -3107458, + 4202405, + -5408453, + 6701148, + -8047492, + 9405707, + -10725265, + 11947230, + -13004891, + 13824697, + -14327462, + 14429788, + -14045649, + 13088048, + -11470615, + 9109021, + -5922006, + 1831778, + 3236529, + -9356825, + 16606129, + -25071849, + 34864132, + -46136605, + 59121873, + -74194623, + 91990571, + -113648968, + 141361465, + -179804090, + 240730427, + -363646608, + 810563475, + 1803574462, + -347492677, + 160074653, + -84319631, + 42697802, + -16356183, + -1558532, + 14146556, + -23030734, + 29161227, + -33149772, + 35424999, + -36310552, + 36066596, + -34912588, + 33039916, + -30618833, + 27802089, + -24726667, + 21514455, + -18272395, + 15092426, + -12051448, + 9211444, + -6619820, + 4310024, + -2302418, + 605406, + 783227, + -1874815, + 2688205, + -3248101, + 3583417, + -3725695, + 3707634, + -3561774, + 3319362, + -3009421, + 2658038, + -2287866, + 1917837, + -1563063, + 1234913, + -941230, + 686666, + -473094, + 300076, + -165350, + 65319, + 4491, + -49017, + 73300, + -82189, + 80124, + -70974, + 57953, + -43581, + 29703, + -481, + 6991, + -19684, + 40608, + -71850, + 115374, + -172805, + 245198, + -332773, + 434644, + -548549, + 670613, + -795140, + 914482, + -1018982, + 1097033, + -1135246, + 1118764, + -1031705, + 857766, + -580946, + 186409, + 338555, + -1003492, + 1813709, + -2769196, + 3863599, + -5083290, + 6406579, + -7803125, + 9233574, + -10649469, + 11993454, + -13199780, + 14195110, + -14899605, + 15228245, + -15092319, + 14401012, + -13062950, + 10987570, + -8086124, + 4272048, + 539639, + -6434389, + 13502396, + -21846247, + 31593960, + -42920994, + 56088077, + -71508734, + 89877033, + -112428961, + 141536184, + -182262236, + 247386910, + -380284228, + 877433881, + 1761222675, + -369253269, + 176394903, + -97334274, + 53486260, + -25467828, + 6189895, + 7562298, + -17471183, + 24519219, + -29335974, + 32359949, + -33920259, + 34280190, + -33661219, + 32256420, + -30237862, + 27760532, + -24964206, + 21974182, + -18901403, + 15842341, + -12878858, + 10078204, + -7493230, + 5162856, + -3112820, + 1356682, + 102954, + -1273023, + 2168467, + -2810627, + 3225619, + -3442762, + 3493092, + -3408013, + 3218117, + -2952203, + 2636494, + -2294076, + 1944540, + -1603816, + 1284192, + -994465, + 740236, + -524277, + 346970, + -206774, + 100697, + -24750, + -25634, + 55236, + -68749, + 70534, + -64457, + 53773, + -41086, + 28343, + 1487, + 3863, + -15184, + 34598, + -64321, + 106497, + -162995, + 235171, + -323605, + 427818, + -545991, + 674703, + -808705, + 940749, + -1061506, + 1159573, + -1221613, + 1232617, + -1176313, + 1035732, + -793904, + 434703, + 56205, + -690313, + 1475175, + -2413294, + 3501037, + -4727629, + 6074278, + -7513479, + 9008531, + -10513327, + 11972419, + -13321389, + 14487529, + -15390792, + 15945007, + -16059273, + 15639456, + -14589677, + 12813640, + -10215588, + 6700653, + -2174199, + -3460316, + 10305790, + -18479459, + 28126564, + -39443530, + 52717949, + -68400236, + 87239667, + -110563635, + 140914364, + -183725293, + 252769392, + -395259851, + 944248409, + 1715998067, + -388164569, + 191382939, + -109607195, + 63846797, + -34346421, + 13837008, + 986177, + -11852624, + 19769948, + -25381094, + 29131416, + -31353298, + 32311442, + -32227943, + 31296363, + -29689549, + 27563791, + -25060831, + 22308635, + -19421496, + 16499849, + -13630036, + 10884173, + -8320233, + 5982371, + -3901538, + 2096348, + -574194, + -667444, + 1639535, + -2359951, + 2851882, + -3142272, + 3260329, + -3236153, + 3099518, + -2878839, + 2600333, + -2287390, + 1960149, + -1635269, + 1325879, + -1041684, + 789192, + -572058, + 391476, + -246628, + 135141, + -53530, + -2379, + 37088, + -55102, + 60687, + -57679, + 49363, + -38408, + 26854, + 3500, + 643, + -10509, + 28288, + -56309, + 96889, + -152129, + 223685, + -312495, + 418492, + -540312, + 675013, + -817819, + 961930, + -1098392, + 1216076, + -1301765, + 1340380, + -1315349, + 1209125, + -1003859, + 682212, + -228303, + -371256, + 1126236, + -2041652, + 3116623, + -4343300, + 5705906, + -7179935, + 8731559, + -10317285, + 11883891, + -13368658, + 14699911, + -15797850, + 16575634, + -16940674, + 16796041, + -16041884, + 14576697, + -12298248, + 9103877, + -4889813, + -451056, + 7033775, + -14989605, + 24480254, + -35722094, + 49028127, + -64883437, + 84088920, + -108057299, + 139490479, + -184171069, + 256823880, + -408444203, + 1010803571, + 1668050139, + -404241579, + 204987659, + -121082758, + 73727425, + -42945082, + 21341174, + -5545247, + -6206794, + 14940609, + -21308069, + 25758375, + -28624990, + 30172330, + -30621716, + 30166013, + -28977798, + 27213735, + -25016695, + 22516558, + -19830299, + 17061728, + -14301156, + 11625142, + -9096433, + 6764154, + -4664268, + 2820324, + -1244439, + -61491, + 1104423, + -1898676, + 2464397, + -2826017, + 3010763, + -3047273, + 2964343, + -2789851, + 2549862, + -2267940, + 1964661, + -1657316, + 1359803, + -1082670, + 833300, + -616199, + 433365, + -284703, + 168467, + -81693, + 20616, + 18957, + -41329, + 50642, + -50685, + 44754, + -35568, + 25247, + 5549, + -2653, + -5685, + 21709, + -47853, + 86593, + -140257, + 210790, + -299485, + 406693, + -531514, + 671503, + -822391, + 977859, + -1129385, + 1266171, + -1375198, + 1441399, + -1447988, + 1376934, + -1209603, + 927537, + -513379, + -48083, + 768797, + -1656271, + 2712395, + -3932303, + 5303334, + -6804131, + 8403937, + -10062130, + 11728016, + -13340936, + 14830655, + -16118067, + 17116148, + -17731140, + 17863858, + -17411032, + 16266514, + -14322155, + 11468077, + -7591943, + 2576661, + 3704331, + -11395604, + 20674454, + -31776050, + 45037156, + -60975032, + 80438187, + -104917870, + 137263378, + -183582620, + 259502414, + -419712799, + 1076894774, + 1617536882, + -417510035, + 217166049, + -131710424, + 83079384, + -51218935, + 28661909, + -11995944, + -565363, + 10058668, + -17140359, + 22260501, + -25751471, + 27875719, + -28852417, + 28872556, + -28107408, + 26713083, + -24832738, + 22597411, + -20126073, + 17525305, + -14888860, + 12297290, + -9817745, + 7504019, + -5396875, + 3524638, + -1904066, + 541438, + 566165, + -1429447, + 2065416, + -2495863, + 2745898, + -2842542, + 2813461, + -2685843, + 2485463, + -2235927, + 1958133, + -1669908, + 1385835, + -1117248, + 872354, + -656486, + 472427, + -320802, + 200499, + -109086, + 43226, + 948, + -27508, + 40458, + -43518, + 39973, + -32583, + 23536, + 7621, + -6007, + -736, + 14894, + -38994, + 75660, + -127433, + 196540, + -284627, + 392460, + -519615, + 664158, + -822352, + 988400, + -1154258, + 1309524, + -1441445, + 1535051, + -1573431, + 1538172, + -1409947, + 1169276, + -797419, + 277409, + 404819, + -1259240, + 2290515, + -3496801, + 4868638, + -6387950, + 8027238, + -9748984, + 11505321, + -13237994, + 14878610, + -16349203, + 17563057, + -18425771, + 18836460, + -18689010, + 17873220, + -16275633, + 13779760, + -10265325, + 5605910, + 335861, + -7717063, + 16729599, + -27626142, + 40765394, + -56694035, + 76303770, + -101156863, + 134236341, + -181948415, + 260763418, + -428946559, + 1142317093, + 1564624147, + -428006161, + 227883239, + -141444941, + 91857370, + -59125330, + 35760088, + -18330605, + 5040240, + 5151709, + -12901810, + 18658053, + -22749601, + 25435286, + -26930784, + 27424055, + -27084043, + 26065382, + -24510678, + 22551364, + -20307718, + 17888471, + -15390274, + 12897199, + -10480406, + 8198041, + -6095412, + 4205450, + -2549436, + 1137983, + 27794, + -954941, + 1657242, + -2153747, + 2467313, + -2623208, + 2647819, + -2567502, + 2407594, + -2191622, + 1940685, + -1673046, + 1403893, + -1145275, + 906179, + -692726, + 508469, + -354744, + 231071, + -135563, + 65328, + -16842, + -13720, + 30196, + -36220, + 35054, + -29476, + 21732, + 9704, + -9400, + 4312, + 7880, + -29778, + 64143, + -113718, + 181001, + -267984, + 375850, + -504651, + 652982, + -817659, + 993446, + -1172820, + 1345834, + -1500074, + 1620750, + -1690919, + 1691880, + -1603723, + 1406042, + -1078812, + 603399, + 36316, + -852727, + 1853256, + -3039108, + 4404088, + -5933517, + 7603318, + -9379303, + 11216711, + -13060024, + 14843085, + -16489509, + 17913380, + -19020184, + 19707903, + -19868176, + 19387367, + -18147343, + 16025661, + -12894779, + 8619667, + -3052913, + -3974175, + 12667024, + -23294389, + 36234910, + -52061681, + 71704802, + -96789360, + 130417102, + -179262467, + 260572020, + -436032406, + 1206866062, + 1509484989, + -435776380, + 237112528, + -150246505, + 100019741, + -66624056, + 42598148, + -24514829, + 10579007, + 247281, + -8616519, + 14971758, + -19636862, + 22865441, + -24868355, + 25829400, + -25914193, + 25274984, + -24053000, + 22379302, + -20374780, + 18149690, + -15803020, + 13421875, + -11081007, + 8842569, + -6756147, + 4859071, + -3177013, + 1724837, + -507673, + -477845, + 1242218, + -1801658, + 2176657, + -2390596, + 2468446, + -2435587, + 2316788, + -2135362, + 1912496, + -1666786, + 1413939, + -1166650, + 934630, + -724755, + 541318, + -386357, + 260025, + -160986, + 86803, + -34313, + -40, + 19914, + -28836, + 30024, + -26266, + 19849, + 11787, + -12814, + 9430, + 703, + -20252, + 52101, + -99179, + 164247, + -249633, + 356931, + -486676, + 638000, + -808298, + 992918, + -1184911, + 1374837, + -1550695, + 1697952, + -1799728, + 1837138, + -1789790, + 1636466, + -1355955, + 928052, + -334663, + -438967, + 1402994, + -2561676, + 3912132, + -5443178, + 7134309, + -8954870, + 10863466, + -12807643, + 14723856, + -16537739, + 18164664, + -19510538, + 20472785, + -20941409, + 20799978, + -19926348, + 18192815, + -15465294, + 11600909, + -6443054, + -187612, + 8508855, + -18803969, + 31469372, + -47101334, + 66663171, + -91833959, + 125817867, + -175524446, + 258900348, + -440863845, + 1270338454, + 1452298982, + -440876977, + 244835359, + -158080894, + 107528693, + -73677538, + 49140283, + -30515313, + 16020510, + -4627259, + -4308703, + 11222694, + -16431263, + 20181240, + -22677390, + 24098252, + -24605137, + 24347021, + -23462932, + 22082806, + -20327449, + 18308006, + -16125231, + 13868759, + -11616500, + 9434250, + -7375578, + 5481987, + -3783377, + 2298767, + -1037252, + -849, + 822711, + -1441631, + 1875633, + -2146094, + 2276436, + -2290930, + 2213645, + -2067549, + 1873805, + -1651237, + 1415981, + -1181308, + 957595, + -752428, + 570818, + -415487, + 287217, + -185224, + 107538, + -51371, + 13454, + 9672, + -21410, + 24917, + -22974, + 17900, + 13855, + -16227, + 14589, + -6598, + -10466, + 39594, + -83889, + 146358, + -229657, + 335786, + -465762, + 619262, + -794276, + 986772, + -1190407, + 1396311, + -1592957, + 1766156, + -1899182, + 1973066, + -1967047, + 1859204, + -1627257, + 1249527, + -706043, + -20249, + 942188, + -2067080, + 3395388, + -4919500, + 6622610, + -8477783, + 10447239, + -12481889, + 14521169, + -16493159, + 18315001, + -19893557, + 21126277, + -21902147, + 22102602, + -21602180, + 20268637, + -17962111, + 14532701, + -9815511, + 3621595, + 4277883, + -14179096, + 26493928, + -41838363, + 61203418, + -86312709, + 120455288, + -170739752, + 255727800, + -443341516, + 1332533071, + 1393251518, + -443373732, + 251041272, + -164919572, + 114350428, + -80251016, + 55352625, + -36300023, + 21335072, + -9444895, + -2555, + 7432167, + -13151232, + 17398298, + -20370809, + 22240988, + -23164895, + 23287367, + -22744429, + 21664149, + -20166555, + 18363041, + -16355554, + 14235741, + -12084218, + 9970044, + -7950452, + 6070872, + -4365248, + 2856630, + -1558011, + 473376, + 401097, + -1075730, + 1565993, + -1891149, + 2072950, + -2134431, + 2098829, + -1988648, + 1824908, + -1626557, + 1410073, + -1189223, + 974992, + -775632, + 596838, + -441997, + 312511, + -208152, + 127423, + -67926, + 26689, + -474, + -13983, + 19762, + -19621, + 15897, + 15897, + -19621, + 19762, + -13983, + -474, + 26689, + -67926, + 127423, + -208152, + 312511, + -441997, + 596838, + -775632, + 974992, + -1189223, + 1410073, + -1626557, + 1824908, + -1988648, + 2098829, + -2134431, + 2072950, + -1891149, + 1565993, + -1075730, + 401097, + 473376, + -1558011, + 2856630, + -4365248, + 6070872, + -7950452, + 9970044, + -12084218, + 14235741, + -16355554, + 18363041, + -20166555, + 21664149, + -22744429, + 23287367, + -23164895, + 22240988, + -20370809, + 17398298, + -13151232, + 7432167, + -2555, + -9444895, + 21335072, + -36300023, + 55352625, + -80251016, + 114350428, + -164919572, + 251041272, + -443373732, + 1393251518, + 1332533071, + -443341516, + 255727800, + -170739752, + 120455288, + -86312709, + 61203418, + -41838363, + 26493928, + -14179096, + 4277883, + 3621595, + -9815511, + 14532701, + -17962111, + 20268637, + -21602180, + 22102602, + -21902147, + 21126277, + -19893557, + 18315001, + -16493159, + 14521169, + -12481889, + 10447239, + -8477783, + 6622610, + -4919500, + 3395388, + -2067080, + 942188, + -20249, + -706043, + 1249527, + -1627257, + 1859204, + -1967047, + 1973066, + -1899182, + 1766156, + -1592957, + 1396311, + -1190407, + 986772, + -794276, + 619262, + -465762, + 335786, + -229657, + 146358, + -83889, + 39594, + -10466, + -6598, + 14589, + -16227, + 13855, + 17900, + -22974, + 24917, + -21410, + 9672, + 13454, + -51371, + 107538, + -185224, + 287217, + -415487, + 570818, + -752428, + 957595, + -1181308, + 1415981, + -1651237, + 1873805, + -2067549, + 2213645, + -2290930, + 2276436, + -2146094, + 1875633, + -1441631, + 822711, + -849, + -1037252, + 2298767, + -3783377, + 5481987, + -7375578, + 9434250, + -11616500, + 13868759, + -16125231, + 18308006, + -20327449, + 22082806, + -23462932, + 24347021, + -24605137, + 24098252, + -22677390, + 20181240, + -16431263, + 11222694, + -4308703, + -4627259, + 16020510, + -30515313, + 49140283, + -73677538, + 107528693, + -158080894, + 244835359, + -440876977, + 1452298982, + 1270338454, + -440863845, + 258900348, + -175524446, + 125817867, + -91833959, + 66663171, + -47101334, + 31469372, + -18803969, + 8508855, + -187612, + -6443054, + 11600909, + -15465294, + 18192815, + -19926348, + 20799978, + -20941409, + 20472785, + -19510538, + 18164664, + -16537739, + 14723856, + -12807643, + 10863466, + -8954870, + 7134309, + -5443178, + 3912132, + -2561676, + 1402994, + -438967, + -334663, + 928052, + -1355955, + 1636466, + -1789790, + 1837138, + -1799728, + 1697952, + -1550695, + 1374837, + -1184911, + 992918, + -808298, + 638000, + -486676, + 356931, + -249633, + 164247, + -99179, + 52101, + -20252, + 703, + 9430, + -12814, + 11787, + 19849, + -26266, + 30024, + -28836, + 19914, + -40, + -34313, + 86803, + -160986, + 260025, + -386357, + 541318, + -724755, + 934630, + -1166650, + 1413939, + -1666786, + 1912496, + -2135362, + 2316788, + -2435587, + 2468446, + -2390596, + 2176657, + -1801658, + 1242218, + -477845, + -507673, + 1724837, + -3177013, + 4859071, + -6756147, + 8842569, + -11081007, + 13421875, + -15803020, + 18149690, + -20374780, + 22379302, + -24053000, + 25274984, + -25914193, + 25829400, + -24868355, + 22865441, + -19636862, + 14971758, + -8616519, + 247281, + 10579007, + -24514829, + 42598148, + -66624056, + 100019741, + -150246505, + 237112528, + -435776380, + 1509484989, + 1206866062, + -436032406, + 260572020, + -179262467, + 130417102, + -96789360, + 71704802, + -52061681, + 36234910, + -23294389, + 12667024, + -3974175, + -3052913, + 8619667, + -12894779, + 16025661, + -18147343, + 19387367, + -19868176, + 19707903, + -19020184, + 17913380, + -16489509, + 14843085, + -13060024, + 11216711, + -9379303, + 7603318, + -5933517, + 4404088, + -3039108, + 1853256, + -852727, + 36316, + 603399, + -1078812, + 1406042, + -1603723, + 1691880, + -1690919, + 1620750, + -1500074, + 1345834, + -1172820, + 993446, + -817659, + 652982, + -504651, + 375850, + -267984, + 181001, + -113718, + 64143, + -29778, + 7880, + 4312, + -9400, + 9704, + 21732, + -29476, + 35054, + -36220, + 30196, + -13720, + -16842, + 65328, + -135563, + 231071, + -354744, + 508469, + -692726, + 906179, + -1145275, + 1403893, + -1673046, + 1940685, + -2191622, + 2407594, + -2567502, + 2647819, + -2623208, + 2467313, + -2153747, + 1657242, + -954941, + 27794, + 1137983, + -2549436, + 4205450, + -6095412, + 8198041, + -10480406, + 12897199, + -15390274, + 17888471, + -20307718, + 22551364, + -24510678, + 26065382, + -27084043, + 27424055, + -26930784, + 25435286, + -22749601, + 18658053, + -12901810, + 5151709, + 5040240, + -18330605, + 35760088, + -59125330, + 91857370, + -141444941, + 227883239, + -428006161, + 1564624147, + 1142317093, + -428946559, + 260763418, + -181948415, + 134236341, + -101156863, + 76303770, + -56694035, + 40765394, + -27626142, + 16729599, + -7717063, + 335861, + 5605910, + -10265325, + 13779760, + -16275633, + 17873220, + -18689010, + 18836460, + -18425771, + 17563057, + -16349203, + 14878610, + -13237994, + 11505321, + -9748984, + 8027238, + -6387950, + 4868638, + -3496801, + 2290515, + -1259240, + 404819, + 277409, + -797419, + 1169276, + -1409947, + 1538172, + -1573431, + 1535051, + -1441445, + 1309524, + -1154258, + 988400, + -822352, + 664158, + -519615, + 392460, + -284627, + 196540, + -127433, + 75660, + -38994, + 14894, + -736, + -6007, + 7621, + 23536, + -32583, + 39973, + -43518, + 40458, + -27508, + 948, + 43226, + -109086, + 200499, + -320802, + 472427, + -656486, + 872354, + -1117248, + 1385835, + -1669908, + 1958133, + -2235927, + 2485463, + -2685843, + 2813461, + -2842542, + 2745898, + -2495863, + 2065416, + -1429447, + 566165, + 541438, + -1904066, + 3524638, + -5396875, + 7504019, + -9817745, + 12297290, + -14888860, + 17525305, + -20126073, + 22597411, + -24832738, + 26713083, + -28107408, + 28872556, + -28852417, + 27875719, + -25751471, + 22260501, + -17140359, + 10058668, + -565363, + -11995944, + 28661909, + -51218935, + 83079384, + -131710424, + 217166049, + -417510035, + 1617536882, + 1076894774, + -419712799, + 259502414, + -183582620, + 137263378, + -104917870, + 80438187, + -60975032, + 45037156, + -31776050, + 20674454, + -11395604, + 3704331, + 2576661, + -7591943, + 11468077, + -14322155, + 16266514, + -17411032, + 17863858, + -17731140, + 17116148, + -16118067, + 14830655, + -13340936, + 11728016, + -10062130, + 8403937, + -6804131, + 5303334, + -3932303, + 2712395, + -1656271, + 768797, + -48083, + -513379, + 927537, + -1209603, + 1376934, + -1447988, + 1441399, + -1375198, + 1266171, + -1129385, + 977859, + -822391, + 671503, + -531514, + 406693, + -299485, + 210790, + -140257, + 86593, + -47853, + 21709, + -5685, + -2653, + 5549, + 25247, + -35568, + 44754, + -50685, + 50642, + -41329, + 18957, + 20616, + -81693, + 168467, + -284703, + 433365, + -616199, + 833300, + -1082670, + 1359803, + -1657316, + 1964661, + -2267940, + 2549862, + -2789851, + 2964343, + -3047273, + 3010763, + -2826017, + 2464397, + -1898676, + 1104423, + -61491, + -1244439, + 2820324, + -4664268, + 6764154, + -9096433, + 11625142, + -14301156, + 17061728, + -19830299, + 22516558, + -25016695, + 27213735, + -28977798, + 30166013, + -30621716, + 30172330, + -28624990, + 25758375, + -21308069, + 14940609, + -6206794, + -5545247, + 21341174, + -42945082, + 73727425, + -121082758, + 204987659, + -404241579, + 1668050139, + 1010803571, + -408444203, + 256823880, + -184171069, + 139490479, + -108057299, + 84088920, + -64883437, + 49028127, + -35722094, + 24480254, + -14989605, + 7033775, + -451056, + -4889813, + 9103877, + -12298248, + 14576697, + -16041884, + 16796041, + -16940674, + 16575634, + -15797850, + 14699911, + -13368658, + 11883891, + -10317285, + 8731559, + -7179935, + 5705906, + -4343300, + 3116623, + -2041652, + 1126236, + -371256, + -228303, + 682212, + -1003859, + 1209125, + -1315349, + 1340380, + -1301765, + 1216076, + -1098392, + 961930, + -817819, + 675013, + -540312, + 418492, + -312495, + 223685, + -152129, + 96889, + -56309, + 28288, + -10509, + 643, + 3500, + 26854, + -38408, + 49363, + -57679, + 60687, + -55102, + 37088, + -2379, + -53530, + 135141, + -246628, + 391476, + -572058, + 789192, + -1041684, + 1325879, + -1635269, + 1960149, + -2287390, + 2600333, + -2878839, + 3099518, + -3236153, + 3260329, + -3142272, + 2851882, + -2359951, + 1639535, + -667444, + -574194, + 2096348, + -3901538, + 5982371, + -8320233, + 10884173, + -13630036, + 16499849, + -19421496, + 22308635, + -25060831, + 27563791, + -29689549, + 31296363, + -32227943, + 32311442, + -31353298, + 29131416, + -25381094, + 19769948, + -11852624, + 986177, + 13837008, + -34346421, + 63846797, + -109607195, + 191382939, + -388164569, + 1715998067, + 944248409, + -395259851, + 252769392, + -183725293, + 140914364, + -110563635, + 87239667, + -68400236, + 52717949, + -39443530, + 28126564, + -18479459, + 10305790, + -3460316, + -2174199, + 6700653, + -10215588, + 12813640, + -14589677, + 15639456, + -16059273, + 15945007, + -15390792, + 14487529, + -13321389, + 11972419, + -10513327, + 9008531, + -7513479, + 6074278, + -4727629, + 3501037, + -2413294, + 1475175, + -690313, + 56205, + 434703, + -793904, + 1035732, + -1176313, + 1232617, + -1221613, + 1159573, + -1061506, + 940749, + -808705, + 674703, + -545991, + 427818, + -323605, + 235171, + -162995, + 106497, + -64321, + 34598, + -15184, + 3863, + 1487, + 28343, + -41086, + 53773, + -64457, + 70534, + -68749, + 55236, + -25634, + -24750, + 100697, + -206774, + 346970, + -524277, + 740236, + -994465, + 1284192, + -1603816, + 1944540, + -2294076, + 2636494, + -2952203, + 3218117, + -3408013, + 3493092, + -3442762, + 3225619, + -2810627, + 2168467, + -1273023, + 102954, + 1356682, + -3112820, + 5162856, + -7493230, + 10078204, + -12878858, + 15842341, + -18901403, + 21974182, + -24964206, + 27760532, + -30237862, + 32256420, + -33661219, + 34280190, + -33920259, + 32359949, + -29335974, + 24519219, + -17471183, + 7562298, + 6189895, + -25467828, + 53486260, + -97334274, + 176394903, + -369253269, + 1761222675, + 877433881, + -380284228, + 247386910, + -182262236, + 141536184, + -112428961, + 89877033, + -71508734, + 56088077, + -42920994, + 31593960, + -21846247, + 13502396, + -6434389, + 539639, + 4272048, + -8086124, + 10987570, + -13062950, + 14401012, + -15092319, + 15228245, + -14899605, + 14195110, + -13199780, + 11993454, + -10649469, + 9233574, + -7803125, + 6406579, + -5083290, + 3863599, + -2769196, + 1813709, + -1003492, + 338555, + 186409, + -580946, + 857766, + -1031705, + 1118764, + -1135246, + 1097033, + -1018982, + 914482, + -795140, + 670613, + -548549, + 434644, + -332773, + 245198, + -172805, + 115374, + -71850, + 40608, + -19684, + 6991, + -481, + 29703, + -43581, + 57953, + -70974, + 80124, + -82189, + 73300, + -49017, + 4491, + 65319, + -165350, + 300076, + -473094, + 686666, + -941230, + 1234913, + -1563063, + 1917837, + -2287866, + 2658038, + -3009421, + 3319362, + -3561774, + 3707634, + -3725695, + 3583417, + -3248101, + 2688205, + -1874815, + 783227, + 605406, + -2302418, + 4310024, + -6619820, + 9211444, + -12051448, + 15092426, + -18272395, + 21514455, + -24726667, + 27802089, + -30618833, + 33039916, + -34912588, + 36066596, + -36310552, + 35424999, + -33149772, + 29161227, + -23030734, + 14146556, + -1558532, + -16356183, + 42697802, + -84319631, + 160074653, + -347492677, + 1803574462, + 810563475, + -363646608, + 240730427, + -179804090, + 141361465, + -113648968, + 91990571, + -74194623, + 59121873, + -46136605, + 34864132, + -25071849, + 16606129, + -9356825, + 3236529, + 1831778, + -5922006, + 9109021, + -11470615, + 13088048, + -14045649, + 14429788, + -14327462, + 13824697, + -13004891, + 11947230, + -10725265, + 9405707, + -8047492, + 6701148, + -5408453, + 4202405, + -3107458, + 2140007, + -1309076, + 617177, + -61272, + -366198, + 676258, + -882378, + 999506, + -1043196, + 1028854, + -971108, + 883320, + -777243, + 662802, + -548005, + 438958, + -339970, + 253728, + -181517, + 123478, + -78861, + 46287, + -23988, + 10009, + -2391, + 30922, + -45875, + 61875, + -77191, + 89396, + -95343, + 91174, + -72399, + 34033, + 29198, + -122574, + 251035, + -418769, + 628746, + -882229, + 1178260, + -1513166, + 1880109, + -2268703, + 2664741, + -3050060, + 3402565, + -3696452, + 3902630, + -3989369, + 3923166, + -3669832, + 3195767, + -2469409, + 1462811, + -153312, + -1474779, + 3428505, + -5704682, + 8288461, + -11152081, + 14253865, + -17537472, + 20931421, + -24348850, + 27687455, + -30829477, + 33641545, + -35974065, + 37659644, + -38509767, + 38308397, + -36800203, + 33669202, + -28499647, + 20702070, + -9365719, + -7060127, + 31536394, + -70623774, + 142481275, + -322878734, + 1842913003, + 743838800, + -345480429, + 232859592, + -176378110, + 140400028, + -114222943, + 93572822, + -76446048, + 61804677, + -49074050, + 37919976, + -28139032, + 19600139, + -12211552, + 5901472, + -606443, + -3735515, + 7188765, + -9821908, + 11708279, + -12925517, + 13554513, + -13677972, + 13378759, + -12738189, + 11834355, + -10740610, + 9524250, + -8245460, + 6956545, + -5701471, + 4515696, + -3426291, + 2452313, + -1605399, + 890535, + -306955, + -150876, + 492250, + -729202, + 875552, + -946025, + 955467, + -918197, + 847482, + -755153, + 651350, + -544392, + 440763, + -345177, + 260730, + -189098, + 130775, + -85320, + 51610, + -28074, + 12904, + -4235, + 31989, + -47951, + 65512, + -83065, + 98295, + -108131, + 108754, + -95644, + 63709, + -7468, + -78677, + 200107, + -361579, + 566765, + -817748, + 1114495, + -1454338, + 1831486, + -2236600, + 2656461, + -3073777, + 3467139, + -3811165, + 4076859, + -4232179, + 4242843, + -4073352, + 3688225, + -3053414, + 2137875, + -915237, + -634475, + 2523112, + -4752753, + 7314167, + -10185457, + 13330935, + -16700244, + 20227751, + -23832188, + 27416498, + -30867753, + 34056997, + -36838696, + 39049344, + -40504484, + 40992891, + -40265760, + 38016952, + -33846579, + 27191831, + -17188414, + 2370183, + 20059730, + -56311834, + 123681704, + -295418482, + 1879107517, + 677458829, + -325922652, + 223839320, + -172016403, + 138665890, + -114153742, + 94619332, + -78253655, + 64123884, + -51718672, + 40745686, + -31031544, + 22468281, + -14982961, + 8519724, + -3028985, + -1539000, + 5237757, + -8126337, + 10269760, + -11738556, + 12607703, + -12955159, + 12860177, + -12401536, + 11655808, + -10695737, + 9588828, + -8396172, + 7171560, + -5960887, + 4801866, + -3724024, + 2748965, + -1890859, + 1157130, + -549277, + 63808, + 306792, + -573065, + 747635, + -844317, + 877324, + -860589, + 807210, + -729033, + 636355, + -537763, + 440076, + -348387, + 266183, + -195518, + 137235, + -91201, + 56552, + -31923, + 15660, + -6004, + 32894, + -49791, + 68837, + -88558, + 106762, + -120476, + 125936, + -118620, + 93352, + -44476, + -33896, + 147561, + -301824, + 501039, + -748105, + 1043920, + -1386840, + 1772161, + -2191643, + 2633139, + -3080323, + 3512594, + -3905136, + 4229207, + -4452629, + 4540525, + -4456280, + 4162717, + -3623483, + 2804592, + -1676097, + 213832, + 1598819, + -3769204, + 6293785, + -9156679, + 12328410, + -15764915, + 19406805, + -23178899, + 26989962, + -30732580, + 34282986, + -37500592, + 40226796, + -42282361, + 43462245, + -43525847, + 42179015, + -39040650, + 33578915, + -24982901, + 11883343, + 8327940, + -41453291, + 103750544, + -265130181, + 1912037381, + 611619158, + -305113114, + 213739369, + -166755690, + 136177148, + -113447741, + 95128646, + -79610621, + 66068996, + -54057534, + 43326832, + -33734200, + 25195199, + -17655988, + 11076877, + -5422371, + 655198, + 3267067, + -6393623, + 8780831, + -10491742, + 11595015, + -12163438, + 12272221, + -11997177, + 11412930, + -10591215, + 9599368, + -8499045, + 7345214, + -6185439, + 5059470, + -3999116, + 3028396, + -2163926, + 1415512, + -786902, + 276654, + 120934, + -414865, + 616501, + -738678, + 794902, + -798646, + 762770, + -699067, + 617937, + -528184, + 436926, + -349605, + 270075, + -200755, + 142832, + -96478, + 61091, + -35517, + 18264, + -7688, + 33628, + -51380, + 71825, + -93631, + 114742, + -132301, + 142617, + -141192, + 122794, + -81621, + 11523, + 93681, + -239818, + 431908, + -673652, + 966880, + -1310988, + 1702388, + -2133995, + 2594800, + -3069544, + 3538547, + -3977702, + 4358678, + -4649339, + 4814405, + -4816338, + 4616467, + -4176326, + 3459161, + -2431600, + 1065406, + 660731, + -2759409, + 5232825, + -8071224, + 11251535, + -14736261, + 18472624, + -22391980, + 26409473, + -30423845, + 34317273, + -37954978, + 41184244, + -43832202, + 45701338, + -46560893, + 46130804, + -44051618, + 39826682, + -32705242, + 21426965, + -3596706, + -26121668, + 82769853, + -232043374, + 1941592615, + 546511275, + -283193876, + 202633912, + -160637058, + 132955829, + -112114768, + 95102298, + -80512677, + 67631668, + -56079484, + 45650434, + -36232960, + 27766410, + -20216199, + 13558939, + -7773356, + 2834811, + 1287823, + -4633647, + 7250078, + -9192352, + 10522446, + -11307588, + 11618536, + -11527724, + 11107417, + -10427946, + 9556104, + -8553765, + 7476766, + -6374069, + 5287232, + -4250161, + 3289146, + -2423146, + 1664286, + -1018530, + 486484, + -64279, + -255503, + 482909, + -629733, + 708701, + -732755, + 714448, + -665458, + 596231, + -515739, + 431358, + -348846, + 272403, + -204796, + 147547, + -101131, + 65208, + -38841, + 20706, + -9280, + 34182, + -52704, + 74453, + -98249, + 122184, + -143530, + 158696, + -163226, + 151865, + -118691, + 57329, + 38758, + -175892, + 359733, + -594769, + 883758, + -1227145, + 1622483, + -2063888, + 2541556, + -3041383, + 3544724, + -4028316, + 4464398, + -4821056, + 5062796, + -5151364, + 5046803, + -4708732, + 4097829, + -3177465, + 1915469, + -285943, + -1728917, + 4137054, + -6934917, + 10105999, + -13619608, + 17429902, + -21475196, + 25677527, + -29942411, + 34158686, + -38198215, + 41915128, + -45144031, + 47696252, + -49352471, + 49848748, + -48850054, + 45898991, + -40311514, + 30947962, + -15650111, + -10394203, + 60828888, + -196198909, + 1967674322, + 482321861, + -260308573, + 190601085, + -153705677, + 129027735, + -110168020, + 94544779, + -80958111, + 68805736, + -57775206, + 47705023, + -38515002, + 30168378, + -22649868, + 15952411, + -10069001, + 4987714, + -688855, + -2856397, + 5686275, + -7847921, + 9396299, + -10392723, + 10903115, + -10996139, + 10741307, + -10207156, + 9459567, + -8560290, + 7565714, + -6525926, + 5484052, + -4475897, + 3529870, + -2667155, + 1902120, + -1242901, + 692140, + -247813, + -95882, + 347629, + -518119, + 619233, + -663317, + 662549, + -628430, + 571392, + -500527, + 423429, + -346138, + 273172, + -207634, + 151366, + -105143, + 68887, + -41880, + 22974, + -10773, + 34549, + -53748, + 76699, + -102378, + 129036, + -154092, + 174073, + -184592, + 180396, + -155477, + 103265, + -16904, + -110392, + 284897, + -511866, + 794976, + -1135722, + 1532822, + -1981628, + 2473603, + -2995880, + 3530958, + -4056551, + 4545624, + -4966659, + 5284147, + -5459325, + 5451164, + -5217590, + 4716911, + -3909439, + 2759229, + -1235917, + -683424, + 3012463, + -5753899, + 8897907, + -12420802, + 16283969, + -20433061, + 24797487, + -29290117, + 33807132, + -38227835, + 42414124, + -46209154, + 49434360, + -51883404, + 53310436, + -53407512, + 51760396, + -47758056, + 40392828, + -27766679, + 5648505, + 38023811, + -157648913, + 1990195080, + 419232110, + -236601758, + 177722526, + -146010513, + 124422261, + -107623957, + 93463482, + -80947762, + 69587242, + -59137260, + 49480700, + -40568784, + 32388587, + -24944046, + 18244355, + -12296738, + 7101991, + -2651916, + -1071905, + 4098341, + -6466197, + 8223147, + -9424262, + 10130279, + -10405719, + 10316965, + -9930385, + 9310586, + -8518847, + 7611800, + -6640370, + 5649007, + -4675211, + 3749341, + -2894682, + 2127752, + -1458807, + 892500, + -428652, + 63101, + 211432, + -404482, + 527028, + -590752, + 607396, + -588221, + 543590, + -482663, + 413209, + -341516, + 272397, + -209267, + 154279, + -108500, + 72114, + -44623, + 25059, + -12160, + 34721, + -54502, + 78543, + -105986, + 135250, + -163918, + 188651, + -205158, + 208217, + -191765, + 149073, + -72998, + -43673, + 207799, + -425379, + 700989, + -1037179, + 1433839, + -1887592, + 2391220, + -2933173, + 3497196, + -4062103, + 4601742, + -5085168, + 5477049, + -5738328, + 5827127, + -5699900, + 5312816, + -4623325, + 3591900, + -2183860, + 371263, + 1865235, + -4534591, + 7633745, + -11146182, + 15040760, + -19270816, + 23773565, + -28469769, + 33263600, + -38042555, + 42677182, + -47020213, + 50904404, + -54137877, + 56494747, + -57696691, + 57376355, + -55001714, + 49707935, + -39879650, + 21922865, + 14457362, + -116456715, + 2009079295, + 357417072, + -212218256, + 164082901, + -137604018, + 119172198, + -104502185, + 91868645, + -80484992, + 69974441, + -60160112, + 50969180, + -42384104, + 34415602, + -27086631, + 20422470, + -14444445, + 9166003, + -4590440, + 709804, + 2495283, + -5055102, + 7009792, + -8407896, + 9304645, + -9760072, + 9837071, + -9599481, + 9110277, + -8429934, + 7615007, + -6716974, + 5781360, + -4847145, + 3946461, + -3104555, + 2339998, + -1665095, + 1086475, + -605799, + 220559, + 75088, + -289476, + 432625, + -515495, + 549328, + -545087, + 513009, + -462273, + 400780, + -335030, + 270101, + -209702, + 156282, + -111194, + 74878, + -47060, + 26953, + -13437, + 34692, + -54955, + 79967, + -109043, + 140782, + -172941, + 202337, + -224799, + 235163, + -227345, + 194491, + -129210, + 23896, + 128858, + -335766, + 602289, + -932016, + 1326022, + -1782225, + 2294772, + -2853501, + 3443495, + -4044797, + 4632281, + -5175749, + 5640246, + -5986632, + 6172410, + -6152800, + 5882058, + -5315007, + 4408735, + -3124425, + 1429252, + 701713, + -3283664, + 6320348, + -9802543, + 13706790, + -17994403, + 22610802, + -27485136, + 32530166, + -37642296, + 42701558, + -47571237, + 52096565, + -56101526, + 59381975, + -61691600, + 62713428, + -62000080, + 58839818, + -51921452, + 38342697, + -9761504, + -72696724, + 2024263503, + 297045034, + -187302521, + 149769424, + -128541802, + 113313516, + -100825318, + 89773270, + -79575654, + 69967790, + -60840152, + 52163826, + -43952149, + 36239129, + -29066432, + 22475153, + -16500506, + 11168450, + -6493698, + 2478769, + 886150, + -3622681, + 5763227, + -7349558, + 8431107, + -9063099, + 9304604, + -9216583, + 8860040, + -8294308, + 7575555, + -6755527, + 5880562, + -4990901, + 4120263, + -3295711, + 2537754, + -1860672, + 1273023, + -778289, + 375620, + -60636, + -173757, + 336572, + -437991, + 488697, + -499297, + 479848, + -439498, + 386235, + -326736, + 266316, + -208952, + 157377, + -113219, + 77171, + -49182, + 28649, + -14599, + 34459, + -55098, + 80956, + -111524, + 145590, + -181098, + 215043, + -243392, + 261071, + -262007, + 239257, + -185221, + 91941, + 48504, + -243510, + 499395, + -820778, + 1209916, + -1666040, + 2184706, + -2757196, + 3370027, + -4004582, + 4636908, + -5237722, + 5772641, + -6202661, + 6484895, + -6573573, + 6421289, + -5980471, + 5205053, + -4052279, + 2484607, + -471637, + -2007999, + 4964862, + -8397104, + 12289112, + -16610435, + 21315045, + -26340927, + 31609982, + -37028184, + 42485831, + -47857679, + 53002526, + -57761531, + 61953950, + -65367712, + 67739468, + -68711741, + 67735480, + -63824057, + 54819639, + -34518018, + -26454257, + 2035696625, + 238276923, + -161998008, + 134871369, + -118882301, + 106885142, + -96618829, + 87193026, + -78228039, + 69569938, + -61175703, + 53059682, + -45265533, + 37850068, + -30873229, + 24391562, + -18453877, + 13098429, + -8351212, + 4225152, + -720019, + -2177059, + 4490599, + -6255384, + 7514797, + -8318967, + 8722819, + -8784113, + 8561545, + -8112988, + 7493908, + -6756030, + 5946252, + -5105842, + 4269918, + -3467197, + 2720008, + -2044515, + 1451150, + -945187, + 527433, + -194984, + -57981, + 239422, + -358694, + 425866, + -451133, + 444319, + -414491, + 369680, + -316703, + 261080, + -207037, + 157571, + -114575, + 78988, + -50983, + 30141, + -15641, + 34018, + -54925, + 81497, + -113405, + 149635, + -188332, + 226683, + -260819, + 285782, + -295544, + 283111, + -240713, + 160080, + -32821, + -149109, + 392856, + -704045, + 1086113, + -1539616, + 2061546, + -2644690, + 3277077, + -3941539, + 4615435, + -5270564, + 5873306, + -6385010, + 6762636, + -6959673, + 6927306, + -6615829, + 5976262, + -4962133, + 3531373, + -1648261, + -714650, + 3574703, + -6937466, + 10795289, + -15126166, + 19892920, + -25042771, + 30507266, + -36202553, + 42029923, + -47876457, + 53615528, + -59106696, + 64194150, + -68702107, + 72423815, + -75096509, + 76342681, + -75519343, + 71263583, + -59692024, + 22174678, + 2043340170, + 181265755, + -136446551, + 119479583, + -108686429, + 99928711, + -91910882, + 84146145, + -76452815, + 68785693, + -61167019, + 53653486, + -46318336, + 39240553, + -32497818, + 26161671, + -20294146, + 14945502, + -10152811, + 5939287, + -2314246, + -726396, + 3199163, + -5131682, + 6561066, + -7532085, + 8095232, + -8304755, + 8216727, + -7887239, + 7370758, + -6718700, + 5978258, + -5191499, + 4394735, + -3618177, + 2885837, + -2215670, + 1619915, + -1105598, + 675170, + -327214, + 57204, + 141729, + -278064, + 361207, + -400888, + 406644, + -387414, + 351228, + -305005, + 254441, + -203982, + 156875, + -115263, + 80328, + -52459, + 31427, + -16561, + 33366, + -54429, + 81577, + -114666, + 152883, + -194589, + 237177, + -276967, + 309142, + -327754, + 325795, + -295366, + 227929, + -114664, + -53081, + 283244, + -582435, + 955257, + -1403593, + 1925896, + -2516507, + 3165039, + -3855877, + 4567820, + -5273911, + 5941485, + -6532455, + 7003869, + -7308730, + 7397079, + -7217343, + 6717888, + -5848770, + 4563613, + -2821553, + 589192, + 2157523, + -5431572, + 9233348, + -13549446, + 18351795, + -23597195, + 29227284, + -35168940, + 41335105, + -47625970, + 53930417, + -60127521, + 66087803, + -71673616, + 76737477, + -81115659, + 84610238, + -86939464, + 87583119, + -85158443, + 73083649, + 2047168391, + 126156109, + -110787761, + 103685994, + -98017220, + 92488315, + -86732158, + 80653302, + -74262948, + 67621984, + -60816270, + 53943683, + -47106124, + 40403994, + -33932065, + 27776325, + -22011583, + 16699742, + -11888686, + 7611738, + -3887666, + 721161, + 1896243, + -3984893, + 5575444, + -6707081, + 7425599, + -7781443, + 7827765, + -7618573, + 7207030, + -6643964, + 5976600, + -5247567, + 4494169, + -3747934, + 3034421, + -2373265, + 1778436, + -1258669, + 818033, + -456599, + 171156, + 44045, + -196566, + 295100, + -348863, + 367056, + -358441, + 331005, + -291729, + 246453, + -199820, + 155305, + -115290, + 81190, + -53608, + 32502, + -17358 + +}; + +static const struct src_stage src_int32_40_21_4535_5000 = { + 11, 21, 40, 116, 4640, 21, 40, 0, 0, + src_int32_40_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_40_7_2976_5000.h b/src/audio/src/coef/src_ipc4_int32_40_7_2976_5000.h new file mode 100644 index 000000000000..1a103403383a --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_40_7_2976_5000.h @@ -0,0 +1,1138 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_40_7_2976_5000_fir[1120] = { + -39160, + 426217, + -1390884, + 2246846, + -715184, + -6277964, + 19555652, + -33622141, + 34905463, + -5633255, + -66580718, + 178242629, + -306348091, + 420001039, + 1712544124, + 375888993, + -296151802, + 180129175, + -72239071, + -493446, + 31920968, + -32681953, + 19789081, + -6838550, + -288698, + 2049052, + -1338832, + 424001, + -36756, + 426249, + -1438870, + 2442370, + -1152748, + -5674596, + 19234649, + -34445505, + 37811782, + -10857342, + -60532747, + 175589478, + -315601691, + 464771521, + 1710261875, + 332522364, + -285077381, + 181259037, + -77493423, + 4543230, + 28872008, + -31631426, + 19936152, + -7355195, + 125233, + 1849949, + -1283142, + 419740, + -33657, + 423964, + -1482364, + 2634636, + -1599817, + -5029827, + 18825202, + -35145903, + 40626247, + -16146122, + -54111400, + 172162536, + -323849537, + 510110684, + 1705702986, + 289985136, + -273190649, + 181644787, + -82331266, + 9458710, + 25772268, + -30477356, + 19998411, + -7826957, + 525233, + 1650470, + -1224241, + 413574, + -29830, + 419236, + -1520944, + 2822638, + -2054723, + -4345257, + 18326797, + -35717570, + 43335268, + -21479341, + -47334749, + 167957444, + -331030283, + 555926238, + 1698878662, + 248358090, + -260558461, + 181301539, + -86741985, + 14235780, + 22635353, + -29226810, + 19977723, + -8253112, + 910029, + 1451517, + -1162554, + 405650, + -25242, + 411945, + -1554196, + 3005352, + -2515712, + -3622705, + 17739290, + -36155154, + 45925405, + -26836152, + -40222662, + 162972740, + -337084529, + 602123593, + 1689805663, + 207718594, + -247248474, + 180246848, + -90716858, + 18858128, + 19474735, + -27887098, + 19876252, + -8633152, + 1278456, + 1253956, + -1098500, + 396114, + -19869, + 401982, + -1581712, + 3181739, + -2980946, + -2864206, + 17062912, + -36453743, + 48383425, + -32195184, + -32796760, + 157209927, + -341955039, + 648606117, + 1678506261, + 168140420, + -233328919, + 178500590, + -94249054, + 23310390, + 16303699, + -26465728, + 19696447, + -8966777, + 1629456, + 1058615, + -1032494, + 385117, + -13688, + 389244, + -1603098, + 3350756, + -3448511, + -2072008, + 16298283, + -36608899, + 50696361, + -37534618, + -25080366, + 150673532, + -345586960, + 695275392, + 1665008170, + 129693568, + -218868371, + 176084845, + -97333622, + 27578197, + 13135291, + -24970378, + 19441027, + -9253896, + 1962082, + 866283, + -964940, + 372806, + -6681, + 373641, + -1617971, + 3511355, + -3916423, + -1248571, + 15446413, + -36616687, + 52851573, + -42832270, + -17098447, + 143371150, + -347928035, + 742031480, + 1649344465, + 92444097, + -203935525, + 173023767, + -99967477, + 31648208, + 9982274, + -23408858, + 19112958, + -9494618, + 2275494, + 677706, + -896234, + 359332, + 1164, + 355094, + -1625966, + 3662487, + -4382632, + -396555, + 14508711, + -36473702, + 54836807, + -48065674, + -8877548, + 135313483, + -348928806, + 788773199, + 1631553479, + 56453983, + -188598972, + 169343456, + -102149371, + 35508147, + 6857076, + -21789073, + 18715437, + -9689249, + 2568969, + 493584, + -826760, + 344840, + 9854, + 333535, + -1626738, + 3803114, + -4845035, + 481178, + 13486989, + -36177097, + 56640253, + -53212164, + -445718, + 126514364, + -348542817, + 835398400, + 1611678694, + 21780976, + -172926975, + 165071815, + -103879865, + 39146828, + 3771751, + -20118987, + 18251873, + -9838282, + 2841890, + 314573, + -756887, + 329476, + 19392, + 308912, + -1619960, + 3932206, + -5301479, + 1381579, + 12383461, + -35724604, + 58250605, + -58248966, + 8167567, + 116990775, + -346726806, + 881804248, + 1589768608, + -11521517, + -156987261, + 160238415, + -105161292, + 42554184, + 737935, + -18406593, + 17725867, + -9942393, + 3093751, + 141280, + -686973, + 313383, + 29772, + 281185, + -1605331, + 4048754, + -5749772, + 2301416, + 11200744, + -35114560, + 59657117, + -63153289, + 16931496, + 106762850, + -343440887, + 927887512, + 1565876590, + -43404543, + -140846804, + 154874348, + -105997710, + 45721278, + -2233195, + -16659874, + 17141191, + -10002430, + 3324157, + -25739, + -617358, + 296699, + 40983, + 250332, + -1582577, + 4151767, + -6187691, + 3237282, + 9941859, + -34345926, + 60849660, + -67902413, + 25814013, + 95853866, + -338648730, + 973544850, + 1540060722, + -73823693, + -124571622, + 149012077, + -106394856, + 48640324, + -5130952, + -14886774, + 16501769, + -10019408, + 3532819, + -185973, + -548366, + 279559, + 53007, + 216344, + -1551451, + 4240285, + -6612989, + 4185612, + 8610222, + -33418306, + 61818777, + -72473788, + 34781922, + 84290231, + -332317724, + 1018673108, + 1512383628, + -102739180, + -108226579, + 142685294, + -106360086, + 51304690, + -7945178, + -13095163, + 15811655, + -9994495, + 3719553, + -338965, + -480302, + 262093, + 65821, + 179233, + -1511738, + 4313382, + -7023410, + 5142686, + 7209647, + -32331960, + 62555735, + -76845124, + 43800992, + 72101449, + -324419137, + 1063169605, + 1482912286, + -130115903, + -91875194, + 135928759, + -105902321, + 53708903, + -10666271, + -11292806, + 15075016, + -9929010, + 3884279, + -484309, + -413456, + 244424, + 79392, + 139025, + -1463257, + 4370168, + -7416693, + 6104649, + 5744332, + -31087821, + 63052578, + -80994491, + 52836072, + 59320082, + -314928258, + 1106932427, + 1451717827, + -155923493, + -75579451, + 128778154, + -105031976, + 55848651, + -13285217, + -9487334, + 14296106, + -9824405, + 4027016, + -621647, + -348095, + 226672, + 93681, + 95766, + -1405862, + 4409800, + -7790586, + 7067519, + 4218853, + -29687504, + 63302174, + -84900414, + 61851208, + 45981695, + -303824534, + 1149860724, + 1418875332, + -180136347, + -59399632, + 121269927, + -103760892, + 57720775, + -15793609, + -7686214, + 13479250, + -9682261, + 4147880, + -750674, + -284467, + 208948, + 108642, + 49522, + -1339444, + 4431485, + -8142855, + 8027203, + 2638152, + -28133313, + 63298262, + -88541966, + 70809769, + 32124798, + -291091693, + 1191854993, + 1384463599, + -202733642, + -43394140, + 113441140, + -102102259, + 59323257, + -18183673, + -5896723, + 12628824, + -9504274, + 4247082, + -871136, + -222803, + 191360, + 124220, + 377, + -1263936, + 4434483, + -8471295, + 8979514, + 1007527, + -26428248, + 63035498, + -91898866, + 79674576, + 17790762, + -276717852, + 1232817367, + 1348564923, + -223699340, + -27619344, + 105329315, + -100070542, + 60655209, + -20448287, + -4125920, + 11749229, + -9292246, + 4324919, + -982825, + -163309, + 174004, + 140354, + -51563, + -1179311, + 4418117, + -8773740, + 9920184, + -667385, + -24576009, + 62509492, + -94951578, + 88408038, + 3023742, + -260695619, + 1272651900, + 1311264844, + -243022174, + -12129430, + 96972284, + -97681395, + 61716852, + -22580991, + -2380623, + 10844881, + -9048074, + 4381776, + -1085587, + -106174, + 156974, + 156974, + -106174, + -1085587, + 4381776, + -9048074, + 10844881, + -2380623, + -22580991, + 61716852, + -97681395, + 96972284, + -12129430, + -243022174, + 1311264844, + 1272651900, + -260695619, + 3023742, + 88408038, + -94951578, + 62509492, + -24576009, + -667385, + 9920184, + -8773740, + 4418117, + -1179311, + -51563, + 140354, + 174004, + -163309, + -982825, + 4324919, + -9292246, + 11749229, + -4125920, + -20448287, + 60655209, + -100070542, + 105329315, + -27619344, + -223699340, + 1348564923, + 1232817367, + -276717852, + 17790762, + 79674576, + -91898866, + 63035498, + -26428248, + 1007527, + 8979514, + -8471295, + 4434483, + -1263936, + 377, + 124220, + 191360, + -222803, + -871136, + 4247082, + -9504274, + 12628824, + -5896723, + -18183673, + 59323257, + -102102259, + 113441140, + -43394140, + -202733642, + 1384463599, + 1191854993, + -291091693, + 32124798, + 70809769, + -88541966, + 63298262, + -28133313, + 2638152, + 8027203, + -8142855, + 4431485, + -1339444, + 49522, + 108642, + 208948, + -284467, + -750674, + 4147880, + -9682261, + 13479250, + -7686214, + -15793609, + 57720775, + -103760892, + 121269927, + -59399632, + -180136347, + 1418875332, + 1149860724, + -303824534, + 45981695, + 61851208, + -84900414, + 63302174, + -29687504, + 4218853, + 7067519, + -7790586, + 4409800, + -1405862, + 95766, + 93681, + 226672, + -348095, + -621647, + 4027016, + -9824405, + 14296106, + -9487334, + -13285217, + 55848651, + -105031976, + 128778154, + -75579451, + -155923493, + 1451717827, + 1106932427, + -314928258, + 59320082, + 52836072, + -80994491, + 63052578, + -31087821, + 5744332, + 6104649, + -7416693, + 4370168, + -1463257, + 139025, + 79392, + 244424, + -413456, + -484309, + 3884279, + -9929010, + 15075016, + -11292806, + -10666271, + 53708903, + -105902321, + 135928759, + -91875194, + -130115903, + 1482912286, + 1063169605, + -324419137, + 72101449, + 43800992, + -76845124, + 62555735, + -32331960, + 7209647, + 5142686, + -7023410, + 4313382, + -1511738, + 179233, + 65821, + 262093, + -480302, + -338965, + 3719553, + -9994495, + 15811655, + -13095163, + -7945178, + 51304690, + -106360086, + 142685294, + -108226579, + -102739180, + 1512383628, + 1018673108, + -332317724, + 84290231, + 34781922, + -72473788, + 61818777, + -33418306, + 8610222, + 4185612, + -6612989, + 4240285, + -1551451, + 216344, + 53007, + 279559, + -548366, + -185973, + 3532819, + -10019408, + 16501769, + -14886774, + -5130952, + 48640324, + -106394856, + 149012077, + -124571622, + -73823693, + 1540060722, + 973544850, + -338648730, + 95853866, + 25814013, + -67902413, + 60849660, + -34345926, + 9941859, + 3237282, + -6187691, + 4151767, + -1582577, + 250332, + 40983, + 296699, + -617358, + -25739, + 3324157, + -10002430, + 17141191, + -16659874, + -2233195, + 45721278, + -105997710, + 154874348, + -140846804, + -43404543, + 1565876590, + 927887512, + -343440887, + 106762850, + 16931496, + -63153289, + 59657117, + -35114560, + 11200744, + 2301416, + -5749772, + 4048754, + -1605331, + 281185, + 29772, + 313383, + -686973, + 141280, + 3093751, + -9942393, + 17725867, + -18406593, + 737935, + 42554184, + -105161292, + 160238415, + -156987261, + -11521517, + 1589768608, + 881804248, + -346726806, + 116990775, + 8167567, + -58248966, + 58250605, + -35724604, + 12383461, + 1381579, + -5301479, + 3932206, + -1619960, + 308912, + 19392, + 329476, + -756887, + 314573, + 2841890, + -9838282, + 18251873, + -20118987, + 3771751, + 39146828, + -103879865, + 165071815, + -172926975, + 21780976, + 1611678694, + 835398400, + -348542817, + 126514364, + -445718, + -53212164, + 56640253, + -36177097, + 13486989, + 481178, + -4845035, + 3803114, + -1626738, + 333535, + 9854, + 344840, + -826760, + 493584, + 2568969, + -9689249, + 18715437, + -21789073, + 6857076, + 35508147, + -102149371, + 169343456, + -188598972, + 56453983, + 1631553479, + 788773199, + -348928806, + 135313483, + -8877548, + -48065674, + 54836807, + -36473702, + 14508711, + -396555, + -4382632, + 3662487, + -1625966, + 355094, + 1164, + 359332, + -896234, + 677706, + 2275494, + -9494618, + 19112958, + -23408858, + 9982274, + 31648208, + -99967477, + 173023767, + -203935525, + 92444097, + 1649344465, + 742031480, + -347928035, + 143371150, + -17098447, + -42832270, + 52851573, + -36616687, + 15446413, + -1248571, + -3916423, + 3511355, + -1617971, + 373641, + -6681, + 372806, + -964940, + 866283, + 1962082, + -9253896, + 19441027, + -24970378, + 13135291, + 27578197, + -97333622, + 176084845, + -218868371, + 129693568, + 1665008170, + 695275392, + -345586960, + 150673532, + -25080366, + -37534618, + 50696361, + -36608899, + 16298283, + -2072008, + -3448511, + 3350756, + -1603098, + 389244, + -13688, + 385117, + -1032494, + 1058615, + 1629456, + -8966777, + 19696447, + -26465728, + 16303699, + 23310390, + -94249054, + 178500590, + -233328919, + 168140420, + 1678506261, + 648606117, + -341955039, + 157209927, + -32796760, + -32195184, + 48383425, + -36453743, + 17062912, + -2864206, + -2980946, + 3181739, + -1581712, + 401982, + -19869, + 396114, + -1098500, + 1253956, + 1278456, + -8633152, + 19876252, + -27887098, + 19474735, + 18858128, + -90716858, + 180246848, + -247248474, + 207718594, + 1689805663, + 602123593, + -337084529, + 162972740, + -40222662, + -26836152, + 45925405, + -36155154, + 17739290, + -3622705, + -2515712, + 3005352, + -1554196, + 411945, + -25242, + 405650, + -1162554, + 1451517, + 910029, + -8253112, + 19977723, + -29226810, + 22635353, + 14235780, + -86741985, + 181301539, + -260558461, + 248358090, + 1698878662, + 555926238, + -331030283, + 167957444, + -47334749, + -21479341, + 43335268, + -35717570, + 18326797, + -4345257, + -2054723, + 2822638, + -1520944, + 419236, + -29830, + 413574, + -1224241, + 1650470, + 525233, + -7826957, + 19998411, + -30477356, + 25772268, + 9458710, + -82331266, + 181644787, + -273190649, + 289985136, + 1705702986, + 510110684, + -323849537, + 172162536, + -54111400, + -16146122, + 40626247, + -35145903, + 18825202, + -5029827, + -1599817, + 2634636, + -1482364, + 423964, + -33657, + 419740, + -1283142, + 1849949, + 125233, + -7355195, + 19936152, + -31631426, + 28872008, + 4543230, + -77493423, + 181259037, + -285077381, + 332522364, + 1710261875, + 464771521, + -315601691, + 175589478, + -60532747, + -10857342, + 37811782, + -34445505, + 19234649, + -5674596, + -1152748, + 2442370, + -1438870, + 426249, + -36756, + 424001, + -1338832, + 2049052, + -288698, + -6838550, + 19789081, + -32681953, + 31920968, + -493446, + -72239071, + 180129175, + -296151802, + 375888993, + 1712544124, + 420001039, + -306348091, + 178242629, + -66580718, + -5633255, + 34905463, + -33622141, + 19555652, + -6277964, + -715184, + 2246846, + -1390884, + 426217, + -39160 + +}; + +static const struct src_stage src_int32_40_7_2976_5000 = { + 4, 23, 40, 28, 1120, 7, 40, 0, 0, + src_int32_40_7_2976_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_1_1134_5000.h b/src/audio/src/coef/src_ipc4_int32_4_1_1134_5000.h new file mode 100644 index 000000000000..417b633382a2 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_1_1134_5000.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_1_1134_5000_fir[64] = { + 165628, + 1977250, + -11171259, + 978678, + 66588346, + -99557752, + -135554939, + 743331382, + 1303528619, + 467876684, + -202592108, + -31949021, + 59109715, + -11059509, + -6095789, + 1887550, + 597342, + 908557, + -15277300, + 19403540, + 55892932, + -164584253, + 3708267, + 999002573, + 1196182439, + 211022284, + -206259032, + 22657062, + 40807995, + -16027219, + -1791180, + 1259814, + 1259814, + -1791180, + -16027219, + 40807995, + 22657062, + -206259032, + 211022284, + 1196182439, + 999002573, + 3708267, + -164584253, + 55892932, + 19403540, + -15277300, + 908557, + 597342, + 1887550, + -6095789, + -11059509, + 59109715, + -31949021, + -202592108, + 467876684, + 1303528619, + 743331382, + -135554939, + -99557752, + 66588346, + 978678, + -11171259, + 1977250, + 165628 + +}; + +static const struct src_stage src_int32_4_1_1134_5000 = { + 0, 1, 4, 16, 64, 1, 4, 0, 0, + src_int32_4_1_1134_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_1_1512_5000.h b/src/audio/src/coef/src_ipc4_int32_4_1_1512_5000.h new file mode 100644 index 000000000000..081ecf7c2738 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_1_1512_5000.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_1_1512_5000_fir[64] = { + -77852, + 2381370, + -5140518, + -14811384, + 66942512, + -55465379, + -188000604, + 727933982, + 1381923084, + 419024837, + -227551144, + 12955701, + 45765868, + -19469262, + -262975, + 1369603, + 51317, + 2987573, + -11496050, + -1310550, + 73822740, + -134312252, + -65038437, + 1022871309, + 1254512989, + 143038517, + -200910161, + 57295291, + 20345597, + -17291791, + 2364387, + 518981, + 518981, + 2364387, + -17291791, + 20345597, + 57295291, + -200910161, + 143038517, + 1254512989, + 1022871309, + -65038437, + -134312252, + 73822740, + -1310550, + -11496050, + 2987573, + 51317, + 1369603, + -262975, + -19469262, + 45765868, + 12955701, + -227551144, + 419024837, + 1381923084, + 727933982, + -188000604, + -55465379, + 66942512, + -14811384, + -5140518, + 2381370, + -77852 + +}; + +static const struct src_stage src_int32_4_1_1512_5000 = { + 0, 1, 4, 16, 64, 1, 4, 0, 0, + src_int32_4_1_1512_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_1_2268_5000.h b/src/audio/src/coef/src_ipc4_int32_4_1_2268_5000.h new file mode 100644 index 000000000000..36e75377cceb --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_1_2268_5000.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_1_2268_5000_fir[80] = { + -79074, + 1261923, + -3505225, + 134551, + 20007489, + -52100361, + 52595384, + 47528502, + -288611016, + 690221989, + 1538628396, + 313597850, + -266863194, + 111657573, + 555592, + -34063205, + 21918363, + -5138234, + -1018364, + 780184, + 4793, + 1370660, + -5922392, + 8209720, + 8710279, + -55744859, + 101567607, + -56713690, + -204307161, + 1066098953, + 1369361423, + 1028111, + -174827784, + 127158385, + -38305258, + -10992658, + 16704845, + -6925322, + 686148, + 296371, + 296371, + 686148, + -6925322, + 16704845, + -10992658, + -38305258, + 127158385, + -174827784, + 1028111, + 1369361423, + 1066098953, + -204307161, + -56713690, + 101567607, + -55744859, + 8710279, + 8209720, + -5922392, + 1370660, + 4793, + 780184, + -1018364, + -5138234, + 21918363, + -34063205, + 555592, + 111657573, + -266863194, + 313597850, + 1538628396, + 690221989, + -288611016, + 47528502, + 52595384, + -52100361, + 20007489, + 134551, + -3505225, + 1261923, + -79074 + +}; + +static const struct src_stage src_int32_4_1_2268_5000 = { + 0, 1, 4, 20, 80, 1, 4, 0, 0, + src_int32_4_1_2268_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_1_3401_5000.h b/src/audio/src/coef/src_ipc4_int32_4_1_3401_5000.h new file mode 100644 index 000000000000..850a923205be --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_1_3401_5000.h @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_1_3401_5000_fir[144] = { + -6865, + 234410, + -916679, + 2089314, + -3289124, + 3374037, + -714769, + -6096148, + 17124328, + -29974467, + 39274091, + -37278552, + 15707980, + 31703226, + -107136821, + 209107855, + -340768703, + 572688133, + 1771256666, + 102715267, + -191004549, + 181011265, + -135967381, + 81093928, + -32110808, + -2348043, + 20148385, + -24086906, + 19483102, + -11768526, + 4834208, + -461556, + -1321405, + 1416940, + -855545, + 320335, + 104772, + -57833, + -491588, + 1910568, + -4204104, + 6582624, + -7246427, + 3699398, + 6252553, + -22987157, + 43559310, + -60904805, + 64275218, + -40793732, + -23167772, + 144955605, + -372356238, + 1085537075, + 1521266396, + -228016089, + -3969993, + 88070338, + -107184976, + 91418514, + -60448310, + 28458177, + -4049351, + -9660080, + 13809725, + -11817164, + 7407345, + -3283250, + 675936, + 387949, + -485772, + 243808, + 243808, + -485772, + 387949, + 675936, + -3283250, + 7407345, + -11817164, + 13809725, + -9660080, + -4049351, + 28458177, + -60448310, + 91418514, + -107184976, + 88070338, + -3969993, + -228016089, + 1521266396, + 1085537075, + -372356238, + 144955605, + -23167772, + -40793732, + 64275218, + -60904805, + 43559310, + -22987157, + 6252553, + 3699398, + -7246427, + 6582624, + -4204104, + 1910568, + -491588, + -57833, + 104772, + 320335, + -855545, + 1416940, + -1321405, + -461556, + 4834208, + -11768526, + 19483102, + -24086906, + 20148385, + -2348043, + -32110808, + 81093928, + -135967381, + 181011265, + -191004549, + 102715267, + 1771256666, + 572688133, + -340768703, + 209107855, + -107136821, + 31703226, + 15707980, + -37278552, + 39274091, + -29974467, + 17124328, + -6096148, + -714769, + 3374037, + -3289124, + 2089314, + -916679, + 234410, + -6865 + +}; + +static const struct src_stage src_int32_4_1_3401_5000 = { + 0, 1, 4, 36, 144, 1, 4, 0, 0, + src_int32_4_1_3401_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_1_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_4_1_4535_5000.h new file mode 100644 index 000000000000..b422972b5d13 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_1_4535_5000.h @@ -0,0 +1,434 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_1_4535_5000_fir[416] = { + -49159, + 81297, + -120482, + 165198, + -212712, + 258912, + -298194, + 323434, + -326060, + 296230, + -223152, + 95517, + 97921, + -367644, + 722575, + -1169180, + 1710545, + -2345423, + 3067336, + -3863753, + 4715409, + -5595821, + 6471023, + -7299594, + 8032982, + -8616152, + 8988572, + -9085506, + 8839609, + -8182747, + 7048019, + -5371857, + 3096140, + -170192, + -3447457, + 7787689, + -12869966, + 18702234, + -25281807, + 32597577, + -40634031, + 49377920, + -58829000, + 69017599, + -80034509, + 92085181, + -105596566, + 121451625, + -141581589, + 170786684, + -224371506, + 388113472, + 2000103495, + -137354110, + 26311862, + 13742473, + -33743701, + 44896568, + -51124857, + 54193457, + -55046230, + 54262274, + -52239879, + 49279385, + -45623305, + 41476541, + -37016696, + 32399221, + -27759841, + 23215588, + -18865200, + 14789333, + -11050851, + 7695331, + -4751878, + 2234247, + -142271, + -1536453, + 2824675, + -3753484, + 4360232, + -4686488, + 4776085, + -4673310, + 4421310, + -4060736, + 3628660, + -3157774, + 2675870, + -2205592, + 1764426, + -1364915, + 1015042, + -718753, + 476569, + -286252, + 143481, + -42510, + -23231, + 60600, + -76304, + 76548, + -66784, + 51563, + -36825, + 68339, + -112973, + 172247, + -246844, + 336285, + -438599, + 550016, + -664708, + 774604, + -869303, + 936115, + -960251, + 925172, + -813117, + 605803, + -285299, + -164951, + 758979, + -1507055, + 2414401, + -3479914, + 4694958, + -6042276, + 7495080, + -9016387, + 10558627, + -12063583, + 13462655, + -14677475, + 15620833, + -16197883, + 16307537, + -15843947, + 14697913, + -12758010, + 9911152, + -6042187, + 1031966, + 5246983, + -12938552, + 22217250, + -33312659, + 46552118, + -62437842, + 81794208, + -106071725, + 138043847, + -183654047, + 258079043, + -414168091, + 1043866669, + 1643080120, + -411113679, + 211084500, + -126295363, + 78252766, + -46925819, + 24877590, + -8712605, + -3348543, + 12341905, + -18927368, + 23561067, + -26582953, + 28263720, + -28830789, + 28482855, + -27397891, + 25737351, + -23648111, + 21263133, + -18701445, + 16067826, + -13452479, + 10930835, + -8563595, + 6397080, + -4463875, + 2783783, + -1365035, + 205715, + 704656, + -1383461, + 1853287, + -2140276, + 2272571, + -2278905, + 2187370, + -2024398, + 1813971, + -1577049, + 1331229, + -1090602, + 865801, + -664189, + 490184, + -345654, + 230379, + -142523, + 79103, + -36434, + 10510, + 2664, + 2664, + 10510, + -36434, + 79103, + -142523, + 230379, + -345654, + 490184, + -664189, + 865801, + -1090602, + 1331229, + -1577049, + 1813971, + -2024398, + 2187370, + -2278905, + 2272571, + -2140276, + 1853287, + -1383461, + 704656, + 205715, + -1365035, + 2783783, + -4463875, + 6397080, + -8563595, + 10930835, + -13452479, + 16067826, + -18701445, + 21263133, + -23648111, + 25737351, + -27397891, + 28482855, + -28830789, + 28263720, + -26582953, + 23561067, + -18927368, + 12341905, + -3348543, + -8712605, + 24877590, + -46925819, + 78252766, + -126295363, + 211084500, + -411113679, + 1643080120, + 1043866669, + -414168091, + 258079043, + -183654047, + 138043847, + -106071725, + 81794208, + -62437842, + 46552118, + -33312659, + 22217250, + -12938552, + 5246983, + 1031966, + -6042187, + 9911152, + -12758010, + 14697913, + -15843947, + 16307537, + -16197883, + 15620833, + -14677475, + 13462655, + -12063583, + 10558627, + -9016387, + 7495080, + -6042276, + 4694958, + -3479914, + 2414401, + -1507055, + 758979, + -164951, + -285299, + 605803, + -813117, + 925172, + -960251, + 936115, + -869303, + 774604, + -664708, + 550016, + -438599, + 336285, + -246844, + 172247, + -112973, + 68339, + -36825, + 51563, + -66784, + 76548, + -76304, + 60600, + -23231, + -42510, + 143481, + -286252, + 476569, + -718753, + 1015042, + -1364915, + 1764426, + -2205592, + 2675870, + -3157774, + 3628660, + -4060736, + 4421310, + -4673310, + 4776085, + -4686488, + 4360232, + -3753484, + 2824675, + -1536453, + -142271, + 2234247, + -4751878, + 7695331, + -11050851, + 14789333, + -18865200, + 23215588, + -27759841, + 32399221, + -37016696, + 41476541, + -45623305, + 49279385, + -52239879, + 54262274, + -55046230, + 54193457, + -51124857, + 44896568, + -33743701, + 13742473, + 26311862, + -137354110, + 2000103495, + 388113472, + -224371506, + 170786684, + -141581589, + 121451625, + -105596566, + 92085181, + -80034509, + 69017599, + -58829000, + 49377920, + -40634031, + 32597577, + -25281807, + 18702234, + -12869966, + 7787689, + -3447457, + -170192, + 3096140, + -5371857, + 7048019, + -8182747, + 8839609, + -9085506, + 8988572, + -8616152, + 8032982, + -7299594, + 6471023, + -5595821, + 4715409, + -3863753, + 3067336, + -2345423, + 1710545, + -1169180, + 722575, + -367644, + 97921, + 95517, + -223152, + 296230, + -326060, + 323434, + -298194, + 258912, + -212712, + 165198, + -120482, + 81297, + -49159 + +}; + +static const struct src_stage src_int32_4_1_4535_5000 = { + 0, 1, 4, 104, 416, 1, 4, 0, 0, + src_int32_4_1_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_21_1080_5000.h b/src/audio/src/coef/src_ipc4_int32_4_21_1080_5000.h new file mode 100644 index 000000000000..b175e8efba70 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_21_1080_5000.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_21_1080_5000_fir[224] = { + -1944411, + -1843091, + 94714, + 4668622, + 12207509, + 22202223, + 33034868, + 41920123, + 45151979, + 38696348, + 19092958, + -15456674, + -64014922, + -122092904, + -181338242, + -229912143, + -253633193, + -237820790, + -169618088, + -40444455, + 151848530, + 401543509, + 694688248, + 1009974305, + 1320838837, + 1598545503, + 1815811874, + 1950431567, + 1988315574, + 1925457025, + 1768494391, + 1533779417, + 1245104751, + 930466103, + 618383980, + 334364343, + 98028373, + -78698070, + -192144835, + -246237798, + -250847922, + -219519789, + -167013375, + -107072544, + -50741721, + -5413513, + 25363754, + 41427396, + 45096582, + 40072669, + 30381635, + 19541336, + 10055235, + 3248379, + -610747, + -2004377, + -2040287, + -1566527, + 967220, + 6278328, + 14518825, + 24921382, + 35571113, + 43416048, + 44599233, + 35135448, + 11874496, + -26393041, + -77902424, + -137203754, + -195008047, + -238753953, + -253938809, + -226108319, + -143248778, + 1793226, + 209297343, + 471475011, + 772402653, + 1089217138, + 1394493456, + 1659508904, + 1857923595, + 1969309976, + 1981966201, + 1894552668, + 1716280420, + 1465620039, + 1167745449, + 851132847, + 543863051, + 270203806, + 47974925, + -112958965, + -210932537, + -251544073, + -245810731, + -207809120, + -152237523, + -92296143, + -38175382, + 3703392, + 30702706, + 43377074, + 44496434, + 37936219, + 27661754, + 16971028, + 8075691, + 2016077, + -1160299, + -2065158, + -2065158, + -1160299, + 2016077, + 8075691, + 16971028, + 27661754, + 37936219, + 44496434, + 43377074, + 30702706, + 3703392, + -38175382, + -92296143, + -152237523, + -207809120, + -245810731, + -251544073, + -210932537, + -112958965, + 47974925, + 270203806, + 543863051, + 851132847, + 1167745449, + 1465620039, + 1716280420, + 1894552668, + 1981966201, + 1969309976, + 1857923595, + 1659508904, + 1394493456, + 1089217138, + 772402653, + 471475011, + 209297343, + 1793226, + -143248778, + -226108319, + -253938809, + -238753953, + -195008047, + -137203754, + -77902424, + -26393041, + 11874496, + 35135448, + 44599233, + 43416048, + 35571113, + 24921382, + 14518825, + 6278328, + 967220, + -1566527, + -2040287, + -2004377, + -610747, + 3248379, + 10055235, + 19541336, + 30381635, + 40072669, + 45096582, + 41427396, + 25363754, + -5413513, + -50741721, + -107072544, + -167013375, + -219519789, + -250847922, + -246237798, + -192144835, + -78698070, + 98028373, + 334364343, + 618383980, + 930466103, + 1245104751, + 1533779417, + 1768494391, + 1925457025, + 1988315574, + 1950431567, + 1815811874, + 1598545503, + 1320838837, + 1009974305, + 694688248, + 401543509, + 151848530, + -40444455, + -169618088, + -237820790, + -253633193, + -229912143, + -181338242, + -122092904, + -64014922, + -15456674, + 19092958, + 38696348, + 45151979, + 41920123, + 33034868, + 22202223, + 12207509, + 4668622, + 94714, + -1843091, + -1944411 + +}; + +static const struct src_stage src_int32_4_21_1080_5000 = { + 5, 1, 4, 56, 224, 21, 4, 0, 3, + src_int32_4_21_1080_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_21_3239_5000.h b/src/audio/src/coef/src_ipc4_int32_4_21_3239_5000.h new file mode 100644 index 000000000000..3085264b8bc6 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_21_3239_5000.h @@ -0,0 +1,530 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_21_3239_5000_fir[512] = { + 27727, + -202088, + -526392, + -850753, + -1033553, + -925361, + -425682, + 459217, + 1578854, + 2641561, + 3269126, + 3098917, + 1911667, + -251521, + -3025148, + -5743530, + -7568141, + -7703092, + -5651937, + -1445024, + 4240047, + 10126255, + 14576095, + 15991067, + 13286371, + 6315710, + -3888821, + -15168484, + -24623002, + -29281807, + -26923176, + -16835934, + -298659, + 19407853, + 37539513, + 48924517, + 49294497, + 36596528, + 11926502, + -20229233, + -52619170, + -76689095, + -84625567, + -71533721, + -37202869, + 13058342, + 68870261, + 116591178, + 142234266, + 134933456, + 90194731, + 12128063, + -85996690, + -183207025, + -254205443, + -274127506, + -223779357, + -94269621, + 110002192, + 370756690, + 657935061, + 934225216, + 1161228122, + 1306106430, + 1347421227, + 1278998403, + 1111049041, + 868318061, + 585633942, + 301750464, + 52698071, + -134069948, + -243652155, + -275129739, + -240329916, + -160341052, + -60626026, + 34193648, + 104823566, + 140227815, + 138573742, + 106210472, + 55111547, + -507031, + -47581448, + -76881637, + -84490632, + -71912572, + -44963160, + -11848935, + 19026282, + 40995201, + 50395565, + 46972710, + 33441764, + 14426801, + -4889358, + -20048403, + -28241331, + -28708798, + -22599262, + -12399208, + -1135775, + 8422688, + 14375949, + 15994378, + 13690792, + 8722548, + 2741380, + -2673084, + -6378663, + -7862418, + -7242422, + -5113797, + -2306623, + 366458, + 2306895, + 3231920, + 3174298, + 2401246, + 1290802, + 207498, + -589251, + -986600, + -1009660, + -776885, + -440613, + -133438, + -18037, + -276961, + -612423, + -915824, + -1039022, + -839119, + -237305, + 726332, + 1863803, + 2854621, + 3313387, + 2901044, + 1453800, + -909187, + -3741123, + -6317223, + -7786776, + -7404493, + -4787203, + -121525, + 5753153, + 11440051, + 15269180, + 15725573, + 11924222, + 4000891, + -6712877, + -17824134, + -26343319, + -29408666, + -25111958, + -13210193, + 4497597, + 24292767, + 41211178, + 50176820, + 47360849, + 31432469, + 4344803, + -28630923, + -59751659, + -80442760, + -83422746, + -64830566, + -25802974, + 26987305, + 82125347, + 125576648, + 143804014, + 127256107, + 73436837, + -11230042, + -111332245, + -204432966, + -264860616, + -268681997, + -198892475, + -49727108, + 170895607, + 441450914, + 729561298, + 997024227, + 1206217456, + 1326665385, + 1340480652, + 1245597281, + 1056145744, + 799894346, + 513271691, + 234964311, + -650300, + -168976121, + -258579692, + -271943492, + -223608505, + -136246795, + -35588370, + 54705728, + 117204556, + 143165065, + 132965892, + 94647840, + 41076463, + -13518869, + -56822282, + -80846575, + -83072420, + -66225991, + -36921066, + -3617502, + 25554165, + 44591142, + 50680270, + 44379639, + 28998585, + 9430705, + -9211833, + -22815121, + -29067045, + -27718043, + -20317227, + -9564864, + 1506265, + 10298405, + 15188843, + 15748340, + 12637013, + 7255955, + 1280386, + -3791139, + -6963342, + -7887872, + -6821261, + -4441778, + -1597589, + 937036, + 2637066, + 3302335, + 3034215, + 2139933, + 1004993, + -25563, + -727161, + -1023981, + -969616, + -696659, + -356929, + -71882, + -71882, + -356929, + -696659, + -969616, + -1023981, + -727161, + -25563, + 1004993, + 2139933, + 3034215, + 3302335, + 2637066, + 937036, + -1597589, + -4441778, + -6821261, + -7887872, + -6963342, + -3791139, + 1280386, + 7255955, + 12637013, + 15748340, + 15188843, + 10298405, + 1506265, + -9564864, + -20317227, + -27718043, + -29067045, + -22815121, + -9211833, + 9430705, + 28998585, + 44379639, + 50680270, + 44591142, + 25554165, + -3617502, + -36921066, + -66225991, + -83072420, + -80846575, + -56822282, + -13518869, + 41076463, + 94647840, + 132965892, + 143165065, + 117204556, + 54705728, + -35588370, + -136246795, + -223608505, + -271943492, + -258579692, + -168976121, + -650300, + 234964311, + 513271691, + 799894346, + 1056145744, + 1245597281, + 1340480652, + 1326665385, + 1206217456, + 997024227, + 729561298, + 441450914, + 170895607, + -49727108, + -198892475, + -268681997, + -264860616, + -204432966, + -111332245, + -11230042, + 73436837, + 127256107, + 143804014, + 125576648, + 82125347, + 26987305, + -25802974, + -64830566, + -83422746, + -80442760, + -59751659, + -28630923, + 4344803, + 31432469, + 47360849, + 50176820, + 41211178, + 24292767, + 4497597, + -13210193, + -25111958, + -29408666, + -26343319, + -17824134, + -6712877, + 4000891, + 11924222, + 15725573, + 15269180, + 11440051, + 5753153, + -121525, + -4787203, + -7404493, + -7786776, + -6317223, + -3741123, + -909187, + 1453800, + 2901044, + 3313387, + 2854621, + 1863803, + 726332, + -237305, + -839119, + -1039022, + -915824, + -612423, + -276961, + -18037, + -133438, + -440613, + -776885, + -1009660, + -986600, + -589251, + 207498, + 1290802, + 2401246, + 3174298, + 3231920, + 2306895, + 366458, + -2306623, + -5113797, + -7242422, + -7862418, + -6378663, + -2673084, + 2741380, + 8722548, + 13690792, + 15994378, + 14375949, + 8422688, + -1135775, + -12399208, + -22599262, + -28708798, + -28241331, + -20048403, + -4889358, + 14426801, + 33441764, + 46972710, + 50395565, + 40995201, + 19026282, + -11848935, + -44963160, + -71912572, + -84490632, + -76881637, + -47581448, + -507031, + 55111547, + 106210472, + 138573742, + 140227815, + 104823566, + 34193648, + -60626026, + -160341052, + -240329916, + -275129739, + -243652155, + -134069948, + 52698071, + 301750464, + 585633942, + 868318061, + 1111049041, + 1278998403, + 1347421227, + 1306106430, + 1161228122, + 934225216, + 657935061, + 370756690, + 110002192, + -94269621, + -223779357, + -274127506, + -254205443, + -183207025, + -85996690, + 12128063, + 90194731, + 134933456, + 142234266, + 116591178, + 68870261, + 13058342, + -37202869, + -71533721, + -84625567, + -76689095, + -52619170, + -20229233, + 11926502, + 36596528, + 49294497, + 48924517, + 37539513, + 19407853, + -298659, + -16835934, + -26923176, + -29281807, + -24623002, + -15168484, + -3888821, + 6315710, + 13286371, + 15991067, + 14576095, + 10126255, + 4240047, + -1445024, + -5651937, + -7703092, + -7568141, + -5743530, + -3025148, + -251521, + 1911667, + 3098917, + 3269126, + 2641561, + 1578854, + 459217, + -425682, + -925361, + -1033553, + -850753, + -526392, + -202088, + 27727 + +}; + +static const struct src_stage src_int32_4_21_3239_5000 = { + 5, 1, 4, 128, 512, 21, 4, 0, 2, + src_int32_4_21_3239_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_4_3_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_4_3_4535_5000.h new file mode 100644 index 000000000000..752e2a801180 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_4_3_4535_5000.h @@ -0,0 +1,450 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_3_4535_5000_fir[432] = { + -38206, + 66050, + -102182, + 146325, + -197265, + 252639, + -308765, + 360513, + -401250, + 422865, + -415908, + 369835, + -273383, + 115067, + 116198, + -430372, + 835469, + -1336677, + 1935457, + -2628642, + 3407603, + -4257518, + 5156792, + -6076676, + 6981126, + -7826934, + 8564161, + -9136872, + 9484191, + -9541637, + 9242735, + -8520828, + 7311039, + -5552309, + 3189400, + -174768, + -3529813, + 7952029, + -13108341, + 19004042, + -25634269, + 32986327, + -41043794, + 49793232, + -59234948, + 69400535, + -80382707, + 92389391, + -105850452, + 121652045, + -141728714, + 170883938, + -224425307, + 388132588, + 2000098159, + -137365631, + 26319995, + 13751732, + -33783471, + 44978515, + -51258570, + 54385918, + -55301412, + 54580890, + -52619300, + 49713722, + -46103656, + 41991393, + -37552445, + 32940796, + -28291393, + 23721210, + -19329637, + 15198656, + -11393050, + 7960813, + -4933835, + 2328890, + -148918, + -1615435, + 2984066, + -3985523, + 4655038, + -5032554, + 5160817, + -5083596, + 4844071, + -4483449, + 4039818, + -3547275, + 3035309, + -2528457, + 2046193, + -1603044, + 1208880, + -869360, + 586484, + -359206, + 184090, + -55956, + -31510, + 85195, + -112085, + 118865, + -111622, + 95633, + -75252, + 53857, + -19220, + 40573, + -73337, + 119719, + -181488, + 259684, + -354305, + 463983, + -585685, + 714434, + -843106, + 962300, + -1060323, + 1123308, + -1135477, + 1079566, + -937419, + 690743, + -322021, + -184451, + 841409, + -1657417, + 2635630, + -3772589, + 5057107, + -6469288, + 7979741, + -9549036, + 11127445, + -12654986, + 14061800, + -15268835, + 16188837, + -16727571, + 16785213, + -16257787, + 15038499, + -13018764, + 10088638, + -6136271, + 1045816, + 5307057, + -13063414, + 22395392, + -33530782, + 46795800, + -62692265, + 82044908, + -106305322, + 138248718, + -183820903, + 258201358, + -414242283, + 1043890982, + 1643089953, + -411165960, + 211166228, + -126394722, + 78356600, + -47020105, + 24948134, + -8745787, + -3365052, + 12418485, + -19071889, + 23778462, + -26874930, + 28628643, + -29263724, + 28975770, + -27940015, + 26315652, + -24247882, + 21868644, + -19296632, + 16636985, + -13980922, + 11405483, + -8973484, + 6733745, + -4721619, + 2959798, + -1459396, + 221242, + 762658, + -1507547, + 2034306, + -2367848, + 2535591, + -2566044, + 2487550, + -2327223, + 2110084, + -1858419, + 1591349, + -1324598, + 1070451, + -837869, + 632734, + -458199, + 315099, + -202402, + 117671, + -57508, + 17964, + 5109, + -15758, + 17704, + 17704, + -15758, + 5109, + 17964, + -57508, + 117671, + -202402, + 315099, + -458199, + 632734, + -837869, + 1070451, + -1324598, + 1591349, + -1858419, + 2110084, + -2327223, + 2487550, + -2566044, + 2535591, + -2367848, + 2034306, + -1507547, + 762658, + 221242, + -1459396, + 2959798, + -4721619, + 6733745, + -8973484, + 11405483, + -13980922, + 16636985, + -19296632, + 21868644, + -24247882, + 26315652, + -27940015, + 28975770, + -29263724, + 28628643, + -26874930, + 23778462, + -19071889, + 12418485, + -3365052, + -8745787, + 24948134, + -47020105, + 78356600, + -126394722, + 211166228, + -411165960, + 1643089953, + 1043890982, + -414242283, + 258201358, + -183820903, + 138248718, + -106305322, + 82044908, + -62692265, + 46795800, + -33530782, + 22395392, + -13063414, + 5307057, + 1045816, + -6136271, + 10088638, + -13018764, + 15038499, + -16257787, + 16785213, + -16727571, + 16188837, + -15268835, + 14061800, + -12654986, + 11127445, + -9549036, + 7979741, + -6469288, + 5057107, + -3772589, + 2635630, + -1657417, + 841409, + -184451, + -322021, + 690743, + -937419, + 1079566, + -1135477, + 1123308, + -1060323, + 962300, + -843106, + 714434, + -585685, + 463983, + -354305, + 259684, + -181488, + 119719, + -73337, + 40573, + -19220, + 53857, + -75252, + 95633, + -111622, + 118865, + -112085, + 85195, + -31510, + -55956, + 184090, + -359206, + 586484, + -869360, + 1208880, + -1603044, + 2046193, + -2528457, + 3035309, + -3547275, + 4039818, + -4483449, + 4844071, + -5083596, + 5160817, + -5032554, + 4655038, + -3985523, + 2984066, + -1615435, + -148918, + 2328890, + -4933835, + 7960813, + -11393050, + 15198656, + -19329637, + 23721210, + -28291393, + 32940796, + -37552445, + 41991393, + -46103656, + 49713722, + -52619300, + 54580890, + -55301412, + 54385918, + -51258570, + 44978515, + -33783471, + 13751732, + 26319995, + -137365631, + 2000098159, + 388132588, + -224425307, + 170883938, + -141728714, + 121652045, + -105850452, + 92389391, + -80382707, + 69400535, + -59234948, + 49793232, + -41043794, + 32986327, + -25634269, + 19004042, + -13108341, + 7952029, + -3529813, + -174768, + 3189400, + -5552309, + 7311039, + -8520828, + 9242735, + -9541637, + 9484191, + -9136872, + 8564161, + -7826934, + 6981126, + -6076676, + 5156792, + -4257518, + 3407603, + -2628642, + 1935457, + -1336677, + 835469, + -430372, + 116198, + 115067, + -273383, + 369835, + -415908, + 422865, + -401250, + 360513, + -308765, + 252639, + -197265, + 146325, + -102182, + 66050, + -38206 + +}; + +static const struct src_stage src_int32_4_3_4535_5000 = { + 2, 3, 4, 108, 432, 3, 4, 0, 0, + src_int32_4_3_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_5_21_1728_5000.h b/src/audio/src/coef/src_ipc4_int32_5_21_1728_5000.h new file mode 100644 index 000000000000..ad1d42e2dec3 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_5_21_1728_5000.h @@ -0,0 +1,338 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_5_21_1728_5000_fir[320] = { + -201787, + 180377, + 1173676, + 2702857, + 4273125, + 4970871, + 3693891, + -391824, + -7284640, + -15687358, + -22913624, + -25359411, + -19570865, + -3702207, + 21073359, + 49765759, + 73897693, + 83216416, + 68619193, + 25653732, + -42404918, + -122999925, + -195115531, + -232762667, + -210651028, + -110833748, + 71364647, + 323857559, + 617990238, + 912780652, + 1162501965, + 1325952915, + 1375217959, + 1301755658, + 1118281917, + 855969642, + 557675559, + 268894937, + 28662678, + -137467013, + -220874092, + -229267960, + -182587428, + -106785446, + -27253493, + 36489043, + 73760467, + 83019189, + 69923448, + 44080305, + 15588934, + -7678686, + -21511470, + -25431817, + -21729281, + -13996904, + -5722884, + 666419, + 4155707, + 4954437, + 3994721, + 2371255, + 924345, + 58628, + -167207, + 327451, + 1445850, + 3037546, + 4517335, + 4907512, + 3117009, + -1566656, + -8911489, + -17333960, + -23906448, + -24952475, + -17217133, + 643256, + 26726230, + 55275022, + 77275998, + 82441953, + 62317803, + 13783947, + -58086045, + -138892119, + -206263104, + -233843223, + -197276207, + -80849980, + 116933201, + 380526699, + 678347162, + 967774197, + 1203227510, + 1345518888, + 1370238779, + 1273097132, + 1070869944, + 797710901, + 497763015, + 215918965, + -11019211, + -160737586, + -228056574, + -223550891, + -168896838, + -90441604, + -12763102, + 46235278, + 77757627, + 81915073, + 65438073, + 38296626, + 10325777, + -11265369, + -23046512, + -25195171, + -20384288, + -12288456, + -4241268, + 1604607, + 4507568, + 4867213, + 3690689, + 2048206, + 699592, + -38870, + -113565, + 500480, + 1738423, + 3369121, + 4718422, + 4755753, + 2421314, + -2852441, + -10586005, + -18909218, + -24677016, + -24188111, + -14447698, + 5330486, + 32488772, + 60526955, + 79975231, + 80638542, + 54853057, + 949777, + -74151289, + -154260554, + -215812952, + -232329774, + -180660334, + -47555704, + 165187248, + 438601600, + 738378391, + 1020587920, + 1240177948, + 1360315684, + 1360315684, + 1240177948, + 1020587920, + 738378391, + 438601600, + 165187248, + -47555704, + -180660334, + -232329774, + -215812952, + -154260554, + -74151289, + 949777, + 54853057, + 80638542, + 79975231, + 60526955, + 32488772, + 5330486, + -14447698, + -24188111, + -24677016, + -18909218, + -10586005, + -2852441, + 2421314, + 4755753, + 4718422, + 3369121, + 1738423, + 500480, + -113565, + -38870, + 699592, + 2048206, + 3690689, + 4867213, + 4507568, + 1604607, + -4241268, + -12288456, + -20384288, + -25195171, + -23046512, + -11265369, + 10325777, + 38296626, + 65438073, + 81915073, + 77757627, + 46235278, + -12763102, + -90441604, + -168896838, + -223550891, + -228056574, + -160737586, + -11019211, + 215918965, + 497763015, + 797710901, + 1070869944, + 1273097132, + 1370238779, + 1345518888, + 1203227510, + 967774197, + 678347162, + 380526699, + 116933201, + -80849980, + -197276207, + -233843223, + -206263104, + -138892119, + -58086045, + 13783947, + 62317803, + 82441953, + 77275998, + 55275022, + 26726230, + 643256, + -17217133, + -24952475, + -23906448, + -17333960, + -8911489, + -1566656, + 3117009, + 4907512, + 4517335, + 3037546, + 1445850, + 327451, + -167207, + 58628, + 924345, + 2371255, + 3994721, + 4954437, + 4155707, + 666419, + -5722884, + -13996904, + -21729281, + -25431817, + -21511470, + -7678686, + 15588934, + 44080305, + 69923448, + 83019189, + 73760467, + 36489043, + -27253493, + -106785446, + -182587428, + -229267960, + -220874092, + -137467013, + 28662678, + 268894937, + 557675559, + 855969642, + 1118281917, + 1301755658, + 1375217959, + 1325952915, + 1162501965, + 912780652, + 617990238, + 323857559, + 71364647, + -110833748, + -210651028, + -232762667, + -195115531, + -122999925, + -42404918, + 25653732, + 68619193, + 83216416, + 73897693, + 49765759, + 21073359, + -3702207, + -19570865, + -25359411, + -22913624, + -15687358, + -7284640, + -391824, + 3693891, + 4970871, + 4273125, + 2702857, + 1173676, + 180377, + -201787 + +}; + +static const struct src_stage src_int32_5_21_1728_5000 = { + 4, 1, 5, 64, 320, 21, 5, 0, 2, + src_int32_5_21_1728_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_5_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_5_21_4535_5000.h new file mode 100644 index 000000000000..b81b50a4dbf2 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_5_21_4535_5000.h @@ -0,0 +1,1758 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_5_21_4535_5000_fir[1740] = { + -236856, + -188323, + -23805, + 189688, + 343360, + 340165, + 151745, + -153052, + -429126, + -522093, + -351473, + 33436, + 460028, + 707035, + 616631, + 188400, + -398277, + -855295, + -924641, + -519383, + 208299, + 917485, + 1235102, + 948445, + 135954, + -840081, + -1490820, + -1442262, + -643145, + 573341, + 1622008, + 1943471, + 1297279, + -80927, + -1553773, + -2372315, + -2052349, + -649895, + 1216551, + 2632292, + 2830201, + 1598904, + -558599, + -2619958, + -3522760, + -2706060, + -440843, + 2238386, + 3999303, + 3868716, + 1759495, + -1413187, + -4118908, + -4944286, + -3323074, + 109386, + 3747495, + 5759187, + 5001382, + 1653015, + -2778107, + -6124240, + -6611083, + -3787189, + 1152375, + 5855814, + 7926224, + 6133720, + 1119412, + -4801137, + -8696722, + -8462920, + -3942533, + 2865362, + 8674061, + 10486551, + 7129189, + -37318, + -7642381, + -11879309, + -10399430, + -3589449, + 5452196, + 12309285, + 13393303, + 7803739, + -2053189, + -11475433, + -15694807, + -12274812, + -2477864, + 9148915, + 16866934, + 16563622, + 7918022, + -5214349, + -16495680, + -20148049, + -13891451, + -293571, + 14239665, + 22461532, + 19877599, + 7162624, + -9880945, + -22942968, + -25235471, + -14988829, + 3372008, + 21094273, + 29243581, + 23178429, + 5126123, + -16540836, + -31153365, + -30967558, + -15219179, + 9089375, + 30252163, + 37459127, + 26271612, + 1222363, + -25930428, + -41674307, + -37416607, + -14088985, + 17746821, + 42613673, + 47583009, + 28917325, + -5484424, + -39320759, + -55534743, + -44823744, + -10808495, + 30938142, + 59914022, + 60646020, + 30798991, + -16742817, + -59273228, + -74961130, + -53875919, + -3858505, + 52068903, + 86089814, + 79186208, + 31407256, + -36566423, + -92046952, + -105705377, + -66613310, + 10540128, + 90341136, + 132352946, + 110894685, + 29537929, + -77356641, + -158189087, + -167786335, + -90816604, + 46408996, + 182839764, + 247379636, + 192088286, + 19672257, + -207921965, + -385989567, + -404454581, + -192608879, + 246639245, + 827888943, + 1405274197, + 1818805200, + 1948473599, + 1755947239, + 1298028577, + 706733440, + 143597841, + -254486468, + -417826212, + -359911788, + -162655632, + 61346588, + 213473743, + 243120176, + 159149231, + 16730322, + -112476644, + -172876646, + -146577438, + -56338588, + 49327025, + 120572410, + 128566359, + 76199934, + -6431437, + -78313789, + -107200388, + -83541791, + -22866125, + 43495601, + 84157015, + 82180833, + 41787144, + -15224117, + -60920261, + -74689113, + -52325924, + -6844745, + 38792824, + 63099641, + 56034428, + 22962378, + -18858430, + -49144557, + -54317544, + -33479697, + 1940055, + 34320167, + 48528888, + 38917278, + 11428472, + -19886112, + -39977001, + -39969768, + -21010495, + 6844590, + 29891500, + 37472060, + 26852437, + 4078429, + -19375320, + -32343955, + -29249283, + -12439335, + 9358401, + 25525394, + 28693677, + 18066042, + -562170, + -17911772, + -25814169, + -21029921, + -6519958, + 10296781, + 21308910, + 21603065, + 11624034, + -3328204, + -15881064, + -20205196, + -14699539, + -2520019, + 10181541, + 17345518, + 15878449, + 6958202, + -4763453, + -13565007, + -15433443, + -9874559, + 51162, + 9384180, + 13730057, + 11314420, + 3674965, + -5260390, + -11177817, + -11448646, + -6278579, + 1557377, + 8184967, + 10535521, + 7754160, + 1471691, + -5120550, + -8880612, + -8203652, + -3687956, + 2286464, + 6798754, + 7806670, + 5058923, + 99253, + -4581584, + -6788156, + -5641391, + -1907919, + 2473031, + 5387167, + 5558391, + 3095705, + -654015, + -3829798, + -4973485, + -3691194, + -763540, + 2308406, + 4065555, + 3777638, + 1734304, + -968309, + -3006700, + -3472722, + -2270432, + -97905, + 1945123, + 2908481, + 2427928, + 849142, + -994014, + -2213593, + -2290825, + -1289048, + 226618, + 1499616, + 1955373, + 1455496, + 323097, + -852048, + -1516091, + -1408283, + -655302, + 326332, + 1054966, + 1216814, + 796173, + 51646, + -634508, + -949291, + -788340, + -281535, + 294745, + 664447, + 681399, + 382169, + -53752, + -406352, + -523676, + -384176, + -89086, + 202333, + 356064, + 322741, + 148070, + -63638, + -208311, + -237416, + -163465, + 18134, + 228878, + 357473, + 316523, + 96238, + -215906, + -466502, + -509522, + -287597, + 122465, + 530492, + 718638, + 554683, + 75338, + -509737, + -906162, + -880188, + -390708, + 364333, + 1022593, + 1228224, + 819913, + -61411, + -1011465, + -1544285, + -1337091, + -416673, + 816797, + 1758349, + 1891234, + 1064277, + -392655, + -1791434, + -2406420, + -1845872, + -286186, + 1565445, + 2786050, + 2692304, + 1213845, + -1015607, + -2921441, + -3501174, + -2344852, + 104226, + 2704527, + 4142286, + 3589293, + 1165917, + -2043782, + -4468527, + -4813109, + -2740559, + 881818, + 4331897, + 5844687, + 4507411, + 787399, + -3603582, + -6488209, + -6295940, + -2904179, + 2196246, + 6543419, + 7884863, + 5334059, + -86039, + -5830531, + -9017969, + -7866370, + -2668566, + 4218122, + 9427905, + 10222111, + 5914131, + -1651102, + -8866514, + -12071951, + -9398532, + -1824675, + 7139270, + 13064059, + 12778276, + 6044693, + -4140446, + -12860262, + -15637944, + -10718255, + -114932, + 11177781, + 17521619, + 15433716, + 5466466, + -7832805, + -17974746, + -19677950, + -11594989, + 2781446, + 16593501, + 22870101, + 18023452, + 3846646, + -13077562, + -24408117, + -24133989, + -11726419, + 7281384, + 23724987, + 29201416, + 20330876, + 741270, + -20350274, + -32441686, + -28942037, + -10704407, + 13971579, + 33071959, + 36679716, + 22072417, + -4490184, + -30377326, + -42546249, + -34060386, + -7934528, + 23777896, + 45482844, + 45651891, + 22856119, + -12889119, + -44430599, + -55630782, + -39529733, + -2432166, + 38386159, + 62619073, + 56917107, + 22063489, + -26437812, + -65106414, + -73701487, + -45622125, + 7760348, + 61444760, + 88296837, + 72509698, + 18469581, + -49756146, + -98816809, + -102012846, + -53319089, + 27635590, + 102921201, + 133501243, + 98715601, + 8667480, + -97311616, + -166850622, + -159091602, + -66627032, + 76091982, + 203578082, + 246675286, + 165816928, + -24355547, + -251227844, + -405552623, + -381623552, + -121357279, + 355565199, + 948938611, + 1505832150, + 1870034590, + 1935266349, + 1682221311, + 1185349653, + 586788459, + 47385533, + -306694229, + -422118419, + -328159128, + -116369070, + 99981997, + 229758543, + 234160378, + 133066878, + -12363419, + -131255230, + -174360818, + -132321537, + -34700222, + 67666700, + 127611618, + 122272974, + 60811705, + -22942304, + -88216508, + -106508031, + -73502459, + -8938821, + 54506101, + 87349909, + 76675320, + 30820175, + -26111669, + -66631207, + -72913025, + -44420194, + 3054173, + 45894032, + 64245659, + 51074069, + 14626610, + -26423783, + -52417361, + -52017827, + -27034394, + 9234189, + 38963561, + 48482299, + 34478200, + 4953886, + -25212994, + -41699131, + -37476740, + -15722415, + 12263899, + 32865527, + 36726967, + 22948079, + -958492, + -23092825, + -33050675, + -26774835, + -8131983, + 13354204, + 27329869, + 27569409, + 14705966, + -4441285, + -20439880, + -25864180, + -18712658, + -3064435, + 13187720, + 22293134, + 20317093, + 8802468, + -6261489, + -17527006, + -19852881, + -12626253, + 194793, + 12213340, + 17767539, + 14579988, + 4651844, + -6926322, + -14565802, + -14862838, + -8092568, + 2129803, + 10756124, + 13785012, + 10102461, + 1844637, + -6804795, + -11720620, + -10791576, + -4804429, + 3100928, + 9062056, + 10370713, + 6688910, + 65847, + -6179983, + -9113274, + -7550958, + -2514616, + 3391984, + 7317464, + 7530755, + 4170347, + -941667, + -5272477, + -6825461, + -5051083, + -1011267, + 3231476, + 5658485, + 5248015, + 2390701, + -1393050, + -4251578, + -4901629, + -3195220, + -108293, + 2802210, + 4177096, + 3483008, + 1203097, + -1467763, + -3241656, + -3353239, + -1880740, + 357077, + 2246135, + 2926575, + 2177976, + 470992, + -1311910, + -2327146, + -2164464, + -1003127, + 523818, + 1667762, + 1927472, + 1262782, + 71280, + -1039493, + -1557718, + -1298955, + -461167, + 506006, + 1137790, + 1174291, + 661492, + -102426, + -734058, + -954110, + -707056, + -162025, + 392375, + 697526, + 642630, + 298711, + -137368, + -451370, + -514568, + -332810, + -25360, + 247119, + 364156, + 296270, + 104976, + -100616, + -223208, + -232907, + -134079, + 61356, + 264704, + 364539, + 285373, + 36825, + -276279, + -495275, + -485893, + -215802, + 211514, + 591874, + 715580, + 479524, + -42251, + -613451, + -939478, + -816373, + -250840, + 516483, + 1108938, + 1195754, + 671552, + -261816, + -1165612, + -1566957, + -1202108, + -176966, + 1048289, + 1861100, + 1798954, + 804837, + -702202, + -1996612, + -2391562, + -1597604, + 89957, + 1888294, + 2885145, + 2496602, + 797218, + -1459444, + -3167867, + -3407225, + -1929529, + 655958, + 3122526, + 4202398, + 3231745, + 539193, + -2642060, + -4731675, + -4581120, + -2093102, + 1647537, + 4835914, + 5811463, + 3913853, + -106683, + -4366759, + -6724160, + -5847282, + -1949466, + 3209309, + 7106145, + 7681275, + 4414388, + -1305661, + -6753916, + -9158565, + -7100884, + -1323548, + 5501707, + 9998127, + 9744910, + 4562710, + -3251129, + -9924157, + -12019699, + -8192917, + -1094, + 8700529, + 13560392, + 11894251, + 4140955, + -6167651, + -13998136, + -15260285, + -8924102, + 2277855, + 13001378, + 17825244, + 13974927, + 2874906, + -10320915, + -19102844, + -18799823, + -9035199, + 5834371, + 18634411, + 22815337, + 15779650, + 414652, + -16042557, + -25390361, + -22526389, + -8187472, + 11085705, + 25899902, + 28561389, + 17035346, + -3708192, + -23786438, + -33080930, + -26301453, + -5919253, + 18623734, + 35247519, + 35140944, + 17373081, + -10177301, + -34254743, + -42557979, + -29967534, + -1544297, + 29394958, + 47456122, + 42762967, + 16252316, + -20122436, + -48695568, + -54589405, + -33358156, + 6103650, + 45147233, + 64078498, + 51971659, + 12754486, + -35728788, + -69690254, + -70913387, + -36309297, + 19399037, + 69709008, + 88729398, + 64235555, + 4932205, + -62157156, + -103681822, + -96156995, + -38671335, + 44508935, + 113651058, + 131930143, + 84225780, + -12885816, + -115771042, + -172307103, + -146865962, + -40320390, + 105180169, + 220842346, + 240829861, + 134976119, + -69977160, + -291622361, + -417826926, + -349077878, + -41167965, + 469327711, + 1068541325, + 1598515423, + 1909013218, + 1909013218, + 1598515423, + 1068541325, + 469327711, + -41167965, + -349077878, + -417826926, + -291622361, + -69977160, + 134976119, + 240829861, + 220842346, + 105180169, + -40320390, + -146865962, + -172307103, + -115771042, + -12885816, + 84225780, + 131930143, + 113651058, + 44508935, + -38671335, + -96156995, + -103681822, + -62157156, + 4932205, + 64235555, + 88729398, + 69709008, + 19399037, + -36309297, + -70913387, + -69690254, + -35728788, + 12754486, + 51971659, + 64078498, + 45147233, + 6103650, + -33358156, + -54589405, + -48695568, + -20122436, + 16252316, + 42762967, + 47456122, + 29394958, + -1544297, + -29967534, + -42557979, + -34254743, + -10177301, + 17373081, + 35140944, + 35247519, + 18623734, + -5919253, + -26301453, + -33080930, + -23786438, + -3708192, + 17035346, + 28561389, + 25899902, + 11085705, + -8187472, + -22526389, + -25390361, + -16042557, + 414652, + 15779650, + 22815337, + 18634411, + 5834371, + -9035199, + -18799823, + -19102844, + -10320915, + 2874906, + 13974927, + 17825244, + 13001378, + 2277855, + -8924102, + -15260285, + -13998136, + -6167651, + 4140955, + 11894251, + 13560392, + 8700529, + -1094, + -8192917, + -12019699, + -9924157, + -3251129, + 4562710, + 9744910, + 9998127, + 5501707, + -1323548, + -7100884, + -9158565, + -6753916, + -1305661, + 4414388, + 7681275, + 7106145, + 3209309, + -1949466, + -5847282, + -6724160, + -4366759, + -106683, + 3913853, + 5811463, + 4835914, + 1647537, + -2093102, + -4581120, + -4731675, + -2642060, + 539193, + 3231745, + 4202398, + 3122526, + 655958, + -1929529, + -3407225, + -3167867, + -1459444, + 797218, + 2496602, + 2885145, + 1888294, + 89957, + -1597604, + -2391562, + -1996612, + -702202, + 804837, + 1798954, + 1861100, + 1048289, + -176966, + -1202108, + -1566957, + -1165612, + -261816, + 671552, + 1195754, + 1108938, + 516483, + -250840, + -816373, + -939478, + -613451, + -42251, + 479524, + 715580, + 591874, + 211514, + -215802, + -485893, + -495275, + -276279, + 36825, + 285373, + 364539, + 264704, + 61356, + -134079, + -232907, + -223208, + -100616, + 104976, + 296270, + 364156, + 247119, + -25360, + -332810, + -514568, + -451370, + -137368, + 298711, + 642630, + 697526, + 392375, + -162025, + -707056, + -954110, + -734058, + -102426, + 661492, + 1174291, + 1137790, + 506006, + -461167, + -1298955, + -1557718, + -1039493, + 71280, + 1262782, + 1927472, + 1667762, + 523818, + -1003127, + -2164464, + -2327146, + -1311910, + 470992, + 2177976, + 2926575, + 2246135, + 357077, + -1880740, + -3353239, + -3241656, + -1467763, + 1203097, + 3483008, + 4177096, + 2802210, + -108293, + -3195220, + -4901629, + -4251578, + -1393050, + 2390701, + 5248015, + 5658485, + 3231476, + -1011267, + -5051083, + -6825461, + -5272477, + -941667, + 4170347, + 7530755, + 7317464, + 3391984, + -2514616, + -7550958, + -9113274, + -6179983, + 65847, + 6688910, + 10370713, + 9062056, + 3100928, + -4804429, + -10791576, + -11720620, + -6804795, + 1844637, + 10102461, + 13785012, + 10756124, + 2129803, + -8092568, + -14862838, + -14565802, + -6926322, + 4651844, + 14579988, + 17767539, + 12213340, + 194793, + -12626253, + -19852881, + -17527006, + -6261489, + 8802468, + 20317093, + 22293134, + 13187720, + -3064435, + -18712658, + -25864180, + -20439880, + -4441285, + 14705966, + 27569409, + 27329869, + 13354204, + -8131983, + -26774835, + -33050675, + -23092825, + -958492, + 22948079, + 36726967, + 32865527, + 12263899, + -15722415, + -37476740, + -41699131, + -25212994, + 4953886, + 34478200, + 48482299, + 38963561, + 9234189, + -27034394, + -52017827, + -52417361, + -26423783, + 14626610, + 51074069, + 64245659, + 45894032, + 3054173, + -44420194, + -72913025, + -66631207, + -26111669, + 30820175, + 76675320, + 87349909, + 54506101, + -8938821, + -73502459, + -106508031, + -88216508, + -22942304, + 60811705, + 122272974, + 127611618, + 67666700, + -34700222, + -132321537, + -174360818, + -131255230, + -12363419, + 133066878, + 234160378, + 229758543, + 99981997, + -116369070, + -328159128, + -422118419, + -306694229, + 47385533, + 586788459, + 1185349653, + 1682221311, + 1935266349, + 1870034590, + 1505832150, + 948938611, + 355565199, + -121357279, + -381623552, + -405552623, + -251227844, + -24355547, + 165816928, + 246675286, + 203578082, + 76091982, + -66627032, + -159091602, + -166850622, + -97311616, + 8667480, + 98715601, + 133501243, + 102921201, + 27635590, + -53319089, + -102012846, + -98816809, + -49756146, + 18469581, + 72509698, + 88296837, + 61444760, + 7760348, + -45622125, + -73701487, + -65106414, + -26437812, + 22063489, + 56917107, + 62619073, + 38386159, + -2432166, + -39529733, + -55630782, + -44430599, + -12889119, + 22856119, + 45651891, + 45482844, + 23777896, + -7934528, + -34060386, + -42546249, + -30377326, + -4490184, + 22072417, + 36679716, + 33071959, + 13971579, + -10704407, + -28942037, + -32441686, + -20350274, + 741270, + 20330876, + 29201416, + 23724987, + 7281384, + -11726419, + -24133989, + -24408117, + -13077562, + 3846646, + 18023452, + 22870101, + 16593501, + 2781446, + -11594989, + -19677950, + -17974746, + -7832805, + 5466466, + 15433716, + 17521619, + 11177781, + -114932, + -10718255, + -15637944, + -12860262, + -4140446, + 6044693, + 12778276, + 13064059, + 7139270, + -1824675, + -9398532, + -12071951, + -8866514, + -1651102, + 5914131, + 10222111, + 9427905, + 4218122, + -2668566, + -7866370, + -9017969, + -5830531, + -86039, + 5334059, + 7884863, + 6543419, + 2196246, + -2904179, + -6295940, + -6488209, + -3603582, + 787399, + 4507411, + 5844687, + 4331897, + 881818, + -2740559, + -4813109, + -4468527, + -2043782, + 1165917, + 3589293, + 4142286, + 2704527, + 104226, + -2344852, + -3501174, + -2921441, + -1015607, + 1213845, + 2692304, + 2786050, + 1565445, + -286186, + -1845872, + -2406420, + -1791434, + -392655, + 1064277, + 1891234, + 1758349, + 816797, + -416673, + -1337091, + -1544285, + -1011465, + -61411, + 819913, + 1228224, + 1022593, + 364333, + -390708, + -880188, + -906162, + -509737, + 75338, + 554683, + 718638, + 530492, + 122465, + -287597, + -509522, + -466502, + -215906, + 96238, + 316523, + 357473, + 228878, + 18134, + -163465, + -237416, + -208311, + -63638, + 148070, + 322741, + 356064, + 202333, + -89086, + -384176, + -523676, + -406352, + -53752, + 382169, + 681399, + 664447, + 294745, + -281535, + -788340, + -949291, + -634508, + 51646, + 796173, + 1216814, + 1054966, + 326332, + -655302, + -1408283, + -1516091, + -852048, + 323097, + 1455496, + 1955373, + 1499616, + 226618, + -1289048, + -2290825, + -2213593, + -994014, + 849142, + 2427928, + 2908481, + 1945123, + -97905, + -2270432, + -3472722, + -3006700, + -968309, + 1734304, + 3777638, + 4065555, + 2308406, + -763540, + -3691194, + -4973485, + -3829798, + -654015, + 3095705, + 5558391, + 5387167, + 2473031, + -1907919, + -5641391, + -6788156, + -4581584, + 99253, + 5058923, + 7806670, + 6798754, + 2286464, + -3687956, + -8203652, + -8880612, + -5120550, + 1471691, + 7754160, + 10535521, + 8184967, + 1557377, + -6278579, + -11448646, + -11177817, + -5260390, + 3674965, + 11314420, + 13730057, + 9384180, + 51162, + -9874559, + -15433443, + -13565007, + -4763453, + 6958202, + 15878449, + 17345518, + 10181541, + -2520019, + -14699539, + -20205196, + -15881064, + -3328204, + 11624034, + 21603065, + 21308910, + 10296781, + -6519958, + -21029921, + -25814169, + -17911772, + -562170, + 18066042, + 28693677, + 25525394, + 9358401, + -12439335, + -29249283, + -32343955, + -19375320, + 4078429, + 26852437, + 37472060, + 29891500, + 6844590, + -21010495, + -39969768, + -39977001, + -19886112, + 11428472, + 38917278, + 48528888, + 34320167, + 1940055, + -33479697, + -54317544, + -49144557, + -18858430, + 22962378, + 56034428, + 63099641, + 38792824, + -6844745, + -52325924, + -74689113, + -60920261, + -15224117, + 41787144, + 82180833, + 84157015, + 43495601, + -22866125, + -83541791, + -107200388, + -78313789, + -6431437, + 76199934, + 128566359, + 120572410, + 49327025, + -56338588, + -146577438, + -172876646, + -112476644, + 16730322, + 159149231, + 243120176, + 213473743, + 61346588, + -162655632, + -359911788, + -417826212, + -254486468, + 143597841, + 706733440, + 1298028577, + 1755947239, + 1948473599, + 1818805200, + 1405274197, + 827888943, + 246639245, + -192608879, + -404454581, + -385989567, + -207921965, + 19672257, + 192088286, + 247379636, + 182839764, + 46408996, + -90816604, + -167786335, + -158189087, + -77356641, + 29537929, + 110894685, + 132352946, + 90341136, + 10540128, + -66613310, + -105705377, + -92046952, + -36566423, + 31407256, + 79186208, + 86089814, + 52068903, + -3858505, + -53875919, + -74961130, + -59273228, + -16742817, + 30798991, + 60646020, + 59914022, + 30938142, + -10808495, + -44823744, + -55534743, + -39320759, + -5484424, + 28917325, + 47583009, + 42613673, + 17746821, + -14088985, + -37416607, + -41674307, + -25930428, + 1222363, + 26271612, + 37459127, + 30252163, + 9089375, + -15219179, + -30967558, + -31153365, + -16540836, + 5126123, + 23178429, + 29243581, + 21094273, + 3372008, + -14988829, + -25235471, + -22942968, + -9880945, + 7162624, + 19877599, + 22461532, + 14239665, + -293571, + -13891451, + -20148049, + -16495680, + -5214349, + 7918022, + 16563622, + 16866934, + 9148915, + -2477864, + -12274812, + -15694807, + -11475433, + -2053189, + 7803739, + 13393303, + 12309285, + 5452196, + -3589449, + -10399430, + -11879309, + -7642381, + -37318, + 7129189, + 10486551, + 8674061, + 2865362, + -3942533, + -8462920, + -8696722, + -4801137, + 1119412, + 6133720, + 7926224, + 5855814, + 1152375, + -3787189, + -6611083, + -6124240, + -2778107, + 1653015, + 5001382, + 5759187, + 3747495, + 109386, + -3323074, + -4944286, + -4118908, + -1413187, + 1759495, + 3868716, + 3999303, + 2238386, + -440843, + -2706060, + -3522760, + -2619958, + -558599, + 1598904, + 2830201, + 2632292, + 1216551, + -649895, + -2052349, + -2372315, + -1553773, + -80927, + 1297279, + 1943471, + 1622008, + 573341, + -643145, + -1442262, + -1490820, + -840081, + 135954, + 948445, + 1235102, + 917485, + 208299, + -519383, + -924641, + -855295, + -398277, + 188400, + 616631, + 707035, + 460028, + 33436, + -351473, + -522093, + -429126, + -153052, + 151745, + 340165, + 343360, + 189688, + -23805, + -188323, + -236856 + +}; + +static const struct src_stage src_int32_5_21_4535_5000 = { + 4, 1, 5, 348, 1740, 21, 5, 0, 2, + src_int32_5_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_5_7_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_5_7_4535_5000.h new file mode 100644 index 000000000000..59869dfb8c70 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_5_7_4535_5000.h @@ -0,0 +1,698 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_5_7_4535_5000_fir[680] = { + 42053, + -83399, + 41109, + 88721, + -189765, + 114286, + 139607, + -352592, + 252547, + 179018, + -580492, + 484689, + 181768, + -876065, + 842875, + 111882, + -1232699, + 1360267, + -78044, + -1631292, + 2067862, + -446662, + -2037123, + 2990729, + -1062847, + -2397100, + 4143877, + -2003945, + -2637502, + 5528089, + -3353622, + -2662132, + 7126034, + -5199912, + -2350478, + 8898939, + -7634405, + -1554950, + 10783916, + -10754128, + -95284, + 12691748, + -14668706, + 2253578, + 14504313, + -19517581, + 5787685, + 16069611, + -25507215, + 10931032, + 17189430, + -32991600, + 18364360, + 17586951, + -42658969, + 29342343, + 16816431, + -56025666, + 46596766, + 13976382, + -77048457, + 77604702, + 6526064, + -119641209, + 152946068, + -18284232, + -286340397, + 711788188, + 1451492900, + 440162937, + -316752676, + 75068640, + 99989562, + -131153382, + 50962460, + 45867747, + -80472759, + 41263024, + 23383278, + -55454510, + 34999266, + 11187410, + -39915028, + 30002658, + 3829007, + -29084880, + 25617814, + -750623, + -21073298, + 21625331, + -3534328, + -14981907, + 17964062, + -5080306, + -10319341, + 14634130, + -5751922, + -6779356, + 11655646, + -5810620, + -4145680, + 9048929, + -5456577, + -2248450, + 6824813, + -4847308, + -944091, + 4980521, + -4106548, + -106597, + 3499005, + -3328955, + 375529, + 2350520, + -2583300, + 599693, + 1495573, + -1915373, + 648686, + 888585, + -1351150, + 590169, + 481678, + -900314, + 476661, + 228169, + -560033, + 346259, + 85432, + -318764, + 224063, + 16931, + -159818, + 124181, + -6640, + -64480, + 21854, + -88349, + 86487, + 32354, + -186204, + 198508, + 21661, + -322375, + 384294, + -33480, + -493433, + 666669, + -164894, + -686999, + 1067240, + -412957, + -879061, + 1603218, + -825724, + -1031601, + 2283722, + -1457166, + -1090730, + 3105782, + -2364573, + -985474, + 4050335, + -3605381, + -627177, + 5078419, + -5233783, + 90716, + 6127736, + -7297694, + 1293163, + 7109446, + -9836850, + 3125490, + 7904702, + -12883111, + 5759082, + 8359570, + -16464609, + 9404934, + 8275485, + -20616580, + 14343434, + 7388921, + -25404608, + 20988797, + 5325673, + -30973774, + 30033924, + 1491743, + -37660517, + 42806913, + -5214087, + -46286668, + 62294021, + -17296421, + -59128107, + 96911997, + -42408361, + -84567361, + 182622722, + -122093886, + -190931451, + 973602131, + 1364156530, + 185019367, + -289670293, + 144244552, + 34879335, + -119016760, + 83542417, + 7952565, + -69572486, + 59971911, + -2928822, + -45104065, + 46275656, + -8272208, + -30192557, + 36666623, + -10898398, + -20141126, + 29224994, + -11930190, + -13032121, + 23165297, + -11942066, + -7920940, + 18124002, + -11286977, + -4268093, + 13914668, + -10210931, + -1723126, + 10427905, + -8898241, + -32271, + 7586028, + -7490683, + 1003552, + 5321741, + -6096149, + 1548148, + 3568678, + -4793207, + 1738792, + 2258273, + -3634344, + 1689953, + 1320092, + -2649141, + 1494909, + 683938, + -1847806, + 1226771, + 282631, + -1225104, + 939701, + 54745, + -764516, + 670655, + -53172, + -442344, + 441687, + -85166, + -231478, + 262712, + -75322, + -104599, + 134481, + -48058, + -36627, + -5900, + -76495, + 120265, + -36112, + -146636, + 252295, + -110026, + -228925, + 453186, + -254282, + -308179, + 735295, + -501524, + -358949, + 1105305, + -889046, + -343872, + 1560827, + -1456557, + -212659, + 2086841, + -2243137, + 98155, + 2652218, + -3283553, + 664657, + 3206560, + -4604225, + 1574378, + 3677449, + -6219212, + 2924881, + 3968015, + -8126626, + 4822867, + 3954349, + -10305910, + 7385077, + 3481644, + -12716346, + 10743149, + 2356795, + -15297102, + 15056321, + 332825, + -17968980, + 20539683, + -2924676, + -20637859, + 27524923, + -7911896, + -23199675, + 36596039, + -15461695, + -25546609, + 48923180, + -27202269, + -27573998, + 67228358, + -46998604, + -29187417, + 99418057, + -87123743, + -30309305, + 180873340, + -218874662, + -30884556, + 1198954071, + 1198954071, + -30884556, + -218874662, + 180873340, + -30309305, + -87123743, + 99418057, + -29187417, + -46998604, + 67228358, + -27573998, + -27202269, + 48923180, + -25546609, + -15461695, + 36596039, + -23199675, + -7911896, + 27524923, + -20637859, + -2924676, + 20539683, + -17968980, + 332825, + 15056321, + -15297102, + 2356795, + 10743149, + -12716346, + 3481644, + 7385077, + -10305910, + 3954349, + 4822867, + -8126626, + 3968015, + 2924881, + -6219212, + 3677449, + 1574378, + -4604225, + 3206560, + 664657, + -3283553, + 2652218, + 98155, + -2243137, + 2086841, + -212659, + -1456557, + 1560827, + -343872, + -889046, + 1105305, + -358949, + -501524, + 735295, + -308179, + -254282, + 453186, + -228925, + -110026, + 252295, + -146636, + -36112, + 120265, + -76495, + -5900, + -36627, + -48058, + 134481, + -104599, + -75322, + 262712, + -231478, + -85166, + 441687, + -442344, + -53172, + 670655, + -764516, + 54745, + 939701, + -1225104, + 282631, + 1226771, + -1847806, + 683938, + 1494909, + -2649141, + 1320092, + 1689953, + -3634344, + 2258273, + 1738792, + -4793207, + 3568678, + 1548148, + -6096149, + 5321741, + 1003552, + -7490683, + 7586028, + -32271, + -8898241, + 10427905, + -1723126, + -10210931, + 13914668, + -4268093, + -11286977, + 18124002, + -7920940, + -11942066, + 23165297, + -13032121, + -11930190, + 29224994, + -20141126, + -10898398, + 36666623, + -30192557, + -8272208, + 46275656, + -45104065, + -2928822, + 59971911, + -69572486, + 7952565, + 83542417, + -119016760, + 34879335, + 144244552, + -289670293, + 185019367, + 1364156530, + 973602131, + -190931451, + -122093886, + 182622722, + -84567361, + -42408361, + 96911997, + -59128107, + -17296421, + 62294021, + -46286668, + -5214087, + 42806913, + -37660517, + 1491743, + 30033924, + -30973774, + 5325673, + 20988797, + -25404608, + 7388921, + 14343434, + -20616580, + 8275485, + 9404934, + -16464609, + 8359570, + 5759082, + -12883111, + 7904702, + 3125490, + -9836850, + 7109446, + 1293163, + -7297694, + 6127736, + 90716, + -5233783, + 5078419, + -627177, + -3605381, + 4050335, + -985474, + -2364573, + 3105782, + -1090730, + -1457166, + 2283722, + -1031601, + -825724, + 1603218, + -879061, + -412957, + 1067240, + -686999, + -164894, + 666669, + -493433, + -33480, + 384294, + -322375, + 21661, + 198508, + -186204, + 32354, + 86487, + -88349, + 21854, + -64480, + -6640, + 124181, + -159818, + 16931, + 224063, + -318764, + 85432, + 346259, + -560033, + 228169, + 476661, + -900314, + 481678, + 590169, + -1351150, + 888585, + 648686, + -1915373, + 1495573, + 599693, + -2583300, + 2350520, + 375529, + -3328955, + 3499005, + -106597, + -4106548, + 4980521, + -944091, + -4847308, + 6824813, + -2248450, + -5456577, + 9048929, + -4145680, + -5810620, + 11655646, + -6779356, + -5751922, + 14634130, + -10319341, + -5080306, + 17964062, + -14981907, + -3534328, + 21625331, + -21073298, + -750623, + 25617814, + -29084880, + 3829007, + 30002658, + -39915028, + 11187410, + 34999266, + -55454510, + 23383278, + 41263024, + -80472759, + 45867747, + 50962460, + -131153382, + 99989562, + 75068640, + -316752676, + 440162937, + 1451492900, + 711788188, + -286340397, + -18284232, + 152946068, + -119641209, + 6526064, + 77604702, + -77048457, + 13976382, + 46596766, + -56025666, + 16816431, + 29342343, + -42658969, + 17586951, + 18364360, + -32991600, + 17189430, + 10931032, + -25507215, + 16069611, + 5787685, + -19517581, + 14504313, + 2253578, + -14668706, + 12691748, + -95284, + -10754128, + 10783916, + -1554950, + -7634405, + 8898939, + -2350478, + -5199912, + 7126034, + -2662132, + -3353622, + 5528089, + -2637502, + -2003945, + 4143877, + -2397100, + -1062847, + 2990729, + -2037123, + -446662, + 2067862, + -1631292, + -78044, + 1360267, + -1232699, + 111882, + 842875, + -876065, + 181768, + 484689, + -580492, + 179018, + 252547, + -352592, + 139607, + 114286, + -189765, + 88721, + 41109, + -83399, + 42053 + +}; + +static const struct src_stage src_int32_5_7_4535_5000 = { + 4, 3, 5, 136, 680, 7, 5, 0, 0, + src_int32_5_7_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_64_21_2381_5000.h b/src/audio/src/coef/src_ipc4_int32_64_21_2381_5000.h new file mode 100644 index 000000000000..4680121475ea --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_64_21_2381_5000.h @@ -0,0 +1,1553 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_64_21_2381_5000_fir[1536] = { + 47591, + 250302, + -2161881, + 5260958, + -3813413, + -11226687, + 39578873, + -56907168, + 18408470, + 109021034, + -306866913, + 500016339, + 1584969758, + 475586321, + -304787599, + 113202848, + 14350486, + -55091896, + 39575290, + -11842807, + -3354035, + 5104429, + -2158300, + 268573, + 53332, + 230720, + -2162004, + 5413465, + -4277163, + -10582872, + 39526837, + -58671546, + 22502033, + 104623873, + -308566270, + 524582475, + 1584255515, + 451309412, + -302338068, + 117167099, + 10333066, + -53229009, + 39517003, + -12430851, + -2899618, + 4944220, + -2151369, + 285546, + 59370, + 209814, + -2158564, + 5561609, + -4744677, + -9911789, + 39418330, + -60381773, + 26626068, + 100013897, + -309876190, + 549267497, + 1582827630, + 427202349, + -299528311, + 120911886, + 6361065, + -51321804, + 39404992, + -12990487, + -2450730, + 4780668, + -2141201, + 301239, + 65701, + 187575, + -2151458, + 5705047, + -5215329, + -9213914, + 39252572, + -62034622, + 30775355, + 95193951, + -310787472, + 574053947, + 1580687306, + 403281600, + -296368555, + 124435620, + 2439212, + -49373589, + 39240295, + -13521430, + -2007922, + 4614110, + -2127910, + 315669, + 72323, + 163996, + -2140588, + 5843434, + -5688476, + -8489773, + 39028849, + -63626894, + 34944559, + 90167203, + -311291202, + 598924161, + 1577836345, + 379563347, + -292869249, + 127737020, + -1427904, + -47387680, + 39024011, + -14023444, + -1571721, + 4444878, + -2111610, + 328856, + 79230, + 139071, + -2125858, + 5976426, + -6163457, + -7739939, + 38746522, + -65155429, + 39128242, + 84937134, + -311378767, + 623860284, + 1574277145, + 356063471, + -289041053, + 130815114, + -5235833, + -45367398, + 38757294, + -14496338, + -1142637, + 4273302, + -2092421, + 340823, + 86416, + 112799, + -2107178, + 6103681, + -6639595, + -6965034, + 38405025, + -66617111, + 43320867, + 79507546, + -311041866, + 648844282, + 1570012701, + 332797542, + -284894819, + 133669233, + -8980270, + -43316059, + 38441352, + -14939966, + -721156, + 4099706, + -2070463, + 351595, + 93874, + 85181, + -2084461, + 6224857, + -7116197, + -6165729, + 38003869, + -68008869, + 47516803, + 73882558, + -310272527, + 673857966, + 1565046601, + 309780804, + -280441585, + 136299008, + -12657056, + -41236974, + 38077443, + -15354231, + -307744, + 3924412, + -2045856, + 361195, + 101595, + 56219, + -2057625, + 6339613, + -7592556, + -5342741, + 37542643, + -69327684, + 51710332, + 68066606, + -309063113, + 698883004, + 1559383019, + 287028158, + -275692553, + 138704368, + -16262187, + -39133445, + 37666873, + -15739077, + 97156, + 3747733, + -2018723, + 369652, + 109571, + 25919, + -2026595, + 6447612, + -8067950, + -4496839, + 37021016, + -70570598, + 55895658, + 62064442, + -307406335, + 723900940, + 1553026714, + 264554155, + -270659081, + 140885533, + -19791811, + -37008756, + 37210994, + -16094496, + 493123, + 3569982, + -1989187, + 376993, + 117790, + -5708, + -1991298, + 6548518, + -8541645, + -3628836, + 36438739, + -71734710, + 60066909, + 55881132, + -305295265, + 748893211, + 1545983024, + 242372982, + -265352664, + 142843015, + -23242237, + -34866172, + 36711199, + -16420520, + 879757, + 3391462, + -1957373, + 383249, + 126243, + -38651, + -1951668, + 6642000, + -9012894, + -2739595, + 35795647, + -72817191, + 64218147, + 49522057, + -302723348, + 773841164, + 1538257861, + 220498447, + -259784925, + 144577605, + -26609932, + -32708934, + 36168925, + -16717225, + 1256681, + 3212471, + -1923404, + 388451, + 134915, + -72894, + -1907645, + 6727731, + -9480939, + -1830023, + 35091658, + -73815282, + 68343375, + 42992903, + -299684407, + 798726077, + 1529857705, + 198943971, + -253967598, + 146090378, + -29891528, + -30540255, + 35585643, + -16984730, + 1623543, + 3033303, + -1887406, + 392630, + 143793, + -108420, + -1859174, + 6805390, + -9945011, + -901076, + 34326779, + -74726302, + 72436545, + 36299668, + -296172659, + 823529173, + 1520789595, + 177722577, + -247912514, + 147382679, + -33083823, + -28363315, + 34962858, + -17223194, + 1980009, + 2854242, + -1849504, + 395819, + 152863, + -145206, + -1806209, + 6874659, + -10404332, + 46246, + 33501104, + -75547652, + 76491561, + 29448654, + -292182721, + 848231640, + 1511061124, + 156846878, + -241631586, + 148456123, + -36183781, + -26181258, + 34302111, + -17432814, + 2325772, + 2675566, + -1809820, + 398053, + 162109, + -183228, + -1748705, + 6935229, + -10858116, + 1010897, + 32614816, + -76276820, + 80502294, + 22446461, + -287709624, + 872814648, + 1500680432, + 136329070, + -235136798, + 149312587, + -39188538, + -23997189, + 33604968, + -17613828, + 2660545, + 2497546, + -1768480, + 399367, + 171512, + -222458, + -1686631, + 6986795, + -11305571, + 1991787, + 31668187, + -76911387, + 84462583, + 15299987, + -282748817, + 897259370, + 1489656194, + 116180917, + -228440188, + 149954205, + -42095400, + -21814165, + 32873024, + -17766511, + 2984066, + 2320445, + -1725607, + 399795, + 181055, + -262864, + -1619956, + 7029060, + -11745895, + 2987784, + 30661582, + -77449029, + 88366247, + 8016425, + -277296177, + 921546997, + 1477997615, + 96413749, + -221553837, + 150383359, + -44901844, + -19635200, + 32107896, + -17891176, + 3296095, + 2144519, + -1681323, + 399374, + 190719, + -304410, + -1548661, + 7061738, + -12178284, + 3997712, + 29595458, + -77887525, + 92207089, + 603252, + -271348022, + 945658759, + 1465714418, + 77038449, + -214489852, + 150602678, + -47605522, + -17463254, + 31311224, + -17988170, + 3596414, + 1970014, + -1635749, + 398140, + 200482, + -347060, + -1472732, + 7084549, + -12601931, + 5020356, + 28470363, + -78224758, + 95978910, + -6931771, + -264901112, + 969575939, + 1452816836, + 58065446, + -207260354, + 150615024, + -50204260, + -15301232, + 30484663, + -18057874, + 3884827, + 1797170, + -1589006, + 396131, + 210324, + -390770, + -1392164, + 7097223, + -13016023, + 6054457, + 27286941, + -78458723, + 99675513, + -14580604, + -257952661, + 993279899, + 1439315596, + 39504709, + -199877464, + 150423493, + -52696059, + -13151983, + 29629886, + -18100704, + 4161162, + 1626216, + -1541212, + 393384, + 220221, + -435497, + -1306960, + 7099499, + -13419748, + 7098722, + 26045928, + -78587528, + 103290711, + -22334939, + -250500343, + 1016752091, + 1425221918, + 21365739, + -192353290, + 150031400, + -55079093, + -11018293, + 28748580, + -18117108, + 4425269, + 1457374, + -1492483, + 389935, + 230149, + -481189, + -1217128, + 7091130, + -13812293, + 8151816, + 24748156, + -78609404, + 106818339, + -30186202, + -242542297, + 1039974078, + 1410547493, + 3657563, + -184699913, + 149442278, + -57351714, + -8902884, + 27842438, + -18107563, + 4677018, + 1290855, + -1442935, + 385823, + 240083, + -527797, + -1122689, + 7071876, + -14192847, + 9212370, + 23394550, + -78522700, + 110252260, + -38125560, + -234077135, + 1062927555, + 1395304478, + -13611270, + -176929375, + 148659867, + -59512446, + -6808413, + 26913165, + -18072577, + 4916304, + 1126865, + -1392682, + 381086, + 249998, + -575263, + -1023669, + 7041513, + -14560598, + 10278979, + 21986132, + -78325896, + 113586372, + -46143931, + -225103949, + 1085594362, + 1379505480, + -30432697, + -169053663, + 147688106, + -61559988, + -4737464, + 25962468, + -18012685, + 5143040, + 965595, + -1341834, + 375761, + 259866, + -623528, + -920104, + 6999826, + -14914743, + 11350206, + 20524016, + -78017603, + 116814621, + -54231989, + -215622310, + 1107956506, + 1363163543, + -46799146, + -161084700, + 146531127, + -63493215, + -2692551, + 24992058, + -17928451, + 5357163, + 807233, + -1290499, + 369886, + 269658, + -672530, + -812038, + 6946617, + -15254478, + 12424581, + 19009414, + -77596567, + 119931007, + -62380170, + -205632280, + 1129996177, + 1346292139, + -62703534, + -153034329, + 145193248, + -65311171, + -676112, + 24003644, + -17820462, + 5558630, + 651952, + -1238785, + 363498, + 279347, + -722203, + -699524, + 6881698, + -15579010, + 13500604, + 17443629, + -77061672, + 122929593, + -70578687, + -195134412, + 1151695767, + 1328905149, + -78139279, + -144914305, + 143678960, + -67013076, + 1309492, + 22998935, + -17689331, + 5747416, + 499920, + -1186795, + 356634, + 288902, + -772475, + -582625, + 6804898, + -15887551, + 14576747, + 15828060, + -76411947, + 125804513, + -78817531, + -184129754, + 1173037887, + 1311016849, + -93100296, + -136736276, + 141992924, + -68598316, + 3261979, + 21979632, + -17535693, + 5923519, + 351293, + -1134630, + 349331, + 298292, + -823275, + -461412, + 6716061, + -16179323, + 15651455, + 14164199, + -75646563, + 128549986, + -87086484, + -172619852, + 1194005384, + 1292641902, + -107581003, + -128511779, + 140139960, + -70066449, + 5179151, + 20947431, + -17360205, + 6086957, + 206217, + -1082389, + 341625, + 307484, + -874526, + -335965, + 6615046, + -16453558, + 16723148, + 12453630, + -74764843, + 131160315, + -95375128, + -160606755, + 1214581359, + 1273795333, + -121576323, + -120252220, + 138125038, + -71417198, + 7058889, + 19904017, + -17163543, + 6237765, + 64830, + -1030166, + 333553, + 316448, + -926147, + -206375, + 6501727, + -16709499, + 17790225, + 10698030, + -73766263, + 133629906, + -103672854, + -148093013, + 1234749186, + 1254492522, + -135081682, + -111968872, + 135953271, + -72650452, + 8899164, + 18851062, + -16946404, + 6375997, + -72740, + -978056, + 325149, + 325149, + -978056, + -72740, + 6375997, + -16946404, + 18851062, + 8899164, + -72650452, + 135953271, + -111968872, + -135081682, + 1254492522, + 1234749186, + -148093013, + -103672854, + 133629906, + -73766263, + 10698030, + 17790225, + -16709499, + 6501727, + -206375, + -926147, + 316448, + 333553, + -1030166, + 64830, + 6237765, + -17163543, + 19904017, + 7058889, + -71417198, + 138125038, + -120252220, + -121576323, + 1273795333, + 1214581359, + -160606755, + -95375128, + 131160315, + -74764843, + 12453630, + 16723148, + -16453558, + 6615046, + -335965, + -874526, + 307484, + 341625, + -1082389, + 206217, + 6086957, + -17360205, + 20947431, + 5179151, + -70066449, + 140139960, + -128511779, + -107581003, + 1292641902, + 1194005384, + -172619852, + -87086484, + 128549986, + -75646563, + 14164199, + 15651455, + -16179323, + 6716061, + -461412, + -823275, + 298292, + 349331, + -1134630, + 351293, + 5923519, + -17535693, + 21979632, + 3261979, + -68598316, + 141992924, + -136736276, + -93100296, + 1311016849, + 1173037887, + -184129754, + -78817531, + 125804513, + -76411947, + 15828060, + 14576747, + -15887551, + 6804898, + -582625, + -772475, + 288902, + 356634, + -1186795, + 499920, + 5747416, + -17689331, + 22998935, + 1309492, + -67013076, + 143678960, + -144914305, + -78139279, + 1328905149, + 1151695767, + -195134412, + -70578687, + 122929593, + -77061672, + 17443629, + 13500604, + -15579010, + 6881698, + -699524, + -722203, + 279347, + 363498, + -1238785, + 651952, + 5558630, + -17820462, + 24003644, + -676112, + -65311171, + 145193248, + -153034329, + -62703534, + 1346292139, + 1129996177, + -205632280, + -62380170, + 119931007, + -77596567, + 19009414, + 12424581, + -15254478, + 6946617, + -812038, + -672530, + 269658, + 369886, + -1290499, + 807233, + 5357163, + -17928451, + 24992058, + -2692551, + -63493215, + 146531127, + -161084700, + -46799146, + 1363163543, + 1107956506, + -215622310, + -54231989, + 116814621, + -78017603, + 20524016, + 11350206, + -14914743, + 6999826, + -920104, + -623528, + 259866, + 375761, + -1341834, + 965595, + 5143040, + -18012685, + 25962468, + -4737464, + -61559988, + 147688106, + -169053663, + -30432697, + 1379505480, + 1085594362, + -225103949, + -46143931, + 113586372, + -78325896, + 21986132, + 10278979, + -14560598, + 7041513, + -1023669, + -575263, + 249998, + 381086, + -1392682, + 1126865, + 4916304, + -18072577, + 26913165, + -6808413, + -59512446, + 148659867, + -176929375, + -13611270, + 1395304478, + 1062927555, + -234077135, + -38125560, + 110252260, + -78522700, + 23394550, + 9212370, + -14192847, + 7071876, + -1122689, + -527797, + 240083, + 385823, + -1442935, + 1290855, + 4677018, + -18107563, + 27842438, + -8902884, + -57351714, + 149442278, + -184699913, + 3657563, + 1410547493, + 1039974078, + -242542297, + -30186202, + 106818339, + -78609404, + 24748156, + 8151816, + -13812293, + 7091130, + -1217128, + -481189, + 230149, + 389935, + -1492483, + 1457374, + 4425269, + -18117108, + 28748580, + -11018293, + -55079093, + 150031400, + -192353290, + 21365739, + 1425221918, + 1016752091, + -250500343, + -22334939, + 103290711, + -78587528, + 26045928, + 7098722, + -13419748, + 7099499, + -1306960, + -435497, + 220221, + 393384, + -1541212, + 1626216, + 4161162, + -18100704, + 29629886, + -13151983, + -52696059, + 150423493, + -199877464, + 39504709, + 1439315596, + 993279899, + -257952661, + -14580604, + 99675513, + -78458723, + 27286941, + 6054457, + -13016023, + 7097223, + -1392164, + -390770, + 210324, + 396131, + -1589006, + 1797170, + 3884827, + -18057874, + 30484663, + -15301232, + -50204260, + 150615024, + -207260354, + 58065446, + 1452816836, + 969575939, + -264901112, + -6931771, + 95978910, + -78224758, + 28470363, + 5020356, + -12601931, + 7084549, + -1472732, + -347060, + 200482, + 398140, + -1635749, + 1970014, + 3596414, + -17988170, + 31311224, + -17463254, + -47605522, + 150602678, + -214489852, + 77038449, + 1465714418, + 945658759, + -271348022, + 603252, + 92207089, + -77887525, + 29595458, + 3997712, + -12178284, + 7061738, + -1548661, + -304410, + 190719, + 399374, + -1681323, + 2144519, + 3296095, + -17891176, + 32107896, + -19635200, + -44901844, + 150383359, + -221553837, + 96413749, + 1477997615, + 921546997, + -277296177, + 8016425, + 88366247, + -77449029, + 30661582, + 2987784, + -11745895, + 7029060, + -1619956, + -262864, + 181055, + 399795, + -1725607, + 2320445, + 2984066, + -17766511, + 32873024, + -21814165, + -42095400, + 149954205, + -228440188, + 116180917, + 1489656194, + 897259370, + -282748817, + 15299987, + 84462583, + -76911387, + 31668187, + 1991787, + -11305571, + 6986795, + -1686631, + -222458, + 171512, + 399367, + -1768480, + 2497546, + 2660545, + -17613828, + 33604968, + -23997189, + -39188538, + 149312587, + -235136798, + 136329070, + 1500680432, + 872814648, + -287709624, + 22446461, + 80502294, + -76276820, + 32614816, + 1010897, + -10858116, + 6935229, + -1748705, + -183228, + 162109, + 398053, + -1809820, + 2675566, + 2325772, + -17432814, + 34302111, + -26181258, + -36183781, + 148456123, + -241631586, + 156846878, + 1511061124, + 848231640, + -292182721, + 29448654, + 76491561, + -75547652, + 33501104, + 46246, + -10404332, + 6874659, + -1806209, + -145206, + 152863, + 395819, + -1849504, + 2854242, + 1980009, + -17223194, + 34962858, + -28363315, + -33083823, + 147382679, + -247912514, + 177722577, + 1520789595, + 823529173, + -296172659, + 36299668, + 72436545, + -74726302, + 34326779, + -901076, + -9945011, + 6805390, + -1859174, + -108420, + 143793, + 392630, + -1887406, + 3033303, + 1623543, + -16984730, + 35585643, + -30540255, + -29891528, + 146090378, + -253967598, + 198943971, + 1529857705, + 798726077, + -299684407, + 42992903, + 68343375, + -73815282, + 35091658, + -1830023, + -9480939, + 6727731, + -1907645, + -72894, + 134915, + 388451, + -1923404, + 3212471, + 1256681, + -16717225, + 36168925, + -32708934, + -26609932, + 144577605, + -259784925, + 220498447, + 1538257861, + 773841164, + -302723348, + 49522057, + 64218147, + -72817191, + 35795647, + -2739595, + -9012894, + 6642000, + -1951668, + -38651, + 126243, + 383249, + -1957373, + 3391462, + 879757, + -16420520, + 36711199, + -34866172, + -23242237, + 142843015, + -265352664, + 242372982, + 1545983024, + 748893211, + -305295265, + 55881132, + 60066909, + -71734710, + 36438739, + -3628836, + -8541645, + 6548518, + -1991298, + -5708, + 117790, + 376993, + -1989187, + 3569982, + 493123, + -16094496, + 37210994, + -37008756, + -19791811, + 140885533, + -270659081, + 264554155, + 1553026714, + 723900940, + -307406335, + 62064442, + 55895658, + -70570598, + 37021016, + -4496839, + -8067950, + 6447612, + -2026595, + 25919, + 109571, + 369652, + -2018723, + 3747733, + 97156, + -15739077, + 37666873, + -39133445, + -16262187, + 138704368, + -275692553, + 287028158, + 1559383019, + 698883004, + -309063113, + 68066606, + 51710332, + -69327684, + 37542643, + -5342741, + -7592556, + 6339613, + -2057625, + 56219, + 101595, + 361195, + -2045856, + 3924412, + -307744, + -15354231, + 38077443, + -41236974, + -12657056, + 136299008, + -280441585, + 309780804, + 1565046601, + 673857966, + -310272527, + 73882558, + 47516803, + -68008869, + 38003869, + -6165729, + -7116197, + 6224857, + -2084461, + 85181, + 93874, + 351595, + -2070463, + 4099706, + -721156, + -14939966, + 38441352, + -43316059, + -8980270, + 133669233, + -284894819, + 332797542, + 1570012701, + 648844282, + -311041866, + 79507546, + 43320867, + -66617111, + 38405025, + -6965034, + -6639595, + 6103681, + -2107178, + 112799, + 86416, + 340823, + -2092421, + 4273302, + -1142637, + -14496338, + 38757294, + -45367398, + -5235833, + 130815114, + -289041053, + 356063471, + 1574277145, + 623860284, + -311378767, + 84937134, + 39128242, + -65155429, + 38746522, + -7739939, + -6163457, + 5976426, + -2125858, + 139071, + 79230, + 328856, + -2111610, + 4444878, + -1571721, + -14023444, + 39024011, + -47387680, + -1427904, + 127737020, + -292869249, + 379563347, + 1577836345, + 598924161, + -311291202, + 90167203, + 34944559, + -63626894, + 39028849, + -8489773, + -5688476, + 5843434, + -2140588, + 163996, + 72323, + 315669, + -2127910, + 4614110, + -2007922, + -13521430, + 39240295, + -49373589, + 2439212, + 124435620, + -296368555, + 403281600, + 1580687306, + 574053947, + -310787472, + 95193951, + 30775355, + -62034622, + 39252572, + -9213914, + -5215329, + 5705047, + -2151458, + 187575, + 65701, + 301239, + -2141201, + 4780668, + -2450730, + -12990487, + 39404992, + -51321804, + 6361065, + 120911886, + -299528311, + 427202349, + 1582827630, + 549267497, + -309876190, + 100013897, + 26626068, + -60381773, + 39418330, + -9911789, + -4744677, + 5561609, + -2158564, + 209814, + 59370, + 285546, + -2151369, + 4944220, + -2899618, + -12430851, + 39517003, + -53229009, + 10333066, + 117167099, + -302338068, + 451309412, + 1584255515, + 524582475, + -308566270, + 104623873, + 22502033, + -58671546, + 39526837, + -10582872, + -4277163, + 5413465, + -2162004, + 230720, + 53332, + 268573, + -2158300, + 5104429, + -3354035, + -11842807, + 39575290, + -55091896, + 14350486, + 113202848, + -304787599, + 475586321, + 1584969758, + 500016339, + -306866913, + 109021034, + 18408470, + -56907168, + 39578873, + -11226687, + -3813413, + 5260958, + -2161881, + 250302, + 47591 + +}; + +static const struct src_stage src_int32_64_21_2381_5000 = { + 20, 61, 64, 24, 1536, 21, 64, 0, 0, + src_int32_64_21_2381_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_6_1_1134_5000.h b/src/audio/src/coef/src_ipc4_int32_6_1_1134_5000.h new file mode 100644 index 000000000000..24afbc0c515b --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_6_1_1134_5000.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_6_1_1134_5000_fir[96] = { + 141841, + 2137064, + -10649573, + -1548553, + 67116454, + -88441806, + -151988727, + 698059922, + 1311209938, + 513830372, + -196718717, + -42910503, + 62024584, + -9743822, + -7154701, + 2076980, + 388020, + 1704365, + -13860879, + 9695347, + 64487054, + -134243422, + -75165021, + 876432390, + 1262604823, + 335256109, + -212035170, + -2335062, + 51448203, + -14687360, + -3911104, + 1717564, + 763787, + 604914, + -16104814, + 23243496, + 52408102, + -174479312, + 33910126, + 1037110179, + 1168968613, + 172564306, + -202617565, + 30022499, + 37776615, + -16622147, + -1269329, + 1234866, + 1234866, + -1269329, + -16622147, + 37776615, + 30022499, + -202617565, + 172564306, + 1168968613, + 1037110179, + 33910126, + -174479312, + 52408102, + 23243496, + -16104814, + 604914, + 763787, + 1717564, + -3911104, + -14687360, + 51448203, + -2335062, + -212035170, + 335256109, + 1262604823, + 876432390, + -75165021, + -134243422, + 64487054, + 9695347, + -13860879, + 1704365, + 388020, + 2076980, + -7154701, + -9743822, + 62024584, + -42910503, + -196718717, + 513830372, + 1311209938, + 698059922, + -151988727, + -88441806, + 67116454, + -1548553, + -10649573, + 2137064, + 141841 + +}; + +static const struct src_stage src_int32_6_1_1134_5000 = { + 0, 1, 6, 16, 96, 1, 6, 0, 0, + src_int32_6_1_1134_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_3_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_7_3_4535_5000.h new file mode 100644 index 000000000000..90b79d1c5e5f --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_3_4535_5000.h @@ -0,0 +1,746 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_3_4535_5000_fir[728] = { + -46837, + 76113, + -110550, + 148125, + -185615, + 218479, + -240797, + 245303, + -223519, + 165997, + -62698, + -96522, + 321288, + -619989, + 998970, + -1461668, + 2007730, + -2632151, + 3324485, + -4068175, + 4840045, + -5610019, + 6341087, + -6989564, + 7505670, + -7834418, + 7916838, + -7691480, + 7096196, + -6070113, + 4555751, + -2501195, + -137776, + 3395708, + -7295743, + 11848284, + -17050146, + 22884373, + -29320838, + 36317862, + -43825102, + 51788199, + -60155939, + 68891461, + -77990538, + 87513553, + -97646814, + 108834426, + -122106072, + 140068865, + -170973962, + 259038733, + 2032057065, + -43241199, + -25605337, + 48863189, + -59441252, + 64332521, + -65972018, + 65470937, + -63444558, + 60290430, + -56298756, + 51701010, + -46692649, + 41443913, + -36104781, + 30807034, + -25664880, + 20774992, + -16216402, + 12050527, + -8321471, + 5056674, + -2267926, + -47283, + 1904102, + -3328434, + 4354894, + -5024678, + 5383441, + -5479253, + 5360697, + -5075172, + 4667441, + -4178456, + 3644482, + -3096511, + 2559962, + -2054648, + 1594969, + -1190302, + 845545, + -561760, + 336881, + -166449, + 44321, + 36667, + -84104, + 105507, + -107919, + 97619, + -79930, + 59122, + -47112, + 80331, + -123173, + 175207, + -234875, + 299248, + -363830, + 422409, + -467007, + 487927, + -473924, + 412517, + -290445, + 94270, + 188874, + -570419, + 1059387, + -1661357, + 2377405, + -3203064, + 4127361, + -5131982, + 6190622, + -7268569, + 8322562, + -9300967, + 10144287, + -10786006, + 11153770, + -11170866, + 10757947, + -9834937, + 8323012, + -6146547, + 3234874, + 476319, + -5044177, + 10518726, + -16944176, + 24362019, + -32816785, + 42365873, + -53095993, + 65150988, + -78780702, + 94431961, + -112931873, + 135897734, + -166791702, + 214239659, + -306489140, + 616244994, + 1909793687, + -267327692, + 105131131, + -42463673, + 9147971, + 11155181, + -24282125, + 32859685, + -38270038, + 41334671, + -42594938, + 42440809, + -41174696, + 39044716, + -36262484, + 33012649, + -29457891, + 25741397, + -21987986, + 18304572, + -14780405, + 11487330, + -8480247, + 5797818, + -3463485, + 1486768, + 135186, + -1415846, + 2377413, + -3048866, + 3464013, + -3659615, + 3673647, + -3543741, + 3305847, + -2993152, + 2635259, + -2257628, + 1881273, + -1522695, + 1194013, + -903269, + 654869, + -450108, + 287753, + -164643, + 76271, + -17329, + -17819, + 34732, + -38580, + 33919, + -37799, + 69224, + -113289, + 171306, + -243728, + 329831, + -427389, + 532392, + -638797, + 738365, + -820602, + 872822, + -880362, + 826959, + -695298, + 467736, + -127189, + -341837, + 952097, + -1712374, + 2626219, + -3690705, + 4895260, + -6220633, + 7638059, + -9108664, + 10583168, + -12001906, + 13295200, + -14384063, + 15181225, + -15592427, + 15517894, + -14853900, + 13494225, + -11331350, + 8257055, + -4162077, + -1065756, + 7545736, + -15412168, + 24828190, + -36009537, + 49265912, + -65075562, + 84227385, + -108113522, + 139398364, + -183786109, + 255795120, + -405609741, + 996516269, + 1678523091, + -400922545, + 202019123, + -118487790, + 71443413, + -40946106, + 19623757, + -4116401, + -7336832, + 15762895, + -21817876, + 25957066, + -28521116, + 29782098, + -29968922, + 29281515, + -27898590, + 25981707, + -23677151, + 21116580, + -18417039, + 15680718, + -12994720, + 10430970, + -8046395, + 5883388, + -3970589, + 2323951, + -948057, + -162363, + 1020784, + -1647165, + 2066227, + -2305794, + 2395239, + -2364102, + 2240898, + -2052147, + 1821635, + -1569906, + 1313976, + -1067255, + 839643, + -637769, + 465349, + -323618, + 211807, + -127634, + 67775, + -28301, + 5060, + 6006, + -19293, + 43027, + -80350, + 134164, + -206947, + 300398, + -415055, + 549906, + -701989, + 866045, + -1034221, + 1195877, + -1337510, + 1442830, + -1493019, + 1467169, + -1342931, + 1097361, + -707956, + 153863, + 582775, + -1515379, + 2651449, + -3991085, + 5525589, + -7236202, + 9093037, + -11054269, + 13065614, + -15060137, + 16958386, + -18668843, + 20088640, + -21104443, + 21593381, + -21423807, + 20455599, + -18539571, + 15515374, + -11206878, + 5413471, + 2105466, + -11657785, + 23666936, + -38760765, + 57943775, + -82958295, + 117127397, + -167641738, + 253331487, + -443517535, + 1363044639, + 1363044639, + -443517535, + 253331487, + -167641738, + 117127397, + -82958295, + 57943775, + -38760765, + 23666936, + -11657785, + 2105466, + 5413471, + -11206878, + 15515374, + -18539571, + 20455599, + -21423807, + 21593381, + -21104443, + 20088640, + -18668843, + 16958386, + -15060137, + 13065614, + -11054269, + 9093037, + -7236202, + 5525589, + -3991085, + 2651449, + -1515379, + 582775, + 153863, + -707956, + 1097361, + -1342931, + 1467169, + -1493019, + 1442830, + -1337510, + 1195877, + -1034221, + 866045, + -701989, + 549906, + -415055, + 300398, + -206947, + 134164, + -80350, + 43027, + -19293, + 6006, + 5060, + -28301, + 67775, + -127634, + 211807, + -323618, + 465349, + -637769, + 839643, + -1067255, + 1313976, + -1569906, + 1821635, + -2052147, + 2240898, + -2364102, + 2395239, + -2305794, + 2066227, + -1647165, + 1020784, + -162363, + -948057, + 2323951, + -3970589, + 5883388, + -8046395, + 10430970, + -12994720, + 15680718, + -18417039, + 21116580, + -23677151, + 25981707, + -27898590, + 29281515, + -29968922, + 29782098, + -28521116, + 25957066, + -21817876, + 15762895, + -7336832, + -4116401, + 19623757, + -40946106, + 71443413, + -118487790, + 202019123, + -400922545, + 1678523091, + 996516269, + -405609741, + 255795120, + -183786109, + 139398364, + -108113522, + 84227385, + -65075562, + 49265912, + -36009537, + 24828190, + -15412168, + 7545736, + -1065756, + -4162077, + 8257055, + -11331350, + 13494225, + -14853900, + 15517894, + -15592427, + 15181225, + -14384063, + 13295200, + -12001906, + 10583168, + -9108664, + 7638059, + -6220633, + 4895260, + -3690705, + 2626219, + -1712374, + 952097, + -341837, + -127189, + 467736, + -695298, + 826959, + -880362, + 872822, + -820602, + 738365, + -638797, + 532392, + -427389, + 329831, + -243728, + 171306, + -113289, + 69224, + -37799, + 33919, + -38580, + 34732, + -17819, + -17329, + 76271, + -164643, + 287753, + -450108, + 654869, + -903269, + 1194013, + -1522695, + 1881273, + -2257628, + 2635259, + -2993152, + 3305847, + -3543741, + 3673647, + -3659615, + 3464013, + -3048866, + 2377413, + -1415846, + 135186, + 1486768, + -3463485, + 5797818, + -8480247, + 11487330, + -14780405, + 18304572, + -21987986, + 25741397, + -29457891, + 33012649, + -36262484, + 39044716, + -41174696, + 42440809, + -42594938, + 41334671, + -38270038, + 32859685, + -24282125, + 11155181, + 9147971, + -42463673, + 105131131, + -267327692, + 1909793687, + 616244994, + -306489140, + 214239659, + -166791702, + 135897734, + -112931873, + 94431961, + -78780702, + 65150988, + -53095993, + 42365873, + -32816785, + 24362019, + -16944176, + 10518726, + -5044177, + 476319, + 3234874, + -6146547, + 8323012, + -9834937, + 10757947, + -11170866, + 11153770, + -10786006, + 10144287, + -9300967, + 8322562, + -7268569, + 6190622, + -5131982, + 4127361, + -3203064, + 2377405, + -1661357, + 1059387, + -570419, + 188874, + 94270, + -290445, + 412517, + -473924, + 487927, + -467007, + 422409, + -363830, + 299248, + -234875, + 175207, + -123173, + 80331, + -47112, + 59122, + -79930, + 97619, + -107919, + 105507, + -84104, + 36667, + 44321, + -166449, + 336881, + -561760, + 845545, + -1190302, + 1594969, + -2054648, + 2559962, + -3096511, + 3644482, + -4178456, + 4667441, + -5075172, + 5360697, + -5479253, + 5383441, + -5024678, + 4354894, + -3328434, + 1904102, + -47283, + -2267926, + 5056674, + -8321471, + 12050527, + -16216402, + 20774992, + -25664880, + 30807034, + -36104781, + 41443913, + -46692649, + 51701010, + -56298756, + 60290430, + -63444558, + 65470937, + -65972018, + 64332521, + -59441252, + 48863189, + -25605337, + -43241199, + 2032057065, + 259038733, + -170973962, + 140068865, + -122106072, + 108834426, + -97646814, + 87513553, + -77990538, + 68891461, + -60155939, + 51788199, + -43825102, + 36317862, + -29320838, + 22884373, + -17050146, + 11848284, + -7295743, + 3395708, + -137776, + -2501195, + 4555751, + -6070113, + 7096196, + -7691480, + 7916838, + -7834418, + 7505670, + -6989564, + 6341087, + -5610019, + 4840045, + -4068175, + 3324485, + -2632151, + 2007730, + -1461668, + 998970, + -619989, + 321288, + -96522, + -62698, + 165997, + -223519, + 245303, + -240797, + 218479, + -185615, + 148125, + -110550, + 76113, + -46837 + +}; + +static const struct src_stage src_int32_7_3_4535_5000 = { + 2, 5, 7, 104, 728, 3, 7, 0, 0, + src_int32_7_3_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_40_2976_5000.h b/src/audio/src/coef/src_ipc4_int32_7_40_2976_5000.h new file mode 100644 index 000000000000..d88f607edb96 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_40_2976_5000.h @@ -0,0 +1,801 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_40_2976_5000_fir[784] = { + -421117, + -873443, + -1322755, + -1593517, + -1494133, + -875322, + 305977, + 1935378, + 3721720, + 5224342, + 5931818, + 5383518, + 3311135, + -233691, + -4803751, + -9565560, + -13411383, + -15168908, + -13877127, + -9073390, + -1022383, + 9181848, + 19692130, + 28180417, + 32279941, + 30125596, + 20884518, + 5151728, + -14905050, + -35729583, + -52906902, + -61980038, + -59421519, + -43572146, + -15337429, + 21547643, + 60810851, + 94518072, + 114439887, + 113704027, + 88442916, + 39109504, + -28839808, + -105108031, + -175639859, + -224529950, + -236499541, + -199554513, + -107371492, + 39028183, + 230661341, + 451202931, + 678817148, + 888962385, + 1057754877, + 1165365556, + 1198903822, + 1154316530, + 1036988523, + 860945132, + 646788849, + 418710646, + 201063855, + 15049839, + -123969705, + -208140633, + -237556125, + -219473106, + -166512376, + -94205483, + -18335557, + 47479356, + 93588752, + 115262298, + 112723681, + 90361539, + 55346507, + 15963162, + -20017836, + -46646307, + -60587377, + -61329947, + -50850645, + -32870225, + -11897359, + 7731235, + 22633035, + 30861893, + 32042571, + 27184128, + 18257378, + 7655385, + -2338819, + -9973487, + -14272925, + -15086232, + -12963411, + -8913684, + -4115983, + 350358, + 3702636, + 5551849, + 5898310, + 5046349, + 3472379, + 1684346, + 105201, + -998677, + -1537513, + -1573189, + -1264997, + -805485, + -480627, + -941437, + -1376902, + -1606222, + -1439974, + -740218, + 516204, + 2189873, + 3965399, + 5386028, + 5939375, + 5183538, + 2888905, + -839329, + -5495912, + -10198866, + -13816387, + -15188511, + -13408417, + -8105599, + 339295, + 10715397, + 21085704, + 29086301, + 32387931, + 29242236, + 19000822, + 2481584, + -17929907, + -38514615, + -54796213, + -62389583, + -57980048, + -40240382, + -10476124, + 27183538, + 66162367, + 98391009, + 115729428, + 111637899, + 82797280, + 30351463, + -39520282, + -115896722, + -184324672, + -228827782, + -234435092, + -189828611, + -89653272, + 63942166, + 260858197, + 483844190, + 710487849, + 916128833, + 1077260839, + 1174887882, + 1197293382, + 1141768318, + 1015012729, + 832143987, + 614476184, + 386436641, + 172121897, + -7956647, + -139435040, + -215597131, + -237634268, + -213699577, + -156989711, + -83233969, + -8043315, + 55438648, + 98227457, + 116319371, + 110598215, + 85944939, + 49793943, + 10451268, + -24502884, + -49456713, + -61479641, + -60447884, + -48639991, + -29950124, + -8918761, + 10211804, + 24242679, + 31451990, + 31680326, + 26104111, + 16788647, + 6142252, + -3605762, + -10804105, + -14596383, + -14942859, + -12475837, + -8246726, + -3435494, + 910992, + 4062796, + 5688996, + 5840056, + 4853574, + 3218822, + 1437851, + -85571, + -1110241, + -1570460, + -1545789, + -1204193, + -738003, + -542379, + -1009006, + -1426859, + -1610769, + -1374731, + -593475, + 735249, + 2446694, + 4201937, + 5529901, + 5919856, + 4951583, + 2436732, + -1464566, + -6189458, + -10810082, + -14175146, + -15142874, + -12866532, + -7072260, + 1741640, + 12249576, + 22430879, + 29895316, + 32362476, + 28211562, + 16986320, + -270294, + -20959622, + -41211706, + -56506417, + -62550798, + -56262045, + -36658385, + -5449480, + 32848951, + 71376299, + 101957388, + 116576173, + 109059101, + 76661321, + 21229682, + -50339571, + -126525855, + -192519577, + -232325660, + -231335763, + -178955902, + -70831317, + 89752427, + 291595903, + 516563953, + 741727992, + 942379288, + 1095458419, + 1182859767, + 1194076531, + 1127752120, + 991881250, + 802627390, + 581952447, + 354448865, + 143889120, + -29958271, + -153758024, + -221937219, + -236765674, + -207252917, + -147119438, + -72237431, + 2002847, + 62967125, + 102353821, + 116883679, + 108082072, + 81292260, + 44177534, + 5032335, + -28779243, + -51998427, + -62101395, + -59343168, + -46287819, + -26982781, + -5980765, + 12585758, + 25710433, + 31897343, + 31198118, + 24947218, + 15293081, + 4648458, + -4819303, + -11563814, + -14848374, + -14741361, + -11952094, + -7568127, + -2765041, + 1446556, + 4391168, + 5795550, + 5758333, + 4647554, + 2962455, + 1196894, + -265863, + -1210038, + -1593362, + -1511884, + -1140901, + -671407, + -606081, + -1075663, + -1472047, + -1606645, + -1298153, + -435273, + 962407, + 2704641, + 4429830, + 5654483, + 5872226, + 4687471, + 1955572, + -2107242, + -6881269, + -11395670, + -14484487, + -15030059, + -12251533, + -5975874, + 3179760, + 13777741, + 23720441, + 30601236, + 32199980, + 27033954, + 14846058, + -3094422, + -23981557, + -43807274, + -58025802, + -62456748, + -54267717, + -32834740, + -274115, + 38521327, + 76427847, + 105194915, + 116965359, + 105964724, + 70046670, + 11770650, + -61258741, + -136949060, + -200177744, + -234984190, + -227177079, + -166932560, + -50925298, + 116416543, + 322813723, + 549290776, + 772465100, + 967650481, + 1112302727, + 1189261314, + 1189261314, + 1112302727, + 967650481, + 772465100, + 549290776, + 322813723, + 116416543, + -50925298, + -166932560, + -227177079, + -234984190, + -200177744, + -136949060, + -61258741, + 11770650, + 70046670, + 105964724, + 116965359, + 105194915, + 76427847, + 38521327, + -274115, + -32834740, + -54267717, + -62456748, + -58025802, + -43807274, + -23981557, + -3094422, + 14846058, + 27033954, + 32199980, + 30601236, + 23720441, + 13777741, + 3179760, + -5975874, + -12251533, + -15030059, + -14484487, + -11395670, + -6881269, + -2107242, + 1955572, + 4687471, + 5872226, + 5654483, + 4429830, + 2704641, + 962407, + -435273, + -1298153, + -1606645, + -1472047, + -1075663, + -606081, + -671407, + -1140901, + -1511884, + -1593362, + -1210038, + -265863, + 1196894, + 2962455, + 4647554, + 5758333, + 5795550, + 4391168, + 1446556, + -2765041, + -7568127, + -11952094, + -14741361, + -14848374, + -11563814, + -4819303, + 4648458, + 15293081, + 24947218, + 31198118, + 31897343, + 25710433, + 12585758, + -5980765, + -26982781, + -46287819, + -59343168, + -62101395, + -51998427, + -28779243, + 5032335, + 44177534, + 81292260, + 108082072, + 116883679, + 102353821, + 62967125, + 2002847, + -72237431, + -147119438, + -207252917, + -236765674, + -221937219, + -153758024, + -29958271, + 143889120, + 354448865, + 581952447, + 802627390, + 991881250, + 1127752120, + 1194076531, + 1182859767, + 1095458419, + 942379288, + 741727992, + 516563953, + 291595903, + 89752427, + -70831317, + -178955902, + -231335763, + -232325660, + -192519577, + -126525855, + -50339571, + 21229682, + 76661321, + 109059101, + 116576173, + 101957388, + 71376299, + 32848951, + -5449480, + -36658385, + -56262045, + -62550798, + -56506417, + -41211706, + -20959622, + -270294, + 16986320, + 28211562, + 32362476, + 29895316, + 22430879, + 12249576, + 1741640, + -7072260, + -12866532, + -15142874, + -14175146, + -10810082, + -6189458, + -1464566, + 2436732, + 4951583, + 5919856, + 5529901, + 4201937, + 2446694, + 735249, + -593475, + -1374731, + -1610769, + -1426859, + -1009006, + -542379, + -738003, + -1204193, + -1545789, + -1570460, + -1110241, + -85571, + 1437851, + 3218822, + 4853574, + 5840056, + 5688996, + 4062796, + 910992, + -3435494, + -8246726, + -12475837, + -14942859, + -14596383, + -10804105, + -3605762, + 6142252, + 16788647, + 26104111, + 31680326, + 31451990, + 24242679, + 10211804, + -8918761, + -29950124, + -48639991, + -60447884, + -61479641, + -49456713, + -24502884, + 10451268, + 49793943, + 85944939, + 110598215, + 116319371, + 98227457, + 55438648, + -8043315, + -83233969, + -156989711, + -213699577, + -237634268, + -215597131, + -139435040, + -7956647, + 172121897, + 386436641, + 614476184, + 832143987, + 1015012729, + 1141768318, + 1197293382, + 1174887882, + 1077260839, + 916128833, + 710487849, + 483844190, + 260858197, + 63942166, + -89653272, + -189828611, + -234435092, + -228827782, + -184324672, + -115896722, + -39520282, + 30351463, + 82797280, + 111637899, + 115729428, + 98391009, + 66162367, + 27183538, + -10476124, + -40240382, + -57980048, + -62389583, + -54796213, + -38514615, + -17929907, + 2481584, + 19000822, + 29242236, + 32387931, + 29086301, + 21085704, + 10715397, + 339295, + -8105599, + -13408417, + -15188511, + -13816387, + -10198866, + -5495912, + -839329, + 2888905, + 5183538, + 5939375, + 5386028, + 3965399, + 2189873, + 516204, + -740218, + -1439974, + -1606222, + -1376902, + -941437, + -480627, + -805485, + -1264997, + -1573189, + -1537513, + -998677, + 105201, + 1684346, + 3472379, + 5046349, + 5898310, + 5551849, + 3702636, + 350358, + -4115983, + -8913684, + -12963411, + -15086232, + -14272925, + -9973487, + -2338819, + 7655385, + 18257378, + 27184128, + 32042571, + 30861893, + 22633035, + 7731235, + -11897359, + -32870225, + -50850645, + -61329947, + -60587377, + -46646307, + -20017836, + 15963162, + 55346507, + 90361539, + 112723681, + 115262298, + 93588752, + 47479356, + -18335557, + -94205483, + -166512376, + -219473106, + -237556125, + -208140633, + -123969705, + 15049839, + 201063855, + 418710646, + 646788849, + 860945132, + 1036988523, + 1154316530, + 1198903822, + 1165365556, + 1057754877, + 888962385, + 678817148, + 451202931, + 230661341, + 39028183, + -107371492, + -199554513, + -236499541, + -224529950, + -175639859, + -105108031, + -28839808, + 39109504, + 88442916, + 113704027, + 114439887, + 94518072, + 60810851, + 21547643, + -15337429, + -43572146, + -59421519, + -61980038, + -52906902, + -35729583, + -14905050, + 5151728, + 20884518, + 30125596, + 32279941, + 28180417, + 19692130, + 9181848, + -1022383, + -9073390, + -13877127, + -15168908, + -13411383, + -9565560, + -4803751, + -233691, + 3311135, + 5383518, + 5931818, + 5224342, + 3721720, + 1935378, + 305977, + -875322, + -1494133, + -1593517, + -1322755, + -873443, + -421117 + +}; + +static const struct src_stage src_int32_7_40_2976_5000 = { + 17, 3, 7, 112, 784, 40, 7, 0, 2, + src_int32_7_40_2976_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_5_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_7_5_4535_5000.h new file mode 100644 index 000000000000..b4a29de3be84 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_5_4535_5000.h @@ -0,0 +1,830 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_5_4535_5000_fir[812] = { + -13317, + 26352, + -45392, + 71324, + -104675, + 145438, + -192882, + 245371, + -300200, + 353458, + -399944, + 433143, + -445288, + 427505, + -370072, + 262778, + -95393, + -141756, + 457116, + -857176, + 1345670, + -1922781, + 2584349, + -3321150, + 4118269, + -4954624, + 5802670, + -6628327, + 7391163, + -8044845, + 8537885, + -8814661, + 8816720, + -8484319, + 7758166, + -6581322, + 4901166, + -2671381, + -146159, + 3579669, + -7646025, + 12349703, + -17682235, + 23622265, + -30136380, + 37180890, + -44704832, + 52654647, + -60981316, + 69651465, + -78665476, + 88089238, + -98115188, + 109193870, + -122361396, + 140230961, + -171059131, + 259067564, + 2032047662, + -43247683, + -25620075, + 48925430, + -59574815, + 64557600, + -66304080, + 65919847, + -64013980, + 60977545, + -57094297, + 52589621, + -47653546, + 42451805, + -37131011, + 31820870, + -26634905, + 21670506, + -17008778, + 12714456, + -8836029, + 5406175, + -2442511, + -51324, + 2084303, + -3676397, + 4856788, + -5661966, + 6133785, + -6317545, + 6260168, + -6008520, + 5607922, + -5100894, + 4526144, + -3917826, + 3305051, + -2711657, + 2156197, + -1652140, + 1208234, + -828999, + 515322, + -265097, + 73888, + 64412, + -156973, + 211477, + -235640, + 236827, + -221755, + 196289, + -165321, + 132731, + -101399, + 73289, + -49553, + 30670, + -6621, + 16117, + -31829, + 55366, + -88218, + 131575, + -186123, + 251819, + -327658, + 411446, + -499596, + 586965, + -666748, + 730458, + -767990, + 767810, + -717255, + 602970, + -411472, + 129832, + 253530, + -747957, + 1359619, + -2090546, + 2937674, + -3891961, + 4937604, + -6051412, + 7202382, + -8351505, + 9451856, + -10448965, + 11281496, + -11882230, + 12179322, + -12097800, + 11561260, + -10493668, + 8821192, + -6473939, + 3387465, + 496107, + -5227570, + 10850987, + -17405276, + 24927567, + -33459180, + 43055611, + -53803078, + 65846371, + -79437676, + 95027437, + -113447487, + 136320702, + -167115391, + 214463830, + -306619781, + 616293167, + 1909795390, + -267379591, + 105200369, + -42522948, + 9170006, + 11196460, + -24410238, + 33094336, + -38626038, + 41821096, + -43214582, + 43189941, + -42043145, + 40016269, + -37315570, + 34121289, + -30592841, + 26871439, + -23081299, + 19330111, + -15709223, + 12293780, + -9143008, + 6300706, + -3796004, + 1644397, + 150982, + -1597871, + 2713240, + -3521539, + 4052922, + -4341487, + 4423597, + -4336338, + 4116140, + -3797608, + 3412578, + -2989400, + 2552460, + -2121927, + 1713692, + -1339504, + 1007242, + -721308, + 483107, + -291572, + 143707, + -35127, + -39443, + 85716, + -109453, + 116156, + -110827, + 97805, + -80682, + 62266, + -44606, + 29061, + 2690, + 1197, + -10416, + 27053, + -53342, + 91517, + -143624, + 211287, + -295453, + 396103, + -511968, + 640242, + -776334, + 913666, + -1043542, + 1155117, + -1235476, + 1269849, + -1241967, + 1134570, + -930073, + 611367, + -162759, + -428991, + 1173556, + -2075889, + 3135090, + -4343322, + 5684844, + -7135201, + 8660626, + -10217685, + 11753213, + -13204542, + 14500048, + -15559987, + 16297593, + -16620391, + 16431625, + -15631710, + 14119530, + -11793403, + 8551428, + -4290847, + -1094126, + 7716819, + -15706291, + 25221399, + -36474784, + 49774396, + -65598155, + 84736076, + -108582807, + 139806506, + -184116193, + 256035834, + -405755724, + 996566661, + 1678543116, + -401020313, + 202170065, + -118668323, + 71627453, + -41106127, + 19732170, + -4146991, + -7407527, + 15954344, + -22144503, + 26427455, + -29137504, + 30540177, + -30857966, + 30284804, + -28994129, + 27143179, + -24875064, + 22319546, + -19593123, + 16798787, + -14025719, + 11349087, + -8830036, + 6515948, + -4440963, + 2626795, + -1083778, + -187869, + 1196617, + -1958104, + 2493570, + -2828289, + 2990087, + -3007951, + 2910798, + -2726421, + 2480621, + -2196559, + 1894303, + -1590568, + 1298647, + -1028485, + 786895, + -577869, + 402964, + -261730, + 152152, + -71093, + 14695, + 21252, + -41002, + 48603, + -47711, + 41470, + -32444, + 22599, + 13098, + -16043, + 15546, + -9388, + -5050, + 30702, + -70668, + 128027, + -205589, + 305605, + -429438, + 577209, + -747441, + 936706, + -1139319, + 1347084, + -1549133, + 1731873, + -1879072, + 1972093, + -1990312, + 1911690, + -1713547, + 1373489, + -870489, + 186103, + 694232, + -1779852, + 3073514, + -4570103, + 6255442, + -8105272, + 10084434, + -12146312, + 14232548, + -16273069, + 18186393, + -19880211, + 21252170, + -22190770, + 22576234, + -22281149, + 21170587, + -19101288, + 15919283, + -11454983, + 5514157, + 2137891, + -11803853, + 23903022, + -39060306, + 58278636, + -83300205, + 117449391, + -167919522, + 253544619, + -443650197, + 1363083471, + 1363083471, + -443650197, + 253544619, + -167919522, + 117449391, + -83300205, + 58278636, + -39060306, + 23903022, + -11803853, + 2137891, + 5514157, + -11454983, + 15919283, + -19101288, + 21170587, + -22281149, + 22576234, + -22190770, + 21252170, + -19880211, + 18186393, + -16273069, + 14232548, + -12146312, + 10084434, + -8105272, + 6255442, + -4570103, + 3073514, + -1779852, + 694232, + 186103, + -870489, + 1373489, + -1713547, + 1911690, + -1990312, + 1972093, + -1879072, + 1731873, + -1549133, + 1347084, + -1139319, + 936706, + -747441, + 577209, + -429438, + 305605, + -205589, + 128027, + -70668, + 30702, + -5050, + -9388, + 15546, + -16043, + 13098, + 22599, + -32444, + 41470, + -47711, + 48603, + -41002, + 21252, + 14695, + -71093, + 152152, + -261730, + 402964, + -577869, + 786895, + -1028485, + 1298647, + -1590568, + 1894303, + -2196559, + 2480621, + -2726421, + 2910798, + -3007951, + 2990087, + -2828289, + 2493570, + -1958104, + 1196617, + -187869, + -1083778, + 2626795, + -4440963, + 6515948, + -8830036, + 11349087, + -14025719, + 16798787, + -19593123, + 22319546, + -24875064, + 27143179, + -28994129, + 30284804, + -30857966, + 30540177, + -29137504, + 26427455, + -22144503, + 15954344, + -7407527, + -4146991, + 19732170, + -41106127, + 71627453, + -118668323, + 202170065, + -401020313, + 1678543116, + 996566661, + -405755724, + 256035834, + -184116193, + 139806506, + -108582807, + 84736076, + -65598155, + 49774396, + -36474784, + 25221399, + -15706291, + 7716819, + -1094126, + -4290847, + 8551428, + -11793403, + 14119530, + -15631710, + 16431625, + -16620391, + 16297593, + -15559987, + 14500048, + -13204542, + 11753213, + -10217685, + 8660626, + -7135201, + 5684844, + -4343322, + 3135090, + -2075889, + 1173556, + -428991, + -162759, + 611367, + -930073, + 1134570, + -1241967, + 1269849, + -1235476, + 1155117, + -1043542, + 913666, + -776334, + 640242, + -511968, + 396103, + -295453, + 211287, + -143624, + 91517, + -53342, + 27053, + -10416, + 1197, + 2690, + 29061, + -44606, + 62266, + -80682, + 97805, + -110827, + 116156, + -109453, + 85716, + -39443, + -35127, + 143707, + -291572, + 483107, + -721308, + 1007242, + -1339504, + 1713692, + -2121927, + 2552460, + -2989400, + 3412578, + -3797608, + 4116140, + -4336338, + 4423597, + -4341487, + 4052922, + -3521539, + 2713240, + -1597871, + 150982, + 1644397, + -3796004, + 6300706, + -9143008, + 12293780, + -15709223, + 19330111, + -23081299, + 26871439, + -30592841, + 34121289, + -37315570, + 40016269, + -42043145, + 43189941, + -43214582, + 41821096, + -38626038, + 33094336, + -24410238, + 11196460, + 9170006, + -42522948, + 105200369, + -267379591, + 1909795390, + 616293167, + -306619781, + 214463830, + -167115391, + 136320702, + -113447487, + 95027437, + -79437676, + 65846371, + -53803078, + 43055611, + -33459180, + 24927567, + -17405276, + 10850987, + -5227570, + 496107, + 3387465, + -6473939, + 8821192, + -10493668, + 11561260, + -12097800, + 12179322, + -11882230, + 11281496, + -10448965, + 9451856, + -8351505, + 7202382, + -6051412, + 4937604, + -3891961, + 2937674, + -2090546, + 1359619, + -747957, + 253530, + 129832, + -411472, + 602970, + -717255, + 767810, + -767990, + 730458, + -666748, + 586965, + -499596, + 411446, + -327658, + 251819, + -186123, + 131575, + -88218, + 55366, + -31829, + 16117, + -6621, + 30670, + -49553, + 73289, + -101399, + 132731, + -165321, + 196289, + -221755, + 236827, + -235640, + 211477, + -156973, + 64412, + 73888, + -265097, + 515322, + -828999, + 1208234, + -1652140, + 2156197, + -2711657, + 3305051, + -3917826, + 4526144, + -5100894, + 5607922, + -6008520, + 6260168, + -6317545, + 6133785, + -5661966, + 4856788, + -3676397, + 2084303, + -51324, + -2442511, + 5406175, + -8836029, + 12714456, + -17008778, + 21670506, + -26634905, + 31820870, + -37131011, + 42451805, + -47653546, + 52589621, + -57094297, + 60977545, + -64013980, + 65919847, + -66304080, + 64557600, + -59574815, + 48925430, + -25620075, + -43247683, + 2032047662, + 259067564, + -171059131, + 140230961, + -122361396, + 109193870, + -98115188, + 88089238, + -78665476, + 69651465, + -60981316, + 52654647, + -44704832, + 37180890, + -30136380, + 23622265, + -17682235, + 12349703, + -7646025, + 3579669, + -146159, + -2671381, + 4901166, + -6581322, + 7758166, + -8484319, + 8816720, + -8814661, + 8537885, + -8044845, + 7391163, + -6628327, + 5802670, + -4954624, + 4118269, + -3321150, + 2584349, + -1922781, + 1345670, + -857176, + 457116, + -141756, + -95393, + 262778, + -370072, + 427505, + -445288, + 433143, + -399944, + 353458, + -300200, + 245371, + -192882, + 145438, + -104675, + 71324, + -45392, + 26352, + -13317 + +}; + +static const struct src_stage src_int32_7_5_4535_5000 = { + 2, 3, 7, 116, 812, 5, 7, 0, 0, + src_int32_7_5_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_8_1361_5000.h b/src/audio/src/coef/src_ipc4_int32_7_8_1361_5000.h new file mode 100644 index 000000000000..69fb97e904be --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_8_1361_5000.h @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_8_1361_5000_fir[140] = { + -165190, + 129875, + 4540182, + -5347695, + -21598007, + 37695221, + 52457996, + -153869901, + -70238332, + 711454789, + 1191755612, + 583050468, + -129395207, + -122270359, + 64798521, + 25224388, + -22375946, + -2173712, + 4033562, + -164025, + -249910, + 561699, + 4745738, + -8913968, + -18854167, + 49666445, + 33954532, + -179706502, + 6565282, + 833398023, + 1165300895, + 453137899, + -170653066, + -87713779, + 71095861, + 13176134, + -21488013, + 451315, + 3342982, + -332868, + -331264, + 1130048, + 4531934, + -12640016, + -13954519, + 60088546, + 9615292, + -196908423, + 99838143, + 944000026, + 1113540395, + 326491416, + -194629290, + -52788465, + 71848406, + 2299386, + -19303830, + 2445029, + 2574260, + -398943, + -389229, + 1814877, + 3791974, + -16223092, + -6857306, + 67848446, + -19740912, + -202709376, + 207474289, + 1038708192, + 1038708192, + 207474289, + -202709376, + -19740912, + 67848446, + -6857306, + -16223092, + 3791974, + 1814877, + -389229, + -398943, + 2574260, + 2445029, + -19303830, + 2299386, + 71848406, + -52788465, + -194629290, + 326491416, + 1113540395, + 944000026, + 99838143, + -196908423, + 9615292, + 60088546, + -13954519, + -12640016, + 4531934, + 1130048, + -331264, + -332868, + 3342982, + 451315, + -21488013, + 13176134, + 71095861, + -87713779, + -170653066, + 453137899, + 1165300895, + 833398023, + 6565282, + -179706502, + 33954532, + 49666445, + -18854167, + -8913968, + 4745738, + 561699, + -249910, + -164025, + 4033562, + -2173712, + -22375946, + 25224388, + 64798521, + -122270359, + -129395207, + 583050468, + 1191755612, + 711454789, + -70238332, + -153869901, + 52457996, + 37695221, + -21598007, + -5347695, + 4540182, + 129875, + -165190 + +}; + +static const struct src_stage src_int32_7_8_1361_5000 = { + 1, 1, 7, 20, 140, 8, 7, 0, 0, + src_int32_7_8_1361_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_8_2468_5000.h b/src/audio/src/coef/src_ipc4_int32_7_8_2468_5000.h new file mode 100644 index 000000000000..3ddeeb8c5fd7 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_8_2468_5000.h @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_8_2468_5000_fir[196] = { + -49360, + 723320, + -1199972, + -1878164, + 8399066, + -7353935, + -13158462, + 38337125, + -22577880, + -55879261, + 127350128, + -53286046, + -241360158, + 684117331, + 1398071396, + 505157133, + -273112819, + 4136654, + 107643419, + -68928421, + -5644203, + 33573706, + -17322895, + -3082637, + 7452746, + -2652237, + -605532, + 611594, + -5543, + 774864, + -1819733, + -726139, + 8657990, + -11591403, + -7107513, + 40062883, + -39471141, + -36024459, + 137561898, + -113617679, + -180654844, + 859343856, + 1357255322, + 330992223, + -277985424, + 54411031, + 81097654, + -74800872, + 9888023, + 26534208, + -19478071, + 842602, + 6011536, + -3044663, + -89464, + 468092, + 71520, + 738105, + -2395456, + 755903, + 8077148, + -15359203, + 500560, + 38188803, + -54712240, + -10415398, + 136170288, + -171812380, + -90638079, + 1022123445, + 1277838845, + 169447753, + -259508627, + 94332311, + 50646877, + -73767789, + 22853011, + 18090405, + -19693857, + 4125183, + 4284034, + -3089028, + 313979, + 318119, + 181532, + 589374, + -2846596, + 2472779, + 6567817, + -18202844, + 9135030, + 32432375, + -66654165, + 19237134, + 121863516, + -222329351, + 27189374, + 1164105694, + 1164105694, + 27189374, + -222329351, + 121863516, + 19237134, + -66654165, + 32432375, + 9135030, + -18202844, + 6567817, + 2472779, + -2846596, + 589374, + 181532, + 318119, + 313979, + -3089028, + 4284034, + 4125183, + -19693857, + 18090405, + 22853011, + -73767789, + 50646877, + 94332311, + -259508627, + 169447753, + 1277838845, + 1022123445, + -90638079, + -171812380, + 136170288, + -10415398, + -54712240, + 38188803, + 500560, + -15359203, + 8077148, + 755903, + -2395456, + 738105, + 71520, + 468092, + -89464, + -3044663, + 6011536, + 842602, + -19478071, + 26534208, + 9888023, + -74800872, + 81097654, + 54411031, + -277985424, + 330992223, + 1357255322, + 859343856, + -180654844, + -113617679, + 137561898, + -36024459, + -39471141, + 40062883, + -7107513, + -11591403, + 8657990, + -726139, + -1819733, + 774864, + -5543, + 611594, + -605532, + -2652237, + 7452746, + -3082637, + -17322895, + 33573706, + -5644203, + -68928421, + 107643419, + 4136654, + -273112819, + 505157133, + 1398071396, + 684117331, + -241360158, + -53286046, + 127350128, + -55879261, + -22577880, + 38337125, + -13158462, + -7353935, + 8399066, + -1878164, + -1199972, + 723320, + -49360 + +}; + +static const struct src_stage src_int32_7_8_2468_5000 = { + 1, 1, 7, 28, 196, 8, 7, 0, 0, + src_int32_7_8_2468_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_8_2721_5000.h b/src/audio/src/coef/src_ipc4_int32_7_8_2721_5000.h new file mode 100644 index 000000000000..4fbb3bb9491a --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_8_2721_5000.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_8_2721_5000_fir[224] = { + 65478, + 113869, + -1097521, + 1829291, + 866266, + -7694470, + 10757389, + 2132466, + -28727942, + 39406895, + 1122403, + -82516219, + 122072792, + -13838695, + -273108251, + 669400230, + 1445174397, + 478400702, + -294248389, + 45138414, + 92291582, + -88727305, + 20087885, + 28536497, + -29831234, + 7831532, + 7301445, + -7626331, + 2026281, + 1130161, + -1009135, + 196003, + 110398, + -17104, + -1073872, + 2473646, + -604424, + -6960118, + 13597645, + -4523268, + -24607039, + 47569695, + -19991916, + -67505728, + 143182098, + -79152663, + -220488382, + 858019422, + 1400377332, + 294566935, + -286930115, + 93498552, + 57317090, + -86434571, + 35412177, + 16210970, + -28137324, + 12162584, + 3625171, + -6873019, + 2813884, + 454239, + -841351, + 232438, + 159020, + -193445, + -912400, + 2975899, + -2277671, + -5375835, + 15437512, + -11572548, + -17531390, + 51908039, + -41391980, + -44228556, + 152585352, + -145412629, + -135287104, + 1034401108, + 1313345467, + 126526073, + -255751877, + 128296068, + 20734997, + -76659207, + 46073395, + 3690571, + -24100216, + 14887819, + 95662, + -5601113, + 3213054, + -136349, + -628791, + 231129, + 202812, + -403842, + -599134, + 3248265, + -4003645, + -2979821, + 15945858, + -18341009, + -7872950, + 51568142, + -60990481, + -14078680, + 148022065, + -206451678, + -18537749, + 1189024692, + 1189024692, + -18537749, + -206451678, + 148022065, + -14078680, + -60990481, + 51568142, + -7872950, + -18341009, + 15945858, + -2979821, + -4003645, + 3248265, + -599134, + -403842, + 202812, + 231129, + -628791, + -136349, + 3213054, + -5601113, + 95662, + 14887819, + -24100216, + 3690571, + 46073395, + -76659207, + 20734997, + 128296068, + -255751877, + 126526073, + 1313345467, + 1034401108, + -135287104, + -145412629, + 152585352, + -44228556, + -41391980, + 51908039, + -17531390, + -11572548, + 15437512, + -5375835, + -2277671, + 2975899, + -912400, + -193445, + 159020, + 232438, + -841351, + 454239, + 2813884, + -6873019, + 3625171, + 12162584, + -28137324, + 16210970, + 35412177, + -86434571, + 57317090, + 93498552, + -286930115, + 294566935, + 1400377332, + 858019422, + -220488382, + -79152663, + 143182098, + -67505728, + -19991916, + 47569695, + -24607039, + -4523268, + 13597645, + -6960118, + -604424, + 2473646, + -1073872, + -17104, + 110398, + 196003, + -1009135, + 1130161, + 2026281, + -7626331, + 7301445, + 7831532, + -29831234, + 28536497, + 20087885, + -88727305, + 92291582, + 45138414, + -294248389, + 478400702, + 1445174397, + 669400230, + -273108251, + -13838695, + 122072792, + -82516219, + 1122403, + 39406895, + -28727942, + 2132466, + 10757389, + -7694470, + 866266, + 1829291, + -1097521, + 113869, + 65478 + +}; + +static const struct src_stage src_int32_7_8_2721_5000 = { + 1, 1, 7, 32, 224, 8, 7, 0, 0, + src_int32_7_8_2721_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_7_8_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_7_8_4535_5000.h new file mode 100644 index 000000000000..0f0724ddba80 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_7_8_4535_5000.h @@ -0,0 +1,858 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_8_4535_5000_fir[840] = { + -9, + -30815, + 77572, + -124342, + 144997, + -111216, + 5229, + 166737, + -366122, + 524442, + -559406, + 402972, + -34030, + -495808, + 1055755, + -1457407, + 1504859, + -1063261, + 125958, + 1144585, + -2424010, + 3291876, + -3348363, + 2354427, + -353206, + -2273123, + 4845412, + -6537393, + 6608107, + -4658981, + 837279, + 4090983, + -8849034, + 11940639, + -12069336, + 8579430, + -1786001, + -6928754, + 15325686, + -20817708, + 21178434, + -15274717, + 3611002, + 11506087, + -26295241, + 36309391, + -37578361, + 27823713, + -7428440, + -20131394, + 48579201, + -69872114, + 75802835, + -59828013, + 18681485, + 46685116, + -131260891, + 227805179, + -332628647, + 478164225, + 1781266803, + 208471783, + -247690789, + 216259135, + -156591962, + 87288725, + -22200658, + -28470887, + 58876519, + -67871138, + 58559744, + -37080662, + 10916443, + 12867854, + -29067966, + 35180448, + -31521505, + 20687332, + -6566684, + -6801877, + 16234228, + -20043574, + 18216919, + -12149628, + 4069555, + 3658066, + -9150820, + 11407705, + -10418133, + 6998695, + -2443317, + -1891849, + 4949389, + -6191499, + 5646074, + -3795835, + 1367465, + 905024, + -2474479, + 3087777, + -2793341, + 1866076, + -686422, + -384075, + 1095593, + -1352080, + 1201577, + -788807, + 291838, + 135486, + -400133, + 479883, + -410278, + 258135, + -92996, + -34286, + 101124, + -111162, + 84508, + -45617, + -15590, + -9533, + 58352, + -120395, + 171263, + -177747, + 109518, + 45359, + -266608, + 496298, + -647249, + 626735, + -371192, + -118245, + 753027, + -1360165, + 1717713, + -1619313, + 952545, + 233400, + -1697911, + 3037733, + -3779550, + 3520608, + -2081123, + -380337, + 3336003, + -5972315, + 7385780, + -6851883, + 4095481, + 524152, + -5990353, + 10808286, + -13369999, + 12427472, + -7547561, + -594588, + 10203239, + -18685903, + 23276528, + -21825644, + 13553743, + 458184, + -17227127, + 32362633, + -41047154, + 39310448, + -25300169, + 213775, + 31393212, + -62074565, + 82698218, + -84144066, + 59066589, + -3139808, + -85044416, + 207313011, + -381411363, + 767720615, + 1698917233, + -23144426, + -141679990, + 177120970, + -159193041, + 113799759, + -58066590, + 5387348, + 34607418, + -56697914, + 60219612, + -48432272, + 27217567, + -3414320, + -16820401, + 29268917, + -32293892, + 26794747, + -15580039, + 2383077, + 9194363, + -16544433, + 18538590, + -15571009, + 9214604, + -1634228, + -5057338, + 9327457, + -10518117, + 8867494, + -5296527, + 1054159, + 2662560, + -5009319, + 5650196, + -4751805, + 2845810, + -620090, + -1292340, + 2469269, + -2768217, + 2306326, + -1374214, + 320705, + 553737, + -1067074, + 1177459, + -961143, + 562546, + -137130, + -194813, + 372644, + -396248, + 308948, + -172190, + 41848, + 46955, + -84084, + 79366, + -52601, + -31029, + 15718, + 28498, + -98367, + 174627, + -223380, + 205125, + -90349, + -122749, + 395349, + -647179, + 772464, + -671995, + 293982, + 329423, + -1065349, + 1695617, + -1968234, + 1676594, + -745515, + -704724, + 2344874, + -3691590, + 4229071, + -3572384, + 1627194, + 1308515, + -4547868, + 7146129, + -8144469, + 6871586, + -3218272, + -2208321, + 8123876, + -12825530, + 14631821, + -12402274, + 5991824, + 3510615, + -13870953, + 22158225, + -25482799, + 21857818, + -10954254, + -5485757, + 23751827, + -38840405, + 45608454, + -40169764, + 21203753, + 9168119, + -45204931, + 78172388, + -97658660, + 93221501, + -55724043, + -22825911, + 154238402, + -381206465, + 1055982975, + 1541078506, + -203003594, + -30186706, + 117878853, + -140287371, + 123482892, + -84341693, + 37067105, + 6569641, + -38198368, + 53610591, + -52815440, + 39312147, + -18760995, + -2613878, + 19513444, + -28625710, + 29073432, + -22225567, + 11004143, + 1076913, + -10869769, + 16313067, + -16771025, + 12963018, + -6562774, + -380935, + 6026675, + -9175637, + 9470484, + -7343862, + 3770601, + 79134, + -3177813, + 4881740, + -5028129, + 3887480, + -2009894, + 25997, + 1535347, + -2366247, + 2415623, + -1848275, + 953878, + -41366, + -648859, + 994149, + -994835, + 743835, + -377491, + 26199, + 220757, + -329310, + 314757, + -222828, + 106882, + -9340, + -47983, + 64004, + -51669, + -43849, + 41524, + -8565, + -59927, + 152761, + -239916, + 277565, + -221663, + 47361, + 231990, + -554478, + 815289, + -891658, + 683666, + -160139, + -606340, + 1431865, + -2052084, + 2191350, + -1655945, + 424688, + 1295692, + -3078875, + 4364173, + -4608498, + 3469699, + -967211, + -2438546, + 5892299, + -8327971, + 8760507, + -6614232, + 1990504, + 4222302, + -10462144, + 14837976, + -15643081, + 11911057, + -3852870, + -6978720, + 17895494, + -25655134, + 27312118, + -21137124, + 7352473, + 11555427, + -31103013, + 45675258, + -49850518, + 39905787, + -15145460, + -21291565, + 62380737, + -97951357, + 115978462, + -103808675, + 47908079, + 72378783, + -323028483, + 1320790300, + 1320790300, + -323028483, + 72378783, + 47908079, + -103808675, + 115978462, + -97951357, + 62380737, + -21291565, + -15145460, + 39905787, + -49850518, + 45675258, + -31103013, + 11555427, + 7352473, + -21137124, + 27312118, + -25655134, + 17895494, + -6978720, + -3852870, + 11911057, + -15643081, + 14837976, + -10462144, + 4222302, + 1990504, + -6614232, + 8760507, + -8327971, + 5892299, + -2438546, + -967211, + 3469699, + -4608498, + 4364173, + -3078875, + 1295692, + 424688, + -1655945, + 2191350, + -2052084, + 1431865, + -606340, + -160139, + 683666, + -891658, + 815289, + -554478, + 231990, + 47361, + -221663, + 277565, + -239916, + 152761, + -59927, + -8565, + 41524, + -43849, + -51669, + 64004, + -47983, + -9340, + 106882, + -222828, + 314757, + -329310, + 220757, + 26199, + -377491, + 743835, + -994835, + 994149, + -648859, + -41366, + 953878, + -1848275, + 2415623, + -2366247, + 1535347, + 25997, + -2009894, + 3887480, + -5028129, + 4881740, + -3177813, + 79134, + 3770601, + -7343862, + 9470484, + -9175637, + 6026675, + -380935, + -6562774, + 12963018, + -16771025, + 16313067, + -10869769, + 1076913, + 11004143, + -22225567, + 29073432, + -28625710, + 19513444, + -2613878, + -18760995, + 39312147, + -52815440, + 53610591, + -38198368, + 6569641, + 37067105, + -84341693, + 123482892, + -140287371, + 117878853, + -30186706, + -203003594, + 1541078506, + 1055982975, + -381206465, + 154238402, + -22825911, + -55724043, + 93221501, + -97658660, + 78172388, + -45204931, + 9168119, + 21203753, + -40169764, + 45608454, + -38840405, + 23751827, + -5485757, + -10954254, + 21857818, + -25482799, + 22158225, + -13870953, + 3510615, + 5991824, + -12402274, + 14631821, + -12825530, + 8123876, + -2208321, + -3218272, + 6871586, + -8144469, + 7146129, + -4547868, + 1308515, + 1627194, + -3572384, + 4229071, + -3691590, + 2344874, + -704724, + -745515, + 1676594, + -1968234, + 1695617, + -1065349, + 329423, + 293982, + -671995, + 772464, + -647179, + 395349, + -122749, + -90349, + 205125, + -223380, + 174627, + -98367, + 28498, + 15718, + -31029, + -52601, + 79366, + -84084, + 46955, + 41848, + -172190, + 308948, + -396248, + 372644, + -194813, + -137130, + 562546, + -961143, + 1177459, + -1067074, + 553737, + 320705, + -1374214, + 2306326, + -2768217, + 2469269, + -1292340, + -620090, + 2845810, + -4751805, + 5650196, + -5009319, + 2662560, + 1054159, + -5296527, + 8867494, + -10518117, + 9327457, + -5057338, + -1634228, + 9214604, + -15571009, + 18538590, + -16544433, + 9194363, + 2383077, + -15580039, + 26794747, + -32293892, + 29268917, + -16820401, + -3414320, + 27217567, + -48432272, + 60219612, + -56697914, + 34607418, + 5387348, + -58066590, + 113799759, + -159193041, + 177120970, + -141679990, + -23144426, + 1698917233, + 767720615, + -381411363, + 207313011, + -85044416, + -3139808, + 59066589, + -84144066, + 82698218, + -62074565, + 31393212, + 213775, + -25300169, + 39310448, + -41047154, + 32362633, + -17227127, + 458184, + 13553743, + -21825644, + 23276528, + -18685903, + 10203239, + -594588, + -7547561, + 12427472, + -13369999, + 10808286, + -5990353, + 524152, + 4095481, + -6851883, + 7385780, + -5972315, + 3336003, + -380337, + -2081123, + 3520608, + -3779550, + 3037733, + -1697911, + 233400, + 952545, + -1619313, + 1717713, + -1360165, + 753027, + -118245, + -371192, + 626735, + -647249, + 496298, + -266608, + 45359, + 109518, + -177747, + 171263, + -120395, + 58352, + -9533, + -15590, + -45617, + 84508, + -111162, + 101124, + -34286, + -92996, + 258135, + -410278, + 479883, + -400133, + 135486, + 291838, + -788807, + 1201577, + -1352080, + 1095593, + -384075, + -686422, + 1866076, + -2793341, + 3087777, + -2474479, + 905024, + 1367465, + -3795835, + 5646074, + -6191499, + 4949389, + -1891849, + -2443317, + 6998695, + -10418133, + 11407705, + -9150820, + 3658066, + 4069555, + -12149628, + 18216919, + -20043574, + 16234228, + -6801877, + -6566684, + 20687332, + -31521505, + 35180448, + -29067966, + 12867854, + 10916443, + -37080662, + 58559744, + -67871138, + 58876519, + -28470887, + -22200658, + 87288725, + -156591962, + 216259135, + -247690789, + 208471783, + 1781266803, + 478164225, + -332628647, + 227805179, + -131260891, + 46685116, + 18681485, + -59828013, + 75802835, + -69872114, + 48579201, + -20131394, + -7428440, + 27823713, + -37578361, + 36309391, + -26295241, + 11506087, + 3611002, + -15274717, + 21178434, + -20817708, + 15325686, + -6928754, + -1786001, + 8579430, + -12069336, + 11940639, + -8849034, + 4090983, + 837279, + -4658981, + 6608107, + -6537393, + 4845412, + -2273123, + -353206, + 2354427, + -3348363, + 3291876, + -2424010, + 1144585, + 125958, + -1063261, + 1504859, + -1457407, + 1055755, + -495808, + -34030, + 402972, + -559406, + 524442, + -366122, + 166737, + 5229, + -111216, + 144997, + -124342, + 77572, + -30815, + -9 + +}; + +static const struct src_stage src_int32_7_8_4535_5000 = { + 1, 1, 7, 120, 840, 8, 7, 0, 0, + src_int32_7_8_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_21_2160_5000.h b/src/audio/src/coef/src_ipc4_int32_8_21_2160_5000.h new file mode 100644 index 000000000000..c82054dd4455 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_21_2160_5000.h @@ -0,0 +1,402 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_21_2160_5000_fir[384] = { + 401690, + 667023, + -90063, + -2274139, + -4405383, + -3299853, + 3149445, + 12229343, + 15746348, + 5427982, + -17879380, + -39116257, + -35878012, + 3310792, + 61719581, + 95372246, + 59826450, + -50026909, + -176088306, + -214411763, + -73383313, + 259564242, + 688575367, + 1044594196, + 1171068926, + 1010096217, + 635189669, + 209748392, + -102289885, + -218072539, + -162821531, + -33610823, + 68804652, + 94256568, + 54710489, + -3299369, + -38235719, + -37357702, + -14643635, + 7579872, + 15943280, + 11195421, + 2082965, + -3720140, + -4244964, + -1951521, + 88169, + 669423, + 455891, + 648050, + -293285, + -2598645, + -4514095, + -2789343, + 4265247, + 13177283, + 15320869, + 3052631, + -21094512, + -40478387, + -32919039, + 10261223, + 68345203, + 95353491, + 49598365, + -66762965, + -187970276, + -207840382, + -41326750, + 310984635, + 740804738, + 1075368998, + 1166394989, + 972131270, + 581015273, + 161818902, + -127979441, + -218962948, + -148397344, + -17686548, + 76493282, + 92078957, + 47422566, + -9507076, + -39996585, + -35247663, + -11429488, + 9494956, + 15924643, + 10095629, + 1076662, + -4051840, + -4040045, + -1635781, + 241127, + 657368, + 508020, + 610495, + -520690, + -2919506, + -4564099, + -2188281, + 5417897, + 14018905, + 14656251, + 471173, + -24244476, + -41401817, + -29362062, + 17481889, + 74481948, + 94138062, + 38177371, + -83634067, + -198242599, + -198239092, + -6216610, + 363707573, + 791513156, + 1102190898, + 1157082555, + 930979656, + 526419555, + 116035293, + -150414190, + -217242162, + -133043338, + -2411597, + 82869574, + 88920832, + 39958450, + -15258371, + -41172267, + -32833015, + -8276373, + 11163850, + 15705473, + 8949592, + 139720, + -4297772, + -3797901, + -1331332, + 369014, + 633037, + 556249, + 552511, + -770907, + -3230696, + -4548730, + -1497755, + 6593369, + 14733947, + 13744600, + -2295015, + -27282847, + -41847658, + -25218412, + 24895401, + 80024929, + 91675263, + 25637909, + -100443629, + -206685390, + -185511372, + 31821444, + 417413214, + 840342255, + 1124858807, + 1143202167, + 886943159, + 471766432, + 72632933, + -169585137, + -213086144, + -116985020, + 12071874, + 87927139, + 84871137, + 32417632, + -20507771, + -41781131, + -30161864, + -5220594, + 12581014, + 15302529, + 7776195, + -720361, + -4461806, + -3525763, + -1041978, + 472468, + 598613, + 598613, + 472468, + -1041978, + -3525763, + -4461806, + -720361, + 7776195, + 15302529, + 12581014, + -5220594, + -30161864, + -41781131, + -20507771, + 32417632, + 84871137, + 87927139, + 12071874, + -116985020, + -213086144, + -169585137, + 72632933, + 471766432, + 886943159, + 1143202167, + 1124858807, + 840342255, + 417413214, + 31821444, + -185511372, + -206685390, + -100443629, + 25637909, + 91675263, + 80024929, + 24895401, + -25218412, + -41847658, + -27282847, + -2295015, + 13744600, + 14733947, + 6593369, + -1497755, + -4548730, + -3230696, + -770907, + 552511, + 556249, + 633037, + 369014, + -1331332, + -3797901, + -4297772, + 139720, + 8949592, + 15705473, + 11163850, + -8276373, + -32833015, + -41172267, + -15258371, + 39958450, + 88920832, + 82869574, + -2411597, + -133043338, + -217242162, + -150414190, + 116035293, + 526419555, + 930979656, + 1157082555, + 1102190898, + 791513156, + 363707573, + -6216610, + -198239092, + -198242599, + -83634067, + 38177371, + 94138062, + 74481948, + 17481889, + -29362062, + -41401817, + -24244476, + 471173, + 14656251, + 14018905, + 5417897, + -2188281, + -4564099, + -2919506, + -520690, + 610495, + 508020, + 657368, + 241127, + -1635781, + -4040045, + -4051840, + 1076662, + 10095629, + 15924643, + 9494956, + -11429488, + -35247663, + -39996585, + -9507076, + 47422566, + 92078957, + 76493282, + -17686548, + -148397344, + -218962948, + -127979441, + 161818902, + 581015273, + 972131270, + 1166394989, + 1075368998, + 740804738, + 310984635, + -41326750, + -207840382, + -187970276, + -66762965, + 49598365, + 95353491, + 68345203, + 10261223, + -32919039, + -40478387, + -21094512, + 3052631, + 15320869, + 13177283, + 4265247, + -2789343, + -4514095, + -2598645, + -293285, + 648050, + 455891, + 669423, + 88169, + -1951521, + -4244964, + -3720140, + 2082965, + 11195421, + 15943280, + 7579872, + -14643635, + -37357702, + -38235719, + -3299369, + 54710489, + 94256568, + 68804652, + -33610823, + -162821531, + -218072539, + -102289885, + 209748392, + 635189669, + 1010096217, + 1171068926, + 1044594196, + 688575367, + 259564242, + -73383313, + -214411763, + -176088306, + -50026909, + 59826450, + 95372246, + 61719581, + 3310792, + -35878012, + -39116257, + -17879380, + 5427982, + 15746348, + 12229343, + 3149445, + -3299853, + -4405383, + -2274139, + -90063, + 667023, + 401690 + +}; + +static const struct src_stage src_int32_8_21_2160_5000 = { + 13, 5, 8, 48, 384, 21, 8, 0, 1, + src_int32_8_21_2160_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_21_3239_5000.h b/src/audio/src/coef/src_ipc4_int32_8_21_3239_5000.h new file mode 100644 index 000000000000..c58c41ad824e --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_21_3239_5000.h @@ -0,0 +1,562 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_21_3239_5000_fir[544] = { + 214310, + 401153, + 58758, + -920479, + -1608501, + -611677, + 2139211, + 4232496, + 2386490, + -3665158, + -8942025, + -6536797, + 4814397, + 16287484, + 14639177, + -4231976, + -26502776, + -28696388, + -315562, + 39355894, + 51320385, + 12339476, + -54139118, + -86639973, + -37921667, + 69930064, + 143936075, + 91007957, + -86556943, + -255333423, + -224398155, + 110165447, + 658318671, + 1161291397, + 1347278452, + 1111160556, + 586029355, + 52783615, + -244371558, + -241453328, + -61038519, + 105804708, + 140287368, + 55985140, + -48525957, + -86552636, + -46292543, + 19699696, + 52510265, + 35092428, + -5171448, + -30136373, + -24356293, + -1237814, + 15866016, + 15327139, + 3119457, + -7395733, + -8582150, + -2804278, + 2891880, + 4130828, + 1760339, + -854036, + -1590426, + -784955, + 143060, + 396357, + 248054, + 397168, + -37061, + -1052324, + -1598462, + -338177, + 2509431, + 4268477, + 1807550, + -4517336, + -9174109, + -5523134, + 6518608, + 17030292, + 13116877, + -7294670, + -28317993, + -26735220, + 4747285, + 43165689, + 49266935, + 4491965, + -61437604, + -85359133, + -26288077, + 83351755, + 145467959, + 74074248, + -112026107, + -265974734, + -199406404, + 171126466, + 729923693, + 1206234776, + 1340346289, + 1056306279, + 513668529, + -651450, + -259393204, + -224708211, + -35841035, + 118342677, + 134664527, + 41746927, + -57980796, + -85150555, + -38038176, + 26478531, + 52851378, + 30458591, + -9753570, + -31054094, + -21925841, + 1644038, + 16791464, + 14174585, + 1460178, + -8094193, + -8107155, + -1949133, + 3319891, + 3969388, + 1379806, + -1063389, + -1546842, + -648604, + 215321, + 383891, + 281079, + 383389, + -143564, + -1177454, + -1558048, + -36139, + 2863671, + 4233658, + 1160439, + -5345680, + -9267232, + -4363439, + 8204213, + 17532657, + 11310228, + -10379031, + -29758032, + -24262483, + 9944217, + 46442482, + 46348344, + -3737335, + -68050919, + -82676050, + -13766103, + 96018929, + 144766275, + 55162523, + -137058346, + -273026339, + -169383146, + 235251805, + 800227273, + 1245572332, + 1326547603, + 997232998, + 441838049, + -49822558, + -269580933, + -205489463, + -11313167, + 128537354, + 127233169, + 27440731, + -66187804, + -82505018, + -29517276, + 32594318, + 52371039, + 25540212, + -14002012, + -31456676, + -19261215, + 4373455, + 17414639, + 12857046, + -138900, + -8629321, + -7530924, + -1113260, + 3668213, + 3754739, + 1004169, + -1238593, + -1480626, + -514058, + 275314, + 364927, + 312327, + 358935, + -259598, + -1292709, + -1485414, + 291096, + 3194386, + 4123867, + 452075, + -6134593, + -9212000, + -3069348, + 9842252, + 17774592, + 9235574, + -13435756, + -30783231, + -21296510, + 15197222, + 49112352, + 42576808, + -12232750, + -73847472, + -78577288, + -516048, + 107702396, + 141742991, + 34468129, + -161252933, + -276165218, + -134370218, + 302083039, + 868614585, + 1278936142, + 1306012919, + 934479844, + 371122486, + -94465377, + -275101086, + -184200796, + 12221586, + 136341228, + 118178596, + 13284104, + -73071036, + -78703443, + -20869887, + 37978625, + 51108188, + 20424215, + -17864417, + -31359015, + -16413813, + 6914450, + 17739505, + 11403121, + -1655394, + -9001057, + -6868261, + -309115, + 3936014, + 3493938, + 639455, + -1379199, + -1394849, + -383692, + 323085, + 340670, + 340670, + 323085, + -383692, + -1394849, + -1379199, + 639455, + 3493938, + 3936014, + -309115, + -6868261, + -9001057, + -1655394, + 11403121, + 17739505, + 6914450, + -16413813, + -31359015, + -17864417, + 20424215, + 51108188, + 37978625, + -20869887, + -78703443, + -73071036, + 13284104, + 118178596, + 136341228, + 12221586, + -184200796, + -275101086, + -94465377, + 371122486, + 934479844, + 1306012919, + 1278936142, + 868614585, + 302083039, + -134370218, + -276165218, + -161252933, + 34468129, + 141742991, + 107702396, + -516048, + -78577288, + -73847472, + -12232750, + 42576808, + 49112352, + 15197222, + -21296510, + -30783231, + -13435756, + 9235574, + 17774592, + 9842252, + -3069348, + -9212000, + -6134593, + 452075, + 4123867, + 3194386, + 291096, + -1485414, + -1292709, + -259598, + 358935, + 312327, + 364927, + 275314, + -514058, + -1480626, + -1238593, + 1004169, + 3754739, + 3668213, + -1113260, + -7530924, + -8629321, + -138900, + 12857046, + 17414639, + 4373455, + -19261215, + -31456676, + -14002012, + 25540212, + 52371039, + 32594318, + -29517276, + -82505018, + -66187804, + 27440731, + 127233169, + 128537354, + -11313167, + -205489463, + -269580933, + -49822558, + 441838049, + 997232998, + 1326547603, + 1245572332, + 800227273, + 235251805, + -169383146, + -273026339, + -137058346, + 55162523, + 144766275, + 96018929, + -13766103, + -82676050, + -68050919, + -3737335, + 46348344, + 46442482, + 9944217, + -24262483, + -29758032, + -10379031, + 11310228, + 17532657, + 8204213, + -4363439, + -9267232, + -5345680, + 1160439, + 4233658, + 2863671, + -36139, + -1558048, + -1177454, + -143564, + 383389, + 281079, + 383891, + 215321, + -648604, + -1546842, + -1063389, + 1379806, + 3969388, + 3319891, + -1949133, + -8107155, + -8094193, + 1460178, + 14174585, + 16791464, + 1644038, + -21925841, + -31054094, + -9753570, + 30458591, + 52851378, + 26478531, + -38038176, + -85150555, + -57980796, + 41746927, + 134664527, + 118342677, + -35841035, + -224708211, + -259393204, + -651450, + 513668529, + 1056306279, + 1340346289, + 1206234776, + 729923693, + 171126466, + -199406404, + -265974734, + -112026107, + 74074248, + 145467959, + 83351755, + -26288077, + -85359133, + -61437604, + 4491965, + 49266935, + 43165689, + 4747285, + -26735220, + -28317993, + -7294670, + 13116877, + 17030292, + 6518608, + -5523134, + -9174109, + -4517336, + 1807550, + 4268477, + 2509431, + -338177, + -1598462, + -1052324, + -37061, + 397168, + 248054, + 396357, + 143060, + -784955, + -1590426, + -854036, + 1760339, + 4130828, + 2891880, + -2804278, + -8582150, + -7395733, + 3119457, + 15327139, + 15866016, + -1237814, + -24356293, + -30136373, + -5171448, + 35092428, + 52510265, + 19699696, + -46292543, + -86552636, + -48525957, + 55985140, + 140287368, + 105804708, + -61038519, + -241453328, + -244371558, + 52783615, + 586029355, + 1111160556, + 1347278452, + 1161291397, + 658318671, + 110165447, + -224398155, + -255333423, + -86556943, + 91007957, + 143936075, + 69930064, + -37921667, + -86639973, + -54139118, + 12339476, + 51320385, + 39355894, + -315562, + -28696388, + -26502776, + -4231976, + 14639177, + 16287484, + 4814397, + -6536797, + -8942025, + -3665158, + 2386490, + 4232496, + 2139211, + -611677, + -1608501, + -920479, + 58758, + 401153, + 214310 + +}; + +static const struct src_stage src_int32_8_21_3239_5000 = { + 13, 5, 8, 68, 544, 21, 8, 0, 1, + src_int32_8_21_3239_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_21_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_8_21_4535_5000.h new file mode 100644 index 000000000000..2090c8a2e429 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_21_4535_5000.h @@ -0,0 +1,2002 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_21_4535_5000_fir[1984] = { + -4705, + 81658, + 87540, + -28233, + -146587, + -102848, + 94954, + 223275, + 88276, + -200557, + -297721, + -26453, + 343432, + 348822, + -98288, + -512640, + -349730, + 295914, + 686152, + 270825, + -566342, + -830576, + -84268, + 895412, + 902858, + -230191, + -1251997, + -854261, + 678791, + 1587074, + 636625, + -1247593, + -1835470, + -210511, + 1897669, + 1920752, + -445526, + -2562750, + -1763349, + 1325669, + 3150360, + 1291522, + -2388975, + -3547153, + -454294, + 3554409, + 3628743, + -765030, + -4700185, + -3273710, + 2336492, + 5668523, + 2380851, + -4174207, + -6276415, + -888111, + 6132075, + 6332305, + -1208886, + -8006107, + -5657815, + 3841116, + 9544408, + 4112871, + -6855702, + -10465107, + -1621865, + 10012940, + 10481609, + -1801941, + -12992466, + -9333561, + 6036806, + 15409348, + 6821096, + -10840496, + -16839869, + -2839217, + 15848146, + 16855585, + -2591131, + -20581299, + -15063167, + 9298628, + 24468169, + 11146563, + -16946541, + -26873655, + -4907467, + 25028641, + 27135911, + -3700180, + -32875824, + -24604413, + 14545533, + 39670614, + 18672130, + -27309081, + -44462731, + -8791091, + 41485372, + 46172252, + -5545817, + -56399651, + -43553272, + 24889047, + 71234502, + 35058023, + -50055816, + -85056214, + -18446567, + 82694519, + 96813687, + -10340489, + -126873020, + -105219459, + 60971656, + 194734355, + 108077111, + -166438970, + -337823125, + -97105500, + 565430224, + 1278815852, + 1558747996, + 1204676795, + 469472916, + -154121315, + -334397260, + -130208035, + 132776897, + 187566243, + 37188941, + -117740536, + -117567740, + 6955898, + 102473868, + 72592953, + -31096227, + -86267719, + -40073396, + 43937593, + 69462298, + 15667820, + -49254537, + -52697465, + 2474951, + 49204930, + 36677276, + -15341149, + -45319086, + -22055854, + 23628422, + 38838887, + 9368924, + -27970986, + -30832366, + 1007541, + 29021850, + 22221657, + -8877061, + -27468453, + -13778212, + 14223385, + 24015448, + 6109528, + -17194876, + -19352450, + 350732, + 18075870, + 14117707, + -5343615, + -17249095, + -8864885, + 8774799, + 15153586, + 4037701, + -10694081, + -12242559, + 44924, + 11266516, + 8945211, + -3192265, + -10738331, + -5635639, + 5334338, + 9401087, + 2610982, + -6505339, + -7557523, + -79720, + 6820586, + 5492000, + -1840088, + -6449957, + -3447696, + 3113851, + 5590868, + 1611756, + -3776751, + -4443493, + -108624, + 3915734, + 3190357, + -999102, + -3649722, + -1981639, + 1703653, + 3110409, + 926758, + -2040731, + -2425583, + -91991, + 2075827, + 1706314, + -496719, + -1890155, + -1038700, + 847077, + 1567858, + 480228, + -991392, + -1185707, + -60245, + 976710, + 805997, + -216365, + -855457, + -472824, + 363400, + 677642, + 211485, + -406636, + -485242, + -30392, + 377239, + 309004, + -75305, + -306140, + -167541, + 119260, + 219877, + 68302, + -119426, + -138141, + -9854, + 94139, + 72962, + 6392, + 88995, + 78792, + -46735, + -152243, + -83526, + 120492, + 222099, + 54512, + -230339, + -282861, + 24258, + 371611, + 312449, + -165793, + -530057, + -284277, + 376101, + 680656, + 170690, + -650094, + -788045, + 52176, + 968085, + 808994, + -398543, + -1293699, + -697095, + 866852, + 1573960, + 409528, + -1434289, + -1742156, + 84611, + 2053044, + 1723809, + -795313, + -2649354, + -1445650, + 1703200, + 3126231, + 847032, + -2753012, + -3370406, + 107273, + 3850487, + 3263533, + -1414390, + -4863878, + -2697114, + 3022561, + 5631016, + 1589964, + -4824155, + -5972212, + 93532, + 6654230, + 5708595, + -2326540, + -8296014, + -4684717, + 5006692, + 9494023, + 2793494, + -7949112, + -9974728, + -972, + 10887521, + 9473731, + -3631955, + -13484702, + -7767536, + 7933810, + 15352688, + 4707157, + -12615337, + -16081957, + -250342, + 17272757, + 15277789, + -5511013, + -21402285, + -12600944, + 12331375, + 24425410, + 7809014, + -19802325, + -25722953, + -794445, + 27354536, + 24674261, + -8384709, + -34269980, + -20696202, + 19484554, + 39700656, + 13274612, + -32067581, + -42685970, + -1977864, + 45507029, + 42153839, + -13563520, + -58999496, + -36875983, + 33741236, + 71574948, + 25311822, + -59186091, + -82076952, + -5170671, + 91307971, + 89036036, + -27843935, + -133811262, + -90160591, + 84275390, + 198137273, + 80053826, + -201098458, + -334379689, + -32940436, + 662354072, + 1345773156, + 1548183654, + 1124237846, + 375501026, + -203638483, + -324582476, + -93158102, + 153819623, + 176906451, + 13407223, + -127549239, + -106140280, + 23706745, + 105950111, + 61235168, + -42878701, + -85719114, + -29453593, + 51786439, + 66316322, + 6268523, + -53879178, + -47982902, + 10337161, + 51203743, + 31189788, + -21499213, + -45249041, + -16419878, + 28048630, + 37231577, + 4062006, + -30734015, + -28188129, + 5643058, + 30300236, + 18995534, + -12624505, + -27501247, + -10364724, + 16980000, + 23081608, + 2830226, + -18956400, + -17744856, + 3254824, + 18917677, + 12119646, + -7713736, + -17304998, + -6730591, + 10530407, + 14593872, + 1978038, + -11823739, + -11252911, + 1871072, + 11814967, + 7708042, + -4680930, + -10791250, + -4315023, + 6434255, + 9069135, + 1341925, + -7211559, + -6961167, + 1037960, + 7165137, + 4748357, + -2743475, + -6490897, + -2660265, + 3774830, + 5401053, + 863517, + -4196982, + -4100196, + 541440, + 4119720, + 2766607, + -1516343, + -3677047, + -1539852, + 2075531, + 3008098, + 514854, + -2272765, + -2241382, + 258074, + 2186531, + 1483415, + -768354, + -1905721, + -812205, + 1036892, + 1517246, + 275371, + -1106058, + -1096613, + 107820, + 1029424, + 701972, + -341518, + -862530, + -371636, + 446695, + 655594, + 124620, + -454028, + -448648, + 36504, + 397315, + 269184, + -121350, + -308121, + -132056, + 146912, + 212114, + 41118, + -133008, + -127179, + 8025, + 98536, + 63148, + 17900, + 94751, + 67996, + -64966, + -154888, + -61774, + 144338, + 216231, + 18595, + -256168, + -261693, + 75817, + 392790, + 268679, + -231490, + -536896, + -211442, + 450286, + 660963, + 64913, + -722145, + -728387, + 190231, + 1022192, + 696681, + -561794, + -1309508, + -522780, + 1040350, + 1528232, + 170184, + -1594577, + -1611506, + 382714, + 2168677, + 1488401, + -1134100, + -2682855, + -1093566, + 2051278, + 3037597, + 378854, + -3065667, + -3122084, + 674298, + 4071598, + 2826557, + -2043290, + -4930007, + -2057845, + 3655404, + 5477671, + 756684, + -5383277, + -5541994, + 1085082, + 7046359, + 4960636, + -3409653, + -8419462, + -3604529, + 6083103, + 9248771, + 1402119, + -8892072, + -9274822, + 1637794, + 11548941, + 8261082, + -5407491, + -13706421, + -6025842, + 9688814, + 14981441, + 2474520, + -14150982, + -14987176, + 2370958, + 18359188, + 13370978, + -8348981, + -21794321, + -9855054, + 15144115, + 23882779, + 4276176, + -22283842, + -24033873, + 3379503, + 29146546, + 21680849, + -12950056, + -34979024, + -16320026, + 24082320, + 38918970, + 7540863, + -36228109, + -40013642, + 4962710, + 48649842, + 37218555, + -21414375, + -60428207, + -29344609, + 42038021, + 70453830, + 14883401, + -67263013, + -77357958, + 8473162, + 98226662, + 79251504, + -45203686, + -138178493, + -72793896, + 106614198, + 197564492, + 49117307, + -233425589, + -323670750, + 37914734, + 759191516, + 1404746936, + 1527184009, + 1038448307, + 284485726, + -245419954, + -308933738, + -56021421, + 170951491, + 163084521, + -9908237, + -134528200, + -92870683, + 39592117, + 107220424, + 48873256, + -53574812, + -83452948, + -18420233, + 58463725, + 61881153, + -3117160, + -57349639, + -42365002, + 17884556, + 52141981, + 25142256, + -27145962, + -44265340, + -10519501, + 31849823, + 34890124, + -1266540, + -32844471, + -25003228, + 10113477, + 30951846, + 15420017, + -16076411, + -26977359, + -6777706, + 19364029, + 21690593, + -471998, + -20315970, + -15794993, + 6062777, + 19367917, + 9897187, + -9903018, + -17010141, + -4482473, + 12054467, + 13744737, + -99850, + -12702121, + -10046112, + 3639758, + 12118407, + 6328318, + -6058613, + -10625213, + -2921705, + 7391705, + 8557388, + 60081, + -7763788, + -6230813, + 2121657, + 7360662, + 3917428, + -3580558, + -6400002, + -1828602, + 4351290, + 5104317, + 107222, + -4526945, + -3678358, + 1172082, + 4237664, + 2292539, + -1995914, + -3629604, + -1073042, + 2400188, + 2846389, + 98490, + -2455416, + -2014577, + 597628, + 2251301, + 1233979, + -1020142, + -1882481, + -572988, + 1202568, + 1436796, + 68479, + -1196329, + -986928, + 270629, + 1060324, + 585725, + -457323, + -852007, + -264987, + 519209, + 620747, + 37139, + -491158, + -403816, + 101063, + 408845, + 224921, + -163722, + -303796, + -94897, + 170762, + 200279, + 13978, + -143416, + -114017, + 25052, + 100731, + 52471, + 29585, + 98729, + 55301, + -82524, + -154356, + -37974, + 165931, + 205651, + -18780, + -277390, + -234490, + 127168, + 406347, + 218243, + -293968, + -532768, + -132571, + 516796, + 627177, + -44432, + -780760, + -652494, + 327073, + 1056257, + 567892, + -716479, + -1298628, + -334609, + 1195453, + 1450275, + -76680, + -1724717, + -1445604, + 677709, + 2241561, + 1218775, + -1454751, + -2661766, + -713829, + 2362323, + 2885352, + -103730, + -3319801, + -2806300, + 1235215, + 4212195, + 2325829, + -2638556, + -4895950, + -1368211, + 4221368, + 5210180, + -102430, + -5838997, + -4993046, + 2066339, + 7298877, + 4102284, + -4435631, + -8371994, + -2438142, + 7047290, + 8811466, + -33577, + -9663598, + -8377397, + 3261089, + 11981331, + 6866249, + -7091625, + -13650173, + -4142229, + 11264400, + 14299853, + 167594, + -15413493, + -13574360, + 4971419, + 19081658, + 11170675, + -11046147, + -21744868, + -6878635, + 17677018, + 22846056, + 618181, + -24336355, + -21835127, + 7529732, + 30362199, + 18210971, + -17301599, + -34980726, + -11559947, + 28240928, + 37331955, + 1583990, + -39698360, + -36489160, + 11890482, + 50838115, + 31454866, + -28935739, + -60639854, + -21100266, + 49601479, + 67870571, + 3974096, + -74103220, + -70963024, + 22214139, + 103273839, + 67613553, + -62063377, + -139816674, + -53401794, + 127505274, + 192874564, + 15750072, + -262663155, + -305392737, + 114895441, + 854869851, + 1455027056, + 1496005264, + 948311365, + 197337702, + -279341880, + -288070054, + -19498930, + 184000082, + 146478248, + -32315147, + -138617977, + -78067946, + 54316412, + 106306795, + 35774160, + -62991072, + -79545204, + -7201616, + 63854298, + 56265864, + -12300665, + -59612631, + -35969430, + 24969306, + 52014614, + 18663777, + -32173857, + -42398979, + -4476988, + 34962524, + 31870303, + -6508829, + -34267049, + -21348025, + 14330263, + 30970331, + 11571164, + -19166151, + -25913308, + -3091538, + 21331180, + 19875340, + -3730101, + -21250280, + -13545881, + 8718780, + 19421561, + 7497643, + -11869045, + -16374159, + -2167224, + 13318566, + 12626421, + -2153712, + -13314118, + -8648911, + 5315795, + 12173338, + 4835517, + -7298635, + -10245988, + -1484697, + 8188893, + 7878229, + -1208453, + -8152601, + -5382792, + 3149823, + 7404949, + 3017071, + -4335180, + -6180705, + -970086, + 4832597, + 4708000, + -641712, + -4761108, + -3187535, + 1770781, + 4268312, + 1778426, + -2428609, + -3509377, + -591009, + 2671712, + 2629402, + -313835, + -2585706, + -1750397, + 919952, + 2269529, + 963473, + -1247297, + -1821532, + -326103, + 1341148, + 1328644, + -136218, + -1260803, + -859246, + 424978, + 1069191, + 459846, + -561613, + -824450, + -155154, + 579695, + 574080, + -49167, + -517502, + -351849, + 162028, + 411806, + 177229, + -201654, + -293427, + -56871, + 190434, + 184740, + -12561, + -150544, + -99006, + 40905, + 100765, + 41196, + 41196, + 100765, + 40905, + -99006, + -150544, + -12561, + 184740, + 190434, + -56871, + -293427, + -201654, + 177229, + 411806, + 162028, + -351849, + -517502, + -49167, + 574080, + 579695, + -155154, + -824450, + -561613, + 459846, + 1069191, + 424978, + -859246, + -1260803, + -136218, + 1328644, + 1341148, + -326103, + -1821532, + -1247297, + 963473, + 2269529, + 919952, + -1750397, + -2585706, + -313835, + 2629402, + 2671712, + -591009, + -3509377, + -2428609, + 1778426, + 4268312, + 1770781, + -3187535, + -4761108, + -641712, + 4708000, + 4832597, + -970086, + -6180705, + -4335180, + 3017071, + 7404949, + 3149823, + -5382792, + -8152601, + -1208453, + 7878229, + 8188893, + -1484697, + -10245988, + -7298635, + 4835517, + 12173338, + 5315795, + -8648911, + -13314118, + -2153712, + 12626421, + 13318566, + -2167224, + -16374159, + -11869045, + 7497643, + 19421561, + 8718780, + -13545881, + -21250280, + -3730101, + 19875340, + 21331180, + -3091538, + -25913308, + -19166151, + 11571164, + 30970331, + 14330263, + -21348025, + -34267049, + -6508829, + 31870303, + 34962524, + -4476988, + -42398979, + -32173857, + 18663777, + 52014614, + 24969306, + -35969430, + -59612631, + -12300665, + 56265864, + 63854298, + -7201616, + -79545204, + -62991072, + 35774160, + 106306795, + 54316412, + -78067946, + -138617977, + -32315147, + 146478248, + 184000082, + -19498930, + -288070054, + -279341880, + 197337702, + 948311365, + 1496005264, + 1455027056, + 854869851, + 114895441, + -305392737, + -262663155, + 15750072, + 192874564, + 127505274, + -53401794, + -139816674, + -62063377, + 67613553, + 103273839, + 22214139, + -70963024, + -74103220, + 3974096, + 67870571, + 49601479, + -21100266, + -60639854, + -28935739, + 31454866, + 50838115, + 11890482, + -36489160, + -39698360, + 1583990, + 37331955, + 28240928, + -11559947, + -34980726, + -17301599, + 18210971, + 30362199, + 7529732, + -21835127, + -24336355, + 618181, + 22846056, + 17677018, + -6878635, + -21744868, + -11046147, + 11170675, + 19081658, + 4971419, + -13574360, + -15413493, + 167594, + 14299853, + 11264400, + -4142229, + -13650173, + -7091625, + 6866249, + 11981331, + 3261089, + -8377397, + -9663598, + -33577, + 8811466, + 7047290, + -2438142, + -8371994, + -4435631, + 4102284, + 7298877, + 2066339, + -4993046, + -5838997, + -102430, + 5210180, + 4221368, + -1368211, + -4895950, + -2638556, + 2325829, + 4212195, + 1235215, + -2806300, + -3319801, + -103730, + 2885352, + 2362323, + -713829, + -2661766, + -1454751, + 1218775, + 2241561, + 677709, + -1445604, + -1724717, + -76680, + 1450275, + 1195453, + -334609, + -1298628, + -716479, + 567892, + 1056257, + 327073, + -652494, + -780760, + -44432, + 627177, + 516796, + -132571, + -532768, + -293968, + 218243, + 406347, + 127168, + -234490, + -277390, + -18780, + 205651, + 165931, + -37974, + -154356, + -82524, + 55301, + 98729, + 29585, + 52471, + 100731, + 25052, + -114017, + -143416, + 13978, + 200279, + 170762, + -94897, + -303796, + -163722, + 224921, + 408845, + 101063, + -403816, + -491158, + 37139, + 620747, + 519209, + -264987, + -852007, + -457323, + 585725, + 1060324, + 270629, + -986928, + -1196329, + 68479, + 1436796, + 1202568, + -572988, + -1882481, + -1020142, + 1233979, + 2251301, + 597628, + -2014577, + -2455416, + 98490, + 2846389, + 2400188, + -1073042, + -3629604, + -1995914, + 2292539, + 4237664, + 1172082, + -3678358, + -4526945, + 107222, + 5104317, + 4351290, + -1828602, + -6400002, + -3580558, + 3917428, + 7360662, + 2121657, + -6230813, + -7763788, + 60081, + 8557388, + 7391705, + -2921705, + -10625213, + -6058613, + 6328318, + 12118407, + 3639758, + -10046112, + -12702121, + -99850, + 13744737, + 12054467, + -4482473, + -17010141, + -9903018, + 9897187, + 19367917, + 6062777, + -15794993, + -20315970, + -471998, + 21690593, + 19364029, + -6777706, + -26977359, + -16076411, + 15420017, + 30951846, + 10113477, + -25003228, + -32844471, + -1266540, + 34890124, + 31849823, + -10519501, + -44265340, + -27145962, + 25142256, + 52141981, + 17884556, + -42365002, + -57349639, + -3117160, + 61881153, + 58463725, + -18420233, + -83452948, + -53574812, + 48873256, + 107220424, + 39592117, + -92870683, + -134528200, + -9908237, + 163084521, + 170951491, + -56021421, + -308933738, + -245419954, + 284485726, + 1038448307, + 1527184009, + 1404746936, + 759191516, + 37914734, + -323670750, + -233425589, + 49117307, + 197564492, + 106614198, + -72793896, + -138178493, + -45203686, + 79251504, + 98226662, + 8473162, + -77357958, + -67263013, + 14883401, + 70453830, + 42038021, + -29344609, + -60428207, + -21414375, + 37218555, + 48649842, + 4962710, + -40013642, + -36228109, + 7540863, + 38918970, + 24082320, + -16320026, + -34979024, + -12950056, + 21680849, + 29146546, + 3379503, + -24033873, + -22283842, + 4276176, + 23882779, + 15144115, + -9855054, + -21794321, + -8348981, + 13370978, + 18359188, + 2370958, + -14987176, + -14150982, + 2474520, + 14981441, + 9688814, + -6025842, + -13706421, + -5407491, + 8261082, + 11548941, + 1637794, + -9274822, + -8892072, + 1402119, + 9248771, + 6083103, + -3604529, + -8419462, + -3409653, + 4960636, + 7046359, + 1085082, + -5541994, + -5383277, + 756684, + 5477671, + 3655404, + -2057845, + -4930007, + -2043290, + 2826557, + 4071598, + 674298, + -3122084, + -3065667, + 378854, + 3037597, + 2051278, + -1093566, + -2682855, + -1134100, + 1488401, + 2168677, + 382714, + -1611506, + -1594577, + 170184, + 1528232, + 1040350, + -522780, + -1309508, + -561794, + 696681, + 1022192, + 190231, + -728387, + -722145, + 64913, + 660963, + 450286, + -211442, + -536896, + -231490, + 268679, + 392790, + 75817, + -261693, + -256168, + 18595, + 216231, + 144338, + -61774, + -154888, + -64966, + 67996, + 94751, + 17900, + 63148, + 98536, + 8025, + -127179, + -133008, + 41118, + 212114, + 146912, + -132056, + -308121, + -121350, + 269184, + 397315, + 36504, + -448648, + -454028, + 124620, + 655594, + 446695, + -371636, + -862530, + -341518, + 701972, + 1029424, + 107820, + -1096613, + -1106058, + 275371, + 1517246, + 1036892, + -812205, + -1905721, + -768354, + 1483415, + 2186531, + 258074, + -2241382, + -2272765, + 514854, + 3008098, + 2075531, + -1539852, + -3677047, + -1516343, + 2766607, + 4119720, + 541440, + -4100196, + -4196982, + 863517, + 5401053, + 3774830, + -2660265, + -6490897, + -2743475, + 4748357, + 7165137, + 1037960, + -6961167, + -7211559, + 1341925, + 9069135, + 6434255, + -4315023, + -10791250, + -4680930, + 7708042, + 11814967, + 1871072, + -11252911, + -11823739, + 1978038, + 14593872, + 10530407, + -6730591, + -17304998, + -7713736, + 12119646, + 18917677, + 3254824, + -17744856, + -18956400, + 2830226, + 23081608, + 16980000, + -10364724, + -27501247, + -12624505, + 18995534, + 30300236, + 5643058, + -28188129, + -30734015, + 4062006, + 37231577, + 28048630, + -16419878, + -45249041, + -21499213, + 31189788, + 51203743, + 10337161, + -47982902, + -53879178, + 6268523, + 66316322, + 51786439, + -29453593, + -85719114, + -42878701, + 61235168, + 105950111, + 23706745, + -106140280, + -127549239, + 13407223, + 176906451, + 153819623, + -93158102, + -324582476, + -203638483, + 375501026, + 1124237846, + 1548183654, + 1345773156, + 662354072, + -32940436, + -334379689, + -201098458, + 80053826, + 198137273, + 84275390, + -90160591, + -133811262, + -27843935, + 89036036, + 91307971, + -5170671, + -82076952, + -59186091, + 25311822, + 71574948, + 33741236, + -36875983, + -58999496, + -13563520, + 42153839, + 45507029, + -1977864, + -42685970, + -32067581, + 13274612, + 39700656, + 19484554, + -20696202, + -34269980, + -8384709, + 24674261, + 27354536, + -794445, + -25722953, + -19802325, + 7809014, + 24425410, + 12331375, + -12600944, + -21402285, + -5511013, + 15277789, + 17272757, + -250342, + -16081957, + -12615337, + 4707157, + 15352688, + 7933810, + -7767536, + -13484702, + -3631955, + 9473731, + 10887521, + -972, + -9974728, + -7949112, + 2793494, + 9494023, + 5006692, + -4684717, + -8296014, + -2326540, + 5708595, + 6654230, + 93532, + -5972212, + -4824155, + 1589964, + 5631016, + 3022561, + -2697114, + -4863878, + -1414390, + 3263533, + 3850487, + 107273, + -3370406, + -2753012, + 847032, + 3126231, + 1703200, + -1445650, + -2649354, + -795313, + 1723809, + 2053044, + 84611, + -1742156, + -1434289, + 409528, + 1573960, + 866852, + -697095, + -1293699, + -398543, + 808994, + 968085, + 52176, + -788045, + -650094, + 170690, + 680656, + 376101, + -284277, + -530057, + -165793, + 312449, + 371611, + 24258, + -282861, + -230339, + 54512, + 222099, + 120492, + -83526, + -152243, + -46735, + 78792, + 88995, + 6392, + 72962, + 94139, + -9854, + -138141, + -119426, + 68302, + 219877, + 119260, + -167541, + -306140, + -75305, + 309004, + 377239, + -30392, + -485242, + -406636, + 211485, + 677642, + 363400, + -472824, + -855457, + -216365, + 805997, + 976710, + -60245, + -1185707, + -991392, + 480228, + 1567858, + 847077, + -1038700, + -1890155, + -496719, + 1706314, + 2075827, + -91991, + -2425583, + -2040731, + 926758, + 3110409, + 1703653, + -1981639, + -3649722, + -999102, + 3190357, + 3915734, + -108624, + -4443493, + -3776751, + 1611756, + 5590868, + 3113851, + -3447696, + -6449957, + -1840088, + 5492000, + 6820586, + -79720, + -7557523, + -6505339, + 2610982, + 9401087, + 5334338, + -5635639, + -10738331, + -3192265, + 8945211, + 11266516, + 44924, + -12242559, + -10694081, + 4037701, + 15153586, + 8774799, + -8864885, + -17249095, + -5343615, + 14117707, + 18075870, + 350732, + -19352450, + -17194876, + 6109528, + 24015448, + 14223385, + -13778212, + -27468453, + -8877061, + 22221657, + 29021850, + 1007541, + -30832366, + -27970986, + 9368924, + 38838887, + 23628422, + -22055854, + -45319086, + -15341149, + 36677276, + 49204930, + 2474951, + -52697465, + -49254537, + 15667820, + 69462298, + 43937593, + -40073396, + -86267719, + -31096227, + 72592953, + 102473868, + 6955898, + -117567740, + -117740536, + 37188941, + 187566243, + 132776897, + -130208035, + -334397260, + -154121315, + 469472916, + 1204676795, + 1558747996, + 1278815852, + 565430224, + -97105500, + -337823125, + -166438970, + 108077111, + 194734355, + 60971656, + -105219459, + -126873020, + -10340489, + 96813687, + 82694519, + -18446567, + -85056214, + -50055816, + 35058023, + 71234502, + 24889047, + -43553272, + -56399651, + -5545817, + 46172252, + 41485372, + -8791091, + -44462731, + -27309081, + 18672130, + 39670614, + 14545533, + -24604413, + -32875824, + -3700180, + 27135911, + 25028641, + -4907467, + -26873655, + -16946541, + 11146563, + 24468169, + 9298628, + -15063167, + -20581299, + -2591131, + 16855585, + 15848146, + -2839217, + -16839869, + -10840496, + 6821096, + 15409348, + 6036806, + -9333561, + -12992466, + -1801941, + 10481609, + 10012940, + -1621865, + -10465107, + -6855702, + 4112871, + 9544408, + 3841116, + -5657815, + -8006107, + -1208886, + 6332305, + 6132075, + -888111, + -6276415, + -4174207, + 2380851, + 5668523, + 2336492, + -3273710, + -4700185, + -765030, + 3628743, + 3554409, + -454294, + -3547153, + -2388975, + 1291522, + 3150360, + 1325669, + -1763349, + -2562750, + -445526, + 1920752, + 1897669, + -210511, + -1835470, + -1247593, + 636625, + 1587074, + 678791, + -854261, + -1251997, + -230191, + 902858, + 895412, + -84268, + -830576, + -566342, + 270825, + 686152, + 295914, + -349730, + -512640, + -98288, + 348822, + 343432, + -26453, + -297721, + -200557, + 88276, + 223275, + 94954, + -102848, + -146587, + -28233, + 87540, + 81658, + -4705 + +}; + +static const struct src_stage src_int32_8_21_4535_5000 = { + 13, 5, 8, 248, 1984, 21, 8, 0, 1, + src_int32_8_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_7_1361_5000.h b/src/audio/src/coef/src_ipc4_int32_8_7_1361_5000.h new file mode 100644 index 000000000000..01c66f61480a --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_7_1361_5000.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_1361_5000_fir[160] = { + 128091, + -1061856, + -689775, + 11430729, + -16875078, + -21931498, + 93782297, + -66762888, + -203577835, + 673018638, + 1362225665, + 524536720, + -233539142, + -25200271, + 84196301, + -30217921, + -10420776, + 10642967, + -1545939, + -704815, + 152881, + -1444794, + 500242, + 11436596, + -23280974, + -10577518, + 98026128, + -109957811, + -153522269, + 819218160, + 1332451252, + 379139512, + -244757091, + 12395161, + 70592637, + -35332699, + -4367007, + 9277364, + -2076301, + -400143, + 150190, + -1814936, + 2000023, + 10483021, + -29111014, + 3484014, + 95800364, + -151998932, + -82915040, + 957614692, + 1274154746, + 241786489, + -239339198, + 44223686, + 54383076, + -37400407, + 936396, + 7544283, + -2314027, + -162347, + 105353, + -2122526, + 3748090, + 8440550, + -33789967, + 19626241, + 86284239, + -189770276, + 7714096, + 1082804852, + 1189774284, + 116805982, + -219979940, + 69065116, + 36963903, + -36734586, + 5249026, + 5643006, + -2309519, + 4647, + 4647, + -2309519, + 5643006, + 5249026, + -36734586, + 36963903, + 69065116, + -219979940, + 116805982, + 1189774284, + 1082804852, + 7714096, + -189770276, + 86284239, + 19626241, + -33789967, + 8440550, + 3748090, + -2122526, + 105353, + -162347, + -2314027, + 7544283, + 936396, + -37400407, + 54383076, + 44223686, + -239339198, + 241786489, + 1274154746, + 957614692, + -82915040, + -151998932, + 95800364, + 3484014, + -29111014, + 10483021, + 2000023, + -1814936, + 150190, + -400143, + -2076301, + 9277364, + -4367007, + -35332699, + 70592637, + 12395161, + -244757091, + 379139512, + 1332451252, + 819218160, + -153522269, + -109957811, + 98026128, + -10577518, + -23280974, + 11436596, + 500242, + -1444794, + 152881, + -704815, + -1545939, + 10642967, + -10420776, + -30217921, + 84196301, + -25200271, + -233539142, + 524536720, + 1362225665, + 673018638, + -203577835, + -66762888, + 93782297, + -21931498, + -16875078, + 11430729, + -689775, + -1061856, + 128091 + +}; + +static const struct src_stage src_int32_8_7_1361_5000 = { + 6, 7, 8, 20, 160, 7, 8, 0, 0, + src_int32_8_7_1361_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_7_2468_5000.h b/src/audio/src/coef/src_ipc4_int32_8_7_2468_5000.h new file mode 100644 index 000000000000..63bb75d74877 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_7_2468_5000.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_2468_5000_fir[192] = { + 38025, + 446289, + -2663076, + 5605413, + -3037488, + -13514231, + 42483171, + -59476100, + 21314038, + 105999567, + -315404120, + 576368350, + 1597846310, + 377469340, + -294151550, + 136729155, + -11515726, + -42789460, + 40508249, + -17709614, + 825275, + 3961847, + -2423832, + 545811, + 104863, + 242883, + -2655671, + 7004317, + -7288478, + -7332268, + 40636241, + -72651923, + 56228244, + 61228967, + -310160003, + 780885819, + 1551104719, + 193136086, + -251745840, + 152539877, + -39743766, + -24406161, + 35344587, + -19818521, + 4015204, + 2267205, + -2012937, + 557925, + 195731, + -70561, + -2339061, + 7953680, + -11552917, + 518621, + 34626799, + -80613955, + 90209807, + 4661396, + -274334376, + 981252733, + 1460170143, + 30971618, + -194329191, + 153844589, + -61509716, + -6083272, + 27827769, + -19939959, + 6351438, + 686842, + -1507713, + 505247, + 302860, + -486141, + -1673805, + 8258698, + -15391493, + 9504285, + 24478667, + -81947626, + 119962140, + -60124022, + -205498170, + 1167475940, + 1329968877, + -103177659, + -128356914, + 142179012, + -75696827, + 10624792, + 18898026, + -18337048, + 7758684, + -653589, + -979263, + 412465, + 412465, + -979263, + -653589, + 7758684, + -18337048, + 18898026, + 10624792, + -75696827, + 142179012, + -128356914, + -103177659, + 1329968877, + 1167475940, + -205498170, + -60124022, + 119962140, + -81947626, + 24478667, + 9504285, + -15391493, + 8258698, + -1673805, + -486141, + 302860, + 505247, + -1507713, + 686842, + 6351438, + -19939959, + 27827769, + -6083272, + -61509716, + 153844589, + -194329191, + 30971618, + 1460170143, + 981252733, + -274334376, + 4661396, + 90209807, + -80613955, + 34626799, + 518621, + -11552917, + 7953680, + -2339061, + -70561, + 195731, + 557925, + -2012937, + 2267205, + 4015204, + -19818521, + 35344587, + -24406161, + -39743766, + 152539877, + -251745840, + 193136086, + 1551104719, + 780885819, + -310160003, + 61228967, + 56228244, + -72651923, + 40636241, + -7332268, + -7288478, + 7004317, + -2655671, + 242883, + 104863, + 545811, + -2423832, + 3961847, + 825275, + -17709614, + 40508249, + -42789460, + -11515726, + 136729155, + -294151550, + 377469340, + 1597846310, + 576368350, + -315404120, + 105999567, + 21314038, + -59476100, + 42483171, + -13514231, + -3037488, + 5605413, + -2663076, + 446289, + 38025 + +}; + +static const struct src_stage src_int32_8_7_2468_5000 = { + 6, 7, 8, 24, 192, 7, 8, 0, 0, + src_int32_8_7_2468_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_7_2721_5000.h b/src/audio/src/coef/src_ipc4_int32_8_7_2721_5000.h new file mode 100644 index 000000000000..9529c59e8c45 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_7_2721_5000.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_2721_5000_fir[192] = { + -68651, + 727228, + -2055563, + 1821307, + 4921529, + -21359365, + 40254462, + -38713186, + -14213238, + 137032299, + -318531781, + 543052491, + 1651520111, + 333732850, + -282811578, + 157149950, + -44277923, + -18491256, + 32869407, + -21769880, + 7458585, + 46488, + -1399220, + 611693, + -56329, + 777965, + -2641826, + 3787294, + 1372111, + -18628719, + 44543585, + -57660197, + 21103102, + 100442213, + -327852525, + 761141804, + 1599944299, + 143038909, + -227345873, + 160974559, + -66994731, + 1026283, + 23450551, + -20141835, + 8901238, + -1398639, + -755877, + 462900, + -15374, + 732391, + -3063016, + 5753628, + -2977568, + -13506111, + 44854657, + -73230835, + 58790154, + 48757444, + -305335599, + 977015848, + 1499792178, + -20906634, + -159422154, + 150060540, + -81154843, + 18150607, + 13118506, + -16911723, + 9286377, + -2433316, + -189867, + 308489, + 59706, + 563977, + -3222211, + 7490254, + -7787642, + -6168808, + 40603720, + -83402755, + 95373959, + -15026432, + -247284953, + 1179271001, + 1356848364, + -152170215, + -86372697, + 127058888, + -86449870, + 31606538, + 2939512, + -12608053, + 8748267, + -3033023, + 256660, + 169607, + 169607, + 256660, + -3033023, + 8748267, + -12608053, + 2939512, + 31606538, + -86449870, + 127058888, + -86372697, + -152170215, + 1356848364, + 1179271001, + -247284953, + -15026432, + 95373959, + -83402755, + 40603720, + -6168808, + -7787642, + 7490254, + -3222211, + 563977, + 59706, + 308489, + -189867, + -2433316, + 9286377, + -16911723, + 13118506, + 18150607, + -81154843, + 150060540, + -159422154, + -20906634, + 1499792178, + 977015848, + -305335599, + 48757444, + 58790154, + -73230835, + 44854657, + -13506111, + -2977568, + 5753628, + -3063016, + 732391, + -15374, + 462900, + -755877, + -1398639, + 8901238, + -20141835, + 23450551, + 1026283, + -66994731, + 160974559, + -227345873, + 143038909, + 1599944299, + 761141804, + -327852525, + 100442213, + 21103102, + -57660197, + 44543585, + -18628719, + 1372111, + 3787294, + -2641826, + 777965, + -56329, + 611693, + -1399220, + 46488, + 7458585, + -21769880, + 32869407, + -18491256, + -44277923, + 157149950, + -282811578, + 333732850, + 1651520111, + 543052491, + -318531781, + 137032299, + -14213238, + -38713186, + 40254462, + -21359365, + 4921529, + 1821307, + -2055563, + 727228, + -68651 + +}; + +static const struct src_stage src_int32_8_7_2721_5000 = { + 6, 7, 8, 24, 192, 7, 8, 0, 0, + src_int32_8_7_2721_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_7_4082_5000.h b/src/audio/src/coef/src_ipc4_int32_8_7_4082_5000.h new file mode 100644 index 000000000000..e4ad44917004 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_7_4082_5000.h @@ -0,0 +1,498 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_4082_5000_fir[480] = { + -48290, + 148731, + -325260, + 579827, + -887499, + 1186941, + -1375801, + 1314181, + -838651, + -212301, + 1962568, + -4456119, + 7613990, + -11198170, + 14790489, + -17793844, + 19460693, + -18950106, + 15410045, + -8076724, + -3621532, + 19971793, + -40913334, + 66023133, + -94573387, + 125700743, + -158793076, + 194489156, + -238354124, + 327027700, + 1939869964, + 70440601, + -126555638, + 136519523, + -130650656, + 116454369, + -97602102, + 76646277, + -55596990, + 36033158, + -19102004, + 5509784, + 4462282, + -10908790, + 14221922, + -14994770, + 13919359, + -11692118, + 8937161, + -6153902, + 3691235, + -1746472, + 384030, + 433017, + -805948, + 864651, + -738162, + 534379, + -329665, + 167255, + -22640, + 104803, + -274270, + 550883, + -932267, + 1380539, + -1811722, + 2091577, + -2041376, + 1456125, + -135905, + -2071417, + 5220548, + -9219015, + 13785767, + -18426909, + 22436139, + -24924555, + 24880170, + -21252034, + 13047994, + 571116, + -20224868, + 46308651, + -79108783, + 119163318, + -168232649, + 232262687, + -333836264, + 615511327, + 1858269422, + -139656310, + -12901361, + 66909208, + -88462718, + 93465721, + -88472671, + 77313616, + -62745126, + 46924252, + -31534696, + 17810263, + -6543173, + -1889810, + 7474291, + -10481162, + 11374754, + -10717930, + 9085472, + -6994754, + 4859144, + -2965588, + 1474255, + -435344, + -183361, + 464840, + -512927, + 428333, + -292827, + 161886, + 13281, + 37663, + -177423, + 442628, + -855264, + 1407003, + -2043612, + 2653292, + -3063163, + 3047762, + -2352069, + 729460, + 2007812, + -5930844, + 10936816, + -16701480, + 22650730, + -27958849, + 31577375, + -32293238, + 28807922, + -19820963, + 4089798, + 19581163, + -52512407, + 96695230, + -156351343, + 243014934, + -398517982, + 917643834, + 1701269854, + -293414501, + 89572209, + -5149348, + -38247109, + 60319038, + -68929861, + 68421990, + -61823961, + 51533458, + -39519636, + 27361883, + -16243078, + 6946562, + 123596, + -4894925, + 7556179, + -8473706, + 8105700, + -6924734, + 5356554, + -3739663, + 2306603, + -1184575, + 410712, + 43880, + -247213, + 281659, + -224736, + 137108, + 55796, + -46561, + -42222, + 260749, + -654336, + 1247090, + -2022936, + 2907507, + -3755362, + 4347325, + -4402091, + 3604628, + -1651403, + -1690637, + 6517437, + -12722264, + 19941188, + -27519280, + 34504729, + -39673421, + 41579548, + -38617928, + 29069110, + -11072104, + -17590217, + 60178653, + -123043401, + 222626346, + -419387185, + 1213001117, + 1480711139, + -386341382, + 170421520, + -70912161, + 13412463, + 21624968, + -41899193, + 51521027, + -53316696, + 49573372, + -42268183, + 33106739, + -23497159, + 14516031, + -6892499, + 1020517, + 3000715, + -5304442, + 6181840, + -6005954, + 5163620, + -4002416, + 2796413, + -1731121, + 905156, + -344205, + 21943, + 117273, + -138148, + 99349, + 99349, + -138148, + 117273, + 21943, + -344205, + 905156, + -1731121, + 2796413, + -4002416, + 5163620, + -6005954, + 6181840, + -5304442, + 3000715, + 1020517, + -6892499, + 14516031, + -23497159, + 33106739, + -42268183, + 49573372, + -53316696, + 51521027, + -41899193, + 21624968, + 13412463, + -70912161, + 170421520, + -386341382, + 1480711139, + 1213001117, + -419387185, + 222626346, + -123043401, + 60178653, + -17590217, + -11072104, + 29069110, + -38617928, + 41579548, + -39673421, + 34504729, + -27519280, + 19941188, + -12722264, + 6517437, + -1690637, + -1651403, + 3604628, + -4402091, + 4347325, + -3755362, + 2907507, + -2022936, + 1247090, + -654336, + 260749, + -42222, + -46561, + 55796, + 137108, + -224736, + 281659, + -247213, + 43880, + 410712, + -1184575, + 2306603, + -3739663, + 5356554, + -6924734, + 8105700, + -8473706, + 7556179, + -4894925, + 123596, + 6946562, + -16243078, + 27361883, + -39519636, + 51533458, + -61823961, + 68421990, + -68929861, + 60319038, + -38247109, + -5149348, + 89572209, + -293414501, + 1701269854, + 917643834, + -398517982, + 243014934, + -156351343, + 96695230, + -52512407, + 19581163, + 4089798, + -19820963, + 28807922, + -32293238, + 31577375, + -27958849, + 22650730, + -16701480, + 10936816, + -5930844, + 2007812, + 729460, + -2352069, + 3047762, + -3063163, + 2653292, + -2043612, + 1407003, + -855264, + 442628, + -177423, + 37663, + 13281, + 161886, + -292827, + 428333, + -512927, + 464840, + -183361, + -435344, + 1474255, + -2965588, + 4859144, + -6994754, + 9085472, + -10717930, + 11374754, + -10481162, + 7474291, + -1889810, + -6543173, + 17810263, + -31534696, + 46924252, + -62745126, + 77313616, + -88472671, + 93465721, + -88462718, + 66909208, + -12901361, + -139656310, + 1858269422, + 615511327, + -333836264, + 232262687, + -168232649, + 119163318, + -79108783, + 46308651, + -20224868, + 571116, + 13047994, + -21252034, + 24880170, + -24924555, + 22436139, + -18426909, + 13785767, + -9219015, + 5220548, + -2071417, + -135905, + 1456125, + -2041376, + 2091577, + -1811722, + 1380539, + -932267, + 550883, + -274270, + 104803, + -22640, + 167255, + -329665, + 534379, + -738162, + 864651, + -805948, + 433017, + 384030, + -1746472, + 3691235, + -6153902, + 8937161, + -11692118, + 13919359, + -14994770, + 14221922, + -10908790, + 4462282, + 5509784, + -19102004, + 36033158, + -55596990, + 76646277, + -97602102, + 116454369, + -130650656, + 136519523, + -126555638, + 70440601, + 1939869964, + 327027700, + -238354124, + 194489156, + -158793076, + 125700743, + -94573387, + 66023133, + -40913334, + 19971793, + -3621532, + -8076724, + 15410045, + -18950106, + 19460693, + -17793844, + 14790489, + -11198170, + 7613990, + -4456119, + 1962568, + -212301, + -838651, + 1314181, + -1375801, + 1186941, + -887499, + 579827, + -325260, + 148731, + -48290 + +}; + +static const struct src_stage src_int32_8_7_4082_5000 = { + 6, 7, 8, 60, 480, 7, 8, 0, 0, + src_int32_8_7_4082_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_8_7_4535_5000.h b/src/audio/src/coef/src_ipc4_int32_8_7_4535_5000.h new file mode 100644 index 000000000000..020e1a0df119 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_8_7_4535_5000.h @@ -0,0 +1,914 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_4535_5000_fir[896] = { + -24053, + 43532, + -69787, + 103039, + -142850, + 187938, + -235996, + 283544, + -325831, + 356790, + -369075, + 354197, + -302754, + 204777, + -50189, + -170632, + 466186, + -843118, + 1305415, + -1853598, + 2483916, + -3187606, + 3950243, + -4751245, + 5563555, + -6353558, + 7081241, + -7700652, + 8160632, + -8405860, + 8378163, + -8018084, + 7266667, + -6067384, + 4368161, + -2123407, + -704046, + 4141167, + -8203235, + 12892734, + -18198728, + 24096855, + -30550052, + 37510200, + -44920907, + 52721837, + -60855252, + 69276079, + -77968136, + 86972275, + -96440039, + 106748630, + -118785911, + 134810618, + -161966358, + 238266169, + 2035697773, + -26452718, + -34510372, + 54792793, + -63768958, + 67644512, + -68579149, + 67561681, + -65143568, + 61684790, + -57451178, + 52657131, + -47485463, + 42096720, + -36633363, + 31221395, + -25970741, + 20975111, + -16311762, + 12041394, + -8208314, + 4840924, + -1952569, + -457292, + 2401615, + -3904065, + 4997142, + -5720204, + 6117472, + -6236081, + 6124235, + -5829541, + 5397543, + -4870515, + 4286505, + -3678661, + 3074824, + -2497373, + 1963300, + -1484487, + 1068135, + -717326, + 431661, + -207944, + 40868, + 76318, + -151197, + 191644, + -205372, + 199571, + -180648, + 154055, + -124206, + 94467, + -67215, + 43927, + -18773, + 36472, + -62227, + 97210, + -142130, + 197012, + -260960, + 331940, + -406569, + 479956, + -545599, + 595362, + -619550, + 607097, + -545878, + 423144, + -226102, + -57400, + 438069, + -924282, + 1521147, + -2229544, + 3045188, + -3957768, + 4950198, + -5998036, + 7069113, + -8123413, + 9113235, + -9983656, + 10673306, + -11115444, + 11239325, + -10971796, + 10239090, + -8968720, + 7091394, + -4542829, + 1265338, + 2790980, + -7667630, + 13397947, + -20008478, + 27522012, + -35962983, + 45366499, + -55793187, + 67354032, + -80253625, + 94870188, + -111915998, + 132794545, + -160514977, + 202550264, + -283145488, + 546492853, + 1941590543, + -232026462, + 82749219, + -26107807, + -3593406, + 21396743, + -32639484, + 39718390, + -43895794, + 45924744, + -46304361, + 45396614, + -43484018, + 40799590, + -37542804, + 33888099, + -29989301, + 25981783, + -21983434, + 18095045, + -14400507, + 10967049, + -7845661, + 5071766, + -2666172, + 636293, + 1022385, + -2324655, + 3293798, + -3959736, + 4357170, + -4523784, + 4498568, + -4320296, + 4026218, + -3650969, + 3225731, + -2777641, + 2329436, + -1899328, + 1501076, + -1144233, + 834526, + -574340, + 363265, + -198674, + 76301, + 9206, + -63791, + 93548, + -104369, + 101666, + -90179, + 73856, + -55811, + 38336, + -9730, + 23033, + -44642, + 76565, + -120609, + 178150, + -249885, + 335548, + -433636, + 541142, + -653318, + 763505, + -863031, + 941208, + -985458, + 981561, + -914058, + 766802, + -523653, + 169316, + 309703, + -924055, + 1680438, + -2580483, + 3619671, + -4786322, + 6060737, + -7414510, + 8810080, + -10200553, + 11529820, + -12732994, + 13737164, + -14462438, + 14823255, + -14729887, + 14090051, + -12810519, + 10798560, + -7963040, + 4214896, + 533343, + -6369504, + 13385918, + -21686972, + 31402055, + -42707507, + 55864395, + -71286028, + 89665711, + -112238162, + 141373332, + -182132682, + 247293691, + -380227946, + 877412897, + 1761215047, + -369220328, + 176345740, + -97278482, + 53434205, + -25430146, + 6176939, + 7541007, + -17407459, + 24406652, + -29170284, + 32139231, + -33645116, + 33953740, + -33288982, + 31846087, + -29798975, + 27304061, + -24502080, + 21518775, + -18465006, + 15436651, + -12514501, + 9764319, + -7237128, + 4969771, + -2985760, + 1296381, + 97981, + -1206335, + 2045462, + -2638241, + 3011981, + -3196807, + 3224165, + -3125483, + 2931014, + -2668892, + 2364408, + -2039506, + 1712491, + -1397940, + 1106773, + -846483, + 621470, + -433456, + 281960, + -164777, + 78465, + -18789, + -18870, + 39176, + -46563, + 45023, + -37979, + 28205, + 2177, + 4529, + -18675, + 42867, + -79807, + 132097, + -201984, + 291077, + -400023, + 528171, + -673236, + 830991, + -995001, + 1156431, + -1303956, + 1423787, + -1499843, + 1514081, + -1446995, + 1278289, + -987716, + 556074, + 33672, + -795165, + 1737372, + -2863293, + 4168706, + -5641010, + 7258214, + -8988136, + 10787844, + -12603380, + 14369797, + -16011507, + 17442918, + -18569346, + 19288101, + -19489666, + 19058810, + -17875426, + 15814813, + -12746980, + 8534375, + -3027107, + -3945831, + 12591906, + -23181539, + 36094581, + -51904820, + 71542496, + -96632282, + 130274971, + -179143565, + 260482780, + -435977132, + 1206847048, + 1509471061, + -435729677, + 237039077, + -150153740, + 99916651, + -66520762, + 42505389, + -24443410, + 10539238, + 246115, + -8566645, + 14867322, + -19474245, + 22643462, + -24588358, + 25495222, + -25532008, + 24853044, + -23601281, + 21909074, + -19898125, + 17678991, + -15350448, + 12998897, + -10697937, + 8508186, + -6477388, + 4640821, + -3021988, + 1633570, + -478591, + -448253, + 1159158, + -1671731, + 2007516, + -2190579, + 2246202, + -2199718, + 2075517, + -1896244, + 1682185, + -1450859, + 1216783, + -991416, + 783242, + -597981, + 438879, + -307076, + 202002, + -121780, + 63627, + -24210, + -27, + 12602, + -16787, + 15459, + 15459, + -16787, + 12602, + -27, + -24210, + 63627, + -121780, + 202002, + -307076, + 438879, + -597981, + 783242, + -991416, + 1216783, + -1450859, + 1682185, + -1896244, + 2075517, + -2199718, + 2246202, + -2190579, + 2007516, + -1671731, + 1159158, + -448253, + -478591, + 1633570, + -3021988, + 4640821, + -6477388, + 8508186, + -10697937, + 12998897, + -15350448, + 17678991, + -19898125, + 21909074, + -23601281, + 24853044, + -25532008, + 25495222, + -24588358, + 22643462, + -19474245, + 14867322, + -8566645, + 246115, + 10539238, + -24443410, + 42505389, + -66520762, + 99916651, + -150153740, + 237039077, + -435729677, + 1509471061, + 1206847048, + -435977132, + 260482780, + -179143565, + 130274971, + -96632282, + 71542496, + -51904820, + 36094581, + -23181539, + 12591906, + -3945831, + -3027107, + 8534375, + -12746980, + 15814813, + -17875426, + 19058810, + -19489666, + 19288101, + -18569346, + 17442918, + -16011507, + 14369797, + -12603380, + 10787844, + -8988136, + 7258214, + -5641010, + 4168706, + -2863293, + 1737372, + -795165, + 33672, + 556074, + -987716, + 1278289, + -1446995, + 1514081, + -1499843, + 1423787, + -1303956, + 1156431, + -995001, + 830991, + -673236, + 528171, + -400023, + 291077, + -201984, + 132097, + -79807, + 42867, + -18675, + 4529, + 2177, + 28205, + -37979, + 45023, + -46563, + 39176, + -18870, + -18789, + 78465, + -164777, + 281960, + -433456, + 621470, + -846483, + 1106773, + -1397940, + 1712491, + -2039506, + 2364408, + -2668892, + 2931014, + -3125483, + 3224165, + -3196807, + 3011981, + -2638241, + 2045462, + -1206335, + 97981, + 1296381, + -2985760, + 4969771, + -7237128, + 9764319, + -12514501, + 15436651, + -18465006, + 21518775, + -24502080, + 27304061, + -29798975, + 31846087, + -33288982, + 33953740, + -33645116, + 32139231, + -29170284, + 24406652, + -17407459, + 7541007, + 6176939, + -25430146, + 53434205, + -97278482, + 176345740, + -369220328, + 1761215047, + 877412897, + -380227946, + 247293691, + -182132682, + 141373332, + -112238162, + 89665711, + -71286028, + 55864395, + -42707507, + 31402055, + -21686972, + 13385918, + -6369504, + 533343, + 4214896, + -7963040, + 10798560, + -12810519, + 14090051, + -14729887, + 14823255, + -14462438, + 13737164, + -12732994, + 11529820, + -10200553, + 8810080, + -7414510, + 6060737, + -4786322, + 3619671, + -2580483, + 1680438, + -924055, + 309703, + 169316, + -523653, + 766802, + -914058, + 981561, + -985458, + 941208, + -863031, + 763505, + -653318, + 541142, + -433636, + 335548, + -249885, + 178150, + -120609, + 76565, + -44642, + 23033, + -9730, + 38336, + -55811, + 73856, + -90179, + 101666, + -104369, + 93548, + -63791, + 9206, + 76301, + -198674, + 363265, + -574340, + 834526, + -1144233, + 1501076, + -1899328, + 2329436, + -2777641, + 3225731, + -3650969, + 4026218, + -4320296, + 4498568, + -4523784, + 4357170, + -3959736, + 3293798, + -2324655, + 1022385, + 636293, + -2666172, + 5071766, + -7845661, + 10967049, + -14400507, + 18095045, + -21983434, + 25981783, + -29989301, + 33888099, + -37542804, + 40799590, + -43484018, + 45396614, + -46304361, + 45924744, + -43895794, + 39718390, + -32639484, + 21396743, + -3593406, + -26107807, + 82749219, + -232026462, + 1941590543, + 546492853, + -283145488, + 202550264, + -160514977, + 132794545, + -111915998, + 94870188, + -80253625, + 67354032, + -55793187, + 45366499, + -35962983, + 27522012, + -20008478, + 13397947, + -7667630, + 2790980, + 1265338, + -4542829, + 7091394, + -8968720, + 10239090, + -10971796, + 11239325, + -11115444, + 10673306, + -9983656, + 9113235, + -8123413, + 7069113, + -5998036, + 4950198, + -3957768, + 3045188, + -2229544, + 1521147, + -924282, + 438069, + -57400, + -226102, + 423144, + -545878, + 607097, + -619550, + 595362, + -545599, + 479956, + -406569, + 331940, + -260960, + 197012, + -142130, + 97210, + -62227, + 36472, + -18773, + 43927, + -67215, + 94467, + -124206, + 154055, + -180648, + 199571, + -205372, + 191644, + -151197, + 76318, + 40868, + -207944, + 431661, + -717326, + 1068135, + -1484487, + 1963300, + -2497373, + 3074824, + -3678661, + 4286505, + -4870515, + 5397543, + -5829541, + 6124235, + -6236081, + 6117472, + -5720204, + 4997142, + -3904065, + 2401615, + -457292, + -1952569, + 4840924, + -8208314, + 12041394, + -16311762, + 20975111, + -25970741, + 31221395, + -36633363, + 42096720, + -47485463, + 52657131, + -57451178, + 61684790, + -65143568, + 67561681, + -68579149, + 67644512, + -63768958, + 54792793, + -34510372, + -26452718, + 2035697773, + 238266169, + -161966358, + 134810618, + -118785911, + 106748630, + -96440039, + 86972275, + -77968136, + 69276079, + -60855252, + 52721837, + -44920907, + 37510200, + -30550052, + 24096855, + -18198728, + 12892734, + -8203235, + 4141167, + -704046, + -2123407, + 4368161, + -6067384, + 7266667, + -8018084, + 8378163, + -8405860, + 8160632, + -7700652, + 7081241, + -6353558, + 5563555, + -4751245, + 3950243, + -3187606, + 2483916, + -1853598, + 1305415, + -843118, + 466186, + -170632, + -50189, + 204777, + -302754, + 354197, + -369075, + 356790, + -325831, + 283544, + -235996, + 187938, + -142850, + 103039, + -69787, + 43532, + -24053 + +}; + +static const struct src_stage src_int32_8_7_4535_5000 = { + 6, 7, 8, 112, 896, 7, 8, 0, 0, + src_int32_8_7_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_ipc4_int32_define.h b/src/audio/src/coef/src_ipc4_int32_define.h new file mode 100644 index 000000000000..8eb7de206a8b --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_define.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_DEFINE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_DEFINE_H__ + +/* SRC constants */ +#define MAX_FIR_DELAY_SIZE 1305 +#define MAX_OUT_DELAY_SIZE 3844 +#define MAX_BLK_IN 80 +#define MAX_BLK_OUT 64 +#define NUM_IN_FS 16 +#define NUM_OUT_FS 13 +#define STAGE1_TIMES_MAX 32 +#define STAGE2_TIMES_MAX 40 +#define STAGE_BUF_SIZE 840 +#define NUM_ALL_COEFFICIENTS 76328 + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_DEFINE_H__ */ diff --git a/src/audio/src/coef/src_ipc4_int32_table.h b/src/audio/src/coef/src_ipc4_int32_table.h new file mode 100644 index 000000000000..96bfe2383016 --- /dev/null +++ b/src/audio/src/coef/src_ipc4_int32_table.h @@ -0,0 +1,357 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_TABLE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_TABLE_H__ + +/* SRC conversions */ +#include "src_ipc4_int32_1_2_2268_5000.h" +#include "src_ipc4_int32_1_2_2500_5000.h" +#include "src_ipc4_int32_1_2_2721_5000.h" +#include "src_ipc4_int32_1_2_3401_5000.h" +#include "src_ipc4_int32_1_2_3887_5000.h" +#include "src_ipc4_int32_1_2_4535_5000.h" +#include "src_ipc4_int32_1_3_2268_5000.h" +#include "src_ipc4_int32_1_3_4535_5000.h" +#include "src_ipc4_int32_1_4_1512_5000.h" +#include "src_ipc4_int32_1_4_2268_5000.h" +#include "src_ipc4_int32_1_4_4535_5000.h" +#include "src_ipc4_int32_1_6_1134_5000.h" +#include "src_ipc4_int32_2_1_2268_5000.h" +#include "src_ipc4_int32_2_1_2500_5000.h" +#include "src_ipc4_int32_2_1_2721_5000.h" +#include "src_ipc4_int32_2_1_3401_5000.h" +#include "src_ipc4_int32_2_1_4535_5000.h" +#include "src_ipc4_int32_2_3_4535_5000.h" +#include "src_ipc4_int32_3_1_2268_5000.h" +#include "src_ipc4_int32_3_1_4535_5000.h" +#include "src_ipc4_int32_3_2_4535_5000.h" +#include "src_ipc4_int32_3_4_4535_5000.h" +#include "src_ipc4_int32_4_1_1134_5000.h" +#include "src_ipc4_int32_4_1_1512_5000.h" +#include "src_ipc4_int32_4_1_2268_5000.h" +#include "src_ipc4_int32_4_1_3401_5000.h" +#include "src_ipc4_int32_4_1_4535_5000.h" +#include "src_ipc4_int32_4_3_4535_5000.h" +#include "src_ipc4_int32_4_21_1080_5000.h" +#include "src_ipc4_int32_4_21_3239_5000.h" +#include "src_ipc4_int32_5_7_4535_5000.h" +#include "src_ipc4_int32_5_21_1728_5000.h" +#include "src_ipc4_int32_5_21_4535_5000.h" +#include "src_ipc4_int32_6_1_1134_5000.h" +#include "src_ipc4_int32_7_3_4535_5000.h" +#include "src_ipc4_int32_7_5_4535_5000.h" +#include "src_ipc4_int32_7_8_1361_5000.h" +#include "src_ipc4_int32_7_8_2468_5000.h" +#include "src_ipc4_int32_7_8_2721_5000.h" +#include "src_ipc4_int32_7_8_4535_5000.h" +#include "src_ipc4_int32_7_40_2976_5000.h" +#include "src_ipc4_int32_8_7_1361_5000.h" +#include "src_ipc4_int32_8_7_2468_5000.h" +#include "src_ipc4_int32_8_7_2721_5000.h" +#include "src_ipc4_int32_8_7_4082_5000.h" +#include "src_ipc4_int32_8_7_4535_5000.h" +#include "src_ipc4_int32_8_21_2160_5000.h" +#include "src_ipc4_int32_8_21_3239_5000.h" +#include "src_ipc4_int32_8_21_4535_5000.h" +#include "src_ipc4_int32_10_9_4535_5000.h" +#include "src_ipc4_int32_10_21_2500_5000.h" +#include "src_ipc4_int32_10_21_3455_5000.h" +#include "src_ipc4_int32_10_21_4535_5000.h" +#include "src_ipc4_int32_16_7_4082_5000.h" +#include "src_ipc4_int32_16_21_4319_5000.h" +#include "src_ipc4_int32_16_21_4535_5000.h" +#include "src_ipc4_int32_20_7_2976_5000.h" +#include "src_ipc4_int32_20_21_1250_5000.h" +#include "src_ipc4_int32_20_21_2500_5000.h" +#include "src_ipc4_int32_20_21_3125_5000.h" +#include "src_ipc4_int32_20_21_4167_5000.h" +#include "src_ipc4_int32_20_21_4535_5000.h" +#include "src_ipc4_int32_21_2_3239_5000.h" +#include "src_ipc4_int32_21_4_1080_5000.h" +#include "src_ipc4_int32_21_4_3239_5000.h" +#include "src_ipc4_int32_21_5_1728_5000.h" +#include "src_ipc4_int32_21_5_4535_5000.h" +#include "src_ipc4_int32_21_8_2160_5000.h" +#include "src_ipc4_int32_21_8_3239_5000.h" +#include "src_ipc4_int32_21_8_4535_5000.h" +#include "src_ipc4_int32_21_10_2500_5000.h" +#include "src_ipc4_int32_21_10_3455_5000.h" +#include "src_ipc4_int32_21_10_4535_5000.h" +#include "src_ipc4_int32_21_16_4319_5000.h" +#include "src_ipc4_int32_21_16_4535_5000.h" +#include "src_ipc4_int32_21_20_1250_5000.h" +#include "src_ipc4_int32_21_20_2500_5000.h" +#include "src_ipc4_int32_21_20_3125_5000.h" +#include "src_ipc4_int32_21_20_4167_5000.h" +#include "src_ipc4_int32_21_20_4535_5000.h" +#include "src_ipc4_int32_21_32_4535_5000.h" +#include "src_ipc4_int32_21_40_2381_5000.h" +#include "src_ipc4_int32_21_40_3968_5000.h" +#include "src_ipc4_int32_21_80_3968_5000.h" +#include "src_ipc4_int32_32_21_4535_5000.h" +#include "src_ipc4_int32_40_7_2976_5000.h" +#include "src_ipc4_int32_40_21_2381_5000.h" +#include "src_ipc4_int32_40_21_2976_5000.h" +#include "src_ipc4_int32_40_21_3968_5000.h" +#include "src_ipc4_int32_40_21_4535_5000.h" +#include "src_ipc4_int32_64_21_2381_5000.h" +#include <stdint.h> + +/* SRC table */ +static const int32_t fir_one = 1073741824; +static const struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; +static const struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; +static const int src_in_fs[16] = { 8000, 11025, 12000, 16000, 18900, 22050, 24000, 32000, + 37800, 44100, 48000, 64000, 88200, 96000, 176400, 192000 + }; +static const int src_out_fs[13] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, + 64000, 88200, 96000, 176400, 192000}; +static const struct src_stage * const src_table1[13][16] = { + { &src_int32_1_1_0_0, &src_int32_16_21_4319_5000, + &src_int32_2_3_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_10_21_3455_5000, + &src_int32_1_3_4535_5000, &src_int32_1_2_2268_5000, + &src_int32_0_0_0_0, &src_int32_8_21_2160_5000, + &src_int32_1_3_2268_5000, &src_int32_1_4_2268_5000, + &src_int32_5_21_1728_5000, &src_int32_1_4_1512_5000, + &src_int32_4_21_1080_5000, &src_int32_1_6_1134_5000 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_21_80_3968_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_7_40_2976_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_2_1_4535_5000, &src_int32_32_21_4535_5000, + &src_int32_4_3_4535_5000, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_16_21_4319_5000, + &src_int32_2_3_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_10_21_3455_5000, + &src_int32_1_3_4535_5000, &src_int32_1_2_2268_5000, + &src_int32_8_21_2160_5000, &src_int32_1_3_2268_5000, + &src_int32_5_21_1728_5000, &src_int32_1_4_1512_5000 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_21_40_3968_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_21_80_3968_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_3_1_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_2_4535_5000, + &src_int32_10_9_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_1_1_0_0, &src_int32_3_4_4535_5000, + &src_int32_0_0_0_0, &src_int32_8_7_2468_5000, + &src_int32_1_2_4535_5000, &src_int32_1_2_3401_5000, + &src_int32_8_21_3239_5000, &src_int32_1_2_2268_5000, + &src_int32_4_21_3239_5000, &src_int32_1_4_2268_5000 + }, + { &src_int32_2_1_4535_5000, &src_int32_32_21_4535_5000, + &src_int32_4_3_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_32_21_4535_5000, + &src_int32_4_3_4535_5000, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_16_21_4319_5000, + &src_int32_2_3_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_10_21_3455_5000, &src_int32_1_3_4535_5000, + &src_int32_8_21_2160_5000, &src_int32_1_3_2268_5000 + }, + { &src_int32_21_10_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_7_5_4535_5000, &src_int32_21_16_4535_5000, + &src_int32_7_3_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_21_10_4535_5000, &src_int32_21_20_4535_5000, + &src_int32_7_3_4535_5000, &src_int32_1_1_0_0, + &src_int32_21_20_4167_5000, &src_int32_21_20_3125_5000, + &src_int32_1_2_4535_5000, &src_int32_21_40_3968_5000, + &src_int32_1_2_2268_5000, &src_int32_21_80_3968_5000 + }, + { &src_int32_2_1_4535_5000, &src_int32_32_21_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_1_4535_5000, + &src_int32_10_9_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_2_4535_5000, + &src_int32_10_9_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_1_1_0_0, &src_int32_3_4_4535_5000, + &src_int32_8_7_2468_5000, &src_int32_1_2_4535_5000, + &src_int32_8_21_3239_5000, &src_int32_1_2_2268_5000 + }, + { &src_int32_2_1_4535_5000, &src_int32_40_21_4535_5000, + &src_int32_4_3_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_32_21_4535_5000, + &src_int32_4_3_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_32_21_4535_5000, + &src_int32_4_3_4535_5000, &src_int32_1_1_0_0, + &src_int32_16_21_4319_5000, &src_int32_2_3_4535_5000, + &src_int32_10_21_3455_5000, &src_int32_1_3_4535_5000 + }, + { &src_int32_21_8_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_7_5_4535_5000, &src_int32_21_10_4535_5000, + &src_int32_0_0_0_0, &src_int32_2_1_4535_5000, + &src_int32_7_5_4535_5000, &src_int32_21_16_4535_5000, + &src_int32_7_3_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_21_10_4535_5000, &src_int32_21_20_4535_5000, + &src_int32_1_1_0_0, &src_int32_21_20_2500_5000, + &src_int32_1_2_2721_5000, &src_int32_21_40_2381_5000 + }, + { &src_int32_3_1_4535_5000, &src_int32_32_21_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_32_21_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_1_4535_5000, + &src_int32_10_9_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_2_4535_5000, + &src_int32_8_7_2721_5000, &src_int32_1_1_0_0, + &src_int32_8_7_1361_5000, &src_int32_1_2_2500_5000 + }, + { &src_int32_21_5_4535_5000, &src_int32_4_1_4535_5000, + &src_int32_7_5_4535_5000, &src_int32_21_8_4535_5000, + &src_int32_0_0_0_0, &src_int32_2_1_4535_5000, + &src_int32_7_5_4535_5000, &src_int32_21_10_4535_5000, + &src_int32_0_0_0_0, &src_int32_2_1_4535_5000, + &src_int32_7_5_4535_5000, &src_int32_21_16_4535_5000, + &src_int32_2_1_2721_5000, &src_int32_21_10_2500_5000, + &src_int32_1_1_0_0, &src_int32_21_20_1250_5000 + }, + { &src_int32_4_1_4535_5000, &src_int32_0_0_0_0, + &src_int32_4_1_4535_5000, &src_int32_3_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_32_21_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_32_21_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_1_4535_5000, + &src_int32_8_7_2721_5000, &src_int32_2_1_2500_5000, + &src_int32_8_7_1361_5000, &src_int32_1_1_0_0 + } +}; + +static const struct src_stage * const src_table2[13][16] = { + { &src_int32_1_1_0_0, &src_int32_20_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_16_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_10_21_4535_5000, + &src_int32_1_2_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_8_21_4535_5000, &src_int32_1_3_4535_5000, + &src_int32_5_21_4535_5000, &src_int32_1_4_4535_5000 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_7_8_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_21_32_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_1_1_0_0, &src_int32_20_21_3125_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_20_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_16_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_1_2_4535_5000, + &src_int32_10_21_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_8_21_4535_5000, &src_int32_1_3_4535_5000 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_7_8_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_7_8_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_1_1_0_0, &src_int32_40_21_3968_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_8_7_4082_5000, &src_int32_20_21_4167_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_10_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_3_4_4535_5000, + &src_int32_5_7_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_5_7_4535_5000, &src_int32_1_2_4535_5000 + }, + { &src_int32_2_1_2268_5000, &src_int32_40_21_2976_5000, + &src_int32_2_1_3401_5000, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_20_21_3125_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_20_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_16_21_4535_5000, &src_int32_1_1_0_0, + &src_int32_10_21_4535_5000, &src_int32_1_2_4535_5000 + }, + { &src_int32_21_8_2160_5000, &src_int32_2_1_2268_5000, + &src_int32_21_8_3239_5000, &src_int32_21_10_3455_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_7_8_2468_5000, &src_int32_21_16_4319_5000, + &src_int32_1_2_3887_5000, &src_int32_1_1_0_0, + &src_int32_7_8_4535_5000, &src_int32_21_32_4535_5000, + &src_int32_1_1_0_0, &src_int32_7_8_4535_5000, + &src_int32_1_2_4535_5000, &src_int32_7_8_4535_5000 + }, + { &src_int32_3_1_2268_5000, &src_int32_20_7_2976_5000, + &src_int32_2_1_2268_5000, &src_int32_1_1_0_0, + &src_int32_16_7_4082_5000, &src_int32_40_21_3968_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_8_7_4082_5000, &src_int32_20_21_4167_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_10_21_4535_5000, &src_int32_1_1_0_0, + &src_int32_5_7_4535_5000, &src_int32_1_2_4535_5000 + }, + { &src_int32_4_1_2268_5000, &src_int32_64_21_2381_5000, + &src_int32_4_1_3401_5000, &src_int32_2_1_2268_5000, + &src_int32_0_0_0_0, &src_int32_40_21_2976_5000, + &src_int32_2_1_3401_5000, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_20_21_3125_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_20_21_4535_5000, &src_int32_1_1_0_0, + &src_int32_16_21_4535_5000, &src_int32_1_1_0_0 + }, + { &src_int32_21_5_1728_5000, &src_int32_4_1_2268_5000, + &src_int32_21_4_3239_5000, &src_int32_21_8_2160_5000, + &src_int32_0_0_0_0, &src_int32_2_1_2268_5000, + &src_int32_21_8_3239_5000, &src_int32_21_10_3455_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_7_8_2468_5000, &src_int32_21_16_4319_5000, + &src_int32_1_1_0_0, &src_int32_7_8_2721_5000, + &src_int32_1_1_0_0, &src_int32_7_8_2721_5000 + }, + { &src_int32_4_1_1512_5000, &src_int32_40_7_2976_5000, + &src_int32_4_1_2268_5000, &src_int32_3_1_2268_5000, + &src_int32_0_0_0_0, &src_int32_20_7_2976_5000, + &src_int32_2_1_2268_5000, &src_int32_1_1_0_0, + &src_int32_16_7_4082_5000, &src_int32_40_21_3968_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_20_21_2500_5000, &src_int32_1_1_0_0, + &src_int32_10_21_2500_5000, &src_int32_1_1_0_0 + }, + { &src_int32_21_4_1080_5000, &src_int32_4_1_1134_5000, + &src_int32_21_2_3239_5000, &src_int32_21_5_1728_5000, + &src_int32_0_0_0_0, &src_int32_4_1_2268_5000, + &src_int32_21_4_3239_5000, &src_int32_21_8_2160_5000, + &src_int32_0_0_0_0, &src_int32_2_1_2268_5000, + &src_int32_21_8_3239_5000, &src_int32_21_10_3455_5000, + &src_int32_1_1_0_0, &src_int32_7_8_1361_5000, + &src_int32_1_1_0_0, &src_int32_7_8_1361_5000 + }, + { &src_int32_6_1_1134_5000, &src_int32_0_0_0_0, + &src_int32_4_1_1134_5000, &src_int32_4_1_1512_5000, + &src_int32_0_0_0_0, &src_int32_40_7_2976_5000, + &src_int32_4_1_2268_5000, &src_int32_3_1_2268_5000, + &src_int32_0_0_0_0, &src_int32_20_7_2976_5000, + &src_int32_2_1_2268_5000, &src_int32_1_1_0_0, + &src_int32_40_21_2381_5000, &src_int32_1_1_0_0, + &src_int32_20_21_1250_5000, &src_int32_1_1_0_0 + } +}; + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_IPC4_INT32_TABLE_H__ */ + +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_10_21_3455_5000.h b/src/audio/src/coef/src_lite_int32_10_21_3455_5000.h new file mode 100755 index 000000000000..10572f91d375 --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_10_21_3455_5000.h @@ -0,0 +1,577 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_10_21_3455_5000_fir[560] = { + -656, + 634708, + 716335, + -1021370, + -2716950, + -332747, + 5165217, + 5212861, + -4803656, + -13150751, + -3013466, + 18914085, + 20340641, + -12818575, + -41396262, + -14006308, + 50215641, + 60607931, + -25150589, + -108434030, + -49828498, + 120112884, + 172806238, + -43010753, + -319933915, + -214031286, + 462616824, + 1321354559, + 1686115002, + 1247304899, + 376120494, + -251519923, + -302325644, + -12160495, + 179440040, + 103972816, + -63203240, + -104899044, + -14061034, + 64240981, + 44589008, + -19507459, + -40528148, + -8692126, + 21917910, + 17061122, + -4945602, + -12966642, + -3556788, + 5696345, + 4692047, + -799681, + -2675850, + -785673, + 784133, + 566497, + 43747, + 697925, + 627222, + -1259449, + -2712649, + 173684, + 5581068, + 4611979, + -6040896, + -13127272, + -935497, + 20546560, + 18362938, + -16916165, + -41635843, + -8060106, + 55261912, + 55870368, + -36266428, + -110386358, + -35134065, + 135020465, + 163137422, + -74719692, + -333481955, + -170277306, + 551221746, + 1390117010, + 1677424565, + 1168644329, + 292400387, + -282691082, + -281127498, + 17423977, + 183069677, + 86890960, + -75106250, + -99893849, + -3166338, + 66754571, + 38490558, + -24495494, + -39069877, + -4602414, + 23087130, + 15026756, + -6708125, + -12588219, + -2320895, + 6061185, + 4172856, + -1221862, + -2593330, + -556385, + 831259, + 495235, + 94677, + 754123, + 516547, + -1495509, + -2659538, + 713273, + 5928627, + 3897081, + -7246946, + -12885789, + 1260913, + 21921343, + 15999375, + -20917006, + -41217199, + -1746803, + 59624424, + 50061434, + -47233203, + -110664167, + -19298386, + 148411975, + 150446876, + -106848480, + -342528155, + -120380359, + 641231123, + 1452959496, + 1660126023, + 1086085085, + 212080955, + -307561728, + -256832021, + 45371344, + 183767995, + 69160656, + -85413197, + -93549051, + 7374029, + 68151526, + 32032109, + -28912928, + -37067565, + -611794, + 23847481, + 12851240, + -8281091, + -12031262, + -1115332, + 6308177, + 3619051, + -1595144, + -2473833, + -337107, + 858708, + 422753, + 151647, + 801239, + 384495, + -1724837, + -2554883, + 1278651, + 6197458, + 3073746, + -8399618, + -12419072, + 3545060, + 23003821, + 13271542, + -24751944, + -40120149, + 4846650, + 63206787, + 43232613, + -57871311, + -109198371, + -2524568, + 160015465, + 134793593, + -138931183, + -346666015, + -64533381, + 731911512, + 1509299954, + 1634383090, + 1000367379, + 135737396, + -326215963, + -229947285, + 71349564, + 181647211, + 51073524, + -94028302, + -86010799, + 17411809, + 68451761, + 25326894, + -32713363, + -34574044, + 3221481, + 24204664, + 10575295, + -9648538, + -11313675, + 42056, + 6440036, + 3041944, + -1916494, + -2322149, + -130980, + 867779, + 350735, + 213957, + 837210, + 231714, + -1942477, + -2396726, + 1861481, + 6377894, + 2149771, + -9476451, + -11723353, + 5883287, + 23762671, + 10207985, + -28351651, + -38334736, + 11625365, + 65921433, + 35453593, + -67999571, + -105944589, + 14961808, + 169575146, + 116283278, + -170479876, + -345530212, + -2999325, + 822507798, + 1558613615, + 1600438980, + 912251174, + 63890242, + -338802300, + -200990197, + 95068726, + 176855826, + 32915286, + -100884739, + -77438022, + 26811829, + 67691360, + 18487748, + -35861795, + -31647763, + 6844029, + 24170537, + 8239428, + -10798568, + -10455088, + 1135157, + 6461249, + 2452564, + -2183978, + -2143310, + 59343, + 860027, + 280694, + 280694, + 860027, + 59343, + -2143310, + -2183978, + 2452564, + 6461249, + 1135157, + -10455088, + -10798568, + 8239428, + 24170537, + 6844029, + -31647763, + -35861795, + 18487748, + 67691360, + 26811829, + -77438022, + -100884739, + 32915286, + 176855826, + 95068726, + -200990197, + -338802300, + 63890242, + 912251174, + 1600438980, + 1558613615, + 822507798, + -2999325, + -345530212, + -170479876, + 116283278, + 169575146, + 14961808, + -105944589, + -67999571, + 35453593, + 65921433, + 11625365, + -38334736, + -28351651, + 10207985, + 23762671, + 5883287, + -11723353, + -9476451, + 2149771, + 6377894, + 1861481, + -2396726, + -1942477, + 231714, + 837210, + 213957, + 350735, + 867779, + -130980, + -2322149, + -1916494, + 3041944, + 6440036, + 42056, + -11313675, + -9648538, + 10575295, + 24204664, + 3221481, + -34574044, + -32713363, + 25326894, + 68451761, + 17411809, + -86010799, + -94028302, + 51073524, + 181647211, + 71349564, + -229947285, + -326215963, + 135737396, + 1000367379, + 1634383090, + 1509299954, + 731911512, + -64533381, + -346666015, + -138931183, + 134793593, + 160015465, + -2524568, + -109198371, + -57871311, + 43232613, + 63206787, + 4846650, + -40120149, + -24751944, + 13271542, + 23003821, + 3545060, + -12419072, + -8399618, + 3073746, + 6197458, + 1278651, + -2554883, + -1724837, + 384495, + 801239, + 151647, + 422753, + 858708, + -337107, + -2473833, + -1595144, + 3619051, + 6308177, + -1115332, + -12031262, + -8281091, + 12851240, + 23847481, + -611794, + -37067565, + -28912928, + 32032109, + 68151526, + 7374029, + -93549051, + -85413197, + 69160656, + 183767995, + 45371344, + -256832021, + -307561728, + 212080955, + 1086085085, + 1660126023, + 1452959496, + 641231123, + -120380359, + -342528155, + -106848480, + 150446876, + 148411975, + -19298386, + -110664167, + -47233203, + 50061434, + 59624424, + -1746803, + -41217199, + -20917006, + 15999375, + 21921343, + 1260913, + -12885789, + -7246946, + 3897081, + 5928627, + 713273, + -2659538, + -1495509, + 516547, + 754123, + 94677, + 495235, + 831259, + -556385, + -2593330, + -1221862, + 4172856, + 6061185, + -2320895, + -12588219, + -6708125, + 15026756, + 23087130, + -4602414, + -39069877, + -24495494, + 38490558, + 66754571, + -3166338, + -99893849, + -75106250, + 86890960, + 183069677, + 17423977, + -281127498, + -282691082, + 292400387, + 1168644329, + 1677424565, + 1390117010, + 551221746, + -170277306, + -333481955, + -74719692, + 163137422, + 135020465, + -35134065, + -110386358, + -36266428, + 55870368, + 55261912, + -8060106, + -41635843, + -16916165, + 18362938, + 20546560, + -935497, + -13127272, + -6040896, + 4611979, + 5581068, + 173684, + -2712649, + -1259449, + 627222, + 697925, + 43747, + 566497, + 784133, + -785673, + -2675850, + -799681, + 4692047, + 5696345, + -3556788, + -12966642, + -4945602, + 17061122, + 21917910, + -8692126, + -40528148, + -19507459, + 44589008, + 64240981, + -14061034, + -104899044, + -63203240, + 103972816, + 179440040, + -12160495, + -302325644, + -251519923, + 376120494, + 1247304899, + 1686115002, + 1321354559, + 462616824, + -214031286, + -319933915, + -43010753, + 172806238, + 120112884, + -49828498, + -108434030, + -25150589, + 60607931, + 50215641, + -14006308, + -41396262, + -12818575, + 20340641, + 18914085, + -3013466, + -13150751, + -4803656, + 5212861, + 5165217, + -332747, + -2716950, + -1021370, + 716335, + 634708, + -656 + +}; + +const struct src_stage src_int32_10_21_3455_5000 = { + 2, 1, 10, 56, 560, 21, 10, 0, 1, + src_int32_10_21_3455_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_16_21_4535_5000.h b/src/audio/src/coef/src_lite_int32_16_21_4535_5000.h new file mode 100755 index 000000000000..501428a0123c --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_16_21_4535_5000.h @@ -0,0 +1,1745 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_16_21_4535_5000_fir[1728] = { + 799, + 132548, + -237458, + 163037, + 137008, + -490003, + 568866, + -150959, + -608584, + 1157461, + -903513, + -247845, + 1616336, + -2080287, + 925035, + 1390657, + -3260464, + 2967835, + -125747, + -3614330, + 5395062, + -3229112, + -2117500, + 7067408, + -7494938, + 1982946, + 6387644, + -11521010, + 8576135, + 1848435, + -13027094, + 16206384, + -7182803, + -9405595, + 21958705, + -19700170, + 1371122, + 21847376, + -32609777, + 19771176, + 11591759, + -40731062, + 44028792, + -12719669, + -36910123, + 70064154, + -55384597, + -10385914, + 91902292, + -128786291, + 68413338, + 100493891, + -335647671, + 570282933, + 1550354162, + 475239535, + -333380739, + 125756558, + 45065562, + -120586607, + 98529888, + -23170055, + -46178896, + 69398403, + -43243988, + -4978485, + 40180454, + -42515442, + 16783332, + 15188800, + -31527430, + 24359440, + -2463430, + -17288397, + 22310574, + -11818057, + -4646717, + 15233275, + -13985714, + 3773527, + 7116328, + -11399306, + 7441754, + 657398, + -6813194, + 7350911, + -2994572, + -2445312, + 5193253, + -4004099, + 478333, + 2584868, + -3294662, + 1723693, + 576835, + -1942084, + 1722298, + -466722, + -740267, + 1136242, + -700452, + -38106, + 511464, + -504148, + 187982, + 120370, + -225161, + 144025, + 18116, + 117748, + -245243, + 203771, + 81605, + -465332, + 616080, + -263523, + -502078, + 1155448, + -1051728, + -19497, + 1475347, + -2178629, + 1260579, + 1023600, + -3159355, + 3296575, + -736641, + -3145257, + 5490255, + -3958525, + -1185268, + 6636675, + -8033714, + 3285512, + 5190606, + -11410737, + 9880164, + -137523, + -11793063, + 16862837, + -9603415, + -6774268, + 21158073, + -21741475, + 5223333, + 18862921, + -33044977, + 24009891, + 6099536, + -38098264, + 47037622, + -20314072, + -29731459, + 69319485, + -63630633, + 2863907, + 83254001, + -134579683, + 91133411, + 72058580, + -331088212, + 666195763, + 1539956755, + 382066261, + -324744664, + 147501708, + 21561511, + -110203492, + 103050924, + -35244659, + -36212990, + 67358138, + -48619587, + 2753102, + 35580674, + -43426746, + 21574313, + 10358540, + -29827326, + 26354454, + -6203820, + -14558725, + 22211850, + -13965912, + -2047278, + 13966721, + -14652998, + 5599933, + 5531876, + -11050932, + 8333620, + -664283, + -6004012, + 7483474, + -3799667, + -1623596, + 4890411, + -4307930, + 1063593, + 2156207, + -3262353, + 2016602, + 223185, + -1767515, + 1791768, + -671921, + -565579, + 1092724, + -776170, + 72759, + 445295, + -507774, + 233627, + 76701, + -208770, + 152078, + 35952, + 99799, + -248180, + 241649, + 22795, + -430348, + 651859, + -373465, + -382786, + 1129732, + -1181555, + 213834, + 1301542, + -2234364, + 1576392, + 629426, + -2992292, + 3563528, + -1342021, + -2605233, + 5475340, + -4617952, + -216050, + 6065464, + -8416689, + 4538364, + 3873103, + -11067820, + 11000056, + -2144834, + -10305319, + 17185566, + -11858157, + -3974790, + 19919613, + -23366625, + 9015439, + 15460825, + -32816368, + 27814934, + 413947, + -34659165, + 49134627, + -27606043, + -21840204, + 67156283, + -70733269, + 16321406, + 72713092, + -137785615, + 112751363, + 40869204, + -319328444, + 761945212, + 1519287652, + 291718396, + -310270900, + 165461449, + -1638961, + -97896238, + 105422494, + -46384504, + -25697878, + 64005912, + -52944168, + 10321102, + 30331301, + -43458036, + 25873999, + 5379955, + -27550848, + 27798620, + -9776324, + -11569472, + 21669744, + -15809246, + 562737, + 12435535, + -15019048, + 7292263, + 3856033, + -10485674, + 9047421, + -1955671, + -5085273, + 7464465, + -4517640, + -780964, + 4494065, + -4521009, + 1618589, + 1691167, + -3165270, + 2264187, + -128727, + -1560744, + 1824042, + -859590, + -383197, + 1028266, + -834585, + 179449, + 371922, + -501099, + 273180, + 32955, + -188774, + 156687, + 53940, + 78952, + -246024, + 275779, + -38299, + -385486, + 675161, + -478453, + -252867, + 1080318, + -1289946, + 447470, + 1097847, + -2245570, + 1865678, + 215714, + -2761593, + 3762270, + -1929479, + -2004177, + 5349012, + -5192999, + 770978, + 5363474, + -8634029, + 5715436, + 2460329, + -10496304, + 11910840, + -4133069, + -8590965, + 17164064, + -13899399, + -1061876, + 18263256, + -24537817, + 12669971, + 11704939, + -31920511, + 31103944, + -5352454, + -30472719, + 50264905, + -34443794, + -13384940, + 63594847, + -76528444, + 29719284, + 60448254, + -138269201, + 132798662, + 7413416, + -300085789, + 856480246, + 1488596462, + 205093365, + -290555025, + 179446779, + -24095718, + -83954743, + 105644567, + -56387043, + -14851755, + 59429268, + -56147217, + 17576937, + 24545760, + -42620013, + 29602625, + 354356, + -24750401, + 28669553, + -13111436, + -8383472, + 20700255, + -17314707, + 3130951, + 10673491, + -15080117, + 8818241, + 2123477, + -9717543, + 9571106, + -3191284, + -4076822, + 7296299, + -5135303, + 65404, + 4013511, + -4640417, + 2132661, + 1199647, + -3006418, + 2462249, + -471870, + -1326508, + 1819180, + -1026311, + -196945, + 944622, + -874921, + 279918, + 293013, + -484550, + 306024, + -9976, + -165718, + 157904, + 71688, + 55535, + -238630, + 305316, + -100472, + -331400, + 685176, + -576198, + -114746, + 1007701, + -1374231, + 676632, + 867857, + -2211202, + 2122065, + -209432, + -2470914, + 3887669, + -2486781, + -1353404, + 5112219, + -5670782, + 1756010, + 4543193, + -8679133, + 6791863, + 979732, + -9704925, + 12591478, + -6061700, + -6682019, + 16794674, + -15683273, + 1906819, + 16217627, + -25225991, + 16111327, + 7667035, + -30367420, + 33803972, + -11084049, + -25613746, + 50392312, + -40682514, + -4527884, + 58683939, + -80875390, + 42786073, + 46666377, + -135945654, + 150821679, + -27757971, + -273175757, + 948745932, + 1448253097, + 123019273, + -266245889, + 189348119, + -45395915, + -68693257, + 103759083, + -65075931, + -3895605, + 53738622, + -58181533, + 24380310, + 18346644, + -40940571, + 32692813, + -4617240, + -21488237, + 28956590, + -16145208, + -5066765, + 19327752, + -18456092, + 5606439, + 8718590, + -14838612, + 10149310, + 369602, + -8764441, + 9896587, + -4347089, + -3000043, + 6984350, + -5641660, + 898495, + 3459602, + -4665157, + 2596133, + 691921, + -2789993, + 2607655, + -799516, + -1070010, + 1777987, + -1169151, + -10646, + 843894, + -896784, + 372293, + 210305, + -458738, + 331697, + -51244, + -140190, + 155848, + 88793, + 29943, + -225961, + 329487, + -162458, + -268954, + 681350, + -664507, + 28922, + 912864, + -1432177, + 896539, + 615776, + -2131127, + 2339738, + -637535, + -2125193, + 3936006, + -3002121, + -665407, + 4768169, + -6040214, + 2719011, + 3619680, + -8548813, + 7744499, + -539515, + -8706988, + 13025346, + -7890913, + -4614832, + 16080745, + -17170610, + 4871833, + 13819569, + -25411524, + 19267324, + 3425450, + -28180515, + 35853071, + -16664454, + -20171634, + 49500450, + -46187379, + 4558159, + 52500273, + -83659865, + 55251443, + 31609332, + -130783246, + 166390683, + -64038136, + -238517308, + 1037697950, + 1398742448, + 46244627, + -238034178, + 195134491, + -65160874, + -52443802, + 99848267, + -72303981, + 6951192, + 47064722, + -59023818, + 30601879, + 11863157, + -38464027, + 35090763, + -9436120, + -17835089, + 28660868, + -18820469, + -1687237, + 17584386, + -19214793, + 7940726, + 6612249, + -14302974, + 11261164, + -1370205, + -7647758, + 10019850, + -5400959, + -1877407, + 6536806, + -6028099, + 1701802, + 2844504, + -4596148, + 3000491, + 178424, + -2521282, + 2698385, + -1105366, + -796803, + 1701983, + -1285718, + 171957, + 728484, + -900164, + 454915, + 125569, + -424448, + 349901, + -90064, + -112808, + 150707, + 104846, + 2635, + -208091, + 347608, + -222959, + -199212, + 663404, + -741327, + 175308, + 797270, + -1462050, + 1102504, + 346338, + -2006146, + 2513577, + -1059915, + -1730576, + 3905075, + -3464365, + 46373, + 4322301, + -6292256, + 3640115, + 2610298, + -8243401, + 8552418, + -2067085, + -7520155, + 13200616, + -9582430, + -2429395, + 15032648, + -18327783, + 7773077, + 11113492, + -25084734, + 22070695, + -936422, + -25396324, + 37201678, + -21978849, + -14248724, + 47593262, + -50836410, + 13693106, + 45147443, + -84796904, + 66851589, + 15550009, + -122805321, + 179108664, + -100772525, + -196136708, + 1122317086, + 1340657419, + -24570642, + -206640569, + 196851395, + -83052158, + -35549422, + 94032194, + -77955498, + 17475141, + 39555751, + -58674790, + 36125670, + 5228452, + -35250026, + 36757161, + -14007817, + -13868663, + 27795162, + -21087881, + 1686754, + 15509358, + -19580081, + 10088734, + 4398427, + -13487432, + 12134182, + -3061271, + -6391895, + 9940985, + -6333100, + -732011, + 5964460, + -6288534, + 2459648, + 2181435, + -4436176, + 3338543, + -330455, + -2206531, + 2733549, + -1383668, + -512678, + 1593360, + -1374198, + 347271, + 601035, + -885423, + 526358, + 40566, + -382614, + 360495, + -125728, + -84206, + 142723, + 119442, + -25874, + -185209, + 359099, + -280669, + -123418, + 631341, + -804797, + 321464, + 662840, + -1462656, + 1290034, + 64724, + -1837997, + 2639264, + -1467861, + -1294304, + 3794254, + -3863291, + 767813, + 3782202, + -6420130, + 4500036, + 1534387, + -7766792, + 9197358, + -3572097, + -6166142, + 13110564, + -11100299, + -168575, + 13667650, + -19127460, + 10551051, + 8150565, + -24246194, + 24460513, + -5331754, + -22063890, + 37813775, + -26916324, + -7958425, + 44695237, + -54523107, + 22693097, + 36754287, + -84233045, + 77334599, + -1212337, + -112091320, + 188619802, + -137268137, + -146169813, + 1201623485, + 1274690423, + -88862701, + -172803701, + 194617438, + -98776761, + -18357362, + 86465685, + -81947965, + 27472734, + 31374131, + -57158821, + 40851195, + -1423065, + -31372160, + 37667779, + -18243945, + -9671999, + 26383492, + -22906842, + 4987757, + 13148050, + -19549225, + 12009641, + 2122720, + -12411658, + 12753763, + -4670324, + -5023740, + 9664135, + -7126409, + 412897, + 5280465, + -6419487, + 3157492, + 1484382, + -4189812, + 3604536, + -824588, + -1852812, + 2713392, + -1629328, + -223537, + 1454926, + -1433377, + 511926, + 464378, + -853282, + 585461, + -42978, + -334300, + 363502, + -157617, + -55021, + 132190, + 132190, + -55021, + -157617, + 363502, + -334300, + -42978, + 585461, + -853282, + 464378, + 511926, + -1433377, + 1454926, + -223537, + -1629328, + 2713392, + -1852812, + -824588, + 3604536, + -4189812, + 1484382, + 3157492, + -6419487, + 5280465, + 412897, + -7126409, + 9664135, + -5023740, + -4670324, + 12753763, + -12411658, + 2122720, + 12009641, + -19549225, + 13148050, + 4987757, + -22906842, + 26383492, + -9671999, + -18243945, + 37667779, + -31372160, + -1423065, + 40851195, + -57158821, + 31374131, + 27472734, + -81947965, + 86465685, + -18357362, + -98776761, + 194617438, + -172803701, + -88862701, + 1274690423, + 1201623485, + -146169813, + -137268137, + 188619802, + -112091320, + -1212337, + 77334599, + -84233045, + 36754287, + 22693097, + -54523107, + 44695237, + -7958425, + -26916324, + 37813775, + -22063890, + -5331754, + 24460513, + -24246194, + 8150565, + 10551051, + -19127460, + 13667650, + -168575, + -11100299, + 13110564, + -6166142, + -3572097, + 9197358, + -7766792, + 1534387, + 4500036, + -6420130, + 3782202, + 767813, + -3863291, + 3794254, + -1294304, + -1467861, + 2639264, + -1837997, + 64724, + 1290034, + -1462656, + 662840, + 321464, + -804797, + 631341, + -123418, + -280669, + 359099, + -185209, + -25874, + 119442, + 142723, + -84206, + -125728, + 360495, + -382614, + 40566, + 526358, + -885423, + 601035, + 347271, + -1374198, + 1593360, + -512678, + -1383668, + 2733549, + -2206531, + -330455, + 3338543, + -4436176, + 2181435, + 2459648, + -6288534, + 5964460, + -732011, + -6333100, + 9940985, + -6391895, + -3061271, + 12134182, + -13487432, + 4398427, + 10088734, + -19580081, + 15509358, + 1686754, + -21087881, + 27795162, + -13868663, + -14007817, + 36757161, + -35250026, + 5228452, + 36125670, + -58674790, + 39555751, + 17475141, + -77955498, + 94032194, + -35549422, + -83052158, + 196851395, + -206640569, + -24570642, + 1340657419, + 1122317086, + -196136708, + -100772525, + 179108664, + -122805321, + 15550009, + 66851589, + -84796904, + 45147443, + 13693106, + -50836410, + 47593262, + -14248724, + -21978849, + 37201678, + -25396324, + -936422, + 22070695, + -25084734, + 11113492, + 7773077, + -18327783, + 15032648, + -2429395, + -9582430, + 13200616, + -7520155, + -2067085, + 8552418, + -8243401, + 2610298, + 3640115, + -6292256, + 4322301, + 46373, + -3464365, + 3905075, + -1730576, + -1059915, + 2513577, + -2006146, + 346338, + 1102504, + -1462050, + 797270, + 175308, + -741327, + 663404, + -199212, + -222959, + 347608, + -208091, + 2635, + 104846, + 150707, + -112808, + -90064, + 349901, + -424448, + 125569, + 454915, + -900164, + 728484, + 171957, + -1285718, + 1701983, + -796803, + -1105366, + 2698385, + -2521282, + 178424, + 3000491, + -4596148, + 2844504, + 1701802, + -6028099, + 6536806, + -1877407, + -5400959, + 10019850, + -7647758, + -1370205, + 11261164, + -14302974, + 6612249, + 7940726, + -19214793, + 17584386, + -1687237, + -18820469, + 28660868, + -17835089, + -9436120, + 35090763, + -38464027, + 11863157, + 30601879, + -59023818, + 47064722, + 6951192, + -72303981, + 99848267, + -52443802, + -65160874, + 195134491, + -238034178, + 46244627, + 1398742448, + 1037697950, + -238517308, + -64038136, + 166390683, + -130783246, + 31609332, + 55251443, + -83659865, + 52500273, + 4558159, + -46187379, + 49500450, + -20171634, + -16664454, + 35853071, + -28180515, + 3425450, + 19267324, + -25411524, + 13819569, + 4871833, + -17170610, + 16080745, + -4614832, + -7890913, + 13025346, + -8706988, + -539515, + 7744499, + -8548813, + 3619680, + 2719011, + -6040214, + 4768169, + -665407, + -3002121, + 3936006, + -2125193, + -637535, + 2339738, + -2131127, + 615776, + 896539, + -1432177, + 912864, + 28922, + -664507, + 681350, + -268954, + -162458, + 329487, + -225961, + 29943, + 88793, + 155848, + -140190, + -51244, + 331697, + -458738, + 210305, + 372293, + -896784, + 843894, + -10646, + -1169151, + 1777987, + -1070010, + -799516, + 2607655, + -2789993, + 691921, + 2596133, + -4665157, + 3459602, + 898495, + -5641660, + 6984350, + -3000043, + -4347089, + 9896587, + -8764441, + 369602, + 10149310, + -14838612, + 8718590, + 5606439, + -18456092, + 19327752, + -5066765, + -16145208, + 28956590, + -21488237, + -4617240, + 32692813, + -40940571, + 18346644, + 24380310, + -58181533, + 53738622, + -3895605, + -65075931, + 103759083, + -68693257, + -45395915, + 189348119, + -266245889, + 123019273, + 1448253097, + 948745932, + -273175757, + -27757971, + 150821679, + -135945654, + 46666377, + 42786073, + -80875390, + 58683939, + -4527884, + -40682514, + 50392312, + -25613746, + -11084049, + 33803972, + -30367420, + 7667035, + 16111327, + -25225991, + 16217627, + 1906819, + -15683273, + 16794674, + -6682019, + -6061700, + 12591478, + -9704925, + 979732, + 6791863, + -8679133, + 4543193, + 1756010, + -5670782, + 5112219, + -1353404, + -2486781, + 3887669, + -2470914, + -209432, + 2122065, + -2211202, + 867857, + 676632, + -1374231, + 1007701, + -114746, + -576198, + 685176, + -331400, + -100472, + 305316, + -238630, + 55535, + 71688, + 157904, + -165718, + -9976, + 306024, + -484550, + 293013, + 279918, + -874921, + 944622, + -196945, + -1026311, + 1819180, + -1326508, + -471870, + 2462249, + -3006418, + 1199647, + 2132661, + -4640417, + 4013511, + 65404, + -5135303, + 7296299, + -4076822, + -3191284, + 9571106, + -9717543, + 2123477, + 8818241, + -15080117, + 10673491, + 3130951, + -17314707, + 20700255, + -8383472, + -13111436, + 28669553, + -24750401, + 354356, + 29602625, + -42620013, + 24545760, + 17576937, + -56147217, + 59429268, + -14851755, + -56387043, + 105644567, + -83954743, + -24095718, + 179446779, + -290555025, + 205093365, + 1488596462, + 856480246, + -300085789, + 7413416, + 132798662, + -138269201, + 60448254, + 29719284, + -76528444, + 63594847, + -13384940, + -34443794, + 50264905, + -30472719, + -5352454, + 31103944, + -31920511, + 11704939, + 12669971, + -24537817, + 18263256, + -1061876, + -13899399, + 17164064, + -8590965, + -4133069, + 11910840, + -10496304, + 2460329, + 5715436, + -8634029, + 5363474, + 770978, + -5192999, + 5349012, + -2004177, + -1929479, + 3762270, + -2761593, + 215714, + 1865678, + -2245570, + 1097847, + 447470, + -1289946, + 1080318, + -252867, + -478453, + 675161, + -385486, + -38299, + 275779, + -246024, + 78952, + 53940, + 156687, + -188774, + 32955, + 273180, + -501099, + 371922, + 179449, + -834585, + 1028266, + -383197, + -859590, + 1824042, + -1560744, + -128727, + 2264187, + -3165270, + 1691167, + 1618589, + -4521009, + 4494065, + -780964, + -4517640, + 7464465, + -5085273, + -1955671, + 9047421, + -10485674, + 3856033, + 7292263, + -15019048, + 12435535, + 562737, + -15809246, + 21669744, + -11569472, + -9776324, + 27798620, + -27550848, + 5379955, + 25873999, + -43458036, + 30331301, + 10321102, + -52944168, + 64005912, + -25697878, + -46384504, + 105422494, + -97896238, + -1638961, + 165461449, + -310270900, + 291718396, + 1519287652, + 761945212, + -319328444, + 40869204, + 112751363, + -137785615, + 72713092, + 16321406, + -70733269, + 67156283, + -21840204, + -27606043, + 49134627, + -34659165, + 413947, + 27814934, + -32816368, + 15460825, + 9015439, + -23366625, + 19919613, + -3974790, + -11858157, + 17185566, + -10305319, + -2144834, + 11000056, + -11067820, + 3873103, + 4538364, + -8416689, + 6065464, + -216050, + -4617952, + 5475340, + -2605233, + -1342021, + 3563528, + -2992292, + 629426, + 1576392, + -2234364, + 1301542, + 213834, + -1181555, + 1129732, + -382786, + -373465, + 651859, + -430348, + 22795, + 241649, + -248180, + 99799, + 35952, + 152078, + -208770, + 76701, + 233627, + -507774, + 445295, + 72759, + -776170, + 1092724, + -565579, + -671921, + 1791768, + -1767515, + 223185, + 2016602, + -3262353, + 2156207, + 1063593, + -4307930, + 4890411, + -1623596, + -3799667, + 7483474, + -6004012, + -664283, + 8333620, + -11050932, + 5531876, + 5599933, + -14652998, + 13966721, + -2047278, + -13965912, + 22211850, + -14558725, + -6203820, + 26354454, + -29827326, + 10358540, + 21574313, + -43426746, + 35580674, + 2753102, + -48619587, + 67358138, + -36212990, + -35244659, + 103050924, + -110203492, + 21561511, + 147501708, + -324744664, + 382066261, + 1539956755, + 666195763, + -331088212, + 72058580, + 91133411, + -134579683, + 83254001, + 2863907, + -63630633, + 69319485, + -29731459, + -20314072, + 47037622, + -38098264, + 6099536, + 24009891, + -33044977, + 18862921, + 5223333, + -21741475, + 21158073, + -6774268, + -9603415, + 16862837, + -11793063, + -137523, + 9880164, + -11410737, + 5190606, + 3285512, + -8033714, + 6636675, + -1185268, + -3958525, + 5490255, + -3145257, + -736641, + 3296575, + -3159355, + 1023600, + 1260579, + -2178629, + 1475347, + -19497, + -1051728, + 1155448, + -502078, + -263523, + 616080, + -465332, + 81605, + 203771, + -245243, + 117748, + 18116, + 144025, + -225161, + 120370, + 187982, + -504148, + 511464, + -38106, + -700452, + 1136242, + -740267, + -466722, + 1722298, + -1942084, + 576835, + 1723693, + -3294662, + 2584868, + 478333, + -4004099, + 5193253, + -2445312, + -2994572, + 7350911, + -6813194, + 657398, + 7441754, + -11399306, + 7116328, + 3773527, + -13985714, + 15233275, + -4646717, + -11818057, + 22310574, + -17288397, + -2463430, + 24359440, + -31527430, + 15188800, + 16783332, + -42515442, + 40180454, + -4978485, + -43243988, + 69398403, + -46178896, + -23170055, + 98529888, + -120586607, + 45065562, + 125756558, + -333380739, + 475239535, + 1550354162, + 570282933, + -335647671, + 100493891, + 68413338, + -128786291, + 91902292, + -10385914, + -55384597, + 70064154, + -36910123, + -12719669, + 44028792, + -40731062, + 11591759, + 19771176, + -32609777, + 21847376, + 1371122, + -19700170, + 21958705, + -9405595, + -7182803, + 16206384, + -13027094, + 1848435, + 8576135, + -11521010, + 6387644, + 1982946, + -7494938, + 7067408, + -2117500, + -3229112, + 5395062, + -3614330, + -125747, + 2967835, + -3260464, + 1390657, + 925035, + -2080287, + 1616336, + -247845, + -903513, + 1157461, + -608584, + -150959, + 568866, + -490003, + 137008, + 163037, + -237458, + 132548, + 799 + +}; + +const struct src_stage src_int32_16_21_4535_5000 = { + 17, 13, 16, 108, 1728, 21, 16, 0, 0, + src_int32_16_21_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_1_2_4535_5000.h b/src/audio/src/coef/src_lite_int32_1_2_4535_5000.h new file mode 100755 index 000000000000..6665e93d8581 --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_1_2_4535_5000.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_4535_5000_fir[184] = { + -224121, + -49304, + 317798, + 126898, + -416245, + -245015, + 510714, + 409656, + -589845, + -624982, + 639804, + 892541, + -644607, + -1210496, + 586664, + 1572902, + -447516, + -1969093, + 208786, + 2383222, + 146694, + -2794008, + -633616, + 3174736, + 1262814, + -3493548, + -2039854, + 3714048, + 2963629, + -3796242, + -4025053, + 3697804, + 5205917, + -3375657, + -6477983, + 2787830, + 7802377, + -1895540, + -9129343, + 665441, + 10398403, + 928051, + -11538943, + -2900433, + 12471235, + 5254876, + -13107874, + -7980178, + 13355585, + 11048968, + -13117323, + -14416251, + 12294575, + 18018311, + -10789710, + -21772007, + 8508229, + 25574414, + -5360684, + -29302712, + 1264016, + 32814154, + 3858030, + -35945808, + -10075874, + 38513576, + 17457109, + -40309709, + -26072548, + 41097509, + 36007004, + -40600943, + -47377715, + 38485045, + 60366028, + -34319124, + -75273585, + 27506089, + 92627632, + -17140132, + -113394340, + 1697633, + 139458254, + 21712672, + -174863548, + -59488186, + 229755034, + 129377748, + -337816632, + -305987319, + 713182490, + 1858414351, + 1858414351, + 713182490, + -305987319, + -337816632, + 129377748, + 229755034, + -59488186, + -174863548, + 21712672, + 139458254, + 1697633, + -113394340, + -17140132, + 92627632, + 27506089, + -75273585, + -34319124, + 60366028, + 38485045, + -47377715, + -40600943, + 36007004, + 41097509, + -26072548, + -40309709, + 17457109, + 38513576, + -10075874, + -35945808, + 3858030, + 32814154, + 1264016, + -29302712, + -5360684, + 25574414, + 8508229, + -21772007, + -10789710, + 18018311, + 12294575, + -14416251, + -13117323, + 11048968, + 13355585, + -7980178, + -13107874, + 5254876, + 12471235, + -2900433, + -11538943, + 928051, + 10398403, + 665441, + -9129343, + -1895540, + 7802377, + 2787830, + -6477983, + -3375657, + 5205917, + 3697804, + -4025053, + -3796242, + 2963629, + 3714048, + -2039854, + -3493548, + 1262814, + 3174736, + -633616, + -2794008, + 146694, + 2383222, + 208786, + -1969093, + -447516, + 1572902, + 586664, + -1210496, + -644607, + 892541, + 639804, + -624982, + -589845, + 409656, + 510714, + -245015, + -416245, + 126898, + 317798, + -49304, + -224121 + +}; + +const struct src_stage src_int32_1_2_4535_5000 = { + 1, 0, 1, 184, 184, 2, 1, 0, 1, + src_int32_1_2_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_1_3_4535_5000.h b/src/audio/src/coef/src_lite_int32_1_3_4535_5000.h new file mode 100755 index 000000000000..7fa0f336b35b --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_1_3_4535_5000.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_3_4535_5000_fir[236] = { + -114015, + 51823, + 219093, + 204454, + -32440, + -302399, + -328340, + -19712, + 384204, + 487369, + 115513, + -453470, + -680437, + -265784, + 496199, + 902893, + 480386, + -495692, + -1145889, + -767174, + 433065, + 1395864, + 1130860, + -288041, + -1634252, + -1571825, + 39998, + 1837441, + 2084965, + 330732, + -1977058, + -2658644, + -841358, + 2020581, + 3273816, + 1504972, + -1932329, + -3903411, + -2328813, + 1674800, + 4512045, + 3312528, + -1210346, + -5056105, + -4446526, + 503134, + 5484260, + 5710509, + 478666, + -5738405, + -7072273, + -1760563, + 5755021, + 8486850, + 3359379, + -5466939, + -9896038, + -5280942, + 4805401, + 11228354, + 7517958, + -3702348, + -12399391, + -10048125, + 2092792, + 13312514, + 12832593, + 82899, + -13859785, + -15814785, + -2876991, + 13922895, + 18919587, + 6332884, + -13373813, + -22052802, + -10484429, + 12074667, + 25100685, + 15356417, + -9876144, + -27929186, + -20966780, + 6613272, + 30382249, + 27331301, + -2096689, + -32278015, + -34472193, + -3903963, + 33400837, + 42433047, + 11690882, + -33485013, + -51305117, + -21696146, + 32181788, + 61275774, + 34595698, + -28990353, + -72724747, + -51549627, + 23104028, + 86436375, + 74764001, + -13029449, + -104138671, + -109015692, + -4522194, + 130175559, + 166834180, + 38821942, + -178638160, + -294402477, + -130851727, + 331810943, + 908234714, + 1305300024, + 1305300024, + 908234714, + 331810943, + -130851727, + -294402477, + -178638160, + 38821942, + 166834180, + 130175559, + -4522194, + -109015692, + -104138671, + -13029449, + 74764001, + 86436375, + 23104028, + -51549627, + -72724747, + -28990353, + 34595698, + 61275774, + 32181788, + -21696146, + -51305117, + -33485013, + 11690882, + 42433047, + 33400837, + -3903963, + -34472193, + -32278015, + -2096689, + 27331301, + 30382249, + 6613272, + -20966780, + -27929186, + -9876144, + 15356417, + 25100685, + 12074667, + -10484429, + -22052802, + -13373813, + 6332884, + 18919587, + 13922895, + -2876991, + -15814785, + -13859785, + 82899, + 12832593, + 13312514, + 2092792, + -10048125, + -12399391, + -3702348, + 7517958, + 11228354, + 4805401, + -5280942, + -9896038, + -5466939, + 3359379, + 8486850, + 5755021, + -1760563, + -7072273, + -5738405, + 478666, + 5710509, + 5484260, + 503134, + -4446526, + -5056105, + -1210346, + 3312528, + 4512045, + 1674800, + -2328813, + -3903411, + -1932329, + 1504972, + 3273816, + 2020581, + -841358, + -2658644, + -1977058, + 330732, + 2084965, + 1837441, + 39998, + -1571825, + -1634252, + -288041, + 1130860, + 1395864, + 433065, + -767174, + -1145889, + -495692, + 480386, + 902893, + 496199, + -265784, + -680437, + -453470, + 115513, + 487369, + 384204, + -19712, + -328340, + -302399, + -32440, + 204454, + 219093, + 51823, + -114015 + +}; + +const struct src_stage src_int32_1_3_4535_5000 = { + 1, 0, 1, 236, 236, 3, 1, 0, 1, + src_int32_1_3_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_20_21_4167_5000.h b/src/audio/src/coef/src_lite_int32_20_21_4167_5000.h new file mode 100755 index 000000000000..7e93144ee13e --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_20_21_4167_5000.h @@ -0,0 +1,1217 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_4167_5000_fir[1200] = { + 5356, + -86589, + 268036, + -548333, + 867012, + -1090120, + 1020344, + -440324, + -811491, + 2745835, + -5134548, + 7463413, + -8958989, + 8710259, + -5883255, + -1879, + 8789289, + -19476630, + 30150523, + -38122888, + 40282655, + -33625635, + 15873737, + 13943469, + -55086105, + 105009578, + -159684990, + 214482385, + -266314523, + 324075642, + 1862904296, + 225301485, + -228938928, + 201119571, + -159324090, + 111812153, + -65112032, + 24390141, + 6876696, + -27113573, + 36572775, + -36977817, + 30975024, + -21518282, + 11312696, + -2413710, + -3968721, + 7462457, + -8366268, + 7393447, + -5400668, + 3163701, + -1236791, + -95624, + 790067, + -967722, + 823868, + -550349, + 286933, + -104869, + -6521, + -65226, + 242700, + -535415, + 895061, + -1196021, + 1238857, + -787427, + -358280, + 2264280, + -4764045, + 7393535, + -9395714, + 9820736, + -7726907, + 2458782, + 6050771, + -17029104, + 28742842, + -38571479, + 43302872, + -39626458, + 24744647, + 3023935, + -43804707, + 96061294, + -157038920, + 224266181, + -300599485, + 427246936, + 1851338587, + 131787966, + -189262861, + 184541060, + -156046245, + 116395666, + -73725273, + 34181131, + -2078302, + -20219799, + 32254240, + -35170051, + 31211775, + -23123849, + 13578381, + -4732986, + -2020264, + 6103427, + -7632063, + 7188247, + -5560067, + 3511787, + -1627040, + 240304, + 552728, + -831723, + 767047, + -541913, + 299359, + -119892, + -19414, + -41034, + 211095, + -511342, + 906837, + -1282747, + 1440975, + -1130322, + 114957, + 1726513, + -4293558, + 7181765, + -9664572, + 10769831, + -9463294, + 4922738, + 3144651, + -14214155, + 26767635, + -38302302, + 45563901, + -44993706, + 33320403, + -8173135, + -31451844, + 85082174, + -151348398, + 230158631, + -331014913, + 533877088, + 1828336959, + 44313969, + -148075932, + 165153449, + -149991055, + 118728634, + -80797692, + 43149222, + -10827004, + -13078515, + 27417839, + -32745020, + 30867170, + -24271765, + 15549331, + -6918564, + -74710, + 4660776, + -6773193, + 6854832, + -5612455, + 3785470, + -1975958, + 561450, + 313008, + -685174, + 698171, + -523660, + 305415, + -131565, + -33104, + -14345, + 173526, + -476078, + 901444, + -1347897, + 1622231, + -1462274, + 599721, + 1141293, + -3729507, + 6828711, + -9756613, + 11536029, + -11057304, + 7343478, + 122533, + -11077899, + 24251551, + -37307196, + 47009215, + -49614668, + 41434281, + -19443300, + -18235468, + 72227479, + -142630607, + 231905478, + -356805070, + 642964062, + 1794157248, + -36434791, + -106155705, + 143398408, + -141343938, + 118821058, + -86231955, + 51145555, + -19212022, + -5826044, + 22162288, + -29758750, + 29958252, + -24949351, + 17194711, + -8932600, + 1831926, + 3163071, + -5808421, + 6402446, + -5559548, + 3981642, + -2278215, + 862267, + 75480, + -531217, + 619032, + -496387, + 305318, + -139866, + -47333, + 14436, + 130443, + -429811, + 878285, + -1389408, + 1778415, + -1776549, + 1087048, + 518528, + -3080271, + 6337694, + -9666054, + 12100822, + -12475793, + 9674375, + -2960780, + -7673396, + 21231933, + -35591517, + 47596589, + -53388541, + 48925013, + -30576630, + -4384149, + 57690979, + -130958594, + 229316872, + -377249243, + 753454100, + 1749181882, + -109872910, + -64256645, + 119744135, + -130331670, + 116723297, + -89962667, + 58041993, + -27085593, + 1401720, + 16592267, + -26276635, + 28512204, + -25152880, + 18490319, + -10741185, + 3665095, + 1639290, + -4758057, + 5842334, + -5404987, + 4098726, + -2529510, + 1137756, + -155476, + -373020, + 531544, + -461030, + 299401, + -144849, + -61810, + 44829, + 82432, + -372960, + 837096, + -1405607, + 1905665, + -2066550, + 1567666, + -130892, + -2356066, + 5714745, + -9390454, + 12449127, + -13688258, + 11869567, + -6048267, + -4059773, + 17756311, + -33174292, + 47299153, + -56228549, + 55639910, + -41361505, + 9856718, + 41702329, + -116461520, + 222272805, + -391673351, + 864254619, + 1693912758, + -175520939, + -23099697, + 94676610, + -117217318, + 112524249, + -91956895, + 63733066, + -34312118, + 8471814, + 10816378, + -22372058, + 26565653, + -24887486, + 19418907, + -12314904, + 5392329, + 118271, + -3643548, + 5187477, + -5154216, + 4136666, + -2726618, + 1383550, + -375750, + -213719, + 437708, + -418640, + 288095, + -146633, + -76217, + 76292, + 30209, + -306176, + 777960, + -1395255, + 2000556, + -2325950, + 2032168, + -795268, + -1568802, + 4968559, + -8930841, + 12569647, + -14667467, + 13884844, + -9081719, + -301224, + 13881698, + -30088107, + 46106180, + -58063826, + 61437876, + -51588521, + 24229087, + 24523726, + -99323920, + 210727566, + -399461119, + 974247793, + 1628964531, + -233009478, + 16637376, + 68690803, + -102294663, + 106348885, + -92214106, + 68137467, + -40770425, + 15256597, + 4945065, + -18124890, + 24163828, + -24166897, + 19970370, + -13629284, + 6983800, + -1371824, + -2487046, + 4452317, + -4814340, + 4096890, + -2867424, + 1595974, + -581571, + -56354, + 339562, + -370358, + 271914, + -145397, + -90211, + 108227, + -25381, + -230340, + 701317, + -1357591, + 2060178, + -2548816, + 2471190, + -1462307, + -731894, + 4110386, + -8291766, + 12455168, + -15390050, + 15678519, + -12002822, + 3534112, + 9673682, + -26378739, + 44023582, + -58841043, + 66192274, + -61054434, + 38466758, + 6445906, + -79783975, + 194713108, + -400064663, + 1082304618, + 1555056413, + -282081676, + 54328754, + 42281974, + -85882230, + 98355195, + -90765514, + 71199069, + -46355736, + 21636009, + -911452, + -13619892, + 21359555, + -23013021, + 20141796, + -14665162, + 8412824, + -2804020, + -1310984, + 3652446, + -4393948, + 3982241, + -2950929, + 1772094, + -769565, + 96180, + 239147, + -317386, + 251445, + -141375, + -103436, + 139987, + -83385, + -146554, + 607974, + -1292364, + 2082213, + -2729746, + 2875593, + -2119334, + 139955, + 3153881, + -7481300, + 12102784, + -15837015, + 17212268, + -14754261, + 7375357, + 5205357, + -22104541, + 41074104, + -58525730, + 69793563, + -69566064, + 52300119, + -12216471, + -58130788, + 174341235, + -393014289, + 1187299281, + 1473002595, + -322594116, + 89408311, + 15937211, + -68317018, + 88730604, + -87672864, + 72887475, + -50981281, + 27499649, + -6645216, + -8945059, + 18212146, + -21455388, + 19937379, + -15408928, + 9656291, + -4153002, + -137648, + 2804288, + -3902915, + 3796886, + -2977237, + 1909752, + -936811, + 241189, + 138464, + -260964, + 227329, + -134843, + -115525, + 170894, + -142749, + -56128, + 499101, + -1199851, + 2064997, + -2863981, + 3236644, + -2753532, + 1031010, + 2114898, + -6510959, + 11514045, + -15994206, + 18451924, + -17280817, + 11150188, + 556073, + -17335570, + 37297207, + -57103275, + 72151677, + -76944096, + 65461058, + -31129984, + -34700698, + 149804573, + -377927364, + 1288123615, + 1383701443, + -354516099, + 121376255, + -9872665, + -49948071, + 77687944, + -83026692, + 73198084, + -54579570, + 32748631, + -12152484, + -4189936, + 14786175, + -19530460, + 19368208, + -15852669, + 10695022, + -5395557, + 1011237, + 1924774, + -3352183, + 3546202, + -2947524, + 2007578, + -1080876, + 376220, + 39434, + -202340, + 200244, + -126113, + -126113, + 200244, + -202340, + 39434, + 376220, + -1080876, + 2007578, + -2947524, + 3546202, + -3352183, + 1924774, + 1011237, + -5395557, + 10695022, + -15852669, + 19368208, + -19530460, + 14786175, + -4189936, + -12152484, + 32748631, + -54579570, + 73198084, + -83026692, + 77687944, + -49948071, + -9872665, + 121376255, + -354516099, + 1383701443, + 1288123615, + -377927364, + 149804573, + -34700698, + -31129984, + 65461058, + -76944096, + 72151677, + -57103275, + 37297207, + -17335570, + 556073, + 11150188, + -17280817, + 18451924, + -15994206, + 11514045, + -6510959, + 2114898, + 1031010, + -2753532, + 3236644, + -2863981, + 2064997, + -1199851, + 499101, + -56128, + -142749, + 170894, + -115525, + -134843, + 227329, + -260964, + 138464, + 241189, + -936811, + 1909752, + -2977237, + 3796886, + -3902915, + 2804288, + -137648, + -4153002, + 9656291, + -15408928, + 19937379, + -21455388, + 18212146, + -8945059, + -6645216, + 27499649, + -50981281, + 72887475, + -87672864, + 88730604, + -68317018, + 15937211, + 89408311, + -322594116, + 1473002595, + 1187299281, + -393014289, + 174341235, + -58130788, + -12216471, + 52300119, + -69566064, + 69793563, + -58525730, + 41074104, + -22104541, + 5205357, + 7375357, + -14754261, + 17212268, + -15837015, + 12102784, + -7481300, + 3153881, + 139955, + -2119334, + 2875593, + -2729746, + 2082213, + -1292364, + 607974, + -146554, + -83385, + 139987, + -103436, + -141375, + 251445, + -317386, + 239147, + 96180, + -769565, + 1772094, + -2950929, + 3982241, + -4393948, + 3652446, + -1310984, + -2804020, + 8412824, + -14665162, + 20141796, + -23013021, + 21359555, + -13619892, + -911452, + 21636009, + -46355736, + 71199069, + -90765514, + 98355195, + -85882230, + 42281974, + 54328754, + -282081676, + 1555056413, + 1082304618, + -400064663, + 194713108, + -79783975, + 6445906, + 38466758, + -61054434, + 66192274, + -58841043, + 44023582, + -26378739, + 9673682, + 3534112, + -12002822, + 15678519, + -15390050, + 12455168, + -8291766, + 4110386, + -731894, + -1462307, + 2471190, + -2548816, + 2060178, + -1357591, + 701317, + -230340, + -25381, + 108227, + -90211, + -145397, + 271914, + -370358, + 339562, + -56354, + -581571, + 1595974, + -2867424, + 4096890, + -4814340, + 4452317, + -2487046, + -1371824, + 6983800, + -13629284, + 19970370, + -24166897, + 24163828, + -18124890, + 4945065, + 15256597, + -40770425, + 68137467, + -92214106, + 106348885, + -102294663, + 68690803, + 16637376, + -233009478, + 1628964531, + 974247793, + -399461119, + 210727566, + -99323920, + 24523726, + 24229087, + -51588521, + 61437876, + -58063826, + 46106180, + -30088107, + 13881698, + -301224, + -9081719, + 13884844, + -14667467, + 12569647, + -8930841, + 4968559, + -1568802, + -795268, + 2032168, + -2325950, + 2000556, + -1395255, + 777960, + -306176, + 30209, + 76292, + -76217, + -146633, + 288095, + -418640, + 437708, + -213719, + -375750, + 1383550, + -2726618, + 4136666, + -5154216, + 5187477, + -3643548, + 118271, + 5392329, + -12314904, + 19418907, + -24887486, + 26565653, + -22372058, + 10816378, + 8471814, + -34312118, + 63733066, + -91956895, + 112524249, + -117217318, + 94676610, + -23099697, + -175520939, + 1693912758, + 864254619, + -391673351, + 222272805, + -116461520, + 41702329, + 9856718, + -41361505, + 55639910, + -56228549, + 47299153, + -33174292, + 17756311, + -4059773, + -6048267, + 11869567, + -13688258, + 12449127, + -9390454, + 5714745, + -2356066, + -130892, + 1567666, + -2066550, + 1905665, + -1405607, + 837096, + -372960, + 82432, + 44829, + -61810, + -144849, + 299401, + -461030, + 531544, + -373020, + -155476, + 1137756, + -2529510, + 4098726, + -5404987, + 5842334, + -4758057, + 1639290, + 3665095, + -10741185, + 18490319, + -25152880, + 28512204, + -26276635, + 16592267, + 1401720, + -27085593, + 58041993, + -89962667, + 116723297, + -130331670, + 119744135, + -64256645, + -109872910, + 1749181882, + 753454100, + -377249243, + 229316872, + -130958594, + 57690979, + -4384149, + -30576630, + 48925013, + -53388541, + 47596589, + -35591517, + 21231933, + -7673396, + -2960780, + 9674375, + -12475793, + 12100822, + -9666054, + 6337694, + -3080271, + 518528, + 1087048, + -1776549, + 1778415, + -1389408, + 878285, + -429811, + 130443, + 14436, + -47333, + -139866, + 305318, + -496387, + 619032, + -531217, + 75480, + 862267, + -2278215, + 3981642, + -5559548, + 6402446, + -5808421, + 3163071, + 1831926, + -8932600, + 17194711, + -24949351, + 29958252, + -29758750, + 22162288, + -5826044, + -19212022, + 51145555, + -86231955, + 118821058, + -141343938, + 143398408, + -106155705, + -36434791, + 1794157248, + 642964062, + -356805070, + 231905478, + -142630607, + 72227479, + -18235468, + -19443300, + 41434281, + -49614668, + 47009215, + -37307196, + 24251551, + -11077899, + 122533, + 7343478, + -11057304, + 11536029, + -9756613, + 6828711, + -3729507, + 1141293, + 599721, + -1462274, + 1622231, + -1347897, + 901444, + -476078, + 173526, + -14345, + -33104, + -131565, + 305415, + -523660, + 698171, + -685174, + 313008, + 561450, + -1975958, + 3785470, + -5612455, + 6854832, + -6773193, + 4660776, + -74710, + -6918564, + 15549331, + -24271765, + 30867170, + -32745020, + 27417839, + -13078515, + -10827004, + 43149222, + -80797692, + 118728634, + -149991055, + 165153449, + -148075932, + 44313969, + 1828336959, + 533877088, + -331014913, + 230158631, + -151348398, + 85082174, + -31451844, + -8173135, + 33320403, + -44993706, + 45563901, + -38302302, + 26767635, + -14214155, + 3144651, + 4922738, + -9463294, + 10769831, + -9664572, + 7181765, + -4293558, + 1726513, + 114957, + -1130322, + 1440975, + -1282747, + 906837, + -511342, + 211095, + -41034, + -19414, + -119892, + 299359, + -541913, + 767047, + -831723, + 552728, + 240304, + -1627040, + 3511787, + -5560067, + 7188247, + -7632063, + 6103427, + -2020264, + -4732986, + 13578381, + -23123849, + 31211775, + -35170051, + 32254240, + -20219799, + -2078302, + 34181131, + -73725273, + 116395666, + -156046245, + 184541060, + -189262861, + 131787966, + 1851338587, + 427246936, + -300599485, + 224266181, + -157038920, + 96061294, + -43804707, + 3023935, + 24744647, + -39626458, + 43302872, + -38571479, + 28742842, + -17029104, + 6050771, + 2458782, + -7726907, + 9820736, + -9395714, + 7393535, + -4764045, + 2264280, + -358280, + -787427, + 1238857, + -1196021, + 895061, + -535415, + 242700, + -65226, + -6521, + -104869, + 286933, + -550349, + 823868, + -967722, + 790067, + -95624, + -1236791, + 3163701, + -5400668, + 7393447, + -8366268, + 7462457, + -3968721, + -2413710, + 11312696, + -21518282, + 30975024, + -36977817, + 36572775, + -27113573, + 6876696, + 24390141, + -65112032, + 111812153, + -159324090, + 201119571, + -228938928, + 225301485, + 1862904296, + 324075642, + -266314523, + 214482385, + -159684990, + 105009578, + -55086105, + 13943469, + 15873737, + -33625635, + 40282655, + -38122888, + 30150523, + -19476630, + 8789289, + -1879, + -5883255, + 8710259, + -8958989, + 7463413, + -5134548, + 2745835, + -811491, + -440324, + 1020344, + -1090120, + 867012, + -548333, + 268036, + -86589, + 5356 + +}; + +const struct src_stage src_int32_20_21_4167_5000 = { + 1, 1, 20, 60, 1200, 21, 20, 0, 0, + src_int32_20_21_4167_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_3_2_4535_5000.h b/src/audio/src/coef/src_lite_int32_3_2_4535_5000.h new file mode 100755 index 000000000000..3f64214097ac --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_3_2_4535_5000.h @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_2_4535_5000_fir[276] = { + -98079, + 150065, + -205969, + 259790, + -303242, + 325746, + -314605, + 255379, + -132488, + -69959, + 367127, + -772214, + 1295079, + -1940762, + 2707995, + -3587771, + 4562059, + -5602758, + 6670992, + -7716790, + 8679256, + -9487245, + 10060574, + -10311759, + 10148236, + -9474983, + 8197436, + -6224556, + 3471851, + 135853, + -4662155, + 10157660, + -16659760, + 24194161, + -32778856, + 42431743, + -53183855, + 65101944, + -78327870, + 93150998, + -110152103, + 130521112, + -156864944, + 195715122, + -268224335, + 497839322, + 1958067093, + -196362819, + 58312833, + -6802826, + -19641225, + 34920892, + -43960645, + 48988891, + -51201917, + 51335964, + -49898844, + 47274356, + -43772636, + 39655316, + -35148125, + 30447022, + -25720991, + 21113213, + -16741593, + 12699211, + -9055020, + 5854961, + -3123546, + 865910, + 929740, + -2289366, + 3250152, + -3857496, + 4162049, + -4216929, + 4075212, + -3787751, + 3401417, + -2957762, + 2492123, + -2033153, + 1602744, + -1216285, + 883201, + -607701, + 389663, + -225588, + 109563, + -34169, + -8699, + 27139, + -85506, + 151343, + -241173, + 356212, + -495575, + 655680, + -829709, + 1007172, + -1173639, + 1310673, + -1396025, + 1404119, + -1306859, + 1074749, + -678344, + 89969, + 714314, + -1752577, + 3034811, + -4560732, + 6317696, + -8278855, + 10401632, + -12626617, + 14876952, + -17058228, + 19058912, + -20751220, + 21992344, + -22625808, + 22482664, + -21382054, + 19130451, + -15518550, + 10314125, + -3248061, + -6011418, + 17905822, + -33074165, + 52524501, + -77994721, + 112795501, + -164097575, + 250704554, + -441905822, + 1362518492, + 1362518492, + -441905822, + 250704554, + -164097575, + 112795501, + -77994721, + 52524501, + -33074165, + 17905822, + -6011418, + -3248061, + 10314125, + -15518550, + 19130451, + -21382054, + 22482664, + -22625808, + 21992344, + -20751220, + 19058912, + -17058228, + 14876952, + -12626617, + 10401632, + -8278855, + 6317696, + -4560732, + 3034811, + -1752577, + 714314, + 89969, + -678344, + 1074749, + -1306859, + 1404119, + -1396025, + 1310673, + -1173639, + 1007172, + -829709, + 655680, + -495575, + 356212, + -241173, + 151343, + -85506, + 27139, + -8699, + -34169, + 109563, + -225588, + 389663, + -607701, + 883201, + -1216285, + 1602744, + -2033153, + 2492123, + -2957762, + 3401417, + -3787751, + 4075212, + -4216929, + 4162049, + -3857496, + 3250152, + -2289366, + 929740, + 865910, + -3123546, + 5854961, + -9055020, + 12699211, + -16741593, + 21113213, + -25720991, + 30447022, + -35148125, + 39655316, + -43772636, + 47274356, + -49898844, + 51335964, + -51201917, + 48988891, + -43960645, + 34920892, + -19641225, + -6802826, + 58312833, + -196362819, + 1958067093, + 497839322, + -268224335, + 195715122, + -156864944, + 130521112, + -110152103, + 93150998, + -78327870, + 65101944, + -53183855, + 42431743, + -32778856, + 24194161, + -16659760, + 10157660, + -4662155, + 135853, + 3471851, + -6224556, + 8197436, + -9474983, + 10148236, + -10311759, + 10060574, + -9487245, + 8679256, + -7716790, + 6670992, + -5602758, + 4562059, + -3587771, + 2707995, + -1940762, + 1295079, + -772214, + 367127, + -69959, + -132488, + 255379, + -314605, + 325746, + -303242, + 259790, + -205969, + 150065, + -98079 + +}; + +const struct src_stage src_int32_3_2_4535_5000 = { + 1, 2, 3, 92, 276, 2, 3, 0, 0, + src_int32_3_2_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_8_7_4535_5000.h b/src/audio/src/coef/src_lite_int32_8_7_4535_5000.h new file mode 100755 index 000000000000..ec4acffbd34d --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_8_7_4535_5000.h @@ -0,0 +1,785 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_4535_5000_fir[768] = { + -58861, + 107730, + -172832, + 253113, + -345154, + 442724, + -536475, + 613835, + -659148, + 654109, + -578518, + 411358, + -132190, + -277178, + 830815, + -1536667, + 2394538, + -3394193, + 4513693, + -5718126, + 6958833, + -8173276, + 9285610, + -10208025, + 10842889, + -11085635, + 10828347, + -9963901, + 8390502, + -6016416, + 2764633, + 1422777, + -6580922, + 12719243, + -19819870, + 27837503, + -36701176, + 46318383, + -56582293, + 67383346, + -78627835, + 90269111, + -102364886, + 115196250, + -129556926, + 147617716, + -176444477, + 253986077, + 2019194931, + -9702485, + -51009915, + 70542082, + -78300494, + 80541275, + -79490419, + 76215681, + -71356391, + 65365272, + -58601572, + 51369665, + -43935065, + 36530379, + -29356755, + 22583516, + -16347364, + 10751915, + -5867960, + 1734621, + 1638567, + -4268709, + 6195894, + -7478983, + 8191088, + -8414932, + 8238316, + -7749886, + 7035366, + -6174380, + 5237958, + -4286770, + 3370088, + -2525438, + 1778886, + -1145840, + 632287, + -236307, + -50238, + 239962, + -348276, + 391852, + -387300, + 350112, + -293878, + 229794, + -166436, + 109764, + -44571, + 89386, + -154606, + 241909, + -350970, + 478818, + -619265, + 762467, + -894683, + 998299, + -1052171, + 1032307, + -912940, + 667957, + -272669, + -294135, + 1047934, + -1996139, + 3135791, + -4451437, + 5913338, + -7476151, + 9078212, + -10641536, + 12072607, + -13263995, + 14096796, + -14443813, + 14173386, + -13153661, + 11257097, + -8364884, + 4370953, + 814873, + -7265082, + 15034706, + -24164477, + 34688300, + -46647352, + 60115038, + -75241272, + 92334387, + -112024252, + 135622799, + -166042347, + 210657968, + -293620014, + 559032609, + 1927341306, + -216535025, + 66484062, + -9572017, + -19892674, + 36968896, + -47029827, + 52525511, + -54786258, + 54644444, + -52686087, + 49363575, + -45049265, + 40061513, + -34677057, + 29136472, + -23646202, + 18379103, + -13474576, + 9038951, + -5146446, + 1840864, + 861946, + -2970941, + 4516165, + -5544644, + 6116079, + -6298532, + 6164299, + -5786133, + 5233945, + -4572102, + 3857366, + -3137506, + 2450561, + -1824720, + 1278719, + -822683, + 459292, + -185155, + -7712, + 130408, + -195765, + 217120, + -207304, + 177864, + -138538, + 96973, + -21246, + 55583, + -112011, + 194828, + -306973, + 449256, + -619588, + 812262, + -1017350, + 1220309, + -1401842, + 1538105, + -1601289, + 1560626, + -1383811, + 1038840, + -496203, + -268646, + 1272637, + -2522383, + 4011584, + -5718684, + 7604937, + -9613042, + 11666462, + -13669531, + 15508401, + -17052838, + 18158796, + -18671667, + 18429989, + -17269341, + 15026041, + -11540148, + 6657081, + -226948, + -7899825, + 17882732, + -29911056, + 44240341, + -61259457, + 81618825, + -106493210, + 138177777, + -181647379, + 249584651, + -385262034, + 885056226, + 1751164779, + -357102982, + 162535669, + -82214981, + 37596078, + -9315679, + -9716373, + 22736279, + -31466906, + 36947913, + -39879854, + 40782453, + -40072356, + 38102583, + -35182487, + 31587350, + -27562402, + 23323941, + -19059124, + 14925388, + -11050078, + 7530617, + -4435408, + 1805497, + 343032, + -2016030, + 3237777, + -4047174, + 4493808, + -4634081, + 4527564, + -4233729, + 3809155, + -3305295, + 2766850, + -2230735, + 1725624, + -1272017, + 882736, + -563771, + 315366, + -133247, + 9891, + 64246, + -99615, + 106627, + -94901, + 72734, + 8746, + 9642, + -48955, + 115660, + -215699, + 353703, + -532115, + 750272, + -1003520, + 1282430, + -1572200, + 1852328, + -2096633, + 2273682, + -2347675, + 2279814, + -2030139, + 1559813, + -833772, + -176352, + 1489154, + -3110392, + 5030075, + -7219897, + 9631154, + -12193309, + 14813305, + -17375711, + 19743703, + -21760828, + 23253432, + -24033492, + 23901512, + -22648954, + 20059463, + -15907783, + 9954680, + -1935116, + -8465113, + 21653277, + -38212357, + 59062537, + -85799061, + 121474736, + -172697737, + 256633647, + -434876583, + 1208546295, + 1504990845, + -428638782, + 227566150, + -138615525, + 86699498, + -52063878, + 27282323, + -8942427, + -4756519, + 14877739, + -22116972, + 26976044, + -29849992, + 31072378, + -30938885, + 29719032, + -27661193, + 24993877, + -21925020, + 18640416, + -15301984, + 12046364, + -8984106, + 6199612, + -3751897, + 1676124, + 14150, + -1324173, + 2274780, + -2898949, + 3238291, + -3339654, + 3251986, + -3023562, + 2699692, + -2320942, + 1921893, + -1530438, + 1167569, + -847590, + 578678, + -363716, + 201280, + -86715, + 13203, + 27242, + -42901, + 41645, + 41645, + -42901, + 27242, + 13203, + -86715, + 201280, + -363716, + 578678, + -847590, + 1167569, + -1530438, + 1921893, + -2320942, + 2699692, + -3023562, + 3251986, + -3339654, + 3238291, + -2898949, + 2274780, + -1324173, + 14150, + 1676124, + -3751897, + 6199612, + -8984106, + 12046364, + -15301984, + 18640416, + -21925020, + 24993877, + -27661193, + 29719032, + -30938885, + 31072378, + -29849992, + 26976044, + -22116972, + 14877739, + -4756519, + -8942427, + 27282323, + -52063878, + 86699498, + -138615525, + 227566150, + -428638782, + 1504990845, + 1208546295, + -434876583, + 256633647, + -172697737, + 121474736, + -85799061, + 59062537, + -38212357, + 21653277, + -8465113, + -1935116, + 9954680, + -15907783, + 20059463, + -22648954, + 23901512, + -24033492, + 23253432, + -21760828, + 19743703, + -17375711, + 14813305, + -12193309, + 9631154, + -7219897, + 5030075, + -3110392, + 1489154, + -176352, + -833772, + 1559813, + -2030139, + 2279814, + -2347675, + 2273682, + -2096633, + 1852328, + -1572200, + 1282430, + -1003520, + 750272, + -532115, + 353703, + -215699, + 115660, + -48955, + 9642, + 8746, + 72734, + -94901, + 106627, + -99615, + 64246, + 9891, + -133247, + 315366, + -563771, + 882736, + -1272017, + 1725624, + -2230735, + 2766850, + -3305295, + 3809155, + -4233729, + 4527564, + -4634081, + 4493808, + -4047174, + 3237777, + -2016030, + 343032, + 1805497, + -4435408, + 7530617, + -11050078, + 14925388, + -19059124, + 23323941, + -27562402, + 31587350, + -35182487, + 38102583, + -40072356, + 40782453, + -39879854, + 36947913, + -31466906, + 22736279, + -9716373, + -9315679, + 37596078, + -82214981, + 162535669, + -357102982, + 1751164779, + 885056226, + -385262034, + 249584651, + -181647379, + 138177777, + -106493210, + 81618825, + -61259457, + 44240341, + -29911056, + 17882732, + -7899825, + -226948, + 6657081, + -11540148, + 15026041, + -17269341, + 18429989, + -18671667, + 18158796, + -17052838, + 15508401, + -13669531, + 11666462, + -9613042, + 7604937, + -5718684, + 4011584, + -2522383, + 1272637, + -268646, + -496203, + 1038840, + -1383811, + 1560626, + -1601289, + 1538105, + -1401842, + 1220309, + -1017350, + 812262, + -619588, + 449256, + -306973, + 194828, + -112011, + 55583, + -21246, + 96973, + -138538, + 177864, + -207304, + 217120, + -195765, + 130408, + -7712, + -185155, + 459292, + -822683, + 1278719, + -1824720, + 2450561, + -3137506, + 3857366, + -4572102, + 5233945, + -5786133, + 6164299, + -6298532, + 6116079, + -5544644, + 4516165, + -2970941, + 861946, + 1840864, + -5146446, + 9038951, + -13474576, + 18379103, + -23646202, + 29136472, + -34677057, + 40061513, + -45049265, + 49363575, + -52686087, + 54644444, + -54786258, + 52525511, + -47029827, + 36968896, + -19892674, + -9572017, + 66484062, + -216535025, + 1927341306, + 559032609, + -293620014, + 210657968, + -166042347, + 135622799, + -112024252, + 92334387, + -75241272, + 60115038, + -46647352, + 34688300, + -24164477, + 15034706, + -7265082, + 814873, + 4370953, + -8364884, + 11257097, + -13153661, + 14173386, + -14443813, + 14096796, + -13263995, + 12072607, + -10641536, + 9078212, + -7476151, + 5913338, + -4451437, + 3135791, + -1996139, + 1047934, + -294135, + -272669, + 667957, + -912940, + 1032307, + -1052171, + 998299, + -894683, + 762467, + -619265, + 478818, + -350970, + 241909, + -154606, + 89386, + -44571, + 109764, + -166436, + 229794, + -293878, + 350112, + -387300, + 391852, + -348276, + 239962, + -50238, + -236307, + 632287, + -1145840, + 1778886, + -2525438, + 3370088, + -4286770, + 5237958, + -6174380, + 7035366, + -7749886, + 8238316, + -8414932, + 8191088, + -7478983, + 6195894, + -4268709, + 1638567, + 1734621, + -5867960, + 10751915, + -16347364, + 22583516, + -29356755, + 36530379, + -43935065, + 51369665, + -58601572, + 65365272, + -71356391, + 76215681, + -79490419, + 80541275, + -78300494, + 70542082, + -51009915, + -9702485, + 2019194931, + 253986077, + -176444477, + 147617716, + -129556926, + 115196250, + -102364886, + 90269111, + -78627835, + 67383346, + -56582293, + 46318383, + -36701176, + 27837503, + -19819870, + 12719243, + -6580922, + 1422777, + 2764633, + -6016416, + 8390502, + -9963901, + 10828347, + -11085635, + 10842889, + -10208025, + 9285610, + -8173276, + 6958833, + -5718126, + 4513693, + -3394193, + 2394538, + -1536667, + 830815, + -277178, + -132190, + 411358, + -578518, + 654109, + -659148, + 613835, + -536475, + 442724, + -345154, + 253113, + -172832, + 107730, + -58861 + +}; + +const struct src_stage src_int32_8_7_4535_5000 = { + 6, 7, 8, 96, 768, 7, 8, 0, 0, + src_int32_8_7_4535_5000_fir}; +/** \endcond */ diff --git a/src/audio/src/coef/src_lite_int32_define.h b/src/audio/src/coef/src_lite_int32_define.h new file mode 100755 index 000000000000..e137b16ccfaa --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_define.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_LITE_INT32_DEFINE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_LITE_INT32_DEFINE_H__ + +/* SRC constants */ +#define MAX_FIR_DELAY_SIZE 384 +#define MAX_OUT_DELAY_SIZE 196 +#define MAX_BLK_IN 21 +#define MAX_BLK_OUT 20 +#define NUM_IN_FS 3 +#define NUM_OUT_FS 2 +#define STAGE1_TIMES_MAX 21 +#define STAGE2_TIMES_MAX 10 +#define STAGE_BUF_SIZE 210 +#define NUM_ALL_COEFFICIENTS 4952 + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_LITE_INT32_DEFINE_H__ */ diff --git a/src/audio/src/coef/src_lite_int32_table.h b/src/audio/src/coef/src_lite_int32_table.h new file mode 100755 index 000000000000..26c21fbd5b69 --- /dev/null +++ b/src/audio/src/coef/src_lite_int32_table.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + */ + +/** \cond GENERATED_BY_TOOLS_TUNE_SRC */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_LITE_INT32_TABLE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_LITE_INT32_TABLE_H__ + +/* SRC conversions */ +#include "src_lite_int32_1_2_4535_5000.h" +#include "src_lite_int32_1_3_4535_5000.h" +#include "src_lite_int32_3_2_4535_5000.h" +#include "src_lite_int32_8_7_4535_5000.h" +#include "src_lite_int32_10_21_3455_5000.h" +#include "src_lite_int32_16_21_4535_5000.h" +#include "src_lite_int32_20_21_4167_5000.h" +#include <stdint.h> + +/* SRC table */ +const int32_t fir_one = 1073741824; +const struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; +const struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; +const int src_in_fs[3] = { 32000, 44100, 48000}; +const int src_out_fs[2] = { 16000, 48000}; +const struct src_stage * const src_table1[2][3] = { + { &src_int32_1_2_4535_5000, &src_int32_10_21_3455_5000, + &src_int32_1_3_4535_5000}, + { &src_int32_3_2_4535_5000, + &src_int32_8_7_4535_5000, &src_int32_1_1_0_0 + } +}; + +const struct src_stage * const src_table2[2][3] = { + { &src_int32_1_1_0_0, &src_int32_16_21_4535_5000, + &src_int32_1_1_0_0}, + { &src_int32_1_1_0_0, + &src_int32_20_21_4167_5000, &src_int32_1_1_0_0 + } +}; + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_LITE_INT32_TABLE_H__ */ + +/** \endcond */ diff --git a/src/audio/src/coef/src_small_int32_1_2_2268_5000.h b/src/audio/src/coef/src_small_int32_1_2_2268_5000.h new file mode 100644 index 000000000000..c76d8df21cac --- /dev/null +++ b/src/audio/src/coef/src_small_int32_1_2_2268_5000.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_2268_5000_fir[40] = { + -102613, + 1042618, + 2316615, + -298661, + -7113516, + -8429876, + 5741987, + 24571100, + 17203849, + -26683813, + -60977315, + -20409074, + 82651321, + 125072127, + -3886862, + -222245839, + -248872541, + 142700044, + 836704356, + 1388371390, + 1388371390, + 836704356, + 142700044, + -248872541, + -222245839, + -3886862, + 125072127, + 82651321, + -20409074, + -60977315, + -26683813, + 17203849, + 24571100, + 5741987, + -8429876, + -7113516, + -298661, + 2316615, + 1042618, + -102613 + +}; + +static const struct src_stage src_int32_1_2_2268_5000 = { + 1, 0, 1, 40, 40, 2, 1, 0, 1, + src_int32_1_2_2268_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_1_2_4535_5000.h b/src/audio/src/coef/src_small_int32_1_2_4535_5000.h new file mode 100644 index 000000000000..73627721fb9d --- /dev/null +++ b/src/audio/src/coef/src_small_int32_1_2_4535_5000.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_2_4535_5000_fir[200] = { + -79638, + 47425, + 131437, + -46101, + -197166, + 29280, + 275788, + 9054, + -364652, + -75182, + 459231, + 175240, + -552929, + -314714, + 636988, + 497862, + -700515, + -727097, + 730662, + 1002338, + -712961, + -1320385, + 631836, + 1674345, + -471281, + -2053159, + 215706, + 2441271, + 149078, + -2818473, + -634761, + 3159975, + 1249353, + -3436724, + -1995992, + 3615984, + 2871767, + -3662209, + -3866638, + 3538178, + 4962504, + -3206397, + -6132477, + 2630727, + 7340428, + -1778195, + -8540840, + 620933, + 9679008, + 861823, + -10691608, + -2681745, + 11507628, + 4839520, + -12049661, + -7323107, + 12235493, + 10106244, + -11979944, + -13147220, + 11196859, + 16387985, + -9801137, + -19753572, + 7710649, + 23151819, + -4847853, + -26473294, + 1140891, + 29591262, + 3476141, + -32361428, + -9064151, + 34621026, + 15681812, + -36186538, + -23391031, + 36848896, + 32266598, + -36364131, + -42412651, + 34435821, + 53990922, + -30682186, + -67270800, + 24573012, + 82723156, + -15302727, + -101210403, + 1514842, + 124413719, + 19366367, + -155939188, + -53041763, + 204829979, + 115329198, + -301107631, + -272718756, + 635613098, + 1656246671, + 1656246671, + 635613098, + -272718756, + -301107631, + 115329198, + 204829979, + -53041763, + -155939188, + 19366367, + 124413719, + 1514842, + -101210403, + -15302727, + 82723156, + 24573012, + -67270800, + -30682186, + 53990922, + 34435821, + -42412651, + -36364131, + 32266598, + 36848896, + -23391031, + -36186538, + 15681812, + 34621026, + -9064151, + -32361428, + 3476141, + 29591262, + 1140891, + -26473294, + -4847853, + 23151819, + 7710649, + -19753572, + -9801137, + 16387985, + 11196859, + -13147220, + -11979944, + 10106244, + 12235493, + -7323107, + -12049661, + 4839520, + 11507628, + -2681745, + -10691608, + 861823, + 9679008, + 620933, + -8540840, + -1778195, + 7340428, + 2630727, + -6132477, + -3206397, + 4962504, + 3538178, + -3866638, + -3662209, + 2871767, + 3615984, + -1995992, + -3436724, + 1249353, + 3159975, + -634761, + -2818473, + 149078, + 2441271, + 215706, + -2053159, + -471281, + 1674345, + 631836, + -1320385, + -712961, + 1002338, + 730662, + -727097, + -700515, + 497862, + 636988, + -314714, + -552929, + 175240, + 459231, + -75182, + -364652, + 9054, + 275788, + 29280, + -197166, + -46101, + 131437, + 47425, + -79638 + +}; + +static const struct src_stage src_int32_1_2_4535_5000 = { + 1, 0, 1, 200, 200, 2, 1, 0, 1, + src_int32_1_2_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_1_3_2268_5000.h b/src/audio/src/coef/src_small_int32_1_3_2268_5000.h new file mode 100644 index 000000000000..8896da331987 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_1_3_2268_5000.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_3_2268_5000_fir[56] = { + 636662, + 1367445, + 1168433, + -1113091, + -5228555, + -8512773, + -6739201, + 2764092, + 17380905, + 28046417, + 23219492, + -2711393, + -41479156, + -70267160, + -62272596, + -5253484, + 82664699, + 152749385, + 147216043, + 35627282, + -153131824, + -325316190, + -354264540, + -140373711, + 329128823, + 953901216, + 1547192859, + 1908310509, + 1908310509, + 1547192859, + 953901216, + 329128823, + -140373711, + -354264540, + -325316190, + -153131824, + 35627282, + 147216043, + 152749385, + 82664699, + -5253484, + -62272596, + -70267160, + -41479156, + -2711393, + 23219492, + 28046417, + 17380905, + 2764092, + -6739201, + -8512773, + -5228555, + -1113091, + 1168433, + 1367445, + 636662 + +}; + +static const struct src_stage src_int32_1_3_2268_5000 = { + 1, 0, 1, 56, 56, 3, 1, 0, 2, + src_int32_1_3_2268_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_1_3_4535_5000.h b/src/audio/src/coef/src_small_int32_1_3_4535_5000.h new file mode 100644 index 000000000000..35e64f1e36a0 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_1_3_4535_5000.h @@ -0,0 +1,283 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_1_3_4535_5000_fir[268] = { + 53316, + -3193, + -78263, + -94410, + -13727, + 106779, + 149415, + 46802, + -131686, + -218458, + -100816, + 147424, + 300219, + 180355, + -147088, + -391581, + -289345, + 122605, + 487327, + 430508, + -65033, + -579922, + -604793, + -34996, + 659410, + 810772, + 186690, + -713463, + -1044078, + -398384, + 727597, + 1296900, + 676729, + -685589, + -1557594, + -1025798, + 570086, + 1810448, + 1446165, + -363427, + -2035646, + -1934003, + 48640, + 2209466, + 2480247, + 389390, + -2304734, + -3069891, + -962640, + 2291555, + 3681471, + 1678584, + -2138313, + -4286781, + -2538830, + 1812940, + 4850877, + 3537793, + -1284409, + -5332393, + -4661504, + 524411, + 5684187, + 5886597, + 490834, + -5854327, + -7179537, + -1778714, + 5787376, + 8496154, + 3348379, + -5425956, + -9781482, + -5198989, + 4712513, + 10969935, + 7318144, + -3591187, + -11985773, + -9680539, + 2009704, + 12743797, + 12246904, + 78881, + -13150167, + -14963245, + -2714719, + 13103138, + 17760339, + 5930190, + -12493462, + -20553411, + -9749650, + 11204030, + 23241795, + 14190202, + -9108138, + -25708241, + -19263960, + 6065370, + 27817290, + 24982482, + -1913444, + -29411709, + -31364570, + -3546973, + 30305092, + 38449669, + 10580094, + -30267040, + -46321273, + -19567058, + 28993377, + 55149987, + 31107760, + -26044259, + -65279105, + -46235163, + 20706690, + 77413504, + 66916127, + -11654755, + -93099762, + -97410434, + -4038926, + 116216226, + 148889159, + 34635074, + -159328672, + -262519729, + -116659642, + 295782476, + 809543553, + 1163409661, + 1163409661, + 809543553, + 295782476, + -116659642, + -262519729, + -159328672, + 34635074, + 148889159, + 116216226, + -4038926, + -97410434, + -93099762, + -11654755, + 66916127, + 77413504, + 20706690, + -46235163, + -65279105, + -26044259, + 31107760, + 55149987, + 28993377, + -19567058, + -46321273, + -30267040, + 10580094, + 38449669, + 30305092, + -3546973, + -31364570, + -29411709, + -1913444, + 24982482, + 27817290, + 6065370, + -19263960, + -25708241, + -9108138, + 14190202, + 23241795, + 11204030, + -9749650, + -20553411, + -12493462, + 5930190, + 17760339, + 13103138, + -2714719, + -14963245, + -13150167, + 78881, + 12246904, + 12743797, + 2009704, + -9680539, + -11985773, + -3591187, + 7318144, + 10969935, + 4712513, + -5198989, + -9781482, + -5425956, + 3348379, + 8496154, + 5787376, + -1778714, + -7179537, + -5854327, + 490834, + 5886597, + 5684187, + 524411, + -4661504, + -5332393, + -1284409, + 3537793, + 4850877, + 1812940, + -2538830, + -4286781, + -2138313, + 1678584, + 3681471, + 2291555, + -962640, + -3069891, + -2304734, + 389390, + 2480247, + 2209466, + 48640, + -1934003, + -2035646, + -363427, + 1446165, + 1810448, + 570086, + -1025798, + -1557594, + -685589, + 676729, + 1296900, + 727597, + -398384, + -1044078, + -713463, + 186690, + 810772, + 659410, + -34996, + -604793, + -579922, + -65033, + 430508, + 487327, + 122605, + -289345, + -391581, + -147088, + 180355, + 300219, + 147424, + -100816, + -218458, + -131686, + 46802, + 149415, + 106779, + -13727, + -94410, + -78263, + -3193, + 53316 + +}; + +static const struct src_stage src_int32_1_3_4535_5000 = { + 1, 0, 1, 268, 268, 3, 1, 0, 1, + src_int32_1_3_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_20_21_4167_5000.h b/src/audio/src/coef/src_small_int32_20_21_4167_5000.h new file mode 100644 index 000000000000..9459d265b612 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_20_21_4167_5000.h @@ -0,0 +1,1135 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_20_21_4167_5000_fir[1120] = { + 125886, + -321269, + 574508, + -781908, + 773601, + -347815, + -661501, + 2294646, + -4377725, + 6468754, + -7871729, + 7741360, + -5279754, + -1700, + 8009461, + -17856576, + 27787309, + -35293075, + 37436971, + -31353996, + 14843278, + 13069550, + -51736860, + 98786784, + -150418530, + 202236992, + -251285082, + 305912317, + 1758726828, + 212671156, + -216012726, + 189629029, + -150069906, + 105178476, + -61147635, + 22858953, + 6429449, + -25277982, + 33983063, + -34225844, + 28540252, + -19722840, + 10305596, + -2183233, + -3560016, + 6628860, + -7346339, + 6403310, + -4600439, + 2640899, + -1006784, + -75399, + 597589, + -691836, + 543269, + -319883, + 115743, + -316147, + 595926, + -860646, + 941473, + -623096, + -292462, + 1894310, + -4065488, + 6412952, + -8260580, + 8732882, + -6937369, + 2225697, + 5515713, + -15617006, + 26496350, + -35715778, + 40251006, + -36955058, + 23141323, + 2834716, + -41145087, + 90375370, + -147934437, + 211471046, + -283642917, + 403306539, + 1747806687, + 124398159, + -178571693, + 173990164, + -146973848, + 109481876, + -69230078, + 32031720, + -1942877, + -18847996, + 29964898, + -32545759, + 28751356, + -21188417, + 12365492, + -4279399, + -1811396, + 5418756, + -6697408, + 6220880, + -4731876, + 2928158, + -1322586, + 189133, + 417064, + -592620, + 503290, + -312400, + 102158, + -304223, + 606588, + -925991, + 1097601, + -895995, + 93967, + 1445990, + -3667253, + 6233855, + -8502186, + 9581817, + -8500080, + 4457758, + 2867502, + -13039103, + 24681427, + -35473835, + 42360176, + -41966825, + 31165421, + -7662539, + -29544873, + 80051889, + -142581840, + 217036224, + -312350939, + 503968068, + 1726088979, + 41828492, + -139707237, + 155704158, + -141262323, + 111667834, + -75864222, + 40431344, + -10120158, + -12189305, + 25467129, + -30295246, + 28426907, + -22233886, + 14155670, + -6253091, + -66956, + 4135718, + -5939933, + 5927805, + -4772038, + 3152759, + -1603916, + 441082, + 235604, + -486539, + 455774, + -299331, + 85170, + -285333, + 605739, + -976064, + 1238476, + -1161130, + 490881, + 956891, + -3188291, + 5931725, + -8588395, + 10268782, + -9936190, + 6652333, + 111770, + -10164918, + 22366752, + -34559276, + 43711538, + -46283864, + 38759476, + -18230581, + -17131341, + 67962048, + -134376456, + 218692296, + -336695652, + 606950905, + 1693817213, + -34390690, + -100153163, + 135187782, + -133110425, + 111746227, + -80959071, + 47918593, + -17955350, + -5429076, + 20581714, + -27526503, + 27582993, + -22847987, + 15648323, + -8070241, + 1641027, + 2805218, + -5090576, + 5532331, + -4722632, + 3312320, + -1846586, + 676144, + 56674, + -375907, + 402015, + -281277, + 64898, + -259453, + 592822, + -1009218, + 1360756, + -1413086, + 890953, + 435213, + -2635571, + 5509185, + -8513827, + 10777033, + -11215725, + 8767105, + -2701563, + -7042924, + 19586431, + -32976658, + 44265418, + -49811801, + 45772425, + -28672543, + -4119057, + 54287839, + -123386655, + 216259743, + -355996556, + 711260171, + 1651352559, + -103706979, + -60621401, + 112882753, + -122732166, + 109764895, + -84453653, + 54373713, + -25310485, + 1306004, + 15406084, + -24300350, + 26245026, + -23027679, + 16821720, + -9700394, + 3281649, + 1453036, + -4167319, + 5044412, + -4586999, + 3405748, + -2047267, + 890482, + -116443, + -263029, + 343367, + -258903, + 41550, + -226709, + 567500, + -1024070, + 1461342, + -1646521, + 1286567, + -109977, + -2017663, + 4971231, + -8276040, + 11092850, + -12311029, + 10760391, + -5520482, + -3727221, + 16384008, + -30743213, + 43996403, + -52469293, + 52061156, + -38789892, + 9261524, + 39245082, + -109733703, + 209624906, + -369617105, + 815864284, + 1599169017, + -165668039, + -21792170, + 89247475, + -110375690, + 105807911, + -86317499, + 59698245, + -32059038, + 7892058, + 10041239, + -20684948, + 24447093, + -22778035, + 17660489, + -11117198, + 4825926, + 104776, + -3189094, + 4475475, + -4370004, + 3433225, + -2203524, + 1080782, + -280696, + -150158, + 281215, + -232927, + 15420, + -187381, + 529677, + -1019549, + 1537448, + -1856275, + 1669954, + -668895, + -1344625, + 4325195, + -7875651, + 11205866, + -13197354, + 12591945, + -8291827, + -276624, + 12811820, + -27888762, + 42894088, + -54189810, + 57493340, + -48386092, + 22767978, + 23080292, + -93591089, + 198744199, + -376975272, + 919707785, + 1537847069, + -219925467, + 15695133, + 64748753, + -96318009, + 99993252, + -86550573, + 63816410, + -38088035, + 14210243, + 4589822, + -16754400, + 22231160, + -22111995, + 18155779, + -12298813, + 6247292, + -1214616, + -2175404, + 3838174, + -4077905, + 3396163, + -2313838, + 1244300, + -433319, + -39449, + 216947, + -204101, + -13113, + -141904, + 479506, + -994926, + 1586666, + -2037474, + 2033344, + -1231213, + -627841, + 3580661, + -7316394, + 11109340, + -13853382, + 14223755, + -10962275, + 3246363, + 8930180, + -24455386, + 40963550, + -54923154, + 61950119, + -57270305, + 36150132, + 6066922, + -75182896, + 183647297, + -377553538, + 1021724627, + 1468065936, + -266237144, + 51250200, + 39853578, + -80859370, + 92469905, + -85182638, + 66676054, + -43299878, + 20148859, + -845814, + -12587267, + 19646149, + -21049971, + 18305291, + -13228222, + 7522044, + -2481295, + -1145946, + 3146115, + -3718194, + 3297148, + -2377603, + 1378892, + -571875, + 67077, + 151923, + -173189, + -43588, + -90871, + 417402, + -949846, + 1607029, + -2185638, + 2369112, + -1786239, + 120159, + 2749341, + -6605122, + 10800367, + -14261714, + 15620810, + -13479348, + 6776653, + 4806382, + -20496867, + 38225542, + -54636713, + 65328587, + -65261060, + 49154524, + -11498983, + -54781256, + 164439215, + -370908161, + 1120851741, + 1390594526, + -304468061, + 84339117, + 15021154, + -64317346, + 83414496, + -82272110, + 68249148, + -47613852, + 25605269, + -6165491, + -8265033, + 16746898, + -19619328, + 18113193, + -13893449, + 8629722, + -3672943, + -120239, + 2413584, + -3299428, + 3139852, + -2395111, + 1483039, + -694288, + 167568, + 87449, + -140955, + -75467, + -35022, + 344043, + -884345, + 1597067, + -2296784, + 2669933, + -2323119, + 885912, + 1844899, + -5751754, + 10280019, + -14409280, + 16751825, + -15792425, + 10247759, + 513569, + -16077886, + 34716397, + -53316405, + 67544022, + -72189824, + 61529016, + -29303630, + -32702884, + 141301234, + -356677552, + 1216042693, + 1306281230, + -334589636, + 114490621, + -9304735, + -47020773, + 73027484, + -77904403, + 68531832, + -50967293, + 30487632, + -11273014, + -3870541, + 13593029, + -17853736, + 17589915, + -14287680, + 9553418, + -4769151, + 882741, + 1655256, + -2831036, + 2928937, + -2367514, + 1555852, + -798871, + 260367, + 24757, + -108144, + -108144, + 24757, + 260367, + -798871, + 1555852, + -2367514, + 2928937, + -2831036, + 1655256, + 882741, + -4769151, + 9553418, + -14287680, + 17589915, + -17853736, + 13593029, + -3870541, + -11273014, + 30487632, + -50967293, + 68531832, + -77904403, + 73027484, + -47020773, + -9304735, + 114490621, + -334589636, + 1306281230, + 1216042693, + -356677552, + 141301234, + -32702884, + -29303630, + 61529016, + -72189824, + 67544022, + -53316405, + 34716397, + -16077886, + 513569, + 10247759, + -15792425, + 16751825, + -14409280, + 10280019, + -5751754, + 1844899, + 885912, + -2323119, + 2669933, + -2296784, + 1597067, + -884345, + 344043, + -35022, + -75467, + -140955, + 87449, + 167568, + -694288, + 1483039, + -2395111, + 3139852, + -3299428, + 2413584, + -120239, + -3672943, + 8629722, + -13893449, + 18113193, + -19619328, + 16746898, + -8265033, + -6165491, + 25605269, + -47613852, + 68249148, + -82272110, + 83414496, + -64317346, + 15021154, + 84339117, + -304468061, + 1390594526, + 1120851741, + -370908161, + 164439215, + -54781256, + -11498983, + 49154524, + -65261060, + 65328587, + -54636713, + 38225542, + -20496867, + 4806382, + 6776653, + -13479348, + 15620810, + -14261714, + 10800367, + -6605122, + 2749341, + 120159, + -1786239, + 2369112, + -2185638, + 1607029, + -949846, + 417402, + -90871, + -43588, + -173189, + 151923, + 67077, + -571875, + 1378892, + -2377603, + 3297148, + -3718194, + 3146115, + -1145946, + -2481295, + 7522044, + -13228222, + 18305291, + -21049971, + 19646149, + -12587267, + -845814, + 20148859, + -43299878, + 66676054, + -85182638, + 92469905, + -80859370, + 39853578, + 51250200, + -266237144, + 1468065936, + 1021724627, + -377553538, + 183647297, + -75182896, + 6066922, + 36150132, + -57270305, + 61950119, + -54923154, + 40963550, + -24455386, + 8930180, + 3246363, + -10962275, + 14223755, + -13853382, + 11109340, + -7316394, + 3580661, + -627841, + -1231213, + 2033344, + -2037474, + 1586666, + -994926, + 479506, + -141904, + -13113, + -204101, + 216947, + -39449, + -433319, + 1244300, + -2313838, + 3396163, + -4077905, + 3838174, + -2175404, + -1214616, + 6247292, + -12298813, + 18155779, + -22111995, + 22231160, + -16754400, + 4589822, + 14210243, + -38088035, + 63816410, + -86550573, + 99993252, + -96318009, + 64748753, + 15695133, + -219925467, + 1537847069, + 919707785, + -376975272, + 198744199, + -93591089, + 23080292, + 22767978, + -48386092, + 57493340, + -54189810, + 42894088, + -27888762, + 12811820, + -276624, + -8291827, + 12591945, + -13197354, + 11205866, + -7875651, + 4325195, + -1344625, + -668895, + 1669954, + -1856275, + 1537448, + -1019549, + 529677, + -187381, + 15420, + -232927, + 281215, + -150158, + -280696, + 1080782, + -2203524, + 3433225, + -4370004, + 4475475, + -3189094, + 104776, + 4825926, + -11117198, + 17660489, + -22778035, + 24447093, + -20684948, + 10041239, + 7892058, + -32059038, + 59698245, + -86317499, + 105807911, + -110375690, + 89247475, + -21792170, + -165668039, + 1599169017, + 815864284, + -369617105, + 209624906, + -109733703, + 39245082, + 9261524, + -38789892, + 52061156, + -52469293, + 43996403, + -30743213, + 16384008, + -3727221, + -5520482, + 10760391, + -12311029, + 11092850, + -8276040, + 4971231, + -2017663, + -109977, + 1286567, + -1646521, + 1461342, + -1024070, + 567500, + -226709, + 41550, + -258903, + 343367, + -263029, + -116443, + 890482, + -2047267, + 3405748, + -4586999, + 5044412, + -4167319, + 1453036, + 3281649, + -9700394, + 16821720, + -23027679, + 26245026, + -24300350, + 15406084, + 1306004, + -25310485, + 54373713, + -84453653, + 109764895, + -122732166, + 112882753, + -60621401, + -103706979, + 1651352559, + 711260171, + -355996556, + 216259743, + -123386655, + 54287839, + -4119057, + -28672543, + 45772425, + -49811801, + 44265418, + -32976658, + 19586431, + -7042924, + -2701563, + 8767105, + -11215725, + 10777033, + -8513827, + 5509185, + -2635571, + 435213, + 890953, + -1413086, + 1360756, + -1009218, + 592822, + -259453, + 64898, + -281277, + 402015, + -375907, + 56674, + 676144, + -1846586, + 3312320, + -4722632, + 5532331, + -5090576, + 2805218, + 1641027, + -8070241, + 15648323, + -22847987, + 27582993, + -27526503, + 20581714, + -5429076, + -17955350, + 47918593, + -80959071, + 111746227, + -133110425, + 135187782, + -100153163, + -34390690, + 1693817213, + 606950905, + -336695652, + 218692296, + -134376456, + 67962048, + -17131341, + -18230581, + 38759476, + -46283864, + 43711538, + -34559276, + 22366752, + -10164918, + 111770, + 6652333, + -9936190, + 10268782, + -8588395, + 5931725, + -3188291, + 956891, + 490881, + -1161130, + 1238476, + -976064, + 605739, + -285333, + 85170, + -299331, + 455774, + -486539, + 235604, + 441082, + -1603916, + 3152759, + -4772038, + 5927805, + -5939933, + 4135718, + -66956, + -6253091, + 14155670, + -22233886, + 28426907, + -30295246, + 25467129, + -12189305, + -10120158, + 40431344, + -75864222, + 111667834, + -141262323, + 155704158, + -139707237, + 41828492, + 1726088979, + 503968068, + -312350939, + 217036224, + -142581840, + 80051889, + -29544873, + -7662539, + 31165421, + -41966825, + 42360176, + -35473835, + 24681427, + -13039103, + 2867502, + 4457758, + -8500080, + 9581817, + -8502186, + 6233855, + -3667253, + 1445990, + 93967, + -895995, + 1097601, + -925991, + 606588, + -304223, + 102158, + -312400, + 503290, + -592620, + 417064, + 189133, + -1322586, + 2928158, + -4731876, + 6220880, + -6697408, + 5418756, + -1811396, + -4279399, + 12365492, + -21188417, + 28751356, + -32545759, + 29964898, + -18847996, + -1942877, + 32031720, + -69230078, + 109481876, + -146973848, + 173990164, + -178571693, + 124398159, + 1747806687, + 403306539, + -283642917, + 211471046, + -147934437, + 90375370, + -41145087, + 2834716, + 23141323, + -36955058, + 40251006, + -35715778, + 26496350, + -15617006, + 5515713, + 2225697, + -6937369, + 8732882, + -8260580, + 6412952, + -4065488, + 1894310, + -292462, + -623096, + 941473, + -860646, + 595926, + -316147, + 115743, + -319883, + 543269, + -691836, + 597589, + -75399, + -1006784, + 2640899, + -4600439, + 6403310, + -7346339, + 6628860, + -3560016, + -2183233, + 10305596, + -19722840, + 28540252, + -34225844, + 33983063, + -25277982, + 6429449, + 22858953, + -61147635, + 105178476, + -150069906, + 189629029, + -216012726, + 212671156, + 1758726828, + 305912317, + -251285082, + 202236992, + -150418530, + 98786784, + -51736860, + 13069550, + 14843278, + -31353996, + 37436971, + -35293075, + 27787309, + -17856576, + 8009461, + -1700, + -5279754, + 7741360, + -7871729, + 6468754, + -4377725, + 2294646, + -661501, + -347815, + 773601, + -781908, + 574508, + -321269, + 125886 + +}; + +static const struct src_stage src_int32_20_21_4167_5000 = { + 1, 1, 20, 56, 1120, 21, 20, 0, 0, + src_int32_20_21_4167_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_21_20_4167_5000.h b/src/audio/src/coef/src_small_int32_21_20_4167_5000.h new file mode 100644 index 000000000000..0d9fd93b03c4 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_21_20_4167_5000.h @@ -0,0 +1,1107 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_21_20_4167_5000_fir[1092] = { + -148365, + 253251, + -300044, + 198018, + 165016, + -904116, + 2109032, + -3809131, + 5936407, + -8293365, + 10533360, + -12160474, + 12553979, + -11019062, + 6861167, + 523301, + -11551306, + 26366797, + -44779009, + 66240300, + -89877091, + 114589459, + -139253201, + 163152569, + -187327445, + 223249753, + 1846610288, + 130583077, + -146550977, + 141645404, + -128384601, + 110446135, + -90107433, + 69197295, + -49230987, + 31387478, + -16470657, + 4896061, + 3285785, + -8331721, + 10723485, + -11073331, + 10031194, + -8205040, + 6102582, + -4098230, + 2424839, + -1186255, + 384239, + 47534, + -209322, + 206397, + -166569, + 297924, + -389487, + 351244, + -65886, + -594767, + 1742814, + -3438876, + 5652714, + -8226411, + 10847843, + -13042081, + 14186734, + -13554119, + 10378908, + -3945006, + -6319272, + 20752631, + -39396566, + 61975727, + -87948323, + 116670859, + -147794258, + 182325160, + -226613958, + 321135533, + 1835142568, + 43907150, + -105054593, + 118266980, + -115448664, + 104364730, + -88671030, + 70818254, + -52688233, + 35733161, + -20992285, + 9094186, + -279892, + -5544994, + 8733380, + -9805380, + 9355049, + -7966914, + 6151241, + -4303075, + 2685872, + -1436800, + 588081, + -97459, + -119135, + 158426, + -182704, + 339334, + -475770, + 504292, + -304392, + -263274, + 1331662, + -2992218, + 5253760, + -8001533, + 10964194, + -13696782, + 15586558, + -15885789, + 13771400, + -8426423, + -867126, + 14639231, + -33166657, + 56457111, + -84320484, + 116601851, + -153783204, + 198725893, + -263628339, + 423384751, + 1812335900, + -36098867, + -63585259, + 93497987, + -100735707, + 96501411, + -85629375, + 71099825, + -55106036, + 39336334, + -25040115, + 13043342, + -3770016, + -2712550, + 6623954, + -8384165, + 8521553, + -7587128, + 6084582, + -4422234, + 2888933, + -1652111, + 773268, + -234431, + -31202, + 110367, + -196221, + 376406, + -556988, + 654120, + -546125, + 84690, + 882096, + -2475521, + 4744073, + -7619042, + 10875497, + -14107040, + 16721924, + -17965764, + 16972057, + -12836658, + 4706629, + 8132057, + -26189820, + 49762567, + -79024638, + 114331768, + -157036133, + 211951991, + -297587677, + 529067481, + 1778446098, + -108855370, + -22856546, + 67827790, + -84560253, + 87041119, + -81072038, + 70063328, + -56459696, + 42144471, + -28548276, + 16675229, + -7121438, + 112182, + 4436862, + -6839472, + 7549877, + -7076264, + 5906903, + -4455925, + 3032010, + -1829335, + 937004, + -361114, + 52885, + 63190, + -206594, + 408096, + -631244, + 797620, + -786478, + 442941, + 401584, + -1896682, + 4130433, + -7082270, + 10578583, + -14259577, + 17565651, + -19749515, + 19916591, + -17091120, + 10299303, + 1346008, + -18582587, + 41993823, + -72123658, + 109849580, + -157414230, + 221643306, + -327720020, + 637190454, + 1733852586, + -173887893, + 16460928, + 41745825, + -67254839, + 76193594, + -75114450, + 67753885, + -56744596, + 44120724, + -31462127, + 19928738, + -10274824, + 2877007, + 2214320, + -5202728, + 6461321, + -6447091, + 5624466, + -4405963, + 3114286, + -1966436, + 1077005, + -475532, + 131688, + 17791, + -213333, + 433415, + -696695, + 931684, + -1020701, + 804881, + -101577, + -1265023, + 3421790, + -6397585, + 10074178, + -14145721, + 18095511, + -21197204, + 22544278, + -21106513, + 15805872, + -5596560, + -10475609, + 33274801, + -63711743, + 103185037, + -154827509, + 227489980, + -353276190, + 746709000, + 1679053311, + -230831156, + 53748160, + 15733235, + -49163659, + 64189024, + -67895272, + 64239127, + -55975907, + 45244301, + -33739058, + 22750948, + -13175685, + 5531904, + -1690, + -3506371, + 5278863, + -5714267, + 5245328, + -4275678, + 3136112, + -2062208, + 1191526, + -576030, + 203942, + -25024, + -215999, + 451454, + -751588, + 1053259, + -1243986, + 1163621, + -618392, + -591147, + 2629159, + -5574342, + 9366983, + -13761673, + 18294762, + -22274546, + 24799176, + -24802430, + 21120916, + -12567987, + -2011483, + 23749746, + -53913345, + 94409091, + -149237778, + 229239476, + -373541538, + 856539835, + 1614658080, + -279431514, + 88445423, + -9745121, + -30636165, + 51273443, + -59573385, + 59607514, + -54187936, + 45510558, + -35349048, + 25097943, + -15775292, + 8029917, + -2170207, + -1783226, + 4026693, + -4894023, + 4779139, + -4069814, + 3098967, + -2116265, + 1279372, + -661292, + 268575, + -64550, + -214216, + 461406, + -794303, + 1159418, + -1451564, + 1512104, + -1139329, + 113226, + 1765456, + -4624776, + 8465674, + -13108687, + 18152577, + -22953565, + 26631281, + -28102936, + 26140600, + -19437611, + 6657687, + 13580950, + -42881510, + 83633578, + -140660768, + 226702870, + -387847468, + 965574536, + 1541380411, + -319547822, + 120058811, + -34248170, + -12020719, + 37703923, + -50324581, + 53966307, + -51433125, + 44930776, + -36274990, + 26935463, + -18031467, + 10327964, + -4252020, + -65882, + 2729728, + -4003815, + 4236922, + -3794399, + 3005395, + -2129028, + 1339905, + -730354, + 324719, + -100192, + -207687, + 462594, + -823393, + 1247420, + -1638800, + 1843234, + -1654484, + 835459, + 845301, + -3563842, + 7382834, + -12193161, + 17664378, + -23213259, + 27997590, + -30938080, + 30764655, + -26074168, + 15372957, + 2946086, + -30795665, + 71010149, + -129167353, + 219760264, + -395582527, + 1072693503, + 1460028025, + -351150697, + 148165618, + -57365516, + 6341573, + 23743694, + -40338013, + 47439236, + -47780750, + 43531654, + -36512758, + 28239346, + -19909241, + 12387561, + -6210372, + 1613909, + 1413132, + -3061969, + 3630827, + -3456591, + 2858925, + -2101682, + 1373031, + -782605, + 371717, + -131473, + -196202, + 454488, + -837618, + 1314775, + -1801289, + 2150023, + -2153762, + 1562212, + -115216, + -2408993, + 6134795, + -11026626, + 16832058, + -23040137, + 28863054, + -33245339, + 34898342, + -32348243, + 23971387, + -7964791, + -17858858, + 56728449, + -114883829, + 208365225, + -396202914, + 1176780210, + 1371492118, + -374320235, + 172418462, + -78723625, + 24122758, + 9657239, + -29812468, + 40163908, + -43315322, + 41354530, + -36071041, + 28995789, + -21381358, + 14175443, + -8011590, + 3225807, + 101840, + -2087313, + 2973875, + -3064512, + 2663971, + -2036136, + 1379185, + -817788, + 409128, + -158038, + -179653, + 436725, + -835989, + 1359301, + -1934954, + 2425723, + -2627070, + 2279687, + -1098814, + -1179906, + 4741422, + -9625642, + 15664078, + -22428631, + 29201397, + -34970939, + 38454339, + -38134741, + 32289015, + -18952542, + -4294518, + 41013562, + -97991225, + 192548148, + -389242219, + 1276735561, + 1276735561, + -389242219, + 192548148, + -97991225, + 41013562, + -4294518, + -18952542, + 32289015, + -38134741, + 38454339, + -34970939, + 29201397, + -22428631, + 15664078, + -9625642, + 4741422, + -1179906, + -1098814, + 2279687, + -2627070, + 2425723, + -1934954, + 1359301, + -835989, + 436725, + -179653, + -158038, + 409128, + -817788, + 1379185, + -2036136, + 2663971, + -3064512, + 2973875, + -2087313, + 101840, + 3225807, + -8011590, + 14175443, + -21381358, + 28995789, + -36071041, + 41354530, + -43315322, + 40163908, + -29812468, + 9657239, + 24122758, + -78723625, + 172418462, + -374320235, + 1371492118, + 1176780210, + -396202914, + 208365225, + -114883829, + 56728449, + -17858858, + -7964791, + 23971387, + -32348243, + 34898342, + -33245339, + 28863054, + -23040137, + 16832058, + -11026626, + 6134795, + -2408993, + -115216, + 1562212, + -2153762, + 2150023, + -1801289, + 1314775, + -837618, + 454488, + -196202, + -131473, + 371717, + -782605, + 1373031, + -2101682, + 2858925, + -3456591, + 3630827, + -3061969, + 1413132, + 1613909, + -6210372, + 12387561, + -19909241, + 28239346, + -36512758, + 43531654, + -47780750, + 47439236, + -40338013, + 23743694, + 6341573, + -57365516, + 148165618, + -351150697, + 1460028025, + 1072693503, + -395582527, + 219760264, + -129167353, + 71010149, + -30795665, + 2946086, + 15372957, + -26074168, + 30764655, + -30938080, + 27997590, + -23213259, + 17664378, + -12193161, + 7382834, + -3563842, + 845301, + 835459, + -1654484, + 1843234, + -1638800, + 1247420, + -823393, + 462594, + -207687, + -100192, + 324719, + -730354, + 1339905, + -2129028, + 3005395, + -3794399, + 4236922, + -4003815, + 2729728, + -65882, + -4252020, + 10327964, + -18031467, + 26935463, + -36274990, + 44930776, + -51433125, + 53966307, + -50324581, + 37703923, + -12020719, + -34248170, + 120058811, + -319547822, + 1541380411, + 965574536, + -387847468, + 226702870, + -140660768, + 83633578, + -42881510, + 13580950, + 6657687, + -19437611, + 26140600, + -28102936, + 26631281, + -22953565, + 18152577, + -13108687, + 8465674, + -4624776, + 1765456, + 113226, + -1139329, + 1512104, + -1451564, + 1159418, + -794303, + 461406, + -214216, + -64550, + 268575, + -661292, + 1279372, + -2116265, + 3098967, + -4069814, + 4779139, + -4894023, + 4026693, + -1783226, + -2170207, + 8029917, + -15775292, + 25097943, + -35349048, + 45510558, + -54187936, + 59607514, + -59573385, + 51273443, + -30636165, + -9745121, + 88445423, + -279431514, + 1614658080, + 856539835, + -373541538, + 229239476, + -149237778, + 94409091, + -53913345, + 23749746, + -2011483, + -12567987, + 21120916, + -24802430, + 24799176, + -22274546, + 18294762, + -13761673, + 9366983, + -5574342, + 2629159, + -591147, + -618392, + 1163621, + -1243986, + 1053259, + -751588, + 451454, + -215999, + -25024, + 203942, + -576030, + 1191526, + -2062208, + 3136112, + -4275678, + 5245328, + -5714267, + 5278863, + -3506371, + -1690, + 5531904, + -13175685, + 22750948, + -33739058, + 45244301, + -55975907, + 64239127, + -67895272, + 64189024, + -49163659, + 15733235, + 53748160, + -230831156, + 1679053311, + 746709000, + -353276190, + 227489980, + -154827509, + 103185037, + -63711743, + 33274801, + -10475609, + -5596560, + 15805872, + -21106513, + 22544278, + -21197204, + 18095511, + -14145721, + 10074178, + -6397585, + 3421790, + -1265023, + -101577, + 804881, + -1020701, + 931684, + -696695, + 433415, + -213333, + 17791, + 131688, + -475532, + 1077005, + -1966436, + 3114286, + -4405963, + 5624466, + -6447091, + 6461321, + -5202728, + 2214320, + 2877007, + -10274824, + 19928738, + -31462127, + 44120724, + -56744596, + 67753885, + -75114450, + 76193594, + -67254839, + 41745825, + 16460928, + -173887893, + 1733852586, + 637190454, + -327720020, + 221643306, + -157414230, + 109849580, + -72123658, + 41993823, + -18582587, + 1346008, + 10299303, + -17091120, + 19916591, + -19749515, + 17565651, + -14259577, + 10578583, + -7082270, + 4130433, + -1896682, + 401584, + 442941, + -786478, + 797620, + -631244, + 408096, + -206594, + 63190, + 52885, + -361114, + 937004, + -1829335, + 3032010, + -4455925, + 5906903, + -7076264, + 7549877, + -6839472, + 4436862, + 112182, + -7121438, + 16675229, + -28548276, + 42144471, + -56459696, + 70063328, + -81072038, + 87041119, + -84560253, + 67827790, + -22856546, + -108855370, + 1778446098, + 529067481, + -297587677, + 211951991, + -157036133, + 114331768, + -79024638, + 49762567, + -26189820, + 8132057, + 4706629, + -12836658, + 16972057, + -17965764, + 16721924, + -14107040, + 10875497, + -7619042, + 4744073, + -2475521, + 882096, + 84690, + -546125, + 654120, + -556988, + 376406, + -196221, + 110367, + -31202, + -234431, + 773268, + -1652111, + 2888933, + -4422234, + 6084582, + -7587128, + 8521553, + -8384165, + 6623954, + -2712550, + -3770016, + 13043342, + -25040115, + 39336334, + -55106036, + 71099825, + -85629375, + 96501411, + -100735707, + 93497987, + -63585259, + -36098867, + 1812335900, + 423384751, + -263628339, + 198725893, + -153783204, + 116601851, + -84320484, + 56457111, + -33166657, + 14639231, + -867126, + -8426423, + 13771400, + -15885789, + 15586558, + -13696782, + 10964194, + -8001533, + 5253760, + -2992218, + 1331662, + -263274, + -304392, + 504292, + -475770, + 339334, + -182704, + 158426, + -119135, + -97459, + 588081, + -1436800, + 2685872, + -4303075, + 6151241, + -7966914, + 9355049, + -9805380, + 8733380, + -5544994, + -279892, + 9094186, + -20992285, + 35733161, + -52688233, + 70818254, + -88671030, + 104364730, + -115448664, + 118266980, + -105054593, + 43907150, + 1835142568, + 321135533, + -226613958, + 182325160, + -147794258, + 116670859, + -87948323, + 61975727, + -39396566, + 20752631, + -6319272, + -3945006, + 10378908, + -13554119, + 14186734, + -13042081, + 10847843, + -8226411, + 5652714, + -3438876, + 1742814, + -594767, + -65886, + 351244, + -389487, + 297924, + -166569, + 206397, + -209322, + 47534, + 384239, + -1186255, + 2424839, + -4098230, + 6102582, + -8205040, + 10031194, + -11073331, + 10723485, + -8331721, + 3285785, + 4896061, + -16470657, + 31387478, + -49230987, + 69197295, + -90107433, + 110446135, + -128384601, + 141645404, + -146550977, + 130583077, + 1846610288, + 223249753, + -187327445, + 163152569, + -139253201, + 114589459, + -89877091, + 66240300, + -44779009, + 26366797, + -11551306, + 523301, + 6861167, + -11019062, + 12553979, + -12160474, + 10533360, + -8293365, + 5936407, + -3809131, + 2109032, + -904116, + 165016, + 198018, + -300044, + 253251, + -148365 + +}; + +static const struct src_stage src_int32_21_20_4167_5000 = { + 19, 20, 21, 52, 1092, 20, 21, 0, 0, + src_int32_21_20_4167_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_2_1_2268_5000.h b/src/audio/src/coef/src_small_int32_2_1_2268_5000.h new file mode 100644 index 000000000000..fd6ac5d56a52 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_2_1_2268_5000.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_2268_5000_fir[40] = { + -96873, + 2187025, + -6715592, + 5420785, + 16241481, + -57566298, + 78027878, + -3669434, + -234950829, + 789899847, + 1310707111, + 134717528, + -209813602, + 118075701, + -19267409, + -25191144, + 23196614, + -7958316, + -281954, + 984295, + 984295, + -281954, + -7958316, + 23196614, + -25191144, + -19267409, + 118075701, + -209813602, + 134717528, + 1310707111, + 789899847, + -234950829, + -3669434, + 78027878, + -57566298, + 16241481, + 5420785, + -6715592, + 2187025, + -96873 + +}; + +static const struct src_stage src_int32_2_1_2268_5000 = { + 0, 1, 2, 20, 40, 1, 2, 0, 0, + src_int32_2_1_2268_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_2_1_4535_5000.h b/src/audio/src/coef/src_small_int32_2_1_4535_5000.h new file mode 100644 index 000000000000..f5864de8e02c --- /dev/null +++ b/src/audio/src/coef/src_small_int32_2_1_4535_5000.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_1_4535_5000_fir[200] = { + -79638, + 131437, + -197166, + 275788, + -364652, + 459231, + -552929, + 636988, + -700515, + 730662, + -712961, + 631836, + -471281, + 215706, + 149078, + -634761, + 1249353, + -1995992, + 2871767, + -3866638, + 4962504, + -6132477, + 7340428, + -8540840, + 9679008, + -10691608, + 11507628, + -12049661, + 12235493, + -11979944, + 11196859, + -9801137, + 7710649, + -4847853, + 1140891, + 3476141, + -9064151, + 15681812, + -23391031, + 32266598, + -42412651, + 53990922, + -67270800, + 82723156, + -101210403, + 124413719, + -155939188, + 204829979, + -301107631, + 635613098, + 1656246671, + -272718756, + 115329198, + -53041763, + 19366367, + 1514842, + -15302727, + 24573012, + -30682186, + 34435821, + -36364131, + 36848896, + -36186538, + 34621026, + -32361428, + 29591262, + -26473294, + 23151819, + -19753572, + 16387985, + -13147220, + 10106244, + -7323107, + 4839520, + -2681745, + 861823, + 620933, + -1778195, + 2630727, + -3206397, + 3538178, + -3662209, + 3615984, + -3436724, + 3159975, + -2818473, + 2441271, + -2053159, + 1674345, + -1320385, + 1002338, + -727097, + 497862, + -314714, + 175240, + -75182, + 9054, + 29280, + -46101, + 47425, + 47425, + -46101, + 29280, + 9054, + -75182, + 175240, + -314714, + 497862, + -727097, + 1002338, + -1320385, + 1674345, + -2053159, + 2441271, + -2818473, + 3159975, + -3436724, + 3615984, + -3662209, + 3538178, + -3206397, + 2630727, + -1778195, + 620933, + 861823, + -2681745, + 4839520, + -7323107, + 10106244, + -13147220, + 16387985, + -19753572, + 23151819, + -26473294, + 29591262, + -32361428, + 34621026, + -36186538, + 36848896, + -36364131, + 34435821, + -30682186, + 24573012, + -15302727, + 1514842, + 19366367, + -53041763, + 115329198, + -272718756, + 1656246671, + 635613098, + -301107631, + 204829979, + -155939188, + 124413719, + -101210403, + 82723156, + -67270800, + 53990922, + -42412651, + 32266598, + -23391031, + 15681812, + -9064151, + 3476141, + 1140891, + -4847853, + 7710649, + -9801137, + 11196859, + -11979944, + 12235493, + -12049661, + 11507628, + -10691608, + 9679008, + -8540840, + 7340428, + -6132477, + 4962504, + -3866638, + 2871767, + -1995992, + 1249353, + -634761, + 149078, + 215706, + -471281, + 631836, + -712961, + 730662, + -700515, + 636988, + -552929, + 459231, + -364652, + 275788, + -197166, + 131437, + -79638 + +}; + +static const struct src_stage src_int32_2_1_4535_5000 = { + 0, 1, 2, 100, 200, 1, 2, 0, 0, + src_int32_2_1_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_2_3_4535_5000.h b/src/audio/src/coef/src_small_int32_2_3_4535_5000.h new file mode 100644 index 000000000000..3775e45474e1 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_2_3_4535_5000.h @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_2_3_4535_5000_fir[272] = { + 12509, + 72682, + -101869, + -17280, + 183342, + -158327, + -119196, + 349975, + -169398, + -329727, + 550177, + -72811, + -672059, + 727777, + 204767, + -1138655, + 789333, + 730569, + -1673889, + 610057, + 1541427, + -2161669, + 51471, + 2615925, + -2423245, + -1009160, + 3848623, + -2229493, + -2640451, + 5033026, + -1329621, + -4815201, + 5859570, + 504991, + -7372894, + 5932721, + 3426684, + -9994160, + 4807613, + 7454958, + -12192929, + 2041743, + 12426558, + -13327185, + -2748154, + 17959816, + -12620967, + -9839704, + 23435231, + -9176106, + -19392145, + 27981320, + -1923372, + -31506635, + 30423816, + 10615562, + -46452494, + 29061753, + 31167738, + -65379735, + 20731500, + 66976180, + -93159250, + -4040632, + 148926012, + -159346832, + -116662167, + 809519577, + 1163363281, + 295779779, + -262536181, + 34641155, + 116254553, + -97461622, + -11663647, + 77494206, + -46298250, + -26089299, + 55267881, + -19617737, + -30360472, + 38589212, + -3561933, + -29554449, + 25120800, + 6103395, + -25889530, + 14302105, + 11302322, + -20753072, + 5993711, + 13257315, + -15155986, + 79990, + 12938746, + -9841278, + -3655758, + 11183063, + -5307918, + -5548334, + 8702095, + -1824981, + -6017518, + 6062230, + 541139, + -5514076, + 3666426, + 1883231, + -4463894, + 1752448, + 2398900, + -3222926, + 410043, + 2334127, + -2050083, + -386635, + 1933479, + -1100011, + -738424, + 1403443, + -433305, + -780271, + 891991, + -38753, + -646785, + 483954, + 139046, + -448521, + 208930, + 173025, + -260361, + 56816, + 132607, + -120702, + -4244, + 70735, + 70735, + -4244, + -120702, + 132607, + 56816, + -260361, + 173025, + 208930, + -448521, + 139046, + 483954, + -646785, + -38753, + 891991, + -780271, + -433305, + 1403443, + -738424, + -1100011, + 1933479, + -386635, + -2050083, + 2334127, + 410043, + -3222926, + 2398900, + 1752448, + -4463894, + 1883231, + 3666426, + -5514076, + 541139, + 6062230, + -6017518, + -1824981, + 8702095, + -5548334, + -5307918, + 11183063, + -3655758, + -9841278, + 12938746, + 79990, + -15155986, + 13257315, + 5993711, + -20753072, + 11302322, + 14302105, + -25889530, + 6103395, + 25120800, + -29554449, + -3561933, + 38589212, + -30360472, + -19617737, + 55267881, + -26089299, + -46298250, + 77494206, + -11663647, + -97461622, + 116254553, + 34641155, + -262536181, + 295779779, + 1163363281, + 809519577, + -116662167, + -159346832, + 148926012, + -4040632, + -93159250, + 66976180, + 20731500, + -65379735, + 31167738, + 29061753, + -46452494, + 10615562, + 30423816, + -31506635, + -1923372, + 27981320, + -19392145, + -9176106, + 23435231, + -9839704, + -12620967, + 17959816, + -2748154, + -13327185, + 12426558, + 2041743, + -12192929, + 7454958, + 4807613, + -9994160, + 3426684, + 5932721, + -7372894, + 504991, + 5859570, + -4815201, + -1329621, + 5033026, + -2640451, + -2229493, + 3848623, + -1009160, + -2423245, + 2615925, + 51471, + -2161669, + 1541427, + 610057, + -1673889, + 730569, + 789333, + -1138655, + 204767, + 727777, + -672059, + -72811, + 550177, + -329727, + -169398, + 349975, + -119196, + -158327, + 183342, + -17280, + -101869, + 72682, + 12509 + +}; + +static const struct src_stage src_int32_2_3_4535_5000 = { + 1, 1, 2, 136, 272, 3, 2, 0, 0, + src_int32_2_3_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_3_1_2268_5000.h b/src/audio/src/coef/src_small_int32_3_1_2268_5000.h new file mode 100644 index 000000000000..8bc858ad0e2a --- /dev/null +++ b/src/audio/src/coef/src_small_int32_3_1_2268_5000.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_1_2268_5000_fir[60] = { + -166536, + 2306339, + -6050784, + 2678997, + 20170183, + -56648456, + 63227591, + 26267865, + -254983011, + 677549850, + 1351061190, + 234544530, + -235734562, + 109710788, + -4081183, + -34183778, + 25146783, + -6857929, + -1408097, + 1421800, + 346619, + 1663348, + -9179696, + 16157737, + -2290482, + -49228991, + 115231627, + -111856179, + -100474502, + 1096579163, + 1096579163, + -100474502, + -111856179, + 115231627, + -49228991, + -2290482, + 16157737, + -9179696, + 1663348, + 346619, + 1421800, + -1408097, + -6857929, + 25146783, + -34183778, + -4081183, + 109710788, + -235734562, + 234544530, + 1351061190, + 677549850, + -254983011, + 26267865, + 63227591, + -56648456, + 20170183, + 2678997, + -6050784, + 2306339, + -166536 + +}; + +static const struct src_stage src_int32_3_1_2268_5000 = { + 0, 1, 3, 20, 60, 1, 3, 0, 0, + src_int32_3_1_2268_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_3_1_4535_5000.h b/src/audio/src/coef/src_small_int32_3_1_4535_5000.h new file mode 100644 index 000000000000..66f81808a02c --- /dev/null +++ b/src/audio/src/coef/src_small_int32_3_1_4535_5000.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_1_4535_5000_fir[276] = { + -92545, + 140559, + -191923, + 241092, + -280468, + 300406, + -289386, + 234365, + -121331, + -63945, + 334966, + -703402, + 1177853, + -1762541, + 2455986, + -3249742, + 4127275, + -5063054, + 6021946, + -6958968, + 7819459, + -8539714, + 9048086, + -9266554, + 9112707, + -8502087, + 7350785, + -5578150, + 3109467, + 121606, + -4171063, + 9083324, + -14891080, + 21616687, + -29275749, + 37883927, + -47468754, + 58089770, + -69873625, + 83078597, + -98222819, + 116367438, + -139836570, + 174452167, + -239067307, + 443704770, + 1745131644, + -175012245, + 51975026, + -6063930, + -17509776, + 31135622, + -39202118, + 43694778, + -45679141, + 45810673, + -44541243, + 42212222, + -39099402, + 35435453, + -31421182, + 27231019, + -23015520, + 18902408, + -14997036, + 11382768, + -8121575, + 5254995, + -2805512, + 778345, + 836405, + -2061324, + 2929094, + -3479822, + 3758420, + -3812130, + 3688274, + -3432310, + 3086244, + -2687418, + 2267686, + -1852975, + 1463188, + -1112411, + 809377, + -558113, + 358723, + -208233, + 101443, + -31750, + -8119, + 25474, + -80455, + 141487, + -224401, + 330182, + -457891, + 604136, + -762591, + 923632, + -1074098, + 1197260, + -1273011, + 1278324, + -1187981, + 975605, + -614950, + 81459, + 645988, + -1583179, + 2738604, + -4111517, + 5690103, + -7449859, + 9352271, + -11343859, + 13355664, + -15303188, + 17086793, + -18592506, + 19693117, + -20249392, + 20111130, + -19117642, + 17097059, + -13863515, + 9210750, + -2899622, + -5364913, + 15975785, + -29502077, + 46841927, + -69544115, + 100559342, + -146278769, + 223461540, + -393862475, + 1214351617, + 1214351617, + -393862475, + 223461540, + -146278769, + 100559342, + -69544115, + 46841927, + -29502077, + 15975785, + -5364913, + -2899622, + 9210750, + -13863515, + 17097059, + -19117642, + 20111130, + -20249392, + 19693117, + -18592506, + 17086793, + -15303188, + 13355664, + -11343859, + 9352271, + -7449859, + 5690103, + -4111517, + 2738604, + -1583179, + 645988, + 81459, + -614950, + 975605, + -1187981, + 1278324, + -1273011, + 1197260, + -1074098, + 923632, + -762591, + 604136, + -457891, + 330182, + -224401, + 141487, + -80455, + 25474, + -8119, + -31750, + 101443, + -208233, + 358723, + -558113, + 809377, + -1112411, + 1463188, + -1852975, + 2267686, + -2687418, + 3086244, + -3432310, + 3688274, + -3812130, + 3758420, + -3479822, + 2929094, + -2061324, + 836405, + 778345, + -2805512, + 5254995, + -8121575, + 11382768, + -14997036, + 18902408, + -23015520, + 27231019, + -31421182, + 35435453, + -39099402, + 42212222, + -44541243, + 45810673, + -45679141, + 43694778, + -39202118, + 31135622, + -17509776, + -6063930, + 51975026, + -175012245, + 1745131644, + 443704770, + -239067307, + 174452167, + -139836570, + 116367438, + -98222819, + 83078597, + -69873625, + 58089770, + -47468754, + 37883927, + -29275749, + 21616687, + -14891080, + 9083324, + -4171063, + 121606, + 3109467, + -5578150, + 7350785, + -8502087, + 9112707, + -9266554, + 9048086, + -8539714, + 7819459, + -6958968, + 6021946, + -5063054, + 4127275, + -3249742, + 2455986, + -1762541, + 1177853, + -703402, + 334966, + -63945, + -121331, + 234365, + -289386, + 300406, + -280468, + 241092, + -191923, + 140559, + -92545 + +}; + +static const struct src_stage src_int32_3_1_4535_5000 = { + 0, 1, 3, 92, 276, 1, 3, 0, 0, + src_int32_3_1_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_3_2_4535_5000.h b/src/audio/src/coef/src_small_int32_3_2_4535_5000.h new file mode 100644 index 000000000000..9e4f9e0915d5 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_3_2_4535_5000.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_2_4535_5000_fir[276] = { + -92545, + 140559, + -191923, + 241092, + -280468, + 300406, + -289386, + 234365, + -121331, + -63945, + 334966, + -703402, + 1177853, + -1762541, + 2455986, + -3249742, + 4127275, + -5063054, + 6021946, + -6958968, + 7819459, + -8539714, + 9048086, + -9266554, + 9112707, + -8502087, + 7350785, + -5578150, + 3109467, + 121606, + -4171063, + 9083324, + -14891080, + 21616687, + -29275749, + 37883927, + -47468754, + 58089770, + -69873625, + 83078597, + -98222819, + 116367438, + -139836570, + 174452167, + -239067307, + 443704770, + 1745131644, + -175012245, + 51975026, + -6063930, + -17509776, + 31135622, + -39202118, + 43694778, + -45679141, + 45810673, + -44541243, + 42212222, + -39099402, + 35435453, + -31421182, + 27231019, + -23015520, + 18902408, + -14997036, + 11382768, + -8121575, + 5254995, + -2805512, + 778345, + 836405, + -2061324, + 2929094, + -3479822, + 3758420, + -3812130, + 3688274, + -3432310, + 3086244, + -2687418, + 2267686, + -1852975, + 1463188, + -1112411, + 809377, + -558113, + 358723, + -208233, + 101443, + -31750, + -8119, + 25474, + -80455, + 141487, + -224401, + 330182, + -457891, + 604136, + -762591, + 923632, + -1074098, + 1197260, + -1273011, + 1278324, + -1187981, + 975605, + -614950, + 81459, + 645988, + -1583179, + 2738604, + -4111517, + 5690103, + -7449859, + 9352271, + -11343859, + 13355664, + -15303188, + 17086793, + -18592506, + 19693117, + -20249392, + 20111130, + -19117642, + 17097059, + -13863515, + 9210750, + -2899622, + -5364913, + 15975785, + -29502077, + 46841927, + -69544115, + 100559342, + -146278769, + 223461540, + -393862475, + 1214351617, + 1214351617, + -393862475, + 223461540, + -146278769, + 100559342, + -69544115, + 46841927, + -29502077, + 15975785, + -5364913, + -2899622, + 9210750, + -13863515, + 17097059, + -19117642, + 20111130, + -20249392, + 19693117, + -18592506, + 17086793, + -15303188, + 13355664, + -11343859, + 9352271, + -7449859, + 5690103, + -4111517, + 2738604, + -1583179, + 645988, + 81459, + -614950, + 975605, + -1187981, + 1278324, + -1273011, + 1197260, + -1074098, + 923632, + -762591, + 604136, + -457891, + 330182, + -224401, + 141487, + -80455, + 25474, + -8119, + -31750, + 101443, + -208233, + 358723, + -558113, + 809377, + -1112411, + 1463188, + -1852975, + 2267686, + -2687418, + 3086244, + -3432310, + 3688274, + -3812130, + 3758420, + -3479822, + 2929094, + -2061324, + 836405, + 778345, + -2805512, + 5254995, + -8121575, + 11382768, + -14997036, + 18902408, + -23015520, + 27231019, + -31421182, + 35435453, + -39099402, + 42212222, + -44541243, + 45810673, + -45679141, + 43694778, + -39202118, + 31135622, + -17509776, + -6063930, + 51975026, + -175012245, + 1745131644, + 443704770, + -239067307, + 174452167, + -139836570, + 116367438, + -98222819, + 83078597, + -69873625, + 58089770, + -47468754, + 37883927, + -29275749, + 21616687, + -14891080, + 9083324, + -4171063, + 121606, + 3109467, + -5578150, + 7350785, + -8502087, + 9112707, + -9266554, + 9048086, + -8539714, + 7819459, + -6958968, + 6021946, + -5063054, + 4127275, + -3249742, + 2455986, + -1762541, + 1177853, + -703402, + 334966, + -63945, + -121331, + 234365, + -289386, + 300406, + -280468, + 241092, + -191923, + 140559, + -92545 + +}; + +static const struct src_stage src_int32_3_2_4535_5000 = { + 1, 2, 3, 92, 276, 2, 3, 0, 0, + src_int32_3_2_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_3_4_4535_5000.h b/src/audio/src/coef/src_small_int32_3_4_4535_5000.h new file mode 100644 index 000000000000..6ea52fbabd3a --- /dev/null +++ b/src/audio/src/coef/src_small_int32_3_4_4535_5000.h @@ -0,0 +1,363 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_3_4_4535_5000_fir[348] = { + -44332, + 116220, + -109098, + -33627, + 240794, + -321403, + 115423, + 314448, + -641593, + 494186, + 186994, + -962890, + 1134308, + -321345, + -1062931, + 1936076, + -1340584, + -632851, + 2616649, + -2843421, + 631013, + 2714105, + -4544561, + 2881667, + 1674072, + -5853890, + 5957644, + -978228, + -5926194, + 9256227, + -5409919, + -3827011, + 11701916, + -11254604, + 1202783, + 11847580, + -17457904, + 9439780, + 8102312, + -22244662, + 20407986, + -979447, + -23198384, + 32716389, + -16485998, + -17318105, + 44008192, + -39279944, + -595684, + 50819147, + -71212136, + 34705264, + 47219229, + -121324396, + 117558963, + 12007300, + -271449759, + 699289475, + 1331682741, + 264196935, + -277391437, + 137011038, + 14653148, + -97174200, + 89922210, + -26044986, + -38244880, + 61211232, + -37344719, + -7151448, + 37860721, + -36448675, + 9888950, + 18871978, + -29424490, + 17517576, + 4722472, + -19958970, + 18625052, + -4372503, + -10638077, + 15687969, + -8840413, + -3112105, + 10881122, + -9677242, + 1864049, + 5915120, + -8178093, + 4298066, + 1895591, + -5623779, + 4721216, + -695006, + -3029403, + 3902352, + -1886988, + -1013767, + 2589898, + -2031207, + 201489, + 1338673, + -1591125, + 694772, + 443429, + -977201, + 702816, + -34518, + -455787, + 487427, + -184804, + -134209, + 246601, + -153072, + -83, + 81507, + 14525, + 88419, + -176706, + 129137, + 93113, + -352599, + 394250, + -62740, + -486395, + 808288, + -495364, + -404446, + 1262020, + -1261867, + 111838, + 1509828, + -2277344, + 1241357, + 1192856, + -3248717, + 3002871, + -68364, + -3665015, + 5134469, + -2517444, + -2875968, + 7023220, + -6075974, + -266908, + 7733102, + -10184738, + 4495975, + 6156960, + -13734821, + 11207733, + 1279548, + -15131077, + 18926056, + -7504671, + -12483154, + 25885754, + -20107684, + -3845504, + 29512631, + -35593886, + 12690366, + 26358450, + -52226792, + 39548761, + 11261209, + -67734857, + 82782282, + -27722745, + -79749407, + 172051496, + -154131608, + -86310851, + 1095777154, + 1095777154, + -86310851, + -154131608, + 172051496, + -79749407, + -27722745, + 82782282, + -67734857, + 11261209, + 39548761, + -52226792, + 26358450, + 12690366, + -35593886, + 29512631, + -3845504, + -20107684, + 25885754, + -12483154, + -7504671, + 18926056, + -15131077, + 1279548, + 11207733, + -13734821, + 6156960, + 4495975, + -10184738, + 7733102, + -266908, + -6075974, + 7023220, + -2875968, + -2517444, + 5134469, + -3665015, + -68364, + 3002871, + -3248717, + 1192856, + 1241357, + -2277344, + 1509828, + 111838, + -1261867, + 1262020, + -404446, + -495364, + 808288, + -486395, + -62740, + 394250, + -352599, + 93113, + 129137, + -176706, + 88419, + 14525, + 81507, + -83, + -153072, + 246601, + -134209, + -184804, + 487427, + -455787, + -34518, + 702816, + -977201, + 443429, + 694772, + -1591125, + 1338673, + 201489, + -2031207, + 2589898, + -1013767, + -1886988, + 3902352, + -3029403, + -695006, + 4721216, + -5623779, + 1895591, + 4298066, + -8178093, + 5915120, + 1864049, + -9677242, + 10881122, + -3112105, + -8840413, + 15687969, + -10638077, + -4372503, + 18625052, + -19958970, + 4722472, + 17517576, + -29424490, + 18871978, + 9888950, + -36448675, + 37860721, + -7151448, + -37344719, + 61211232, + -38244880, + -26044986, + 89922210, + -97174200, + 14653148, + 137011038, + -277391437, + 264196935, + 1331682741, + 699289475, + -271449759, + 12007300, + 117558963, + -121324396, + 47219229, + 34705264, + -71212136, + 50819147, + -595684, + -39279944, + 44008192, + -17318105, + -16485998, + 32716389, + -23198384, + -979447, + 20407986, + -22244662, + 8102312, + 9439780, + -17457904, + 11847580, + 1202783, + -11254604, + 11701916, + -3827011, + -5409919, + 9256227, + -5926194, + -978228, + 5957644, + -5853890, + 1674072, + 2881667, + -4544561, + 2714105, + 631013, + -2843421, + 2616649, + -632851, + -1340584, + 1936076, + -1062931, + -321345, + 1134308, + -962890, + 186994, + 494186, + -641593, + 314448, + 115423, + -321403, + 240794, + -33627, + -109098, + 116220, + -44332 + +}; + +static const struct src_stage src_int32_3_4_4535_5000 = { + 1, 1, 3, 116, 348, 4, 3, 0, 0, + src_int32_3_4_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_4_3_4535_5000.h b/src/audio/src/coef/src_small_int32_4_3_4535_5000.h new file mode 100644 index 000000000000..dd81b252e4b4 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_4_3_4535_5000.h @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_3_4535_5000_fir[352] = { + -92406, + 134596, + -172955, + 199213, + -202952, + 171872, + -92271, + -50243, + 269806, + -579151, + 988295, + -1503105, + 2123834, + -2843689, + 3647541, + -4510854, + 5398956, + -6266696, + 7058601, + -7709550, + 8146004, + -8287785, + 8050355, + -7347530, + 6094510, + -4211085, + 1624834, + 1725890, + -5889416, + 10898942, + -16771756, + 23509887, + -31102720, + 39532369, + -48783143, + 58857567, + -69803863, + 81765532, + -95078238, + 110480787, + -129645170, + 156801585, + -205545868, + 352289694, + 1775663649, + -115092154, + 16013223, + 19545653, + -36989159, + 46321858, + -51068157, + 52836065, + -52507853, + 50644700, + -47648483, + 43833437, + -39459786, + 34749839, + -29895522, + 25061680, + -20387357, + 15986286, + -11947265, + 8334785, + -5190123, + 2532951, + -363454, + -1335110, + 2593518, + -3453483, + 3964496, + -4180727, + 4158132, + -3951853, + 3614009, + -3191933, + 2726878, + -2253207, + 1798040, + -1381308, + 1016168, + -709698, + 463787, + -276159, + 141438, + -52186, + -133, + 24318, + -117075, + 189618, + -277971, + 378322, + -483989, + 585105, + -668473, + 717655, + -713318, + 633869, + -456402, + 157934, + 283079, + -885003, + 1661121, + -2617655, + 3751798, + -5049885, + 6485781, + -8019632, + 9597032, + -11148719, + 12590816, + -13825651, + 14743115, + -15222474, + 15134503, + -14343708, + 12710360, + -10091891, + 6343080, + -1314149, + -5154556, + 13243486, + -23174218, + 35246386, + -49905711, + 67875066, + -90425662, + 119998879, + -161853737, + 229472505, + -369909774, + 932444601, + 1461114371, + -361976166, + 182728934, + -106383275, + 63007473, + -34766272, + 15038822, + -795929, + -9561299, + 16978445, + -22073792, + 25290375, + -26972147, + 27403763, + -26831647, + 25474929, + -23530723, + 21176260, + -18569352, + 15848091, + -13130355, + 10513476, + -8074279, + 5869613, + -3937391, + 2298127, + -956886, + -94423, + 874553, + -1410327, + 1734067, + -1881173, + 1887914, + -1789538, + 1618728, + -1404449, + 1171177, + -938509, + 721093, + -528870, + 367521, + -239095, + 142729, + -75412, + -75412, + 142729, + -239095, + 367521, + -528870, + 721093, + -938509, + 1171177, + -1404449, + 1618728, + -1789538, + 1887914, + -1881173, + 1734067, + -1410327, + 874553, + -94423, + -956886, + 2298127, + -3937391, + 5869613, + -8074279, + 10513476, + -13130355, + 15848091, + -18569352, + 21176260, + -23530723, + 25474929, + -26831647, + 27403763, + -26972147, + 25290375, + -22073792, + 16978445, + -9561299, + -795929, + 15038822, + -34766272, + 63007473, + -106383275, + 182728934, + -361976166, + 1461114371, + 932444601, + -369909774, + 229472505, + -161853737, + 119998879, + -90425662, + 67875066, + -49905711, + 35246386, + -23174218, + 13243486, + -5154556, + -1314149, + 6343080, + -10091891, + 12710360, + -14343708, + 15134503, + -15222474, + 14743115, + -13825651, + 12590816, + -11148719, + 9597032, + -8019632, + 6485781, + -5049885, + 3751798, + -2617655, + 1661121, + -885003, + 283079, + 157934, + -456402, + 633869, + -713318, + 717655, + -668473, + 585105, + -483989, + 378322, + -277971, + 189618, + -117075, + 24318, + -133, + -52186, + 141438, + -276159, + 463787, + -709698, + 1016168, + -1381308, + 1798040, + -2253207, + 2726878, + -3191933, + 3614009, + -3951853, + 4158132, + -4180727, + 3964496, + -3453483, + 2593518, + -1335110, + -363454, + 2532951, + -5190123, + 8334785, + -11947265, + 15986286, + -20387357, + 25061680, + -29895522, + 34749839, + -39459786, + 43833437, + -47648483, + 50644700, + -52507853, + 52836065, + -51068157, + 46321858, + -36989159, + 19545653, + 16013223, + -115092154, + 1775663649, + 352289694, + -205545868, + 156801585, + -129645170, + 110480787, + -95078238, + 81765532, + -69803863, + 58857567, + -48783143, + 39532369, + -31102720, + 23509887, + -16771756, + 10898942, + -5889416, + 1725890, + 1624834, + -4211085, + 6094510, + -7347530, + 8050355, + -8287785, + 8146004, + -7709550, + 7058601, + -6266696, + 5398956, + -4510854, + 3647541, + -2843689, + 2123834, + -1503105, + 988295, + -579151, + 269806, + -50243, + -92271, + 171872, + -202952, + 199213, + -172955, + 134596, + -92406 + +}; + +static const struct src_stage src_int32_4_3_4535_5000 = { + 2, 3, 4, 88, 352, 3, 4, 0, 0, + src_int32_4_3_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_4_5_4535_5000.h b/src/audio/src/coef/src_small_int32_4_5_4535_5000.h new file mode 100644 index 000000000000..aa7e35768a9f --- /dev/null +++ b/src/audio/src/coef/src_small_int32_4_5_4535_5000.h @@ -0,0 +1,463 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_4_5_4535_5000_fir[448] = { + 71197, + -96779, + 49471, + 85409, + -249620, + 321751, + -187249, + -162743, + 572338, + -766164, + 506483, + 214023, + -1075304, + 1535643, + -1134552, + -157396, + 1774072, + -2748372, + 2241133, + -141248, + -2649605, + 4526754, + -4040825, + 880487, + 3634157, + -6991115, + 6800004, + -2339659, + -4597630, + 10262034, + -10859531, + 4910493, + 5331598, + -14483712, + 16700446, + -9174130, + -5519618, + 19896659, + -25124266, + 16109422, + 4656499, + -27042398, + 37777274, + -27726862, + -1778565, + 37420162, + -58980862, + 49472473, + -5686995, + -56402088, + 105055953, + -104547276, + 30335097, + 120333249, + -332918830, + 641217564, + 1515878931, + 254016049, + -283518341, + 188001418, + -61254071, + -41716994, + 90509401, + -82264524, + 36951969, + 15118703, + -47934955, + 50108990, + -27004864, + -5041821, + 28528196, + -33402967, + 20612607, + 301835, + -17418197, + 22780995, + -15711374, + 1916803, + 10470131, + -15421055, + 11715755, + -2742286, + -6022945, + 10173762, + -8438543, + 2773374, + 3221936, + -6449790, + 5809674, + -2384200, + -1538201, + 3875806, + -3781265, + 1823308, + 603237, + -2172444, + 2294270, + -1251922, + -146740, + 1110939, + -1271122, + 763718, + -28762, + -500257, + 620541, + -399952, + 60879, + 185210, + -247312, + 164013, + -37441, + -46793, + 53196, + -118900, + 132265, + -37302, + -158942, + 356034, + -395146, + 159954, + 310006, + -778671, + 906885, + -461246, + -474555, + 1440627, + -1790070, + 1074820, + 580252, + -2379592, + 3186860, + -2182763, + -501007, + 3603589, + -5253282, + 4021510, + 42998, + -5078385, + 8157742, + -6894411, + 1074280, + 6717506, + -12093356, + 11206091, + -3254844, + -8374809, + 17324320, + -17555796, + 7116647, + 9834903, + -24317648, + 26994230, + -13743550, + -10782869, + 34124908, + -41805068, + 25498644, + 10678376, + -49718675, + 68500003, + -49463489, + -8104787, + 82993023, + -136382438, + 123761888, + -6035650, + -264895412, + 1028749682, + 1341442134, + -63806136, + -157121838, + 185455984, + -122130393, + 28660134, + 47261926, + -78855949, + 64379051, + -22147905, + -21466923, + 45274738, + -41823323, + 18187533, + 10127571, + -28200844, + 28864160, + -14869008, + -4193068, + 17845847, + -20132109, + 11849132, + 995700, + -11111597, + 13846766, + -9105405, + 611055, + 6660091, + -9244198, + 6692693, + -1256094, + -3765930, + 5913035, + -4666762, + 1339785, + 1960696, + -3576007, + 3055637, + -1133409, + -906287, + 2011528, + -1851585, + 818846, + 347252, + -1027906, + 1014441, + -508955, + -91950, + 458499, + -481234, + 262654, + 3130, + -164016, + 178312, + -99102, + 9852, + 9852, + -99102, + 178312, + -164016, + 3130, + 262654, + -481234, + 458499, + -91950, + -508955, + 1014441, + -1027906, + 347252, + 818846, + -1851585, + 2011528, + -906287, + -1133409, + 3055637, + -3576007, + 1960696, + 1339785, + -4666762, + 5913035, + -3765930, + -1256094, + 6692693, + -9244198, + 6660091, + 611055, + -9105405, + 13846766, + -11111597, + 995700, + 11849132, + -20132109, + 17845847, + -4193068, + -14869008, + 28864160, + -28200844, + 10127571, + 18187533, + -41823323, + 45274738, + -21466923, + -22147905, + 64379051, + -78855949, + 47261926, + 28660134, + -122130393, + 185455984, + -157121838, + -63806136, + 1341442134, + 1028749682, + -264895412, + -6035650, + 123761888, + -136382438, + 82993023, + -8104787, + -49463489, + 68500003, + -49718675, + 10678376, + 25498644, + -41805068, + 34124908, + -10782869, + -13743550, + 26994230, + -24317648, + 9834903, + 7116647, + -17555796, + 17324320, + -8374809, + -3254844, + 11206091, + -12093356, + 6717506, + 1074280, + -6894411, + 8157742, + -5078385, + 42998, + 4021510, + -5253282, + 3603589, + -501007, + -2182763, + 3186860, + -2379592, + 580252, + 1074820, + -1790070, + 1440627, + -474555, + -461246, + 906885, + -778671, + 310006, + 159954, + -395146, + 356034, + -158942, + -37302, + 132265, + -118900, + 53196, + -46793, + -37441, + 164013, + -247312, + 185210, + 60879, + -399952, + 620541, + -500257, + -28762, + 763718, + -1271122, + 1110939, + -146740, + -1251922, + 2294270, + -2172444, + 603237, + 1823308, + -3781265, + 3875806, + -1538201, + -2384200, + 5809674, + -6449790, + 3221936, + 2773374, + -8438543, + 10173762, + -6022945, + -2742286, + 11715755, + -15421055, + 10470131, + 1916803, + -15711374, + 22780995, + -17418197, + 301835, + 20612607, + -33402967, + 28528196, + -5041821, + -27004864, + 50108990, + -47934955, + 15118703, + 36951969, + -82264524, + 90509401, + -41716994, + -61254071, + 188001418, + -283518341, + 254016049, + 1515878931, + 641217564, + -332918830, + 120333249, + 30335097, + -104547276, + 105055953, + -56402088, + -5686995, + 49472473, + -58980862, + 37420162, + -1778565, + -27726862, + 37777274, + -27042398, + 4656499, + 16109422, + -25124266, + 19896659, + -5519618, + -9174130, + 16700446, + -14483712, + 5331598, + 4910493, + -10859531, + 10262034, + -4597630, + -2339659, + 6800004, + -6991115, + 3634157, + 880487, + -4040825, + 4526754, + -2649605, + -141248, + 2241133, + -2748372, + 1774072, + -157396, + -1134552, + 1535643, + -1075304, + 214023, + 506483, + -766164, + 572338, + -162743, + -187249, + 321751, + -249620, + 85409, + 49471, + -96779, + 71197 + +}; + +static const struct src_stage src_int32_4_5_4535_5000 = { + 1, 1, 4, 112, 448, 5, 4, 0, 0, + src_int32_4_5_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_5_4_4535_5000.h b/src/audio/src/coef/src_small_int32_5_4_4535_5000.h new file mode 100644 index 000000000000..afbbec4122be --- /dev/null +++ b/src/audio/src/coef/src_small_int32_5_4_4535_5000.h @@ -0,0 +1,455 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_5_4_4535_5000_fir[440] = { + -83573, + 123255, + -160503, + 187662, + -194816, + 169963, + -99413, + -31555, + 237777, + -533049, + 928749, + -1432306, + 2045568, + -2763183, + 3571078, + -4445155, + 5350323, + -6239964, + 7055936, + -7729182, + 8180988, + -8324897, + 8069255, + -7320302, + 5985695, + -3978305, + 1220083, + 2354242, + -6793899, + 12129543, + -18371801, + 25511269, + -33520492, + 42358605, + -51979800, + 62347685, + -73459618, + 85389914, + -98372924, + 112981571, + -130571352, + 154629535, + -196364057, + 317509286, + 1894871335, + -79753133, + -7542746, + 37898401, + -52096437, + 58989529, + -61697143, + 61660667, + -59690841, + 56320619, + -51944606, + 46879672, + -41392530, + 35712260, + -30035688, + 24529420, + -19330488, + 14546675, + -10257080, + 6513231, + -3340841, + 742224, + 1300724, + -2823102, + 3873307, + -4509233, + 4794542, + -4795165, + 4576168, + -4199091, + 3719826, + -3187081, + 2641422, + -2114863, + 1630962, + -1205330, + 846469, + -556843, + 334087, + -172257, + 63037, + 3152, + -36198, + 45533, + -104602, + 168065, + -243920, + 327919, + -413003, + 489008, + -542547, + 557143, + -513626, + 390850, + -166736, + -180367, + 670033, + -1317870, + 2133467, + -3118282, + 4263577, + -5548534, + 6938669, + -8384681, + 9821846, + -11170022, + 12334354, + -13206648, + 13667413, + -13588439, + 12835765, + -11272797, + 8763226, + -5173336, + 373069, + 5764967, + -13369812, + 22581761, + -33570694, + 46569474, + -61935137, + 80265665, + -102639004, + 131154423, + -170345927, + 231725796, + -354343580, + 801509473, + 1676815034, + -331091304, + 150372751, + -76520609, + 35787473, + -10114691, + -7092514, + 18840204, + -26726422, + 31712691, + -34443350, + 35392372, + -34935610, + 33387666, + -31020803, + 28074354, + -24759028, + 21258568, + -17730192, + 14304652, + -11086443, + 8154428, + -5563034, + 3344031, + -1508866, + 51442, + 1048791, + -1823568, + 2312541, + -2560130, + 2612639, + -2515737, + 2312365, + -2041140, + 1735242, + -1421782, + 1121614, + -849528, + 614741, + -421631, + 270600, + -159015, + 82139, + -33996, + -88646, + 156214, + -248013, + 364876, + -505192, + 664212, + -833445, + 1000178, + -1147218, + 1252903, + -1291443, + 1233643, + -1048021, + 702331, + -165473, + -590276, + 1586764, + -2837331, + 4344126, + -6095545, + 8063911, + -10203541, + 12449319, + -14715871, + 16897394, + -18868139, + 20483463, + -21581297, + 21983732, + -21498284, + 19918160, + -17020486, + 12560868, + -6261566, + -2211506, + 13291980, + -27594850, + 46077612, + -70380387, + 103621567, + -152557355, + 234920355, + -416100017, + 1285934782, + 1285934782, + -416100017, + 234920355, + -152557355, + 103621567, + -70380387, + 46077612, + -27594850, + 13291980, + -2211506, + -6261566, + 12560868, + -17020486, + 19918160, + -21498284, + 21983732, + -21581297, + 20483463, + -18868139, + 16897394, + -14715871, + 12449319, + -10203541, + 8063911, + -6095545, + 4344126, + -2837331, + 1586764, + -590276, + -165473, + 702331, + -1048021, + 1233643, + -1291443, + 1252903, + -1147218, + 1000178, + -833445, + 664212, + -505192, + 364876, + -248013, + 156214, + -88646, + -33996, + 82139, + -159015, + 270600, + -421631, + 614741, + -849528, + 1121614, + -1421782, + 1735242, + -2041140, + 2312365, + -2515737, + 2612639, + -2560130, + 2312541, + -1823568, + 1048791, + 51442, + -1508866, + 3344031, + -5563034, + 8154428, + -11086443, + 14304652, + -17730192, + 21258568, + -24759028, + 28074354, + -31020803, + 33387666, + -34935610, + 35392372, + -34443350, + 31712691, + -26726422, + 18840204, + -7092514, + -10114691, + 35787473, + -76520609, + 150372751, + -331091304, + 1676815034, + 801509473, + -354343580, + 231725796, + -170345927, + 131154423, + -102639004, + 80265665, + -61935137, + 46569474, + -33570694, + 22581761, + -13369812, + 5764967, + 373069, + -5173336, + 8763226, + -11272797, + 12835765, + -13588439, + 13667413, + -13206648, + 12334354, + -11170022, + 9821846, + -8384681, + 6938669, + -5548534, + 4263577, + -3118282, + 2133467, + -1317870, + 670033, + -180367, + -166736, + 390850, + -513626, + 557143, + -542547, + 489008, + -413003, + 327919, + -243920, + 168065, + -104602, + 45533, + -36198, + 3152, + 63037, + -172257, + 334087, + -556843, + 846469, + -1205330, + 1630962, + -2114863, + 2641422, + -3187081, + 3719826, + -4199091, + 4576168, + -4795165, + 4794542, + -4509233, + 3873307, + -2823102, + 1300724, + 742224, + -3340841, + 6513231, + -10257080, + 14546675, + -19330488, + 24529420, + -30035688, + 35712260, + -41392530, + 46879672, + -51944606, + 56320619, + -59690841, + 61660667, + -61697143, + 58989529, + -52096437, + 37898401, + -7542746, + -79753133, + 1894871335, + 317509286, + -196364057, + 154629535, + -130571352, + 112981571, + -98372924, + 85389914, + -73459618, + 62347685, + -51979800, + 42358605, + -33520492, + 25511269, + -18371801, + 12129543, + -6793899, + 2354242, + 1220083, + -3978305, + 5985695, + -7320302, + 8069255, + -8324897, + 8180988, + -7729182, + 7055936, + -6239964, + 5350323, + -4445155, + 3571078, + -2763183, + 2045568, + -1432306, + 928749, + -533049, + 237777, + -31555, + -99413, + 169963, + -194816, + 187662, + -160503, + 123255, + -83573 + +}; + +static const struct src_stage src_int32_5_4_4535_5000 = { + 3, 4, 5, 88, 440, 4, 5, 0, 0, + src_int32_5_4_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_5_6_4354_5000.h b/src/audio/src/coef/src_small_int32_5_6_4354_5000.h new file mode 100644 index 000000000000..414fddc38515 --- /dev/null +++ b/src/audio/src/coef/src_small_int32_5_6_4354_5000.h @@ -0,0 +1,395 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_5_6_4354_5000_fir[380] = { + -110765, + 202615, + -181213, + -60411, + 501917, + -921634, + 953432, + -299021, + -994344, + 2375699, + -2930341, + 1853065, + 938266, + -4421028, + 6675774, + -5774708, + 1018501, + 6157586, + -12304414, + 13377047, + -6992399, + -5591173, + 19053336, + -25865264, + 19988179, + -798577, + -24932443, + 44636431, + -45182001, + 19866113, + 26046873, + -74343877, + 98819194, + -74821263, + -10514225, + 152667682, + -335622766, + 582806597, + 1554862275, + 262253212, + -280549671, + 194075077, + -79589975, + -18519170, + 74070145, + -81274868, + 52259402, + -9027332, + -26768671, + 42009053, + -35327860, + 14935758, + 7047191, + -20678805, + 22006533, + -13416074, + 1099419, + 8600165, + -12066006, + 9371949, + -3330588, + -2481991, + 5557309, + -5318073, + 2851946, + 63634, + -1989169, + 2393574, + -1619886, + 439526, + 460670, + -781233, + 616459, + -258714, + -28531, + 136998, + -84272, + 227519, + -313644, + 183996, + 244422, + -848023, + 1264573, + -1041170, + -62356, + 1773109, + -3236736, + 3338270, + -1353763, + -2384260, + 6258494, + -7899350, + 5411268, + 1253179, + -9597597, + 15229439, + -13885351, + 4029762, + 11363736, + -25148377, + 28871533, + -17231281, + -7971064, + 36720596, + -53867037, + 45807278, + -8187315, + -48973765, + 101648548, + -118211915, + 69147397, + 66618723, + -316432297, + 912796765, + 1434247379, + -10835542, + -175714416, + 187947221, + -124187428, + 37194100, + 34538116, + -69457064, + 65060050, + -34187001, + -3335742, + 30011856, + -37157358, + 26443067, + -6800413, + -11082012, + 19809927, + -17768431, + 8487264, + 2149878, + -9109682, + 10269995, + -6653311, + 1157507, + 3259408, + -4952125, + 3982226, + -1602490, + -676653, + 1872174, + -1825398, + 1008386, + -84144, + -482090, + 579489, + -372305, + 106682, + 52972, + -26669, + 196411, + -387115, + 417986, + -109422, + -552896, + 1295790, + -1602646, + 975263, + 680802, + -2778428, + 4131268, + -3494980, + 381983, + 4297017, + -8261457, + 8789295, + -4266521, + -4414489, + 13534842, + -17852419, + 13241572, + 511288, + -18365939, + 31340812, + -30467503, + 11871794, + 19540469, + -50157374, + 62395995, + -42778263, + -9896067, + 80067707, + -136995981, + 141425750, + -50460371, + -208459562, + 1209907046, + 1209907046, + -208459562, + -50460371, + 141425750, + -136995981, + 80067707, + -9896067, + -42778263, + 62395995, + -50157374, + 19540469, + 11871794, + -30467503, + 31340812, + -18365939, + 511288, + 13241572, + -17852419, + 13534842, + -4414489, + -4266521, + 8789295, + -8261457, + 4297017, + 381983, + -3494980, + 4131268, + -2778428, + 680802, + 975263, + -1602646, + 1295790, + -552896, + -109422, + 417986, + -387115, + 196411, + -26669, + 52972, + 106682, + -372305, + 579489, + -482090, + -84144, + 1008386, + -1825398, + 1872174, + -676653, + -1602490, + 3982226, + -4952125, + 3259408, + 1157507, + -6653311, + 10269995, + -9109682, + 2149878, + 8487264, + -17768431, + 19809927, + -11082012, + -6800413, + 26443067, + -37157358, + 30011856, + -3335742, + -34187001, + 65060050, + -69457064, + 34538116, + 37194100, + -124187428, + 187947221, + -175714416, + -10835542, + 1434247379, + 912796765, + -316432297, + 66618723, + 69147397, + -118211915, + 101648548, + -48973765, + -8187315, + 45807278, + -53867037, + 36720596, + -7971064, + -17231281, + 28871533, + -25148377, + 11363736, + 4029762, + -13885351, + 15229439, + -9597597, + 1253179, + 5411268, + -7899350, + 6258494, + -2384260, + -1353763, + 3338270, + -3236736, + 1773109, + -62356, + -1041170, + 1264573, + -848023, + 244422, + 183996, + -313644, + 227519, + -84272, + 136998, + -28531, + -258714, + 616459, + -781233, + 460670, + 439526, + -1619886, + 2393574, + -1989169, + 63634, + 2851946, + -5318073, + 5557309, + -2481991, + -3330588, + 9371949, + -12066006, + 8600165, + 1099419, + -13416074, + 22006533, + -20678805, + 7047191, + 14935758, + -35327860, + 42009053, + -26768671, + -9027332, + 52259402, + -81274868, + 74070145, + -18519170, + -79589975, + 194075077, + -280549671, + 262253212, + 1554862275, + 582806597, + -335622766, + 152667682, + -10514225, + -74821263, + 98819194, + -74343877, + 26046873, + 19866113, + -45182001, + 44636431, + -24932443, + -798577, + 19988179, + -25865264, + 19053336, + -5591173, + -6992399, + 13377047, + -12304414, + 6157586, + 1018501, + -5774708, + 6675774, + -4421028, + 938266, + 1853065, + -2930341, + 2375699, + -994344, + -299021, + 953432, + -921634, + 501917, + -60411, + -181213, + 202615, + -110765 + +}; + +static const struct src_stage src_int32_5_6_4354_5000 = { + 1, 1, 5, 76, 380, 6, 5, 0, 0, + src_int32_5_6_4354_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_6_5_4354_5000.h b/src/audio/src/coef/src_small_int32_6_5_4354_5000.h new file mode 100644 index 000000000000..6738c05b884e --- /dev/null +++ b/src/audio/src/coef/src_small_int32_6_5_4354_5000.h @@ -0,0 +1,399 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_6_5_4354_5000_fir[384] = { + -122729, + 196634, + -249782, + 247228, + -144395, + -109525, + 565887, + -1268757, + 2245363, + -3495634, + 4981904, + -6620079, + 8273620, + -9751632, + 10812091, + -11170770, + 10515920, + -8528033, + 4903361, + 620828, + -8241850, + 18071114, + -30121039, + 44303371, + -60444150, + 78323752, + -97759589, + 118776503, + -142002792, + 169812384, + -210916831, + 314734689, + 1865916563, + -13004206, + -60572172, + 83031930, + -89887398, + 89039047, + -83556033, + 75128491, + -64926564, + 53865148, + -42689976, + 32002640, + -22265509, + 13802955, + -6805786, + 1341418, + 2629977, + -5234475, + 6660371, + -7133253, + 6892271, + -6169392, + 5172972, + -4076403, + 3012002, + -2069806, + 1300460, + -721154, + 323399, + -81465, + -39539, + 76746, + -162323, + 288382, + -430169, + 559717, + -634563, + 598435, + -384367, + -79457, + 861136, + -2014137, + 3564771, + -5499170, + 7751141, + -10192388, + 12626599, + -14788626, + 16349570, + -16927941, + 16106305, + -13451864, + 8538426, + -965962, + -9627644, + 23570709, + -41191016, + 62903738, + -89411161, + 122164212, + -164553432, + 225657595, + -336741254, + 699423821, + 1721178547, + -250187728, + 79972277, + -12626314, + -22250260, + 41522712, + -51468862, + 55163663, + -54468639, + 50705446, + -44911645, + 37940474, + -30497334, + 23150979, + -16336703, + 10359773, + -5402812, + 1538281, + 1254322, + -3067852, + 4045259, + -4357570, + 4183830, + -3694379, + 3038345, + -2335736, + 1673994, + -1108468, + 665942, + -350220, + 148707, + -39046, + -166351, + 321375, + -528470, + 773480, + -1025826, + 1236191, + -1336245, + 1241100, + -854928, + 79902, + 1171778, + -2963460, + 5318269, + -8203425, + 11516243, + -15073474, + 18605395, + -21755646, + 24087065, + -25092821, + 24210826, + -20837670, + 14335759, + -4022932, + -10874888, + 31347458, + -58891845, + 96217809, + -149156391, + 233001432, + -402830430, + 1095427867, + 1451967844, + -379784762, + 183278830, + -95584911, + 44691924, + -11898744, + -9852006, + 23927867, + -32276875, + 36232633, + -36834829, + 34960944, + -31376441, + 26748533, + -21644850, + 16528002, + -11751861, + 7562409, + -4104130, + 1431660, + 474425, + -1689268, + 2324598, + -2510495, + 2379451, + -2053729, + 1636582, + -1207376, + 820305, + -506047, + 275522, + -124854, + -124854, + 275522, + -506047, + 820305, + -1207376, + 1636582, + -2053729, + 2379451, + -2510495, + 2324598, + -1689268, + 474425, + 1431660, + -4104130, + 7562409, + -11751861, + 16528002, + -21644850, + 26748533, + -31376441, + 34960944, + -36834829, + 36232633, + -32276875, + 23927867, + -9852006, + -11898744, + 44691924, + -95584911, + 183278830, + -379784762, + 1451967844, + 1095427867, + -402830430, + 233001432, + -149156391, + 96217809, + -58891845, + 31347458, + -10874888, + -4022932, + 14335759, + -20837670, + 24210826, + -25092821, + 24087065, + -21755646, + 18605395, + -15073474, + 11516243, + -8203425, + 5318269, + -2963460, + 1171778, + 79902, + -854928, + 1241100, + -1336245, + 1236191, + -1025826, + 773480, + -528470, + 321375, + -166351, + -39046, + 148707, + -350220, + 665942, + -1108468, + 1673994, + -2335736, + 3038345, + -3694379, + 4183830, + -4357570, + 4045259, + -3067852, + 1254322, + 1538281, + -5402812, + 10359773, + -16336703, + 23150979, + -30497334, + 37940474, + -44911645, + 50705446, + -54468639, + 55163663, + -51468862, + 41522712, + -22250260, + -12626314, + 79972277, + -250187728, + 1721178547, + 699423821, + -336741254, + 225657595, + -164553432, + 122164212, + -89411161, + 62903738, + -41191016, + 23570709, + -9627644, + -965962, + 8538426, + -13451864, + 16106305, + -16927941, + 16349570, + -14788626, + 12626599, + -10192388, + 7751141, + -5499170, + 3564771, + -2014137, + 861136, + -79457, + -384367, + 598435, + -634563, + 559717, + -430169, + 288382, + -162323, + 76746, + -39539, + -81465, + 323399, + -721154, + 1300460, + -2069806, + 3012002, + -4076403, + 5172972, + -6169392, + 6892271, + -7133253, + 6660371, + -5234475, + 2629977, + 1341418, + -6805786, + 13802955, + -22265509, + 32002640, + -42689976, + 53865148, + -64926564, + 75128491, + -83556033, + 89039047, + -89887398, + 83031930, + -60572172, + -13004206, + 1865916563, + 314734689, + -210916831, + 169812384, + -142002792, + 118776503, + -97759589, + 78323752, + -60444150, + 44303371, + -30121039, + 18071114, + -8241850, + 620828, + 4903361, + -8528033, + 10515920, + -11170770, + 10812091, + -9751632, + 8273620, + -6620079, + 4981904, + -3495634, + 2245363, + -1268757, + 565887, + -109525, + -144395, + 247228, + -249782, + 196634, + -122729 + +}; + +static const struct src_stage src_int32_6_5_4354_5000 = { + 4, 5, 6, 64, 384, 5, 6, 0, 0, + src_int32_6_5_4354_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_7_8_4535_5000.h b/src/audio/src/coef/src_small_int32_7_8_4535_5000.h new file mode 100644 index 000000000000..528da1cbe98b --- /dev/null +++ b/src/audio/src/coef/src_small_int32_7_8_4535_5000.h @@ -0,0 +1,659 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_7_8_4535_5000_fir[644] = { + -1007, + -96094, + 242640, + -381988, + 424738, + -280782, + -93512, + 650578, + -1232177, + 1594041, + -1479668, + 727727, + 622321, + -2272348, + 3695256, + -4267611, + 3482895, + -1184302, + -2268506, + 5981440, + -8703830, + 9186789, + -6635500, + 1113458, + 6258943, + -13430918, + 17903445, + -17479559, + 11084235, + 609059, + -14995467, + 27951399, + -34829269, + 31832387, + -17414295, + -6718221, + 35362958, + -60530092, + 73033814, + -64633956, + 30188470, + 30811190, + -113932062, + 211410274, + -317877633, + 461686142, + 1668052163, + 209738924, + -242218976, + 205545620, + -141891825, + 71019482, + -7602771, + -38214594, + 61616268, + -63199427, + 48005297, + -23712768, + -1521836, + 21028332, + -30937164, + 30605674, + -22173610, + 9489454, + 3218003, + -12533544, + 16619057, + -15412986, + 10308030, + -3487402, + -2834248, + 7034088, + -8416490, + 7218636, + -4347977, + 980404, + 1835272, + -3451050, + 3715641, + -2901752, + 1523539, + -124452, + -892483, + 1349154, + -1285582, + 886509, + -381800, + -40076, + 280288, + -333735, + 259847, + -139778, + -47510, + -32575, + 187993, + -379272, + 520014, + -499461, + 228113, + 307119, + -1001281, + 1628033, + -1890280, + 1521405, + -410322, + -1295157, + 3156998, + -4523127, + 4713001, + -3271039, + 208228, + 3864443, + -7790464, + 10138976, + -9647531, + 5717425, + 1204229, + -9518385, + 16744747, + -20159998, + 17665599, + -8640951, + -5505824, + 21332740, + -34015860, + 38580205, + -31437366, + 11820142, + 17324920, + -49324227, + 74761113, + -83287701, + 65805814, + -16310156, + -67599344, + 187515183, + -358876654, + 730996555, + 1592150862, + -8011351, + -145526975, + 173436395, + -149186864, + 99457121, + -42465930, + -7889760, + 42430804, + -57303990, + 53756119, + -36940236, + 14046507, + 7749565, + -23011835, + 29063396, + -26147585, + 16817970, + -4835454, + -6058053, + 13141672, + -15260034, + 12839891, + -7466769, + 1218560, + 4011786, + -7009738, + 7441987, + -5765883, + 2929457, + 7983, + -2206283, + 3237738, + -3114585, + 2178707, + -918114, + -216419, + 937554, + -1164499, + 989881, + -600348, + 188897, + 109772, + -245295, + 240863, + -159883, + -93748, + 43522, + 100159, + -321356, + 548300, + -663024, + 539377, + -101861, + -614984, + 1434364, + -2056897, + 2141837, + -1435660, + -91075, + 2153099, + -4157667, + 5336292, + -4985281, + 2752143, + 1129530, + -5759525, + 9715137, + -11423736, + 9684497, + -4187480, + -4154992, + 13224059, + -20129512, + 22007494, + -16989113, + 5053360, + 11539062, + -28454845, + 40199395, + -41580905, + 29385503, + -3809322, + -30793319, + 66133852, + -91205216, + 94171436, + -64227720, + -7873114, + 133963932, + -353785685, + 998244056, + 1446575195, + -178771684, + -42062699, + 121497390, + -136315458, + 113076178, + -69940265, + 22138004, + 18352023, + -43957431, + 52093682, + -44757780, + 27213478, + -6141629, + -12245613, + 23663331, + -26483087, + 21657700, + -11987520, + 1028195, + 8008442, + -13061279, + 13563713, + -10310403, + 4969657, + 556273, + -4712515, + 6658675, + -6356815, + 4409621, + -1746520, + -718168, + 2347226, + -2901103, + 2511608, + -1549828, + 453401, + 423418, + -895194, + 954999, + -724500, + 376326, + -61948, + -131992, + 191763, + -156345, + -132395, + 122157, + -11210, + -211769, + 500108, + -743914, + 795093, + -522325, + -118804, + 1027618, + -1943007, + 2492897, + -2309262, + 1181498, + 803466, + -3195751, + 5240567, + -6072791, + 5010976, + -1865338, + -2852992, + 7925181, + -11673970, + 12441411, + -9178272, + 1962208, + 7753186, + -17304733, + 23435447, + -23248298, + 15251838, + -174443, + -18760839, + 36292247, + -46302635, + 43505079, + -25224170, + -7212191, + 47891729, + -86756328, + 110928362, + -106317740, + 58041280, + 54810193, + -294785465, + 1243169872, + 1243169872, + -294785465, + 54810193, + 58041280, + -106317740, + 110928362, + -86756328, + 47891729, + -7212191, + -25224170, + 43505079, + -46302635, + 36292247, + -18760839, + -174443, + 15251838, + -23248298, + 23435447, + -17304733, + 7753186, + 1962208, + -9178272, + 12441411, + -11673970, + 7925181, + -2852992, + -1865338, + 5010976, + -6072791, + 5240567, + -3195751, + 803466, + 1181498, + -2309262, + 2492897, + -1943007, + 1027618, + -118804, + -522325, + 795093, + -743914, + 500108, + -211769, + -11210, + 122157, + -132395, + -156345, + 191763, + -131992, + -61948, + 376326, + -724500, + 954999, + -895194, + 423418, + 453401, + -1549828, + 2511608, + -2901103, + 2347226, + -718168, + -1746520, + 4409621, + -6356815, + 6658675, + -4712515, + 556273, + 4969657, + -10310403, + 13563713, + -13061279, + 8008442, + 1028195, + -11987520, + 21657700, + -26483087, + 23663331, + -12245613, + -6141629, + 27213478, + -44757780, + 52093682, + -43957431, + 18352023, + 22138004, + -69940265, + 113076178, + -136315458, + 121497390, + -42062699, + -178771684, + 1446575195, + 998244056, + -353785685, + 133963932, + -7873114, + -64227720, + 94171436, + -91205216, + 66133852, + -30793319, + -3809322, + 29385503, + -41580905, + 40199395, + -28454845, + 11539062, + 5053360, + -16989113, + 22007494, + -20129512, + 13224059, + -4154992, + -4187480, + 9684497, + -11423736, + 9715137, + -5759525, + 1129530, + 2752143, + -4985281, + 5336292, + -4157667, + 2153099, + -91075, + -1435660, + 2141837, + -2056897, + 1434364, + -614984, + -101861, + 539377, + -663024, + 548300, + -321356, + 100159, + 43522, + -93748, + -159883, + 240863, + -245295, + 109772, + 188897, + -600348, + 989881, + -1164499, + 937554, + -216419, + -918114, + 2178707, + -3114585, + 3237738, + -2206283, + 7983, + 2929457, + -5765883, + 7441987, + -7009738, + 4011786, + 1218560, + -7466769, + 12839891, + -15260034, + 13141672, + -6058053, + -4835454, + 16817970, + -26147585, + 29063396, + -23011835, + 7749565, + 14046507, + -36940236, + 53756119, + -57303990, + 42430804, + -7889760, + -42465930, + 99457121, + -149186864, + 173436395, + -145526975, + -8011351, + 1592150862, + 730996555, + -358876654, + 187515183, + -67599344, + -16310156, + 65805814, + -83287701, + 74761113, + -49324227, + 17324920, + 11820142, + -31437366, + 38580205, + -34015860, + 21332740, + -5505824, + -8640951, + 17665599, + -20159998, + 16744747, + -9518385, + 1204229, + 5717425, + -9647531, + 10138976, + -7790464, + 3864443, + 208228, + -3271039, + 4713001, + -4523127, + 3156998, + -1295157, + -410322, + 1521405, + -1890280, + 1628033, + -1001281, + 307119, + 228113, + -499461, + 520014, + -379272, + 187993, + -32575, + -47510, + -139778, + 259847, + -333735, + 280288, + -40076, + -381800, + 886509, + -1285582, + 1349154, + -892483, + -124452, + 1523539, + -2901752, + 3715641, + -3451050, + 1835272, + 980404, + -4347977, + 7218636, + -8416490, + 7034088, + -2834248, + -3487402, + 10308030, + -15412986, + 16619057, + -12533544, + 3218003, + 9489454, + -22173610, + 30605674, + -30937164, + 21028332, + -1521836, + -23712768, + 48005297, + -63199427, + 61616268, + -38214594, + -7602771, + 71019482, + -141891825, + 205545620, + -242218976, + 209738924, + 1668052163, + 461686142, + -317877633, + 211410274, + -113932062, + 30811190, + 30188470, + -64633956, + 73033814, + -60530092, + 35362958, + -6718221, + -17414295, + 31832387, + -34829269, + 27951399, + -14995467, + 609059, + 11084235, + -17479559, + 17903445, + -13430918, + 6258943, + 1113458, + -6635500, + 9186789, + -8703830, + 5981440, + -2268506, + -1184302, + 3482895, + -4267611, + 3695256, + -2272348, + 622321, + 727727, + -1479668, + 1594041, + -1232177, + 650578, + -93512, + -280782, + 424738, + -381988, + 242640, + -96094, + -1007 + +}; + +static const struct src_stage src_int32_7_8_4535_5000 = { + 1, 1, 7, 92, 644, 8, 7, 0, 0, + src_int32_7_8_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_8_7_4535_5000.h b/src/audio/src/coef/src_small_int32_8_7_4535_5000.h new file mode 100644 index 000000000000..e20488b0aa6e --- /dev/null +++ b/src/audio/src/coef/src_small_int32_8_7_4535_5000.h @@ -0,0 +1,655 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int32_t src_int32_8_7_4535_5000_fir[640] = { + -93442, + 125750, + -138530, + 116746, + -43044, + -101212, + 334492, + -673307, + 1130107, + -1711012, + 2413497, + -3224193, + 4117001, + -5051674, + 5973063, + -6811159, + 7482045, + -7889824, + 7929516, + -7490867, + 6462930, + -4739228, + 2223229, + 1166168, + -5489507, + 10782375, + -17052137, + 24276232, + -32402484, + 41351981, + -51025278, + 61313219, + -72114819, + 83367552, + -95102678, + 107559185, + -121458671, + 138823375, + -166299384, + 239693620, + 1906322077, + -9155468, + -48066112, + 66316974, + -73372729, + 75158695, + -73800022, + 70331439, + -65384437, + 59413677, + -52783069, + 45800568, + -38731928, + 31805359, + -25212372, + 19107391, + -13607426, + 8792492, + -4707074, + 1362701, + 1258444, + -3199055, + 4521635, + -5303103, + 5629354, + -5590070, + 5273997, + -4764909, + 4138376, + -3459432, + 2781152, + -2144104, + 1576595, + -1095574, + 708054, + -412876, + 202662, + -65790, + -11742, + 44663, + -132653, + 197980, + -257939, + 298508, + -301891, + 247105, + -111018, + -130148, + 498877, + -1014055, + 1688395, + -2525745, + 3518433, + -4644847, + 5867453, + -7131421, + 8364048, + -9475101, + 10358167, + -10893025, + 10948993, + -10389113, + 9074969, + -6871821, + 3653688, + 692113, + -6261556, + 13132355, + -21365269, + 31009674, + -42115701, + 54757023, + -69072344, + 85342903, + -104147133, + 126702130, + -155732115, + 198172545, + -276796278, + 527626477, + 1819577413, + -204301038, + 62632189, + -8995514, + -18631993, + 34478025, + -43632343, + 48430179, + -50153312, + 49615358, + -47397405, + 43952580, + -39654929, + 34822532, + -29728081, + 24603352, + -19640909, + 14994852, + -10781648, + 7081550, + -3940876, + 1375167, + 626850, + -2098677, + 3091078, + -3666967, + 3896424, + -3852056, + 3604922, + -3221139, + 2759303, + -2268728, + 1788516, + -1347378, + 964118, + -648631, + 403293, + -224566, + 104689, + -33319, + -157401, + 249355, + -351579, + 452951, + -537563, + 584769, + -569671, + 464121, + -238246, + -137518, + 689930, + -1440088, + 2400356, + -3571235, + 4938388, + -6470013, + 8114782, + -9800532, + 11433856, + -12900711, + 14068057, + -14786499, + 14893780, + -14218878, + 12586331, + -9820284, + 5747523, + -198546, + -6994767, + 16007069, + -27036704, + 40338832, + -56287799, + 75497698, + -99070470, + 129159125, + -170440817, + 234865238, + -363259237, + 835404953, + 1653204873, + -336879526, + 153079914, + -77234854, + 35196411, + -8682787, + -9007956, + 20945903, + -28778067, + 33510715, + -35832580, + 36262449, + -35220704, + 33064806, + -30106580, + 26620047, + -22844382, + 18984585, + -15211356, + 11661068, + -8436324, + 5607361, + -3214353, + 1270562, + 233819, + -1327322, + 2052619, + -2461913, + 2612553, + -2563062, + 2369743, + -2083970, + 1750225, + -1404888, + 1075730, + -782049, + 535321, + -340250, + 196063, + -97941, + -161676, + 269707, + -403118, + 555269, + -714319, + 862702, + -976996, + 1028269, + -982981, + 804478, + -455075, + -101301, + 896012, + -1952277, + 3281574, + -4880094, + 6725437, + -8773807, + 10957871, + -13185496, + 15339450, + -17278127, + 18837243, + -19832342, + 20061790, + -19309771, + 17348537, + -13938827, + 8826736, + -1734368, + -7660419, + 19763765, + -35142385, + 54674937, + -79870317, + 113606237, + -162110074, + 241570301, + -410115501, + 1140827794, + 1420741782, + -404301345, + 214269566, + -130169088, + 81125199, + -48496846, + 25274569, + -8231184, + -4345798, + 13478677, + -19847633, + 23953028, + -26195886, + 26918835, + -26426583, + 24995354, + -22876290, + 20295681, + -17453751, + 14523076, + -11647299, + 8940551, + -6487778, + 4346040, + -2546721, + 1098526, + 8926, + -801135, + 1314612, + -1592849, + 1682583, + -1630502, + 1480527, + -1271747, + 1037023, + -802247, + 586201, + -400924, + 252466, + -141924, + -141924, + 252466, + -400924, + 586201, + -802247, + 1037023, + -1271747, + 1480527, + -1630502, + 1682583, + -1592849, + 1314612, + -801135, + 8926, + 1098526, + -2546721, + 4346040, + -6487778, + 8940551, + -11647299, + 14523076, + -17453751, + 20295681, + -22876290, + 24995354, + -26426583, + 26918835, + -26195886, + 23953028, + -19847633, + 13478677, + -4345798, + -8231184, + 25274569, + -48496846, + 81125199, + -130169088, + 214269566, + -404301345, + 1420741782, + 1140827794, + -410115501, + 241570301, + -162110074, + 113606237, + -79870317, + 54674937, + -35142385, + 19763765, + -7660419, + -1734368, + 8826736, + -13938827, + 17348537, + -19309771, + 20061790, + -19832342, + 18837243, + -17278127, + 15339450, + -13185496, + 10957871, + -8773807, + 6725437, + -4880094, + 3281574, + -1952277, + 896012, + -101301, + -455075, + 804478, + -982981, + 1028269, + -976996, + 862702, + -714319, + 555269, + -403118, + 269707, + -161676, + -97941, + 196063, + -340250, + 535321, + -782049, + 1075730, + -1404888, + 1750225, + -2083970, + 2369743, + -2563062, + 2612553, + -2461913, + 2052619, + -1327322, + 233819, + 1270562, + -3214353, + 5607361, + -8436324, + 11661068, + -15211356, + 18984585, + -22844382, + 26620047, + -30106580, + 33064806, + -35220704, + 36262449, + -35832580, + 33510715, + -28778067, + 20945903, + -9007956, + -8682787, + 35196411, + -77234854, + 153079914, + -336879526, + 1653204873, + 835404953, + -363259237, + 234865238, + -170440817, + 129159125, + -99070470, + 75497698, + -56287799, + 40338832, + -27036704, + 16007069, + -6994767, + -198546, + 5747523, + -9820284, + 12586331, + -14218878, + 14893780, + -14786499, + 14068057, + -12900711, + 11433856, + -9800532, + 8114782, + -6470013, + 4938388, + -3571235, + 2400356, + -1440088, + 689930, + -137518, + -238246, + 464121, + -569671, + 584769, + -537563, + 452951, + -351579, + 249355, + -157401, + -33319, + 104689, + -224566, + 403293, + -648631, + 964118, + -1347378, + 1788516, + -2268728, + 2759303, + -3221139, + 3604922, + -3852056, + 3896424, + -3666967, + 3091078, + -2098677, + 626850, + 1375167, + -3940876, + 7081550, + -10781648, + 14994852, + -19640909, + 24603352, + -29728081, + 34822532, + -39654929, + 43952580, + -47397405, + 49615358, + -50153312, + 48430179, + -43632343, + 34478025, + -18631993, + -8995514, + 62632189, + -204301038, + 1819577413, + 527626477, + -276796278, + 198172545, + -155732115, + 126702130, + -104147133, + 85342903, + -69072344, + 54757023, + -42115701, + 31009674, + -21365269, + 13132355, + -6261556, + 692113, + 3653688, + -6871821, + 9074969, + -10389113, + 10948993, + -10893025, + 10358167, + -9475101, + 8364048, + -7131421, + 5867453, + -4644847, + 3518433, + -2525745, + 1688395, + -1014055, + 498877, + -130148, + -111018, + 247105, + -301891, + 298508, + -257939, + 197980, + -132653, + 44663, + -11742, + -65790, + 202662, + -412876, + 708054, + -1095574, + 1576595, + -2144104, + 2781152, + -3459432, + 4138376, + -4764909, + 5273997, + -5590070, + 5629354, + -5303103, + 4521635, + -3199055, + 1258444, + 1362701, + -4707074, + 8792492, + -13607426, + 19107391, + -25212372, + 31805359, + -38731928, + 45800568, + -52783069, + 59413677, + -65384437, + 70331439, + -73800022, + 75158695, + -73372729, + 66316974, + -48066112, + -9155468, + 1906322077, + 239693620, + -166299384, + 138823375, + -121458671, + 107559185, + -95102678, + 83367552, + -72114819, + 61313219, + -51025278, + 41351981, + -32402484, + 24276232, + -17052137, + 10782375, + -5489507, + 1166168, + 2223229, + -4739228, + 6462930, + -7490867, + 7929516, + -7889824, + 7482045, + -6811159, + 5973063, + -5051674, + 4117001, + -3224193, + 2413497, + -1711012, + 1130107, + -673307, + 334492, + -101212, + -43044, + 116746, + -138530, + 125750, + -93442 + +}; + +static const struct src_stage src_int32_8_7_4535_5000 = { + 6, 7, 8, 80, 640, 7, 8, 0, 0, + src_int32_8_7_4535_5000_fir}; diff --git a/src/audio/src/coef/src_small_int32_define.h b/src/audio/src/coef/src_small_int32_define.h new file mode 100644 index 000000000000..f8f82501fcae --- /dev/null +++ b/src/audio/src/coef/src_small_int32_define.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_SMALL_INT32_DEFINE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_SMALL_INT32_DEFINE_H__ + +/* SRC constants */ +#define MAX_FIR_DELAY_SIZE 452 +#define MAX_OUT_DELAY_SIZE 401 +#define MAX_BLK_IN 21 +#define MAX_BLK_OUT 21 +#define NUM_IN_FS 7 +#define NUM_OUT_FS 7 +#define STAGE1_TIMES_MAX 21 +#define STAGE2_TIMES_MAX 21 +#define STAGE_BUF_SIZE 168 +#define NUM_ALL_COEFFICIENTS 7536 + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_SMALL_INT32_DEFINE_H__ */ diff --git a/src/audio/src/coef/src_small_int32_table.h b/src/audio/src/coef/src_small_int32_table.h new file mode 100644 index 000000000000..33cb3ab82c2f --- /dev/null +++ b/src/audio/src/coef/src_small_int32_table.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_SMALL_INT32_TABLE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_SMALL_INT32_TABLE_H__ + +/* SRC conversions */ +#include "src_small_int32_1_2_2268_5000.h" +#include "src_small_int32_1_2_4535_5000.h" +#include "src_small_int32_1_3_2268_5000.h" +#include "src_small_int32_1_3_4535_5000.h" +#include "src_small_int32_2_1_2268_5000.h" +#include "src_small_int32_2_1_4535_5000.h" +#include "src_small_int32_2_3_4535_5000.h" +#include "src_small_int32_3_1_2268_5000.h" +#include "src_small_int32_3_1_4535_5000.h" +#include "src_small_int32_3_2_4535_5000.h" +#include "src_small_int32_3_4_4535_5000.h" +#include "src_small_int32_4_3_4535_5000.h" +#include "src_small_int32_4_5_4535_5000.h" +#include "src_small_int32_5_4_4535_5000.h" +#include "src_small_int32_5_6_4354_5000.h" +#include "src_small_int32_6_5_4354_5000.h" +#include "src_small_int32_7_8_4535_5000.h" +#include "src_small_int32_8_7_4535_5000.h" +#include "src_small_int32_20_21_4167_5000.h" +#include "src_small_int32_21_20_4167_5000.h" + +#include <stdint.h> + +/* SRC table */ +static const int32_t fir_one = 1073741824; +static const struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; +static const struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; +static const int src_in_fs[7] = { 8000, 16000, 24000, 32000, 44100, 48000, 50000}; +static const int src_out_fs[7] = { 8000, 16000, 24000, 32000, 44100, 48000, 50000}; +static const struct src_stage * const src_table1[7][7] = { + { &src_int32_1_1_0_0, &src_int32_1_2_4535_5000, + &src_int32_1_3_4535_5000, &src_int32_1_2_2268_5000, + &src_int32_0_0_0_0, &src_int32_1_3_2268_5000, + &src_int32_0_0_0_0}, + { &src_int32_2_1_4535_5000, + &src_int32_1_1_0_0, &src_int32_2_3_4535_5000, + &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, + &src_int32_1_3_4535_5000, &src_int32_0_0_0_0 + }, + { &src_int32_3_1_4535_5000, &src_int32_3_2_4535_5000, + &src_int32_1_1_0_0, &src_int32_3_4_4535_5000, + &src_int32_0_0_0_0, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0}, + { &src_int32_2_1_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_4_3_4535_5000, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_2_3_4535_5000, &src_int32_0_0_0_0 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_21_20_4167_5000, + &src_int32_0_0_0_0}, + { &src_int32_2_1_4535_5000, + &src_int32_3_1_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_3_2_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_1_1_0_0, &src_int32_6_5_4354_5000 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_5_4_4535_5000, + &src_int32_1_1_0_0} +}; + +static const struct src_stage * const src_table2[7][7] = { + { &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0}, + { &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0}, + { &src_int32_2_1_2268_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_7_8_4535_5000, + &src_int32_0_0_0_0}, + { &src_int32_3_1_2268_5000, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_20_21_4167_5000, + &src_int32_1_1_0_0, &src_int32_4_5_4535_5000 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_5_6_4354_5000, + &src_int32_1_1_0_0} +}; + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_SMALL_INT32_TABLE_H__ */ diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_10_21_4535_5000.h b/src/audio/src/coef/src_std_int32_10_21_4535_5000.h similarity index 99% rename from src/include/sof/audio/coefficients/src/src_std_int32_10_21_4535_5000.h rename to src/audio/src/coef/src_std_int32_10_21_4535_5000.h index 66476a0fde6a..1fe75ffcfc60 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_10_21_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_10_21_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_10_21_4535_5000_fir[1720] = { +__cold_rodata static const int32_t src_int32_10_21_4535_5000_fir[1720] = { 64820, 140936, -51986, @@ -1731,6 +1731,6 @@ const int32_t src_int32_10_21_4535_5000_fir[1720] = { }; -struct src_stage src_int32_10_21_4535_5000 = { +static const struct src_stage src_int32_10_21_4535_5000 = { 2, 1, 10, 172, 1720, 21, 10, 0, 1, src_int32_10_21_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_1_2_2268_5000.h b/src/audio/src/coef/src_std_int32_1_2_2268_5000.h similarity index 84% rename from src/include/sof/audio/coefficients/src/src_std_int32_1_2_2268_5000.h rename to src/audio/src/coef/src_std_int32_1_2_2268_5000.h index 84ad12ab1121..6da68b7325d3 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_1_2_2268_5000.h +++ b/src/audio/src/coef/src_std_int32_1_2_2268_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_1_2_2268_5000_fir[40] = { +__cold_rodata static const int32_t src_int32_1_2_2268_5000_fir[40] = { -102613, 1042618, 2316615, @@ -51,6 +51,6 @@ const int32_t src_int32_1_2_2268_5000_fir[40] = { }; -struct src_stage src_int32_1_2_2268_5000 = { +static const struct src_stage src_int32_1_2_2268_5000 = { 1, 0, 1, 40, 40, 2, 1, 0, 1, src_int32_1_2_2268_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_1_2_4535_5000.h b/src/audio/src/coef/src_std_int32_1_2_4535_5000.h similarity index 94% rename from src/include/sof/audio/coefficients/src/src_std_int32_1_2_4535_5000.h rename to src/audio/src/coef/src_std_int32_1_2_4535_5000.h index 2a0dab672b32..83fcad96732e 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_1_2_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_1_2_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_1_2_4535_5000_fir[200] = { +__cold_rodata static const int32_t src_int32_1_2_4535_5000_fir[200] = { -84357, 50235, 139225, @@ -211,6 +211,6 @@ const int32_t src_int32_1_2_4535_5000_fir[200] = { }; -struct src_stage src_int32_1_2_4535_5000 = { +static const struct src_stage src_int32_1_2_4535_5000 = { 1, 0, 1, 200, 200, 2, 1, 0, 1, src_int32_1_2_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_1_3_2268_5000.h b/src/audio/src/coef/src_std_int32_1_3_2268_5000.h similarity index 87% rename from src/include/sof/audio/coefficients/src/src_std_int32_1_3_2268_5000.h rename to src/audio/src/coef/src_std_int32_1_3_2268_5000.h index 8bfafbee4499..0119326d60d4 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_1_3_2268_5000.h +++ b/src/audio/src/coef/src_std_int32_1_3_2268_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_1_3_2268_5000_fir[56] = { +__cold_rodata static const int32_t src_int32_1_3_2268_5000_fir[56] = { 636662, 1367445, 1168433, @@ -67,6 +67,6 @@ const int32_t src_int32_1_3_2268_5000_fir[56] = { }; -struct src_stage src_int32_1_3_2268_5000 = { +static const struct src_stage src_int32_1_3_2268_5000 = { 1, 0, 1, 56, 56, 3, 1, 0, 2, src_int32_1_3_2268_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_1_3_4535_5000.h b/src/audio/src/coef/src_std_int32_1_3_4535_5000.h similarity index 95% rename from src/include/sof/audio/coefficients/src/src_std_int32_1_3_4535_5000.h rename to src/audio/src/coef/src_std_int32_1_3_4535_5000.h index a0976d42317c..4f432a4c48a6 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_1_3_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_1_3_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_1_3_4535_5000_fir[268] = { +__cold_rodata static const int32_t src_int32_1_3_4535_5000_fir[268] = { 53316, -3193, -78263, @@ -279,6 +279,6 @@ const int32_t src_int32_1_3_4535_5000_fir[268] = { }; -struct src_stage src_int32_1_3_4535_5000 = { +static const struct src_stage src_int32_1_3_4535_5000 = { 1, 0, 1, 268, 268, 3, 1, 0, 1, src_int32_1_3_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_20_21_4167_5000.h b/src/audio/src/coef/src_std_int32_20_21_4167_5000.h similarity index 98% rename from src/include/sof/audio/coefficients/src/src_std_int32_20_21_4167_5000.h rename to src/audio/src/coef/src_std_int32_20_21_4167_5000.h index 1f509a70f00e..a0dae03d0d09 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_20_21_4167_5000.h +++ b/src/audio/src/coef/src_std_int32_20_21_4167_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_20_21_4167_5000_fir[1120] = { +__cold_rodata static const int32_t src_int32_20_21_4167_5000_fir[1120] = { 125886, -321269, 574508, @@ -1131,6 +1131,6 @@ const int32_t src_int32_20_21_4167_5000_fir[1120] = { }; -struct src_stage src_int32_20_21_4167_5000 = { +static const struct src_stage src_int32_20_21_4167_5000 = { 1, 1, 20, 56, 1120, 21, 20, 0, 0, src_int32_20_21_4167_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_20_7_2976_5000.h b/src/audio/src/coef/src_std_int32_20_7_2976_5000.h similarity index 97% rename from src/include/sof/audio/coefficients/src/src_std_int32_20_7_2976_5000.h rename to src/audio/src/coef/src_std_int32_20_7_2976_5000.h index b2ff074f872b..85b8be57e692 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_20_7_2976_5000.h +++ b/src/audio/src/coef/src_std_int32_20_7_2976_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_20_7_2976_5000_fir[480] = { +__cold_rodata static const int32_t src_int32_20_7_2976_5000_fir[480] = { -256723, 1344746, -2486660, @@ -491,6 +491,6 @@ const int32_t src_int32_20_7_2976_5000_fir[480] = { }; -struct src_stage src_int32_20_7_2976_5000 = { +static const struct src_stage src_int32_20_7_2976_5000 = { 1, 3, 20, 24, 480, 7, 20, 0, 0, src_int32_20_7_2976_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_21_20_4167_5000.h b/src/audio/src/coef/src_std_int32_21_20_4167_5000.h similarity index 98% rename from src/include/sof/audio/coefficients/src/src_std_int32_21_20_4167_5000.h rename to src/audio/src/coef/src_std_int32_21_20_4167_5000.h index 38d6c22ce158..4f72a75d68a2 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_21_20_4167_5000.h +++ b/src/audio/src/coef/src_std_int32_21_20_4167_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_21_20_4167_5000_fir[1092] = { +__cold_rodata static const int32_t src_int32_21_20_4167_5000_fir[1092] = { -148365, 253251, -300044, @@ -1103,6 +1103,6 @@ const int32_t src_int32_21_20_4167_5000_fir[1092] = { }; -struct src_stage src_int32_21_20_4167_5000 = { +static const struct src_stage src_int32_21_20_4167_5000 = { 19, 20, 21, 52, 1092, 20, 21, 0, 0, src_int32_21_20_4167_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_21_40_3968_5000.h b/src/audio/src/coef/src_std_int32_21_40_3968_5000.h similarity index 99% rename from src/include/sof/audio/coefficients/src/src_std_int32_21_40_3968_5000.h rename to src/audio/src/coef/src_std_int32_21_40_3968_5000.h index 0abb3006c3e2..ac453af42104 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_21_40_3968_5000.h +++ b/src/audio/src/coef/src_std_int32_21_40_3968_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_21_40_3968_5000_fir[1596] = { +__cold_rodata static const int32_t src_int32_21_40_3968_5000_fir[1596] = { -210430, -287852, 472564, @@ -1607,6 +1607,6 @@ const int32_t src_int32_21_40_3968_5000_fir[1596] = { }; -struct src_stage src_int32_21_40_3968_5000 = { +static const struct src_stage src_int32_21_40_3968_5000 = { 19, 10, 21, 76, 1596, 40, 21, 0, 1, src_int32_21_40_3968_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_21_80_3968_5000.h b/src/audio/src/coef/src_std_int32_21_80_3968_5000.h similarity index 99% rename from src/include/sof/audio/coefficients/src/src_std_int32_21_80_3968_5000.h rename to src/audio/src/coef/src_std_int32_21_80_3968_5000.h index a88bee5d425a..d42d08134595 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_21_80_3968_5000.h +++ b/src/audio/src/coef/src_std_int32_21_80_3968_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_21_80_3968_5000_fir[3108] = { +__cold_rodata static const int32_t src_int32_21_80_3968_5000_fir[3108] = { -174020, 2072, 309190, @@ -3119,6 +3119,6 @@ const int32_t src_int32_21_80_3968_5000_fir[3108] = { }; -struct src_stage src_int32_21_80_3968_5000 = { +static const struct src_stage src_int32_21_80_3968_5000 = { 19, 5, 21, 148, 3108, 80, 21, 0, 2, src_int32_21_80_3968_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_2_1_2268_5000.h b/src/audio/src/coef/src_std_int32_2_1_2268_5000.h similarity index 84% rename from src/include/sof/audio/coefficients/src/src_std_int32_2_1_2268_5000.h rename to src/audio/src/coef/src_std_int32_2_1_2268_5000.h index 39a017edf2f1..f2fda6e7a712 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_2_1_2268_5000.h +++ b/src/audio/src/coef/src_std_int32_2_1_2268_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_2_1_2268_5000_fir[40] = { +__cold_rodata static const int32_t src_int32_2_1_2268_5000_fir[40] = { -96873, 2187025, -6715592, @@ -51,6 +51,6 @@ const int32_t src_int32_2_1_2268_5000_fir[40] = { }; -struct src_stage src_int32_2_1_2268_5000 = { +static const struct src_stage src_int32_2_1_2268_5000 = { 0, 1, 2, 20, 40, 1, 2, 0, 0, src_int32_2_1_2268_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_2_1_4535_5000.h b/src/audio/src/coef/src_std_int32_2_1_4535_5000.h similarity index 94% rename from src/include/sof/audio/coefficients/src/src_std_int32_2_1_4535_5000.h rename to src/audio/src/coef/src_std_int32_2_1_4535_5000.h index f3df8d078349..5ba7f5d860dd 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_2_1_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_2_1_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_2_1_4535_5000_fir[200] = { +__cold_rodata static const int32_t src_int32_2_1_4535_5000_fir[200] = { -79638, 131437, -197166, @@ -211,6 +211,6 @@ const int32_t src_int32_2_1_4535_5000_fir[200] = { }; -struct src_stage src_int32_2_1_4535_5000 = { +static const struct src_stage src_int32_2_1_4535_5000 = { 0, 1, 2, 100, 200, 1, 2, 0, 0, src_int32_2_1_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_2_3_4535_5000.h b/src/audio/src/coef/src_std_int32_2_3_4535_5000.h similarity index 96% rename from src/include/sof/audio/coefficients/src/src_std_int32_2_3_4535_5000.h rename to src/audio/src/coef/src_std_int32_2_3_4535_5000.h index 77aa6a6c8a07..1a5af78d38fe 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_2_3_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_2_3_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_2_3_4535_5000_fir[272] = { +__cold_rodata static const int32_t src_int32_2_3_4535_5000_fir[272] = { 12509, 72682, -101869, @@ -283,6 +283,6 @@ const int32_t src_int32_2_3_4535_5000_fir[272] = { }; -struct src_stage src_int32_2_3_4535_5000 = { +static const struct src_stage src_int32_2_3_4535_5000 = { 1, 1, 2, 136, 272, 3, 2, 0, 0, src_int32_2_3_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_32_21_4535_5000.h b/src/audio/src/coef/src_std_int32_32_21_4535_5000.h similarity index 99% rename from src/include/sof/audio/coefficients/src/src_std_int32_32_21_4535_5000.h rename to src/audio/src/coef/src_std_int32_32_21_4535_5000.h index a7e4908f2241..8bd7522a8320 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_32_21_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_32_21_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_32_21_4535_5000_fir[2816] = { +__cold_rodata static const int32_t src_int32_32_21_4535_5000_fir[2816] = { -70924, 93303, -103450, @@ -2827,6 +2827,6 @@ const int32_t src_int32_32_21_4535_5000_fir[2816] = { }; -struct src_stage src_int32_32_21_4535_5000 = { +static const struct src_stage src_int32_32_21_4535_5000 = { 19, 29, 32, 88, 2816, 21, 32, 0, 0, src_int32_32_21_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_3_1_2268_5000.h b/src/audio/src/coef/src_std_int32_3_1_2268_5000.h similarity index 87% rename from src/include/sof/audio/coefficients/src/src_std_int32_3_1_2268_5000.h rename to src/audio/src/coef/src_std_int32_3_1_2268_5000.h index 7535aa1dc8a9..34e0e2bd2253 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_3_1_2268_5000.h +++ b/src/audio/src/coef/src_std_int32_3_1_2268_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_3_1_2268_5000_fir[60] = { +__cold_rodata static const int32_t src_int32_3_1_2268_5000_fir[60] = { -166536, 2306339, -6050784, @@ -71,6 +71,6 @@ const int32_t src_int32_3_1_2268_5000_fir[60] = { }; -struct src_stage src_int32_3_1_2268_5000 = { +static const struct src_stage src_int32_3_1_2268_5000 = { 0, 1, 3, 20, 60, 1, 3, 0, 0, src_int32_3_1_2268_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_3_1_4535_5000.h b/src/audio/src/coef/src_std_int32_3_1_4535_5000.h similarity index 96% rename from src/include/sof/audio/coefficients/src/src_std_int32_3_1_4535_5000.h rename to src/audio/src/coef/src_std_int32_3_1_4535_5000.h index 0d9e0b7490c8..e212da23624b 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_3_1_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_3_1_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_3_1_4535_5000_fir[276] = { +__cold_rodata static const int32_t src_int32_3_1_4535_5000_fir[276] = { -92545, 140559, -191923, @@ -287,6 +287,6 @@ const int32_t src_int32_3_1_4535_5000_fir[276] = { }; -struct src_stage src_int32_3_1_4535_5000 = { +static const struct src_stage src_int32_3_1_4535_5000 = { 0, 1, 3, 92, 276, 1, 3, 0, 0, src_int32_3_1_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_3_2_4535_5000.h b/src/audio/src/coef/src_std_int32_3_2_4535_5000.h similarity index 96% rename from src/include/sof/audio/coefficients/src/src_std_int32_3_2_4535_5000.h rename to src/audio/src/coef/src_std_int32_3_2_4535_5000.h index 207e5d46ec53..69e7978b6af0 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_3_2_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_3_2_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_3_2_4535_5000_fir[276] = { +__cold_rodata static const int32_t src_int32_3_2_4535_5000_fir[276] = { -92545, 140559, -191923, @@ -287,6 +287,6 @@ const int32_t src_int32_3_2_4535_5000_fir[276] = { }; -struct src_stage src_int32_3_2_4535_5000 = { +static const struct src_stage src_int32_3_2_4535_5000 = { 1, 2, 3, 92, 276, 2, 3, 0, 0, src_int32_3_2_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_3_4_4535_5000.h b/src/audio/src/coef/src_std_int32_3_4_4535_5000.h similarity index 96% rename from src/include/sof/audio/coefficients/src/src_std_int32_3_4_4535_5000.h rename to src/audio/src/coef/src_std_int32_3_4_4535_5000.h index 1b095ea7d260..685fdfd7c706 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_3_4_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_3_4_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_3_4_4535_5000_fir[348] = { +__cold_rodata static const int32_t src_int32_3_4_4535_5000_fir[348] = { -44332, 116220, -109098, @@ -359,6 +359,6 @@ const int32_t src_int32_3_4_4535_5000_fir[348] = { }; -struct src_stage src_int32_3_4_4535_5000 = { +static const struct src_stage src_int32_3_4_4535_5000 = { 1, 1, 3, 116, 348, 4, 3, 0, 0, src_int32_3_4_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_40_21_3968_5000.h b/src/audio/src/coef/src_std_int32_40_21_3968_5000.h similarity index 99% rename from src/include/sof/audio/coefficients/src/src_std_int32_40_21_3968_5000.h rename to src/audio/src/coef/src_std_int32_40_21_3968_5000.h index 2226af00f136..46a7dbb012a1 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_40_21_3968_5000.h +++ b/src/audio/src/coef/src_std_int32_40_21_3968_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_40_21_3968_5000_fir[1600] = { +__cold_rodata static const int32_t src_int32_40_21_3968_5000_fir[1600] = { -168855, 272170, -146895, @@ -1611,6 +1611,6 @@ const int32_t src_int32_40_21_3968_5000_fir[1600] = { }; -struct src_stage src_int32_40_21_3968_5000 = { +static const struct src_stage src_int32_40_21_3968_5000 = { 11, 21, 40, 40, 1600, 21, 40, 0, 0, src_int32_40_21_3968_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_4_3_4535_5000.h b/src/audio/src/coef/src_std_int32_4_3_4535_5000.h similarity index 96% rename from src/include/sof/audio/coefficients/src/src_std_int32_4_3_4535_5000.h rename to src/audio/src/coef/src_std_int32_4_3_4535_5000.h index cda7ad86fcee..8476fccf5982 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_4_3_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_4_3_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_4_3_4535_5000_fir[352] = { +__cold_rodata static const int32_t src_int32_4_3_4535_5000_fir[352] = { -92406, 134596, -172955, @@ -363,6 +363,6 @@ const int32_t src_int32_4_3_4535_5000_fir[352] = { }; -struct src_stage src_int32_4_3_4535_5000 = { +static const struct src_stage src_int32_4_3_4535_5000 = { 2, 3, 4, 88, 352, 3, 4, 0, 0, src_int32_4_3_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_4_5_4535_5000.h b/src/audio/src/coef/src_std_int32_4_5_4535_5000.h similarity index 97% rename from src/include/sof/audio/coefficients/src/src_std_int32_4_5_4535_5000.h rename to src/audio/src/coef/src_std_int32_4_5_4535_5000.h index c1235f9b290e..148660ded07b 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_4_5_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_4_5_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_4_5_4535_5000_fir[448] = { +__cold_rodata static const int32_t src_int32_4_5_4535_5000_fir[448] = { 71197, -96779, 49471, @@ -459,6 +459,6 @@ const int32_t src_int32_4_5_4535_5000_fir[448] = { }; -struct src_stage src_int32_4_5_4535_5000 = { +static const struct src_stage src_int32_4_5_4535_5000 = { 1, 1, 4, 112, 448, 5, 4, 0, 0, src_int32_4_5_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_5_4_4535_5000.h b/src/audio/src/coef/src_std_int32_5_4_4535_5000.h similarity index 97% rename from src/include/sof/audio/coefficients/src/src_std_int32_5_4_4535_5000.h rename to src/audio/src/coef/src_std_int32_5_4_4535_5000.h index b431e207a7be..b3416487732b 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_5_4_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_5_4_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_5_4_4535_5000_fir[440] = { +__cold_rodata static const int32_t src_int32_5_4_4535_5000_fir[440] = { -83573, 123255, -160503, @@ -451,6 +451,6 @@ const int32_t src_int32_5_4_4535_5000_fir[440] = { }; -struct src_stage src_int32_5_4_4535_5000 = { +static const struct src_stage src_int32_5_4_4535_5000 = { 3, 4, 5, 88, 440, 4, 5, 0, 0, src_int32_5_4_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_5_6_4354_5000.h b/src/audio/src/coef/src_std_int32_5_6_4354_5000.h similarity index 97% rename from src/include/sof/audio/coefficients/src/src_std_int32_5_6_4354_5000.h rename to src/audio/src/coef/src_std_int32_5_6_4354_5000.h index afdb5e87ff4f..b861063c4671 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_5_6_4354_5000.h +++ b/src/audio/src/coef/src_std_int32_5_6_4354_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_5_6_4354_5000_fir[380] = { +__cold_rodata static const int32_t src_int32_5_6_4354_5000_fir[380] = { -110765, 202615, -181213, @@ -391,6 +391,6 @@ const int32_t src_int32_5_6_4354_5000_fir[380] = { }; -struct src_stage src_int32_5_6_4354_5000 = { +static const struct src_stage src_int32_5_6_4354_5000 = { 1, 1, 5, 76, 380, 6, 5, 0, 0, src_int32_5_6_4354_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_5_7_4535_5000.h b/src/audio/src/coef/src_std_int32_5_7_4535_5000.h similarity index 98% rename from src/include/sof/audio/coefficients/src/src_std_int32_5_7_4535_5000.h rename to src/audio/src/coef/src_std_int32_5_7_4535_5000.h index 0cd95a072d71..44cfdaf8cf42 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_5_7_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_5_7_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_5_7_4535_5000_fir[580] = { +__cold_rodata static const int32_t src_int32_5_7_4535_5000_fir[580] = { -38462, 102037, -72148, @@ -591,6 +591,6 @@ const int32_t src_int32_5_7_4535_5000_fir[580] = { }; -struct src_stage src_int32_5_7_4535_5000 = { +static const struct src_stage src_int32_5_7_4535_5000 = { 4, 3, 5, 116, 580, 7, 5, 0, 0, src_int32_5_7_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_6_5_4354_5000.h b/src/audio/src/coef/src_std_int32_6_5_4354_5000.h similarity index 97% rename from src/include/sof/audio/coefficients/src/src_std_int32_6_5_4354_5000.h rename to src/audio/src/coef/src_std_int32_6_5_4354_5000.h index 97dd8bb58b90..4d61ac9e77c1 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_6_5_4354_5000.h +++ b/src/audio/src/coef/src_std_int32_6_5_4354_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_6_5_4354_5000_fir[384] = { +__cold_rodata static const int32_t src_int32_6_5_4354_5000_fir[384] = { -122729, 196634, -249782, @@ -395,6 +395,6 @@ const int32_t src_int32_6_5_4354_5000_fir[384] = { }; -struct src_stage src_int32_6_5_4354_5000 = { +static const struct src_stage src_int32_6_5_4354_5000 = { 4, 5, 6, 64, 384, 5, 6, 0, 0, src_int32_6_5_4354_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_7_8_4535_5000.h b/src/audio/src/coef/src_std_int32_7_8_4535_5000.h similarity index 98% rename from src/include/sof/audio/coefficients/src/src_std_int32_7_8_4535_5000.h rename to src/audio/src/coef/src_std_int32_7_8_4535_5000.h index 5a062efbba8b..01f3b2b2325e 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_7_8_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_7_8_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_7_8_4535_5000_fir[644] = { +__cold_rodata static const int32_t src_int32_7_8_4535_5000_fir[644] = { -1007, -96094, 242640, @@ -655,6 +655,6 @@ const int32_t src_int32_7_8_4535_5000_fir[644] = { }; -struct src_stage src_int32_7_8_4535_5000 = { +static const struct src_stage src_int32_7_8_4535_5000 = { 1, 1, 7, 92, 644, 8, 7, 0, 0, src_int32_7_8_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_8_21_3239_5000.h b/src/audio/src/coef/src_std_int32_8_21_3239_5000.h similarity index 97% rename from src/include/sof/audio/coefficients/src/src_std_int32_8_21_3239_5000.h rename to src/audio/src/coef/src_std_int32_8_21_3239_5000.h index b004c13c2390..4441d148cc71 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_8_21_3239_5000.h +++ b/src/audio/src/coef/src_std_int32_8_21_3239_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_8_21_3239_5000_fir[480] = { +__cold_rodata static const int32_t src_int32_8_21_3239_5000_fir[480] = { -149226, 295321, 1071448, @@ -491,6 +491,6 @@ const int32_t src_int32_8_21_3239_5000_fir[480] = { }; -struct src_stage src_int32_8_21_3239_5000 = { +static const struct src_stage src_int32_8_21_3239_5000 = { 13, 5, 8, 60, 480, 21, 8, 0, 1, src_int32_8_21_3239_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_8_7_2468_5000.h b/src/audio/src/coef/src_std_int32_8_7_2468_5000.h similarity index 94% rename from src/include/sof/audio/coefficients/src/src_std_int32_8_7_2468_5000.h rename to src/audio/src/coef/src_std_int32_8_7_2468_5000.h index 47e251542b12..e4dcf0f08514 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_8_7_2468_5000.h +++ b/src/audio/src/coef/src_std_int32_8_7_2468_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_8_7_2468_5000_fir[160] = { +__cold_rodata static const int32_t src_int32_8_7_2468_5000_fir[160] = { -422312, 2368615, -2932237, @@ -171,6 +171,6 @@ const int32_t src_int32_8_7_2468_5000_fir[160] = { }; -struct src_stage src_int32_8_7_2468_5000 = { +static const struct src_stage src_int32_8_7_2468_5000 = { 6, 7, 8, 20, 160, 7, 8, 0, 0, src_int32_8_7_2468_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_8_7_4535_5000.h b/src/audio/src/coef/src_std_int32_8_7_4535_5000.h similarity index 98% rename from src/include/sof/audio/coefficients/src/src_std_int32_8_7_4535_5000.h rename to src/audio/src/coef/src_std_int32_8_7_4535_5000.h index 8a0d48af9a04..f6ddb96c7a0a 100644 --- a/src/include/sof/audio/coefficients/src/src_std_int32_8_7_4535_5000.h +++ b/src/audio/src/coef/src_std_int32_8_7_4535_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int32_t src_int32_8_7_4535_5000_fir[640] = { +__cold_rodata static const int32_t src_int32_8_7_4535_5000_fir[640] = { -93442, 125750, -138530, @@ -651,6 +651,6 @@ const int32_t src_int32_8_7_4535_5000_fir[640] = { }; -struct src_stage src_int32_8_7_4535_5000 = { +static const struct src_stage src_int32_8_7_4535_5000 = { 6, 7, 8, 80, 640, 7, 8, 0, 0, src_int32_8_7_4535_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_define.h b/src/audio/src/coef/src_std_int32_define.h similarity index 100% rename from src/include/sof/audio/coefficients/src/src_std_int32_define.h rename to src/audio/src/coef/src_std_int32_define.h diff --git a/src/audio/src/coef/src_std_int32_table.h b/src/audio/src/coef/src_std_int32_table.h new file mode 100644 index 000000000000..d0aa798b17e9 --- /dev/null +++ b/src/audio/src/coef/src_std_int32_table.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_STD_INT32_TABLE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_STD_INT32_TABLE_H__ + +/* SRC conversions */ +#include "src_std_int32_1_2_2268_5000.h" +#include "src_std_int32_1_2_4535_5000.h" +#include "src_std_int32_1_3_2268_5000.h" +#include "src_std_int32_1_3_4535_5000.h" +#include "src_std_int32_2_1_2268_5000.h" +#include "src_std_int32_2_1_4535_5000.h" +#include "src_std_int32_2_3_4535_5000.h" +#include "src_std_int32_3_1_2268_5000.h" +#include "src_std_int32_3_1_4535_5000.h" +#include "src_std_int32_3_2_4535_5000.h" +#include "src_std_int32_3_4_4535_5000.h" +#include "src_std_int32_4_3_4535_5000.h" +#include "src_std_int32_4_5_4535_5000.h" +#include "src_std_int32_5_4_4535_5000.h" +#include "src_std_int32_5_6_4354_5000.h" +#include "src_std_int32_5_7_4535_5000.h" +#include "src_std_int32_6_5_4354_5000.h" +#include "src_std_int32_7_8_4535_5000.h" +#include "src_std_int32_8_7_2468_5000.h" +#include "src_std_int32_8_7_4535_5000.h" +#include "src_std_int32_8_21_3239_5000.h" +#include "src_std_int32_10_21_4535_5000.h" +#include "src_std_int32_20_7_2976_5000.h" +#include "src_std_int32_20_21_4167_5000.h" +#include "src_std_int32_21_20_4167_5000.h" +#include "src_std_int32_21_40_3968_5000.h" +#include "src_std_int32_21_80_3968_5000.h" +#include "src_std_int32_32_21_4535_5000.h" +#include "src_std_int32_40_21_3968_5000.h" + +#include <stdint.h> + +/* SRC table */ +static const int32_t fir_one = 1073741824; +static const struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; +static const struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; +static const int src_in_fs[15] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 50000, 64000, 88200, 96000, 176400, 192000}; +static const int src_out_fs[10] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 50000}; +static const struct src_stage * const src_table1[10][15] = { + { &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_1_3_4535_5000, + &src_int32_1_2_2268_5000, &src_int32_0_0_0_0, + &src_int32_1_3_2268_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_21_80_3968_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_2_2268_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_2_3_4535_5000, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_1_3_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_21_40_3968_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_3_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_3_2_4535_5000, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_3_4_4535_5000, + &src_int32_0_0_0_0, &src_int32_1_2_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_2_1_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_2_1_4535_5000, + &src_int32_0_0_0_0, &src_int32_4_3_4535_5000, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_2_3_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_21_20_4167_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_2_1_4535_5000, &src_int32_32_21_4535_5000, + &src_int32_2_1_4535_5000, &src_int32_3_1_4535_5000, + &src_int32_8_7_4535_5000, &src_int32_2_1_4535_5000, + &src_int32_3_2_4535_5000, &src_int32_8_7_4535_5000, + &src_int32_1_1_0_0, &src_int32_6_5_4354_5000, + &src_int32_3_4_4535_5000, &src_int32_8_7_2468_5000, + &src_int32_1_2_4535_5000, &src_int32_8_21_3239_5000, + &src_int32_1_2_2268_5000}, + { &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_5_4_4535_5000, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + } +}; + +static const struct src_stage * const src_table2[10][15] = { + { &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, + &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_7_8_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_7_8_4535_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_2_1_2268_5000, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_0_0_0_0, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0}, + { &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_1_1_0_0, &src_int32_7_8_4535_5000, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + }, + { &src_int32_3_1_2268_5000, &src_int32_20_7_2976_5000, + &src_int32_2_1_2268_5000, &src_int32_1_1_0_0, + &src_int32_40_21_3968_5000, &src_int32_1_1_0_0, + &src_int32_1_1_0_0, &src_int32_20_21_4167_5000, + &src_int32_1_1_0_0, &src_int32_4_5_4535_5000, + &src_int32_1_1_0_0, &src_int32_10_21_4535_5000, + &src_int32_1_1_0_0, &src_int32_5_7_4535_5000, + &src_int32_1_2_4535_5000}, + { &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_5_6_4354_5000, + &src_int32_1_1_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0, + &src_int32_0_0_0_0, &src_int32_0_0_0_0 + } +}; + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_STD_INT32_TABLE_H__ */ diff --git a/src/audio/src/coef/src_tiny_int16_1_2_1814_5000.h b/src/audio/src/coef/src_tiny_int16_1_2_1814_5000.h new file mode 100644 index 000000000000..a8fde1f7561a --- /dev/null +++ b/src/audio/src/coef/src_tiny_int16_1_2_1814_5000.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int16_t src_int16_1_2_1814_5000_fir[32] = { + -7, + 7, + 63, + 87, + -62, + -341, + -351, + 274, + 1130, + 982, + -905, + -3147, + -2531, + 3124, + 12030, + 18851, + 18851, + 12030, + 3124, + -2531, + -3147, + -905, + 982, + 1130, + 274, + -351, + -341, + -62, + 87, + 63, + 7, + -7 + +}; + +static const struct src_stage src_int16_1_2_1814_5000 = { + 1, 0, 1, 32, 32, 2, 1, 0, 1, + src_int16_1_2_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_1_3_1814_5000.h b/src/audio/src/coef/src_tiny_int16_1_3_1814_5000.h similarity index 81% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_1_3_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_1_3_1814_5000.h index b98a3334b3e8..ef70aaa690d5 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_1_3_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_1_3_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_1_3_1814_5000_fir[48] = { +__cold_rodata static const int16_t src_int16_1_3_1814_5000_fir[48] = { -9, -7, 22, @@ -59,6 +59,6 @@ const int16_t src_int16_1_3_1814_5000_fir[48] = { }; -struct src_stage src_int16_1_3_1814_5000 = { +static const struct src_stage src_int16_1_3_1814_5000 = { 1, 0, 1, 48, 48, 3, 1, 0, 2, src_int16_1_3_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_1_6_1814_5000.h b/src/audio/src/coef/src_tiny_int16_1_6_1814_5000.h similarity index 87% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_1_6_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_1_6_1814_5000.h index 9a5a4eb7406e..672c44a75c27 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_1_6_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_1_6_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_1_6_1814_5000_fir[92] = { +__cold_rodata static const int16_t src_int16_1_6_1814_5000_fir[92] = { -4, 0, 10, @@ -103,6 +103,6 @@ const int16_t src_int16_1_6_1814_5000_fir[92] = { }; -struct src_stage src_int16_1_6_1814_5000 = { +static const struct src_stage src_int16_1_6_1814_5000 = { 1, 0, 1, 92, 92, 6, 1, 0, 3, src_int16_1_6_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_20_21_1667_5000.h b/src/audio/src/coef/src_tiny_int16_20_21_1667_5000.h similarity index 94% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_20_21_1667_5000.h rename to src/audio/src/coef/src_tiny_int16_20_21_1667_5000.h index 7c38826a6025..923612f9d120 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_20_21_1667_5000.h +++ b/src/audio/src/coef/src_tiny_int16_20_21_1667_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_20_21_1667_5000_fir[320] = { +__cold_rodata static const int16_t src_int16_20_21_1667_5000_fir[320] = { 3, 49, -174, @@ -331,6 +331,6 @@ const int16_t src_int16_20_21_1667_5000_fir[320] = { }; -struct src_stage src_int16_20_21_1667_5000 = { +static const struct src_stage src_int16_20_21_1667_5000 = { 1, 1, 20, 16, 320, 21, 20, 0, 0, src_int16_20_21_1667_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_21_20_1667_5000.h b/src/audio/src/coef/src_tiny_int16_21_20_1667_5000.h similarity index 94% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_21_20_1667_5000.h rename to src/audio/src/coef/src_tiny_int16_21_20_1667_5000.h index af44903679c8..21a83348dddc 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_21_20_1667_5000.h +++ b/src/audio/src/coef/src_tiny_int16_21_20_1667_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_21_20_1667_5000_fir[336] = { +__cold_rodata static const int16_t src_int16_21_20_1667_5000_fir[336] = { -4, 61, -87, @@ -347,6 +347,6 @@ const int16_t src_int16_21_20_1667_5000_fir[336] = { }; -struct src_stage src_int16_21_20_1667_5000 = { +static const struct src_stage src_int16_21_20_1667_5000 = { 19, 20, 21, 16, 336, 20, 21, 0, 0, src_int16_21_20_1667_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_24_25_1814_5000.h b/src/audio/src/coef/src_tiny_int16_24_25_1814_5000.h similarity index 96% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_24_25_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_24_25_1814_5000.h index c824621b077e..e68f37e9376c 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_24_25_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_24_25_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_24_25_1814_5000_fir[480] = { +__cold_rodata static const int16_t src_int16_24_25_1814_5000_fir[480] = { 5, -32, -12, @@ -491,6 +491,6 @@ const int16_t src_int16_24_25_1814_5000_fir[480] = { }; -struct src_stage src_int16_24_25_1814_5000 = { +static const struct src_stage src_int16_24_25_1814_5000 = { 1, 1, 24, 20, 480, 25, 24, 0, 0, src_int16_24_25_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_25_24_1814_5000.h b/src/audio/src/coef/src_tiny_int16_25_24_1814_5000.h similarity index 95% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_25_24_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_25_24_1814_5000.h index 33c7231697b4..fab00bf21661 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_25_24_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_25_24_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_25_24_1814_5000_fir[400] = { +__cold_rodata static const int16_t src_int16_25_24_1814_5000_fir[400] = { -6, 60, -44, @@ -411,6 +411,6 @@ const int16_t src_int16_25_24_1814_5000_fir[400] = { }; -struct src_stage src_int16_25_24_1814_5000 = { +static const struct src_stage src_int16_25_24_1814_5000 = { 23, 24, 25, 16, 400, 24, 25, 0, 0, src_int16_25_24_1814_5000_fir}; diff --git a/src/audio/src/coef/src_tiny_int16_2_1_1814_5000.h b/src/audio/src/coef/src_tiny_int16_2_1_1814_5000.h new file mode 100644 index 000000000000..79838f8bd89d --- /dev/null +++ b/src/audio/src/coef/src_tiny_int16_2_1_1814_5000.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + */ + +#include <stdint.h> + +__cold_rodata static const int16_t src_int16_2_1_1814_5000_fir[32] = { + -7, + 63, + -62, + -351, + 1130, + -905, + -2531, + 12030, + 18851, + 3124, + -3147, + 982, + 274, + -341, + 87, + 7, + 7, + 87, + -341, + 274, + 982, + -3147, + 3124, + 18851, + 12030, + -2531, + -905, + 1130, + -351, + -62, + 63, + -7 + +}; + +static const struct src_stage src_int16_2_1_1814_5000 = { + 0, 1, 2, 16, 32, 1, 2, 0, 0, + src_int16_2_1_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_2_3_1814_5000.h b/src/audio/src/coef/src_tiny_int16_2_3_1814_5000.h similarity index 81% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_2_3_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_2_3_1814_5000.h index 41ae8c78fb56..c38daaf5f46b 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_2_3_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_2_3_1814_5000.h @@ -7,21 +7,21 @@ #include <stdint.h> -const int16_t src_int16_2_3_1814_5000_fir[48] = { +__cold_rodata static const int16_t src_int16_2_3_1814_5000_fir[48] = { -9, 21, 126, -37, -520, -150, - 1392, + 1391, 1036, -2922, -3942, - 6035, + 6034, 21417, 25826, - 14052, + 14053, -409, -4467, -693, @@ -42,14 +42,14 @@ const int16_t src_int16_2_3_1814_5000_fir[48] = { -693, -4467, -409, - 14053, + 14052, 25826, 21417, - 6034, + 6035, -3942, -2922, 1036, - 1391, + 1392, -150, -520, -37, @@ -59,6 +59,6 @@ const int16_t src_int16_2_3_1814_5000_fir[48] = { }; -struct src_stage src_int16_2_3_1814_5000 = { +static const struct src_stage src_int16_2_3_1814_5000 = { 1, 1, 2, 24, 48, 3, 2, 0, 1, src_int16_2_3_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_3_1_1814_5000.h b/src/audio/src/coef/src_tiny_int16_3_1_1814_5000.h similarity index 81% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_3_1_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_3_1_1814_5000.h index e2f7b46be76f..abf1a6cd7126 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_3_1_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_3_1_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_3_1_1814_5000_fir[48] = { +__cold_rodata static const int16_t src_int16_3_1_1814_5000_fir[48] = { -7, 58, -28, @@ -59,6 +59,6 @@ const int16_t src_int16_3_1_1814_5000_fir[48] = { }; -struct src_stage src_int16_3_1_1814_5000 = { +static const struct src_stage src_int16_3_1_1814_5000 = { 0, 1, 3, 16, 48, 1, 3, 0, 0, src_int16_3_1_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_3_2_1814_5000.h b/src/audio/src/coef/src_tiny_int16_3_2_1814_5000.h similarity index 81% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_3_2_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_3_2_1814_5000.h index 58cfaf76b8d5..41bc4fd41cf7 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_3_2_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_3_2_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_3_2_1814_5000_fir[48] = { +__cold_rodata static const int16_t src_int16_3_2_1814_5000_fir[48] = { -6, 58, -28, @@ -59,6 +59,6 @@ const int16_t src_int16_3_2_1814_5000_fir[48] = { }; -struct src_stage src_int16_3_2_1814_5000 = { +static const struct src_stage src_int16_3_2_1814_5000 = { 1, 2, 3, 16, 48, 2, 3, 0, 0, src_int16_3_2_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_6_1_1814_5000.h b/src/audio/src/coef/src_tiny_int16_6_1_1814_5000.h similarity index 87% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_6_1_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_6_1_1814_5000.h index 777ea855c8f5..204c4b05c338 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_6_1_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_6_1_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_6_1_1814_5000_fir[96] = { +__cold_rodata static const int16_t src_int16_6_1_1814_5000_fir[96] = { -7, 53, -2, @@ -32,7 +32,7 @@ const int16_t src_int16_6_1_1814_5000_fir[96] = { -991, -2466, 12047, - 18754, + 18753, 3229, -3189, 954, @@ -47,7 +47,7 @@ const int16_t src_int16_6_1_1814_5000_fir[96] = { 1284, -1837, -1123, - 14805, + 14806, 17104, 799, -2613, @@ -64,7 +64,7 @@ const int16_t src_int16_6_1_1814_5000_fir[96] = { -2613, 799, 17104, - 14806, + 14805, -1123, -1837, 1284, @@ -79,7 +79,7 @@ const int16_t src_int16_6_1_1814_5000_fir[96] = { 954, -3189, 3229, - 18753, + 18754, 12047, -2466, -991, @@ -107,6 +107,6 @@ const int16_t src_int16_6_1_1814_5000_fir[96] = { }; -struct src_stage src_int16_6_1_1814_5000 = { +static const struct src_stage src_int16_6_1_1814_5000 = { 0, 1, 6, 16, 96, 1, 6, 0, 0, src_int16_6_1_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_7_8_1814_5000.h b/src/audio/src/coef/src_tiny_int16_7_8_1814_5000.h similarity index 90% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_7_8_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_7_8_1814_5000.h index 6a95ea17288e..9193c1005088 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_7_8_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_7_8_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_7_8_1814_5000_fir[140] = { +__cold_rodata static const int16_t src_int16_7_8_1814_5000_fir[140] = { -3, -28, 94, @@ -151,6 +151,6 @@ const int16_t src_int16_7_8_1814_5000_fir[140] = { }; -struct src_stage src_int16_7_8_1814_5000 = { +static const struct src_stage src_int16_7_8_1814_5000 = { 1, 1, 7, 20, 140, 8, 7, 0, 0, src_int16_7_8_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_8_7_1814_5000.h b/src/audio/src/coef/src_tiny_int16_8_7_1814_5000.h similarity index 89% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_8_7_1814_5000.h rename to src/audio/src/coef/src_tiny_int16_8_7_1814_5000.h index 42c2c9707492..c7d2c94d67dd 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_8_7_1814_5000.h +++ b/src/audio/src/coef/src_tiny_int16_8_7_1814_5000.h @@ -7,7 +7,7 @@ #include <stdint.h> -const int16_t src_int16_8_7_1814_5000_fir[128] = { +__cold_rodata static const int16_t src_int16_8_7_1814_5000_fir[128] = { -7, 55, -1, @@ -139,6 +139,6 @@ const int16_t src_int16_8_7_1814_5000_fir[128] = { }; -struct src_stage src_int16_8_7_1814_5000 = { +static const struct src_stage src_int16_8_7_1814_5000 = { 6, 7, 8, 16, 128, 7, 8, 0, 0, src_int16_8_7_1814_5000_fir}; diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_define.h b/src/audio/src/coef/src_tiny_int16_define.h similarity index 88% rename from src/include/sof/audio/coefficients/src/src_tiny_int16_define.h rename to src/audio/src/coef/src_tiny_int16_define.h index f3c95f238d17..d499f5ca02c8 100644 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_define.h +++ b/src/audio/src/coef/src_tiny_int16_define.h @@ -13,11 +13,11 @@ #define MAX_OUT_DELAY_SIZE 577 #define MAX_BLK_IN 25 #define MAX_BLK_OUT 25 -#define NUM_IN_FS 6 -#define NUM_OUT_FS 6 +#define NUM_IN_FS 7 +#define NUM_OUT_FS 7 #define STAGE1_TIMES_MAX 21 #define STAGE2_TIMES_MAX 25 #define STAGE_BUF_SIZE 168 -#define NUM_ALL_COEFFICIENTS 2184 +#define NUM_ALL_COEFFICIENTS 2248 #endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_DEFINE_H__ */ diff --git a/src/audio/src/coef/src_tiny_int16_table.h b/src/audio/src/coef/src_tiny_int16_table.h new file mode 100644 index 000000000000..6f51ccace53e --- /dev/null +++ b/src/audio/src/coef/src_tiny_int16_table.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_TABLE_H__ +#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_TABLE_H__ + +/* SRC conversions */ +#include "src_tiny_int16_1_2_1814_5000.h" +#include "src_tiny_int16_1_3_1814_5000.h" +#include "src_tiny_int16_1_6_1814_5000.h" +#include "src_tiny_int16_2_1_1814_5000.h" +#include "src_tiny_int16_2_3_1814_5000.h" +#include "src_tiny_int16_3_1_1814_5000.h" +#include "src_tiny_int16_3_2_1814_5000.h" +#include "src_tiny_int16_6_1_1814_5000.h" +#include "src_tiny_int16_7_8_1814_5000.h" +#include "src_tiny_int16_8_7_1814_5000.h" +#include "src_tiny_int16_20_21_1667_5000.h" +#include "src_tiny_int16_21_20_1667_5000.h" +#include "src_tiny_int16_24_25_1814_5000.h" +#include "src_tiny_int16_25_24_1814_5000.h" +#include <stdint.h> + +/* SRC table */ +static const int16_t fir_one = 16384; +static const struct src_stage src_int16_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; +static const struct src_stage src_int16_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; +static const int src_in_fs[7] = { 8000, 16000, 32000, 44100, 48000, 50000, 96000}; +static const int src_out_fs[7] = { 8000, 16000, 32000, 44100, 48000, 50000, 96000}; +static const struct src_stage * const src_table1[7][7] = { + { &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_6_1814_5000, &src_int16_0_0_0_0, + &src_int16_0_0_0_0}, + { &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_1_3_1814_5000, + &src_int16_0_0_0_0, &src_int16_0_0_0_0 + }, + { &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_2_3_1814_5000, &src_int16_0_0_0_0, + &src_int16_0_0_0_0}, + { &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_21_20_1667_5000, + &src_int16_0_0_0_0, &src_int16_0_0_0_0 + }, + { &src_int16_6_1_1814_5000, &src_int16_3_1_1814_5000, + &src_int16_3_2_1814_5000, &src_int16_8_7_1814_5000, + &src_int16_1_1_0_0, &src_int16_24_25_1814_5000, + &src_int16_1_2_1814_5000}, + { &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_25_24_1814_5000, + &src_int16_1_1_0_0, &src_int16_0_0_0_0 + }, + { &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_2_1_1814_5000, &src_int16_0_0_0_0, + &src_int16_1_1_0_0} +}; + +static const struct src_stage * const src_table2[7][7] = { + { &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0}, + { &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_1_1_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0 + }, + { &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0}, + { &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_7_8_1814_5000, + &src_int16_0_0_0_0, &src_int16_0_0_0_0 + }, + { &src_int16_1_1_0_0, &src_int16_1_1_0_0, + &src_int16_1_1_0_0, &src_int16_20_21_1667_5000, + &src_int16_1_1_0_0, &src_int16_1_1_0_0, + &src_int16_1_1_0_0}, + { &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_1_1_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0 + }, + { &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_0_0_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0, &src_int16_0_0_0_0, + &src_int16_1_1_0_0} +}; + +#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_TABLE_H__ */ diff --git a/src/audio/src/llext/CMakeLists.txt b/src/audio/src/llext/CMakeLists.txt new file mode 100644 index 000000000000..7cd52be725c7 --- /dev/null +++ b/src/audio/src/llext/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_COMP_SRC_LITE) +sof_llext_build("src" + SOURCES ../src_hifi2ep.c + ../src_generic.c + ../src_hifi3.c + ../src_hifi4.c + ../src_hifi5.c + ../src.c + ../src_common.c + ../src_ipc4.c + ../src_lite.c + LIB openmodules +) +else() +sof_llext_build("src" + SOURCES ../src_hifi2ep.c + ../src_generic.c + ../src_hifi3.c + ../src_hifi4.c + ../src_hifi5.c + ../src.c + ../src_common.c + ../src_ipc4.c + LIB openmodules +) +endif() diff --git a/src/audio/src/llext/llext.toml.h b/src/audio/src/llext/llext.toml.h new file mode 100644 index 000000000000..cfb334ca24e7 --- /dev/null +++ b/src/audio/src/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../src.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 7560d7ce6a0d..9870ad911ca8 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -1,941 +1,110 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2017 Intel Corporation. All rights reserved. +// Copyright(c) 2024 Intel Corporation. All rights reserved. // -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> +// Author: Tobiasz Dryjanski <tobiaszx.dryjanski@intel.com> -#include <sof/common.h> -#include <sof/audio/buffer.h> -#include <sof/audio/component.h> -#include <sof/audio/pipeline.h> -#include <sof/audio/src/src.h> -#include <sof/audio/src/src_config.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/math/numbers.h> -#include <sof/platform.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <ipc/control.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> +/* + * This file has been extracted from src_common.c (formerly src.c) + * to create separation between defines in different src types. + */ -#if SRC_SHORT -#include <sof/audio/coefficients/src/src_tiny_int16_define.h> -#include <sof/audio/coefficients/src/src_tiny_int16_table.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> +#include <module/module/llext.h> + +#include "src_common.h" +#include "src_config.h" + +#if SRC_SHORT || CONFIG_COMP_SRC_TINY +#include "coef/src_tiny_int16_define.h" +#include "coef/src_tiny_int16_table.h" +#elif CONFIG_COMP_SRC_SMALL +#include "coef/src_small_int32_define.h" +#include "coef/src_small_int32_table.h" +#elif CONFIG_COMP_SRC_STD +#include "coef/src_std_int32_define.h" +#include "coef/src_std_int32_table.h" +#elif CONFIG_COMP_SRC_IPC4_FULL_MATRIX +#include "coef/src_ipc4_int32_define.h" +#include "coef/src_ipc4_int32_table.h" #else -#include <sof/audio/coefficients/src/src_std_int32_define.h> -#include <sof/audio/coefficients/src/src_std_int32_table.h> +#error "No valid configuration selected for SRC" #endif -/* The FIR maximum lengths are per channel so need to multiply them */ -#define MAX_FIR_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE) -#define MAX_OUT_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE) - -static const struct comp_driver comp_src; - -/* c1c5326d-8390-46b4-aa47-95c3beca6550 */ -DECLARE_SOF_UUID("src", src_uuid, 0xc1c5326d, 0x8390, 0x46b4, - 0xaa, 0x47, 0x95, 0xc3, 0xbe, 0xca, 0x65, 0x50); - -/* src component private data */ -struct comp_data { - struct polyphase_src src; - struct src_param param; - int32_t *delay_lines; - uint32_t sink_rate; - uint32_t source_rate; - uint32_t sink_format; - uint32_t source_format; - int32_t *sbuf_w_ptr; - int32_t *sbuf_r_ptr; - int sbuf_avail; - int data_shift; - int source_frames; - int sink_frames; - int sample_container_bytes; - void (*src_func)(struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - int *consumed, - int *produced); - void (*polyphase_func)(struct src_stage_prm *s); -}; - -/* Calculates the needed FIR delay line length */ -static int src_fir_delay_length(struct src_stage *s) -{ - return s->subfilter_length + (s->num_of_subfilters - 1) * s->idm - + s->blk_in; -} - -/* Calculates the FIR output delay line length */ -static int src_out_delay_length(struct src_stage *s) -{ - return 1 + (s->num_of_subfilters - 1) * s->odm; -} - -/* Returns index of a matching sample rate */ -static int src_find_fs(int fs_list[], int list_length, int fs) -{ - int i; - - for (i = 0; i < list_length; i++) { - if (fs_list[i] == fs) - return i; - } - return -EINVAL; -} - -/* Calculates buffers to allocate for a SRC mode */ -int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, - int source_frames) -{ - struct src_stage *stage1; - struct src_stage *stage2; - int r1; - - if (nch > PLATFORM_MAX_CHANNELS) { - /* TODO: should be device, not class */ - comp_cl_err(&comp_src, "src_buffer_lengths() error: nch = %u > PLATFORM_MAX_CHANNELS", - nch); - return -EINVAL; - } - - a->nch = nch; - a->idx_in = src_find_fs(src_in_fs, NUM_IN_FS, fs_in); - a->idx_out = src_find_fs(src_out_fs, NUM_OUT_FS, fs_out); - - /* Check that both in and out rates are supported */ - if (a->idx_in < 0 || a->idx_out < 0) { - comp_cl_err(&comp_src, "src_buffer_lengths() error: rates not supported, fs_in: %u, fs_out: %u", - fs_in, fs_out); - return -EINVAL; - } - - stage1 = src_table1[a->idx_out][a->idx_in]; - stage2 = src_table2[a->idx_out][a->idx_in]; - - /* Check from stage1 parameter for a deleted in/out rate combination.*/ - if (stage1->filter_length < 1) { - comp_cl_err(&comp_src, "src_buffer_lengths() error: Non-supported combination sfs_in = %d, fs_out = %d", - fs_in, fs_out); - return -EINVAL; - } - - a->fir_s1 = nch * src_fir_delay_length(stage1); - a->out_s1 = nch * src_out_delay_length(stage1); - - /* Computing of number of blocks to process is done in - * copy() per each frame. - */ - a->stage1_times = 0; - a->stage2_times = 0; - a->blk_in = 0; - a->blk_out = 0; - - if (stage2->filter_length == 1) { - a->fir_s2 = 0; - a->out_s2 = 0; - a->sbuf_length = 0; - } else { - a->fir_s2 = nch * src_fir_delay_length(stage2); - a->out_s2 = nch * src_out_delay_length(stage2); - - /* Stage 1 is repeated max. amount that just exceeds one - * period. - */ - r1 = source_frames / stage1->blk_in + 1; - - /* Set sbuf length to allow storing two stage 1 output - * periods. This is an empirically found value for no - * xruns to happen with SRC in/out buffers. Due to - * variable number of blocks to process per each stage - * there is no equation known for minimum size. - */ - a->sbuf_length = 2 * nch * stage1->blk_out * r1; - } - - a->src_multich = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2; - a->total = a->sbuf_length + a->src_multich; - - return 0; -} - -static void src_state_reset(struct src_state *state) -{ - state->fir_delay_size = 0; - state->out_delay_size = 0; -} - -static int init_stages(struct src_stage *stage1, struct src_stage *stage2, - struct polyphase_src *src, struct src_param *p, - int n, int32_t *delay_lines_start) -{ - /* Clear FIR state */ - src_state_reset(&src->state1); - src_state_reset(&src->state2); - - src->number_of_stages = n; - src->stage1 = stage1; - src->stage2 = stage2; - if (n == 1 && stage1->blk_out == 0) - return -EINVAL; - - /* Optimized SRC requires subfilter length multiple of 4 */ - if (stage1->filter_length > 1 && (stage1->subfilter_length & 0x3) > 0) - return -EINVAL; - - if (stage2->filter_length > 1 && (stage2->subfilter_length & 0x3) > 0) - return -EINVAL; - - /* Delay line sizes */ - src->state1.fir_delay_size = p->fir_s1; - src->state1.out_delay_size = p->out_s1; - src->state1.fir_delay = delay_lines_start; - src->state1.out_delay = - src->state1.fir_delay + src->state1.fir_delay_size; - /* Initialize to last ensures that circular wrap cannot happen - * mid-frame. The size is multiple of channels count. - */ - src->state1.fir_wp = &src->state1.fir_delay[p->fir_s1 - 1]; - src->state1.out_rp = src->state1.out_delay; - if (n > 1) { - src->state2.fir_delay_size = p->fir_s2; - src->state2.out_delay_size = p->out_s2; - src->state2.fir_delay = - src->state1.out_delay + src->state1.out_delay_size; - src->state2.out_delay = - src->state2.fir_delay + src->state2.fir_delay_size; - /* Initialize to last ensures that circular wrap cannot happen - * mid-frame. The size is multiple of channels count. - */ - src->state2.fir_wp = &src->state2.fir_delay[p->fir_s2 - 1]; - src->state2.out_rp = src->state2.out_delay; - } else { - src->state2.fir_delay_size = 0; - src->state2.out_delay_size = 0; - src->state2.fir_delay = NULL; - src->state2.out_delay = NULL; - } +LOG_MODULE_DECLARE(src, CONFIG_SOF_LOG_LEVEL); - /* Check the sizes are less than MAX */ - if (src->state1.fir_delay_size > MAX_FIR_DELAY_SIZE_XNCH || - src->state1.out_delay_size > MAX_OUT_DELAY_SIZE_XNCH || - src->state2.fir_delay_size > MAX_FIR_DELAY_SIZE_XNCH || - src->state2.out_delay_size > MAX_OUT_DELAY_SIZE_XNCH) { - src->state1.fir_delay = NULL; - src->state1.out_delay = NULL; - src->state2.fir_delay = NULL; - src->state2.out_delay = NULL; - return -EINVAL; - } - - return 0; -} - -void src_polyphase_reset(struct polyphase_src *src) +static int src_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - src->number_of_stages = 0; - src->stage1 = NULL; - src->stage2 = NULL; - src_state_reset(&src->state1); - src_state_reset(&src->state2); -} - -int src_polyphase_init(struct polyphase_src *src, struct src_param *p, - int32_t *delay_lines_start) -{ - struct src_stage *stage1; - struct src_stage *stage2; - int n_stages; + struct comp_data *cd = module_get_private_data(mod); + struct src_param *a = &cd->param; int ret; - if (p->idx_in < 0 || p->idx_out < 0) - return -EINVAL; + comp_info(mod->dev, "entry"); - /* Get setup for 2 stage conversion */ - stage1 = src_table1[p->idx_out][p->idx_in]; - stage2 = src_table2[p->idx_out][p->idx_in]; - ret = init_stages(stage1, stage2, src, p, 2, delay_lines_start); - if (ret < 0) + if (num_of_sources != 1 || num_of_sinks != 1) return -EINVAL; - /* Get number of stages used for optimize opportunity. 2nd - * stage length is one if conversion needs only one stage. - * If input and output rate is the same return 0 to - * use a simple copy function instead of 1 stage FIR with one - * tap. - */ - n_stages = (src->stage2->filter_length == 1) ? 1 : 2; - if (p->idx_in == p->idx_out) - n_stages = 0; - - /* If filter length for first stage is zero this is a deleted - * mode from in/out matrix. Computing of such SRC mode needs - * to be prevented. - */ - if (src->stage1->filter_length == 0) - return -EINVAL; - - return n_stages; -} - -/* Fallback function */ -static void src_fallback(struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, int *n_read, int *n_written) -{ - *n_read = 0; - *n_written = 0; -} - -/* Normal 2 stage SRC */ -static void src_2s(struct comp_dev *dev, const struct audio_stream *source, - struct audio_stream *sink, int *n_read, int *n_written) -{ - struct src_stage_prm s1; - struct src_stage_prm s2; - int s1_blk_in; - int s1_blk_out; - int s2_blk_in; - int s2_blk_out; - struct comp_data *cd = comp_get_drvdata(dev); - 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 sbuf_free = cd->param.sbuf_length - cd->sbuf_avail; - int avail_b = source->avail; - int free_b = sink->free; - int sz = cd->sample_container_bytes; - - *n_read = 0; - *n_written = 0; - s1.x_end_addr = source->end_addr; - s1.x_size = source->size; - 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.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.state = &cd->src.state2; - s2.stage = cd->src.stage2; - s2.x_rptr = cd->sbuf_r_ptr; - s2.y_wptr = sink->w_ptr; - s2.nch = nch; - s2.shift = cd->data_shift; - - /* Test if 1st stage can be run with default block length to reach - * the period length or just under it. - */ - s1.times = cd->param.stage1_times; - s1_blk_in = s1.times * cd->src.stage1->blk_in * nch; - s1_blk_out = s1.times * cd->src.stage1->blk_out * nch; - - /* The sbuf may limit how many times s1 can be looped. It's harder - * to prepare for in advance so the repeats number is adjusted down - * here if need. - */ - if (s1_blk_out > sbuf_free) { - s1.times = sbuf_free / (cd->src.stage1->blk_out * nch); - s1_blk_in = s1.times * cd->src.stage1->blk_in * nch; - s1_blk_out = s1.times * cd->src.stage1->blk_out * nch; - comp_dbg(dev, "s1.times = %d", s1.times); - } - - if (avail_b >= s1_blk_in * sz && sbuf_free >= s1_blk_out) { - cd->polyphase_func(&s1); - - cd->sbuf_w_ptr = s1.y_wptr; - cd->sbuf_avail += s1_blk_out; - *n_read += s1.times * cd->src.stage1->blk_in; - } - - s2.times = cd->param.stage2_times; - s2_blk_in = s2.times * cd->src.stage2->blk_in * nch; - s2_blk_out = s2.times * cd->src.stage2->blk_out * nch; - if (s2_blk_in > cd->sbuf_avail) { - s2.times = cd->sbuf_avail / (cd->src.stage2->blk_in * nch); - s2_blk_in = s2.times * cd->src.stage2->blk_in * nch; - s2_blk_out = s2.times * cd->src.stage2->blk_out * nch; - comp_dbg(dev, "s2.times = %d", s2.times); - } - - /* Test if second stage can be run with default block length. */ - if (cd->sbuf_avail >= s2_blk_in && free_b >= s2_blk_out * sz) { - cd->polyphase_func(&s2); - - cd->sbuf_r_ptr = s2.x_rptr; - cd->sbuf_avail -= s2_blk_in; - *n_written += s2.times * cd->src.stage2->blk_out; - } -} - -/* 1 stage SRC for simple conversions */ -static void src_1s(struct comp_dev *dev, const struct audio_stream *source, - struct audio_stream *sink, int *n_read, int *n_written) -{ - struct src_stage_prm s1; - struct comp_data *cd = comp_get_drvdata(dev); - - 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.state = &cd->src.state1; - s1.stage = cd->src.stage1; - s1.nch = source->channels; - s1.shift = cd->data_shift; - - cd->polyphase_func(&s1); - - *n_read = cd->param.blk_in; - *n_written = cd->param.blk_out; -} - -/* A fast copy function for same in and out rate */ -static void src_copy_s32(struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - int *n_read, int *n_written) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int frames = cd->param.blk_in; - - audio_stream_copy_s32(source, 0, sink, 0, frames * source->channels); - - *n_read = frames; - *n_written = frames; -} - -#if CONFIG_FORMAT_S16LE -static void src_copy_s16(struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - int *n_read, int *n_written) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int frames = cd->param.blk_in; - - audio_stream_copy_s16(source, 0, sink, 0, frames * source->channels); - - *n_read = frames; - *n_written = frames; -} -#endif /* CONFIG_FORMAT_S16LE */ - -static struct comp_dev *src_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct comp_dev *dev; - struct sof_ipc_comp_src *src; - struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *)comp; - struct comp_data *cd; - int ret; - - comp_cl_info(&comp_src, "src_new()"); - - /* validate init data - either SRC sink or source rate must be set */ - if (ipc_src->source_rate == 0 && ipc_src->sink_rate == 0) { - comp_cl_err(&comp_src, "src_new() error: SRC sink and source rate are not set"); - return NULL; - } - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_src)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_src); - - src = COMP_GET_IPC(dev, sof_ipc_comp_src); - - ret = memcpy_s(src, sizeof(*src), ipc_src, - sizeof(struct sof_ipc_comp_src)); - assert(!ret); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); - - 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()"); + a->in_fs = src_in_fs; + a->out_fs = src_out_fs; + a->num_in_fs = NUM_IN_FS; + a->num_out_fs = NUM_OUT_FS; + a->max_fir_delay_size_xnch = (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE); + a->max_out_delay_size_xnch = (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE); - /* Free dynamically reserved buffers for SRC algorithm */ - if (cd->delay_lines) - rfree(cd->delay_lines); + src_get_source_sink_params(mod->dev, sources[0], sinks[0]); - rfree(cd); - rfree(dev); -} - -static int src_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct sof_ipc_comp_src *src = COMP_GET_IPC(dev, sof_ipc_comp_src); - int ret; - - comp_dbg(dev, "src_verify_params()"); - - /* check whether params->rate (received from driver) are equal - * to src->source_rate (PLAYBACK) or src->sink_rate (CAPTURE) set during - * creating src component in src_new(). - * src->source/sink_rate = 0 means that source/sink rate can vary. - */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - if (src->source_rate && (params->rate != src->source_rate)) { - comp_err(dev, "src_verify_params(): error: runtime stream pcm rate does not match rate fetched from ipc."); - return -EINVAL; - } - } else { - if (src->sink_rate && (params->rate != src->sink_rate)) { - comp_err(dev, "src_verify_params(): error: runtime stream pcm rate does not match rate fetched from ipc."); - return -EINVAL; - } - } - - /* update downstream (playback) or upstream (capture) buffer parameters - */ - ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); - if (ret < 0) { - comp_err(dev, "src_verify_params() error: comp_verify_params() failed."); + ret = src_param_set(mod->dev, cd); + if (ret < 0) return ret; - } - - return 0; -} - -/* set component audio stream parameters */ -static int src_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct sof_ipc_comp_src *src = COMP_GET_IPC(dev, sof_ipc_comp_src); - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sinkb; - struct comp_buffer *sourceb; - size_t delay_lines_size; - int32_t *buffer_start; - int n = 0; - int err; - - comp_info(dev, "src_params()"); - - err = src_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "src_params(): pcm params verification failed."); - return -EINVAL; - } - - cd->sample_container_bytes = params->sample_container_bytes; - - /* 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); - - comp_info(dev, "src_params(): src->source_rate: %d", src->source_rate); - comp_info(dev, "src_params(): src->sink_rate: %d", src->sink_rate); - - /* Set source/sink_rate/frames */ - cd->source_rate = sourceb->stream.rate; - cd->sink_rate = sinkb->stream.rate; - - cd->source_frames = dev->frames * cd->source_rate / cd->sink_rate; - cd->sink_frames = dev->frames; - - /* Allocate needed memory for delay lines */ - comp_info(dev, "src_params(), source_rate = %u, sink_rate = %u", - cd->source_rate, cd->sink_rate); - comp_info(dev, "src_params(), sourceb->channels = %u, sinkb->channels = %u, dev->frames = %u", - sourceb->stream.channels, - sinkb->stream.channels, dev->frames); - err = src_buffer_lengths(&cd->param, cd->source_rate, - cd->sink_rate, - sourceb->stream.channels, cd->source_frames); - if (err < 0) { - comp_err(dev, "src_params() error: src_buffer_lengths() failed"); - return err; - } - - comp_info(dev, "src_params(), blk_in = %u, blk_out = %u", - cd->param.blk_in, cd->param.blk_out); - delay_lines_size = sizeof(int32_t) * cd->param.total; - if (delay_lines_size == 0) { - comp_err(dev, "src_params() error: delay_lines_size = 0"); - return -EINVAL; - } - - /* free any existing delay lines. TODO reuse if same size */ - if (cd->delay_lines) - rfree(cd->delay_lines); - - cd->delay_lines = rballoc(0, SOF_MEM_CAPS_RAM, delay_lines_size); - if (!cd->delay_lines) { - comp_err(dev, "src_params() error: failed to alloc cd->delay_lines, delay_lines_size = %u", - delay_lines_size); - return -EINVAL; - } - - /* Clear all delay lines here */ - memset(cd->delay_lines, 0, delay_lines_size); - buffer_start = cd->delay_lines + cd->param.sbuf_length; - - /* Initialize SRC for actual sample rate */ - n = src_polyphase_init(&cd->src, &cd->param, buffer_start); - - /* Reset stage buffer */ - cd->sbuf_r_ptr = cd->delay_lines; - cd->sbuf_w_ptr = cd->delay_lines; - cd->sbuf_avail = 0; - - switch (n) { - case 0: - /* 1:1 fast copy */ - cd->src_func = src_copy_s32; - break; - case 1: - cd->src_func = src_1s; /* Simpler 1 stage SRC */ - break; - case 2: - cd->src_func = src_2s; /* Default 2 stage SRC */ - break; - default: - /* This is possibly due to missing coefficients for - * requested rates combination. - */ - comp_info(dev, "src_params(), missing coefficients for requested rates combination"); - cd->src_func = src_fallback; - return -EINVAL; - } - - return 0; -} - -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 = data; - 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) - assert(cd->polyphase_func); - - return comp_set_state(dev, cmd); -} - -static int src_get_copy_limits(struct comp_data *cd, - const struct comp_buffer *source, - const struct comp_buffer *sink) -{ - struct src_param *sp; - struct src_stage *s1; - struct src_stage *s2; - int frames_src; - int frames_snk; - - /* Get SRC parameters */ - sp = &cd->param; - s1 = cd->src.stage1; - s2 = cd->src.stage2; - - /* Calculate how many blocks can be processed with - * available source and free sink frames amount. - */ - if (s2->filter_length > 1) { - /* Two polyphase filters case */ - frames_snk = sink->stream.free / - audio_stream_frame_bytes(&sink->stream); - frames_snk = MIN(frames_snk, cd->sink_frames + s2->blk_out); - sp->stage2_times = frames_snk / s2->blk_out; - frames_src = source->stream.avail / - audio_stream_frame_bytes(&source->stream); - frames_src = MIN(frames_src, cd->source_frames + s1->blk_in); - sp->stage1_times = frames_src / s1->blk_in; - sp->blk_in = sp->stage1_times * s1->blk_in; - sp->blk_out = sp->stage2_times * s2->blk_out; - } else { - /* Single polyphase filter case */ - frames_snk = sink->stream.free / - audio_stream_frame_bytes(&sink->stream); - frames_snk = MIN(frames_snk, cd->sink_frames + s1->blk_out); - sp->stage1_times = frames_snk / s1->blk_out; - frames_src = source->stream.avail / - audio_stream_frame_bytes(&source->stream); - frames_snk = MIN(frames_src, cd->source_frames + s1->blk_in); - sp->stage1_times = MIN(sp->stage1_times, - frames_src / s1->blk_in); - sp->blk_in = sp->stage1_times * s1->blk_in; - sp->blk_out = sp->stage1_times * s1->blk_out; - } - - if (sp->blk_in == 0 || sp->blk_out == 0) - return -EIO; - - return 0; -} - -static void src_process(struct comp_dev *dev, struct comp_buffer *source, - struct comp_buffer *sink) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int consumed = 0; - int produced = 0; - - /* consumed bytes are not known at this point */ - buffer_invalidate(source, source->stream.size); - cd->src_func(dev, &source->stream, &sink->stream, &consumed, &produced); - buffer_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; - struct comp_buffer *sink; - int ret; - uint32_t flags = 0; - - 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); - - buffer_lock(source, &flags); - buffer_lock(sink, &flags); - - /* 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, sink); - - buffer_unlock(sink, flags); - buffer_unlock(source, flags); - - if (ret) { - comp_info(dev, "No data to process."); - return PPL_STATUS_PATH_STOP; - } - - src_process(dev, source, sink); - - /* produced no data */ - return 0; -} - -static int src_prepare(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *sinkb; - struct comp_buffer *sourceb; - uint32_t source_period_bytes; - uint32_t sink_period_bytes; - int ret; - - comp_info(dev, "src_prepare()"); - - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + ret = src_allocate_copy_stages(mod, a, + src_table1[a->idx_out][a->idx_in], + src_table2[a->idx_out][a->idx_in]); if (ret < 0) return ret; - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - - /* SRC component 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); - - /* get source data format and period bytes */ - cd->source_format = sourceb->stream.frame_fmt; - source_period_bytes = audio_stream_period_bytes(&sourceb->stream, - dev->frames); - - /* get sink data format and period bytes */ - cd->sink_format = sinkb->stream.frame_fmt; - sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, - dev->frames); - - if (sinkb->stream.size < config->periods_sink * sink_period_bytes) { - comp_err(dev, "src_prepare() error: sink buffer size is insufficient"); - ret = -ENOMEM; - goto err; - } - - /* validate */ - if (!sink_period_bytes) { - comp_err(dev, "src_prepare() error: sink_period_bytes = 0"); - ret = -EINVAL; - goto err; - } - if (!source_period_bytes) { - comp_err(dev, "src_prepare() error: source_period_bytes = 0"); - ret = -EINVAL; - goto err; - } - - /* SRC supports S16_LE, S24_4LE and S32_LE formats */ - if (cd->source_format != cd->sink_format) { - comp_err(dev, "src_prepare() error: Source fmt %d and sink fmt %d are different.", - cd->source_format, cd->sink_format); - ret = -EINVAL; - goto err; - } - - switch (cd->source_format) { -#if CONFIG_FORMAT_S16LE - case SOF_IPC_FRAME_S16_LE: - cd->data_shift = 0; - cd->polyphase_func = src_polyphase_stage_cir_s16; - /* Copy function is set by default in params() for 32 bit - * data. Change it to 16 bit version here if source and sink - * rates are equal. - */ - if (cd->source_rate == cd->sink_rate) - cd->src_func = src_copy_s16; - break; -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - case SOF_IPC_FRAME_S24_4LE: - cd->data_shift = 8; - cd->polyphase_func = src_polyphase_stage_cir; - break; -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - case SOF_IPC_FRAME_S32_LE: - cd->data_shift = 0; - cd->polyphase_func = src_polyphase_stage_cir; - break; -#endif /* CONFIG_FORMAT_S32LE */ - default: - comp_err(dev, "src_prepare() error: invalid format %d", - cd->source_format); - ret = -EINVAL; - goto err; - } - - return 0; + ret = src_params_general(mod, sources[0], sinks[0]); + if (ret < 0) + return ret; -err: - comp_set_state(dev, COMP_TRIGGER_RESET); - return ret; + return src_prepare_general(mod, sources[0], sinks[0]); } -static int src_reset(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); +static const struct module_interface src_interface = { + .init = src_init, + .prepare = src_prepare, + .process = src_process, + .is_ready_to_process = src_is_ready_to_process, + .reset = src_reset, + .free = src_free, +}; - comp_info(dev, "src_reset()"); +#if CONFIG_COMP_SRC_MODULE +/* modular: llext dynamic link */ - cd->src_func = src_fallback; - src_polyphase_reset(&cd->src); +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> - comp_set_state(dev, COMP_TRIGGER_RESET); - return 0; -} +#if CONFIG_COMP_SRC_LITE +extern const struct module_interface src_lite_interface; +#endif -static const struct comp_driver comp_src = { - .type = SOF_COMP_SRC, - .uid = SOF_UUID(src_uuid), - .ops = { - .new = src_new, - .free = src_free, - .params = src_params, - .cmd = src_cmd, - .trigger = src_trigger, - .copy = src_copy, - .prepare = src_prepare, - .reset = src_reset, - }, +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { + SOF_LLEXT_MODULE_MANIFEST("SRC", &src_interface, 1, SOF_REG_UUID(src4), 1), +#if CONFIG_COMP_SRC_LITE + SOF_LLEXT_MODULE_MANIFEST("SRC_LITE", &src_lite_interface, 1, SOF_REG_UUID(src_lite), 1), +#endif }; -static SHARED_DATA struct comp_driver_info comp_src_info = { - .drv = &comp_src, -}; +SOF_LLEXT_BUILDINFO; -static void sys_comp_src_init(void) -{ - comp_register(platform_shared_get(&comp_src_info, - sizeof(comp_src_info))); -} +#else + +DECLARE_MODULE_ADAPTER(src_interface, SRC_UUID, src_tr); +SOF_MODULE_INIT(src, sys_comp_module_src_interface_init); -DECLARE_MODULE(sys_comp_src_init); +#endif diff --git a/src/audio/src/src.toml b/src/audio/src/src.toml new file mode 100644 index 000000000000..ab496c5b8a80 --- /dev/null +++ b/src/audio/src/src.toml @@ -0,0 +1,150 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "SRC" + uuid = UUIDREG_STR_SRC4 + affinity_mask = "0x1" + REM #instance_count = "10" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "7" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xffff, 0xc, 0x8, 0x05ff, + 1, 0, 0xf6c9, 0xc, 0x8, 0x05ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 12832, 15976000, 128, 512, 0, 15976, 0, + 1, 0, 0, 0, 12832, 15340000, 64, 256, 0, 15340, 0, + 2, 0, 0, 0, 12832, 21880000, 96, 512, 0, 21880, 0, + 3, 0, 0, 0, 12832, 19968000, 48, 256, 0, 19968, 0, + 4, 0, 0, 0, 12832, 18236000, 64, 256, 0, 18236, 0, + 5, 0, 0, 0, 12832, 15244000, 32, 256, 0, 15244, 0, + 6, 0, 0, 0, 12832, 56028000, 1536, 512, 0, 56028, 0, + 7, 0, 0, 0, 12832, 46740000, 768, 256, 0, 46740, 0, + 8, 0, 0, 0, 12832, 24656000, 768, 512, 0, 24656, 0, + 9, 0, 0, 0, 12832, 23516000, 384, 256, 0, 23516, 0, + 10, 0, 0, 0, 12832, 29368000, 384, 488, 0, 29368, 0, + 11, 0, 0, 0, 12832, 27164000, 192, 244, 0, 27164, 0, + 12, 0, 0, 0, 12832, 15892000, 384, 384, 0, 15892, 0, + 13, 0, 0, 0, 12832, 19916000, 192, 512, 0, 19916, 0, + 14, 0, 0, 0, 12832, 19176000, 96, 256, 0, 19176, 0, + 15, 0, 0, 0, 12832, 12676000, 192, 192, 0, 12676, 0, + 16, 0, 0, 0, 12832, 16280000, 384, 320, 0, 16280, 0, + 17, 0, 0, 0, 12832, 13076000, 192, 160, 0, 13076, 0, + 18, 0, 0, 0, 12832, 11440000, 384, 256, 0, 11440, 0, + 19, 0, 0, 0, 12832, 10996000, 192, 128, 0, 10996, 0, + 20, 0, 0, 0, 12832, 11428000, 384, 192, 0, 11428, 0, + 21, 0, 0, 0, 12832, 10740000, 192, 96, 0, 10740, 0, + 22, 0, 0, 0, 12832, 29936000, 360, 512, 0, 29936, 0, + 23, 0, 0, 0, 12832, 27696000, 180, 256, 0, 27696, 0, + 24, 0, 0, 0, 12832, 18368000, 256, 512, 0, 18368, 0, + 25, 0, 0, 0, 12832, 15204000, 128, 256, 0, 15204, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 12832, 14748000, 128, 512, 0, 14748, 0, + 1, 0, 0, 0, 12832, 14152000, 64, 256, 0, 14152, 0, + 2, 0, 0, 0, 12832, 16988000, 96, 512, 0, 16988, 0, + 3, 0, 0, 0, 12832, 15972000, 48, 256, 0, 15972, 0, + 4, 0, 0, 0, 12832, 13272000, 64, 256, 0, 13272, 0, + 5, 0, 0, 0, 12832, 12872000, 32, 256, 0, 12872, 0, + 6, 0, 0, 0, 12832, 45419000, 1536, 512, 0, 45419, 0, + 7, 0, 0, 0, 12832, 43279000, 768, 256, 0, 43279, 0, + 8, 0, 0, 0, 12832, 25796000, 768, 512, 0, 25796, 0, + 9, 0, 0, 0, 12832, 25131000, 384, 256, 0, 25131, 0, + 10, 0, 0, 0, 12832, 27360000, 384, 488, 0, 27360, 0, + 11, 0, 0, 0, 12832, 23032000, 192, 244, 0, 23032, 0, + 12, 0, 0, 0, 12832, 12432000, 384, 384, 0, 12432, 0, + 13, 0, 0, 0, 12832, 15584000, 192, 512, 0, 15584, 0, + 14, 0, 0, 0, 12832, 15360000, 96, 256, 0, 15360, 0, + 15, 0, 0, 0, 12832, 12104000, 192, 192, 0, 12104, 0, + 16, 0, 0, 0, 12832, 13064000, 384, 320, 0, 13064, 0, + 17, 0, 0, 0, 12832, 12768000, 192, 160, 0, 12768, 0, + 18, 0, 0, 0, 12832, 11636000, 384, 256, 0, 11636, 0, + 19, 0, 0, 0, 12832, 11244000, 192, 128, 0, 11244, 0, + 20, 0, 0, 0, 12832, 11224000, 384, 192, 0, 11224, 0, + 21, 0, 0, 0, 12832, 10360000, 192, 96, 0, 10360, 0, + 22, 0, 0, 0, 12832, 27616000, 360, 512, 0, 27616, 0, + 23, 0, 0, 0, 12832, 21852000, 180, 256, 0, 21852, 0, + 24, 0, 0, 0, 12832, 12629000, 256, 512, 0, 12629, 0, + 25, 0, 0, 0, 12832, 13996000, 128, 256, 0, 13996, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 12832, 30633000, 128, 512, 0, 30633, 0, + 1, 0, 0, 0, 12832, 28143000, 64, 256, 0, 28143, 0, + 2, 0, 0, 0, 12832, 33513000, 96, 512, 0, 33513, 0, + 3, 0, 0, 0, 12832, 0, 48, 256, 0, 0, 0, + 4, 0, 0, 0, 12832, 22867000, 64, 256, 0, 22867, 0, + 5, 0, 0, 0, 12832, 19779000, 32, 256, 0, 19779, 0, + 6, 0, 0, 0, 12832, 80857000, 1536, 512, 0, 80857, 0, + 7, 0, 0, 0, 12832, 62393000, 768, 256, 0, 62393, 0, + 8, 0, 0, 0, 12832, 46159000, 768, 512, 0, 46159, 0, + 9, 0, 0, 0, 12832, 36607000, 384, 256, 0, 36607, 0, + 10, 0, 0, 0, 12832, 49951000, 384, 488, 0, 49951, 0, + 11, 0, 0, 0, 12832, 44031000, 192, 244, 0, 44031, 0, + 12, 0, 0, 0, 12832, 28973000, 384, 384, 0, 28973, 0, + 13, 0, 0, 0, 12832, 35669000, 192, 512, 0, 35669, 0, + 14, 0, 0, 0, 12832, 25931000, 96, 256, 0, 25931, 0, + 15, 0, 0, 0, 12832, 19423000, 192, 192, 0, 19423, 0, + 16, 0, 0, 0, 12832, 25667000, 384, 320, 0, 25667, 0, + 17, 0, 0, 0, 12832, 20623000, 192, 160, 0, 20623, 0, + 18, 0, 0, 0, 12832, 23383000, 384, 256, 0, 23383, 0, + 19, 0, 0, 0, 12832, 18269000, 192, 128, 0, 18269, 0, + 20, 0, 0, 0, 12832, 18181000, 384, 192, 0, 18181, 0, + 21, 0, 0, 0, 12832, 15345000, 192, 96, 0, 15345, 0, + 22, 0, 0, 0, 12832, 49977000, 360, 512, 0, 49977, 0, + 23, 0, 0, 0, 12832, 40403000, 180, 256, 0, 40403, 0, + 24, 0, 0, 0, 12832, 28085000, 256, 512, 0, 28085, 0, + 25, 0, 0, 0, 12832, 22923000, 128, 256, 0, 22923, 0] +#endif + + index = __COUNTER__ + +#if CONFIG_COMP_SRC_LITE + REM # SRC lite module config + [[module.entry]] + name = "SRC_LITE" + uuid = UUIDREG_STR_SRC_LITE + affinity_mask = "0x1" + REM #instance_count = "10" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "0x1F" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xffff, 0xc, 0x8, 0x05ff, + 1, 0, 0xf6c9, 0xc, 0x8, 0x05ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] + REM # identical for MTL and LNL + mod_cfg = [0, 0, 0, 0, 12832, 1365500, 0, 0, 0, 1365, 0, + 1, 0, 0, 0, 12832, 2302300, 0, 0, 0, 2302, 0, + 2, 0, 0, 0, 12832, 3218200, 0, 0, 0, 3218, 0, + 3, 0, 0, 0, 12832, 4169700, 0, 0, 0, 4169, 0, + 4, 0, 0, 0, 12832, 5095100, 0, 0, 0, 5095, 0, + 5, 0, 0, 0, 12832, 6014800, 0, 0, 0, 6014, 0, + 6, 0, 0, 0, 12832, 6963500, 0, 0, 0, 6963, 0, + 7, 0, 0, 0, 12832, 7791000, 0, 0, 0, 7791, 0, + 8, 0, 0, 0, 12832, 8843000, 0, 0, 0, 8843, 0, + 9, 0, 0, 0, 12832, 9755100, 0, 0, 0, 9755, 0, + 10, 0, 0, 0, 12832, 10726500, 0, 0, 0, 10726, 0, + 11, 0, 0, 0, 12832, 11624100, 0, 0, 0, 11624, 0, + 12, 0, 0, 0, 12832, 12518700, 0, 0, 0, 12518, 0, + 13, 0, 0, 0, 12832, 13555000, 0, 0, 0, 13555, 0, + 14, 0, 0, 0, 12832, 14144500, 0, 0, 0, 14144, 0, + 15, 0, 0, 0, 12832, 15809800, 0, 0, 0, 15809, 0, + 16, 0, 0, 0, 12832, 16749000, 0, 0, 0, 16749, 0, + 17, 0, 0, 0, 12832, 18433500, 0, 0, 0, 18433, 0, + 18, 0, 0, 0, 12832, 19425900, 0, 0, 0, 19425, 0, + 19, 0, 0, 0, 12832, 20396900, 0, 0, 0, 20396, 0, + 20, 0, 0, 0, 12832, 20881000, 0, 0, 0, 20881, 0, + 21, 0, 0, 0, 12832, 23431000, 0, 0, 0, 23431, 0, + 22, 0, 0, 0, 12832, 30471000, 0, 0, 0, 30471, 0] + + index = __COUNTER__ +#endif diff --git a/src/audio/src/src_common.c b/src/audio/src/src_common.c new file mode 100644 index 000000000000..3a9c7dac280f --- /dev/null +++ b/src/audio/src/src_common.c @@ -0,0 +1,704 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/lib/fast-get.h> +#include <sof/lib/memory.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/base-config.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <limits.h> + +#include "src_common.h" +#include "src_config.h" + +LOG_MODULE_REGISTER(src, CONFIG_SOF_LOG_LEVEL); + +/* Calculates buffers to allocate for a SRC mode */ +static int src_buffer_lengths(struct comp_dev *dev, struct comp_data *cd, int nch) +{ + const struct src_stage *stage1; + const struct src_stage *stage2; + struct src_param *a; + int fs_in, fs_out; + int source_frames; + int r1, n; + + a = &cd->param; + fs_in = cd->source_rate; + fs_out = cd->sink_rate; + source_frames = cd->source_frames; + + if (nch > PLATFORM_MAX_CHANNELS) { + /* TODO: should be device, not class */ + comp_err(dev, "nch = %u > PLATFORM_MAX_CHANNELS", + nch); + return -EINVAL; + } + + a->nch = nch; + + stage1 = a->stage1; + stage2 = a->stage2; + + /* Check from stage1 parameter for a deleted in/out rate combination.*/ + if (stage1->filter_length < 1) { + comp_err(dev, "Non-supported combination sfs_in = %d, fs_out = %d", + fs_in, fs_out); + return -EINVAL; + } + + a->fir_s1 = nch * src_fir_delay_length(stage1); + a->out_s1 = nch * src_out_delay_length(stage1); + + /* Computing of number of blocks to process is done in + * copy() per each frame. + */ + a->stage1_times = 0; + a->stage2_times = 0; + a->blk_in = 0; + a->blk_out = 0; + + if (stage2->filter_length == 1) { + a->fir_s2 = 0; + a->out_s2 = 0; + a->sbuf_length = 0; + } else { + a->fir_s2 = nch * src_fir_delay_length(stage2); + a->out_s2 = nch * src_out_delay_length(stage2); + + /* Stage 1 is repeated max. amount that just exceeds one + * period. + */ + r1 = source_frames / stage1->blk_in + 1; + + /* Set sbuf length to allow storing two stage 1 output + * periods. This is an empirically found value for no + * xruns to happen with SRC in/out buffers. Due to + * variable number of blocks to process per each stage + * there is no equation known for minimum size. + */ + n = 2 * stage1->blk_out * r1; + a->sbuf_length = nch * (n + (n >> 3)); + } + + a->src_multich = a->fir_s1 + a->fir_s2 + a->out_s1 + a->out_s2; + a->total = a->sbuf_length + a->src_multich; + + return 0; +} + +static int init_stages(const struct src_stage *stage1, const struct src_stage *stage2, + struct polyphase_src *src, struct src_param *p, + int n, int32_t *delay_lines_start) +{ + /* Clear FIR state */ + src_state_reset(&src->state1); + src_state_reset(&src->state2); + + src->number_of_stages = n; + src->stage1 = stage1; + src->stage2 = stage2; + if (n == 1 && stage1->blk_out == 0) + return -EINVAL; + + /* Optimized SRC requires subfilter length multiple of 4 */ + if (stage1->filter_length > 1 && (stage1->subfilter_length & 0x3) > 0) + return -EINVAL; + + if (stage2->filter_length > 1 && (stage2->subfilter_length & 0x3) > 0) + return -EINVAL; + + /* Delay line sizes */ + src->state1.fir_delay_size = p->fir_s1; + src->state1.out_delay_size = p->out_s1; + src->state1.fir_delay = delay_lines_start; + src->state1.out_delay = + src->state1.fir_delay + src->state1.fir_delay_size; + /* Initialize to last ensures that circular wrap cannot happen + * mid-frame. The size is multiple of channels count. + */ + src->state1.fir_wp = &src->state1.fir_delay[p->fir_s1 - 1]; + src->state1.out_rp = src->state1.out_delay; + if (n > 1) { + src->state2.fir_delay_size = p->fir_s2; + src->state2.out_delay_size = p->out_s2; + src->state2.fir_delay = + src->state1.out_delay + src->state1.out_delay_size; + src->state2.out_delay = + src->state2.fir_delay + src->state2.fir_delay_size; + /* Initialize to last ensures that circular wrap cannot happen + * mid-frame. The size is multiple of channels count. + */ + src->state2.fir_wp = &src->state2.fir_delay[p->fir_s2 - 1]; + src->state2.out_rp = src->state2.out_delay; + } else { + src->state2.fir_delay_size = 0; + src->state2.out_delay_size = 0; + src->state2.fir_delay = NULL; + src->state2.out_delay = NULL; + } + + /* Check the sizes are less than MAX */ + if (src->state1.fir_delay_size > p->max_fir_delay_size_xnch || + src->state1.out_delay_size > p->max_out_delay_size_xnch || + src->state2.fir_delay_size > p->max_fir_delay_size_xnch || + src->state2.out_delay_size > p->max_out_delay_size_xnch) { + src->state1.fir_delay = NULL; + src->state1.out_delay = NULL; + src->state2.fir_delay = NULL; + src->state2.out_delay = NULL; + return -EINVAL; + } + + return 0; +} + +static int src_polyphase_init(struct polyphase_src *src, struct src_param *p, + int32_t *delay_lines_start) +{ + const struct src_stage *stage1; + const struct src_stage *stage2; + int n_stages; + int ret; + + if (p->idx_in < 0 || p->idx_out < 0) + return -EINVAL; + + /* Get setup for 2 stage conversion */ + stage1 = p->stage1; + stage2 = p->stage2; + ret = init_stages(stage1, stage2, src, p, 2, delay_lines_start); + if (ret < 0) + return -EINVAL; + + /* Get number of stages used for optimize opportunity. 2nd + * stage length is one if conversion needs only one stage. + * If input and output rate is the same return 0 to + * use a simple copy function instead of 1 stage FIR with one + * tap. + */ + + n_stages = (src->stage2->filter_length == 1) ? 1 : 2; + if (p->in_fs[p->idx_in] == p->out_fs[p->idx_out]) + n_stages = 0; + + /* If filter length for first stage is zero this is a deleted + * mode from in/out matrix. Computing of such SRC mode needs + * to be prevented. + */ + if (src->stage1->filter_length == 0) + return -EINVAL; + + return n_stages; +} + +/* Normal 2 stage SRC */ +static int src_2s(struct comp_data *cd, + struct sof_source *source, struct sof_sink *sink) +{ + struct src_stage_prm s1; + struct src_stage_prm s2; + int s1_blk_in; + int s1_blk_out; + int s2_blk_in; + int s2_blk_out; + uint32_t n_read = 0, n_written = 0; + int ret; + uint8_t const *source_buffer_start; + uint8_t *sink_buffer_start; + void *sbuf_end_addr = &cd->delay_lines[cd->param.sbuf_length]; + size_t sbuf_size = cd->param.sbuf_length * sizeof(int32_t); + /* chan sink == chan src therefore we only need to use one*/ + int nch = source_get_channels(source); + int sbuf_free = cd->param.sbuf_length - cd->sbuf_avail; + int avail_b = source_get_data_available(source); + int free_b = sink_get_free_size(sink); + int sz = cd->sample_container_bytes; + uint32_t source_frag_size = cd->param.blk_in * source_get_frame_bytes(source); + uint32_t sink_frag_size = cd->param.blk_out * sink_get_frame_bytes(sink); + + ret = source_get_data(source, source_frag_size, + &s1.x_rptr, (void const **)&source_buffer_start, &s1.x_size); + if (ret) + return ret; + s1.x_end_addr = source_buffer_start + s1.x_size; + + ret = sink_get_buffer(sink, sink_frag_size, + &s2.y_wptr, (void **)&sink_buffer_start, &s2.y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + s2.y_end_addr = sink_buffer_start + s2.y_size; + + s1.y_end_addr = sbuf_end_addr; + s1.y_size = sbuf_size; + s1.state = &cd->src.state1; + s1.stage = cd->src.stage1; + 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.state = &cd->src.state2; + s2.stage = cd->src.stage2; + s2.x_rptr = cd->sbuf_r_ptr; + s2.nch = nch; + s2.shift = cd->data_shift; + + /* Test if 1st stage can be run with default block length to reach + * the period length or just under it. + */ + s1.times = cd->param.stage1_times; + s1_blk_out = s1.times * cd->src.stage1->blk_out * nch; + + /* The sbuf may limit how many times s1 can be looped. It's harder + * to prepare for in advance so the repeats number is adjusted down + * here if need. + */ + if (s1_blk_out > sbuf_free) { + s1.times = sbuf_free / (cd->src.stage1->blk_out * nch); + s1_blk_out = s1.times * cd->src.stage1->blk_out * nch; + } + + s1_blk_in = s1.times * cd->src.stage1->blk_in * nch; + if (avail_b >= s1_blk_in * sz && sbuf_free >= s1_blk_out) { + cd->polyphase_func(&s1); + + cd->sbuf_w_ptr = s1.y_wptr; + cd->sbuf_avail += s1_blk_out; + n_read += s1.times * cd->src.stage1->blk_in; + } + + s2.times = cd->param.stage2_times; + s2_blk_in = s2.times * cd->src.stage2->blk_in * nch; + if (s2_blk_in > cd->sbuf_avail) { + s2.times = cd->sbuf_avail / (cd->src.stage2->blk_in * nch); + s2_blk_in = s2.times * cd->src.stage2->blk_in * nch; + } + + /* Test if second stage can be run with default block length. */ + s2_blk_out = s2.times * cd->src.stage2->blk_out * nch; + if (cd->sbuf_avail >= s2_blk_in && free_b >= s2_blk_out * sz) { + cd->polyphase_func(&s2); + + cd->sbuf_r_ptr = s2.x_rptr; + cd->sbuf_avail -= s2_blk_in; + n_written += s2.times * cd->src.stage2->blk_out; + } + + /* commit the processed data */ + source_release_data(source, n_read * source_get_frame_bytes(source)); + sink_commit_buffer(sink, n_written * sink_get_frame_bytes(sink)); + return 0; +} + +/* 1 stage SRC for simple conversions */ +static int src_1s(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink) +{ + struct src_stage_prm s1; + int ret; + uint8_t const *source_buffer_start; + uint8_t *sink_buffer_start; + uint32_t source_frag_size = cd->param.blk_in * source_get_frame_bytes(source); + uint32_t sink_frag_size = cd->param.blk_out * sink_get_frame_bytes(sink); + + ret = source_get_data(source, source_frag_size, + &s1.x_rptr, (void const **)&source_buffer_start, &s1.x_size); + if (ret) + return ret; + s1.x_end_addr = source_buffer_start + s1.x_size; + + ret = sink_get_buffer(sink, sink_frag_size, + &s1.y_wptr, (void **)&sink_buffer_start, &s1.y_size); + if (ret) { + source_release_data(source, 0); + return ret; + } + s1.y_end_addr = sink_buffer_start + s1.y_size; + + s1.times = cd->param.stage1_times; + s1.state = &cd->src.state1; + s1.stage = cd->src.stage1; + s1.nch = source_get_channels(source); /* src channels must == sink channels */ + s1.shift = cd->data_shift; + + cd->polyphase_func(&s1); + + /* commit the processed data */ + source_release_data(source, UINT_MAX); + sink_commit_buffer(sink, UINT_MAX); + + return 0; +} + +/* A fast copy function for same in and out rate */ +int src_copy_sxx(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink) +{ + int frames = cd->param.blk_in; + + switch (source_get_frm_fmt(source)) { + case SOF_IPC_FRAME_S16_LE: + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + return source_to_sink_copy(source, sink, true, + frames * source_get_frame_bytes(source)); + default: + break; + } + + return -ENOTSUP; +} + +void src_set_alignment(struct sof_source *source) +{ + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; + const uint32_t frame_align_req = SOF_FRAME_COUNT_ALIGN; + + source_set_alignment_constants(source, byte_align, frame_align_req); +} + +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, "entry"); + + /* check whether params->rate (received from driver) are equal + * to src->source_rate (PLAYBACK) or src->sink_rate (CAPTURE) set during + * creating src component in src_new(). + * src->source/sink_rate = 0 means that source/sink rate can vary. + */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + ret = src_stream_pcm_sink_rate_check(cd->ipc_config, params); + if (ret < 0) { + comp_err(dev, "sink stream rate does not match rate fetched from ipc."); + return ret; + } + } else { + ret = src_stream_pcm_source_rate_check(cd->ipc_config, params); + if (ret < 0) { + comp_err(dev, "source stream rate does not match rate fetched from ipc."); + return ret; + } + } + + /* update downstream (playback) or upstream (capture) buffer parameters + */ + ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); + if (ret < 0) + comp_err(dev, "comp_verify_params() failed."); + + return ret; +} + +static bool src_get_copy_limits(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink) +{ + struct src_param *sp; + const struct src_stage *s1; + const struct src_stage *s2; + int frames_src; + int frames_snk; + + /* Get SRC parameters */ + sp = &cd->param; + s1 = cd->src.stage1; + s2 = cd->src.stage2; + + /* Calculate how many blocks can be processed with + * available source and free sink frames amount. + */ + frames_snk = sink_get_free_frames(sink); + frames_src = source_get_data_frames_available(source); + if (s2->filter_length > 1) { + /* Two polyphase filters case */ + frames_snk = MIN(frames_snk, cd->sink_frames + s2->blk_out); + sp->stage2_times = frames_snk / s2->blk_out; + frames_src = MIN(frames_src, cd->source_frames + s1->blk_in); + sp->stage1_times = frames_src / s1->blk_in; + sp->blk_in = sp->stage1_times * s1->blk_in; + sp->blk_out = sp->stage2_times * s2->blk_out; + } else { + /* Single polyphase filter case */ + frames_snk = MIN(frames_snk, cd->sink_frames + s1->blk_out); + sp->stage1_times = frames_snk / s1->blk_out; + sp->stage1_times = MIN(sp->stage1_times, + frames_src / s1->blk_in); + sp->blk_in = sp->stage1_times * s1->blk_in; + sp->blk_out = sp->stage1_times * s1->blk_out; + } + + if (sp->blk_in == 0 && sp->blk_out == 0) + return false; + + return true; +} + +int src_params_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + size_t delay_lines_size; + int32_t *buffer_start; + int n; + int err; + + comp_info(dev, "entry"); + + err = src_set_params(mod, sink); + if (err < 0) { + comp_err(dev, "set params failed."); + return err; + } + + err = src_verify_params(mod); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return err; + } + + comp_info(dev, "source_rate = %u, sink_rate = %u", + cd->source_rate, cd->sink_rate); + comp_dbg(dev, "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, "zero sink rate"); + return -EINVAL; + } + + cd->source_frames = dev->frames * cd->source_rate / cd->sink_rate; + cd->sink_frames = dev->frames; + + /* Allocate needed memory for delay lines */ + err = src_buffer_lengths(dev, cd, cd->channels_count); + if (err < 0) { + comp_err(dev, "src_buffer_lengths() failed"); + return err; + } + + /* + * delay_lines_size is used to compute buffer_start which needs to + * be aligned to 8 bytes as required by some Xtensa + * instructions (e.g AE_L32X2F24_XC) + */ + delay_lines_size = ALIGN_UP(sizeof(int32_t) * cd->param.total, 8); + if (delay_lines_size == 0) { + comp_err(dev, "delay_lines_size = 0"); + + return -EINVAL; + } + + /* free any existing delay lines. TODO reuse if same size */ + mod_free(mod, cd->delay_lines); + + cd->delay_lines = mod_alloc(mod, delay_lines_size); + if (!cd->delay_lines) { + comp_err(dev, "failed to alloc cd->delay_lines, delay_lines_size = %zu", + delay_lines_size); + return -ENOMEM; + } + + /* Clear all delay lines here */ + memset(cd->delay_lines, 0, delay_lines_size); + buffer_start = cd->delay_lines + ALIGN_UP(cd->param.sbuf_length, 2); + + /* Initialize SRC for actual sample rate */ + n = src_polyphase_init(&cd->src, &cd->param, buffer_start); + + /* Reset stage buffer */ + cd->sbuf_r_ptr = cd->delay_lines; + cd->sbuf_w_ptr = cd->delay_lines; + cd->sbuf_avail = 0; + + switch (n) { + case 0: + /* 1:1 fast copy */ + cd->src_func = src_copy_sxx; + break; + case 1: + cd->src_func = src_1s; /* Simpler 1 stage SRC */ + break; + case 2: + cd->src_func = src_2s; /* Default 2 stage SRC */ + break; + default: + /* This is possibly due to missing coefficients for + * requested rates combination. + */ + comp_info(dev, "missing coefficients for requested rates combination"); + cd->src_func = src_fallback; + return -EINVAL; + } + + return 0; +} + +int src_param_set(struct comp_dev *dev, struct comp_data *cd) +{ + struct src_param *a = &cd->param; + int fs_in = cd->source_rate; + int fs_out = cd->sink_rate; + + a->idx_in = src_find_fs(a->in_fs, a->num_in_fs, fs_in); + a->idx_out = src_find_fs(a->out_fs, a->num_out_fs, fs_out); + + /* Check that both in and out rates are supported */ + if (a->idx_in < 0 || a->idx_out < 0) { + comp_err(dev, "rates not supported, fs_in: %u, fs_out: %u", + fs_in, fs_out); + return -EINVAL; + } + + return 0; +} + +int src_allocate_copy_stages(struct processing_module *mod, struct src_param *prm, + const struct src_stage *stage_src1, + const struct src_stage *stage_src2) +{ +#if CONFIG_FAST_GET + struct src_stage *stage_dst; + size_t coef_size[2]; +#if SRC_SHORT + size_t tap_size = sizeof(int16_t); +#else + size_t tap_size = sizeof(int32_t); +#endif + + stage_dst = mod_alloc(mod, 2 * sizeof(*stage_dst)); + if (!stage_dst) { + comp_err(mod->dev, "failed to allocate stages"); + return -ENOMEM; + } + + /* Make local copies of the src_stages */ + stage_dst[0] = *stage_src1; + stage_dst[1] = *stage_src2; + + coef_size[0] = tap_size * stage_src1->filter_length; + coef_size[1] = tap_size * stage_src2->filter_length; + + if (coef_size[0] == 0 || coef_size[1] == 0) { + comp_err(mod->dev, + "illegal zero coefficient vector size for unsupported conversion request %d to %d", + prm->in_fs[prm->idx_in], prm->out_fs[prm->idx_out]); + return -EINVAL; + } + + stage_dst[0].coefs = mod_fast_get(mod, stage_src1->coefs, coef_size[0]); + stage_dst[1].coefs = mod_fast_get(mod, stage_src2->coefs, coef_size[1]); + + if (!stage_dst[0].coefs || !stage_dst[1].coefs) { + comp_err(mod->dev, "failed to allocate coefficients"); + return -ENOMEM; + } + + prm->stage1 = stage_dst; + prm->stage2 = stage_dst + 1; +#else + prm->stage1 = stage_src1; + prm->stage2 = stage_src2; +#endif + + return 0; +} + +bool src_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + return sink_get_free_frames(sinks[0]) || source_get_data_frames_available(sources[0]); +} + +int src_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + /* src component needs 1 source and 1 sink */ + if (!src_get_copy_limits(cd, sources[0], sinks[0])) { + comp_dbg(mod->dev, "No data to process."); + return 0; + } + + return cd->src_func(cd, sources[0], sinks[0]); +} + +int src_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + cd->src_func = src_fallback; + src_polyphase_reset(&cd->src); + + return 0; +} + +__cold int src_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + comp_info(mod->dev, "entry"); + +#if CONFIG_FAST_GET + struct src_param *a = &cd->param; + + if (a->stage1) + mod_fast_put(mod, a->stage1->coefs); + if (a->stage2) + mod_fast_put(mod, a->stage2->coefs); +#endif + + mod_free(mod, cd->delay_lines); + mod_free(mod, cd); + + return 0; +} diff --git a/src/audio/src/src_common.h b/src/audio/src/src_common.h new file mode 100644 index 000000000000..98f29a263131 --- /dev/null +++ b/src/audio/src/src_common.h @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017-2024 Intel Corporation. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_SRC_SRC_COMMON_H__ +#define __SOF_AUDIO_SRC_SRC_COMMON_H__ + +#include <stddef.h> +#include <stdint.h> +#include <ipc4/base-config.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "src_ipc.h" + +struct src_stage { + int idm; + int odm; + int num_of_subfilters; + int subfilter_length; + int filter_length; + int blk_in; + int blk_out; + int halfband; + int shift; + const void *coefs; /* Can be int16_t or int32_t depending on config */ +}; + +struct src_param { + int fir_s1; + int fir_s2; + int out_s1; + int out_s2; + int sbuf_length; + int src_multich; + int total; + int blk_in; + int blk_out; + int stage1_times; + int stage2_times; + int idx_in; + int idx_out; + int num_in_fs; + int num_out_fs; + int max_fir_delay_size_xnch; + int max_out_delay_size_xnch; + int nch; + const struct src_stage *stage1; + const struct src_stage *stage2; + const int *in_fs; + const int *out_fs; +}; + +struct src_state { + int fir_delay_size; /* samples */ + int out_delay_size; /* samples */ + int32_t *fir_delay; + int32_t *out_delay; + int32_t *fir_wp; + int32_t *out_rp; +}; + +struct polyphase_src { + int number_of_stages; + const struct src_stage *stage1; + const struct src_stage *stage2; + struct src_state state1; + struct src_state state2; +}; + +struct src_stage_prm { + int nch; + int times; + void const *x_rptr; + void const *x_end_addr; + size_t x_size; + void *y_wptr; + void *y_addr; + void *y_end_addr; + size_t y_size; + int shift; + struct src_state *state; + const struct src_stage *stage; +}; + +static inline void src_inc_wrap(int32_t **ptr, int32_t *end, size_t size) +{ + if (*ptr >= end) + *ptr = (int32_t *)((uint8_t *)*ptr - size); +} + +static inline void src_dec_wrap(int32_t **ptr, int32_t *addr, size_t size) +{ + if (*ptr < addr) + *ptr = (int32_t *)((uint8_t *)*ptr + size); +} + +#if CONFIG_FORMAT_S16LE +static inline void src_inc_wrap_s16(int16_t **ptr, int16_t *end, size_t size) +{ + if (*ptr >= end) + *ptr = (int16_t *)((uint8_t *)*ptr - size); +} + +static inline void src_dec_wrap_s16(int16_t **ptr, int16_t *addr, size_t size) +{ + if (*ptr < addr) + *ptr = (int16_t *)((uint8_t *)*ptr + size); +} +#endif /* CONFIG_FORMAT_S16LE */ + +static inline void src_state_reset(struct src_state *state) +{ + state->fir_delay_size = 0; + state->out_delay_size = 0; +} + +static inline void src_polyphase_reset(struct polyphase_src *src) +{ + src->number_of_stages = 0; + src->stage1 = NULL; + src->stage2 = NULL; + src_state_reset(&src->state1); + src_state_reset(&src->state2); +} + +int src_polyphase(struct polyphase_src *src, int32_t x[], int32_t y[], + int n_in); + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +void src_polyphase_stage_cir(struct src_stage_prm *s); +#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +void src_polyphase_stage_cir_s16(struct src_stage_prm *s); +#endif /* CONFIG_FORMAT_S16LE */ + +int32_t src_input_rates(void); + +int32_t src_output_rates(void); + +void src_set_alignment(struct sof_source *source); + +struct comp_data { +#if CONFIG_IPC_MAJOR_4 + struct ipc4_config_src ipc_config; +#else + struct ipc_config_src ipc_config; +#endif /* CONFIG_IPC_MAJOR_4 */ + struct polyphase_src src; + struct src_param param; + int32_t *delay_lines; + uint32_t sink_rate; + uint32_t source_rate; + int32_t *sbuf_w_ptr; + int32_t const *sbuf_r_ptr; + int sbuf_avail; + int data_shift; + int source_frames; + int sink_frames; + int sample_container_bytes; + int channels_count; + int (*src_func)(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink); + void (*polyphase_func)(struct src_stage_prm *s); +}; + +#if CONFIG_IPC_MAJOR_4 + +int src_stream_pcm_source_rate_check(struct ipc4_config_src cfg, + struct sof_ipc_stream_params *params); +int src_stream_pcm_sink_rate_check(struct ipc4_config_src cfg, + struct sof_ipc_stream_params *params); +#elif CONFIG_IPC_MAJOR_3 +int src_stream_pcm_sink_rate_check(struct ipc_config_src cfg, + struct sof_ipc_stream_params *params); +int src_stream_pcm_source_rate_check(struct ipc_config_src cfg, + struct sof_ipc_stream_params *params); +#endif /* CONFIG_IPC_MAJOR_4 */ + +/* Calculates the needed FIR delay line length */ +static inline int src_fir_delay_length(const struct src_stage *s) +{ + return s->subfilter_length + (s->num_of_subfilters - 1) * s->idm + + s->blk_in; +} + +/* Calculates the FIR output delay line length */ +static inline int src_out_delay_length(const struct src_stage *s) +{ + return 1 + (s->num_of_subfilters - 1) * s->odm; +} + +/* Returns index of a matching sample rate */ +static inline int src_find_fs(const int *fs_list, int list_length, int fs) +{ + int i; + + for (i = 0; i < list_length; i++) { + if (fs_list[i] == fs) + return i; + } + return -EINVAL; +} + +/* Fallback function */ +static inline int src_fallback(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink) +{ + return 0; +} + +int src_allocate_copy_stages(struct processing_module *mod, struct src_param *prm, + const struct src_stage *stage_src1, + const struct src_stage *stage_src2); +int src_rate_check(const void *spec); +int src_set_params(struct processing_module *mod, struct sof_sink *sink); + +void src_get_source_sink_params(struct comp_dev *dev, struct sof_source *source, + struct sof_sink *sink); +int src_prepare_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink); +int src_init(struct processing_module *mod); + +int src_copy_sxx(struct comp_data *cd, struct sof_source *source, + struct sof_sink *sink); +int src_params_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink); +int src_param_set(struct comp_dev *dev, struct comp_data *cd); + +bool src_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); +int src_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + +int src_free(struct processing_module *mod); +int src_reset(struct processing_module *mod); +extern struct tr_ctx src_tr; + +#ifdef CONFIG_IPC_MAJOR_4 +#define SRC_UUID src4_uuid +#else +#define SRC_UUID src_uuid +#endif +extern const struct sof_uuid SRC_UUID; + +#endif /* __SOF_AUDIO_SRC_SRC_COMMON_H__ */ diff --git a/src/audio/src/src_config.h b/src/audio/src/src_config.h new file mode 100644 index 000000000000..9e53704b123f --- /dev/null +++ b/src/audio/src/src_config.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_SRC_SRC_CONFIG_H__ +#define __SOF_AUDIO_SRC_SRC_CONFIG_H__ + +#include <sof/common.h> + +/* Follow kconfig for FILTER in SRC component */ +#if SOF_USE_MIN_HIFI(5, FILTER) +#define SRC_HIFI5 1 +#elif SOF_USE_MIN_HIFI(4, FILTER) +#define SRC_HIFI4 1 +#elif SOF_USE_MIN_HIFI(3, FILTER) +#define SRC_HIFI3 1 +#elif SOF_USE_HIFI(2, FILTER) +#define SRC_HIFIEP 1 +#else +#define SRC_GENERIC 1 +#endif + +/* Kconfig option tiny needs 16 bits coefficients, other options use 32 bits, + * also gcc builds for all platforms and testbench (library) + */ +#if !defined(SRC_SHORT) +#if CONFIG_COMP_SRC_TINY +#define SRC_SHORT 1 /* 16 bit coefficients filter core */ +#else +#define SRC_SHORT 0 /* 32 bit coefficients filter core */ +#endif +#endif + +#endif /* __SOF_AUDIO_SRC_SRC_CONFIG_H__ */ diff --git a/src/audio/src/src_generic.c b/src/audio/src/src_generic.c index f37d9d5de020..3072fe1f741c 100644 --- a/src/audio/src/src_generic.c +++ b/src/audio/src/src_generic.c @@ -8,20 +8,20 @@ * architecture. */ -#include <sof/audio/src/src_config.h> +#include "src_config.h" #if SRC_GENERIC #include <sof/audio/format.h> -#include <sof/audio/src/src.h> #include <stddef.h> #include <stdint.h> +#include "src_common.h" + #if SRC_SHORT /* 16 bit coefficients version */ static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, int32_t *fir_start, int32_t *fir_end, - const int fir_delay_length, const int taps_x_nch, const int shift, const int nch) { @@ -59,22 +59,18 @@ static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, * output shift includes the shift by 15 for Qx.46 to * Qx.31. */ - for (i = 0; i < n1; i++) { - y0 += (int64_t)(*coef) * (*data); - data++; - y1 += (int64_t)(*coef) * (*data); - data++; - coef++; + for (i = 0; i < n1; i++, coef++, data += 2) { + y0 += (int64_t)(*coef) * data[0]; + y1 += (int64_t)(*coef) * data[1]; } - if (data == fir_end) - data = fir_start; - for (i = 0; i < n2; i++) { - y0 += (int64_t)(*coef) * (*data); - data++; - y1 += (int64_t)(*coef) * (*data); - data++; - coef++; + /* No need to check for circular wrap. Pointer data is moved to + * fir_start to be used by next loop if n2 is greater than zero. + */ + data = fir_start; + for (i = 0; i < n2; i++, coef++, data += 2) { + y0 += (int64_t)(*coef) * data[0]; + y1 += (int64_t)(*coef) * data[1]; } *wp = sat_int32(y1 >> qshift); @@ -100,19 +96,15 @@ static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, * output shift includes the shift by 15 for Qx.46 to * Qx.31. */ - for (i = 0; i < n1; i += nch) { + for (i = 0; i < n1; i += nch, coef++, data += nch) y0 += (int64_t)(*coef) * (*data); - coef++; - data += nch; - } - if (data >= fir_end) - data -= fir_delay_length; - for (i = 0; i < n2; i += nch) { + /* No need to check for circular wrap. Pointer data is moved to fir_start + * plus actual channel to be used by next loop if n2 is greater than zero. + */ + data = fir_start + nch - j - 1; + for (i = 0; i < n2; i += nch, coef++, data += nch) y0 += (int64_t)(*coef) * (*data); - coef++; - data += nch; - } *wp = sat_int32(y0 >> qshift); wp++; @@ -123,12 +115,12 @@ static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, int32_t *fir_start, int32_t *fir_end, - int fir_delay_length, const int taps_x_nch, const int shift, const int nch) { int64_t y0; int64_t y1; + int32_t scaled_coef; int32_t *data; const int32_t *coef; int i; @@ -162,22 +154,20 @@ static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, * output shift includes the shift by 23 for Qx.54 to * Qx.31. */ - for (i = 0; i < n1; i++) { - y0 += (int64_t)(*coef >> 8) * (*data); - data++; - y1 += (int64_t)(*coef >> 8) * (*data); - data++; - coef++; + for (i = 0; i < n1; i++, coef++, data += 2) { + scaled_coef = *coef >> 8; + y0 += (int64_t)scaled_coef * data[0]; + y1 += (int64_t)scaled_coef * data[1]; } - if (data == fir_end) - data = fir_start; - for (i = 0; i < n2; i++) { - y0 += (int64_t)(*coef >> 8) * (*data); - data++; - y1 += (int64_t)(*coef >> 8) * (*data); - data++; - coef++; + /* No need to check for circular wrap. Pointer data is moved to + * fir_start to be used by next loop if n2 is greater than zero. + */ + data = fir_start; + for (i = 0; i < n2; i++, coef++, data += 2) { + scaled_coef = *coef >> 8; + y0 += (int64_t)scaled_coef * data[0]; + y1 += (int64_t)scaled_coef * data[1]; } *wp = sat_int32(y1 >> qshift); *(wp + 1) = sat_int32(y0 >> qshift); @@ -202,19 +192,16 @@ static inline void fir_filter_generic(int32_t *rp, const void *cp, int32_t *wp0, * output shift includes the shift by 23 for Qx.54 to * Qx.31. */ - for (i = 0; i < n1; i += nch) { + for (i = 0; i < n1; i += nch, coef++, data += nch) y0 += (int64_t)(*coef >> 8) * (*data); - coef++; - data += nch; - } - if (data >= fir_end) - data -= fir_delay_length; - for (i = 0; i < n2; i += nch) { + /* No need to check for circular wrap. Pointer data is moved to fir_start + * plus actual channel to be used by next loop if n2 is greater than zero. + */ + data = fir_start + nch - j - 1; + for (i = 0; i < n2; i += nch, coef++, data += nch) y0 += (int64_t)(*coef >> 8) * (*data); - coef++; - data += nch; - } + *wp = sat_int32(y0 >> qshift); wp++; } @@ -235,7 +222,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) int32_t *wp; struct src_state *fir = s->state; - struct src_stage *cfg = s->stage; + const struct src_stage *cfg = s->stage; int32_t *fir_delay = fir->fir_delay; int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; @@ -245,9 +232,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) const int nch_x_odm = cfg->odm * nch; const int blk_in_words = nch * cfg->blk_in; const int blk_out_words = nch * cfg->num_of_subfilters; - const int fir_length = fir->fir_delay_size; - const int rewind = nch * (cfg->blk_in - + (cfg->num_of_subfilters - 1) * cfg->idm) - nch; + const int rewind = nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); const int nch_x_idm = nch * cfg->idm; const size_t fir_size = fir->fir_delay_size * sizeof(int32_t); const int taps_x_nch = cfg->subfilter_length * nch; @@ -289,8 +274,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) src_inc_wrap(&rp, fir_end, fir_size); wp = fir->out_rp; for (i = 0; i < cfg->num_of_subfilters; i++) { - fir_filter_generic(rp, cp, wp, - fir_delay, fir_end, fir_length, + fir_filter_generic(rp, cp, wp, fir_delay, fir_end, taps_x_nch, cfg->shift, nch); wp += nch_x_odm; cp = (char *)cp + subfilter_size; @@ -336,7 +320,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) int32_t *wp; struct src_state *fir = s->state; - struct src_stage *cfg = s->stage; + const struct src_stage *cfg = s->stage; int32_t *fir_delay = fir->fir_delay; int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; @@ -346,9 +330,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) const int nch_x_odm = cfg->odm * nch; const int blk_in_words = nch * cfg->blk_in; const int blk_out_words = nch * cfg->num_of_subfilters; - const int fir_length = fir->fir_delay_size; - const int rewind = nch * (cfg->blk_in - + (cfg->num_of_subfilters - 1) * cfg->idm) - nch; + const int rewind = nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); const int nch_x_idm = nch * cfg->idm; const size_t fir_size = fir->fir_delay_size * sizeof(int32_t); const int taps_x_nch = cfg->subfilter_length * nch; @@ -390,8 +372,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) src_inc_wrap(&rp, fir_end, fir_size); wp = fir->out_rp; for (i = 0; i < cfg->num_of_subfilters; i++) { - fir_filter_generic(rp, cp, wp, - fir_delay, fir_end, fir_length, + fir_filter_generic(rp, cp, wp, fir_delay, fir_end, taps_x_nch, cfg->shift, nch); wp += nch_x_odm; cp = (char *)cp + subfilter_size; @@ -410,7 +391,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) n_min = (m < n_min) ? m : n_min; m -= n_min; for (i = 0; i < n_min; i++) { - *y_wptr = Q_SHIFT_RND(*fir->out_rp, 31, 15); + *y_wptr = sat_int16(Q_SHIFT_RND(*fir->out_rp, 31, 15)); y_wptr++; fir->out_rp++; } diff --git a/src/audio/src/src_hifi2ep.c b/src/audio/src/src_hifi2ep.c index 05578e50ae50..73bf0797c91c 100644 --- a/src/audio/src/src_hifi2ep.c +++ b/src/audio/src/src_hifi2ep.c @@ -6,11 +6,12 @@ /* HiFi EP optimized code parts for SRC */ -#include <sof/audio/src/src_config.h> +#include "src_config.h" #if SRC_HIFIEP -#include <sof/audio/src/src.h> +#include "src_common.h" + #include <xtensa/config/defs.h> #include <xtensa/tie/xt_hifi2.h> #include <stddef.h> @@ -312,7 +313,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) int n_wrap_buf; int n_min; struct src_state *fir = s->state; - struct src_stage *cfg = s->stage; + const struct src_stage *cfg = s->stage; int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; const char *cp; /* Can be int32_t or int16_t */ @@ -323,8 +324,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) const int blk_out_words = nch * cfg->num_of_subfilters; const int sz = sizeof(int32_t); const int n_sz = -sizeof(int32_t); - const int rewind_sz = sz * (nch * (cfg->blk_in - + (cfg->num_of_subfilters - 1) * cfg->idm) - nch); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); const int taps_div_4 = cfg->subfilter_length >> 2; int32_t *x_rptr = (int32_t *)s->x_rptr; @@ -438,7 +438,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) int n_wrap_buf; int n_min; struct src_state *fir = s->state; - struct src_stage *cfg = s->stage; + const struct src_stage *cfg = s->stage; int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; const char *cp; /* Can be int32_t or int16_t */ @@ -449,8 +449,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) const int blk_out_words = nch * cfg->num_of_subfilters; const int sz = sizeof(int32_t); const int n_sz = -sizeof(int32_t); - const int rewind_sz = sz * (nch * (cfg->blk_in - + (cfg->num_of_subfilters - 1) * cfg->idm) - nch); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); const int taps_div_4 = cfg->subfilter_length >> 2; int16_t *x_rptr = (int16_t *)s->x_rptr; diff --git a/src/audio/src/src_hifi3.c b/src/audio/src/src_hifi3.c index 4c79e28107df..06a7b7aa75ba 100644 --- a/src/audio/src/src_hifi3.c +++ b/src/audio/src/src_hifi3.c @@ -6,11 +6,12 @@ /* HiFi3 optimized code parts for SRC */ -#include <sof/audio/src/src_config.h> +#include "src_config.h" #if SRC_HIFI3 -#include <sof/audio/src/src.h> +#include "src_common.h" + #include <xtensa/config/defs.h> #include <xtensa/tie/xt_hifi3.h> #include <stddef.h> @@ -316,7 +317,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) int n_wrap_buf; int n_min; struct src_state *fir = s->state; - struct src_stage *cfg = s->stage; + const struct src_stage *cfg = s->stage; int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; const void *cp; /* Can be int32_t or int16_t */ @@ -327,8 +328,7 @@ void src_polyphase_stage_cir(struct src_stage_prm *s) const int blk_out_words = nch * cfg->num_of_subfilters; const int sz = sizeof(int32_t); const int n_sz = -sizeof(int32_t); - const int rewind_sz = sz * (nch * (cfg->blk_in - + (cfg->num_of_subfilters - 1) * cfg->idm) - nch); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); const int taps_div_4 = cfg->subfilter_length >> 2; int32_t *x_rptr = (int32_t *)s->x_rptr; @@ -443,7 +443,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) int n_min; struct src_state *fir = s->state; - struct src_stage *cfg = s->stage; + const struct src_stage *cfg = s->stage; int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; const void *cp; /* Can be int32_t or int16_t */ @@ -454,8 +454,7 @@ void src_polyphase_stage_cir_s16(struct src_stage_prm *s) const int blk_out_words = nch * cfg->num_of_subfilters; const int sz = sizeof(int32_t); const int n_sz = -sizeof(int32_t); - const int rewind_sz = sz * (nch * (cfg->blk_in - + (cfg->num_of_subfilters - 1) * cfg->idm) - nch); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); const int taps_div_4 = cfg->subfilter_length >> 2; int16_t *x_rptr = (int16_t *)s->x_rptr; diff --git a/src/audio/src/src_hifi4.c b/src/audio/src/src_hifi4.c new file mode 100644 index 000000000000..ad3b8583113f --- /dev/null +++ b/src/audio/src/src_hifi4.c @@ -0,0 +1,586 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2025 Intel Corporation. +// +// Author: Krzysztof Frydryk <krzysztofx.frydryk@intel.com> +// Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +/* HiFi5 optimized code parts for SRC */ + +#include "src_config.h" + +#if SRC_HIFI4 + +#include "src_common.h" + +#include <sof/math/numbers.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi4.h> +#include <stddef.h> +#include <stdint.h> + +/* sof/math/numbers.h doesn't define MIN when used with zephyr */ +#ifdef __ZEPHYR__ +#include <zephyr/sys/util.h> +#endif /* __ZEPHYR__ */ + +#if SRC_SHORT +#define SRC_COEF_SIZE sizeof(int16_t) +#else +#define SRC_COEF_SIZE sizeof(int32_t) +#endif + +#if SRC_SHORT /* 16 bit coefficients version */ + +static inline void fir_filter_2ch(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift) +{ + /* This function uses + * 7x 64 bit registers + * 2x integers + * 3x address pointers, + */ + ae_f64 a0; + ae_f64 a1; + ae_valign u; + ae_f16x4 coef4; + ae_f32x2 d0; + ae_f32x2 d1; + ae_f32x2 data2; + ae_f16x4 *coefp; + ae_f32x2 *dp; + int i; + ae_f32 *wp = wp0; + const int inc = 2 * sizeof(int32_t); + + /* Move data pointer back by one sample to start from right + * channel sample. Discard read value p0. + */ + dp = (ae_f32x2 *)rp; + AE_L32_XC(d0, (ae_f32 *)dp, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_f16x4 *)cp; + a0 = AE_ZERO64(); + a1 = AE_ZERO64(); + u = AE_LA64_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Four coefficients + * are loaded simultaneously. Data is read + * from interleaved buffer with stride of channels + * count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients */ + AE_LA16X4_IP(coef4, u, coefp); + + /* Load two data samples from two channels */ + AE_L32X2_XC(d0, dp, inc); /* r0, l0 */ + AE_L32X2_XC(d1, dp, inc); /* r1, l1 */ + + /* Select to data2 sequential samples from a channel + * and then accumulate to a0 and a1 + * data2_h * coef4_3 + data2_l * coef4_2. + * The data is 32 bits Q1.31 and coefficient 16 bits + * Q1.15. The accumulators are Q17.47. + */ + data2 = AE_SEL32_LL(d0, d1); /* l0, l1 */ + AE_MULAAFD32X16_H3_L2(a0, data2, coef4); + data2 = AE_SEL32_HH(d0, d1); /* r0, r1 */ + AE_MULAAFD32X16_H3_L2(a1, data2, coef4); + + /* Load two data samples from two channels */ + AE_L32X2_XC(d0, dp, inc); /* r2, l2 */ + AE_L32X2_XC(d1, dp, inc); /* r3, l3 */ + + /* Accumulate + * data2_h * coef4_1 + data2_l * coef4_0. + */ + data2 = AE_SEL32_LL(d0, d1); /* l2, l3 */ + AE_MULAAFD32X16_H1_L0(a0, data2, coef4); + data2 = AE_SEL32_HH(d0, d1); /* r2, r3 */ + AE_MULAAFD32X16_H1_L0(a1, data2, coef4); + } + + /* Scale FIR output with right shifts, round/saturate + * to Q1.31, and store 32 bit output. + */ + AE_S32_L_XP(AE_ROUND32F48SSYM(AE_SRAA64(a0, shift)), wp, sizeof(int32_t)); + AE_S32_L_XP(AE_ROUND32F48SSYM(AE_SRAA64(a1, shift)), wp, sizeof(int32_t)); +} + +static inline void fir_filter(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift, + const int nch) +{ + /* This function uses + * 6x 64 bit registers + * 3x integers + * 3x address pointers, + */ + ae_f64 a0; + ae_valign u; + ae_f16x4 coef4; + ae_f32x2 d0; + ae_f32x2 d1; + ae_f32x2 data2; + ae_f16x4 *coefp; + ae_f32 *dp0; + ae_f32 *dp1; + int i; + int j; + ae_f32 *wp = wp0; + const int inc = nch * sizeof(int32_t); + + dp1 = (ae_f32 *)rp; + for (j = 0; j < nch; j++) { + /* Copy pointer and advance to next ch with dummy load */ + dp0 = dp1; + AE_L32_XC(d0, dp1, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_f16x4 *)cp; + a0 = AE_ZERO64(); + u = AE_LA64_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Data is read from + * interleaved buffer with stride of channels count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients */ + AE_LA16X4_IP(coef4, u, coefp); + + /* Load two data samples, place to high and + * low of data2. + */ + AE_L32_XC(d0, dp0, inc); + AE_L32_XC(d1, dp0, inc); + data2 = AE_SEL32_LL(d0, d1); + + /* Accumulate + * data2_h * coef4_3 + data2_l* coef4_2. + * The data is 32 bits Q1.31 and coefficient 16 bits + * Q1.15. The accumulator is Q17.47. + */ + AE_MULAAFD32X16_H3_L2(a0, data2, coef4); + + /* Repeat with next two samples */ + AE_L32_XC(d0, dp0, inc); + AE_L32_XC(d1, dp0, inc); + data2 = AE_SEL32_LL(d0, d1); + + /* Accumulate + * data2_h * coef4_1 + data2_l * coef4_0. + */ + AE_MULAAFD32X16_H1_L0(a0, data2, coef4); + } + + /* Scale FIR output with right shifts, round/saturate Q17.47 + * to Q1.31, and store 32 bit output. Advance write + * pointer to next sample. + */ + AE_S32_L_XP(AE_ROUND32F48SSYM(AE_SRAA64(a0, shift)), wp, + sizeof(int32_t)); + } +} + +#else /* 32bit coefficients version */ + +static inline void fir_filter_2ch(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift) +{ + ae_f64 a0 = AE_ZERO64(); + ae_f64 a1 = AE_ZERO64(); + ae_valign coef_align; + ae_f32x2 coef32; + ae_f32x2 coef10; + ae_f32x2 sample10; + ae_f32x2 f0; + ae_f32x2 f1; + ae_int32x2 *coefp; + ae_f32x2 *dp; + ae_f32 *wp = wp0; + const int inc = 2 * sizeof(int32_t); + int i; + + /* Move data pointer back by one sample to start from right + * channel sample. Discard read value p0. + */ + dp = (ae_f32x2 *)rp; + AE_L32_XC(f0, (ae_f32 *)dp, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_int32x2 *)cp; + coef_align = AE_LA64_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Two coefficients + * are loaded simultaneously. Data is read + * from interleaved buffer with stride of channels + * count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients */ + AE_LA32X2_IP(coef10, coef_align, coefp); + AE_LA32X2_IP(coef32, coef_align, coefp); + + /* Load two data samples from two channels. Note: Due to + * polyphase array data start shift for sub-filters can't + * use 128 bits load due to align requirement. + */ + AE_L32X2_XC(f0, dp, inc); /* f0.h is left0, f0.l is right0 */ + AE_L32X2_XC(f1, dp, inc); /* f1.h is left1, f1.l is right1 */ + + /* a0 (left) += left10.h (left1) * coef10.h (coef2) + * += left10.l (left0) * coef10.l (coef1) + * a1 (right) += right10.h (right1) * coef10.h (coef2) + * += right10.l (right0) * coef10.l (coef1) + */ + sample10 = AE_SEL32_HH(f0, f1); + AE_MULAAFD32RA_HH_LL(a0, sample10, coef10); + sample10 = AE_SEL32_LL(f0, f1); + AE_MULAAFD32RA_HH_LL(a1, sample10, coef10); + + /* Repeat for next two taps */ + AE_L32X2_XC(f0, dp, inc); /* f0.h is left2, f0.l is right2 */ + AE_L32X2_XC(f1, dp, inc); /* f1.h is left3, f1.l is right3 */ + sample10 = AE_SEL32_HH(f0, f1); + AE_MULAAFD32RA_HH_LL(a0, sample10, coef32); + sample10 = AE_SEL32_LL(f0, f1); + AE_MULAAFD32RA_HH_LL(a1, sample10, coef32); + } + + /* Scale FIR output with right shifts, round/saturate + * to Q1.31, and store 32 bit output. + */ + f0 = AE_ROUND32X2F48SASYM(AE_SRAA64(a1, shift), AE_SRAA64(a0, shift)); + AE_S32X2_I(f0, (ae_int32x2 *)wp, 0); +} + +static inline void fir_filter(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift, + const int nch) +{ + ae_f64 a0 = AE_ZERO64(); + ae_valign coef_align; + ae_f32x2 coef32; + ae_f32x2 coef10; + ae_f32x2 sample10; + ae_f32x2 f0; + ae_f32x2 f1; + ae_int32x2 *coefp; + ae_f32 *dp; + ae_f32 *dp1 = rp; + ae_f32 *wp = wp0; + const int inc = nch * sizeof(int32_t); + int i; + int j; + + for (j = 0; j < nch; j++) { + /* Copy pointer and advance to next ch with dummy load */ + dp = dp1; + AE_L32_XC(f0, dp1, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_int32x2 *)cp; + a0 = AE_ZERO64(); + coef_align = AE_LA64_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Data is read from + * interleaved buffer with stride of channels count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients + * TODO: Ensure coefficients are 128 bits aligned + */ + AE_LA32X2_IP(coef10, coef_align, coefp); + AE_LA32X2_IP(coef32, coef_align, coefp); + + /* Load two data samples, place to high and + * low of data2. + */ + AE_L32_XC(f0, dp, inc); + AE_L32_XC(f1, dp, inc); + sample10 = AE_SEL32_LL(f0, f1); + + /* Accumulate to data2_h * coef2_h + + * data2_l*coef2_l. The Q1.31 bit data is used + * as Q1.23 from MSB side bits of the 32 bit + * word. The accumulator m is Q17.47. + */ + AE_MULAAFD32RA_HH_LL(a0, sample10, coef10); + + /* Repeat the same for next two filter taps */ + AE_L32_XC(f0, dp, inc); + AE_L32_XC(f1, dp, inc); + sample10 = AE_SEL32_LL(f0, f1); + AE_MULAAFD32RA_HH_LL(a0, sample10, coef32); + } + + /* Scale FIR output with right shifts, round/saturate Q17.47 + * to Q1.31, and store 32 bit output. Advance write + * pointer to next sample. + */ + f0 = AE_ROUND32F48SASYM(AE_SRAA64(a0, shift)); + AE_S32_L_XP(f0, wp, sizeof(int32_t)); + } +} + +#endif /* 32bit coefficients version */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +void src_polyphase_stage_cir(struct src_stage_prm *s) +{ + /* This function uses + * 1x 64 bit registers + * 16x integers + * 11x address pointers, + */ + ae_int32x2 q; + ae_f32 *rp; + ae_f32 *wp; + int i; + int n; + int m; + int n_wrap_buf; + int n_min; + struct src_state *fir = s->state; + const struct src_stage *cfg = s->stage; + int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; + int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; + const void *cp; /* Can be int32_t or int16_t */ + const size_t out_size = fir->out_delay_size * sizeof(int32_t); + const int nch = s->nch; + const int nch_x_odm = cfg->odm * nch; + const int blk_in_words = nch * cfg->blk_in; + const int blk_out_words = nch * cfg->num_of_subfilters; + const int sz = sizeof(int32_t); + const int n_sz = -sizeof(int32_t); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); + const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); + const int taps_div_4 = cfg->subfilter_length >> 2; + int32_t *x_rptr = (int32_t *)s->x_rptr; + int32_t *y_wptr = (int32_t *)s->y_wptr; + int32_t *x_end_addr = (int32_t *)s->x_end_addr; + int32_t *y_end_addr = (int32_t *)s->y_end_addr; + const size_t subfilter_size = cfg->subfilter_length * SRC_COEF_SIZE; + + for (n = 0; n < s->times; n++) { + /* Input data to filter */ + + /* Setup circular buffer for FIR input data delay */ + AE_SETCBEGIN0(fir->fir_delay); + AE_SETCEND0(fir_end); + + for (m = blk_in_words; m > 0; m -= n_min) { + /* Number of words until circular wrap */ + n_wrap_buf = x_end_addr - x_rptr; + n_min = MIN(m, n_wrap_buf); + for (i = 0; i < n_min; i++) { + /* Load 32 bits sample to accumulator, + * advance pointer, shift left with saturate. + */ + AE_L32_XP(q, (ae_int32 *)x_rptr, sz); + q = AE_SLAA32(q, s->shift); + + /* Store to circular buffer, advance pointer */ + AE_S32_L_XC(q, (ae_int32 *)fir->fir_wp, n_sz); + } + + /* Check for wrap */ + src_inc_wrap(&x_rptr, x_end_addr, s->x_size); + } + + /* Do filter */ + cp = cfg->coefs; /* Reset to 1st coefficient */ + rp = (ae_f32 *)fir->fir_wp; + + /* Do circular modification to pointer rp by amount of + * rewind to data start. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, rewind_sz); + + /* Reset FIR write pointer and compute all polyphase + * sub-filters. + */ + wp = (ae_f32 *)fir->out_rp; + if (nch == 2) { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter_2ch(rp, cp, wp, taps_div_4, cfg->shift); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + /* Circular advance pointer rp by number of channels x input + * delay multiplier. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } else { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter(rp, cp, wp, taps_div_4, cfg->shift, nch); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } + + /* Output */ + + /* Setup circular buffer for SRC out delay access */ + AE_SETCBEGIN0(fir->out_delay); + AE_SETCEND0(out_delay_end); + for (m = blk_out_words; m > 0; m -= n_min) { + n_wrap_buf = y_end_addr - y_wptr; + n_min = MIN(m, n_wrap_buf); + for (i = 0; i < n_min; i++) { + /* Circular load, shift right, linear store, + * and advance read and write pointers. + */ + AE_L32_XC(q, (ae_int32 *)fir->out_rp, sz); + q = AE_SRAA32(q, s->shift); + AE_S32_L_XP(q, (ae_int32 *)y_wptr, sz); + } + + /* Check wrap */ + src_inc_wrap(&y_wptr, y_end_addr, s->y_size); + } + } + s->x_rptr = x_rptr; + s->y_wptr = y_wptr; +} +#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +void src_polyphase_stage_cir_s16(struct src_stage_prm *s) +{ + /* This function uses + * 2x 64 bit registers + * 16x integers + * 11x address pointers, + */ + ae_int32x2 q = AE_ZERO32(); + ae_int16x4 d = AE_ZERO16(); + ae_f32 *rp; + ae_f32 *wp; + int i; + int n; + int m; + int n_wrap_buf; + int n_min; + + struct src_state *fir = s->state; + const struct src_stage *cfg = s->stage; + int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; + int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; + const void *cp; /* Can be int32_t or int16_t */ + const size_t out_size = fir->out_delay_size * sizeof(int32_t); + const int nch = s->nch; + const int nch_x_odm = cfg->odm * nch; + const int blk_in_words = nch * cfg->blk_in; + const int blk_out_words = nch * cfg->num_of_subfilters; + const int sz = sizeof(int32_t); + const int n_sz = -sizeof(int32_t); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); + const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); + const int taps_div_4 = cfg->subfilter_length >> 2; + int16_t *x_rptr = (int16_t *)s->x_rptr; + int16_t *y_wptr = (int16_t *)s->y_wptr; + int16_t *x_end_addr = (int16_t *)s->x_end_addr; + int16_t *y_end_addr = (int16_t *)s->y_end_addr; + const size_t subfilter_size = cfg->subfilter_length * SRC_COEF_SIZE; + + for (n = 0; n < s->times; n++) { + /* Input data */ + + /* Setup circular buffer for FIR input data delay */ + AE_SETCBEGIN0(fir->fir_delay); + AE_SETCEND0(fir_end); + for (m = blk_in_words; m > 0; m -= n_min) { + /* Number of words without circular wrap */ + n_wrap_buf = x_end_addr - x_rptr; + n_min = (m < n_wrap_buf) ? m : n_wrap_buf; + for (i = 0; i < n_min; i++) { + /* Load a 16 bits sample into d and left shift + * by 16 into q, advance read and write + * pointers. + */ + AE_L16_XP(d, (ae_int16 *)x_rptr, + sizeof(ae_int16)); + q = AE_CVT32X2F16_32(d); + AE_S32_L_XC(q, (ae_int32 *)fir->fir_wp, n_sz); + } + + /* Check for wrap */ + src_inc_wrap_s16(&x_rptr, x_end_addr, s->x_size); + } + + /* Do filter */ + cp = cfg->coefs; /* Reset to 1st coefficient */ + rp = (ae_f32 *)fir->fir_wp; + + /* Do circular modification to pointer rp by amount of + * rewind to data start. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, rewind_sz); + + /* Reset FIR output write pointer and compute all polyphase + * sub-filters. + */ + wp = (ae_f32 *)fir->out_rp; + if (nch == 2) { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter_2ch(rp, cp, wp, taps_div_4, cfg->shift); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + /* Circular advance pointer rp by number of channels x input delay + * multiplier. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } else { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter(rp, cp, wp, taps_div_4, cfg->shift, nch); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } + + /* Output */ + + /* Setup circular buffer for SRC out delay access */ + AE_SETCBEGIN0(fir->out_delay); + AE_SETCEND0(out_delay_end); + for (m = blk_out_words; m > 0; m -= n_min) { + n_wrap_buf = y_end_addr - y_wptr; + n_min = (m < n_wrap_buf) ? m : n_wrap_buf; + for (i = 0; i < n_min; i++) { + /* Circular load for 32 bit sample, + * advance read pointer. + */ + AE_L32_XC(q, (ae_int32 *)fir->out_rp, sz); + + /* Store Q1.31 value as Q1.15 and + * advance write pointer. + */ + d = AE_ROUND16X4F32SSYM(q, q); + AE_S16_0_XP(d, (ae_int16 *)y_wptr, + sizeof(ae_int16)); + } + + /* Check wrap */ + src_inc_wrap_s16(&y_wptr, y_end_addr, s->y_size); + } + } + s->x_rptr = x_rptr; + s->y_wptr = y_wptr; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#endif diff --git a/src/audio/src/src_hifi5.c b/src/audio/src/src_hifi5.c new file mode 100644 index 000000000000..0adfc4796d25 --- /dev/null +++ b/src/audio/src/src_hifi5.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Krzysztof Frydryk <krzysztofx.frydryk@intel.com> + +/* HiFi5 optimized code parts for SRC */ + +#include "src_config.h" + +#if SRC_HIFI5 + +#include "src_common.h" + +#include <sof/math/numbers.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi5.h> +#include <stddef.h> +#include <stdint.h> + +/* sof/math/numbers.h doesn't define MIN when used with zephyr */ +#ifdef __ZEPHYR__ +#include <zephyr/sys/util.h> +#endif /* __ZEPHYR__ */ + +#if SRC_SHORT +#define SRC_COEF_SIZE sizeof(int16_t) +#else +#define SRC_COEF_SIZE sizeof(int32_t) +#endif + +#if SRC_SHORT /* 16 bit coefficients version */ + +static inline void fir_filter_2ch(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift) +{ + /* This function uses + * 7x 64 bit registers + * 2x integers + * 3x address pointers, + */ + ae_f64 a0; + ae_f64 a1; + ae_valign u; + ae_f16x4 coef4; + ae_f32x2 d0; + ae_f32x2 d1; + ae_f32x2 data2; + ae_f16x4 *coefp; + ae_f32x2 *dp; + int i; + ae_f32 *wp = wp0; + const int inc = 2 * sizeof(int32_t); + + /* Move data pointer back by one sample to start from right + * channel sample. Discard read value p0. + */ + dp = (ae_f32x2 *)rp; + AE_L32_XC(d0, (ae_f32 *)dp, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_f16x4 *)cp; + a0 = AE_ZERO64(); + a1 = AE_ZERO64(); + u = AE_LA64_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Four coefficients + * are loaded simultaneously. Data is read + * from interleaved buffer with stride of channels + * count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients */ + AE_LA16X4_IP(coef4, u, coefp); + + /* Load two data samples from two channels */ + AE_L32X2_XC(d0, dp, inc); /* r0, l0 */ + AE_L32X2_XC(d1, dp, inc); /* r1, l1 */ + + /* Select to data2 sequential samples from a channel + * and then accumulate to a0 and a1 + * data2_h * coef4_3 + data2_l * coef4_2. + * The data is 32 bits Q1.31 and coefficient 16 bits + * Q1.15. The accumulators are Q17.47. + */ + data2 = AE_SEL32_LL(d0, d1); /* l0, l1 */ + AE_MULAAFD32X16_H3_L2(a0, data2, coef4); + data2 = AE_SEL32_HH(d0, d1); /* r0, r1 */ + AE_MULAAFD32X16_H3_L2(a1, data2, coef4); + + /* Load two data samples from two channels */ + AE_L32X2_XC(d0, dp, inc); /* r2, l2 */ + AE_L32X2_XC(d1, dp, inc); /* r3, l3 */ + + /* Accumulate + * data2_h * coef4_1 + data2_l * coef4_0. + */ + data2 = AE_SEL32_LL(d0, d1); /* l2, l3 */ + AE_MULAAFD32X16_H1_L0(a0, data2, coef4); + data2 = AE_SEL32_HH(d0, d1); /* r2, r3 */ + AE_MULAAFD32X16_H1_L0(a1, data2, coef4); + } + + /* Scale FIR output with right shifts, round/saturate + * to Q1.31, and store 32 bit output. + */ + AE_S32_L_XP(AE_ROUND32F48SSYM(AE_SRAA64(a0, shift)), wp, sizeof(int32_t)); + AE_S32_L_XP(AE_ROUND32F48SSYM(AE_SRAA64(a1, shift)), wp, sizeof(int32_t)); +} + +static inline void fir_filter(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift, + const int nch) +{ + /* This function uses + * 6x 64 bit registers + * 3x integers + * 3x address pointers, + */ + ae_f64 a0; + ae_valign u; + ae_f16x4 coef4; + ae_f32x2 d0; + ae_f32x2 d1; + ae_f32x2 data2; + ae_f16x4 *coefp; + ae_f32 *dp0; + ae_f32 *dp1; + int i; + int j; + ae_f32 *wp = wp0; + const int inc = nch * sizeof(int32_t); + + dp1 = (ae_f32 *)rp; + for (j = 0; j < nch; j++) { + /* Copy pointer and advance to next ch with dummy load */ + dp0 = dp1; + AE_L32_XC(d0, dp1, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_f16x4 *)cp; + a0 = AE_ZERO64(); + u = AE_LA64_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Data is read from + * interleaved buffer with stride of channels count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients */ + AE_LA16X4_IP(coef4, u, coefp); + + /* Load two data samples, place to high and + * low of data2. + */ + AE_L32_XC(d0, dp0, inc); + AE_L32_XC(d1, dp0, inc); + data2 = AE_SEL32_LL(d0, d1); + + /* Accumulate + * data2_h * coef4_3 + data2_l* coef4_2. + * The data is 32 bits Q1.31 and coefficient 16 bits + * Q1.15. The accumulator is Q17.47. + */ + AE_MULAAFD32X16_H3_L2(a0, data2, coef4); + + /* Repeat with next two samples */ + AE_L32_XC(d0, dp0, inc); + AE_L32_XC(d1, dp0, inc); + data2 = AE_SEL32_LL(d0, d1); + + /* Accumulate + * data2_h * coef4_1 + data2_l * coef4_0. + */ + AE_MULAAFD32X16_H1_L0(a0, data2, coef4); + } + + /* Scale FIR output with right shifts, round/saturate Q17.47 + * to Q1.31, and store 32 bit output. Advance write + * pointer to next sample. + */ + AE_S32_L_XP(AE_ROUND32F48SSYM(AE_SRAA64(a0, shift)), wp, + sizeof(int32_t)); + } +} + +#else /* 32bit coefficients version */ + +static inline void fir_filter_2ch(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift) +{ + ae_valignx2 coef_align; + ae_f64 a0 = AE_ZERO64(); + ae_f64 a1 = AE_ZERO64(); + ae_f32x2 coef32; + ae_f32x2 coef10; + ae_f32x2 left10; + ae_f32x2 right10; + ae_f32x2 f0; + ae_f32x2 f1; + ae_int32x4 *coefp; + ae_f32x2 *dp; + ae_f32 *wp = wp0; + const int inc = 2 * sizeof(int32_t); + int i; + + /* Move data pointer back by one sample to start from right + * channel sample. Discard read value p0. + */ + dp = (ae_f32x2 *)rp; + AE_L32_XC(f0, (ae_f32 *)dp, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_int32x4 *)cp; + coef_align = AE_LA128_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Two coefficients + * are loaded simultaneously. Data is read + * from interleaved buffer with stride of channels + * count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients */ + AE_LA32X2X2_IP(coef10, coef32, coef_align, coefp); + + /* Load two data samples from two channels. Note: Due to + * polyphase array data start shift for sub-filters can't + * use 128 bits load due to align requirement. + */ + AE_L32X2_XC(f0, dp, inc); /* f0.h is left0, f0.l is right0 */ + AE_L32X2_XC(f1, dp, inc); /* f1.h is left1, f1.l is right1 */ + + /* a0 (left) += left10.h (left1) * coef10.h (coef2) + * += left10.l (left0) * coef10.l (coef1) + * a1 (right) += right10.h (right1) * coef10.h (coef2) + * += right10.l (right0) * coef10.l (coef1) + */ + left10 = AE_SEL32_HH(f0, f1); + right10 = AE_SEL32_LL(f0, f1); + AE_MULAAF2D32RA_HH_LL(a0, a1, left10, right10, coef10, coef10); + + /* Repeat for next two taps */ + AE_L32X2_XC(f0, dp, inc); /* f0.h is left2, f0.l is right2 */ + AE_L32X2_XC(f1, dp, inc); /* f1.h is left3, f1.l is right3 */ + left10 = AE_SEL32_HH(f0, f1); + right10 = AE_SEL32_LL(f0, f1); + AE_MULAAF2D32RA_HH_LL(a0, a1, left10, right10, coef32, coef32); + } + + /* Scale FIR output with right shifts, round/saturate + * to Q1.31, and store 32 bit output. + */ + f0 = AE_ROUND32X2F48SASYM(AE_SRAA64(a1, shift), AE_SRAA64(a0, shift)); + AE_S32X2_I(f0, (ae_int32x2 *)wp, 0); +} + +static inline void fir_filter(ae_f32 *rp, const void *cp, ae_f32 *wp0, + const int taps_div_4, const int shift, + const int nch) +{ + ae_valignx2 coef_align; + ae_f64 a0 = AE_ZERO64(); + ae_f32x2 coef32; + ae_f32x2 coef10; + ae_f32x2 sample10; + ae_f32x2 f0; + ae_f32x2 f1; + ae_int32x4 *coefp; + ae_f32 *dp; + ae_f32 *dp1 = rp; + ae_f32 *wp = wp0; + const int inc = nch * sizeof(int32_t); + int i; + int j; + + for (j = 0; j < nch; j++) { + /* Copy pointer and advance to next ch with dummy load */ + dp = dp1; + AE_L32_XC(f0, dp1, -sizeof(ae_f32)); + + /* Reset coefficient pointer and clear accumulator */ + coefp = (ae_int32x4 *)cp; + a0 = AE_ZERO64(); + coef_align = AE_LA128_PP(coefp); + + /* Compute FIR filter for current channel with four + * taps per every loop iteration. Data is read from + * interleaved buffer with stride of channels count. + */ + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients + * TODO: Ensure coefficients are 128 bits aligned + */ + AE_LA32X2X2_IP(coef10, coef32, coef_align, coefp); + + /* Load two data samples, place to high and + * low of data2. + */ + AE_L32_XC(f0, dp, inc); + AE_L32_XC(f1, dp, inc); + sample10 = AE_SEL32_LL(f0, f1); + + /* Accumulate to data2_h * coef2_h + + * data2_l*coef2_l. The Q1.31 bit data is used + * as Q1.23 from MSB side bits of the 32 bit + * word. The accumulator m is Q17.47. + */ + AE_MULAAFD32RA_HH_LL(a0, sample10, coef10); + + /* Repeat the same for next two filter taps */ + AE_L32_XC(f0, dp, inc); + AE_L32_XC(f1, dp, inc); + sample10 = AE_SEL32_LL(f0, f1); + AE_MULAAFD32RA_HH_LL(a0, sample10, coef32); + } + + /* Scale FIR output with right shifts, round/saturate Q17.47 + * to Q1.31, and store 32 bit output. Advance write + * pointer to next sample. + */ + f0 = AE_ROUND32F48SASYM(AE_SRAA64(a0, shift)); + AE_S32_L_XP(f0, wp, sizeof(int32_t)); + } +} + +#endif /* 32bit coefficients version */ + +#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE +void src_polyphase_stage_cir(struct src_stage_prm *s) +{ + /* This function uses + * 1x 64 bit registers + * 16x integers + * 11x address pointers, + */ + ae_int32x2 q; + ae_f32 *rp; + ae_f32 *wp; + int i; + int n; + int m; + int n_wrap_buf; + int n_min; + struct src_state *fir = s->state; + const struct src_stage *cfg = s->stage; + int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; + int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; + const void *cp; /* Can be int32_t or int16_t */ + const size_t out_size = fir->out_delay_size * sizeof(int32_t); + const int nch = s->nch; + const int nch_x_odm = cfg->odm * nch; + const int blk_in_words = nch * cfg->blk_in; + const int blk_out_words = nch * cfg->num_of_subfilters; + const int sz = sizeof(int32_t); + const int n_sz = -sizeof(int32_t); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); + const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); + const int taps_div_4 = cfg->subfilter_length >> 2; + int32_t *x_rptr = (int32_t *)s->x_rptr; + int32_t *y_wptr = (int32_t *)s->y_wptr; + int32_t *x_end_addr = (int32_t *)s->x_end_addr; + int32_t *y_end_addr = (int32_t *)s->y_end_addr; + const size_t subfilter_size = cfg->subfilter_length * SRC_COEF_SIZE; + + for (n = 0; n < s->times; n++) { + /* Input data to filter */ + + /* Setup circular buffer for FIR input data delay */ + AE_SETCBEGIN0(fir->fir_delay); + AE_SETCEND0(fir_end); + + for (m = blk_in_words; m > 0; m -= n_min) { + /* Number of words until circular wrap */ + n_wrap_buf = x_end_addr - x_rptr; + n_min = MIN(m, n_wrap_buf); + for (i = 0; i < n_min; i++) { + /* Load 32 bits sample to accumulator, + * advance pointer, shift left with saturate. + */ + AE_L32_XP(q, (ae_int32 *)x_rptr, sz); + q = AE_SLAA32(q, s->shift); + + /* Store to circular buffer, advance pointer */ + AE_S32_L_XC(q, (ae_int32 *)fir->fir_wp, n_sz); + } + + /* Check for wrap */ + src_inc_wrap(&x_rptr, x_end_addr, s->x_size); + } + + /* Do filter */ + cp = cfg->coefs; /* Reset to 1st coefficient */ + rp = (ae_f32 *)fir->fir_wp; + + /* Do circular modification to pointer rp by amount of + * rewind to data start. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, rewind_sz); + + /* Reset FIR write pointer and compute all polyphase + * sub-filters. + */ + wp = (ae_f32 *)fir->out_rp; + if (nch == 2) { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter_2ch(rp, cp, wp, taps_div_4, cfg->shift); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + /* Circular advance pointer rp by number of channels x input + * delay multiplier. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } else { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter(rp, cp, wp, taps_div_4, cfg->shift, nch); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } + + /* Output */ + + /* Setup circular buffer for SRC out delay access */ + AE_SETCBEGIN0(fir->out_delay); + AE_SETCEND0(out_delay_end); + for (m = blk_out_words; m > 0; m -= n_min) { + n_wrap_buf = y_end_addr - y_wptr; + n_min = MIN(m, n_wrap_buf); + for (i = 0; i < n_min; i++) { + /* Circular load, shift right, linear store, + * and advance read and write pointers. + */ + AE_L32_XC(q, (ae_int32 *)fir->out_rp, sz); + q = AE_SRAA32(q, s->shift); + AE_S32_L_XP(q, (ae_int32 *)y_wptr, sz); + } + + /* Check wrap */ + src_inc_wrap(&y_wptr, y_end_addr, s->y_size); + } + } + s->x_rptr = x_rptr; + s->y_wptr = y_wptr; +} +#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +void src_polyphase_stage_cir_s16(struct src_stage_prm *s) +{ + /* This function uses + * 2x 64 bit registers + * 16x integers + * 11x address pointers, + */ + ae_int32x2 q = AE_ZERO32(); + ae_int16x4 d = AE_ZERO16(); + ae_f32 *rp; + ae_f32 *wp; + int i; + int n; + int m; + int n_wrap_buf; + int n_min; + + struct src_state *fir = s->state; + const struct src_stage *cfg = s->stage; + int32_t *fir_end = &fir->fir_delay[fir->fir_delay_size]; + int32_t *out_delay_end = &fir->out_delay[fir->out_delay_size]; + const void *cp; /* Can be int32_t or int16_t */ + const size_t out_size = fir->out_delay_size * sizeof(int32_t); + const int nch = s->nch; + const int nch_x_odm = cfg->odm * nch; + const int blk_in_words = nch * cfg->blk_in; + const int blk_out_words = nch * cfg->num_of_subfilters; + const int sz = sizeof(int32_t); + const int n_sz = -sizeof(int32_t); + const int rewind_sz = sz * nch * (cfg->blk_in + (cfg->num_of_subfilters - 1) * cfg->idm); + const int nch_x_idm_sz = -nch * cfg->idm * sizeof(int32_t); + const int taps_div_4 = cfg->subfilter_length >> 2; + int16_t *x_rptr = (int16_t *)s->x_rptr; + int16_t *y_wptr = (int16_t *)s->y_wptr; + int16_t *x_end_addr = (int16_t *)s->x_end_addr; + int16_t *y_end_addr = (int16_t *)s->y_end_addr; + const size_t subfilter_size = cfg->subfilter_length * SRC_COEF_SIZE; + + for (n = 0; n < s->times; n++) { + /* Input data */ + + /* Setup circular buffer for FIR input data delay */ + AE_SETCBEGIN0(fir->fir_delay); + AE_SETCEND0(fir_end); + for (m = blk_in_words; m > 0; m -= n_min) { + /* Number of words without circular wrap */ + n_wrap_buf = x_end_addr - x_rptr; + n_min = (m < n_wrap_buf) ? m : n_wrap_buf; + for (i = 0; i < n_min; i++) { + /* Load a 16 bits sample into d and left shift + * by 16 into q, advance read and write + * pointers. + */ + AE_L16_XP(d, (ae_int16 *)x_rptr, + sizeof(ae_int16)); + q = AE_CVT32X2F16_32(d); + AE_S32_L_XC(q, (ae_int32 *)fir->fir_wp, n_sz); + } + + /* Check for wrap */ + src_inc_wrap_s16(&x_rptr, x_end_addr, s->x_size); + } + + /* Do filter */ + cp = cfg->coefs; /* Reset to 1st coefficient */ + rp = (ae_f32 *)fir->fir_wp; + + /* Do circular modification to pointer rp by amount of + * rewind to data start. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, rewind_sz); + + /* Reset FIR output write pointer and compute all polyphase + * sub-filters. + */ + wp = (ae_f32 *)fir->out_rp; + if (nch == 2) { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter_2ch(rp, cp, wp, taps_div_4, cfg->shift); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + /* Circular advance pointer rp by number of channels x input delay + * multiplier. Loaded value q is discarded. + */ + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } else { + for (i = 0; i < cfg->num_of_subfilters; i++) { + fir_filter(rp, cp, wp, taps_div_4, cfg->shift, nch); + wp += nch_x_odm; + cp = (uint8_t *)cp + subfilter_size; + src_inc_wrap((int32_t **)&wp, out_delay_end, out_size); + AE_L32_XC(q, rp, nch_x_idm_sz); + } + } + + /* Output */ + + /* Setup circular buffer for SRC out delay access */ + AE_SETCBEGIN0(fir->out_delay); + AE_SETCEND0(out_delay_end); + for (m = blk_out_words; m > 0; m -= n_min) { + n_wrap_buf = y_end_addr - y_wptr; + n_min = (m < n_wrap_buf) ? m : n_wrap_buf; + for (i = 0; i < n_min; i++) { + /* Circular load for 32 bit sample, + * advance read pointer. + */ + AE_L32_XC(q, (ae_int32 *)fir->out_rp, sz); + + /* Store Q1.31 value as Q1.15 and + * advance write pointer. + */ + d = AE_ROUND16X4F32SSYM(q, q); + AE_S16_0_XP(d, (ae_int16 *)y_wptr, + sizeof(ae_int16)); + } + + /* Check wrap */ + src_inc_wrap_s16(&y_wptr, y_end_addr, s->y_size); + } + } + s->x_rptr = x_rptr; + s->y_wptr = y_wptr; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#endif diff --git a/src/audio/src/src_ipc.h b/src/audio/src/src_ipc.h new file mode 100644 index 000000000000..cd6fdb6af3a2 --- /dev/null +++ b/src/audio/src/src_ipc.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017-2024 Intel Corporation + */ + +#ifndef __SOF_AUDIO_SRC_SRC_IPC_H__ +#define __SOF_AUDIO_SRC_SRC_IPC_H__ + +#include <sof/audio/ipc-config.h> +#include <ipc4/base-config.h> +#include <stdint.h> + +/* src component private data */ +struct ipc4_config_src { + struct ipc4_base_module_cfg base; + uint32_t sink_rate; +}; + +#endif /* __SOF_AUDIO_SRC_SRC_IPC_H__ */ diff --git a/src/audio/src/src_ipc3.c b/src/audio/src/src_ipc3.c new file mode 100644 index 000000000000..541efcdb24be --- /dev/null +++ b/src/audio/src/src_ipc3.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/sink_source_utils.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/base-config.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <limits.h> + +#include "src_common.h" +#include "src_config.h" + +SOF_DEFINE_REG_UUID(src); + +DECLARE_TR_CTX(src_tr, SOF_UUID(src_uuid), LOG_LEVEL_INFO); + +LOG_MODULE_DECLARE(src, CONFIG_SOF_LOG_LEVEL); + +int src_rate_check(const void *spec) +{ + const struct ipc_config_src *ipc_src = spec; + + if (ipc_src->source_rate == 0 && ipc_src->sink_rate == 0) + return -EINVAL; + + return 0; +} + +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; +} + +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; +} + +int src_set_params(struct processing_module *mod, struct sof_sink *sink) +{ + return 0; +} + +void src_get_source_sink_params(struct comp_dev *dev, struct sof_source *source, + struct sof_sink *sink) +{ + struct processing_module *mod = comp_mod(dev); + struct comp_data *cd = module_get_private_data(mod); + + /* Set source/sink_rate/frames */ + cd->channels_count = source_get_channels(source); + cd->source_rate = source_get_rate(source); + cd->sink_rate = sink_get_rate(sink); + cd->sample_container_bytes = mod->stream_params->sample_container_bytes; +} + +int src_prepare_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret = 0; + enum sof_ipc_frame source_format; + enum sof_ipc_frame sink_format; + + /* set align requirements */ + src_set_alignment(source); + + /* get source/sink data format */ + source_format = source_get_frm_fmt(source); + sink_format = sink_get_frm_fmt(sink); + + /* SRC supports S16_LE, S24_4LE and S32_LE formats */ + if (source_format != sink_format) { + comp_err(dev, "Source fmt %d and sink fmt %d are different.", + source_format, sink_format); + ret = -EINVAL; + goto out; + } + + switch (source_format) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir_s16; + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + cd->data_shift = 8; + cd->polyphase_func = src_polyphase_stage_cir; + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir; + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(dev, "invalid format %d", source_format); + ret = -EINVAL; + goto out; + } + +out: + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + return ret; +} + +int src_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct module_config *cfg = &md->cfg; + struct comp_dev *dev = mod->dev; + struct comp_data *cd = NULL; + + comp_dbg(dev, "entry"); + + if (dev->ipc_config.type != SOF_COMP_SRC) { + comp_err(dev, "Wrong IPC config type %u", + dev->ipc_config.type); + return -EINVAL; + } + + if (!cfg->init_data || cfg->size != sizeof(cd->ipc_config)) { + comp_err(dev, "Missing or bad size (%zu) init data", + cfg->size); + return -EINVAL; + } + + /* validate init data - either SRC sink or source rate must be set */ + if (src_rate_check(cfg->init_data) < 0) { + comp_err(dev, "SRC sink and source rate are not set"); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(*cd)); + 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; + cd->src_func = src_fallback; + cd->polyphase_func = NULL; + src_polyphase_reset(&cd->src); + + mod->verify_params_flags = BUFF_PARAMS_RATE; + + return 0; +} + diff --git a/src/audio/src/src_ipc4.c b/src/audio/src/src_ipc4.c new file mode 100644 index 000000000000..91f286347a5f --- /dev/null +++ b/src/audio/src/src_ipc4.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc4/base-config.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <limits.h> + +#include "src_common.h" +#include "src_config.h" + +SOF_DEFINE_REG_UUID(src4); + +DECLARE_TR_CTX(src_tr, SOF_UUID(src4_uuid), LOG_LEVEL_INFO); + +LOG_MODULE_DECLARE(src, CONFIG_SOF_LOG_LEVEL); + +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) + return -EINVAL; + + return 0; +} + +int src_stream_pcm_source_rate_check(struct ipc4_config_src cfg, + struct sof_ipc_stream_params *params) +{ + /* Nothing to check */ + return 0; +} + +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; +} + +/* In ipc4 case param is figured out by module config so we need to first + * set up param then verify param. BTW for IPC3 path, the param is sent by + * host driver. + */ +int src_set_params(struct processing_module *mod, struct sof_sink *sink) +{ + 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; + 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; + + /* 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 = valid_fmt; + ret = sink_set_params(sink, &src_params, true); + if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + /* if module is to be run as DP, calculate module period + * according to OBS size and data rate + * as SRC uses period value to calculate its internal buffers, + * it must be done here, right after setting sink parameters + * + * calculate period using 64bit integer to avoid overflows + */ + dev->period = 1000000ULL * sink_get_min_free_space(sink) / + (sink_get_frame_bytes(sink) * sink_get_rate(sink)); + /* align down period to LL cycle time */ + dev->period /= LL_TIMER_PERIOD_US; + dev->period *= LL_TIMER_PERIOD_US; + + comp_info(dev, "SRC DP period calculated as: %u us", dev->period); + } + + component_set_nearest_period_frames(dev, src_params.rate); + /* Update module stream_params */ + params->rate = cd->ipc_config.sink_rate; + return ret; +} + +void src_get_source_sink_params(struct comp_dev *dev, struct sof_source *source, + struct sof_sink *sink) +{ + struct processing_module *mod = comp_mod(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, + &frame_fmt, &valid_fmt, + cd->ipc_config.base.audio_fmt.s_type); + sink_set_frm_fmt(sink, frame_fmt); + sink_set_valid_fmt(sink, valid_fmt); + sink_set_channels(sink, cd->ipc_config.base.audio_fmt.channels_count); + sink_set_buffer_fmt(sink, cd->ipc_config.base.audio_fmt.interleaving_style); + sink_set_rate(sink, cd->ipc_config.sink_rate); +} + +int src_prepare_general(struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret = 0; + + /* set align requirements */ + src_set_alignment(source); + + switch (cd->ipc_config.base.audio_fmt.valid_bit_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, "Invalid depth %d", + cd->ipc_config.base.audio_fmt.depth); + ret = -EINVAL; + goto out; + } + +out: + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + return ret; +} + +__cold int src_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct module_config *cfg = &md->cfg; + struct comp_dev *dev = mod->dev; + struct comp_data *cd = NULL; + + assert_can_be_cold(); + + comp_dbg(dev, "entry"); + + if (!cfg->init_data || cfg->size != sizeof(cd->ipc_config)) { + comp_err(dev, "Missing or bad size (%u) init data", + cfg->size); + return -EINVAL; + } + + /* validate init data - either SRC sink or source rate must be set */ + if (src_rate_check(cfg->init_data) < 0) { + comp_err(dev, "SRC sink and source rate are not set"); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(*cd)); + 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; + cd->src_func = src_fallback; + cd->polyphase_func = NULL; + src_polyphase_reset(&cd->src); + + comp_dbg(dev, "channels_count = %d, depth = %d", + cd->ipc_config.base.audio_fmt.channels_count, + cd->ipc_config.base.audio_fmt.depth); + comp_dbg(dev, "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, "Illegal sample depth %d", + cd->ipc_config.base.audio_fmt.depth); + return -EINVAL; + } + + return 0; +} + diff --git a/src/audio/src/src_lite.c b/src/audio/src/src_lite.c new file mode 100644 index 000000000000..9d5593ff34ca --- /dev/null +++ b/src/audio/src/src_lite.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Fabiola Jasinska <fabiola.jasinska@intel.com> + +#include <rtos/init.h> + +#include "src_common.h" +#include "src_config.h" + +#include "coef/src_lite_int32_define.h" +#include "coef/src_lite_int32_table.h" + +LOG_MODULE_REGISTER(src_lite, CONFIG_SOF_LOG_LEVEL); + +/* + * This function is 100% identical to src_prepare(), but it's + * assigning different coefficient arrays because it's including + * different headers. + */ +static int src_lite_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + struct src_param *a = &cd->param; + int ret; + + comp_info(mod->dev, "entry"); + + if (num_of_sources != 1 || num_of_sinks != 1) + return -EINVAL; + + a->in_fs = src_in_fs; + a->out_fs = src_out_fs; + a->num_in_fs = NUM_IN_FS; + a->num_out_fs = NUM_OUT_FS; + a->max_fir_delay_size_xnch = (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE); + a->max_out_delay_size_xnch = (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE); + + ret = src_param_set(mod->dev, cd); + if (ret < 0) + return ret; + + ret = src_allocate_copy_stages(mod, a, + src_table1[a->idx_out][a->idx_in], + src_table2[a->idx_out][a->idx_in]); + if (ret < 0) + return ret; + + ret = src_params_general(mod, sources[0], sinks[0]); + if (ret < 0) + return ret; + + return src_prepare_general(mod, sources[0], sinks[0]); +} + +const struct module_interface src_lite_interface = { + .init = src_init, + .prepare = src_lite_prepare, + .process = src_process, + .is_ready_to_process = src_is_ready_to_process, + .reset = src_reset, + .free = src_free, +}; + +SOF_DEFINE_REG_UUID(src_lite); + +DECLARE_TR_CTX(src_lite_tr, SOF_UUID(src_lite_uuid), LOG_LEVEL_INFO); + +#if !CONFIG_COMP_SRC_MODULE +DECLARE_MODULE_ADAPTER(src_lite_interface, src_lite_uuid, src_lite_tr); +SOF_MODULE_INIT(src_lite, sys_comp_module_src_lite_interface_init); +#endif diff --git a/src/audio/src/tune/README b/src/audio/src/tune/README new file mode 100644 index 000000000000..ad90d7098fc3 --- /dev/null +++ b/src/audio/src/tune/README @@ -0,0 +1,36 @@ +Sample rate converter (SRC) Setup Tools +======================================= + +This is a tool to set up SRC conversions sample rates list, define +quality related parameters, and test the C implementation for a number +of objective audio quality parameters. + +The tools need GNU Octave version 4.0.0 or later with octave-signal +package. + +sof_src_std_int32.m +------------------- + +This script creates the default coefficient set and contains nothing +else but call for src_generate. + +sof_src_tiny_int16.m +-------------------- + +This script creates the tiny coefficient set. The script contains an +example how to customize the input/output rates matrix and in a simple +way the scale conversions quality. More controlled quality adjust can +be done by editing file src_param.m directly. Note that int16 +presentation for SRC coefficients will degrade even the default +quality. + +sof_src_generate.m +------------------ + +Creates the header files to include to C into directory "include". A +report of create modes is written to directory "reports". The +coefficients need to be copied to directory +sof.git/src/include/sof/audio/coefficients/src. + +The default quality of SRC is defined in module src_param.m. The +quality impacts the complexity and coefficients tables size of SRC. diff --git a/src/audio/src/tune/sof_src_generate.m b/src/audio/src/tune/sof_src_generate.m new file mode 100644 index 000000000000..85f79c94c9f6 --- /dev/null +++ b/src/audio/src/tune/sof_src_generate.m @@ -0,0 +1,472 @@ +function sof_src_generate(fs_in, fs_out, fs_inout, cfg); + +% sof_src_generate - export src conversions for given fs_in and fs_out +% +% sof_src_generate(fs_in, fs_out <, fs_inout, <cfg>>) +% +% fs_in - vector of input sample rates (M) +% fs_out - vector of output sample rates (N) +% fs_inout - matrix of supported conversions (MxN), +% 0 = no support, 1 = supported +% cfg - configuration struct with fields +% ctype - coefficient type, use 'int16','int24', 'int32', or 'float' +% profile - differentiate set with identifier, e.g. 'std' +% quality - quality factor, usually 1.0 +% speed - optimize speed, gives higher RAM size, usually 0 +% gain - overal filter gain, defaults to -1 dB if empty +% +% If fs_inout matrix is omitted this script will compute coefficients +% for all fs_in <-> fs_out combinations. +% +% If cfg is omitted the script will assume 'int32', 'std', 1.0, 0. +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2024, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +src_paths(1); + +if (nargin < 2) || (nargin > 4) + error('Incorrect arguments for function!'); +end +if nargin < 4 + cfg.ctype = 'int32'; + cfg.profile = 'std'; + cfg.quality = 1.0; + cfg.speed = 0; + cfg.gain = -1; + cfg.thdn = -90; +end +if nargin < 3 + fs_inout = ones(length(fs_in), length(fs_out)); +end + +sio = size(fs_inout); +if (length(fs_in) ~= sio(1)) || (length(fs_out) ~= sio(2)) + error('Sample rates in/out matrix size mismatch!'); +end + +if exist('OCTAVE_VERSION', 'builtin') + pkg load signal +end + + +%% Exported coefficients type int16, int24, int32, float + +switch cfg.ctype + case 'int16' + coef_label = 'int16'; + coef_ctype = 'int16_t'; + coef_bits = 16; + coef_bytes = 2; + case 'int24' + coef_label = 'int24'; + coef_ctype = 'int32_t'; + coef_bits = 24; + coef_bytes = 4; + case 'int32' + coef_label = 'int32'; + coef_ctype = 'int32_t'; + coef_bits = 32; + coef_bytes = 4; + case 'float' + coef_label = 'float'; + coef_ctype = 'float'; + coef_bits = 24; + coef_bytes = 4; + otherwise + error('Request for incorrect coefficient type'); +end +data_bytes = 4; + +hdir = mkdir_check('include'); +rdir = mkdir_check('reports'); + +%% Find fractional conversion factors +nfsi = length(fs_in); +nfso = length(fs_out); +l_2s = zeros(2, nfsi, nfso); +m_2s = zeros(2, nfsi, nfso); +mops_2s = zeros(2, nfsi, nfso); +pb_2s = zeros(2,nfsi, nfso); +sb_2s = zeros(2,nfsi, nfso); +taps_2s = zeros(2,nfsi, nfso); +defs.fir_delay_size = 0; +defs.out_delay_size = 0; +defs.blk_in = 0; +defs.blk_out = 0; +defs.num_in_fs = nfsi; +defs.num_out_fs = nfso; +defs.stage1_times_max = 0; +defs.stage2_times_max = 0; +defs.stage_buf_size = 0; +tbl.data = []; +tbl.idx = 0; +for pass = 1:2 + for b = 1:nfso + for a = 1:nfsi + fs1 = fs_in(a); + fs2 = fs_out(b); + if fs_inout(a,b) < eps + continue; + end + + [l1, m1, l2, m2] = src_factor2_lm(fs1, fs2); + % If the interpolate/decimate factors are low, use single step + % conversion. The increases RAM consumption but lowers the MCPS. + if cfg.speed && max(l1 * l2, m1 * m2) < 30 + l1 = l1 * l2; + l2 = 1; + m1 = m1 * m2; + m2 = 1; + end + fs3 = fs1 * l1 / m1; + cnv1 = src_param(fs1, fs3, coef_bits, cfg.quality, cfg.gain); + cnv2 = src_param(fs3, fs2, coef_bits, cfg.quality, cfg.gain); + if (fs2 < fs1) + % When decimating 1st stage passband can be limited + % for wider transition band + f_pb = fs2 * cnv2.c_pb; + cnv1.c_pb = f_pb / min(fs1, fs3); + end + if (fs2 > fs1) + % When interpolating 2nd stage passband can be limited + % for wider transition band + f_pb = fs1 * cnv1.c_pb; + cnv2.c_pb = f_pb / min(fs2, fs3); + end + if pass == 1 + src1 = src_get(cnv1); + src2 = src_get(cnv2); + delta = test_proto_src(src1, src2, cfg); + big_step = 0; + if delta > 0 + big_step = delta; + fprintf(1, 'Increase attenuation by %.1f dB\n', big_step); + cnv1.rs = cnv1.rs + big_step; + cnv2.rs = cnv2.rs + big_step; + src1 = src_get(cnv1); + src2 = src_get(cnv2); + delta = test_proto_src(src1, src2, cfg); + end + if big_step + while delta < -1.5 + rs_step = -1; + fprintf(1, 'Step attenuation by %.1f dB\n', rs_step); + cnv1.rs = cnv1.rs + rs_step; + cnv2.rs = cnv2.rs + rs_step; + src1 = src_get(cnv1); + src2 = src_get(cnv2); + delta = test_proto_src(src1, src2, cfg); + end + while delta > 0 + rs_step = 1; + fprintf(1, 'Increase attenuation by %.1f dB\n', rs_step); + cnv1.rs = cnv1.rs + rs_step; + cnv2.rs = cnv2.rs + rs_step; + src1 = src_get(cnv1); + src2 = src_get(cnv2); + delta = test_proto_src(src1, src2, cfg); + end + end + tbl = export_check(src1, tbl, coef_label, coef_ctype, hdir, cfg); + tbl = export_check(src2, tbl, coef_label, coef_ctype, hdir, cfg); + else + src1 = export_get(l1, m1, cnv1, tbl); + src2 = export_get(l2, m2, cnv2, tbl); + fs2_check = fs1 * src1.L / src1.M * src2.L / src2.M; + if abs(fs2 - fs2_check) > eps + error('Something went wrong.'); + end + k = gcd(src1.blk_out, src2.blk_in); + stage1_times = src2.blk_in/k; + stage2_times = stage1_times * src1.blk_out / src2.blk_in; + defs.stage1_times_max = max(defs.stage1_times_max, stage1_times); + defs.stage2_times_max = max(defs.stage2_times_max, stage2_times); + l_2s(:,a,b) = [src1.L src2.L]; + m_2s(:,a,b) = [src1.M src2.M]; + mops_2s(:,a,b) = [src1.MOPS src2.MOPS]; + pb_2s(:,a,b) = [src1.c_pbi src2.c_pbi]; + sb_2s(:,a,b) = [src1.c_sbi src2.c_sbi]; + taps_2s(:,a,b) = [src1.filter_length src2.filter_length]; + defs.fir_delay_size = max(defs.fir_delay_size, src1.fir_delay_size); + defs.out_delay_size = max(defs.out_delay_size, src1.out_delay_size); + defs.blk_in = max(defs.blk_in, src1.blk_in); + defs.blk_out = max(defs.blk_out, src1.blk_out); + defs.fir_delay_size = max(defs.fir_delay_size, src2.fir_delay_size); + defs.out_delay_size = max(defs.out_delay_size, src2.out_delay_size); + defs.blk_in = max(defs.blk_in, src2.blk_in); + defs.blk_out = max(defs.blk_out, src2.blk_out); + defs.stage_buf_size = max(defs.stage_buf_size, src1.blk_out * stage1_times); + end + end % a + end % b +end % pass + +%% Export modes table +defs.sum_filter_lengths = src_export_table_2s(fs_in, fs_out, l_2s, m_2s, ... + pb_2s, sb_2s, taps_2s, coef_label, coef_ctype, ... + 'sof/audio/coefficients/src/', hdir, cfg.profile); +src_export_defines(defs, coef_label, hdir, cfg.profile); + +%% Print 2 stage conversion factors +fn = sprintf('%s/src_2stage.txt', rdir); +fh = fopen(fn,'w'); +fprintf(fh,'\n'); +fprintf(fh,'Dual stage fractional SRC: Ratios\n'); +fprintf(fh,'%8s, ', 'in \ out'); +for b = 1:nfso + fprintf(fh,'%12.1f, ', fs_out(b)/1e3); +end +fprintf(fh,'\n'); +for a = 1:nfsi + fprintf(fh,'%8.1f, ', fs_in(a)/1e3); + for b = 1:nfso + cstr = print_ratios(l_2s, m_2s, a, b); + fprintf(fh,'%12s, ', cstr); + end + fprintf(fh,'\n'); +end +fprintf(fh,'\n'); + +%% Print 2 stage MOPS +fprintf(fh,'Dual stage fractional SRC: MOPS\n'); +fprintf(fh,'%8s, ', 'in \ out'); +for b = 1:nfso + fprintf(fh,'%8.1f, ', fs_out(b)/1e3); +end +fprintf(fh,'\n'); +for a = 1:nfsi + fprintf(fh,'%8.1f, ', fs_in(a)/1e3); + for b = 1:nfso + mops = sum(mops_2s(:,a,b)); + if sum(l_2s(:,a,b)) < eps + mops_str = 'x'; + else + mops_str = sprintf('%.2f', mops); + end + fprintf(fh,'%8s, ', mops_str); + end + fprintf(fh,'\n'); +end +fprintf(fh,'\n'); + +%% Print 2 stage MOPS per stage +fprintf(fh,'Dual stage fractional SRC: MOPS per stage\n'); +fprintf(fh,'%10s, ', 'in \ out'); +for b = 1:nfso + fprintf(fh,'%10.1f, ', fs_out(b)/1e3); +end +fprintf(fh,'\n'); +for a = 1:nfsi + fprintf(fh,'%10.1f, ', fs_in(a)/1e3); + for b = 1:nfso + mops = mops_2s(:,a,b); + if sum(l_2s(:,a,b)) < eps + mops_str = 'x'; + else + mops_str = sprintf('%.2f+%.2f', mops(1), mops(2)); + end + fprintf(fh,'%10s, ', mops_str); + end + fprintf(fh,'\n'); +end +fprintf(fh,'\n'); + +fprintf(fh,'Coefficient RAM %.1f kB\n', ... + defs.sum_filter_lengths*coef_bytes/1024); +fprintf(fh,'Max. data RAM %.1f kB\n', ... + (defs.fir_delay_size + defs.out_delay_size+defs.stage_buf_size) ... + * data_bytes/1024); + +fprintf(fh,'\n'); +fclose(fh); +type(fn); + +src_paths(0); + +end + +%% Helper functions + +function tbl = export_check(src_in, tbl, coef_label, coef_ctype, hdir, cfg) +if src_in.active + upgrade_converter = false; + new_converter = true; + item = [src_in.L src_in.M src_in.c_pbi src_in.c_sbi src_in.filter_length]; + for i = 1:tbl.idx + if sum(abs(tbl.data(i, 1:4) - item(1:4))) < eps + new_converter = false; + fprintf(1, 'Conversion exists\n'); + previous_length = tbl.data(i,5); + if src_in.filter_length > previous_length + fprintf(1, 'Conversion is upgraded %d -> %d\n', ... + previous_length, src_in.filter_length); + upgrade_converter = true; + tbl.data(i, :) = item; + tbl.src(i) = src_in; + end + end + end + if new_converter || upgrade_converter + src_export_coef(src_in, coef_label, coef_ctype, hdir, cfg.profile); + end + if new_converter + tbl.idx = tbl.idx + 1; + tbl.data(tbl.idx, :) = item; + tbl.src(tbl.idx) = src_in; + end +end +end + +function src_out = export_get(l, m, cnv, tbl) + +src_out.active = 0; +src_out.L=1; +src_out.M=1; +src_out.odm=1; +src_out.idm=1; +src_out.MOPS=0; +src_out.c_pb = 0; +src_out.c_sb = 0; +src_out.fir_delay_size = 0; +src_out.out_delay_size = 0; +src_out.blk_in = 1; +src_out.blk_out = 1; +src_out.gain = 1; +src_out.filter_length = 0; +src_out.c_pbi = 0; +src_out.c_sbi = 0; + +if abs(cnv.fs1 - cnv.fs2) < 1 + return +end + +pbi = round(1e4 * cnv.c_pb); +sbi = round(1e4 * cnv.c_sb); +spec = [l m pbi sbi ]; +for i = 1:tbl.idx + if sum(abs(tbl.data(i, 1:4) - spec)) < eps + src_out = tbl.src(i); + return + end +end +error('Not found, something went wrong'); + +end + +function d = mkdir_check(d) +if ~exist(fullfile('.', d),'dir') + mkdir(d); +end +end + +function cstr = print_ratios(l_2s, m_2s, a, b) +l1 = l_2s(1,a,b); +m1 = m_2s(1,a,b); +l2 = l_2s(2,a,b); +m2 = m_2s(2,a,b); +if l1+m2+l2+m2 == 0 + cstr = 'x'; +else + if m2 == 1 + if l2 == 1 + cstr2 = ''; + else + cstr2 = sprintf('*%d', l2); + end + else + cstr2 = sprintf('*%d/%d', l2, m2); + end + if m1 == 1 + cstr1 = sprintf('%d', l1); + else + cstr1 = sprintf('%d/%d', l1, m1); + end + cstr = sprintf('%s%s', cstr1, cstr2); +end +end + +function delta = test_proto_src(src1, src2, cfg) + +if src1.filter_length < 1 + delta = 0; + return; +end + +[fs1, fs2] = src_fs12(src1, src2); +t = 1.0; +t_ignore = 0.5; +a = 10^(-1/20); +f_start = 100; +f_end = min(0.45 * min(fs1, fs2), 20e3); +n_oct = ceil(log(f_end / f_start) / log(2)); +f = logspace(log10(f_start), log10(f_end), n_oct); +thdn = zeros(1, n_oct); +for i = 1:n_oct + thdn(i) = src_thdn(src1, src2, f(i), a, t_ignore, t); +end + +delta = max(thdn) - cfg.thdn; + +end + +function [fs1, fs2] = src_fs12(src1, src2) + +fs1 = src1.fs1; +if src2.filter_length > 0 + fs2 = src2.fs2; +else + fs2 = src1.fs2; +end + +end + +function thdn = src_thdn(src1, src2, f, a, t_ignore, t) + +[fs1, fs2] = src_fs12(src1, src2); +x = multitone(fs1, f, a, t); +y2 = proto_src(src1, src2, x); + +% Apply standard low-pass for higher output rates +if fs2 > 42e3 + y2 = stdlpf(y2, 20e3, fs2); +end + +y3 = stdnotch(y2, f, fs2); +idx = round(t_ignore * fs2); +level_total = 20*log10(a); +level_residual = level_dbfs(y3(idx:end)); +thdn = level_residual - level_total; + +end + +function y2 = proto_src(src1, src2, x) + +y1 = proto_src1(src1, x); +if src2.filter_length > 0 + y2 = proto_src1(src2, y1); +else + y2 = y1; +end + +end + +function y = proto_src1(src, x) + +if src.L > 1 + x0 = zeros(length(x) * src.L, 1); + x0(1:src.L:end) = x; +else + x0 = x; +end +y0 = filter(src.coefs, 1, x0) * src.gain; +if src.M > 1 + y = y0(1:src.M:end); +else + y = y0; +end +end diff --git a/src/audio/src/tune/sof_src_ipc4_int32.m b/src/audio/src/tune/sof_src_ipc4_int32.m new file mode 100644 index 000000000000..6729d48e84d0 --- /dev/null +++ b/src/audio/src/tune/sof_src_ipc4_int32.m @@ -0,0 +1,40 @@ +%% Export full set of conversions for IPC4 + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022-2025 Intel Corporation. + +fs1 = [ 8 11.025 12 16 18.9 22.05 24 32 37.8 44.1 48 64 88.2 96 176.4 192 ] * 1e3; +fs2 = [ 8 11.025 16 22.05 24 32 44.1 48 64 88.2 96 176.4 192 ] * 1e3; + +fs_matrix = [ +% 1 1 +% 1 1 2 2 3 4 4 6 8 9 7 9 +% 8 1 6 2 4 2 4 8 4 8 6 6 2 +% + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 8 + 1 0 1 0 1 1 1 1 1 1 1 1 0 % 11 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 12 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 16 + 0 0 0 0 1 0 1 1 0 0 0 0 0 % 18.9 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 22.05 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 24 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 32 + 0 0 0 0 0 0 1 1 0 1 1 0 0 % 37.8 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 44.1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 % 48 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 64 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 88.2 + 1 1 1 1 1 1 1 1 1 1 1 1 1 % 96 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 176.4 + 1 0 1 0 1 1 1 1 1 1 1 1 1 % 192 +]; + +cfg.ctype = 'int32'; +cfg.profile = 'ipc4'; +cfg.quality = 1.0; +cfg.thdn = -92; +cfg.speed = 0; +cfg.gain = 0; % Make gain 0 dB + +sof_src_generate(fs1, fs2, fs_matrix, cfg); diff --git a/src/audio/src/tune/sof_src_lite_int32.m b/src/audio/src/tune/sof_src_lite_int32.m new file mode 100755 index 000000000000..84bbe5ef828a --- /dev/null +++ b/src/audio/src/tune/sof_src_lite_int32.m @@ -0,0 +1,25 @@ +%% Export full set of conversions for src-lite + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +fs1 = [ 32 44.1 48 ] * 1e3; + +fs2 = [ 16 48 ] * 1e3; + +fs_matrix = [ + 1 1 + 1 1 + 1 1 + +]; + +cfg.ctype = 'int32'; +cfg.profile = 'lite'; +cfg.quality = 1.0; +cfg.thdn = -92; +cfg.speed = 0; +cfg.gain = 0; % Make gain 0 dB + +sof_src_generate(fs1, fs2, fs_matrix, cfg); diff --git a/src/audio/src/tune/sof_src_small_int32.m b/src/audio/src/tune/sof_src_small_int32.m new file mode 100644 index 000000000000..3583aa2a75e5 --- /dev/null +++ b/src/audio/src/tune/sof_src_small_int32.m @@ -0,0 +1,28 @@ +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. + +fs1 = [8 16 24 32 44.1 48 50] * 1e3; + +fs2 = [8 16 24 32 44.1 48 50] * 1e3; + +% In +% 8 1 2 3 4 4 5 +% 6 4 2 4 8 0 Out +fs_matrix = [ 0 1 1 1 0 1 0 ; ... % 8 + 1 0 1 1 0 1 0 ; ... % 16 + 1 1 0 1 0 1 0 ; ... % 24 + 1 1 1 0 0 1 0 ; ... % 32 + 0 0 0 0 0 1 0 ; ... % 44 + 1 1 1 1 1 0 1 ; ... % 48 + 0 0 0 0 0 1 0 ; ... % 50 + ]; + +cfg.ctype = 'int32'; +cfg.profile = 'small'; +cfg.quality = 1.0; +cfg.thdn = -90; +cfg.speed = 0; +cfg.gain = 0; + +sof_src_generate(fs1, fs2, fs_matrix, cfg); diff --git a/src/audio/src/tune/sof_src_std_int32.m b/src/audio/src/tune/sof_src_std_int32.m new file mode 100644 index 000000000000..81e6f98d20fd --- /dev/null +++ b/src/audio/src/tune/sof_src_std_int32.m @@ -0,0 +1,57 @@ +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +fs1 = [8 11.025 12 16 22.05 24 32 44.1 48 50 64 88.2 96 176.4 192] * 1e3; + +fs2 = [8 11.025 12 16 22.05 24 32 44.1 48 50] * 1e3; + +fs_matrix = [ 0 0 0 1 0 1 1 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 1 0 0 0 0 1 1 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 1 0 0 1 0 0 1 0 1 0 ; ... + 1 0 0 1 0 1 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 1 1 1 1 1 1 1 1 0 1 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ; ... + 0 0 0 0 0 0 0 0 1 0 ]; + +cfg.ctype = 'int32'; +cfg.profile = 'std'; +cfg.quality = 1.0; +cfg.thdn = -90; +cfg.speed = 0; +cfg.gain = 0; + +sof_src_generate(fs1, fs2, fs_matrix, cfg); diff --git a/src/audio/src/tune/sof_src_tiny_int16.m b/src/audio/src/tune/sof_src_tiny_int16.m new file mode 100644 index 000000000000..26dfdf3bae4e --- /dev/null +++ b/src/audio/src/tune/sof_src_tiny_int16.m @@ -0,0 +1,48 @@ +% Copyright (c) 2016, Intel Corporation +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the Intel Corporation nor the +% names of its contributors may be used to endorse or promote products +% derived from this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +% + +fs1 = [8e3 16e3 32e3 44.1e3 48e3 50e3 96e3]; +fs2 = [8e3 16e3 32e3 44.1e3 48e3 50e3 96e3]; +fsm = [0 0 0 0 1 0 0; ... + 0 0 0 0 1 0 0; ... + 0 0 0 0 1 0 0; ... + 0 0 0 0 1 0 0; ... + 1 1 1 1 0 1 1; ... + 0 0 0 0 1 0 0; ... + 0 0 0 0 1 0 0; ... + ]; + +cfg.ctype = 'int16'; +cfg.profile = 'tiny'; +cfg.quality = 0.40; +cfg.thdn = -90; +cfg.speed = 1; +cfg.gain = 0; + +sof_src_generate(fs1, fs2, fsm, cfg); diff --git a/tools/tune/src/src_export_coef.m b/src/audio/src/tune/src_export_coef.m similarity index 78% rename from tools/tune/src/src_export_coef.m rename to src/audio/src/tune/src_export_coef.m index f43862bdb1a4..a8c8fcd4c9dd 100644 --- a/tools/tune/src/src_export_coef.m +++ b/src/audio/src/tune/src_export_coef.m @@ -11,34 +11,11 @@ % profile - string to append to filename % -% Copyright (c) 2016, Intel Corporation -% All rights reserved. +% SPDX-License-Identifier: BSD-3-Clause % -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. % % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% if nargin < 5 profile = ''; @@ -60,7 +37,21 @@ sfn = sprintf('src_%s_%d_%d_%d_%d', ctype, src.L, src.M, pbi, sbi); fprintf('Exporting %s ...\n', hfn); + if exist(hfn, 'file') + fprintf(1, 'Overwrite %s\n', hfn); + end fh = fopen(hfn, 'w'); + y = datestr(now(), 'yyyy'); + + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', y); + fprintf(fh, ' *\n'); + fprintf(fh, ' */\n'); + fprintf(fh, '\n'); + fprintf(fh, '/** \\cond GENERATED_BY_TOOLS_TUNE_SRC */\n'); + fprintf(fh, '#include <stdint.h>\n'); + fprintf(fh, '\n'); switch ctype case 'float' @@ -85,14 +76,14 @@ fprintf(fh, '\n'); switch ctype case 'float' - fprintf(fh, 'struct src_stage %s = {\n', sfn); + fprintf(fh, 'const struct src_stage %s = {\n', sfn); fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %d, %f,\n\t%s};\n', ... src.idm, src.odm, src.num_of_subfilters, ... src.subfilter_length, src.filter_length, ... src.blk_in, src.blk_out, src.halfband, ... src.gain, vfn); case { 'int16' 'int24' 'int32' } - fprintf(fh, 'struct src_stage %s = {\n', sfn); + fprintf(fh, 'static const struct src_stage %s = {\n', sfn); fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %d, %d,\n\t%s};\n', ... src.idm, src.odm, src.num_of_subfilters, ... src.subfilter_length, src.filter_length, ... @@ -101,7 +92,7 @@ otherwise error('Unknown type %s !!!', ctype); end - %fprintf(fh, '\n'); + fprintf(fh, '/** \\endcond */\n'); fclose(fh); success = 1; end @@ -109,7 +100,7 @@ end function print_int_coef(src, fh, vtype, vfn, nbits) - fprintf(fh, 'const %s %s[%d] = {\n', ... + fprintf(fh, '__cold_rodata static const %s %s[%d] = {\n', ... vtype, vfn, src.filter_length); cint = coef_quant(src, nbits); diff --git a/src/audio/src/tune/src_export_defines.m b/src/audio/src/tune/src_export_defines.m new file mode 100644 index 000000000000..877fc5728718 --- /dev/null +++ b/src/audio/src/tune/src_export_defines.m @@ -0,0 +1,59 @@ +function src_export_defines(defs, ctype, hdir, profile) + +% src_export_defines - Exports the constants to header files +% +% src_export_defines(defs, ctype, hdir) +% +% defs - defs struct +% ctype - e.g. 'int24' appended to file name +% hdir - directory for header file +% profile - string to append to file name +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 4 + profile = ''; +end + +if isempty(profile) + hfn = sprintf('src_%s_define.h', ctype); +else + hfn = sprintf('src_%s_%s_define.h', profile, ctype); +end + +fh = fopen(fullfile(hdir,hfn), 'w'); +pu = upper(profile); +cu = upper(ctype); +y = datestr(now(), 'yyyy'); +def = sprintf('__SOF_AUDIO_COEFFICIENTS_SRC_SRC_%s_%s_DEFINE_H__', pu, cu); + +fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); +fprintf(fh, ' *\n'); +fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', y); +fprintf(fh, ' *\n'); +fprintf(fh, ' */\n'); +fprintf(fh, '\n'); +fprintf(fh, '#ifndef %s\n', def); +fprintf(fh, '#define %s\n', def); +fprintf(fh, '\n'); +fprintf(fh, '/* SRC constants */\n'); +fprintf(fh, '#define MAX_FIR_DELAY_SIZE %d\n', defs.fir_delay_size); +fprintf(fh, '#define MAX_OUT_DELAY_SIZE %d\n', defs.out_delay_size); +fprintf(fh, '#define MAX_BLK_IN %d\n', defs.blk_in); +fprintf(fh, '#define MAX_BLK_OUT %d\n', defs.blk_out); +fprintf(fh, '#define NUM_IN_FS %d\n', defs.num_in_fs); +fprintf(fh, '#define NUM_OUT_FS %d\n', defs.num_out_fs); +fprintf(fh, '#define STAGE1_TIMES_MAX %d\n', defs.stage1_times_max); +fprintf(fh, '#define STAGE2_TIMES_MAX %d\n', defs.stage2_times_max); +fprintf(fh, '#define STAGE_BUF_SIZE %d\n', defs.stage_buf_size); +fprintf(fh, '#define NUM_ALL_COEFFICIENTS %d\n', defs.sum_filter_lengths); +fprintf(fh, '\n'); +fprintf(fh, '#endif /* %s */\n', def); +fclose(fh); + +end diff --git a/src/audio/src/tune/src_export_table_2s.m b/src/audio/src/tune/src_export_table_2s.m new file mode 100644 index 000000000000..34342b2ca069 --- /dev/null +++ b/src/audio/src/tune/src_export_table_2s.m @@ -0,0 +1,186 @@ +function sfl = src_export_table_2s(fs_in, fs_out, l_2s, m_2s, ... + pb_2s, sb_2s, taps_2s, ctype, vtype, ppath, hdir, profile) + +% src_export_table_2s - Export src setup table +% +% src_export_table_2s(fs_in, fs_out, l, m, pb, sb, ctype, vtype, hdir, profile) +% +% The parameters are used to differentiate files for possibly many same +% conversion factor filters with possibly different characteristic. +% +% fs_in - input sample rates +% fs_out - output sample rates +% l - interpolation factors +% m - decimation factors +% pb - passband widths +% sb - stopband start frequencies +% ctype - coefficient quantization +% vtype - C variable type +% ppath - print directory prefix to header file name include +% hdir - directory for header files +% profile - string to append to file name +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 12 + profile = ''; +end + +if isempty(profile) + hfn = sprintf('src_%s_table.h', ctype); +else + hfn = sprintf('src_%s_%s_table.h', profile, ctype); +end +fh = fopen(fullfile(hdir,hfn), 'w'); +pu = upper(profile); +cu = upper(ctype); +y = datestr(now(), 'yyyy'); +def = sprintf('__SOF_AUDIO_COEFFICIENTS_SRC_SRC_%s_%s_TABLE_H__', pu, cu); + +fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); +fprintf(fh, ' *\n'); +fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', y); +fprintf(fh, ' *\n'); +fprintf(fh, ' */\n'); +fprintf(fh, '\n'); +fprintf(fh, '/** \\cond GENERATED_BY_TOOLS_TUNE_SRC */\n\n'); +fprintf(fh, '#ifndef %s\n', def); +fprintf(fh, '#define %s\n', def); +fprintf(fh, '\n'); + +fprintf(fh, '/* SRC conversions */\n'); +sfl = 0; +n_in = length(fs_in); +n_out = length(fs_out); +i=1; +all_modes = zeros(2*n_in*n_out, 7); +for n=1:2 + for b=1:n_out + for a=1:n_in + all_modes(i,:) = [ l_2s(n,a,b) m_2s(n,a,b) ... + pb_2s(n,a,b) sb_2s(n,a,b) n a b ]; + i=i+1; + end + end +end + +all_modes_sub = all_modes(:,1:4); +[unique_modes, ia] = unique(all_modes_sub,'rows'); +sm = size(unique_modes); + +if isempty(profile) + prof_ctype = ctype; +else + prof_ctype = sprintf('%s_%s', profile, ctype); +end +for i=1:sm(1) + um_tmp = unique_modes(i,:); + if isequal(um_tmp(1:2),[1 1]) || isequal(um_tmp(1:2),[0 0]) + else + fprintf(fh, '#include \"src_%s_%d_%d_%d_%d.h\"\n', ... + prof_ctype, um_tmp(1:4)); + + n = all_modes(ia(i), 5); + a = all_modes(ia(i), 6); + b = all_modes(ia(i), 7); + sfl = sfl +taps_2s(n, a, b); % Count sum of filter lengths + end +end +fprintf(fh, '#include <stdint.h>\n'); +fprintf(fh,'\n'); + +fprintf(fh, '/* SRC table */\n'); +switch ctype + case 'float' + fprintf(fh, 'static const %s fir_one = 1.0;\n', vtype); + fprintf(fh, 'static const struct src_stage src_double_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, 1.0, &fir_one };\n'); + fprintf(fh, 'static const struct src_stage src_double_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0.0, &fir_one };\n'); + case 'int16' + scale16 = 2^15; + fprintf(fh, 'static const %s fir_one = %d;\n', vtype, round(scale16*0.5)); + fprintf(fh, 'static const struct src_stage src_int16_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n'); + fprintf(fh, 'static const struct src_stage src_int16_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n'); + case 'int24' + scale24 = 2^23; + fprintf(fh, 'static const %s fir_one = %d;\n', vtype, round(scale24*0.5)); + fprintf(fh, 'static const struct src_stage src_int24_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n'); + fprintf(fh, 'static const struct src_stage src_int24_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n'); + case 'int32' + scale32 = 2^31; + fprintf(fh, 'static const %s fir_one = %d;\n', vtype, round(scale32*0.5)); + fprintf(fh, 'static const struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n'); + fprintf(fh, 'static const struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n'); + otherwise + error('Unknown coefficient type!'); +end + +fprintf(fh, 'static const int src_in_fs[%d] = {', n_in); +j = 1; +for i=1:n_in + fprintf(fh, ' %d', fs_in(i)); + if i < n_in + fprintf(fh, ','); + end + j = j + 1; + if (j > 8) + fprintf(fh, '\n\t'); + j = 1; + end +end +fprintf(fh, '};\n'); + +fprintf(fh, 'static const int src_out_fs[%d] = {', n_out); +j = 1; +for i=1:n_out + fprintf(fh, ' %d', fs_out(i)); + if i < n_out + fprintf(fh, ','); + end + j = j + 1; + if (j > 8) + fprintf(fh, '\n\t'); + j = 1; + end +end +fprintf(fh, '};\n'); + +for n = 1:2 + fprintf(fh, 'static const struct src_stage * const src_table%d[%d][%d] = {\n', ... + n, n_out, n_in); + i = 1; + for b = 1:n_out + fprintf(fh, '\t{'); + for a = 1:n_in + fprintf(fh, ' &src_%s_%d_%d_%d_%d', ... + ctype, l_2s(n,a,b), m_2s(n,a,b), ... + pb_2s(n,a,b), sb_2s(n,a,b)); + if a < n_in + fprintf(fh, ','); + end + i = i + 1; + if i > 2 + fprintf(fh, '\n\t'); + i = 1; + end + end + fprintf(fh, '}'); + if b < n_out + fprintf(fh, ',\n'); + else + fprintf(fh, '\n'); + end + end + fprintf(fh, '};\n\n'); +end + +fprintf(fh, '#endif /* %s */\n', def); +fprintf(fh, '\n'); +fprintf(fh, '/** \\endcond */\n'); +fclose(fh); + +end diff --git a/tools/tune/src/src_factor1_lm.m b/src/audio/src/tune/src_factor1_lm.m similarity index 100% rename from tools/tune/src/src_factor1_lm.m rename to src/audio/src/tune/src_factor1_lm.m diff --git a/tools/tune/src/src_factor2_lm.m b/src/audio/src/tune/src_factor2_lm.m similarity index 98% rename from tools/tune/src/src_factor2_lm.m rename to src/audio/src/tune/src_factor2_lm.m index 6ac86020d438..58eb02227207 100644 --- a/tools/tune/src/src_factor2_lm.m +++ b/src/audio/src/tune/src_factor2_lm.m @@ -82,7 +82,7 @@ fs3 = [r11 r12 r21 r22].*fs1; -if fs1 > fs2 % Decrease sample rate, dont go below output rate +if fs1 > fs2 % Decrease sample rate, don't go below output rate idx = find(fs3 >= fs2); if length(idx) < 1 error('Cant factorise interpolations'); @@ -150,6 +150,3 @@ end b = c/a; end - - - diff --git a/tools/tune/src/src_find_l0m0.m b/src/audio/src/tune/src_find_l0m0.m similarity index 100% rename from tools/tune/src/src_find_l0m0.m rename to src/audio/src/tune/src_find_l0m0.m diff --git a/tools/tune/src/src_get.m b/src/audio/src/tune/src_get.m similarity index 84% rename from tools/tune/src/src_get.m rename to src/audio/src/tune/src_get.m index b4f6cf923e3e..c84381525d4a 100644 --- a/tools/tune/src/src_get.m +++ b/src/audio/src/tune/src_get.m @@ -37,6 +37,7 @@ % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> % +debug = 0; use_firpm = 0; use_remez = 0; use_kaiser = 0; @@ -53,24 +54,33 @@ error('Unknown FIR design request!'); end +%% Default minimum needed for scripts to work +src.active = 0; +src.L=1; +src.M=1; +src.odm=1; +src.idm=1; +src.MOPS=0; +src.c_pb = 0; +src.c_sb = 0; +src.fir_delay_size = 0; +src.out_delay_size = 0; +src.blk_in = 1; +src.blk_out = 1; +src.gain = 1; +src.filter_length = 0; +src.c_pbi = 0; +src.c_sbi = 0; + if abs(cnv.fs1-cnv.fs2) < 1 - %% Return minimum needed for scripts to work - src.L=1; - src.M=1; - src.odm=1; - src.idm=1; - src.MOPS=0; - src.c_pb = 0; - src.c_sb = 0; - src.fir_delay_size = 0; - src.out_delay_size = 0; - src.blk_in = 1; - src.blk_out = 1; - src.gain = 1; - src.filter_length = 0; return end +if cnv.rs > cnv.rs_max + fprintf(1, 'Requested stop-band %.1f dB exceeds maximum %.1f.\n', cnv.rs, cnv.rs_max); + error('Failed'); +end + %% fractional SRC parameters [L, M] = src_factor1_lm(cnv.fs1, cnv.fs2); src.L = L; @@ -152,14 +162,13 @@ b = fir1(nfir, kw, kftype, kaiser(nfir+1, kbeta)); end m_b = max(abs(b)); - %sref = 2^(cnv.coef_bits-1); - %bq = round(b*sref/m_b)*m_b/sref; - bq = b; - h_sb = freqz(bq, 1, f_sb, fs3); + h_sb = freqz(b, 1, f_sb, fs3); m_sb = 20*log10(abs(h_sb)); delta_prev = delta; delta = cnv.rs+max(m_sb); - fprintf('Step=%3d, Delta=%f dB, N=%d\n', n, delta, nfir); + if debug + fprintf('Step=%3d, Delta=%f dB, N=%d\n', n, delta, nfir); + end dn(n) = delta; fn(n) = nfir; if delta < 0 @@ -180,7 +189,7 @@ else stopband_ok = 1; % Exit after reverse fprintf('Warning: Filter stop band could not be '); - fprintf('reached.\n', cnv.coef_bits); + fprintf('reached. FIR order is left to %d\n', nfir); end end end @@ -188,17 +197,17 @@ end f_p = linspace(0, fs3/2, 2000); -m_db = 20*log10(abs(freqz(bq, 1, f_p, fs3))); +m_db = 20*log10(abs(freqz(b, 1, f_p, fs3))); i_pb = find(f_p < src.f_pb); i_m3 = find(m_db > -3); f_m3 = f_p(i_m3(end)); g_dc = m_db(1); g_dc_comp_lin = 10^(-g_dc/20); -if 1 +if cnv.do_plots p_ymin = floor((-cnv.rs-50)/10)*10; p_ymax = 10; - figure; + figure(1); clf; plot(f_p, m_db); grid on; @@ -221,30 +230,19 @@ box off; end +%% Make output struct src.subfilter_length = ceil((nfir+1)/src.num_of_subfilters); src.filter_length = src.subfilter_length*src.num_of_subfilters; -src.b = zeros(src.filter_length,1); +src.coefs = zeros(src.filter_length,1); src.gain = 1; -src.b(1:nfir+1) = b * src.L * g_dc_comp_lin * 10^(cnv.gain/20); -m = max(abs(src.b)); +src.coefs(1:nfir+1) = b * src.L * g_dc_comp_lin * 10^(cnv.gain/20); +m = max(abs(src.coefs)); gmax = (32767/32768)/m; maxshift = floor(log(gmax)/log(2)); -src.b = src.b * 2^maxshift; +src.coefs = src.coefs * 2^maxshift; src.gain = 1/2^maxshift; src.shift = maxshift; -%% Reorder coefficients -if 1 - src.coefs = src.b; -else - src.coefs = zeros(src.filter_length,1); - for n = 1:src.num_of_subfilters - i11 = (n-1)*src.subfilter_length+1; - i12 = i11+src.subfilter_length-1; - src.coefs(i11:i12) = src.b(n:src.num_of_subfilters:end); - end -end - src.halfband = 0; src.blk_in = M; src.blk_out = L; @@ -252,5 +250,8 @@ src.fir_delay_size = src.subfilter_length + ... (src.num_of_subfilters-1)*src.idm + src.blk_in; src.out_delay_size = (src.num_of_subfilters-1)*src.odm + 1; +src.c_pbi = round(src.c_pb * 1e4); +src.c_sbi = round(src.c_sb * 1e4); +src.active = 1; end diff --git a/tools/tune/src/src_param.m b/src/audio/src/tune/src_param.m similarity index 87% rename from tools/tune/src/src_param.m rename to src/audio/src/tune/src_param.m index 01eefca1e1c7..81e83035e2a5 100644 --- a/tools/tune/src/src_param.m +++ b/src/audio/src/tune/src_param.m @@ -1,14 +1,15 @@ -function cnv = src_param(fs1, fs2, coef_bits, q) +function cnv = src_param(fs1, fs2, coef_bits, q, gain) % src_param - get converter parameters % -% cnv = src_param(fs1, fs2, coef_bits, q) +% cnv = src_param(fs1, fs2, coef_bits, q, gain) % % fs1 - input rate % fs2 - output rate % coef_bits - word length identifier % q - quality scale filter bandwidth and stopband attenuation, % 1 is default +% gain - overall gain of SRC, defaults to -1 (dB) if omitted % % Copyright (c) 2016, Intel Corporation @@ -44,10 +45,17 @@ % Both give about -80 dB THD+N with 24 bit coefficients. With 16 bit % coefficients THD+N is limited to about -76 dB. +if nargin < 5 + gain = -1; +end + if nargin < 4 q = 1.0; end +%% Create plots +cnv.do_plots = 0; + %% Copy input parameters cnv.fs1 = fs1; cnv.fs2 = fs2; @@ -59,10 +67,11 @@ %% Default SRC quality cnv.c_pb = q * 20/44.1; % Gives 20 kHz BW @ 44.1 kHz cnv.c_sb = 0.5; % Start stopband at Fs/2 -cnv.rs = 70; % Stopband attenuation in dB +cnv.rs = 63; % Stopband attenuation in dB, initial value that will stepped to meet THD+N +cnv.rs_max = 120; % Do not exceed this cnv.rp = 0.1; % Passband ripple in dB cnv.rp_tot = 0.1; % Max +/- passband ripple allowed, used in test script only -cnv.gain = -1; % Gain in decibels at 0 Hz +cnv.gain = gain; % Gain in decibels at 0 Hz %% Constrain sub-filter lengths. Make subfilters lengths multiple of four % is a good assumption for processors. diff --git a/src/audio/src/tune/src_paths.m b/src/audio/src/tune/src_paths.m new file mode 100644 index 000000000000..b2ee172190a3 --- /dev/null +++ b/src/audio/src/tune/src_paths.m @@ -0,0 +1,22 @@ +function src_paths(enable) + +% src_paths(enable) +% enable - set to 1 to enable needed search path +% set to 0 to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + +audio_test = '../../../../tools/test/audio/'; + +if enable + addpath(fullfile(audio_test, 'std_utils')); + addpath(fullfile(audio_test, 'test_utils')); +else + rmpath(fullfile(audio_test, 'std_utils')); + rmpath(fullfile(audio_test, 'test_utils')); +end + +end diff --git a/src/audio/stft_process/CMakeLists.txt b/src/audio/stft_process/CMakeLists.txt new file mode 100644 index 000000000000..e3a13e17bb93 --- /dev/null +++ b/src/audio/stft_process/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_STFT_PROCESS STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/stft_process_llext) + add_dependencies(app stft_process) +else() + add_local_sources(sof stft_process.c) + add_local_sources(sof stft_process_setup.c) + add_local_sources(sof stft_process_common.c) + add_local_sources(sof stft_process-generic.c) + add_local_sources(sof stft_process-hifi3.c) + + if(CONFIG_IPC_MAJOR_4) + add_local_sources(sof stft_process-ipc4.c) + endif() +endif() diff --git a/src/audio/stft_process/Kconfig b/src/audio/stft_process/Kconfig new file mode 100644 index 000000000000..426d272477a9 --- /dev/null +++ b/src/audio/stft_process/Kconfig @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_STFT_PROCESS + tristate "STFT processing component" + default n + select MATH_FFT + select MATH_32BIT_FFT + select MATH_FFT_MULTI + help + Select for stft_process component. STFT acronym means + short term Fourier transform. It converts audio + to multiple FFTs with selected FFT size, hop, and + window function. Possible signal processing can be + done in it in frequency domain for FFTs that is + efficient for more complex signal processing techniques. + The component converts then the frequency domain + version of signal back to normal PCM audio stream + with inverse STFT. + +if COMP_STFT_PROCESS + +rsource "Kconfig.simd" + +config STFT_PROCESS_MAGNITUDE_PHASE + bool "Convert FFTs to polar magnitude and phase" + default n + help + Select for processing in polar magnitude and phase + domain. Such complex values format is common for + frequency domain signal processing. + +endif # COMP_STFT_PROCESS diff --git a/src/audio/stft_process/Kconfig.simd b/src/audio/stft_process/Kconfig.simd new file mode 100644 index 000000000000..0b981df583fa --- /dev/null +++ b/src/audio/stft_process/Kconfig.simd @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: BSD-3-Clause + +comment "STFT Process optimization level select" + +choice "COMP_STFT_PROCESS_SIMD_LEVEL_SELECT" + prompt "Choose which SIMD level is used for the STFT Process module" + depends on COMP_STFT_PROCESS + default COMP_STFT_PROCESS_HIFI_MAX + + config COMP_STFT_PROCESS_HIFI_MAX + prompt "SIMD will be selected by toolchain pre-defined header" + bool + help + When this is selected, the optimization level will be + determined by the toolchain pre-defined macros in the + core isa header file. + + config COMP_STFT_PROCESS_HIFI_3 + prompt "Choose HIFI3 intrinsic optimized STFT Process module" + bool + help + This option is used to build HIFI3 intrinsic optimized + STFT Process code. + + config COMP_STFT_PROCESS_HIFI_NONE + prompt "Choose generic C STFT Process module, no HIFI SIMD involved" + bool + help + This option is used to build STFT Process + with generic C code. +endchoice diff --git a/src/audio/stft_process/README.md b/src/audio/stft_process/README.md new file mode 100644 index 000000000000..074b2c0cf331 --- /dev/null +++ b/src/audio/stft_process/README.md @@ -0,0 +1,14 @@ +# STFT Process Architecture + +This directory provides Short-Time Fourier Transform (STFT) utilities. + +## Overview + +Converts time-domain audio slices into the frequency domain using FFTs, runs frequency-domain processing over those bins, and applies the inverse-STFT (Overlap-Add) back to the time-domain. + +## Configuration and Scripts + +- **Kconfig**: Manages the STFT processing component (`COMP_STFT_PROCESS`) and requires multi-channel 32-bit FFT math libraries (`MATH_FFT`, `MATH_32BIT_FFT`, `MATH_FFT_MULTI`). Also optionally supports converting pure FFTs into polar magnitude and phase domains (`STFT_PROCESS_MAGNITUDE_PHASE`). +- **CMakeLists.txt**: Compiles generic STFT operations (`stft_process.c`, `stft_process_common.c`, `stft_process-generic.c`) and IPC4 wrappers (`stft_process-ipc4.c`), fully supporting the `llext` format. +- **stft_process.toml**: Defines the default `STFTPROC` module layout with UUID `UUIDREG_STR_STFT_PROCESS`. +- **Topology (.conf)**: Instantiated from `tools/topology/topology2/include/components/stft_process.conf`, creating a `stft_process` widget type `effect` (UUID `a6:6e:11:0d:50:91:de:46:98:b8:b2:b3:a7:91:da:29`). diff --git a/src/audio/stft_process/llext/CMakeLists.txt b/src/audio/stft_process/llext/CMakeLists.txt new file mode 100644 index 000000000000..133330c4a69d --- /dev/null +++ b/src/audio/stft_process/llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("stft_process" + SOURCES ../stft_process.c + ../stft_process_setup.c + ../stft_process_common.c + ../stft_process-generic.c + ../stft_process-ipc4.c + LIB openmodules +) diff --git a/src/audio/stft_process/llext/llext.toml.h b/src/audio/stft_process/llext/llext.toml.h new file mode 100644 index 000000000000..e3988e4bb4ed --- /dev/null +++ b/src/audio/stft_process/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../stft_process.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/stft_process/stft_process-generic.c b/src/audio/stft_process/stft_process-generic.c new file mode 100644 index 000000000000..5241c372261f --- /dev/null +++ b/src/audio/stft_process/stft_process-generic.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025-2026 Intel Corporation. + +#include <sof/audio/format.h> +#include <sof/common.h> +#include <assert.h> +#include <stdint.h> +#include "stft_process.h" + +#if SOF_USE_HIFI(NONE, COMP_STFT_PROCESS) +void stft_process_overlap_add_ifft_buffer(struct stft_process_state *state, int ch) +{ + struct stft_process_buffer *obuf = &state->obuf[ch]; + struct stft_process_fft *fft = &state->fft; + int32_t *w = obuf->w_ptr; + int32_t sample; + int i; + int n; + int samples_remain = fft->fft_size; + int idx = 0; + + while (samples_remain) { + n = stft_process_buffer_samples_without_wrap(obuf, w); + n = MIN(samples_remain, n); + + /* Abort if n is zero to avoid infinite loop. The assert can + * trigger only with incorrect usage of this function. + */ + assert(n); + for (i = 0; i < n; i++) { + sample = Q_MULTSR_32X32((int64_t)state->gain_comp, fft->fft_buf[idx].real, + 31, 31, 31); + *w = sat_int32((int64_t)*w + sample); + w++; + idx++; + } + w = stft_process_buffer_wrap(obuf, w); + samples_remain -= n; + } + + w = obuf->w_ptr + fft->fft_hop_size; + obuf->w_ptr = stft_process_buffer_wrap(obuf, w); + obuf->s_avail += fft->fft_hop_size; + obuf->s_free -= fft->fft_hop_size; +} + +void stft_process_apply_window(struct stft_process_state *state) +{ + struct stft_process_fft *fft = &state->fft; + int j; + + /* Multiply Q1.31 by Q1.15 gives Q2.46, shift right by 15 to get Q2.31, no saturate need */ + for (j = 0; j < fft->fft_size; j++) + fft->fft_buf[j].real = + sat_int32(Q_MULTSR_32X32((int64_t)fft->fft_buf[j].real, + state->window[j], 31, 31, 31)); +} +#endif /* SOF_USE_HIFI(NONE, COMP_STFT_PROCESS) */ diff --git a/src/audio/stft_process/stft_process-hifi3.c b/src/audio/stft_process/stft_process-hifi3.c new file mode 100644 index 000000000000..6cf7c3dc7e85 --- /dev/null +++ b/src/audio/stft_process/stft_process-hifi3.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025-2026 Intel Corporation. + +/** + * \file + * \brief HiFi3 SIMD-optimized helpers for the STFT processing component. + * + * This compilation unit provides HiFi3 intrinsic versions of selected + * hot-path helpers. It is guarded by SOF_USE_MIN_HIFI(3, COMP_STFT_PROCESS) + * so only one of the generic or hifi implementations is active. + */ + +#include <sof/audio/format.h> +#include <sof/common.h> +#include <assert.h> +#include <stdint.h> +#include "stft_process.h" + +#if SOF_USE_MIN_HIFI(3, COMP_STFT_PROCESS) + +#include <xtensa/tie/xt_hifi3.h> + +/** + * stft_process_apply_window() - Multiply FFT buffer by the analysis window. + * @state: STFT processing state that contains the FFT buffer and window. + * + * The real part of each icomplex32 sample in the FFT buffer is multiplied + * by the corresponding Q1.31 window coefficient. + */ +void stft_process_apply_window(struct stft_process_state *state) +{ + struct stft_process_fft *fft = &state->fft; + ae_int32 *buf; + const ae_int32x2 *win; + ae_f32x2 data01, data23; + ae_f32x2 win01, win23; + ae_int32x2 d0, d1; + int fft_size = fft->fft_size; + int j; + int n4; + + /* + * buf points to {real, imag} pairs (struct icomplex32). + * win points to scalar Q1.31 window coefficients. + * + * We load each complex pair, multiply only the real part by the + * window value, then store the pair back with the updated real. + * The imaginary part is left untouched. + * + * Stride for buf is sizeof(ae_int32x2) = 8 bytes per complex sample. + * Stride for win is sizeof(ae_int32) = 4 bytes per scalar window value. + */ + buf = (ae_int32 *)fft->fft_buf; + win = (const ae_int32x2 *)state->window; + + assert(!(fft_size & 3)); + + /* Main loop: process 4 samples per iteration */ + n4 = fft_size >> 2; + for (j = 0; j < n4; j++) { + /* Load four FFT real part values, combine into fft_data, + * buf[0] goes to data01 low, buf[1] goes to data01 high. + */ + d0 = AE_L32_I(buf, 0 * sizeof(ae_int32x2)); + d1 = AE_L32_I(buf, 1 * sizeof(ae_int32x2)); + data01 = AE_SEL32_HH(d0, d1); + d0 = AE_L32_I(buf, 2 * sizeof(ae_int32x2)); + d1 = AE_L32_I(buf, 3 * sizeof(ae_int32x2)); + data23 = AE_SEL32_HH(d0, d1); + + /* Load four window coefficients, + * win[0] goes to win01 low, win[1] goes to win01 high + */ + AE_L32X2_IP(win01, win, sizeof(ae_int32x2)); + AE_L32X2_IP(win23, win, sizeof(ae_int32x2)); + + /* Multiply with window function */ + data01 = AE_MULFP32X2RS(data01, win01); + data23 = AE_MULFP32X2RS(data23, win23); + + /* Store back the updated real parts */ + AE_S32_L_IP(AE_SEL32_LH(data01, data01), buf, sizeof(ae_int32x2)); + AE_S32_L_IP(data01, buf, sizeof(ae_int32x2)); + AE_S32_L_IP(AE_SEL32_LH(data23, data23), buf, sizeof(ae_int32x2)); + AE_S32_L_IP(data23, buf, sizeof(ae_int32x2)); + } +} + +/** + * stft_process_overlap_add_ifft_buffer() - Overlap-add IFFT output to circular output buffer. + * @state: STFT processing state. + * @ch: Channel index. + * + * Each IFFT output sample is multiplied by gain_comp (Q1.31 x Q1.31) and + * added with saturation to the existing content of the circular output + * buffer. HiFi3 AE_MULF32S_HH handles the multiply and + * AE_ADD32S provides the saturating accumulation. + * + * Note: obuf must be even number of samples and 64-bit aligned. + */ +void stft_process_overlap_add_ifft_buffer(struct stft_process_state *state, int ch) +{ + struct stft_process_buffer *obuf = &state->obuf[ch]; + struct stft_process_fft *fft = &state->fft; + ae_f32x2 gain = AE_MOVDA32(state->gain_comp); + ae_f32x2 buffer_data; + ae_f32x2 fft_data; + ae_f32x2 d0, d1; + ae_f32x2 *w = (ae_f32x2 *)obuf->w_ptr; + ae_f32 *fft_p = (ae_f32 *)fft->fft_buf; + int samples_remain = fft->fft_size; + int i, n; + + while (samples_remain) { + n = stft_process_buffer_samples_without_wrap(obuf, (int32_t *)w); + + /* The samples count must be even and not zero, the latter to avoid infinite + * loop. The assert can trigger only with incorrect usage of this function. + */ + assert(n && !(n & 1)); + n = MIN(samples_remain, n) >> 1; + for (i = 0; i < n; i++) { + /* Load two FFT real part values, combine into fft_data */ + AE_L32_IP(d0, fft_p, sizeof(ae_f32x2)); + AE_L32_IP(d1, fft_p, sizeof(ae_f32x2)); + fft_data = AE_SEL32_HH(d0, d1); + + /* Load buffer data, multiply fft_data with gain and accumulate, and + * store to output buffer. + */ + buffer_data = AE_L32X2_I(w, 0); + AE_MULAFP32X2RS(buffer_data, fft_data, gain); + AE_S32X2_IP(buffer_data, w, sizeof(ae_f32x2)); + } + w = (ae_f32x2 *)stft_process_buffer_wrap(obuf, (int32_t *)w); + samples_remain -= n << 1; + } + + obuf->w_ptr = stft_process_buffer_wrap(obuf, obuf->w_ptr + fft->fft_hop_size); + obuf->s_avail += fft->fft_hop_size; + obuf->s_free -= fft->fft_hop_size; +} + +#endif /* SOF_USE_MIN_HIFI(3, COMP_STFT_PROCESS) */ diff --git a/src/audio/stft_process/stft_process-ipc4.c b/src/audio/stft_process/stft_process-ipc4.c new file mode 100644 index 000000000000..ac6d9b5e56b5 --- /dev/null +++ b/src/audio/stft_process/stft_process-ipc4.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include "stft_process.h" + +LOG_MODULE_DECLARE(stft_process, CONFIG_SOF_LOG_LEVEL); + +/* IPC4 controls handler */ +__cold int stft_process_set_config(struct processing_module *mod, uint32_t param_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 stft_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "Illegal control param_id %d.", param_id); + return -EINVAL; + } + + if (fragment_size != sizeof(struct sof_stft_process_config)) { + comp_err(dev, "Illegal fragment size %d, expect %d.", fragment_size, + sizeof(struct sof_stft_process_config)); + return -EINVAL; + } + + if (!cd->config) { + cd->config = mod_alloc(mod, sizeof(struct sof_stft_process_config)); + if (!cd->config) { + comp_err(dev, "Failed to allocate configuration."); + return -ENOMEM; + } + } + + memcpy_s(cd->config, sizeof(struct sof_stft_process_config), fragment, fragment_size); + return 0; +} + +/* Not used in IPC4 systems, if IPC4 only component, omit .get_configuration set */ +__cold int stft_process_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, + size_t fragment_size) +{ + assert_can_be_cold(); + return 0; +} diff --git a/src/audio/stft_process/stft_process.c b/src/audio/stft_process/stft_process.c new file mode 100644 index 000000000000..5fb96a267f15 --- /dev/null +++ b/src/audio/stft_process/stft_process.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <rtos/init.h> +#include "stft_process.h" + +/* UUID identifies the components. Use e.g. command uuidgen from package + * uuid-runtime, add it to uuid-registry.txt in SOF top level. + */ +SOF_DEFINE_REG_UUID(stft_process); + +/* Creates logging data for the component */ +LOG_MODULE_REGISTER(stft_process, CONFIG_SOF_LOG_LEVEL); + +#if STFT_DEBUG +FILE *stft_debug_fft_in_fh; +FILE *stft_debug_fft_out_fh; +FILE *stft_debug_ifft_out_fh; +#endif + +/** + * stft_process_init() - Initialize the stft_process component. + * @mod: Pointer to module data. + * + * This function is called when the instance is created. The + * macro __cold informs that the code that is non-critical + * is loaded to slower but large DRAM. + * + * Return: Zero if success, otherwise error code. + */ +__cold static int stft_process_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct stft_comp_data *cd; + + assert_can_be_cold(); + + comp_info(dev, "entry"); + + cd = mod_alloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + memset(cd, 0, sizeof(*cd)); + +#if STFT_DEBUG + stft_debug_fft_in_fh = fopen("stft_debug_fft_in.txt", "w"); + if (!stft_debug_fft_in_fh) { + fprintf(stderr, "Debug file open failed.\n"); + return -EINVAL; + } + + stft_debug_fft_out_fh = fopen("stft_debug_fft_out.txt", "w"); + if (!stft_debug_fft_out_fh) { + fprintf(stderr, "Debug file open failed.\n"); + return -EINVAL; + } + + stft_debug_ifft_out_fh = fopen("stft_debug_ifft_out.txt", "w"); + if (!stft_debug_ifft_out_fh) { + fprintf(stderr, "Debug file open failed.\n"); + fclose(stft_debug_fft_out_fh); + return -EINVAL; + } +#endif + + return 0; +} + +/** + * stft_process_process() - The audio data processing function. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * This is the processing function that is called for scheduled + * pipelines. The processing is controlled by the enable switch. + * + * Return: Zero if success, otherwise error code. + */ +static int stft_process_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + struct sof_source *source = sources[0]; /* One input in this example */ + struct sof_sink *sink = sinks[0]; /* One output in this example */ + int frames = source_get_data_frames_available(source); + int sink_frames = sink_get_free_frames(sink); + int ret; + + frames = MIN(frames, sink_frames); + + /* Process the data with the channels swap example function. */ + ret = cd->stft_process_func(mod, source, sink, frames); + + return ret; +} + +/** + * stft_process_prepare() - Prepare the component for processing. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * Function prepare is called just before the pipeline is started. In + * this case the audio format parameters are for better code performance + * saved to component data to avoid to find out them in process. The + * processing function pointer is set to process the current audio format. + * + * Return: Value zero if success, otherwise error code. + */ +static int stft_process_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame source_format; + int ret; + + comp_dbg(dev, "prepare"); + + /* The processing example in this component supports one input and one + * output. Generally there can be more. + */ + if (num_of_sources != 1 || num_of_sinks != 1) { + comp_err(dev, "Only one source and one sink is supported."); + return -EINVAL; + } + + /* Initialize STFT, max_frames is set to dev->frames + 4 */ + if (!cd->config) { + comp_err(dev, "Can't prepare without bytes control configuration."); + return -EINVAL; + } + + /* get source data format */ + cd->max_frames = dev->frames + 2; + cd->frame_bytes = source_get_frame_bytes(sources[0]); + cd->channels = source_get_channels(sources[0]); + source_format = source_get_frm_fmt(sources[0]); + + ret = stft_process_setup(mod, cd->max_frames, source_get_rate(sources[0]), + source_get_channels(sources[0])); + if (ret < 0) { + comp_err(dev, "setup failed."); + return ret; + } + + cd->stft_process_func = stft_process_find_proc_func(source_format); + if (!cd->stft_process_func) { + comp_err(dev, "No processing function found for format %d.", + source_format); + return -EINVAL; + } + + return 0; +} + +/** + * stft_process_reset() - Reset the component. + * @mod: Pointer to module data. + * + * The component reset is called when pipeline is stopped. The reset + * should return the component to same state as init. + * + * Return: Value zero, always success. + */ +static int stft_process_reset(struct processing_module *mod) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "reset"); + + stft_process_free_buffers(mod); + memset(cd, 0, sizeof(*cd)); + return 0; +} + +/** + * stft_process_free() - Free dynamic allocations. + * @mod: Pointer to module data. + * + * Component free is called when the pipelines are deleted. All + * dynamic allocations need to be freed here. The macro __cold + * instructs the build to locate this performance wise non-critical + * function to large and slower DRAM. + * + * Return: Value zero, always success. + */ +__cold static int stft_process_free(struct processing_module *mod) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + comp_dbg(mod->dev, "free"); + mod_free(mod, cd); + +#if STFT_DEBUG + fclose(stft_debug_fft_in_fh); + fclose(stft_debug_fft_out_fh); + fclose(stft_debug_ifft_out_fh); +#endif + return 0; +} + +/* This defines the module operations */ +static const struct module_interface stft_process_interface = { + .init = stft_process_init, + .prepare = stft_process_prepare, + .process = stft_process_process, + .set_configuration = stft_process_set_config, + .get_configuration = stft_process_get_config, + .reset = stft_process_reset, + .free = stft_process_free +}; + +/* This controls build of the module. If COMP_MODULE is selected in kconfig + * this is build as dynamically loadable module. + */ +#if CONFIG_COMP_STFT_PROCESS_MODULE + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("STFT_PROCESS", &stft_process_interface, 1, + SOF_REG_UUID(stft_process), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(stft_process_tr, SOF_UUID(stft_process_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(stft_process_interface, stft_process_uuid, stft_process_tr); +SOF_MODULE_INIT(stft_process, sys_comp_module_stft_process_interface_init); + +#endif diff --git a/src/audio/stft_process/stft_process.h b/src/audio/stft_process/stft_process.h new file mode 100644 index 000000000000..558023ba55bc --- /dev/null +++ b/src/audio/stft_process/stft_process.h @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + */ +#ifndef __SOF_AUDIO_STFT_PROCESS_H__ +#define __SOF_AUDIO_STFT_PROCESS_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/auditory.h> +#include <sof/math/dct.h> +#include <sof/math/fft.h> + +#include <stdbool.h> +#include <stdint.h> + +#if CONFIG_LIBRARY +#define STFT_DEBUG 0 /* Keep zero, produces large files with fprintf() */ +#else +#define STFT_DEBUG 0 +#endif + +#define SOF_STFT_PROCESS_CONFIG_MAX_SIZE 256 /* Max size for configuration data in bytes */ + +enum sof_stft_process_fft_pad_type { + STFT_PAD_END = 0, + STFT_PAD_CENTER = 1, + STFT_PAD_START = 2, +}; + +enum sof_stft_process_fft_window_type { + STFT_RECTANGULAR_WINDOW = 0, + STFT_BLACKMAN_WINDOW = 1, + STFT_HAMMING_WINDOW = 2, + STFT_HANN_WINDOW = 3, + STFT_POVEY_WINDOW = 4, +}; + +struct sof_stft_process_config { + uint32_t size; /**< Size of this struct in bytes */ + uint32_t reserved[8]; + int32_t sample_frequency; /**< Hz. e.g. 16000 */ + int32_t window_gain_comp; /**< Q1.31 gain for IFFT */ + int32_t reserved_32; + int16_t channel; /**< -1 expect mono, 0 left, 1 right, ... */ + int16_t frame_length; /**< samples, e.g. 400 for 25 ms @ 16 kHz*/ + int16_t frame_shift; /**< samples, e.g. 160 for 10 ms @ 16 kHz */ + int16_t reserved_16; + enum sof_stft_process_fft_pad_type pad; /**< Use PAD_END, PAD_CENTER, PAD_START */ + enum sof_stft_process_fft_window_type window; /**< Use RECTANGULAR_WINDOW, etc. */ +} __attribute__((packed)); + +struct stft_process_buffer { + int32_t *addr; + int32_t *end_addr; + int32_t *r_ptr; + int32_t *w_ptr; + int s_avail; /**< samples count */ + int s_free; /**< samples count */ + int s_length; /**< length in samples for wrap */ +}; + +struct stft_process_fft { + struct icomplex32 *fft_buf; /**< fft_padded_size */ + struct icomplex32 *fft_out; /**< fft_padded_size */ + struct ipolar32 *fft_polar; + struct fft_multi_plan *fft_plan; + struct fft_multi_plan *ifft_plan; + int fft_size; + int fft_padded_size; + int fft_hop_size; + int fft_buf_size; + int half_fft_size; + size_t fft_buffer_size; /**< bytes */ +}; + +struct stft_process_state { + struct stft_process_buffer ibuf[PLATFORM_MAX_CHANNELS]; /**< Buffer for input data */ + struct stft_process_buffer obuf[PLATFORM_MAX_CHANNELS]; /**< Buffer for output data */ + struct stft_process_fft fft; /**< FFT related */ + int32_t *prev_data[PLATFORM_MAX_CHANNELS]; /**< prev_data_size */ + int32_t gain_comp; /**< Gain to compensate window gain */ + int32_t *buffers; + int32_t *window; /**< fft_size */ + int source_channel; + int prev_data_size; + int sample_rate; + bool waiting_fill; /**< booleans */ + bool prev_samples_valid; +}; + +/** + * struct stft_process_func - Function call pointer for process function + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + */ +typedef int (*stft_process_func)(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames); + +/** + * struct stft_comp_data + * @stft_process_func: Pointer to used processing function. + * @channels_order[]: Vector with desired sink channels order. + * @source_format: Source samples format. + * @frame_bytes: Number of bytes in an audio frame. + * @channels: Channels count. + * @enable: Control processing on/off, on - reorder channels + */ +struct stft_comp_data { + stft_process_func stft_process_func; /**< processing function */ + struct stft_process_state state; + struct sof_stft_process_config *config; + size_t frame_bytes; + int source_channel; + int max_frames; + int channels; + bool fft_done; +}; + +static inline int stft_process_buffer_samples_without_wrap(struct stft_process_buffer *buffer, + int32_t *ptr) +{ + return buffer->end_addr - ptr; +} + +static inline int32_t *stft_process_buffer_wrap(struct stft_process_buffer *buffer, int32_t *ptr) +{ + if (ptr >= buffer->end_addr) + ptr -= buffer->s_length; + + return ptr; +} + +/** + * struct stft_process_proc_fnmap - processing functions for frame formats + * @frame_fmt: Current frame format + * @stft_process_proc_func: Function pointer for the suitable processing function + */ +struct stft_process_proc_fnmap { + enum sof_ipc_frame frame_fmt; + stft_process_func stft_process_function; +}; + +/** + * stft_process_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +stft_process_func stft_process_find_proc_func(enum sof_ipc_frame src_fmt); + +#if CONFIG_IPC_MAJOR_4 +/** + * stft_process_set_config() - Handle controls set + * @mod: Pointer to module data. + * @param_id: Id to know control type, used to know ALSA control type. + * @pos: Position of the fragment in the large message. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * @response_size: Size of response. + * + * This function handles the real-time controls. The ALSA controls have the + * param_id set to indicate the control type. The control ID, from topology, + * is used to separate the controls instances of same type. In control payload + * the num_elems defines to how many channels the control is applied to. + * + * Return: Zero if success, otherwise error code. + */ +int stft_process_set_config(struct processing_module *mod, uint32_t param_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); +/** + * stft_process_set_config() - Handle controls get + * @mod: Pointer to module data. + * @config_id: Configuration ID. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * + * This function is used for controls get. + * + * Return: Zero if success, otherwise error code. + */ +int stft_process_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, size_t fragment_size); +#else +static inline int stft_process_set_config(struct processing_module *mod, uint32_t param_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) +{ + return 0; +} + +static inline int stft_process_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, + size_t fragment_size) +{ + return 0; +} +#endif + +/** + * stft_process_setup() - Initialize STFT processing state and allocate buffers. + * @mod: Pointer to processing module. + * @max_frames: Maximum number of frames per processing call. + * @rate: Audio sample rate in Hz. + * @channels: Number of audio channels. + * + * Configures FFT parameters, allocates aligned sample and FFT buffers, + * sets up window function, and creates FFT/IFFT plans based on the + * component configuration. + * + * Return: Zero on success, otherwise a negative error code. + */ +int stft_process_setup(struct processing_module *mod, int max_frames, int rate, int channels); + +/** + * stft_process_source_s16() - Copy S16_LE source data to STFT internal buffers. + * @cd: STFT component data. + * @source: Source for PCM samples data. + * @frames: Number of audio data frames to process. + * + * De-interleaves S16_LE audio frames from the source circular buffer + * into per-channel internal circular buffers. Each 16-bit sample is + * converted to Q1.31 format by left-shifting 16 bits. + * + * Return: Zero on success, otherwise an error code. + */ +int stft_process_source_s16(struct stft_comp_data *cd, struct sof_source *source, int frames); + +/** + * stft_process_sink_s16() - Copy STFT internal buffers to S16_LE sink. + * @cd: STFT component data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to produce. + * + * Interleaves per-channel STFT output buffers into the sink circular + * buffer in S16_LE format. Q1.31 samples are converted to Q1.15 with + * rounding and saturation. Output buffer samples are cleared after + * reading to prepare for the next overlap-add cycle. + * + * Return: Zero on success, otherwise an error code. + */ +int stft_process_sink_s16(struct stft_comp_data *cd, struct sof_sink *sink, int frames); + +/** + * stft_process_source_s32() - Copy S32_LE source data to STFT internal buffers. + * @cd: STFT component data. + * @source: Source for PCM samples data. + * @frames: Number of audio data frames to process. + * + * De-interleaves S32_LE audio frames from the source circular buffer + * into per-channel internal circular buffers. + * + * Return: Zero on success, otherwise an error code. + */ +int stft_process_source_s32(struct stft_comp_data *cd, struct sof_source *source, int frames); + +/** + * stft_process_sink_s32() - Copy STFT internal buffers to S32_LE sink. + * @cd: STFT component data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to produce. + * + * Interleaves per-channel STFT output buffers into the sink circular + * buffer in S32_LE format. The output buffer samples are cleared after + * reading to prepare for the next overlap-add cycle. + * + * Return: Zero on success, otherwise an error code. + */ +int stft_process_sink_s32(struct stft_comp_data *cd, struct sof_sink *sink, int frames); + +/** + * stft_process_free_buffers() - Free all STFT processing buffers. + * @mod: Pointer to processing module. + * + * Releases sample buffers, FFT buffers, and FFT/IFFT plans allocated + * during stft_process_setup(). + */ +void stft_process_free_buffers(struct processing_module *mod); + +/** + * stft_process_fill_prev_samples() - Save overlap samples for next STFT frame. + * @buf: Circular buffer to read overlap samples from. + * @prev_data: Destination array for the overlap data. + * @prev_data_length: Number of samples to copy. + * + * Copies prev_data_length samples from the circular buffer into the + * linear prev_data array, handling wrap-around as needed. + */ +void stft_process_fill_prev_samples(struct stft_process_buffer *buf, int32_t *prev_data, + int prev_data_length); + +/** + * stft_process_fill_fft_buffer() - Assemble FFT input from overlap and new data. + * @state: STFT processing state. + * @ch: Channel index. + * + * Constructs the FFT input buffer by concatenating the previous overlap + * samples and one hop of new samples from the input circular buffer. + * Imaginary parts are set to zero. The overlap buffer is updated with + * data for the next frame. + */ +void stft_process_fill_fft_buffer(struct stft_process_state *state, int ch); + +/** + * stft_process_apply_window() - Multiply FFT buffer by the analysis window. + * @state: STFT processing state that contains the FFT buffer and window. + * + * The real part of each complex sample in the FFT buffer is multiplied + * by the corresponding Q1.31 window coefficient. + */ +void stft_process_apply_window(struct stft_process_state *state); + +/** + * stft_process_overlap_add_ifft_buffer() - Overlap-add IFFT output to circular output buffer. + * @state: STFT processing state. + * @ch: Channel index. + * + * Each IFFT output sample is multiplied by the gain compensation value + * and added with saturation to the existing content of the circular + * output buffer. + */ +void stft_process_overlap_add_ifft_buffer(struct stft_process_state *state, int ch); + +#endif // __SOF_AUDIO_STFT_PROCESS_H__ diff --git a/src/audio/stft_process/stft_process.toml b/src/audio/stft_process/stft_process.toml new file mode 100644 index 000000000000..5e0f3b805c7d --- /dev/null +++ b/src/audio/stft_process/stft_process.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Template component module config + [[module.entry]] + name = "STFTPROC" + uuid = UUIDREG_STR_STFT_PROCESS + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/stft_process/stft_process_common.c b/src/audio/stft_process/stft_process_common.c new file mode 100644 index 000000000000..6ab3199082de --- /dev/null +++ b/src/audio/stft_process/stft_process_common.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/format.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex32.h> +#include <sof/math/matrix.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> + +#include "stft_process.h" + +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#if STFT_DEBUG +extern FILE *stft_debug_fft_in_fh; +extern FILE *stft_debug_fft_out_fh; +extern FILE *stft_debug_ifft_out_fh; + +static void debug_print_to_file_real(FILE *fh, struct icomplex32 *c, int n) +{ + for (int i = 0; i < n; i++) + fprintf(fh, "%d\n", c[i].real); +} + +static void debug_print_to_file_complex(FILE *fh, struct icomplex32 *c, int n) +{ + for (int i = 0; i < n; i++) + fprintf(fh, "%d %d\n", c[i].real, c[i].imag); +} +#endif + +#if CONFIG_FORMAT_S32LE +int stft_process_source_s32(struct stft_comp_data *cd, struct sof_source *source, int frames) +{ + struct stft_process_state *state = &cd->state; + struct stft_process_buffer *ibuf; + int32_t const *x, *x_start, *x_end; + int x_size; + int bytes = frames * cd->frame_bytes; + int frames_left = frames; + int ret; + int n1; + int n2; + int channels = cd->channels; + int n; + int i; + int j; + + /* Get pointer to source data in circular buffer */ + ret = source_get_data_s32(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + + while (frames_left) { + /* Find out samples to process before first wrap or end of data. */ + ibuf = &state->ibuf[0]; + n1 = (x_end - x) / cd->channels; + n2 = stft_process_buffer_samples_without_wrap(ibuf, ibuf->w_ptr); + n = MIN(n1, n2); + n = MIN(n, frames_left); + for (i = 0; i < n; i++) { + for (j = 0; j < channels; j++) { + ibuf = &state->ibuf[j]; + *ibuf->w_ptr++ = *x++; + } + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + for (j = 0; j < channels; j++) { + ibuf = &state->ibuf[j]; + ibuf->w_ptr = stft_process_buffer_wrap(ibuf, ibuf->w_ptr); + } + + if (x >= x_end) + x -= x_size; + + /* Update processed samples count for next loop iteration. */ + frames_left -= n; + } + + /* Update the source for bytes consumed. Return success. */ + source_release_data(source, bytes); + for (j = 0; j < channels; j++) { + ibuf = &state->ibuf[j]; + ibuf->s_avail += frames; + ibuf->s_free -= frames; + } + + return 0; +} + +int stft_process_sink_s32(struct stft_comp_data *cd, struct sof_sink *sink, int frames) +{ + struct stft_process_state *state = &cd->state; + struct stft_process_buffer *obuf; + int32_t *y, *y_start, *y_end; + int frames_remain = frames; + int channels = cd->channels; + int bytes = frames * cd->frame_bytes; + int y_size; + int ret; + int ch, n1, n, i; + + /* Get pointer to sink data in circular buffer */ + ret = sink_get_buffer_s32(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + y_end = y_start + y_size; + while (frames_remain) { + /* Find out samples to process before first wrap or end of data. */ + obuf = &state->obuf[0]; + n1 = (y_end - y) / cd->channels; + n = stft_process_buffer_samples_without_wrap(obuf, obuf->r_ptr); + n = MIN(n1, n); + n = MIN(n, frames_remain); + + for (i = 0; i < n; i++) { + for (ch = 0; ch < channels; ch++) { + obuf = &state->obuf[ch]; + *y++ = *obuf->r_ptr; + *obuf->r_ptr++ = 0; /* clear overlap add mix */ + } + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + for (ch = 0; ch < cd->channels; ch++) { + obuf = &state->obuf[ch]; + obuf->r_ptr = stft_process_buffer_wrap(obuf, obuf->r_ptr); + } + + if (y >= y_end) + y -= y_size; + + /* Update processed samples count for next loop iteration. */ + frames_remain -= n; + } + + /* Update the sink for bytes produced. Return success. */ + sink_commit_buffer(sink, bytes); + for (ch = 0; ch < channels; ch++) { + obuf = &state->obuf[ch]; + obuf->s_avail -= frames; + obuf->s_free += frames; + } + + return 0; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +int stft_process_source_s16(struct stft_comp_data *cd, struct sof_source *source, int frames) +{ + struct stft_process_state *state = &cd->state; + struct stft_process_buffer *ibuf; + int16_t const *x, *x_start, *x_end; + int16_t in; + int x_size; + int channels = cd->channels; + int bytes = frames * cd->frame_bytes; + int frames_left = frames; + int ret; + int n1; + int n2; + int n; + int i; + int j; + + ret = source_get_data_s16(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + x_end = x_start + x_size; + + while (frames_left) { + ibuf = &state->ibuf[0]; + n1 = (x_end - x) / cd->channels; + n2 = stft_process_buffer_samples_without_wrap(ibuf, ibuf->w_ptr); + n = MIN(n1, n2); + n = MIN(n, frames_left); + for (i = 0; i < n; i++) { + for (j = 0; j < channels; j++) { + ibuf = &state->ibuf[j]; + in = *x++; + *ibuf->w_ptr++ = (int32_t)in << 16; + } + } + + for (j = 0; j < channels; j++) { + ibuf = &state->ibuf[j]; + ibuf->w_ptr = stft_process_buffer_wrap(ibuf, ibuf->w_ptr); + } + + if (x >= x_end) + x -= x_size; + + frames_left -= n; + } + + source_release_data(source, bytes); + for (j = 0; j < channels; j++) { + ibuf = &state->ibuf[j]; + ibuf->s_avail += frames; + ibuf->s_free -= frames; + } + return 0; +} + +int stft_process_sink_s16(struct stft_comp_data *cd, struct sof_sink *sink, int frames) +{ + struct stft_process_state *state = &cd->state; + struct stft_process_buffer *obuf; + int16_t *y, *y_start, *y_end; + int frames_remain = frames; + int channels = cd->channels; + int bytes = frames * cd->frame_bytes; + int y_size; + int ret; + int ch, n1, n, i; + + ret = sink_get_buffer_s16(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + y_end = y_start + y_size; + while (frames_remain) { + obuf = &state->obuf[0]; + n1 = (y_end - y) / cd->channels; + n = stft_process_buffer_samples_without_wrap(obuf, obuf->r_ptr); + n = MIN(n1, n); + n = MIN(n, frames_remain); + + for (i = 0; i < n; i++) { + for (ch = 0; ch < channels; ch++) { + obuf = &state->obuf[ch]; + *y++ = sat_int16(Q_SHIFT_RND(*obuf->r_ptr, 31, 15)); + *obuf->r_ptr++ = 0; /* clear overlap add mix */ + } + } + + for (ch = 0; ch < channels; ch++) { + obuf = &state->obuf[ch]; + obuf->r_ptr = stft_process_buffer_wrap(obuf, obuf->r_ptr); + } + + if (y >= y_end) + y -= y_size; + + frames_remain -= n; + } + + sink_commit_buffer(sink, bytes); + for (ch = 0; ch < channels; ch++) { + obuf = &state->obuf[ch]; + obuf->s_avail -= frames; + obuf->s_free += frames; + } + + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +void stft_process_fill_prev_samples(struct stft_process_buffer *buf, int32_t *prev_data, + int prev_data_length) +{ + int32_t *r = buf->r_ptr; + int32_t *p = prev_data; + int copied; + int nmax; + int n; + + for (copied = 0; copied < prev_data_length; copied += n) { + nmax = prev_data_length - copied; + n = stft_process_buffer_samples_without_wrap(buf, r); + n = MIN(n, nmax); + memcpy(p, r, sizeof(int32_t) * n); + p += n; + r += n; + r = stft_process_buffer_wrap(buf, r); + } + + buf->s_avail -= copied; + buf->s_free += copied; + buf->r_ptr = r; +} + +void stft_process_fill_fft_buffer(struct stft_process_state *state, int ch) +{ + struct stft_process_buffer *ibuf = &state->ibuf[ch]; + struct stft_process_fft *fft = &state->fft; + int32_t *prev_data = state->prev_data[ch]; + int32_t *r = ibuf->r_ptr; + int copied; + int nmax; + int idx; + int j; + int n; + + /* Copy overlapped samples from state buffer. Imaginary part of input + * remains zero. + */ + for (j = 0; j < state->prev_data_size; j++) { + fft->fft_buf[j].real = prev_data[j]; + fft->fft_buf[j].imag = 0; + } + + /* Copy hop size of new data from circular buffer */ + idx = state->prev_data_size; + for (copied = 0; copied < fft->fft_hop_size; copied += n) { + nmax = fft->fft_hop_size - copied; + n = stft_process_buffer_samples_without_wrap(ibuf, r); + n = MIN(n, nmax); + for (j = 0; j < n; j++) { + fft->fft_buf[idx].real = *r++; + fft->fft_buf[idx].imag = 0; + idx++; + } + r = stft_process_buffer_wrap(ibuf, r); + } + + ibuf->s_avail -= copied; + ibuf->s_free += copied; + ibuf->r_ptr = r; + + /* Copy for next time data back to overlap buffer */ + idx = fft->fft_hop_size; + for (j = 0; j < state->prev_data_size; j++) + prev_data[j] = fft->fft_buf[idx + j].real; +} + +LOG_MODULE_REGISTER(stft_process_common, CONFIG_SOF_LOG_LEVEL); + +/* + * The main processing function for STFT_PROCESS + */ + +static int stft_prepare_fft(struct stft_process_state *state, int channel) +{ + struct stft_process_buffer *ibuf = &state->ibuf[channel]; + struct stft_process_fft *fft = &state->fft; + + /* Wait for FFT hop size of new data */ + if (ibuf->s_avail < fft->fft_hop_size) + return 0; + + return 1; +} + +static void stft_do_fft(struct stft_process_state *state, int ch) +{ + struct stft_process_fft *fft = &state->fft; + + /* Copy data to FFT input buffer from overlap buffer and from new samples buffer */ + stft_process_fill_fft_buffer(state, ch); + + /* Window function */ + stft_process_apply_window(state); + +#if STFT_DEBUG + debug_print_to_file_real(stft_debug_fft_in_fh, fft->fft_buf, fft->fft_size); +#endif + + /* Compute FFT. A full scale s16 sine input with 2^N samples period in low + * part of s32 real part and zero imaginary part gives to output about 0.5 + * full scale 32 bit output to real and imaginary. The scaling is same for + * all FFT sizes. + */ + fft_multi_execute_32(fft->fft_plan, false); + +#if STFT_DEBUG + debug_print_to_file_complex(stft_debug_fft_out_fh, fft->fft_out, fft->fft_size); +#endif +} + +static void stft_do_ifft(struct stft_process_state *state, int ch) +{ + struct stft_process_fft *fft = &state->fft; + + /* Compute IFFT */ + fft_multi_execute_32(fft->ifft_plan, true); + +#if STFT_DEBUG + debug_print_to_file_complex(stft_debug_ifft_out_fh, fft->fft_buf, fft->fft_size); +#endif + + /* Window function */ + stft_process_apply_window(state); + + /* Copy to output buffer */ + stft_process_overlap_add_ifft_buffer(state, ch); +} + +#if CONFIG_STFT_PROCESS_MAGNITUDE_PHASE +static void stft_convert_to_polar(struct stft_process_fft *fft) +{ + int i; + + for (i = 0; i < fft->half_fft_size; i++) + sofm_icomplex32_to_polar(&fft->fft_out[i], &fft->fft_polar[i]); +} + +static void stft_convert_to_complex(struct stft_process_fft *fft) +{ + int i; + + for (i = 0; i < fft->half_fft_size; i++) + sofm_ipolar32_to_complex(&fft->fft_polar[i], &fft->fft_out[i]); +} + +static void stft_apply_fft_symmetry(struct stft_process_fft *fft) +{ + int i, j, k; + + j = 2 * fft->half_fft_size - 2; + for (i = fft->half_fft_size; i < fft->fft_size; i++) { + k = j - i; + fft->fft_out[i].real = fft->fft_out[k].real; + fft->fft_out[i].imag = -fft->fft_out[k].imag; + } +} +#endif + +static void stft_do_fft_ifft(const struct processing_module *mod) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + struct stft_process_state *state = &cd->state; + int num_fft; + int ch; + + for (ch = 0; ch < cd->channels; ch++) { + num_fft = stft_prepare_fft(state, ch); + + if (num_fft) { + stft_do_fft(state, ch); + +#if CONFIG_STFT_PROCESS_MAGNITUDE_PHASE + /* Convert half-FFT to polar and back, and fix upper part */ + stft_convert_to_polar(&state->fft); + stft_convert_to_complex(&state->fft); + stft_apply_fft_symmetry(&state->fft); +#endif + + stft_do_ifft(state, ch); + cd->fft_done = true; + } + } +} + +#if CONFIG_FORMAT_S32LE +static int stft_process_output_zeros_s32(struct stft_comp_data *cd, struct sof_sink *sink, + int frames) +{ + int32_t *y, *y_start, *y_end; + int samples = frames * cd->channels; + size_t bytes = samples * sizeof(int32_t); + int samples_without_wrap; + int y_size; + int ret; + + /* Get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + y_end = y_start + y_size; + while (samples) { + /* Find out samples to process before first wrap or end of data. */ + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, samples); + memset(y, 0, samples_without_wrap * sizeof(int32_t)); + y += samples_without_wrap; + + /* Check for wrap */ + if (y >= y_end) + y -= y_size; + + /* Update processed samples count for next loop iteration. */ + samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + sink_commit_buffer(sink, bytes); + return 0; +} + +static int stft_process_s32(const struct processing_module *mod, struct sof_source *source, + struct sof_sink *sink, uint32_t frames) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + + /* Get samples from source buffer */ + stft_process_source_s32(cd, source, frames); + + /* Do STFT, processing and inverse STFT */ + stft_do_fft_ifft(mod); + + /* Get samples from source buffer */ + if (cd->fft_done) + stft_process_sink_s32(cd, sink, frames); + else + stft_process_output_zeros_s32(cd, sink, frames); + + return 0; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +static int stft_process_output_zeros_s16(struct stft_comp_data *cd, struct sof_sink *sink, + int frames) +{ + int16_t *y, *y_start, *y_end; + int samples = frames * cd->channels; + size_t bytes = samples * sizeof(int16_t); + int samples_without_wrap; + int y_size; + int ret; + + /* Get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s16(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + y_end = y_start + y_size; + while (samples) { + /* Find out samples to process before first wrap or end of data. */ + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, samples); + memset(y, 0, samples_without_wrap * sizeof(int16_t)); + y += samples_without_wrap; + + /* Check for wrap */ + if (y >= y_end) + y -= y_size; + + /* Update processed samples count for next loop iteration. */ + samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + sink_commit_buffer(sink, bytes); + return 0; +} + +static int stft_process_s16(const struct processing_module *mod, struct sof_source *source, + struct sof_sink *sink, uint32_t frames) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + + /* Get samples from source buffer */ + stft_process_source_s16(cd, source, frames); + + /* Do STFT, processing and inverse STFT */ + stft_do_fft_ifft(mod); + + /* Get samples from source buffer */ + if (cd->fft_done) + stft_process_sink_s16(cd, sink, frames); + else + stft_process_output_zeros_s16(cd, sink, frames); + + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +#endif /* CONFIG_FORMAT_S24LE */ + +/* This struct array defines the used processing functions for + * the PCM formats + */ +const struct stft_process_proc_fnmap stft_process_functions[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, stft_process_s16 }, + { SOF_IPC_FRAME_S32_LE, stft_process_s32 }, +#endif +}; + +/** + * stft_process_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +stft_process_func stft_process_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < ARRAY_SIZE(stft_process_functions); i++) + if (src_fmt == stft_process_functions[i].frame_fmt) + return stft_process_functions[i].stft_process_function; + + return NULL; +} diff --git a/src/audio/stft_process/stft_process_setup.c b/src/audio/stft_process/stft_process_setup.c new file mode 100644 index 000000000000..377d5feeabc8 --- /dev/null +++ b/src/audio/stft_process/stft_process_setup.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/component.h> +#include <sof/audio/audio_stream.h> +#include <sof/math/auditory.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <sof/trace/trace.h> +#include "stft_process.h" + +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* Definitions for cepstral lifter */ +#define PI_Q23 Q_CONVERT_FLOAT(3.1415926536, 23) +#define TWO_PI_Q23 Q_CONVERT_FLOAT(6.2831853072, 23) +#define ONE_Q9 Q_CONVERT_FLOAT(1, 9) + +#define STFT_MAX_ALLOC_SIZE 65536 + +LOG_MODULE_REGISTER(stft_process_setup, CONFIG_SOF_LOG_LEVEL); + +static void stft_process_init_buffer(struct stft_process_buffer *buf, int32_t *base, int size) +{ + buf->addr = base; + buf->end_addr = base + size; + buf->r_ptr = base; + buf->w_ptr = base; + buf->s_free = size; + buf->s_avail = 0; + buf->s_length = size; +} + +static int stft_process_get_window(struct stft_process_state *state, + enum sof_stft_process_fft_window_type name) +{ + struct stft_process_fft *fft = &state->fft; + + switch (name) { + case STFT_RECTANGULAR_WINDOW: + win_rectangular_32b(state->window, fft->fft_size); + return 0; + case STFT_BLACKMAN_WINDOW: + win_blackman_32b(state->window, fft->fft_size, WIN_BLACKMAN_A0_Q31); + return 0; + case STFT_HAMMING_WINDOW: + win_hamming_32b(state->window, fft->fft_size); + return 0; + case STFT_HANN_WINDOW: + win_hann_32b(state->window, fft->fft_size); + return 0; + + default: + return -EINVAL; + } +} + +/* TODO stft_process setup needs to use the config blob, not hard coded parameters. + * Also this is a too long function. Split to STFT, Mel filter, etc. parts. + */ +int stft_process_setup(struct processing_module *mod, int max_frames, + int sample_rate, int channels) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_stft_process_config *config = cd->config; + struct stft_process_state *state = &cd->state; + struct stft_process_fft *fft = &state->fft; + size_t sample_buffers_size; + size_t ibuf_size; + size_t obuf_size; + size_t prev_size; + int32_t *addr; + int ret; + int i; + + comp_dbg(dev, "entry"); + + /* Check size */ + if (config->size != sizeof(struct sof_stft_process_config)) { + comp_err(dev, "Illegal configuration size %d.", config->size); + return -EINVAL; + } + + if (config->sample_frequency != sample_rate) { + comp_err(dev, "Config sample_frequency does not match stream"); + return -EINVAL; + } + + /* max_frames needs to be even for buffer size allocation for Xtensa HiFi SIMD. */ + max_frames = ALIGN_UP(max_frames, 2); + cd->max_frames = max_frames; + state->sample_rate = sample_rate; + + comp_info(dev, "source_channel = %d, stream_channels = %d", + config->channel, channels); + if (config->channel >= channels) { + comp_err(dev, "Illegal channel"); + return -EINVAL; + } + + if (config->channel < 0) + state->source_channel = 0; + else + state->source_channel = config->channel; + + fft->fft_size = config->frame_length; + fft->fft_padded_size = fft->fft_size; /* Same */ + fft->fft_hop_size = config->frame_shift; + fft->half_fft_size = (fft->fft_padded_size >> 1) + 1; + + /* FFT size needs to be a multiple of 4 for Xtensa HiFi SIMD, + * and FFT hop size needs to be a multiple of 2. Check also + * for otherwise sane values. + */ + if (fft->fft_size <= 0 || fft->fft_hop_size <= 0 || + fft->fft_hop_size > fft->fft_size || + (fft->fft_size & 3) || (fft->fft_hop_size & 1)) { + comp_err(dev, "FFT size %d or hop size %d are invalid.", + fft->fft_size, fft->fft_hop_size); + return -EINVAL; + } + + comp_info(dev, "fft_size = %d, fft_hop_size = %d, window = %d", + fft->fft_size, fft->fft_hop_size, config->window); + + /* Calculated parameters */ + state->prev_data_size = fft->fft_size - fft->fft_hop_size; + ibuf_size = fft->fft_hop_size + max_frames; + obuf_size = fft->fft_size + max_frames; + prev_size = state->prev_data_size; + + /* Allocate buffer input samples, overlap buffer, window */ + sample_buffers_size = sizeof(int32_t) * + (cd->channels * (ibuf_size + obuf_size + prev_size) + fft->fft_size); + + if (sample_buffers_size > STFT_MAX_ALLOC_SIZE) { + comp_err(dev, "Illegal allocation size"); + return -ENOMEM; + } + + state->buffers = mod_balloc_align(mod, sample_buffers_size, 2 * sizeof(int32_t)); + if (!state->buffers) { + comp_err(dev, "Failed buffer allocate"); + ret = -ENOMEM; + goto exit; + } + + bzero(state->buffers, sample_buffers_size); + addr = state->buffers; + for (i = 0; i < cd->channels; i++) { + stft_process_init_buffer(&state->ibuf[i], addr, ibuf_size); + addr += ibuf_size; + stft_process_init_buffer(&state->obuf[i], addr, obuf_size); + addr += obuf_size; + state->prev_data[i] = addr; + addr += prev_size; + } + state->window = addr; + + /* Allocate buffers for FFT input and output data */ + fft->fft_buffer_size = fft->fft_padded_size * sizeof(struct icomplex32); + fft->fft_buf = mod_balloc_align(mod, fft->fft_buffer_size, sizeof(struct icomplex32)); + if (!fft->fft_buf) { + comp_err(dev, "Failed FFT buffer allocate"); + ret = -ENOMEM; + goto free_buffers; + } + + fft->fft_out = mod_balloc_align(mod, fft->fft_buffer_size, sizeof(struct icomplex32)); + if (!fft->fft_out) { + comp_err(dev, "Failed FFT output allocate"); + ret = -ENOMEM; + goto free_fft_buf; + } + + /* Share the fft_out buffer for polar format */ + fft->fft_polar = (struct ipolar32 *)fft->fft_out; + + /* Setup FFT */ + fft->fft_plan = mod_fft_multi_plan_new(mod, fft->fft_buf, fft->fft_out, + fft->fft_padded_size, 32); + if (!fft->fft_plan) { + comp_err(dev, "Failed FFT init"); + ret = -EINVAL; + goto free_fft_out; + } + + fft->ifft_plan = mod_fft_multi_plan_new(mod, fft->fft_out, fft->fft_buf, + fft->fft_padded_size, 32); + if (!fft->ifft_plan) { + comp_err(dev, "Failed IFFT init"); + ret = -EINVAL; + goto free_ifft_out; + } + + /* Setup window */ + ret = stft_process_get_window(state, config->window); + if (ret < 0) { + comp_err(dev, "Failed Window function"); + goto free_window_out; + } + + /* Need to compensate the window function gain */ + state->gain_comp = config->window_gain_comp; + + /* Set initial state for STFT */ + state->waiting_fill = true; + state->prev_samples_valid = false; + + comp_dbg(dev, "done"); + return 0; + +free_window_out: + mod_free(mod, fft->ifft_plan); + +free_ifft_out: + mod_free(mod, fft->fft_plan); + +free_fft_out: + mod_free(mod, fft->fft_out); + +free_fft_buf: + mod_free(mod, fft->fft_buf); + +free_buffers: + mod_free(mod, state->buffers); + +exit: + return ret; +} + +void stft_process_free_buffers(struct processing_module *mod) +{ + struct stft_comp_data *cd = module_get_private_data(mod); + struct stft_process_state *state = &cd->state; + struct stft_process_fft *fft = &state->fft; + + mod_fft_multi_plan_free(mod, fft->ifft_plan); + mod_fft_multi_plan_free(mod, fft->fft_plan); + mod_free(mod, cd->state.fft.fft_buf); + mod_free(mod, cd->state.fft.fft_out); + mod_free(mod, cd->state.buffers); +} diff --git a/src/audio/stft_process/tune/setup_stft_process.m b/src/audio/stft_process/tune/setup_stft_process.m new file mode 100644 index 000000000000..4018a1d7aeb7 --- /dev/null +++ b/src/audio/stft_process/tune/setup_stft_process.m @@ -0,0 +1,185 @@ +% setup_stft_process() +% +% Create binary configuration blob for STFT_PROCESS component. The hex data +% is written to tools/topology/topology1/m4/stft_process/stft_process_config.m4 + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2025, Intel Corporation. + +function setup_stft_process(cfg) + + cfg.tools_path = '../../../../tools/'; + cfg.tplg_path = [cfg.tools_path 'topology/topology2/include/components/stft_process/']; + cfg.common_path = [cfg.tools_path 'tune/common']; + cfg.tplg_ver = 2; + cfg.ipc_ver = 4; + cfg.channel = 0; + cfg.sample_frequency = 48000; + + cfg.frame_length = 192; % 4 ms + cfg.frame_shift = 48; % 1 ms + cfg.window_type = 'hann'; + cfg.tplg_fn = 'hann_192_48.conf'; + export_stft_process_setup(cfg); + + cfg.frame_length = 512; % 10.7 ms + cfg.frame_shift = 128; % 2.7 ms + cfg.window_type = 'hann'; + cfg.tplg_fn = 'hann_512_128.conf'; + export_stft_process_setup(cfg); + + cfg.frame_length = 768; % 16 ms + cfg.frame_shift = 120; % 2.5 ms + cfg.window_type = 'hann'; + cfg.tplg_fn = 'hann_768_120.conf'; + export_stft_process_setup(cfg); + + cfg.frame_length = 1024; % 21.3 ms + cfg.frame_shift = 256; % 5.3 ms + cfg.window_type = 'hann'; + cfg.tplg_fn = 'hann_1024_256.conf'; + export_stft_process_setup(cfg); + + cfg.frame_length = 1536; % 32 ms + cfg.frame_shift = 240; % 5 ms + cfg.window_type = 'hann'; + cfg.tplg_fn = 'hann_1536_240.conf'; + export_stft_process_setup(cfg); + +end + +function export_stft_process_setup(cfg) + + % Use blob tool from EQ + addpath(cfg.common_path); + + % Blob size, size plus reserved(8) + current parameters + nbytes_data = 64; + + % Get ABI information + [abi_bytes, nbytes_abi] = sof_get_abi(nbytes_data, cfg.ipc_ver); + + % Initialize correct size uint8 array + nbytes = nbytes_abi + nbytes_data; + b8 = uint8(zeros(1,nbytes)); + + % Insert ABI header + fprintf(1, 'STFT_PROCESS blob size is %d, ABI header is %d, data is %d\n',nbytes, nbytes_abi, nbytes_data); + b8(1:nbytes_abi) = abi_bytes; + j = nbytes_abi + 1; + + % Apply default STFT_PROCESS configuration, first struct header and reserved, then data + [b8, j] = add_w32b(nbytes_data, b8, j); + for i = 1:8 + [b8, j] = add_w32b(0, b8, j); + end + + fft_length = cfg.frame_length; + fft_hop = cfg.frame_shift; + [window_idx, window_gain_comp] = get_window(cfg, fft_length, fft_hop); + + v = q_convert(cfg.sample_frequency, 0); [b8, j] = add_w32b(v, b8, j); + v = q_convert(window_gain_comp, 31); [b8, j] = add_w32b(v, b8, j); + v = 0; [b8, j] = add_w32b(v, b8, j); % reserved + v = cfg.channel; [b8, j] = add_w16b(v, b8, j); + v = fft_length; [b8, j] = add_w16b(v, b8, j); + v = fft_hop; [b8, j] = add_w16b(v, b8, j); + v = 0; [b8, j] = add_w16b(v, b8, j); % reserved + v = 0; [b8, j] = add_w32b(v, b8, j); % enum pad + v = window_idx; [b8, j] = add_w32b(v, b8, j); % enum window + + % Export + switch cfg.tplg_ver + case 2 + sof_tplg2_write([cfg.tplg_path cfg.tplg_fn], b8, "stft_process_config", ... + "Exported STFT_PROCESS configuration", ... + "cd tools/tune/stft_process; octave setup_stft_process.m"); + otherwise + error("Illegal cfg.tplg_ver, use 2 topology v2."); + end + + rmpath(cfg.common_path); + +end + +%% Helper functions + +function [idx, iwg] = get_window(cfg, len, hop) + switch lower(cfg.window_type) + case 'rectangular' + win = boxcar(len); + idx = 0; + case 'blackman' + win = blackman(len); + idx = 1; + case 'hamming' + win = hamming(len); + idx = 2; + case 'hann' + win = hann(len); + idx = 3; + case 'povey' + idx = 4; + n = 0:(len-1); + win = ((1 - cos(2 * pi * n / len)) / 2).^0.85; + otherwise + error('Unknown window type'); + end + iwg = hop / sum(win.^2); +end + +function bytes = w8b(word) + bytes = uint8(zeros(1,1)); + bytes(1) = bitand(word, 255); +end + +function bytes = w16b(word) + sh = [0 -8]; + bytes = uint8(zeros(1,2)); + bytes(1) = bitand(bitshift(word, sh(1)), 255); + bytes(2) = bitand(bitshift(word, sh(2)), 255); +end + +function bytes = w32b(word) + sh = [0 -8 -16 -24]; + bytes = uint8(zeros(1,4)); + bytes(1) = bitand(bitshift(word, sh(1)), 255); + bytes(2) = bitand(bitshift(word, sh(2)), 255); + bytes(3) = bitand(bitshift(word, sh(3)), 255); + bytes(4) = bitand(bitshift(word, sh(4)), 255); +end + +function n = q_convert(val, q) + n = round(val * 2^q); +end + +function [blob8, j] = add_w8b(v, blob8, j) + if j > length(blob8) + error('Blob size is not sufficient'); + end + blob8(j) = w8b(v); + j = j + 1; +end + +function [blob8, j] = add_w16b(v, blob8, j) + if j + 1 > length(blob8) + error('Blob size is not sufficient'); + end + if v < 0 + v = 2^16 + v; + end + blob8(j : j + 1) = w16b(v); + j = j + 2; +end + +function [blob8, j] = add_w32b(v, blob8, j) + if j + 3 > length(blob8) + error('Blob size is not sufficient'); + end + if v < 0 + v = 2^32 + v; + end + blob8(j : j + 3) = w32b(v); + j = j + 4; +end diff --git a/src/audio/switch.c b/src/audio/switch.c deleted file mode 100644 index 175143be82e4..000000000000 --- a/src/audio/switch.c +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/common.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/trace/trace.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <stddef.h> - -static const struct comp_driver comp_switch; - -/* 385cc44b-f34e-4b9b-8be0-535c5f43a825 */ -DECLARE_SOF_UUID("switch", switch_uuid, 0x385cc44b, 0xf34e, 0x4b9b, - 0x8b, 0xe0, 0x53, 0x5c, 0x5f, 0x43, 0xa8, 0x25); - -static struct comp_dev *switch_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - comp_cl_info(&comp_switch, "switch_new()"); - - return NULL; -} - -static void switch_free(struct comp_dev *dev) -{ -} - -/* set component audio stream parameters */ -static int switch_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - return 0; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int switch_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - /* switch will use buffer "connected" status */ - return 0; -} - -/* copy and process stream data from source to sink buffers */ -static int switch_copy(struct comp_dev *dev) -{ - return 0; -} - -static int switch_reset(struct comp_dev *dev) -{ - return 0; -} - -static int switch_prepare(struct comp_dev *dev) -{ - return 0; -} - -static const struct comp_driver comp_switch = { - .type = SOF_COMP_SWITCH, - .uid = SOF_UUID(switch_uuid), - .ops = { - .new = switch_new, - .free = switch_free, - .params = switch_params, - .cmd = switch_cmd, - .copy = switch_copy, - .prepare = switch_prepare, - .reset = switch_reset, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_switch_info = { - .drv = &comp_switch, -}; - -static void sys_comp_switch_init(void) -{ - comp_register(platform_shared_get(&comp_switch_info, - sizeof(comp_switch_info))); -} - -DECLARE_MODULE(sys_comp_switch_init); diff --git a/src/audio/tdfb/CMakeLists.txt b/src/audio/tdfb/CMakeLists.txt new file mode 100644 index 000000000000..aaa61cacaa9f --- /dev/null +++ b/src/audio/tdfb/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_TDFB STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/tdfb_llext) + add_dependencies(app tdfb) +else() + add_local_sources(sof tdfb.c tdfb_generic.c tdfb_hifiep.c tdfb_hifi3.c tdfb_direction.c) + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof tdfb_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof tdfb_ipc4.c) + endif() +endif() diff --git a/src/audio/tdfb/Kconfig b/src/audio/tdfb/Kconfig new file mode 100644 index 000000000000..3a8cff21431a --- /dev/null +++ b/src/audio/tdfb/Kconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_TDFB + tristate "TDFB component" + depends on COMP_MODULE_ADAPTER + select MATH_FIR + select MATH_IIR_DF1 + select SQRT_FIXED + select CORDIC_FIXED + select COMP_BLOB + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for time domain fixed beamformer (TDFB) component. The + beamformer component enhances microphone capture by spatial + suppression of noise and improvement of signal-to-noise ratio of + capture from beam direction. The component is essentially a generic + single rate FIR filter bank that performs microphone array + directivity enhancement when programmed with suitable configuration + for channels selection, channel filter coefficients, and output + streams mixing. diff --git a/src/audio/tdfb/README.md b/src/audio/tdfb/README.md new file mode 100644 index 000000000000..cf3bc13dbe2d --- /dev/null +++ b/src/audio/tdfb/README.md @@ -0,0 +1,15 @@ +# Time Domain Filter Bank Architecture + +This directory contains the TDFB component. + +## Overview + +Generally used for operations like beamforming or highly directional microphone array processing in the time domain. + +## Configuration and Scripts + +- **Kconfig**: Manages the Time Domain Fixed Beamformer component (`COMP_TDFB`), requiring generic `COMP_MODULE_ADAPTER` integration along with high-precision math packages (`MATH_FIR`, `MATH_IIR_DF1`, `SQRT_FIXED`, `CORDIC_FIXED`). +- **CMakeLists.txt**: Builds the standard source set (`tdfb.c`, `tdfb_generic.c`, `tdfb_hifiep.c`, `tdfb_hifi3.c`, `tdfb_direction.c`) handling generic and HIFI implementations alongside IPC abstractions (`tdfb_ipc3.c`, `tdfb_ipc4.c`). Inherits out-of-tree loader (`llext`) generation. +- **tdfb.toml**: Generates ALSA properties mapping the component to `UUIDREG_STR_TDFB`. +- **Topology (.conf)**: Instantiated from `tools/topology/topology2/include/components/tdfb.conf`, creating a `tdfb` widget type `effect` (UUID `49:17:51:dd:fa:d9:5c:45:b3:a7:13:58:56:93:f1:af`). Provides multiple internal mixer controls spanning phase/direction toggles. +- **MATLAB Tuning (`tune/`)**: `sof_example_circular_array.m` and similar array topology scripts define spatial setups (e.g., circular, linear, L-shape, rectangular). They take microphone layout coordinates, compute beamforming angles (azimuth/elevation) and delays, and pack them into binary configuration blobs allowing microphones to "steer" their listening direction interactively. diff --git a/src/audio/tdfb/llext/CMakeLists.txt b/src/audio/tdfb/llext/CMakeLists.txt new file mode 100644 index 000000000000..3a12afea12ca --- /dev/null +++ b/src/audio/tdfb/llext/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("tdfb" + SOURCES ../tdfb.c + ../tdfb_direction.c + ../tdfb_generic.c + ../tdfb_hifiep.c + ../tdfb_hifi3.c + ../tdfb_ipc4.c + LIB openmodules +) diff --git a/src/audio/tdfb/llext/llext.toml.h b/src/audio/tdfb/llext/llext.toml.h new file mode 100644 index 000000000000..f5dbd89a4cc2 --- /dev/null +++ b/src/audio/tdfb/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../tdfb.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/tdfb/tdfb.c b/src/audio/tdfb/tdfb.c new file mode 100644 index 000000000000..5df4563c3558 --- /dev/null +++ b/src/audio/tdfb/tdfb.c @@ -0,0 +1,830 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +/* Note: The script tools/tune/tdfb/example_all.sh can be used to re-calculate + * all the beamformer topology data files if need. It also creates the additional + * data files for simulated tests with testbench. Matlab or Octave is needed. + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <sof/lib/uuid.h> +#include <sof/math/fir_generic.h> +#include <sof/math/fir_hifi2ep.h> +#include <sof/math/fir_hifi3.h> +#include <sof/platform.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <rtos/init.h> +#include <rtos/panic.h> +#include <rtos/string.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/ut.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "tdfb.h" +#include "tdfb_comp.h" + +LOG_MODULE_REGISTER(tdfb, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(tdfb); + +static inline int set_func(struct processing_module *mod, enum sof_ipc_frame fmt) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + switch (fmt) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S16_LE"); + cd->tdfb_func = tdfb_fir_s16; + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S24_4LE"); + cd->tdfb_func = tdfb_fir_s24; + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S32_LE"); + cd->tdfb_func = tdfb_fir_s32; + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(mod->dev, "invalid frame_fmt"); + return -EINVAL; + } + return 0; +} + +/* + * Pass-through processing functions + */ + +static void tdfb_pass_same_format(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); +} + +#if CONFIG_FORMAT_S16LE +static void tdfb_pass_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); + int16_t s0, s1; + int fmax; + int is, om; + int f, i, j, k; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + const int num_filters = cd->config->num_filters; + int remaining_frames = frames; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + for (i = 0; i < num_filters; i++) { + is = cd->input_channel_select[i]; + om = cd->output_channel_mix[i]; + s0 = x[is]; + s1 = x[is + in_nch]; + for (k = 0; k < out_nch; k++) { + if (om & 1) { + y[k] = s0; + y[k + out_nch] = s1; + } + om = om >> 1; + } + } + x += 2 * in_nch; + y += 2 * out_nch; + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S24LE +static void tdfb_pass_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int32_t s0, s1; + int fmax; + int is, om; + int f, i, j, k; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + const int num_filters = cd->config->num_filters; + int remaining_frames = frames; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + for (i = 0; i < num_filters; i++) { + is = cd->input_channel_select[i]; + om = cd->output_channel_mix[i]; + s0 = x[is]; + s1 = x[is + in_nch]; + for (k = 0; k < out_nch; k++) { + if (om & 1) { + y[k] = s0; + y[k + out_nch] = s1; + } + om = om >> 1; + } + } + x += 2 * in_nch; + y += 2 * out_nch; + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S32LE +static void tdfb_pass_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); + int32_t s0, s1; + int fmax; + int is, om; + int f, i, j, k; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + const int num_filters = cd->config->num_filters; + int remaining_frames = frames; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + for (i = 0; i < num_filters; i++) { + is = cd->input_channel_select[i]; + om = cd->output_channel_mix[i]; + s0 = x[is]; + s1 = x[is + in_nch]; + for (k = 0; k < out_nch; k++) { + if (om & 1) { + y[k] = s0; + y[k + out_nch] = s1; + } + om = om >> 1; + } + } + x += 2 * in_nch; + y += 2 * out_nch; + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +static inline int set_pass_func(struct processing_module *mod, enum sof_ipc_frame fmt) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + switch (fmt) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S16_LE"); + cd->tdfb_func = tdfb_pass_s16; + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S24_4LE"); + cd->tdfb_func = tdfb_pass_s24; + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + comp_dbg(mod->dev, "SOF_IPC_FRAME_S32_LE"); + cd->tdfb_func = tdfb_pass_s32; + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(mod->dev, "invalid frame_fmt"); + return -EINVAL; + } + return 0; +} + +/* + * Control code functions next. The processing is in fir_ C modules. + */ + +static void tdfb_free_delaylines(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + struct fir_state_32x16 *fir = cd->fir; + int i = 0; + + /* Free the common buffer for all EQs and point then + * each FIR channel delay line to NULL. + */ + mod_free(mod, cd->fir_delay); + cd->fir_delay = NULL; + cd->fir_delay_size = 0; + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + fir[i].delay = NULL; +} + +static int16_t *tdfb_filter_seek(struct sof_tdfb_config *config, int num_filters) +{ + struct sof_fir_coef_data *coef_data; + int i; + int16_t *coefp = ASSUME_ALIGNED(&config->data[0], 2); /* 2 for 16 bits data */ + + /* Note: FIR coefficients are int16_t. An uint_8 type pointer coefp + * is used for jumping in the flexible array member structs coef_data. + */ + for (i = 0; i < num_filters; i++) { + coef_data = (struct sof_fir_coef_data *)coefp; + coefp = coef_data->coef + coef_data->length; + } + + return coefp; +} + +static int wrap_180(int a) +{ + if (a > 180) + return ((a + 180) % 360) - 180; + + if (a < -180) + return 180 - ((180 - a) % 360); + + return a; +} + +static int tdfb_init_coef(struct processing_module *mod, int source_nch, + int sink_nch) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + struct sof_fir_coef_data *coef_data; + struct sof_tdfb_config *config = cd->config; + struct comp_dev *dev = mod->dev; + int16_t *output_channel_mix_beam_off = NULL; + int16_t *coefp; + int size_sum = 0; + int min_delta_idx; /* Index to beam angle with smallest delta vs. target */ + int min_delta; /* Smallest angle difference found in degrees */ + int max_ch; + int num_filters; + int target_az; /* Target azimuth angle in degrees */ + int delta; /* Target minus found angle in degrees absolute value */ + int idx; + int s; + int i; + + /* Sanity checks */ + if (config->num_output_channels > PLATFORM_MAX_CHANNELS || + !config->num_output_channels) { + comp_err(dev, "invalid num_output_channels %d", + config->num_output_channels); + return -EINVAL; + } + + if (config->num_output_channels != sink_nch) { + comp_err(dev, "stream output channels count %d does not match configuration %d", + sink_nch, config->num_output_channels); + return -EINVAL; + } + + if (config->num_filters > SOF_TDFB_FIR_MAX_COUNT) { + comp_err(dev, "invalid num_filters %d", + config->num_filters); + return -EINVAL; + } + + if (config->num_angles > SOF_TDFB_MAX_ANGLES) { + comp_err(dev, "invalid num_angles %d", + config->num_angles); + return -EINVAL; + } + + if (config->beam_off_defined > 1) { + comp_err(dev, "invalid beam_off_defined %d", + config->beam_off_defined); + return -EINVAL; + } + + if (config->num_mic_locations > SOF_TDFB_MAX_MICROPHONES) { + comp_err(dev, "invalid num_mic_locations %d", + config->num_mic_locations); + return -EINVAL; + } + + /* In SOF v1.6 - 1.8 based beamformer topologies the multiple angles, mic locations, + * and beam on/off switch were not defined. Return error if such configuration is seen. + * A most basic blob has num_angles equals 1. Mic locations data is optional. + */ + if (config->num_angles == 0 && config->num_mic_locations == 0) { + comp_err(dev, "ABI version less than 3.19.1 is not supported."); + return -EINVAL; + } + + /* Skip filter coefficients */ + num_filters = config->num_filters * (config->num_angles + config->beam_off_defined); + coefp = tdfb_filter_seek(config, num_filters); + + /* Get shortcuts to input and output configuration */ + cd->input_channel_select = coefp; + coefp += config->num_filters; + cd->output_channel_mix = coefp; + coefp += config->num_filters; + cd->output_stream_mix = coefp; + coefp += config->num_filters; + + /* Check if there's beam-off configured, then get pointers to beam angles data + * and microphone locations. Finally check that size matches. + */ + if (config->beam_off_defined) { + output_channel_mix_beam_off = coefp; + coefp += config->num_filters; + } + cd->filter_angles = (struct sof_tdfb_angle *)coefp; + cd->mic_locations = (struct sof_tdfb_mic_location *) + (&cd->filter_angles[config->num_angles]); + if ((uint8_t *)&cd->mic_locations[config->num_mic_locations] != + (uint8_t *)config + config->size) { + comp_err(dev, "invalid config size"); + return -EINVAL; + } + + /* Skip to requested coefficient set */ + min_delta = 360; + min_delta_idx = 0; + target_az = wrap_180(cd->az_value * config->angle_enum_mult + config->angle_enum_offs); + + for (i = 0; i < config->num_angles; i++) { + delta = ABS(target_az - wrap_180(cd->filter_angles[i].azimuth)); + if (delta < min_delta) { + min_delta = delta; + min_delta_idx = i; + } + } + + idx = cd->filter_angles[min_delta_idx].filter_index; + if (cd->beam_on) { + comp_info(dev, "angle request %d, found %d, idx %d", + target_az, cd->filter_angles[min_delta_idx].azimuth, idx); + } else if (config->beam_off_defined) { + cd->output_channel_mix = output_channel_mix_beam_off; + idx = config->num_filters * config->num_angles; + comp_info(dev, "configure beam off"); + } else { + comp_info(dev, "beam off is not defined, using filter %d, idx %d", + cd->filter_angles[min_delta_idx].azimuth, idx); + } + + /* Seek to proper filter for requested angle or beam off configuration */ + coefp = tdfb_filter_seek(config, idx); + + /* Initialize filter bank */ + for (i = 0; i < config->num_filters; i++) { + /* Get delay line size */ + coef_data = (struct sof_fir_coef_data *)coefp; + s = fir_delay_size(coef_data); + if (s > 0) { + size_sum += s; + } else { + comp_err(dev, "FIR length %d is invalid", + coef_data->length); + return -EINVAL; + } + + /* Initialize coefficients for FIR filter and find next + * filter. + */ + fir_init_coef(&cd->fir[i], coef_data); + coefp = coef_data->coef + coef_data->length; + } + + /* Find max used input channel */ + max_ch = 0; + for (i = 0; i < config->num_filters; i++) { + if (cd->input_channel_select[i] > max_ch) + max_ch = cd->input_channel_select[i]; + } + + /* The stream must contain at least the number of channels that is + * used for filters input. + */ + if (max_ch + 1 > source_nch) { + comp_err(dev, "stream input channels count %d is not sufficient for configuration %d", + source_nch, max_ch + 1); + return -EINVAL; + } + + return size_sum; +} + +static void tdfb_init_delay(struct tdfb_comp_data *cd) +{ + int32_t *fir_delay = cd->fir_delay; + int i; + + /* Initialize second phase to set delay lines pointers */ + for (i = 0; i < cd->config->num_filters; i++) { + if (cd->fir[i].length > 0) + fir_init_delay(&cd->fir[i], &fir_delay); + } +} + +static int tdfb_setup(struct processing_module *mod, int source_nch, int sink_nch, + enum sof_ipc_frame fmt) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + int delay_size; + + /* If beam on, restore processing function. If off, use for same source and + * sink format the efficient 1:1 copy, otherwise faster pass-through processing + * functions those copy selected source channels to selected sink channels. + */ + if (cd->beam_on) { + set_func(mod, fmt); + } else { + if (source_nch == sink_nch) + cd->tdfb_func = tdfb_pass_same_format; + else + set_pass_func(mod, fmt); + } + + /* Set coefficients for each channel from coefficient blob */ + delay_size = tdfb_init_coef(mod, source_nch, sink_nch); + if (delay_size < 0) + return delay_size; /* Contains error code */ + + /* If all channels were set to bypass there's no need to + * allocate delay. Just return with success. + */ + if (!delay_size) + return 0; + + if (delay_size > cd->fir_delay_size) { + /* Free existing FIR channels data if it was allocated */ + tdfb_free_delaylines(mod); + + /* Allocate all FIR channels data in a big chunk and clear it */ + cd->fir_delay = mod_balloc(mod, delay_size); + if (!cd->fir_delay) { + comp_err(mod->dev, "delay allocation failed for size %d", + delay_size); + return -ENOMEM; + } + + memset(cd->fir_delay, 0, delay_size); + cd->fir_delay_size = delay_size; + } + + /* Assign delay line to all channel filters */ + tdfb_init_delay(cd); + + return 0; +} + +/* + * End of algorithm code. Next the standard component methods. + */ + +static int tdfb_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct tdfb_comp_data *cd; + int ret; + int i; + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + + /* Defaults for processing function pointer tdfb_func, fir_delay + * pointer, are NULL. Fir_delay_size is zero from rzalloc(). + */ + + /* Defaults for enum controls are zeros from rzalloc() + * az_value is zero, beam off is false, and update is false. + */ + + /* Initialize IPC for direction of arrival estimate update */ + ret = tdfb_ipc_notification_init(mod); + if (ret) + goto err_free_cd; + + /* Handler for configuration data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto err; + } + + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + fir_reset(&cd->fir[i]); + + /* Allow different number of channels in source and sink, in other + * aspects TDFB is simple component type. + */ + mod->verify_params_flags = BUFF_PARAMS_CHANNELS; + return 0; + +err: + /* These are null if not used for IPC version */ + mod_free(mod, cd->ctrl_data); + ipc_msg_free(cd->msg); + mod_data_blob_handler_free(mod, cd->model_handler); + +err_free_cd: + mod_free(mod, cd); + return ret; + +} + +static int tdfb_free(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + ipc_msg_free(cd->msg); + tdfb_free_delaylines(mod); + mod_data_blob_handler_free(mod, cd->model_handler); + tdfb_direction_free(mod); + mod_free(mod, cd->ctrl_data); + mod_free(mod, cd); + return 0; +} + +static int tdfb_get_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + return tdfb_get_ipc_config(mod, param_id, data_offset_size, fragment, fragment_size); +} + +static int tdfb_set_config(struct processing_module *mod, uint32_t param_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) +{ + return tdfb_set_ipc_config(mod, param_id, pos, data_offset_size, fragment, + fragment_size, response, response_size); +} + +/* + * copy and process stream data from source to sink buffers + */ + +static int tdfb_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 comp_dev *dev = mod->dev; + struct tdfb_comp_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + int frame_count = input_buffers[0].size; + int ret; + + comp_dbg(dev, "entry"); + + /* 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, audio_stream_get_channels(source), + audio_stream_get_channels(sink), + audio_stream_get_frm_fmt(source)); + if (ret < 0) { + comp_err(dev, "failed FIR setup"); + return ret; + } + } + + /* Handle enum controls */ + if (cd->update) { + cd->update = false; + ret = tdfb_setup(mod, audio_stream_get_channels(source), + audio_stream_get_channels(sink), + audio_stream_get_frm_fmt(source)); + if (ret < 0) { + comp_err(dev, "failed FIR setup"); + return ret; + } + } + + /* + * Process only even number of frames with the FIR function. The + * optimized filter function loads the successive input samples from + * internal delay line with a 64 bit load operation. + */ + frame_count = MIN(frame_count, cd->max_frames) & ~0x1; + if (frame_count) { + cd->tdfb_func(cd, input_buffers, output_buffers, frame_count); + module_update_buffer_position(input_buffers, output_buffers, frame_count); + + /* Update sound direction estimate */ + 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); + + if (cd->direction_updates && cd->direction_change) { + tdfb_send_ipc_notification(mod); + cd->direction_change = false; + comp_dbg(dev, "tdfb_dupd %d %d", + cd->az_value_estimate, cd->direction.az_slow); + } + } + + return 0; +} + +static void tdfb_set_alignment(struct audio_stream *source) +{ + const uint32_t byte_align = SOF_FRAME_BYTE_ALIGN; + const uint32_t frame_align_req = 2; /* Process multiples of 2 frames */ + + audio_stream_set_align(byte_align, frame_align_req, source); +} + +static int tdfb_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + struct comp_buffer *sourceb, *sinkb; + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame frame_fmt; + size_t data_size; + int source_channels; + int sink_channels; + int rate; + int ret; + + comp_info(dev, "entry"); + + /* Find source and sink buffers */ + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + + ret = tdfb_params(mod); + if (ret) { + comp_err(dev, "Failed tdfb_params()"); + return ret; + } + + tdfb_set_alignment(&sourceb->stream); + + frame_fmt = audio_stream_get_frm_fmt(&sourceb->stream); + source_channels = audio_stream_get_channels(&sourceb->stream); + sink_channels = audio_stream_get_channels(&sinkb->stream); + rate = audio_stream_get_rate(&sourceb->stream); + + /* Initialize filter */ + cd->config = comp_get_data_blob(cd->model_handler, &data_size, NULL); + if (!cd->config || !data_size) { + comp_err(dev, "Missing a configuration blob."); + ret = -EINVAL; + goto out; + } + + ret = tdfb_setup(mod, source_channels, sink_channels, frame_fmt); + if (ret < 0) { + comp_err(dev, "error: tdfb_setup failed."); + goto out; + } + + /* Clear in/out buffers */ + memset(cd->in, 0, TDFB_IN_BUF_LENGTH * sizeof(int32_t)); + memset(cd->out, 0, TDFB_IN_BUF_LENGTH * sizeof(int32_t)); + + ret = set_func(mod, frame_fmt); + if (ret) + goto out; + + /* The max. amount of processing need to be limited for sound direction + * processing. Max frames is used in tdfb_direction_init() and copy(). + */ + cd->max_frames = Q_MULTSR_16X16((int32_t)dev->frames, TDFB_MAX_FRAMES_MULT_Q14, 0, 14, 0); + comp_dbg(dev, "dev_frames = %d, max_frames = %d", dev->frames, cd->max_frames); + + /* Initialize tracking */ + ret = tdfb_direction_init(mod, rate, source_channels); + if (!ret) { + comp_info(dev, "max_lag = %d, xcorr_size = %zu", + cd->direction.max_lag, cd->direction.d_size); + comp_info(dev, "line_array = %d, a_step = %d, a_offs = %d", + (int)cd->direction.line_array, cd->config->angle_enum_mult, + cd->config->angle_enum_offs); + } + +out: + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + return ret; +} + +static int tdfb_reset(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + int i; + + comp_dbg(mod->dev, "entry"); + + tdfb_free_delaylines(mod); + + cd->tdfb_func = NULL; + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + fir_reset(&cd->fir[i]); + + /* Clear in/out buffers */ + memset(cd->in, 0, TDFB_IN_BUF_LENGTH * sizeof(int32_t)); + memset(cd->out, 0, TDFB_IN_BUF_LENGTH * sizeof(int32_t)); + + return 0; +} + +static const struct module_interface tdfb_interface = { + .init = tdfb_init, + .free = tdfb_free, + .set_configuration = tdfb_set_config, + .get_configuration = tdfb_get_config, + .process_audio_stream = tdfb_process, + .prepare = tdfb_prepare, + .reset = tdfb_reset, +}; + +#if CONFIG_COMP_TDFB_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("TDFB", &tdfb_interface, 1, SOF_REG_UUID(tdfb), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(tdfb_tr, SOF_UUID(tdfb_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(tdfb_interface, tdfb_uuid, tdfb_tr); +SOF_MODULE_INIT(tdfb, sys_comp_module_tdfb_interface_init); + +#endif diff --git a/src/audio/tdfb/tdfb.h b/src/audio/tdfb/tdfb.h new file mode 100644 index 000000000000..d5a09776301f --- /dev/null +++ b/src/audio/tdfb/tdfb.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __USER_TDFB_H__ +#define __USER_TDFB_H__ + +#include <stdint.h> + +#define SOF_TDFB_NUM_INPUT_PINS 1 /* One source */ +#define SOF_TDFB_NUM_OUTPUT_PINS 1 /* One sink */ +#define SOF_TDFB_MAX_SIZE 4096 /* Max size for coef data in bytes */ +#define SOF_TDFB_FIR_MAX_LENGTH 256 /* Max length for individual filter */ +#define SOF_TDFB_FIR_MAX_COUNT 16 /* A blob can define max 16 FIR EQs */ +#define SOF_TDFB_MAX_STREAMS 8 /* Support 1..8 sinks */ +#define SOF_TDFB_MAX_ANGLES 360 /* Up to 1 degree precision for 360 degrees coverage */ +#define SOF_TDFB_MAX_MICROPHONES 16 /* Up to 16 microphone locations */ + +/* The driver assigns running numbers for control index. If there's single control of + * type switch, enum, binary they all have index 0. + */ +#define SOF_TDFB_CTRL_INDEX_PROCESS 0 /* switch */ +#define SOF_TDFB_CTRL_INDEX_DIRECTION 1 /* switch */ +#define SOF_TDFB_CTRL_INDEX_AZIMUTH 0 /* enum */ +#define SOF_TDFB_CTRL_INDEX_AZIMUTH_ESTIMATE 1 /* enum */ +#define SOF_TDFB_CTRL_INDEX_FILTERBANK 0 /* bytes */ + +/* + * sof_tdfb_config data[] + + * int16_t fir_filter1[length_filter1]; Multiple of 4 taps and 32 bit align + * int16_t fir_filter2[length_filter2]; Multiple of 4 taps and 32 bit align + * ... + * int16_t fir_filterN[length_filterN]; Multiple of 4 taps and 32 bit align + * int16_t input_channel_select[num_filters]; 0 = ch0, 1 = 1ch1, .. + * int16_t output_channel_mix[num_filters]; + * int16_t output_stream_mix[num_filters]; + * + */ + +struct sof_tdfb_config { + uint32_t size; /* Size of entire struct */ + uint16_t num_filters; /* Total number of filters */ + uint16_t num_output_channels; /* Total number of output channels */ + uint16_t num_output_streams; /* one source, N output sinks */ + + /* Since ABI version 3.19 */ + uint16_t num_mic_locations; /* Number of microphones locations entries */ + uint16_t num_angles; /* Number of steer angles in data, not counting beam off */ + uint16_t beam_off_defined; /* Set if a beam off filters configuration is present */ + uint16_t track_doa; /* Track direction of arrival angle */ + int16_t angle_enum_mult; /* Multiply enum value (0..15) to get angle in degrees */ + int16_t angle_enum_offs; /* After multiplication add this degrees offset to angle */ + + /* reserved */ + uint16_t reserved16; /* To keep data 32 bit aligned */ + uint32_t reserved32[1]; /* For future */ + + int16_t data[]; +} __attribute__((packed)); + +struct sof_tdfb_angle { + int16_t azimuth; /* Beam polar azimuth angle -180 to +180 degrees Q15.0 */ + int16_t elevation; /* Beam polar elevation angle -90 to +90 degrees Q15.0 */ + int16_t filter_index; /* Index of first filter for the filter bank for this beam angle */ + int16_t reserved; /* For future */ +} __attribute__((packed)); + +struct sof_tdfb_mic_location { + int16_t x; /* Microphone x coordinate as Q4.12 meters */ + int16_t y; /* Microphone y coordinate as Q4.12 meters */ + int16_t z; /* Microphone z coordinate as Q4.12 meters */ + int16_t reserved; /* For future */ +} __attribute__((packed)); + +#endif /* __USER_TDFB_H__ */ diff --git a/src/audio/tdfb/tdfb.toml b/src/audio/tdfb/tdfb.toml new file mode 100644 index 000000000000..ffd25a63d0c1 --- /dev/null +++ b/src/audio/tdfb/tdfb.toml @@ -0,0 +1,22 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # TDFB module config + [[module.entry]] + name = "TDFB" + uuid = UUIDREG_STR_TDFB + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + init_config = "1" + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/tdfb/tdfb_comp.h b/src/audio/tdfb/tdfb_comp.h new file mode 100644 index 000000000000..ef33f28fa612 --- /dev/null +++ b/src/audio/tdfb/tdfb_comp.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_TDFB_CONFIG_H__ +#define __SOF_AUDIO_TDFB_CONFIG_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/audio_stream.h> +#include <sof/math/fir_generic.h> +#include <sof/math/fir_hifi2ep.h> +#include <sof/math/fir_hifi3.h> +#include <sof/math/iir_df1.h> +#include <sof/platform.h> +#include <sof/common.h> + +/* TDFB and EQFIR depend on math FIR. + * so align TDFB, math FIR, and EQFIR use same selection. + */ +#if SOF_USE_MIN_HIFI(3, FILTER) +#define TDFB_HIFI3 1 +#elif SOF_USE_HIFI(2, FILTER) +#define TDFB_HIFI2 1 +#else +#define TDFB_GENERIC 1 +#endif + +#define TDFB_IN_BUF_LENGTH (2 * PLATFORM_MAX_CHANNELS) +#define TDFB_OUT_BUF_LENGTH (2 * PLATFORM_MAX_CHANNELS) + +/* When set to one only one IPC is sent to host. There is not other requests + * triggered. If set to zero the IPC sent will be empty and the driver will + * issue an actual control get. In simple case with known # of control channels + * including is more efficient. + */ +#define TDFB_ADD_DIRECTION_TO_GET_CMD 1 + +/* Allocate size is header plus single control value */ +#define TDFB_GET_CTRL_DATA_SIZE (sizeof(struct sof_ipc_ctrl_data) + \ + sizeof(struct sof_ipc_ctrl_value_chan)) + +/* Process max 10% more frames than one period */ +#define TDFB_MAX_FRAMES_MULT_Q14 Q_CONVERT_FLOAT(1.10, 14) + +/* TDFB component private data */ + +struct tdfb_direction_data { + struct iir_state_df1 emphasis[PLATFORM_MAX_CHANNELS]; + int32_t timediff[PLATFORM_MAX_CHANNELS]; + int32_t timediff_iter[PLATFORM_MAX_CHANNELS]; + int64_t level_ambient; + uint32_t trigger; + int32_t level; + int32_t unit_delay; /* Q1.31 seconds */ + int32_t frame_count_since_control; + int32_t *df1_delay; + int32_t *r; + int16_t *d; + int16_t *d_end; + int16_t *wp; + int16_t *rp; + int16_t step_sign; + int16_t az_slow; + int16_t az; + int16_t max_lag; + size_t d_size; + size_t r_size; + bool line_array; /* Limit scan to -90 to 90 degrees */ +}; + +struct tdfb_comp_data { + struct fir_state_32x16 fir[SOF_TDFB_FIR_MAX_COUNT]; /**< FIR state */ + struct comp_data_blob_handler *model_handler; + struct sof_tdfb_config *config; /**< pointer to setup blob */ + struct sof_tdfb_angle *filter_angles; + struct sof_tdfb_mic_location *mic_locations; + struct sof_ipc_ctrl_data *ctrl_data; + struct ipc_msg *msg; + struct tdfb_direction_data direction; + int32_t in[TDFB_IN_BUF_LENGTH]; /**< input samples buffer */ + int32_t out[TDFB_IN_BUF_LENGTH]; /**< output samples mix buffer */ + int32_t *fir_delay; /**< pointer to allocated RAM */ + int16_t *input_channel_select; /**< For each FIR define in ch */ + int16_t *output_channel_mix; /**< For each FIR define out ch */ + int16_t *output_stream_mix; /**< for each FIR define stream */ + int16_t az_value; /**< beam steer azimuth as in control enum */ + int16_t az_value_estimate; /**< beam steer azimuth as in control enum */ + size_t fir_delay_size; /**< allocated size */ + unsigned int max_frames; /**< max frames to process */ + bool direction_updates:1; /**< set true if direction angle control is updated */ + bool direction_change:1; /**< set if direction value has significant change */ + bool beam_on:1; /**< set true if beam is off */ + bool update:1; /**< set true if control enum has been received */ + void (*tdfb_func)(struct tdfb_comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, + int frames); +}; + +#if CONFIG_FORMAT_S16LE +void tdfb_fir_s16(struct tdfb_comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif + +#if CONFIG_FORMAT_S24LE +void tdfb_fir_s24(struct tdfb_comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif + +#if CONFIG_FORMAT_S32LE +void tdfb_fir_s32(struct tdfb_comp_data *cd, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif + +int tdfb_direction_init(struct processing_module *mod, int32_t fs, int channels); +void tdfb_direction_copy_emphasis(struct tdfb_comp_data *cd, int channels, int *channel, int32_t x); +void tdfb_direction_estimate(struct tdfb_comp_data *cd, int frames, int channels); +void tdfb_direction_free(struct processing_module *mod); + +static inline void tdfb_cinc_s16(int16_t **ptr, int16_t *end, size_t size) +{ + if (*ptr >= end) + *ptr = (int16_t *)((uint8_t *)*ptr - size); +} + +static inline void tdfb_cdec_s16(int16_t **ptr, int16_t *start, size_t size) +{ + if (*ptr < start) + *ptr = (int16_t *)((uint8_t *)*ptr + size); +} + +int tdfb_ipc_notification_init(struct processing_module *mod); +void tdfb_send_ipc_notification(struct processing_module *mod); +int tdfb_get_ipc_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); +int tdfb_set_ipc_config(struct processing_module *mod, uint32_t param_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); +int tdfb_params(struct processing_module *mod); + +#ifdef UNIT_TEST +void sys_comp_module_tdfb_interface_init(void); +#endif + +#endif /* __SOF_AUDIO_TDFB_CONFIG_H__ */ diff --git a/src/audio/tdfb/tdfb_direction.c b/src/audio/tdfb/tdfb_direction.c new file mode 100644 index 000000000000..71b544003ee7 --- /dev/null +++ b/src/audio/tdfb/tdfb_direction.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include "tdfb.h" +#include "tdfb_comp.h" + +#include <ipc/topology.h> +#include <sof/math/iir_df1.h> +#include <sof/math/trig.h> +#include <sof/math/sqrt.h> +#include <user/eq.h> +#include <stdint.h> + +/* Generic definitions */ +#define COEF_DEG_TO_RAD Q_CONVERT_FLOAT(0.017453, 15) /* Q1.15 */ +#define COEF_RAD_TO_DEG Q_CONVERT_FLOAT(57.296, 9) /* Q6.9 */ +#define PI_Q12 Q_CONVERT_FLOAT(3.1416, 12) +#define PIMUL2_Q12 Q_CONVERT_FLOAT(6.2832, 12) +#define PIDIV2_Q12 Q_CONVERT_FLOAT(1.5708, 12) + +/* Sound levels filtering related, these form a primitive voice activity + * detector. Sound levels below ambient estimate times threshold (kind of dB offset) + * are not scanned for sound direction. + */ +#define SLOW_LEVEL_SHIFT 12 +#define FAST_LEVEL_SHIFT 1 +#define POWER_THRESHOLD Q_CONVERT_FLOAT(15.849, 10) /* 12 dB, value is 10^(dB/10) */ + +/* Iteration parameters, smaller step and larger iterations is more accurate but + * consumes more cycles. + */ +#define AZ_STEP Q_CONVERT_FLOAT(0.6, 12) /* Radians as Q4.12 (~34 deg) */ +#define AZ_ITERATIONS 8 /* loops in min err search */ +#define SOURCE_DISTANCE Q_CONVERT_FLOAT(3.0, 12) /* source distance in m Q4.12 */ + +/* Sound direction angle filtering */ +#define SLOW_AZ_C1 Q_CONVERT_FLOAT(0.02, 15) +#define SLOW_AZ_C2 Q_CONVERT_FLOAT(0.98, 15) + +/* Threshold for notifying user space, no more often than every 200 ms */ +#define CONTROL_UPDATE_MIN_TIME Q_CONVERT_FLOAT(0.2, 16) + +/* Another filter, a bit mask for controlling notifications to user space, at least four + * periods with level over ambient + */ +#define CONTROL_UPDATE_MIN_MASK 0x0f + +/* Emphasis filters for sound direction (IIR). These coefficients were + * created with the script tools/tune/tdfb/example_direction_emphasis.m + * from output files tdfb_iir_emphasis_48k.h and tdfb_iir_emphasis_16k.h. + */ + +uint32_t iir_emphasis_48k[20] = { + 0x00000002, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xc8cf47b5, 0x7689916a, + 0x1dc95968, 0xc46d4d30, 0x1dc95968, 0x00000000, + 0x00004000, 0xe16f20ea, 0x51e57f66, 0x01966267, + 0x032cc4ce, 0x01966267, 0xfffffffe, 0x00004222 +}; + +uint32_t iir_emphasis_16k[20] = { + 0x00000002, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xd6f418ae, 0x63e7b85c, + 0x19ae069b, 0xcca3f2ca, 0x19ae069b, 0x00000000, + 0x00004000, 0xf504f334, 0x00000000, 0x09651419, + 0x12ca2831, 0x09651419, 0xfffffffe, 0x0000414c +}; + +/** + * \brief This function copies data to sound direction estimation + * + * Function to copy data from component source to cross correlation buffer. The copy + * operation includes emphasis filtering. The copy is skipped if tracking is not + * enabled. + * + * \param[in,out] cd Component data + * \param[in] ch_count Number of channels in audio stream + * \param[in,out] ch Current channel for emphasis, incremented + * and reset to zero after channel_count -1. + * \param[in] x Input PCM sample + */ +void tdfb_direction_copy_emphasis(struct tdfb_comp_data *cd, int ch_count, int *ch, int32_t x) +{ + int32_t y; + + y = iir_df1(&cd->direction.emphasis[*ch], x); + *cd->direction.wp = sat_int16(Q_SHIFT_RND(y, 31, 18)); /* 18 dB boost after high-pass */ + cd->direction.wp++; + tdfb_cinc_s16(&cd->direction.wp, cd->direction.d_end, cd->direction.d_size); + (*ch)++; + if (*ch == ch_count) + *ch = 0; +} + +/* Use function y = sqrt_int16(x), where x is Q4.12 unsigned, y is Q4.12 + * TODO: Add scaling of input to Q4.12 with a suitable N^2 or (1/N)^2 value + * to increase sqrt() computation precision and avoid MIN() function to + * saturate for large distances (over 4m). The current virtual source + * distance 3m allows max 1m size array for this to work correctly without + * hitting the saturation. + */ +static inline int16_t tdfb_mic_distance_sqrt(int32_t x) +{ + int32_t xs; + + xs = Q_SHIFT_RND(x, 24, 12); + xs = MIN(xs, UINT16_MAX); + return sofm_sqrt_int16((uint16_t)xs); +} + +static int16_t max_mic_distance(struct tdfb_comp_data *cd) +{ + int16_t d; + int16_t dx; + int16_t dy; + int16_t dz; + int32_t d2; + int32_t d2_max = 0; + int i; + int j; + + /* Max lag based on largest array dimension. Microphone coordinates are Q4.12 meters */ + for (i = 0; i < cd->config->num_mic_locations; i++) { + /* Calculate distances between all possible microphone pairs to + * find the maximum distance + */ + for (j = i + 1; j < cd->config->num_mic_locations; j++) { + dx = cd->mic_locations[i].x - cd->mic_locations[j].x; + dy = cd->mic_locations[i].y - cd->mic_locations[j].y; + dz = cd->mic_locations[i].z - cd->mic_locations[j].z; + + /* d2 is Q8.24 meters */ + d2 = dx * dx + dy * dy + dz * dz; + if (d2 > d2_max) + d2_max = d2; + } + } + + /* Squared distance is Q8.24, return Q4.12 meters */ + d = tdfb_mic_distance_sqrt(d2_max); + return d; +} + +static bool line_array_mode_check(struct tdfb_comp_data *cd) +{ + int32_t px, py, pz; + int16_t a, b, c, d, e, f; + int i; + int num_mic_locations = cd->config->num_mic_locations; + + if (num_mic_locations == 2) + return true; + + /* Cross product of vectors AB and AC is (0, 0, 0) if they are co-linear. + * Form vector AB(a,b,c) from x(i+1) - x(i), y(i+1) - y(i), z(i+1) - z(i) + * Form vector AC(d,e,f) from x(i+2) - x(i), y(i+2) - y(i), z(i+2) - z(i) + */ + for (i = 0; i < num_mic_locations - 2; i++) { + a = cd->mic_locations[i + 1].x - cd->mic_locations[i].x; + b = cd->mic_locations[i + 1].y - cd->mic_locations[i].y; + c = cd->mic_locations[i + 1].z - cd->mic_locations[i].z; + d = cd->mic_locations[i + 2].x - cd->mic_locations[i].x; + e = cd->mic_locations[i + 2].y - cd->mic_locations[i].y; + f = cd->mic_locations[i + 2].z - cd->mic_locations[i].z; + cross_product_s16(&px, &py, &pz, a, b, c, d, e, f); + + /* Allow small room for rounding error with |x| > 1 in check */ + if (ABS(px) > 1 || ABS(py) > 1 || ABS(pz) > 1) + return false; + } + + return true; +} + +int tdfb_direction_init(struct processing_module *mod, int32_t fs, int ch_count) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + struct sof_eq_iir_header *filt; + int32_t *delay; + int32_t d_max; + int32_t t_max; + size_t size; + int n; + int i; + + /* Select emphasis response per sample rate */ + switch (fs) { + case 16000: + filt = (struct sof_eq_iir_header *)iir_emphasis_16k; + break; + case 48000: + filt = (struct sof_eq_iir_header *)iir_emphasis_48k; + break; + default: + return -EINVAL; + } + + /* Allocate delay lines for IIR filters and initialize them */ + size = ch_count * iir_delay_size_df1(filt); + delay = mod_zalloc(mod, size); + if (!delay) + return -ENOMEM; + + cd->direction.df1_delay = delay; + for (i = 0; i < ch_count; i++) { + iir_init_coef_df1(&cd->direction.emphasis[i], filt); + iir_init_delay_df1(&cd->direction.emphasis[i], &delay); + } + + /* Unit delay length in Q1.31 seconds */ + cd->direction.unit_delay = Q_SHIFT_LEFT(1LL, 0, 31) / fs; + + /* Get max possible mic-mic distance, then from max distance to max time t = d_max / v, + * t is Q1.15, d is Q4.12, v is Q9.0 + */ + d_max = max_mic_distance(cd); + t_max = Q_SHIFT_LEFT(d_max, 12, 15) / SPEED_OF_SOUND; + + /* Calculate max lag to search and allocate delay line for cross correlation + * compute. Add one to make sure max possible lag is in search window. + */ + cd->direction.max_lag = Q_MULTSR_32X32((int64_t)fs, t_max, 0, 15, 0) + 1; + n = (cd->max_frames + (2 * cd->direction.max_lag + 1)) * ch_count; + cd->direction.d_size = n * sizeof(int16_t); + cd->direction.d = mod_zalloc(mod, cd->direction.d_size); + if (!cd->direction.d) + goto err_free_iir; + + /* Set needed pointers to xcorr delay line, advance write pointer by max_lag to keep read + * always behind write + */ + cd->direction.d_end = cd->direction.d + n; + cd->direction.rp = cd->direction.d; + cd->direction.wp = cd->direction.d + ch_count * (cd->direction.max_lag + 1); + + /* xcorr result is temporary but too large for stack so it is allocated here */ + cd->direction.r_size = (2 * cd->direction.max_lag + 1) * sizeof(int32_t); + cd->direction.r = mod_zalloc(mod, cd->direction.r_size); + if (!cd->direction.r) + goto err_free_all; + + /* Check for line array mode */ + cd->direction.line_array = line_array_mode_check(cd); + + /* Initialize direction to zero radians, set initial step sign to +1 */ + cd->direction.az = 0; + cd->direction.step_sign = 1; + return 0; + +err_free_all: + mod_free(mod, cd->direction.d); + cd->direction.d = NULL; + +err_free_iir: + mod_free(mod, cd->direction.df1_delay); + cd->direction.df1_delay = NULL; + return -ENOMEM; +} + +void tdfb_direction_free(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + mod_free(mod, cd->direction.df1_delay); + mod_free(mod, cd->direction.d); + mod_free(mod, cd->direction.r); +} + +/* Measure level of one channel */ +static void level_update(struct tdfb_comp_data *cd, int frames, int ch_count, int channel) +{ + int64_t tmp = 0; + int64_t ambient; + int64_t level; + int16_t s; + int16_t *p = cd->direction.rp + channel; + int shift; + int thr; + int n; + + /* Calculate mean square level */ + for (n = 0; n < frames; n++) { + s = *p; + tmp += ((int32_t)s * s); + p += ch_count; + tdfb_cinc_s16(&p, cd->direction.d_end, cd->direction.d_size); + } + + /* Calculate mean square power */ + cd->direction.level = sat_int32(tmp / frames); + + /* Slow track minimum level and use it as ambient noise level estimate */ + level = ((int64_t)cd->direction.level) << 32; + ambient = cd->direction.level_ambient; + shift = (level < ambient) ? FAST_LEVEL_SHIFT : SLOW_LEVEL_SHIFT; + ambient = (level >> shift) - (ambient >> shift) + ambient; + thr = sat_int32(Q_MULTS_32X32(ambient >> 32, POWER_THRESHOLD, 31, 10, 31)); /* int64_t */ + cd->direction.level_ambient = ambient; + cd->direction.trigger <<= 1; + if (cd->direction.level > thr) + cd->direction.trigger |= 1; + + /* Levels update runs always when tracking, increment frame counter until wrap */ + cd->direction.frame_count_since_control += frames; + if (cd->direction.frame_count_since_control < 0) + cd->direction.frame_count_since_control = INT32_MAX; +} + +static int find_max_value_index(int32_t *v, int length) +{ + int idx = 0; + int i; + + for (i = 1; i < length; i++) { + if (v[i] > v[idx]) + idx = i; + } + + return idx; +} + +static void time_differences(struct tdfb_comp_data *cd, int frames, int ch_count) +{ + int64_t r; + int16_t *x; + int16_t *y; + int r_max_idx; + int max_lag = cd->direction.max_lag; + int c; + int k; + int i; + int32_t maxval = 0; + + /* Calculate xcorr for channel 0 vs. 1 .. (ch_count-1). Scan -maxlag .. +maxlag*/ + for (c = 1; c < ch_count; c++) { + for (k = -max_lag; k <= max_lag; k++) { + y = cd->direction.rp; /* First channel */ + x = y + k * ch_count + c; /* other channel C */ + tdfb_cinc_s16(&x, cd->direction.d_end, cd->direction.d_size); + tdfb_cdec_s16(&x, cd->direction.d, cd->direction.d_size); + r = 0; + for (i = 0; i < frames; i++) { + if (maxval < *y) + maxval = *y; + + r += (int32_t)*x * *y; + y += ch_count; + tdfb_cinc_s16(&y, cd->direction.d_end, cd->direction.d_size); + x += ch_count; + tdfb_cinc_s16(&x, cd->direction.d_end, cd->direction.d_size); + } + /* Scale for max. 20 ms 48 kHz frame */ + cd->direction.r[k + max_lag] = sat_int32(((r >> 8) + 1) >> 1); + } + r_max_idx = find_max_value_index(&cd->direction.r[0], 2 * max_lag + 1); + cd->direction.timediff[c - 1] = (int32_t)(r_max_idx - max_lag) * + cd->direction.unit_delay; + } + cd->direction.rp += frames * ch_count; + tdfb_cinc_s16(&cd->direction.rp, cd->direction.d_end, cd->direction.d_size); +} + +static int16_t distance_from_source(struct tdfb_comp_data *cd, int mic_n, + int16_t x, int16_t y, int16_t z) +{ + int32_t d2; + int16_t dx; + int16_t dy; + int16_t dz; + int16_t d; + + dx = x - cd->mic_locations[mic_n].x; + dy = y - cd->mic_locations[mic_n].y; + dz = z - cd->mic_locations[mic_n].z; + + /* d2 is Q8.24 meters */ + d2 = dx * dx + dy * dy + dz * dz; + + /* Squared distance is Q8.24, return Q4.12 meters */ + d = tdfb_mic_distance_sqrt(d2); + return d; +} + +static void theoretical_time_differences(struct tdfb_comp_data *cd, int16_t az) +{ + int16_t d[PLATFORM_MAX_CHANNELS]; + int16_t src_x; + int16_t src_y; + int16_t sin_az; + int16_t cos_az; + int32_t delta_d; + int n_mic = cd->config->num_mic_locations; + int i; + + sin_az = sin_fixed_16b(Q_SHIFT_LEFT((int32_t)az, 12, 28)); /* Q1.15 */ + cos_az = cos_fixed_16b(Q_SHIFT_LEFT((int32_t)az, 12, 28)); /* Q1.15 */ + src_x = Q_MULTSR_16X16((int32_t)cos_az, SOURCE_DISTANCE, 15, 12, 12); + src_y = Q_MULTSR_16X16((int32_t)sin_az, SOURCE_DISTANCE, 15, 12, 12); + + for (i = 0; i < n_mic; i++) + d[i] = distance_from_source(cd, i, src_x, src_y, 0); + + for (i = 0; i < n_mic - 1; i++) { + delta_d = d[i + 1] - d[0]; /* Meters Q4.12 */ + /* Multiply delta_d (Q4.12) by RECIPROCAL_SPEED_OF_SOUND_Q31 (Q1.31) and + * right-shift the result by 12 bits to preserve the Q1.31 format. + */ + cd->direction.timediff_iter[i] = + Q_MULTS_32X32((int64_t)delta_d, RECIPROCAL_SPEED_OF_SOUND_Q31, 12, 31, 31); + } +} + +static int64_t mean_square_time_difference_err(struct tdfb_comp_data *cd) +{ + int64_t err = 0; + int32_t delta; + int i; + + for (i = 0; i < cd->config->num_mic_locations - 1; i++) { + delta = cd->direction.timediff[i] - cd->direction.timediff_iter[i]; + err += (int64_t)delta * delta; + } + + return err; +} + +static int unwrap_radians(int radians) +{ + int a = radians; + + if (a > PI_Q12) + a -= PIMUL2_Q12; + + if (a < -PI_Q12) + a += PIMUL2_Q12; + + return a; +} + +static void iterate_source_angle(struct tdfb_comp_data *cd) +{ + int64_t err_prev; + int64_t err; + int32_t ds1; + int32_t ds2; + int az_slow; + int i; + int az_step = AZ_STEP * cd->direction.step_sign; + int az = cd->direction.az_slow; + + /* Start next iteration opposite direction */ + cd->direction.step_sign *= -1; + + /* Get theoretical time differences for previous angle */ + theoretical_time_differences(cd, az); + err_prev = mean_square_time_difference_err(cd); + + for (i = 0; i < AZ_ITERATIONS; i++) { + az += az_step; + theoretical_time_differences(cd, az); + err = mean_square_time_difference_err(cd); + if (err > err_prev) { + az_step = -(az_step >> 1); + if (az_step == 0) + break; + } + + err_prev = err; + } + + az = unwrap_radians(az); + if (cd->direction.line_array) { + /* Line array azimuth angle is -90 .. +90 */ + if (az > PIDIV2_Q12) + az = PI_Q12 - az; + + if (az < -PIDIV2_Q12) + az = -PI_Q12 - az; + } + + cd->direction.az = az; + + /* Avoid low-pass filtering to zero the angle in 360 degree arrays + * due to discontinuity at -180 or +180 degree point and estimation + * noise. Try to camp on either side of the circle. + */ + ds1 = cd->direction.az_slow - az; + ds1 = ds1 * ds1; + ds2 = cd->direction.az_slow - (az - 360); + ds2 = ds2 * ds2; + if (ds2 < ds1) { + az -= 360; + } else { + ds2 = cd->direction.az_slow - (az + 360); + ds2 = ds2 * ds2; + if (ds2 < ds1) + az += 360; + } + + az_slow = Q_MULTSR_16X16((int32_t)az, SLOW_AZ_C1, 12, 15, 12) + + Q_MULTSR_16X16((int32_t)cd->direction.az_slow, SLOW_AZ_C2, 12, 15, 12); + cd->direction.az_slow = unwrap_radians(az_slow); +} + +static void updates_when_no_trigger(struct tdfb_comp_data *cd, int frames, int ch_count) +{ + cd->direction.rp += frames * ch_count; + tdfb_cinc_s16(&cd->direction.rp, cd->direction.d_end, cd->direction.d_size); +} + +static int convert_angle_to_enum(struct tdfb_comp_data *cd) +{ + int16_t deg; + int new_az_value; + + /* Update azimuth enum with radians to degrees to enum step conversion. First + * convert radians to deg, subtract angle offset, and make angles positive. + */ + deg = Q_MULTS_16X16((int32_t)cd->direction.az_slow, COEF_RAD_TO_DEG, 12, 9, 0) - + cd->config->angle_enum_offs; + + /* Divide and round to enum angle scale, remove duplicate 0 and 360 degree angle + * representation to have single zero degree enum. + */ + new_az_value = ((2 * deg / cd->config->angle_enum_mult) + 1) >> 1; + if (new_az_value * cd->config->angle_enum_mult == 360) + new_az_value -= 360 / cd->config->angle_enum_mult; + + return new_az_value; +} + +/* Placeholder function for sound direction estimate */ +void tdfb_direction_estimate(struct tdfb_comp_data *cd, int frames, int ch_count) +{ + int32_t time_since; + int new_az_value; + + if (!cd->direction_updates) + return; + + /* Update levels, skip rest of estimation if level does not exceed well ambient */ + level_update(cd, frames, ch_count, 0); + if (!(cd->direction.trigger & 1)) { + updates_when_no_trigger(cd, frames, ch_count); + return; + } + + /* Compute time differences of ch_count vs. reference channel 1 */ + time_differences(cd, frames, ch_count); + + /* Determine direction angle */ + iterate_source_angle(cd); + + /* Convert radians to enum*/ + new_az_value = convert_angle_to_enum(cd); + + /* Time after last control as Q16.16, unit delay is Q1.131, count is Q0. */ + time_since = Q_MULTS_32X32((int64_t)cd->direction.unit_delay, + cd->direction.frame_count_since_control, 31, 0, 16); + + /* Need a new enum value, sufficient time since last update and four measurement frames + * to update user space. + */ + if (new_az_value != cd->az_value_estimate && time_since > CONTROL_UPDATE_MIN_TIME && + (cd->direction.trigger & CONTROL_UPDATE_MIN_MASK) == CONTROL_UPDATE_MIN_MASK) { + cd->az_value_estimate = new_az_value; + cd->direction.frame_count_since_control = 0; + cd->direction_change = true; + } +} diff --git a/src/audio/tdfb/tdfb_generic.c b/src/audio/tdfb/tdfb_generic.c new file mode 100644 index 000000000000..ba4e44c8073f --- /dev/null +++ b/src/audio/tdfb/tdfb_generic.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/audio_stream.h> +#include <user/fir.h> + +#include "tdfb.h" +#include "tdfb_comp.h" + +#if TDFB_GENERIC + +#include <sof/math/fir_generic.h> + +static inline void tdfb_core(struct tdfb_comp_data *cd, int in_nch, int out_nch) +{ + struct fir_state_32x16 *filter; + int32_t y0; + int32_t y1; + int is2; + int is; + int om; + int i; + int k; + const int num_filters = cd->config->num_filters; + + /* Clear output mix*/ + memset(cd->out, 0, 2 * out_nch * sizeof(int32_t)); + + /* Run and mix all filters to their output channel */ + for (i = 0; i < num_filters; i++) { + is = cd->input_channel_select[i]; + is2 = is + in_nch; + om = cd->output_channel_mix[i]; + filter = &cd->fir[i]; + /* Process sample and successive sample. This follows + * optimized FIR version implementation that processes + * two samples per call. The output is stored as Q5.27 + * to fit max. 16 filters sum to a channel. + */ + fir_32x16_2x(filter, cd->in[is], cd->in[is2], &y0, &y1); + y0 >>= 4; + y1 >>= 4; + for (k = 0; k < out_nch; k++) { + if (om & 1) { + cd->out[k] += y0; + cd->out[k + out_nch] += y1; + } + om = om >> 1; + } + } +} + + +#if CONFIG_FORMAT_S16LE +void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + int remaining_frames = frames; + int emp_ch = 0; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + /* Read two frames from all input channels */ + for (i = 0; i < 2 * in_nch; i++) { + cd->in[i] = *x << 16; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, *x << 16); + + x++; + } + + /* Process */ + tdfb_core(cd, in_nch, out_nch); + + /* Write two frames of output */ + for (i = 0; i < 2 * out_nch; i++) { + *y = sat_int16(Q_SHIFT_RND(cd->out[i], 27, 15)); + y++; + } + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S24LE +void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + int remaining_frames = frames; + int emp_ch = 0; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + /* Read two frames from all input channels */ + for (i = 0; i < 2 * in_nch; i++) { + cd->in[i] = *x << 8; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, *x << 8); + + x++; + } + + /* Process */ + tdfb_core(cd, in_nch, out_nch); + + /* Write two frames of output */ + for (i = 0; i < 2 * out_nch; i++) { + *y = sat_int24(Q_SHIFT_RND(cd->out[i], 27, 23)); + y++; + } + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S32LE +void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + int remaining_frames = frames; + int emp_ch = 0; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + /* Read two frames from all input channels */ + for (i = 0; i < 2 * in_nch; i++) { + cd->in[i] = *x; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, *x); + + x++; + } + + /* Process */ + tdfb_core(cd, in_nch, out_nch); + + /* Write two frames of output. In Q5.27 to Q1.31 conversion + * rounding is not applicable so just shift left by 4. + */ + for (i = 0; i < 2 * out_nch; i++) { + *y = sat_int32((int64_t)cd->out[i] << 4); + y++; + } + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#endif /* TDFB_GENERIC */ + diff --git a/src/audio/tdfb/tdfb_hifi3.c b/src/audio/tdfb/tdfb_hifi3.c new file mode 100644 index 000000000000..f5484d337395 --- /dev/null +++ b/src/audio/tdfb/tdfb_hifi3.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/audio_stream.h> +#include <user/fir.h> + +#include "tdfb.h" +#include "tdfb_comp.h" + +#if TDFB_HIFI3 + +#include <sof/math/fir_hifi3.h> + +#if CONFIG_FORMAT_S16LE +void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct sof_tdfb_config *cfg = cd->config; + struct fir_state_32x16 *f; + ae_int16x4 d; + ae_int32 y0; + ae_int32 y1; + ae_int16 *x = audio_stream_get_rptr(source); + ae_int16 *y = audio_stream_get_wptr(sink); + int shift; + int is2; + int is; + int om; + int i; + int j; + int k; + int in_nch = audio_stream_get_channels(source); + int out_nch = audio_stream_get_channels(sink); + int emp_ch = 0; + int n, nmax; + int remaining_frames = frames; + const int inc = sizeof(ae_int16); + + while (remaining_frames) { + nmax = audio_stream_frames_without_wrap(source, x); + n = MIN(remaining_frames, nmax); + nmax = audio_stream_frames_without_wrap(sink, y); + n = MIN(n, nmax); + + for (j = 0; j < n; j += 2) { + /* Clear output mix*/ + memset(cd->out, 0, 2 * out_nch * sizeof(int32_t)); + + /* Read two frames from all input channels + * there won't be buffer overflow since we + * set 2 frames align in tdfb_prepare function. + */ + for (i = 0; i < 2 * in_nch; i++) { + AE_L16_XP(d, x, inc); + cd->in[i] = (ae_int32)AE_CVT32X2F16_32(d); + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, + cd->in[i]); + } + + /* Run and mix all filters to their output channel */ + for (i = 0; i < cfg->num_filters; i++) { + is = cd->input_channel_select[i]; + is2 = is + in_nch; + om = cd->output_channel_mix[i]; + + /* Get filter instance */ + f = &cd->fir[i]; + shift = -f->out_shift; + + /* Compute FIR and mix as Q5.27*/ + fir_core_setup_circular(f); + fir_32x16_2x(f, cd->in[is], cd->in[is2], &y0, &y1, shift); + for (k = 0; k < out_nch; k++) { + if (om & 1) { + cd->out[k] += (int32_t)y0 >> 4; + cd->out[k + out_nch] += + (int32_t)y1 >> 4; + } + om = om >> 1; + } + } + + /* Write two frames of output. The values in out[] are shifted + * left and saturated to convert to Q1.27. The values + * are then rounded to 16 bit and converted to Q1.15 for + * sink buffer. TODO: Could saturate four samples with + * one AE_ROUND16X4F32SSYM() instruction. + */ + for (i = 0; i < 2 * out_nch; i++) { + d = AE_ROUND16X4F32SSYM(0, AE_SLAI32S(cd->out[i], 4)); + AE_S16_0_XP(d, y, inc); + } + } + remaining_frames -= n; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S24LE +void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct sof_tdfb_config *cfg = cd->config; + struct fir_state_32x16 *f; + ae_int32x2 d; + ae_int32 y0; + ae_int32 y1; + ae_int32 *x = audio_stream_get_rptr(source); + ae_int32 *y = audio_stream_get_wptr(sink); + int shift; + int is2; + int is; + int om; + int i; + int j; + int k; + int in_nch = audio_stream_get_channels(source); + int out_nch = audio_stream_get_channels(sink); + int emp_ch = 0; + int n, nmax; + int remaining_frames = frames; + const int inc = sizeof(ae_int32); + + while (remaining_frames) { + nmax = audio_stream_frames_without_wrap(source, x); + n = MIN(remaining_frames, nmax); + nmax = audio_stream_frames_without_wrap(sink, y); + n = MIN(n, nmax); + + for (j = 0; j < n; j += 2) { + /* Clear output mix*/ + memset(cd->out, 0, 2 * out_nch * sizeof(int32_t)); + + /* Read two frames from all input channels + * there won't be buffer overflow since we + * set 2 frames align in tdfb_prepare function. + */ + for (i = 0; i < 2 * in_nch; i++) { + AE_L32_XP(d, x, inc); + cd->in[i] = AE_SLAI32(d, 8); + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, + cd->in[i]); + } + + /* Run and mix all filters to their output channel */ + for (i = 0; i < cfg->num_filters; i++) { + is = cd->input_channel_select[i]; + is2 = is + in_nch; + om = cd->output_channel_mix[i]; + + /* Get filter instance */ + f = &cd->fir[i]; + shift = -f->out_shift; + + /* Compute FIR and mix as Q5.27*/ + fir_core_setup_circular(f); + fir_32x16_2x(f, cd->in[is], cd->in[is2], &y0, &y1, shift); + for (k = 0; k < out_nch; k++) { + if (om & 1) { + cd->out[k] += (int32_t)y0 >> 4; + cd->out[k + out_nch] += + (int32_t)y1 >> 4; + } + om = om >> 1; + } + } + + /* Write two frames of output. The values in out[] are shifted + * left and saturated to convert to Q1.27. The values + * are then rounded to 16 bit and converted to Q1.15 for + * sink buffer. TODO: Could saturate four samples with + * one AE_ROUND16X4F32SSYM() instruction. + */ + for (i = 0; i < 2 * out_nch; i++) { + d = AE_SRAI32(AE_SLAI32S(AE_SRAI32R(cd->out[i], 4), 8), 8); + AE_S32_L_XP(d, y, inc); + } + } + remaining_frames -= n; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S32LE +void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + struct sof_tdfb_config *cfg = cd->config; + struct fir_state_32x16 *f; + ae_int32x2 d; + ae_int32 y0; + ae_int32 y1; + ae_int32 *x = audio_stream_get_rptr(source); + ae_int32 *y = audio_stream_get_wptr(sink); + int shift; + int is2; + int is; + int om; + int i; + int j; + int k; + int in_nch = audio_stream_get_channels(source); + int out_nch = audio_stream_get_channels(sink); + int emp_ch = 0; + int n, nmax; + int remaining_frames = frames; + const int inc = sizeof(ae_int32); + + while (remaining_frames) { + nmax = audio_stream_frames_without_wrap(source, x); + n = MIN(remaining_frames, nmax); + nmax = audio_stream_frames_without_wrap(sink, y); + n = MIN(n, nmax); + + for (j = 0; j < n; j += 2) { + /* Clear output mix*/ + memset(cd->out, 0, 2 * out_nch * sizeof(int32_t)); + + /* Read two frames from all input channels + * there won't be buffer overflow since we + * set 2 frames align in tdfb_prepare function. + */ + for (i = 0; i < 2 * in_nch; i++) { + AE_L32_XC(d, x, inc); + cd->in[i] = d; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, + cd->in[i]); + } + + for (i = 0; i < cfg->num_filters; i++) { + is = cd->input_channel_select[i]; + is2 = is + in_nch; + om = cd->output_channel_mix[i]; + + /* Get filter instance */ + f = &cd->fir[i]; + shift = -f->out_shift; + + /* Compute FIR and mix as Q5.27*/ + fir_core_setup_circular(f); + fir_32x16_2x(f, cd->in[is], cd->in[is2], &y0, &y1, shift); + for (k = 0; k < out_nch; k++) { + if (om & 1) { + cd->out[k] += (int32_t)y0 >> 4; + cd->out[k + out_nch] += + (int32_t)y1 >> 4; + } + om = om >> 1; + } + } + + /* Write two frames of output. In Q5.27 to Q1.31 conversion + * rounding is not applicable so just shift left by 4 and + * saturate. TODO: Could shift two samples with one + * instruction. + */ + for (i = 0; i < 2 * out_nch; i++) { + d = AE_SLAI32S(cd->out[i], 4); + AE_S32_L_XP(d, y, inc); + } + } + remaining_frames -= n; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#endif /* TDFB_HIFI3 */ + diff --git a/src/audio/tdfb/tdfb_hifiep.c b/src/audio/tdfb/tdfb_hifiep.c new file mode 100644 index 000000000000..d6fea124b542 --- /dev/null +++ b/src/audio/tdfb/tdfb_hifiep.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/audio_stream.h> +#include <user/fir.h> + +#include "tdfb.h" +#include "tdfb_comp.h" + +#if TDFB_HIFIEP + +#include <sof/math/fir_hifi2ep.h> + +static inline void tdfb_core(struct tdfb_comp_data *cd, int in_nch, int out_nch) +{ + struct fir_state_32x16 *f; + int32_t y0; + int32_t y1; + int lshift; + int rshift; + int is2; + int is; + int om; + int i; + int k; + const int num_filters = cd->config->num_filters; + + /* Clear output mix*/ + memset(cd->out, 0, 2 * out_nch * sizeof(int32_t)); + + /* Run and mix all filters to their output channel */ + for (i = 0; i < num_filters; i++) { + is = cd->input_channel_select[i]; + is2 = is + in_nch; + om = cd->output_channel_mix[i]; + /* Prepare FIR */ + f = &cd->fir[i]; + fir_hifiep_setup_circular(f); + fir_get_lrshifts(f, &lshift, &rshift); + /* Process two samples */ + fir_32x16_2x(f, cd->in[is], cd->in[is2], &y0, &y1, lshift, rshift); + /* Mix as Q5.27 */ + for (k = 0; k < out_nch; k++) { + if (om & 1) { + cd->out[k] += y0 >> 4; + cd->out[k + out_nch] += y1 >> 4; + } + om = om >> 1; + } + } +} + +#if CONFIG_FORMAT_S16LE +void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + int remaining_frames = frames; + int emp_ch = 0; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + /* Read two frames from all input channels */ + for (i = 0; i < 2 * in_nch; i++) { + cd->in[i] = *x << 16; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, *x << 16); + + x++; + } + + /* Process */ + tdfb_core(cd, in_nch, out_nch); + + /* Write two frames of output */ + for (i = 0; i < 2 * out_nch; i++) { + *y = sat_int16(Q_SHIFT_RND(cd->out[i], 27, 15)); + y++; + } + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S24LE +void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + int remaining_frames = frames; + int emp_ch = 0; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + /* Read two frames from all input channels */ + for (i = 0; i < 2 * in_nch; i++) { + cd->in[i] = *x << 8; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, *x << 8); + + x++; + } + + /* Process */ + tdfb_core(cd, in_nch, out_nch); + + /* Write two frames of output */ + for (i = 0; i < 2 * out_nch; i++) { + *y = sat_int24(Q_SHIFT_RND(cd->out[i], 27, 23)); + y++; + } + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#if CONFIG_FORMAT_S32LE +void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + 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 = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); + int remaining_frames = frames; + int emp_ch = 0; + + while (remaining_frames) { + fmax = audio_stream_frames_without_wrap(source, x); + f = MIN(remaining_frames, fmax); + fmax = audio_stream_frames_without_wrap(sink, y); + f = MIN(f, fmax); + for (j = 0; j < f; j += 2) { + /* Clear output mix*/ + memset(cd->out, 0, 2 * out_nch * sizeof(int32_t)); + + /* Read two frames from all input channels */ + for (i = 0; i < 2 * in_nch; i++) { + cd->in[i] = *x; + if (cd->direction_updates) + tdfb_direction_copy_emphasis(cd, in_nch, &emp_ch, *x); + + x++; + } + + /* Process */ + tdfb_core(cd, in_nch, out_nch); + + /* Write two frames of output. In Q5.27 to Q1.31 conversion + * rounding is not applicable so just shift left by 4. + */ + for (i = 0; i < 2 * out_nch; i++) { + *y = sat_int32((int64_t)cd->out[i] << 4); + y++; + } + } + remaining_frames -= f; + x = audio_stream_wrap(source, x); + y = audio_stream_wrap(sink, y); + } +} +#endif + +#endif /* TDFB_HIFIEP */ + diff --git a/src/audio/tdfb/tdfb_ipc3.c b/src/audio/tdfb/tdfb_ipc3.c new file mode 100644 index 000000000000..544acbe9a41f --- /dev/null +++ b/src/audio/tdfb/tdfb_ipc3.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +/* this file contains ipc3 specific functions for tdfb. + */ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <rtos/alloc.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <ipc/header.h> +#include <ipc/control.h> +#include <sof/ipc/msg.h> +#include <errno.h> +#include <sof/audio/data_blob.h> +#include <sof/trace/trace.h> +#include <stdint.h> + +#include "tdfb.h" +#include "tdfb_comp.h" + +LOG_MODULE_DECLARE(tdfb, CONFIG_SOF_LOG_LEVEL); + +static int init_get_ctl_ipc(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + int comp_id = dev_comp_id(mod->dev); + + cd->ctrl_data = mod_zalloc(mod, TDFB_GET_CTRL_DATA_SIZE); + if (!cd->ctrl_data) + return -ENOMEM; + + cd->ctrl_data->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | SOF_IPC_COMP_GET_VALUE | comp_id; + cd->ctrl_data->rhdr.hdr.size = TDFB_GET_CTRL_DATA_SIZE; + cd->msg = ipc_msg_init(cd->ctrl_data->rhdr.hdr.cmd, cd->ctrl_data->rhdr.hdr.size); + + cd->ctrl_data->comp_id = comp_id; + cd->ctrl_data->type = SOF_CTRL_TYPE_VALUE_CHAN_GET; + cd->ctrl_data->cmd = SOF_CTRL_CMD_ENUM; + cd->ctrl_data->index = SOF_TDFB_CTRL_INDEX_AZIMUTH_ESTIMATE; + cd->ctrl_data->num_elems = 0; + return 0; +} + +static void send_get_ctl_ipc(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + +#if TDFB_ADD_DIRECTION_TO_GET_CMD + cd->ctrl_data->chanv[0].channel = 0; + cd->ctrl_data->chanv[0].value = cd->az_value_estimate; + cd->ctrl_data->num_elems = 1; +#endif + + ipc_msg_send(cd->msg, cd->ctrl_data, false); +} + +int tdfb_ipc_notification_init(struct processing_module *mod) +{ + return init_get_ctl_ipc(mod); +} + +void tdfb_send_ipc_notification(struct processing_module *mod) +{ + send_get_ctl_ipc(mod); +} + +/* + * Module commands handling + */ +static int tdfb_cmd_switch_get(struct sof_ipc_ctrl_data *cdata, struct tdfb_comp_data *cd) +{ + int j; + + /* Fail if wrong index in control, needed if several in same type */ + if (cdata->index != SOF_TDFB_CTRL_INDEX_PROCESS) + return -EINVAL; + + for (j = 0; j < cdata->num_elems; j++) + cdata->chanv[j].value = cd->beam_on; + + return 0; +} + +static int tdfb_cmd_enum_get(struct sof_ipc_ctrl_data *cdata, struct tdfb_comp_data *cd) +{ + int j; + + switch (cdata->index) { + case SOF_TDFB_CTRL_INDEX_AZIMUTH: + for (j = 0; j < cdata->num_elems; j++) + cdata->chanv[j].value = cd->az_value; + + break; + case SOF_TDFB_CTRL_INDEX_AZIMUTH_ESTIMATE: + for (j = 0; j < cdata->num_elems; j++) + cdata->chanv[j].value = cd->az_value_estimate; + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tdfb_cmd_get_value(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_dbg(mod->dev, "SOF_CTRL_CMD_ENUM index=%d", + cdata->index); + return tdfb_cmd_enum_get(cdata, cd); + case SOF_CTRL_CMD_SWITCH: + comp_dbg(mod->dev, "SOF_CTRL_CMD_SWITCH index=%d", + cdata->index); + return tdfb_cmd_switch_get(cdata, cd); + } + + comp_err(mod->dev, "error: invalid cdata->cmd"); + return -EINVAL; +} + +int tdfb_get_ipc_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct tdfb_comp_data *cd = module_get_private_data(mod); + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) + return tdfb_cmd_get_value(mod, cdata); + + comp_dbg(mod->dev, "binary"); + return comp_data_blob_get_cmd(cd->model_handler, cdata, fragment_size); +} + +static int tdfb_cmd_enum_set(struct sof_ipc_ctrl_data *cdata, struct tdfb_comp_data *cd) +{ + if (cdata->num_elems != 1) + return -EINVAL; + + if (cdata->chanv[0].value > SOF_TDFB_MAX_ANGLES) + return -EINVAL; + + switch (cdata->index) { + case SOF_TDFB_CTRL_INDEX_AZIMUTH: + cd->az_value = cdata->chanv[0].value; + cd->update = true; + break; + case SOF_TDFB_CTRL_INDEX_AZIMUTH_ESTIMATE: + cd->az_value_estimate = cdata->chanv[0].value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tdfb_cmd_switch_set(struct sof_ipc_ctrl_data *cdata, struct tdfb_comp_data *cd) +{ + if (cdata->num_elems != 1) + return -EINVAL; + + switch (cdata->index) { + case SOF_TDFB_CTRL_INDEX_PROCESS: + cd->beam_on = cdata->chanv[0].value; + cd->update = true; + break; + case SOF_TDFB_CTRL_INDEX_DIRECTION: + cd->direction_updates = cdata->chanv[0].value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tdfb_cmd_set_value(struct processing_module *mod, struct sof_ipc_ctrl_data *cdata) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_dbg(mod->dev, "SOF_CTRL_CMD_ENUM index=%d", + cdata->index); + return tdfb_cmd_enum_set(cdata, cd); + case SOF_CTRL_CMD_SWITCH: + comp_dbg(mod->dev, "SOF_CTRL_CMD_SWITCH index=%d", + cdata->index); + return tdfb_cmd_switch_set(cdata, cd); + } + + comp_err(mod->dev, "error: invalid cdata->cmd"); + return -EINVAL; +} + +int tdfb_set_ipc_config(struct processing_module *mod, uint32_t param_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 sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct tdfb_comp_data *cd = module_get_private_data(mod); + int ret; + + if (cdata->cmd != SOF_CTRL_CMD_BINARY) { + ret = tdfb_cmd_set_value(mod, cdata); + } else { + comp_info(mod->dev, "binary"); + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); + } + + return ret; +} + +int tdfb_params(struct processing_module *mod) +{ + return 0; +} + diff --git a/src/audio/tdfb/tdfb_ipc4.c b/src/audio/tdfb/tdfb_ipc4.c new file mode 100644 index 000000000000..2f7e7e865214 --- /dev/null +++ b/src/audio/tdfb/tdfb_ipc4.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +/* this file contains ipc4 specific functions for tdfb. + */ + +#include <sof/audio/module_adapter/module/module_interface.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/trace/trace.h> +#include <sof/ipc/msg.h> +#include <errno.h> +#include <sof/audio/component.h> +#include <ipc4/notification.h> +#include <ipc4/module.h> +#include <ipc4/header.h> +#include <ipc4/base-config.h> +#include <rtos/string.h> +#include <ipc/stream.h> +#include <sof/audio/buffer.h> +#include <sof/audio/data_blob.h> +#include <sof/list.h> +#include <stdint.h> + +#include "tdfb.h" +#include "tdfb_comp.h" + +LOG_MODULE_DECLARE(tdfb, CONFIG_SOF_LOG_LEVEL); + +static struct ipc_msg *tdfb_notification_init(struct processing_module *mod, + uint32_t control_type_param_id, + uint32_t control_id) +{ + struct ipc_msg msg_proto; + struct comp_dev *dev = mod->dev; + struct comp_ipc_config *ipc_config = &dev->ipc_config; + union ipc4_notification_header *primary = + (union ipc4_notification_header *)&msg_proto.header; + struct sof_ipc4_notify_module_data *msg_module_data; + struct sof_ipc4_control_msg_payload *msg_payload; + struct ipc_msg *msg; + + /* Clear header, extension, and other ipc_msg members */ + memset_s(&msg_proto, sizeof(msg_proto), 0, sizeof(msg_proto)); + primary->r.notif_type = SOF_IPC4_MODULE_NOTIFICATION; + primary->r.type = SOF_IPC4_GLB_NOTIFICATION; + primary->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + primary->r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg = ipc_msg_w_ext_init(msg_proto.header, msg_proto.extension, + sizeof(struct sof_ipc4_notify_module_data) + + sizeof(struct sof_ipc4_control_msg_payload) + + sizeof(struct sof_ipc4_ctrl_value_chan)); + if (!msg) + return NULL; + + msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data; + msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id); + msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id); + msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL | + control_type_param_id; + msg_module_data->event_data_size = sizeof(struct sof_ipc4_control_msg_payload) + + sizeof(struct sof_ipc4_ctrl_value_chan); + + msg_payload = (struct sof_ipc4_control_msg_payload *)msg_module_data->event_data; + msg_payload->id = control_id; + msg_payload->num_elems = 1; + msg_payload->chanv[0].channel = 0; + + comp_dbg(dev, "instance_id = 0x%08x, module_id = 0x%08x", + msg_module_data->instance_id, msg_module_data->module_id); + return msg; +} + +static void tdfb_send_notification(struct ipc_msg *msg, uint32_t val) +{ + struct sof_ipc4_notify_module_data *msg_module_data; + struct sof_ipc4_control_msg_payload *msg_payload; + + msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data; + msg_payload = (struct sof_ipc4_control_msg_payload *)msg_module_data->event_data; + msg_payload->chanv[0].value = val; + ipc_msg_send(msg, NULL, false); +} + +int tdfb_ipc_notification_init(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + cd->msg = tdfb_notification_init(mod, SOF_IPC4_ENUM_CONTROL_PARAM_ID, + SOF_TDFB_CTRL_INDEX_AZIMUTH_ESTIMATE); + if (!cd->msg) { + comp_err(mod->dev, "Failed to initialize control notification."); + return -EINVAL; + } + + return 0; +} + +void tdfb_send_ipc_notification(struct processing_module *mod) +{ + struct tdfb_comp_data *cd = module_get_private_data(mod); + + tdfb_send_notification(cd->msg, cd->az_value_estimate); +} + +int tdfb_get_ipc_config(struct processing_module *mod, + uint32_t param_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + comp_err(mod->dev, "Not supported, should not happen"); + return -EINVAL; +} + +static int tdfb_cmd_enum_set(struct sof_ipc4_control_msg_payload *ctl, struct tdfb_comp_data *cd) +{ + if (ctl->num_elems != 1) + return -EINVAL; + + if (ctl->chanv[0].value > SOF_TDFB_MAX_ANGLES) + return -EINVAL; + + switch (ctl->id) { + case SOF_TDFB_CTRL_INDEX_AZIMUTH: + cd->az_value = ctl->chanv[0].value; + cd->update = true; + break; + case SOF_TDFB_CTRL_INDEX_AZIMUTH_ESTIMATE: + cd->az_value_estimate = ctl->chanv[0].value; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tdfb_cmd_switch_set(struct sof_ipc4_control_msg_payload *ctl, struct tdfb_comp_data *cd) +{ + if (ctl->num_elems != 1) + return -EINVAL; + + switch (ctl->id) { + case SOF_TDFB_CTRL_INDEX_PROCESS: + cd->beam_on = ctl->chanv[0].value; + cd->update = true; + break; + case SOF_TDFB_CTRL_INDEX_DIRECTION: + cd->direction_updates = ctl->chanv[0].value; + break; + default: + return -EINVAL; + } + + return 0; +} + +int tdfb_set_ipc_config(struct processing_module *mod, uint32_t param_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 sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + struct tdfb_comp_data *cd = module_get_private_data(mod); + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + comp_dbg(mod->dev, "SOF_IPC4_SWITCH_CONTROL_PARAM_ID id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + return tdfb_cmd_switch_set(ctl, cd); + + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_dbg(mod->dev, "SOF_IPC4_ENUM_CONTROL_PARAM_ID id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + return tdfb_cmd_enum_set(ctl, cd); + default: + comp_info(mod->dev, "binary"); + return comp_data_blob_set(cd->model_handler, pos, data_offset_size, + fragment, fragment_size); + } +} + +int tdfb_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + if (mod->priv.cfg.nb_input_pins != SOF_TDFB_NUM_INPUT_PINS) { + comp_err(dev, "Illegal input pins count %d", mod->priv.cfg.nb_input_pins); + return -EINVAL; + } + + if (mod->priv.cfg.nb_output_pins != SOF_TDFB_NUM_OUTPUT_PINS) { + comp_err(dev, "Illegal output pins count %d", mod->priv.cfg.nb_output_pins); + return -EINVAL; + } + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + component_set_nearest_period_frames(dev, params->rate); + + /* The caller has verified source and sink buffer validity */ + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.input_pins[0].audio_fmt); + + sinkb = comp_dev_get_first_data_consumer(dev); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.output_pins[0].audio_fmt); + return 0; +} + diff --git a/src/audio/tdfb/tune/README.md b/src/audio/tdfb/tune/README.md new file mode 100644 index 000000000000..342b27d74db8 --- /dev/null +++ b/src/audio/tdfb/tune/README.md @@ -0,0 +1,41 @@ +# Settings blobs generators for TDFB + +This directory contains the scripts to generate settings blobs for +the time-domain fixed beamformer (TDFB) for various microphone array +geometries and beamformer features. + +The requirement is Octave or Matlab with signal processing package. + +The most straightforward way to generate all blobs for topologies, +sof-ctl and UCM is to run command + +``` +./sof_example_all.sh +``` + +It creates the blobs for passthrough mode, single beam blobs for +line and circular arrays, and dual beam blobs for stereo audio +capture. Running it can take about 30 minutes. + +All the topology ASCII text format blobs contain instructions +how to generate them from command line shell. E.g. these +commands do a more fine grained build. + +``` +cd $SOF_WORKSPACE/sof + +# Generate pass-through blobs +cd tools/tune/tdfb; octave --no-window-system example_pass_config.m + +# Generate blobs for line array and single beam +cd tools/tune/tdfb; octave --no-window-system example_line_array.m + +# Generate blobs for stereo capture for arrays with known mm-spacing +cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams + +# Generate bobs for stereo capture for generic arrays with known microphones count +cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams_default +``` + +Further information about TDFB component is available in SOF Docs, see +https://thesofproject.github.io/latest/algos/tdfb/time_domain_fixed_beamformer.html diff --git a/src/audio/tdfb/tune/sof_bf_array_circ.m b/src/audio/tdfb/tune/sof_bf_array_circ.m new file mode 100644 index 000000000000..db6fab035db1 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_array_circ.m @@ -0,0 +1,28 @@ +% bf = sof_bf_array_circ(bf) +% +% Inputs +% bf.mic_n ... number of microphones +% bf.mic_r ... radius of circular array [m] +% +% Outputs +% bf.mic_x ... x coordinates [m] +% bf.mic_y ... y coordinates [m] +% bf.mic_z ... z coordinates [m] + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_array_circ(bf) + +bf.mic_angle = (0:bf.mic_n-1)*360/bf.mic_n; % Mic 1 at 0 deg +idx = find(bf.mic_angle > 180); % wrap > 180 deg to -180 .. 0 +bf.mic_angle(idx) = bf.mic_angle(idx)-360; +bf.mic_x = bf.mic_r*cosd(bf.mic_angle); +bf.mic_y = bf.mic_r*sind(bf.mic_angle); +bf.mic_z = zeros(1,bf.mic_n); +bf.mic_d = sqrt((bf.mic_x(1)-bf.mic_x(2))^2+(bf.mic_y(1)-bf.mic_y(2))^2); + +end diff --git a/src/audio/tdfb/tune/sof_bf_array_line.m b/src/audio/tdfb/tune/sof_bf_array_line.m new file mode 100644 index 000000000000..db9f66809d74 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_array_line.m @@ -0,0 +1,25 @@ +% bf = sof_bf_array_line(bf) +% +% Inputs +% bf.mic_n ... number of microphones +% bf.mic_d ... distance between microphones [m] +% +% Outputs +% bf.mic_x ... x coordinates [m] +% bf.mic_y ... y coordinates [m] +% bf.mic_z ... z coordinates [m] + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_array_line(bf) + +bf.mic_y = linspace(0, -(bf.mic_n-1) * bf.mic_d, bf.mic_n) ... + + (bf.mic_n-1) * bf.mic_d / 2; +bf.mic_x = zeros(1, bf.mic_n); +bf.mic_z = zeros(1, bf.mic_n); + +end diff --git a/src/audio/tdfb/tune/sof_bf_array_lshape.m b/src/audio/tdfb/tune/sof_bf_array_lshape.m new file mode 100644 index 000000000000..965e8c3100bc --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_array_lshape.m @@ -0,0 +1,44 @@ +% bf = sof_bf_array_lshape(bf) +% +% Inputs +% bf.mic_nxy ... vector of two with number of microphones along x and y +% bf.mic_rxy ... vector of two with distance along x and y [m] +% +% Outputs +% bf.mic_x ... x coordinates [m] +% bf.mic_y ... y coordinates [m] +% bf.mic_z ... z coordinates [m] + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_array_lshape(bf) + +bf.mic_x = []; +bf.mic_y = []; + +bf.mic_n = sum(bf.mic_nxy) -1; +bf.mic_z = zeros(1, bf.mic_n); +n = 1; +for x = 0:(bf.mic_nxy(1) -1) + bf.mic_x(n) = 0; + bf.mic_y(n) = -x * bf.mic_dxy(1); + n = n + 1; +end + +for y = 1:(bf.mic_nxy(2) -1) + bf.mic_x(n) = y * bf.mic_dxy(2); + bf.mic_y(n) = 0; + n = n + 1; +end + +bf.mic_x = bf.mic_x - mean(bf.mic_x); +bf.mic_y = bf.mic_y - mean(bf.mic_y); +bf.mic_z = bf.mic_z - mean(bf.mic_z); + +bf.mic_d = max(bf.mic_dxy); + +end diff --git a/src/audio/tdfb/tune/sof_bf_array_rect.m b/src/audio/tdfb/tune/sof_bf_array_rect.m new file mode 100644 index 000000000000..cab63190a1dd --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_array_rect.m @@ -0,0 +1,38 @@ +% bf = sof_bf_array_rect(bf) +% +% Inputs +% bf.mic_nxy ... vector of two with number of microphones along x and y +% bf.mic_rxy ... vector of two with distance along x and y [m] +% +% Outputs +% bf.mic_x ... x coordinates [m] +% bf.mic_y ... y coordinates [m] +% bf.mic_z ... z coordinates [m] + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_array_rect(bf) + +bf.mic_x = []; +bf.mic_y = []; + +bf.mic_n = prod(bf.mic_nxy); +bf.mic_z = zeros(1, bf.mic_n); +for y = 1:bf.mic_nxy(2) + for x = 1:bf.mic_nxy(1) + n = x + bf.mic_nxy(1) * (y - 1); + bf.mic_y(n) = -x * bf.mic_dxy(1); + bf.mic_x(n) = y * bf.mic_dxy(2); + end +end + +bf.mic_x = bf.mic_x - mean(bf.mic_x); +bf.mic_y = bf.mic_y - mean(bf.mic_y); +bf.mic_z = bf.mic_z - mean(bf.mic_z); +bf.mic_d = max(bf.mic_dxy); + +end diff --git a/src/audio/tdfb/tune/sof_bf_array_rot.m b/src/audio/tdfb/tune/sof_bf_array_rot.m new file mode 100644 index 000000000000..6bdde5f0a49d --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_array_rot.m @@ -0,0 +1,58 @@ +% bf = sof_bf_array_rot(bf) +% +% Inputs +% bf.array_angle ... three element vector for x, y, z rotation [degrees] +% bf.mic_x ......... x coordinates of microphones in [m] +% bf.mic_y ......... y coordinates of microphones in [m] +% bf.mic_z ......... z coordinates of microphones in [m] +% +% Outputs +% bf.mic_x +% bf.mic_y +% bf.mic_z + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_array_rot(bf) + +% Equations reference +% https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations + +% Rotate around X-axis +% +% | x' | | 1 0 0 | | x | +% | y' | = | 0 cosa -sina | | y | +% | z' | | 0 sina cosa | | z | +a = bf.array_angle(1) * pi/180; +y = bf.mic_y; +z = bf.mic_z; +bf.mic_y = cos(a) * y - sin(a) * z; +bf.mic_z = sin(a) * y + cos(a) * z; + +% Rotate around Y-axis +% +% | x' | | cosa 0 sina | | x | +% | y' | = | 0 1 0 | | y | +% | z' | | -sina 0 cosa | | z | +a = bf.array_angle(2) * pi/180; +x = bf.mic_x; +z = bf.mic_z; +bf.mic_x = cos(a) * x + sin(a) * z; +bf.mic_z = -sin(a) * x + cos(a) * z; + +% Rotate around Z-axis +% +% | x' | | cosa -sina 0 | | x | +% | y' | = | sina cosa 0 | | y | +% | z' | | 0 0 1 | | z | +a = bf.array_angle(3) * pi/180; +x = bf.mic_x; +y = bf.mic_y; +bf.mic_x = cos(a) * x - sin(a) * y; +bf.mic_y = sin(a) * x + cos(a) * y; + +end diff --git a/src/audio/tdfb/tune/sof_bf_array_xyz.m b/src/audio/tdfb/tune/sof_bf_array_xyz.m new file mode 100644 index 000000000000..6426b651c3e1 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_array_xyz.m @@ -0,0 +1,27 @@ +% bf = sof_bf_array_xyz(bf) +% +% Inputs +% bf.mic_x ... x coordinates [m] +% bf.mic_y ... y coordinates [m] +% bf.mic_z ... z coordinates [m] +% +% Outputs +% bf.mic_n ... Number of microphones +% bf.mic_x ... x coordinates [m] +% bf.mic_y ... y coordinates [m] +% bf.mic_z ... z coordinates [m] + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_array_xyz(bf) + +bf.mic_n = length(bf.mic_x); +bf.mic_x = bf.mic_x - mean(bf.mic_x); +bf.mic_y = bf.mic_y - mean(bf.mic_y); +bf.mic_z = bf.mic_z - mean(bf.mic_z); + +end diff --git a/src/audio/tdfb/tune/sof_bf_blob_pack.m b/src/audio/tdfb/tune/sof_bf_blob_pack.m new file mode 100644 index 000000000000..d1e91931f215 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_blob_pack.m @@ -0,0 +1,179 @@ +function blob8 = sof_bf_blob_pack(bf, ipc_version) + +%% Pack TDFB struct to bytes +% +% blob8 = bf_blob_pack(bf) +% +% bf ..... TDFB design data struct input +% blob8 .. Packed bytes blob output +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2020 Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Check for sane parameters +if bf.num_filters < 1 || bf.num_filters > 16 + error('Invalid number of filters'); +end + +if bf.num_output_channels < 1 || bf.num_output_channels > 8 + error('Invalid number of output channels'); +end + +if bf.num_output_streams < 1 || bf.num_output_streams > 8 + error('Invalid number of output streams'); +end + +if length(bf.input_channel_select) ~= bf.num_filters + error('input_channel_select length does not match'); +end + +if length(bf.output_channel_mix) ~= bf.num_filters + error('output_channel_mix length does not match'); +end + +if length(bf.output_stream_mix) ~= bf.num_filters + error('output_stream_mix length does not match'); +end + +% Use finer angle enum scale for line array that is limited to -90..+90 deg +% TODO: This should be done somewhere else +if strcmp(bf.array, 'line') + bf.angle_enum_mult = 15; + bf.angle_enum_offs = -90; +end + +%% Endianness of blob +switch lower(bf.endian) + case 'little' + sh16 = [0 -8]; + sh32 = [0 -8 -16 -24]; + case 'big' + sh16 = [-8 0]; + sh32 = [-24 -16 -8 0]; + otherwise + error('Unknown endianness'); +end + +%% Header format is +% uint32_t size; +% uint16_t num_filters; +% uint16_t num_output_channels; +% uint16_t num_output_streams; +% uint16_t reserved16; +% uint32_t reserved32[4]; +% int16_t data[]; +% +% data[] is +% int16_t fir_filter1[length_filter1]; Multiple of 4 taps and 32 bit align +% int16_t fir_filter2[length_filter2]; Multiple of 4 taps and 32 bit align +% ... +% int16_t fir_filterN[length_filterN]; Multiple of 4 taps and 32 bit align +% int16_t input_channel_select[num_filters]; 0 = ch0, 1 = 1ch1, .. +% int16_t output_channel_mix[num_filters]; +% int16_t output_stream_mix[num_filters]; + +%% Pack as 16 bits +nh16 = 14; +h16 = zeros(1, nh16, 'int16'); +nc16 = length(bf.all_filters); +na16 = 4 * bf.num_angles; +nl16 = 4 * bf.mic_n; +if bf.beam_off_defined + nm16 = 4 * bf.num_filters; +else + nm16 = 3 * bf.num_filters; +end + +nb16 = ceil((nh16 + nc16 + nm16 + na16 + nl16)/2)*2; +h16(1) = 2 * nb16; +h16(2) = 0; +h16(3) = bf.num_filters; +h16(4) = bf.num_output_channels; +h16(5) = bf.num_output_streams; +h16(6) = bf.mic_n; +h16(7) = bf.num_angles; +h16(8) = bf.beam_off_defined; +h16(9) = bf.track_doa; +h16(10) = bf.angle_enum_mult; +h16(11) = bf.angle_enum_offs; + +%% Merge header and coefficients, make even number of int16 to make it +% multiple of int32 +blob16 = zeros(1,nb16, 'int16'); +blob16(1:nh16) = h16; +i1 = nh16 + 1; +i2 = i1 + nc16 -1; +blob16(i1:i2) = int16(bf.all_filters); +i1 = i2 + 1; +i2 = i1 + bf.num_filters - 1; +blob16(i1:i2) = int16(bf.input_channel_select); +i1 = i2 + 1; +i2 = i1 + bf.num_filters - 1; +blob16(i1:i2) = int16(bf.output_channel_mix); +i1 = i2 + 1; +i2 = i1 + bf.num_filters - 1; +blob16(i1:i2) = int16(bf.output_stream_mix); + +if (bf.beam_off_defined) + i1 = i2 + 1; + i2 = i1 + bf.num_filters - 1; + blob16(i1:i2) = int16(bf.output_channel_mix_beam_off); +end + +for i = 1:bf.num_angles + i1 = i2 + 1; + i2 = i1 + 4 - 1; + blob16(i1:i2) = int16([ bf.steer_az(i) bf.steer_el(i) (i - 1)*bf.num_filters 0 ]); +end + +% Coordinates are Q4.12 m +scale=2^12; +for i = 1:bf.mic_n + i1 = i2 + 1; + i2 = i1 + 4 - 1; + loc = [ round(bf.mic_x(i)*scale) round(bf.mic_y(i)*scale) round(bf.mic_z(i)*scale) 0 ]; + blob16(i1:i2) = int16(loc); +end + +%% Pack as 8 bits +nbytes_data = nb16 * 2; + +%% Get ABI information +[abi_bytes, nbytes_abi] = sof_get_abi(nbytes_data, ipc_version); + +%% Initialize uint8 array with correct size +nbytes = nbytes_abi + nbytes_data; +blob8 = zeros(1, nbytes, 'uint8'); + +%% Inset ABI header +blob8(1:nbytes_abi) = abi_bytes; +j = nbytes_abi + 1; + +%% Component data +for i = 1:length(blob16) + blob8(j:j+1) = w16b(blob16(i), sh16); + j = j+2; +end + +%% Done +fprintf('Blob size is %d bytes.\n', nbytes); + +end + +function bytes = w16b(word, sh) +bytes = uint8(zeros(1,2)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +end + +function bytes = w32b(word, sh) +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); +end diff --git a/src/audio/tdfb/tune/sof_bf_defaults.m b/src/audio/tdfb/tune/sof_bf_defaults.m new file mode 100644 index 000000000000..cf8e8838ed32 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_defaults.m @@ -0,0 +1,67 @@ +function bf = sof_bf_defaults() + +% Recording array general setup +bf.taylorwin_sidelobe = -30; +bf.chebwin_sidelobe = 30; +bf.taylorwin_nbar = 4; +bf.type_filt = 'hann'; % filter +bf.type = 'SDB'; % SDB for superdirectivem, DSB for delay and sum +bf.fs = 16e3; % Design for 16 kHz sample rate +bf.c = 343; % Speed of sound in 20C +bf.steer_az = 0; % Azimuth 0 deg +bf.steer_el = 0; % Elevation 0 deg +bf.steer_r = 5.0; % Distance 5.0m +bf.fir_length = 64; % 64 tap FIR filters +bf.kaiser_beta = 10; % Beta for kaiser window method FIR design +bf.mu_db = -40; % dB of diagonal loading to noise covariance matrix +bf.do_plots = 0; +bf.plot_box = 0.20; % Show 20cm wide plot cube for array geometry +bf.array_angle = [0 0 0]; % Array rotation angles for xyz +bf.tplg_fn = ''; +bf.sofctl_fn = ''; +bf.ucmbin3_fn = ''; +bf.ucmbin4_fn = ''; +sof_tools = '../../../../tools'; +bf.tplg1_path = fullfile(sof_tools, 'topology/topology1/m4/tdfb'); +bf.tplg2_path = fullfile(sof_tools, 'topology/topology2/include/components/tdfb'); +bf.sofctl3_path = fullfile(sof_tools, 'ctl/ipc3/tdfb'); +bf.sofctl4_path = fullfile(sof_tools, 'ctl/ipc4/tdfb'); +bf.data_path = './data'; +bf.endian = 'little'; +bf.fn = 1; +bf.create_simulation_data = false; +bf.sinerot_a = 10^(-20/20); +bf.sinerot_f = 2e3; +bf.sinerot_t = 1.0; +bf.sinerot_az_step = 5; +bf.sinerot_az_start = -180; +bf.sinerot_az_stop = 180; +bf.diffuse_t = 1; +bf.diffuse_lev = -20; +bf.random_t = 1; +bf.random_lev = -20; +bf.num_output_channels = 1; +bf.num_output_streams = 1; +bf.input_channel_select = []; +bf.output_channel_mix_beam_off = []; +bf.output_channel_mix = []; +bf.output_stream_mix = []; +bf.num_filters = []; +bf.angle_enum_mult = 30; +bf.angle_enum_offs = 0; +bf.track_doa = 0; +bf.beam_off_defined = 1; +bf.array = ''; +bf.mic_x = []; +bf.mic_y = []; +bf.mic_z = []; +bf.mic_n = 0; +bf.array_id = {''}; +bf.noiserot_fn = {''}; +bf.sinerot_fn = {''}; +bf.diffuse_fn = {''}; +bf.random_fn = {''}; +bf.mat_fn = {''}; +bf.export_note = ''; +bf.export_howto = ''; +end diff --git a/src/audio/tdfb/tune/sof_bf_design.m b/src/audio/tdfb/tune/sof_bf_design.m new file mode 100644 index 000000000000..5121ebe6630f --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_design.m @@ -0,0 +1,566 @@ +% bf = sof_bf_design(bf) +% +% This script calculates beamformer filters with superdirective design +% criteria. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_design(bf) + +sof_bf_paths(true); +mkdir_check('plots'); +mkdir_check('data'); + +if length(bf.steer_az) ~= length(bf.steer_el) + error('The steer_az and steer_el lengths need to be equal.'); +end + +if max(bf.steer_az) > 180 || min(bf.steer_az) < -180 + error('The steer_az angles need to be -180 to +180 degrees'); +end + +if max(bf.steer_el) > 90 || min(bf.steer_el) < -90 + error('The steer_el angles need to be -90 to +90 degrees'); +end + +switch lower(bf.array) + case 'line' + bf = sof_bf_array_line(bf); + case 'circular' + bf = sof_bf_array_circ(bf); + case 'rectangle' + bf = sof_bf_array_rect(bf); + case 'lshape' + bf = sof_bf_array_lshape(bf); + case 'xyz' + bf = sof_bf_array_xyz(bf); + otherwise + error('Invalid array type') +end + +if isempty(bf.num_filters) + if isempty(bf.input_channel_select) + bf.num_filters = bf.mic_n; + else + bf.num_filters = length(bf.input_channel_select); + end +end + +bf = sof_bf_array_rot(bf); + +% The design function handles only single (az, el) value, so need to +% loop every steer angle. +bf.num_angles = length(bf.steer_az); +all_az = bf.steer_az; +all_el = bf.steer_el; +all_array_id = bf.array_id; +all_noiserot_fn = bf.noiserot_fn; +all_sinerot_fn = bf.sinerot_fn; +all_diffuse_fn = bf.diffuse_fn; +all_random_fn = bf.random_fn; +all_mat_fn = bf.mat_fn; + +for n = 1:bf.num_angles + bf.steer_az = all_az(n); + bf.steer_el = all_el(n); + bf.array_id = all_array_id{n}; + bf.noiserot_fn = all_noiserot_fn{n}; + bf.sinerot_fn = all_sinerot_fn{n}; + bf.diffuse_fn = all_diffuse_fn{n}; + bf.random_fn = all_random_fn{n}; + bf.mat_fn = all_mat_fn{n}; + bf = bf_one_design(bf); + w_all(:,:,n) = bf.w; +end + +bf.steer_az = all_az; +bf.steer_el = all_el; +bf.array_id = all_array_id; +bf.noiserot_fn = all_noiserot_fn; +bf.sinerot_fn = all_sinerot_fn; +bf.diffuse_fn = all_diffuse_fn; +bf.random_fn = all_random_fn; +bf.mat_fn = all_mat_fn; +bf.w = w_all; + +sof_bf_paths(false); +end + +function bf = bf_one_design(bf) + +%% Defaults +j = complex(0,-1); +fs = bf.fs; +N = 1024; +N_half = N/2+1; +f = (0:N/2)*fs/N'; +phi_rad = (-180:180)*pi/180; +phi_rad = phi_rad(1:end-1); +n_phi = length(phi_rad); +steer_az = bf.steer_az*pi/180; +steer_el = bf.steer_el*pi/180; +mu = ones(1,N_half) * 10^(bf.mu_db/20); +%% Source at distance r +[src_x, src_y, src_z] = source_xyz(bf.steer_r, steer_az, steer_el); + +%% Default frequency domain weights +W = zeros(N_half, bf.num_filters); + +%% Coherence matrix, diffuse field +% Equation 2.11 +Gamma_vv = zeros(N_half, bf.num_filters, bf.num_filters); +for n=1:bf.num_filters + for m=1:bf.num_filters + % Equation 2.17 + lnm = sqrt( (bf.mic_x(n) - bf.mic_x(m))^2 ... + +(bf.mic_y(n) - bf.mic_y(m))^2 ... + +(bf.mic_z(n) - bf.mic_z(m))^2); + % singular value decomposition + [U,S,V] = svd(sinc(2*pi*f*lnm/bf.c), 'econ'); + Gamma_vv(:,n,m) = U*S*V'; + end +end + +%% Delays from source to each mic +dt = delay_from_source(bf, src_x, src_y, src_z); +dt = dt-min(dt); + +%% Create array vector +tau0 = zeros(n_phi, bf.num_filters); +A = zeros(N_half, n_phi, bf.num_filters); +d = zeros(N_half, bf.num_filters); +for n=1:bf.num_filters + % Equation 2.27 + d(:,n) = exp(-j*2*pi*f*dt(n)); % Delays to steer direction + for ip = 1:n_phi; + phi = phi_rad(ip); + x_phi = bf.steer_r*cos(phi)*cos(steer_el); + y_phi = bf.steer_r*sin(phi)*cos(steer_el); + z_phi = bf.steer_r*sin(steer_el); + tau0(ip, n) = sqrt((x_phi-bf.mic_x(n))^2 ... + + (y_phi-bf.mic_y(n))^2 ... + + (z_phi-bf.mic_z(n))^2)/bf.c; + end +end +tau = tau0-min(min(tau0)); + +for n=1:bf.num_filters + for ip = 1:n_phi + % N_half x n_phi x Nm + A(:, ip, n) = exp(-j*2*pi*f*tau(ip, n)); + end +end + +switch lower(bf.type) + case 'sdb' + % Superdirective + for iw = 1:N_half + % Equation 2.33 + I = eye(bf.num_filters, bf.num_filters); + d_w = d(iw,:).'; + Gamma_vv_w = squeeze(Gamma_vv(iw, :, :)); + Gamma_vv_w_diagload = Gamma_vv_w + mu(iw)*I; + Gamma_vv_w_inv = inv(Gamma_vv_w_diagload); + num = Gamma_vv_w_inv * d_w; + denom1 = d_w' * Gamma_vv_w_inv; + denom2 = denom1 * d_w; + W_w = num / denom2; + W(iw, :) = W_w.'; + end + case 'dsb' + % Delay and sum + for iw = 1:N_half + % Equation 2.31 + % W = 1/N*d + d_w = d(iw, :); + W_w = 1/bf.num_filters * d_w; + W(iw, :) = W_w.'; + end + otherwise + error('Invalid type, use SDB or DSB'); +end + +%% Convert w to time domain +W_full = zeros(N, bf.num_filters); +W_full = W(1:N_half, :); +for i=N_half+1:N + W_full(i,:) = conj(W(N_half-(i-N_half),:)); +end +bf.w = zeros(bf.fir_length, bf.num_filters); +w_tmp = zeros(N, bf.num_filters); +idx_max = zeros(bf.num_filters, 1); +for i=1:bf.num_filters + h = real(fftshift(ifft(W_full(:,i)))); + w_tmp(:,i) = h; + idx_max(i) = find(h == max(h)); +end + +center_idx = round(mean(idx_max)); +start = center_idx - floor(bf.fir_length/2); +switch lower(bf.type_filt) + case 'hann' + win0 = hann (bf.fir_length); + case 'hamming' + win0 = hamming(bf.fir_length); + case 'taylorwin' + win0 = taylorwin(bf.fir_length, bf.taylorwin_nbar, bf.taylorwin_sidelobe); + case 'chebwin' + win0 = chebwin(bf.fir_length, bf.chebwin_sidelobe); + case 'kaiser' + win0 = kaiser(bf.fir_length,bf.kaiser_beta); +end +for i=1:bf.num_filters + win = zeros(bf.fir_length, 1); + win_shift = center_idx - idx_max(i) - 1; + if (win_shift >= 0) + win(1:end-win_shift) = win0(win_shift+1:end); + else + win(-win_shift:end) = win0(1:end+win_shift+1); + end + bf.w(:,i) = w_tmp(start:start + bf.fir_length - 1, i) .* win; +end + +%% Back to frequency domain to check spatial response +W2_full = zeros(N, bf.num_filters); +for i=1:bf.num_filters + % Zero pad + h2 = zeros(1,N); + h2(start:start + bf.fir_length - 1) = bf.w(:,i); + W2_full(:,i) = fft(h2); +end +W2 = W2_full(1:N_half, :); +B2 = zeros(N_half, n_phi); +for iw = 1:N_half + WT = (W2(iw,:)').'; + AS = squeeze(A(iw,:,:)).'; + WA = WT * AS; + B2(iw,:) = WA; +end +bf.resp_fa = B2'; +bf.resp_angle = phi_rad * 180/pi; + +%% Directivity in diffuse field +% Equation 2.18 +% DI(exp(j Omega) = 10*log10( abs(W^H d)^2 / (W^H Gamma_vv W)) +bf.f = f; +bf.di_db = zeros(1, N_half); +for iw = 1:N_half + W_w = W2(iw,:).'; + d_w = d(iw,:).'; + Gamma_vv_w = squeeze(Gamma_vv(iw,:,:)); + W_wh = W_w'; + num = abs(W_wh * d_w)^2; + denom1 = W_wh * Gamma_vv_w; + denom2 = denom1 * W_w; + di = num / denom2; + bf.di_db(iw) = 10*log10(abs(di)); +end + + +%% White noise gain +for iw = 1:N_half + % WNG = abs(^w^H d)^2/(w^H w); + W_w = W2(iw,:).'; + d_w = d(iw,:).'; + W_wh = W_w'; + num = abs(W_wh * d_w)^2; + denom = W_wh * W_w; + wng = num / denom2; + wng_db(iw) = 10*log10(abs(wng)); +end +bf.wng_db = wng_db; + +if bf.do_plots + %% Array + fh(1) = figure(bf.fn); + plot3(bf.mic_x(1), bf.mic_y(1), bf.mic_z(1), 'ro'); + hold on; + plot3(bf.mic_x(2:end), bf.mic_y(2:end), bf.mic_z(2:end), 'bo'); + plot3(src_x, src_y, src_z, 'gx'); + plot3([0 src_x],[0 src_y],[0 src_z],'c--') + for n=1:bf.num_filters + text(bf.mic_x(n), bf.mic_y(n), bf.mic_z(n) + 20e-3, ... + num2str(n)); + end + hold off + pb2 = bf.plot_box / 2; + axis([-pb2 pb2 -pb2 pb2 -pb2 pb2]); + axis('square'); + grid on; + xlabel('x (m)'); ylabel('y (m)'); zlabel('z (m)'); + view(-50, 30); + title(['Geometry ' bf.array_id], 'Interpreter','none'); + + %% Coef + fh(2) = figure(bf.fn + 1); + plot(bf.w) + grid on; + xlabel('FIR coefficient'); ylabel('Tap value'); + title(['FIR filters ' bf.array_id], 'Interpreter','none'); + ch_legend(bf.num_filters); + + %% Frequency responses + fh(3) = figure(bf.fn + 2); + f = linspace(0, bf.fs/2, 256); + h = zeros(256, bf.num_filters); + for i = 1:bf.num_filters + h(:,i) = freqz(bf.w(:,i), 1, f, bf.fs); + end + plot(f, 20*log10(abs(h))); + grid on + ylabel('Magnitude (dB)'); + xlabel('Frequency (Hz)'); + title(['FIR magnitude responses ' bf.array_id], 'Interpreter','none'); + ch_legend(bf.num_filters); + + %% Group delays + fh(4) = figure(bf.fn + 3); + gd = zeros(256, bf.num_filters); + for i = 1:bf.num_filters + gd(:,i) = grpdelay(bf.w(:,i), 1, f, bf.fs); + end + plot(f, gd/bf.fs*1e6); + grid on + ylabel('Group delay (us)'); + xlabel('Frequency (Hz)'); + title(['FIR group delays ' bf.array_id], 'Interpreter','none'); + ch_legend(bf.num_filters); + + %% DI + bf.fh(5) = figure(bf.fn + 4); + semilogx(bf.f(2:end), bf.di_db(2:end)) + xlabel('Frequency (Hz)'); ylabel('DI (dB)'); grid on; + legend('Suppression of diffuse field noise','Location','SouthEast'); + title(['Directivity Index ' bf.array_id], 'Interpreter','none'); + + %% WNG + bf.fh(6) = figure(bf.fn + 5); + semilogx(bf.f(2:end), bf.wng_db(2:end)) + xlabel('Frequency (Hz)'); ylabel('WNG (dB)'); grid on; + legend('Attenuation of uncorrelated noise','Location','SouthEast'); + title(['White noise gain ' bf.array_id], 'Interpreter','none'); + drawnow; + + %% 2D + bf.fh(7) = figure(bf.fn + 6); + colormap(jet); + phi_deg = phi_rad*180/pi; + imagesc(bf.f, bf.resp_angle, 20*log10(abs(bf.resp_fa)), [-30 0]); + set(gca,'YDir','normal') + grid on; + colorbar; + xlabel('Frequency (Hz)'); ylabel('Angle (deg)'); + title(['Spatial response ' bf.array_id], 'Interpreter','none'); + + %% Polar + bf.fh(8) = figure(bf.fn + 7); + flist = [1000 2000 3000 4000]; + idx = []; + for i = 1:length(flist) + idx(i) = find(f > flist(i), 1, 'first'); + end + bf.resp_polar = abs(B2(idx,:)); + if exist('OCTAVE_VERSION', 'builtin') + polar(phi_rad, bf.resp_polar); + else + polarplot(phi_rad, bf.resp_polar); + end + legend('1 kHz','2 kHz','3 kHz','4 kHz'); + title(['Polar response ' bf.array_id], 'Interpreter','none'); +end + +%% Create data for simulation 1s per angle +if bf.create_simulation_data + if isempty(bf.sinerot_fn) + fprintf(1, 'No file for 360 degree sine source rotate specified\n'); + else + rotate_sound_source(bf, bf.sinerot_fn, 'sine'); + end + + if isempty(bf.noiserot_fn) + fprintf(1, 'No file for 360 degree random noise source rotate specified\n'); + else + rotate_sound_source(bf, bf.noiserot_fn, 'noise'); + end + + + if isempty(bf.diffuse_fn) + fprintf(1, 'No file for diffuse noise field specified\n'); + else + fprintf(1, 'Creating diffuse noise field...\n'); + fsi = 384e3; % Target interpolated rate + p = round(fsi / bf.fs); % Interpolation factor + fsi = p * bf.fs; % Recalculate high rate + ti = 1/fsi; % period at higher rate + t_add = 10.0/bf.c; % Additional signal time for max 20m propagation + t0 = bf.diffuse_t + t_add; % Total sine length per angle + n0 = floor(bf.fs * t0); + nt = floor(bf.fs * bf.diffuse_t); % Number samples output per angle + nti = p * nt; % Number samples output per angle at high rate + el = 0; + for az_deg = -160:20:180 % Azimuth plane only noise with sources + az = az_deg * pi/180; + [nx, ny, nz] = source_xyz(bf.steer_r, az, el); + dt = delay_from_source(bf, nx, ny, nz); + dn = round(dt / ti); + ns = rand(n0, 1) + rand(n0, 1) - 1; + nsi = interp(ns, p); + nmi = zeros(nti, bf.mic_n); + for j = 1:bf.mic_n + nmi(:,j) = nmi(:,j) + nsi(end-dn(j)-nti+1:end-dn(j)); + end + end + nm = nmi(1:p:end, :); + nlev = level_dbfs(nm(:,1)); + nm = nm * 10^((bf.diffuse_lev - nlev)/20); + myaudiowrite(bf.diffuse_fn, nm, bf.fs); + end + + if isempty(bf.random_fn) + fprintf(1, 'No file for random noise specified\n'); + else + fprintf(1, 'Creating random noise ...\n'); + nt = bf.fs * bf.random_t; + rn = rand(nt, bf.num_filters) + rand(nt, bf.num_filters) - 1; + + nlev = level_dbfs(rn(:,1)); + rn = rn * 10^((bf.random_lev - nlev)/20); + myaudiowrite(bf.random_fn, rn, bf.fs); + end + + if isempty(bf.mat_fn) + fprintf(1, 'No file for beam pattern simulation data specified.\n'); + else + fprintf(1, 'Saving design to %s\n', bf.mat_fn); + bf_copy = bf; + bf.fh = []; % Don't save the large figures, this avoids a warning print too + mkdir_check(bf.data_path); + save(bf.mat_fn, 'bf'); + bf = bf_copy; + end +end + +fprintf(1, 'Done.\n'); + +end + +%% Helper functions + +function rotate_sound_source(bf, fn, type); + fprintf(1, 'Creating 360 degree %s source rotate...\n', type); + fsi = 384e3; % Target interpolated rate + t_add = 10.0/bf.c; % Additional signal time for max 10m propagation + t_ramp = 5e-3; % 5 ms ramp to start and end of each angle tone + t_idle = 25e-3; % 25 ms idle to start and end of each angle tone + p = round(fsi / bf.fs); % Interpolation factor + fsi = p * bf.fs; % Recalculate high rate + ti = 1/fsi; % perid at higher rate + tt0 = bf.sinerot_t + t_add; % Total sine length per angle + nt = bf.fs * bf.sinerot_t; % Number samples output per angle + nt0 = floor(bf.fs * tt0); % Number samples output per angle + nti = p * nt; % Number samples output per angle at high rate + n_ramp = round(t_ramp * fsi); + n_idle = round(t_idle * fsi); + n_win = round(tt0 * fsi); + win = ones(n_win, 1); % Make a kind of hat shape window + win(n_idle:(n_idle + n_ramp - 1)) = linspace(0, 1, n_ramp); + win((end - n_idle - n_ramp + 1):(end - n_idle)) = linspace(1, 0, n_ramp); + win(1:n_idle) = zeros(1, n_idle); + win(end - n_idle + 1: end) = zeros(1, n_idle); + switch lower(type) + case 'sine' + si = multitone(fsi, bf.sinerot_f, bf.sinerot_a, tt0); + si = si .* win; + case 'noise' + [b, a] = butter(4, 2*[100 7000]/bf.fs); + ns0 = bf.sinerot_a * (2 * rand(round(tt0*bf.fs) + 1, 1) - 1); + nsf = filter(b, a, ns0); + si = interp(nsf, p); + si = si(1:n_win) .* win; + otherwise + error('no test signal type defined'); + end + test_az = (bf.sinerot_az_start:bf.sinerot_az_step:bf.sinerot_az_stop) * pi/180; + test_n = length(test_az); + test_el = zeros(1, test_n); + [test_x, test_y, test_z] = source_xyz(bf.steer_r, test_az, test_el); + td = zeros(test_n * nt, bf.mic_n); + for i = 1:length(test_az) + dt = delay_from_source(bf, test_x(i), test_y(i), test_z(i)); + dn = round(dt / ti); + mi = zeros(nti, bf.num_filters); + for j = 1:bf.mic_n + mi(:,j) = mi(:,j) + si(end-dn(j)-nti+1:end-dn(j)); + end + i1 = (i - 1) * nt + 1; + i2 = i1 + nt -1; + for j = 1:bf.mic_n + m = mi(1:p:end, j); + td(i1:i2, j) = m; + end + end + myaudiowrite(fn, td, bf.fs); +end + +function [x, y, z] = source_xyz(r, az, el) + +x = r * cos(az) .* cos(el); +y = r * sin(az) .* cos(el); +z = r * sin(el); + +end + +function dt = delay_from_source(bf, src_x, src_y, src_z) + +dm = zeros(1,bf.num_filters); +for n=1:bf.num_filters + dm(n) = sqrt((src_x - bf.mic_x(n))^2 ... + + (src_y - bf.mic_y(n))^2 ... + + (src_z - bf.mic_z(n))^2); +end +dt = dm/bf.c; + +end + +function ch_legend(n) +switch n + case 2 + legend('1', '2'); + case 3 + legend('1', '2', '3'); + case 4 + legend('1', '2', '3', '4'); + case 5 + legend('1', '2', '3', '4', '5'); + case 6 + legend('1', '2', '3', '4', '5', '6'); + case 7 + legend('1', '2', '3', '4', '5', '6', '7'); + otherwise + legend('1', '2', '3', '4', '5', '6', '7', '8'); +end +end + +function myaudiowrite(fn, x, fs) +[~, ~, ext] = fileparts(fn); +if strcmpi(ext, '.raw') + s = size(x); + xq = zeros(s(1) * s(2), 1, 'int16'); + scale = 2^15; + xs = round(x * scale); + xs(xs > scale - 1) = scale -1; + xs(xs < -scale) = -scale; + for i = 1:s(2) + xq(i:s(2):end) = xs(:,i); + end + fh = fopen(fn, 'wb'); + fwrite(fh, xq, 'int16'); + fclose(fh); +else + audiowrite(fn, x, fs); +end +end diff --git a/src/audio/tdfb/tune/sof_bf_export.m b/src/audio/tdfb/tune/sof_bf_export.m new file mode 100644 index 000000000000..a1856cc2a769 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_export.m @@ -0,0 +1,129 @@ +% sof_bf_export(bf) +% +% Inputs +% bf.sofctl3_fn .... filename of ascii text format blob +% bf.sofctl4_fn .... filename of ascii text format blob +% bf.ucmbin3_fn .... filename of binary format blob for UCM (IPC3) +% bf.ucmbin4_fn .... filename of binary format blob for UCM (IPC4) +% bf.tplg1_fn ...... filename of topology m4 format blob +% bf.tplg2_fn ...... filename of topology m4 format blob +% bf ............... the design procedure output + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_export(bf) + +% Use functions from common, test utils +sof_bf_paths(true); + +%% Add needed default controls if missing + +% Num of filters same as number of microphones +if isempty(bf.num_filters) + bf.num_filters = bf.mic_n; +end + +% Use all inputs linearly +if isempty(bf.input_channel_select) + bf.input_channel_select = 0:bf.num_filters - 1; +end + +% Mix all filters to all output channels +if isempty(bf.output_channel_mix) + bf.output_channel_mix = sum(2.^(0:(bf.num_output_channels - 1))) * ... + ones(1, bf.num_filters); +end + +% Mix all filters to all output channels +if isempty(bf.output_channel_mix_beam_off) + if (bf.num_output_channels == bf.num_filters) + bf.output_channel_mix_beam_off = 2.^(0:(bf.num_output_channels - 1)); + else + fprintf(1, 'Number of output channels: %d\n', bf.num_output_channels); + fprintf(1, 'Number of filters: %d\n', bf.num_filters); + error('Need to specify output_channel_mix_beam_off'); + end +end + +% All to first output stream +if isempty(bf.output_stream_mix) + bf.output_stream_mix = zeros(1, bf.num_filters); +end + + +%% Quantize filters +filters = []; +for j=1:bf.num_angles + for i=1:bf.num_filters + coefs = squeeze(bf.w(:,i,j)); + bq = sof_eq_fir_blob_quant(coefs, 16, 0); + filters = [filters bq ]; + end +end + +%% Add beam-off preset +if bf.beam_off_defined + b_pass = [1]; + bq = sof_eq_fir_blob_quant(b_pass, 16, 0); + for i=1:bf.num_filters + filters = [filters bq ]; + end +end + +%% Build blob +bf.all_filters = filters; +bp3 = sof_bf_blob_pack(bf, 3); +bp4 = sof_bf_blob_pack(bf, 4); + +%% Export +if isempty(bf.sofctl3_fn) + fprintf(1, 'No sof-ctl3 output file specified.\n'); +else + fprintf(1, 'Exporting to %s\n', bf.sofctl3_fn); + sof_alsactl_write(bf.sofctl3_fn, bp3); +end + +if isempty(bf.sofctl4_fn) + fprintf(1, 'No sof-ctl4 output file specified.\n'); +else + fprintf(1, 'Exporting to %s\n', bf.sofctl4_fn); + sof_alsactl_write(bf.sofctl4_fn, bp4); +end + +if isempty(bf.export_note) + export_note = sprintf("Exported with script example_%s_array.m", bf.array); +else + export_note = bf.export_note; +end + +if isempty(bf.tplg1_fn) + fprintf(1, 'No topology1 output file specified.\n'); +else + fprintf(1, 'Exporting to %s\n', bf.tplg1_fn); + sof_tplg_write(bf.tplg1_fn, bp3, 'DEF_TDFB_PRIV', export_note, bf.export_howto); +end + +if isempty(bf.tplg2_fn) + fprintf(1, 'No topology2 output file specified.\n'); +else + fprintf(1, 'Exporting to %s\n', bf.tplg2_fn); + sof_tplg2_write(bf.tplg2_fn, bp4, "tdfb_config", export_note, bf.export_howto); +end + +if ~isempty(bf.ucmbin3_fn) + fprintf(1, 'Exporting to %s\n', bf.ucmbin3_fn); + sof_ucm_blob_write(bf.ucmbin3_fn, bp3); +end + +if ~isempty(bf.ucmbin4_fn) + fprintf(1, 'Exporting to %s\n', bf.ucmbin4_fn); + sof_ucm_blob_write(bf.ucmbin4_fn, bp4); +end + +sof_bf_paths(false); + +end diff --git a/src/audio/tdfb/tune/sof_bf_filenames_helper.m b/src/audio/tdfb/tune/sof_bf_filenames_helper.m new file mode 100644 index 000000000000..edab6825d1c3 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_filenames_helper.m @@ -0,0 +1,108 @@ +% bf = sof_bf_filenames_helper(bf, id) +% +% Automatically defines output files names based on array geometry +% and steer angle. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bf = sof_bf_filenames_helper(bf, id) + +switch lower(bf.array) + case {'rectangle' 'lshape'} + mic_n_str = sprintf('%dx%d', bf.mic_nxy(1), bf.mic_nxy(2)); + dmm = round(1e3 * bf.mic_dxy); + mic_d_str = sprintf('%dx%d', dmm(1), dmm(2)); + case 'circular' + mic_n_str = sprintf('%d', bf.mic_n); + mic_d_str = sprintf('%d', round(1e3 * bf.mic_r)); + case 'xyz' + mic_n_str = sprintf('%d', length(bf.mic_x)); + mic_d_str = 'x'; + otherwise + mic_n_str = sprintf('%d', bf.mic_n); + mic_d_str = sprintf('%d', round(1e3 * bf.mic_d)); +end + +if length(bf.steer_az) ~= length(bf.steer_el) + error('The steer_az and steer_el lengths need to be equal.'); +end + +[az_str_pm] = angles_to_str(bf.steer_az); +[el_str_pm] = angles_to_str(bf.steer_el); + +if strcmp(bf.array, 'line') + el_str_show = ''; +else + el_str_show = sprintf('_el%s', el_str_pm); +end + +if nargin > 1 + idstr = sprintf('%s_az%s%s_%dkhz', ... + id, az_str_pm, el_str_show, round(bf.fs/1e3)); +else + idstr = sprintf('%s%s_%smm_az%s%s_%dkhz', ... + bf.array, mic_n_str, mic_d_str, ... + az_str_pm, el_str_show, round(bf.fs/1e3)); +end + +% Contain multiple (az, el) angles +bf.sofctl3_fn = fullfile(bf.sofctl3_path, sprintf('coef_%s.txt', idstr)); +bf.tplg1_fn = fullfile(bf.tplg1_path, sprintf('coef_%s.m4', idstr)); +bf.sofctl4_fn = fullfile(bf.sofctl4_path, sprintf('%s.txt', idstr)); +bf.ucmbin3_fn = fullfile(bf.sofctl3_path, sprintf('%s.bin', idstr)); +bf.ucmbin4_fn = fullfile(bf.sofctl4_path, sprintf('%s.bin', idstr)); +bf.tplg2_fn = fullfile(bf.tplg2_path, sprintf('%s.conf', idstr)); + + +for n = 1:length(bf.steer_az) + + az = bf.steer_az(n); + el = bf.steer_el(n); + + if nargin > 1 + bf.array_id{n} = sprintf('%s (%d, %d) deg', ... + id, az, el); + idstr = sprintf('%s_az%sel%sdeg_%dkhz', ... + id, numpm(az), numpm(el), round(bf.fs/1e3)); + else + bf.array_id{n} = sprintf('%s %s mic %s mm (%d, %d) deg', ... + bf.array, mic_n_str, mic_d_str, ... + az, el); + idstr = sprintf('%s%s_%smm_az%sel%sdeg_%dkhz', ... + bf.array, mic_n_str, mic_d_str, ... + numpm(az), numpm(el), round(bf.fs/1e3)); + end + + % Single (az, el) value per file + bf.mat_fn{n} = fullfile(bf.data_path, sprintf('tdfb_coef_%s.mat', idstr)); + bf.noiserot_fn{n} = fullfile(bf.data_path, sprintf('simcap_noiserot_%s.raw', idstr)); + bf.sinerot_fn{n} = fullfile(bf.data_path, sprintf('simcap_sinerot_%s.raw', idstr)); + bf.diffuse_fn{n} = fullfile(bf.data_path, sprintf('simcap_diffuse_%s.raw', idstr)); + bf.random_fn{n} = fullfile(bf.data_path, sprintf('simcap_random_%s.raw', idstr)); + +end + +end + +function nstr = numpm(n) + if n < 0 + nstr = sprintf('m%d', -round(n)); + else + nstr = sprintf('%d', round(n)); + end +end + +function a_str_pm = angles_to_str(a) + if length(a) > 1 + a_min = min(round(a)); + a_max = max(round(a)); + n = length(a); + a_str_pm = sprintf('%s_%s_%d', numpm(a_min), numpm(a_max), n); + else + a_str_pm = numpm(a); + end +end diff --git a/src/audio/tdfb/tune/sof_bf_line2_two_beams.m b/src/audio/tdfb/tune/sof_bf_line2_two_beams.m new file mode 100644 index 000000000000..533ed65d1b41 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_line2_two_beams.m @@ -0,0 +1,75 @@ +function sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm) + +% sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm) +% Input +% fs - sample rate +% d - microphones distance in meters +% a1 - steer angle beam 1 +% a2 - steer angle beam 2 +% fn - struct with exported blob files names +% prm +% .add_beam_beam_off - controls addition of beam off definition to blob +% .type - Use 'SDB' or 'DSB' +% .export_note - comment about build generally +% .export_howto - detailed build instruction +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020-2024, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +% Get defaults +bf1 = sof_bf_defaults(); +bf1.fs = fs; + +% Setup array +bf1.array='line'; % Calculate xyz coordinates for line +bf1.mic_n = 2; +bf1.mic_d = d; +bf1.beam_off_defined = prm.add_beam_off; +bf1.type = prm.type; + +% Copy settings for bf2 +bf2 = bf1; + +% Design beamformer 1 (left) +bf1.steer_az = a1; +bf1.steer_el = 0 * a1; +bf1.input_channel_select = [0 1]; % Input two channels +bf1.output_channel_mix = [1 1]; % Mix both filters to channel 2^0 +bf1.output_channel_mix_beam_off = [1 2]; % Filter 1 to channel 2^0, etc. +bf1.output_stream_mix = [0 0]; % Mix both filters to stream 0 +bf1.num_output_channels = 2; +bf1.fn = 10; % Figs 10.... +bf1 = sof_bf_filenames_helper(bf1); +bf1 = sof_bf_design(bf1); + +% Design beamformer 2 (right) +bf2.steer_az = a2; +bf2.steer_el = 0 * a2; +bf2.input_channel_select = [0 1]; % Input two channels +bf2.output_channel_mix = [2 2]; % Mix both filters to channel 2^1 +bf2.output_channel_mix_beam_off = [0 0]; % Filters omitted +bf2.output_stream_mix = [0 0]; % Mix both filters to stream 0 +bf2.num_output_channels = 2; +bf2.fn = 20; % Figs 20.... +bf2 = sof_bf_filenames_helper(bf2); +bf2 = sof_bf_design(bf2); + +% Merge two beamformers into single description, set file names +bfm = sof_bf_merge(bf1, bf2); +bfm.sofctl3_fn = fullfile(bfm.sofctl3_path, fn.sofctl3_fn); +bfm.tplg1_fn = fullfile(bfm.tplg1_path, fn.tplg1_fn); +bfm.sofctl4_fn = fullfile(bfm.sofctl4_path, fn.sofctl4_fn); +bfm.ucmbin3_fn = fullfile(bfm.sofctl3_path, fn.ucmbin3_fn); +bfm.ucmbin4_fn = fullfile(bfm.sofctl4_path, fn.ucmbin4_fn); +bfm.tplg2_fn = fullfile(bfm.tplg2_path, fn.tplg2_fn); + +% Export files for topology and sof-ctl +bfm.export_note = prm.export_note; +bfm.export_howto = prm.export_howto; +sof_bf_export(bfm); + +end diff --git a/src/audio/tdfb/tune/sof_bf_line4_two_beams.m b/src/audio/tdfb/tune/sof_bf_line4_two_beams.m new file mode 100644 index 000000000000..a90b03e26d29 --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_line4_two_beams.m @@ -0,0 +1,75 @@ +function sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm) + +% sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm) +% Input +% fs - sample rate +% d - microphones distance in meters +% a1 - steer angle beam 1 +% a2 - steer angle beam 2 +% fn - struct with exported blob files names +% prm +% .add_beam_beam_off - controls addition of beam off definition to blob +% .type - Use 'SDB' or 'DSB' +% .export_note - comment about build generally +% .export_howto - detailed build instruction +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020-2024, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +% Get defaults +bf1 = sof_bf_defaults(); +bf1.fs = fs; + +% Setup array +bf1.array='line'; % Calculate xyz coordinates for line +bf1.mic_n = 4; +bf1.mic_d = d; +bf1.beam_off_defined = prm.add_beam_off; +bf1.type = prm.type; + +% Copy settings for bf2 +bf2 = bf1; + +% Design beamformer 1 (left) +bf1.steer_az = a1; +bf1.steer_el = 0 * a1; +bf1.input_channel_select = [0 1 2 3]; % Input four channels +bf1.output_channel_mix = [1 1 1 1]; % Mix filters to channel 2^0 +bf1.output_channel_mix_beam_off = [1 0 0 2]; % Filter 1 to channel 2^0, filter 4 to channel 2^1 +bf1.output_stream_mix = [0 0 0 0]; % Mix filters to stream 0 +bf1.num_output_channels = 2; +bf1.fn = 10; % Figs 10.... +bf1 = sof_bf_filenames_helper(bf1); +bf1 = sof_bf_design(bf1); + +% Design beamformer 2 (right) +bf2.steer_az = a2; +bf2.steer_el = 0 * a2; +bf2.input_channel_select = [0 1 2 3]; % Input two channels +bf2.output_channel_mix = [2 2 2 2]; % Mix filters to channel 2^1 +bf2.output_channel_mix_beam_off = [0 0 0 0]; % Filters omitted +bf2.output_stream_mix = [0 0 0 0]; % Mix filters to stream 0 +bf2.num_output_channels = 2; +bf2.fn = 20; % Figs 20.... +bf2 = sof_bf_filenames_helper(bf2); +bf2 = sof_bf_design(bf2); + +% Merge two beamformers into single description, set file names +bfm = sof_bf_merge(bf1, bf2); +bfm.sofctl3_fn = fullfile(bfm.sofctl3_path, fn.sofctl3_fn); +bfm.tplg1_fn = fullfile(bfm.tplg1_path, fn.tplg1_fn); +bfm.sofctl4_fn = fullfile(bfm.sofctl4_path, fn.sofctl4_fn); +bfm.ucmbin3_fn = fullfile(bfm.sofctl3_path, fn.ucmbin3_fn); +bfm.ucmbin4_fn = fullfile(bfm.sofctl4_path, fn.ucmbin4_fn); +bfm.tplg2_fn = fullfile(bfm.tplg2_path, fn.tplg2_fn); + +% Export files for topology and sof-ctl +bfm.export_note = prm.export_note; +bfm.export_howto = prm.export_howto; +sof_bf_export(bfm); + +end diff --git a/src/audio/tdfb/tune/sof_bf_merge.m b/src/audio/tdfb/tune/sof_bf_merge.m new file mode 100644 index 000000000000..a82d2edf47ac --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_merge.m @@ -0,0 +1,75 @@ +% bfm = sof_bf_merge(bf1, bf2) + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function bfm = sof_bf_merge(bf1, bf2) + +if nargin > 2 + error('Current implementation can merge only two beams configuration'); +end + +% Check that filter lengths match, the size values are [filter length, filters count, angles count] +s1 = size(bf1.w); +n1 = s1(2); +s2 = size(bf2.w); +n2 = s2(2); +if s1(1) ~= s2(1) + error('Mismatch in filteres length'); +end +if length(s1) == 3 && length(s2) == 3 + if s1(3) ~= s2(3) + error('Mismatch in angles count'); + end +end + +% Get data from bf1, then update fields impacted by merge +bfm = bf1; + +% Merge coefficients +if length(s1) == 3 + bfm.w = zeros(s1(1), n1 + n2, s1(3)); + for i = 1:n1 + bfm.w(:,i,:) = bf1.w(:,i,:); + end + for i = 1:n2 + bfm.w(:,n1 + i,:) = bf2.w(:,i,:); + end +else + bfm.w = zeros(s1(1), n1 + n2); + for i = 1:n1 + bfm.w(:,i) = bf1.w(:,i); + end + for i = 1:n2 + bfm.w(:,n1 + i) = bf2.w(:,i); + end +end + +% Merge filter inputs specification +bfm.input_channel_select = [bf1.input_channel_select bf2.input_channel_select]; + +% Merge filter outputs specification +bfm.output_channel_mix = [bf1.output_channel_mix bf2.output_channel_mix]; +bfm.output_channel_mix_beam_off = [bf1.output_channel_mix_beam_off bf2.output_channel_mix_beam_off]; + +if isempty(bf1.output_stream_mix) + bf1.output_stream_mix = zeros(1, bf1.num_filters); +end +if isempty(bf2.output_stream_mix) + bf2.output_stream_mix = zeros(1, bf2.num_filters); +end +bfm.output_stream_mix = [bf1.output_stream_mix bf2.output_stream_mix]; + +bfm.num_filters = bf1.num_filters + bf2.num_filters; +bfm.num_output_channels = floor(log(max(union(bf1.output_channel_mix, bf2.output_channel_mix)))/log(2)) + 1; +bfm.num_output_streams = max(union(bf1.output_stream_mix, bf2.output_stream_mix)) + 1; + +fprintf(1, 'Merge is ready\n'); +fprintf(1, 'Number of filters %d\n', bfm.num_filters); +fprintf(1, 'Number of output channels %d\n', bfm.num_output_channels); +fprintf(1, 'Number of output streams %d\n', bfm.num_output_streams); + +end diff --git a/src/audio/tdfb/tune/sof_bf_paths.m b/src/audio/tdfb/tune/sof_bf_paths.m new file mode 100644 index 000000000000..9a6a351bdf7d --- /dev/null +++ b/src/audio/tdfb/tune/sof_bf_paths.m @@ -0,0 +1,29 @@ +function sof_bf_paths(enable) + +% sof_bf_paths(enable) +% enable - set to true to enable needed search path +% set to false to disable the search paths +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. + + sof_tools = '../../../../tools'; + sof_modules = '../..'; + common = fullfile(sof_tools, 'tune/common'); + eq = fullfile(sof_modules, 'eq_iir/tune'); + test_utils = fullfile(sof_tools, 'test/audio/test_utils'); + std_utils = fullfile(sof_tools, 'test/audio/std_utils'); + if enable + addpath(common); + addpath(eq); + addpath(test_utils); + addpath(std_utils); + else + rmpath(common); + rmpath(eq); + rmpath(test_utils); + rmpath(std_utils); + end +end diff --git a/src/audio/tdfb/tune/sof_example_all.sh b/src/audio/tdfb/tune/sof_example_all.sh new file mode 100755 index 000000000000..2a263f3438f5 --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_all.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022-2024 Intel Corporation. + +set -e + +CONFIG_LIST=( sof_example_pass_config sof_example_line_array + sof_example_line_0mm36mm146mm182mm sof_example_circular_array + sof_example_two_beams sof_example_two_beams_default ) +OCTAVE_CMD=( octave --no-window-system ) +MATLAB_CMD=( matlab -nodisplay -batch ) + +main () { + if command -v octave &> /dev/null; then + echo "Using Octave" + CMD=( "${OCTAVE_CMD[@]}" ) + EXT=".m" + elif command -v matlab &> /dev/null; then + echo "Using Matlab" + CMD=( "${MATLAB_CMD[@]}" ) + EXT= + else + echo "Please install Matlab or Octave to run this script." + exit 1 + fi + export_configurations +} + +export_configurations() +{ + for cfg in "${CONFIG_LIST[@]}" ; do + "${CMD[@]}" "${cfg}""${EXT}" + done +} + +main "$@" diff --git a/src/audio/tdfb/tune/sof_example_circular_array.m b/src/audio/tdfb/tune/sof_example_circular_array.m new file mode 100644 index 000000000000..dcc2bd52579d --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_circular_array.m @@ -0,0 +1,55 @@ +function sof_example_circular_array() + +% example_circular_array() +% +% Creates a circular array configuration blobs for devices +% with 6 microphones and radius 30 mm + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2021, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +% Circular array with one beam and one output channel + +az = -180:30:150; +circular_one_beam(16e3, 100e-3, 8, 28, az); +circular_one_beam(48e3, 100e-3, 8, 64, az); + +end + +% Note: In the example all designs are made 2ch out for the test script +% in tools/test/audio/tdfb_test.m to work correctly. So in this one beam +% example there's a dual mono (stereo) output. If there would be no need +% to build two beams design with same array this could be one channel out. + +function circular_one_beam(fs, r, n, fir_length, az); + +% Get defaults +bf = sof_bf_defaults(); +bf.input_channel_select = 0:(n-1); % Input all n channels to filters +bf.output_channel_mix_beam_off = zeros(1, n); % For some stereo symmetry +bf.output_channel_mix_beam_off(2) = 1; % Mic2 to channel 2^0 +bf.output_channel_mix_beam_off(n) = 2; % Mic2 to channel 2^1 +bf.output_channel_mix = 3 * ones(1, n); % Mix all filters to channel 1 and 2 +bf.output_stream_mix = zeros(1, n); % No support yet +bf.num_output_channels = 2; % Two channels +bf.num_output_streams = 1; % One sink stream +bf.array = 'circular'; % Calculate xyz coordinates for circular +bf.mic_n = n; + +% From parameters +bf.fs = fs; +bf.mic_r = r; +bf.steer_az = az; +bf.steer_el = 0 * az; +bf.fir_length = fir_length; + +% Design +bf = sof_bf_filenames_helper(bf); +bf = sof_bf_design(bf); +bf.export_note = 'Created with script sof_example_circular_array.m'; +bf.export_howto = 'cd tools/tune/tdfb; octave --no-window-system sof_example_circular_array.m'; +sof_bf_export(bf); +end diff --git a/src/audio/tdfb/tune/sof_example_direction_emphasis.m b/src/audio/tdfb/tune/sof_example_direction_emphasis.m new file mode 100644 index 000000000000..7cbf92a12fec --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_direction_emphasis.m @@ -0,0 +1,67 @@ +% Design 48 kHz and 16 kHz emphasis filter for crosscorrelation +% operation in sound direction estimation. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function example_direction_emphasis() + +addpath('../eq'); + +%% -------------------------------------------------- +%% Example: TDFB emphasis filter 16 kHz and 48 kHz +%% -------------------------------------------------- +tdfb_emphasis(48e3, 'tdfb_iir_emphasis_48k.h', 'iir_emphasis_48k'); +tdfb_emphasis(16e3, 'tdfb_iir_emphasis_16k.h', 'iir_emphasis_16k'); + +%% ------------------------------------ +%% Done. +%% ------------------------------------ + +end + +%% ------------------- +%% EQ design functions +%% ------------------- + +function eq = tdfb_emphasis(fs, fn, vn) + +%% Get defaults for equalizer design +eq = eq_defaults(); +eq.fs = fs; +eq.enable_iir = 1; +eq.norm_type = 'peak'; +eq.norm_offs_db = 0; + +%% Parametric EQ +eq.peq = [ ... + eq.PEQ_HP2 800 NaN NaN ; ... + eq.PEQ_LP2 4000 NaN NaN ; ... + ]; + +%% Design EQ +eq = eq_compute(eq); + +%% Plot +eq_plot(eq); + +%% Quantize and pack filter coefficients plus shifts etc. +bq = eq_iir_blob_quant(eq.p_z, eq.p_p, eq.p_k); + +%% Build blob +channels_in_config = 2; % Setup max 4 channels EQ +assign_response = [0 0]; % Order: lo, hi, lo, hi +num_responses = 1; % Two responses: lo, hi +bm = eq_iir_blob_merge(channels_in_config, ... + num_responses, ... + assign_response, ... + bq); + +%% Pack and write file +bp = eq_iir_blob_pack(bm); +export_c_eq_uint32t(fn, bp, vn, 1); + +end diff --git a/src/audio/tdfb/tune/sof_example_line_0mm36mm146mm182mm.m b/src/audio/tdfb/tune/sof_example_line_0mm36mm146mm182mm.m new file mode 100644 index 000000000000..62e5cae7172f --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_line_0mm36mm146mm182mm.m @@ -0,0 +1,61 @@ +function sof_example_line_0mm36mm146mm182mm() + +% Creates beamformer for device with device with microphones +% at 0, 36, 146, 182mm locations + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +line_xyz(16e3, 40, -90:15:90); +line_xyz(48e3, 80, -90:15:90); + +end + +function line_xyz(fs, fir_length, az) + +tplg1_fn = sprintf('coef_line4_0mm36mm146mm182mm_%dkhz.m4', fs/1e3); +sofctl3_fn = sprintf('coef_line4_0mm36mm146mm182mm_%dkhz.txt', fs/1e3); +tplg2_fn = sprintf('line4_0mm36mm146mm182mm_%dkhz.conf', fs/1e3); +sofctl4_fn = sprintf('line4_0mm36mm146mm182mm_%dkhz.txt', fs/1e3); + +% Get defaults +close all; +bf = sof_bf_defaults(); +bf.fs = fs; +bf.beta = 5; + +% Setup array +bf.array = 'xyz'; +bf.mic_y = [182 146 36 0]*1e-3; +bf.mic_x = [0 0 0 0]; +bf.mic_z = [0 0 0 0]; + +% Despite xyz array this is line, so use the -90 .. +90 degree enum scale for +% angles. Array equals 'line' get this setting automatically. +bf.angle_enum_mult = 15; +bf.angle_enum_offs = -90; + +% Design beamformer +bf.fir_length = fir_length; +bf.steer_az = az; +bf.steer_el = 0 * az; +bf.input_channel_select = [0 1 2 3]; % Input four channels +bf.output_channel_mix = [3 3 3 3]; % Mix filters to channel 2^0 and 2^1 +bf.output_channel_mix_beam_off = [1 0 0 2]; % Filter 1 to channel 2^0, filter 4 to channel 2^1 +bf.output_stream_mix = [0 0 0 0]; % Mix filters to stream 0 +bf.num_output_channels = 2; % Stereo + +%bf.sofctl_fn = fullfile(bf.sofctl_path, sofctl_fn); +%bf.tplg_fn = fullfile(bf.tplg_path, tplg_fn); +bf = sof_bf_filenames_helper(bf, 'line4_0mm36mm146mm182mm'); +bf = sof_bf_design(bf); + +% Export files for topology and sof-ctl +bf.export_note = 'Created with script example_line_0mm36mm146mm182mm.m'; +bf.export_howto = 'cd tools/tune/tdfb; octave --no-window-system example_line_0mm36mm146mm182mm.m'; +sof_bf_export(bf); + +end diff --git a/src/audio/tdfb/tune/sof_example_line_array.m b/src/audio/tdfb/tune/sof_example_line_array.m new file mode 100644 index 000000000000..5ae28003fc79 --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_line_array.m @@ -0,0 +1,66 @@ +function sof_example_line_array() + +% example_line_array() +% +% Creates a number of line array configuration blobs for devices +% with 2 microphones with spacing of 50 mm and 68 mm +% with 4 microphones with spacing of 28 mm, 68 mm, and 78 mm + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% 2 mic arrays +az = -90:15:90; +close all; line_one_beam(48e3, 50e-3, az, 2, 64); +close all; line_one_beam(48e3, 68e-3, az, 2, 64); +close all; line_one_beam(48e3, 73.5e-3, az, 2, 64); +close all; line_one_beam(16e3, 50e-3, az, 2, 40); +close all; line_one_beam(16e3, 68e-3, az, 2, 40); +close all; line_one_beam(16e3, 73.5e-3, az, 2, 40); + +%% 4 mic arrays +close all; line_one_beam(48e3, 28e-3, az, 4, 80); +close all; line_one_beam(48e3, 68e-3, az, 4, 112); +close all; line_one_beam(48e3, 78e-3, az, 4, 120); + +close all; line_one_beam(16e3, 28e-3, az, 4, 40); +close all; line_one_beam(16e3, 68e-3, az, 4, 52); +close all; line_one_beam(16e3, 78e-3, az, 4, 60); + +end + +function line_one_beam(fs, d, az, n_mic, n_fir) + % Get defaults + bf = sof_bf_defaults(); + bf.input_channel_select = 0:(n_mic-1); % Input all n channels to filters + bf.output_channel_mix = 3 * ones(1, n_mic); % Mix all filters to channel 1 and 2 + bf.output_stream_mix = zeros(1, n_mic); % Mix filters to stream 0 + bf.num_output_channels = 2; % Stereo + bf.num_output_streams = 1; % One sink stream + bf.array = 'line'; % Calculate xyz coordinates for line + bf.mic_n = n_mic; + + % Mix only filters 1 and N to left and right stereo, it gives best + % passive stereo effect for beam off mode + bf.output_channel_mix_beam_off = [1 zeros(1, n_mic-2) 2]; + + % From parameters + bf.fs = fs; + bf.mic_d = d; + bf.steer_az = az; + bf.steer_el = 0 * az; % all 0 deg + + if nargin > 4 + bf.fir_length = n_fir; + end + + % Design + bf = sof_bf_filenames_helper(bf); + bf = sof_bf_design(bf); + bf.export_note = 'Created with script sof_example_line_array.m'; + bf.export_howto = 'cd tools/tune/tdfb; octave --no-window-system sof_example_line_array.m'; + sof_bf_export(bf); +end diff --git a/src/audio/tdfb/tune/sof_example_pass_config.m b/src/audio/tdfb/tune/sof_example_pass_config.m new file mode 100644 index 000000000000..0092f978d73e --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_pass_config.m @@ -0,0 +1,84 @@ +function sof_example_pass_config() + +% example_pass_config() +% +% Creates a number for topologies a special configuration blob +% that instantiates two min. length filters and configures +% each channel to pass. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +% Setup for two channels +bf = sof_bf_defaults(); +bf.input_channel_select = [0 1]; % Input two channels +bf.output_channel_mix = [1 2]; % Filter1 -> ch0, filter2 -> ch1 +bf.output_stream_mix = [0 0]; % Mix both filters to stream 0 +bf.num_output_channels = 2; % Two channels +bf.num_output_streams = 1; % One sink stream +bf.beam_off_defined = 0; % No need for separate bypass definition +bf.num_angles = 1; % Need at least one beam defined even +bf.steer_az = 0; % if no processing happens, claim it's +bf.steer_el = 0; % angle (0, 0). +bf.num_filters = 2; % Two filters + +% Minimal manual design fields for successful export +bf.w = [1 0 0 0; 1 0 0 0]'; % Two FIR filters with first tap set to one + +% Files +bf.export_note = 'Exported with script sof_example_pass_config.m'; +bf.export_howto = 'cd tools/tune/tdfb; octave --no-window-system sof_example_pass_config.m'; +bf.sofctl3_fn = fullfile(bf.sofctl3_path, 'coef_line2_pass.txt'); +bf.tplg1_fn = fullfile(bf.tplg1_path, 'coef_line2_pass.m4'); +bf.sofctl4_fn = fullfile(bf.sofctl4_path, 'line2_pass.txt'); +bf.ucmbin3_fn = fullfile(bf.sofctl3_path, 'line2_pass.bin'); +bf.ucmbin4_fn = fullfile(bf.sofctl4_path, 'line2_pass.bin'); +bf.tplg2_fn = fullfile(bf.tplg2_path, 'line2_pass.conf'); +sof_bf_export(bf); + +% Setup for four channels +bf.input_channel_select = [0 1 2 3]; % Input four channels +bf.output_channel_mix = [1 2 4 8]; % Filter1 -> ch0, filter2 -> ch1, ... +bf.output_stream_mix = [0 0 0 0]; % Mix both filters to stream 0 +bf.num_output_channels = 4; % Four channels +bf.num_output_streams = 1; % One sink stream + +% Minimal manual design fields for successful export +bf.num_filters = 4; +bf.w = [1 0 0 0; 1 0 0 0; 1 0 0 0; 1 0 0 0]'; % Four FIR filters with first tap set to one + +% Files +bf.sofctl3_fn = fullfile(bf.sofctl3_path, 'coef_line4_pass.txt'); +bf.tplg1_fn = fullfile(bf.tplg1_path, 'coef_line4_pass.m4'); +bf.sofctl4_fn = fullfile(bf.sofctl4_path, 'line4_pass.txt'); +bf.ucmbin3_fn = fullfile(bf.sofctl3_path, 'line4_pass.bin'); +bf.ucmbin4_fn = fullfile(bf.sofctl4_path, 'line4_pass.bin'); +bf.tplg2_fn = fullfile(bf.tplg2_path, 'line4_pass.conf'); +sof_bf_export(bf); + + +% Setup for four channels to two channels passthrough + +bf.input_channel_select = [0 3]; % Input two channels, leftmost, rightmost mic of 4 +bf.output_channel_mix = [1 2]; % Filter1 -> ch0, filter2 -> ch1 +bf.output_stream_mix = [0 0]; % Mix both filters to stream 0 +bf.num_output_channels = 2; % Two channels +bf.num_output_streams = 1; % One sink stream + +% Minimal manual design fields for successful export +bf.num_filters = 2; +bf.w = [1 0 0 0; 1 0 0 0]'; % Two FIR filters with first tap set to one + +% Files +bf.sofctl3_fn = fullfile(bf.sofctl3_path, 'coef_line4to2_pass.txt'); +bf.tplg1_fn = fullfile(bf.tplg1_path, 'coef_line4to2_pass.m4'); +bf.sofctl4_fn = fullfile(bf.sofctl4_path, 'line4to2_pass.txt'); +bf.ucmbin3_fn = fullfile(bf.sofctl3_path, 'line4to2_pass.bin'); +bf.ucmbin4_fn = fullfile(bf.sofctl4_path, 'line4to2_pass.bin'); +bf.tplg2_fn = fullfile(bf.tplg2_path, 'line4to2_pass.conf'); +sof_bf_export(bf); + +end diff --git a/src/audio/tdfb/tune/sof_example_two_beams.m b/src/audio/tdfb/tune/sof_example_two_beams.m new file mode 100644 index 000000000000..2ae2c08a5f02 --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_two_beams.m @@ -0,0 +1,256 @@ +function sof_example_two_beams() + +% example_two_beams() +% +% Creates configuration files for a two beams design, one +% points to -90 or -25 degrees and other to +90 or +25 degrees +% direction for 50 mm spaced two microphones configuration. The +% beams are output to stereo and left right channels. +% +% The four channels version is for 28 mm mic spacing. The +% first beam is copied to channels 1 and 3. The second +% beam is copied to channels 2 and 4. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2020, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Stereo capture blobs with two beams +az = [5 15 30 90]; +azstr = az_to_string(az); + +prm.export_note = 'Created with script example_two_beams.m'; +prm.export_howto = 'cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams'; +prm.type = 'SDB'; +prm.add_beam_off = 1; + +for fs = [16e3 48e3] + %% Close all plots to avoid issues with large number of windows + close all; + a1 = az; % Azimuth +az deg + a2 = -az; % Azimuth -az deg + + %% 2 mic 50 mm array + d = 50e-3; % 50 mm spacing + fn = export_names_helper('line2', azstr, d, fs); + sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm); + + %% 2 mic 68 mm array + d = 68e-3; % 68 mm spacing + fn = export_names_helper('line2', azstr, d, fs); + sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm); + + %% 2 mic 73.5 mm array + d = 73.5e-3; % 73.5 mm spacing + fn = export_names_helper('line2', azstr, d, fs); + sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm); + + %% 4 mic 28 mm spaced array + d = 28e-3; % 28 mm spacing + fn = export_names_helper('line4', azstr, d, fs); + sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm); + + %% 4 mic 68 mm spaced array + d = 68e-3; % 68 mm spacing + fn = export_names_helper('line4', azstr, d, fs); + sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm); + + %% 4 mic 78 mm spaced array + d = 78e-3; % 78 mm spacing + fn = export_names_helper('line4', azstr, d, fs); + sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm); +end + +%% Export blob with just +/- 90 deg beams for testbench beampattern check +close all; +az = [90]; +azstr = az_to_string(az); +prm.add_beam_off = 0; +for fs = [16e3 48e3] + %% 2 mic 50 mm array, disable beam off description in blob to force processing on + fn.tplg1_fn = sprintf('coef_line2_50mm_pm%sdeg_%dkhz.m4', azstr, fs/1e3); + fn.sofctl3_fn = sprintf('coef_line2_50mm_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.tplg2_fn = sprintf('line2_50mm_pm%sdeg_%dkhz.conf', azstr, fs/1e3); + fn.sofctl4_fn = sprintf('line2_50mm_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + d = 50e-3; % 50 mm spacing + a1 = az; % Azimuth +az deg + a2 = -az; % Azimuth -az deg + sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm); + + %% 4 mic 28 mm spaced array, no beam off configuration + fn.tplg1_fn = sprintf('coef_line4_28mm_pm%sdeg_%dkhz.m4', azstr, fs/1e3); + fn.sofctl3_fn = sprintf('coef_line4_28mm_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.tplg2_fn = sprintf('line4_28mm_pm%sdeg_%dkhz.conf', azstr, fs/1e3); + fn.sofctl4_fn = sprintf('line4_28mm_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + d = 28e-3; % 28 mm spacing + a1 = az; % Azimuth +az deg + a2 = -az; % Azimuth -az deg + sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm); +end + +%% Circular array with two beams +az = 30; +azstr = az_to_string(az); +for fs = [48e3 16e3] + fn.tplg1_fn = sprintf('coef_circular8_100mm_pm%sdeg_%dkhz.m4', azstr, fs/1e3); + fn.sofctl3_fn = sprintf('coef_circular8_100mm_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.tplg2_fn = sprintf('coef_circular8_100mm_pm%sdeg_%dkhz.conf', azstr, fs/1e3); + fn.sofctl4_fn = sprintf('coef_circular8_100mm_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + circular_two_beams(fs, 100e-3, 8, az, -az, fn, 0); +end + +%% Creates beamformer with two beams for device with device with microphones +% at 0, 36, 146, 182mm locations +line_xyz(16e3); +line_xyz(48e3); + +end + +function s = az_to_string(az) + s = sprintf('%d', az(1)); + for n = 2:length(az) + s = sprintf('%s_%d', s, az(n)); + end +end + +function circular_two_beams(fs, r, n, a1, a2, fn, add_beam_off) + +% Get defaults and common settings +bf1 = sof_bf_defaults(); +bf1.beam_off_defined = add_beam_off; +bf1.fs = fs; +bf1.mic_r = r; +bf1.mic_n = n; +bf1.array = 'circular'; % Calculate xyz coordinates for circular +bf1.output_stream_mix = zeros(1, n); % No support yet +bf1.num_output_channels = 2; % Two channels +bf1.num_output_streams = 1; % One sink stream +bf1.input_channel_select = 0:(n-1); % Input all n channels to filters + +% Copy settings for bf2 +bf2 = bf1; + +% Design beamformer 1 (left) +bf1.output_channel_mix_beam_off = zeros(1, n); % For some stereo symmetry +bf1.output_channel_mix_beam_off(2) = 1; % Mic2 to channel 2^0 +bf1.output_channel_mix_beam_off(n) = 2; % Mic2 to channel 2^1 +bf1.output_channel_mix = 1 * ones(1, n); % Mix all filters to channel 1 +bf1.steer_az = a1; +bf1 = sof_bf_filenames_helper(bf1); +bf1 = sof_bf_design(bf1); + +% Design beamformer 2 (right) +bf2.output_channel_mix_beam_off = zeros(1, n); % No channels input +bf2.output_channel_mix = 2 * ones(1, n); % Mix all filters to channel 2 +bf2.steer_az = a2; +bf2 = sof_bf_filenames_helper(bf2); +bf2 = sof_bf_design(bf2); + +% Merge two beamformers into single description, set file names +bfm = sof_bf_merge(bf1, bf2); +bfm.sofctl3_fn = fullfile(bfm.sofctl3_path, fn.sofctl3_fn); +bfm.tplg1_fn = fullfile(bfm.tplg1_path, fn.tplg1_fn); +bfm.sofctl4_fn = fullfile(bfm.sofctl4_path, fn.sofctl4_fn); +bfm.tplg2_fn = fullfile(bfm.tplg2_path, fn.tplg2_fn); + +% Export files for topology and sof-ctl +bfm.export_note = 'Created with script sof_example_two_beams.m'; +bfm.export_howto = 'cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r sof_example_two_beams'; +sof_bf_export(bfm); + +end + +function line_xyz(fs) + +% Get defaults +bf1 = sof_bf_defaults(); +bf1.fs = fs; +bf1.beta = 5; + +% The large size array needs more taps for 48 kHz, also the blob needs to +% be less than 4 kB. +switch fs + case 16000 + az = [0 30 90]; + azstr = 'pm0_30_90deg'; + bf1.fir_length = 64; + case 48000 + az = [0 30]; + azstr = 'pm0_30deg'; + bf1.fir_length = 100; +end + +% Setup array +tplg1_fn = sprintf('coef_line4_0mm36mm146mm182mm_%s_%dkhz.m4', azstr, fs/1e3); +sofctl3_fn = sprintf('coef_line4_0mm36mm146mm182mm_%s_%dkhz.txt', azstr, fs/1e3); +tplg2_fn = sprintf('line4_0mm36mm146mm182mm_%s_%dkhz.conf', azstr, fs/1e3); +sofctl4_fn = sprintf('line4_0mm36mm146mm182mm_%s_%dkhz.txt', azstr, fs/1e3); +a1 = az; % Azimuth +az deg +a2 = -az; % Azimuth -az deg +close all; +bf1.array = 'xyz'; +bf1.mic_y = [182 146 36 0]*1e-3; +bf1.mic_x = [0 0 0 0]; +bf1.mic_z = [0 0 0 0]; + +% Despite xyz array this is line, so use the -90 .. +90 degree enum scale for +% angles. Array equals 'line' get this setting automatically. +bf1.angle_enum_mult = 15; +bf1.angle_enum_offs = -90; + +% Copy settings to other beam +bf2 = bf1; + +% Design beamformer 1 (left) +bf1.steer_az = a1; +bf1.steer_el = 0 * a1; +bf1.input_channel_select = [0 1 2 3]; % Input four channels +bf1.output_channel_mix = [1 1 1 1]; % Mix filters to channel 2^0 +bf1.output_channel_mix_beam_off = [1 0 0 2]; % Filter 1 to channel 2^0, filter 4 to channel 2^1 +bf1.output_stream_mix = [0 0 0 0]; % Mix filters to stream 0 +bf1.num_output_channels = 2; % Stereo +bf1.fn = 10; % Figs 10.... +bf1 = sof_bf_filenames_helper(bf1); +bf1 = sof_bf_design(bf1); + +% Design beamformer 2 (right) +bf2.steer_az = a2; +bf2.steer_el = 0 * a2; +bf2.input_channel_select = [0 1 2 3]; % Input two channels +bf2.output_channel_mix = [2 2 2 2]; % Mix filters to channel 2^1 +bf2.output_channel_mix_beam_off = [0 0 0 0]; % Filters omitted +bf2.output_stream_mix = [0 0 0 0]; % Mix filters to stream 0 +bf2.num_output_channels = 2; % Stereo +bf2.fn = 20; % Figs 20.... +bf2 = sof_bf_filenames_helper(bf2); +bf2 = sof_bf_design(bf2); + +% Merge two beamformers into single description, set file names +bfm = sof_bf_merge(bf1, bf2); +bfm.sofctl3_fn = fullfile(bfm.sofctl3_path, sofctl3_fn); +bfm.tplg1_fn = fullfile(bfm.tplg1_path, tplg1_fn); +bfm.sofctl4_fn = fullfile(bfm.sofctl4_path, sofctl4_fn); +bfm.tplg2_fn = fullfile(bfm.tplg2_path, tplg2_fn); + +% Export files for topology and sof-ctl +bfm.export_note = 'Created with script sof_example_two_beams.m'; +bfm.export_howto = 'cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r sof_example_two_beams'; +sof_bf_export(bfm); + +end + +function fn = export_names_helper(arrayname, azstr, d, fs) + +mmstr = sprintf('%dmm', round(d * 1e3)); +fsstr = sprintf('%dkhz', round(fs/1e3)); +fn.tplg1_fn = sprintf('coef_%s_%s_pm%sdeg_%s.m4', arrayname, mmstr, azstr, fsstr); +fn.tplg2_fn = sprintf('%s_%s_pm%sdeg_%s.conf', arrayname, mmstr, azstr, fsstr); +fn.sofctl3_fn = sprintf('%s_%s_pm%sdeg_%s.txt', arrayname, mmstr, azstr, fsstr); +fn.sofctl4_fn = sprintf('%s_%s_pm%sdeg_%s.txt', arrayname, mmstr, azstr, fsstr); +fn.ucmbin3_fn = sprintf('%s_%s_pm%sdeg_%s.bin', arrayname, mmstr, azstr, fsstr); +fn.ucmbin4_fn = sprintf('%s_%s_pm%sdeg_%s.bin', arrayname, mmstr, azstr, fsstr); + +end + diff --git a/src/audio/tdfb/tune/sof_example_two_beams_default.m b/src/audio/tdfb/tune/sof_example_two_beams_default.m new file mode 100644 index 000000000000..779005fcde36 --- /dev/null +++ b/src/audio/tdfb/tune/sof_example_two_beams_default.m @@ -0,0 +1,65 @@ +function sof_example_two_beams_default() + +% sof_example_two_beams_default() +% +% Creates configuration files for a two beams design, one +% points to -10 degrees and other to 10 degrees +% direction for default 50 mm spaced two microphones configuration. The +% beams are output to stereo and left right channels. The angle is +% slightly different for different microphones spacing. With larger +% microphones spacing the angle narrows a bit. But since the target +% is user focused audio with slight stereo effect it's acceptable. +% The bespoke blobs for a device can be applied with ALSA UCM. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Stereo capture blobs with two beams +az = [10]; +azstr = az_to_string(az); + +prm.export_note = 'Created with script sof_example_two_beams_default.m'; +prm.export_howto = 'cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r sof_example_two_beams_default'; +prm.type = 'DSB'; +prm.add_beam_off = 1; + +for fs = [16e3 48e3] + %% Close all plots to avoid issues with large number of windows + close all; + + %% 2 mic array + fn.tplg1_fn = sprintf('coef_line2_generic_pm%sdeg_%dkhz.m4', azstr, fs/1e3); + fn.sofctl3_fn = sprintf('coef_line2_generic_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.tplg2_fn = sprintf('line2_generic_pm%sdeg_%dkhz.conf', azstr, fs/1e3); + fn.sofctl4_fn = sprintf('line2_generic_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.ucmbin3_fn = sprintf('line2_generic_pm%sdeg_%dkhz.bin', azstr, fs/1e3); + fn.ucmbin4_fn = sprintf('line2_generic_pm%sdeg_%dkhz.bin', azstr, fs/1e3); + d = 50e-3; % 50 mm spacing + a1 = az; % Azimuth +az deg + a2 = -az; % Azimuth -az deg + sof_bf_line2_two_beams(fs, d, a1, a2, fn, prm); + + %% 4 mic array + fn.tplg1_fn = sprintf('coef_line4_generic_pm%sdeg_%dkhz.m4', azstr, fs/1e3); + fn.sofctl3_fn = sprintf('coef_line4_generic_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.tplg2_fn = sprintf('line4_generic_pm%sdeg_%dkhz.conf', azstr, fs/1e3); + fn.sofctl4_fn = sprintf('line4_generic_pm%sdeg_%dkhz.txt', azstr, fs/1e3); + fn.ucmbin3_fn = sprintf('line4_generic_pm%sdeg_%dkhz.bin', azstr, fs/1e3); + fn.ucmbin4_fn = sprintf('line4_generic_pm%sdeg_%dkhz.bin', azstr, fs/1e3); + d = 40e-3; % 40 mm spacing + a1 = az; % Azimuth +az deg + a2 = -az; % Azimuth -az deg + sof_bf_line4_two_beams(fs, d, a1, a2, fn, prm); +end + +end + +function s = az_to_string(az) + s = sprintf('%d', az(1)); + for n = 2:length(az) + s = sprintf('%s_%d', s, az(n)); + end +end diff --git a/src/audio/template/CMakeLists.txt b/src/audio/template/CMakeLists.txt new file mode 100644 index 000000000000..1dec4618ed5c --- /dev/null +++ b/src/audio/template/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_TEMPLATE STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/template_llext) + add_dependencies(app template) +else() + add_local_sources(sof template.c) + add_local_sources(sof template-generic.c) + + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof template-ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof template-ipc4.c) + endif() +endif() diff --git a/src/audio/template/Kconfig b/src/audio/template/Kconfig new file mode 100644 index 000000000000..907749c5fa8e --- /dev/null +++ b/src/audio/template/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_TEMPLATE + tristate "Template example component" + default y + help + Select for template component. Reason for existence + is to provide a minimal component example and use as + placeholder in processing pipelines. As example processing + it swaps or reverses the channels when the switch control + is enabled. diff --git a/src/audio/template/README.md b/src/audio/template/README.md new file mode 100644 index 000000000000..93e48c80f2cc --- /dev/null +++ b/src/audio/template/README.md @@ -0,0 +1,14 @@ +# Template Component Architecture + +This directory contains template code. + +## Overview + +Provides a reference or stub implementation that developers can copy and modify to easily construct new custom audio components. + +## Configuration and Scripts + +- **Kconfig**: Exposes the `COMP_TEMPLATE` toggle to build the baseline framework plugin (internally swaps or reverses channels). +- **CMakeLists.txt**: Compiles generic operations (`template.c`, `template-generic.c`) and connects via either IPC major version. Generates a Zephyr `llext` by default. +- **template.toml**: Includes default setup arguments and UUID bindings (`UUIDREG_STR_TEMPLATE`). +- **Topology (.conf)**: Defined in `tools/topology/topology2/include/components/template_comp.conf`, registering the `template_comp` widget of type `effect` (UUID `af:e1:2d:a6:64:59:2e:4e:b1:67:7f:dc:97:27:9a:29`). diff --git a/src/audio/template/llext/CMakeLists.txt b/src/audio/template/llext/CMakeLists.txt new file mode 100644 index 000000000000..f84bd6daf916 --- /dev/null +++ b/src/audio/template/llext/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("template_comp" + SOURCES ../template.c + ../template-generic.c + ../template-ipc4.c + LIB openmodules +) diff --git a/src/audio/template/llext/llext.toml.h b/src/audio/template/llext/llext.toml.h new file mode 100644 index 000000000000..4808c9af8f42 --- /dev/null +++ b/src/audio/template/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../template_comp.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/template/template-generic.c b/src/audio/template/template-generic.c new file mode 100644 index 000000000000..14b68c31d9c5 --- /dev/null +++ b/src/audio/template/template-generic.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/source_api.h> +#include <stdint.h> +#include "template.h" + +#if CONFIG_FORMAT_S16LE +/** + * template_s16() - Process S16_LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * This is the processing function for 16-bit signed integer PCM formats. The + * audio samples in every frame are re-order to channels order defined in + * component data channel_map[]. + * + * Return: Value zero for success, otherwise an error code. + */ +static int template_s16(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct template_comp_data *cd = module_get_private_data(mod); + int16_t const *x, *x_start, *x_end; + int16_t *y, *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int ch; + int i; + + /* Get pointer to source data in circular buffer, get buffer start and size to + * check for wrap. The size in bytes is converted to number of s16 samples to + * control the samples process loop. If the number of bytes requested is not + * possible, an error is returned. + */ + ret = source_get_data_s16(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s16(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x; + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, samples); + + /* Since the example processing is for frames of audio channels, process + * with step of channels count. + */ + for (i = 0; i < samples_without_wrap; i += cd->channels) { + /* In inner loop process the frame. As example re-arrange the channels + * as defined in array channel_map[]. + */ + for (ch = 0; ch < cd->channels; ch++) { + *y = *(x + cd->channel_map[ch]); + y++; + } + x += cd->channels; + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= x_end) ? x - x_size : x; + y = (y >= y_end) ? y - y_size : y; + + /* Update processed samples count for next loop iteration. */ + samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S32LE || CONFIG_FORMAT_S24LE +/** + * template_s32() - Process S32_LE or S24_4LE format. + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + * + * Processing function for signed integer 32-bit PCM formats. The same + * function works for s24 and s32 formats since the samples values are + * not modified in computation. The audio samples in every frame are + * re-order to channels order defined in component data channel_map[]. + * + * Return: Value zero for success, otherwise an error code. + */ +static int template_s32(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames) +{ + struct template_comp_data *cd = module_get_private_data(mod); + int32_t const *x, *x_start, *x_end; + int32_t *y, *y_start, *y_end; + int x_size, y_size; + int source_samples_without_wrap; + int samples_without_wrap; + int samples = frames * cd->channels; + int bytes = frames * cd->frame_bytes; + int ret; + int ch; + int i; + + /* Get pointer to source data in circular buffer, get buffer start and size to + * check for wrap. The size in bytes is converted to number of s16 samples to + * control the samples process loop. If the number of bytes requested is not + * possible, an error is returned. + */ + ret = source_get_data_s32(source, bytes, &x, &x_start, &x_size); + if (ret) + return ret; + + /* Similarly get pointer to sink data in circular buffer, buffer start and size. */ + ret = sink_get_buffer_s32(sink, bytes, &y, &y_start, &y_size); + if (ret) + return ret; + + /* Set helper pointers to buffer end for wrap check. Then loop until all + * samples are processed. + */ + x_end = x_start + x_size; + y_end = y_start + y_size; + while (samples) { + /* Find out samples to process before first wrap or end of data. */ + source_samples_without_wrap = x_end - x; + samples_without_wrap = y_end - y; + samples_without_wrap = MIN(samples_without_wrap, source_samples_without_wrap); + samples_without_wrap = MIN(samples_without_wrap, samples); + + /* Since the example processing is for frames of audio channels, process + * with step of channels count. + */ + for (i = 0; i < samples_without_wrap; i += cd->channels) { + /* In inner loop process the frame. As example re-arrange the channels + * as defined in array channel_map[]. + */ + for (ch = 0; ch < cd->channels; ch++) { + *y = *(x + cd->channel_map[ch]); + y++; + } + x += cd->channels; + } + + /* One of the buffers needs a wrap (or end of data), so check for wrap */ + x = (x >= x_end) ? x - x_size : x; + y = (y >= y_end) ? y - y_size : y; + + /* Update processed samples count for next loop iteration. */ + samples -= samples_without_wrap; + } + + /* Update the source and sink for bytes consumed and produced. Return success. */ + source_release_data(source, bytes); + sink_commit_buffer(sink, bytes); + return 0; +} +#endif /* CONFIG_FORMAT_S32LE || CONFIG_FORMAT_S24LE */ + +/* This struct array defines the used processing functions for + * the PCM formats + */ +const struct template_proc_fnmap template_proc_fnmap[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, template_s16 }, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, template_s32 }, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, template_s32 }, +#endif +}; + +/** + * template_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +template_func template_find_proc_func(enum sof_ipc_frame src_fmt) +{ + int i; + + /* Find suitable processing function from map */ + for (i = 0; i < ARRAY_SIZE(template_proc_fnmap); i++) + if (src_fmt == template_proc_fnmap[i].frame_fmt) + return template_proc_fnmap[i].template_proc_func; + + return NULL; +} diff --git a/src/audio/template/template-ipc3.c b/src/audio/template/template-ipc3.c new file mode 100644 index 000000000000..ad35389341f6 --- /dev/null +++ b/src/audio/template/template-ipc3.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include "template.h" + +LOG_MODULE_DECLARE(template, CONFIG_SOF_LOG_LEVEL); + +/* This function handles the real-time controls. The ALSA controls have the + * param_id set to indicate the control type. The control ID, from topology, + * is used to separate the controls instances of same type. In control payload + * the num_elems defines to how many channels the control is applied to. + */ +__cold int template_set_config(struct processing_module *mod, uint32_t param_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 sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct template_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + comp_dbg(dev, "entry"); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_SWITCH: + if (cdata->index != 0) { + comp_err(dev, "Illegal switch control index = %d.", cdata->index); + return -EINVAL; + } + + if (cdata->num_elems != 1) { + comp_err(dev, "Illegal switch control num_elems = %d.", cdata->num_elems); + return -EINVAL; + } + + cd->enable = cdata->chanv[0].value; + comp_info(dev, "Setting enable = %d.", cd->enable); + return 0; + + case SOF_CTRL_CMD_ENUM: + comp_err(dev, "Illegal enum control, no support in this component."); + return -EINVAL; + case SOF_CTRL_CMD_BINARY: + comp_err(dev, "Illegal bytes control, no support in this component."); + return -EINVAL; + } + + comp_err(dev, "Illegal control, unknown type."); + return -EINVAL; +} + +__cold int template_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct template_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + comp_info(dev, "entry"); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_SWITCH: + if (cdata->index != 0) { + comp_err(dev, "Illegal switch control index = %d.", cdata->index); + return -EINVAL; + } + + if (cdata->num_elems != 1) { + comp_err(dev, "Illegal switch control num_elems = %d.", cdata->num_elems); + return -EINVAL; + } + + cdata->chanv[0].value = cd->enable; + return 0; + + case SOF_CTRL_CMD_ENUM: + comp_err(dev, "Illegal enum control, no support in this component."); + return -EINVAL; + + case SOF_CTRL_CMD_BINARY: + comp_err(dev, "Illegal bytes control, no support in this component."); + return -EINVAL; + } + + comp_err(dev, "Illegal control, unknown type."); + return -EINVAL; +} diff --git a/src/audio/template/template-ipc4.c b/src/audio/template/template-ipc4.c new file mode 100644 index 000000000000..f66015d9041c --- /dev/null +++ b/src/audio/template/template-ipc4.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include "template.h" + +LOG_MODULE_DECLARE(template, CONFIG_SOF_LOG_LEVEL); + +/* IPC4 controls handler */ +__cold int template_set_config(struct processing_module *mod, + uint32_t param_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 sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + struct template_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + assert_can_be_cold(); + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + comp_dbg(dev, "Switch control id = %d, num_elems = %d.", ctl->id, ctl->num_elems); + if (ctl->id != 0) { + comp_err(dev, "Illegal switch control id = %d.", ctl->id); + return -EINVAL; + } + + if (ctl->num_elems != 1) { + comp_err(dev, "Illegal switch control num_elems = %d.", ctl->num_elems); + return -EINVAL; + } + + cd->enable = ctl->chanv[0].value; + comp_info(dev, "Setting enable = %d.", cd->enable); + return 0; + + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "Illegal enum control, no support in this component."); + return -EINVAL; + } + + comp_err(mod->dev, "Illegal bytes control, no support in this component."); + return -EINVAL; +} + +/* Not used in IPC4 systems, if IPC4 only component, omit .get_configuration set */ +__cold int template_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + assert_can_be_cold(); + return 0; +} diff --git a/src/audio/template/template.c b/src/audio/template/template.c new file mode 100644 index 000000000000..1bef6668b75e --- /dev/null +++ b/src/audio/template/template.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_source_utils.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <rtos/init.h> +#include "template.h" + +/* UUID identifies the components. Use e.g. command uuidgen from package + * uuid-runtime, add it to uuid-registry.txt in SOF top level. + */ +SOF_DEFINE_REG_UUID(template); + +/* Creates logging data for the component */ +LOG_MODULE_REGISTER(template, CONFIG_SOF_LOG_LEVEL); + +/** + * template_init() - Initialize the template component. + * @mod: Pointer to module data. + * + * This function is called when the instance is created. The + * macro __cold informs that the code that is non-critical + * is loaded to slower but large DRAM. + * + * Return: Zero if success, otherwise error code. + */ +__cold static int template_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct template_comp_data *cd; + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + return 0; +} + +/** + * template_process() - The audio data processing function. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * This is the processing function that is called for scheduled + * pipelines. The processing is controlled by the enable switch. + * + * Return: Zero if success, otherwise error code. + */ +static int template_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + struct template_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_source *source = sources[0]; /* One input in this example */ + struct sof_sink *sink = sinks[0]; /* One output in this example */ + int frames = source_get_data_frames_available(source); + int sink_frames = sink_get_free_frames(sink); + + comp_dbg(dev, "entry"); + + frames = MIN(frames, sink_frames); + if (cd->enable) + /* Process the data with the channels swap example function. */ + return cd->template_func(mod, source, sink, frames); + + /* Just copy from source to sink. */ + source_to_sink_copy(source, sink, true, frames * cd->frame_bytes); + return 0; +} + +/** + * template_prepare() - Prepare the component for processing. + * @mod: Pointer to module data. + * @sources: Pointer to audio samples data sources array. + * @num_of_sources: Number of sources in the array. + * @sinks: Pointer to audio samples data sinks array. + * @num_of_sinks: Number of sinks in the array. + * + * Function prepare is called just before the pipeline is started. In + * this case the audio format parameters are for better code performance + * saved to component data to avoid to find out them in process. The + * processing function pointer is set to process the current audio format. + * + * Return: Value zero if success, otherwise error code. + */ +static int template_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct template_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + enum sof_ipc_frame source_format; + int i; + + comp_dbg(dev, "entry"); + + /* The processing example in this component supports one input and one + * output. Generally there can be more. + */ + if (num_of_sources != 1 || num_of_sinks != 1) + return -EINVAL; + + /* get source data format */ + cd->frame_bytes = source_get_frame_bytes(sources[0]); + cd->channels = source_get_channels(sources[0]); + source_format = source_get_frm_fmt(sources[0]); + + /* Initialize channels order for reversing */ + for (i = 0; i < cd->channels; i++) + cd->channel_map[i] = cd->channels - i - 1; + + cd->template_func = template_find_proc_func(source_format); + if (!cd->template_func) { + comp_err(dev, "No processing function found for format %d.", + source_format); + return -EINVAL; + } + + return 0; +} + +/** + * template_reset() - Reset the component. + * @mod: Pointer to module data. + * + * The component reset is called when pipeline is stopped. The reset + * should return the component to same state as init. + * + * Return: Value zero, always success. + */ +static int template_reset(struct processing_module *mod) +{ + struct template_comp_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + memset(cd, 0, sizeof(*cd)); + return 0; +} + +/** + * template_free() - Free dynamic allocations. + * @mod: Pointer to module data. + * + * Component free is called when the pipelines are deleted. All + * dynamic allocations need to be freed here. The macro __cold + * instructs the build to locate this performance wise non-critical + * function to large and slower DRAM. + * + * Return: Value zero, always success. + */ +__cold static int template_free(struct processing_module *mod) +{ + struct template_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + comp_dbg(mod->dev, "entry"); + mod_free(mod, cd); + return 0; +} + +/* This defines the module operations */ +static const struct module_interface template_interface = { + .init = template_init, + .prepare = template_prepare, + .process = template_process, + .set_configuration = template_set_config, + .get_configuration = template_get_config, + .reset = template_reset, + .free = template_free +}; + +/* This controls build of the module. If COMP_MODULE is selected in kconfig + * this is build as dynamically loadable module. + */ +#if CONFIG_COMP_TEMPLATE_MODULE + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("TEMPLATE", &template_interface, 1, + SOF_REG_UUID(template), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +/* Only used for the module adapter trace context, soon to be deprecated */ +DECLARE_TR_CTX(template_tr, SOF_UUID(template_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(template_interface, template_uuid, template_tr); +SOF_MODULE_INIT(template, sys_comp_module_template_interface_init); + +#endif diff --git a/src/audio/template/template.h b/src/audio/template/template.h new file mode 100644 index 000000000000..c139a492e6c0 --- /dev/null +++ b/src/audio/template/template.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + */ +#ifndef __SOF_AUDIO_TEMPLATE_H__ +#define __SOF_AUDIO_TEMPLATE_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <stdbool.h> +#include <stdint.h> + +/** + * struct template_func - Function call pointer for process function + * @mod: Pointer to module data. + * @source: Source for PCM samples data. + * @sink: Sink for PCM samples data. + * @frames: Number of audio data frames to process. + */ +typedef int (*template_func)(const struct processing_module *mod, + struct sof_source *source, + struct sof_sink *sink, + uint32_t frames); + +/* Template component private data */ + +/** + * struct template_comp_data + * @template_func: Pointer to used processing function. + * @channels_order[]: Vector with desired sink channels order. + * @source_format: Source samples format. + * @frame_bytes: Number of bytes in an audio frame. + * @channels: Channels count. + * @enable: Control processing on/off, on - reorder channels + */ +struct template_comp_data { + template_func template_func; + int channel_map[PLATFORM_MAX_CHANNELS]; + int source_format; + int frame_bytes; + int channels; + bool enable; +}; + +/** + * struct template_proc_fnmap - processing functions for frame formats + * @frame_fmt: Current frame format + * @template_proc_func: Function pointer for the suitable processing function + */ +struct template_proc_fnmap { + enum sof_ipc_frame frame_fmt; + template_func template_proc_func; +}; + +/** + * template_find_proc_func() - Find suitable processing function. + * @src_fmt: Enum value for PCM format. + * + * This function finds the suitable processing function to use for + * the used PCM format. If not found, return NULL. + * + * Return: Pointer to processing function for the requested PCM format. + */ +template_func template_find_proc_func(enum sof_ipc_frame src_fmt); + +/** + * template_set_config() - Handle controls set + * @mod: Pointer to module data. + * @param_id: Id to know control type, used to know ALSA control type. + * @pos: Position of the fragment in the large message. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * @response_size: Size of response. + * + * This function handles the real-time controls. The ALSA controls have the + * param_id set to indicate the control type. The control ID, from topology, + * is used to separate the controls instances of same type. In control payload + * the num_elems defines to how many channels the control is applied to. + * + * Return: Zero if success, otherwise error code. + */ +int template_set_config(struct processing_module *mod, + uint32_t param_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); + +/** + * template_set_config() - Handle controls get + * @mod: Pointer to module data. + * @config_id: Configuration ID. + * @data_offset_size: Size of the whole configuration if it is the first or only + * fragment. Otherwise it is offset of the fragment. + * @fragment: Message payload data. + * @fragment_size: Size of this fragment. + * + * This function is used for controls get. + * + * Return: Zero if success, otherwise error code. + */ +int template_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); + +#endif // __SOF_AUDIO_TEMPLATE_H__ diff --git a/src/audio/template/template.toml b/src/audio/template/template.toml new file mode 100644 index 000000000000..6d41f3a599f5 --- /dev/null +++ b/src/audio/template/template.toml @@ -0,0 +1,21 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Template component module config + [[module.entry]] + name = "TEMPLATE" + uuid = UUIDREG_STR_TEMPLATE + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/tensorflow/CMakeLists.txt b/src/audio/tensorflow/CMakeLists.txt new file mode 100644 index 000000000000..5cb3086f46b1 --- /dev/null +++ b/src/audio/tensorflow/CMakeLists.txt @@ -0,0 +1,465 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +# are we building the llext module ? +if(CONFIG_COMP_TENSORFLOW STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/tflm_llext) + add_dependencies(app tflm) + return() +endif() + +# TODO: detect Hifi4/5 for NN lib kernels +set(NN_HIFI_PATH ${sof_top_dir}/../nnlib-hifi4/xa_nnlib) + +# paths for dependencies +set(TFLM_PATH ${sof_top_dir}/../tflite-micro) +set(FLATBUFFERS_PATH ${sof_top_dir}/../flatbuffers) +set(GEMMLOWP_PATH ${sof_top_dir}/../gemmlowp) +set(RUY_PATH ${sof_top_dir}/../ruy) + +add_library(nn_hifi_lib STATIC + ${NN_HIFI_PATH}/algo/common/src/xa_nnlib_common_api.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_pad_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_stride_slice_int16.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_batch_to_space_nd_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_transpose_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_depth_to_space_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_pad_16.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_stride_slice_int32.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_space_to_batch_nd_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_pad_32.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_stride_slice_int8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_space_to_depth_8.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_32_32.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_f32_f32.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_sym16_sym16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_softmax_asym8_asym8.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_32_16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_16_16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_8_8.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_asym16_asym16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_32_8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_16x16_16_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_group_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_asym8xasym8_asym8_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x8_8_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_8x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_16x16_16_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_f32_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x16_16_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_sym8sxsym16s_sym16s_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_8x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_f32_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_asym8xasym8_asym8_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_8x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_sym8sxasym8s_asym8s_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x16_16_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x8_8_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_sym4sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_8x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_f32.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym8xasym8_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_8x8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_8x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym4sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_f32_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_f32.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_16x16_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_asym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_16x8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_16x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x16_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_16x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x8_batch.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_f32.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_asym8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_f32_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_16_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_16.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_16_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_asym8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_inv_256_tbl.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_16.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_f32_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_asym8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_f32.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_asym8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/norm/hifi4/xa_nn_l2_norm_asym8s.c + ${NN_HIFI_PATH}/algo/kernels/norm/hifi4/xa_nn_l2_norm_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sqrt_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_16x16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_add_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_lstm_utils.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_dot_prod_16x16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sub_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_round_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_acc_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_cosine_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_reduce_asym8s_asym8s.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_memset_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_floor_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_squared_diff_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_add_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_reduce_asym16s_asym16s.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_minmax_8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_logn_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_div_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sub_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_compare_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_logical_bool.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_broadcast_8_8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_quantize.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_neg_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_add_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_vec_interpolation_q15.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_square_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sine_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_abs_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_memmove.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_squared_diff_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_memmove_16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sub_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_ceil_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_rsqrt_f32.c + ${NN_HIFI_PATH}/algo/kernels/fc/hifi4/xa_nn_fully_connected.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_tanh32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/scl_sigmoidf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/inv2pif_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/nanf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/pow2f_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_sigmoidf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_reluf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/expf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_tanhf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_sigmoid32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/lognf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/sinf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_cosinef_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_sinef_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_softmaxf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/scl_tanhf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_softmax32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_lognf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/sqrt2f_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/inff_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_alognf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_relu32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/tanhf_tbl.c +) + +target_include_directories(nn_hifi_lib PRIVATE + ${NN_HIFI_PATH}/include + ${NN_HIFI_PATH}/algo/common/include/ + ${NN_HIFI_PATH}/include/nnlib/ + ${NN_HIFI_PATH}/algo/ndsp/hifi4/include +) + +# TODO: Need to detect and add mul16/32 options. +#ifeq "$(has_mul16)" "0" +#CFLAGS += -mno-mul16 +#endif +#ifeq "$(has_mul32)" "0" +#CFLAGS += -mno-mul32 -mno-div32 +#endif +target_compile_options(nn_hifi_lib PRIVATE + -fsigned-char + -fno-exceptions + -mlongcalls + -INLINE:requested + -mcoproc + -fno-zero-initialized-in-bss + -mtext-section-literals + -Wsign-compare + -m32 + -DMODEL_INT16 + -DNNLIB_V2 + -Dhifi4 + -DTFLITE_SINGLE_ROUNDING=1 +) + +# TODO: complete sources have been added here from userspace build but +# not all are needed so this is a list of "needed" sources to build +# a memory and performance optimized TFLM for SOF. +# All sources have been left in for completeness now, but will be removed +# when support is mature. +add_library(tflm_lib STATIC + ${TFLM_PATH}/tensorflow/compiler/mlir/lite/core/api/error_reporter.cc + ${TFLM_PATH}/tensorflow/compiler/mlir/lite/schema/schema_utils.cc + ${TFLM_PATH}/tensorflow/lite/core/c/common.cc + ${TFLM_PATH}/tensorflow/lite/core/api/flatbuffer_conversions.cc + ${TFLM_PATH}/tensorflow/lite/core/api/tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/common.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/runtime_shape.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/quantization_util.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/tensor_ctypes.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/portable_tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/reference/comparisons.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/kernel_util.cc + # Stock micro kernels - not needed atm + #${TFLM_PATH}/tensorflow/lite/micro/kernels/activations_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/activations.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/add_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/add_n.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/arg_min_max.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/assign_variable.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/batch_matmul.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/batch_to_space_nd.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/broadcast_args.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/broadcast_to.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/call_once.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/cast.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/ceil.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/circular_buffer_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/circular_buffer.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/comparisons.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/concatenation.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/conv_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/cumsum.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/depth_to_space.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/depthwise_conv_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/dequantize_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/detection_postprocess.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/div.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/elementwise.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/elu.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/embedding_lookup.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/ethosu.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/expand_dims.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/exp.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/fill.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/floor_div.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/floor_mod.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/floor.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/fully_connected_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/gather_nd.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/gather.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/hard_swish_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/hard_swish.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/if.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/kernel_runner.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/kernel_util.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/l2norm.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/l2_pool_2d.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/leaky_relu_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/logical_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/logical.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/logistic_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/log_softmax.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/lstm_eval_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/maximum_minimum.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/micro_tensor_utils.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/mirror_pad.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/mul_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/mul.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/neg.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/pack.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/pooling_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/prelu_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/prelu.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/quantize_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/read_variable.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/reduce_common.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/reshape_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/resize_bilinear.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/round.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/select.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/shape.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/slice.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/softmax_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/space_to_batch_nd.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/space_to_depth.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/split.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/split_v.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/squared_difference.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/squeeze.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/strided_slice_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/sub_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/svdf_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/tanh.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/transpose.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/unpack.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/var_handle.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/while.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/zeros_like.cc + # xtensa kernels + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/sub.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_hifi.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pooling_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/softmax_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/unidirectional_sequence_lstm.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/transpose_conv.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected_common_xtensa.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/lstm_eval_hifi.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/add_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/depthwise_conv.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reshape.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/softmax.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/depthwise_conv_hifi.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_int16_reference.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_int8_reference.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected_int8.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pad_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_int8_int16.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/softmax_int8_int16.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/logistic.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reduce.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/lstm_eval.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reshape_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pad.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reduce_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/dequantize.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/add.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pooling_int8.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/depthwise_conv_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/strided_slice.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_common_xtensa.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/svdf.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/leaky_relu.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/quantize.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pooling.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/mock_micro_graph.cc + ${TFLM_PATH}/tensorflow/lite/micro/flatbuffer_utils.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_interpreter_graph.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_resource_variable.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_interpreter_context.cc + ${TFLM_PATH}/tensorflow/lite/micro/fake_micro_context.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/tflite_bridge/flatbuffer_conversions_bridge.cc + ${TFLM_PATH}/tensorflow/lite/micro/tflite_bridge/micro_error_reporter.cc + ${TFLM_PATH}/tensorflow/lite/micro/system_setup.cc + #${TFLM_PATH}/tensorflow/lite/micro/span_test.cc + ${TFLM_PATH}/tensorflow/lite/micro/test_helper_custom_ops.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_context.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_log.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_profiler.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_time.cc + #${TFLM_PATH}/tensorflow/lite/micro/static_vector_test.cc + ${TFLM_PATH}/tensorflow/lite/micro/debug_log.cc + ${TFLM_PATH}/tensorflow/lite/micro/test_helpers.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_op_resolver.cc + ${TFLM_PATH}/tensorflow/lite/micro/recording_micro_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_helpers.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_allocation_info.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_planner/linear_memory_planner.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_utils.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_interpreter.cc + micro_speech_quantized_model_data.cc + speech.cc +) + +target_include_directories(tflm_lib PRIVATE + ${TFLM_PATH} + ${FLATBUFFERS_PATH}/include + ${GEMMLOWP_PATH} + ${RUY_PATH} + ${NN_HIFI_PATH} + ${NN_HIFI_PATH}/include + ${sof_top_dir}/posix/include +) + +# TODO: Need to detect and add mul16/32 options. +#ifeq "$(has_mul16)" "0" +#CFLAGS += -mno-mul16 +#endif +#ifeq "$(has_mul32)" "0" +#CFLAGS += -mno-mul32 -mno-div32 +#endif +target_compile_options(tflm_lib PRIVATE + -std=c++17 + -stdlib=libc++ + -fno-rtti + -fno-exceptions + -fno-threadsafe-statics + -Wnon-virtual-dtor + -fno-unwind-tables + -fmessage-length=0 + -DTF_LITE_STATIC_MEMORY + -DTF_LITE_DISABLE_X86_NEON + -Wsign-compare + -Wdouble-promotion + -Wunused-variable + -Wswitch + -Wvla + -Wall + -Wextra + -Wmissing-field-initializers + -Wstrict-aliasing + -Wno-unused-parameter + -DXTENSA + -DKERNELS_OPTIMIZED_FOR_SPEED + -DTF_LITE_MCU_DEBUG_LOG + -DTF_LITE_USE_CTIME + --xtensa-core=ace10_LX7HiFi4_2022_10 + -mcoproc + -DHIFI4 + -mlongcalls + -DNNLIB_V2 + -Wno-shadow +) + +add_local_sources(sof tflm-classify.c llext-wrap.c) + +# Need to link libc++ and libc after tflm and nnlib +zephyr_link_libraries(tflm_lib nn_hifi_lib c++ c) +zephyr_include_directories(${TFLM_PATH}) diff --git a/src/audio/tensorflow/Kconfig b/src/audio/tensorflow/Kconfig new file mode 100644 index 000000000000..446f9add2849 --- /dev/null +++ b/src/audio/tensorflow/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_TENSORFLOW + tristate "Tensorflow Micro component" + depends on SOF_STAGING + depends on CPP + depends on STD_CPP17 + help + Select for Tensorflow component support. This module supports + Tensorflow Micro library. It is used for running machine learning + models on DSP. It is a lightweight version of Tensorflow library + designed for microcontrollers and embedded systems. diff --git a/src/audio/tensorflow/README.md b/src/audio/tensorflow/README.md new file mode 100644 index 000000000000..a8e3f59ba3ce --- /dev/null +++ b/src/audio/tensorflow/README.md @@ -0,0 +1,22 @@ +# TensorFlow Lite Micro (TFLM) Architecture + +This directory acts as the bridge for running ML models. + +## Overview + +Integrates TensorFlow Lite for Microcontrollers into the SOF audio pipeline. Evaluates pre-trained neural network topologies inline with the audio stream for tasks like wake-word, noise cancellation, or sound classification. + +## Architecture Diagram + +```mermaid +graph LR + Feat[Audio Features] --> TFLM[TFLM Inference Engine] + SubGraph[FlatBuffer Model] -.-> TFLM + TFLM --> Out[Inference Labels/Scores] +``` + +## Configuration and Scripts + +- **Kconfig**: Enforces requirements for C++17 support and core framework staging logic (`COMP_TENSORFLOW`). +- **CMakeLists.txt**: An intricate build specification linking the Tensilica neural network library block computations (`nn_hifi_lib`) and the TensorFlow Lite micro core engine (`tflm_lib`). Also hooks the `tflm-classify.c` SOF adapter via compiler flags explicitly enforcing memory, precision, and XTENSA optimizations. +- **tflmcly.toml**: Topology definition for the specific TFLM Classifier implementation binding the engine against the UUID `UUIDREG_STR_TFLMCLY`. diff --git a/src/audio/tensorflow/llext-wrap.c b/src/audio/tensorflow/llext-wrap.c new file mode 100644 index 000000000000..7d43dbe165ef --- /dev/null +++ b/src/audio/tensorflow/llext-wrap.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. + +#include <stdint.h> +#include <errno.h> +#include <assert.h> +#include <rtos/symbol.h> + +/* + * Stubs that are needed for linkage of some applications or libraries + * that come from porting userspace code. Anyone porting should + * make sure that any code does not depend on working copies of these + * reentrant functions. We will fail for any caller. + */ + +struct stat; +struct _reent; + +size_t _read_r(struct _reent *ptr, int fd, char *buf, size_t cnt) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +size_t _write_r(struct _reent *ptr, int fd, char *buf, size_t cnt) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) +{ + errno = -ENOTSUP; + return NULL; +} + +int _lseek_r(struct _reent *ptr, int fd, int pos, int whence) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _kill_r(struct _reent *ptr, int pid, int sig) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _getpid_r(struct _reent *ptr) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +int _close_r(struct _reent *ptr, int fd) +{ + errno = -ENOTSUP; + return -ENOTSUP; +} + +/* TFLM needs exit if build as a llext module only atm */ +#if CONFIG_COMP_TENSORFLOW == m +void _exit(int status) +{ + assert(0); + while (1) { + /* spin forever */ + } + /* NOTREACHED */ +} +#endif diff --git a/src/audio/tensorflow/llext/CMakeLists.txt b/src/audio/tensorflow/llext/CMakeLists.txt new file mode 100644 index 000000000000..22bfc22da748 --- /dev/null +++ b/src/audio/tensorflow/llext/CMakeLists.txt @@ -0,0 +1,465 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +# TODO: detect Hifi4/5 for NN lib kernels +set(NN_HIFI_PATH ${sof_top_dir}/../nnlib-hifi4/xa_nnlib) + +# paths for dependencies +set(TFLM_PATH ${sof_top_dir}/../tflite-micro) +set(FLATBUFFERS_PATH ${sof_top_dir}/../flatbuffers) +set(GEMMLOWP_PATH ${sof_top_dir}/../gemmlowp) +set(RUY_PATH ${sof_top_dir}/../ruy) + +add_library(nn_hifi_lib STATIC + ${NN_HIFI_PATH}/algo/common/src/xa_nnlib_common_api.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_pad_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_stride_slice_int16.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_batch_to_space_nd_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_transpose_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_depth_to_space_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_pad_16.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_stride_slice_int32.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_space_to_batch_nd_8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_pad_32.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_stride_slice_int8.c + ${NN_HIFI_PATH}/algo/kernels/reorg/hifi4/xa_nn_space_to_depth_8.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_32_32.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_f32_f32.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_sym16_sym16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_softmax_asym8_asym8.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_32_16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_16_16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_8_8.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_asym16_asym16.c + ${NN_HIFI_PATH}/algo/kernels/activations/hifi4/xa_nn_activations_32_8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_16x16_16_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_group_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_asym8xasym8_asym8_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x8_8_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_8x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_16x16_16_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_f32_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x16_16_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_sym8sxsym16s_sym16s_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_8x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_f32_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_asym8xasym8_asym8_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_transpose_conv_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_8x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_8x8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_sym8sxasym8s_asym8s_circ.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_pointwise_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_circ_buf.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x16_16_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_16x16.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_matXvec_8x8_8_circ_nb.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_std_sym4sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv1d_std_f32.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/cnn/hifi4/xa_nn_conv2d_depthwise_8x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_f32.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym8xasym8_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_8x8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_8x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym4sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_f32_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_f32.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_16x16_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_sym8sxsym16s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_asym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_16x8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matmul_16x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x16_batch.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_16x16.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_asym8xasym8.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_sym8sxasym8s.c + ${NN_HIFI_PATH}/algo/kernels/matXvec/hifi4/xa_nn_matXvec_8x8_batch.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_f32.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_asym8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_f32_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_16_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_16.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_16_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_asym8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_inv_256_tbl.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_16.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_f32_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_asym8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_f32.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_maxpool_asym8.c + ${NN_HIFI_PATH}/algo/kernels/pool/hifi4/xa_nn_avgpool_8_nhwc.c + ${NN_HIFI_PATH}/algo/kernels/norm/hifi4/xa_nn_l2_norm_asym8s.c + ${NN_HIFI_PATH}/algo/kernels/norm/hifi4/xa_nn_l2_norm_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sqrt_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_16x16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_add_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_lstm_utils.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_dot_prod_16x16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sub_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_round_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_acc_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_cosine_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_reduce_asym8s_asym8s.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_memset_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_floor_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_squared_diff_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_add_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_reduce_asym16s_asym16s.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_minmax_8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_logn_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_div_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sub_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_compare_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_logical_bool.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_broadcast_8_8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_quantize.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_neg_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_add_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_vec_interpolation_q15.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_square_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sine_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_abs_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_memmove.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_mul_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_squared_diff_quant16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_memmove_16.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_sub_quant8.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_ceil_f32.c + ${NN_HIFI_PATH}/algo/kernels/basic/hifi4/xa_nn_elm_rsqrt_f32.c + ${NN_HIFI_PATH}/algo/kernels/fc/hifi4/xa_nn_fully_connected.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_tanh32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/scl_sigmoidf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/inv2pif_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/nanf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/pow2f_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_sigmoidf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_reluf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/expf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_tanhf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_sigmoid32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/lognf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/sinf_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_cosinef_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_sinef_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_softmaxf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/scl_tanhf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_softmax32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_lognf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/sqrt2f_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/inff_tbl.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_alognf_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/vec_relu32x32_hifi4.c + ${NN_HIFI_PATH}/algo/ndsp/hifi4/src/tanhf_tbl.c +) + +target_include_directories(nn_hifi_lib PRIVATE + ${NN_HIFI_PATH}/include + ${NN_HIFI_PATH}/algo/common/include/ + ${NN_HIFI_PATH}/include/nnlib/ + ${NN_HIFI_PATH}/algo/ndsp/hifi4/include +) + +# TODO: Need to detect and add mul16/32 options. +#ifeq "$(has_mul16)" "0" +#CFLAGS += -mno-mul16 +#endif +#ifeq "$(has_mul32)" "0" +#CFLAGS += -mno-mul32 -mno-div32 +#endif +target_compile_options(nn_hifi_lib PRIVATE + -fsigned-char + -fno-exceptions + -mlongcalls + -INLINE:requested + -mcoproc + -fno-zero-initialized-in-bss + -mtext-section-literals + -Wsign-compare + -m32 + -DMODEL_INT16 + -DNNLIB_V2 + -Dhifi4 + -DTFLITE_SINGLE_ROUNDING=1 +) + +# TODO: complete sources have been added here from userspace build but +# not all are needed so this is a list of "needed" sources to build +# a memory and performance optimized TFLM for SOF. +# All sources have been left in for completeness now, but will be removed +# when support is mature. +add_library(tflm_lib STATIC + ${TFLM_PATH}/tensorflow/compiler/mlir/lite/core/api/error_reporter.cc + ${TFLM_PATH}/tensorflow/compiler/mlir/lite/schema/schema_utils.cc + ${TFLM_PATH}/tensorflow/lite/core/c/common.cc + ${TFLM_PATH}/tensorflow/lite/core/api/flatbuffer_conversions.cc + ${TFLM_PATH}/tensorflow/lite/core/api/tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/common.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/runtime_shape.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/quantization_util.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/tensor_ctypes.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/portable_tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/reference/comparisons.cc + ${TFLM_PATH}/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc + ${TFLM_PATH}/tensorflow/lite/kernels/kernel_util.cc + # Stock micro kernels - not needed atm + #${TFLM_PATH}/tensorflow/lite/micro/kernels/activations_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/activations.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/add_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/add_n.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/arg_min_max.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/assign_variable.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/batch_matmul.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/batch_to_space_nd.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/broadcast_args.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/broadcast_to.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/call_once.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/cast.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/ceil.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/circular_buffer_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/circular_buffer.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/comparisons.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/concatenation.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/conv_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/cumsum.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/depth_to_space.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/depthwise_conv_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/dequantize_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/detection_postprocess.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/div.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/elementwise.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/elu.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/embedding_lookup.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/ethosu.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/expand_dims.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/exp.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/fill.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/floor_div.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/floor_mod.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/floor.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/fully_connected_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/gather_nd.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/gather.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/hard_swish_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/hard_swish.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/if.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/kernel_runner.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/kernel_util.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/l2norm.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/l2_pool_2d.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/leaky_relu_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/logical_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/logical.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/logistic_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/log_softmax.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/lstm_eval_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/maximum_minimum.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/micro_tensor_utils.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/mirror_pad.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/mul_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/mul.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/neg.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/pack.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/pooling_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/prelu_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/prelu.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/quantize_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/read_variable.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/reduce_common.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/reshape_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/resize_bilinear.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/round.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/select.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/shape.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/slice.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/softmax_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/space_to_batch_nd.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/space_to_depth.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/split.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/split_v.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/squared_difference.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/squeeze.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/strided_slice_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/sub_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/svdf_common.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/tanh.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/transpose.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/unpack.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/var_handle.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/while.cc + #${TFLM_PATH}/tensorflow/lite/micro/kernels/zeros_like.cc + # xtensa kernels + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/sub.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_hifi.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pooling_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/softmax_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/unidirectional_sequence_lstm.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/transpose_conv.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected_common_xtensa.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/lstm_eval_hifi.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/add_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/depthwise_conv.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reshape.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/softmax.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/depthwise_conv_hifi.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_int16_reference.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_int8_reference.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected_int8.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pad_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_int8_int16.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/softmax_int8_int16.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/logistic.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reduce.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/lstm_eval.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reshape_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pad.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/reduce_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/dequantize.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/add.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pooling_int8.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/depthwise_conv_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/strided_slice.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_common_xtensa.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/svdf.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/fully_connected.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/leaky_relu.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/quantize.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/pooling.cc + ${TFLM_PATH}/tensorflow/lite/micro/kernels/xtensa/conv_vision.cc + ${TFLM_PATH}/tensorflow/lite/micro/mock_micro_graph.cc + ${TFLM_PATH}/tensorflow/lite/micro/flatbuffer_utils.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_interpreter_graph.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_resource_variable.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_interpreter_context.cc + ${TFLM_PATH}/tensorflow/lite/micro/fake_micro_context.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/persistent_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/recording_single_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/non_persistent_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/arena_allocator/single_arena_buffer_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/tflite_bridge/flatbuffer_conversions_bridge.cc + ${TFLM_PATH}/tensorflow/lite/micro/tflite_bridge/micro_error_reporter.cc + ${TFLM_PATH}/tensorflow/lite/micro/system_setup.cc + #${TFLM_PATH}/tensorflow/lite/micro/span_test.cc + ${TFLM_PATH}/tensorflow/lite/micro/test_helper_custom_ops.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_context.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_log.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_profiler.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_time.cc + #${TFLM_PATH}/tensorflow/lite/micro/static_vector_test.cc + ${TFLM_PATH}/tensorflow/lite/micro/debug_log.cc + ${TFLM_PATH}/tensorflow/lite/micro/test_helpers.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_op_resolver.cc + ${TFLM_PATH}/tensorflow/lite/micro/recording_micro_allocator.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_helpers.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_allocation_info.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_planner/greedy_memory_planner.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_planner/non_persistent_buffer_planner_shim.cc + ${TFLM_PATH}/tensorflow/lite/micro/memory_planner/linear_memory_planner.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_utils.cc + ${TFLM_PATH}/tensorflow/lite/micro/micro_interpreter.cc + ../micro_speech_quantized_model_data.cc + ../speech.cc +) + +target_include_directories(tflm_lib PRIVATE + ${TFLM_PATH} + ${FLATBUFFERS_PATH}/include + ${GEMMLOWP_PATH} + ${RUY_PATH} + ${NN_HIFI_PATH} + ${NN_HIFI_PATH}/include + ${sof_top_dir}/posix/include +) + +# TODO: Need to detect and add mul16/32 options. +#ifeq "$(has_mul16)" "0" +#CFLAGS += -mno-mul16 +#endif +#ifeq "$(has_mul32)" "0" +#CFLAGS += -mno-mul32 -mno-div32 +#endif +target_compile_options(tflm_lib PRIVATE + -std=c++17 + -stdlib=libc++ + -fno-rtti + -fno-exceptions + -fno-threadsafe-statics + -Wnon-virtual-dtor + -fno-unwind-tables + -fmessage-length=0 + -DTF_LITE_STATIC_MEMORY + -DTF_LITE_DISABLE_X86_NEON + -Wsign-compare + -Wdouble-promotion + -Wunused-variable + -Wswitch + -Wvla + -Wall + -Wextra + -Wmissing-field-initializers + -Wstrict-aliasing + -Wno-unused-parameter + -DXTENSA + -DKERNELS_OPTIMIZED_FOR_SPEED + -DTF_LITE_MCU_DEBUG_LOG + -DTF_LITE_USE_CTIME + --xtensa-core=ace10_LX7HiFi4_2022_10 + -mcoproc + -DHIFI4 + -mlongcalls + -DNNLIB_V2 + -Wno-shadow +) + +sof_llext_build("tflm" + SOURCES ../tflm-classify.c ../llext-wrap.c + + INCLUDES + ${TFLM_PATH} + + # TFLM is a C++ userspace application so hence we need to link + # userspace C++, C, maths and C runtime for llext module usage. + LIBS tflm_lib nn_hifi_lib c++ m c gcc hal + LIBS_PATH . +) + diff --git a/src/audio/tensorflow/llext/llext.toml.h b/src/audio/tensorflow/llext/llext.toml.h new file mode 100644 index 000000000000..521a0e5acf64 --- /dev/null +++ b/src/audio/tensorflow/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../tflmcly.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/tensorflow/micro_speech_quantized_model_data.cc b/src/audio/tensorflow/micro_speech_quantized_model_data.cc new file mode 100644 index 000000000000..ce9cc5086804 --- /dev/null +++ b/src/audio/tensorflow/micro_speech_quantized_model_data.cc @@ -0,0 +1,5 @@ +#include <cstdint> + +#include "micro_speech_quantized_model_data.h" + +alignas(16) const unsigned char g_micro_speech_quantized_model_data[] = {0x20,0x0,0x0,0x0,0x54,0x46,0x4c,0x33,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x0,0x1c,0x0,0x4,0x0,0x8,0x0,0xc,0x0,0x10,0x0,0x14,0x0,0x0,0x0,0x18,0x0,0x12,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0xec,0x48,0x0,0x0,0x8c,0x42,0x0,0x0,0x74,0x42,0x0,0x0,0x3c,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x8,0x0,0xc,0x0,0x4,0x0,0x8,0x0,0x8,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0xb,0x0,0x0,0x0,0x13,0x0,0x0,0x0,0x6d,0x69,0x6e,0x5f,0x72,0x75,0x6e,0x74,0x69,0x6d,0x65,0x5f,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x0,0xc,0x0,0x0,0x0,0x28,0x42,0x0,0x0,0xfc,0x41,0x0,0x0,0x68,0x3,0x0,0x0,0x34,0x3,0x0,0x0,0x28,0x3,0x0,0x0,0x14,0x3,0x0,0x0,0xe8,0x2,0x0,0x0,0xdc,0x2,0x0,0x0,0x40,0x0,0x0,0x0,0x34,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xbe,0xbc,0xff,0xff,0x4,0x0,0x0,0x0,0x5,0x0,0x0,0x0,0x31,0x2e,0x35,0x2e,0x30,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40,0xba,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x50,0xba,0xff,0xff,0x0,0x0,0x0,0x0,0xee,0xbc,0xff,0xff,0x4,0x0,0x0,0x0,0x80,0x2,0x0,0x0,0xfa,0xee,0x28,0xc4,0xee,0xfe,0xcf,0xf,0x1e,0xf7,0x1f,0x6,0xd,0xed,0xe9,0x83,0x5c,0xc9,0x18,0xe3,0xf9,0x14,0x28,0x2a,0x9,0xf2,0x18,0x34,0x62,0xea,0xef,0xd6,0x36,0xb7,0x1e,0xf7,0x3b,0x22,0x28,0x39,0xc2,0x9d,0xf1,0x7,0x5e,0xb,0x1e,0x2c,0x7,0xdd,0xfd,0xc3,0xd8,0x4a,0xf3,0x28,0xa7,0x16,0xd5,0xf1,0xc3,0x5,0xfd,0x27,0xcc,0xba,0x1e,0xcb,0xd7,0x3d,0xd4,0x29,0x0,0xfd,0x28,0x44,0xfb,0xf2,0xf3,0xb6,0x4f,0xcf,0x9,0xf0,0xfa,0x45,0x41,0x49,0x5,0xc5,0x17,0x5d,0x64,0x0,0xf8,0xee,0x48,0x17,0xf4,0xe9,0x2e,0x4b,0x2e,0x3f,0xdf,0xee,0xe4,0x8,0x38,0xf1,0x16,0x13,0x2f,0x2a,0xed,0xc2,0xbf,0x36,0xf4,0x2,0xcf,0xaa,0xd2,0xfa,0xac,0x13,0xf6,0xe8,0xb5,0x68,0x12,0xb6,0xce,0xe,0xdf,0x58,0xe4,0x49,0x14,0x15,0x3,0xed,0xfa,0xd4,0x40,0xa7,0xf6,0xca,0xfb,0x0,0x4d,0x5e,0xe4,0x55,0x1d,0x30,0x45,0xe2,0xfc,0x1,0x48,0x81,0xe9,0xf1,0x1e,0xfc,0x21,0x32,0xed,0x4b,0xed,0xfa,0x2f,0xd2,0xfa,0xfb,0x4d,0xa7,0xed,0xc7,0x92,0xdf,0xe6,0xdb,0xf8,0x1f,0xd9,0xfa,0x91,0xf5,0xe5,0xc5,0x8c,0x17,0xf,0xb9,0xd2,0xc7,0xfe,0x68,0xd3,0x51,0x2e,0x49,0x1f,0xbd,0x1,0xeb,0x31,0x17,0xf0,0xef,0xff,0xb8,0x5d,0x62,0x2,0xf,0x1f,0x78,0x6a,0xb0,0xf9,0xfe,0x4f,0xcc,0xd3,0xff,0xa,0x96,0x1e,0x2c,0xed,0xbc,0xf4,0xb,0x42,0xc8,0xf1,0xea,0x6e,0x58,0xec,0xc4,0x99,0xae,0xdc,0xd7,0x12,0x87,0xd8,0x6,0xa2,0xc2,0xe6,0xa2,0x81,0x24,0xe9,0xac,0xce,0xb6,0x15,0x6b,0xba,0x0,0x19,0x58,0x29,0xb6,0xfe,0x1,0x25,0x96,0xd2,0xec,0xe,0x9c,0x60,0x5f,0xe9,0xf4,0xf5,0x69,0x6b,0xb5,0xe1,0xf6,0x5e,0xb7,0xb1,0xe5,0x11,0x9b,0x18,0x10,0xe3,0xe1,0xe0,0xd,0x4f,0xa5,0xde,0xe5,0x6f,0xe2,0xfb,0x99,0x82,0xa5,0xc9,0xb6,0x1f,0x46,0xf3,0x4,0xc6,0xca,0xd6,0x97,0x90,0x1d,0xc0,0x95,0xf0,0x19,0x30,0x77,0xc2,0x3c,0xfa,0x24,0x2,0x4d,0x6,0x7,0x15,0x2,0xb0,0xe7,0x27,0x22,0x67,0x4d,0xf1,0xc2,0xf4,0x64,0x38,0x40,0xdf,0xf6,0x3a,0x43,0xb8,0xe1,0xd,0x15,0x11,0xfe,0xf5,0xec,0xf9,0xe5,0x22,0x36,0xe4,0xfd,0x6d,0xbf,0xd,0x8e,0xb7,0x15,0xbf,0x9f,0x16,0xad,0xa,0x2,0x8e,0x14,0xda,0x9b,0x8e,0xc3,0xa6,0xca,0xf5,0x7f,0x51,0x56,0xc1,0xb3,0xd9,0x35,0xf8,0x7f,0x4,0xa,0x3,0x3f,0xbe,0xee,0x19,0x68,0x78,0x50,0xf9,0xa7,0xf7,0x7f,0x1d,0x76,0xdb,0xe8,0x33,0xb9,0xd7,0xe7,0xe8,0x69,0x15,0xf7,0xf5,0xb2,0xfe,0xe8,0xf3,0x5b,0xe2,0x6,0x6e,0x9,0x36,0xb7,0xcc,0x38,0xbf,0x8a,0x28,0x14,0x2e,0x18,0xa7,0x26,0xcb,0xb2,0x95,0x37,0xac,0xcd,0xd7,0x51,0x67,0x44,0xcd,0x31,0xde,0x4,0xe9,0x6a,0x0,0x13,0xa,0xc,0xdd,0x16,0xe0,0x24,0x7e,0x49,0xf1,0xb5,0x4,0x52,0x1,0x50,0xdd,0xf5,0x26,0xc9,0xf4,0xf8,0xd6,0x31,0x1b,0xd0,0xef,0x3,0xa,0xc0,0xd4,0x4f,0xe2,0xfd,0x72,0xf4,0x5a,0xc9,0xd7,0x31,0xc0,0x8e,0x17,0x5e,0x57,0x0,0xb4,0x3a,0xc8,0xd2,0x92,0x32,0xcb,0xd8,0xc3,0xa6,0x63,0x26,0xcf,0xbc,0xe8,0x57,0x9b,0xe9,0xf7,0x1c,0xea,0x12,0xf1,0xf7,0xdb,0xb9,0x7f,0x16,0xf6,0xe0,0x8,0x70,0xa2,0xed,0xcc,0xf1,0x1e,0x10,0x4,0xf7,0xa9,0xb7,0x34,0xaa,0xa,0xdb,0x2a,0xa6,0xb6,0x10,0xea,0xf8,0x5e,0x6,0x72,0xdd,0xd0,0xb9,0xd6,0xa0,0x10,0x9f,0x5a,0x17,0xb1,0xe7,0xc0,0x1,0x9d,0x1,0xe0,0xe0,0xaf,0x9c,0x46,0xd8,0xaf,0xe8,0xce,0x2,0x8a,0xbb,0xe4,0xf6,0xf3,0x36,0x7,0xca,0xcb,0x87,0x6e,0xcc,0xd6,0x9e,0xa,0x2a,0x81,0xd7,0xcf,0xc0,0x4,0xeb,0x24,0xcc,0xc9,0x95,0x33,0x81,0xf7,0xad,0x1c,0x9c,0xa4,0xd6,0xf9,0xe6,0x3d,0x84,0x7f,0xcc,0xd4,0xb0,0xf4,0xa2,0xe9,0x3c,0x36,0xee,0xd5,0xcf,0xcd,0x2d,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0xbc,0xff,0xff,0x0,0x0,0x0,0x0,0x8e,0xbf,0xff,0xff,0x4,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x31,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xbd,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0xbd,0xff,0xff,0x0,0x0,0x0,0x0,0xce,0xbf,0xff,0xff,0x4,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x8a,0xfe,0xff,0xff,0xa9,0x0,0x0,0x0,0xd0,0xff,0xff,0xff,0xd0,0x0,0x0,0x0,0x52,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x4f,0xfb,0xff,0xff,0x4a,0xfd,0xff,0xff,0x0,0x0,0x0,0x0,0xfe,0xbf,0xff,0xff,0x4,0x0,0x0,0x0,0x80,0x3e,0x0,0x0,0xff,0xf9,0xfd,0xa,0x7,0x8,0x7,0x3,0x7,0xf2,0xd1,0x9,0xf0,0xe9,0x28,0x9,0xdf,0x5,0xfa,0xf0,0xe8,0xe3,0x13,0xe,0x8,0xef,0xd3,0xee,0xf,0xe8,0xeb,0x14,0xf7,0xed,0xfd,0x1f,0xe8,0xd5,0xeb,0xfc,0xe,0xf4,0xf7,0x7,0x5,0xea,0xf6,0x1f,0xf8,0xdb,0xdc,0xb,0x3,0xdd,0xd8,0xf3,0xf,0x19,0xe1,0x9,0xfc,0xe4,0x2,0x4,0xf1,0x4,0xeb,0xf3,0x1e,0x6,0xfd,0x11,0xfc,0xfa,0xf6,0x1f,0xf,0x2,0xf5,0xf7,0xff,0x24,0xdf,0xf7,0xf8,0xf3,0xf6,0xe9,0xef,0x3,0xdd,0xf2,0x28,0xe1,0xf2,0x22,0xf4,0x9,0xf7,0xf9,0xf0,0xd4,0xf9,0xee,0xff,0x14,0xda,0xf3,0x11,0xe2,0xf6,0xc,0xf2,0xeb,0xf8,0xe8,0xe3,0x8,0x2,0x17,0xf4,0xb,0xc,0x27,0xe6,0x2,0x3,0xf9,0x14,0x18,0xf6,0xeb,0x1f,0xc,0xf1,0xee,0xfc,0x8,0xf0,0xfe,0xfd,0xee,0x17,0xfd,0x1c,0xef,0xfd,0xde,0x4,0x5,0xf0,0x31,0xfa,0xb,0xdc,0xd,0xed,0xf5,0xfa,0xf4,0x8,0xc,0xd7,0x1e,0x15,0x3,0xf5,0x2,0xf4,0xfb,0xed,0x1,0xfe,0xd6,0x1f,0xfd,0xfd,0xe,0xfa,0x6,0xf1,0xf9,0xe2,0x16,0xe9,0xf1,0x3,0xd,0xd,0xdf,0xf9,0x1a,0xe,0xf6,0xfc,0xa,0x19,0xe2,0xe0,0x9,0x15,0xf0,0xf1,0x6,0xf1,0xe1,0xef,0x1a,0x8,0xe8,0xfd,0x12,0x14,0x6,0xf1,0xfc,0xea,0xfb,0xf7,0xea,0x1d,0x9,0xfa,0xf6,0x8,0xf2,0xe7,0xf8,0xfc,0x16,0xf5,0xe,0x8,0xf9,0xa,0x3,0x26,0xd8,0x2,0xf5,0xf6,0xf6,0xef,0x1f,0xe4,0xe2,0xfb,0x2,0x1b,0xe6,0xde,0x0,0xf2,0xed,0xfb,0x18,0xe4,0x16,0x1a,0x1d,0xf1,0xf6,0xea,0x16,0x5,0xde,0xfb,0x18,0xf5,0xe4,0xfe,0xe2,0x1b,0x1c,0xc,0xe8,0x2,0xee,0xfb,0x7,0x24,0xf2,0xe9,0xfa,0xd,0x5,0xf1,0x3,0xfe,0xf6,0x19,0x6,0xff,0xf9,0x4,0xfb,0x15,0xef,0xf1,0xf8,0xe9,0xe1,0x10,0x4,0xfc,0xe6,0x1f,0xed,0xb,0xef,0x0,0x1e,0xe6,0x16,0xf3,0x9,0xfd,0x8,0x8,0x6,0x6,0x23,0xdf,0xfc,0x8,0xf4,0xea,0xc,0xf2,0xe6,0x18,0xf5,0x2,0xf9,0x50,0x9,0x1,0xda,0xb,0x5,0x12,0x18,0xef,0x4,0xe,0xd9,0xff,0xdc,0xf6,0x16,0xf9,0xf4,0xec,0xff,0xea,0xe6,0xfa,0xa,0xed,0xef,0x2,0xf0,0x25,0x21,0xf1,0x26,0xf5,0xed,0x9,0xea,0xea,0x24,0xfa,0x11,0xfc,0xdf,0xf3,0xa,0x28,0xc,0x19,0xff,0xf5,0xd6,0xe,0xe2,0x2a,0x6,0xfa,0x3,0xf9,0xe6,0xef,0x23,0xf9,0xfa,0xe6,0xfe,0xfc,0x3,0x6,0x1a,0xf9,0x8,0xe0,0xe5,0xff,0x5,0x1,0xe7,0x12,0x2,0x1d,0x5,0x3,0x5,0xb,0xee,0xed,0xfc,0xf,0xf3,0x2,0xe0,0x15,0xdf,0x2,0xed,0x10,0x26,0xef,0xd,0x6,0xee,0xef,0xf6,0xeb,0x11,0x9,0xf4,0xf7,0x6,0xf,0x1,0x2a,0xb,0x1,0xdd,0xfc,0xf4,0xf1,0x17,0x3,0x4,0x7,0xfc,0x22,0xfc,0xde,0xfe,0xb,0x3,0xf3,0xfb,0xc,0x25,0x4,0x19,0x4,0x3,0x1,0xfa,0xfb,0xf7,0xf6,0xe,0x15,0xe,0x9,0xff,0x6,0xfa,0xfb,0x1e,0xfb,0x5,0x22,0xf9,0xfe,0xf7,0x1d,0xed,0xdf,0x18,0x9,0xeb,0xef,0x4,0x12,0xea,0xdf,0xfb,0xda,0xf6,0xdf,0x17,0xef,0xef,0xe1,0x1a,0xd9,0xe2,0xe2,0xfc,0x5,0x11,0xf6,0xee,0xe8,0xf2,0xe1,0x8,0x26,0x4,0xed,0x3,0xe0,0xfb,0xee,0xc,0xee,0xf6,0x4,0x2d,0xf2,0xd3,0xf4,0xe0,0xf8,0xc,0xfe,0x11,0xb,0xd7,0xfd,0x18,0x7,0xd,0x7,0x8,0xf4,0xc6,0xa,0xa,0x1f,0xc,0xf4,0x1d,0x2,0xb,0x9,0xe,0x21,0xff,0x17,0xb,0xd,0xf2,0xed,0xd7,0xa,0xf8,0x3,0x6,0xfa,0xe5,0xfd,0x3,0x14,0xf,0xe9,0x1a,0xf4,0xda,0x1,0xe6,0x9,0x6,0x11,0xd,0xfd,0xeb,0x16,0x23,0xfa,0x0,0xb,0x17,0xf7,0xda,0xd7,0x1b,0xfa,0x1,0x3,0x5,0xfe,0xd6,0x2,0xee,0xee,0x2,0xf3,0x6,0xed,0x3,0xec,0x1,0xf2,0xf,0x5,0x17,0xb,0xfb,0xf,0x5,0x3,0x13,0xff,0x6,0x2,0xf5,0xf4,0x18,0x2b,0xf0,0x0,0x17,0xfc,0xfd,0x5,0xb,0xe,0x14,0xe1,0x24,0x8,0x24,0xe6,0xeb,0x21,0x12,0xfb,0x12,0xe7,0xf4,0xe8,0xe,0x18,0xee,0xf5,0xf3,0xd9,0xf3,0xdb,0xec,0xc,0x1e,0xcf,0x14,0xdb,0xe3,0xdc,0x2,0xc,0xfb,0xdb,0x1b,0xd0,0xfe,0xf9,0xfe,0x2a,0xf5,0x0,0xb,0xcd,0xe0,0xe2,0xe,0x4,0xf8,0xda,0x1c,0xe5,0xf,0xe8,0xf4,0xf7,0x15,0x6,0xf8,0x2,0xf7,0xf,0xfb,0x17,0xf9,0xda,0x1,0xda,0xd1,0xf6,0x2,0xfd,0x16,0xf1,0xe4,0xfa,0x7,0xee,0xa,0xf3,0xfd,0xf2,0x23,0xf0,0xe1,0xa,0x1a,0x12,0x1f,0xef,0x27,0x9,0xf1,0xc,0x13,0x23,0xfd,0xf5,0x3,0xfe,0x9,0xfd,0x16,0xf8,0x7,0x8,0x25,0x8,0xf8,0xf6,0xa,0xf1,0xf5,0x7,0x9,0x5,0xcc,0xf8,0x8,0x13,0xf9,0x1d,0x11,0xf,0xdc,0xee,0xf3,0x27,0xf9,0xf9,0x22,0xfa,0xd,0xe2,0x13,0xfb,0x11,0x3,0x1e,0xff,0xfb,0xed,0xf1,0xe,0xb,0xf,0x0,0x6,0xe0,0x15,0xf3,0x13,0xfc,0x18,0xf9,0xff,0x9,0xfa,0x1f,0x12,0xe5,0xe2,0x6,0xf9,0xf4,0x7,0x15,0xb,0x4,0xdb,0xd,0xeb,0xf3,0xe6,0x6,0xe5,0xee,0xd8,0x22,0xd8,0x10,0xea,0xf9,0x1c,0xf7,0xd3,0x11,0xc3,0xf8,0xde,0x5,0x0,0xe6,0x7,0xfd,0xd3,0x3,0xea,0xe0,0x13,0x14,0xcf,0xeb,0xcd,0xd3,0xde,0xf5,0xf0,0xc,0xc,0xfa,0xeb,0xd3,0xfb,0xfd,0x8,0xf9,0xf4,0x10,0xfa,0xd3,0xf4,0x11,0x11,0xf8,0xef,0xf8,0xf8,0xf1,0xfc,0xe1,0xf7,0x12,0x4,0xf4,0xfb,0xed,0xef,0xc,0xfd,0x1c,0xfe,0xe,0xfd,0xe2,0xfe,0xa,0x2,0xfe,0xe6,0x1f,0xef,0xe5,0xe6,0xf8,0x16,0x27,0xe8,0x20,0x5,0xe3,0xf1,0xef,0xee,0xed,0xd,0x11,0x16,0xfb,0xf3,0xff,0x14,0x1,0xff,0x15,0x10,0x2,0xe5,0x28,0x29,0x13,0x13,0x16,0xe6,0x0,0xd2,0x26,0xfd,0x3,0x4,0x5,0x7,0x6,0xf1,0xe,0x5,0xd,0xe2,0xf,0x2,0xe1,0x7,0xf7,0x1c,0xfa,0x14,0x30,0xf7,0xee,0x0,0xfa,0x3d,0x6,0x1c,0x4,0x6,0x7,0x5,0x1a,0x10,0xf6,0xee,0xa,0xeb,0x4,0xeb,0xdf,0x1d,0x9,0xd5,0xe8,0xd6,0xf4,0xf0,0xf,0x1d,0xea,0xf2,0xf8,0xa6,0xb,0xdc,0x9,0x8,0x24,0xee,0x24,0xaa,0xe4,0xcb,0x15,0xef,0xe7,0xe9,0xc,0xcf,0x6,0xe3,0x12,0x11,0x0,0x7,0x14,0xd7,0xde,0xf6,0xf,0xb,0x4,0xfb,0xd,0xf8,0xd,0xf6,0x1b,0xf1,0x21,0xdd,0xfc,0xf4,0xe9,0xf8,0xe8,0xf7,0x6,0x3,0x1e,0xce,0xe1,0xea,0xf6,0x5,0xf9,0x16,0x15,0x4,0xe0,0x14,0xf7,0x1e,0x1c,0xa,0x27,0xef,0xf3,0xf,0xf3,0xee,0x4,0xf8,0xf1,0x7,0xe3,0x5,0xb,0x0,0x1c,0x15,0x27,0x7,0xf7,0xfa,0xb,0xfa,0xfa,0x17,0x13,0xe1,0xf5,0xfb,0xc,0x21,0x2f,0xd7,0xfb,0xf5,0xfd,0xd3,0xf4,0x7,0xe,0xfd,0xb,0xfc,0xfa,0xf5,0xe,0x2,0xfa,0xfa,0x19,0xfd,0xfa,0xfc,0x13,0x24,0xc,0xe4,0x31,0xf8,0x12,0xf4,0x4,0x18,0x29,0x27,0x19,0xfc,0x8,0x11,0xe3,0x7,0xfe,0x26,0x40,0x5,0x2,0x4,0x2,0xf,0xee,0xf4,0x27,0xea,0xf4,0xf5,0x11,0x26,0xb,0xe7,0x5,0xd2,0xf6,0xea,0xfa,0xb,0xf9,0xfa,0x16,0xba,0x0,0xfb,0xd,0xb,0xf9,0xe6,0xf6,0xc5,0xf8,0xf6,0x1,0xf,0xed,0xed,0x13,0xcd,0xd,0xda,0x6,0x17,0xee,0x7,0x1d,0xb8,0xfa,0xe2,0xea,0xf2,0xee,0x4,0x0,0xdc,0xd0,0xfb,0xf5,0xec,0xfe,0xf1,0xd,0xf0,0xdb,0xf9,0xd,0x3,0x3,0xe,0xa,0xda,0xd6,0x1,0xf2,0x6,0x14,0x1c,0x1f,0xe8,0xe8,0xe,0xfd,0xc,0xf5,0xf3,0x3d,0xf3,0x5,0x10,0xfa,0x1b,0x18,0x8,0x36,0x9,0xf1,0xeb,0xf9,0x22,0x1,0xf3,0xf7,0xff,0xf0,0xc,0xe9,0x1,0x29,0x21,0x15,0x3,0xee,0xe9,0x1a,0xf7,0x15,0x6,0x25,0xfa,0xf0,0xe4,0xf1,0x1f,0x1,0xdc,0x2d,0xce,0xe9,0xea,0xb,0x6,0x2c,0xa,0x30,0xe7,0x9,0xf4,0xf0,0x10,0x29,0xf9,0x3d,0xe7,0xdc,0xe4,0xf7,0x3b,0x27,0x23,0x3a,0xa,0x6,0xe,0xfd,0x2c,0x7,0x2b,0x1c,0xfa,0x0,0xf9,0x11,0xea,0x14,0xeb,0xfc,0x18,0x3,0xf1,0x16,0x12,0x4,0xcf,0x12,0xdd,0xe4,0xe,0xf0,0x9,0xe8,0xf3,0xfb,0xa8,0xf9,0xee,0xfb,0x1e,0x1d,0xfd,0x5,0xab,0xe5,0xff,0x1,0xfe,0x4,0xf9,0x2,0xb9,0xdc,0xdf,0x5,0xf1,0xef,0xf1,0x1e,0xc7,0xee,0xf7,0x1e,0x0,0x0,0xf8,0x10,0xec,0xe8,0x4,0xf,0xf6,0xff,0x4,0x9,0xe0,0xa,0xe,0xe4,0xf0,0xf1,0x16,0x2b,0xd3,0xe1,0xa,0xef,0xf9,0xfe,0xb,0x22,0xf5,0x1,0xa,0xf8,0x2,0x0,0x17,0x19,0xf3,0x5,0x21,0xfa,0xee,0xee,0x12,0xf2,0xfa,0xf5,0x5,0x12,0xee,0xe4,0x28,0xfa,0xf1,0x3,0x15,0x16,0x18,0xfd,0xf,0x21,0x4,0xf4,0xe5,0xc,0x6,0x13,0xde,0x36,0xe8,0xfb,0xe7,0xfd,0xf6,0x12,0xe,0x1d,0xea,0xf8,0xd4,0xe8,0x19,0x7,0xe5,0x1c,0xf7,0xc,0xef,0x5,0xf,0x9,0xdd,0x1a,0xea,0xd7,0xf9,0xf9,0x12,0x17,0x2e,0x10,0x8,0xfe,0x14,0xf5,0x1d,0xfa,0x6,0x33,0xed,0xfe,0xf7,0x11,0xf0,0x15,0xe2,0x24,0xf6,0xa,0xe2,0xfc,0x23,0x12,0xdd,0x11,0xfd,0xe5,0x8,0xff,0x15,0xf6,0xf1,0x1b,0xae,0xfe,0xe6,0x15,0x2c,0x2d,0x15,0x15,0xc5,0xf8,0xea,0xe7,0x7,0x4,0xfe,0x28,0xa1,0xf2,0xe1,0xf9,0xf8,0xff,0xf4,0x22,0xb4,0xdb,0x3,0x20,0xe6,0xf3,0xe,0x19,0xe3,0xa,0xfa,0xee,0xf3,0xe5,0xd8,0xf9,0xf1,0xde,0x6,0x5,0xf2,0xf5,0xe7,0x16,0xd8,0xfe,0x7,0xea,0xee,0xe,0xfa,0xff,0xdb,0xe7,0x3,0xed,0x1,0xfd,0x9,0x1a,0xfa,0xe6,0x5,0x10,0xe9,0x1,0x1f,0x13,0xf7,0xf6,0xfb,0x13,0xff,0xdb,0xed,0xfe,0xa,0x10,0x9,0x29,0xf5,0x4,0xf5,0x26,0xd,0xc,0xf9,0x16,0xfa,0x2,0xf4,0x2e,0xde,0xf5,0xe1,0x1d,0xfb,0x2,0xb,0x23,0x7,0xea,0xd9,0xa,0xf3,0xa,0xf,0x1e,0xe7,0xf1,0xd7,0xb,0xf6,0xff,0xd,0x24,0xcc,0xa,0xee,0xda,0x14,0x12,0x11,0x29,0xf4,0x1a,0xef,0xb,0xfa,0xec,0xc,0x1b,0xf4,0xff,0xf5,0xef,0xf,0x10,0xd4,0x4,0xf9,0xf8,0xec,0xf9,0x21,0x5,0xd3,0x27,0xf3,0x17,0xff,0xf6,0x15,0xf9,0xed,0xa,0xac,0x2,0xfd,0xfb,0x4,0x29,0x6,0x3,0xb8,0xe6,0xd5,0x17,0x9,0x1b,0xf6,0x1b,0xab,0xdc,0xdf,0xfd,0x6,0x9,0x9,0x37,0xbb,0xed,0x19,0xd7,0xe2,0xdd,0x5,0x1,0xec,0xfb,0xe4,0xe,0xeb,0xf0,0x3,0x17,0x4,0xeb,0x9,0xee,0xeb,0xe7,0xc,0x16,0xcb,0xe,0x17,0xd8,0xe1,0xf8,0x2b,0x19,0xde,0xeb,0x10,0xf2,0xff,0xf8,0xee,0xe,0xe7,0xf0,0x15,0x8,0xf8,0xdf,0x6,0xd,0xf9,0x14,0xfa,0xb,0x4,0xfd,0x15,0x23,0x20,0xff,0xfd,0x1d,0xc,0xf1,0xfe,0x15,0xa,0x2,0xed,0xfe,0xfb,0x4,0xfb,0x1e,0xdd,0x5,0xe0,0x16,0xf9,0xf6,0xfd,0x32,0xdc,0xf2,0xd3,0x8,0xf4,0xec,0x17,0x25,0xe2,0xf0,0xee,0xf1,0xd,0xfe,0x13,0x2d,0x1,0x11,0xd4,0xe4,0x7,0xfb,0x32,0x11,0x14,0x7,0xd7,0x2,0x10,0xeb,0x2b,0x1d,0x1,0xfc,0xf3,0xf0,0x13,0x1a,0xdb,0x20,0x0,0xf0,0xf0,0x5,0x16,0x3,0xd4,0xe3,0xc2,0xf0,0x6,0x2,0x1e,0xa,0xec,0x1f,0xab,0xea,0xfa,0xe3,0x20,0x22,0x3,0x1b,0xb3,0xe,0xe3,0xf3,0x1d,0x27,0xe3,0x10,0xa7,0xda,0xf3,0x0,0xa,0xa,0x4,0xfb,0xb2,0xf,0xc,0xf5,0x7,0xff,0x13,0x1e,0xdb,0xf6,0xf9,0xef,0xe8,0xe7,0xfb,0x18,0xeb,0xec,0x9,0xda,0xf1,0xf0,0xb,0x4,0xe1,0xfa,0x1c,0x25,0xee,0x1,0xb,0x29,0xd7,0xc,0x4,0xb,0xef,0xfd,0x1c,0xfc,0xf1,0xfb,0xb,0xf,0xdf,0xed,0x17,0x38,0xc,0xd7,0xff,0xfd,0x1,0xfc,0xfb,0xfb,0x18,0x1a,0x18,0xe3,0xf9,0xf4,0xfa,0x20,0x6,0x9,0x11,0x8,0x1d,0xf8,0xfa,0x1d,0xf5,0x1c,0xf5,0xfe,0x3,0x7,0xe4,0x33,0xc8,0xc,0xe1,0x13,0xff,0xe5,0x10,0x2c,0xd3,0xf0,0xed,0x4,0x7,0x1,0xf1,0x16,0xe0,0x13,0xfa,0x11,0x7,0xfa,0x19,0x16,0x1,0x0,0x7,0x26,0x0,0xec,0x1d,0x23,0x5,0xf4,0x7,0x17,0x2c,0x1d,0xee,0xf0,0xc,0x9,0xe3,0x1a,0x24,0xb,0xf3,0x1e,0xce,0xfe,0xfe,0x12,0x21,0x1a,0xf6,0x23,0xc3,0x3,0xf4,0x10,0x1a,0x2a,0xf4,0x8,0xbf,0xff,0x4,0xf4,0xb,0x1d,0x1a,0xf8,0xcc,0x0,0xf7,0x13,0xf4,0xfd,0xf4,0x19,0xbd,0xef,0xc,0xd,0x2,0xfc,0x12,0x13,0xe9,0xe7,0xf5,0xfa,0xfa,0xf6,0x1a,0x2e,0xce,0xd4,0x1,0x12,0xfd,0xfc,0x26,0x10,0xcc,0xe7,0xee,0x13,0xee,0xff,0xef,0xea,0x0,0xe,0x1a,0x17,0x4,0xc,0x4,0xc,0xe6,0xf3,0xf6,0xdb,0xdd,0x4,0xf4,0x22,0x11,0x16,0xf3,0x7,0xec,0xf8,0xf2,0x7,0x3,0x2,0xf5,0xa,0xf6,0x2,0x1d,0x1b,0x11,0x6,0xf8,0x6,0x2,0xea,0xf3,0x1d,0xce,0x0,0xed,0xf9,0xef,0xf6,0xec,0x22,0xc7,0xf0,0xed,0xdb,0xe0,0x2,0x11,0x7,0xe8,0xf0,0xd1,0xed,0xff,0xfd,0xc,0x2e,0xd4,0xed,0xec,0xe,0xf1,0x7,0x1,0xe,0xe,0xfe,0xda,0xb,0xa,0xa,0x1f,0x2e,0x13,0x7,0x0,0x7,0x14,0x21,0xe9,0xfc,0xf0,0x1e,0xd7,0xea,0x34,0x7,0xc6,0xc,0xd4,0xec,0xfd,0x6,0x24,0xa,0xf3,0x15,0xaf,0xff,0xe9,0xf1,0xd,0x3e,0xe9,0x18,0xba,0x13,0xed,0xd7,0xb,0x31,0x5,0xe,0xaf,0x13,0xd6,0xe,0x10,0x2,0x2,0x14,0xcb,0xd5,0xf9,0xc,0xf9,0xe,0x1f,0x24,0xd5,0xeb,0xff,0xf1,0xf5,0xc,0x8,0x7,0xf4,0xd7,0x6,0x10,0xe8,0xef,0xfc,0x2f,0xee,0xf1,0x18,0xf8,0xf4,0x2,0x11,0x21,0xd3,0x12,0x14,0xe4,0xf4,0x2,0x5,0x24,0xca,0xf2,0xf3,0xeb,0xe7,0xf8,0x16,0x1a,0xeb,0xd,0x5,0x16,0xf1,0xec,0x11,0x1c,0x9,0x1e,0xe0,0xe6,0xfa,0xe,0xd,0x2a,0xea,0x2e,0xed,0xf9,0xf7,0x16,0x9,0x5,0xdd,0xd6,0x2,0xeb,0xf5,0xf3,0xe4,0x3b,0xed,0x4,0xe0,0xe,0xfd,0x9,0xfd,0x35,0xdc,0x18,0xf3,0x4,0xfa,0x5,0x15,0x34,0xe5,0xe1,0xe4,0xf4,0xe0,0xf9,0x8,0x32,0x4,0x8,0xf4,0xf,0xff,0x8,0x9,0x2f,0x6,0x2,0xfd,0x5,0xc,0x24,0xe3,0x1e,0xf5,0xc,0xdd,0xf8,0x18,0x20,0xd8,0x14,0xef,0xf4,0x17,0x8,0x25,0x14,0x4,0x6,0xb0,0xf5,0xf5,0x9,0xf,0x3e,0xff,0x28,0xb3,0xf5,0x19,0xd8,0x14,0x21,0xd9,0xf7,0xb7,0xe5,0xfe,0xe7,0x7,0x1e,0x4,0x15,0xc5,0xf9,0x14,0x20,0xeb,0x1,0x1,0x18,0xce,0x0,0xe6,0xe2,0xf7,0xfb,0xf3,0xd,0xd3,0xf3,0x4,0xf8,0xf0,0x3,0xf1,0x25,0xb5,0xef,0x5,0xe0,0x1,0xf6,0x4,0x16,0xd1,0x1,0xa,0x21,0x1,0x5,0xe,0x1,0xf0,0xa,0xf3,0x0,0x3,0xf8,0xfa,0x3,0xb,0xde,0xfe,0xff,0xfb,0xea,0x9,0x2,0xf5,0xe8,0xe7,0x8,0x0,0xf5,0xf8,0xf,0x13,0xfa,0xeb,0xe8,0xfb,0x1f,0x8,0x16,0xe6,0xfa,0xe1,0x0,0x3,0xdd,0xf1,0x26,0xe5,0x1d,0xd9,0xff,0xf2,0xf8,0xff,0x33,0xea,0xe5,0x3,0xc,0x7,0xf9,0xf8,0xf,0xe1,0x1e,0xdd,0xf,0x0,0xf1,0x6,0x21,0x9,0x5,0xf3,0xec,0xe6,0x4,0x7,0x32,0xf1,0xf9,0xf2,0x1,0x18,0x1f,0xd2,0xe2,0xa,0xf4,0xca,0xfc,0x28,0x16,0xc2,0x10,0xf2,0xfc,0x8,0xe9,0x2a,0xf,0xfa,0xf5,0xa9,0x7,0xec,0xe9,0x19,0x43,0xb,0x1c,0xa6,0xe9,0xf4,0x16,0xd,0x2b,0xfc,0x11,0x9a,0xe1,0xf1,0x1c,0xf5,0xf,0xe4,0x18,0xc0,0xd9,0x14,0x26,0xe6,0xf8,0xa,0x17,0xec,0xfb,0xe1,0x22,0xdf,0xf2,0xfe,0x1e,0xd4,0xeb,0xd7,0xe,0x8,0xf6,0xef,0xfc,0xe6,0xd4,0xf7,0xb,0xfb,0xf5,0x1,0x25,0xd7,0xfb,0xd,0xfe,0xff,0xf3,0x1d,0x32,0xfe,0xee,0x12,0xf2,0xc,0xec,0x2,0x10,0xef,0x1,0xf2,0xb,0xf3,0xf7,0xfa,0x25,0xfb,0xd,0x11,0x15,0x4,0xfc,0xc,0x21,0x12,0x29,0x0,0xfa,0xf6,0xf5,0x6,0x22,0xea,0xe2,0xee,0x0,0xfd,0xf0,0xb,0x1d,0xd3,0xe4,0xe4,0xa,0xfc,0xe8,0xea,0x2c,0xed,0xed,0xef,0xe8,0xf2,0x5,0xfd,0x15,0xd8,0xda,0xca,0xee,0xfa,0x0,0xfe,0xe,0xf2,0xf0,0xe,0xf5,0x4,0x3,0x1d,0x2b,0xee,0x5,0xf,0x10,0x13,0x35,0xe2,0x4,0x10,0xdf,0xcf,0xeb,0x40,0x26,0xe4,0x3,0xf3,0xf9,0xf5,0x14,0x24,0x2a,0xdf,0xfe,0xab,0xe5,0xfe,0x1c,0x27,0x35,0xdb,0xff,0xac,0x1,0xf6,0xfc,0x19,0x1a,0x11,0x1f,0xa8,0xf5,0x2,0xf,0x1a,0x1f,0xf7,0xf2,0xa2,0x0,0x15,0x22,0xe4,0x13,0x0,0x9,0xd9,0xd5,0x2,0x19,0xfd,0xf8,0xe7,0xff,0xfb,0xe0,0xef,0xf7,0xee,0xf3,0xf3,0x19,0xb0,0xdf,0x0,0xf,0x8,0xf3,0x15,0x17,0xec,0xf,0x11,0x14,0x2,0x8,0x10,0x17,0xe6,0x8,0xf7,0x0,0xed,0xf7,0x29,0x7,0x10,0x5,0x5,0xe7,0xed,0xf4,0xf9,0x15,0xf9,0xf0,0x8,0x0,0x3,0x9,0x21,0x28,0xf6,0xe,0xfb,0xf3,0x3,0xf7,0xf,0xc,0xf0,0xf5,0xe3,0xd8,0xf8,0xf2,0x9,0x1c,0xe7,0xfb,0xe4,0xf6,0xfa,0xf8,0xf1,0x42,0xf6,0xda,0xdd,0xd7,0xfa,0xff,0x2f,0x2c,0xda,0xa,0xde,0xec,0xf1,0x14,0xfb,0x1d,0xeb,0xee,0xf2,0xeb,0xf3,0xed,0xe,0x35,0xf0,0x6,0x19,0x4,0x2f,0x23,0xe2,0x7,0x13,0xf,0xe9,0xf0,0x22,0x2e,0xd9,0x1a,0xcb,0xed,0xfd,0x4,0x27,0x1e,0xf6,0x7,0x96,0xd6,0xd8,0x11,0x18,0x56,0xd2,0xfb,0x92,0xfc,0xb,0xa,0x17,0x2c,0xe5,0x4,0xa2,0xf8,0xe2,0x4,0x1a,0xd,0xeb,0x11,0xa2,0xe5,0xe5,0xf8,0x2,0xf7,0x17,0x3,0xca,0xe9,0xc,0x1f,0xfe,0xf5,0x18,0x12,0xdd,0x8,0x15,0xff,0xfc,0xf6,0xe1,0x1d,0xe2,0xe1,0xfe,0xfc,0x3,0xff,0xf2,0x23,0xd2,0x1,0x13,0xdd,0xf3,0xf4,0xf2,0x7,0xef,0x3,0x15,0x21,0xd8,0xf8,0x9,0xf3,0xe8,0xea,0xe8,0xf2,0x8,0xf0,0x4,0x1a,0xf2,0x19,0xfb,0x1b,0x15,0xfc,0x1d,0x30,0xe5,0x1e,0x9,0xe8,0xe9,0x9,0xf7,0x2a,0xe1,0xe,0x0,0x21,0xf3,0xff,0xfb,0x1,0xdf,0xf2,0xfe,0xf4,0xfc,0xf0,0xb,0xb,0xdd,0xe4,0xd2,0x14,0xf7,0xfe,0xb,0x39,0x1,0xe6,0xe4,0x27,0xfa,0xe4,0x4,0x2c,0xe2,0x4,0xf5,0x7,0xf2,0x3,0xf0,0x10,0xf5,0xf6,0xfc,0x16,0x22,0x1b,0xf8,0x11,0xe4,0x9,0xf6,0xf0,0x41,0x1e,0xcf,0x4,0xea,0xee,0xe,0xf6,0x1b,0x2f,0xc7,0xf1,0xba,0xef,0xf,0x16,0x1e,0x39,0x5,0x1e,0x90,0xe6,0xd,0xfa,0x22,0x3f,0xe3,0x23,0xa5,0xe3,0xe9,0xf,0x5,0x27,0x2,0x11,0x99,0x5,0xfa,0x5,0x3,0x1,0xff,0x26,0xd3,0xf7,0xf7,0xf9,0x5,0xf4,0xef,0x23,0xd2,0xdd,0x5,0x8,0xfa,0xff,0x3,0x4,0xbd,0xd7,0x14,0x6,0xef,0x6,0xe5,0x5,0xea,0xea,0x2,0xfd,0xd,0x0,0x8,0xff,0xe7,0xfb,0xfe,0x13,0xfe,0xec,0xf9,0x2,0xf3,0xff,0xff,0x8,0x4,0xed,0x19,0x1d,0xfa,0xa,0xd,0xf2,0xf,0xec,0x25,0x1c,0xec,0xb,0x1,0xff,0x1,0xf6,0x8,0x9,0xe8,0xe2,0xec,0x23,0xe5,0xe9,0xf0,0x2e,0xbd,0xe1,0xef,0x14,0xe9,0xf6,0xf5,0x1d,0xdc,0xe3,0xd7,0xfc,0xf9,0xf2,0xfe,0x24,0xf2,0x5,0xd5,0xed,0xe9,0xf9,0xfa,0x2d,0xf0,0xfe,0xee,0xf2,0xe8,0xf7,0x6,0x14,0x1,0x10,0x6,0xf3,0xe,0xe,0xc2,0x1d,0xf2,0x1c,0xed,0xe3,0x53,0x21,0xb8,0xc,0xde,0x3,0x15,0xeb,0x46,0x39,0xdf,0xf6,0xa3,0xee,0xf6,0xe0,0x33,0x50,0xdd,0x27,0x9f,0x7,0x13,0xe2,0x1f,0x35,0xed,0x1f,0xb7,0x7,0x11,0xed,0x17,0x28,0xf4,0x20,0xc1,0xec,0xef,0x16,0x2,0xfa,0xe0,0x1b,0xf7,0xdb,0xfd,0xa,0xe7,0xfb,0xe7,0x25,0xe2,0xe7,0xf8,0xf0,0xee,0xe9,0x2,0x6,0xc9,0xe4,0x14,0xe3,0xe2,0xf7,0xf8,0xfd,0xdd,0xe2,0x8,0xa,0xe4,0x5,0xf5,0x16,0xe7,0x1,0x0,0x1c,0xe7,0xf0,0xf6,0x19,0xfe,0xc,0xf2,0x6,0x3,0xe8,0xb,0xfe,0xe3,0x19,0x8,0x1a,0x10,0xfd,0x0,0x21,0xf0,0xeb,0x18,0x2,0xf3,0x4,0xf0,0x18,0xdb,0x5,0x1,0xde,0xed,0xe9,0x23,0x15,0xaf,0xe6,0xf1,0xa,0xe6,0xea,0x1,0x18,0xd8,0xfd,0xf1,0xe6,0xec,0xf5,0xe,0x1e,0xcc,0xfc,0xe7,0x0,0xe9,0x11,0x0,0x30,0xf9,0x14,0xf4,0x19,0xdd,0xf7,0xf7,0x2f,0xf4,0xf2,0xff,0x27,0x15,0x1c,0xbc,0x2f,0xe9,0x14,0xf5,0xe8,0x44,0x30,0xe8,0x1d,0xe4,0x18,0x11,0x0,0xc,0x2b,0xf3,0x29,0x96,0xe0,0x6,0xee,0x3e,0x55,0xdc,0x13,0x98,0xdf,0xf0,0xfe,0x17,0x33,0xe8,0x9,0xa3,0x7,0xef,0xe,0x1d,0x37,0xdd,0xfe,0xb5,0x0,0xf7,0xe0,0xea,0xfd,0xfd,0x19,0xbc,0xfd,0x15,0xfe,0x1,0xf3,0xd5,0x20,0xbf,0xe3,0x15,0xe,0xf0,0xf6,0xf2,0x14,0xcc,0xf0,0xf7,0x4,0xf2,0xff,0xb,0x2,0xd2,0xd8,0xfa,0xfc,0xe5,0x2,0x0,0xfb,0xf0,0xdc,0x1e,0x10,0x2,0x1,0x0,0x18,0xe9,0xdb,0x1e,0xf6,0xfc,0x3,0xef,0xa,0x0,0x16,0x0,0xf,0xf4,0x16,0xfa,0xb,0xe2,0xfa,0xe0,0x7,0xfb,0x2,0x21,0xe,0xdd,0xb,0xea,0xf0,0xeb,0xfb,0x19,0x9,0xd4,0xf2,0xef,0xb,0x0,0xeb,0x1a,0x2f,0xea,0x6,0x3,0xf6,0xf8,0xfb,0xfe,0x1d,0xea,0xdd,0xed,0xfd,0xfb,0xe7,0xfe,0x18,0xf4,0xfc,0xb,0xf6,0xfc,0xb,0xfb,0x28,0x7,0xff,0x7,0x1e,0x3,0x21,0xcf,0x22,0x5,0xe6,0xea,0xe7,0x43,0x2e,0xe7,0x14,0xfb,0xa,0x1e,0xfe,0x2c,0x24,0xd5,0xfd,0x9e,0xd1,0xf2,0x1c,0x32,0x51,0x1,0xf3,0xac,0xe1,0xf4,0xe5,0x1c,0x37,0xf1,0xf,0xa7,0xdb,0x0,0xf6,0xf,0x18,0xe1,0x10,0xc9,0xc5,0xe8,0xeb,0xf2,0xfd,0xf6,0x2,0xc2,0xff,0x0,0x19,0x3,0xf,0x2,0x22,0xd4,0xe7,0x7,0xf,0xe5,0x1a,0x9,0xb,0xdc,0xd2,0x0,0x5,0xee,0xf8,0xdc,0x14,0xd0,0xa,0xa,0xfa,0xeb,0x4,0xf3,0x6,0xde,0x5,0xfb,0xfd,0xe3,0xec,0xfd,0x14,0xd7,0x11,0xe,0xe6,0x6,0xec,0xde,0x22,0xd7,0x0,0x3,0xf5,0xf5,0xd,0x1,0x5,0xea,0xb,0x16,0x4,0xff,0x13,0xf3,0x12,0xd2,0xdf,0xb,0xe4,0x6,0xf6,0x8,0x2d,0xd3,0xd6,0xe7,0xa,0xec,0xff,0xfe,0x1,0xdf,0xf4,0xdf,0x1c,0xfe,0xf9,0xf7,0x13,0xca,0xff,0x3,0x6,0xe9,0xf7,0x6,0x8,0xd7,0xf3,0xed,0x8,0xe3,0xfd,0xc,0x11,0x15,0xfb,0x15,0x8,0x28,0x40,0xe7,0xd,0x8,0xec,0xe8,0x16,0x67,0x46,0xc8,0x16,0xf1,0x2,0x24,0x0,0x3a,0x43,0xd6,0x12,0xae,0xe7,0xf4,0xf8,0x3a,0x65,0xe4,0xc,0xb2,0xef,0x1f,0xe8,0x29,0x59,0xf8,0x11,0xc4,0xe1,0xfe,0xfa,0x27,0x43,0xc9,0x1e,0xbb,0xfb,0xf3,0x13,0x15,0xd,0xf1,0x13,0xcd,0xf0,0x7,0x19,0x7,0x0,0xd8,0xeb,0xbf,0xf0,0xfc,0xf6,0xef,0x16,0x1,0x2,0xc1,0xdf,0xfd,0xe9,0x6,0x6,0xf1,0x8,0xd7,0xcc,0xfb,0xe,0xfc,0x14,0xf2,0x1a,0xe2,0xd,0xeb,0x9,0x7,0x10,0xe6,0x13,0xeb,0xf5,0x15,0x14,0xeb,0xfe,0xf9,0x17,0xd2,0xe3,0x1e,0xf5,0x4,0xa,0xf1,0xe,0xde,0xe7,0x1,0x20,0xc,0xfc,0xdc,0xf9,0xe5,0xe9,0xff,0x1d,0xa,0xfe,0xec,0x25,0xaf,0xd2,0x1,0x16,0xfc,0x17,0xe8,0x1e,0xcd,0xd9,0xe2,0xf1,0xeb,0x8,0xff,0x33,0xe5,0xfb,0xeb,0x4,0xfe,0xf7,0xfd,0x1f,0xee,0xff,0xed,0xf8,0xe0,0xff,0xfd,0x2b,0xa,0xf5,0x15,0x1d,0xf3,0x3f,0x16,0xf6,0xf2,0xee,0xf4,0xef,0xf0,0x56,0xa,0x1a,0xbc,0xfc,0x2f,0xfb,0xf0,0x56,0x1e,0xe,0xc6,0xe8,0x6,0xb,0x11,0x62,0x3e,0xf9,0xb8,0xc9,0xed,0xeb,0x2,0x63,0x2c,0xfd,0xc5,0xe9,0x0,0x17,0xf,0x37,0xfe,0x20,0xcc,0xe0,0xe0,0xe,0xe6,0x20,0xa,0xfd,0xdf,0xee,0xb,0x2,0xee,0x1f,0xfb,0x6,0xd2,0xed,0xfe,0xeb,0xfc,0x12,0xfd,0x14,0x0,0xd8,0x8,0xf6,0xec,0x17,0xf9,0x10,0x0,0xd9,0x18,0xf1,0xee,0xf,0xf4,0x3,0xee,0xeb,0xf0,0xef,0xf2,0x6,0x4,0x0,0xf4,0xf,0x9,0x6,0xf7,0xb,0xfd,0x1,0x3,0x3,0xf4,0xf6,0xdd,0x14,0x1c,0xef,0xf1,0xdd,0xf7,0x13,0xd9,0x15,0xef,0x2,0xd2,0xe7,0x5,0x5,0xe2,0x9,0xf2,0x11,0xf5,0xba,0xf0,0x4,0xe0,0x1,0x6,0x10,0xe6,0xef,0xfc,0x12,0xf9,0xf4,0x1b,0x2f,0xe3,0xf,0xd7,0xf6,0xb,0x11,0xf7,0xc,0x0,0x6,0x18,0xef,0x6,0x3,0xa,0x9,0xf6,0x1a,0xd,0xed,0xfe,0x2c,0x43,0xf4,0xe5,0xde,0xf5,0x2,0x25,0x5a,0x49,0xd4,0xe6,0x24,0x1e,0xf7,0xe,0x5c,0x5d,0xf0,0xf9,0xe4,0x1c,0xeb,0x28,0x7f,0x5b,0xec,0xfa,0xdb,0xc,0xf5,0x20,0x49,0x51,0xe1,0xed,0xe6,0xe,0x26,0x28,0x33,0x35,0x5,0xe1,0xe4,0x1f,0xfc,0xf9,0x39,0x18,0x4,0xed,0xed,0x1,0xe7,0xe6,0x8,0x9,0x3,0xe7,0xf9,0xe,0x6,0xec,0x8,0x12,0x1a,0xda,0xef,0xdf,0xf9,0xe2,0x1e,0x1c,0x0,0x12,0xd7,0x1,0xf7,0x21,0x17,0x13,0x19,0xde,0xe0,0xec,0x16,0x1,0x1b,0x6,0xc,0xf0,0xe8,0x18,0x3,0x6,0xe,0x9,0xfa,0x3,0xf3,0xdd,0x1,0xfb,0xa,0x2a,0xf4,0xf6,0xda,0xe9,0xfe,0xe9,0x12,0x19,0xe9,0x5,0xdf,0x0,0xeb,0xf2,0x10,0xc,0xe1,0xcd,0xcb,0xf2,0x1f,0xd9,0xc,0xfa,0xfb,0xe8,0xde,0x0,0xfc,0xe5,0x0,0x11,0x2,0xe6,0x17,0x14,0x0,0xf2,0xfd,0x0,0xe1,0x10,0x24,0x12,0xec,0xed,0x1e,0x9,0x18,0x3,0xc,0x4,0xf4,0x15,0xf,0x10,0x18,0xd6,0x29,0x10,0x4,0x1c,0xef,0xf,0xc,0xc7,0x4,0xfe,0xeb,0xff,0xf5,0xe3,0x15,0xfe,0xcb,0x10,0xff,0x12,0xfb,0xe4,0xeb,0xf9,0x0,0x2,0xf1,0x14,0x13,0x1,0x2,0xf9,0x1,0x6,0xc,0xf5,0xa,0x1e,0x1,0x19,0xe,0x5,0xf5,0xa,0xff,0xff,0xf2,0xfb,0xdb,0xf8,0x6,0x17,0xf2,0xf7,0xd,0xe,0xf4,0xfa,0xf7,0x14,0xdb,0xe0,0xfd,0x8,0x16,0xf7,0x16,0xfc,0x9,0x27,0x7,0x9,0xfb,0xa,0xfc,0xc,0xe4,0xdb,0xee,0xff,0x10,0xf3,0x9,0xfa,0xf4,0x23,0xf3,0xf4,0x19,0xff,0xfa,0xff,0x19,0xf,0x11,0xed,0xec,0xf8,0xf,0x10,0xf3,0xff,0xb,0xf7,0x6,0xb,0xe,0x7,0xe4,0x18,0xa,0x8,0xe,0x2,0xa,0x5,0x19,0x2,0xf3,0xfe,0xfe,0xb,0xf,0xfc,0xfa,0x5,0xf9,0xe2,0xf9,0x1b,0xf7,0xf,0x7,0xfc,0x12,0xfe,0x1,0xfd,0xf0,0x4,0xf4,0xfd,0x7,0xf2,0x4,0x4,0x7,0xef,0xc,0xed,0xe,0xf6,0xef,0x8,0x7,0x4,0xe9,0xf3,0x20,0xda,0x15,0xf8,0xff,0xec,0xe0,0xf6,0xff,0xe9,0x8,0x1,0x10,0xf0,0xfc,0xe9,0x8,0xe8,0xf5,0xf8,0xe5,0x17,0xe6,0x3,0xfc,0x9,0xf5,0xdd,0xf2,0xff,0x5,0xf6,0xf8,0xf5,0x7,0xfc,0xf1,0x4,0xf3,0x13,0xe1,0xf,0xf2,0xa,0xf9,0xfd,0x1c,0xe0,0x11,0x1b,0xe6,0xef,0x5,0x5,0xc,0x23,0x10,0x9,0xfe,0xf7,0x1a,0xf1,0xfc,0x11,0x1d,0xff,0x3,0x3,0xe6,0x7,0x11,0xc,0xd,0x16,0x5,0x5,0x25,0xf3,0x10,0x10,0x6,0x9,0xe8,0x1a,0xf0,0xee,0x9,0xff,0x24,0xf7,0xfb,0xe6,0x6,0xfa,0x8,0x3,0x0,0xf2,0x4,0xf0,0xeb,0x14,0x1c,0x3,0x21,0x14,0x1d,0xfe,0x3,0xf6,0x2,0x9,0xff,0x0,0x13,0xef,0x10,0x1e,0xb,0x1d,0x1c,0xf1,0xf6,0xe7,0xfd,0x14,0x1,0xff,0x13,0xf7,0xfc,0x0,0x21,0xe3,0xeb,0x7,0xe,0x9,0xf1,0xf8,0xfd,0x3,0xee,0x19,0xfd,0xff,0xfb,0xff,0xea,0xfb,0x7,0xf0,0xa,0x4,0x4,0xb,0x12,0xfe,0xb,0xe0,0xff,0xf6,0xe5,0xfc,0x11,0xed,0xfd,0x15,0x3,0xdd,0xdb,0x4,0xfe,0xff,0xe,0xff,0xfa,0xfb,0xe5,0xef,0xf6,0xfe,0x22,0xf,0xe8,0xfe,0xf4,0xfd,0xd9,0x3,0xa,0xdf,0xcf,0xf1,0x14,0x5,0xfd,0xfb,0xf3,0xfb,0xfb,0xf,0xf8,0x5,0x9,0x3,0xf7,0x5,0x5,0x13,0xfb,0xeb,0x23,0xe7,0x18,0xfb,0x0,0xfe,0xdd,0xe9,0xea,0xd3,0xe8,0x1a,0xef,0x1,0xf1,0x9,0x1d,0xd8,0xfc,0xda,0x19,0x3,0xec,0xe5,0xf3,0xed,0xa,0xf4,0x13,0xb,0xf7,0xc,0x0,0xf9,0xea,0xe3,0xfe,0xff,0xd,0xa,0x1b,0xd7,0x17,0xeb,0xe9,0x0,0xe,0xee,0x24,0xef,0x9,0x7,0xf0,0xf5,0x7,0xf5,0xf5,0x10,0x17,0x6,0xf7,0xfc,0x2,0xfb,0xf9,0xe7,0xa,0x26,0xf3,0x1,0x1,0x9,0xb,0x2,0x27,0xf8,0xee,0xfd,0x1c,0xf8,0xf2,0xf,0xfc,0xd,0xe0,0xea,0x2,0xb,0x0,0xe0,0x8,0xfe,0x10,0x4,0xfe,0xeb,0x13,0x1,0xc,0xe,0xed,0x9,0x1,0xc,0xe3,0x10,0xdf,0xd1,0x14,0xf3,0xef,0x9,0xf0,0xee,0xe5,0x11,0xf4,0xf6,0x0,0xe8,0x20,0xa,0xfc,0xea,0xf7,0x2,0x16,0xe7,0xf3,0xd,0xe4,0x4,0xe6,0xef,0xf8,0xf,0x23,0x2,0xe0,0x1,0x1,0x1,0x5,0xf5,0xd,0xf5,0xf5,0xe1,0xff,0x4,0x0,0xf4,0xd,0xee,0xf1,0xef,0xf7,0xb,0xff,0x1b,0xec,0x5,0xe7,0xf3,0x13,0x12,0xf2,0xf3,0xfc,0xea,0x6,0xfe,0x13,0x12,0xdb,0x11,0xe2,0xfc,0xd,0x1c,0xe8,0x1d,0xfc,0xf2,0xe2,0x13,0x1d,0xda,0xf6,0x1c,0x18,0x1e,0xf4,0xfa,0x3,0xdc,0xf,0xff,0xff,0x18,0xb,0xed,0xf1,0xf8,0x2,0xf4,0x10,0xf9,0xeb,0xb,0xe,0xf,0x1,0x2,0x1b,0x6,0x10,0x0,0xe7,0x23,0xd,0xf6,0x11,0x8,0xf5,0xf,0x5,0x13,0xf7,0x1,0x1,0xc,0xf6,0xf9,0xf0,0x29,0x1,0xe9,0x11,0x2,0xfa,0xeb,0x16,0xe,0x10,0x9,0xe,0x1c,0xa,0xe3,0xd3,0x1,0xe3,0x0,0x6,0xe2,0xe9,0x19,0xef,0x12,0xf3,0xfc,0x2,0xb,0xc,0xd,0xed,0xfd,0xf6,0xf9,0xe9,0xf2,0x28,0xfe,0x3,0xec,0x3,0x0,0xf8,0xde,0xd,0x25,0x7,0x1a,0xe7,0xfd,0x29,0xd8,0xf7,0xfb,0xde,0xc,0x8,0x6,0x22,0xee,0x1d,0x5,0x7,0xf0,0xfb,0xfe,0x7,0xf1,0x4,0xe9,0x1,0xfc,0xf1,0x0,0xeb,0xe3,0x8,0xec,0xfe,0x4,0xeb,0xfc,0x1,0xf6,0xe,0xdf,0xf8,0x12,0xe3,0x16,0xdc,0x21,0xa,0xe6,0x6,0xe5,0x10,0x7,0xf7,0x1e,0xde,0xe3,0x7,0x16,0xed,0x23,0xf2,0x12,0xd,0xe9,0xf9,0xe8,0xfe,0xe,0x2,0x18,0xa,0xea,0xec,0xfb,0xfe,0xc,0x1b,0x19,0x20,0xfa,0x7,0xe5,0xc,0x4,0x27,0xdb,0xe6,0xfe,0xd,0xa,0xa,0xfe,0x39,0xdd,0xde,0x5,0xec,0x9,0x5,0xa,0x2c,0xf4,0x2,0x1f,0xd3,0x24,0xee,0xf,0x3c,0xf5,0xfd,0xf8,0xf8,0x12,0xf5,0xf3,0x19,0xf9,0xda,0xf6,0xa,0xa,0xf4,0x9,0xf,0xfc,0x0,0x1,0x1,0xf3,0xf8,0x5,0xf3,0xc,0x19,0xe,0xfd,0xfa,0xe1,0xfc,0xc,0x3,0xfb,0x1b,0x6,0xcc,0xe4,0x8,0xf9,0x10,0xe9,0x6,0x0,0x17,0xe8,0xd,0x12,0xca,0xf5,0x23,0xe4,0x21,0xf6,0x19,0x33,0xdd,0xfa,0xc,0x1,0x14,0x7,0x0,0x34,0xda,0x5,0x7,0x1,0x7,0xe4,0x6,0x24,0x2,0xff,0xf0,0x9,0xfc,0xf4,0x3,0x6,0xee,0x8,0xe2,0x1d,0xfa,0xc,0xfc,0x2,0x3,0xe5,0xf0,0xe2,0xa,0x18,0x12,0xc,0x1e,0x20,0xed,0x20,0xe4,0x1,0x2a,0x9,0xd,0xe,0xd0,0xf4,0xdd,0xfd,0x2b,0xf2,0x8,0xc,0xf8,0xf7,0xfc,0xf9,0x15,0xef,0x19,0x1c,0x1,0xff,0xe2,0x1,0xf3,0x30,0xe,0xfb,0x15,0xe8,0x1c,0x0,0xfa,0x16,0xef,0xea,0xfb,0x5,0xf0,0xe,0x2,0x13,0xf4,0x1,0x3,0xe5,0x29,0x7,0x9,0x24,0xf9,0xe3,0xf8,0xde,0x2d,0xf4,0xf5,0x40,0xed,0xdf,0x7,0xef,0xf,0xa,0xb,0x32,0xd,0xe8,0x0,0xe6,0xf6,0xfc,0xfd,0x19,0x11,0x9,0xf3,0x3,0xea,0xf1,0xfb,0x2,0xfd,0x6,0xff,0xfe,0x9,0xec,0x6,0xc,0x15,0xf9,0x6,0xd7,0xe3,0xf7,0xed,0x1,0x3,0xfd,0x14,0x1,0xe,0xe0,0x37,0xd,0xd2,0x18,0x2f,0xea,0x12,0xd,0x5,0x3a,0xd5,0x7,0x1e,0xf2,0x21,0x11,0xf9,0x36,0xd3,0xf5,0x12,0xf6,0xfb,0xf6,0x6,0xf,0xde,0xf9,0x6,0x9,0xdf,0xff,0xb,0xf3,0xf5,0x1,0xf1,0xea,0xf2,0x2,0x12,0xfc,0xe,0xee,0xf8,0xeb,0x0,0xef,0x21,0xf,0x9,0xef,0xeb,0x1e,0xef,0xf2,0x26,0xf9,0x17,0xf1,0xf1,0xf0,0xc,0x10,0x1d,0xff,0x1d,0x6,0x3,0xf6,0xfb,0x14,0x1b,0x3,0x22,0xfd,0xec,0x3,0xfa,0xf8,0x1,0x2b,0x1e,0x1b,0x9,0x9,0x7,0xff,0xf0,0x20,0xee,0x14,0xfb,0xf6,0xf8,0x11,0xd9,0x29,0xf4,0xfa,0x7,0xef,0x20,0xf9,0xf2,0x30,0xee,0xf0,0xf3,0xd6,0xd,0xfe,0x3,0x36,0xf5,0xd7,0x1,0xe6,0x4,0xf0,0x5,0x1f,0xf,0xdd,0xff,0xf8,0x1f,0xf2,0x4,0x37,0xfa,0x0,0xfd,0xf8,0x10,0xe1,0xfb,0xd,0xed,0xf6,0xe2,0xfe,0x8,0xfe,0x7,0x8,0x8,0x11,0xa,0xf0,0xf8,0xf5,0x4,0xea,0x8,0x12,0x6,0xd,0xf,0x10,0x40,0x28,0xc0,0xfb,0x3f,0x8,0x1d,0x9,0x1b,0x3d,0xee,0xf4,0x29,0x13,0x20,0xfc,0x11,0x4c,0xdb,0x2,0x15,0x5,0xec,0xeb,0xa,0x22,0xe7,0x0,0x2,0x1,0xd4,0xea,0xa,0xf3,0xe3,0xf8,0xf5,0xfa,0x1,0xd,0x19,0x6,0x24,0x13,0x2,0xf5,0xf1,0xf1,0x1b,0xf,0x19,0x4,0xe3,0xf9,0xe7,0x2,0x29,0xfc,0x29,0xec,0xe9,0x4,0xdc,0x22,0x1d,0xfd,0x1f,0x1,0xec,0xe8,0xf5,0x14,0x1b,0x19,0x6,0xe,0x2,0xd,0xf9,0x6,0xfc,0x15,0x7,0xfa,0xc,0xe1,0x18,0x1a,0xe8,0x1b,0xe9,0xef,0xa,0x18,0xfc,0x5,0xf9,0x14,0xdc,0x4,0x1,0xff,0x7,0xfd,0xf0,0x2c,0xf2,0xec,0xe,0xe7,0x1a,0x5,0xe8,0x35,0x13,0x9,0xf9,0x7,0xfe,0xfa,0xd,0x40,0xc,0xea,0xf4,0x4,0x1,0x11,0xfc,0x23,0xeb,0xf4,0xe9,0x4,0xeb,0xe7,0x7,0x9,0xfb,0xf1,0xf6,0xfd,0x2,0xfa,0x2,0xff,0x0,0xff,0xf1,0xf1,0x1a,0xe9,0x10,0xe3,0xb,0xc,0x8,0x4,0x1b,0xa,0x2b,0x10,0xe1,0x1,0x1f,0x6,0x4,0xec,0x19,0x49,0xee,0xf8,0x22,0xc,0x20,0x2,0x7,0x31,0xe7,0xff,0xf,0xf0,0xfd,0xea,0x13,0x26,0xce,0xfa,0xff,0xee,0xe9,0xfe,0x15,0x8,0x4,0x5,0xd,0xfa,0xdd,0xf8,0x7,0xb,0x33,0xef,0xec,0xf9,0xd9,0xe6,0x1d,0x10,0x41,0xf6,0xdf,0x11,0xe3,0x14,0x1d,0xfb,0x2b,0x15,0xdc,0x9,0xf6,0x5,0x16,0x0,0x1c,0x27,0xe4,0xfc,0xf7,0x16,0x8,0x8,0x2f,0xdd,0xf8,0xfa,0xe9,0xe,0xb,0xb,0x2,0x12,0x2,0xfd,0x19,0x3,0xeb,0x11,0xf4,0x9,0x9,0x15,0x12,0xd,0xef,0x1c,0xe4,0xfe,0x17,0xc,0x9,0x4,0xea,0x2f,0xf2,0x1e,0x2,0xfb,0xfe,0xe3,0x0,0x2e,0x4,0xf9,0xc,0x5,0x27,0xc,0x7,0x2d,0xf7,0xb,0xfb,0xf9,0x1c,0xdf,0x11,0x36,0x5,0xf2,0x2,0xf8,0xb,0x7,0x5,0xfb,0xfc,0xe,0x13,0xfa,0xfb,0x9,0xf5,0xfd,0x6,0x15,0xf9,0x3,0x18,0xfd,0x1a,0xa,0x3,0xe2,0xfb,0x0,0x1e,0xfe,0x4f,0x27,0xe1,0xf7,0x31,0xf0,0x1b,0xec,0x7,0x5f,0xe2,0xf8,0x40,0x5,0x17,0x24,0xc,0x3c,0xf3,0x10,0x13,0xf8,0xb,0xf3,0xf9,0x36,0xe1,0xf3,0xf4,0xe8,0xef,0xf8,0xfc,0xeb,0xe3,0xfb,0xf0,0xee,0xdb,0x6,0xc,0x11,0x1e,0x10,0xe2,0xe9,0xeb,0xd,0x34,0xf,0x43,0xd9,0xef,0x8,0xec,0x5,0x1d,0x2,0x33,0xef,0xf4,0xf7,0xe6,0xf9,0x22,0x7,0x4,0x6,0xe9,0x2,0xf0,0xfc,0x24,0x20,0x24,0x17,0xe6,0xf,0x5,0xf6,0xfc,0x1f,0xf2,0x1,0xd,0xe7,0xff,0x1d,0xf0,0xfa,0xd0,0x0,0xff,0xe,0x23,0xf9,0xf3,0x11,0xde,0xd,0x5,0x4,0xb,0xb,0xfb,0x26,0xd,0xd,0xff,0xe8,0x16,0xe8,0xb,0x3c,0x18,0xe4,0x4,0xff,0xfa,0xf3,0xff,0x40,0xee,0x6,0xfc,0xd,0x0,0xf7,0x13,0x3f,0xf7,0x13,0x6,0x8,0xf9,0x13,0xf2,0x19,0xfd,0xf9,0xf3,0xe6,0xfc,0x7,0xf6,0xfd,0xa,0x22,0x0,0x1,0x19,0xff,0xe7,0xff,0x8,0xfd,0x3,0xfd,0x1f,0xe7,0x28,0x8,0xde,0xf3,0x43,0xf6,0xc,0xfe,0x1e,0x52,0xf2,0x4,0x17,0xf2,0x8,0xd,0x4,0x38,0xde,0xc,0x10,0xef,0xdf,0xf,0x1,0x24,0xde,0xe1,0xd,0xfd,0xd4,0xf6,0x12,0xe,0xed,0x1,0xf0,0xf3,0xfd,0xff,0x18,0xf3,0x36,0xda,0xf6,0xef,0xe8,0xef,0x37,0x27,0x4e,0xf8,0xf4,0xff,0xe5,0xf3,0x32,0xb,0x36,0x8,0xe9,0xf6,0xe2,0x13,0x21,0xfe,0x12,0xed,0xdd,0xfb,0xf8,0x5,0xf,0x3,0x1c,0x4,0xfc,0xf2,0x23,0xe,0x3,0xfc,0xf9,0x18,0xf7,0x1,0x1b,0x3,0xf5,0xfd,0xde,0xf3,0x19,0xfc,0x11,0x2,0xe7,0x13,0xde,0xd8,0xf2,0x5,0x28,0x2,0x2,0x27,0x7,0x8,0xff,0x7,0x27,0xe,0x19,0x40,0xfb,0x2,0xc,0xf6,0xd,0x7,0xf,0x47,0xf8,0x5,0xe,0xfd,0x3,0x1e,0x7,0x32,0xe7,0xf6,0x24,0x1,0x1,0x2,0xa,0xff,0xf6,0x26,0x15,0xf0,0x4,0x13,0x3,0xfa,0xfe,0xf6,0xf1,0x9,0x2a,0xe6,0xea,0xf6,0x17,0x13,0xeb,0xff,0x15,0xeb,0x23,0x6,0xc8,0xf6,0x33,0xeb,0xf4,0xe7,0x12,0x2a,0xe3,0xe6,0x32,0xfa,0x16,0x15,0x17,0x40,0xf1,0x8,0x1a,0xf3,0xf6,0xc,0xc,0x11,0xd0,0x22,0x2,0xee,0xea,0xf4,0xf8,0xf9,0x13,0x10,0x17,0xf5,0xf1,0xa,0xe,0xfd,0x32,0xda,0xf1,0xe2,0xdb,0xf2,0x34,0x1f,0x53,0xfc,0xe4,0xf2,0xf6,0xf2,0x1d,0x4,0x4a,0xec,0xee,0x6,0xdf,0x1,0x1a,0x4,0x27,0xfc,0xe6,0xfd,0xd9,0xfd,0xe,0x0,0xc,0x16,0xf3,0x3,0xf7,0xfc,0xe,0xf,0x9,0x6,0x6,0x4,0x8,0x2,0xed,0xf5,0xe4,0xe6,0x7,0x6,0x3,0x18,0xea,0x13,0xe2,0xfa,0x10,0xf2,0x2,0xec,0x3,0x3c,0xf6,0xf6,0xa,0x10,0x9,0xf8,0x15,0x24,0xfd,0xd,0x9,0x1,0x0,0xff,0x0,0x1a,0xf0,0xee,0x8,0x3,0x1d,0x5,0x16,0x46,0xe6,0xf8,0x8,0x0,0x9,0x9,0xff,0x1,0xfc,0x20,0xfc,0xec,0x5,0x1b,0x3,0xf1,0x12,0xe4,0xfa,0x24,0x1c,0xf5,0xf2,0x5,0x11,0xe7,0xfa,0x2,0x20,0xea,0x31,0x10,0xcf,0xd8,0x33,0xee,0xff,0x9,0x20,0x3f,0xe2,0xa,0x29,0xee,0x3a,0xf2,0x1e,0x39,0x2,0x1e,0xfe,0xf2,0xef,0xe2,0xd,0xf,0xf1,0x19,0x2,0xe7,0xec,0xff,0xfe,0xe4,0xfe,0xfb,0x2,0xf6,0xf1,0xf4,0x7,0x1a,0x2a,0xf9,0x6,0xf9,0xda,0xf4,0x22,0x2,0x4f,0xa,0xf3,0xfc,0xf3,0xf6,0x25,0xa,0x28,0x1,0xf7,0x9,0xe6,0x5,0x28,0xf7,0x1e,0xf2,0xee,0x13,0xee,0x5,0xf,0xa,0x9,0xe8,0xe8,0xe,0x5,0x12,0xf,0x15,0x2,0xec,0xf8,0x2,0xf7,0x5,0xf8,0xff,0xdc,0x0,0x1,0x0,0x12,0x17,0xec,0x19,0xfa,0x9,0xfa,0xf3,0x1d,0xb,0x7,0x25,0xea,0xc,0xf5,0xfa,0x4,0xf7,0xfe,0x33,0xfe,0x14,0xef,0x4,0xf0,0x0,0x0,0x3a,0xea,0xfa,0x10,0x1,0xe4,0x0,0xff,0x23,0xe9,0x26,0x15,0x10,0x4,0x14,0xd,0x8,0xf8,0xfd,0x10,0xfb,0x0,0x21,0x6,0xfa,0xf,0x8,0xf1,0x9,0x28,0xf0,0xd8,0xd,0x8,0x9,0x2,0xfb,0x12,0x3,0xe,0xfb,0xce,0xf0,0x39,0xe5,0x9,0xf6,0x1f,0x35,0xdd,0x1c,0x25,0xef,0x17,0xc,0xf6,0x3e,0xf0,0x21,0x8,0xff,0xd7,0xfc,0xfd,0x1f,0xe5,0x18,0x12,0xe9,0xf5,0xe9,0x12,0xf6,0x2,0x13,0xf4,0xa,0xfd,0x3,0x9,0x8,0x2f,0x7,0xee,0xfd,0xd7,0x0,0x2b,0x29,0x3b,0xdb,0xde,0xf1,0xe1,0xf7,0x47,0x12,0x35,0xc,0xe4,0x9,0xef,0x17,0x2b,0xea,0x2d,0xf8,0xe8,0x18,0xef,0x3,0x11,0xa,0x10,0xff,0xe8,0x7,0xc,0x7,0x3,0x18,0x5,0x8,0xf8,0xf8,0x6,0x18,0xe9,0xf9,0xe0,0xf,0xd,0x18,0x4,0x1,0xf0,0x1c,0xf6,0x14,0xfd,0x12,0xc,0xc,0x2,0x34,0xf6,0xe6,0xfd,0xf9,0xf9,0xfd,0x0,0x2a,0xfc,0xf9,0xff,0xa,0xfe,0x1b,0xf5,0x34,0xdc,0xf9,0x15,0x13,0xe7,0x1b,0xf7,0x25,0xfd,0x9,0x8,0xa,0xf0,0x17,0xf,0x4,0xf4,0xe9,0x6,0x7,0xf5,0x2,0xfc,0xf5,0x9,0xee,0xf1,0x7,0x38,0x3,0x5,0xf,0x16,0xf,0xed,0xff,0x21,0xf8,0x34,0x7,0xd1,0xf9,0x27,0x0,0xc,0x21,0x18,0x42,0xe6,0x2,0x1a,0xf1,0x2f,0xf1,0xe,0x3b,0xee,0xf8,0x8,0xea,0xfe,0xf9,0x3,0x18,0xf5,0xf8,0xd,0xeb,0x1,0x10,0x9,0x2,0x15,0xfb,0xf1,0xb,0xf2,0x6,0x8,0x9,0x2f,0x19,0x2,0xfe,0xe4,0x6,0x1f,0x17,0x49,0xf2,0xe2,0x2,0xef,0x4,0x26,0x16,0x3f,0x8,0xf1,0xa,0xfd,0xf9,0x28,0x1,0x15,0xb,0xf9,0x10,0xdc,0x2,0x20,0xf7,0x16,0xe6,0x9,0x3,0xf1,0xf5,0x12,0x1c,0xfb,0x2a,0x8,0xfa,0xa,0x16,0xf6,0x15,0xf0,0x6,0x11,0xfd,0xe,0xf9,0xf6,0x12,0xed,0xf3,0xfd,0x1f,0xb,0xfa,0x8,0x30,0xf8,0xff,0xb,0xeb,0x10,0xff,0x7,0x22,0xd,0x7,0x9,0x3,0xf6,0xf8,0xfc,0x26,0xf8,0xee,0x11,0x2,0x3,0xa,0xef,0x38,0xfe,0x13,0x1b,0x9,0xfe,0x6,0x5,0xf3,0x4,0xdf,0xfc,0x0,0xe7,0x15,0xec,0xf1,0xf8,0xfc,0xed,0x5,0xe,0xf3,0x15,0x9,0x1,0xd,0xfd,0x0,0x24,0xe2,0x31,0x13,0xd5,0x1b,0x2b,0xe8,0x3,0x8,0x1d,0x33,0xdc,0xfd,0x24,0xe4,0x20,0xfa,0x7,0x33,0x1,0x12,0x6,0xf5,0xef,0xf7,0xfa,0x13,0x1,0xec,0xee,0xe0,0xfd,0xd,0xff,0x9,0xf6,0x0,0xed,0x7,0xea,0xe,0xff,0xe,0x26,0xfc,0xf0,0xe7,0xe7,0xfe,0x30,0xff,0x24,0x4,0x6,0xf4,0xf5,0xf8,0x23,0xe,0x3d,0xf2,0xfd,0x4,0xe8,0xfb,0x23,0xfe,0x33,0xe1,0x1,0xfd,0xdc,0xfb,0xe,0xfa,0x22,0xfb,0x11,0xfa,0xff,0x8,0x21,0x30,0x13,0x3,0xf2,0x3,0xf8,0xf,0xec,0xd,0xef,0xf,0x10,0x10,0xf,0xf6,0xf9,0x1e,0xf7,0xe5,0x8,0xfa,0x9,0xff,0x0,0x15,0x2,0x0,0x8,0xfe,0xfb,0xe,0x15,0x28,0xfa,0xfb,0x13,0x6,0xfb,0x5,0xf6,0x11,0xf6,0xb,0x6,0x15,0xe1,0x0,0xe9,0xf,0xe1,0x1d,0x18,0xfd,0xb,0xf,0xff,0xf2,0xf5,0xfd,0x14,0xff,0xf4,0xfe,0xe2,0xf8,0x14,0xb,0xeb,0x7,0x35,0xe2,0xeb,0xb,0x4,0x22,0xfe,0xe,0x1d,0xf2,0x24,0x11,0xcc,0xec,0x25,0xf7,0xff,0xf9,0x6,0x29,0xe4,0x7,0x1c,0xdb,0xf8,0x1d,0xfa,0x44,0xf2,0x1,0xf,0xe6,0x11,0x3,0xee,0x17,0x6,0xe0,0xc,0xd8,0xe9,0xfd,0x11,0xfe,0x7,0xdd,0xea,0xff,0xde,0xdd,0xa,0x9,0x30,0xf2,0x1,0xe4,0xe0,0xeb,0x2d,0x12,0x2d,0xeb,0xfc,0xf0,0xe8,0xf9,0x1f,0x8,0x3f,0xeb,0xe,0x13,0xf9,0xc,0x1c,0x2,0x25,0xec,0xf6,0x5,0xf3,0xf4,0x18,0x8,0x12,0xe9,0xfb,0xfd,0xf9,0x8,0x13,0x1c,0x8,0xec,0xfe,0x2,0xf1,0x19,0xf3,0x1d,0xf1,0x7,0x11,0x12,0xfa,0xf2,0xf6,0xd,0xff,0x17,0xa,0xfb,0x1f,0xf8,0x11,0x24,0xf6,0xfc,0xfe,0x7,0xed,0x5,0x1c,0x21,0xfe,0xfe,0x16,0xd,0x8,0xf,0x9,0x33,0xf4,0x1f,0x14,0xc,0xfe,0xf5,0xeb,0x2a,0xee,0xf3,0x12,0x19,0xec,0x1,0x6,0xf7,0x5,0x22,0xb,0xeb,0xeb,0x6,0xe1,0xf5,0xd,0xee,0xfb,0xa,0x31,0xff,0xe3,0xea,0x18,0x9,0xe3,0x7,0x1a,0xf8,0x15,0xfc,0xcc,0xf2,0x2a,0xe5,0x1,0xea,0x10,0x1f,0xd9,0x2,0x13,0xf6,0x16,0x1,0xe,0x3c,0x2,0x17,0x4,0xf1,0xf7,0x2,0x7,0xc,0x2,0x1f,0xf4,0xe6,0xf0,0xe9,0x5,0xf4,0xfd,0xe4,0xf7,0xe9,0xfc,0xef,0x6,0x2,0x26,0xf1,0xf1,0xeb,0xe9,0xe6,0x30,0x1c,0x38,0xf,0x3,0xf1,0x10,0x4,0x30,0x19,0x1f,0xfb,0xfc,0x5,0xe2,0xfe,0x18,0xf2,0x1c,0xf2,0xf5,0xe,0xf2,0x5,0x1d,0x28,0x12,0xf0,0xf0,0xf,0xa,0x3,0x1a,0x1a,0xf3,0x8,0x13,0xef,0xf5,0x1c,0x6,0x0,0xee,0x12,0x1d,0x3,0x18,0x6,0xa,0xe,0xf0,0xeb,0xfa,0xd,0x8,0xff,0x6,0x24,0xf,0x3,0xa,0xf,0xe,0xff,0x8,0x33,0xfc,0x0,0xe,0xfb,0xfb,0x5,0x7,0x19,0xe8,0xe7,0x12,0x11,0x15,0xf7,0xc,0x1a,0xf6,0x28,0x8,0xeb,0xf2,0x25,0xee,0x1,0x3,0xec,0xed,0xfa,0xf0,0xf2,0xef,0xf1,0x2,0x23,0xef,0x1,0x41,0xfa,0xf4,0xf4,0x15,0xf5,0xf5,0xf9,0x28,0xde,0x20,0xf6,0xc7,0xde,0x21,0xe4,0xfe,0xec,0xd,0x2c,0xee,0x24,0x10,0xf0,0x1d,0x12,0xe,0x2b,0x6,0xf8,0xfd,0x1,0x8,0xef,0xfd,0xf,0xeb,0xed,0xe1,0xdf,0xf1,0xe5,0x16,0xe3,0x8,0xfc,0xf6,0xf6,0xd8,0xf0,0x23,0xfc,0x2b,0xf5,0xff,0xe7,0xf4,0xe9,0x29,0x9,0x2b,0xc,0xff,0x8,0xb,0xed,0x29,0x14,0x3c,0xf5,0xeb,0x18,0xf6,0x10,0x22,0xf9,0x17,0x23,0x2,0xc,0xf6,0xfa,0x2f,0xfe,0x1e,0xeb,0xfd,0x3,0xf0,0x7,0x1c,0x9,0xfa,0xe1,0xd,0xf,0x18,0x3,0xfe,0xf0,0xec,0xb,0x10,0x2,0x14,0x6,0xef,0xf7,0xea,0xb,0x5,0xfe,0x1f,0x6,0xe,0x7,0x0,0xe1,0x1,0x1,0x7,0x5,0x9,0xf7,0xef,0x15,0xf7,0x12,0x5,0x3,0x4,0x1d,0x4,0x10,0x12,0x6,0x5,0x0,0x8,0x18,0xd6,0xf2,0xfa,0x7,0xf8,0x12,0x7,0xfd,0xdd,0x0,0x4,0xfb,0xf8,0x9,0xf3,0x9,0xfb,0xf0,0xe8,0x9,0x27,0xf5,0xf8,0x6,0x1,0x2,0xe,0xf6,0x1f,0xfa,0x29,0xf8,0xd6,0x1,0x22,0xf8,0x1d,0xe3,0x1a,0x39,0xa,0xd,0x19,0xf5,0x12,0xfb,0x1d,0x2a,0x3,0xf6,0xc,0xf2,0xfd,0xec,0x18,0x13,0xfe,0x1a,0xe8,0xdd,0x1,0xf8,0x30,0x1,0xf8,0xfe,0xe4,0xe7,0xff,0xeb,0x23,0xfa,0x2c,0xf0,0xfc,0xe7,0xa,0xf8,0x18,0x10,0x23,0x1,0xfa,0xe8,0xf1,0xfa,0x1d,0xe,0x17,0xe7,0xe4,0xf5,0xf9,0xc,0x17,0xc,0x13,0xe8,0xe1,0x17,0x19,0x5,0xb,0xf,0x23,0xed,0xff,0xfe,0xe0,0x14,0x16,0x0,0xd,0x1c,0xb,0xf5,0xfb,0x18,0xee,0xff,0xff,0xf3,0x18,0xc,0x5,0xfa,0xf6,0xfe,0xfe,0xf8,0xf8,0x9,0xef,0xf8,0xe,0xf0,0x0,0xf8,0xc,0xf8,0xf6,0x7,0x16,0x11,0xf8,0xea,0xff,0xff,0x1,0x20,0x7,0x8,0xfd,0x1c,0xfc,0x6,0xed,0xd,0x8,0x15,0xf0,0x25,0x1,0x1b,0x0,0x2,0xfe,0x1,0x5,0x1,0xfd,0xf1,0xe5,0xc,0xe4,0xe1,0xf0,0xfa,0xee,0xe,0x35,0xee,0x15,0xef,0xa,0xf9,0x1,0xf5,0x1f,0x5,0x1f,0xd,0xe1,0xf4,0xff,0xf5,0x23,0x2,0x18,0x30,0xfc,0xf0,0xd,0x4,0xd,0x6,0x29,0x1d,0xf9,0x8,0x6,0xe5,0x13,0xfd,0xd,0x26,0xef,0x9,0xdc,0xf2,0x5,0xdf,0xc,0xf6,0xf3,0xd9,0xf8,0x8,0xef,0xeb,0xf,0xf9,0x3a,0x3,0xff,0xe0,0xf7,0xf0,0x15,0x12,0x41,0xb,0xf1,0x4,0x4,0xe2,0xe,0xb,0x2c,0x3,0xea,0x2,0xfb,0xe7,0x8,0xe9,0x22,0xf3,0xf2,0x1c,0xfa,0xf3,0x11,0x4,0x1f,0xf5,0x2,0xf,0x1a,0x1f,0x24,0xb,0x6,0x1f,0xf3,0x6,0x0,0x2,0xe8,0xf6,0xf4,0xe8,0x7,0x2e,0xfb,0xf8,0x10,0x9,0xf0,0xe,0xff,0xfe,0x1c,0x14,0x17,0x6,0xe2,0xf1,0xfa,0x1,0x11,0x13,0x12,0x29,0xf1,0xf,0x1f,0xfa,0xfd,0xfd,0x2,0x7,0xe,0xfb,0xe,0x4,0x1,0x1,0xed,0xfe,0xde,0xfd,0x8,0xef,0xf6,0xa,0xff,0xf,0xe7,0xf2,0xf,0x2,0xea,0x10,0xf9,0xec,0xfd,0x9,0xea,0x1f,0x46,0xdd,0xe2,0xf7,0x8,0xf5,0xf7,0xe9,0x33,0xfb,0x2f,0xf6,0xb5,0x1d,0x15,0xeb,0x11,0xf7,0x2a,0x2e,0x8,0x1d,0xf4,0xfb,0x15,0xfa,0x22,0x34,0xff,0x6,0xf6,0xfd,0xfa,0xf9,0x3,0xf5,0xf4,0xf4,0xd5,0xea,0x1,0x8,0x22,0xf1,0xf2,0x6,0xd1,0xe5,0xc,0xef,0x12,0x3,0x8,0x2,0xf7,0x5,0x1b,0x7,0x39,0x34,0x21,0xe2,0xe3,0xb,0xc,0xf6,0x29,0xf7,0x24,0xa,0xfc,0xff,0x1a,0xfd,0x5,0xff,0xff,0xe,0xa,0x1a,0x9,0xfb,0x15,0x4,0x3,0xf7,0xfe,0x0,0xfc,0xfb,0x11,0xfa,0x1d,0xe,0x6,0xed,0xfc,0x23,0xd8,0xf2,0x4,0xe5,0xf,0x16,0x29,0xfe,0xf5,0xec,0xe2,0xe,0xeb,0x9,0x1d,0x11,0x5,0x11,0xe4,0x29,0x12,0x2,0x12,0x19,0xe,0x1a,0xee,0xf9,0x5,0x9,0xf5,0xfd,0x5,0x4,0xe4,0xf1,0x17,0x1,0xf2,0xfe,0xb,0xf4,0xd,0x4,0x6,0xfe,0xff,0xec,0xe9,0x0,0xff,0x3,0x3,0xfd,0xf1,0x15,0xfc,0xf3,0xff,0xfe,0x9,0xee,0x3c,0x1,0xec,0x2,0xf0,0xf6,0x20,0xeb,0x16,0x7,0x32,0xf3,0xce,0xf0,0x2,0xd4,0x11,0xe6,0x28,0xe,0xe3,0x21,0xee,0xce,0x1e,0xd9,0x23,0x26,0x6,0xfa,0xf9,0xf1,0x1,0xe6,0xb,0x7,0xdc,0x21,0xbc,0xe3,0xef,0xf8,0x12,0xfc,0xe6,0xfe,0xf5,0xd4,0x15,0xa,0x0,0x13,0xfc,0xec,0xf3,0xd6,0x1a,0xe3,0x21,0x36,0x2a,0x3,0xe9,0xe3,0xff,0x0,0x13,0x1c,0xe,0x20,0xe5,0xf5,0x24,0xb,0x20,0x14,0x13,0xf8,0x4,0x1b,0x2f,0xa,0x15,0x0,0xf4,0x1a,0x11,0xd,0x3,0x18,0xf,0x18,0x4,0x1f,0xfb,0xf2,0x1f,0x15,0x3,0xfb,0xb,0x17,0xfb,0xb,0x1b,0x1f,0xf4,0x7,0xf9,0xf9,0xf8,0xf4,0x14,0xf,0xf6,0xfe,0xdd,0xb,0xff,0x1,0x18,0x4,0x1b,0xa,0xed,0xe7,0xf9,0x16,0x2,0x1,0x0,0xf7,0xf1,0x7,0xf0,0x6,0xf8,0xb,0x2,0xf3,0xff,0x20,0xfd,0x1,0x4,0xf5,0xd9,0xf4,0xf4,0xf2,0xe8,0xff,0x4,0x0,0xf0,0xe2,0xfe,0xed,0x1b,0xef,0x20,0xfa,0xfb,0xf4,0x2,0x18,0x7,0xfb,0xef,0xe4,0x8,0xd,0xe1,0xe,0x25,0xc6,0xfd,0xc,0x1c,0xb,0xf0,0x1,0x1c,0xd4,0x11,0xf5,0x1b,0x9,0xfb,0xda,0x13,0xe3,0xf9,0x10,0x14,0xf0,0xf0,0xfd,0x1f,0xcf,0xf4,0xe4,0xfb,0xe,0xa,0x11,0xed,0xdc,0xfc,0xe6,0xf7,0xfc,0x13,0xe1,0xb,0xe4,0x4,0x11,0xee,0x21,0x14,0xe1,0x7,0xe4,0xfb,0x8,0x3,0x2b,0x27,0xf6,0xd,0x2,0x1b,0x9,0x9,0xf8,0x14,0x19,0xf,0xb,0x1,0x10,0x9,0x12,0x3,0xf5,0x18,0xf3,0xfb,0xf5,0x2,0xe,0xd,0x0,0x7,0xfc,0x18,0x25,0xb,0xf0,0xf9,0xe6,0x8,0x1,0x24,0x14,0xfa,0xed,0xe5,0x1f,0x9,0xfe,0x8,0xee,0x1a,0x1a,0x5,0x0,0xff,0xc,0xfe,0xf9,0x11,0x11,0xea,0xfe,0x8,0xf9,0xf0,0xe4,0x1,0xd,0xf1,0x0,0xb,0xea,0x19,0xea,0xf3,0xf8,0x8,0x12,0x1c,0x1f,0xfb,0xef,0xf0,0xf2,0x14,0xe1,0x3,0xfa,0xf9,0xda,0xe9,0xfc,0xf3,0xff,0x12,0x4,0xf7,0xfc,0x17,0xf,0xfc,0x29,0x3,0xe5,0xf2,0xee,0x1e,0xfa,0x4,0xed,0x25,0xf4,0xe1,0x15,0x10,0x1e,0xef,0x1c,0x4,0xde,0xe5,0x8,0x21,0xfd,0xfd,0xea,0x3,0xca,0xda,0x26,0x0,0xa,0xfd,0x5,0xf0,0xd4,0xe1,0x1a,0xe4,0xf5,0x7,0xe7,0xfa,0xdf,0xd4,0x3,0xf0,0x10,0x15,0xc,0xf4,0xed,0xe3,0xfb,0xf,0x1e,0x16,0x9,0x0,0xec,0xea,0x13,0x16,0xb,0x1,0xfb,0xff,0x0,0xfb,0x7,0x13,0x8,0xf4,0xe4,0x12,0x0,0xfb,0xfa,0xfc,0x8,0xeb,0x19,0x2,0x1c,0xe8,0x26,0xf3,0x10,0x9,0xf,0x19,0x2,0xfb,0xec,0xf7,0xe2,0xfb,0xfa,0x11,0xf3,0xb,0x8,0xff,0xd9,0xf8,0x12,0x18,0x6,0x7,0x22,0xff,0x19,0xf5,0xb,0xa,0x13,0xf2,0xfa,0x2,0x21,0xeb,0x11,0x17,0x17,0xec,0xe1,0xe,0xf7,0xe8,0xd8,0xe,0x1,0xf1,0xed,0xed,0xf0,0x9,0xf7,0xe7,0xfd,0xf0,0xf9,0xdb,0xee,0xdc,0xfb,0xf8,0xa,0xf5,0xb,0xd4,0xd7,0x8,0x6,0x18,0x6,0xc,0x13,0xfd,0x9,0x13,0x26,0x12,0xf4,0xef,0x0,0xf5,0x28,0x18,0xfe,0x4,0xe,0x21,0x1a,0xa,0x1e,0x9,0xf0,0xd,0xf,0xec,0xf3,0x17,0x22,0x0,0xec,0xe,0x1,0xe9,0x8,0x9,0xf2,0xf2,0x8,0xf0,0xb,0xd9,0x9,0x14,0xf5,0xf6,0x4,0x19,0xf4,0x11,0xe9,0xf2,0xd,0x20,0x17,0xa,0x5,0xc,0x4,0x1,0xfd,0xf4,0xfb,0x1b,0xc,0xf2,0xb,0xff,0xfe,0x1,0xd8,0xfa,0xe,0xf5,0x14,0xf9,0x1,0x4,0xf8,0xfa,0x2,0xe8,0xf9,0xf9,0xea,0xf1,0x7,0xff,0x1e,0x1,0xb,0xf7,0xa,0xf7,0xc,0xfd,0xec,0xf3,0x5,0xf8,0xda,0xb,0x15,0xf6,0xee,0xf9,0x10,0xfa,0xfe,0x8,0xf0,0xe6,0xec,0x5,0xff,0x15,0x19,0x1f,0x11,0xfc,0x9,0x8,0x1,0x6,0xfe,0x4,0x8,0xfb,0xfb,0x8,0xf4,0xf6,0x28,0x10,0xf9,0x28,0xb,0xf8,0xd,0x1,0x0,0xff,0x2,0x5,0x8,0xea,0xe9,0xf4,0xf6,0x1,0xea,0xdf,0x1f,0xfe,0xa,0xf9,0xf7,0xc,0x1b,0x6,0xed,0xf6,0xf2,0x3,0x3,0xfd,0x4,0xf5,0x10,0xa,0xb,0xf4,0xf8,0xf1,0xe7,0x5,0xfe,0xe7,0xb,0xf1,0xec,0xf4,0xec,0x6,0xee,0xde,0x5,0x1b,0xfe,0x13,0xf3,0xd9,0xea,0x4,0x10,0x5,0xed,0x15,0x2,0xb,0x10,0xfa,0x2,0x5,0xb,0x2,0x7,0xfc,0xf5,0x15,0x14,0x5,0xf7,0xc,0xfe,0xf6,0xf4,0xfa,0x6,0xfc,0x13,0xdc,0xe4,0x9,0xfa,0x2,0x23,0xec,0x6,0x11,0x13,0xf8,0xfa,0x27,0x28,0xb,0x23,0xec,0xf1,0x9,0x17,0xf,0x13,0xff,0xf2,0xfc,0xa,0xf5,0xd,0x3,0x26,0x1,0xf,0xfe,0xf1,0xfb,0xe6,0xf0,0x2,0xf2,0xff,0x2,0x11,0xff,0xfd,0x1c,0x2,0xb,0xf6,0x14,0xc,0xb,0x21,0x28,0xf0,0x11,0x5,0x6,0xed,0xf9,0xa,0xf2,0xef,0xf8,0xf1,0xfe,0xd,0xf9,0xf7,0xea,0x0,0x8,0xdb,0x2,0xf,0xfe,0x4,0xef,0x20,0x16,0x1,0xe8,0xed,0xe4,0x22,0xf6,0x19,0x0,0x4,0x1,0x13,0xeb,0xd,0xec,0x1,0x8,0x5,0xc,0xe,0xfe,0x2,0x12,0xf7,0x27,0xf9,0xfd,0x18,0xfe,0x24,0xf7,0x13,0xed,0x1e,0x9,0xff,0xd8,0xf4,0x12,0xf8,0x4,0xc,0x1c,0x11,0xfd,0x17,0x1d,0x1,0x13,0xee,0x11,0xf3,0xf8,0x6,0xf6,0x16,0xfe,0x15,0x16,0xdc,0x1f,0x0,0x25,0xee,0xff,0xf7,0xf6,0x2,0xdd,0x15,0xf1,0x14,0x8,0xe8,0xe5,0x21,0xea,0xf0,0x1a,0x7,0xea,0x8,0xea,0xe4,0x1e,0x0,0x13,0x17,0xec,0x11,0xd6,0x11,0x18,0x17,0x4,0x15,0x3,0x3a,0xd6,0x2,0x7,0x4,0xe6,0xe5,0xfe,0xe,0xff,0xed,0xfc,0xfb,0xff,0x1c,0x6,0xa,0xfb,0xf9,0xea,0x1a,0x21,0xf5,0x4,0x6,0xa,0xe3,0x16,0xea,0x4,0xe2,0xf9,0xf9,0xe6,0xfb,0xf,0xfc,0x6,0xfb,0x10,0x7,0x7,0x13,0x7,0xfc,0x16,0xef,0x7,0xdc,0x12,0x1f,0x8,0xf4,0xe9,0x14,0x6,0xf7,0xf1,0xc,0x1,0xc,0xe6,0x4,0xf3,0xf2,0xe5,0xf3,0xef,0x1d,0xf6,0x20,0x7,0xfe,0xf4,0x5,0xee,0x10,0xfd,0xe,0xb,0x2,0xd,0xd8,0x7,0xfb,0x26,0xa,0x1c,0x21,0x6,0x1f,0xf4,0x6,0x37,0x18,0xfa,0x16,0x1e,0x24,0xfb,0xf0,0x12,0xf9,0x2,0x9,0x17,0x16,0xf3,0xf9,0x17,0xf2,0x2,0xa,0x2d,0xe7,0xe3,0x25,0xf0,0xf9,0xf,0xdd,0x15,0xe6,0x4,0xfc,0xf1,0x17,0xa,0xea,0x24,0x7,0xf1,0x11,0x13,0x29,0xf4,0xc5,0xfb,0x7,0xef,0x13,0xb,0xe1,0xf1,0xeb,0xf8,0x1b,0x9,0x8,0x1f,0x15,0xf2,0x5,0x2,0xdd,0x9,0xf,0x16,0x10,0x1,0x30,0xf2,0xe0,0x27,0xfe,0xf1,0xe,0xe,0x7,0xe6,0x7,0xb,0x18,0xfe,0xf,0x1,0x7,0xf4,0x7,0x10,0xe7,0xfb,0xf3,0xf7,0xb,0xf9,0x15,0x18,0x25,0xc,0x14,0x2,0x8,0xa,0xf,0x10,0xec,0xee,0x1a,0x3,0x14,0xf,0xfa,0x25,0xff,0x18,0xd,0xb,0xea,0x1f,0x28,0x10,0xc,0xe7,0xee,0xf7,0xfa,0x3,0x15,0xc,0x1d,0x1,0x0,0x12,0xee,0x1,0xf1,0xf8,0xb,0xf3,0xfd,0x4,0xf8,0x2,0x1e,0xe,0xf3,0x2,0x10,0xfd,0x7,0xb,0x9,0x3,0x10,0x3e,0x8,0xe,0xc,0xf4,0xe7,0xfd,0x1c,0x27,0x1a,0xed,0xe1,0x8,0xdc,0xd9,0xf1,0x1e,0x7,0x12,0xf1,0x10,0xfb,0xc8,0x8,0xf,0x3,0x1d,0xdc,0x23,0x4,0xf9,0xa,0xff,0x8,0xe,0xc9,0x39,0xa,0x1,0x7,0xec,0xe0,0x5,0xe8,0x14,0xd8,0xe1,0xfa,0xd6,0xf8,0xed,0xdb,0xff,0x1d,0xf5,0x17,0xf,0x1c,0xdc,0xed,0xff,0xff,0x4,0x13,0xf5,0xe7,0xd2,0x12,0xdb,0xe1,0x13,0x11,0x23,0xe,0xf9,0x31,0xdc,0xef,0x7,0xa,0x20,0xf2,0xf9,0x13,0xff,0x1c,0x2a,0xdf,0xdb,0xe7,0x11,0xf2,0xfd,0xfb,0x28,0x0,0x15,0x3,0x2,0x20,0x7,0xf7,0x19,0x13,0x13,0xf6,0x9,0xfe,0xfd,0x20,0x14,0xf5,0xf5,0xfc,0x14,0xe,0x17,0xfe,0x15,0x4,0xf9,0xf6,0x1d,0xf6,0x1b,0xe4,0xee,0xfd,0x0,0xe9,0xee,0xce,0xf,0x20,0x5,0x2,0xd,0x6,0x5,0xf8,0xef,0xdf,0x16,0x17,0xe6,0xf1,0x10,0xf3,0x6,0x4,0xdb,0xfb,0xe7,0xf8,0x2,0x11,0xff,0xd,0xa,0xfa,0x27,0xa,0xfc,0xe8,0x11,0x17,0xf0,0xd,0xd,0xee,0xdf,0xdd,0xf1,0x15,0xd6,0xf7,0x0,0xef,0x2e,0xe6,0x24,0xfd,0xd5,0x4,0xf0,0x8,0x8,0xed,0x22,0x7,0xe1,0x9,0xd0,0xb,0x18,0xe6,0x3f,0xa,0xe5,0xe2,0xf9,0x8,0x2,0xd6,0x13,0x15,0xbd,0x0,0xe,0xf8,0xe2,0xca,0xec,0xe,0xe6,0xef,0x15,0x11,0xcb,0xdf,0xf9,0x3,0x22,0x10,0xfb,0xf9,0xe5,0x8,0xe1,0x11,0x10,0xfc,0xfa,0x0,0xf8,0x30,0xe5,0x8,0x14,0xe8,0x12,0xe2,0x4,0x19,0xb,0xfa,0x33,0xf3,0xec,0xfe,0xf8,0x25,0xf8,0x21,0x28,0xef,0x0,0xde,0xff,0x2b,0x3,0xfc,0x10,0xc,0xcf,0xfd,0x19,0xa,0xc,0xf2,0xf7,0xc,0xfd,0x2,0x1c,0xdf,0x26,0xd,0xf0,0xb,0xce,0x15,0xfb,0xec,0x27,0xf6,0xf9,0xe5,0xe2,0xfb,0xfd,0xd8,0x28,0xec,0xe9,0xf2,0xca,0x9,0x2,0x6,0xc,0xfa,0x5,0x1,0xd5,0xa,0x2,0xfb,0x4,0x17,0xdd,0xfe,0xeb,0xf1,0x9,0x10,0x12,0xff,0x0,0xe0,0x26,0xf7,0xed,0xf4,0x0,0xf2,0xfa,0x7,0x2,0xf5,0x6,0xe8,0x3,0xfd,0xdc,0xf2,0xc2,0xff,0xb,0xd6,0x25,0x4,0xe9,0xf0,0xd9,0x8,0x9,0xc5,0x23,0x12,0xf6,0x13,0x11,0xf3,0x18,0xf0,0x34,0xfe,0xfe,0xed,0xea,0x2,0x17,0xdc,0x1b,0x1b,0xea,0xfe,0xea,0xfe,0xf2,0xc4,0xfd,0x4,0xe9,0xd,0xd,0x9,0xca,0xd4,0xe1,0x4,0x1e,0xff,0xf,0xef,0xd6,0xf,0xd5,0xf8,0x26,0xd6,0x33,0xe8,0xf5,0x3b,0xf1,0xe8,0x39,0xe8,0x8,0xe5,0x1,0x2,0x4,0xf6,0x19,0xa,0xd0,0xeb,0xb,0x15,0xf7,0xe,0x23,0xf6,0xf4,0xd8,0xf4,0x17,0x23,0x25,0x14,0x1,0xd7,0xfd,0xf9,0x1f,0x1b,0x11,0xa,0x18,0xf5,0xf5,0xf,0xe0,0x2e,0x1,0xe5,0xdb,0xe2,0xf2,0x14,0xfa,0x2a,0x0,0xe2,0xea,0xfd,0xe,0xfc,0xc1,0x35,0x8,0xf6,0xf9,0xec,0x0,0x6,0x0,0xb,0xf6,0x1,0xfe,0xea,0xb,0x8,0x5,0xe4,0xea,0xd7,0xfd,0xee,0xf3,0xc,0xc,0xd,0x2,0xfd,0xee,0x17,0x10,0x13,0xfd,0x7,0x3,0xf8,0xc,0xd4,0xed,0xfe,0x7,0xf4,0xee,0xf4,0x3,0xc2,0x18,0x2c,0xd1,0x33,0xd8,0xdb,0xfa,0xed,0x10,0x1c,0xe3,0x37,0xa,0xea,0xfe,0xf6,0xef,0x20,0xed,0x32,0xf7,0xf5,0xf3,0xca,0xfd,0xa,0xcf,0xd,0x10,0xde,0x7,0x18,0x10,0xf0,0xd6,0xc,0x4,0xeb,0x1a,0xf9,0x8,0xc4,0xcb,0xe4,0xb,0x19,0xfc,0x29,0xf6,0xec,0x7,0xf3,0xed,0x2b,0xe9,0xfa,0x2,0xec,0x2b,0xf0,0xf2,0x2d,0xe8,0xed,0x0,0x12,0x13,0xed,0x1a,0x3d,0xf0,0x5,0x4,0xfc,0x13,0x10,0x1,0x40,0xf2,0x6,0x2,0xf9,0x22,0x24,0xff,0x18,0x0,0xeb,0xe8,0x14,0xf9,0x25,0xe0,0xff,0x3,0xe5,0xfd,0x8,0xea,0x2e,0xb,0x5,0xe7,0xde,0xe4,0xf5,0xea,0x3a,0xf4,0xf4,0xe7,0xed,0xec,0xf8,0xee,0x30,0xa,0xdb,0x5,0xf7,0x16,0xff,0xf7,0xfa,0x1f,0xef,0xe4,0xce,0xf8,0x13,0x4,0xf9,0x1,0xe1,0x3,0xf9,0xf9,0x8,0x4,0xfa,0xe4,0xe7,0xf7,0x28,0xfd,0xfd,0x0,0xfc,0xfb,0xef,0xa,0xec,0xc,0xa,0xd2,0x5,0xfb,0xcd,0xfb,0x9d,0xea,0x1c,0xe5,0x25,0xe8,0xea,0xb,0xf0,0xf3,0xd,0xab,0x49,0xe,0xeb,0x0,0xe2,0x3,0x29,0xe0,0x3d,0x6,0xf7,0xf8,0xcf,0xc,0x1a,0xd6,0x1f,0xef,0xfd,0xff,0xef,0xc,0xdb,0xe0,0x20,0x6,0xdf,0x1a,0xe7,0xfc,0xb2,0xd1,0xdf,0x13,0x7,0x1f,0xc,0xf7,0xde,0xa,0xdb,0xdf,0x1a,0xf5,0x29,0xd,0xeb,0x2c,0xcf,0xe,0x26,0xfe,0xef,0x4,0xf5,0x14,0x9,0x13,0x34,0xff,0xfe,0xe,0x6,0xe,0x10,0xf9,0x2a,0xb,0xe6,0xfe,0xf1,0x1a,0x36,0x29,0x29,0x5,0x5,0xd8,0x14,0x12,0x26,0xb,0x18,0xff,0xd7,0xdf,0xf,0xed,0x31,0xf7,0xfc,0xec,0xb,0xef,0xc,0xd2,0x30,0xf9,0x4,0xfe,0xef,0xe4,0xfb,0xd1,0x32,0xe5,0xee,0xf0,0xc,0xe6,0x13,0xed,0x1e,0xb,0xe4,0xe0,0xfa,0xf4,0x14,0xf4,0x18,0xf7,0xd9,0xf6,0xed,0xea,0xfc,0x6,0xfc,0xf5,0xed,0xeb,0x5,0x3,0x1b,0xb,0xff,0xb,0xef,0x1,0xf1,0x16,0x5,0x0,0xee,0xa,0xdb,0x10,0xb4,0x14,0xf,0xe1,0x1c,0xfd,0xf0,0xf8,0xc3,0x11,0x17,0xba,0x47,0x15,0xe6,0x1,0xea,0xf1,0xc,0x8,0x4a,0x15,0xf0,0xf7,0xea,0x0,0xf5,0xd4,0xf1,0xff,0xe0,0xc,0xf4,0x17,0xd8,0xea,0x3,0xff,0xd5,0x18,0xfb,0x7,0xc7,0xc9,0xdd,0xf3,0x15,0xd,0x22,0xea,0xdb,0xa,0xd6,0x9,0x1d,0xe5,0x2d,0x4,0xfc,0x35,0xc6,0xe,0x33,0xf1,0xd7,0xea,0x1,0x1b,0xe,0x1,0x2a,0xff,0xef,0xf1,0xf7,0xf,0xff,0x0,0x3b,0xe8,0xa,0xff,0xf4,0xd,0x1f,0x4,0x17,0xf7,0xdf,0xec,0x12,0x26,0x36,0x7,0xc,0x6,0xe7,0xd6,0x13,0xe3,0x30,0x9,0x0,0xf5,0xe0,0xf3,0x11,0xe2,0x38,0xd,0xf6,0x5,0xec,0x5,0x0,0xe5,0x24,0xef,0xfe,0xf8,0x0,0xd8,0x18,0xf1,0x26,0xb,0xf2,0xfc,0xe0,0xe4,0x6,0xb,0x1a,0x5,0xc6,0xf6,0xe8,0xde,0xfe,0xc,0x3,0x9,0xfe,0xe2,0x18,0x1b,0xfb,0xf7,0x6,0xf1,0xfe,0xf6,0xef,0x1b,0x7,0xd,0x1,0xa,0xed,0xf0,0xad,0x1a,0x17,0xd6,0x37,0xfd,0xd8,0xec,0xca,0xf1,0x15,0xc4,0x33,0xf1,0xed,0xf0,0xe9,0x15,0xd,0xf2,0x36,0xde,0xfd,0xe,0xfb,0x10,0xf,0xf6,0xf9,0xc,0xea,0xf0,0xe5,0xb,0xee,0xc1,0x10,0xf4,0xe8,0x1f,0xee,0x0,0xd0,0xe4,0xe7,0x13,0x7,0x27,0x12,0xea,0xea,0xf,0xea,0xf4,0x14,0xee,0xfe,0x9,0xfb,0x31,0xdb,0x1b,0x1c,0xe7,0xef,0xf5,0xf7,0x1a,0x6,0x1,0x2c,0xed,0xfb,0x4,0xfa,0x7,0x19,0xec,0x2b,0xd,0xfc,0xd8,0xfc,0xf,0x1f,0xfc,0x2d,0xf3,0xc9,0xda,0xa,0xfe,0x29,0x0,0xfa,0x9,0xe8,0xf6,0x21,0xf3,0x4a,0x1a,0xf8,0x0,0xe7,0xf0,0x21,0x1,0x22,0xf3,0x0,0xe9,0x6,0xe3,0x15,0xd7,0x3d,0xc,0x7,0xf1,0xf3,0xec,0x17,0xdf,0x29,0x1b,0xfd,0xfe,0xeb,0xed,0x17,0xf6,0x23,0xa,0xea,0xee,0xf9,0xf3,0xf,0xc,0xf8,0xf5,0xed,0xe8,0x1c,0x14,0x7,0x17,0xb,0xd,0xed,0xf7,0xed,0x10,0x7,0xd5,0xf2,0x9,0xd6,0xf7,0xb5,0xf6,0x19,0xc9,0x25,0x15,0xe8,0xf5,0xc4,0xf9,0x2a,0xb0,0x39,0xe,0x2,0x11,0xf0,0xf7,0x1d,0xeb,0x39,0x10,0x2,0x15,0xe0,0x8,0x1,0xee,0x1c,0x1e,0x8,0x4,0xf2,0x2,0xe8,0xda,0xfa,0xfb,0xe0,0xfe,0x5,0x2,0xd3,0xca,0xf4,0xec,0x10,0x16,0x5,0xd,0xd7,0x9,0xdc,0xf6,0x1e,0xf8,0x10,0xed,0xf7,0x27,0xf5,0x8,0x28,0xee,0xec,0xe0,0xf8,0x17,0xfb,0x23,0x2e,0xf1,0xfa,0xf5,0xfc,0x1a,0x10,0xf7,0x32,0xfb,0xfb,0xe8,0xf1,0x3,0x24,0xeb,0x25,0xf9,0xca,0xf1,0xfe,0x1,0x2e,0x7,0x18,0x3,0xe5,0xea,0x10,0xfa,0x3b,0x7,0xf,0x11,0x4,0xf7,0x1d,0xf1,0x24,0xd9,0x8,0xef,0x2,0xdd,0x7,0xc8,0x2c,0xd,0x6,0xec,0x17,0xda,0x21,0xdf,0x34,0xd9,0xfb,0xf2,0xf4,0xec,0xe,0xa,0xf,0xf,0xdb,0xf0,0xfb,0xe6,0xf,0x0,0x4,0xf9,0x1,0x5,0x5,0xfe,0x8,0xf3,0xe,0xf2,0xfb,0x1,0xfd,0x18,0x1d,0xf6,0xee,0x6,0xcf,0xfc,0xae,0x27,0x21,0xd2,0x33,0x3,0xe0,0xe0,0xc9,0xfb,0x3a,0xbd,0x4d,0x4,0xe8,0xf5,0xe6,0xeb,0x19,0xf2,0x4b,0x1d,0xfc,0xf7,0xd9,0xff,0xfe,0xea,0xf,0x4,0xe,0x0,0xed,0x19,0xe9,0xe9,0xff,0x11,0xef,0x14,0x1,0x17,0xbc,0xb5,0xef,0xc,0x22,0x27,0xf,0x1,0xd4,0x3,0xce,0x1,0x25,0xff,0xf9,0xf0,0xa,0x1c,0xe5,0xf,0x1c,0xee,0xf4,0xf1,0xf4,0xc,0x0,0x8,0x1c,0xf4,0xd5,0xf1,0xfc,0x1f,0x11,0x0,0x18,0x3,0xf7,0xe4,0xff,0x7,0x9,0x1a,0x18,0xff,0xea,0xec,0xfd,0x13,0x2b,0xf8,0xc,0xfa,0xdf,0xf6,0x11,0xda,0x2a,0xdc,0xfc,0xff,0xff,0xec,0x12,0xe1,0x37,0xfd,0xeb,0xfe,0xea,0xd1,0x12,0xfa,0x28,0x1a,0xd,0xf0,0xf7,0xe0,0xc,0xeb,0x35,0x14,0xeb,0x0,0xeb,0xe7,0x1b,0xfc,0x9,0x0,0xf2,0x4,0xf9,0xe5,0x1a,0xe,0x8,0x12,0xf8,0xfe,0x9,0xf,0xd,0xea,0x3,0xe1,0xfe,0xf2,0xec,0xd,0x2,0xdb,0x4,0x1d,0xd4,0x1,0xca,0x13,0x29,0xca,0x28,0x4,0xe2,0xf1,0xdb,0xb,0x2c,0xcd,0x44,0x0,0xe7,0xf4,0xd0,0x12,0x15,0xff,0x42,0x11,0x5,0xfd,0xd9,0x11,0x1c,0xf4,0x15,0xec,0xf2,0x24,0xd6,0x1d,0xec,0xda,0xf5,0xec,0xe5,0x22,0xf2,0xb,0xbd,0xd0,0xeb,0x5,0x7,0x1b,0x1,0xed,0xf5,0x2,0xcf,0x8,0x15,0xfd,0x1c,0xe5,0x4,0x19,0xc7,0x25,0x22,0xf3,0xde,0xfb,0xfb,0x20,0xf6,0xeb,0x25,0xfe,0xf5,0x8,0xf5,0x17,0xe,0x4,0x1c,0xf9,0xee,0xec,0xe1,0x6,0x12,0xff,0x2a,0x13,0xed,0xfe,0x5,0x18,0x25,0x20,0x9,0x13,0xea,0xd7,0x5,0x6,0x33,0x25,0xff,0xa,0xf0,0xea,0x17,0xe1,0x30,0xfa,0xd,0xa,0x4,0x0,0xe,0xe9,0x16,0x20,0xd,0x2,0xe8,0xed,0x7,0xe8,0x3c,0xf1,0xd9,0xfa,0xe1,0xed,0x18,0xfc,0xf0,0x9,0xe3,0x5,0xfe,0xd1,0xb,0xe,0xf5,0x25,0xfd,0xfb,0x30,0x1e,0x8,0xfc,0xc,0x21,0xea,0xfc,0xe5,0x1e,0x16,0xf5,0xf4,0xfc,0xf0,0xea,0xc4,0x21,0x27,0xe9,0x2b,0xdb,0xdb,0xec,0xe5,0xfe,0x37,0xe2,0x46,0x25,0xfa,0xec,0xe4,0xf3,0x19,0xf2,0x4c,0x6,0x0,0xfb,0xeb,0x10,0x10,0xf7,0x2a,0xf8,0xe9,0x18,0xee,0x21,0xe8,0xd5,0xf4,0xa,0xed,0x24,0xfe,0xf9,0xb2,0xbc,0xf3,0x1d,0x0,0x2f,0x7,0x8,0xe1,0xf1,0xed,0x27,0x27,0xfe,0x22,0xfd,0x2,0x20,0xd8,0x5,0x25,0xec,0xf1,0xff,0xa,0xf,0xe6,0xfe,0x46,0xfd,0xe1,0xca,0xf7,0x22,0x3,0x8,0x21,0xf5,0xf,0xf7,0xfb,0xc,0xfb,0x14,0x2d,0x3,0xe5,0xe4,0x9,0xb,0x1a,0xe6,0x1,0x28,0xe9,0xd6,0xb,0xf7,0x2c,0xfb,0x11,0xee,0xb,0xed,0x17,0xf0,0x3c,0xf5,0x8,0xfa,0xf8,0xcd,0x17,0xfa,0x39,0xea,0x11,0xf5,0xed,0xee,0xa,0xec,0x41,0xd6,0xe7,0xf9,0xfa,0xc8,0x15,0xf7,0x8,0xe,0xe3,0x8,0xe8,0xec,0xfd,0xfe,0xf1,0x0,0xe9,0xf4,0x9,0x26,0x2,0x16,0xf0,0x1,0xef,0x1,0xff,0x3,0x22,0xdb,0xfc,0xf5,0xde,0xe5,0xc4,0x1,0x28,0xd4,0x38,0x8,0xd0,0xec,0xd5,0x4,0x2f,0xce,0x4e,0xeb,0xf9,0xe7,0xdf,0xf0,0x1b,0xf5,0x42,0xf1,0xf6,0x9,0xd5,0xa,0xd,0x8,0x4,0x5,0xe2,0xe,0xd7,0x19,0xdb,0xda,0xe1,0x25,0xde,0x15,0xe,0x14,0xbd,0xb0,0xe3,0xe5,0x24,0x1e,0xf8,0xd,0xd8,0xf7,0xf2,0xff,0x18,0xf5,0x7,0xf0,0x2,0x25,0xd5,0x1e,0x2e,0xdf,0xe7,0x5,0xef,0x11,0xe8,0xe7,0x47,0xf4,0xe1,0xde,0x9,0x36,0x1a,0x11,0x11,0xf5,0x12,0xe5,0xe7,0x18,0x1,0x17,0x2a,0x3,0x5,0xea,0x9,0xb,0x12,0x4,0x17,0xf0,0xee,0xd7,0x11,0xed,0x3c,0x17,0x16,0xff,0x2,0xdc,0x21,0xf3,0x2e,0xe5,0x13,0xef,0xec,0xe2,0x10,0xd0,0x2e,0xee,0xff,0x1,0xe0,0xe5,0xb,0xda,0x1f,0xf8,0xf6,0xfb,0x7,0xdb,0x5,0xf6,0xc,0xf3,0xf0,0x10,0xf9,0xf5,0xf2,0xd,0x10,0xf7,0xf6,0xff,0x2b,0xd,0x6,0x1e,0xf3,0xc,0xe9,0x1,0xf2,0x23,0xfe,0xe9,0xdd,0x12,0xdd,0xf7,0xbb,0x22,0x1b,0xd4,0x38,0x29,0xd4,0xcf,0xf5,0xf9,0x27,0xdd,0x47,0x0,0xf2,0xe5,0x9,0xfc,0xe,0xf9,0x34,0xa,0x2,0xfd,0xec,0x25,0x1d,0x3,0x15,0x9,0xf1,0x1b,0xd0,0x17,0xda,0xda,0xe7,0x7,0xe3,0x15,0xf1,0x2,0xb9,0xce,0xe6,0xc,0x10,0x31,0xfe,0xf7,0xd9,0xfa,0xed,0xed,0x33,0xf4,0x19,0xe7,0xfe,0x3f,0xe5,0x6,0x2e,0xe6,0xf2,0xdc,0xf5,0x18,0xe6,0x1,0x2f,0xee,0xe7,0xe4,0xfe,0x2c,0x3,0xf7,0x20,0x5,0x7,0xe2,0x6,0x1e,0x5,0xed,0x2f,0x3,0xea,0xf8,0xe,0xc,0x1f,0xff,0x20,0xf4,0xe8,0xe1,0x1c,0xec,0x22,0x1e,0x5,0xfd,0xf5,0xca,0x30,0xe9,0x30,0xe4,0x14,0xff,0xf2,0xdc,0x17,0xf8,0x26,0xe1,0xb,0x1,0x11,0xc2,0x2,0xf1,0x36,0x10,0x2,0x5,0xed,0xf1,0x15,0xfa,0x17,0xf8,0xf7,0xf1,0xe8,0xd3,0xfd,0x8,0xfb,0x27,0xf5,0xf5,0x13,0x6,0xb,0xf0,0x1,0xf9,0xd7,0xe,0xec,0x12,0xfe,0xfd,0xee,0x25,0xd8,0xf1,0xb2,0x9,0x1c,0xbf,0x34,0xea,0xc8,0xea,0xdb,0xe,0x24,0xde,0x47,0xfe,0xdc,0xe0,0xf3,0x6,0x20,0xfe,0x2b,0xf6,0x18,0x14,0xcd,0x19,0x16,0xfe,0x1a,0x15,0xf8,0x11,0xf4,0x22,0xd7,0xcc,0xdd,0x15,0xdc,0x14,0xf9,0x2,0xbb,0xca,0xe3,0xf3,0xd,0x1e,0x2a,0xc,0xe4,0x5,0xe0,0x18,0x2a,0x7,0x20,0xed,0xf6,0x17,0xcf,0xf4,0x2a,0xd6,0xfb,0xce,0x3,0x37,0xe2,0xfd,0x1d,0xfb,0xe5,0xe0,0x5,0x29,0xef,0x16,0x23,0xf7,0x1,0xf4,0xc,0x14,0xff,0xee,0x31,0xf9,0x12,0xf9,0x14,0xf6,0xc,0xf6,0xb,0xf,0xd8,0xdc,0xfe,0xf,0x37,0xfa,0x1,0x9,0x4,0xd1,0xb,0xc,0x29,0xf3,0xa,0xf9,0xed,0xc2,0x18,0xf4,0x25,0x18,0xf,0x8,0xf7,0xed,0x1f,0xf7,0x4f,0xe,0xf0,0xe4,0x0,0xeb,0xfa,0x1a,0xc,0x3,0xe9,0xfc,0xf0,0xcc,0x6,0x5,0xf2,0x12,0x4,0xe2,0x16,0xa,0xa,0xf3,0xb,0xf3,0xdc,0xfd,0x10,0xfc,0xe,0xe2,0xe0,0xfe,0xf0,0xff,0xb1,0x6,0x1b,0xe4,0x30,0x13,0xc6,0xc3,0xfa,0xc,0x1e,0xd9,0x57,0x11,0xe1,0xd6,0xfa,0xee,0x1d,0xf7,0x37,0xea,0xf0,0x5,0xef,0x24,0x1e,0xf1,0x10,0xe8,0xeb,0x19,0xd1,0x18,0xf5,0xc8,0xf8,0xec,0xf5,0x1f,0xf2,0xff,0xb3,0xd2,0xe6,0xe,0x6,0x2e,0x7,0x17,0xe0,0xf5,0x2,0xf9,0x20,0x7,0x16,0x8,0xe8,0x1d,0xd3,0x8,0x34,0xda,0xf2,0xce,0xfb,0x1f,0xe1,0x0,0x2d,0xdb,0xdf,0xcc,0x5,0xfb,0xf7,0x0,0x33,0xf9,0xb,0x1,0x13,0x28,0xf8,0x7,0x24,0xf8,0xf,0x3,0xd,0xe9,0x6,0xfe,0x18,0xf9,0xed,0xf5,0xc,0xe0,0x2c,0xe,0xf9,0x6,0xfb,0xce,0x27,0xe8,0x29,0x19,0xf9,0x1,0xe,0xc8,0x25,0xed,0x30,0xeb,0x1,0xfe,0x10,0xdc,0x1e,0x0,0x1e,0x10,0xf9,0x0,0xfc,0xc8,0xe,0x4,0x13,0x4,0xf0,0x2,0xfe,0xd8,0xf,0x1b,0xf7,0xe1,0xf8,0xde,0x12,0xe2,0xef,0xa,0x2,0xe0,0xdd,0xf1,0xe,0x2a,0x25,0x15,0xeb,0x2,0xf4,0xf0,0xbf,0xfc,0x27,0xdc,0x42,0xf,0xe9,0xbf,0xe8,0x20,0x33,0xc9,0x3f,0x10,0xec,0xf3,0x3,0x2,0x2c,0x4,0x38,0x6,0xa,0xf9,0xe5,0x1c,0x3f,0xf,0xc,0x25,0xe2,0x6,0xe6,0x3,0xf4,0xd7,0xfe,0xf6,0xe7,0x2f,0xfa,0x3,0xb6,0xcb,0xf1,0x11,0xa,0x2c,0xfc,0x1e,0xe0,0xff,0xc2,0xdd,0x1d,0xf3,0x10,0xfa,0x7,0x1e,0xf6,0x20,0x7,0xe6,0xf1,0xa,0xe8,0x27,0xf1,0xf5,0x24,0xed,0xfd,0xee,0x13,0x15,0xe9,0xe2,0x22,0xe5,0xf9,0xdd,0x1d,0x32,0x4,0xfa,0x25,0x0,0xee,0xfd,0xb,0xe,0x23,0xfa,0xf,0x1,0xf8,0xf0,0x15,0xe4,0x21,0xf7,0x10,0xf9,0xe7,0xc3,0x19,0xe1,0x34,0xff,0xed,0xf4,0xef,0xd7,0x21,0x1,0x31,0xee,0xf7,0xf2,0xf3,0xe5,0xa,0xee,0x2e,0x1e,0xf2,0xc,0x7,0xc2,0x8,0xa,0x14,0x14,0x0,0xfc,0xf9,0xd6,0xfb,0xf8,0xe5,0xf1,0xfa,0xe0,0x15,0x21,0xef,0x6,0xf9,0x0,0xf5,0xf4,0xb,0xb,0x18,0x2,0xf5,0x4,0xdb,0xfd,0xcc,0x32,0x1d,0xc9,0x3b,0x12,0xd9,0xaf,0xcf,0xf,0x26,0xde,0x35,0xe4,0xdb,0xd3,0x22,0x11,0x2e,0xfb,0x36,0xfa,0xfd,0x2,0xeb,0xf,0x37,0xb,0x14,0x1d,0xdd,0x18,0xe0,0x10,0xe0,0xdf,0x14,0xf9,0xf0,0x19,0xf7,0xfb,0xc4,0xe5,0xe7,0x11,0x1,0x31,0x1a,0xf7,0xd8,0xf1,0xe9,0xf3,0x21,0xf9,0xfe,0xe4,0xe9,0x2,0xd0,0x6,0x14,0xd7,0xfc,0xec,0x6,0x10,0xfc,0xf0,0x1c,0xe7,0xec,0xe3,0x3,0x21,0xe4,0x4,0x12,0xf0,0xf3,0xed,0x16,0x36,0x2,0xfd,0x13,0x11,0xdf,0xeb,0x19,0x7,0x10,0xc,0xf9,0x8,0xf8,0xf4,0x1d,0xfd,0x1d,0x16,0xf4,0xa,0x8,0xec,0xc,0x9,0x3d,0xe0,0xb,0xee,0x10,0xd1,0x1e,0x15,0x43,0xeb,0xfa,0xf3,0x5,0xc7,0xf2,0xd9,0x25,0x20,0xee,0xe9,0xfd,0xce,0x16,0xc,0x27,0x6,0xa,0x6,0xf9,0xd6,0xb,0x5,0xe8,0x2,0xe8,0xd2,0x10,0x1,0xf2,0x15,0x9,0x4,0xd3,0xe2,0xfe,0xf0,0x32,0x1b,0xd9,0xf5,0xea,0xcc,0xcb,0x10,0x1c,0xf1,0x3b,0x2,0xd4,0xbf,0xca,0xfe,0x12,0xdb,0x3b,0xf8,0xd5,0xe7,0x13,0x10,0x1a,0xf4,0x38,0x9,0x8,0xee,0xf4,0xf4,0x3c,0xf7,0x15,0x4,0xe4,0xfa,0xf4,0x4,0xee,0xf4,0x7,0xf8,0xe9,0x3b,0xe2,0x1f,0xd5,0xed,0xe6,0xfd,0x18,0x49,0x21,0x6,0xd8,0xde,0xfa,0xf0,0x1b,0xfe,0xde,0x8,0xf7,0x14,0xc7,0xf,0x1d,0xcf,0x0,0xea,0xff,0x1b,0xd5,0x8,0xd,0xd9,0xf1,0xf4,0x16,0x23,0xd8,0xc,0x29,0xdc,0xf1,0xf2,0x21,0x49,0xfc,0xe2,0x8,0x1,0xf0,0xf8,0x17,0xf9,0xf,0xf5,0xfa,0x1a,0xef,0xec,0x9,0xeb,0x1a,0xc,0x17,0x9,0x11,0xe9,0x1a,0xf7,0x29,0xf9,0xfd,0x7,0x1,0xdd,0xa,0xec,0x22,0x15,0x3,0xfd,0xe2,0xd2,0x15,0xec,0x4d,0xd7,0xfc,0xf6,0xb,0xcc,0xe,0x4,0x3,0xf7,0xfb,0xfb,0xd,0xeb,0x19,0x7,0xf4,0xf4,0xe5,0xde,0x22,0x7,0xea,0xf7,0xeb,0x23,0xc8,0xee,0x3,0x4,0xf,0x19,0xc3,0xf8,0x6,0xd0,0xf7,0xfe,0xe,0xe7,0xa,0x2,0xb0,0xb8,0x0,0xfb,0x18,0xf,0x22,0xf7,0xe9,0xdc,0x9,0x15,0x23,0xd,0x22,0x13,0xe2,0xed,0xeb,0x18,0x20,0xb,0x12,0xfc,0x2,0xf1,0xdb,0xe,0xe1,0x4,0xdb,0xf,0xf3,0x1a,0x6,0xef,0xdb,0xdc,0xdd,0xfb,0x0,0x2a,0x20,0xfd,0xc1,0xe3,0xef,0x1,0x14,0xf2,0x14,0x0,0xf,0x28,0xd9,0xff,0xf4,0xdc,0x9,0xfa,0x1c,0x8,0xd1,0x3,0xa,0xf4,0xe4,0xdb,0x20,0x30,0xea,0x6,0x11,0xe2,0x26,0xf7,0x16,0x22,0xf9,0x7,0x2,0xf5,0xf6,0xfb,0x1d,0xc,0x16,0xa,0x7,0xf9,0x11,0xde,0x20,0x8,0x19,0x4,0xa,0xb,0xc,0xf7,0xf4,0xfc,0x41,0xf1,0xf8,0x16,0x9,0xdc,0xe,0x1a,0x2b,0x1f,0xe7,0xfe,0x1,0xe0,0xfd,0xe2,0x34,0xec,0xf3,0xf5,0x3,0xec,0xb,0xfb,0x4,0xf6,0xdd,0xfd,0x6,0x14,0xd,0xfa,0xfc,0xf1,0xa,0xca,0x1,0xec,0xe,0xe,0xec,0xd7,0xee,0xd4,0xf2,0xfe,0x16,0xfa,0xbd,0xd,0xef,0xcb,0xc4,0xee,0xed,0x13,0x10,0x19,0xf8,0xb1,0xf1,0xe3,0x0,0xf3,0xc,0xf6,0xde,0xc6,0x15,0x27,0x14,0x29,0x15,0xf6,0xf4,0xf5,0xe7,0x0,0xb,0x2f,0xc,0xef,0x3,0xf,0xfd,0x8,0xf3,0xf9,0xf9,0x5,0xd,0x34,0x15,0x1b,0xc8,0xd1,0xf2,0x1b,0xa,0x22,0x12,0x11,0xe9,0xf4,0xe1,0x2a,0x20,0x3,0xf2,0xf8,0x14,0xb,0xd0,0xf4,0xe,0xbf,0xc6,0xd8,0x4,0x5,0xf8,0xf4,0x4,0xc9,0xea,0xfd,0xf7,0xfa,0xe3,0x1b,0x11,0xde,0xc,0x11,0x25,0x29,0xe5,0x2,0xef,0xef,0x2,0xfa,0x1a,0x21,0x19,0x9,0x8,0x5,0x4,0xe5,0xfa,0xed,0x2d,0x26,0xfa,0x17,0xf6,0xe8,0x12,0x12,0x31,0xfc,0xd,0x0,0xf7,0xeb,0x19,0xf1,0x2a,0x6,0x14,0xec,0x8,0xd3,0x21,0x7,0x32,0xe3,0x2,0xb,0xfb,0xd8,0x27,0x7,0x5,0xe6,0xf5,0xf5,0xa,0xf7,0x2c,0x2a,0xd8,0x1b,0xda,0xf7,0xea,0xf6,0xf9,0xe,0xf8,0xc,0x5,0xc7,0xd6,0x6,0x12,0xe3,0xe1,0xe1,0xd8,0xdb,0xc6,0xf8,0xe6,0xfa,0xc,0x7,0xf8,0xe7,0xe1,0xf,0x0,0xf3,0x3,0xf0,0xde,0xcc,0xf5,0xfc,0xef,0x1e,0x16,0x13,0xfb,0xf4,0x3,0xe9,0xfc,0xfa,0x15,0xe8,0x15,0x9,0xf1,0xd,0xdb,0xa,0xe8,0x9,0xf5,0x1a,0x4,0xf8,0xd8,0xd4,0x4,0xee,0x25,0x29,0x9,0xfe,0xf3,0xf5,0xd4,0xa,0x15,0x19,0xf5,0x12,0xfe,0x4,0xe7,0x1,0xeb,0xde,0xbe,0xfe,0x9,0x12,0xdf,0x13,0xe0,0xef,0xc7,0xff,0x3,0x8,0xfe,0xf2,0x19,0xe0,0xe4,0xc,0x22,0x1e,0x5,0xf7,0x16,0xf2,0xf9,0x6,0x17,0xf6,0xc,0x1e,0x23,0x8,0xfe,0xdc,0xfd,0x17,0x11,0xdf,0xf5,0xf,0x1,0x3,0x8,0xee,0x1b,0x2,0xb,0x1b,0xc,0x16,0x1a,0x0,0xf,0x26,0x14,0xf8,0xf4,0xf3,0x19,0x16,0x22,0xa,0xd0,0xf9,0xf1,0x5,0x2b,0x1e,0x1e,0xef,0xf5,0x6,0x5,0xe7,0x3f,0x2a,0x6,0xf0,0x15,0x14,0x13,0x20,0x1b,0xde,0x10,0x5,0x33,0xf8,0x8,0x4,0x17,0xd,0xf,0xf6,0x1,0xed,0x28,0x25,0x1c,0x13,0xfb,0xea,0xfb,0xf3,0x1c,0xf9,0x1f,0xf0,0xfb,0x17,0xf8,0xff,0x10,0xf7,0xb,0x24,0x4,0x0,0xd,0xc,0xf7,0xa,0x16,0x13,0xf8,0x5,0xa,0xf1,0xf5,0xee,0xf8,0x14,0xe,0xed,0xfe,0x1b,0xfe,0x17,0x13,0x10,0x12,0x21,0x1c,0xfa,0xe5,0xb,0x8,0xc,0x10,0x1b,0x3,0xef,0xd,0x5,0xa,0xf0,0x4,0x11,0x15,0x0,0xfd,0xef,0x2,0x18,0xf4,0x9,0xfa,0xf6,0x2,0xf7,0xfd,0x13,0xef,0x13,0xf7,0xf9,0x17,0xf,0xfa,0xf8,0x15,0xff,0x4,0xef,0xf0,0x15,0xfa,0xfe,0xf0,0xf4,0xed,0x6,0x1c,0x2,0xfb,0xf7,0x5,0xfb,0xc,0xef,0xf4,0xf0,0xf6,0xec,0x17,0xf3,0xf5,0xef,0x2,0xfd,0xe5,0x21,0xc,0xf1,0x1e,0x8,0xf1,0xb,0xf7,0x9,0x1d,0xf2,0xf9,0xf2,0xfb,0xe,0xed,0xf8,0xfa,0xdd,0xf0,0xfd,0xdb,0x1a,0xf4,0xef,0xc,0x6,0xf,0xdf,0xe2,0x6,0x6,0xee,0xfa,0xd,0x17,0xfc,0xf9,0x15,0x1a,0xe4,0xfb,0xc,0x1a,0xfc,0x1b,0x4,0x7,0x20,0xff,0x9,0xf,0xf2,0x26,0x19,0x1f,0xd,0x2,0x16,0x3,0x3,0xfd,0x5,0x1,0x1b,0xa,0x11,0xfa,0x21,0x13,0xfb,0xc,0x5,0xf3,0xdd,0xe4,0xdc,0x22,0x1b,0x15,0x14,0xe,0xe8,0x0,0xf7,0xf8,0xf4,0xb,0xb,0xfd,0x21,0xe3,0xf,0xe1,0x22,0x1,0x21,0xb,0x1f,0x9,0x10,0xe2,0x18,0x11,0xe,0xed,0x1,0x14,0x12,0xfd,0x11,0xf6,0xe9,0x20,0xe1,0xf5,0x1b,0x27,0x22,0xfa,0xf7,0xfe,0x13,0xf6,0xdc,0x6,0xd,0xf4,0x5,0x20,0xd,0xb,0xe4,0x15,0x28,0xc,0x0,0xf5,0x7,0xc,0xa,0x6,0xe,0xf3,0xfb,0xfe,0x4,0x8,0xf4,0xef,0x3,0xe4,0xeb,0x6,0xee,0xed,0xdb,0xeb,0x1d,0xf4,0xfa,0xc,0xfc,0xfe,0x11,0xf7,0xf8,0xf5,0xef,0xe7,0xfc,0x1b,0xdc,0x17,0xfd,0xfe,0x0,0xea,0xf4,0xf1,0xf7,0xf,0x21,0x4,0xfd,0xd,0xc,0xa,0x14,0xfd,0x19,0x9,0x1,0xfd,0xe2,0xc,0xc,0xe0,0x25,0xfb,0xff,0xd,0x18,0xf6,0xb,0x19,0x12,0x10,0x9,0xb,0x6,0x12,0x1c,0x10,0x3,0x13,0xa,0x5,0xf,0x9,0x1,0x21,0xe4,0x1,0x26,0xf9,0xf4,0x5,0x19,0x0,0xff,0xb,0xff,0x16,0x9,0xe7,0xee,0xed,0xf5,0xf,0x2f,0xee,0x19,0x3,0xa,0x10,0xee,0xf7,0x2e,0xf4,0x8,0xf7,0xee,0x7,0x0,0xfc,0xe,0xf0,0x12,0x8,0x5,0xed,0x11,0xfc,0xfb,0xf7,0x25,0xf1,0x5,0xc,0xf9,0xfa,0x3,0xc,0x16,0x4,0x25,0xf8,0xe7,0xfc,0x11,0xd,0x19,0xd8,0xfa,0xb,0x6,0xfd,0xef,0x13,0xf6,0xff,0xe,0xf9,0x4,0xf1,0xdc,0xfb,0xe1,0xf6,0xb,0x15,0x7,0xf7,0x2,0xe,0xf1,0xfd,0xe3,0xeb,0x7,0xf1,0xef,0x3,0xfe,0xf8,0x7,0x10,0xf7,0x0,0xf9,0xf2,0xe,0xf9,0xf2,0x1d,0xf5,0xd8,0xff,0xe6,0x18,0x2a,0x1b,0x3,0x16,0xfe,0xf4,0xf5,0xfd,0x4,0x1,0xfe,0xfe,0x7,0xfc,0xe,0xfa,0x15,0xeb,0x2,0x15,0xea,0xfd,0x4,0xe5,0xfe,0xed,0xfe,0x1a,0x9,0x2a,0x1b,0xdf,0xfb,0xf8,0xf1,0x4,0x1a,0x34,0x7,0xf9,0xd,0xf5,0xef,0xec,0x10,0x1a,0xb,0xf,0x13,0xfe,0x10,0x22,0x1e,0x2,0xe6,0xf7,0x11,0xfa,0x11,0xfc,0x1b,0x21,0x12,0xf4,0x18,0x16,0x29,0xe4,0xc,0x2e,0x12,0x7,0x20,0xf6,0x1d,0xf4,0x12,0x33,0xf4,0xee,0xfe,0x5,0x6,0xfb,0x13,0xc,0xe,0xf0,0x0,0xf8,0xee,0xf3,0x17,0x0,0xf7,0xfb,0xfc,0xf,0xf4,0xd5,0xa,0xed,0xeb,0xf5,0xe9,0xef,0xd8,0xf0,0xf8,0xe2,0x19,0xf7,0xf8,0xa,0xb,0x9,0xfa,0xe7,0xf,0xfc,0xe8,0x2,0x0,0x1a,0xfe,0xfd,0x1b,0xe6,0xef,0xf,0xe3,0x10,0xf1,0xe2,0xb,0xe,0x6,0x29,0x0,0x1,0xf3,0x0,0x11,0x4,0xf2,0xf7,0xea,0xf8,0xe0,0x9,0xe,0x13,0xf4,0x0,0x9,0xfa,0xf5,0xc,0xff,0x18,0x8,0xd,0xfa,0xde,0xfa,0x3,0xf2,0xf3,0x1b,0xeb,0x6,0xea,0xfb,0xff,0xd,0xf5,0x10,0x17,0xf8,0xe8,0xf1,0xf1,0xf5,0x0,0x3,0xa,0x9,0xa,0xf3,0xfb,0x33,0x26,0xe7,0x17,0xe3,0xfa,0x1f,0x24,0xfc,0x7,0x2,0xe2,0xeb,0x8,0x2c,0xf8,0x2,0x1f,0x4,0xeb,0xb,0x4,0x17,0xf7,0xff,0x1c,0xed,0x0,0x3f,0xd5,0x17,0x1d,0xfe,0x3,0xf1,0x1c,0x17,0xec,0xe,0x54,0xee,0xf5,0x25,0xfa,0x8,0xee,0x13,0x32,0xe,0xd8,0x9,0xf,0xee,0xe5,0x6,0x10,0xf4,0xfb,0xe4,0xfb,0x9,0xde,0x13,0xff,0x2,0xf9,0xec,0xa,0x0,0xe9,0xfd,0xdc,0x6,0x4,0xdb,0x6,0x1,0xf8,0x9,0xe2,0xc,0x14,0xda,0xfe,0x20,0xe3,0x9,0xda,0x14,0x12,0xe1,0x5,0xff,0xf3,0x0,0x8,0xfb,0xf1,0xfd,0xf3,0x4,0xfa,0x8,0xff,0x1,0x1d,0xb,0xfd,0xa,0xf4,0xfb,0xfc,0xf9,0x19,0xed,0xfc,0xf2,0x6,0xe7,0x2,0xf6,0xc,0xfc,0xfb,0x1,0xc,0xeb,0x1b,0xff,0xff,0x8,0x1d,0xf7,0xe8,0xfc,0xf4,0xc,0xfa,0xf1,0xee,0xed,0xdd,0xfc,0x6,0x5,0xdc,0x1a,0xfc,0xf9,0x7,0xdf,0x1b,0x14,0xc,0xfc,0x1,0x16,0xe1,0xed,0x9,0x34,0xee,0xe4,0x1c,0x1b,0xfc,0x3b,0x3,0x15,0xf2,0xeb,0x14,0x0,0xdd,0x24,0x4,0xf1,0xed,0xfd,0xe6,0x32,0xf9,0x24,0x4,0xe,0x22,0x3,0x14,0x2f,0xf5,0x1a,0x37,0xf4,0x18,0x3,0xf,0x4b,0xe6,0xd,0x5c,0xf7,0x1f,0x1c,0xe6,0x23,0xc,0x15,0x4e,0xe0,0x5,0x1c,0xec,0xff,0x4,0x13,0x15,0xee,0x7,0xec,0xc,0xdd,0xf8,0xe,0x3,0xc,0x1f,0xe8,0xe,0xf5,0xec,0xfc,0xe2,0xe8,0xfb,0xf6,0x0,0xe5,0xea,0xf3,0xd3,0xf5,0xfd,0xd2,0xfd,0x1b,0xed,0x9,0xd1,0x23,0xfa,0xd4,0xf7,0xe9,0xf0,0xa,0xd6,0x14,0x3,0xe6,0x10,0xf4,0x18,0xfe,0xe1,0xb,0x25,0xf5,0xfc,0xe9,0xf2,0xe9,0xf4,0xd,0xf5,0x0,0xf9,0x17,0x2,0xfd,0x3,0x4,0xf8,0xf5,0x14,0xe3,0xd3,0xeb,0xe7,0x9,0xf3,0x14,0x17,0xee,0xe6,0xf6,0xff,0x11,0x26,0xf4,0xf7,0x2,0xfa,0x5,0x8,0x16,0xff,0xd,0xf7,0xf1,0xf7,0xe6,0xfb,0x4,0x4,0x7,0x2,0x4,0x9,0xf5,0xfc,0x5f,0xd6,0xe7,0x2a,0x23,0xf4,0x1b,0x6,0x1,0xea,0xe7,0x5,0x25,0xe3,0x25,0x7,0xea,0xfb,0xfb,0x9,0x25,0xde,0x37,0x4,0x7,0xe5,0xff,0x14,0x2f,0xa,0x30,0x23,0x4,0xf0,0x23,0xfe,0x1c,0xd2,0x2b,0x55,0x1,0xe5,0x26,0xfe,0x14,0xed,0x24,0x46,0xe6,0xee,0xf,0xfd,0xed,0xef,0xe,0x1e,0x5,0xa,0x12,0xff,0xe4,0xf5,0xc,0xed,0xfd,0xea,0xd,0x13,0x1a,0xe5,0xfc,0xc2,0xef,0xa,0xe2,0xf,0xfe,0xff,0xc,0xf0,0xff,0xdf,0xea,0x0,0xf6,0xe1,0x4,0xd8,0x26,0x20,0xdc,0xf4,0x19,0x6,0xe8,0xd2,0x10,0x4,0xf1,0x2,0xc,0x6,0xf0,0xf0,0x4,0x1f,0xf4,0xf5,0xed,0xf1,0xfa,0xf1,0x4,0x2,0xf8,0xfb,0x4,0xf1,0xe5,0xe4,0xa,0xf0,0xfe,0xef,0x1c,0xe3,0xeb,0xf3,0x0,0x17,0x1,0x13,0x19,0xda,0xf8,0x6,0xde,0x11,0xea,0xf7,0xf4,0xef,0x3,0x4,0xb,0xe8,0x8,0xe,0xe2,0xee,0xde,0x6,0xe,0x29,0xfb,0xfa,0x0,0x2,0xec,0x1b,0x52,0xff,0xde,0x3a,0x2f,0x13,0x30,0xe9,0xff,0xf6,0xe7,0x15,0x1d,0xd9,0x3c,0xf,0xe6,0x14,0xee,0x13,0x1f,0xe7,0x33,0x8,0xfc,0x6,0xc,0x8,0x19,0xd9,0x2b,0x1f,0x7,0x10,0x24,0x16,0x29,0xfc,0x31,0x4d,0xf0,0xd9,0x3f,0xf2,0x20,0xe2,0x25,0x49,0xe5,0xec,0xa,0xf5,0xf2,0xd9,0x22,0x1f,0xed,0x22,0x2,0xa,0x16,0x8,0xf7,0xfb,0xe,0xfb,0xfb,0x1d,0xf3,0x1c,0xf6,0xe1,0xcf,0x19,0xf4,0xf,0xee,0xf9,0x4,0xd1,0xf9,0xe2,0xda,0xf1,0x24,0xf5,0x7,0xdf,0x1d,0xf9,0xdb,0x18,0xb,0xea,0x8,0xca,0xf2,0xfa,0xec,0x4,0xe,0x17,0xed,0xf1,0x6,0x15,0xfc,0xfd,0x8,0xfa,0xe3,0xe4,0xa,0xfc,0xee,0x8,0xf5,0x9,0xef,0xee,0x6,0xef,0xe1,0x19,0x7,0xe8,0xe6,0xdf,0xea,0xd,0xf1,0x16,0xee,0xed,0xf8,0x9,0xfa,0xfb,0xc,0xf8,0xeb,0xda,0x0,0xfc,0x4,0xfe,0xf5,0xff,0xf6,0xe1,0xc,0xa,0x13,0xd,0xf6,0xf5,0x15,0x7,0xca,0xec,0x50,0xe,0xd0,0x26,0x4c,0xf8,0x23,0xeb,0xff,0x8,0xe3,0x11,0x2c,0xf9,0x2a,0xf1,0xe9,0xb,0xe9,0xf,0x15,0xec,0x33,0x11,0xc,0xd,0x1,0x1,0x32,0xe3,0x41,0x27,0x11,0x2,0x2e,0x7,0x9,0xe3,0x22,0x4d,0xf1,0x5,0x27,0x3,0x25,0xf5,0x2c,0x3b,0xf4,0x0,0x16,0xb,0xec,0xfe,0x17,0xd,0xff,0xe7,0xfe,0x24,0x6,0xee,0xf0,0xe9,0xfa,0x1c,0xf2,0x19,0x8,0xfa,0xff,0xd2,0x1,0x2,0xea,0x5,0xf2,0xf4,0xb,0xd2,0xf9,0xd,0xcd,0xd,0x12,0xf2,0xe,0xe1,0x1f,0x0,0xe7,0x14,0x4,0xff,0x9,0xdb,0xfc,0xd9,0x6,0xf9,0xeb,0x1,0xef,0xfa,0xfb,0xf5,0xfc,0xfb,0x14,0xe2,0xf9,0xf5,0x2,0xfd,0xfc,0x1,0xf7,0xf3,0x0,0xec,0xe7,0xf2,0x0,0xf1,0x11,0xec,0xf0,0xe9,0x11,0xa,0x7,0x4,0x1,0xee,0xfb,0xf2,0x14,0x1,0x12,0xf0,0xf2,0xf1,0xf0,0xfb,0x8,0x3,0xf8,0x1,0xe8,0xf9,0x17,0x26,0xf,0xea,0xf7,0xf8,0x1e,0xfe,0xf2,0xf8,0x3f,0x0,0xd4,0x1c,0x53,0xfe,0x1e,0xf,0xef,0xdd,0xed,0x10,0x19,0xe7,0x34,0xe,0xde,0xdf,0xfa,0xe,0x29,0xe3,0x16,0x9,0x6,0x12,0xeb,0xf9,0x32,0xe0,0x1a,0x1d,0xf3,0xed,0x10,0x7,0x31,0xf2,0x12,0x52,0xeb,0xf7,0x1e,0xf7,0x1a,0xdc,0x3e,0x33,0xe3,0xfb,0x1f,0xb,0x8,0xfe,0x13,0x1a,0xf4,0xf8,0xfe,0x8,0xfc,0xe9,0xfe,0xeb,0xe6,0xf6,0x2,0x18,0x2,0xe8,0xfb,0xf3,0x1,0x8,0xd7,0x13,0x4,0xe6,0x2,0xe6,0xd7,0x1,0xd4,0xf0,0xe,0x5,0x18,0xe5,0x8,0xe5,0xd2,0x16,0x12,0xfe,0xe,0xd3,0xfc,0x1f,0xe9,0xf8,0x11,0x6,0xf3,0xd5,0xf8,0xff,0xf0,0x4,0xa,0xd9,0xf8,0xfd,0xf5,0x12,0xff,0x6,0x1b,0xe6,0xfe,0xfe,0xde,0xee,0xf6,0x18,0xf1,0xf8,0x6,0xf3,0x2,0xea,0x4,0x14,0xfc,0xee,0xe6,0x9,0xf9,0xee,0xe3,0xe7,0xfc,0xd9,0xef,0xfc,0xa,0xc,0x3,0xf6,0xe2,0x11,0xf,0x19,0x18,0x10,0xef,0xe5,0x22,0xf5,0xe5,0xe9,0x4b,0xf7,0xdb,0xc,0x4f,0xde,0x22,0x16,0x9,0x16,0xd1,0xf8,0x19,0xe0,0x24,0xfe,0xb8,0xfb,0xe5,0x12,0x1c,0xe3,0x22,0x9,0x5,0x29,0xf7,0x10,0x31,0xe1,0x33,0x3f,0xfd,0xed,0x4,0x3,0x2e,0xed,0x30,0x36,0xee,0x16,0x2f,0xf5,0x1b,0xdc,0x3a,0x56,0xe5,0xef,0x26,0xff,0x3,0xd7,0x31,0x16,0xef,0xf1,0x8,0x13,0x1,0x2,0x3,0xf1,0xf2,0x8,0xff,0x5,0x12,0xf2,0xee,0xda,0xed,0xec,0xea,0xf7,0xc,0xf1,0x9,0xe6,0xe6,0x0,0xcc,0x10,0xd,0xd,0x20,0xf4,0x18,0x23,0xec,0xf9,0x0,0xe4,0x7,0xd4,0xfb,0x16,0xd2,0x1,0xe6,0x1,0x6,0xf0,0xfe,0x3,0xf3,0x9,0x1,0xd,0x5,0xf7,0xd4,0x2,0xfb,0xfb,0x8,0xf0,0x1f,0xf3,0xfe,0xeb,0x2,0xe,0x1b,0xf,0x4,0xf5,0xf0,0x1f,0x14,0xf7,0x6,0xdc,0xf9,0xe9,0x1,0xff,0x8,0xf2,0x6,0xff,0xff,0xf3,0x5,0x1a,0xfc,0xfa,0xeb,0xfb,0xfa,0x12,0x20,0xf6,0xe0,0xe8,0x1c,0xfa,0xd6,0xd,0x2c,0x4,0xe1,0x9,0x3b,0xd3,0x2a,0xee,0xf7,0xed,0xf1,0xf7,0xd,0xf0,0x32,0xf,0xc9,0xe,0x0,0x10,0x24,0xfb,0x31,0xf0,0xf4,0xdd,0xf5,0x4,0x25,0xc7,0x27,0x25,0x16,0x11,0x2e,0x9,0x30,0xd1,0x2c,0x34,0xe6,0xf0,0x21,0xf5,0x21,0xc8,0x40,0x39,0xde,0xf0,0x12,0xf3,0x10,0xe8,0x1f,0x18,0xfa,0xea,0x7,0x11,0xdf,0xed,0xfa,0xf0,0x7,0xef,0xf3,0x5,0x10,0xe5,0xf3,0xe9,0xe9,0xe8,0xd6,0x1,0xf9,0x5,0xb,0xee,0xf9,0x12,0xe3,0x5,0xfd,0xe6,0x16,0xe2,0x1b,0x12,0xc5,0x0,0xfd,0x2,0x4,0xd2,0xff,0xec,0xf6,0xfd,0x0,0xe4,0xf7,0xf3,0xeb,0xfa,0xf8,0xd,0x3,0xfa,0xfe,0xe4,0xdb,0xe3,0x6,0xff,0xf4,0xf2,0x1b,0xf1,0xf7,0x2,0x1,0x4,0x13,0xe5,0xc,0x5,0xf7,0xa,0x3,0x3,0xb,0x3,0xee,0xf7,0x21,0x20,0xff,0xf3,0x9,0xe5,0xff,0xec,0x17,0x0,0x6,0x14,0xeb,0xf2,0x18,0x16,0x1f,0xec,0xee,0xe1,0x1e,0x3,0xfa,0xfe,0x28,0x3,0xc9,0xc,0x3f,0xd8,0x30,0x16,0x3,0xf8,0xe9,0xfb,0x28,0xe1,0x36,0xa,0xdf,0xe5,0xeb,0x8,0x1c,0xcd,0x29,0xf2,0xfc,0xa,0xed,0x1,0x29,0xf1,0x20,0x13,0x4,0xec,0x17,0xa,0x35,0xc3,0x1a,0x46,0xe0,0xd7,0x3c,0x9,0x28,0xd1,0x22,0x20,0xd5,0xfa,0x28,0xfa,0xff,0xea,0x1d,0x23,0xe0,0x7,0x7,0xf,0xf1,0xf1,0x8,0xf0,0xf8,0xff,0x5,0x1b,0x5,0xfa,0xf0,0xfb,0xe3,0xe4,0xcc,0x1a,0xf9,0x9,0x6,0xee,0xf4,0x3,0xd0,0x14,0xf4,0xff,0x1d,0xe8,0x11,0xf4,0xd1,0xf4,0x4,0xb,0xfb,0xdc,0xa,0xc,0xeb,0xed,0x6,0xf3,0x4,0xdd,0xdf,0xf9,0xea,0xfc,0xf5,0xf2,0xfb,0xea,0xe3,0x3,0xee,0xe,0xff,0xdb,0x1e,0x4,0xf7,0x1a,0x4,0xc,0xd,0xda,0x4,0xe9,0xff,0x4,0x0,0xc,0xf9,0xe4,0xfb,0xf6,0x14,0xde,0x1b,0x0,0xb,0xfe,0x6,0xf8,0xf,0xdc,0x1,0xef,0xef,0xd,0xf8,0xf1,0xf,0xf9,0xf9,0xdf,0xd,0xe4,0xd9,0xf9,0x2b,0xee,0xe8,0x9,0x40,0xf9,0x2f,0xa,0xfa,0xe8,0xe9,0x1,0xe,0xe7,0x23,0xa,0xd0,0x19,0xd3,0xe,0x4,0xda,0x2b,0xf,0xe7,0xe6,0xf3,0xfb,0x2c,0xd3,0x36,0x19,0xe,0xfe,0x3,0x1a,0x2e,0xd0,0x23,0x32,0xf1,0xe1,0x2a,0x9,0x1b,0xf6,0x29,0x3e,0xce,0x15,0xa,0xe8,0xec,0xdf,0x44,0x28,0xd9,0xfd,0xfa,0x9,0xff,0xe7,0x8,0xec,0xf4,0xef,0x1,0x19,0x11,0xf3,0xeb,0xeb,0xed,0x1a,0xdd,0x15,0xf,0x7,0xfe,0xeb,0xff,0xd6,0xd5,0x4,0xf5,0x7,0x10,0xe6,0xc,0xe4,0xda,0xc,0x8,0xee,0x6,0xd8,0xf8,0xf1,0xe0,0x1,0x8,0xfe,0xf9,0xf3,0xdf,0x3,0xe6,0xf4,0xa,0xff,0xf2,0xe0,0xd9,0xeb,0x1,0x10,0x2,0xfc,0xd,0x14,0xea,0xf8,0x3,0x18,0xf3,0x9,0xfc,0xc,0xb,0x1f,0xf5,0x5,0xf7,0xf9,0x0,0xfd,0x4,0xfc,0x16,0x7,0x0,0xdf,0xf9,0xfa,0xc,0xfb,0xf4,0xf7,0xf0,0xeb,0x7,0x17,0x20,0xfb,0xf0,0xec,0x4,0x0,0xf8,0xf2,0x2d,0xf9,0xd9,0xb,0x55,0xec,0x33,0x26,0xf8,0xa,0xf2,0xb,0x25,0xdf,0x29,0x5,0xd1,0x14,0xe2,0xf2,0x12,0xdd,0x28,0xfc,0xec,0x8,0xfd,0x2,0x3a,0xe6,0x29,0x25,0xd,0x10,0x9,0xa,0x32,0xf5,0x17,0x2d,0xea,0xfb,0x35,0xfc,0x28,0xd0,0x29,0x2f,0xcb,0x6,0xf,0x4,0xf2,0xf3,0x34,0x1c,0xf4,0x8,0x5,0xfc,0xfd,0xed,0xf,0xf8,0xe9,0xf0,0x9,0x16,0xfe,0x2,0xff,0xd4,0xea,0xa,0xeb,0xc,0xf8,0xf4,0x9,0xf4,0xf2,0x7,0xd9,0xb,0xfd,0xe4,0x1a,0xef,0x14,0x8,0xd8,0xfc,0xf5,0xe1,0x3,0xcf,0xf1,0x11,0xdb,0x15,0x7,0x10,0xf8,0xfc,0xe2,0xf1,0xf5,0xde,0xff,0xe7,0x1,0xea,0xee,0xe9,0x2,0xa,0x18,0xec,0xfe,0xf9,0x9,0xf3,0xe,0x2,0xf1,0xfc,0xf9,0x16,0x5,0x7,0x9,0xd,0xe,0xf7,0x4,0xed,0x4,0xdb,0x4,0x4,0xf6,0xdc,0xee,0xec,0xf5,0xfe,0xf4,0x2,0xe4,0xb,0xe0,0x17,0xa,0xe0,0xf7,0xdc,0x11,0xd6,0xfe,0xfa,0x35,0xde,0xe6,0x6,0x44,0xf9,0x35,0xa,0xfb,0xff,0xec,0xfb,0x16,0xd9,0x23,0xf,0xd4,0xef,0xdf,0x6,0xb,0xd9,0x25,0xff,0xf8,0xeb,0xf4,0xa,0x20,0xe5,0x22,0x1c,0xeb,0xf4,0xd,0xc,0x19,0xe1,0x1e,0x31,0xe9,0xfb,0x20,0xf0,0x23,0xfe,0x35,0x28,0xb4,0x6,0x28,0xe7,0xfb,0xe9,0x2a,0x1a,0xef,0x15,0xc,0xed,0xf1,0x4,0xe,0xa,0xff,0x16,0x1,0x4,0x17,0xea,0xec,0xdc,0xf4,0xf7,0x4,0x16,0x1f,0xa,0x11,0xef,0x12,0xdf,0xd9,0xc,0xf5,0x10,0x2,0xf3,0x10,0x3,0xd3,0xf5,0xb,0x2,0x0,0xcb,0xf6,0x23,0xf6,0xf1,0x1f,0xf9,0xfc,0xf0,0xf6,0xfe,0xfa,0xf8,0xf9,0xf4,0xfb,0xa,0xd6,0x29,0x9,0x2,0x0,0xfc,0xfc,0xee,0xf5,0x5,0xfb,0x1e,0xf1,0xf1,0xf3,0x2,0xec,0x1c,0xc,0xe,0xb,0x4,0xf6,0xe7,0x14,0x8,0x27,0x1,0xfe,0xe5,0xe7,0x1,0x1b,0xf0,0xf6,0xff,0xf4,0xe7,0xee,0x18,0xd,0x8,0xf8,0xd6,0x7,0xf4,0x8,0xff,0x1d,0x13,0xe7,0xb,0x42,0xef,0x28,0x0,0xf9,0xf0,0xf3,0x0,0x15,0xfd,0x1a,0x22,0xc1,0xf5,0xe0,0xf8,0x9,0xe6,0xe,0x5,0xf9,0xf6,0x1,0x1,0x13,0xdc,0x1f,0xd,0xfb,0x4,0x8,0xb,0x15,0xdb,0x28,0x34,0xed,0xb,0x3a,0xed,0x16,0xe3,0x39,0x32,0xc4,0xb,0x20,0xe7,0xf7,0x2,0x35,0x24,0xfc,0xe8,0x1c,0xf8,0xf1,0xfa,0xc,0x1d,0xf2,0x5,0xff,0x12,0xf,0x1,0xec,0xea,0xf0,0x3,0xe7,0x15,0xfd,0x5,0x8,0xe0,0x1b,0xf8,0xe1,0x1e,0xed,0xdc,0x11,0xeb,0xfd,0x1a,0xeb,0x9,0xf9,0xf3,0x0,0xe8,0xe6,0x8,0xf7,0xde,0x1e,0x0,0x0,0x0,0xe4,0x9,0xf2,0xf8,0xe7,0xf2,0xd,0xfa,0xe2,0xf,0x4,0x8,0xf2,0x13,0xf8,0xf9,0xf1,0xff,0x3,0x11,0x12,0xe9,0xf4,0x13,0x7,0xc,0x13,0x2b,0xf7,0xdd,0xf9,0xe9,0xfa,0xdb,0x1d,0xf6,0xf6,0xf9,0xe4,0xf6,0xd,0xeb,0xd,0x8,0xe7,0xe7,0xf2,0x3,0x1d,0xd9,0xd8,0xe4,0xf7,0xea,0xdc,0xdc,0x26,0x2,0xee,0xfa,0x38,0xfc,0x1a,0xef,0xda,0xf1,0xdf,0xb,0x1a,0xe0,0x16,0x16,0xdc,0x4,0xfa,0xf7,0xee,0x2,0x25,0x2,0xf5,0xfb,0x8,0xf6,0x11,0xf5,0x12,0x8,0xf4,0xe3,0x1b,0xf5,0x3a,0xdc,0x20,0x2e,0xe0,0xf5,0x30,0xe4,0x9,0xf8,0x3c,0x45,0xd3,0x8,0x23,0xd8,0x9,0xe4,0x35,0x30,0xe4,0xfe,0x7,0xf6,0x5,0x1,0x5,0xff,0xf6,0xd,0x2,0xfd,0x3,0x5,0xd,0x0,0xf5,0xd6,0xcf,0x19,0x6,0xee,0xd,0xf2,0x1,0x18,0xef,0x12,0x4,0x2,0x21,0xd9,0x2,0xd,0xeb,0xe9,0x13,0x8,0x15,0xf0,0xee,0x3,0xec,0x6,0x17,0xed,0x0,0x1a,0xee,0xf2,0xfc,0x9,0xec,0xf8,0xf8,0x18,0xf4,0x13,0x4,0xf6,0x2,0xf0,0xfc,0xfe,0xe3,0x1,0xa,0x1c,0x1b,0xec,0xe,0x1,0xfb,0x8,0x11,0xf5,0x0,0x14,0xe6,0x12,0x7,0xf4,0x15,0x7,0xfc,0xfb,0xf5,0xf1,0x1,0x21,0x1,0xe9,0xe8,0xef,0xdb,0xdf,0x1f,0xa,0xdd,0xd1,0x16,0x4,0xfd,0xe1,0x24,0xf0,0xec,0xf4,0x38,0xe1,0x16,0xfd,0xe0,0xec,0xe7,0xc,0x2a,0x4,0xc,0x17,0xdc,0xe8,0xf2,0x3,0xec,0xfd,0x19,0xfe,0xf3,0xf0,0xf3,0xfb,0x18,0xdf,0x1c,0x0,0x9,0xf4,0x18,0xb,0x1f,0xf6,0x34,0x22,0xf4,0x22,0x45,0xeb,0x23,0xcf,0x32,0x34,0xf2,0xf9,0x29,0xd4,0xf7,0xb,0x38,0x2a,0x9,0xe6,0x5,0x1,0xb,0xfe,0x17,0xfb,0x0,0xeb,0x8,0xfd,0xc,0x2,0x1d,0xea,0xfa,0xb,0xeb,0x9,0xfe,0xfe,0x10,0xe0,0xf6,0x6,0xf0,0x15,0xf3,0x9,0x11,0xe4,0xf9,0x7,0xe1,0xed,0x17,0x5,0xc,0xe1,0xdb,0xf2,0xf8,0xea,0x22,0xe9,0x2,0x0,0xfd,0xe7,0xf2,0xf8,0xf9,0xfc,0xfa,0xe8,0xe8,0xeb,0xe9,0xd,0x4,0xf8,0xf8,0xf7,0xf8,0xd,0x3,0xc,0x13,0xf2,0xf,0xf9,0xe6,0xfd,0xf,0x19,0x8,0xf7,0xfa,0x1,0xf3,0x12,0x1e,0x5,0xa,0x9,0xfd,0xb,0x7,0x8,0x2,0xfc,0xd6,0xe8,0x14,0x1,0x13,0x19,0xef,0xda,0xe,0xa,0x7,0xef,0x34,0xe0,0x5,0x1e,0x4e,0xe9,0x19,0xff,0xe1,0x4,0xfb,0xe,0x11,0x5,0x1f,0x15,0xd4,0xec,0xf9,0xe7,0xf9,0xfc,0x25,0xff,0x6,0xf2,0x1,0xf6,0x2a,0x17,0x24,0x11,0xf3,0x1a,0x1f,0xfb,0x32,0xeb,0x33,0x2f,0x0,0x8,0x2c,0xf0,0x26,0xf4,0x25,0x36,0xd9,0xf1,0x1a,0xd5,0xec,0xf9,0x32,0x27,0xfc,0xf4,0xf0,0xe3,0xfa,0xc,0x16,0x17,0xfa,0xf9,0xe5,0x1f,0x1f,0xfa,0xff,0xfd,0xd,0x2,0xe9,0xe,0xf0,0x12,0x9,0xda,0x2,0xea,0xe5,0xa,0xff,0x3,0x13,0xf0,0xa,0xf9,0xe9,0xff,0x10,0xfc,0x1a,0xf3,0xf7,0xf,0xf4,0xfa,0xf4,0x5,0x10,0xa,0xdd,0x9,0xf7,0xf0,0xe5,0x7,0x7,0xfa,0x2,0xd7,0xf8,0xf7,0x1,0xfb,0xe,0xf8,0x7,0xf,0xfe,0x3,0x12,0x5,0x9,0x13,0xf8,0xdc,0xfd,0x27,0xf,0xec,0xf7,0x7,0x0,0xfc,0x12,0xf8,0xfb,0xea,0xe4,0xe9,0xe9,0xe0,0xff,0xdc,0xd6,0xeb,0xf2,0xf7,0xd,0x1b,0xe9,0xc4,0x6,0x0,0xfd,0x4,0x46,0xf9,0xe9,0x13,0x2d,0xc,0x1f,0xf8,0xd3,0xc,0x14,0x11,0x5,0xe5,0x27,0x8,0xc5,0xef,0xdf,0xdd,0x4,0xf8,0x11,0x10,0xf0,0xe7,0xfb,0x3,0x3c,0xe7,0x14,0xc,0xf4,0xf6,0x1b,0xa,0x23,0xf2,0x2d,0x1a,0x8,0xff,0x32,0xe7,0x1a,0x5,0x2b,0x34,0xf1,0xa,0x0,0xe8,0x2,0xdf,0x2c,0x2a,0x3,0xe6,0xfc,0xef,0xfc,0xe4,0x3,0x1,0x3,0xee,0xe9,0x15,0x5,0x3,0x13,0x11,0xe,0xee,0xf5,0x22,0x1b,0xe,0xfd,0xf3,0xa,0x2,0xdd,0x20,0xeb,0x6,0xf8,0xe2,0x6,0xe,0xde,0xd,0xf9,0x16,0x1c,0xc,0xe0,0xf0,0xec,0xc,0xf,0xf2,0x27,0x1d,0xde,0xe6,0xf0,0xf9,0xf0,0x2,0xa,0x7,0x6,0xf9,0xf,0xfa,0xf0,0xee,0xf1,0xf7,0xff,0x2,0xb,0xd,0x1b,0xee,0xf6,0x5,0xff,0x1c,0x17,0x4,0x5,0x17,0x0,0xff,0xd,0xf3,0x23,0x10,0xfd,0x5,0xfb,0xea,0x3,0x10,0x7,0xd7,0xf7,0xff,0xf3,0xf1,0x17,0xed,0xd3,0xcb,0x14,0x1c,0xf5,0x3,0x47,0xf6,0xf7,0xf2,0x3e,0xf2,0x22,0xf4,0xed,0xfc,0xee,0xb,0xf4,0xf1,0x25,0x10,0xd0,0xf6,0x0,0xef,0x10,0xfc,0x15,0xe5,0xdb,0xf3,0xea,0x10,0x22,0xf2,0x2b,0x11,0xf9,0xa,0xfc,0xf5,0x53,0x16,0x25,0x43,0xe0,0xe,0x13,0xfc,0x2d,0xe2,0x55,0x65,0xf4,0x8,0x1,0xdf,0xa,0x0,0x49,0x1c,0xfe,0xdf,0xef,0xf2,0xf9,0xf6,0xfd,0xff,0xf3,0x2,0xf6,0x14,0xb,0xe8,0x9,0xfc,0xfc,0xe2,0xe5,0x11,0x3,0x9,0xfb,0x6,0x10,0x1a,0xf3,0xd,0xfa,0xa,0xd5,0xf5,0x1a,0x11,0xf2,0xfc,0x1f,0xfe,0xe,0xe4,0xef,0xd7,0xee,0x6,0x1e,0x4,0x12,0x28,0xf7,0xe,0x6,0xf8,0xee,0xf0,0x1a,0x1,0xf7,0xfd,0x3,0x11,0x19,0x10,0x4,0xfb,0xd7,0xfa,0x16,0x6,0x7,0x23,0xfa,0x14,0x11,0xf1,0x12,0x10,0x4,0xe1,0xee,0xf7,0x21,0xe,0xa,0xa,0xf8,0x7,0xa,0xee,0x3,0x1f,0xfa,0xc4,0xec,0x12,0x1,0x1e,0xfd,0xf1,0xe8,0xcc,0xf4,0x17,0xff,0xdd,0x45,0x10,0xee,0xfa,0x3d,0xe7,0x27,0xdd,0xd7,0xf9,0xf4,0xf6,0x6,0xf8,0x1e,0x13,0xe7,0xe2,0xf1,0xe3,0xf3,0xf7,0x18,0x12,0xe4,0xa,0xdb,0xff,0xff,0xfe,0x20,0x9,0x0,0xf7,0x23,0xf6,0x2d,0x14,0x26,0x28,0xe5,0xff,0xf,0xe3,0x1d,0xe8,0x56,0x43,0xe7,0xfb,0xf9,0xe6,0xe9,0xe2,0x19,0x19,0x8,0xfa,0xf3,0xe5,0x23,0x7,0xf,0xf8,0xf8,0xf3,0xfc,0x11,0x2a,0x5,0xf4,0xf1,0xfa,0xfb,0xf1,0x1e,0x13,0xf,0xf9,0xf5,0xfa,0x9,0xf9,0x3,0xf0,0xf0,0xe7,0xec,0xf1,0xc,0xe6,0xee,0xf6,0x20,0xf,0xe9,0x0,0xf4,0xfe,0xf0,0x13,0xa,0x17,0x13,0xee,0x13,0xfb,0xff,0xf8,0xfd,0xf4,0xe2,0xe8,0x6,0xfc,0x14,0x3,0x17,0x0,0x3,0xe6,0xfd,0xf2,0x12,0x12,0x20,0xeb,0x10,0x2,0xf7,0x13,0xd,0x11,0xfd,0xde,0xf5,0x7,0xf3,0x4,0xff,0x6,0x5,0xfb,0xea,0xf0,0xa,0x0,0xb5,0xe8,0x1a,0x3,0xfe,0xd,0x1a,0xe7,0xc0,0xd6,0xdc,0xf6,0xf8,0x39,0xf5,0xd5,0xf8,0x22,0xfa,0x22,0x5,0xd0,0xf4,0x2d,0xfc,0x0,0xa,0x1b,0xfc,0xe6,0x9,0x14,0xfa,0x0,0x1d,0x1a,0xfd,0xf3,0x18,0xfc,0xeb,0x15,0xf5,0xe,0xa,0xf3,0xf1,0x1b,0x5,0x14,0x3,0x2d,0x27,0xfb,0x18,0x22,0xef,0xf6,0x6,0x28,0x2b,0xde,0xec,0xef,0xe8,0xd3,0xfe,0x17,0x12,0x1,0x13,0x5,0xf7,0x0,0xde,0xf3,0xe5,0x3,0xfb,0x7,0xb,0xfd,0xdc,0xdf,0x3,0xc,0x0,0xfa,0x6,0xe,0x2,0x5,0xfa,0xfd,0xed,0x9,0xc,0xfd,0xfb,0xc,0xf0,0xe4,0x4,0xd6,0xf3,0x9,0xa,0xf9,0xf8,0xe2,0xef,0xdf,0xf0,0xf8,0x3,0xf,0x20,0xf4,0xe3,0xf8,0x2,0xe2,0xe5,0x25,0xf,0xeb,0xf8,0xe9,0xfd,0x4,0xc,0xc,0xfe,0x1,0x8,0xfc,0xfc,0x1b,0x1,0xe5,0x13,0xf9,0xe8,0x7,0x20,0xfe,0x6,0xec,0xfe,0x9,0xef,0x14,0x4,0xb,0xf5,0xe7,0xff,0xa,0x2,0x9,0xe9,0xc4,0x16,0xd,0xe7,0x15,0x14,0xf1,0xd0,0xec,0xe7,0xf0,0xf0,0x33,0x5,0xda,0xf2,0xb,0x8,0x38,0x1,0x7,0xfd,0xd8,0x6,0xd9,0xf0,0x16,0x1f,0xff,0xf7,0xe0,0xd8,0xf3,0xf7,0x12,0x8,0xe,0x5,0xf6,0x3,0xef,0x1b,0x12,0xf4,0xe8,0xf,0x2,0xfd,0xf2,0x16,0x26,0x22,0xe0,0x7,0xf7,0xe6,0xeb,0x16,0x22,0x1a,0xb,0x1,0xf5,0xea,0xd2,0x22,0xf,0x13,0x15,0x8,0xf0,0xfb,0xed,0x11,0xf3,0xe9,0xff,0xde,0xa,0x18,0xf,0x2,0xfb,0xf9,0xfb,0xe8,0x12,0x18,0x1,0xf4,0xf6,0xf8,0xf0,0x1f,0x24,0x15,0xf5,0x0,0x1c,0xf9,0x1,0xa,0x11,0xd5,0x1,0x12,0x2,0xec,0xfd,0x7,0xf2,0xea,0xf9,0xff,0xf7,0xfb,0x15,0xec,0xe5,0x1,0xeb,0x5,0xf9,0x10,0xfe,0x28,0xe5,0xa,0xeb,0x1b,0xe,0xf9,0xde,0x2,0x15,0xa,0xff,0xfe,0x11,0x24,0x3,0xf8,0x0,0x8,0xfd,0xe,0xeb,0xf3,0xf6,0xf7,0x14,0xe,0xfc,0xf5,0xde,0xf5,0x0,0x0,0x0,0x0,0x8e,0xfe,0xff,0xff,0x4,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0xab,0x1,0x0,0x0,0xfa,0xfd,0xff,0xff,0xa2,0xff,0xff,0xff,0xba,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0xfc,0xff,0xff,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x54,0x4f,0x43,0x4f,0x20,0x43,0x6f,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,0x2e,0x0,0x1,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x24,0xfb,0xff,0xff,0x68,0x1,0x0,0x0,0x5c,0x1,0x0,0x0,0x50,0x1,0x0,0x0,0x4,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xf4,0x0,0x0,0x0,0x90,0x0,0x0,0x0,0x48,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xce,0xff,0xff,0xff,0x0,0x0,0x0,0x9,0x3,0x0,0x0,0x0,0x1c,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1a,0xff,0xff,0xff,0x0,0x0,0x80,0x3f,0x1,0x0,0x0,0x0,0x9,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x18,0x0,0x8,0x0,0xc,0x0,0x10,0x0,0x7,0x0,0x14,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x1,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xc4,0xfc,0xff,0xff,0x1,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x16,0x0,0x0,0x0,0x8,0x0,0xc,0x0,0x7,0x0,0x10,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x38,0x0,0x0,0x0,0x2c,0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x14,0x0,0x0,0x0,0x8,0x0,0xc,0x0,0x10,0x0,0x7,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x2,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x1a,0x0,0x8,0x0,0xc,0x0,0x10,0x0,0x7,0x0,0x14,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x11,0x2,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x2c,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x8,0x0,0x4,0x0,0x6,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xff,0xff,0xff,0xff,0x31,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x5,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x9,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0x34,0x4,0x0,0x0,0xcc,0x3,0x0,0x0,0x4c,0x3,0x0,0x0,0xdc,0x2,0x0,0x0,0x60,0x2,0x0,0x0,0x20,0x2,0x0,0x0,0xb0,0x1,0x0,0x0,0x44,0x1,0x0,0x0,0x70,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2,0xfc,0xff,0xff,0x0,0x0,0x0,0x9,0x44,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xf4,0xfb,0xff,0xff,0x14,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0x0,0x0,0x80,0x3b,0xe,0x0,0x0,0x0,0x6c,0x61,0x62,0x65,0x6c,0x73,0x5f,0x73,0x6f,0x66,0x74,0x6d,0x61,0x78,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x1a,0x0,0x8,0x0,0x7,0x0,0xc,0x0,0x10,0x0,0x14,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x9,0xb4,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x94,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x12,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0xc,0x0,0x12,0x0,0x0,0x0,0x50,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x11,0x1e,0x23,0x3a,0x9e,0xa1,0x15,0x39,0x23,0x69,0x45,0x3a,0x9,0xe4,0xe4,0x39,0x65,0xd7,0x13,0x3a,0xe0,0xb2,0xfd,0x39,0x1b,0xc1,0x53,0x3a,0xc2,0x50,0x2d,0x3a,0x12,0x0,0x0,0x0,0x66,0x69,0x72,0x73,0x74,0x5f,0x77,0x65,0x69,0x67,0x68,0x74,0x73,0x2f,0x72,0x65,0x61,0x64,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x3a,0xfd,0xff,0xff,0x0,0x0,0x0,0x9,0x54,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x2c,0xfd,0xff,0xff,0x14,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xb5,0xfa,0xfa,0x39,0x1f,0x0,0x0,0x0,0x66,0x69,0x6e,0x61,0x6c,0x5f,0x66,0x63,0x5f,0x77,0x65,0x69,0x67,0x68,0x74,0x73,0x2f,0x72,0x65,0x61,0x64,0x2f,0x74,0x72,0x61,0x6e,0x73,0x70,0x6f,0x73,0x65,0x0,0x2,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xa0,0xf,0x0,0x0,0xa2,0xfd,0xff,0xff,0x0,0x0,0x0,0x9,0x58,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x44,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x74,0xfe,0xff,0xff,0x30,0x0,0x0,0x0,0x24,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xf2,0xdd,0xbb,0x3d,0x1,0x0,0x0,0x0,0x32,0xa3,0x25,0x41,0x1,0x0,0x0,0x0,0xf6,0xa0,0x50,0xc1,0x5,0x0,0x0,0x0,0x61,0x64,0x64,0x5f,0x31,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xe,0xfe,0xff,0xff,0x0,0x0,0x0,0x2,0x2c,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x4,0x0,0x4,0x0,0x4,0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x52,0x65,0x73,0x68,0x61,0x70,0x65,0x5f,0x32,0x2f,0x73,0x68,0x61,0x70,0x65,0x0,0x1,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x4a,0xfe,0xff,0xff,0x0,0x0,0x0,0x9,0x5c,0x0,0x0,0x0,0x5,0x0,0x0,0x0,0x44,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1c,0xff,0xff,0xff,0x30,0x0,0x0,0x0,0x24,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x50,0x50,0xd0,0x3d,0x1,0x0,0x0,0x0,0x0,0x80,0xcf,0x41,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9,0x0,0x0,0x0,0x52,0x65,0x73,0x68,0x61,0x70,0x65,0x5f,0x32,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x31,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc2,0xfe,0xff,0xff,0x0,0x0,0x0,0x9,0x58,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x94,0xff,0xff,0xff,0x2c,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0x50,0x50,0xd0,0x3d,0x1,0x0,0x0,0x0,0x0,0x80,0xcf,0x41,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x9,0x0,0x0,0x0,0x52,0x65,0x73,0x68,0x61,0x70,0x65,0x5f,0x31,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xa8,0x7,0x0,0x0,0x2e,0xff,0xff,0xff,0x0,0x0,0x0,0x9,0x60,0x0,0x0,0x0,0x9,0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0xc,0x0,0x14,0x0,0x4,0x0,0x8,0x0,0xc,0x0,0x10,0x0,0xc,0x0,0x0,0x0,0x2c,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1,0x0,0x0,0x0,0x3a,0x6a,0xac,0x3d,0x1,0x0,0x0,0x0,0xd0,0xbd,0xab,0x41,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x52,0x65,0x6c,0x75,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x19,0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0xaa,0xff,0xff,0xff,0x0,0x0,0x0,0x2,0x44,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2c,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x9c,0xff,0xff,0xff,0x18,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x96,0x8,0x29,0x38,0xb,0x0,0x0,0x0,0x4d,0x61,0x74,0x4d,0x75,0x6c,0x5f,0x62,0x69,0x61,0x73,0x0,0x1,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x18,0x0,0x8,0x0,0x7,0x0,0xc,0x0,0x10,0x0,0x14,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0xa0,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x88,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0xc,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x8,0x0,0xc,0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x9a,0xbb,0x84,0x38,0x83,0x84,0x73,0x37,0x5b,0xa3,0xa0,0x38,0x16,0x41,0x3a,0x38,0xc7,0x9a,0x70,0x38,0xed,0x70,0x4e,0x38,0x54,0x4f,0xac,0x38,0xfd,0x7,0x8d,0x38,0xb,0x0,0x0,0x0,0x43,0x6f,0x6e,0x76,0x32,0x44,0x5f,0x62,0x69,0x61,0x73,0x0,0x1,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x4c,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x1c,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0xe6,0xff,0xff,0xff,0x0,0x0,0x0,0x19,0x2,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x6,0x0,0x5,0x0,0x6,0x0,0x0,0x0,0x0,0x16,0xa,0x0,0xe,0x0,0x7,0x0,0x0,0x0,0x8,0x0,0xa,0x0,0x0,0x0,0x0,0x0,0x0,0x9,0x4,0x0,0x0,0x0,0x0,0x0,0xa,0x0,0xc,0x0,0x7,0x0,0x0,0x0,0x8,0x0,0xa,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x3,0x0,0x0,0x0}; diff --git a/src/audio/tensorflow/micro_speech_quantized_model_data.h b/src/audio/tensorflow/micro_speech_quantized_model_data.h new file mode 100644 index 000000000000..3babbb703d36 --- /dev/null +++ b/src/audio/tensorflow/micro_speech_quantized_model_data.h @@ -0,0 +1,4 @@ +#include <cstdint> + +constexpr unsigned int g_micro_speech_quantized_model_data_size = 18800; +extern const unsigned char g_micro_speech_quantized_model_data[]; diff --git a/src/audio/tensorflow/speech.cc b/src/audio/tensorflow/speech.cc new file mode 100644 index 000000000000..82ffdf698141 --- /dev/null +++ b/src/audio/tensorflow/speech.cc @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. + +#include <algorithm> +#include <cstdint> +#include <iterator> + +#include "tensorflow/lite/core/c/common.h" +#include "tensorflow/lite/micro/micro_interpreter.h" +#include "tensorflow/lite/micro/micro_log.h" +#include "tensorflow/lite/micro/micro_mutable_op_resolver.h" +#include "tensorflow/lite/micro/testing/micro_test.h" +#include "speech.h" + +// hard code the model today +#include "micro_speech_quantized_model_data.h" + +// The following values are derived from values used during model training. +// If you change the way you preprocess the input, update all these constants. +//constexpr int kAudioSampleFrequency = TFLM_SAMPLE_RATE; +static constexpr int kFeatureSize = TFLM_FEATURE_SIZE; +static constexpr int kFeatureCount = TFLM_FEATURE_COUNT; +static constexpr int kFeatureElementCount = TFLM_FEATURE_ELEM_COUNT; + +// Arena size is a guesstimate, followed by use of +// MicroInterpreter::arena_used_bytes() on both the AudioPreprocessor and +// MicroSpeech models and using the larger of the two results. +static constexpr size_t kArenaSize = 28584; // xtensa p6 +alignas(16) static uint8_t g_arena[kArenaSize]; + +// type for features +using Features = int8_t[kFeatureCount][kFeatureSize]; + +// inference +static const tflite::Model *model; +static TfLiteTensor *input; +static TfLiteTensor *output; +static tflite::MicroInterpreter *interpreter; + +using MicroSpeechOpResolver = tflite::MicroMutableOpResolver<4>; +static MicroSpeechOpResolver *op_resolver; + +// Adding more kernels is quite efficient. TODO add more +int RegisterOps(MicroSpeechOpResolver *op_resolver) { + TF_LITE_ENSURE_STATUS(op_resolver->AddReshape()); + TF_LITE_ENSURE_STATUS(op_resolver->AddFullyConnected()); + TF_LITE_ENSURE_STATUS(op_resolver->AddDepthwiseConv2D()); + TF_LITE_ENSURE_STATUS(op_resolver->AddSoftmax()); + return 0; +} + +int TF_InitOps(struct tf_classify *tfc) +{ + op_resolver = new MicroSpeechOpResolver(); + if (RegisterOps(op_resolver) != 0) { + tfc->error = "register ops failed"; + return -EINVAL; + } + + // create the interpreter + interpreter = new tflite::MicroInterpreter(model, *op_resolver, + g_arena, kArenaSize); + + // and allocate the tensors + if (interpreter->AllocateTensors() != kTfLiteOk) { + tfc->error = "interpreter tensor allocate failed"; + delete interpreter; + delete op_resolver; + interpreter = nullptr; + op_resolver = nullptr; + return -EINVAL; + } + + return 0; +} + +static int Init_Interpreter(struct tf_classify *tfc) +{ + input = interpreter->input(0); + if (!input){ + tfc->error = "input interpreter NULL"; + return -EINVAL; + } + + // check input shape is compatible with our feature data size + if (kFeatureElementCount != input->dims->data[input->dims->size - 1]){ + tfc->error = "input interpreter shape incompatible"; + return -EINVAL; + } + + output = interpreter->output(0); + if (!output){ + tfc->error = "output interpreter NULL"; + return -EINVAL; + } + + // check output shape is compatible with our number of prediction categories + if (tfc->categories != output->dims->data[output->dims->size - 1]) { + tfc->error = "output shape != categories"; + return -EINVAL; + } + + return 0; +} + +int TF_SetModel(struct tf_classify *tfc, unsigned char *model_tflite) +{ + // ignore passed in model today until we can load via binary kcontrol + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + model = tflite::GetModel(g_micro_speech_quantized_model_data); + if (model->version() != TFLITE_SCHEMA_VERSION) { + tfc->error = "failed to load model"; + return -EINVAL; + } + + return 0; +} + +int TF_ProcessClassify(struct tf_classify *tfc) +{ + Features *features = reinterpret_cast<Features *>(tfc->audio_features); + int ret; + + // initialise the interpreter for current feature block + ret = Init_Interpreter(tfc); + if (!ret) + return ret; + + float output_scale = output->params.scale; + int output_zero_point = output->params.zero_point; + + // copy features to input then invoke() + std::copy_n(features[0][0], kFeatureElementCount, + tflite::GetTensorData<int8_t>(input)); + + // run the interpreter + if (interpreter->Invoke() != kTfLiteOk) { + tfc->error = "invoke failed"; + return -EINVAL; + } + + // Dequantize output values + for (int i = 0; i < tfc->categories; i++) { + tfc->predictions[i] = + (tflite::GetTensorData<int8_t>(output)[i] - output_zero_point) * + output_scale; + } + +return 0; +} diff --git a/src/audio/tensorflow/speech.h b/src/audio/tensorflow/speech.h new file mode 100644 index 000000000000..7b45022e3564 --- /dev/null +++ b/src/audio/tensorflow/speech.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. + +#ifndef __TFLM_SPEECH_H__ +#define __TFLM_SPEECH_H__ + +#include "tensorflow/lite/core/c/common.h" + +/* default model configuration */ +#define TFLM_SAMPLE_RATE 16000 +#define TFLM_FEATURE_SIZE 40 +#define TFLM_FEATURE_COUNT 49 +#define TFLM_FEATURE_ELEM_COUNT (TFLM_FEATURE_SIZE * TFLM_FEATURE_COUNT) +#define TFLM_FEATURE_STRIDE_MS 20 +#define TFLM_FEATURE_DURATION_MS 30 + +#define TFLM_CATEGORY_COUNT 4 +#define TFLM_CATEGORY_DATA {"silence", "unknown", "yes", "no",} +struct tf_classify { + int8_t *audio_features; + size_t audio_data_size; + int categories; + const char *error; + float predictions[TFLM_CATEGORY_COUNT]; +}; + +/* Export of C++ APIs into C namespace for linkage */ +#ifdef __cplusplus +extern "C" +{ +#endif + + /* 1st - pass in tflite flatbuffer formatted model, size is included in + * model metadata. + */ + int TF_SetModel(struct tf_classify *tfc, unsigned char *model); + + /* 2nd - register the kernels and init TF micro for inference */ + int TF_InitOps(struct tf_classify *tfc); + + /* 3rd - perform the inference */ + int TF_ProcessClassify(struct tf_classify *tfc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/audio/tensorflow/tflm-classify.c b/src/audio/tensorflow/tflm-classify.c new file mode 100644 index 000000000000..827f6711bc41 --- /dev/null +++ b/src/audio/tensorflow/tflm-classify.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/pipeline.h> +#include <sof/ipc/msg.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <module/module/llext.h> +#include <rtos/init.h> +#include <rtos/panic.h> +#include <rtos/string.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/ut.h> +#include <user/eq.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "speech.h" + +SOF_DEFINE_REG_UUID(tflmcly); +LOG_MODULE_REGISTER(tflmcly, CONFIG_SOF_LOG_LEVEL); +EXPORT_SYMBOL(tflmcly_uuid); +EXPORT_SYMBOL(log_const_tflmcly); + +static const char * const prediction[] = TFLM_CATEGORY_DATA; + +struct tflm_comp_data { + struct comp_data_blob_handler *model_handler; + struct tf_classify tfc; +}; + +__cold static int tflm_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *cfg = &md->cfg; + struct tflm_comp_data *cd; + size_t bs = cfg->size; + int ret; + + assert_can_be_cold(); + + comp_info(dev, "entry"); + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + md->private = cd; + + /* Handler for configuration data */ + cd->model_handler = mod_data_blob_handler_new(mod); + if (!cd->model_handler) { + comp_err(dev, "mod_data_blob_handler_new() failed."); + ret = -ENOMEM; + goto fail; + } + + /* Get configuration data and reset DRC state */ + ret = comp_init_data_blob(cd->model_handler, bs, cfg->data); + if (ret < 0) { + comp_err(dev, "comp_init_data_blob() failed."); + goto fail; + } + + /* hard coded atm */ + cd->tfc.categories = TFLM_CATEGORY_COUNT; + + /* set default model for the moment*/ + ret = TF_SetModel(&cd->tfc, NULL); + if (!ret) { + comp_err(dev, "failed to set model"); + goto fail; + } + + /* initialise ops */ + ret = TF_InitOps(&cd->tfc); + if (!ret) { + comp_err(dev, "failed to init ops"); + goto fail; + } + + return ret; + +fail: + /* Passing NULL pointer to free functions is Ok */ + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); + return ret; +} + +__cold static int tflm_free(struct processing_module *mod) +{ + struct tflm_comp_data *cd = module_get_private_data(mod); + + assert_can_be_cold(); + + mod_data_blob_handler_free(mod, cd->model_handler); + mod_free(mod, cd); + return 0; +} + +__cold static int tflm_set_config(struct processing_module *mod, uint32_t param_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 tflm_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + assert_can_be_cold(); + + comp_dbg(dev, "entry"); + + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + comp_info(dev, "bytes control"); + ret = comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, + fragment_size); + + /* TODO: now load the model from the blob */ + + return ret; +} + +#if DEBUG + +/* The first feature for no and yes used in tflm_speech example */ + +int8_t expected_feature_no[TFLM_FEATURE_SIZE] = { + 126, 103, 124, 102, 124, 102, 123, 100, 118, 97, 118, 100, 118, 98, + 121, 100, 121, 98, 117, 91, 96, 74, 54, 87, 100, 87, 109, 92, + 91, 80, 64, 55, 83, 74, 74, 78, 114, 95, 101, 81, +}; + +int8_t expected_feature_yes[TFLM_FEATURE_SIZE] = { + 124, 105, 126, 103, 125, 101, 123, 100, 116, 98, 115, 97, 113, 90, + 91, 82, 104, 96, 117, 97, 121, 103, 126, 101, 125, 104, 126, 104, + 125, 101, 116, 90, 81, 74, 80, 71, 83, 76, 82, 71, +}; +#endif + +/* + * This expects features from 16kHz mono 16 bit input stream. + * + * Features must be processed using the following flow + * https://github.com/tensorflow/tflite-micro/blob/main/tensorflow/lite/micro/examples/micro_speech/images/audio_preprocessor_int8.png + * 1. Preprocess the audio data using MFCC to generate the features + * 2. Run the features through the model + * 3. Print the model output predictions + * + * Each call TF_ProcessClassify() needs 1470ms of audio features or + * TFLM_FEATURE_COUNT (49) features. We iterate over the feature count + * and increment starting feature one by one (a 30ms stride) and re + * call TF_ProcessClassify() until we have less than TFLM_FEATURE_COUNT + * features in the input buffer. + */ + +static int tflm_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 tflm_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct audio_stream *source = input_buffers[0].data; + struct audio_stream *sink = output_buffers[0].data; + int features = input_buffers[0].size; + int ret; + + comp_dbg(dev, "entry"); + + /* Window size is TFLM_FEATURE_ELEM_COUNT and we increment + * by TFLM_FEATURE_SIZE until buffer empty. + */ + while (features >= TFLM_FEATURE_ELEM_COUNT) { + cd->tfc.audio_features = source->r_ptr; + cd->tfc.audio_data_size = TFLM_FEATURE_ELEM_COUNT; + ret = TF_ProcessClassify(&cd->tfc); + if (!ret) { + comp_err(dev, "classify failed %s.", + cd->tfc.error); + return ret; + } + + /* debug - dump the output */ + for (int i = 0; i < cd->tfc.categories; i++) { + comp_dbg(dev, "tf: predictions %1.3f %s", + cd->tfc.predictions[i], prediction[i]); + } + + /* calc new free and available after moving onto next feature */ + module_update_buffer_position(&input_buffers[0], + &output_buffers[0], TFLM_FEATURE_SIZE); + features = input_buffers[0].size; + } + + return ret; +} + +static int tflm_reset(struct processing_module *mod) +{ + //struct tflm_comp_data *cd = module_get_private_data(mod); + + return 0; +} + +static const struct module_interface tflmcly_interface = { + .init = tflm_init, +// .prepare = tflm_prepare, + .process_audio_stream = tflm_process, + .set_configuration = tflm_set_config, +// .get_configuration = tflm_get_config, + .reset = tflm_reset, + .free = tflm_free +}; + +DECLARE_TR_CTX(tflm_tr, SOF_UUID(tflmcly_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(tflmcly_interface, tflmcly_uuid, tflm_tr); +SOF_MODULE_INIT(tflmcly, sys_comp_module_tflmcly_interface_init); + +#if CONFIG_COMP_TENSORFLOW_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("TFLMCLY", &tflmcly_interface, 1, SOF_REG_UUID(tflmcly), 40); + +SOF_LLEXT_BUILDINFO; + +#endif diff --git a/src/audio/tensorflow/tflmcly.toml b/src/audio/tensorflow/tflmcly.toml new file mode 100644 index 000000000000..1c88bff533ee --- /dev/null +++ b/src/audio/tensorflow/tflmcly.toml @@ -0,0 +1,22 @@ + +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # TFLM Classifier module config + [[module.entry]] + name = "TFLMCLY" + uuid = UUIDREG_STR_TFLMCLY + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/tone.c b/src/audio/tone.c deleted file mode 100644 index f91532d6a567..000000000000 --- a/src/audio/tone.c +++ /dev/null @@ -1,733 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component.h> -#include <sof/audio/format.h> -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/list.h> -#include <sof/math/trig.h> -#include <sof/platform.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <ipc/control.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/tone.h> -#include <user/trace.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* Convert float frequency in Hz to Q16.16 fractional format */ -#define TONE_FREQ(f) Q_CONVERT_FLOAT(f, 16) - -/* Convert float gain to Q1.31 fractional format */ -#define TONE_GAIN(v) Q_CONVERT_FLOAT(v, 31) - -/* Set default tone amplitude and frequency */ -#define TONE_AMPLITUDE_DEFAULT TONE_GAIN(0.1) /* -20 dB */ -#define TONE_FREQUENCY_DEFAULT TONE_FREQ(997.0) -#define TONE_NUM_FS 13 /* Table size for 8-192 kHz range */ - -static const struct comp_driver comp_tone; - -/* 04e3f894-2c5c-4f2e-8dc1-694eeaab53fa */ -DECLARE_SOF_UUID("tone", tone_uuid, 0x04e3f894, 0x2c5c, 0x4f2e, - 0x8d, 0xc1, 0x69, 0x4e, 0xea, 0xab, 0x53, 0xfa); - -/* 2*pi/Fs lookup tables in Q1.31 for each Fs */ -static const int32_t tone_fs_list[TONE_NUM_FS] = { - 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, - 64000, 88200, 96000, 176400, 192000 -}; - -static const int32_t tone_pi2_div_fs[TONE_NUM_FS] = { - 1686630, 1223858, 843315, 611929, 562210, 421657, 305965, - 281105, 210829, 152982, 140552, 76491, 70276 -}; - -/* tone component private data */ - -struct tone_state { - int mute; - int32_t a; /* Current amplitude Q1.31 */ - int32_t a_target; /* Target amplitude Q1.31 */ - int32_t ampl_coef; /* Amplitude multiplier Q2.30 */ - int32_t c; /* Coefficient 2*pi/Fs Q1.31 */ - int32_t f; /* Frequency Q16.16 */ - int32_t freq_coef; /* Frequency multiplier Q2.30 */ - int32_t fs; /* Sample rate in Hertz Q32.0 */ - int32_t ramp_step; /* Amplitude ramp step Q1.31 */ - int32_t w; /* Angle radians Q4.28 */ - int32_t w_step; /* Angle step Q4.28 */ - uint32_t block_count; - uint32_t repeat_count; - uint32_t repeats; /* Number of repeats for tone (sweep steps) */ - uint32_t sample_count; - uint32_t samples_in_block; /* Samples in 125 us block */ - uint32_t tone_length; /* Active length in 125 us blocks */ - uint32_t tone_period; /* Active + idle time in 125 us blocks */ -}; - -struct comp_data { - uint32_t period_bytes; - uint32_t channels; - uint32_t frame_bytes; - uint32_t rate; - struct tone_state sg[PLATFORM_MAX_CHANNELS]; - void (*tone_func)(struct comp_dev *dev, struct audio_stream *sink, - uint32_t frames); -}; - -static int32_t tonegen(struct tone_state *sg); -static void tonegen_control(struct tone_state *sg); -static void tonegen_update_f(struct tone_state *sg, int32_t f); - -/* - * Tone generator algorithm code - */ - -static inline void tone_circ_inc_wrap(int32_t **ptr, int32_t *end, size_t size) -{ - if (*ptr >= end) - *ptr = (int32_t *)((size_t)*ptr - size); -} - -static void tone_s32_default(struct comp_dev *dev, struct audio_stream *sink, - uint32_t frames) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int32_t *dest = (int32_t *)sink->w_ptr; - int i; - int n; - int n_wrap_dest; - int n_min; - int nch = cd->channels; - - n = frames * nch; - while (n > 0) { - n_wrap_dest = (int32_t *)sink->end_addr - dest; - n_min = (n < n_wrap_dest) ? n : n_wrap_dest; - /* Process until wrap or completed n */ - while (n_min > 0) { - n -= nch; - n_min -= nch; - for (i = 0; i < nch; i++) { - tonegen_control(&cd->sg[i]); - *dest = tonegen(&cd->sg[i]); - dest++; - } - } - tone_circ_inc_wrap(&dest, sink->end_addr, sink->size); - } -} - -static int32_t tonegen(struct tone_state *sg) -{ - int64_t sine; - int64_t w; - - /* sg->w is angle in Q4.28 radians format, sin() returns Q1.31 */ - /* sg->a is amplitude as Q1.31 */ - sine = - q_mults_32x32(sin_fixed(sg->w), sg->a, - Q_SHIFT_BITS_64(31, 31, 31)); - - /* Next point */ - w = (int64_t)sg->w + sg->w_step; - sg->w = (w > PI_MUL2_Q4_28) - ? (int32_t)(w - PI_MUL2_Q4_28) : (int32_t)w; - - if (sg->mute) - return 0; - else - return (int32_t)sine; /* Q1.31 no saturation need */ -} - -static void tonegen_control(struct tone_state *sg) -{ - int64_t a; - int64_t p; - - /* Count samples, 125 us blocks */ - sg->sample_count++; - if (sg->sample_count < sg->samples_in_block) - return; - - sg->sample_count = 0; - if (sg->block_count < INT32_MAX) - sg->block_count++; - - /* Fade-in ramp during tone */ - if (sg->block_count < sg->tone_length) { - if (sg->a == 0) - sg->w = 0; /* Reset phase to have less clicky ramp */ - - if (sg->a > sg->a_target) { - a = (int64_t)sg->a - sg->ramp_step; - if (a < sg->a_target) - a = sg->a_target; - - } else { - a = (int64_t)sg->a + sg->ramp_step; - if (a > sg->a_target) - a = sg->a_target; - } - sg->a = (int32_t)a; - } - - /* Fade-out ramp after tone*/ - if (sg->block_count > sg->tone_length) { - a = (int64_t)sg->a - sg->ramp_step; - if (a < 0) - a = 0; - - sg->a = (int32_t)a; - } - - /* New repeated tone, update for frequency or amplitude sweep */ - if ((sg->block_count > sg->tone_period) && - (sg->repeat_count + 1 < sg->repeats)) { - sg->block_count = 0; - if (sg->ampl_coef > 0) { - sg->a_target = - sat_int32(q_multsr_32x32(sg->a_target, - sg->ampl_coef, Q_SHIFT_BITS_64(31, 30, 31))); - sg->a = (sg->ramp_step > sg->a_target) - ? sg->a_target : sg->ramp_step; - } - if (sg->freq_coef > 0) { - /* f is Q16.16, freq_coef is Q2.30 */ - p = q_multsr_32x32(sg->f, sg->freq_coef, - Q_SHIFT_BITS_64(16, 30, 16)); - tonegen_update_f(sg, (int32_t)p); /* No saturation */ - } - sg->repeat_count++; - } -} - -/* Set sine amplitude */ -static inline void tonegen_set_a(struct tone_state *sg, int32_t a) -{ - sg->a_target = a; -} - -/* Repeated number of beeps */ -static void tonegen_set_repeats(struct tone_state *sg, uint32_t r) -{ - sg->repeats = r; -} - -/* The next functions support zero as shortcut for defaults to get - * make a nicer API without need to remember the neutral steady - * non-swept tone settings. - */ - -/* Multiplication factor for frequency as Q2.30 for logarithmic change */ -static void tonegen_set_freq_mult(struct tone_state *sg, int32_t fm) -{ - sg->freq_coef = (fm > 0) ? fm : ONE_Q2_30; /* Set freq mult to 1.0 */ -} - -/* Multiplication factor for amplitude as Q2.30 for logarithmic change */ -static void tonegen_set_ampl_mult(struct tone_state *sg, int32_t am) -{ - sg->ampl_coef = (am > 0) ? am : ONE_Q2_30; /* Set ampl mult to 1.0 */ -} - -/* Tone length in samples, this is the active length of tone */ -static void tonegen_set_length(struct tone_state *sg, uint32_t tl) -{ - sg->tone_length = (tl > 0) ? tl : INT32_MAX; /* Count rate 125 us */ -} - -/* Tone period in samples, this is the length including the pause after beep */ -static void tonegen_set_period(struct tone_state *sg, uint32_t tp) -{ - sg->tone_period = (tp > 0) ? tp : INT32_MAX; /* Count rate 125 us */ -} - -/* Tone ramp parameters: - * step - Value that is added or subtracted to amplitude. A zero or negative - * number disables the ramp and amplitude is immediately modified to - * final value. - */ - -static inline void tonegen_set_linramp(struct tone_state *sg, int32_t step) -{ - sg->ramp_step = (step > 0) ? step : INT32_MAX; -} - -static inline int32_t tonegen_get_f(struct tone_state *sg) -{ - return sg->f; -} - -static inline int32_t tonegen_get_a(struct tone_state *sg) -{ - return sg->a_target; -} - -static inline void tonegen_mute(struct tone_state *sg) -{ - sg->mute = 1; -} - -static inline void tonegen_unmute(struct tone_state *sg) -{ - sg->mute = 0; -} - -static void tonegen_update_f(struct tone_state *sg, int32_t f) -{ - int64_t w_tmp; - int64_t f_max; - - /* Calculate Fs/2, fs is Q32.0, f is Q16.16 */ - f_max = Q_SHIFT_LEFT((int64_t)sg->fs, 0, 16 - 1); - f_max = (f_max > INT32_MAX) ? INT32_MAX : f_max; - sg->f = (f > f_max) ? f_max : f; - /* Q16 x Q31 -> Q28 */ - w_tmp = q_multsr_32x32(sg->f, sg->c, Q_SHIFT_BITS_64(16, 31, 28)); - w_tmp = (w_tmp > PI_Q4_28) ? PI_Q4_28 : w_tmp; /* Limit to pi Q4.28 */ - sg->w_step = (int32_t)w_tmp; -} - -static void tonegen_reset(struct tone_state *sg) -{ - sg->mute = 1; - sg->a = 0; - sg->a_target = TONE_AMPLITUDE_DEFAULT; - sg->c = 0; - sg->f = TONE_FREQUENCY_DEFAULT; - sg->w = 0; - sg->w_step = 0; - - sg->block_count = 0; - sg->repeat_count = 0; - sg->repeats = 0; - sg->sample_count = 0; - sg->samples_in_block = 0; - - /* Continuous tone */ - sg->freq_coef = ONE_Q2_30; /* Set freq multiplier to 1.0 */ - sg->ampl_coef = ONE_Q2_30; /* Set ampl multiplier to 1.0 */ - sg->tone_length = INT32_MAX; - sg->tone_period = INT32_MAX; - sg->ramp_step = ONE_Q1_31; /* Set lin ramp modification to max */ -} - -static int tonegen_init(struct tone_state *sg, int32_t fs, int32_t f, int32_t a) -{ - int idx; - int i; - - sg->a_target = a; - sg->a = (sg->ramp_step > sg->a_target) ? sg->a_target : sg->ramp_step; - - idx = -1; - sg->mute = 1; - sg->fs = 0; - - /* Find index of current sample rate and then get from lookup table the - * corresponding 2*pi/Fs value. - */ - for (i = 0; i < TONE_NUM_FS; i++) { - if (fs == tone_fs_list[i]) - idx = i; - } - - if (idx < 0) { - sg->w_step = 0; - return -EINVAL; - } - - sg->fs = fs; - sg->c = tone_pi2_div_fs[idx]; /* Store 2*pi/Fs */ - sg->mute = 0; - tonegen_update_f(sg, f); - - /* 125us as Q1.31 is 268435, calculate fs * 125e-6 in Q31.0 */ - sg->samples_in_block = - (int32_t) q_multsr_32x32(fs, 268435, Q_SHIFT_BITS_64(0, 31, 0)); - - return 0; -} - -/* - * End of algorithm code. Next the standard component methods. - */ - -static struct comp_dev *tone_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) -{ - struct comp_dev *dev; - struct sof_ipc_comp_tone *tone; - struct sof_ipc_comp_tone *ipc_tone = (struct sof_ipc_comp_tone *)comp; - struct comp_data *cd; - int i; - int ret; - - comp_cl_info(&comp_tone, "tone_new()"); - - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_tone)); - if (!dev) - return NULL; - dev->drv = drv; - - dev->size = COMP_SIZE(struct sof_ipc_comp_tone); - - tone = COMP_GET_IPC(dev, sof_ipc_comp_tone); - ret = memcpy_s(tone, sizeof(*tone), ipc_tone, - sizeof(struct sof_ipc_comp_tone)); - assert(!ret); - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); - cd->tone_func = tone_s32_default; - - cd->rate = ipc_tone->sample_rate; - - /* Reset tone generator and set channels volumes to default */ - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - tonegen_reset(&cd->sg[i]); - - dev->state = COMP_STATE_READY; - return dev; -} - -static void tone_free(struct comp_dev *dev) -{ - struct tone_data *td = comp_get_drvdata(dev); - - comp_info(dev, "tone_free()"); - - rfree(td); - rfree(dev); -} - -/* set component audio stream parameters */ -static int tone_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *sourceb; - struct comp_buffer *sinkb; - uint32_t flags = 0; - - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - comp_info(dev, "tone_params(), config->frame_fmt = %u", - config->frame_fmt); - - /* Tone supports only S32_LE PCM format atm */ - if (config->frame_fmt != SOF_IPC_FRAME_S32_LE) - return -EINVAL; - - buffer_lock(sourceb, &flags); - buffer_lock(sinkb, &flags); - - sourceb->stream.frame_fmt = config->frame_fmt; - sinkb->stream.frame_fmt = config->frame_fmt; - - /* calculate period size based on config */ - cd->period_bytes = dev->frames * - audio_stream_frame_bytes(&sourceb->stream); - - buffer_unlock(sinkb, flags); - buffer_unlock(sourceb, flags); - - return 0; -} - -static int tone_cmd_get_value(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int max_size) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int j; - - comp_info(dev, "tone_cmd_get_value()"); - - if (cdata->cmd == SOF_CTRL_CMD_SWITCH) { - for (j = 0; j < cdata->num_elems; j++) { - cdata->chanv[j].channel = j; - cdata->chanv[j].value = !cd->sg[j].mute; - comp_info(dev, "tone_cmd_get_value(), j = %u, cd->sg[j].mute = %u", - j, cd->sg[j].mute); - } - } - return 0; -} - -static int tone_cmd_set_value(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int j; - uint32_t ch; - bool val; - - if (cdata->cmd == SOF_CTRL_CMD_SWITCH) { - comp_info(dev, "tone_cmd_set_value(), SOF_CTRL_CMD_SWITCH"); - for (j = 0; j < cdata->num_elems; j++) { - ch = cdata->chanv[j].channel; - val = cdata->chanv[j].value; - comp_info(dev, "tone_cmd_set_value(), SOF_CTRL_CMD_SWITCH, ch = %u, val = %u", - ch, val); - if (ch >= PLATFORM_MAX_CHANNELS) { - comp_err(dev, "tone_cmd_set_value() error: ch >= PLATFORM_MAX_CHANNELS"); - return -EINVAL; - } - - if (val) - tonegen_unmute(&cd->sg[ch]); - else - tonegen_mute(&cd->sg[ch]); - - } - } else { - comp_err(dev, "tone_cmd_set_value() error: invalid cdata->cmd"); - return -EINVAL; - } - - return 0; -} - -static int tone_cmd_set_data(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_ctrl_value_comp *compv; - int i; - uint32_t ch; - uint32_t val; - - comp_info(dev, "tone_cmd_set_data()"); - - switch (cdata->cmd) { - case SOF_CTRL_CMD_ENUM: - comp_info(dev, "tone_cmd_set_data(), SOF_CTRL_CMD_ENUM, cdata->index = %u", - cdata->index); - compv = (struct sof_ipc_ctrl_value_comp *)cdata->data->data; - for (i = 0; i < (int)cdata->num_elems; i++) { - ch = compv[i].index; - val = compv[i].svalue; - comp_info(dev, "tone_cmd_set_data(), SOF_CTRL_CMD_ENUM, ch = %u, val = %u", - ch, val); - switch (cdata->index) { - case SOF_TONE_IDX_FREQUENCY: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_FREQUENCY"); - tonegen_update_f(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_AMPLITUDE: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_AMPLITUDE"); - tonegen_set_a(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_FREQ_MULT: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_FREQ_MULT"); - tonegen_set_freq_mult(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_AMPL_MULT: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_AMPL_MULT"); - tonegen_set_ampl_mult(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_LENGTH: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_LENGTH"); - tonegen_set_length(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_PERIOD: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_PERIOD"); - tonegen_set_period(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_REPEATS: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_REPEATS"); - tonegen_set_repeats(&cd->sg[ch], val); - break; - case SOF_TONE_IDX_LIN_RAMP_STEP: - comp_info(dev, "tone_cmd_set_data(), SOF_TONE_IDX_LIN_RAMP_STEP"); - tonegen_set_linramp(&cd->sg[ch], val); - break; - default: - comp_err(dev, "tone_cmd_set_data() error: invalid cdata->index"); - return -EINVAL; - } - } - break; - default: - comp_err(dev, "tone_cmd_set_data() error: invalid cdata->cmd"); - return -EINVAL; - } - - return 0; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int tone_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = data; - int ret = 0; - - comp_info(dev, "tone_cmd()"); - - switch (cmd) { - case COMP_CMD_SET_DATA: - ret = tone_cmd_set_data(dev, cdata); - break; - case COMP_CMD_SET_VALUE: - ret = tone_cmd_set_value(dev, cdata); - break; - case COMP_CMD_GET_VALUE: - ret = tone_cmd_get_value(dev, cdata, max_data_size); - break; - } - - return ret; -} - -static int tone_trigger(struct comp_dev *dev, int cmd) -{ - comp_info(dev, "tone_trigger()"); - - return comp_set_state(dev, cmd); -} - -/* copy and process stream data from source to sink buffers */ -static int tone_copy(struct comp_dev *dev) -{ - struct comp_buffer *sink; - struct comp_data *cd = comp_get_drvdata(dev); - uint32_t free; - uint32_t flags = 0; - - comp_dbg(dev, "tone_copy()"); - - /* tone component sink buffer */ - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - buffer_lock(sink, &flags); - free = sink->stream.free; - buffer_unlock(sink, flags); - - /* Test that sink has enough free frames. Then run once to maintain - * low latency and steady load for tones. - */ - if (free >= cd->period_bytes) { - /* create tone */ - cd->tone_func(dev, &sink->stream, dev->frames); - buffer_writeback(sink, cd->period_bytes); - - /* calc new free and available */ - comp_update_buffer_produce(sink, cd->period_bytes); - - return dev->frames; - } - - return 0; -} - -static int tone_prepare(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sourceb; - int32_t f; - int32_t a; - int ret; - int i; - - comp_info(dev, "tone_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; - - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - - cd->channels = sourceb->stream.channels; - comp_info(dev, "tone_prepare(), cd->channels = %u, cd->rate = %u", - cd->channels, cd->rate); - - for (i = 0; i < cd->channels; i++) { - f = tonegen_get_f(&cd->sg[i]); - a = tonegen_get_a(&cd->sg[i]); - if (tonegen_init(&cd->sg[i], cd->rate, f, a) < 0) { - comp_set_state(dev, COMP_TRIGGER_RESET); - return -EINVAL; - } - } - - return 0; -} - -static int tone_reset(struct comp_dev *dev) -{ - - struct comp_data *cd = comp_get_drvdata(dev); - int i; - - comp_info(dev, "tone_reset()"); - - /* Initialize with the defaults */ - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - tonegen_reset(&cd->sg[i]); - - comp_set_state(dev, COMP_TRIGGER_RESET); - - return 0; -} - -static const struct comp_driver comp_tone = { - .type = SOF_COMP_TONE, - .uid = SOF_UUID(tone_uuid), - .ops = { - .new = tone_new, - .free = tone_free, - .params = tone_params, - .cmd = tone_cmd, - .trigger = tone_trigger, - .copy = tone_copy, - .prepare = tone_prepare, - .reset = tone_reset, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_tone_info = { - .drv = &comp_tone, -}; - -static void sys_comp_tone_init(void) -{ - comp_register(platform_shared_get(&comp_tone_info, - sizeof(comp_tone_info))); -} - -DECLARE_MODULE(sys_comp_tone_init); diff --git a/src/audio/tone/CMakeLists.txt b/src/audio/tone/CMakeLists.txt new file mode 100644 index 000000000000..58f22ec6c59e --- /dev/null +++ b/src/audio/tone/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_COMP_TONE STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/tone_llext) + add_dependencies(app tone) +else() + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof tone.c tone-ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof tone.c tone-ipc4.c) + endif() +endif() diff --git a/src/audio/tone/Kconfig b/src/audio/tone/Kconfig new file mode 100644 index 000000000000..8cb6f7302497 --- /dev/null +++ b/src/audio/tone/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_TONE + tristate "Tone component" + default m if LIBRARY_DEFAULT_MODULAR + default y + depends on COMP_MODULE_ADAPTER + depends on IPC_MAJOR_4 + select CORDIC_FIXED + help + Select for Tone component. This component is used to generate + audio tones (sine waves) at specified frequencies when the Tone + mode is enabled. The two other modes it supports are silence where + it generates 0s and passthrough where the input is passed to the + output. Warning: This component is untested with IPC_MAJOR_3 and + is unavailable. diff --git a/src/audio/tone/README.md b/src/audio/tone/README.md new file mode 100644 index 000000000000..e2435c2e2b3a --- /dev/null +++ b/src/audio/tone/README.md @@ -0,0 +1,13 @@ +# Tone Generator Architecture + +This directory contains the Tone component. + +## Overview + +Synthesizes simple sine-waves or beep sequences, generally used for internal testing, diagnostics, or system alert sounds. + +## Configuration and Scripts + +- **Kconfig**: Controls compilation inclusion via `COMP_TONE` acting securely on top of the generic `COMP_MODULE_ADAPTER` and `IPC_MAJOR_4`. Depends on the `CORDIC_FIXED` library for sine approximations. +- **CMakeLists.txt**: Links `tone.c` to respective system-level pipelines (`tone-ipc3.c` or `tone-ipc4.c`) and allows execution seamlessly as a zephyr `llext`. +- **tone.toml**: Describes module structure mappings assigning `UUIDREG_STR_TONE` up to multi-instance capacities. diff --git a/src/audio/tone/llext/CMakeLists.txt b/src/audio/tone/llext/CMakeLists.txt new file mode 100644 index 000000000000..39b0894a013a --- /dev/null +++ b/src/audio/tone/llext/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2025 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("tone" + SOURCES ../tone.c ../tone-ipc4.c + LIB openmodules +) diff --git a/src/audio/tone/llext/llext.toml.h b/src/audio/tone/llext/llext.toml.h new file mode 100644 index 000000000000..20f5940c3555 --- /dev/null +++ b/src/audio/tone/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../tone.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/tone/tone-ipc3.c b/src/audio/tone/tone-ipc3.c new file mode 100644 index 000000000000..b2f153696c20 --- /dev/null +++ b/src/audio/tone/tone-ipc3.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/trig.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/tone.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include "tone.h" + +SOF_DEFINE_REG_UUID(tone); +LOG_MODULE_DECLARE(tone, CONFIG_SOF_LOG_LEVEL); + +static const struct comp_driver comp_tone; + +static struct comp_dev *tone_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev; + const struct ipc_config_tone *ipc_tone = spec; + struct comp_data *cd; + int i; + + comp_cl_info(&comp_tone, "tone_new()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) { + comp_free_device(dev); + return NULL; + } + + comp_set_drvdata(dev, cd); + cd->tone_func = tone_s32_default; + + cd->rate = ipc_tone->sample_rate; + + /* Reset tone generator and set channels volumes to default */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + tonegen_reset(&cd->sg[i]); + + dev->state = COMP_STATE_READY; + return dev; +} + +static void tone_free(struct comp_dev *dev) +{ + struct tone_data *td = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + + rfree(td); + comp_free_device(dev); +} + +/* set component audio stream parameters */ +static int tone_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *sourceb, *sinkb; + + sourceb = comp_dev_get_first_data_producer(dev); + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } + + comp_info(dev, "config->frame_fmt = %u", + dev->ipc_config.frame_fmt); + + /* Tone supports only S32_LE PCM format atm */ + if (dev->ipc_config.frame_fmt != SOF_IPC_FRAME_S32_LE) + return -EINVAL; + + audio_stream_set_frm_fmt(&sourceb->stream, dev->ipc_config.frame_fmt); + audio_stream_set_frm_fmt(&sinkb->stream, dev->ipc_config.frame_fmt); + + /* calculate period size based on config */ + cd->period_bytes = dev->frames * + audio_stream_frame_bytes(&sourceb->stream); + + return 0; +} + +#if CONFIG_IPC_MAJOR_3 +static int tone_cmd_get_value(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, int max_size) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int j; + + comp_info(dev, "entry"); + + if (cdata->type != SOF_CTRL_TYPE_VALUE_CHAN_GET) { + comp_err(dev, "wrong cdata->type: %u", + cdata->type); + return -EINVAL; + } + + if (cdata->cmd == SOF_CTRL_CMD_SWITCH) { + for (j = 0; j < cdata->num_elems; j++) { + cdata->chanv[j].channel = j; + cdata->chanv[j].value = !cd->sg[j].mute; + comp_info(dev, "j = %u, cd->sg[j].mute = %u", + j, cd->sg[j].mute); + } + } + return 0; +} + +static int tone_cmd_set_value(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int j; + uint32_t ch; + bool val; + + if (cdata->type != SOF_CTRL_TYPE_VALUE_CHAN_SET) { + comp_err(dev, "wrong cdata->type: %u", + cdata->type); + return -EINVAL; + } + + if (cdata->cmd == SOF_CTRL_CMD_SWITCH) { + comp_info(dev, "SOF_CTRL_CMD_SWITCH"); + for (j = 0; j < cdata->num_elems; j++) { + ch = cdata->chanv[j].channel; + val = cdata->chanv[j].value; + comp_info(dev, "SOF_CTRL_CMD_SWITCH, ch = %u, val = %u", + ch, val); + if (ch >= PLATFORM_MAX_CHANNELS) { + comp_err(dev, "ch >= PLATFORM_MAX_CHANNELS"); + return -EINVAL; + } + + if (val) + tonegen_unmute(&cd->sg[ch]); + else + tonegen_mute(&cd->sg[ch]); + } + } else { + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } + + return 0; +} + +static int tone_cmd_set_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct sof_ipc_ctrl_value_comp *compv; + int i; + uint32_t ch; + uint32_t val; + + comp_info(dev, "entry"); + + if (cdata->type != SOF_CTRL_TYPE_VALUE_COMP_SET) { + comp_err(dev, "wrong cdata->type: %u", + cdata->type); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_info(dev, "SOF_CTRL_CMD_ENUM, cdata->index = %u", + cdata->index); + compv = (struct sof_ipc_ctrl_value_comp *)ASSUME_ALIGNED(&cdata->data->data, 4); + + for (i = 0; i < (int)cdata->num_elems; i++) { + ch = compv[i].index; + val = compv[i].svalue; + comp_info(dev, "SOF_CTRL_CMD_ENUM, ch = %u, val = %u", + ch, val); + switch (cdata->index) { + case SOF_TONE_IDX_FREQUENCY: + comp_info(dev, "SOF_TONE_IDX_FREQUENCY"); + tonegen_update_f(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_AMPLITUDE: + comp_info(dev, "SOF_TONE_IDX_AMPLITUDE"); + tonegen_set_a(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_FREQ_MULT: + comp_info(dev, "SOF_TONE_IDX_FREQ_MULT"); + tonegen_set_freq_mult(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_AMPL_MULT: + comp_info(dev, "SOF_TONE_IDX_AMPL_MULT"); + tonegen_set_ampl_mult(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_LENGTH: + comp_info(dev, "SOF_TONE_IDX_LENGTH"); + tonegen_set_length(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_PERIOD: + comp_info(dev, "SOF_TONE_IDX_PERIOD"); + tonegen_set_period(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_REPEATS: + comp_info(dev, "SOF_TONE_IDX_REPEATS"); + tonegen_set_repeats(&cd->sg[ch], val); + break; + case SOF_TONE_IDX_LIN_RAMP_STEP: + comp_info(dev, "SOF_TONE_IDX_LIN_RAMP_STEP"); + tonegen_set_linramp(&cd->sg[ch], val); + break; + default: + comp_err(dev, "invalid cdata->index"); + return -EINVAL; + } + } + break; + default: + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } + + return 0; +} + +/* used to pass standard and bespoke commands (with data) to component */ +static int tone_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, "entry"); + + switch (cmd) { + case COMP_CMD_SET_DATA: + ret = tone_cmd_set_data(dev, cdata); + break; + case COMP_CMD_SET_VALUE: + ret = tone_cmd_set_value(dev, cdata); + break; + case COMP_CMD_GET_VALUE: + ret = tone_cmd_get_value(dev, cdata, max_data_size); + break; + } + + return ret; +} +#endif + +static int tone_trigger(struct comp_dev *dev, int cmd) +{ + comp_info(dev, "entry"); + + return comp_set_state(dev, cmd); +} + +/* copy and process stream data from source to sink buffers */ +static int tone_copy(struct comp_dev *dev) +{ + struct comp_buffer *sink; + struct comp_data *cd = comp_get_drvdata(dev); + uint32_t free; + int ret = 0; + + comp_dbg(dev, "entry"); + + /* tone component sink buffer */ + sink = comp_dev_get_first_data_consumer(dev); + free = audio_stream_get_free_bytes(&sink->stream); + + /* Test that sink has enough free frames. Then run once to maintain + * low latency and steady load for tones. + */ + if (free >= cd->period_bytes) { + /* create tone */ + cd->tone_func(dev, &sink->stream, dev->frames); + buffer_stream_writeback(sink, cd->period_bytes); + + /* calc new free and available */ + comp_update_buffer_produce(sink, cd->period_bytes); + + ret = dev->frames; + } + + return ret; +} + +static int tone_prepare(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *sourceb; + int32_t f; + int32_t a; + int ret; + int i; + + comp_info(dev, "entry"); + + 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; + + sourceb = comp_dev_get_first_data_producer(dev); + if (!sourceb) { + comp_err(dev, "no source buffer"); + return -ENOTCONN; + } + + cd->channels = audio_stream_get_channels(&sourceb->stream); + comp_info(dev, "cd->channels = %u, cd->rate = %u", + cd->channels, cd->rate); + + for (i = 0; i < cd->channels; i++) { + f = tonegen_get_f(&cd->sg[i]); + a = tonegen_get_a(&cd->sg[i]); + if (tonegen_init(&cd->sg[i], cd->rate, f, a) < 0) { + comp_set_state(dev, COMP_TRIGGER_RESET); + return -EINVAL; + } + } + + return 0; +} + +static int tone_reset(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int i; + + comp_info(dev, "entry"); + + /* Initialize with the defaults */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + tonegen_reset(&cd->sg[i]); + + comp_set_state(dev, COMP_TRIGGER_RESET); + + return 0; +} + +DECLARE_TR_CTX(tone_tr, SOF_UUID(tone_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_tone = { + .type = SOF_COMP_TONE, + .uid = SOF_RT_UUID(tone_uuid), + .tctx = &tone_tr, + .ops = { + .create = tone_new, + .free = tone_free, + .params = tone_params, +#if CONFIG_IPC_MAJOR_3 + .cmd = tone_cmd, +#endif + .trigger = tone_trigger, + .copy = tone_copy, + .prepare = tone_prepare, + .reset = tone_reset, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_tone_info = { + .drv = &comp_tone, +}; + +UT_STATIC void sys_comp_tone_init(void) +{ + comp_register(platform_shared_get(&comp_tone_info, + sizeof(comp_tone_info))); +} + +DECLARE_MODULE(sys_comp_tone_init); +SOF_MODULE_INIT(tone, sys_comp_tone_init); diff --git a/src/audio/tone/tone-ipc4.c b/src/audio/tone/tone-ipc4.c new file mode 100644 index 000000000000..30d99058a3d6 --- /dev/null +++ b/src/audio/tone/tone-ipc4.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/trig.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/tone.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <ipc4/base-config.h> +#include <sof/audio/sink_api.h> +#include "tone.h" + +SOF_DEFINE_REG_UUID(tone); +LOG_MODULE_DECLARE(tone, CONFIG_SOF_LOG_LEVEL); + +static int tone_init(struct processing_module *mod) +{ + struct module_data *mod_data = &mod->priv; + struct module_config *mod_config = &mod->priv.cfg; + struct comp_dev *dev = mod->dev; + struct comp_data *cd; + int i; + + cd = mod_alloc(mod, sizeof(*cd)); + if (!cd) + return -ENOMEM; + + mod_data->private = cd; + + /* Tnoe only supports 32-bit format */ + cd->tone_func = tone_s32_default; + + /* + * set direction for the comp. In the case of the tone generator being used for + * echo reference, the number of input pins will be non-zero + */ + if (mod_config->nb_input_pins > 0) { + dev->direction = SOF_IPC_STREAM_CAPTURE; + cd->mode = TONE_MODE_SILENCE; + + } else { + dev->direction = SOF_IPC_STREAM_PLAYBACK; + cd->mode = TONE_MODE_TONEGEN; + } + + dev->direction_set = true; + + /* Reset tone generator and set channels volumes to default */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + tonegen_reset(&cd->sg[i]); + + return 0; +} + +static int tone_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "entry"); + + mod_free(mod, cd); + return 0; +} + +/* set component audio stream parameters */ +static int tone_params(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *sinkb; + enum sof_ipc_frame frame_fmt, valid_fmt; + + sinkb = comp_dev_get_first_data_consumer(dev); + if (!sinkb) { + comp_err(dev, "no sink buffer found for tone component"); + return -ENOTCONN; + } + + 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); + cd->rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; + + /* Tone supports only S32_LE PCM format atm */ + if (frame_fmt != SOF_IPC_FRAME_S32_LE) { + comp_err(dev, "unsupported frame_fmt = %u", frame_fmt); + return -EINVAL; + } + + return 0; +} + +/* copy and process stream data from source to sink buffers */ +static int tone_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + + if (num_of_sources > 0) + return cd->tone_func(mod, sinks[0], sources[0]); + + return cd->tone_func(mod, sinks[0], NULL); +} + +static int tone_prepare(struct processing_module *mod, struct sof_source **sources, + int num_of_sources, struct sof_sink **sinks, int num_of_sinks) +{ + struct comp_data *cd = module_get_private_data(mod); + int32_t f; + int32_t a; + int ret; + int i; + + ret = tone_params(mod); + if (ret < 0) + return ret; + + cd->channels = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + + for (i = 0; i < cd->channels; i++) { + f = tonegen_get_f(&cd->sg[i]); + a = tonegen_get_a(&cd->sg[i]); + if (tonegen_init(&cd->sg[i], cd->rate, f, a) < 0) + return -EINVAL; + } + + return 0; +} + +static int tone_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + int i; + + /* Initialize with the defaults */ + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + tonegen_reset(&cd->sg[i]); + + return 0; +} + +static int tone_bind(struct processing_module *mod, struct bind_info *bind_data) +{ + struct comp_data *cd = module_get_private_data(mod); + + /* nothing to do when tone is not the sink */ + if (bind_data->bind_type != COMP_BIND_TYPE_SOURCE) + return 0; + + /* set passthrough mode when tone generator is bound as a sink */ + cd->mode = TONE_MODE_PASSTHROUGH; + + return 0; +} + +static int tone_unbind(struct processing_module *mod, struct bind_info *unbind_data) +{ + struct comp_data *cd = module_get_private_data(mod); + + /* nothing to do when tone is not the sink */ + if (unbind_data->bind_type != COMP_BIND_TYPE_SOURCE) + return 0; + + /* set silence mode when tone generator is unbound from a source module */ + cd->mode = TONE_MODE_SILENCE; + + return 0; +} + +static const struct module_interface tone_interface = { + .init = tone_init, + .prepare = tone_prepare, + .process = tone_process, + .reset = tone_reset, + .free = tone_free, + .bind = tone_bind, + .unbind = tone_unbind, +}; + +#if CONFIG_COMP_TONE_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { + SOF_LLEXT_MODULE_MANIFEST("TONE", &tone_interface, 1, SOF_REG_UUID(tone), 30), +}; + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(tone_tr, SOF_UUID(tone_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(tone_interface, tone_uuid, tone_tr); +SOF_MODULE_INIT(tone, sys_comp_module_tone_interface_init); + +#endif diff --git a/src/audio/tone/tone.c b/src/audio/tone/tone.c new file mode 100644 index 000000000000..975e4ee06bc8 --- /dev/null +++ b/src/audio/tone/tone.c @@ -0,0 +1,355 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/trig.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/tone.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <ipc4/base-config.h> +#include <sof/audio/sink_api.h> +#include "tone.h" + +LOG_MODULE_REGISTER(tone, CONFIG_SOF_LOG_LEVEL); + +static int32_t tonegen(struct tone_state *sg) +{ + int64_t sine; + int64_t w; + /* sg->w is angle in Q4.28 radians format, sin() returns Q1.31 */ + /* sg->a is amplitude as Q1.31 */ + sine = + q_mults_32x32(sin_fixed_32b(sg->w), sg->a, + Q_SHIFT_BITS_64(31, 31, 31)); + + /* Next point */ + w = (int64_t)sg->w + sg->w_step; + sg->w = (w > PI_MUL2_Q4_28) + ? (int32_t)(w - PI_MUL2_Q4_28) : (int32_t)w; + + if (sg->mute) + return 0; + else + return (int32_t)sine; /* Q1.31 no saturation need */ +} + +static void tonegen_control(struct tone_state *sg) +{ + int64_t a; + int64_t p; + + /* Count samples, 125 us blocks */ + sg->sample_count++; + if (sg->sample_count < sg->samples_in_block) + return; + + sg->sample_count = 0; + if (sg->block_count < INT32_MAX) + sg->block_count++; + + /* Fade-in ramp during tone */ + if (sg->block_count < sg->tone_length) { + if (sg->a == 0) + sg->w = 0; /* Reset phase to have less clicky ramp */ + + if (sg->a > sg->a_target) { + a = (int64_t)sg->a - sg->ramp_step; + if (a < sg->a_target) + a = sg->a_target; + + } else { + a = (int64_t)sg->a + sg->ramp_step; + if (a > sg->a_target) + a = sg->a_target; + } + sg->a = (int32_t)a; + } + + /* Fade-out ramp after tone*/ + if (sg->block_count > sg->tone_length) { + a = (int64_t)sg->a - sg->ramp_step; + if (a < 0) + a = 0; + + sg->a = (int32_t)a; + } + + /* New repeated tone, update for frequency or amplitude sweep */ + if (sg->block_count > sg->tone_period && + (sg->repeat_count + 1 < sg->repeats)) { + sg->block_count = 0; + if (sg->ampl_coef > 0) { + sg->a_target = + sat_int32(q_multsr_32x32(sg->a_target, + sg->ampl_coef, + Q_SHIFT_BITS_64(31, 30, 31))); + sg->a = (sg->ramp_step > sg->a_target) + ? sg->a_target : sg->ramp_step; + } + if (sg->freq_coef > 0) { + /* f is Q16.16, freq_coef is Q2.30 */ + p = q_multsr_32x32(sg->f, sg->freq_coef, + Q_SHIFT_BITS_64(16, 30, 16)); + tonegen_update_f(sg, (int32_t)p); /* No saturation */ + } + sg->repeat_count++; + } +} + +static int tone_s32_passthrough(struct processing_module *mod, struct sof_sink *sink, + struct sof_source *source) +{ + struct comp_data *cd = module_get_private_data(mod); + size_t output_frame_bytes, output_frames; + size_t input_frame_bytes, input_frames; + int32_t *output_pos, *output_start, output_cirbuf_size; + int32_t const *input_pos, *input_start, *input_end; + int32_t *output_end, input_cirbuf_size; + uint32_t frames, bytes; + int nch = cd->channels; + int n; + int ret; + + /* tone generator only ever has 1 sink */ + output_frames = sink_get_free_frames(sink); + output_frame_bytes = sink_get_frame_bytes(sink); + output_frames = mod->period_bytes / output_frame_bytes; + + ret = sink_get_buffer_s32(sink, output_frames * output_frame_bytes, + &output_pos, &output_start, &output_cirbuf_size); + if (ret) { + comp_err(mod->dev, "sink_get_buffer_s32() failed"); + return -ENODATA; + } + + input_frames = source_get_data_frames_available(source); + input_frame_bytes = source_get_frame_bytes(source); + + ret = source_get_data_s32(source, input_frames * input_frame_bytes, + &input_pos, &input_start, &input_cirbuf_size); + if (ret) { + comp_err(mod->dev, "source_get_data_s32() failed"); + return -ENODATA; + } + input_end = input_start + input_cirbuf_size; + + frames = MIN(output_frames, input_frames); + + if (frames * output_frame_bytes >= mod->period_bytes) + frames = mod->period_bytes / output_frame_bytes; + bytes = frames * output_frame_bytes; + + output_end = output_start + output_cirbuf_size; + + n = frames * nch; + + while (n > 0) { + int n_wrap_source, n_wrap_dest, n_min; + int i; + + n_wrap_dest = output_end - output_pos; + n_wrap_source = input_end - input_pos; + + /* Process until source/dest wrap or completed n */ + n_min = (n < n_wrap_dest) ? n : n_wrap_dest; + n_min = (n_min < n_wrap_source) ? n_min : n_wrap_source; + while (n_min > 0) { + n -= nch; + n_min -= nch; + for (i = 0; i < nch; i++) { + *output_pos = *input_pos; + output_pos++; + input_pos++; + } + } + + /* Wrap destination/source buffer */ + if (output_pos >= output_end) + output_pos = output_start; + if (input_pos >= input_end) + input_pos = input_start; + } + + ret = sink_commit_buffer(sink, bytes); + if (ret) + return ret; + + return source_release_data(source, bytes); +} + +/* + * Tone generator algorithm code + */ +int tone_s32_default(struct processing_module *mod, struct sof_sink *sink, + struct sof_source *source) +{ + struct comp_data *cd = module_get_private_data(mod); + size_t output_frame_bytes, output_frames; + int32_t *output_pos, *output_start, output_cirbuf_size; + int32_t *output_end; + uint32_t frames, bytes; + int nch = cd->channels; + int i; + int n; + int n_wrap_dest; + int n_min; + int ret; + + if (cd->mode == TONE_MODE_PASSTHROUGH) + return tone_s32_passthrough(mod, sink, source); + + /* tone generator only ever has 1 sink */ + output_frames = sink_get_free_frames(sink); + output_frame_bytes = sink_get_frame_bytes(sink); + output_frames = mod->period_bytes / output_frame_bytes; + + ret = sink_get_buffer_s32(sink, output_frames * output_frame_bytes, + &output_pos, &output_start, &output_cirbuf_size); + if (ret) + return -ENODATA; + + frames = output_frames; + + if (frames * output_frame_bytes >= mod->period_bytes) + frames = mod->period_bytes / output_frame_bytes; + bytes = frames * output_frame_bytes; + + output_end = output_start + output_cirbuf_size; + + n = frames * nch; + if (!source) { + while (n > 0) { + n_wrap_dest = output_end - output_pos; + + /* Process until wrap or completed n */ + n_min = (n < n_wrap_dest) ? n : n_wrap_dest; + while (n_min > 0) { + n -= nch; + n_min -= nch; + for (i = 0; i < nch; i++) { + switch (cd->mode) { + case TONE_MODE_TONEGEN: + tonegen_control(&cd->sg[i]); + *output_pos = tonegen(&cd->sg[i]); + break; + case TONE_MODE_SILENCE: + *output_pos = 0; + break; + default: + break; + } + output_pos++; + } + } + + /* Wrap destination buffer */ + output_pos = output_start; + } + } + + return sink_commit_buffer(sink, bytes); +} + +void tonegen_update_f(struct tone_state *sg, int32_t f) +{ + int64_t w_tmp; + int64_t f_max; + + /* Calculate Fs/2, fs is Q32.0, f is Q16.16 */ + f_max = Q_SHIFT_LEFT((int64_t)sg->fs, 0, 16 - 1); + f_max = (f_max > INT32_MAX) ? INT32_MAX : f_max; + sg->f = (f > f_max) ? f_max : f; + /* Q16 x Q31 -> Q28 */ + w_tmp = q_multsr_32x32(sg->f, sg->c, Q_SHIFT_BITS_64(16, 31, 28)); + w_tmp = (w_tmp > PI_Q4_28) ? PI_Q4_28 : w_tmp; /* Limit to pi Q4.28 */ + sg->w_step = (int32_t)w_tmp; +} + +void tonegen_reset(struct tone_state *sg) +{ + sg->mute = 1; + sg->a = 0; + sg->a_target = TONE_AMPLITUDE_DEFAULT; + sg->c = 0; + sg->f = TONE_FREQUENCY_DEFAULT; + sg->w = 0; + sg->w_step = 0; + + sg->block_count = 0; + sg->repeat_count = 0; + sg->repeats = 0; + sg->sample_count = 0; + sg->samples_in_block = 0; + + /* Continuous tone */ + sg->freq_coef = ONE_Q2_30; /* Set freq multiplier to 1.0 */ + sg->ampl_coef = ONE_Q2_30; /* Set ampl multiplier to 1.0 */ + sg->tone_length = INT32_MAX; + sg->tone_period = INT32_MAX; + sg->ramp_step = ONE_Q1_31; /* Set lin ramp modification to max */ +} + +int tonegen_init(struct tone_state *sg, int32_t fs, int32_t f, int32_t a) +{ + int idx; + int i; + + sg->a_target = a; + sg->a = (sg->ramp_step > sg->a_target) ? sg->a_target : sg->ramp_step; + + idx = -1; + sg->mute = 1; + sg->fs = 0; + + /* Find index of current sample rate and then get from lookup table the + * corresponding 2*pi/Fs value. + */ + for (i = 0; i < TONE_NUM_FS; i++) { + if (fs == tone_fs_list[i]) + idx = i; + } + + if (idx < 0) { + sg->w_step = 0; + return -EINVAL; + } + + sg->fs = fs; + sg->c = tone_pi2_div_fs[idx]; /* Store 2*pi/Fs */ + sg->mute = 0; + tonegen_update_f(sg, f); + + /* 125us as Q1.31 is 268435, calculate fs * 125e-6 in Q31.0 */ + sg->samples_in_block = + (int32_t)q_multsr_32x32(fs, 268435, Q_SHIFT_BITS_64(0, 31, 0)); + + return 0; +} diff --git a/src/audio/tone/tone.h b/src/audio/tone/tone.h new file mode 100644 index 000000000000..4183543e0beb --- /dev/null +++ b/src/audio/tone/tone.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. + * + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> /* for SHARED_DATA */ +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/trig.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/tone.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +/* Convert float frequency in Hz to Q16.16 fractional format */ +#define TONE_FREQ(f) Q_CONVERT_FLOAT(f, 16) + +/* Convert float gain to Q1.31 fractional format */ +#define TONE_GAIN(v) Q_CONVERT_FLOAT(v, 31) + +/* Set default tone amplitude and frequency */ +#define TONE_AMPLITUDE_DEFAULT TONE_GAIN(0.1) /* -20 dB */ +#define TONE_FREQUENCY_DEFAULT TONE_FREQ(997.0) +#define TONE_NUM_FS 13 /* Table size for 8-192 kHz range */ + +#define TONE_MODE_TONEGEN 0 +#define TONE_MODE_PASSTHROUGH 1 +#define TONE_MODE_SILENCE 2 + +extern struct tr_ctx tone_tr; +extern const struct sof_uuid tone; + +/* 2*pi/Fs lookup tables in Q1.31 for each Fs */ +static const int32_t tone_fs_list[TONE_NUM_FS] = { + 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, + 64000, 88200, 96000, 176400, 192000 +}; + +static const int32_t tone_pi2_div_fs[TONE_NUM_FS] = { + 1686630, 1223858, 843315, 611929, 562210, 421657, 305965, + 281105, 210829, 152982, 140552, 76491, 70276 +}; + +/* tone component private data */ + +struct tone_state { + int mute; + int32_t a; /* Current amplitude Q1.31 */ + int32_t a_target; /* Target amplitude Q1.31 */ + int32_t ampl_coef; /* Amplitude multiplier Q2.30 */ + int32_t c; /* Coefficient 2*pi/Fs Q1.31 */ + int32_t f; /* Frequency Q16.16 */ + int32_t freq_coef; /* Frequency multiplier Q2.30 */ + int32_t fs; /* Sample rate in Hertz Q32.0 */ + int32_t ramp_step; /* Amplitude ramp step Q1.31 */ + int32_t w; /* Angle radians Q4.28 */ + int32_t w_step; /* Angle step Q4.28 */ + uint32_t block_count; + uint32_t repeat_count; + uint32_t repeats; /* Number of repeats for tone (sweep steps) */ + uint32_t sample_count; + uint32_t samples_in_block; /* Samples in 125 us block */ + uint32_t tone_length; /* Active length in 125 us blocks */ + uint32_t tone_period; /* Active + idle time in 125 us blocks */ +}; + +struct comp_data { + uint32_t channels; + uint32_t rate; + struct tone_state sg[PLATFORM_MAX_CHANNELS]; + int (*tone_func)(struct processing_module *mod, struct sof_sink *sink, + struct sof_source *source); + int mode; +}; + +void tonegen_reset(struct tone_state *sg); +int tonegen_init(struct tone_state *sg, int32_t fs, int32_t f, int32_t a); +void tonegen_update_f(struct tone_state *sg, int32_t f); +int tone_s32_default(struct processing_module *mod, struct sof_sink *sink, + struct sof_source *source); + +/* Set sine amplitude */ +static inline void tonegen_set_a(struct tone_state *sg, int32_t a) +{ + sg->a_target = a; +} + +/* Repeated number of beeps */ +static inline void tonegen_set_repeats(struct tone_state *sg, uint32_t r) +{ + sg->repeats = r; +} + +/* The next functions support zero as shortcut for defaults to get + * make a nicer API without need to remember the neutral steady + * non-swept tone settings. + */ + +/* Multiplication factor for frequency as Q2.30 for logarithmic change */ +static inline void tonegen_set_freq_mult(struct tone_state *sg, int32_t fm) +{ + sg->freq_coef = (fm > 0) ? fm : ONE_Q2_30; /* Set freq mult to 1.0 */ +} + +/* Multiplication factor for amplitude as Q2.30 for logarithmic change */ +static inline void tonegen_set_ampl_mult(struct tone_state *sg, int32_t am) +{ + sg->ampl_coef = (am > 0) ? am : ONE_Q2_30; /* Set ampl mult to 1.0 */ +} + +/* Tone length in samples, this is the active length of tone */ +static inline void tonegen_set_length(struct tone_state *sg, uint32_t tl) +{ + sg->tone_length = (tl > 0) ? tl : INT32_MAX; /* Count rate 125 us */ +} + +/* Tone period in samples, this is the length including the pause after beep */ +static inline void tonegen_set_period(struct tone_state *sg, uint32_t tp) +{ + sg->tone_period = (tp > 0) ? tp : INT32_MAX; /* Count rate 125 us */ +} + +/* Tone ramp parameters: + * step - Value that is added or subtracted to amplitude. A zero or negative + * number disables the ramp and amplitude is immediately modified to + * final value. + */ + +static inline void tonegen_set_linramp(struct tone_state *sg, int32_t step) +{ + sg->ramp_step = (step > 0) ? step : INT32_MAX; +} + +static inline int32_t tonegen_get_f(struct tone_state *sg) +{ + return sg->f; +} + +static inline int32_t tonegen_get_a(struct tone_state *sg) +{ + return sg->a_target; +} + +static inline void tonegen_mute(struct tone_state *sg) +{ + sg->mute = 1; +} + +static inline void tonegen_unmute(struct tone_state *sg) +{ + sg->mute = 0; +} diff --git a/src/audio/tone/tone.toml b/src/audio/tone/tone.toml new file mode 100644 index 000000000000..02d6e5dca96b --- /dev/null +++ b/src/audio/tone/tone.toml @@ -0,0 +1,22 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # Template component module config + [[module.entry]] + name = "TONE" + uuid = UUIDREG_STR_TONE + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + init_config = "1" + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, 1, 0, 0xfeef, 0xf, 0xf, 0x1ff] + REM # 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, 4096, 1000000, 128, 128, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/audio/up_down_mixer/CMakeLists.txt b/src/audio/up_down_mixer/CMakeLists.txt new file mode 100644 index 000000000000..57e9e22e3ee4 --- /dev/null +++ b/src/audio/up_down_mixer/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof up_down_mixer.c) +add_local_sources(sof up_down_mixer_hifi3.c) diff --git a/src/audio/up_down_mixer/Kconfig b/src/audio/up_down_mixer/Kconfig new file mode 100644 index 000000000000..be3cf794061e --- /dev/null +++ b/src/audio/up_down_mixer/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_UP_DOWN_MIXER + bool "UP_DOWN_MIXER component" + depends on IPC_MAJOR_4 + help + Select for Up Down Mixer component Conversions supported: + Up/Downmixing for stereo output: + 1, 2, 2.1, 3.0, 3.1, Quatro, 4.0, 5.0, 5.1, 7.1 -> 2 + Upmixing for multichannel output: + 1, 2 -> 5.1 + 2 -> 7.1 + Downmixing for mono output: + 4.0, Quatro, 3.1, 2 -> 1 diff --git a/src/audio/up_down_mixer/README.md b/src/audio/up_down_mixer/README.md new file mode 100644 index 000000000000..723d5cc609fc --- /dev/null +++ b/src/audio/up_down_mixer/README.md @@ -0,0 +1,13 @@ +# Up/Down Mixer Architecture + +This directory contains the Up/Down channel mixer. + +## Overview + +Converts the spatial format of audio (e.g., Stereo up to 5.1 surround, or 5.1 mixed down to Stereo) natively. + +## Configuration and Scripts + +- **Kconfig**: Enabled via `COMP_UP_DOWN_MIXER`, specifically tuned for `IPC_MAJOR_4`. Supports heavy format transformations up to 7.1 endpoints. +- **CMakeLists.txt**: Implements the base `up_down_mixer.c` component along with highly-optimized architecture primitives (`up_down_mixer_hifi3.c`). +- **up_down_mixer.toml**: Robust configuration map controlling `UPDWMIX` deployment against variable system arrays depending on Meteor Lake, Lunar Lake, or ACE platform parameters (UUID binding `UUIDREG_STR_UP_DOWN_MIXER`). diff --git a/src/audio/up_down_mixer/up_down_mixer.c b/src/audio/up_down_mixer/up_down_mixer.c new file mode 100644 index 000000000000..a5843026710a --- /dev/null +++ b/src/audio/up_down_mixer/up_down_mixer.c @@ -0,0 +1,449 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@intel.com> +// Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "up_down_mixer_coef.h" +#include "up_down_mixer.h" + +LOG_MODULE_REGISTER(up_down_mixer, CONFIG_SOF_LOG_LEVEL); + +/* these ids aligns windows driver requirement to support windows driver */ +SOF_DEFINE_REG_UUID(up_down_mixer); + +int32_t custom_coeffs[UP_DOWN_MIX_COEFFS_LENGTH]; + +static int set_downmix_coefficients(struct processing_module *mod, + const struct ipc4_audio_format *format, + const enum ipc4_channel_config out_channel_config, + const downmix_coefficients downmix_coefficients) +{ + struct up_down_mixer_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + if (cd->downmix_coefficients) { + ret = memcpy_s(&custom_coeffs, sizeof(custom_coeffs), downmix_coefficients, + sizeof(int32_t) * UP_DOWN_MIX_COEFFS_LENGTH); + + if (ret < 0) + return ret; + + cd->downmix_coefficients = custom_coeffs; + + return 0; + } + + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_MONO: + case IPC4_CHANNEL_CONFIG_STEREO: + case IPC4_CHANNEL_CONFIG_2_POINT_1: + case IPC4_CHANNEL_CONFIG_DUAL_MONO: + cd->downmix_coefficients = k_lo_ro_downmix32bit; + break; + case IPC4_CHANNEL_CONFIG_3_POINT_0: + case IPC4_CHANNEL_CONFIG_3_POINT_1: + if (format->depth == IPC4_DEPTH_16BIT) + cd->downmix_coefficients = k_half_scaled_lo_ro_downmix16bit; + else + cd->downmix_coefficients = k_half_scaled_lo_ro_downmix32bit; + break; + case IPC4_CHANNEL_CONFIG_QUATRO: + if (out_channel_config == IPC4_CHANNEL_CONFIG_MONO) { + cd->downmix_coefficients = (format->depth == IPC4_DEPTH_16BIT) ? + k_quatro_mono_scaled_lo_ro_downmix16bit : + k_quatro_mono_scaled_lo_ro_downmix32bit; + } else { /*out_channel_config == IPC4_CHANNEL_CONFIG_STEREO*/ + cd->downmix_coefficients = (format->depth == IPC4_DEPTH_16BIT) ? + k_half_scaled_lo_ro_downmix16bit : + k_half_scaled_lo_ro_downmix32bit; + } + break; + case IPC4_CHANNEL_CONFIG_4_POINT_0: + if (format->depth == IPC4_DEPTH_16BIT) { + cd->downmix_coefficients = k_scaled_lo_ro_downmix16bit; + } else { + if (out_channel_config == IPC4_CHANNEL_CONFIG_5_POINT_1) + cd->downmix_coefficients = k_lo_ro_downmix32bit; + else + cd->downmix_coefficients = k_scaled_lo_ro_downmix32bit; + } + break; + case IPC4_CHANNEL_CONFIG_5_POINT_0: + case IPC4_CHANNEL_CONFIG_5_POINT_1: + case IPC4_CHANNEL_CONFIG_7_POINT_1: + cd->downmix_coefficients = k_scaled_lo_ro_downmix32bit; + break; + default: + comp_err(dev, "invalid channel config."); + return -EINVAL; + } + + return 0; +} + +static up_down_mixer_routine select_mix_out_stereo(struct comp_dev *dev, + const struct ipc4_audio_format *format) +{ + if (format->depth == IPC4_DEPTH_16BIT) { + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_MONO: + return shiftcopy16bit_mono; + case IPC4_CHANNEL_CONFIG_DUAL_MONO: + case IPC4_CHANNEL_CONFIG_STEREO: + return shiftcopy16bit_stereo; + case IPC4_CHANNEL_CONFIG_2_POINT_1: + case IPC4_CHANNEL_CONFIG_3_POINT_0: + case IPC4_CHANNEL_CONFIG_3_POINT_1: + case IPC4_CHANNEL_CONFIG_QUATRO: + case IPC4_CHANNEL_CONFIG_4_POINT_0: + case IPC4_CHANNEL_CONFIG_5_POINT_0: + return downmix16bit; + case IPC4_CHANNEL_CONFIG_5_POINT_1: + return downmix16bit_5_1; + case IPC4_CHANNEL_CONFIG_INVALID: + default: + comp_err(dev, "invalid channel config."); + /* + * This is a strange situation. We will allow to process it + * in the release code (hoping for the best) with downmix16bit, + * but will log err in debug to double check if everything is ok + */ + return NULL; + } + } else { + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_MONO: + return shiftcopy32bit_mono; + case IPC4_CHANNEL_CONFIG_DUAL_MONO: + case IPC4_CHANNEL_CONFIG_STEREO: + return shiftcopy32bit_stereo; + case IPC4_CHANNEL_CONFIG_2_POINT_1: + return downmix32bit_2_1; + case IPC4_CHANNEL_CONFIG_3_POINT_0: + return downmix32bit_3_0; + case IPC4_CHANNEL_CONFIG_3_POINT_1: + return downmix32bit_3_1; + case IPC4_CHANNEL_CONFIG_QUATRO: + return downmix32bit; + case IPC4_CHANNEL_CONFIG_4_POINT_0: + return downmix32bit_4_0; + case IPC4_CHANNEL_CONFIG_5_POINT_0: + return downmix32bit_5_0_mono; + case IPC4_CHANNEL_CONFIG_5_POINT_1: + return downmix32bit_5_1; + case IPC4_CHANNEL_CONFIG_7_POINT_1: + return downmix32bit_7_1; + case IPC4_CHANNEL_CONFIG_INVALID: + default: + comp_err(dev, "invalid channel config."); + /* + * This is a strange situation. We will allow to process it + * in the release code (hoping for the best) with downmix32bit, + * but will log err in debug to double check if everything is ok. + */ + return NULL; + } + } +} + +static up_down_mixer_routine select_mix_out_mono(struct comp_dev *dev, + const struct ipc4_audio_format *format) +{ + if (format->depth == IPC4_DEPTH_16BIT) { + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_STEREO: + return downmix16bit_stereo; + case IPC4_CHANNEL_CONFIG_3_POINT_1: + case IPC4_CHANNEL_CONFIG_QUATRO: + case IPC4_CHANNEL_CONFIG_4_POINT_0: + return downmix16bit_4ch_mono; + case IPC4_CHANNEL_CONFIG_INVALID: + default: + comp_err(dev, "invalid channel config."); + /* + * This is a strange situation. We will allow to process it + * in the release code (hoping for the best) with downmix16bit, + * but will log err in debug to double check if everything is ok + */ + return NULL; + } + } else { + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_DUAL_MONO: + case IPC4_CHANNEL_CONFIG_STEREO: + return downmix32bit_stereo; + case IPC4_CHANNEL_CONFIG_3_POINT_1: + return downmix32bit_3_1_mono; + case IPC4_CHANNEL_CONFIG_QUATRO: + return downmix32bit_quatro_mono; + case IPC4_CHANNEL_CONFIG_4_POINT_0: + return downmix32bit_4_0_mono; + case IPC4_CHANNEL_CONFIG_5_POINT_0: + return downmix32bit_5_0_mono; + case IPC4_CHANNEL_CONFIG_5_POINT_1: + return downmix32bit_5_1_mono; + case IPC4_CHANNEL_CONFIG_7_POINT_1: + return downmix32bit_7_1_mono; + case IPC4_CHANNEL_CONFIG_INVALID: + default: + comp_err(dev, "invalid channel config."); + /* + * This is a strange situation. We will allow to process it + * in the release code (hoping for the best) with downmix32bit, + * but will log err in debug to double check if everything is ok. + */ + return NULL; + } + } +} + +static up_down_mixer_routine select_mix_out_5_1(struct comp_dev *dev, + const struct ipc4_audio_format *format) +{ + if (format->depth == IPC4_DEPTH_16BIT) { + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_MONO: + return upmix16bit_1_to_5_1; + case IPC4_CHANNEL_CONFIG_STEREO: + return upmix16bit_2_0_to_5_1; + case IPC4_CHANNEL_CONFIG_INVALID: + default: + comp_err(dev, "invalid channel config."); + return NULL; + } + } else { + switch (format->ch_cfg) { + case IPC4_CHANNEL_CONFIG_MONO: + return upmix32bit_1_to_5_1; + case IPC4_CHANNEL_CONFIG_STEREO: + return upmix32bit_2_0_to_5_1; + case IPC4_CHANNEL_CONFIG_QUATRO: + return upmix32bit_quatro_to_5_1; + case IPC4_CHANNEL_CONFIG_4_POINT_0: + return upmix32bit_4_0_to_5_1; + case IPC4_CHANNEL_CONFIG_7_POINT_1: + return downmix32bit_7_1_to_5_1; + case IPC4_CHANNEL_CONFIG_INVALID: + default: + comp_err(dev, "invalid channel config."); + return NULL; + } + } +} + +static int init_mix(struct processing_module *mod, + const struct ipc4_audio_format *format, + enum ipc4_channel_config out_channel_config, + const downmix_coefficients downmix_coefficients) +{ + struct up_down_mixer_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + if (!format) + return -EINVAL; + + if (out_channel_config == IPC4_CHANNEL_CONFIG_MONO) { + /* Select dowm mixing routine. */ + cd->mix_routine = select_mix_out_mono(dev, format); + + /* Update audio format. */ + cd->out_fmt[0].channels_count = 1; + cd->out_fmt[0].ch_cfg = IPC4_CHANNEL_CONFIG_MONO; + cd->out_fmt[0].ch_map = create_channel_map(IPC4_CHANNEL_CONFIG_MONO); + + } else if (out_channel_config == IPC4_CHANNEL_CONFIG_STEREO) { + /* DOWN_MIX */ + if (format->interleaving_style != IPC4_CHANNELS_INTERLEAVED || + format->depth == IPC4_DEPTH_8BIT) + return -EINVAL; + + /* Select dowm mixing routine. */ + cd->mix_routine = select_mix_out_stereo(dev, format); + + /* Update audio format. */ + cd->out_fmt[0].channels_count = 2; + cd->out_fmt[0].ch_cfg = IPC4_CHANNEL_CONFIG_STEREO; + cd->out_fmt[0].ch_map = create_channel_map(IPC4_CHANNEL_CONFIG_STEREO); + + } else if (out_channel_config == IPC4_CHANNEL_CONFIG_5_POINT_1) { + /* Select dowm mixing routine. */ + cd->mix_routine = select_mix_out_5_1(dev, format); + + /* Update audio format. */ + cd->out_fmt[0].channels_count = 6; + cd->out_fmt[0].ch_cfg = IPC4_CHANNEL_CONFIG_5_POINT_1; + cd->out_fmt[0].ch_map = create_channel_map(IPC4_CHANNEL_CONFIG_5_POINT_1); + + } else if (out_channel_config == IPC4_CHANNEL_CONFIG_7_POINT_1 && + format->ch_cfg == IPC4_CHANNEL_CONFIG_STEREO) { + /* Select up mixing routine. */ + cd->mix_routine = upmix32bit_2_0_to_7_1; + + if (format->depth == IPC4_DEPTH_16BIT) + return -EINVAL; + } else { + return -EINVAL; + } + + /* Update audio format. */ + cd->out_fmt[0].valid_bit_depth = IPC4_DEPTH_24BIT; + cd->out_fmt[0].depth = IPC4_DEPTH_32BIT; + + cd->in_channel_no = format->channels_count; + cd->in_channel_map = format->ch_map; + cd->in_channel_config = format->ch_cfg; + + return set_downmix_coefficients(mod, format, out_channel_config, downmix_coefficients); +} + +static int up_down_mixer_free(struct processing_module *mod) +{ + struct up_down_mixer_data *cd = module_get_private_data(mod); + + mod_free(mod, cd->buf_in); + mod_free(mod, cd->buf_out); + mod_free(mod, cd); + + return 0; +} + +static int up_down_mixer_init(struct processing_module *mod) +{ + struct module_config *dst = &mod->priv.cfg; + const struct ipc4_up_down_mixer_module_cfg *up_down_mixer = dst->init_data; + struct module_data *mod_data = &mod->priv; + struct comp_dev *dev = mod->dev; + struct up_down_mixer_data *cd; + int ret; + + cd = mod_zalloc(mod, sizeof(*cd)); + if (!cd) { + comp_free(dev); + return -ENOMEM; + } + + mod_data->private = cd; + + cd->buf_in = mod_balloc(mod, mod->priv.cfg.base_cfg.ibs); + cd->buf_out = mod_balloc(mod, mod->priv.cfg.base_cfg.obs); + if (!cd->buf_in || !cd->buf_out) { + ret = -ENOMEM; + goto err; + } + + switch (up_down_mixer->coefficients_select) { + case DEFAULT_COEFFICIENTS: + cd->out_channel_map = create_channel_map(up_down_mixer->out_channel_config); + ret = init_mix(mod, &mod->priv.cfg.base_cfg.audio_fmt, + up_down_mixer->out_channel_config, NULL); + break; + case CUSTOM_COEFFICIENTS: + cd->out_channel_map = create_channel_map(up_down_mixer->out_channel_config); + ret = init_mix(mod, &mod->priv.cfg.base_cfg.audio_fmt, + up_down_mixer->out_channel_config, up_down_mixer->coefficients); + break; + case DEFAULT_COEFFICIENTS_WITH_CHANNEL_MAP: + cd->out_channel_map = up_down_mixer->channel_map; + ret = init_mix(mod, &mod->priv.cfg.base_cfg.audio_fmt, + up_down_mixer->out_channel_config, NULL); + break; + case CUSTOM_COEFFICIENTS_WITH_CHANNEL_MAP: + cd->out_channel_map = up_down_mixer->channel_map; + ret = init_mix(mod, &mod->priv.cfg.base_cfg.audio_fmt, + up_down_mixer->out_channel_config, up_down_mixer->coefficients); + break; + default: + comp_err(dev, "unsupported coefficient type"); + ret = -EINVAL; + break; + } + + if (ret < 0) { + comp_err(dev, "failed to initialize up_down_mix"); + goto err; + } + + return 0; + +err: + up_down_mixer_free(mod); + return ret; +} + +static int +up_down_mixer_process(struct processing_module *mod, + struct sof_source **input_buffers, int num_input_buffers, + struct sof_sink **output_buffers, int num_output_buffers) +{ + struct up_down_mixer_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + size_t output_frames, input_frames, ret, input_cirbuf_size, output_cirbuf_size; + const uint8_t *input0_pos, *input0_start; + uint8_t *output_pos, *output_start; + + comp_dbg(dev, "entry"); + + output_frames = sink_get_free_frames(output_buffers[0]); + input_frames = source_get_data_frames_available(input_buffers[0]); + + const size_t output_frame_bytes = sink_get_frame_bytes(output_buffers[0]); + + ret = sink_get_buffer(output_buffers[0], output_frames * output_frame_bytes, + (void **)&output_pos, (void **)&output_start, &output_cirbuf_size); + if (ret) + return -ENODATA; + + const size_t input0_frame_bytes = source_get_frame_bytes(input_buffers[0]); + + ret = source_get_data(input_buffers[0], input_frames * input0_frame_bytes, + (const void **)&input0_pos, (const void **)&input0_start, + &input_cirbuf_size); + if (ret) { + sink_commit_buffer(output_buffers[0], 0); + return -ENODATA; + } + + cd->mix_routine(cd, (const void *)input0_start, input_cirbuf_size, (void *)output_start); + + ret = sink_commit_buffer(output_buffers[0], output_frames * output_frame_bytes); + if (ret) + return ret; + + ret = source_release_data(input_buffers[0], input_frames * input0_frame_bytes); + if (ret) + return ret; + return 0; +} + +static const struct module_interface up_down_mixer_interface = { + .init = up_down_mixer_init, + .process = up_down_mixer_process, + .free = up_down_mixer_free +}; + +DECLARE_TR_CTX(up_down_mixer_comp_tr, SOF_UUID(up_down_mixer_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(up_down_mixer_interface, up_down_mixer_uuid, up_down_mixer_comp_tr); +SOF_MODULE_INIT(up_down_mixer, sys_comp_module_up_down_mixer_interface_init); diff --git a/src/audio/up_down_mixer/up_down_mixer.h b/src/audio/up_down_mixer/up_down_mixer.h new file mode 100644 index 000000000000..52a5f1e34daa --- /dev/null +++ b/src/audio/up_down_mixer/up_down_mixer.h @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@intel.com> +// Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + +#ifndef __SOF_AUDIO_UP_DOWN_MIXER_H__ +#define __SOF_AUDIO_UP_DOWN_MIXER_H__ + +#include <sof/audio/component_ext.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <ipc4/module.h> +#include <ipc4/base-config.h> +#include <stddef.h> +#include <stdint.h> + +#include "up_down_mixer_ipc4.h" + +/** This type is introduced for better readability. */ +typedef const int32_t *downmix_coefficients; + +/** forward declaration */ +struct up_down_mixer_data; + +/** Function's pointer to up/down-mix routines. */ +typedef void (*up_down_mixer_routine)(struct up_down_mixer_data *cd, + const uint8_t * const in_data, + const uint32_t in_size, + uint8_t * const out_data); + +/** + * Simple 'macro-style' method to create proper channel map from a valid + * channel configuration. + */ +static inline channel_map create_channel_map(enum ipc4_channel_config channel_config) +{ + switch (channel_config) { + case IPC4_CHANNEL_CONFIG_MONO: + return (0xFFFFFFF0 | CHANNEL_CENTER); + case IPC4_CHANNEL_CONFIG_STEREO: + return (0xFFFFFF00 | CHANNEL_LEFT | (CHANNEL_RIGHT << 4)); + case IPC4_CHANNEL_CONFIG_2_POINT_1: + return (0xFFFFF000 | CHANNEL_LEFT | (CHANNEL_RIGHT << 4) | (CHANNEL_LFE << 8)); + case IPC4_CHANNEL_CONFIG_3_POINT_0: + return (0xFFFFF000 | CHANNEL_LEFT | (CHANNEL_CENTER << 4) | (CHANNEL_RIGHT << 8)); + case IPC4_CHANNEL_CONFIG_3_POINT_1: + return (0xFFFF0000 | CHANNEL_LEFT | (CHANNEL_CENTER << 4) | (CHANNEL_RIGHT << 8) + | (CHANNEL_LFE << 12)); + case IPC4_CHANNEL_CONFIG_QUATRO: + return (0xFFFF0000 | CHANNEL_LEFT | (CHANNEL_RIGHT << 4) + | (CHANNEL_LEFT_SURROUND << 8) | (CHANNEL_RIGHT_SURROUND << 12)); + case IPC4_CHANNEL_CONFIG_4_POINT_0: + return (0xFFFF0000 | CHANNEL_LEFT | (CHANNEL_CENTER << 4) | (CHANNEL_RIGHT << 8) + | (CHANNEL_CENTER_SURROUND << 12)); + case IPC4_CHANNEL_CONFIG_5_POINT_0: + return (0xFFF00000 | CHANNEL_LEFT | (CHANNEL_CENTER << 4) | (CHANNEL_RIGHT << 8) + | (CHANNEL_LEFT_SURROUND << 12) + | (CHANNEL_RIGHT_SURROUND << 16)); + case IPC4_CHANNEL_CONFIG_5_POINT_1: + return (0xFF000000 | CHANNEL_LEFT + | (CHANNEL_CENTER << 4) + | (CHANNEL_RIGHT << 8) + | (CHANNEL_LEFT_SURROUND << 12) + | (CHANNEL_RIGHT_SURROUND << 16) + | (CHANNEL_LFE << 20)); + case IPC4_CHANNEL_CONFIG_7_POINT_1: + return (CHANNEL_LEFT | (CHANNEL_CENTER << 4) + | (CHANNEL_RIGHT << 8) + | (CHANNEL_LEFT_SURROUND << 12) + | (CHANNEL_RIGHT_SURROUND << 16) + | (CHANNEL_LFE << 20) + | (CHANNEL_LEFT_SIDE << 24) + | (CHANNEL_RIGHT_SIDE << 28)); + case IPC4_CHANNEL_CONFIG_DUAL_MONO: + return (0xFFFFFF00 | CHANNEL_LEFT | (CHANNEL_LEFT << 4)); + case IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_0: + return (0xFFFFFF00 | CHANNEL_LEFT | (CHANNEL_RIGHT << 4)); + case IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_1: + return (0xFFFF00FF | (CHANNEL_LEFT << 8) | (CHANNEL_RIGHT << 12)); + default: + return 0xFFFFFFFF; + } +} + +static inline uint8_t get_channel_location(const channel_map map, + const enum ipc4_channel_index channel) +{ + uint8_t offset = 0xF; + uint8_t i; + + /* Search through all 4 bits of each byte in the integer for the channel. */ + for (i = 0; i < 8; i++) { + if (((map >> (i * 4)) & 0xF) == (uint8_t)channel) { + offset = i; + break; + } + } + + return offset; +} + +static inline enum ipc4_channel_index get_channel_index(const channel_map map, + const uint8_t location) +{ + return (enum ipc4_channel_index)((map >> (location * 4)) & 0xF); +} + +/** + * \brief up_down_mixer component private data. + */ +struct up_down_mixer_data { + /** Number of channels in the input buffer. */ + size_t in_channel_no; + + /** Channel map in the input buffer. */ + channel_map in_channel_map; + + /** Channel configuration in the input buffer. */ + enum ipc4_channel_config in_channel_config; + channel_map out_channel_map; + + /** Function pointer to up/down-mix routine. */ + up_down_mixer_routine mix_routine; + + /** Downmix coefficients. */ + downmix_coefficients downmix_coefficients; + + struct ipc4_audio_format out_fmt[IPC4_UP_DOWN_MIXER_MODULE_OUTPUT_PINS_COUNT]; + + const int32_t k_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_scaled_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_half_scaled_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_quatro_mono_scaled_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_scaled_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_half_scaled_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH]; + const int32_t k_quatro_mono_scaled_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH]; + + /** In/out internal buffers */ + int32_t *buf_in; + int32_t *buf_out; +}; + +/** + * \brief 32 bit upmixer (mono -> 5_1). + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix32bit_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit upmixer (mono -> 5_1). + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix16bit_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit upmixer (2_0 -> 5_1). + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix32bit_2_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit upmixer (2_0 -> 5_1). + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix16bit_2_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit upmixer (2_0 -> 7_1). + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix32bit_2_0_to_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit shift copier for mono streams. + * Copy the 32 MSB input mono stream (left, right) to 32 MSB stereo one. + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void shiftcopy32bit_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit shift copier for stereo. + * Copy the 32 MSB input streo stream (left, right) to 32 MSB one. + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void shiftcopy32bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 24 bit downmixer specialized for the 2.1. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_2_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 24 bit downmixer specialized for the 3.0. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_3_0(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 24 bit downmixer specialized for the 3.1. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_3_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 24 bit downmixer. This function is highly power consuming + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 24 bit downmixer specialized for the 4.0. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_4_0(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 5.0 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_5_0_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 5.1 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 7.1 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit shift copier for mono. + * Copy the 16 bit input mono stream (left, right) to 32 MSB stereo one. + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void shiftcopy16bit_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit shift copier for stereo. + * Copy the 16 bit input streo stream (left, right) to 32 MSB one. + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void shiftcopy16bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit downmixer. This function is highly power consuming + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix16bit(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit downmixer specialized for the 5.1. + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix16bit_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit downmixer 4 channels to mono. This function is highly power consuming + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix16bit_4ch_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 24 bit downmixer specialized for the 2.0. + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 16 bit downmix from stereo to mono. + * \note needs to be optimized!!! + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix16bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 3.1 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_3_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 4.0 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_4_0_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the Quatro to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_quatro_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 5.1 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_5_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 7.1 to mono downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_7_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 7.1 to 5_1 downmixing. + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void downmix32bit_7_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the 4.0 to 5_1 + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix32bit_4_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +/** + * \brief 32 bit downmixer specialized for the Quatro to 5_1 + * \note implementation is based on Downmix32bit + * + * \param[in] cd Component private data. + * \param[in] in_data Input buffer. + * \param[in] in_size Input buffer size. + * \param[out] out_data Output buffer. + */ +void upmix32bit_quatro_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data); + +#endif /* __SOF_AUDIO_UP_DOWN_MIXER_H__ */ diff --git a/src/audio/up_down_mixer/up_down_mixer.toml b/src/audio/up_down_mixer/up_down_mixer.toml new file mode 100644 index 000000000000..713cff7a87d8 --- /dev/null +++ b/src/audio/up_down_mixer/up_down_mixer.toml @@ -0,0 +1,90 @@ + [[module.entry]] + name = "UPDWMIX" + uuid = UUIDREG_STR_UP_DOWN_MIXER + affinity_mask = "0x1" + instance_count = "15" + domain_types = "0" + load_type = "0" + module_type = "5" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xffff, 0xc, 0x8, 0x05ff, + 1, 0, 0xffff, 0xc, 0x8, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 216, 5044000, 384, 192, 0, 5044, 0, + 1, 0, 0, 0, 216, 2660000, 384, 384, 0, 2660, 0, + 2, 0, 0, 0, 216, 3164000, 576, 384, 0, 3164, 0, + 3, 0, 0, 0, 216, 3316000, 768, 384, 0, 3316, 0, + 4, 0, 0, 0, 216, 5264000, 768, 384, 0, 5264, 0, + 5, 0, 0, 0, 216, 5440000, 768, 384, 0, 5440, 0, + 6, 0, 0, 0, 216, 2888000, 768, 192, 0, 2888, 0, + 7, 0, 0, 0, 216, 2856000, 768, 192, 0, 2856, 0, + 8, 0, 0, 0, 216, 2876000, 768, 192, 0, 2876, 0, + 9, 0, 0, 0, 216, 2956000, 960, 192, 0, 2956, 0, + 10, 0, 0, 0, 216, 2888000, 1152, 192, 0, 2888, 0, + 11, 0, 0, 0, 216, 2888000, 1152, 192, 0, 2888, 0, + 12, 0, 0, 0, 216, 2816000, 1536, 192, 0, 2816, 0, + 13, 0, 0, 0, 216, 2468000, 192, 384, 0, 2468, 0, + 14, 0, 0, 0, 216, 3084000, 576, 384, 0, 3084, 0, + 15, 0, 0, 0, 216, 3442000, 960, 384, 0, 3442, 0, + 16, 0, 0, 0, 216, 3478000, 1152, 384, 0, 3478, 0, + 17, 0, 0, 0, 216, 3478000, 1152, 384, 0, 3478, 0, + 18, 0, 0, 0, 216, 3736000, 1536, 384, 0, 3736, 0, + 19, 0, 0, 0, 216, 3216000, 192, 1152, 0, 3216, 0, + 20, 0, 0, 0, 216, 3308000, 384, 1152, 0, 3308, 0, + 21, 0, 0, 0, 216, 3616000, 768, 1152, 0, 3616, 0, + 22, 0, 0, 0, 216, 3616000, 768, 1152, 0, 3616, 0, + 23, 0, 0, 0, 216, 4916000, 1536, 1152, 0, 4916, 0, + 24, 0, 0, 0, 216, 3228000, 192, 1152, 0, 3228, 0, + 25, 0, 0, 0, 216, 3452000, 384, 1152, 0, 3452, 0, + 26, 0, 0, 0, 216, 4016000, 768, 1152, 0, 4016, 0, + 27, 0, 0, 0, 216, 5080000, 1536, 1152, 0, 5080, 0, + 28, 0, 0, 0, 216, 3552000, 384, 1536, 0, 3552, 0, + 29, 0, 0, 0, 216, 3728000, 768, 1152, 0, 3728, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 216, 4153000, 384, 192, 0, 4153, 0, + 1, 0, 0, 0, 216, 3604000, 384, 384, 0, 3604, 0, + 2, 0, 0, 0, 216, 4320000, 576, 384, 0, 4320, 0, + 3, 0, 0, 0, 216, 4436000, 768, 384, 0, 4436, 0, + 4, 0, 0, 0, 216, 7792000, 768, 384, 0, 7792, 0, + 5, 0, 0, 0, 216, 4332000, 768, 384, 0, 4332, 0, + 6, 0, 0, 0, 216, 4412000, 768, 192, 0, 4412, 0, + 7, 0, 0, 0, 216, 4404000, 960, 192, 0, 4404, 0, + 8, 0, 0, 0, 216, 4420000, 1152, 192, 0, 4420, 0, + 9, 0, 0, 0, 216, 4464000, 1536, 192, 0, 4464, 0, + 10, 0, 0, 0, 216, 3616000, 192, 384, 0, 3616, 0, + 11, 0, 0, 0, 216, 4300000, 960, 384, 0, 4300, 0, + 12, 0, 0, 0, 216, 4740000, 1152, 384, 0, 4740, 0, + 13, 0, 0, 0, 216, 4844000, 1536, 384, 0, 4844, 0, + 14, 0, 0, 0, 216, 4660000, 192, 1152, 0, 4660, 0, + 15, 0, 0, 0, 216, 4548000, 384, 1152, 0, 4548, 0, + 16, 0, 0, 0, 216, 4596000, 768, 1152, 0, 4596, 0, + 17, 0, 0, 0, 216, 5572000, 1536, 1152, 0, 5572, 0, + 18, 0, 0, 0, 216, 4896000, 384, 1536, 0, 4896, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 216, 4841000, 384, 192, 0, 4841, 0, + 1, 0, 0, 0, 216, 4355000, 384, 384, 0, 4355, 0, + 2, 0, 0, 0, 216, 5079000, 576, 384, 0, 5079, 0, + 3, 0, 0, 0, 216, 5275000, 768, 384, 0, 5275, 0, + 4, 0, 0, 0, 216, 9177000, 768, 384, 0, 9177, 0, + 5, 0, 0, 0, 216, 5175000, 768, 384, 0, 5175, 0, + 6, 0, 0, 0, 216, 5141000, 768, 192, 0, 5141, 0, + 7, 0, 0, 0, 216, 5207000, 960, 192, 0, 5207, 0, + 8, 0, 0, 0, 216, 5367000, 1152, 192, 0, 5367, 0, + 9, 0, 0, 0, 216, 5485000, 1536, 192, 0, 5485, 0, + 10, 0, 0, 0, 216, 4469000, 192, 384, 0, 4469, 0, + 11, 0, 0, 0, 216, 5185000, 960, 384, 0, 5185, 0, + 12, 0, 0, 0, 216, 5405000, 1152, 384, 0, 5405, 0, + 13, 0, 0, 0, 216, 5691000, 1536, 384, 0, 5691, 0, + 14, 0, 0, 0, 216, 5577000, 192, 1152, 0, 5577, 0, + 15, 0, 0, 0, 216, 5311000, 384, 1152, 0, 5311, 0, + 16, 0, 0, 0, 216, 5323000, 768, 1152, 0, 5323, 0, + 17, 0, 0, 0, 216, 6269000, 1536, 1152, 0, 6269, 0, + 18, 0, 0, 0, 216, 5699000, 384, 1536, 0, 5699, 0] +#endif + + index = __COUNTER__ diff --git a/src/audio/up_down_mixer/up_down_mixer_coef.h b/src/audio/up_down_mixer/up_down_mixer_coef.h new file mode 100644 index 000000000000..2085b8e33720 --- /dev/null +++ b/src/audio/up_down_mixer/up_down_mixer_coef.h @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@intel.com> +// Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + +#include "up_down_mixer_ipc4.h" +#include <stdint.h> + +#if CONFIG_COMP_UP_DOWN_MIXER + +#define COMPUTE_COEFF_32BIT(counter, denominator) ((0x7fffffffULL * (counter)) / (denominator)) +#define COMPUTE_COEFF_16BIT(counter, denominator) ((0x7fffULL * (counter)) / (denominator)) + +const int32_t k_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_32BIT(1, 1), /* 1.0 - L */ + COMPUTE_COEFF_32BIT(707, 1000), /* 0.707 - Center */ + COMPUTE_COEFF_32BIT(1, 1), /* 1.0 - R */ + COMPUTE_COEFF_32BIT(707, 1000), /* 0.707 - Ls */ + COMPUTE_COEFF_32BIT(707, 1000), /* 0.707 - Rs */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_32BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_scaled_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_32BIT(414, 1000), /* 0.414 - L */ + COMPUTE_COEFF_32BIT(293, 1000), /* 0.293 - Center */ + COMPUTE_COEFF_32BIT(414, 1000), /* 0.414 - R */ + COMPUTE_COEFF_32BIT(293, 1000), /* 0.293 - Ls */ + COMPUTE_COEFF_32BIT(293, 1000), /* 0.293 - Rs */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_32BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_half_scaled_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_32BIT(586, 1000), /* 0.586 - L */ + COMPUTE_COEFF_32BIT(414, 1000), /* 0.414 - Center */ + COMPUTE_COEFF_32BIT(586, 1000), /* 0.586 - R */ + COMPUTE_COEFF_32BIT(414, 1000), /* 0.414 - Ls */ + COMPUTE_COEFF_32BIT(414, 1000), /* 0.414 - Rs */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_32BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_quatro_mono_scaled_lo_ro_downmix32bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_32BIT(293, 1000), /* 0.293 - L */ + COMPUTE_COEFF_32BIT(207, 1000), /* 0.207 - Center */ + COMPUTE_COEFF_32BIT(293, 1000), /* 0.293 - R */ + COMPUTE_COEFF_32BIT(207, 1000), /* 0.207 - Ls */ + COMPUTE_COEFF_32BIT(207, 1000), /* 0.207 - Rs */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_32BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_32BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_16BIT(1, 1), /* 1.0 - L */ + COMPUTE_COEFF_16BIT(707, 1000), /* 0.707 - Center */ + COMPUTE_COEFF_16BIT(1, 1), /* 1.0 - R */ + COMPUTE_COEFF_16BIT(707, 1000), /* 0.707 - Ls, Cs */ + COMPUTE_COEFF_16BIT(707, 1000), /* 0.707 - Rs */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_16BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_scaled_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_16BIT(414, 1000), /* 0.414 - L */ + COMPUTE_COEFF_16BIT(293, 1000), /* 0.293 - Center */ + COMPUTE_COEFF_16BIT(414, 1000), /* 0.414 - R */ + COMPUTE_COEFF_16BIT(293, 1000), /* 0.293 - Ls Cs */ + COMPUTE_COEFF_16BIT(293, 1000), /* 0.293 - Rs */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_16BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_half_scaled_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_16BIT(586, 1000), /* 0.586 - L */ + COMPUTE_COEFF_16BIT(414, 1000), /* 0.414 - Center */ + COMPUTE_COEFF_16BIT(586, 1000), /* 0.586 - R */ + COMPUTE_COEFF_16BIT(414, 1000), /* 0.414 - Ls Cs */ + COMPUTE_COEFF_16BIT(414, 1000), /* 0.414 - Rs */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_16BIT(000, 1000), /* 0.000 - LFE */ +}; + +const int32_t k_quatro_mono_scaled_lo_ro_downmix16bit[UP_DOWN_MIX_COEFFS_LENGTH] = { + COMPUTE_COEFF_16BIT(293, 1000), /* 0.293 - L */ + COMPUTE_COEFF_16BIT(207, 1000), /* 0.207 - Center */ + COMPUTE_COEFF_16BIT(293, 1000), /* 0.293 - R */ + COMPUTE_COEFF_16BIT(207, 1000), /* 0.207 - Ls */ + COMPUTE_COEFF_16BIT(207, 1000), /* 0.207 - Rs */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - LS */ + COMPUTE_COEFF_16BIT(100, 1000), /* 0.100 - RS */ + COMPUTE_COEFF_16BIT(000, 1000), /* 0.000 - LFE */ +}; + +#endif /* CONFIG_COMP_UP_DOWN_MIXER */ + diff --git a/src/audio/up_down_mixer/up_down_mixer_hifi3.c b/src/audio/up_down_mixer/up_down_mixer_hifi3.c new file mode 100644 index 000000000000..259cf5128b9f --- /dev/null +++ b/src/audio/up_down_mixer/up_down_mixer_hifi3.c @@ -0,0 +1,2101 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@intel.com> + +#include "up_down_mixer.h" + +#if defined(__XCC__) && XCHAL_HAVE_HIFI3 + +#include <xtensa/tie/xt_hifi3.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +void upmix32bit_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + /* Only load the channel if it's present. */ + ae_int32 *output_left = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT) << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_CENTER) << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT) << 2)); + ae_int32 *output_left_surround = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + ae_int32 *output_right_surround = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LFE) << 2)); + + ae_int32 *in_ptr = (ae_int32 *)in_data; + + for (i = 0; i < (in_size >> 2); ++i) { + output_left[i * 6] = in_ptr[i]; + output_right[i * 6] = in_ptr[i]; + output_center[i * 6] = 0; + output_left_surround[i * 6] = in_ptr[i]; + output_right_surround[i * 6] = in_ptr[i]; + output_lfe[i * 6] = 0; + } +} + +void upmix16bit_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + /* Only load the channel if it's present. */ + ae_int32 *output_left = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT) << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_CENTER) << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT) << 2)); + ae_int32 *output_left_surround = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + ae_int32 *output_right_surround = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LFE) << 2)); + + ae_int16 *in_ptr = (ae_int16 *)in_data; + + for (i = 0; i < (in_size >> 1); ++i) { + output_left[i * 6] = AE_MOVINT32_FROMINT16(in_ptr[i]) << 16; + output_right[i * 6] = AE_MOVINT32_FROMINT16(in_ptr[i]) << 16; + output_center[i * 6] = 0; + output_left_surround[i * 6] = AE_MOVINT32_FROMINT16(in_ptr[i]) << 16; + output_right_surround[i * 6] = AE_MOVINT32_FROMINT16(in_ptr[i]) << 16; + output_lfe[i * 6] = 0; + } +} + +void upmix32bit_2_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + const uint8_t left_slot = get_channel_location(out_channel_map, CHANNEL_LEFT); + const uint8_t center_slot = get_channel_location(out_channel_map, CHANNEL_CENTER); + const uint8_t right_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT); + uint8_t left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND); + uint8_t right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND); + const uint8_t lfe_slot = get_channel_location(out_channel_map, CHANNEL_LFE); + + /* Must support also 5.1 Surround */ + if (left_surround_slot == CHANNEL_INVALID && right_surround_slot == CHANNEL_INVALID) { + left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SIDE); + right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SIDE); + } + + ae_int32 *output_left = (ae_int32 *)(out_data + (left_slot << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + (center_slot << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + (right_slot << 2)); + ae_int32 *output_left_surround = (ae_int32 *)(out_data + (left_surround_slot << 2)); + ae_int32 *output_right_surround = (ae_int32 *)(out_data + (right_surround_slot << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + (lfe_slot << 2)); + + ae_int32 *in_left_ptr = (ae_int32 *)in_data; + ae_int32 *in_right_ptr = (ae_int32 *)(in_data + 4); + + for (i = 0; i < (in_size >> 3); ++i) { + output_left[i * 6] = in_left_ptr[i * 2]; + output_right[i * 6] = in_right_ptr[i * 2]; + output_center[i * 6] = 0; + output_left_surround[i * 6] = in_left_ptr[i * 2]; + output_right_surround[i * 6] = in_right_ptr[i * 2]; + output_lfe[i * 6] = 0; + } +} + +void upmix16bit_2_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + const uint8_t left_slot = get_channel_location(out_channel_map, CHANNEL_LEFT); + const uint8_t center_slot = get_channel_location(out_channel_map, CHANNEL_CENTER); + const uint8_t right_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT); + uint8_t left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND); + uint8_t right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND); + const uint8_t lfe_slot = get_channel_location(out_channel_map, CHANNEL_LFE); + + /* Must support also 5.1 Surround */ + if (left_surround_slot == CHANNEL_INVALID && right_surround_slot == CHANNEL_INVALID) { + left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SIDE); + right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SIDE); + } + + ae_int32 *output_left = (ae_int32 *)(out_data + (left_slot << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + (center_slot << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + (right_slot << 2)); + ae_int32 *output_left_surround = (ae_int32 *)(out_data + (left_surround_slot << 2)); + ae_int32 *output_right_surround = (ae_int32 *)(out_data + (right_surround_slot << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + (lfe_slot << 2)); + + ae_int16 *in_left_ptr = (ae_int16 *)in_data; + ae_int16 *in_right_ptr = (ae_int16 *)(in_data + 2); + + for (i = 0; i < (in_size >> 2); ++i) { + output_left[i * 6] = AE_MOVINT32_FROMINT16(in_left_ptr[i * 2]) << 16; + output_right[i * 6] = AE_MOVINT32_FROMINT16(in_right_ptr[i * 2]) << 16; + output_center[i * 6] = 0; + output_left_surround[i * 6] = AE_MOVINT32_FROMINT16(in_left_ptr[i * 2]) << 16; + output_right_surround[i * 6] = AE_MOVINT32_FROMINT16(in_right_ptr[i * 2]) << 16; + output_lfe[i * 6] = 0; + } +} + +void upmix32bit_2_0_to_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + /* Only load the channel if it's present. */ + ae_int32 *output_left = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT) << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_CENTER) << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT) << 2)); + ae_int32 *output_left_surround = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + ae_int32 *output_right_surround = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LFE) << 2)); + ae_int32 *output_left_side = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_LEFT_SIDE) << 2)); + ae_int32 *output_right_side = (ae_int32 *)(out_data + + (get_channel_location(out_channel_map, CHANNEL_RIGHT_SIDE) << 2)); + + ae_int32 *in_left_ptr = (ae_int32 *)in_data; + ae_int32 *in_right_ptr = (ae_int32 *)(in_data + 4); + + for (i = 0; i < (in_size >> 3); ++i) { + output_left[i * 8] = in_left_ptr[i * 2]; + output_right[i * 8] = in_right_ptr[i * 2]; + output_center[i * 8] = 0; + output_left_surround[i * 8] = in_left_ptr[i * 2]; + output_right_surround[i * 8] = in_right_ptr[i * 2]; + output_lfe[i * 8] = 0; + output_left_side[i * 8] = 0; + output_right_side[i * 8] = 0; + } +} + +void shiftcopy32bit_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_p24f *in_ptr = (ae_p24f *)in_data; + ae_p24x2f *out_ptr = (ae_p24x2f *)out_data; + + for (i = 0; i < (in_size >> 2); ++i) + out_ptr[i] = in_ptr[i]; +} + +void shiftcopy32bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + ae_p24x2f *in_ptr = (ae_p24x2f *)in_data; + ae_p24x2f *out_ptr = (ae_p24x2f *)out_data; + + for (i = 0; i < (in_size >> 3); ++i) + out_ptr[i] = in_ptr[i]; +} + +void downmix32bit_2_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_lfe; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_lfe_tmp = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_lfe = AE_SEL32_LL(P_coefficient_lfe_tmp, P_coefficient_lfe_tmp); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_lfe = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 2)); + + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_right; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + const ae_int32 *const end_input_left = input_left + (in_size / (sizeof(ae_int32))); + + while (input_left < end_input_left) { + /* update output left channel based on input left channel */ + AE_L32_IP(P_input_left, input_left, 12); + ae_f64 Q_tmp_left = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + /* update output right channel based on input right channel */ + AE_L32_IP(P_input_right, input_right, 12); + ae_f64 Q_tmp_right = AE_MULF32S_LL(P_input_right, P_coefficient_left_right); + + /* update output left and right channels based on input lfe channel */ + AE_L32_IP(P_input_lfe, input_lfe, 12); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_lfe); + AE_MULAF32S_LL(Q_tmp_right, P_input_lfe, P_coefficient_lfe); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + AE_S32_L_IP(P_output_left, output_left, 2 * 4); + AE_S32_L_IP(P_output_right, output_right, 2 * 4); + } +} + +void downmix32bit_3_0(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center_tmp = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center = AE_SEL32_LL(P_coefficient_center_tmp, P_coefficient_center_tmp); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + const ae_int32 *const end_input_left = input_left + (in_size / (sizeof(ae_int32))); + + while (input_left < end_input_left) { + ae_f64 Q_tmp_left; + ae_f64 Q_tmp_right; + + /* update output left channel based on input left channel */ + AE_L32_IP(P_input_left, input_left, 3 * sizeof(ae_int32)); + Q_tmp_left = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + /* update output left and right channels based on input center channel */ + AE_L32_IP(P_input_center, input_center, 3 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp_left, P_input_center, P_coefficient_center); + Q_tmp_right = AE_MULF32S_LH(P_input_center, P_coefficient_center); + + /* update output right channel based on input right channel */ + AE_L32_IP(P_input_right, input_right, 3 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + AE_S32_L_IP(P_output_left, output_left, 2 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right, output_right, 2 * sizeof(ae_int32)); + } +} + +void downmix32bit_3_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center_lfe; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_lfe = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 2)); + + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + const ae_int32 *const end_input_left = input_left + (in_size / (sizeof(ae_int32))); + + while (input_left < end_input_left) { + ae_f64 Q_tmp_left; + ae_f64 Q_tmp_right; + + AE_L32_IP(P_input_left, input_left, 4 * sizeof(ae_int32)); + Q_tmp_left = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_center, input_center, 4 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp_left, P_input_center, P_coefficient_center_lfe); + Q_tmp_right = AE_MULF32S_LH(P_input_center, P_coefficient_center_lfe); + + AE_L32_IP(P_input_right, input_right, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_lfe, input_lfe, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_center_lfe); + AE_MULAF32S_LL(Q_tmp_right, P_input_lfe, P_coefficient_center_lfe); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + AE_S32_L_IP(P_output_left, output_left, 2 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right, output_right, 2 * sizeof(ae_int32)); + } +} + +void downmix32bit(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + /* + * We have 6 coefficients (constant inside loop), 6 channels and only 8 + * AE_P registers. But each of those registers is 48bit or 2x24bit wide. + * Also many Hifi2 operations can use either lower or higher 24 bits from + * those registers. By combining 6 coefficients in pairs we save 3 AE_P + * registers. + */ + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + /* See what channels are available. */ + bool left = (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) != 0xF); + bool center = (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) != 0xF); + bool right = (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) != 0xF); + bool left_surround = + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) != 0xF); + bool right_surround = + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) != 0xF); + bool lfe = (get_channel_location(cd->in_channel_map, CHANNEL_LFE) != 0xF); + + /* Downmixer single load. */ + ae_int32 *input_left = NULL; + ae_int32 *input_center = NULL; + ae_int32 *input_right = NULL; + ae_int32 *input_left_surround = NULL; + ae_int32 *input_right_surround = NULL; + ae_int32 *input_lfe = NULL; + + /* Only load the channel if it's present. */ + if (left) { + input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + } + + if (center) { + input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + } + if (right) { + input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + } + if (left_surround) { + input_left_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + } + if (right_surround) { + input_right_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + } + if (lfe) { + input_lfe = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 2)); + } + + /** Calculate number of samples in a single channel. */ + uint32_t number_of_samples_in_one_channel = in_size / cd->in_channel_no; + + number_of_samples_in_one_channel >>= 2; + + /* Downmixer single store. */ + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + /* We will be using P & Q registers. */ + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_left_surround; + ae_int32x2 P_input_right_surround; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + /* + * Calculating this outside of the loop is significant performance + * improvement. The value of this expression was reevaluated in each + * * iteration when placed inside loop. + */ + int sample_offset = cd->in_channel_no << 2; + + for (i = 0; i < number_of_samples_in_one_channel; i++) { + /* Zero-out the Q register first. */ + ae_f64 Q_tmp_left = AE_ZERO64(); + ae_f64 Q_tmp_right = AE_ZERO64(); + + /* Load one 24-bit value, replicate in two elements of register P. */ + if (left) { + P_input_left = AE_L32_X(input_left, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_left, P_coefficient_left_right); + } + if (center) { + P_input_center = AE_L32_X(input_center, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_center, P_coefficient_center_lfe); + AE_MULAF32S_LH(Q_tmp_right, P_input_center, P_coefficient_center_lfe); + } + if (right) { + P_input_right = AE_L32_X(input_right, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + } + if (left_surround) { + P_input_left_surround = AE_L32_X(input_left_surround, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_surround, + P_coefficient_left_s_right_s); + + if (cd->in_channel_config == IPC4_CHANNEL_CONFIG_4_POINT_0) { + AE_MULAF32S_LH(Q_tmp_right, + P_input_left_surround, + P_coefficient_left_s_right_s); + } + } + if (right_surround) { + P_input_right_surround = + AE_L32_X(input_right_surround, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_right, P_input_right_surround, + P_coefficient_left_s_right_s); + } + if (lfe) { + P_input_lfe = AE_L32_X(input_lfe, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_center_lfe); + AE_MULAF32S_LL(Q_tmp_right, P_input_lfe, P_coefficient_center_lfe); + } + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + output_left[i * 2] = P_output_left; + output_right[i * 2] = P_output_right; + } +} + +void downmix32bit_4_0(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_left_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_left_surround; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + const ae_int32 *const end_input_left = input_left + (in_size / (sizeof(ae_int32))); + + while (input_left < end_input_left) { + ae_f64 Q_tmp_left; + ae_f64 Q_tmp_right; + + AE_L32_IP(P_input_left, input_left, 4 * sizeof(ae_int32)); + Q_tmp_left = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_center, input_center, 4 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp_left, P_input_center, P_coefficient_center_lfe); + Q_tmp_right = AE_MULF32S_LH(P_input_center, P_coefficient_center_lfe); + + AE_L32_IP(P_input_right, input_right, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + + /* for 4.0 left surround if propagated to both left and right output channels */ + AE_L32_IP(P_input_left_surround, input_left_surround, 4 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_surround, P_coefficient_left_s_right_s); + AE_MULAF32S_LH(Q_tmp_right, P_input_left_surround, P_coefficient_left_s_right_s); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + AE_S32_L_IP(P_output_left, output_left, 2 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right, output_right, 2 * sizeof(ae_int32)); + } +} + +void downmix32bit_5_0_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center_cs; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_cs = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER_SURROUND << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center_cs = AE_SEL32_LL(P_coefficient_center, P_coefficient_cs); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_cs = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER_SURROUND) << 2)); + + ae_int32 *output = (ae_int32 *)(out_data); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_cs; + + ae_int32x2 P_output; + + const uint32_t channel_no = 5; + + for (i = 0; i < in_size / (sizeof(ae_int32)); i += channel_no) { + ae_f64 Q_tmp; + + AE_L32_IP(P_input_left, input_left, 5 * sizeof(ae_int32)); + Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_center, input_center, 5 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp, P_input_center, P_coefficient_center_cs); + + AE_L32_IP(P_input_right, input_right, 5 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_cs, input_cs, 5 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_cs, P_coefficient_center_cs); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + AE_S32_L_IP(P_output, output, sizeof(ae_int32)); + } +} + +void downmix32bit_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + const uint8_t left_slot = get_channel_location(cd->in_channel_map, CHANNEL_LEFT); + const uint8_t center_slot = get_channel_location(cd->in_channel_map, CHANNEL_CENTER); + const uint8_t right_slot = get_channel_location(cd->in_channel_map, CHANNEL_RIGHT); + uint8_t left_surround_slot = get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND); + uint8_t right_surround_slot = get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND); + const uint8_t lfe_slot = get_channel_location(cd->in_channel_map, CHANNEL_LFE); + + /* Must support also 5.1 Surround */ + const bool surround_5_1_channel_map = (left_surround_slot == CHANNEL_INVALID) && + (right_surround_slot == CHANNEL_INVALID); + + if (surround_5_1_channel_map) { + left_surround_slot = get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SIDE); + right_surround_slot = get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SIDE); + } + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + if (surround_5_1_channel_map) { + P_coefficient_left_surround = AE_L32_X((ae_int32 *)cd->downmix_coefficients, + CHANNEL_LEFT_SIDE << 2); + P_coefficient_right_surround = AE_L32_X((ae_int32 *)cd->downmix_coefficients, + CHANNEL_RIGHT_SIDE << 2); + } + + /* + * We have 6 coefficients (constant inside loop), 6 channels and only 8 + * AE_P registers. But each of those registers is 48bit or 2x24bit wide. + * Also many Hifi2 operations can use either lower or higher 24 bits from + * those registers. By combining 6 coefficients in pairs we save 3 AE_P + * registers. + */ + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + const ae_int32 *input_left = (ae_int32 *)(in_data + (left_slot << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + (center_slot << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + (right_slot << 2)); + const ae_int32 *input_left_surround = (ae_int32 *)(in_data + (left_surround_slot << 2)); + const ae_int32 *input_right_surround = (ae_int32 *)(in_data + (right_surround_slot << 2)); + const ae_int32 *input_lfe = (ae_int32 *)(in_data + (lfe_slot << 2)); + + /* Downmixer single store. */ + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + /* We will be using P & Q registers. */ + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_left_surround; + ae_int32x2 P_input_right_surround; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + /* + * We don't need to initialize those registers in loop's body. + * Using non accumulating multiplication for the first left,rignt channels + * is more efficient. + * For non 5.1 version we cannot use this optimization, we don't know + * which channel is present and which multiplication should reset output + * accumulators. + */ + ae_f64 Q_tmp_left = AE_ZERO64(); + ae_f64 Q_tmp_right = AE_ZERO64(); + + const ae_int32 *const end_input_left = input_left + (in_size / (sizeof(ae_int32))); + + while (input_left < end_input_left) { + /* Load one 24-bit value, replicate in two elements of register P. */ + AE_L32_IP(P_input_center, input_center, 6 * sizeof(ae_int32)); + Q_tmp_left = AE_MULF32S_LH(P_input_center, P_coefficient_center_lfe); + + AE_L32_IP(P_input_lfe, input_lfe, 6 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_center_lfe); + + Q_tmp_right = Q_tmp_left; + + AE_L32_IP(P_input_left, input_left, 6 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp_left, P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_right, input_right, 6 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_left_surround, input_left_surround, 6 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_surround, P_coefficient_left_s_right_s); + + AE_L32_IP(P_input_right_surround, input_right_surround, 6 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp_right, P_input_right_surround, P_coefficient_left_s_right_s); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + AE_S32_L_IP(P_output_left, output_left, 2 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right, output_right, 2 * sizeof(ae_int32)); + } +} + +void downmix32bit_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + ae_int32x2 P_coefficient_left_S_right_S; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + ae_int32x2 P_coefficient_left_side = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SIDE << 2); + ae_int32x2 P_coefficient_right_side = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SIDE << 2); + + /* + * We have 6 coefficients (constant inside loop), 6 channels and only 8 + * AE_P registers. But each of those registers is 48bit or 2x24bit wide. + * Also many Hifi2 operations can use either lower or higher 24 bits from + * those registers. By combining 6 coefficients in pairs we save 3 AE_P + * registers. + */ + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + P_coefficient_left_S_right_S = AE_SEL32_LL(P_coefficient_left_side, + P_coefficient_right_side); + + /* Only load the channel if it's present. */ + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_left_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + const ae_int32 *input_right_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + const ae_int32 *input_lfe = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 2)); + const ae_int32 *input_left_side = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SIDE) << 2)); + const ae_int32 *input_right_side = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SIDE) << 2)); + + /* Downmixer single store. */ + ae_int32 *output_left = (ae_int32 *)(out_data); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + /* We will be using P & Q registers. */ + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_left_surround; + ae_int32x2 P_input_right_surround; + ae_int32x2 P_input_lfe; + ae_int32x2 P_input_left_side; + ae_int32x2 P_input_right_side; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + /* + * We don't need to initialize those registers in loop's body. + * Using non accumulating multiplication for the first left,rignt channels + * is more efficient. + * For non 5.1 version we cannot use this optimization, we don't know + * which channel is present and which multiplication should reset output + * accumulators. + */ + ae_f64 Q_tmp_left = AE_ZERO64(); + ae_f64 Q_tmp_right = AE_ZERO64(); + + const ae_int32 *const end_input_left = input_left + (in_size / (sizeof(ae_int32))); + const char cs = 8 * sizeof(ae_int32); + + while (input_left < end_input_left) { + /* Load one 24-bit value, replicate in two elements of register P. */ + AE_L32_XP(P_input_center, input_center, cs); + Q_tmp_left = AE_MULF32S_LH(P_input_center, P_coefficient_center_lfe); + + AE_L32_XP(P_input_lfe, input_lfe, cs); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_center_lfe); + + Q_tmp_right = Q_tmp_left; + + AE_L32_XP(P_input_left, input_left, cs); + AE_MULAF32S_LH(Q_tmp_left, P_input_left, P_coefficient_left_right); + + AE_L32_XP(P_input_right, input_right, cs); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + + AE_L32_XP(P_input_left_surround, input_left_surround, cs); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_surround, P_coefficient_left_s_right_s); + + AE_L32_XP(P_input_right_surround, input_right_surround, cs); + AE_MULAF32S_LL(Q_tmp_right, P_input_right_surround, P_coefficient_left_s_right_s); + + AE_L32_XP(P_input_left_side, input_left_side, cs); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_side, P_coefficient_left_S_right_S); + + AE_L32_XP(P_input_right_side, input_right_side, cs); + AE_MULAF32S_LL(Q_tmp_right, P_input_right_side, P_coefficient_left_S_right_S); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + AE_S32_L_IP(P_output_left, output_left, 2 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right, output_right, 2 * sizeof(ae_int32)); + } +} + +void shiftcopy16bit_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + ae_int16 *in_ptrs = (ae_int16 *)in_data; + ae_int32x2 *out_ptrs = (ae_int32x2 *)out_data; + + for (i = 0; i < (in_size >> 1); ++i) + out_ptrs[i] = AE_MOVINT32_FROMINT16(in_ptrs[i]) << 16; +} + +void shiftcopy16bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + ae_p16x2s *in_ptrs = (ae_p16x2s *)in_data; + ae_p24x2f *out_ptrs = (ae_p24x2f *)out_data; + ae_p24x2s in_regs = AE_ZEROP48(); + + for (i = 0; i < (in_size >> 2); ++i) { + in_regs = in_ptrs[i]; + AE_SP24X2F_X(in_regs, out_ptrs, i << 3); + } +} + +void downmix16bit(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + /* + * We have 6 coefficients (constant inside loop), 6 channels and only 8 + * AE_P registers. But each of those registers is 48bit or 2x24bit wide. + * Also many Hifi2 operations can use either lower or higher 24 bits from + * those registers. By combining 6 coefficients in pairs we save 3 AE_P + * registers. + */ + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + /* See what channels are available. */ + bool left = (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) != 0xF); + bool center = (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) != 0xF); + bool right = (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) != 0xF); + bool left_surround = + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) != 0xF); + bool right_surround = + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) != 0xF); + bool lfe = (get_channel_location(cd->in_channel_map, CHANNEL_LFE) != 0xF); + + /* Downmixer single load. */ + ae_p16s *input_left = NULL; + ae_p16s *input_center = NULL; + ae_p16s *input_right = NULL; + ae_p16s *input_left_surround = NULL; + ae_p16s *input_right_surround = NULL; + ae_p16s *input_lfe = NULL; + + /* Only load the channel if it's present. */ + if (left) { + input_left = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 1)); + } + if (center) { + input_center = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 1)); + } + if (right) { + input_right = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 1)); + } + if (left_surround) { + input_left_surround = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 1)); + } + if (right_surround) { + input_right_surround = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) << 1)); + } + if (lfe) { + input_lfe = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 1)); + } + + /** Calculate number of samples in a single channel. */ + uint32_t number_of_samples_in_one_channel = in_size / cd->in_channel_no; + + number_of_samples_in_one_channel >>= 1; + + /* Downmixer single store. */ + ae_int32 *output_left = (ae_int32 *)(out_data + 0); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_left_surround; + ae_int32x2 P_input_right_surround; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + /* + * Calculating this outside of the loop is significant performance + * improvement. The value of this expression was reevaluated in each + * iteration when placed inside loop. + */ + int sample_offset = cd->in_channel_no << 1; + + for (i = 0; i < (number_of_samples_in_one_channel); i++) { + ae_f64 Q_tmp_left = AE_ZEROQ56(); + ae_f64 Q_tmp_right = AE_ZEROQ56(); + + /* Load one 24-bit value, replicate in two elements of register P. */ + if (left) { + P_input_left = AE_L16M_X(input_left, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_left, P_coefficient_left_right); + } + if (center) { + P_input_center = AE_L16M_X(input_center, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_center, P_coefficient_center_lfe); + AE_MULAF32S_LH(Q_tmp_right, P_input_center, P_coefficient_center_lfe); + } + if (right) { + P_input_right = AE_L16M_X(input_right, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + } + if (left_surround) { + P_input_left_surround = AE_L16M_X(input_left_surround, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_surround, + P_coefficient_left_s_right_s); + if (cd->in_channel_config == IPC4_CHANNEL_CONFIG_4_POINT_0) { + AE_MULAF32S_LH(Q_tmp_right, P_input_left_surround, + P_coefficient_left_s_right_s); + } + } + if (right_surround) { + P_input_right_surround = AE_L16M_X(input_right_surround, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_right, P_input_right_surround, + P_coefficient_left_s_right_s); + } + if (lfe) { + P_input_lfe = AE_L16M_X(input_lfe, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_center_lfe); + AE_MULAF32S_LL(Q_tmp_right, P_input_lfe, P_coefficient_center_lfe); + } + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + output_left[i * 2] = AE_SLAI32(P_output_left, 2 * sizeof(ae_int32)); + output_right[i * 2] = AE_SLAI32(P_output_right, 2 * sizeof(ae_int32)); + } +} + +void downmix16bit_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + /* Downmixer single load. */ + ae_p16s *input_left = NULL; + ae_p16s *input_center = NULL; + ae_p16s *input_right = NULL; + ae_p16s *input_left_surround = NULL; + ae_p16s *input_right_surround = NULL; + ae_p16s *input_lfe = NULL; + + /* Only load the channel if it's present. */ + input_left = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 1)); + input_center = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 1)); + input_right = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 1)); + input_left_surround = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 1)); + input_right_surround = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) << 1)); + input_lfe = (ae_p16s *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 1)); + + /** Calculate number of samples in a single channel. */ + uint32_t number_of_samples_in_one_channel = in_size / cd->in_channel_no; + + number_of_samples_in_one_channel >>= 1; + + /* Downmixer single store. */ + ae_int32 *output_left = (ae_int32 *)(out_data + 0); + ae_int32 *output_right = (ae_int32 *)(out_data + sizeof(ae_int32)); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_left_surround; + ae_int32x2 P_input_right_surround; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + /* + * We don't need to initialize those registers in loop's body. + * Using non accumulating multiplication for the first left,rignt channels + * is more efficient. + * For non 5.1 version we cannot use this optimization, we don't know + * which channel is present and which multiplication should reset output + * accumulators. + */ + ae_f64 Q_tmp_left = AE_ZERO64(); + ae_f64 Q_tmp_right = AE_ZERO64(); + + /* + * Calculating this outside of the loop is significant performance + * improvement. The value of this expression was reevaluated in each + * iteration when placed inside loop. + */ + int sample_offset = cd->in_channel_no << 1; + /* 0.011xSR(k) MIPS */ + for (i = 0; i < (number_of_samples_in_one_channel); i++) { + /* Load one 16-bit value, replicate in two elements of register P. */ + P_input_center = AE_L16M_X(input_center, i * sample_offset); + Q_tmp_left = AE_MULF32S_LH(P_input_center, P_coefficient_center_lfe); + + P_input_lfe = AE_L16M_X(input_lfe, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_left, P_input_lfe, P_coefficient_center_lfe); + + Q_tmp_right = Q_tmp_left; + + P_input_left = AE_L16M_X(input_left, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_left, P_coefficient_left_right); + + P_input_right = AE_L16M_X(input_right, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_right, P_input_right, P_coefficient_left_right); + + P_input_left_surround = AE_L16M_X(input_left_surround, i * sample_offset); + AE_MULAF32S_LH(Q_tmp_left, P_input_left_surround, P_coefficient_left_s_right_s); + + P_input_right_surround = AE_L16M_X(input_right_surround, i * sample_offset); + AE_MULAF32S_LL(Q_tmp_right, P_input_right_surround, P_coefficient_left_s_right_s); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right); + + output_left[i * 2] = AE_SLAI32(P_output_left, 2 * sizeof(ae_int32)); + output_right[i * 2] = AE_SLAI32(P_output_right, 2 * sizeof(ae_int32)); + } +} + +void downmix16bit_4ch_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + uint32_t idx1 = get_channel_index(cd->in_channel_map, 0); + uint32_t idx2 = get_channel_index(cd->in_channel_map, 1); + uint32_t idx3 = get_channel_index(cd->in_channel_map, 2); + uint32_t idx4 = get_channel_index(cd->in_channel_map, 3); + + uint16_t coeffs[4] = {cd->downmix_coefficients[idx1], + cd->downmix_coefficients[idx2], + cd->downmix_coefficients[idx3], + cd->downmix_coefficients[idx4] + }; + + ae_int16x4 coeff = AE_L16X4_X((ae_int16x4 *)coeffs, 0); + + const ae_int16x4 *input_data = (const ae_int16x4 *)in_data; + ae_int16 *output_data = (ae_int16 *)out_data; + + ae_int16x4 P_input; + ae_int16x4 P_output; + + const uint32_t channel_no = 4; + + for (i = 0; i < in_size / (sizeof(int16_t)); i += channel_no) { + AE_L16X4_XP(P_input, input_data, sizeof(ae_int16) * channel_no); + ae_f32x2 Q_tmp = AE_MULF16SS_00(P_input, coeff); + + AE_MULAF16SS_11(Q_tmp, P_input, coeff); + AE_MULAF16SS_22(Q_tmp, P_input, coeff); + AE_MULAF16SS_33(Q_tmp, P_input, coeff); + + P_output = AE_ROUND16X4F32SSYM(Q_tmp, Q_tmp); + AE_S16_0_IP(P_output, output_data, sizeof(ae_int16)); + } +} + +void downmix32bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + uint32_t downmix_coefficient = 1073741568; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left_right = AE_L32_X((ae_int32 *)&downmix_coefficient, 0); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_right; + ae_int32x2 P_output; + + const ae_int32 *input_left = (ae_int32 *)in_data; + const ae_int32 *input_right = input_left + 1; + + ae_int32 *output = (ae_int32 *)(out_data); + + for (i = 0; i < (in_size >> 3); ++i) { + P_input_left = AE_L32_X(input_left, i * 2 * sizeof(ae_int32)); + ae_f64 Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + P_input_right = AE_L32_X(input_right, i * 2 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + output[i] = P_output; + } +} + +void downmix16bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t idx; + + /* TODO: optimize using Hifi3 */ + const uint16_t *in_data16 = (uint16_t *)in_data; + uint16_t *out_data16 = (uint16_t *)out_data; + + for (idx = 0; idx < (in_size / 4); ++idx) + out_data16[idx] = (in_data16[2 * idx] / 2) + (in_data16[2 * idx + 1] / 2); +} + +void downmix32bit_3_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center_lfe; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_lfe = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LFE) << 2)); + + ae_int32 *output = (ae_int32 *)(out_data); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_lfe; + + ae_int32x2 P_output; + + const uint32_t channel_no = 4; + + for (i = 0; i < in_size / (sizeof(ae_int32)); i += channel_no) { + ae_f64 Q_tmp; + + AE_L32_IP(P_input_left, input_left, 4 * sizeof(ae_int32)); + Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_center, input_center, 4 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp, P_input_center, P_coefficient_center_lfe); + + AE_L32_IP(P_input_right, input_right, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_lfe, input_lfe, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_lfe, P_coefficient_center_lfe); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + AE_S32_L_IP(P_output, output, sizeof(ae_int32)); + } +} + +void downmix32bit_4_0_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center_cs; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_cs = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER_SURROUND << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center_cs = AE_SEL32_LL(P_coefficient_center, P_coefficient_cs); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_cs = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER_SURROUND) << 2)); + + ae_int32 *output = (ae_int32 *)(out_data); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_cs; + + ae_int32x2 P_output; + + const uint32_t channel_no = 4; + + for (i = 0; i < in_size / (sizeof(ae_int32)); i += channel_no) { + ae_f64 Q_tmp; + + AE_L32_IP(P_input_left, input_left, 4 * sizeof(ae_int32)); + Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_center, input_center, 4 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp, P_input_center, P_coefficient_center_cs); + + AE_L32_IP(P_input_right, input_right, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_cs, input_cs, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_cs, P_coefficient_center_cs); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + AE_S32_L_IP(P_output, output, sizeof(ae_int32)); + } +} + +void downmix32bit_quatro_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_ls_rs; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_ls = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_rs = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_ls_rs = AE_SEL32_LL(P_coefficient_ls, P_coefficient_rs); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_ls = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_rs = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + + ae_int32 *output = (ae_int32 *)(out_data); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_ls; + ae_int32x2 P_input_right; + ae_int32x2 P_input_rs; + + ae_int32x2 P_output; + + const uint32_t channel_no = 4; + + for (i = 0; i < in_size / (sizeof(ae_int32)); i += channel_no) { + ae_f64 Q_tmp; + + AE_L32_IP(P_input_left, input_left, 4 * sizeof(ae_int32)); + Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_ls, input_ls, 4 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp, P_input_ls, P_coefficient_ls_rs); + + AE_L32_IP(P_input_right, input_right, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_rs, input_rs, 4 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_rs, P_coefficient_ls_rs); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + AE_S32_L_IP(P_output, output, sizeof(ae_int32)); + } +} + +void downmix32bit_5_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center_cs; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_cs = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER_SURROUND << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center_cs = AE_SEL32_LL(P_coefficient_center, P_coefficient_cs); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_cs = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER_SURROUND) << 2)); + + ae_int32 *output = (ae_int32 *)(out_data); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_cs; + + ae_int32x2 P_output; + + const uint32_t channel_no = 6; + + for (i = 0; i < in_size / (sizeof(ae_int32)); i += channel_no) { + ae_f64 Q_tmp; + + AE_L32_IP(P_input_left, input_left, 6 * sizeof(ae_int32)); + Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_IP(P_input_center, input_center, 6 * sizeof(ae_int32)); + AE_MULAF32S_LH(Q_tmp, P_input_center, P_coefficient_center_cs); + + AE_L32_IP(P_input_right, input_right, 6 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + AE_L32_IP(P_input_cs, input_cs, 6 * sizeof(ae_int32)); + AE_MULAF32S_LL(Q_tmp, P_input_cs, P_coefficient_center_cs); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + AE_S32_L_IP(P_output, output, sizeof(ae_int32)); + } +} + +void downmix32bit_7_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + size_t i; + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_center_cs; + + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_cs = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER_SURROUND << 2); + + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_center_cs = AE_SEL32_LL(P_coefficient_center, P_coefficient_cs); + + const ae_int32 *input_left = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT) << 2)); + const ae_int32 *input_center = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER) << 2)); + const ae_int32 *input_right = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT) << 2)); + const ae_int32 *input_cs = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER_SURROUND) << 2)); + + ae_int32 *output = (ae_int32 *)(out_data); + + ae_int32x2 P_input_left; + ae_int32x2 P_input_center; + ae_int32x2 P_input_right; + ae_int32x2 P_input_cs; + + ae_int32x2 P_output; + + const uint32_t channel_no = 8; + const size_t offset = sizeof(ae_int32) * channel_no; + + for (i = 0; i < in_size / (sizeof(ae_int32)); i += channel_no) { + ae_f64 Q_tmp; + + AE_L32_XP(P_input_left, input_left, offset); + Q_tmp = AE_MULF32S_LH(P_input_left, P_coefficient_left_right); + + AE_L32_XP(P_input_center, input_center, offset); + AE_MULAF32S_LH(Q_tmp, P_input_center, P_coefficient_center_cs); + + AE_L32_XP(P_input_right, input_right, offset); + AE_MULAF32S_LL(Q_tmp, P_input_right, P_coefficient_left_right); + + AE_L32_XP(P_input_cs, input_cs, offset); + AE_MULAF32S_LL(Q_tmp, P_input_cs, P_coefficient_center_cs); + + P_output = AE_ROUND32F64SSYM(Q_tmp); + + AE_S32_L_IP(P_output, output, sizeof(ae_int32)); + } +} + +void downmix32bit_7_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + const uint8_t left_slot = get_channel_location(out_channel_map, CHANNEL_LEFT); + const uint8_t center_slot = get_channel_location(out_channel_map, CHANNEL_CENTER); + const uint8_t right_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT); + uint8_t right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND); + uint8_t left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND); + const uint8_t lfe_slot = get_channel_location(out_channel_map, CHANNEL_LFE); + + /* Must support also 5.1 Surround */ + const bool surround_5_1_channel_map = (left_surround_slot == CHANNEL_INVALID) && + (right_surround_slot == CHANNEL_INVALID); + + if (surround_5_1_channel_map) { + left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SIDE); + right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SIDE); + } + + ae_int32 *output_left_ptr = (ae_int32 *)(out_data + (left_slot << 2)); + ae_int32 *output_center_ptr = (ae_int32 *)(out_data + (center_slot << 2)); + ae_int32 *output_right_ptr = (ae_int32 *)(out_data + (right_slot << 2)); + ae_int32 *output_side_left_ptr = (ae_int32 *)(out_data + (left_surround_slot << 2)); + ae_int32 *output_side_right_ptr = (ae_int32 *)(out_data + (right_surround_slot << 2)); + ae_int32 *output_lfe_ptr = (ae_int32 *)(out_data + (lfe_slot << 2)); + + ae_int32 *in_left_ptr = (ae_int32 *)in_data; + ae_int32 *in_center_ptr = (ae_int32 *)(in_data + 4); + ae_int32 *in_right_ptr = (ae_int32 *)(in_data + 8); + ae_int32 *in_lfe_ptr = (ae_int32 *)(in_data + 20); + + for (i = 0; i < (in_size >> 5); ++i) { + output_left_ptr[i * 6] = in_left_ptr[i * 8]; + output_right_ptr[i * 6] = in_right_ptr[i * 8]; + output_center_ptr[i * 6] = in_center_ptr[i * 8]; + output_lfe_ptr[i * 6] = in_lfe_ptr[i * 8]; + } + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + ae_int32x2 P_coefficient_left_S_right_S; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + ae_int32x2 P_coefficient_left_side = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SIDE << 2); + ae_int32x2 P_coefficient_right_side = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SIDE << 2); + + /* + * We have 6 coefficients (constant inside loop), 6 channels and only 8 + * AE_P registers. But each of those registers is 48bit or 2x24bit wide. + * Also many Hifi2 operations can use either lower or higher 24 bits from + * those registers. By combining 6 coefficients in pairs we save 3 AE_P + * registers. + */ + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + P_coefficient_left_S_right_S = AE_SEL32_LL(P_coefficient_left_side, + P_coefficient_right_side); + + const ae_int32 *input_left_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SURROUND) << 2)); + const ae_int32 *input_right_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SURROUND) << 2)); + const ae_int32 *input_left_side = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SIDE) << 2)); + const ae_int32 *input_right_side = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SIDE) << 2)); + + /* We will be using P & Q registers. */ + ae_int32x2 P_input_left_surround; + ae_int32x2 P_input_right_surround; + ae_int32x2 P_input_left_side; + ae_int32x2 P_input_right_side; + + ae_int32x2 P_output_left; + ae_int32x2 P_output_right; + + const ae_int32 *const end_input_left = input_left_surround + (in_size / (sizeof(ae_int32))); + const char cs = 8 * sizeof(ae_int32); + + while (input_left_surround < end_input_left) { + ae_f64 Q_tmp_right_side; + ae_f64 Q_tmp_left_side; + + /* Load one 24-bit value, replicate in two elements of register P. */ + AE_L32_XP(P_input_left_surround, input_left_surround, cs); + Q_tmp_left_side = AE_MULF32S_LH(P_input_left_surround, P_coefficient_left_right); + Q_tmp_right_side = AE_MULF32S_LL(P_input_left_surround, P_coefficient_left_S_right_S); + + AE_L32_XP(P_input_right_surround, input_right_surround, cs); + AE_MULAF32S_LH(Q_tmp_left_side, P_input_right_surround, P_coefficient_left_S_right_S); + AE_MULAF32S_LL(Q_tmp_right_side, P_input_right_surround, P_coefficient_left_right); + + AE_L32_XP(P_input_left_side, input_left_side, cs); + AE_MULAF32S_LH(Q_tmp_left_side, P_input_left_side, P_coefficient_left_right); + + AE_L32_XP(P_input_right_side, input_right_side, cs); + AE_MULAF32S_LL(Q_tmp_right_side, P_input_right_side, P_coefficient_left_right); + + P_output_left = AE_ROUND32F64SSYM(Q_tmp_left_side); + P_output_right = AE_ROUND32F64SSYM(Q_tmp_right_side); + + AE_S32_L_IP(P_output_left, output_side_left_ptr, 6 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right, output_side_right_ptr, 6 * sizeof(ae_int32)); + } +} + +void upmix32bit_4_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + const uint8_t left_slot = get_channel_location(out_channel_map, CHANNEL_LEFT); + const uint8_t center_slot = get_channel_location(out_channel_map, CHANNEL_CENTER); + const uint8_t right_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT); + uint8_t right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND); + uint8_t left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND); + const uint8_t lfe_slot = get_channel_location(out_channel_map, CHANNEL_LFE); + + /* Must support also 5.1 Surround */ + const bool surround_5_1_channel_map = (left_surround_slot == CHANNEL_INVALID) && + (right_surround_slot == CHANNEL_INVALID); + + if (surround_5_1_channel_map) { + left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SIDE); + right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SIDE); + } + + ae_int32 *output_left = (ae_int32 *)(out_data + (left_slot << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + (center_slot << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + (right_slot << 2)); + ae_int32 *output_side_left = (ae_int32 *)(out_data + (left_surround_slot << 2)); + ae_int32 *output_side_right = (ae_int32 *)(out_data + (right_surround_slot << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + (lfe_slot << 2)); + + ae_int32 *in_left_ptr = (ae_int32 *)in_data; + ae_int32 *in_center_ptr = (ae_int32 *)(in_data + 4); + ae_int32 *in_right_ptr = (ae_int32 *)(in_data + 8); + + for (i = 0; i < (in_size >> 4); ++i) { + output_left[i * 6] = in_left_ptr[i * 4]; + output_right[i * 6] = in_right_ptr[i * 4]; + output_center[i * 6] = in_center_ptr[i * 4]; + output_lfe[i * 6] = 0; + } + + ae_int32x2 P_coefficient_left_right; + ae_int32x2 P_coefficient_left_s_right_s; + ae_int32x2 P_coefficient_center_lfe; + ae_int32x2 P_coefficient_left_S_right_S; + + /* Load the downmix coefficients. */ + ae_int32x2 P_coefficient_left = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT << 2); + ae_int32x2 P_coefficient_center = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_CENTER << 2); + ae_int32x2 P_coefficient_right = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT << 2); + ae_int32x2 P_coefficient_left_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SURROUND << 2); + ae_int32x2 P_coefficient_right_surround = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SURROUND << 2); + ae_int32x2 P_coefficient_lfe = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LFE << 2); + ae_int32x2 P_coefficient_left_side = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_LEFT_SIDE << 2); + ae_int32x2 P_coefficient_right_side = + AE_L32_X((ae_int32 *)cd->downmix_coefficients, CHANNEL_RIGHT_SIDE << 2); + + /* + * We have 6 coefficients (constant inside loop), 6 channels and only 8 + * AE_P registers. But each of those registers is 48bit or 2x24bit wide. + * Also many Hifi2 operations can use either lower or higher 24 bits from + * those registers. By combining 6 coefficients in pairs we save 3 AE_P + * registers. + */ + P_coefficient_left_right = AE_SEL32_LL(P_coefficient_left, P_coefficient_right); + P_coefficient_left_s_right_s = AE_SEL32_LL(P_coefficient_left_surround, + P_coefficient_right_surround); + P_coefficient_center_lfe = AE_SEL32_LL(P_coefficient_center, P_coefficient_lfe); + P_coefficient_left_S_right_S = AE_SEL32_LL(P_coefficient_left_side, + P_coefficient_right_side); + + const ae_int32 *input_center_surround = (ae_int32 *)(in_data + + (get_channel_location(cd->in_channel_map, CHANNEL_CENTER_SURROUND) << 2)); + + /* We will be using P & Q registers. */ + ae_int32x2 P_input_center_surround; + + ae_int32x2 P_output_left_side; + ae_int32x2 P_output_right_side; + + /* + * We don't need to initialize those registers in loop's body. + * Using non accumulating multiplication for the first left,rignt channels + * is more efficient. + * For non 5.1 version we cannot use this optimization, we don't know + * which channel is present and which multiplication should reset output + * accumulators. + */ + ae_f64 Q_tmp_right_side = AE_ZERO64(); + ae_f64 Q_tmp_left_side = AE_ZERO64(); + + const ae_int32 *const end_input_left = input_center_surround + (in_size / (sizeof(ae_int32))); + const char cs = 4 * sizeof(ae_int32); + + while (input_center_surround < end_input_left) { + /* Load one 24-bit value, replicate in two elements of register P. */ + AE_L32_XP(P_input_center_surround, input_center_surround, cs); + Q_tmp_left_side = AE_MULF32S_LH(P_input_center_surround, + P_coefficient_left_s_right_s); + Q_tmp_right_side = AE_MULF32S_LL(P_input_center_surround, + P_coefficient_left_s_right_s); + + P_output_left_side = AE_ROUND32F64SSYM(Q_tmp_left_side); + P_output_right_side = AE_ROUND32F64SSYM(Q_tmp_right_side); + + AE_S32_L_IP(P_output_left_side, output_side_left, 6 * sizeof(ae_int32)); + AE_S32_L_IP(P_output_right_side, output_side_right, 6 * sizeof(ae_int32)); + } +} + +void upmix32bit_quatro_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + uint32_t i; + + channel_map out_channel_map = cd->out_channel_map; + + const uint8_t left_slot = get_channel_location(out_channel_map, CHANNEL_LEFT); + const uint8_t center_slot = get_channel_location(out_channel_map, CHANNEL_CENTER); + const uint8_t right_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT); + uint8_t right_surround_slot = get_channel_location(out_channel_map, CHANNEL_RIGHT_SURROUND); + uint8_t left_surround_slot = get_channel_location(out_channel_map, CHANNEL_LEFT_SURROUND); + const uint8_t lfe_slot = get_channel_location(out_channel_map, CHANNEL_LFE); + + /* Must support also 5.1 Surround */ + const bool surround_5_1_channel_map = (left_surround_slot == CHANNEL_INVALID) && + (right_surround_slot == CHANNEL_INVALID); + + if (surround_5_1_channel_map) { + left_surround_slot = get_channel_location(cd->in_channel_map, CHANNEL_LEFT_SIDE); + right_surround_slot = get_channel_location(cd->in_channel_map, CHANNEL_RIGHT_SIDE); + } + + ae_int32 *output_left = (ae_int32 *)(out_data + (left_slot << 2)); + ae_int32 *output_center = (ae_int32 *)(out_data + (center_slot << 2)); + ae_int32 *output_right = (ae_int32 *)(out_data + (right_slot << 2)); + ae_int32 *output_side_left = (ae_int32 *)(out_data + (left_surround_slot << 2)); + ae_int32 *output_side_right = (ae_int32 *)(out_data + (right_surround_slot << 2)); + ae_int32 *output_lfe = (ae_int32 *)(out_data + (lfe_slot << 2)); + + ae_int32 *in_left_ptr = (ae_int32 *)in_data; + ae_int32 *in_right_ptr = (ae_int32 *)(in_data + 4); + ae_int32 *in_left_sorround_ptr = (ae_int32 *)(in_data + 8); + ae_int32 *in_right_sorround_ptr = (ae_int32 *)(in_data + 12); + + for (i = 0; i < (in_size >> 4); ++i) { + output_left[i * 6] = in_left_ptr[i * 4]; + output_right[i * 6] = in_right_ptr[i * 4]; + output_center[i * 6] = 0; + output_side_left[i * 6] = in_left_sorround_ptr[i * 4]; + output_side_right[i * 6] = in_right_sorround_ptr[i * 4]; + output_lfe[i * 6] = 0; + } +} + +#else /* !XCHAL_HAVE_HIFI3 */ + +/* TODO: replace with generic ANSI C version */ + +void upmix32bit_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void upmix16bit_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void upmix32bit_2_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void upmix16bit_2_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void upmix32bit_2_0_to_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void shiftcopy32bit_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void shiftcopy32bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_2_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_3_0(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_3_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_4_0(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_5_0_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix16bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ +} + +void shiftcopy16bit_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void shiftcopy16bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix16bit(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix16bit_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix16bit_4ch_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_stereo(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_3_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_4_0_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_quatro_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_5_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_7_1_mono(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void downmix32bit_7_1_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void upmix32bit_4_0_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +void upmix32bit_quatro_to_5_1(struct up_down_mixer_data *cd, const uint8_t * const in_data, + const uint32_t in_size, uint8_t * const out_data) +{ + sof_panic(0); +} + +#endif diff --git a/src/audio/up_down_mixer/up_down_mixer_ipc4.h b/src/audio/up_down_mixer/up_down_mixer_ipc4.h new file mode 100644 index 000000000000..5300f5cb71d4 --- /dev/null +++ b/src/audio/up_down_mixer/up_down_mixer_ipc4.h @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@intel.com> + +#ifndef __SOF_IPC4_UP_DOWN_MIXER_H__ +#define __SOF_IPC4_UP_DOWN_MIXER_H__ + +#include <ipc4/base-config.h> + +/** + * \brief bits field map which helps to describe each channel location a the data stream buffer + */ +typedef uint32_t channel_map; + +enum up_down_mix_coeff_select { + /**< module will use default coeffs */ + DEFAULT_COEFFICIENTS = 0, + /**< custom coeffs are required */ + CUSTOM_COEFFICIENTS, + /**< module will use default coeffs */ + DEFAULT_COEFFICIENTS_WITH_CHANNEL_MAP, + /**< custom coeffs are required */ + CUSTOM_COEFFICIENTS_WITH_CHANNEL_MAP +}; + +#define UP_DOWN_MIX_COEFFS_LENGTH 8 +#define IPC4_UP_DOWN_MIXER_MODULE_OUTPUT_PINS_COUNT 1 + +struct ipc4_up_down_mixer_module_cfg { + struct ipc4_base_module_cfg base_cfg; + + /* + * Output Channel Configuration. + * Together with audio_fmt.channel_config determines module conversion ratio. + * Please note that UpDownMixer module does not support all conversions. + */ + enum ipc4_channel_config out_channel_config; + + /**< Selects which coeffs are going to be used by UpDownMixer. */ + enum up_down_mix_coeff_select coefficients_select; + + /* + * Optional, when coefficients_select == #CUSTOM_COEFFICIENTS. For + * #CUSTOM_COEFFICIENTS expect coeffs array in quantity equal to + * #UP_DOWN_MIX_COEFFS_LENGTH. Values in this array should be + * in range <#MIN_COEFF_VALUE, #MAX_COEFF_VALUE>. + * + * Coefficients should be in order: + * 1. Left + * 2. Center + * 3. Right + * 4. Left Surround + * 5. Right Surround + * 6. Low Frequency Effects + */ + int32_t coefficients[UP_DOWN_MIX_COEFFS_LENGTH]; + + /* + * Optional, When coefficients_select is set to + * #DEFAULT_COEFFICIENTS_WITH_CHANNEL_MAP or + * #CUSTOM_COEFFICIENTS_WITH_CHANNEL_MAP, then it will be used for + * channel decoding. + */ + channel_map channel_map; +} __packed __aligned(8); + +#endif /* __SOF_IPC4_UP_DOWN_MIXER_H__ */ diff --git a/src/audio/volume/CMakeLists.txt b/src/audio/volume/CMakeLists.txt index a39492b7b26b..34491132ee2c 100644 --- a/src/audio/volume/CMakeLists.txt +++ b/src/audio/volume/CMakeLists.txt @@ -1,3 +1,22 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof volume_generic.c volume_hifi3.c volume.c) +if(CONFIG_COMP_VOLUME STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/volume_llext) + add_dependencies(app volume) +else() + add_local_sources(sof + volume_generic.c + volume_hifi3.c + volume_hifi4.c + volume_hifi5.c + volume_generic_with_peakvol.c + volume_hifi3_with_peakvol.c + volume_hifi4_with_peakvol.c + volume_hifi5_with_peakvol.c + volume.c) + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof volume_ipc3.c) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof volume_ipc4.c) + endif() +endif() diff --git a/src/audio/volume/Kconfig b/src/audio/volume/Kconfig new file mode 100644 index 000000000000..bed49b6403f9 --- /dev/null +++ b/src/audio/volume/Kconfig @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_VOLUME + tristate "Volume component" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for Volume component + +if COMP_VOLUME + +rsource "Kconfig.simd" + +config COMP_VOLUME_WINDOWS_FADE + bool "Windows Fade shape volume transitions support" + help + This option enables volume ramp shape that follows + power of 1.75. The shape is not linear, not logarithmic. + The power function uses a lookup table that consumes + 256 bytes. The topology must set volume ramp token to + SOF_VOLUME_WINDOWS_FADE for the volume instance to use + this ramp shape. + +config COMP_VOLUME_LINEAR_RAMP + bool "Linear ramp volume transitions support" + default y + help + This option enables volume linear ramp shape. + +config COMP_PEAK_VOL + bool "Report peak vol data to host" + default y + depends on IPC_MAJOR_4 + help + This option enables reporting to host peak vol regs. + See: struct ipc4_peak_volume_regs + +choice "PEAK_METER_UPDATE_PERIOD_CHOICE" + prompt "The periods(ms) of updating peak meter value" + default PEAK_METER_UPDATE_10MS + depends on COMP_PEAK_VOL + + config PEAK_METER_UPDATE_1MS + bool "1ms" + help + Update the peak meter value every 1ms + + config PEAK_METER_UPDATE_10MS + bool "10ms" + help + Update the peak meter value every 10ms + + config PEAK_METER_UPDATE_100MS + bool "100ms" + help + Update the peak meter value every 100ms + + config PEAK_METER_UPDATE_1000MS + bool "1000ms" + help + Update the peak meter value every 1000ms + endchoice + +config PEAK_METER_UPDATE_PERIOD + int + depends on COMP_PEAK_VOL + default 1 if PEAK_METER_UPDATE_1MS + default 10 if PEAK_METER_UPDATE_10MS + default 100 if PEAK_METER_UPDATE_100MS + default 1000 if PEAK_METER_UPDATE_1000MS + help + Decide which period of update the peak volume meter value + +config COMP_GAIN + bool "GAIN component" + default y + depends on IPC_MAJOR_4 + help + This option enables gain to change volume. It works + as peak volume without updating peak vol to host + +endif # volume diff --git a/src/audio/volume/Kconfig.simd b/src/audio/volume/Kconfig.simd new file mode 100644 index 000000000000..88dd09cfb57a --- /dev/null +++ b/src/audio/volume/Kconfig.simd @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: BSD-3-Clause + +comment "volume optimization level select" + +choice "VOLUME_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for volume module" + depends on COMP_VOLUME + default VOLUME_HIFI_MAX + + config VOLUME_HIFI_MAX + prompt "SIMD will selected by toolchain pre-defined header" + bool + help + When this was selected, optimization level will be determined + by toolchain pre-defined macros in core isa header file. + + config VOLUME_HIFI_5 + prompt "choose HIFI5 intrinsic optimized volume module" + bool + help + This option used to build HIFI5 optimized volume code + + config VOLUME_HIFI_4 + prompt "choose HIFI4 intrinsic optimized volume module" + bool + help + This option used to build HIFI4 optimized volume code + + config VOLUME_HIFI_3 + prompt "choose HIFI3 intrinsic optimized volume module" + bool + help + This option used to build HIFI3 intrinsic optimized volume code + + config VOLUME_HIFI_NONE + prompt "choose generic C volume module, no HIFI SIMD involved" + bool + help + This option used to build volume generic code. +endchoice diff --git a/src/audio/volume/README.md b/src/audio/volume/README.md new file mode 100644 index 000000000000..c044d73fd11d --- /dev/null +++ b/src/audio/volume/README.md @@ -0,0 +1,24 @@ +# Volume Component Architecture + +This directory contains the Volume control component. + +## Overview + +Applies amplitude modifications to the stream, supporting smooth ramping and muting interfaces configurable by the host. + +## Architecture Diagram + +```mermaid +graph LR + In[Audio Input] --> Mult[Multiplier] + IPC[IPC Control] -.-> Ramp[Ramp Generator] + Ramp --> Mult + Mult --> Out[Audio Output] +``` + +## Configuration and Scripts + +- **Kconfig**: Extensive tuning for the standard volume framework (`COMP_VOLUME`), selecting underlying algorithms (e.g., `COMP_VOLUME_WINDOWS_FADE`, `COMP_VOLUME_LINEAR_RAMP`). Manages sub-settings like querying host telemetry (`COMP_PEAK_VOL`, `PEAK_METER_UPDATE_PERIOD_CHOICE`). +- **CMakeLists.txt**: Extremely versatile linkage resolving general pathways (`volume_generic.c`), custom optimized builds across HIFI pipelines (`volume_hifi3.c`, `volume_hifi4.c`, `volume_hifi5.c`), and dual-path execution logic (`*_with_peakvol.c`). +- **volume.toml**: Registers independent modules `PEAKVOL` (`UUIDREG_STR_VOLUME4`) and `GAIN` (`UUIDREG_STR_GAIN`), outlining explicit memory mapping parameters via platform-dependent constraints. +- **Topology (.conf)**: Derived from `tools/topology/topology2/include/components/volume.conf`, configuring a standard `pga` widget (UUID `7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:86:82`). Outlines parameters for ramp steps interpolation methods and binds specific ALSA interface elements. diff --git a/src/audio/volume/llext/CMakeLists.txt b/src/audio/volume/llext/CMakeLists.txt new file mode 100644 index 000000000000..edaeec449450 --- /dev/null +++ b/src/audio/volume/llext/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("volume" + SOURCES ../volume_generic.c + ../volume_hifi3.c + ../volume_hifi4.c + ../volume_hifi5.c + ../volume_generic_with_peakvol.c + ../volume_hifi3_with_peakvol.c + ../volume_hifi4_with_peakvol.c + ../volume_hifi5_with_peakvol.c + ../volume.c + ../volume_ipc4.c + LIB openmodules +) diff --git a/src/audio/volume/llext/llext.toml.h b/src/audio/volume/llext/llext.toml.h new file mode 100644 index 000000000000..98db03706286 --- /dev/null +++ b/src/audio/volume/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../volume.toml" + +[module] +count = __COUNTER__ diff --git a/src/audio/volume/peak_volume.h b/src/audio/volume/peak_volume.h new file mode 100644 index 000000000000..057db458277a --- /dev/null +++ b/src/audio/volume/peak_volume.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/* + * \file volume/peak_volume.h + * \brief peak volume definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_PEAK_VOL_H__ +#define __SOF_IPC4_PEAK_VOL_H__ + +#include <ipc/topology.h> +#include <ipc4/base-config.h> + +enum ipc4_vol_mode { + IPC4_MODE_PEAKVOL = 1, + IPC4_MODE_GAIN = 2, +}; + +enum ipc4_peak_volume_param { + /* + * Use LARGE_CONFIG_SET to change volume / apply curve. + * Ipc mailbox must contain properly built PeakVolumeConfig. + */ + IPC4_VOLUME = 0, + IPC4_SET_ATTENUATION, + IPC4_VOLUME_TRANSITION_DELAY +}; + +enum ipc4_curve_type { + IPC4_AUDIO_CURVE_TYPE_NONE = 0, + IPC4_AUDIO_CURVE_TYPE_WINDOWS_FADE, + IPC4_AUDIO_CURVE_TYPE_LINEAR, + IPC4_AUDIO_CURVE_TYPE_LOG, + IPC4_AUDIO_CURVE_TYPE_LINEAR_ZC, + IPC4_AUDIO_CURVE_TYPE_LOG_ZC, +}; + +static const uint32_t IPC4_ALL_CHANNELS_MASK = 0xffffffff; + +struct ipc4_peak_volume_config { + /* + * ID of channel. If set to ALL_CHANNELS_MASK then + * configuration is identical and will be set for all all channels + */ + uint32_t channel_id; + /* + * Target channel volume. Takes values from 0 to 0x7fffffff. + */ + uint32_t target_volume; + /* + * Fade curve type - uses enum ipc4_curve_type + */ + uint32_t curve_type; + uint32_t reserved; + /** + * Curve duration in number of hundreds nanoseconds for format specified during + * initialization. + */ + uint64_t curve_duration; +} __packed __aligned(8); + +struct ipc4_peak_volume_module_cfg { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_peak_volume_config config[]; +} __packed __aligned(8); + +static inline enum sof_volume_ramp ipc4_curve_type_convert(enum ipc4_curve_type ipc4_type) +{ + switch (ipc4_type) { + case IPC4_AUDIO_CURVE_TYPE_WINDOWS_FADE: + return SOF_VOLUME_WINDOWS_FADE; + + case IPC4_AUDIO_CURVE_TYPE_LINEAR: + return SOF_VOLUME_LINEAR; + + case IPC4_AUDIO_CURVE_TYPE_LOG: + return SOF_VOLUME_LOG; + + case IPC4_AUDIO_CURVE_TYPE_LINEAR_ZC: + return SOF_VOLUME_LINEAR_ZC; + + case IPC4_AUDIO_CURVE_TYPE_LOG_ZC: + return SOF_VOLUME_LOG_ZC; + + case IPC4_AUDIO_CURVE_TYPE_NONE: + default: + return SOF_VOLUME_WINDOWS_NO_FADE; + } +} +#endif diff --git a/src/audio/volume/volume.c b/src/audio/volume/volume.c index affbff90fed3..a6cff8a09083 100644 --- a/src/audio/volume/volume.c +++ b/src/audio/volume/volume.c @@ -7,757 +7,765 @@ // Tomasz Lauda <tomasz.lauda@linux.intel.com> /** - * \file audio/volume.c + * \file * \brief Volume component implementation * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com>\n * Keyon Jie <yang.jie@linux.intel.com>\n * Tomasz Lauda <tomasz.lauda@linux.intel.com> */ +#include <sof/audio/coefficients/volume/windows_fade.h> +#include <sof/audio/component_ext.h> #include <sof/audio/component.h> #include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/pipeline.h> -#include <sof/audio/volume.h> +#include <sof/audio/ipc-config.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> #include <sof/lib/cpu.h> -#include <sof/lib/memory.h> #include <sof/lib/uuid.h> #include <sof/list.h> #include <sof/math/numbers.h> #include <sof/platform.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/string.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <sof/ut.h> #include <ipc/control.h> #include <ipc/stream.h> #include <ipc/topology.h> #include <user/trace.h> + #include <errno.h> +#include <stdbool.h> #include <stddef.h> #include <stdint.h> -/* Shift to use in volume fractional multiplications */ -#define Q_MUL_SHIFT Q_SHIFT_BITS_32(VOL_QXY_Y, VOL_QXY_Y, VOL_QXY_Y) - -static const struct comp_driver comp_volume; +LOG_MODULE_REGISTER(volume, CONFIG_SOF_LOG_LEVEL); -/* b77e677e-5ff4-4188-af14-fba8bdbf8682 */ -DECLARE_SOF_UUID("volume", volume_uuid, 0xb77e677e, 0x5ff4, 0x4188, - 0xaf, 0x14, 0xfb, 0xa8, 0xbd, 0xbf, 0x86, 0x82); - -/* 34dc0385-fc2f-4f7f-82d2-6cee444533e0 */ -DECLARE_SOF_UUID("volume-task", volume_task_uuid, 0x34dc0385, 0xfc2f, 0x4f7f, - 0x82, 0xd2, 0x6c, 0xee, 0x44, 0x45, 0x33, 0xe0); +#include "volume_uuid.h" +#include "volume.h" +#if CONFIG_FORMAT_S16LE /** - * \brief Synchronize host mmap() volume with real value. - * \param[in,out] cd Volume component private data. - * \param[in] num_channels Update channels 0 to num_channels -1. + * \brief Used to find nearest zero crossing frame for 16 bit format. + * \param[in,out] source Source buffer. + * \param[in] frames Number of frames. + * \param[in,out] prev_sum Previous sum of channel samples. */ -static void vol_sync_host(struct comp_dev *dev, unsigned int num_channels) +static uint32_t vol_zc_get_s16(const struct audio_stream *source, + uint32_t frames, int64_t *prev_sum) { - struct comp_data *cd = comp_get_drvdata(dev); - int n; + uint32_t curr_frames = frames; + int32_t sum; + int16_t *x = audio_stream_get_rptr(source); + int bytes; + int nmax; + int i, j, n; + 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 */ + while (remaining_samples) { + bytes = audio_stream_rewind_bytes_without_wrap(source, x); + nmax = VOL_BYTES_TO_S16_SAMPLES(bytes) + 1; + n = MIN(nmax, remaining_samples); + for (i = 0; i < n; i += nch) { + sum = 0; + for (j = 0; j < nch; j++) { + sum += *x; + x--; + } - if (!cd->hvol) { - comp_dbg(dev, "vol_sync_host() Warning: null hvol, no update"); - return; - } + /* first sign change */ + if ((sum ^ *prev_sum) < 0) + return curr_frames; - if (num_channels < SOF_IPC_MAX_CHANNELS) { - for (n = 0; n < num_channels; n++) - cd->hvol[n].value = cd->volume[n]; - } else { - comp_err(dev, "vol_sync_host() error: channels count %d exceeds SOF_IPC_MAX_CHANNELS", - num_channels); + *prev_sum = sum; + curr_frames--; + } + remaining_samples -= n; + x = audio_stream_rewind_wrap(source, x); } + + /* sign change not detected, process all samples */ + return frames; } +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE /** - * \brief Ramps volume changes over time. - * \param[in,out] data Volume base component device. - * \param[in] delay Update time. - * \return Time until next work. + * \brief Used to find nearest zero crossing frame for 24 in 32 bit format. + * \param[in,out] source Source buffer. + * \param[in] frames Number of frames. + * \param[in,out] prev_sum Previous sum of channel samples. */ -static enum task_state vol_work(void *data) +static uint32_t vol_zc_get_s24(const struct audio_stream *source, + uint32_t frames, int64_t *prev_sum) { - struct comp_dev *dev = (struct comp_dev *)data; - struct comp_data *cd = comp_get_drvdata(dev); - int32_t vol; - int again = 0; - int i; + int64_t sum; + uint32_t curr_frames = frames; + int32_t *x = audio_stream_get_rptr(source); + int bytes; + int nmax; + int i, j, n; + 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 */ + while (remaining_samples) { + bytes = audio_stream_rewind_bytes_without_wrap(source, x); + nmax = VOL_BYTES_TO_S32_SAMPLES(bytes) + 1; + n = MIN(nmax, remaining_samples); + for (i = 0; i < n; i += nch) { + sum = 0; + for (j = 0; j < nch; j++) { + sum += sign_extend_s24(*x); + x--; + } - /* No need to ramp in idle state, jump volume to request. */ - if (dev->state == COMP_STATE_READY) { - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - cd->volume[i] = cd->tvolume[i]; + /* first sign change */ + if ((sum ^ *prev_sum) < 0) + return curr_frames; - vol_sync_host(dev, PLATFORM_MAX_CHANNELS); - return SOF_TASK_STATE_COMPLETED; + *prev_sum = sum; + curr_frames--; + } + remaining_samples -= n; + x = audio_stream_rewind_wrap(source, x); } - /* The first is set and cleared to indicate ongoing ramp, the - * latter is set once to enable self launched ramp only once - * in stream start. - */ - cd->vol_ramp_active = true; - cd->ramp_started = true; + /* sign change not detected, process all samples */ + return frames; +} - /* inc/dec each volume if it's not at target for active channels */ - for (i = 0; i < cd->channels; i++) { - /* skip if target reached */ - if (cd->volume[i] == cd->tvolume[i]) - continue; +#endif /* CONFIG_FORMAT_S24LE */ - /* Update volume gain with ramp. Linear ramp increment is - * in compatible Q1.16 format with volume. - */ - vol = cd->volume[i]; - vol += cd->ramp_increment[i]; - if (cd->volume[i] < cd->tvolume[i]) { - /* ramp up, check if ramp completed */ - if (vol >= cd->tvolume[i] || vol >= cd->vol_max) { - cd->ramp_increment[i] = 0; - cd->volume[i] = cd->tvolume[i]; - } else { - cd->volume[i] = vol; - again = 1; - } - } else { - /* ramp down */ - if (vol <= 0) { - /* cannot ramp down below 0 */ - cd->ramp_increment[i] = 0; - cd->volume[i] = cd->tvolume[i]; - } else { - /* ramp completed ? */ - if (vol <= cd->tvolume[i] || - vol <= cd->vol_min) { - cd->ramp_increment[i] = 0; - cd->volume[i] = cd->tvolume[i]; - } else { - cd->volume[i] = vol; - again = 1; - } +#if CONFIG_FORMAT_S32LE +/** + * \brief Used to find nearest zero crossing frame for 32 bit format. + * \param[in,out] source Source buffer. + * \param[in] frames Number of frames. + * \param[in,out] prev_sum Previous sum of channel samples. + */ +static uint32_t vol_zc_get_s32(const struct audio_stream *source, + uint32_t frames, int64_t *prev_sum) +{ + int64_t sum; + uint32_t curr_frames = frames; + int32_t *x = audio_stream_get_rptr(source); + int bytes; + int nmax; + int i, j, n; + 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 */ + while (remaining_samples) { + bytes = audio_stream_rewind_bytes_without_wrap(source, x); + nmax = VOL_BYTES_TO_S32_SAMPLES(bytes) + 1; + n = MIN(nmax, remaining_samples); + for (i = 0; i < n; i += nch) { + sum = 0; + for (j = 0; j < nch; j++) { + sum += *x; + x--; } - } + /* first sign change */ + if ((sum ^ *prev_sum) < 0) + return curr_frames; + + *prev_sum = sum; + curr_frames--; + } + remaining_samples -= n; + x = audio_stream_rewind_wrap(source, x); } - /* sync host with new value */ - vol_sync_host(dev, cd->channels); + /* sign change not detected, process all samples */ + return frames; +} - /* do we need to continue ramping */ - if (again) - return SOF_TASK_STATE_RESCHEDULE; +#endif /* CONFIG_FORMAT_S32LE */ - cd->vol_ramp_active = 0; - return SOF_TASK_STATE_COMPLETED; -} +/** + * \brief Map of formats with dedicated zc functions. + * + * This is only used during @c .prepare() so it isn't performance-critical. + */ +__cold_rodata static const struct comp_zc_func_map zc_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_zc_get_s16 }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_zc_get_s24 }, +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_zc_get_s32 }, +#endif /* CONFIG_FORMAT_S32LE */ +}; +#if CONFIG_COMP_VOLUME_LINEAR_RAMP /** - * \brief Allocates task of volume component. - * \param[in,out] dev Volume base component device. - * \return Error code. + * \brief Calculate linear ramp function + * \param[in,out] dev Component data: ramp start gain, actual gain + * \param[in] ramp_time Time spent since ramp start as milliseconds Q29.3 + * \param[in] channel Current channel to update */ -static int vol_task_init(struct comp_dev *dev) +static inline int32_t volume_linear_ramp(struct vol_data *cd, int32_t ramp_time, int channel) { - struct comp_data *cd = comp_get_drvdata(dev); - int ret; - - /* initialize task if necessary */ - if (cd->volwork) - return 0; - - cd->volwork = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*cd->volwork)); - if (!cd->volwork) - return -ENOMEM; - - ret = schedule_task_init_ll(cd->volwork, SOF_UUID(volume_task_uuid), - SOF_SCHEDULE_LL_TIMER, - SOF_TASK_PRI_MED, vol_work, dev, - cpu_get_id(), 0); - if (ret < 0) { - rfree(cd->volwork); - return ret; - } + if (!cd->initial_ramp) + return cd->tvolume[channel]; - return 0; + return sat_int32((int64_t)ramp_time * cd->ramp_coef[channel] + cd->rvolume[channel]); } +#endif +#if CONFIG_COMP_VOLUME_WINDOWS_FADE /** - * \brief Creates volume component. - * \param[in,out] data Volume base component device. - * \param[in] delay Update time. - * \return Pointer to volume base component device. + * \brief Calculate windows fade ramp function + * \param[in,out] dev Component data: target gain, ramp start gain, ramp duration + * \param[in] ramp_time Time spent since ramp start as milliseconds Q29.3 + * \param[in] channel Current channel to update */ -static struct comp_dev *volume_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) + +static inline int32_t volume_windows_fade_ramp(struct vol_data *cd, int32_t ramp_time, int channel) { - struct comp_dev *dev; - struct sof_ipc_comp_volume *vol; - struct sof_ipc_comp_volume *ipc_vol = - (struct sof_ipc_comp_volume *)comp; - struct comp_data *cd; - int i; - int ret; + int32_t time_ratio; /* Q2.30 */ + int32_t pow_value; /* Q2.30 */ + int32_t volume_delta = cd->tvolume[channel] - cd->rvolume[channel]; /* Q16.16 */ + + if (!cd->initial_ramp) + return cd->tvolume[channel]; + + time_ratio = (((int64_t)ramp_time) << 30) / (cd->initial_ramp << 3); + if (volume_delta < 0) { + time_ratio = (1 << 30) - time_ratio; + pow_value = volume_pow_175(time_ratio); + return cd->tvolume[channel] - Q_MULTSR_32X32((int64_t)volume_delta, + pow_value, 16, 30, 16); + } - comp_cl_dbg(&comp_volume, "volume_new()"); + pow_value = volume_pow_175(time_ratio); + return cd->rvolume[channel] + Q_MULTSR_32X32((int64_t)volume_delta, pow_value, 16, 30, 16); +} +#endif - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_volume)); - if (!dev) - return NULL; - dev->drv = drv; +void volume_set_ramp_channel_counter(struct vol_data *cd, uint32_t channels_count) +{ + int i; + bool is_same_volume = true; - dev->size = COMP_SIZE(struct sof_ipc_comp_volume); + for (i = 1; i < channels_count; i++) { + if (cd->tvolume[0] != cd->tvolume[i] || cd->volume[0] != cd->volume[i]) { + is_same_volume = false; + break; + } + } - vol = COMP_GET_IPC(dev, sof_ipc_comp_volume); - ret = memcpy_s(vol, sizeof(*vol), ipc_vol, - sizeof(struct sof_ipc_comp_volume)); - assert(!ret); + if (is_same_volume) + cd->ramp_channel_counter = 1; + else + cd->ramp_channel_counter = channels_count; +} - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } +/** + * \brief Ramps volume changes over time. + * \param[in,out] vol_data Volume component data + */ - comp_set_drvdata(dev, cd); +/* Note: Using inline saves 0.4 MCPS */ +static inline void volume_ramp(struct processing_module *mod) +{ + struct vol_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int32_t new_vol; + int32_t tvolume; + int32_t volume; + int i; - /* Set the default volumes. If IPC sets min_value or max_value to - * not-zero, use them. Otherwise set to internal limits and notify - * ramp step calculation about assumed range with the range set to - * zero. + cd->ramp_finished = true; + cd->copy_gain = true; + + /* Current ramp time in Q29.3 milliseconds. Note that max. ramp length + * can be 1.3s at 192 kHz rate and 5.5s at 48 kHz rate without + * exceeding int32_t range. Inverse of sample rate is 1000/sample_rate + * for milliseconds. */ - if (vol->min_value || vol->max_value) { - if (vol->min_value < VOL_MIN) { - /* Use VOL_MIN instead, no need to stop new(). */ - cd->vol_min = VOL_MIN; - comp_err(dev, "volume_new(): vol->min_value was limited to VOL_MIN."); - } else { - cd->vol_min = vol->min_value; +#if defined CONFIG_COMP_VOLUME_WINDOWS_FADE || defined CONFIG_COMP_VOLUME_LINEAR_RAMP + int32_t ramp_time = Q_MULTSR_32X32((int64_t)cd->vol_ramp_elapsed_frames, + cd->sample_rate_inv, 0, 31, 3); +#endif + + /* Update each volume if it's not at target for active channels */ + for (i = 0; i < cd->ramp_channel_counter; i++) { + /* skip if target reached */ + volume = cd->volume[i]; + tvolume = cd->tvolume[i]; + if (volume == tvolume) + continue; + + /* Update volume gain with ramp. The ramp gain value is + * calculated from previous gain and ramp time. The slope + * coefficient is calculated in volume_set_chan(). + */ + switch (cd->ramp_type) { +#if CONFIG_COMP_VOLUME_WINDOWS_FADE + case SOF_VOLUME_WINDOWS_FADE: + new_vol = volume_windows_fade_ramp(cd, ramp_time, i); + break; +#endif +#if CONFIG_COMP_VOLUME_LINEAR_RAMP + case SOF_VOLUME_LINEAR: + case SOF_VOLUME_LINEAR_ZC: + new_vol = volume_linear_ramp(cd, ramp_time, i); + break; +#endif + default: + new_vol = tvolume; } - if (vol->max_value > VOL_MAX) { - /* Use VOL_MAX instead, no need to stop new(). */ - cd->vol_max = VOL_MAX; - comp_err(dev, "volume_new(): vol->max_value was limited to VOL_MAX."); + if (volume < tvolume) { + /* ramp up, check if ramp completed */ + if (new_vol < tvolume) + cd->ramp_finished = false; + else + new_vol = tvolume; } else { - cd->vol_max = vol->max_value; + /* ramp down */ + if (new_vol > tvolume) + cd->ramp_finished = false; + else + new_vol = tvolume; } - - cd->vol_ramp_range = vol->max_value - vol->min_value; - } else { - /* Legacy mode, set the limits to firmware capability where - * VOL_MAX is a very large gain to avoid restricting valid - * requests. The default ramp rate will be computed based - * on 0 - 1.0 gain range assumption when vol_ramp_range - * is set to 0. - */ - cd->vol_min = VOL_MIN; - cd->vol_max = VOL_MAX; - cd->vol_ramp_range = 0; + cd->volume[i] = new_vol; } + /* assign other channel volume as the first calculated volume with same volume case */ + for (i = cd->ramp_channel_counter; i < cd->channels; i++) + cd->volume[i] = cd->volume[0]; - for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) { - cd->volume[i] = MAX(MIN(cd->vol_max, VOL_ZERO_DB), - cd->vol_min); - cd->tvolume[i] = cd->volume[i]; - cd->mvolume[i] = cd->volume[i]; - cd->muted[i] = false; + cd->is_passthrough = cd->ramp_finished; + for (i = 0; i < cd->channels; i++) { + if (cd->volume[i] != VOL_ZERO_DB) { + cd->is_passthrough = false; + break; + } } - cd->vol_ramp_active = false; - cd->channels = 0; /* To be set in prepare() */ - - comp_info(dev, "vol->initial_ramp = %d, vol->ramp = %d, vol->min_value = %d, vol->max_value = %d", - vol->initial_ramp, vol->ramp, - vol->min_value, vol->max_value); - - dev->state = COMP_STATE_READY; - return dev; + if (cd->is_passthrough) + set_volume_process(cd, dev, true); } /** - * \brief Frees volume component. - * \param[in,out] dev Volume base component device. + * \brief Reset state except controls. */ -static void volume_free(struct comp_dev *dev) +void volume_reset_state(struct vol_data *cd) { - struct comp_data *cd = comp_get_drvdata(dev); - - comp_dbg(dev, "volume_free()"); + int i; - /* remove scheduling */ - if (cd->volwork) { - schedule_task_free(cd->volwork); - rfree(cd->volwork); + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) { + cd->rvolume[i] = 0; + cd->ramp_coef[i] = 0; } - rfree(cd); - rfree(dev); + cd->channels = 0; + cd->ramp_finished = true; + cd->vol_ramp_frames = 0; + cd->vol_ramp_elapsed_frames = 0; + cd->sample_rate_inv = 0; + cd->copy_gain = true; + cd->is_passthrough = false; + +#if CONFIG_COMP_PEAK_VOL + memset(cd->peak_regs.peak_meter, 0, sizeof(cd->peak_regs.peak_meter)); +#endif } -static int volume_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) +void volume_prepare_ramp(struct comp_dev *dev, struct vol_data *cd) { - int ret; + int ramp_update_us; - comp_dbg(dev, "volume_verify_params()"); - - ret = comp_verify_params(dev, 0, params); - if (ret < 0) { - comp_err(dev, "volume_verify_params() error: comp_verify_params() failed."); - return ret; - } - - return 0; + /* Determine ramp update rate depending on requested ramp length. To + * ensure evenly updated gain envelope with limited fraction resolution + * four presets are used. + */ + if (cd->initial_ramp < VOL_RAMP_UPDATE_THRESHOLD_FASTEST_MS) + ramp_update_us = VOL_RAMP_UPDATE_FASTEST_US; + else if (cd->initial_ramp < VOL_RAMP_UPDATE_THRESHOLD_FAST_MS) + ramp_update_us = VOL_RAMP_UPDATE_FAST_US; + else if (cd->initial_ramp < VOL_RAMP_UPDATE_THRESHOLD_SLOW_MS) + ramp_update_us = VOL_RAMP_UPDATE_SLOW_US; + else + ramp_update_us = VOL_RAMP_UPDATE_SLOWEST_US; + + /* The volume ramp is updated at least once per copy(). If the ramp update + * period is larger than schedule period the frames count for update is set + * to copy schedule equivalent number of frames. This also prevents a divide + * by zero to happen with a combinations of topology parameters for the volume + * component and the pipeline. + */ + if (ramp_update_us > dev->period) + cd->vol_ramp_frames = dev->frames; + else + cd->vol_ramp_frames = dev->frames / (dev->period / ramp_update_us); } -/** - * \brief Sets volume component audio stream parameters. - * \param[in,out] dev Volume base component device. - * \param[in] params Audio (PCM) stream parameters (ignored for this component) - * \return Error code. - * - * All done in prepare() since we need to know source and sink component params. - */ -static int volume_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) +static void set_linear_ramp_coef(struct vol_data *cd, int chan, bool constant_rate_ramp) { - int err; + int32_t delta; + int32_t delta_abs; + int32_t coef; - comp_dbg(dev, "volume_params()"); + if (!cd->initial_ramp) + return; - err = volume_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "vol_params(): pcm params verification failed."); - return -EINVAL; + /* Get volume transition delta and absolute value */ + delta = cd->tvolume[chan] - cd->volume[chan]; + if (!delta) { + cd->ramp_coef[chan] = 0; + return; } - return 0; + delta_abs = ABS(delta); + + /* The ramp length (initial_ramp [ms]) describes time of mute + * to vol_max unmuting. Normally the volume ramp has a + * constant linear slope defined this way and variable + * completion time. However in streaming start it is feasible + * to apply the entire topology defined ramp time to unmute to + * any used volume. In this case the ramp rate is not constant. + * Note also the legacy mode without known vol_ramp_range where + * the volume transition always uses the topology defined time. + */ + if (constant_rate_ramp && cd->vol_ramp_range > 0) + coef = cd->vol_ramp_range; + else + coef = delta_abs; + + /* Divide and round to nearest. Note that there will + * be some accumulated error in ramp time the longer + * the ramp and the smaller the transition is. + */ + coef = ((int64_t)coef * 2 / cd->initial_ramp + 1) >> 1; + + /* Scale coefficient by 1/8, round */ + coef = ((coef >> 2) + 1) >> 1; + + /* Ensure ramp coefficient is at least min. non-zero + * fractional value. + */ + coef = MAX(coef, 1); + + /* Invert sign for volume down ramp step */ + if (delta < 0) + coef = -coef; + + cd->ramp_coef[chan] = coef; } /** * \brief Sets channel target volume. - * \param[in,out] dev Volume base component device. + * \param[in,out] mod Volume processing module handle * \param[in] chan Channel number. * \param[in] vol Target volume. * \param[in] constant_rate_ramp When true do a constant rate * and variable time length ramp. When false do * a fixed length and variable rate ramp. */ -static inline int volume_set_chan(struct comp_dev *dev, int chan, - int32_t vol, bool constant_rate_ramp) +int volume_set_chan(struct processing_module *mod, int chan, + int32_t vol, bool constant_rate_ramp) { - struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_volume *pga = - COMP_GET_IPC(dev, sof_ipc_comp_volume); + struct vol_data *cd = module_get_private_data(mod); int32_t v = vol; - int32_t delta; - int32_t delta_abs; - int32_t inc; /* Limit received volume gain to MIN..MAX range before applying it. - * MAX is needed for now for the generic C gain arithmetics to prevent + * MAX is needed for now for the generic C gain arithmetic to prevent * multiplication overflow with the 32 bit value. Non-zero MIN option * can be useful to prevent totally muted small volume gain. */ - if (v < VOL_MIN) { + if (v < cd->vol_min) { /* No need to fail, just trace the event. */ - comp_warn(dev, "volume_set_chan: Limited request %d to min. %d", - v, VOL_MIN); - v = VOL_MIN; + comp_warn(mod->dev, "Limited request %d to min. %d", + v, cd->vol_min); + v = cd->vol_min; } - if (v > VOL_MAX) { + if (v > cd->vol_max) { /* No need to fail, just trace the event. */ - comp_warn(dev, "volume_set_chan: Limited request %d to max. %d", - v, VOL_MAX); - v = VOL_MAX; + comp_warn(mod->dev, "Limited request %d to max. %d", + v, cd->vol_max); + v = cd->vol_max; } cd->tvolume[chan] = v; + cd->rvolume[chan] = cd->volume[chan]; + cd->vol_ramp_elapsed_frames = 0; - /* Check ramp type */ - switch (pga->ramp) { - case SOF_VOLUME_LINEAR: - /* Get volume transition delta and absolute value */ - delta = cd->tvolume[chan] - cd->volume[chan]; - delta_abs = ABS(delta); - - /* The ramp length (initial_ramp [ms]) describes time of mute - * to vol_max unmuting. Normally the volume ramp has a - * constant linear slope defined this way and variable - * completion time. However in streaming start it is feasible - * to apply the entire topology defined ramp time to unmute to - * any used volume. In this case the ramp rate is not constant. - * Note also the legacy mode without known vol_ramp_range where - * the volume transition always uses the topology defined time. - */ - if (pga->initial_ramp > 0) { - if (constant_rate_ramp && cd->vol_ramp_range > 0) - inc = q_multsr_32x32(cd->vol_ramp_range, - VOL_RAMP_STEP_CONST, - Q_MUL_SHIFT); - else - inc = q_multsr_32x32(delta_abs, - VOL_RAMP_STEP_CONST, - Q_MUL_SHIFT); + /* Ramp type specific initialize */ + if (cd->ramp_type == SOF_VOLUME_LINEAR || cd->ramp_type == SOF_VOLUME_LINEAR_ZC) + set_linear_ramp_coef(cd, chan, constant_rate_ramp); - /* Divide and round to nearest. Note that there will - * be some accumulated error in ramp time the longer - * the ramp and the smaller the transition is. - */ - inc = (2 * inc / pga->initial_ramp + 1) >> 1; - } else { - inc = delta_abs; - } - - /* Ensure inc is at least one */ - inc = MAX(inc, 1); - - /* Invert sign for volume down ramp step */ - if (delta < 0) - inc = -inc; - - cd->ramp_increment[chan] = inc; - comp_dbg(dev, "cd->ramp_increment[%d] = %d", chan, - cd->ramp_increment[chan]); - break; - case SOF_VOLUME_LOG: - case SOF_VOLUME_LINEAR_ZC: - case SOF_VOLUME_LOG_ZC: - default: - comp_err(dev, "volume_set_chan() error: invalid ramp type %d", - pga->ramp); - return -EINVAL; - } + if (!cd->initial_ramp || cd->ramp_type == SOF_VOLUME_WINDOWS_NO_FADE) + cd->volume[chan] = v; return 0; } /** * \brief Mutes channel. - * \param[in,out] dev Volume base component device. + * \param[in,out] mod Volume processing module handle * \param[in] chan Channel number. */ -static inline void volume_set_chan_mute(struct comp_dev *dev, int chan) +void volume_set_chan_mute(struct processing_module *mod, int chan) { - struct comp_data *cd = comp_get_drvdata(dev); + struct vol_data *cd = module_get_private_data(mod); if (!cd->muted[chan]) { cd->mvolume[chan] = cd->tvolume[chan]; - volume_set_chan(dev, chan, 0, true); + volume_set_chan(mod, chan, 0, true); cd->muted[chan] = true; } } /** * \brief Unmutes channel. - * \param[in,out] dev Volume base component device. + * \param[in,out] mod Volume processing module handle * \param[in] chan Channel number. */ -static inline void volume_set_chan_unmute(struct comp_dev *dev, int chan) +void volume_set_chan_unmute(struct processing_module *mod, int chan) { - struct comp_data *cd = comp_get_drvdata(dev); + struct vol_data *cd = module_get_private_data(mod); if (cd->muted[chan]) { cd->muted[chan] = false; - volume_set_chan(dev, chan, cd->mvolume[chan], true); + volume_set_chan(mod, chan, cd->mvolume[chan], true); } } -/** - * \brief Sets volume control command. - * \param[in,out] dev Volume base component device. - * \param[in,out] cdata Control command data. +/* + * \brief Copies and processes stream data. + * \param[in,out] mod Volume processing module handle * \return Error code. */ -static int volume_ctrl_set_cmd(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata) +static int volume_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 comp_data *cd = comp_get_drvdata(dev); - uint32_t val; - int ch; - int j; - int ret = 0; - - /* validate */ - if (cdata->num_elems == 0 || cdata->num_elems > SOF_IPC_MAX_CHANNELS) { - comp_err(dev, "volume_ctrl_set_cmd() error: invalid cdata->num_elems"); - return -EINVAL; - } - - switch (cdata->cmd) { - case SOF_CTRL_CMD_VOLUME: - comp_dbg(dev, "volume_ctrl_set_cmd(), SOF_CTRL_CMD_VOLUME, cdata->comp_id = %u", - cdata->comp_id); - for (j = 0; j < cdata->num_elems; j++) { - ch = cdata->chanv[j].channel; - val = cdata->chanv[j].value; - comp_info(dev, "volume_ctrl_set_cmd(), channel = %d, value = %u", - ch, val); - if (ch < 0 || ch >= SOF_IPC_MAX_CHANNELS) { - comp_err(dev, "volume_ctrl_set_cmd(), illegal channel = %d", - ch); - return -EINVAL; - } - - if (cd->muted[ch]) { - cd->mvolume[ch] = val; - } else { - ret = volume_set_chan(dev, ch, val, true); - if (ret) - return ret; - } - } - - if (!cd->vol_ramp_active) { - ret = vol_task_init(dev); - if (ret < 0) - return ret; - - schedule_task(cd->volwork, VOL_RAMP_UPDATE_US, - VOL_RAMP_UPDATE_US); - } - break; - - case SOF_CTRL_CMD_SWITCH: - comp_dbg(dev, "volume_ctrl_set_cmd(), SOF_CTRL_CMD_SWITCH, cdata->comp_id = %u", - cdata->comp_id); - for (j = 0; j < cdata->num_elems; j++) { - ch = cdata->chanv[j].channel; - val = cdata->chanv[j].value; - comp_info(dev, "volume_ctrl_set_cmd(), channel = %d, value = %u", - ch, val); - if (ch < 0 || ch >= SOF_IPC_MAX_CHANNELS) { - comp_err(dev, "volume_ctrl_set_cmd(), illegal channel = %d", - ch); - return -EINVAL; - } - - if (val) - volume_set_chan_unmute(dev, ch); - else - volume_set_chan_mute(dev, ch); + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = input_buffers[0].data; + uint32_t avail_frames = input_buffers[0].size; + uint32_t frames; + int64_t prev_sum = 0; + + comp_dbg(mod->dev, "entry"); + + while (avail_frames) { +#if CONFIG_COMP_PEAK_VOL + volume_update_current_vol_ipc4(cd); +#endif + if (cd->ramp_finished || cd->vol_ramp_frames > avail_frames) { + /* without ramping process all at once */ + frames = avail_frames; + } else if (cd->ramp_type == SOF_VOLUME_LINEAR_ZC) { + /* with ZC ramping look for next ZC offset */ + frames = cd->zc_get(source, cd->vol_ramp_frames, &prev_sum); + /* Align frames count to audio stream constraints. If it rounds to zero + * round it up to smallest nonzero aligned frames count. + */ + frames = audio_stream_align_frames_round_nearest(source, frames); + if (!frames) + frames = audio_stream_align_frames_round_up(source, 1); + } else { + /* During volume ramp align the number of frames used in this + * gain step. Align up since with low rates this would typically + * become zero. + */ + frames = audio_stream_align_frames_round_up(source, cd->vol_ramp_frames); } - if (!cd->vol_ramp_active) { - ret = vol_task_init(dev); - if (ret < 0) - return ret; + /* Cancel the gain step for ZC or smaller ramp step if it exceeds + * the available frames. + */ + if (frames > avail_frames) + frames = avail_frames; - schedule_task(cd->volwork, VOL_RAMP_UPDATE_US, - VOL_RAMP_UPDATE_US); + if (!cd->ramp_finished) { + volume_ramp(mod); + cd->vol_ramp_elapsed_frames += frames; } - break; - default: - comp_err(dev, "volume_ctrl_set_cmd() error: invalid cdata->cmd"); - return -EINVAL; - } + /* copy and scale volume */ + cd->scale_vol(mod, &input_buffers[0], &output_buffers[0], frames, cd->attenuation); - return 0; -} - -/** - * \brief Gets volume control command. - * \param[in,out] dev Volume base component device. - * \param[in,out] cdata Control command data. - * \return Error code. - */ -static int volume_ctrl_get_cmd(struct comp_dev *dev, - struct sof_ipc_ctrl_data *cdata, int size) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int j; - - /* validate */ - if (cdata->num_elems == 0 || cdata->num_elems > SOF_IPC_MAX_CHANNELS) { - comp_err(dev, "volume_ctrl_get_cmd() error: invalid cdata->num_elems %u", - cdata->num_elems); - return -EINVAL; + avail_frames -= frames; } - - if (cdata->cmd == SOF_CTRL_CMD_VOLUME || - cdata->cmd == SOF_CTRL_CMD_SWITCH) { - comp_dbg(dev, "volume_ctrl_get_cmd(), SOF_CTRL_CMD_VOLUME / SOF_CTRL_CMD_SWITCH, cdata->comp_id = %u", - cdata->comp_id); - for (j = 0; j < cdata->num_elems; j++) { - cdata->chanv[j].channel = j; - cdata->chanv[j].value = cd->tvolume[j]; - comp_info(dev, "volume_ctrl_get_cmd(), channel = %u, value = %u", - cdata->chanv[j].channel, - cdata->chanv[j].value); - } - } else { - comp_err(dev, "volume_ctrl_get_cmd() error: invalid cdata->cmd"); - return -EINVAL; +#if CONFIG_COMP_PEAK_VOL + cd->peak_cnt++; + if (cd->peak_cnt == cd->peak_report_cnt) { + cd->peak_cnt = 0; + peak_vol_update(cd); + memset(cd->peak_regs.peak_meter, 0, sizeof(cd->peak_regs.peak_meter)); +#if SOF_USE_HIFI(4, VOLUME) || SOF_USE_HIFI(5, VOLUME) + memset(cd->peak_vol, 0, sizeof(int32_t) * SOF_IPC_MAX_CHANNELS * 4); +#endif } +#endif return 0; } -/** - * \brief Used to pass standard and bespoke commands (with data) to component. +/* + * \brief Retrieves volume zero crossing function. * \param[in,out] dev Volume base component device. - * \param[in] cmd Command type. - * \param[in,out] data Control command data. - * \return Error code. */ -static int volume_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) +static vol_zc_func vol_get_zc_function(struct comp_dev *dev, + struct comp_buffer *sinkb) { - struct sof_ipc_ctrl_data *cdata = data; - - comp_dbg(dev, "volume_cmd()"); + int i; - switch (cmd) { - case COMP_CMD_SET_VALUE: - return volume_ctrl_set_cmd(dev, cdata); - case COMP_CMD_GET_VALUE: - return volume_ctrl_get_cmd(dev, cdata, max_data_size); - default: - return -EINVAL; + /* map the zc function to frame format */ + for (i = 0; i < ARRAY_SIZE(zc_func_map); i++) { + if (audio_stream_get_valid_fmt(&sinkb->stream) == zc_func_map[i].frame_fmt) + return zc_func_map[i].func; } -} - -/** - * \brief Sets volume component state. - * \param[in,out] dev Volume base component device. - * \param[in] cmd Command type. - * \return Error code. - */ -static int volume_trigger(struct comp_dev *dev, int cmd) -{ - comp_dbg(dev, "volume_trigger()"); - return comp_set_state(dev, cmd); + return NULL; } /** - * \brief Copies and processes stream data. - * \param[in,out] dev Volume base component device. - * \return Error code. + * \brief Set volume frames alignment limit. + * \param[in,out] source Structure pointer of source. */ -static int volume_copy(struct comp_dev *dev) +static void volume_set_alignment(struct audio_stream *source) { - struct comp_copy_limits c; - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source; - struct comp_buffer *sink; - uint32_t flags = 0; - - comp_dbg(dev, "volume_copy()"); - - if (!cd->ramp_started) - schedule_task(cd->volwork, VOL_RAMP_UPDATE_US, - VOL_RAMP_UPDATE_US); - - source = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - buffer_lock(source, &flags); - buffer_lock(sink, &flags); - - /* Get source, sink, number of frames etc. to process. */ - comp_get_copy_limits(source, sink, &c); - - buffer_unlock(sink, flags); - buffer_unlock(source, flags); - - comp_dbg(dev, "volume_copy(), source_bytes = 0x%x, sink_bytes = 0x%x", - c.source_bytes, c.sink_bytes); - - /* copy and scale volume */ - buffer_invalidate(source, c.source_bytes); - cd->scale_vol(dev, &sink->stream, &source->stream, c.frames); - buffer_writeback(sink, c.sink_bytes); + const int channels = audio_stream_get_channels(source); + + /* The source buffer in HiFi5 processing version needs 16 bytes alignment. The + * macro SOF_FRAME_BYTE_ALIGN is set in common.h to the requirement align. + * The VOLUME_HIFI3_HIFI4_FRAME_BYTE_ALIGN_6CH also has the value 16 and the + * same align for 5.1 channels works for HiFi5 too. + * + * In HiFi4 processing version the source align requirement is 8 bytes. While + * the 5.1 format SSE audio requires 16 bytes alignment. + */ + const uint32_t byte_align = + (channels == 6) ? VOLUME_HIFI3_HIFI4_FRAME_BYTE_ALIGN_6CH : SOF_FRAME_BYTE_ALIGN; + + /* On HiFi5 the number of samples to process must be multiple of four for s24/s32 + * and multiple of eight for s16. For HiFi4 and HiFi3 the number of samples + * need to be multiple of two for s32 and multiple of four for s16. + * E.g. for s32 format for channels counts of 1, 2, 4, 6, ... the + * frame align need to be 4, 2, 1, 2, ... + */ +#if SOF_USE_HIFI(5, VOLUME) + const int n = (audio_stream_get_valid_fmt(source) == SOF_IPC_FRAME_S16_LE) ? 8 : 4; +#else + const int n = (audio_stream_get_valid_fmt(source) == SOF_IPC_FRAME_S16_LE) ? 4 : 2; +#endif - /* calculate new free and available */ - comp_update_buffer_produce(sink, c.sink_bytes); - comp_update_buffer_consume(source, c.source_bytes); + const uint32_t frame_align_req = (uint32_t)(n / gcd(n, channels)); - return 0; + audio_stream_set_align(byte_align, frame_align_req, source); } /** * \brief Prepares volume component for processing. - * \param[in,out] dev Volume base component device. + * \param[in,out] mod Volume processing module handle + * \return Error code. * * Volume component is usually first and last in pipelines so it makes sense * to also do some type of conversion here. */ -static int volume_prepare(struct comp_dev *dev) +static int volume_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sinkb; - struct sof_ipc_comp_config *config = dev_comp_config(dev); + struct vol_data *cd = module_get_private_data(mod); + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct comp_buffer *sourceb, *sinkb; uint32_t sink_period_bytes; - int i; int ret; + int i; - comp_dbg(dev, "volume_prepare()"); + comp_dbg(dev, "entry"); - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; + /* volume component will only ever have 1 sink and source buffer */ + sinkb = comp_dev_get_first_data_consumer(dev); + sourceb = comp_dev_get_first_data_producer(dev); + if (!sourceb || !sinkb) { + comp_err(dev, "no source or sink buffer"); + return -ENOTCONN; + } - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + ret = volume_peak_prepare(cd, mod); - /* volume component will only ever have 1 sink buffer */ - sinkb = list_first_item(&dev->bsink_list, - struct comp_buffer, source_list); + volume_set_alignment(&sourceb->stream); /* get sink period bytes */ sink_period_bytes = audio_stream_period_bytes(&sinkb->stream, dev->frames); - if (sinkb->stream.size < config->periods_sink * sink_period_bytes) { - comp_err(dev, "volume_prepare() error: sink buffer size is insufficient"); + if (audio_stream_get_size(&sinkb->stream) < sink_period_bytes) { + comp_err(dev, "sink buffer size %d is insufficient < %d", + audio_stream_get_size(&sinkb->stream), sink_period_bytes); ret = -ENOMEM; goto err; } - cd->scale_vol = vol_get_processing_function(dev); + set_volume_process(cd, dev, false); + if (!cd->scale_vol) { - comp_err(dev, "volume_prepare() error: invalid cd->scale_vol"); + comp_err(dev, "invalid cd->scale_vol"); ret = -EINVAL; goto err; } - vol_sync_host(dev, PLATFORM_MAX_CHANNELS); + cd->zc_get = vol_get_zc_function(dev, sinkb); + if (!cd->zc_get) { + comp_err(dev, "invalid cd->zc_get"); + ret = -EINVAL; + goto err; + } /* Set current volume to min to ensure ramp starts from minimum - * to previous volume request. Copy() checks for ramp started - * and schedules it if it has not yet started as result of + * to previous volume request. Copy() checks for ramp finished + * and executes it if it has not yet finished as result of * driver commands. Ramp is not constant rate to ensure it lasts * for entire topology specified time. */ - cd->ramp_started = false; - cd->channels = sinkb->stream.channels; + cd->ramp_finished = false; + + cd->channels = audio_stream_get_channels(&sinkb->stream); + if (cd->channels > SOF_IPC_MAX_CHANNELS) { + ret = -EINVAL; + goto err; + } + + cd->sample_rate_inv = (int32_t)(1000LL * INT32_MAX / + audio_stream_get_rate(&sinkb->stream)); + for (i = 0; i < cd->channels; i++) { cd->volume[i] = cd->vol_min; - volume_set_chan(dev, i, cd->tvolume[i], false); + volume_set_chan(mod, i, cd->tvolume[i], false); + if (cd->volume[i] != cd->tvolume[i]) + cd->ramp_finished = false; } - ret = vol_task_init(dev); - if (ret < 0) - return ret; + volume_prepare_ramp(dev, cd); + + /* + * volume component does not do any format conversion, so use the buffer size for source + * and sink + */ + md->mpd.in_buff_size = sink_period_bytes; + md->mpd.out_buff_size = sink_period_bytes; return 0; @@ -768,44 +776,83 @@ static int volume_prepare(struct comp_dev *dev) /** * \brief Resets volume component. - * \param[in,out] dev Volume base component device. + * \param[in,out] mod Volume processing module handle * \return Error code. */ -static int volume_reset(struct comp_dev *dev) +static int volume_reset(struct processing_module *mod) { - comp_dbg(dev, "volume_reset()"); + struct vol_data *cd = module_get_private_data(mod); - comp_set_state(dev, COMP_TRIGGER_RESET); + comp_dbg(mod->dev, "entry"); + volume_reset_state(cd); return 0; } -/** \brief Volume component definition. */ -static const struct comp_driver comp_volume = { - .type = SOF_COMP_VOLUME, - .uid = SOF_UUID(volume_uuid), - .ops = { - .new = volume_new, - .free = volume_free, - .params = volume_params, - .cmd = volume_cmd, - .trigger = volume_trigger, - .copy = volume_copy, - .prepare = volume_prepare, - .reset = volume_reset, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_volume_info = { - .drv = &comp_volume, -}; - /** - * \brief Initializes volume component. + * \brief Frees volume component. + * \param[in,out] mod Volume processing module handle */ -UT_STATIC void sys_comp_volume_init(void) +static int volume_free(struct processing_module *mod) { - comp_register(platform_shared_get(&comp_volume_info, - sizeof(comp_volume_info))); + struct vol_data *cd = module_get_private_data(mod); + + comp_dbg(mod->dev, "entry"); + + volume_peak_free(mod); + mod_free(mod, cd->vol); + mod_free(mod, cd); + + return 0; } -DECLARE_MODULE(sys_comp_volume_init); +static const struct module_interface volume_interface = { + .init = volume_init, + .prepare = volume_prepare, + .process_audio_stream = volume_process, + .set_configuration = volume_set_config, + .get_configuration = volume_get_config, + .reset = volume_reset, + .free = volume_free +}; + +#if CONFIG_COMP_GAIN +static const struct module_interface gain_interface = { + .init = volume_init, + .prepare = volume_prepare, + .process_audio_stream = volume_process, + .set_configuration = volume_set_config, + .get_configuration = volume_get_config, + .reset = volume_reset, + .free = volume_free +}; +#endif + +#if CONFIG_COMP_VOLUME_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { +#if CONFIG_COMP_PEAK_VOL + SOF_LLEXT_MODULE_MANIFEST("PEAKVOL", &volume_interface, 1, SOF_REG_UUID(volume4), 10), +#endif +#if CONFIG_COMP_GAIN + SOF_LLEXT_MODULE_MANIFEST("GAIN", &gain_interface, 1, SOF_REG_UUID(gain), 40), +#endif +}; + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_MODULE_ADAPTER(volume_interface, volume_uuid, volume_tr); +SOF_MODULE_INIT(volume, sys_comp_module_volume_interface_init); + +#if CONFIG_COMP_GAIN +DECLARE_MODULE_ADAPTER(gain_interface, gain_uuid, gain_tr); +SOF_MODULE_INIT(gain, sys_comp_module_gain_interface_init); +#endif + +#endif diff --git a/src/audio/volume/volume.h b/src/audio/volume/volume.h new file mode 100644 index 000000000000..9d1d08a280fe --- /dev/null +++ b/src/audio/volume/volume.h @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +/** + * \file volume/volume.h + * \brief Volume component header file + * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com>\n + * Keyon Jie <yang.jie@linux.intel.com>\n + * Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_VOLUME_H__ +#define __SOF_AUDIO_VOLUME_H__ + +#include <sof/audio/component.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <sof/trace/trace.h> +#include <ipc/stream.h> +#include <user/trace.h> +#include <stddef.h> +#include <stdint.h> +#if CONFIG_IPC_MAJOR_4 +#include "peak_volume.h" +#include <ipc4/fw_reg.h> +#endif + +struct comp_buffer; +struct sof_ipc_ctrl_value_chan; + +/** + * \brief In IPC3 volume is in Q8.16 format, in IPC4 in Q1.31, but is converted + * by firmware to Q1.23 format. + */ +#if CONFIG_IPC_MAJOR_3 + +//** \brief Volume gain Qx.y */ +#define COMP_VOLUME_Q8_16 1 + +#else + +//** \brief Volume gain Qx.y */ +#define COMP_VOLUME_Q1_31 1 + +#endif + +#if COMP_VOLUME_Q1_31 +/** \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 1 + +//** \brief Volume gain Qx.y fractional y number of bits. */ +#define VOL_QXY_Y 31 + +#define VOLUME_Q17_47_SHIFT 0 +#elif COMP_VOLUME_Q1_23 +/** \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 + +#define VOLUME_Q17_47_SHIFT 8 + +#elif COMP_VOLUME_Q8_16 +//** \brief Volume gain Qx.y integer x number of bits including sign bit. */ +#define VOL_QXY_X 8 + +//** \brief Volume gain Qx.y fractional y number of bits. */ +#define VOL_QXY_Y 16 + +#define VOLUME_Q17_47_SHIFT 15 + +#else +#error "Need CONFIG_COMP_VOLUME_Qx_y" +#endif + +/** + * \brief Volume ramp update rate in microseconds. + * Update volume gain value every 125 to 1000 us. The faster gain ramps need + * higher update rate to avoid annoying zipper noise sound. The below + * values were tested subjectively for constraint of 125 microseconds + * multiple gain update rate. + */ +#define VOL_RAMP_UPDATE_SLOWEST_US 1000 +#define VOL_RAMP_UPDATE_SLOW_US 500 +#define VOL_RAMP_UPDATE_FAST_US 250 +#define VOL_RAMP_UPDATE_FASTEST_US 125 + +#define VOL_RAMP_UPDATE_THRESHOLD_SLOW_MS 128 +#define VOL_RAMP_UPDATE_THRESHOLD_FAST_MS 64 +#define VOL_RAMP_UPDATE_THRESHOLD_FASTEST_MS 32 + +/** + * \brief left shift 8 bits to put the valid 24 bits into + * higher part of 32 bits container. + */ +#define PEAK_24S_32C_ADJUST 8 + +/** + * \brief left shift 16 bits to put the valid 16 bits into + * higher part of 32 bits container. + */ +#define PEAK_16S_32C_ADJUST 16 + +#if COMP_VOLUME_Q1_31 +/** \brief Volume maximum value. */ +#define VOL_MAX INT32_MAX + +/** \brief Volume 0dB value. */ +#define VOL_ZERO_DB INT32_MAX + +#else +/** \brief Volume maximum value. */ +#define VOL_MAX ((1 << (VOL_QXY_X + VOL_QXY_Y - 1)) - 1) + +/** \brief Volume 0dB value. */ +#define VOL_ZERO_DB BIT(VOL_QXY_Y) + +#endif + +/** \brief Volume minimum value. */ +#define VOL_MIN 0 + +/** \brief Macros to convert without division bytes count to samples count */ +#define VOL_BYTES_TO_S16_SAMPLES(b) ((b) >> 1) +#define VOL_BYTES_TO_S32_SAMPLES(b) ((b) >> 2) + +#define VOL_S16_SAMPLES_TO_BYTES(s) ((s) << 1) +#define VOL_S32_SAMPLES_TO_BYTES(s) ((s) << 2) + +/** + * \brief Bytes align requirement for 6ch PCM frame on HiFi3 and Hifi4 + * platforms for volume component. + */ +#define VOLUME_HIFI3_HIFI4_FRAME_BYTE_ALIGN_6CH 16 + +/** + * \brief volume processing function interface + */ +typedef void (*vol_scale_func)(struct processing_module *mod, struct input_stream_buffer *source, + struct output_stream_buffer *sink, uint32_t frames, uint32_t attenuation); + +/** + * \brief volume interface for function getting nearest zero crossing frame + */ +typedef uint32_t (*vol_zc_func)(const struct audio_stream *source, + uint32_t frames, int64_t *prev_sum); + +/** + * \brief Function for volume ramp shape function + */ + +struct vol_data { +#if CONFIG_IPC_MAJOR_4 + uint32_t mailbox_offset; /**< store peak volume in mailbox */ + + /**< these values will be stored to mailbox for host (IPC4) */ + struct ipc4_peak_volume_regs peak_regs; + /**< store temp peak volume 4 times for scale_vol function */ + int32_t *peak_vol; + uint32_t peak_cnt; /**< accumulated period of volume processing*/ + uint32_t peak_report_cnt; /**< the period number to update peak meter*/ +#endif + int32_t volume[SOF_IPC_MAX_CHANNELS]; /**< current volume */ + int32_t tvolume[SOF_IPC_MAX_CHANNELS]; /**< target volume */ + int32_t mvolume[SOF_IPC_MAX_CHANNELS]; /**< mute volume */ + int32_t rvolume[SOF_IPC_MAX_CHANNELS]; /**< ramp start volume */ + int32_t ramp_coef[SOF_IPC_MAX_CHANNELS]; /**< parameter for slope */ + /**< store current volume 4 times for scale_vol function */ + int32_t *vol; + uint32_t initial_ramp; /**< ramp space in ms */ + uint32_t ramp_type; /**< SOF_VOLUME_ */ + int32_t vol_min; /**< minimum volume */ + int32_t vol_max; /**< maximum volume */ + int32_t vol_ramp_range; /**< max ramp transition */ + /**< max number of frames to process per ramp transition */ + uint32_t vol_ramp_frames; + uint32_t vol_ramp_elapsed_frames; /**< frames since transition */ + int32_t sample_rate_inv; /**< 1000x inverse of sample rate as Q1.31 */ + unsigned int channels; /**< current channels count */ + bool muted[SOF_IPC_MAX_CHANNELS]; /**< set if channel is muted */ + bool ramp_finished; /**< control ramp launch */ + vol_scale_func scale_vol; /**< volume processing function */ + vol_zc_func zc_get; /**< function getting nearest zero crossing frame */ + bool copy_gain; /**< control copy gain or not */ + uint32_t attenuation; /**< peakmeter adjustment in range [0 - 31] */ + bool is_passthrough; /**< is passthrough or do gain multiplication */ + uint32_t ramp_channel_counter; /**< channels need new ramp volume */ +}; + +/** \brief Volume processing functions map. */ +struct comp_func_map { + uint16_t frame_fmt; /**< frame format */ + vol_scale_func func; /**< volume processing function */ + vol_scale_func passthrough_func; /**< volume passthrough function */ +}; + +/** \brief Map of formats with dedicated processing functions. */ +extern const struct comp_func_map volume_func_map[]; + +/** \brief Number of processing functions. */ +extern const size_t volume_func_count; + +/** \brief Volume zero crossing functions map. */ +struct comp_zc_func_map { + uint16_t frame_fmt; /**< frame format */ + vol_zc_func func; /**< volume zc function */ +}; + +#if CONFIG_IPC_MAJOR_3 +/** + * \brief Retrievies volume processing function. + * \param[in,out] dev Volume base component device. + * \param[in] sinkb Sink buffer to match against + * \param[in] cd Volume data structure. + */ +static inline vol_scale_func vol_get_processing_function(struct comp_dev *dev, + struct comp_buffer *sinkb, + struct vol_data *cd) +{ + int i; + + /* map the volume function for source and sink buffers */ + for (i = 0; i < volume_func_count; i++) { + if (audio_stream_get_frm_fmt(&sinkb->stream) != volume_func_map[i].frame_fmt) + continue; + + if (cd->is_passthrough) + return volume_func_map[i].passthrough_func; + else + return volume_func_map[i].func; + } + + return NULL; +} + +#else +/** + * \brief Retrievies volume processing function. + * \param[in,out] dev Volume base component device. + * \param[in] cd Volume data structure + */ +static inline vol_scale_func vol_get_processing_function(struct comp_dev *dev, + struct vol_data *cd) +{ + struct processing_module *mod = comp_mod(dev); + + if (cd->is_passthrough) { + switch (mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth) { + case IPC4_DEPTH_16BIT: + return volume_func_map[0].passthrough_func; + case IPC4_DEPTH_24BIT: + return volume_func_map[1].passthrough_func; + case IPC4_DEPTH_32BIT: + return volume_func_map[2].passthrough_func; + default: + comp_err(dev, "unsupported depth %d", + mod->priv.cfg.base_cfg.audio_fmt.depth); + return NULL; + } + } else { + switch (mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth) { + case IPC4_DEPTH_16BIT: + return volume_func_map[0].func; + case IPC4_DEPTH_24BIT: + return volume_func_map[1].func; + case IPC4_DEPTH_32BIT: + return volume_func_map[2].func; + default: + comp_err(dev, "unsupported depth %d", + mod->priv.cfg.base_cfg.audio_fmt.depth); + return NULL; + } + } +} +#endif + +static inline void peak_vol_update(struct vol_data *cd) +{ +#if CONFIG_COMP_PEAK_VOL + /* update peakvol in mailbox */ + mailbox_sw_regs_write(cd->mailbox_offset, &cd->peak_regs, sizeof(cd->peak_regs)); +#endif +} + +#ifdef UNIT_TEST +void sys_comp_module_volume_interface_init(void); +#endif + +/* source_or_sink, true means source, false means sink */ +void set_volume_process(struct vol_data *cd, struct comp_dev *dev, bool source_or_sink); + +void volume_peak_free(struct processing_module *mod); + +int volume_peak_prepare(struct vol_data *cd, struct processing_module *mod); + +int volume_init(struct processing_module *mod); + +int volume_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); + +int volume_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); + +void volume_update_current_vol_ipc4(struct vol_data *cd); + +void volume_reset_state(struct vol_data *cd); + +void volume_prepare_ramp(struct comp_dev *dev, struct vol_data *cd); + +int volume_set_chan(struct processing_module *mod, int chan, + int32_t vol, bool constant_rate_ramp); + +void volume_set_chan_mute(struct processing_module *mod, int chan); + +void volume_set_chan_unmute(struct processing_module *mod, int chan); + +void volume_set_ramp_channel_counter(struct vol_data *cd, uint32_t channels_count); + +#endif /* __SOF_AUDIO_VOLUME_H__ */ diff --git a/src/audio/volume/volume.toml b/src/audio/volume/volume.toml new file mode 100644 index 000000000000..0c30281def81 --- /dev/null +++ b/src/audio/volume/volume.toml @@ -0,0 +1,82 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + +#if CONFIG_COMP_PEAK_VOL + [[module.entry]] + name = "PEAKVOL" + uuid = UUIDREG_STR_VOLUME4 + affinity_mask = "0x1" + instance_count = "10" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "4" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 480, 11667000, 384, 384, 0, 11667, 0, + 1, 0, 0, 0, 480, 5943000, 192, 192, 0, 5943, 0, + 2, 0, 0, 0, 480, 12567000, 720, 720, 0, 12567, 0, + 3, 0, 0, 0, 480, 7360000, 768, 768, 0, 7360, 0, + 4, 0, 0, 0, 480, 12236000, 1536, 1536, 0, 12236, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 480, 5546000, 384, 384, 0, 5546, 0, + 1, 0, 0, 0, 480, 4966000, 192, 192, 0, 4966, 0, + 2, 0, 0, 0, 480, 6846000, 720, 720, 0, 6846, 0, + 3, 0, 0, 0, 480, 7212000, 768, 768, 0, 7212, 0, + 4, 0, 0, 0, 480, 9532000, 1536, 1536, 0, 9532, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 480, 6993000, 384, 384, 0, 6993, 0, + 1, 0, 0, 0, 480, 6385000, 192, 192, 0, 6385, 0, + 2, 0, 0, 0, 480, 10887000, 720, 720, 0, 10887, 0, + 3, 0, 0, 0, 480, 10575000, 768, 768, 0, 10575, 0, + 4, 0, 0, 0, 480, 11897000, 1536, 1536, 0, 11897, 0] +#endif + + index = __COUNTER__ +#endif + +#if CONFIG_COMP_GAIN + [[module.entry]] + name = "GAIN" + uuid = UUIDREG_STR_GAIN + affinity_mask = "0x1" + instance_count = "40" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xf, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 416, 12100000, 1536, 1536, 0, 12100, 0, + 1, 0, 0, 0, 416, 10183000, 384, 384, 0, 10183, 0, + 2, 0, 0, 0, 416, 8192000, 512, 512, 0, 8192, 0, + 3, 0, 0, 0, 416, 10091000, 128, 128, 0, 10091, 0, + 4, 0, 0, 0, 416, 5908000, 768, 768, 0, 5908, 0] +#elif CONFIG_LUNARLAKE + mod_cfg = [0, 0, 0, 0, 416, 9525000, 1536, 1536, 0, 9525, 0, + 1, 0, 0, 0, 416, 6266000, 384, 384, 0, 6266, 0, + 2, 0, 0, 0, 416, 7882000, 512, 512, 0, 7882, 0, + 3, 0, 0, 0, 416, 5170000, 128, 128, 0, 5170, 0, + 4, 0, 0, 0, 416, 5908000, 768, 768, 0, 0, 0] +#elif CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 + mod_cfg = [0, 0, 0, 0, 416, 11865000, 1536, 1536, 0, 11865, 0, + 1, 0, 0, 0, 416, 7797000, 384, 384, 1, 7797, 1, + 2, 0, 0, 0, 416, 12083000, 512, 512, 2, 12083, 2, + 3, 0, 0, 0, 416, 7163000, 128, 128, 3, 7163, 3] +#endif + + index = __COUNTER__ +#endif diff --git a/src/audio/volume/volume_generic.c b/src/audio/volume/volume_generic.c index 89c11b7e3637..0830677c7c94 100644 --- a/src/audio/volume/volume_generic.c +++ b/src/audio/volume/volume_generic.c @@ -7,17 +7,13 @@ // Tomasz Lauda <tomasz.lauda@linux.intel.com> /** - * \file audio/volume_generic.c - * \brief Volume generic processing implementation + * \file + * \brief Volume generic processing implementation without peak volume detection * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com>\n * Keyon Jie <yang.jie@linux.intel.com>\n * Tomasz Lauda <tomasz.lauda@linux.intel.com> */ -#include <sof/audio/volume.h> - -#ifdef CONFIG_GENERIC - #include <sof/audio/buffer.h> #include <sof/audio/component.h> #include <sof/audio/format.h> @@ -25,6 +21,15 @@ #include <ipc/stream.h> #include <stddef.h> #include <stdint.h> +#include <stdlib.h> + +LOG_MODULE_DECLARE(volume_generic, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(NONE, VOLUME) + +#if (!CONFIG_COMP_PEAK_VOL) #if CONFIG_FORMAT_S24LE /** @@ -33,44 +38,100 @@ * \param[in] vol gain. * \return output sample. * - * Volume multiply for 24 bit input and 24 bit bit output. + * Volume multiply for 24 bit input and 24 bit output. */ static inline int32_t vol_mult_s24_to_s24(int32_t x, int32_t vol) { - return q_multsr_sat_32x32_24(sign_extend_s24(x), vol, - Q_SHIFT_BITS_64(23, 16, 23)); + return q_multsr_sat_32x32_24(sign_extend_s24(x), vol, Q_SHIFT_BITS_64(23, VOL_QXY_Y, 23)); } /** * \brief Volume processing from 24/32 bit to 24/32 bit. * \param[in,out] dev Volume base component device. * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. + * \param[in,out] source Input buffer. * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) * * Copy and scale volume from 24/32 bit source buffer * to 24/32 bit destination buffer. */ -static void vol_s24_to_s24(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames) +static void vol_s24_to_s24(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t *src; - int32_t *dest; - int32_t i; - uint32_t channel; - uint32_t buff_frag = 0; - - /* Samples are Q1.23 --> Q1.23 and volume is Q8.16 */ - for (i = 0; i < frames; i++) { - for (channel = 0; channel < sink->channels; channel++) { - src = audio_stream_read_frag_s32(source, buff_frag); - dest = audio_stream_write_frag_s32(sink, buff_frag); - - *dest = vol_mult_s24_to_s24(*src, cd->volume[channel]); - - buff_frag++; + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t vol; + int32_t *x, *x0; + int32_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + 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) { + nmax = audio_stream_samples_without_wrap_s24(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s24(sink, y); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + vol = cd->volume[j]; + for (i = 0; i < n; i += nch) { + y0[i] = vol_mult_s24_to_s24(x0[i], vol); + } } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} + +/** + * \brief Volume passthrough from 24/32 bit to 24/32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + * + * Copy and scale volume from 24/32 bit source buffer + * to 24/32 bit destination buffer. + */ +static void vol_passthrough_s24_to_s24(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t *x; + int32_t *y; + int nmax, n; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + 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) { + nmax = audio_stream_samples_without_wrap_s24(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s24(sink, y); + n = MIN(n, nmax); + memcpy_s(y, n * sizeof(int32_t), x, n * sizeof(int32_t)); + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); } } #endif /* CONFIG_FORMAT_S24LE */ @@ -80,34 +141,91 @@ static void vol_s24_to_s24(struct comp_dev *dev, struct audio_stream *sink, * \brief Volume processing from 32 bit to 32 bit. * \param[in,out] dev Volume base component device. * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. + * \param[in,out] source Input buffer. * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) * * Copy and scale volume from 32 bit source buffer * to 32 bit destination buffer. */ -static void vol_s32_to_s32(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames) +static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) { - struct comp_data *cd = comp_get_drvdata(dev); - int32_t *src; - int32_t *dest; - int32_t i; - uint32_t channel; - uint32_t buff_frag = 0; - - /* Samples are Q1.31 --> Q1.31 and volume is Q8.16 */ - for (i = 0; i < frames; i++) { - for (channel = 0; channel < sink->channels; channel++) { - src = audio_stream_read_frag_s32(source, buff_frag); - dest = audio_stream_write_frag_s32(sink, buff_frag); - - *dest = q_multsr_sat_32x32 - (*src, cd->volume[channel], - Q_SHIFT_BITS_64(31, 16, 31)); - - buff_frag++; + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t vol; + int32_t *x, *x0; + int32_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + 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) { + nmax = audio_stream_samples_without_wrap_s32(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, y); + n = MIN(n, nmax); + /* Note: on Xtensa processing one channel volume at time performed slightly + * better than simpler interleaved code version (average 19 us vs. 20 us). + */ + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + vol = cd->volume[j]; + for (i = 0; i < n; i += nch) { + y0[i] = q_multsr_sat_32x32(x0[i], vol, + Q_SHIFT_BITS_64(31, VOL_QXY_Y, 31)); + } } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} + +/** + * \brief Volume passthrough from 32 bit to 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + * + * Copy and scale volume from 32 bit source buffer + * to 32 bit destination buffer. + */ +static void vol_passthrough_s32_to_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t *x; + int32_t *y; + int nmax, n; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + 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) { + nmax = audio_stream_samples_without_wrap_s32(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, y); + n = MIN(n, nmax); + memcpy_s(y, n * sizeof(int32_t), x, n * sizeof(int32_t)); + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); } } #endif /* CONFIG_FORMAT_S32LE */ @@ -117,50 +235,105 @@ static void vol_s32_to_s32(struct comp_dev *dev, struct audio_stream *sink, * \brief Volume processing from 16 bit to 16 bit. * \param[in,out] dev Volume base component device. * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. + * \param[in,out] source Input buffer. * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) * * Copy and scale volume from 16 bit source buffer * to 16 bit destination buffer. */ -static void vol_s16_to_s16(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames) +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) { - struct comp_data *cd = comp_get_drvdata(dev); - int16_t *src; - int16_t *dest; - int32_t i; - uint32_t channel; - uint32_t buff_frag = 0; - - /* Samples are Q1.15 --> Q1.15 and volume is Q8.16 */ - for (i = 0; i < frames; i++) { - for (channel = 0; channel < sink->channels; channel++) { - src = audio_stream_read_frag_s16(source, buff_frag); - dest = audio_stream_write_frag_s16(sink, buff_frag); - - *dest = q_multsr_sat_32x32_16 - (*src, cd->volume[channel], - Q_SHIFT_BITS_32(15, 16, 15)); - - buff_frag++; + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t vol; + int16_t *x, *x0; + int16_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + 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) { + nmax = audio_stream_samples_without_wrap_s16(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, y); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + vol = cd->volume[j]; + for (i = 0; i < n; i += nch) { + y0[i] = q_multsr_sat_32x32_16(x0[i], vol, + Q_SHIFT_BITS_32(15, VOL_QXY_Y, 15)); + } } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} + +/** + * \brief Volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + * + * Copy and scale volume from 16 bit source buffer + * to 16 bit destination buffer. + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int16_t *x; + int16_t *y; + int nmax, n; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + + 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) { + nmax = audio_stream_samples_without_wrap_s16(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, y); + n = MIN(n, nmax); + memcpy_s(y, n * sizeof(int16_t), x, n * sizeof(int16_t)); + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); } } #endif /* CONFIG_FORMAT_S16LE */ -const struct comp_func_map func_map[] = { +const struct comp_func_map volume_func_map[] = { #if CONFIG_FORMAT_S16LE - { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16 }, -#endif /* CONFIG_FORMAT_S16LE */ + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif #if CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24 }, -#endif /* CONFIG_FORMAT_S24LE */ + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24, vol_passthrough_s24_to_s24}, +#endif #if CONFIG_FORMAT_S32LE - { SOF_IPC_FRAME_S32_LE, vol_s32_to_s32 }, -#endif /* CONFIG_FORMAT_S32LE */ + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s32, vol_passthrough_s32_to_s32}, +#endif }; -const size_t func_count = ARRAY_SIZE(func_map); +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); #endif +#endif diff --git a/src/audio/volume/volume_generic_with_peakvol.c b/src/audio/volume/volume_generic_with_peakvol.c new file mode 100644 index 000000000000..106e1d3c7bdd --- /dev/null +++ b/src/audio/volume/volume_generic_with_peakvol.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +/** + * \file + * \brief Volume generic processing implementation with peak volume detection + * \authors Andrula Song <andrula.song@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +LOG_MODULE_DECLARE(volume_generic, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(NONE, VOLUME) + +#if CONFIG_COMP_PEAK_VOL + +#if CONFIG_FORMAT_S24LE +/** + * \brief Volume s24 to s24 multiply function + * \param[in] x input sample. + * \param[in] vol gain. + * \return output sample. + * + * Volume multiply for 24 bit input and 24 bit output. + */ +static inline int32_t vol_mult_s24_to_s24(int32_t x, int32_t vol) +{ + return q_multsr_sat_32x32_24(sign_extend_s24(x), vol, Q_SHIFT_BITS_64(23, VOL_QXY_Y, 23)); +} + +/** + * \brief Volume processing from 24/32 bit to 24/32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + * + * Copy and scale volume from 24/32 bit source buffer + * to 24/32 bit destination buffer. + */ +static void vol_s24_to_s24(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t vol; + int32_t *x, *x0; + int32_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + int32_t tmp; + + 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) { + nmax = audio_stream_samples_without_wrap_s24(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s24(sink, y); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + vol = cd->volume[j]; + tmp = 0; + for (i = 0; i < n; i += nch) { + y0[i] = vol_mult_s24_to_s24(x0[i], vol); + tmp = MAX(abs(x0[i]), tmp); + } + tmp = tmp << (attenuation + PEAK_24S_32C_ADJUST); + cd->peak_regs.peak_meter[j] = MAX(tmp, cd->peak_regs.peak_meter[j]); + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} + +/** + * \brief Volume passthrough from 24/32 bit to 24/32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + * + * Copy and scale volume from 24/32 bit source buffer + * to 24/32 bit destination buffer. + */ +static void vol_passthrough_s24_to_s24(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t *x, *x0; + int32_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + int32_t tmp; + + 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) { + nmax = audio_stream_samples_without_wrap_s24(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s24(sink, y); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + tmp = 0; + for (i = 0; i < n; i += nch) { + y0[i] = x0[i]; + tmp = MAX(abs(x0[i]), tmp); + } + tmp = tmp << (attenuation + PEAK_24S_32C_ADJUST); + cd->peak_regs.peak_meter[j] = MAX(tmp, cd->peak_regs.peak_meter[j]); + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief Volume processing from 32 bit to 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + * + * Copy and scale volume from 32 bit source buffer + * to 32 bit destination buffer. + */ +static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t vol; + int32_t *x, *x0; + int32_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + int32_t tmp; + + 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) { + nmax = audio_stream_samples_without_wrap_s32(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, y); + n = MIN(n, nmax); + /* Note: on Xtensa processing one channel volume at time performed slightly + * better than simpler interleaved code version (average 19 us vs. 20 us). + */ + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + vol = cd->volume[j]; + tmp = 0; + for (i = 0; i < n; i += nch) { + y0[i] = q_multsr_sat_32x32(x0[i], vol, + Q_SHIFT_BITS_64(31, VOL_QXY_Y, 31)); + tmp = MAX(abs(x0[i]), tmp); + } + tmp = tmp << attenuation; + cd->peak_regs.peak_meter[j] = MAX(tmp, cd->peak_regs.peak_meter[j]); + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} + +/** + * \brief Volume passthrough from 32 bit to 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + * + * Copy and scale volume from 32 bit source buffer + * to 32 bit destination buffer. + */ +static void vol_passthrough_s32_to_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t *x, *x0; + int32_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + int32_t tmp; + + 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) { + nmax = audio_stream_samples_without_wrap_s32(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s32(sink, y); + n = MIN(n, nmax); + /* Note: on Xtensa processing one channel volume at time performed slightly + * better than simpler interleaved code version (average 19 us vs. 20 us). + */ + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + tmp = 0; + for (i = 0; i < n; i += nch) { + y0[i] = x0[i]; + tmp = MAX(abs(x0[i]), tmp); + } + tmp = tmp << attenuation; + cd->peak_regs.peak_meter[j] = MAX(tmp, cd->peak_regs.peak_meter[j]); + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +/** + * \brief Volume processing from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + * + * Copy and scale volume from 16 bit source buffer + * to 16 bit destination buffer. + */ +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int32_t vol; + int16_t *x, *x0; + int16_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + uint32_t tmp; + + 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) { + nmax = audio_stream_samples_without_wrap_s16(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, y); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + vol = cd->volume[j]; + tmp = 0; + for (i = 0; i < n; i += nch) { + y0[i] = q_multsr_sat_32x32_16(x0[i], vol, + Q_SHIFT_BITS_32(15, VOL_QXY_Y, 15)); + tmp = MAX(abs(x0[i]), tmp); + } + tmp <<= PEAK_16S_32C_ADJUST; + cd->peak_regs.peak_meter[j] = MAX(tmp, cd->peak_regs.peak_meter[j]); + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} + +/** + * \brief Volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + * + * Copy and scale volume from 16 bit source buffer + * to 16 bit destination buffer. + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + int16_t *x, *x0; + int16_t *y, *y0; + int nmax, n, i, j; + const int nch = audio_stream_get_channels(source); + int remaining_samples = frames * nch; + uint32_t tmp; + + 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) { + nmax = audio_stream_samples_without_wrap_s16(source, x); + n = MIN(remaining_samples, nmax); + nmax = audio_stream_samples_without_wrap_s16(sink, y); + n = MIN(n, nmax); + for (j = 0; j < nch; j++) { + x0 = x + j; + y0 = y + j; + tmp = 0; + for (i = 0; i < n; i += nch) { + y0[i] = x0[i]; + tmp = MAX(abs(x0[i]), tmp); + } + tmp <<= PEAK_16S_32C_ADJUST; + cd->peak_regs.peak_meter[j] = MAX(tmp, cd->peak_regs.peak_meter[j]); + } + remaining_samples -= n; + x = audio_stream_wrap(source, x + n); + y = audio_stream_wrap(sink, y + n); + } +} +#endif + +const struct comp_func_map volume_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24, vol_passthrough_s24_to_s24}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s32, vol_passthrough_s32_to_s32}, +#endif +}; + +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif +#endif diff --git a/src/audio/volume/volume_hifi3.c b/src/audio/volume/volume_hifi3.c index 12c5ad8c1f04..afbb8ff44c02 100644 --- a/src/audio/volume/volume_hifi3.c +++ b/src/audio/volume/volume_hifi3.c @@ -5,31 +5,46 @@ // Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> /** - * \file audio/volume_hifi3.c - * \brief Volume HiFi3 processing implementation + * \file + * \brief Volume HiFi3 processing implementation without peak volume detection * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> */ -#include <sof/audio/volume.h> - -#if defined(__XCC__) && XCHAL_HAVE_HIFI3 - #include <sof/audio/buffer.h> #include <sof/audio/component.h> #include <sof/common.h> #include <ipc/stream.h> -#include <xtensa/tie/xt_hifi3.h> #include <stddef.h> #include <stdint.h> +LOG_MODULE_DECLARE(volume_hifi3, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(3, VOLUME) + +#if (!CONFIG_COMP_PEAK_VOL) + +#include <xtensa/tie/xt_hifi3.h> + /** - * \brief Sets buffer to be circular using HiFi3 functions. - * \param[in,out] buffer Circular buffer. + * \brief store volume gain 4 times for xtensa multi-way intrinsic operations. + * Simultaneous processing 2 data. + * \param[in,out] cd Volume component private data. + * \param[in] channels_count Number of channels to process. */ -static void vol_setup_circular(const struct audio_stream *buffer) +static void vol_store_gain(struct vol_data *cd, const int channels_count) { - AE_SETCBEGIN0(buffer->addr); - AE_SETCEND0(buffer->end_addr); + int32_t i; + + /* using for loop instead of memcpy_s(), because for loop costs less cycles */ + for (i = 0; i < channels_count; i++) { + cd->vol[i] = cd->volume[i]; + cd->vol[i + channels_count * 1] = cd->volume[i]; + cd->vol[i + channels_count * 2] = cd->volume[i]; + cd->vol[i + channels_count * 3] = cd->volume[i]; + } + cd->copy_gain = false; } #if CONFIG_FORMAT_S24LE @@ -37,58 +52,135 @@ static void vol_setup_circular(const struct audio_stream *buffer) * \brief HiFi3 enabled volume processing from 24/32 bit to 24/32 or 32 bit. * \param[in,out] dev Volume base component device. * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. + * \param[in,out] source Input buffer. * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) */ -static void vol_s24_to_s24_s32(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, - uint32_t frames) +static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) { - struct comp_data *cd = comp_get_drvdata(dev); - ae_f64 mult; - ae_f32x2 in_sample = AE_ZERO32(); + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; ae_f32x2 out_sample; ae_f32x2 volume; - size_t channel; - int i; - int shift = 8; - ae_int32 *in = (ae_int32 *)source->r_ptr; - ae_int32 *out = (ae_int32 *)sink->w_ptr; - - /* Main processing loop */ - for (i = 0; i < frames; i++) { - /* Processing per channel */ - for (channel = 0; channel < sink->channels; channel++) { - /* Set source as circular buffer */ - vol_setup_circular(source); + ae_f32x2 *buf; + ae_f32x2 *buf_end; + int i, n, m; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 2); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s24(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s24(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the volume value */ + AE_L32X2_XC(volume, vol, inc); /* Load the input sample */ - AE_L32_XC(in_sample, in, sizeof(ae_int32)); - - /* Load volume */ - volume = (ae_f32x2)cd->volume[channel]; + AE_LA32X2_IP(in_sample, inu, in); /* Multiply the input sample */ - mult = AE_MULF32S_LL(volume, AE_SLAA32(in_sample, 8)); - - /* Multiplication of Q1.31 x Q1.31 gives Q1.63. - * Now multiplication is Q8.16 x Q1.31, the result - * is Q9.48. Need to shift right by one to get Q17.47 - * compatible format for round. - */ - out_sample = AE_ROUND32F48SSYM(AE_SRAI64(mult, 1)); +#if COMP_VOLUME_Q8_16 + out_sample = AE_MULFP32X2RS(AE_SLAI32S(volume, 7), AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_23 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); +#endif - /* Shift for S24_LE */ - out_sample = AE_SRAA32RS(out_sample, shift); - out_sample = AE_SLAA32S(out_sample, shift); - out_sample = AE_SRAA32(out_sample, shift); + /* Shift to S24_LE */ + out_sample = AE_SRAI32(out_sample, 8); - /* Set sink as circular buffer */ - vol_setup_circular(sink); + /* Store the output sample */ + AE_SA32X2_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} +/** + * \brief HiFi3 enabled volume passthrough from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s24(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s24(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); /* Store the output sample */ - AE_S32_L_XC(out_sample, out, sizeof(ae_int32)); + AE_SA32X2_IP(in_sample, outu, out); } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } } #endif /* CONFIG_FORMAT_S24LE */ @@ -96,60 +188,134 @@ static void vol_s24_to_s24_s32(struct comp_dev *dev, struct audio_stream *sink, #if CONFIG_FORMAT_S32LE /** * \brief HiFi3 enabled volume processing from 32 bit to 24/32 or 32 bit. - * \param[in,out] dev Volume base component device. + * \param[in,out] mod Pointer to struct processing_module * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. + * \param[in,out] source Input buffer. * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) */ -static void vol_s32_to_s24_s32(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, - uint32_t frames) +static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) { - struct comp_data *cd = comp_get_drvdata(dev); - ae_f64 mult; - ae_f32x2 in_sample = AE_ZERO32(); + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; ae_f32x2 out_sample; ae_f32x2 volume; - size_t channel; - int shift = 0; - int i; - ae_int32 *in = (ae_int32 *)source->r_ptr; - ae_int32 *out = (ae_int32 *)sink->w_ptr; - - /* Main processing loop */ - for (i = 0; i < frames; i++) { - /* Processing per channel */ - for (channel = 0; channel < sink->channels; channel++) { - /* Set source as circular buffer */ - vol_setup_circular(source); + int i, n, m; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_rptr(source) + + bsource->consumed); + 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 + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 2); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the volume value */ + AE_L32X2_XC(volume, vol, inc); /* Load the input sample */ - AE_L32_XC(in_sample, in, sizeof(ae_int32)); - - /* Load volume */ - volume = (ae_f32x2)cd->volume[channel]; - - /* Multiply the input sample */ - mult = AE_MULF32S_LL(volume, in_sample); - - /* Multiplication of Q1.31 x Q1.31 gives Q1.63. - * Now multiplication is Q8.16 x Q1.31, the result - * is Q9.48. Need to shift right by one to get Q17.47 - * compatible format for round. + AE_LA32X2_IP(in_sample, inu, in); +#if COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, in_sample); +#else + /* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 */ - out_sample = AE_ROUND32F48SSYM(AE_SRAI64(mult, 1)); + ae_f64 mult0 = AE_MULF32R_HH(volume, in_sample); + ae_f64 mult1 = AE_MULF32R_LL(volume, in_sample); - /* Shift for S24_LE */ - out_sample = AE_SRAA32RS(out_sample, shift); - out_sample = AE_SLAA32S(out_sample, shift); - out_sample = AE_SRAA32(out_sample, shift); - - /* Set sink as circular buffer */ - vol_setup_circular(sink); + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ +#endif + AE_SA32X2_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} - /* Store the output sample */ - AE_S32_L_XC(out_sample, out, sizeof(ae_int32)); +/** + * \brief HiFi3 enabled volume passthrough from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + AE_SA32X2_IP(in_sample, outu, out); } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } } #endif /* CONFIG_FORMAT_S32LE */ @@ -159,67 +325,160 @@ static void vol_s32_to_s24_s32(struct comp_dev *dev, struct audio_stream *sink, * \brief HiFi3 enabled volume processing from 16 bit to 16 bit. * \param[in,out] dev Volume base component device. * \param[in,out] sink Destination buffer. - * \param[in,out] source Source buffer. + * \param[in,out] source Input buffer. * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) */ -static void vol_s16_to_s16(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames) +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) { - struct comp_data *cd = comp_get_drvdata(dev); - ae_f64 mult; - ae_f32x2 volume; - ae_f32x2 out_sample; - ae_f16x4 in_sample = AE_ZERO16(); - size_t channel; - int i; - ae_int16 *in = (ae_int16 *)source->r_ptr; - ae_int16 *out = (ae_int16 *)sink->w_ptr; - - /* Main processing loop */ - for (i = 0; i < frames; i++) { - /* Processing per channel */ - for (channel = 0; channel < sink->channels; channel++) { - /* Set source as circular buffer */ - vol_setup_circular(source); + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 volume0; + ae_f32x2 volume1; + ae_f32x2 out_sample0; + ae_f32x2 out_sample1; + ae_f16x4 in_sample; + ae_f16x4 out_sample; + int i, n, m; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 4); + vol = buf; + + /* Set buf as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + for (i = 0; i < n; i += 4) { + /* load first two volume gain */ + AE_L32X2_XC(volume0, vol, inc); + + /* load second two volume gain */ + AE_L32X2_XC(volume1, vol, inc); /* Load the input sample */ - AE_L16_XC(in_sample, in, sizeof(ae_int16)); - - /* Load volume */ - volume = (ae_f32x2)cd->volume[channel]; - + AE_LA16X4_IP(in_sample, inu, in); + +#if COMP_VOLUME_Q1_31 + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample); +#else +#if COMP_VOLUME_Q8_16 + /* Shift Q8.16 to Q9.23 + * No need to shift Q1.23, it is OK as such + */ + volume0 = AE_SLAI32S(volume0, 7); + volume1 = AE_SLAI32S(volume1, 7); +#endif /* Multiply the input sample */ - mult = AE_MULF32X16_L0(volume, in_sample); + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample); - /* Multiply of Q1.31 x Q1.15 gives Q1.47. Multiply of - * Q8.16 x Q1.15 gives Q8.32, so need to shift left - * by 31 to get Q1.63. Sample is Q1.31. - */ - out_sample = AE_ROUND32F64SSYM(AE_SLAI64S(mult, 31)); + /* Q9.23 to Q1.31 */ + out_sample0 = AE_SLAI32S(out_sample0, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#endif - /* Set sink as circular buffer */ - vol_setup_circular(sink); + /* store the output */ + out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample1); + // AE_SA16X4_IC(out_sample, outu, out); + AE_SA16X4_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} - /* Round to Q1.15 and store the output sample */ - AE_S16_0_XC(AE_ROUND16X4F32SSYM(out_sample, out_sample), - out, sizeof(ae_int16)); +/** + * \brief HiFi3 enabled volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f16x4 in_sample; + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + for (i = 0; i < n; i += 4) { + /* Load the input sample */ + AE_LA16X4_IP(in_sample, inu, in); + AE_SA16X4_IP(in_sample, outu, out); } + AE_SA64POS_FP(outu, out); + samples -= n; + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); } } #endif /* CONFIG_FORMAT_S16LE */ - -const struct comp_func_map func_map[] = { +const struct comp_func_map volume_func_map[] = { #if CONFIG_FORMAT_S16LE - { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16 }, + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, #endif #if CONFIG_FORMAT_S24LE - { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32 }, + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32, vol_passthrough_s24_to_s24_s32 }, #endif #if CONFIG_FORMAT_S32LE - { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32 }, + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32, vol_passthrough_s32_to_s24_s32 }, #endif }; -const size_t func_count = ARRAY_SIZE(func_map); - +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif #endif diff --git a/src/audio/volume/volume_hifi3_with_peakvol.c b/src/audio/volume/volume_hifi3_with_peakvol.c new file mode 100644 index 000000000000..4f89330baca7 --- /dev/null +++ b/src/audio/volume/volume_hifi3_with_peakvol.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +/** + * \file + * \brief Volume HiFi3 processing implementation with peak volume detection + * \authors Andrula Song <andrula.song@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(volume_hifi3, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(3, VOLUME) + +#if CONFIG_COMP_PEAK_VOL + +#include <xtensa/tie/xt_hifi3.h> + +#if CONFIG_FORMAT_S24LE +/** + * \brief HiFi3 enabled volume processing from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + ae_f32x2 out_sample; + ae_f32x2 volume; + int channel, n, i, m; + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + ae_f32 *in, *out; + 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; + uint32_t *peak_meter = cd->peak_regs.peak_meter; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in0); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out0); + n = MIN(m, n); + for (channel = 0; channel < channels_count; channel++) { + peak_vol = AE_ZERO32(); + /* set start address of sample load */ + in = in0 + channel; + /* set start address of sample store */ + out = out0 + channel; + /* Load volume */ + volume = (ae_f32x2)cd->volume[channel]; + for (i = 0; i < n; i += channels_count) { + /* Load the input sample */ + AE_L32_XP(in_sample, in, inc); + /* calc peak vol */ + peak_vol = AE_MAXABS32S(in_sample, peak_vol); + + /* Multiply the input sample */ +#if COMP_VOLUME_Q8_16 + out_sample = AE_MULFP32X2RS(AE_SLAI32S(volume, 7), + AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_23 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); +#endif + + /* Shift to S24_LE */ + out_sample = AE_SRAI32(out_sample, 8); + /* Store the output sample */ + AE_S32_L_XP(out_sample, out, inc); + } + peak_vol = AE_SLAA32S(peak_vol, attenuation + PEAK_24S_32C_ADJUST); + peak_meter[channel] = AE_MAX32(peak_vol, peak_meter[channel]); + } + samples -= n; + out0 = audio_stream_wrap(sink, out0 + n); + in0 = audio_stream_wrap(source, in0 + n); + } +} + +/** + * \brief HiFi3 enabled volume passthrough from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int channel, n, i, m; + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + ae_f32 *in, *out; + 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; + uint32_t *peak_meter = cd->peak_regs.peak_meter; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in0); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out0); + n = MIN(m, n); + for (channel = 0; channel < channels_count; channel++) { + peak_vol = AE_ZERO32(); + /* set start address of sample load */ + in = in0 + channel; + /* set start address of sample store */ + out = out0 + channel; + for (i = 0; i < n; i += channels_count) { + /* Load the input sample */ + AE_L32_XP(in_sample, in, inc); + /* calc peak vol */ + peak_vol = AE_MAXABS32S(in_sample, peak_vol); + /* Store the output sample */ + AE_S32_L_XP(in_sample, out, inc); + } + peak_vol = AE_SLAA32S(peak_vol, attenuation + PEAK_24S_32C_ADJUST); + peak_meter[channel] = AE_MAX32(peak_vol, peak_meter[channel]); + } + samples -= n; + out0 = audio_stream_wrap(sink, out0 + n); + in0 = audio_stream_wrap(source, in0 + n); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief HiFi3 enabled volume processing from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + ae_f32x2 out_sample; + ae_f32x2 volume; + int i, n, channel, m; + 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 *)audio_stream_get_rptr(source) + + bsource->consumed); + 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; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in0); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out0); + n = MIN(m, n); + for (channel = 0; channel < channels_count; channel++) { + peak_vol = AE_ZERO32(); + /* set start address of sample load */ + in = in0 + channel; + /* set start address of sample store */ + out = out0 + channel; + /* Load volume */ + volume = (ae_f32x2)cd->volume[channel]; + for (i = 0; i < n; i += channels_count) { + /* Load the input sample */ + AE_L32_XP(in_sample, in, inc); + /* calc peak vol */ + peak_vol = AE_MAXABS32S(in_sample, peak_vol); + +#if COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, in_sample); +#else + /* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 + */ + ae_f64 mult0 = AE_MULF32R_HH(volume, in_sample); + + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + out_sample = AE_ROUND32F48SSYM(mult0); /* Q2.47 -> Q1.31 */ +#endif + + AE_S32_L_XP(out_sample, out, inc); + } + peak_vol = AE_SLAA32S(peak_vol, attenuation); + peak_meter[channel] = AE_MAX32(peak_vol, peak_meter[channel]); + } + samples -= n; + out0 = audio_stream_wrap(sink, out0 + n); + in0 = audio_stream_wrap(source, in0 + n); + } +} + +/** + * \brief HiFi3 enabled volume passthrough from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int i, n, channel, m; + 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 *)audio_stream_get_rptr(source) + + bsource->consumed); + 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; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in0); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out0); + n = MIN(m, n); + for (channel = 0; channel < channels_count; channel++) { + peak_vol = AE_ZERO32(); + /* set start address of sample load */ + in = in0 + channel; + /* set start address of sample store */ + out = out0 + channel; + for (i = 0; i < n; i += channels_count) { + /* Load the input sample */ + AE_L32_XP(in_sample, in, inc); + /* calc peak vol */ + peak_vol = AE_MAXABS32S(in_sample, peak_vol); + + AE_S32_L_XP(in_sample, out, inc); + } + peak_vol = AE_SLAA32S(peak_vol, attenuation); + peak_meter[channel] = AE_MAX32(peak_vol, peak_meter[channel]); + } + samples -= n; + out0 = audio_stream_wrap(sink, out0 + n); + in0 = audio_stream_wrap(source, in0 + n); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +/** + * \brief HiFi3 enabled volume processing from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + */ +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 volume; + ae_f32x2 out_sample0; + ae_f16x4 in_sample; + ae_f16x4 out_sample; + int i, n, channel, m; + ae_f16 *in; + ae_f16 *out; + 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 *)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; + uint32_t *peak_meter = cd->peak_regs.peak_meter; + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in0); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out0); + n = MIN(m, n); + for (channel = 0; channel < channels_count; channel++) { + peak_vol = AE_ZERO32(); + /* set start address of sample load */ + in = in0 + channel; + /* set start address of sample store */ + out = out0 + channel; + /* Load volume */ + volume = (ae_f32x2)cd->volume[channel]; +#if COMP_VOLUME_Q8_16 + /* Shift Q8.16 to Q9.23 + * No need to shift Q1.23, it is OK as such + */ + volume = AE_SLAI32S(volume, 7); +#endif + for (i = 0; i < n; i += channels_count) { + /* Load the input sample */ + AE_L16_XP(in_sample, in, inc); + + /* calc peak vol */ + peak_vol = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), peak_vol); + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume, in_sample); + +#if COMP_VOLUME_Q1_31 + /* No shift need, the product is Q1.31 */ +#else + /* Q9.23 to Q1.31 */ + out_sample0 = AE_SLAI32S(out_sample0, 8); +#endif + + /* store the output */ + out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample0); + // AE_SA16X4_IC(out_sample, outu, out); + AE_S16_0_XP(out_sample, out, inc); + } + peak_vol = AE_SLAA32(peak_vol, PEAK_16S_32C_ADJUST); + peak_meter[channel] = AE_MAX32(peak_vol, peak_meter[channel]); + } + out0 = audio_stream_wrap(sink, out0 + n); + in0 = audio_stream_wrap(source, in0 + n); + samples -= n; + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + } +} + +/** + * \brief HiFi3 enabled volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f16x4 in_sample; + int i, n, channel, m; + ae_f16 *in; + ae_f16 *out; + 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 *)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; + uint32_t *peak_meter = cd->peak_regs.peak_meter; + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in0); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out0); + n = MIN(m, n); + for (channel = 0; channel < channels_count; channel++) { + peak_vol = AE_ZERO32(); + /* set start address of sample load */ + in = in0 + channel; + /* set start address of sample store */ + out = out0 + channel; + for (i = 0; i < n; i += channels_count) { + /* Load the input sample */ + AE_L16_XP(in_sample, in, inc); + + /* calc peak vol */ + peak_vol = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), peak_vol); + + /* store the output */ + AE_S16_0_XP(in_sample, out, inc); + } + peak_vol = AE_SLAA32(peak_vol, PEAK_16S_32C_ADJUST); + peak_meter[channel] = AE_MAX32(peak_vol, peak_meter[channel]); + } + out0 = audio_stream_wrap(sink, out0 + n); + in0 = audio_stream_wrap(source, in0 + n); + samples -= n; + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +const struct comp_func_map volume_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32, vol_passthrough_s24_to_s24_s32}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32, vol_passthrough_s32_to_s24_s32}, +#endif +}; + +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif +#endif diff --git a/src/audio/volume/volume_hifi4.c b/src/audio/volume/volume_hifi4.c new file mode 100644 index 000000000000..2f879a31ec0e --- /dev/null +++ b/src/audio/volume/volume_hifi4.c @@ -0,0 +1,522 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +/** + * \file + * \brief Volume HiFi4 processing implementation without peak volume detection + * \authors Andrula Song <andrula.song@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(volume_hifi4, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(4, VOLUME) + +#if (!CONFIG_COMP_PEAK_VOL) + +#include <xtensa/tie/xt_hifi4.h> + +/** + * \brief store volume gain 4 times for xtensa multi-way intrinsic operations. + * Simultaneous processing 2 data. + * \param[in,out] cd Volume component private data. + * \param[in] channels_count Number of channels to process. + */ +static void vol_store_gain(struct vol_data *cd, const int channels_count) +{ + int32_t i; + + /* using for loop instead of memcpy_s(), because for loop costs less cycles */ + for (i = 0; i < channels_count; i++) { + cd->vol[i] = cd->volume[i]; + cd->vol[i + channels_count * 1] = cd->volume[i]; + cd->vol[i + channels_count * 2] = cd->volume[i]; + cd->vol[i + channels_count * 3] = cd->volume[i]; + } + cd->copy_gain = false; +} + +#if CONFIG_FORMAT_S24LE +/** + * \brief HiFi4 enabled volume processing from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + ae_f32x2 out_sample; + ae_f32x2 volume; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + int i, n, m; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 2); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s24(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s24(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the volume value */ + AE_L32X2_XC(volume, vol, inc); + + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + + /* Multiply the input sample */ +#if COMP_VOLUME_Q8_16 + out_sample = AE_MULFP32X2RS(AE_SLAI32S(volume, 7), AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_23 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); +#endif + + /* Shift to S24_LE */ + out_sample = AE_SRAI32(out_sample, 8); + + /* Store the output sample */ + AE_SA32X2_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +/** + * \brief HiFi4 enabled volume passthrough from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + int samples = audio_stream_get_channels(sink) * frames; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s24(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s24(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + /* Store the output sample */ + AE_SA32X2_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief HiFi4 enabled volume processing from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + ae_f32x2 out_sample; + ae_f32x2 volume; + int i, n, m; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_rptr(source) + + bsource->consumed); + 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 + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 2); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the volume value */ + AE_L32X2_XC(volume, vol, inc); + + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + +#if COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, in_sample); +#else + /* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 + */ + ae_f64 mult0 = AE_MULF32R_HH(volume, in_sample); + ae_f64 mult1 = AE_MULF32R_LL(volume, in_sample); + + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ +#endif + + AE_SA32X2_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +/** + * \brief HiFi4 enabled volume passthrough from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + AE_SA32X2_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +/** + * \brief HiFi4 enabled volume processing from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 volume0; + ae_f32x2 volume1; + ae_f32x2 out_sample0; + ae_f32x2 out_sample1; + ae_f16x4 in_sample; + ae_f16x4 out_sample; + int i, n, m, left; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 4); + vol = buf; + + /* Set buf as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + m = n >> 2; + left = n & 0x03; + /* Process samples in blocks of 4*/ + for (i = 0; i < m; i++) { + /* load first two volume gain */ + AE_L32X2_XC(volume0, vol, inc); + + /* load second two volume gain */ + AE_L32X2_XC(volume1, vol, inc); + + /* Load the input sample */ + AE_LA16X4_IP(in_sample, inu, in); + +#if COMP_VOLUME_Q1_31 + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample); +#else +#if COMP_VOLUME_Q8_16 + /* Shift Q8.16 to Q9.23 + * No need to shift Q1.23, it is OK as such + */ + volume0 = AE_SLAI32S(volume0, 7); + volume1 = AE_SLAI32S(volume1, 7); +#endif + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample); + + /* Q9.23 to Q1.31 */ + out_sample0 = AE_SLAI32S(out_sample0, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#endif + + /* store the output */ + out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample1); + AE_SA16X4_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* Process remaining samples if n is not a multiple of 4*/ + for (i = 0; i < left; i++) { + /* load volume gain */ + AE_L32_XC(volume0, (ae_f32 *)vol, sizeof(ae_f32)); + /* Load the input sample */ + AE_L16_IP(in_sample, (ae_f16 *)in, sizeof(ae_f16)); +#if COMP_VOLUME_Q1_31 + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); +#else +#if COMP_VOLUME_Q8_16 + /* Q8.16 to Q9.23 */ + volume0 = AE_SLAI32S(volume0, 7); +#endif + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + /* Q9.23 to Q1.31 */ + out_sample0 = AE_SLAI32S(out_sample0, 8); +#endif + /* store the output */ + out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample0); + AE_S16_0_IP(out_sample, (ae_f16 *)out, sizeof(ae_f16)); + } + + samples -= n; + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +/** + * \brief HiFi4 enabled volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f16x4 in_sample; + int i, n, m, left; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + m = n >> 2; + left = n & 0x03; + for (i = 0; i < m; i++) { + /* Load the input sample */ + AE_LA16X4_IP(in_sample, inu, in); + AE_SA16X4_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* Process remaining samples if n is not a multiple of 4*/ + for (i = 0; i < left; i++) { + /* Load the input sample */ + AE_L16_IP(in_sample, (ae_f16 *)in, sizeof(ae_f16)); + /* store the output */ + AE_S16_0_IP(in_sample, (ae_f16 *)out, sizeof(ae_f16)); + } + + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} +#endif /* CONFIG_FORMAT_S16LE */ +const struct comp_func_map volume_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32, vol_passthrough_s24_to_s24_s32}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32, vol_passthrough_s32_to_s24_s32}, +#endif +}; +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif +#endif diff --git a/src/audio/volume/volume_hifi4_with_peakvol.c b/src/audio/volume/volume_hifi4_with_peakvol.c new file mode 100644 index 000000000000..f3908ee1a8a0 --- /dev/null +++ b/src/audio/volume/volume_hifi4_with_peakvol.c @@ -0,0 +1,626 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +/** + * \file + * \brief Volume HIFI4 processing implementation with peak volume detection + * \authors Andrula Song <andrula.song@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(volume_hifi4, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(4, VOLUME) + +#if CONFIG_COMP_PEAK_VOL +#include <xtensa/tie/xt_hifi4.h> + +static inline void vol_store_gain(struct vol_data *cd, const int channels_count) +{ + int32_t i; + + /* using for loop instead of memcpy_s(), because for loop costs less cycles */ + for (i = 0; i < channels_count; i++) { + cd->vol[i] = cd->volume[i]; + cd->vol[i + channels_count * 1] = cd->volume[i]; + cd->vol[i + channels_count * 2] = cd->volume[i]; + cd->vol[i + channels_count * 3] = cd->volume[i]; + } + cd->copy_gain = false; +} + +#if CONFIG_FORMAT_S24LE +/** + * \brief HiFi4 enabled volume processing from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + ae_f32x2 out_sample; + ae_f32x2 volume; + int i, n, m; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + ae_f32x2 *peakvol = (ae_f32x2 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data twice) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 2); + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + vol = (ae_f32x2 *)cd->vol; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(vol); + AE_SETCEND0(cd->vol + channels_count * 2); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the volume value */ + AE_L32X2_XC(volume, vol, inc); + + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + AE_S32X2_XC1(temp, peakvol, inc); + +#if COMP_VOLUME_Q8_16 + out_sample = AE_MULFP32X2RS(AE_SLAI32S(volume, 7), AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_23 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); + out_sample = AE_SLAI32S(out_sample, 8); +#elif COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); +#endif + + /* Shift to S24_LE */ + out_sample = AE_SRAI32(out_sample, 8); + + /* Store the output sample */ + AE_SA32X2_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) + cd->peak_regs.peak_meter[i] = MAX(cd->peak_vol[i], + cd->peak_vol[i + channels_count]) + << (attenuation + PEAK_24S_32C_ADJUST); +} + +/** + * \brief HiFi4 enabled volume passthrough from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + ae_f32x2 *peakvol = (ae_f32x2 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data twice) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 2); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + AE_S32X2_XC1(temp, peakvol, inc); + /* Store the output sample */ + AE_SA32X2_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) + cd->peak_regs.peak_meter[i] = MAX(cd->peak_vol[i], + cd->peak_vol[i + channels_count]) + << (attenuation + PEAK_24S_32C_ADJUST); +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief HiFi4 enabled volume processing from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + ae_f32x2 out_sample; + ae_f32x2 volume; + int i, n, m; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_rptr(source) + + bsource->consumed); + 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; + + /* Set peakvol(which stores the peak volume data twice) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 2); + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 2); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the volume value */ + AE_L32X2_XC(volume, vol, inc); + + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + AE_S32X2_XC1(temp, peakvol, inc); + +#if COMP_VOLUME_Q1_31 + out_sample = AE_MULFP32X2RS(volume, in_sample); +#else + /* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 + */ + ae_f64 mult0 = AE_MULF32R_HH(volume, in_sample); + ae_f64 mult1 = AE_MULF32R_LL(volume, in_sample); + + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ +#endif + + AE_SA32X2_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) + cd->peak_regs.peak_meter[i] = MAX(cd->peak_vol[i], + cd->peak_vol[i + channels_count]) << attenuation; +} + +/** + * \brief HiFi4 enabled volume passthrough from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 in_sample; + int i, n, m; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)audio_stream_get_rptr(source) + + bsource->consumed); + 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; + + /* Set peakvol(which stores the peak volume data twice) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 2); + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + /* process two continuous sample data once */ + for (i = 0; i < n; i += 2) { + /* Load the input sample */ + AE_LA32X2_IP(in_sample, inu, in); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + AE_S32X2_XC1(temp, peakvol, inc); + + AE_SA32X2_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) + cd->peak_regs.peak_meter[i] = MAX(cd->peak_vol[i], + cd->peak_vol[i + channels_count]) << attenuation; +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +/** + * \brief HiFi4 enabled volume processing from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + */ +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f32x2 volume0; + ae_f32x2 volume1; + ae_f32x2 out_sample0; + ae_f32x2 out_sample1; + ae_f16x4 in_sample; + ae_f16x4 out_sample; + int i, n, m, left; + ae_f32x2 *buf; + ae_f32x2 *buf_end; + ae_f32x2 *vol; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + ae_f32x2 *peakvol = (ae_f32x2 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data 4 times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + /* to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_f32x2 *)cd->vol; + buf_end = (ae_f32x2 *)(cd->vol + channels_count * 4); + vol = buf; + + /* Set buf as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + m = n >> 2; + left = n & 0x03; + for (i = 0; i < m; i++) { + /* load first two volume gain */ + AE_L32X2_XC(volume0, vol, inc); + + /* load second two volume gain */ + AE_L32X2_XC(volume1, vol, inc); + + /* Load the input sample */ + AE_LA16X4_IP(in_sample, inu, in); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), temp); + AE_S32X2_XC1(temp, peakvol, inc); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample), temp); + AE_S32X2_XC1(temp, peakvol, inc); + +#if COMP_VOLUME_Q1_31 + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample); +#else +#if COMP_VOLUME_Q8_16 + /* Shift Q8.16 to Q9.23 + * No need to shift Q1.23, it is OK as such + */ + volume0 = AE_SLAI32S(volume0, 7); + volume1 = AE_SLAI32S(volume1, 7); +#endif + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + out_sample1 = AE_MULFP32X16X2RS_L(volume1, in_sample); + + /* Q9.23 to Q1.31 */ + out_sample0 = AE_SLAI32S(out_sample0, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#endif + + /* store the output */ + out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample1); + AE_SA16X4_IP(out_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* Process remaining samples if n is not a multiple of 4*/ + for (i = 0; i < left; i++) { + /* load first volume gain */ + AE_L32_XC(volume0, (ae_f32 *)vol, sizeof(ae_f32)); + + /* Load the input sample */ + AE_L16_IP(in_sample, (ae_f16 *)in, sizeof(ae_f16)); + /* calculate the peak volume*/ + AE_L32_XC1(temp, (ae_f32 *)peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), temp); + AE_S32_L_XC1(temp, (ae_f32 *)peakvol, sizeof(ae_f32)); + +#if COMP_VOLUME_Q1_31 + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); +#else +#if COMP_VOLUME_Q8_16 + /* Q8.16 to Q9.23 */ + volume0 = AE_SLAI32S(volume0, 7); +#endif + /* Multiply the input sample */ + out_sample0 = AE_MULFP32X16X2RS_H(volume0, in_sample); + /* Q9.23 to Q1.31 */ + out_sample0 = AE_SLAI32S(out_sample0, 8); +#endif + /* store the output */ + out_sample = AE_ROUND16X4F32SSYM(out_sample0, out_sample0); + AE_S16_0_IP(out_sample, (ae_f16 *)out, sizeof(ae_f16)); + } + + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + } + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << PEAK_16S_32C_ADJUST; + } +} + +/** + * \brief HiFi4 enabled volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_f16x4 in_sample; + int i, n, m, left; + ae_valign inu; + ae_valign outu = AE_ZALIGN64(); + 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 *)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; + ae_f32x2 *peakvol = (ae_f32x2 *)cd->peak_vol; + + /* Set peakvol (which stores the peak volume data 4 times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA64_PP(in); + m = n >> 2; + left = n & 0x03; + /* Process samples in blocks of 4*/ + for (i = 0; i < m; i++) { + /* Load the input sample */ + AE_LA16X4_IP(in_sample, inu, in); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), temp); + AE_S32X2_XC1(temp, peakvol, inc); + /* calculate the peak volume*/ + AE_L32X2_XC1(temp, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample), temp); + AE_S32X2_XC1(temp, peakvol, inc); + /* store the output */ + AE_SA16X4_IP(in_sample, outu, out); + } + AE_SA64POS_FP(outu, out); + + /* Process remaining samples if n is not a multiple of 4*/ + for (i = 0; i < left; i++) { + /* Load the input sample */ + AE_L16_IP(in_sample, (ae_f16 *)in, sizeof(ae_f16)); + /* store the output */ + AE_S16_0_IP(in_sample, (ae_f16 *)out, sizeof(ae_f16)); + /* calculate the peak volume*/ + AE_L32_XC1(temp, (ae_f32 *)peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample), temp); + AE_S32_L_XC1(temp, (ae_f32 *)peakvol, sizeof(ae_f32)); + } + + samples -= n; + in = (ae_f16x4 *)audio_stream_wrap(source, in); + out = (ae_f16x4 *)audio_stream_wrap(sink, out); + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + } + + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << PEAK_16S_32C_ADJUST; + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +const struct comp_func_map volume_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32, vol_passthrough_s24_to_s24_s32}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32, vol_passthrough_s32_to_s24_s32}, +#endif +}; + +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif +#endif diff --git a/src/audio/volume/volume_hifi5.c b/src/audio/volume/volume_hifi5.c new file mode 100644 index 000000000000..794330cddd9b --- /dev/null +++ b/src/audio/volume/volume_hifi5.c @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +/** + * \file + * \brief Volume HiFi5 processing implementation without peak volume detection + * \authors Andrula Song <andrula.song@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(volume, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +#if SOF_USE_HIFI(5, VOLUME) + +#if (!CONFIG_COMP_PEAK_VOL) + +#include <xtensa/tie/xt_hifi5.h> + +/** + * \brief store volume gain 4 times for xtensa multi-way intrinsic operations. + * Simultaneous processing 4 samples. + * \param[in,out] cd Volume component private data. + * \param[in] channels_count Number of channels to process. + */ +static void vol_store_gain(struct vol_data *cd, const int channels_count) +{ + int32_t i; + + for (i = 0; i < channels_count; i++) { + cd->vol[i] = cd->volume[i]; + cd->vol[i + channels_count * 1] = cd->volume[i]; + cd->vol[i + channels_count * 2] = cd->volume[i]; + cd->vol[i + channels_count * 3] = cd->volume[i]; + } + cd->copy_gain = false; +} + +#if CONFIG_FORMAT_S24LE +/** + * \brief HiFi5 enabled volume processing from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x2 volume, volume1; + ae_int32x4 *buf; + ae_int32x4 *buf_end; + int i, n, m; + ae_int32x4 *vol; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)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_int32x4); + int samples = channels_count * frames; + + /* to ensure the address is 16-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_int32x4 *)cd->vol; + buf_end = (ae_int32x4 *)(cd->vol + channels_count * 4); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s24(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s24(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per iteration */ + for (i = 0; i < n; i += 4) { + /* Load the volume value */ + AE_L32X2X2_XC(volume, volume1, vol, inc); + + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + + /* Multiply the input sample */ +#if COMP_VOLUME_Q8_16 + AE_MULF2P32X4RS(out_sample, out_sample1, + AE_SLAI32S(volume, 7), AE_SLAI32S(volume1, 7), + AE_SLAI32(in_sample, 8), AE_SLAI32(in_sample1, 8)); + out_sample = AE_SLAI32S(out_sample, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#elif COMP_VOLUME_Q1_23 + AE_MULF2P32X4RS(out_sample, out_sample1, volume, volume1, + AE_SLAI32(in_sample, 8), AE_SLAI32(in_sample1, 8)); + out_sample = AE_SLAI32S(out_sample, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#elif COMP_VOLUME_Q1_31 + AE_MULF2P32X4RS(out_sample, out_sample1, volume, volume1, + AE_SLAI32(in_sample, 8), AE_SLAI32(in_sample1, 8)); +#endif + + /* Shift for S24_LE */ + out_sample = AE_SRAI32(out_sample, 8); + out_sample1 = AE_SRAI32(out_sample1, 8); + + /* Store the output sample */ + AE_SA32X2X2_IP(out_sample, out_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +/** + * \brief HiFi5 enabled volume passthrough from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + int i, n, m; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)audio_stream_wrap(sink, + (char *)audio_stream_get_wptr(sink) + + bsink->size); + int samples = audio_stream_get_channels(sink) * frames; + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s24(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s24(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process 4 continuous samples once */ + for (i = 0; i < n; i += 4) { + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* Store the output sample */ + AE_SA32X2X2_IP(in_sample, in_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief HiFi5 enabled volume processing from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x2 volume, volume1; + int i, n, m; + ae_int32x4 *buf; + ae_int32x4 *buf_end; + ae_int32x4 *vol; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + const int channels_count = audio_stream_get_channels(sink); + const int inc = sizeof(ae_int32x4); + int samples = channels_count * frames; + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)audio_stream_wrap(sink, + (char *)audio_stream_get_wptr(sink) + + bsink->size); + + /** to ensure the address is 16-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_int32x4 *)cd->vol; + buf_end = (ae_int32x4 *)(cd->vol + channels_count * 4); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per iteration */ + for (i = 0; i < n; i += 4) { + /* Load the volume value */ + AE_L32X2X2_XC(volume, volume1, vol, inc); + + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); +#if COMP_VOLUME_Q1_31 + AE_MULF2P32X4RS(out_sample, out_sample1, + volume, volume1, + in_sample, in_sample1); +#else + /* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 + */ + ae_int64 mult0, mult1; + + AE_MULF32X2R_HH_LL(mult0, mult1, volume, in_sample); + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ + + AE_MULF32X2R_HH_LL(mult0, mult1, volume1, in_sample1); + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample1 = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ +#endif + AE_SA32X2X2_IP(out_sample, out_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +/** + * \brief HiFi5 enabled volume passthrough from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + int i, n, m; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)audio_stream_wrap(sink, + (char *)audio_stream_get_wptr(sink) + + bsink->size); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per iteration */ + for (i = 0; i < n; i += 4) { + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + AE_SA32X2X2_IP(in_sample, in_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +/** + * \brief HiFi5 enabled volume processing from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 volume, volume1, volume2, volume3; + ae_int32x2 out_temp, out_temp1; + ae_int16x4 in_sample, in_sample1; + ae_int16x4 out_sample, out_sample1; + int i, n, m; + ae_int32x4 *buf; + ae_int32x4 *buf_end; + ae_int32x4 *vol; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int16x8 *in = (ae_int16x8 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int16x8 *out = (ae_int16x8 *)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_int32x4); + int samples = channels_count * frames; + + /** to ensure the address is 16-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_int32x4 *)cd->vol; + buf_end = (ae_int32x4 *)(cd->vol + channels_count * 4); + vol = buf; + + /* Set buf as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + for (i = 0; i < n; i += 8) { + /* load 4x2 volume gain */ + AE_L32X2X2_XC(volume, volume1, vol, inc); + + AE_L32X2X2_XC(volume2, volume3, vol, inc); + + /* Load the input sample */ + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + +#if COMP_VOLUME_Q1_31 + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume, volume1, in_sample); + out_sample = AE_ROUND16X4F32SSYM(out_temp, out_temp1); + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume2, volume3, in_sample1); + out_sample1 = AE_ROUND16X4F32SSYM(out_temp, out_temp1); +#else +#if COMP_VOLUME_Q8_16 + /* Shift Q8.16 to Q9.23 + * No need to shift Q1.23, it is OK as such + */ + volume = AE_SLAI32S(volume, 7); + volume1 = AE_SLAI32S(volume1, 7); + volume2 = AE_SLAI32S(volume2, 7); + volume3 = AE_SLAI32S(volume3, 7); +#endif + + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume, volume1, in_sample); + /* Q9.23 to Q1.31 */ + out_temp = AE_SLAI32S(out_temp, 8); + out_temp1 = AE_SLAI32S(out_temp1, 8); + out_sample = AE_ROUND16X4F32SSYM(out_temp, out_temp1); + + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume2, volume3, in_sample1); + /* Q9.23 to Q1.31 */ + out_temp = AE_SLAI32S(out_temp, 8); + out_temp1 = AE_SLAI32S(out_temp1, 8); + out_sample1 = AE_ROUND16X4F32SSYM(out_temp, out_temp1); +#endif + + /* store the output */ + AE_SA16X4X2_IP(out_sample, out_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} + +/** + * \brief HiFi5 enabled volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused) + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int16x4 in_sample, in_sample1; + int i, n, m; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int16x8 *in = (ae_int16x8 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int16x8 *out = (ae_int16x8 *)audio_stream_wrap(sink, + (char *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); + int samples = channels_count * frames; + + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(samples); + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + for (i = 0; i < n; i += 8) { + /* Load the input sample */ + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + AE_SA16X4X2_IP(in_sample, in_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } +} +#endif /* CONFIG_FORMAT_S16LE */ +const struct comp_func_map volume_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32, vol_passthrough_s24_to_s24_s32}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32, vol_passthrough_s32_to_s24_s32}, +#endif +}; + +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif +#endif diff --git a/src/audio/volume/volume_hifi5_with_peakvol.c b/src/audio/volume/volume_hifi5_with_peakvol.c new file mode 100644 index 000000000000..16d2f7cb8bf9 --- /dev/null +++ b/src/audio/volume/volume_hifi5_with_peakvol.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +/** + * \file + * \brief Volume HIFI5 processing implementation with peak volume detection + * \authors Andrula Song <andrula.song@intel.com> + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/common.h> +#include <ipc/stream.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(volume, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +/* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * + * With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 + */ + +#if SOF_USE_HIFI(5, VOLUME) + +#if CONFIG_COMP_PEAK_VOL +#include <xtensa/tie/xt_hifi5.h> + +static inline void vol_store_gain(struct vol_data *cd, const int channels_count) +{ + int32_t i; + + for (i = 0; i < channels_count; i++) { + cd->vol[i] = cd->volume[i]; + cd->vol[i + channels_count * 1] = cd->volume[i]; + cd->vol[i + channels_count * 2] = cd->volume[i]; + cd->vol[i + channels_count * 3] = cd->volume[i]; + } + cd->copy_gain = false; +} + +#if CONFIG_FORMAT_S24LE +/** + * \brief HiFi5 enabled volume processing from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x2 volume, volume1; + int i, n, m; + ae_int32x4 *vol; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)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_int32x4); + int samples = channels_count * frames; + ae_int32x2 temp, temp1; + ae_int32x4 *peakvol = (ae_int32x4 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data four times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + /** to ensure the address is 16-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + vol = (ae_int32x4 *)cd->vol; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(vol); + AE_SETCEND0(cd->vol + channels_count * 4); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per loop */ + for (i = 0; i < n; i += 4) { + /* Load the volume value */ + AE_L32X2X2_XC(volume, volume1, vol, inc); + + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* calculate the peak volume*/ + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + temp1 = AE_MAXABS32S(in_sample1, temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + + /* Multiply the input sample */ +#if COMP_VOLUME_Q8_16 + AE_MULF2P32X4RS(out_sample, out_sample1, + AE_SLAI32S(volume, 7), AE_SLAI32S(volume1, 7), + AE_SLAI32(in_sample, 8), AE_SLAI32(in_sample1, 8)); + out_sample = AE_SLAI32S(out_sample, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#elif COMP_VOLUME_Q1_23 + AE_MULF2P32X4RS(out_sample, out_sample1, volume, volume1, + AE_SLAI32(in_sample, 8), AE_SLAI32(in_sample1, 8)); + out_sample = AE_SLAI32S(out_sample, 8); + out_sample1 = AE_SLAI32S(out_sample1, 8); +#elif COMP_VOLUME_Q1_31 + AE_MULF2P32X4RS(out_sample, out_sample1, volume, volume1, + AE_SLAI32(in_sample, 8), AE_SLAI32(in_sample1, 8)); +#endif + + /* Shift for S24_LE */ + out_sample = AE_SRAI32(out_sample, 8); + out_sample1 = AE_SRAI32(out_sample1, 8); + + /* Store the output sample */ + AE_SA32X2X2_IP(out_sample, out_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << (attenuation + PEAK_24S_32C_ADJUST); + } +} + +/** + * \brief HiFi5 enabled volume passthrough from 24/32 bit to 24/32 or 32 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_passthrough_s24_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + int i, n, m; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)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_int32x4); + int samples = channels_count * frames; + ae_int32x2 temp, temp1; + ae_int32x4 *peakvol = (ae_int32x4 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data four times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per loop */ + for (i = 0; i < n; i += 4) { + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* calculate the peak volume*/ + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + temp1 = AE_MAXABS32S(in_sample1, temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + /* Store the output sample */ + AE_SA32X2X2_IP(in_sample, in_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << (attenuation + PEAK_24S_32C_ADJUST); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +/** + * \brief HiFi5 enabled volume processing from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + ae_int32x2 out_sample, out_sample1; + ae_int32x2 volume, volume1; + int i, n, m; + ae_int32x4 *buf; + ae_int32x4 *buf_end; + ae_int32x4 *vol; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + const int channels_count = audio_stream_get_channels(sink); + const int inc = sizeof(ae_int32x4); + int samples = channels_count * frames; + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)audio_stream_wrap(sink, + (char *)audio_stream_get_wptr(sink) + + bsink->size); + ae_int32x2 temp, temp1; + ae_int32x4 *peakvol = (ae_int32x4 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data four times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + /** to ensure the address is 16-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_int32x4 *)cd->vol; + buf_end = (ae_int32x4 *)(cd->vol + channels_count * 4); + vol = buf; + /* Set buf who stores the volume gain data as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per loop */ + for (i = 0; i < n; i += 4) { + /* Load the volume value */ + AE_L32X2X2_XC(volume, volume1, vol, inc); + + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* calculate the peak volume*/ + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + temp1 = AE_MAXABS32S(in_sample1, temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); +#if COMP_VOLUME_Q1_31 + AE_MULF2P32X4RS(out_sample, out_sample1, + volume, volume1, + in_sample, in_sample1); +#else + /* With Q1.31 x Q1.31 -> Q17.47 HiFi multiplications the result is + * Q8.16 x Q1.31 << 1 >> 16 -> Q9.32, shift left by 15 for Q17.47 + * Q1.23 x Q1.31 << 1 >> 16 -> Q2.39, shift left by 8 for Q17.47 + */ + ae_f64 mult0, mult1; + + AE_MULF32X2R_HH_LL(mult0, mult1, volume, in_sample); + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ + + AE_MULF32X2R_HH_LL(mult0, mult1, volume1, in_sample1); + mult0 = AE_SLAI64(mult0, VOLUME_Q17_47_SHIFT); + mult1 = AE_SLAI64(mult1, VOLUME_Q17_47_SHIFT); + out_sample1 = AE_ROUND32X2F48SSYM(mult0, mult1); /* Q2.47 -> Q1.31 */ +#endif + AE_SA32X2X2_IP(out_sample, out_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << attenuation; + } +} + +/** + * \brief HiFi5 enabled volume passthrough from 32 bit to 24/32 or 32 bit. + * \param[in,out] mod Pointer to struct processing_module + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment + */ +static void vol_passthrough_s32_to_s24_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 in_sample, in_sample1; + int i, n, m; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + const int channels_count = audio_stream_get_channels(sink); + const int inc = sizeof(ae_int32x4); + int samples = channels_count * frames; + ae_int32x4 *in = (ae_int32x4 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int32x4 *out = (ae_int32x4 *)audio_stream_wrap(sink, + (char *)audio_stream_get_wptr(sink) + + bsink->size); + ae_int32x2 temp, temp1; + ae_int32x4 *peakvol = (ae_int32x4 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data four times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(samples); + bsink->size += VOL_S32_SAMPLES_TO_BYTES(samples); + + while (samples) { + m = audio_stream_samples_without_wrap_s32(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s32(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + /* process four continuous samples per iteration */ + for (i = 0; i < n; i += 4) { + /* Load the input sample */ + AE_LA32X2X2_IP(in_sample, in_sample1, inu, in); + /* calculate the peak volume*/ + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(in_sample, temp); + temp1 = AE_MAXABS32S(in_sample1, temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + + AE_SA32X2X2_IP(in_sample, in_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + } + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << attenuation; + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S16LE +/** + * \brief HiFi5 enabled volume processing from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + */ +static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int32x2 volume, volume1, volume2, volume3; + ae_int32x2 out_temp, out_temp1; + ae_int16x4 in_sample, in_sample1; + ae_int16x4 out_sample, out_sample1; + int i, n, m; + ae_int32x4 *buf; + ae_int32x4 *buf_end; + ae_int32x4 *vol; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int16x8 *in = (ae_int16x8 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int16x8 *out = (ae_int16x8 *)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_int32x4); + int samples = channels_count * frames; + ae_int32x2 temp, temp1; + ae_int32x4 *peakvol = (ae_int32x4 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data 4 times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + /** to ensure the address is 8-byte aligned and avoid risk of + * error loading of volume gain while the cd->vol would be set + * as circular buffer + */ + if (cd->copy_gain) + vol_store_gain(cd, channels_count); + + buf = (ae_int32x4 *)cd->vol; + buf_end = (ae_int32x4 *)(cd->vol + channels_count * 4); + vol = buf; + + /* Set buf as circular buffer */ + AE_SETCBEGIN0(buf); + AE_SETCEND0(buf_end); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + for (i = 0; i < n; i += 8) { + /* load volume gain */ + AE_L32X2X2_XC(volume, volume1, vol, inc); + AE_L32X2X2_XC(volume2, volume3, vol, inc); + + /* Load the input sample */ + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + /* calculate the peak volume*/ + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), temp); + temp1 = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample), temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample1), temp); + temp1 = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample1), temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + +#if COMP_VOLUME_Q1_31 + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume, volume1, in_sample); + out_sample = AE_ROUND16X4F32SSYM(out_temp, out_temp1); + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume2, volume3, in_sample1); + out_sample1 = AE_ROUND16X4F32SSYM(out_temp, out_temp1); +#else +#if COMP_VOLUME_Q8_16 + /* Shift Q8.16 to Q9.23 + * No need to shift Q1.23, it is OK as such + */ + volume = AE_SLAI32S(volume, 7); + volume1 = AE_SLAI32S(volume1, 7); + volume2 = AE_SLAI32S(volume2, 7); + volume3 = AE_SLAI32S(volume3, 7); +#endif + + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume, volume1, in_sample); + /* Q9.23 to Q1.31 */ + out_temp = AE_SLAI32S(out_temp, 8); + out_temp1 = AE_SLAI32S(out_temp1, 8); + out_sample = AE_ROUND16X4F32SSYM(out_temp, out_temp1); + + AE_MULF2P32X16X4RS(out_temp, out_temp1, volume2, volume3, in_sample1); + /* Q9.23 to Q1.31 */ + out_temp = AE_SLAI32S(out_temp, 8); + out_temp1 = AE_SLAI32S(out_temp1, 8); + out_sample1 = AE_ROUND16X4F32SSYM(out_temp, out_temp1); +#endif + /* store the output */ + AE_SA16X4X2_IP(out_sample, out_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + } + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << PEAK_16S_32C_ADJUST; + } +} + +/** + * \brief HiFi5 enabled volume passthrough from 16 bit to 16 bit. + * \param[in,out] dev Volume base component device. + * \param[in,out] sink Destination buffer. + * \param[in,out] source Input buffer. + * \param[in] frames Number of frames to process. + * \param[in] attenuation factor for peakmeter adjustment (unused for 16bit) + */ +static void vol_passthrough_s16_to_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + uint32_t attenuation) +{ + struct vol_data *cd = module_get_private_data(mod); + struct audio_stream *source = bsource->data; + struct audio_stream *sink = bsink->data; + ae_int16x4 in_sample, in_sample1; + int i, n, m; + ae_valignx2 inu; + ae_valignx2 outu = AE_ZALIGN128(); + ae_int16x8 *in = (ae_int16x8 *)audio_stream_wrap(source, + (char *)audio_stream_get_rptr(source) + + bsource->consumed); + ae_int16x8 *out = (ae_int16x8 *)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_int32x4); + int samples = channels_count * frames; + ae_int32x2 temp, temp1; + ae_int32x4 *peakvol = (ae_int32x4 *)cd->peak_vol; + + /* Set peakvol(which stores the peak volume data 4 times) as circular buffer */ + AE_SETCBEGIN1(cd->peak_vol); + AE_SETCEND1(cd->peak_vol + channels_count * 4); + + while (samples) { + m = audio_stream_samples_without_wrap_s16(source, in); + n = MIN(m, samples); + m = audio_stream_samples_without_wrap_s16(sink, out); + n = MIN(m, n); + inu = AE_LA128_PP(in); + for (i = 0; i < n; i += 8) { + /* Load the input sample */ + AE_LA16X4X2_IP(in_sample, in_sample1, inu, in); + /* calculate the peak volume*/ + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample), temp); + temp1 = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample), temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + + AE_L32X2X2_XC1(temp, temp1, peakvol, 0); + temp = AE_MAXABS32S(AE_SEXT32X2D16_32(in_sample1), temp); + temp1 = AE_MAXABS32S(AE_SEXT32X2D16_10(in_sample1), temp1); + AE_S32X2X2_XC1(temp, temp1, peakvol, inc); + + /* store the output */ + AE_SA16X4X2_IP(in_sample, in_sample1, outu, out); + } + AE_SA128POS_FP(outu, out); + samples -= n; + in = audio_stream_wrap(source, in); + out = audio_stream_wrap(sink, out); + bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(n); + bsink->size += VOL_S16_SAMPLES_TO_BYTES(n); + } + for (i = 0; i < channels_count; i++) { + m = MAX(cd->peak_vol[i], cd->peak_vol[i + channels_count]); + m = MAX(m, cd->peak_vol[i + channels_count * 2]); + m = MAX(m, cd->peak_vol[i + channels_count * 3]); + cd->peak_regs.peak_meter[i] = m << PEAK_16S_32C_ADJUST; + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +const struct comp_func_map volume_func_map[] = { +#if CONFIG_FORMAT_S16LE + { SOF_IPC_FRAME_S16_LE, vol_s16_to_s16, vol_passthrough_s16_to_s16}, +#endif +#if CONFIG_FORMAT_S24LE + { SOF_IPC_FRAME_S24_4LE, vol_s24_to_s24_s32, vol_passthrough_s24_to_s24_s32}, +#endif +#if CONFIG_FORMAT_S32LE + { SOF_IPC_FRAME_S32_LE, vol_s32_to_s24_s32, vol_passthrough_s32_to_s24_s32}, +#endif +}; + +const size_t volume_func_count = ARRAY_SIZE(volume_func_map); +#endif +#endif diff --git a/src/audio/volume/volume_ipc3.c b/src/audio/volume/volume_ipc3.c new file mode 100644 index 000000000000..99a9a9c57ce1 --- /dev/null +++ b/src/audio/volume/volume_ipc3.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +#include <sof/audio/coefficients/volume/windows_fade.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/cpu.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> + +LOG_MODULE_DECLARE(volume, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +void set_volume_process(struct vol_data *cd, struct comp_dev *dev, bool source_or_sink) +{ + struct comp_buffer *bufferb; + + if (source_or_sink) + bufferb = comp_dev_get_first_data_producer(dev); + else + bufferb = comp_dev_get_first_data_consumer(dev); + + cd->scale_vol = vol_get_processing_function(dev, bufferb, cd); +} + +/** + * \brief Ramps volume changes over time. + * \param[in,out] mod Volume processing module handle + */ +static void volume_ramp_check(struct processing_module *mod) +{ + struct vol_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int i; + + /* No need to ramp in idle state, jump volume to request. */ + cd->ramp_finished = false; + if (dev->state == COMP_STATE_READY) { + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) + cd->volume[i] = cd->tvolume[i]; + + cd->ramp_finished = true; + } +} + +int volume_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *cfg = &md->cfg; + struct ipc_config_volume *vol = cfg->data; + struct vol_data *cd; + const size_t vol_size = sizeof(int32_t) * SOF_IPC_MAX_CHANNELS * 4; + int i; + + if (!vol || cfg->size != sizeof(*vol)) { + comp_err(dev, "No configuration data or bad data size %zu", + cfg->size); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(struct vol_data)); + if (!cd) + return -ENOMEM; + + /* + * malloc memory to store current volume 4 times to ensure the address + * is 8-byte aligned for multi-way xtensa intrinsic operations. + */ + cd->vol = mod_alloc_align(mod, vol_size, SOF_FRAME_BYTE_ALIGN); + if (!cd->vol) { + mod_free(mod, cd); + comp_err(dev, "Failed to allocate %zu", vol_size); + return -ENOMEM; + } + + md->private = cd; + cd->is_passthrough = false; + + /* Set the default volumes. If IPC sets min_value or max_value to + * not-zero, use them. Otherwise set to internal limits and notify + * ramp step calculation about assumed range with the range set to + * zero. + */ + if (vol->min_value || vol->max_value) { + if (vol->min_value < VOL_MIN) { + /* Use VOL_MIN instead, no need to stop new(). */ + cd->vol_min = VOL_MIN; + comp_err(dev, "vol->min_value was limited to VOL_MIN."); + } else { + cd->vol_min = vol->min_value; + } + + if (vol->max_value > VOL_MAX) { + /* Use VOL_MAX instead, no need to stop new(). */ + cd->vol_max = VOL_MAX; + comp_err(dev, "vol->max_value was limited to VOL_MAX."); + } else { + cd->vol_max = vol->max_value; + } + + cd->vol_ramp_range = vol->max_value - vol->min_value; + } else { + /* Legacy mode, set the limits to firmware capability where + * VOL_MAX is a very large gain to avoid restricting valid + * requests. The default ramp rate will be computed based + * on 0 - 1.0 gain range assumption when vol_ramp_range + * is set to 0. + */ + cd->vol_min = VOL_MIN; + cd->vol_max = VOL_MAX; + cd->vol_ramp_range = 0; + } + + for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) { + cd->volume[i] = MAX(MIN(cd->vol_max, VOL_ZERO_DB), + cd->vol_min); + cd->tvolume[i] = cd->volume[i]; + cd->mvolume[i] = cd->volume[i]; + cd->muted[i] = false; + } + + /* all target volume are same */ + cd->ramp_channel_counter = 1; + + switch (cd->ramp_type) { +#if CONFIG_COMP_VOLUME_LINEAR_RAMP + case SOF_VOLUME_LINEAR: + case SOF_VOLUME_LINEAR_ZC: +#endif +#if CONFIG_COMP_VOLUME_WINDOWS_FADE + case SOF_VOLUME_WINDOWS_FADE: +#endif + cd->ramp_type = vol->ramp; + cd->initial_ramp = vol->initial_ramp; + break; + default: + comp_err(dev, "invalid ramp type %d", vol->ramp); + mod_free(mod, cd); + mod_free(mod, cd->vol); + return -EINVAL; + } + + volume_reset_state(cd); + + return 0; +} + +void volume_peak_free(struct processing_module *mod) +{ +} + +int volume_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 sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct vol_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + uint32_t val; + uint32_t ch; + int j; + int ret = 0; + + comp_dbg(dev, "entry"); + + /* validate */ + if (cdata->num_elems == 0 || cdata->num_elems > SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "invalid cdata->num_elems"); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_VOLUME: + comp_dbg(dev, "SOF_CTRL_CMD_VOLUME, cdata->comp_id = %u", + cdata->comp_id); + for (j = 0; j < cdata->num_elems; j++) { + ch = cdata->chanv[j].channel; + val = cdata->chanv[j].value; + comp_dbg(dev, "channel = %d, value = %u", + ch, val); + + if (ch >= SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "illegal channel = %d", + ch); + return -EINVAL; + } + + if (cd->muted[ch]) { + cd->mvolume[ch] = val; + } else { + ret = volume_set_chan(mod, ch, val, true); + if (ret) + return ret; + } + } + volume_set_ramp_channel_counter(cd, cd->channels); + + volume_ramp_check(mod); + break; + + case SOF_CTRL_CMD_SWITCH: + comp_dbg(dev, "SOF_CTRL_CMD_SWITCH, cdata->comp_id = %u", + cdata->comp_id); + for (j = 0; j < cdata->num_elems; j++) { + ch = cdata->chanv[j].channel; + val = cdata->chanv[j].value; + comp_dbg(dev, "channel = %d, value = %u", + ch, val); + if (ch >= SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "illegal channel = %d", + ch); + return -EINVAL; + } + + if (val) + volume_set_chan_unmute(mod, ch); + else + volume_set_chan_mute(mod, ch); + } + + volume_ramp_check(mod); + break; + + default: + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } + + return 0; +} + +int volume_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + struct vol_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int j; + + comp_dbg(dev, "entry"); + + /* validate */ + if (cdata->num_elems == 0 || cdata->num_elems > SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "invalid cdata->num_elems %u", + cdata->num_elems); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_VOLUME: + for (j = 0; j < cdata->num_elems; j++) { + cdata->chanv[j].channel = j; + cdata->chanv[j].value = cd->tvolume[j]; + comp_dbg(dev, "channel = %u, value = %u", + cdata->chanv[j].channel, + cdata->chanv[j].value); + } + break; + case SOF_CTRL_CMD_SWITCH: + for (j = 0; j < cdata->num_elems; j++) { + cdata->chanv[j].channel = j; + cdata->chanv[j].value = !cd->muted[j]; + comp_dbg(dev, "channel = %u, value = %u", + cdata->chanv[j].channel, + cdata->chanv[j].value); + } + break; + default: + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } + + return 0; +} + +void volume_update_current_vol_ipc4(struct vol_data *cd) +{ +} + +int volume_peak_prepare(struct vol_data *cd, struct processing_module *mod) +{ + return 0; +} + diff --git a/src/audio/volume/volume_ipc4.c b/src/audio/volume/volume_ipc4.c new file mode 100644 index 000000000000..57a5f427903e --- /dev/null +++ b/src/audio/volume/volume_ipc4.c @@ -0,0 +1,461 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Baofeng Tian <baofeng.tian@intel.com> + +#include <sof/audio/coefficients/volume/windows_fade.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/lib/cpu.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <sof/trace/trace.h> +#include <sof/ut.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <user/trace.h> + +LOG_MODULE_DECLARE(volume, CONFIG_SOF_LOG_LEVEL); + +#include "volume.h" + +void set_volume_process(struct vol_data *cd, struct comp_dev *dev, bool source_or_sink) +{ + cd->scale_vol = vol_get_processing_function(dev, cd); +} + +static int set_volume_ipc4(struct vol_data *cd, uint32_t const channel, + uint32_t const target_volume, + uint32_t const curve_type, + uint64_t const curve_duration) +{ + /* update target volume in peak_regs */ + cd->peak_regs.target_volume[channel] = target_volume; + /* update peak meter in peak_regs */ + cd->peak_regs.peak_meter[channel] = 0; + cd->peak_cnt = 0; + + /* init target volume */ + cd->tvolume[channel] = target_volume; + /* init ramp start volume*/ + cd->rvolume[channel] = 0; + + /* ATM there is support for the same ramp for all channels */ + cd->ramp_type = ipc4_curve_type_convert((enum ipc4_curve_type)curve_type); + + return 0; +} + +/* In IPC4 driver sends volume in Q1.31 format. It is converted + * into Q1.23 format to be processed by firmware. + */ +static uint32_t convert_volume_ipc4_to_ipc3(struct comp_dev *dev, uint32_t volume) +{ +#if COMP_VOLUME_Q1_31 + return volume; +#else + return sat_int32(Q_SHIFT_RND((int64_t)volume, 31, VOL_QXY_Y)); +#endif +} + +static 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 + */ +#if COMP_VOLUME_Q1_31 + return volume; +#else + return sat_int32(Q_SHIFT_LEFT((int64_t)volume, VOL_QXY_Y, 31)); +#endif +} + +static void init_ramp(struct vol_data *cd, uint32_t curve_duration, uint32_t target_volume) +{ + cd->ramp_finished = false; + + /* In IPC4 driver sends curve_duration in hundred of ns - it should be + * converted into ms value required by firmware + */ + if (cd->ramp_type == SOF_VOLUME_WINDOWS_NO_FADE) { + cd->initial_ramp = 0; + cd->ramp_finished = true; + } else { + cd->initial_ramp = Q_MULTSR_32X32((int64_t)curve_duration, + Q_CONVERT_FLOAT(1.0 / 10000, 31), 0, 31, 0); + } + + cd->vol_min = VOL_MIN; + cd->vol_max = VOL_MAX; + cd->copy_gain = true; +} + +int volume_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct module_config *cfg = &md->cfg; + struct comp_dev *dev = mod->dev; + const struct ipc4_peak_volume_module_cfg *vol = cfg->init_data; + uint32_t target_volume[SOF_IPC_MAX_CHANNELS]; + struct vol_data *cd; + const size_t vol_size = sizeof(int32_t) * SOF_IPC_MAX_CHANNELS * 4; + uint32_t channels_count; + uint8_t channel_cfg; + uint8_t channel; + uint32_t instance_id = IPC4_INST_ID(dev_comp_id(dev)); + + if (instance_id >= IPC4_MAX_PEAK_VOL_REG_SLOTS) { + comp_err(dev, "instance_id %u out of array bounds.", instance_id); + return -EINVAL; + } + channels_count = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + if (channels_count > SOF_IPC_MAX_CHANNELS || !channels_count) { + comp_err(dev, "Invalid channels count %u", channels_count); + return -EINVAL; + } + + cd = mod_zalloc(mod, sizeof(struct vol_data)); + if (!cd) + return -ENOMEM; + + /* + * malloc memory to store current volume 4 times to ensure the address + * is 8-byte aligned for multi-way xtensa intrinsic operations. + */ + cd->vol = mod_alloc_align(mod, vol_size, SOF_FRAME_BYTE_ALIGN); + if (!cd->vol) { + mod_free(mod, cd); + comp_err(dev, "Failed to allocate %d", vol_size); + return -ENOMEM; + } + + /* malloc memory to store temp peak volume 4 times to ensure the address + * is 8-byte aligned for multi-way xtensa intrinsic operations. + */ + cd->peak_vol = mod_zalloc(mod, vol_size); + if (!cd->peak_vol) { + mod_free(mod, cd->vol); + mod_free(mod, cd); + comp_err(dev, "Failed to allocate %d for peak_vol", vol_size); + return -ENOMEM; + } + + md->private = cd; + + for (channel = 0; channel < channels_count; channel++) { + if (vol->config[0].channel_id == IPC4_ALL_CHANNELS_MASK) + channel_cfg = 0; + else + channel_cfg = channel; + + target_volume[channel] = + convert_volume_ipc4_to_ipc3(dev, vol->config[channel].target_volume); + + set_volume_ipc4(cd, channel, + target_volume[channel_cfg], + vol->config[channel_cfg].curve_type, + vol->config[channel_cfg].curve_duration); + + /* set muted as false*/ + cd->muted[channel] = false; + } + + init_ramp(cd, vol->config[0].curve_duration, target_volume[0]); + + volume_set_ramp_channel_counter(cd, channels_count); + + cd->mailbox_offset = offsetof(struct ipc4_fw_registers, peak_vol_regs); + cd->mailbox_offset += instance_id * sizeof(struct ipc4_peak_volume_regs); + + cd->attenuation = 0; + cd->is_passthrough = false; + + volume_reset_state(cd); + + return 0; +} + +void volume_peak_free(struct processing_module *mod) +{ + struct vol_data *cd = module_get_private_data(mod); + struct ipc4_peak_volume_regs regs; + + /* clear mailbox */ + memset_s(®s, sizeof(regs), 0, sizeof(regs)); + mailbox_sw_regs_write(cd->mailbox_offset, ®s, sizeof(regs)); + mod_free(mod, cd->peak_vol); +} + +static int volume_set_volume(struct processing_module *mod, const uint8_t *data, int data_size) +{ + struct vol_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct ipc4_peak_volume_config cdata; + uint32_t i, channels_count; + + if (data_size < sizeof(cdata)) { + comp_err(dev, "error: data_size %d should be bigger than %d", data_size, + sizeof(cdata)); + return -EINVAL; + } + + cdata = *(const struct ipc4_peak_volume_config *)data; + cdata.target_volume = convert_volume_ipc4_to_ipc3(dev, cdata.target_volume); + + if (cdata.channel_id != IPC4_ALL_CHANNELS_MASK && + cdata.channel_id >= SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "Invalid channel_id %u", cdata.channel_id); + return -EINVAL; + } + + channels_count = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + if (channels_count > SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "Invalid channels count %u", channels_count); + return -EINVAL; + } + + if (cdata.channel_id == IPC4_ALL_CHANNELS_MASK) { + for (i = 0; i < channels_count; i++) { + if (cd->muted[i]) { + cd->mvolume[i] = cdata.target_volume; + } else { + set_volume_ipc4(cd, i, cdata.target_volume, + cdata.curve_type, + cdata.curve_duration); + init_ramp(cd, cdata.curve_duration, cdata.target_volume); + volume_set_chan(mod, i, cd->tvolume[i], true); + } + } + } else { + if (cd->muted[cdata.channel_id]) { + cd->mvolume[cdata.channel_id] = cdata.target_volume; + } else { + set_volume_ipc4(cd, cdata.channel_id, + cdata.target_volume, + cdata.curve_type, + cdata.curve_duration); + init_ramp(cd, cdata.curve_duration, cdata.target_volume); + volume_set_chan(mod, cdata.channel_id, + cd->tvolume[cdata.channel_id], true); + } + } + + cd->is_passthrough = false; + volume_set_ramp_channel_counter(cd, channels_count); + cd->scale_vol = vol_get_processing_function(dev, cd); + volume_prepare_ramp(dev, cd); + return 0; +} + +static int volume_set_attenuation(struct processing_module *mod, const uint8_t *data, + 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; + + /* only support attenuation in format of 32bit */ + if (data_size > sizeof(uint32_t)) { + comp_err(dev, "attenuation data size %d is incorrect", data_size); + return -EINVAL; + } + + attenuation = *(const uint32_t *)data; + if (attenuation > 31) { + comp_err(dev, "attenuation %d is out of range", attenuation); + return -EINVAL; + } + + 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); + + if (frame_fmt < SOF_IPC_FRAME_S24_4LE) { + comp_err(dev, "frame_fmt %d isn't supported by attenuation", + frame_fmt); + return -EINVAL; + } + + cd->attenuation = attenuation; + + return 0; +} + +static int volume_set_switch(struct processing_module *mod, const uint8_t *data, + int data_size) +{ + struct vol_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct sof_ipc4_control_msg_payload *ctl; + unsigned int channels_count, num_elems; + unsigned int i, val; + + if (data_size < sizeof(struct sof_ipc4_control_msg_payload)) { + comp_err(dev, "error: data_size %d should be bigger than %d", data_size, + sizeof(struct sof_ipc4_control_msg_payload)); + return -EINVAL; + } + + ctl = (struct sof_ipc4_control_msg_payload *)data; + + channels_count = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + if (channels_count > SOF_IPC_MAX_CHANNELS) { + comp_err(dev, "Invalid channels count %u", channels_count); + return -EINVAL; + } + + num_elems = ctl->num_elems; + if (num_elems > channels_count) { + comp_warn(dev, "limit num_elems %d to %d", num_elems, channels_count); + num_elems = channels_count; + } + + for (i = 0; i < num_elems; i++) { + val = ctl->chanv[i].value; + comp_dbg(dev, "channel %i, value %u", i, val); + + if (val) + volume_set_chan_unmute(mod, i); + else + volume_set_chan_mute(mod, i); + } + + cd->ramp_finished = false; + cd->is_passthrough = false; + volume_set_ramp_channel_counter(cd, channels_count); + cd->scale_vol = vol_get_processing_function(dev, cd); + volume_prepare_ramp(dev, cd); + return 0; +} + +int volume_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; + int ret; + + comp_dbg(dev, "entry"); + + ret = module_set_configuration(mod, config_id, pos, data_offset_size, fragment, + fragment_size, response, response_size); + if (ret < 0) + return ret; + + /* return if more fragments are expected or if the module is not prepared */ + if (pos != MODULE_CFG_FRAGMENT_LAST && pos != MODULE_CFG_FRAGMENT_SINGLE) + return 0; + + switch (config_id) { + case IPC4_VOLUME: + return volume_set_volume(mod, fragment, fragment_size); + case IPC4_SET_ATTENUATION: + return volume_set_attenuation(mod, fragment, fragment_size); + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + return volume_set_switch(mod, fragment, fragment_size); + default: + comp_err(dev, "unsupported param %d", config_id); + return -EINVAL; + } + + return 0; +} + +int volume_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct vol_data *cd = module_get_private_data(mod); + struct ipc4_peak_volume_config *cdata; + int i; + + comp_dbg(mod->dev, "volume_get_large_config()"); + + cdata = (struct ipc4_peak_volume_config *)ASSUME_ALIGNED(fragment, 8); + + switch (config_id) { + case IPC4_VOLUME: + for (i = 0; i < cd->channels; i++) { + uint32_t volume = cd->peak_regs.target_volume[i]; + + cdata[i].channel_id = i; + cdata[i].target_volume = convert_volume_ipc3_to_ipc4(volume); + } + *data_offset_size = sizeof(*cdata) * cd->channels; + break; + default: + comp_err(mod->dev, "unsupported param %d", config_id); + return -EINVAL; + } + + return 0; +} + +static int volume_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_buffer *sinkb, *sourceb; + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "entry"); + + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + + component_set_nearest_period_frames(dev, params->rate); + + /* + * volume component will only ever have 1 sink buffer, the caller has + * verified their validity + */ + sinkb = comp_dev_get_first_data_consumer(dev); + ipc4_update_buffer_format(sinkb, &mod->priv.cfg.base_cfg.audio_fmt); + + sourceb = comp_dev_get_first_data_producer(dev); + ipc4_update_buffer_format(sourceb, &mod->priv.cfg.base_cfg.audio_fmt); + + return 0; +} + +void volume_update_current_vol_ipc4(struct vol_data *cd) +{ + int i; + + assert(cd); + + for (i = 0; i < cd->channels; i++) + cd->peak_regs.current_volume[i] = cd->volume[i]; +} + +int volume_peak_prepare(struct vol_data *cd, struct processing_module *mod) +{ + int ret; + + cd->peak_cnt = 0; +#if CONFIG_COMP_PEAK_VOL + cd->peak_report_cnt = CONFIG_PEAK_METER_UPDATE_PERIOD * 1000 / mod->dev->period; + if (cd->peak_report_cnt == 0) + cd->peak_report_cnt = 1; +#endif + ret = volume_params(mod); + if (ret < 0) + return ret; + + return 0; +} + diff --git a/src/audio/volume/volume_uuid.h b/src/audio/volume/volume_uuid.h new file mode 100644 index 000000000000..d68b0ab5b4cd --- /dev/null +++ b/src/audio/volume/volume_uuid.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian <baofeng.tian@intel.com> + */ + +#ifndef __SOF_AUDIO_VOLUME_UUID_H__ +#define __SOF_AUDIO_VOLUME_UUID_H__ + +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +#if CONFIG_IPC_MAJOR_3 +SOF_DEFINE_REG_UUID(volume); +#else +/* these ids aligns windows driver requirement to support windows driver */ +SOF_DEFINE_REG_UUID(volume4); +#define volume_uuid volume4_uuid + +SOF_DEFINE_REG_UUID(gain); + +DECLARE_TR_CTX(gain_tr, SOF_UUID(gain_uuid), LOG_LEVEL_INFO); +#endif + +DECLARE_TR_CTX(volume_tr, SOF_UUID(volume_uuid), LOG_LEVEL_INFO); + +#endif /* __SOF_AUDIO_VOLUME_UUID_H__ */ diff --git a/src/debug/CMakeLists.txt b/src/debug/CMakeLists.txt index 394895f58c9e..5cb8e8bd9c6c 100644 --- a/src/debug/CMakeLists.txt +++ b/src/debug/CMakeLists.txt @@ -4,4 +4,14 @@ if(CONFIG_GDB_DEBUG) add_subdirectory(gdb) endif() -add_local_sources(sof panic.c) +add_subdirectory(tester) + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + +add_subdirectory(debug_stream) +add_subdirectory(telemetry) + +zephyr_library_sources_ifdef(CONFIG_COLD_STORE_EXECUTE_DEBUG dram.c) + +endif() # Zephyr diff --git a/src/debug/debug_stream/CMakeLists.txt b/src/debug/debug_stream/CMakeLists.txt new file mode 100644 index 000000000000..36de0d24a46d --- /dev/null +++ b/src/debug/debug_stream/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources_ifdef(CONFIG_SOF_DEBUG_STREAM_SLOT sof debug_stream_slot.c) + +add_local_sources_ifdef(CONFIG_SOF_DEBUG_STREAM_THREAD_INFO sof debug_stream_thread_info.c) + +add_local_sources_ifdef(CONFIG_SOF_DEBUG_STREAM_TEXT_MSG sof debug_stream_text_msg.c) diff --git a/src/debug/debug_stream/Kconfig b/src/debug/debug_stream/Kconfig new file mode 100644 index 000000000000..6ac6280c611c --- /dev/null +++ b/src/debug/debug_stream/Kconfig @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config SOF_DEBUG_STREAM_SLOT + bool "Enable SOF debug stream debug window slot" + help + Debug stream is an abstract stream of records of debug + information from SOF system that are streamed from SOF DSP + to the host side for decoding and presentation. This option + enables transferring the records from DSP to host over a + debug window slot. To extract the debugstream see + tools/debug_stream/debug_stream.py. + +if SOF_DEBUG_STREAM_SLOT + +config SOF_DEBUG_STREAM_SLOT_NUMBER + int "Debug window slot where to put debug stream slot" + default 3 + range 0 14 + help + Which debug slot to reserve for Debug Stream. Remember to map + the slot with MEMORY_WIN_2_SIZE in soc/intel/intel_adsp/Kconfig, + in Zephyr source tree. The slots are 4k in size and one slot is + used for descriptors, so for slot 3 to be mapped, the WIN_2_SIZE + must be (1 + 3) * 4k = 16k or greater. + +config SOF_DEBUG_STREAM_THREAD_INFO + bool "Enable Zephyr thread info reporting through Debug-Stream" + select INIT_STACKS + select THREAD_MONITOR + select THREAD_STACK_INFO + select THREAD_RUNTIME_STATS + help + This activates Zephyr thread info reporting through + Debug-Stream. Thread info reports some basic live data from + the Zephyr threads, like stack usage high-water-mark and CPU + usage. Please select THREAD_NAME=y for the thread names more + than just hex numbers. + +config SOF_DEBUG_STREAM_THREAD_INFO_INTERVAL + int "Thread information collection interval in seconds" + depends on SOF_DEBUG_STREAM_THREAD_INFO + default 2 + range 1 10 + help + Decides how often thread info runs and checks execution cycle + statistics and stack usage. + +config SOF_DEBUG_STREAM_THREAD_INFO_TOTAL_CPU_LOAD_TO_LOG + bool "Print summarized total CPU load to log subsystem" + depends on SOF_DEBUG_STREAM_THREAD_INFO + default y + help + In addition to printing thread statistics to debug stream, + print the total CPU load (sum of all threads) to + the logging system. + +config SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS + int "Number of cpu sections slot is divided to" + default CORE_COUNT + range 1 MP_MAX_NUM_CPUS + help + In some situations a high number of cpu sections shrinks the + circular buffer size so much that it limit debugging. With + this option its possible to use fewer sections. The downside + is that the cpus above the number of sections can not send + any debug stream messages. + +config SOF_DEBUG_STREAM_TEXT_MSG + bool "Enable text message sending through Debug-Stream" + help + Enable debug message sending over debug stream. To use this + feature one only needs to enable debug stream with this + config option and print the debug messages with + ds_msg(). See include/user/debug_stream_text_msg.h for + prototype. + +config SOF_DEBUG_STREAM_TEXT_MSG_ASSERT_PRINT + bool "Enable assert print sending through Debug-Stream" + depends on EXCEPTION_DUMP_HOOK && (ASSERT || ASSERT_VERBOSE) + select SOF_DEBUG_STREAM_TEXT_MSG + help + Enable assert print sending over debug stream as text + message. This feature is also sensitive to Zephyr option + CONFIG_EXCEPTION_DUMP_HOOK_ONLY. If that is set then the + asserts are not printed through printk interface. + +endif diff --git a/src/debug/debug_stream/README.md b/src/debug/debug_stream/README.md new file mode 100644 index 000000000000..592edef8a719 --- /dev/null +++ b/src/debug/debug_stream/README.md @@ -0,0 +1,61 @@ +# SOF Debug Stream + +The `debug_stream` framework is an abstract logging and live-data streaming mechanism allowing the DSP to asynchronously push structured or freeform diagnostic records immediately out to the host. + +## Feature Overview + +Unlike standard tracing (`mtrace`), which requires buffering and complex host parsing logic often tied directly to pipeline topologies or ALSA interfaces, the `debug_stream` bypasses the audio framework entirely. It utilizes the dedicated IPC Memory Windows (specifically the debug slot) to write data. + +The stream is particularly useful for reporting: + +1. **Thread Information:** Real-time data from Zephyr OS threads (like CPU runtime, context switch frequencies, or stack high-water marks). +2. **Text Messages (`ds_msg`):** Lightweight string prints that bypass the standard heavily-formatted logger. + +## How to Enable + +These features are disabled by default to save firmware footprint. You can enable them via Kconfig: + +* `CONFIG_SOF_DEBUG_STREAM_SLOT=y` : Master switch. Reserves exactly one Memory Window 4k block (default Slot 3) mapping to host space. +* `CONFIG_SOF_DEBUG_STREAM_THREAD_INFO=y` : Activates the Zephyr thread statistics compiler integration (`INIT_STACKS`, `THREAD_MONITOR`). +* `CONFIG_SOF_DEBUG_STREAM_TEXT_MSG=y` : Allows calling `ds_msg("...", ...)` scattered throughout DSP C code to emit plain strings. + +## Architecture + +The architecture revolves around a "Slot" abstraction where data is copied sequentially over a ringbuffer into the ADSP debug window slot used for the debug stream (mapped over PCIe/SPI for the Host to read non-destructively). + +```mermaid +graph TD + subgraph SOF Firmware + SysEvent["System Event / OS Timer"] --> |Triggers| DSThread["Thread Info Collector"] + DevCode["Developer Code"] --> |"ds_msg()"| Text["Text Subsystem"] + + DSThread --> Formatter[DS Formatter] + Text --> Formatter + + Formatter --> Slot[Memory Window Slot 3] + end + + subgraph Host System + PyTool[tools/debug_stream/debug_stream.py] + Slot -.->|PCIe DMA / IPC Memory| PyTool + PyTool --> |Stdout| User[Developer Terminal] + end +``` + +## Usage Example + +If you enable `CONFIG_SOF_DEBUG_STREAM_TEXT_MSG=y`, developers can insert rapid debug markers without setting up topology traces: + +```c +#include <user/debug_stream_text_msg.h> + +void my_function() { + ds_msg("Reached tricky initialization state! Value: %d", some_val); +} +``` + +On the host machine, you extract this continuous output stream by running the provided SOF tooling: + +```bash +python3 tools/debug_stream/debug_stream.py +``` diff --git a/src/debug/debug_stream/debug_stream_slot.c b/src/debug/debug_stream/debug_stream_slot.c new file mode 100644 index 000000000000..82816a6788f3 --- /dev/null +++ b/src/debug/debug_stream/debug_stream_slot.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. + +#include <zephyr/logging/log.h> +#include <zephyr/spinlock.h> +#include <adsp_debug_window.h> +#include <adsp_memory.h> +#include <sof/common.h> +#include <rtos/string.h> +#include <user/debug_stream.h> +#include <user/debug_stream_slot.h> +#include <zephyr/kernel.h> + +LOG_MODULE_REGISTER(debug_stream_slot); + +struct cpu_mutex { + struct k_spinlock l; +} __aligned(CONFIG_DCACHE_LINE_SIZE); + +/* CPU specific mutexes for each circular buffer */ +static struct cpu_mutex cpu_mutex[CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS]; + +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +static struct debug_stream_slot_hdr *dbg_stream_slot; +#else +static const int debug_stream_slot = CONFIG_SOF_DEBUG_STREAM_SLOT_NUMBER; +#endif + +static struct debug_stream_slot_hdr *debug_stream_get_slot(void) +{ +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + if (!dbg_stream_slot) { + struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_DEBUG_STREAM, }; + + dbg_stream_slot = (struct debug_stream_slot_hdr *) + adsp_dw_request_slot(&slot_desc, NULL); + } + + return dbg_stream_slot; +#else + return (struct debug_stream_slot_hdr *)ADSP_DW->slots[debug_stream_slot]; +#endif +} + +static +struct debug_stream_circular_buf * +debug_stream_get_circular_buffer(struct debug_stream_section_descriptor *desc, unsigned int core) +{ + struct debug_stream_slot_hdr *hdr = debug_stream_get_slot(); + + if (hdr->hdr.magic != DEBUG_STREAM_IDENTIFIER) { + LOG_ERR("Debug stream slot not initialized."); + return NULL; + } + + if (core >= CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS) { + LOG_DBG("No section for cpu %u >= %u ", core, + CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS); + return NULL; + } + + *desc = hdr->section_desc[core]; + LOG_DBG("Section %u (desc %u %u %u)", core, desc->core_id, desc->buf_words, desc->offset); + + return (struct debug_stream_circular_buf *) (((uint8_t *)hdr) + desc->offset); +} + +int debug_stream_slot_send_record(struct debug_stream_record *rec) +{ + struct debug_stream_section_descriptor desc = { 0 }; + struct debug_stream_circular_buf *buf = + debug_stream_get_circular_buffer(&desc, arch_proc_id()); + uint32_t record_size = rec->size_words; + uint32_t record_start, buf_remain; + k_spinlock_key_t key; + + LOG_DBG("Sending record %u id %u len %u", rec->seqno, rec->id, rec->size_words); + + if (!buf) + return -ENODEV; + + if (rec->size_words >= desc.buf_words) { + LOG_ERR("Record too big %u >= %u (desc %u %u %u)", rec->size_words, + desc.buf_words, desc.core_id, desc.buf_words, desc.offset); + return -ENOMEM; + } + key = k_spin_lock(&cpu_mutex[arch_proc_id()].l); + + rec->seqno = buf->next_seqno++; + rec->size_words = record_size + 1; /* +1 for size at the end of record */ + record_start = buf->w_ptr; + buf->w_ptr = (record_start + record_size) % desc.buf_words; + buf_remain = desc.buf_words - record_start; + if (buf_remain < record_size) { + uint32_t rec_remain = record_size - buf_remain; + int ret; + + ret = memcpy_s(&buf->data[record_start], buf_remain * sizeof(uint32_t), + rec, buf_remain * sizeof(uint32_t)); + assert(!ret); + ret = memcpy_s(&buf->data[0], desc.buf_words * sizeof(uint32_t), + ((uint32_t *) rec) + buf_remain, rec_remain * sizeof(uint32_t)); + assert(!ret); + } else { + int ret; + + ret = memcpy_s(&buf->data[record_start], buf_remain * sizeof(uint32_t), + rec, record_size * sizeof(uint32_t)); + assert(!ret); + } + /* Write record size again after the record */ + buf->data[buf->w_ptr] = record_size + 1; + buf->w_ptr = (buf->w_ptr + 1) % desc.buf_words; + + k_spin_unlock(&cpu_mutex[arch_proc_id()].l, key); + + LOG_DBG("Record %u id %u len %u sent", rec->seqno, rec->id, record_size); + return 0; +} + +static int debug_stream_slot_init(void) +{ + struct debug_stream_slot_hdr *hdr = debug_stream_get_slot(); + size_t hdr_size = ALIGN_UP( + offsetof(struct debug_stream_slot_hdr, + section_desc[CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS]), + CONFIG_DCACHE_LINE_SIZE); + size_t section_area_size = ADSP_DW_SLOT_SIZE - hdr_size; + size_t section_size = ALIGN_DOWN(section_area_size / + CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS, + CONFIG_DCACHE_LINE_SIZE); + size_t offset = hdr_size; + int i; + + LOG_INF("%u sections of %u bytes, hdr %u, section area %u", + CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS, section_size, hdr_size, + section_area_size); + +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + if (!hdr) + return -ENOMEM; +#else + if (ADSP_DW->descs[debug_stream_slot].type != 0) + LOG_WRN("Slot %d was not free: %u", debug_stream_slot, + ADSP_DW->descs[debug_stream_slot].type); + ADSP_DW->descs[debug_stream_slot].type = ADSP_DW_SLOT_DEBUG_STREAM; +#endif + + hdr->hdr.magic = DEBUG_STREAM_IDENTIFIER; + hdr->hdr.hdr_size = hdr_size; + hdr->total_size = hdr_size + CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS * section_size; + hdr->num_sections = CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS; + for (i = 0; i < CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS; i++) { + hdr->section_desc[i].core_id = i; + hdr->section_desc[i].buf_words = + (section_size - offsetof(struct debug_stream_circular_buf, data[0])) / + sizeof(uint32_t); + hdr->section_desc[i].offset = offset; + LOG_DBG("sections %u, size %u, offset %u", i, section_size, offset); + offset += section_size; + } + for (i = 0; i < CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS; i++) { + struct debug_stream_section_descriptor desc = { 0 }; + struct debug_stream_circular_buf *buf = debug_stream_get_circular_buffer(&desc, i); + + buf->next_seqno = 0; + buf->w_ptr = 0; + } + LOG_DBG("Debug stream slot initialized"); + + return 0; +} + +SYS_INIT(debug_stream_slot_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/src/debug/debug_stream/debug_stream_text_msg.c b/src/debug/debug_stream/debug_stream_text_msg.c new file mode 100644 index 000000000000..97db0fd29330 --- /dev/null +++ b/src/debug/debug_stream/debug_stream_text_msg.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. + +#include <sys/types.h> +#include <stdarg.h> +#include <stdio.h> +#include <soc.h> +#include <adsp_debug_window.h> +#include <sof/common.h> +#include <zephyr/logging/log.h> +#include <zephyr/arch/exception.h> + +#include <user/debug_stream_text_msg.h> + +LOG_MODULE_REGISTER(debug_stream_text_msg); + +void ds_vamsg(const char *format, va_list args) +{ + struct { + struct debug_stream_text_msg msg; + char text[128]; + } __packed buf = { 0 }; + ssize_t len; + + len = vsnprintf(buf.text, sizeof(buf.text), format, args); + + if (len < 0) + return; + len = MIN(len, sizeof(buf.text)); + + buf.msg.hdr.id = DEBUG_STREAM_RECORD_ID_TEXT_MSG; + buf.msg.hdr.size_words = SOF_DIV_ROUND_UP(sizeof(buf.msg) + len, + sizeof(buf.msg.hdr.data[0])); + debug_stream_slot_send_record(&buf.msg.hdr); +} + +void ds_msg(const char *format, ...) +{ + va_list args; + + va_start(args, format); + ds_vamsg(format, args); + va_end(args); +} + +#if defined(CONFIG_EXCEPTION_DUMP_HOOK) +/* The debug stream debug window slot is 4k, and when it is split + * between the cores and the header/other overhead is removed, with 5 + * cores the size is 768 bytes. The dump record must be smaller than + * that to get through to the host side. + * + * Also, because of the limited circular buffer size, we should only + * send one exception record. On some situations the exceptions happen + * in bursts, and sending more than one record in short time makes the + * host-side decoder lose track of things. + */ + +/* Per-CPU state for exception dump and assert_print(). Static data is + * currently placed in .bss and its ATM uncached so the ds_cpu table + * elements do not need to be cache aligned, but if this changes we + * need __aligned(CONFIG_DCACHE_LINE_SIZE) here. + */ +static struct ds_cpu_state { + struct { + struct debug_stream_text_msg msg; + char text[640]; + } __packed buf; + int reports_sent; + size_t pos; +} ds_cpu[CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS]; + +static void ds_exception_drain(bool flush) +{ + unsigned int cpu = arch_proc_id(); + struct ds_cpu_state *cs = &ds_cpu[cpu]; + + if (flush) { + cs->pos = 0; + return; + } + + if (cs->pos == 0) + return; + + if (cs->reports_sent > 0) + return; + + cs->buf.msg.hdr.id = DEBUG_STREAM_RECORD_ID_TEXT_MSG; + cs->buf.msg.hdr.size_words = + SOF_DIV_ROUND_UP(sizeof(cs->buf.msg) + cs->pos, + sizeof(cs->buf.msg.hdr.data[0])); + + /* Make sure the possible up to 3 extra bytes at end of msg are '\0' */ + memset(cs->buf.text + cs->pos, 0, + cs->buf.msg.hdr.size_words * sizeof(cs->buf.msg.hdr.data[0]) - cs->pos); + debug_stream_slot_send_record(&cs->buf.msg.hdr); + cs->reports_sent = 1; + cs->pos = 0; +} + +static void ds_exception_dump(const char *format, va_list args) +{ + ssize_t len; + size_t avail; + size_t written; + unsigned int cpu = arch_proc_id(); + struct ds_cpu_state *cs = &ds_cpu[cpu]; + + if (cs->reports_sent > 0) + return; + + avail = sizeof(cs->buf.text) - cs->pos; + if (avail == 0) { + ds_exception_drain(false); + return; + } + + if (format[0] == '\0') + return; + + /* Skip useless " ** " prefix to save bytes */ + if (strlen(format) >= 4 && + format[0] == ' ' && format[1] == '*' && format[2] == '*' && format[3] == ' ') + format += 4; + + len = vsnprintf(cs->buf.text + cs->pos, avail, format, args); + if (len < 0) { + cs->pos = 0; + return; + } + + if (len == 0) + return; + + if ((size_t)len >= avail) + written = avail - 1; + else + written = (size_t)len; + + cs->pos += written; + + if (cs->pos >= sizeof(cs->buf.text)) + ds_exception_drain(false); +} + +static int init_exception_dump_hook(void) +{ + arch_exception_set_dump_hook(ds_exception_dump, ds_exception_drain); + LOG_DBG("exception_dump_hook set"); + return 0; +} + +SYS_INIT(init_exception_dump_hook, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +#if defined(CONFIG_SOF_DEBUG_STREAM_TEXT_MSG_ASSERT_PRINT) +void assert_print(const char *fmt, ...) +{ + va_list ap; + + /* Do not print assert after exception has been dumped */ + if (ds_cpu[arch_proc_id()].reports_sent > 0) + return; + + va_start(ap, fmt); +#if !defined(CONFIG_EXCEPTION_DUMP_HOOK_ONLY) + { + va_list ap2; + + va_copy(ap2, ap); +#endif + ds_vamsg(fmt, ap); +#if !defined(CONFIG_EXCEPTION_DUMP_HOOK_ONLY) + vprintk(fmt, ap2); + va_end(ap2); + } +#endif + ds_vamsg(fmt, ap); + va_end(ap); +} +EXPORT_SYMBOL(assert_print); +#endif +#endif diff --git a/src/debug/debug_stream/debug_stream_thread_info.c b/src/debug/debug_stream/debug_stream_thread_info.c new file mode 100644 index 000000000000..5c0d1bd7ffb1 --- /dev/null +++ b/src/debug/debug_stream/debug_stream_thread_info.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. + +#include <zephyr/logging/log.h> +#include <zephyr/kernel.h> +#include <rtos/alloc.h> +#include <ipc/topology.h> +#include <stdio.h> +#include <soc.h> +#include <adsp_debug_window.h> + +#include <user/debug_stream_thread_info.h> + +LOG_MODULE_REGISTER(thread_info); + +#define THREAD_INFO_MAX_THREADS 64 +/* Must be bigger than sizeof(struct thread_info_record_hdr) */ +#define THREAD_INFO_INITIAL_RECORD_BUFFER_SIZE 256 + +#ifdef CONFIG_THREAD_RUNTIME_STATS +/* Data structure to store the cycle counter values from the previous + * round. The numbers are used to calculate what the load was on this + * round. + * Static data is currently placed in .bss and its ATM uncached so the + * ds_cpu table elements do not need to be cache aligned, but if this + * changes we need __aligned(CONFIG_DCACHE_LINE_SIZE) here. + */ +static struct previous_counters { /* Cached data from previous round */ + uint64_t active; /* All execution cycles */ + uint64_t all; /* All cycles including idle */ + struct thread_counters { + void *tid; /* thread ID (the thread struct ptr) */ + uint64_t cycles; /* cycle counter value */ + } threads[THREAD_INFO_MAX_THREADS]; /* The max amount of threads we follow */ +} previous[CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS]; +#endif + +/* + * Buffer structure for building the Debug Stream record before + * sending it forward. The buffer is persistent and each record is + * build in the same buffer. Its reallocated as double size if it + * becomes too small. + */ +struct record_buf { + size_t size; + size_t w_ptr; + uint8_t *buf; +}; + +/* + * Data structure to be passed down to thread_info_cb() by + * k_thread_foreach_current_cpu(). + */ +struct user_data { + int core; + struct record_buf *bufd; + int thread_count; +#ifdef CONFIG_THREAD_RUNTIME_STATS + bool stats_valid; + uint32_t all_cycles; + void *active_threads[THREAD_INFO_MAX_THREADS]; + struct previous_counters *previous; +#endif +}; + +#ifdef CONFIG_THREAD_RUNTIME_STATS + +/* Finds and/or updates cached cycle counter value for 'tid'-thread + * and calculates used execution cycles since previous round and + * returns it. The tid is actually a k_tread pointer, but since its + * used just as an id and never accessed, I pass it as a void pointer. + */ + +static uint32_t thread_info_get_cycles(void *tid, k_thread_runtime_stats_t *thread_stats, + struct user_data *ud, const char *name) + +{ + int i; + + if (ud->thread_count >= ARRAY_SIZE(ud->active_threads)) { + LOG_WRN("Thread count exceeds the max threads %u >= %u", + ud->thread_count, ARRAY_SIZE(ud->active_threads)); + return 0; + } + + /* Mark the thread as active */ + ud->active_threads[ud->thread_count] = tid; + /* look for cached value from previous round for 'tid'-thread */ + for (i = 0; i < ARRAY_SIZE(ud->previous->threads); i++) { + if (ud->previous->threads[i].tid == tid) { + /* Calculate number cycles since previous round */ + uint32_t cycles = (uint32_t) (thread_stats->execution_cycles - + ud->previous->threads[i].cycles); + + LOG_DBG("%p found at %d (%s %llu)", tid, i, + name, thread_stats->execution_cycles); + /* update cached value */ + ud->previous->threads[i].cycles = thread_stats->execution_cycles; + return cycles; + } + } + + /* If no cached value was found, look for an empty slot to store the recent value */ + for (i = 0; i < ARRAY_SIZE(ud->previous->threads); i++) { + if (ud->previous->threads[i].tid == NULL) { + ud->previous->threads[i].tid = tid; + ud->previous->threads[i].cycles = thread_stats->execution_cycles; + LOG_DBG("%p placed at %d (%s %llu)", tid, i, + name, ud->previous->threads[i].cycles); + break; + } + } + + /* If there is more than THREAD_INFO_MAX_THREADS threads in this core */ + if (i == ARRAY_SIZE(ud->previous->threads)) + LOG_WRN("No place found for %s %p", name, tid); + + /* If there was no previous counter value to compare, return 0 cycles. */ + return 0; +} + +static uint8_t thread_info_cpu_utilization(struct k_thread *thread, + struct user_data *ud, const char *name) +{ + k_thread_runtime_stats_t thread_stats; + uint32_t cycles; + + if (!ud->stats_valid) + return 0; + + if (k_thread_runtime_stats_get(thread, &thread_stats) != 0) + return 0; + + cycles = thread_info_get_cycles(thread, &thread_stats, ud, name); + + LOG_DBG("thread %s %u / %u", name, cycles, ud->all_cycles); + + return (uint8_t) ((255llu * cycles) / ud->all_cycles); +} +#else +static uint8_t thread_info_cpu_utilization(struct k_thread *thread, + struct user_data *ud, const char *name) +{ + return 0; +} +#endif + +#ifdef CONFIG_THREAD_STACK_INFO +static uint8_t thread_info_stack_level(struct k_thread *thread, const char *name) +{ + size_t stack_size, stack_unused; + int ret; + + stack_size = thread->stack_info.size; + ret = k_thread_stack_space_get(thread, &stack_unused); + if (ret) { + LOG_ERR(" %-20s: unable to get stack space (%d)", + name, ret); + stack_unused = 0; + } + return (UINT8_MAX * (stack_size - stack_unused)) / stack_size; +} +#else +static uint8_t thread_info_stack_level(struct k_thread *thread, const char *name) +{ + return 0; +} +#endif + +static int thread_info_buf_realloc(struct record_buf *bufd, size_t req_size) +{ + size_t size = bufd->size; + + while (size < bufd->w_ptr + req_size) + size *= 2; + + if (size != bufd->size) { + uint8_t *buf = rmalloc(SOF_MEM_FLAG_USER, size); + + if (!buf) + return -ENOMEM; + + memcpy_s(buf, size, bufd->buf, bufd->w_ptr); + rfree(bufd->buf); + bufd->size = size; + bufd->buf = buf; + } + + return 0; +} + +static void thread_info_cb(const struct k_thread *cthread, void *user_data) +{ + struct k_thread *thread = (struct k_thread *)cthread; + struct user_data *ud = user_data; + struct thread_info *tinfo; + const char *name; + + name = k_thread_name_get((k_tid_t)thread); + if (!name || name[0] == '\0') { + size_t ptr_str_len = 11; /* length of "0x12345678\0" */ + + if (thread_info_buf_realloc(ud->bufd, sizeof(*tinfo) + ptr_str_len)) + return; + + tinfo = (struct thread_info *) &ud->bufd->buf[ud->bufd->w_ptr]; + snprintk(tinfo->name, ptr_str_len, "%p", (void *)thread); + /* Drop the terminating '\0', that is why -1 is here. */ + tinfo->name_len = ptr_str_len - 1; + ud->bufd->w_ptr += sizeof(*tinfo) + ptr_str_len - 1; + } else { + size_t len = strlen(name); + + if (thread_info_buf_realloc(ud->bufd, sizeof(*tinfo) + len + 1)) + return; + + tinfo = (struct thread_info *) &ud->bufd->buf[ud->bufd->w_ptr]; + strncpy(tinfo->name, name, len + 1); + tinfo->name_len = len; + ud->bufd->w_ptr += sizeof(*tinfo) + len; + } + + tinfo->stack_usage = thread_info_stack_level(thread, name); + tinfo->cpu_usage = thread_info_cpu_utilization(thread, ud, name); + + LOG_DBG("core %u %s stack %u%% cpu %u%%", ud->core, + tinfo->name, tinfo->stack_usage * 100U / 255, + tinfo->cpu_usage * 100U / 255); + + /* .is_idle depends on CONFIG_SMP */ +#if defined(CONFIG_SOF_DEBUG_STREAM_THREAD_INFO_TOTAL_CPU_LOAD_TO_LOG) && defined(CONFIG_SMP) + if (thread->base.is_idle) + LOG_INF("core %u utilization %u%%", ud->core, + 100U - tinfo->cpu_usage * 100U / 255); +#endif + + ud->thread_count++; +} + +#ifdef CONFIG_THREAD_RUNTIME_STATS + +/* Marks cached thread cycle counter entries of removed threads + * free. This also happens to threads pinned to other cpu than the + * primary. In the beginning they are listed on primary cpu, until the + * pinned cpu is started up and the thread is executed for the fist + * time and it moves to the cpu its pinned on. + */ +static void cleanup_old_thread_cycles(struct user_data *ud) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(ud->previous->threads); i++) { + bool found = false; + + /* This entry is already free, continue */ + if (ud->previous->threads[i].tid == NULL) + continue; + + /* Check if the thread was seen on previous round */ + for (j = 0; j < ud->thread_count; j++) { + if (ud->active_threads[j] == ud->previous->threads[i].tid) { + found = true; + break; + } + } + /* If the thead is not any more active, mark the entry free */ + if (!found) { + ud->previous->threads[i].tid = NULL; + ud->previous->threads[i].cycles = 0; + } + } +} +#else +static void cleanup_old_thread_cycles(struct user_data *ud) { } +#endif + +static void thread_info_get(int core, struct record_buf *bufd) +{ + k_thread_runtime_stats_t core_stats; + struct user_data ud = { + .core = core, + .bufd = bufd, + .thread_count = 0, +#ifdef CONFIG_THREAD_RUNTIME_STATS + .active_threads = { NULL }, + .previous = &previous[core], +#endif + }; + struct thread_info_record_hdr *hdr; + uint8_t load = 0; +#ifdef CONFIG_THREAD_RUNTIME_STATS + int ret = k_thread_runtime_stats_cpu_get(core, &core_stats); + + if (ret == 0) { + uint32_t active_cycles = (uint32_t) (core_stats.total_cycles - + ud.previous->active); + uint32_t all_cycles = (uint32_t) (core_stats.execution_cycles - + ud.previous->all); + + ud.stats_valid = true; + load = (uint8_t) ((255LLU * active_cycles) / all_cycles); + LOG_DBG("Core %u load %u / %u total %llu / %llu", core, + active_cycles, all_cycles, + core_stats.total_cycles, core_stats.execution_cycles); + ud.previous->active = core_stats.total_cycles; + ud.previous->all = core_stats.execution_cycles; + ud.all_cycles = all_cycles; + } +#endif + + hdr = (struct thread_info_record_hdr *) bufd->buf; + bufd->w_ptr = sizeof(*hdr); + hdr->hdr.id = DEBUG_STREAM_RECORD_ID_THREAD_INFO; + hdr->load = load; + /* This is best effort debug tool. Unlocked version should be fine. */ + k_thread_foreach_unlocked_filter_by_cpu(core, thread_info_cb, &ud); + + cleanup_old_thread_cycles(&ud); + + hdr->thread_count = ud.thread_count; + hdr->hdr.size_words = SOF_DIV_ROUND_UP(bufd->w_ptr, sizeof(hdr->hdr.data[0])); + debug_stream_slot_send_record(&hdr->hdr); +} + +static void thread_info_run(void *cnum, void *a, void *b) +{ + int core = (int) cnum; + struct record_buf bufd = { + .size = THREAD_INFO_INITIAL_RECORD_BUFFER_SIZE, + .w_ptr = 0, + }; + + bufd.buf = rmalloc(SOF_MEM_FLAG_USER, bufd.size); + if (!bufd.buf) { + LOG_ERR("malloc failed"); + return; + } + + for (;;) { + thread_info_get(core, &bufd); + k_sleep(K_SECONDS(CONFIG_SOF_DEBUG_STREAM_THREAD_INFO_INTERVAL)); + } +} + +#define THREAD_STACK_SIZE (2048) +static K_THREAD_STACK_ARRAY_DEFINE(info_thread_stacks, + CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS, + THREAD_STACK_SIZE); +static struct k_thread info_thread[CONFIG_SOF_DEBUG_STREAM_SLOT_FORCE_MAX_CPUS]; + +static int thread_info_start(void) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(info_thread); i++) { + char name[24]; + k_tid_t tid; + int ret; + + tid = k_thread_create(&info_thread[i], info_thread_stacks[i], + THREAD_STACK_SIZE, thread_info_run, + (void *) i, NULL, NULL, + K_LOWEST_APPLICATION_THREAD_PRIO, 0, + K_FOREVER); + if (!tid) { + LOG_ERR("k_thread_create() failed for core %u", i); + continue; + } +#ifdef CONFIG_SCHED_CPU_MASK + ret = k_thread_cpu_pin(tid, i); + if (ret < 0) { + LOG_ERR("Pinning thread to code core %u", i); + k_thread_abort(tid); + continue; + } +#endif + snprintf(name, sizeof(name), "%u thread info", i); + ret = k_thread_name_set(tid, name); + if (ret < 0) + LOG_INF("k_thread_name_set failed: %d for %u", ret, i); + + k_thread_start(tid); + LOG_DBG("Thread %p for core %u started", tid, i); + } + + return 0; +} + +SYS_INIT(thread_info_start, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/src/debug/dram.c b/src/debug/dram.c new file mode 100644 index 000000000000..5721a8b73e87 --- /dev/null +++ b/src/debug/dram.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <rtos/kernel.h> +#include <rtos/symbol.h> +#include <zephyr/logging/log.h> +#include <zephyr/sys/__assert.h> + +LOG_MODULE_REGISTER(dbg_path, CONFIG_SOF_LOG_LEVEL); + +static struct k_spinlock hot_path_lock; +static unsigned int hot_path_depth; +static const char *cold_path_fn; +static bool hot_path_confirmed; + +void dbg_path_cold_enter(const char *fn) +{ + k_spinlock_key_t key = k_spin_lock(&hot_path_lock); + + cold_path_fn = fn; + + k_spin_unlock(&hot_path_lock, key); +} +EXPORT_SYMBOL(dbg_path_cold_enter); + +void dbg_path_hot_start_watching(void) +{ + k_spinlock_key_t key = k_spin_lock(&hot_path_lock); + + if (!hot_path_depth++) { + cold_path_fn = NULL; + hot_path_confirmed = false; + } + + k_spin_unlock(&hot_path_lock, key); +} + +void dbg_path_hot_confirm(void) +{ + k_spinlock_key_t key = k_spin_lock(&hot_path_lock); + + hot_path_confirmed = true; + + k_spin_unlock(&hot_path_lock, key); +} + +void dbg_path_hot_stop_watching(void) +{ + bool underrun, error; + k_spinlock_key_t key = k_spin_lock(&hot_path_lock); + + if (hot_path_depth) { + underrun = false; + hot_path_depth--; + error = hot_path_confirmed && cold_path_fn; + } else { + error = underrun = true; + } + + k_spin_unlock(&hot_path_lock, key); + + if (underrun) + LOG_ERR("Hot path depth underrun!"); + else + __ASSERT(!error, "Cold function %s() has run while on hot path!", cold_path_fn); +} diff --git a/src/debug/gdb/CMakeLists.txt b/src/debug/gdb/CMakeLists.txt index 3cd0fe5f2d2b..4ca1af254b05 100644 --- a/src/debug/gdb/CMakeLists.txt +++ b/src/debug/gdb/CMakeLists.txt @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause +# Common to Zephyr and XTOS add_local_sources(sof gdb.c ringbuffer.c diff --git a/src/debug/gdb/README.md b/src/debug/gdb/README.md new file mode 100644 index 000000000000..33b6a31915c1 --- /dev/null +++ b/src/debug/gdb/README.md @@ -0,0 +1,65 @@ +# GDB Remote Debugging Stub + +The Sound Open Firmware (SOF) project carries a GNU Debugger (GDB) stub directly integrated with the framework's exception handlers. This translates commands sent by a GDB client (running on the host Linux machine) into architecture-specific logic. + +## Feature Overview + +Instead of completely relying on complex JTAG setups, developers can use this stub to dynamically introspect panic states, stack traces, and variable states during firmware execution, particularly inside isolated SoC DSP cores. + +When the firmware faults or hits a defined breakpoint, the exception vector routes control into this stub. It then waits for GDB Remote Protocol packet streams (ASCII formatted over the SOF mailbox/shared memory window). The Host reads these mailbox slots and pushes/pulls responses to its active GNU Debugger session. + +## Architecture + +Data moves between the Host GDB environment, the physical mailboxes bounding the DSP domain, the DSP firmware's built-in stub, and the active exception state. + +```mermaid +sequenceDiagram + participant GdbSession as Host GDB Client + participant IPC as SOF Driver / ALSA + participant Stub as Firmware GDB Stub (gdb_parser) + participant HW as DSP Context Registers + + HW-->>Stub: Hard Fault / Breakpoint Hit + activate Stub + + Note over Stub: Stores fault context (sregs/aregs) + + Stub-->>IPC: Write Mailbox: Breakpoint Notification + + GdbSession->>IPC: Send Packet (e.g., $g#67 to Read Regs) + IPC->>Stub: Passes 'g' string + + Stub->>HW: Reads requested register values + HW-->>Stub: Values + + Stub->>Stub: mem_to_hex() formatting + Stub-->>GdbSession: Returns hex payload via Mailbox + + GdbSession->>IPC: Send Packet ($c#63 to Continue) + IPC->>Stub: Process 'c' + Stub->>HW: Restores Context, Retains Execution + deactivate Stub +``` + +## How to Enable + +A basic GDB debugging configuration is exposed via Kconfig and must be explicitly bound: + +* `CONFIG_GDB_DEBUG`: Needs to be toggled `=y` to compile `src/debug/gdb/gdb.c` into the main application. + +Additionally, the overarching architecture requires the corresponding Exception vectors to be rewritten. In Zephyr OS based builds (which currently drive native architectures), fatal exception handling must be configured to pass register dumps recursively to `gdb_handle_exception()`. + +## Usage and Protocols + +The protocol adheres precisely to the standard GDB remote serial specification. Each string packet expects the format: + +`$<packet-data>#<check-sum>` + +Supported Command Handlers inside the Stub: + +* `g` (Read all registers) / `G` (Write all registers) +* `m` (Read memory) / `M` (Write memory) +* `p` (Read specific register) / `P` (Write specific register) +* `v` (Query architecture/support details like `vCont`) +* `c` / `s` (Continue execution / Single-step) +* `z` / `Z` (Insert/Remove breakpoints) diff --git a/src/debug/gdb/gdb.c b/src/debug/gdb/gdb.c index 3663ca7d6a8d..0345acfced92 100644 --- a/src/debug/gdb/gdb.c +++ b/src/debug/gdb/gdb.c @@ -12,7 +12,7 @@ #include <sof/debug/gdb/gdb.h> #include <sof/debug/gdb/ringbuffer.h> -#include <sof/lib/cache.h> +#include <rtos/cache.h> #include <string.h> /* local functions */ @@ -123,8 +123,6 @@ void gdb_handle_exception(void) /** * \brief Parse incoming GDB packets. - * \param[in] none. - * \param[out] none. * * Every incoming packet has the format: $packet-data#check-sum * packet-data varies depending on command. Full description @@ -445,7 +443,7 @@ static unsigned char *mem_to_hex(void *mem_, unsigned char *buf, unsigned char *mem = mem_; unsigned char ch; - if ((mem == NULL) || (buf == NULL)) + if (!mem || !buf) return NULL; while (count-- > 0) { ch = arch_gdb_load_from_memory(mem); @@ -468,7 +466,7 @@ static unsigned char *hex_to_mem(const unsigned char *buf, void *mem_, int i; unsigned char ch; - if ((mem == NULL) || (buf == NULL)) + if (!mem || !buf) return NULL; for (i = 0; i < count; i++) { ch = get_hex(*buf++) << 4; @@ -477,6 +475,6 @@ static unsigned char *hex_to_mem(const unsigned char *buf, void *mem_, mem++; } - dcache_writeback_region((void *)mem, count); + dcache_writeback_region((__sparse_force void __sparse_cache *)mem, count); return mem; } diff --git a/src/debug/panic.c b/src/debug/panic.c index e093acd183ac..0c56886e386a 100644 --- a/src/debug/panic.c +++ b/src/debug/panic.c @@ -4,16 +4,17 @@ // // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +#include <sof/debug/backtrace.h> #include <sof/debug/debug.h> -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/cache.h> +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <rtos/cache.h> #include <sof/lib/mailbox.h> #include <sof/platform.h> -#include <sof/string.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <ipc/trace.h> -#include <config.h> + #include <stddef.h> #include <stdint.h> @@ -30,36 +31,76 @@ void dump_panicinfo(void *addr, struct sof_ipc_panic_info *panic_info) dcache_writeback_region(addr, sizeof(struct sof_ipc_panic_info)); } -/* panic and rewind stack */ -void panic_rewind(uint32_t p, uint32_t stack_rewind_frames, - struct sof_ipc_panic_info *panic_info, uintptr_t *data) +/** Dumps stack as part of panic. + * + * \return SOF_IPC_PANIC_STACK if offset is off the stack_limit, + * unchanged 'p' panic code input otherwise. + */ +static uint32_t dump_stack(uint32_t p, void *addr, size_t offset, + size_t limit, uintptr_t *stack_ptr) +{ + uintptr_t stack_limit = (uintptr_t)arch_get_stack_entry(); + uintptr_t stack_bottom = stack_limit + arch_get_stack_size() - + sizeof(void *); + uintptr_t stack_top = (uintptr_t)arch_get_stack_ptr() + offset; + size_t size = stack_bottom - stack_top; + int ret; + + *stack_ptr = stack_top; + + /* is stack smashed ? */ + if (stack_top - offset <= stack_limit) { + p = SOF_IPC_PANIC_STACK; + return p; + } + + /* make sure stack size won't overflow dump area */ + if (size > limit) + size = limit; + + /* copy stack contents and writeback */ + ret = memcpy_s(addr, limit, (void *)stack_top, size - sizeof(void *)); + assert(!ret); + dcache_writeback_region(addr, size - sizeof(void *)); + + return p; +} + +/** Copy registers, panic_info and current stack to mailbox exception + * window. Opaque 'data' (e.g.: optional epc1) is passed to + * arch_dump_regs(). + */ +void panic_dump(uint32_t p, struct sof_ipc_panic_info *panic_info, + uintptr_t *data) { char *ext_offset; - size_t count; + size_t avail; uintptr_t stack_ptr; /* disable all IRQs */ interrupt_global_disable(); + /* ARCH_OOPS_SIZE is platform-dependent */ ext_offset = (char *)mailbox_get_exception_base() + ARCH_OOPS_SIZE; - /* dump panic info, filename ane linenum */ + /* dump panic info, filename and linenum */ dump_panicinfo(ext_offset, panic_info); ext_offset += sizeof(struct sof_ipc_panic_info); - count = MAILBOX_EXCEPTION_SIZE - - (size_t)(ext_offset - (char *)mailbox_get_exception_base()); - - /* flush last trace messages */ #if CONFIG_TRACE - trace_flush(); + trace_flush_dma_to_mbox(); #endif - /* dump stack frames */ - p = dump_stack(p, ext_offset, stack_rewind_frames, count, &stack_ptr); + /* Dump stack frames and override panic code 'p' if ext_offset is + * off stack_limit. Find stack_ptr. + */ + avail = MAILBOX_EXCEPTION_SIZE - + (size_t)(ext_offset - (char *)mailbox_get_exception_base()); + p = dump_stack(p, ext_offset, 0, avail, &stack_ptr); - /* dump DSP core registers - * after arch_dump_regs() use only inline funcs if needed + /* Write oops.arch_hdr and oops.plat_hdr headers and dump DSP core + * registers. After arch_dump_regs() use only inline funcs if + * needed. */ arch_dump_regs((void *)mailbox_get_exception_base(), stack_ptr, data); @@ -71,30 +112,30 @@ void panic_rewind(uint32_t p, uint32_t stack_rewind_frames, ; } -void __panic(uint32_t p, char *filename, uint32_t linenum) +void __panic(uint32_t panic_code, const char *filename, uint32_t linenum) { struct sof_ipc_panic_info panicinfo = { .linenum = linenum }; - int strlen; + const unsigned int length_max = sizeof(panicinfo.filename); + int mem_len; int ret; - strlen = rstrlen(filename); + /* including the ending '\0' */ + mem_len = rstrlen(filename) + 1; - if (strlen >= SOF_TRACE_FILENAME_SIZE) { + if (mem_len > length_max) { + /* copy those last bytes only */ ret = memcpy_s(panicinfo.filename, - sizeof(panicinfo.filename), - filename + strlen - SOF_TRACE_FILENAME_SIZE, - SOF_TRACE_FILENAME_SIZE); + length_max, + filename + mem_len - length_max, + length_max); /* TODO are asserts safe in this context? */ assert(!ret); - ret = memcpy_s(panicinfo.filename, - sizeof(panicinfo.filename), - "...", 3); + /* prefixing with "..." */ + ret = memcpy_s(panicinfo.filename, length_max, "...", 3); assert(!ret); } else { - ret = memcpy_s(panicinfo.filename, - sizeof(panicinfo.filename), - filename, strlen + 1); + ret = memcpy_s(panicinfo.filename, length_max, filename, mem_len); assert(!ret); } @@ -109,5 +150,5 @@ void __panic(uint32_t p, char *filename, uint32_t linenum) "a3", "memory"); #endif - panic_rewind(p, 0, &panicinfo, NULL); + panic_dump(panic_code, &panicinfo, NULL); } diff --git a/src/debug/telemetry/CMakeLists.txt b/src/debug/telemetry/CMakeLists.txt new file mode 100644 index 000000000000..6be536afc0c5 --- /dev/null +++ b/src/debug/telemetry/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources_ifdef(CONFIG_SOF_TELEMETRY sof telemetry.c) +add_local_sources_ifdef(CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS sof performance_monitor.c) \ No newline at end of file diff --git a/src/debug/telemetry/Kconfig b/src/debug/telemetry/Kconfig new file mode 100644 index 000000000000..f380a90e1808 --- /dev/null +++ b/src/debug/telemetry/Kconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config SOF_TELEMETRY + bool "enable telemetry" + default n + depends on !SOF_USERSPACE_LL + help + Enables telemetry. Enables performance measurements and debug utilities + that use memory window 2 (debug window) as interface. Measurements include + systick_info measurement which measures scheduler task performance and may + slightly affect overall performance. + +config SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + bool "enable performance measurements" + default n + help + Enables performance measurements. Requires ADSP_MW interface. Each created component + can have its performance checked by measuring execution time of copy function. + Performance records are stored in the limited number of slots in Memory Window 3, + so only a certain number (PERFORMANCE_DATA_ENTRIES_COUNT) of components can be measured. + +config SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + bool "enable I/O performance measurements" + help + Enables IO performance measurements. Each data interface will have its data throughput + measured (IPC/IDC and GPIO will measure number of messages/state changes). + Disabled by default and enabled with IPC. Measurements can be extracted also by IPC. + Interfaces measured: IPC, IDC, DMIC, I2S, SNDW, HDA, USB, GPIO, I2c, I3C, UART, SPI, CSI_2, DTF. + diff --git a/src/debug/telemetry/README.md b/src/debug/telemetry/README.md new file mode 100644 index 000000000000..19664ad2be8c --- /dev/null +++ b/src/debug/telemetry/README.md @@ -0,0 +1,48 @@ +# Telemetry and Performance Measurements + +The SOF Telemetry subsystem is a suite of built-in diagnostics measuring code execution efficiencies, cycle overheads, and hardware I/O throughput. + +## Feature Overview + +Latency and real-time execution bounds are critical in DSP firmware. The telemetry feature provides mechanisms to monitor these bounds accurately without intrusive breakpoints or slowing down the pipeline too aggressively. + +Capabilities include: + +1. **Component Performance Tracking**: For every instantiated component in the graph, it measures the pure execution time bounds (min/max/average) of that component's `comp_copy()` routines. +2. **I/O Throughput Tracking**: Measures hardware bus speeds or message handling by counting bytes, state changes, or tokens across distinct interfaces: IPC, DMIC, I2S, HD/A, I2C, SPI, etc. +3. **Zephyr Systick Measurement**: Specifically tracks the overall scheduler overhead bounding RTOS ticks. + +Measurements are batched into a ringbuffer locally, then synced across mapped ADSP memory windows into user space, limiting the impact on the active instruction cache. + +## Architecture + +The architecture bridges the component layer (like pure IPC or Audio Component wrappers) directly into independent statistics accumulators. + +```mermaid +graph TD + subgraph DSP Environment + Comp[Audio Component X] --> |"comp_copy() Execution"| Telemetry[perf_measure_execute] + HW[I2S / DMIC HW Driver] --> |"State Change Count"| Telemetry + + Telemetry --> RingBuffer[Statistics Ringbuffer] + RingBuffer --> Sync["Memory Window 3 (perf_data_sync)"] + end + + subgraph Host Userspace + Dev[sof-logger / IPC Tooling] --> |Reads/Queries| Sync + end +``` + +## How to Enable + +Telemetry depends strictly on NOT being built inside a host-userspace environment simulator (`depends on !SOF_USERSPACE_LL`). Ensure your target is a physical or emulated DSP target. + +Settings to configure in `Kconfig`: + +* `CONFIG_SOF_TELEMETRY=y` : Enable the overarching telemetry interfaces, giving you systick and basic task metrics over Memory Window 2 interfaces. +* `CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=y` : Adds granular tracking to audio components (creating the explicit `telemetry.c` ringbuffer maps via Memory Window 3 slots). Be aware that only a specific configured amount (`PERFORMANCE_DATA_ENTRIES_COUNT`) can be actively tracked due to RAM constraints. +* `CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=y` : Instructs hardware and communication buses to start pumping data into the metrics collector. + +## Extracting Data + +You can fetch these metrics via `sof-logger` or standard IPC interrogation tools that support polling the corresponding debug window slots mapped for your particular platform's `ADSP_MW`. diff --git a/src/debug/telemetry/performance_monitor.c b/src/debug/telemetry/performance_monitor.c new file mode 100644 index 000000000000..b7aedc5ffa7c --- /dev/null +++ b/src/debug/telemetry/performance_monitor.c @@ -0,0 +1,645 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Tobiasz Dryjanski <tobiaszx.dryjanski@intel.com> + +#include <sof/audio/component.h> +#include <sof/debug/telemetry/performance_monitor.h> +#include <sof/debug/telemetry/telemetry.h> +#include <sof/lib/cpu.h> +#include <sof/lib_manager.h> + +#include <zephyr/sys/bitarray.h> + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <adsp_debug_window.h> + +#include <ipc/trace.h> +#include <ipc4/logging.h> +#include <ipc4/base_fw.h> +#include <ipc4/base_fw_vendor.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +#define PERFORMANCE_DATA_ENTRIES_COUNT \ + (CONFIG_MEMORY_WIN_3_SIZE / sizeof(struct perf_data_item_comp)) + +SYS_BITARRAY_DEFINE_STATIC(performance_data_bit_array, PERFORMANCE_DATA_ENTRIES_COUNT); + +struct perf_bitmap { + sys_bitarray_t *array; + uint16_t occupied; + size_t size; +}; + +struct io_perf_monitor_ctx { + struct k_spinlock lock; + enum ipc4_perf_measurements_state_set state; + struct perf_bitmap io_performance_data_bitmap; + struct io_perf_data_item *io_perf_data; +}; + +struct perf_bitmap performance_data_bitmap; + +struct perf_data_item_comp *perf_data; + +/* Note that ref. FW used one state per core, all set together to the same state + * by one IPC but only for active cores. It may work slightly different in case + * where we enable a core while perf meas is started. + */ +enum ipc4_perf_measurements_state_set perf_measurements_state = IPC4_PERF_MEASUREMENTS_DISABLED; + +static int perf_bitmap_init(struct perf_bitmap * const bitmap, sys_bitarray_t *array, size_t size) +{ + k_spinlock_key_t key = k_spin_lock(&array->lock); + + bitmap->array = array; + bitmap->size = size; + bitmap->occupied = 0; + + k_spin_unlock(&array->lock, key); + return 0; +} + +static int perf_bitmap_alloc(struct perf_bitmap * const bitmap, size_t *offset) +{ + k_spinlock_key_t key; + int ret = sys_bitarray_alloc(bitmap->array, 1, offset); + + if (!ret) { + key = k_spin_lock(&bitmap->array->lock); + bitmap->occupied++; + k_spin_unlock(&bitmap->array->lock, key); + } + + return ret; +} + +static int perf_bitmap_free(struct perf_bitmap * const bitmap, size_t offset) +{ + k_spinlock_key_t key; + int ret = sys_bitarray_free(bitmap->array, 1, offset); + + if (!ret) { + key = k_spin_lock(&bitmap->array->lock); + bitmap->occupied--; + k_spin_unlock(&bitmap->array->lock, key); + } + + return ret; +} + +static int perf_bitmap_setbit(struct perf_bitmap * const bitmap, size_t bit) +{ + return sys_bitarray_set_bit(bitmap->array, bit); +} + +__attribute__((unused)) +static int perf_bitmap_clearbit(struct perf_bitmap * const bitmap, size_t bit) +{ + return sys_bitarray_clear_bit(bitmap->array, bit); +} + +static inline uint16_t perf_bitmap_get_occupied(struct perf_bitmap * const bitmap) +{ + return bitmap->occupied; +} + +static inline uint16_t perf_bitmap_get_size(struct perf_bitmap * const bitmap) +{ + return bitmap->size; +} + +static bool perf_bitmap_is_bit_clear(struct perf_bitmap * const bitmap, size_t bit) +{ + int val; + int ret = sys_bitarray_test_bit(bitmap->array, bit, &val); + + if (ret < 0) + return false; + return !val; +} + +struct perf_data_item_comp *perf_data_getnext(void) +{ + size_t idx; + int ret = perf_bitmap_alloc(&performance_data_bitmap, &idx); + + if (ret < 0) + return NULL; + /* ref. FW did not set the bits, but here we do it to not have to use + * isFree() check that the bitarray does not provide yet. Instead we will use isClear + * ,and always set bit on bitmap alloc. + */ + ret = perf_bitmap_setbit(&performance_data_bitmap, idx); + if (ret < 0) { + perf_bitmap_free(&performance_data_bitmap, idx); + return NULL; + } + return &perf_data[idx]; +} + +int perf_data_free(struct perf_data_item_comp * const item) +{ + /* find index of item */ + int idx = (item - perf_data); + int ret = perf_bitmap_free(&performance_data_bitmap, idx); + if (ret < 0) + return ret; + + return 0; +} + +void perf_data_item_comp_reset(struct perf_data_item_comp *perf) +{ + perf->total_iteration_count = 0; + perf->total_cycles_consumed = 0; + perf->restricted_total_iterations = 0; + perf->restricted_total_cycles = 0; + perf->restricted_peak_cycles = 0; + perf->item.peak_kcps = 0; + perf->item.avg_kcps = 0; +} + +void perf_data_item_comp_init(struct perf_data_item_comp *perf, uint32_t resource_id, + uint32_t power_mode) +{ + perf_data_item_comp_reset(perf); + perf->item.resource_id = resource_id; + perf->item.is_removed = false; + perf->item.power_mode = power_mode; +} + +int free_performance_data(struct perf_data_item_comp *item) +{ + int ret; + + if (item) { + item->item.is_removed = true; + /* if we don't get the disabled state now, item will be + * deleted on next disable perf meas message + */ + if (perf_measurements_state == IPC4_PERF_MEASUREMENTS_DISABLED) { + ret = perf_data_free(item); + if (ret < 0) + return ret; + } + } + return 0; +} + +enum ipc4_perf_measurements_state_set perf_meas_get_state(void) +{ + return perf_measurements_state; +} + +void perf_meas_set_state(enum ipc4_perf_measurements_state_set state) +{ + perf_measurements_state = state; +} + +int get_performance_data(struct global_perf_data * const global_perf_data) +{ + if (!global_perf_data) { + tr_err(&ipc_tr, "IPC data is NULL"); + return -EINVAL; + } + + size_t slots_count; + size_t slot_idx = 0; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct system_tick_info *systick_info = telemetry_get_systick_info_ptr(); + + if (!systick_info) + return 0; +#else + struct telemetry_wnd_data *wnd_data = + (struct telemetry_wnd_data *)ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT]; + struct system_tick_info *systick_info = + (struct system_tick_info *)wnd_data->system_tick_info; +#endif + + /* Fill one performance record with performance stats per core */ + for (int core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) { + if (!(cpu_enabled_cores() & BIT(core_id))) + continue; + memset(&global_perf_data->perf_items[slot_idx], 0, sizeof(struct perf_data_item)); + + global_perf_data->perf_items[slot_idx].resource_id = core_id; + global_perf_data->perf_items[slot_idx].avg_kcps = + systick_info[core_id].avg_utilization; + global_perf_data->perf_items[slot_idx].peak_kcps = + systick_info[core_id].peak_utilization; + ++slot_idx; + } + slots_count = perf_bitmap_get_occupied(&performance_data_bitmap) + slot_idx; + global_perf_data->perf_item_count = slots_count; + + /* fill the rest of the IPC records with data from + * components registered in MW3 for performance measurement + */ + for (int idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap) && + slot_idx < slots_count; ++idx) { + if (perf_bitmap_is_bit_clear(&performance_data_bitmap, idx)) + continue; + global_perf_data->perf_items[slot_idx] = perf_data[idx].item; + ++slot_idx; + } + return 0; +} + +int get_extended_performance_data(struct extended_global_perf_data * const ext_global_perf_data) +{ + if (!ext_global_perf_data) { + tr_err(&ipc_tr, "IPC data is NULL"); + return -EINVAL; + } + + size_t slots_count; + size_t slot_idx = 0; + uint64_t total_dsp_cycles[CONFIG_MAX_CORE_COUNT]; + + /* TODO + * Setting temporary values here. + * Replace this with actual total dsp cycles info once it is available. + */ + for (int core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) + total_dsp_cycles[core_id] = 1; + + /* Fill one performance record per core with total dsp cycles */ + for (int core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) { + if (!(cpu_enabled_cores() & BIT(core_id))) + continue; + + memset(&ext_global_perf_data->perf_items[slot_idx], 0, + sizeof(struct ext_perf_data_item)); + + ext_global_perf_data->perf_items[slot_idx].resource_id = core_id; + ext_global_perf_data->perf_items[slot_idx].module_total_dsp_cycles_consumed = + total_dsp_cycles[core_id]; + ++slot_idx; + } + + slots_count = perf_bitmap_get_occupied(&performance_data_bitmap) + slot_idx; + ext_global_perf_data->perf_item_count = slots_count; + + /* fill the rest of the IPC records with data from + * components registered in MW3 for performance measurement + */ + for (int idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap) && + slot_idx < slots_count; ++idx) { + if (perf_bitmap_is_bit_clear(&performance_data_bitmap, idx)) + continue; + + ext_global_perf_data->perf_items[slot_idx].resource_id = + perf_data[idx].item.resource_id; + ext_global_perf_data->perf_items[slot_idx].power_mode = + perf_data[idx].item.power_mode; + ext_global_perf_data->perf_items[slot_idx].is_removed = + perf_data[idx].item.is_removed; + ext_global_perf_data->perf_items[slot_idx].module_total_dsp_iterations = + perf_data[idx].total_iteration_count; + ext_global_perf_data->perf_items[slot_idx].module_total_dsp_cycles_consumed = + perf_data[idx].total_cycles_consumed; + ext_global_perf_data->perf_items[slot_idx].module_peak_dsp_cycles = + perf_data[idx].item.peak_kcps * 1000; + ext_global_perf_data->perf_items[slot_idx].module_peak_restricted_cycles = + perf_data[idx].restricted_peak_cycles; + ext_global_perf_data->perf_items[slot_idx].module_total_restricted_cycles_consumed = + perf_data[idx].restricted_total_cycles; + ext_global_perf_data->perf_items[slot_idx].module_total_restricted_iterations = + perf_data[idx].restricted_total_iterations; + ext_global_perf_data->perf_items[slot_idx].rsvd = 0; + ++slot_idx; + } + return 0; +} + +void disable_performance_counters(void) +{ + for (int idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap); ++idx) { + if (perf_bitmap_is_bit_clear(&performance_data_bitmap, idx)) + continue; + if (perf_data[idx].item.is_removed) + perf_data_free(&perf_data[idx]); + } +} + +int enable_performance_counters(void) +{ + struct sof_man_module *man_module; + struct comp_dev *dev; + uint32_t comp_id; + const struct sof_man_fw_desc *desc; + + if (perf_measurements_state != IPC4_PERF_MEASUREMENTS_DISABLED) + return -EINVAL; + + for (int lib_id = 0; lib_id < LIB_MANAGER_MAX_LIBS; ++lib_id) { + if (lib_id == 0) { + desc = basefw_vendor_get_manifest(); + } else { +#if CONFIG_LIBRARY_MANAGER + desc = lib_manager_get_library_manifest(LIB_MANAGER_PACK_LIB_ID(lib_id)); +#else + desc = NULL; +#endif + } + if (!desc) + continue; + + /* Reinitialize performance data for all created components */ + for (int mod_id = 0 ; mod_id < desc->header.num_module_entries; mod_id++) { + man_module = + (struct sof_man_module *)(desc + SOF_MAN_MODULE_OFFSET(mod_id)); + + for (int inst_id = 0; inst_id < man_module->instance_max_count; inst_id++) { + comp_id = IPC4_COMP_ID(mod_id, inst_id); + dev = ipc4_get_comp_dev(comp_id); + + if (dev) + comp_init_performance_data(dev); + } + } + } + + /* TODO clear total_dsp_ycles here once implemented */ + return 0; +} + +int reset_performance_counters(void) +{ + if (perf_measurements_state == IPC4_PERF_MEASUREMENTS_DISABLED) + return -EINVAL; + +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct system_tick_info *systick_info = telemetry_get_systick_info_ptr(); + + if (!systick_info) + return 0; +#else + struct telemetry_wnd_data *wnd_data = + (struct telemetry_wnd_data *)ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT]; + struct system_tick_info *systick_info = + (struct system_tick_info *)wnd_data->system_tick_info; +#endif + + for (int core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) { + if (!(cpu_enabled_cores() & BIT(core_id))) + continue; + systick_info[core_id].peak_utilization = 0; + } + for (int idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap); ++idx) { + if (!perf_bitmap_is_bit_clear(&performance_data_bitmap, idx)) + perf_data_item_comp_reset(&perf_data[idx]); + } + /* TODO clear totaldspcycles here once implemented */ + + return 0; +} + +int performance_monitor_init(void) +{ + /* init global performance measurement */ + perf_data = (struct perf_data_item_comp *)ADSP_PMW; + perf_bitmap_init(&performance_data_bitmap, &performance_data_bit_array, + PERFORMANCE_DATA_ENTRIES_COUNT); + + return 0; +} + +/* init performance monitor using Zephyr */ +SYS_INIT(performance_monitor_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + +SYS_BITARRAY_DEFINE_STATIC(io_performance_data_bit_array, PERFORMANCE_DATA_ENTRIES_COUNT); + +#define IO_PERFORMANCE_ALLOC_BYTES 0x1000 +#define IO_PERFORMANCE_MAX_ENTRIES (IO_PERFORMANCE_ALLOC_BYTES / sizeof(struct io_perf_data_item)) + +static struct io_perf_monitor_ctx perf_monitor_ctx; +static struct io_perf_data_item io_perf_data_items[IO_PERFORMANCE_MAX_ENTRIES]; + +int io_perf_monitor_init(void) +{ + int ret; + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + + k_spinlock_init(&self->lock); + k_spinlock_key_t key = k_spin_lock(&self->lock); + + self->io_perf_data = (struct io_perf_data_item *)io_perf_data_items; + self->state = IPC4_PERF_MEASUREMENTS_DISABLED; + + ret = perf_bitmap_init(&self->io_performance_data_bitmap, &io_performance_data_bit_array, + IO_PERFORMANCE_MAX_ENTRIES); + + k_spin_unlock(&self->lock, key); + return ret; +} + +static struct io_perf_data_item *io_perf_monitor_get_next_slot(struct io_perf_monitor_ctx *self) +{ + size_t idx; + int ret; + k_spinlock_key_t key = k_spin_lock(&self->lock); + + ret = perf_bitmap_alloc(&self->io_performance_data_bitmap, &idx); + if (ret < 0) + goto out_unlock; + /* ref. FW did not set the bits, but here we do it to not have to use + * isFree() check that the bitarray does not provide yet. Instead we will use isClear + * ,and always set bit on bitmap alloc. + */ + + ret = perf_bitmap_setbit(&self->io_performance_data_bitmap, idx); + if (ret < 0) { + perf_bitmap_free(&self->io_performance_data_bitmap, idx); + goto out_unlock; + } + + k_spin_unlock(&self->lock, key); + return &self->io_perf_data[idx]; + +out_unlock: + k_spin_unlock(&self->lock, key); + return NULL; +} + +int io_perf_monitor_release_slot(struct io_perf_data_item *item) +{ + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + int idx; + int ret; + k_spinlock_key_t key; + + if (!item) { + tr_err(&ipc_tr, "perf_data_item is null"); + return -EINVAL; + } + + item->is_removed = true; + + key = k_spin_lock(&self->lock); + idx = item - self->io_perf_data; + k_spin_unlock(&self->lock, key); + + /* we assign data items ourselves so neither of those should ever fail */ + ret = perf_bitmap_free(&self->io_performance_data_bitmap, idx); + assert(!ret); + return ret; +} + +int +io_perf_monitor_get_performance_data(struct io_global_perf_data *io_global_perf_data) +{ + if (!io_global_perf_data) + return 0; + + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + k_spinlock_key_t key = k_spin_lock(&self->lock); + + size_t slot_idx = 0; + size_t slots_count = self->io_performance_data_bitmap.occupied; + size_t entries_cont = self->io_performance_data_bitmap.size; + + for (size_t idx = 0; idx < entries_cont && slot_idx < slots_count; ++idx) { + if (perf_bitmap_is_bit_clear(&self->io_performance_data_bitmap, idx)) + continue; + io_global_perf_data->perf_items[slot_idx] = self->io_perf_data[idx]; + ++slot_idx; + } + io_global_perf_data->perf_item_count = slots_count; + + k_spin_unlock(&self->lock, key); + return 0; +} + +static int +io_perf_monitor_disable(struct io_perf_monitor_ctx *self) +{ + return 0; +} + +static int +io_perf_monitor_stop(struct io_perf_monitor_ctx *self) +{ + size_t slot_idx = 0; + size_t slots_count = self->io_performance_data_bitmap.occupied; + size_t entries_cont = self->io_performance_data_bitmap.size; + + for (size_t idx = 0; idx < entries_cont && slot_idx < slots_count; ++idx) { + if (perf_bitmap_is_bit_clear(&self->io_performance_data_bitmap, idx)) + continue; + + self->io_perf_data[idx].data = 0; + ++slot_idx; + } + + return 0; +} + +static int +io_perf_monitor_start(struct io_perf_monitor_ctx *self) +{ + return 0; +} + +static int +io_perf_monitor_pause(struct io_perf_monitor_ctx *self) +{ + return 0; +} + +int io_perf_monitor_set_state(enum ipc4_perf_measurements_state_set state) +{ + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + int ret = 0; + k_spinlock_key_t key = k_spin_lock(&self->lock); + + switch (state) { + case IPC4_PERF_MEASUREMENTS_DISABLED: + ret = io_perf_monitor_disable(self); + break; + case IPC4_PERF_MEASUREMENTS_STOPPED: + ret = io_perf_monitor_stop(self); + break; + case IPC4_PERF_MEASUREMENTS_STARTED: + ret = io_perf_monitor_start(self); + break; + case IPC4_PERF_MEASUREMENTS_PAUSED: + ret = io_perf_monitor_pause(self); + break; + default: + ret = -EINVAL; + } + + if (ret == 0) + self->state = state; + + k_spin_unlock(&self->lock, key); + return ret; +} + +inline enum ipc4_perf_measurements_state_set io_perf_monitor_get_state(void) +{ + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + + return self->state; +} + +int io_perf_monitor_init_data(struct io_perf_data_item **slot_id, + struct io_perf_data_item *init_data) +{ + if (!slot_id) + return IPC4_ERROR_INVALID_PARAM; + + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + struct io_perf_data_item *new_slot = io_perf_monitor_get_next_slot(self); + + if (!new_slot) + return IPC4_FAILURE; + + new_slot->id = init_data->id; + new_slot->instance = init_data->instance; + new_slot->direction = init_data->direction; + new_slot->state = init_data->state; + new_slot->power_mode = init_data->power_mode; + new_slot->is_removed = false; + new_slot->data = 0; + + *slot_id = new_slot; + + return 0; +} + +void io_perf_monitor_update_data(struct io_perf_data_item *slot_id, uint32_t increment) +{ + if (!slot_id) + return; + + struct io_perf_monitor_ctx *self = &perf_monitor_ctx; + + /* this does not need a lock if each perf slot has only one user */ + if (self->state == IPC4_PERF_MEASUREMENTS_STARTED) + slot_id->data += increment; +} + +inline void io_perf_monitor_update_io_state(struct io_perf_data_item *slot_id, bool const power_up) +{ + slot_id->state = power_up; +} + +inline void io_perf_monitor_update_power_mode(struct io_perf_data_item *slot_id, + bool const power_mode) +{ + slot_id->power_mode = power_mode; +} +#endif /* CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS */ diff --git a/src/debug/telemetry/telemetry.c b/src/debug/telemetry/telemetry.c new file mode 100644 index 000000000000..1e4c522dfee0 --- /dev/null +++ b/src/debug/telemetry/telemetry.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Tobiasz Dryjanski <tobiaszx.dryjanski@intel.com> + +#include <zephyr/debug/sparse.h> + +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/debug/telemetry/telemetry.h> +#include <sof/lib_manager.h> + +#include <ipc/trace.h> +#include <ipc4/base_fw.h> +#include <ipc4/base_fw_vendor.h> + +#include <adsp_debug_window.h> +#include <errno.h> +#include <limits.h> +#include <mem_window.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +/* Systic variables, one set per core */ +static int telemetry_systick_counter[CONFIG_MAX_CORE_COUNT]; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +static struct telemetry_wnd_data *wnd_data; +#endif + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS +static int telemetry_prev_ccount[CONFIG_MAX_CORE_COUNT]; +static int telemetry_perf_period_sum[CONFIG_MAX_CORE_COUNT]; +static int telemetry_perf_period_cnt[CONFIG_MAX_CORE_COUNT]; +static struct telemetry_perf_queue telemetry_perf_queue[CONFIG_MAX_CORE_COUNT]; +#endif + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS +static void telemetry_perf_queue_append(struct telemetry_perf_queue *q, size_t element) +{ + if (!q->full) { + q->elements[q->index] = element; + q->sum += element; + q->index++; + q->size++; + if (q->index >= SOF_AVG_PERF_MEAS_DEPTH) { + q->index = 0; + q->size = SOF_AVG_PERF_MEAS_DEPTH; + q->full = true; + } + } else { + /* no space, pop tail */ + q->sum -= q->elements[q->index]; + /* replace tail */ + q->elements[q->index] = element; + q->sum += element; + /* move tail */ + q->index++; + if (q->index >= SOF_AVG_PERF_MEAS_DEPTH) + q->index = 0; + } +} + +static size_t telemetry_perf_queue_avg(struct telemetry_perf_queue *q) +{ + if (!q->size) + return 0; + return q->sum / q->size; +} +#endif + +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +struct system_tick_info *telemetry_get_systick_info_ptr(void) +{ + if (!wnd_data) + return NULL; + + return (struct system_tick_info *)wnd_data->system_tick_info; +} +#endif + +int telemetry_init(void) +{ + /* systick_init */ +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_TELEMETRY, }; + struct system_tick_info *systick_info; + + if (wnd_data) + return 0; + + wnd_data = (struct telemetry_wnd_data *)adsp_dw_request_slot(&slot_desc, + NULL); + if (!wnd_data) + return -ENOMEM; + + systick_info = (struct system_tick_info *)wnd_data->system_tick_info; +#else + uint8_t slot_num = SOF_DW_TELEMETRY_SLOT; + volatile struct adsp_debug_window *window = ADSP_DW; + struct telemetry_wnd_data *wnd_data = (struct telemetry_wnd_data *)ADSP_DW->slots[slot_num]; + struct system_tick_info *systick_info = + (struct system_tick_info *)wnd_data->system_tick_info; + + window->descs[slot_num].type = ADSP_DW_SLOT_TELEMETRY; + window->descs[slot_num].resource_id = 0; +#endif + + tr_info(&ipc_tr, "Telemetry enabled. May affect performance"); + + wnd_data->separator_1 = 0x0000C0DE; + + /* Zero values per core */ + for (int i = 0; i < CONFIG_MAX_CORE_COUNT; i++) { + systick_info[i].count = 0; + systick_info[i].last_time_elapsed = 0; + systick_info[i].max_time_elapsed = 0; + systick_info[i].last_ccount = 0; + systick_info[i].avg_utilization = 0; + systick_info[i].peak_utilization = 0; + systick_info[i].peak_utilization_4k = 0; + systick_info[i].peak_utilization_8k = 0; + } + + return 0; +} + +void telemetry_update(uint32_t begin_stamp, uint32_t current_stamp) +{ + int prid = cpu_get_id(); +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct system_tick_info *systick_info = telemetry_get_systick_info_ptr(); + + if (!systick_info) + return; +#else + struct telemetry_wnd_data *wnd_data = + (struct telemetry_wnd_data *)ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT]; + struct system_tick_info *systick_info = + (struct system_tick_info *)wnd_data->system_tick_info; +#endif + + ++telemetry_systick_counter[prid]; + + systick_info[prid].count = telemetry_systick_counter[prid]; + systick_info[prid].last_time_elapsed = current_stamp - begin_stamp; + systick_info[prid].max_time_elapsed = + MAX(current_stamp - begin_stamp, + systick_info[prid].max_time_elapsed); + systick_info[prid].last_ccount = current_stamp; + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + const size_t measured_systick = begin_stamp - telemetry_prev_ccount[prid]; + + telemetry_prev_ccount[prid] = begin_stamp; + if (telemetry_systick_counter[prid] > 2) { + telemetry_perf_period_sum[prid] += measured_systick; + telemetry_perf_period_cnt[prid] = + (telemetry_perf_period_cnt[prid] + 1) % SOF_AVG_PERF_MEAS_PERIOD; + if (telemetry_perf_period_cnt[prid] == 0) { + /* Append average of last SOF_AVG_PERF_MEAS_PERIOD runs */ + telemetry_perf_queue_append(&telemetry_perf_queue[prid], + telemetry_perf_period_sum[prid] + / SOF_AVG_PERF_MEAS_PERIOD); + telemetry_perf_period_sum[prid] = 0; + /* Calculate average from all buckets */ + systick_info[prid].avg_utilization = + telemetry_perf_queue_avg(&telemetry_perf_queue[prid]); + } + + systick_info[prid].peak_utilization = + MAX(systick_info[prid].peak_utilization, + measured_systick); + systick_info[prid].peak_utilization_4k = + MAX(systick_info[prid].peak_utilization_4k, + measured_systick); + systick_info[prid].peak_utilization_8k = + MAX(systick_info[prid].peak_utilization_8k, + measured_systick); + + /* optimized: counter % 0x1000 */ + if ((telemetry_systick_counter[prid] & 0xfff) == 0) + systick_info[prid].peak_utilization_4k = 0; + /* optimized: counter % 0x2000 */ + if ((telemetry_systick_counter[prid] & 0x1fff) == 0) + systick_info[prid].peak_utilization_8k = 0; + } +#endif +} + +/* init telemetry using Zephyr*/ +SYS_INIT(telemetry_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); + diff --git a/src/debug/tester/CMakeLists.txt b/src/debug/tester/CMakeLists.txt new file mode 100644 index 000000000000..85bf026b5ed3 --- /dev/null +++ b/src/debug/tester/CMakeLists.txt @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: BSD-3-Clause + +set(base_files + tester.c + tester_dummy_test.c + tester_simple_dram_test.c +) + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + if(CONFIG_COMP_TESTER STREQUAL "m" AND DEFINED CONFIG_LLEXT) + + add_subdirectory(llext ${PROJECT_BINARY_DIR}/tester_llext) + add_dependencies(app tester) + + elseif(CONFIG_COMP_TESTER STREQUAL "y") + + zephyr_library_sources(${base_files}) + + endif() + +endif() diff --git a/src/debug/tester/Kconfig b/src/debug/tester/Kconfig new file mode 100644 index 000000000000..66a5140a097c --- /dev/null +++ b/src/debug/tester/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config COMP_TESTER + tristate "tester module" + default n + depends on IPC_MAJOR_4 + help + Build a tester module. To be used in continuous + integration process for special test cases that + require a test code injected into the system itself \ No newline at end of file diff --git a/src/debug/tester/README.md b/src/debug/tester/README.md new file mode 100644 index 000000000000..bd558fd80a4d --- /dev/null +++ b/src/debug/tester/README.md @@ -0,0 +1,54 @@ +# Tester Component + +The `tester` directory implements a pseudo-component inside the SOF architecture. Instead of processing audio like an EQ or Mixer, it acts as a test execution harness designed specifically for Continuous Integration (CI) and automated system verifications. + +## Feature Overview + +Continuous integration often requires validating low-level system interactions that cannot be reached or easily triggered via standard ALSA driver behaviors. To overcome this, the `tester` component can be instantiated via Topologies or explicit IPC commands. Once bound, the host can send configuration blobs triggering embedded testing subroutines compiled directly into the firmware. + +Currently, it supports functionalities like: + +* **Dummy Operations**: Echoing parameters to verify full-stack serialization roundtrips. +* **DRAM Verification**: Stress-testing memory allocation arrays within the `LLB`/`L2` domains to detect caching bugs or out-of-bounds pointer crashes (`tester_simple_dram_test`). + +## Architecture + +The architecture functions identical to an IPC Version 4 standard module, containing `comp_driver`, `comp_dev`, `comp_buffer` wrappers and implementing `tester_params()` handlers. + +```mermaid +graph TD + subgraph Host Automation + Testbench[CI Testbench / ALSA Tool] + Testbench -->> |Topology Payload: CMD_TEST| IPC + end + + subgraph SOF Firmware + IPC[IPC4 Handler] -->> |ipc4_set_module_params| Tester[Tester Component] + + Tester -->> |Switch on Test Type| Dummy[tester_dummy_test.c] + Tester -->> |Switch on Test Type| DRAM[tester_simple_dram_test.c] + + Dummy -->> IPC + DRAM -->> |Runs Data Verifications| ExtMemory[SoC DRAM / Caches] + DRAM -->> IPC + end +``` + +## How to Enable + +Because the tester artificially exposes internal memory bounds limits and allows arbitrary firmware injection tests, it is locked out of standard release payloads. + +To compile it into your build, you must append: + +* `CONFIG_COMP_TESTER=y` + +**Constraints:** +It strictly `depends on IPC_MAJOR_4`. You cannot instantiate this tester under the legacy IPC3 streaming mechanisms. + +## Creating New Tests + +Developers diagnosing tricky hardware bugs can extend the tester by: + +1. Adding a new case to the test selection switch in `tester.c:tester_init()` (and, if needed, extending runtime handling in `tester_set_configuration()`). +2. Defining a new `test_runner()` C file implementing their data patterns. +3. Adding the target configurations in `tester.toml` to automatically sync with the module offset calculators (`llext_offset_calc`). diff --git a/src/debug/tester/llext/CMakeLists.txt b/src/debug/tester/llext/CMakeLists.txt new file mode 100644 index 000000000000..096cbf65d853 --- /dev/null +++ b/src/debug/tester/llext/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("tester" + SOURCES ../tester.c + ../tester_dummy_test.c + ../tester_simple_dram_test.c +) diff --git a/src/debug/tester/llext/llext.toml.h b/src/debug/tester/llext/llext.toml.h new file mode 100644 index 000000000000..764d6e743506 --- /dev/null +++ b/src/debug/tester/llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../tester.toml" + +[module] +count = __COUNTER__ diff --git a/src/debug/tester/tester.c b/src/debug/tester/tester.c new file mode 100644 index 000000000000..161b90a7d3f3 --- /dev/null +++ b/src/debug/tester/tester.c @@ -0,0 +1,255 @@ +//SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Marcin Szkudlinski <marcin.szkudlinski@linux.intel.com> + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> +#include <rtos/init.h> +#include <sof/lib/uuid.h> +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/sink_source_utils.h> +#include "tester.h" +#include "tester_dummy_test.h" +#include "tester_simple_dram_test.h" + +/** + * Tester module is a framework for a runtime testing that need a special test code + * injected into the SOF system, i.e. + * - provide an extra load to CPU by running additional thread + * - execute some incorrect operations + * + * The idea is to allow using of special cases in testing like Continuous Integration or pre-release + * testing using a standard, production build. + * + * In order to have only one testing module (in meaning of a SOF module with separate UUID), + * a framework is introduced, where a test to be executed is selected by IPC parameter + * + * In production, module should be compiled as a loadable module, as it should not needed to be + * loaded and used on customers' boards. + * During developing, however, the module may be built in to keep debugging simpler + * + */ + +LOG_MODULE_REGISTER(tester, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(tester); + +struct tester_init_config { + struct ipc4_base_module_cfg ipc4_cfg; + int32_t test_type; +} __attribute__((packed, aligned(4))); + +static int tester_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct comp_dev *dev = mod->dev; + struct module_config *cfg = &md->cfg; + size_t bs = cfg->size; + struct tester_module_data *cd = NULL; + int ret = 0; + + if (bs != sizeof(struct tester_init_config)) { + comp_err(dev, "Invalid config"); + return -EINVAL; + } + + /* allocate ctx for test module in shared memory - to allow all non-standard operations + * without problems with cache + */ + cd = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*cd)); + if (!cd) { + comp_err(dev, "Out of memory"); + return -ENOMEM; + } + + struct tester_init_config *init_cfg = (struct tester_init_config *)cfg->init_data; + + cd->test_case_type = init_cfg->test_type; + switch (cd->test_case_type) { + case TESTER_MODULE_CASE_DUMMY_TEST: + cd->tester_case_interface = &tester_interface_dummy_test; + break; + case TESTER_MODULE_CASE_SIMPLE_DRAM_TEST: + cd->tester_case_interface = &tester_interface_simple_dram_test; + break; + + default: + comp_err(dev, "Invalid config, unknown test type"); + rfree(cd); + return -EINVAL; + } + + module_set_private_data(mod, cd); + + if (cd->tester_case_interface->init) + ret = cd->tester_case_interface->init(mod, &cd->test_case_ctx); + + if (ret) { + module_set_private_data(mod, NULL); + rfree(cd); + } + + return ret; +} + +static int tester_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->prepare) + ret = cd->tester_case_interface->prepare(cd->test_case_ctx, mod, + sources, num_of_sources, + sinks, num_of_sinks); + + return ret; +} + +int tester_set_configuration(struct processing_module *mod, + uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->set_configuration) + ret = cd->tester_case_interface->set_configuration(cd->test_case_ctx, mod, + config_id, pos, data_offset_size, + fragment, fragment_size, + response, response_size); + + return ret; +} + +static int tester_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + bool do_copy = true; + + if (cd->tester_case_interface->process) + ret = cd->tester_case_interface->process(cd->test_case_ctx, mod, + sources, num_of_sources, + sinks, num_of_sinks, &do_copy); + + if (!ret) { + size_t sink_free = sink_get_free_size(sinks[0]); + size_t source_avail = source_get_data_available(sources[0]); + size_t to_copy = MIN(sink_free, source_avail); + + if (do_copy) { + /* copy data from input to output */ + source_to_sink_copy(sources[0], sinks[0], true, to_copy); + } else { + /* drop data and generate silence */ + source_drop_data(sources[0], to_copy); + sink_fill_with_silence(sinks[0], to_copy); + } + } + + return ret; +} + +static int tester_reset(struct processing_module *mod) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->reset) + ret = cd->tester_case_interface->reset(cd->test_case_ctx, mod); + + return ret; +} + +static int tester_free(struct processing_module *mod) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->free) + ret = cd->tester_case_interface->free(cd->test_case_ctx, mod); + + rfree(cd); + module_set_private_data(mod, NULL); + return ret; +} + +static int tester_bind(struct processing_module *mod, struct bind_info *bind_data) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->bind) + ret = cd->tester_case_interface->bind(cd->test_case_ctx, mod, bind_data); + + return ret; +} + +static int tester_unbind(struct processing_module *mod, struct bind_info *unbind_data) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->unbind) + ret = cd->tester_case_interface->unbind(cd->test_case_ctx, mod, unbind_data); + + return ret; +} + +static int tester_trigger(struct processing_module *mod, int cmd) +{ + struct tester_module_data *cd = module_get_private_data(mod); + int ret = 0; + + if (cd->tester_case_interface->trigger) + ret = cd->tester_case_interface->trigger(cd->test_case_ctx, mod, cmd); + + if (!ret) + ret = module_adapter_set_state(mod, mod->dev, cmd); + + return ret; +} + +static const struct module_interface tester_interface = { + .init = tester_init, + .prepare = tester_prepare, + .set_configuration = tester_set_configuration, + .process = tester_process, + .reset = tester_reset, + .free = tester_free, + .bind = tester_bind, + .unbind = tester_unbind, + .trigger = tester_trigger +}; + +#if CONFIG_COMP_TESTER_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("TESTER", &tester_interface, 1, SOF_REG_UUID(tester), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_TR_CTX(tester_tr, SOF_UUID(tester_uuid), LOG_LEVEL_INFO); +DECLARE_MODULE_ADAPTER(tester_interface, tester_uuid, tester_tr); +SOF_MODULE_INIT(tester, sys_comp_module_tester_interface_init); + +#endif diff --git a/src/debug/tester/tester.h b/src/debug/tester/tester.h new file mode 100644 index 000000000000..79a65b65a7b2 --- /dev/null +++ b/src/debug/tester/tester.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + * Author: Marcin Szkudlinski <marcin.szkudlinski@linux.intel.com> + */ + +#ifndef COMP_TESTER +#define COMP_TESTER + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> +#include <module/module/interface.h> + +#define TESTER_MODULE_CASE_NO_TEST 0 +#define TESTER_MODULE_CASE_DUMMY_TEST 1 +#define TESTER_MODULE_CASE_SIMPLE_DRAM_TEST 2 + +/** + * API of a test case + * it is mostly a replica of module interface, with some additional parameters and functions + * + * all methods are optional + */ +struct tester_test_case_interface { + /** + * test initialization procedure, + * called in module init method + * It should allocate all required structures and return pointer to context + * in ctx param + */ + int (*init)(struct processing_module *mod, void **ctx); + + /** + * copy of module prepare method, with additional ctx param + */ + int (*prepare)(void *ctx, struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * copy of module set_configuration method, with additional ctx param + */ + int (*set_configuration)(void *ctx, 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); + + /** + * copy of module process method, with additional + * - ctx param + * - do_copy return flag. If is set to true, the tester base will do copy all samples + * from source to sink. + * May be used to indicate if the test has failed without any messages, just by stopping + * data stream + */ + int (*process)(void *ctx, struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks, + bool *do_copy); + + /** + * copy of module reset method, with additional ctx param + */ + int (*reset)(void *ctx, struct processing_module *mod); + + /** + * copy of module free method, with additional ctx param + * must free all data allocated during test + */ + int (*free)(void *ctx, struct processing_module *mod); + + /** + * copy of module bind method, with additional ctx param + */ + int (*bind)(void *ctx, struct processing_module *mod, struct bind_info *bind_data); + + /** + * copy of module unbind method, with additional ctx param + */ + int (*unbind)(void *ctx, struct processing_module *mod, struct bind_info *unbind_data); + + /** + * copy of module trigger method, with additional ctx param + */ + int (*trigger)(void *ctx, struct processing_module *mod, int cmd); + +}; + +struct tester_module_data { + const struct tester_test_case_interface *tester_case_interface; + uint32_t test_case_type; + void *test_case_ctx; +}; + +#endif /* COMP_TESTER */ diff --git a/src/debug/tester/tester.toml b/src/debug/tester/tester.toml new file mode 100644 index 000000000000..586bf2c3046b --- /dev/null +++ b/src/debug/tester/tester.toml @@ -0,0 +1,75 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "TESTER" + uuid = UUIDREG_STR_TESTER + affinity_mask = "0x1" + REM #instance_count = "10" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "7" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xffff, 0xc, 0x8, 0x05ff, + 1, 0, 0xf6c9, 0xc, 0x8, 0x05ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#if CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 12832, 15976000, 128, 512, 0, 15976, 0, + 1, 0, 0, 0, 12832, 15340000, 64, 256, 0, 15340, 0, + 2, 0, 0, 0, 12832, 21880000, 96, 512, 0, 21880, 0, + 3, 0, 0, 0, 12832, 19968000, 48, 256, 0, 19968, 0, + 4, 0, 0, 0, 12832, 18236000, 64, 256, 0, 18236, 0, + 5, 0, 0, 0, 12832, 15244000, 32, 256, 0, 15244, 0, + 6, 0, 0, 0, 12832, 56028000, 1536, 512, 0, 56028, 0, + 7, 0, 0, 0, 12832, 46740000, 768, 256, 0, 46740, 0, + 8, 0, 0, 0, 12832, 24656000, 768, 512, 0, 24656, 0, + 9, 0, 0, 0, 12832, 23516000, 384, 256, 0, 23516, 0, + 10, 0, 0, 0, 12832, 29368000, 384, 488, 0, 29368, 0, + 11, 0, 0, 0, 12832, 27164000, 192, 244, 0, 27164, 0, + 12, 0, 0, 0, 12832, 15892000, 384, 384, 0, 15892, 0, + 13, 0, 0, 0, 12832, 19916000, 192, 512, 0, 19916, 0, + 14, 0, 0, 0, 12832, 19176000, 96, 256, 0, 19176, 0, + 15, 0, 0, 0, 12832, 12676000, 192, 192, 0, 12676, 0, + 16, 0, 0, 0, 12832, 16280000, 384, 320, 0, 16280, 0, + 17, 0, 0, 0, 12832, 13076000, 192, 160, 0, 13076, 0, + 18, 0, 0, 0, 12832, 11440000, 384, 256, 0, 11440, 0, + 19, 0, 0, 0, 12832, 10996000, 192, 128, 0, 10996, 0, + 20, 0, 0, 0, 12832, 11428000, 384, 192, 0, 11428, 0, + 21, 0, 0, 0, 12832, 10740000, 192, 96, 0, 10740, 0, + 22, 0, 0, 0, 12832, 29936000, 360, 512, 0, 29936, 0, + 23, 0, 0, 0, 12832, 27696000, 180, 256, 0, 27696, 0, + 24, 0, 0, 0, 12832, 18368000, 256, 512, 0, 18368, 0, + 25, 0, 0, 0, 12832, 15204000, 128, 256, 0, 15204, 0] +#elif defined(CONFIG_LUNARLAKE) || defined(CONFIG_SOC_ACE30) || \ + defined(CONFIG_SOC_ACE40) + mod_cfg = [0, 0, 0, 0, 12832, 1365500, 0, 0, 0, 1365, 0, + 1, 0, 0, 0, 12832, 2302300, 0, 0, 0, 2302, 0, + 2, 0, 0, 0, 12832, 3218200, 0, 0, 0, 3218, 0, + 3, 0, 0, 0, 12832, 4169700, 0, 0, 0, 4169, 0, + 4, 0, 0, 0, 12832, 5095100, 0, 0, 0, 5095, 0, + 5, 0, 0, 0, 12832, 6014800, 0, 0, 0, 6014, 0, + 6, 0, 0, 0, 12832, 6963500, 0, 0, 0, 6963, 0, + 7, 0, 0, 0, 12832, 7791000, 0, 0, 0, 7791, 0, + 8, 0, 0, 0, 12832, 8843000, 0, 0, 0, 8843, 0, + 9, 0, 0, 0, 12832, 9755100, 0, 0, 0, 9755, 0, + 10, 0, 0, 0, 12832, 10726500, 0, 0, 0, 10726, 0, + 11, 0, 0, 0, 12832, 11624100, 0, 0, 0, 11624, 0, + 12, 0, 0, 0, 12832, 12518700, 0, 0, 0, 12518, 0, + 13, 0, 0, 0, 12832, 13555000, 0, 0, 0, 13555, 0, + 14, 0, 0, 0, 12832, 14144500, 0, 0, 0, 14144, 0, + 15, 0, 0, 0, 12832, 15809800, 0, 0, 0, 15809, 0, + 16, 0, 0, 0, 12832, 16749000, 0, 0, 0, 16749, 0, + 17, 0, 0, 0, 12832, 18433500, 0, 0, 0, 18433, 0, + 18, 0, 0, 0, 12832, 19425900, 0, 0, 0, 19425, 0, + 19, 0, 0, 0, 12832, 20396900, 0, 0, 0, 20396, 0, + 20, 0, 0, 0, 12832, 20881000, 0, 0, 0, 20881, 0, + 21, 0, 0, 0, 12832, 23431000, 0, 0, 0, 23431, 0, + 22, 0, 0, 0, 12832, 30471000, 0, 0, 0, 30471, 0] +#endif + + index = __COUNTER__ diff --git a/src/debug/tester/tester_dummy_test.c b/src/debug/tester/tester_dummy_test.c new file mode 100644 index 000000000000..6d9e2596b3f4 --- /dev/null +++ b/src/debug/tester/tester_dummy_test.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Marcin Szkudlinski <marcin.szkudlinski@linux.intel.com> + +#include "tester_dummy_test.h" +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> + +/* + * This is a dummy test case + * The test case will copy every 2nd frame of data + * by setting do_copy flag to true/false + */ + +struct tester_module_dummy_test_data { + bool do_copy_data; +}; + +static int dummy_test_case_init(struct processing_module *mod, void **ctx) +{ + struct tester_module_dummy_test_data *data = + rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*data)); + + if (!data) + return -ENOMEM; + + data->do_copy_data = false; + *ctx = data; + return 0; +} + +int dummy_test_case_process(void *ctx, struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks, + bool *do_copy) +{ + struct tester_module_dummy_test_data *data = ctx; + + /* copy every second cycle */ + *do_copy = data->do_copy_data; + data->do_copy_data = !data->do_copy_data; + + return 0; +} + +int dummy_test_free(void *ctx, struct processing_module *mod) +{ + rfree(ctx); + return 0; +} + +const struct tester_test_case_interface tester_interface_dummy_test = { + .init = dummy_test_case_init, + .process = dummy_test_case_process, + .free = dummy_test_free +}; diff --git a/src/debug/tester/tester_dummy_test.h b/src/debug/tester/tester_dummy_test.h new file mode 100644 index 000000000000..55a53266d243 --- /dev/null +++ b/src/debug/tester/tester_dummy_test.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + * Author: Marcin Szkudlinski <marcin.szkudlinski@linux.intel.com> + */ + +#ifndef TESTER_DUMMY_TEST +#define TESTER_DUMMY_TEST + +#include <stddef.h> +#include <stdint.h> + +#include "tester.h" + +extern const struct tester_test_case_interface tester_interface_dummy_test; + +#endif /* TESTER_DUMMY_TEST */ diff --git a/src/debug/tester/tester_simple_dram_test.c b/src/debug/tester/tester_simple_dram_test.c new file mode 100644 index 000000000000..1a32e0ff6440 --- /dev/null +++ b/src/debug/tester/tester_simple_dram_test.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + +#include "tester_simple_dram_test.h" +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/lib/memory.h> + +/* + * This is a simple test case for DRAM execution + * The test case will copy every 2nd frame of data + * by setting do_copy flag to true/false + */ + +struct tester_module_simple_dram_test_data { + bool do_copy_data; +}; + +static int validate_l3_memory(void *ptr) +{ + if (!((POINTER_TO_UINT(ptr) >= L3_MEM_BASE_ADDR) && + (POINTER_TO_UINT(ptr) < L3_MEM_BASE_ADDR + L3_MEM_SIZE))) + return -EINVAL; + + return 0; +} + +__cold static int simple_dram_test_case_init(struct processing_module *mod, void **ctx) +{ +#if !CONFIG_L3_HEAP + return -EINVAL; +#endif + struct tester_module_simple_dram_test_data *data = + rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_L3, sizeof(*data)); + + assert_can_be_cold(); + + if (!data) + return -ENOMEM; + + if (validate_l3_memory(data) != 0) { + rfree(data); + return -EINVAL; + } + + if (validate_l3_memory(tester_interface_simple_dram_test.init) != 0 || + validate_l3_memory(tester_interface_simple_dram_test.process) != 0 || + validate_l3_memory(tester_interface_simple_dram_test.free) != 0) { + rfree(data); + return -EINVAL; + } + + data->do_copy_data = false; + *ctx = data; + return 0; +} + +__cold static int simple_dram_test_case_process(void *ctx, struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks, + bool *do_copy) +{ + struct tester_module_simple_dram_test_data *data = ctx; + + assert_can_be_cold(); + + /* copy every second cycle */ + *do_copy = data->do_copy_data; + data->do_copy_data = !data->do_copy_data; + + return 0; +} + +__cold static int simple_dram_test_free(void *ctx, struct processing_module *mod) +{ + assert_can_be_cold(); + + rfree(ctx); + return 0; +} + +const struct tester_test_case_interface tester_interface_simple_dram_test = { + .init = simple_dram_test_case_init, + .process = simple_dram_test_case_process, + .free = simple_dram_test_free +}; diff --git a/src/debug/tester/tester_simple_dram_test.h b/src/debug/tester/tester_simple_dram_test.h new file mode 100644 index 000000000000..86febb54c06e --- /dev/null +++ b/src/debug/tester/tester_simple_dram_test.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + * Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + */ + +#ifndef TESTER_SIMPLE_DRAM_TEST +#define TESTER_SIMPLE_DRAM_TEST + +#include <stddef.h> +#include <stdint.h> + +#include "tester.h" + +extern const struct tester_test_case_interface tester_interface_simple_dram_test; + +#endif /* TESTER_DUMMY_TEST */ diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt index 1f080fae2f20..dc82ed66a737 100644 --- a/src/drivers/CMakeLists.txt +++ b/src/drivers/CMakeLists.txt @@ -4,8 +4,17 @@ if(CONFIG_IMX) add_subdirectory(imx) endif() -if(CONFIG_INTEL) - add_subdirectory(intel) +if(CONFIG_AMD) + add_subdirectory(amd) +endif() + +if(CONFIG_MEDIATEK) + add_subdirectory(mediatek) +endif() + +if(CONFIG_LIBRARY) + add_subdirectory(host) + return() endif() if(CONFIG_DW) diff --git a/src/drivers/Kconfig b/src/drivers/Kconfig index 1b41df48bf4b..7818bd74796b 100644 --- a/src/drivers/Kconfig +++ b/src/drivers/Kconfig @@ -2,9 +2,13 @@ menu "Drivers" -source "src/drivers/intel/cavs/Kconfig" +rsource "dw/Kconfig" -source "src/drivers/dw/Kconfig" +rsource "imx/Kconfig" + +rsource "mediatek/Kconfig" + +rsource "amd/Kconfig" config DUMMY_DMA bool "Dummy DMA (software DMA driver)" @@ -18,13 +22,6 @@ config DUMMY_DMA If unsure, select "n". -config IMX_EDMA - bool "i.MX EDMA driver" - default n - depends on IMX - help - Select this to enable support for i.MX EDMA DMA controller. - config IPC_POLLING bool "Enable IPC Polling support" default n diff --git a/src/drivers/amd/CMakeLists.txt b/src/drivers/amd/CMakeLists.txt new file mode 100644 index 000000000000..a6ece5e3a0ed --- /dev/null +++ b/src/drivers/amd/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause +add_subdirectory(common) +if(CONFIG_RENOIR) + add_subdirectory(renoir) +elseif(CONFIG_REMBRANDT OR CONFIG_ACP_6_3 OR CONFIG_ACP_7_0) + add_subdirectory(rembrandt) +elseif(CONFIG_VANGOGH) + add_subdirectory(vangogh) +endif() diff --git a/src/drivers/amd/Kconfig b/src/drivers/amd/Kconfig new file mode 100644 index 000000000000..15c7e0eb911d --- /dev/null +++ b/src/drivers/amd/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config AMD_BINARY_BUILD + bool + default n + help + Select this if the platform need firmware binaries. diff --git a/src/drivers/amd/common/CMakeLists.txt b/src/drivers/amd/common/CMakeLists.txt new file mode 100644 index 000000000000..4e74f474d72f --- /dev/null +++ b/src/drivers/amd/common/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + acp_dma.c + acp_bt_dai.c + acp_dmic_dai.c + ipc.c + timer.c + acp_sp_dma.c + acp_dmic_dma.c +) diff --git a/src/drivers/amd/common/acp_bt_dai.c b/src/drivers/amd/common/acp_bt_dai.c new file mode 100644 index 000000000000..9f5a79ce15f8 --- /dev/null +++ b/src/drivers/amd/common/acp_bt_dai.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> + +SOF_DEFINE_REG_UUID(btdai); + +DECLARE_TR_CTX(btdai_tr, SOF_UUID(btdai_uuid), LOG_LEVEL_INFO); + +static inline int btdai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + /* nothing to do */ + return 0; +} + +static int btdai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do */ + return 0; +} + +static int btdai_probe(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int btdai_remove(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int btdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Not a valid direction"); + return -EINVAL; + } +} + +static int btdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return dai->plat_data.fifo[direction].handshake; +} + +static int btdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, int dir) +{ + /* supported parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = ACP_DEFAULT_NUM_CHANNELS; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + return 0; +} + +const struct dai_driver acp_btdai_driver = { + .type = SOF_DAI_AMD_BT, + .uid = SOF_UUID(btdai_uuid), + .tctx = &btdai_tr, + .dma_dev = SOF_DMA_DEV_BT, + .dma_caps = SOF_DMA_CAP_BT, + .ops = { + .trigger = btdai_trigger, + .set_config = btdai_set_config, + .probe = btdai_probe, + .remove = btdai_remove, + .get_fifo = btdai_get_fifo, + .get_handshake = btdai_get_handshake, + .get_hw_params = btdai_get_hw_params, + }, +}; diff --git a/src/drivers/amd/common/acp_dma.c b/src/drivers/amd/common/acp_dma.c new file mode 100644 index 000000000000..bd1e6cba16a2 --- /dev/null +++ b/src/drivers/amd/common/acp_dma.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/audio/component.h> +#include <platform/chip_registers.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_offset_byte.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/acp_dma.h> +#include <sof/probe/probe.h> + +SOF_DEFINE_REG_UUID(acpdma); +DECLARE_TR_CTX(acpdma_tr, SOF_UUID(acpdma_uuid), LOG_LEVEL_INFO); +#define PROBE_UPDATE_POS_MASK 0x80000000 +#define PROBE_BUFFER_WATERMARK (16 * 1024) +static uint32_t probe_pos_update, probe_pos; + + +void dma_config_descriptor(uint32_t dscr_start_idx, uint32_t dscr_count, + acp_cfg_dma_descriptor_t *psrc_dscr, + acp_cfg_dma_descriptor_t *pdest_dscr) +{ + uint16_t dscr; + + if (dscr_count && psrc_dscr && pdest_dscr && + dscr_start_idx < MAX_NUM_DMA_DESC_DSCR) { + for (dscr = 0; dscr < dscr_count; dscr++) { + pdest_dscr[dscr_start_idx + dscr].src_addr = + psrc_dscr[dscr].src_addr; + pdest_dscr[dscr_start_idx + dscr].dest_addr = + psrc_dscr[dscr].dest_addr; + pdest_dscr[dscr_start_idx + dscr].trns_cnt.u32all = + psrc_dscr[dscr].trns_cnt.u32all; + } + } +} + +static struct dma_chan_data *acp_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acpdma_tr, "DMA: Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acpdma_tr, "DMA: channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + /* reset read and write pointers */ + struct acp_dma_chan_data *acp_dma_chan = dma_chan_get_data(channel); + + acp_dma_chan->config[req_chan].rd_size = 0; + acp_dma_chan->config[req_chan].wr_size = 0; + acp_dma_chan->config[req_chan].size = 0; + acp_dma_chan->config[req_chan].probe_channel = 0xFF; + if (dma->priv_data) { + acp_dma_chan->config[req_chan].probe_channel = *(uint32_t *)dma->priv_data; + if (acp_dma_chan->config[req_chan].probe_channel == channel->index) { + /*probe update pos & flag*/ + probe_pos_update = 0; + probe_pos = 0; + io_reg_write(PU_REGISTER_BASE + ACP_FUTURE_REG_ACLK_0, + PROBE_UPDATE_POS_MASK); + } + } + return channel; +} + +static void acp_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + struct acp_dma_chan_data *acp_dma_chan = dma_chan_get_data(channel); + + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); + /* reset read and write pointer */ + acp_dma_chan->config[channel->index].rd_size = 0; + acp_dma_chan->config[channel->index].wr_size = 0; + acp_dma_chan->config[channel->index].size = 0; + if (acp_dma_chan->config[channel->index].probe_channel == channel->index) { + acp_dma_chan->config[channel->index].probe_channel = 0XFF; + probe_pos_update = 0; + probe_pos = 0; + /*probe update pos & flag*/ + io_reg_write(PU_REGISTER_BASE + ACP_FUTURE_REG_ACLK_0, + PROBE_UPDATE_POS_MASK); + } +} + +/* Stop the requested channel */ +static int acp_dma_stop(struct dma_chan_data *channel) +{ + acp_dma_cntl_0_t dma_cntl; + acp_dma_ch_sts_t ch_sts; + uint32_t dmach_mask; + uint32_t delay_cnt = 10000; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; /* do not try to stop multiple times */ + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + dmach_mask = (1 << channel->index); + dma_cntl = (acp_dma_cntl_0_t)dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + /* Do the HW stop of the DMA */ + /* set DMAChRst bit to stop the transfer */ + dma_cntl.bits.dmachrun = 0; + dma_cntl.bits.dmachiocen = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + if (ch_sts.bits.dmachrunsts & dmach_mask) { + /* set the reset bit for this channel to stop the dma transfer */ + dma_cntl.bits.dmachrst = 1; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + } + + while (delay_cnt > 0) { + ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + if (!(ch_sts.bits.dmachrunsts & dmach_mask)) { + /* clear the reset flag after successfully stopping the dma transfer + * and break from the loop + */ + dma_cntl.bits.dmachrst = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + break; + } + delay_cnt--; + } + return 0; +} + +static int acp_dma_start(struct dma_chan_data *channel) +{ + acp_dma_cntl_0_t dma_cntl; + acp_dma_ch_sts_t dma_sts; + uint32_t chan_sts; +#ifdef __ZEPHYR__ + uint64_t deadline = sof_cycle_get_64() + k_us_to_cyc_ceil64(500); +#else + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; +#endif + if (channel->status != COMP_STATE_PREPARE && + channel->status != COMP_STATE_SUSPEND) + return -EINVAL; + channel->status = COMP_STATE_ACTIVE; + /* Clear DMAChRun before starting the DMA Ch */ + dma_cntl = (acp_dma_cntl_0_t)dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_cntl.bits.dmachiocen = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + + dma_cntl = (acp_dma_cntl_0_t)dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 1; + dma_cntl.bits.dmachiocen = 0; + + /* set dmachrun bit to start the transfer */ + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + + /* poll for the status bit + * to finish the dma transfer + * then initiate call back function + */ + do { + dma_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + chan_sts = dma_sts.u32all & (1 << channel->index); + if (!chan_sts) + return 0; +#ifdef __ZEPHYR__ + } while (sof_cycle_get_64() <= deadline); +#else + } while (platform_timer_get(timer) <= deadline); +#endif + + tr_err(&acpdma_tr, "acp-dma: timed out for dma start"); + + return -ETIME; +} + +static int acp_dma_release(struct dma_chan_data *channel) +{ + tr_info(&acpdma_tr, "DMA: release(%d)", channel->index); + if (channel->status != COMP_STATE_PAUSED) + return -EINVAL; + channel->status = COMP_STATE_ACTIVE; + return 0; +} + +static int acp_dma_pause(struct dma_chan_data *channel) +{ + tr_info(&acpdma_tr, "h/w pause is not supported, changing the status of(%d) channel", + channel->index); + if (channel->status != COMP_STATE_ACTIVE) + return -EINVAL; + channel->status = COMP_STATE_PAUSED; + return 0; +} + +static int acp_dma_copy(struct dma_chan_data *channel, int bytes, uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + acp_dma_ch_sts_t ch_sts; + struct acp_dma_chan_data *acp_dma_chan; + uint32_t dmach_mask = (1 << channel->index); + int ret = 0; + acp_dma_chan = dma_chan_get_data(channel); + if (channel->index != DMA_TRACE_CHANNEL) + amd_dma_reconfig(channel, bytes); + + ret = acp_dma_start(channel); + if (ret < 0) + return ret; + ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + while (ch_sts.bits.dmachrunsts & dmach_mask) + ch_sts = (acp_dma_ch_sts_t)dma_reg_read(channel->dma, ACP_DMA_CH_STS); + ret = acp_dma_stop(channel); + if (ret >= 0 && acp_dma_chan->config[channel->index].probe_channel == channel->index) { + probe_pos_update += bytes; + probe_pos += bytes; + if (probe_pos >= PROBE_BUFFER_WATERMARK) { + io_reg_write(PU_REGISTER_BASE + ACP_FUTURE_REG_ACLK_0, + PROBE_UPDATE_POS_MASK | probe_pos_update); + acp_dsp_to_host_intr_trig(); + probe_pos = 0; + } + } + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return ret; +} + +static int acp_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction) +{ + status->state = channel->status; + status->flags = 0; +#ifdef __ZEPHYR__ + status->timestamp = sof_cycle_get_64(); +#else + status->timestamp = timer_get_system(timer_get()); +#endif + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +static int acp_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t dir; + + channel->direction = config->direction; + dir = config->direction; + return dma_setup(channel, &config->elem_array, dir); +} + +static int acp_dma_probe(struct dma *dma) +{ + struct acp_dma_chan_data *acp_dma_chan; + int channel; + + if (dma->chan) { + tr_err(&acpdma_tr, "DMA: Already probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acpdma_tr, "DMA: unable to allocate channel context"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + acp_dma_chan = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct acp_dma_chan_data)); + if (!acp_dma_chan) { + rfree(dma->chan); + tr_err(&acpdma_tr, "acp-dma: %d channel %d private data alloc failed", + dma->plat_data.id, channel); + return -ENOMEM; + } + dma_chan_set_data(&dma->chan[channel], acp_dma_chan); + } + return 0; +} + +static int acp_dma_remove(struct dma *dma) +{ + int channel; + + if (!dma->chan) { + tr_err(&acpdma_tr, "DMA: Invalid remove call"); + return 0; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) + rfree(dma->chan[channel].priv_data); + rfree(dma->chan); + dma->chan = NULL; + + return 0; +} + +static int acp_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + + if (channel->status == COMP_STATE_INIT) + return 0; + + switch (cmd) { + case DMA_IRQ_STATUS_GET: + status = dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT) & 0xFF; + return status & (1 << channel->index); + case DMA_IRQ_CLEAR: + status = dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT); + status = status & (1 << channel->index); + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + status = dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + status = status & (~(1 << channel->index)); + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + status = dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + status = status | (1 << channel->index); + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} + +static int acp_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + struct acp_dma_chan_data *acp_dma_chan = dma_chan_get_data(channel); + uint32_t data_size = 0; + uint32_t tc = 0; /* transfer count in bytes */ + + tc = acp_dma_chan->config[channel->index].size; + data_size = (uint32_t)tc; + switch (channel->direction) { + case DMA_DIR_MEM_TO_DEV: + case DMA_DIR_HMEM_TO_LMEM: + *avail = ABS(data_size) / 2; + break; + case DMA_DIR_DEV_TO_MEM: + case DMA_DIR_LMEM_TO_HMEM: + *free = ABS(data_size) / 2; + break; + default: + tr_err(&acpdma_tr, "dma_get_data_size() Invalid direction %d", + channel->direction); + return -EINVAL; + } + return 0; +} + +const struct dma_ops acp_dma_ops = { + .channel_get = acp_dma_channel_get, + .channel_put = acp_dma_channel_put, + .start = acp_dma_start, + .stop = acp_dma_stop, + .pause = acp_dma_pause, + .release = acp_dma_release, + .copy = acp_dma_copy, + .status = acp_dma_status, + .set_config = acp_dma_set_config, + .probe = acp_dma_probe, + .remove = acp_dma_remove, + .interrupt = acp_dma_interrupt, + .get_attribute = acp_dma_get_attribute, + .get_data_size = acp_dma_get_data_size, +}; diff --git a/src/drivers/amd/common/acp_dmic_dai.c b/src/drivers/amd/common/acp_dmic_dai.c new file mode 100644 index 000000000000..18851843f005 --- /dev/null +++ b/src/drivers/amd/common/acp_dmic_dai.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023, 2026 AMD. All rights reserved. +// +// Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> +#include <platform/acp_dmic_dma.h> + +extern struct acp_dmic_silence acp_initsilence; + +SOF_DEFINE_REG_UUID(acp_dmic_dai); + +DECLARE_TR_CTX(acp_dmic_dai_tr, SOF_UUID(acp_dmic_dai_uuid), LOG_LEVEL_INFO); + +static inline int acp_dmic_dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + acp_wov_pdm_no_of_channels_t pdm_channels; + const struct sof_ipc_dai_config *config = spec_config; + struct acp_pdata *acpdata = dai_get_drvdata(dai); + acp_wov_clk_ctrl_t clk_ctrl; + + acpdata->config = *config; + acpdata->dmic_params = config->acpdmic; + clk_ctrl = (acp_wov_clk_ctrl_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + clk_ctrl.u32all = 0; + pdm_channels.u32all = io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_NO_OF_CHANNELS); + acp_initsilence.samplerate_khz = acpdata->dmic_params.pdm_rate / 1000; + switch (acpdata->dmic_params.pdm_rate) { + case 48000: + /* DMIC Clock for 48K sample rate */ + clk_ctrl.bits.brm_clk_ctrl = 7; + break; + case 16000: + /* DMIC Clock for 16K sample rate */ + clk_ctrl.bits.brm_clk_ctrl = 1; + break; + default: + dai_err(dai, "unsupported samplerate"); + return -EINVAL; + } + io_reg_write(PU_REGISTER_BASE + ACP_WOV_CLK_CTRL, clk_ctrl.u32all); + acp_initsilence.num_chs = acpdata->dmic_params.pdm_ch; + switch (acpdata->dmic_params.pdm_ch) { + case 2: + pdm_channels.bits.pdm_no_of_channels = 0; + break; + case 4: + pdm_channels.bits.pdm_no_of_channels = 1; + break; + default: + dai_err(dai, "acp_dmic_set_config unsupported channels"); + return -EINVAL; + } + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_NO_OF_CHANNELS, + pdm_channels.u32all); + return 0; +} + +static int acp_dmic_dai_trigger(struct dai *dai, int cmd, int direction) +{ + switch (cmd) { + case COMP_TRIGGER_START: + case COMP_TRIGGER_STOP: + default: + break; + } + return 0; +} + +static int acp_dmic_dai_probe(struct dai *dai) +{ + struct acp_pdata *acp; + + dai_info(dai, "dmic dai probe"); + /* allocate private data */ + acp = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*acp)); + if (!acp) { + dai_err(dai, "dmic dai probe alloc failed"); + return -ENOMEM; + } + dai_set_drvdata(dai, acp); + return 0; +} + +static int acp_dmic_dai_remove(struct dai *dai) +{ + struct acp_pdata *acp = dai_get_drvdata(dai); + + rfree(acp); + dai_set_drvdata(dai, NULL); + return 0; +} + +static int acp_dmic_dai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int acp_dmic_dai_get_handshake(struct dai *dai, int direction, + int stream_id) +{ + return dai->plat_data.fifo[direction].handshake; +} + +static int acp_dmic_dai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + switch (acpdata->dmic_params.pdm_rate) { + case 48000: + case 16000: + params->rate = acpdata->dmic_params.pdm_rate; + break; + default: + dai_err(dai, "unsupported samplerate %d", acpdata->dmic_params.pdm_rate); + return -EINVAL; + } + switch (acpdata->dmic_params.pdm_ch) { + case 2: + case 4: + params->channels = acpdata->dmic_params.pdm_ch; + break; + default: + dai_err(dai, "unsupported channels %d", acpdata->dmic_params.pdm_ch); + return -EINVAL; + } + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S32_LE; + acp_initsilence.bytes_per_sample = 4; + return 0; +} + +const struct dai_driver acp_dmic_dai_driver = { + .type = SOF_DAI_AMD_DMIC, + .uid = SOF_UUID(acp_dmic_dai_uuid), + .tctx = &acp_dmic_dai_tr, + .dma_dev = SOF_DMA_DEV_DMIC, + .dma_caps = SOF_DMA_CAP_DMIC, + .ops = { + .trigger = acp_dmic_dai_trigger, + .set_config = acp_dmic_dai_set_config, + .probe = acp_dmic_dai_probe, + .remove = acp_dmic_dai_remove, + .get_fifo = acp_dmic_dai_get_fifo, + .get_handshake = acp_dmic_dai_get_handshake, + .get_hw_params = acp_dmic_dai_get_hw_params, + }, +}; diff --git a/src/drivers/amd/common/acp_dmic_dma.c b/src/drivers/amd/common/acp_dmic_dma.c new file mode 100644 index 000000000000..70d371d62784 --- /dev/null +++ b/src/drivers/amd/common/acp_dmic_dma.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_dmic_dma.h> + +extern uint32_t dmic_rngbuff_size; +struct acp_dmic_silence acp_initsilence; + +SOF_DEFINE_REG_UUID(acp_dmic_dma_common); +DECLARE_TR_CTX(acp_dmic_dma_tr, SOF_UUID(acp_dmic_dma_common_uuid), LOG_LEVEL_INFO); + +/* allocate next free DMA channel */ +static struct dma_chan_data *acp_dmic_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_dmic_dma_tr, "Channel %d out of range", + req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_dmic_dma_tr, "Cannot reuse channel %d", + req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + return channel; +} + +static void acp_dmic_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dmic_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + tr_dbg(&acp_dmic_dma_tr, "dmic dma release()"); + return 0; +} + +static int acp_dmic_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + tr_dbg(&acp_dmic_dma_tr, "dmic dma pause()"); + return 0; +} + +static int acp_dmic_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + acp_wov_pdm_dma_enable_t pdm_dma_enable; + + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + return (int)(pdm_dma_enable.bits.pdm_dma_en_status); +} + +static int acp_dmic_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + uint32_t i; + uint32_t j; + int numsamples; + char *dmic_rngbuff_addr2 = acp_initsilence.dmic_rngbuff_addr1; + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + if (acp_initsilence.silence_incr < acp_initsilence.silence_cnt) { + if (acp_initsilence.silence_incr & 1) + dmic_rngbuff_addr2 = acp_initsilence.dmic_rngbuff_addr1 + + (dmic_rngbuff_size >> 1); + for (i = 0; i < (dmic_rngbuff_size >> 1); i++) + dmic_rngbuff_addr2[i] = 0; + acp_initsilence.silence_incr++; + } else if (acp_initsilence.silence_incr < acp_initsilence.silence_cnt + + acp_initsilence.numfilterbuffers) { + numsamples = (dmic_rngbuff_size >> 1) / (acp_initsilence.num_chs * + acp_initsilence.bytes_per_sample); + if (acp_initsilence.silence_incr & 1) + dmic_rngbuff_addr2 = acp_initsilence.dmic_rngbuff_addr1 + + (dmic_rngbuff_size >> 1); + acp_initsilence.dmic_rngbuff_iaddr = (int *)dmic_rngbuff_addr2; + for (i = 0; i < numsamples * acp_initsilence.num_chs; + i += acp_initsilence.num_chs, acp_initsilence.coeff++) { + for (j = 0; j < acp_initsilence.num_chs; j++) { + acp_initsilence.dmic_rngbuff_iaddr[i + j] = + (acp_initsilence.dmic_rngbuff_iaddr[i + j] / + (numsamples * acp_initsilence.numfilterbuffers)) * + acp_initsilence.coeff; + } + } + acp_initsilence.silence_incr++; + } + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dmic_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_dmic_dma_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_dmic_dma_tr, "unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dmic_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_dmic_dma_tr, "remove called without probe"); + return 0; + } + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +static int acp_dmic_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_DEV_TO_MEM) { + *avail = dmic_rngbuff_size >> 1; + *free = dmic_rngbuff_size >> 1; + } else { + tr_err(&acp_dmic_dma_tr, "Channel direction Not defined %d", + channel->direction); + } + + tr_info(&acp_dmic_dma_tr, "avail %d and free %d", + avail[0], free[0]); + return 0; +} + +static int acp_dmic_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT); + status = acp_intr_stat.bits.wov_dma_stat; + return status; + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.wov_dma_stat = 1; + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.wov_dma_intr_mask = 0; + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.wov_dma_intr_mask = 1; + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dmic_dma_ops = { + .channel_get = acp_dmic_dma_channel_get, + .channel_put = acp_dmic_dma_channel_put, + .start = acp_dmic_dma_start, + .stop = acp_dmic_dma_stop, + .pause = acp_dmic_dma_pause, + .release = acp_dmic_dma_release, + .copy = acp_dmic_dma_copy, + .status = acp_dmic_dma_status, + .set_config = acp_dmic_dma_set_config, + .interrupt = acp_dmic_dma_interrupt, + .probe = acp_dmic_dma_probe, + .remove = acp_dmic_dma_remove, + .get_data_size = acp_dmic_dma_get_data_size, + .get_attribute = acp_dmic_dma_get_attribute, +}; diff --git a/src/drivers/amd/common/acp_sp_dma.c b/src/drivers/amd/common/acp_sp_dma.c new file mode 100644 index 000000000000..fd431ba7b4b7 --- /dev/null +++ b/src/drivers/amd/common/acp_sp_dma.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_sp_dma.h> + +SOF_DEFINE_REG_UUID(acp_sp_common); +DECLARE_TR_CTX(acp_sp_tr, SOF_UUID(acp_sp_common_uuid), LOG_LEVEL_INFO); + +/* allocate next free DMA channel */ +static struct dma_chan_data *acp_dai_sp_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_sp_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_sp_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_sp_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dai_sp_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do */ + return 0; +} + +static int acp_dai_sp_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do */ + return 0; +} + +static int acp_dai_sp_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do */ + return 0; +} + +static int acp_dai_sp_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dai_sp_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_sp_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_sp_tr, "Probe failure,unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_sp_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_sp_tr, "remove called without probe,it's a no-op"); + return 0; + } + + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +const struct dma_ops acp_dai_sp_dma_ops = { + .channel_get = acp_dai_sp_dma_channel_get, + .channel_put = acp_dai_sp_dma_channel_put, + .start = acp_dai_sp_dma_start, + .stop = acp_dai_sp_dma_stop, + .pause = acp_dai_sp_dma_pause, + .release = acp_dai_sp_dma_release, + .copy = acp_dai_sp_dma_copy, + .status = acp_dai_sp_dma_status, + .set_config = acp_dai_sp_dma_set_config, + .interrupt = acp_dai_sp_dma_interrupt, + .probe = acp_dai_sp_dma_probe, + .remove = acp_dai_sp_dma_remove, + .get_data_size = acp_dai_sp_dma_get_data_size, + .get_attribute = acp_dai_sp_dma_get_attribute, +}; diff --git a/src/drivers/amd/common/ipc.c b/src/drivers/amd/common/ipc.c new file mode 100644 index 000000000000..fbb0ebdb1492 --- /dev/null +++ b/src/drivers/amd/common/ipc.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/platform.h> +#include <platform/ipc.h> + +SOF_DEFINE_REG_UUID(ipc_task_amd); + +extern volatile acp_scratch_mem_config_t *pscratch_mem_cfg; + +inline uint32_t sof_ipc_host_status(void) +{ + return (pscratch_mem_cfg->acp_host_ack_write | pscratch_mem_cfg->acp_host_msg_write); +} + +inline uint32_t sof_ipc_host_msg_flag(void) +{ + return pscratch_mem_cfg->acp_host_msg_write; +} + +inline uint32_t sof_ipc_host_ack_flag(void) +{ + return pscratch_mem_cfg->acp_host_ack_write; +} + +inline uint32_t sof_ipc_dsp_status(void) +{ + return (pscratch_mem_cfg->acp_dsp_msg_write | pscratch_mem_cfg->acp_dsp_ack_write); +} + +inline void sof_ipc_host_ack_clear(void) +{ + pscratch_mem_cfg->acp_host_ack_write = 0; +} + +inline void sof_ipc_host_msg_clear(void) +{ + pscratch_mem_cfg->acp_host_msg_write = 0; +} + +inline void sof_ipc_dsp_ack_set(void) +{ + pscratch_mem_cfg->acp_dsp_ack_write = 1; +} + +inline void sof_ipc_dsp_msg_set(void) +{ + pscratch_mem_cfg->acp_dsp_msg_write = 1; +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; + + hdr = mailbox_validate(); + ipc_cmd(hdr); + return SOF_TASK_STATE_COMPLETED; +} + +int platform_ipc_init(struct ipc *ipc) +{ + ipc_set_drvdata(ipc, NULL); + /* schedule */ + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_amd_uuid), + &ipc_task_ops, ipc, 0, 0); + interrupt_disable(IRQ_NUM_EXT_LEVEL3, ipc); + interrupt_register(IRQ_NUM_EXT_LEVEL3, amd_irq_handler, ipc); + /* Enabling software interuppts */ + interrupt_enable(IRQ_NUM_EXT_LEVEL3, ipc); + return 0; +} diff --git a/src/drivers/amd/common/timer.c b/src/drivers/amd/common/timer.c new file mode 100644 index 000000000000..e2fa9d3d9e6c --- /dev/null +++ b/src/drivers/amd/common/timer.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <xtensa/config/core-isa.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/component.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <ipc/stream.h> +#include <errno.h> +#include <stdint.h> + +void platform_timer_start(struct timer *timer) +{ + /* Nothing to do here */ +} + +void platform_timer_stop(struct timer *timer) +{ + arch_timer_disable(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks) +{ + return arch_timer_set(timer, ticks); +} + +void platform_timer_clear(struct timer *timer) +{ + arch_timer_clear(timer); +} + +uint64_t platform_timer_get(struct timer *timer) +{ + return arch_timer_get_system(timer); +} + +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return arch_timer_get_system(timer); +} + +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + int err; + + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; +} + +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + posn->wallclock = timer_get_system(timer_get()) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; +} + +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = timer_get_system(timer_get()); +} + +int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) +{ + switch (timer->id) { + case TIMER0: + case TIMER1: + return arch_timer_register(timer, handler, arg); + default: + return -EINVAL; + } +} + +void timer_unregister(struct timer *timer, void *arg) +{ + interrupt_unregister(timer->irq, arg); +} + +void timer_enable(struct timer *timer, void *arg, int core) +{ + interrupt_enable(timer->irq, arg); +} + +void timer_disable(struct timer *timer, void *arg, int core) +{ + interrupt_disable(timer->irq, arg); +} diff --git a/src/drivers/amd/rembrandt/CMakeLists.txt b/src/drivers/amd/rembrandt/CMakeLists.txt new file mode 100644 index 000000000000..08b13df744d2 --- /dev/null +++ b/src/drivers/amd/rembrandt/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + acp_dma.c + acp_sp_dai.c + acp_hs_dai.c + acp_sw_audio_dai.c + interrupt.c + ipc.c + acp_bt_dma.c + acp_sp_dma.c + acp_hs_dma.c + acp_sw_audio_dma.c + acp_dmic_dma.c +) diff --git a/src/drivers/amd/rembrandt/acp_bt_dma.c b/src/drivers/amd/rembrandt/acp_bt_dma.c new file mode 100644 index 000000000000..ecf85027528a --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_bt_dma.c @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +SOF_DEFINE_REG_UUID(acp_bt_dma); + +DECLARE_TR_CTX(acp_bt_dma_tr, SOF_UUID(acp_bt_dma_uuid), LOG_LEVEL_INFO); + +/* DMA number of buffer periods */ +#define BT_FIFO_SIZE 768 +#define BT_TX_FIFO_ADDR (BT_FIFO_SIZE * 3) +#define BT_RX_FIFO_ADDR (BT_TX_FIFO_ADDR + BT_FIFO_SIZE) + +/* ACP DMA transfer size */ +#define ACP_BT_DMA_TRANS_SIZE 128 +#define BT_IER_DISABLE 0x0 + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t bt_buff_size; + +/* Allocate requested DMA channel if it is free */ +static struct dma_chan_data *acp_dai_bt_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_bt_dma_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_bt_dma_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_bt_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dai_bt_dma_start(struct dma_chan_data *channel) +{ + acp_bttdm_ier_t bt_ier; + acp_bttdm_iter_t bt_tdm_iter; + acp_bttdm_irer_t bt_tdm_irer; + uint32_t acp_pdm_en; + + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_ITER)); + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!bt_tdm_iter.bits.bttdm_txen && !bt_tdm_irer.bits.bttdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + bt_ier = (acp_bttdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IER); + bt_ier.bits.bttdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); + bt_tdm_iter.u32all = 0; + bt_tdm_iter.bits.bttdm_txen = 1; + bt_tdm_iter.bits.bttdm_tx_protocol_mode = 0; + bt_tdm_iter.bits.bttdm_tx_data_path_mode = 1; + bt_tdm_iter.bits.bttdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_ITER), bt_tdm_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + bt_ier = (acp_bttdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IER); + bt_ier.bits.bttdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); + bt_tdm_irer.u32all = 0; + bt_tdm_irer.bits.bttdm_rx_en = 1; + bt_tdm_irer.bits.bttdm_rx_protocol_mode = 0; + bt_tdm_irer.bits.bttdm_rx_data_path_mode = 1; + bt_tdm_irer.bits.bttdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IRER), bt_tdm_irer.u32all); + } else { + tr_err(&acp_bt_dma_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + + +static int acp_dai_bt_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + return 0; +} + +static int acp_dai_bt_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + return 0; +} + +static int acp_dai_bt_dma_stop(struct dma_chan_data *channel) +{ + acp_bttdm_iter_t bt_tdm_iter; + acp_bttdm_irer_t bt_tdm_irer; + uint32_t acp_pdm_en; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_ITER); + bt_tdm_iter.bits.bttdm_txen = 0; + io_reg_write(PU_REGISTER_BASE + ACP_BTTDM_ITER, bt_tdm_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IRER); + bt_tdm_irer.bits.bttdm_rx_en = 0; + io_reg_write(PU_REGISTER_BASE + ACP_BTTDM_IRER, bt_tdm_irer.u32all); + } else { + tr_err(&acp_bt_dma_tr, "direction not defined %d", channel->direction); + return -EINVAL; + } + + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_ITER); + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IRER); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!bt_tdm_iter.bits.bttdm_txen && !bt_tdm_irer.bits.bttdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), BT_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + } + + return 0; +} + +/* fill in "status" with current DMA channel state and position */ +static int acp_dai_bt_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do on rembrandt */ + return 0; +} + +/* set the DMA channel configuration + * source/target address + * DMA transfer sizes + */ +static int acp_dai_bt_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t bt_ringbuff_addr; + uint32_t bt_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_bt_dma_tr, "cyclic configurations only supported"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_bt_dma_tr, "scatter enabled, that is not supported for now"); + return -EINVAL; + } + + channel->is_scheduling_source = true; + channel->direction = config->direction; + bt_buff_size = config->elem_array.elems[0].size * config->elem_array.count; + + switch (config->direction) { + case DMA_DIR_MEM_TO_DEV: + + /* BT Transmit FIFO Address and FIFO Size */ + bt_fifo_addr = BT_TX_FIFO_ADDR; + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_TX_FIFOADDR), bt_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_TX_FIFOSIZE), (uint32_t)(BT_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size */ + config->elem_array.elems[0].src = + (config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK); + bt_ringbuff_addr = (config->elem_array.elems[0].src | ACP_SRAM); + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_TX_RINGBUFADDR), bt_ringbuff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_TX_RINGBUFSIZE), bt_buff_size); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + /* Watermark size for BT transfer fifo */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_TX_INTR_WATERMARK_SIZE), + (bt_buff_size >> 1)); + break; + case DMA_DIR_DEV_TO_MEM: + + /* BT Receive FIFO Address and FIFO Size*/ + bt_fifo_addr = BT_RX_FIFO_ADDR; + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_RX_FIFOADDR), bt_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_RX_FIFOSIZE), (uint32_t)(BT_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size */ + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + bt_ringbuff_addr = (config->elem_array.elems[0].dest | ACP_SRAM); + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_RX_RINGBUFADDR), bt_ringbuff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_RX_RINGBUFSIZE), bt_buff_size); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + /* Watermark size for BT receive fifo */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_BT_RX_INTR_WATERMARK_SIZE), + (bt_buff_size >> 1)); + break; + default: + tr_err(&acp_bt_dma_tr, "unsupported config direction"); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_bt_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dai_bt_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_bt_dma_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_bt_dma_tr, "Probe failure, unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_bt_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_bt_dma_tr, "remove called without probe, it's a no-op"); + return 0; + } + + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +static int acp_dai_bt_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > bt_buff_size ? + (curr_tx_pos - prev_tx_pos) % bt_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = bt_buff_size - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = bt_buff_size >> 1; + *avail = bt_buff_size >> 1; +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > bt_buff_size ? + (curr_rx_pos - prev_rx_pos) % bt_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = bt_buff_size - *free; + prev_rx_pos = curr_rx_pos; +#else + *free = bt_buff_size >> 1; + *avail = bt_buff_size >> 1; +#endif + } else { + tr_err(&acp_bt_dma_tr, "Channel direction Not defined %d", + channel->direction); + return -EINVAL; + } + return 0; +} + +static int acp_dai_bt_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} + +static int acp_dai_bt_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + (dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT1)); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1<<channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT1, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL1); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL1, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL1); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL1, status); + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dai_bt_dma_ops = { + .channel_get = acp_dai_bt_dma_channel_get, + .channel_put = acp_dai_bt_dma_channel_put, + .start = acp_dai_bt_dma_start, + .stop = acp_dai_bt_dma_stop, + .pause = acp_dai_bt_dma_pause, + .release = acp_dai_bt_dma_release, + .copy = acp_dai_bt_dma_copy, + .status = acp_dai_bt_dma_status, + .set_config = acp_dai_bt_dma_set_config, + .interrupt = acp_dai_bt_dma_interrupt, + .probe = acp_dai_bt_dma_probe, + .remove = acp_dai_bt_dma_remove, + .get_data_size = acp_dai_bt_dma_get_data_size, + .get_attribute = acp_dai_bt_dma_get_attribute, +}; diff --git a/src/drivers/amd/rembrandt/acp_dma.c b/src/drivers/amd/rembrandt/acp_dma.c new file mode 100644 index 000000000000..ef94d92dcfd8 --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_dma.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/audio/component.h> +#include <platform/chip_registers.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_offset_byte.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/acp_dma.h> + +void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes) +{ + uint32_t strt_idx = 0; + uint32_t src = 0; + uint32_t dest = 0; + uint32_t tail = 0, head = 0; + uint32_t src1 = 0; + uint32_t dest1 = 0; + + acp_cfg_dma_descriptor_t psrc_dscr[ACP_MAX_STREAMS]; + acp_cfg_dma_descriptor_t *pdest_dscr; + acp_dma_cntl_0_t dma_cntl; + struct acp_dma_chan_data *acp_dma_chan; + struct acp_dma_config *dma_cfg; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + acp_dma_chan = dma_chan_get_data(channel); + dma_cfg = &acp_dma_chan->config[channel->index]; + pdest_dscr = (acp_cfg_dma_descriptor_t *)(pscratch_mem_cfg->acp_cfg_dma_descriptor); + if (channel->direction == DMA_DIR_HMEM_TO_LMEM) { + head = bytes; + /* Update the read and write pointers */ + dma_cfg->rd_ptr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off + dma_cfg->rd_size; + dma_cfg->wr_ptr = dma_cfg->base + dma_cfg->wr_size; + src = dma_cfg->rd_ptr; + dest = dma_cfg->wr_ptr; + psrc_dscr[strt_idx].src_addr = src; + dest = (dest & ACP_DRAM_ADDRESS_MASK); + /* Known Data hack */ + psrc_dscr[strt_idx].dest_addr = (dest | ACP_SRAM); + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = bytes; + /* Configure a single descrption */ + dma_config_descriptor(strt_idx, 1, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 1); + /* Check for wrap-around case for system buffer */ + if (dma_cfg->rd_size + bytes > dma_cfg->sys_buff_size) { + /* Configure the descriptor for head and tail */ + /* values for the wrap around case */ + tail = dma_cfg->sys_buff_size - dma_cfg->rd_size; + head = bytes - tail; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].src_addr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off; + dest1 = dest+tail; + dest1 = (dest1 & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx + 1].dest_addr = (dest1 | ACP_SRAM); + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->rd_size = 0; + } + /* Check for wrap-around case for host buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->size) { + tail = dma_cfg->size - dma_cfg->wr_size; + head = bytes - tail; + + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + + psrc_dscr[strt_idx + 1].dest_addr = + ((dma_cfg->base & ACP_DRAM_ADDRESS_MASK) | ACP_SRAM); + + src1 = src + tail; + psrc_dscr[strt_idx + 1].src_addr = src1; + + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + + dma_cfg->rd_size += head; + dma_cfg->rd_size %= dma_cfg->sys_buff_size; + dma_cfg->wr_size += bytes; + dma_cfg->wr_size %= dma_cfg->size; + } else if (channel->direction == DMA_DIR_LMEM_TO_HMEM) { + head = bytes; + dma_cfg->wr_ptr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off + dma_cfg->wr_size; + dma_cfg->rd_ptr = dma_cfg->base + dma_cfg->rd_size; + src = dma_cfg->rd_ptr; + dest = dma_cfg->wr_ptr; + src = (src & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx].src_addr = (src | ACP_SRAM); + psrc_dscr[strt_idx].dest_addr = dest; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = bytes; + /* Configure a single descrption */ + dma_config_descriptor(strt_idx, 1, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 1); + /* Check for wrap-around case for system buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->sys_buff_size) { + /* Configure the descriptor for head and + * tail values for the wrap around case + */ + tail = dma_cfg->sys_buff_size - dma_cfg->wr_size; + head = bytes - tail; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + src1 = src + tail; + psrc_dscr[strt_idx+1].dest_addr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off; + psrc_dscr[strt_idx+1].trns_cnt.bits.trns_cnt = head; + src1 = (src1 & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx+1].src_addr = (src1 | ACP_SRAM); + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + dma_cfg->wr_size += head; + dma_cfg->wr_size %= dma_cfg->sys_buff_size; + dma_cfg->rd_size += bytes; + dma_cfg->rd_size %= dma_cfg->size; + } + /* clear the dma channel control bits */ + dma_cntl = (acp_dma_cntl_0_t) dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + /* Load start index of decriptor and priority */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_STRT_IDX_0, strt_idx); + dma_chan_reg_write(channel, ACP_DMA_PRIO_0, 1); + channel->status = COMP_STATE_PREPARE; +} + +/* Some set_config helper functions */ +int dma_setup(struct dma_chan_data *channel, + struct dma_sg_elem_array *sgelems, uint32_t dir) +{ + uint32_t dscr_cnt, dscr = 0; + uint32_t tc; + uint16_t dscr_strt_idx = 0; + uint32_t *phy_off; + uint32_t *syst_buff_size; + uint32_t src; + uint32_t dest; + uint32_t buff_size = 0; + acp_dma_cntl_0_t dma_cntl; + struct acp_dma_config *dma_cfg; + struct acp_dma_chan_data *acp_dma_chan = dma_chan_get_data(channel); + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + dscr_cnt = sgelems->count; + /* Trace uses descriptor from index seven */ + /* and other streams use descriptors from zero */ + if (channel->index == DMA_TRACE_CHANNEL) + dscr_strt_idx = DMA_TRACE_CHANNEL; + else + dscr_strt_idx = 0; + + /* ACP DMA Descriptor in scratch memory */ + acp_cfg_dma_descriptor_t *dma_config_dscr; + + dma_config_dscr = (acp_cfg_dma_descriptor_t *)(pscratch_mem_cfg->acp_cfg_dma_descriptor); + /* physical offset of system memory */ + phy_off = (uint32_t *)(pscratch_mem_cfg->phy_offset); + /* size of system memory buffer */ + syst_buff_size = (uint32_t *)(pscratch_mem_cfg->syst_buff_size); + for (dscr = 0; dscr < dscr_cnt; dscr++) { + if (dir == DMA_DIR_HMEM_TO_LMEM) { + if (channel->index != DMA_TRACE_CHANNEL) + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + (phy_off[channel->index] + ACP_SYST_MEM_WINDOW + buff_size); + else + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + sgelems->elems[dscr].src + ACP_SYST_MEM_WINDOW; + dest = sgelems->elems[dscr].dest; + dest = (dest & ACP_DRAM_ADDRESS_MASK); + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = (dest | ACP_SRAM); + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + } else { + if (channel->index != DMA_TRACE_CHANNEL) + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + (phy_off[channel->index] + ACP_SYST_MEM_WINDOW + buff_size); + else + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + (sgelems->elems[dscr].dest + ACP_SYST_MEM_WINDOW); + src = sgelems->elems[dscr].src; + src = (src & ACP_DRAM_ADDRESS_MASK); + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + (src | ACP_SRAM);/*rembrandt-arch*/ + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + } + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + buff_size = sgelems->elems[dscr].size; + } + dma_config_dscr[dscr_strt_idx + (dscr-1)].trns_cnt.bits.ioc = 0; + dma_cfg = &acp_dma_chan->config[channel->index]; + /* bytes of data to be transferred for the dma */ + tc = dma_config_dscr[dscr_strt_idx].trns_cnt.bits.trns_cnt; + /* DMA configuration for stream */ + if (channel->index != DMA_TRACE_CHANNEL) { + if (!dma_cfg->size) { + acp_dma_chan->dir = dir; + acp_dma_chan->idx = channel->index; + dma_cfg->phy_off = phy_off[channel->index]; + dma_cfg->size = tc * dscr_cnt; + dma_cfg->sys_buff_size = syst_buff_size[channel->index]; + + if (dir == DMA_DIR_HMEM_TO_LMEM) { + /* Playback */ + dma_config_dscr[dscr_strt_idx].dest_addr = + (dma_config_dscr[dscr_strt_idx].dest_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = + dma_config_dscr[dscr_strt_idx].dest_addr | ACP_SRAM; + dma_cfg->wr_size = 0; + dma_cfg->rd_size = dma_cfg->size; + } else { + /* Capture */ + dma_config_dscr[dscr_strt_idx].src_addr = + (dma_config_dscr[dscr_strt_idx].src_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = dma_config_dscr[dscr_strt_idx].src_addr | ACP_SRAM; + dma_cfg->rd_size = 0; + if (channel->index == dma_cfg->probe_channel) + dma_cfg->wr_size = 0; + else + dma_cfg->wr_size = dma_cfg->size; + } + } + } + /* clear the dma channel control bits */ + dma_cntl = (acp_dma_cntl_0_t) dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_cntl.bits.dmachiocen = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + + /* Program DMAChDscrStrIdx to the index + * number of the first descriptor to be processed. + */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_STRT_IDX_0, dscr_strt_idx); + /* program DMAChDscrdscrcnt to the + * number of descriptors to be processed in the transfer + */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, dscr_cnt); + /* set DMAChPrioLvl according to the priority */ + dma_chan_reg_write(channel, ACP_DMA_PRIO_0, 1); + channel->status = COMP_STATE_PREPARE; + return 0; +} + +int acp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} diff --git a/src/drivers/amd/rembrandt/acp_dmic_dma.c b/src/drivers/amd/rembrandt/acp_dmic_dma.c new file mode 100644 index 000000000000..b0577d2544fe --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_dmic_dma.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_dmic_dma.h> + +SOF_DEFINE_REG_UUID(acp_dmic_dma); +DECLARE_TR_CTX(acp_dmic_dma_rmb_tr, SOF_UUID(acp_dmic_dma_uuid), LOG_LEVEL_INFO); + +uint32_t dmic_rngbuff_size; +extern struct acp_dmic_silence acp_initsilence; + +int acp_dmic_dma_start(struct dma_chan_data *channel) +{ + acp_wov_pdm_decimation_factor_t deci_fctr; + acp_wov_misc_ctrl_t wov_misc_ctrl; + acp_wov_pdm_dma_enable_t pdm_dma_enable; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + uint32_t acp_pdm_en; +#ifdef __ZEPHYR__ + uint64_t deadline = sof_cycle_get_64() + k_us_to_cyc_ceil64(500); +#else + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; +#endif + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + acp_initsilence.silence_incr = 0; + acp_initsilence.coeff = 0; + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + channel->status = COMP_STATE_ACTIVE; + if (channel->direction == DMA_DIR_DEV_TO_MEM) { + /* Decimation Factor */ + deci_fctr.u32all = 2; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DECIMATION_FACTOR, + deci_fctr.u32all); + /* PDM Control */ + wov_misc_ctrl = (acp_wov_misc_ctrl_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_MISC_CTRL); + wov_misc_ctrl.u32all |= 0x10; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_MISC_CTRL, + wov_misc_ctrl.u32all); + /* PDM Enable */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE, 1); + /* PDM DMA Enable */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE, 1); + /* Check the PDM DMA Enable status bit */ + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + while (!(uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) { +#ifdef __ZEPHYR__ + if (deadline < sof_cycle_get_64()) +#else + if (deadline < platform_timer_get(timer)) +#endif + + { + /* safe check in case we've got preempted after read */ + if ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) + return 0; + tr_err(&acp_dmic_dma_rmb_tr, "timed out for dma start"); + return -ETIME; + } + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + } + } + return 0; +} + +int acp_dmic_dma_stop(struct dma_chan_data *channel) +{ + acp_wov_pdm_dma_enable_t pdm_dma_enable; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + uint32_t acp_pdm_en; +#ifdef __ZEPHYR__ + uint64_t deadline = sof_cycle_get_64() + k_us_to_cyc_ceil64(500); +#else + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; +#endif + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + /* Disable PDM DMA */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE, 0); + /* Disable PDM */ + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + /* Check PDM DMA Status */ + while ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) { +#ifdef __ZEPHYR__ + if (deadline < sof_cycle_get_64()) +#else + if (deadline < platform_timer_get(timer)) +#endif + { + /* safe check in case we've got preempted after read */ + if ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) + return 0; + tr_err(&acp_dmic_dma_rmb_tr, "timed out for dma stop"); + return -ETIME; + } + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + } + /* Disable PDM */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE, 0); + /* Clear PDM FIFO */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_FIFO_FLUSH, 1); + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !acp_pdm_en) { + /* Request SMU to set aclk to minimum aclk */ + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dmic_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t ring_buff_addr; + uint32_t timeperiod_ms; + acp_wov_rx_ringbufsize_t dmic_ringbuff_size; + acp_wov_rx_intr_watermark_size_t watermark; + + channel->is_scheduling_source = true; + channel->direction = config->direction; + switch (config->direction) { + case DMA_DIR_DEV_TO_MEM: + case DMA_DIR_MEM_TO_DEV: + acp_initsilence.dmic_rngbuff_addr1 = (char *)config->elem_array.elems[0].dest; + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + ring_buff_addr = (config->elem_array.elems[0].dest | ACP_SRAM); + /* Load Ring buffer address */ + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_RINGBUFADDR, ring_buff_addr); + /* Load Ring buffer Size */ + dmic_rngbuff_size = (config->elem_array.elems[0].size * + config->elem_array.count); + dmic_ringbuff_size.bits.rx_ringbufsize = dmic_rngbuff_size; + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_RINGBUFSIZE, dmic_ringbuff_size.u32all); + /* Write the ring buffer size to register */ + watermark.bits.rx_intr_watermark_size = (dmic_rngbuff_size >> 1); + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_INTR_WATERMARK_SIZE, watermark.u32all); + + timeperiod_ms = dmic_rngbuff_size / (acp_initsilence.num_chs * + acp_initsilence.samplerate_khz * acp_initsilence.bytes_per_sample * + config->elem_array.count); + acp_initsilence.silence_cnt = DMIC_SETTLING_TIME_MS / timeperiod_ms; + acp_initsilence.numfilterbuffers = DMIC_SMOOTH_TIME_MS / timeperiod_ms; + + break; + default: + tr_err(&acp_dmic_dma_rmb_tr, "unsupported config direction"); + return -EINVAL; + } + if (!config->cyclic) { + tr_err(&acp_dmic_dma_rmb_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_dmic_dma_rmb_tr, "scatter enabled, not supported for now!"); + return -EINVAL; + } + return 0; +} + +int acp_dmic_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} diff --git a/src/drivers/amd/rembrandt/acp_hs_dai.c b/src/drivers/amd/rembrandt/acp_hs_dai.c new file mode 100644 index 000000000000..bc1579d3f4d8 --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_hs_dai.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> + +SOF_DEFINE_REG_UUID(hsdai); +DECLARE_TR_CTX(hsdai_tr, SOF_UUID(hsdai_uuid), LOG_LEVEL_INFO); + +#if defined(__ZEPHYR__) +#define interrupt_get_irq mux_interrupt_get_irq +#endif + +static inline int hsdai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + const struct sof_ipc_dai_config *config = spec_config; + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + acp_i2stdm_mstrclkgen_t i2stdm_mstrclkgen; + + acpdata->config = *config; + acpdata->params = config->acphs; + i2stdm_mstrclkgen.u32all = io_reg_read(PU_REGISTER_BASE + ACP_I2STDM2_MSTRCLKGEN); + i2stdm_mstrclkgen.bits.i2stdm_master_mode = 1; + switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { + case SOF_DAI_FMT_DSP_A: + i2stdm_mstrclkgen.bits.i2stdm_format_mode = 1; + switch (acpdata->params.tdm_slots) { + case 2: + i2stdm_mstrclkgen.bits.i2stdm_lrclk_div_val = 0x20; + i2stdm_mstrclkgen.bits.i2stdm_bclk_div_val = 0x80; + break; + case 4: + i2stdm_mstrclkgen.bits.i2stdm_lrclk_div_val = 0x40; + i2stdm_mstrclkgen.bits.i2stdm_bclk_div_val = 0x40; + break; + case 6: + i2stdm_mstrclkgen.bits.i2stdm_lrclk_div_val = 0x60; + i2stdm_mstrclkgen.bits.i2stdm_bclk_div_val = 0x30; + break; + case 8: + i2stdm_mstrclkgen.bits.i2stdm_lrclk_div_val = 0x80; + i2stdm_mstrclkgen.bits.i2stdm_bclk_div_val = 0x20; + break; + default: + dai_err(dai, "unsupported slots"); + return -EINVAL; + } + break; + case SOF_DAI_FMT_I2S: + i2stdm_mstrclkgen.bits.i2stdm_format_mode = 0; + i2stdm_mstrclkgen.bits.i2stdm_lrclk_div_val = 0x20; + i2stdm_mstrclkgen.bits.i2stdm_bclk_div_val = 0x80; + break; + default: + dai_err(dai, "invalid format"); + return -EINVAL; + } + + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + /* set master clk for hs dai */ + io_reg_write(PU_REGISTER_BASE + ACP_I2STDM2_MSTRCLKGEN, i2stdm_mstrclkgen.u32all); + switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { + case SOF_DAI_FMT_DSP_A: + { + acp_hstdm_txfrmt_t i2stdm_txfrmt; + acp_hstdm_rxfrmt_t i2stdm_rxfrmt; + + i2stdm_txfrmt.u32all = io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_TXFRMT); + i2stdm_txfrmt.bits.hstdm_num_slots = acpdata->params.tdm_slots; + i2stdm_txfrmt.bits.hstdm_slot_len = 16; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_TXFRMT), i2stdm_txfrmt.u32all); + + hs_iter.bits.hstdm_tx_protocol_mode = 1; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_ITER), hs_iter.u32all); + + i2stdm_rxfrmt.u32all = io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_RXFRMT); + i2stdm_rxfrmt.bits.hstdm_num_slots = acpdata->params.tdm_slots; + i2stdm_rxfrmt.bits.hstdm_slot_len = 16; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_RXFRMT), i2stdm_rxfrmt.u32all); + + hs_irer.bits.hstdm_rx_protocol_mode = 1; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IRER), hs_irer.u32all); + } + break; + case SOF_DAI_FMT_I2S: + hs_iter.bits.hstdm_tx_protocol_mode = 0; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_ITER), hs_iter.u32all); + + hs_irer.bits.hstdm_rx_protocol_mode = 0; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IRER), hs_irer.u32all); + break; + default: + dai_err(dai, "invalid format"); + return -EINVAL; + } + return 0; +} + +static int hsdai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do on rembrandt for HS dai */ + return 0; +} + +static int hsdai_probe(struct dai *dai) +{ + struct acp_pdata *acp; + + dai_info(dai, "HS dai probe"); + /* allocate private data */ + acp = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*acp)); + if (!acp) { + dai_err(dai, "HS dai probe alloc failed"); + return -ENOMEM; + } + dai_set_drvdata(dai, acp); + return 0; +} + +static int hsdai_remove(struct dai *dai) +{ + struct acp_pdata *acp = dai_get_drvdata(dai); + + rfree(acp); + dai_set_drvdata(dai, NULL); + + return 0; +} + +static int hsdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int hsdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + int handshake = dai->plat_data.fifo[direction].handshake; + + interrupt_get_irq(handshake, "irqsteer1"); + return dai->plat_data.fifo[direction].handshake; +} + +static int hsdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + if (dir == DAI_DIR_PLAYBACK) { + /* SP DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = acpdata->params.tdm_slots; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + } else if (dir == DAI_DIR_CAPTURE) { + /* SP DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = acpdata->params.tdm_slots; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + } + + return 0; +} + +const struct dai_driver acp_hsdai_driver = { + .type = SOF_DAI_AMD_HS, + .uid = SOF_UUID(hsdai_uuid), + .tctx = &hsdai_tr, + .dma_dev = SOF_DMA_DEV_SP, + .dma_caps = SOF_DMA_CAP_SP, + .ops = { + .trigger = hsdai_trigger, + .set_config = hsdai_set_config, + .probe = hsdai_probe, + .remove = hsdai_remove, + .get_fifo = hsdai_get_fifo, + .get_handshake = hsdai_get_handshake, + .get_hw_params = hsdai_get_hw_params, + }, +}; diff --git a/src/drivers/amd/rembrandt/acp_hs_dma.c b/src/drivers/amd/rembrandt/acp_hs_dma.c new file mode 100644 index 000000000000..fbed6593ad55 --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_hs_dma.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +SOF_DEFINE_REG_UUID(acp_hs); +DECLARE_TR_CTX(acp_hs_tr, SOF_UUID(acp_hs_uuid), LOG_LEVEL_INFO); + +#define HS_FIFO_SIZE 512 +#define HS_TX_FIFO_ADDR 0x0 +#define HS_RX_FIFO_ADDR (HS_TX_FIFO_ADDR+HS_FIFO_SIZE) +#define HS_IER_DISABLE 0x0 + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t hs_buff_size_playback; +static uint32_t hs_buff_size_capture; +/* allocate next free DMA channel */ +static struct dma_chan_data *acp_dai_hs_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_hs_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_hs_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_hs_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); + +} + +static int acp_dai_hs_dma_start(struct dma_chan_data *channel) +{ + acp_hstdm_ier_t hs_ier; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + uint32_t acp_pdm_en; + + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !acp_pdm_en) { + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); +#ifdef CONFIG_ACP_6_3 + if (!io_reg_read(PU_REGISTER_BASE + ACP_I2S_196MHZ_CLK_SEL)) + io_reg_write((PU_REGISTER_BASE + ACP_I2S_196MHZ_CLK_SEL), 0x1); +#endif + } + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + hs_ier = (acp_hstdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_IER); + hs_ier.bits.hstdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IER), hs_ier.u32all); + hs_iter.bits.hstdm_txen = 1; + hs_iter.bits.hstdm_tx_data_path_mode = 1; + hs_iter.bits.hstdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_ITER), hs_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + hs_ier = (acp_hstdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_IER); + hs_ier.bits.hstdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IER), hs_ier.u32all); + hs_irer.bits.hstdm_rx_en = 1; + hs_irer.bits.hstdm_rx_data_path_mode = 1; + hs_irer.bits.hstdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IRER), hs_irer.u32all); + } else { + tr_err(&acp_hs_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + + +static int acp_dai_hs_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + return 0; +} + +static int acp_dai_hs_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + return 0; +} + +static int acp_dai_hs_dma_stop(struct dma_chan_data *channel) +{ + acp_hstdm_irer_t hs_irer; + acp_hstdm_iter_t hs_iter; + uint32_t acp_pdm_en; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + hs_iter = (acp_hstdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_ITER); + hs_iter.bits.hstdm_txen = 0; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_ITER), hs_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_READY; + hs_irer = (acp_hstdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_IRER); + hs_irer.bits.hstdm_rx_en = 0; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IRER), hs_irer.u32all); + } else { + tr_err(&acp_hs_tr, "Stop direction not defined %d", channel->direction); + return -EINVAL; + } + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IER), HS_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + acp_change_clock_notify(0); +#ifdef CONFIG_ACP_6_3 + if (io_reg_read(PU_REGISTER_BASE + ACP_I2S_196MHZ_CLK_SEL)) + io_reg_write((PU_REGISTER_BASE + ACP_I2S_196MHZ_CLK_SEL), 0x0); +#endif + } + } + return 0; +} + +static int acp_dai_hs_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do on rembrandt */ + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +static int acp_dai_hs_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t hs_buff_addr; + uint32_t hs_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_hs_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_hs_tr, "scatter enabled, that is not supported for now!"); + return -EINVAL; + } + + channel->is_scheduling_source = true; + channel->direction = config->direction; + + if (config->direction == DMA_DIR_MEM_TO_DEV) { + + hs_buff_size_playback = config->elem_array.elems[0].size * config->elem_array.count; + /* HS Transmit FIFO Address and FIFO Size*/ + hs_fifo_addr = HS_TX_FIFO_ADDR; + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_TX_FIFOADDR), hs_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_TX_FIFOSIZE), (uint32_t)(HS_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size*/ + config->elem_array.elems[0].src = (config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK); + hs_buff_addr = (config->elem_array.elems[0].src | ACP_SRAM); + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_TX_RINGBUFADDR), hs_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_TX_RINGBUFSIZE), hs_buff_size_playback); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + + /* Watermark size for HS transmit FIFO - Half of HS buffer size */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_TX_INTR_WATERMARK_SIZE), + (hs_buff_size_playback >> 1)); + + } else if (config->direction == DMA_DIR_DEV_TO_MEM) { + + hs_buff_size_capture = config->elem_array.elems[0].size * config->elem_array.count; + /* HS Receive FIFO Address and FIFO Size*/ + hs_fifo_addr = HS_RX_FIFO_ADDR; + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_RX_FIFOADDR), hs_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_RX_FIFOSIZE), + (uint32_t)(HS_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size*/ + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + hs_buff_addr = (config->elem_array.elems[0].dest | ACP_SRAM); + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_RX_RINGBUFADDR), hs_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_RX_RINGBUFSIZE), hs_buff_size_capture); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + + /* Watermark size for receive fifo - Half of HS buffer size*/ + io_reg_write((PU_REGISTER_BASE + ACP_P1_HS_RX_INTR_WATERMARK_SIZE), + (hs_buff_size_capture >> 1)); + + } else { + tr_err(&acp_hs_tr, "Config channel direction undefined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_hs_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dai_hs_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_hs_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_hs_tr, "Probe failure,unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_hs_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_hs_tr, "remove called without probe,it's a no-op"); + return 0; + } + + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +static int acp_dai_hs_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high<<32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > hs_buff_size_playback ? + (curr_tx_pos - prev_tx_pos) % hs_buff_size_playback : + (curr_tx_pos - prev_tx_pos); + *avail = hs_buff_size_playback - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = (hs_buff_size_playback >> 1); + *avail = (hs_buff_size_playback >> 1); +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high<<32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > hs_buff_size_capture ? + (curr_rx_pos - prev_rx_pos) % hs_buff_size_capture : + (curr_rx_pos - prev_rx_pos); + *avail = hs_buff_size_capture - *free; + prev_rx_pos = curr_rx_pos; +#else + *free = (hs_buff_size_capture >> 1); + *avail = (hs_buff_size_capture >> 1); +#endif + } else { + tr_err(&acp_hs_tr, "Channel direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + +static int acp_dai_hs_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; + } + return 0; +} + +static int acp_dai_hs_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat1_t acp_intr_stat1; + acp_dsp0_intr_cntl1_t acp_intr_cntl1; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat1 = (acp_dsp0_intr_stat1_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT1); + status = acp_intr_stat1.bits.audio_buffer_int_stat; + return (status & (1<<channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat1.u32all = 0; + acp_intr_stat1.bits.audio_buffer_int_stat = + (1 << channel->index); + status = acp_intr_stat1.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT1, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl1 = (acp_dsp0_intr_cntl1_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL1); + acp_intr_cntl1.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl1.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL1, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl1 = (acp_dsp0_intr_cntl1_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL1); + acp_intr_cntl1.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl1.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL1, status); + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dai_hs_dma_ops = { + .channel_get = acp_dai_hs_dma_channel_get, + .channel_put = acp_dai_hs_dma_channel_put, + .start = acp_dai_hs_dma_start, + .stop = acp_dai_hs_dma_stop, + .pause = acp_dai_hs_dma_pause, + .release = acp_dai_hs_dma_release, + .copy = acp_dai_hs_dma_copy, + .status = acp_dai_hs_dma_status, + .set_config = acp_dai_hs_dma_set_config, + .interrupt = acp_dai_hs_dma_interrupt, + .probe = acp_dai_hs_dma_probe, + .remove = acp_dai_hs_dma_remove, + .get_data_size = acp_dai_hs_dma_get_data_size, + .get_attribute = acp_dai_hs_dma_get_attribute, +}; + diff --git a/src/drivers/amd/rembrandt/acp_sp_dai.c b/src/drivers/amd/rembrandt/acp_sp_dai.c new file mode 100644 index 000000000000..1dc5facc1533 --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_sp_dai.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> + +SOF_DEFINE_REG_UUID(spdai); +DECLARE_TR_CTX(spdai_tr, SOF_UUID(spdai_uuid), LOG_LEVEL_INFO); + +static inline int spdai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + /* nothing to do on rembrandt for SP dai */ + return 0; +} + +static int spdai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do on rembrandt for SP dai */ + return 0; +} + +static int spdai_probe(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int spdai_remove(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int spdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int spdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return dai->plat_data.fifo[direction].handshake; +} + +static int spdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + /* SP DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = ACP_DEFAULT_NUM_CHANNELS; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + return 0; +} + +const struct dai_driver acp_spdai_driver = { + .type = SOF_DAI_AMD_SP, + .uid = SOF_UUID(spdai_uuid), + .tctx = &spdai_tr, + .dma_dev = SOF_DMA_DEV_SP, + .dma_caps = SOF_DMA_CAP_SP, + .ops = { + .trigger = spdai_trigger, + .set_config = spdai_set_config, + .probe = spdai_probe, + .remove = spdai_remove, + .get_fifo = spdai_get_fifo, + .get_handshake = spdai_get_handshake, + .get_hw_params = spdai_get_hw_params, + }, +}; diff --git a/src/drivers/amd/rembrandt/acp_sp_dma.c b/src/drivers/amd/rembrandt/acp_sp_dma.c new file mode 100644 index 000000000000..423e364e879f --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_sp_dma.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_sp_dma.h> + +SOF_DEFINE_REG_UUID(acp_sp); +DECLARE_TR_CTX(acp_sp_rmb_tr, SOF_UUID(acp_sp_uuid), LOG_LEVEL_INFO); + +#define SP_TX_FIFO_ADDR (SP_FIFO_SIZE * 2) +#define SP_RX_FIFO_ADDR (SP_TX_FIFO_ADDR+SP_FIFO_SIZE) + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t sp_buff_size; + +int acp_dai_sp_dma_start(struct dma_chan_data *channel) +{ + acp_i2stdm_ier_t sp_ier; + acp_i2stdm_iter_t sp_iter; + acp_i2stdm_irer_t sp_irer; + uint32_t acp_pdm_en; + + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + sp_ier = (acp_i2stdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IER); + sp_ier.bits.i2stdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), sp_ier.u32all); + sp_iter.bits.i2stdm_txen = 1; + sp_iter.bits.i2stdm_tx_protocol_mode = 0; + sp_iter.bits.i2stdm_tx_data_path_mode = 1; + sp_iter.bits.i2stdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + sp_ier = (acp_i2stdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IER); + sp_ier.bits.i2stdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), sp_ier.u32all); + sp_irer.bits.i2stdm_rx_en = 1; + sp_irer.bits.i2stdm_rx_protocol_mode = 0; + sp_irer.bits.i2stdm_rx_data_path_mode = 1; + sp_irer.bits.i2stdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } else { + tr_err(&acp_sp_rmb_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +int acp_dai_sp_dma_stop(struct dma_chan_data *channel) +{ + acp_i2stdm_irer_t sp_irer; + acp_i2stdm_iter_t sp_iter; + uint32_t acp_pdm_en; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + sp_iter = (acp_i2stdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_ITER); + sp_iter.bits.i2stdm_txen = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + sp_irer = (acp_i2stdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IRER); + sp_irer.bits.i2stdm_rx_en = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } else { + tr_err(&acp_sp_rmb_tr, "Stop direction not defined %d", channel->direction); + return -EINVAL; + } + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), SP_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + } + + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t sp_buff_addr; + uint32_t sp_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_sp_rmb_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_sp_rmb_tr, "scatter enabled, that is not supported for now!"); + return -EINVAL; + } + + channel->is_scheduling_source = true; + channel->direction = config->direction; + sp_buff_size = config->elem_array.elems[0].size * config->elem_array.count; + + if (config->direction == DMA_DIR_MEM_TO_DEV) { + + /* SP Transmit FIFO Address and FIFO Size*/ + sp_fifo_addr = SP_TX_FIFO_ADDR; + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_TX_FIFOADDR), sp_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_TX_FIFOSIZE), (uint32_t)(SP_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size*/ + config->elem_array.elems[0].src = (config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK); + sp_buff_addr = (config->elem_array.elems[0].src | ACP_SRAM); + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_TX_RINGBUFADDR), sp_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_TX_RINGBUFSIZE), sp_buff_size); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + + /* Watermark size for SP transmit FIFO - Half of SP buffer size */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_TX_INTR_WATERMARK_SIZE), + (sp_buff_size >> 1)); + + } else if (config->direction == DMA_DIR_DEV_TO_MEM) { + + /* SP Receive FIFO Address and FIFO Size*/ + sp_fifo_addr = SP_RX_FIFO_ADDR; + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_RX_FIFOADDR), sp_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_RX_FIFOSIZE), + (uint32_t)(SP_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size*/ + config->elem_array.elems[0].dest = (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + sp_buff_addr = (config->elem_array.elems[0].dest | ACP_SRAM); + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_RX_RINGBUFADDR), sp_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_RX_RINGBUFSIZE), sp_buff_size); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + + /* Watermark size for SP receive fifo - Half of SP buffer size*/ + io_reg_write((PU_REGISTER_BASE + ACP_P1_I2S_RX_INTR_WATERMARK_SIZE), + (sp_buff_size >> 1)); + + } else { + tr_err(&acp_sp_rmb_tr, "DMA Config channel direction undefined %d", + channel->direction); + return -EINVAL; + } + + return 0; +} + +int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high<<32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > sp_buff_size ? + (curr_tx_pos - prev_tx_pos) % sp_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = sp_buff_size - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = (sp_buff_size >> 1); + *avail = (sp_buff_size >> 1); +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high<<32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > sp_buff_size ? + (curr_rx_pos - prev_rx_pos) % sp_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = sp_buff_size - *free; + prev_rx_pos = curr_rx_pos; +#else + *free = (sp_buff_size >> 1); + *avail = (sp_buff_size >> 1); +#endif + } else { + tr_err(&acp_sp_rmb_tr, "Channel direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + +int acp_dai_sp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; + } + return 0; +} + +int acp_dai_sp_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT1); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1<<channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = + (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT1, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL1); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL1, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL1); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL1, status); + return 0; + default: + return -EINVAL; + } +} diff --git a/src/drivers/amd/rembrandt/acp_sw_audio_dai.c b/src/drivers/amd/rembrandt/acp_sw_audio_dai.c new file mode 100644 index 000000000000..bcee323a2303 --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_sw_audio_dai.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Maruthi Machani <maruthi.machani@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +SOF_DEFINE_REG_UUID(swaudiodai); + +DECLARE_TR_CTX(swaudiodai_tr, SOF_UUID(swaudiodai_uuid), LOG_LEVEL_INFO); + +static inline int swaudiodai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + const struct sof_ipc_dai_config *config = spec_config; + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + acpdata->config = *config; + acpdata->sdw_params = config->acpsdw; + + return 0; +} + +static int swaudiodai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do on rembrandt for SW dai */ + return 0; +} + +static int swaudiodai_probe(struct dai *dai) +{ + struct acp_pdata *acp; + + dai_info(dai, "#$AMD$# SW dai probe"); + /* allocate private data */ + acp = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*acp)); + if (!acp) { + dai_err(dai, "SW dai probe alloc failed"); + return -ENOMEM; + } + dai_set_drvdata(dai, acp); + + return 0; +} + +static int swaudiodai_remove(struct dai *dai) +{ + struct acp_pdata *acp = dai_get_drvdata(dai); + + dai_info(dai, "entry"); + rfree(acp); + dai_set_drvdata(dai, NULL); + + return 0; +} + +static int swaudiodai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int swaudiodai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + int handshake = dai->plat_data.fifo[direction].handshake; + + interrupt_get_irq(handshake, "irqsteer1"); + + return dai->plat_data.fifo[direction].handshake; +} + +static int swaudiodai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + /* DAI currently supports only these parameters */ + params->rate = acpdata->sdw_params.rate; + params->channels = acpdata->sdw_params.channels; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + + return 0; +} + +const struct dai_driver acp_swaudiodai_driver = { + .type = SOF_DAI_AMD_SDW, + .uid = SOF_UUID(swaudiodai_uuid), + .tctx = &swaudiodai_tr, + .dma_dev = DMA_DEV_SW, + .dma_caps = DMA_CAP_SW, + .ops = { + .trigger = swaudiodai_trigger, + .set_config = swaudiodai_set_config, + .probe = swaudiodai_probe, + .remove = swaudiodai_remove, + .get_fifo = swaudiodai_get_fifo, + .get_handshake = swaudiodai_get_handshake, + .get_hw_params = swaudiodai_get_hw_params, + }, +}; + diff --git a/src/drivers/amd/rembrandt/acp_sw_audio_dma.c b/src/drivers/amd/rembrandt/acp_sw_audio_dma.c new file mode 100644 index 000000000000..25c72c9c0fff --- /dev/null +++ b/src/drivers/amd/rembrandt/acp_sw_audio_dma.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: BSD-3-Clause// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Maruthi Machani <maruthi.machani@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/notifier.h> +#include <platform/chip_registers.h> +#include <rtos/wait.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +#if defined(CONFIG_ACP_6_3) || defined(CONFIG_ACP_7_0) + +SOF_DEFINE_REG_UUID(acp_sw_audio); + +DECLARE_TR_CTX(acp_sw_audio_tr, SOF_UUID(acp_sw_audio_uuid), LOG_LEVEL_INFO); + +#if defined(CONFIG_ACP_6_3) +#define DMA_CH_COUNT 8 +#elif defined(CONFIG_ACP_7_0) +#define DMA_CH_COUNT 12 +#endif + +//initialization of soundwire-0 fifos(Audio, BT and HS) +#define SW0_AUDIO_FIFO_SIZE 128 +#define SW0_AUDIO_TX_FIFO_ADDR 0 +#define SW0_AUDIO_RX_FIFO_ADDR (SW0_AUDIO_TX_FIFO_ADDR + SW0_AUDIO_FIFO_SIZE) + +#define SW0_BT_FIFO_SIZE 128 +#define SW0_BT_TX_FIFO_ADDR (SW0_AUDIO_RX_FIFO_ADDR + SW0_AUDIO_FIFO_SIZE) +#define SW0_BT_RX_FIFO_ADDR (SW0_BT_TX_FIFO_ADDR + SW0_BT_FIFO_SIZE) + +#define SW0_HS_FIFO_SIZE 128 +#define SW0_HS_TX_FIFO_ADDR (SW0_BT_RX_FIFO_ADDR + SW0_BT_FIFO_SIZE) +#define SW0_HS_RX_FIFO_ADDR (SW0_HS_TX_FIFO_ADDR + SW0_HS_FIFO_SIZE) + +//initialization of soundwire-1 fifos(Audio, BT and HS) +#define SW1_AUDIO_FIFO_SIZE 128 +#define SW1_AUDIO_TX_FIFO_ADDR (SW0_HS_RX_FIFO_ADDR + SW0_HS_FIFO_SIZE) +#define SW1_AUDIO_RX_FIFO_ADDR (SW1_AUDIO_TX_FIFO_ADDR + SW1_AUDIO_FIFO_SIZE) + +#define SW1_BT_FIFO_SIZE 128 +#define SW1_BT_TX_FIFO_ADDR (SW1_AUDIO_RX_FIFO_ADDR + SW1_AUDIO_FIFO_SIZE) +#define SW1_BT_RX_FIFO_ADDR (SW1_BT_TX_FIFO_ADDR + SW1_BT_FIFO_SIZE) + +#define SW1_HS_FIFO_SIZE 128 +#define SW1_HS_TX_FIFO_ADDR (SW1_BT_RX_FIFO_ADDR + SW1_BT_FIFO_SIZE) +#define SW1_HS_RX_FIFO_ADDR (SW1_HS_TX_FIFO_ADDR + SW1_HS_FIFO_SIZE) + +static uint32_t sw_audio_buff_size_playback; +static uint32_t sw_audio_buff_size_capture; + +struct sw_dev_register { + uint32_t sw_dev_en; + uint32_t sw_dev_en_status; + uint32_t sw_dev_fifo_addr; + uint32_t fifo_addr; + uint32_t sw_dev_fifo_size; + uint32_t fifo_size; + uint32_t sw_dev_ringbuff_addr; + uint32_t sw_dev_ringbuff_size; + uint32_t sw_dev_dma_size; + uint32_t sw_dev_dma_watermark; + uint32_t sw_dev_dma_intr_status; + uint32_t sw_dev_dma_intr_cntl; + uint32_t statusindex; +}; + +static struct sw_dev_register sw_dev[DMA_CH_COUNT] = { +{ACP_SW_HS_RX_EN, ACP_SW_HS_RX_EN_STATUS, ACP_HS_RX_FIFOADDR, SW0_HS_RX_FIFO_ADDR, +ACP_HS_RX_FIFOSIZE, SW0_HS_FIFO_SIZE, ACP_HS_RX_RINGBUFADDR, ACP_HS_RX_RINGBUFSIZE, +ACP_HS_RX_DMA_SIZE, ACP_HS_RX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT, ACP_DSP0_INTR_CNTL, 0}, + +{ACP_SW_HS_TX_EN, ACP_SW_HS_TX_EN_STATUS, ACP_HS_TX_FIFOADDR, SW0_HS_TX_FIFO_ADDR, +ACP_HS_TX_FIFOSIZE, SW0_HS_FIFO_SIZE, ACP_HS_TX_RINGBUFADDR, ACP_HS_TX_RINGBUFSIZE, +ACP_HS_TX_DMA_SIZE, ACP_HS_TX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT, ACP_DSP0_INTR_CNTL, 1}, + +{ACP_P1_SW_BT_RX_EN, ACP_P1_SW_BT_RX_EN_STATUS, ACP_P1_BT_RX_FIFOADDR, SW1_BT_RX_FIFO_ADDR, +ACP_P1_BT_RX_FIFOSIZE, SW1_BT_FIFO_SIZE, ACP_P1_BT_RX_RINGBUFADDR, ACP_P1_BT_RX_RINGBUFSIZE, +ACP_P1_BT_RX_DMA_SIZE, ACP_P1_BT_RX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT1, ACP_DSP0_INTR_CNTL1, +2}, + +{ACP_P1_SW_BT_TX_EN, ACP_P1_SW_BT_TX_EN_STATUS, ACP_P1_BT_TX_FIFOADDR, SW1_BT_TX_FIFO_ADDR, +ACP_P1_BT_TX_FIFOSIZE, SW1_BT_FIFO_SIZE, ACP_P1_BT_TX_RINGBUFADDR, ACP_P1_BT_TX_RINGBUFSIZE, +ACP_P1_BT_TX_DMA_SIZE, ACP_P1_BT_TX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT1, ACP_DSP0_INTR_CNTL1, +3}, + +{ACP_SW_AUDIO_RX_EN, ACP_SW_AUDIO_RX_EN_STATUS, ACP_AUDIO_RX_FIFOADDR, SW0_AUDIO_RX_FIFO_ADDR, +ACP_AUDIO_RX_FIFOSIZE, SW0_AUDIO_FIFO_SIZE, ACP_AUDIO_RX_RINGBUFADDR, ACP_AUDIO_RX_RINGBUFSIZE, +ACP_AUDIO_RX_DMA_SIZE, ACP_AUDIO_RX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT, ACP_DSP0_INTR_CNTL, 4}, + +{ACP_SW_AUDIO_TX_EN, ACP_SW_AUDIO_TX_EN_STATUS, ACP_AUDIO_TX_FIFOADDR, SW0_AUDIO_TX_FIFO_ADDR, +ACP_AUDIO_TX_FIFOSIZE, SW0_AUDIO_FIFO_SIZE, ACP_AUDIO_TX_RINGBUFADDR, ACP_AUDIO_TX_RINGBUFSIZE, +ACP_AUDIO_TX_DMA_SIZE, ACP_AUDIO_TX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT, ACP_DSP0_INTR_CNTL, 5}, + +{ACP_SW_BT_RX_EN, ACP_SW_BT_RX_EN_STATUS, ACP_BT_RX_FIFOADDR, SW0_BT_RX_FIFO_ADDR, +ACP_BT_RX_FIFOSIZE, SW0_BT_FIFO_SIZE, ACP_BT_RX_RINGBUFADDR, ACP_BT_RX_RINGBUFSIZE, +ACP_BT_RX_DMA_SIZE, ACP_BT_RX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT, ACP_DSP0_INTR_CNTL, 2}, + +{ACP_SW_BT_TX_EN, ACP_SW_BT_TX_EN_STATUS, ACP_BT_TX_FIFOADDR, SW0_BT_TX_FIFO_ADDR, +ACP_BT_TX_FIFOSIZE, SW0_BT_FIFO_SIZE, ACP_BT_TX_RINGBUFADDR, ACP_BT_TX_RINGBUFSIZE, +ACP_BT_TX_DMA_SIZE, ACP_BT_TX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT, ACP_DSP0_INTR_CNTL, 3}, + +#if defined(CONFIG_ACP_7_0) +{ACP_P1_SW_AUDIO_RX_EN, ACP_P1_SW_AUDIO_RX_EN_STATUS, ACP_P1_AUDIO_RX_FIFOADDR, +SW1_AUDIO_RX_FIFO_ADDR, ACP_P1_AUDIO_RX_FIFOSIZE, SW1_AUDIO_FIFO_SIZE, +ACP_P1_AUDIO_RX_RINGBUFADDR, ACP_P1_AUDIO_RX_RINGBUFSIZE, ACP_P1_AUDIO_RX_DMA_SIZE, +ACP_P1_AUDIO_RX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT1, ACP_DSP0_INTR_CNTL1, 4}, + +{ACP_P1_SW_AUDIO_TX_EN, ACP_P1_SW_AUDIO_TX_EN_STATUS, ACP_P1_AUDIO_TX_FIFOADDR, +SW1_AUDIO_TX_FIFO_ADDR, ACP_P1_AUDIO_TX_FIFOSIZE, SW1_AUDIO_FIFO_SIZE, +ACP_P1_AUDIO_TX_RINGBUFADDR, ACP_P1_AUDIO_TX_RINGBUFSIZE, ACP_P1_AUDIO_TX_DMA_SIZE, +ACP_P1_AUDIO_TX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT1, ACP_DSP0_INTR_CNTL1, 5}, + +{ACP_P1_SW_HEADSET_RX_EN, ACP_P1_SW_HEADSET_RX_EN_STATUS, ACP_P1_HS_RX_FIFOADDR, +SW1_HS_RX_FIFO_ADDR, ACP_P1_HS_RX_FIFOSIZE, SW1_HS_FIFO_SIZE, +ACP_P1_HS_RX_RINGBUFADDR, ACP_P1_HS_RX_RINGBUFSIZE, ACP_P1_HS_RX_DMA_SIZE, +ACP_P1_HS_RX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT1, ACP_DSP0_INTR_CNTL1, 0}, + +{ACP_P1_SW_HEADSET_TX_EN, ACP_P1_SW_HEADSET_TX_EN_STATUS, ACP_P1_HS_TX_FIFOADDR, +SW1_HS_TX_FIFO_ADDR, ACP_P1_HS_TX_FIFOSIZE, SW1_HS_FIFO_SIZE, +ACP_P1_HS_TX_RINGBUFADDR, ACP_P1_HS_TX_RINGBUFSIZE, ACP_P1_HS_TX_DMA_SIZE, +ACP_P1_HS_TX_INTR_WATERMARK_SIZE, ACP_DSP0_INTR_STAT1, ACP_DSP0_INTR_CNTL1, 1}, +#endif +}; + +/* allocate next free DMA channel */ +static struct dma_chan_data *acp_dai_sw_audio_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_sw_audio_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_sw_audio_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_sw_audio_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dai_sw_audio_dma_start(struct dma_chan_data *channel) +{ + uint32_t sw0_audio_tx_en = 0; + uint32_t sw0_audio_rx_en = 0; + uint32_t acp_pdm_en; + int i; + + for (i = 0; i < DMA_CH_COUNT; i += 2) { + sw0_audio_tx_en |= io_reg_read(PU_REGISTER_BASE + sw_dev[i].sw_dev_en); + sw0_audio_rx_en |= io_reg_read(PU_REGISTER_BASE + sw_dev[i + 1].sw_dev_en); + } + + acp_pdm_en = io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + if (!sw0_audio_tx_en && !sw0_audio_rx_en && !acp_pdm_en) { + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + io_reg_write(PU_REGISTER_BASE + ACP_CLKMUX_SEL, ACP_ACLK_CLK_SEL); + } + + switch (channel->direction) { + case DMA_DIR_MEM_TO_DEV: + case DMA_DIR_DEV_TO_MEM: + channel->status = COMP_STATE_ACTIVE; + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_en, 1); + poll_for_register_delay(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_en_status, + 0x1, 0x1, 15); + break; + default: + tr_err(&acp_sw_audio_tr, "Start direction not defined %d", + channel->direction); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_sw_audio_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + return 0; +} + +static int acp_dai_sw_audio_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on rembrandt */ + return 0; +} + +static int acp_dai_sw_audio_dma_stop(struct dma_chan_data *channel) +{ + uint32_t sw0_audio_tx_en = 0; + uint32_t sw0_audio_rx_en = 0; + uint32_t acp_pdm_en; + int i; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + switch (channel->direction) { + case DMA_DIR_MEM_TO_DEV: + case DMA_DIR_DEV_TO_MEM: + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_en, 0); + poll_for_register_delay(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_en_status, + 0x1, 0x0, 15); + break; + default: + tr_err(&acp_sw_audio_tr, "Stop direction not defined %d", + channel->direction); + return -EINVAL; + } + + for (i = 0; i < DMA_CH_COUNT; i += 2) { + sw0_audio_tx_en |= io_reg_read(PU_REGISTER_BASE + sw_dev[i].sw_dev_en); + sw0_audio_rx_en |= io_reg_read(PU_REGISTER_BASE + sw_dev[i + 1].sw_dev_en); + } + acp_pdm_en = io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!sw0_audio_tx_en && !sw0_audio_rx_en) { + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + io_reg_write(PU_REGISTER_BASE + ACP_CLKMUX_SEL, ACP_INTERNAL_CLK_SEL); + acp_change_clock_notify(0); + } + } + + return 0; +} + +static int acp_dai_sw_audio_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do on rembrandt */ + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +static int acp_dai_sw_audio_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t sw0_audio_ringbuff_addr; + uint32_t sw0_audio_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_sw_audio_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_sw_audio_tr, "scatter enabled, that is not supported for now!"); + return -EINVAL; + } + + channel->is_scheduling_source = true; + channel->direction = config->direction; + + switch (channel->direction) { + case DMA_DIR_MEM_TO_DEV: + sw_audio_buff_size_playback = config->elem_array.elems[0].size * + config->elem_array.count; + /* SW Transmit FIFO Address and FIFO Size*/ + sw0_audio_fifo_addr = sw_dev[channel->index].fifo_addr; + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_fifo_addr, + sw0_audio_fifo_addr); + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_fifo_size, + sw_dev[channel->index].fifo_size); + + /* Transmit RINGBUFFER Address and size*/ + config->elem_array.elems[0].src = (config->elem_array.elems[0].src & + ACP_DRAM_ADDRESS_MASK); + sw0_audio_ringbuff_addr = (config->elem_array.elems[0].src | ACP_SRAM); + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_ringbuff_addr, + sw0_audio_ringbuff_addr); + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_ringbuff_size, + sw_audio_buff_size_playback); + + /* Transmit DMA transfer size in bytes */ + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_dma_size, + (uint32_t)(64/*ACP_DMA_TRANS_SIZE_128*/)); + + /* Watermark size for SW transmit FIFO - Half of SW buffer size */ + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_dma_watermark, + (sw_audio_buff_size_playback >> 1)); + break; + case DMA_DIR_DEV_TO_MEM: + sw_audio_buff_size_capture = config->elem_array.elems[0].size * + config->elem_array.count; + /* SW Receive FIFO Address and FIFO Size*/ + sw0_audio_fifo_addr = sw_dev[channel->index].fifo_addr; + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_fifo_addr, + sw0_audio_fifo_addr); + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_fifo_size, + sw_dev[channel->index].fifo_size); + + /* Receive RINGBUFFER Address and size*/ + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + sw0_audio_ringbuff_addr = (config->elem_array.elems[0].dest | ACP_SRAM); + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_ringbuff_addr, + sw0_audio_ringbuff_addr); + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_ringbuff_size, + sw_audio_buff_size_capture); + + /* Receive DMA transfer size in bytes */ + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_dma_size, + (uint32_t)(64/*ACP_DMA_TRANS_SIZE_128*/)); + + /* Watermark size for receive fifo - Half of SW buffer size*/ + io_reg_write(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_dma_watermark, + sw_audio_buff_size_capture >> 1); + break; + default: + tr_err(&acp_sw_audio_tr, "Config channel direction undefined %d", + channel->direction); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_sw_audio_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + + return 0; +} + +static int acp_dai_sw_audio_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_sw_audio_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_sw_audio_tr, "Probe failure,unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_sw_audio_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_sw_audio_tr, "remove called without probe,it's a no-op"); + return 0; + } + + rfree(dma->chan); + dma->chan = NULL; + + return 0; +} + +static int acp_dai_sw_audio_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + *free = sw_audio_buff_size_playback >> 1; + *avail = sw_audio_buff_size_playback >> 1; + + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + *free = sw_audio_buff_size_capture >> 1; + *avail = sw_audio_buff_size_capture >> 1; + + } else { + tr_err(&acp_sw_audio_tr, "Channel direction not defined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_sw_audio_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; + } + + return 0; +} + +static int acp_dai_sw_audio_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status = 0; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + acp_dsp0_intr_stat1_t acp_intr_stat1; + acp_dsp0_intr_cntl1_t acp_intr_cntl1; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + switch (channel->index) { + case SDW1_ACP_P1_SW_BT_TX_EN_CH: + case SDW1_ACP_P1_SW_BT_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_TX_EN_CH: + case SDW1_ACP_P1_SW_HS_RX_EN_CH: + case SDW1_ACP_P1_SW_HS_TX_EN_CH: + acp_intr_stat1 = (acp_dsp0_intr_stat1_t)dma_reg_read(channel->dma, + sw_dev[channel->index].sw_dev_dma_intr_status); + status = acp_intr_stat1.bits.audio_buffer_int_stat; + break; + default: + acp_intr_stat = (acp_dsp0_intr_stat_t)dma_reg_read(channel->dma, + sw_dev[channel->index].sw_dev_dma_intr_status); + status = acp_intr_stat.bits.audio_buffer_int_stat; + break; + } + return (status & (1 << sw_dev[channel->index].statusindex)); + case DMA_IRQ_CLEAR: + switch (channel->index) { + case SDW1_ACP_P1_SW_BT_TX_EN_CH: + case SDW1_ACP_P1_SW_BT_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_TX_EN_CH: + case SDW1_ACP_P1_SW_HS_RX_EN_CH: + case SDW1_ACP_P1_SW_HS_TX_EN_CH: + acp_intr_stat1.u32all = 0; + acp_intr_stat1.bits.audio_buffer_int_stat = + (1 << sw_dev[channel->index].statusindex); + status = acp_intr_stat1.u32all; + dma_reg_write(channel->dma, sw_dev[channel->index].sw_dev_dma_intr_status, + status); + break; + default: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = + (1 << sw_dev[channel->index].statusindex); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, sw_dev[channel->index].sw_dev_dma_intr_status, + status); + break; + } + return 0; + case DMA_IRQ_MASK: + switch (channel->index) { + case SDW1_ACP_P1_SW_BT_TX_EN_CH: + case SDW1_ACP_P1_SW_BT_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_TX_EN_CH: + case SDW1_ACP_P1_SW_HS_RX_EN_CH: + case SDW1_ACP_P1_SW_HS_TX_EN_CH: + acp_intr_cntl1 = (acp_dsp0_intr_cntl1_t)dma_reg_read(channel->dma, + sw_dev[channel->index].sw_dev_dma_intr_cntl); + acp_intr_cntl1.bits.audio_buffer_int_mask &= + (~(1 << sw_dev[channel->index].statusindex)); + status = acp_intr_cntl1.u32all; + dma_reg_write(channel->dma, sw_dev[channel->index].sw_dev_dma_intr_cntl, + status); + break; + default: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + io_reg_read(PU_REGISTER_BASE + sw_dev[channel->index].sw_dev_dma_intr_cntl); + acp_intr_cntl.bits.audio_buffer_int_mask &= + (~(1 << sw_dev[channel->index].statusindex)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, sw_dev[channel->index].sw_dev_dma_intr_cntl, + status); + break; + } + return 0; + case DMA_IRQ_UNMASK: + switch (channel->index) { + case SDW1_ACP_P1_SW_BT_TX_EN_CH: + case SDW1_ACP_P1_SW_BT_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_RX_EN_CH: + case SDW1_ACP_P1_SW_AUDIO_TX_EN_CH: + case SDW1_ACP_P1_SW_HS_RX_EN_CH: + case SDW1_ACP_P1_SW_HS_TX_EN_CH: + acp_intr_cntl1 = (acp_dsp0_intr_cntl1_t)dma_reg_read(channel->dma, + sw_dev[channel->index].sw_dev_dma_intr_cntl); + acp_intr_cntl1.bits.audio_buffer_int_mask |= + (1 << sw_dev[channel->index].statusindex); + status = acp_intr_cntl1.u32all; + dma_reg_write(channel->dma, sw_dev[channel->index].sw_dev_dma_intr_cntl, + status); + break; + default: + acp_intr_cntl = (acp_dsp0_intr_cntl_t)dma_reg_read(channel->dma, + sw_dev[channel->index].sw_dev_dma_intr_cntl); + acp_intr_cntl.bits.audio_buffer_int_mask |= + (1 << sw_dev[channel->index].statusindex); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, sw_dev[channel->index].sw_dev_dma_intr_cntl, + status); + break; + } + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dai_sw_audio_dma_ops = { + .channel_get = acp_dai_sw_audio_dma_channel_get, + .channel_put = acp_dai_sw_audio_dma_channel_put, + .start = acp_dai_sw_audio_dma_start, + .stop = acp_dai_sw_audio_dma_stop, + .pause = acp_dai_sw_audio_dma_pause, + .release = acp_dai_sw_audio_dma_release, + .copy = acp_dai_sw_audio_dma_copy, + .status = acp_dai_sw_audio_dma_status, + .set_config = acp_dai_sw_audio_dma_set_config, + .interrupt = acp_dai_sw_audio_dma_interrupt, + .probe = acp_dai_sw_audio_dma_probe, + .remove = acp_dai_sw_audio_dma_remove, + .get_data_size = acp_dai_sw_audio_dma_get_data_size, + .get_attribute = acp_dai_sw_audio_dma_get_attribute, +}; + +#endif diff --git a/src/drivers/amd/rembrandt/interrupt.c b/src/drivers/amd/rembrandt/interrupt.c new file mode 100644 index 000000000000..8d54c9654d2a --- /dev/null +++ b/src/drivers/amd/rembrandt/interrupt.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> +#include <sof/common.h> +#include <platform/chip_offset_byte.h> +#include <platform/chip_registers.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <xtensa/hal.h> +#include <xtensa/config/core.h> +#include <xtensa/config/specreg.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(irq_acp); + +DECLARE_TR_CTX(acp_irq_tr, SOF_UUID(irq_acp_uuid), LOG_LEVEL_INFO); + +#define IRQ_INT_MASK(irq) (1 << (irq)) +#define RESERVED_IRQS_NUM 0 +#define IRQS_NUM 9 +#define IRQS_PER_LINE 1 + +static inline uint32_t acp_irq_status_read(uint32_t reg) +{ + return io_reg_read(PU_REGISTER_BASE + reg); +} + +static inline void acp_irq_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(PU_REGISTER_BASE + reg, mask, value); +} + +static uint32_t acp_irq_get_status(uint32_t index) +{ + acp_dsp0_intr_stat1_t acp_intr_stat1; + /* 0-7 interrupts are used */ + if (index > 7) + return 0; + if (index == IRQ_NUM_EXT_LEVEL5) { + acp_intr_stat1 = (acp_dsp0_intr_stat1_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP0_INTR_STAT1); + if (acp_intr_stat1.bits.audio_buffer_int_stat) + return acp_irq_status_read(ACP_DSP0_INTR_STAT1); + else + return acp_irq_status_read(ACP_DSP0_INTR_STAT); + } else + return acp_irq_status_read(ACP_DSP0_INTR_STAT); +} + +static void acp_irq_mask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < RESERVED_IRQS_NUM || irq >= IRQS_NUM) { + tr_err(&acp_irq_tr, "Invalid interrupt"); + return; + } + mask = IRQ_INT_MASK(irq); + if (irq == IRQ_NUM_EXT_LEVEL5) + acp_irq_update_bits(ACP_DSP0_INTR_CNTL1, mask, 0); + else + acp_irq_update_bits(ACP_DSP0_INTR_CNTL, mask, 0); +} + +static void acp_irq_unmask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < RESERVED_IRQS_NUM || irq >= IRQS_NUM) { + tr_err(&acp_irq_tr, "Invalid interrupt"); + return; + } + mask = IRQ_INT_MASK(irq); + if (irq == IRQ_NUM_EXT_LEVEL5) + acp_irq_update_bits(ACP_DSP0_INTR_CNTL1, mask, mask); + else + acp_irq_update_bits(ACP_DSP0_INTR_CNTL, mask, mask); +} + +static uint64_t acp_get_irq_interrupts(uint32_t index) +{ + return acp_irq_get_status(index); +} + +static int get_first_irq(uint64_t ints) +{ + return ffs(ints) - 1; +} + +static inline void acp_handle_irq_5(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + int bit; + bool handled; + k_spinlock_key_t key; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); + bit = 5; + + key = k_spin_lock(&cascade->lock); + + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + k_spin_unlock(&cascade->lock, key); + child->handler(child->handler_arg); + k_spin_lock(&cascade->lock); + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&acp_irq_tr, "irq_handler(): not handled, bit %d", + bit); + acp_irq_mask_int(line_index * IRQS_PER_LINE + bit); + } + } +} + +static inline void acp_handle_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + int bit; + bool handled; + k_spinlock_key_t key; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); + + key = k_spin_lock(&cascade->lock); + + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&acp_irq_tr, "irq_handler(): not handled, bit %d", + bit); + acp_irq_mask_int(line_index * IRQS_PER_LINE + bit); + } + } +} + +static void irqhandler_5(void *data) +{ + uint32_t line_index = 5; + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + + line_index = 5; + status = acp_get_irq_interrupts(line_index); + + if (status) + /* Handle current interrupts */ + acp_handle_irq_5(cascade, line_index, status); + else + tr_err(&acp_irq_tr, "invalid interrupt status"); +} + +static inline void irq_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + + status = acp_get_irq_interrupts(line_index); + if (status) + /* Handle current interrupts */ + acp_handle_irq(cascade, line_index, status); + else + tr_err(&acp_irq_tr, "invalid interrupt status"); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + irq_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(0) +DEFINE_IRQ_HANDLER(1) +DEFINE_IRQ_HANDLER(3) +DEFINE_IRQ_HANDLER(4) + +static void acp_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + acp_irq_mask_int(irq); +} + +static void acp_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + acp_irq_unmask_int(irq); +} + +static const struct irq_cascade_ops irq_ops = { + .mask = acp_irq_mask, + .unmask = acp_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .irq = IRQ_NUM_TIMER0, + .handler = irqhandler_0, + .ops = &irq_ops, + .global_mask = false, + }, { + .irq = IRQ_NUM_SOFTWARE0, + .handler = irqhandler_1, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL3, + .handler = irqhandler_3, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL4, + .handler = irqhandler_4, + .ops = &irq_ops, + .global_mask = false, + }, + { + .name = "irqsteer1", + .irq = IRQ_NUM_EXT_LEVEL5, + .handler = irqhandler_5, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +void platform_interrupt_init(void) +{ + int i; + + acp_intr_route(); + /* disable all interrupts and their service routines */ + acp_intr_disable(); + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); + acp_intr_enable(); + acp_dsp_sw_intr_enable(); +} + +#ifndef __ZEPHYR__ +void platform_interrupt_set(uint32_t irq) +{ + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + switch (irq) { + case IRQ_NUM_TIMER0: + case IRQ_NUM_SOFTWARE0: + case IRQ_NUM_EXT_LEVEL3: + case IRQ_NUM_EXT_LEVEL4: + case IRQ_NUM_EXT_LEVEL5: + arch_interrupt_clear(irq); + break; + default: + break; + } +} +#endif + +uint32_t platform_interrupt_get_enabled(void) +{ + /* TODO */ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + arch_interrupt_clear(irq); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + arch_interrupt_set(irq); +} + + +void acp_intr_route(void) +{ + dsp_interrupt_routing_ctrl_0_t interrupt_rout_cntl_0; + dsp_interrupt_routing_ctrl_1_t interrupt_rout_cntl_1; + /* Routing the particular interrupts to the particular level */ + interrupt_rout_cntl_0 = (dsp_interrupt_routing_ctrl_0_t) io_reg_read( + (PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_0)); + interrupt_rout_cntl_0.bits.dma_intr_level = acp_interrupt_level_5; + interrupt_rout_cntl_0.bits.az_sw_i2s_intr_level = acp_interrupt_level_5; + io_reg_write((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_0), + interrupt_rout_cntl_0.u32all); + + interrupt_rout_cntl_1 = (dsp_interrupt_routing_ctrl_1_t) io_reg_read( + (PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_1)); + interrupt_rout_cntl_1.bits.host_to_dsp_intr1_level = acp_interrupt_level_3; + interrupt_rout_cntl_1.bits.wov_intr_level = acp_interrupt_level_4; + interrupt_rout_cntl_1.bits.p1_sw_i2s_intr_level = acp_interrupt_level_5; + io_reg_write((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_1), + interrupt_rout_cntl_1.u32all); +} + +void acp_dsp_sw_intr_enable(void) +{ + acp_dsp_sw_intr_cntl_t sw_intr_ctrl_reg; + + xthal_set_intclear(IRQ_NUM_EXT_LEVEL5); + sw_intr_ctrl_reg = (acp_dsp_sw_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP_SW_INTR_CNTL)); + sw_intr_ctrl_reg.bits.dsp0_to_host_intr_mask = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_CNTL), sw_intr_ctrl_reg.u32all); + /* Enabling software interuppts */ + platform_interrupt_set(IRQ_NUM_EXT_LEVEL3); +} + +void acp_intr_enable(void) +{ + acp_dsp0_intr_cntl_t interrupt_cntl; + acp_dsp0_intr_stat_t interrupt_sts; + acp_dsp0_intr_cntl1_t interrupt_cntl1; + acp_dsp0_intr_stat1_t interrupt_sts1; + acp_external_intr_enb_t ext_interrupt_enb; + + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL5, 0); + platform_interrupt_clear(IRQ_NUM_TIMER0, 0); + interrupt_sts.u32all = 0; + /* Clear status of all interrupts in ACP_DSP0_INTR_STAT register */ + interrupt_sts.bits.dmaiocstat = 0xFF; + interrupt_sts.bits.audio_buffer_int_stat = 0x3F; + interrupt_sts.bits.wov_dma_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT), + interrupt_sts.u32all); + interrupt_sts1.u32all = 0; + interrupt_sts1.bits.audio_buffer_int_stat = 0x3F; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT1), + interrupt_sts1.u32all); + /* Disable the ACP to Host interrupts */ + ext_interrupt_enb.bits.acpextintrenb = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_EXTERNAL_INTR_ENB), + ext_interrupt_enb.u32all); + interrupt_cntl = (acp_dsp0_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL)); + interrupt_cntl.u32all = 0; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + interrupt_cntl.bits.dmaiocmask = 0xFF; + interrupt_cntl.bits.wov_dma_intr_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + interrupt_cntl1 = (acp_dsp0_intr_cntl1_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL1)); + interrupt_cntl1.u32all = 0; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL1), interrupt_cntl1.u32all); + interrupt_cntl1.bits.audio_buffer_int_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL1), interrupt_cntl1.u32all); + platform_interrupt_set(IRQ_NUM_EXT_LEVEL5); + platform_interrupt_set(IRQ_NUM_EXT_LEVEL4); +} + +void acp_intr_disable(void) +{ + acp_dsp0_intr_stat_t interrupt_status; + acp_dsp0_intr_stat1_t interrupt_status1; + acp_external_intr_enb_t ext_interrupt_enb; + acp_dsp0_intr_cntl_t interrupt_cntl; + acp_dsp0_intr_cntl1_t interrupt_cntl1; + + interrupt_status = (acp_dsp0_intr_stat_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_STAT)); + /* Check and Clear all the Interrupt status bits */ + interrupt_status.bits.dmaiocstat = 0xFF; + interrupt_status.bits.wov_dma_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT), interrupt_status.u32all); + interrupt_status1 = (acp_dsp0_intr_stat1_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_STAT1)); + /* Check and Clear all the Interrupt status bits */ + interrupt_status1.bits.audio_buffer_int_stat = 0x3F; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT1), interrupt_status1.u32all); + + /* Disable the ACP to Host interrupts */ + ext_interrupt_enb.bits.acpextintrenb = INTERRUPT_CLEAR; + io_reg_write((PU_REGISTER_BASE + ACP_EXTERNAL_INTR_ENB), ext_interrupt_enb.u32all); + /* Disable all the required ACP interrupts + * in acp_dsp0_intr_cntl_t register + */ + interrupt_cntl = (acp_dsp0_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL)); + interrupt_cntl.bits.dmaiocmask = INTERRUPT_DISABLE; + interrupt_cntl.bits.wov_dma_intr_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + interrupt_cntl1 = (acp_dsp0_intr_cntl1_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL1)); + interrupt_cntl1.bits.audio_buffer_int_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL1), interrupt_cntl1.u32all); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL5, 0); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL3, 0); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL4, 0); + platform_interrupt_clear(IRQ_NUM_TIMER1, 0); + platform_interrupt_clear(IRQ_NUM_TIMER0, 0); +} + +void acp_dsp_sw_intr_disable(void) +{ + acp_dsp_sw_intr_cntl_t sw_intr_ctrl_reg; + /* Read the register */ + sw_intr_ctrl_reg = (acp_dsp_sw_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP_SW_INTR_CNTL)); + sw_intr_ctrl_reg.bits.dsp0_to_host_intr_mask = INTERRUPT_DISABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_CNTL), sw_intr_ctrl_reg.u32all); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL3, 0); +} + +/* This function triggers a host interrupt from ACP DSP */ +void acp_dsp_to_host_intr_trig(void) +{ + acp_sw_intr_trig_t sw_intr_trig; + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t) io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* Clear the Acknowledge ( status) for the host to DSP interrupt */ +void acp_ack_intr_from_host(void) +{ + /* acknowledge the host interrupt */ + acp_dsp_sw_intr_stat_t sw_intr_stat; + + sw_intr_stat.u32all = 0; + sw_intr_stat.bits.host_to_dsp0_intr1_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT), sw_intr_stat.u32all); +} diff --git a/src/drivers/amd/rembrandt/ipc.c b/src/drivers/amd/rembrandt/ipc.c new file mode 100644 index 000000000000..ffc13987bb13 --- /dev/null +++ b/src/drivers/amd/rembrandt/ipc.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> +// Sivasubramanian <sravisar@amd.com> +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/platform.h> +#include <platform/ipc.h> + +#define HOST_TO_DSP_INTR 1 +#define INTERRUPT_DISABLE 0 +LOG_MODULE_REGISTER(ipc1, CONFIG_SOF_LOG_LEVEL); +volatile acp_scratch_mem_config_t *pscratch_mem_cfg = (volatile acp_scratch_mem_config_t *) + (PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +/* Clear the Acknowledge ( status) for the host to DSP interrupt */ +void acp_ack_intr_from_host(void) +{ + /* acknowledge the host interrupt */ + acp_dsp_sw_intr_stat_t sw_intr_stat; + + sw_intr_stat.u32all = 0; + sw_intr_stat.bits.host_to_dsp0_intr1_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT), sw_intr_stat.u32all); +} + +/* This function triggers a host interrupt from ACP DSP */ +void acp_dsp_to_host_intr_trig(void) +{ + acp_sw_intr_trig_t sw_intr_trig; + + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} +#endif /* CONFIG_ZEPHYR_NATIVE_DRIVERS */ + +void amd_irq_handler(void *arg) +{ + struct ipc *ipc = arg; + uint32_t status; + uint32_t lock; + acp_dsp_sw_intr_stat_t swintrstat; + acp_sw_intr_trig_t swintrtrig; + + swintrstat = (acp_dsp_sw_intr_stat_t)io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = swintrstat.u32all & HOST_TO_DSP_INTR; + if (status) { + /* Interrupt source */ + if (sof_ipc_host_status()) { + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + while (lock) + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + /* Check if it is response from host */ + if (sof_ipc_host_ack_flag()) { + /* Clear the ACK from host */ + sof_ipc_host_ack_clear(); + /* Clear the Host to DSP Status Register */ + acp_ack_intr_from_host(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t) + io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE; + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), + swintrtrig.u32all); + } + /* Check if new message from host */ + if (sof_ipc_host_msg_flag()) { + /* Clear the msg bit from host */ + sof_ipc_host_msg_clear(); + /* Clear the Host to DSP Status Register */ + acp_ack_intr_from_host(); + ipc_schedule_process(ipc); + } + io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock); + } else { + tr_err(&ipc_tr, "IPC:interrupt without setting flags host status 0x%x", + sof_ipc_host_status()); + } + } +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + acp_sw_intr_trig_t sw_intr_trig; + + /* Set Dsp Ack for msg from host */ + sof_ipc_dsp_ack_set(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t) + io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE; + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + /* now interrupt host to tell it we have sent a message */ + acp_dsp_to_host_intr_trig(); + /* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + if (ipc->pm_prepare_D3) { + while (1) + wait_for_interrupt(0); + } +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + int ret = 0; + acp_sw_intr_trig_t sw_intr_trig; + acp_dsp_sw_intr_stat_t sw_intr_stat; + uint32_t status; + uint32_t lock; + /* Check if host cleared the status for previous messages */ + sw_intr_stat = (acp_dsp_sw_intr_stat_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = sw_intr_stat.bits.dsp0_to_host_intr_stat; + if (sof_ipc_dsp_status() || status) { + sw_intr_stat = (acp_dsp_sw_intr_stat_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = sw_intr_stat.bits.dsp0_to_host_intr_stat; + return -EBUSY; + } + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + while (lock) + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + /* Write new message in the mailbox */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + /* Need to set DSP message flag */ + sof_ipc_dsp_msg_set(); + /* now interrupt host to tell it we have sent a message */ + acp_dsp_to_host_intr_trig(); + /* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock); + return ret; +} + +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + diff --git a/src/drivers/amd/renoir/CMakeLists.txt b/src/drivers/amd/renoir/CMakeLists.txt new file mode 100644 index 000000000000..3987a52c2446 --- /dev/null +++ b/src/drivers/amd/renoir/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + acp_dma.c + acp_sp_dai.c + interrupt.c + ipc.c + acp_bt_dma.c + acp_sp_dma.c + acp_dmic_dma.c +) diff --git a/src/drivers/amd/renoir/acp_bt_dma.c b/src/drivers/amd/renoir/acp_bt_dma.c new file mode 100644 index 000000000000..d3e05fd77810 --- /dev/null +++ b/src/drivers/amd/renoir/acp_bt_dma.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +SOF_DEFINE_REG_UUID(acp_bt_dma); + +DECLARE_TR_CTX(acp_bt_dma_tr, SOF_UUID(acp_bt_dma_uuid), LOG_LEVEL_INFO); + +/* DMA number of buffer periods */ +#define BT_FIFO_SIZE 768 + +/* ACP DMA transfer size */ +#define ACP_BT_DMA_TRANS_SIZE 64 +#define BT_IER_DISABLE 0x0 + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t bt_buff_size; + +/* Allocate requested DMA channel if it is free */ +static struct dma_chan_data *acp_dai_bt_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_bt_dma_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_bt_dma_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_bt_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dai_bt_dma_start(struct dma_chan_data *channel) +{ + acp_bttdm_ier_t bt_ier; + acp_bttdm_iter_t bt_tdm_iter; + acp_bttdm_irer_t bt_tdm_irer; + uint32_t acp_pdm_en; + + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_ITER)); + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!bt_tdm_iter.bits.bttdm_txen && !bt_tdm_irer.bits.bttdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + bt_ier = (acp_bttdm_ier_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_IER)); + bt_ier.bits.bttdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); + bt_tdm_iter.u32all = 0; + bt_tdm_iter.bits.bttdm_txen = 1; + bt_tdm_iter.bits.bttdm_tx_protocol_mode = 0; + bt_tdm_iter.bits.bttdm_tx_data_path_mode = 1; + bt_tdm_iter.bits.bttdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_ITER), bt_tdm_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + bt_ier = (acp_bttdm_ier_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_IER)); + bt_ier.bits.bttdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); + bt_tdm_irer.u32all = 0; + bt_tdm_irer.bits.bttdm_rx_en = 1; + bt_tdm_irer.bits.bttdm_rx_protocol_mode = 0; + bt_tdm_irer.bits.bttdm_rx_data_path_mode = 1; + bt_tdm_irer.bits.bttdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IRER), bt_tdm_irer.u32all); + } else { + tr_err(&acp_bt_dma_tr, " ACP:Start direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + + +static int acp_dai_bt_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on renoir */ + return 0; +} + +static int acp_dai_bt_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on renoir */ + return 0; +} + +static int acp_dai_bt_dma_stop(struct dma_chan_data *channel) +{ + acp_bttdm_iter_t bt_tdm_iter; + acp_bttdm_irer_t bt_tdm_irer; + uint32_t acp_pdm_en; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_ITER); + bt_tdm_iter.bits.bttdm_txen = 0; + io_reg_write(PU_REGISTER_BASE + ACP_BTTDM_ITER, bt_tdm_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IRER); + bt_tdm_irer.bits.bttdm_rx_en = 0; + io_reg_write(PU_REGISTER_BASE + ACP_BTTDM_IRER, bt_tdm_irer.u32all); + } else { + tr_err(&acp_bt_dma_tr, "direction not defined %d", channel->direction); + return -EINVAL; + } + + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_ITER); + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IRER); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + if (!bt_tdm_iter.bits.bttdm_txen && !bt_tdm_irer.bits.bttdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), BT_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + } + + return 0; +} + +/* fill in "status" with current DMA channel state and position */ +static int acp_dai_bt_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do on renoir */ + return 0; +} + +/* set the DMA channel configuration + * source/target address + * DMA transfer sizes + */ +static int acp_dai_bt_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t bt_ringbuff_addr; + uint32_t fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_bt_dma_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_bt_dma_tr, "scatter enabled, that is not supported for now"); + return -EINVAL; + } + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *) (PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + channel->is_scheduling_source = true; + channel->direction = config->direction; + bt_buff_size = config->elem_array.elems[0].size * config->elem_array.count; + + switch (config->direction) { + case DMA_DIR_MEM_TO_DEV: + + /* BT Transmit FIFO Address and FIFO Size */ + fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_transmit_fifo_buffer); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_FIFOADDR), fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_FIFOSIZE), (uint32_t)(BT_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size */ + bt_ringbuff_addr = config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK; + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_RINGBUFADDR), bt_ringbuff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_RINGBUFSIZE), bt_buff_size); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_DMA_SIZE), + (uint32_t)(ACP_BT_DMA_TRANS_SIZE)); + + /* Watermark size for BT transfer fifo */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_INTR_WATERMARK_SIZE), + (bt_buff_size >> 1)); + break; + case DMA_DIR_DEV_TO_MEM: + + /* BT Receive FIFO Address and FIFO Size*/ + fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_receive_fifo_buffer); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_FIFOADDR), fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_FIFOSIZE), (uint32_t)(BT_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size */ + bt_ringbuff_addr = config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK; + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_RINGBUFADDR), bt_ringbuff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_RINGBUFSIZE), bt_buff_size); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_DMA_SIZE), + (uint32_t)(ACP_BT_DMA_TRANS_SIZE)); + /* Watermark size for BT receive fifo */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_INTR_WATERMARK_SIZE), + (bt_buff_size >> 1)); + break; + default: + tr_err(&acp_bt_dma_tr, "unsupported config direction"); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_bt_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dai_bt_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_bt_dma_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_bt_dma_tr, "Probe failure, unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_bt_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_bt_dma_tr, "remove call without probe, it's a no-op"); + return 0; + } + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +static int acp_dai_bt_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > bt_buff_size ? + (curr_tx_pos - prev_tx_pos) % bt_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = bt_buff_size - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = bt_buff_size >> 1; + *avail = bt_buff_size >> 1; +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > bt_buff_size ? + (curr_rx_pos - prev_rx_pos) % bt_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = bt_buff_size - *free; + prev_rx_pos = curr_rx_pos; +#else + *free = bt_buff_size >> 1; + *avail = bt_buff_size >> 1; +#endif + } else { + tr_err(&acp_bt_dma_tr, "Channel direction Not defined %d", + channel->direction); + return -EINVAL; + } + return 0; +} + +static int acp_dai_bt_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} + +static int acp_dai_bt_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + (dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT)); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1<<channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dai_bt_dma_ops = { + .channel_get = acp_dai_bt_dma_channel_get, + .channel_put = acp_dai_bt_dma_channel_put, + .start = acp_dai_bt_dma_start, + .stop = acp_dai_bt_dma_stop, + .pause = acp_dai_bt_dma_pause, + .release = acp_dai_bt_dma_release, + .copy = acp_dai_bt_dma_copy, + .status = acp_dai_bt_dma_status, + .set_config = acp_dai_bt_dma_set_config, + .interrupt = acp_dai_bt_dma_interrupt, + .probe = acp_dai_bt_dma_probe, + .remove = acp_dai_bt_dma_remove, + .get_data_size = acp_dai_bt_dma_get_data_size, + .get_attribute = acp_dai_bt_dma_get_attribute, +}; diff --git a/src/drivers/amd/renoir/acp_dma.c b/src/drivers/amd/renoir/acp_dma.c new file mode 100644 index 000000000000..84dda2baf2aa --- /dev/null +++ b/src/drivers/amd/renoir/acp_dma.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/audio/component.h> +#include <platform/chip_registers.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_offset_byte.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/acp_dma.h> + +void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes) +{ + uint32_t strt_idx = 0; + uint32_t src; + uint32_t dest; + uint32_t tail, head; + + acp_cfg_dma_descriptor_t psrc_dscr[ACP_MAX_STREAMS]; + acp_cfg_dma_descriptor_t *pdest_dscr; + acp_dma_cntl_0_t dma_cntl; + struct acp_dma_chan_data *acp_dma_chan; + struct acp_dma_config *dma_cfg; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + acp_dma_chan = dma_chan_get_data(channel); + dma_cfg = &acp_dma_chan->config[channel->index]; + pdest_dscr = (acp_cfg_dma_descriptor_t *)(pscratch_mem_cfg->acp_cfg_dma_descriptor); + if (channel->direction == DMA_DIR_HMEM_TO_LMEM) { + head = bytes; + /* Update the read and write pointers */ + dma_cfg->rd_ptr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off + dma_cfg->rd_size; + dma_cfg->wr_ptr = dma_cfg->base + dma_cfg->wr_size; + src = dma_cfg->rd_ptr; + dest = dma_cfg->wr_ptr; + psrc_dscr[strt_idx].src_addr = src; + psrc_dscr[strt_idx].dest_addr = dest; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = bytes; + /* Configure a single descrption */ + dma_config_descriptor(strt_idx, 1, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 1); + /* Check for wrap-around case for system buffer */ + if (dma_cfg->rd_size + bytes > dma_cfg->sys_buff_size) { + /* Configure the descriptor for head and tail */ + /* values for the wrap around case */ + tail = dma_cfg->sys_buff_size - dma_cfg->rd_size; + head = bytes - tail; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx+1].src_addr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off; + psrc_dscr[strt_idx+1].dest_addr = dest+tail; + psrc_dscr[strt_idx+1].trns_cnt.bits.trns_cnt = head; + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->rd_size = 0; + } + /* Check for wrap-around case for host buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->size) { + tail = dma_cfg->size - dma_cfg->wr_size; + head = bytes - tail; + + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + + /* start from "0" like starting address of buffer */ + psrc_dscr[strt_idx + 1].dest_addr = dma_cfg->base; + + psrc_dscr[strt_idx + 1].src_addr = src + tail; + + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + + dma_cfg->rd_size += head; + dma_cfg->rd_size %= dma_cfg->sys_buff_size; + dma_cfg->wr_size += bytes; + dma_cfg->wr_size %= dma_cfg->size; + } else if (channel->direction == DMA_DIR_LMEM_TO_HMEM) { + head = bytes; + dma_cfg->wr_ptr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off + dma_cfg->wr_size; + dma_cfg->rd_ptr = dma_cfg->base + dma_cfg->rd_size; + src = dma_cfg->rd_ptr; + dest = dma_cfg->wr_ptr; + psrc_dscr[strt_idx].src_addr = src; + psrc_dscr[strt_idx].dest_addr = dest; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = bytes; + /* Configure a single descrption */ + dma_config_descriptor(strt_idx, 1, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 1); + /* Check for wrap-around case for system buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->sys_buff_size) { + /* Configure the descriptor for head and + * tail values for the wrap around case + */ + tail = dma_cfg->sys_buff_size - dma_cfg->wr_size; + head = bytes - tail; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx+1].src_addr = src + tail; + psrc_dscr[strt_idx+1].dest_addr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off; + psrc_dscr[strt_idx+1].trns_cnt.bits.trns_cnt = head; + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + dma_cfg->wr_size += head; + dma_cfg->wr_size %= dma_cfg->sys_buff_size; + dma_cfg->rd_size += bytes; + dma_cfg->rd_size %= dma_cfg->size; + } + /* clear the dma channel control bits */ + dma_cntl = (acp_dma_cntl_0_t) dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + /* Load start index of decriptor and priority */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_STRT_IDX_0, strt_idx); + dma_chan_reg_write(channel, ACP_DMA_PRIO_0, 1); + channel->status = COMP_STATE_PREPARE; +} + +/* Some set_config helper functions */ +int dma_setup(struct dma_chan_data *channel, + struct dma_sg_elem_array *sgelems, uint32_t dir) +{ + uint32_t dscr_cnt, dscr = 0; + uint32_t tc; + uint16_t dscr_strt_idx = 0; + uint32_t *phy_off; + uint32_t *syst_buff_size; + acp_dma_cntl_0_t dma_cntl; + struct acp_dma_config *dma_cfg; + struct acp_dma_chan_data *acp_dma_chan = dma_chan_get_data(channel); + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + dscr_cnt = sgelems->count; + /* Trace uses descriptor from index seven */ + /* and other streams use descriptors from zero */ + if (channel->index == DMA_TRACE_CHANNEL) + dscr_strt_idx = DMA_TRACE_CHANNEL; + else + dscr_strt_idx = 0; + /* ACP DMA Descriptor in scratch memory */ + acp_cfg_dma_descriptor_t *dma_config_dscr; + + dma_config_dscr = (acp_cfg_dma_descriptor_t *)(pscratch_mem_cfg->acp_cfg_dma_descriptor); + /* physical offset of system memory */ + phy_off = (uint32_t *)(pscratch_mem_cfg->phy_offset); + /* size of system memory buffer */ + syst_buff_size = (uint32_t *)(pscratch_mem_cfg->syst_buff_size); + + for (dscr = 0; dscr < dscr_cnt; dscr++) { + if (dir == DMA_DIR_HMEM_TO_LMEM) { + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + sgelems->elems[dscr].src + ACP_SYST_MEM_WINDOW; + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + sgelems->elems[dscr].dest & ACP_DRAM_ADDRESS_MASK; + } else { + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + sgelems->elems[dscr].dest + ACP_SYST_MEM_WINDOW; + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + sgelems->elems[dscr].src & ACP_DRAM_ADDRESS_MASK; + } + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + } + dma_config_dscr[dscr_strt_idx + (dscr-1)].trns_cnt.bits.ioc = 0; + dma_cfg = &acp_dma_chan->config[channel->index]; + /* bytes of data to be transferred for the dma */ + tc = dma_config_dscr[dscr_strt_idx].trns_cnt.bits.trns_cnt; + /* DMA configuration for stream */ + if (channel->index != DMA_TRACE_CHANNEL) { + if (!dma_cfg->size) { + acp_dma_chan->dir = dir; + acp_dma_chan->idx = channel->index; + dma_cfg->phy_off = phy_off[channel->index]; + dma_cfg->size = tc * dscr_cnt; + dma_cfg->sys_buff_size = syst_buff_size[channel->index]; + + if (dir == DMA_DIR_HMEM_TO_LMEM) { + /* Playback */ + dma_cfg->base = dma_config_dscr[dscr_strt_idx].dest_addr; + dma_cfg->wr_size = 0; + dma_cfg->rd_size = dma_cfg->size; + } else { + /* Capture */ + dma_cfg->base = dma_config_dscr[dscr_strt_idx].src_addr; + dma_cfg->rd_size = 0; + if (channel->index == dma_cfg->probe_channel) + dma_cfg->wr_size = 0; + else + dma_cfg->wr_size = dma_cfg->size; + } + } + } + /* clear the dma channel control bits */ + dma_cntl = (acp_dma_cntl_0_t) dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_cntl.bits.dmachiocen = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + + /* Program DMAChDscrStrIdx to the index + * number of the first descriptor to be processed. + */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_STRT_IDX_0, dscr_strt_idx); + /* program DMAChDscrdscrcnt to the + * number of descriptors to be processed in the transfer + */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, dscr_cnt); + /* set DMAChPrioLvl according to the priority */ + dma_chan_reg_write(channel, ACP_DMA_PRIO_0, 1); + channel->status = COMP_STATE_PREPARE; + return 0; +} + +int acp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} diff --git a/src/drivers/amd/renoir/acp_dmic_dma.c b/src/drivers/amd/renoir/acp_dmic_dma.c new file mode 100644 index 000000000000..797124ae2c99 --- /dev/null +++ b/src/drivers/amd/renoir/acp_dmic_dma.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_dmic_dma.h> + +SOF_DEFINE_REG_UUID(acp_dmic_dma); +DECLARE_TR_CTX(acp_dmic_dma_rn_tr, SOF_UUID(acp_dmic_dma_uuid), LOG_LEVEL_INFO); + +uint32_t dmic_rngbuff_size; +extern struct acp_dmic_silence acp_initsilence; + +int acp_dmic_dma_start(struct dma_chan_data *channel) +{ + acp_wov_pdm_decimation_factor_t deci_fctr; + acp_wov_misc_ctrl_t wov_misc_ctrl; + acp_wov_pdm_dma_enable_t pdm_dma_enable; + acp_i2stdm_iter_t sp_iter; + acp_i2stdm_irer_t sp_irer; + uint32_t acp_pdm_en; + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; + + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + acp_initsilence.silence_incr = 0; + acp_initsilence.coeff = 0; + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + + channel->status = COMP_STATE_ACTIVE; + if (channel->direction == DMA_DIR_DEV_TO_MEM) { + /* Channel for DMIC */ + /* Decimation Factor */ + deci_fctr.u32all = 2; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DECIMATION_FACTOR, + deci_fctr.u32all); + /* PDM Control */ + wov_misc_ctrl = (acp_wov_misc_ctrl_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_MISC_CTRL); + wov_misc_ctrl.u32all |= 0x10; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_MISC_CTRL, + wov_misc_ctrl.u32all); + /* PDM Enable */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE, 1); + /* PDM DMA Enable */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE, 1); + /* Check the PDM DMA Enable status bit */ + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + while (!(uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) { + if (deadline < platform_timer_get(timer)) { + /* safe check in case we've got preempted after read */ + if ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) + return 0; + tr_err(&acp_dmic_dma_rn_tr, "DMICDMA: timed out for dma start"); + return -ETIME; + } + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + } + } + return 0; +} + +int acp_dmic_dma_stop(struct dma_chan_data *channel) +{ + acp_wov_pdm_dma_enable_t pdm_dma_enable; + acp_i2stdm_iter_t sp_iter; + acp_i2stdm_irer_t sp_irer; + uint32_t acp_pdm_en; + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + /* Disable PDM DMA */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE, 0); + /* Disable PDM */ + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + /* Check PDM DMA Status */ + while ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) { + if (deadline < platform_timer_get(timer)) { + /* safe check in case we've got preempted after read */ + if ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) + return 0; + tr_err(&acp_dmic_dma_rn_tr, "DMIC-DMA: timed out for dma stop"); + return -ETIME; + } + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + } + /* Disable PDM */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE, 0); + /* Clear PDM FIFO */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_FIFO_FLUSH, 1); + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en && !acp_pdm_en) { + /* Request SMU to set aclk to minimum aclk */ + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dmic_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t ring_buff_addr; + uint32_t timeperiod_ms; + acp_wov_rx_ringbufaddr_t dmic_ringbuff_addr; + acp_wov_rx_ringbufsize_t dmic_ringbuff_size; + acp_wov_rx_intr_watermark_size_t watermark; + + channel->is_scheduling_source = true; + channel->direction = config->direction; + switch (config->direction) { + case DMA_DIR_DEV_TO_MEM: + case DMA_DIR_MEM_TO_DEV: + acp_initsilence.dmic_rngbuff_addr1 = (char *)config->elem_array.elems[0].dest; + ring_buff_addr = config->elem_array.elems[0].dest & + ACP_DRAM_ADDRESS_MASK; + /* Load Ring buffer address */ + dmic_ringbuff_addr.bits.rx_ringbufaddr = ring_buff_addr; + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_RINGBUFADDR, dmic_ringbuff_addr.u32all); + /* Load Ring buffer Size */ + dmic_rngbuff_size = (config->elem_array.elems[0].size* + config->elem_array.count); + + dmic_ringbuff_size.bits.rx_ringbufsize = dmic_rngbuff_size; + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_RINGBUFSIZE, dmic_ringbuff_size.u32all); + /* Write the ring buffer size to register */ + watermark.bits.rx_intr_watermark_size = (dmic_rngbuff_size >> 1); + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_INTR_WATERMARK_SIZE, watermark.u32all); + timeperiod_ms = dmic_rngbuff_size / (acp_initsilence.num_chs * + acp_initsilence.samplerate_khz * acp_initsilence.bytes_per_sample * + config->elem_array.count); + acp_initsilence.silence_cnt = DMIC_SETTLING_TIME_MS / timeperiod_ms; + acp_initsilence.numfilterbuffers = DMIC_SMOOTH_TIME_MS / timeperiod_ms; + break; + default: + tr_err(&acp_dmic_dma_rn_tr, + "dmic dma_set_config() unsupported config direction"); + return -EINVAL; + } + if (!config->cyclic) { + tr_err(&acp_dmic_dma_rn_tr, + "DMIC DMA: cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_dmic_dma_rn_tr, + "DMIC DMA: scatter enabled, not supported for now!"); + return -EINVAL; + } + return 0; +} + +int acp_dmic_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} diff --git a/src/drivers/amd/renoir/acp_sp_dai.c b/src/drivers/amd/renoir/acp_sp_dai.c new file mode 100644 index 000000000000..fbff87105ced --- /dev/null +++ b/src/drivers/amd/renoir/acp_sp_dai.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> + +SOF_DEFINE_REG_UUID(spdai); +DECLARE_TR_CTX(spdai_tr, SOF_UUID(spdai_uuid), LOG_LEVEL_INFO); + +static inline int spdai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + const struct sof_ipc_dai_config *config = spec_config; + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + acp_i2stdm_iter_t sp_iter; + acp_i2stdm_irer_t sp_irer; + + acpdata->config = *config; + acpdata->params = config->acpsp; + + sp_iter = (acp_i2stdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_ITER); + sp_irer = (acp_i2stdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IRER); + switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { + case SOF_DAI_FMT_DSP_A: + { + acp_i2stdm_txfrmt_t i2stdm_txfrmt; + acp_i2stdm_rxfrmt_t reg_i2stdm_rxfrmt; + + i2stdm_txfrmt.u32all = io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_TXFRMT)); + i2stdm_txfrmt.bits.i2stdm_num_slots = acpdata->params.tdm_slots; + i2stdm_txfrmt.bits.i2stdm_slot_len = 16; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_TXFRMT), i2stdm_txfrmt.u32all); + + sp_iter.bits.i2stdm_tx_protocol_mode = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + + reg_i2stdm_rxfrmt.u32all = io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_RXFRMT)); + reg_i2stdm_rxfrmt.bits.i2stdm_num_slots = 2; + reg_i2stdm_rxfrmt.bits.i2stdm_slot_len = 16; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_RXFRMT), reg_i2stdm_rxfrmt.u32all); + + sp_irer.bits.i2stdm_rx_protocol_mode = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } + break; + case SOF_DAI_FMT_I2S: + sp_iter.bits.i2stdm_tx_protocol_mode = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + + sp_irer.bits.i2stdm_rx_protocol_mode = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + break; + default: + dai_err(dai, "hsdai_set_config invalid format"); + return -EINVAL; + } + return 0; +} + +static int spdai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do on renoir for SP dai */ + return 0; +} + +static int spdai_probe(struct dai *dai) +{ + struct acp_pdata *acp; + + dai_info(dai, "SP dai probe"); + /* allocate private data */ + acp = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*acp)); + if (!acp) { + dai_err(dai, "SP dai probe alloc failed"); + return -ENOMEM; + } + dai_set_drvdata(dai, acp); + return 0; +} + +static int spdai_remove(struct dai *dai) +{ + struct acp_pdata *acp = dai_get_drvdata(dai); + + rfree(acp); + dai_set_drvdata(dai, NULL); + return 0; +} + +static int spdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int spdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return dai->plat_data.fifo[direction].handshake; +} + +static int spdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + struct acp_pdata *acpdata = dai_get_drvdata(dai); + + if (dir == DAI_DIR_PLAYBACK) { + /* SP DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = acpdata->params.tdm_slots; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + } else if (dir == DAI_DIR_CAPTURE) { + /* SP DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = 2; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + } + return 0; +} + +const struct dai_driver acp_spdai_driver = { + .type = SOF_DAI_AMD_SP, + .uid = SOF_UUID(spdai_uuid), + .tctx = &spdai_tr, + .dma_dev = DMA_DEV_SP, + .dma_caps = DMA_CAP_SP, + .ops = { + .trigger = spdai_trigger, + .set_config = spdai_set_config, + .probe = spdai_probe, + .remove = spdai_remove, + .get_fifo = spdai_get_fifo, + .get_handshake = spdai_get_handshake, + .get_hw_params = spdai_get_hw_params, + }, +}; + + diff --git a/src/drivers/amd/renoir/acp_sp_dma.c b/src/drivers/amd/renoir/acp_sp_dma.c new file mode 100644 index 000000000000..1877c9ab88c0 --- /dev/null +++ b/src/drivers/amd/renoir/acp_sp_dma.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_sp_dma.h> + +SOF_DEFINE_REG_UUID(acp_sp); +DECLARE_TR_CTX(acp_sp_rn_tr, SOF_UUID(acp_sp_uuid), LOG_LEVEL_INFO); + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t sp_buff_size_playback; +static uint32_t sp_buff_size_capture; +/* allocate next free DMA channel */ +int acp_dai_sp_dma_start(struct dma_chan_data *channel) +{ + acp_i2stdm_ier_t sp_ier; + acp_i2stdm_iter_t sp_iter; + acp_i2stdm_irer_t sp_irer; + uint32_t acp_pdm_en; + + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + sp_ier = (acp_i2stdm_ier_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IER)); + sp_ier.bits.i2stdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), sp_ier.u32all); + sp_iter.bits.i2stdm_txen = 1; + sp_iter.bits.i2stdm_tx_data_path_mode = 1; + sp_iter.bits.i2stdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + sp_ier = (acp_i2stdm_ier_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IER)); + sp_ier.bits.i2stdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), sp_ier.u32all); + sp_irer.bits.i2stdm_rx_en = 1; + sp_irer.bits.i2stdm_rx_data_path_mode = 1; + sp_irer.bits.i2stdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } else { + tr_err(&acp_sp_rn_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +int acp_dai_sp_dma_stop(struct dma_chan_data *channel) +{ + acp_i2stdm_irer_t sp_irer; + acp_i2stdm_iter_t sp_iter; + uint32_t acp_pdm_en; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_iter.bits.i2stdm_txen = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + sp_irer.bits.i2stdm_rx_en = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } else { + tr_err(&acp_sp_rn_tr, "Stop direction not defined %d", channel->direction); + return -EINVAL; + } + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), SP_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + } + + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t sp_buff_addr; + uint32_t sp_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_sp_rn_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_sp_rn_tr, "scatter enabled, that is not supported for now!"); + return -EINVAL; + } + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + channel->is_scheduling_source = true; + channel->direction = config->direction; + + if (config->direction == DMA_DIR_MEM_TO_DEV) { + + sp_buff_size_playback = config->elem_array.elems[0].size * config->elem_array.count; + /* SP Transmit FIFO Address and FIFO Size*/ + sp_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_transmit_fifo_buffer); + memset((void *)sp_fifo_addr, 0, SP_FIFO_SIZE); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_FIFOADDR), sp_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_FIFOSIZE), (uint32_t)(SP_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size*/ + sp_buff_addr = config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK; + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_RINGBUFADDR), sp_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_RINGBUFSIZE), sp_buff_size_playback); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE)); + + /* Watermark size for SP transmit FIFO - Half of SP buffer size */ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_INTR_WATERMARK_SIZE), + (sp_buff_size_playback >> 1)); + + } else if (config->direction == DMA_DIR_DEV_TO_MEM) { + + sp_buff_size_capture = config->elem_array.elems[0].size * config->elem_array.count; + /* SP Receive FIFO Address and FIFO Size*/ + sp_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_receive_fifo_buffer); + memset((void *)sp_fifo_addr, 0, SP_FIFO_SIZE); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_FIFOADDR), sp_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_FIFOSIZE), + (uint32_t)(SP_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size*/ + sp_buff_addr = config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK; + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR), sp_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFSIZE), sp_buff_size_capture); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE)); + + /* Watermark size for SP receive fifo - Half of SP buffer size*/ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_INTR_WATERMARK_SIZE), + (sp_buff_size_capture >> 1)); + + } else { + tr_err(&acp_sp_rn_tr, "config channel direction undefined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high<<32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > sp_buff_size_playback ? + (curr_tx_pos - prev_tx_pos) % sp_buff_size_playback : + (curr_tx_pos - prev_tx_pos); + *avail = sp_buff_size_playback - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = (sp_buff_size_playback >> 1); + *avail = (sp_buff_size_playback >> 1); +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high<<32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > sp_buff_size_capture ? + (curr_rx_pos - prev_rx_pos) % sp_buff_size_capture : + (curr_rx_pos - prev_rx_pos); + *avail = sp_buff_size_capture - *free; + prev_rx_pos = curr_rx_pos; +#else + *avail = (sp_buff_size_capture >> 1); + *free = (sp_buff_size_capture >> 1); +#endif + } else { + tr_err(&acp_sp_rn_tr, "Channel direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + +int acp_dai_sp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; + } + return 0; +} + +int acp_dai_sp_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + (dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT)); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1<<channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = + (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} diff --git a/src/drivers/amd/renoir/interrupt.c b/src/drivers/amd/renoir/interrupt.c new file mode 100644 index 000000000000..6327c792cdd8 --- /dev/null +++ b/src/drivers/amd/renoir/interrupt.c @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> +#include <sof/common.h> +#include <platform/chip_offset_byte.h> +#include <platform/chip_registers.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <xtensa/hal.h> +#include <xtensa/config/core.h> +#include <xtensa/config/specreg.h> +#include <xtensa/core-macros.h> +#include "xtos-internal.h" +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(irq_acp); + +DECLARE_TR_CTX(acp_irq_tr, SOF_UUID(irq_acp_uuid), LOG_LEVEL_INFO); + +#define IRQ_INT_MASK(irq) (1 << (irq)) +#define RESERVED_IRQS_NUM 0 +#define IRQS_NUM 8 +#define IRQS_PER_LINE 1 + +static inline uint32_t acp_irq_status_read(uint32_t reg) +{ + return io_reg_read(PU_REGISTER_BASE + reg); +} + +static inline void acp_irq_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(PU_REGISTER_BASE + reg, mask, value); +} + +static uint32_t acp_irq_get_status(uint32_t index) +{ + /* 0-7 interrupts are used */ + if (index > 7) + return 0; + return acp_irq_status_read(ACP_DSP0_INTR_STAT); +} + +static void acp_irq_mask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < RESERVED_IRQS_NUM || irq >= IRQS_NUM) { + tr_err(&acp_irq_tr, "Invalid interrupt"); + return; + } + mask = IRQ_INT_MASK(irq); + acp_irq_update_bits(ACP_DSP0_INTR_CNTL, mask, 0); +} + +static void acp_irq_unmask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < RESERVED_IRQS_NUM || irq >= IRQS_NUM) { + tr_err(&acp_irq_tr, "Invalid interrupt"); + return; + } + mask = IRQ_INT_MASK(irq); + acp_irq_update_bits(ACP_DSP0_INTR_CNTL, mask, mask); +} + +static uint64_t acp_get_irq_interrupts(uint32_t index) +{ + return acp_irq_get_status(index); +} + +static int get_first_irq(uint64_t ints) +{ + return ffs(ints) - 1; +} + +static inline void acp_handle_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + int bit; + bool handled; + k_spinlock_key_t key; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); + + key = k_spin_lock(&cascade->lock); + + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&acp_irq_tr, "irq_handler(): not handled, bit %d", + bit); + acp_irq_mask_int(line_index * IRQS_PER_LINE + bit); + } + } +} + +static inline void irq_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + + status = acp_get_irq_interrupts(line_index); + + if (status) + /* Handle current interrupts */ + acp_handle_irq(cascade, line_index, status); + else + tr_err(&acp_irq_tr, "invalid interrupt status"); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + irq_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(0) +DEFINE_IRQ_HANDLER(1) +DEFINE_IRQ_HANDLER(3) +DEFINE_IRQ_HANDLER(4) +DEFINE_IRQ_HANDLER(5) + +static void acp_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + acp_irq_mask_int(irq); +} + +static void acp_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + acp_irq_unmask_int(irq); +} + +static const struct irq_cascade_ops irq_ops = { + .mask = acp_irq_mask, + .unmask = acp_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .irq = IRQ_NUM_TIMER0, + .handler = irqhandler_0, + .ops = &irq_ops, + .global_mask = false, + }, { + .irq = IRQ_NUM_SOFTWARE0, + .handler = irqhandler_1, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL3, + .handler = irqhandler_3, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL4, + .handler = irqhandler_4, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL5, + .handler = irqhandler_5, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +void platform_interrupt_init(void) +{ + int i; + + acp_intr_route(); + /* disable all interrupts and their service routines */ + acp_intr_disable(); + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); + acp_intr_enable(); + acp_dsp_sw_intr_enable(); +} + +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + switch (irq) { + case IRQ_NUM_TIMER0: + case IRQ_NUM_SOFTWARE0: + case IRQ_NUM_EXT_LEVEL3: + case IRQ_NUM_EXT_LEVEL4: + case IRQ_NUM_EXT_LEVEL5: + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); + break; + default: + break; + } +} + +uint32_t platform_interrupt_get_enabled(void) +{ + /* TODO */ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + + +void acp_intr_route(void) +{ + dsp_interrupt_routing_ctrl_t interrupt_rout_cntl; + /* Routing the particular interrupts to the particular level */ + interrupt_rout_cntl = (dsp_interrupt_routing_ctrl_t) io_reg_read( + (PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL)); + interrupt_rout_cntl.bits.dma_intr_level = acp_interrupt_level_5; + interrupt_rout_cntl.bits.az_sw_i2s_intr_level = acp_interrupt_level_5; + interrupt_rout_cntl.bits.host_to_dsp_intr1_level = acp_interrupt_level_3; + interrupt_rout_cntl.bits.wov_intr_level = acp_interrupt_level_4; + io_reg_write((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL), + interrupt_rout_cntl.u32all); +} + +void acp_dsp_sw_intr_enable(void) +{ + acp_dsp_sw_intr_cntl_t sw_intr_ctrl_reg; + + xthal_set_intclear(IRQ_NUM_EXT_LEVEL5); + sw_intr_ctrl_reg = (acp_dsp_sw_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP_SW_INTR_CNTL)); + sw_intr_ctrl_reg.bits.dsp0_to_host_intr_mask = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_CNTL), sw_intr_ctrl_reg.u32all); + /* Enabling software interuppts */ + platform_interrupt_set(IRQ_NUM_EXT_LEVEL3); +} + +void acp_intr_enable(void) +{ + acp_dsp0_intr_cntl_t interrupt_cntl; + acp_dsp0_intr_stat_t interrupt_sts; + acp_external_intr_enb_t ext_interrupt_enb; + + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL5, 0); + platform_interrupt_clear(IRQ_NUM_TIMER0, 0); + interrupt_sts.u32all = 0; + /* Clear status of all interrupts in ACP_DSP0_INTR_STAT register */ + interrupt_sts.bits.dmaiocstat = 0xFF; + interrupt_sts.bits.audio_buffer_int_stat = 0x3F; + interrupt_sts.bits.wov_dma_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT), + interrupt_sts.u32all); + /* Disable the ACP to Host interrupts */ + ext_interrupt_enb.bits.acpextintrenb = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_EXTERNAL_INTR_ENB), + ext_interrupt_enb.u32all); + interrupt_cntl = (acp_dsp0_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL)); + interrupt_cntl.u32all = 0; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + interrupt_cntl.bits.dmaiocmask = 0xFF; + interrupt_cntl.bits.audio_buffer_int_mask = INTERRUPT_DISABLE; + interrupt_cntl.bits.wov_dma_intr_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + platform_interrupt_set(IRQ_NUM_EXT_LEVEL5); + platform_interrupt_set(IRQ_NUM_EXT_LEVEL4); +} + +void acp_intr_disable(void) +{ + acp_dsp0_intr_stat_t interrupt_status; + acp_external_intr_enb_t ext_interrupt_enb; + acp_dsp0_intr_cntl_t interrupt_cntl; + + interrupt_status = (acp_dsp0_intr_stat_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_STAT)); + /* Check and Clear all the Interrupt status bits */ + interrupt_status.bits.dmaiocstat = 0xFF; + interrupt_status.bits.audio_buffer_int_stat = 0x3F; + interrupt_status.bits.wov_dma_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT), interrupt_status.u32all); + /* Disable the ACP to Host interrupts */ + ext_interrupt_enb.bits.acpextintrenb = INTERRUPT_CLEAR; + io_reg_write((PU_REGISTER_BASE + ACP_EXTERNAL_INTR_ENB), ext_interrupt_enb.u32all); + /* Disable all the required ACP interrupts + * in acp_dsp0_intr_cntl_t register + */ + interrupt_cntl = (acp_dsp0_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL)); + interrupt_cntl.bits.dmaiocmask = INTERRUPT_DISABLE; + interrupt_cntl.bits.audio_buffer_int_mask = INTERRUPT_DISABLE; + interrupt_cntl.bits.wov_dma_intr_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL5, 0); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL3, 0); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL4, 0); + platform_interrupt_clear(IRQ_NUM_TIMER1, 0); + platform_interrupt_clear(IRQ_NUM_TIMER0, 0); +} + +void acp_dsp_sw_intr_disable(void) +{ + acp_dsp_sw_intr_cntl_t sw_intr_ctrl_reg; + /* Read the register */ + sw_intr_ctrl_reg = (acp_dsp_sw_intr_cntl_t) io_reg_read((PU_REGISTER_BASE + + ACP_DSP_SW_INTR_CNTL)); + sw_intr_ctrl_reg.bits.dsp0_to_host_intr_mask = INTERRUPT_DISABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_CNTL), sw_intr_ctrl_reg.u32all); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL3, 0); +} + +/* This function triggers a host interrupt from ACP DSP */ +void acp_dsp_to_host_intr_trig(void) +{ + acp_sw_intr_trig_t sw_intr_trig; + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t) io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* Clear the Acknowledge ( status) for the host to DSP interrupt */ +void acp_ack_intr_from_host(void) +{ + /* acknowledge the host interrupt */ + acp_dsp_sw_intr_stat_t sw_intr_stat; + + sw_intr_stat.u32all = 0; + sw_intr_stat.bits.host_to_dsp0_intr1_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT), sw_intr_stat.u32all); +} diff --git a/src/drivers/amd/renoir/ipc.c b/src/drivers/amd/renoir/ipc.c new file mode 100644 index 000000000000..b718f57540ba --- /dev/null +++ b/src/drivers/amd/renoir/ipc.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <rtos/panic.h> +#include <xtensa/core-macros.h> +#include <platform/chip_offset_byte.h> +#include <platform/chip_registers.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/platform.h> +#include <platform/ipc.h> + +volatile acp_scratch_mem_config_t *pscratch_mem_cfg = (volatile acp_scratch_mem_config_t *) + (PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + +void amd_irq_handler(void *arg) +{ + struct ipc *ipc = arg; + uint32_t status; + uint32_t lock; + uint32_t delay_cnt = 10000; + bool lock_fail = false; + acp_dsp_sw_intr_stat_t swintrstat; + acp_sw_intr_trig_t swintrtrig; + + swintrstat = (acp_dsp_sw_intr_stat_t)io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = swintrstat.u32all & HOST_TO_DSP_INTR; + if (status) { + /* Interrupt source */ + if (sof_ipc_host_status()) { + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + while (lock) { + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + if (!delay_cnt) { + lock_fail = true; + break; + } + delay_cnt--; + } + if (lock_fail) { + tr_err(&ipc_tr, "ACP fail to acquire the lock"); + return; + } + /* Check if it is response from host */ + if (sof_ipc_host_ack_flag()) { + /* Clear the ACK from host */ + sof_ipc_host_ack_clear(); + /* Clear the Host to DSP Status Register */ + acp_ack_intr_from_host(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t) + io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE; + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), + swintrtrig.u32all); + } + /* Check if new message from host */ + if (sof_ipc_host_msg_flag()) { + /* Clear the msg bit from host */ + sof_ipc_host_msg_clear(); + /* Clear the Host to DSP Status Register */ + acp_ack_intr_from_host(); + ipc_schedule_process(ipc); + } + io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock); + } else { + tr_err(&ipc_tr, "IPC:interrupt without setting flags host status 0x%x", + sof_ipc_host_status()); + } + } +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + acp_sw_intr_trig_t sw_intr_trig; + + /* Set Dsp Ack for msg from host */ + sof_ipc_dsp_ack_set(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t) + io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE; + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + /* now interrupt host to tell it we have sent a message */ + acp_dsp_to_host_intr_trig(); + if (ipc->pm_prepare_D3) { + while (1) + wait_for_interrupt(0); + } +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + acp_sw_intr_trig_t sw_intr_trig; + acp_dsp_sw_intr_stat_t sw_intr_stat; + uint32_t status; + uint32_t lock; + uint32_t delay_cnt = 10000; + /* Check if host cleared the status for previous messages */ + sw_intr_stat = (acp_dsp_sw_intr_stat_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = sw_intr_stat.bits.dsp0_to_host_intr_stat; + if (sof_ipc_dsp_status() || status) { + sw_intr_stat = (acp_dsp_sw_intr_stat_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = sw_intr_stat.bits.dsp0_to_host_intr_stat; + return -EBUSY; + } + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + while (lock) { + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + if (!delay_cnt) + return -EBUSY; + + delay_cnt--; + } + + /* Write new message in the mailbox */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + /* Need to set DSP message flag */ + sof_ipc_dsp_msg_set(); + /* now interrupt host to tell it we have sent a message */ + acp_dsp_to_host_intr_trig(); + /* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock); + return 0; +} + +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + diff --git a/src/drivers/amd/vangogh/CMakeLists.txt b/src/drivers/amd/vangogh/CMakeLists.txt new file mode 100644 index 000000000000..24e80e3e76d7 --- /dev/null +++ b/src/drivers/amd/vangogh/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + acp_dma.c + acp_sp_dai.c + acp_hs_dai.c + interrupt.c + ipc.c + acp_bt_dma.c + acp_sp_dma.c + acp_hs_dma.c + acp_dmic_dma.c +) diff --git a/src/drivers/amd/vangogh/acp_bt_dma.c b/src/drivers/amd/vangogh/acp_bt_dma.c new file mode 100644 index 000000000000..4f08bc69abee --- /dev/null +++ b/src/drivers/amd/vangogh/acp_bt_dma.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +SOF_DEFINE_REG_UUID(acp_bt_dma); + +DECLARE_TR_CTX(acp_bt_dma_tr, SOF_UUID(acp_bt_dma_uuid), LOG_LEVEL_INFO); + +/* DMA number of buffer periods */ +#define BT_FIFO_SIZE 768 + +/* ACP DMA transfer size */ +#define ACP_BT_DMA_TRANS_SIZE 128 +#define BT_IER_DISABLE 0x0 +/* Vangogh hw specific addr map */ +#define ACP_DRAM_PHY_TRNS 0x0DEB0000 + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t bt_buff_size; + +/* Allocate requested DMA channel if it is free */ +static struct dma_chan_data *acp_dai_bt_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_bt_dma_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_bt_dma_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_bt_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dai_bt_dma_start(struct dma_chan_data *channel) +{ + acp_bttdm_ier_t bt_ier; + acp_bttdm_iter_t bt_tdm_iter; + acp_bttdm_irer_t bt_tdm_irer; + + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_ITER)); + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_BTTDM_IRER)); + + if (!bt_tdm_iter.bits.bttdm_txen && !bt_tdm_irer.bits.bttdm_rx_en) + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + bt_ier = (acp_bttdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IER); + bt_ier.bits.bttdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); + bt_tdm_iter.u32all = 0; + bt_tdm_iter.bits.bttdm_txen = 1; + bt_tdm_iter.bits.bttdm_tx_protocol_mode = 0; + bt_tdm_iter.bits.bttdm_tx_data_path_mode = 1; + bt_tdm_iter.bits.bttdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_ITER), bt_tdm_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + bt_ier = (acp_bttdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IER); + bt_ier.bits.bttdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), bt_ier.u32all); + bt_tdm_irer.u32all = 0; + bt_tdm_irer.bits.bttdm_rx_en = 1; + bt_tdm_irer.bits.bttdm_rx_protocol_mode = 0; + bt_tdm_irer.bits.bttdm_rx_data_path_mode = 1; + bt_tdm_irer.bits.bttdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IRER), bt_tdm_irer.u32all); + } else { + tr_err(&acp_bt_dma_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + +static int acp_dai_bt_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on vangogh */ + return 0; +} + +static int acp_dai_bt_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on vangogh */ + return 0; +} + +static int acp_dai_bt_dma_stop(struct dma_chan_data *channel) +{ + acp_bttdm_iter_t bt_tdm_iter; + acp_bttdm_irer_t bt_tdm_irer; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_ITER); + bt_tdm_iter.bits.bttdm_txen = 0; + io_reg_write(PU_REGISTER_BASE + ACP_BTTDM_ITER, bt_tdm_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IRER); + bt_tdm_irer.bits.bttdm_rx_en = 0; + io_reg_write(PU_REGISTER_BASE + ACP_BTTDM_IRER, bt_tdm_irer.u32all); + } else { + tr_err(&acp_bt_dma_tr, "direction not defined %d", channel->direction); + return -EINVAL; + } + + bt_tdm_iter = (acp_bttdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_ITER); + bt_tdm_irer = (acp_bttdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_BTTDM_IRER); + if (!bt_tdm_iter.bits.bttdm_txen && !bt_tdm_irer.bits.bttdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_BTTDM_IER), BT_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + acp_change_clock_notify(0); + } + + return 0; +} + +/* fill in "status" with current DMA channel state and position */ +static int acp_dai_bt_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do on vangogh */ + return 0; +} + +/* set the DMA channel configuration + * source/target address + * DMA transfer sizes + */ +static int acp_dai_bt_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t bt_ringbuff_addr; + uint32_t bt_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_bt_dma_tr, "cyclic configurations only supported"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_bt_dma_tr, "scatter enabled, that is not supported for now"); + return -EINVAL; + } + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + channel->is_scheduling_source = true; + channel->direction = config->direction; + bt_buff_size = config->elem_array.elems[0].size * config->elem_array.count; + + switch (config->direction) { + case DMA_DIR_MEM_TO_DEV: + + /* BT Transmit FIFO Address and FIFO Size */ + bt_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_transmit_fifo_buffer); + bt_fifo_addr = (bt_fifo_addr & ACP_DRAM_ADDRESS_MASK); + bt_fifo_addr = (bt_fifo_addr - ACP_DRAM_PHY_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_FIFOADDR), bt_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_FIFOSIZE), (uint32_t)(BT_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size */ + config->elem_array.elems[0].src = + (config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK); + bt_ringbuff_addr = (config->elem_array.elems[0].src | 0x01000000); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_RINGBUFADDR), bt_ringbuff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_RINGBUFSIZE), bt_buff_size); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + /* Watermark size for BT transfer fifo */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_TX_INTR_WATERMARK_SIZE), + (bt_buff_size >> 1)); + break; + case DMA_DIR_DEV_TO_MEM: + + /* BT Receive FIFO Address and FIFO Size*/ + bt_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_receive_fifo_buffer); + bt_fifo_addr = (bt_fifo_addr & ACP_DRAM_ADDRESS_MASK); + bt_fifo_addr = (bt_fifo_addr - ACP_DRAM_PHY_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_FIFOADDR), bt_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_FIFOSIZE), (uint32_t)(BT_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size */ + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + bt_ringbuff_addr = (config->elem_array.elems[0].dest | 0x01000000); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_RINGBUFADDR), bt_ringbuff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_RINGBUFSIZE), bt_buff_size); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + /* Watermark size for BT receive fifo */ + io_reg_write((PU_REGISTER_BASE + ACP_BT_RX_INTR_WATERMARK_SIZE), + (bt_buff_size >> 1)); + break; + default: + tr_err(&acp_bt_dma_tr, "unsupported config direction"); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_bt_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dai_bt_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_bt_dma_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_bt_dma_tr, "Probe failure, unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_bt_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_bt_dma_tr, "remove called without probe, it's a no-op"); + return 0; + } + + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +static int acp_dai_bt_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > bt_buff_size ? + (curr_tx_pos - prev_tx_pos) % bt_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = bt_buff_size - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = bt_buff_size >> 1; + *avail = bt_buff_size >> 1; +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > bt_buff_size ? + (curr_rx_pos - prev_rx_pos) % bt_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = bt_buff_size - *free; + prev_rx_pos = curr_rx_pos; +#else + *free = bt_buff_size >> 1; + *avail = bt_buff_size >> 1; +#endif + } else { + tr_err(&acp_bt_dma_tr, "Channel direction Not defined %d", + channel->direction); + return -EINVAL; + } + return 0; +} + +static int acp_dai_bt_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} + +static int acp_dai_bt_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + (dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT)); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1 << channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dai_bt_dma_ops = { + .channel_get = acp_dai_bt_dma_channel_get, + .channel_put = acp_dai_bt_dma_channel_put, + .start = acp_dai_bt_dma_start, + .stop = acp_dai_bt_dma_stop, + .pause = acp_dai_bt_dma_pause, + .release = acp_dai_bt_dma_release, + .copy = acp_dai_bt_dma_copy, + .status = acp_dai_bt_dma_status, + .set_config = acp_dai_bt_dma_set_config, + .interrupt = acp_dai_bt_dma_interrupt, + .probe = acp_dai_bt_dma_probe, + .remove = acp_dai_bt_dma_remove, + .get_data_size = acp_dai_bt_dma_get_data_size, + .get_attribute = acp_dai_bt_dma_get_attribute, +}; diff --git a/src/drivers/amd/vangogh/acp_dma.c b/src/drivers/amd/vangogh/acp_dma.c new file mode 100644 index 000000000000..853460d289c8 --- /dev/null +++ b/src/drivers/amd/vangogh/acp_dma.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/audio/component.h> +#include <platform/chip_registers.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_offset_byte.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/acp_dma.h> + +void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes) +{ + uint32_t strt_idx = 0; + uint32_t src; + uint32_t dest; + uint32_t tail, head; + uint32_t src1; + uint32_t dest1; + + acp_cfg_dma_descriptor_t psrc_dscr[ACP_MAX_STREAMS]; + acp_cfg_dma_descriptor_t *pdest_dscr; + acp_dma_cntl_0_t dma_cntl; + struct acp_dma_chan_data *acp_dma_chan; + struct acp_dma_config *dma_cfg; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + acp_dma_chan = dma_chan_get_data(channel); + dma_cfg = &acp_dma_chan->config[channel->index]; + pdest_dscr = (acp_cfg_dma_descriptor_t *)(pscratch_mem_cfg->acp_cfg_dma_descriptor); + if (channel->direction == DMA_DIR_HMEM_TO_LMEM) { + head = bytes; + /* Update the read and write pointers */ + dma_cfg->rd_ptr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off + dma_cfg->rd_size; + dma_cfg->wr_ptr = dma_cfg->base + dma_cfg->wr_size; + src = dma_cfg->rd_ptr; + dest = dma_cfg->wr_ptr; + psrc_dscr[strt_idx].src_addr = src; + dest = (dest & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx].dest_addr = (dest | ACP_DRAM_ADDR_TRNS); + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = bytes; + /* Configure a single descrption */ + dma_config_descriptor(strt_idx, 1, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 1); + /* Check for wrap-around case for system buffer */ + if (dma_cfg->rd_size + bytes > dma_cfg->sys_buff_size) { + /* Configure the descriptor for head and tail */ + /* values for the wrap around case */ + tail = dma_cfg->sys_buff_size - dma_cfg->rd_size; + head = bytes - tail; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].src_addr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off; + dest1 = dest + tail; + dest1 = (dest1 & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx + 1].dest_addr = (dest1 | ACP_DRAM_ADDR_TRNS); + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->rd_size = 0; + } + /* Check for wrap-around case for host buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->size) { + tail = dma_cfg->size - dma_cfg->wr_size; + head = bytes - tail; + + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + + /* start from "0" like starting address of buffer */ + psrc_dscr[strt_idx + 1].dest_addr = + ((dma_cfg->base & ACP_DRAM_ADDRESS_MASK) | ACP_DRAM_ADDR_TRNS); + + src1 = src + tail; + psrc_dscr[strt_idx + 1].src_addr = src1; + + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + + dma_cfg->rd_size += head; + dma_cfg->rd_size %= dma_cfg->sys_buff_size; + dma_cfg->wr_size += bytes; + dma_cfg->wr_size %= dma_cfg->size; + } else if (channel->direction == DMA_DIR_LMEM_TO_HMEM) { + head = bytes; + dma_cfg->wr_ptr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off + dma_cfg->wr_size; + dma_cfg->rd_ptr = dma_cfg->base + dma_cfg->rd_size; + src = dma_cfg->rd_ptr; + dest = dma_cfg->wr_ptr; + src = (src & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx].src_addr = (src | ACP_DRAM_ADDR_TRNS); + psrc_dscr[strt_idx].dest_addr = dest; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = bytes; + /* Configure a single descrption */ + dma_config_descriptor(strt_idx, 1, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 1); + /* Check for wrap-around case for system buffer */ + if (dma_cfg->wr_size + bytes > dma_cfg->sys_buff_size) { + /* Configure the descriptor for head and + * tail values for the wrap around case + */ + tail = dma_cfg->sys_buff_size - dma_cfg->wr_size; + head = bytes - tail; + psrc_dscr[strt_idx].trns_cnt.bits.trns_cnt = tail; + src1 = src + tail; + psrc_dscr[strt_idx + 1].dest_addr = ACP_SYST_MEM_WINDOW + dma_cfg->phy_off; + psrc_dscr[strt_idx + 1].trns_cnt.bits.trns_cnt = head; + src1 = (src1 & ACP_DRAM_ADDRESS_MASK); + psrc_dscr[strt_idx + 1].src_addr = (src1 | ACP_DRAM_ADDR_TRNS); + dma_config_descriptor(strt_idx, 2, psrc_dscr, pdest_dscr); + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, 2); + dma_cfg->wr_size = 0; + } + dma_cfg->wr_size += head; + dma_cfg->wr_size %= dma_cfg->sys_buff_size; + dma_cfg->rd_size += bytes; + dma_cfg->rd_size %= dma_cfg->size; + } + /* clear the dma channel control bits */ + dma_cntl = (acp_dma_cntl_0_t)dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + /* Load start index of decriptor and priority */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_STRT_IDX_0, strt_idx); + dma_chan_reg_write(channel, ACP_DMA_PRIO_0, 1); + channel->status = COMP_STATE_PREPARE; +} + +/* Some set_config helper functions */ +int dma_setup(struct dma_chan_data *channel, + struct dma_sg_elem_array *sgelems, uint32_t dir) +{ + uint32_t dscr_cnt, dscr; + uint32_t tc; + uint16_t dscr_strt_idx; + uint32_t *phy_off; + uint32_t *syst_buff_size; + uint32_t src; + uint32_t dest; + uint32_t buff_size = 0; + acp_dma_cntl_0_t dma_cntl; + struct acp_dma_config *dma_cfg; + struct acp_dma_chan_data *acp_dma_chan = dma_chan_get_data(channel); + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + dscr_cnt = sgelems->count; + /* Trace uses descriptor from index seven */ + /* and other streams use descriptors from zero */ + if (channel->index == DMA_TRACE_CHANNEL) + dscr_strt_idx = DMA_TRACE_CHANNEL; + else + dscr_strt_idx = 0; + + /* ACP DMA Descriptor in scratch memory */ + acp_cfg_dma_descriptor_t *dma_config_dscr; + + dma_config_dscr = (acp_cfg_dma_descriptor_t *)(pscratch_mem_cfg->acp_cfg_dma_descriptor); + /* physical offset of system memory */ + phy_off = (uint32_t *)(pscratch_mem_cfg->phy_offset); + /* size of system memory buffer */ + syst_buff_size = (uint32_t *)(pscratch_mem_cfg->syst_buff_size); + for (dscr = 0; dscr < dscr_cnt; dscr++) { + if (dir == DMA_DIR_HMEM_TO_LMEM) { + if (channel->index != DMA_TRACE_CHANNEL) { + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + (phy_off[channel->index] + ACP_SYST_MEM_WINDOW + buff_size); + } else { + dma_config_dscr[dscr_strt_idx + dscr].src_addr = + sgelems->elems[dscr].src + ACP_SYST_MEM_WINDOW; + } + dest = sgelems->elems[dscr].dest; + dest = (dest & ACP_DRAM_ADDRESS_MASK); + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + (dest | ACP_DRAM_ADDR_TRNS); + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + } else { + if (channel->index != DMA_TRACE_CHANNEL) + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + (phy_off[channel->index] + ACP_SYST_MEM_WINDOW + buff_size); + else + dma_config_dscr[dscr_strt_idx + dscr].dest_addr = + (sgelems->elems[dscr].dest + ACP_SYST_MEM_WINDOW); + src = sgelems->elems[dscr].src; + src = (src & ACP_DRAM_ADDRESS_MASK); + dma_config_dscr[dscr_strt_idx + dscr].src_addr = (src | ACP_DRAM_ADDR_TRNS); + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + } + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.u32all = 0; + dma_config_dscr[dscr_strt_idx + dscr].trns_cnt.bits.trns_cnt = + sgelems->elems[dscr].size; + buff_size = sgelems->elems[dscr].size; + } + dma_config_dscr[dscr_strt_idx + (dscr - 1)].trns_cnt.bits.ioc = 0; + dma_cfg = &acp_dma_chan->config[channel->index]; + /* bytes of data to be transferred for the dma */ + tc = dma_config_dscr[dscr_strt_idx].trns_cnt.bits.trns_cnt; + /* DMA configuration for stream */ + if (channel->index != DMA_TRACE_CHANNEL) { + if (!dma_cfg->size) { + acp_dma_chan->dir = dir; + acp_dma_chan->idx = channel->index; + dma_cfg->phy_off = phy_off[channel->index]; + dma_cfg->size = tc * dscr_cnt; + dma_cfg->sys_buff_size = syst_buff_size[channel->index]; + + if (dir == DMA_DIR_HMEM_TO_LMEM) { + /* Playback */ + dma_config_dscr[dscr_strt_idx].dest_addr = + (dma_config_dscr[dscr_strt_idx].dest_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = + dma_config_dscr[dscr_strt_idx].dest_addr | + ACP_DRAM_ADDR_TRNS; + dma_cfg->wr_size = 0; + dma_cfg->rd_size = dma_cfg->size; + } else { + /* Capture */ + dma_config_dscr[dscr_strt_idx].src_addr = + (dma_config_dscr[dscr_strt_idx].src_addr & + ACP_DRAM_ADDRESS_MASK); + dma_cfg->base = + dma_config_dscr[dscr_strt_idx].src_addr | + ACP_DRAM_ADDR_TRNS; + dma_cfg->rd_size = 0; + if (channel->index == dma_cfg->probe_channel) + dma_cfg->wr_size = 0; + else + dma_cfg->wr_size = dma_cfg->size; + } + } + } + /* clear the dma channel control bits */ + dma_cntl = (acp_dma_cntl_0_t)dma_chan_reg_read(channel, ACP_DMA_CNTL_0); + dma_cntl.bits.dmachrun = 0; + dma_cntl.bits.dmachiocen = 0; + dma_chan_reg_write(channel, ACP_DMA_CNTL_0, dma_cntl.u32all); + + /* Program DMAChDscrStrIdx to the index + * number of the first descriptor to be processed. + */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_STRT_IDX_0, dscr_strt_idx); + /* program DMAChDscrdscrcnt to the + * number of descriptors to be processed in the transfer + */ + dma_chan_reg_write(channel, ACP_DMA_DSCR_CNT_0, dscr_cnt); + /* set DMAChPrioLvl according to the priority */ + dma_chan_reg_write(channel, ACP_DMA_PRIO_0, 1); + channel->status = COMP_STATE_PREPARE; + return 0; +} + +int acp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} diff --git a/src/drivers/amd/vangogh/acp_dmic_dma.c b/src/drivers/amd/vangogh/acp_dmic_dma.c new file mode 100644 index 000000000000..a802163a1847 --- /dev/null +++ b/src/drivers/amd/vangogh/acp_dmic_dma.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_dmic_dma.h> + +SOF_DEFINE_REG_UUID(acp_dmic_dma); +DECLARE_TR_CTX(acp_dmic_dma_vgh_tr, SOF_UUID(acp_dmic_dma_uuid), LOG_LEVEL_INFO); + +uint32_t dmic_rngbuff_size; + +int acp_dmic_dma_start(struct dma_chan_data *channel) +{ + acp_wov_pdm_no_of_channels_t pdm_channels; + acp_wov_pdm_decimation_factor_t deci_fctr; + acp_wov_misc_ctrl_t wov_misc_ctrl; + acp_wov_pdm_dma_enable_t pdm_dma_enable; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + uint32_t acp_pdm_en; + + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + channel->status = COMP_STATE_ACTIVE; + if (channel->direction == DMA_DIR_DEV_TO_MEM) { + /* Channel for DMIC */ + pdm_channels.bits.pdm_no_of_channels = 0; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_NO_OF_CHANNELS, + pdm_channels.u32all); + /* Decimation Factor */ + deci_fctr.u32all = 2; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DECIMATION_FACTOR, + deci_fctr.u32all); + /* PDM Control */ + wov_misc_ctrl = (acp_wov_misc_ctrl_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_MISC_CTRL); + wov_misc_ctrl.u32all |= 0x10; + io_reg_write(PU_REGISTER_BASE + ACP_WOV_MISC_CTRL, + wov_misc_ctrl.u32all); + /* PDM Enable */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE, 1); + /* PDM DMA Enable */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE, 1); + /* Check the PDM DMA Enable status bit */ + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + while (!(uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) { + if (deadline < platform_timer_get(timer)) { + /* safe check in case we've got preempted after read */ + if ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) + return 0; + tr_err(&acp_dmic_dma_vgh_tr, "timed out for dma start"); + return -ETIME; + } + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + } + } + return 0; +} + +int acp_dmic_dma_stop(struct dma_chan_data *channel) +{ + acp_wov_pdm_dma_enable_t pdm_dma_enable; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + uint32_t acp_pdm_en; + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * 500 / 1000; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + /* Disable PDM DMA */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE, 0); + /* Disable PDM */ + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + /* Check PDM DMA Status */ + while ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) { + if (deadline < platform_timer_get(timer)) { + /* safe check in case we've got preempted after read */ + if ((uint32_t)pdm_dma_enable.bits.pdm_dma_en_status) + return 0; + tr_err(&acp_dmic_dma_vgh_tr, "timed out for dma stop"); + return -ETIME; + } + pdm_dma_enable = (acp_wov_pdm_dma_enable_t) + io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_DMA_ENABLE); + } + /* Disable PDM */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE, 0); + /* Clear PDM FIFO */ + io_reg_write(PU_REGISTER_BASE + ACP_WOV_PDM_FIFO_FLUSH, 1); + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !acp_pdm_en) { + /* Request SMU to set aclk to minimum aclk */ + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dmic_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t ring_buff_addr; + acp_wov_rx_ringbufsize_t dmic_ringbuff_size; + acp_wov_rx_intr_watermark_size_t watermark; + + channel->is_scheduling_source = true; + channel->direction = config->direction; + switch (config->direction) { + case DMA_DIR_DEV_TO_MEM: + case DMA_DIR_MEM_TO_DEV: + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + ring_buff_addr = (config->elem_array.elems[0].dest | 0x01000000); + /* Load Ring buffer address */ + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_RINGBUFADDR, ring_buff_addr); + /* Load Ring buffer Size */ + dmic_rngbuff_size = (config->elem_array.elems[0].size * + config->elem_array.count); + dmic_ringbuff_size.bits.rx_ringbufsize = dmic_rngbuff_size; + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_RINGBUFSIZE, dmic_ringbuff_size.u32all); + /* Write the ring buffer size to register */ + watermark.bits.rx_intr_watermark_size = (dmic_rngbuff_size >> 1); + io_reg_write(PU_REGISTER_BASE + + ACP_WOV_RX_INTR_WATERMARK_SIZE, watermark.u32all); + break; + default: + tr_err(&acp_dmic_dma_vgh_tr, "unsupported config direction"); + return -EINVAL; + } + if (!config->cyclic) { + tr_err(&acp_dmic_dma_vgh_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_dmic_dma_vgh_tr, "scatter enabled, not supported for now!"); + return -EINVAL; + } + return 0; +} + +int acp_dmic_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; /* Attribute not found */ + } + return 0; +} diff --git a/src/drivers/amd/vangogh/acp_hs_dai.c b/src/drivers/amd/vangogh/acp_hs_dai.c new file mode 100644 index 000000000000..13c72f5f65ef --- /dev/null +++ b/src/drivers/amd/vangogh/acp_hs_dai.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> + +SOF_DEFINE_REG_UUID(hsdai); +DECLARE_TR_CTX(hsdai_tr, SOF_UUID(hsdai_uuid), LOG_LEVEL_INFO); + +static inline int hsdai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + /* set master clk for hs dai */ + io_reg_write(PU_REGISTER_BASE + ACP_I2STDM2_MSTRCLKGEN, 0x40081); + return 0; +} + +static int hsdai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do on vangogh for HS dai */ + return 0; +} + +static int hsdai_probe(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int hsdai_remove(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int hsdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int hsdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + int handshake = dai->plat_data.fifo[direction].handshake; + + interrupt_get_irq(handshake, "irqsteer1"); + return dai->plat_data.fifo[direction].handshake; +} + +static int hsdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + /* HS DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = ACP_DEFAULT_NUM_CHANNELS; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + return 0; +} + +const struct dai_driver acp_hsdai_driver = { + .type = SOF_DAI_AMD_HS, + .uid = SOF_UUID(hsdai_uuid), + .tctx = &hsdai_tr, + .dma_dev = DMA_DEV_HS, + .dma_caps = DMA_CAP_HS, + .ops = { + .trigger = hsdai_trigger, + .set_config = hsdai_set_config, + .probe = hsdai_probe, + .remove = hsdai_remove, + .get_fifo = hsdai_get_fifo, + .get_handshake = hsdai_get_handshake, + .get_hw_params = hsdai_get_hw_params, + }, +}; diff --git a/src/drivers/amd/vangogh/acp_hs_dma.c b/src/drivers/amd/vangogh/acp_hs_dma.c new file mode 100644 index 000000000000..b15a7f5e51b3 --- /dev/null +++ b/src/drivers/amd/vangogh/acp_hs_dma.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +SOF_DEFINE_REG_UUID(acp_hs); +DECLARE_TR_CTX(acp_hs_tr, SOF_UUID(acp_hs_uuid), LOG_LEVEL_INFO); + +#define HS_FIFO_SIZE 512 +#define HS_IER_DISABLE 0x0 +/* Vangogh hw specific addr map */ +#define ACP_DRAM_PHY_TRNS 0x0DEB0000 + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t hs_buff_size; +/* allocate next free DMA channel */ +static struct dma_chan_data *acp_dai_hs_dma_channel_get(struct dma *dma, + unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_hs_tr, "Channel %d not in range", req_chan); + return NULL; + } + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&acp_hs_tr, "channel already in use %d", req_chan); + return NULL; + } + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + return channel; +} + +/* channel must not be running when this is called */ +static void acp_dai_hs_dma_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + notifier_unregister_all(NULL, channel); + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int acp_dai_hs_dma_start(struct dma_chan_data *channel) +{ + acp_hstdm_ier_t hs_ier; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + uint32_t acp_pdm_en; + + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !acp_pdm_en) { + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_ACLK_CLK_SEL); + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + } + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + hs_ier = (acp_hstdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_IER); + hs_ier.bits.hstdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IER), hs_ier.u32all); + hs_iter.bits.hstdm_txen = 1; + hs_iter.bits.hstdm_tx_protocol_mode = 0; + hs_iter.bits.hstdm_tx_data_path_mode = 1; + hs_iter.bits.hstdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_ITER), hs_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + hs_ier = (acp_hstdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_IER); + hs_ier.bits.hstdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IER), hs_ier.u32all); + hs_irer.bits.hstdm_rx_en = 1; + hs_irer.bits.hstdm_rx_protocol_mode = 0; + hs_irer.bits.hstdm_rx_data_path_mode = 1; + hs_irer.bits.hstdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IRER), hs_irer.u32all); + } else { + tr_err(&acp_hs_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_hs_dma_release(struct dma_chan_data *channel) +{ + /* nothing to do on vangogh */ + return 0; +} + +static int acp_dai_hs_dma_pause(struct dma_chan_data *channel) +{ + /* nothing to do on vangogh */ + return 0; +} + +static int acp_dai_hs_dma_stop(struct dma_chan_data *channel) +{ + acp_hstdm_irer_t hs_irer; + acp_hstdm_iter_t hs_iter; + acp_i2stdm_irer_t sp_irer; + acp_i2stdm_iter_t sp_iter; + uint32_t acp_pdm_en; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + hs_iter = (acp_hstdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_ITER); + hs_iter.bits.hstdm_txen = 0; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_ITER), hs_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_READY; + hs_irer = (acp_hstdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_HSTDM_IRER); + hs_irer.bits.hstdm_rx_en = 0; + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IRER), hs_irer.u32all); + } else { + tr_err(&acp_hs_tr, "Stop direction not defined %d", channel->direction); + return -EINVAL; + } + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + acp_pdm_en = (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_WOV_PDM_ENABLE); + if (!hs_iter.bits.hstdm_txen && !hs_irer.bits.hstdm_rx_en && !sp_iter.bits.i2stdm_txen && + !sp_irer.bits.i2stdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_HSTDM_IER), HS_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + if (!acp_pdm_en) { + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + } + return 0; +} + +static int acp_dai_hs_dma_status(struct dma_chan_data *channel, + struct dma_chan_status *status, + uint8_t direction) +{ + /* nothing to do on vangogh */ + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +static int acp_dai_hs_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t hs_buff_addr; + uint32_t hs_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_hs_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_hs_tr, "scatter enabled, that is not supported for now!"); + return -EINVAL; + } + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + channel->is_scheduling_source = true; + channel->direction = config->direction; + hs_buff_size = config->elem_array.elems[0].size * config->elem_array.count; + if (config->direction == DMA_DIR_MEM_TO_DEV) { + /* HS Transmit FIFO Address and FIFO Size*/ + hs_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_transmit_hs_fifo_buffer); + hs_fifo_addr = (hs_fifo_addr & ACP_DRAM_ADDRESS_MASK); + hs_fifo_addr = (hs_fifo_addr - ACP_DRAM_PHY_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_HS_TX_FIFOADDR), hs_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_HS_TX_FIFOSIZE), (uint32_t)(HS_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size*/ + config->elem_array.elems[0].src = + (config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK); + hs_buff_addr = (config->elem_array.elems[0].src | ACP_DRAM_ADDR_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_HS_TX_RINGBUFADDR), hs_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_HS_TX_RINGBUFSIZE), hs_buff_size); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_HS_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE)); + + /* Watermark size for HS transmit FIFO - Half of HS buffer size */ + io_reg_write((PU_REGISTER_BASE + ACP_HS_TX_INTR_WATERMARK_SIZE), + (hs_buff_size >> 1)); + + } else if (config->direction == DMA_DIR_DEV_TO_MEM) { + /* HS Receive FIFO Address and FIFO Size*/ + hs_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_receive_fifo_buffer); + hs_fifo_addr = (hs_fifo_addr & ACP_DRAM_ADDRESS_MASK); + hs_fifo_addr = (hs_fifo_addr - ACP_DRAM_PHY_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_HS_RX_FIFOADDR), hs_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_HS_RX_FIFOSIZE), + (uint32_t)(HS_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size*/ + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + hs_buff_addr = (config->elem_array.elems[0].dest | ACP_DRAM_ADDR_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_HS_RX_RINGBUFADDR), hs_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_HS_RX_RINGBUFSIZE), hs_buff_size); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_HS_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE)); + + /* Watermark size for receive fifo - Half of HS buffer size*/ + io_reg_write((PU_REGISTER_BASE + ACP_HS_RX_INTR_WATERMARK_SIZE), + (hs_buff_size >> 1)); + + } else { + tr_err(&acp_hs_tr, "Config channel direction undefined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +static int acp_dai_hs_dma_copy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + tr_info(&acp_hs_tr, "entry"); + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + return 0; +} + +static int acp_dai_hs_dma_probe(struct dma *dma) +{ + int channel; + + if (dma->chan) { + tr_err(&acp_hs_tr, "Repeated probe"); + return -EEXIST; + } + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * + sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&acp_hs_tr, "Probe failure,unable to allocate channel descriptors"); + return -ENOMEM; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + } + atomic_init(&dma->num_channels_busy, 0); + return 0; +} + +static int acp_dai_hs_dma_remove(struct dma *dma) +{ + if (!dma->chan) { + tr_err(&acp_hs_tr, "remove called without probe,it's a no-op"); + return 0; + } + + rfree(dma->chan); + dma->chan = NULL; + return 0; +} + +static int acp_dai_hs_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_HS_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > hs_buff_size ? + (curr_tx_pos - prev_tx_pos) % hs_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = hs_buff_size - *free; + prev_tx_pos = curr_tx_pos; +#else + *free = (hs_buff_size >> 1); + *avail = (hs_buff_size >> 1); +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_HS_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > hs_buff_size ? + (curr_rx_pos - prev_rx_pos) % hs_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = hs_buff_size - *free; + prev_rx_pos = curr_rx_pos; +#else + *free = (hs_buff_size >> 1); + *avail = (hs_buff_size >> 1); +#endif + } else { + tr_err(&acp_hs_tr, "Channel direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + +static int acp_dai_hs_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; + } + return 0; +} + +static int acp_dai_hs_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1 << channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = + (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} + +const struct dma_ops acp_dai_hs_dma_ops = { + .channel_get = acp_dai_hs_dma_channel_get, + .channel_put = acp_dai_hs_dma_channel_put, + .start = acp_dai_hs_dma_start, + .stop = acp_dai_hs_dma_stop, + .pause = acp_dai_hs_dma_pause, + .release = acp_dai_hs_dma_release, + .copy = acp_dai_hs_dma_copy, + .status = acp_dai_hs_dma_status, + .set_config = acp_dai_hs_dma_set_config, + .interrupt = acp_dai_hs_dma_interrupt, + .probe = acp_dai_hs_dma_probe, + .remove = acp_dai_hs_dma_remove, + .get_data_size = acp_dai_hs_dma_get_data_size, + .get_attribute = acp_dai_hs_dma_get_attribute, +}; diff --git a/src/drivers/amd/vangogh/acp_sp_dai.c b/src/drivers/amd/vangogh/acp_sp_dai.c new file mode 100644 index 000000000000..04754d2f82aa --- /dev/null +++ b/src/drivers/amd/vangogh/acp_sp_dai.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/audio/component.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <ipc/topology.h> +#include <platform/fw_scratch_mem.h> +#include <sof/lib/io.h> +#include <platform/chip_offset_byte.h> + +SOF_DEFINE_REG_UUID(spdai); +DECLARE_TR_CTX(spdai_tr, SOF_UUID(spdai_uuid), LOG_LEVEL_INFO); + +static inline int spdai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + /* nothing to do on vangogh for SP dai */ + io_reg_write(PU_REGISTER_BASE + ACP_I2STDM0_MSTRCLKGEN, 0x40081); + return 0; +} + +static int spdai_trigger(struct dai *dai, int cmd, int direction) +{ + /* nothing to do on vangogh for SP dai */ + return 0; +} + +static int spdai_probe(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int spdai_remove(struct dai *dai) +{ + /* TODO */ + return 0; +} + +static int spdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai_fifo(dai, direction); + default: + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int spdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return dai->plat_data.fifo[direction].handshake; +} + +static int spdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + /* SP DAI currently supports only these parameters */ + params->rate = ACP_DEFAULT_SAMPLE_RATE; + params->channels = ACP_DEFAULT_NUM_CHANNELS; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S16_LE; + return 0; +} + +const struct dai_driver acp_spdai_driver = { + .type = SOF_DAI_AMD_SP, + .uid = SOF_UUID(spdai_uuid), + .tctx = &spdai_tr, + .dma_dev = DMA_DEV_SP, + .dma_caps = DMA_CAP_SP, + .ops = { + .trigger = spdai_trigger, + .set_config = spdai_set_config, + .probe = spdai_probe, + .remove = spdai_remove, + .get_fifo = spdai_get_fifo, + .get_handshake = spdai_get_handshake, + .get_hw_params = spdai_get_hw_params, + }, +}; diff --git a/src/drivers/amd/vangogh/acp_sp_dma.c b/src/drivers/amd/vangogh/acp_sp_dma.c new file mode 100644 index 000000000000..c0bc227e46ef --- /dev/null +++ b/src/drivers/amd/vangogh/acp_sp_dma.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> +#include <platform/acp_sp_dma.h> + +SOF_DEFINE_REG_UUID(acp_sp); +DECLARE_TR_CTX(acp_sp_vgh_tr, SOF_UUID(acp_sp_uuid), LOG_LEVEL_INFO); + +/* Vangogh hw specific addr map */ +#define ACP_DRAM_PHY_TRNS 0x0DEB0000 + +static uint64_t prev_tx_pos; +static uint64_t prev_rx_pos; +static uint32_t sp_buff_size; + +int acp_dai_sp_dma_start(struct dma_chan_data *channel) +{ + acp_i2stdm_ier_t sp_ier; + acp_i2stdm_iter_t sp_iter; + acp_i2stdm_irer_t sp_irer; + + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en) + /* Request SMU to set aclk to 600 Mhz */ + acp_change_clock_notify(600000000); + + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + channel->status = COMP_STATE_ACTIVE; + prev_tx_pos = 0; + sp_ier = (acp_i2stdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IER); + sp_ier.bits.i2stdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), sp_ier.u32all); + sp_iter.bits.i2stdm_txen = 1; + sp_iter.bits.i2stdm_tx_protocol_mode = 0; + sp_iter.bits.i2stdm_tx_data_path_mode = 1; + sp_iter.bits.i2stdm_tx_samp_len = 2; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + channel->status = COMP_STATE_ACTIVE; + prev_rx_pos = 0; + sp_ier = (acp_i2stdm_ier_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IER); + sp_ier.bits.i2stdm_ien = 1; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), sp_ier.u32all); + sp_irer.bits.i2stdm_rx_en = 1; + sp_irer.bits.i2stdm_rx_protocol_mode = 0; + sp_irer.bits.i2stdm_rx_data_path_mode = 1; + sp_irer.bits.i2stdm_rx_samplen = 2; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } else { + tr_err(&acp_sp_vgh_tr, "Start direction not defined %d", channel->direction); + return -EINVAL; + } + + return 0; +} + +int acp_dai_sp_dma_stop(struct dma_chan_data *channel) +{ + acp_i2stdm_irer_t sp_irer; + acp_i2stdm_iter_t sp_iter; + acp_hstdm_iter_t hs_iter; + acp_hstdm_irer_t hs_irer; + + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + if (channel->direction == DMA_DIR_MEM_TO_DEV) { + sp_iter = (acp_i2stdm_iter_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_ITER); + sp_iter.bits.i2stdm_txen = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_ITER), sp_iter.u32all); + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { + sp_irer = (acp_i2stdm_irer_t)io_reg_read(PU_REGISTER_BASE + ACP_I2STDM_IRER); + sp_irer.bits.i2stdm_rx_en = 0; + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IRER), sp_irer.u32all); + } else { + tr_err(&acp_sp_vgh_tr, "Stop direction not defined %d", channel->direction); + return -EINVAL; + } + sp_iter = (acp_i2stdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_ITER)); + sp_irer = (acp_i2stdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_I2STDM_IRER)); + hs_iter = (acp_hstdm_iter_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_ITER)); + hs_irer = (acp_hstdm_irer_t)io_reg_read((PU_REGISTER_BASE + ACP_HSTDM_IRER)); + if (!sp_iter.bits.i2stdm_txen && !sp_irer.bits.i2stdm_rx_en && !hs_iter.bits.hstdm_txen && + !hs_irer.bits.hstdm_rx_en) { + io_reg_write((PU_REGISTER_BASE + ACP_I2STDM_IER), SP_IER_DISABLE); + /* Request SMU to scale down aclk to minimum clk */ + acp_change_clock_notify(0); + io_reg_write((PU_REGISTER_BASE + ACP_CLKMUX_SEL), ACP_INTERNAL_CLK_SEL); + } + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + uint32_t sp_buff_addr; + uint32_t sp_fifo_addr; + + if (!config->cyclic) { + tr_err(&acp_sp_vgh_tr, "cyclic configurations only supported!"); + return -EINVAL; + } + if (config->scatter) { + tr_err(&acp_sp_vgh_tr, "scatter enabled, that is not supported for now!"); + return -EINVAL; + } + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + channel->is_scheduling_source = true; + channel->direction = config->direction; + sp_buff_size = config->elem_array.elems[0].size * config->elem_array.count; + + if (config->direction == DMA_DIR_MEM_TO_DEV) { + /* SP Transmit FIFO Address and FIFO Size*/ + sp_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_transmit_fifo_buffer); + sp_fifo_addr = (sp_fifo_addr & ACP_DRAM_ADDRESS_MASK); + sp_fifo_addr = (sp_fifo_addr - ACP_DRAM_PHY_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_FIFOADDR), sp_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_FIFOSIZE), (uint32_t)(SP_FIFO_SIZE)); + + /* Transmit RINGBUFFER Address and size*/ + config->elem_array.elems[0].src = + (config->elem_array.elems[0].src & ACP_DRAM_ADDRESS_MASK); + sp_buff_addr = (config->elem_array.elems[0].src | ACP_DRAM_ADDR_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_RINGBUFADDR), sp_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_RINGBUFSIZE), sp_buff_size); + + /* Transmit DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + + /* Watermark size for SP transmit FIFO - Half of SP buffer size */ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_TX_INTR_WATERMARK_SIZE), + (sp_buff_size >> 1)); + + } else if (config->direction == DMA_DIR_DEV_TO_MEM) { + /* SP Receive FIFO Address and FIFO Size*/ + sp_fifo_addr = (uint32_t)(&pscratch_mem_cfg->acp_receive_fifo_buffer); + sp_fifo_addr = (sp_fifo_addr & ACP_DRAM_ADDRESS_MASK); + sp_fifo_addr = (sp_fifo_addr - ACP_DRAM_PHY_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_FIFOADDR), sp_fifo_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_FIFOSIZE), + (uint32_t)(SP_FIFO_SIZE)); + + /* Receive RINGBUFFER Address and size*/ + config->elem_array.elems[0].dest = + (config->elem_array.elems[0].dest & ACP_DRAM_ADDRESS_MASK); + sp_buff_addr = (config->elem_array.elems[0].dest | ACP_DRAM_ADDR_TRNS); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR), sp_buff_addr); + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFSIZE), sp_buff_size); + + /* Receive DMA transfer size in bytes */ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_DMA_SIZE), + (uint32_t)(ACP_DMA_TRANS_SIZE_128)); + + /* Watermark size for SP receive fifo - Half of SP buffer size*/ + io_reg_write((PU_REGISTER_BASE + ACP_I2S_RX_INTR_WATERMARK_SIZE), + (sp_buff_size >> 1)); + + } else { + tr_err(&acp_sp_vgh_tr, "DMA Config channel direction undefined %d", + channel->direction); + return -EINVAL; + } + + return 0; +} + +int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t tx_low, curr_tx_pos, tx_high; + tx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW); + tx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); + curr_tx_pos = (uint64_t)((tx_high << 32) | tx_low); + *free = (curr_tx_pos - prev_tx_pos) > sp_buff_size ? + (curr_tx_pos - prev_tx_pos) % sp_buff_size : + (curr_tx_pos - prev_tx_pos); + *avail = sp_buff_size - *free; + prev_tx_pos = curr_tx_pos; +#else + //TODO timer-based scheduling + *free = (sp_buff_size >> 1); + *avail = (sp_buff_size >> 1); +#endif + } else if (channel->direction == DMA_DIR_DEV_TO_MEM) { +#if CONFIG_DISABLE_DESCRIPTOR_SPLIT + uint64_t rx_low, curr_rx_pos, rx_high; + rx_low = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW); + rx_high = (uint32_t)io_reg_read(PU_REGISTER_BASE + + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); + curr_rx_pos = (uint64_t)((rx_high << 32) | rx_low); + *free = (curr_rx_pos - prev_rx_pos) > sp_buff_size ? + (curr_rx_pos - prev_rx_pos) % sp_buff_size : + (curr_rx_pos - prev_rx_pos); + *avail = sp_buff_size - *free; + prev_rx_pos = curr_rx_pos; +#else + //TODO timer-based scheduling + *free = (sp_buff_size >> 1); + *avail = (sp_buff_size >> 1); +#endif + } else { + tr_err(&acp_sp_vgh_tr, "Channel direction not defined %d", channel->direction); + return -EINVAL; + } + return 0; +} + +int acp_dai_sp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = ACP_DMA_BUFFER_ALIGN_128; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: + *value = PLATFORM_DCACHE_ALIGN; + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = ACP_DAI_DMA_BUFFER_PERIOD_COUNT; + break; + default: + return -ENOENT; + } + return 0; +} + +int acp_dai_sp_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + uint32_t status; + acp_dsp0_intr_stat_t acp_intr_stat; + acp_dsp0_intr_cntl_t acp_intr_cntl; + + if (channel->status == COMP_STATE_INIT) + return 0; + switch (cmd) { + case DMA_IRQ_STATUS_GET: + acp_intr_stat = (acp_dsp0_intr_stat_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_STAT); + status = acp_intr_stat.bits.audio_buffer_int_stat; + return (status & (1 << channel->index)); + case DMA_IRQ_CLEAR: + acp_intr_stat.u32all = 0; + acp_intr_stat.bits.audio_buffer_int_stat = + (1 << channel->index); + status = acp_intr_stat.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_STAT, status); + return 0; + case DMA_IRQ_MASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask &= (~(1 << channel->index)); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + case DMA_IRQ_UNMASK: + acp_intr_cntl = (acp_dsp0_intr_cntl_t) + dma_reg_read(channel->dma, ACP_DSP0_INTR_CNTL); + acp_intr_cntl.bits.audio_buffer_int_mask |= (1 << channel->index); + status = acp_intr_cntl.u32all; + dma_reg_write(channel->dma, ACP_DSP0_INTR_CNTL, status); + return 0; + default: + return -EINVAL; + } +} diff --git a/src/drivers/amd/vangogh/interrupt.c b/src/drivers/amd/vangogh/interrupt.c new file mode 100644 index 000000000000..51b0b0e492fb --- /dev/null +++ b/src/drivers/amd/vangogh/interrupt.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +#include <sof/common.h> +#include <platform/chip_offset_byte.h> +#include <platform/chip_registers.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <xtensa/hal.h> +#include <xtensa/config/core.h> +#include <xtensa/config/specreg.h> +#include <xtensa/core-macros.h> +#include "xtos-internal.h" +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(irq_acp); + +DECLARE_TR_CTX(acp_irq_tr, SOF_UUID(irq_acp_uuid), LOG_LEVEL_INFO); + +#define IRQ_INT_MASK(irq) (1 << (irq)) +#define RESERVED_IRQS_NUM 0 +#define IRQS_NUM 9 +#define IRQS_PER_LINE 1 + +static inline uint32_t acp_irq_status_read(uint32_t reg) +{ + return io_reg_read(PU_REGISTER_BASE + reg); +} + +static inline void acp_irq_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(PU_REGISTER_BASE + reg, mask, value); +} + +static uint32_t acp_irq_get_status(uint32_t index) +{ + /* 0-7 interrupts are used */ + if (index > 7) + return 0; + return acp_irq_status_read(ACP_DSP0_INTR_STAT); +} + +static void acp_irq_mask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < RESERVED_IRQS_NUM || irq >= IRQS_NUM) { + tr_err(&acp_irq_tr, "Invalid interrupt"); + return; + } + mask = IRQ_INT_MASK(irq); + acp_irq_update_bits(ACP_DSP0_INTR_CNTL, mask, 0); +} + +static void acp_irq_unmask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < RESERVED_IRQS_NUM || irq >= IRQS_NUM) { + tr_err(&acp_irq_tr, "Invalid interrupt"); + return; + } + mask = IRQ_INT_MASK(irq); + acp_irq_update_bits(ACP_DSP0_INTR_CNTL, mask, mask); +} + +static uint64_t acp_get_irq_interrupts(uint32_t index) +{ + return acp_irq_get_status(index); +} + +static int get_first_irq(uint64_t ints) +{ + return ffs(ints) - 1; +} + +static inline void acp_handle_irq_5(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + int bit; + bool handled; + k_spinlock_key_t key; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); + bit = 5;//bit-23;//HARDCODING + + key = k_spin_lock(&cascade->lock); + + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + k_spin_unlock(&cascade->lock, key); + child->handler(child->handler_arg); + k_spin_lock(&cascade->lock); + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&acp_irq_tr, "irq_handler(): not handled, bit %d", + bit); + acp_irq_mask_int(line_index * IRQS_PER_LINE + bit); + } + } +} + +static inline void acp_handle_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + int bit; + bool handled; + k_spinlock_key_t key; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); + + key = k_spin_lock(&cascade->lock); + + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&acp_irq_tr, "irq_handler(): not handled, bit %d", bit); + acp_irq_mask_int(line_index * IRQS_PER_LINE + bit); + } + } +} + +static void irqhandler_5(void *data) +{ + uint32_t line_index = 5; + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + + line_index = 5; + status = acp_get_irq_interrupts(line_index); + + if (status) + /* Handle current interrupts */ + acp_handle_irq_5(cascade, line_index, status); + else + tr_err(&acp_irq_tr, "invalid interrupt status"); +} + +static inline void irq_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + + status = acp_get_irq_interrupts(line_index); + if (status) + /* Handle current interrupts */ + acp_handle_irq(cascade, line_index, status); + else + tr_err(&acp_irq_tr, "invalid interrupt status"); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + irq_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(0) +DEFINE_IRQ_HANDLER(1) +DEFINE_IRQ_HANDLER(3) +DEFINE_IRQ_HANDLER(4) + +static void acp_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + acp_irq_mask_int(irq); +} + +static void acp_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + acp_irq_unmask_int(irq); +} + +static const struct irq_cascade_ops irq_ops = { + .mask = acp_irq_mask, + .unmask = acp_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .irq = IRQ_NUM_TIMER0, + .handler = irqhandler_0, + .ops = &irq_ops, + .global_mask = false, + }, { + .irq = IRQ_NUM_SOFTWARE0, + .handler = irqhandler_1, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL3, + .handler = irqhandler_3, + .ops = &irq_ops, + .global_mask = false, + }, + { + .irq = IRQ_NUM_EXT_LEVEL4, + .handler = irqhandler_4, + .ops = &irq_ops, + .global_mask = false, + }, + { + .name = "irqsteer1", + .irq = IRQ_NUM_EXT_LEVEL5, + .handler = irqhandler_5, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +void platform_interrupt_init(void) +{ + int i; + + acp_intr_route(); + /* disable all interrupts and their service routines */ + acp_intr_disable(); + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); + acp_intr_enable(); + acp_dsp_sw_intr_enable(); +} + +void platform_interrupt_set(uint32_t irq) +{ + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + switch (irq) { + case IRQ_NUM_TIMER0: + case IRQ_NUM_SOFTWARE0: + case IRQ_NUM_EXT_LEVEL3: + case IRQ_NUM_EXT_LEVEL4: + case IRQ_NUM_EXT_LEVEL5: + arch_interrupt_clear(irq); + break; + default: + break; + } +} + +uint32_t platform_interrupt_get_enabled(void) +{ + /* TODO */ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + arch_interrupt_clear(irq); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + arch_interrupt_set(irq); +} + +void acp_intr_route(void) +{ + dsp_interrupt_routing_ctrl_0_t interrupt_rout_cntl_0; + dsp_interrupt_routing_ctrl_1_t interrupt_rout_cntl_1; + + /* Routing the particular interrupts to the particular level */ + interrupt_rout_cntl_0 = (dsp_interrupt_routing_ctrl_0_t)io_reg_read + ((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_0)); + interrupt_rout_cntl_0.bits.dma_intr_level = acp_interrupt_level_5; + interrupt_rout_cntl_0.bits.az_sw_i2s_intr_level = acp_interrupt_level_5; + io_reg_write((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_0), + interrupt_rout_cntl_0.u32all); + + interrupt_rout_cntl_1 = (dsp_interrupt_routing_ctrl_1_t)io_reg_read + ((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_1)); + interrupt_rout_cntl_1.bits.host_to_dsp_intr1_level = acp_interrupt_level_3; + interrupt_rout_cntl_1.bits.wov_intr_level = acp_interrupt_level_4; + io_reg_write((PU_REGISTER_BASE + DSP_INTERRUPT_ROUTING_CTRL_1), + interrupt_rout_cntl_1.u32all); +} + +void acp_dsp_sw_intr_enable(void) +{ + acp_dsp_sw_intr_cntl_t sw_intr_ctrl_reg; + + xthal_set_intclear(IRQ_NUM_EXT_LEVEL5); + sw_intr_ctrl_reg = (acp_dsp_sw_intr_cntl_t)io_reg_read((PU_REGISTER_BASE + + ACP_DSP_SW_INTR_CNTL)); + sw_intr_ctrl_reg.bits.dsp0_to_host_intr_mask = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_CNTL), sw_intr_ctrl_reg.u32all); + /* Enabling software interuppts */ + platform_interrupt_set(IRQ_NUM_EXT_LEVEL3); +} + +void acp_intr_enable(void) +{ + acp_dsp0_intr_cntl_t interrupt_cntl; + acp_dsp0_intr_stat_t interrupt_sts; + acp_external_intr_enb_t ext_interrupt_enb; + + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL5, 0); + platform_interrupt_clear(IRQ_NUM_TIMER0, 0); + interrupt_sts.u32all = 0; + /* Clear status of all interrupts in ACP_DSP0_INTR_STAT register */ + interrupt_sts.bits.dmaiocstat = 0xFF; + interrupt_sts.bits.audio_buffer_int_stat = 0x3F; + interrupt_sts.bits.wov_dma_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT), + interrupt_sts.u32all); + /* Disable the ACP to Host interrupts */ + ext_interrupt_enb.bits.acpextintrenb = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_EXTERNAL_INTR_ENB), + ext_interrupt_enb.u32all); + interrupt_cntl = (acp_dsp0_intr_cntl_t)io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL)); + interrupt_cntl.u32all = 0; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + interrupt_cntl.bits.dmaiocmask = 0xFF; + interrupt_cntl.bits.audio_buffer_int_mask = INTERRUPT_DISABLE; + interrupt_cntl.bits.wov_dma_intr_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + platform_interrupt_set(IRQ_NUM_EXT_LEVEL5); + platform_interrupt_set(IRQ_NUM_EXT_LEVEL4); +} + +void acp_intr_disable(void) +{ + acp_dsp0_intr_stat_t interrupt_status; + acp_external_intr_enb_t ext_interrupt_enb; + acp_dsp0_intr_cntl_t interrupt_cntl; + + interrupt_status = (acp_dsp0_intr_stat_t)io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_STAT)); + /* Check and Clear all the Interrupt status bits */ + interrupt_status.bits.dmaiocstat = 0xFF; + interrupt_status.bits.audio_buffer_int_stat = 0x3F; + interrupt_status.bits.wov_dma_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_STAT), interrupt_status.u32all); + + /* Disable the ACP to Host interrupts */ + ext_interrupt_enb.bits.acpextintrenb = INTERRUPT_CLEAR; + io_reg_write((PU_REGISTER_BASE + ACP_EXTERNAL_INTR_ENB), ext_interrupt_enb.u32all); + /* Disable all the required ACP interrupts + * in acp_dsp0_intr_cntl_t register + */ + interrupt_cntl = (acp_dsp0_intr_cntl_t)io_reg_read((PU_REGISTER_BASE + + ACP_DSP0_INTR_CNTL)); + interrupt_cntl.bits.dmaiocmask = INTERRUPT_DISABLE; + interrupt_cntl.bits.audio_buffer_int_mask = INTERRUPT_DISABLE; + interrupt_cntl.bits.wov_dma_intr_mask = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP0_INTR_CNTL), interrupt_cntl.u32all); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL5, 0); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL3, 0); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL4, 0); + platform_interrupt_clear(IRQ_NUM_TIMER1, 0); + platform_interrupt_clear(IRQ_NUM_TIMER0, 0); +} + +void acp_dsp_sw_intr_disable(void) +{ + acp_dsp_sw_intr_cntl_t sw_intr_ctrl_reg; + /* Read the register */ + sw_intr_ctrl_reg = (acp_dsp_sw_intr_cntl_t)io_reg_read((PU_REGISTER_BASE + + ACP_DSP_SW_INTR_CNTL)); + sw_intr_ctrl_reg.bits.dsp0_to_host_intr_mask = INTERRUPT_DISABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_CNTL), sw_intr_ctrl_reg.u32all); + platform_interrupt_clear(IRQ_NUM_EXT_LEVEL3, 0); +} + +/* This function triggers a host interrupt from ACP DSP */ +void acp_dsp_to_host_intr_trig(void) +{ + acp_sw_intr_trig_t sw_intr_trig; + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt controller register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* Clear the Acknowledge ( status) for the host to DSP interrupt */ +void acp_ack_intr_from_host(void) +{ + /* acknowledge the host interrupt */ + acp_dsp_sw_intr_stat_t sw_intr_stat; + + sw_intr_stat = (acp_dsp_sw_intr_stat_t)io_reg_read(PU_REGISTER_BASE + + ACP_DSP_SW_INTR_STAT); + sw_intr_stat.bits.host_to_dsp0_intr1_stat = INTERRUPT_ENABLE; + io_reg_write((PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT), sw_intr_stat.u32all); +} diff --git a/src/drivers/amd/vangogh/ipc.c b/src/drivers/amd/vangogh/ipc.c new file mode 100644 index 000000000000..05f3de709310 --- /dev/null +++ b/src/drivers/amd/vangogh/ipc.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <rtos/panic.h> +#include <xtensa/core-macros.h> +#include <platform/chip_offset_byte.h> +#include <platform/chip_registers.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/platform.h> +#include <platform/ipc.h> + +volatile acp_scratch_mem_config_t *pscratch_mem_cfg = (volatile acp_scratch_mem_config_t *) + (PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + +void amd_irq_handler(void *arg) +{ + struct ipc *ipc = arg; + uint32_t status; + uint32_t lock; + acp_dsp_sw_intr_stat_t swintrstat; + acp_sw_intr_trig_t swintrtrig; + + swintrstat = (acp_dsp_sw_intr_stat_t)io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = swintrstat.u32all & HOST_TO_DSP_INTR; + if (status) { + /* Interrupt source */ + if (sof_ipc_host_status()) { + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + while (lock) + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + /* Check if it is response from host */ + if (sof_ipc_host_ack_flag()) { + /* Clear the ACK from host */ + sof_ipc_host_ack_clear(); + /* Clear the Host to DSP Status Register */ + acp_ack_intr_from_host(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t) + io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE; + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), + swintrtrig.u32all); + } + /* Check if new message from host */ + if (sof_ipc_host_msg_flag()) { + /* Clear the msg bit from host */ + sof_ipc_host_msg_clear(); + /* Clear the Host to DSP Status Register */ + acp_ack_intr_from_host(); + ipc_schedule_process(ipc); + } + io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock); + } else { + tr_err(&ipc_tr, "IPC:interrupt without setting flags host status 0x%x", + sof_ipc_host_status()); + } + } +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + acp_sw_intr_trig_t sw_intr_trig; + + /* Set Dsp Ack for msg from host */ + sof_ipc_dsp_ack_set(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t) + io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_host_to_dsp0_intr1 = INTERRUPT_DISABLE; + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + /* now interrupt host to tell it we have sent a message */ + acp_dsp_to_host_intr_trig(); + /* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + if (ipc->pm_prepare_D3) { + while (1) + wait_for_interrupt(0); + } +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + int ret = 0; + acp_sw_intr_trig_t sw_intr_trig; + acp_dsp_sw_intr_stat_t sw_intr_stat; + uint32_t status; + uint32_t lock; + /* Check if host cleared the status for previous messages */ + sw_intr_stat = (acp_dsp_sw_intr_stat_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = sw_intr_stat.bits.dsp0_to_host_intr_stat; + if (sof_ipc_dsp_status() || status) { + sw_intr_stat = (acp_dsp_sw_intr_stat_t) + io_reg_read(PU_REGISTER_BASE + ACP_DSP_SW_INTR_STAT); + status = sw_intr_stat.bits.dsp0_to_host_intr_stat; + return ret; + } + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + while (lock) + lock = io_reg_read(PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0); + /* Write new message in the mailbox */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + /* Need to set DSP message flag */ + sof_ipc_dsp_msg_set(); + /* now interrupt host to tell it we have sent a message */ + acp_dsp_to_host_intr_trig(); + /* Disable the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); + io_reg_write((PU_REGISTER_BASE + ACP_AXI2DAGB_SEM_0), lock); + return ret; +} + +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + diff --git a/src/drivers/dw/Kconfig b/src/drivers/dw/Kconfig index f6b77c0bf42a..552139abc50b 100644 --- a/src/drivers/dw/Kconfig +++ b/src/drivers/dw/Kconfig @@ -14,6 +14,18 @@ config DW_DMA help Select this to enable support for the Designware DMA controller. +config DW_DMA_AGGREGATED_IRQ + bool + default n + help + Some platforms cannot register interrupt per DW-DMA channel + and have the possibility only to register interrupts per + DMA controller, which require manual handling of aggregated + irq. + + Any platforms with DW-DMA aggregated interrupts support + should set this. + config DW_SPI bool default n diff --git a/src/drivers/dw/dma.c b/src/drivers/dw/dma.c index 30a4a212b042..102cbbe0d7ba 100644 --- a/src/drivers/dw/dma.c +++ b/src/drivers/dw/dma.c @@ -20,34 +20,42 @@ * used to construct the DMA configuration for the host client 1 above. */ -#include <sof/atomic.h> +#include <rtos/atomic.h> #include <sof/audio/component.h> -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/common.h> #include <sof/drivers/dw-dma.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/lib/cpu.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> #include <sof/lib/pm_runtime.h> -#include <sof/lib/wait.h> +#include <rtos/wait.h> #include <sof/lib/notifier.h> #include <sof/platform.h> -#include <sof/spinlock.h> +#include <rtos/spinlock.h> #include <ipc/topology.h> -#include <config.h> + #include <errno.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> +LOG_MODULE_REGISTER(dw_dma, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dw_dma); + +DECLARE_TR_CTX(dwdma_tr, SOF_UUID(dw_dma_uuid), LOG_LEVEL_INFO); + /* pointer data for DW DMA buffer */ struct dw_dma_ptr_data { uint32_t current_ptr; uint32_t start_ptr; uint32_t end_ptr; + uint32_t hw_ptr; uint32_t buffer_bytes; }; @@ -66,12 +74,14 @@ struct dw_dma_chan_data { */ static const uint32_t burst_elems[] = {1, 2, 4, 8}; -#if CONFIG_HW_LLI -#define DW_DMA_BUFFER_PERIOD_COUNT 3 +#if CONFIG_DMA_HW_LLI +#define DW_DMA_BUFFER_PERIOD_COUNT 4 #else #define DW_DMA_BUFFER_PERIOD_COUNT 2 #endif +static int dw_dma_stop(struct dma_chan_data *channel); + static void dw_dma_interrupt_mask(struct dma_chan_data *channel) { /* mask block, transfer and error interrupts for channel */ @@ -84,7 +94,7 @@ static void dw_dma_interrupt_mask(struct dma_chan_data *channel) static void dw_dma_interrupt_unmask(struct dma_chan_data *channel) { /* unmask block, transfer and error interrupts for channel */ -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI dma_reg_write(channel->dma, DW_MASK_BLOCK, DW_CHAN_UNMASK(channel->index)); #else @@ -109,7 +119,7 @@ static uint32_t dw_dma_interrupt_status(struct dma_chan_data *channel) { uint32_t status; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI status = dma_reg_read(channel->dma, DW_STATUS_BLOCK); #else status = dma_reg_read(channel->dma, DW_STATUS_TFR); @@ -126,7 +136,7 @@ static void dw_dma_increment_pointer(struct dw_dma_chan_data *chan, int bytes) (chan->ptr_data.current_ptr - chan->ptr_data.end_ptr); } -#if !CONFIG_HW_LLI +#if !CONFIG_DMA_HW_LLI /* reload using LLI data from DMA IRQ cb */ static inline void dw_dma_chan_reload_lli_cb(void *arg, enum notify_id type, void *data) @@ -175,13 +185,13 @@ static inline void dw_dma_chan_reload_lli_cb(void *arg, enum notify_id type, static struct dma_chan_data *dw_dma_channel_get(struct dma *dma, unsigned int req_chan) { - uint32_t flags; + k_spinlock_key_t key; int i; - trace_dwdma("dw_dma_channel_get(): dma %d request channel %d", - dma->plat_data.id, req_chan); + tr_info(&dwdma_tr, "dw_dma_channel_get(): dma %d request channel %d", + dma->plat_data.id, req_chan); - spin_lock_irq(&dma->lock, flags); + key = k_spin_lock(&dma->lock); /* find first free non draining channel */ for (i = 0; i < dma->plat_data.channels; i++) { @@ -193,20 +203,20 @@ static struct dma_chan_data *dw_dma_channel_get(struct dma *dma, dma->chan[i].status = COMP_STATE_READY; atomic_add(&dma->num_channels_busy, 1); -#if !CONFIG_HW_LLI +#if !CONFIG_DMA_HW_LLI notifier_register(&dma->chan[i], &dma->chan[i], - NOTIFIER_ID_DMA_IRQ, dw_dma_chan_reload_lli_cb); + NOTIFIER_ID_DMA_IRQ, dw_dma_chan_reload_lli_cb, 0); #endif /* return channel */ - spin_unlock_irq(&dma->lock, flags); + k_spin_unlock(&dma->lock, key); return &dma->chan[i]; } /* DMA controller has no free channels */ - spin_unlock_irq(&dma->lock, flags); - trace_dwdma_error("dw_dma_channel_get() error: dma %d " - "no free channels", dma->plat_data.id); + k_spin_unlock(&dma->lock, key); + tr_err(&dwdma_tr, "dw_dma_channel_get(): dma %d no free channels", + dma->plat_data.id); return NULL; } @@ -218,6 +228,9 @@ static void dw_dma_channel_put_unlocked(struct dma_chan_data *channel) dw_dma_interrupt_mask(channel); + /* disable linear link position */ + platform_dw_dma_llp_disable(channel->dma, channel); + /* free the lli allocated by set_config*/ if (dw_chan->lli) { rfree(dw_chan->lli); @@ -239,14 +252,14 @@ static void dw_dma_channel_put_unlocked(struct dma_chan_data *channel) /* channel must not be running when this is called */ static void dw_dma_channel_put(struct dma_chan_data *channel) { - uint32_t flags; + k_spinlock_key_t key; - trace_dwdma("dw_dma_channel_put(): dma %d channel %d put", - channel->dma->plat_data.id, channel->index); + tr_info(&dwdma_tr, "dma %d channel %d put", + channel->dma->plat_data.id, channel->index); - spin_lock_irq(&channel->dma->lock, flags); + key = k_spin_lock(&channel->dma->lock); dw_dma_channel_put_unlocked(channel); - spin_unlock_irq(&channel->dma->lock, flags); + k_spin_unlock(&channel->dma->lock, key); } static int dw_dma_start(struct dma_chan_data *channel) @@ -256,37 +269,36 @@ static int dw_dma_start(struct dma_chan_data *channel) struct dw_lli *lli = dw_chan->lli_current; uint32_t flags; int ret = 0; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI uint32_t words_per_tfr = 0; #endif - tracev_dwdma("dw_dma_start(): dma %d channel %d start", - channel->dma->plat_data.id, channel->index); + tr_dbg(&dwdma_tr, "dma %d channel %d start", + channel->dma->plat_data.id, channel->index); irq_local_disable(flags); /* check if channel idle, disabled and ready */ - if (channel->status != COMP_STATE_PREPARE || + if ((channel->status != COMP_STATE_PREPARE && + channel->status != COMP_STATE_PAUSED) || (dma_reg_read(dma, DW_DMA_CHAN_EN) & DW_CHAN(channel->index))) { - trace_dwdma_error("dw_dma_start() error: dma %d channel %d " - "not ready ena 0x%x status 0x%x", - dma->plat_data.id, channel->index, - dma_reg_read(dma, DW_DMA_CHAN_EN), - channel->status); + tr_err(&dwdma_tr, "dma %d channel %d not ready ena 0x%x status 0x%x", + dma->plat_data.id, channel->index, + dma_reg_read(dma, DW_DMA_CHAN_EN), + channel->status); ret = -EBUSY; goto out; } /* is valid stream */ if (!dw_chan->lli) { - trace_dwdma_error("dw_dma_start() error: dma %d channel %d " - "invalid stream", dma->plat_data.id, - channel->index); + tr_err(&dwdma_tr, "dma %d channel %d invalid stream", + dma->plat_data.id, channel->index); ret = -EINVAL; goto out; } -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI /* LLP mode - write LLP pointer unless in scatter mode */ dma_reg_write(dma, DW_LLP(channel->index), (lli->ctrl_lo & (DW_CTLL_LLP_D_EN | DW_CTLL_LLP_S_EN)) ? @@ -304,7 +316,7 @@ static int dw_dma_start(struct dma_chan_data *channel) dma_reg_write(dma, DW_CFG_LOW(channel->index), dw_chan->cfg_lo); dma_reg_write(dma, DW_CFG_HIGH(channel->index), dw_chan->cfg_hi); -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI if (lli->ctrl_lo & DW_CTLL_D_SCAT_EN) { words_per_tfr = (lli->ctrl_hi & DW_CTLH_BLOCK_TS_MASK) >> ((lli->ctrl_lo & DW_CTLL_DST_WIDTH_MASK) >> @@ -336,14 +348,17 @@ static int dw_dma_release(struct dma_chan_data *channel) struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); uint32_t flags; - trace_dwdma("dw_dma_release(): dma %d channel %d release", - channel->dma->plat_data.id, channel->index); + tr_info(&dwdma_tr, "dma %d channel %d release", + channel->dma->plat_data.id, channel->index); irq_local_disable(flags); /* get next lli for proper release */ dw_chan->lli_current = (struct dw_lli *)dw_chan->lli_current->llp; + /* prepare to start */ + dw_dma_stop(channel); + irq_local_enable(flags); return 0; @@ -351,16 +366,21 @@ static int dw_dma_release(struct dma_chan_data *channel) static int dw_dma_pause(struct dma_chan_data *channel) { + struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); + struct dma *dma = channel->dma; uint32_t flags; - trace_dwdma("dw_dma_pause(): dma %d channel %d pause", - channel->dma->plat_data.id, channel->index); + tr_info(&dwdma_tr, "dma %d channel %d pause", + channel->dma->plat_data.id, channel->index); irq_local_disable(flags); if (channel->status != COMP_STATE_ACTIVE) goto out; + dma_reg_write(dma, DW_CFG_LOW(channel->index), + dw_chan->cfg_lo | DW_CFGL_SUSPEND); + /* pause the channel */ channel->status = COMP_STATE_PAUSED; @@ -374,25 +394,24 @@ static int dw_dma_stop(struct dma_chan_data *channel) { struct dma *dma = channel->dma; uint32_t flags; + int ret; -#if CONFIG_HW_LLI || CONFIG_DMA_SUSPEND_DRAIN +#if CONFIG_DMA_HW_LLI || CONFIG_DMA_SUSPEND_DRAIN struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); #endif -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI struct dw_lli *lli = dw_chan->lli; int i; #endif -#if CONFIG_DMA_SUSPEND_DRAIN - int ret; -#endif - trace_dwdma("dw_dma_stop(): dma %d channel %d stop", - dma->plat_data.id, channel->index); + tr_info(&dwdma_tr, "dma %d channel %d stop", + dma->plat_data.id, channel->index); irq_local_disable(flags); - if (channel->status != COMP_STATE_ACTIVE) + if (channel->status != COMP_STATE_ACTIVE && + channel->status != COMP_STATE_PAUSED) goto out; #if CONFIG_DMA_SUSPEND_DRAIN @@ -404,29 +423,37 @@ static int dw_dma_stop(struct dma_chan_data *channel) /* now we wait for FIFO to be empty */ ret = poll_for_register_delay(dma_base(dma) + - DW_CFG_LOW(channel->index), + DW_CFG_LOW(channel->index), DW_CFGL_FIFO_EMPTY, DW_CFGL_FIFO_EMPTY, DW_DMA_TIMEOUT); if (ret < 0) - trace_dwdma_error("dw_dma_stop() error: dma %d channel %d " - "timeout", dma->plat_data.id, channel->index); + tr_err(&dwdma_tr, "dma %d channel %d timeout", + dma->plat_data.id, channel->index); #endif dma_reg_write(dma, DW_DMA_CHAN_EN, DW_CHAN_MASK(channel->index)); -#if CONFIG_HW_LLI + /* wait for channel to be disabled */ + ret = poll_for_register_delay(dma_base(dma) + DW_DMA_CHAN_EN, + DW_CHAN(channel->index), 0, DW_DMA_TIMEOUT); + if (ret < 0) { + tr_err(&dwdma_tr, "dma %d channel %d disable timeout", + dma->plat_data.id, channel->index); + return -ETIMEDOUT; + } + +#if CONFIG_DMA_HW_LLI for (i = 0; i < channel->desc_count; i++) { lli->ctrl_hi &= ~DW_CTLH_DONE(1); lli++; } - dcache_writeback_region(dw_chan->lli, +#ifndef __ZEPHYR__ + dcache_writeback_region((__sparse_force void __sparse_cache *)dw_chan->lli, sizeof(struct dw_lli) * channel->desc_count); #endif - - /* disable linear link position */ - platform_dw_dma_llp_disable(dma, channel); +#endif channel->status = COMP_STATE_PREPARE; @@ -444,37 +471,15 @@ static int dw_dma_status(struct dma_chan_data *channel, status->state = channel->status; status->r_pos = dma_reg_read(channel->dma, DW_SAR(channel->index)); status->w_pos = dma_reg_read(channel->dma, DW_DAR(channel->index)); - status->timestamp = timer_get_system(timer_get()); - - return 0; -} + status->timestamp = sof_cycle_get_64(); -/* mask address for dma to identify memory space. - * It is requested by BYT, HSW, BDW. For other - * platforms, the mask is zero. - */ -static void dw_dma_mask_address(struct dma_sg_elem *sg_elem, - struct dw_lli *lli_desc, uint32_t direction) -{ - lli_desc->sar = sg_elem->src; - lli_desc->dar = sg_elem->dest; + if (status->ipc_posn_data) { + uint32_t *llp = (uint32_t *)status->ipc_posn_data; - switch (direction) { - case DMA_DIR_LMEM_TO_HMEM: - case DMA_DIR_MEM_TO_DEV: - lli_desc->sar |= PLATFORM_DW_DMA_HOST_MASK; - break; - case DMA_DIR_HMEM_TO_LMEM: - case DMA_DIR_DEV_TO_MEM: - lli_desc->dar |= PLATFORM_DW_DMA_HOST_MASK; - break; - case DMA_DIR_MEM_TO_MEM: - lli_desc->sar |= PLATFORM_DW_DMA_HOST_MASK; - lli_desc->dar |= PLATFORM_DW_DMA_HOST_MASK; - break; - default: - break; + platform_dw_dma_llp_read(channel->dma, channel, llp, llp + 1); } + + return 0; } /* set the DMA channel configuration, source/target address, buffer sizes */ @@ -494,8 +499,8 @@ static int dw_dma_set_config(struct dma_chan_data *channel, int ret = 0; int i; - tracev_dwdma("dw_dma_set_config(): dma %d channel %d config", - channel->dma->plat_data.id, channel->index); + tr_dbg(&dwdma_tr, "dma %d channel %d config", + channel->dma->plat_data.id, channel->index); irq_local_disable(flags); @@ -509,19 +514,17 @@ static int dw_dma_set_config(struct dma_chan_data *channel, dw_chan->cfg_hi = DW_CFG_HIGH_DEF; if (!config->elem_array.count) { - trace_dwdma_error("dw_dma_set_config() error: dma %d " - "channel %d no elems", - channel->dma->plat_data.id, channel->index); + tr_err(&dwdma_tr, "dma %d channel %d no elems", + channel->dma->plat_data.id, channel->index); ret = -EINVAL; goto out; } if (config->irq_disabled && config->elem_array.count < DW_DMA_CFG_NO_IRQ_MIN_ELEMS) { - trace_dwdma_error("dw_dma_set_config() error: dma %d channel " - "%d not enough elems for config with irq " - "disabled %d", channel->dma->plat_data.id, - channel->index, config->elem_array.count); + tr_err(&dwdma_tr, "dma %d channel %d not enough elems for config with irq disabled %d", + channel->dma->plat_data.id, + channel->index, config->elem_array.count); ret = -EINVAL; goto out; } @@ -531,19 +534,23 @@ static int dw_dma_set_config(struct dma_chan_data *channel, channel->desc_count = config->elem_array.count; - /* allocate descriptors for channel */ + /* + * Allocate descriptors for channel. They must be cache-line + * size aligned to avoid corrupting adjacent memory when + * synchronizing caches. Such corruption has been observed with + * Zephyr. A generic fix will be implemented for all SOF DMA + * allocations on Zephyr to always force cache-line size + * alignment. + */ if (dw_chan->lli) rfree(dw_chan->lli); - dw_chan->lli = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, - SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, - sizeof(struct dw_lli) * - channel->desc_count); + dw_chan->lli = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, + sizeof(struct dw_lli) * channel->desc_count); if (!dw_chan->lli) { - trace_dwdma_error("dw_dma_set_config() error: dma %d " - "channel %d lli alloc failed", - channel->dma->plat_data.id, - channel->index); + tr_err(&dwdma_tr, "dma %d channel %d lli alloc failed", + channel->dma->plat_data.id, + channel->index); ret = -ENOMEM; goto out; } @@ -593,10 +600,9 @@ static int dw_dma_set_config(struct dma_chan_data *channel, lli_desc->ctrl_lo |= DW_CTLL_SRC_WIDTH(2); break; default: - trace_dwdma_error("dw_dma_set_config() error: dma %d " - "channel %d invalid src width %d", - channel->dma->plat_data.id, - channel->index, config->src_width); + tr_err(&dwdma_tr, "dma %d channel %d invalid src width %d", + channel->dma->plat_data.id, + channel->index, config->src_width); ret = -EINVAL; goto out; } @@ -622,10 +628,9 @@ static int dw_dma_set_config(struct dma_chan_data *channel, lli_desc->ctrl_lo |= DW_CTLL_DST_WIDTH(2); break; default: - trace_dwdma_error("dw_dma_set_config() error: dma %d " - "channel %d invalid dest width %d", - channel->dma->plat_data.id, - channel->index, config->dest_width); + tr_err(&dwdma_tr, "dma %d channel %d invalid dest width %d", + channel->dma->plat_data.id, + channel->index, config->dest_width); ret = -EINVAL; goto out; } @@ -641,7 +646,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, case DMA_DIR_LMEM_TO_HMEM: lli_desc->ctrl_lo |= DW_CTLL_FC_M2M | DW_CTLL_SRC_INC | DW_CTLL_DST_INC; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI lli_desc->ctrl_lo |= DW_CTLL_LLP_S_EN | DW_CTLL_LLP_D_EN; #endif @@ -649,7 +654,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, case DMA_DIR_HMEM_TO_LMEM: lli_desc->ctrl_lo |= DW_CTLL_FC_M2M | DW_CTLL_SRC_INC | DW_CTLL_DST_INC; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI lli_desc->ctrl_lo |= DW_CTLL_LLP_S_EN | DW_CTLL_LLP_D_EN; #endif @@ -657,7 +662,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, case DMA_DIR_MEM_TO_MEM: lli_desc->ctrl_lo |= DW_CTLL_FC_M2M | DW_CTLL_SRC_INC | DW_CTLL_DST_INC; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI lli_desc->ctrl_lo |= DW_CTLL_LLP_S_EN | DW_CTLL_LLP_D_EN; #endif @@ -665,7 +670,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, case DMA_DIR_MEM_TO_DEV: lli_desc->ctrl_lo |= DW_CTLL_FC_M2P | DW_CTLL_SRC_INC | DW_CTLL_DST_FIX; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI lli_desc->ctrl_lo |= DW_CTLL_LLP_S_EN; dw_chan->cfg_lo |= DW_CFG_RELOAD_DST; #endif @@ -676,7 +681,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, case DMA_DIR_DEV_TO_MEM: lli_desc->ctrl_lo |= DW_CTLL_FC_P2M | DW_CTLL_SRC_FIX | DW_CTLL_DST_INC; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI if (!config->scatter) lli_desc->ctrl_lo |= DW_CTLL_LLP_D_EN; else @@ -693,7 +698,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, case DMA_DIR_DEV_TO_DEV: lli_desc->ctrl_lo |= DW_CTLL_FC_P2P | DW_CTLL_SRC_FIX | DW_CTLL_DST_FIX; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI lli_desc->ctrl_lo |= DW_CTLL_LLP_S_EN | DW_CTLL_LLP_D_EN; #endif @@ -701,21 +706,20 @@ static int dw_dma_set_config(struct dma_chan_data *channel, DW_CFGH_DST(config->dest_dev); break; default: - trace_dwdma_error("dw_dma_set_config() error: dma %d " - "channel %d invalid direction %d", - channel->dma->plat_data.id, - channel->index, config->direction); + tr_err(&dwdma_tr, "dma %d channel %d invalid direction %d", + channel->dma->plat_data.id, + channel->index, config->direction); ret = -EINVAL; goto out; } - dw_dma_mask_address(sg_elem, lli_desc, config->direction); + lli_desc->sar = sg_elem->src; + lli_desc->dar = sg_elem->dest; if (sg_elem->size > DW_CTLH_BLOCK_TS_MASK) { - trace_dwdma_error("dw_dma_set_config() error: dma %d " - "channel %d block size too big %d", - channel->dma->plat_data.id, - channel->index, sg_elem->size); + tr_err(&dwdma_tr, "dma %d channel %d block size too big %d", + channel->dma->plat_data.id, + channel->index, sg_elem->size); ret = -EINVAL; goto out; } @@ -736,7 +740,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, lli_desc++; } -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI dw_chan->cfg_lo |= DW_CFG_CTL_HI_UPD_EN; #endif @@ -745,15 +749,17 @@ static int dw_dma_set_config(struct dma_chan_data *channel, lli_desc_tail->llp = (uint32_t)lli_desc_head; } else { lli_desc_tail->llp = 0; -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI lli_desc_tail->ctrl_lo &= ~(DW_CTLL_LLP_S_EN | DW_CTLL_LLP_D_EN); #endif } /* write back descriptors so DMA engine can read them directly */ - dcache_writeback_region(dw_chan->lli, +#ifndef __ZEPHYR__ + dcache_writeback_region((__sparse_force void __sparse_cache *)dw_chan->lli, sizeof(struct dw_lli) * channel->desc_count); +#endif channel->status = COMP_STATE_PREPARE; dw_chan->lli_current = dw_chan->lli; @@ -764,6 +770,7 @@ static int dw_dma_set_config(struct dma_chan_data *channel, dw_chan->ptr_data.end_ptr = dw_chan->ptr_data.start_ptr + dw_chan->ptr_data.buffer_bytes; dw_chan->ptr_data.current_ptr = dw_chan->ptr_data.start_ptr; + dw_chan->ptr_data.hw_ptr = dw_chan->ptr_data.start_ptr; out: irq_local_enable(flags); @@ -771,29 +778,16 @@ static int dw_dma_set_config(struct dma_chan_data *channel, return ret; } -/* restore DMA context after leaving D3 */ -static int dw_dma_pm_context_restore(struct dma *dma) -{ - return 0; -} - -/* store DMA context before leaving D0 */ -static int dw_dma_pm_context_store(struct dma *dma) -{ - /* disable the DMA controller */ - dma_reg_write(dma, DW_DMA_CFG, 0); - - return 0; -} - - static void dw_dma_verify_transfer(struct dma_chan_data *channel, struct dma_cb_data *next) { struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); -#if CONFIG_HW_LLI +#if CONFIG_DMA_HW_LLI +#if defined __ZEPHYR__ + int i; +#else struct dw_lli *lli = platform_dw_dma_lli_get(dw_chan->lli_current); - +#endif switch (next->status) { case DMA_CB_STATUS_END: channel->status = COMP_STATE_PREPARE; @@ -801,12 +795,20 @@ static void dw_dma_verify_transfer(struct dma_chan_data *channel, DW_CHAN_MASK(channel->index)); /* fallthrough */ default: + /* default action is to clear the DONE bit for all LLI making + * sure the cache is coherent between DSP and DMAC. + */ +#if defined __ZEPHYR__ + for (i = 0; i < channel->desc_count; i++) + dw_chan->lli[i].ctrl_hi &= ~DW_CTLH_DONE(1); +#else while (lli->ctrl_hi & DW_CTLH_DONE(1)) { lli->ctrl_hi &= ~DW_CTLH_DONE(1); dw_chan->lli_current = (struct dw_lli *)dw_chan->lli_current->llp; lli = platform_dw_dma_lli_get(dw_chan->lli_current); } +#endif break; } #else @@ -835,9 +837,10 @@ static int dw_dma_copy(struct dma_chan_data *channel, int bytes, .elem = { .size = bytes }, .status = DMA_CB_STATUS_END, }; + k_spinlock_key_t key; - tracev_dwdma("dw_dma_copy(): dma %d channel %d copy", - channel->dma->plat_data.id, channel->index); + tr_dbg(&dwdma_tr, "dma %d channel %d copy", + channel->dma->plat_data.id, channel->index); notifier_event(channel, NOTIFIER_ID_DMA_COPY, NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); @@ -855,14 +858,18 @@ static int dw_dma_copy(struct dma_chan_data *channel, int bytes, DW_DMA_CHAN_EN, DW_CHAN(channel->index), 0, DW_DMA_TIMEOUT); - if (ret < 0) + if (ret < 0) { + tr_dbg(&dwdma_tr, "poll_for_register_delay timeout"); return ret; + } } dw_dma_verify_transfer(channel, &next); /* increment current pointer */ + key = k_spin_lock(&channel->dma->lock); dw_dma_increment_pointer(dw_chan, bytes); + k_spin_unlock(&channel->dma->lock, key); return ret; } @@ -881,8 +888,8 @@ static int dw_dma_setup(struct dma *dma) break; if (!i) { - trace_dwdma_error("dw_dma_setup(): dma %d setup failed", - dma->plat_data.id); + tr_err(&dwdma_tr, "dma %d setup failed", + dma->plat_data.id); return -EIO; } @@ -929,13 +936,12 @@ static int dw_dma_probe(struct dma *dma) pm_runtime_get_sync(DW_DMAC_CLK, dma->plat_data.id); /* allocate dma channels */ - dma->chan = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(struct dma_chan_data) * - dma->plat_data.channels); + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct dma_chan_data) * dma->plat_data.channels); if (!dma->chan) { - trace_dwdma_error("dw_dma_probe() error: dma %d allocaction of " - "channels failed", dma->plat_data.id); + tr_err(&dwdma_tr, "dma %d allocation of channels failed", + dma->plat_data.id); goto out; } @@ -951,13 +957,12 @@ static int dw_dma_probe(struct dma *dma) chan->index = i; chan->core = DMA_CORE_INVALID; - dw_chan = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, + dw_chan = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*dw_chan)); if (!dw_chan) { - trace_dwdma_error("dw_dma_probe() error: dma %d " - "allocaction of channel %d private " - "data failed", dma->plat_data.id, i); + tr_err(&dwdma_tr, "dma %d allocation of channel %d private data failed", + dma->plat_data.id, i); goto out; } @@ -984,7 +989,7 @@ static int dw_dma_remove(struct dma *dma) { int i; - tracev_dwdma("dw_dma_remove(): dma %d remove", dma->plat_data.id); + tr_dbg(&dwdma_tr, "dma %d remove", dma->plat_data.id); pm_runtime_put_sync(DW_DMAC_CLK, dma->plat_data.id); @@ -997,36 +1002,64 @@ static int dw_dma_remove(struct dma *dma) return 0; } +/* capture */ static int dw_dma_avail_data_size(struct dma_chan_data *channel) { struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); int32_t read_ptr = dw_chan->ptr_data.current_ptr; int32_t write_ptr = dma_reg_read(channel->dma, DW_DAR(channel->index)); + int32_t delta = write_ptr - dw_chan->ptr_data.hw_ptr; int size; + dw_chan->ptr_data.hw_ptr = write_ptr; + size = write_ptr - read_ptr; - if (size < 0) + if (size < 0) { size += dw_chan->ptr_data.buffer_bytes; + } else if (!size) { + /* + * Buffer is either full or empty. If the DMA pointer has + * changed, then the DMA has filled the buffer. + */ + if (delta) + size = dw_chan->ptr_data.buffer_bytes; + else + tr_info(&dwdma_tr, "size is 0!"); + } - if (!size) - trace_dwdma("dw_dma_avail_data_size() size is 0!"); + tr_dbg(&dwdma_tr, "DAR %x reader 0x%x free 0x%x avail 0x%x", write_ptr, + read_ptr, dw_chan->ptr_data.buffer_bytes - size, size); return size; } +/* playback */ static int dw_dma_free_data_size(struct dma_chan_data *channel) { struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); int32_t read_ptr = dma_reg_read(channel->dma, DW_SAR(channel->index)); int32_t write_ptr = dw_chan->ptr_data.current_ptr; + int32_t delta = read_ptr - dw_chan->ptr_data.hw_ptr; int size; + dw_chan->ptr_data.hw_ptr = read_ptr; + size = read_ptr - write_ptr; - if (size < 0) + if (size < 0) { size += dw_chan->ptr_data.buffer_bytes; + } else if (!size) { + /* + * Buffer is either full or empty. If the DMA pointer has + * changed, then the DMA has emptied the buffer. + */ + if (delta) + size = dw_chan->ptr_data.buffer_bytes; + else + tr_info(&dwdma_tr, "size is 0!"); + } - if (!size) - trace_dwdma("dw_dma_free_data_size() size is 0!"); + tr_dbg(&dwdma_tr, "SAR %x writer 0x%x free 0x%x avail 0x%x", read_ptr, + write_ptr, size, dw_chan->ptr_data.buffer_bytes - size); return size; } @@ -1034,31 +1067,34 @@ static int dw_dma_free_data_size(struct dma_chan_data *channel) static int dw_dma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) { - uint32_t flags; + struct dw_dma_chan_data *dw_chan = dma_chan_get_data(channel); + k_spinlock_key_t key; int ret = 0; - tracev_dwdma("dw_dma_get_data_size(): dma %d channel %d get data size", - channel->dma->plat_data.id, channel->index); + tr_dbg(&dwdma_tr, "dma %d channel %d get data size", + channel->dma->plat_data.id, channel->index); - irq_local_disable(flags); + key = k_spin_lock(&channel->dma->lock); -#if CONFIG_HW_LLI + if (channel->direction == DMA_DIR_HMEM_TO_LMEM || + channel->direction == DMA_DIR_DEV_TO_MEM) { + *avail = dw_dma_avail_data_size(channel); + *free = dw_chan->ptr_data.buffer_bytes - *avail; + } else { + *free = dw_dma_free_data_size(channel); + *avail = dw_chan->ptr_data.buffer_bytes - *free; + } + + k_spin_unlock(&channel->dma->lock, key); + +#if CONFIG_DMA_HW_LLI if (!(dma_reg_read(channel->dma, DW_DMA_CHAN_EN) & DW_CHAN(channel->index))) { - trace_dwdma_error("dw_dma_get_data_size() error: " - "xrun detected"); + tr_err(&dwdma_tr, "xrun detected"); return -ENODATA; } #endif - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_DEV_TO_MEM) - *avail = dw_dma_avail_data_size(channel); - else - *free = dw_dma_free_data_size(channel); - - irq_local_enable(flags); - return ret; } @@ -1123,8 +1159,6 @@ const struct dma_ops dw_dma_ops = { .copy = dw_dma_copy, .status = dw_dma_status, .set_config = dw_dma_set_config, - .pm_context_restore = dw_dma_pm_context_restore, - .pm_context_store = dw_dma_pm_context_store, .probe = dw_dma_probe, .remove = dw_dma_remove, .get_data_size = dw_dma_get_data_size, diff --git a/src/drivers/dw/ssi-spi.c b/src/drivers/dw/ssi-spi.c index 2acc318089ab..364ea9d19b9c 100644 --- a/src/drivers/dw/ssi-spi.c +++ b/src/drivers/dw/ssi-spi.c @@ -5,34 +5,32 @@ // Author: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> #include <sof/common.h> -#include <sof/debug/panic.h> +#include <rtos/panic.h> #include <sof/drivers/gpio.h> -#include <sof/drivers/ipc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/schedule.h> #include <sof/drivers/spi.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/clk.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <rtos/clk.h> #include <sof/lib/dma.h> #include <sof/lib/io.h> #include <sof/lib/mailbox.h> #include <sof/lib/memory.h> #include <sof/lib/uuid.h> -#include <sof/lib/wait.h> +#include <rtos/wait.h> #include <sof/platform.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <sof/string.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> #include <ipc/header.h> #include <ipc/topology.h> #include <stddef.h> #include <stdint.h> -/* a417b6fb-459d-4cf9-be65-d38dc9057b80 */ -DECLARE_SOF_UUID("spi-completion", spi_compl_task_uuid, 0xa417b6fb, - 0x459d, 0x4cf9, - 0xbe, 0x65, 0xd3, 0x8d, 0xc9, 0x05, 0x7b, 0x80); +SOF_DEFINE_REG_UUID(spi_completion); #define SPI_REG_CTRLR0 0x00 #define SPI_REG_CTRLR1 0x04 @@ -169,9 +167,7 @@ static void spi_stop(struct spi *spi) static void delay(unsigned int ms) { - uint64_t tick = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, ms); - - wait_delay(tick); + wait_delay_ms(ms); } static int spi_trigger(struct spi *spi, int cmd, int direction) @@ -181,7 +177,7 @@ static int spi_trigger(struct spi *spi, int cmd, int direction) switch (cmd) { case SPI_TRIGGER_START: /* trigger the SPI-Slave + DMA + INT + Receiving */ - ret = dma_start(spi->chan[direction]); + ret = dma_start_legacy(spi->chan[direction]); if (ret < 0) return ret; @@ -197,7 +193,7 @@ static int spi_trigger(struct spi *spi, int cmd, int direction) case SPI_TRIGGER_STOP: /* Stop the SPI-Slave */ spi_stop(spi); - dma_stop(spi->chan[direction]); + dma_stop_legacy(spi->chan[direction]); break; default: @@ -281,7 +277,7 @@ static int spi_slave_dma_set_config(struct spi *spi, config.elem_array.count = 1; config.elem_array.elems = &local_sg_elem; - return dma_set_config(chan, &config); + return dma_set_config_legacy(chan, &config); } static int spi_set_config(struct spi *spi, @@ -304,7 +300,8 @@ static enum task_state spi_completion_work(void *data) case IPC_READ: hdr = (struct sof_ipc_hdr *)spi->rx_buffer; - dcache_invalidate_region(spi->rx_buffer, SPI_BUFFER_SIZE); + dcache_invalidate_region((__sparse_force void __sparse_cache *)spi->rx_buffer, + SPI_BUFFER_SIZE); mailbox_hostbox_write(0, spi->rx_buffer, hdr->size); ipc_schedule_process(ipc_get()); @@ -321,7 +318,7 @@ static enum task_state spi_completion_work(void *data) /* configure to receive next header */ spi->ipc_status = IPC_READ; config = spi->config + SPI_DIR_RX; - config->transfer_len = ALIGN_UP(sizeof(*hdr), 16); + config->transfer_len = ALIGN_UP_COMPILE(sizeof(*hdr), 16); spi_set_config(spi, config); spi_trigger(spi, SPI_TRIGGER_START, SPI_DIR_RX); @@ -337,7 +334,7 @@ int spi_push(struct spi *spi, const void *data, size_t size) int ret; if (size > SPI_BUFFER_SIZE) { - trace_ipc_error("ePs"); + tr_err(&ipc_tr, "ePs"); return -ENOBUFS; } @@ -346,7 +343,7 @@ int spi_push(struct spi *spi, const void *data, size_t size) return ret; /* configure transmit path of SPI-slave */ - config->transfer_len = ALIGN_UP(size, 16); + config->transfer_len = ALIGN_UP_COMPILE(size, 16); ret = spi_set_config(spi, config); if (ret < 0) return ret; @@ -357,7 +354,7 @@ int spi_push(struct spi *spi, const void *data, size_t size) ret = memcpy_s(config->src_buf, config->buffer_size, data, size); assert(!ret); - dcache_writeback_region(config->src_buf, size); + dcache_writeback_region((__sparse_force void __sparse_cache *)config->src_buf, size); ret = spi_trigger(spi, SPI_TRIGGER_START, SPI_DIR_TX); if (ret < 0) @@ -389,13 +386,13 @@ static int spi_slave_init(struct spi *spi) /* configure receive path of SPI-slave */ config->dir = SPI_DIR_RX; config->dest_buf = spi->rx_buffer; - config->transfer_len = ALIGN_UP(sizeof(struct sof_ipc_hdr), 16); + config->transfer_len = ALIGN_UP_COMPILE(sizeof(struct sof_ipc_hdr), 16); ret = spi_set_config(spi, config); if (ret < 0) return ret; - dcache_invalidate_region(spi->rx_buffer, SPI_BUFFER_SIZE); + dcache_invalidate_region((__sparse_force void __sparse_cache *)spi->rx_buffer, SPI_BUFFER_SIZE); ret = spi_trigger(spi, SPI_TRIGGER_START, SPI_DIR_RX); if (ret < 0) return ret; @@ -406,7 +403,7 @@ static int spi_slave_init(struct spi *spi) config->src_buf = spi->tx_buffer; config->buffer_size = spi->buffer_size; - spi->completion.private = NULL; + spi->completion.priv_data = NULL; ret = schedule_task_init_ll(&spi->completion, SOF_UUID(spi_compl_task_uuid), @@ -435,11 +432,11 @@ int spi_probe(struct spi *spi) if (!spi->dma[SPI_DIR_TX]) return -ENODEV; - spi->chan[SPI_DIR_RX] = dma_channel_get(spi->dma[SPI_DIR_RX], 0); + spi->chan[SPI_DIR_RX] = dma_channel_get_legacy(spi->dma[SPI_DIR_RX], 0); if (!spi->chan[SPI_DIR_RX]) return -ENODEV; - spi->chan[SPI_DIR_TX] = dma_channel_get(spi->dma[SPI_DIR_TX], 0); + spi->chan[SPI_DIR_TX] = dma_channel_get_legacy(spi->dma[SPI_DIR_TX], 0); if (!spi->chan[SPI_DIR_TX]) return -ENODEV; @@ -454,19 +451,19 @@ int spi_probe(struct spi *spi) /* configure the spi clock */ io_reg_write(SSI_SLAVE_CLOCK_CTL, 0x00000001); - spi->rx_buffer = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_DMA, + spi->rx_buffer = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_DMA, SPI_BUFFER_SIZE); - if (spi->rx_buffer == NULL) { - trace_ipc_error("eSp"); + if (!spi->rx_buffer) { + tr_err(&ipc_tr, "eSp"); return -ENOMEM; } - spi->tx_buffer = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_DMA, + spi->tx_buffer = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_DMA, SPI_BUFFER_SIZE); spi->buffer_size = SPI_BUFFER_SIZE; - if (spi->tx_buffer == NULL) { + if (!spi->tx_buffer) { rfree(spi->rx_buffer); - trace_ipc_error("eSp"); + tr_err(&ipc_tr, "eSp"); return -ENOMEM; } @@ -476,22 +473,23 @@ int spi_probe(struct spi *spi) } /* lock */ -spinlock_t spi_lock; +struct k_spinlock spi_lock; static struct spi *spi_devices; static unsigned int n_spi_devices; struct spi *spi_get(enum spi_type type) { struct spi *spi; - unsigned int i, flags; + unsigned int i; + k_spinlock_key_t key; - spin_lock_irq(&spi_lock, flags); + key = k_spin_lock(&spi_lock); for (i = 0, spi = spi_devices; i < n_spi_devices; i++, spi++) if (spi->plat_data->type == type) break; - spin_unlock_irq(&spi_lock, flags); + k_spin_unlock(&spi_lock, key); return i < n_spi_devices ? spi : NULL; } @@ -499,17 +497,18 @@ struct spi *spi_get(enum spi_type type) int spi_install(const struct spi_platform_data *plat, size_t n) { struct spi *spi; - unsigned int i, flags; + unsigned int i; + k_spinlock_key_t key; int ret; - spin_lock_irq(&spi_lock, flags); + key = k_spin_lock(&spi_lock); if (spi_devices) { ret = -EBUSY; goto unlock; } - spi_devices = rmalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, + spi_devices = rmalloc(SOF_MEM_FLAG_KERNEL, sizeof(*spi) * n); if (!spi_devices) { ret = -ENOMEM; @@ -525,12 +524,12 @@ int spi_install(const struct spi_platform_data *plat, size_t n) } unlock: - spin_unlock_irq(&spi_lock, flags); + k_spin_unlock(&spi_lock, key); return ret; } void spi_init(void) { - spinlock_init(&spi_lock); + k_spinlock_init(&spi_lock); } diff --git a/src/drivers/generic/dummy-dma.c b/src/drivers/generic/dummy-dma.c index 364ccf391b7c..c088d9415d55 100644 --- a/src/drivers/generic/dummy-dma.c +++ b/src/drivers/generic/dummy-dma.c @@ -25,32 +25,32 @@ * holds if you have CONFIG_HOST_PTABLE enabled, at least currently. */ -#include <sof/atomic.h> +#include <rtos/atomic.h> #include <sof/audio/component.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/lib/dma.h> #include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> #include <sof/platform.h> -#include <sof/spinlock.h> -#include <sof/string.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <sys/types.h> #include <ipc/topology.h> #include <user/trace.h> -#include <config.h> + #include <errno.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> -#define trace_dummydma(__e, ...) \ - trace_event(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define tracev_dummydma(__e, ...) \ - tracev_event(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define trace_dummydma_error(__e, ...) \ - trace_error(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) +LOG_MODULE_REGISTER(dummy_dma, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dummy_dma); + +DECLARE_TR_CTX(ddma_tr, SOF_UUID(dummy_dma_uuid), LOG_LEVEL_INFO); struct dma_chan_pdata { struct dma_sg_elem_array *elems; @@ -223,10 +223,10 @@ static ssize_t dummy_dma_do_copies(struct dma_chan_pdata *pdata, int bytes) static struct dma_chan_data *dummy_dma_channel_get(struct dma *dma, unsigned int req_chan) { - uint32_t flags; + k_spinlock_key_t key; int i; - spin_lock_irq(&dma->lock, flags); + key = k_spin_lock(&dma->lock); for (i = 0; i < dma->plat_data.channels; i++) { /* use channel if it's free */ if (dma->chan[i].status == COMP_STATE_INIT) { @@ -235,13 +235,13 @@ static struct dma_chan_data *dummy_dma_channel_get(struct dma *dma, atomic_add(&dma->num_channels_busy, 1); /* return channel */ - spin_unlock_irq(&dma->lock, flags); + k_spin_unlock(&dma->lock, key); return &dma->chan[i]; } } - spin_unlock_irq(&dma->lock, flags); - trace_dummydma_error("dummy-dmac: %d no free channel", - dma->plat_data.id); + k_spin_unlock(&dma->lock, key); + tr_err(&ddma_tr, "dummy-dmac: %d no free channel", + dma->plat_data.id); return NULL; } @@ -272,11 +272,11 @@ static void dummy_dma_channel_put_unlocked(struct dma_chan_data *channel) */ static void dummy_dma_channel_put(struct dma_chan_data *channel) { - uint32_t flags; + k_spinlock_key_t key; - spin_lock_irq(&channel->dma->lock, flags); + key = k_spin_lock(&channel->dma->lock); dummy_dma_channel_put_unlocked(channel); - spin_unlock_irq(&channel->dma->lock, flags); + k_spin_unlock(&channel->dma->lock, key); } /* Since copies are synchronous, the triggers do nothing */ @@ -315,7 +315,7 @@ static int dummy_dma_status(struct dma_chan_data *channel, status->r_pos = ch->r_pos; status->w_pos = ch->w_pos; - status->timestamp = timer_get_system(timer_get()); + status->timestamp = sof_cycle_get_64(); return 0; } @@ -332,15 +332,15 @@ static int dummy_dma_set_config(struct dma_chan_data *channel, struct dma_sg_config *config) { struct dma_chan_pdata *ch = dma_chan_get_data(channel); - uint32_t flags; + k_spinlock_key_t key; int ret = 0; - spin_lock_irq(&channel->dma->lock, flags); + key = k_spin_lock(&channel->dma->lock); if (!config->elem_array.count) { - trace_dummydma_error("dummy-dmac: %d channel %d no DMA descriptors", - channel->dma->plat_data.id, - channel->index); + tr_err(&ddma_tr, "dummy-dmac: %d channel %d no DMA descriptors", + channel->dma->plat_data.id, + channel->index); ret = -EINVAL; goto out; @@ -348,12 +348,12 @@ static int dummy_dma_set_config(struct dma_chan_data *channel, channel->direction = config->direction; - if (config->direction != DMA_DIR_HMEM_TO_LMEM && - config->direction != DMA_DIR_LMEM_TO_HMEM) { + if (config->direction != SOF_DMA_DIR_HMEM_TO_LMEM && + config->direction != SOF_DMA_DIR_LMEM_TO_HMEM) { /* Shouldn't even happen though */ - trace_dummydma_error("dummy-dmac: %d channel %d invalid direction %d", - channel->dma->plat_data.id, channel->index, - config->direction); + tr_err(&ddma_tr, "dummy-dmac: %d channel %d invalid direction %d", + channel->dma->plat_data.id, channel->index, + config->direction); ret = -EINVAL; goto out; } @@ -364,24 +364,10 @@ static int dummy_dma_set_config(struct dma_chan_data *channel, channel->status = COMP_STATE_PREPARE; out: - spin_unlock_irq(&channel->dma->lock, flags); + k_spin_unlock(&channel->dma->lock, key); return ret; } -/* restore DMA context after leaving D3 */ -static int dummy_dma_pm_context_restore(struct dma *dma) -{ - /* Virtual device, no hardware registers */ - return 0; -} - -/* store DMA context after leaving D3 */ -static int dummy_dma_pm_context_store(struct dma *dma) -{ - /* Virtual device, no hardware registers */ - return 0; -} - /** * \brief Perform the DMA copy itself * \param[in] channel The channel to do the copying @@ -417,7 +403,7 @@ static int dummy_dma_copy(struct dma_chan_data *channel, int bytes, /** * \brief Initialize the driver - * \param[in] The preallocated DMA controller structure + * \param[in] dma The preallocated DMA controller structure * \return 0 on success, a negative value on error * * This function must be called before any other will work. Calling functions @@ -430,26 +416,25 @@ static int dummy_dma_probe(struct dma *dma) int i; if (dma->chan) { - trace_dummydma_error("dummy-dmac %d already created!", - dma->plat_data.id); + tr_err(&ddma_tr, "dummy-dmac %d already created!", + dma->plat_data.id); return -EEXIST; /* already created */ } - dma->chan = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, dma->plat_data.channels * sizeof(dma->chan[0])); if (!dma->chan) { - trace_dummydma_error("dummy-dmac %d: Out of memory!", - dma->plat_data.id); + tr_err(&ddma_tr, "dummy-dmac %d: Out of memory!", + dma->plat_data.id); return -ENOMEM; } - chanp = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, + chanp = rzalloc(SOF_MEM_FLAG_KERNEL, dma->plat_data.channels * sizeof(chanp[0])); if (!chanp) { rfree(dma->chan); - trace_dummydma_error("dummy-dmac %d: Out of memory!", - dma->plat_data.id); + tr_err(&ddma_tr, "dummy-dmac %d: Out of memory!", + dma->plat_data.id); dma->chan = NULL; return -ENOMEM; } @@ -458,7 +443,7 @@ static int dummy_dma_probe(struct dma *dma) dma->chan[i].dma = dma; dma->chan[i].index = i; dma->chan[i].status = COMP_STATE_INIT; - dma->chan[i].private = &chanp[i]; + dma_chan_set_data(&dma->chan[i], &chanp[i]); } atomic_init(&dma->num_channels_busy, 0); @@ -479,7 +464,7 @@ static int dummy_dma_probe(struct dma *dma) */ static int dummy_dma_remove(struct dma *dma) { - tracev_dummydma("dummy_dma %d -> remove", dma->plat_data.id); + tr_dbg(&ddma_tr, "dummy_dma %d -> remove", dma->plat_data.id); if (!dma->chan) return 0; @@ -505,15 +490,15 @@ static int dummy_dma_get_data_size(struct dma_chan_data *channel, uint32_t size = dummy_dma_compute_avail_data(pdata); switch (channel->direction) { - case DMA_DIR_HMEM_TO_LMEM: + case SOF_DMA_DIR_HMEM_TO_LMEM: *avail = size; break; - case DMA_DIR_LMEM_TO_HMEM: + case SOF_DMA_DIR_LMEM_TO_HMEM: *free = size; break; default: - trace_dummydma_error("get_data_size direction: %d", - channel->direction); + tr_err(&ddma_tr, "get_data_size direction: %d", + channel->direction); return -EINVAL; } return 0; @@ -556,8 +541,6 @@ const struct dma_ops dummy_dma_ops = { .copy = dummy_dma_copy, .status = dummy_dma_status, .set_config = dummy_dma_set_config, - .pm_context_restore = dummy_dma_pm_context_restore, - .pm_context_store = dummy_dma_pm_context_store, .probe = dummy_dma_probe, .remove = dummy_dma_remove, .get_data_size = dummy_dma_get_data_size, diff --git a/src/drivers/host/CMakeLists.txt b/src/drivers/host/CMakeLists.txt new file mode 100644 index 000000000000..febe0a11b66b --- /dev/null +++ b/src/drivers/host/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + timer.c + ipc.c +) diff --git a/src/drivers/host/ipc.c b/src/drivers/host/ipc.c new file mode 100644 index 000000000000..f53710ab26f2 --- /dev/null +++ b/src/drivers/host/ipc.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +#include <rtos/alloc.h> +#include <sof/ipc/driver.h> +#include <stdlib.h> + +/* testbench ipc */ +struct ipc *_ipc; + +/* private data for IPC */ +struct ipc_data { + struct ipc_data_host_buffer dh_buffer; +}; + +int ipc_platform_compact_write_msg(struct ipc_cmd_hdr *hdr, int words) +{ + return 0; /* number of words read - not currently used on this platform */ +} + +int ipc_platform_compact_read_msg(struct ipc_cmd_hdr *hdr, int words) +{ + return 0; /* number of words read - not currently used on this platform */ +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ +} + +int platform_ipc_init(struct ipc *ipc) +{ + struct ipc_data *iipc; + + _ipc = ipc; + + /* init ipc data */ + iipc = malloc(sizeof(struct ipc_data)); + ipc_set_drvdata(_ipc, iipc); + + /* allocate page table buffer */ + iipc->dh_buffer.page_table = malloc(HOST_PAGE_SIZE); + if (iipc->dh_buffer.page_table) + bzero(iipc->dh_buffer.page_table, HOST_PAGE_SIZE); + + return 0; +} diff --git a/src/drivers/host/timer.c b/src/drivers/host/timer.c new file mode 100644 index 000000000000..5d7900642fc8 --- /dev/null +++ b/src/drivers/host/timer.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Rander Wang <rander.wang@intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/audio/component.h> +#include <rtos/timer.h> +#include <stdint.h> + +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ +} + +/* Add function to avoid tools/oss-fuzz build fail */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = 0; +} + +#ifndef __ZEPHYR__ +uint64_t platform_timer_get(struct timer *timer) +{ + return 0; +} + +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return 0; +} + +void platform_timer_stop(struct timer *timer) +{ +} +#endif /* __ZEPHYR__ */ diff --git a/src/drivers/imx/CMakeLists.txt b/src/drivers/imx/CMakeLists.txt index 94e3c11ecc48..b5dc724256c7 100644 --- a/src/drivers/imx/CMakeLists.txt +++ b/src/drivers/imx/CMakeLists.txt @@ -1,14 +1,29 @@ # SPDX-License-Identifier: BSD-3-Clause add_local_sources(sof - esai.c sai.c - interrupt.c ipc.c timer.c - sdma.c ) if(CONFIG_IMX_EDMA) add_local_sources(sof edma.c) endif() + +if(CONFIG_IMX_ESAI) + add_local_sources(sof esai.c) +endif() + +if(CONFIG_IMX_SDMA) + add_local_sources(sof sdma.c) +endif() + +if(CONFIG_IMX_MICFIL) + add_local_sources(sof micfil.c) +endif() + +if(CONFIG_IMX_INTERRUPT_IRQSTEER) + add_local_sources(sof interrupt-irqsteer.c) +elseif(CONFIG_IMX_INTERRUPT_GENERIC) + add_local_sources(sof interrupt-generic.c) +endif() diff --git a/src/drivers/imx/Kconfig b/src/drivers/imx/Kconfig new file mode 100644 index 000000000000..85f2a50a1162 --- /dev/null +++ b/src/drivers/imx/Kconfig @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config IMX_EDMA + bool "i.MX EDMA driver" + default n + depends on IMX + help + Select this to enable support for i.MX EDMA DMA controller. + +config IMX_SDMA + bool "i.MX SDMA driver" + default n + depends on IMX + help + Select this to enable support for i.MX SDMA DMA controller. + +config IMX_ESAI + bool "i.MX ESAI driver" + default n + depends on IMX + help + Select this to enable support for i.MX ESAI IP. + +config IMX_MICFIL + bool "i.MX MICFIL PDM driver" + default n + depends on IMX + select HAVE_SDMA_FIRMWARE + help + Select this to enable support for i.MX MICFIL PDM IP. This block implements + the required digital interface to provide a 24-bits audio signal from a PDM + microphone bitstream in a configurable output sampling rate + +config IMX_INTERRUPT_IRQSTEER + bool + default n + help + This has to be selected for i.MX NXP platform that have irqsteer. + It enables NXP platforms-specific features. + +config IMX_INTERRUPT_GENERIC + bool + default n + help + This has to be selected for i.MX NXP platform that do not have irqsteer. + It enables NXP platforms-specific features. + +config HAVE_SDMA_FIRMWARE + bool "Enable SDMA firmware load" + default n + help + Select this to load SDMA firmware to enable additional functionality + for SDMA controller. diff --git a/src/drivers/imx/edma.c b/src/drivers/imx/edma.c index 60df010b5137..b21c58bcb02c 100644 --- a/src/drivers/imx/edma.c +++ b/src/drivers/imx/edma.c @@ -7,17 +7,32 @@ #include <sof/audio/component.h> #include <sof/drivers/edma.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> #include <sof/lib/dma.h> #include <sof/lib/io.h> #include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> #include <sof/math/numbers.h> #include <sof/platform.h> #include <errno.h> #include <stddef.h> #include <stdint.h> +LOG_MODULE_REGISTER(edma, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(edma); + +DECLARE_TR_CTX(edma_tr, SOF_UUID(edma_uuid), LOG_LEVEL_INFO); + +static void chan_addr_convert(struct dma_chan_data *channel, uint32_t *sbase, uint32_t *dbase) +{ + if (channel->direction == DMA_DIR_MEM_TO_DEV) + *sbase = local_to_host(*sbase); + else + *dbase = local_to_host(*dbase); +} + static int edma_encode_tcd_attr(int src_width, int dest_width) { int result = 0; @@ -81,28 +96,28 @@ static int edma_encode_tcd_attr(int src_width, int dest_width) static struct dma_chan_data *edma_channel_get(struct dma *dma, unsigned int req_chan) { - uint32_t flags; + k_spinlock_key_t key; struct dma_chan_data *channel; - tracev_edma("EDMA: channel_get(%d)", req_chan); + tr_dbg(&edma_tr, "EDMA: channel_get(%d)", req_chan); - spin_lock_irq(&dma->lock, flags); + key = k_spin_lock(&dma->lock); if (req_chan >= dma->plat_data.channels) { - spin_unlock_irq(&dma->lock, flags); - trace_edma_error("EDMA: Channel %d out of range", req_chan); + k_spin_unlock(&dma->lock, key); + tr_err(&edma_tr, "EDMA: Channel %d out of range", req_chan); return NULL; } channel = &dma->chan[req_chan]; if (channel->status != COMP_STATE_INIT) { - spin_unlock_irq(&dma->lock, flags); - trace_edma_error("EDMA: Cannot reuse channel %d", req_chan); + k_spin_unlock(&dma->lock, key); + tr_err(&edma_tr, "EDMA: Cannot reuse channel %d", req_chan); return NULL; } atomic_add(&dma->num_channels_busy, 1); channel->status = COMP_STATE_READY; - spin_unlock_irq(&dma->lock, flags); + k_spin_unlock(&dma->lock, key); return channel; } @@ -110,33 +125,30 @@ static struct dma_chan_data *edma_channel_get(struct dma *dma, /* channel must not be running when this is called */ static void edma_channel_put(struct dma_chan_data *channel) { - uint32_t flags; + k_spinlock_key_t key; /* Assuming channel is stopped, we thus don't need hardware to * do anything right now */ - trace_edma("EDMA: channel_put(%d)", channel->index); + tr_info(&edma_tr, "EDMA: channel_put(%d)", channel->index); notifier_unregister_all(NULL, channel); - spin_lock_irq(&channel->dma->lock, flags); + key = k_spin_lock(&channel->dma->lock); channel->status = COMP_STATE_INIT; atomic_sub(&channel->dma->num_channels_busy, 1); - spin_unlock_irq(&channel->dma->lock, flags); + k_spin_unlock(&channel->dma->lock, key); } static int edma_start(struct dma_chan_data *channel) { - trace_edma("EDMA: start(%d)", channel->index); + tr_info(&edma_tr, "EDMA: start(%d)", channel->index); if (channel->status != COMP_STATE_PREPARE && - channel->status != COMP_STATE_SUSPEND) + channel->status != COMP_STATE_PAUSED) return -EINVAL; channel->status = COMP_STATE_ACTIVE; - /* Do the HW start of the DMA */ - dma_chan_reg_update_bits(channel, EDMA_TCD_CSR, - EDMA_TCD_CSR_START, EDMA_TCD_CSR_START); /* Allow the HW to automatically trigger further transfers */ dma_chan_reg_update_bits(channel, EDMA_CH_CSR, EDMA_CH_CSR_ERQ_EARQ, EDMA_CH_CSR_ERQ_EARQ); @@ -146,19 +158,19 @@ static int edma_start(struct dma_chan_data *channel) static int edma_release(struct dma_chan_data *channel) { /* TODO actually handle pause/release properly? */ - trace_edma("EDMA: release(%d)", channel->index); + tr_info(&edma_tr, "EDMA: release(%d)", channel->index); if (channel->status != COMP_STATE_PAUSED) return -EINVAL; - channel->status = COMP_STATE_ACTIVE; + channel->status = COMP_STATE_PREPARE; return 0; } static int edma_pause(struct dma_chan_data *channel) { /* TODO actually handle pause/release properly? */ - trace_edma("EDMA: pause(%d)", channel->index); + tr_info(&edma_tr, "EDMA: pause(%d)", channel->index); if (channel->status != COMP_STATE_ACTIVE) return -EINVAL; @@ -173,7 +185,7 @@ static int edma_pause(struct dma_chan_data *channel) static int edma_stop(struct dma_chan_data *channel) { - trace_edma("EDMA: stop(%d)", channel->index); + tr_info(&edma_tr, "EDMA: stop(%d)", channel->index); /* Validate state */ // TODO: Should we? switch (channel->status) { @@ -219,7 +231,7 @@ static int edma_status(struct dma_chan_data *channel, */ status->r_pos = dma_chan_reg_read(channel, EDMA_TCD_SADDR); status->w_pos = dma_chan_reg_read(channel, EDMA_TCD_DADDR); - status->timestamp = timer_get_system(timer_get()); + status->timestamp = sof_cycle_get_64(); return 0; } @@ -271,6 +283,10 @@ static int edma_setup_tcd(struct dma_chan_data *channel, int16_t soff, int dest_width, uint32_t burst_elems) { int rc; +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) + struct dai_data *dd = channel->dev_data; + int direction, handshake, dmamux_cfg; +#endif uint32_t sbase, dbase, total_size, elem_count, elem_size, size; assert(!sg); @@ -304,7 +320,7 @@ static int edma_setup_tcd(struct dma_chan_data *channel, int16_t soff, /* burst_elems is in words translate it in bytes and divide by two * to fill the FIFO to half its size */ - burst_elems = burst_elems * 4U / 2U; + burst_elems = burst_elems * src_width / 2U; size = MIN(elem_size, burst_elems); while (size >= 4U) { @@ -317,6 +333,24 @@ static int edma_setup_tcd(struct dma_chan_data *channel, int16_t soff, if (rc < 0) return rc; +#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. + */ + if (channel->direction == DMA_DIR_MEM_TO_DEV) + direction = DAI_DIR_PLAYBACK; + else + direction = DAI_DIR_CAPTURE; + + handshake = dai_get_handshake(dd->dai, direction, 0); + dmamux_cfg = EDMA_HS_GET_DMAMUX_CFG(handshake); + + if (!dma_chan_reg_read(channel, EDMA_CH_MUX)) + dma_chan_reg_write(channel, EDMA_CH_MUX, dmamux_cfg); +#endif + + chan_addr_convert(channel, &sbase, &dbase); + /* Configure the in-hardware TCD */ dma_chan_reg_write(channel, EDMA_TCD_SADDR, sbase); dma_chan_reg_write16(channel, EDMA_TCD_SOFF, soff); @@ -339,17 +373,10 @@ static int edma_setup_tcd(struct dma_chan_data *channel, int16_t soff, static int edma_set_config(struct dma_chan_data *channel, struct dma_sg_config *config) { - int handshake, irq; int16_t soff = 0; int16_t doff = 0; - /* We may need to pass some data through the handshake in the - * future, so we just have them here, even if unused for now - */ - (void)handshake; - (void)irq; - - trace_edma("EDMA: set config"); + tr_info(&edma_tr, "EDMA: set config"); channel->is_scheduling_source = config->is_scheduling_source; channel->direction = config->direction; @@ -358,24 +385,22 @@ static int edma_set_config(struct dma_chan_data *channel, case DMA_DIR_MEM_TO_DEV: soff = config->src_width; doff = 0; - handshake = config->dest_dev; break; case DMA_DIR_DEV_TO_MEM: soff = 0; doff = config->dest_width; - handshake = config->src_dev; break; default: - trace_edma_error("edma_set_config() unsupported config direction"); + tr_err(&edma_tr, "unsupported config direction"); return -EINVAL; } if (!config->cyclic) { - trace_edma_error("EDMA: Only cyclic configurations are supported!"); + tr_err(&edma_tr, "EDMA: Only cyclic configurations are supported!"); return -EINVAL; } if (config->scatter) { - trace_edma_error("EDMA: scatter enabled, that is not supported for now!"); + tr_err(&edma_tr, "EDMA: scatter enabled, that is not supported for now!"); return -EINVAL; } @@ -385,35 +410,21 @@ static int edma_set_config(struct dma_chan_data *channel, config->dest_width, config->burst_elems); } -/* restore DMA context after leaving D3 */ -static int edma_pm_context_restore(struct dma *dma) -{ - /* External to the DSP, won't lose power */ - return 0; -} - -/* store DMA context after leaving D3 */ -static int edma_pm_context_store(struct dma *dma) -{ - /* External to the DSP, won't lose power */ - return 0; -} - static int edma_probe(struct dma *dma) { int channel; if (dma->chan) { - trace_edma_error("EDMA: Repeated probe"); + tr_err(&edma_tr, "EDMA: Repeated probe"); return -EEXIST; } - trace_edma("EDMA: probe"); + tr_info(&edma_tr, "EDMA: probe"); - dma->chan = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, dma->plat_data.channels * sizeof(struct dma_chan_data)); if (!dma->chan) { - trace_edma_error("EDMA: Probe failure, unable to allocate channel descriptors"); + tr_err(&edma_tr, "EDMA: Probe failure, unable to allocate channel descriptors"); return -ENOMEM; } for (channel = 0; channel < dma->plat_data.channels; channel++) { @@ -428,7 +439,7 @@ static int edma_remove(struct dma *dma) int channel; if (!dma->chan) { - trace_edma_error("EDMA: remove called without probe, it's a no-op"); + tr_err(&edma_tr, "EDMA: remove called without probe, it's a no-op"); return 0; } for (channel = 0; channel < dma->plat_data.channels; channel++) { @@ -530,8 +541,8 @@ static int edma_get_data_size(struct dma_chan_data *channel, *avail = ABS(capture_data_size) / 2; break; default: - trace_edma_error("edma_get_data_size() unsupported direction %d", - channel->direction); + tr_err(&edma_tr, "unsupported direction %d", + channel->direction); return -EINVAL; } return 0; @@ -547,8 +558,6 @@ const struct dma_ops edma_ops = { .copy = edma_copy, .status = edma_status, .set_config = edma_set_config, - .pm_context_restore = edma_pm_context_restore, - .pm_context_store = edma_pm_context_store, .probe = edma_probe, .remove = edma_remove, .interrupt = edma_interrupt, diff --git a/src/drivers/imx/esai.c b/src/drivers/imx/esai.c index 7a83418159d0..60af9bef9e5a 100644 --- a/src/drivers/imx/esai.c +++ b/src/drivers/imx/esai.c @@ -8,15 +8,22 @@ #include <sof/audio/component.h> #include <sof/drivers/edma.h> #include <sof/drivers/esai.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/alloc.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> #include <sof/lib/dai.h> #include <sof/lib/dma.h> +#include <sof/lib/uuid.h> #include <ipc/dai.h> #include <ipc/topology.h> #include <errno.h> #include <stdint.h> +LOG_MODULE_REGISTER(esai, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(esai); + +DECLARE_TR_CTX(esai_tr, SOF_UUID(esai_uuid), LOG_LEVEL_INFO); + struct esai_pdata { struct { uint32_t ecr; @@ -34,67 +41,21 @@ struct esai_pdata { uint32_t prrc; uint32_t pcrc; } regs; + struct sof_ipc_dai_esai_params params; }; -static int esai_context_store(struct dai *dai) -{ - struct esai_pdata *pdata = dai_get_drvdata(dai); - - if (!pdata) - return -EINVAL; - - pdata->regs.ecr = dai_read(dai, REG_ESAI_ECR); - pdata->regs.tfcr = dai_read(dai, REG_ESAI_TFCR); - pdata->regs.rfcr = dai_read(dai, REG_ESAI_RFCR); - pdata->regs.saicr = dai_read(dai, REG_ESAI_SAICR); - pdata->regs.tcr = dai_read(dai, REG_ESAI_TCR); - pdata->regs.tccr = dai_read(dai, REG_ESAI_TCCR); - pdata->regs.rcr = dai_read(dai, REG_ESAI_RCR); - pdata->regs.rccr = dai_read(dai, REG_ESAI_RCCR); - pdata->regs.tsma = dai_read(dai, REG_ESAI_TSMA); - pdata->regs.tsmb = dai_read(dai, REG_ESAI_TSMB); - pdata->regs.rsma = dai_read(dai, REG_ESAI_RSMA); - pdata->regs.rsmb = dai_read(dai, REG_ESAI_RSMB); - pdata->regs.prrc = dai_read(dai, REG_ESAI_PRRC); - pdata->regs.pcrc = dai_read(dai, REG_ESAI_PCRC); - - return 0; -} - -static int esai_context_restore(struct dai *dai) +static inline int esai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) { - struct esai_pdata *pdata = dai_get_drvdata(dai); - - if (!pdata) - return -EINVAL; - - dai_write(dai, REG_ESAI_ECR, ESAI_ECR_ERST); - dai_write(dai, REG_ESAI_ECR, ESAI_ECR_ESAIEN); - dai_write(dai, REG_ESAI_TFCR, pdata->regs.tfcr); - dai_write(dai, REG_ESAI_RFCR, pdata->regs.rfcr); - dai_write(dai, REG_ESAI_SAICR, pdata->regs.saicr); - dai_write(dai, REG_ESAI_TCCR, pdata->regs.tccr); - dai_write(dai, REG_ESAI_RCCR, pdata->regs.rccr); - dai_write(dai, REG_ESAI_TSMA, pdata->regs.tsma); - dai_write(dai, REG_ESAI_TSMB, pdata->regs.tsmb); - dai_write(dai, REG_ESAI_RSMA, pdata->regs.rsma); - dai_write(dai, REG_ESAI_RSMB, pdata->regs.rsmb); - dai_write(dai, REG_ESAI_PRRC, pdata->regs.prrc); - dai_write(dai, REG_ESAI_PCRC, pdata->regs.pcrc); - dai_write(dai, REG_ESAI_TCR, pdata->regs.tcr); - dai_write(dai, REG_ESAI_RCR, pdata->regs.rcr); - dai_write(dai, REG_ESAI_ECR, pdata->regs.ecr); + const struct sof_ipc_dai_config *config = spec_config; + uint32_t xcr = 0, xccr = 0, mask; + struct esai_pdata *esai = dai_get_drvdata(dai); - return 0; -} + dai_dbg(dai, "ESAI: set_config format 0x%04x", + config->format); -static inline int esai_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) -{ - uint32_t xcr = 0, xccr = 0, mask; + esai->params = config->esai; - tracev_esai("ESAI: set_config format 0x%04x", - config->format); switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { case SOF_DAI_FMT_I2S: /* Data on rising edge of bclk, frame low, 1clk before @@ -127,10 +88,10 @@ static inline int esai_set_config(struct dai *dai, xccr |= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP; break; case SOF_DAI_FMT_PDM: - trace_esai_error("ESAI: Unsupported format (PDM)"); + dai_err(dai, "ESAI: Unsupported format (PDM)"); return -EINVAL; default: - trace_esai_error("ESAI: invalid format"); + dai_err(dai, "ESAI: invalid format"); return -EINVAL; } @@ -151,25 +112,25 @@ static inline int esai_set_config(struct dai *dai, xccr ^= ESAI_xCCR_xCKP | ESAI_xCCR_xHCKP | ESAI_xCCR_xFSP; break; default: - trace_esai_error("ESAI: Invalid bit inversion format"); + dai_err(dai, "ESAI: Invalid bit inversion format"); return -EINVAL; } - switch (config->format & SOF_DAI_FMT_MASTER_MASK) { - case SOF_DAI_FMT_CBM_CFM: + switch (config->format & SOF_DAI_FMT_CLOCK_PROVIDER_MASK) { + case SOF_DAI_FMT_CBP_CFP: /* Nothing to do in the registers */ break; - case SOF_DAI_FMT_CBM_CFS: + case SOF_DAI_FMT_CBP_CFC: xccr |= ESAI_xCCR_xFSD; break; - case SOF_DAI_FMT_CBS_CFM: + case SOF_DAI_FMT_CBC_CFP: xccr |= ESAI_xCCR_xCKD; break; - case SOF_DAI_FMT_CBS_CFS: + case SOF_DAI_FMT_CBC_CFC: xccr |= ESAI_xCCR_xFSD | ESAI_xCCR_xCKD; break; default: - trace_esai_error("ESAI: Invalid clock master-slave configuration"); + dai_err(dai, "ESAI: Invalid clock provider-consumer configuration"); return -EINVAL; } @@ -197,8 +158,8 @@ static inline int esai_set_config(struct dai *dai, dai_update_bits(dai, REG_ESAI_TCCR, mask, xccr); /* There is a hardware limitation which prevents tx and rx to be - * simultaneously master or simultaneously slave. As a workaround, - * we will leave tx as master and set rx as slave. + * simultaneously provider or simultaneously consumer. As a workaround, + * we will leave tx as provider and set rx as consumer. */ xccr &= ~(ESAI_xCCR_xCKD | ESAI_xCCR_xFSD); dai_update_bits(dai, REG_ESAI_RCCR, mask, xccr); @@ -350,7 +311,7 @@ static void esai_stop(struct dai *dai, int direction) static int esai_trigger(struct dai *dai, int cmd, int direction) { - tracev_esai("ESAI: trigger"); + dai_dbg(dai, "ESAI: trigger"); switch (cmd) { case COMP_TRIGGER_START: @@ -361,12 +322,8 @@ static int esai_trigger(struct dai *dai, int cmd, int direction) case COMP_TRIGGER_PAUSE: esai_stop(dai, direction); break; - /* Remaining triggers are no-ops */ - case COMP_TRIGGER_SUSPEND: - case COMP_TRIGGER_RESUME: - break; default: - trace_esai_error("ESAI: invalid trigger cmd %d", cmd); + dai_err(dai, "ESAI: invalid trigger cmd %d", cmd); return -EINVAL; } return 0; @@ -376,17 +333,18 @@ static int esai_probe(struct dai *dai) { struct esai_pdata *pdata; - tracev_esai("ESAI: probe"); + dai_dbg(dai, "ESAI: probe"); if (dai_get_drvdata(dai)) { - trace_esai_error("ESAI: Repeated probe, skipping"); + dai_err(dai, "ESAI: Repeated probe, skipping"); return -EEXIST; } - pdata = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*pdata)); + pdata = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*pdata)); if (!pdata) { - trace_esai_error("ESAI probe failure, out of memory"); + dai_err(dai, "ESAI probe failure, out of memory"); return -ENOMEM; } + dai_set_drvdata(dai, pdata); + /* ESAI core reset */ dai_write(dai, REG_ESAI_ECR, ESAI_ECR_ERST | ESAI_ECR_ESAIEN); dai_write(dai, REG_ESAI_ECR, ESAI_ECR_ESAIEN); @@ -405,13 +363,25 @@ static int esai_probe(struct dai *dai) return 0; } +static int esai_remove(struct dai *dai) +{ + struct esai_pdata *pdata = dai_get_drvdata(dai); + + dai_info(dai, "entry"); + + rfree(pdata); + dai_set_drvdata(dai, NULL); + + return 0; +} + static int esai_get_handshake(struct dai *dai, int direction, int stream_id) { int handshake = dai->plat_data.fifo[direction].handshake; int channel = EDMA_HS_GET_CHAN(handshake); int irq = irqstr_get_sof_int(EDMA_HS_GET_IRQ(handshake)); - return EDMA_HANDSHAKE(irq, channel); + return EDMA_HANDSHAKE(irq, channel, 0); } static int esai_get_fifo(struct dai *dai, int direction, int stream_id) @@ -421,7 +391,19 @@ static int esai_get_fifo(struct dai *dai, int direction, int stream_id) case DAI_DIR_CAPTURE: return dai_fifo(dai, direction); /* stream_id is unused */ default: - trace_esai_error("esai_get_fifo(): Invalid direction"); + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int esai_get_fifo_depth(struct dai *dai, int direction) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai->plat_data.fifo[direction].depth; + default: + dai_err(dai, "Invalid direction"); return -EINVAL; } } @@ -430,26 +412,33 @@ static int esai_get_hw_params(struct dai *dai, struct sof_ipc_stream_params *params, int dir) { + struct esai_pdata *esai = dai_get_drvdata(dai); + /* ESAI only currently supports these parameters */ - params->rate = 48000; + params->rate = esai->params.fsync_rate; params->channels = 2; params->buffer_fmt = 0; params->frame_fmt = SOF_IPC_FRAME_S24_4LE; + dai_info(dai, "params->rate = %d, fsync_rate = %d", + params->rate, esai->params.fsync_rate); + return 0; } const struct dai_driver esai_driver = { .type = SOF_DAI_IMX_ESAI, + .uid = SOF_UUID(esai_uuid), + .tctx = &esai_tr, .dma_dev = DMA_DEV_ESAI, .ops = { .trigger = esai_trigger, .set_config = esai_set_config, - .pm_context_store = esai_context_store, - .pm_context_restore = esai_context_restore, .probe = esai_probe, + .remove = esai_remove, .get_handshake = esai_get_handshake, .get_fifo = esai_get_fifo, + .get_fifo_depth = esai_get_fifo_depth, .get_hw_params = esai_get_hw_params, }, }; diff --git a/src/drivers/imx/interrupt-generic.c b/src/drivers/imx/interrupt-generic.c new file mode 100644 index 000000000000..1b5bd0c7c537 --- /dev/null +++ b/src/drivers/imx/interrupt-generic.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Peng Zhang <peng.zhang_8@nxp.com> + +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(generic_irq_imx, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(interrupt); + +DECLARE_TR_CTX(noirq_i_tr, SOF_UUID(interrupt_uuid), LOG_LEVEL_INFO); + +/* this is needed because i.MX8 implementation assumes all boards have an irqsteer. + * Needs to be fixed. + */ +int irqstr_get_sof_int(int irqstr_int) +{ + return irqstr_int; +} + +void platform_interrupt_init(void) {} + +#ifndef __ZEPHYR__ +void platform_interrupt_set(uint32_t irq) +{ + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + arch_interrupt_clear(irq); +} +#endif /* __ZEPHYR__ */ + +uint32_t platform_interrupt_get_enabled(void) +{ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) {} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) {} diff --git a/src/drivers/imx/interrupt-irqsteer.c b/src/drivers/imx/interrupt-irqsteer.c new file mode 100644 index 000000000000..e42dce923bc9 --- /dev/null +++ b/src/drivers/imx/interrupt-irqsteer.c @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2019 NXP +// +// Author: Daniel Baluta <daniel.baluta@nxp.com> +// Author: Paul Olaru <paul.olaru@nxp.com> + +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(irq_imx, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(interrupt); + +DECLARE_TR_CTX(irq_i_tr, SOF_UUID(interrupt_uuid), LOG_LEVEL_INFO); + +/* + * The IRQ_STEER module takes 512 shared interrupts and delivers them + * via 8 interrupt lines to any other component. It supports 5 channels, + * one of them being for the DSP itself (channel 0). + * + * +-----------+ + * IRQ 0-63 ------/64---> | | ---/8----> Channel 0 (DSP) + * IRQ 64-127 ----/64---> | | + * IRQ 128-191 ---/64---> | | ---/8----> Channel 1 (M4) + * IRQ 192-255 ---/64---> | IRQ_STEER | + * IRQ 256-319 ---/64---> | | ---/8----> Channel 2 (SCU2) + * IRQ 320-383 ---/64---> | | ---/8----> Channel 3 (SCU1) + * IRQ 384-447 ---/64---> | | + * IRQ 448-511 ---/64---> | | ---/1----> Channel 4 (CTI) + * +-----------+ + * + * IRQ steer channel block diagram (all 5 channels are identical) + * + * +---------------------------------------------------------+ + * | +---+ +----+ +---+ | + * ---> IRQ 0-63 ---> | | | | | | | + * | [MASK 0-63] --> | & | --/64--> | OR | ---/1---> | & | ----> OUT[0] + * | | | [STATUS] | | [MD0] --> | | | + * | +---+ +----+ +---+ | + * | | + * | ... (same for the other IRQ lines and outputs to OUT[7] | + * | | + * +---------------------------------------------------------+ + * + * In the schematic above: + * IRQ 0-511: Input IRQ lines (shared IRQs). IRQs 0-31 are reserved. + * MASK 0-511: Configurable mask for interrupts. + * MD0-MD7: Master disable register, block an entire output interrupt + * line. + * STATUS: Read only register which shows what interrupts are active. + * OUT: The 8 interrupt lines that lead to the DSP, leading to arch + * IRQs IRQ_NUM_IRQSTR_DSP0 through 7. + * + * Usage of the hardware: We turn on the hardware itself, then we + * configure the mask (all mask bits default to 0), enable our arch + * interrupts and wait for an interrupt on an output line. + * + * Upon receiving an arch interrupt, the driver must check the STATUS + * registers corresponding to the arch interrupt in order to figure out + * what the actual, input shared interrupt was, and then call any + * registered callback to handle the condition leading to the interrupt. + * + * The hardware also supports forcing an interrupt from the software; I + * have omitted this from the schematic since it is not relevant to the + * usage in this driver. + */ + +/* The MASK, SET (unused) and STATUS registers are 512-bit registers + * split into 16 32-bit registers that we can directly access. + * + * To get the proper register for the shared interrupt irq, we do + * IRQSTR_CH_MASK(IRQSTR_INT_REG(irq)) (MASK can be replaced by SET or + * STATUS). + * + * The interrupt mapping to registers is defined in + * platform/drivers/interrupt.h for each platform. + * + * The IRQSTR_CH_* macros perform the second part of this calculation + * (offset) automatically. + */ + +#define IRQSTR_INT_REG(irq) ((irq) / 32) +#define IRQSTR_INT_BIT(irq) ((irq) % 32) +#define IRQSTR_INT_MASK(irq) (1 << IRQSTR_INT_BIT(irq)) + +#if defined(__ZEPHYR__) +#define interrupt_get_irq mux_interrupt_get_irq +#endif + +/* HW register access helper methods */ + +static inline void irqstr_write(uint32_t reg, uint32_t value) +{ + io_reg_write(IRQSTR_BASE_ADDR + reg, value); +} + +static inline uint32_t irqstr_read(uint32_t reg) +{ + return io_reg_read(IRQSTR_BASE_ADDR + reg); +} + +static inline void irqstr_update_bits(uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(IRQSTR_BASE_ADDR + reg, mask, value); +} + +/* IRQ_STEER helper methods + * These methods are usable in any IRQ_STEER driver, not specific to SOF + */ + +static void irqstr_enable_hw(void) +{ + irqstr_write(IRQSTR_CHANCTL, 1); +} + +static void irqstr_disable_hw(void) +{ + irqstr_write(IRQSTR_CHANCTL, 0); +} + +/* irqstr_get_status_word() - Get an interrupt status word + * @index The index of the status word + * + * Get the status of interrupts 32*index .. 32*(index+1)-1 in a word. + * This status is in one hardware register. + * Return: Status register word for the corresponding interrupts + */ +static uint32_t irqstr_get_status_word(uint32_t index) +{ + if (index < IRQSTR_RESERVED_IRQS_NUM / 32) + return 0; + /* On out of range for our platform, be silent */ + if (index >= IRQSTR_IRQS_REGISTERS_NUM) + return 0; + return irqstr_read(IRQSTR_CH_STATUS(index)); +} + +static uint32_t irqstr_fixup_irq(uint32_t irq) +{ +#ifdef CONFIG_IMX8M + return irq - 32; +#else + return irq; +#endif +} + +/* Mask, that is, disable interrupts */ +static void irqstr_mask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < IRQSTR_RESERVED_IRQS_NUM || irq >= IRQSTR_IRQS_NUM) + return; // Unusable interrupts + + irq = irqstr_fixup_irq(irq); + + mask = IRQSTR_INT_MASK(irq); + irqstr_update_bits(IRQSTR_CH_MASK(IRQSTR_INT_REG(irq)), mask, 0); +} + +/* Unmask, that is, enable interrupts */ +static void irqstr_unmask_int(uint32_t irq) +{ + uint32_t mask; + + if (irq < IRQSTR_RESERVED_IRQS_NUM || irq >= IRQSTR_IRQS_NUM) + return; // Unusable interrupts + + irq = irqstr_fixup_irq(irq); + + mask = IRQSTR_INT_MASK(irq); + irqstr_update_bits(IRQSTR_CH_MASK(IRQSTR_INT_REG(irq)), mask, mask); +} + +#ifdef CONFIG_IMX8M + +/* Quirk of the driver in SOF (Quirk is specific to 8MP): + * -> IRQSTR has 5 input channels each with 32 interrupts + * -> IRQSTR has 3 output channels each with 64 interrupts + * -> IRQ in[31:0] => IRQ out[63:32] (output channel #0) + * -> IRQ in[63:32] => IRQ out[95:64] (output channel #1, low half) + * -> IRQ in[95:64] => IRQ out[127:96] (output channel #1, high half) + * -> IRQ in[127:96] => IRQ out[159:128] (output channel #2, low half) + * -> IRQ in[159:128] => IRQ out[191:160] (output channel #2, high half) + * Thus in SOF irqsteer we shift everything with 32 and we get: + * -> Interrupts 0-31 are not usable + * -> Interrupts 32-63 map to hw irqs 0-31 (irqsteer0) + * -> Interrupts 64-127 map to hw irqs 32-95 (irqsteer1) + * -> Interrupts 128-191 map to hw irqs 96-159 (irqsteer2) + */ + +const char * const irq_name_irqsteer[] = { + "irqsteer0", + "irqsteer1", + "irqsteer2" +}; +#else +/* SOF specific part of the driver */ + +/* Quirk of the driver in SOF (Quirk is specific to 8QXP/8QM): + * -> Interrupts 0-31 are hardware + * -> Interrupts 32-63 are unusable, as they are reserved in irqstr. We + * will never get an event on these shared interrupt lines. + * -> Interrupts 64-543 are usable, mapping to 32-512 in IRQSTR itself + * The above functions expect the 32-512 interrupts valid, not the + * shifted SOF ones. + */ + +const char * const irq_name_irqsteer[] = { + "irqsteer0", + "irqsteer1", + "irqsteer2", + "irqsteer3", + "irqsteer4", + "irqsteer5", + "irqsteer6", + "irqsteer7" +}; +#endif + +#define IRQ_MAX_TRIES 1000 + +/* Extract the 64 status bits corresponding to output interrupt line + * index (64 input interrupts) + */ +#ifdef CONFIG_IMX8M +static uint64_t get_irqsteer_interrupts(uint32_t index) +{ + uint64_t result = 0; + + result = irqstr_get_status_word(2 * index); + result <<= 32; + + /* line 0 is special only maps interrupts [63..32], + * interval [31..0] is not used + */ + if (index == 0) + return result; + + result |= irqstr_get_status_word(2 * index - 1); + return result; +} +#else +static uint64_t get_irqsteer_interrupts(uint32_t index) +{ + uint64_t result = irqstr_get_status_word(2 * index + 1); + + result <<= 32; + result |= irqstr_get_status_word(2 * index); + return result; +} +#endif + +/** + * get_first_irq() Get the first IRQ bit set in this group. + * + * Get the first pending IRQ in the group. For example, get_first_irq(0x40) + * will return 6 (as 1 << 6 is 0x40), while get_first_irq(0) will return -1. + * + * @param ints The 64 input interrupts + * @return -1 if all interrupts are clear, or a shift value if at least + * one interrupt is set. + */ +static int get_first_irq(uint64_t ints) +{ + return ffsll(ints) - 1; +} + +static inline void handle_irq_batch(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + int bit; + bool handled; + k_spinlock_key_t key; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); /* Release interrupt */ + + key = k_spin_lock(&cascade->lock); + + /* Get child if any and run handler */ + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + /* run handler in non atomic context */ + k_spin_unlock(&cascade->lock, key); + child->handler(child->handler_arg); + k_spin_lock(&cascade->lock); + + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&irq_i_tr, "irq_handler(): nobody cared, bit %d", + bit); + /* Mask this interrupt so it won't happen again */ + irqstr_mask_int(line_index * IRQSTR_IRQS_PER_LINE + bit); + } + } +} + +static inline void irq_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + uint32_t tries = IRQ_MAX_TRIES; + + status = get_irqsteer_interrupts(line_index); + + while (status) { + /* Handle current interrupts */ + handle_irq_batch(cascade, line_index, status); + + /* Any interrupts happened while we were handling the + * current ones? + */ + status = get_irqsteer_interrupts(line_index); + if (!status) + break; + + /* Any device keeping interrupting while we're handling + * or can't clear? + */ + + if (!--tries) { + tries = IRQ_MAX_TRIES; + tr_err(&irq_i_tr, "IRQ storm, status 0x%08x%08x", + (uint32_t)(status >> 32), (uint32_t)status); + } + } +} + +#define DEFINE_IRQ_HANDLER(n) \ + static inline void irqstr_irqhandler_##n(void *arg) \ + { \ + irq_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(0) +DEFINE_IRQ_HANDLER(1) +DEFINE_IRQ_HANDLER(2) +DEFINE_IRQ_HANDLER(3) +DEFINE_IRQ_HANDLER(4) +DEFINE_IRQ_HANDLER(5) +DEFINE_IRQ_HANDLER(6) +DEFINE_IRQ_HANDLER(7) + +static void irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + uint32_t irq_base = desc->irq - IRQ_NUM_IRQSTR_DSP0; + + /* Compute the actual IRQ_STEER IRQ number */ + irq_base *= IRQSTR_IRQS_PER_LINE; + irq += irq_base; + + irqstr_mask_int(irq); +} + +static void irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + uint32_t irq_base = desc->irq - IRQ_NUM_IRQSTR_DSP0; + + /* Compute the actual IRQ_STEER IRQ number */ + irq_base *= IRQSTR_IRQS_PER_LINE; + irq += irq_base; + + irqstr_unmask_int(irq); +} + +static const struct irq_cascade_ops irq_ops = { + .mask = irq_mask, + .unmask = irq_unmask, +}; + +/* IRQ_STEER interrupts */ +#define IRQSTR_CASCADE_TMPL_DECL(n) \ + { \ + .name = "irqsteer" #n, \ + .irq = IRQ_NUM_IRQSTR_DSP##n, \ + .handler = irqstr_irqhandler_##n, \ + .ops = &irq_ops, \ + .global_mask = false, \ + }, + +static const struct irq_cascade_tmpl dsp_irq[] = { + IRQSTR_CASCADE_TMPL_DECL(0) + IRQSTR_CASCADE_TMPL_DECL(1) + IRQSTR_CASCADE_TMPL_DECL(2) + IRQSTR_CASCADE_TMPL_DECL(3) + IRQSTR_CASCADE_TMPL_DECL(4) + IRQSTR_CASCADE_TMPL_DECL(5) + IRQSTR_CASCADE_TMPL_DECL(6) + IRQSTR_CASCADE_TMPL_DECL(7) +}; + +int irqstr_get_sof_int(int irqstr_int) +{ + int line, irq; + + /* Is it a valid interrupt? */ + if (irqstr_int < 0 || irqstr_int >= IRQSTR_IRQS_NUM) + return -EINVAL; + + line = irqstr_int / IRQSTR_IRQS_PER_LINE; + irq = irqstr_int % IRQSTR_IRQS_PER_LINE; + + return interrupt_get_irq(irq, irq_name_irqsteer[line]); +} + +void platform_interrupt_init(void) +{ + int i; + + /* Turn off the hardware so we don't have stray interrupts while + * initializing + */ + irqstr_disable_hw(); + /* Mask every external IRQ first */ + for (i = 0; i < IRQSTR_IRQS_REGISTERS_NUM; i++) + irqstr_write(IRQSTR_CH_MASK(i), 0); + /* Turn on the IRQ_STEER hardware */ + irqstr_enable_hw(); + + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); +} + +#ifndef __ZEPHYR__ +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + +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) +{ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->mask) + cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, + cpu); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->unmask) + cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, + cpu); +} diff --git a/src/drivers/imx/interrupt.c b/src/drivers/imx/interrupt.c deleted file mode 100644 index 20b114b8899f..000000000000 --- a/src/drivers/imx/interrupt.c +++ /dev/null @@ -1,430 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright 2019 NXP -// -// Author: Daniel Baluta <daniel.baluta@nxp.com> -// Author: Paul Olaru <paul.olaru@nxp.com> - -#include <sof/common.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/cpu.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/list.h> -#include <sof/spinlock.h> -#include <errno.h> -#include <inttypes.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* - * The IRQ_STEER module takes 512 shared interrupts and delivers them - * via 8 interrupt lines to any other component. It supports 5 channels, - * one of them being for the DSP itself (channel 0). - * - * +-----------+ - * IRQ 0-63 ------/64---> | | ---/8----> Channel 0 (DSP) - * IRQ 64-127 ----/64---> | | - * IRQ 128-191 ---/64---> | | ---/8----> Channel 1 (M4) - * IRQ 192-255 ---/64---> | IRQ_STEER | - * IRQ 256-319 ---/64---> | | ---/8----> Channel 2 (SCU2) - * IRQ 320-383 ---/64---> | | ---/8----> Channel 3 (SCU1) - * IRQ 384-447 ---/64---> | | - * IRQ 448-511 ---/64---> | | ---/1----> Channel 4 (CTI) - * +-----------+ - * - * IRQ steer channel block diagram (all 5 channels are identical) - * - * +---------------------------------------------------------+ - * | +---+ +----+ +---+ | - * ---> IRQ 0-63 ---> | | | | | | | - * | [MASK 0-63] --> | & | --/64--> | OR | ---/1---> | & | ----> OUT[0] - * | | | [STATUS] | | [MD0] --> | | | - * | +---+ +----+ +---+ | - * | | - * | ... (same for the other IRQ lines and outputs to OUT[7] | - * | | - * +---------------------------------------------------------+ - * - * In the schematic above: - * IRQ 0-511: Input IRQ lines (shared IRQs). IRQs 0-31 are reserved. - * MASK 0-511: Configurable mask for interrupts. - * MD0-MD7: Master disable register, block an entire output interrupt - * line. - * STATUS: Read only register which shows what interrupts are active. - * OUT: The 8 interrupt lines that lead to the DSP, leading to arch - * IRQs IRQ_NUM_IRQSTR_DSP0 through 7. - * - * Usage of the hardware: We turn on the hardware itself, then we - * configure the mask (all mask bits default to 0), enable our arch - * interrupts and wait for an interrupt on an output line. - * - * Upon receiving an arch interrupt, the driver must check the STATUS - * registers corresponding to the arch interrupt in order to figure out - * what the actual, input shared interrupt was, and then call any - * registered callback to handle the condition leading to the interrupt. - * - * The hardware also supports forcing an interrupt from the software; I - * have omitted this from the schematic since it is not relevant to the - * usage in this driver. - */ - -/* The MASK, SET (unused) and STATUS registers are 512-bit registers - * split into 16 32-bit registers that we can directly access. - * - * To get the proper register for the shared interrupt irq, we do - * IRQSTR_CH_MASK(IRQSTR_INT_REG(irq)) (MASK can be replaced by SET or - * STATUS). - * - * The interrupt mapping to registers is defined in - * platform/drivers/interrupt.h for each platform. - * - * The IRQSTR_CH_* macros perform the second part of this calculation - * (offset) automatically. - */ - -#define IRQSTR_INT_REG(irq) ((irq) / 32) -#define IRQSTR_INT_BIT(irq) ((irq) % 32) -#define IRQSTR_INT_MASK(irq) (1 << IRQSTR_INT_BIT(irq)) - -/* HW register access helper methods */ - -static inline void irqstr_write(uint32_t reg, uint32_t value) -{ - io_reg_write(IRQSTR_BASE_ADDR + reg, value); -} - -static inline uint32_t irqstr_read(uint32_t reg) -{ - return io_reg_read(IRQSTR_BASE_ADDR + reg); -} - -static inline void irqstr_update_bits(uint32_t reg, uint32_t mask, - uint32_t value) -{ - io_reg_update_bits(IRQSTR_BASE_ADDR + reg, mask, value); -} - -/* IRQ_STEER helper methods - * These methods are usable in any IRQ_STEER driver, not specific to SOF - */ - -static void irqstr_enable_hw(void) -{ - irqstr_write(IRQSTR_CHANCTL, 1); -} - -static void irqstr_disable_hw(void) -{ - irqstr_write(IRQSTR_CHANCTL, 0); -} - -/* irqstr_get_status_word() - Get an interrupt status word - * @index The index of the status word - * - * Get the status of interrupts 32*index .. 32*(index+1)-1 in a word. - * This status is in one hardware register. - * Return: Status register word for the corresponding interrupts - */ -static uint32_t irqstr_get_status_word(uint32_t index) -{ - if (index < IRQSTR_RESERVED_IRQS_NUM / 32) - return 0; - /* On out of range for our platform, be silent */ - if (index >= IRQSTR_IRQS_REGISTERS_NUM) - return 0; - return irqstr_read(IRQSTR_CH_STATUS(index)); -} - -/* Mask, that is, disable interrupts */ -static void irqstr_mask_int(uint32_t irq) -{ - uint32_t mask; - - if (irq < IRQSTR_RESERVED_IRQS_NUM || irq >= IRQSTR_IRQS_NUM) - return; // Unusable interrupts - mask = IRQSTR_INT_MASK(irq); - irqstr_update_bits(IRQSTR_CH_MASK(IRQSTR_INT_REG(irq)), mask, 0); -} - -/* Unmask, that is, enable interrupts */ -static void irqstr_unmask_int(uint32_t irq) -{ - uint32_t mask; - - if (irq < IRQSTR_RESERVED_IRQS_NUM || irq >= IRQSTR_IRQS_NUM) - return; // Unusable interrupts - mask = IRQSTR_INT_MASK(irq); - irqstr_update_bits(IRQSTR_CH_MASK(IRQSTR_INT_REG(irq)), mask, mask); -} - -/* SOF specific part of the driver */ - -/* Quirk of the driver in SOF (Quirk is specific to 8QXP/8QM): - * -> Interrupts 0-31 are hardware - * -> Interrupts 32-63 are unusable, as they are reserved in irqstr. We - * will never get an event on these shared interrupt lines. - * -> Interrupts 64-543 are usable, mapping to 32-512 in IRQSTR itself - * The above functions expect the 32-512 interrupts valid, not the - * shifted SOF ones. - */ - -const char * const irq_name_irqsteer[] = { - "irqsteer0", - "irqsteer1", - "irqsteer2", - "irqsteer3", - "irqsteer4", - "irqsteer5", - "irqsteer6", - "irqsteer7" -}; - -#define IRQ_MAX_TRIES 1000 - -/* Extract the 64 status bits corresponding to output interrupt line - * index (64 input interrupts) - */ -static uint64_t get_irqsteer_interrupts(uint32_t index) -{ - uint64_t result = irqstr_get_status_word(2 * index + 1); - - result <<= 32; - result |= irqstr_get_status_word(2 * index); - return result; -} - -/** - * get_first_irq() Get the first IRQ bit set in this group. - * @ints The 64 input interrupts - * - * Get the first pending IRQ in the group. For example, get_first_irq(0x40) - * will return 6 (as 1 << 6 is 0x40), while get_first_irq(0) will return -1. - * - * Return: -1 if all interrupts are clear, or a shift value if at least - * one interrupt is set. - */ -static int get_first_irq(uint64_t ints) -{ - return ffsll(ints) - 1; -} - -static inline void handle_irq_batch(struct irq_cascade_desc *cascade, - uint32_t line_index, uint64_t status) -{ - int core = cpu_get_id(); - struct list_item *clist; - struct irq_desc *child = NULL; - int bit; - bool handled; - - while (status) { - bit = get_first_irq(status); - handled = false; - status &= ~(1ull << bit); /* Release interrupt */ - - spin_lock(&cascade->lock); - - /* Get child if any and run handler */ - list_for_item(clist, &cascade->child[bit].list) { - child = container_of(clist, struct irq_desc, irq_list); - - if (child->handler && (child->cpu_mask & 1 << core)) { - /* run handler in non atomic context */ - spin_unlock(&cascade->lock); - child->handler(child->handler_arg); - spin_lock(&cascade->lock); - - handled = true; - } - - platform_shared_commit(child, sizeof(*child)); - } - - platform_shared_commit(cascade, sizeof(*cascade)); - - spin_unlock(&cascade->lock); - - if (!handled) { - trace_irq_error("irq_handler(): nobody cared, bit %d", - bit); - /* Mask this interrupt so it won't happen again */ - irqstr_mask_int(line_index * IRQSTR_IRQS_PER_LINE + bit); - } - } -} - -static inline void irq_handler(void *data, uint32_t line_index) -{ - struct irq_desc *parent = data; - struct irq_cascade_desc *cascade = - container_of(parent, struct irq_cascade_desc, desc); - uint64_t status; - uint32_t tries = IRQ_MAX_TRIES; - - status = get_irqsteer_interrupts(line_index); - - while (status) { - /* Handle current interrupts */ - handle_irq_batch(cascade, line_index, status); - - /* Any interrupts happened while we were handling the - * current ones? - */ - status = get_irqsteer_interrupts(line_index); - if (!status) - break; - - /* Any device keeping interrupting while we're handling - * or can't clear? - */ - - if (!--tries) { - tries = IRQ_MAX_TRIES; - trace_irq_error("irq_handler(): IRQ storm, status " - PRIx64, - get_irqsteer_interrupts(line_index)); - } - } - - platform_shared_commit(parent, sizeof(*parent)); -} - -#define DEFINE_IRQ_HANDLER(n) \ - static inline void irqstr_irqhandler_##n(void *arg) \ - { \ - irq_handler(arg, n); \ - } - -DEFINE_IRQ_HANDLER(0) -DEFINE_IRQ_HANDLER(1) -DEFINE_IRQ_HANDLER(2) -DEFINE_IRQ_HANDLER(3) -DEFINE_IRQ_HANDLER(4) -DEFINE_IRQ_HANDLER(5) -DEFINE_IRQ_HANDLER(6) -DEFINE_IRQ_HANDLER(7) - -static void irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) -{ - uint32_t irq_base = desc->irq - IRQ_NUM_IRQSTR_DSP0; - - /* Compute the actual IRQ_STEER IRQ number */ - irq_base *= IRQSTR_IRQS_PER_LINE; - irq += irq_base; - - irqstr_mask_int(irq); - - platform_shared_commit(desc, sizeof(*desc)); -} - -static void irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) -{ - uint32_t irq_base = desc->irq - IRQ_NUM_IRQSTR_DSP0; - - /* Compute the actual IRQ_STEER IRQ number */ - irq_base *= IRQSTR_IRQS_PER_LINE; - irq += irq_base; - - irqstr_unmask_int(irq); - - platform_shared_commit(desc, sizeof(*desc)); -} - -static const struct irq_cascade_ops irq_ops = { - .mask = irq_mask, - .unmask = irq_unmask, -}; - -/* IRQ_STEER interrupts */ -#define IRQSTR_CASCADE_TMPL_DECL(n) \ - { \ - .name = "irqsteer" #n, \ - .irq = IRQ_NUM_IRQSTR_DSP##n, \ - .handler = irqstr_irqhandler_##n, \ - .ops = &irq_ops, \ - .global_mask = false, \ - }, - -static const struct irq_cascade_tmpl dsp_irq[] = { - IRQSTR_CASCADE_TMPL_DECL(0) - IRQSTR_CASCADE_TMPL_DECL(1) - IRQSTR_CASCADE_TMPL_DECL(2) - IRQSTR_CASCADE_TMPL_DECL(3) - IRQSTR_CASCADE_TMPL_DECL(4) - IRQSTR_CASCADE_TMPL_DECL(5) - IRQSTR_CASCADE_TMPL_DECL(6) - IRQSTR_CASCADE_TMPL_DECL(7) -}; - -int irqstr_get_sof_int(int irqstr_int) -{ - int line, irq; - - /* Is it a valid interrupt? */ - if (irqstr_int < 0 || irqstr_int >= IRQSTR_IRQS_NUM) - return -EINVAL; - - line = irqstr_int / IRQSTR_IRQS_PER_LINE; - irq = irqstr_int % IRQSTR_IRQS_PER_LINE; - - return interrupt_get_irq(irq, irq_name_irqsteer[line]); -} - -void platform_interrupt_init(void) -{ - int i; - - /* Turn off the hardware so we don't have stray interrupts while - * initializing - */ - irqstr_disable_hw(); - /* Mask every external IRQ first */ - for (i = 0; i < IRQSTR_IRQS_REGISTERS_NUM; i++) - irqstr_write(IRQSTR_CH_MASK(i), 0); - /* Turn on the IRQ_STEER hardware */ - irqstr_enable_hw(); - - for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) - interrupt_cascade_register(dsp_irq + i); -} - -void platform_interrupt_set(uint32_t irq) -{ - if (interrupt_is_dsp_direct(irq)) - arch_interrupt_set(irq); -} - -void platform_interrupt_clear(uint32_t irq, uint32_t mask) -{ - if (interrupt_is_dsp_direct(irq)) - arch_interrupt_clear(irq); -} - -uint32_t platform_interrupt_get_enabled(void) -{ - return 0; -} - -void interrupt_mask(uint32_t irq, unsigned int cpu) -{ - struct irq_cascade_desc *cascade = interrupt_get_parent(irq); - - if (cascade && cascade->ops->mask) - cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, - cpu); - - platform_shared_commit(cascade, sizeof(*cascade)); -} - -void interrupt_unmask(uint32_t irq, unsigned int cpu) -{ - struct irq_cascade_desc *cascade = interrupt_get_parent(irq); - - if (cascade && cascade->ops->unmask) - cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, - cpu); - - platform_shared_commit(cascade, sizeof(*cascade)); -} diff --git a/src/drivers/imx/ipc.c b/src/drivers/imx/ipc.c index d57ed6c10da5..a124d20a9028 100644 --- a/src/drivers/imx/ipc.c +++ b/src/drivers/imx/ipc.c @@ -4,33 +4,44 @@ // // Author: Daniel Baluta <daniel.baluta@nxp.com> -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> #include <sof/drivers/mu.h> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> #include <sof/lib/dma.h> #include <sof/lib/mailbox.h> #include <sof/lib/memory.h> #include <sof/lib/uuid.h> -#include <sof/lib/wait.h> +#include <rtos/wait.h> #include <sof/list.h> #include <sof/platform.h> #include <sof/schedule/edf_schedule.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> #include <ipc/header.h> #include <ipc/topology.h> -#include <config.h> +#include <ipc/trace.h> + #include <errno.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> -/* 389c9186-5a7d-4ad1-a02c-a02ecdadfb33 */ -DECLARE_SOF_UUID("ipc-task", ipc_task_uuid, 0x389c9186, 0x5a7d, 0x4ad1, - 0xa0, 0x2c, 0xa0, 0x2e, 0xcd, 0xad, 0xfb, 0x33); +LOG_MODULE_REGISTER(ipc_task, CONFIG_SOF_LOG_LEVEL); + +/* 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) + +SOF_DEFINE_REG_UUID(ipc_task); struct ipc_data { struct ipc_data_host_buffer dh_buffer; @@ -42,34 +53,26 @@ static void irq_handler(void *arg) uint32_t status; /* Interrupt arrived, check src */ - status = imx_mu_read(IMX_MU_xSR); + status = imx_mu_read(IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); - tracev_ipc("ipc: irq isr 0x%x", status); + tr_dbg(&ipc_tr, "ipc: irq isr 0x%x", status); /* reply message(done) from host */ - if (status & IMX_MU_xSR_GIPn(1)) { - /* Disable GP interrupt #1 */ - imx_mu_xcr_rmw(0, IMX_MU_xCR_GIEn(1)); - + if (status & IMX_MU_xSR_GIPn(IMX_MU_VERSION, 1)) { /* Clear GP pending interrupt #1 */ - imx_mu_xsr_rmw(IMX_MU_xSR_GIPn(1), 0); + imx_mu_write(IMX_MU_xSR_GIPn(IMX_MU_VERSION, 1), + IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); interrupt_clear(PLATFORM_IPC_INTERRUPT); ipc->is_notification_pending = false; - - /* unmask GP interrupt #1 */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(1), 0); } /* new message from host */ - if (status & IMX_MU_xSR_GIPn(0)) { - - /* Disable GP interrupt #0 */ - imx_mu_xcr_rmw(0, IMX_MU_xCR_GIEn(0)); - + if (status & IMX_MU_xSR_GIPn(IMX_MU_VERSION, 0)) { /* Clear GP pending interrupt #0 */ - imx_mu_xsr_rmw(IMX_MU_xSR_GIPn(0), 0); + imx_mu_write(IMX_MU_xSR_GIPn(IMX_MU_VERSION, 0), + IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); interrupt_clear(PLATFORM_IPC_INTERRUPT); @@ -77,71 +80,94 @@ static void irq_handler(void *arg) } } -enum task_state ipc_platform_do_cmd(void *data) +int ipc_platform_compact_write_msg(struct ipc_cmd_hdr *hdr, int words) { - struct ipc *ipc = ipc_get(); - struct sof_ipc_cmd_hdr *hdr; + return 0; /* number of words read - not currently used on this platform */ +} + +int ipc_platform_compact_read_msg(struct ipc_cmd_hdr *hdr, int words) +{ + return 0; /* number of words read - not currently used on this platform */ +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; /* Use struct ipc_data *iipc = ipc_get_drvdata(ipc); if needed */ /* perform command */ hdr = mailbox_validate(); ipc_cmd(hdr); - platform_shared_commit(ipc, sizeof(*ipc)); - return SOF_TASK_STATE_COMPLETED; } -void ipc_platform_complete_cmd(void *data) +void ipc_platform_complete_cmd(struct ipc *ipc) { - struct ipc *ipc = data; + int ret; - /* enable GP interrupt #0 - accept new messages */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(0), 0); + /* make sure GIR0 and GIR1 are not already set before asserting GIR0 */ + ret = poll_for_register_delay(MU_BASE + IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR), + IMX_MU_xCR_GIRn(IMX_MU_VERSION, 0), + 0, + 100); + if (ret < 0) + tr_err(&ipc_tr, "failed poll for GIR0"); + + + ret = poll_for_register_delay(MU_BASE + IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR), + IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), + 0, + 100); + if (ret < 0) + tr_err(&ipc_tr, "failed poll for GIR1"); /* request GP interrupt #0 - notify host that reply is ready */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(0), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 0), 0); // TODO: signal audio work to enter D3 in normal context /* are we about to enter D3 ? */ +#ifdef CONFIG_XTENSA if (ipc->pm_prepare_D3) { - platform_shared_commit(ipc, sizeof(*ipc)); - while (1) + /* + * Note, that this function is now called with + * interrupts disabled, so this wait will never even + * return anyway + */ wait_for_interrupt(0); } - - platform_shared_commit(ipc, sizeof(*ipc)); +#endif /* CONFIG_XTENSA */ } -int ipc_platform_send_msg(struct ipc_msg *msg) +int ipc_platform_send_msg(const struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); - int ret = 0; + uint32_t gir0_set, gir1_set, control; + + control = imx_mu_read(IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR)); + gir1_set = control & IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1); + gir0_set = control & IMX_MU_xCR_GIRn(IMX_MU_VERSION, 0); /* can't send notification when one is in progress */ - if (ipc->is_notification_pending || - imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) { - ret = -EBUSY; - goto out; - } + if (ipc->is_notification_pending || gir0_set || gir1_set) + return -EBUSY; /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - list_item_del(&msg->list); - tracev_ipc("ipc: msg tx -> 0x%x", msg->header); + + tr_dbg(&ipc_tr, "ipc: msg tx -> 0x%x", msg->header); ipc->is_notification_pending = true; /* now interrupt host to tell it we have sent a message */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0); - - platform_shared_commit(msg, sizeof(*msg)); - -out: - platform_shared_commit(ipc, sizeof(*ipc)); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); + return 0; +} - return ret; +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ } #if CONFIG_HOST_PTABLE @@ -149,8 +175,6 @@ struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) { struct ipc_data *iipc = ipc_get_drvdata(ipc); - platform_shared_commit(ipc, sizeof(*ipc)); - return &iipc->dh_buffer; } #endif @@ -160,9 +184,9 @@ int platform_ipc_init(struct ipc *ipc) #if CONFIG_HOST_PTABLE struct ipc_data *iipc; - iipc = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(*iipc)); + iipc = rzalloc(SOF_MEM_FLAG_USER, sizeof(*iipc)); if (!iipc) { - trace_ipc_error("Unable to allocate IPC private data"); + tr_err(&ipc_tr, "Unable to allocate IPC private data"); return -ENOMEM; } ipc_set_drvdata(ipc, iipc); @@ -176,29 +200,58 @@ int platform_ipc_init(struct ipc *ipc) #if CONFIG_HOST_PTABLE /* allocate page table buffer */ - iipc->dh_buffer.page_table = rzalloc(SOF_MEM_ZONE_SYS, 0, - SOF_MEM_CAPS_RAM, + iipc->dh_buffer.page_table = rzalloc(SOF_MEM_FLAG_USER, PLATFORM_PAGE_TABLE_SIZE); - if (iipc->dh_buffer.page_table) - bzero(iipc->dh_buffer.page_table, PLATFORM_PAGE_TABLE_SIZE); - iipc->dh_buffer.dmac = dma_get(DMA_DIR_HMEM_TO_LMEM, 0, DMA_DEV_HOST, - DMA_ACCESS_SHARED); + if (!iipc->dh_buffer.page_table) + sof_panic(SOF_IPC_PANIC_IPC); + bzero(iipc->dh_buffer.page_table, PLATFORM_PAGE_TABLE_SIZE); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + iipc->dh_buffer.dmac = sof_dma_get(SOF_DMA_DIR_HMEM_TO_LMEM, 0, SOF_DMA_DEV_HOST, + SOF_DMA_ACCESS_SHARED); +#else + iipc->dh_buffer.dmac = dma_get(SOF_DMA_DIR_HMEM_TO_LMEM, 0, SOF_DMA_DEV_HOST, + SOF_DMA_ACCESS_SHARED); +#endif if (!iipc->dh_buffer.dmac) { - trace_ipc_error("Unable to find DMA for host page table"); - panic(SOF_IPC_PANIC_IPC); + tr_err(&ipc_tr, "Unable to find DMA for host page table"); + sof_panic(SOF_IPC_PANIC_IPC); } #endif - /* configure interrupt */ + /* Disable interrupt for DSP Core */ + interrupt_disable(PLATFORM_IPC_INTERRUPT, ipc); + + /* Disable interrupt from MU: + * GP #0 for Host -> DSP message notification + * GP #1 for DSP -> Host message confirmation + * GP #2 and #3 not used + */ + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, 0, + IMX_MU_xCR_GIEn(IMX_MU_VERSION, 0) | + IMX_MU_xCR_GIEn(IMX_MU_VERSION, 1) | + IMX_MU_xCR_GIEn(IMX_MU_VERSION, 2) | + IMX_MU_xCR_GIEn(IMX_MU_VERSION, 3)); + + /* Clear all pending interrupts from MU */ + imx_mu_write(IMX_MU_xSR_GIPn(IMX_MU_VERSION, 0) | + IMX_MU_xSR_GIPn(IMX_MU_VERSION, 1) | + IMX_MU_xSR_GIPn(IMX_MU_VERSION, 2) | + IMX_MU_xSR_GIPn(IMX_MU_VERSION, 3), + IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); + + /* Clear pending interrupt for DSP Core */ + interrupt_clear(PLATFORM_IPC_INTERRUPT); + + /* Configure interrupt for DSP Core */ interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, ipc); interrupt_enable(PLATFORM_IPC_INTERRUPT, ipc); - /* enable GP #0 for Host -> DSP message notification - * enable GP #1 for DSP -> Host message notification + /* Enable interrupt from MU: + * enable GP #0 for Host -> DSP message notification + * enable GP #1 for DSP -> Host message confirmation */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(0) | IMX_MU_xCR_GIEn(1), 0); - - platform_shared_commit(ipc, sizeof(*ipc)); + 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; } @@ -214,10 +267,10 @@ int ipc_platform_poll_init(void) void ipc_platform_poll_set_cmd_done(void) { /* enable GP interrupt #0 - accept new messages */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(0), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, IMX_MU_xCR_GIEn(IMX_MU_VERSION, 0), 0); /* request GP interrupt #0 - notify host that reply is ready */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(0), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 0), 0); } /* read the IPC register for any new command messages */ @@ -226,16 +279,16 @@ int ipc_platform_poll_is_cmd_pending(void) uint32_t status; /* Interrupt arrived, check src */ - status = imx_mu_read(IMX_MU_xSR); + status = imx_mu_read(IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); /* new message from host */ - if (status & IMX_MU_xSR_GIPn(0)) { - + if (status & IMX_MU_xSR_GIPn(IMX_MU_VERSION, 0)) { /* Disable GP interrupt #0 */ - imx_mu_xcr_rmw(0, IMX_MU_xCR_GIEn(0)); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(IMX_MU_VERSION, 0)); /* Clear GP pending interrupt #0 */ - imx_mu_xsr_rmw(IMX_MU_xSR_GIPn(0), 0); + imx_mu_write(IMX_MU_xSR_GIPn(IMX_MU_VERSION, 0), + IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); interrupt_clear(PLATFORM_IPC_INTERRUPT); @@ -252,20 +305,21 @@ int ipc_platform_poll_is_host_ready(void) uint32_t status; /* Interrupt arrived, check src */ - status = imx_mu_read(IMX_MU_xSR); + status = imx_mu_read(IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); /* reply message(done) from host */ - if (status & IMX_MU_xSR_GIPn(1)) { + if (status & IMX_MU_xSR_GIPn(IMX_MU_VERSION, 1)) { /* Disable GP interrupt #1 */ - imx_mu_xcr_rmw(0, IMX_MU_xCR_GIEn(1)); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, 0, IMX_MU_xCR_GIEn(IMX_MU_VERSION, 1)); /* Clear GP pending interrupt #1 */ - imx_mu_xsr_rmw(IMX_MU_xSR_GIPn(1), 0); + imx_mu_write(IMX_MU_xSR_GIPn(IMX_MU_VERSION, 1), + IMX_MU_xSR(IMX_MU_VERSION, IMX_MU_GSR)); interrupt_clear(PLATFORM_IPC_INTERRUPT); /* unmask GP interrupt #1 */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(1), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, IMX_MU_xCR_GIEn(IMX_MU_VERSION, 1), 0); /* host done */ return 1; @@ -278,17 +332,17 @@ 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_xCR_GIRn(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 */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); /* now interrupt host to tell it we have sent a message */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); /* message sent */ - platform_shared_commit(msg, sizeof(*msg)); return 1; } diff --git a/src/drivers/imx/micfil.c b/src/drivers/imx/micfil.c new file mode 100644 index 000000000000..0946ca165c57 --- /dev/null +++ b/src/drivers/imx/micfil.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 NXP +// +// Author: Daniel Baluta <daniel.baluta@nxp.com> + +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <rtos/alloc.h> +#include <sof/drivers/micfil.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/uuid.h> +#include <ipc/dai.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(micfil_dai, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(micfil); + +DECLARE_TR_CTX(micfil_tr, SOF_UUID(micfil_uuid), LOG_LEVEL_INFO); + +#define MICFIL_OSR_DEFAULT 16 +/* set default gain to 2 */ +#define MICFIL_DEFAULT_ADJ_RANGE 0x22222222 +#define MICFIL_CLK_ROOT 24576000 + +enum micfil_quality { + QUALITY_HIGH, + QUALITY_MEDIUM, + QUALITY_LOW, + QUALITY_VLOW0, + QUALITY_VLOW1, + QUALITY_VLOW2, +}; + +static void micfil_reset(struct dai *dai) +{ + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_MDIS, 0); + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_SRES, MICFIL_CTRL1_SRES); + dai_update_bits(dai, REG_MICFIL_STAT, 0xff, 0xff); +} + +static int micfil_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, int dir) +{ + struct micfil_pdata *micfil = dai_get_drvdata(dai); + + dai_info(dai, "entry"); + + params->rate = micfil->params.pdm_rate; + params->channels = micfil->params.pdm_ch; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params->frame_fmt = SOF_IPC_FRAME_S32_LE; + + return 0; +} + +static int micfil_set_quality(struct dai *dai) +{ + struct micfil_pdata *micfil = dai_get_drvdata(dai); + int qsel; + + switch (micfil->quality) { + case QUALITY_HIGH: + qsel = MICFIL_QSEL_HIGH_QUALITY; + break; + case QUALITY_MEDIUM: + qsel = MICFIL_QSEL_MEDIUM_QUALITY; + break; + case QUALITY_LOW: + qsel = MICFIL_QSEL_LOW_QUALITY; + break; + case QUALITY_VLOW0: + qsel = MICFIL_QSEL_VLOW0_QUALITY; + break; + case QUALITY_VLOW1: + qsel = MICFIL_QSEL_VLOW1_QUALITY; + break; + case QUALITY_VLOW2: + qsel = MICFIL_QSEL_VLOW2_QUALITY; + break; + default: + dai_err(dai, "MICFIL: invalid quality mode %d", micfil->quality); + return -EINVAL; + } + + dai_update_bits(dai, REG_MICFIL_CTRL2, MICFIL_CTRL2_QSEL, + MICFIL_CTRL2_QSEL_BITS(qsel)); + + return 0; +} + +/* get_pdm_clk - computes the product between k-factor and PDM_CLK rate + * @param dai, SOF DAI struct + * @param rate, output sampling rate + * + * PDM_CLK depends on Quality Mode, output sampling rate and quality + * mode + */ +static unsigned int micfil_get_pdm_clk(struct dai *dai, int rate) +{ + unsigned int osr; + unsigned int qsel; + unsigned int ctrl2_reg; + unsigned int pdm_clk = 0; + + ctrl2_reg = dai_read(dai, REG_MICFIL_CTRL2); + osr = 16 - ((ctrl2_reg & MICFIL_CTRL2_CICOSR) >> MICFIL_CTRL2_CICOSR_SHIFT); + qsel = (ctrl2_reg & MICFIL_CTRL2_QSEL) >> MICFIL_CTRL2_QSEL_SHIFT; + + /* See Quality modes chapter in MICFIL documentation */ + switch (qsel) { + case MICFIL_QSEL_HIGH_QUALITY: + pdm_clk = rate * 8 * osr / 2; /* kfactor = 0.5 */ + break; + case MICFIL_QSEL_MEDIUM_QUALITY: + case MICFIL_QSEL_VLOW0_QUALITY: + pdm_clk = rate * 4 * osr; /* kfactor = 1 */ + break; + case MICFIL_QSEL_LOW_QUALITY: + case MICFIL_QSEL_VLOW1_QUALITY: + pdm_clk = rate * 2 * osr * 2; /* kfactor = 2 */ + break; + case MICFIL_QSEL_VLOW2_QUALITY: + pdm_clk = rate * osr; /* kfactor = 4 */ + break; + default: + break; + } + + return pdm_clk; +} + +static int micfil_get_clk_div(struct dai *dai, int rate) +{ + unsigned int pdm_clk; + + pdm_clk = micfil_get_pdm_clk(dai, rate); + if (!pdm_clk) + return -EINVAL; + + /* + * + * See: Clock divider chapter from micfil documentation + * PDM_CLK rate = MICFIL_CLK_ROOT rate / (2 * K * CLKDIV) + * + * this means that if we want to compute CLKDIV then: + * CLKDIV = MICFIL_CLK_ROOT rate / (PDM_CLK rate * K * 2) + * + * micfil_get_pdm_clk function returns K * PDM_CLK rate + */ + return MICFIL_CLK_ROOT / (pdm_clk * 2); +} + +static int micfil_set_clock_params(struct dai *dai, int rate) +{ + int clk_div; + + dai_update_bits(dai, REG_MICFIL_CTRL2, MICFIL_CTRL2_CICOSR, + MICFIL_CTRL2_CICOSR_BITS(MICFIL_OSR_DEFAULT)); + + clk_div = micfil_get_clk_div(dai, rate); + if (clk_div < 0) + return clk_div; + + dai_update_bits(dai, REG_MICFIL_CTRL2, MICFIL_CTRL2_CLKDIV, + MICFIL_CTRL2_CLKDIV_BITS(clk_div)); + + return 0; +} + +static int micfil_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + int i, ret; + unsigned int val = 0; + struct micfil_pdata *micfil = dai_get_drvdata(dai); + const struct sof_ipc_dai_config *config = spec_config; + + micfil->params = config->micfil; + + dai_info(dai, "dai_idx %d channels %d sampling_freq %d", + common_config->dai_index, micfil->params.pdm_ch, micfil->params.pdm_rate); + + /* disable the module */ + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_PDMIEN, 0); + + micfil_set_quality(dai); + + /* set default gain to 2 */ + dai_write(dai, REG_MICFIL_OUT_CTRL, MICFIL_DEFAULT_ADJ_RANGE); + + /* set DC Remover in bypass mode */ + for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++) + val |= MICFIL_DC_BYPASS << MICFIL_DC_CHX_SHIFT(i); + dai_update_bits(dai, REG_MICFIL_DC_CTRL, MICFIL_DC_CTRL_CONFIG, val); + + /* FIFO WMK */ + dai_update_bits(dai, REG_MICFIL_FIFO_CTRL, MICFIL_FIFO_CTRL_FIFOWMK, + MICFIL_FIFO_CTRL_FIFOWMK_BITS(31)); + + /* enable channels */ + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_CHNEN, + ((1 << micfil->params.pdm_ch) - 1)); + + ret = micfil_set_clock_params(dai, micfil->params.pdm_rate); + if (ret < 0) + return ret; + + return 0; +} + +static int micfil_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return dai->plat_data.fifo[SOF_IPC_STREAM_CAPTURE].handshake; +} + +static int micfil_get_fifo(struct dai *dai, int direction, int stream_id) +{ + return dai->plat_data.fifo[SOF_IPC_STREAM_CAPTURE].offset; +} + +static int micfil_get_fifo_depth(struct dai *dai, int direction) +{ + return dai->plat_data.fifo[SOF_IPC_STREAM_CAPTURE].depth; +} + +static void micfil_start(struct dai *dai) +{ + dai_info(dai, "entry"); + + micfil_reset(dai); + + /* DMA Interrupt Selection - DISEL bits + * 00 - DMA and IRQ disabled + * 01 - DMA req enabled + * 10 - IRQ enabled + * 11 - reserved + */ + dai_update_bits(dai, REG_MICFIL_CTRL1, + MICFIL_CTRL1_DISEL, + MICFIL_CTRL1_DISEL_BITS(MICFIL_CTRL1_DISEL_DMA)); + + /* Enable the module */ + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_PDMIEN, MICFIL_CTRL1_PDMIEN); +} + +static void micfil_stop(struct dai *dai) +{ + dai_info(dai, "entry"); + + /* Disable the module */ + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_PDMIEN, 0); + + dai_update_bits(dai, REG_MICFIL_CTRL1, MICFIL_CTRL1_DISEL, + MICFIL_CTRL1_DISEL_BITS(MICFIL_CTRL1_DISEL_DISABLE)); +} + +static int micfil_trigger(struct dai *dai, int cmd, int direction) +{ + dai_info(dai, "cmd %d dir %d", cmd, direction); + + switch (cmd) { + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + micfil_start(dai); + break; + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_PAUSE: + micfil_stop(dai); + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + break; + default: + dai_err(dai, "MICFIL: invalid trigger cmd %d", cmd); + return -EINVAL; + } + + return 0; +} + +static int micfil_probe(struct dai *dai) +{ + struct micfil_pdata *micfil; + + dai_info(dai, "entry"); + + micfil = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*micfil)); + if (!micfil) { + dai_err(dai, "micfil probe failed"); + return -ENOMEM; + } + + micfil->quality = QUALITY_VLOW0; + + dai_set_drvdata(dai, micfil); + + return 0; +} + +static int micfil_remove(struct dai *dai) +{ + struct micfil_pdata *micfil = dai_get_drvdata(dai); + + dai_info(dai, "entry"); + + rfree(micfil); + dai_set_drvdata(dai, NULL); + + return 0; +} + +const struct dai_driver micfil_driver = { + .type = SOF_DAI_IMX_MICFIL, + .uid = SOF_UUID(micfil_uuid), + .tctx = &micfil_tr, + .dma_dev = SOF_DMA_DEV_MICFIL, + .ops = { + .trigger = micfil_trigger, + .set_config = micfil_set_config, + .get_hw_params = micfil_get_hw_params, + .get_handshake = micfil_get_handshake, + .get_fifo = micfil_get_fifo, + .get_fifo_depth = micfil_get_fifo_depth, + .probe = micfil_probe, + .remove = micfil_remove, + }, +}; diff --git a/src/drivers/imx/sai.c b/src/drivers/imx/sai.c index 0735a36b7d2c..1d748c44a6e0 100644 --- a/src/drivers/imx/sai.c +++ b/src/drivers/imx/sai.c @@ -7,101 +7,256 @@ // Author: Guido Roncarolo <guido.roncarolo@nxp.com> #include <sof/audio/component.h> -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/drivers/edma.h> #include <sof/drivers/sai.h> #include <sof/lib/dai.h> #include <sof/lib/dma.h> +#include <rtos/wait.h> +#include <sof/lib/uuid.h> #include <ipc/dai.h> #include <errno.h> #include <stdint.h> +LOG_MODULE_REGISTER(sai, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(sai); + +DECLARE_TR_CTX(sai_tr, SOF_UUID(sai_uuid), LOG_LEVEL_INFO); + #define REG_TX_DIR 0 #define REG_RX_DIR 1 static void sai_start(struct dai *dai, int direction) { - trace_sai("SAI: sai_start"); + dai_info(dai, "SAI: entry"); + struct sai_pdata *sai = dai_get_drvdata(dai); + int chan_idx = 0; uint32_t xcsr = 0U; + int i; + int n; +#ifdef CONFIG_IMX8ULP + int fifo_offset = 0; +#endif + if (direction == DAI_DIR_CAPTURE) { + /* Software Reset */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE), + REG_SAI_CSR_SR, REG_SAI_CSR_SR); + /* Clear SR bit to finish the reset */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE), + REG_SAI_CSR_SR, 0U); + /* Check if the opposite direction is also disabled */ + xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK)); + if (!(xcsr & REG_SAI_CSR_FRDE)) { + /* Software Reset */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_SR, REG_SAI_CSR_SR); + /* Clear SR bit to finish the reset */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_SR, 0U); + /* Transmitter enable */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); + } + } else { + /* Check if the opposite direction is also disabled */ + xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE)); + if (!(xcsr & REG_SAI_CSR_FRDE)) { + /* Software Reset */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_SR, REG_SAI_CSR_SR); + /* Clear SR bit to finish the reset */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_SR, 0U); + } + } + + /* W1C */ dai_update_bits(dai, REG_SAI_XCSR(direction), - REG_SAI_CSR_FRDE, REG_SAI_CSR_FRDE); + REG_SAI_CSR_FEF, 1); + dai_update_bits(dai, REG_SAI_XCSR(direction), + REG_SAI_CSR_SEF, 1); + dai_update_bits(dai, REG_SAI_XCSR(direction), + REG_SAI_CSR_WSF, 1); + + /* + * Add one frame of data to FIFO before TRCE is enabled. + * In FIFO words this equates to tdm_slots/(slots_per_32b_fifo_word). Minimum: one word. + * Not performing this 'priming' can lead to negative effects like shifted + * and / or missing slots. + * TODO: check if that works in all situations + */ + + switch (sai->params.tdm_slot_width) { + case 8: + n = sai->params.tdm_slots / 4; + break; + case 16: + n = sai->params.tdm_slots / 2; + break; + default: + n = sai->params.tdm_slots; + break; + } + + if (!n) + n = 1; + + if (direction == DAI_DIR_PLAYBACK) { + for (i = 0; i < n; i++) + dai_write(dai, REG_SAI_TDR0, 0x0); + } else { + for (i = 0; i < n; i++) + dai_write(dai, REG_SAI_RDR0, 0x0); + } + /* enable DMA requests */ dai_update_bits(dai, REG_SAI_XCSR(direction), - REG_SAI_CSR_FWDE, REG_SAI_CSR_FWDE); - /* transmitter enable */ + REG_SAI_CSR_FRDE, REG_SAI_CSR_FRDE); + + chan_idx = BIT(0); + /* RX3 supports capture on imx8ulp */ +#ifdef CONFIG_IMX8ULP + if (direction == DAI_DIR_CAPTURE) { + fifo_offset = (dai_fifo(dai, DAI_DIR_CAPTURE) - dai_base(dai) - REG_SAI_RDR0) >> 2; + chan_idx = BIT(fifo_offset); + } else { + fifo_offset = (dai_fifo(dai, DAI_DIR_PLAYBACK) - dai_base(dai) - REG_SAI_TDR0) >> 2; + chan_idx = BIT(fifo_offset); + } +#endif + + /* transmit/receive data channel enable */ + dai_update_bits(dai, REG_SAI_XCR3(direction), + REG_SAI_CR3_TRCE_MASK, REG_SAI_CR3_TRCE(chan_idx)); + + /* transmitter/receiver enable */ dai_update_bits(dai, REG_SAI_XCSR(direction), REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); - /* TODO: for the time being use half FIFO size as watermark */ - dai_update_bits(dai, REG_SAI_XCR1(direction), - REG_SAI_CR1_RFW_MASK, SAI_FIFO_WORD_SIZE / 2); - dai_update_bits(dai, REG_SAI_XCR3(direction), - REG_SAI_CR3_TRCE_MASK, REG_SAI_CR3_TRCE(1)); +} + +static void sai_release(struct dai *dai, int direction) +{ + dai_info(dai, "SAI: entry"); + int chan_idx = 0; +#ifdef CONFIG_IMX8ULP + int fifo_offset = 0; +#endif + /* enable DMA requests */ + dai_update_bits(dai, REG_SAI_XCSR(direction), + REG_SAI_CSR_FRDE, REG_SAI_CSR_FRDE); + + chan_idx = BIT(0); +#ifdef CONFIG_IMX8ULP if (direction == DAI_DIR_CAPTURE) { - xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK)); - if (!(xcsr & REG_SAI_CSR_FRDE)) - dai_update_bits(dai, REG_SAI_XCR3(DAI_DIR_PLAYBACK), - REG_SAI_CR3_TRCE_MASK, - REG_SAI_CR3_TRCE(1)); + fifo_offset = (dai_fifo(dai, DAI_DIR_CAPTURE) - dai_base(dai) - REG_SAI_RDR0) >> 2; + chan_idx = BIT(fifo_offset); + } else { + fifo_offset = (dai_fifo(dai, DAI_DIR_PLAYBACK) - dai_base(dai) - REG_SAI_TDR0) >> 2; + chan_idx = BIT(fifo_offset); } +#endif - /* add one word to FIFO after TRCE has been enabled */ - if (direction == DAI_DIR_PLAYBACK) - dai_update_bits(dai, REG_SAI_TDR0, 0x0, 0x0); - else - dai_update_bits(dai, REG_SAI_RDR0, 0x0, 0x0); + /* transmit/receive data channel enable */ + dai_update_bits(dai, REG_SAI_XCR3(direction), + REG_SAI_CR3_TRCE_MASK, REG_SAI_CR3_TRCE(chan_idx)); + + /* transmitter/receiver enable */ + dai_update_bits(dai, REG_SAI_XCSR(direction), + REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); } static void sai_stop(struct dai *dai, int direction) { - trace_sai("SAI: sai_stop"); + dai_info(dai, "SAI: entry"); uint32_t xcsr = 0U; + int ret = 0; + /* Disable DMA request */ dai_update_bits(dai, REG_SAI_XCSR(direction), REG_SAI_CSR_FRDE, 0); + + /* Transmit/Receive data channel disable */ + dai_update_bits(dai, REG_SAI_XCR3(direction), + REG_SAI_CR3_TRCE_MASK, + REG_SAI_CR3_TRCE(0)); + + /* Disable interrupts */ dai_update_bits(dai, REG_SAI_XCSR(direction), REG_SAI_CSR_XIE_MASK, 0); - /* Check if the opposite direction is also disabled */ - xcsr = dai_read(dai, REG_SAI_XCSR(!direction)); - if (!(xcsr & REG_SAI_CSR_FRDE)) { - /* Disable both directions and reset their FIFOs */ - dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_TERE, 0); - dai_update_bits(dai, REG_SAI_RCSR, REG_SAI_CSR_TERE, 0); - - /* Software Reset for both Tx and Rx */ - dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_SR, - REG_SAI_CSR_SR); - dai_update_bits(dai, REG_SAI_RCSR, REG_SAI_CSR_SR, - REG_SAI_CSR_SR); + /* Disable transmitter/receiver */ + if (direction == DAI_DIR_CAPTURE) { + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE), REG_SAI_CSR_TERE, 0); + ret = poll_for_register_delay(dai_base(dai) + + REG_SAI_XCSR(DAI_DIR_CAPTURE), + REG_SAI_CSR_TERE, 0, 100); - /* Clear SR bit to finish the reset */ - dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_SR, 0U); - dai_update_bits(dai, REG_SAI_RCSR, REG_SAI_CSR_SR, 0U); + /* Check if the opposite direction is also disabled */ + xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK)); + if (!(xcsr & REG_SAI_CSR_FRDE)) { + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), REG_SAI_CSR_TERE, 0); + ret = poll_for_register_delay(dai_base(dai) + + REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_TERE, 0, 100); + } + } else { + /* Check if the opposite direction is also disabled */ + xcsr = dai_read(dai, REG_SAI_XCSR(DAI_DIR_CAPTURE)); + if (!(xcsr & REG_SAI_CSR_FRDE)) { + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), REG_SAI_CSR_TERE, 0); + ret = poll_for_register_delay(dai_base(dai) + + REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_TERE, 0, 100); + } } -} -static int sai_context_store(struct dai *dai) -{ - return 0; -} - -static int sai_context_restore(struct dai *dai) -{ - return 0; + if (ret < 0) + dai_warn(dai, "sai: poll for register delay failed"); } -static inline int sai_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) +static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) { - trace_sai("SAI: sai_set_config"); + dai_info(dai, "SAI: entry"); + const struct sof_ipc_dai_config *config = spec_config; uint32_t val_cr2 = 0, val_cr4 = 0, val_cr5 = 0; uint32_t mask_cr2 = 0, mask_cr4 = 0, mask_cr5 = 0; - /* TODO: this value will be provided by config */ - uint32_t sywd = 32; + uint32_t clk_div; + bool tdm_enable; + struct sai_pdata *sai = dai_get_drvdata(dai); + + sai->config = *config; + sai->params = config->sai; + + /* bit width of a single slot; FIFO word always 32b */ + uint32_t sywd = sai->params.tdm_slot_width; + + /* + * Divide the audio main clock to generate the bit clock when + * configured for an internal bit clock. + * The division value is (DIV + 1) * 2. + * If mclk == bclk set the divider bypass bit, REG_SAI_CR2_BYP. + */ + + if (config->sai.mclk_rate == config->sai.bclk_rate) { + val_cr2 |= REG_SAI_CR2_BYP; + clk_div = 0; + } else { + clk_div = (config->sai.mclk_rate / config->sai.bclk_rate / 2) - 1; + } + + /* TDM mode is enabled only when fmt is dsp_a or dsp_b and + * we can have from 1 to 32 channels. + * for any other formats we assume I2S like interface where + * audio frames have 2 channels, even for mono scenario. The + * second channel will be masked out. + */ + tdm_enable = false; switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { case SOF_DAI_FMT_I2S: @@ -111,11 +266,13 @@ static inline int sai_set_config(struct dai *dai, * that is, together with the last bit of the previous * data word. */ +#ifdef CONFIG_IMX8ULP + val_cr4 |= REG_SAI_CR4_FSE; +#else val_cr2 |= REG_SAI_CR2_BCP; val_cr4 |= REG_SAI_CR4_FSE | REG_SAI_CR4_FSP; val_cr4 |= REG_SAI_CR4_SYWD(sywd); - val_cr4 |= REG_SAI_CR4_MF; - val_cr4 |= REG_SAI_CR4_FSE; +#endif break; case SOF_DAI_FMT_LEFT_J: /* @@ -124,7 +281,6 @@ static inline int sai_set_config(struct dai *dai, */ val_cr2 |= REG_SAI_CR2_BCP; val_cr4 |= REG_SAI_CR4_SYWD(sywd); - val_cr4 |= REG_SAI_CR4_MF; break; case SOF_DAI_FMT_DSP_A: /* @@ -135,9 +291,8 @@ static inline int sai_set_config(struct dai *dai, */ val_cr2 |= REG_SAI_CR2_BCP; val_cr4 |= REG_SAI_CR4_FSE; - val_cr4 |= REG_SAI_CR4_SYWD(0U); - val_cr4 |= REG_SAI_CR4_MF; - val_cr4 |= REG_SAI_CR4_FSE; + val_cr4 |= REG_SAI_CR4_SYWD(1U); + tdm_enable = true; break; case SOF_DAI_FMT_DSP_B: /* @@ -145,17 +300,15 @@ static inline int sai_set_config(struct dai *dai, * frame sync asserts with the first bit of the frame. */ val_cr2 |= REG_SAI_CR2_BCP; - val_cr4 |= REG_SAI_CR4_SYWD(0U); - val_cr4 |= REG_SAI_CR4_MF; + val_cr4 |= REG_SAI_CR4_SYWD(1U); + tdm_enable = true; break; case SOF_DAI_FMT_PDM: val_cr2 |= REG_SAI_CR2_BCP; val_cr4 &= ~REG_SAI_CR4_MF; - val_cr4 |= REG_SAI_CR4_MF; break; case SOF_DAI_FMT_RIGHT_J: val_cr4 |= REG_SAI_CR4_SYWD(sywd); - val_cr4 |= REG_SAI_CR4_MF; break; default: return -EINVAL; @@ -183,91 +336,126 @@ static inline int sai_set_config(struct dai *dai, return -EINVAL; } - /* DAI clock master masks */ - switch (config->format & SOF_DAI_FMT_MASTER_MASK) { - case SOF_DAI_FMT_CBS_CFS: - trace_sai("SAI: codec is slave"); + /* DAI clock provider masks */ + switch (config->format & SOF_DAI_FMT_CLOCK_PROVIDER_MASK) { + case SOF_DAI_FMT_CBC_CFC: + dai_info(dai, "SAI: codec is consumer"); val_cr2 |= REG_SAI_CR2_MSEL_MCLK1; val_cr2 |= REG_SAI_CR2_BCD_MSTR; - val_cr2 |= SAI_CLOCK_DIV; /* TODO: determine dynamically.*/ + val_cr2 |= clk_div; val_cr4 |= REG_SAI_CR4_FSD_MSTR; break; - case SOF_DAI_FMT_CBM_CFM: - trace_sai("SAI: codec is master"); + case SOF_DAI_FMT_CBP_CFP: + dai_info(dai, "SAI: codec is provider"); /* - * fields CR2_DIV and CR2_MSEL not relevant in slave mode. + * fields CR2_DIV and CR2_MSEL not relevant in consumer mode. * fields CR2_BCD and CR4_MFSD already at 0 */ break; - case SOF_DAI_FMT_CBS_CFM: + case SOF_DAI_FMT_CBC_CFP: val_cr2 |= REG_SAI_CR2_BCD_MSTR; - val_cr2 |= SAI_CLOCK_DIV; /* TODO: determine dynamically.*/ + val_cr2 |= clk_div; break; - case SOF_DAI_FMT_CBM_CFS: + case SOF_DAI_FMT_CBP_CFC: val_cr4 |= REG_SAI_CR4_FSD_MSTR; - val_cr2 |= SAI_CLOCK_DIV; /* TODO: determine dynamically.*/ + val_cr2 |= clk_div; break; default: return -EINVAL; } - /* TODO: set number of slots from config */ - val_cr4 |= REG_SAI_CR4_FRSZ(SAI_TDM_SLOTS); +#ifndef CONFIG_IMX8ULP + switch (sai->params.tdm_slot_width) { + case 8: + val_cr4 |= REG_SAI_CR4_FPACK_8; + break; + case 16: + val_cr4 |= REG_SAI_CR4_FPACK_16; + break; + default: + break; + } +#endif + + if (tdm_enable) + val_cr4 |= REG_SAI_CR4_FRSZ(sai->params.tdm_slots); + else + val_cr4 |= REG_SAI_CR4_FRSZ( + (sai->params.tdm_slots == 1) ? 2 : sai->params.tdm_slots); + + val_cr4 |= REG_SAI_CR4_CHMOD; + val_cr4 |= REG_SAI_CR4_MF; val_cr5 |= REG_SAI_CR5_WNW(sywd) | REG_SAI_CR5_W0W(sywd) | REG_SAI_CR5_FBT(sywd); mask_cr2 = REG_SAI_CR2_BCP | REG_SAI_CR2_BCD_MSTR | + REG_SAI_CR2_BYP_MASK | REG_SAI_CR2_MSEL_MASK | REG_SAI_CR2_DIV_MASK; mask_cr4 = REG_SAI_CR4_MF | REG_SAI_CR4_FSE | REG_SAI_CR4_FSP | REG_SAI_CR4_FSD_MSTR | - REG_SAI_CR4_FRSZ_MASK | REG_SAI_CR4_SYWD_MASK; + REG_SAI_CR4_FRSZ_MASK | REG_SAI_CR4_SYWD_MASK | + REG_SAI_CR4_CHMOD_MASK | REG_SAI_CR4_FPACK_MASK; mask_cr5 = REG_SAI_CR5_WNW_MASK | REG_SAI_CR5_W0W_MASK | REG_SAI_CR5_FBT_MASK; + dai_update_bits(dai, REG_SAI_XCR1(REG_TX_DIR), REG_SAI_CR1_RFW_MASK, + dai->plat_data.fifo[REG_TX_DIR].watermark); dai_update_bits(dai, REG_SAI_XCR2(REG_TX_DIR), mask_cr2, val_cr2); 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, - ~(BIT(0) | BIT(1))); + /* turn on (set to zero) slots */ + dai_update_bits(dai, REG_SAI_XMR(REG_TX_DIR), REG_SAI_XMR_MASK, + ~(sai->params.tx_slots)); val_cr2 |= REG_SAI_CR2_SYNC; mask_cr2 |= REG_SAI_CR2_SYNC_MASK; + + dai_update_bits(dai, REG_SAI_XCR1(REG_RX_DIR), REG_SAI_CR1_RFW_MASK, + dai->plat_data.fifo[REG_RX_DIR].watermark); dai_update_bits(dai, REG_SAI_XCR2(REG_RX_DIR), mask_cr2, val_cr2); dai_update_bits(dai, REG_SAI_XCR4(REG_RX_DIR), mask_cr4, val_cr4); dai_update_bits(dai, REG_SAI_XCR5(REG_RX_DIR), mask_cr5, val_cr5); - /* turn on (set to zero) stereo slot */ + /* turn on (set to zero) slots */ dai_update_bits(dai, REG_SAI_XMR(REG_RX_DIR), REG_SAI_XMR_MASK, - ~(BIT(0) | BIT(1))); + ~(sai->params.rx_slots)); + +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) + /* + * For i.MX8MP, MCLK is bound with TX enable bit. + * Therefore, enable transmitter to output MCLK + */ + dai_update_bits(dai, REG_SAI_XCSR(DAI_DIR_PLAYBACK), + REG_SAI_CSR_TERE, REG_SAI_CSR_TERE); + dai_update_bits(dai, REG_SAI_MCTL, REG_SAI_MCTL_MCLK_EN, + REG_SAI_MCTL_MCLK_EN); +#endif return 0; } static int sai_trigger(struct dai *dai, int cmd, int direction) { - trace_sai("SAI: sai_trigger"); + dai_info(dai, "SAI: entry"); switch (cmd) { case COMP_TRIGGER_START: sai_start(dai, direction); break; - case COMP_TRIGGER_STOP: - sai_stop(dai, direction); + case COMP_TRIGGER_RELEASE: + sai_release(dai, direction); break; + case COMP_TRIGGER_STOP: case COMP_TRIGGER_PAUSE: sai_stop(dai, direction); break; - case COMP_TRIGGER_RELEASE: - break; - case COMP_TRIGGER_SUSPEND: - break; - case COMP_TRIGGER_RESUME: + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: break; default: - trace_sai_error("SAI: invalid trigger cmd %d", cmd); + dai_err(dai, "SAI: invalid trigger cmd %d", cmd); break; } return 0; @@ -275,7 +463,17 @@ static int sai_trigger(struct dai *dai, int cmd, int direction) static int sai_probe(struct dai *dai) { - trace_sai("SAI: sai_probe"); + struct sai_pdata *sai; + + dai_info(dai, "SAI: entry"); + + /* allocate private data */ + sai = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*sai)); + if (!sai) { + dai_err(dai, "alloc failed"); + return -ENOMEM; + } + dai_set_drvdata(dai, sai); /* Software Reset for both Tx and Rx */ dai_update_bits(dai, REG_SAI_TCSR, REG_SAI_CSR_SR, REG_SAI_CSR_SR); @@ -302,6 +500,18 @@ static int sai_probe(struct dai *dai) return 0; } +static int sai_remove(struct dai *dai) +{ + struct sai_pdata *sai = dai_get_drvdata(dai); + + dai_info(dai, "entry"); + + rfree(sai); + dai_set_drvdata(dai, NULL); + + return 0; +} + static int sai_get_handshake(struct dai *dai, int direction, int stream_id) { return dai->plat_data.fifo[direction].handshake; @@ -314,7 +524,19 @@ static int sai_get_fifo(struct dai *dai, int direction, int stream_id) case DAI_DIR_CAPTURE: return dai_fifo(dai, direction); /* stream_id is unused */ default: - trace_sai_error("sai_get_fifo(): Invalid direction"); + dai_err(dai, "Invalid direction"); + return -EINVAL; + } +} + +static int sai_get_fifo_depth(struct dai *dai, int direction) +{ + switch (direction) { + case DAI_DIR_PLAYBACK: + case DAI_DIR_CAPTURE: + return dai->plat_data.fifo[direction].depth; + default: + dai_err(dai, "Invalid direction"); return -EINVAL; } } @@ -323,10 +545,12 @@ static int sai_get_hw_params(struct dai *dai, struct sof_ipc_stream_params *params, int dir) { - /* SAI only currently supports these parameters */ - params->rate = 48000; - params->channels = 2; - params->buffer_fmt = 0; + struct sai_pdata *sai = dai_get_drvdata(dai); + + params->rate = sai->params.fsync_rate; + params->channels = sai->params.tdm_slots; + params->buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + /* frame_fmt always S32_LE because that is the native width of the fifo registers */ params->frame_fmt = SOF_IPC_FRAME_S32_LE; return 0; @@ -334,15 +558,17 @@ static int sai_get_hw_params(struct dai *dai, const struct dai_driver sai_driver = { .type = SOF_DAI_IMX_SAI, - .dma_dev = DMA_DEV_SAI, + .uid = SOF_UUID(sai_uuid), + .tctx = &sai_tr, + .dma_dev = SOF_DMA_DEV_SAI, .ops = { .trigger = sai_trigger, .set_config = sai_set_config, - .pm_context_store = sai_context_store, - .pm_context_restore = sai_context_restore, .probe = sai_probe, + .remove = sai_remove, .get_handshake = sai_get_handshake, .get_fifo = sai_get_fifo, + .get_fifo_depth = sai_get_fifo_depth, .get_hw_params = sai_get_hw_params, }, }; diff --git a/src/drivers/imx/sdma.c b/src/drivers/imx/sdma.c index 72f8612f1596..a613f98b40c5 100644 --- a/src/drivers/imx/sdma.c +++ b/src/drivers/imx/sdma.c @@ -6,21 +6,23 @@ #include <sof/audio/component.h> #include <sof/drivers/sdma.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> #include <sof/lib/dma.h> #include <sof/lib/io.h> #include <sof/lib/notifier.h> -#include <sof/lib/wait.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> #include <sof/platform.h> #include <errno.h> #include <stddef.h> #include <stdint.h> -#define trace_sdma(fmt, ...) trace_event(TRACE_CLASS_DMA, fmt, ##__VA_ARGS__) -#define tracev_sdma(fmt, ...) tracev_event(TRACE_CLASS_DMA, fmt, ##__VA_ARGS__) -#define trace_sdma_error(fmt, ...) \ - trace_error(TRACE_CLASS_DMA, fmt, ##__VA_ARGS__) +LOG_MODULE_REGISTER(sdma, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(sdma); + +DECLARE_TR_CTX(sdma_tr, SOF_UUID(sdma_uuid), LOG_LEVEL_INFO); #define SDMA_BUFFER_PERIOD_COUNT 2 @@ -57,13 +59,17 @@ struct sdma_chan { /* Statically allocate BDs; we can change if we ever need dynamic * allocation */ - struct sdma_bd descriptors[SDMA_MAX_BDS]; - int descriptor_count; + struct sdma_bd desc[SDMA_MAX_BDS]; + int desc_count; struct sdma_context *ctx; struct sdma_ccb *ccb; int hw_event; + int next_bd; int sdma_chan_type; int fifo_paddr; + + unsigned int watermark_level; + unsigned int sw_done_sel; /* software done selector */ }; /* Private data for the whole controller */ @@ -79,14 +85,23 @@ struct sdma_pdata { static void sdma_set_overrides(struct dma_chan_data *channel, bool event_override, bool host_override) { - tracev_sdma("sdma_set_overrides(%d, %d)", event_override, - host_override); + tr_dbg(&sdma_tr, "event %d, host %d", event_override, host_override); dma_reg_update_bits(channel->dma, SDMA_EVTOVR, BIT(channel->index), event_override ? BIT(channel->index) : 0); dma_reg_update_bits(channel->dma, SDMA_HOSTOVR, BIT(channel->index), host_override ? BIT(channel->index) : 0); } +static void sdma_enable_channel(struct dma *dma, int channel) +{ + dma_reg_write(dma, SDMA_HSTART, BIT(channel)); +} + +static void sdma_disable_channel(struct dma *dma, int channel) +{ + dma_reg_write(dma, SDMA_STOP_STAT, BIT(channel)); +} + static int sdma_run_c0(struct dma *dma, uint8_t cmd, uint32_t buf_addr, uint16_t sdma_addr, uint16_t count) { @@ -94,29 +109,28 @@ static int sdma_run_c0(struct dma *dma, uint8_t cmd, uint32_t buf_addr, struct sdma_chan *c0data = dma_chan_get_data(c0); int ret; - tracev_sdma("sdma_run_c0 cmd %d buf_addr 0x%08x sdma_addr 0x%04x count %d", - cmd, buf_addr, sdma_addr, count); + tr_dbg(&sdma_tr, "cmd %d buf_addr 0x%08x sdma_addr 0x%04x count %d", + cmd, buf_addr, sdma_addr, count); - c0data->descriptors[0].config = SDMA_BD_CMD(cmd) | SDMA_BD_COUNT(count) - | SDMA_BD_WRAP | SDMA_BD_DONE | SDMA_BD_INT | SDMA_BD_CONT; - c0data->descriptors[0].buf_addr = buf_addr; - c0data->descriptors[0].buf_xaddr = sdma_addr; + c0data->desc[0].config = SDMA_BD_CMD(cmd) | SDMA_BD_COUNT(count) + | SDMA_BD_WRAP | SDMA_BD_DONE; + c0data->desc[0].buf_addr = buf_addr; + c0data->desc[0].buf_xaddr = sdma_addr; if (sdma_addr) - c0data->descriptors[0].config |= SDMA_BD_EXTD; + c0data->desc[0].config |= SDMA_BD_EXTD; - c0data->ccb->current_bd_paddr = (uint32_t)&c0data->descriptors[0]; - c0data->ccb->base_bd_paddr = (uint32_t)&c0data->descriptors[0]; + c0data->ccb->current_bd_paddr = (uint32_t)&c0data->desc[0]; + c0data->ccb->base_bd_paddr = (uint32_t)&c0data->desc[0]; /* Writeback descriptors and CCB */ - dcache_writeback_region(c0data->descriptors, - sizeof(c0data->descriptors[0])); + dcache_writeback_region(c0data->desc, + sizeof(c0data->desc[0])); dcache_writeback_region(c0data->ccb, sizeof(*c0data->ccb)); /* Set event override to true so we can manually start channel */ sdma_set_overrides(c0, true, false); - ret = dma_start(&dma->chan[0]); - if (ret < 0) - return ret; + + sdma_enable_channel(dma, 0); /* 1 is BIT(0) for channel 0, the bit will be cleared as the * channel finishes execution. 1ms is sufficient if everything is fine. @@ -127,7 +141,7 @@ static int sdma_run_c0(struct dma *dma, uint8_t cmd, uint32_t buf_addr, ret = 0; if (ret < 0) - trace_sdma_error("SDMA channel 0 timed out"); + tr_err(&sdma_tr, "SDMA channel 0 timed out"); /* Switch to dynamic context switch mode if needed. This saves power. */ if ((dma_reg_read(dma, SDMA_CONFIG) & SDMA_CONFIG_CSM_MSK) == @@ -135,7 +149,7 @@ static int sdma_run_c0(struct dma *dma, uint8_t cmd, uint32_t buf_addr, dma_reg_update_bits(dma, SDMA_CONFIG, SDMA_CONFIG_CSM_MSK, SDMA_CONFIG_CSM_DYN); - tracev_sdma("sdma_run_c0 done, ret = %d", ret); + tr_dbg(&sdma_tr, "done, ret = %d", ret); return ret; } @@ -144,17 +158,20 @@ static int sdma_register_init(struct dma *dma) { int ret; struct sdma_pdata *pdata = dma_get_drvdata(dma); + int i; - tracev_sdma("sdma_register_init"); + tr_dbg(&sdma_tr, "entry"); dma_reg_write(dma, SDMA_RESET, 1); /* Wait for 10us */ ret = poll_for_register_delay(dma_base(dma) + SDMA_RESET, 1, 0, 1000); if (ret < 0) { - trace_sdma_error("SDMA reset error, base address 0x%08x", - (uintptr_t)dma_base(dma)); + tr_err(&sdma_tr, "SDMA reset error, base address %p", + (void *)dma_base(dma)); return ret; } + dma_reg_write(dma, SDMA_MC0PTR, 0); + /* Ack all interrupts, they're leftover */ dma_reg_write(dma, SDMA_INTR, MASK(31, 0)); @@ -180,9 +197,12 @@ static int sdma_register_init(struct dma *dma) * It shall be updated whenever channels need to be activated by * hardware events. */ - for (int i = 0; i < SDMA_HWEVENTS_COUNT; i++) + for (i = 0; i < SDMA_HWEVENTS_COUNT; i++) dma_reg_write(dma, SDMA_CHNENBL(i), 0); + for (i = 0; i < dma->plat_data.channels; i++) + dma_reg_write(dma, SDMA_CHNPRI(i), 0); + /* Write ccb_array pointer to SDMA controller */ dma_reg_write(dma, SDMA_MC0PTR, (uint32_t)pdata->ccb_array); @@ -195,7 +215,7 @@ static void sdma_init_c0(struct dma *dma) struct sdma_pdata *sdma_pdata = dma_get_drvdata(dma); struct sdma_chan *pdata = &sdma_pdata->chan_pdata[0]; - tracev_sdma("sdma_init_c0"); + tr_dbg(&sdma_tr, "entry"); c0->status = COMP_STATE_READY; /* Reset channel 0 private data */ @@ -204,20 +224,22 @@ static void sdma_init_c0(struct dma *dma) pdata->ccb = sdma_pdata->ccb_array; pdata->hw_event = -1; dma_chan_set_data(c0, pdata); + + dma_reg_write(dma, SDMA_CHNPRI(0), SDMA_MAXPRI); } static int sdma_boot(struct dma *dma) { int ret; - tracev_sdma("sdma_boot"); + tr_dbg(&sdma_tr, "entry"); ret = sdma_register_init(dma); if (ret < 0) return ret; sdma_init_c0(dma); - tracev_sdma("sdma_boot done"); + tr_dbg(&sdma_tr, "done"); return 0; } @@ -228,52 +250,28 @@ static int sdma_upload_context(struct dma_chan_data *chan) /* Ensure context is ready for upload */ dcache_writeback_region(pdata->ctx, sizeof(*pdata->ctx)); - tracev_sdma("sdma_upload_context for channel %d", chan->index); + tr_dbg(&sdma_tr, "for channel %d", chan->index); /* Last parameters are unneeded for this command and are ignored; * set to 0. */ return sdma_run_c0(chan->dma, SDMA_CMD_C0_SET_DM, (uint32_t)pdata->ctx, SDMA_SRAM_CONTEXTS_BASE + + /* https://trac.cppcheck.net/ticket/10179 */ + /* cppcheck-suppress divideSizeof */ chan->index * sizeof(*pdata->ctx) / 4, + /* https://trac.cppcheck.net/ticket/10179 */ + /* cppcheck-suppress divideSizeof */ sizeof(*pdata->ctx) / 4); } -static int sdma_upload_contexts_all(struct dma *dma) -{ - struct sdma_pdata *pdata = dma_get_drvdata(dma); - - tracev_sdma("sdma_upload_contexts_all"); - dcache_writeback_region(pdata->contexts, sizeof(*pdata->contexts)); - - /* Division by 4 in size calculation is because count is in words and - * not in bytes - */ - return sdma_run_c0(dma, SDMA_CMD_C0_SET_DM, (uint32_t)pdata->contexts, - SDMA_SRAM_CONTEXTS_BASE, - dma->plat_data.channels * - sizeof(*pdata->contexts) / 4); -} - -static int sdma_download_contexts_all(struct dma *dma) +#if CONFIG_HAVE_SDMA_FIRMWARE +static int sdma_load_firmware(struct dma *dma, void *buf, int addr, int size) { - struct sdma_pdata *pdata = dma_get_drvdata(dma); - int ret; - - tracev_sdma("sdma_download_contexts_all"); - - /* Division by 4 in size calculation is because count is in words and - * not in bytes - */ - ret = sdma_run_c0(dma, SDMA_CMD_C0_GET_DM, (uint32_t)pdata->contexts, - SDMA_SRAM_CONTEXTS_BASE, - dma->plat_data.channels * - sizeof(*pdata->contexts) / 4); - - dcache_invalidate_region(pdata->contexts, sizeof(*pdata->contexts)); - - return ret; + return sdma_run_c0(dma->chan->dma, SDMA_CMD_C0_SET_PM, + (uint32_t)buf, addr, size / 2); } +#endif /* Below SOF related functions will be placed */ @@ -284,68 +282,79 @@ static int sdma_probe(struct dma *dma) struct sdma_pdata *pdata; if (dma->chan) { - trace_sdma_error("SDMA: Repeated probe"); + tr_err(&sdma_tr, "SDMA: Repeated probe"); return -EEXIST; } - trace_sdma("SDMA: probe"); + tr_info(&sdma_tr, "SDMA: probe"); - dma->chan = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, dma->plat_data.channels * sizeof(struct dma_chan_data)); if (!dma->chan) { - trace_sdma_error("SDMA: Probe failure, unable to allocate channel descriptors"); + tr_err(&sdma_tr, "SDMA: Probe failure, unable to allocate channel descriptors"); return -ENOMEM; } - pdata = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + pdata = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*pdata)); if (!pdata) { rfree(dma->chan); dma->chan = NULL; - trace_sdma_error("SDMA: Probe failure, unable to allocate private data"); + tr_err(&sdma_tr, "SDMA: Probe failure, unable to allocate private data"); return -ENOMEM; } dma_set_drvdata(dma, pdata); for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].status = COMP_STATE_INIT; dma->chan[channel].index = channel; dma->chan[channel].dma = dma; } - pdata->chan_pdata = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + pdata->chan_pdata = rzalloc(SOF_MEM_FLAG_KERNEL, dma->plat_data.channels * sizeof(struct sdma_chan)); if (!pdata->chan_pdata) { ret = -ENOMEM; - trace_sdma_error("SDMA: probe: out of memory"); + tr_err(&sdma_tr, "SDMA: probe: out of memory"); goto err; } - pdata->contexts = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + pdata->contexts = rzalloc(SOF_MEM_FLAG_KERNEL, dma->plat_data.channels * sizeof(struct sdma_context)); if (!pdata->contexts) { ret = -ENOMEM; - trace_sdma_error("SDMA: probe: unable to allocate contexts"); + tr_err(&sdma_tr, "SDMA: probe: unable to allocate contexts"); goto err; } - pdata->ccb_array = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, + pdata->ccb_array = rzalloc(SOF_MEM_FLAG_KERNEL, dma->plat_data.channels * sizeof(struct sdma_ccb)); if (!pdata->ccb_array) { ret = -ENOMEM; - trace_sdma_error("SDMA: probe: unable to allocate CCBs"); + tr_err(&sdma_tr, "SDMA: probe: unable to allocate CCBs"); goto err; } ret = sdma_boot(dma); if (ret < 0) { - trace_sdma_error("SDMA: Unable to boot"); + tr_err(&sdma_tr, "SDMA: Unable to boot"); goto err; } +#if CONFIG_HAVE_SDMA_FIRMWARE + ret = sdma_load_firmware(dma, (void *)sdma_code, + RAM_CODE_START_ADDR, + RAM_CODE_SIZE * sizeof(short)); + if (ret < 0) { + tr_err(&sdma_tr, "SDMA: Failed to load firmware"); + goto err; + } +#endif + goto out; err: if (pdata->chan_pdata) @@ -368,11 +377,11 @@ static int sdma_remove(struct dma *dma) struct sdma_pdata *pdata = dma_get_drvdata(dma); if (!dma->chan) { - trace_sdma_error("SDMA: Remove called without probe, that's a noop"); + tr_err(&sdma_tr, "SDMA: Remove called without probe, that's a noop"); return 0; } - tracev_sdma("sdma_remove"); + tr_dbg(&sdma_tr, "entry"); /* Prevent all channels except channel 0 from running */ dma_reg_write(dma, SDMA_HOSTOVR, 1); @@ -401,10 +410,10 @@ static struct dma_chan_data *sdma_channel_get(struct dma *dma, struct dma_chan_data *channel; struct sdma_chan *cdata; int i; - /* Ignoring channel; let's just allocate a free channel */ + /* Ignoring channel 0; let's just allocate a free channel */ - tracev_sdma("sdma_channel_get"); - for (i = 0; i < dma->plat_data.channels; i++) { + tr_dbg(&sdma_tr, "sdma_channel_get"); + for (i = 1; i < dma->plat_data.channels; i++) { channel = &dma->chan[i]; if (channel->status != COMP_STATE_INIT) continue; @@ -417,114 +426,89 @@ static struct dma_chan_data *sdma_channel_get(struct dma *dma, cdata->hw_event = -1; channel->status = COMP_STATE_READY; + channel->index = i; dma_chan_set_data(channel, cdata); /* Allow events, allow manual */ - sdma_set_overrides(channel, true, false); + sdma_set_overrides(channel, false, false); return channel; } - trace_sdma_error("sdma no channel free"); + tr_err(&sdma_tr, "sdma no channel free"); return NULL; } -static void sdma_clear_event(struct dma_chan_data *channel) +static void sdma_enable_event(struct dma_chan_data *channel, int eventnum) { struct sdma_chan *pdata = dma_chan_get_data(channel); - tracev_sdma("sdma_clear_event(%d); old event is %d", channel->index, - pdata->hw_event); - if (pdata->hw_event != -1) - dma_reg_update_bits(channel->dma, SDMA_CHNENBL(pdata->hw_event), - BIT(channel->index), 0); - pdata->hw_event = -1; + tr_dbg(&sdma_tr, "channel %d, event %d", channel->index, eventnum); + + if (eventnum < 0 || eventnum > SDMA_HWEVENTS_COUNT) + return; /* No change if request is invalid */ + + dma_reg_update_bits(channel->dma, SDMA_CHNENBL(eventnum), + BIT(channel->index), BIT(channel->index)); + + if (pdata->sw_done_sel & BIT(31)) { + unsigned int done0; + + done0 = SDMA_DONE0_CONFIG_DONE_SEL | ~SDMA_DONE0_CONFIG_DONE_DIS; + dma_reg_update_bits(channel->dma, SDMA_DONE0_CONFIG, 0xFF, done0); + } } -static void sdma_set_event(struct dma_chan_data *channel, int eventnum) +static void sdma_disable_event(struct dma_chan_data *channel, int eventnum) { - struct sdma_chan *pdata = dma_chan_get_data(channel); + tr_dbg(&sdma_tr, "channel %d, event %d", channel->index, eventnum); - if (eventnum < -1 || eventnum > SDMA_HWEVENTS_COUNT) + if (eventnum < 0 || eventnum > SDMA_HWEVENTS_COUNT) return; /* No change if request is invalid */ - sdma_clear_event(channel); - if (eventnum == -1) { - sdma_set_overrides(channel, true, false); - return; - } - - tracev_sdma("sdma_set_event(%d, %d)", channel->index, eventnum); dma_reg_update_bits(channel->dma, SDMA_CHNENBL(eventnum), - BIT(channel->index), BIT(channel->index)); - pdata->hw_event = eventnum; - - /* Set correct overrides for event-driven channels: - * EVTOVR=0 HOSTOVR=1 - */ - sdma_set_overrides(channel, false, true); + BIT(channel->index), 0); } static void sdma_channel_put(struct dma_chan_data *channel) { + struct sdma_chan *pdata = dma_chan_get_data(channel); + if (channel->status == COMP_STATE_INIT) return; /* Channel was already free */ - tracev_sdma("sdma_channel_put(%d)", channel->index); - dma_interrupt(channel, DMA_IRQ_CLEAR); - sdma_clear_event(channel); + tr_dbg(&sdma_tr, "channel %d", channel->index); + + dma_interrupt_legacy(channel, DMA_IRQ_CLEAR); + sdma_disable_event(channel, pdata->hw_event); sdma_set_overrides(channel, false, false); channel->status = COMP_STATE_INIT; } static int sdma_start(struct dma_chan_data *channel) { - struct sdma_chan *pdata = dma_chan_get_data(channel); + tr_dbg(&sdma_tr, "channel %d", channel->index); - if (channel->status == COMP_STATE_INIT) + if (channel->status != COMP_STATE_PREPARE && + channel->status != COMP_STATE_PAUSED) return -EINVAL; - trace_sdma_error("sdma_start(%d)", channel->index); - - /* If channel is event driven, allow it to run by setting HOSTOVR. - * If it's manually controlled, kickstart it by writing to SDMA_HSTART. - */ - if (pdata->hw_event != -1) - dma_reg_update_bits(channel->dma, SDMA_HOSTOVR, - BIT(channel->index), BIT(channel->index)); - else - dma_reg_write(channel->dma, SDMA_HSTART, BIT(channel->index)); + channel->status = COMP_STATE_ACTIVE; - /* Set a runnable channel priority (channel 0 requires maximum priority) - * so it remains usable even if others are schedulable. - */ - if (channel->index) - dma_reg_write(channel->dma, SDMA_CHNPRI(channel->index), - SDMA_DEFPRI); - else - dma_reg_write(channel->dma, SDMA_CHNPRI(0), SDMA_MAXPRI); + sdma_enable_channel(channel->dma, channel->index); return 0; } static int sdma_stop(struct dma_chan_data *channel) { - struct sdma_chan *pdata = dma_chan_get_data(channel); + /* do not try to stop multiple times */ + if (channel->status != COMP_STATE_ACTIVE && + channel->status != COMP_STATE_PAUSED) + return 0; - if (channel->status == COMP_STATE_INIT) - return -EINVAL; + channel->status = COMP_STATE_READY; - tracev_sdma("sdma_stop(%d)", channel->index); - if (pdata->hw_event != -1) { - /* For event driven channels, disable them from running by - * setting HOSTOVR to 0. Manually controlled channels need not - * be stopped as they will finish their transfer and stop on - * their own. - */ - dma_reg_update_bits(channel->dma, SDMA_HOSTOVR, - BIT(channel->index), 0); + tr_dbg(&sdma_tr, "channel %d", channel->index); - /* Reset channel, making it ready to start over */ - pdata->ccb->current_bd_paddr = pdata->ccb->base_bd_paddr; - return sdma_upload_context(channel); - } + sdma_disable_channel(channel->dma, channel->index); return 0; } @@ -533,9 +517,11 @@ static int sdma_pause(struct dma_chan_data *channel) { struct sdma_chan *pdata = dma_chan_get_data(channel); - if (channel->status == COMP_STATE_INIT) + if (channel->status != COMP_STATE_ACTIVE) return -EINVAL; + channel->status = COMP_STATE_PAUSED; + /* Manually controlled channels need not be paused. */ if (pdata->hw_event != -1) dma_reg_update_bits(channel->dma, SDMA_HOSTOVR, @@ -546,6 +532,11 @@ static int sdma_pause(struct dma_chan_data *channel) static int sdma_release(struct dma_chan_data *channel) { + if (channel->status != COMP_STATE_PAUSED) + return -EINVAL; + + channel->status = COMP_STATE_PREPARE; + /* No pointer realignment is necessary for release, context points * correctly to beginning of the following BD. */ @@ -554,23 +545,32 @@ static int sdma_release(struct dma_chan_data *channel) static int sdma_copy(struct dma_chan_data *channel, int bytes, uint32_t flags) { - /* Check the buffer descriptors, set the "DONE" bit on one of - * them. Ignoring "bytes" value, if the pipeline is incorrect it - * will be audible. - */ struct sdma_chan *pdata = dma_chan_get_data(channel); + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + int idx; + + tr_dbg(&sdma_tr, "entry"); + + idx = (pdata->next_bd + 1) % 2; + pdata->next_bd = idx; + + /* Work around the fact that we cannot allocate uncached memory + * on all platforms supporting SDMA. + */ + dcache_invalidate_region(&pdata->desc[idx].config, + sizeof(pdata->desc[idx].config)); + pdata->desc[idx].config |= SDMA_BD_DONE; + dcache_writeback_region(&pdata->desc[idx].config, + sizeof(pdata->desc[idx].config)); + + notifier_event(channel, NOTIFIER_ID_DMA_COPY, + NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + + sdma_enable_channel(channel->dma, channel->index); - tracev_sdma("sdma_copy"); - for (int i = 0; i < pdata->descriptor_count; i++) { - /* Work around the fact that we cannot allocate uncached memory - * on all platforms supporting SDMA. - */ - dcache_invalidate_region(&pdata->descriptors[i].config, - sizeof(pdata->descriptors[i].config)); - pdata->descriptors[i].config |= SDMA_BD_DONE; - dcache_writeback_region(&pdata->descriptors[i].config, - sizeof(pdata->descriptors[i].config)); - } return 0; } @@ -580,14 +580,14 @@ static int sdma_status(struct dma_chan_data *channel, struct sdma_chan *pdata = dma_chan_get_data(channel); struct sdma_bd *bd; - tracev_sdma("sdma_status"); + tr_dbg(&sdma_tr, "entry"); if (channel->status == COMP_STATE_INIT) return -EINVAL; status->state = channel->status; status->flags = 0; status->w_pos = 0; status->r_pos = 0; - status->timestamp = timer_get_system(timer_get()); + status->timestamp = sof_cycle_get_64(); bd = (struct sdma_bd *)pdata->ccb->current_bd_paddr; @@ -598,11 +598,14 @@ static int sdma_status(struct dma_chan_data *channel, status->w_pos = bd->buf_xaddr; break; case SDMA_CHAN_TYPE_AP2MCU: + case SDMA_CHAN_TYPE_MCU2SHP: + case SDMA_CHAN_TYPE_SAI2MCU: status->r_pos = bd->buf_addr; status->w_pos = pdata->fifo_paddr; /* We cannot see the target address */ break; case SDMA_CHAN_TYPE_MCU2AP: + case SDMA_CHAN_TYPE_SHP2MCU: status->w_pos = bd->buf_addr; status->r_pos = pdata->fifo_paddr; break; @@ -610,165 +613,197 @@ static int sdma_status(struct dma_chan_data *channel, return 0; } -static int sdma_set_config(struct dma_chan_data *channel, - struct dma_sg_config *config) +static void sdma_set_watermarklevel(struct dma_chan_data *chan) { - struct sdma_chan *pdata = dma_chan_get_data(channel); - int handshake; - bool src_may_change, dst_may_change; - uint32_t fifo_paddr = 0; - int i; - int hwevent, watermark; - int width; - int ret; - uint32_t sdma_script_addr; + struct sdma_chan *pdata = dma_chan_get_data(chan); + + /* TODO: retrieve this information from DAI */ + unsigned int n_fifos = 4; /* number of HW fifos used */ + unsigned int words_per_fifo = 1; /* number of audio channels per frame */ - tracev_sdma("sdma_set_config channel %d", channel->index); - /* Data to store in the descriptors: - * 1) Each descriptor corresponds to each of the - * config->elem_array elems; if we have more than - * MAX_DESCRIPTORS we bail outright. For the future, we could - * allocate the per-channel descriptors dynamically. - * 2) For each of them, store the host side (SDRAM side) as - * buf_addr and keep the FIFO address as a separate variable. - * Complain if this address changes between descriptors as we - * do not support this for now. - * 3) Enable interrupts, set up transfer width, length of elem, - * wrap bit on the last descriptor, host side address, and - * finally the DONE bit so the SDMA can use the descriptors. - * 4) The FIFO address will be stored in the context. - * 5) Actually upload context now as we are inside DAI prepare. - * We have no other opportunity in the future. + /* sw_done_sel mimics software done configuration from Linux + * see Documentation/devicetree/bindings/fsl-imx-sdma.txt */ + unsigned int sw_done_sel = 0; - /* Validate requested configuration */ - if (config->elem_array.count > SDMA_MAX_BDS) { - trace_sdma_error("sdma_set_config: Unable to handle %d descriptors", - config->elem_array.count); - return -EINVAL; - } - if (config->elem_array.count <= 0) { - trace_sdma_error("sdma_set_config: Invalid descriptor count: %d", - config->elem_array.count); - return -EINVAL; - } + /* sw_done_sel configuration + * - bit31: sw_done + * - bit15:8 selector + * - bit7-0 priority + */ + sw_done_sel |= BIT(31); + + /* watermark level: + * bit0~11: wartermark level(wml*fifo_number) + * bit15~12: to do-fifo number + * bit16~19: fifo offset + * bit27~24: sw done selector + * bit28~31: numbers of audio channels in one frame, 0: 1 channel,1: 2 channels + * bit23: sw done enable + */ + + pdata->watermark_level |= SDMA_WATERMARK_LEVEL_SW_DONE | + (sw_done_sel & 0xff) << SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF; + + pdata->watermark_level |= + SDMA_WATERMARK_LEVEL_N_FIFOS(n_fifos); + + pdata->watermark_level |= + SDMA_WATERMARK_LEVEL_WORDS_PER_FIFO(words_per_fifo - 1); + + pdata->sw_done_sel = sw_done_sel; +} + +static int sdma_read_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + int i; + struct sdma_chan *pdata = dma_chan_get_data(channel); + struct dai_data *dd = channel->dev_data; + uint32_t dma_dev = dd->dai->drv->dma_dev; switch (config->direction) { - case DMA_DIR_MEM_TO_DEV: - src_may_change = true; dst_may_change = false; - handshake = config->dest_dev; - pdata->sdma_chan_type = SDMA_CHAN_TYPE_SHP2MCU; - break; - case DMA_DIR_DEV_TO_MEM: - src_may_change = false; dst_may_change = true; - handshake = config->src_dev; + case SOF_DMA_DIR_MEM_TO_DEV: + pdata->hw_event = config->dest_dev; pdata->sdma_chan_type = SDMA_CHAN_TYPE_MCU2SHP; + pdata->fifo_paddr = config->elem_array.elems[0].dest; + break; + case SOF_DMA_DIR_DEV_TO_MEM: + pdata->hw_event = config->src_dev; + if (dma_dev == SOF_DMA_DEV_MICFIL) + pdata->sdma_chan_type = SDMA_CHAN_TYPE_SAI2MCU; + else + pdata->sdma_chan_type = SDMA_CHAN_TYPE_SHP2MCU; + pdata->fifo_paddr = config->elem_array.elems[0].src; break; - case DMA_DIR_MEM_TO_MEM: + case SOF_DMA_DIR_MEM_TO_MEM: pdata->sdma_chan_type = SDMA_CHAN_TYPE_AP2AP; - /* Fallthrough, TODO implement if desired, both are true */ + /* Fallthrough, TODO: implement to support m2m */ default: - trace_sdma_error("sdma_set_config: Unsupported direction %d", - config->direction); + tr_err(&sdma_tr, "sdma_set_config: Unsupported direction %d", + config->direction); return -EINVAL; } for (i = 0; i < config->elem_array.count; i++) { - if (!src_may_change) { - /* src is fifo */ - if (i == 0) { - fifo_paddr = config->elem_array.elems[0].src; - } else if (fifo_paddr != config->elem_array.elems[i].src) { - trace_sdma_error("sdma_set_config: FIFO changes address!"); - return -EINVAL; - } + if (config->direction == SOF_DMA_DIR_MEM_TO_DEV && + pdata->fifo_paddr != config->elem_array.elems[i].dest) { + tr_err(&sdma_tr, "FIFO changes address!"); + return -EINVAL; } - if (!dst_may_change) { - /* dst is fifo */ - if (i == 0) { - fifo_paddr = config->elem_array.elems[0].dest; - } else if (fifo_paddr != config->elem_array.elems[i].dest) { - trace_sdma_error("sdma_set_config: FIFO changes address!"); - return -EINVAL; - } + + if (config->direction == SOF_DMA_DIR_DEV_TO_MEM && + pdata->fifo_paddr != config->elem_array.elems[i].src) { + tr_err(&sdma_tr, "FIFO changes address!"); + return -EINVAL; } + if (config->elem_array.elems[i].size > SDMA_BD_MAX_COUNT) { /* Future improvement: Create multiple BDs so as to * support this situation */ - trace_sdma_error("sdma_set_config: elem transfers too much: %d bytes", - config->elem_array.elems[i].size); + tr_err(&sdma_tr, "sdma_set_config: elem transfers too much: %d bytes", + config->elem_array.elems[i].size); return -EINVAL; } } - /* Checks passed, we need to populate the buffer descriptors, - * adjust count, configure context so the FIFO address is also - * stored, upload context and have everything be ready. - */ - /* The handshake currently only contains the hardware channel - * number itself. + return 0; +} + +/* Data to store in the descriptors: + * 1) Each descriptor corresponds to each of the + * config->elem_array elems; if we have more than + * MAX_DESCRIPTORS we bail outright. For the future, we could + * allocate the per-channel descriptors dynamically. + * 2) For each of them, store the host side (SDRAM side) as + * buf_addr and keep the FIFO address as a separate variable. + * Complain if this address changes between descriptors as we + * do not support this for now. + * 3) Enable interrupts, set up transfer width, length of elem, + * wrap bit on the last descriptor, host side address, and + * finally the DONE bit so the SDMA can use the descriptors. + * 4) The FIFO address will be stored in the context. + * 5) Actually upload context now as we are inside DAI prepare. + * We have no other opportunity in the future. + */ +static int sdma_prep_desc(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + int i; + int width; + int watermark; + uint32_t sdma_script_addr; + struct sdma_chan *pdata = dma_chan_get_data(channel); + struct sdma_bd *bd; + + /* Validate requested configuration */ + if (config->elem_array.count > SDMA_MAX_BDS) { + tr_err(&sdma_tr, "sdma_set_config: Unable to handle %d descriptors", + config->elem_array.count); + return -EINVAL; + } + if (config->elem_array.count <= 0) { + tr_err(&sdma_tr, "sdma_set_config: Invalid descriptor count: %d", + config->elem_array.count); + return -EINVAL; + } + + pdata->next_bd = 0; + + /* Silence "may be used uninitialized" warnings with gcc10 -O1 + * and maybe other compilers/levels that don't know that + * config->elem_array.count > 0 */ - hwevent = handshake; - watermark = config->burst_elems; + bd = &pdata->desc[0]; + width = 0; for (i = 0; i < config->elem_array.count; i++) { + bd = &pdata->desc[i]; /* For MEM2DEV and DEV2MEM, buf_addr holds the RAM address and * the FIFO address is stored in one of the general registers of * the SDMA core. * For MEM2MEM the source is stored in buf_addr and destination * is in buf_xaddr. */ - pdata->descriptors[i].buf_xaddr = 0; - pdata->descriptors[i].buf_addr = - config->elem_array.elems[i].src; - if (!src_may_change) - pdata->descriptors[i].buf_addr = - config->elem_array.elems[i].dest; - if (src_may_change && dst_may_change) { - /* M2M copy */ - pdata->descriptors[i].buf_xaddr = - config->elem_array.elems[i].dest; - } - - /* We are interested in the element width on the hardware side; - * on RAM side we can adjust. - */ - width = config->src_width; - if (!dst_may_change) + switch (config->direction) { + case SOF_DMA_DIR_MEM_TO_DEV: + bd->buf_addr = config->elem_array.elems[i].src; + width = config->src_width; + break; + case SOF_DMA_DIR_DEV_TO_MEM: + bd->buf_addr = config->elem_array.elems[i].dest; width = config->dest_width; + break; + case SOF_DMA_DIR_MEM_TO_MEM: + bd->buf_addr = config->elem_array.elems[i].src; + bd->buf_xaddr = config->elem_array.elems[i].dest; + width = config->dest_width; + break; + default: + return -EINVAL; + } - pdata->descriptors[i].config = - SDMA_BD_COUNT(config->elem_array.elems[i].size) | - SDMA_BD_CMD(SDMA_CMD_XFER_SIZE(width)) | SDMA_BD_CONT; + bd->config = SDMA_BD_COUNT(config->elem_array.elems[i].size) | + SDMA_BD_CMD(SDMA_CMD_XFER_SIZE(width)); if (!config->irq_disabled) - pdata->descriptors[i].config |= SDMA_BD_INT; - if (dst_may_change) { - /* Capture or M2M, enable this descriptor to be - * used by SDMAC - */ - pdata->descriptors[i].config |= SDMA_BD_DONE; - /* On playback we don't do this and instead wait - * for copy() to let us know the data is ready. - * copy() is called during preload. - */ - } - if (src_may_change && dst_may_change) - pdata->descriptors[i].config |= SDMA_BD_EXTD; + bd->config |= SDMA_BD_INT; + + bd->config |= SDMA_BD_CONT; + if (pdata->next_bd == i) + bd->config |= SDMA_BD_DONE; } + /* Configure last BD to account for cyclic transfers */ if (config->cyclic) - pdata->descriptors[config->elem_array.count - 1].config |= - SDMA_BD_WRAP; - else - pdata->descriptors[config->elem_array.count - 1].config &= - ~SDMA_BD_CONT; + bd->config |= SDMA_BD_WRAP; + bd->config &= ~SDMA_BD_CONT; /* CCB must point to buffer descriptors array */ memset(pdata->ccb, 0, sizeof(*pdata->ccb)); - pdata->ccb->base_bd_paddr = (uint32_t)pdata->descriptors; - pdata->ccb->current_bd_paddr = (uint32_t)pdata->descriptors; - pdata->descriptor_count = config->elem_array.count; + pdata->ccb->base_bd_paddr = (uint32_t)pdata->desc; + pdata->ccb->current_bd_paddr = (uint32_t)pdata->desc; + pdata->desc_count = config->elem_array.count; /* Context must be configured, dependent on transfer direction */ @@ -782,14 +817,26 @@ static int sdma_set_config(struct dma_chan_data *channel, case SDMA_CHAN_TYPE_SHP2MCU: sdma_script_addr = SDMA_SCRIPT_SHP2MCU_OFF; break; + case SDMA_CHAN_TYPE_SAI2MCU: + sdma_script_addr = SDMA_SCRIPT_SAI2MCU_OFF; + break; default: /* This case doesn't happen; we need to assign the other cases * for AP2MCU and MCU2AP */ - trace_sdma_error("Unexpected SDMA error"); + tr_err(&sdma_tr, "Unexpected SDMA error"); return -EINVAL; } + watermark = (config->burst_elems * width) / 8; + + if (pdata->sdma_chan_type == SDMA_CHAN_TYPE_SAI2MCU) { + sdma_set_watermarklevel(channel); + watermark |= pdata->watermark_level; + } else { + watermark = (config->burst_elems * width) / 8; + } + memset(pdata->ctx, 0, sizeof(*pdata->ctx)); pdata->ctx->pc = sdma_script_addr; @@ -797,51 +844,68 @@ static int sdma_set_config(struct dma_chan_data *channel, /* Base of RAM, TODO must be moved to a define */ pdata->ctx->g_reg[7] = 0x40000000; } else { - if (hwevent != -1) { - if (hwevent >= 32) - pdata->ctx->g_reg[0] |= BIT(hwevent - 32); + if (pdata->hw_event != -1) { + if (pdata->hw_event >= 32) + pdata->ctx->g_reg[0] |= BIT(pdata->hw_event - 32); else - pdata->ctx->g_reg[1] |= BIT(hwevent); + pdata->ctx->g_reg[1] |= BIT(pdata->hw_event); } - pdata->ctx->g_reg[6] = fifo_paddr; + pdata->ctx->g_reg[6] = pdata->fifo_paddr; pdata->ctx->g_reg[7] = watermark; } + dcache_writeback_region(pdata->desc, sizeof(pdata->desc)); + dcache_writeback_region(pdata->ccb, sizeof(*pdata->ccb)); + dcache_writeback_region(pdata->ctx, sizeof(*pdata->ctx)); + + return 0; +} + +static int sdma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + struct sdma_chan *pdata = dma_chan_get_data(channel); + int ret; + + tr_dbg(&sdma_tr, "channel %d", channel->index); + + ret = sdma_read_config(channel, config); + if (ret < 0) + return ret; + + channel->is_scheduling_source = config->is_scheduling_source; + channel->direction = config->direction; + + ret = sdma_prep_desc(channel, config); + if (ret < 0) + return ret; + + /* allow events + allow manual start */ + sdma_set_overrides(channel, false, false); + /* Upload context */ ret = sdma_upload_context(channel); if (ret < 0) { - trace_sdma_error("Unable to upload context, bailing"); + tr_err(&sdma_tr, "Unable to upload context, bailing"); return ret; } - tracev_sdma("SDMA context uploaded"); + tr_dbg(&sdma_tr, "SDMA context uploaded"); /* Context uploaded, we can set up events now */ - sdma_set_event(channel, hwevent); + sdma_enable_event(channel, pdata->hw_event); /* Finally set channel priority */ dma_reg_write(channel->dma, SDMA_CHNPRI(channel->index), SDMA_DEFPRI); - return 0; -} + channel->status = COMP_STATE_PREPARE; -static int sdma_pm_context_store(struct dma *dma) -{ - return sdma_download_contexts_all(dma); -} - -static int sdma_pm_context_restore(struct dma *dma) -{ - return sdma_upload_contexts_all(dma); + return 0; } static int sdma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) { - if (!channel->index) { - trace_sdma_error("sdma_interrupt called for channel 0; ignoring command"); + if (!channel->index) return 0; - } - - tracev_sdma("sdma_interrupt(%d cmd %d)", channel->index, cmd); switch (cmd) { case DMA_IRQ_STATUS_GET: @@ -860,7 +924,7 @@ static int sdma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) */ return 0; default: - trace_sdma_error("sdma_interrupt unknown cmd %d", cmd); + tr_err(&sdma_tr, "unknown cmd %d", cmd); return -EINVAL; } } @@ -901,31 +965,33 @@ static int sdma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t result_data = 0; int i; - tracev_sdma("sdma_get_data_size(%d)", channel->index); + tr_dbg(&sdma_tr, "channel %d", channel->index); if (channel->index == 0) { /* Channel 0 shouldn't have this called anyway */ - trace_sdma_error("Please do not call get_data_size on SDMA channel 0!"); + tr_err(&sdma_tr, "Please do not call get_data_size on SDMA channel 0!"); *avail = *free = 0; return -EINVAL; } - for (i = 0; i < pdata->descriptor_count && i < SDMA_MAX_BDS; i++) { - if (pdata->descriptors[i].config & SDMA_BD_DONE) + 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 */ - result_data += pdata->descriptors[i].config & + result_data += pdata->desc[i].config & SDMA_BD_COUNT_MASK; } *avail = *free = 0; switch (channel->direction) { - case DMA_DIR_MEM_TO_DEV: - *avail = result_data; - break; - case DMA_DIR_DEV_TO_MEM: + case SOF_DMA_DIR_MEM_TO_DEV: *free = result_data; break; + case SOF_DMA_DIR_DEV_TO_MEM: + *avail = result_data; + break; default: - trace_sdma_error("sdma_get_data_size channel invalid direction"); + tr_err(&sdma_tr, "channel invalid direction"); return -EINVAL; } return 0; @@ -941,8 +1007,6 @@ const struct dma_ops sdma_ops = { .copy = sdma_copy, .status = sdma_status, .set_config = sdma_set_config, - .pm_context_restore = sdma_pm_context_restore, - .pm_context_store = sdma_pm_context_store, .probe = sdma_probe, .remove = sdma_remove, .interrupt = sdma_interrupt, diff --git a/src/drivers/imx/timer.c b/src/drivers/imx/timer.c index 6c74fdeae754..fd396af493ea 100644 --- a/src/drivers/imx/timer.c +++ b/src/drivers/imx/timer.c @@ -5,8 +5,8 @@ // Author: Daniel Baluta <daniel.baluta@nxp.com> #include <sof/audio/component_ext.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> #include <sof/lib/memory.h> #include <sof/platform.h> #include <ipc/stream.h> @@ -38,6 +38,12 @@ uint64_t platform_timer_get(struct timer *timer) return arch_timer_get_system(timer); } +/* IRQs off in arch_timer_get_system() */ +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return arch_timer_get_system(timer); +} + /* get timestamp for host stream DMA position */ void platform_host_timestamp(struct comp_dev *host, struct sof_ipc_stream_posn *posn) @@ -87,28 +93,20 @@ int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) break; } - platform_shared_commit(timer, sizeof(*timer)); - return ret; } void timer_unregister(struct timer *timer, void *arg) { interrupt_unregister(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); } void timer_enable(struct timer *timer, void *arg, int core) { interrupt_enable(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); } void timer_disable(struct timer *timer, void *arg, int core) { interrupt_disable(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); } diff --git a/src/drivers/intel/CMakeLists.txt b/src/drivers/intel/CMakeLists.txt deleted file mode 100644 index 31d10c3ed63a..000000000000 --- a/src/drivers/intel/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -if(CONFIG_BAYTRAIL OR CONFIG_CHERRYTRAIL) - add_local_sources(sof pmc-ipc.c) - add_subdirectory(baytrail) -elseif(CONFIG_HASWELL OR CONFIG_BROADWELL) - add_subdirectory(haswell) -elseif(CONFIG_CAVS) - add_subdirectory(cavs) -endif() diff --git a/src/drivers/intel/baytrail/CMakeLists.txt b/src/drivers/intel/baytrail/CMakeLists.txt deleted file mode 100644 index 2582290b7786..000000000000 --- a/src/drivers/intel/baytrail/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof - interrupt.c - ssp.c - ipc.c - timer.c -) diff --git a/src/drivers/intel/baytrail/interrupt.c b/src/drivers/intel/baytrail/interrupt.c deleted file mode 100644 index 4f881d52308f..000000000000 --- a/src/drivers/intel/baytrail/interrupt.c +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/lib/shim.h> -#include <config.h> -#include <stdint.h> - -void platform_interrupt_init(void) {} - -void platform_interrupt_set(uint32_t irq) -{ - arch_interrupt_set(irq); -} - -/* clear mask in PISR, bits are W1C in docs but some bits need preserved ?? */ -void platform_interrupt_clear(uint32_t irq, uint32_t mask) -{ - switch (irq) { -#if CONFIG_INTERRUPT_LEVEL_1 - case IRQ_NUM_SOFTWARE2: -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - case IRQ_NUM_SOFTWARE3: -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - case IRQ_NUM_SOFTWARE4: - case IRQ_NUM_SOFTWARE5: -#endif -#if CONFIG_INTERRUPT_LEVEL_4 - case IRQ_NUM_EXT_PMC: - case IRQ_NUM_EXT_IA: -#endif -#if CONFIG_INTERRUPT_LEVEL_1 || CONFIG_INTERRUPT_LEVEL_2 || \ - CONFIG_INTERRUPT_LEVEL_3 || CONFIG_INTERRUPT_LEVEL_4 - arch_interrupt_clear(irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_5 - case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_PISR, mask << 3); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_PISR, mask << 4); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_SSP2: - shim_write(SHIM_PISR, mask << 5); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_PISR, mask << 16); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_PISR, mask << 24); - arch_interrupt_clear(irq); - break; -#if defined CONFIG_CHERRYTRAIL - case IRQ_NUM_EXT_DMAC2: - shim_write(SHIM_PISRH, mask << 0); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_SSP3: - shim_write(SHIM_PISRH, mask << 8); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_SSP4: - shim_write(SHIM_PISRH, mask << 9); - arch_interrupt_clear(irq); - break; - case IRQ_NUM_EXT_SSP5: - shim_write(SHIM_PISRH, mask << 10); - arch_interrupt_clear(irq); - break; -#endif -#endif - default: - break; - } -} - -/* TODO: expand this to 64 bit - should we just return mask of IRQ numbers */ -uint32_t platform_interrupt_get_enabled(void) -{ - return shim_read(SHIM_PIMR); -} - -void interrupt_mask(uint32_t irq, unsigned int cpu) -{ -#if CONFIG_INTERRUPT_LEVEL_5 - switch (irq) { - case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_PIMR, 1 << 3); - break; - case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_PIMR, 1 << 4); - break; - case IRQ_NUM_EXT_SSP2: - shim_write(SHIM_PIMR, 1 << 5); - break; - case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_PIMR, 1 << 16); - break; - case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_PIMR, 1 << 24); - break; -#if defined CONFIG_CHERRYTRAIL - case IRQ_NUM_EXT_DMAC2: - shim_write(SHIM_PIMRH, 1 << 8); - break; - case IRQ_NUM_EXT_SSP3: - shim_write(SHIM_PIMRH, 1 << 0); - break; - case IRQ_NUM_EXT_SSP4: - shim_write(SHIM_PIMRH, 1 << 1); - break; - case IRQ_NUM_EXT_SSP5: - shim_write(SHIM_PIMRH, 1 << 2); - break; -#endif - default: - break; - } -#endif -} - -void interrupt_unmask(uint32_t irq, unsigned int cpu) -{ -#if CONFIG_INTERRUPT_LEVEL_5 - switch (irq) { - case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 3)); - break; - case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 4)); - break; - case IRQ_NUM_EXT_SSP2: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 5)); - break; - case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 16)); - break; - case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) & ~(1 << 24)); - break; -#if defined CONFIG_CHERRYTRAIL - case IRQ_NUM_EXT_DMAC2: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 8)); - break; - case IRQ_NUM_EXT_SSP3: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 0)); - break; - case IRQ_NUM_EXT_SSP4: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 1)); - break; - case IRQ_NUM_EXT_SSP5: - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) & ~(1 << 2)); - break; -#endif - default: - break; - } -#endif -} diff --git a/src/drivers/intel/baytrail/ipc.c b/src/drivers/intel/baytrail/ipc.c deleted file mode 100644 index 56ef73c6a35d..000000000000 --- a/src/drivers/intel/baytrail/ipc.c +++ /dev/null @@ -1,275 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dma.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/lib/uuid.h> -#include <sof/lib/wait.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/spinlock.h> -#include <ipc/header.h> -#include <ipc/topology.h> -#include <stdbool.h> -#include <stdint.h> - -/* 80ef9faa-a407-47d2-ae50-7973d106489e */ -DECLARE_SOF_UUID("ipc-task", ipc_task_uuid, 0x80ef9faa, 0xa407, 0x47d2, - 0xae, 0x50, 0x79, 0x73, 0xd1, 0x06, 0x48, 0x9e); - -/* private data for IPC */ -struct ipc_data { - struct ipc_data_host_buffer dh_buffer; -}; - -static void irq_handler(void *arg) -{ - struct ipc *ipc = arg; - uint32_t isr; - uint32_t imrd; - - /* Interrupt arrived, check src */ - isr = shim_read(SHIM_ISRD); - imrd = shim_read(SHIM_IMRD); - - tracev_ipc("ipc: irq isr 0x%x", isr); - - /* reply message(done) from host */ - if (isr & SHIM_ISRD_DONE && - !(imrd & SHIM_IMRD_DONE)) { - - /* Mask Done interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_DONE); - - /* clear DONE bit - tell Host we have completed */ - shim_write(SHIM_IPCDH, - shim_read(SHIM_IPCDH) & ~SHIM_IPCDH_DONE); - - ipc->is_notification_pending = false; - - /* unmask Done interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE); - } - - /* new message from host */ - if (isr & SHIM_ISRD_BUSY && - !(imrd & SHIM_IMRD_BUSY)) { - - /* Mask Busy interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_BUSY); - - ipc_schedule_process(ipc); - } -} - -enum task_state ipc_platform_do_cmd(void *data) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_cmd_hdr *hdr; - /* Use struct ipc_data *iipc = ipc_get_drvdata(ipc); if needed */ - - /* perform command */ - hdr = mailbox_validate(); - ipc_cmd(hdr); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return SOF_TASK_STATE_COMPLETED; -} - -void ipc_platform_complete_cmd(void *data) -{ - uint32_t ipcxh; - - /* clear BUSY bit and set DONE bit - accept new messages */ - ipcxh = shim_read(SHIM_IPCXH); - ipcxh &= ~SHIM_IPCXH_BUSY; - ipcxh |= SHIM_IPCXH_DONE; - shim_write(SHIM_IPCXH, ipcxh); - - /* unmask busy interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY); -} - -int ipc_platform_send_msg(struct ipc_msg *msg) -{ - struct ipc *ipc = ipc_get(); - int ret = 0; - - /* can't send notification when one is in progress */ - if (ipc->is_notification_pending || - shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) { - ret = -EBUSY; - goto out; - } - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - list_item_del(&msg->list); - tracev_ipc("ipc: msg tx -> 0x%x", msg->header); - - ipc->is_notification_pending = true; - - /* now interrupt host to tell it we have message sent */ - shim_write(SHIM_IPCDL, msg->header); - shim_write(SHIM_IPCDH, SHIM_IPCDH_BUSY); - - platform_shared_commit(msg, sizeof(*msg)); - -out: - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) -{ - struct ipc_data *iipc = ipc_get_drvdata(ipc); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return &iipc->dh_buffer; -} - -int platform_ipc_init(struct ipc *ipc) -{ - struct ipc_data *iipc; - uint32_t imrd, dir, caps, dev; - - /* init ipc data */ - iipc = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(struct ipc_data)); - ipc_set_drvdata(ipc, iipc); - - /* schedule */ - schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), - &ipc_task_ops, ipc, 0, 0); - -#if CONFIG_HOST_PTABLE - /* allocate page table buffer */ - iipc->dh_buffer.page_table = rzalloc(SOF_MEM_ZONE_SYS, 0, - SOF_MEM_CAPS_RAM, - PLATFORM_PAGE_TABLE_SIZE); - if (iipc->dh_buffer.page_table) - bzero(iipc->dh_buffer.page_table, PLATFORM_PAGE_TABLE_SIZE); -#endif - - /* request HDA DMA with shared access privilege */ - caps = 0; - dir = DMA_DIR_HMEM_TO_LMEM; - dev = DMA_DEV_HOST; - iipc->dh_buffer.dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED); - - /* configure interrupt */ - interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, ipc); - interrupt_enable(PLATFORM_IPC_INTERRUPT, ipc); - - /* Unmask Busy and Done interrupts */ - imrd = shim_read(SHIM_IMRD); - imrd &= ~(SHIM_IMRD_BUSY | SHIM_IMRD_DONE); - shim_write(SHIM_IMRD, imrd); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return 0; -} - -#if CONFIG_IPC_POLLING - -int ipc_platform_poll_init(void) -{ - return 0; -} - -/* tell host we have completed command */ -void ipc_platform_poll_set_cmd_done(void) -{ - ipc_platform_complete_cmd(NULL); -} - -/* read the IPC register for any new command messages */ -int ipc_platform_poll_is_cmd_pending(void) -{ - uint32_t isr; - uint32_t imrd; - - /* Interrupt arrived, check src */ - isr = shim_read(SHIM_ISRD); - imrd = shim_read(SHIM_IMRD); - - /* new message from host */ - if (isr & SHIM_ISRD_BUSY && - !(imrd & SHIM_IMRD_BUSY)) { - - /* Mask Busy interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_BUSY); - - /* new message */ - return 1; - } - - /* no new message */ - return 0; -} - -int ipc_platform_poll_is_host_ready(void) -{ - uint32_t isr; - uint32_t imrd; - - /* Interrupt arrived, check src */ - isr = shim_read(SHIM_ISRD); - imrd = shim_read(SHIM_IMRD); - - /* reply message(done) from host */ - if (isr & SHIM_ISRD_DONE && - !(imrd & SHIM_IMRD_DONE)) { - - /* Mask Done interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_DONE); - - /* clear DONE bit - tell Host we have completed */ - shim_write(SHIM_IPCDH, - shim_read(SHIM_IPCDH) & ~SHIM_IPCDH_DONE); - - /* unmask Done interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE); - - /* host done */ - return 1; - } - - /* host still pending */ - return 0; -} - -int ipc_platform_poll_tx_host_msg(struct ipc_msg *msg) -{ - /* can't send notification when one is in progress */ - if (shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) - return 0; - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - - /* now interrupt host to tell it we have message sent */ - shim_write(SHIM_IPCDL, msg->header); - shim_write(SHIM_IPCDH, SHIM_IPCDH_BUSY); - - /* message sent */ - platform_shared_commit(msg, sizeof(*msg)); - return 1; -} - -#endif diff --git a/src/drivers/intel/baytrail/ssp.c b/src/drivers/intel/baytrail/ssp.c deleted file mode 100644 index b1efc197a0e1..000000000000 --- a/src/drivers/intel/baytrail/ssp.c +++ /dev/null @@ -1,659 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/dai-intel.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stdbool.h> -#include <stdint.h> - -/* empty SSP receive FIFO */ -static void ssp_empty_rx_fifo(struct dai *dai) -{ - uint32_t sssr; - uint32_t entries; - uint32_t i; - - sssr = ssp_read(dai, SSSR); - - /* clear interrupt */ - if (sssr & SSSR_ROR) - ssp_write(dai, SSSR, sssr); - - /* empty fifo */ - if (sssr & SSSR_RNE) { - entries = SFIFOL_RFL(ssp_read(dai, SFIFOL)); - for (i = 0; i < entries + 1; i++) - ssp_read(dai, SSDR); - } -} - -/* save SSP context prior to entering D3 */ -static int ssp_context_store(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - ssp->sscr0 = ssp_read(dai, SSCR0); - ssp->sscr1 = ssp_read(dai, SSCR1); - - /* FIXME: need to store sscr2,3,4,5 */ - ssp->psp = ssp_read(dai, SSPSP); - - return 0; -} - -/* restore SSP context after leaving D3 */ -static int ssp_context_restore(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - ssp_write(dai, SSCR0, ssp->sscr0); - ssp_write(dai, SSCR1, ssp->sscr1); - /* FIXME: need to restore sscr2,3,4,5 */ - ssp_write(dai, SSPSP, ssp->psp); - - return 0; -} - -/* Digital Audio interface formatting */ -static int ssp_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - uint32_t sscr0; - uint32_t sscr1; - uint32_t sscr2; - uint32_t sscr3; - uint32_t sscr4; - uint32_t sscr5; - uint32_t sspsp; - uint32_t sfifott; - uint32_t mdiv; - uint32_t bdiv; - uint32_t data_size; - uint32_t start_delay; - uint32_t active_tx_slots = 2; - uint32_t active_rx_slots = 2; - uint32_t frame_len = 0; - bool inverted_frame = false; - bool cfs = false; - bool cbs = false; - int ret = 0; - - spin_lock(&dai->lock); - - /* is playback/capture already running */ - if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE || - ssp->state[DAI_DIR_CAPTURE] == COMP_STATE_ACTIVE) { - dai_err(dai, "ssp_set_config(): playback/capture already running"); - ret = -EINVAL; - goto out; - } - - dai_info(dai, "ssp_set_config(), config->format = %d", config->format); - - /* reset SSP settings */ - /* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */ - /* - * FIXME: MOD, ACS, NCS are not set, - * no support for network mode for now - */ - sscr0 = SSCR0_PSP | SSCR0_RIM | SSCR0_TIM; - - /* - * FIXME: PINTE and RWOT are not set in sscr1 - * sscr1 = SSCR1_PINTE | SSCR1_RWOT; - */ - - /* sscr1 dynamic settings are TFT, RFT, SFRMDIR, SCLKDIR, SCFR */ - sscr1 = 0; -#ifdef ENABLE_SSCR1_TRISTATE - sscr1 |= SSCR1_TTE; /* make sure SDO line is tri-stated when inactive */ -#endif -#ifdef ENABLE_TIE_RIE /* FIXME: not enabled, difference with SST driver */ - sscr1 |= SSCR1_TIE | SSCR1_RIE; -#endif - - /* sscr2 dynamic setting is SLV_EXT_CLK_RUN_EN */ - sscr2 = SSCR2_URUN_FIX0; - sscr2 |= SSCR2_ASRC_INTR_MASK; -#ifdef ENABLE_SSCR2_FIXES /* FIXME: is this needed ? */ - sscr2 |= SSCR2_UNDRN_FIX_EN | SSCR2_FIFO_EMPTY_FIX_EN; -#endif - - /* - * sscr3 dynamic settings are FRM_MS_EN, I2S_MODE_EN, I2S_FRM_POL, - * I2S_TX_EN, I2S_RX_EN, I2S_CLK_MST - */ - sscr3 = SSCR3_SYN_FIX_EN; -#ifdef ENABLE_SSRC3_FIXES - /* - * this seems to prevent DSP modes from working but is harmless for - * I2S and LEFT_J. Keep with ifdef in case it's ever needed. - */ - sscr3 |= SSCR3_I2S_TX_SS_FIX_EN | SSCR3_I2S_RX_SS_FIX_EN | - SSCR3_STRETCH_TX | SSCR3_STRETCH_RX; -#endif - -#ifdef ENABLE_CLK_EDGE_SEL /* FIXME: is this needed ? */ - sscr3 |= SSCR3_CLK_EDGE_SEL; -#endif - - /* sscr4 dynamic settings is TOT_FRAME_PRD */ - sscr4 = 0x0; - - /* sscr4 dynamic settings are FRM_ASRT_CLOCKS and FRM_POLARITY */ - sscr5 = 0x0; - - /* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */ - sspsp = SSPSP_ETDS; /* last value (bit 0) */ - - ssp->config = *config; - ssp->params = config->ssp; - - /* clock masters */ - /* - * On TNG/BYT/CHT, the SSP wrapper generates the fs even in master mode, - * the master/slave choice depends on the clock type - */ - sscr1 |= SSCR1_SFRMDIR; - - switch (config->format & SOF_DAI_FMT_MASTER_MASK) { - case SOF_DAI_FMT_CBM_CFM: - sscr0 |= SSCR0_ECS; /* external clock used */ - sscr1 |= SSCR1_SCLKDIR; - /* - * FIXME: does SSRC1.SCFR need to be set - * when codec is master ? - */ - sscr2 |= SSCR2_SLV_EXT_CLK_RUN_EN; - break; - case SOF_DAI_FMT_CBS_CFS: -#ifdef ENABLE_SSRCR1_SCFR /* FIXME: is this needed ? */ - sscr1 |= SSCR1_SCFR; -#endif - sscr3 |= SSCR3_FRM_MST_EN; - cfs = true; - cbs = true; - break; - case SOF_DAI_FMT_CBM_CFS: - sscr0 |= SSCR0_ECS; /* external clock used */ - sscr1 |= SSCR1_SCLKDIR; - /* - * FIXME: does SSRC1.SCFR need to be set - * when codec is master ? - */ - sscr2 |= SSCR2_SLV_EXT_CLK_RUN_EN; - sscr3 |= SSCR3_FRM_MST_EN; - cfs = true; - /* FIXME: this mode has not been tested */ - break; - case SOF_DAI_FMT_CBS_CFM: -#ifdef ENABLE_SSRCR1_SCFR /* FIXME: is this needed ? */ - sscr1 |= SSCR1_SCFR; -#endif - /* FIXME: this mode has not been tested */ - cbs = true; - break; - default: - dai_err(dai, "ssp_set_config() error: format & MASTER_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - /* clock signal polarity */ - switch (config->format & SOF_DAI_FMT_INV_MASK) { - case SOF_DAI_FMT_NB_NF: - break; - case SOF_DAI_FMT_NB_IF: - inverted_frame = true; /* handled later with format */ - break; - case SOF_DAI_FMT_IB_IF: - sspsp |= SSPSP_SCMODE(2); - inverted_frame = true; /* handled later with format */ - break; - case SOF_DAI_FMT_IB_NF: - sspsp |= SSPSP_SCMODE(2); - break; - default: - dai_err(dai, "ssp_set_config() error: format & INV_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - /* Additional hardware settings */ - - /* Receiver Time-out Interrupt Disabled/Enabled */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_TINTE) ? - SSCR1_TINTE : 0; - - /* Peripheral Trailing Byte Interrupts Disable/Enable */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PINTE) ? - SSCR1_PINTE : 0; - - /* Enable/disable internal loopback. Output of transmit serial - * shifter connected to input of receive serial shifter, internally. - */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_LBM) ? - SSCR1_LBM : 0; - - /* Checks for quirks that were requested but are not supported. */ - if (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_SMTATF) { - dai_err(dai, "SMTATF is not supported"); - ret = -EINVAL; - goto out; - } - - if (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_MMRATF) { - dai_err(dai, "MMRATF is not supported"); - ret = -EINVAL; - goto out; - } - - if (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD) { - dai_err(dai, "PSPSTWFDFD is not supported"); - ret = -EINVAL; - goto out; - } - - if (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD) { - dai_err(dai, "PSPSRWFDFD is not supported"); - ret = -EINVAL; - goto out; - } - - /* BCLK is generated from MCLK - must be divisable */ - if (config->ssp.mclk_rate % config->ssp.bclk_rate) { - dai_err(dai, "ssp_set_config() error: MCLK is not divisable"); - ret = -EINVAL; - goto out; - } - - /* divisor must be within SCR range */ - mdiv = (config->ssp.mclk_rate / config->ssp.bclk_rate) - 1; - if (mdiv > (SSCR0_SCR_MASK >> 8)) { - dai_err(dai, "ssp_set_config() error: divisor is not within SCR range"); - ret = -EINVAL; - goto out; - } - - /* set the SCR divisor */ - sscr0 |= SSCR0_SCR(mdiv); - - /* calc frame width based on BCLK and rate - must be divisable */ - if (config->ssp.bclk_rate % config->ssp.fsync_rate) { - dai_err(dai, "ssp_set_config() error: BLCK is not divisable"); - ret = -EINVAL; - goto out; - } - - /* must be enouch BCLKs for data */ - bdiv = config->ssp.bclk_rate / config->ssp.fsync_rate; - if (bdiv < config->ssp.tdm_slot_width * - config->ssp.tdm_slots) { - dai_err(dai, "ssp_set_config() error: not enough BCLKs"); - ret = -EINVAL; - goto out; - } - - /* tdm_slot_width must be <= 38 for SSP */ - if (config->ssp.tdm_slot_width > 38) { - dai_err(dai, "ssp_set_config() error: tdm_slot_width > 38"); - ret = -EINVAL; - goto out; - } - - /* format */ - switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { - case SOF_DAI_FMT_I2S: - - start_delay = 1; - - /* enable I2S mode */ - sscr3 |= SSCR3_I2S_MODE_EN | SSCR3_I2S_TX_EN | SSCR3_I2S_RX_EN; - - /* set asserted frame length */ - frame_len = config->ssp.tdm_slot_width; - - /* handle frame polarity, I2S default is falling/active low */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - sscr3 |= SSCR3_I2S_FRM_POL(!inverted_frame); - - if (cbs) { - /* - * keep RX functioning on a TX underflow - * (I2S/LEFT_J master only) - */ - sscr3 |= SSCR3_MST_CLK_EN; - - /* - * total frame period (both asserted and - * deasserted time of frame - */ - sscr4 |= SSCR4_TOT_FRM_PRD(frame_len << 1); - } - - break; - - case SOF_DAI_FMT_LEFT_J: - - start_delay = 0; - - /* apparently we need the same initialization as for I2S */ - sscr3 |= SSCR3_I2S_MODE_EN | SSCR3_I2S_TX_EN | SSCR3_I2S_RX_EN; - - /* set asserted frame length */ - frame_len = config->ssp.tdm_slot_width; - - /* LEFT_J default is rising/active high, opposite of I2S */ - sspsp |= SSPSP_SFRMP(inverted_frame); - sscr3 |= SSCR3_I2S_FRM_POL(inverted_frame); - - if (cbs) { - /* - * keep RX functioning on a TX underflow - * (I2S/LEFT_J master only) - */ - sscr3 |= SSCR3_MST_CLK_EN; - - /* - * total frame period (both asserted and - * deasserted time of frame - */ - sscr4 |= SSCR4_TOT_FRM_PRD(frame_len << 1); - } - - break; - case SOF_DAI_FMT_DSP_A: - - start_delay = 1; - - sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->ssp.tdm_slots); - - /* set asserted frame length */ - frame_len = 1; - - /* handle frame polarity, DSP_A default is rising/active high */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - if (cfs) { - /* set sscr frame polarity in DSP/master mode only */ - sscr5 |= SSCR5_FRM_POLARITY(inverted_frame); - } - - /* - * total frame period (both asserted and - * deasserted time of frame) - */ - if (cbs) - sscr4 |= SSCR4_TOT_FRM_PRD(config->ssp.tdm_slots * - config->ssp.tdm_slot_width); - - active_tx_slots = popcount(config->ssp.tx_slots); - active_rx_slots = popcount(config->ssp.rx_slots); - - break; - case SOF_DAI_FMT_DSP_B: - - start_delay = 0; - - sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->ssp.tdm_slots); - - /* set asserted frame length */ - frame_len = 1; - - /* handle frame polarity, DSP_A default is rising/active high */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - if (cfs) { - /* set sscr frame polarity in DSP/master mode only */ - sscr5 |= SSCR5_FRM_POLARITY(inverted_frame); - } - - /* - * total frame period (both asserted and - * deasserted time of frame - */ - if (cbs) - sscr4 |= SSCR4_TOT_FRM_PRD(config->ssp.tdm_slots * - config->ssp.tdm_slot_width); - - active_tx_slots = popcount(config->ssp.tx_slots); - active_rx_slots = popcount(config->ssp.rx_slots); - - break; - default: - dai_err(dai, "ssp_set_config() error: format & FORMAT_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - sspsp |= SSPSP_DMYSTRT(start_delay); - sspsp |= SSPSP_SFRMWDTH(frame_len); - sscr5 |= SSCR5_FRM_ASRT_CLOCKS(frame_len); - - data_size = config->ssp.sample_valid_bits; - - if (data_size > 16) - sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16)); - else - sscr0 |= SSCR0_DSIZE(data_size); - - /* FIXME: - * watermarks - (RFT + 1) should equal DMA SRC_MSIZE - */ - sfifott = (SFIFOTT_TX(2 * active_tx_slots) | - SFIFOTT_RX(2 * active_rx_slots)); - - ssp_write(dai, SSCR0, sscr0); - ssp_write(dai, SSCR1, sscr1); - ssp_write(dai, SSCR2, sscr2); - ssp_write(dai, SSCR3, sscr3); - ssp_write(dai, SSCR4, sscr4); - ssp_write(dai, SSCR5, sscr5); - ssp_write(dai, SSPSP, sspsp); - ssp_write(dai, SFIFOTT, sfifott); - ssp_write(dai, SSTSA, SSTSA_SSTSA(config->ssp.tx_slots)); - ssp_write(dai, SSRSA, SSRSA_SSRSA(config->ssp.rx_slots)); - - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_PREPARE; - ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE; - - dai_info(dai, "ssp_set_config(), done"); - -out: - spin_unlock(&dai->lock); - - return ret; -} - -/* get SSP hw params */ -static int ssp_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - params->rate = ssp->params.fsync_rate; - params->buffer_fmt = 0; - - if (dir == SOF_IPC_STREAM_PLAYBACK) - params->channels = popcount(ssp->params.tx_slots); - else - params->channels = popcount(ssp->params.rx_slots); - - switch (ssp->params.sample_valid_bits) { - case 16: - params->frame_fmt = SOF_IPC_FRAME_S16_LE; - break; - case 24: - params->frame_fmt = SOF_IPC_FRAME_S24_4LE; - break; - case 32: - params->frame_fmt = SOF_IPC_FRAME_S32_LE; - break; - default: - dai_err(dai, "ssp_get_hw_params(): not supported format"); - return -EINVAL; - } - - return 0; -} - -/* start the SSP for either playback or capture */ -static void ssp_start(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - spin_lock(&dai->lock); - - /* enable port */ - ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); - ssp->state[direction] = COMP_STATE_ACTIVE; - - dai_info(dai, "ssp_start()"); - - /* enable DMA */ - if (direction == DAI_DIR_PLAYBACK) - ssp_update_bits(dai, SSCR1, SSCR1_TSRE, SSCR1_TSRE); - else - ssp_update_bits(dai, SSCR1, SSCR1_RSRE, SSCR1_RSRE); - - spin_unlock(&dai->lock); -} - -/* stop the SSP for either playback or capture */ -static void ssp_stop(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - spin_lock(&dai->lock); - - /* stop Rx if neeed */ - if (direction == DAI_DIR_CAPTURE && - ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0); - ssp_empty_rx_fifo(dai); - ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE; - dai_info(dai, "ssp_stop(), RX stop"); - } - - /* stop Tx if needed */ - if (direction == DAI_DIR_PLAYBACK && - ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0); - ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE; - dai_info(dai, "ssp_stop(), TX stop"); - } - - /* disable SSP port if no users */ - if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE && - ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0); - dai_info(dai, "ssp_stop(), SSP port disabled"); - } - - spin_unlock(&dai->lock); -} - -static void ssp_pause(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - if (direction == SOF_IPC_STREAM_CAPTURE) - dai_info(dai, "ssp_pause(), RX"); - else - dai_info(dai, "ssp_pause(), TX"); - - ssp->state[direction] = COMP_STATE_PAUSED; -} - -static int ssp_trigger(struct dai *dai, int cmd, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - dai_info(dai, "ssp_trigger()"); - - switch (cmd) { - case COMP_TRIGGER_START: - if (ssp->state[direction] == COMP_STATE_PREPARE || - ssp->state[direction] == COMP_STATE_PAUSED) - ssp_start(dai, direction); - break; - case COMP_TRIGGER_RELEASE: - if (ssp->state[direction] == COMP_STATE_PAUSED || - ssp->state[direction] == COMP_STATE_PREPARE) - ssp_start(dai, direction); - break; - case COMP_TRIGGER_STOP: - ssp_stop(dai, direction); - break; - case COMP_TRIGGER_PAUSE: - ssp_pause(dai, direction); - break; - case COMP_TRIGGER_RESUME: - ssp_context_restore(dai); - break; - case COMP_TRIGGER_SUSPEND: - ssp_context_store(dai); - break; - default: - break; - } - - return 0; -} - -static int ssp_probe(struct dai *dai) -{ - struct ssp_pdata *ssp; - - /* allocate private data */ - ssp = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, SOF_MEM_CAPS_RAM, - sizeof(*ssp)); - dai_set_drvdata(dai, ssp); - - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY; - ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY; - - ssp_empty_rx_fifo(dai); - return 0; -} - -static int ssp_get_handshake(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[direction].handshake; -} - -static int ssp_get_fifo(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[direction].offset; -} - -const struct dai_driver ssp_driver = { - .type = SOF_DAI_INTEL_SSP, - .dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, - .dma_dev = DMA_DEV_SSP, - .ops = { - .trigger = ssp_trigger, - .set_config = ssp_set_config, - .pm_context_store = ssp_context_store, - .pm_context_restore = ssp_context_restore, - .get_hw_params = ssp_get_hw_params, - .get_handshake = ssp_get_handshake, - .get_fifo = ssp_get_fifo, - .probe = ssp_probe, - }, -}; diff --git a/src/drivers/intel/baytrail/timer.c b/src/drivers/intel/baytrail/timer.c deleted file mode 100644 index f759da48f938..000000000000 --- a/src/drivers/intel/baytrail/timer.c +++ /dev/null @@ -1,240 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -/* - * Baytrail external timer control. - */ - -#include <sof/audio/component_ext.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/platform.h> -#include <ipc/stream.h> -#include <errno.h> -#include <stdint.h> - -static void platform_timer_64_handler(void *arg) -{ - struct timer *timer = arg; - uint32_t timeout; - - /* get timeout value - will tell us timeout reason */ - timeout = shim_read(SHIM_EXT_TIMER_CNTLL); - - /* we don't use the timer clear bit as we only need to clear the ISR */ - shim_write(SHIM_PISR, SHIM_PISR_EXT_TIMER); - - /* is this a 32 bit rollover ? */ - if (timeout == 1) { - /* roll over the timer */ - timer->hitime++; - } else { - /* no roll over, run the handler */ - timer->handler(timer->data); - } - - /* get next timeout value */ - if (timer->hitimeout == timer->hitime) { - /* timeout is in this 32 bit period */ - timeout = timer->lowtimeout; - } else { - /* timeout is in another 32 bit period */ - timeout = 1; - } - - /* set new value and run */ - shim_write(SHIM_EXT_TIMER_CNTLH, SHIM_EXT_TIMER_RUN); - shim_write(SHIM_EXT_TIMER_CNTLL, timeout); - - platform_shared_commit(timer, sizeof(*timer)); -} - -void platform_timer_start(struct timer *timer) -{ - /* run timer */ - shim_write(SHIM_EXT_TIMER_CNTLH, SHIM_EXT_TIMER_RUN); - shim_write(SHIM_EXT_TIMER_CNTLL, 1); -} - -/* this seems to stop rebooting with RTD3 ???? */ -void platform_timer_stop(struct timer *timer) -{ - /* run timer */ - shim_write(SHIM_EXT_TIMER_CNTLL, 0); - shim_write(SHIM_EXT_TIMER_CNTLH, SHIM_EXT_TIMER_CLEAR); -} - -int64_t platform_timer_set(struct timer *timer, uint64_t ticks) -{ - uint32_t time = 1; - uint32_t hitimeout = ticks >> 32; - uint32_t flags; - - /* a tick value of 0 will not generate an IRQ */ - /* value of 1 represents rollover */ - if ((ticks & 0xffffffff) < 0x2) - ticks += 2; - - flags = arch_interrupt_global_disable(); - - /* same hi 64 bit context as ticks ? */ - if (hitimeout < timer->hitime) { - /* can't be in the past */ - arch_interrupt_global_enable(flags); - return -EINVAL; - } - - /* set for checking at next timeout */ - time = ticks; - timer->hitimeout = hitimeout; - timer->lowtimeout = ticks; - - /* set new value and run */ - shim_write(SHIM_EXT_TIMER_CNTLH, SHIM_EXT_TIMER_RUN); - shim_write(SHIM_EXT_TIMER_CNTLL, time); - - arch_interrupt_global_enable(flags); - - return ticks; -} - -void platform_timer_clear(struct timer *timer) -{ - /* we don't use the timer clear bit as we only need to clear the ISR */ - shim_write(SHIM_PISR, SHIM_PISR_EXT_TIMER); -} - -uint64_t platform_timer_get(struct timer *timer) -{ - uint64_t time; - uint32_t flags; - uint32_t low; - uint32_t high; - - flags = arch_interrupt_global_disable(); - - /* read low 32 bits */ - low = shim_read(SHIM_EXT_TIMER_STAT); - - /* check and see whether 32bit IRQ is pending for timer */ - if (arch_interrupt_get_status() & IRQ_MASK_EXT_TIMER && - shim_read(SHIM_EXT_TIMER_CNTLL) == 1) { - /* yes, overflow has occurred but handler has not run */ - high = timer->hitime + 1; - } else { - /* no overflow */ - high = timer->hitime; - } - - time = ((uint64_t)high << 32) | low; - - arch_interrupt_global_enable(flags); - - platform_shared_commit(timer, sizeof(*timer)); - - return time; -} - -/* get timestamp for host stream DMA position */ -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn) -{ - int err; - - /* get host position */ - err = comp_position(host, posn); - if (err == 0) - posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; -} - -/* get timestamp for DAI stream DMA position */ -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn) -{ - int err; - - /* get DAI position */ - err = comp_position(dai, posn); - if (err == 0) - posn->flags |= SOF_TIME_DAI_VALID; - - /* get SSP wallclock - DAI sets this to stream start value */ - posn->wallclock = platform_timer_get(timer_get()) - posn->wallclock; - posn->wallclock_hz = clock_get_freq(PLATFORM_DEFAULT_CLOCK); - posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; -} - -/* get current wallclock for component */ -void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) -{ - /* only 1 wallclock on BYT */ - *wallclock = platform_timer_get(timer_get()); -} - -static int platform_timer_register(struct timer *timer, - void (*handler)(void *arg), void *arg) -{ - uint32_t flags; - int ret; - - flags = arch_interrupt_global_disable(); - timer->handler = handler; - timer->data = arg; - timer->hitime = 0; - timer->hitimeout = 0; - ret = arch_interrupt_register(timer->irq, - platform_timer_64_handler, timer); - arch_interrupt_global_enable(flags); - - return ret; -} - -int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) -{ - int ret; - - switch (timer->id) { - case TIMER0: - case TIMER1: - case TIMER2: - ret = arch_timer_register(timer, handler, arg); - break; - case TIMER3: - ret = platform_timer_register(timer, handler, arg); - break; - default: - ret = -EINVAL; - break; - } - - platform_shared_commit(timer, sizeof(*timer)); - - return ret; -} - -void timer_unregister(struct timer *timer, void *arg) -{ - interrupt_unregister(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); -} - -void timer_enable(struct timer *timer, void *arg, int core) -{ - interrupt_enable(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); -} - -void timer_disable(struct timer *timer, void *arg, int core) -{ - interrupt_disable(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); -} diff --git a/src/drivers/intel/cavs/CMakeLists.txt b/src/drivers/intel/cavs/CMakeLists.txt deleted file mode 100644 index 6ee55286fa06..000000000000 --- a/src/drivers/intel/cavs/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof - hda-dma.c - hda.c - interrupt.c - timer.c -) - -if(CONFIG_INTEL_IOMUX) - add_local_sources(sof sue-iomux.c) -endif() - -if(CONFIG_SUECREEK) - add_local_sources(sof sue-ipc.c) -else() - add_local_sources(sof ipc.c) -endif() - -if(CONFIG_CAVS_DMIC) - add_local_sources(sof dmic.c) -endif() - -if(CONFIG_CAVS_SSP) - add_local_sources(sof ssp.c) -endif() - -if(CONFIG_CAVS_MN) - add_local_sources(sof mn.c) -endif() - -if(CONFIG_CAVS_ALH) - add_local_sources(sof alh.c) -endif() - -if(CONFIG_SMP) - add_local_sources(sof idc.c) -endif() diff --git a/src/drivers/intel/cavs/Kconfig b/src/drivers/intel/cavs/Kconfig deleted file mode 100644 index 63a360d9c6fd..000000000000 --- a/src/drivers/intel/cavs/Kconfig +++ /dev/null @@ -1,144 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -config CAVS_DMIC - bool "Intel cAVS DMIC driver" - depends on CAVS - default n - help - Select this to enable Intel cAVS DMIC driver. The DMIC driver provides - as DAI the SoC direct attach digital microphones interface. - -if CAVS_DMIC - -choice - prompt "FIR decimation coefficients set" - default CAVS_DMIC_FIR_FULL - -config CAVS_DMIC_FIR_FULL - bool "Full set" - select CAVS_DMIC_FIR_DECIMATE_BY_2 - select CAVS_DMIC_FIR_DECIMATE_BY_3 - select CAVS_DMIC_FIR_DECIMATE_BY_4 - select CAVS_DMIC_FIR_DECIMATE_BY_5 - select CAVS_DMIC_FIR_DECIMATE_BY_6 - select CAVS_DMIC_FIR_DECIMATE_BY_8 - select CAVS_DMIC_FIR_DECIMATE_BY_12 - help - This option adds to previous all currently defined FIR - coefficients sets to support sample rates 8 - 96 kHz with - several microphone clock rates. The tables increase the size - of the driver so this option should not be used in minimal - systems. - -config CAVS_DMIC_FIR_LOW_MEMORY - bool "Small set" - select CAVS_DMIC_FIR_DECIMATE_BY_2 - select CAVS_DMIC_FIR_DECIMATE_BY_6 - help - This option is used to minimize driver footprint but - preserve support for 48 kHz and 16 kHz sample rates - at typical 2.4 MHz microphone clock rate. The option - enables decimation factors 2 and 6. - -config CAVS_DMIC_FIR_CUSTOM - bool "Custom set" - help - This option is used to select each supported decimation - factor. - -endchoice - -menu "Decimation factors" - visible if CAVS_DMIC_FIR_CUSTOM - -config CAVS_DMIC_FIR_DECIMATE_BY_2 - bool "FIR decimate by 2" - default n - help - This includes FIR coefficients to decimate by 2 into the build. It - is commonly used for 48 kHz capture with 2.4 MHz microphone clock. - Decimate by 2 in FIR gives good bandwidth vs. Nyquist and narrow - transition region due to lower FIR order need compared to higher - decimation factors. - -config CAVS_DMIC_FIR_DECIMATE_BY_3 - bool "FIR decimate by 3" - default n - help - This includes FIR coefficients to decimate by 3 into the build. - Decimation by 3 in FIR is useful with microphone clock and sample - rate combinations where a 3 is the lowest factor of the oversampling - ratio. Having this low prime decimation factor for FIR enabled is - useful when decimation by 2 is not possible. - -config CAVS_DMIC_FIR_DECIMATE_BY_4 - bool "FIR decimate by 4" - default n - help - This includes FIR coefficients to decimate by 4 into the build. - Decimation by 4 in FIR is useful in some cases with high microphone - clock rates due to max. decimation factor limit of CIC. In such - cases decimation by 2 may not be usable. - -config CAVS_DMIC_FIR_DECIMATE_BY_5 - bool "FIR decimate by 5" - default n - help - This includes FIR coefficients to decimate by 5 into the build. - Decimation by 5 in FIR is useful with microphone clock and sample - rate combinations where a 5 is the lowest factor of the oversampling - ratio. - -config CAVS_DMIC_FIR_DECIMATE_BY_6 - bool "FIR decimate by 6" - default n - help - This includes FIR coefficients to decimate by 6 into the build. It - is commonly used for 16 kHz capture from secondary FIFO while - primary FIFO is configured for 48 kHz rate. - -config CAVS_DMIC_FIR_DECIMATE_BY_8 - bool "FIR decimate by 8" - default n - help - This includes FIR coefficients to decimate by 8 into the build. - The high FIR decimation factors are needed for high microphone clock - rates due to max. decimation factor limitation of CIC. Also dual - FIFO configurations may need for one FIR decimation such high - decimation factor. - -config CAVS_DMIC_FIR_DECIMATE_BY_12 - bool "FIR decimate by 12" - default n - help - This includes FIR coefficients to decimate by 12 into the build. It - is used for 16 kHz capture for secondary FIFO while the primary - FIFO is configured for 96 kHz. - -endmenu # "Decimation factors" - -endif # CAVS_DMIC - -config CAVS_MN - bool - depends on CAVS - default n - help - Select this to enable driver for Intel M/N divider. - -config CAVS_SSP - bool "Intel cAVS SSP driver" - depends on CAVS - select CAVS_MN - default n - help - Select this to enable Intel cAVS Synchronous Serial Port (SSP) driver. - -config CAVS_ALH - bool "Intel cAVS ALH driver" - depends on CAVS - default n - help - Select this to enable Intel cAVS ALH driver. - The ALH is an intermediary device, which acts as a hub and provides an - abstracted support for numerous sound interfaces (e.g. SoundWire). diff --git a/src/drivers/intel/cavs/alh.c b/src/drivers/intel/cavs/alh.c deleted file mode 100644 index 9fa2ad3f5467..000000000000 --- a/src/drivers/intel/cavs/alh.c +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/drivers/alh.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/trace/trace.h> -#include <sof/common.h> -#include <ipc/dai.h> -#include <ipc/stream.h> -#include <user/trace.h> -#include <stdint.h> - -/* a8e4218c-e863-4c93-84e7-5c27d2504501 */ -DECLARE_SOF_UUID("alh-dai", alh_uuid, 0xa8e4218c, 0xe863, 0x4c93, - 0x84, 0xe7, 0x5c, 0x27, 0xd2, 0x50, 0x45, 0x01); - -static int alh_trigger(struct dai *dai, int cmd, int direction) -{ - dai_info(dai, "alh_trigger() cmd %d", cmd); - - return 0; -} - -static int alh_set_config(struct dai *dai, struct sof_ipc_dai_config *config) -{ - dai_info(dai, "alh_set_config() config->format = 0x%4x", - config->format); - - return 0; -} - -/* get ALH hw params */ -static int alh_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) -{ - /* 0 means variable */ - params->rate = 0; - params->channels = 0; - params->buffer_fmt = 0; - params->frame_fmt = 0; - - return 0; -} - -static int alh_context_store(struct dai *dai) -{ - dai_info(dai, "alh_context_store()"); - - return 0; -} - -static int alh_context_restore(struct dai *dai) -{ - dai_info(dai, "alh_context_restore()"); - - return 0; -} - -static int alh_probe(struct dai *dai) -{ - dai_info(dai, "alh_probe()"); - - return 0; -} - -static int alh_remove(struct dai *dai) -{ - dai_info(dai, "alh_remove()"); - - return 0; -} - -static int alh_get_handshake(struct dai *dai, int direction, int stream_id) -{ - if (stream_id >= ARRAY_SIZE(alh_handshake_map)) { - dai_err(dai, "alh_get_handshake() error: " - "stream_id %d out of range", stream_id); - - return -1; - } - - return alh_handshake_map[stream_id]; -} - -static int alh_get_fifo(struct dai *dai, int direction, int stream_id) -{ - uint32_t offset = direction == SOF_IPC_STREAM_PLAYBACK ? - ALH_TXDA_OFFSET : ALH_RXDA_OFFSET; - - return ALH_BASE + offset + ALH_STREAM_OFFSET * stream_id; -} - -const struct dai_driver alh_driver = { - .type = SOF_DAI_INTEL_ALH, - .uid = SOF_UUID(alh_uuid), - .dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, - .dma_dev = DMA_DEV_ALH, - .ops = { - .trigger = alh_trigger, - .set_config = alh_set_config, - .pm_context_store = alh_context_store, - .pm_context_restore = alh_context_restore, - .get_hw_params = alh_get_hw_params, - .get_handshake = alh_get_handshake, - .get_fifo = alh_get_fifo, - .probe = alh_probe, - .remove = alh_remove, - }, -}; diff --git a/src/drivers/intel/cavs/dmic.c b/src/drivers/intel/cavs/dmic.c deleted file mode 100644 index 9f0172aaafaf..000000000000 --- a/src/drivers/intel/cavs/dmic.c +++ /dev/null @@ -1,1746 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -#include <sof/drivers/dmic.h> - -#if defined DMIC_HW_VERSION - -#include <sof/audio/coefficients/pdm_decim/pdm_decim_fir.h> -#include <sof/audio/coefficients/pdm_decim/pdm_decim_table.h> -#include <sof/audio/component.h> -#include <sof/audio/format.h> -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timestamp.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cpu.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/uuid.h> -#include <sof/math/decibels.h> -#include <sof/math/numbers.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <sof/string.h> -#include <ipc/dai.h> -#include <ipc/dai-intel.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -/* aafc26fe-3b8d-498d-8bd6-248fc72efa31 */ -DECLARE_SOF_UUID("dmic-dai", dmic_uuid, 0xaafc26fe, 0x3b8d, 0x498d, - 0x8b, 0xd6, 0x24, 0x8f, 0xc7, 0x2e, 0xfa, 0x31); - -/* 59c87728-d8f9-42f6-b89d-5870a87b0e1e */ -DECLARE_SOF_UUID("dmic-work", dmic_work_task_uuid, 0x59c87728, 0xd8f9, 0x42f6, - 0xb8, 0x9d, 0x58, 0x70, 0xa8, 0x7b, 0x0e, 0x1e); - -#define DMIC_MAX_MODES 50 - -/* HW FIR pipeline needs 5 additional cycles per channel for internal - * operations. This is used in MAX filter length check. - */ -#define DMIC_FIR_PIPELINE_OVERHEAD 5 - -struct decim_modes { - int16_t clkdiv[DMIC_MAX_MODES]; - int16_t mcic[DMIC_MAX_MODES]; - int16_t mfir[DMIC_MAX_MODES]; - int num_of_modes; -}; - -struct matched_modes { - int16_t clkdiv[DMIC_MAX_MODES]; - int16_t mcic[DMIC_MAX_MODES]; - int16_t mfir_a[DMIC_MAX_MODES]; - int16_t mfir_b[DMIC_MAX_MODES]; - int num_of_modes; -}; - -struct dmic_configuration { - struct pdm_decim *fir_a; - struct pdm_decim *fir_b; - int clkdiv; - int mcic; - int mfir_a; - int mfir_b; - int cic_shift; - int fir_a_shift; - int fir_b_shift; - int fir_a_length; - int fir_b_length; - int32_t fir_a_scale; - int32_t fir_b_scale; -}; - -struct pdm_controllers_configuration { - uint32_t cic_control; - uint32_t cic_config; - uint32_t mic_control; - uint32_t fir_control_a; - uint32_t fir_config_a; - uint32_t dc_offset_left_a; - uint32_t dc_offset_right_a; - uint32_t out_gain_left_a; - uint32_t out_gain_right_a; - uint32_t fir_control_b; - uint32_t fir_config_b; - uint32_t dc_offset_left_b; - uint32_t dc_offset_right_b; - uint32_t out_gain_left_b; - uint32_t out_gain_right_b; -}; - -/* Configuration ABI version, increment if not compatible with previous - * version. - */ -#define DMIC_IPC_VERSION 1 - -/* Minimum OSR is always applied for 48 kHz and less sample rates */ -#define DMIC_MIN_OSR 50 - -/* These are used as guideline for configuring > 48 kHz sample rates. The - * minimum OSR can be relaxed down to 40 (use 3.84 MHz clock for 96 kHz). - */ -#define DMIC_HIGH_RATE_MIN_FS 64000 -#define DMIC_HIGH_RATE_OSR_MIN 40 - -/* Used for scaling FIR coefficients for HW */ -#define DMIC_HW_FIR_COEF_MAX ((1 << (DMIC_HW_BITS_FIR_COEF - 1)) - 1) -#define DMIC_HW_FIR_COEF_Q (DMIC_HW_BITS_FIR_COEF - 1) - -/* Internal precision in gains computation, e.g. Q4.28 in int32_t */ -#define DMIC_FIR_SCALE_Q 28 - -/* Used in unmute ramp values calculation */ -#define DMIC_HW_FIR_GAIN_MAX ((1 << (DMIC_HW_BITS_FIR_GAIN - 1)) - 1) - -/* Hardwired log ramp parameters. The first value is the initial gain in - * decibels. The second value is the default ramp time. - */ -#define LOGRAMP_START_DB Q_CONVERT_FLOAT(-90, DB2LIN_FIXED_INPUT_QY) -#define LOGRAMP_TIME_MS 400 /* Default ramp time in milliseconds */ - -/* Limits for ramp time from topology */ -#define LOGRAMP_TIME_MIN_MS 10 /* Min. 10 ms */ -#define LOGRAMP_TIME_MAX_MS 1000 /* Max. 1s */ - -/* Simplify log ramp step calculation equation with this constant term */ -#define LOGRAMP_CONST_TERM ((int32_t) \ - ((int64_t)-LOGRAMP_START_DB * DMIC_UNMUTE_RAMP_US / 1000)) - -/* Fractional shift for gain update. Gain format is Q2.30. */ -#define Q_SHIFT_GAIN_X_GAIN_COEF \ - (Q_SHIFT_BITS_32(30, DB2LIN_FIXED_OUTPUT_QY, 30)) - -/* Base addresses (in PDM scope) of 2ch PDM controllers and coefficient RAM. */ -static const uint32_t base[4] = {PDM0, PDM1, PDM2, PDM3}; -static const uint32_t coef_base_a[4] = {PDM0_COEFFICIENT_A, PDM1_COEFFICIENT_A, - PDM2_COEFFICIENT_A, PDM3_COEFFICIENT_A}; -static const uint32_t coef_base_b[4] = {PDM0_COEFFICIENT_B, PDM1_COEFFICIENT_B, - PDM2_COEFFICIENT_B, PDM3_COEFFICIENT_B}; - -/* Global configuration request for DMIC */ -static struct sof_ipc_dai_dmic_params *dmic_prm[DMIC_HW_FIFOS]; -static int dmic_active_fifos; - -/* this ramps volume changes over time */ -static enum task_state dmic_work(void *data) -{ - struct dai *dai = (struct dai *)data; - struct dmic_pdata *dmic = dai_get_drvdata(dai); - int32_t gval; - uint32_t val; - int i; - int ret; - - dai_dbg(dai, "dmic_work()"); - - ret = spin_try_lock(&dai->lock); - if (!ret) { - platform_shared_commit(dai, sizeof(*dai)); - dai_dbg(dai, "dmic_work(): spin_try_lock(dai->lock, ret) failed: RESCHEDULE"); - return SOF_TASK_STATE_RESCHEDULE; - } - - /* Increment gain with logarithmic step. - * Gain is Q2.30 and gain modifier is Q12.20. - */ - dmic->startcount++; - dmic->gain = q_multsr_sat_32x32(dmic->gain, dmic->gain_coef, - Q_SHIFT_GAIN_X_GAIN_COEF); - - /* Gain is stored as Q2.30, while HW register is Q1.19 so shift - * the value right by 11. - */ - gval = dmic->gain >> 11; - - /* Note that DMIC gain value zero has a special purpose. Value zero - * sets gain bypass mode in HW. Zero value will be applied after ramp - * is complete. It is because exact 1.0 gain is not possible with Q1.19. - */ - if (gval > DMIC_HW_FIR_GAIN_MAX) - gval = 0; - - /* Write gain to registers */ - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - if (!dmic->enable[i]) - continue; - - if (dmic->startcount == DMIC_UNMUTE_CIC) - dai_update_bits(dai, base[i] + CIC_CONTROL, - CIC_CONTROL_MIC_MUTE_BIT, 0); - - if (dmic->startcount == DMIC_UNMUTE_FIR) { - switch (dai->index) { - case 0: - dai_update_bits(dai, base[i] + FIR_CONTROL_A, - FIR_CONTROL_A_MUTE_BIT, 0); - break; - case 1: - dai_update_bits(dai, base[i] + FIR_CONTROL_B, - FIR_CONTROL_B_MUTE_BIT, 0); - break; - } - } - switch (dai->index) { - case 0: - val = OUT_GAIN_LEFT_A_GAIN(gval); - dai_write(dai, base[i] + OUT_GAIN_LEFT_A, val); - dai_write(dai, base[i] + OUT_GAIN_RIGHT_A, val); - break; - case 1: - val = OUT_GAIN_LEFT_B_GAIN(gval); - dai_write(dai, base[i] + OUT_GAIN_LEFT_B, val); - dai_write(dai, base[i] + OUT_GAIN_RIGHT_B, val); - break; - } - } - - platform_shared_commit(dai, sizeof(*dai)); - - spin_unlock(&dai->lock); - - return gval ? SOF_TASK_STATE_RESCHEDULE : SOF_TASK_STATE_COMPLETED; -} - -/* This function returns a raw list of potential microphone clock and decimation - * modes for achieving requested sample rates. The search is constrained by - * decimation HW capabililies and setup parameters. The parameters such as - * microphone clock min/max and duty cycle requirements need be checked from - * used microphone component datasheet. - */ -static void find_modes(struct dai *dai, - struct decim_modes *modes, uint32_t fs, int di) -{ - int clkdiv_min; - int clkdiv_max; - int clkdiv; - int c1; - int du_min; - int du_max; - int pdmclk; - int osr; - int mfir; - int mcic; - int ioclk_test; - int osr_min = DMIC_MIN_OSR; - int j; - int i = 0; - - /* Defaults, empty result */ - modes->num_of_modes = 0; - - /* The FIFO is not requested if sample rate is set to zero. Just - * return in such case with num_of_modes as zero. - */ - if (fs == 0) - return; - - /* Override DMIC_MIN_OSR for very high sample rates, use as minimum - * the nominal clock for the high rates. - */ - if (fs >= DMIC_HIGH_RATE_MIN_FS) - osr_min = DMIC_HIGH_RATE_OSR_MIN; - - /* Check for sane pdm clock, min 100 kHz, max ioclk/2 */ - if (dmic_prm[di]->pdmclk_max < DMIC_HW_PDM_CLK_MIN || - dmic_prm[di]->pdmclk_max > DMIC_HW_IOCLK / 2) { - dai_err(dai, "find_modes() error: pdm clock max not in range"); - return; - } - if (dmic_prm[di]->pdmclk_min < DMIC_HW_PDM_CLK_MIN || - dmic_prm[di]->pdmclk_min > dmic_prm[di]->pdmclk_max) { - dai_err(dai, "find_modes() error: pdm clock min not in range"); - return; - } - - /* Check for sane duty cycle */ - if (dmic_prm[di]->duty_min > dmic_prm[di]->duty_max) { - dai_err(dai, "find_modes() error: duty cycle min > max"); - return; - } - if (dmic_prm[di]->duty_min < DMIC_HW_DUTY_MIN || - dmic_prm[di]->duty_min > DMIC_HW_DUTY_MAX) { - dai_err(dai, "find_modes() error: pdm clock min not in range"); - return; - } - if (dmic_prm[di]->duty_max < DMIC_HW_DUTY_MIN || - dmic_prm[di]->duty_max > DMIC_HW_DUTY_MAX) { - dai_err(dai, "find_modes() error: pdm clock max not in range"); - return; - } - - /* Min and max clock dividers */ - clkdiv_min = ceil_divide(DMIC_HW_IOCLK, dmic_prm[di]->pdmclk_max); - clkdiv_min = MAX(clkdiv_min, DMIC_HW_CIC_DECIM_MIN); - clkdiv_max = DMIC_HW_IOCLK / dmic_prm[di]->pdmclk_min; - - /* Loop possible clock dividers and check based on resulting - * oversampling ratio that CIC and FIR decimation ratios are - * feasible. The ratios need to be integers. Also the mic clock - * duty cycle need to be within limits. - */ - for (clkdiv = clkdiv_min; clkdiv <= clkdiv_max; clkdiv++) { - /* Calculate duty cycle for this clock divider. Note that - * odd dividers cause non-50% duty cycle. - */ - c1 = clkdiv >> 1; - du_min = 100 * c1 / clkdiv; - du_max = 100 - du_min; - - /* Calculate PDM clock rate and oversampling ratio. */ - pdmclk = DMIC_HW_IOCLK / clkdiv; - osr = pdmclk / fs; - - /* Check that OSR constraints is met and clock duty cycle does - * not exceed microphone specification. If exceed proceed to - * next clkdiv. - */ - if (osr < osr_min || du_min < dmic_prm[di]->duty_min || - du_max > dmic_prm[di]->duty_max) - continue; - - /* Loop FIR decimation factors candidates. If the - * integer divided decimation factors and clock dividers - * as multiplied with sample rate match the IO clock - * rate the division was exact and such decimation mode - * is possible. Then check that CIC decimation constraints - * are met. The passed decimation modes are added to array. - */ - for (j = 0; fir_list[j]; j++) { - mfir = fir_list[j]->decim_factor; - - /* Skip if previous decimation factor was the same */ - if (j > 1 && fir_list[j - 1]->decim_factor == mfir) - continue; - - mcic = osr / mfir; - ioclk_test = fs * mfir * mcic * clkdiv; - - if (ioclk_test == DMIC_HW_IOCLK && - mcic >= DMIC_HW_CIC_DECIM_MIN && - mcic <= DMIC_HW_CIC_DECIM_MAX && - i < DMIC_MAX_MODES) { - modes->clkdiv[i] = clkdiv; - modes->mcic[i] = mcic; - modes->mfir[i] = mfir; - i++; - } - } - } - - modes->num_of_modes = i; -} - -/* The previous raw modes list contains sane configuration possibilities. When - * there is request for both FIFOs A and B operation this function returns - * list of compatible settings. - */ -static void match_modes(struct matched_modes *c, struct decim_modes *a, - struct decim_modes *b) -{ - int16_t idx[DMIC_MAX_MODES]; - int idx_length; - int i; - int n; - int m; - - /* Check if previous search got results. */ - c->num_of_modes = 0; - if (a->num_of_modes == 0 && b->num_of_modes == 0) { - /* Nothing to do */ - return; - } - - /* Ensure that num_of_modes is sane. */ - if (a->num_of_modes > DMIC_MAX_MODES || - b->num_of_modes > DMIC_MAX_MODES) - return; - - /* Check for request only for FIFO A or B. In such case pass list for - * A or B as such. - */ - if (b->num_of_modes == 0) { - c->num_of_modes = a->num_of_modes; - for (i = 0; i < a->num_of_modes; i++) { - c->clkdiv[i] = a->clkdiv[i]; - c->mcic[i] = a->mcic[i]; - c->mfir_a[i] = a->mfir[i]; - c->mfir_b[i] = 0; /* Mark FIR B as non-used */ - } - return; - } - - if (a->num_of_modes == 0) { - c->num_of_modes = b->num_of_modes; - for (i = 0; i < b->num_of_modes; i++) { - c->clkdiv[i] = b->clkdiv[i]; - c->mcic[i] = b->mcic[i]; - c->mfir_b[i] = b->mfir[i]; - c->mfir_a[i] = 0; /* Mark FIR A as non-used */ - } - return; - } - - /* Merge a list of compatible modes */ - i = 0; - for (n = 0; n < a->num_of_modes; n++) { - /* Find all indices of values a->clkdiv[n] in b->clkdiv[] */ - idx_length = find_equal_int16(idx, b->clkdiv, a->clkdiv[n], - b->num_of_modes, 0); - for (m = 0; m < idx_length; m++) { - if (b->mcic[idx[m]] == a->mcic[n]) { - c->clkdiv[i] = a->clkdiv[n]; - c->mcic[i] = a->mcic[n]; - c->mfir_a[i] = a->mfir[n]; - c->mfir_b[i] = b->mfir[idx[m]]; - i++; - } - } - c->num_of_modes = i; - } -} - -/* Finds a suitable FIR decimation filter from the included set */ -static struct pdm_decim *get_fir(struct dai *dai, - struct dmic_configuration *cfg, int mfir) -{ - int i; - int fs; - int cic_fs; - int fir_max_length; - struct pdm_decim *fir = NULL; - - if (mfir <= 0) - return fir; - - cic_fs = DMIC_HW_IOCLK / cfg->clkdiv / cfg->mcic; - fs = cic_fs / mfir; - /* FIR max. length depends on available cycles and coef RAM - * length. Exceeding this length sets HW overrun status and - * overwrite of other register. - */ - fir_max_length = MIN(DMIC_HW_FIR_LENGTH_MAX, - DMIC_HW_IOCLK / fs / 2 - - DMIC_FIR_PIPELINE_OVERHEAD); - - i = 0; - /* Loop until NULL */ - while (fir_list[i]) { - if (fir_list[i]->decim_factor == mfir) { - if (fir_list[i]->length <= fir_max_length) { - /* Store pointer, break from loop to avoid a - * Possible other mode with lower FIR length. - */ - fir = fir_list[i]; - break; - } - dai_info(dai, "get_fir(), Note length=%d exceeds max=%d", - fir_list[i]->length, fir_max_length); - } - i++; - } - - return fir; -} - -/* Calculate scale and shift to use for FIR coefficients. Scale is applied - * before write to HW coef RAM. Shift will be programmed to HW register. - */ -static int fir_coef_scale(int32_t *fir_scale, int *fir_shift, int add_shift, - const int32_t coef[], int coef_length, int32_t gain) -{ - int32_t amax; - int32_t new_amax; - int32_t fir_gain; - int shift; - - /* Multiply gain passed from CIC with output full scale. */ - fir_gain = Q_MULTSR_32X32((int64_t)gain, DMIC_HW_SENS_Q28, - DMIC_FIR_SCALE_Q, 28, DMIC_FIR_SCALE_Q); - - /* Find the largest FIR coefficient value. */ - amax = find_max_abs_int32((int32_t *)coef, coef_length); - - /* Scale max. tap value with FIR gain. */ - new_amax = Q_MULTSR_32X32((int64_t)amax, fir_gain, 31, - DMIC_FIR_SCALE_Q, DMIC_FIR_SCALE_Q); - if (new_amax <= 0) - return -EINVAL; - - /* Get left shifts count to normalize the fractional value as 32 bit. - * We need right shifts count for scaling so need to invert. The - * difference of Q31 vs. used Q format is added to get the correct - * normalization right shift value. - */ - shift = 31 - DMIC_FIR_SCALE_Q - norm_int32(new_amax); - - /* Add to shift for coef raw Q31 format shift and store to - * configuration. Ensure range (fail should not happen with OK - * coefficient set). - */ - *fir_shift = -shift + add_shift; - if (*fir_shift < DMIC_HW_FIR_SHIFT_MIN || - *fir_shift > DMIC_HW_FIR_SHIFT_MAX) - return -EINVAL; - - /* Compensate shift into FIR coef scaler and store as Q4.20. */ - if (shift < 0) - *fir_scale = (fir_gain << -shift); - else - *fir_scale = (fir_gain >> shift); - - return 0; -} - -/* This function selects with a simple criteria one mode to set up the - * decimator. For the settings chosen for FIFOs A and B output a lookup - * is done for FIR coefficients from the included coefficients tables. - * For some decimation factors there may be several length coefficient sets. - * It is due to possible restruction of decimation engine cycles per given - * sample rate. If the coefficients length is exceeded the lookup continues. - * Therefore the list of coefficient set must present the filters for a - * decimation factor in decreasing length order. - * - * Note: If there is no filter available an error is returned. The parameters - * should be reviewed for such case. If still a filter is missing it should be - * added into the included set. FIR decimation with a high factor usually - * needs compromizes into specifications and is not desirable. - */ -static int select_mode(struct dai *dai, - struct dmic_configuration *cfg, - struct matched_modes *modes) -{ - int32_t g_cic; - int32_t fir_in_max; - int32_t cic_out_max; - int32_t gain_to_fir; - int16_t idx[DMIC_MAX_MODES]; - int16_t *mfir; - int n = 1; - int mmin; - int count; - int mcic; - int bits_cic; - int ret; - - /* If there are more than one possibilities select a mode with lowest - * FIR decimation factor. If there are several select mode with highest - * ioclk divider to minimize microphone power consumption. The highest - * clock divisors are in the end of list so select the last of list. - * The minimum OSR criteria used in previous ensures that quality in - * the candidates should be sufficient. - */ - if (modes->num_of_modes == 0) { - dai_err(dai, "select_mode() error: no modes available"); - return -EINVAL; - } - - /* Valid modes presence is indicated with non-zero decimation - * factor in 1st element. If FIR A is not used get decimation factors - * from FIR B instead. - */ - if (modes->mfir_a[0] > 0) - mfir = modes->mfir_a; - else - mfir = modes->mfir_b; - - mmin = find_min_int16(mfir, modes->num_of_modes); - count = find_equal_int16(idx, mfir, mmin, modes->num_of_modes, 0); - n = idx[count - 1]; - - /* Get microphone clock and decimation parameters for used mode from - * the list. - */ - cfg->clkdiv = modes->clkdiv[n]; - cfg->mfir_a = modes->mfir_a[n]; - cfg->mfir_b = modes->mfir_b[n]; - cfg->mcic = modes->mcic[n]; - cfg->fir_a = NULL; - cfg->fir_b = NULL; - - /* Find raw FIR coefficients to match the decimation factors of FIR - * A and B. - */ - if (cfg->mfir_a > 0) { - cfg->fir_a = get_fir(dai, cfg, cfg->mfir_a); - if (!cfg->fir_a) { - dai_err(dai, "select_mode() error: cannot find FIR coefficients, mfir_a = %u", - cfg->mfir_a); - return -EINVAL; - } - } - - if (cfg->mfir_b > 0) { - cfg->fir_b = get_fir(dai, cfg, cfg->mfir_b); - if (!cfg->fir_b) { - dai_err(dai, "select_mode() error: cannot find FIR coefficients, mfir_b = %u", - cfg->mfir_b); - return -EINVAL; - } - } - - /* Calculate CIC shift from the decimation factor specific gain. The - * gain of HW decimator equals decimation factor to power of 5. - */ - mcic = cfg->mcic; - g_cic = mcic * mcic * mcic * mcic * mcic; - if (g_cic < 0) { - /* Erroneous decimation factor and CIC gain */ - dai_err(dai, "select_mode() error: erroneous decimation factor and CIC gain"); - return -EINVAL; - } - - bits_cic = 32 - norm_int32(g_cic); - cfg->cic_shift = bits_cic - DMIC_HW_BITS_FIR_INPUT; - - /* Calculate remaining gain to FIR in Q format used for gain - * values. - */ - fir_in_max = (1 << (DMIC_HW_BITS_FIR_INPUT - 1)); - if (cfg->cic_shift >= 0) - cic_out_max = g_cic >> cfg->cic_shift; - else - cic_out_max = g_cic << -cfg->cic_shift; - - gain_to_fir = (int32_t)((((int64_t)fir_in_max) << DMIC_FIR_SCALE_Q) / - cic_out_max); - - /* Calculate FIR scale and shift */ - if (cfg->mfir_a > 0) { - cfg->fir_a_length = cfg->fir_a->length; - ret = fir_coef_scale(&cfg->fir_a_scale, &cfg->fir_a_shift, - cfg->fir_a->shift, cfg->fir_a->coef, - cfg->fir_a->length, gain_to_fir); - if (ret < 0) { - /* Invalid coefficient set found, should not happen. */ - dai_err(dai, "select_mode() error: invalid coefficient set found"); - return -EINVAL; - } - } else { - cfg->fir_a_scale = 0; - cfg->fir_a_shift = 0; - cfg->fir_a_length = 0; - } - - if (cfg->mfir_b > 0) { - cfg->fir_b_length = cfg->fir_b->length; - ret = fir_coef_scale(&cfg->fir_b_scale, &cfg->fir_b_shift, - cfg->fir_b->shift, cfg->fir_b->coef, - cfg->fir_b->length, gain_to_fir); - if (ret < 0) { - /* Invalid coefficient set found, should not happen. */ - dai_err(dai, "select_mode() error: invalid coefficient set found"); - return -EINVAL; - } - } else { - cfg->fir_b_scale = 0; - cfg->fir_b_shift = 0; - cfg->fir_b_length = 0; - } - - return 0; -} - -/* The FIFO input packer mode (IPM) settings are somewhat different in - * HW versions. This helper function returns a suitable IPM bit field - * value to use. - */ - -static inline void ipm_helper1(int *ipm, int di) -{ - int pdm[DMIC_HW_CONTROLLERS]; - int i; - - /* Loop number of PDM controllers in the configuration. If mic A - * or B is enabled then a pdm controller is marked as active for - * this DAI. - */ - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - if (dmic_prm[di]->pdm[i].enable_mic_a || - dmic_prm[di]->pdm[i].enable_mic_b) - pdm[i] = 1; - else - pdm[i] = 0; - } - - /* Set IPM to match active pdm controllers. */ - *ipm = 0; - - if (pdm[0] == 0 && pdm[1] > 0) - *ipm = 1; - - if (pdm[0] > 0 && pdm[1] > 0) - *ipm = 2; -} - -#if DMIC_HW_VERSION == 2 - -static inline void ipm_helper2(int source[], int *ipm, int di) -{ - int pdm[DMIC_HW_CONTROLLERS]; - int i; - int n = 0; - - for (i = 0; i < OUTCONTROLX_IPM_NUMSOURCES; i++) - source[i] = 0; - - /* Loop number of PDM controllers in the configuration. If mic A - * or B is enabled then a pdm controller is marked as active. - * The function returns in array source[] the indice of enabled - * pdm controllers to be used for IPM configuration. - */ - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - if (dmic_prm[di]->pdm[i].enable_mic_a || - dmic_prm[di]->pdm[i].enable_mic_b) { - pdm[i] = 1; - source[n] = i; - n++; - } else { - pdm[i] = 0; - } - } - - /* IPM bit field is set to count of active pdm controllers. */ - *ipm = pdm[0]; - for (i = 1; i < DMIC_HW_CONTROLLERS; i++) - *ipm += pdm[i]; -} -#endif - -/* Loop number of PDM controllers in the configuration. The function - * checks if the controller should operate as stereo or mono left (A) - * or mono right (B) mode. Mono right mode is setup as channel - * swapped mono left. - */ -static int stereo_helper(int stereo[], int swap[]) -{ - int cnt; - int i; - int swap_check; - int ret = 0; - - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - cnt = 0; - if (dmic_prm[0]->pdm[i].enable_mic_a || - dmic_prm[1]->pdm[i].enable_mic_a) - cnt++; - - if (dmic_prm[0]->pdm[i].enable_mic_b || - dmic_prm[1]->pdm[i].enable_mic_b) - cnt++; - - /* Set stereo mode if both mic A anc B are enabled. */ - cnt >>= 1; - stereo[i] = cnt; - - /* Swap channels if only mic B is used for mono processing. */ - swap[i] = (dmic_prm[0]->pdm[i].enable_mic_b || - dmic_prm[1]->pdm[i].enable_mic_b) && !cnt; - - /* Check that swap does not conflict with other DAI request */ - swap_check = dmic_prm[1]->pdm[i].enable_mic_a || - dmic_prm[0]->pdm[i].enable_mic_a; - - if (swap_check && swap[i]) - ret = -EINVAL; - } - return ret; -} - -static int configure_registers(struct dai *dai, - struct dmic_configuration *cfg) -{ - int stereo[DMIC_HW_CONTROLLERS]; - int swap[DMIC_HW_CONTROLLERS]; - uint32_t val; - int32_t ci; - uint32_t cu; - int ipm; - int of0; - int of1; - int fir_decim; - int fir_length; - int length; - int edge; - int dccomp; - int cic_start_a; - int cic_start_b; - int fir_start_a; - int fir_start_b; - int soft_reset; - int i; - int j; - int ret; - int di = dai->index; - struct dmic_pdata *pdata = dai_get_drvdata(dai); - int array_a = 0; - int array_b = 0; - int cic_mute = 1; - int fir_mute = 1; - int bfth = 3; /* Should be 3 for 8 entries, 1 is 2 entries */ - int th = 0; /* Used with TIE=1 */ - - /* Normal start sequence */ - dccomp = 1; - soft_reset = 1; - cic_start_a = 0; - cic_start_b = 0; - fir_start_a = 0; - fir_start_b = 0; - -#if DMIC_HW_VERSION == 2 && DMIC_HW_CONTROLLERS > 2 - int source[OUTCONTROLX_IPM_NUMSOURCES]; -#endif - - /* pdata is set by dmic_probe(), error if it has not been set */ - if (!pdata) { - dai_err(dai, "configure_registers() error: pdata not set"); - return -EINVAL; - } - - dai_info(dai, "configuring registers"); - - /* OUTCONTROL0 and OUTCONTROL1 */ - of0 = (dmic_prm[0]->fifo_bits == 32) ? 2 : 0; - -#if DMIC_HW_FIFOS > 1 - of1 = (dmic_prm[1]->fifo_bits == 32) ? 2 : 0; -#else - of1 = 0; -#endif - -#if DMIC_HW_VERSION == 1 || (DMIC_HW_VERSION == 2 && DMIC_HW_CONTROLLERS <= 2) - ipm_helper1(&ipm, 0); - val = OUTCONTROL0_TIE(0) | - OUTCONTROL0_SIP(0) | - OUTCONTROL0_FINIT(1) | - OUTCONTROL0_FCI(0) | - OUTCONTROL0_BFTH(bfth) | - OUTCONTROL0_OF(of0) | - OUTCONTROL0_IPM(ipm) | - OUTCONTROL0_TH(th); - dai_write(dai, OUTCONTROL0, val); - dai_dbg(dai, "configure_registers(), OUTCONTROL0 = %u", val); - - ipm_helper1(&ipm, 1); - val = OUTCONTROL1_TIE(0) | - OUTCONTROL1_SIP(0) | - OUTCONTROL1_FINIT(1) | - OUTCONTROL1_FCI(0) | - OUTCONTROL1_BFTH(bfth) | - OUTCONTROL1_OF(of1) | - OUTCONTROL1_IPM(ipm) | - OUTCONTROL1_TH(th); - dai_write(dai, OUTCONTROL1, val); - dai_dbg(dai, "configure_registers(), OUTCONTROL1 = %u", val); -#endif - -#if DMIC_HW_VERSION == 2 && DMIC_HW_CONTROLLERS > 2 - ipm_helper2(source, &ipm, 0); - val = OUTCONTROL0_TIE(0) | - OUTCONTROL0_SIP(0) | - OUTCONTROL0_FINIT(1) | - OUTCONTROL0_FCI(0) | - OUTCONTROL0_BFTH(bfth) | - OUTCONTROL0_OF(of0) | - OUTCONTROL0_IPM(ipm) | - OUTCONTROL0_IPM_SOURCE_1(source[0]) | - OUTCONTROL0_IPM_SOURCE_2(source[1]) | - OUTCONTROL0_IPM_SOURCE_3(source[2]) | - OUTCONTROL0_IPM_SOURCE_4(source[3]) | - OUTCONTROL0_TH(th); - dai_write(dai, OUTCONTROL0, val); - dai_dbg(dai, "configure_registers(), OUTCONTROL0 = %u", val); - - ipm_helper2(source, &ipm, 1); - val = OUTCONTROL1_TIE(0) | - OUTCONTROL1_SIP(0) | - OUTCONTROL1_FINIT(1) | - OUTCONTROL1_FCI(0) | - OUTCONTROL1_BFTH(bfth) | - OUTCONTROL1_OF(of1) | - OUTCONTROL1_IPM(ipm) | - OUTCONTROL1_IPM_SOURCE_1(source[0]) | - OUTCONTROL1_IPM_SOURCE_2(source[1]) | - OUTCONTROL1_IPM_SOURCE_3(source[2]) | - OUTCONTROL1_IPM_SOURCE_4(source[3]) | - OUTCONTROL1_TH(th); - dai_write(dai, OUTCONTROL1, val); - dai_dbg(dai, "configure_registers(), OUTCONTROL1 = %u", val); -#endif - - /* Mark enabled microphones into private data to be later used - * for starting correct parts of the HW. - */ - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - pdata->enable[i] = (dmic_prm[di]->pdm[i].enable_mic_b << 1) | - dmic_prm[di]->pdm[i].enable_mic_a; - } - - ret = stereo_helper(stereo, swap); - if (ret < 0) { - dai_err(dai, "configure_registers(): enable conflict"); - return ret; - } - - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - /* CIC */ - val = CIC_CONTROL_SOFT_RESET(soft_reset) | - CIC_CONTROL_CIC_START_B(cic_start_b) | - CIC_CONTROL_CIC_START_A(cic_start_a) | - CIC_CONTROL_MIC_B_POLARITY(dmic_prm[di]->pdm[i].polarity_mic_a) | - CIC_CONTROL_MIC_A_POLARITY(dmic_prm[di]->pdm[i].polarity_mic_b) | - CIC_CONTROL_MIC_MUTE(cic_mute) | - CIC_CONTROL_STEREO_MODE(stereo[i]); - dai_write(dai, base[i] + CIC_CONTROL, val); - dai_dbg(dai, "configure_registers(), CIC_CONTROL = %u", - val); - - val = CIC_CONFIG_CIC_SHIFT(cfg->cic_shift + 8) | - CIC_CONFIG_COMB_COUNT(cfg->mcic - 1); - dai_write(dai, base[i] + CIC_CONFIG, val); - dai_dbg(dai, "configure_registers(), CIC_CONFIG = %u", - val); - - /* Mono right channel mic usage requires swap of PDM channels - * since the mono decimation is done with only left channel - * processing active. - */ - edge = dmic_prm[di]->pdm[i].clk_edge; - if (swap[i]) - edge = !edge; - - val = MIC_CONTROL_PDM_CLKDIV(cfg->clkdiv - 2) | - MIC_CONTROL_PDM_SKEW(dmic_prm[di]->pdm[i].skew) | - MIC_CONTROL_CLK_EDGE(edge) | - MIC_CONTROL_PDM_EN_B(cic_start_b) | - MIC_CONTROL_PDM_EN_A(cic_start_a); - dai_write(dai, base[i] + MIC_CONTROL, val); - dai_dbg(dai, "configure_registers(), MIC_CONTROL = %u", - val); - - /* FIR A */ - fir_decim = MAX(cfg->mfir_a - 1, 0); - fir_length = MAX(cfg->fir_a_length - 1, 0); - val = FIR_CONTROL_A_START(fir_start_a) | - FIR_CONTROL_A_ARRAY_START_EN(array_a) | - FIR_CONTROL_A_DCCOMP(dccomp) | - FIR_CONTROL_A_MUTE(fir_mute) | - FIR_CONTROL_A_STEREO(stereo[i]); - dai_write(dai, base[i] + FIR_CONTROL_A, val); - dai_dbg(dai, "configure_registers(), FIR_CONTROL_A = %u", - val); - - val = FIR_CONFIG_A_FIR_DECIMATION(fir_decim) | - FIR_CONFIG_A_FIR_SHIFT(cfg->fir_a_shift) | - FIR_CONFIG_A_FIR_LENGTH(fir_length); - dai_write(dai, base[i] + FIR_CONFIG_A, val); - dai_dbg(dai, "configure_registers(), FIR_CONFIG_A = %u", - val); - - val = DC_OFFSET_LEFT_A_DC_OFFS(DCCOMP_TC0); - dai_write(dai, base[i] + DC_OFFSET_LEFT_A, val); - dai_dbg(dai, "configure_registers(), DC_OFFSET_LEFT_A = %u", - val); - - val = DC_OFFSET_RIGHT_A_DC_OFFS(DCCOMP_TC0); - dai_write(dai, base[i] + DC_OFFSET_RIGHT_A, val); - dai_dbg(dai, "configure_registers(), DC_OFFSET_RIGHT_A = %u", - val); - - val = OUT_GAIN_LEFT_A_GAIN(0); - dai_write(dai, base[i] + OUT_GAIN_LEFT_A, val); - dai_dbg(dai, "configure_registers(), OUT_GAIN_LEFT_A = %u", - val); - - val = OUT_GAIN_RIGHT_A_GAIN(0); - dai_write(dai, base[i] + OUT_GAIN_RIGHT_A, val); - dai_dbg(dai, "configure_registers(), OUT_GAIN_RIGHT_A = %u", - val); - - /* FIR B */ - fir_decim = MAX(cfg->mfir_b - 1, 0); - fir_length = MAX(cfg->fir_b_length - 1, 0); - val = FIR_CONTROL_B_START(fir_start_b) | - FIR_CONTROL_B_ARRAY_START_EN(array_b) | - FIR_CONTROL_B_DCCOMP(dccomp) | - FIR_CONTROL_B_MUTE(fir_mute) | - FIR_CONTROL_B_STEREO(stereo[i]); - dai_write(dai, base[i] + FIR_CONTROL_B, val); - dai_dbg(dai, "configure_registers(), FIR_CONTROL_B = %u", - val); - - val = FIR_CONFIG_B_FIR_DECIMATION(fir_decim) | - FIR_CONFIG_B_FIR_SHIFT(cfg->fir_b_shift) | - FIR_CONFIG_B_FIR_LENGTH(fir_length); - dai_write(dai, base[i] + FIR_CONFIG_B, val); - dai_dbg(dai, "configure_registers(), FIR_CONFIG_B = %u", - val); - - val = DC_OFFSET_LEFT_B_DC_OFFS(DCCOMP_TC0); - dai_write(dai, base[i] + DC_OFFSET_LEFT_B, val); - dai_dbg(dai, "configure_registers(), DC_OFFSET_LEFT_B = %u", - val); - - val = DC_OFFSET_RIGHT_B_DC_OFFS(DCCOMP_TC0); - dai_write(dai, base[i] + DC_OFFSET_RIGHT_B, val); - dai_dbg(dai, "configure_registers(), DC_OFFSET_RIGHT_B = %u", - val); - - val = OUT_GAIN_LEFT_B_GAIN(0); - dai_write(dai, base[i] + OUT_GAIN_LEFT_B, val); - dai_dbg(dai, "configure_registers(), OUT_GAIN_LEFT_B = %u", - val); - - val = OUT_GAIN_RIGHT_B_GAIN(0); - dai_write(dai, base[i] + OUT_GAIN_RIGHT_B, val); - dai_dbg(dai, "configure_registers(), OUT_GAIN_RIGHT_B = %u", - val); - - /* Write coef RAM A with scaled coefficient in reverse order */ - length = cfg->fir_a_length; - for (j = 0; j < length; j++) { - ci = (int32_t)Q_MULTSR_32X32( - (int64_t)cfg->fir_a->coef[j], cfg->fir_a_scale, - 31, DMIC_FIR_SCALE_Q, DMIC_HW_FIR_COEF_Q); - cu = FIR_COEF_A(ci); - dai_write(dai, coef_base_a[i] - + ((length - j - 1) << 2), cu); - } - - /* Write coef RAM B with scaled coefficient in reverse order */ - length = cfg->fir_b_length; - for (j = 0; j < length; j++) { - ci = (int32_t)Q_MULTSR_32X32( - (int64_t)cfg->fir_b->coef[j], cfg->fir_b_scale, - 31, DMIC_FIR_SCALE_Q, DMIC_HW_FIR_COEF_Q); - cu = FIR_COEF_B(ci); - dai_write(dai, coef_base_b[i] - + ((length - j - 1) << 2), cu); - } - } - - return 0; -} - -/* get DMIC hw params */ -static int dmic_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) -{ - int di = dai->index; - - params->rate = dmic_prm[di]->fifo_fs; - params->buffer_fmt = 0; - - switch (dmic_prm[di]->num_pdm_active) { - case 1: - params->channels = 2; - break; - case 2: - params->channels = 4; - break; - default: - dai_info(dai, "dmic_get_hw_params(): not supported channels amount"); - return -EINVAL; - } - - switch (dmic_prm[di]->fifo_bits) { - case 16: - params->frame_fmt = SOF_IPC_FRAME_S16_LE; - break; - case 32: - params->frame_fmt = SOF_IPC_FRAME_S32_LE; - break; - default: - dai_err(dai, "dmic_get_hw_params(): not supported format"); - return -EINVAL; - } - - return 0; -} - -static int dmic_set_config(struct dai *dai, struct sof_ipc_dai_config *config) -{ - struct dmic_pdata *dmic = dai_get_drvdata(dai); - struct matched_modes modes_ab; - struct dmic_configuration cfg; - struct decim_modes modes_a; - struct decim_modes modes_b; - int32_t unmute_ramp_time_ms; - int32_t step_db; - size_t size; - int i, j, ret = 0; - int di = dai->index; - - dai_info(dai, "dmic_set_config()"); - - if (config->dmic.driver_ipc_version != DMIC_IPC_VERSION) { - dai_err(dai, "dmic_set_config() error: wrong ipc version"); - return -EINVAL; - } - - /* Compute unmute ramp gain update coefficient. Use the value from - * topology if it is non-zero, otherwise use default length. - */ - if (config->dmic.unmute_ramp_time) - unmute_ramp_time_ms = config->dmic.unmute_ramp_time; - else - unmute_ramp_time_ms = LOGRAMP_TIME_MS; - - if (unmute_ramp_time_ms < LOGRAMP_TIME_MIN_MS || - unmute_ramp_time_ms > LOGRAMP_TIME_MAX_MS) { - dai_err(dai, "dmic_set_config(): Illegal ramp time = %d", - unmute_ramp_time_ms); - return -EINVAL; - } - - if (di >= DMIC_HW_FIFOS) { - dai_err(dai, "dmic_set_config() error: dai->index exceeds number of FIFOs"); - return -EINVAL; - } - - if (config->dmic.num_pdm_active > DMIC_HW_CONTROLLERS) { - dai_err(dai, "dmic_set_config() error: the requested PDM controllers count exceeds platform capability"); - return -EINVAL; - } - - step_db = LOGRAMP_CONST_TERM / unmute_ramp_time_ms; - dmic->gain_coef = db2lin_fixed(step_db); - dai_info(dai, "dmic_set_config(): unmute_ramp_time_ms = %d", - unmute_ramp_time_ms); - - /* - * "config" might contain pdm controller params for only - * the active controllers - * "prm" is initialized with default params for all HW controllers - */ - if (!dmic_prm[0]) { - size = sizeof(struct sof_ipc_dai_dmic_params) - + DMIC_HW_CONTROLLERS - * sizeof(struct sof_ipc_dai_dmic_pdm_ctrl); - dmic_prm[0] = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, - SOF_MEM_CAPS_RAM, - DMIC_HW_FIFOS * size); - if (!dmic_prm[0]) { - dai_err(dai, "dmic_set_config() error: prm not initialized"); - return -ENOMEM; - } - for (i = 1; i < DMIC_HW_FIFOS; i++) - dmic_prm[i] = (struct sof_ipc_dai_dmic_params *) - ((uint8_t *)dmic_prm[i - 1] + size); - } - - /* Copy the new DMIC params to persistent. The last request - * determines the parameters. - */ - ret = memcpy_s(dmic_prm[di], sizeof(*dmic_prm[di]), &config->dmic, - sizeof(struct sof_ipc_dai_dmic_params)); - assert(!ret); - - /* copy the pdm controller params from ipc */ - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - dmic_prm[di]->pdm[i].id = i; - for (j = 0; j < config->dmic.num_pdm_active; j++) { - /* copy the pdm controller params id the id's match */ - if (dmic_prm[di]->pdm[i].id == config->dmic.pdm[j].id) { - ret = memcpy_s(&dmic_prm[di]->pdm[i], - sizeof(dmic_prm[di]->pdm[i]), - &config->dmic.pdm[j], - sizeof( - struct sof_ipc_dai_dmic_pdm_ctrl)); - assert(!ret); - } - } - } - - dai_info(dai, "dmic_set_config(), prm config->dmic.num_pdm_active = %u", - config->dmic.num_pdm_active); - dai_info(dai, "dmic_set_config(), prm pdmclk_min = %u, pdmclk_max = %u", - dmic_prm[di]->pdmclk_min, dmic_prm[di]->pdmclk_max); - dai_info(dai, "dmic_set_config(), prm duty_min = %u, duty_max = %u", - dmic_prm[di]->duty_min, dmic_prm[di]->duty_max); - dai_info(dai, "dmic_set_config(), prm fifo_fs = %u, fifo_bits = %u", - dmic_prm[di]->fifo_fs, dmic_prm[di]->fifo_bits); - - switch (dmic_prm[di]->fifo_bits) { - case 0: - case 16: - case 32: - break; - default: - dai_err(dai, "dmic_set_config() error: fifo_bits EINVAL"); - return -EINVAL; - } - - /* Match and select optimal decimators configuration for FIFOs A and B - * paths. This setup phase is still abstract. Successful completion - * points struct cfg to FIR coefficients and contains the scale value - * to use for FIR coefficient RAM write as well as the CIC and FIR - * shift values. - */ - find_modes(dai, &modes_a, dmic_prm[0]->fifo_fs, di); - if (modes_a.num_of_modes == 0 && dmic_prm[0]->fifo_fs > 0) { - dai_err(dai, "dmic_set_config() error: No modes found found for FIFO A"); - return -EINVAL; - } - - find_modes(dai, &modes_b, dmic_prm[1]->fifo_fs, di); - if (modes_b.num_of_modes == 0 && dmic_prm[1]->fifo_fs > 0) { - dai_err(dai, "dmic_set_config() error: No modes found for FIFO B"); - return -EINVAL; - } - - match_modes(&modes_ab, &modes_a, &modes_b); - ret = select_mode(dai, &cfg, &modes_ab); - if (ret < 0) { - dai_err(dai, "dmic_set_config() error: select_mode() failed"); - return -EINVAL; - } - - dai_info(dai, "dmic_set_config(), cfg clkdiv = %u, mcic = %u", - cfg.clkdiv, cfg.mcic); - dai_info(dai, "dmic_set_config(), cfg mfir_a = %u, mfir_b = %u", - cfg.mfir_a, cfg.mfir_b); - dai_info(dai, "dmic_set_config(), cfg cic_shift = %u", - cfg.cic_shift); - dai_info(dai, "dmic_set_config(), cfg fir_a_shift = %u, cfg.fir_b_shift = %u", - cfg.fir_a_shift, cfg.fir_b_shift); - dai_info(dai, "dmic_set_config(), cfg fir_a_length = %u, fir_b_length = %u", - cfg.fir_a_length, cfg.fir_b_length); - - /* Struct reg contains a mirror of actual HW registers. Determine - * register bits configuration from decimator configuration and the - * requested parameters. - */ - ret = configure_registers(dai, &cfg); - if (ret < 0) { - dai_err(dai, "dmic_set_config() error: cannot configure registers"); - return -EINVAL; - } - - dmic->state = COMP_STATE_PREPARE; - - return ret; -} - -/* start the DMIC for capture */ -static void dmic_start(struct dai *dai) -{ - struct dmic_pdata *dmic = dai_get_drvdata(dai); - int i; - int mic_a; - int mic_b; - int fir_a; - int fir_b; - - /* enable port */ - spin_lock(&dai->lock); - dai_dbg(dai, "dmic_start()"); - dmic->state = COMP_STATE_ACTIVE; - dmic->startcount = 0; - - /* Initial gain value, convert Q12.20 to Q2.30 */ - dmic->gain = Q_SHIFT_LEFT(db2lin_fixed(LOGRAMP_START_DB), 20, 30); - - switch (dai->index) { - case 0: - dai_info(dai, "dmic_start(), dmic->fifo_a"); - /* Clear FIFO A initialize, Enable interrupts to DSP, - * Start FIFO A packer. - */ - dai_update_bits(dai, OUTCONTROL0, - OUTCONTROL0_FINIT_BIT | OUTCONTROL0_SIP_BIT, - OUTCONTROL0_SIP_BIT); - break; - case 1: - dai_info(dai, "dmic_start(), dmic->fifo_b"); - /* Clear FIFO B initialize, Enable interrupts to DSP, - * Start FIFO B packer. - */ - dai_update_bits(dai, OUTCONTROL1, - OUTCONTROL1_FINIT_BIT | OUTCONTROL1_SIP_BIT, - OUTCONTROL1_SIP_BIT); - } - - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - mic_a = dmic->enable[i] & 1; - mic_b = (dmic->enable[i] & 2) >> 1; - if (dmic_prm[0]->fifo_fs > 0) - fir_a = (dmic->enable[i] > 0) ? 1 : 0; - else - fir_a = 0; - -#if DMIC_HW_FIFOS > 1 - if (dmic_prm[1]->fifo_fs > 0) - fir_b = (dmic->enable[i] > 0) ? 1 : 0; - else - fir_b = 0; -#else - fir_b = 0; -#endif - dai_info(dai, "dmic_start(), mic_a = %u, mic_b = %u, fir_a = %u, fir_b = %u", - mic_a, mic_b, fir_a, fir_b); - - /* If both microphones are needed start them simultaneously - * to start them in sync. The reset may be cleared for another - * FIFO already. If only one mic, start them independently. - * This makes sure we do not clear start/en for another DAI. - */ - if (mic_a && mic_b) { - dai_update_bits(dai, base[i] + CIC_CONTROL, - CIC_CONTROL_CIC_START_A_BIT | - CIC_CONTROL_CIC_START_B_BIT, - CIC_CONTROL_CIC_START_A(1) | - CIC_CONTROL_CIC_START_B(1)); - dai_update_bits(dai, base[i] + MIC_CONTROL, - MIC_CONTROL_PDM_EN_A_BIT | - MIC_CONTROL_PDM_EN_B_BIT, - MIC_CONTROL_PDM_EN_A(1) | - MIC_CONTROL_PDM_EN_B(1)); - } else if (mic_a) { - dai_update_bits(dai, base[i] + CIC_CONTROL, - CIC_CONTROL_CIC_START_A_BIT, - CIC_CONTROL_CIC_START_A(1)); - dai_update_bits(dai, base[i] + MIC_CONTROL, - MIC_CONTROL_PDM_EN_A_BIT, - MIC_CONTROL_PDM_EN_A(1)); - } else if (mic_b) { - dai_update_bits(dai, base[i] + CIC_CONTROL, - CIC_CONTROL_CIC_START_B_BIT, - CIC_CONTROL_CIC_START_B(1)); - dai_update_bits(dai, base[i] + MIC_CONTROL, - MIC_CONTROL_PDM_EN_B_BIT, - MIC_CONTROL_PDM_EN_B(1)); - } - - switch (dai->index) { - case 0: - dai_update_bits(dai, base[i] + FIR_CONTROL_A, - FIR_CONTROL_A_START_BIT, - FIR_CONTROL_A_START(fir_a)); - break; - case 1: - dai_update_bits(dai, base[i] + FIR_CONTROL_B, - FIR_CONTROL_B_START_BIT, - FIR_CONTROL_B_START(fir_b)); - break; - } - } - - /* Clear soft reset for all/used PDM controllers. This should - * start capture in sync. - */ - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - dai_update_bits(dai, base[i] + CIC_CONTROL, - CIC_CONTROL_SOFT_RESET_BIT, 0); - } - - dmic_active_fifos++; - - spin_unlock(&dai->lock); - - /* Currently there's no DMIC HW internal mutings and wait times - * applied into this start sequence. It can be implemented here if - * start of audio capture would contain clicks and/or noise and it - * is not suppressed by gain ramp somewhere in the capture pipe. - */ - - schedule_task(&dmic->dmicwork, DMIC_UNMUTE_RAMP_US, - DMIC_UNMUTE_RAMP_US); - - dai_info(dai, "dmic_start(), done active_fifos = %d", - dmic_active_fifos); -} - -/* stop the DMIC for capture */ -static void dmic_stop(struct dai *dai) -{ - struct dmic_pdata *dmic = dai_get_drvdata(dai); - int i; - - dai_dbg(dai, "dmic_stop()"); - spin_lock(&dai->lock); - - if (dmic->state != COMP_STATE_ACTIVE) { - dai_info(dai, "dmic_stop(), already stopped"); - goto out; - } - - dmic->state = COMP_STATE_PREPARE; - - /* Stop FIFO packers and set FIFO initialize bits */ - switch (dai->index) { - case 0: - dai_update_bits(dai, OUTCONTROL0, - OUTCONTROL0_SIP_BIT | OUTCONTROL0_FINIT_BIT, - OUTCONTROL0_FINIT_BIT); - break; - case 1: - dai_update_bits(dai, OUTCONTROL1, - OUTCONTROL1_SIP_BIT | OUTCONTROL1_FINIT_BIT, - OUTCONTROL1_FINIT_BIT); - break; - } - - /* Set soft reset and mute on for all PDM controllers. - */ - dai_info(dai, "dmic_stop(), dmic_active_fifos = %d", - dmic_active_fifos); - - for (i = 0; i < DMIC_HW_CONTROLLERS; i++) { - /* Don't stop CIC yet if both FIFOs were active */ - if (dmic_active_fifos == 1) { - dai_update_bits(dai, base[i] + CIC_CONTROL, - CIC_CONTROL_SOFT_RESET_BIT | - CIC_CONTROL_MIC_MUTE_BIT, - CIC_CONTROL_SOFT_RESET_BIT | - CIC_CONTROL_MIC_MUTE_BIT); - } - switch (dai->index) { - case 0: - dai_update_bits(dai, base[i] + FIR_CONTROL_A, - FIR_CONTROL_A_MUTE_BIT, - FIR_CONTROL_A_MUTE_BIT); - break; - case 1: - dai_update_bits(dai, base[i] + FIR_CONTROL_B, - FIR_CONTROL_B_MUTE_BIT, - FIR_CONTROL_B_MUTE_BIT); - break; - } - } - - dmic_active_fifos--; - - schedule_task_cancel(&dmic->dmicwork); -out: - spin_unlock(&dai->lock); -} - -/* save DMIC context prior to entering D3 */ -static int dmic_context_store(struct dai *dai) -{ - /* Nothing stored at the moment. */ - return 0; -} - -/* restore DMIC context after leaving D3 */ -static int dmic_context_restore(struct dai *dai) -{ - /* Nothing restored at the moment. */ - return 0; -} - -static int dmic_trigger(struct dai *dai, int cmd, int direction) -{ - struct dmic_pdata *dmic = dai_get_drvdata(dai); - - dai_dbg(dai, "dmic_trigger()"); - - /* dai private is set in dmic_probe(), error if not set */ - if (!dmic) { - dai_err(dai, "dmic_trigger() error: dai not set"); - return -EINVAL; - } - - if (direction != DAI_DIR_CAPTURE) { - dai_err(dai, "dmic_trigger() error: direction != DAI_DIR_CAPTURE"); - return -EINVAL; - } - - switch (cmd) { - case COMP_TRIGGER_RELEASE: - case COMP_TRIGGER_START: - if (dmic->state == COMP_STATE_PREPARE || - dmic->state == COMP_STATE_PAUSED) { - dmic_start(dai); - } else { - dai_err(dai, "dmic_trigger() error: state is not prepare or paused, dmic->state = %u", - dmic->state); - } - break; - case COMP_TRIGGER_STOP: - case COMP_TRIGGER_PAUSE: - dmic_stop(dai); - break; - case COMP_TRIGGER_RESUME: - dmic_context_restore(dai); - break; - case COMP_TRIGGER_SUSPEND: - dmic_context_store(dai); - break; - default: - break; - } - - return 0; -} - -/* On DMIC IRQ event trace the status register that contains the status and - * error bit fields. - */ -static void dmic_irq_handler(void *data) -{ - struct dai *dai = data; - uint32_t val0; - uint32_t val1; - - /* Trace OUTSTAT0 register */ - val0 = dai_read(dai, OUTSTAT0); - val1 = dai_read(dai, OUTSTAT1); - dai_info(dai, "dmic_irq_handler(), OUTSTAT0 = %u", val0); - dai_info(dai, "dmic_irq_handler(), OUTSTAT1 = %u", val1); - - if (val0 & OUTSTAT0_ROR_BIT) { - dai_err(dai, "dmic_irq_handler() error: full fifo A or PDM overrun"); - dai_write(dai, OUTSTAT0, val0); - } - - if (val1 & OUTSTAT1_ROR_BIT) { - dai_err(dai, "dmic_irq_handler() error: full fifo B or PDM overrun"); - dai_write(dai, OUTSTAT1, val1); - } -} - -static int dmic_probe(struct dai *dai) -{ - int irq = dmic_irq(dai); - struct dmic_pdata *dmic; - int ret; - - dai_info(dai, "dmic_probe()"); - - if (dai_get_drvdata(dai)) - return -EEXIST; /* already created */ - - /* allocate private data */ - dmic = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*dmic)); - if (!dmic) { - dai_err(dai, "dmic_probe() error: alloc failed"); - return -ENOMEM; - } - dai_set_drvdata(dai, dmic); - - /* Set state, note there is no playback direction support */ - dmic->state = COMP_STATE_READY; - - /* register our IRQ handler */ - dmic->irq = interrupt_get_irq(irq, dmic_irq_name(dai)); - if (dmic->irq < 0) { - ret = dmic->irq; - rfree(dmic); - return ret; - } - - ret = interrupt_register(dmic->irq, dmic_irq_handler, dai); - if (ret < 0) { - dai_err(dai, "dmic failed to allocate IRQ"); - rfree(dmic); - return ret; - } - - /* Initialize start sequence handler */ - schedule_task_init_ll(&dmic->dmicwork, SOF_UUID(dmic_work_task_uuid), - SOF_SCHEDULE_LL_TIMER, - SOF_TASK_PRI_MED, dmic_work, dai, 0, 0); - - /* Enable DMIC power */ - pm_runtime_get_sync(DMIC_POW, dai->index); - /* Disable dynamic clock gating for dmic before touching any reg */ - pm_runtime_get_sync(DMIC_CLK, dai->index); - - interrupt_unmask(dmic->irq, cpu_get_id()); - interrupt_enable(dmic->irq, dai); - - return 0; -} - -static int dmic_remove(struct dai *dai) -{ - struct dmic_pdata *dmic = dai_get_drvdata(dai); - int i; - - interrupt_disable(dmic->irq, dai); - interrupt_mask(dmic->irq, cpu_get_id()); - interrupt_unregister(dmic->irq, dai); - - pm_runtime_put_sync(DMIC_CLK, dai->index); - /* Disable DMIC power */ - pm_runtime_put_sync(DMIC_POW, dai->index); - - /* remove scheduling */ - schedule_task_free(&dmic->dmicwork); - - rfree(dai_get_drvdata(dai)); - dai_set_drvdata(dai, NULL); - - rfree(dmic_prm[0]); - for (i = 0; i < DMIC_HW_FIFOS; i++) - dmic_prm[i] = NULL; - - return 0; -} - -static int dmic_get_handshake(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[SOF_IPC_STREAM_CAPTURE].handshake; -} - -static int dmic_get_fifo(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[SOF_IPC_STREAM_CAPTURE].offset; -} - -/* Functions for HW timestamp */ - -static inline uint32_t dmic_ts_local_tsctrl_addr(void) -{ - return TIMESTAMP_BASE + TS_DMIC_LOCAL_TSCTRL; -} - -static inline uint32_t dmic_ts_local_offs_addr(void) -{ - return TIMESTAMP_BASE + TS_DMIC_LOCAL_OFFS; -} - -static inline uint32_t dmic_ts_local_sample_addr(void) -{ - return TIMESTAMP_BASE + TS_DMIC_LOCAL_SAMPLE; -} - -static inline uint32_t dmic_ts_local_walclk_addr(void) -{ - return TIMESTAMP_BASE + TS_DMIC_LOCAL_WALCLK; -} - -static inline uint32_t dmic_ts_tscc_addr(void) -{ - return TIMESTAMP_BASE + TS_DMIC_TSCC; -} - -static int dmic_ts_config(struct dai *dai, struct timestamp_cfg *cfg) -{ - if (cfg->type != SOF_DAI_INTEL_DMIC) { - dai_err(dai, "dmic_ts_config(): Illegal DAI type"); - return -EINVAL; - } - - cfg->walclk_rate = DMIC_HW_IOCLK; - - return 0; -} - -static int dmic_ts_start(struct dai *dai, struct timestamp_cfg *cfg) -{ - uint32_t cdmas; - uint32_t addr = dmic_ts_local_tsctrl_addr(); - - /* Set DMIC timestamp registers */ - - /* First point CDMAS to GPDMA channel that is used by DMIC - * also clear NTK to be sure there is no old timestamp. - */ - cdmas = TS_LOCAL_TSCTRL_CDMAS(cfg->dma_chan_index + - cfg->dma_chan_count * cfg->dma_id); - io_reg_write(addr, TS_LOCAL_TSCTRL_NTK_BIT | cdmas); - - /* Request on demand timestamp */ - io_reg_write(addr, TS_LOCAL_TSCTRL_ODTS_BIT | cdmas); - - return 0; -} - -static int dmic_ts_stop(struct dai *dai, struct timestamp_cfg *cfg) -{ - /* Clear NTK and write zero to CDMAS */ - io_reg_write(dmic_ts_local_tsctrl_addr(), TS_LOCAL_TSCTRL_NTK_BIT); - return 0; -} - -static int dmic_ts_get(struct dai *dai, struct timestamp_cfg *cfg, - struct timestamp_data *tsd) -{ - /* Read DMIC timestamp registers */ - uint32_t ntk; - uint32_t tsctrl = dmic_ts_local_tsctrl_addr(); - - /* Read SSP timestamp registers */ - ntk = io_reg_read(tsctrl) & TS_LOCAL_TSCTRL_NTK_BIT; - if (!ntk) - goto out; - - /* NTK was set, get wall clock */ - tsd->walclk = io_reg_read_64(dmic_ts_local_walclk_addr()); - - /* Sample */ - tsd->sample = io_reg_read_64(dmic_ts_local_sample_addr()); - - /* Clear NTK to enable successive timestamps */ - io_reg_write(tsctrl, TS_LOCAL_TSCTRL_NTK_BIT); - -out: - tsd->walclk_rate = cfg->walclk_rate; - if (!ntk) - return -ENODATA; - - return 0; -} - -const struct dai_driver dmic_driver = { - .type = SOF_DAI_INTEL_DMIC, - .uid = SOF_UUID(dmic_uuid), - .dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, - .dma_dev = DMA_DEV_DMIC, - .ops = { - .trigger = dmic_trigger, - .set_config = dmic_set_config, - .get_hw_params = dmic_get_hw_params, - .pm_context_store = dmic_context_store, - .pm_context_restore = dmic_context_restore, - .get_handshake = dmic_get_handshake, - .get_fifo = dmic_get_fifo, - .probe = dmic_probe, - .remove = dmic_remove, - }, - .ts_ops = { - .ts_config = dmic_ts_config, - .ts_start = dmic_ts_start, - .ts_get = dmic_ts_get, - .ts_stop = dmic_ts_stop, - }, -}; - -#endif diff --git a/src/drivers/intel/cavs/hda-dma.c b/src/drivers/intel/cavs/hda-dma.c deleted file mode 100644 index 19aef1b8fede..000000000000 --- a/src/drivers/intel/cavs/hda-dma.c +++ /dev/null @@ -1,943 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Keyon Jie <yang.jie@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/atomic.h> -#include <sof/audio/component.h> -#include <sof/bit.h> -#include <sof/drivers/hda-dma.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> -#include <sof/lib/dma.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/notifier.h> -#include <sof/platform.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -#define trace_hddma(__e, ...) \ - trace_event(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define tracev_hddma(__e, ...) \ - tracev_event(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define trace_hddma_error(__e, ...) \ - trace_error(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) - -/* Gateway Stream Registers */ -#define DGCS 0x00 -#define DGBBA 0x04 -#define DGBS 0x08 -#define DGBFPI 0x0c /* firmware need to update this when DGCS.FWCB=1 */ -#define DGBRP 0x10 /* Read Only, read pointer */ -#define DGBWP 0x14 /* Read Only, write pointer */ -#define DGBSP 0x18 -#define DGMBS 0x1c -#define DGLLPI 0x24 -#define DGLPIBI 0x28 - -/* DGCS */ -#define DGCS_SCS BIT(31) -#define DGCS_GEN BIT(26) -#define DGCS_FWCB BIT(23) -#define DGCS_BSC BIT(11) -/* NOTE: both XRUN bits are the same, just direction is different */ -#define DGCS_BOR BIT(10) /* buffer overrun (input streams) */ -#define DGCS_BUR BIT(10) /* buffer underrun (output streams) */ -#define DGCS_BF BIT(9) /* buffer full */ -#define DGCS_BNE BIT(8) /* buffer not empty */ -#define DGCS_FIFORDY BIT(5) /* enable FIFO */ - -/* DGBBA */ -#define DGBBA_MASK 0xffff80 - -/* DGBS */ -#define DGBS_MASK 0xfffff0 - -#define HDA_STATE_RELEASE BIT(0) - -/* DGMBS align value */ -#define HDA_DMA_BUFFER_ALIGNMENT 0x20 -#define HDA_DMA_COPY_ALIGNMENT 0x20 -#define HDA_DMA_BUFFER_ADDRESS_ALIGNMENT 0x80 - -/* DMA host transfer timeout in microseconds */ -#define HDA_DMA_TIMEOUT 200 - -/* DMA number of buffer periods */ -#define HDA_DMA_BUFFER_PERIOD_COUNT 2 - -/* - * DMA Pointer Trace - * - * - * DMA pointer trace will output hardware DMA pointers and the BNE flag - * for n samples after stream start. - * It will also show current values on start/stop. - * Additionally values after the last copy will be output on stop. - * - * The trace will output three 32-bit values and context info, - * looking like this: - * hda-dma-ptr-trace AAAAooBC DDDDEEEE FFFFGGGG <context info> - * where: - * o - unused - * A - indicates the direction of the transfer - * B - will be 1 if BNE was set before an operation - * C - will be 1 if BNE was set after an operation - * D - hardware write pointer before an operation - * E - hardware write pointer after an operation - * F - hardware read pointer before an operation - * G - hardware read pointer after an operation - */ - -#define HDA_DMA_PTR_DBG 0 /* trace DMA pointers */ -#define HDA_DMA_PTR_DBG_NUM_CP 32 /* number of traces to output after start */ - -#if HDA_DMA_PTR_DBG - -enum hda_dbg_src { - HDA_DBG_HOST = 0, /* enables dma pointer traces for host */ - HDA_DBG_LINK, /* enables dma pointer traces for link */ - HDA_DBG_BOTH /* enables dma pointer traces for host and link */ -}; - -#define HDA_DBG_SRC HDA_DBG_BOTH - -enum hda_dbg_sample { - HDA_DBG_PRE = 0, - HDA_DBG_POST, - - HDA_DBG_MAX_SAMPLES -}; - -struct hda_dbg_data { - uint16_t cur_sample; - uint16_t last_wp[HDA_DBG_MAX_SAMPLES]; - uint16_t last_rp[HDA_DBG_MAX_SAMPLES]; - uint8_t last_bne[HDA_DBG_MAX_SAMPLES]; -}; -#endif - -struct hda_chan_data { - uint32_t stream_id; - uint32_t state; /* hda specific additional state */ - uint32_t desc_avail; - - uint32_t period_bytes; - uint32_t buffer_bytes; - -#if HDA_DMA_PTR_DBG - struct hda_dbg_data dbg_data; -#endif -}; - -static int hda_dma_stop(struct dma_chan_data *channel); - -static inline void hda_dma_inc_fp(struct dma_chan_data *chan, - uint32_t value) -{ - dma_chan_reg_write(chan, DGBFPI, value); - /* TODO: wp update, not rp should inc LLPI and LPIBI in the - * coupled input DMA - */ - dma_chan_reg_write(chan, DGLLPI, value); - dma_chan_reg_write(chan, DGLPIBI, value); -} - -static inline void hda_dma_inc_link_fp(struct dma_chan_data *chan, - uint32_t value) -{ - dma_chan_reg_write(chan, DGBFPI, value); - /* TODO: wp update should inc LLPI and LPIBI in the input DMA */ -} - -#if HDA_DMA_PTR_DBG - -static void hda_dma_dbg_count_reset(struct dma_chan_data *chan) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(chan); - - hda_chan->dbg_data.cur_sample = 0; -} - -static void hda_dma_get_dbg_vals(struct dma_chan_data *chan, - enum hda_dbg_sample sample, - enum hda_dbg_src src) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(chan); - struct hda_dbg_data *dbg_data = &hda_chan->dbg_data; - - if ((HDA_DBG_SRC == HDA_DBG_BOTH) || (src == HDA_DBG_BOTH) || - (src == HDA_DBG_SRC)) { - dbg_data->last_wp[sample] = dma_chan_reg_read(chan, DGBWP); - dbg_data->last_rp[sample] = dma_chan_reg_read(chan, DGBRP); - dbg_data->last_bne[sample] = (dma_chan_reg_read(chan, DGCS) & - DGCS_BNE) ? 1 : 0; - } -} - -#define hda_dma_ptr_trace(chan, postfix, src) \ - do { \ - struct hda_chan_data *hda_chan = dma_chan_get_data(chan); \ - struct hda_dbg_data *dbg_data = &(hda_chan)->dbg_data; \ - if ((HDA_DBG_SRC == HDA_DBG_BOTH) || (src == HDA_DBG_BOTH) || \ - (src == HDA_DBG_SRC)) { \ - if (dbg_data->cur_sample < HDA_DMA_PTR_DBG_NUM_CP) { \ - uint32_t bne = merge_4b4b(\ - dbg_data->last_bne[HDA_DBG_PRE], \ - dbg_data->last_bne[HDA_DBG_POST]); \ - uint32_t info = \ - merge_16b16b((chan)->direction, bne); \ - uint32_t wp = merge_16b16b(\ - dbg_data->last_wp[HDA_DBG_PRE], \ - dbg_data->last_wp[HDA_DBG_POST]); \ - uint32_t rp = merge_16b16b(\ - dbg_data->last_rp[HDA_DBG_PRE], \ - dbg_data->last_rp[HDA_DBG_POST]); \ - trace_hddma("hda-dma-ptr-trace %08X %08X " \ - "%08X " postfix, info, wp, rp); \ - ++dbg_data->cur_sample; \ - } \ - } \ - } while (0) -#else -#define hda_dma_dbg_count_reset(...) -#define hda_dma_get_dbg_vals(...) -#define hda_dma_ptr_trace(...) -#endif - -static inline int hda_dma_is_buffer_full(struct dma_chan_data *chan) -{ - return dma_chan_reg_read(chan, DGCS) & DGCS_BF; -} - -static inline int hda_dma_is_buffer_empty(struct dma_chan_data *chan) -{ - return !(dma_chan_reg_read(chan, DGCS) & DGCS_BNE); -} - -static int hda_dma_wait_for_buffer_full(struct dma_chan_data *chan) -{ - struct timer *timer = timer_get(); - uint64_t deadline = platform_timer_get(timer) + - clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * - HDA_DMA_TIMEOUT / 1000; - - while (!hda_dma_is_buffer_full(chan)) { - if (deadline < platform_timer_get(timer)) { - /* safe check in case we've got preempted after read */ - if (hda_dma_is_buffer_full(chan)) - return 0; - - trace_hddma_error("hda-dmac: %d wait for buffer full " - "timeout rp 0x%x wp 0x%x", - chan->dma->plat_data.id, - dma_chan_reg_read(chan, DGBRP), - dma_chan_reg_read(chan, DGBWP)); - return -ETIME; - } - } - - return 0; -} - -static int hda_dma_wait_for_buffer_empty(struct dma_chan_data *chan) -{ - struct timer *timer = timer_get(); - uint64_t deadline = platform_timer_get(timer) + - clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * - HDA_DMA_TIMEOUT / 1000; - - while (!hda_dma_is_buffer_empty(chan)) { - if (deadline < platform_timer_get(timer)) { - /* safe check in case we've got preempted after read */ - if (hda_dma_is_buffer_empty(chan)) - return 0; - - trace_hddma_error("hda-dmac: %d wait for buffer empty " - "timeout rp 0x%x wp 0x%x", - chan->dma->plat_data.id, - dma_chan_reg_read(chan, DGBRP), - dma_chan_reg_read(chan, DGBWP)); - return -ETIME; - } - } - - return 0; -} - -static void hda_dma_post_copy(struct dma_chan_data *chan, int bytes) -{ - struct dma_cb_data next = { - .channel = chan, - .elem = { .size = bytes }, - }; - - notifier_event(chan, NOTIFIER_ID_DMA_COPY, - NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); - - if (chan->direction == DMA_DIR_HMEM_TO_LMEM || - chan->direction == DMA_DIR_LMEM_TO_HMEM) { - /* set BFPI to let host gateway know we have read size, - * which will trigger next copy start. - */ - hda_dma_inc_fp(chan, bytes); - - /* Force Host DMA to exit L1 */ - pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); - } else { - /* - * set BFPI to let link gateway know we have read size, - * which will trigger next copy start. - */ - hda_dma_inc_link_fp(chan, bytes); - } -} - -static int hda_dma_link_copy_ch(struct dma_chan_data *chan, int bytes) -{ - int ret = 0; - - tracev_hddma("hda-dmac: %d channel %d -> copy 0x%x bytes", - chan->dma->plat_data.id, chan->index, bytes); - - hda_dma_get_dbg_vals(chan, HDA_DBG_PRE, HDA_DBG_LINK); - - hda_dma_post_copy(chan, bytes); - - hda_dma_get_dbg_vals(chan, HDA_DBG_POST, HDA_DBG_LINK); - hda_dma_ptr_trace(chan, "link copy", HDA_DBG_LINK); - - return ret; -} - -/* lock should be held by caller */ -static void hda_dma_enable_unlock(struct dma_chan_data *channel) -{ - struct hda_chan_data *hda_chan; - - trace_hddma("hda-dmac: %d channel %d -> enable", - channel->dma->plat_data.id, channel->index); - - hda_dma_get_dbg_vals(channel, HDA_DBG_PRE, HDA_DBG_BOTH); - - /* enable the channel */ - dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, - DGCS_GEN | DGCS_FIFORDY); - - /* full buffer is copied at startup */ - hda_chan = dma_chan_get_data(channel); - hda_chan->desc_avail = channel->desc_count; - - /* Force Host DMA to exit L1 */ - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_LMEM_TO_HMEM) - pm_runtime_put(PM_RUNTIME_HOST_DMA_L1, 0); - - /* start link output transfer now */ - if (channel->direction == DMA_DIR_MEM_TO_DEV && - !(hda_chan->state & HDA_STATE_RELEASE)) - hda_dma_inc_link_fp(channel, hda_chan->buffer_bytes); - - hda_chan->state &= ~HDA_STATE_RELEASE; - - hda_dma_get_dbg_vals(channel, HDA_DBG_POST, HDA_DBG_BOTH); - hda_dma_ptr_trace(channel, "enable", HDA_DBG_BOTH); -} - -/* notify DMA to copy bytes */ -static int hda_dma_link_copy(struct dma_chan_data *channel, int bytes, - uint32_t flags) -{ - return hda_dma_link_copy_ch(channel, bytes); -} - -/* notify DMA to copy bytes */ -static int hda_dma_host_copy(struct dma_chan_data *channel, int bytes, - uint32_t flags) -{ - int ret; - - tracev_hddma("hda-dmac: %d channel %d -> copy 0x%x bytes", - channel->dma->plat_data.id, channel->index, bytes); - - hda_dma_get_dbg_vals(channel, HDA_DBG_PRE, HDA_DBG_HOST); - - /* blocking mode copy */ - if (flags & DMA_COPY_BLOCKING) { - ret = channel->direction == DMA_DIR_HMEM_TO_LMEM ? - hda_dma_wait_for_buffer_full(channel) : - hda_dma_wait_for_buffer_empty(channel); - if (ret < 0) - return ret; - } - - hda_dma_post_copy(channel, bytes); - - hda_dma_get_dbg_vals(channel, HDA_DBG_POST, HDA_DBG_HOST); - hda_dma_ptr_trace(channel, "host copy", HDA_DBG_HOST); - - return 0; -} - -/* acquire the specific DMA channel */ -static struct dma_chan_data *hda_dma_channel_get(struct dma *dma, - unsigned int channel) -{ - uint32_t flags; - - if (channel >= dma->plat_data.channels) { - trace_hddma_error("hda-dmac: %d invalid channel %d", - dma->plat_data.id, channel); - return NULL; - } - - spin_lock_irq(&dma->lock, flags); - - trace_hddma("hda-dmac: %d channel %d -> get", dma->plat_data.id, - channel); - - /* use channel if it's free */ - if (dma->chan[channel].status == COMP_STATE_INIT) { - dma->chan[channel].status = COMP_STATE_READY; - - atomic_add(&dma->num_channels_busy, 1); - - /* return channel */ - spin_unlock_irq(&dma->lock, flags); - return &dma->chan[channel]; - } - - /* DMAC has no free channels */ - spin_unlock_irq(&dma->lock, flags); - trace_hddma_error("hda-dmac: %d no free channel %d", dma->plat_data.id, - channel); - return NULL; -} - -/* channel must not be running when this is called */ -static void hda_dma_channel_put_unlocked(struct dma_chan_data *channel) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(channel); - - /* set new state */ - channel->status = COMP_STATE_INIT; - hda_chan->state = 0; - hda_chan->period_bytes = 0; - hda_chan->buffer_bytes = 0; - - /* Make sure that all callbacks to this channel are freed */ - notifier_unregister_all(NULL, channel); -} - -/* channel must not be running when this is called */ -static void hda_dma_channel_put(struct dma_chan_data *channel) -{ - struct dma *dma = channel->dma; - uint32_t flags; - - spin_lock_irq(&dma->lock, flags); - hda_dma_channel_put_unlocked(channel); - spin_unlock_irq(&dma->lock, flags); - - atomic_sub(&dma->num_channels_busy, 1); -} - -static int hda_dma_start(struct dma_chan_data *channel) -{ - uint32_t flags; - uint32_t dgcs; - int ret = 0; - - irq_local_disable(flags); - - trace_hddma("hda-dmac: %d channel %d -> start", - channel->dma->plat_data.id, channel->index); - - hda_dma_dbg_count_reset(channel); - - /* is channel idle, disabled and ready ? */ - dgcs = dma_chan_reg_read(channel, DGCS); - if (channel->status != COMP_STATE_PREPARE || (dgcs & DGCS_GEN)) { - ret = -EBUSY; - trace_hddma_error("hda-dmac: %d channel %d busy. dgcs 0x%x " - "status %d", channel->dma->plat_data.id, - channel->index, dgcs, channel->status); - goto out; - } - - hda_dma_enable_unlock(channel); - - channel->status = COMP_STATE_ACTIVE; - channel->core = cpu_get_id(); - -out: - irq_local_enable(flags); - return ret; -} - -static int hda_dma_release(struct dma_chan_data *channel) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(channel); - uint32_t flags; - - irq_local_disable(flags); - - trace_hddma("hda-dmac: %d channel %d -> release", - channel->dma->plat_data.id, channel->index); - - /* - * Prepare for the handling of release condition on the first work cb. - * This flag will be unset afterwards. - */ - hda_chan->state |= HDA_STATE_RELEASE; - - irq_local_enable(flags); - return 0; -} - -static int hda_dma_pause(struct dma_chan_data *channel) -{ - uint32_t flags; - - irq_local_disable(flags); - - trace_hddma("hda-dmac: %d channel %d -> pause", - channel->dma->plat_data.id, channel->index); - - if (channel->status != COMP_STATE_ACTIVE) - goto out; - - /* pause the channel */ - channel->status = COMP_STATE_PAUSED; - -out: - irq_local_enable(flags); - return 0; -} - -static int hda_dma_stop(struct dma_chan_data *channel) -{ - struct hda_chan_data *hda_chan; - uint32_t flags; - - irq_local_disable(flags); - - hda_dma_dbg_count_reset(channel); - hda_dma_ptr_trace(channel, "last-copy", HDA_DBG_BOTH); - hda_dma_get_dbg_vals(channel, HDA_DBG_PRE, HDA_DBG_BOTH); - - trace_hddma("hda-dmac: %d channel %d -> stop", - channel->dma->plat_data.id, channel->index); - - /* disable the channel */ - dma_chan_reg_update_bits(channel, DGCS, DGCS_GEN | DGCS_FIFORDY, 0); - channel->status = COMP_STATE_PREPARE; - hda_chan = dma_chan_get_data(channel); - hda_chan->state = 0; - - hda_dma_get_dbg_vals(channel, HDA_DBG_POST, HDA_DBG_BOTH); - hda_dma_ptr_trace(channel, "stop", HDA_DBG_BOTH); - - irq_local_enable(flags); - return 0; -} - -/* fill in "status" with current DMA channel state and position */ -static int hda_dma_status(struct dma_chan_data *channel, - struct dma_chan_status *status, uint8_t direction) -{ - status->state = channel->status; - status->r_pos = dma_chan_reg_read(channel, DGBRP); - status->w_pos = dma_chan_reg_read(channel, DGBWP); - status->timestamp = timer_get_system(timer_get()); - - return 0; -} - -/* set the DMA channel configuration, source/target address, buffer sizes */ -static int hda_dma_set_config(struct dma_chan_data *channel, - struct dma_sg_config *config) -{ - struct dma *dma = channel->dma; - struct hda_chan_data *hda_chan; - struct dma_sg_elem *sg_elem; - uint32_t buffer_addr = 0; - uint32_t period_bytes = 0; - uint32_t buffer_bytes = 0; - uint32_t flags; - uint32_t addr; - uint32_t dgcs; - int i; - int ret = 0; - - if (channel->status == COMP_STATE_ACTIVE) - return 0; - - irq_local_disable(flags); - - trace_hddma("hda-dmac: %d channel %d -> config", - dma->plat_data.id, channel->index); - - if (!config->elem_array.count) { - trace_hddma_error("hda-dmac: %d channel %d no DMA descriptors", - dma->plat_data.id, channel->index); - ret = -EINVAL; - goto out; - } - - if ((config->direction & (DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM)) && - !config->irq_disabled) { - trace_hddma_error("hda-dmac: %d channel %d HDA Link DMA " - "doesn't support irq scheduling", - dma->plat_data.id, channel->index); - ret = -EINVAL; - goto out; - } - - /* default channel config */ - channel->direction = config->direction; - channel->desc_count = config->elem_array.count; - channel->is_scheduling_source = config->is_scheduling_source; - channel->period = config->period; - - /* validate - HDA only supports continuous elems of same size */ - for (i = 0; i < config->elem_array.count; i++) { - sg_elem = config->elem_array.elems + i; - - if (config->direction == DMA_DIR_HMEM_TO_LMEM || - config->direction == DMA_DIR_DEV_TO_MEM) - addr = sg_elem->dest; - else - addr = sg_elem->src; - - /* make sure elem is continuous */ - if (buffer_addr && (buffer_addr + buffer_bytes) != addr) { - trace_hddma_error("hda-dmac: %d chan %d - " - "non continuous elem", - dma->plat_data.id, channel->index); - trace_hddma_error(" addr 0x%x buffer 0x%x size 0x%x", - addr, buffer_addr, buffer_bytes); - ret = -EINVAL; - goto out; - } - - /* make sure period_bytes are constant */ - if (period_bytes && period_bytes != sg_elem->size) { - trace_hddma_error("hda-dmac: %d chan %d - period size " - "not constant %d", dma->plat_data.id, - channel->index, period_bytes); - ret = -EINVAL; - goto out; - } - - /* update counters */ - period_bytes = sg_elem->size; - buffer_bytes += period_bytes; - - if (buffer_addr == 0) - buffer_addr = addr; - } - - /* buffer size must be multiple of hda dma burst size */ - if (buffer_bytes % HDA_DMA_BUFFER_ALIGNMENT) { - trace_hddma_error("hda-dmac: %d chan %d - buffer not DMA " - "aligned 0x%x", dma->plat_data.id, - channel->index, buffer_bytes); - ret = -EINVAL; - goto out; - } - hda_chan = dma_chan_get_data(channel); - hda_chan->period_bytes = period_bytes; - hda_chan->buffer_bytes = buffer_bytes; - - /* init channel in HW */ - dma_chan_reg_write(channel, DGBBA, buffer_addr); - dma_chan_reg_write(channel, DGBS, buffer_bytes); - - if (config->direction == DMA_DIR_LMEM_TO_HMEM || - config->direction == DMA_DIR_HMEM_TO_LMEM) - dma_chan_reg_write(channel, DGMBS, - ALIGN_UP(buffer_bytes, - HDA_DMA_BUFFER_ALIGNMENT)); - - /* firmware control buffer */ - dgcs = DGCS_FWCB; - - /* set DGCS.SCS bit to 1 for 16bit(2B) container */ - if ((config->direction & (DMA_DIR_HMEM_TO_LMEM | DMA_DIR_DEV_TO_MEM) && - config->dest_width <= 2) || - (config->direction & (DMA_DIR_LMEM_TO_HMEM | DMA_DIR_MEM_TO_DEV) && - config->src_width <= 2)) - dgcs |= DGCS_SCS; - - /* set DGCS.FIFORDY for output dma */ - if ((config->cyclic && config->direction == DMA_DIR_MEM_TO_DEV) || - (!config->cyclic && config->direction == DMA_DIR_LMEM_TO_HMEM)) - dgcs |= DGCS_FIFORDY; - - dma_chan_reg_write(channel, DGCS, dgcs); - - channel->status = COMP_STATE_PREPARE; -out: - irq_local_enable(flags); - return ret; -} - -/* restore DMA conext after leaving D3 */ -static int hda_dma_pm_context_restore(struct dma *dma) -{ - return 0; -} - -/* store DMA conext after leaving D3 */ -static int hda_dma_pm_context_store(struct dma *dma) -{ - return 0; -} - -static int hda_dma_probe(struct dma *dma) -{ - struct hda_chan_data *hda_chan; - int i; - struct dma_chan_data *chan; - - trace_hddma("hda-dmac :%d -> probe", dma->plat_data.id); - - if (dma->chan) - return -EEXIST; /* already created */ - - dma->chan = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(struct dma_chan_data) * - dma->plat_data.channels); - - if (!dma->chan) { - trace_hddma_error("hda-dmac: %d channels alloc failed", - dma->plat_data.id); - goto out; - } - - /* init channel status */ - chan = dma->chan; - - for (i = 0; i < dma->plat_data.channels; i++, chan++) { - chan->dma = dma; - chan->index = i; - chan->status = COMP_STATE_INIT; - chan->core = DMA_CORE_INVALID; - - hda_chan = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, - SOF_MEM_CAPS_RAM, - sizeof(struct hda_chan_data)); - if (!hda_chan) { - trace_hddma_error("hda-dma: %d channel %d private data " - "alloc failed", dma->plat_data.id, i); - goto out; - } - - dma_chan_set_data(chan, hda_chan); - } - - /* init number of channels draining */ - atomic_init(&dma->num_channels_busy, 0); - - return 0; - -out: - if (dma->chan) { - for (i = 0; i < dma->plat_data.channels; i++) - rfree(dma_chan_get_data(&dma->chan[i])); - rfree(dma->chan); - dma->chan = NULL; - } - - return -ENOMEM; -} - -static int hda_dma_remove(struct dma *dma) -{ - int i; - - trace_hddma("hda-dmac :%d -> remove", dma->plat_data.id); - - for (i = 0; i < dma->plat_data.channels; i++) - rfree(dma_chan_get_data(&dma->chan[i])); - - rfree(dma->chan); - dma->chan = NULL; - - return 0; -} - -static int hda_dma_link_check_xrun(struct dma_chan_data *chan) -{ - uint32_t dgcs = dma_chan_reg_read(chan, DGCS); - - if (chan->direction == DMA_DIR_MEM_TO_DEV && dgcs & DGCS_BUR) { - trace_hddma_error("hda_dma_link_check_xrun() error: underrun detected"); - dma_chan_reg_update_bits(chan, DGCS, DGCS_BUR, DGCS_BUR); - } else if (chan->direction == DMA_DIR_DEV_TO_MEM && dgcs & DGCS_BOR) { - trace_hddma_error("hda_dma_link_check_xrun() error: overrun detected"); - dma_chan_reg_update_bits(chan, DGCS, DGCS_BOR, DGCS_BOR); - } - - return 0; -} - -static int hda_dma_avail_data_size(struct dma_chan_data *chan) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(chan); - uint32_t status; - int32_t read_ptr; - int32_t write_ptr; - int size; - - status = dma_chan_reg_read(chan, DGCS); - - if (status & DGCS_BF) - return hda_chan->buffer_bytes; - - if (!(status & DGCS_BNE)) - return 0; - - read_ptr = dma_chan_reg_read(chan, DGBRP); - write_ptr = dma_chan_reg_read(chan, DGBWP); - - size = write_ptr - read_ptr; - if (size <= 0) - size += hda_chan->buffer_bytes; - - return size; -} - -static int hda_dma_free_data_size(struct dma_chan_data *chan) -{ - struct hda_chan_data *hda_chan = dma_chan_get_data(chan); - uint32_t status; - int32_t read_ptr; - int32_t write_ptr; - int size; - - status = dma_chan_reg_read(chan, DGCS); - - if (status & DGCS_BF) - return 0; - - if (!(status & DGCS_BNE)) - return hda_chan->buffer_bytes; - - read_ptr = dma_chan_reg_read(chan, DGBRP); - write_ptr = dma_chan_reg_read(chan, DGBWP); - - size = read_ptr - write_ptr; - if (size <= 0) - size += hda_chan->buffer_bytes; - - return size; -} - -static int hda_dma_data_size(struct dma_chan_data *channel, - uint32_t *avail, uint32_t *free) -{ - uint32_t flags; - int ret = 0; - - tracev_hddma("hda-dmac: %d channel %d -> get_data_size", - channel->dma->plat_data.id, channel->index); - - irq_local_disable(flags); - - ret = hda_dma_link_check_xrun(channel); - if (ret < 0) - return ret; - - if (channel->direction == DMA_DIR_HMEM_TO_LMEM || - channel->direction == DMA_DIR_DEV_TO_MEM) - *avail = hda_dma_avail_data_size(channel); - else - *free = hda_dma_free_data_size(channel); - - irq_local_enable(flags); - - return ret; -} - -static int hda_dma_get_attribute(struct dma *dma, uint32_t type, - uint32_t *value) -{ - int ret = 0; - - switch (type) { - case DMA_ATTR_BUFFER_ALIGNMENT: - *value = HDA_DMA_BUFFER_ALIGNMENT; - break; - case DMA_ATTR_COPY_ALIGNMENT: - *value = HDA_DMA_COPY_ALIGNMENT; - break; - case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: - *value = HDA_DMA_BUFFER_ADDRESS_ALIGNMENT; - break; - case DMA_ATTR_BUFFER_PERIOD_COUNT: - *value = HDA_DMA_BUFFER_PERIOD_COUNT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int hda_dma_interrupt(struct dma_chan_data *channel, - enum dma_irq_cmd cmd) -{ - /* HDA-DMA doesn't support interrupts */ - return -EINVAL; -} - -const struct dma_ops hda_host_dma_ops = { - .channel_get = hda_dma_channel_get, - .channel_put = hda_dma_channel_put, - .start = hda_dma_start, - .stop = hda_dma_stop, - .copy = hda_dma_host_copy, - .pause = hda_dma_pause, - .release = hda_dma_release, - .status = hda_dma_status, - .set_config = hda_dma_set_config, - .pm_context_restore = hda_dma_pm_context_restore, - .pm_context_store = hda_dma_pm_context_store, - .probe = hda_dma_probe, - .remove = hda_dma_remove, - .get_data_size = hda_dma_data_size, - .get_attribute = hda_dma_get_attribute, - .interrupt = hda_dma_interrupt, -}; - -const struct dma_ops hda_link_dma_ops = { - .channel_get = hda_dma_channel_get, - .channel_put = hda_dma_channel_put, - .start = hda_dma_start, - .stop = hda_dma_stop, - .copy = hda_dma_link_copy, - .pause = hda_dma_pause, - .release = hda_dma_release, - .status = hda_dma_status, - .set_config = hda_dma_set_config, - .pm_context_restore = hda_dma_pm_context_restore, - .pm_context_store = hda_dma_pm_context_store, - .probe = hda_dma_probe, - .remove = hda_dma_remove, - .get_data_size = hda_dma_data_size, - .get_attribute = hda_dma_get_attribute, - .interrupt = hda_dma_interrupt, -}; diff --git a/src/drivers/intel/cavs/hda.c b/src/drivers/intel/cavs/hda.c deleted file mode 100644 index 3b9229f94ff4..000000000000 --- a/src/drivers/intel/cavs/hda.c +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Marcin Maka <marcin.maka@linux.intel.com> - -#include <sof/drivers/hda.h> -#include <sof/drivers/ssp.h> -#include <sof/drivers/timestamp.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/uuid.h> -#include <ipc/dai.h> -#include <ipc/stream.h> - -/* bc9ebe20-4577-41bb-9eed-d0cb236328da */ -DECLARE_SOF_UUID("hda-dai", hda_uuid, 0xbc9ebe20, 0x4577, 0x41bb, - 0x9e, 0xed, 0xd0, 0xcb, 0x23, 0x63, 0x28, 0xda); - -static int hda_trigger(struct dai *dai, int cmd, int direction) -{ - return 0; -} - -static int hda_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) -{ - return 0; -} - -/* get HDA hw params */ -static int hda_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) -{ - /* 0 means variable */ - params->rate = 0; - params->channels = 0; - params->buffer_fmt = 0; - params->frame_fmt = 0; - - return 0; -} - -static int hda_dummy(struct dai *dai) -{ - return 0; -} - -static int hda_get_handshake(struct dai *dai, int direction, int stream_id) -{ - return 0; -} - -static int hda_get_fifo(struct dai *dai, int direction, int stream_id) -{ - return 0; -} - -/* Functions for HW timestamp */ - -static inline uint32_t hda_ts_local_tsctrl_addr(void) -{ - return TIMESTAMP_BASE + TS_HDA_LOCAL_TSCTRL; -} - -static inline uint32_t hda_ts_local_offs_addr(void) -{ - return TIMESTAMP_BASE + TS_HDA_LOCAL_OFFS; -} - -static inline uint32_t hda_ts_local_sample_addr(void) -{ - return TIMESTAMP_BASE + TS_HDA_LOCAL_SAMPLE; -} - -static inline uint32_t hda_ts_local_walclk_addr(void) -{ - return TIMESTAMP_BASE + TS_HDA_LOCAL_WALCLK; -} - -static inline uint32_t hda_ts_tscc_addr(void) -{ - return TIMESTAMP_BASE + TS_HDA_TSCC; -} - -static int hda_ts_config(struct dai *dai, struct timestamp_cfg *cfg) -{ - int i; - - if (cfg->type != SOF_DAI_INTEL_HDA) { - dai_err(dai, "dmic_ts_config(): Illegal DAI type"); - return -EINVAL; - } - - cfg->walclk_rate = 0; - for (i = 0; i < NUM_SSP_FREQ; i++) { - if (ssp_freq_sources[i] == SSP_CLOCK_XTAL_OSCILLATOR) - cfg->walclk_rate = ssp_freq[i].freq; - } - - return 0; -} - -static int hda_ts_start(struct dai *dai, struct timestamp_cfg *cfg) -{ - /* Set HDA timestamp registers */ - uint32_t cdmas; - uint32_t addr = hda_ts_local_tsctrl_addr(); - - /* Set HDA timestamp registers */ - - /* Set CDMAS(4:0) to match DMA engine index and direction - * also clear NTK to be sure there is no old timestamp. - */ - cdmas = TS_LOCAL_TSCTRL_CDMAS(cfg->dma_chan_index | - (cfg->direction == SOF_IPC_STREAM_PLAYBACK ? BIT(4) : 0)); - io_reg_write(addr, TS_LOCAL_TSCTRL_NTK_BIT | cdmas); - - /* Request on demand timestamp */ - io_reg_write(addr, TS_LOCAL_TSCTRL_ODTS_BIT | cdmas); - - return 0; -} - -static int hda_ts_stop(struct dai *dai, struct timestamp_cfg *cfg) -{ - /* Clear NTK and write zero to CDMAS */ - io_reg_write(hda_ts_local_tsctrl_addr(), TS_LOCAL_TSCTRL_NTK_BIT); - return 0; -} - -static int hda_ts_get(struct dai *dai, struct timestamp_cfg *cfg, - struct timestamp_data *tsd) -{ - /* Read HDA timestamp registers */ - uint32_t ntk; - uint32_t tsctrl = hda_ts_local_tsctrl_addr(); - - ntk = io_reg_read(tsctrl) & TS_LOCAL_TSCTRL_NTK_BIT; - if (!ntk) - goto out; - - /* NTK was set, get wall clock */ - tsd->walclk = io_reg_read_64(hda_ts_local_walclk_addr()); - - /* Sample */ - tsd->sample = io_reg_read_64(hda_ts_local_sample_addr()); - - /* Clear NTK to enable successive timestamps */ - io_reg_write(tsctrl, TS_LOCAL_TSCTRL_NTK_BIT); - -out: - tsd->walclk_rate = cfg->walclk_rate; - if (!ntk) - return -ENODATA; - - return 0; -} - -const struct dai_driver hda_driver = { - .type = SOF_DAI_INTEL_HDA, - .uid = SOF_UUID(hda_uuid), - .dma_caps = DMA_CAP_HDA, - .dma_dev = DMA_DEV_HDA, - .ops = { - .trigger = hda_trigger, - .set_config = hda_set_config, - .pm_context_store = hda_dummy, - .pm_context_restore = hda_dummy, - .get_hw_params = hda_get_hw_params, - .get_handshake = hda_get_handshake, - .get_fifo = hda_get_fifo, - .probe = hda_dummy, - .remove = hda_dummy, - }, - .ts_ops = { - .ts_config = hda_ts_config, - .ts_start = hda_ts_start, - .ts_get = hda_ts_get, - .ts_stop = hda_ts_stop, - }, -}; diff --git a/src/drivers/intel/cavs/idc.c b/src/drivers/intel/cavs/idc.c deleted file mode 100644 index 7ae5f9d7ffad..000000000000 --- a/src/drivers/intel/cavs/idc.c +++ /dev/null @@ -1,547 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/audio/component_ext.h> -#include <sof/audio/pipeline.h> -#include <sof/debug/panic.h> -#include <sof/drivers/idc.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/shim.h> -#include <sof/lib/uuid.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <ipc/control.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <xtos-structs.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/** \brief IDC message payload per core. */ -static SHARED_DATA struct idc_payload payload[PLATFORM_CORE_COUNT]; - -/* b90f5a4e-5537-4375-a1df-95485472ff9e */ -DECLARE_SOF_UUID("comp-task", idc_comp_task_uuid, 0xb90f5a4e, 0x5537, 0x4375, - 0xa1, 0xdf, 0x95, 0x48, 0x54, 0x72, 0xff, 0x9e); - -/* a5dacb0e-88dc-415c-a1b5-3e8df77f1976 */ -DECLARE_SOF_UUID("idc-cmd-task", idc_cmd_task_uuid, 0xa5dacb0e, 0x88dc, 0x415c, - 0xa1, 0xb5, 0x3e, 0x8d, 0xf7, 0x7f, 0x19, 0x76); - -/** - * \brief Returns IDC data. - * \return Pointer to pointer of IDC data. - */ -static struct idc **idc_get(void) -{ - struct core_context *ctx = (struct core_context *)cpu_read_threadptr(); - - return &ctx->idc; -} - -/** - * \brief Enables IDC interrupts. - * \param[in] target_core Target core id. - * \param[in] source_core Source core id. - */ -void idc_enable_interrupts(int target_core, int source_core) -{ - struct idc *idc = *idc_get(); - - idc_write(IPC_IDCCTL, target_core, - IPC_IDCCTL_IDCTBIE(source_core)); - interrupt_unmask(idc->irq, target_core); -} - -/** - * \brief IDC interrupt handler. - * \param[in,out] arg Pointer to IDC data. - */ -static void idc_irq_handler(void *arg) -{ - struct idc *idc = arg; - int core = cpu_get_id(); - uint32_t idctfc; - uint32_t idctefc; - uint32_t idcietc; - uint32_t i; - - tracev_idc("idc_irq_handler()"); - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - /* skip current core */ - if (core == i) - continue; - - idctfc = idc_read(IPC_IDCTFC(i), core); - - if (idctfc & IPC_IDCTFC_BUSY) { - trace_idc("idc_irq_handler(), IPC_IDCTFC_BUSY"); - - /* disable BUSY interrupt */ - idc_write(IPC_IDCCTL, core, idc->done_bit_mask); - - idc->received_msg.core = i; - idc->received_msg.header = - idctfc & IPC_IDCTFC_MSG_MASK; - - idctefc = idc_read(IPC_IDCTEFC(i), core); - idc->received_msg.extension = - idctefc & IPC_IDCTEFC_MSG_MASK; - - schedule_task(&idc->idc_task, 0, IDC_DEADLINE); - } - } - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - /* skip current core */ - if (core == i) - continue; - - idcietc = idc_read(IPC_IDCIETC(i), core); - - if (idcietc & IPC_IDCIETC_DONE) { - tracev_idc("idc_irq_handler(), " - "IPC_IDCIETC_DONE"); - - idc_write(IPC_IDCIETC(i), core, - idcietc | IPC_IDCIETC_DONE); - - idc->msg_processed[i] = true; - } - } -} - -/** - * \brief Sets IDC command status after execution. - * \param[in] status Status to be set. - * \param[in] core Id of the core for this status. - */ -static void idc_msg_status_set(int status, uint32_t core) -{ - struct idc *idc = *idc_get(); - struct idc_payload *payload = idc_payload_get(idc, core); - - *(uint32_t *)payload->data = status; - - platform_shared_commit(payload, sizeof(*payload)); -} - -/** - * \brief Retrieves IDC command status after sending message. - * \param[in] core Id of the core for this status. - * \return Last IDC message status. - */ -static int idc_msg_status_get(uint32_t core) -{ - struct idc *idc = *idc_get(); - struct idc_payload *payload = idc_payload_get(idc, core); - int status; - - status = *(uint32_t *)payload->data; - - platform_shared_commit(payload, sizeof(*payload)); - - return status; -} - -/** - * \brief Sends IDC message. - * \param[in,out] msg Pointer to IDC message. - * \param[in] mode Is message blocking or not. - * \return Error code. - */ -int idc_send_msg(struct idc_msg *msg, uint32_t mode) -{ - struct timer *timer = timer_get(); - struct idc *idc = *idc_get(); - struct idc_payload *payload = idc_payload_get(idc, msg->core); - int core = cpu_get_id(); - uint64_t deadline; - int ret = 0; - - tracev_idc("arch_idc_send_msg()"); - - idc->msg_processed[msg->core] = false; - - /* copy payload if available */ - if (msg->payload) { - ret = memcpy_s(payload->data, IDC_MAX_PAYLOAD_SIZE, - msg->payload, msg->size); - assert(!ret); - platform_shared_commit(payload, sizeof(*payload)); - } - - idc_write(IPC_IDCIETC(msg->core), core, msg->extension); - idc_write(IPC_IDCITC(msg->core), core, msg->header | IPC_IDCITC_BUSY); - - if (mode == IDC_BLOCKING) { - deadline = platform_timer_get(timer) + - clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * - IDC_TIMEOUT / 1000; - - while (!idc->msg_processed[msg->core]) { - if (deadline < platform_timer_get(timer)) { - /* safe check in case we've got preempted - * after read - */ - if (idc->msg_processed[msg->core]) - break; - - trace_idc_error("arch_idc_send_msg() error: " - "timeout"); - return -ETIME; - } - } - - ret = idc_msg_status_get(msg->core); - } - - return ret; -} - -/** - * \brief Executes IDC IPC processing message. - */ -static void idc_ipc(void) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_cmd_hdr *hdr = ipc->comp_data; - - ipc_cmd(hdr); -} - -/** - * \brief Executes IDC component params message. - * \param[in] comp_id Component id to have params set. - * \return Error code. - */ -static int idc_params(uint32_t comp_id) -{ - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *ipc_dev; - struct idc *idc = *idc_get(); - struct idc_payload *payload = idc_payload_get(idc, cpu_get_id()); - struct sof_ipc_stream_params *params = - (struct sof_ipc_stream_params *)payload; - int ret; - - ipc_dev = ipc_get_comp_by_id(ipc, comp_id); - if (!ipc_dev) - return -ENODEV; - - ret = comp_params(ipc_dev->cd, params); - - platform_shared_commit(payload, sizeof(*payload)); - platform_shared_commit(ipc_dev, sizeof(*ipc_dev)); - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -static enum task_state comp_task(void *data) -{ - if (comp_copy(data) < 0) - return SOF_TASK_STATE_COMPLETED; - - return SOF_TASK_STATE_RESCHEDULE; -} - -/** - * \brief Executes IDC component prepare message. - * \param[in] comp_id Component id to be prepared. - * \return Error code. - */ -static int idc_prepare(uint32_t comp_id) -{ - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *ipc_dev; - struct comp_dev *dev; - int ret; - - ipc_dev = ipc_get_comp_by_id(ipc, comp_id); - if (!ipc_dev) - return -ENODEV; - - dev = ipc_dev->cd; - - /* we're running on different core, so allocate our own task */ - if (!dev->task) { - /* allocate task for shared component */ - dev->task = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*dev->task)); - if (!dev->task) { - ret = -ENOMEM; - goto out; - } - - ret = schedule_task_init_ll(dev->task, - SOF_UUID(idc_comp_task_uuid), - SOF_SCHEDULE_LL_TIMER, - dev->priority, comp_task, dev, - dev->comp.core, 0); - if (ret < 0) { - rfree(dev->task); - goto out; - } - } - - ret = comp_prepare(ipc_dev->cd); - -out: - platform_shared_commit(dev, sizeof(*dev)); - platform_shared_commit(ipc_dev, sizeof(*ipc_dev)); - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -/** - * \brief Executes IDC component trigger message. - * \param[in] comp_id Component id to be triggered. - * \return Error code. - */ -static int idc_trigger(uint32_t comp_id) -{ - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *ipc_dev; - struct idc *idc = *idc_get(); - struct idc_payload *payload = idc_payload_get(idc, cpu_get_id()); - uint32_t cmd = *(uint32_t *)payload; - int ret; - - ipc_dev = ipc_get_comp_by_id(ipc, comp_id); - if (!ipc_dev) - return -ENODEV; - - ret = comp_trigger(ipc_dev->cd, cmd); - if (ret < 0) - goto out; - - /* schedule or cancel task */ - switch (cmd) { - case COMP_TRIGGER_START: - case COMP_TRIGGER_RELEASE: - schedule_task(ipc_dev->cd->task, 0, ipc_dev->cd->period); - break; - case COMP_TRIGGER_XRUN: - case COMP_TRIGGER_PAUSE: - case COMP_TRIGGER_STOP: - schedule_task_cancel(ipc_dev->cd->task); - break; - } - -out: - platform_shared_commit(payload, sizeof(*payload)); - platform_shared_commit(ipc_dev->cd, sizeof(*ipc_dev->cd)); - platform_shared_commit(ipc_dev, sizeof(*ipc_dev)); - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -/** - * \brief Executes IDC component reset message. - * \param[in] comp_id Component id to be reset. - * \return Error code. - */ -static int idc_reset(uint32_t comp_id) -{ - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *ipc_dev; - int ret; - - ipc_dev = ipc_get_comp_by_id(ipc, comp_id); - if (!ipc_dev) - return -ENODEV; - - ret = comp_reset(ipc_dev->cd); - - platform_shared_commit(ipc_dev, sizeof(*ipc_dev)); - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -/** - * \brief Executes IDC message based on type. - * \param[in,out] msg Pointer to IDC message. - */ -static void idc_cmd(struct idc_msg *msg) -{ - uint32_t type = iTS(msg->header); - int ret = 0; - - switch (type) { - case iTS(IDC_MSG_POWER_DOWN): - cpu_power_down_core(); - break; - case iTS(IDC_MSG_NOTIFY): - notifier_notify_remote(); - break; - case iTS(IDC_MSG_IPC): - idc_ipc(); - break; - case iTS(IDC_MSG_PARAMS): - ret = idc_params(msg->extension); - break; - case iTS(IDC_MSG_PREPARE): - ret = idc_prepare(msg->extension); - break; - case iTS(IDC_MSG_TRIGGER): - ret = idc_trigger(msg->extension); - break; - case iTS(IDC_MSG_RESET): - ret = idc_reset(msg->extension); - break; - default: - trace_idc_error("idc_cmd() error: invalid msg->header = %u", - msg->header); - } - - idc_msg_status_set(ret, cpu_get_id()); -} - -/** - * \brief Handles received IDC message. - * \param[in,out] data Pointer to IDC data. - */ -static enum task_state idc_do_cmd(void *data) -{ - struct idc *idc = data; - int core = cpu_get_id(); - int initiator = idc->received_msg.core; - - trace_idc("idc_do_cmd()"); - - idc_cmd(&idc->received_msg); - - /* clear BUSY bit */ - idc_write(IPC_IDCTFC(initiator), core, - idc_read(IPC_IDCTFC(initiator), core) | IPC_IDCTFC_BUSY); - - /* enable BUSY interrupt */ - idc_write(IPC_IDCCTL, core, idc->busy_bit_mask | idc->done_bit_mask); - - return SOF_TASK_STATE_COMPLETED; -} - -/** - * \brief Returns BUSY interrupt mask based on core id. - * \param[in] core Core id. - * \return BUSY interrupt mask. - */ -static uint32_t idc_get_busy_bit_mask(int core) -{ - uint32_t busy_mask = 0; - int i; - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - if (i != core) - busy_mask |= IPC_IDCCTL_IDCTBIE(i); - } - - return busy_mask; -} - -/** - * \brief Returns DONE interrupt mask based on core id. - * \param[in] core Core id. - * \return DONE interrupt mask. - */ -static uint32_t idc_get_done_bit_mask(int core) -{ - uint32_t done_mask = 0; - int i; - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - if (i != core) - done_mask |= IPC_IDCCTL_IDCIDIE(i); - } - - return done_mask; -} - -/** - * \brief Initializes IDC data and registers for interrupt. - */ -int idc_init(void) -{ - int core = cpu_get_id(); - int ret; - struct task_ops ops = { - .run = idc_do_cmd, - .get_deadline = ipc_task_deadline, - }; - - trace_idc("arch_idc_init()"); - - /* initialize idc data */ - struct idc **idc = idc_get(); - *idc = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(**idc)); - (*idc)->busy_bit_mask = idc_get_busy_bit_mask(core); - (*idc)->done_bit_mask = idc_get_done_bit_mask(core); - (*idc)->payload = cache_to_uncache((struct idc_payload *)payload); - - /* process task */ - schedule_task_init_edf(&(*idc)->idc_task, SOF_UUID(idc_cmd_task_uuid), - &ops, *idc, core, 0); - - /* configure interrupt */ - (*idc)->irq = interrupt_get_irq(PLATFORM_IDC_INTERRUPT, - PLATFORM_IDC_INTERRUPT_NAME); - if ((*idc)->irq < 0) - return (*idc)->irq; - ret = interrupt_register((*idc)->irq, idc_irq_handler, *idc); - if (ret < 0) - return ret; - interrupt_enable((*idc)->irq, *idc); - - /* enable BUSY and DONE interrupts */ - idc_write(IPC_IDCCTL, core, - (*idc)->busy_bit_mask | (*idc)->done_bit_mask); - - return 0; -} - -/** - * \brief Frees IDC data and unregisters interrupt. - */ -void idc_free(void) -{ - struct idc *idc = *idc_get(); - int core = cpu_get_id(); - int i = 0; - uint32_t idctfc; - - trace_idc("idc_free()"); - - /* disable and unregister interrupt */ - interrupt_disable(idc->irq, idc); - interrupt_unregister(idc->irq, idc); - - /* clear BUSY bits */ - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - idctfc = idc_read(IPC_IDCTFC(i), core); - if (idctfc & IPC_IDCTFC_BUSY) - idc_write(IPC_IDCTFC(i), core, idctfc); - } - - schedule_task_free(&idc->idc_task); -} diff --git a/src/drivers/intel/cavs/interrupt.c b/src/drivers/intel/cavs/interrupt.c deleted file mode 100644 index 8510828dcda1..000000000000 --- a/src/drivers/intel/cavs/interrupt.c +++ /dev/null @@ -1,316 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Keyon Jie <yang.jie@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Rander Wang <rander.wang@intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/list.h> -#include <sof/spinlock.h> -#include <config.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* - * Number of status reload tries before warning the user we are in an IRQ - * storm where some device(s) are repeatedly interrupting and cannot be - * cleared. - */ -#define LVL2_MAX_TRIES 1000 - -#if CONFIG_INTERRUPT_LEVEL_2 -const char irq_name_level2[] = "level2"; -#endif -#if CONFIG_INTERRUPT_LEVEL_3 -const char irq_name_level3[] = "level3"; -#endif -#if CONFIG_INTERRUPT_LEVEL_4 -const char irq_name_level4[] = "level4"; -#endif -#if CONFIG_INTERRUPT_LEVEL_5 -const char irq_name_level5[] = "level5"; -#endif - -/* - * The level2 handler attempts to try and fairly service interrupt sources by - * servicing on first come first served basis. If two or more IRQs arrive at the - * same time then they are serviced in order of ascending status bit. - */ -static inline void irq_lvl2_handler(void *data, int level, uint32_t ilxsd, - uint32_t ilxmsd) -{ - struct irq_desc *parent = data; - struct irq_cascade_desc *cascade = container_of(parent, - struct irq_cascade_desc, desc); - struct irq_desc *child = NULL; - int core = cpu_get_id(); - struct list_item *clist; - uint32_t status; - uint32_t tries = LVL2_MAX_TRIES; - - platform_shared_commit(parent, sizeof(*parent)); - - /* read active interrupt status */ - status = irq_read(ilxsd); - if (!status) - return; - - /* handle each child */ - for (;;) { - unsigned int bit = ffs(status) - 1; - bool handled = false; - - status &= ~(1 << bit); - - spin_lock(&cascade->lock); - - /* get child if any and run handler */ - list_for_item(clist, &cascade->child[bit].list) { - child = container_of(clist, struct irq_desc, irq_list); - - if (child->handler && (child->cpu_mask & 1 << core)) { - /* run handler in non atomic context */ - spin_unlock(&cascade->lock); - child->handler(child->handler_arg); - spin_lock(&cascade->lock); - - handled = true; - } - - platform_shared_commit(child, sizeof(*child)); - } - - platform_shared_commit(cascade, sizeof(*cascade)); - - spin_unlock(&cascade->lock); - - if (!handled) { - /* nobody cared ? */ - trace_irq_error("irq_lvl2_handler() error: " - "nobody cared level %d bit %d", - level, bit); - /* now mask it */ - irq_write(ilxmsd, 0x1 << bit); - } - - /* are all IRQs serviced from last status ? */ - if (status) - continue; - - /* yes, so reload the new status and service again */ - status = irq_read(ilxsd); - if (!status) - break; - - /* any devices continually interrupting / can't be cleared ? */ - if (!--tries) { - tries = LVL2_MAX_TRIES; - trace_irq_error("irq_lvl2_handler() error: " - "IRQ storm at level %d status %08X", - level, irq_read(ilxsd)); - } - } -} - -#define IRQ_LVL2_HANDLER(n) int core = cpu_get_id(); \ - irq_lvl2_handler(data, \ - IRQ_NUM_EXT_LEVEL##n, \ - REG_IRQ_IL##n##SD(core), \ - REG_IRQ_IL##n##MSD(core)) - -#if CONFIG_INTERRUPT_LEVEL_2 -static void irq_lvl2_level2_handler(void *data) -{ - IRQ_LVL2_HANDLER(2); -} -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 -static void irq_lvl2_level3_handler(void *data) -{ - IRQ_LVL2_HANDLER(3); -} -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 -static void irq_lvl2_level4_handler(void *data) -{ - IRQ_LVL2_HANDLER(4); -} -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 -static void irq_lvl2_level5_handler(void *data) -{ - IRQ_LVL2_HANDLER(5); -} -#endif - -uint32_t platform_interrupt_get_enabled(void) -{ - return 0; -} - -void interrupt_mask(uint32_t irq, unsigned int cpu) -{ - struct irq_cascade_desc *cascade = interrupt_get_parent(irq); - - if (cascade && cascade->ops->mask) - cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, - cpu); - - platform_shared_commit(cascade, sizeof(*cascade)); -} - -void interrupt_unmask(uint32_t irq, unsigned int cpu) -{ - struct irq_cascade_desc *cascade = interrupt_get_parent(irq); - - if (cascade && cascade->ops->unmask) - cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, - cpu); - - platform_shared_commit(cascade, sizeof(*cascade)); -} - -static void irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) -{ - /* mask external interrupt bit */ - switch (desc->irq) { -#if CONFIG_INTERRUPT_LEVEL_5 - case IRQ_NUM_EXT_LEVEL5: - irq_write(REG_IRQ_IL5MSD(core), 1 << irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_4 - case IRQ_NUM_EXT_LEVEL4: - irq_write(REG_IRQ_IL4MSD(core), 1 << irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - case IRQ_NUM_EXT_LEVEL3: - irq_write(REG_IRQ_IL3MSD(core), 1 << irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - case IRQ_NUM_EXT_LEVEL2: - irq_write(REG_IRQ_IL2MSD(core), 1 << irq); - break; -#endif - } - - platform_shared_commit(desc, sizeof(*desc)); -} - -static void irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) -{ - /* unmask external interrupt bit */ - switch (desc->irq) { -#if CONFIG_INTERRUPT_LEVEL_5 - case IRQ_NUM_EXT_LEVEL5: - irq_write(REG_IRQ_IL5MCD(core), 1 << irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_4 - case IRQ_NUM_EXT_LEVEL4: - irq_write(REG_IRQ_IL4MCD(core), 1 << irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - case IRQ_NUM_EXT_LEVEL3: - irq_write(REG_IRQ_IL3MCD(core), 1 << irq); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - case IRQ_NUM_EXT_LEVEL2: - irq_write(REG_IRQ_IL2MCD(core), 1 << irq); - break; -#endif - } - - platform_shared_commit(desc, sizeof(*desc)); -} - -static const struct irq_cascade_ops irq_ops = { - .mask = irq_mask, - .unmask = irq_unmask, -}; - -/* DSP internal interrupts */ -static const struct irq_cascade_tmpl dsp_irq[] = { -#if CONFIG_INTERRUPT_LEVEL_2 - { - .name = irq_name_level2, - .irq = IRQ_NUM_EXT_LEVEL2, - .handler = irq_lvl2_level2_handler, - .ops = &irq_ops, - .global_mask = false, - }, -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - { - .name = irq_name_level3, - .irq = IRQ_NUM_EXT_LEVEL3, - .handler = irq_lvl2_level3_handler, - .ops = &irq_ops, - .global_mask = false, - }, -#endif -#if CONFIG_INTERRUPT_LEVEL_4 - { - .name = irq_name_level4, - .irq = IRQ_NUM_EXT_LEVEL4, - .handler = irq_lvl2_level4_handler, - .ops = &irq_ops, - .global_mask = false, - }, -#endif -#if CONFIG_INTERRUPT_LEVEL_5 - { - .name = irq_name_level5, - .irq = IRQ_NUM_EXT_LEVEL5, - .handler = irq_lvl2_level5_handler, - .ops = &irq_ops, - .global_mask = false, - }, -#endif -}; - -void platform_interrupt_set(uint32_t irq) -{ - if (interrupt_is_dsp_direct(irq)) - arch_interrupt_set(irq); -} - -void platform_interrupt_clear(uint32_t irq, uint32_t mask) -{ - if (interrupt_is_dsp_direct(irq)) - arch_interrupt_clear(irq); -} - -/* Called on each core: from platform_init() and from slave_core_init() */ -void platform_interrupt_init(void) -{ - int i; - int core = cpu_get_id(); - - /* mask all external IRQs by default */ - irq_write(REG_IRQ_IL2MSD(core), REG_IRQ_IL2MD_ALL); - irq_write(REG_IRQ_IL3MSD(core), REG_IRQ_IL3MD_ALL); - irq_write(REG_IRQ_IL4MSD(core), REG_IRQ_IL4MD_ALL); - irq_write(REG_IRQ_IL5MSD(core), REG_IRQ_IL5MD_ALL); - - if (core != PLATFORM_MASTER_CORE_ID) - return; - - for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) - interrupt_cascade_register(dsp_irq + i); -} diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c deleted file mode 100644 index 74ac22d390a1..000000000000 --- a/src/drivers/intel/cavs/ipc.c +++ /dev/null @@ -1,456 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@intel.com> - -#include <cavs/version.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/uuid.h> -#include <sof/lib/wait.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <ipc/header.h> -#if CAVS_VERSION >= CAVS_VERSION_1_8 -#include <ipc/header-intel-cavs.h> -#include <ipc/pm.h> -#endif -#include <config.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#if CAVS_VERSION >= CAVS_VERSION_1_8 - -#define CAVS_IPC_TYPE_S(x) ((x) & CAVS_IPC_TYPE_MASK) - -#endif - -/* 8fa1d42f-bc6f-464b-867f-547af08834da */ -DECLARE_SOF_UUID("ipc-task", ipc_task_uuid, 0x8fa1d42f, 0xbc6f, 0x464b, - 0x86, 0x7f, 0x54, 0x7a, 0xf0, 0x88, 0x34, 0xda); - -/* No private data for IPC */ - -#if CONFIG_DEBUG_IPC_COUNTERS -static inline void increment_ipc_received_counter(void) -{ - static uint32_t ipc_received_counter; - - mailbox_sw_reg_write(SRAM_REG_FW_IPC_RECEIVED_COUNT, - ipc_received_counter++); -} - -static inline void increment_ipc_processed_counter(void) -{ - static uint32_t ipc_processed_counter; - - mailbox_sw_reg_write(SRAM_REG_FW_IPC_PROCESSED_COUNT, - ipc_processed_counter++); -} -#endif - -/* test code to check working IRQ */ -static void ipc_irq_handler(void *arg) -{ - struct ipc *ipc = arg; - uint32_t dipcctl; - -#if CAVS_VERSION == CAVS_VERSION_1_5 - uint32_t dipct; - uint32_t dipcie; - - dipct = ipc_read(IPC_DIPCT); - dipcie = ipc_read(IPC_DIPCIE); - dipcctl = ipc_read(IPC_DIPCCTL); - - tracev_ipc("ipc: irq dipct 0x%x dipcie 0x%x dipcctl 0x%x", dipct, - dipcie, dipcctl); -#else - uint32_t dipctdr; - uint32_t dipcida; - - dipctdr = ipc_read(IPC_DIPCTDR); - dipcida = ipc_read(IPC_DIPCIDA); - dipcctl = ipc_read(IPC_DIPCCTL); - - tracev_ipc("ipc: irq dipctdr 0x%x dipcida 0x%x dipcctl 0x%x", dipctdr, - dipcida, dipcctl); -#endif - - /* new message from host */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - if (dipct & IPC_DIPCT_BUSY && dipcctl & IPC_DIPCCTL_IPCTBIE) -#else - if (dipctdr & IPC_DIPCTDR_BUSY && dipcctl & IPC_DIPCCTL_IPCTBIE) -#endif - { - /* mask Busy interrupt */ - ipc_write(IPC_DIPCCTL, dipcctl & ~IPC_DIPCCTL_IPCTBIE); - -#if CONFIG_DEBUG_IPC_COUNTERS - increment_ipc_received_counter(); -#endif - - ipc_schedule_process(ipc); - } - - /* reply message(done) from host */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - if (dipcie & IPC_DIPCIE_DONE && dipcctl & IPC_DIPCCTL_IPCIDIE) -#else - if (dipcida & IPC_DIPCIDA_DONE) -#endif - { - /* mask Done interrupt */ - ipc_write(IPC_DIPCCTL, - ipc_read(IPC_DIPCCTL) & ~IPC_DIPCCTL_IPCIDIE); - - /* clear DONE bit - tell host we have completed the operation */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, - ipc_read(IPC_DIPCIE) | IPC_DIPCIE_DONE); -#else - ipc_write(IPC_DIPCIDA, - ipc_read(IPC_DIPCIDA) | IPC_DIPCIDA_DONE); -#endif - - ipc->is_notification_pending = false; - - /* unmask Done interrupt */ - ipc_write(IPC_DIPCCTL, - ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCIDIE); - - /* send next message to host */ - ipc_send_queued_msg(); - } -} - -#if CAVS_VERSION >= CAVS_VERSION_1_8 -static struct sof_ipc_cmd_hdr *ipc_cavs_read_set_d0ix(uint32_t dr, uint32_t dd) -{ - struct sof_ipc_pm_gate *cmd = ipc_get()->comp_data; - - cmd->hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE; - cmd->hdr.size = sizeof(*cmd); - cmd->flags = dd & CAVS_IPC_MOD_SETD0IX_BIT_MASK; - - return &cmd->hdr; -} - -static struct sof_ipc_cmd_hdr *ipc_compact_read_msg(void) -{ - struct sof_ipc_cmd_hdr *hdr; - uint32_t dr; - uint32_t dd; - - dr = ipc_read(IPC_DIPCTDR); - dd = ipc_read(IPC_DIPCTDD); - - /* if there is no cAVS module IPC in regs go the previous path */ - if (!(dr & CAVS_IPC_MSG_TGT)) - return mailbox_validate(); - - switch (CAVS_IPC_TYPE_S(dr)) { - case CAVS_IPC_MOD_SET_D0IX: - hdr = ipc_cavs_read_set_d0ix(dr, dd); - break; - default: - return NULL; - } - - platform_shared_commit(hdr, hdr->size); - - return hdr; -} -#endif - -enum task_state ipc_platform_do_cmd(void *data) -{ -#if !CONFIG_SUECREEK - struct ipc *ipc = data; -#endif - struct sof_ipc_cmd_hdr *hdr; - struct sof_ipc_reply reply; - -#if CAVS_VERSION >= CAVS_VERSION_1_8 - hdr = ipc_compact_read_msg(); -#else - hdr = mailbox_validate(); -#endif - /* perform command */ - if (hdr) - ipc_cmd(hdr); - else { - /* send invalid command error in reply */ - reply.error = -EINVAL; - reply.hdr.cmd = SOF_IPC_GLB_REPLY; - reply.hdr.size = sizeof(reply); - mailbox_hostbox_write(0, &reply, sizeof(reply)); - } - - /* are we about to enter D3 ? */ -#if !CONFIG_SUECREEK - if (ipc->pm_prepare_D3) { - platform_shared_commit(ipc, sizeof(*ipc)); - - /* no return - memory will be powered off and IPC sent */ - platform_pm_runtime_power_off(); - } - - platform_shared_commit(ipc, sizeof(*ipc)); -#endif - - return SOF_TASK_STATE_COMPLETED; -} - -void ipc_platform_complete_cmd(void *data) -{ -#if CONFIG_SUECREEK - struct ipc *ipc = data; -#endif - - /* write 1 to clear busy, and trigger interrupt to host*/ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCT, ipc_read(IPC_DIPCT) | IPC_DIPCT_BUSY); -#else - ipc_write(IPC_DIPCTDR, ipc_read(IPC_DIPCTDR) | IPC_DIPCTDR_BUSY); - ipc_write(IPC_DIPCTDA, ipc_read(IPC_DIPCTDA) | IPC_DIPCTDA_DONE); -#endif - -#if CONFIG_DEBUG_IPC_COUNTERS - increment_ipc_processed_counter(); -#endif - - /* unmask Busy interrupt */ - ipc_write(IPC_DIPCCTL, ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCTBIE); - -#if CONFIG_SUECREEK - if (ipc->pm_prepare_D3) { - platform_shared_commit(ipc, sizeof(*ipc)); - - //TODO: add support for Icelake - while (1) - wait_for_interrupt(0); - } - - platform_shared_commit(ipc, sizeof(*ipc)); -#endif -} - -int ipc_platform_send_msg(struct ipc_msg *msg) -{ - struct ipc *ipc = ipc_get(); - int ret = 0; - - if (ipc->is_notification_pending || -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) { -#else - ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY || - ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE) { -#endif - ret = -EBUSY; - goto out; - } - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - list_item_del(&msg->list); - tracev_ipc("ipc: msg tx -> 0x%x", msg->header); - - ipc->is_notification_pending = true; - - /* now interrupt host to tell it we have message sent */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, 0); - ipc_write(IPC_DIPCI, IPC_DIPCI_BUSY | msg->header); -#else - ipc_write(IPC_DIPCIDD, 0); - ipc_write(IPC_DIPCIDR, 0x80000000 | msg->header); -#endif - - platform_shared_commit(msg, sizeof(*msg)); - -out: - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -int platform_ipc_init(struct ipc *ipc) -{ - int irq; - - ipc_set_drvdata(ipc, NULL); - - /* schedule */ - schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), - &ipc_task_ops, ipc, 0, 0); - - /* configure interrupt */ - irq = interrupt_get_irq(PLATFORM_IPC_INTERRUPT, - PLATFORM_IPC_INTERRUPT_NAME); - if (irq < 0) - return irq; - interrupt_register(irq, ipc_irq_handler, ipc); - interrupt_enable(irq, ipc); - - /* enable IPC interrupts from host */ - ipc_write(IPC_DIPCCTL, IPC_DIPCCTL_IPCIDIE | IPC_DIPCCTL_IPCTBIE); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return 0; -} - -#if CONFIG_IPC_POLLING - -int ipc_platform_poll_init(void) -{ - return 0; -} - -/* tell host we have completed command */ -void ipc_platform_poll_set_cmd_done(void) -{ - - /* write 1 to clear busy, and trigger interrupt to host*/ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCT, ipc_read(IPC_DIPCT) | IPC_DIPCT_BUSY); -#else - ipc_write(IPC_DIPCTDR, ipc_read(IPC_DIPCTDR) | IPC_DIPCTDR_BUSY); - ipc_write(IPC_DIPCTDA, ipc_read(IPC_DIPCTDA) | IPC_DIPCTDA_DONE); -#endif - - /* unmask Busy interrupt */ - ipc_write(IPC_DIPCCTL, ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCTBIE); -} - -/* read the IPC register for any new command messages */ -int ipc_platform_poll_is_cmd_pending(void) -{ - uint32_t dipcctl; - -#if CAVS_VERSION == CAVS_VERSION_1_5 - uint32_t dipct; - - dipct = ipc_read(IPC_DIPCT); - dipcctl = ipc_read(IPC_DIPCCTL); - - -#else - uint32_t dipctdr; - - dipctdr = ipc_read(IPC_DIPCTDR); - dipcctl = ipc_read(IPC_DIPCCTL); -#endif - - /* new message from host */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - if (dipct & IPC_DIPCT_BUSY && dipcctl & IPC_DIPCCTL_IPCTBIE) -#else - if (dipctdr & IPC_DIPCTDR_BUSY && dipcctl & IPC_DIPCCTL_IPCTBIE) -#endif - { - /* mask Busy interrupt */ - ipc_write(IPC_DIPCCTL, dipcctl & ~IPC_DIPCCTL_IPCTBIE); - - /* new message */ - return 1; - } - - /* no new message */ - return 0; -} - -int ipc_platform_poll_is_host_ready(void) -{ -#if CAVS_VERSION == CAVS_VERSION_1_5 - uint32_t dipcie; - uint32_t dipcctl; - - dipcie = ipc_read(IPC_DIPCIE); - dipcctl = ipc_read(IPC_DIPCCTL); - - -#else - uint32_t dipcida; - - dipcida = ipc_read(IPC_DIPCIDA); -#endif - - /* reply message(done) from host */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - if (dipcie & IPC_DIPCIE_DONE && dipcctl & IPC_DIPCCTL_IPCIDIE) -#else - if (dipcida & IPC_DIPCIDA_DONE) -#endif - { - /* mask Done interrupt */ - ipc_write(IPC_DIPCCTL, - ipc_read(IPC_DIPCCTL) & ~IPC_DIPCCTL_IPCIDIE); - - /* clear DONE bit - tell host we have completed the operation */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, - ipc_read(IPC_DIPCIE) | IPC_DIPCIE_DONE); -#else - ipc_write(IPC_DIPCIDA, - ipc_read(IPC_DIPCIDA) | IPC_DIPCIDA_DONE); -#endif - - /* unmask Done interrupt */ - ipc_write(IPC_DIPCCTL, - ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCIDIE); - - /* host has completed */ - return 1; - } - - /* host still pending */ - return 0; -} - - - -int ipc_platform_poll_tx_host_msg(struct ipc_msg *msg) -{ - -#if CAVS_VERSION == CAVS_VERSION_1_5 - if (ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) -#else - if (ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY || - ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE) -#endif - /* cant send message atm */ - return 0; - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - - /* now interrupt host to tell it we have message sent */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, 0); - ipc_write(IPC_DIPCI, IPC_DIPCI_BUSY | msg->header); -#else - ipc_write(IPC_DIPCIDD, 0); - ipc_write(IPC_DIPCIDR, 0x80000000 | msg->header); -#endif - - /* message sent */ - platform_shared_commit(msg, sizeof(*msg)); - return 1; -} - -#endif diff --git a/src/drivers/intel/cavs/mn.c b/src/drivers/intel/cavs/mn.c deleted file mode 100644 index f056d84381a4..000000000000 --- a/src/drivers/intel/cavs/mn.c +++ /dev/null @@ -1,526 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2020 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/drivers/mn.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/math/numbers.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <stdbool.h> -#include <stdint.h> - -/* tracing */ -#define trace_mn(__e, ...) \ - trace_event(TRACE_CLASS_MN, __e, ##__VA_ARGS__) -#define trace_mn_error(__e, ...) \ - trace_error(TRACE_CLASS_MN, __e, ##__VA_ARGS__) -#define tracev_mn(__e, ...) \ - tracev_event(TRACE_CLASS_MN, __e, ##__VA_ARGS__) - -/** \brief BCLKs can be driven by multiple sources - M/N or XTAL directly. - * Even in the case of M/N, the actual clock source can be XTAL, - * Audio cardinal clock (24.576) or 96 MHz PLL. - * The MN block is not really the source of clocks, but rather - * an intermediate component. - * Input for source is shared by all outputs coming from that source - * and once it's in use, it can be adjusted only with dividers. - * In order to change input, the source should not be in use, that's why - * it's necessary to keep track of BCLKs sources to know when it's safe - * to change shared input clock. - */ -enum bclk_source { - MN_BCLK_SOURCE_NONE = 0, /**< port is not using any clock */ - MN_BCLK_SOURCE_MN, /**< port is using clock driven by M/N */ - MN_BCLK_SOURCE_XTAL, /**< port is using XTAL directly */ -}; - -struct mn { - /**< keep track of which MCLKs are in use to know when it's safe to - * change shared clock - */ - bool mclk_sources_used[DAI_NUM_SSP_MCLK]; - int mclk_source_clock; - - enum bclk_source bclk_sources[(DAI_NUM_SSP_BASE + DAI_NUM_SSP_EXT)]; - int bclk_source_mn_clock; - - spinlock_t lock; /**< lock mechanism */ -}; - -static SHARED_DATA struct mn mn; - -void mn_init(struct sof *sof) -{ - int i; - - sof->mn = cache_to_uncache(&mn); - - for (i = 0; i < ARRAY_SIZE(sof->mn->bclk_sources); i++) - sof->mn->bclk_sources[i] = MN_BCLK_SOURCE_NONE; - - spinlock_init(&sof->mn->lock); - - platform_shared_commit(sof->mn, sizeof(*sof->mn)); -} - -/** - * \brief Checks if given clock is used as source for any MCLK. - * \param[in] clk_src MCLK source. - * \return true if any port use given clock source, false otherwise. - */ -static inline bool is_mclk_source_in_use(void) -{ - struct mn *mn = mn_get(); - bool ret = false; - int i; - - for (i = 0; i < ARRAY_SIZE(mn->mclk_sources_used); i++) { - if (mn->mclk_sources_used[i]) { - ret = true; - break; - } - } - - platform_shared_commit(mn, sizeof(*mn)); - - return ret; -} - -/** - * \brief Configures source clock for MCLK. - * All MCLKs share the same source, so it should be changed - * only if there are no other ports using it already. - * \param[in] mclk_rate master clock frequency. - * \return 0 on success, error code otherwise. - */ -static inline int setup_initial_mclk_source(uint32_t mclk_rate) -{ - struct mn *mn = mn_get(); - int i; - int clk_index = -1; - uint32_t mdivc = mn_reg_read(MN_MDIVCTRL); - int ret = 0; - - /* searching the smallest possible mclk source */ - for (i = MAX_SSP_FREQ_INDEX; i >= 0; i--) { - if (mclk_rate > ssp_freq[i].freq) - break; - - if (ssp_freq[i].freq % mclk_rate == 0) - clk_index = i; - } - - if (clk_index < 0) { - trace_mn_error("error: MCLK %d, no valid source", - mclk_rate); - ret = -EINVAL; - goto out; - } - - mn->mclk_source_clock = clk_index; - - /* enable MCLK divider */ - mdivc |= MN_MDIVCTRL_M_DIV_ENABLE; - - /* select source clock */ - mdivc |= MCDSS(ssp_freq_sources[clk_index]); - - mn_reg_write(MN_MDIVCTRL, mdivc); - -out: - platform_shared_commit(mn, sizeof(*mn)); - - return ret; -} - -/** - * \brief Checks if requested MCLK can be achieved with current source. - * \param[in] mclk_rate master clock frequency. - * \return 0 on success, error code otherwise. - */ -static inline int check_current_mclk_source(uint32_t mclk_rate) -{ - struct mn *mn = mn_get(); - int ret = 0; - - if (ssp_freq[mn->mclk_source_clock].freq % mclk_rate != 0) { - trace_mn_error("error: MCLK %d, no valid configuration for already selected source = %d", - mclk_rate, mn->mclk_source_clock); - ret = -EINVAL; - } - - platform_shared_commit(mn, sizeof(*mn)); - - return ret; -} - -/** - * \brief Sets MCLK divider to given value. - * \param[in] mclk_id ID of MCLK. - * \param[in] mdivr_val divider value. - * \return 0 on success, error code otherwise. - */ -static inline int set_mclk_divider(uint16_t mclk_id, uint32_t mdivr_val) -{ - uint32_t mdivr; - - switch (mdivr_val) { - case 1: - mdivr = 0x00000fff; /* bypass divider for MCLK */ - break; - case 2: - mdivr = 0x0; /* 1/2 */ - break; - case 4: - mdivr = 0x2; /* 1/4 */ - break; - case 8: - mdivr = 0x6; /* 1/8 */ - break; - default: - trace_mn_error("error: invalid mdivr_val %d", mdivr_val); - return -EINVAL; - } - - mn_reg_write(MN_MDIVR(mclk_id), mdivr); - return 0; -} - -int mn_set_mclk(uint16_t mclk_id, uint32_t mclk_rate) -{ - struct mn *mn = mn_get(); - int ret = 0; - - if (mclk_id >= DAI_NUM_SSP_MCLK) { - trace_mn_error("error: mclk ID (%d) >= %d", - mclk_id, DAI_NUM_SSP_MCLK); - return -EINVAL; - } - - spin_lock(&mn->lock); - - mn->mclk_sources_used[mclk_id] = false; - - if (is_mclk_source_in_use()) - ret = check_current_mclk_source(mclk_rate); - else - ret = setup_initial_mclk_source(mclk_rate); - - if (ret < 0) - goto out; - - mn->mclk_sources_used[mclk_id] = true; - - ret = set_mclk_divider(mclk_id, - ssp_freq[mn->mclk_source_clock].freq / - mclk_rate); - -out: - platform_shared_commit(mn, sizeof(*mn)); - - spin_unlock(&mn->lock); - - return ret; -} - -void mn_release_mclk(uint32_t mclk_id) -{ - struct mn *mn = mn_get(); - - spin_lock(&mn->lock); - mn->mclk_sources_used[mclk_id] = false; - platform_shared_commit(mn, sizeof(*mn)); - spin_unlock(&mn->lock); -} - -/** - * \brief Finds valid M/(N * SCR) values for given frequencies. - * \param[in] freq SSP clock frequency. - * \param[in] bclk Bit clock frequency. - * \param[out] out_scr_div SCR divisor. - * \param[out] out_m M value of M/N divider. - * \param[out] out_n N value of M/N divider. - * \return true if found suitable values, false otherwise. - */ -static bool find_mn(uint32_t freq, uint32_t bclk, - uint32_t *out_scr_div, uint32_t *out_m, uint32_t *out_n) -{ - uint32_t m, n, mn_div; - uint32_t scr_div = freq / bclk; - - /* check if just SCR is enough */ - if (freq % bclk == 0 && scr_div < (SSCR0_SCR_MASK >> 8) + 1) { - *out_scr_div = scr_div; - *out_m = 1; - *out_n = 1; - - return true; - } - - /* M/(N * scr_div) has to be less than 1/2 */ - if ((bclk * 2) >= freq) - return false; - - /* odd SCR gives lower duty cycle */ - if (scr_div > 1 && scr_div % 2 != 0) - --scr_div; - - /* clamp to valid SCR range */ - scr_div = MIN(scr_div, (SSCR0_SCR_MASK >> 8) + 1); - - /* find highest even divisor */ - while (scr_div > 1 && freq % scr_div != 0) - scr_div -= 2; - - /* compute M/N with smallest dividend and divisor */ - mn_div = gcd(bclk, freq / scr_div); - - m = bclk / mn_div; - n = freq / scr_div / mn_div; - - /* M/N values can be up to 24 bits */ - if (n & (~0xffffff)) - return false; - - *out_scr_div = scr_div; - *out_m = m; - *out_n = n; - - return true; -} - -/** - * \brief Finds index of clock valid for given BCLK rate. - * Clock that can use just SCR is preferred. - * M/N other than 1/1 is used only if there are no other possibilities. - * \param[in] bclk Bit clock frequency. - * \param[out] scr_div SCR divisor. - * \param[out] m M value of M/N divider. - * \param[out] n N value of M/N divider. - * \return index of suitable clock if could find it, -1 otherwise. - */ -static int find_bclk_source(uint32_t bclk, - uint32_t *scr_div, uint32_t *m, uint32_t *n) -{ - int i; - - /* searching the smallest possible bclk source */ - for (i = 0; i <= MAX_SSP_FREQ_INDEX; i++) - if (ssp_freq[i].freq % bclk == 0) { - *scr_div = ssp_freq[i].freq / bclk; - return i; - } - - /* check if we can get target BCLK with M/N */ - for (i = 0; i <= MAX_SSP_FREQ_INDEX; i++) - if (find_mn(ssp_freq[i].freq, bclk, - scr_div, m, n)) - return i; - - return -1; -} - -/** - * \brief Checks if given clock is used as source for any BCLK. - * \param[in] clk_src Bit clock source. - * \return true if any port use given clock source, false otherwise. - */ -static inline bool is_bclk_source_in_use(enum bclk_source clk_src) -{ - struct mn *mn = mn_get(); - bool ret = false; - int i; - - for (i = 0; i < ARRAY_SIZE(mn->bclk_sources); i++) { - if (mn->bclk_sources[i] == clk_src) { - ret = true; - break; - } - } - - platform_shared_commit(mn, sizeof(*mn)); - - return ret; -} - -/** - * \brief Configures M/N source clock for BCLK. - * All ports that use M/N share the same source, so it should be changed - * only if there are no other ports using M/N already. - * \param[in] bclk Bit clock frequency. - * \param[out] scr_div SCR divisor. - * \param[out] m M value of M/N divider. - * \param[out] n N value of M/N divider. - * \return 0 on success, error code otherwise. - */ -static inline int setup_initial_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, - uint32_t *m, uint32_t *n) -{ - struct mn *mn = mn_get(); - int clk_index = find_bclk_source(bclk, scr_div, m, n); - - if (clk_index < 0) { - trace_mn_error("error: BCLK %d, no valid source", bclk); - return -EINVAL; - } - - mn->bclk_source_mn_clock = clk_index; - - mn_reg_write(MN_MDIVCTRL, (mn_reg_read(MN_MDIVCTRL) | - MNDSS(ssp_freq_sources[clk_index]))); - - platform_shared_commit(mn, sizeof(*mn)); - - return 0; -} - -/** - * \brief Finds valid M/(N * SCR) values for source clock that is already locked - * because other ports use it. - * \param[in] bclk Bit clock frequency. - * \param[out] scr_div SCR divisor. - * \param[out] m M value of M/N divider. - * \param[out] n N value of M/N divider. - * \return 0 on success, error code otherwise. - */ -static inline int setup_current_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, - uint32_t *m, uint32_t *n) -{ - struct mn *mn = mn_get(); - int ret = 0; - - /* source for M/N is already set, no need to do it */ - if (find_mn(ssp_freq[mn->bclk_source_mn_clock].freq, bclk, scr_div, m, - n)) - goto out; - - trace_mn_error("error: BCLK %d, no valid configuration for already selected source = %d", - bclk, mn->bclk_source_mn_clock); - ret = -EINVAL; - -out: - platform_shared_commit(mn, sizeof(*mn)); - - return ret; -} - -#if CAVS_VERSION >= CAVS_VERSION_2_0 -static inline bool check_bclk_xtal_source(uint32_t bclk, bool mn_in_use, - uint32_t *scr_div) -{ - /* since cAVS 2.0 bypassing XTAL (ECS=0) is not supported */ - return false; -} -#else -/** - * \brief Checks if XTAL source for BCLK should be used. - * Before cAVS 2.0 BCLK could use XTAL directly (without M/N). - * BCLK that use M/N = 1/1 or bypass XTAL is preferred. - * \param[in] bclk Bit clock frequency. - * \param[in] mn_in_use True if M/N source is already locked by another port. - * \param[out] scr_div SCR divisor. - * \return true if XTAL source should be used, false otherwise. - */ -static inline bool check_bclk_xtal_source(uint32_t bclk, bool mn_in_use, - uint32_t *scr_div) -{ - struct mn *mn = mn_get(); - bool ret = false; - int i; - - for (i = 0; i <= MAX_SSP_FREQ_INDEX; i++) { - if (ssp_freq[i].freq % bclk != 0) - continue; - - if (ssp_freq_sources[i] == SSP_CLOCK_XTAL_OSCILLATOR) { - /* XTAL turned out to be lowest source that can work - * just with SCR, so use it - */ - *scr_div = ssp_freq[i].freq / bclk; - ret = true; - break; - } - - /* if M/N is already set up for desired clock, - * we can quit and let M/N logic handle it - */ - if (!mn_in_use || mn->bclk_source_mn_clock == i) - break; - } - - platform_shared_commit(mn, sizeof(*mn)); - - return ret; -} -#endif - -int mn_set_bclk(uint32_t dai_index, uint32_t bclk_rate, - uint32_t *out_scr_div, bool *out_need_ecs) -{ - struct mn *mn = mn_get(); - uint32_t m = 1; - uint32_t n = 1; - int ret = 0; - bool mn_in_use; - - spin_lock(&mn->lock); - - mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; - - mn_in_use = is_bclk_source_in_use(MN_BCLK_SOURCE_MN); - - if (check_bclk_xtal_source(bclk_rate, mn_in_use, out_scr_div)) { - mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_XTAL; - *out_need_ecs = false; - goto out; - } - - *out_need_ecs = true; - - if (mn_in_use) - ret = setup_current_bclk_mn_source(bclk_rate, - out_scr_div, &m, &n); - else - ret = setup_initial_bclk_mn_source(bclk_rate, - out_scr_div, &m, &n); - - if (ret >= 0) { - mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_MN; - - mn_reg_write(MN_MDIV_M_VAL(dai_index), m); - mn_reg_write(MN_MDIV_N_VAL(dai_index), n); - } - -out: - platform_shared_commit(mn, sizeof(*mn)); - - spin_unlock(&mn->lock); - - return ret; -} - -void mn_release_bclk(uint32_t dai_index) -{ - struct mn *mn = mn_get(); - - spin_lock(&mn->lock); - mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; - platform_shared_commit(mn, sizeof(*mn)); - spin_unlock(&mn->lock); -} - -void mn_reset_bclk_divider(uint32_t dai_index) -{ - struct mn *mn = mn_get(); - - spin_lock(&mn->lock); - mn_reg_write(MN_MDIV_M_VAL(dai_index), 1); - mn_reg_write(MN_MDIV_N_VAL(dai_index), 1); - spin_unlock(&mn->lock); -} diff --git a/src/drivers/intel/cavs/ssp.c b/src/drivers/intel/cavs/ssp.c deleted file mode 100644 index dc266cb6236c..000000000000 --- a/src/drivers/intel/cavs/ssp.c +++ /dev/null @@ -1,1016 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/common.h> -#include <sof/drivers/mn.h> -#include <sof/drivers/timestamp.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/uuid.h> -#include <sof/lib/wait.h> -#include <sof/platform.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/dai-intel.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stdbool.h> -#include <stdint.h> - -/* 31458125-95c4-4085-8f3f-497434cb2daf */ -DECLARE_SOF_UUID("ssp-dai", ssp_uuid, 0x31458125, 0x95c4, 0x4085, - 0x8f, 0x3f, 0x49, 0x74, 0x34, 0xcb, 0x2d, 0xaf); - -/* empty SSP transmit FIFO */ -static void ssp_empty_tx_fifo(struct dai *dai) -{ - uint32_t sssr; - - sssr = ssp_read(dai, SSSR); - - /* clear interrupt */ - if (sssr & SSSR_TUR) - ssp_write(dai, SSSR, sssr); -} - -/* empty SSP receive FIFO */ -static void ssp_empty_rx_fifo(struct dai *dai) -{ - uint32_t sssr; - uint32_t entries; - uint32_t i; - - sssr = ssp_read(dai, SSSR); - - /* clear interrupt */ - if (sssr & SSSR_ROR) - ssp_write(dai, SSSR, sssr); - - /* empty fifo */ - if (sssr & SSSR_RNE) { - entries = SSCR3_RFL_VAL(ssp_read(dai, SSCR3)); - for (i = 0; i < entries + 1; i++) - ssp_read(dai, SSDR); - } -} - -/* save SSP context prior to entering D3 */ -static int ssp_context_store(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - ssp->sscr0 = ssp_read(dai, SSCR0); - ssp->sscr1 = ssp_read(dai, SSCR1); - - /* FIXME: need to store sscr2,3,4,5 */ - ssp->psp = ssp_read(dai, SSPSP); - - return 0; -} - -/* restore SSP context after leaving D3 */ -static int ssp_context_restore(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - ssp_write(dai, SSCR0, ssp->sscr0); - ssp_write(dai, SSCR1, ssp->sscr1); - /* FIXME: need to restore sscr2,3,4,5 */ - ssp_write(dai, SSPSP, ssp->psp); - - return 0; -} - -/* Digital Audio interface formatting */ -static int ssp_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - uint32_t sscr0; - uint32_t sscr1; - uint32_t sscr2; - uint32_t sscr3; - uint32_t sspsp; - uint32_t sspsp2; - uint32_t sstsa; - uint32_t ssrsa; - uint32_t ssto; - uint32_t ssioc; - uint32_t mdiv; - uint32_t bdiv; - uint32_t data_size; - uint32_t frame_end_padding; - uint32_t slot_end_padding; - uint32_t frame_len = 0; - uint32_t bdiv_min; - uint32_t tft; - uint32_t rft; - uint32_t active_tx_slots = 2; - uint32_t active_rx_slots = 2; - uint32_t sample_width = 2; - - bool inverted_bclk = false; - bool inverted_frame = false; - bool cfs = false; - bool start_delay = false; - bool need_ecs; - - int ret = 0; - - spin_lock(&dai->lock); - - /* is playback/capture already running */ - if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE || - ssp->state[DAI_DIR_CAPTURE] == COMP_STATE_ACTIVE) { - dai_info(dai, "ssp_set_config() error: playback/capture already running"); - ret = -EINVAL; - goto out; - } - - dai_info(dai, "ssp_set_config(), config->format = 0x%4x", - config->format); - - /* reset SSP settings */ - /* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */ - /* - * FIXME: MOD, ACS, NCS are not set, - * no support for network mode for now - */ - sscr0 = SSCR0_PSP | SSCR0_RIM | SSCR0_TIM; - - /* sscr1 dynamic settings are SFRMDIR, SCLKDIR, SCFR */ - sscr1 = SSCR1_TTE | SSCR1_TTELP | SSCR1_TRAIL | SSCR1_RSRE | SSCR1_TSRE; - - /* sscr2 dynamic setting is LJDFD */ - sscr2 = SSCR2_SDFD | SSCR2_TURM1; - - /* sscr3 dynamic settings are TFT, RFT */ - sscr3 = 0; - - /* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */ - sspsp = 0; - - ssp->config = *config; - ssp->params = config->ssp; - - /* sspsp2 no dynamic setting */ - sspsp2 = 0x0; - - /* ssioc dynamic setting is SFCR */ - ssioc = SSIOC_SCOE; - - /* ssto no dynamic setting */ - ssto = 0x0; - - /* sstsa dynamic setting is TTSA, default 2 slots */ - sstsa = SSTSA_SSTSA(config->ssp.tx_slots); - - /* ssrsa dynamic setting is RTSA, default 2 slots */ - ssrsa = SSRSA_SSRSA(config->ssp.rx_slots); - - switch (config->format & SOF_DAI_FMT_MASTER_MASK) { - case SOF_DAI_FMT_CBM_CFM: - sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; - break; - case SOF_DAI_FMT_CBS_CFS: - sscr1 |= SSCR1_SCFR; - cfs = true; - break; - case SOF_DAI_FMT_CBM_CFS: - sscr1 |= SSCR1_SCLKDIR; - /* FIXME: this mode has not been tested */ - - cfs = true; - break; - case SOF_DAI_FMT_CBS_CFM: - sscr1 |= SSCR1_SCFR | SSCR1_SFRMDIR; - /* FIXME: this mode has not been tested */ - break; - default: - dai_err(dai, "ssp_set_config() error: format & MASTER_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - /* clock signal polarity */ - switch (config->format & SOF_DAI_FMT_INV_MASK) { - case SOF_DAI_FMT_NB_NF: - break; - case SOF_DAI_FMT_NB_IF: - inverted_frame = true; /* handled later with format */ - break; - case SOF_DAI_FMT_IB_IF: - inverted_bclk = true; /* handled later with bclk idle */ - inverted_frame = true; /* handled later with format */ - break; - case SOF_DAI_FMT_IB_NF: - inverted_bclk = true; /* handled later with bclk idle */ - break; - default: - dai_err(dai, "ssp_set_config() error: format & INV_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - /* supporting bclk idle state */ - if (ssp->params.clks_control & - SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH) { - /* bclk idle state high */ - sspsp |= SSPSP_SCMODE((inverted_bclk ^ 0x3) & 0x3); - } else { - /* bclk idle state low */ - sspsp |= SSPSP_SCMODE(inverted_bclk); - } - - sscr0 |= SSCR0_MOD | SSCR0_ACS; - - /* Additional hardware settings */ - - /* Receiver Time-out Interrupt Disabled/Enabled */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_TINTE) ? - SSCR1_TINTE : 0; - - /* Peripheral Trailing Byte Interrupts Disable/Enable */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PINTE) ? - SSCR1_PINTE : 0; - - /* Enable/disable internal loopback. Output of transmit serial - * shifter connected to input of receive serial shifter, internally. - */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_LBM) ? - SSCR1_LBM : 0; - - /* Transmit data are driven at the same/opposite clock edge specified - * in SSPSP.SCMODE[1:0] - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_SMTATF) ? - SSCR2_SMTATF : 0; - - /* Receive data are sampled at the same/opposite clock edge specified - * in SSPSP.SCMODE[1:0] - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_MMRATF) ? - SSCR2_MMRATF : 0; - - /* Enable/disable the fix for PSP slave mode TXD wait for frame - * de-assertion before starting the second channel - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD) ? - SSCR2_PSPSTWFDFD : 0; - - /* Enable/disable the fix for PSP master mode FSRT with dummy stop & - * frame end padding capability - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD) ? - SSCR2_PSPSRWFDFD : 0; - - if (!config->ssp.mclk_rate || - config->ssp.mclk_rate > ssp_freq[MAX_SSP_FREQ_INDEX].freq) { - dai_err(dai, "ssp_set_config() error: invalid MCLK = %d Hz (valid < %d)", - config->ssp.mclk_rate, - ssp_freq[MAX_SSP_FREQ_INDEX].freq); - ret = -EINVAL; - goto out; - } - - if (!config->ssp.bclk_rate || - config->ssp.bclk_rate > config->ssp.mclk_rate) { - dai_err(dai, "ssp_set_config() error: BCLK %d Hz = 0 or > MCLK %d Hz", - config->ssp.bclk_rate, config->ssp.mclk_rate); - ret = -EINVAL; - goto out; - } - - /* MCLK config */ - ret = mn_set_mclk(config->ssp.mclk_id, config->ssp.mclk_rate); - if (ret < 0) { - dai_err(dai, "error: invalid mclk_rate = %d for mclk_id = %d", - config->ssp.mclk_id, config->ssp.mclk_rate); - goto out; - } - - /* BCLK config */ - ret = mn_set_bclk(config->dai_index, config->ssp.bclk_rate, - &mdiv, &need_ecs); - if (ret < 0) { - dai_err(dai, "error: invalid bclk_rate = %d for dai_index = %d", - config->ssp.bclk_rate, config->dai_index); - goto out; - } - - if (need_ecs) - sscr0 |= SSCR0_ECS; - - /* clock divisor is SCR + 1 */ - mdiv -= 1; - - /* divisor must be within SCR range */ - if (mdiv > (SSCR0_SCR_MASK >> 8)) { - dai_err(dai, "ssp_set_config() error: divisor %d is not within SCR range", - mdiv); - ret = -EINVAL; - goto out; - } - - /* set the SCR divisor */ - sscr0 |= SSCR0_SCR(mdiv); - - /* calc frame width based on BCLK and rate - must be divisable */ - if (config->ssp.bclk_rate % config->ssp.fsync_rate) { - dai_err(dai, "ssp_set_config() error: BCLK %d is not divisable by rate %d", - config->ssp.bclk_rate, config->ssp.fsync_rate); - ret = -EINVAL; - goto out; - } - - /* must be enough BCLKs for data */ - bdiv = config->ssp.bclk_rate / config->ssp.fsync_rate; - if (bdiv < config->ssp.tdm_slot_width * config->ssp.tdm_slots) { - dai_err(dai, "ssp_set_config() error: not enough BCLKs need %d", - config->ssp.tdm_slot_width * - config->ssp.tdm_slots); - ret = -EINVAL; - goto out; - } - - /* tdm_slot_width must be <= 38 for SSP */ - if (config->ssp.tdm_slot_width > 38) { - dai_err(dai, "ssp_set_config() error: tdm_slot_width %d > 38", - config->ssp.tdm_slot_width); - ret = -EINVAL; - goto out; - } - - bdiv_min = config->ssp.tdm_slots * - (config->ssp.tdm_per_slot_padding_flag ? - config->ssp.tdm_slot_width : config->ssp.sample_valid_bits); - if (bdiv < bdiv_min) { - dai_err(dai, "ssp_set_config() error: bdiv(%d) < bdiv_min(%d)", - bdiv, bdiv_min); - ret = -EINVAL; - goto out; - } - - frame_end_padding = bdiv - bdiv_min; - if (frame_end_padding > SSPSP2_FEP_MASK) { - dai_err(dai, "ssp_set_config() error: frame_end_padding too big: %u", - frame_end_padding); - ret = -EINVAL; - goto out; - } - - /* format */ - switch (config->format & SOF_DAI_FMT_FORMAT_MASK) { - case SOF_DAI_FMT_I2S: - - start_delay = true; - - sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots); - - if (bdiv % 2) { - dai_err(dai, "ssp_set_config() error: bdiv %d is not divisible by 2", - bdiv); - ret = -EINVAL; - goto out; - } - - /* set asserted frame length to half frame length */ - frame_len = bdiv / 2; - - /* - * handle frame polarity, I2S default is falling/active low, - * non-inverted(inverted_frame=0) -- active low(SFRMP=0), - * inverted(inverted_frame=1) -- rising/active high(SFRMP=1), - * so, we should set SFRMP to inverted_frame. - */ - sspsp |= SSPSP_SFRMP(inverted_frame); - - /* - * for I2S/LEFT_J, the padding has to happen at the end - * of each slot - */ - if (frame_end_padding % 2) { - dai_err(dai, "ssp_set_config() error: frame_end_padding %d is not divisible by 2", - frame_end_padding); - ret = -EINVAL; - goto out; - } - - slot_end_padding = frame_end_padding / 2; - - if (slot_end_padding > SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX) { - /* too big padding */ - dai_err(dai, "ssp_set_config() error: slot_end_padding > %d", - SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX); - ret = -EINVAL; - goto out; - } - - sspsp |= SSPSP_DMYSTOP(slot_end_padding); - slot_end_padding >>= SSPSP_DMYSTOP_BITS; - sspsp |= SSPSP_EDMYSTOP(slot_end_padding); - - break; - - case SOF_DAI_FMT_LEFT_J: - - /* default start_delay value is set to false */ - - sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots); - - /* LJDFD enable */ - sscr2 &= ~SSCR2_LJDFD; - - if (bdiv % 2) { - dai_err(dai, "ssp_set_config() error: bdiv %d is not divisible by 2", - bdiv); - ret = -EINVAL; - goto out; - } - - /* set asserted frame length to half frame length */ - frame_len = bdiv / 2; - - /* - * handle frame polarity, LEFT_J default is rising/active high, - * non-inverted(inverted_frame=0) -- active high(SFRMP=1), - * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), - * so, we should set SFRMP to !inverted_frame. - */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - - /* - * for I2S/LEFT_J, the padding has to happen at the end - * of each slot - */ - if (frame_end_padding % 2) { - dai_err(dai, "ssp_set_config() error: frame_end_padding %d is not divisible by 2", - frame_end_padding); - ret = -EINVAL; - goto out; - } - - slot_end_padding = frame_end_padding / 2; - - if (slot_end_padding > 15) { - /* can't handle padding over 15 bits */ - dai_err(dai, "ssp_set_config() error: slot_end_padding %d > 15 bits", - slot_end_padding); - ret = -EINVAL; - goto out; - } - - sspsp |= SSPSP_DMYSTOP(slot_end_padding); - slot_end_padding >>= SSPSP_DMYSTOP_BITS; - sspsp |= SSPSP_EDMYSTOP(slot_end_padding); - - break; - case SOF_DAI_FMT_DSP_A: - - start_delay = true; - - /* fallthrough */ - - case SOF_DAI_FMT_DSP_B: - - /* default start_delay value is set to false */ - - sscr0 |= SSCR0_MOD | SSCR0_FRDC(config->ssp.tdm_slots); - - /* set asserted frame length */ - frame_len = 1; /* default */ - - if (cfs && ssp->params.frame_pulse_width > 0 && - ssp->params.frame_pulse_width <= - SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) { - frame_len = ssp->params.frame_pulse_width; - } - - /* frame_pulse_width must less or equal 38 */ - if (ssp->params.frame_pulse_width > - SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX) { - dai_err(dai, "ssp_set_config() error: frame_pulse_width > %d", - SOF_DAI_INTEL_SSP_FRAME_PULSE_WIDTH_MAX); - ret = -EINVAL; - goto out; - } - /* - * handle frame polarity, DSP_B default is rising/active high, - * non-inverted(inverted_frame=0) -- active high(SFRMP=1), - * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), - * so, we should set SFRMP to !inverted_frame. - */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - - active_tx_slots = popcount(config->ssp.tx_slots); - active_rx_slots = popcount(config->ssp.rx_slots); - - /* - * handle TDM mode, TDM mode has padding at the end of - * each slot. The amount of padding is equal to result of - * subtracting slot width and valid bits per slot. - */ - if (ssp->params.tdm_per_slot_padding_flag) { - frame_end_padding = bdiv - config->ssp.tdm_slots * - config->ssp.tdm_slot_width; - - slot_end_padding = config->ssp.tdm_slot_width - - config->ssp.sample_valid_bits; - - if (slot_end_padding > - SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX) { - dai_err(dai, "ssp_set_config() error: slot_end_padding > %d", - SOF_DAI_INTEL_SSP_SLOT_PADDING_MAX); - ret = -EINVAL; - goto out; - } - - sspsp |= SSPSP_DMYSTOP(slot_end_padding); - slot_end_padding >>= SSPSP_DMYSTOP_BITS; - sspsp |= SSPSP_EDMYSTOP(slot_end_padding); - } - - sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK); - - break; - default: - dai_err(dai, "ssp_set_config() error: invalid format 0x%04x", - config->format); - ret = -EINVAL; - goto out; - } - - if (start_delay) - sspsp |= SSPSP_FSRT; - - sspsp |= SSPSP_SFRMWDTH(frame_len); - - data_size = config->ssp.sample_valid_bits; - - if (data_size > 16) - sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16)); - else - sscr0 |= SSCR0_DSIZE(data_size); - - /* setting TFT and RFT */ - switch (config->ssp.sample_valid_bits) { - case 16: - /* use 2 bytes for each slot */ - sample_width = 2; - break; - case 24: - case 32: - /* use 4 bytes for each slot */ - sample_width = 4; - break; - default: - dai_err(dai, "ssp_set_config() error: sample_valid_bits %d", - config->ssp.sample_valid_bits); - ret = -EINVAL; - goto out; - } - - tft = MIN(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK, - sample_width * active_tx_slots); - rft = MIN(SSP_FIFO_DEPTH - SSP_FIFO_WATERMARK, - sample_width * active_rx_slots); - - sscr3 |= SSCR3_TX(tft) | SSCR3_RX(rft); - - ssp_write(dai, SSCR0, sscr0); - ssp_write(dai, SSCR1, sscr1); - ssp_write(dai, SSCR2, sscr2); - ssp_write(dai, SSCR3, sscr3); - ssp_write(dai, SSPSP, sspsp); - ssp_write(dai, SSPSP2, sspsp2); - ssp_write(dai, SSIOC, ssioc); - ssp_write(dai, SSTO, ssto); - ssp_write(dai, SSTSA, sstsa); - ssp_write(dai, SSRSA, ssrsa); - - dai_info(dai, "ssp_set_config(), sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", - sscr0, sscr1, ssto, sspsp); - dai_info(dai, "ssp_set_config(), sscr2 = 0x%08x, sspsp2 = 0x%08x, sscr3 = 0x%08x, ssioc = 0x%08x", - sscr2, sspsp2, sscr3, ssioc); - dai_info(dai, "ssp_set_config(), ssrsa = 0x%08x, sstsa = 0x%08x", - ssrsa, sstsa); - - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_PREPARE; - ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE; - -out: - platform_shared_commit(ssp, sizeof(*ssp)); - - spin_unlock(&dai->lock); - - return ret; -} - -/* get SSP hw params */ -static int ssp_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - params->rate = ssp->params.fsync_rate; - params->buffer_fmt = 0; - - if (dir == SOF_IPC_STREAM_PLAYBACK) - params->channels = popcount(ssp->params.tx_slots); - else - params->channels = popcount(ssp->params.rx_slots); - - switch (ssp->params.sample_valid_bits) { - case 16: - params->frame_fmt = SOF_IPC_FRAME_S16_LE; - break; - case 24: - params->frame_fmt = SOF_IPC_FRAME_S24_4LE; - break; - case 32: - params->frame_fmt = SOF_IPC_FRAME_S32_LE; - break; - default: - dai_err(dai, "ssp_get_hw_params(): not supported format"); - return -EINVAL; - } - - return 0; -} - -/* start the SSP for either playback or capture */ -static void ssp_start(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - spin_lock(&dai->lock); - - /* enable port */ - ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); - ssp->state[direction] = COMP_STATE_ACTIVE; - - dai_info(dai, "ssp_start()"); - - if (ssp->params.bclk_delay) { - /* drive BCLK early for guaranteed time, - * before first FSYNC, it is required by some codecs - */ - wait_delay(clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, - ssp->params.bclk_delay)); - } - - /* enable DMA */ - if (direction == DAI_DIR_PLAYBACK) { - ssp_update_bits(dai, SSCR1, SSCR1_TSRE, SSCR1_TSRE); - ssp_update_bits(dai, SSTSA, SSTSA_TXEN, SSTSA_TXEN); - } else { - ssp_update_bits(dai, SSCR1, SSCR1_RSRE, SSCR1_RSRE); - ssp_update_bits(dai, SSRSA, SSRSA_RXEN, SSRSA_RXEN); - } - - /* wait to get valid fifo status */ - wait_delay(PLATFORM_SSP_DELAY); - - spin_unlock(&dai->lock); -} - -/* stop the SSP for either playback or capture */ -static void ssp_stop(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - spin_lock(&dai->lock); - - /* wait to get valid fifo status */ - wait_delay(PLATFORM_SSP_DELAY); - - /* stop Rx if neeed */ - if (direction == DAI_DIR_CAPTURE && - ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0); - ssp_update_bits(dai, SSRSA, SSRSA_RXEN, 0); - ssp_empty_rx_fifo(dai); - ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE; - dai_info(dai, "ssp_stop(), RX stop"); - } - - /* stop Tx if needed */ - if (direction == DAI_DIR_PLAYBACK && - ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) { - ssp_empty_tx_fifo(dai); - ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0); - ssp_update_bits(dai, SSTSA, SSTSA_TXEN, 0); - ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE; - dai_info(dai, "ssp_stop(), TX stop"); - } - - /* disable SSP port if no users */ - if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE && - ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0); - dai_info(dai, "ssp_stop(), SSP port disabled"); - } - - spin_unlock(&dai->lock); -} - -static void ssp_pause(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - if (direction == SOF_IPC_STREAM_CAPTURE) - dai_info(dai, "ssp_pause(), RX"); - else - dai_info(dai, "ssp_pause(), TX"); - - ssp->state[direction] = COMP_STATE_PAUSED; -} - -static int ssp_trigger(struct dai *dai, int cmd, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - dai_info(dai, "ssp_trigger() cmd %d", cmd); - - switch (cmd) { - case COMP_TRIGGER_START: - if (ssp->state[direction] == COMP_STATE_PREPARE || - ssp->state[direction] == COMP_STATE_PAUSED) - ssp_start(dai, direction); - break; - case COMP_TRIGGER_RELEASE: - if (ssp->state[direction] == COMP_STATE_PAUSED || - ssp->state[direction] == COMP_STATE_PREPARE) - ssp_start(dai, direction); - break; - case COMP_TRIGGER_STOP: - ssp_stop(dai, direction); - break; - case COMP_TRIGGER_PAUSE: - ssp_pause(dai, direction); - break; - case COMP_TRIGGER_RESUME: - ssp_context_restore(dai); - break; - case COMP_TRIGGER_SUSPEND: - ssp_context_store(dai); - break; - default: - break; - } - - platform_shared_commit(ssp, sizeof(*ssp)); - - return 0; -} - -static int ssp_probe(struct dai *dai) -{ - struct ssp_pdata *ssp; - - if (dai_get_drvdata(dai)) - return -EEXIST; /* already created */ - - /* allocate private data */ - ssp = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*ssp)); - if (!ssp) { - dai_err(dai, "ssp_probe() error: alloc failed"); - return -ENOMEM; - } - dai_set_drvdata(dai, ssp); - - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY; - ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY; - - /* Reset M/N, power-gating functions need it */ - mn_reset_bclk_divider(dai->index); - - /* Enable SSP power */ - pm_runtime_get_sync(SSP_POW, dai->index); - - /* Disable dynamic clock gating before touching any register */ - pm_runtime_get_sync(SSP_CLK, dai->index); - - ssp_empty_rx_fifo(dai); - - platform_shared_commit(ssp, sizeof(*ssp)); - - return 0; -} - -static int ssp_remove(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - pm_runtime_put_sync(SSP_CLK, dai->index); - - mn_release_mclk(ssp->config.ssp.mclk_id); - mn_release_bclk(dai->index); - - /* Disable SSP power */ - pm_runtime_put_sync(SSP_POW, dai->index); - - rfree(dai_get_drvdata(dai)); - dai_set_drvdata(dai, NULL); - - return 0; -} - -static int ssp_get_handshake(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[direction].handshake; -} - -static int ssp_get_fifo(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[direction].offset; -} - -/* Functions for HW timestamp */ - -static inline uint32_t ssp_ts_local_tsctrl_addr(int index) -{ -#if CONFIG_APOLLOLAKE - /* TSCTRL registers for SSP0, 1, 2, and 3 are in continuous - * registers space while SSP4 and more are handled with other - * macro. - */ - if (index < DAI_NUM_SSP_BASE) - return TIMESTAMP_BASE + TS_I2S_LOCAL_TSCTRL(index); - else - return TIMESTAMP_BASE + TS_I2SE_LOCAL_TSCTRL(index); -#else - return TIMESTAMP_BASE + TS_I2S_LOCAL_TSCTRL(index); -#endif -} - -static inline uint32_t ssp_ts_local_offs_addr(int index) -{ -#if CONFIG_APOLLOLAKE - if (index < DAI_NUM_SSP_BASE) - return TIMESTAMP_BASE + TS_I2S_LOCAL_OFFS(index); - else - return TIMESTAMP_BASE + TS_I2SE_LOCAL_OFFS(index); -#else - return TIMESTAMP_BASE + TS_I2S_LOCAL_OFFS(index); -#endif -} - -static inline uint32_t ssp_ts_local_sample_addr(int index) -{ -#if CONFIG_APOLLOLAKE - if (index < DAI_NUM_SSP_BASE) - return TIMESTAMP_BASE + TS_I2S_LOCAL_SAMPLE(index); - else - return TIMESTAMP_BASE + TS_I2SE_LOCAL_SAMPLE(index); -#else - return TIMESTAMP_BASE + TS_I2S_LOCAL_SAMPLE(index); -#endif -} - -static inline uint32_t ssp_ts_local_walclk_addr(int index) -{ -#if CONFIG_APOLLOLAKE - if (index < DAI_NUM_SSP_BASE) - return TIMESTAMP_BASE + TS_I2S_LOCAL_WALCLK(index); - else - return TIMESTAMP_BASE + TS_I2SE_LOCAL_WALCLK(index); -#else - return TIMESTAMP_BASE + TS_I2S_LOCAL_WALCLK(index); -#endif -} - -static inline uint32_t ssp_ts_tscc_addr(int index) -{ -#if CONFIG_APOLLOLAKE - if (index < DAI_NUM_SSP_BASE) - return TIMESTAMP_BASE + TS_I2S_TSCC(index); - else - return TIMESTAMP_BASE + TS_I2SE_TSCC(index); -#else - return TIMESTAMP_BASE + TS_I2S_TSCC(index); -#endif -} - -static int ssp_ts_config(struct dai *dai, struct timestamp_cfg *cfg) -{ - int i; - - if (cfg->type != SOF_DAI_INTEL_SSP) { - dai_err(dai, "ssp_ts_config(): Illegal DAI type"); - return -EINVAL; - } - - if (cfg->index > DAI_NUM_SSP_BASE + DAI_NUM_SSP_EXT - 1) { - dai_err(dai, "ssp_ts_config(): Illegal DAI index"); - return -EINVAL; - } - - cfg->walclk_rate = 0; - for (i = 0; i < NUM_SSP_FREQ; i++) { - if (ssp_freq_sources[i] == SSP_CLOCK_XTAL_OSCILLATOR) - cfg->walclk_rate = ssp_freq[i].freq; - } - - if (!cfg->walclk_rate) { - dai_err(dai, "ssp_ts_config(): No XTAL frequency defined"); - return -EINVAL; - } - - return 0; -} - -static int ssp_ts_start(struct dai *dai, struct timestamp_cfg *cfg) -{ - uint32_t cdmas; - uint32_t addr = ssp_ts_local_tsctrl_addr(cfg->index); - - /* Set SSP timestamp registers */ - - /* First point CDMAS to GPDMA channel that is used by this SSP, - * also clear NTK to be sure there is no old timestamp. - */ - cdmas = TS_LOCAL_TSCTRL_CDMAS(cfg->dma_chan_index + - cfg->dma_chan_count * cfg->dma_id); - io_reg_write(addr, TS_LOCAL_TSCTRL_NTK_BIT | cdmas); - - /* Request on demand timestamp */ - io_reg_write(addr, TS_LOCAL_TSCTRL_ODTS_BIT | cdmas); - - return 0; -} - -static int ssp_ts_stop(struct dai *dai, struct timestamp_cfg *cfg) -{ - /* Clear NTK and write zero to CDMAS */ - io_reg_write(ssp_ts_local_tsctrl_addr(cfg->index), - TS_LOCAL_TSCTRL_NTK_BIT); - return 0; -} - -static int ssp_ts_get(struct dai *dai, struct timestamp_cfg *cfg, - struct timestamp_data *tsd) -{ - uint32_t ntk; - uint32_t tsctrl = ssp_ts_local_tsctrl_addr(cfg->index); - - /* Read SSP timestamp registers */ - ntk = io_reg_read(tsctrl) & TS_LOCAL_TSCTRL_NTK_BIT; - if (!ntk) - goto out; - - /* NTK was set, get wall clock */ - tsd->walclk = io_reg_read_64(ssp_ts_local_walclk_addr(cfg->index)); - - /* Sample */ - tsd->sample = io_reg_read_64(ssp_ts_local_sample_addr(cfg->index)); - - /* Clear NTK to enable successive timestamps */ - io_reg_write(tsctrl, TS_LOCAL_TSCTRL_NTK_BIT); - -out: - tsd->walclk_rate = cfg->walclk_rate; - if (!ntk) - return -ENODATA; - - return 0; -} - -const struct dai_driver ssp_driver = { - .type = SOF_DAI_INTEL_SSP, - .uid = SOF_UUID(ssp_uuid), - .dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, - .dma_dev = DMA_DEV_SSP, - .ops = { - .trigger = ssp_trigger, - .set_config = ssp_set_config, - .pm_context_store = ssp_context_store, - .pm_context_restore = ssp_context_restore, - .get_hw_params = ssp_get_hw_params, - .get_handshake = ssp_get_handshake, - .get_fifo = ssp_get_fifo, - .probe = ssp_probe, - .remove = ssp_remove, - }, - .ts_ops = { - .ts_config = ssp_ts_config, - .ts_start = ssp_ts_start, - .ts_get = ssp_ts_get, - .ts_stop = ssp_ts_stop, - }, -}; diff --git a/src/drivers/intel/cavs/sue-iomux.c b/src/drivers/intel/cavs/sue-iomux.c deleted file mode 100644 index 3bc13d90d60d..000000000000 --- a/src/drivers/intel/cavs/sue-iomux.c +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> - -#include <sof/drivers/iomux.h> -#include <sof/lib/io.h> -#include <errno.h> -#include <stddef.h> - -#define IOMUX_PIN_UNCONFIGURED 0 - -int iomux_configure(struct iomux *iomux, const struct iomux_pin_config *cfg) -{ - if (iomux->pin_state[cfg->bit] != IOMUX_PIN_UNCONFIGURED) - return -EBUSY; - - io_reg_update_bits(iomux->base, cfg->mask << cfg->bit, - cfg->fn << cfg->bit); - - iomux->pin_state[cfg->bit] = cfg->fn + 1; - - return 0; -} - -struct iomux *iomux_get(unsigned int id) -{ - return id >= n_iomux ? NULL : iomux_data + id; -} - -int iomux_probe(struct iomux *iomux) -{ - unsigned int i; - - for (i = 0; i < n_iomux; i++) - if (iomux_data + i == iomux) - return 0; - - return -ENODEV; -} diff --git a/src/drivers/intel/cavs/sue-ipc.c b/src/drivers/intel/cavs/sue-ipc.c deleted file mode 100644 index 07365ea447a5..000000000000 --- a/src/drivers/intel/cavs/sue-ipc.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@intel.com> - -#include <sof/drivers/ipc.h> -#include <sof/drivers/spi.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/lib/wait.h> -#include <sof/list.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <ipc/header.h> -#include <stddef.h> -#include <stdint.h> - -/* 7552b3a1-98dd-4419-ad6f-fbf21ebfceec */ -DECLARE_SOF_UUID("ipc-task", ipc_task_uuid, 0x7552b3a1, 0x98dd, 0x4419, - 0xad, 0x6f, 0xfb, 0xf2, 0x1e, 0xbf, 0xce, 0xec); - -/* No private data for IPC */ -enum task_state ipc_platform_do_cmd(void *data) -{ - struct ipc *ipc = data; - struct sof_ipc_cmd_hdr *hdr; - struct sof_ipc_reply reply; - - /* perform command */ - hdr = mailbox_validate(); - ipc_cmd(hdr); - - mailbox_hostbox_read(&reply, SOF_IPC_MSG_MAX_SIZE, - 0, sizeof(reply)); - spi_push(spi_get(SOF_SPI_INTEL_SLAVE), &reply, sizeof(reply)); - - // TODO: signal audio work to enter D3 in normal context - /* are we about to enter D3 ? */ - if (ipc->pm_prepare_D3) { - platform_shared_commit(ipc, sizeof(*ipc)); - - while (1) - wait_for_interrupt(0); - } - - return SOF_TASK_STATE_COMPLETED; -} - -void ipc_platform_complete_cmd(void *data) -{ -} - -int ipc_platform_send_msg(struct ipc_msg *msg) -{ - struct ipc *ipc = ipc_get(); - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - list_item_del(&msg->list); - tracev_ipc("ipc: msg tx -> 0x%x", msg->header); - - /* now interrupt host to tell it we have message sent */ - - platform_shared_commit(ipc, sizeof(*ipc)); - - return 0; -} - -int platform_ipc_init(struct ipc *ipc) -{ - ipc_set_drvdata(ipc, NULL); - - /* schedule */ - schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), - &ipc_task_ops, ipc, 0, 0); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return 0; -} diff --git a/src/drivers/intel/cavs/timer.c b/src/drivers/intel/cavs/timer.c deleted file mode 100644 index fe8714274ff3..000000000000 --- a/src/drivers/intel/cavs/timer.c +++ /dev/null @@ -1,206 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/audio/component_ext.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/platform.h> -#include <ipc/stream.h> -#include <stdint.h> - -void platform_timer_start(struct timer *timer) -{ - /* run timer */ - shim_write64(SHIM_DSPWCT0C, 0); - shim_write(SHIM_DSPWCTCS, - shim_read(SHIM_DSPWCTCS) | SHIM_DSPWCTCS_T0A); -} - -void platform_timer_stop(struct timer *timer) -{ - /* stop timer */ - shim_write64(SHIM_DSPWCT0C, 0); - shim_write(SHIM_DSPWCTCS, - shim_read(SHIM_DSPWCTCS) & ~SHIM_DSPWCTCS_T0A); -} - -int64_t platform_timer_set(struct timer *timer, uint64_t ticks) -{ - /* a tick value of 0 will not generate an IRQ */ - if (ticks == 0) - ticks = 1; - - /* Check if requested time is not past time */ - if (ticks > shim_read64(SHIM_DSPWC)) - shim_write64(SHIM_DSPWCT0C, ticks); - else - shim_write64(SHIM_DSPWCT0C, shim_read64(SHIM_DSPWC) + 1); - - /* Enable IRQ */ - shim_write(SHIM_DSPWCTCS, SHIM_DSPWCTCS_T0A); - - return shim_read64(SHIM_DSPWCT0C); -} - -void platform_timer_clear(struct timer *timer) -{ - /* write 1 to clear the timer interrupt */ - shim_write(SHIM_DSPWCTCS, SHIM_DSPWCTCS_T0T); -} - -uint64_t platform_timer_get(struct timer *timer) -{ -// return arch_timer_get_system(timer); - return (uint64_t)shim_read64(SHIM_DSPWC); -} - -/* get timestamp for host stream DMA position */ -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn) -{ - int err; - - /* get host position */ - err = comp_position(host, posn); - if (err == 0) - posn->flags |= SOF_TIME_HOST_VALID; -} - -/* get timestamp for DAI stream DMA position */ -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn) -{ - int err; - - /* get DAI position */ - err = comp_position(dai, posn); - if (err == 0) - posn->flags |= SOF_TIME_DAI_VALID; - - /* get SSP wallclock - DAI sets this to stream start value */ - posn->wallclock = shim_read64(SHIM_DSPWC) - posn->wallclock; - posn->wallclock_hz = clock_get_freq(PLATFORM_DEFAULT_CLOCK); - posn->flags |= SOF_TIME_WALL_VALID; -} - -/* get current wallclock for componnent */ -void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) -{ - *wallclock = shim_read64(SHIM_DSPWC); -} - -static int platform_timer_register(struct timer *timer, - void (*handler)(void *arg), void *arg) -{ - int err; - - /* register timer interrupt */ - timer->logical_irq = interrupt_get_irq(timer->irq, timer->irq_name); - if (timer->logical_irq < 0) - return timer->logical_irq; - - err = interrupt_register(timer->logical_irq, handler, arg); - if (err < 0) - return err; - - /* enable timer interrupt */ - interrupt_enable(timer->logical_irq, arg); - - /* disable timer interrupt on core level */ - timer_disable(timer, arg, cpu_get_id()); - - return err; -} - -int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) -{ - int ret; - - switch (timer->id) { - case TIMER0: - case TIMER1: - case TIMER2: - ret = arch_timer_register(timer, handler, arg); - break; - case TIMER3: - case TIMER4: - ret = platform_timer_register(timer, handler, arg); - break; - default: - ret = -EINVAL; - break; - } - - platform_shared_commit(timer, sizeof(*timer)); - - return ret; -} - -static void platform_timer_unregister(struct timer *timer, void *arg) -{ - /* disable timer interrupt */ - interrupt_disable(timer->logical_irq, arg); - - /* unregister timer interrupt */ - interrupt_unregister(timer->logical_irq, arg); -} - -void timer_unregister(struct timer *timer, void *arg) -{ - switch (timer->id) { - case TIMER0: - case TIMER1: - case TIMER2: - interrupt_unregister(timer->logical_irq, arg); - break; - case TIMER3: - case TIMER4: - platform_timer_unregister(timer, arg); - break; - } - - platform_shared_commit(timer, sizeof(*timer)); -} - -void timer_enable(struct timer *timer, void *arg, int core) -{ - switch (timer->id) { - case TIMER0: - case TIMER1: - case TIMER2: - interrupt_enable(timer->logical_irq, arg); - break; - case TIMER3: - case TIMER4: - interrupt_unmask(timer->logical_irq, core); - break; - } - - platform_shared_commit(timer, sizeof(*timer)); -} - -void timer_disable(struct timer *timer, void *arg, int core) -{ - switch (timer->id) { - case TIMER0: - case TIMER1: - case TIMER2: - interrupt_disable(timer->logical_irq, arg); - break; - case TIMER3: - case TIMER4: - interrupt_mask(timer->logical_irq, core); - break; - } - - platform_shared_commit(timer, sizeof(*timer)); -} diff --git a/src/drivers/intel/haswell/CMakeLists.txt b/src/drivers/intel/haswell/CMakeLists.txt deleted file mode 100644 index 2582290b7786..000000000000 --- a/src/drivers/intel/haswell/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof - interrupt.c - ssp.c - ipc.c - timer.c -) diff --git a/src/drivers/intel/haswell/interrupt.c b/src/drivers/intel/haswell/interrupt.c deleted file mode 100644 index d6137a2e79fc..000000000000 --- a/src/drivers/intel/haswell/interrupt.c +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/lib/shim.h> -#include <config.h> -#include <stdint.h> - -void platform_interrupt_init(void) {} - -void platform_interrupt_set(uint32_t irq) -{ - arch_interrupt_set(irq); -} - -/* clear mask in PISR, bits are W1C in docs but some bits need preserved ?? */ -void platform_interrupt_clear(uint32_t irq, uint32_t mask) -{ - switch (irq) { -#if CONFIG_INTERRUPT_LEVEL_1 - case IRQ_NUM_EXT_SSP0: - case IRQ_NUM_EXT_SSP1: - case IRQ_NUM_EXT_IA: - case IRQ_NUM_SOFTWARE1: -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - case IRQ_NUM_EXT_DMAC0: -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - case IRQ_NUM_EXT_DMAC1: - case IRQ_NUM_SOFTWARE2: -#endif -#if CONFIG_INTERRUPT_LEVEL_1 || CONFIG_INTERRUPT_LEVEL_2 || \ - CONFIG_INTERRUPT_LEVEL_3 - arch_interrupt_clear(irq); - break; -#endif - default: - break; - } -} - -/* TODO: expand this to 64 bit - should we just return mask of IRQ numbers */ -uint32_t platform_interrupt_get_enabled(void) -{ - return shim_read(SHIM_IMRD); -} - -void interrupt_mask(uint32_t irq, unsigned int cpu) -{ - switch (irq) { -#if CONFIG_INTERRUPT_LEVEL_1 - case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_IMRD, SHIM_IMRD_SSP0); - break; - case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_IMRD, SHIM_IMRD_SSP1); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_IMRD, SHIM_IMRD_DMAC0); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_IMRD, SHIM_IMRD_DMAC1); - break; -#endif - default: - break; - } -} - -void interrupt_unmask(uint32_t irq, unsigned int cpu) -{ - switch (irq) { -#if CONFIG_INTERRUPT_LEVEL_1 - case IRQ_NUM_EXT_SSP0: - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_SSP0); - break; - case IRQ_NUM_EXT_SSP1: - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_SSP1); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_2 - case IRQ_NUM_EXT_DMAC0: - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DMAC0); - break; -#endif -#if CONFIG_INTERRUPT_LEVEL_3 - case IRQ_NUM_EXT_DMAC1: - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DMAC1); - break; -#endif - default: - break; - } -} diff --git a/src/drivers/intel/haswell/ipc.c b/src/drivers/intel/haswell/ipc.c deleted file mode 100644 index b966c832ca84..000000000000 --- a/src/drivers/intel/haswell/ipc.c +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dma.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/lib/uuid.h> -#include <sof/lib/wait.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <ipc/header.h> -#include <ipc/topology.h> -#include <stdbool.h> -#include <stdint.h> - -/* 092355d4-b1b8-4868-9942-da19427a3249 */ -DECLARE_SOF_UUID("ipc-task", ipc_task_uuid, 0x092355d4, 0xb1b8, 0x4868, - 0x99, 0x42, 0xda, 0x19, 0x42, 0x7a, 0x32, 0x49); - -/* private data for IPC */ -struct ipc_data { - struct ipc_data_host_buffer dh_buffer; -}; - -static void irq_handler(void *arg) -{ - struct ipc *ipc = arg; - uint32_t isr, imrd; - - /* Interrupt arrived, check src */ - isr = shim_read(SHIM_ISRD); - imrd = shim_read(SHIM_IMRD); - - tracev_ipc("ipc: irq isr 0x%x", isr); - - if (isr & SHIM_ISRD_DONE) { - - /* Mask Done interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_DONE); - - /* clear DONE bit - tell Host we have completed */ - shim_write(SHIM_IPCD, 0); - - ipc->is_notification_pending = false; - - /* unmask Done interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE); - } - - if (isr & SHIM_ISRD_BUSY && !(imrd & SHIM_IMRD_BUSY)) { - - /* Mask Busy interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_BUSY); - - ipc_schedule_process(ipc); - } -} - -enum task_state ipc_platform_do_cmd(void *data) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_cmd_hdr *hdr; - /* Use struct ipc_data *iipc = ipc_get_drvdata(ipc); if needed */ - - /* perform command */ - hdr = mailbox_validate(); - ipc_cmd(hdr); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return SOF_TASK_STATE_COMPLETED; -} - -void ipc_platform_complete_cmd(void *data) -{ - struct ipc *ipc = data; - - /* clear BUSY bit and set DONE bit - accept new messages */ - shim_write(SHIM_IPCX, SHIM_IPCX_DONE); - - /* unmask busy interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY); - - // TODO: signal audio work to enter D3 in normal context - /* are we about to enter D3 ? */ - if (ipc->pm_prepare_D3) { - platform_shared_commit(ipc, sizeof(*ipc)); - - while (1) - wait_for_interrupt(0); - } - - platform_shared_commit(ipc, sizeof(*ipc)); -} - -int ipc_platform_send_msg(struct ipc_msg *msg) -{ - struct ipc *ipc = ipc_get(); - int ret = 0; - - /* can't send nofication when one is in progress */ - if (ipc->is_notification_pending || - shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) { - ret = -EBUSY; - goto out; - } - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - list_item_del(&msg->list); - tracev_ipc("ipc: msg tx -> 0x%x", msg->header); - - ipc->is_notification_pending = true; - - /* now interrupt host to tell it we have message sent */ - shim_write(SHIM_IPCD, SHIM_IPCD_BUSY); - - platform_shared_commit(msg, sizeof(*msg)); - -out: - platform_shared_commit(ipc, sizeof(*ipc)); - - return ret; -} - -struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) -{ - struct ipc_data *iipc = ipc_get_drvdata(ipc); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return &iipc->dh_buffer; -} - -int platform_ipc_init(struct ipc *ipc) -{ - struct ipc_data *iipc; - uint32_t imrd, dir, caps, dev; - - /* init ipc data */ - iipc = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(struct ipc_data)); - ipc_set_drvdata(ipc, iipc); - - /* schedule */ - schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), - &ipc_task_ops, ipc, 0, 0); - -#if CONFIG_HOST_PTABLE - /* allocate page table buffer */ - iipc->dh_buffer.page_table = rzalloc(SOF_MEM_ZONE_SYS, 0, - SOF_MEM_CAPS_RAM, - PLATFORM_PAGE_TABLE_SIZE); - if (iipc->dh_buffer.page_table) - bzero(iipc->dh_buffer.page_table, PLATFORM_PAGE_TABLE_SIZE); -#endif - - /* request GP DMA with shared access privilege */ - caps = 0; - dir = DMA_DIR_HMEM_TO_LMEM; - dev = DMA_DEV_HOST; - iipc->dh_buffer.dmac = dma_get(dir, caps, dev, DMA_ACCESS_SHARED); - - /* configure interrupt */ - interrupt_register(PLATFORM_IPC_INTERRUPT, irq_handler, ipc); - interrupt_enable(PLATFORM_IPC_INTERRUPT, ipc); - - /* Unmask Busy and Done interrupts */ - imrd = shim_read(SHIM_IMRD); - imrd &= ~(SHIM_IMRD_BUSY | SHIM_IMRD_DONE); - shim_write(SHIM_IMRD, imrd); - - platform_shared_commit(ipc, sizeof(*ipc)); - - return 0; -} - -#if CONFIG_IPC_POLLING - -int ipc_platform_poll_init(void) -{ - return 0; -} - -/* tell host we have completed command */ -void ipc_platform_poll_set_cmd_done(void) -{ - /* clear BUSY bit and set DONE bit - accept new messages */ - shim_write(SHIM_IPCX, SHIM_IPCX_DONE); - - /* unmask busy interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY); -} - -/* read the IPC register for any new command messages */ -int ipc_platform_poll_is_cmd_pending(void) -{ - uint32_t isr, imrd; - - /* Interrupt arrived, check src */ - isr = shim_read(SHIM_ISRD); - imrd = shim_read(SHIM_IMRD); - - if (isr & SHIM_ISRD_BUSY && !(imrd & SHIM_IMRD_BUSY)) { - - /* Mask Busy interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_BUSY); - - /* new message */ - return 1; - } - - /* no new message */ - return 0; -} - -int ipc_platform_poll_is_host_ready(void) -{ - uint32_t isr; - - /* Interrupt arrived, check src */ - isr = shim_read(SHIM_ISRD); - - if (isr & SHIM_ISRD_DONE) { - - /* Mask Done interrupt before return */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) | SHIM_IMRD_DONE); - - /* clear DONE bit - tell Host we have completed */ - shim_write(SHIM_IPCD, 0); - - /* unmask Done interrupt */ - shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE); - - /* host done */ - return 1; - } - - /* host still pending */ - return 0; -} - -int ipc_platform_poll_tx_host_msg(struct ipc_msg *msg) -{ - /* can't send nofication when one is in progress */ - if (shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) - return 0; - - /* now send the message */ - mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); - - /* now interrupt host to tell it we have message sent */ - shim_write(SHIM_IPCD, SHIM_IPCD_BUSY); - - /* message sent */ - platform_shared_commit(msg, sizeof(*msg)); - return 1; -} - -#endif diff --git a/src/drivers/intel/haswell/ssp.c b/src/drivers/intel/haswell/ssp.c deleted file mode 100644 index 710f2add2b83..000000000000 --- a/src/drivers/intel/haswell/ssp.c +++ /dev/null @@ -1,575 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/shim.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/dai-intel.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <errno.h> -#include <stdbool.h> -#include <stdint.h> - -/* save SSP context prior to entering D3 */ -static int ssp_context_store(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - ssp->sscr0 = ssp_read(dai, SSCR0); - ssp->sscr1 = ssp_read(dai, SSCR1); - - /* FIXME: need to store sscr2,3,4,5 */ - ssp->psp = ssp_read(dai, SSPSP); - - return 0; -} - -/* restore SSP context after leaving D3 */ -static int ssp_context_restore(struct dai *dai) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - ssp_write(dai, SSCR0, ssp->sscr0); - ssp_write(dai, SSCR1, ssp->sscr1); - /* FIXME: need to restore sscr2,3,4,5 */ - ssp_write(dai, SSPSP, ssp->psp); - - return 0; -} - -/* Digital Audio interface formatting */ -static int ssp_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - uint32_t sscr0; - uint32_t sscr1; - uint32_t sscr2; - uint32_t sspsp; - uint32_t sspsp2; - uint32_t mdiv; - uint32_t bdiv; - uint32_t data_size; - uint32_t start_delay; - uint32_t frame_end_padding; - uint32_t slot_end_padding; - uint32_t frame_len = 0; - uint32_t bdiv_min; - uint32_t format; - bool inverted_frame = false; - int ret = 0; - - spin_lock(&dai->lock); - - /* is playback/capture already running */ - if (ssp->state[DAI_DIR_PLAYBACK] == COMP_STATE_ACTIVE || - ssp->state[DAI_DIR_CAPTURE] == COMP_STATE_ACTIVE) { - dai_err(dai, "ssp_set_config() error: playback/capture already running"); - ret = -EINVAL; - goto out; - } - - dai_info(dai, "ssp_set_config()"); - - /* disable clock */ - shim_update_bits(SHIM_CLKCTL, SHIM_CLKCTL_EN_SSP(dai->index), 0); - - /* enable MCLK */ - shim_update_bits(SHIM_CLKCTL, SHIM_CLKCTL_SMOS(0x3), - SHIM_CLKCTL_SMOS(0x3)); - - /* reset SSP settings */ - /* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */ - sscr0 = SSCR0_MOD | SSCR0_PSP; - - /* sscr1 dynamic settings are TFT, RFT, SFRMDIR, SCLKDIR, SCFR */ - sscr1 = SSCR1_TTE | SSCR1_TTELP; - - /* enable Transmit underrun mode 1 */ - sscr2 = SSCR2_TURM1; - - /* sspsp dynamic settings are SCMODE, SFRMP, DMYSTRT, SFRMWDTH */ - sspsp = 0x0; - - /* sspsp2 no dynamic setting */ - sspsp2 = 0x0; - - ssp->config = *config; - ssp->params = config->ssp; - - switch (config->format & SOF_DAI_FMT_MASTER_MASK) { - case SOF_DAI_FMT_CBM_CFM: - sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; -#ifdef ENABLE_SSRCR1_SCFR - sscr1 |= SSCR1_SCFR; -#endif - break; - case SOF_DAI_FMT_CBS_CFS: - break; - case SOF_DAI_FMT_CBM_CFS: - sscr1 |= SSCR1_SCLKDIR; -#ifdef ENABLE_SSRCR1_SCFR - sscr1 |= SSCR1_SCFR; -#endif - break; - case SOF_DAI_FMT_CBS_CFM: - sscr1 |= SSCR1_SFRMDIR; - break; - default: - dai_err(dai, "ssp_set_config() error: format & MASTER_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - /* clock signal polarity */ - switch (config->format & SOF_DAI_FMT_INV_MASK) { - case SOF_DAI_FMT_NB_NF: - break; - case SOF_DAI_FMT_NB_IF: - inverted_frame = true; /* handled later with format */ - break; - case SOF_DAI_FMT_IB_IF: - sspsp |= SSPSP_SCMODE(2); - inverted_frame = true; /* handled later with format */ - break; - case SOF_DAI_FMT_IB_NF: - sspsp |= SSPSP_SCMODE(2); - break; - default: - dai_err(dai, "ssp_set_config() error: format & INV_MASK EINVAL"); - ret = -EINVAL; - goto out; - } - - /* Additional hardware settings */ - - /* Receiver Time-out Interrupt Disabled/Enabled */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_TINTE) ? - SSCR1_TINTE : 0; - - /* Peripheral Trailing Byte Interrupts Disable/Enable */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PINTE) ? - SSCR1_PINTE : 0; - - /* Enable/disable internal loopback. Output of transmit serial - * shifter connected to input of receive serial shifter, internally. - */ - sscr1 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_LBM) ? - SSCR1_LBM : 0; - - /* Transmit data are driven at the same/opposite clock edge specified - * in SSPSP.SCMODE[1:0] - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_SMTATF) ? - SSCR2_SMTATF : 0; - - /* Receive data are sampled at the same/opposite clock edge specified - * in SSPSP.SCMODE[1:0] - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_MMRATF) ? - SSCR2_MMRATF : 0; - - /* Enable/disable the fix for PSP slave mode TXD wait for frame - * de-assertion before starting the second channel - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSTWFDFD) ? - SSCR2_PSPSTWFDFD : 0; - - /* Enable/disable the fix for PSP master mode FSRT with dummy stop & - * frame end padding capability - */ - sscr2 |= (ssp->params.quirks & SOF_DAI_INTEL_SSP_QUIRK_PSPSRWFDFD) ? - SSCR2_PSPSRWFDFD : 0; - - /* BCLK is generated from MCLK - must be divisable */ - if (config->ssp.mclk_rate % config->ssp.bclk_rate) { - dai_err(dai, "ssp_set_config() error: MCLK is not divisable"); - ret = -EINVAL; - goto out; - } - - /* divisor must be within SCR range */ - mdiv = (config->ssp.mclk_rate / config->ssp.bclk_rate) - 1; - if (mdiv > (SSCR0_SCR_MASK >> 8)) { - dai_err(dai, "ssp_set_config() error: divisor is not within SCR range"); - ret = -EINVAL; - goto out; - } - - /* set the SCR divisor */ - sscr0 |= SSCR0_SCR(mdiv); - - /* calc frame width based on BCLK and rate - must be divisable */ - if (config->ssp.bclk_rate % config->ssp.fsync_rate) { - dai_err(dai, "ssp_set_config() error: BLCK is not divisable"); - ret = -EINVAL; - goto out; - } - - /* must be enouch BCLKs for data */ - bdiv = config->ssp.bclk_rate / config->ssp.fsync_rate; - if (bdiv < config->ssp.tdm_slot_width * - config->ssp.tdm_slots) { - dai_err(dai, "ssp_set_config() error: not enough BCLKs"); - ret = -EINVAL; - goto out; - } - - /* tdm_slot_width must be <= 38 for SSP */ - if (config->ssp.tdm_slot_width > 38) { - dai_err(dai, "ssp_set_config() error: tdm_slot_width > 38"); - ret = -EINVAL; - goto out; - } - - bdiv_min = config->ssp.tdm_slots * config->ssp.sample_valid_bits; - if (bdiv < bdiv_min) { - dai_err(dai, "ssp_set_config() error: bdiv < bdiv_min"); - ret = -EINVAL; - goto out; - } - - frame_end_padding = bdiv - bdiv_min; - if (frame_end_padding > SSPSP2_FEP_MASK) { - dai_err(dai, "ssp_set_config() error: frame_end_padding > SSPSP2_FEP_MASK"); - ret = -EINVAL; - goto out; - } - - /* format */ - format = config->format & SOF_DAI_FMT_FORMAT_MASK; - switch (format) { - case SOF_DAI_FMT_I2S: - case SOF_DAI_FMT_LEFT_J: - - if (format == SOF_DAI_FMT_I2S) { - start_delay = 1; - - /* - * handle frame polarity, I2S default is falling/active low, - * non-inverted(inverted_frame=0) -- active low(SFRMP=0), - * inverted(inverted_frame=1) -- rising/active high(SFRMP=1), - * so, we should set SFRMP to inverted_frame. - */ - sspsp |= SSPSP_SFRMP(inverted_frame); - sspsp |= SSPSP_FSRT; - - } else { - start_delay = 0; - - /* - * handle frame polarity, LEFT_J default is rising/active high, - * non-inverted(inverted_frame=0) -- active high(SFRMP=1), - * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), - * so, we should set SFRMP to !inverted_frame. - */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - } - - sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots); - - if (bdiv % 2) { - dai_err(dai, "ssp_set_config() error: bdiv is not divisible by 2"); - ret = -EINVAL; - goto out; - } - - /* set asserted frame length to half frame length */ - frame_len = bdiv / 2; - - /* - * for I2S/LEFT_J, the padding has to happen at the end - * of each slot - */ - if (frame_end_padding % 2) { - dai_err(dai, "ssp_set_config() error: frame_end_padding is not divisible by 2"); - ret = -EINVAL; - goto out; - } - - slot_end_padding = frame_end_padding / 2; - - if (slot_end_padding > 15) { - /* can't handle padding over 15 bits */ - dai_err(dai, "ssp_set_config() error: slot_end_padding over 15 bits"); - ret = -EINVAL; - goto out; - } - - sspsp |= SSPSP_DMYSTOP(slot_end_padding); - slot_end_padding >>= SSPSP_DMYSTOP_BITS; - sspsp |= SSPSP_EDMYSTOP(slot_end_padding); - - break; - case SOF_DAI_FMT_DSP_A: - - start_delay = 1; - - sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots); - - /* set asserted frame length */ - frame_len = 1; - - /* handle frame polarity, DSP_A default is rising/active high */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK); - - break; - case SOF_DAI_FMT_DSP_B: - - start_delay = 0; - - sscr0 |= SSCR0_FRDC(config->ssp.tdm_slots); - - /* set asserted frame length */ - frame_len = 1; - - /* handle frame polarity, DSP_B default is rising/active high */ - sspsp |= SSPSP_SFRMP(!inverted_frame); - sspsp2 |= (frame_end_padding & SSPSP2_FEP_MASK); - - break; - default: - dai_err(dai, "ssp_set_config() error: invalid format"); - ret = -EINVAL; - goto out; - } - - if (start_delay) - sspsp |= SSPSP_FSRT; - - sspsp |= SSPSP_SFRMWDTH(frame_len); - - data_size = config->ssp.sample_valid_bits; - - if (data_size > 16) - sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16)); - else - sscr0 |= SSCR0_DSIZE(data_size); - - sscr1 |= SSCR1_TFT(0x8) | SSCR1_RFT(0x8); - - ssp_write(dai, SSCR0, sscr0); - ssp_write(dai, SSCR1, sscr1); - ssp_write(dai, SSCR2, sscr2); - ssp_write(dai, SSPSP, sspsp); - ssp_write(dai, SSTSA, SSTSA_SSTSA(config->ssp.tx_slots)); - ssp_write(dai, SSRSA, SSRSA_SSRSA(config->ssp.rx_slots)); - ssp_write(dai, SSPSP2, sspsp2); - - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_PREPARE; - ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_PREPARE; - - /* enable clock */ - shim_update_bits(SHIM_CLKCTL, SHIM_CLKCTL_EN_SSP(dai->index), - SHIM_CLKCTL_EN_SSP(dai->index)); - - /* enable free running clock */ - ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); - ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0); - - dai_info(dai, "ssp_set_config(), done"); - -out: - spin_unlock(&dai->lock); - - return ret; -} - -/* get SSP hw params */ -static int ssp_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, int dir) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - params->rate = ssp->params.fsync_rate; - params->buffer_fmt = 0; - - if (dir == SOF_IPC_STREAM_PLAYBACK) - params->channels = popcount(ssp->params.tx_slots); - else - params->channels = popcount(ssp->params.rx_slots); - - switch (ssp->params.sample_valid_bits) { - case 16: - params->frame_fmt = SOF_IPC_FRAME_S16_LE; - break; - case 24: - params->frame_fmt = SOF_IPC_FRAME_S24_4LE; - break; - case 32: - params->frame_fmt = SOF_IPC_FRAME_S32_LE; - break; - default: - dai_err(dai, "ssp_get_hw_params(): not supported format"); - return -EINVAL; - } - - return 0; -} - -/* start the SSP for either playback or capture */ -static void ssp_start(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - spin_lock(&dai->lock); - - dai_info(dai, "ssp_start()"); - - /* enable DMA */ - if (direction == DAI_DIR_PLAYBACK) { - ssp_update_bits(dai, SSCR1, SSCR1_TSRE | SSCR1_EBCEI, - SSCR1_TSRE | SSCR1_EBCEI); - ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); - ssp_update_bits(dai, SSCR0, SSCR0_TIM, 0); - ssp_update_bits(dai, SSTSA, SSTSA_TSEN, SSTSA_TSEN); - } else { - ssp_update_bits(dai, SSCR1, SSCR1_RSRE | SSCR1_EBCEI, - SSCR1_RSRE | SSCR1_EBCEI); - ssp_update_bits(dai, SSCR0, SSCR0_SSE, SSCR0_SSE); - ssp_update_bits(dai, SSCR0, SSCR0_RIM, 0); - ssp_update_bits(dai, SSRSA, SSRSA_RSEN, SSRSA_RSEN); - } - - /* enable port */ - ssp->state[direction] = COMP_STATE_ACTIVE; - - spin_unlock(&dai->lock); -} - -/* stop the SSP for either playback or capture */ -static void ssp_stop(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - spin_lock(&dai->lock); - - /* stop Rx if neeed */ - if (direction == DAI_DIR_CAPTURE && - ssp->state[SOF_IPC_STREAM_CAPTURE] != COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR1, SSCR1_RSRE, 0); - ssp_update_bits(dai, SSCR0, SSCR0_RIM, SSCR0_RIM); - ssp->state[SOF_IPC_STREAM_CAPTURE] = COMP_STATE_PREPARE; - dai_info(dai, "ssp_stop(), RX stop"); - } - - /* stop Tx if needed */ - if (direction == DAI_DIR_PLAYBACK && - ssp->state[SOF_IPC_STREAM_PLAYBACK] != COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR1, SSCR1_TSRE, 0); - ssp_update_bits(dai, SSCR0, SSCR0_TIM, SSCR0_TIM); - ssp->state[SOF_IPC_STREAM_PLAYBACK] = COMP_STATE_PREPARE; - dai_info(dai, "ssp_stop(), TX stop"); - } - - /* disable SSP port if no users */ - if (ssp->state[SOF_IPC_STREAM_CAPTURE] == COMP_STATE_PREPARE && - ssp->state[SOF_IPC_STREAM_PLAYBACK] == COMP_STATE_PREPARE) { - ssp_update_bits(dai, SSCR0, SSCR0_SSE, 0); - dai_info(dai, "ssp_stop(), SSP port disabled"); - } - - spin_unlock(&dai->lock); -} - -static void ssp_pause(struct dai *dai, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - if (direction == SOF_IPC_STREAM_CAPTURE) - dai_info(dai, "ssp_pause(), RX"); - else - dai_info(dai, "ssp_pause(), TX"); - - ssp->state[direction] = COMP_STATE_PAUSED; -} - -static int ssp_trigger(struct dai *dai, int cmd, int direction) -{ - struct ssp_pdata *ssp = dai_get_drvdata(dai); - - dai_info(dai, "ssp_trigger()"); - - switch (cmd) { - case COMP_TRIGGER_START: - if (ssp->state[direction] == COMP_STATE_PREPARE || - ssp->state[direction] == COMP_STATE_PAUSED) - ssp_start(dai, direction); - break; - case COMP_TRIGGER_RELEASE: - if (ssp->state[direction] == COMP_STATE_PAUSED || - ssp->state[direction] == COMP_STATE_PREPARE) - ssp_start(dai, direction); - break; - case COMP_TRIGGER_STOP: - ssp_stop(dai, direction); - break; - case COMP_TRIGGER_PAUSE: - ssp_pause(dai, direction); - break; - case COMP_TRIGGER_RESUME: - ssp_context_restore(dai); - break; - case COMP_TRIGGER_SUSPEND: - ssp_context_store(dai); - break; - default: - break; - } - - return 0; -} - -static int ssp_probe(struct dai *dai) -{ - struct ssp_pdata *ssp; - - /* allocate private data */ - ssp = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, SOF_MEM_CAPS_RAM, - sizeof(*ssp)); - dai_set_drvdata(dai, ssp); - - ssp->state[DAI_DIR_PLAYBACK] = COMP_STATE_READY; - ssp->state[DAI_DIR_CAPTURE] = COMP_STATE_READY; - - return 0; -} - -static int ssp_get_handshake(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[direction].handshake; -} - -static int ssp_get_fifo(struct dai *dai, int direction, int stream_id) -{ - return dai->plat_data.fifo[direction].offset; -} - -const struct dai_driver ssp_driver = { - .type = SOF_DAI_INTEL_SSP, - .dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP, - .dma_dev = DMA_DEV_SSP, - .ops = { - .trigger = ssp_trigger, - .set_config = ssp_set_config, - .pm_context_store = ssp_context_store, - .pm_context_restore = ssp_context_restore, - .get_hw_params = ssp_get_hw_params, - .get_handshake = ssp_get_handshake, - .get_fifo = ssp_get_fifo, - .probe = ssp_probe, - }, -}; diff --git a/src/drivers/intel/haswell/timer.c b/src/drivers/intel/haswell/timer.c deleted file mode 100644 index 026f6d82c6e0..000000000000 --- a/src/drivers/intel/haswell/timer.c +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/audio/component_ext.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/platform.h> -#include <ipc/stream.h> -#include <errno.h> -#include <stdint.h> - -void platform_timer_start(struct timer *timer) -{ - //nothing to do on BDW & HSW for cpu timer -} - -void platform_timer_stop(struct timer *timer) -{ - arch_timer_disable(timer); -} - -int64_t platform_timer_set(struct timer *timer, uint64_t ticks) -{ - return arch_timer_set(timer, ticks); -} - -void platform_timer_clear(struct timer *timer) -{ - arch_timer_clear(timer); -} - -uint64_t platform_timer_get(struct timer *timer) -{ - return arch_timer_get_system(timer); -} - -/* get timestamp for host stream DMA position */ -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn) -{ - int err; - - /* get host position */ - err = comp_position(host, posn); - if (err == 0) - posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; -} - -/* get timestamp for DAI stream DMA position */ -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn) -{ - int err; - - /* get DAI position */ - err = comp_position(dai, posn); - if (err == 0) - posn->flags |= SOF_TIME_DAI_VALID; - - /* get SSP wallclock - DAI sets this to stream start value */ - posn->wallclock = timer_get_system(timer_get()) - posn->wallclock; - posn->wallclock_hz = clock_get_freq(PLATFORM_DEFAULT_CLOCK); - posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; -} - -/* get current wallclock for componnent */ -void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) -{ - /* only 1 wallclock on HSW */ - *wallclock = timer_get_system(timer_get()); -} - -int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) -{ - int ret; - - switch (timer->id) { - case TIMER0: - case TIMER1: - case TIMER2: - ret = arch_timer_register(timer, handler, arg); - break; - default: - ret = -EINVAL; - break; - } - - platform_shared_commit(timer, sizeof(*timer)); - - return ret; -} - -void timer_unregister(struct timer *timer, void *arg) -{ - interrupt_unregister(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); -} - -void timer_enable(struct timer *timer, void *arg, int core) -{ - interrupt_enable(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); -} - -void timer_disable(struct timer *timer, void *arg, int core) -{ - interrupt_disable(timer->irq, arg); - - platform_shared_commit(timer, sizeof(*timer)); -} diff --git a/src/drivers/intel/pmc-ipc.c b/src/drivers/intel/pmc-ipc.c deleted file mode 100644 index 3aec24e603e9..000000000000 --- a/src/drivers/intel/pmc-ipc.c +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/pmc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/shim.h> -#include <sof/lib/wait.h> -#include <sof/platform.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stdint.h> - -/* private data for IPC */ -struct intel_ipc_pmc_data { - uint32_t msg_l; - uint32_t msg_h; - uint32_t pending; -}; - -static struct intel_ipc_pmc_data *_pmc; - -static void do_cmd(void) -{ - uint32_t ipcsc; - uint32_t status = 0; - - trace_ipc("pmc: tx -> 0x%x", _pmc->msg_l); - - _pmc->pending = 0; - - /* clear BUSY bit and set DONE bit - accept new messages */ - ipcsc = shim_read(SHIM_IPCSCH); - ipcsc &= ~SHIM_IPCSCH_BUSY; - ipcsc |= SHIM_IPCSCH_DONE | status; - shim_write(SHIM_IPCSCH, ipcsc); - - /* unmask busy interrupt */ - shim_write(SHIM_IMRLPESC, - shim_read(SHIM_IMRLPESC) & ~SHIM_IMRLPESC_BUSY); -} - -/* process current message */ -int pmc_process_msg_queue(void) -{ - if (_pmc->pending) - do_cmd(); - return 0; -} - -static void do_notify(void) -{ - trace_ipc("pmc: not rx"); - - /* clear DONE bit */ - shim_write(SHIM_IPCLPESCH, - shim_read(SHIM_IPCLPESCH) & ~SHIM_IPCLPESCH_DONE); - - /* unmask Done interrupt */ - shim_write(SHIM_IMRLPESC, - shim_read(SHIM_IMRLPESC) & ~SHIM_IMRLPESC_DONE); -} - -static void irq_handler(void *arg) -{ - uint32_t isrlpesc; - - /* Interrupt arrived, check src */ - isrlpesc = shim_read(SHIM_ISRLPESC); - - tracev_ipc("pmc: irq isrlpesc 0x%x", isrlpesc); - - if (isrlpesc & SHIM_ISRLPESC_DONE) { - /* Mask Done interrupt before return */ - shim_write(SHIM_IMRLPESC, - shim_read(SHIM_IMRLPESC) | SHIM_IMRLPESC_DONE); - interrupt_clear(IRQ_NUM_EXT_PMC); - do_notify(); - } - - if (isrlpesc & SHIM_ISRLPESC_BUSY) { - /* Mask Busy interrupt before return */ - shim_write(SHIM_IMRLPESC, - shim_read(SHIM_IMRLPESC) | SHIM_IMRLPESC_BUSY); - interrupt_clear(IRQ_NUM_EXT_PMC); - - /* place message in Q and process later */ - _pmc->msg_l = shim_read(SHIM_IPCSCL); - _pmc->msg_h = shim_read(SHIM_IPCSCH); - _pmc->pending = 1; - } -} - -int ipc_pmc_send_msg(uint32_t message) -{ - uint32_t ipclpesch; - int ret; - - tracev_ipc("pmc: msg tx -> 0x%x", message); - - ipclpesch = shim_read(SHIM_IPCLPESCH); - - /* we can only send new messages if the SC is not busy */ - if (ipclpesch & SHIM_IPCLPESCH_BUSY) { - trace_ipc_error("pmc: busy 0x%x", ipclpesch); - return -EAGAIN; - } - - /* send the new message */ - shim_write(SHIM_IPCLPESCL, 0); - shim_write(SHIM_IPCLPESCH, SHIM_IPCLPESCH_BUSY | message); - - /* wait for idle status */ - ret = poll_for_register_delay(SHIM_BASE + SHIM_IPCLPESCH, - SHIM_IPCLPESCH_BUSY, 0, - PLATFORM_LPE_DELAY); - - /* did command succeed */ - if (ret < 0) { - trace_ipc_error("pmc: command 0x%x failed", message); - return -EINVAL; - } - - return 0; -} - -int platform_ipc_pmc_init(void) -{ - uint32_t imrlpesc; - - /* init ipc data */ - _pmc = rmalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(struct intel_ipc_pmc_data)); - - /* configure interrupt */ - interrupt_register(IRQ_NUM_EXT_PMC, irq_handler, _pmc); - interrupt_enable(IRQ_NUM_EXT_PMC, _pmc); - - /* Unmask Busy and Done interrupts */ - imrlpesc = shim_read(SHIM_IMRLPESC); - imrlpesc &= ~(SHIM_IMRLPESC_BUSY | SHIM_IMRLPESC_DONE); - shim_write(SHIM_IMRLPESC, imrlpesc); - - return 0; -} diff --git a/src/drivers/interrupt.c b/src/drivers/interrupt.c index b4dcd9e1d456..5bc1a26e53f7 100644 --- a/src/drivers/interrupt.c +++ b/src/drivers/interrupt.c @@ -6,19 +6,43 @@ // Liam Girdwood <liam.r.girdwood@linux.intel.com> #include <sof/common.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/alloc.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> #include <sof/lib/cpu.h> #include <sof/lib/memory.h> +#include <sof/lib/uuid.h> #include <sof/list.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> #include <sof/trace/trace.h> #include <ipc/topology.h> #include <errno.h> #include <stddef.h> #include <stdint.h> +LOG_MODULE_REGISTER(irq, CONFIG_SOF_LOG_LEVEL); + +/* 1862d39a-3a84-4d64-8c91-dce1dfc122db */ + +SOF_DEFINE_REG_UUID(irq); + +DECLARE_TR_CTX(irq_tr, SOF_UUID(irq_uuid), LOG_LEVEL_INFO); + +/* For i.MX, when building SOF with Zephyr, we use wrapper.c, + * interrupt.c and interrupt-irqsteer.c which causes name + * collisions. + * In order to avoid this and make any second level interrupt + * handling go through interrupt-irqsteer.c define macros to + * rename the duplicated functions. + */ +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +#define interrupt_get_irq mux_interrupt_get_irq +#define interrupt_register mux_interrupt_register +#define interrupt_unregister mux_interrupt_unregister +#define interrupt_enable mux_interrupt_enable +#define interrupt_disable mux_interrupt_disable +#endif + static SHARED_DATA struct cascade_root cascade_root; static int interrupt_register_internal(uint32_t irq, void (*handler)(void *arg), @@ -30,31 +54,33 @@ int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl) { struct cascade_root *root = cascade_root_get(); struct irq_cascade_desc **cascade; - unsigned long flags; + k_spinlock_key_t key; unsigned int i; int ret; if (!tmpl->name || !tmpl->ops) return -EINVAL; - spin_lock_irq(&root->lock, flags); + key = k_spin_lock(&root->lock); for (cascade = &root->list; *cascade; cascade = &(*cascade)->next) { if (!rstrcmp((*cascade)->name, tmpl->name)) { ret = -EEXIST; - trace_error(TRACE_CLASS_IRQ, - "error: cascading IRQ controller name duplication!"); + tr_err(&irq_tr, "cascading IRQ controller name duplication!"); goto unlock; } - platform_shared_commit(*cascade, sizeof(**cascade)); } - *cascade = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(**cascade)); + *cascade = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(**cascade)); + if (!*cascade) { + ret = -ENOMEM; + tr_err(&irq_tr, "cascading IRQ controller allocation failed!"); + goto unlock; + } - spinlock_init(&(*cascade)->lock); + k_spinlock_init(&(*cascade)->lock); for (i = 0; i < PLATFORM_IRQ_CHILDREN; i++) list_init(&(*cascade)->child[i].list); @@ -72,12 +98,10 @@ int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl) ret = 0; - platform_shared_commit(*cascade, sizeof(**cascade)); unlock: - platform_shared_commit(root, sizeof(*root)); - spin_unlock_irq(&root->lock, flags); + k_spin_unlock(&root->lock, key); return ret; } @@ -86,21 +110,20 @@ int interrupt_get_irq(unsigned int irq, const char *name) { struct cascade_root *root = cascade_root_get(); struct irq_cascade_desc *cascade; - unsigned long flags; int ret = -ENODEV; + k_spinlock_key_t key; if (!name || name[0] == '\0') return irq; /* If a name is specified, irq must be <= PLATFORM_IRQ_CHILDREN */ if (irq >= PLATFORM_IRQ_CHILDREN) { - trace_error(TRACE_CLASS_IRQ, - "error: IRQ %d invalid as a child interrupt!", - irq); + tr_err(&irq_tr, "IRQ %d invalid as a child interrupt!", + irq); return -EINVAL; } - spin_lock_irq(&root->lock, flags); + key = k_spin_lock(&root->lock); for (cascade = root->list; cascade; cascade = cascade->next) { /* .name is non-volatile */ @@ -109,13 +132,10 @@ int interrupt_get_irq(unsigned int irq, const char *name) break; } - platform_shared_commit(cascade, sizeof(*cascade)); } - platform_shared_commit(cascade, sizeof(*cascade)); - platform_shared_commit(root, sizeof(*root)); - spin_unlock_irq(&root->lock, flags); + k_spin_unlock(&root->lock, key); return ret; } @@ -124,12 +144,12 @@ struct irq_cascade_desc *interrupt_get_parent(uint32_t irq) { struct cascade_root *root = cascade_root_get(); struct irq_cascade_desc *cascade, *c = NULL; - unsigned long flags; + k_spinlock_key_t key; if (irq < PLATFORM_IRQ_HW_NUM) return NULL; - spin_lock_irq(&root->lock, flags); + key = k_spin_lock(&root->lock); for (cascade = root->list; cascade; cascade = cascade->next) { if (irq >= cascade->irq_base && @@ -138,13 +158,10 @@ struct irq_cascade_desc *interrupt_get_parent(uint32_t irq) break; } - platform_shared_commit(cascade, sizeof(*cascade)); } - platform_shared_commit(cascade, sizeof(*cascade)); - platform_shared_commit(root, sizeof(*root)); - spin_unlock_irq(&root->lock, flags); + k_spin_unlock(&root->lock, key); return c; } @@ -155,7 +172,7 @@ void interrupt_init(struct sof *sof) sizeof(cascade_root)); sof->cascade_root->last_irq = PLATFORM_IRQ_FIRST_CHILD - 1; - spinlock_init(&sof->cascade_root->lock); + k_spinlock_init(&sof->cascade_root->lock); } static int irq_register_child(struct irq_cascade_desc *cascade, int irq, @@ -180,24 +197,21 @@ static int irq_register_child(struct irq_cascade_desc *cascade, int irq, child = container_of(list, struct irq_desc, irq_list); if (child->handler_arg == arg) { - platform_shared_commit(child, sizeof(*child)); - trace_error(TRACE_CLASS_IRQ, - "error: IRQ 0x%x handler argument re-used!", - irq); + tr_err(&irq_tr, "IRQ 0x%x handler argument re-used!", + irq); ret = -EEXIST; goto out; } - platform_shared_commit(child, sizeof(*child)); } if (!desc) { /* init child from run-time, may be registered and unregistered * many times at run-time */ - child = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(struct irq_desc)); + child = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct irq_desc)); if (!child) { ret = -ENOMEM; goto out; @@ -222,10 +236,8 @@ static int irq_register_child(struct irq_cascade_desc *cascade, int irq, if (!ret) cascade->num_children[core]++; - platform_shared_commit(child, sizeof(*child)); out: - platform_shared_commit(cascade, sizeof(*cascade)); return ret; } @@ -255,15 +267,12 @@ static void irq_unregister_child(struct irq_cascade_desc *cascade, int irq, interrupt_unregister_internal(parent->irq, parent, parent); - platform_shared_commit(child, sizeof(*child)); break; } - platform_shared_commit(child, sizeof(*child)); } - platform_shared_commit(cascade, sizeof(*cascade)); } static uint32_t irq_enable_child(struct irq_cascade_desc *cascade, int irq, @@ -274,14 +283,14 @@ static uint32_t irq_enable_child(struct irq_cascade_desc *cascade, int irq, struct irq_child *child; unsigned int child_idx; struct list_item *list; - unsigned long flags; + k_spinlock_key_t key; /* * Locking is child to parent: when called recursively we are already * holding the child's lock and then also taking the parent's lock. The * same holds for the interrupt_(un)register() paths. */ - spin_lock_irq(&cascade->lock, flags); + key = k_spin_lock(&cascade->lock); child = cascade->child + hw_irq; child_idx = cascade->global_mask ? 0 : core; @@ -292,11 +301,9 @@ static uint32_t irq_enable_child(struct irq_cascade_desc *cascade, int irq, if (d->handler_arg == arg) { d->cpu_mask |= 1 << core; - platform_shared_commit(d, sizeof(*d)); break; } - platform_shared_commit(d, sizeof(*d)); } if (!child->enable_count[child_idx]++) { @@ -309,9 +316,8 @@ static uint32_t irq_enable_child(struct irq_cascade_desc *cascade, int irq, interrupt_unmask(irq, core); } - platform_shared_commit(cascade, sizeof(*cascade)); - spin_unlock_irq(&cascade->lock, flags); + k_spin_unlock(&cascade->lock, key); return 0; } @@ -324,9 +330,9 @@ static uint32_t irq_disable_child(struct irq_cascade_desc *cascade, int irq, struct irq_child *child; unsigned int child_idx; struct list_item *list; - unsigned long flags; + k_spinlock_key_t key; - spin_lock_irq(&cascade->lock, flags); + key = k_spin_lock(&cascade->lock); child = cascade->child + hw_irq; child_idx = cascade->global_mask ? 0 : core; @@ -337,17 +343,14 @@ static uint32_t irq_disable_child(struct irq_cascade_desc *cascade, int irq, if (d->handler_arg == arg) { d->cpu_mask &= ~(1 << core); - platform_shared_commit(d, sizeof(*d)); break; } - platform_shared_commit(d, sizeof(*d)); } if (!child->enable_count[child_idx]) { - trace_error(TRACE_CLASS_IRQ, - "error: IRQ %x unbalanced interrupt_disable()", - irq); + tr_err(&irq_tr, "IRQ %x unbalanced interrupt_disable()", + irq); } else if (!--child->enable_count[child_idx]) { /* disable the child interrupt */ interrupt_mask(irq, core); @@ -358,9 +361,8 @@ static uint32_t irq_disable_child(struct irq_cascade_desc *cascade, int irq, cascade->desc.handler_arg); } - platform_shared_commit(cascade, sizeof(*cascade)); - spin_unlock_irq(&cascade->lock, flags); + k_spin_unlock(&cascade->lock, key); return 0; } @@ -374,18 +376,27 @@ static int interrupt_register_internal(uint32_t irq, void (*handler)(void *arg), void *arg, struct irq_desc *desc) { struct irq_cascade_desc *cascade; - /* Avoid a bogus compiler warning */ - unsigned long flags = 0; + k_spinlock_key_t key; int ret; /* no parent means we are registering DSP internal IRQ */ cascade = interrupt_get_parent(irq); - if (!cascade) + if (!cascade) { +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +/* undefine the macro so that interrupt_register() + * is resolved to the one from wrapper.c + */ +#undef interrupt_register + + return interrupt_register(irq, handler, arg); +#else return arch_interrupt_register(irq, handler, arg); +#endif + } - spin_lock_irq(&cascade->lock, flags); + key = k_spin_lock(&cascade->lock); ret = irq_register_child(cascade, irq, handler, arg, desc); - spin_unlock_irq(&cascade->lock, flags); + k_spin_unlock(&cascade->lock, key); return ret; } @@ -399,19 +410,27 @@ static void interrupt_unregister_internal(uint32_t irq, const void *arg, struct irq_desc *desc) { struct irq_cascade_desc *cascade; - /* Avoid a bogus compiler warning */ - unsigned long flags = 0; + k_spinlock_key_t key; /* no parent means we are unregistering DSP internal IRQ */ cascade = interrupt_get_parent(irq); if (!cascade) { +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +/* undefine the macro so that interrupt_unregister() + * is resolved to the one from wrapper.c + */ +#undef interrupt_unregister + + interrupt_unregister(irq, arg); +#else arch_interrupt_unregister(irq); +#endif return; } - spin_lock_irq(&cascade->lock, flags); + key = k_spin_lock(&cascade->lock); irq_unregister_child(cascade, irq, arg, desc); - spin_unlock_irq(&cascade->lock, flags); + k_spin_unlock(&cascade->lock, key); } uint32_t interrupt_enable(uint32_t irq, void *arg) @@ -423,7 +442,16 @@ uint32_t interrupt_enable(uint32_t irq, void *arg) if (cascade) return irq_enable_child(cascade, irq, arg); +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +/* undefine the macro so that interrupt_enable() + * is resolved to the one from wrapper.c + */ +#undef interrupt_enable + + return interrupt_enable(irq, arg); +#else return arch_interrupt_enable_mask(1 << irq); +#endif } uint32_t interrupt_disable(uint32_t irq, void *arg) @@ -435,5 +463,14 @@ uint32_t interrupt_disable(uint32_t irq, void *arg) if (cascade) return irq_disable_child(cascade, irq, arg); +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +/* undefine the macro so that interrupt_disable() + * is resolved to the one from wrapper.c + */ +#undef interrupt_disable + + return interrupt_disable(irq, arg); +#else return arch_interrupt_disable_mask(1 << irq); +#endif } diff --git a/src/drivers/mediatek/CMakeLists.txt b/src/drivers/mediatek/CMakeLists.txt new file mode 100644 index 000000000000..4362b62ec7cb --- /dev/null +++ b/src/drivers/mediatek/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(afe) +if(CONFIG_MT8195) + add_subdirectory(mt8195) +endif() +if(CONFIG_MT8186 OR CONFIG_MT8188) + add_subdirectory(mt818x) +endif() +if(CONFIG_MT8196) + add_subdirectory(mt8196) +endif() +if(CONFIG_MT8365) + add_subdirectory(mt8365) +endif() diff --git a/src/drivers/mediatek/Kconfig b/src/drivers/mediatek/Kconfig new file mode 100644 index 000000000000..22d27a4bbbb6 --- /dev/null +++ b/src/drivers/mediatek/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config TEST_SGEN + bool + default n + help + Note: TEST_SGEN for test only + Define this TEST_SGEN to enable sine tone generator, + then output data to audio memory interface(memif) + +config MEDIATEK_DRAM_IMAGE + bool "Change image location to DRAM" + default n + help + Select this to generate the SOF image on DRAM for MediaTek platform. + If the image size cannot fit in the DSP SRAM, enable this option will + move all sections except vector from SRAM to DRAM. + + If unsure, select "n". diff --git a/src/drivers/mediatek/afe/CMakeLists.txt b/src/drivers/mediatek/afe/CMakeLists.txt new file mode 100644 index 000000000000..228a6555d2c8 --- /dev/null +++ b/src/drivers/mediatek/afe/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof afe-memif.c afe-dai.c afe-drv.c) +if(CONFIG_MT8186) + add_subdirectory(mt8186) +endif() +if(CONFIG_MT8188) + add_subdirectory(mt8188) +endif() +if(CONFIG_MT8195) + add_subdirectory(mt8195) +endif() +if(CONFIG_MT8196) + add_subdirectory(mt8196) +endif() +if(CONFIG_MT8365) + add_subdirectory(mt8365) +endif() diff --git a/src/drivers/mediatek/afe/afe-dai.c b/src/drivers/mediatek/afe/afe-dai.c new file mode 100644 index 000000000000..b8225471e5f0 --- /dev/null +++ b/src/drivers/mediatek/afe/afe-dai.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * YC Hung <yc.hung@mediatek.com> + * Chunxu Li <chunxu.li@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <sof/audio/component.h> +#include <sof/drivers/afe-drv.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <ipc/dai.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(afe_dai); + +DECLARE_TR_CTX(afe_dai_tr, SOF_UUID(afe_dai_uuid), LOG_LEVEL_INFO); +LOG_MODULE_DECLARE(mtk_afe, CONFIG_SOF_LOG_LEVEL); + +static int afe_dai_drv_trigger(struct dai *dai, int cmd, int direction) +{ + return 0; +} + +static int afe_dai_drv_set_config(struct dai *dai, struct ipc_config_dai *common_config, + const void *spec_config) +{ + const struct sof_ipc_dai_config *config = spec_config; + struct mtk_base_afe *afe = dai_get_drvdata(dai); + + return afe_dai_set_config(afe, + dai->index, + config->afe.dai_channels, + config->afe.dai_rate, + config->afe.dai_format); +} + +/* get AFE hw params */ +static int afe_dai_drv_get_hw_params(struct dai *dai, struct sof_ipc_stream_params *params, int dir) +{ + int ret; + struct mtk_base_afe *afe = dai_get_drvdata(dai); + unsigned int channel, rate, format; + + ret = afe_dai_get_config(afe, dai->index, &channel, &rate, &format); + if (ret < 0) + return ret; + + params->rate = rate; + params->channels = channel; + params->buffer_fmt = format; + params->frame_fmt = format; + + return 0; +} + +static int afe_dai_drv_probe(struct dai *dai) +{ + struct mtk_base_afe *afe = afe_get(); + + dai_info(dai, "afe_dai_probe()"); + + if (dai_get_drvdata(dai)) + return -EEXIST; + + dai_set_drvdata(dai, afe); + + return 0; +} + +static int afe_dai_drv_remove(struct dai *dai) +{ + dai_info(dai, "afe_dai_remove()"); + + return 0; +} + +static int afe_dai_drv_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return (int)dai->plat_data.fifo[0].handshake; +} + +static int afe_dai_drv_get_fifo(struct dai *dai, int direction, int stream_id) +{ + return 0; +} + +const struct dai_driver afe_dai_driver = { + .type = SOF_DAI_MEDIATEK_AFE, + .uid = SOF_UUID(afe_dai_uuid), + .tctx = &afe_dai_tr, + .dma_dev = SOF_DMA_DEV_AFE_MEMIF, + .ops = { + .trigger = afe_dai_drv_trigger, + .set_config = afe_dai_drv_set_config, + .get_hw_params = afe_dai_drv_get_hw_params, + .get_handshake = afe_dai_drv_get_handshake, + .get_fifo = afe_dai_drv_get_fifo, + .probe = afe_dai_drv_probe, + .remove = afe_dai_drv_remove, + }, +}; diff --git a/src/drivers/mediatek/afe/afe-drv.c b/src/drivers/mediatek/afe/afe-drv.c new file mode 100644 index 000000000000..5f09359117e6 --- /dev/null +++ b/src/drivers/mediatek/afe/afe-drv.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * YC Hung <yc.hung@mediatek.com> + * Chunxu Li <chunxu.li@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/io.h> +#include <rtos/alloc.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <errno.h> +#include <sof/drivers/afe-drv.h> +#include <sof/drivers/afe-memif.h> + +/*#define AFE_DRV_LOG*/ +static struct mtk_base_afe mtk_afe; + +#ifndef AFE_DRV_LOG +#undef printf +#define printf(format, ...) +#endif + +SOF_DEFINE_REG_UUID(afedrv); + +DECLARE_TR_CTX(afedrv_tr, SOF_UUID(afedrv_uuid), LOG_LEVEL_INFO); +LOG_MODULE_DECLARE(mtk_afe, CONFIG_SOF_LOG_LEVEL); + +static inline void afe_reg_read(struct mtk_base_afe *afe, uint32_t reg, uint32_t *value) +{ + *value = io_reg_read((uint32_t)((char *)afe->base + reg)); + tr_dbg(&afedrv_tr, "r_reg:0x%x, value:0x%x\n", reg, *value); +} + +static inline void afe_reg_write(struct mtk_base_afe *afe, uint32_t reg, uint32_t value) +{ + io_reg_write((uint32_t)((char *)afe->base + reg), value); + tr_dbg(&afedrv_tr, "w_reg:0x%x, value:0x%x\n", reg, value); +} + +static inline void afe_reg_update_bits(struct mtk_base_afe *afe, uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits((uint32_t)((char *)afe->base + reg), mask, value); + tr_dbg(&afedrv_tr, "u_reg:0x%x, value:0x%x\n", reg, value); +} + +static int afe_memif_set_channel(struct mtk_base_afe *afe, int id, unsigned int channel) +{ + struct mtk_base_afe_memif *memif = &afe->memif[id]; + unsigned int mono; + + if (memif->data->ch_num_reg >= 0) { + afe_reg_update_bits(afe, memif->data->ch_num_reg, + memif->data->ch_num_maskbit << memif->data->ch_num_shift, + channel << memif->data->ch_num_shift); + } + + if (memif->data->quad_ch_mask) { + unsigned int quad_ch = (channel == 4); + + afe_reg_update_bits(afe, memif->data->quad_ch_reg, + memif->data->quad_ch_mask << memif->data->quad_ch_shift, + quad_ch << memif->data->quad_ch_shift); + } + + mono = (bool)memif->data->mono_invert ^ (channel == 1); + + if (memif->data->int_odd_flag_reg > 0) + afe_reg_update_bits(afe, memif->data->int_odd_flag_reg, + 1 << memif->data->int_odd_flag_shift, + mono << memif->data->int_odd_flag_shift); + + if (memif->data->mono_reg > 0 && memif->data->mono_shift >= 0) + afe_reg_update_bits(afe, memif->data->mono_reg, + 1 << memif->data->mono_shift, + mono << memif->data->mono_shift); + return 0; +} + +static int afe_memif_set_rate(struct mtk_base_afe *afe, int id, unsigned int rate) +{ + struct mtk_base_afe_memif *memif = &afe->memif[id]; + int fs; + + fs = afe->afe_fs(rate, memif->data->id); + if (fs < 0) { + tr_err(&afedrv_tr, "invalid fs:%d\n", fs); + return -EINVAL; + } + + afe_reg_update_bits(afe, memif->data->fs_reg, + memif->data->fs_maskbit << memif->data->fs_shift, + fs << memif->data->fs_shift); + + return 0; +} + +static int afe_memif_set_format(struct mtk_base_afe *afe, int id, unsigned int format) +{ + struct mtk_base_afe_memif *memif = &afe->memif[id]; + int hd_audio; + int memif_32bit_supported = afe->memif_32bit_supported; + + /* set hd mode */ + switch (format) { + case SOF_IPC_FRAME_S16_LE: + hd_audio = 0; + break; + case SOF_IPC_FRAME_S32_LE: + case SOF_IPC_FRAME_S24_4LE: + if (memif_32bit_supported) + hd_audio = 2; + else + hd_audio = 1; + break; + default: + tr_err(&afedrv_tr, "not support format:%u\n", format); + return -EINVAL; + } + + afe_reg_update_bits(afe, memif->data->hd_reg, 0x3 << memif->data->hd_shift, + hd_audio << memif->data->hd_shift); + return 0; +} + +int afe_memif_set_params(struct mtk_base_afe *afe, int id, unsigned int channel, unsigned int rate, + unsigned int format) +{ + int ret; + + ret = afe_memif_set_channel(afe, id, channel); + if (ret < 0) + return ret; + ret = afe_memif_set_rate(afe, id, rate); + if (ret < 0) + return ret; + ret = afe_memif_set_format(afe, id, format); + if (ret < 0) + return ret; + /* TODO IRQ direction, irq format setting ? */ + + return ret; +} + +int afe_memif_set_addr(struct mtk_base_afe *afe, int id, unsigned int dma_addr, + unsigned int dma_bytes) +{ + struct mtk_base_afe_memif *memif = &afe->memif[id]; + int msb_at_bit33 = 0; /* for dsp side only support 32bit address */ + unsigned int phys_buf_addr; + unsigned int phys_buf_addr_upper_32 = 0; /* for dsp side only support 32bit address */ + + memif->dma_addr = dma_addr; + + /* convert adsp address to afe address */ + if (afe->adsp2afe_addr) + dma_addr = afe->adsp2afe_addr(dma_addr); + + phys_buf_addr = dma_addr; + + memif->afe_addr = phys_buf_addr; + memif->buffer_size = dma_bytes; + tr_dbg(&afedrv_tr, "dma_addr:0x%x, size:%u\n", dma_addr, dma_bytes); + /* start */ + afe_reg_write(afe, memif->data->reg_ofs_base, phys_buf_addr); + /* end */ + if (memif->data->reg_ofs_end) + afe_reg_write(afe, memif->data->reg_ofs_end, phys_buf_addr + dma_bytes - 1); + else + afe_reg_write(afe, memif->data->reg_ofs_base + afe->base_end_offset, + phys_buf_addr + dma_bytes - 1); + + /* set start, end, upper 32 bits */ + if (memif->data->reg_ofs_base_msb) { + afe_reg_write(afe, memif->data->reg_ofs_base_msb, phys_buf_addr_upper_32); + afe_reg_write(afe, memif->data->reg_ofs_end_msb, phys_buf_addr_upper_32); + } + + /* set MSB to 33-bit */ + if (memif->data->msb_reg > 0) + afe_reg_update_bits(afe, memif->data->msb_reg, 1 << memif->data->msb_shift, + msb_at_bit33 << memif->data->msb_shift); + + /* set MSB to 33-bit, for memif end address */ + if (memif->data->msb2_reg > 0) + afe_reg_update_bits(afe, memif->data->msb2_reg, 1 << memif->data->msb2_shift, + msb_at_bit33 << memif->data->msb2_shift); + + return 0; +} + +int afe_memif_set_enable(struct mtk_base_afe *afe, int id, int enable) +{ + const struct mtk_base_memif_data *memif_data = afe->memif[id].data; + + if (memif_data->enable_shift < 0) + return 0; + + /* enable agent */ + /* TODO: enable/disable should in different sequence? */ + if (memif_data->agent_disable_reg > 0) { + afe_reg_update_bits(afe, memif_data->agent_disable_reg, + 1 << memif_data->agent_disable_shift, + (!enable) << memif_data->agent_disable_shift); + } + + afe_reg_update_bits(afe, memif_data->enable_reg, 1 << memif_data->enable_shift, + enable << memif_data->enable_shift); + + return 0; +} + +int afe_memif_get_direction(struct mtk_base_afe *afe, int id) +{ + const struct mtk_base_memif_data *memif_data = afe->memif[id].data; + + if (memif_data->id >= 0 && memif_data->id < afe->memif_dl_num) + return MEM_DIR_PLAYBACK; + return MEM_DIR_CAPTURE; +} + +unsigned int afe_memif_get_cur_position(struct mtk_base_afe *afe, int id) +{ + const struct mtk_base_memif_data *memif_data = afe->memif[id].data; + unsigned int hw_ptr; + + if (memif_data->reg_ofs_cur < 0) + return 0; + afe_reg_read(afe, memif_data->reg_ofs_cur, &hw_ptr); + + /* convert afe address to adsp address */ + if (afe->afe2adsp_addr) + hw_ptr = afe->afe2adsp_addr(hw_ptr); + return hw_ptr; +} + +int afe_dai_set_config(struct mtk_base_afe *afe, int id, unsigned int channel, unsigned int rate, + unsigned int format) +{ + struct mtk_base_afe_dai *dai; + + /* TODO 1. if need use dai->id to search target dai */ + /* TODO 1. if need a status to control the dai status */ + + if (id >= afe->dais_size) + return -EINVAL; + + tr_info(&afedrv_tr, "id:%d\n", id); + + dai = &afe->dais[id]; + dai->channel = channel; + dai->format = format; + dai->rate = rate; + + tr_info(&afedrv_tr, "dai:%d set: format:%d, rate:%d, channel:%d\n", id, format, rate, + channel); + + return 0; +} + +int afe_dai_get_config(struct mtk_base_afe *afe, int id, unsigned int *channel, unsigned int *rate, + unsigned int *format) +{ + struct mtk_base_afe_dai *dai; + + /* TODO 1. if need use dai->id to search target dai */ + /* TODO 1. if need a status to control the dai status */ + tr_info(&afedrv_tr, "id:%d\n", id); + + if (id >= afe->dais_size || id < 0) { + tr_err(&afedrv_tr, ", invalid id:%d\n", id); + return -EINVAL; + } + dai = &afe->dais[id]; + + *channel = dai->channel; + *rate = dai->rate; + *format = dai->format; + + tr_info(&afedrv_tr, "dai:%d get: format:%d, rate:%d, channel:%d\n", id, *format, *rate, + *channel); + + return 0; +} + +/* TODO, IRQ common register name need use config? */ +int afe_irq_get_status(struct mtk_base_afe *afe, int id) +{ + return 0; +} + +int afe_irq_clear(struct mtk_base_afe *afe, int id) +{ + return 0; +} + +int afe_irq_config(struct mtk_base_afe *afe, int id, unsigned int rate, unsigned int period) +{ + struct mtk_base_afe_irq *irq = &afe->irqs[id]; + int fs; + + afe_reg_update_bits(afe, irq->irq_data->irq_cnt_reg, + irq->irq_data->irq_cnt_maskbit << irq->irq_data->irq_cnt_shift, + period << irq->irq_data->irq_cnt_shift); + + /* set irq fs */ + fs = afe->irq_fs(rate); + if (fs < 0) + return -EINVAL; + + afe_reg_update_bits(afe, irq->irq_data->irq_fs_reg, + irq->irq_data->irq_fs_maskbit << irq->irq_data->irq_fs_shift, + fs << irq->irq_data->irq_fs_shift); + return 0; +} + +/* TODO, for dma based scheduler*/ +int afe_irq_enable(struct mtk_base_afe *afe, int id) +{ + return 0; +} + +int afe_irq_disable(struct mtk_base_afe *afe, int id) +{ + return 0; +} + +struct mtk_base_afe *afe_get(void) +{ + return &mtk_afe; +} + +int afe_probe(struct mtk_base_afe *afe) +{ + int i; + struct mtk_base_afe_platform *platform = &mtk_afe_platform; + + /* mtk afe already init done */ + if (afe->ref_count > 0) { + afe->ref_count++; + return 0; + } + + afe->platform_priv = platform; + afe->base = platform->base_addr; + afe->memif_32bit_supported = platform->memif_32bit_supported; + afe->memif_dl_num = platform->memif_dl_num; + + afe->base_end_offset = platform->base_end_offset; + afe->adsp2afe_addr = platform->adsp2afe_addr; + afe->afe2adsp_addr = platform->afe2adsp_addr; + afe->afe_fs = platform->afe_fs; /* must be */ + afe->irq_fs = platform->irq_fs; + if (!afe->afe_fs) + return -EINVAL; + tr_dbg(&afedrv_tr, "afe_base:0x%x\n", afe->base); + /* TODO how to get the memif number, how to sync with dmac lib */ + afe->memifs_size = platform->memif_size; + afe->memif = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct mtk_base_afe_memif) * afe->memifs_size); + if (!afe->memif) + return -ENOMEM; + + for (i = 0; i < afe->memifs_size; i++) + afe->memif[i].data = &platform->memif_datas[i]; + + /* TODO how to get the dai number, how to sync with dai lib*/ + afe->dais_size = platform->dais_size; + afe->dais = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct mtk_base_afe_dai) * afe->dais_size); + if (!afe->dais) + goto err_alloc_memif; + + /* TODO how to get the irq number */ + afe->irqs_size = platform->irqs_size; + afe->irqs = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct mtk_base_afe_irq) * afe->irqs_size); + if (!afe->irqs && afe->irqs_size) + goto err_alloc_dais; + + for (i = 0; i < afe->irqs_size; i++) + afe->irqs[i].irq_data = &platform->irq_datas[i]; + + afe->ref_count++; + + return 0; +err_alloc_dais: + rfree(afe->dais); +err_alloc_memif: + rfree(afe->memif); + + return -ENOMEM; +} + +void afe_remove(struct mtk_base_afe *afe) +{ + afe->ref_count--; + + if (afe->ref_count > 0) + return; + + if (afe->ref_count < 0) { + afe->ref_count = 0; + tr_dbg(&afedrv_tr, "afe ref_count < 0, :%d\n", afe->ref_count); + return; + } + + rfree(afe->memif); + afe->memif = NULL; + + rfree(afe->dais); + afe->dais = NULL; + + rfree(afe->irqs); + afe->irqs = NULL; +} + diff --git a/src/drivers/mediatek/afe/afe-memif.c b/src/drivers/mediatek/afe/afe-memif.c new file mode 100644 index 000000000000..1e57f5cf0289 --- /dev/null +++ b/src/drivers/mediatek/afe/afe-memif.c @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * YC Hung <yc.hung@mediatek.com> + * Chunxu Li <chunxu.li@mediatek.com> + * Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/audio/component.h> +#include <sof/drivers/afe-drv.h> +#include <sof/drivers/afe-dai.h> +#include <sof/drivers/afe-memif.h> +#include <sof/drivers/afe-sgen.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(memif); + +DECLARE_TR_CTX(memif_tr, SOF_UUID(memif_uuid), LOG_LEVEL_INFO); +LOG_MODULE_REGISTER(mtk_afe, CONFIG_SOF_LOG_LEVEL); + +struct afe_memif_dma { + int direction; /* 1 downlink, 0 uplink */ + + int memif_id; + int dai_id; + int irq_id; + struct mtk_base_afe *afe; + + uint32_t dma_base; + uint32_t dma_size; + uint32_t rptr; + uint32_t wptr; + + uint32_t period_size; + + unsigned int channel; + unsigned int rate; + unsigned int format; +}; + +/* acquire the specific DMA channel */ +static struct dma_chan_data *memif_channel_get(struct dma *dma, unsigned int req_chan) +{ + k_spinlock_key_t key; + struct dma_chan_data *channel; + + tr_dbg(&memif_tr, "MEMIF: channel_get(%d)", req_chan); + + key = k_spin_lock(&dma->lock); + if (req_chan >= dma->plat_data.channels) { + k_spin_unlock(&dma->lock, key); + tr_err(&memif_tr, "MEMIF: Channel %d out of range", req_chan); + return NULL; + } + + channel = &dma->chan[req_chan]; + if (channel->status != COMP_STATE_INIT) { + k_spin_unlock(&dma->lock, key); + tr_err(&memif_tr, "MEMIF: Cannot reuse channel %d", req_chan); + return NULL; + } + + atomic_add(&dma->num_channels_busy, 1); + channel->status = COMP_STATE_READY; + k_spin_unlock(&dma->lock, key); + + return channel; +} + +/* channel must not be running when this is called */ +static void memif_channel_put(struct dma_chan_data *channel) +{ + k_spinlock_key_t key; + + /* Assuming channel is stopped, we thus don't need hardware to + * do anything right now + */ + tr_info(&memif_tr, "MEMIF: channel_put(%d)", channel->index); + + notifier_unregister_all(NULL, channel); + + key = k_spin_lock(&channel->dma->lock); + channel->status = COMP_STATE_INIT; + atomic_sub(&channel->dma->num_channels_busy, 1); + k_spin_unlock(&channel->dma->lock, key); +} + +static int memif_start(struct dma_chan_data *channel) +{ + struct afe_memif_dma *memif = dma_chan_get_data(channel); + + tr_info(&memif_tr, "MEMIF:%d start(%d), channel_status:%d", memif->memif_id, channel->index, + channel->status); + + if (channel->status != COMP_STATE_PREPARE && channel->status != COMP_STATE_SUSPEND) + return -EINVAL; + + channel->status = COMP_STATE_ACTIVE; +#if CONFIG_TEST_SGEN + afe_sinegen_enable(); +#endif + /* Do the HW start of the DMA */ + return afe_memif_set_enable(memif->afe, memif->memif_id, 1); +} + +static int memif_release(struct dma_chan_data *channel) +{ + int ret; + struct afe_memif_dma *memif = dma_chan_get_data(channel); + + /* TODO actually handle pause/release properly? */ + tr_info(&memif_tr, "MEMIF: release(%d)", channel->index); + + if (channel->status != COMP_STATE_PAUSED) + return -EINVAL; + + channel->status = COMP_STATE_ACTIVE; + ret = afe_memif_set_enable(memif->afe, memif->memif_id, 0); + if (ret < 0) + return ret; +#if CONFIG_TEST_SGEN + afe_sinegen_disable(); +#endif + + return 0; +} + +static int memif_pause(struct dma_chan_data *channel) +{ + struct afe_memif_dma *memif = dma_chan_get_data(channel); + + /* TODO actually handle pause/release properly? */ + tr_info(&memif_tr, "MEMIF: pause(%d)", channel->index); + + if (channel->status != COMP_STATE_ACTIVE) + return -EINVAL; + + channel->status = COMP_STATE_PAUSED; + + /* Disable HW requests */ + return afe_memif_set_enable(memif->afe, memif->memif_id, 0); +} + +static int memif_stop(struct dma_chan_data *channel) +{ + struct afe_memif_dma *memif = dma_chan_get_data(channel); + + tr_info(&memif_tr, "MEMIF: stop(%d)", channel->index); + /* Validate state */ + /* TODO: Should we? */ + switch (channel->status) { + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + return 0; /* do not try to stop multiple times */ + case COMP_STATE_PAUSED: + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + channel->status = COMP_STATE_READY; + /* Disable channel */ + return afe_memif_set_enable(memif->afe, memif->memif_id, 0); +} + +static int memif_copy(struct dma_chan_data *channel, int bytes, uint32_t flags) +{ + struct afe_memif_dma *memif = dma_chan_get_data(channel); + struct dma_cb_data next = { + .channel = channel, + .elem.size = bytes, + }; + + /* TODO XRUN check, update hw ptr */ + /* TODO TBD Playback first data check */ + + /* update user hwptr */ + if (memif->direction) + memif->wptr = (memif->wptr + bytes) % memif->dma_size; + else + memif->rptr = (memif->rptr + bytes) % memif->dma_size; + tr_dbg(&memif_tr, "wptr:%u, rptr:%u", memif->wptr, memif->rptr); + + notifier_event(channel, NOTIFIER_ID_DMA_COPY, NOTIFIER_TARGET_CORE_LOCAL, &next, + sizeof(next)); + + return 0; +} + +static int memif_status(struct dma_chan_data *channel, struct dma_chan_status *status, + uint8_t direction) +{ + struct afe_memif_dma *memif = dma_chan_get_data(channel); + unsigned int hw_ptr; + + status->state = channel->status; + status->flags = 0; + + /* update current hw point */ + hw_ptr = afe_memif_get_cur_position(memif->afe, memif->memif_id); + if (!hw_ptr) { + status->r_pos = 0; + status->w_pos = 0; + status->timestamp = sof_cycle_get_64(); + return -EINVAL; + } + hw_ptr -= memif->dma_base; + if (memif->direction) + memif->rptr = hw_ptr; + else + memif->wptr = hw_ptr; + + status->r_pos = memif->rptr + memif->dma_base; + status->w_pos = memif->wptr + memif->dma_base; + status->timestamp = sof_cycle_get_64(); + return 0; +} + +/* set the DMA channel configuration, source/target address, buffer sizes */ +static int memif_set_config(struct dma_chan_data *channel, struct dma_sg_config *config) +{ + unsigned int dma_addr; + int i, dai_id, irq_id, direction, ret; + int dma_size = 0; + struct afe_memif_dma *memif = dma_chan_get_data(channel); + + channel->is_scheduling_source = config->is_scheduling_source; + channel->direction = config->direction; + + direction = afe_memif_get_direction(memif->afe, memif->memif_id); + tr_info(&memif_tr, "direction:%d, afe_dir:%d", config->direction, + direction); + + switch (config->direction) { + case DMA_DIR_MEM_TO_DEV: + if (direction != MEM_DIR_PLAYBACK) + return -EINVAL; + + dai_id = (int)AFE_HS_GET_DAI(config->dest_dev); + irq_id = (int)AFE_HS_GET_IRQ(config->dest_dev); + dma_addr = (int)config->elem_array.elems[0].src; + break; + case DMA_DIR_DEV_TO_MEM: + if (direction != MEM_DIR_CAPTURE) + return -EINVAL; + + dai_id = (int)AFE_HS_GET_DAI(config->src_dev); + irq_id = (int)AFE_HS_GET_IRQ(config->src_dev); + dma_addr = (int)config->elem_array.elems[0].dest; + tr_dbg(&memif_tr, "capture: dai_id:%d, dma_addr:%u\n", dai_id, dma_addr); + break; + default: + tr_err(&memif_tr, "afe_unsupported config direction"); + return -EINVAL; + } + + for (i = 0; i < config->elem_array.count; i++) + dma_size += (int)config->elem_array.elems[i].size; + + if (!config->cyclic) { + tr_err(&memif_tr, "afe-memif: Only cyclic configurations are supported!"); + return -ENOTSUP; + } + if (config->scatter) { + tr_err(&memif_tr, "afe-memif: scatter enabled, that is not supported for now!"); + return -ENOTSUP; + } + + memif->dai_id = dai_id; + memif->irq_id = irq_id; + memif->dma_base = dma_addr; + memif->dma_size = dma_size; + memif->direction = direction; + /* TODO risk, it may has sync problems with DAI comp */ + memif->rptr = 0; + memif->wptr = 0; + memif->period_size = config->elem_array.elems[0].size; + + /* get dai's config setting from afe driver */ + ret = afe_dai_get_config(memif->afe, dai_id, &memif->channel, &memif->rate, &memif->format); + if (ret < 0) + return ret; + + /* memif format should follow DAI component, not dai hw configuration */ + switch (config->src_width) { + case 2: + memif->format = SOF_IPC_FRAME_S16_LE; + break; + case 4: + memif->format = SOF_IPC_FRAME_S32_LE; + break; + default: + tr_err(&memif_tr, "afe-memif: not support bitwidth %u!", config->src_width); + return -ENOTSUP; + } + + /* set the afe memif parameters */ + ret = afe_memif_set_params(memif->afe, memif->memif_id, memif->channel, memif->rate, + memif->format); + if (ret < 0) + return ret; + ret = afe_memif_set_addr(memif->afe, memif->memif_id, memif->dma_base, memif->dma_size); + if (ret < 0) + return ret; + channel->status = COMP_STATE_PREPARE; + + return 0; +} + +static int memif_remove(struct dma *dma) +{ + int channel; + struct mtk_base_afe *afe = afe_get(); + + if (!dma->chan) { + tr_err(&memif_tr, "MEMIF: remove called without probe, it's a no-op"); + return 0; + } + for (channel = 0; channel < dma->plat_data.channels; channel++) { + /* TODO Disable HW requests for this channel */ + + rfree(dma_chan_get_data(&dma->chan[channel])); + } + rfree(dma->chan); + dma->chan = NULL; + + afe_remove(afe); + return 0; +} + +static int memif_probe(struct dma *dma) +{ + int channel; + int ret; + struct mtk_base_afe *afe = afe_get(); + struct afe_memif_dma *memif; + + if (!dma || dma->chan) { + tr_err(&memif_tr, "MEMIF: Repeated probe"); + return -EEXIST; + } + + /* do afe driver probe */ + ret = afe_probe(afe); + if (ret < 0) { + tr_err(&memif_tr, "MEMIF: afe_probe fail:%d", ret); + return ret; + } + + dma->chan = rzalloc(SOF_MEM_FLAG_KERNEL, + dma->plat_data.channels * sizeof(struct dma_chan_data)); + if (!dma->chan) { + tr_err(&memif_tr, "MEMIF: Probe failure, unable to allocate channel descriptors"); + return -ENOMEM; + } + + for (channel = 0; channel < dma->plat_data.channels; channel++) { + dma->chan[channel].dma = dma; + /* TODO need divide to UL and DL for different index */ + dma->chan[channel].index = channel; + dma->chan[channel].status = COMP_STATE_INIT; + + memif = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct afe_memif_dma)); + if (!memif) { + tr_err(&memif_tr, "afe-memif: %d channel %d private data alloc failed", + dma->plat_data.id, channel); + goto out; + } + + memif->afe = afe; + memif->memif_id = channel; + dma_chan_set_data(&dma->chan[channel], memif); + } + return 0; + +out: + memif_remove(dma); + + return -ENOMEM; +} + +static int memif_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd) +{ + int ret; + unsigned int period; + unsigned int sample_size; + struct afe_memif_dma *memif; + struct mtk_base_afe *afe = afe_get(); + + if (channel->status == COMP_STATE_INIT) + return 0; + + memif = dma_chan_get_data(channel); + + switch (cmd) { + case DMA_IRQ_STATUS_GET: + return afe_irq_get_status(afe, memif->irq_id); + case DMA_IRQ_CLEAR: + return afe_irq_clear(afe, memif->irq_id); + case DMA_IRQ_MASK: + return afe_irq_disable(afe, memif->irq_id); + case DMA_IRQ_UNMASK: + sample_size = ((memif->format == SOF_IPC_FRAME_S16_LE) ? 2 : 4) * memif->channel; + period = memif->period_size / sample_size; + ret = afe_irq_config(afe, memif->irq_id, memif->rate, period); + if (ret < 0) + return ret; + ret = afe_irq_enable(afe, memif->irq_id); + if (ret < 0) + return ret; + return 0; + default: + return -EINVAL; + } +} + +/* TODO need convert number to platform MACRO */ +static int memif_get_attribute(struct dma *dma, uint32_t type, uint32_t *value) +{ + switch (type) { + case DMA_ATTR_BUFFER_ALIGNMENT: + case DMA_ATTR_COPY_ALIGNMENT: + *value = 4; + break; + case DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT: +#if defined(CONFIG_SOC_SERIES_MT818X) || defined(CONFIG_SOC_MT8195) + *value = 64; +#else + *value = 16; +#endif + break; + case DMA_ATTR_BUFFER_PERIOD_COUNT: + *value = 4; + break; + default: + return -ENOENT; + } + return 0; +} + +static int memif_get_data_size(struct dma_chan_data *channel, uint32_t *avail, uint32_t *free) +{ + uint32_t hw_ptr; + struct afe_memif_dma *memif = dma_chan_get_data(channel); + + /* update hw pointer from afe memif */ + hw_ptr = afe_memif_get_cur_position(memif->afe, memif->memif_id); + tr_dbg(&memif_tr, "get_pos:0x%x, base:0x%x, dir:%d", hw_ptr, memif->dma_base, + memif->direction); + tr_dbg(&memif_tr, "dma_size:%u, period_size:%d", memif->dma_size, memif->period_size); + if (!hw_ptr) + return -EINVAL; + + hw_ptr -= memif->dma_base; + + if (memif->direction) + memif->rptr = hw_ptr; + else + memif->wptr = hw_ptr; + + *avail = (memif->wptr + memif->dma_size - memif->rptr) % memif->dma_size; + /* TODO, check if need alignment the available and free size to 1 period */ + if (memif->direction) + *avail = SOF_DIV_ROUND_UP(*avail, memif->period_size) * memif->period_size; + else + *avail = *avail / memif->period_size * memif->period_size; + + *free = memif->dma_size - *avail; + tr_dbg(&memif_tr, "r:0x%x, w:0x%x, avail:%u, free:%u ", + memif->rptr, memif->wptr, *avail, *free); + + return 0; +} + +const struct dma_ops memif_ops = { + .channel_get = memif_channel_get, + .channel_put = memif_channel_put, + .start = memif_start, + .stop = memif_stop, + .pause = memif_pause, + .release = memif_release, + .copy = memif_copy, + .status = memif_status, + .set_config = memif_set_config, + .probe = memif_probe, + .remove = memif_remove, + .interrupt = memif_interrupt, + .get_attribute = memif_get_attribute, + .get_data_size = memif_get_data_size, +}; diff --git a/src/drivers/mediatek/afe/mt8186/CMakeLists.txt b/src/drivers/mediatek/afe/mt8186/CMakeLists.txt new file mode 100644 index 000000000000..3f0653684edf --- /dev/null +++ b/src/drivers/mediatek/afe/mt8186/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_TEST_SGEN) +add_local_sources(sof afe-sgen.c) +endif() diff --git a/src/drivers/mediatek/afe/mt8186/afe-sgen.c b/src/drivers/mediatek/afe/mt8186/afe-sgen.c new file mode 100644 index 000000000000..145db9ab81db --- /dev/null +++ b/src/drivers/mediatek/afe/mt8186/afe-sgen.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ +#include <stdint.h> + +#include <sof/drivers/afe-sgen.h> +#include <sof/lib/io.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +#include <mt8186-afe-regs.h> +#include <mt8186-afe-common.h> + +SOF_DEFINE_REG_UUID(sgen_mt8186); + +DECLARE_TR_CTX(sgen_tr, SOF_UUID(sgen_mt8186_uuid), LOG_LEVEL_INFO); + +/* + * Note: TEST_SGEN for test only + * Define this TEST_SGEN to enable sine tone generator + * then output data to audio memory interface(memif), + * you can set TEST_SGEN_ID to choose output to which memif. + * e.g. set TEST_SGEN as '1' and TEST_SGEN_ID as "MT8186_MEMIF_DL2", + * the data source of DL2 will from sine generator. + */ +#define TEST_SGEN_ID MT8186_MEMIF_UL1 +#define AUDIO_TML_PD_MASK 1 +#define AUDIO_TML_PD_SHIFT 27 + +#define AFE_SGEN_FREQ_DIV_CH1_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH1_SHIFT 0 +#define AFE_SGEN_FREQ_DIV_CH2_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH2_SHIFT 12 +#define AFE_SGEN_AMP_DIV_CH1_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH1_SHIFT 5 +#define AFE_SGEN_AMP_DIV_CH2_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH2_SHIFT 17 +#define AFE_SGEN_MUTE_CH1_MASK 0x1 +#define AFE_SGEN_MUTE_CH1_SHIFT 24 +#define AFE_SGEN_MUTE_CH2_MASK 0x1 +#define AFE_SGEN_MUTE_CH2_SHIFT 25 +#define AFE_SGEN_ENABLE_MASK 0x1 +#define AFE_SGEN_ENABLE_SHIFT 26 + +#define AFE_SINEGEN_CON1_TIMING_CH1_MASK 0xf +#define AFE_SINEGEN_CON1_TIMING_CH1_SHIFT 8 +#define AFE_SINEGEN_CON1_TIMING_CH2_MASK 0xf +#define AFE_SINEGEN_CON1_TIMING_CH2_SHIFT 20 + +#define AFE_SINEGEN_LB_MODE_MSK 0xff +#define AFE_SINEGEN_LB_MODE_SHIFT 0 + +enum { + MT8186_SGEN_UL1 = 0x96, + MT8186_SGEN_UL2 = 0x86, + MT8186_SGEN_DL1 = 0x6, + MT8186_SGEN_DL2 = 0x8, +}; + +/*sgen freq div*/ +enum { + SGEN_FREQ_64D1 = 1, + SGEN_FREQ_64D2 = 2, + SGEN_FREQ_64D3 = 3, + SGEN_FREQ_64D4 = 4, + SGEN_FREQ_64D5 = 5, + SGEN_FREQ_64D6 = 6, + SGEN_FREQ_64D7 = 7, + SGEN_FREQ_64D8 = 8, +}; + +/*sgen amp div*/ +enum { + SGEN_AMP_D128 = 0, + SGEN_AMP_D64 = 1, + SGEN_AMP_D32 = 2, + SGEN_AMP_D16 = 3, + SGEN_AMP_D8 = 4, + SGEN_AMP_D4 = 5, + SGEN_AMP_D2 = 6, + SGEN_AMP_D1 = 7, +}; + +enum { + SGEN_CH_TIMING_8K = 0, + SGEN_CH_TIMING_11P025K = 1, + SGEN_CH_TIMING_12K = 2, + SGEN_CH_TIMING_384K = 3, + SGEN_CH_TIMING_16K = 4, + SGEN_CH_TIMING_22P05K = 5, + SGEN_CH_TIMING_24K = 6, + SGEN_CH_TIMING_352P8K = 7, + SGEN_CH_TIMING_32K = 8, + SGEN_CH_TIMING_44P1K = 9, + SGEN_CH_TIMING_48K = 10, + SGEN_CH_TIMING_88P2K = 11, + SGEN_CH_TIMING_96K = 12, + SGEN_CH_TIMING_176P4K = 13, + SGEN_CH_TIMING_192K = 14, +}; + +static uint32_t mt8186_sinegen_timing(uint32_t rate) +{ + uint32_t sinegen_timing; + + switch (rate) { + case 8000: + sinegen_timing = SGEN_CH_TIMING_8K; + break; + case 12000: + sinegen_timing = SGEN_CH_TIMING_12K; + break; + case 16000: + sinegen_timing = SGEN_CH_TIMING_16K; + break; + case 24000: + sinegen_timing = SGEN_CH_TIMING_24K; + break; + case 32000: + sinegen_timing = SGEN_CH_TIMING_32K; + break; + case 48000: + sinegen_timing = SGEN_CH_TIMING_48K; + break; + case 96000: + sinegen_timing = SGEN_CH_TIMING_96K; + break; + case 192000: + sinegen_timing = SGEN_CH_TIMING_192K; + break; + case 384000: + sinegen_timing = SGEN_CH_TIMING_384K; + break; + case 11025: + sinegen_timing = SGEN_CH_TIMING_11P025K; + break; + case 22050: + sinegen_timing = SGEN_CH_TIMING_22P05K; + break; + case 44100: + sinegen_timing = SGEN_CH_TIMING_44P1K; + break; + case 88200: + sinegen_timing = SGEN_CH_TIMING_88P2K; + break; + case 176400: + sinegen_timing = SGEN_CH_TIMING_176P4K; + break; + case 352800: + sinegen_timing = SGEN_CH_TIMING_352P8K; + break; + default: + sinegen_timing = SGEN_CH_TIMING_48K; + tr_err(&sgen_tr, "invalid rate %d, set default 48k ", rate); + } + tr_dbg(&sgen_tr, "rate %d, sinegen_timing %d ", rate, sinegen_timing); + return sinegen_timing; +} + +static void mtk_afe_reg_update_bits(uint32_t addr_offset, uint32_t mask, uint32_t val, int shift) +{ + io_reg_update_bits(AFE_BASE_ADDR + addr_offset, mask << shift, val << shift); +} + +static uint32_t mtk_afe_reg_read(uint32_t addr_offset) +{ + return io_reg_read(AFE_BASE_ADDR + addr_offset); +} + +static void mt8186_afe_sinegen_enable(uint32_t sgen_id, uint32_t rate, int enable) +{ + uint32_t loopback_mode, reg_1, reg_2, sinegen_timing; + + tr_dbg(&sgen_tr, "sgen_id %d, enable %d", sgen_id, enable); + + sinegen_timing = mt8186_sinegen_timing(rate); + + if (enable == 1) { + /* set loopback mode */ + switch (sgen_id) { + case MT8186_MEMIF_UL1: + loopback_mode = MT8186_SGEN_UL1; + break; + case MT8186_MEMIF_UL2: + loopback_mode = MT8186_SGEN_UL2; + break; + case MT8186_MEMIF_DL1: + loopback_mode = MT8186_SGEN_DL1; + break; + case MT8186_MEMIF_DL2: + loopback_mode = MT8186_SGEN_DL2; + break; + default: + tr_err(&sgen_tr, "invalid sgen_id %d", sgen_id); + return; + } + /* enable sinegen clock*/ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 0, AUDIO_TML_PD_SHIFT); + + /*loopback source*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON2, AFE_SINEGEN_LB_MODE_MSK, loopback_mode, + AFE_SINEGEN_LB_MODE_SHIFT); + + /* sine gen timing*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SINEGEN_CON1_TIMING_CH1_MASK, + sinegen_timing, AFE_SINEGEN_CON1_TIMING_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SINEGEN_CON1_TIMING_CH2_MASK, + sinegen_timing, AFE_SINEGEN_CON1_TIMING_CH2_SHIFT); + + /*freq div*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_FREQ_DIV_CH1_MASK, + SGEN_FREQ_64D1, AFE_SGEN_FREQ_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_FREQ_DIV_CH2_MASK, + SGEN_FREQ_64D2, AFE_SGEN_FREQ_DIV_CH2_SHIFT); + + /*amp div*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_AMP_DIV_CH1_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_AMP_DIV_CH2_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH2_SHIFT); + /* enable sgen*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_ENABLE_MASK, 1, + AFE_SGEN_ENABLE_SHIFT); + } else { + /* disable sgen*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_ENABLE_MASK, 0, + AFE_SGEN_ENABLE_SHIFT); + + /* disable sgen clock */ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 1, AUDIO_TML_PD_SHIFT); + } + + reg_1 = mtk_afe_reg_read(AFE_SINEGEN_CON0); + reg_2 = mtk_afe_reg_read(AFE_SINEGEN_CON2); + tr_dbg(&sgen_tr, "AFE_SINEGEN_CON0 0x%x, AFE_SINEGEN_CON2 0x%x", reg_1, reg_2); +} + +void afe_sinegen_enable(void) +{ + mt8186_afe_sinegen_enable(TEST_SGEN_ID, 48000, 1); +} + +void afe_sinegen_disable(void) +{ + mt8186_afe_sinegen_enable(TEST_SGEN_ID, 48000, 0); +} diff --git a/src/drivers/mediatek/afe/mt8188/CMakeLists.txt b/src/drivers/mediatek/afe/mt8188/CMakeLists.txt new file mode 100644 index 000000000000..3f0653684edf --- /dev/null +++ b/src/drivers/mediatek/afe/mt8188/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_TEST_SGEN) +add_local_sources(sof afe-sgen.c) +endif() diff --git a/src/drivers/mediatek/afe/mt8188/afe-sgen.c b/src/drivers/mediatek/afe/mt8188/afe-sgen.c new file mode 100644 index 000000000000..97223816bef9 --- /dev/null +++ b/src/drivers/mediatek/afe/mt8188/afe-sgen.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <stdint.h> + +#include <sof/drivers/afe-sgen.h> +#include <sof/lib/io.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +#include <mt8188-afe-reg.h> +#include <mt8188-afe-common.h> + +SOF_DEFINE_REG_UUID(sgen_mt8188); + +DECLARE_TR_CTX(sgen_tr, SOF_UUID(sgen_mt8188_uuid), LOG_LEVEL_INFO); + +/* + * Note: TEST_SGEN for test only + * Define this TEST_SGEN to enable sine tone generator + * then output data to audio memory interface(memif), + * you can set TEST_SGEN_ID to choose output to which memif. + * e.g. set TEST_SGEN as '1' and TEST_SGEN_ID as "MT8186_MEMIF_DL2", + * the data source of DL2 will from sine generator. + */ +#define TEST_SGEN_ID MT8188_MEMIF_DL2 +#define AUDIO_TML_PD_MASK 1 +#define AUDIO_TML_PD_SHIFT 27 + +#define AFE_SGEN_FREQ_DIV_CH1_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH1_SHIFT 0 +#define AFE_SGEN_FREQ_DIV_CH2_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH2_SHIFT 12 +#define AFE_SGEN_AMP_DIV_CH1_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH1_SHIFT 5 +#define AFE_SGEN_AMP_DIV_CH2_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH2_SHIFT 17 +#define AFE_SGEN_MUTE_CH1_MASK 0x1 +#define AFE_SGEN_MUTE_CH1_SHIFT 24 +#define AFE_SGEN_MUTE_CH2_MASK 0x1 +#define AFE_SGEN_MUTE_CH2_SHIFT 25 +#define AFE_SGEN_ENABLE_MASK 0x1 +#define AFE_SGEN_ENABLE_SHIFT 26 + +#define AFE_SINEGEN_CON1_TIMING_CH1_MASK 0x1f +#define AFE_SINEGEN_CON1_TIMING_CH1_SHIFT 16 +#define AFE_SINEGEN_CON1_TIMING_CH2_MASK 0x1f +#define AFE_SINEGEN_CON1_TIMING_CH2_SHIFT 21 + +#define AFE_SINEGEN_LB_MODE_MSK 0xff +#define AFE_SINEGEN_LB_MODE_SHIFT 24 + +enum { + MT8188_SGEN_UL5 = 0x18, + MT8188_SGEN_UL4 = 0x1f, + MT8188_SGEN_DL3 = 0x47, + MT8188_SGEN_DL2 = 0x60, +}; + +/*sgen freq div*/ +enum { + SGEN_FREQ_64D1 = 1, + SGEN_FREQ_64D2 = 2, + SGEN_FREQ_64D3 = 3, + SGEN_FREQ_64D4 = 4, + SGEN_FREQ_64D5 = 5, + SGEN_FREQ_64D6 = 6, + SGEN_FREQ_64D7 = 7, + SGEN_FREQ_64D8 = 8, +}; + +/*sgen amp div*/ +enum { + SGEN_AMP_D1 = 0, + SGEN_AMP_D2 = 1, + SGEN_AMP_D4 = 2, + SGEN_AMP_D8 = 3, + SGEN_AMP_D16 = 4, + SGEN_AMP_D32 = 5, + SGEN_AMP_D64 = 6, + SGEN_AMP_D128 = 7, +}; + +enum { + SGEN_CH_TIMING_8K = 0, + SGEN_CH_TIMING_12K = 1, + SGEN_CH_TIMING_16K = 2, + SGEN_CH_TIMING_24K = 3, + SGEN_CH_TIMING_32K = 4, + SGEN_CH_TIMING_48K = 5, + SGEN_CH_TIMING_96K = 6, + SGEN_CH_TIMING_192K = 7, + SGEN_CH_TIMING_384K = 8, + SGEN_CH_TIMING_7P35K = 16, + SGEN_CH_TIMING_11P025K = 17, + SGEN_CH_TIMING_14P7K = 18, + SGEN_CH_TIMING_22P05K = 19, + SGEN_CH_TIMING_29P4K = 20, + SGEN_CH_TIMING_44P1K = 21, + SGEN_CH_TIMING_88P2K = 22, + SGEN_CH_TIMING_176P4K = 23, + SGEN_CH_TIMING_352P8K = 24, +}; + +static uint32_t mt8188_sinegen_timing(uint32_t rate) +{ + uint32_t sinegen_timing; + + switch (rate) { + case 8000: + sinegen_timing = SGEN_CH_TIMING_8K; + break; + case 12000: + sinegen_timing = SGEN_CH_TIMING_12K; + break; + case 16000: + sinegen_timing = SGEN_CH_TIMING_16K; + break; + case 24000: + sinegen_timing = SGEN_CH_TIMING_24K; + break; + case 32000: + sinegen_timing = SGEN_CH_TIMING_32K; + break; + case 48000: + sinegen_timing = SGEN_CH_TIMING_48K; + break; + case 96000: + sinegen_timing = SGEN_CH_TIMING_96K; + break; + case 192000: + sinegen_timing = SGEN_CH_TIMING_192K; + break; + case 384000: + sinegen_timing = SGEN_CH_TIMING_384K; + break; + case 7350: + sinegen_timing = SGEN_CH_TIMING_7P35K; + break; + case 11025: + sinegen_timing = SGEN_CH_TIMING_11P025K; + break; + case 22050: + sinegen_timing = SGEN_CH_TIMING_22P05K; + break; + case 44100: + sinegen_timing = SGEN_CH_TIMING_44P1K; + break; + case 88200: + sinegen_timing = SGEN_CH_TIMING_88P2K; + break; + case 176400: + sinegen_timing = SGEN_CH_TIMING_176P4K; + break; + case 352800: + sinegen_timing = SGEN_CH_TIMING_352P8K; + break; + default: + sinegen_timing = SGEN_CH_TIMING_48K; + tr_err(&sgen_tr, "invalid rate %d, set default 48k ", rate); + } + tr_dbg(&sgen_tr, "rate %d, sinegen_timing %d ", rate, sinegen_timing); + return sinegen_timing; +} + +static void mtk_afe_reg_update_bits(uint32_t addr_offset, uint32_t mask, uint32_t val, int shift) +{ + io_reg_update_bits(AFE_BASE_ADDR + addr_offset, mask << shift, val << shift); +} + +static uint32_t mtk_afe_reg_read(uint32_t addr_offset) +{ + return io_reg_read(AFE_BASE_ADDR + addr_offset); +} + +static void mt8188_afe_sinegen_enable(uint32_t sgen_id, uint32_t rate, int enable) +{ + uint32_t loopback_mode, reg_1, reg_2, sinegen_timing; + + tr_dbg(&sgen_tr, "sgen_id %d, enable %d", sgen_id, enable); + + sinegen_timing = mt8188_sinegen_timing(rate); + + if (enable == 1) { + /* set loopback mode */ + switch (sgen_id) { + case MT8188_MEMIF_UL4: + loopback_mode = MT8188_SGEN_UL4; + break; + case MT8188_MEMIF_UL5: + loopback_mode = MT8188_SGEN_UL5; + break; + case MT8188_MEMIF_DL2: + loopback_mode = MT8188_SGEN_DL2; + break; + case MT8188_MEMIF_DL3: + loopback_mode = MT8188_SGEN_DL3; + break; + default: + tr_err(&sgen_tr, "invalid sgen_id %d", sgen_id); + return; + } + /* enable sinegen clock*/ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 0, AUDIO_TML_PD_SHIFT); + + /*loopback source*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON2, AFE_SINEGEN_LB_MODE_MSK, loopback_mode, + AFE_SINEGEN_LB_MODE_SHIFT); + + /* sine gen timing*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON1, AFE_SINEGEN_CON1_TIMING_CH1_MASK, + sinegen_timing, AFE_SINEGEN_CON1_TIMING_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON1, AFE_SINEGEN_CON1_TIMING_CH2_MASK, + sinegen_timing, AFE_SINEGEN_CON1_TIMING_CH2_SHIFT); + + /*freq div*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_FREQ_DIV_CH1_MASK, + SGEN_FREQ_64D1, AFE_SGEN_FREQ_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_FREQ_DIV_CH2_MASK, + SGEN_FREQ_64D2, AFE_SGEN_FREQ_DIV_CH2_SHIFT); + + /*amp div*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_AMP_DIV_CH1_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_AMP_DIV_CH2_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH2_SHIFT); + /* enable sgen*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_ENABLE_MASK, 1, + AFE_SGEN_ENABLE_SHIFT); + } else { + /* disable sgen*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_ENABLE_MASK, 0, + AFE_SGEN_ENABLE_SHIFT); + + /* disable sgen clock */ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 1, AUDIO_TML_PD_SHIFT); + } + + reg_1 = mtk_afe_reg_read(AFE_SINEGEN_CON0); + reg_2 = mtk_afe_reg_read(AFE_SINEGEN_CON2); + tr_dbg(&sgen_tr, "AFE_SINEGEN_CON0 0x%x, AFE_SINEGEN_CON2 0x%x", reg_1, reg_2); +} + +void afe_sinegen_enable(void) +{ + mt8188_afe_sinegen_enable(TEST_SGEN_ID, 48000, 1); +} + +void afe_sinegen_disable(void) +{ + mt8188_afe_sinegen_enable(TEST_SGEN_ID, 48000, 0); +} diff --git a/src/drivers/mediatek/afe/mt8195/CMakeLists.txt b/src/drivers/mediatek/afe/mt8195/CMakeLists.txt new file mode 100644 index 000000000000..3f0653684edf --- /dev/null +++ b/src/drivers/mediatek/afe/mt8195/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_TEST_SGEN) +add_local_sources(sof afe-sgen.c) +endif() diff --git a/src/drivers/mediatek/afe/mt8195/afe-sgen.c b/src/drivers/mediatek/afe/mt8195/afe-sgen.c new file mode 100644 index 000000000000..58478ac3aa9e --- /dev/null +++ b/src/drivers/mediatek/afe/mt8195/afe-sgen.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <stdint.h> + +#include <sof/drivers/afe-sgen.h> +#include <sof/lib/io.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +#include <mt8195-afe-regs.h> +#include <mt8195-afe-common.h> + +SOF_DEFINE_REG_UUID(sgen_mt8195); + +DECLARE_TR_CTX(sgen_tr, SOF_UUID(sgen_mt8195_uuid), LOG_LEVEL_INFO); + +/* + * Note: TEST_SGEN for test only + * Define this TEST_SGEN to enable sine tone generator + * then output data to audio memory interface(memif), + * you can set TEST_SGEN_ID to choose output to which memif. + * e.g. set TEST_SGEN as '1' and TEST_SGEN_ID as "MT8186_MEMIF_DL2", + * the data source of DL2 will from sine generator. + */ +#include <mt8195-afe-regs.h> +#include <mt8195-afe-common.h> +#define TEST_SGEN_ID MT8195_MEMIF_DL2 +#define AUDIO_TML_PD_MASK 1 +#define AUDIO_TML_PD_SHIFT 27 + +#define AFE_SGEN_FREQ_DIV_CH1_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH1_SHIFT 0 +#define AFE_SGEN_FREQ_DIV_CH2_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH2_SHIFT 12 +#define AFE_SGEN_AMP_DIV_CH1_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH1_SHIFT 5 +#define AFE_SGEN_AMP_DIV_CH2_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH2_SHIFT 17 +#define AFE_SGEN_MUTE_CH1_MASK 0x1 +#define AFE_SGEN_MUTE_CH1_SHIFT 24 +#define AFE_SGEN_MUTE_CH2_MASK 0x1 +#define AFE_SGEN_MUTE_CH2_SHIFT 25 +#define AFE_SGEN_ENABLE_MASK 0x1 +#define AFE_SGEN_ENABLE_SHIFT 26 + +#define AFE_SINEGEN_CON1_TIMING_CH1_MASK 0x1f +#define AFE_SINEGEN_CON1_TIMING_CH1_SHIFT 16 +#define AFE_SINEGEN_CON1_TIMING_CH2_MASK 0x1f +#define AFE_SINEGEN_CON1_TIMING_CH2_SHIFT 21 + +#define AFE_SINEGEN_LB_MODE_MSK 0xff +#define AFE_SINEGEN_LB_MODE_SHIFT 24 + +enum { + MT8195_SGEN_UL5 = 0x18, + MT8195_SGEN_UL4 = 0x1f, + MT8195_SGEN_DL3 = 0x47, + MT8195_SGEN_DL2 = 0x60, +}; + +/*sgen freq div*/ +enum { + SGEN_FREQ_64D1 = 1, + SGEN_FREQ_64D2 = 2, + SGEN_FREQ_64D3 = 3, + SGEN_FREQ_64D4 = 4, + SGEN_FREQ_64D5 = 5, + SGEN_FREQ_64D6 = 6, + SGEN_FREQ_64D7 = 7, + SGEN_FREQ_64D8 = 8, +}; + +/*sgen amp div*/ +enum { + SGEN_AMP_D1 = 0, + SGEN_AMP_D2 = 1, + SGEN_AMP_D4 = 2, + SGEN_AMP_D8 = 3, + SGEN_AMP_D16 = 4, + SGEN_AMP_D32 = 5, + SGEN_AMP_D64 = 6, + SGEN_AMP_D128 = 7, +}; + +enum { + SGEN_CH_TIMING_8K = 0, + SGEN_CH_TIMING_12K = 1, + SGEN_CH_TIMING_16K = 2, + SGEN_CH_TIMING_24K = 3, + SGEN_CH_TIMING_32K = 4, + SGEN_CH_TIMING_48K = 5, + SGEN_CH_TIMING_96K = 6, + SGEN_CH_TIMING_192K = 7, + SGEN_CH_TIMING_384K = 8, + SGEN_CH_TIMING_7P35K = 16, + SGEN_CH_TIMING_11P025K = 17, + SGEN_CH_TIMING_14P7K = 18, + SGEN_CH_TIMING_22P05K = 19, + SGEN_CH_TIMING_29P4K = 20, + SGEN_CH_TIMING_44P1K = 21, + SGEN_CH_TIMING_88P2K = 22, + SGEN_CH_TIMING_176P4K = 23, + SGEN_CH_TIMING_352P8K = 24, +}; + +static uint32_t mt8195_sinegen_timing(uint32_t rate) +{ + uint32_t sinegen_timing; + + switch (rate) { + case 8000: + sinegen_timing = SGEN_CH_TIMING_8K; + break; + case 12000: + sinegen_timing = SGEN_CH_TIMING_12K; + break; + case 16000: + sinegen_timing = SGEN_CH_TIMING_16K; + break; + case 24000: + sinegen_timing = SGEN_CH_TIMING_24K; + break; + case 32000: + sinegen_timing = SGEN_CH_TIMING_32K; + break; + case 48000: + sinegen_timing = SGEN_CH_TIMING_48K; + break; + case 96000: + sinegen_timing = SGEN_CH_TIMING_96K; + break; + case 192000: + sinegen_timing = SGEN_CH_TIMING_192K; + break; + case 384000: + sinegen_timing = SGEN_CH_TIMING_384K; + break; + case 7350: + sinegen_timing = SGEN_CH_TIMING_7P35K; + break; + case 11025: + sinegen_timing = SGEN_CH_TIMING_11P025K; + break; + case 14700: + sinegen_timing = SGEN_CH_TIMING_14P7K; + break; + case 22050: + sinegen_timing = SGEN_CH_TIMING_22P05K; + break; + case 29400: + sinegen_timing = SGEN_CH_TIMING_29P4K; + break; + case 44100: + sinegen_timing = SGEN_CH_TIMING_44P1K; + break; + case 88200: + sinegen_timing = SGEN_CH_TIMING_88P2K; + break; + case 176400: + sinegen_timing = SGEN_CH_TIMING_176P4K; + break; + case 352800: + sinegen_timing = SGEN_CH_TIMING_352P8K; + break; + default: + sinegen_timing = SGEN_CH_TIMING_48K; + tr_err(&sgen_tr, "invalid rate %d, set default 48k ", rate); + } + tr_dbg(&sgen_tr, "rate %d, sinegen_timing %d ", rate, sinegen_timing); + return sinegen_timing; +} + +static void mtk_afe_reg_update_bits(uint32_t addr_offset, uint32_t mask, uint32_t val, int shift) +{ + io_reg_update_bits(AFE_BASE_ADDR + addr_offset, mask << shift, val << shift); +} + +static uint32_t mtk_afe_reg_read(uint32_t addr_offset) +{ + return io_reg_read(AFE_BASE_ADDR + addr_offset); +} + +static void mt8195_afe_sinegen_enable(uint32_t sgen_id, uint32_t rate, int enable) +{ + uint32_t loopback_mode, reg_1, reg_2, sinegen_timing; + + tr_dbg(&sgen_tr, "sgen_id %d, enable %d", sgen_id, enable); + + sinegen_timing = mt8195_sinegen_timing(rate); + + if (enable == 1) { + /* set loopback mode */ + switch (sgen_id) { + case MT8195_MEMIF_UL4: + loopback_mode = MT8195_SGEN_UL4; + break; + case MT8195_MEMIF_UL5: + loopback_mode = MT8195_SGEN_UL5; + break; + case MT8195_MEMIF_DL2: + loopback_mode = MT8195_SGEN_DL2; + break; + case MT8195_MEMIF_DL3: + loopback_mode = MT8195_SGEN_DL3; + break; + default: + tr_err(&sgen_tr, "invalid sgen_id %d", sgen_id); + return; + } + /* enable sinegen clock*/ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 0, AUDIO_TML_PD_SHIFT); + + /*loopback source*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON2, AFE_SINEGEN_LB_MODE_MSK, loopback_mode, + AFE_SINEGEN_LB_MODE_SHIFT); + + /* sine gen timing*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON1, AFE_SINEGEN_CON1_TIMING_CH1_MASK, + sinegen_timing, AFE_SINEGEN_CON1_TIMING_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON1, AFE_SINEGEN_CON1_TIMING_CH2_MASK, + sinegen_timing, AFE_SINEGEN_CON1_TIMING_CH2_SHIFT); + + /*freq div*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_FREQ_DIV_CH1_MASK, + SGEN_FREQ_64D1, AFE_SGEN_FREQ_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_FREQ_DIV_CH2_MASK, + SGEN_FREQ_64D2, AFE_SGEN_FREQ_DIV_CH2_SHIFT); + + /*amp div*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_AMP_DIV_CH1_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_AMP_DIV_CH2_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH2_SHIFT); + /* enable sgen*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_ENABLE_MASK, 1, + AFE_SGEN_ENABLE_SHIFT); + } else { + /* disable sgen*/ + mtk_afe_reg_update_bits(AFE_SINEGEN_CON0, AFE_SGEN_ENABLE_MASK, 0, + AFE_SGEN_ENABLE_SHIFT); + + /* disable sgen clock */ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 1, AUDIO_TML_PD_SHIFT); + } + + reg_1 = mtk_afe_reg_read(AFE_SINEGEN_CON0); + reg_2 = mtk_afe_reg_read(AFE_SINEGEN_CON2); + tr_dbg(&sgen_tr, "AFE_SINEGEN_CON0 0x%x, AFE_SINEGEN_CON2 0x%x", reg_1, reg_2); +} + +void afe_sinegen_enable(void) +{ + mt8195_afe_sinegen_enable(TEST_SGEN_ID, 48000, 1); +} + +void afe_sinegen_disable(void) +{ + mt8195_afe_sinegen_enable(TEST_SGEN_ID, 48000, 0); +} diff --git a/src/drivers/mediatek/afe/mt8196/CMakeLists.txt b/src/drivers/mediatek/afe/mt8196/CMakeLists.txt new file mode 100755 index 000000000000..3f0653684edf --- /dev/null +++ b/src/drivers/mediatek/afe/mt8196/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_TEST_SGEN) +add_local_sources(sof afe-sgen.c) +endif() diff --git a/src/drivers/mediatek/afe/mt8196/afe-sgen.c b/src/drivers/mediatek/afe/mt8196/afe-sgen.c new file mode 100755 index 000000000000..f78b8e4a5d8d --- /dev/null +++ b/src/drivers/mediatek/afe/mt8196/afe-sgen.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Darren Ye <darren.ye@mediatek.com> + */ + +#include <stdint.h> + +#include <sof/drivers/afe-sgen.h> +#include <sof/lib/io.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> +#include <mt8196-afe-reg.h> +#include <mt8196-afe-common.h> + +void afe_sinegen_enable(void) +{ +} + +void afe_sinegen_disable(void) +{ +} diff --git a/src/drivers/mediatek/afe/mt8365/CMakeLists.txt b/src/drivers/mediatek/afe/mt8365/CMakeLists.txt new file mode 100644 index 000000000000..3f0653684edf --- /dev/null +++ b/src/drivers/mediatek/afe/mt8365/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_TEST_SGEN) +add_local_sources(sof afe-sgen.c) +endif() diff --git a/src/drivers/mediatek/afe/mt8365/afe-sgen.c b/src/drivers/mediatek/afe/mt8365/afe-sgen.c new file mode 100644 index 000000000000..e632f7ca6676 --- /dev/null +++ b/src/drivers/mediatek/afe/mt8365/afe-sgen.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <stdint.h> + +#include <sof/drivers/afe-sgen.h> +#include <sof/lib/io.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> + +#include <mt8365-afe-regs.h> +#include <mt8365-afe-common.h> + +SOF_DEFINE_REG_UUID(sgen_mt8365); + +DECLARE_TR_CTX(sgen_tr, SOF_UUID(sgen_mt8365_uuid), LOG_LEVEL_INFO); + +/* + * Note: TEST_SGEN for test only + * Define this TEST_SGEN to enable sine tone generator + * then output data to audio memory interface(memif), + * you can set TEST_SGEN_ID to choose output to which memif. + * e.g. set TEST_SGEN as '1' and TEST_SGEN_ID as "MT8365_MEMIF_DL1", + * the data source of DL2 will from sine generator. + */ +#define TEST_SGEN_ID MT8365_MEMIF_DL1 +#define AUDIO_TML_PD_MASK 1 +#define AUDIO_TML_PD_SHIFT 27 + +#define AFE_SGEN_FREQ_DIV_CH1_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH1_SHIFT 0 +#define AFE_SGEN_FREQ_DIV_CH2_MASK 0x1f +#define AFE_SGEN_FREQ_DIV_CH2_SHIFT 12 +#define AFE_SGEN_AMP_DIV_CH1_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH1_SHIFT 5 +#define AFE_SGEN_AMP_DIV_CH2_MASK 0x7 +#define AFE_SGEN_AMP_DIV_CH2_SHIFT 17 +#define AFE_SGEN_MUTE_CH1_MASK 0x1 +#define AFE_SGEN_MUTE_CH1_SHIFT 24 +#define AFE_SGEN_MUTE_CH2_MASK 0x1 +#define AFE_SGEN_MUTE_CH2_SHIFT 25 +#define AFE_SGEN_ENABLE_MASK 0x1 +#define AFE_SGEN_ENABLE_SHIFT 26 + +#define AFE_SGEN_TIMING_CH1_MASK 0x0f +#define AFE_SGEN_TIMING_CH1_SHIFT 8 +#define AFE_SGEN_TIMING_CH2_MASK 0x0f +#define AFE_SGEN_TIMING_CH2_SHIFT 20 + +#define AFE_SINEGEN_LB_MODE_MSK 0x1f +#define AFE_SINEGEN_LB_MODE_SHIFT 27 + +enum { + MT8365_SGEN_AWB = (0x3 << 1) | 1, // o5 + o6 + SGEN to out + MT8365_SGEN_VUL = (0x5 << 1) | 1, // o9 + o10 + SGEN to out + MT8365_SGEN_DL1 = (0x3 << 1) | 0, // i5 + i6 + SGEN to in + MT8365_SGEN_DL2 = (0x4 << 1) | 0 // i7 + i8 + SGEN to in +}; + +/*sgen freq div*/ +enum { + SGEN_FREQ_64D1 = 1, + SGEN_FREQ_64D2 = 2, + SGEN_FREQ_64D3 = 3, + SGEN_FREQ_64D4 = 4, + SGEN_FREQ_64D5 = 5, + SGEN_FREQ_64D6 = 6, + SGEN_FREQ_64D7 = 7, + SGEN_FREQ_64D8 = 8, +}; + +/*sgen amp div*/ +enum { + SGEN_AMP_D1 = 0, + SGEN_AMP_D2 = 1, + SGEN_AMP_D4 = 2, + SGEN_AMP_D8 = 3, + SGEN_AMP_D16 = 4, + SGEN_AMP_D32 = 5, + SGEN_AMP_D64 = 6, + SGEN_AMP_D128 = 7, +}; + +enum { + SGEN_CH_TIMING_8K = 0, + SGEN_CH_TIMING_11P025K = 1, + SGEN_CH_TIMING_12K = 2, + SGEN_CH_TIMING_16K = 4, + SGEN_CH_TIMING_22P05K = 5, + SGEN_CH_TIMING_24K = 6, + SGEN_CH_TIMING_32K = 8, + SGEN_CH_TIMING_44P1K = 9, + SGEN_CH_TIMING_48K = 10, + SGEN_CH_TIMING_88P2K = 11, + SGEN_CH_TIMING_96K = 12, + SGEN_CH_TIMING_176P4K = 13, + SGEN_CH_TIMING_192K = 14, +}; + +static uint32_t mt8365_sinegen_timing(uint32_t rate) +{ + uint32_t sinegen_timing; + + switch (rate) { + case 8000: + sinegen_timing = SGEN_CH_TIMING_8K; + break; + case 11025: + sinegen_timing = SGEN_CH_TIMING_11P025K; + break; + case 12000: + sinegen_timing = SGEN_CH_TIMING_12K; + break; + case 16000: + sinegen_timing = SGEN_CH_TIMING_16K; + break; + case 22050: + sinegen_timing = SGEN_CH_TIMING_22P05K; + break; + case 24000: + sinegen_timing = SGEN_CH_TIMING_24K; + break; + case 32000: + sinegen_timing = SGEN_CH_TIMING_32K; + break; + case 44100: + sinegen_timing = SGEN_CH_TIMING_44P1K; + break; + case 48000: + sinegen_timing = SGEN_CH_TIMING_48K; + break; + case 88200: + sinegen_timing = SGEN_CH_TIMING_88P2K; + break; + case 96000: + sinegen_timing = SGEN_CH_TIMING_96K; + break; + case 176400: + sinegen_timing = SGEN_CH_TIMING_176P4K; + break; + case 192000: + sinegen_timing = SGEN_CH_TIMING_192K; + break; + default: + sinegen_timing = SGEN_CH_TIMING_48K; + tr_err(&sgen_tr, "invalid rate %d, set default 48k ", rate); + } + tr_dbg(&sgen_tr, "rate %d, sinegen_timing %d ", rate, sinegen_timing); + return sinegen_timing; +} + +static void mtk_afe_reg_update_bits(uint32_t addr_offset, uint32_t mask, uint32_t val, int shift) +{ + io_reg_update_bits(AFE_REG_BASE + addr_offset, mask << shift, val << shift); +} + +static uint32_t mtk_afe_reg_read(uint32_t addr_offset) +{ + return io_reg_read(AFE_REG_BASE + addr_offset); +} + +static void mt8365_afe_sinegen_enable(uint32_t sgen_id, uint32_t rate, int enable) +{ + uint32_t loopback_mode, reg_1, sinegen_timing; + + tr_dbg(&sgen_tr, "sgen_id %d, enable %d", sgen_id, enable); + + sinegen_timing = mt8365_sinegen_timing(rate); + + if (enable == 1) { + /* set loopback mode */ + switch (sgen_id) { + case MT8365_MEMIF_AWB: + loopback_mode = MT8365_SGEN_AWB; + break; + case MT8365_MEMIF_VUL: + loopback_mode = MT8365_SGEN_VUL; + break; + case MT8365_MEMIF_DL1: + loopback_mode = MT8365_SGEN_DL1; + break; + case MT8365_MEMIF_DL2: + loopback_mode = MT8365_SGEN_DL2; + break; + default: + tr_err(&sgen_tr, "invalid sgen_id %d", sgen_id); + return; + } + /* enable sinegen clock*/ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 0, AUDIO_TML_PD_SHIFT); + + /*loopback source*/ + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SINEGEN_LB_MODE_MSK, loopback_mode, + AFE_SINEGEN_LB_MODE_SHIFT); + + /* sine gen timing*/ + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_TIMING_CH1_MASK, + sinegen_timing, AFE_SGEN_TIMING_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_TIMING_CH2_MASK, + sinegen_timing, AFE_SGEN_TIMING_CH2_SHIFT); + + /*freq div*/ + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_FREQ_DIV_CH1_MASK, + SGEN_FREQ_64D1, AFE_SGEN_FREQ_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_FREQ_DIV_CH2_MASK, + SGEN_FREQ_64D2, AFE_SGEN_FREQ_DIV_CH2_SHIFT); + + /*amp div*/ + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_AMP_DIV_CH1_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH1_SHIFT); + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_AMP_DIV_CH2_MASK, SGEN_AMP_D2, + AFE_SGEN_AMP_DIV_CH2_SHIFT); + /* enable sgen*/ + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_ENABLE_MASK, 1, + AFE_SGEN_ENABLE_SHIFT); + } else { + /* disable sgen*/ + mtk_afe_reg_update_bits(AFE_SGEN_CON0, AFE_SGEN_ENABLE_MASK, 0, + AFE_SGEN_ENABLE_SHIFT); + + /* disable sgen clock */ + mtk_afe_reg_update_bits(AUDIO_TOP_CON0, AUDIO_TML_PD_MASK, 1, AUDIO_TML_PD_SHIFT); + } + + reg_1 = mtk_afe_reg_read(AFE_SGEN_CON0); + tr_dbg(&sgen_tr, "AFE_SGEN_CON0 0x%x", reg_1); +} + +void afe_sinegen_enable(void) +{ + mt8365_afe_sinegen_enable(TEST_SGEN_ID, 48000, 1); +} + +void afe_sinegen_disable(void) +{ + mt8365_afe_sinegen_enable(TEST_SGEN_ID, 48000, 0); +} diff --git a/src/drivers/mediatek/mt818x/CMakeLists.txt b/src/drivers/mediatek/mt818x/CMakeLists.txt new file mode 100644 index 000000000000..179e42329834 --- /dev/null +++ b/src/drivers/mediatek/mt818x/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof interrupt.c ipc.c timer.c) + diff --git a/src/drivers/mediatek/mt818x/interrupt.c b/src/drivers/mediatek/mt818x/interrupt.c new file mode 100644 index 000000000000..cf48a3ea4eb9 --- /dev/null +++ b/src/drivers/mediatek/mt818x/interrupt.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <errno.h> +#include <inttypes.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define PENDING_IRQ_INDEX_MAX 32 + +SOF_DEFINE_REG_UUID(irq_mt818x); + +DECLARE_TR_CTX(int_tr, SOF_UUID(irq_mt818x_uuid), LOG_LEVEL_INFO); + +static void mtk_irq_init(void) +{ + /* disable all ADSP IRQ */ + io_reg_write(MTK_ADSP_IRQ_EN, 0); + + /* mask all IRQs between ADSP and other subsys */ + io_reg_write(MTK_ADSP_IRQ_MASK, MTK_DSP_OUT_IRQ_MASK); +} + +static void mtk_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + if (!desc) { + io_reg_update_bits(MTK_ADSP_IRQ_EN, BIT(irq), 0); + } else { + switch (desc->irq) { + case MTK_DSP_IRQ_MAILBOX: + io_reg_update_bits(MTK_ADSP_IRQ_EN, BIT(desc->irq), 0); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", desc->irq); + return; + } + } +} + +static void mtk_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + if (!desc) { + io_reg_update_bits(MTK_ADSP_IRQ_EN, BIT(irq), BIT(irq)); + } else { + switch (desc->irq) { + case MTK_DSP_IRQ_MAILBOX: + io_reg_update_bits(MTK_ADSP_IRQ_EN, BIT(desc->irq), BIT(desc->irq)); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", desc->irq); + return; + } + } +} + +static uint32_t mtk_irq_group_pending_status(uint32_t irq) +{ + uint32_t irq_status = 0; + + if (irq == MTK_DSP_IRQ_MAILBOX && + (io_reg_read(MTK_ADSP_IRQ_STATUS) & BIT(MTK_DSP_IRQ_MAILBOX))) { + irq_status = io_reg_read(MTK_MBOX_IRQ_IN) & MTK_DSP_MBOX_MASK; + } + + return irq_status; +} + +static uint32_t mtk_get_pending_index(uint32_t current, uint32_t *next) +{ + uint32_t index; + + if (current == 0) + return PENDING_IRQ_INDEX_MAX; + + /* ffs returns one plus the index of the least significant 1-bit of input int */ + index = ffs(current) - 1; + + /* remove the handling index from current pending status */ + *next = current & ~(1ull << index); + + return index; +} + +static inline void mtk_handle_group_pending_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint32_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + uint32_t idx; + uint32_t next_status; + bool handled; + k_spinlock_key_t key; + + idx = mtk_get_pending_index(status, &next_status); + while (idx < PENDING_IRQ_INDEX_MAX) { + handled = false; + + key = k_spin_lock(&cascade->lock); + list_for_item(clist, &cascade->child[idx].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&int_tr, "Not handle irq %u in group %u", + idx, line_index); + } + + idx = mtk_get_pending_index(next_status, &next_status); + } +} + +static inline void mtk_irq_group_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint32_t status; + + status = mtk_irq_group_pending_status(line_index); + if (status) + mtk_handle_group_pending_irq(cascade, line_index, status); + else + tr_err(&int_tr, "No pending irq in group %d", line_index); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + mtk_irq_group_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(2) + +static const char mtk_irq_mailbox[] = "mtk_irq_mailbox"; + +static const struct irq_cascade_ops irq_ops = { + .mask = mtk_irq_mask, + .unmask = mtk_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .name = mtk_irq_mailbox, + .irq = MTK_DSP_IRQ_MAILBOX, + .handler = irqhandler_2, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +int mtk_irq_group_id(uint32_t in_irq) +{ + if (in_irq >= MTK_MAX_IRQ_NUM) + in_irq -= MTK_MAX_IRQ_NUM; + + return interrupt_get_irq(in_irq, dsp_irq[0].name); +} + +void platform_interrupt_init(void) +{ + int i; + + mtk_irq_init(); + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); +} + +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); +} + +uint32_t platform_interrupt_get_enabled(void) +{ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->mask) + cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_mask(NULL, irq, 0); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->unmask) + cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_unmask(NULL, irq, 0); +} diff --git a/src/drivers/mediatek/mt818x/ipc.c b/src/drivers/mediatek/mt818x/ipc.c new file mode 100644 index 000000000000..e8a7ab3c22e5 --- /dev/null +++ b/src/drivers/mediatek/mt818x/ipc.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <ipc/trace.h> +#include <platform/drivers/mt_reg_base.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define IPC_DSPMBOX_DSP_RSP 0 +#define IPC_DSPMBOX_DSP_REQ 1 + +SOF_DEFINE_REG_UUID(ipc_task_mt818x); + +static struct ipc *local_ipc; + +struct ipc_data { + struct ipc_data_host_buffer dh_buffer; +}; + +static void mbox0_handler(void *args) +{ + uint32_t op = io_reg_read(MTK_ADSP_MBOX_IN_CMD(0)); + + /* clear interrupt */ + io_reg_write(MTK_ADSP_MBOX_IN_CMD_CLR(0), op); + ipc_schedule_process(local_ipc); +} + +static void mbox1_handler(void *args) +{ + uint32_t op = io_reg_read(MTK_ADSP_MBOX_IN_CMD(1)); + + /* clear interrupt */ + io_reg_write(MTK_ADSP_MBOX_IN_CMD_CLR(1), op); + local_ipc->is_notification_pending = false; +} + +void trigger_irq_to_host_rsp(void) +{ + io_reg_write(MTK_ADSP_MBOX_OUT_CMD(0), ADSP_IPI_OP_RSP); +} + +void trigger_irq_to_host_req(void) +{ + io_reg_write(MTK_ADSP_MBOX_OUT_CMD(1), ADSP_IPI_OP_REQ); +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; + + hdr = mailbox_validate(); + ipc_cmd(hdr); + + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + trigger_irq_to_host_rsp(); + while (ipc->pm_prepare_D3) + wait_for_interrupt(0); +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + struct ipc *ipc = ipc_get(); + + if (ipc->is_notification_pending) + return -EBUSY; + + /* now send the message */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + ipc->is_notification_pending = true; + + /* now interrupt host to tell it we have sent a message */ + trigger_irq_to_host_req(); + 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) +{ + struct ipc_data *iipc = ipc_get_drvdata(ipc); + + return &iipc->dh_buffer; +} +#endif + +int platform_ipc_init(struct ipc *ipc) +{ + int mbox_irq0, mbox_irq1; + int ret; + +#if CONFIG_HOST_PTABLE + struct ipc_data *iipc; + + iipc = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*iipc)); + if (!iipc) { + tr_err(&ipc_tr, "Unable to allocate memory for IPC data"); + sof_panic(SOF_IPC_PANIC_IPC); + } + ipc_set_drvdata(ipc, iipc); +#else + ipc_set_drvdata(ipc, NULL); +#endif + + local_ipc = ipc; + + /* schedule */ + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_mt818x_uuid), + &ipc_task_ops, ipc, 0, 0); + +#if CONFIG_HOST_PTABLE + /* allocate page table buffer */ + iipc->dh_buffer.page_table = + rzalloc(SOF_MEM_FLAG_KERNEL, PLATFORM_PAGE_TABLE_SIZE); + if (!iipc->dh_buffer.page_table) { + tr_err(&ipc_tr, "Unable to allocate host page table buffer"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + iipc->dh_buffer.dmac = dma_get(DMA_DIR_HMEM_TO_LMEM, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); + if (!iipc->dh_buffer.dmac) { + tr_err(&ipc_tr, "Unable to find DMA for host page table"); + sof_panic(SOF_IPC_PANIC_IPC); + } +#endif + + /* + * AP req -- mbox0 --> DSP + * AP <-- mbox0 -- DSP rsp + * AP <-- mbox1 -- DSP req + * AP rsp -- mbox1 --> DSP + */ + mbox_irq0 = mtk_irq_group_id(MTK_DSP_IRQ_MBOX0); + if (mbox_irq0 < 0) { + tr_err(&ipc_tr, "Invalid ipc mbox 0 IRQ:%d", mbox_irq0); + sof_panic(SOF_IPC_PANIC_IPC); + } + + mbox_irq1 = mtk_irq_group_id(MTK_DSP_IRQ_MBOX1); + if (mbox_irq1 < 0) { + tr_err(&ipc_tr, "Invalid ipc mbox 1 IRQ:%d", mbox_irq1); + sof_panic(SOF_IPC_PANIC_IPC); + } + + ret = interrupt_register(mbox_irq0, mbox0_handler, ipc); + if (ret < 0) { + tr_err(&ipc_tr, "Unable to register ipc mbox 0 IRQ"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + ret = interrupt_register(mbox_irq1, mbox1_handler, ipc); + if (ret < 0) { + tr_err(&ipc_tr, "Unable to register ipc mbox 1 IRQ"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + interrupt_enable(mbox_irq0, ipc); + interrupt_enable(mbox_irq1, ipc); + + return 0; +} diff --git a/src/drivers/mediatek/mt818x/timer.c b/src/drivers/mediatek/mt818x/timer.c new file mode 100644 index 000000000000..564708d2cdc3 --- /dev/null +++ b/src/drivers/mediatek/mt818x/timer.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <sof/audio/component_ext.h> +#include <rtos/interrupt.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <platform/drivers/timer.h> +#include <ipc/stream.h> +#include <errno.h> +#include <stdint.h> + +void platform_timer_start(struct timer *timer) +{ + /* set 26m clksrc */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_CLKSRC_BIT, + MTK_TIMER_CLK_SRC_CLK_26M); + + /* enable timer */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, + MTK_TIMER_ENABLE_BIT); + + /* enable system boot time timer */ + io_reg_update_bits(MTK_OSTIMER_CON, MTK_OSTIMER_EN_BIT, + MTK_OSTIMER_EN_BIT); +} + +void platform_timer_stop(struct timer *timer) +{ + if (timer->id > NR_TMRS) + return; + + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_ENABLE, 0); +} + +/* IRQs off in arch_timer_get_system() */ +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return platform_timer_get(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks) +{ + uint64_t time; + uint32_t flags; + uint32_t low, high; + uint32_t ticks_set; + + if (timer->id > NR_TMRS) + return -EINVAL; + + flags = arch_interrupt_global_disable(); + + low = io_reg_read(MTK_OSTIMER_CUR_L); + high = io_reg_read(MTK_OSTIMER_CUR_H); + + /* ostimer 13M counter to 26M interrupt */ + time = (((uint64_t)high << 32) | low) << 1; + + ticks_set = (ticks > time) ? ticks - time : UINT64_MAX - time + ticks; + + timer->hitimeout = ticks >> 32; + timer->lowtimeout = ticks_set; + + /* disable timer before config it */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + + /* timer reset value */ + io_reg_write(MTK_TIMER_RST_VAL(timer->id), ticks_set); + + /* clear and enable irq */ + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_CLEAR, + MTK_TIMER_IRQ_CLEAR); + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_ENABLE, + MTK_TIMER_IRQ_ENABLE); + + /* enable timer */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, + MTK_TIMER_ENABLE_BIT); + + arch_interrupt_global_enable(flags); + + return ticks; +} + +void platform_timer_clear(struct timer *timer) +{ + if (timer->id > NR_TMRS) + return; + + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_CLEAR, + MTK_TIMER_IRQ_CLEAR); +} + +uint64_t platform_timer_get(struct timer *timer) +{ + uint64_t time; + uint32_t low; + uint32_t high0; + uint32_t high1; + + if (timer->id > NR_TMRS) + return -EINVAL; + + /* 64bit reads are non atomic on xtensa so we must + * read a stable value where there is no bit 32 flipping. + */ + do { + high0 = io_reg_read(MTK_OSTIMER_CUR_H); + low = io_reg_read(MTK_OSTIMER_CUR_L); + high1 = io_reg_read(MTK_OSTIMER_CUR_H); + + /* worst case is we perform this twice so 6 * 32b clock reads */ + } while (high0 != high1); + + /* convert 13M ostimer counter value to 26M */ + time = (((uint64_t)high0 << 32) | low) << 1; + + return time; +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get host position */ + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get DAI position */ + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + posn->wallclock = timer_get_system(timer_get()) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = platform_timer_get(timer_get()); +} + +static void platform_timer_handler(void *arg) +{ + struct timer *timer = arg; + + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_CLEAR, + MTK_TIMER_IRQ_CLEAR); + + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_ENABLE, 0); + + timer->handler(timer->data); +} + +static int platform_timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) +{ + timer->handler = handler; + timer->data = arg; + timer->hitime = 0; + timer->hitimeout = 0; + + return interrupt_register(timer->irq, platform_timer_handler, timer); +} + +int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) +{ + switch (timer->id) { + case OSTIMER0: + case OSTIMER1: + case OSTIMER2: + case OSTIMER3: + return platform_timer_register(timer, handler, arg); + default: + return -EINVAL; + } +} + +void timer_unregister(struct timer *timer, void *arg) +{ + interrupt_unregister(timer->irq, arg); +} + +void timer_enable(struct timer *timer, void *arg, int core) +{ + interrupt_unmask(timer->irq, cpu_get_id()); + interrupt_enable(timer->irq, arg); +} + +void timer_disable(struct timer *timer, void *arg, int core) +{ + interrupt_disable(timer->irq, arg); + interrupt_mask(timer->irq, cpu_get_id()); +} diff --git a/src/drivers/mediatek/mt8195/CMakeLists.txt b/src/drivers/mediatek/mt8195/CMakeLists.txt new file mode 100644 index 000000000000..0c8e351f06b5 --- /dev/null +++ b/src/drivers/mediatek/mt8195/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof ipc.c timer.c interrupt.c) + diff --git a/src/drivers/mediatek/mt8195/interrupt.c b/src/drivers/mediatek/mt8195/interrupt.c new file mode 100644 index 000000000000..3aaf883600fd --- /dev/null +++ b/src/drivers/mediatek/mt8195/interrupt.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#include <sof/common.h> +#include <rtos/bit.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(interrupt); + +DECLARE_TR_CTX(int_tr, SOF_UUID(interrupt_uuid), LOG_LEVEL_INFO); + +/* os timer reg value * 77ns 13M os timer + * 1 ms: 12987* 1.5ms: 19436 + * 2 ms: 25974* 3 ms: 38961 + */ + +static void irq_mask_all(void) +{ + io_reg_update_bits(RG_DSP_IRQ_EN, 0xffffffff, 0x0); + io_reg_update_bits(DSP_IRQ_EN, 0xffffffff, 0x0); +} + +static void mtk_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + int32_t in_irq, level; + + if (!desc) { + level = GET_INTLEVEL(irq); + in_irq = GET_INTERRUPT_ID(irq); + if (level > MAX_IRQ_NUM) { + tr_err(&int_tr, "Invalid interrupt %d", irq); + return; + } + + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(in_irq), 0x0); + } else { + switch (desc->irq) { + case IRQ_EXT_DOMAIN0: + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(irq + IRQ_EXT_DOMAIN0_OFFSET), 0x0); + break; + case IRQ_EXT_DOMAIN1: + io_reg_update_bits(DSP_IRQ_EN, BIT(irq), 0x0); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", desc->irq); + return; + } + } +} + +static void mtk_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + int32_t in_irq, level; + + if (!desc) { + level = GET_INTLEVEL(irq); + in_irq = GET_INTERRUPT_ID(irq); + if (level > MAX_IRQ_NUM) { + tr_err(&int_tr, "Invalid interrupt %d", irq); + return; + } + + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(in_irq), BIT(in_irq)); + } else { + switch (desc->irq) { + case IRQ_EXT_DOMAIN0: + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(irq + IRQ_EXT_DOMAIN0_OFFSET), + BIT(irq + IRQ_EXT_DOMAIN0_OFFSET)); + break; + case IRQ_EXT_DOMAIN1: + io_reg_update_bits(DSP_IRQ_EN, BIT(irq), BIT(irq)); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", desc->irq); + return; + } + } +} + +static uint64_t mtk_get_irq_interrupts(uint32_t irq) +{ + uint32_t irq_status; + + switch (irq) { + case IRQ_NUM_EXT_LEVEL23: + irq_status = io_reg_read(DSP_IRQ_STATUS); + irq_status &= IRQ_EXT_DOMAIN2_MASK; + break; + default: + irq_status = io_reg_read(RG_DSP_IRQ_STATUS); + irq_status &= IRQ_EXT_DOMAIN1_MASK; + break; + } + return irq_status; +} + +static int get_first_irq(uint64_t ints) +{ + return ffs(ints) - 1; +} + +static inline void mtk_handle_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint64_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + k_spinlock_key_t key; + int bit; + bool handled; + + while (status) { + bit = get_first_irq(status); + handled = false; + status &= ~(1ull << bit); + + key = k_spin_lock(&cascade->lock); + + list_for_item(clist, &cascade->child[bit].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&int_tr, "irq_handler(): not handled, bit %d", bit); + if (line_index == IRQ_NUM_EXT_LEVEL23) + io_reg_update_bits(DSP_IRQ_EN, BIT(bit), 0x0); + else + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(bit), 0x0); + } + } +} + +static inline void irq_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint64_t status; + + status = mtk_get_irq_interrupts(line_index); + + if (status) + /* Handle current interrupts */ + mtk_handle_irq(cascade, line_index, status); + else + tr_err(&int_tr, "invalid interrupt status"); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + irq_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(1) +DEFINE_IRQ_HANDLER(23) + +static const char mtk_irq_ext_domain0[] = "mtk_irq_ext_domain0"; +static const char mtk_irq_ext_domain1[] = "mtk_irq_ext_domain1"; + +static const struct irq_cascade_ops irq_ops = { + .mask = mtk_irq_mask, + .unmask = mtk_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .name = mtk_irq_ext_domain0, + .irq = IRQ_NUM_EXT_LEVEL01, + .handler = irqhandler_1, + .ops = &irq_ops, + .global_mask = false, + }, + { + .name = mtk_irq_ext_domain1, + .irq = IRQ_NUM_EXT_LEVEL23, + .handler = irqhandler_23, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +uint32_t mtk_get_irq_domain_id(int32_t irq) +{ + uint32_t in_irq = GET_INTERRUPT_ID(irq); + int32_t level = GET_INTLEVEL(irq); + + if (in_irq >= DOMAIN1_MAX_IRQ_NUM) + in_irq -= DOMAIN1_MAX_IRQ_NUM; + + if (level == IRQ_EXT_DOMAIN0) + return interrupt_get_irq(in_irq, dsp_irq[0].name); + else + return interrupt_get_irq(in_irq, dsp_irq[1].name); +} + +void platform_interrupt_init(void) +{ + int i; + + irq_mask_all(); + + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); +} + +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); +} + +uint32_t platform_interrupt_get_enabled(void) +{ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->mask) + cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_mask(NULL, irq, 0); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->unmask) + cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_unmask(NULL, irq, 0); +} diff --git a/src/drivers/mediatek/mt8195/ipc.c b/src/drivers/mediatek/mt8195/ipc.c new file mode 100644 index 000000000000..cb3734d0fbc3 --- /dev/null +++ b/src/drivers/mediatek/mt8195/ipc.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <Allen-KH.Cheng@mediatek.com> + */ + +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <ipc/trace.h> +#include <platform/drivers/mt_reg_base.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define IPC_DSPMBOX_DSP_RSP 0 +#define IPC_DSPMBOX_DSP_REQ 1 + +SOF_DEFINE_REG_UUID(ipc_task); + +static struct ipc *local_ipc; + +struct ipc_data { + struct ipc_data_host_buffer dh_buffer; +}; + +static void mbox0_handler(void *args) +{ + uint32_t op = io_reg_read(MTK_DSP_MBOX_IN_CMD(0)); + + /* clear interrupt */ + io_reg_write(MTK_DSP_MBOX_IN_CMD_CLR(0), op); + ipc_schedule_process(local_ipc); +} + +static void mbox1_handler(void *args) +{ + uint32_t op = io_reg_read(MTK_DSP_MBOX_IN_CMD(1)); + + /* clear interrupt */ + io_reg_write(MTK_DSP_MBOX_IN_CMD_CLR(1), op); + local_ipc->is_notification_pending = false; +} + +void trigger_irq_to_host_rsp(void) +{ + io_reg_write(MTK_DSP_MBOX_OUT_CMD(0), ADSP_IPI_OP_RSP); +} + +void trigger_irq_to_host_req(void) +{ + io_reg_write(MTK_DSP_MBOX_OUT_CMD(1), ADSP_IPI_OP_REQ); +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; + + hdr = mailbox_validate(); + ipc_cmd(hdr); + + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + trigger_irq_to_host_rsp(); + while (ipc->pm_prepare_D3) { + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_SUSPEND_CPU_HZ); + asm volatile("waiti 15"); + } +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + struct ipc *ipc = ipc_get(); + + if (ipc->is_notification_pending) + return -EBUSY; + + /* now send the message */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + ipc->is_notification_pending = true; + + /* now interrupt host to tell it we have sent a message */ + trigger_irq_to_host_req(); + 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) +{ + struct ipc_data *iipc = ipc_get_drvdata(ipc); + + return &iipc->dh_buffer; +} +#endif + +int platform_ipc_init(struct ipc *ipc) +{ + uint32_t mbox_irq0, mbox_irq1; +#if CONFIG_HOST_PTABLE + struct ipc_data *iipc; + + iipc = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*iipc)); + if (!iipc) { + tr_err(&ipc_tr, "Unable to allocate memory for IPC data"); + sof_panic(SOF_IPC_PANIC_IPC); + } + ipc_set_drvdata(ipc, iipc); +#else + ipc_set_drvdata(ipc, NULL); +#endif + + local_ipc = ipc; + + /* schedule */ + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), &ipc_task_ops, ipc, 0, 0); + +#if CONFIG_HOST_PTABLE + /* allocate page table buffer */ + iipc->dh_buffer.page_table = + rzalloc(SOF_MEM_FLAG_KERNEL, PLATFORM_PAGE_TABLE_SIZE); + if (!iipc->dh_buffer.page_table) { + tr_err(&ipc_tr, "Unable to allocate host page table buffer"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + iipc->dh_buffer.dmac = dma_get(DMA_DIR_HMEM_TO_LMEM, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); + if (!iipc->dh_buffer.dmac) { + tr_err(&ipc_tr, "Unable to find DMA for host page table"); + sof_panic(SOF_IPC_PANIC_IPC); + } +#endif + + mbox_irq0 = mtk_get_irq_domain_id(LX_MBOX_IRQ0_B); + mbox_irq1 = mtk_get_irq_domain_id(LX_MBOX_IRQ1_B); + interrupt_register(mbox_irq0, mbox0_handler, ipc); + interrupt_register(mbox_irq1, mbox1_handler, ipc); + interrupt_enable(mbox_irq0, ipc); + interrupt_enable(mbox_irq1, ipc); + + return 0; +} diff --git a/src/drivers/mediatek/mt8195/timer.c b/src/drivers/mediatek/mt8195/timer.c new file mode 100644 index 000000000000..06ceafe7bb80 --- /dev/null +++ b/src/drivers/mediatek/mt8195/timer.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author:Fengquan Chen <fengquan.chen@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#include <sof/audio/component_ext.h> +#include <rtos/interrupt.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <platform/drivers/timer.h> +#include <ipc/stream.h> +#include <errno.h> +#include <stdint.h> + +void platform_timer_start(struct timer *timer) +{ + /*set 13M clksrc*/ + io_reg_update_bits(CNTCR, CLKSRC_BIT, 0x0); + io_reg_update_bits(CNTCR, CLKSRC_13M_BIT, CLKSRC_13M_BIT); + + /*enable timer*/ + io_reg_update_bits(CNTCR, CNT_EN_BIT, CNT_EN_BIT); +} + +void platform_timer_stop(struct timer *timer) +{ + if (timer->id > NR_TMRS) + return; + + io_reg_update_bits(TIMER_CON(timer->id), TIMER_ENABLE_BIT, 0x0); + io_reg_update_bits(TIMER_IRQ_ACK(timer->id), TIMER_IRQ_ENABLE, 0x0); +} + +/* IRQs off in arch_timer_get_system() */ +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return platform_timer_get(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks) +{ + uint64_t time; + uint32_t flags; + uint32_t low, high; + uint32_t ticks_set; + + if (timer->id > NR_TMRS) + return -EINVAL; + + flags = arch_interrupt_global_disable(); + + low = io_reg_read(OSTIMER_CUR_L); + high = io_reg_read(OSTIMER_CUR_H); + + /*ostimer 13M counter to 26M interrupt */ + time = (((uint64_t)high << 32) | low) << 1; + ticks_set = (ticks > time) ? ticks - time : UINT64_MAX - time + ticks; + timer->hitimeout = ticks >> 32; + timer->lowtimeout = ticks_set; + + /*selsect 26M clksrc*/ + io_reg_update_bits(TIMER_CON(timer->id), TIMER_CLKSRC_BIT, 0x0); + io_reg_update_bits(TIMER_CON(timer->id), + TIMER_CLK_SRC_CLK_26M << TIMER_CLK_SRC_SHIFT, + TIMER_CLK_SRC_CLK_26M << TIMER_CLK_SRC_SHIFT); + + io_reg_write(TIMER_RST_VAL(timer->id), ticks_set); + io_reg_update_bits(TIMER_IRQ_ACK(timer->id), TIMER_IRQ_CLEAR, TIMER_IRQ_CLEAR); + io_reg_update_bits(TIMER_IRQ_ACK(timer->id), TIMER_IRQ_ENABLE, TIMER_IRQ_ENABLE); + io_reg_update_bits(TIMER_CON(timer->id), TIMER_ENABLE_BIT, TIMER_ENABLE_BIT); + + arch_interrupt_global_enable(flags); + + return ticks; +} + +void platform_timer_clear(struct timer *timer) +{ + if (timer->id > NR_TMRS) + return; + + io_reg_update_bits(TIMER_IRQ_ACK(timer->id), TIMER_IRQ_CLEAR, TIMER_IRQ_CLEAR); +} + +uint64_t platform_timer_get(struct timer *timer) +{ + uint64_t time; + uint32_t low; + uint32_t high0; + uint32_t high1; + + if (timer->id > NR_TMRS) + return -EINVAL; + + /* 64bit reads are non atomic on xtensa so we must + * read a stable value where there is no bit 32 flipping. + */ + do { + high0 = io_reg_read(OSTIMER_CUR_H); + low = io_reg_read(OSTIMER_CUR_L); + high1 = io_reg_read(OSTIMER_CUR_H); + + /* worst case is we perform this twice so 6 * 32b clock reads */ + } while (high0 != high1); + + /*ostimer 13M counter to 26M interrupt */ + time = (((uint64_t)high0 << 32) | low) << 1; + + return time; +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get host position */ + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get DAI position */ + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + posn->wallclock = timer_get_system(timer_get()) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = platform_timer_get(timer_get()); +} + +static void platform_timer_handler(void *arg) +{ + struct timer *timer = arg; + + io_reg_update_bits(TIMER_IRQ_ACK(timer->id), TIMER_IRQ_CLEAR, TIMER_IRQ_CLEAR); + io_reg_update_bits(TIMER_CON(timer->id), TIMER_ENABLE_BIT, 0x0); + io_reg_update_bits(TIMER_IRQ_ACK(timer->id), TIMER_IRQ_ENABLE, 0x0); + timer->handler(timer->data); +} + +static int platform_timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) +{ + uint32_t timer_irq0; + int err; + + timer->handler = handler; + timer->data = arg; + timer->hitime = 0; + timer->hitimeout = 0; + + timer_irq0 = mtk_get_irq_domain_id(timer->irq); + err = interrupt_register(timer_irq0, platform_timer_handler, timer); + if (err < 0) + return err; + + /* enable timer interrupt */ + interrupt_enable(timer_irq0, timer); + + return err; +} + +int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) +{ + switch (timer->id) { + case OSTIMER0: + case OSTIMER1: + case OSTIMER2: + case OSTIMER3: + return platform_timer_register(timer, handler, arg); + default: + return -EINVAL; + } +} + +void timer_unregister(struct timer *timer, void *arg) +{ + interrupt_unregister(timer->irq, arg); +} + +void timer_enable(struct timer *timer, void *arg, int core) +{ + interrupt_enable(timer->irq, arg); +} + +void timer_disable(struct timer *timer, void *arg, int core) +{ + interrupt_disable(timer->irq, arg); +} diff --git a/src/drivers/mediatek/mt8196/CMakeLists.txt b/src/drivers/mediatek/mt8196/CMakeLists.txt new file mode 100644 index 000000000000..0d5d85f72215 --- /dev/null +++ b/src/drivers/mediatek/mt8196/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof interrupt.c intc.c intc_map.c ipc.c timer.c) + diff --git a/src/drivers/mediatek/mt8196/intc.c b/src/drivers/mediatek/mt8196/intc.c new file mode 100644 index 000000000000..472d6ad8e7d7 --- /dev/null +++ b/src/drivers/mediatek/mt8196/intc.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <rtos/interrupt.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <sof/lib/uuid.h> +#include <platform/drivers/interrupt.h> +#include <platform/drivers/intc.h> +#include <errno.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(intc_mt8196); +DECLARE_TR_CTX(intc_tr, SOF_UUID(intc_mt8196_uuid), LOG_LEVEL_INFO); + +static struct intc_desc_t intc_desc; + +void intc_init(void) +{ + uint32_t word, group, irq; + + for (group = 0; group < INTC_GRP_NUM; group++) { + for (word = 0; word < INTC_GRP_LEN; word++) + intc_desc.grp_irqs[group][word] = 0x0; + } + + for (word = 0; word < INTC_GRP_LEN; word++) + intc_desc.int_en[word] = 0x0; + + for (irq = 0; irq < IRQ_MAX_CHANNEL; irq++) { + intc_desc.irqs[irq].id = irq; + intc_desc.irqs[irq].group = irq2grp_map[irq]; + intc_desc.irqs[irq].pol = INTC_POL_LOW; + } + + for (word = 0; word < INTC_GRP_LEN; word++) { + io_reg_write(INTC_IRQ_EN(word), 0x0); + io_reg_write(INTC_IRQ_WAKE_EN(word), 0x0); + io_reg_write(INTC_IRQ_STAGE1_EN(word), 0x0); + io_reg_write(INTC_IRQ_POL(word), 0xFFFFFFFF); + } + + for (group = 0; group < INTC_GRP_NUM; group++) { + for (word = 0; word < INTC_GRP_LEN; word++) + io_reg_write(INTC_IRQ_GRP(group, word), 0x0); + } +} + +void intc_irq_unmask(enum IRQn_Type irq) +{ + uint32_t word; + + if (irq < IRQ_MAX_CHANNEL && intc_desc.irqs[irq].group < INTC_GRP_NUM) { + word = INTC_WORD(irq); + io_reg_update_bits(INTC_IRQ_EN(word), INTC_BIT(irq), INTC_BIT(irq)); + } else { + tr_err(&intc_tr, "Invalid INTC interrupt %d", irq); + } +} + +void intc_irq_mask(enum IRQn_Type irq) +{ + uint32_t word; + + if (irq < IRQ_MAX_CHANNEL) { + word = INTC_WORD(irq); + io_reg_update_bits(INTC_IRQ_EN(word), INTC_BIT(irq), 0); + } else { + tr_err(&intc_tr, "Invalid INTC interrupt %d", irq); + } +} + +int intc_irq_enable(enum IRQn_Type irq) +{ + uint32_t word, irq_b, group, pol; + int ret; + + if (irq < IRQ_MAX_CHANNEL && intc_desc.irqs[irq].group < INTC_GRP_NUM && + intc_desc.irqs[irq].pol < INTC_POL_NUM) { + word = INTC_WORD(irq); + irq_b = INTC_BIT(irq); + group = intc_desc.irqs[irq].group; + pol = intc_desc.irqs[irq].pol; + + intc_desc.int_en[word] |= irq_b; + intc_desc.grp_irqs[group][word] |= irq_b; + io_reg_update_bits(INTC_IRQ_EN(word), irq_b, 0); + if (pol == INTC_POL_HIGH) + io_reg_update_bits(INTC_IRQ_POL(word), irq_b, 0); + else + io_reg_update_bits(INTC_IRQ_POL(word), irq_b, irq_b); + + io_reg_update_bits(INTC_IRQ_GRP(group, word), irq_b, irq_b); + io_reg_update_bits(INTC_IRQ_EN(word), irq_b, irq_b); + + ret = 1; + } else { + tr_err(&intc_tr, "Invalid INTC interrupt %d", irq); + ret = 0; + } + + return ret; +} + +int intc_irq_disable(enum IRQn_Type irq) +{ + uint32_t word, irq_b, group; + int ret; + + if (irq < IRQ_MAX_CHANNEL && intc_desc.irqs[irq].group < INTC_GRP_NUM) { + word = INTC_WORD(irq); + irq_b = INTC_BIT(irq); + group = intc_desc.irqs[irq].group; + + intc_desc.int_en[word] &= ~irq_b; + intc_desc.grp_irqs[group][word] &= ~irq_b; + io_reg_update_bits(INTC_IRQ_EN(word), irq_b, 0); + io_reg_update_bits(INTC_IRQ_GRP(group, word), irq_b, 0); + + ret = 1; + } else { + tr_err(&intc_tr, "INTC fail to disable irq %u\n", irq); + ret = 0; + } + + return ret; +} + diff --git a/src/drivers/mediatek/mt8196/intc_map.c b/src/drivers/mediatek/mt8196/intc_map.c new file mode 100644 index 000000000000..2c3fcbba965d --- /dev/null +++ b/src/drivers/mediatek/mt8196/intc_map.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <sof/audio/component_ext.h> +#include <rtos/interrupt.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <platform/drivers/timer.h> +#include <platform/drivers/interrupt.h> +#include <ipc/stream.h> +#include <errno.h> +#include <stdint.h> + +const unsigned char grp_pri[INTC_GRP_NUM] = { + INTC_GRP0_LEVEL, INTC_GRP1_LEVEL, INTC_GRP2_LEVEL, INTC_GRP3_LEVEL, + INTC_GRP4_LEVEL, INTC_GRP5_LEVEL, INTC_GRP6_LEVEL, INTC_GRP7_LEVEL, + INTC_GRP8_LEVEL, INTC_GRP9_LEVEL, INTC_GRP10_LEVEL, INTC_GRP11_LEVEL, + INTC_GRP12_LEVEL, INTC_GRP13_LEVEL, INTC_GRP14_LEVEL, INTC_GRP15_LEVEL, +}; + +const uint8_t irq2grp_map[IRQ_MAX_CHANNEL] = { + [CCU_IRQn] = INTC_GRP1, + [SCP_IRQn] = INTC_GRP1, + [SPM_IRQn] = INTC_GRP1, + [PCIE_IRQn] = INTC_GRP1, + [INFRA_HANG_IRQn] = INTC_GRP1, + [PERI_TIMEOUT_IRQn] = INTC_GRP1, + [MBOX_C0_IRQn] = INTC_GRP2, + [MBOX_C1_IRQn] = INTC_GRP2, + [TIMER0_IRQn] = INTC_GRP1, + [TIMER1_IRQn] = INTC_GRP1, + [IPC_C0_IRQn] = INTC_GRP1, + [IPC_C1_IRQn] = INTC_GRP1, + [IPC1_RSV_IRQn] = INTC_GRP1, + [C2C_SW_C0_IRQn] = INTC_GRP1, + [C2C_SW_C1_IRQn] = INTC_GRP1, + [UART_IRQn] = INTC_GRP12, + [UART_BT_IRQn] = INTC_GRP12, + [LATENCY_MON_IRQn] = INTC_GRP11, + [BUS_TRACKER_IRQn] = INTC_GRP13, + [USB0_IRQn] = INTC_GRP8, + [USB1_IRQn] = INTC_GRP8, + [SCPVOW_IRQn] = NO_GRP, + [CCIF3_C0_IRQn] = INTC_GRP8, + [CCIF3_C1_IRQn] = INTC_GRP8, + [PWR_CTRL_IRQn] = NO_GRP, + [DMA_C0_IRQn] = INTC_GRP10, + [DMA_C1_IRQn] = NO_GRP, + [AXI_DMA0_IRQn] = INTC_GRP9, + [AXI_DMA1_IRQn] = NO_GRP, + [AUDIO_C0_IRQn] = INTC_GRP10, + [AUDIO_C1_IRQn] = INTC_GRP10, + [HIFI5_WDT_C0_IRQn] = INTC_GRP13, + [HIFI5_WDT_C1_IRQn] = INTC_GRP13, + [APU_MBOX_C0_IRQn] = INTC_GRP0, + [APU_MBOX_C1_IRQn] = INTC_GRP0, + [TIMER2_IRQn] = INTC_GRP13, + [PWR_ON_C0_IRQ] = INTC_GRP13, + [PWR_ON_C1_IRQ] = INTC_GRP13, + [WAKEUP_SRC_C0_IRQn] = INTC_GRP13, + [WAKEUP_SRC_C1_IRQn] = INTC_GRP13, + [WDT_IRQn] = NO_GRP, + [CONNSYS1_IRQn] = INTC_GRP3, + [CONNSYS3_IRQn] = INTC_GRP3, + [CONNSYS4_IRQn] = INTC_GRP3, + [CONNSYS2_IRQn] = INTC_GRP3, + [IPIC_IRQn] = INTC_GRP1, + [AXI_DMA2_IRQn] = INTC_GRP9, + [AXI_DMA3_IRQn] = NO_GRP, + [APSRC_DDREN_IRQn] = INTC_GRP4, + [LAT_MON_EMI_IRQn] = INTC_GRP11, + [LAT_MON_INFRA_IRQn] = INTC_GRP11, + [DEVAPC_VIO_IRQn] = INTC_GRP11, + [AO_INFRA_HANG_IRQn] = NO_GRP, + [BUS_TRA_EMI_IRQn] = INTC_GRP13, + [BUS_TRA_INFRA_IRQn] = INTC_GRP13, + [L2SRAM_VIO_IRQn] = INTC_GRP11, + [L2SRAM_SETERR_IRQn] = INTC_GRP11, + [PCIERC_GRP2_IRQn] = INTC_GRP8, + [PCIERC_GRP3_IRQn] = INTC_GRP8, +}; + +const uint8_t grp2hifi_irq_map[INTC_GRP_NUM] = { + [INTC_GRP0] = 0, + [INTC_GRP1] = 1, + [INTC_GRP2] = 2, + [INTC_GRP3] = 3, + [INTC_GRP4] = 4, + [INTC_GRP5] = 5, + [INTC_GRP6] = 7, + [INTC_GRP7] = 8, + [INTC_GRP8] = 9, + [INTC_GRP9] = 10, + [INTC_GRP10] = 11, + [INTC_GRP11] = 16, + [INTC_GRP12] = 17, + [INTC_GRP13] = 18, + [INTC_GRP14] = 20, + [INTC_GRP15] = 21, +}; diff --git a/src/drivers/mediatek/mt8196/interrupt.c b/src/drivers/mediatek/mt8196/interrupt.c new file mode 100644 index 000000000000..d329544cb5ae --- /dev/null +++ b/src/drivers/mediatek/mt8196/interrupt.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <errno.h> +#include <inttypes.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define PENDING_IRQ_INDEX_MAX 32 + +SOF_DEFINE_REG_UUID(irq_mt8196); + +DECLARE_TR_CTX(int_tr, SOF_UUID(irq_mt8196_uuid), LOG_LEVEL_INFO); + +static void mtk_irq_init(void) +{ + intc_init(); +} + +static void mtk_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + if (!desc) { + if (irq >= 0 && irq < IRQ_MAX_CHANNEL) + intc_irq_disable(irq); + else + tr_err(&int_tr, "Invalid interrupt num%d", irq); + } else { + switch (desc->irq) { + case MTK_DSP_IRQ_MBOX_C0: + intc_irq_disable(6); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", desc->irq); + return; + } + } +} + +static void mtk_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + if (!desc) { + if (irq >= 0 && irq < IRQ_MAX_CHANNEL) + intc_irq_enable(irq); + else + tr_err(&int_tr, "Invalid interrupt num%d", irq); + } else { + switch (desc->irq) { + case MTK_DSP_IRQ_MBOX_C0: + intc_irq_enable(6); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", desc->irq); + return; + } + } +} + +static uint32_t mtk_irq_group_pending_status(uint32_t irq) +{ + uint32_t irq_status = 0; + + if (irq == MTK_DSP_IRQ_MBOX_C0 && + (io_reg_read(INTC_IRQ_STA0) & BIT(6))) { + irq_status = io_reg_read(MTK_MBOX_IRQ_IN) & MTK_DSP_MBOX_MASK; + } + + return irq_status; +} + +static uint32_t mtk_get_pending_index(uint32_t current, uint32_t *next) +{ + uint32_t index; + + if (current == 0) + return PENDING_IRQ_INDEX_MAX; + + /* ffs returns one plus the index of the least significant 1-bit of input int */ + index = ffs(current) - 1; + + /* remove the handling index from current pending status */ + *next = current & ~(1ull << index); + + return index; +} + +static inline void mtk_handle_group_pending_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint32_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + uint32_t idx; + uint32_t next_status; + bool handled; + k_spinlock_key_t key; + + idx = mtk_get_pending_index(status, &next_status); + while (idx < PENDING_IRQ_INDEX_MAX) { + handled = false; + + key = k_spin_lock(&cascade->lock); + list_for_item(clist, &cascade->child[idx].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&int_tr, "Not handle irq %u in group %u", + idx, line_index); + } + + idx = mtk_get_pending_index(next_status, &next_status); + } +} + +static inline void mtk_irq_group_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint32_t status; + + status = mtk_irq_group_pending_status(line_index); + if (status) + mtk_handle_group_pending_irq(cascade, line_index, status); + else + tr_err(&int_tr, "No pending irq in group %d", line_index); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + mtk_irq_group_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(2) + +static const char mtk_irq_mailbox[] = "mtk_irq_mailbox"; + +static const struct irq_cascade_ops irq_ops = { + .mask = mtk_irq_mask, + .unmask = mtk_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .name = mtk_irq_mailbox, + .irq = MTK_DSP_IRQ_MBOX_C0, + .handler = irqhandler_2, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +int mtk_irq_group_id(uint32_t in_irq) +{ + if (in_irq >= MTK_MAX_IRQ_NUM) + in_irq -= MTK_MAX_IRQ_NUM; + + return interrupt_get_irq(in_irq, dsp_irq[0].name); +} + +void platform_interrupt_init(void) +{ + int i; + + mtk_irq_init(); + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); +} + +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); +} + +uint32_t platform_interrupt_get_enabled(void) +{ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->mask) + cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_mask(NULL, irq, 0); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->unmask) + cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_unmask(NULL, irq, 0); +} diff --git a/src/drivers/mediatek/mt8196/ipc.c b/src/drivers/mediatek/mt8196/ipc.c new file mode 100644 index 000000000000..dda51b495ab8 --- /dev/null +++ b/src/drivers/mediatek/mt8196/ipc.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <ipc/trace.h> +#include <platform/drivers/mt_reg_base.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define IPC_DSPMBOX_DSP_RSP 0 +#define IPC_DSPMBOX_DSP_REQ 1 + +SOF_DEFINE_REG_UUID(ipc_task_mt8196); + +static struct ipc *local_ipc; + +struct ipc_data { + struct ipc_data_host_buffer dh_buffer; +}; + +static void mbox0_handler(void *args) +{ + uint32_t op = io_reg_read(MTK_ADSP_MBOX_IN_CMD(0)); + + /* clear interrupt */ + io_reg_write(MTK_ADSP_MBOX_IN_CMD_CLR(0), op); + ipc_schedule_process(local_ipc); +} + +static void mbox1_handler(void *args) +{ + uint32_t op = io_reg_read(MTK_ADSP_MBOX_IN_CMD(1)); + + /* clear interrupt */ + io_reg_write(MTK_ADSP_MBOX_IN_CMD_CLR(1), op); + local_ipc->is_notification_pending = false; +} + +void trigger_irq_to_host_rsp(void) +{ + io_reg_write(MTK_ADSP_MBOX_OUT_CMD(0), ADSP_IPI_OP_RSP); +} + +void trigger_irq_to_host_req(void) +{ + io_reg_write(MTK_ADSP_MBOX_OUT_CMD(1), ADSP_IPI_OP_REQ); +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; + + hdr = mailbox_validate(); + ipc_cmd(hdr); + + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + trigger_irq_to_host_rsp(); + while (ipc->pm_prepare_D3) + wait_for_interrupt(0); +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + struct ipc *ipc = ipc_get(); + + if (ipc->is_notification_pending) + return -EBUSY; + + /* now send the message */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + ipc->is_notification_pending = true; + + /* now interrupt host to tell it we have sent a message */ + trigger_irq_to_host_req(); + 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) +{ + struct ipc_data *iipc = ipc_get_drvdata(ipc); + + return &iipc->dh_buffer; +} +#endif + +int platform_ipc_init(struct ipc *ipc) +{ + int mbox_irq0, mbox_irq1; + int ret; + +#if CONFIG_HOST_PTABLE + struct ipc_data *iipc; + + iipc = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*iipc)); + if (!iipc) { + tr_err(&ipc_tr, "Unable to allocate memory for IPC data"); + sof_panic(SOF_IPC_PANIC_IPC); + } + ipc_set_drvdata(ipc, iipc); +#else + ipc_set_drvdata(ipc, NULL); +#endif + + local_ipc = ipc; + + /* schedule */ + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_mt8196_uuid), + &ipc_task_ops, ipc, 0, 0); + +#if CONFIG_HOST_PTABLE + /* allocate page table buffer */ + iipc->dh_buffer.page_table = + rzalloc(SOF_MEM_FLAG_KERNEL, PLATFORM_PAGE_TABLE_SIZE); + if (!iipc->dh_buffer.page_table) { + tr_err(&ipc_tr, "Unable to allocate host page table buffer"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + iipc->dh_buffer.dmac = dma_get(DMA_DIR_HMEM_TO_LMEM, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); + if (!iipc->dh_buffer.dmac) { + tr_err(&ipc_tr, "Unable to find DMA for host page table"); + sof_panic(SOF_IPC_PANIC_IPC); + } +#endif + + /* + * AP req -- mbox0 --> DSP + * AP <-- mbox0 -- DSP rsp + * AP <-- mbox1 -- DSP req + * AP rsp -- mbox1 --> DSP + */ + mbox_irq0 = mtk_irq_group_id(MTK_DSP_IRQ_MBOX0); + if (mbox_irq0 < 0) { + tr_err(&ipc_tr, "Invalid ipc mbox 0 IRQ:%d", mbox_irq0); + sof_panic(SOF_IPC_PANIC_IPC); + } + + mbox_irq1 = mtk_irq_group_id(MTK_DSP_IRQ_MBOX1); + if (mbox_irq1 < 0) { + tr_err(&ipc_tr, "Invalid ipc mbox 1 IRQ:%d", mbox_irq1); + sof_panic(SOF_IPC_PANIC_IPC); + } + + ret = interrupt_register(mbox_irq0, mbox0_handler, ipc); + if (ret < 0) { + tr_err(&ipc_tr, "Unable to register ipc mbox 0 IRQ"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + ret = interrupt_register(mbox_irq1, mbox1_handler, ipc); + if (ret < 0) { + tr_err(&ipc_tr, "Unable to register ipc mbox 1 IRQ"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + interrupt_enable(mbox_irq0, ipc); + interrupt_enable(mbox_irq1, ipc); + + return 0; +} diff --git a/src/drivers/mediatek/mt8196/timer.c b/src/drivers/mediatek/mt8196/timer.c new file mode 100644 index 000000000000..211cd45fe19d --- /dev/null +++ b/src/drivers/mediatek/mt8196/timer.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <sof/audio/component_ext.h> +#include <rtos/interrupt.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <platform/drivers/timer.h> +#include <platform/drivers/interrupt.h> +#include <platform/drivers/intc.h> +#include <ipc/stream.h> +#include <errno.h> +#include <stdint.h> + +void platform_timer_start(struct timer *timer) +{ + /* set 26m clksrc */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_CLKSRC_BIT, + MTK_TIMER_CLK_SRC_CLK_26M); + + /* enable timer */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, + MTK_TIMER_ENABLE_BIT); + + /* enable system boot time timer */ + io_reg_update_bits(MTK_OSTIMER_CON, MTK_OSTIMER_EN_BIT, + MTK_OSTIMER_EN_BIT); +} + +void platform_timer_stop(struct timer *timer) +{ + if (timer->id > NR_TMRS) + return; + + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_ENABLE, 0); +} + +/* IRQs off in arch_timer_get_system() */ +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return platform_timer_get(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks) +{ + uint64_t time; + uint32_t flags; + uint32_t low, high; + uint32_t ticks_set; + + if (timer->id > NR_TMRS) + return -EINVAL; + + flags = arch_interrupt_global_disable(); + + low = io_reg_read(MTK_OSTIMER_CUR_L); + high = io_reg_read(MTK_OSTIMER_CUR_H); + + /* ostimer 13M counter to 26M interrupt */ + time = (((uint64_t)high << 32) | low) << 1; + + ticks_set = (ticks > time) ? ticks - time : UINT64_MAX - time + ticks; + + timer->hitimeout = ticks >> 32; + timer->lowtimeout = ticks_set; + + /* disable timer before config it */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + + /* set 26m clksrc */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_CLKSRC_BIT, + MTK_TIMER_CLK_SRC_CLK_26M); + /* timer reset value */ + io_reg_write(MTK_TIMER_RST_VAL(timer->id), ticks_set); + + /* clear and enable irq */ + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_CLEAR, + MTK_TIMER_IRQ_CLEAR); + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_ENABLE, + MTK_TIMER_IRQ_ENABLE); + + /* enable timer */ + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, + MTK_TIMER_ENABLE_BIT); + + arch_interrupt_global_enable(flags); + + return ticks; +} + +void platform_timer_clear(struct timer *timer) +{ + if (timer->id > NR_TMRS) + return; + + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_CLEAR, + MTK_TIMER_IRQ_CLEAR); +} + +uint64_t platform_timer_get(struct timer *timer) +{ + uint64_t time; + uint32_t low; + uint32_t high0; + uint32_t high1; + + if (timer->id > NR_TMRS) + return -EINVAL; + + /* 64bit reads are non atomic on xtensa so we must + * read a stable value where there is no bit 32 flipping. + */ + do { + high0 = io_reg_read(MTK_OSTIMER_CUR_H); + low = io_reg_read(MTK_OSTIMER_CUR_L); + high1 = io_reg_read(MTK_OSTIMER_CUR_H); + + /* worst case is we perform this twice so 6 * 32b clock reads */ + } while (high0 != high1); + + /* convert 13M ostimer counter value to 26M */ + time = (((uint64_t)high0 << 32) | low) << 1; + + return time; +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get host position */ + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get DAI position */ + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + posn->wallclock = timer_get_system(timer_get()) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = platform_timer_get(timer_get()); +} + +static void platform_timer_handler(void *arg) +{ + struct timer *timer = arg; + + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_CLEAR, + MTK_TIMER_IRQ_CLEAR); + + io_reg_update_bits(MTK_TIMER_CON(timer->id), MTK_TIMER_ENABLE_BIT, 0); + + io_reg_update_bits(MTK_TIMER_IRQ_ACK(timer->id), MTK_TIMER_IRQ_ENABLE, 0); + + timer->handler(timer->data); +} + +static int platform_timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) +{ + timer->handler = handler; + timer->data = arg; + timer->hitime = 0; + timer->hitimeout = 0; + + return interrupt_register(timer->irq, platform_timer_handler, timer); +} + +int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) +{ + switch (timer->id) { + case OSTIMER0: + case OSTIMER1: + case OSTIMER2: + case OSTIMER3: + return platform_timer_register(timer, handler, arg); + default: + return -EINVAL; + } +} + +void timer_unregister(struct timer *timer, void *arg) +{ + interrupt_unregister(timer->irq, arg); +} + +void timer_enable(struct timer *timer, void *arg, int core) +{ + /* enable timer interrupt */ + interrupt_enable(timer->irq, arg); + + interrupt_unmask(8, cpu_get_id()); +} + +void timer_disable(struct timer *timer, void *arg, int core) +{ + /* enable timer interrupt */ + interrupt_disable(timer->irq, arg); + interrupt_mask(8, cpu_get_id()); +} diff --git a/src/drivers/mediatek/mt8365/CMakeLists.txt b/src/drivers/mediatek/mt8365/CMakeLists.txt new file mode 100644 index 000000000000..0c8e351f06b5 --- /dev/null +++ b/src/drivers/mediatek/mt8365/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof ipc.c timer.c interrupt.c) + diff --git a/src/drivers/mediatek/mt8365/interrupt.c b/src/drivers/mediatek/mt8365/interrupt.c new file mode 100644 index 000000000000..1e341ab87a28 --- /dev/null +++ b/src/drivers/mediatek/mt8365/interrupt.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <errno.h> +#include <inttypes.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define PENDING_IRQ_INDEX_MAX 10 + +SOF_DEFINE_REG_UUID(interrupt); + +DECLARE_TR_CTX(int_tr, SOF_UUID(interrupt_uuid), LOG_LEVEL_INFO); + +static void mtk_irq_init(void) +{ + /* disable all ADSP IRQ */ + io_reg_write(RG_DSP_IRQ_EN, 0x0); +} + +static void mtk_irq_mask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + if (!desc) { + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(irq + IRQ_EXT_BIT_OFFSET), 0); + } else { + switch (desc->irq) { + case IRQ_EXT_GROUP1_BASE: + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(irq + IRQ_EXT_GROUP1_BIT_OFFSET), 0); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", irq); + return; + } + } +} + +static void mtk_irq_unmask(struct irq_desc *desc, uint32_t irq, unsigned int core) +{ + if (!desc) { + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(irq + IRQ_EXT_BIT_OFFSET), + BIT(irq + IRQ_EXT_BIT_OFFSET)); + } else { + switch (desc->irq) { + case IRQ_EXT_GROUP1_BASE: + io_reg_update_bits(RG_DSP_IRQ_EN, BIT(irq + IRQ_EXT_GROUP1_BIT_OFFSET), + BIT(irq + IRQ_EXT_GROUP1_BIT_OFFSET)); + break; + default: + tr_err(&int_tr, "Invalid interrupt %d", irq); + return; + } + } +} + +static uint32_t mtk_irq_group_pending_status(uint32_t irq) +{ + uint32_t irq_status = 0; + + if (irq == IRQ_EXT_GROUP1_BASE) { + irq_status = io_reg_read(RG_DSP_IRQ_STATUS); + irq_status &= IRQ_EXT_MASK; + } + + return irq_status; +} + +static uint32_t mtk_get_pending_index(uint32_t current, uint32_t *next) +{ + uint32_t index; + + if (current == 0) + return PENDING_IRQ_INDEX_MAX; + + /* ffs returns one plus the index of the least significant 1-bit of input int */ + index = ffs(current) - 1; + + /* remove the handling index from current pending status */ + *next = current & ~(1ull << index); + + return index; +} + +static inline void mtk_handle_group_pending_irq(struct irq_cascade_desc *cascade, + uint32_t line_index, uint32_t status) +{ + int core = cpu_get_id(); + struct list_item *clist; + struct irq_desc *child = NULL; + uint32_t idx; + uint32_t next_status; + bool handled; + k_spinlock_key_t key; + + idx = mtk_get_pending_index(status, &next_status); + while (idx < PENDING_IRQ_INDEX_MAX) { + handled = false; + + key = k_spin_lock(&cascade->lock); + list_for_item(clist, &cascade->child[idx - IRQ_EXT_GROUP1_BIT_OFFSET].list) { + child = container_of(clist, struct irq_desc, irq_list); + + if (child->handler && (child->cpu_mask & 1 << core)) { + child->handler(child->handler_arg); + handled = true; + } + } + k_spin_unlock(&cascade->lock, key); + + if (!handled) { + tr_err(&int_tr, "Not handle irq %u in group %u", + idx, line_index); + } + + idx = mtk_get_pending_index(next_status, &next_status); + } +} + +static inline void mtk_irq_group_handler(void *data, uint32_t line_index) +{ + struct irq_desc *parent = data; + struct irq_cascade_desc *cascade = + container_of(parent, struct irq_cascade_desc, desc); + uint32_t status; + + status = mtk_irq_group_pending_status(line_index); + if (status) + mtk_handle_group_pending_irq(cascade, line_index, status); + else + tr_err(&int_tr, "No pending irq in group %d", line_index); +} + +#define DEFINE_IRQ_HANDLER(n) \ + static void irqhandler_##n(void *arg) \ + { \ + mtk_irq_group_handler(arg, n); \ + } + +DEFINE_IRQ_HANDLER(1) + +static const char mtk_ext_irq[] = "mtk_ext_irq"; + +static const struct irq_cascade_ops irq_ops = { + .mask = mtk_irq_mask, + .unmask = mtk_irq_unmask, +}; + +static const struct irq_cascade_tmpl dsp_irq[] = { + { + .name = mtk_ext_irq, + .irq = IRQ_EXT_GROUP1_BASE, + .handler = irqhandler_1, + .ops = &irq_ops, + .global_mask = false, + }, +}; + +int mtk_irq_group_id(uint32_t in_irq) +{ + if (in_irq >= PLATFORM_IRQ_HW_NUM) + in_irq -= PLATFORM_IRQ_HW_NUM; + + return interrupt_get_irq(in_irq, dsp_irq[0].name); +} + +void platform_interrupt_init(void) +{ + int i; + + mtk_irq_init(); + for (i = 0; i < ARRAY_SIZE(dsp_irq); i++) + interrupt_cascade_register(dsp_irq + i); +} + +void platform_interrupt_set(uint32_t irq) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_set(irq); +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + if (interrupt_is_dsp_direct(irq)) + arch_interrupt_clear(irq); +} + +uint32_t platform_interrupt_get_enabled(void) +{ + return 0; +} + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->mask) + cascade->ops->mask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_mask(NULL, irq, 0); +} + +void interrupt_unmask(uint32_t irq, unsigned int cpu) +{ + struct irq_cascade_desc *cascade = interrupt_get_parent(irq); + + if (cascade && cascade->ops->unmask) + cascade->ops->unmask(&cascade->desc, irq - cascade->irq_base, + cpu); + else + mtk_irq_unmask(NULL, irq, 0); +} diff --git a/src/drivers/mediatek/mt8365/ipc.c b/src/drivers/mediatek/mt8365/ipc.c new file mode 100644 index 000000000000..348cd6a51f45 --- /dev/null +++ b/src/drivers/mediatek/mt8365/ipc.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <rtos/panic.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <ipc/topology.h> +#include <ipc/trace.h> +#include <platform/drivers/mt_reg_base.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(ipc_task); + +static struct ipc *local_ipc; + +struct ipc_data { + struct ipc_data_host_buffer dh_buffer; +}; + +static void irq_handler(void *args) +{ + uint32_t status; + + /* Interrupt arrived, check src */ + status = mailbox_sw_reg_read(SRAM_REG_OP_CPU2DSP); + + tr_dbg(&ipc_tr, "ipc: irq isr 0x%x", status); + + /* reply message(done) from host */ + if (status == ADSP_IPI_OP_RSP) { + /* clear interrupt */ + io_reg_update_bits(DSP_RG_INT2CIRQ, CPU2DSP_IRQ, 0); + local_ipc->is_notification_pending = false; + } + + /* new message from host */ + if (status == ADSP_IPI_OP_REQ) { + /* clear interrupt */ + io_reg_update_bits(DSP_RG_INT2CIRQ, CPU2DSP_IRQ, 0); + ipc_schedule_process(local_ipc); + } +} + +/* DSP -> HOST RSP */ +void trigger_irq_to_host_rsp(void) +{ + mailbox_sw_reg_write(SRAM_REG_OP_DSP2CPU, ADSP_IPI_OP_RSP); + /* trigger host irq */ + io_reg_update_bits(DSP_RG_INT2CIRQ, DSP2SPM_IRQ_B, 0); + io_reg_update_bits(DSP_RG_INT2CIRQ, DSP2CPU_IRQ, DSP2CPU_IRQ); +} + +/* DSP -> HOST REQ */ +void trigger_irq_to_host_req(void) +{ + mailbox_sw_reg_write(SRAM_REG_OP_DSP2CPU, ADSP_IPI_OP_REQ); + /* trigger host irq */ + io_reg_update_bits(DSP_RG_INT2CIRQ, DSP2SPM_IRQ_B, 0); + io_reg_update_bits(DSP_RG_INT2CIRQ, DSP2CPU_IRQ, DSP2CPU_IRQ); +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; + + hdr = mailbox_validate(); + ipc_cmd(hdr); + + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + trigger_irq_to_host_rsp(); + while (ipc->pm_prepare_D3) { + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_SUSPEND_CPU_HZ); + asm volatile("waiti 15"); + } +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + struct ipc *ipc = ipc_get(); + + if (ipc->is_notification_pending) + return -EBUSY; + + /* now send the message */ + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + tr_dbg(&ipc_tr, "ipc: msg tx -> 0x%x", msg->header); + + ipc->is_notification_pending = true; + + /* now interrupt host to tell it we have sent a message */ + trigger_irq_to_host_req(); + 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) +{ + struct ipc_data *iipc = ipc_get_drvdata(ipc); + + return &iipc->dh_buffer; +} +#endif + +int platform_ipc_init(struct ipc *ipc) +{ + uint32_t ipi_irq; + +#if CONFIG_HOST_PTABLE + struct ipc_data *iipc; + + iipc = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*iipc)); + if (!iipc) { + tr_err(&ipc_tr, "Unable to allocate IPC private data"); + sof_panic(SOF_IPC_PANIC_IPC); + } + ipc_set_drvdata(ipc, iipc); +#else + ipc_set_drvdata(ipc, NULL); +#endif + + local_ipc = ipc; + + /* schedule */ + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_uuid), &ipc_task_ops, ipc, 0, 0); + +#if CONFIG_HOST_PTABLE + /* allocate page table buffer */ + iipc->dh_buffer.page_table = + rzalloc(SOF_MEM_FLAG_KERNEL, PLATFORM_PAGE_TABLE_SIZE); + if (!iipc->dh_buffer.page_table) { + tr_err(&ipc_tr, "Unable to allocate host page table buffer"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + iipc->dh_buffer.dmac = dma_get(DMA_DIR_HMEM_TO_LMEM, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); + if (!iipc->dh_buffer.dmac) { + tr_err(&ipc_tr, "Unable to find DMA for host page table"); + sof_panic(SOF_IPC_PANIC_IPC); + } +#endif + + ipi_irq = mtk_irq_group_id(LX_MCU_IRQ_B); + interrupt_register(ipi_irq, irq_handler, ipc); + interrupt_enable(ipi_irq, ipc); + + return 0; +} diff --git a/src/drivers/mediatek/mt8365/timer.c b/src/drivers/mediatek/mt8365/timer.c new file mode 100644 index 000000000000..40d33a6d1b50 --- /dev/null +++ b/src/drivers/mediatek/mt8365/timer.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <sof/audio/component_ext.h> +#include <rtos/interrupt.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <platform/drivers/timer.h> +#include <ipc/stream.h> +#include <errno.h> +#include <stdint.h> + +void platform_timer_start(struct timer *timer) +{ + if (timer->id >= NR_TMRS) + return; + + /*timer use 13M clksrc*/ + /*clear irq, if pending and enable timer*/ + io_reg_write(TIMER_CON(timer->id), TIMER_IRQ_CLEAR | TIMER_ENABLE_BIT); +} + +void platform_timer_stop(struct timer *timer) +{ + if (timer->id >= NR_TMRS) + return; + + io_reg_write(TIMER_CON(timer->id), TIMER_IRQ_CLEAR | TIMER_ENABLE_BIT); + io_reg_write(TIMER_CON(timer->id), 0); + +} + +/* IRQs off in arch_timer_get_system() */ +uint64_t platform_timer_get_atomic(struct timer *timer) +{ + return platform_timer_get(timer); +} + +int64_t platform_timer_set(struct timer *timer, uint64_t ticks) +{ + uint64_t time; + uint32_t flags; + uint32_t ticks_set; + + if (timer->id >= NR_TMRS) + return -EINVAL; + + flags = arch_interrupt_global_disable(); + + time = platform_timer_get(timer); + ticks_set = (ticks > time) ? ticks - time : UINT64_MAX - time + ticks; + timer->hitimeout = ticks >> 32; + timer->lowtimeout = ticks_set; + + io_reg_write(TIMER_CNT_VAL(timer->id), ticks_set); + io_reg_write(TIMER_CON(timer->id), TIMER_IRQ_ENABLE | TIMER_ENABLE_BIT); + + arch_interrupt_global_enable(flags); + + return ticks; +} + +void platform_timer_clear(struct timer *timer) +{ + if (timer->id >= NR_TMRS) + return; + + io_reg_write(TIMER_CON(timer->id), TIMER_IRQ_CLEAR | TIMER_ENABLE_BIT); +} + +uint64_t platform_timer_get(struct timer *timer) +{ + uint64_t time; + uint32_t low, high; + + if (timer->id >= NR_TMRS) + return -EINVAL; + + /* CNTCV_H is only updated when the CNTCV_L is read. + * Always read CNTCV_L before CNTCV_H to get a valid 64-bit timestamp. + */ + low = io_reg_read(CNTCV_L); + high = io_reg_read(CNTCV_H); + time = ((uint64_t)high << 32) | low; + + return time; +} + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get host position */ + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID | SOF_TIME_HOST_64; +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get DAI position */ + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + posn->wallclock = timer_get_system(timer_get()) - posn->wallclock; + posn->flags |= SOF_TIME_WALL_VALID | SOF_TIME_WALL_64; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = platform_timer_get(timer_get()); +} + +static void platform_timer_handler(void *arg) +{ + struct timer *timer = arg; + + timer->handler(timer->data); +} + +static int platform_timer_register(struct timer *timer, void (*handler)(void *arg), void *arg) +{ + timer->handler = handler; + timer->data = arg; + timer->hitime = 0; + timer->hitimeout = 0; + + return interrupt_register(timer->irq, platform_timer_handler, timer); +} + +int timer_register(struct timer *timer, void(*handler)(void *arg), void *arg) +{ + switch (timer->id) { + case OSTIMER0: + return platform_timer_register(timer, handler, arg); + default: + return -EINVAL; + } +} + +void timer_unregister(struct timer *timer, void *arg) +{ + interrupt_unregister(timer->irq, arg); +} + +void timer_enable(struct timer *timer, void *arg, int core) +{ + interrupt_unmask(timer->irq, cpu_get_id()); + interrupt_enable(timer->irq, arg); +} + +void timer_disable(struct timer *timer, void *arg, int core) +{ + interrupt_disable(timer->irq, arg); + interrupt_mask(timer->irq, cpu_get_id()); +} diff --git a/src/idc/CMakeLists.txt b/src/idc/CMakeLists.txt new file mode 100644 index 000000000000..1cedc1f739f4 --- /dev/null +++ b/src/idc/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +is_zephyr(zephyr) +if(zephyr) + add_local_sources_ifdef(CONFIG_SMP sof idc.c) + add_local_sources(sof zephyr_idc.c) +endif() diff --git a/src/idc/Kconfig b/src/idc/Kconfig new file mode 100644 index 000000000000..d2e74c066b4d --- /dev/null +++ b/src/idc/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config IDC_TIMEOUT_US + int "Timeout for blocking IDC call, microseconds" + default 15000 + help + It may be beneficial to have different timeout values + for fast platforms (manufactured silicon) and at least + 10 times slower FPGA platforms. diff --git a/src/idc/idc.c b/src/idc/idc.c new file mode 100644 index 000000000000..bafa44299073 --- /dev/null +++ b/src/idc/idc.c @@ -0,0 +1,463 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + +#include <sof/audio/component.h> +#include <sof/audio/component_ext.h> +#include <rtos/idc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/notifier.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/uuid.h> +#include <sof/lib/watchdog.h> +#include <sof/platform.h> +#include <rtos/wait.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <sof/trace/trace.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdint.h> +#include <sof/lib/ams.h> + +#include <sof/debug/telemetry/performance_monitor.h> + +LOG_MODULE_REGISTER(idc, CONFIG_SOF_LOG_LEVEL); + +/** \brief IDC message payload per core. */ +static SHARED_DATA struct idc_payload static_payload[CONFIG_CORE_COUNT]; + +SOF_DEFINE_REG_UUID(idc); + +DECLARE_TR_CTX(idc_tr, SOF_UUID(idc_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(idc_task); + +/** + * \brief Sets IDC command status after execution. + * \param[in] status Status to be set. + * \param[in] core Id of the core for this status. + */ +static void idc_msg_status_set(int status, uint32_t core) +{ + struct idc *idc = *idc_get(); + struct idc_payload *payload = idc_payload_get(idc, core); + + *(uint32_t *)payload->data = status; +} + +/** + * \brief Retrieves IDC command status after sending message. + * \param[in] core Id of the core for this status. + * \return Last IDC message status. + */ +int idc_msg_status_get(uint32_t core) +{ + struct idc *idc = *idc_get(); + struct idc_payload *payload = idc_payload_get(idc, core); + + return *(uint32_t *)payload->data; +} + +/** + * \brief Executes IDC IPC processing message. + */ +static void idc_ipc(void) +{ + struct ipc *ipc = ipc_get(); + + ipc_cmd(ipc->comp_data); +} + +static int idc_ipc4_bind(uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_dev; + struct idc_payload *payload; + struct bind_info *bu; + + ipc_dev = ipc_get_comp_by_id(ipc_get(), comp_id); + if (!ipc_dev) + return -ENODEV; + + payload = idc_payload_get(*idc_get(), cpu_get_id()); + bu = (struct bind_info *)payload; + + return comp_bind(ipc_dev->cd, bu); +} + +static int idc_ipc4_unbind(uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_dev; + struct idc_payload *payload; + struct bind_info *bu; + + ipc_dev = ipc_get_comp_by_id(ipc_get(), comp_id); + if (!ipc_dev) + return -ENODEV; + + payload = idc_payload_get(*idc_get(), cpu_get_id()); + bu = (struct bind_info *)payload; + + return comp_unbind(ipc_dev->cd, bu); +} + +static int idc_get_attribute(uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_dev; + struct idc_payload *idc_payload; + struct get_attribute_remote_payload *get_attr_payload; + + ipc_dev = ipc_get_comp_by_id(ipc_get(), comp_id); + if (!ipc_dev) + return -ENODEV; + + idc_payload = idc_payload_get(*idc_get(), cpu_get_id()); + get_attr_payload = (struct get_attribute_remote_payload *)idc_payload; + + return comp_get_attribute(ipc_dev->cd, get_attr_payload->type, get_attr_payload->value); +} + +/** + * \brief Executes IDC component params message. + * \param[in] comp_id Component id to have params set. + * \return Error code. + */ +static int idc_params(uint32_t comp_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *ipc_dev; + struct idc *idc = *idc_get(); + struct idc_payload *payload = idc_payload_get(idc, cpu_get_id()); + struct sof_ipc_stream_params *params = + (struct sof_ipc_stream_params *)payload; + int ret; + + ipc_dev = ipc_get_comp_by_id(ipc, comp_id); + if (!ipc_dev) + return -ENODEV; + + ret = comp_params(ipc_dev->cd, params); + + + return ret; +} + +static enum task_state comp_task(void *data) +{ + if (comp_copy(data) < 0) + return SOF_TASK_STATE_COMPLETED; + + return SOF_TASK_STATE_RESCHEDULE; +} + +/** + * \brief Executes IDC component prepare message. + * \param[in] comp_id Component id to be prepared. + * \return Error code. + */ +static int idc_prepare(uint32_t comp_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *ipc_dev; + struct comp_dev *dev; + int ret; + + ipc_dev = ipc_get_comp_by_id(ipc, comp_id); + if (!ipc_dev) + return -ENODEV; + + dev = ipc_dev->cd; + + /* we're running LL on different core, so allocate our own task */ + if (!dev->task && dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) { + /* allocate task for shared component */ + dev->task = sof_heap_alloc(dev->drv->user_heap, SOF_MEM_FLAG_USER, + sizeof(*dev->task), 0); + if (!dev->task) { + ret = -ENOMEM; + goto out; + } + + memset(dev->task, 0, sizeof(*dev->task)); + ret = schedule_task_init_ll(dev->task, + SOF_UUID(idc_task_uuid), + SOF_SCHEDULE_LL_TIMER, + dev->priority, comp_task, dev, + dev->ipc_config.core, 0); + if (ret < 0) { + sof_heap_free(dev->drv->user_heap, dev->task); + goto out; + } + } + + ret = comp_prepare(ipc_dev->cd); + +out: + + return ret; +} + +/** + * \brief Executes IDC component trigger message. + * \param[in] comp_id Component id to be triggered. + * \return Error code. + */ +static int idc_trigger(uint32_t comp_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *ipc_dev; + struct idc *idc = *idc_get(); + struct idc_payload *payload = idc_payload_get(idc, cpu_get_id()); + uint32_t cmd = *(uint32_t *)payload; + + ipc_dev = ipc_get_comp_by_id(ipc, comp_id); + if (!ipc_dev) + return -ENODEV; + + return comp_trigger(ipc_dev->cd, cmd); +} + +/** + * \brief Executes IDC component reset message. + * \param[in] comp_id Component id to be reset. + * \return Error code. + */ +static int idc_reset(uint32_t comp_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *ipc_dev; + int ret; + + ipc_dev = ipc_get_comp_by_id(ipc, comp_id); + if (!ipc_dev) + return -ENODEV; + + ret = comp_reset(ipc_dev->cd); + + return ret; +} + +/** + * \brief Executes IDC component reset message. + * \param[in] comp_id Component id to be reset. + * \return Error code. + */ +static int idc_comp_free(uint32_t comp_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + int ret; + + icd = ipc_get_comp_by_id(ipc, comp_id); + if (!icd) + return -ENODEV; + + ret = ipc_comp_free(ipc, comp_id); + return ret; +} + +/** + * \brief Executes IDC pipeline set state message. + * \param[in] ppl_id Pipeline id to be triggered. + * \return Error code. + */ +static int idc_ppl_state(uint32_t ppl_id, uint32_t phase) +{ + struct ipc *ipc = ipc_get(); + struct idc *idc = *idc_get(); + struct idc_payload *payload = idc_payload_get(idc, cpu_get_id()); + struct ipc_comp_dev *ppl_icd; + uint32_t cmd = *(uint32_t *)payload; + + ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, ppl_id, IPC_COMP_IGNORE_REMOTE); + if (!ppl_icd) { + tr_err(&idc_tr, "idc: comp %d not found", ppl_id); + return IPC4_INVALID_RESOURCE_ID; + } + + /* if no phase specified, correct it to be a ONESHOT */ + if (!phase) + phase = IDC_PPL_STATE_PHASE_ONESHOT; + + if (phase & IDC_PPL_STATE_PHASE_PREPARE) { + int ret; + + ret = ipc4_pipeline_prepare(ppl_icd, cmd); + if (ret) + return ret; + } + + if (phase & IDC_PPL_STATE_PHASE_TRIGGER) { + bool delayed = false; + + return ipc4_pipeline_trigger(ppl_icd, cmd, &delayed); + } + + return 0; +} + +static void idc_prepare_d0ix(void) +{ + /* set prepare_d0ix flag, which indicates that in the next + * platform_wait_for_interrupt invocation(), core should get ready for + * d0ix power down - it is required by D0->D0ix flow, when primary + * core disables all secondary cores. + */ + platform_pm_runtime_prepare_d0ix_en(cpu_get_id()); +} + +static void idc_process_async_msg(uint32_t slot) +{ +#if CONFIG_AMS + process_incoming_message(slot); +#else + tr_err(&idc_tr, "AMS not enabled"); +#endif +} + +/** + * \brief Handle IDC secondary core crashed message. + * \param[in] header IDC message header + */ +static void idc_secondary_core_crashed(const uint32_t header) +{ + const uint32_t core = (header >> IDC_SCC_CORE_SHIFT) & IDC_SCC_CORE_MASK; + const uint32_t reason = (header >> IDC_SCC_REASON_SHIFT) & IDC_SCC_REASON_MASK; + + (void)core; + switch (reason) { +#if IS_ENABLED(CONFIG_LL_WATCHDOG) + case IDC_SCC_REASON_WATCHDOG: + watchdog_secondary_core_timeout(core); + break; +#endif + } +} + +/** + * \brief Executes IDC message based on type. + * \param[in,out] msg Pointer to IDC message. + */ +void idc_cmd(struct idc_msg *msg) +{ + uint32_t type = iTS(msg->header); + int ret = 0; + + switch (type) { +#ifndef CONFIG_PM +/* In flow with Zephyr PM this IDC is not used. + * Primary core is forcing OFF state directly via power manager. + */ + case iTS(IDC_MSG_POWER_DOWN): + cpu_power_down_core(0); + break; +#endif + case iTS(IDC_MSG_NOTIFY): + notifier_notify_remote(); + break; + case iTS(IDC_MSG_IPC): + dbg_path_hot_start_watching(); + idc_ipc(); + dbg_path_hot_stop_watching(); + break; + case iTS(IDC_MSG_BIND): + ret = idc_ipc4_bind(msg->extension); + break; + case iTS(IDC_MSG_UNBIND): + ret = idc_ipc4_unbind(msg->extension); + break; + case iTS(IDC_MSG_GET_ATTRIBUTE): + ret = idc_get_attribute(msg->extension); + break; + case iTS(IDC_MSG_FREE): + ret = idc_comp_free(msg->extension); + break; + case iTS(IDC_MSG_PARAMS): + ret = idc_params(msg->extension); + break; + case iTS(IDC_MSG_PREPARE): + ret = idc_prepare(msg->extension); + break; + case iTS(IDC_MSG_TRIGGER): + ret = idc_trigger(msg->extension); + break; + case iTS(IDC_MSG_RESET): + ret = idc_reset(msg->extension); + break; + case iTS(IDC_MSG_PPL_STATE): + ret = idc_ppl_state(msg->extension & IDC_PPL_STATE_PPL_ID_MASK, + IDC_PPL_STATE_PHASE_GET(msg->extension)); + break; + case iTS(IDC_MSG_PREPARE_D0ix): + idc_prepare_d0ix(); + break; + case iTS(IDC_MSG_SECONDARY_CORE_CRASHED): + idc_secondary_core_crashed(msg->header); + break; + case iTS(IDC_MSG_AMS): + idc_process_async_msg(IDC_HEADER_TO_AMS_SLOT_MASK(msg->header)); + break; + default: + tr_err(&idc_tr, "invalid msg->header = %u", + msg->header); + } + + idc_msg_status_set(ret, cpu_get_id()); +} + +/* Runs on each CPU */ +int idc_init(void) +{ + struct idc **idc = idc_get(); + + tr_dbg(&idc_tr, "entry"); + + /* initialize idc data */ + (*idc)->payload = platform_shared_get(static_payload, sizeof(static_payload)); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + struct io_perf_data_item init_data = {IO_PERF_IDC_ID, + cpu_get_id(), + IO_PERF_INPUT_DIRECTION, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 }; + io_perf_monitor_init_data(&(*idc)->io_perf_in_msg_count, &init_data); + init_data.direction = IO_PERF_OUTPUT_DIRECTION; + io_perf_monitor_init_data(&(*idc)->io_perf_out_msg_count, &init_data); +#endif + + /* process task */ + idc_init_thread(); + + return 0; +} + +int idc_restore(void) +{ + struct idc **idc __unused = idc_get(); + + tr_info(&idc_tr, "entry"); + + /* idc_restore() is invoked during D0->D0ix/D0ix->D0 flow. In that + * case basic core structures e.g. idc struct should be already + * allocated (in D0->D0ix primary core disables all secondary cores, but + * memory has not been powered off). + */ + assert(*idc); + + return 0; +} diff --git a/src/idc/zephyr_idc.c b/src/idc/zephyr_idc.c new file mode 100644 index 000000000000..8ffc770eb6ee --- /dev/null +++ b/src/idc/zephyr_idc.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. + +/* + * Use P4WQ to implement IDC for SOF. We create a P4 work queue per core and + * when the primary core sends a message to a secondary core, a work item from + * a static per-core array is queued accordingly. The secondary core is then + * woken up, it executes irc_handler(), which eventually calls idc_cmd() just + * like in the native SOF case. One work item per secondary core is enough + * because IDC on SOF is always synchronous, the primary core always waits for + * secondary cores to complete operation, so no races can occur. + * + * Design: + * - use K_P4WQ_ARRAY_DEFINE() to statically create one queue with one thread + * per DSP core. + * - k_p4wq_submit() + * runs on primary CPU + * send tasks to other CPUs. + */ + +#include <zephyr/kernel.h> +#include <zephyr/cache.h> + +#include <zephyr/sys/p4wq.h> +#include <rtos/idc.h> +#include <sof/init.h> +#include <sof/ipc/common.h> +#include <sof/schedule/edf_schedule.h> +#include <rtos/alloc.h> +#include <rtos/spinlock.h> +#include <ipc/topology.h> +#include <sof/trace/trace.h> +#include <sof/lib/uuid.h> + +#include <sof/debug/telemetry/performance_monitor.h> + +LOG_MODULE_REGISTER(zephyr_idc, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(zephyr_idc); + +DECLARE_TR_CTX(zephyr_idc_tr, SOF_UUID(zephyr_idc_uuid), LOG_LEVEL_INFO); + +/* + * Inter-CPU communication is only used in + * - IPC + * - Notifier + * - Power management (IDC_MSG_POWER_UP, IDC_MSG_POWER_DOWN) + */ + +#if !CONFIG_MULTICORE || !defined(CONFIG_SMP) + +void idc_init_thread(void) +{ +} + +int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return -ENOTSUP; +} + +#else + +K_P4WQ_ARRAY_DEFINE(q_zephyr_idc, CONFIG_CORE_COUNT, SOF_STACK_SIZE, + K_P4WQ_USER_CPU_MASK); + +struct zephyr_idc_msg { + struct k_p4wq_work work; + struct idc_msg msg; +}; + +static void idc_handler(struct k_p4wq_work *work) +{ + struct zephyr_idc_msg *zmsg = container_of(work, struct zephyr_idc_msg, work); + struct idc *idc = *idc_get(); + struct ipc *ipc = ipc_get(); + struct idc_msg *msg = &zmsg->msg; + int payload = -1; + k_spinlock_key_t key; + + __ASSERT_NO_MSG(!is_cached(msg)); + + if (msg->size == sizeof(int)) { + const int idc_handler_memcpy_err __unused = + memcpy_s(&payload, sizeof(payload), msg->payload, msg->size); + assert(!idc_handler_memcpy_err); + } + + idc->received_msg.core = msg->core; + idc->received_msg.header = msg->header; + idc->received_msg.extension = msg->extension; + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Increment performance counters */ + io_perf_monitor_update_data(idc->io_perf_in_msg_count, 1); +#endif + + switch (msg->header) { + case IDC_MSG_POWER_UP: + /* Run the core initialisation? */ + secondary_core_init(sof_get()); + break; + default: + idc_cmd(&idc->received_msg); + break; + case IDC_MSG_IPC: + idc_cmd(&idc->received_msg); + /* Signal the host */ + key = k_spin_lock(&ipc->lock); + ipc->task_mask &= ~IPC_TASK_SECONDARY_CORE; + ipc_complete_cmd(ipc); + k_spin_unlock(&ipc->lock, key); + } +} + +/* + * Used for *target* CPUs, since the initiator (usually core 0) can launch + * several IDC messages at once. Also we need 2 work items per target core, + * because the p4wq thread might just have returned from the work handler, but + * hasn't released the work buffer yet (hasn't set thread pointer to NULL). + * Then submitting the same work item again can result in an assertion failure. + */ +static struct zephyr_idc_msg idc_work[CONFIG_CORE_COUNT * 2]; +/* Protect the above array */ +static K_MUTEX_DEFINE(idc_mutex); + +int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + struct idc *idc = *idc_get(); + struct idc_payload *payload = idc_payload_get(idc, msg->core); + unsigned int target_cpu = msg->core; + struct zephyr_idc_msg *zmsg = idc_work + target_cpu * 2; + struct idc_msg *msg_cp = &zmsg->msg; + struct k_p4wq_work *work = &zmsg->work; + int ret; + int idc_send_memcpy_err __unused; + + k_mutex_lock(&idc_mutex, K_FOREVER); + + if (unlikely(work->thread)) { + /* See comment above the idc_work[] array. */ + zmsg++; + work = &zmsg->work; + msg_cp = &zmsg->msg; + } + + idc_send_memcpy_err = memcpy_s(msg_cp, sizeof(*msg_cp), msg, sizeof(*msg)); + assert(!idc_send_memcpy_err); + + /* Same priority as the IPC thread which is an EDF task and under Zephyr */ + work->priority = CONFIG_EDF_THREAD_PRIORITY; + work->deadline = 0; + work->handler = idc_handler; + work->sync = mode == IDC_BLOCKING; + + if (!cpu_is_core_enabled(target_cpu)) { + tr_err(&zephyr_idc_tr, "Core %u is down, cannot sent IDC message", target_cpu); + return -EACCES; + } + if (msg->payload) { + idc_send_memcpy_err = memcpy_s(payload->data, sizeof(payload->data), + msg->payload, msg->size); + assert(!idc_send_memcpy_err); + + /* Sending a message to another core, write back local payload cache */ + sys_cache_data_flush_range(payload->data, MIN(sizeof(payload->data), msg->size)); + } + + /* Temporarily store sender core ID */ + msg_cp->core = cpu_get_id(); + + __ASSERT_NO_MSG(!is_cached(msg_cp)); + + k_p4wq_submit(q_zephyr_idc + target_cpu, work); + + k_mutex_unlock(&idc_mutex); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Increment performance counters */ + io_perf_monitor_update_data(idc->io_perf_out_msg_count, 1); +#endif + + switch (mode) { + case IDC_BLOCKING: + ret = k_p4wq_wait(work, K_USEC(CONFIG_IDC_TIMEOUT_US)); + if (!ret) + /* message was sent and executed successfully, get status code */ + ret = idc_msg_status_get(msg->core); + break; + case IDC_POWER_UP: + case IDC_NON_BLOCKING: + default: + ret = 0; + } + + return ret; +} + +void idc_init_thread(void) +{ + char thread_name[] = "idc_p4wq0"; + int cpu = cpu_get_id(); + + k_p4wq_enable_static_thread(q_zephyr_idc + cpu, + _p4threads_q_zephyr_idc + cpu, BIT(cpu)); + + thread_name[sizeof(thread_name) - 2] = '0' + cpu; + k_thread_name_set(_p4threads_q_zephyr_idc + cpu, thread_name); + /* + * Assign SOF system heap to the IDC thread. Otherwise by default it + * uses the Zephyr heap for DP stack allocation + */ + k_thread_heap_assign(_p4threads_q_zephyr_idc + cpu, sof_sys_heap_get()); +} + +#endif /* CONFIG_MULTICORE */ diff --git a/src/include/README.md b/src/include/README.md new file mode 100644 index 000000000000..ca04815738e5 --- /dev/null +++ b/src/include/README.md @@ -0,0 +1,49 @@ +** SOF Header Layout ** + +Today SOF is somewhat coupled with xtensa xtos/HAL and it's own SOF RTOS logic. +This coupling is reflected in the headers where we have a mix of RTOS and +common headers at the top level ```src/include``` directory. + +Previously SOF had the following **mandatory** include PATHS + + 1) Toplevel ```src/include``` + + The top level common which included RTOS level APIs, drivers, library, IPC, debug and audio. + + 2) Platform ```$PLATFORM``` + + Platform level includes for IP configuration and IP drivers. + + 3) Architecture ```$ARCH``` + + DSP Architecture level includes that define DSP architecture. + + + ** RTOS Header Decoupling ** + + Due to the mixing of RTOS, driver and library headers at the top level include + directory it was necessary to create RTOS specific directories for RTOS specific + logic and headers i.e. + +``` +xtos/include +zephyr/include +``` + +These RTOS include directories will eventually contain RTOS specific headers +whilst common logic and structures will be placed in non RTOS directories. + +This will also mean + +```c +#include <sof/spinlock.h> +``` + +will become + +```c +#include <rtos/spinlock.h> +``` + +and will allow easier visualisation of where and why RTOS headers are being used. +This will help to eliminate cross usage of headers between RTOSes. \ No newline at end of file diff --git a/src/include/ipc/channel_map.h b/src/include/ipc/channel_map.h index cb3a4caf6e66..1de26af60f04 100644 --- a/src/include/ipc/channel_map.h +++ b/src/include/ipc/channel_map.h @@ -40,8 +40,8 @@ struct sof_ipc_channel_map { uint32_t ext_id; uint32_t ch_mask; uint32_t reserved; - int32_t ch_coeffs[0]; -} __packed; + int32_t ch_coeffs[]; +} __attribute__((packed, aligned(4))); /** * \brief Complete map for each channel of a multichannel stream. @@ -56,7 +56,7 @@ struct sof_ipc_stream_map { struct sof_ipc_cmd_hdr hdr; uint32_t num_ch_map; uint32_t reserved[3]; - struct sof_ipc_channel_map ch_map[0]; -} __packed; + struct sof_ipc_channel_map ch_map[]; +} __attribute__((packed, aligned(4))); #endif /* __IPC_CHANNEL_MAP_H__ */ diff --git a/src/include/ipc/compress_params.h b/src/include/ipc/compress_params.h new file mode 100644 index 000000000000..71c5e5f3a9f1 --- /dev/null +++ b/src/include/ipc/compress_params.h @@ -0,0 +1,456 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) AND MIT) */ +/* + * compress_params.h - codec types and parameters for compressed data + * streaming interface + * + * Copyright (C) 2011 Intel Corporation + * Authors: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> + * Vinod Koul <vinod.koul@linux.intel.com> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * The definitions in this file are derived from the OpenMAX AL version 1.1 + * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below. + * + * Copyright (c) 2007-2010 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and/or associated documentation files (the + * "Materials "), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are 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 Materials. + * + * THE MATERIALS ARE 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 + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + */ +#ifndef __SND_COMPRESS_PARAMS_H +#define __SND_COMPRESS_PARAMS_H + +#include <stdint.h> + +/* AUDIO CODECS SUPPORTED */ +#define MAX_NUM_CODECS 32 +#define MAX_NUM_CODEC_DESCRIPTORS 32 +#define MAX_NUM_BITRATES 32 +#define MAX_NUM_SAMPLE_RATES 32 + +/* Codecs are listed linearly to allow for extensibility */ +#define SND_AUDIOCODEC_PCM ((uint32_t) 0x00000001) +#define SND_AUDIOCODEC_MP3 ((uint32_t) 0x00000002) +#define SND_AUDIOCODEC_AMR ((uint32_t) 0x00000003) +#define SND_AUDIOCODEC_AMRWB ((uint32_t) 0x00000004) +#define SND_AUDIOCODEC_AMRWBPLUS ((uint32_t) 0x00000005) +#define SND_AUDIOCODEC_AAC ((uint32_t) 0x00000006) +#define SND_AUDIOCODEC_WMA ((uint32_t) 0x00000007) +#define SND_AUDIOCODEC_REAL ((uint32_t) 0x00000008) +#define SND_AUDIOCODEC_VORBIS ((uint32_t) 0x00000009) +#define SND_AUDIOCODEC_FLAC ((uint32_t) 0x0000000A) +#define SND_AUDIOCODEC_IEC61937 ((uint32_t) 0x0000000B) +#define SND_AUDIOCODEC_G723_1 ((uint32_t) 0x0000000C) +#define SND_AUDIOCODEC_G729 ((uint32_t) 0x0000000D) +#define SND_AUDIOCODEC_BESPOKE ((uint32_t) 0x0000000E) +#define SND_AUDIOCODEC_ALAC ((uint32_t) 0x0000000F) +#define SND_AUDIOCODEC_APE ((uint32_t) 0x00000010) +#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_APE + +/* + * Profile and modes are listed with bit masks. This allows for a + * more compact representation of fields that will not evolve + * (in contrast to the list of codecs) + */ + +#define SND_AUDIOPROFILE_PCM ((uint32_t) 0x00000001) + +/* MP3 modes are only useful for encoders */ +#define SND_AUDIOCHANMODE_MP3_MONO ((uint32_t) 0x00000001) +#define SND_AUDIOCHANMODE_MP3_STEREO ((uint32_t) 0x00000002) +#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO ((uint32_t) 0x00000004) +#define SND_AUDIOCHANMODE_MP3_DUAL ((uint32_t) 0x00000008) + +#define SND_AUDIOPROFILE_AMR ((uint32_t) 0x00000001) + +/* AMR modes are only useful for encoders */ +#define SND_AUDIOMODE_AMR_DTX_OFF ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_AMR_VAD1 ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_AMR_VAD2 ((uint32_t) 0x00000004) + +#define SND_AUDIOSTREAMFORMAT_UNDEFINED ((uint32_t) 0x00000000) +#define SND_AUDIOSTREAMFORMAT_CONFORMANCE ((uint32_t) 0x00000001) +#define SND_AUDIOSTREAMFORMAT_IF1 ((uint32_t) 0x00000002) +#define SND_AUDIOSTREAMFORMAT_IF2 ((uint32_t) 0x00000004) +#define SND_AUDIOSTREAMFORMAT_FSF ((uint32_t) 0x00000008) +#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD ((uint32_t) 0x00000010) +#define SND_AUDIOSTREAMFORMAT_ITU ((uint32_t) 0x00000020) + +#define SND_AUDIOPROFILE_AMRWB ((uint32_t) 0x00000001) + +/* AMRWB modes are only useful for encoders */ +#define SND_AUDIOMODE_AMRWB_DTX_OFF ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_AMRWB_VAD1 ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_AMRWB_VAD2 ((uint32_t) 0x00000004) + +#define SND_AUDIOPROFILE_AMRWBPLUS ((uint32_t) 0x00000001) + +#define SND_AUDIOPROFILE_AAC ((uint32_t) 0x00000001) + +/* AAC modes are required for encoders and decoders */ +#define SND_AUDIOMODE_AAC_MAIN ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_AAC_LC ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_AAC_SSR ((uint32_t) 0x00000004) +#define SND_AUDIOMODE_AAC_LTP ((uint32_t) 0x00000008) +#define SND_AUDIOMODE_AAC_HE ((uint32_t) 0x00000010) +#define SND_AUDIOMODE_AAC_SCALABLE ((uint32_t) 0x00000020) +#define SND_AUDIOMODE_AAC_ERLC ((uint32_t) 0x00000040) +#define SND_AUDIOMODE_AAC_LD ((uint32_t) 0x00000080) +#define SND_AUDIOMODE_AAC_HE_PS ((uint32_t) 0x00000100) +#define SND_AUDIOMODE_AAC_HE_MPS ((uint32_t) 0x00000200) + +/* AAC formats are required for encoders and decoders */ +#define SND_AUDIOSTREAMFORMAT_MP2ADTS ((uint32_t) 0x00000001) +#define SND_AUDIOSTREAMFORMAT_MP4ADTS ((uint32_t) 0x00000002) +#define SND_AUDIOSTREAMFORMAT_MP4LOAS ((uint32_t) 0x00000004) +#define SND_AUDIOSTREAMFORMAT_MP4LATM ((uint32_t) 0x00000008) +#define SND_AUDIOSTREAMFORMAT_ADIF ((uint32_t) 0x00000010) +#define SND_AUDIOSTREAMFORMAT_MP4FF ((uint32_t) 0x00000020) +#define SND_AUDIOSTREAMFORMAT_RAW ((uint32_t) 0x00000040) + +#define SND_AUDIOPROFILE_WMA7 ((uint32_t) 0x00000001) +#define SND_AUDIOPROFILE_WMA8 ((uint32_t) 0x00000002) +#define SND_AUDIOPROFILE_WMA9 ((uint32_t) 0x00000004) +#define SND_AUDIOPROFILE_WMA10 ((uint32_t) 0x00000008) +#define SND_AUDIOPROFILE_WMA9_PRO ((uint32_t) 0x00000010) +#define SND_AUDIOPROFILE_WMA9_LOSSLESS ((uint32_t) 0x00000020) +#define SND_AUDIOPROFILE_WMA10_LOSSLESS ((uint32_t) 0x00000040) + +#define SND_AUDIOMODE_WMA_LEVEL1 ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_WMA_LEVEL2 ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_WMA_LEVEL3 ((uint32_t) 0x00000004) +#define SND_AUDIOMODE_WMA_LEVEL4 ((uint32_t) 0x00000008) +#define SND_AUDIOMODE_WMAPRO_LEVELM0 ((uint32_t) 0x00000010) +#define SND_AUDIOMODE_WMAPRO_LEVELM1 ((uint32_t) 0x00000020) +#define SND_AUDIOMODE_WMAPRO_LEVELM2 ((uint32_t) 0x00000040) +#define SND_AUDIOMODE_WMAPRO_LEVELM3 ((uint32_t) 0x00000080) + +#define SND_AUDIOSTREAMFORMAT_WMA_ASF ((uint32_t) 0x00000001) +/* + * Some implementations strip the ASF header and only send ASF packets + * to the DSP + */ +#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR ((uint32_t) 0x00000002) + +#define SND_AUDIOPROFILE_REALAUDIO ((uint32_t) 0x00000001) + +#define SND_AUDIOMODE_REALAUDIO_G2 ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_REALAUDIO_8 ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_REALAUDIO_10 ((uint32_t) 0x00000004) +#define SND_AUDIOMODE_REALAUDIO_SURROUND ((uint32_t) 0x00000008) + +#define SND_AUDIOPROFILE_VORBIS ((uint32_t) 0x00000001) + +#define SND_AUDIOMODE_VORBIS ((uint32_t) 0x00000001) + +#define SND_AUDIOPROFILE_FLAC ((uint32_t) 0x00000001) + +/* + * Define quality levels for FLAC encoders, from LEVEL0 (fast) + * to LEVEL8 (best) + */ +#define SND_AUDIOMODE_FLAC_LEVEL0 ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_FLAC_LEVEL1 ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_FLAC_LEVEL2 ((uint32_t) 0x00000004) +#define SND_AUDIOMODE_FLAC_LEVEL3 ((uint32_t) 0x00000008) +#define SND_AUDIOMODE_FLAC_LEVEL4 ((uint32_t) 0x00000010) +#define SND_AUDIOMODE_FLAC_LEVEL5 ((uint32_t) 0x00000020) +#define SND_AUDIOMODE_FLAC_LEVEL6 ((uint32_t) 0x00000040) +#define SND_AUDIOMODE_FLAC_LEVEL7 ((uint32_t) 0x00000080) +#define SND_AUDIOMODE_FLAC_LEVEL8 ((uint32_t) 0x00000100) + +#define SND_AUDIOSTREAMFORMAT_FLAC ((uint32_t) 0x00000001) +#define SND_AUDIOSTREAMFORMAT_FLAC_OGG ((uint32_t) 0x00000002) + +/* IEC61937 payloads without CUVP and preambles */ +#define SND_AUDIOPROFILE_IEC61937 ((uint32_t) 0x00000001) +/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */ +#define SND_AUDIOPROFILE_IEC61937_SPDIF ((uint32_t) 0x00000002) + +/* + * IEC modes are mandatory for decoders. Format autodetection + * will only happen on the DSP side with mode 0. The PCM mode should + * not be used, the PCM codec should be used instead. + */ +#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER ((uint32_t) 0x00000000) +#define SND_AUDIOMODE_IEC_LPCM ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_IEC_AC3 ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_IEC_MPEG1 ((uint32_t) 0x00000004) +#define SND_AUDIOMODE_IEC_MP3 ((uint32_t) 0x00000008) +#define SND_AUDIOMODE_IEC_MPEG2 ((uint32_t) 0x00000010) +#define SND_AUDIOMODE_IEC_AACLC ((uint32_t) 0x00000020) +#define SND_AUDIOMODE_IEC_DTS ((uint32_t) 0x00000040) +#define SND_AUDIOMODE_IEC_ATRAC ((uint32_t) 0x00000080) +#define SND_AUDIOMODE_IEC_SACD ((uint32_t) 0x00000100) +#define SND_AUDIOMODE_IEC_EAC3 ((uint32_t) 0x00000200) +#define SND_AUDIOMODE_IEC_DTS_HD ((uint32_t) 0x00000400) +#define SND_AUDIOMODE_IEC_MLP ((uint32_t) 0x00000800) +#define SND_AUDIOMODE_IEC_DST ((uint32_t) 0x00001000) +#define SND_AUDIOMODE_IEC_WMAPRO ((uint32_t) 0x00002000) +#define SND_AUDIOMODE_IEC_REF_CXT ((uint32_t) 0x00004000) +#define SND_AUDIOMODE_IEC_HE_AAC ((uint32_t) 0x00008000) +#define SND_AUDIOMODE_IEC_HE_AAC2 ((uint32_t) 0x00010000) +#define SND_AUDIOMODE_IEC_MPEG_SURROUND ((uint32_t) 0x00020000) + +#define SND_AUDIOPROFILE_G723_1 ((uint32_t) 0x00000001) + +#define SND_AUDIOMODE_G723_1_ANNEX_A ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_G723_1_ANNEX_B ((uint32_t) 0x00000002) +#define SND_AUDIOMODE_G723_1_ANNEX_C ((uint32_t) 0x00000004) + +#define SND_AUDIOPROFILE_G729 ((uint32_t) 0x00000001) + +#define SND_AUDIOMODE_G729_ANNEX_A ((uint32_t) 0x00000001) +#define SND_AUDIOMODE_G729_ANNEX_B ((uint32_t) 0x00000002) + +/* <FIXME: multichannel encoders aren't supported for now. Would need + an additional definition of channel arrangement> */ + +/* VBR/CBR definitions */ +#define SND_RATECONTROLMODE_CONSTANTBITRATE ((uint32_t) 0x00000001) +#define SND_RATECONTROLMODE_VARIABLEBITRATE ((uint32_t) 0x00000002) + +/* Encoder options */ + +struct snd_enc_wma { + uint32_t super_block_align; /* WMA Type-specific data */ +}; + + +/** + * struct snd_enc_vorbis + * + * \@quality: Sets encoding quality to n, between -1 (low) and 10 (high). + * In the default mode of operation, the quality level is 3. + * Normal quality range is 0 - 10. + * \@managed: Boolean. Set bitrate management mode. This turns off the + * normal VBR encoding, but allows hard or soft bitrate constraints to be + * enforced by the encoder. This mode can be slower, and may also be + * lower quality. It is primarily useful for streaming. + * \@max_bit_rate: Enabled only if managed is TRUE + * \@min_bit_rate: Enabled only if managed is TRUE + * \@downmix: Boolean. Downmix input from stereo to mono (has no effect on + * non-stereo streams). Useful for lower-bitrate encoding. + * + * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc + * properties + * + * For best quality users should specify VBR mode and set quality levels. + */ + +struct snd_enc_vorbis { + int32_t quality; + uint32_t managed; + uint32_t max_bit_rate; + uint32_t min_bit_rate; + uint32_t downmix; +} __attribute__((packed, aligned(4))); + + +/** + * struct snd_enc_real + * + * \@quant_bits: number of coupling quantization bits in the stream + * \@start_region: coupling start region in the stream + * \@num_regions: number of regions value + * + * These options were extracted from the OpenMAX IL spec + */ + +struct snd_enc_real { + uint32_t quant_bits; + uint32_t start_region; + uint32_t num_regions; +} __attribute__((packed, aligned(4))); + +/** + * struct snd_enc_flac + * + * \@num: serial number, valid only for OGG formats + * needs to be set by application + * \@gain: Add replay gain tags + * + * These options were extracted from the FLAC online documentation + * at http://flac.sourceforge.net/documentation_tools_flac.html + * + * To make the API simpler, it is assumed that the user will select quality + * profiles. Additional options that affect encoding quality and speed can + * be added at a later stage if needed. + * + * By default the Subset format is used by encoders. + * + * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are + * not supported in this API. + */ + +struct snd_enc_flac { + uint32_t num; + uint32_t gain; +} __attribute__((packed, aligned(4))); + +struct snd_enc_generic { + uint32_t bw; /* encoder bandwidth */ + int32_t reserved[15]; /* Can be used for SND_AUDIOCODEC_BESPOKE */ +} __attribute__((packed, aligned(4))); + +struct snd_dec_flac { + uint16_t sample_size; + uint16_t min_blk_size; + uint16_t max_blk_size; + uint16_t min_frame_size; + uint16_t max_frame_size; + uint16_t reserved; +} __attribute__((packed, aligned(4))); + +struct snd_dec_wma { + uint32_t encoder_option; + uint32_t adv_encoder_option; + uint32_t adv_encoder_option2; + uint32_t reserved; +} __attribute__((packed, aligned(4))); + +struct snd_dec_alac { + uint32_t frame_length; + uint8_t compatible_version; + uint8_t pb; + uint8_t mb; + uint8_t kb; + uint32_t max_run; + uint32_t max_frame_bytes; +} __attribute__((packed, aligned(4))); + +struct snd_dec_ape { + uint16_t compatible_version; + uint16_t compression_level; + uint32_t format_flags; + uint32_t blocks_per_frame; + uint32_t final_frame_blocks; + uint32_t total_frames; + uint32_t seek_table_present; +} __attribute__((packed, aligned(4))); + +union snd_codec_options { + struct snd_enc_wma wma; + struct snd_enc_vorbis vorbis; + struct snd_enc_real real; + struct snd_enc_flac flac; + struct snd_enc_generic generic; + struct snd_dec_flac flac_d; + struct snd_dec_wma wma_d; + struct snd_dec_alac alac_d; + struct snd_dec_ape ape_d; +} __attribute__((packed, aligned(4))); + +/** struct snd_codec_desc - description of codec capabilities + * + * \@max_ch: Maximum number of audio channels + * \@sample_rates: Sampling rates in Hz, use values like 48000 for this + * \@num_sample_rates: Number of valid values in sample_rates array + * \@bit_rate: Indexed array containing supported bit rates + * \@num_bitrates: Number of valid values in bit_rate array + * \@rate_control: value is specified by SND_RATECONTROLMODE defines. + * \@profiles: Supported profiles. See SND_AUDIOPROFILE defines. + * \@modes: Supported modes. See SND_AUDIOMODE defines + * \@formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines + * \@min_buffer: Minimum buffer size handled by codec implementation + * \@reserved: reserved for future use + * + * This structure provides a scalar value for profiles, modes and stream + * format fields. + * If an implementation supports multiple combinations, they will be listed as + * codecs with different descriptors, for example there would be 2 descriptors + * for AAC-RAW and AAC-ADTS. + * This entails some redundancy but makes it easier to avoid invalid + * configurations. + * + */ + +struct snd_codec_desc { + uint32_t max_ch; + uint32_t sample_rates[MAX_NUM_SAMPLE_RATES]; + uint32_t num_sample_rates; + uint32_t bit_rate[MAX_NUM_BITRATES]; + uint32_t num_bitrates; + uint32_t rate_control; + uint32_t profiles; + uint32_t modes; + uint32_t formats; + uint32_t min_buffer; + uint32_t reserved[15]; +} __attribute__((packed, aligned(4))); + +/** + * struct snd_codec + * + * \@id: Identifies the supported audio encoder/decoder. + * See SND_AUDIOCODEC macros. + * \@ch_in: Number of input audio channels + * \@ch_out: Number of output channels. In case of contradiction between + * this field and the channelMode field, the channelMode field + * overrides. + * \@sample_rate: Audio sample rate of input data in Hz, use values like 48000 + * for this. + * \@bit_rate: Bitrate of encoded data. May be ignored by decoders + * \@rate_control: Encoding rate control. See SND_RATECONTROLMODE defines. + * Encoders may rely on profiles for quality levels. + * May be ignored by decoders. + * \@profile: Mandatory for encoders, can be mandatory for specific + * decoders as well. See SND_AUDIOPROFILE defines. + * \@level: Supported level (Only used by WMA at the moment) + * \@ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines + * \@format: Format of encoded bistream. Mandatory when defined. + * See SND_AUDIOSTREAMFORMAT defines. + * \@align: Block alignment in bytes of an audio sample. + * Only required for PCM or IEC formats. + * \@options: encoder-specific settings + * \@reserved: reserved for future use + */ +struct snd_codec { + uint32_t id; + uint32_t ch_in; + uint32_t ch_out; + uint32_t sample_rate; + uint32_t bit_rate; + uint32_t rate_control; + uint32_t profile; + uint32_t level; + uint32_t ch_mode; + uint32_t format; + uint32_t align; + union snd_codec_options options; + uint32_t reserved[3]; +} __attribute__((packed, aligned(4))); + +#endif diff --git a/src/include/ipc/control.h b/src/include/ipc/control.h index 5789bbe3daf8..8c7be6d7a0e7 100644 --- a/src/include/ipc/control.h +++ b/src/include/ipc/control.h @@ -101,7 +101,7 @@ enum sof_ipc_ctrl_cmd { struct sof_ipc_ctrl_value_chan { uint32_t channel; /**< channel map - enum sof_ipc_chmap */ uint32_t value; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * Generic component mapped value data. @@ -112,7 +112,7 @@ struct sof_ipc_ctrl_value_comp { uint32_t uvalue; int32_t svalue; }; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * Generic control data. @@ -136,6 +136,13 @@ struct sof_ipc_ctrl_data { /* reserved for future use */ uint32_t reserved[6]; + /* Flexible array members[] are forbidden in unions but this + * does not seem to bother gcc as long as non-standard + * zero-length arrays[0] are used instead. Nesting flexible + * array member declarations in arrays or structures is + * forbidden too. Cleaning this up would likely require code + * changes to explicitly cast intermediate steps. + */ /* control data - add new types if needed */ union { /* channel values can be used by volume type controls */ @@ -145,7 +152,7 @@ struct sof_ipc_ctrl_data { /* data can be used by binary controls */ struct sof_abi_hdr data[0]; }; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** Event type */ enum sof_ipc_ctrl_event_type { @@ -175,7 +182,7 @@ struct sof_ipc_comp_event { /* event specific values */ uint32_t event_value; }; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** @}*/ diff --git a/src/include/ipc/dai-amd.h b/src/include/ipc/dai-amd.h new file mode 100644 index 000000000000..ceeb870c163e --- /dev/null +++ b/src/include/ipc/dai-amd.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ + +#ifndef __IPC_DAI_AMD_H__ +#define __IPC_DAI_AMD_H__ + +#include <ipc/header.h> +#include <stdint.h> + +/* DAI Configuration Request - SOF_IPC_DAI_ACP_DMIC_CONFIG */ +struct sof_ipc_dai_acpdmic_params { + uint32_t pdm_rate; + uint32_t pdm_ch; +} __attribute__((packed, aligned(4))); + +/* ACP Configuration Request - SOF_IPC_DAI_AMD_CONFIG */ +struct sof_ipc_dai_acp_params { + uint32_t reserved0; + uint32_t fsync_rate; + uint32_t tdm_slots; +} __attribute__((packed, aligned(4))); + +/* ACP Configuration Request - SOF_IPC_DAI_AMD_SDW_CONFIG */ +struct sof_ipc_dai_acp_sdw_params { + uint32_t reserved0; + uint32_t rate; + uint32_t channels; +} __attribute__((packed, aligned(4))); +#endif /* __IPC_DAI_AMD_H__ */ diff --git a/src/include/ipc/dai-imx.h b/src/include/ipc/dai-imx.h index 922018dd9d67..5f9fc4dce837 100644 --- a/src/include/ipc/dai-imx.h +++ b/src/include/ipc/dai-imx.h @@ -18,9 +18,12 @@ struct sof_ipc_dai_esai_params { /* MCLK */ uint16_t reserved1; uint16_t mclk_id; - uint32_t mclk_rate; /* MCLK frequency in Hz */ uint32_t mclk_direction; + uint32_t mclk_rate; /* MCLK frequency in Hz */ + uint32_t fsync_rate; + uint32_t bclk_rate; + /* TDM */ uint32_t tdm_slots; uint32_t rx_slots; @@ -28,7 +31,7 @@ struct sof_ipc_dai_esai_params { uint16_t tdm_slot_width; uint16_t reserved2; /* alignment */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* SAI Configuration Request - SOF_IPC_DAI_SAI_CONFIG */ struct sof_ipc_dai_sai_params { @@ -37,9 +40,12 @@ struct sof_ipc_dai_sai_params { /* MCLK */ uint16_t reserved1; uint16_t mclk_id; - uint32_t mclk_rate; /* MCLK frequency in Hz */ uint32_t mclk_direction; + uint32_t mclk_rate; /* MCLK frequency in Hz */ + uint32_t fsync_rate; + uint32_t bclk_rate; + /* TDM */ uint32_t tdm_slots; uint32_t rx_slots; @@ -47,5 +53,12 @@ struct sof_ipc_dai_sai_params { uint16_t tdm_slot_width; uint16_t reserved2; /* alignment */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); + +/* MICFIL Configuration Request - SOF_IPC_DAI_MICFIL_CONFIG */ +struct sof_ipc_dai_micfil_params { + uint32_t pdm_rate; + uint32_t pdm_ch; +} __attribute__((packed, aligned(4))); + #endif /* __IPC_DAI_IMX_H__ */ diff --git a/src/include/ipc/dai-intel.h b/src/include/ipc/dai-intel.h index e57afd09d1c6..4545a2b40282 100644 --- a/src/include/ipc/dai-intel.h +++ b/src/include/ipc/dai-intel.h @@ -56,6 +56,15 @@ #define SOF_DAI_INTEL_SSP_CLKCTRL_FS_KA BIT(4) /* bclk idle */ #define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5) +/* mclk early start */ +#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_ES BIT(6) +/* bclk early start */ +#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_ES BIT(7) +/* mclk always on */ +#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_AON BIT(8) + +/* DMIC max. four controllers for eight microphone channels */ +#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4 /* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */ struct sof_ipc_dai_ssp_params { @@ -87,22 +96,26 @@ struct sof_ipc_dai_ssp_params { uint32_t bclk_delay; /* guaranteed time (ms) for which BCLK * will be driven, before sending data */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* HDA Configuration Request - SOF_IPC_DAI_HDA_CONFIG */ struct sof_ipc_dai_hda_params { uint32_t reserved0; uint32_t link_dma_ch; -} __attribute__((packed)); + uint32_t rate; + uint32_t channels; +} __attribute__((packed, aligned(4))); /* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */ struct sof_ipc_dai_alh_params { uint32_t reserved0; uint32_t stream_id; + uint32_t rate; + uint32_t channels; /* reserved for future use */ - uint32_t reserved[15]; -} __attribute__((packed)); + uint32_t reserved[13]; +} __attribute__((packed, aligned(4))); /* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */ @@ -137,13 +150,13 @@ struct sof_ipc_dai_dmic_pdm_ctrl { uint16_t skew; /**< Adjust PDM data sampling vs. clock (0..15) */ uint16_t reserved[3]; /**< Make sure the total size is 4 bytes aligned */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* This struct contains the global settings for all 2ch PDM controllers. The * version number used in configuration data is checked vs. version used by * device driver src/drivers/dmic.c need to match. It is incremented from * initial value 1 if updates done for the to driver would alter the operation - * of the microhone. + * of the microphone. * * Note: The microphone clock (pdmclk_min, pdmclk_max, duty_min, duty_max) * parameters need to be set as defined in microphone data sheet. E.g. clock @@ -168,6 +181,7 @@ struct sof_ipc_dai_dmic_pdm_ctrl { * met. The unit for both is microseconds (us). Exceed of 100 ms will be * treated as an error. */ + struct sof_ipc_dai_dmic_params { uint32_t reserved0; uint32_t driver_ipc_version; /**< Version (1..N) */ @@ -178,12 +192,13 @@ struct sof_ipc_dai_dmic_params { uint32_t fifo_fs; /**< FIFO sample rate in Hz (8000..96000) */ uint32_t reserved_1; /**< Reserved */ uint16_t fifo_bits; /**< FIFO word length (16 or 32) */ - uint16_t reserved_2; /**< Reserved */ + uint16_t fifo_bits_b; /**< Deprecated since firmware ABI 3.0.1 */ uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ - uint32_t num_pdm_active; /**< Number of active pdm controllers */ + uint32_t num_pdm_active; /**< Number of active pdm controllers. */ + /**< Range is 1..SOF_DAI_INTEL_DMIC_NUM_CTRL */ uint32_t wake_up_time; /**< Time from clock start to data (us) */ uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */ @@ -192,8 +207,8 @@ struct sof_ipc_dai_dmic_params { /* reserved for future use */ uint32_t reserved[5]; - /**< variable number of pdm controller config */ - struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; -} __attribute__((packed)); + /**< PDM controllers configuration */ + struct sof_ipc_dai_dmic_pdm_ctrl pdm[SOF_DAI_INTEL_DMIC_NUM_CTRL]; +} __attribute__((packed, aligned(4))); #endif /* __IPC_DAI_INTEL_H__ */ diff --git a/src/include/ipc/dai-mediatek.h b/src/include/ipc/dai-mediatek.h new file mode 100644 index 000000000000..d170e3bcc86f --- /dev/null +++ b/src/include/ipc/dai-mediatek.h @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Mediatek +// +// Author: Bo Pan <bo.pan@mediatek.com> + +#ifndef __IPC_DAI_MEDIATEK_H__ +#define __IPC_DAI_MEDIATEK_H__ + +#include <ipc/header.h> +#include <stdint.h> + +/* AFE Configuration Request - SOF_DAI_MEDIATEK_AFE */ +struct sof_ipc_dai_afe_params { + uint32_t reserved0; + + uint32_t dai_channels; + uint32_t dai_rate; + uint32_t dai_format; + uint32_t stream_id; + uint32_t reserved[4]; /* reserve for future */ +} __attribute__((packed)); + +#endif /* __IPC_DAI_MEDIATEK_H__ */ + diff --git a/src/include/ipc/dai.h b/src/include/ipc/dai.h index 50f986f54baa..dfc2a3e9ffb0 100644 --- a/src/include/ipc/dai.h +++ b/src/include/ipc/dai.h @@ -18,7 +18,10 @@ #include <ipc/dai-intel.h> #include <ipc/dai-imx.h> +#include <ipc/dai-mediatek.h> +#include <ipc/dai-amd.h> #include <ipc/header.h> +#include <stddef.h> #include <stdint.h> /* @@ -42,15 +45,38 @@ #define SOF_DAI_FMT_IB_NF (3 << 8) /**< invert BCLK + nor FRM */ #define SOF_DAI_FMT_IB_IF (4 << 8) /**< invert BCLK + FRM */ -#define SOF_DAI_FMT_CBM_CFM (0 << 12) /**< codec clk & FRM master */ -#define SOF_DAI_FMT_CBS_CFM (2 << 12) /**< codec clk slave & FRM master */ -#define SOF_DAI_FMT_CBM_CFS (3 << 12) /**< codec clk master & frame slave */ -#define SOF_DAI_FMT_CBS_CFS (4 << 12) /**< codec clk & FRM slave */ +#define SOF_DAI_FMT_CBP_CFP (0 << 12) /**< codec bclk provider & frame provider */ +#define SOF_DAI_FMT_CBC_CFP (2 << 12) /**< codec bclk consumer & frame provider */ +#define SOF_DAI_FMT_CBP_CFC (3 << 12) /**< codec bclk provider & frame consumer */ +#define SOF_DAI_FMT_CBC_CFC (4 << 12) /**< codec bclk consumer & frame consumer */ #define SOF_DAI_FMT_FORMAT_MASK 0x000f #define SOF_DAI_FMT_CLOCK_MASK 0x00f0 #define SOF_DAI_FMT_INV_MASK 0x0f00 -#define SOF_DAI_FMT_MASTER_MASK 0xf000 +#define SOF_DAI_FMT_CLOCK_PROVIDER_MASK 0xf000 + +/* + * DAI_CONFIG flags. The 4 LSB bits are used for the commands, HW_PARAMS, HW_FREE and PAUSE + * representing when the IPC is sent. The 4 MSB bits are used to add quirks along with the above + * commands. + */ +#define SOF_DAI_CONFIG_FLAGS_CMD_MASK 0xF +#define SOF_DAI_CONFIG_FLAGS_NONE 0 /**< DAI_CONFIG sent without stage information */ +#define SOF_DAI_CONFIG_FLAGS_HW_PARAMS BIT(0) /**< DAI_CONFIG sent during hw_params stage */ +#define SOF_DAI_CONFIG_FLAGS_HW_FREE BIT(1) /**< DAI_CONFIG sent during hw_free stage */ +/**< DAI_CONFIG sent during pause trigger. Only available ABI 3.20 onwards */ +#define SOF_DAI_CONFIG_FLAGS_PAUSE BIT(2) +#define SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT 4 +#define SOF_DAI_CONFIG_FLAGS_QUIRK_MASK (0xF << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT) +/* + * This should be used along with the SOF_DAI_CONFIG_FLAGS_HW_PARAMS to indicate that pipeline + * stop/pause and DAI DMA stop/pause should happen in two steps. This change is only available + * ABI 3.20 onwards. + */ +#define SOF_DAI_CONFIG_FLAGS_2_STEP_STOP BIT(0) + +#define SOF_DAI_QUIRK_IS_SET(flags, quirk) \ + (((flags & SOF_DAI_CONFIG_FLAGS_QUIRK_MASK) >> SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT) & quirk) /** \brief Types of DAI */ enum sof_ipc_dai_type { @@ -61,8 +87,20 @@ enum sof_ipc_dai_type { SOF_DAI_INTEL_ALH, /**< Intel ALH */ SOF_DAI_IMX_SAI, /**< i.MX SAI */ SOF_DAI_IMX_ESAI, /**< i.MX ESAI */ + SOF_DAI_AMD_BT, /**< Amd BT */ + SOF_DAI_AMD_SP, /**< Amd SP */ + SOF_DAI_AMD_DMIC, /**< Amd DMIC */ + SOF_DAI_MEDIATEK_AFE, /**< Mtk AFE */ + SOF_DAI_AMD_HS, /**< Amd HS */ + SOF_DAI_AMD_SP_VIRTUAL, /**<Amd SP VIRTUAL */ + SOF_DAI_AMD_HS_VIRTUAL, /**<Amd HS VIRTUAL */ + SOF_DAI_IMX_MICFIL, /**< i.MX MICFIL */ + SOF_DAI_AMD_SDW, /**< Amd SDW */ + SOF_DAI_INTEL_UAOL, /**< Intel UAOL */ }; +#define SOF_DAI_CONFIG_HW_SPEC_OFFSET offsetof(struct sof_ipc_dai_config, ssp) + /* general purpose DAI configuration */ struct sof_ipc_dai_config { struct sof_ipc_cmd_hdr hdr; @@ -71,7 +109,8 @@ struct sof_ipc_dai_config { /* physical protocol and clocking */ uint16_t format; /**< SOF_DAI_FMT_ */ - uint16_t reserved16; /**< alignment */ + uint8_t group_id; /**< group ID, 0 means no group (ABI 3.17) */ + uint8_t flags; /**< SOF_DAI_CONFIG_FLAGS_ (ABI 3.19) */ /* reserved for future use */ uint32_t reserved[8]; @@ -84,7 +123,14 @@ struct sof_ipc_dai_config { struct sof_ipc_dai_alh_params alh; struct sof_ipc_dai_esai_params esai; struct sof_ipc_dai_sai_params sai; + struct sof_ipc_dai_acp_params acpbt; + struct sof_ipc_dai_acp_params acpsp; + struct sof_ipc_dai_acpdmic_params acpdmic; + struct sof_ipc_dai_acp_params acphs; + struct sof_ipc_dai_afe_params afe; + struct sof_ipc_dai_micfil_params micfil; + struct sof_ipc_dai_acp_sdw_params acpsdw; }; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); #endif /* __IPC_DAI_H__ */ diff --git a/src/include/ipc/debug.h b/src/include/ipc/debug.h new file mode 100644 index 000000000000..78664a2a8ef7 --- /dev/null +++ b/src/include/ipc/debug.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#ifndef __IPC_DEBUG_H__ +#define __IPC_DEBUG_H__ + +#include <ipc/header.h> +#include <stdint.h> + +/** ABI3.18 */ +enum sof_ipc_dbg_mem_zone { + SOF_IPC_MEM_ZONE_SYS = 0, /**< System zone */ + SOF_IPC_MEM_ZONE_SYS_RUNTIME = 1, /**< System-runtime zone */ + SOF_IPC_MEM_ZONE_RUNTIME = 2, /**< Runtime zone */ + SOF_IPC_MEM_ZONE_BUFFER = 3, /**< Buffer zone */ + SOF_IPC_MEM_ZONE_RUNTIME_SHARED = 4, /**< System runtime zone */ + SOF_IPC_MEM_ZONE_SYS_SHARED = 5, /**< System shared zone */ +}; + +/** ABI3.18 */ +struct sof_ipc_dbg_mem_usage_elem { + uint32_t zone; /**< see sof_ipc_dbg_mem_zone */ + uint32_t id; /**< heap index within zone */ + uint32_t used; /**< number of bytes used in zone */ + uint32_t free; /**< number of bytes free to use within zone */ + uint32_t reserved; /**< reserved for future use */ +} __attribute__((packed, aligned(4))); + +/** ABI3.18 */ +struct sof_ipc_dbg_mem_usage { + struct sof_ipc_reply rhdr; /**< generic IPC reply header */ + uint32_t reserved[4]; /**< reserved for future use */ + uint32_t num_elems; /**< elems[] counter */ + struct sof_ipc_dbg_mem_usage_elem elems[]; /**< memory usage information */ +} __attribute__((packed, aligned(4))); + +#endif /* __IPC_DEBUG_H__ */ diff --git a/src/include/ipc/header-intel-cavs.h b/src/include/ipc/header-intel-cavs.h index 4b66753a274b..4891317f8b2c 100644 --- a/src/include/ipc/header-intel-cavs.h +++ b/src/include/ipc/header-intel-cavs.h @@ -14,7 +14,7 @@ #ifndef __IPC_HEADER_INTEL_CAVS_H__ #define __IPC_HEADER_INTEL_CAVS_H__ -#include <sof/bit.h> +#include <rtos/bit.h> /* Primary register, mapped to * - DIPCTDR (HIPCIDR) in sideband IPC (cAVS 1.8+) diff --git a/src/include/ipc/header.h b/src/include/ipc/header.h index 436b150a3dc2..d8d030f17216 100644 --- a/src/include/ipc/header.h +++ b/src/include/ipc/header.h @@ -18,19 +18,151 @@ #include <stdint.h> +/** + * Common IPC logic uses standard types for abstract IPC features. This means all ABI MAJOR + * abstraction is done in the IPC layer only and not in the surrounding infrastructure. + */ +#if CONFIG_IPC_MAJOR_3 +#include <ipc3/header.h> +#elif CONFIG_IPC_MAJOR_4 +#include <ipc4/header.h> +#endif + +/** + * Generic IPC Header structure - Header for all IPC structures which provides + * abstraction of IPC header implementation for different IPC ABI MAJOR types. + */ +struct ipc_cmd_hdr; + +#define ipc_to_hdr(x) ((struct ipc_cmd_hdr *)x) + /** \addtogroup sof_uapi uAPI - * SOF uAPI specification. + * SOF uAPI specification * - * IPC messages have a prefixed 32 bit identifier made up as follows :- + * **Overview** * - * 0xGCCCNNNN where - * - G is global cmd type (4 bits) - * - C is command type (12 bits) - * - N is the ID number (16 bits) - monotonic and overflows + * The SOF Audio DSP firmware defines an Inter-Process Communication + * (IPC) interface to facilitate communication with the host. + * + * The SOF IPC is bi-directional. Messages can be initiated by the + * host and acknowledged by the DSP. Similarly, they can be initiated + * by the DSP and acknowledged by the host. + * + * IPC messages are divided into several groups: global, topology, + * power management, component, stream, DAI, trace, and a separate + * "firmware ready" message. Multiple messages can also be grouped + * into a message that belong to a compound group. Most messages are + * sent by the host to the DSP; only the following messages are sent + * by the DSP to the host: + * - firmware ready: sent only once during initialization + * - trace: optional, contains firmware trace data + * - position update: only used if position data cannot be + * transferred in a memory window or if forced by the kernel + * configuration + * + * **Message encoding** + * + * All multi-byte protocol fields are encoded with little-endian + * byte-order. + * + * **Message structure** + * + * IPC messages have a fixed header and variable length payload. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Size | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Command | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * The header contains size of the IPC message and a 32bit Command + * identifier with following structure: + * + * 0xGCCCNNNN is little-endian value where + * - G is the Global Type (4 bits) + * - C is the Command Type (12 bits) + * - N is the ID Number (16 bits) - monotonic and overflows + * + * The Global and Command Types together define the structure of the + * payload. E.g. for topology IPC message COMP_NEW structure is (ABI + * 3.17.0 example): + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Size (Total size including Extended Data) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Command (G=TPLG_MSG, C=COMP_NEW) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Component ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pipeline ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Core | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Extended Data size | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type specific payload, size varies based on Component ID. | + * | Ends at: Total size - Extended Data size | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | extended data, including e.g. UUID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * \see sof_ipc_comp + * + * **Reply Messages** + * + * Reply messages are defined per Command. The response IPC messages + * have a common layout, but some Commands have extended fields + * defined. The common format is: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Size | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Command (G=REPLY, C=0) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Error | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * \see sof_ipc_reply + * + * **IPC ABI version compatibility rules** + * + * 1. FW binaries will only support one MAJOR ABI version which is advertised + * to host at FW boot. + * + * 2. Host drivers will support the current and older MAJOR ABI versions of + * the IPC ABI (up to a certain age to be determined by market information). + * + * 3. MINOR and PATCH ABI versions can differ between host and FW but must be + * backwards compatible on both host and FW. + * + * IPC messages sizes can be different for sender and receiver if MINOR or + * PATCH ABI versions differ as new fields can be added to the end of + * messages. + * + * i) SenderVersion > ReceiverVersion: + * Receiver only copies its own ABI structure size. + * + * ii) ReceiverVersion > SenderVersion: + * Receiver copies its own ABI size and zero pads + * new fields. i.e. new structure fields must be non + * zero to be activated. + * + * Guidelines for extending ABI compatible messages :- + * + * - i) Use reserved fields. + * + * - ii) Grow structure at the end. + * + * - iii) Iff (i) and (ii) are not possible then MAJOR ABI is bumped. * - * This is sent at the start of the IPM message in the mailbox. Messages should - * not be sent in the doorbell (special exceptions for firmware). - * @{ */ @@ -40,7 +172,7 @@ /** Shift-left bits to extract the global cmd type */ #define SOF_GLB_TYPE_SHIFT 28 -#define SOF_GLB_TYPE_MASK (0xf << SOF_GLB_TYPE_SHIFT) +#define SOF_GLB_TYPE_MASK (0xfUL << SOF_GLB_TYPE_SHIFT) #define SOF_GLB_TYPE(x) ((x) << SOF_GLB_TYPE_SHIFT) /** @} */ @@ -51,7 +183,7 @@ /** Shift-left bits to extract the command type */ #define SOF_CMD_TYPE_SHIFT 16 -#define SOF_CMD_TYPE_MASK (0xfff << SOF_CMD_TYPE_SHIFT) +#define SOF_CMD_TYPE_MASK (0xfffL << SOF_CMD_TYPE_SHIFT) #define SOF_CMD_TYPE(x) ((x) << SOF_CMD_TYPE_SHIFT) /** @} */ @@ -72,6 +204,7 @@ #define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU) #define SOF_IPC_GLB_TEST SOF_GLB_TYPE(0xBU) #define SOF_IPC_GLB_PROBE SOF_GLB_TYPE(0xCU) +#define SOF_IPC_GLB_DEBUG SOF_GLB_TYPE(0xDU) /** @} */ @@ -152,6 +285,8 @@ #define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001) #define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002) #define SOF_IPC_TRACE_DMA_PARAMS_EXT SOF_CMD_TYPE(0x003) +#define SOF_IPC_TRACE_FILTER_UPDATE SOF_CMD_TYPE(0x004) /**< ABI3.17 */ +#define SOF_IPC_TRACE_DMA_FREE SOF_CMD_TYPE(0x005) /**< ABI3.20 */ /** @} */ @@ -170,6 +305,14 @@ /** @} */ +/** \name DSP Command: Debug - additional services + * @{ + */ + +#define SOF_IPC_DEBUG_MEM_USAGE SOF_CMD_TYPE(0x001) + +/** @} */ + /** \name DSP Command: Test - Debug build only * @{ */ @@ -186,8 +329,13 @@ #define SOF_IPC_MESSAGE_ID(x) ((x) & 0xffff) /** Maximum message size for mailbox Tx/Rx */ +#if CONFIG_IPC_MAJOR_4 +#define SOF_IPC_MSG_MAX_SIZE 0x1000 +#elif CONFIG_LIBRARY_STATIC || UNIT_TEST +#define SOF_IPC_MSG_MAX_SIZE 0x2000 +#else #define SOF_IPC_MSG_MAX_SIZE 384 - +#endif /** @} */ /** @@ -198,7 +346,7 @@ */ struct sof_ipc_hdr { uint32_t size; /**< size of structure */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * Command Header - Header for all IPC commands. Identifies IPC message. @@ -209,7 +357,7 @@ struct sof_ipc_hdr { struct sof_ipc_cmd_hdr { uint32_t size; /**< size of structure */ uint32_t cmd; /**< SOF_IPC_GLB_ + cmd */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * Generic reply message. Some commands override this with their own reply @@ -218,7 +366,7 @@ struct sof_ipc_cmd_hdr { struct sof_ipc_reply { struct sof_ipc_cmd_hdr hdr; int32_t error; /**< negative error numbers */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * Compound commands - SOF_IPC_GLB_COMPOUND. @@ -231,7 +379,7 @@ struct sof_ipc_reply { struct sof_ipc_compound_hdr { struct sof_ipc_cmd_hdr hdr; uint32_t count; /**< count of 0 means end of compound sequence */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * OOPS header architecture specific data. @@ -239,7 +387,7 @@ struct sof_ipc_compound_hdr { struct sof_ipc_dsp_oops_arch_hdr { uint32_t arch; /* Identifier of architecture */ uint32_t totalsize; /* Total size of oops message */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** * OOPS header platform specific data. @@ -252,7 +400,7 @@ struct sof_ipc_dsp_oops_plat_hdr { * oops message */ uint32_t stackptr; /* Stack ptr */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /** @}*/ diff --git a/src/include/ipc/info.h b/src/include/ipc/info.h index f782b19d813d..5693079b3ce0 100644 --- a/src/include/ipc/info.h +++ b/src/include/ipc/info.h @@ -33,6 +33,7 @@ #define SOF_IPC_INFO_LOCKS BIT(1) #define SOF_IPC_INFO_LOCKSV BIT(2) #define SOF_IPC_INFO_GDB BIT(3) +#define SOF_IPC_INFO_D3_PERSISTENT BIT(4) /* extended data types that can be appended onto end of sof_ipc_fw_ready */ enum sof_ipc_ext_data { @@ -54,10 +55,12 @@ struct sof_ipc_fw_version { uint8_t time[10]; uint8_t tag[6]; uint32_t abi_version; + /** used to check FW and ldc file compatibility, reproducible value (ABI3.17) */ + uint32_t src_hash; /* reserved for future use */ - uint32_t reserved[4]; -} __attribute__((packed)); + uint32_t reserved[3]; +} __attribute__((packed, aligned(4))); /* FW ready Message - sent by firmware when boot has completed */ struct sof_ipc_fw_ready { @@ -73,7 +76,7 @@ struct sof_ipc_fw_ready { /* reserved for future use */ uint32_t reserved[4]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* * Extended Firmware data. All optional, depends on platform/arch. @@ -91,7 +94,7 @@ enum sof_ipc_region { struct sof_ipc_ext_data_hdr { struct sof_ipc_cmd_hdr hdr; uint32_t type; /**< SOF_IPC_EXT_ */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); struct sof_ipc_window_elem { struct sof_ipc_hdr hdr; @@ -101,14 +104,14 @@ struct sof_ipc_window_elem { uint32_t size; /**< size of region in bytes */ /* offset in window region as windows can be partitioned */ uint32_t offset; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* extended data memory windows for IPC, trace and debug */ struct sof_ipc_window { struct sof_ipc_ext_data_hdr ext_hdr; uint32_t num_windows; - struct sof_ipc_window_elem window[]; -} __attribute__((packed)); + struct sof_ipc_window_elem window[SOF_IPC_MAX_ELEMS]; /**< ABI3.17: Fixed size */ +} __attribute__((packed, aligned(4))); /* extended data, compiler version */ struct sof_ipc_cc_version { @@ -120,10 +123,10 @@ struct sof_ipc_cc_version { /* reserved for future use */ uint32_t reserved[4]; - char name[16]; /* null terminated compiler name */ - char optim[4]; /* null terminated compiler -O flag value */ - char desc[]; /* null terminated compiler description */ -} __attribute__((packed)); + uint8_t name[16]; /* null terminated compiler name */ + uint8_t optim[4]; /* null terminated compiler -O flag value */ + uint8_t desc[32]; /* null terminated compiler description */ +} __attribute__((packed, aligned(4))); /* extended data: Probe setup */ struct sof_ipc_probe_support { @@ -134,13 +137,13 @@ struct sof_ipc_probe_support { /* reserved for future use */ uint32_t reserved[2]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* extended data: user abi version(s) */ struct sof_ipc_user_abi_version { struct sof_ipc_ext_data_hdr ext_hdr; uint32_t abi_dbg_version; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); #endif /* __IPC_INFO_H__ */ diff --git a/src/include/ipc/pm.h b/src/include/ipc/pm.h index 7f3a656ceb24..1edb1524fa81 100644 --- a/src/include/ipc/pm.h +++ b/src/include/ipc/pm.h @@ -30,7 +30,7 @@ struct sof_ipc_pm_ctx_elem { uint32_t type; uint32_t size; uint64_t addr; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* * PM context - SOF_IPC_PM_CTX_SAVE, SOF_IPC_PM_CTX_RESTORE, @@ -46,13 +46,13 @@ struct sof_ipc_pm_ctx { uint32_t reserved[8]; struct sof_ipc_pm_ctx_elem elems[]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* enable or disable cores - SOF_IPC_PM_CORE_ENABLE */ struct sof_ipc_pm_core_config { struct sof_ipc_cmd_hdr hdr; uint32_t enable_mask; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); struct sof_ipc_pm_gate { struct sof_ipc_cmd_hdr hdr; @@ -60,7 +60,7 @@ struct sof_ipc_pm_gate { /* reserved for future use */ uint32_t reserved[5]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); #define SOF_PM_PG_RSVD BIT(0) diff --git a/src/include/ipc/probe.h b/src/include/ipc/probe.h index 8eff353f551f..3f54f7a12594 100644 --- a/src/include/ipc/probe.h +++ b/src/include/ipc/probe.h @@ -1,177 +1,12 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Adrian Bonislawski <adrian.bonislawski@linux.intel.com> - * Artur Kloniecki <arturx.kloniecki@linux.intel.com> - */ - -/** - * \file include/ipc/probe.h - * \brief Probe IPC definitions - * \author Adrian Bonislawski <adrian.bonislawski@linux.intel.com> - * \author Artur Kloniecki <arturx.kloniecki@linux.intel.com> - */ - -#ifndef __IPC_PROBE_H__ -#define __IPC_PROBE_H__ - -#include <ipc/header.h> -#include <sof/bit.h> -#include <stdint.h> - -#define PROBE_PURPOSE_EXTRACTION 0x1 -#define PROBE_PURPOSE_INJECTION 0x2 - -#define PROBE_EXTRACT_SYNC_WORD 0xBABEBEBA - -/** - * \brief Definitions of shifts and masks for format encoding in probe - * extraction stream - * - * Audio format from extraction probes is encoded as 32 bit value. Following - * graphic explains encoding. - * - * A|BBBB|CCCC|DDDD|EEEEE|FF|GG|H|I|J|XXXXXXX - * A - 1 bit - Specifies Type Encoding - 1 for Standard encoding - * B - 4 bits - Specify Standard Type - 0 for Audio - * C - 4 bits - Specify Audio format - 0 for PCM - * D - 4 bits - Specify Sample Rate - value enumerating standard sample rates: - * 8000 Hz = 0x0 - * 11025 Hz = 0x1 - * 12000 Hz = 0x2 - * 16000 Hz = 0x3 - * 22050 Hz = 0x4 - * 24000 Hz = 0x5 - * 32000 Hz = 0x6 - * 44100 Hz = 0x7 - * 48000 Hz = 0x8 - * 64000 Hz = 0x9 - * 88200 Hz = 0xA - * 96000 Hz = 0xB - * 128000 Hz = 0xC - * 176400 Hz = 0xD - * 192000 Hz = 0xE - * none of the above = 0xF - * E - 5 bits - Specify Number of Channels minus 1 - * F - 2 bits - Specify Sample Size, number of valid sample bytes minus 1 - * G - 2 bits - Specify Container Size, number of container bytes minus 1 - * H - 1 bit - Specifies Sample Format - 0 for Integer, 1 for Floating point - * I - 1 bit - Specifies Sample Endianness - 0 for LE - * J - 1 bit - Specifies Interleaving - 1 for Sample Interleaving - */ -#define PROBE_SHIFT_FMT_TYPE 31 -#define PROBE_SHIFT_STANDARD_TYPE 27 -#define PROBE_SHIFT_AUDIO_FMT 23 -#define PROBE_SHIFT_SAMPLE_RATE 19 -#define PROBE_SHIFT_NB_CHANNELS 14 -#define PROBE_SHIFT_SAMPLE_SIZE 12 -#define PROBE_SHIFT_CONTAINER_SIZE 10 -#define PROBE_SHIFT_SAMPLE_FMT 9 -#define PROBE_SHIFT_SAMPLE_END 8 -#define PROBE_SHIFT_INTERLEAVING_ST 7 - -#define PROBE_MASK_FMT_TYPE MASK(31, 31) -#define PROBE_MASK_STANDARD_TYPE MASK(30, 27) -#define PROBE_MASK_AUDIO_FMT MASK(26, 23) -#define PROBE_MASK_SAMPLE_RATE MASK(22, 19) -#define PROBE_MASK_NB_CHANNELS MASK(18, 14) -#define PROBE_MASK_SAMPLE_SIZE MASK(13, 12) -#define PROBE_MASK_CONTAINER_SIZE MASK(11, 10) -#define PROBE_MASK_SAMPLE_FMT MASK(9, 9) -#define PROBE_MASK_SAMPLE_END MASK(8, 8) -#define PROBE_MASK_INTERLEAVING_ST MASK(7, 7) - -/** - * Header for data packets sent via compressed PCM from extraction probes - */ -struct probe_data_packet { - uint32_t sync_word; /**< PROBE_EXTRACT_SYNC_WORD */ - uint32_t buffer_id; /**< Buffer ID from which data was extracted */ - uint32_t format; /**< Encoded data format */ - uint32_t timestamp_low; /**< Low 32 bits of timestamp in us */ - uint32_t timestamp_high; /**< High 32 bits of timestamp in us */ - uint32_t checksum; /**< CRC32 of header and payload */ - uint32_t data_size_bytes; /**< Size of following audio data */ - uint32_t data[]; /**< Audio data extracted from buffer */ -} __attribute__((packed)); - -/** - * Description of probe dma + * Copyright(c) 2022 Intel Corporation. All rights reserved. */ -struct probe_dma { - uint32_t stream_tag; /**< Stream tag associated with this DMA */ - uint32_t dma_buffer_size; /**< Size of buffer associated with this DMA */ -} __attribute__((packed)); -/** - * Description of probe point - */ -struct probe_point { - uint32_t buffer_id; /**< ID of buffer to which probe is attached */ - uint32_t purpose; /**< PROBE_PURPOSE_EXTRACTION or PROBE_PURPOSE_INJECTION */ - uint32_t stream_tag; /**< Stream tag of DMA via which data will be provided for injection. - * For extraction purposes, stream tag is ignored when received, - * but returned actual extraction stream tag via INFO function. - */ -} __attribute__((packed)); - -/** - * \brief DMA ADD for probes. - * - * Used as payload for IPCs: SOF_IPC_PROBE_INIT, SOF_IPC_PROBE_DMA_ADD. - */ -struct sof_ipc_probe_dma_add_params { - struct sof_ipc_cmd_hdr hdr; /**< Header */ - uint32_t num_elems; /**< Count of DMAs specified in array */ - struct probe_dma probe_dma[]; /**< Array of DMAs to be added */ -} __attribute__((packed)); - -/** - * \brief Reply to INFO functions. - * - * Used as payload for IPCs: SOF_IPC_PROBE_DMA_INFO, SOF_IPC_PROBE_POINT_INFO. - */ -struct sof_ipc_probe_info_params { - struct sof_ipc_reply rhdr; /**< Header */ - uint32_t num_elems; /**< Count of elements in array */ - union { - struct probe_dma probe_dma[0]; /**< DMA info */ - struct probe_point probe_point[0]; /**< Probe Point info */ - }; -} __attribute__((packed)); - -/** - * \brief Probe DMA remove. - * - * Used as payload for IPC: SOF_IPC_PROBE_DMA_REMOVE - */ -struct sof_ipc_probe_dma_remove_params { - struct sof_ipc_cmd_hdr hdr; /**< Header */ - uint32_t num_elems; /**< Count of stream tags specified in array */ - uint32_t stream_tag[]; /**< Array of stream tags associated with DMAs to remove */ -} __attribute__((packed)); - -/** - * \brief Add probe points. - * - * Used as payload for IPC: SOF_IPC_PROBE_POINT_ADD - */ -struct sof_ipc_probe_point_add_params { - struct sof_ipc_cmd_hdr hdr; /**< Header */ - uint32_t num_elems; /**< Count of Probe Points specified in array */ - struct probe_point probe_point[]; /**< Array of Probe Points to add */ -} __attribute__((packed)); - -/** - * \brief Remove probe point. - * - * Used as payload for IPC: SOF_IPC_PROBE_POINT_REMOVE - */ -struct sof_ipc_probe_point_remove_params { - struct sof_ipc_cmd_hdr hdr; /**< Header */ - uint32_t num_elems; /**< Count of buffer IDs specified in array */ - uint32_t buffer_id[]; /**< Array of buffer IDs from which Probe Points should be removed */ -} __attribute__((packed)); +#include <ipc/probe_dma_frame.h> -#endif /* __IPC_PROBE_H__ */ +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/probe.h> +#else +#include <ipc3/probe.h> +#endif diff --git a/src/include/ipc/probe_dma_frame.h b/src/include/ipc/probe_dma_frame.h new file mode 100644 index 000000000000..0628704fdcef --- /dev/null +++ b/src/include/ipc/probe_dma_frame.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __IPC_PROBE_DMA_FRAME_H__ +#define __IPC_PROBE_DMA_FRAME_H__ + +#include <rtos/bit.h> + +/** + * Header for data packets sent via compressed PCM from extraction probes + */ +struct probe_data_packet { + uint32_t sync_word; /**< PROBE_EXTRACT_SYNC_WORD */ + uint32_t buffer_id; /**< Buffer ID from which data was extracted */ + uint32_t format; /**< Encoded data format */ + uint32_t timestamp_low; /**< Low 32 bits of timestamp in us */ + uint32_t timestamp_high; /**< High 32 bits of timestamp in us */ + uint32_t data_size_bytes; /**< Size of following audio data */ + uint8_t data[]; /**< Audio data extracted from buffer */ +} __attribute__((packed, aligned(4))); + +#define PROBE_EXTRACT_SYNC_WORD 0xBABEBEBA + +/** + * \brief Definitions of shifts and masks for format encoding in probe + * extraction stream + * + * Audio format from extraction probes is encoded as 32 bit value. Following + * graphic explains encoding. + * + * A|BBBB|CCCC|DDDD|EEEEE|FF|GG|H|I|J|XXXXXXX + * A - 1 bit - Specifies Type Encoding - 1 for Standard encoding + * B - 4 bits - Specify Standard Type - 0 for Audio + * C - 4 bits - Specify Audio format - 0 for PCM + * D - 4 bits - Specify Sample Rate - value enumerating standard sample rates: + * 8000 Hz = 0x0 + * 11025 Hz = 0x1 + * 12000 Hz = 0x2 + * 16000 Hz = 0x3 + * 22050 Hz = 0x4 + * 24000 Hz = 0x5 + * 32000 Hz = 0x6 + * 44100 Hz = 0x7 + * 48000 Hz = 0x8 + * 64000 Hz = 0x9 + * 88200 Hz = 0xA + * 96000 Hz = 0xB + * 128000 Hz = 0xC + * 176400 Hz = 0xD + * 192000 Hz = 0xE + * none of the above = 0xF + * E - 5 bits - Specify Number of Channels minus 1 + * F - 2 bits - Specify Sample Size, number of valid sample bytes minus 1 + * G - 2 bits - Specify Container Size, number of container bytes minus 1 + * H - 1 bit - Specifies Sample Format - 0 for Integer, 1 for Floating point + * I - 1 bit - Specifies Sample Endianness - 0 for LE + * J - 1 bit - Specifies Interleaving - 1 for Sample Interleaving + */ +#define PROBE_SHIFT_FMT_TYPE 31 +#define PROBE_SHIFT_STANDARD_TYPE 27 +#define PROBE_SHIFT_AUDIO_FMT 23 +#define PROBE_SHIFT_SAMPLE_RATE 19 +#define PROBE_SHIFT_NB_CHANNELS 14 +#define PROBE_SHIFT_SAMPLE_SIZE 12 +#define PROBE_SHIFT_CONTAINER_SIZE 10 +#define PROBE_SHIFT_SAMPLE_FMT 9 +#define PROBE_SHIFT_SAMPLE_END 8 +#define PROBE_SHIFT_INTERLEAVING_ST 7 + +#define PROBE_MASK_FMT_TYPE MASK(31, 31) +#define PROBE_MASK_STANDARD_TYPE MASK(30, 27) +#define PROBE_MASK_AUDIO_FMT MASK(26, 23) +#define PROBE_MASK_SAMPLE_RATE MASK(22, 19) +#define PROBE_MASK_NB_CHANNELS MASK(18, 14) +#define PROBE_MASK_SAMPLE_SIZE MASK(13, 12) +#define PROBE_MASK_CONTAINER_SIZE MASK(11, 10) +#define PROBE_MASK_SAMPLE_FMT MASK(9, 9) +#define PROBE_MASK_SAMPLE_END MASK(8, 8) +#define PROBE_MASK_INTERLEAVING_ST MASK(7, 7) + +#endif diff --git a/src/include/ipc/stream.h b/src/include/ipc/stream.h index ba10a41f50c8..7cc020e50897 100644 --- a/src/include/ipc/stream.h +++ b/src/include/ipc/stream.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 - 2023 Intel Corporation. All rights reserved. * * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> * Keyon Jie <yang.jie@linux.intel.com> @@ -16,15 +16,13 @@ #ifndef __IPC_STREAM_H__ #define __IPC_STREAM_H__ +#include <module/ipc/stream.h> #include <ipc/header.h> #include <stdint.h> /* * Stream configuration. */ - -#define SOF_IPC_MAX_CHANNELS 8 - /* common sample rates for use in masks */ #define SOF_RATE_8000 (1 << 0) /**< 8000Hz */ #define SOF_RATE_11025 (1 << 1) /**< 11025Hz */ @@ -48,15 +46,6 @@ /* generic PCM flags for runtime settings */ #define SOF_PCM_FLAG_XRUN_STOP (1 << 0) /**< Stop on any XRUN */ -/* stream PCM frame format */ -enum sof_ipc_frame { - SOF_IPC_FRAME_S16_LE = 0, - SOF_IPC_FRAME_S24_4LE, - SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_FLOAT, - /* other formats here */ -}; - /* stream buffer format */ enum sof_ipc_buffer_format { SOF_IPC_BUFFER_INTERLEAVED, @@ -77,7 +66,7 @@ struct sof_ipc_host_buffer { uint32_t pages; uint32_t size; uint32_t reserved[3]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); struct sof_ipc_stream_params { struct sof_ipc_hdr hdr; @@ -93,10 +82,14 @@ struct sof_ipc_stream_params { uint32_t host_period_bytes; uint16_t no_stream_position; /**< 1 means don't send stream position */ + uint8_t cont_update_posn; /**< 1 means continuous update stream position */ + uint8_t reserved0; + uint16_t ext_data_length; /**< 0 means no extended data */ - uint16_t reserved[3]; + uint8_t reserved[2]; uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */ -} __attribute__((packed)); + int8_t data[]; /**< extended data */ +} __attribute__((packed, aligned(4))); /* PCM params info - SOF_IPC_STREAM_PCM_PARAMS */ struct sof_ipc_pcm_params { @@ -105,20 +98,20 @@ struct sof_ipc_pcm_params { uint32_t flags; /**< generic PCM flags - SOF_PCM_FLAG_ */ uint32_t reserved[2]; struct sof_ipc_stream_params params; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* PCM params info reply - SOF_IPC_STREAM_PCM_PARAMS_REPLY */ struct sof_ipc_pcm_params_reply { struct sof_ipc_reply rhdr; uint32_t comp_id; uint32_t posn_offset; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* free stream - SOF_IPC_STREAM_PCM_PARAMS */ struct sof_ipc_stream { struct sof_ipc_cmd_hdr hdr; uint32_t comp_id; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* flags indicating which time stamps are in sync with each other */ #define SOF_TIME_HOST_SYNC (1 << 0) @@ -151,6 +144,6 @@ struct sof_ipc_stream_posn { uint64_t timestamp; /**< system time stamp */ uint32_t xrun_comp_id; /**< comp ID of XRUN component */ int32_t xrun_size; /**< XRUN size in bytes */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); #endif /* __IPC_STREAM_H__ */ diff --git a/src/include/ipc/topology.h b/src/include/ipc/topology.h index 149301d5076b..a83b806a3467 100644 --- a/src/include/ipc/topology.h +++ b/src/include/ipc/topology.h @@ -34,9 +34,9 @@ enum sof_comp_type { SOF_COMP_MIXER, SOF_COMP_MUX, SOF_COMP_SRC, - SOF_COMP_SPLITTER, + SOF_COMP_DEPRECATED0, /* Formerly SOF_COMP_SPLITTER */ SOF_COMP_TONE, - SOF_COMP_SWITCH, + SOF_COMP_DEPRECATED1, /* Formerly SOF_COMP_SWITCH */ SOF_COMP_BUFFER, SOF_COMP_EQ_IIR, SOF_COMP_EQ_FIR, @@ -45,6 +45,9 @@ enum sof_comp_type { SOF_COMP_SELECTOR, /**< channel selector component */ SOF_COMP_DEMUX, SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ + SOF_COMP_DCBLOCK, + SOF_COMP_SMART_AMP, /**< smart amplifier component */ + SOF_COMP_MODULE_ADAPTER, /**< module adapter */ /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -59,13 +62,14 @@ enum sof_comp_type { struct sof_ipc_comp { struct sof_ipc_cmd_hdr hdr; uint32_t id; - enum sof_comp_type type; + /* holds an "enum sof_comp_type" value. Fixed-size because of #9378 */ + uint32_t type; uint32_t pipeline_id; uint32_t core; - /* reserved for future use */ - uint32_t reserved[1]; -} __attribute__((packed)); + /** extended data length, 0 if no extended data (ABI3.17) */ + uint32_t ext_data_length; +} __attribute__((packed, aligned(4))); /* * Component Buffers @@ -74,21 +78,39 @@ struct sof_ipc_comp { /* * SOF memory capabilities, add new ones at the end */ -#define SOF_MEM_CAPS_RAM (1 << 0) -#define SOF_MEM_CAPS_ROM (1 << 1) -#define SOF_MEM_CAPS_EXT (1 << 2) /**< external */ -#define SOF_MEM_CAPS_LP (1 << 3) /**< low power */ -#define SOF_MEM_CAPS_HP (1 << 4) /**< high performance */ -#define SOF_MEM_CAPS_DMA (1 << 5) /**< DMA'able */ -#define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */ -#define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */ +#define SOF_MEM_CAPS_RAM BIT(0) +#define SOF_MEM_CAPS_ROM BIT(1) +#define SOF_MEM_CAPS_EXT BIT(2) /**< external */ +#define SOF_MEM_CAPS_LP BIT(3) /**< low power */ +#define SOF_MEM_CAPS_HP BIT(4) /**< high performance */ +#define SOF_MEM_CAPS_DMA BIT(5) /**< DMA'able */ +#define SOF_MEM_CAPS_CACHE BIT(6) /**< cacheable */ +#define SOF_MEM_CAPS_EXEC BIT(7) /**< executable */ +#define SOF_MEM_CAPS_L3 BIT(8) /**< L3 memory */ +/* Don't forget to update when adding a new bit to the ABI. */ +#define SOF_MEM_CAPS_LOWEST_INVALID BIT(9) /**< Used for input validation */ + +/* + * overrun will cause ring buffer overwrite, instead of XRUN. + */ +#define SOF_BUF_OVERRUN_PERMITTED BIT(0) + +/* + * underrun will cause readback of 0s, instead of XRUN. + */ +#define SOF_BUF_UNDERRUN_PERMITTED BIT(1) + +/* the UUID size in bytes, shared between FW and host */ +#define SOF_UUID_SIZE 16 /* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */ struct sof_ipc_buffer { struct sof_ipc_comp comp; uint32_t size; /**< buffer size in bytes */ uint32_t caps; /**< SOF_MEM_CAPS_ */ -} __attribute__((packed)); + uint32_t flags; /**< SOF_BUF_ flags defined above */ + uint32_t reserved; /**< reserved for future use */ +} __attribute__((packed, aligned(4))); /* generic component config data - must always be after struct sof_ipc_comp */ struct sof_ipc_comp_config { @@ -101,7 +123,7 @@ struct sof_ipc_comp_config { /* reserved for future use */ uint32_t reserved[2]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic host component */ struct sof_ipc_comp_host { @@ -110,7 +132,7 @@ struct sof_ipc_comp_host { uint32_t direction; /**< SOF_IPC_STREAM_ */ uint32_t no_irq; /**< don't send periodic IRQ to host/DSP */ uint32_t dmac_config; /**< DMA engine specific */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic DAI component */ struct sof_ipc_comp_dai { @@ -120,13 +142,13 @@ struct sof_ipc_comp_dai { uint32_t dai_index; /**< index of this type dai */ uint32_t type; /**< DAI type - SOF_DAI_ */ uint32_t reserved; /**< reserved */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic mixer component */ struct sof_ipc_comp_mixer { struct sof_ipc_comp comp; struct sof_ipc_comp_config config; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* volume ramping types */ enum sof_volume_ramp { @@ -134,6 +156,8 @@ enum sof_volume_ramp { SOF_VOLUME_LOG, SOF_VOLUME_LINEAR_ZC, SOF_VOLUME_LOG_ZC, + SOF_VOLUME_WINDOWS_FADE, + SOF_VOLUME_WINDOWS_NO_FADE, }; /* generic volume component */ @@ -145,7 +169,7 @@ struct sof_ipc_comp_volume { uint32_t max_value; uint32_t ramp; /**< SOF_VOLUME_ */ uint32_t initial_ramp; /**< ramp space in ms */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic SRC component */ struct sof_ipc_comp_src { @@ -155,7 +179,7 @@ struct sof_ipc_comp_src { uint32_t source_rate; /**< source rate or 0 for variable */ uint32_t sink_rate; /**< sink rate or 0 for variable */ uint32_t rate_mask; /**< SOF_RATE_ supported rates */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic ASRC component */ struct sof_ipc_comp_asrc { @@ -181,13 +205,13 @@ struct sof_ipc_comp_asrc { /* reserved for future use */ uint32_t reserved[4]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic MUX component */ struct sof_ipc_comp_mux { struct sof_ipc_comp comp; struct sof_ipc_comp_config config; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic tone generator component */ struct sof_ipc_comp_tone { @@ -202,7 +226,7 @@ struct sof_ipc_comp_tone { int32_t period; int32_t repeats; int32_t ramp_step; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* generic "effect", "codec" or proprietary processing component */ struct sof_ipc_comp_process { @@ -214,8 +238,28 @@ struct sof_ipc_comp_process { /* reserved for future use */ uint32_t reserved[7]; - unsigned char data[0]; -} __attribute__((packed)); + unsigned char data[]; +} __attribute__((packed, aligned(4))); + +/* IPC file component used by testbench only */ +struct sof_ipc_comp_file { + /* These need to be the same as in above sof_ipc_comp_process */ + struct sof_ipc_comp comp; + struct sof_ipc_comp_config config; + uint32_t size; /**< size of bespoke data section in bytes */ + uint32_t type; /**< sof_ipc_process_type */ + + /* reserved for future use */ + uint32_t reserved[7]; + + /* These are additional parameters for file */ + uint32_t rate; + uint32_t channels; + char *fn; + uint32_t mode; + uint32_t frame_fmt; + uint32_t direction; /**< SOF_IPC_STREAM_ */ +} __attribute__((packed, aligned(4))); /* frees components, buffers and pipelines * SOF_IPC_TPLG_COMP_FREE, SOF_IPC_TPLG_PIPE_FREE, SOF_IPC_TPLG_BUFFER_FREE @@ -223,13 +267,13 @@ struct sof_ipc_comp_process { struct sof_ipc_free { struct sof_ipc_cmd_hdr hdr; uint32_t id; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); struct sof_ipc_comp_reply { struct sof_ipc_reply rhdr; uint32_t id; uint32_t offset; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* * Pipeline @@ -254,24 +298,29 @@ struct sof_ipc_pipe_new { uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */ uint32_t xrun_limit_usecs; /**< report xruns greater than limit */ uint32_t time_domain; /**< scheduling time domain */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* pipeline construction complete - SOF_IPC_TPLG_PIPE_COMPLETE */ struct sof_ipc_pipe_ready { struct sof_ipc_cmd_hdr hdr; uint32_t comp_id; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); struct sof_ipc_pipe_free { struct sof_ipc_cmd_hdr hdr; uint32_t comp_id; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); /* connect two components in pipeline - SOF_IPC_TPLG_COMP_CONNECT */ struct sof_ipc_pipe_comp_connect { struct sof_ipc_cmd_hdr hdr; uint32_t source_id; uint32_t sink_id; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); + +/* extended data struct for UUID components */ +struct sof_ipc_comp_ext { + uint8_t uuid[SOF_UUID_SIZE]; +} __attribute__((packed, aligned(4))); #endif /* __IPC_TOPOLOGY_H__ */ diff --git a/src/include/ipc/trace.h b/src/include/ipc/trace.h index ca4b34fae6ff..3f79e025edd0 100644 --- a/src/include/ipc/trace.h +++ b/src/include/ipc/trace.h @@ -11,6 +11,7 @@ * \brief IPC definitions * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> * \author Keyon Jie <yang.jie@linux.intel.com> + * \author Karol Trzcinski <karolx.trzcinski@linux.intel.com> */ #ifndef __IPC_TRACE_H__ @@ -26,30 +27,59 @@ #define SOF_TRACE_FILENAME_SIZE 32 -/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */ +/* DMA for Trace params info - SOF_IPC_TRACE_DMA_PARAMS */ /* Deprecated - use sof_ipc_dma_trace_params_ext */ struct sof_ipc_dma_trace_params { struct sof_ipc_cmd_hdr hdr; struct sof_ipc_host_buffer buffer; uint32_t stream_tag; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); -/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS_EXT */ +/* DMA for Trace params info - SOF_IPC_TRACE_DMA_PARAMS_EXT */ struct sof_ipc_dma_trace_params_ext { struct sof_ipc_cmd_hdr hdr; struct sof_ipc_host_buffer buffer; uint32_t stream_tag; uint64_t timestamp_ns; /* in nanosecnd */ uint32_t reserved[8]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); -/* DMA for Trace params info - SOF_IPC_DEBUG_DMA_PARAMS */ +/* DMA for Trace params info - SOF_IPC_TRACE_DMA_POSITION */ struct sof_ipc_dma_trace_posn { struct sof_ipc_reply rhdr; uint32_t host_offset; /* Offset of DMA host buffer */ uint32_t overflow; /* overflow bytes if any */ uint32_t messages; /* total trace messages */ -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); + +/* Values used in sof_ipc_trace_filter_elem */ + +/* bits 6..0 */ +#define SOF_IPC_TRACE_FILTER_ELEM_SET_LEVEL 0x01 /**< trace level for selected components */ +#define SOF_IPC_TRACE_FILTER_ELEM_BY_UUID 0x02 /**< filter by uuid key */ +#define SOF_IPC_TRACE_FILTER_ELEM_BY_COMP 0x03 /**< filter by component id */ +#define SOF_IPC_TRACE_FILTER_ELEM_BY_PIPE 0x04 /**< filter by pipeline */ +#define SOF_IPC_TRACE_FILTER_ELEM_TYPE_MASK 0x7F /**< filter element type mask */ + +/* bit 7 */ +#define SOF_IPC_TRACE_FILTER_ELEM_FIN 0x80 /**< mark last filter in set */ + +/* bits 31..8: Unused */ + +/** part of sof_ipc_trace_filter, ABI3.17 */ +struct sof_ipc_trace_filter_elem { + int32_t key; /**< SOF_IPC_TRACE_FILTER_ELEM_ {LEVEL, UUID, COMP, PIPE} */ + int32_t value; /**< element value */ +} __attribute__((packed, aligned(4))); + +/** Runtime tracing filtration data - SOF_IPC_TRACE_FILTER_UPDATE, ABI3.17 */ +struct sof_ipc_trace_filter { + struct sof_ipc_cmd_hdr hdr; /**< IPC command header */ + uint32_t elem_cnt; /**< number of entries in elems[] array */ + uint32_t reserved[8]; /**< reserved for future usage */ + /** variable size array with new filtering settings */ + struct sof_ipc_trace_filter_elem elems[]; +} __attribute__((packed, aligned(4))); /* * Commom debug @@ -61,6 +91,7 @@ struct sof_ipc_dma_trace_posn { #define SOF_IPC_PANIC_MAGIC 0x0dead000 #define SOF_IPC_PANIC_MAGIC_MASK 0x0ffff000 #define SOF_IPC_PANIC_CODE_MASK 0x00000fff + #define SOF_IPC_PANIC_MEM (SOF_IPC_PANIC_MAGIC | 0x0) #define SOF_IPC_PANIC_WORK (SOF_IPC_PANIC_MAGIC | 0x1) #define SOF_IPC_PANIC_IPC (SOF_IPC_PANIC_MAGIC | 0x2) @@ -82,6 +113,6 @@ struct sof_ipc_panic_info { uint32_t code; /* SOF_IPC_PANIC_ */ char filename[SOF_TRACE_FILENAME_SIZE]; uint32_t linenum; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); #endif /* __IPC_TRACE_H__ */ diff --git a/src/include/ipc/xtensa.h b/src/include/ipc/xtensa.h index d392844470a2..6cf655a6efff 100644 --- a/src/include/ipc/xtensa.h +++ b/src/include/ipc/xtensa.h @@ -54,6 +54,6 @@ struct sof_ipc_dsp_oops_xtensa { uint32_t windowstart; uint32_t excsave1; uint32_t ar[]; -} __attribute__((packed)); +} __attribute__((packed, aligned(4))); #endif /* __IPC_XTENSA_H__ */ diff --git a/src/include/ipc3/header.h b/src/include/ipc3/header.h new file mode 100644 index 000000000000..0c3b5bba7010 --- /dev/null +++ b/src/include/ipc3/header.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc3/header.h + * \brief IPC3 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC3_HEADER_H__ +#define __SOF_IPC3_HEADER_H__ + +#include <stdint.h> + +#define ipc_from_hdr(x) ((struct sof_ipc_cmd_hdr *)x) + +/** + * \brief Generic message header. IPC MAJOR 3 version. + * All IPC3 messages use this header as abstraction + * to platform specific calls. + */ +struct ipc_cmd_hdr { + uint32_t dat[2]; +}; + +#endif diff --git a/src/include/ipc3/probe.h b/src/include/ipc3/probe.h new file mode 100644 index 000000000000..b603f77a9cdd --- /dev/null +++ b/src/include/ipc3/probe.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Adrian Bonislawski <adrian.bonislawski@linux.intel.com> + * Artur Kloniecki <arturx.kloniecki@linux.intel.com> + */ + +/** + * \file include/ipc/probe.h + * \brief Probe IPC definitions + * \author Adrian Bonislawski <adrian.bonislawski@linux.intel.com> + * \author Artur Kloniecki <arturx.kloniecki@linux.intel.com> + */ + +#ifndef __IPC_PROBE_H__ +#define __IPC_PROBE_H__ + +#include <ipc/header.h> +#include <rtos/bit.h> +#include <stdint.h> + +/* + * Buffer id used in the probe output stream headers for + * logging data packet. + */ +#define PROBE_LOGGING_BUFFER_ID 0 + +#define PROBE_PURPOSE_EXTRACTION 0x1 +#define PROBE_PURPOSE_INJECTION 0x2 +#define PROBE_PURPOSE_LOGGING 0x3 +#define PROBE_PURPOSE_TRACING 0x4 + +/** + * Description of probe dma + */ +struct probe_dma { + uint32_t stream_tag; /**< Stream tag associated with this DMA */ + uint32_t dma_buffer_size; /**< Size of buffer associated with this DMA */ +} __attribute__((packed, aligned(4))); + +/** + * Description of probe point id + */ +typedef struct probe_point_id { + uint32_t full_id; +} __attribute__((packed, aligned(4))) probe_point_id_t; + +/** + * Description of probe point + */ +struct probe_point { + probe_point_id_t buffer_id; /**< ID of buffer to which probe is attached */ + uint32_t purpose; /**< PROBE_PURPOSE_xxx */ + uint32_t stream_tag; /**< Stream tag of DMA via which data will be provided for injection. + * For extraction purposes, stream tag is ignored when received, + * but returned actual extraction stream tag via INFO function. + */ +} __attribute__((packed, aligned(4))); + +/** + * \brief DMA ADD for probes. + * + * Used as payload for IPCs: SOF_IPC_PROBE_INIT, SOF_IPC_PROBE_DMA_ADD. + */ +struct sof_ipc_probe_dma_add_params { + struct sof_ipc_cmd_hdr hdr; /**< Header */ + uint32_t num_elems; /**< Count of DMAs specified in array */ + struct probe_dma probe_dma[]; /**< Array of DMAs to be added */ +} __attribute__((packed, aligned(4))); + +/** + * \brief Reply to INFO functions. + * + * Used as payload for IPCs: SOF_IPC_PROBE_DMA_INFO, SOF_IPC_PROBE_POINT_INFO. + */ +struct sof_ipc_probe_info_params { + struct sof_ipc_reply rhdr; /**< Header */ + uint32_t num_elems; /**< Count of elements in array */ + union { + struct probe_dma probe_dma[0]; /**< DMA info */ + struct probe_point probe_point[0]; /**< Probe Point info */ + }; +} __attribute__((packed, aligned(4))); + +/** + * \brief Probe DMA remove. + * + * Used as payload for IPC: SOF_IPC_PROBE_DMA_REMOVE + */ +struct sof_ipc_probe_dma_remove_params { + struct sof_ipc_cmd_hdr hdr; /**< Header */ + uint32_t num_elems; /**< Count of stream tags specified in array */ + uint32_t stream_tag[]; /**< Array of stream tags associated with DMAs to remove */ +} __attribute__((packed, aligned(4))); + +/** + * \brief Add probe points. + * + * Used as payload for IPC: SOF_IPC_PROBE_POINT_ADD + */ +struct sof_ipc_probe_point_add_params { + struct sof_ipc_cmd_hdr hdr; /**< Header */ + uint32_t num_elems; /**< Count of Probe Points specified in array */ + struct probe_point probe_point[]; /**< Array of Probe Points to add */ +} __attribute__((packed, aligned(4))); + +/** + * \brief Remove probe point. + * + * Used as payload for IPC: SOF_IPC_PROBE_POINT_REMOVE + */ +struct sof_ipc_probe_point_remove_params { + struct sof_ipc_cmd_hdr hdr; /**< Header */ + uint32_t num_elems; /**< Count of buffer IDs specified in array */ + uint32_t buffer_id[]; /**< Array of buffer IDs from which Probe Points should be removed */ +} __attribute__((packed, aligned(4))); + +#endif /* __IPC_PROBE_H__ */ diff --git a/src/include/ipc4/aec.h b/src/include/ipc4/aec.h new file mode 100644 index 000000000000..9456f86bcdf8 --- /dev/null +++ b/src/include/ipc4/aec.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/aec.h + * \brief IPC4 global aec definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_AEC_CONFIG_H__ +#define __SOF_IPC4_AEC_CONFIG_H__ + +#include <stdint.h> +#include <ipc4/base-config.h> + +struct sof_ipc4_aec_config { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_audio_format reference_fmt; + struct ipc4_audio_format output_fmt; + uint32_t cpc_low_power_mode; +}; + +enum sof_ipc4_aec_config_params { + IPC4_AEC_SET_EXT_FMT, +}; + +#endif diff --git a/src/include/ipc4/alh.h b/src/include/ipc4/alh.h new file mode 100644 index 000000000000..7691b9fe0a11 --- /dev/null +++ b/src/include/ipc4/alh.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/alh.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_ALH_H__ +#define __SOF_IPC4_ALH_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> +#include <ipc4/gateway.h> + +#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 + +#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS) || \ + defined(CONFIG_SOC_ACE15_MTPM) +#define IPC4_DAI_NUM_ALH_BI_DIR_LINKS 16 +#define IPC4_DAI_NUM_ALH_BI_DIR_LINKS_GROUP 4 +#else +#define IPC4_DAI_NUM_ALH_BI_DIR_LINKS 0 +#define IPC4_DAI_NUM_ALH_BI_DIR_LINKS_GROUP 0 +#endif + +/* copier id = (group id << 4) + codec id + IPC4_ALH_DAI_INDEX_OFFSET + * dai_index = (group id << 8) + codec id; + */ +#define IPC4_ALH_DAI_INDEX(x) ((((x) & 0xF0) << IPC4_DAI_NUM_ALH_BI_DIR_LINKS_GROUP) + \ + (((x) & 0xF) - IPC4_ALH_DAI_INDEX_OFFSET)) + +/* Multi-gateways addressing starts from IPC4_ALH_MULTI_GTW_BASE */ +#define IPC4_ALH_MULTI_GTW_BASE 0x50 + +static inline bool is_multi_gateway(const union ipc4_connector_node_id node_id) +{ + return node_id.f.v_index >= IPC4_ALH_MULTI_GTW_BASE; +} + +struct ipc4_alh_multi_gtw_cfg { + /* Number of single channels (valid items in mapping array). */ + uint32_t count; + /* Single to multi aggregation mapping item. */ + struct { + /* Vindex of a single ALH channel aggregated. */ + uint32_t alh_id; + /* Channel mask */ + uint32_t channel_mask; + } mapping[IPC4_ALH_MAX_NUMBER_OF_GTW]; /* < Mapping items */ +} __attribute__((packed, aligned(4))); + +struct sof_alh_configuration_blob { + union ipc4_gateway_attributes gtw_attributes; + struct ipc4_alh_multi_gtw_cfg alh_cfg; +} __attribute__((packed, aligned(4))); + +static inline size_t +get_alh_config_size(const struct sof_alh_configuration_blob *alh_blob) +{ + return sizeof(alh_blob->gtw_attributes) + + sizeof(alh_blob->alh_cfg.count) + + sizeof(alh_blob->alh_cfg.mapping[0]) * alh_blob->alh_cfg.count; +} + +#endif 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 <ievgen.ganakov@intel.com> + */ + +#ifndef __SOF_LIB_AMS_HELPERS_H__ +#define __SOF_LIB_AMS_HELPERS_H__ + +#include <sof/lib/ams.h> +#include <sof/lib/ams_msg.h> +#include <stdint.h> + +#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/base-config.h b/src/include/ipc4/base-config.h new file mode 100644 index 000000000000..0c89d534637a --- /dev/null +++ b/src/include/ipc4/base-config.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 - 2023 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/base-config.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_BASE_CONFIG_H__ +#define __SOF_IPC4_BASE_CONFIG_H__ + +#include <sof/compiler_attributes.h> +#include <module/ipc4/base-config.h> + +struct sof_ipc_stream_params; +void ipc4_base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, + struct sof_ipc_stream_params *params); +void ipc4_audio_format_to_stream_params(const struct ipc4_audio_format *audio_fmt, + struct sof_ipc_stream_params *params); +struct comp_buffer; +void ipc4_update_buffer_format(struct comp_buffer *buf_c, + const struct ipc4_audio_format *fmt); +struct sof_source; +void ipc4_update_source_format(struct sof_source *source, + const struct ipc4_audio_format *fmt); +struct sof_sink; +void ipc4_update_sink_format(struct sof_sink *sink, + const struct ipc4_audio_format *fmt); + +#endif diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h new file mode 100644 index 000000000000..2ae358010c2d --- /dev/null +++ b/src/include/ipc4/base_fw.h @@ -0,0 +1,832 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/base_fw.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_BASE_FW_H__ +#define __SOF_IPC4_BASE_FW_H__ + +/* SOF FW performs autonomous management of clock sources. + * Set MAX_CLK_STATES to 0 in order to propagate this information through IPC and thus + * prevent reception of unsupported clock configuration. + */ +#define IPC4_MAX_CLK_STATES 0 + +/* Max src queue count supported by ipc4 */ +#define IPC4_MAX_SRC_QUEUE 8 + +/* Max dst queue count supported by ipc4 */ +#define IPC4_MAX_DST_QUEUE 8 + +/* Max module instance for single module count supported by ipc4 */ +#define IPC4_MAX_MODULE_INSTANCES 256 + +/* Max ll tasks for a schedule priority count supported by ipc4 */ +#define IPC4_MAX_LL_TASKS_PER_PRI_COUNT 16 + +/* Max dp tasks count supported by ipc4 */ +#define IPC4_MAX_DP_TASKS_COUNT 16 + +/* Max external libraries count supported by ipc4 */ +#define IPC4_MAX_LIBS_COUNT 16 + +/* Max pipeline count supported by ipc4 */ +#define IPC4_MAX_PPL_COUNT 32 + +enum ipc4_basefw_params { + /* Use LARGE_CONFIG_GET to retrieve fw properties as TLV structure + * with typeof AdspProperties. + */ + IPC4_DSP_PROPERTIES = 0, + + IPC4_DSP_RESOURCE_STATE = 1, + + IPC4_RESERVED = 2, + + /* Driver sends this request to enable/disable notifications. This message + * should be used by the driver in debug mode to avoid flooding host with + * underrun notifications when driver is stopped by breakpoint for example. + */ + IPC4_NOTIFICATION_MASK = 3, + + /* Driver sends A-State Table data right after the Base FW is up and ready to + * handle IPC communication. The table is forwarded to the Power Manager to + * configure available power states according to the underlying platform. + */ + IPC4_ASTATE_TABLE = 4, + + /* Driver sends the DMA Control parameter in order to initialize or modify + * DMA gateway configuration outside of a stream lifetime. Typically a DMA + * gateway is initialized during pipeline creation when a Copier module is + * instantiated and attached to that gateway. Similarly the gateway is + * de-initialized when the Copiers parent pipeline is being destroyed. + * However sometimes the driver may want to control the gateway before or + * after a stream is being attached to it. + * + * The data of DMA Control parameter starts with DmaControl structure + * optionally followed by the target gateway specific data (that may consist + * of two parts, the former coming from NHLT BIOS tables and the latter + * aux_config in form of TLV list provided by the driver). + */ + IPC4_DMA_CONTROL = 5, + + /* Driver sets this parameter to control state of FW logging. Driver may + * enable logging for each core and specify logging level. Driver also + * configures period of aging and FIFO full timers. Aging timer period + * specifies how frequently FW sends Log Buffer Status notification for new + * entries in case the usual notification sending criteria are not met + * (half of the buffer is full). Fifo full timer period specifies the latency + * of logging "dropped log entries" information after the content is consumed + * by the driver but no new log entry appears (which would trigger logging + * "dropped entries" as well). + * + * SystemTime property must be provided by the driver prior to enabling + *the logs for the first time, otherwise error is raised by FW since + * it will not be able to translate log event timestamps into the host + * CPU clock domain. + * + * Log FIFO content is reset on logs enabled by the driver, so the RP + * is expected to be 0, however the driver should not assume that value + * but just read the RP from FW Registers instead. + */ + IPC4_ENABLE_LOGS = 6, + + /* Use LARGE_CONFIG_SET/LARGE_CONFIG_GET to write/read FW configuration. + * + * Driver requests value of this Base FW property to discover FW configuration. + * Configuration data is returned in form of TLV list and contains items as + * defined in the next table. + * + * Driver may also set values of parameters that are marked as RW in the table. + * FirmwareConfig is expected to be queried/set once at the FW + * initialization time. Properties that are expected to be changed more + * frequently (e.g. current number of modules descriptors loaded or + * performance measurements state) are moved and became separate + * parameters. + */ + IPC4_FW_CONFIG = 7, + + /* Use LARGE_CONFIG_GET to read HW configuration. + * + * Driver requests value of this Base FW property to discover underlying HW + * configuration. Configuration data is returned in form of TLV list. + */ + IPC4_HW_CONFIG_GET = 8, + + /* Use LARGE_CONFIG_GET to read modules configuration. + * + * Driver requests value of this Base FW property to retrieve list of the + * module entries loaded into the FW memory space (as part of either the + * image manifest or library manifest). + * + * The response may be too large to fit into a single message. The driver + * must be prepared to handle multiple fragments. + */ + IPC4_MODULES_INFO_GET = 9, + + /* Use LARGE_CONFIG_GET to read pipeline list. + * + * Driver requests value of this Base FW property to retrieve list of + * pipelines IDs. Once the list is received driver may retrieve properties of + * each pipeline by querying Pipeline Info specifying IDs from the list. + */ + IPC4_PIPELINE_LIST_INFO_GET = 10, + + /* Use LARGE_CONFIG_GET to read pipelines properties. + * + * Driver requests value of this Base FW property to retrieve properties of a + * pipeline. Full parameter id wrapped by APPLICATION_PARAM into the request + * payload is of ExtendedParameterId type where parameter_type is set to + * PIPELINE_PROPS and parameter_instance is set to the target pipeline id. + * + * Properties of a single pipeline are expected to fit into a single IPC + * response as there is a room for ~1K of IDs of tasks and modules instances. + */ + IPC4_PIPELINE_PROPS_GET = 11, + + /* Use SCHEDULERS_INFO_GET to read schedulers configuration. + * + * Driver requests value of this Base FW property to retrieve list of task + * schedulers and tasks created inside the FW and being executed on a core. + * Full parameter id wrapped by APPLICATION_PARAM into the request payload + * is of ExtendedParameterId type where parameter_type is set to + * SCHEDULERS_INFO and parameter_instance is set to the target core id. + */ + IPC4_SCHEDULERS_INFO_GET = 12, + + /* Use LARGE_CONFIG_GET to read gateway configuration */ + IPC4_GATEWAYS_INFO_GET = 13, + + /* Use LARGE_CONFIG_GET to get information on memory state. + * + * Driver requests value of this Base FW property to retrieve information + * about current DSP memory state. Configuration data is returned in form of + * TLV list and contains items as defined in the next table. + */ + IPC4_MEMORY_STATE_INFO_GET = 14, + + /* Use LARGE_CONFIG_GET to get information on power state. + * + * Driver requests value of this Base FW property to retrieve information + * about current DSP power state. Configuration data is returned in form of + * TLV list and contains items as defined in the next table. + */ + IPC4_POWER_STATE_INFO_GET = 15, + + /* Use LARGE_CONFIG_GET to get information about libraries + * loaded into the ADSP memory. + */ + IPC4_LIBRARIES_INFO_GET = 16, + + /* Use LARGE_CONFIG_SET to set value of this Base FW property to control + * performance measurements state. There is one global flag that controls the + * state of performance measurements process globally. + * + * Driver may set value of this Base FW property to control state of + * performance measurements process in the DSP FW. + * + * This state is applied to MCPS monitoring only. Memory allocation + * state is always available. + */ + IPC4_PERF_MEASUREMENTS_STATE = 17, + + /* Use LARGE_CONFIG_GET to retrieve retrieve global performance data. FW + * sends a list of captured performance data per enabled core and power mode. + * MCPS are sampled each DSP system tick (1ms in D0) and used to compute peak + * and average values. + * + * Driver requests value of this Base FW property to retrieve performance data + * captured on the DSP. FW sends a list of items reported by FW components. + * KCPS are sampled either each DSP system tick (1ms in D0) for low latency + * and infrastructure components, or each processed frame otherwise. The KCPS + * are used to compute reported peak and average values by FW. + * + * Data items reported for resource_id = {module_id = 0, instance_id = + * core_id} contain total KCPS spent on each active core. + * + *This parameter reports only KCPS, while the memory state is reported + * by Memory State Info parameter. + */ + IPC4_GLOBAL_PERF_DATA = 18, + + /* Use LARGE_CONFIG_GET to get information on l2 cache state. + * + * Driver requests value of this Base FW property to retrieve information + * about current state of L2 Cache. Available on platforms where L2 cache is + * in use, otherwise ADSP_IPC_UNAVAILABLE is returned. + */ + IPC4_L2_CACHE_INFO_GET = 19, + + /* Driver sets this property to pass down information about host system time. + * + * Driver sets this property to pass down information about current system + * time. It is used by FW to translate event timestamps (Logs, Probes packets + * for example) to the system time (current host time) domain. + * + * The value of system time is expressed in us + * Time is in UTC + * Epoch is 1601-01-01T00:00:00Z + */ + IPC4_SYSTEM_TIME = 20, + + /* Use LARGE_CONFIG_SET to configure firmware for performance */ + IPC4_PERFORMANCE_CONFIGURATION = 21, + + /* Use LARGE_CONFIG_SET to register KCPS into power manager + * service per core 0. Negative numbers are allowed. + */ + IPC4_REGISTER_KCPS = 22, + + /* Use LARGE_CONFIG_SET to request additional resource allocation */ + IPC4_RESOURCE_ALLOCATION_REQUEST = 23, + + /* Driver may set value of this Base FW property to control state of + * I/o performance measurements process in the DSP FW. + */ + IPC4_IO_PERF_MEASUREMENTS_STATE = 24, + + /* The command returns I/O statistics when they are enabled */ + IPC4_IO_GLOBAL_PERF_DATA = 25, + + /* The command is shorter version of Modules Info command. + * It is used to retrieve module ID for a specified module UUID. + */ + IPC4_GET_MODULE_ID = 26, + + /* EXTENDED_SYSTEM_TIME command returns current value of UTC, RTC and HH. + * The system time must be set first via SYSTEM_TIME command before + * EXTENDED_SYSTEM_TIME can be used. + */ + IPC4_EXTENDED_SYSTEM_TIME = 27, + + /* Driver may set value of this Base FW property to control state + * of telemetry collection process in the DSP FW. + * In started state, TELEMETRY_STATE command is used to change threshold + * and aging timer depend on system state. + */ + IPC4_TELEMETRY_STATE = 28, + + /* The command to read data from the telemetry circular buffer. + * The telemetry data can be produced by firmware modules using + * System Service APIand then all telemetry is collected via one + * common mechanism provided by the base firmware. + */ + IPC4_TELEMETRY_DATA = 29, + + /* This command is extended version of Global Performance Data which + * provides more details information about total number of + * cycles consumed by each of the modules. + */ + IPC4_EXTENDED_GLOBAL_PERF_DATA = 30, + + /* Use LARGE_CONFIG_SET to change SDW ownership */ + IPC4_SDW_OWNERSHIP = 31, + + /* This command is used by SW to notify FW for changing state of Mic Privacy */ + IPC4_MIC_PRIVACY_HW_MANAGED_STATE_CHANGE = 35, + + /* Set policy mask for mic privacy in FW managed mode */ + IPC4_SET_MIC_PRIVACY_FW_MANAGED_POLICY_MASK = 36, +}; + +enum ipc4_fw_config_params { + /* Firmware version */ + IPC4_FW_VERSION_FW_CFG = 0, + /* Indicates whether legacy DMA memory is managed by FW */ + IPC4_MEMORY_RECLAIMED_FW_CFG = 1, + /* Frequency of oscillator clock */ + IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG = 2, + /* Frequency of PLL clock */ + IPC4_FAST_CLOCK_FREQ_HZ_FW_CFG = 3, + /* List of static and dynamic DMA buffer sizes. + * SW may configure minimum and maximum size for each buffer. + */ + IPC4_DMA_BUFFER_CONFIG_FW_CFG = 4, + /* Audio Hub Link support level. + * Note: Lower 16-bits may be used in future to indicate + * implementation revision if necessary. + */ + IPC4_ALH_SUPPORT_LEVEL_FW_CFG = 5, + /* Size of IPC downlink mailbox */ + IPC4_DL_MAILBOX_BYTES_FW_CFG = 6, + /* Size of IPC uplink mailbox */ + IPC4_UL_MAILBOX_BYTES_FW_CFG = 7, + /* Size of trace log buffer */ + IPC4_TRACE_LOG_BYTES_FW_CFG = 8, + /* Maximum number of pipelines that may be instantiated at the same time */ + IPC4_MAX_PPL_CNT_FW_CFG = 9, + /* Maximum number of A-state table entries that may be configured by the driver. + * Driver may also use this value to estimate the size of data retrieved as + * ASTATE_TABLE property. + */ + IPC4_MAX_ASTATE_COUNT_FW_CFG = 10, + /* Maximum number of input or output pins supported by a module */ + IPC4_MAX_MODULE_PIN_COUNT_FW_CFG = 11, + /* Current total number of module entries loaded into the DSP */ + IPC4_MODULES_COUNT_FW_CFG = 12, + /* Maximum number of module instances supported by FW */ + IPC4_MAX_MOD_INST_COUNT_FW_CFG = 13, + /* Maximum number of LL tasks that may be allocated with + * the same priority (specified by a priority of the parent pipeline). + */ + IPC4_MAX_LL_TASKS_PER_PRI_COUNT_FW_CFG = 14, + /* Number of LL priorities */ + IPC4_LL_PRI_COUNT = 15, + /* Maximum number of DP tasks that may be allocated on a single core */ + IPC4_MAX_DP_TASKS_COUNT_FW_CFG = 16, + /* Maximum number of libraries that can be loaded into the ADSP memory */ + IPC4_MAX_LIBS_COUNT_FW_CFG = 17, + /* Configuration of system tick source and period */ + IPC4_SCHEDULER_CONFIGURATION = 18, + /* Frequency of xtal oscillator clock */ + IPC4_XTAL_FREQ_HZ_FW_CFG = 19, + /* Configuration of clocks */ + IPC4_CLOCKS_CONFIGURATION = 20, + /* USB Audio Offload support */ + IPC4_UAOL_SUPPORT = 21, + /* Configuration of Dynamic Power Gating Policy */ + IPC4_POWER_GATING_POLICY = 22, + /* Configuration of assert mode + * Run-time asserts requires special handling by decoder. + * Asserts will be in format: "%passert", ptr_to_assert_desc. + * + * ptr_to_assert_desc will point to place in .asserts_desc section in ELF. + * Data must be cased to struct: struct assert_entry + */ + IPC4_ASSERT_MODE = 23, + /* Size of telemetry buffer in bytes. The default size is 4KB */ + IPC4_TELEMETRY_BUFFER_SIZE = 24, + /* HW version information */ + IPC4_BUS_HARDWARE_ID = 25, + /* Total memory size available in debug window */ + IPC4_DEBUG_WINDOW_SIZE = 26, + /* Number of realtime Key Phrase Buffer (KPB) output pins */ + IPC4_KPB_RT_SINK_COUNT = 27, + /* Manual control of DMI L1 state */ + IPC4_DMI_FORCE_L1_EXIT = 28, + /* FW context save on D3 entry */ + IPC4_FW_CONTEXT_SAVE = 29, + /* Minimum size of host buffer in ms */ + IPC4_FW_MIN_HOST_BUFFER_PERIODS = 33, + /* decoder/encoder codec information */ + IPC4_FW_SOF_INFO = 35, + /* Total number of FW config parameters */ + IPC4_FW_CFG_PARAMS_COUNT, + /* Max config parameter id */ + IPC4_MAX_FW_CFG_PARAM = IPC4_FW_CFG_PARAMS_COUNT - 1, +}; + +/* + * tuple based array for SOF specific information under IPC4_FW_SOF_INFO + * tuple of fw_config + */ +enum ipc4_fw_sof_info_params { + /* decoder/encoder codec information */ + IPC4_SOF_CODEC_INFO = 0, + + /* Total number of SOF config parameters */ + IPC4_SOF_CFG_PARAMS_COUNT, + /* Max config parameter id */ + IPC4_MAX_SOF_CFG_PARAM = IPC4_SOF_CFG_PARAMS_COUNT - 1, +}; + +enum ipc4_hw_config_params { + /* Version of cAVS implemented by FW (from ROMInfo) */ + IPC4_CAVS_VER_HW_CFG = 0, + /* How many dsp cores are available in current audio subsystem */ + IPC4_DSP_CORES_HW_CFG = 1, + /* Size of a single memory page */ + IPC4_MEM_PAGE_BYTES_HW_CFG = 2, + /* Total number of physical pages available for allocation */ + IPC4_TOTAL_PHYS_MEM_PAGES_HW_CFG = 3, + /* + * Number of items in controller_base_addr array is specified by + * controller_count. note Lower 16 bits of I2sVersion may be used + * in future to indicate implementation revision if necessary. + */ + IPC4_I2S_CAPS_HW_CFG = 4, + /* GPDMA capabilities */ + IPC4_GPDMA_CAPS_HW_CFG = 5, + /*Total number of DMA gateways of all types */ + IPC4_GATEWAY_COUNT_HW_CFG = 6, + /* Number of HP SRAM memory banks manageable by DSP */ + IPC4_HP_EBB_COUNT_HW_CFG = 7, + /* Number of LP SRAM memory banks manageable by DSP */ + IPC4_LP_EBB_COUNT_HW_CFG = 8, + /* Size of a single memory bank (EBB) in bytes */ + IPC4_EBB_SIZE_BYTES_HW_CFG = 9, + /* UAOL capabilities */ + IPC4_UAOL_CAPS_HW_CFG = 10, + /* Mic privacy capabilities */ + IPC4_INTEL_MIC_PRIVACY_CAPS_HW_CFG = 11 +}; + +enum ipc4_memory_type { + /* High power sram memory */ + IPC4_HP_SRAM_MEMORY = 0, + /*Low power sram memory */ + IPC4_LP_SRAM_MEMORY = 1 +}; + +enum ipc4_resource_state_request { + /* + * This type is used to inform about free physical HP sram memory pages + * available. + */ + IPC4_FREE_PHYS_MEM_PAGES = 0 +}; + +/* PhysMemPages describes current free phys memory pages */ +struct ipc4_phys_mem_pages { + uint32_t mem_type; + /* Number of pages */ + uint32_t pages; +} __attribute__((packed, aligned(4))); + +#define IPC4_UNDERRUN_AT_GATEWAY_NOTIFICATION_MASK_IDX 0 +#define IPC4_UNDERRUN_AT_MIXER_NOTIFICATION_MASK_IDX 1 +#define IPC4_BUDGET_VIOLATION_NOTIFICATION_MASK_IDX 2 +#define IPC4_OVERRUN_AT_GATEWAY_NOTIFICATION_MASK_IDX 3 + +struct ipc4_notification_mask_info { + /* Indicates which notifications are begin enabled/disabled */ + uint32_t ntfy_mask; + /* Indicates if notifications indicated by corresponding bits in ntfy_mask + * are enabled (b'1) or disabled (b'0). + */ + uint32_t enabled_mask; +} __attribute__((packed, aligned(4))); + +enum ipc4_clock_src { + /* Low Power XTAL (oscillator) clock source */ + IPC4_CLOCK_SRC_XTAL = 0, + + /* Low Power Ring Oscillator */ + IPC4_CLOCK_SRC_LP_RING_OSC, + /* High Power Ring Oscillator */ + IPC4_CLOCK_SRC_HP_RING_OSC, + /* Low Power XTAL (oscillator) clock source + * Frequency depends on platform. This XTAL is different from CLOCK_SRC_XTAL + * because it is generate in IP (not given from platform), saving more power. + */ + IPC4_CLOCK_SRC_WOV_XTAL, + IPC4_CLOCK_SRC_INVALID, + IPC4_CLOCK_SRC_MAX_IDX = IPC4_CLOCK_SRC_INVALID - 1, +}; + +struct ipc4_astate { + /* Kilo Cycles Per Second. + * Specifies core load threshold (expressed in kilo cycles per second). When + * load is below this threshold DSP is clocked from source specified by clk_src. + * + * Configuring 0 kcps in the first entry means that this clock source will be + * used in idle state only. + */ + uint32_t kcps; + /* Clock source associated with kcps threshold */ + enum ipc4_clock_src clock_src; +} __attribute__((packed, aligned(4))); + +/* Power Manager Astate Table */ +struct ipc4_astate_table { + /* Number of entries in astates_ array. The value does not exceed maximum + * number specified by MAX_ASTATE_COUNT member of Base FWs + * FIRMWARE_CONFIG parameter. + */ + uint32_t astates_count_; + /* Array of states. */ + struct ipc4_astate astates_[3]; +} __attribute__((packed, aligned(4))); + +/* All members have the same meaning as in the CopierGatewayCfg structure + * (except for the dma_buffer_size that is not used here). + */ +struct ipc4_dma_control { + uint32_t node_id; + uint32_t config_length; + uint32_t config_data[0]; +} __attribute__((packed, aligned(4))); + +enum ipc4_perf_measurements_state_set { + IPC4_PERF_MEASUREMENTS_DISABLED = 0, + IPC4_PERF_MEASUREMENTS_STOPPED = 1, + IPC4_PERF_MEASUREMENTS_STARTED = 2, + IPC4_PERF_MEASUREMENTS_PAUSED = 3, +}; + +struct ipc4_perf_data_item { + /*ID of the core running the load being reported */ + uint32_t resource_id; + /* + * 0 - D0, + * 1 - D0i3, + */ + uint32_t power_mode : 1; + uint32_t rsvd : 30; + uint32_t is_removed : 1; + /* Peak KCPS (Kilo Cycles Per Second) captured */ + uint32_t peak_kcps; + /* Average KCPS (Kilo Cycles Per Second) measured */ + uint32_t avg_kcps; +} __attribute__((packed, aligned(4))); + +/* + * PerfDataItem with additional fields required by module + * instance to properly calculate its performance data. + * NOTE: Only PerfDataItem is part of GlobalPerfData. + */ +struct ipc4_perf_data_item_mi { + struct ipc4_perf_data_item item; + /* Total iteration count of module instance */ + uint32_t total_iteration_count; + /* Total cycles consumed by module instance */ + uint64_t total_cycles_consumed; +} __attribute__((packed, aligned(4))); + +struct ipc4_global_perf_data { + /* Specifies number of items in perf_items array */ + uint32_t perf_item_count; + /* Array of global performance measurements */ + struct ipc4_perf_data_item perf_items[1]; +} __attribute__((packed, aligned(4))); + +enum ipc4_low_latency_interrupt_source { + IPC4_LOW_POWER_TIMER_INTERRUPT_SOURCE = 1, + IPC4_DMA_GATEWAY_INTERRUPT_SOURCE = 2 +}; + +struct ipc4_scheduler_config { + uint32_t sys_tick_multiplier; + uint32_t sys_tick_divider; + uint32_t sys_tick_source; + uint32_t sys_tick_cfg_length; + uint32_t sys_tick_cfg[1]; +} __attribute__((packed, aligned(4))); + +struct ipc4_system_time { + /* Lower DWORD of current system time value */ + uint32_t val_l; + /* Upper DWORD of current system time value */ + uint32_t val_u; +} __attribute__((packed, aligned(4))); + +struct ipc4_system_time_info { + struct ipc4_system_time host_time; + struct ipc4_system_time dsp_time; +} __attribute__((packed, aligned(4))); + +struct ipc4_ext_system_time { + /* Lower DWORD of current system time value. */ + uint32_t utc_l; + /* Upper DWORD of current system time value. */ + uint32_t utc_u; + /* Lower DWORD of current RTC value. */ + uint32_t rtc_l; + /* Upper DWORD of current RTC value. */ + uint32_t rtc_u; + /* Lower DWORD of current ART value. */ + uint32_t art_l; + /* Upper DWORD of current ART value. */ + uint32_t art_u; +}; + +enum ipc4_pipeline_attributes { + /* Determines whether on pipeline will be allocated module(s) with ULP capability */ + IPC4_ULTRA_LOW_POWER = 0, + /* Determines whether on pipeline will be allocated + * module(s) that can report autonomous reset. + */ + IPC4_AUTONOMOUS_RESET = 1, +}; + +enum ipc4_resource_allocation_type { + /* Allocate KCPS */ + IPC4_RAT_DSP_KCPS = 0, + IPC4_RAT_MEMORY = 1, +}; + +struct ipc4_resource_kcps { + uint32_t core_id; + int32_t kcps; +} __attribute__((packed, aligned(4))); + +struct ipc4_resource_memory { + /* base address to allocate */ + uint32_t address; + /* size of allocate */ + uint32_t size; +} __attribute__((packed, aligned(4))); + +struct ipc4_resource_request { + /* Type of resource to allocate */ + uint32_t ra_type; + union { + /* Valid for ra_type == RAT_DSP_KCPS */ + struct ipc4_resource_kcps kcps; + /* Valid for ra_type == RAT_MEMORY */ + struct ipc4_resource_memory memory; + } ra_data; +} __attribute__((packed, aligned(4))); + +#define IPC4_LPSRAM_STATE 0 +#define IPC4_HPSRAM_STATE 1 + +struct ipc4_sram_state_page_alloc { + /* Number of items in page_alloc array */ + uint32_t page_alloc_count; + /* State of memory page allocation. + * bit[i] indicates whether i-th page is allocated. + */ + uint16_t page_alloc[1]; +} __attribute__((packed, aligned(4))); + +struct ipc4_sram_state_info { + /* Number of free memory pages */ + uint32_t free_phys_mem_pages; + /* Number of items in ebb_state array */ + uint32_t ebb_state_dword_count; + /* State of EBBs (memory banks) */ + /* bit[i] indicates whether i-th EBB is in use (1) or powered down (0) */ + uint32_t ebb_state[1]; + struct ipc4_sram_state_page_alloc page_alloc_struct; +} __attribute__((packed, aligned(4))); + +enum ipc4_alh_version { + IPC4_ALH_NO_SUPPORT, + IPC4_ALH_CAVS_1_8 = 0x10000, +}; + +struct ipc4_library_props { + /* Library run-time identifier, depends on order of loading. */ + /* Base FW is always reported with id 0. */ + uint32_t id; + /* Name of the library. */ + uint8_t name[8]; + /* Major version of the library. */ + uint16_t major_version; + /* Minor version of the library. */ + uint16_t minor_version; + /* Hotfix version of the library. */ + uint16_t hotfix_version; + /* Build version of the library. */ + uint16_t build_version; + /* Number of modules packed into the library. */ + uint32_t num_module_entries; +} __packed __aligned(4); + +struct ipc4_libraries_info { + /* Specifies number of items in libraries array. */ + uint32_t library_count; + /* Array of libraries properties. */ + struct ipc4_library_props libraries[0]; +} __packed __aligned(4); + +struct ipc4_log_state_info { + /* + * Specifies how frequently FW sends Log Buffer Status + * notification for new entries in case the usual notification + * sending criteria are not met (half of the buffer is full). The + * parameter is specified in number of system ticks. + */ + uint32_t aging_timer_period; + + /* + * Specifies the latency of logging 'dropped log entries' + * information after the content is consumed by the driver but no + * new log entry appears (which would trigger logging 'dropped + * entries' as well). The parameter is specified in number of + * system ticks. + */ + uint32_t fifo_full_timer_period; + + /* 0 if logging is disabled, otherwise enabled */ + uint32_t enable; + + /* + * Logging mask of priorities and components for all + * supported providers. Nth entry in array gives priorities and + * components mask for Nth provider (library). + */ + uint32_t logs_mask[IPC4_MAX_LIBS_COUNT]; +} __attribute__((packed, aligned(4))); + +enum ipc4_power_state_type { + IPC4_ACTIVE_CORES_MASK = 0, + IPC4_CORE_KCPS = 1, +}; + +/* Scheduler info get structures */ + +struct task_props { + /* Unique ID of task. */ + uint32_t task_id; + /* Specifies number of items in module_instance_id array. */ + uint32_t module_instance_count; + /* Array of IDs of module instances running inside the task. */ + uint32_t module_instance_id[]; +} __packed __aligned(4); + +struct scheduler_props { + /* Processing domain, one of: + * COMP_PROCESSING_DOMAIN_LL or COMP_PROCESSING_DOMAIN_DP + */ + uint32_t processing_domain; + /* ID of core that scheduler is running on. */ + uint32_t core_id; + /* Specifies number of items in task_info array. */ + uint32_t task_count; + struct task_props task_info[]; +} __packed __aligned(4); + +struct schedulers_info { + /* Specifies number of items in scheduler_info array. */ + uint32_t scheduler_count; + /* Array of scheduler properties. */ + struct scheduler_props scheduler_info[]; +} __packed __aligned(4); + +struct ipc4_system_time_info *basefw_get_system_time_info(void); + +/* Specifies I2S IPC4 version for PTL platform */ +static const uint32_t I2S_VER_30_PTL = 0x40000; + +struct perf_data_item { + /* ID of the FW component */ + uint32_t resource_id; + /* 0 - D0, 1 - D0i3. */ + uint32_t power_mode : 1; + uint32_t rsvd : 30; + /* the component still exists (0) or has been already deleted (1) */ + uint32_t is_removed : 1; + /* Peak KCPS captured */ + uint32_t peak_kcps; + /* Average KCPS measured */ + uint32_t avg_kcps; +} __packed __aligned(4); + +struct ext_perf_data_item { + /* ID of the FW component */ + uint32_t resource_id; + /* 0 - D0, 1 - D0i3. */ + uint32_t power_mode : 1; + uint32_t rsvd : 30; + /* the component still exists (0) or has been already deleted (1) */ + uint32_t is_removed : 1; + /* peak number of DSP cycles used by a module */ + uint32_t module_peak_dsp_cycles; + /* total number of DSP used since by a module start of measurements, */ + uint64_t module_total_dsp_cycles_consumed; + /* how many times a module was executed */ + uint64_t module_total_dsp_iterations; + /* peak number of <restricted> cycles used by a module. + * It is measured against DSP wall clock + */ + uint32_t module_peak_restricted_cycles; + /* total number of <restricted> cycles used by a module since start of + * measurements. It is measured against DSP wall clock + */ + uint64_t module_total_restricted_cycles_consumed; + /* how many times a module invoke <restricted> */ + uint64_t module_total_restricted_iterations; +} __packed __aligned(4); + +struct extended_global_perf_data { + /* Specifies number of items in perf_items array. */ + uint32_t perf_item_count; + /* Array of extended global performance measurements. */ + struct ext_perf_data_item perf_items[0]; +} __packed __aligned(4); + +struct perf_data_item_comp { + struct perf_data_item item; + /* Total iteration count of module instance */ + uint32_t total_iteration_count; + /* Total cycles consumed by module instance */ + uint64_t total_cycles_consumed; + /* <restricted> usage statistics against DSP wallclock cycles */ + uint32_t restricted_peak_cycles; + uint64_t restricted_total_iterations; + uint64_t restricted_total_cycles; + +} __packed __aligned(4); + +struct global_perf_data { + /* Specifies number of items in perf_items array. */ + uint32_t perf_item_count; + /* Array of global performance measurements. */ + struct perf_data_item perf_items[0]; + +} __packed __aligned(4); + +#endif /* __SOF_IPC4_BASE_FW_H__ */ diff --git a/src/include/ipc4/base_fw_vendor.h b/src/include/ipc4/base_fw_vendor.h new file mode 100644 index 000000000000..60173439b502 --- /dev/null +++ b/src/include/ipc4/base_fw_vendor.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + * + * Author: Kai Vehmanen <kai.vehmanen@linux.intel.com> + */ + +/** + * \file include/ipc4/base_fw_platform.h + * \brief Platform specific IPC4 base firmware functionality. + */ + +#ifndef __SOF_IPC4_BASE_FW_VENDOR_H__ +#define __SOF_IPC4_BASE_FW_VENDOR_H__ + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> + +struct comp_dev; + +/* + * TODO: Add a more generic BASE_FW_VENDOR Kconfig if/when + * more vendor specific implementations are added. + */ +#ifdef CONFIG_IPC4_BASE_FW_INTEL + +/** + * \brief Vendor specific routine to add data tuples to FW_CONFIG + * structure sent to host via IPC. + * \param[out] data_offset data offset after tuples added + * \param[in] data pointer where to add new entries + * \return 0 if successful, error code otherwise. + */ +int basefw_vendor_fw_config(uint32_t *data_offset, char *data); + +/** + * \brief Vendor specific routine to add data tuples to HW_CONFIG + * structure sent to host via IPC. + * \param[out] data_offset data offset after tuples added + * \param[in] data pointer where to add new entries + * \return 0 if successful, error code otherwise. + */ +int basefw_vendor_hw_config(uint32_t *data_offset, char *data); + +/** + * \brief Vendor specific routine which return the pointer to + * the boot base manifest. + * \return pointer to struct if successful, null otherwise. + */ +struct sof_man_fw_desc *basefw_vendor_get_manifest(void); + +/** + * \brief Vendor specific routine to get information about modules. + * Function add information and sent to host via IPC. + * \param[out] data_offset data offset after structure added + * \param[in] data pointer where to add new entries + * \return 0 if successful, error code otherwise. + */ +int basefw_vendor_modules_info_get(uint32_t *data_offset, char *data); + +/** + * \brief Implement vendor specific parameter for basefw module. + * This function is called for parameters not handled by + * generic base_fw code. + */ +int basefw_vendor_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data); + +/** + * \brief Implement vendor specific parameter for basefw module. + * This function is called for parameters not handled by + * generic base_fw code. + */ +int basefw_vendor_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data); + +/** + * @brief Vendor specific routine to configure DMA gateway. + * + * @param node_id The node ID of the DMA gateway to configure. + * @param config_data pointer to the configuration data. + * @param data_size Size of the configuration data. + * @return 0 if successful, error code otherwise. + */ +int basefw_vendor_dma_control(uint32_t node_id, + const char *config_data, + size_t data_size); + +#else /* !CONFIG_IPC4_BASE_FW_INTEL */ + +static inline int basefw_vendor_fw_config(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + +static inline int basefw_vendor_hw_config(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + +static inline struct sof_man_fw_desc *basefw_vendor_get_manifest(void) +{ + struct sof_man_fw_desc *desc = NULL; + + return desc; +} + +static inline int basefw_vendor_modules_info_get(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + +static inline int basefw_vendor_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data) +{ + return -EINVAL; +} + +static inline int basefw_vendor_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + return IPC4_UNKNOWN_MESSAGE_TYPE; +} + +static inline int basefw_vendor_dma_control(uint32_t node_id, + const char *config_data, + size_t data_size) +{ + return IPC4_UNKNOWN_MESSAGE_TYPE; +} + +#endif + +#endif /* __SOF_IPC4_BASE_FW_VENDOR_H__ */ diff --git a/src/include/ipc4/detect_test.h b/src/include/ipc4/detect_test.h new file mode 100644 index 000000000000..603bf1741b2c --- /dev/null +++ b/src/include/ipc4/detect_test.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Ievgen Ganakov <ievgen.ganakov@intel.com> + */ + +/** + * \file include/ipc4/detect_test.h + * \brief KD module definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_DETECT_TEST_H__ +#define __SOF_IPC4_DETECT_TEST_H__ + +enum ipc4_detect_test_module_config_params { + /* Use LARGE_CONFIG_SET to process model blob. Ipc mailbox must + * contain properly configured BLOB for Detect Keyword module. + */ + IPC4_DETECT_TEST_SET_MODEL_BLOB = 1, + + /* Use LARGE_CONFIG_SET to set Detect Keyword module parameters. + * Ipc mailbox must contain properly built sof_detect_test_config + * struct. + */ + IPC4_DETECT_TEST_SET_CONFIG = 2, + + /* Use LARGE_CONFIG_GET to retrieve Detect Test config + * Ipc mailbox must contain properly built sof_detect_test_config + * struct. + */ + IPC4_DETECT_TEST_GET_CONFIG = 3 +}; +#endif diff --git a/src/include/ipc4/dmic.h b/src/include/ipc4/dmic.h new file mode 100644 index 000000000000..d09332ec9c5c --- /dev/null +++ b/src/include/ipc4/dmic.h @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_IPC4_DMIC_H__ +#define __SOF_IPC4_DMIC_H__ + +#include <stdint.h> +#include <stddef.h> +#include <sof/drivers/dmic.h> +#include "gateway.h" + +/** + * \file include/ipc4/dmic.h + * \brief IPC4 DMIC definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +/* IOCTL ID of DMIC Set Gain Coefficients */ +#define DMIC_SET_GAIN_COEFFICIENTS 2 + +/* Maximum number of dmic gain coefficients */ +#define DMIC_MAX_GAIN_COEFFS_CNT 4 + +/** + * @brief Structure representing the global configuration for DMIC (Digital Microphone) module. + */ +union dmic_global_cfg { + /** + * @brief Raw 32-bit value of Global Cfg. + */ + uint32_t clock_on_delay; + + /** + * @brief Bitfields of Extended Global Config. + */ + struct { + /** + * @brief Specifies the period in milliseconds to override data with silence after + * DMA transfer is started. + */ + uint32_t silence_period : 16; + + /** + * @brief Specifies the period in milliseconds for fade-in to apply on input data + * (following silence_period if applied). + */ + uint32_t fade_in_period : 16; + } ext_global_cfg; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration of a DMIC channel. + */ +struct dmic_channel_cfg { + /** + * @brief Outcontrol + */ + uint32_t out_control; +}; + +/** + * @brief Structure representing FIR (Finite Impulse Response) configuration. + */ +struct dmic_fir_cfg { + /** + * @brief FIR_CONTROL + * Control register for FIR configuration. + */ + uint32_t fir_control; + + /** + * @brief FIR_CONFIG + * Configuration register for FIR filter. + */ + uint32_t fir_config; + + /** + * @brief DC_OFFSET_LEFT + * DC offset value for the left channel. + */ + uint32_t dc_offset_left; + + /** + * @brief DC_OFFSET_RIGHT + * DC offset value for the right channel. + */ + uint32_t dc_offset_rigth; + + /** + * @brief OUT_GAIN_LEFT + * Output gain value for the left channel. + */ + uint32_t out_gain_left; + + /** + * @brief OUT_GAIN_RIGHT + * Output gain value for the right channel. + */ + uint32_t out_gain_rigth; + + /** + * @brief rsvd_2 + * Reserved field. + */ + uint32_t rsvd_2[2]; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration of the PDM control for DMIC. + * + * This structure defines the configuration parameters for the PDM control of the DMIC + * (Digital Microphone) module. It includes fields for controlling the CIC (Cascaded + * Integrator-Comb) filter, MIC (Microphone) control, SoundWire mapping, FIR (Finite + * Impulse Response) configurations, and FIR coefficients. + */ +struct dmic_pdm_ctrl_cfg { + /** + * @brief CIC_CONTROL + * Control register for CIC configuration. + */ + uint32_t cic_control; + /** + * @brief CIC_CONFIG + * Configuration register for CIC filter. + */ + uint32_t cic_config; + /** + * @brief Reserved field + */ + uint32_t rsvd_0; + /** + * @brief MIC_CONTROL + * Control register for MIC configuration. + */ + uint32_t mic_control; + /** + * @brief + * This field is used on platforms with SoundWire, otherwise ignored. + */ + uint32_t pdmsm; + /** + * @brief Index of another PDMCtrlCfg to be used as a source of FIR coefficients. + */ + uint32_t reuse_fir_from_pdm; + /** + * @brief Reserved field + */ + uint32_t rsvd_1[2]; + /** + * @brief FIR configurations + */ + struct dmic_fir_cfg fir_config[2]; + /** + * @brief Array of FIR coefficients, channel A goes first, then channel B. + */ + uint32_t fir_coeffs[0]; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration blob for DMIC (Digital Microphone) settings. + * + * This structure contains various configuration settings for DMIC, including time-slot mappings, + * global configuration, PDM channel configuration, and PDM controller configuration. + */ +struct dmic_config_blob { + /** + * @brief Time-slot mappings. + */ + uint32_t ts_group[4]; + + /** + * @brief DMIC global configuration. + */ + union dmic_global_cfg global_cfg; + + /** + * @brief PDM channels to be programmed using data from channel_cfg array. + */ + uint32_t channel_ctrl_mask : 8; + + /** + * @brief Clock source for DMIC. + */ + uint32_t clock_source : 8; + + /** + * @brief Reserved field. + */ + uint32_t rsvd : 16; + + /** + * @brief PDM channel configuration settings. + */ + struct dmic_channel_cfg channel_cfg[0]; + + /** + * @brief PDM controllers to be programmed using data from pdm_ctrl_cfg array. + */ + uint32_t pdm_ctrl_mask; + + /** + * @brief PDM controller configuration settings. + */ + struct dmic_pdm_ctrl_cfg pdm_ctrl_cfg[0]; +} __packed __aligned(4); + +/** + * @brief Structure representing the configuration data for DMIC. + */ +struct dmic_config_data { + /**< Gateway attributes */ + union ipc4_gateway_attributes gtw_attributes; + /**< DMIC Configuration BLOB */ + struct dmic_config_blob dmic_blob; +} __packed __aligned(4); + +#endif /* __SOF_IPC4_DMIC_H__ */ diff --git a/src/include/ipc4/error_status.h b/src/include/ipc4/error_status.h new file mode 100644 index 000000000000..c3ad27bf2a61 --- /dev/null +++ b/src/include/ipc4/error_status.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/error_status.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_ERROR_STATUS_H__ +#define __SOF_IPC4_ERROR_STATUS_H__ + +#define IPC4_IXC_STATUS_BITS 24 + +enum ipc4_status { + /**< The operation was successful */ + IPC4_SUCCESS = 0, + + /**< Invalid parameter specified */ + IPC4_ERROR_INVALID_PARAM = 1, + /**< Unknown message type specified */ + IPC4_UNKNOWN_MESSAGE_TYPE = 2, + /**< Not enough space in the IPC reply buffer to complete the request */ + IPC4_OUT_OF_MEMORY = 3, + + /**< The system or resource is busy */ + IPC4_BUSY = 4, + /**< Replaced ADSP IPC PENDING (unused) - according to cAVS v0.5 */ + IPC4_BAD_STATE = 5, + /**< Unknown error while processing the request */ + IPC4_FAILURE = 6, + /**< Unsupported operation requested */ + IPC4_INVALID_REQUEST = 7, + + /**< Specified resource not found */ + IPC4_INVALID_RESOURCE_ID = 9, + /**< A resource's ID requested to be created is already assigned */ + IPC4_RESOURCE_ID_EXISTS = 10, + + /**< Required resource is in invalid state */ + IPC4_INVALID_RESOURCE_STATE = 12, + + /**< Requested power transition failed to complete */ + IPC4_POWER_TRANSITION_FAILED = 13, + + /**< Manifest of the library being loaded is invalid */ + IPC4_INVALID_MANIFEST = 14, + + /**< Requested service or data is unavailable on the target platform */ + IPC4_UNAVAILABLE = 15, + + /* Load/unload library specific codes */ + + /**< Library target address is out of storage memory range */ + IPC4_LOAD_ADDRESS_OUT_OF_RANGE = 42, + + /**< Image verification by CSE failed */ + IPC4_CSE_VALIDATION_FAILED = 44, + + /**< General module management error */ + IPC4_MOD_MGMT_ERROR = 100, + /**< Module loading failed */ + IPC4_MOD_LOAD_CL_FAILED = 101, + /**< Integrity check of the loaded module content failed */ + IPC4_MOD_LOAD_INVALID_HASH = 102, + + /**< Attempt to unload code of the module in use */ + IPC4_MOD_INSTANCE_EXISTS = 103, + /**< Other failure of module instance initialization request */ + IPC4_MOD_NOT_INITIALIZED = 104, + + /**< Invalid (out of range) module ID provided */ + IPC4_MOD_INVALID_ID = 110, + /**< Invalid module instance ID provided */ + IPC4_MOD_INST_INVALID_ID = 111, + /**< Invalid queue (pin) ID provided */ + IPC4_QUEUE_INVALID_ID = 112, + /**< Invalid destination queue (pin) ID provided */ + IPC4_QUEUE_DST_INVALID_ID = 113, + + /**< Invalid target code ID provided */ + IPC4_INVALID_CORE_ID = 116, + + /**< Injection DMA buffer is too small for probing the input pin */ + IPC4_PROBE_DMA_INJECTION_BUFFER_TOO_SMALL = 117, + /**< Extraction DMA buffer is too small for probing the output pin */ + IPC4_PROBE_DMA_EXTRACTION_BUFFER_TOO_SMALL = 118, + + /**< Invalid ID of configuration item provided in TLV list */ + IPC4_INVALID_CONFIG_PARAM_ID = 120, + /**< Invalid length of configuration item provided in TLV list */ + IPC4_INVALID_CONFIG_DATA_LEN = 121, + /**< Invalid structure of configuration item provided */ + IPC4_INVALID_CONFIG_DATA_STRUCT = 122, + + /**< Initialization of DMA Gateway failed */ + IPC4_GATEWAY_NOT_INITIALIZED = 140, + /**< Invalid ID of gateway provided */ + IPC4_GATEWAY_NOT_EXIST = 141, + /**< Setting state of DMA Gateway failed */ + IPC4_GATEWAY_STATE_NOT_SET = 142, + /**< DMA_CONTROL message targeting gateway not allocated yet */ + IPC4_GATEWAY_NOT_ALLOCATED = 143, + + /**< Attempt to configure SCLK while I2S port is running */ + IPC4_SCLK_ALREADY_RUNNING = 150, + /**< Attempt to configure MCLK while I2S port is running */ + IPC4_MCLK_ALREADY_RUNNING = 151, + /**< Attempt to stop SCLK that is not running */ + IPC4_NO_RUNNING_SCLK = 152, + /**< Attempt to stop MCLK that is not running */ + IPC4_NO_RUNNING_MCLK = 153, + + /**< Reverted for ULP purposes */ + IPC4_PIPELINE_STATE_NOT_SET = 164, + + /**< HDA chained gateways wrong state transition*/ + IPC4_INVALID_CHAIN_STATE_TRANSITION = 3018, + + IPC4_MAX_STATUS = ((1 << IPC4_IXC_STATUS_BITS) - 1) +}; +#endif diff --git a/src/include/ipc4/fw_reg.h b/src/include/ipc4/fw_reg.h new file mode 100644 index 000000000000..a0f450954050 --- /dev/null +++ b/src/include/ipc4/fw_reg.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/fw_reg.h + * \brief IPC4 fw registers in mailbox for host. Fw exposes dsp / fw + * state information to the host via shared memory window 0, .e.g. fw error, + * pipeline state, dma llp counter and others. These information are included + * in ipc4_fw_registers structure defined in this file. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __IPC4_FW_REG_H__ +#define __IPC4_FW_REG_H__ + +#include <stdint.h> +#include <ipc4/error_status.h> +#include <ipc4/module.h> +#include <sof/lib/cpu.h> + +/* Reports current ROM/FW status. */ +struct ipc4_fw_status_reg { + uint32_t state : 28; + /* Last module ID updated FSR */ + uint32_t module : 3; + /* State of DSP core */ + uint32_t running : 1; +} __attribute__((packed, aligned(4))); + +typedef uint32_t ipc4_last_error; + +struct ipc4_fw_pwr_status { + /* currently set astate */ + uint32_t curr_astate : 4; + /* cached IMR usage status for previous D0i3 */ + uint32_t cached_imr_usage_status : 1; + uint32_t curr_fstate : 3; + uint32_t wake_tick_period : 5; + uint32_t active_pipelines_count : 6; + uint32_t rsvd0 : 13; +} __attribute__((packed, aligned(4))); + +struct ipc4_pipeline_registers { + /** + * Stream start offset (LPIB) reported by mixin module allocated on pipeline attached + * to Host Output Gateway when first data is being mixed to mixout module. When data + * is not mixed (right after creation/after reset) value "(uint64_t)-1" is reported. + * In number of bytes. + * */ + uint64_t stream_start_offset; + /** + * Stream end offset (LPIB) reported by mixin module allocated on pipeline attached + * to Host Output Gateway during transition from RUNNING to PAUSED. When data + * is not mixed (right after creation/after reset) value "(uint64_t)-1" is reported. When + * first data is mixed then value "0"is reported. + * In number of bytes. + * */ + uint64_t stream_end_offset; +} __attribute__((packed, aligned(8))); + +#define IPC4_PV_MAX_SUPPORTED_CHANNELS 8 +struct ipc4_peak_volume_regs { + uint32_t peak_meter[IPC4_PV_MAX_SUPPORTED_CHANNELS]; + uint32_t current_volume[IPC4_PV_MAX_SUPPORTED_CHANNELS]; + uint32_t target_volume[IPC4_PV_MAX_SUPPORTED_CHANNELS]; +} __attribute__((packed, aligned(4))); + +struct ipc4_llp_reading { + /* lower part of 64-bit LLP */ + uint32_t llp_l; + /* upper part of 64-bit LLP */ + uint32_t llp_u; + /* lower part of 64-bit Wallclock */ + uint32_t wclk_l; + /* upper part of 64-bit Wallclock */ + uint32_t wclk_u; +} __attribute__((packed, aligned(4))); + +struct ipc4_llp_reading_extended { + struct ipc4_llp_reading llp_reading; + /* total processed data (low part) */ + uint32_t tpd_low; + /* total processed data (high part) */ + uint32_t tpd_high; +} __attribute__((packed, aligned(4))); + +struct ipc4_llp_reading_slot { + uint32_t node_id; + struct ipc4_llp_reading reading; +} __attribute__((packed, aligned(4))); + +union ipc4_rom_info { + struct { + uint32_t fuse_values: 8; + uint32_t load_method: 1; + uint32_t downlink_IPC_use_DMA: 1; + uint32_t load_method_reserved: 2; + uint32_t implementation_revision_min: 4; + uint32_t implementation_revision_maj: 4; + uint32_t implementation_version_min: 4; + uint32_t implementation_version_maj: 4; + uint32_t reserved : 4; + } bits; + struct { + uint32_t rsvd1: 16; + uint32_t type: 12; + uint32_t rsvd2: 4; + } platform; +} __attribute__((packed, aligned(4))); + +/* Number of dsp core supported in FW Regs. */ +#define IPC4_MAX_SUPPORTED_ADSP_CORES 8 + +/* Number of pipeline registers slots in FW Regs. */ +#define IPC4_MAX_PIPELINE_REG_SLOTS 16 + +/* Number of PeakVol registers slots in FW Regs. */ +#define IPC4_MAX_PEAK_VOL_REG_SLOTS 16 + +/* Number of GPDMA LLP Reading slots in FW Regs. */ +#define IPC4_MAX_LLP_GPDMA_READING_SLOTS 24 + +/* Number of Aggregated SNDW Reading slots in FW Regs. */ +#define IPC4_MAX_LLP_SNDW_READING_SLOTS 16 + +/* Current ABI version of the FwRegisters layout. */ +#define IPC4_FW_REGS_ABI_VER 1 + +/* FW Registers exposes additional DSP / FW state information to the driver. */ +struct ipc4_fw_registers { + /* Current ROM / FW status(at 0x0) */ + struct ipc4_fw_status_reg fsr; + + /* Last ROM / FW error code(at 0x4). */ + ipc4_last_error lec; + + /* Current DSP clock status(at 0x8). */ + struct ipc4_fw_pwr_status fps; + + /* Last Native Error Code(from external library) (at 0xC). */ + uint32_t lnec; + + /* Copy of LTRC HW register value(FW only) (at 0x10). */ + uint32_t ltr; + + uint32_t rsvd0; + + /* ROM info(at 0x18). */ + union ipc4_rom_info rom_info; + + /* Version of the layout, set to the current FW_REGS_ABI_VER (at 0x1C). */ + uint32_t abi_ver; + + uint8_t slave_core_sts[IPC4_MAX_SUPPORTED_ADSP_CORES]; + + uint32_t rsvd2[6]; + + /* State of pipelines attached to host output gateways. */ + struct ipc4_pipeline_registers pipeline_regs[IPC4_MAX_PIPELINE_REG_SLOTS]; + + /* State of PeakVol instances, indexed by the PeakVol's instance_id. */ + struct ipc4_peak_volume_regs peak_vol_regs[IPC4_MAX_PEAK_VOL_REG_SLOTS]; + + /* LLP Readings for single link gateways. */ + struct ipc4_llp_reading_slot llp_gpdma_reading_slots[IPC4_MAX_LLP_GPDMA_READING_SLOTS]; + + /* LLP Readings for SNDW aggregated link gateways. */ + struct ipc4_llp_reading_slot llp_sndw_reading_slots[IPC4_MAX_LLP_SNDW_READING_SLOTS - 1]; + + /* LLP Readings for EVAD gateway. */ + struct ipc4_llp_reading_slot llp_evad_reading_slot; +} __attribute__((packed, aligned(4))); + +#endif diff --git a/src/include/ipc4/gateway.h b/src/include/ipc4/gateway.h new file mode 100644 index 000000000000..9398bb44be0e --- /dev/null +++ b/src/include/ipc4/gateway.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/header.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_GATEWAY_H__ +#define __SOF_IPC4_GATEWAY_H__ + +#include <stdint.h> +#include <rtos/bit.h> + +/**< Type of the gateway. */ +enum ipc4_connector_node_id_type { + /**< HD/A host output (-> DSP). */ + ipc4_hda_host_output_class = 0, + /**< HD/A host input (<- DSP). */ + ipc4_hda_host_input_class = 1, + /**< HD/A host input/output (rsvd for future use). */ + ipc4_hda_host_inout_class = 2, + + /**< HD/A link output (DSP ->). */ + ipc4_hda_link_output_class = 8, + /**< HD/A link input (DSP <-). */ + ipc4_hda_link_input_class = 9, + /**< HD/A link input/output (rsvd for future use). */ + ipc4_hda_link_inout_class = 10, + + /**< DMIC link input (DSP <-). */ + ipc4_dmic_link_input_class = 11, + + /**< I2S link output (DSP ->). */ + ipc4_i2s_link_output_class = 12, + /**< I2S link input (DSP <-). */ + ipc4_i2s_link_input_class = 13, + + /**< ALH link output, legacy for SNDW (DSP ->). */ + ipc4_alh_link_output_class = 16, + /**< ALH link input, legacy for SNDW (DSP <-). */ + ipc4_alh_link_input_class = 17, + + /**< SNDW link output (DSP ->). */ + ipc4_alh_snd_wire_stream_link_output_class = 16, + /**< SNDW link input (DSP <-). */ + ipc4_alh_snd_wire_stream_link_input_class = 17, + + /**< UAOL link output (DSP ->). */ + ipc4_alh_uaol_stream_link_output_class = 18, + /**< UAOL link input (DSP <-). */ + ipc4_alh_uaol_stream_link_input_class = 19, + + /**< IPC output (DSP ->). */ + ipc4_ipc_output_class = 20, + /**< IPC input (DSP <-). */ + ipc4_ipc_input_class = 21, + + /**< I2S Multi gtw output (DSP ->). */ + ipc4_i2s_multi_link_output_class = 22, + /**< I2S Multi gtw input (DSP <-). */ + ipc4_i2s_multi_link_input_class = 23, + /**< GPIO */ + ipc4_gpio_class = 24, + /**< SPI */ + ipc4_spi_output_class = 25, + ipc4_spi_input_class = 26, + ipc4_max_connector_node_id_type +}; + +/**< Invalid raw node id (to indicate uninitialized node id). */ +#define IPC4_INVALID_NODE_ID 0xffffffff + +/**< all bits of v_index and dma_type */ +#define IPC4_NODE_ID_MASK 0x1fff + +/**< Base top-level structure of an address of a gateway. */ +/*! + * The virtual index value, presented on the top level as raw 8 bits, + * is expected to be encoded in a gateway specific way depending on + * the actual type of gateway. + */ +union ipc4_connector_node_id { + + /**< Raw 32-bit value of node id. */ + uint32_t dw; + + /**< Bit fields */ + struct { + /**< Index of the virtual DMA at the gateway. */ + uint32_t v_index : 8; + + /**< Type of the gateway, one of ConnectorNodeId::Type values. */ + uint32_t dma_type : 5; + + /**< Rsvd field. */ + uint32_t _rsvd : 19; + } f; /**<< Bits */ +} __attribute__((packed, aligned(4))); + +#define IPC4_HW_HOST_OUTPUT_NODE_ID_BASE 0x00 +#define IPC4_HW_CODE_LOADER_NODE_ID 0x0F +#define IPC4_HW_LINK_INPUT_NODE_ID_BASE 0x10 + +/*! + * Attributes are usually provided along with the gateway configuration + * BLOB when the FW is requested to instantiate that gateway. + * + * There are flags which requests FW to allocate gateway related data + * (buffers and other items used while transferring data, like linked list) + * to be allocated from a special memory area, e.g low power memory. + */ +union ipc4_gateway_attributes { + + /**< Raw value */ + uint32_t dw; + + /**< Access to the fields */ + struct { + /**< Gateway data requested in low power memory. */ + uint32_t lp_buffer_alloc : 1; + + /**< Gateway data requested in register file memory. */ + uint32_t alloc_from_reg_file : 1; + + /**< Reserved field */ + uint32_t _rsvd : 30; + } bits; /**<< Bits */ +} __attribute__((packed, aligned(4))); + +/**< Gateway configuration BLOB structure. */ +/*! + * Actual config_blob content depends on the specific target gateway type. + */ +struct ipc4_gateway_config_data { + /**< Gateway attributes */ + union ipc4_gateway_attributes gtw_attributes; + + /**< Configuration BLOB */ + uint32_t config_blob[]; +} __attribute__((packed, aligned(4))); + +/**< Configuration for the IPC Gateway */ +struct ipc4_ipc_gateway_config_blob { + + /**< Size of the gateway buffer, specified in bytes */ + uint32_t buffer_size; + + /**< Flags */ + union { + struct { + /**< Activates high threshold notification */ + /*! + * Indicates whether notification should be sent to the host + * when the size of data in the buffer reaches the high threshold + * specified by threshold_high parameter. + */ + uint32_t notif_high : 1; + + /**< Activates low threshold notification */ + /*! + * Indicates whether notification should be sent to the host + * when the size of data in the buffer reaches the low threshold + * specified by threshold_low parameter. + */ + uint32_t notif_low : 1; + + /**< Reserved field */ + uint32_t rsvd : 30; + } f; /**<< Bits */ + /**< Raw value of flags */ + uint32_t flags_raw; + } u; /**<< Flags */ + + /**< High threshold */ + /*! + * Specifies the high threshold (in bytes) for notifying the host + * about the buffered data level. + */ + uint32_t threshold_high; + + /**< Low threshold */ + /*! + * Specifies the low threshold (in bytes) for notifying the host + * about the buffered data level. + */ + uint32_t threshold_low; +} __attribute__((packed, aligned(4))); + +enum ipc4_gateway_type { + ipc4_gtw_none = BIT(0), + ipc4_gtw_host = BIT(1), + ipc4_gtw_dmic = BIT(2), + ipc4_gtw_link = BIT(3), + ipc4_gtw_alh = BIT(4), + ipc4_gtw_ssp = BIT(5), + ipc4_gtw_all = BIT(6) - 1 +}; + +enum ipc4_direction_type { + ipc4_playback = BIT(0), + ipc4_capture = BIT(1), + ipc4_bidirection = BIT(0) | BIT(1) +}; + +#define IPC4_DIRECTION(x) BIT(x) +#endif diff --git a/src/include/ipc4/handler.h b/src/include/ipc4/handler.h new file mode 100644 index 000000000000..b25cb98e9427 --- /dev/null +++ b/src/include/ipc4/handler.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __SOF_IPC4_HANDLER_H__ +#define __SOF_IPC4_HANDLER_H__ + +struct ipc4_message_request; + +/** + * \brief Processes IPC4 userspace module message. + * @param[in] ipc4 IPC4 message request. + * @param[in] reply IPC message reply structure. + * @return IPC4_SUCCESS on success, error code otherwise. + */ +int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, struct ipc_msg *reply); + +/** + * \brief Processes IPC4 userspace global message. + * @param[in] ipc4 IPC4 message request. + * @param[in] reply IPC message reply structure. + * @return IPC4_SUCCESS on success, error code otherwise. + */ +int ipc4_user_process_glb_message(struct ipc4_message_request *ipc4, struct ipc_msg *reply); + +/** + * \brief Increment the IPC compound message pre-start counter. + * @param[in] msg_id IPC message ID. + */ +void ipc_compound_pre_start(int msg_id); + +/** + * \brief Decrement the IPC compound message pre-start counter on return value status. + * @param[in] msg_id IPC message ID. + * @param[in] ret Return value of the IPC command. + * @param[in] delayed True if the reply is delayed. + */ +void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed); + +/** + * \brief Complete the IPC compound message. + * @param[in] msg_id IPC message ID. + * @param[in] error Error code of the IPC command. + */ +void ipc_compound_msg_done(uint32_t msg_id, int error); + +/** + * \brief Wait for the IPC compound message to complete. + * @return 0 on success, error code otherwise on timeout. + */ +int ipc_wait_for_compound_msg(void); + +#endif /* __SOF_IPC4_HANDLER_H__ */ diff --git a/src/include/ipc4/header.h b/src/include/ipc4/header.h new file mode 100644 index 000000000000..6a6eb59d02e5 --- /dev/null +++ b/src/include/ipc4/header.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/header.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_HEADER_H__ +#define __SOF_IPC4_HEADER_H__ + +#include <stdint.h> + +#define ipc_from_hdr(x) ((struct ipc4_message_request *)x) + +/**< Message target, value of msg_tgt field. */ +enum ipc4_message_target { + /**< Global FW message */ + SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG = 0, + /**< Module message */ + SOF_IPC4_MESSAGE_TARGET_MODULE_MSG = 1 +}; + +/**< Message direction, value of rsp field. */ +enum ipc4_message_direction { + /**< Request, Notification */ + SOF_IPC4_MESSAGE_DIR_MSG_REQUEST = 0, + /**< Reply */ + SOF_IPC4_MESSAGE_DIR_MSG_REPLY = 1, +}; + +/* + * Global IPC4 message types - must fit into 5 bits. + */ +enum ipc4_message_type { + /**< Boot Config. */ + SOF_IPC4_GLB_BOOT_CONFIG = 0, + /**< ROM Control (directed to ROM). */ + SOF_IPC4_GLB_ROM_CONTROL = 1, + /**< Execute IPC gateway command */ + SOF_IPC4_GLB_IPCGATEWAY_CMD = 2, + + /* GAP HERE- DO NOT USE - size 10 (3 .. 12) */ + + /**< Execute performance measurements command. */ + SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD = 13, + /**< DMA Chain command. */ + SOF_IPC4_GLB_CHAIN_DMA = 14, + /**< Load multiple modules */ + SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES = 15, + /**< Unload multiple modules */ + SOF_IPC4_GLB_UNLOAD_MULTIPLE_MODULES = 16, + /**< Create pipeline */ + SOF_IPC4_GLB_CREATE_PIPELINE = 17, + /**< Delete pipeline */ + SOF_IPC4_GLB_DELETE_PIPELINE = 18, + /**< Set pipeline state */ + SOF_IPC4_GLB_SET_PIPELINE_STATE = 19, + /**< Get pipeline state */ + SOF_IPC4_GLB_GET_PIPELINE_STATE = 20, + /**< Get pipeline context size */ + SOF_IPC4_GLB_GET_PIPELINE_CONTEXT_SIZE = 21, + /**< Save pipeline */ + SOF_IPC4_GLB_SAVE_PIPELINE = 22, + /**< Restore pipeline */ + SOF_IPC4_GLB_RESTORE_PIPELINE = 23, + /**< Loads library */ + SOF_IPC4_GLB_LOAD_LIBRARY = 24, + /**< Loads library prepare */ + SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE = 25, + /**< Internal FW message */ + SOF_IPC4_GLB_INTERNAL_MESSAGE = 26, + /**< Notification (FW to SW driver) */ + SOF_IPC4_GLB_NOTIFICATION = 27, + /* GAP HERE- DO NOT USE - size 3 (28 .. 30) */ + /**< Enter GDB stub to wait for commands in memory window */ + SOF_IPC4_GLB_ENTER_GDB = 31, + + /**< Maximum message number */ + SOF_IPC4_GLB_MAX_IXC_MESSAGE_TYPE = 32 +}; + +/** + * \brief Generic message header. IPC MAJOR 4 version. + * All IPC4 messages use this header as abstraction + * to platform specific calls. + */ +struct ipc_cmd_hdr { + uint32_t pri; + uint32_t ext; +}; + +/** + * \brief IPC MAJOR 4 message header. All IPC4 messages use this header. + * When msg_tgt is SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG then type is + * enum ipc4_message_type. + */ +struct ipc4_message_request { + union { + uint32_t dat; + + struct { + uint32_t rsvd0 : 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 ext_data : 30; + uint32_t _reserved_0 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_message_reply { + union { + uint32_t dat; + + struct { + /**< Processing status, one of IxcStatus values */ + uint32_t status : 24; + + /**< Type, symmetric to Msg */ + uint32_t type : 5; + + /**< MSG_REPLY */ + uint32_t rsp : 1; + + /**< same as request, one of FW_GEN_MSG, MODULE_MSG */ + uint32_t msg_tgt : 1; + + /**< Reserved field (HW ctrl bits) */ + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /**< Reserved field */ + uint32_t rsvd1 : 30; + + /**< Reserved field (HW ctrl bits) */ + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute((packed, aligned(4))); + +#define SOF_IPC4_SWITCH_CONTROL_PARAM_ID 200 +#define SOF_IPC4_ENUM_CONTROL_PARAM_ID 201 +#define SOF_IPC4_BYTES_CONTROL_PARAM_ID 202 +#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL ((uint32_t)(0xA15A << 16)) +#define SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL ((uint32_t)(0xC0C0 << 16)) + +/** + * struct sof_ipc4_ctrl_value_chan: generic channel mapped value data + * @channel: Channel ID + * @value: control value + */ +struct sof_ipc4_ctrl_value_chan { + uint32_t channel; + uint32_t value; +} __attribute((packed, aligned(4))); + +/** + * struct sof_ipc4_control_msg_payload - IPC payload for kcontrol parameters + * @id: unique id of the control + * @num_elems: Number of elements in the chanv array or number of bytes in data + * @reserved: reserved for future use, must be set to 0 + * @chanv: channel ID and value array + * @data: binary payload + */ +struct sof_ipc4_control_msg_payload { + uint16_t id; + uint16_t num_elems; + uint32_t reserved[4]; + union { + struct sof_ipc4_ctrl_value_chan chanv[0]; + uint8_t data[0]; + }; +} __attribute((packed, aligned(4))); + +/** + * struct sof_ipc4_notify_module_data - payload for module notification + * @instance_id: instance ID of the originator module of the notification + * @module_id: module ID of the originator of the notification + * @event_id: module specific event id + * @event_data_size: Size of the @event_data (if any) in bytes + * @event_data: Optional notification data, module and notification dependent + */ +struct sof_ipc4_notify_module_data { + uint16_t instance_id; + uint16_t module_id; + uint32_t event_id; + uint32_t event_data_size; + uint8_t event_data[]; +} __attribute((packed, aligned(4))); + +#endif diff --git a/src/include/ipc4/kpb.h b/src/include/ipc4/kpb.h new file mode 100644 index 000000000000..0c56942313c3 --- /dev/null +++ b/src/include/ipc4/kpb.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Ievgen Ganakov <ievgen.ganakov@intel.com> + */ + +/** + * \file include/ipc4/kpb.h + * \brief KPB module definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_KPB_H__ +#define __SOF_IPC4_KPB_H__ + +#include "base-config.h" + +struct ipc4_kpb_module_cfg { + struct ipc4_base_module_cfg base_cfg; +} __packed __aligned(4); + +/* For the sake of compatibility, do not change IDs, only add new ones.*/ +enum ipc4_kpb_module_config_params { + /*! Configure the module ID's which would be part of the Fast mode tasks */ + KP_BUF_CFG_FM_MODULE = 1, + /* Mic selector for client - sets microphone id for real time sink mic selector + * IPC4-compatible ID - please do not change the number + */ + KP_BUF_CLIENT_MIC_SELECT = 11, +}; + +#endif + diff --git a/src/include/ipc4/logging.h b/src/include/ipc4/logging.h new file mode 100644 index 000000000000..55f4a5edbffc --- /dev/null +++ b/src/include/ipc4/logging.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_IPC4_LOGGING_H__ +#define __SOF_IPC4_LOGGING_H__ + +#define SOF_IPC4_LOGGING_MTRACE_PAGE_SIZE 0x1000 + +int ipc4_logging_enable_logs(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data); + +int ipc4_logging_shutdown(void); + +#endif diff --git a/src/include/ipc4/module.h b/src/include/ipc4/module.h new file mode 100644 index 000000000000..dfe0f02e628e --- /dev/null +++ b/src/include/ipc4/module.h @@ -0,0 +1,538 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/module.h + * \brief IPC4 module definitions + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __IPC4_MODULE_H__ +#define __IPC4_MODULE_H__ + +#include <ipc4/error_status.h> + +#include <stdint.h> + +/* TODO: revisit it. Now it aligns with audio sdk + * and we will update this value and sdk when more + * libraries are supported + */ +#define IPC4_MAX_SUPPORTED_LIBRARIES 16 + +#define IPC4_MAX_MODULE_COUNT 128 + +#define SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE 3 +#define SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE 3 + +/* Special large_param_id values */ +#define VENDOR_CONFIG_PARAM 0xFF + +enum sof_ipc4_module_type { + SOF_IPC4_MOD_INIT_INSTANCE = 0, + SOF_IPC4_MOD_CONFIG_GET = 1, + SOF_IPC4_MOD_CONFIG_SET = 2, + SOF_IPC4_MOD_LARGE_CONFIG_GET = 3, + SOF_IPC4_MOD_LARGE_CONFIG_SET = 4, + SOF_IPC4_MOD_BIND = 5, + SOF_IPC4_MOD_UNBIND = 6, + SOF_IPC4_MOD_SET_DX = 7, + SOF_IPC4_MOD_SET_D0IX = 8, + SOF_IPC4_MOD_ENTER_MODULE_RESTORE = 9, + SOF_IPC4_MOD_EXIT_MODULE_RESTORE = 10, + SOF_IPC4_MOD_DELETE_INSTANCE = 11, +}; + +/* + * Structs for Vendor Config + */ + +union ipc4_extended_param_id { + uint32_t full; + struct{ + uint32_t parameter_type : 8; + uint32_t parameter_instance : 24; + } part; +} __attribute__((packed, aligned(4))); + +struct ipc4_vendor_error { + /* Index of the failed parameter */ + uint32_t param_idx; + /* Error code */ + uint32_t err_code; +}; + +/* IDs for all global object types in struct ipc4_module_init_ext_object */ +enum ipc4_mod_init_data_glb_id { + IPC4_MOD_INIT_DATA_ID_INVALID = 0, + IPC4_MOD_INIT_DATA_ID_DP_DATA = 1, + IPC4_MOD_INIT_DATA_ID_MODULE_DATA = 2, + IPC4_MOD_INIT_DATA_ID_MAX = IPC4_MOD_INIT_DATA_ID_MODULE_DATA, +}; + +/* data object for vendor bespoke data with ABI growth and backwards compat */ +struct ipc4_module_init_ext_object { + uint32_t last_object : 1; /* object is last in array if 1 else object follows. */ + uint32_t object_id : 15; /* unique ID for this object or globally */ + uint32_t object_words : 16; /* size in dwords (excluding this structure) */ +} __attribute__((packed, aligned(4))); +/* the object data will be placed in memory here and will have size "object_words" */ + +/* Ext init array data object for Data Processing module memory requirements */ +struct ipc4_module_init_ext_obj_dp_data { + uint32_t domain_id; /* userspace domain ID */ + uint32_t stack_bytes; /* required stack size in bytes */ + uint32_t interim_heap_bytes; /* required interim heap size in bytes */ + uint32_t lifetime_heap_bytes; /* required lifetime heap size in bytes */ + uint32_t shared_bytes; /* required shared memory size in bytes */ +} __attribute__((packed, aligned(4))); + +/* + * Host Driver sends this message to create a new module instance. + */ +struct ipc4_module_init_ext_init { + /**< if it is set to 1, proc_domain should be ignored and processing */ + /* domain is RTOS scheduling */ + uint32_t rtos_domain : 1; + /**< Indicates that GNA is used by a module and additional information */ + /* (gna_config) is passed after ExtendedData. */ + uint32_t gna_used : 1; + uint32_t data_obj_array : 1; /* struct ipc4_module_init_ext_object data */ + uint32_t rsvd_0 : 29; + uint32_t rsvd_1[2]; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_init_ext_data { + struct ipc4_module_init_ext_init extended_init; + + /**< Data (actual size set to param_block_size) */ + uint32_t param_data[]; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_init_gna_config { + /**< Number of GNA cycles required to process one input frame. */ + /* This information is used by DP scheduler to correctly schedule + * a DP module. + */ + uint32_t gna_cpc; + uint32_t rsvd; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_init_data { + /**< Data (actual size set to param_block_size) */ + uint32_t param_data[0]; +} __attribute__((packed, aligned(4))); + +/*! + Created instance is a child element of pipeline identified by the ppl_id + specified by the driver. + + The module_id should be set to an index of the module entry in the FW Image + Manifest. + + The instance_id assigned by the driver should be in the + 0..ModuleEntry.max_instance_count range defined in the FW Image Manifest. + + Initial configuration of the module instance is provided by the driver in + the param_data array. Size of the array is specified in param_block_size + field of the message header. + + Refer to Module Configuration section of FW I/F Specification for details on + module specific initial configuration parameters. + + \remark hide_methods +*/ +struct ipc4_module_init_instance { + + union { + uint32_t dat; + + struct { + /**< module id */ + uint32_t module_id : 16; + /**< instance id */ + uint32_t instance_id : 8; + /**< ModuleMsg::INIT_INSTANCE */ + uint32_t type : 5; + /**< Msg::MSG_REQUEST */ + uint32_t rsp : 1; + /**< Msg::MODULE_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /**< Size of Data::param_data[] (in dwords) */ + uint32_t param_block_size : 16; + /**< ID of module instance's parent pipeline */ + uint32_t ppl_instance_id : 8; + /**< ID of core that instance will run on */ + uint32_t core_id : 4; + /**< Processing domain, 0-LL, 1-DP */ + uint32_t proc_domain : 1; + /* reserved in cAVS */ + uint32_t extended_init : 1; + uint32_t _hw_reserved_2 : 2; + } r; + } extension; +/* + * The following objects are optional and follow this structure in this + * order provided the respective object bit is set in preceding object. + * + * struct ipc4_module_init_ext_init ext_init; + * struct ipc4_module_init_ext_data ext_data; + * struct ipc4_module_init_gna_config gna_config; + * struct ipc4_module_init_data init_data; + */ +} __attribute__((packed, aligned(4))); + +/*! + SW Driver sends Bind IPC message to connect two module instances together + creating data processing path between them. + + Unbind IPC message is sent to destroy a connection between two module instances + (belonging to different pipelines) previously created with Bind call. + + NOTE: when both module instances are parts of the same pipeline Unbind IPC would + be ignored by FW since FW does not support changing internal topology of pipeline + during run-time. The only way to change pipeline topology is to delete the whole + pipeline and create it in modified form. + + \remark hide_methods + */ +struct ipc4_module_bind_unbind { + union { + uint32_t dat; + + struct { + /**< module id */ + uint32_t module_id : 16; + /**< instance id */ + uint32_t instance_id : 8; + /**< ModuleMsg::BIND / UNBIND. */ + uint32_t type : 5; + /**< Msg::MSG_REQUEST */ + uint32_t rsp : 1; + /**< Msg::MODULE_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /**< destination module id */ + uint32_t dst_module_id : 16; + /**< destination instance id */ + uint32_t dst_instance_id : 8; + /**< destination queue (pin) id */ + uint32_t dst_queue : SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE; + /**< source queue (pin) id */ + uint32_t src_queue : SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/* + * Using Module Config Get / Set command, host driver may send a parameter + * that fits into the header (a very short one), packed along with parameter id. + * Larger parameters require fragmentation and a series of Large Config Set + * commands. + * + * param_id_data specifies both ID of the parameter, defined by the module + * and value of the parameter. + * It is up to the module how to distribute bits to ID and value of the parameter. + * If there are more bits required than available to value, then Input Data may + * be used to pass the value + * + * NOTE: Module Config Get/Set commands are used internally by the driver + * for small parameters defined by Intel components. While all externally + * developed components communicates with host using Large Config commands + * no matter what the size of parameter is. + */ +struct ipc4_module_config { + union { + uint32_t dat; + + struct { + uint32_t module_id : 16; /* module id */ + uint32_t instance_id : 8; /* instance id */ + /* SOF_IPC4_MOD_CONFIG_GET / SOF_IPC4_MOD_CONFIG_SET */ + uint32_t type : 5; + uint32_t rsp : 1; /* SOF_IPC4_MESSAGE_DIR_MSG_REQUEST */ + uint32_t msg_tgt : 1; /* SOF_IPC4_MESSAGE_TARGET_MODULE_MSG */ + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /* Param id and data */ + uint32_t param_id_data : 30; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/* + * Sent by FW in response to Module Config Get. + */ +struct ipc4_module_config_reply { + union { + uint32_t dat; + + struct { + uint32_t status : IPC4_IXC_STATUS_BITS; + uint32_t type : 5; /* SOF_IPC4_MOD_CONFIG_GET */ + uint32_t rsp : 1; /* SOF_IPC4_MESSAGE_DIR_MSG_REPLY */ + uint32_t msg_tgt : 1; /* SOF_IPC4_MESSAGE_TARGET_MODULE_MSG */ + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /* + * Value of this field may be changed by the module + * if parameter value fits into the available bits, + * or stay intact if the value is copied to the Output Data. + */ + uint32_t param_id_data : 30; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_large_config { + union { + uint32_t dat; + + struct { + /**< module id */ + uint32_t module_id : 16; + /**< instance id */ + uint32_t instance_id : 8; + /**< ModuleMsg::LARGE_CONFIG_GET / LARGE_CONFIG_SET */ + uint32_t type : 5; + /**< Msg::MSG_REQUEST or Msg::MSG_REPLY */ + uint32_t rsp : 1; + /**< Msg::MODULE_MSG or Msg::FW_GEN_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /**< data size for single block, offset for multiple block case */ + uint32_t data_off_size : 20; + /**< param type : VENDOR_CONFIG_PARAM / GENERIC_CONFIG_PARAM */ + uint32_t large_param_id : 8; + /**< 1 if final block */ + uint32_t final_block : 1; + /**< 1 if init block */ + uint32_t init_block : 1; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_large_config_reply { + union { + uint32_t dat; + + struct { + uint32_t status :IPC4_IXC_STATUS_BITS; + /**< ModuleMsg::LARGE_CONFIG_GET / LARGE_CONFIG_SET */ + uint32_t type : 5; + /**< Msg::MSG_REQUEST */ + uint32_t rsp : 1; + /**< Msg::MODULE_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /**< data size/offset */ + uint32_t data_off_size : 20; + /**< param type : VENDOR_CONFIG_PARAM / GENERIC_CONFIG_PARAM */ + uint32_t large_param_id : 8; + /**< 1 if final block */ + uint32_t final_block : 1; + /**< 1 if first block */ + uint32_t init_block : 1; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_delete_instance { + union { + uint32_t dat; + + struct { + uint32_t module_id : 16; + uint32_t instance_id : 8; + /**< ModuleMsg::DELETE_INSTANCE */ + uint32_t type : 5; + /**< Msg::MSG_REQUEST */ + uint32_t rsp : 1; + /**< Msg::MODULE_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + uint32_t rsvd : 30; + uint32_t _reserved_1 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_set_d0ix { + union { + uint32_t dat; + + struct { + /* module id (must be 0 - Base FW) */ + uint32_t module_id : 16; + /* instance id (must be 0 - core 0) */ + uint32_t instance_id : 8; + /* ModuleMsg::SET_D0IX */ + uint32_t type : 5; + /* Msg::MSG_REQUEST */ + uint32_t rsp : 1; + /* Msg::MODULE_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + /* legacy wake type (see WakeType) */ + uint32_t wake : 1; + /* streaming active now */ + uint32_t streaming : 1; + /* D0/D0ix transitions allowed (PG disabled) */ + uint32_t prevent_power_gating : 1; + /* Clock gating enabled */ + uint32_t prevent_local_clock_gating : 1; + + uint32_t rsvd1 : 26; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_dx_state_info { + /* Indicates which cores are subject to change the power state */ + uint32_t core_mask; + /* Indicates core state. + * bit[core_id] = 0 -> put core_id to D3 + * bit[core_id] = 1 -> put core_id to D0 + */ + uint32_t dx_mask; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_set_dx { + union { + uint32_t dat; + + struct { + /* module id (must be 0 - Base FW) */ + uint32_t module_id : 16; + /* instance id (must be 0 - core 0) */ + uint32_t instance_id : 8; + /* ModuleMsg::SET_DX */ + uint32_t type : 5; + /* Msg::MSG_REQUEST */ + uint32_t rsp : 1; + /* Msg::MODULE_MSG */ + uint32_t msg_tgt : 1; + uint32_t _reserved_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + uint32_t rsvd : 30; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_module_load_library { + union { + uint32_t dat; + + struct { + /* ID of HD/A HO DMA to load the code */ + uint32_t dma_id : 5; + uint32_t rsvd0 : 11; + /* ID of library */ + uint32_t lib_id : 4; + uint32_t rsvd1 : 4; + /* Global::LOAD_LIBRARY */ + 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; + } header; + + union { + uint32_t dat; + + struct { + uint32_t load_offset : 30; + uint32_t _reserved_2 : 2; + } r; + } data; +} __attribute__((packed, aligned(4))); + +#define IPC4_COMP_ID(x, y) ((y) << 16 | (x)) +#define IPC4_MOD_ID(x) (IS_ENABLED(CONFIG_IPC_MAJOR_4) ? ((x) & 0xffff) : 0) +#define IPC4_INST_ID(x) ((x) >> 16) +#define IPC4_SRC_QUEUE_ID(x) ((x) & 0xffff) +#define IPC4_SINK_QUEUE_ID(x) (((x) >> 16) & 0xffff) + +#endif diff --git a/src/include/ipc4/notification.h b/src/include/ipc4/notification.h new file mode 100644 index 000000000000..614a926d16ad --- /dev/null +++ b/src/include/ipc4/notification.h @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/notification.h + * \brief IPC4 notification definitions + */ + +#ifndef __IPC4_NOTIFICATION_H__ +#define __IPC4_NOTIFICATION_H__ + +#include <stdint.h> +#include <ipc/header.h> +#include <sof/ipc/msg.h> +#include <sof/compiler_attributes.h> + +/* ipc4 notification msg */ +enum sof_ipc4_notification_type { + SOF_IPC4_NOTIFY_PHRASE_DETECTED = 4, + SOF_IPC4_NOTIFY_RESOURCE_EVENT = 5, + SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS = 6, + SOF_IPC4_NOTIFY_TIMESTAMP_CAPTURED = 7, + SOF_IPC4_NOTIFY_FW_READY = 8, + SOF_IPC4_FW_AUD_CLASS_RESULT = 9, + SOF_IPC4_EXCEPTION_CAUGHT = 10, + SOF_IPC4_MODULE_NOTIFICATION = 12, + SOF_IPC4_UAOL_EVENT = 13, + SOF_IPC4_PROBE_DATA_AVAILABLE = 14, + SOF_IPC4_WATCHDOG_TIMEOUT = 15, + SOF_IPC4_MANAGEMENT_SERVICE = 16, +}; + +/** + * \brief Resource Event Notification provides unified structure for events that may be raised by + * identifiable entity from inside the FW. + */ +enum sof_ipc4_resource_event_type { + /* MCPS budget for the module exceeded */ + SOF_IPC4_BUDGET_VIOLATION = 0, + /* Underrun detected by the Mixer */ + SOF_IPC4_MIXER_UNDERRUN_DETECTED = 1, + /* Stream data segment completed by the gateway */ + SOF_IPC4_STREAM_DATA_SEGMENT = 2, + /* Error caught during data processing */ + SOF_IPC4_PROCESS_DATA_ERROR = 3, + /* Stack overflow in a module instance */ + SOF_IPC4_STACK_OVERFLOW = 4, + /* KPB changed buffering mode */ + SOF_IPC4_BUFFERING_MODE_CHANGED = 5, + /* Underrun detected by gateway. */ + SOF_IPC4_GATEWAY_UNDERRUN_DETECTED = 6, + /* Overrun detected by gateway */ + SOF_IPC4_GATEWAY_OVERRUN_DETECTED = 7, + /* DP task missing the deadline */ + SOF_IPC4_EDF_DOMAIN_UNSTABLE = 8, + /* Watchdog notification */ + SOF_IPC4_WATCHDOG_EVENT = 9, + /* IPC gateway reached high threshold */ + SOF_IPC4_GATEWAY_HIGH_THRES = 10, + /* IPC gateway reached low threshold */ + SOF_IPC4_GATEWAY_LOW_THRES = 11, + /* Bit Count Error detected on I2S port */ + SOF_IPC4_I2S_BCE_DETECTED = 12, + /* Clock detected/loss on I2S port */ + SOF_IPC4_I2S_CLK_STATE_CHANGED = 13, + /* I2S Sink started/stopped dropping data in non-blk mode */ + SOF_IPC4_I2S_SINK_MODE_CHANGED = 14, + /* I2S Source started/stopped generating 0's in non-blk mode */ + SOF_IPC4_I2S_SOURCE_MODE_CHANGED = 15, + /* Frequency drift exceeded limit in SRE */ + SOF_IPC4_SRE_DRIFT_TOO_HIGH = 16, + /* The notification should be sent only once after exceeding threshold or aging timer. */ + SOF_IPC4_TELEMETRY_DATA_STATUS = 17, + /* SNDW debug notification e.g. external VAD detected */ + SOF_IPC4_SNDW_DEBUG_INFO = 18, + /* Invalid type */ + SOF_IPC4_INVALID_RESOURCE_EVENT_TYPE = 19, +}; + +/* Resource Type - source of the event */ +enum sof_ipc4_resource_type { + /* Module instance */ + SOF_IPC4_MODULE_INSTANCE = 0, + /* Pipeline */ + SOF_IPC4_PIPELINE = 1, + /* Gateway */ + SOF_IPC4_GATEWAY = 2, + /* EDF Task*/ + SOF_IPC4_EDF_TASK = 3, + /* Invalid type */ + SOF_IPC4_INVALID_RESOURCE_TYPE = 4, +}; + +#define SOF_IPC4_GLB_NOTIFY_DIR_MASK BIT(29) +#define SOF_IPC4_REPLY_STATUS_MASK 0xFFFFFF +#define SOF_IPC4_GLB_NOTIFY_TYPE_SHIFT 16 +#define SOF_IPC4_GLB_NOTIFY_MSG_TYPE_SHIFT 24 + +#define SOF_IPC4_FW_READY \ + (((SOF_IPC4_NOTIFY_FW_READY) << (SOF_IPC4_GLB_NOTIFY_TYPE_SHIFT)) |\ + ((SOF_IPC4_GLB_NOTIFICATION) << (SOF_IPC4_GLB_NOTIFY_MSG_TYPE_SHIFT))) + +#define SOF_IPC4_FW_READY_LIB_RESTORED BIT(15) + +#define SOF_IPC4_NOTIF_HEADER(notif_type) \ + ((notif_type) << (SOF_IPC4_GLB_NOTIFY_TYPE_SHIFT) | \ + ((SOF_IPC4_GLB_NOTIFICATION) << (SOF_IPC4_GLB_NOTIFY_MSG_TYPE_SHIFT))) + +/** + * \brief IPC MAJOR 4 notification header. All IPC4 notifications use this header. + */ +union ipc4_notification_header { + uint32_t dat; + + struct { + uint32_t rsvd0 : 16; + + /**< Notification::MODULE_EVENT */ + uint32_t notif_type : 8; + + /**< 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; +} __packed __aligned(4); + +/** + * \brief This notification is reported by the Detector module upon key phrase detection. + */ +struct ipc4_voice_cmd_notification { + union { + uint32_t dat; + + struct { + /**< ID of detected keyword */ + uint32_t word_id : 16; + /**< Notification::PHRASE_DETECTED */ + uint32_t notif_type : 8; + /**< Global::NOTIFICATION */ + uint32_t type : 5; + /**< Msg::MSG_NOTIFICATION */ + 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 { + /**< Final speaker verification score in range of 0..8192 */ + uint32_t sv_score : 16; + uint32_t rsvd1 : 14; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __packed __aligned(4); + +/** + * \brief This notification is reported by the Base FW when DSP core receive WDT timeout interrupt. + */ +struct ipc4_watchdog_timeout_notification { + union { + uint32_t dat; + + struct { + /* ID of a core that timeouted. */ + uint32_t core_id : 4; + /* Indicates that it was first timeout and crash dump was done */ + uint32_t first_timeout : 1; + uint32_t rsvd : 11; + /* Notification::WATCHDOG_TIMEOUT */ + uint32_t notif_type : 8; + /* Global::NOTIFICATION */ + uint32_t type : 5; + /* Msg::MSG_NOTIFICATION (0) */ + uint32_t rsp : 1; + /* Msg::FW_GEN_MSG */ + uint32_t msg_tgt : 1; + uint32_t _hw_rsvd_0 : 1; + } r; + } primary; + + union { + uint32_t dat; + + struct { + uint32_t rsvd1 : 30; + uint32_t _hw_rsvd_2 : 2; + } r; + } extension; +} __packed __aligned(4); + +static inline void ipc4_notification_watchdog_init(struct ipc4_watchdog_timeout_notification *notif, + uint32_t core_id, bool first_timeout) +{ + notif->primary.dat = 0; + notif->extension.dat = 0; + + /* ID of a core that timeouted. */ + notif->primary.r.core_id = core_id; + + /* Indicates that it was first timeout and crash dump was done */ + notif->primary.r.first_timeout = first_timeout; + + notif->primary.r.notif_type = SOF_IPC4_WATCHDOG_TIMEOUT; + notif->primary.r.type = SOF_IPC4_GLB_NOTIFICATION; + notif->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + notif->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; +} + +/** + * \brief This notification is sent by a shim of module instance on error raised by data processing + * function. + * + * In case of 3rd party IP error_code is set to its native error code returned by the 3rd party + * library. + */ +struct ipc4_process_data_error_event_data { + /* Error code returned by data processing function */ + uint32_t error_code; +}; + +/** + * \brief This notification is sent by the mixer on stream underrun detection. The frequency of + * sending this notification by Mixer depends on the MixIn settings. + */ +struct ipc4_mixer_underrun_event_data { + /* Indicates EndOfStream */ + uint32_t eos_flag; + /* Data processed by module (in bytes) */ + uint32_t data_mixed; + /* Expected data to be processed (in bytes) */ + uint32_t expected_data_mixed; +}; + +/** + * \brief Input data payload is reserved field in parent technical spec which can be easily + * extendable if needed by specific resource event types in the future. For backward compatibility + * the size of this structure is 6 dw. + */ +union ipc4_resource_event_data { + /* Raw data */ + uint32_t dws[6]; + /* Process Data Error Data (res type = MODULE_INSTANCE) */ + struct ipc4_process_data_error_event_data process_data_error; + /* Mixer Underrun Detected Data (res type = PIPELINE) */ + struct ipc4_mixer_underrun_event_data mixer_underrun; +}; + +struct ipc4_resource_event_data_notification { + /* Type of originator (see sof_ipc4_resource_type) */ + uint32_t resource_type; + /* ID of resource firing event */ + uint32_t resource_id; + /* Type of fired event (see sof_ipc4_resource_event_type enum) */ + uint32_t event_type; + /* Explicit alignment as ipc4_resource_event_data contains 64bit fields and needs + * alignment + */ + uint32_t reserved0; + /* Detailed event data */ + union ipc4_resource_event_data event_data; +} __packed __aligned(8); + +#define IPC4_RESOURCE_EVENT_SIZE sizeof(struct ipc4_resource_event_data_notification) + +void send_process_data_error_notif_msg(uint32_t resource_id, uint32_t error_code); + +bool send_copier_gateway_xrun_notif_msg(uint32_t pipeline_id, enum sof_ipc_stream_direction dir); +bool send_gateway_xrun_notif_msg(uint32_t resource_id, enum sof_ipc_stream_direction dir); + +void send_mixer_underrun_notif_msg(uint32_t resource_id, uint32_t eos_flag, uint32_t data_mixed, + uint32_t expected_data_mixed); +void ipc4_update_notification_mask(uint32_t ntfy_mask, uint32_t enabled_mask); + +#endif /* __IPC4_NOTIFICATION_H__ */ diff --git a/src/include/ipc4/pipeline.h b/src/include/ipc4/pipeline.h new file mode 100644 index 000000000000..198918cf8577 --- /dev/null +++ b/src/include/ipc4/pipeline.h @@ -0,0 +1,456 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/pipeline.h + * \brief IPC4 pipeline definitions + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_PIPELINE_H__ +#define __SOF_IPC4_PIPELINE_H__ + +#include <stdint.h> +#include <ipc4/error_status.h> + +/**< Pipeline priority */ +enum ipc4_pipeline_priority { + /**< Priority 0 (run first) */ + SOF_IPC4_PIPELINE_PRIORITY_0 = 0, + /**< Priority 1 */ + SOF_IPC4_PIPELINE_PRIORITY_1, + /**< Priority 2 */ + SOF_IPC4_PIPELINE_PRIORITY_2, + /**< Priority 3 */ + SOF_IPC4_PIPELINE_PRIORITY_3, + /**< Priority 4 */ + SOF_IPC4_PIPELINE_PRIORITY_4, + /**< Priority 5 */ + SOF_IPC4_PIPELINE_PRIORITY_5, + /**< Priority 6 */ + SOF_IPC4_PIPELINE_PRIORITY_6, + /**< Priority 7 */ + SOF_IPC4_PIPELINE_PRIORITY_7, + /**< Max (and lowest) priority */ + SOF_IPC4_MAX_PIPELINE_PRIORITY = SOF_IPC4_PIPELINE_PRIORITY_7 +}; + +/**< Pipeline State */ +enum ipc4_pipeline_state { + /**< Invalid value */ + SOF_IPC4_PIPELINE_STATE_INVALID = 0, + /**< Created but initialization incomplete */ + SOF_IPC4_PIPELINE_STATE_UNINITIALIZED = 1, + /**< Resets pipeline */ + SOF_IPC4_PIPELINE_STATE_RESET = 2, + /**< Pauses pipeline */ + SOF_IPC4_PIPELINE_STATE_PAUSED = 3, + /**< Starts pipeline */ + SOF_IPC4_PIPELINE_STATE_RUNNING = 4, + /**< Marks pipeline as expecting End Of Stream */ + SOF_IPC4_PIPELINE_STATE_EOS = 5, + /**< Stopped on error */ + SOF_IPC4_PIPELINE_STATE_ERROR_STOP, + /**< Saved to the host memory */ + SOF_IPC4_PIPELINE_STATE_SAVED +}; + +/* IDs for all pipeline ext data types in struct ipc4_pipeline_init_ext_object */ +enum ipc4_pipeline_ext_obj_id { + IPC4_GLB_PIPE_EXT_OBJ_ID_INVALID = 0, + IPC4_GLB_PIPE_EXT_OBJ_ID_MEM_DATA = 1, + IPC4_GLB_PIPE_EXT_OBJ_ID_MAX = IPC4_GLB_PIPE_EXT_OBJ_ID_MEM_DATA, +}; + +/* data object for vendor bespoke data with ABI growth and backwards compat */ +struct ipc4_pipeline_ext_object { + uint32_t last_object : 1; /* object is last in array if 1 else object follows. */ + uint32_t object_id : 15; /* unique ID for this object or globally */ + uint32_t object_words : 16; /* size in dwords (excluding this structure) */ +} __packed __aligned(4); +/* the object data will be placed in memory here and will have size "object_words" */ + +/* Ext array data object for pipeline instance's memory requirements */ +struct ipc4_pipeline_ext_obj_mem_data { + uint32_t domain_id; /* userspace domain ID */ + uint32_t stack_bytes; /* required stack size in bytes */ + uint32_t interim_heap_bytes; /* required interim heap size in bytes */ + uint32_t lifetime_heap_bytes; /* required lifetime heap size in bytes */ + uint32_t shared_bytes; /* required shared memory in bytes */ +} __packed __aligned(4); + +/* + * Host Driver sends this message to create a new pipeline instance. + */ +struct ipc4_pipeline_ext_payload { + uint32_t payload_words : 24; /* size in dwords (excluding this structure) */ + uint32_t data_obj_array : 1; /* struct ipc4_pipeline_ext_object data */ + uint32_t rsvd0 : 7; + uint32_t rsvd1; + uint32_t rsvd2; +} __packed __aligned(4); + +/*! + * lp - indicates whether the pipeline should be kept on running in low power + * mode. On BXT the driver should set this flag to 1 for WoV pipeline. + * + * \remark hide_methods + */ +struct ipc4_pipeline_create { + + union { + uint32_t dat; + + struct { + /**< # pages for pipeline */ + uint32_t ppl_mem_size : 11; + /**< priority - uses enum ipc4_pipeline_priority */ + uint32_t ppl_priority : 5; + /**< pipeline id */ + uint32_t instance_id : 8; + /**< Global::CREATE_PIPELINE */ + 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 { + /**< 1 - is low power */ + uint32_t lp : 1; + uint32_t rsvd1 : 3; + uint32_t attributes : 16; + uint32_t core_id : 4; + uint32_t rsvd2 : 5; + uint32_t payload : 1; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/*! + * SW Driver sends this IPC message to delete a pipeline from ADSP memory. + * + * All module instances and tasks that are associated with the pipeline are + * deleted too. + * + * There must be no existing binding from any pipeline's module instance + * to another pipeline to complete the command successfully. + * + * \remark hide_methods + */ +struct ipc4_pipeline_delete { + union { + uint32_t dat; + + struct { + uint32_t rsvd0 : 16; + /**< Ppl instance id */ + uint32_t instance_id : 8; + /**< Global::DELETE_PIPELINE */ + 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 rsvd1 : 30; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/*! + * Host SW sends this message to set a pipeline to the specified state. + * + * If there are multiple pipelines, from FW input to FW output, connected + * in a data processing stream, the driver should start them in reverse order, + * beginning with pipeline connected to the output gateway, in order to avoid + * overruns (FW protects the output gateway against underruns in this scenario). + * + * If driver starts multiple pipelines using a single Set Pipeline State + * command, it should take care of the pipeline ID order in the command payload + * to follow the above rule. + * + * sync_stop_start indicates whether all specified pipelines' gateways should + * be started with a minimal delay possible. If this flag is set to 0 while + * multiple pipelines are specified, the target pipelines' state is adjusted + * pipeline by pipeline meaning that internal propagation to all child modules + * may take more time between reaching state of attached gateways. Output and + * input gateways are grouped separately, and started/stopped separately. + * + * NOTE: Task Creation/Registration is part of the first state transition. + * There is no other dedicated call for this. + * + * \remark hide_methods + */ +struct ipc4_pipeline_set_state_data { + /**< Number of items in ppl_id[] */ + uint32_t pipelines_count; + /**< Pipeline ids */ + uint32_t ppl_id[]; +} __attribute__((packed, aligned(4))); + +struct ipc4_pipeline_set_state { + union { + uint32_t dat; + + struct { + /**< new state, one of enum ipc4_pipeline_state */ + uint32_t ppl_state : 16; + /**< pipeline instance id (ignored if multi_ppl =1) */ + uint32_t ppl_id : 8; + /**< Global::SET_PIPELINE_STATE */ + 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 { + /**< = 1 if there are more pipeline ids in payload */ + uint32_t multi_ppl : 1; + /**< = 1 if FW should sync state change across multiple ppls */ + uint32_t sync_stop_start : 1; + uint32_t rsvd1 : 28; + uint32_t _reserved_2: 2; + } r; + } extension; + + /* multiple pipeline states */ + struct ipc4_pipeline_set_state_data s_data; +} __attribute__((packed, aligned(4))); + +/**< Reply to Set Pipeline State */ +/*! + * In case of error, there is failed pipeline id reported back. + * + \remark hide_methods +*/ +struct ipc4_pipeline_set_state_reply { + union { + uint32_t dat; + + struct { + /**< status */ + uint32_t status : IPC4_IXC_STATUS_BITS; + /**< Global::SET_PIPELINE_STATE */ + uint32_t type : 5; + /**< Msg::MSG_REPLY */ + 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 { + /**< id of failed pipeline on error */ + uint32_t ppl_id : 30; + uint32_t _reserved_2: 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/**< This IPC message is sent to the FW in order to retrieve a pipeline state. */ +/*! \remark hide_methods */ +struct ipc4_pipeline_get_state { + union { + uint32_t dat; + + struct { + /**< pipeline id */ + uint32_t ppl_id : 8; + uint32_t rsvd : 16; + /**< Global::GET_PIPELINE_STATE */ + 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 rsvd1 : 30; + uint32_t _reserved_2: 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/**< Sent by the FW in response to GetPipelineState. */ +/*! \remark hide_methods */ +struct ipc4_pipeline_get_state_reply { + union { + uint32_t dat; + + struct { + /**< status */ + uint32_t status :IPC4_IXC_STATUS_BITS; + /**< Global::GET_PIPELINE_STATE */ + uint32_t type : 5; + /**< Msg::MSG_REPLY */ + 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 { + /**< one of PipelineState */ + uint32_t state : 5; + uint32_t rsvd1 : 25; + uint32_t _reserved_2: 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/*! + * The size is expressed in number of pages. It is a total number of memory pages + * allocated for pipeline memory buffer and all separately allocated child + * module instances. + * + * \remark hide_methods + */ +struct ipc4_pipeline_get_context_size { + union { + uint32_t dat; + + struct { + uint32_t rsvd0 : 16; + /**< pipeline id */ + uint32_t instance_id : 8; + /**< Global::GET_PIPELINE_CONTEXT_SIZE */ + 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 rsvd1 : 30; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +/**< Reply to Get Pipeline Context Size. */ +/*! \remark hide_methods */ +struct ipc4_pipeline_get_context_size_reply { + union { + uint32_t dat; + + struct { + /**< status */ + uint32_t status :IPC4_IXC_STATUS_BITS; + /**< Global::GET_PIPELINE_CONTEXT_SIZE */ + uint32_t type : 5; + /**< Msg::MSG_REPLY */ + 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 { + /**< size of pipeline context (in number of pages) */ + uint32_t ctx_size : 16; + uint32_t rsvd1 : 14; + uint32_t _reserved_2: 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +struct ipc4_chain_dma { + union { + uint32_t dat; + + struct { + uint32_t host_dma_id : 5; + uint32_t rsvd4 : 3; + uint32_t link_dma_id : 5; + uint32_t rsvd3 : 3; + /* allocate buffer specified by FIFO size */ + uint32_t allocate : 1; + uint32_t enable : 1; + /* controls SCS bit in both Host and Link gateway */ + uint32_t scs : 1; + uint32_t rsvd2 : 5; + /* Global::CHAIN_DMA */ + 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 { + /* size of FIFO (bytes) */ + uint32_t fifo_size : 24; + uint32_t rsvd1 : 6; + uint32_t _reserved_2 : 2; + } r; + } extension; +} __attribute__((packed, aligned(4))); + +#endif diff --git a/src/include/ipc4/probe.h b/src/include/ipc4/probe.h new file mode 100644 index 000000000000..70b23632eecb --- /dev/null +++ b/src/include/ipc4/probe.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/* + * \file include/ipc4/probe.h + * \brief probe ipc4 definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_PROBE_H__ +#define __SOF_IPC4_PROBE_H__ + +#include <sof/compiler_attributes.h> +#include "base-config.h" +#include <rtos/bit.h> +#include <stdint.h> + +/* + * Buffer id used in the probe output stream headers for + * logging data packet. + */ +#define PROBE_LOGGING_BUFFER_ID 0x01000000 + +#define PROBE_PURPOSE_EXTRACTION 0 +#define PROBE_PURPOSE_INJECTION 1 + +#define PROBE_TYPE_INPUT 0 +#define PROBE_TYPE_OUTPUT 1 +#define PROBE_TYPE_INTERNAL 2 + +#define IPC4_PROBE_MODULE_INJECTION_DMA_ADD 1 +#define IPC4_PROBE_MODULE_INJECTION_DMA_DETACH 2 +#define IPC4_PROBE_MODULE_PROBE_POINTS_ADD 3 +#define IPC4_PROBE_MODULE_DISCONNECT_PROBE_POINTS 4 +#define IPC4_PROBE_MODULE_AVAILABLE_PROBE_POINTS 5 + +/** + * Description of probe dma + */ +struct probe_dma { + uint32_t stream_tag; /**< Node_id associated with this DMA */ + uint32_t dma_buffer_size; /**< Size of buffer associated with this DMA */ +} __attribute__((packed, aligned(4))); + +/** + * Description of probe point id + */ +typedef union probe_point_id { + uint32_t full_id; + struct { + uint32_t module_id : 16; /**< Target module ID */ + uint32_t instance_id : 8; /**< Target module instance ID */ + uint32_t type : 2; /**< Probe point type as specified by ProbeType enumeration */ + uint32_t index : 6; /**< Queue index inside target module */ + } fields; +} __attribute__((packed, aligned(4))) probe_point_id_t; + +/** + * Description of probe point + */ +struct probe_point { + probe_point_id_t buffer_id; /**< ID of buffer to which probe is attached */ + uint32_t purpose; /**< PROBE_PURPOSE_xxx */ + uint32_t stream_tag; /**< Stream tag of DMA via which data will be provided for injection. + * For extraction purposes, stream tag is ignored when received, + * but returned actual extraction stream tag via INFO function. + */ +} __attribute__((packed, aligned(4))); + +struct sof_ipc_probe_info_params { + uint32_t num_elems; /**< Count of elements in array */ + union { + struct probe_dma probe_dma[0]; /**< DMA info */ + struct probe_point probe_point[0]; /**< Probe Point info */ + }; +} __attribute__((packed, aligned(4))); + +struct ipc4_probe_module_cfg { + struct ipc4_base_module_cfg base_cfg; + struct probe_dma gtw_cfg; +} __packed __aligned(8); + +#endif /* __SOF_IPC4_PROBE_H__ */ diff --git a/src/include/ipc4/ssp.h b/src/include/ipc4/ssp.h new file mode 100644 index 000000000000..752cb59193bf --- /dev/null +++ b/src/include/ipc4/ssp.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + */ + +/** + * \file include/ipc4/ssp.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __SOF_IPC4_SSP_H__ +#define __SOF_IPC4_SSP_H__ + +#include <stdint.h> +#include <ipc4/gateway.h> + +#define I2S_TDM_INVALID_SLOT_MAP1 0xF +#define I2S_TDM_MAX_CHANNEL_COUNT 8 +#define I2S_TDM_MAX_SLOT_MAP_COUNT 8 + +/* i2s Configuration BLOB building blocks */ + +/* i2s registers for i2s Configuration */ +struct ipc4_ssp_config { + uint32_t ssc0; + uint32_t ssc1; + uint32_t sscto; + uint32_t sspsp; + uint32_t sstsa; + uint32_t ssrsa; + uint32_t ssc2; + uint32_t sspsp2; + uint32_t ssc3; + uint32_t ssioc; +} __attribute__((packed, aligned(4))); + +struct ipc4_ssp_mclk_config { + /* master clock divider control register */ + uint32_t mdivc; + + /* master clock divider ratio register */ + uint32_t mdivr; +} __attribute__((packed, aligned(4))); + +struct ipc4_ssp_driver_config { + struct ipc4_ssp_config i2s_config; + struct ipc4_ssp_mclk_config mclk_config; +} __attribute__((packed, aligned(4))); + +struct ipc4_ssp_start_control { + /* delay in msec between enabling interface (moment when + * Copier instance is being attached to the interface) and actual + * interface start. Value of 0 means no delay. + */ + uint32_t clock_warm_up : 16; + + /* specifies if parameters target MCLK (1) or SCLK (0) */ + uint32_t mclk : 1; + + /* value of 1 means that clock should be started immediately + * even if no Copier instance is currently attached to the interface. + */ + uint32_t warm_up_ovr : 1; + uint32_t rsvd0 : 14; +} __attribute__((packed, aligned(4))); + +struct ipc4_ssp_stop_control { + /* delay in msec between stopping the interface + * (moment when Copier instance is being detached from the interface) + * and interface clock stop. Value of 0 means no delay. + */ + uint32_t clock_stop_delay : 16; + + /* value of 1 means that clock should be kept running (infinite + * stop delay) after Copier instance detaches from the interface. + */ + uint32_t keep_running : 1; + + /* value of 1 means that clock should be stopped immediately */ + uint32_t clock_stop_ovr : 1; + uint32_t rsvd1 : 14; +} __attribute__((packed, aligned(4))); + +union ipc4_ssp_dma_control { + struct ipc4_ssp_control { + struct ipc4_ssp_start_control start_control; + struct ipc4_ssp_stop_control stop_control; + } control_data; + + struct ipc4_mn_div_config { + uint32_t mval; + uint32_t nval; + } mndiv_control_data; +} __attribute__((packed, aligned(4))); + +struct ipc4_ssp_configuration_blob { + union ipc4_gateway_attributes gw_attr; + + /* TDM time slot mappings */ + uint32_t tdm_ts_group[I2S_TDM_MAX_SLOT_MAP_COUNT]; + + /* i2s port configuration */ + struct ipc4_ssp_driver_config i2s_driver_config; + + /* optional configuration parameters */ + union ipc4_ssp_dma_control i2s_dma_control[]; +} __attribute__((packed, aligned(4))); + +#endif diff --git a/src/include/kernel/abi.h b/src/include/kernel/abi.h index a442b760ab3e..c46361de8da5 100644 --- a/src/include/kernel/abi.h +++ b/src/include/kernel/abi.h @@ -29,8 +29,8 @@ /** \brief SOF ABI version major, minor and patch numbers */ #define SOF_ABI_MAJOR 3 -#define SOF_ABI_MINOR 14 -#define SOF_ABI_PATCH 0 +#define SOF_ABI_MINOR 29 +#define SOF_ABI_PATCH 1 /** \brief SOF ABI version number. Format within 32bit word is MMmmmppp */ #define SOF_ABI_MAJOR_SHIFT 24 @@ -61,5 +61,7 @@ /** \brief SOF ABI magic number "SOF\0". */ #define SOF_ABI_MAGIC 0x00464F53 +/** \brief SOF IPC4 ABI magic number "SOF4". */ +#define SOF_IPC4_ABI_MAGIC 0x34464F53 #endif /* __KERNEL_ABI_H__ */ diff --git a/src/include/kernel/ext_manifest.h b/src/include/kernel/ext_manifest.h new file mode 100644 index 000000000000..c429cbe0340e --- /dev/null +++ b/src/include/kernel/ext_manifest.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +/* + * Parts of this file are copied to ext_manifest.h in Linux kernel tree + * and to the rimage tree. This duplication is OK because it is part of + * a versioned ABI. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + * + * To add new content to ext_man, in firmware code define struct which starts + * with ext_man_elem_head followed by usage dependent content and place whole + * struct in "fw_metadata" section. Moreover kernel code should be modified to + * properly read new packet. + * + * Extended manifest is designed to be extensible. In header there is a field + * which describe header length, so after appending some data to header then it + * can be easily skipped by device with older version of this header. + * Unknown ext_man elements should be just skipped by host, + * to be backward compatible. Field `ext_man_elem_header.elem_size` should be + * used in such a situation. + */ + +#ifndef __KERNEL_EXT_MANIFEST_H__ +#define __KERNEL_EXT_MANIFEST_H__ + +#include <ipc/info.h> +#include <sof/compiler_attributes.h> +#include <stdint.h> + +/* Top-level headers shared with rimage */ + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +/* In ASCII `XMan` */ +#define EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ( \ + ((uint32_t)(MAJOR) << 24) | \ + ((uint32_t)(MINOR) << 12) | \ + (uint32_t)(PATH)) + +/* check extended manifest version consistency */ +#define EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define EXT_MAN_VERSION EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* struct size alignment for ext_man elements */ +#define EXT_MAN_ALIGN 16 + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct ext_man_header { + uint32_t magic; /**< identification number, */ + /**< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /**< [bytes] full size of ext_man, */ + /**< (header + content + padding) */ + uint32_t header_size; /**< [bytes] makes header extensionable, */ + /**< after append new field to ext_man header */ + /**< then backward compatible won't be lost */ + uint32_t header_version; /**< value of EXT_MAN_VERSION */ + /**< not related with following content */ + + /* just after this header should be list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct ext_man_elem_header { + uint32_t type; /**< EXT_MAN_ELEM_* */ + uint32_t elem_size; /**< in bytes, including header size */ + + /* just after this header should be type dependent content */ +} __packed; + +/* End of the top-level headers shared with rimage */ + +/* Extended manifest elements identificators */ +enum ext_man_elem_type { + EXT_MAN_ELEM_FW_VERSION = 0, + EXT_MAN_ELEM_WINDOW = SOF_IPC_EXT_WINDOW, + EXT_MAN_ELEM_CC_VERSION = SOF_IPC_EXT_CC_INFO, + EXT_MAN_ELEM_PROBE_INFO = SOF_IPC_EXT_PROBE_INFO, + EXT_MAN_ELEM_DBG_ABI = SOF_IPC_EXT_USER_ABI_INFO, /**< ABI3.17 */ + EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ + EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, /**< ABI3.17 */ +}; + +/* EXT_MAN_ELEM_CONFIG_DATA elements identificators */ +enum config_elem_type { + EXT_MAN_CONFIG_IPC_MSG_SIZE = 1, + EXT_MAN_CONFIG_MEMORY_USAGE_SCAN = 2, /**< ABI3.18 */ + EXT_MAN_CONFIG_LAST_ELEM, /**< keep it at the end of enum list */ +}; + +struct config_elem { + uint32_t token; + uint32_t value; +} __attribute__((packed, aligned(4))); + +/* FW version */ +struct ext_man_fw_version { + struct ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __attribute__((packed, aligned(4))); + +/* windows info */ +struct ext_man_windows { + struct ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_window window; +} __attribute__((packed, aligned(4))); + +/* Used C compiler description */ +struct ext_man_cc_version { + struct ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_cc_version cc_version; +} __attribute__((packed, aligned(4))); + +struct ext_man_probe_support { + struct ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_probe_support probe; +} __attribute__((packed, aligned(4))); + +struct ext_man_dbg_abi { + struct ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_user_abi_version dbg_abi; +} __attribute__((packed, aligned(4))); + +/** EXT_MAN_ELEM_CONFIG_DATA elements (ABI3.17) */ +struct ext_man_config_data { + struct ext_man_elem_header hdr; + + struct config_elem elems[]; +} __attribute__((packed, aligned(4))); + +#endif /* __KERNEL_EXT_MANIFEST_H__ */ diff --git a/src/include/kernel/header.h b/src/include/kernel/header.h index 1fa31b2d994e..1fe7a9398855 100644 --- a/src/include/kernel/header.h +++ b/src/include/kernel/header.h @@ -22,18 +22,27 @@ * \brief Header for all non IPC ABI data. * * Identifies data type, size and ABI. - * Data header used for all component data structures and binary blobs sent to - * firmware as runtime data. This data is typically sent by userspace - * applications and tunnelled through any OS kernel (via binary kcontrol on - * Linux) to the firmware. + * Only in case of IPC3 the data header used for all component data structures + * and binary blobs sent to firmware as runtime data. This data is typically sent + * by userspace applications and tunnelled through any OS kernel (via binary + * kcontrol on Linux) to the firmware. + * With IPC4 the ABI header is used between user space and kernel for verification + * purposes and to provide information about the attached binary blob, like the + * param_id of it. */ struct sof_abi_hdr { - uint32_t magic; /**< 'S', 'O', 'F', '\0' */ - uint32_t type; /**< component specific type */ + uint32_t magic; /**< Magic number for validation */ + /**< for IPC3 data: 0x00464F53 ('S', 'O', 'F', '\0') */ + /**< for IPC4 data: 0x34464F53 ('S', 'O', 'F', '4') */ + uint32_t type; /**< module specific parameter */ + /**< for IPC3: Component specific type */ + /**< for IPC4: parameter ID (param_id) of the data */ uint32_t size; /**< size in bytes of data excl. this struct */ - uint32_t abi; /**< SOF ABI version */ + uint32_t abi; /**< SOF ABI version. */ + /**< The version is valid in scope of the 'magic', */ + /**< IPC3 and IPC4 ABI version numbers have no relationship. */ uint32_t reserved[4]; /**< reserved for future use */ - uint32_t data[0]; /**< Component data - opaque to core */ + uint32_t data[]; /**< Component data - opaque to core */ } __attribute__((packed)); #endif /* __KERNEL_HEADER_H__ */ diff --git a/src/include/kernel/mailbox.h b/src/include/kernel/mailbox.h new file mode 100644 index 000000000000..1c2d0ff55881 --- /dev/null +++ b/src/include/kernel/mailbox.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Adrian Bonislawski <adrian.bonislawski@linux.intel.com> + */ + +/** + * \file include/kernel/mailbox.h + * \brief FW Regs API definition + * \author Adrian Bonislawski <adrian.bonislawski@linux.intel.com> + */ + +#ifndef __KERNEL_MAILBOX_H__ +#define __KERNEL_MAILBOX_H__ + +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/fw_reg.h> +#endif + +/** \addtogroup fw_regs_api FW Regs API + * This is a common SRAM window 0 FW "registers" layout + * used in the platfrom-defined SRAM window 0 region + * @{ + */ +#if CONFIG_IPC_MAJOR_4 +#define SRAM_REG_FW_STATUS offsetof(struct ipc4_fw_registers, fsr) +#define SRAM_REG_LAST_ERROR_CODE offsetof(struct ipc4_fw_registers, lec) +#define SRAM_REG_FW_PWR_STATUS offsetof(struct ipc4_fw_registers, fps) +#define SRAM_REG_LNEC offsetof(struct ipc4_fw_registers, lnec) +#define SRAM_REG_LTR offsetof(struct ipc4_fw_registers, ltr) +#define SRAM_REG_ROM_INFO offsetof(struct ipc4_fw_registers, rom_info) +#define SRAM_REG_ABI_VER offsetof(struct ipc4_fw_registers, abi_ver) +#define SRAM_REG_SLAVE_CORE_STS offsetof(struct ipc4_fw_registers, slave_core_sts) +#define SRAM_REG_PIPELINE_REGS offsetof(struct ipc4_fw_registers, pipeline_regs) +#define SRAM_REG_PEAK_VOL_REGS offsetof(struct ipc4_fw_registers, peak_vol_regs) +#define SRAM_REG_LLP_GPDMA_READING_SLOTS offsetof(struct ipc4_fw_registers, llp_gpdma_reading_slots) +#define SRAM_REG_LLP_SNDW_READING_SLOTS offsetof(struct ipc4_fw_registers, llp_sndw_reading_slots) +#define SRAM_REG_LLP_EVAD_SLOTS offsetof(struct ipc4_fw_registers, llp_evad_reading_slot) +#define SRAM_REG_FW_END sizeof(struct ipc4_fw_registers) +#else /* CONFIG_IPC_MAJOR_4 */ +#define SRAM_REG_ROM_STATUS 0x0 +#define SRAM_REG_FW_STATUS 0x4 +#define SRAM_REG_FW_TRACEP 0x8 +#define SRAM_REG_FW_IPC_RECEIVED_COUNT 0xc +#define SRAM_REG_FW_IPC_PROCESSED_COUNT 0x10 +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_BASE 0x14 +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_1 SRAM_REG_FW_TRACEP_SECONDARY_CORE_BASE +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_2 0x18 +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_3 0x1C +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_4 0x20 +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_5 0x24 +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_6 0x28 +#define SRAM_REG_FW_TRACEP_SECONDARY_CORE_7 0x2C +#define SRAM_REG_R_STATE_TRACE_BASE 0x30 +#define SRAM_REG_R0_STATE_TRACE SRAM_REG_R_STATE_TRACE_BASE +#define SRAM_REG_R1_STATE_TRACE 0x38 +#define SRAM_REG_R2_STATE_TRACE 0x40 +#define SRAM_REG_FW_END (SRAM_REG_R2_STATE_TRACE + 0x8) +#endif + +/** @}*/ + +#endif /* __KERNEL_MAILBOX_H__ */ diff --git a/src/include/kernel/tokens.h b/src/include/kernel/tokens.h index 26b1fd7ad1cc..93c4754f831c 100644 --- a/src/include/kernel/tokens.h +++ b/src/include/kernel/tokens.h @@ -22,6 +22,9 @@ #define SOF_TPLG_KCTL_ENUM_ID 257 #define SOF_TPLG_KCTL_BYTES_ID 258 #define SOF_TPLG_KCTL_SWITCH_ID 259 +#define SOF_TPLG_KCTL_BYTES_VOLATILE_RO 260 +#define SOF_TPLG_KCTL_BYTES_VOLATILE_RW 261 +#define SOF_TPLG_KCTL_BYTES_WO_ID 262 /* * Tokens - must match values in topology configurations @@ -30,6 +33,7 @@ /* buffers */ #define SOF_TKN_BUF_SIZE 100 #define SOF_TKN_BUF_CAPS 101 +#define SOF_TKN_BUF_FLAGS 102 /* DAI */ /* Token retired with ABI 3.2, do not use for new capabilities @@ -46,11 +50,17 @@ #define SOF_TKN_SCHED_CORE 203 #define SOF_TKN_SCHED_FRAMES 204 #define SOF_TKN_SCHED_TIME_DOMAIN 205 +#define SOF_TKN_SCHED_DYNAMIC_PIPELINE 206 +#define SOF_TKN_SCHED_LP_MODE 207 /* volume */ #define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250 #define SOF_TKN_VOLUME_RAMP_STEP_MS 251 +#define SOF_TKN_GAIN_RAMP_TYPE 260 +#define SOF_TKN_GAIN_RAMP_DURATION 261 +#define SOF_TKN_GAIN_VAL 262 + /* SRC */ #define SOF_TKN_SRC_RATE_IN 300 #define SOF_TKN_SRC_RATE_OUT 301 @@ -71,6 +81,21 @@ /* Token retired with ABI 3.2, do not use for new capabilities * #define SOF_TKN_COMP_PRELOAD_COUNT 403 */ +#define SOF_TKN_COMP_CORE_ID 404 +#define SOF_TKN_COMP_UUID 405 +#define SOF_TKN_COMP_CPC 406 +#define SOF_TKN_COMP_IS_PAGES 409 +#define SOF_TKN_COMP_NUM_AUDIO_FORMATS 410 +#define SOF_TKN_COMP_NUM_INPUT_PINS 411 +#define SOF_TKN_COMP_NUM_OUTPUT_PINS 412 +/* + * The token for input/output pin binding, it specifies the widget + * name that the input/output pin is connected from/to. + */ +#define SOF_TKN_COMP_INPUT_PIN_BINDING_WNAME 413 +#define SOF_TKN_COMP_OUTPUT_PIN_BINDING_WNAME 414 +#define SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS 415 +#define SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS 416 /* SSP */ #define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500 @@ -90,6 +115,7 @@ #define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE 605 #define SOF_TKN_INTEL_DMIC_SAMPLE_RATE 608 #define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH 609 +#define SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS 610 /* DMIC PDM */ #define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID 700 @@ -115,8 +141,55 @@ /* ESAI */ #define SOF_TKN_IMX_ESAI_MCLK_ID 1100 +/* Stream */ +#define SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3 1200 +#define SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 1201 + /* Led control for mute switches */ #define SOF_TKN_MUTE_LED_USE 1300 #define SOF_TKN_MUTE_LED_DIRECTION 1301 +/* ALH */ +#define SOF_TKN_INTEL_ALH_RATE 1400 +#define SOF_TKN_INTEL_ALH_CH 1401 + +/* HDA */ +#define SOF_TKN_INTEL_HDA_RATE 1500 +#define SOF_TKN_INTEL_HDA_CH 1501 + +/* AFE */ +#define SOF_TKN_MEDIATEK_AFE_RATE 1600 +#define SOF_TKN_MEDIATEK_AFE_CH 1601 +#define SOF_TKN_MEDIATEK_AFE_FORMAT 1602 + +/* MIXER */ +#define SOF_TKN_MIXER_TYPE 1700 + +/* CAVS AUDIO FORMAT */ +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE 1900 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH 1901 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_VALID_BIT_DEPTH 1902 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CHANNELS 1903 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP 1904 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG 1905 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE 1906 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG 1907 +#define SOF_TKN_CAVS_AUDIO_FORMAT_IN_SAMPLE_TYPE 1908 +#define SOF_TKN_CAVS_AUDIO_FORMAT_INPUT_PIN_INDEX 1909 +/* intentional token numbering discontinuity, reserved for future use */ +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE 1930 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH 1931 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_VALID_BIT_DEPTH 1932 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CHANNELS 1933 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP 1934 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG 1935 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE 1936 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG 1937 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUT_SAMPLE_TYPE 1938 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OUTPUT_PIN_INDEX 1939 +/* intentional token numbering discontinuity, reserved for future use */ +#define SOF_TKN_CAVS_AUDIO_FORMAT_IBS 1970 +#define SOF_TKN_CAVS_AUDIO_FORMAT_OBS 1971 +#define SOF_TKN_CAVS_AUDIO_FORMAT_DMA_BUFFER_SIZE 1972 + #endif /* __KERNEL_TOKENS_H__ */ diff --git a/src/include/module/audio/audio_stream.h b/src/include/module/audio/audio_stream.h new file mode 100644 index 000000000000..e032ef322f85 --- /dev/null +++ b/src/include/module/audio/audio_stream.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_AUDIO_AUDIO_STREAM_H__ +#define __MODULE_AUDIO_AUDIO_STREAM_H__ + +#include <stdint.h> +#include <stdbool.h> +#include "../ipc/stream.h" + + +/** + * @enum sof_audio_buffer_state + * @brief Define states of an audio stream buffer connecting two components. + * + * This enum represents the lifecycle of an audio stream, including its + * initialization, readiness, and end-of-stream handling. It is used to + * track and manage the state transitions of the stream during audio processing. + */ +enum sof_audio_buffer_state { + AUDIOBUF_STATE_INITIAL, /* Initial state, hw params not configured. */ + AUDIOBUF_STATE_READY, /* Stream ready, hw params configured */ + AUDIOBUF_STATE_END_OF_STREAM, /* Detected End Of Stream */ + AUDIOBUF_STATE_END_OF_STREAM_FLUSH, /* Detected End Of Stream, generating silence + * to flush buffers in dp modules. + */ +}; + +/** + * set of parameters describing audio stream + * this structure is shared between audio_stream.h and sink/source interface + * TODO: compressed formats + */ +struct sof_audio_stream_params { + uint32_t id; + uint32_t pipeline_id; + enum sof_ipc_frame frame_fmt; /**< Sample data format */ + enum sof_ipc_frame valid_sample_fmt; + + uint32_t rate; /**< Number of data frames per second [Hz] */ + uint16_t channels; /**< Number of samples in each frame */ + + /** + * align_frame_cnt indicates minimum number of frames that satisfies both byte + * align and frame align requirements. E.g: Consider an algorithm that processes + * in blocks of 3 frames configured to process 16-bit stereo using xtensa HiFi3 + * SIMD. Therefore with 16-bit stereo we have a frame size of 4 bytes, and + * SIMD intrinsic requirement of 8 bytes(2 frames) for HiFi3 and an algorithim + * requirement of 3 frames. Hence the common processing block size has to align + * with frame(1), intrinsic(2) and algorithm (3) giving us an optimum processing + * block size of 6 frames. + */ + uint16_t align_frame_cnt; + + /** + * the free/available bytes of sink/source right shift align_shift_idx, the result + * multiplied by align_frame_cnt is the frame count free/available that can meet + * the align requirement. + */ + uint16_t align_shift_idx; + + bool overrun_permitted; /**< indicates whether overrun is permitted */ + bool underrun_permitted; /**< indicates whether underrun is permitted */ + + uint32_t buffer_fmt; /**< enum sof_ipc_buffer_format */ + + uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */ + + enum sof_audio_buffer_state state; /**< audio stream state */ +}; + +#endif /* __MODULE_AUDIO_AUDIO_STREAM_H__ */ diff --git a/src/include/module/audio/format.h b/src/include/module/audio/format.h new file mode 100644 index 000000000000..7fccef12f49e --- /dev/null +++ b/src/include/module/audio/format.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 - 2023 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_AUDIO_FORMAT_H__ +#define __MODULE_AUDIO_FORMAT_H__ + +#include <stdint.h> +#include "../ipc/stream.h" + +static inline uint32_t get_sample_bytes(enum sof_ipc_frame fmt) +{ + switch (fmt) { + case SOF_IPC_FRAME_S16_LE: + return 2; + case SOF_IPC_FRAME_S24_3LE: + return 3; + case SOF_IPC_FRAME_U8: + case SOF_IPC_FRAME_A_LAW: + case SOF_IPC_FRAME_MU_LAW: + return 1; + default: + return 4; + } +} + +static inline uint32_t get_sample_bitdepth(enum sof_ipc_frame fmt) +{ + switch (fmt) { + case SOF_IPC_FRAME_S16_LE: + return 16; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S24_3LE: + return 24; + case SOF_IPC_FRAME_U8: + case SOF_IPC_FRAME_A_LAW: + case SOF_IPC_FRAME_MU_LAW: + return 8; + default: + return 32; + } +} + +static inline uint32_t get_frame_bytes(enum sof_ipc_frame fmt, uint32_t channels) +{ + return get_sample_bytes(fmt) * channels; +} + +#endif /* __MODULE_AUDIO_FORMAT_H__ */ diff --git a/src/include/module/audio/sink_api.h b/src/include/module/audio/sink_api.h new file mode 100644 index 000000000000..920087d6f8b3 --- /dev/null +++ b/src/include/module/audio/sink_api.h @@ -0,0 +1,362 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __MODULE_AUDIO_SINK_API_H__ +#define __MODULE_AUDIO_SINK_API_H__ + +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> + +#include "audio_stream.h" +#include "format.h" + +/** + * this is a definition of API to sink of audio data + * + * THE SINK is any component that can store data somehow and provide a buffer to be filled + * with data at request. The sink API does not define how the data will be processed/used + * + * The user - a module - sees this API as a destination it must send data to + * The IMPLEMENTATION - audio_stream, DP Queue - sees this as a producer that + * PROVIDES data for processing + * + * Examples of components that should expose SINK api + * - /dev/null + * all the data stored in sink buffer are just simply discarded + * - I2S sender + * Data stored in sink buffer will be sent to the external world + * - a memory ring buffer + * data stored in the buffer will be sent to another module (usually using source API, but it + * does not matter in fact). + * + * The main advantage of using sink API instead of just taking pointers to the buffers is that + * the buffer may be prepared at the moment the data producer is requesting it. i.e. + * - cache may be written back/invalidated if necessary + * - data may be moved to make linear space + * - part of the buffer may be locked to prevent reading + * etc.etc. it depends on implementation of the data sink + * + * NOTE: the module should get a complete portion of space it needs for processing, fill it + * than release. The reason is - the depending on the implementation, the calls may be + * expensive - may involve some data moving in memory, cache writebacks, etc. + * + */ + +/* forward def */ +struct sof_sink; +struct sof_audio_stream_params; +struct sof_ipc_stream_params; +struct processing_module; + +/** + * this is a definition of internals of sink API + * + * The clients of stream API should use access functions provided below! + * + */ + +struct sink_ops { + /** + * see comment of sink_get_free_size() + */ + size_t (*get_free_size)(struct sof_sink *sink); + + /** + * see comment of sink_get_buffer() + */ + int (*get_buffer)(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size); + + /** + * see comment of sink_commit_buffer() + */ + int (*commit_buffer)(struct sof_sink *sink, size_t commit_size); + + /** + * get latest feeding time for this sink, result is a number of microseconds since "NOW" + * where "now" means a start of last LL cycle, as described in zephyr_dp_schedule.c + */ + uint32_t (*get_lft)(struct sof_sink *sink); + + /** + * OPTIONAL: Notification to the sink implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * sink may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameters are not supported + */ + int (*on_audio_format_set)(struct sof_sink *sink); + + /** + * OPTIONAL + * see sink_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_sink *sink, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for sink_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); + + /** + * OPTIONAL + * events called when a module is starting / finishing using of the API + * on the core that the module and API will executed on + */ + int (*on_bind)(struct sof_sink *sink, struct processing_module *module); + int (*on_unbind)(struct sof_sink *sink); +}; + +/** internals of sink API. NOT TO BE MODIFIED OUTSIDE OF sink_api.c */ +struct sof_sink { + const struct sink_ops *ops; /** operations interface */ + size_t requested_write_frag_size; /** keeps number of bytes requested by get_buffer() */ + size_t num_of_bytes_processed; /** processed bytes counter */ + size_t min_free_space; /** minimum buffer space required by the module using sink + * it is module's OBS as declared in module bind IPC + */ + struct processing_module *bound_module; /* a pointer module that is using sink API */ + struct sof_audio_stream_params *audio_stream_params; /** pointer to audio params */ +}; + +/** + * + * Public functions + * + */ + +/** + * Retrieves size of free space available in sink (in bytes) + * return number of free bytes in buffer available to immediate filling + */ +static inline size_t sink_get_free_size(struct sof_sink *sink) +{ + return sink->ops->get_free_size(sink); +} + +static inline enum sof_ipc_frame sink_get_frm_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->frame_fmt; +} + +static inline uint32_t sink_get_channels(struct sof_sink *sink) +{ + return sink->audio_stream_params->channels; +} + +/** get size of a single audio frame (in bytes) */ +size_t sink_get_frame_bytes(struct sof_sink *sink); + +/** + * Retrieves size of free space available in sink (in frames) + * return number of free frames in buffer available to immediate filling + */ +size_t sink_get_free_frames(struct sof_sink *sink); + +/** + * Get a circular buffer to operate on (to write). + * + * Retrieves a fragment of circular data to be used by the caller + * After calling get_buffer, the space for data is guaranteed to be available + * for exclusive use on the caller core through provided pointer + * if the provided pointers are cached, it is guaranteed that the caller may safely use it without + * any additional cache operations + * The caller MUST take care of data circularity based on provided pointers + * + * @param sink a handler to sink + * @param [in] req_size requested size of space + * @param [out] data_ptr a pointer to the space will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_size size of circular buffer + * + * @retval -ENODATA if req_size is bigger than free space + * + */ +int sink_get_buffer(struct sof_sink *sink, size_t req_size, void **data_ptr, void **buffer_start, + size_t *buffer_size); + +/** + * Get a circular buffer to operate on (to write). + * + * Same as sink_get_buffer() except that the size of circular buffer is returned as + * 16 bit samples count. The returned samples count simplifies pointer arithmetic in a + * samples process function. The data pointers are int16_t type. + * + * @param sink a handler to sink + * @param [in] req_size requested size of space + * @param [out] data_ptr a pointer to the space will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_samples number of s16 samples total in circular buffer + * + * @retval -ENODATA if req_size is bigger than free space + * + */ +int sink_get_buffer_s16(struct sof_sink *sink, size_t req_size, int16_t **data_ptr, + int16_t **buffer_start, int *buffer_samples); + +/** + * Get a circular buffer to operate on (to write). + * + * Same as sink_get_buffer() except that the size of circular buffer is returned as + * 32 bit samples count. The returned samples count simplifies pointer arithmetic in a + * samples process function. The data pointers are int32_t type. + * + * @param sink a handler to sink + * @param [in] req_size requested size of space + * @param [out] data_ptr a pointer to the space will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_samples number of s32 samples total in circular buffer + * + * @retval -ENODATA if req_size is bigger than free space + * + */ +int sink_get_buffer_s32(struct sof_sink *sink, size_t req_size, int32_t **data_ptr, + int32_t **buffer_start, int *buffer_samples); + +/** + * Commits that the buffer previously obtained by get_buffer is filled with data + * and ready to be used + * + * @param sink a handler to sink + * @param commit_size amount of data that the caller declares as valid + * if commit_size is bigger than the amount of data obtained before by get_buffer(), only + * the amount obtained before will be committed. That means - if somebody obtained a buffer, + * filled it with data and wants to commit it in whole, it may simple call + * commit_buffer with commit_size==MAXINT + * @return proper error code (0 on success) + */ +int sink_commit_buffer(struct sof_sink *sink, size_t commit_size); + +/** set of functions for retrieve audio parameters */ +int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt); + +static inline enum sof_ipc_frame sink_get_valid_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->valid_sample_fmt; +} + +static inline uint32_t sink_get_rate(struct sof_sink *sink) +{ + return sink->audio_stream_params->rate; +} + +static inline uint32_t sink_get_buffer_fmt(struct sof_sink *sink) +{ + return sink->audio_stream_params->buffer_fmt; +} + +/** + * initial set of audio parameters, provided in sof_ipc_stream_params + * + * @param sink a handler to sink + * @param params the set of parameters + * @param force_update tells the implementation that the params should override actual settings + * @return 0 if success + */ +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update); + +/** + * Set frame_align_shift and frame_align of stream according to byte_align and + * frame_align_req alignment requirement. Once the channel number,frame size + * are determined, the frame_align and frame_align_shift are determined too. + * these two feature will be used in audio_stream_get_avail_frames_aligned + * to calculate the available frames. it should be called in component prepare + * or param functions only once before stream copy. if someone forgets to call + * this first, there would be unexampled error such as nothing is copied at all. + * + * @param sink a handler to sink + * @param byte_align Processing byte alignment requirement. + * @param frame_align_req Processing frames alignment requirement. + * + * @return 0 if success + */ +int sink_set_alignment_constants(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); + +int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt); +int sink_set_rate(struct sof_sink *sink, unsigned int rate); +int sink_set_channels(struct sof_sink *sink, unsigned int channels); +int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt); +int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted); +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update); + +static inline size_t sink_get_min_free_space(struct sof_sink *sink) +{ + return sink->min_free_space; +} + +static inline uint32_t sink_get_id(struct sof_sink *sink) +{ + return sink->audio_stream_params->id; +} + +static inline uint32_t sink_get_pipeline_id(struct sof_sink *sink) +{ + return sink->audio_stream_params->pipeline_id; +} + +/** + * @brief hook to be called when a module connects to the API + * + * NOTE! it MUST be called at core that a module is bound to + */ +static inline int sink_bind(struct sof_sink *sink, struct processing_module *module) +{ + int ret = 0; + + if (sink->bound_module) + return -EBUSY; + + if (sink->ops->on_bind) + ret = sink->ops->on_bind(sink, module); + + if (!ret) + sink->bound_module = module; + + return ret; +} + +/** + * @brief hook to be called when a module disconnects from the API + * + * NOTE! it MUST be called at core that a module is bound to + */ +static inline int sink_unbind(struct sof_sink *sink) +{ + int ret = 0; + + if (!sink->bound_module) + return -EINVAL; + + if (sink->ops->on_unbind) + ret = sink->ops->on_unbind(sink); + + if (!ret) + sink->bound_module = NULL; + + return ret; +} + +static inline struct processing_module *sink_get_bound_module(struct sof_sink *sink) +{ + return sink->bound_module; +} + +static inline uint32_t sink_get_last_feeding_time(struct sof_sink *sink) +{ + return sink->ops->get_lft(sink); +} + +#endif /* __MODULE_AUDIO_SINK_API_H__ */ diff --git a/src/include/module/audio/source_api.h b/src/include/module/audio/source_api.h new file mode 100644 index 000000000000..556dead4a583 --- /dev/null +++ b/src/include/module/audio/source_api.h @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __MODULE_AUDIO_SOURCE_API_H__ +#define __MODULE_AUDIO_SOURCE_API_H__ + +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> + +#include "audio_stream.h" +#include "format.h" + +/** + * this is a definition of API to source of audio data + * + * THE SOURCE is any component in the system that have data stored somehow and can give the + * data outside at request. The source API does not define who and how has produced the data + * + * The user - a module - sees this as a producer that PROVIDES data for processing + * The IMPLEMENTATION - audio_stream, DP Queue - sees this API as a destination it must send data to + * * + * Examples of components that should expose source API: + * - DMIC + * Data are coming from the outside world, stores in tmp buffer and can be presented + * to the rest of the system using source_api + * - a memory ring buffer + * Data are coming from other module (usually using sink_api, but it does not matter in fact) + * + * The main advantage of using source API instead of just taking pointers to the data is that + * the data may be prepared at the moment the data receiver is requesting it. i.e. + * - cache may be written back/invalidated if necessary + * - data may be moved from circular to linear space + * - part of the buffer may be locked to prevent writing + * etc.etc. it depends on implementation of the data source + * + * Data in general are provided as a circular buffer and the data receiver should be able to + * deal with it. Of course if needed an implementation of source providing linear data can be + * implemented and used as a mid-layer for modules needing it. + * + * NOTE: the module should get a complete portion of data it needs for processing, process it + * than release. The reason is - the depending on the implementation, the calls may be + * expensive - may involve some data moving in memory, cache writebacks, etc. + */ + + /* forward def */ +struct sof_source; +struct sof_audio_stream_params; +struct sof_ipc_stream_params; +struct processing_module; + +/** + * this is a definition of internals of source API + * + * The clients of stream API should use access functions provided below! + * + */ + +struct source_ops { + /** + * see comment of source_get_data_available() + */ + size_t (*get_data_available)(struct sof_source *source); + + /** + * see comment of source_get_data_available() + */ + int (*get_data)(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, size_t *buffer_size); + + /** + * see comment of source_release_data() + */ + int (*release_data)(struct sof_source *source, size_t free_size); + + /** + * OPTIONAL: Notification to the source implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * source may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameteres are not supported + */ + int (*on_audio_format_set)(struct sof_source *source); + + /** + * OPTIONAL + * see source_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for source_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req); + + /** + * OPTIONAL + * events called when a module is starting / finishing using of the API + * on the core that the module and API will executed on + */ + int (*on_bind)(struct sof_source *source, struct processing_module *module); + int (*on_unbind)(struct sof_source *source); +}; + +/** internals of source API. NOT TO BE MODIFIED OUTSIDE OF source_api.c */ +struct sof_source { + const struct source_ops *ops; + size_t requested_read_frag_size; /* keeps size of data obtained by get_data() */ + size_t num_of_bytes_processed; /* processed bytes counter */ + size_t min_available; /* minimum data available required by the module using + * source + * it is module's IBS as declared in module bind IPC + */ + struct processing_module *bound_module; /* a pointer module that is using source API */ + struct sof_audio_stream_params *audio_stream_params; +}; + +/** + * + * Public functions + * + */ + +/** + * Retrieves size of available data (in bytes) + * return number of bytes that are available for immediate use + */ +static inline size_t source_get_data_available(struct sof_source *source) +{ + return source->ops->get_data_available(source); +} + +static inline enum sof_ipc_frame source_get_frm_fmt(struct sof_source *source) +{ + return source->audio_stream_params->frame_fmt; +} + +static inline unsigned int source_get_channels(struct sof_source *source) +{ + return source->audio_stream_params->channels; +} + +/** get size of a single audio frame (in bytes) */ +size_t source_get_frame_bytes(struct sof_source *source); + +/** + * Retrieves size of available data (in frames) + * return number of frames that are available for immediate use + */ +size_t source_get_data_frames_available(struct sof_source *source); + +/** + * Retrieves a fragment of circular data to be used by the caller (to read) + * After calling get_data, the data are guaranteed to be available + * for exclusive use (read only) + * if the provided pointers are cached, it is guaranteed that the caller may safely use it without + * any additional cache operations + * + * The caller MUST take care of data circularity based on provided pointers + * + * Depending on implementation - there may be a way to have several receivers of the same + * data, as long as the receiver respects that data are read-only and won'do anything + * fancy with cache handling itself + * + * some implementation data may be stored in linear buffer + * in that case: + * data_ptr = buffer_start + * buffer_end = data_ptr + req_size + * buffer_size = req_size + * + * and the data receiver may use it as usual, rollover will simple never occur + * NOTE! the caller MUST NOT assume that pointers to start/end of the circular buffer + * are constant. They may change between calls + * + * @param source a handler to source + * @param [in] req_size requested size of data. + * @param [out] data_ptr a pointer to data will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_size size of circular buffer + * + * @retval -ENODATA if req_size is bigger than available data + */ +int source_get_data(struct sof_source *source, size_t req_size, void const **data_ptr, + void const **buffer_start, size_t *buffer_size); + +/** + * Retrieves a fragment of circular data (to read) + * + * Same as source_get_data() except that the size of circular buffer is returned as + * 16 bit samples count. The returned samples count simplifies pointer arithmetic in a + * samples process function. The data pointers are int16_t type. + * + * @param source a handler to source + * @param [in] req_size requested size of data. + * @param [out] data_ptr a pointer to data will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_samples number of 16 bit samples total in circular buffer + * + * @retval -ENODATA if req_size is bigger than available data + */ +int source_get_data_s16(struct sof_source *source, size_t req_size, int16_t const **data_ptr, + int16_t const **buffer_start, int *buffer_samples); + +/** + * Retrieves a fragment of circular data (to read) + * + * Same as source_get_data() except that the size of circular buffer is returned as + * 32 bit samples count. The returned samples count simplifies pointer arithmetic in a + * samples process function. The data pointers are int32_t type. + * + * @param source a handler to source + * @param [in] req_size requested size of data. + * @param [out] data_ptr a pointer to data will be provided there + * @param [out] buffer_start pointer to circular buffer start + * @param [out] buffer_samples number of 32 bit samples total in circular buffer + * + * @retval -ENODATA if req_size is bigger than available data + */ +int source_get_data_s32(struct sof_source *source, size_t req_size, int32_t const **data_ptr, + int32_t const **buffer_start, int *buffer_samples); + +/** + * Releases fragment previously obtained by source_get_data() + * Once called, the data are no longer available for the caller + * + * @param source a handler to source + * @param free_size amount of data that the caller declares as "never needed again" + * if free_size == 0 the source implementation MUST keep all data in memory and make them + * available again at next get_data() call + * if free_size is bigger than the amount of data obtained before by get_data(), only + * the amount obtained before will be freed. That means - if somebody obtained some data, + * processed it and won't need it again, it may simple call put_data with free_size==MAXINT + * + * @return proper error code (0 on success) + */ +int source_release_data(struct sof_source *source, size_t free_size); + +/** set of functions for retrieve audio parameters */ +static inline enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source) +{ + return source->audio_stream_params->valid_sample_fmt; +} + +static inline unsigned int source_get_rate(struct sof_source *source) +{ + return source->audio_stream_params->rate; +} + +static inline uint32_t source_get_buffer_fmt(struct sof_source *source) +{ + return source->audio_stream_params->buffer_fmt; +} + +static inline size_t source_get_min_available(struct sof_source *source) +{ + return source->min_available; +} + +static inline uint32_t source_get_id(struct sof_source *source) +{ + return source->audio_stream_params->id; +} + +static inline uint32_t source_get_pipeline_id(struct sof_source *source) +{ + return source->audio_stream_params->pipeline_id; +} + +/** + * @brief hook to be called when a module connects to the API + * + * NOTE! it MUST be called at core that a module is bound to + */ +static inline int source_bind(struct sof_source *source, struct processing_module *module) +{ + int ret = 0; + + if (source->bound_module) + return -EBUSY; + + if (source->ops->on_bind) + ret = source->ops->on_bind(source, module); + + if (!ret) + source->bound_module = module; + + return ret; +} + +/** + * @brief hook to be called when a module disconnects from the API + * + * NOTE! it MUST be called at core that a module is bound to + */ +static inline int source_unbind(struct sof_source *source) +{ + int ret = 0; + + if (!source->bound_module) + return -EINVAL; + + if (source->ops->on_unbind) + ret = source->ops->on_unbind(source); + + if (!ret) + source->bound_module = NULL; + + return ret; +} + +static inline struct processing_module *source_get_bound_module(struct sof_source *source) +{ + return source->bound_module; +} + +static inline enum sof_audio_buffer_state source_get_state(const struct sof_source *source) +{ + return source->audio_stream_params->state; +} + +#endif /* __MODULE_AUDIO_SOURCE_API_H__ */ diff --git a/src/include/module/crossover/crossover_common.h b/src/include/module/crossover/crossover_common.h new file mode 100644 index 000000000000..d238ff7c1008 --- /dev/null +++ b/src/include/module/crossover/crossover_common.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Sebastiano Carlucci <scarlucci@google.com> + */ + +#ifndef __SOF_CROSSOVER_COMMON_H__ +#define __SOF_CROSSOVER_COMMON_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> + +/* Number of sinks for a 2 way crossover filter */ +#define CROSSOVER_2WAY_NUM_SINKS 2 +/* Number of sinks for a 3 way crossover filter */ +#define CROSSOVER_3WAY_NUM_SINKS 3 +/* Number of sinks for a 4 way crossover filter */ +#define CROSSOVER_4WAY_NUM_SINKS 4 +/* Number of delay slots allocated for LR4 Filters */ +#define CROSSOVER_NUM_DELAYS_LR4 4 +/* Maximum number of LR4 highpass OR lowpass filters */ +#define CROSSOVER_MAX_LR4 3 +/* Maximum Number of sinks allowed in config */ +#define SOF_CROSSOVER_MAX_STREAMS 4 + +/** + * Stores the state of one channel of the Crossover filter + */ +struct crossover_state { + /* Store the state for each LR4 filter. */ + struct iir_state_df1 lowpass[CROSSOVER_MAX_LR4]; + struct iir_state_df1 highpass[CROSSOVER_MAX_LR4]; +}; + +typedef void (*crossover_split)(int32_t in, int32_t out[], + struct crossover_state *state); + +extern const crossover_split crossover_split_fnmap[]; + +/* crossover init function */ +int crossover_init_coef_ch(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, + struct crossover_state *ch_state, + int32_t num_sinks); + +/** + * \brief Reset the state of an LR4 filter. + */ +static inline void crossover_reset_state_lr4(struct processing_module *mod, + struct iir_state_df1 *lr4) +{ + mod_free(mod, lr4->coef); + mod_free(mod, lr4->delay); + + lr4->coef = NULL; + lr4->delay = NULL; +} + +/** + * \brief Reset the state (coefficients and delay) of the crossover filter + * of a single channel. + */ +static inline void crossover_reset_state_ch(struct processing_module *mod, + struct crossover_state *ch_state) +{ + int i; + + for (i = 0; i < CROSSOVER_MAX_LR4; i++) { + crossover_reset_state_lr4(mod, &ch_state->lowpass[i]); + crossover_reset_state_lr4(mod, &ch_state->highpass[i]); + } +} + +/** + * \brief Returns Crossover split function. + */ +static inline crossover_split crossover_find_split_func(int32_t num_sinks) +{ + if (num_sinks < CROSSOVER_2WAY_NUM_SINKS || + num_sinks > CROSSOVER_4WAY_NUM_SINKS) + return NULL; + // The functions in the map are offset by 2 indices. + return crossover_split_fnmap[num_sinks - CROSSOVER_2WAY_NUM_SINKS]; +} + +#endif /* __SOF_CROSSOVER_COMMON_H__ */ diff --git a/src/include/module/iadk/adsp_error_code.h b/src/include/module/iadk/adsp_error_code.h new file mode 100644 index 000000000000..4d3382de918a --- /dev/null +++ b/src/include/module/iadk/adsp_error_code.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 - 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_IADK_ADSP_ERROR_CODE_H__ +#define __MODULE_IADK_ADSP_ERROR_CODE_H__ + +#include <stdint.h> + +/** + * Defines error codes that are returned in the ADSP project. + * NOTE: intel_adsp::ErrorCode should be merged into this namespaceless + * type to be used in 3rd party's C code. + */ +typedef uint32_t AdspErrorCode; + + /* Reports no error */ +#define ADSP_NO_ERROR 0 +/* Reports that some parameters passed to the method are invalid */ +#define ADSP_INVALID_PARAMETERS 1 +/* Reports that the system or resource is busy. */ +#define ADSP_BUSY_RESOURCE 4 +/** + * Module has detected some unexpected critical situation (e.g. memory corruption). + * Upon this error code the ADSP System is asked to stop any interactions with the module + * instance. + */ +#define ADSP_FATAL_FAILURE 6 +/* Report out of memory. */ +#define ADSP_OUT_OF_MEMORY 15 +/* Report invalid target. */ +#define ADSP_INVALID_TARGET 142 +/* Service is not supported on target platform. */ +#define ADSP_SERVICE_UNAVAILABLE 143 + +/* SystemAgentInterface */ +#define ADSP_MODULE_CREATION_FAILURE 16 + +/* ProcessingModuleFactoryInterface */ + +/* Reports that the given value of Input Buffer Size is invalid */ +#define ADSP_INVALID_IBS 17 +/* Reports that the given value of Output Buffer Size is invalid */ +#define ADSP_INVALID_OBS 18 +/* Reports that the given value of Cycles Per Chunk processing is invalid */ +#define ADSP_INVALID_CPC 19 +/* Reports that the settings provided for module creation are invalid */ +#define ADSP_INVALID_SETTINGS 20 + +/* ProcessingModuleInterface */ +/* Reports that the message content given for configuration is invalid */ +#define ADSP_INVALID_CONFIGURATION 21 + +/* Reports that the module does not support retrieval of its current configuration information */ +#define ADSP_NO_CONFIGURATION 22 + +#endif /* __MODULE_IADK_ADSP_ERROR_CODE_H__ */ diff --git a/src/include/module/ipc/stream.h b/src/include/module/ipc/stream.h new file mode 100644 index 000000000000..6e49d9f75cf2 --- /dev/null +++ b/src/include/module/ipc/stream.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 - 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_IPC_STREAM_H__ +#define __MODULE_IPC_STREAM_H__ + +#define SOF_IPC_MAX_CHANNELS 8 + +/* stream PCM frame format */ +enum sof_ipc_frame { + SOF_IPC_FRAME_S16_LE = 0, + SOF_IPC_FRAME_S24_4LE, + SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_FLOAT, + /* other formats here */ + SOF_IPC_FRAME_S24_3LE, + SOF_IPC_FRAME_S24_4LE_MSB, + SOF_IPC_FRAME_U8, + SOF_IPC_FRAME_S16_4LE, /* 16-bit in 32-bit container */ + SOF_IPC_FRAME_A_LAW, + SOF_IPC_FRAME_MU_LAW, + SOF_IPC_FRAME_INVALID, /* keep last */ +}; + +#endif /* __MODULE_IPC_STREAM_H__ */ diff --git a/src/include/module/ipc4/base-config.h b/src/include/module/ipc4/base-config.h new file mode 100644 index 000000000000..e5a5b49effd5 --- /dev/null +++ b/src/include/module/ipc4/base-config.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 - 2023 Intel Corporation. All rights reserved. + */ + +/* + * This file contains structures that are exact copies of an existing ABI used + * by IOT middleware. They are Intel specific and will be used by one middleware. + * + * Some of the structures may contain programming implementations that makes them + * unsuitable for generic use and general usage. + * + * This code is mostly copied "as-is" from existing C++ interface files hence the use of + * different style in places. The intention is to keep the interface as close as possible to + * original so it's easier to track changes with IPC host code. + */ + +/** + * \file include/ipc4/base-config.h + * \brief IPC4 global definitions. + * NOTE: This ABI uses bit fields and is non portable. + */ + +#ifndef __MODULE_IPC4_BASE_CONFIG_H__ +#define __MODULE_IPC4_BASE_CONFIG_H__ + +#include <stdint.h> + +enum ipc4_sampling_frequency { + IPC4_FS_8000HZ = 8000, + IPC4_FS_11025HZ = 11025, + IPC4_FS_12000HZ = 12000, /**< Mp3, AAC, SRC only */ + IPC4_FS_16000HZ = 16000, + IPC4_FS_18900HZ = 18900, /**< SRC only for 44100 */ + IPC4_FS_22050HZ = 22050, + IPC4_FS_24000HZ = 24000, /**< Mp3, AAC, SRC only */ + IPC4_FS_32000HZ = 32000, + IPC4_FS_37800HZ = 37800, /**< SRC only for 44100 */ + IPC4_FS_44100HZ = 44100, + IPC4_FS_48000HZ = 48000, /**< Default */ + IPC4_FS_64000HZ = 64000, /**< AAC, SRC only */ + IPC4_FS_88200HZ = 88200, /**< AAC, SRC only */ + IPC4_FS_96000HZ = 96000, /**< AAC, SRC only */ + IPC4_FS_176400HZ = 176400, /**< SRC only */ + IPC4_FS_192000HZ = 192000, /**< SRC only */ + IPC4_FS_INVALID +}; + +enum ipc4_bit_depth { + IPC4_DEPTH_8BIT = 8, /**< 8 bits depth */ + IPC4_DEPTH_16BIT = 16, /**< 16 bits depth */ + IPC4_DEPTH_24BIT = 24, /**< 24 bits depth - Default */ + IPC4_DEPTH_32BIT = 32, /**< 32 bits depth */ + IPC4_DEPTH_64BIT = 64, /**< 64 bits depth */ + IPC4_DEPTH_INVALID +}; + +enum ipc4_channel_config { + IPC4_CHANNEL_CONFIG_MONO = 0, /**< one channel only */ + IPC4_CHANNEL_CONFIG_STEREO = 1, /**< L & R */ + IPC4_CHANNEL_CONFIG_2_POINT_1 = 2, /**< L, R & LFE; PCM only */ + IPC4_CHANNEL_CONFIG_3_POINT_0 = 3, /**< L, C & R; MP3 & AAC only */ + IPC4_CHANNEL_CONFIG_3_POINT_1 = 4, /**< L, C, R & LFE; PCM only */ + IPC4_CHANNEL_CONFIG_QUATRO = 5, /**< L, R, Ls & Rs; PCM only */ + IPC4_CHANNEL_CONFIG_4_POINT_0 = 6, /**< L, C, R & Cs; MP3 & AAC only */ + IPC4_CHANNEL_CONFIG_5_POINT_0 = 7, /**< L, C, R, Ls & Rs */ + IPC4_CHANNEL_CONFIG_5_POINT_1 = 8, /**< L, C, R, Ls, Rs & LFE */ + IPC4_CHANNEL_CONFIG_DUAL_MONO = 9, /**< one channel replicated in two */ + /**< Stereo (L,R) in 4 slots, 1st stream: [ L, R, -, - ] */ + IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_0 = 10, + /**< Stereo (L,R) in 4 slots, 2nd stream: [ -, -, L, R ] */ + IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_1 = 11, + IPC4_CHANNEL_CONFIG_7_POINT_1 = 12, /**< L, C, R, Ls, Rs & LFE., LS, RS */ + IPC4_CHANNEL_CONFIG_INVALID +}; + +enum ipc4_channel_index { + CHANNEL_LEFT = 0, + CHANNEL_CENTER = 1, + CHANNEL_RIGHT = 2, + CHANNEL_LEFT_SURROUND = 3, + CHANNEL_CENTER_SURROUND = 3, + CHANNEL_RIGHT_SURROUND = 4, + CHANNEL_LEFT_SIDE = 5, + CHANNEL_RIGHT_SIDE = 6, + CHANNEL_LFE = 7, + CHANNEL_INVALID = 0xF, +}; + +enum ipc4_interleaved_style { + IPC4_CHANNELS_INTERLEAVED = 0, + IPC4_CHANNELS_NONINTERLEAVED = 1, +}; + +enum ipc4_sample_type { + IPC4_TYPE_MSB_INTEGER = 0, /**< integer with Most Significant Byte first */ + IPC4_TYPE_LSB_INTEGER = 1, /**< integer with Least Significant Byte first */ + IPC4_TYPE_SIGNED_INTEGER = 2, + IPC4_TYPE_UNSIGNED_INTEGER = 3, + IPC4_TYPE_FLOAT = 4, + IPC4_TYPE_A_LAW = 5, + IPC4_TYPE_MU_LAW = 6, +}; + +enum ipc4_stream_type { + IPC4_STREAM_PCM = 0, /**< PCM stream */ + IPC4_STREAM_MP3 = 1, /**< MP3 encoded stream */ + IPC4_STREAM_AAC = 2, /**< AAC encoded stream */ + /* TODO: revisit max stream type count. Currently + * it aligns with windows audio driver and we will + * update all when more types are supported + */ + IPC4_STREAM_COUNT = 3, + IPC4_STREAM_INVALID = 0xFF +}; + +struct ipc4_audio_format { + enum ipc4_sampling_frequency sampling_frequency; + enum ipc4_bit_depth depth; + uint32_t ch_map; + enum ipc4_channel_config ch_cfg; + uint32_t interleaving_style; + uint32_t channels_count : 8; + uint32_t valid_bit_depth : 8; + enum ipc4_sample_type s_type : 8; + uint32_t reserved : 8; +} __attribute__((packed, aligned(4))); + +struct ipc4_base_module_cfg { + uint32_t cpc; /**< the max count of Cycles Per Chunk processing */ + uint32_t ibs; /**< input Buffer Size (in bytes) */ + uint32_t obs; /**< output Buffer Size (in bytes) */ + uint32_t is_pages; /**< number of physical pages used */ + struct ipc4_audio_format audio_fmt; +} __attribute__((packed, aligned(4))); + +struct ipc4_input_pin_format { + uint32_t pin_index; /**< index of the pin */ + uint32_t ibs; /**< specifies input frame size (in bytes) */ + struct ipc4_audio_format audio_fmt; /**< format of the input data */ +} __attribute__((packed, aligned(4))); + +struct ipc4_output_pin_format { + uint32_t pin_index; /**< index of the pin */ + uint32_t obs; /**< specifies output frame size (in bytes) */ + struct ipc4_audio_format audio_fmt; /**< format of the output data */ +} __attribute__((packed, aligned(4))); + +struct ipc4_base_module_cfg_ext { + /* specifies number of items in input_pins array. Maximum size is 8 */ + uint16_t nb_input_pins; + /* specifies number of items in output_pins array. Maximum size is 8 */ + uint16_t nb_output_pins; + uint8_t reserved[12]; + /* Specifies format of input pins followed by output pins. + * Pin format arrays may be non-continuous i.e. may contain pin #0 format + * followed by pin #2 format in case pin #1 will not be in use. + * FW assigned format of the pin based on pin_index, not on a position of + * the item in the array. Applies to both input and output pins. + */ + uint8_t pin_formats[]; +} __attribute__((packed, aligned(4))); + +#define ipc4_calc_base_module_cfg_ext_size(in_pins, out_pins) \ + (sizeof(struct ipc4_base_module_cfg_ext) + \ + (in_pins) * sizeof(struct ipc4_input_pin_format) + \ + (out_pins) * sizeof(struct ipc4_output_pin_format)) + +/* Struct to combine the base_cfg and base_cfg_ext for easier parsing */ +struct ipc4_base_module_extended_cfg { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_base_module_cfg_ext base_cfg_ext; +} __attribute__((packed, aligned(4))); + +/* This enum defines short 16bit parameters common for all modules. + * Value of module specific parameters have to be less than 0x3000. + */ +enum ipc4_base_module_params { + /* handled inside LargeConfigGet of module instance */ + IPC4_MOD_INST_PROPS = 0xFE, + /* handled inside ConfigSet of module instance */ + IPC4_MOD_INST_ENABLE = 0x3000 +}; + +struct ipc4_pin_props { + /* type of the connected stream. + * Holds an "enum ipc4_stream_type" value. Fixed-size because of #9378 + */ + uint32_t stream_type; + + /* audio format of the stream. The content is valid in case of ePcm stream_type. */ + struct ipc4_audio_format format; + + /* unique ID of the physical queue connected to the pin. + * If there is no queue connected, then -1 (invalid queue ID) is set + */ + uint32_t phys_queue_id; +} __attribute__((packed, aligned(4))); + +struct ipc4_pin_list_info { + uint32_t pin_count; + struct ipc4_pin_props pin_info[1]; +} __attribute__((packed, aligned(4))); + +/* structure describing module instance properties used in response + * to module LargeConfigGet with MOD_INST_PROPS parameter. + */ +struct ipc4_module_instance_props { + uint32_t id; + uint32_t dp_queue_type; + uint32_t queue_alignment; + uint32_t cp_usage_mask; + uint32_t stack_bytes; + uint32_t bss_total_bytes; + uint32_t bss_used_bytes; + uint32_t ibs_bytes; + uint32_t obs_bytes; + uint32_t cpc; + uint32_t cpc_peak; + struct ipc4_pin_list_info input_queues; + struct ipc4_pin_list_info output_queues; + uint32_t input_gateway; + uint32_t output_gateway; +} __attribute__((packed, aligned(4))); + +/* Reflects the last two entries in ModuleInstanceProps sttructure */ +struct ipc4_in_out_gateway { + uint32_t input_gateway; + uint32_t output_gateway; +} __attribute__((packed, aligned(4))); + +/* this structure may be used by modules to carry + * short 16bit parameters as part of the IxC register content. + */ +union ipc4_cfg_param_id_data { + uint32_t dw; + struct { + uint32_t data16 : 16; /* Input/Output small config data */ + uint32_t id : 14; /* input parameter ID */ + uint32_t _rsvd : 2; + } f; +} __attribute__((packed, aligned(4))); + +#endif /* __MODULE_IPC4_BASE_CONFIG_H__ */ diff --git a/src/include/module/module/api_ver.h b/src/include/module/module/api_ver.h new file mode 100644 index 000000000000..35aedb0305d7 --- /dev/null +++ b/src/include/module/module/api_ver.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ + +#ifndef __MODULE_MODULE_API_VER_H__ +#define __MODULE_MODULE_API_VER_H__ + +#include <stdint.h> + +#define MODULE_API_VERSION_ENCODE(a, b, c) \ + (((0x3FF & (a)) << 20) | ((0x3FF & (b)) << 10) | (0x3FF & (c))) + +#define SOF_MODULE_API_BUILD_INFO_FORMAT 0x80000000 + +/* + * Api version 5.0.0 for sof loadable modules + */ + +#define SOF_MODULE_API_MAJOR_VERSION 5 +#define SOF_MODULE_API_MIDDLE_VERSION 0 +#define SOF_MODULE_API_MINOR_VERSION 1 + +#define SOF_MODULE_API_CURRENT_VERSION MODULE_API_VERSION_ENCODE(SOF_MODULE_API_MAJOR_VERSION, \ + SOF_MODULE_API_MIDDLE_VERSION, SOF_MODULE_API_MINOR_VERSION) + +union sof_module_api_version { + uint32_t full; + struct { + uint32_t minor : 10; + uint32_t middle : 10; + uint32_t major : 10; + uint32_t reserved : 2; + } fields; +}; + +struct sof_module_api_build_info { + uint32_t format; + union sof_module_api_version api_version_number; +}; + +#define DECLARE_LOADABLE_MODULE_API_VERSION(name) \ +struct sof_module_api_build_info name ## _build_info __attribute__((section(".buildinfo"))) = { \ + SOF_MODULE_API_BUILD_INFO_FORMAT, SOF_MODULE_API_CURRENT_VERSION \ +} + +#endif /* __MODULE_MODULE_API_VER_H__ */ diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h new file mode 100644 index 000000000000..657673099d60 --- /dev/null +++ b/src/include/module/module/base.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_MODULE_BASE__ +#define __MODULE_MODULE_BASE__ + +#include <stdint.h> +#include <stddef.h> +#include <stdbool.h> + +#include "interface.h" +#include "../ipc4/base-config.h" + +#ifdef SOF_MODULE_API_PRIVATE +#include <sof/list.h> +#endif + +#define module_get_private_data(mod) ((mod)->priv.private) +#define module_set_private_data(mod, data) ((mod)->priv.private = data) + +/** + * \struct module_ext_init_data + * \brief Container for found ext init object pointers + * This struct contains pointers that point to IPC payload directly. The + * module should store what it needs in its init() callback as the data + * is not valid after that. + */ +struct ipc4_module_init_ext_obj_dp_data; +struct module_ext_init_data { + const struct ipc4_module_init_ext_obj_dp_data *dp_data; + const void *module_data; + size_t module_data_size; +}; + +/** + * \struct module_config + * \brief Module config container, used for both config types. + */ +struct module_config { + size_t size; /**< Specifies the size of whole config */ + bool avail; /**< Marks config as available to use.*/ + void *data; /**< tlv config, a pointer to memory where config is stored. */ + const void *init_data; /**< Initial IPC configuration. */ +#if CONFIG_IPC_MAJOR_4 + struct ipc4_base_module_cfg base_cfg; + uint8_t nb_input_pins; + uint8_t nb_output_pins; + struct ipc4_input_pin_format *input_pins; + struct ipc4_output_pin_format *output_pins; + struct module_ext_init_data *ext_data; /**< IPC payload pointers, NULL after init() */ +#endif +}; + +/* + * A structure containing a module's private data, intended for its exclusive use. + * + * This structure should contain only fields that are used be a module. + * All other fields, used exclusively by SOF must be moved to another structure! + */ +struct module_data { + void *private; /**< self object, memory tables etc here */ + struct module_config cfg; /**< module configuration data */ + + /* + * Fields below can only be accessed by the SOF and must be moved to a new structure. + * Below #ifdef is a temporary solution used until work on separating a common interface + * for loadable modules is completed. + */ +#ifdef SOF_MODULE_API_PRIVATE + enum module_state state; + size_t new_cfg_size; /**< size of new module config data */ + void *runtime_params; + struct module_resources resources; /**< resources allocated by module */ + struct module_processing_data mpd; /**< shared data comp <-> module */ +#endif /* SOF_MODULE_PRIVATE */ +}; + +enum module_processing_type { + MODULE_PROCESS_TYPE_SOURCE_SINK, + MODULE_PROCESS_TYPE_STREAM, + MODULE_PROCESS_TYPE_RAW, +}; + +struct userspace_context; +struct k_mem_domain; + +/* + * A pointer to this structure is passed to module API functions (from struct module_interface). + * This structure should contain only fields that should be available to a module. + * All other fields, used exclusively by SOF must be moved to another structure! + */ +struct processing_module { + struct module_data priv; /**< module private data */ + uint32_t period_bytes; /** pipeline period bytes */ + + /* + * Fields below can only be accessed by the SOF and must be moved to a new structure. + * Below #ifdef is a temporary solution used until work on separating a common interface + * for loadable modules is completed. + */ +#ifdef SOF_MODULE_API_PRIVATE + struct sof_ipc_stream_params *stream_params; + /* list of sink buffers to save produced output, to be used in Raw data + * processing mode + */ + struct list_item raw_data_buffers_list; + + /* + * This is a temporary change in order to support the trace messages in the modules. This + * will be removed once the trace API is updated. + */ + struct comp_dev *dev; + uint32_t deep_buff_bytes; /**< copy start threshold */ + uint32_t output_buffer_size; /**< size of local buffer to save produced samples */ + + /* number of sinks / sources and (when in use) input_buffers / input_buffers */ + uint32_t num_of_sources; + uint32_t num_of_sinks; + + /* sink and source handlers for the module */ + struct sof_sink *sinks[CONFIG_MODULE_MAX_CONNECTIONS]; + struct sof_source *sources[CONFIG_MODULE_MAX_CONNECTIONS]; + + /* this is used in case of raw data or audio_stream mode + * number of buffers described by fields: + * input_buffers - num_of_sources + * output_buffers - num_of_sinks + */ + struct input_stream_buffer *input_buffers; + struct output_stream_buffer *output_buffers; + struct comp_buffer *source_comp_buffer; /**< single source component buffer */ + struct comp_buffer *sink_comp_buffer; /**< single sink compoonent buffer */ + + /* module-specific flags for comp_verify_params() */ + uint32_t verify_params_flags; + + /* indicates that this DP module did not yet reach its first deadline and + * no data should be passed yet to next LL module + * + * why: lets assume DP with 10ms period (a.k.a a deadline). It starts and finishes + * Earlier, i.e. in 2ms providing 10ms of data. LL starts consuming data in 1ms chunks and + * will drain 10ms buffer in 10ms, expecting a new portion of data on 11th ms + * BUT - the DP module deadline is still 10ms, regardless if it had finished earlier + * and it is completely fine that processing in next cycle takes full 10ms - as long as it + * fits into the deadline. + * It may lead to underruns: + * + * LL1 (1ms) ---> DP (10ms) -->LL2 (1ms) + * + * ticks 0..9 -> LL1 is producing 1ms data portions, DP is waiting, LL2 is waiting + * tick 10 - DP has enough data to run, it starts processing + * tick 12 - DP finishes earlier, LL2 starts consuming, LL1 is producing data + * ticks 13-19 LL1 is producing data, LL2 is consuming data (both in 1ms chunks) + * tick 20 - DP starts processing a new portion of 10ms data, having 10ms to finish + * !!!! but LL2 has already consumed 8ms !!!! + * tick 22 - LL2 is consuming the last 1ms data chunk + * tick 23 - DP is still processing, LL2 has no data to process + * !!! UNDERRUN !!!! + * tick 19 - DP finishes properly in a deadline time + * + * Solution: even if DP finishes before its deadline, the data must be held till + * deadline time, so LL2 may start processing no earlier than tick 20 + */ + bool dp_startup_delay; + + /* flag to indicate module does not pause */ + bool no_pause; + + /* + * flag to indicate that the sink buffer writeback should be skipped. It will be handled + * in the module's process callback + */ + bool skip_sink_buffer_writeback; + + /* + * flag to indicate that the source buffer invalidate should be skipped. It will be handled + * in the module's process callback + */ + bool skip_src_buffer_invalidate; + + /* + * True for module with one source component buffer and one sink component buffer + * to enable reduction of module processing overhead. False if component uses + * multiple buffers. + */ + bool stream_copy_single_to_single; + + /* total processed data after stream started */ + uint64_t total_data_consumed; + uint64_t total_data_produced; + + /* max source/sinks supported by the module */ + uint32_t max_sources; + uint32_t max_sinks; + + enum module_processing_type proc_type; +#if CONFIG_USERSPACE + struct userspace_context *user_ctx; + struct k_mem_domain *mdom; +#endif /* CONFIG_USERSPACE */ +#endif /* SOF_MODULE_PRIVATE */ +}; + +#endif /* __MODULE_MODULE_BASE__ */ diff --git a/src/include/module/module/interface.h b/src/include/module/module/interface.h new file mode 100644 index 000000000000..26c176aee9b1 --- /dev/null +++ b/src/include/module/module/interface.h @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_MODULE_INTERFACE__ +#define __MODULE_MODULE_INTERFACE__ + +#include <stdint.h> +#include <stdbool.h> + +/** + * \enum module_cfg_fragment_position + * \brief Fragment position in config + * MODULE_CFG_FRAGMENT_FIRST: first fragment of the large configuration + * MODULE_CFG_FRAGMENT_SINGLE: only fragment of the configuration + * MODULE_CFG_FRAGMENT_LAST: last fragment of the configuration + * MODULE_CFG_FRAGMENT_MIDDLE: intermediate fragment of the large configuration + */ +enum module_cfg_fragment_position { + MODULE_CFG_FRAGMENT_MIDDLE = 0, + MODULE_CFG_FRAGMENT_FIRST, + MODULE_CFG_FRAGMENT_LAST, + MODULE_CFG_FRAGMENT_SINGLE, +}; + +/** + * \enum module_processing_mode + * MODULE_PROCESSING_NORMAL: Indicates that module is expected to apply its custom processing on + * the input signal + * MODULE_PROCESSING_BYPASS: Indicates that module is expected to skip custom processing on + * the input signal and act as a passthrough component + */ + +enum module_processing_mode { + MODULE_PROCESSING_NORMAL = 0, + MODULE_PROCESSING_BYPASS, +}; + +/** + * \struct input_stream_buffer + * \brief Input stream buffer + */ +struct input_stream_buffer { + void *data; /* data stream buffer */ + uint32_t size; /* size of data in the buffer */ + uint32_t consumed; /* number of bytes consumed by the module */ + + /* Indicates end of stream condition has occurred on the input stream */ + bool end_of_stream; +}; + +/** + * \struct output_stream_buffer + * \brief Output stream buffer + */ +struct output_stream_buffer { + void *data; /* data stream buffer */ + uint32_t size; /* size of data in the buffer */ +}; + +struct processing_module; +struct sof_source; +struct sof_sink; +struct bind_info; +struct bind_info; + +/* + * This structure may be used by modules to carry short 16bit parameters. + */ +union config_param_id_data { + uint32_t dw; + struct { + uint32_t data16 : 16; /* Input/Output small config data */ + uint32_t id : 14; /* input parameter ID */ + uint32_t _rsvd : 2; + } f; +}; + +/** + * \struct module_interface + * \brief 3rd party processing module interface + * + * Module operations can be optimized for performance (default - no action) or + * for memory and power efficiency (opt in using __cold). It is recommended that + * module authors review their modules for non time sensitive code and mark it + * using __cold based on the descriptions below. This will ensure modules + * maintain peak performance and peak power/memory efficiency. Similarly cold + * read-only data can be marked with __cold_rodata. In cases where a subset of + * cold data has to be accessed from hot paths, it can be copied to fast memory, + * using the \c fast_get() API and then released using \c fast_put(). + */ +struct module_interface { + /** + * Module specific initialization procedure, called as part of + * module_adapter component creation in .new(). Usually can be __cold + */ + int (*init)(struct processing_module *mod); + + /** + * (optional) Module specific prepare procedure, called as part of module_adapter + * component preparation in .prepare(). Usually can be __cold + */ + int (*prepare)(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * (optional) return true if the module is ready to process + * This procedure should check if the module is ready for immediate + * processing. + * + * NOTE! the call MUST NOT perform any time consuming operations + * + * this procedure will always return true for LL module + * + * For DP there's a default implementation that will do a simple check if there's + * at least IBS bytes of data on first source and at least OBS free space on first sink + * + * In case more sophisticated check is needed the method should be implemented in + * the module. Usually shouldn't be __cold + */ + bool (*is_ready_to_process)(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * Module specific processing procedure + * This procedure is responsible to consume + * samples provided by the module_adapter and produce/output the processed + * ones back to module_adapter. + * + * there are 3 versions of the procedure, the difference is the format of + * input/output data + * + * the module MUST implement one and ONLY one of them + * + * process_audio_stream and process_raw_data are depreciated and will be removed + * once pipeline learns to use module API directly (without module adapter) + * modules that need such processing should use proper wrappers + * + * process + * - sources are handlers to source API struct source*[] + * - sinks are handlers to sink API struct sink*[] + * + * Usually shouldn't be __cold + */ + int (*process)(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + + /** + * process_audio_stream (depreciated) + * - sources are input_stream_buffer[] + * - sources[].data is a pointer to audio_stream structure + * - sinks are output_stream_buffer[] + * - sinks[].data is a pointer to audio_stream structure + * + * It can be used by modules that support 1:1, 1:N, N:1 sources:sinks configuration. + * + * Usually shouldn't be __cold + */ + int (*process_audio_stream)(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers); + + /** + * process_raw_data (depreciated) + * - sources are input_stream_buffer[] + * - sources[].data is a pointer to raw audio data + * - sinks are output_stream_buffer[] + * - sinks[].data is a pointer to raw audio data + * + * Usually shouldn't be __cold + */ + int (*process_raw_data)(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers); + + /** + * (optional) Set module configuration parameter + * + * Using Module Config Set command, host driver may send a parameter + * that fits into the header (a very short one), packed along with parameter id. + * + * param_id_data specifies both ID of the parameter, defined by the module + * and value of the parameter. + * It is up to the module how to distribute bits to ID and value of the parameter. + */ + int (*set_config_param)(struct processing_module *mod, uint32_t param_id_data); + + /** + * (optional) Get module configuration parameter + * + * Using Module Config Get command, host driver may send a parameter + * that fits into the header (a very short one), packed along with parameter id. + * + * param_id_data specifies both ID of the parameter, defined by the module + * and value of the parameter. + * It is up to the module how to distribute bits to ID and value of the parameter. + */ + int (*get_config_param)(struct processing_module *mod, uint32_t *param_id_data); + + /** + * (optional) Set module configuration for the given configuration ID + * + * If the complete configuration message is greater than MAX_BLOB_SIZE bytes, the + * transmission will be split into several smaller fragments. + * In this case the ADSP System will perform multiple calls to SetConfiguration() until + * completion of the configuration message sending. + * \note config_id indicates ID of the configuration message only on the first fragment + * sending, otherwise it is set to 0. Usually can be __cold + */ + int (*set_configuration)(struct processing_module *mod, + uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size); + + /** + * (optional) Get module runtime configuration for the given configuration ID + * + * If the complete configuration message is greater than MAX_BLOB_SIZE bytes, the + * transmission will be split into several smaller fragments. + * In this case the ADSP System will perform multiple calls to GetConfiguration() until + * completion of the configuration message retrieval. + * \note config_id indicates ID of the configuration message only on the first fragment + * retrieval, otherwise it is set to 0. Usually can be __cold + */ + int (*get_configuration)(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size); + + /** + * (unused) Set processing mode for the module + */ + int (*set_processing_mode)(struct processing_module *mod, + enum module_processing_mode mode); + + /** + * (unused) Get the current processing mode for the module + */ + enum module_processing_mode (*get_processing_mode)(struct processing_module *mod); + + /** + * (optional) Module specific reset procedure, called as part of module_adapter component + * reset in .reset(). This should reset all parameters to their initial stage + * and free all memory allocated during prepare(). Usually shouldn't be __cold since it's + * called from pipeline_reset() from ipc4_pipeline_trigger() + */ + int (*reset)(struct processing_module *mod); + + /** + * (optional) Module specific free procedure, called as part of module_adapter component + * free in .free(). This should free all memory allocated during module initialization. + * Usually can be __cold + */ + int (*free)(struct processing_module *mod); + + /** + * (optional) Module specific bind procedure, called when modules are bound with each other. + * Usually can be __cold + */ + int (*bind)(struct processing_module *mod, struct bind_info *bind_data); + + /** + * (optional) Module specific unbind procedure, called when modules are disconnected from + * one another. Usually can be __cold + */ + int (*unbind)(struct processing_module *mod, struct bind_info *unbind_data); + + /** + * (optional) Module specific trigger procedure, called when modules are triggered. Usually + * shouldn't be __cold. If a module implements this method, even if it only handles + * commands, running in non-LL context, it will still be called from the high priority + * LL context, which will cause a short jump to DRAM to check for supported commands. + */ + int (*trigger)(struct processing_module *mod, int cmd); + + /* + * Ops relevant only for the endpoint devices such as the host copier or DAI copier. + * Other modules should not implement these. + * + * Below #ifdef is a temporary solution used until work on separating a common interface + * for loadable modules is completed. + */ +#ifdef SOF_MODULE_API_PRIVATE + const struct module_endpoint_ops *endpoint_ops; +#endif /* SOF_MODULE_PRIVATE */ +}; + +#endif /* __MODULE_MODULE_INTERFACE__ */ diff --git a/src/include/module/module/llext.h b/src/include/module/module/llext.h new file mode 100644 index 000000000000..2f05cb6c692a --- /dev/null +++ b/src/include/module/module/llext.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ + +#ifndef MODULE_LLEXT_H +#define MODULE_LLEXT_H + +#define SOF_LLEXT_MODULE_MANIFEST(manifest_name, entry, affinity, mod_uuid, instances) \ +{ \ + .module = { \ + .name = manifest_name, \ + .uuid = mod_uuid, \ + .entry_point = (uint32_t)(entry), \ + .instance_max_count = instances, \ + .type = { \ + .load_type = SOF_MAN_MOD_TYPE_LLEXT, \ + .domain_ll = 1, \ + }, \ + .affinity_mask = (affinity), \ + } \ +} + +#define SOF_LLEXT_AUX_MANIFEST(manifest_name, entry, mod_uuid) \ +{ \ + .module = { \ + .name = manifest_name, \ + .uuid = mod_uuid, \ + .entry_point = (uint32_t)(entry), \ + .type = { \ + .load_type = SOF_MAN_MOD_TYPE_LLEXT_AUX, \ + }, \ + } \ +} + +#define SOF_LLEXT_BUILDINFO \ +static const struct sof_module_api_build_info buildinfo __section(".mod_buildinfo") __used = { \ + .format = SOF_MODULE_API_BUILD_INFO_FORMAT, \ + .api_version_number.full = SOF_MODULE_API_CURRENT_VERSION, \ +} + +#endif diff --git a/src/include/module/module/logger.h b/src/include/module/module/logger.h new file mode 100644 index 000000000000..db6b66611e7b --- /dev/null +++ b/src/include/module/module/logger.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_MODULE_LOGGER_H__ +#define __MODULE_MODULE_LOGGER_H__ + +/* Log level priority enumeration. */ +enum log_priority { + L_CRITICAL, /* Critical message. */ + L_ERROR, /* Error message. */ + L_HIGH, /* High importance log level. */ + L_WARNING, /* Warning message. */ + L_MEDIUM, /* Medium importance log level. */ + L_LOW, /* Low importance log level. */ + L_INFO, /* Information. */ + L_VERBOSE, /* Verbose message. */ + L_DEBUG, + L_MAX, +}; + +/* struct log_handle identifies the log message sender. + * + * struct log_handle instance is passed to the system_service::log_message function. + * This struct should not be used directly. + */ +struct log_handle; + +#endif /* __MODULE_MODULE_LOGGER_H__ */ diff --git a/src/include/module/module/system_service.h b/src/include/module/module/system_service.h new file mode 100644 index 000000000000..0fb60834fc6d --- /dev/null +++ b/src/include/module/module/system_service.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef MODULE_MODULE_SYSTEM_SERVICE_H +#define MODULE_MODULE_SYSTEM_SERVICE_H + +#include <stdint.h> +#include <stddef.h> + +#include "logger.h" +#include "../iadk/adsp_error_code.h" + +#ifdef __XTENSA__ + #define RESTRICT __restrict +#else + #define RESTRICT +#endif + +/*! This struct defines the obfuscating type for notifications. */ +struct notification_handle; + +/* Defines parameters used by ADSP system during notification creation. */ +struct notification_params { + uint32_t type; /*!< Notification type */ + uint16_t user_val_1; /*!< 16 bits user value available directly in IPC header + * for some notifications + */ + uint32_t user_val_2; /*!< 30 bits user value available directly in IPC header + * for some notifications + */ + uint32_t max_payload_size; /*!< Data size of payload (NotificationCreate updates this + * value to max possible payload size) + */ + uint8_t *payload; /*!< Pointer on the payload */ +}; + +/* Defines parameters used by ADSP system during Module Event notification creation. */ +struct module_event_notification { + uint32_t module_instance_id; /*!< Module ID (MS word) + Module Instance ID (LS word) */ + uint32_t event_id; /*!< Module specific event ID. */ + uint32_t event_data_size; /*!< Size of event_data array in bytes. May be set to 0 + * in case there is no data. + */ + uint32_t event_data[]; /*!< Optional event data (size set to 0 as it is optional + * data) + */ +}; + +/* Defines notification targets supported by ADSP system + * FW defines only two notification targets, HOST and ISH (Integrated Sensor Hub). + */ +enum notification_target { + NOTIFICATION_TARGET_DSP_TO_HOST = 1, /* Notification target is HOST */ + NOTIFICATION_TARGET_DSP_TO_ISH = 2 /* Notification target is ISH */ +}; + +/* Defines notification types supported by ADSP system + * FW use reserved first 20 positions describing types of notifications. + */ +enum notification_type { + /* corresponding to PHRASE_DETECTED notification */ + NOTIFICATION_TYPE_VOICE_COMMAND_NOTIFICATION = 4, + + /* corresponding to FW_AUD_CLASS_RESULT notification */ + NOTIFICATION_TYPE_AUDIO_CLASSIFIER_RESULTS = 9, + + /* corresponding to MODULE_NOTIFICATION notification */ + NOTIFICATION_TYPE_MODULE_EVENT_NOTIFICATION = 12, +}; + +/* Defines extended interfaces for IADK modules */ +enum interface_id { + INTERFACE_ID_GNA = 0x1000, /* Reserved for ADSP system */ + INTERFACE_ID_INFERENCE_SERVICE = 0x1001, /* See InferenceServiceInterface */ + INTERFACE_ID_SDCA = 0x1002, /* See SdcaInterface */ + INTERFACE_ID_ASYNC_MESSAGE_SERVICE = 0x1003, /* See AsyncMessageInterface */ + INTERFACE_ID_AM_SERVICE = 0x1005, /* Reserved for ADSP system */ + INTERFACE_ID_KPB_SERVICE = 0x1006 /* See KpbInterface */ +}; + +/* sub interface definition. + * This type may contain generic interface properties like id or struct size if needed. + */ +struct system_service_iface; + +struct system_service { + void (*log_message)(enum log_priority log_priority, uint32_t log_entry, + struct log_handle const *log_handle, uint32_t param1, + uint32_t param2, uint32_t param3, uint32_t param4); + + AdspErrorCode (*safe_memcpy)(void *RESTRICT dst, size_t maxlen, + const void *RESTRICT src, size_t len); + + AdspErrorCode (*safe_memmove)(void *dst, size_t maxlen, + const void *src, size_t len); + + void* (*vec_memset)(void *dst, int c, size_t len); + + AdspErrorCode (*notification_create)(struct notification_params *params, + uint8_t *notification_buffer, + uint32_t notification_buffer_size, + struct notification_handle **handle); + AdspErrorCode (*notification_send)(enum notification_target notification_target, + struct notification_handle *message, + uint32_t actual_payload_size); + + AdspErrorCode (*get_interface)(enum interface_id id, struct system_service_iface **iface); +}; +#endif /* MODULE_MODULE_SYSTEM_SERVICE_H */ diff --git a/src/include/sof/audio/MaxxEffect/Control/Direct/MaxxEffect_Revision.h b/src/include/sof/audio/MaxxEffect/Control/Direct/MaxxEffect_Revision.h new file mode 100644 index 000000000000..eeb47e704b4f --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/Control/Direct/MaxxEffect_Revision.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +#ifndef MAXX_EFFECT_REVISION_H +#define MAXX_EFFECT_REVISION_H + +#include <stdint.h> +#include <sof/audio/MaxxEffect/MaxxEffect.h> +#include <sof/audio/MaxxEffect/MaxxStatus.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Get null-terminated revision string. + * + * @param[in] effect Initialized effect. + * @param[out] revision Revision string. + * @param[out] bytes Revision string size. Optional, use NULL if not needed. + * + * @return 0 if success, otherwise fail + ******************************************************************************/ +MaxxStatus_t MaxxEffect_Revision_Get( + MaxxEffect_t* effect, + const char** revision, + uint32_t* bytes); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/sof/audio/MaxxEffect/Control/RPC/MaxxEffect_RPC_Server.h b/src/include/sof/audio/MaxxEffect/Control/RPC/MaxxEffect_RPC_Server.h new file mode 100644 index 000000000000..984060c4cdc1 --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/Control/RPC/MaxxEffect_RPC_Server.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +#ifndef MAXX_EFFECT_RPC_SERVER_H +#define MAXX_EFFECT_RPC_SERVER_H + +#include <stdint.h> +#include <sof/audio/MaxxEffect/MaxxEffect.h> +#include <sof/audio/MaxxEffect/MaxxStatus.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Get required buffers size for communication. + * + * @param[in] effect initialized effect + * @param[out] requestBytes request buffer size + * @param[out] responseBytes response buffer size + * + * @return 0 if success, otherwise fail + ******************************************************************************/ +MaxxStatus_t MaxxEffect_GetMessageMaxSize( + MaxxEffect_t* effect, + uint32_t* requestBytes, + uint32_t* responseBytes); + +/******************************************************************************* + * Process request buffer and provide with the response. + * + * @param[in] effect initialized effect + * @param[in] request request buffer + * @param[in] requestBytes request buffer size + * @param[out] response response buffer + * @param[out] responseBytes response buffer size + * + * @return 0 if success, otherwise fail + ******************************************************************************/ +MaxxStatus_t MaxxEffect_Message( + MaxxEffect_t* effect, + const void* request, + uint32_t requestBytes, + void* response, + uint32_t* responseBytes); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/sof/audio/MaxxEffect/Initialize/MaxxEffect_Initialize.h b/src/include/sof/audio/MaxxEffect/Initialize/MaxxEffect_Initialize.h new file mode 100644 index 000000000000..41a7747a189b --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/Initialize/MaxxEffect_Initialize.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +/******************************************************************************* + * @page Initialization_Default Default Initialization + * + * Refer to the diagram below for the default initialization workflow. + * + * ![Default initialization workflow] + * (Initialize/Default_Initialization.svg) + * + * Example code for the default effect initialization with the interleaved + * stereo streams processing at 48 kHz with Q1.31 fixed-point data samples: + * + * ~~~{.c} + * uint32_t bytes = 0; + * MaxxEffect_t* effect = NULL; + * + * // Get required size for storing MaxxEffect_t handler + * if (0 == MaxxEffect_GetEffectSize(&bytes)) + * { + * // Allocate required size for effect + * effect = (MaxxEffect_t*)malloc(bytes); + * if (NULL != effect) + * { + * // Prepare expected formats + * // Identical for both input and output streams + * MaxxStreamFormat_t const expectedFormat = { + * .sampleRate = 48000, + * .numChannels = 2, + * .samplesFormat = MAXX_BUFFER_FORMAT_Q1_31, + * .samplesLayout = MAXX_BUFFER_LAYOUT_INTERLEAVED + * }; + * + * // Prepare I/O stream format arrays + * MaxxStreamFormat_t const* inputFormats[1]; + * MaxxStreamFormat_t const* outputFormats[1]; + * inputFormats[0] = &expectedFormat; + * outputFormats[0] = &expectedFormat; + * + * // Initialize effect with the expected IO formats + * if (0 == MaxxEffect_Initialize(effect, + * inputFormats, 1, + * outputFormats, 1)) + * { + * // MaxxEffect successfully initialized + * } + * } + * } + * ~~~ + ******************************************************************************/ +#ifndef MAXX_EFFECT_INITIALIZE_H +#define MAXX_EFFECT_INITIALIZE_H + +#include <stdint.h> +#include <sof/audio/MaxxEffect/MaxxEffect.h> +#include <sof/audio/MaxxEffect/MaxxStatus.h> +#include <sof/audio/MaxxEffect/MaxxStream.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Provides with the required data size for holding @ref MaxxEffect_t handler. + * It is caller responsibility to allocate enough memory (bytes) for effect. + * + * @see MaxxEffect_Initialize for allocated effect initialization + * + * @param[out] bytes required data size + * + * @return 0 if success, otherwise fail + ******************************************************************************/ +MaxxStatus_t MaxxEffect_GetEffectSize( + uint32_t* bytes); + + +/******************************************************************************* + * Initializes preallocated @ref MaxxEffect_t handler to the requested scenario. + * Required scenario is determined based on the provided streams formats. + * Supported streams count is defined by specific product. + * + * @see MaxxEffect_GetEffectSize for the required effect size + * + * @param[in] effect pointer to the pre-allocated handler + * @param[in] inputFormats array of pointers to the input formats + * @param[in] inputFormatsCount number of elements in the inputFormats + * @param[in] outputFormats array of pointers to the output formats + * @param[in] outputFormatsCount number of elements in the outputFormats + * + * @return 0 if effect is initialized, non-zero error code otherwise + ******************************************************************************/ +MaxxStatus_t MaxxEffect_Initialize( + MaxxEffect_t* effect, + MaxxStreamFormat_t* const inputFormats[], + uint32_t inputFormatsCount, + MaxxStreamFormat_t* const outputFormats[], + uint32_t outputFormatsCount); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/sof/audio/MaxxEffect/MaxxEffect.h b/src/include/sof/audio/MaxxEffect/MaxxEffect.h new file mode 100644 index 000000000000..f76341d68ec0 --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/MaxxEffect.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +/******************************************************************************* + * @page CoreConcepts_MaxxEffect MaxxEffect + * + * @ref MaxxEffect_t or simply **effect** - is a Waves algorithms handler, that + * contains: + * @ref MaxxEffect_InternalData_Parameters, + * @ref MaxxEffect_InternalData_Coefficients, + * @ref MaxxEffect_InternalData_States, + * @ref MaxxEffect_InternalData_Meters, etc. required during + * effect life-cycle. It is caller responsibility to allocate enough memory + * for storing effect handler, and to properly initialize it. Refer to the + * @ref Initialization page for handler allocation and initialization. + * + * @section MaxxEffect_InternalData Data structures + * @subsection MaxxEffect_InternalData_Parameters Parameters + * Data segment with algorithms parameters representing some + * configuration available for tuning, e.g. Master Bypass, Mute, Parametric + * EQ band frequency, gain etc. *Parameters preset* is an array of parameter + * ID and float-point value (id, value) pairs. Might not be included in + * MaxxEffect handler. **Updated in the control path.** + * + * @subsection MaxxEffect_InternalData_Coefficients Coefficients + * Data segment with algorithms coefficients such as filters + * difference equations. Computed from parameters and used for processing. + * Single coefficient is represented by its ID and the corresponding buffer. + * *Coefficients preset* is an array of such pairs. + * **Updated in the control path.** + * + * @subsection MaxxEffect_InternalData_States States + * Data segment with algorithms states. + * **Updated in the data path.** + * + * @subsection MaxxEffect_InternalData_Meters Meters + * Data segment with algorithms meters representing measure of some value + * over a period of time, e.g. level, gain reduction, peak, etc. + * **Updated in the data path.** + ******************************************************************************/ +#ifndef MAXX_EFFECT_H +#define MAXX_EFFECT_H + +/** + * Waves effect handler. + * + * @see @ref CoreConcepts_MaxxEffect + */ +typedef void MaxxEffect_t; + + +#endif diff --git a/src/include/sof/audio/MaxxEffect/MaxxStatus.h b/src/include/sof/audio/MaxxEffect/MaxxStatus.h new file mode 100644 index 000000000000..65f058f9f339 --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/MaxxStatus.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +#ifndef MAXX_STATUS_H +#define MAXX_STATUS_H + +#include <stdint.h> + +/** + * Non-zero value represents error code type + */ +typedef int32_t MaxxStatus_t; + +#endif diff --git a/src/include/sof/audio/MaxxEffect/MaxxStream.h b/src/include/sof/audio/MaxxEffect/MaxxStream.h new file mode 100644 index 000000000000..25ed35597c9d --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/MaxxStream.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +/******************************************************************************* + * @page CoreConcepts_DataPath Data Path + * + * Data path is a collection of components and functions used in processing. + * + * **Sample** is a signal value at some point, irrespective of the number of + * channels. Thus, for mono signal sample value is a single data element but + * for multiple channels, sample is a collection of data values, + * one per channel. + * + * **Frame** is a sequence of **samples** to be processed. + * + * ![Interleaved stereo buffer] + * (CoreConcepts/DataPath/MaxxBuffer_StereoFrame.svg) + * + * @section CoreConcepts_DataPath_Streams Data Streams + * All @ref CoreConcepts_MaxxEffect instances receive frames from input streams + * and send processed frames to output streams. Stream example is shown below. + * + * ![Data stream and the corresponding format] + * (CoreConcepts/DataPath/MaxxStream_DeinterleavedStereo.svg) + * + * @subsection CoreConcepts_DataPath_Stream Stream + * @ref MaxxStream_t contains information about all used @ref MaxxBuffer_t, + * and available/processed samples count. @ref MaxxEffect_t handler might + * require a specific frame length to be available in the stream. + * + * @subsection CoreConcepts_DataPath_StreamFormat Stream Format + * Expected streams formats must be defined during @ref Initialization with + * @ref MaxxStreamFormat_t. It holds information about @ref MaxxStream_t + * configuration such as + * [sampling rate](@ref MaxxStreamFormat_t.sampleRate), + * [number of channels](@ref MaxxStreamFormat_t.numChannels), + * [format](@ref MaxxStreamFormat_t.samplesFormat), and + * [layout](@ref MaxxStreamFormat_t.samplesLayout). + * + * @subsection CoreConcepts_DataPath_Buffer Buffer + * @ref MaxxBuffer_t is a pointer to the continuous memory region which + * is used for storing data values. Buffers can contain audio, IV sensors, + * head-tracking data, etc. + * + * @subsection CoreConcepts_DataPath_MultichannelStreams Multichannel Streams + * Multichannel data can be represented in interleaved or deinterleaved manner. + * In interleaved stream single buffer is used to store all channels, whereas + * in deinterleaved stream several buffers are used, one for each channel. + * @ref MaxxBuffer_Layout_t defines buffer layout for multichannel data. This + * field is ignored for single-channel data. + ******************************************************************************/ +#ifndef MAXX_STREAM_H +#define MAXX_STREAM_H + +#include <stdint.h> + +/** + * An array of signal values with the @ref MaxxBuffer_Format_t format. + * + * @see @ref CoreConcepts_DataPath_Buffer + */ +typedef void* MaxxBuffer_t; + + +/** + * Defines data encoding format of @ref MaxxBuffer_t elements. + */ +typedef enum +{ + MAXX_BUFFER_FORMAT_Q1_15 = 0, /**< PCM Q15 */ + MAXX_BUFFER_FORMAT_Q9_23 = 1, /**< PCM Q23 in 32 bit container */ + MAXX_BUFFER_FORMAT_Q1_31 = 2, /**< PCM Q31 */ + MAXX_BUFFER_FORMAT_FLOAT = 3, /**< FLOAT */ + MAXX_BUFFER_FORMAT_Q5_27 = 4, /**< PCM Q27 */ + MAXX_BUFFER_FORMAT_Q1_23 = 5, /**< PCM Q23 */ + + MAXX_BUFFER_FORMAT_FORCE_SIZE = INT32_MAX +} MaxxBuffer_Format_t; + +/** + * Defines buffers layout inside of the @ref MaxxStream_t. + * + * @see @ref CoreConcepts_DataPath_MultichannelStreams + */ +typedef enum +{ + MAXX_BUFFER_LAYOUT_INTERLEAVED = 0, /**< Interleaved buffer */ + MAXX_BUFFER_LAYOUT_DEINTERLEAVED = 1, /**< Deinterleaved buffer */ + + MAXX_BUFFER_LAYOUT_FORCE_SIZE = INT32_MAX +} MaxxBuffer_Layout_t; + + +/** + * Defines @ref CoreConcepts_DataPath_StreamFormat. + */ +typedef struct +{ + uint32_t sampleRate; /**< Sampling rate in Hz */ + uint32_t numChannels; /**< Channels count */ + MaxxBuffer_Format_t samplesFormat; /**< Data format */ + MaxxBuffer_Layout_t samplesLayout; /**< Data layout */ + + uint32_t frameSize; /**< Minimum available samples count */ +} MaxxStreamFormat_t; + + +/** + * A @ref CoreConcepts_DataPath_Stream with the @ref MaxxStreamFormat_t format. + */ +typedef struct +{ + /** + * For @ref MAXX_BUFFER_LAYOUT_INTERLEAVED array length must be 1. + * For @ref MAXX_BUFFER_LAYOUT_DEINTERLEAVED must be equal to the + * [number of channels](@ref MaxxStreamFormat_t.numChannels). + */ + MaxxBuffer_t* buffersArray; + + /** number of available samples in data buffers. */ + uint32_t numAvailableSamples; + + /** number of processed samples in data buffers. */ + uint32_t numProcessedSamples; + + /** maximum number of samples which buffers can contain. */ + uint32_t maxNumSamples; +} MaxxStream_t; + + +#endif diff --git a/src/include/sof/audio/MaxxEffect/Process/MaxxEffect_Process.h b/src/include/sof/audio/MaxxEffect/Process/MaxxEffect_Process.h new file mode 100644 index 000000000000..c9e18aa26d30 --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/Process/MaxxEffect_Process.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +/******************************************************************************* + * @page Processing Processing + * + * Refer to the diagram below for the processing workflow. + * + * ![Processing workflow](Process/MaxxEffect-ProcessingWorkflow.svg) + * + * Example code for the interleaved stereo streams processing at 48 kHz with + * Q1.31 fixed-point data samples: + * + * ~~~{.c} + * // 10 ms at 48 kHz + * #define BUFFER_SAMPLES (480) + * + * // Interleaved buffer with 2 Q31 channels + * int32_t samplesBuffer[2 * BUFFER_SAMPLES]; + * + * // Format used for initialization + * // Identical for both input and output streams + * MaxxStreamFormat_t expectedFormat = { + * .sampleRate = 48000, + * .numChannels = 2, + * .samplesFormat = MAXX_BUFFER_FORMAT_Q1_31, + * .samplesLayout = MAXX_BUFFER_LAYOUT_INTERLEAVED + * }; + * + * // Prepare I/O streams + * MaxxStream_t inputStream = { + * .buffersArray = samplesBuffer, + * .numAvailableSamples = 0, + * .numProcessedSamples = 0 + * }; + * // Point to the same buffer for in-place processing + * MaxxStream_t outputStream = inputStream; + * + * // Read frame of 480 samples to the input stream + * + * // Update available samples count in the input stream + * inputStream.numAvailableSamples = 480; + * + * // Prepare I/O stream arrays + * MaxxStream_t* inputStreams[1] = { &inputStream }; + * MaxxStream_t* outputStreams[1] = { &outputStream }; + * + * // Effect must be already initialized to use 1 input stream and 1 output + * // stream with the expectedFormat + * + * // Process frame + * MaxxEffect_Process(effect, inputStreams, outputStreams); + * + * // Validate result + * if (inputStream.numAvailableSamples != inputStream.numProcessedSamples) + * { + * // There are unread samples left in the input stream. Might be true if + * // the input frame size is not divisible by the internal frame size. + * } + * + * if (inputStream.numProcessedSamples != outputStream.numAvailableSamples) + * { + * // Sanity check. In the current example number of processed samples must + * // always be equal to the number of consumed samples since the sample + * // rate matches between input and output streams format. Otherwise + * // might differ by the resampling ratio. + * } + * + * ~~~ + ******************************************************************************/ +#ifndef MAXX_EFFECT_PROCESS_H +#define MAXX_EFFECT_PROCESS_H + +#include <sof/audio/MaxxEffect/MaxxEffect.h> +#include <sof/audio/MaxxEffect/MaxxStatus.h> +#include <sof/audio/MaxxEffect/MaxxStream.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Get available samples from input streams and store processed in output. + * All streams must have the same format that was used during initialization. + * + * Different streams might point to the same buffer for in-place processing, but + * only when sample rate is matched for input and output streams. + * + * Sets numProcessedSamples in inputStreams to number of read samples. + * Sets numAvailableSamples in outputStreams to number of written samples. + * + * @see @ref CoreConcepts_DataPath_Streams for arrays content. + * + * @param[in] effect initialized effect + * @param[in] inputStreams array of input streams + * @param[in] outputStreams array of output streams + * + * @return 0 on success, otherwise fail + ******************************************************************************/ +MaxxStatus_t MaxxEffect_Process( + MaxxEffect_t* effect, + MaxxStream_t* const inputStreams[], + MaxxStream_t* const outputStreams[]); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/include/sof/audio/MaxxEffect/Process/MaxxEffect_Reset.h b/src/include/sof/audio/MaxxEffect/Process/MaxxEffect_Reset.h new file mode 100644 index 000000000000..75ff92947acb --- /dev/null +++ b/src/include/sof/audio/MaxxEffect/Process/MaxxEffect_Reset.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Waves Audio Ltd. All rights reserved. + */ +#ifndef MAXX_EFFECT_RESET_H +#define MAXX_EFFECT_RESET_H + +#include <sof/audio/MaxxEffect/MaxxEffect.h> +#include <sof/audio/MaxxEffect/MaxxStatus.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Reset internal [states](@ref MaxxEffect_InternalData_States), and [meters] + * (@ref MaxxEffect_InternalData_Meters). Configuration remains the same. + * Should be called only if [MaxxEffect_GetActive](@ref MaxxEffect_GetActive) + * is 0 to avoid audio artifacts. + * + * @param[in] effect initialized effect + * + * @return 0 on success, otherwise fail + ******************************************************************************/ +MaxxStatus_t MaxxEffect_Reset( + MaxxEffect_t* effect); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/include/sof/audio/asrc/asrc_config.h b/src/include/sof/audio/asrc/asrc_config.h deleted file mode 100644 index ca2a7f015e35..000000000000 --- a/src/include/sof/audio/asrc/asrc_config.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2012 Intel Corporation. All rights reserved. - */ - -#ifndef __SOF_AUDIO_ASRC_ASRC_CONFIG_H__ -#define __SOF_AUDIO_ASRC_ASRC_CONFIG_H__ - -#include <config.h> - -/* If next define is set to 1 the ASRC is configured automatically. Setting - * to zero temporarily is useful is for testing needs. - */ -#define ASRC_AUTOARCH 1 - -/* Select optimized code variant when xt-xcc compiler is used on HiFi3 */ -#if ASRC_AUTOARCH == 1 -#if defined __XCC__ -/* For xt-xcc */ -#include <xtensa/config/core-isa.h> -#if XCHAL_HAVE_HIFI3 == 1 -/* Version for HiFi3 */ -#define ASRC_HIFI3 1 -#define ASRC_GENERIC 0 -#else -/* Version for e.g. HiFi2EP */ -#define ASRC_HIFI3 0 -#define ASRC_GENERIC 1 -#endif -#else -/* For GCC */ -#define ASRC_GENERIC 1 -#define ASRC_HIFI3 0 -#endif /* XCC */ -#else -/* Applied when ASRC_AUTOARCH is set to zero */ -#define ASRC_GENERIC 1 /* Enable generic */ -#define ASRC_HIFI3 0 /* Disable HiFi3 */ -#endif /* Autoarch */ - -#endif /* __SOF_AUDIO_ASRC_ASRC_CONFIG_H__ */ diff --git a/src/include/sof/audio/audio_buffer.h b/src/include/sof/audio/audio_buffer.h new file mode 100644 index 000000000000..95317e5dc964 --- /dev/null +++ b/src/include/sof/audio/audio_buffer.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ +#ifndef __SOF_AUDIO_BUFFER__ +#define __SOF_AUDIO_BUFFER__ + +#include <sof/common.h> +#include <ipc/topology.h> +#include <sof/coherent.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> + +#define BUFFER_TYPE_LEGACY_BUFFER 1 +#define BUFFER_TYPE_RING_BUFFER 2 + +/* forward def */ +struct sof_audio_buffer; + +struct audio_buffer_ops { + /** + * @brief this method must free all structures allocated by buffer implementation + * and the buffer itself + * OBLIGATORY + */ + void (*free)(struct sof_audio_buffer *buffer); + + /** + * @brief clean all buffer data, set buffer positions to initial, leaving config as is + * the procedure is to be called only when buffer is not in use + * OPTIONAL + */ + void (*reset)(struct sof_audio_buffer *buffer); + + /** + * OPTIONAL: Notification to the sink implementation about changes in audio format + * + * Once any of *audio_stream_params elements changes, the implementation of + * sink may need to perform some extra operations. + * This callback will be called immediately after any change + * + * @retval 0 if success, negative if new parameters are not supported + */ + int (*on_audio_format_set)(struct sof_audio_buffer *buffer); + + /** + * OPTIONAL + * see sink_set_params comments + */ + int (*audio_set_ipc_params)(struct sof_audio_buffer *buffer, + struct sof_ipc_stream_params *params, bool force_update); + + /** + * OPTIONAL + * see comment for sink_set_alignment_constants + */ + int (*set_alignment_constants)(struct sof_audio_buffer *buffer, + const uint32_t byte_align, + const uint32_t frame_align_req); +}; + +struct mod_alloc_ctx; +/* base class for all buffers, all buffers must inherit from it */ +struct sof_audio_buffer { + CORE_CHECK_STRUCT_FIELD; + + /* type of the buffer BUFFER_TYPE_* */ + uint32_t buffer_type; + + bool is_shared; /* buffer structure is shared between 2 cores */ + +#if CONFIG_PIPELINE_2_0 + /** + * sink API of an additional buffer + * of any type at data input + * + * to be removed when hybrid buffers are no longer needed + */ + struct sof_audio_buffer *secondary_buffer_sink; + + /** + * source API of an additional buffer + * at data output + */ + struct sof_audio_buffer *secondary_buffer_source; + +#endif /* CONFIG_PIPELINE_2_0 */ + + /* effective runtime stream params + * before pipelin2.0 is ready, stream params may be kept in audio_stream structure + * also for hybrid buffering audio params need to be shared between primary and secondary + * buffers + * + * So currently only a pointer to effective stream params is here. + * Note that the same pointer MUST be set in source and sink api (kept there for + * performance reasons) + */ + struct sof_audio_stream_params *audio_stream_params; + + + /* private: */ + struct sof_source _source_api; /**< src api handler */ + struct sof_sink _sink_api; /**< sink api handler */ + + /* virtual methods */ + const struct audio_buffer_ops *ops; + + /* + * legacy params, needed for pipeline binding/iterating, not for data buffering + * should not be in struct sof_audio_buffer at all, kept for pipeline2.0 transition + */ + bool walking; /**< indicates if the buffer is being walked */ + + struct mod_alloc_ctx *alloc; +}; + +#if CONFIG_PIPELINE_2_0 +/* + * attach a secondary buffer (any type) before buffer (when at_input == true) or behind a buffer + * + * before buffer (at_input == true): + * 2.0 mod ==> (sink_API) secondary buffer ==> + * ==> comp_buffer (audio_stream or source API) ==> 1.0 mod + * + * after buffer (at_input == false): + * 1.0 mod ==> (audio_stream or sink API) ==> comp_buffer ==> + * ==> secondary buffer(source API) == 2.0 mod + * + * If a secondary buffer is attached, it replaces source or sink interface of audio_stream + * allowing the module connected to it using all properties of secondary buffer (like + * lockless cross-core connection in case of ring_buffer etc.) keeping legacy interface + * to other modules + * + * buffer_sync_secondary_buffer must be called every 1 ms to move data to/from + * secondary buffer to comp_buffer + * + * @param buffer pointer to a buffer + * @param at_input true indicates that a secondary buffer is located at data input, replacing + * sink API of audio_stream + * false indicates that a secondary buffer is located at data output, replacing + * source API of audio_stream + * @param secondary_buffer pointer to a buffer to be attached + * + * to be removed when hybrid buffers are no longer needed + */ +int audio_buffer_attach_secondary_buffer(struct sof_audio_buffer *buffer, bool at_input, + struct sof_audio_buffer *secondary_buffer); + +/* + * move data from/to secondary buffer, must be called periodically as described above + * + * @param buffer pointer to a buffer + * @param limit data copy limit. Indicates maximum amount of data that will be moved from/to + * secondary buffer in an operation + * + * to be removed when hybrid buffers are no longer needed + */ +int audio_buffer_sync_secondary_buffer(struct sof_audio_buffer *buffer, size_t limit); + +/** + * @brief return a handler to sink API of audio_buffer. + * the handler may be used by helper functions defined in sink_api.h + */ +static inline +struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer) +{ + CORE_CHECK_STRUCT(buffer); + return buffer->secondary_buffer_sink ? + audio_buffer_get_sink(buffer->secondary_buffer_sink) : + &buffer->_sink_api; +} + +/** + * @brief return a handler to source API of audio_buffer + * the handler may be used by helper functions defined in source_api.h + */ +static inline +struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer) +{ + CORE_CHECK_STRUCT(buffer); + return buffer->secondary_buffer_source ? + audio_buffer_get_source(buffer->secondary_buffer_source) : + &buffer->_source_api; +} + +#else /* CONFIG_PIPELINE_2_0 */ + +/** + * @brief return a handler to sink API of audio_buffer. + * the handler may be used by helper functions defined in sink_api.h + */ +static inline +struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer) +{ + CORE_CHECK_STRUCT(buffer); + return &buffer->_sink_api; +} + +/** + * @brief return a handler to source API of audio_buffer + * the handler may be used by helper functions defined in source_api.h + */ +static inline +struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer) +{ + CORE_CHECK_STRUCT(buffer); + return &buffer->_source_api; +} + +#endif /* CONFIG_PIPELINE_2_0 */ + +static inline bool audio_buffer_is_shared(struct sof_audio_buffer *buffer) +{ + return buffer->is_shared; +} + +static inline bool audio_buffer_hw_params_configured(struct sof_audio_buffer *buffer) +{ + return buffer->audio_stream_params->state != AUDIOBUF_STATE_INITIAL; +} + +static inline void audio_buffer_set_hw_params_configured(struct sof_audio_buffer *buffer) +{ + buffer->audio_stream_params->state = AUDIOBUF_STATE_READY; +} + +static inline void audio_buffer_reset_params(struct sof_audio_buffer *buffer) +{ + buffer->audio_stream_params->state = AUDIOBUF_STATE_INITIAL; +} + +static inline enum sof_audio_buffer_state audio_buffer_get_state( + const struct sof_audio_buffer *buffer) +{ + return buffer->audio_stream_params->state; +} + +static inline void audio_buffer_set_state(struct sof_audio_buffer *buffer, + enum sof_audio_buffer_state state) +{ + buffer->audio_stream_params->state = state; +} + +static inline void audio_buffer_set_eos(struct sof_audio_buffer *buffer) +{ + buffer->audio_stream_params->state = AUDIOBUF_STATE_END_OF_STREAM; +} + +static inline uint16_t audio_buffer_get_chmap(struct sof_audio_buffer *buffer, size_t index) +{ + return buffer->audio_stream_params->chmap[index]; +} + +static inline void audio_buffer_set_chmap(struct sof_audio_buffer *buffer, size_t index, + uint16_t value) +{ + buffer->audio_stream_params->chmap[index] = value; +} + +/** + * @brief return a handler to stream params structure + */ +static inline +struct sof_audio_stream_params *audio_buffer_get_stream_params(struct sof_audio_buffer *buffer) +{ + return buffer->audio_stream_params; +} + +/** + * @brief return a pointer to struct sof_audio_buffer from sink pointer + * NOTE! ensure that sink is really provided by sof_audio_buffer + * otherwise a random value will be returned + */ +static inline struct sof_audio_buffer *sof_audio_buffer_from_sink(struct sof_sink *sink) +{ + return container_of(sink, struct sof_audio_buffer, _sink_api); +} + +/** + * @brief return a pointer to struct sof_audio_buffer from source pointer + * NOTE! ensure that source is really provided by sof_audio_buffer + * otherwise a random value will be returned + */ +static inline struct sof_audio_buffer *sof_audio_buffer_from_source(struct sof_source *source) +{ + return container_of(source, struct sof_audio_buffer, _source_api); +} + +/** + * @brief initialize audio buffer structures + * + * @param buffer pointer to the audio_buffer + * @param buffer_type a type of the buffer, BUFFER_TYPE_* + * @param is_shared indicates if the buffer will be shared between cores + * @param source_ops pointer to virtual methods table for source API + * @param sink_ops pointer to virtual methods table for sink API + * @param audio_buffer_ops pointer to required buffer virtual methods implementation + * @param audio_stream_params pointer to audio stream (currently kept in buffer implementation) + * + * in sink_ops and source_ops API if there's no implemented of following methods: + * on_audio_format_set + * audio_set_ipc_params + * set_alignment_constants + * + * default implementation will be used instead, redirecting those calls to proper + * audio_buffer_ops operations + */ +void audio_buffer_init(struct sof_audio_buffer *buffer, uint32_t buffer_type, bool is_shared, + const struct source_ops *source_ops, const struct sink_ops *sink_ops, + const struct audio_buffer_ops *audio_buffer_ops, + struct sof_audio_stream_params *audio_stream_params); + +/** + * @brief free buffer and all allocated resources + */ +void audio_buffer_free(struct sof_audio_buffer *buffer); + +/** + * @brief clean all buffer data, set buffer positions to initial, leaving config as is + * the procedure is to be called only when buffer is not in use + */ +static inline +void audio_buffer_reset(struct sof_audio_buffer *buffer) +{ + if (buffer->ops->reset) + buffer->ops->reset(buffer); + +#if CONFIG_PIPELINE_2_0 + if (buffer->secondary_buffer_sink && buffer->secondary_buffer_sink->ops->reset) + buffer->secondary_buffer_sink->ops->reset(buffer->secondary_buffer_sink); + + if (buffer->secondary_buffer_source && buffer->secondary_buffer_source->ops->reset) + buffer->secondary_buffer_source->ops->reset(buffer->secondary_buffer_source); +#endif +} + +/* Audio-buffer wrappers for the source-sink API */ +int audio_buffer_source_set_ipc_params(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update); +int audio_buffer_source_on_audio_format_set(struct sof_source *source); +int audio_buffer_source_set_alignment_constants(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req); +int audio_buffer_sink_set_ipc_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, + bool force_update); +int audio_buffer_sink_on_audio_format_set(struct sof_sink *sink); +int audio_buffer_sink_set_alignment_constants(struct sof_sink *sink, + const uint32_t byte_align, + const uint32_t frame_align_req); +uint32_t audio_buffer_sink_get_lft(struct sof_sink *sink); + +#endif /* __SOF_AUDIO_BUFFER__ */ diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index 08da4336cf4b..dd81c157b8d8 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -1,168 +1,672 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. * * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> */ /** - * audio_stream is kind of circular buffer with information about data format - * and buffer size. Audio processing functions should work on this component. - * This component is not responsible for memory menagement for himself, - * it is a role of highly coupled comp_buffer or dma component as usual. - */ + * \file include/sof/audio/audio_stream.h + * \brief Audio Stream API definition + * \author Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ #ifndef __SOF_AUDIO_AUDIO_STREAM_H__ #define __SOF_AUDIO_AUDIO_STREAM_H__ #include <sof/audio/format.h> -#include <sof/debug/panic.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/compiler_attributes.h> +#include <rtos/panic.h> #include <sof/math/numbers.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <sof/lib/dma.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <ipc/stream.h> -#include <config.h> +#include <ipc4/base-config.h> +#include <module/audio/audio_stream.h> + +#include <stdbool.h> #include <stdint.h> -/* audio circular stream */ +/** \addtogroup audio_stream_api Audio Stream API + * @{ + */ + +/** + * Audio stream is a circular buffer aware of audio format of the data + * in the buffer so provides API for reading and writing not only bytes, + * but also samples and frames. + * + * Audio stream does not perform any memory allocations. A client (a component + * buffer or dma) must allocate the memory for the underlying data buffer and + * provide it to the initialization routine. + * + * Once the client is done with reading/writing the data, it must commit the + * consumption/production and update the buffer state by calling + * audio_stream_consume()/audio_stream_produce() (just a single call following + * series of reads/writes). + * + */ struct audio_stream { /* runtime data */ - uint32_t size; /* runtime buffer size in bytes (period multiple) */ - uint32_t avail; /* available bytes for reading */ - uint32_t free; /* free bytes for writing */ - void *w_ptr; /* buffer write pointer */ - void *r_ptr; /* buffer read position */ - void *addr; /* buffer base address */ - void *end_addr; /* buffer end address */ + uint32_t size; /**< Runtime buffer size in bytes (period multiple) */ + uint32_t avail; /**< Available bytes for reading */ + uint32_t free; /**< Free bytes for writing */ + void *w_ptr; /**< Buffer write pointer */ + void *r_ptr; /**< Buffer read position */ + void *addr; /**< Buffer base address */ + void *end_addr; /**< Buffer end address */ + uint8_t byte_align_req; + uint8_t frame_align_req; + /* runtime stream params */ - enum sof_ipc_frame frame_fmt; /**< sample data format */ - uint32_t rate; /**< number of data frames per second [Hz] */ - uint16_t channels; /**< number of samples in each frame */ + struct sof_audio_stream_params runtime_stream_params; }; +void audio_stream_recalc_align(struct audio_stream *stream); + +static inline void *audio_stream_get_rptr(const struct audio_stream *buf) +{ + return buf->r_ptr; +} + +static inline void *audio_stream_get_wptr(const struct audio_stream *buf) +{ + return buf->w_ptr; +} + +static inline void *audio_stream_get_end_addr(const struct audio_stream *buf) +{ + return buf->end_addr; +} + +static inline void *audio_stream_get_addr(const struct audio_stream *buf) +{ + return buf->addr; +} + +static inline uint32_t audio_stream_get_size(const struct audio_stream *buf) +{ + return buf->size; +} + +static inline uint32_t audio_stream_get_avail(const struct audio_stream *buf) +{ + return buf->avail; +} + +static inline uint32_t audio_stream_get_free(const struct audio_stream *buf) +{ + return buf->free; +} + +static inline enum sof_ipc_frame audio_stream_get_frm_fmt(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.frame_fmt; +} + +static inline enum sof_ipc_frame audio_stream_get_valid_fmt(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.valid_sample_fmt; +} + +static inline uint32_t audio_stream_get_rate(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.rate; +} + +static inline uint32_t audio_stream_get_channels(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.channels; +} + +static inline bool audio_stream_get_underrun(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.underrun_permitted; +} + +static inline uint32_t audio_stream_get_buffer_fmt(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.buffer_fmt; +} + +static inline bool audio_stream_get_overrun(const struct audio_stream *buf) +{ + return buf->runtime_stream_params.overrun_permitted; +} + +static inline void audio_stream_set_rptr(struct audio_stream *buf, void *val) +{ + buf->r_ptr = val; +} + +static inline void audio_stream_set_wptr(struct audio_stream *buf, void *val) +{ + buf->w_ptr = val; +} + +static inline void audio_stream_set_end_addr(struct audio_stream *buf, void *val) +{ + buf->end_addr = val; +} + +static inline void audio_stream_set_addr(struct audio_stream *buf, void *val) +{ + buf->addr = val; +} + +static inline void audio_stream_set_size(struct audio_stream *buf, uint32_t val) +{ + buf->size = val; +} + +static inline void audio_stream_set_avail(struct audio_stream *buf, uint32_t val) +{ + buf->avail = val; +} + +static inline void audio_stream_set_free(struct audio_stream *buf, uint32_t val) +{ + buf->free = val; +} + +static inline void audio_stream_set_frm_fmt(struct audio_stream *buf, + enum sof_ipc_frame val) +{ + buf->runtime_stream_params.frame_fmt = val; + audio_stream_recalc_align(buf); +} + +static inline void audio_stream_set_valid_fmt(struct audio_stream *buf, + enum sof_ipc_frame val) +{ + buf->runtime_stream_params.valid_sample_fmt = val; +} + +static inline void audio_stream_set_rate(struct audio_stream *buf, uint32_t val) +{ + buf->runtime_stream_params.rate = val; +} + +static inline void audio_stream_set_channels(struct audio_stream *buf, uint16_t val) +{ + buf->runtime_stream_params.channels = val; + audio_stream_recalc_align(buf); +} + +static inline void audio_stream_set_underrun(struct audio_stream *buf, + bool underrun_permitted) +{ + buf->runtime_stream_params.underrun_permitted = underrun_permitted; +} + +static inline void audio_stream_set_overrun(struct audio_stream *buf, + bool overrun_permitted) +{ + buf->runtime_stream_params.overrun_permitted = overrun_permitted; +} + +static inline void audio_stream_set_buffer_fmt(struct audio_stream *buf, + uint32_t buffer_fmt) +{ + buf->runtime_stream_params.buffer_fmt = buffer_fmt; +} + +/** + * Retrieves readable address of a sample at specified index (see versions of + * this macro specialized for various sample types). + * @param buffer Buffer. + * @param idx Index of sample. + * @param size Size of sample in bytes. + * @return Pointer to the sample. + * + * Once the consumer finishes reading samples from the buffer, it should + * "commit" the operation and update the buffer state by calling + * audio_stream_consume(). + * + * @note Components should call comp_update_buffer_consume(). + * + * @see audio_stream_get_frag(). + * @see audio_stream_consume(). + * @see comp_update_buffer_consume(). + */ #define audio_stream_read_frag(buffer, idx, size) \ - audio_stream_get_frag(buffer, buffer->r_ptr, idx, size) + audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, size) +/** + * Retrieves readable address of a signed 16-bit sample at specified index. + * @param buffer Buffer. + * @param idx Index of sample. + * @return Pointer to the sample. + * + * @see audio_stream_get_frag(). + */ #define audio_stream_read_frag_s16(buffer, idx) \ - audio_stream_get_frag(buffer, buffer->r_ptr, idx, sizeof(int16_t)) + audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, sizeof(int16_t)) +/** + * Retrieves readable address of a signed 32-bit sample at specified index. + * @param buffer Buffer. + * @param idx Index of sample. + * @return Pointer to the sample. + * + * @see audio_stream_get_frag(). + */ #define audio_stream_read_frag_s32(buffer, idx) \ - audio_stream_get_frag(buffer, buffer->r_ptr, idx, sizeof(int32_t)) + audio_stream_get_frag(buffer, (buffer)->r_ptr, idx, sizeof(int32_t)) +/** + * Retrieves writeable address of a sample at specified index (see versions of + * this macro specialized for various sample types). + * @param buffer Buffer. + * @param idx Index of sample. + * @param size Size of sample in bytes. + * @return Pointer to the space for sample. + * + * Once the producer finishes writing samples to the buffer, it should + * "commit" the operation and update the buffer state by calling + * audio_stream_produce(). + * + * @note Components should call comp_update_buffer_produce(). + * + * @see audio_stream_get_frag(). + * @see audio_stream_produce(). + * @see comp_update_buffer_produce(). + */ #define audio_stream_write_frag(buffer, idx, size) \ - audio_stream_get_frag(buffer, buffer->w_ptr, idx, size) + audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, size) +/** + * Retrieves writeable address of a signed 16-bit sample at specified index. + * @param buffer Buffer. + * @param idx Index of sample. + * @return Pointer to the space for sample. + * + * @see audio_stream_get_frag(). + */ #define audio_stream_write_frag_s16(buffer, idx) \ - audio_stream_get_frag(buffer, buffer->w_ptr, idx, sizeof(int16_t)) + audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, sizeof(int16_t)) +/** + * Retrieves writeable address of a signed 32-bit sample at specified index. + * @param buffer Buffer. + * @param idx Index of sample. + * @return Pointer to the space for sample. + * + * @see audio_stream_get_frag(). + */ #define audio_stream_write_frag_s32(buffer, idx) \ - audio_stream_get_frag(buffer, buffer->w_ptr, idx, sizeof(int32_t)) + audio_stream_get_frag(buffer, (buffer)->w_ptr, idx, sizeof(int32_t)) +/** + * Retrieves address of sample (space for sample) at specified index within + * the buffer. Index is interpreted as an offset relative to the specified + * pointer, rollover is ensured. + * @param buffer Circular buffer. + * @param ptr Pointer to start from, it may be either read or write pointer. + * @param idx Index of the sample. + * @param sample_size Size of the sample in bytes. + * @return Pointer to the sample. + */ #define audio_stream_get_frag(buffer, ptr, idx, sample_size) \ audio_stream_wrap(buffer, (char *)(ptr) + ((idx) * (sample_size))) +/** + * Calculates period size in bytes based on component stream's parameters. + * @param buf Component buffer. + * @return Period size in bytes. + */ +static inline uint32_t audio_stream_frame_bytes(const struct audio_stream *buf) +{ + return get_frame_bytes(buf->runtime_stream_params.frame_fmt, + buf->runtime_stream_params.channels); +} + +/** + * Calculates sample size in bytes based on component stream's parameters. + * @param buf Component buffer. + * @return Size of sample in bytes. + */ +static inline uint32_t audio_stream_sample_bytes(const struct audio_stream *buf) +{ + return get_sample_bytes(buf->runtime_stream_params.frame_fmt); +} + +/** + * @brief Set processing alignment requirements + * + * Sets the sample byte alignment and aligned frame count required for + * processing done on this stream. This function may be called at any + * time, the internal constants are recalculated if the frame/sample + * size changes. @see audio_stream_avail_frames_aligned(). + * + * @param byte_align Processing byte alignment requirement. + * @param frame_align_req Processing frames alignment requirement. + * @param stream Sink or source stream structure which to be set. + */ +void audio_stream_set_align(const uint32_t byte_align, + const uint32_t frame_align_req, + struct audio_stream *stream); + +/** + * Applies parameters to the buffer. + * @param buffer Audio stream buffer. + * @param params Parameters (frame format, rate, number of channels). + * @return 0 if succeeded, error code otherwise. + */ static inline int audio_stream_set_params(struct audio_stream *buffer, struct sof_ipc_stream_params *params) { if (!params) return -EINVAL; - buffer->frame_fmt = params->frame_fmt; - buffer->rate = params->rate; - buffer->channels = params->channels; + buffer->runtime_stream_params.frame_fmt = (enum sof_ipc_frame)params->frame_fmt; + buffer->runtime_stream_params.rate = params->rate; + buffer->runtime_stream_params.channels = params->channels; + + audio_stream_recalc_align(buffer); return 0; } -static inline void *audio_stream_wrap(const struct audio_stream *buffer, - void *ptr) +/** + * Calculates period size in bytes based on component stream's parameters. + * @param buf Component buffer. + * @param frames Number of processing frames. + * @return Period size in bytes. + */ +static inline uint32_t audio_stream_period_bytes(const struct audio_stream *buf, uint32_t frames) +{ + return frames * audio_stream_frame_bytes(buf); +} + +/** + * Verifies the pointer and performs rollover when reached the end of + * the buffer. + * @param buffer Buffer accessed by the pointer. + * @param ptr Pointer + * @return Pointer, adjusted if necessary. + */ +static inline void *audio_stream_wrap(const struct audio_stream *buffer, void *ptr) { if (ptr >= buffer->end_addr) ptr = (char *)buffer->addr + ((char *)ptr - (char *)buffer->end_addr); + assert((intptr_t)ptr <= (intptr_t)buffer->end_addr); + + return ptr; +} + +/** + * Verifies the pointer and performs rollover when reached the end of + * the circular buffer. + * @param ptr Pointer + * @param buf_addr Start address of the circular buffer. + * @param buf_end End address of the circular buffer. + * @return Pointer, adjusted if necessary. + */ +static inline void *cir_buf_wrap(void *ptr, void *buf_addr, void *buf_end) +{ + if (ptr >= buf_end) + ptr = (char *)buf_addr + + ((char *)ptr - (char *)buf_end); + + assert((intptr_t)ptr <= (intptr_t)buf_end); + + return ptr; +} + +/** + * Verifies the pointer and performs rollover when reached the end of + * the buffer. + * @param buffer Buffer accessed by the pointer. + * @param ptr Pointer + * @return Pointer, adjusted if necessary. + */ +static inline void *audio_stream_rewind_wrap(const struct audio_stream *buffer, void *ptr) +{ + if (ptr < buffer->addr) + ptr = (char *)buffer->end_addr - ((char *)buffer->addr - (char *)ptr); + + assert((intptr_t)ptr >= (intptr_t)buffer->addr); + return ptr; } -/* get the max number of bytes that can be copied between sink and source */ +/** + * Calculates available data in bytes, handling underrun_permitted behaviour + * @param stream Stream pointer + * @return amount of data available for processing in bytes + */ +static inline uint32_t +audio_stream_get_avail_bytes(const struct audio_stream *stream) +{ + /* + * In case of underrun-permitted stream, report buffer full instead of + * empty. This way, any data present in such stream is processed at + * regular pace, but buffer will never be seen as completely empty by + * clients, and in turn will not cause underrun/XRUN. + */ + if (stream->runtime_stream_params.underrun_permitted) + return stream->avail != 0 ? stream->avail : stream->size; + + return stream->avail; +} + +/** + * Calculates available data in samples, handling underrun_permitted behaviour + * @param stream Stream pointer + * @return amount of data available for processing in samples + */ +static inline uint32_t +audio_stream_get_avail_samples(const struct audio_stream *stream) +{ + return audio_stream_get_avail_bytes(stream) / + audio_stream_sample_bytes(stream); +} + +/** + * Calculates available data in frames, handling underrun_permitted behaviour + * @param stream Stream pointer + * @return amount of data available for processing in frames + */ +static inline uint32_t +audio_stream_get_avail_frames(const struct audio_stream *stream) +{ + return audio_stream_get_avail_bytes(stream) / + audio_stream_frame_bytes(stream); +} + +/** + * Calculates free space in bytes, handling overrun_permitted behaviour + * @param stream Stream pointer + * @return amount of space free in bytes + */ +static inline uint32_t +audio_stream_get_free_bytes(const struct audio_stream *stream) +{ + /* + * In case of overrun-permitted stream, report buffer empty instead of + * full. This way, if there's any actual free space for data it is + * processed at regular pace, but buffer will never be seen as + * completely full by clients, and in turn will not cause overrun/XRUN. + */ + if (stream->runtime_stream_params.overrun_permitted) + return stream->free != 0 ? stream->free : stream->size; + + return stream->free; +} + +/** + * Calculates free space in samples, handling overrun_permitted behaviour + * @param stream Stream pointer + * @return amount of space free in samples + */ +static inline uint32_t +audio_stream_get_free_samples(const struct audio_stream *stream) +{ + return audio_stream_get_free_bytes(stream) / + audio_stream_sample_bytes(stream); +} + +/** + * Calculates free space in frames, handling overrun_permitted behaviour + * @param stream Stream pointer + * @return amount of space free in frames + */ +static inline uint32_t +audio_stream_get_free_frames(const struct audio_stream *stream) +{ + return audio_stream_get_free_bytes(stream) / + audio_stream_frame_bytes(stream); +} + +/** + * Verifies whether specified number of bytes can be copied from source buffer + * to sink buffer. + * @param source Source buffer. + * @param sink Sink buffer. + * @param bytes Number of bytes to copy. + * @return 0 if there is enough data in source and enough free space in sink. + * @return 1 if there is not enough free space in sink. + * @return -1 if there is not enough data in source. + */ static inline int audio_stream_can_copy_bytes(const struct audio_stream *source, const struct audio_stream *sink, uint32_t bytes) { /* check for underrun */ - if (source->avail < bytes) + if (audio_stream_get_avail_bytes(source) < bytes) return -1; /* check for overrun */ - if (sink->free < bytes) + if (audio_stream_get_free_bytes(sink) < bytes) return 1; /* we are good to copy */ return 0; } +/** + * Computes maximum number of bytes that can be copied from source buffer to + * sink buffer, verifying number of bytes available in source vs. free space + * available in sink. + * @param source Source buffer. + * @param sink Sink buffer. + * @return Number of bytes. + */ static inline uint32_t audio_stream_get_copy_bytes(const struct audio_stream *source, const struct audio_stream *sink) { - if (source->avail > sink->free) - return sink->free; + uint32_t avail = audio_stream_get_avail_bytes(source); + uint32_t free = audio_stream_get_free_bytes(sink); + + if (avail > free) + return free; else - return source->avail; + return avail; } /** - * Calculates period size in bytes based on component stream's parameters. - * @param buf Component buffer. - * @return Period size in bytes. + * Computes maximum number of frames that can be copied from source buffer + * to sink buffer, verifying number of available source frames vs. free + * space available in sink. + * @param source Source buffer. + * @param sink Sink buffer. + * @return Number of frames. */ -static inline uint32_t audio_stream_frame_bytes(const struct audio_stream *buf) +static inline uint32_t +audio_stream_avail_frames(const struct audio_stream *source, + const struct audio_stream *sink) { - return get_frame_bytes(buf->frame_fmt, buf->channels); + uint32_t src_frames = audio_stream_get_avail_frames(source); + uint32_t sink_frames = audio_stream_get_free_frames(sink); + + return MIN(src_frames, sink_frames); } /** - * Calculates sample size in bytes based on component stream's parameters. - * @param buf Component buffer. - * @return Size of sample in bytes. + * Rounds down a frame count to meet the alignment constraint of the stream. + * @param stream Audio stream with alignment requirements set. + * @param frames Frame count to round down. + * @return Largest aligned frame count less than or equal to frames. */ -static inline uint32_t audio_stream_sample_bytes(const struct audio_stream *buf) +static inline uint32_t audio_stream_align_frames_round_down(const struct audio_stream *stream, + uint32_t frames) { - return get_sample_bytes(buf->frame_fmt); + uint16_t align = stream->runtime_stream_params.align_frame_cnt; + + return ROUND_DOWN(frames, align); } /** - * Calculates period size in bytes based on component stream's parameters. - * @param buf Component buffer. - * @param frames Number of processing frames. - * @return Period size in bytes. + * Rounds up a frame count to meet the alignment constraint of the stream. + * @param stream Audio stream with alignment requirements set. + * @param frames Frame count to round up. + * @return Smallest aligned frame count greater than or equal to frames. */ -static inline uint32_t audio_stream_period_bytes(const struct audio_stream *buf, - uint32_t frames) +static inline uint32_t audio_stream_align_frames_round_up(const struct audio_stream *stream, + uint32_t frames) { - return frames * audio_stream_frame_bytes(buf); + uint16_t align = stream->runtime_stream_params.align_frame_cnt; + uint32_t aligned_frames = ROUND_DOWN(frames, align); + + if (aligned_frames < frames) + aligned_frames += align; + + return aligned_frames; } +/** + * Rounds to nearest a frame count to meet the alignment constraint of the stream. + * @param stream Audio stream with alignment requirements set. + * @param frames Frame count to round to nearest. + * @return Aligned frame count. + */ +static inline uint32_t audio_stream_align_frames_round_nearest(const struct audio_stream *stream, + uint32_t frames) +{ + uint16_t align = stream->runtime_stream_params.align_frame_cnt; + + return ROUND_DOWN(frames + (align >> 1), align); +} + +/** + * Computes maximum number of frames aligned with source align criteria + * that can be copied from source buffer to sink buffer, verifying number + * of available source frames vs. free space available in sink. + * @param source Buffer of source. + * @param sink Buffer of sink. + * @return Number of frames. + */ static inline uint32_t -audio_stream_avail_frames(const struct audio_stream *source, - const struct audio_stream *sink) +audio_stream_avail_frames_aligned(const struct audio_stream *source, + const struct audio_stream *sink) { - uint32_t src_frames = source->avail / audio_stream_frame_bytes(source); - uint32_t sink_frames = sink->free / audio_stream_frame_bytes(sink); + uint32_t src_frames = audio_stream_get_avail_frames(source); + uint32_t sink_frames = audio_stream_get_free_frames(sink); + uint32_t n = MIN(src_frames, sink_frames); - return MIN(src_frames, sink_frames); + return audio_stream_align_frames_round_down(source, n); } -/* called only by a comp_buffer procedures */ -static inline void audio_stream_produce(struct audio_stream *buffer, - uint32_t bytes) +/** + * Updates the buffer state after writing to the buffer. + * @param buffer Buffer to update. + * @param bytes Number of written bytes. + */ +static inline void audio_stream_produce(struct audio_stream *buffer, uint32_t bytes) { buffer->w_ptr = audio_stream_wrap(buffer, (char *)buffer->w_ptr + bytes); /* "overwrite" old data in circular wrap case */ - if (bytes > buffer->free) + if (bytes > audio_stream_get_free_bytes(buffer)) buffer->r_ptr = buffer->w_ptr; /* calculate available bytes */ @@ -178,9 +682,12 @@ static inline void audio_stream_produce(struct audio_stream *buffer, buffer->free = buffer->size - buffer->avail; } -/* called only by a comp_buffer procedures */ -static inline void audio_stream_consume(struct audio_stream *buffer, - uint32_t bytes) +/** + * Updates the buffer state after reading from the buffer. + * @param buffer Buffer to update. + * @param bytes Number of read bytes. + */ +static inline void audio_stream_consume(struct audio_stream *buffer, uint32_t bytes) { buffer->r_ptr = audio_stream_wrap(buffer, (char *)buffer->r_ptr + bytes); @@ -198,6 +705,39 @@ static inline void audio_stream_consume(struct audio_stream *buffer, buffer->free = buffer->size - buffer->avail; } +#ifdef __ZEPHYR__ +/** + * Replicates the hardware state of the DMA buffer as a struct audio_stream. + * @param stream Stream to update. + * @param dma_status DMA buffer hardware state (struct dma_status from Zephyr). + */ +static inline void audio_stream_sync_to_hw(struct audio_stream *stream, + const struct dma_status *dma_status) +{ + uintptr_t buf_start = (uintptr_t)audio_stream_get_addr(stream); + + /* Note: It is assumed here that dma_status values are reported as bytes. However, + * this is actually platform-specific. Although unlikely, they could be, for example, + * words on some particular platform, and changes should be made here to address + * such case. + */ + + assert(dma_status->write_position < audio_stream_get_size(stream)); + assert(dma_status->read_position < audio_stream_get_size(stream)); + assert(dma_status->pending_length <= audio_stream_get_size(stream)); + assert(dma_status->free <= audio_stream_get_size(stream)); + + audio_stream_set_wptr(stream, (void *)(buf_start + dma_status->write_position)); + audio_stream_set_rptr(stream, (void *)(buf_start + dma_status->read_position)); + audio_stream_set_avail(stream, dma_status->pending_length); + audio_stream_set_free(stream, dma_status->free); +} +#endif /* __ZEPHYR__ */ + +/** + * Resets the buffer. + * @param buffer Buffer to reset. + */ static inline void audio_stream_reset(struct audio_stream *buffer) { /* reset read and write pointer to buffer bas */ @@ -211,17 +751,21 @@ static inline void audio_stream_reset(struct audio_stream *buffer) buffer->avail = 0; } -static inline void audio_stream_init(struct audio_stream *buffer, - void *buff_addr, uint32_t size) -{ - buffer->size = size; - buffer->addr = buff_addr; - buffer->end_addr = (char *)buffer->addr + size; - audio_stream_reset(buffer); -} +/** + * Initializes the buffer with specified memory block and size. + * @param audio_stream the audio_stream a to initialize. + * @param buff_addr Address of the memory block to assign. + * @param size Size of the memory block in bytes. + */ +void audio_stream_init(struct audio_stream *audio_stream, void *buff_addr, uint32_t size); -static inline void audio_stream_invalidate(struct audio_stream *buffer, - uint32_t bytes) +/** + * Invalidates (in DSP d-cache) the buffer in range [r_ptr, r_ptr+bytes], + * with rollover if necessary. + * @param buffer Buffer. + * @param bytes Size of the fragment to invalidate. + */ +static inline void audio_stream_invalidate(struct audio_stream *buffer, uint32_t bytes) { uint32_t head_size = bytes; uint32_t tail_size = 0; @@ -232,13 +776,19 @@ static inline void audio_stream_invalidate(struct audio_stream *buffer, tail_size = bytes - head_size; } - dcache_invalidate_region(buffer->r_ptr, head_size); + dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->r_ptr, head_size); if (tail_size) - dcache_invalidate_region(buffer->addr, tail_size); + dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->addr, + tail_size); } -static inline void audio_stream_writeback(struct audio_stream *buffer, - uint32_t bytes) +/** + * Writes back (from DSP d-cache) the buffer in range [w_ptr, w_ptr+bytes], + * with rollover if necessary. + * @param buffer Buffer. + * @param bytes Size of the fragment to write back. + */ +static inline void audio_stream_writeback(struct audio_stream *buffer, uint32_t bytes) { uint32_t head_size = bytes; uint32_t tail_size = 0; @@ -249,70 +799,326 @@ static inline void audio_stream_writeback(struct audio_stream *buffer, tail_size = bytes - head_size; } - dcache_writeback_region(buffer->w_ptr, head_size); + dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, head_size); if (tail_size) - dcache_writeback_region(buffer->addr, tail_size); + dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->addr, + tail_size); } -static inline void audio_stream_copy(const struct audio_stream *source, - uint32_t ioffset_bytes, - struct audio_stream *sink, - uint32_t ooffset_bytes, uint32_t bytes) +/** + * @brief Calculates numbers of bytes to buffer wrap. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of data samples to buffer wrap. + */ +static inline int +audio_stream_bytes_without_wrap(const struct audio_stream *source, const void *ptr) { - void *src = audio_stream_wrap(source, - (char *)source->r_ptr + ioffset_bytes); - void *snk = audio_stream_wrap(sink, - (char *)sink->w_ptr + ooffset_bytes); - uint32_t bytes_src; - uint32_t bytes_snk; - uint32_t bytes_copied; - int ret; + assert((intptr_t)source->end_addr >= (intptr_t)ptr); + return (intptr_t)source->end_addr - (intptr_t)ptr; +} - while (bytes) { - bytes_src = (char *)source->end_addr - (char *)src; - bytes_snk = (char *)sink->end_addr - (char *)snk; - bytes_copied = MIN(bytes, MIN(bytes_src, bytes_snk)); +/** + * @brief Calculates numbers of bytes to buffer wrap when reading stream + * backwards from current sample pointed by ptr towards begin. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of bytes to buffer wrap. For number of samples calculate + * need to add size of sample to returned bytes count. + */ +static inline int +audio_stream_rewind_bytes_without_wrap(const struct audio_stream *source, const void *ptr) +{ + assert((intptr_t)ptr >= (intptr_t)source->addr); + int to_begin = (intptr_t)ptr - (intptr_t)source->addr; + return to_begin; +} - ret = memcpy_s(snk, bytes_snk, src, bytes_copied); - assert(!ret); +/** + * @brief Calculate position of write pointer to the position before the data was copied + * to source buffer. + * @param source Stream to get information from. + * @param bytes Number of bytes copied to source buffer. + * @return Previous position of the write pointer. + */ +static inline uint32_t +*audio_stream_rewind_wptr_by_bytes(const struct audio_stream *source, const uint32_t bytes) +{ + void *wptr = audio_stream_get_wptr(source); + int to_begin = audio_stream_rewind_bytes_without_wrap(source, wptr); - bytes -= bytes_copied; - src = (char *)src + bytes_copied; - snk = (char *)snk + bytes_copied; + assert((intptr_t)wptr >= (intptr_t)source->addr); + assert((intptr_t)source->end_addr > (intptr_t)wptr); - src = audio_stream_wrap(source, src); - snk = audio_stream_wrap(sink, snk); - } + if (to_begin > bytes) + return (uint32_t *)((intptr_t)wptr - bytes); + else + return (uint32_t *)((intptr_t)source->end_addr - (bytes - to_begin)); } -#if CONFIG_FORMAT_S16LE +/** + * @brief Calculates numbers of s16 samples to buffer wrap when buffer + * is read forward towards end address. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of data s16 samples until circular wrap need at end + */ +static inline int +audio_stream_samples_without_wrap_s16(const struct audio_stream *source, const void *ptr) +{ + int to_end = (int16_t *)source->end_addr - (int16_t *)ptr; -static inline void audio_stream_copy_s16(const struct audio_stream *source, - uint32_t ioffset, - struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) + assert((intptr_t)source->end_addr >= (intptr_t)ptr); + return to_end; +} + +/** + * @brief Calculates numbers of s24 samples to buffer wrap when buffer + * is read forward towards end address. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of data s24 samples until circular wrap need at end + */ +static inline int +audio_stream_samples_without_wrap_s24(const struct audio_stream *source, const void *ptr) { - const int ssize = sizeof(int16_t); + int to_end = (int32_t *)source->end_addr - (int32_t *)ptr; - audio_stream_copy(source, ioffset * ssize, sink, ooffset * ssize, - samples * ssize); + assert((intptr_t)source->end_addr >= (intptr_t)ptr); + return to_end; } -#endif /* CONFIG_FORMAT_S16LE */ +/** + * @brief Calculates numbers of s32 samples to buffer wrap when buffer + * is read forward towards end address. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of data s32 samples until circular wrap need at end + */ +static inline int +audio_stream_samples_without_wrap_s32(const struct audio_stream *source, const void *ptr) +{ + int to_end = (int32_t *)source->end_addr - (int32_t *)ptr; + + assert((intptr_t)source->end_addr >= (intptr_t)ptr); + return to_end; +} + +/** + * @brief Calculates numbers of bytes to buffer wrap when reading stream + * backwards from current sample pointed by ptr towards begin. + * @param ptr Read or write pointer og circular buffer. + * @param buf_end End address of circular buffer. + * @return Number of bytes to buffer wrap. For number of samples calculate + * need to add size of sample to returned bytes count. + */ +static inline int cir_buf_bytes_without_wrap(void *ptr, void *buf_end) +{ + assert((intptr_t)buf_end >= (intptr_t)ptr); + return (intptr_t)buf_end - (intptr_t)ptr; +} + +/** + * @brief Calculates numbers of s32 samples to buffer wrap when reading stream + * backwards from current sample pointed by ptr towards begin. + * @param ptr Read or write pointer og circular buffer. + * @param buf_end End address of circular buffer. + * @return Number of bytes to buffer wrap. For number of samples calculate + * need to add size of sample to returned bytes count. + */ +static inline int cir_buf_samples_without_wrap_s32(void *ptr, void *buf_end) +{ + int to_end = (int32_t *)buf_end - (int32_t *)ptr; -#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE || CONFIG_FORMAT_FLOAT + assert((intptr_t)buf_end >= (intptr_t)ptr); + return to_end; +} -static inline void audio_stream_copy_s32(const struct audio_stream *source, - uint32_t ioffset, - struct audio_stream *sink, - uint32_t ooffset, uint32_t samples) +/** + * @brief Calculates numbers of frames to buffer wrap and return + * minimum of calculated value. + * @param source Stream to get information from. + * @param ptr Read or write pointer from source + * @return Number of data frames to buffer wrap. + */ +static inline uint32_t +audio_stream_frames_without_wrap(const struct audio_stream *source, const void *ptr) { - const int ssize = sizeof(int32_t); + uint32_t bytes = audio_stream_bytes_without_wrap(source, ptr); + uint32_t frame_bytes = audio_stream_frame_bytes(source); - audio_stream_copy(source, ioffset * ssize, sink, ooffset * ssize, - samples * ssize); + return bytes / frame_bytes; } -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE || CONFIG_FORMAT_FLOAT */ +/** + * Copies data from source buffer to sink buffer. + * @param source Source buffer. + * @param ioffset Offset (in samples) in source buffer to start reading from. + * @param sink Sink buffer. + * @param ooffset Offset (in samples) in sink buffer to start writing to. + * @param samples Number of samples to copy. + * @return number of processed samples. + */ +int audio_stream_copy(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, uint32_t samples); + +/** + * Copies data from one circular buffer to another circular buffer. + * @param src Source pointer of source circular buffer. + * @param src_addr Start address of source circular buffer. + * @param src_end End address of source circular buffer. + * @param dst Sink pointer of source circular buffer. + * @param dst_addr Start address of sink circular buffer + * @param dst_end End address of sink circular buffer. + * @param byte_size Number of bytes to copy. + */ +void cir_buf_copy(void *src, void *src_addr, void *src_end, void *dst, + void *dst_addr, void *dst_end, size_t byte_size); + +/** + * Copies data from linear source buffer to circular sink buffer. + * @param linear_source Source buffer. + * @param ioffset Offset (in samples) in source buffer to start reading from. + * @param sink Sink buffer. + * @param ooffset Offset (in samples) in sink buffer to start writing to. + * @param samples Number of samples to copy. + */ +void audio_stream_copy_from_linear(const void *linear_source, int ioffset, + struct audio_stream *sink, int ooffset, + unsigned int samples); + +/** + * Copies data from circular source buffer to linear sink buffer. + * @param source Source buffer. + * @param ioffset Offset (in samples) in source buffer to start reading from. + * @param linear_sink Sink buffer. + * @param ooffset Offset (in samples) in sink buffer to start writing to. + * @param samples Number of samples to copy. + */ +void audio_stream_copy_to_linear(const struct audio_stream *source, int ioffset, + void *linear_sink, int ooffset, unsigned int samples); + +/** + * Writes zeros in range [w_ptr, w_ptr+bytes], with rollover if necessary. + * @param buffer Buffer. + * @param bytes Size of the fragment to write zero. + * @return 0 if there is enough free space in buffer. + * @return 1 if there is not enough free space in buffer. + */ +static inline int audio_stream_set_zero(struct audio_stream *buffer, uint32_t bytes) +{ + uint32_t head_size = bytes; + uint32_t tail_size = 0; + + /* check for overrun */ + if (audio_stream_get_free_bytes(buffer) < bytes) + return 1; + + /* check for potential wrap */ + if ((char *)buffer->w_ptr + bytes > (char *)buffer->end_addr) { + head_size = (char *)buffer->end_addr - (char *)buffer->w_ptr; + tail_size = bytes - head_size; + } + + memset(buffer->w_ptr, 0, head_size); + if (tail_size) + memset(buffer->addr, 0, tail_size); + + return 0; +} + +/** + * Writes zeros to circular buffer in range [ptr, ptr+bytes] with rollover if necessary. + * @param ptr Pointer inside circular biffer to start writing from. + * @param buf_addr Start of the circular buffer. + * @param buf_end End of the circular buffer. + * @param bytes Size of the fragment to write zeros. + */ +static inline void cir_buf_set_zero(void *ptr, void *buf_addr, void *buf_end, uint32_t bytes) +{ + uint32_t head_size = bytes; + uint32_t tail_size = 0; + + /* check for potential wrap */ + if ((char *)ptr + bytes > (char *)buf_end) { + head_size = (char *)buf_end - (char *)ptr; + tail_size = bytes - head_size; + } + + memset(ptr, 0, head_size); + if (tail_size) + memset(buf_addr, 0, tail_size); +} + +static inline int audio_stream_fmt_conversion(enum ipc4_bit_depth depth, + enum ipc4_bit_depth valid, + enum sof_ipc_frame *frame_fmt, + enum sof_ipc_frame *valid_fmt, + enum ipc4_sample_type type) +{ + int ret = -EINVAL; + *frame_fmt = SOF_IPC_FRAME_INVALID; + *valid_fmt = SOF_IPC_FRAME_INVALID; + + switch (type) { + case IPC4_TYPE_FLOAT: +#ifdef CONFIG_FORMAT_FLOAT + if (depth == 32 && valid == 32) { + *frame_fmt = SOF_IPC_FRAME_FLOAT; + *valid_fmt = SOF_IPC_FRAME_FLOAT; + ret = 0; + } +#endif + break; + case IPC4_TYPE_MSB_INTEGER: + case IPC4_TYPE_LSB_INTEGER: + case IPC4_TYPE_SIGNED_INTEGER: + if (depth == 24 && valid == 24) { +#ifdef CONFIG_FORMAT_S24_3LE + *frame_fmt = SOF_IPC_FRAME_S24_3LE; + *valid_fmt = SOF_IPC_FRAME_S24_3LE; + ret = 0; +#endif + } else { + /* IPC4_DEPTH_16BIT (16) <---> SOF_IPC_FRAME_S16_LE (0) + * IPC4_DEPTH_24BIT (24) <---> SOF_IPC_FRAME_S24_4LE (1) + * IPC4_DEPTH_32BIT (32) <---> SOF_IPC_FRAME_S32_LE (2) + */ + *frame_fmt = (enum sof_ipc_frame)((depth >> 3) - 2); + *valid_fmt = (enum sof_ipc_frame)((valid >> 3) - 2); + ret = 0; + } + break; + case IPC4_TYPE_UNSIGNED_INTEGER: +#ifdef CONFIG_FORMAT_U8 + if (depth == 8 && valid == 8) { + *frame_fmt = SOF_IPC_FRAME_U8; + *valid_fmt = SOF_IPC_FRAME_U8; + ret = 0; + } +#endif /* CONFIG_FORMAT_U8 */ + break; + case IPC4_TYPE_A_LAW: +#ifdef CONFIG_FORMAT_A_LAW + if (depth == 8 && valid == 8) { + *frame_fmt = SOF_IPC_FRAME_A_LAW; + *valid_fmt = SOF_IPC_FRAME_A_LAW; + ret = 0; + } +#endif + break; + case IPC4_TYPE_MU_LAW: +#ifdef CONFIG_FORMAT_MU_LAW + if (depth == 8 && valid == 8) { + *frame_fmt = SOF_IPC_FRAME_MU_LAW; + *valid_fmt = SOF_IPC_FRAME_MU_LAW; + ret = 0; + } +#endif + break; + } + return ret; +} +/** @}*/ #endif /* __SOF_AUDIO_AUDIO_STREAM_H__ */ diff --git a/src/include/sof/audio/buffer.h b/src/include/sof/audio/buffer.h index d9930adf9b88..6e6b8a9caef8 100644 --- a/src/include/sof/audio/buffer.h +++ b/src/include/sof/audio/buffer.h @@ -9,48 +9,100 @@ #define __SOF_AUDIO_BUFFER_H__ #include <sof/audio/audio_stream.h> +#include <sof/audio/audio_buffer.h> #include <sof/audio/pipeline.h> #include <sof/math/numbers.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <rtos/panic.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/list.h> +#include <sof/coherent.h> #include <sof/math/numbers.h> -#include <sof/spinlock.h> -#include <sof/string.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> #include <sof/trace/trace.h> #include <ipc/stream.h> #include <ipc/topology.h> #include <user/trace.h> #include <sof/audio/format.h> -#include <config.h> + #include <stdbool.h> #include <stddef.h> #include <stdint.h> struct comp_dev; +struct buffer_cb_transact; + +/** \name Trace macros + * @{ + */ /* buffer tracing */ -#define trace_buffer(__e, ...) \ - trace_event(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__) -#define trace_buffer_with_ids(buf_ptr, __e, ...) \ - trace_event_with_ids(TRACE_CLASS_BUFFER, 0, (buf_ptr)->pipeline_id, \ - (buf_ptr)->id, __e, ##__VA_ARGS__) - -#define tracev_buffer(__e, ...) \ - tracev_event(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__) -#define tracev_buffer_with_ids(buf_ptr, __e, ...) \ - tracev_event_with_ids(TRACE_CLASS_BUFFER, 0, (buf_ptr)->pipeline_id, \ - (buf_ptr)->id, __e, ##__VA_ARGS__) - -#define trace_buffer_error(__e, ...) \ - trace_error(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__) -#define trace_buffer_error_atomic(__e, ...) \ - trace_error_atomic(TRACE_CLASS_BUFFER, __e, ##__VA_ARGS__) -#define trace_buffer_error_with_ids(buf_ptr, __e, ...) \ - trace_error_with_ids(TRACE_CLASS_BUFFER, 0, (buf_ptr)->pipeline_id, \ - (buf_ptr)->id, __e, ##__VA_ARGS__) +extern struct tr_ctx buffer_tr; + +/** \brief Retrieves trace context from the buffer */ +#define trace_buf_get_tr_ctx(buf_ptr) (&(buf_ptr)->tctx) + +/** \brief Retrieves subid (comp id) from the buffer */ +#define buf_get_id(buf_ptr) ((buf_ptr)->stream.runtime_stream_params.id) + +#if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) + +#if CONFIG_IPC_MAJOR_4 +#define __BUF_FMT "buf:%u %#x " +#else +#define __BUF_FMT "buf:%u.%u " +#endif + +#define buf_err(buf_ptr, __e, ...) LOG_ERR(__BUF_FMT __e, buffer_pipeline_id(buf_ptr), \ + buf_get_id(buf_ptr), ##__VA_ARGS__) + +#define buf_warn(buf_ptr, __e, ...) LOG_WRN(__BUF_FMT __e, buffer_pipeline_id(buf_ptr), \ + buf_get_id(buf_ptr), ##__VA_ARGS__) + +#define buf_info(buf_ptr, __e, ...) LOG_INF(__BUF_FMT __e, buffer_pipeline_id(buf_ptr), \ + buf_get_id(buf_ptr), ##__VA_ARGS__) + +#define buf_dbg(buf_ptr, __e, ...) LOG_DBG(__BUF_FMT __e, buffer_pipeline_id(buf_ptr), \ + buf_get_id(buf_ptr), ##__VA_ARGS__) + +#else +/** \brief Trace error message from buffer */ +#define buf_err(buf_ptr, __e, ...) \ + trace_dev_err(trace_buf_get_tr_ctx, buffer_pipeline_id, \ + buf_get_id, \ + (__sparse_force const struct comp_buffer *)buf_ptr, \ + __e, ##__VA_ARGS__) + +/** \brief Trace warning message from buffer */ +#define buf_warn(buf_ptr, __e, ...) \ + trace_dev_warn(trace_buf_get_tr_ctx, buffer_pipeline_id, \ + buf_get_id, \ + (__sparse_force const struct comp_buffer *)buf_ptr, \ + __e, ##__VA_ARGS__) + +/** \brief Trace info message from buffer */ +#define buf_info(buf_ptr, __e, ...) \ + trace_dev_info(trace_buf_get_tr_ctx, buffer_pipeline_id, \ + buf_get_id, \ + (__sparse_force const struct comp_buffer *)buf_ptr, \ + __e, ##__VA_ARGS__) + +/** \brief Trace debug message from buffer */ +#if defined(CONFIG_LIBRARY) +#define buf_dbg(buf_ptr, __e, ...) +#else +#define buf_dbg(buf_ptr, __e, ...) \ + trace_dev_dbg(trace_buf_get_tr_ctx, buffer_pipeline_id, \ + buf_get_id, \ + (__sparse_force const struct comp_buffer *)buf_ptr, \ + __e, ##__VA_ARGS__) +#endif + +#endif /* #if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) */ + +/** @}*/ /* buffer callback types */ #define BUFF_CB_TYPE_PRODUCE BIT(0) @@ -65,19 +117,26 @@ struct comp_dev; #define BUFF_PARAMS_RATE BIT(2) #define BUFF_PARAMS_CHANNELS BIT(3) -/* audio component buffer - connects 2 audio components together in pipeline */ -struct comp_buffer { - spinlock_t *lock; /* locking mechanism */ +/* buffer usage */ +#define BUFFER_USAGE_SHARED true /* buffer used by multiple DSP core and/or HW blocks */ +#define BUFFER_USAGE_NOT_SHARED false /* buffer only used by one HW block */ +/* + * audio component buffer - connects 2 audio components together in pipeline. + * + * this is a legacy component connector for pipeline 1.0 + * + */ +struct comp_buffer { /* data buffer */ + struct sof_audio_buffer audio_buffer; + struct audio_stream stream; /* configuration */ - uint32_t id; - uint32_t pipeline_id; - uint32_t caps; + uint32_t flags; uint32_t core; - bool inter_core; /* true if connected to a comp from another core */ + struct tr_ctx tctx; /* trace settings */ /* connected components */ struct comp_dev *source; /* source component */ @@ -87,43 +146,68 @@ struct comp_buffer { struct list_item source_list; /* list in comp buffers */ struct list_item sink_list; /* list in comp buffers */ - /* runtime stream params */ - uint32_t buffer_fmt; /**< enum sof_ipc_buffer_format */ - uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */ - - bool hw_params_configured; /**< indicates whether hw params were set */ + /* list of buffers, to be used i.e. in raw data processing mode*/ + struct list_item buffers_list; + +#if CONFIG_PROBE + /** probe produce callback, called on buffer produce */ + void (*probe_cb_produce)(void *arg, struct buffer_cb_transact *cb_data); + /** probe free callback, called on buffer free */ + void (*probe_cb_free)(void *arg); + /** opaque argument passed to probe callbacks */ + void *probe_cb_arg; +#endif }; +/* + * get a component providing data to the buffer + */ +static inline struct comp_dev *comp_buffer_get_source_component(const struct comp_buffer *buffer) +{ + return buffer->source; +} + +/* + * get a component consuming data from the buffer + */ +static inline struct comp_dev *comp_buffer_get_sink_component(const struct comp_buffer *buffer) +{ + return buffer->sink; +} + +static inline +void comp_buffer_set_source_component(struct comp_buffer *buffer, struct comp_dev *comp) +{ + buffer->source = comp; +} + +static inline +void comp_buffer_set_sink_component(struct comp_buffer *buffer, struct comp_dev *comp) +{ + buffer->sink = comp; +} + +static inline void comp_buffer_reset_source_list(struct comp_buffer *buffer) +{ + list_init(&buffer->source_list); +} + +static inline void comp_buffer_reset_sink_list(struct comp_buffer *buffer) +{ + list_init(&buffer->sink_list); +} + +/* Used as parameter for probe produce callback */ struct buffer_cb_transact { struct comp_buffer *buffer; uint32_t transaction_amount; void *transaction_begin_address; }; -struct buffer_cb_free { - struct comp_buffer *buffer; -}; - -#define buffer_comp_list(buffer, dir) \ - ((dir) == PPL_DIR_DOWNSTREAM ? &buffer->source_list : \ - &buffer->sink_list) - -#define buffer_from_list(ptr, type, dir) \ +#define buffer_from_list(ptr, dir) \ ((dir) == PPL_DIR_DOWNSTREAM ? \ - container_of(ptr, type, source_list) : \ - container_of(ptr, type, sink_list)) - -#define buffer_get_comp(buffer, dir) \ - ((dir) == PPL_DIR_DOWNSTREAM ? buffer->sink : \ - buffer->source) - -#define buffer_set_comp(buffer, comp, dir) \ - do { \ - if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) \ - buffer->source = comp; \ - else \ - buffer->sink = comp; \ - } while (0) \ + container_of(ptr, struct comp_buffer, source_list) : \ + container_of(ptr, struct comp_buffer, sink_list)) #define buffer_set_cb(buffer, func, data, type) \ do { \ @@ -132,148 +216,108 @@ struct buffer_cb_free { buffer->cb_type = type; \ } while (0) +struct mod_alloc_ctx; /* pipeline buffer creation and destruction */ -struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t align); -struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc); -int buffer_set_size(struct comp_buffer *buffer, uint32_t size); -void buffer_free(struct comp_buffer *buffer); - -/* called by a component after producing data into this buffer */ -void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes); - -/* called by a component after consuming data from this buffer */ -void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes); - -static inline void buffer_invalidate(struct comp_buffer *buffer, uint32_t bytes) +struct comp_buffer *buffer_alloc(struct mod_alloc_ctx *alloc, size_t size, uint32_t flags, + uint32_t align, bool is_shared); +struct comp_buffer *buffer_alloc_range(struct mod_alloc_ctx *alloc, size_t preferred_size, + size_t minimum_size, + uint32_t flags, uint32_t align, bool is_shared); +struct comp_buffer *buffer_new(struct mod_alloc_ctx *alloc, const struct sof_ipc_buffer *desc, + bool is_shared); + +int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignment); +int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size, + uint32_t alignment); + +/* legacy wrappers, to be removed. Don't use them if possible */ +static inline struct comp_buffer *comp_buffer_get_from_source(struct sof_source *source) { - if (!buffer->inter_core) - return; + struct sof_audio_buffer *audio_buffer = sof_audio_buffer_from_source(source); - audio_stream_invalidate(&buffer->stream, bytes); + return container_of(audio_buffer, struct comp_buffer, audio_buffer); } -static inline void buffer_writeback(struct comp_buffer *buffer, uint32_t bytes) +static inline struct comp_buffer *comp_buffer_get_from_sink(struct sof_sink *sink) { - if (!buffer->inter_core) - return; + struct sof_audio_buffer *audio_buffer = sof_audio_buffer_from_sink(sink); - audio_stream_writeback(&buffer->stream, bytes); + return container_of(audio_buffer, struct comp_buffer, audio_buffer); } -/** - * Locks buffer instance for buffers connecting components - * running on different cores. Buffer parameters will be invalidated - * to make sure the latest data can be retrieved. - * @param buffer Buffer instance. - * @param flags IRQ flags. - */ -static inline void buffer_lock(struct comp_buffer *buffer, uint32_t *flags) +static inline void buffer_free(struct comp_buffer *buffer) { - if (!buffer->inter_core) - return; + audio_buffer_free(&buffer->audio_buffer); +} - spin_lock_irq(buffer->lock, *flags); +/* end of legacy wrappers */ - /* invalidate in case something has changed during our wait */ - dcache_invalidate_region(buffer, sizeof(*buffer)); -} +void buffer_zero(struct comp_buffer *buffer); -/** - * Unlocks buffer instance for buffers connecting components - * running on different cores. Buffer parameters will be flushed - * to make sure all the changes are saved. Also they will be invalidated - * to spare the need of locking/unlocking buffer, when only reading parameters. - * @param buffer Buffer instance. - * @param flags IRQ flags. - */ -static inline void buffer_unlock(struct comp_buffer *buffer, uint32_t flags) -{ - if (!buffer->inter_core) - return; +/* called by a component after producing data into this buffer */ +void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes); - /* save lock pointer to avoid memory access after cache flushing */ - spinlock_t *lock = buffer->lock; +/* called by a component after consuming data from this buffer */ +void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes); - /* wtb and inv to avoid buffer locking in read only situations */ - dcache_writeback_invalidate_region(buffer, sizeof(*buffer)); +int buffer_set_params(struct comp_buffer *buffer, + struct sof_ipc_stream_params *params, bool force_update); - spin_unlock_irq(lock, flags); -} +bool buffer_params_match(struct comp_buffer *buffer, + struct sof_ipc_stream_params *params, uint32_t flag); -static inline void buffer_zero(struct comp_buffer *buffer) +static inline void buffer_stream_invalidate(struct comp_buffer *buffer, uint32_t bytes) { - tracev_buffer_with_ids(buffer, "stream_zero()"); - - bzero(buffer->stream.addr, buffer->stream.size); - if (buffer->caps & SOF_MEM_CAPS_DMA) - dcache_writeback_region(buffer->stream.addr, - buffer->stream.size); +#if CONFIG_INCOHERENT + if (audio_buffer_is_shared(&buffer->audio_buffer)) + audio_stream_invalidate(&buffer->stream, bytes); +#endif } -static inline void buffer_reset_pos(struct comp_buffer *buffer, void *data) +static inline void buffer_stream_writeback(struct comp_buffer *buffer, uint32_t bytes) { - uint32_t flags = 0; - - buffer_lock(buffer, &flags); +#if CONFIG_INCOHERENT + if (audio_buffer_is_shared(&buffer->audio_buffer)) + audio_stream_writeback(&buffer->stream, bytes); +#endif +} - /* reset rw pointers and avail/free bytes counters */ - audio_stream_reset(&buffer->stream); - /* clear buffer contents */ - buffer_zero(buffer); +/* + * Attach a new buffer at the beginning of the list. Note, that "head" must + * really be the head of the list, not a list head within another buffer. We + * don't synchronise its cache, so it must not be embedded in an object, using + * the coherent API. The caller takes care to protect list heads. + */ +void buffer_attach(struct comp_buffer *buffer, struct list_item *head, int dir); - buffer_unlock(buffer, flags); -} +/* + * Detach a buffer from anywhere in the list. "head" is again the head of the + * list, we need it to verify, whether this buffer was the first or the last on + * the list. Again it is assumed that the head's cache doesn't need to be + * synchronized. The caller takes care to protect list heads. + */ +void buffer_detach(struct comp_buffer *buffer, struct list_item *head, int dir); -static inline void buffer_init(struct comp_buffer *buffer, uint32_t size, - uint32_t caps) +static inline struct comp_dev *buffer_get_comp(struct comp_buffer *buffer, int dir) { - buffer->caps = caps; - - /* addr should be set in alloc function */ - audio_stream_init(&buffer->stream, buffer->stream.addr, size); + struct comp_dev *comp = (dir == PPL_DIR_DOWNSTREAM) ? + comp_buffer_get_sink_component(buffer) : + comp_buffer_get_source_component(buffer); + return comp; } -static inline void buffer_reset_params(struct comp_buffer *buffer, void *data) +static inline uint32_t buffer_pipeline_id(const struct comp_buffer *buffer) { - uint32_t flags = 0; - - buffer_lock(buffer, &flags); - - buffer->hw_params_configured = false; - - buffer_unlock(buffer, flags); + return buffer->stream.runtime_stream_params.pipeline_id; } -static inline int buffer_set_params(struct comp_buffer *buffer, - struct sof_ipc_stream_params *params, - bool force_update) +/* Run-time buffer re-configuration calls this too, so it must use cached access */ +static inline void buffer_init_stream(struct comp_buffer *buffer, size_t size) { - int ret; - int i; - - if (!params) { - trace_buffer_error("buffer_set_params() error: !params"); - return -EINVAL; - } - - if (buffer->hw_params_configured && !force_update) - return 0; - - ret = audio_stream_set_params(&buffer->stream, params); - if (ret < 0) { - trace_buffer_error("buffer_set_params() error: audio_stream_set_params failed"); - return -EINVAL; - } - - buffer->buffer_fmt = params->buffer_fmt; - for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) - buffer->chmap[i] = params->chmap[i]; - - buffer->hw_params_configured = true; - - return 0; + /* addr should be set in alloc function */ + audio_stream_init(&buffer->stream, buffer->stream.addr, size); } #endif /* __SOF_AUDIO_BUFFER_H__ */ diff --git a/src/include/sof/audio/cadence/aac_dec/xa_aac_dec_api.h b/src/include/sof/audio/cadence/aac_dec/xa_aac_dec_api.h new file mode 100644 index 000000000000..95e87308f01c --- /dev/null +++ b/src/include/sof/audio/cadence/aac_dec/xa_aac_dec_api.h @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2006-2020 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. + */ + + +#ifndef __XA_AAC_DEC_API_H__ +#define __XA_AAC_DEC_API_H__ + +/* aac_dec-specific configuration parameters */ +enum xa_config_param_aac_dec { + XA_AACDEC_CONFIG_PARAM_BDOWNSAMPLE = 0, /* Applicable only for aac*plus* libraries */ + XA_AACDEC_CONFIG_PARAM_BBITSTREAMDOWNMIX = 1, /* Applicable only for aac*plus* libraries */ + XA_AACDEC_CONFIG_PARAM_EXTERNAL_SAMPLERATE = 2, +#define XA_AACDEC_CONFIG_PARAM_EXTERNALSAMPLINGRATE XA_AACDEC_CONFIG_PARAM_EXTERNAL_SAMPLERATE // Renamed, maintained for backward comapatible + XA_AACDEC_CONFIG_PARAM_EXTERNALBSFORMAT = 3, + XA_AACDEC_CONFIG_PARAM_TO_STEREO = 4, + XA_AACDEC_CONFIG_PARAM_OUT_SAMPLERATE = 5, +#define XA_AACDEC_CONFIG_PARAM_SAMP_FREQ XA_AACDEC_CONFIG_PARAM_OUT_SAMPLERATE // Renamed, maintained for backward comapatible + XA_AACDEC_CONFIG_PARAM_NUM_CHANNELS = 6, + XA_AACDEC_CONFIG_PARAM_PCM_WDSZ = 7, + XA_AACDEC_CONFIG_PARAM_SBR_TYPE = 8, + XA_AACDEC_CONFIG_PARAM_AAC_SAMPLERATE = 9, + XA_AACDEC_CONFIG_PARAM_DATA_RATE = 10, + XA_AACDEC_CONFIG_PARAM_OUTNCHANS = 11, + XA_AACDEC_CONFIG_PARAM_CHANROUTING = 12, + XA_AACDEC_CONFIG_PARAM_SBR_SIGNALING = 13, /* Applicable only for aac*plus* libraries */ + XA_AACDEC_CONFIG_PARAM_CHANMAP = 14, + XA_AACDEC_CONFIG_PARAM_ACMOD = 15, + XA_AACDEC_CONFIG_PARAM_AAC_FORMAT = 16, + XA_AACDEC_CONFIG_PARAM_ZERO_UNUSED_CHANS = 17, + XA_AACDEC_CONFIG_PARAM_DECODELAYERS = 18, /* Depricated, no more implemented */ + XA_AACDEC_CONFIG_PARAM_EXTERNALCHCONFIG = 19, /* Depricated, no more implemented */ + XA_AACDEC_CONFIG_PARAM_RAW_AU_SIDEINFO = 20, /* For DAB-plus only */ + XA_AACDEC_CONFIG_PARAM_EXTERNALBITRATE = 21, /* For DAB-plus only */ + XA_AACDEC_CONFIG_PARAM_PAD_SIZE = 22, /* For DAB-plus only */ + XA_AACDEC_CONFIG_PARAM_PAD_PTR = 23, /* For DAB-plus only */ + XA_AACDEC_CONFIG_PARAM_MPEGSURR_PRESENT = 24, /* For DAB-plus only */ + XA_AACDEC_CONFIG_PARAM_METADATASTRUCT_PTR = 25, /* Only if Audio MetaData support is present for the library */ + XA_AACDEC_CONFIG_PARAM_ASCONFIGSTRUCT_PTR = 26, /* Only if Audio MetaData support is present for the library */ + XA_AACDEC_CONFIG_PARAM_LIMITBANDWIDTH = 27, /* Depricated, no more implemented */ + XA_AACDEC_CONFIG_PARAM_PCE_STATUS = 28, /* for Loas build only */ + XA_AACDEC_CONFIG_PARAM_DWNMIX_METADATA = 29, /* for Loas build only */ + XA_AACDEC_CONFIG_PARAM_MPEG_ID = 30, /* Applicable only for adts streams */ + XA_AACDEC_CONFIG_PARAM_DWNMIX_LEVEL_DVB = 31 /* for Loas build only */ + /* DRC and PRL information as per ISO/IEC 14496.3 */ + /* PRL Parametbers */ + ,XA_AACDEC_CONFIG_PARAM_ENABLE_APPLY_PRL = 32 /* for Loas build only */ + ,XA_AACDEC_CONFIG_PARAM_TARGET_LEVEL = 33 /* for Loas build only */ + ,XA_AACDEC_CONFIG_PARAM_PROG_REF_LEVEL = 34 /* for Loas build only */ + /* DRC Parametbers */ + ,XA_AACDEC_CONFIG_PARAM_ENABLE_APPLY_DRC = 35 /* for Loas build only */ + ,XA_AACDEC_CONFIG_PARAM_DRC_COMPRESS_FAC = 36 /* for Loas build only */ + ,XA_AACDEC_CONFIG_PARAM_DRC_BOOST_FAC = 37 /* for Loas build only */ + ,XA_AACDEC_CONFIG_PARAM_DRC_EXT_PRESENT = 38 + ,XA_AACDEC_CONFIG_PARAM_ORIGINAL_OR_COPY = 39 /* for ADTS and ADIF files only */ + ,XA_AACDEC_CONFIG_PARAM_COPYRIGHT_ID_PTR = 40 /* for ADTS and ADIF files only */ + ,XA_AACDEC_CONFIG_PARAM_PARSED_DRC_INFO = 41 /* applicable only for aacmch* builds */ + ,XA_AACDEC_CONFIG_PARAM_INPUT_BITOFFSET = 42 + ,XA_AACDEC_CONFIG_PARAM_ENABLE_FRAME_BY_FRAME_DECODE = 43 + ,XA_AACDEC_CONFIG_PARAM_CONCEALMENT_FADE_OUT_FRAMES = 44 + ,XA_AACDEC_CONFIG_PARAM_CONCEALMENT_MUTE_RELEASE_FRAMES = 45 + ,XA_AACDEC_CONFIG_PARAM_CONCEALMENT_FADE_IN_FRAMES = 46 + ,XA_AACDEC_CONFIG_PARAM_MPEG4_AMENDMENT4_ENABLE = 47 + ,XA_AACDEC_CONFIG_PARAM_CHANNEL_CONFIG_INFO_FROM_PCE = 48 + ,XA_AACDEC_CONFIG_PARAM_RESET_STATE_ON_SYNC_LOSS_ERROR = 49 +}; + +/* Types of channel modes (acmod) */ +/* +====================================================================================== +Acro. Expansion MPEG2/4 CH. Mapping MPEG4 AMD.4 CH. Mapping +======================================================================================= +CF Center Front CF -> C CF -> C +LF Left Front LF or LCF -> L LF -> L +RF Right Front RF or RCF -> R RF -> R +LCF Left Center Front LS or LOF -> l LS -> l +RCF Right Center Front RS or ROF -> r RS -> r +rs Rear Surround rs -> Cs rc -> Cs +LSR Left Surround Rear LSR -> Sbl rsl -> Sbl +RSR Right Surround Rear RSR -> Rsr rsr -> Rsr +LOF Left Outside Front LFE -> LFE LFE -> LFE +ROF Right Outside Front LFC -> Sbl +LFE Low Frequency Effects RFC -> Sbr +rc Rear Center LFVH -> Sbl +rsl Rear Surround Left RFVH -> Sbr +rsr Rear Surround Right +LFVH Left Front Vertical Height +RFVH Right Front Vertical Height +LFC Left Front Center +RFC Right Front Center +======================================================================================= +*/ + +typedef enum { + //Input Channel Map Enum Tensilica Convention (used for routing) MPEG2/4 MPEG4 AMD. 4 + XA_AACDEC_CHANNELMODE_UNDEFINED = 0, // undefined + XA_AACDEC_CHANNELMODE_MONO = 1, // mono (1/0 ) CF (1) == SAME == + XA_AACDEC_CHANNELMODE_PARAMETRIC_STEREO = 2, // parametric stereo (aacPlus v2 only) LF, RF (2) == SAME == + XA_AACDEC_CHANNELMODE_DUAL_CHANNEL = 3, // dual mono (1/0 + 1/0) + XA_AACDEC_CHANNELMODE_STEREO = 4, // stereo (2/0) LF, RF (2) == SAME == + XA_AACDEC_CHANNELMODE_3_CHANNEL_FRONT = 5, // C, L, R (3/0) CF, LF, RF (3) == SAME == + XA_AACDEC_CHANNELMODE_3_CHANNEL_SURR = 6, // L, R, l (2/1) + XA_AACDEC_CHANNELMODE_4_CHANNEL_2SURR = 7, // L, R, l, r (2/2) + XA_AACDEC_CHANNELMODE_4_CHANNEL_1SURR = 8, // C, L R, Cs (3/0/1) CF, LF, RF, rs (4) CF, LF, RF, rc (4) + XA_AACDEC_CHANNELMODE_5_CHANNEL = 9, // C, L, R, l, r (3/2) CF, LF, RF, LSR, RSR (5) CF, LF, RF, LS, RS (5) + XA_AACDEC_CHANNELMODE_6_CHANNEL = 10, // C, L, R, l, r, Cs (3/2/1) + XA_AACDEC_CHANNELMODE_7_CHANNEL = 11, // C, L, R, l, r, Sbl, Sbr (3/2/2) + XA_AACDEC_CHANNELMODE_7_CHANNEL_FRONT = 11, // C, Sbl, Sbr, L, R, l, r (3/2/2) + XA_AACDEC_CHANNELMODE_7_CHANNEL_BACK = 20, // C, L, R, l, r, Sbl, Sbr (3/2/2) + XA_AACDEC_CHANNELMODE_7_CHANNEL_TOP = 21, // C, L, R, l, r, Sbl, Sbr (3/2/2) + XA_AACDEC_CHANNELMODE_2_1_STEREO = 12, // L, R, LFE (2/0.1) + XA_AACDEC_CHANNELMODE_3_1_CHANNEL_FRONT = 13, // C, L, R, LFE (3/0.1) + XA_AACDEC_CHANNELMODE_3_1_CHANNEL_SURR = 14, // L, R, Cs, LFE (2/0/1.1) + XA_AACDEC_CHANNELMODE_4_1_CHANNEL_2SURR = 15, // L, R, Ls, Rs, LFE (2/2.1) + XA_AACDEC_CHANNELMODE_4_1_CHANNEL_1SURR = 16, // C, L, R, Cs, LFE (3/0/1.1) + XA_AACDEC_CHANNELMODE_5_1_CHANNEL = 17, // C, L, R, l, r, LFE (5.1 mode) CF, LF, RF, LSR, RSR, LFE (6) CF, LF, RF, LS, RS, LFE (6) + XA_AACDEC_CHANNELMODE_6_1_CHANNEL = 18, // C, L, R, l, r, Cs, LFE (3/2/1.1) NA CF, LF, RF, LS, RS, rc, LFE (11) + XA_AACDEC_CHANNELMODE_7_1_CHANNEL = 19, // C, L, R, l, r, Sbl, Sbr, LFE (7.1 mode) CF, LCF, RCF, LOF, ROF, LSR, RSR, LFE (7) NA + XA_AACDEC_CHANNELMODE_7_1_CHANNEL_FRONT = 19, // C, Sbl, Sbr, L, R, l, r, LFE (7.1 mode) NA CF, LFC, RFC, LF, RF, LS, RS, LFE (7) + XA_AACDEC_CHANNELMODE_7_1_CHANNEL_BACK = 22, // C, L, R, l, r, Sbl, Sbr, LFE (7.1 mode) NA CF, LF, RF, LS, RS, rsl, rsr, LFE (12) + XA_AACDEC_CHANNELMODE_7_1_CHANNEL_TOP = 23, // C, L, R, l, r, LFE, Sbl, Sbr (7.1 mode) NA CF, LF, RF, LS, RS, LFE, LFVH, RFVH(14) + +} XA_AACDEC_CHANNELMODE; + +/* Types of bitstreams */ +typedef enum { + /* The bitstream type has not (yet) been successfully determined. */ + XA_AACDEC_EBITSTREAM_TYPE_UNKNOWN = 0, + /* ADIF is an unsynced, unframed format. Errors in the bitstream cannot always + be detected, and when they occur, no further parsing is possible. Avoid ADIF at + all costs. */ + XA_AACDEC_EBITSTREAM_TYPE_AAC_ADIF = 1, + /* ADTS is a simple synced framing format similar to MPEG layer-3. */ + XA_AACDEC_EBITSTREAM_TYPE_AAC_ADTS = 2, + /* LATM, with in-band config. This format cannot be detected by the library; + it needs to be signaled explicitely. */ + XA_AACDEC_EBITSTREAM_TYPE_AAC_LATM = 3, + /* LATM, with out of band config. This format is not supported. */ + XA_AACDEC_EBITSTREAM_TYPE_AAC_LATM_OUTOFBAND_CONFIG = 4, + /* Low overhead audio stream. */ + XA_AACDEC_EBITSTREAM_TYPE_AAC_LOAS = 5, + + /* Raw bitstream. This format cannot be detected by the library; + it needs to be signaled explicitly. */ + XA_AACDEC_EBITSTREAM_TYPE_AAC_RAW = 6, + + /* Raw DAB+ bitstream. It needs sideInfo for every frame for error recovery */ + XA_AACDEC_EBITSTREAM_TYPE_DABPLUS_RAW_SIDEINFO = 8, + + /* DAB+ audio superframe bitstream */ + XA_AACDEC_EBITSTREAM_TYPE_DABPLUS = 9 + +} XA_AACDEC_EBITSTREAM_TYPE; + +/* commands */ +#include "xa_apicmd_standards.h" + +/* error codes */ +#include "xa_error_standards.h" + +#define XA_CODEC_AAC_DEC 3 + +/* aac_dec-specific error codes */ +/*****************************************************************************/ +/* Class 0: API Errors */ +/*****************************************************************************/ +/* Non Fatal Errors */ +enum xa_error_nonfatal_api_aac_dec { + XA_AACDEC_API_NONFATAL_CMD_TYPE_NOT_SUPPORTED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_api, XA_CODEC_AAC_DEC, 0), + XA_AACDEC_API_NONFATAL_INVALID_API_SEQ = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_api, XA_CODEC_AAC_DEC, 1) +}; + +enum xa_error_fatal_api_aac_dec { + XA_AACDEC_API_FATAL_INVALID_API_SEQ = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_AAC_DEC, 4) +}; + +/* Fatal Errors */ +/* (none) */ + +/*****************************************************************************/ +/* Class 1: Configuration Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_config_aac_dec { + XA_AACDEC_CONFIG_NONFATAL_PARAMS_NOT_SET = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 0), + XA_AACDEC_CONFIG_NONFATAL_DATA_RATE_NOT_SET = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 1), + XA_AACDEC_CONFIG_NONFATAL_PARTIAL_CHANROUTING = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 2) + ,XA_AACDEC_CONFIG_NONFATAL_INVALID_GEN_STRM_POS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 3) + ,XA_AACDEC_CONFIG_NONFATAL_CPID_NOT_PRESENT = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 4) + ,XA_AACDEC_CONFIG_NONFATAL_INVALID_PRL_PARAMS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 5) + ,XA_AACDEC_CONFIG_NONFATAL_INVALID_DRC_PARAMS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 6) + ,XA_AACDEC_CONFIG_NONFATAL_INVALID_PARAM_VALUE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_AAC_DEC, 7) +}; +/* Fatal Errors */ +enum xa_error_fatal_config_aac_dec { + XA_AACDEC_CONFIG_FATAL_INVALID_BDOWNSAMPLE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 0), + XA_AACDEC_CONFIG_FATAL_INVALID_BBITSTREAMDOWNMIX = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 1), + XA_AACDEC_CONFIG_FATAL_INVALID_EXTERNALSAMPLINGRATE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 2), + XA_AACDEC_CONFIG_FATAL_INVALID_EXTERNALBSFORMAT = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 3), + XA_AACDEC_CONFIG_FATAL_INVALID_TO_STEREO = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 4), + XA_AACDEC_CONFIG_FATAL_INVALID_OUTNCHANS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 5), + XA_AACDEC_CONFIG_FATAL_INVALID_SBR_SIGNALING = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 6), + XA_AACDEC_CONFIG_FATAL_INVALID_CHANROUTING = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 7), + XA_AACDEC_CONFIG_FATAL_INVALID_PCM_WDSZ = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 8), + XA_AACDEC_CONFIG_FATAL_INVALID_ZERO_UNUSED_CHANS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 9), + /* Code For Invalid Number of input channels */ + XA_AACDEC_CONFIG_FATAL_INVALID_EXTERNALCHCONFIG = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 10), // Depricated, no more implemented + XA_AACDEC_CONFIG_FATAL_INVALID_DECODELAYERS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 11), // Depricated, no more implemented + XA_AACDEC_CONFIG_FATAL_INVALID_EXTERNALBITRATE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 12), + XA_AACDEC_CONFIG_FATAL_INVALID_CONCEALMENT_PARAM = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_AAC_DEC, 13) +}; +/*****************************************************************************/ +/* Class 2: Execution Class Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_execute_aac_dec { + XA_AACDEC_EXECUTE_NONFATAL_INSUFFICIENT_FRAME_DATA = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 0) + ,XA_AACDEC_EXECUTE_NONFATAL_RUNTIME_INIT_RAMP_DOWN = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 1) + ,XA_AACDEC_EXECUTE_NONFATAL_RAW_FRAME_PARSE_ERROR = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 2) + ,XA_AACDEC_EXECUTE_NONFATAL_ADTS_HEADER_ERROR = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 3) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_NONFATAL_ADTS_HEADER_NOT_FOUND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 4) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_NONFATAL_DABPLUS_HEADER_NOT_FOUND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 5) + ,XA_AACDEC_EXECUTE_NONFATAL_LOAS_HEADER_ERROR = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 6) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_NONFATAL_STREAM_CHANGE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 7) + ,XA_AACDEC_EXECUTE_NONFATAL_HEADER_NOT_FOUND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 8) + ,XA_AACDEC_EXECUTE_NONFATAL_UNSUPPORTED_FEATURE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 9) + ,XA_AACDEC_EXECUTE_NONFATAL_HEADER_ERROR = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 10) + ,XA_AACDEC_EXECUTE_NONFATAL_PARTIAL_LAST_FRAME = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 11) + ,XA_AACDEC_EXECUTE_NONFATAL_EMPTY_INPUT_BUFFER = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 12) + ,XA_AACDEC_EXECUTE_NONFATAL_ROUTING_ABSENT_CH_IGNORED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 13) + ,XA_AACDEC_EXECUTE_NONFATAL_NEXT_SYNC_NOT_FOUND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_AAC_DEC, 14) +}; +/* Fatal Errors */ +enum xa_error_fatal_execute_aac_dec { + XA_AACDEC_EXECUTE_FATAL_PARSING_ERROR = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 0) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_FATAL_RAW_FRAME_PARSE_ERROR = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 1) + ,XA_AACDEC_EXECUTE_FATAL_BAD_INPUT_FAILURE = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 2) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_FATAL_UNSUPPORTED_FEATURE = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 3) + ,XA_AACDEC_EXECUTE_FATAL_ERROR_IN_CHANROUTING = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 4) + ,XA_AACDEC_EXECUTE_FATAL_EMPTY_INPUT_BUFFER = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 5) + ,XA_AACDEC_EXECUTE_FATAL_LOAS_HEADER_CHANGE = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 6) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_FATAL_INIT_ERROR = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 7) // Depreciated error, decoder don't return this error anymore + ,XA_AACDEC_EXECUTE_FATAL_UNKNOWN_STREAM_FORMAT = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 8) + ,XA_AACDEC_EXECUTE_FATAL_ADIF_HEADER_NOT_FOUND = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_AAC_DEC, 9) + +}; + +#include "xa_type_def.h" + +/* Relevant for loas build only */ +/* PCE status in the bit-stream */ +typedef enum { + XA_AACDEC_PCE_NOT_FOUND_YET = 0, /* No PCE found in the stream yet. */ + XA_AACDEC_PCE_NEW = 1, /* New PCE found in the current frame. */ + XA_AACDEC_PCE_USE_PREV = 2 /* No PCE in current frame, using previous PCE. */ +} xa_aac_dec_pce_status; + +/* MetaData Structure */ +typedef struct +{ + UWORD8 bMatrixMixdownIdxPresent; /* Flag indicating if ucMatrixMixdownIndex & bPseudoSurroundEnable were present in PCE */ + UWORD8 ucMatrixMixdownIndex; /* 2-bit value selecting the coefficient set for matrix downmix. + Note, ucMatrixMixdownIndex is valid only if bMatrixMixdownIdxPresent = 1 */ + UWORD8 bPseudoSurroundEnable; /* Flag indicating the possibility of mixdown for pseudo surround reproduction. + Note, bPseudoSurroundEnable is valid only if bMatrixMixdownIdxPresent = 1 */ +} xa_aac_dec_dwnmix_metadata_t; + +/* Structure for downmix levels present in acnillary data (DSE) */ +/* +Where +new_dvb_downmix_data: + Flag for indicating the presence of new downmixing data + in the current frame. + 0 - no "new" dvb downmixing data + 1 - dvb downmixing data available + +mpeg_audio_type: + 2-bits value indicating mpeg audio type. + 0 - Reserved + 1,2 - MPEG1 and MPEG2 Audio data. + 3 - MPEG4 Audio data. +(Refer Section C.4.2.3 and C.5.2.2.1 of ETSI TS 101 154 V1.9.1 document ) + +dolby_surround_mode: + 2-bits value indicating dolby surround mode. + 0,3 - Reserved + 1 - 2-ch audio is not dolby surround encoded. + 2 - 2-ch audio is dolby surround encoded. +(Refer Section C.4.2.4 and C.5.2.2.2 of ETSI TS 101 154 V1.9.1 document ) + +center_mix_level_on: + Flag for the presence of center_mix_level_value. + 0 or 1 are valid values(Refer to ETSI TS 101 154 V1.9.1) +center_mix_level_value; + 3-bit value for the downmix factor for mixing the center channel + into the stereo output. Values refer to ETSI TS 101 154 V1.9.1 +surround_mix_level_on: + Flag for the presence of surround_mix_level_value + 0 or 1 are valid values(Refer to ETSI TS 101 154 V1.9.1) +surround_mix_level_value: + 3-bit value for the downmix factor for mixing the left and + right surrond into the stereo output. + Values refer to ETSI TS 101 154 V1.9.1 +(Refer Section C.4.2.10 and C.5.2.4 of ETSI TS 101 154 V1.9.1 document for the above) + +coarse_grain_timecode_on; +fine_grain_timecode_on; + 2 bit flags indicating whether the coarse or fine time codes are present or not. +coarse_grain_timecode_value; +fine_grain_timecode_value; + 14 bit values containing the coarse or fine grain_timecode values. +(Refer Section C.4.2.13 / C.4.2.14 and C.5.2.4 of ETSI TS 101 154 V1.9.1 document ) + +(Details about timecodes: +Resetting of corse_grain_timecode_value based on (coarse_grain_timecode_on == '10') shall NOT +be done by the library. Same shall be true true of fine_grain_time_code_value. + +For MPEG4, if the status bit coarse_grain_timecode_status is 0, then both +coarse_grain_timecode_on; +coarse_grain_timecode_value; +shall be set to 0. +Same shall hold true for fine_grain_timecode values.) + +*/ + +typedef struct { + UWORD8 new_dvb_downmix_data; + UWORD8 mpeg_audio_type; + UWORD8 dolby_surround_mode; + UWORD8 center_mix_level_on; + UWORD8 center_mix_level_value; + UWORD8 surround_mix_level_on; + UWORD8 surround_mix_level_value; + UWORD8 coarse_grain_timecode_on; + UWORD coarse_grain_timecode_value; + UWORD8 fine_grain_timecode_on; + UWORD fine_grain_timecode_value; +} xa_aac_dec_dwnmix_level_dvb_info_t; + +#define MAX_NUM_CHANNELS 8 +#define MAX_NUM_DRC_BANDS 16 +/* + drc_info_valid: Flag to indicate if the rest of the nine elements in + structure are valid (1) or not (0) for current frame. + The definition and values of the rest of the nine elements are + the same as defined in Table 4.52 of ISO/IEC 14496-3. +*/ +typedef struct { + unsigned char drc_info_valid; + unsigned char exclude_masks[MAX_NUM_CHANNELS]; + unsigned char drc_bands_present; + unsigned char drc_interpolation_scheme; + unsigned char drc_num_bands; + unsigned char drc_band_incr; + unsigned char drc_band_top[MAX_NUM_DRC_BANDS]; + unsigned char prog_ref_level_present; + unsigned char prog_ref_level; + char dyn_rng_dbx4[MAX_NUM_DRC_BANDS]; +} xa_aac_dec_parsed_drc_info_t; + +typedef struct _xa_aac_dec_parsed_pce_info_t +{ + /* Number of elements */ + UWORD8 num_front_channel_elements; + UWORD8 num_side_channel_elements; + UWORD8 num_back_channel_elements; + UWORD8 num_lfe_channel_elements; + + /* channels per element */ + UWORD8 num_front_channels_per_element[16]; + UWORD8 num_side_channels_per_element[16]; + UWORD8 num_back_channels_per_element[16]; + UWORD8 num_lfe_channels_per_element[16]; + + /* channel height info */ + UWORD8 front_element_height_info[16]; + UWORD8 side_element_height_info[16]; + UWORD8 back_element_height_info[16]; +}xa_aac_dec_parsed_pce_info_t; + +#if defined(USE_DLL) && defined(_WIN32) +#define DLL_SHARED __declspec(dllimport) +#elif defined (_WINDLL) +#define DLL_SHARED __declspec(dllexport) +#else +#define DLL_SHARED +#endif + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ +DLL_SHARED xa_codec_func_t xa_aac_dec; +DLL_SHARED xa_codec_func_t xa_dabplus_dec; +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#endif /* __XA_AAC_DEC_API_H__ */ diff --git a/src/include/sof/audio/cadence/mp3_dec/xa_mp3_dec_api.h b/src/include/sof/audio/cadence/mp3_dec/xa_mp3_dec_api.h new file mode 100644 index 000000000000..70563f320cbd --- /dev/null +++ b/src/include/sof/audio/cadence/mp3_dec/xa_mp3_dec_api.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2006-2020 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. + */ + + +#ifndef __XA_MP3_DEC_API_H__ +#define __XA_MP3_DEC_API_H__ + +/*****************************************************************************/ +/* MP3 Decoder specific API definitions */ +/*****************************************************************************/ + +/* mp3_dec-specific configuration parameters */ +enum xa_config_param_mp3_dec { + XA_MP3DEC_CONFIG_PARAM_PCM_WDSZ = 0, + XA_MP3DEC_CONFIG_PARAM_SAMP_FREQ = 1, + XA_MP3DEC_CONFIG_PARAM_NUM_CHANNELS = 2, + XA_MP3DEC_CONFIG_PARAM_BITRATE = 3, + XA_MP3DEC_CONFIG_PARAM_CRC_CHECK = 4, + XA_MP3DEC_CONFIG_PARAM_MCH_ENABLE = 5, + XA_MP3DEC_CONFIG_PARAM_MCH_STATUS = 6, + XA_MP3DEC_CONFIG_PARAM_LFE_PRESENT = 7, + XA_MP3DEC_CONFIG_PARAM_EXTN_PRESENT = 8, + XA_MP3DEC_CONFIG_PARAM_CHAN_CONFIG = 9, + XA_MP3DEC_CONFIG_PARAM_CHAN_MAP = 10, + XA_MP3DEC_CONFIG_PARAM_NUM_XCHANS = 11, + XA_MP3DEC_CONFIG_PARAM_CHMODE_INFO = 12 +#ifdef ENABLE_SCF_CRC + ,XA_MP3DEC_CONFIG_PARAM_DAB_MP2 = 13 + +#endif + + ,XA_MP3DEC_CONFIG_PARAM_ACTIVATE_VLC_REWIND = 14 + ,XA_MP3DEC_CONFIG_PARAM_ORIGINAL_OR_COPY = 15 + ,XA_MP3DEC_CONFIG_PARAM_COPYRIGHT_FLAG = 16 + ,XA_MP3DEC_CONFIG_PARAM_MCH_EXT_HDR_INFO = 17 + ,XA_MP3DEC_CONFIG_PARAM_MCH_COPYRIGHT_ID_PTR = 18 + ,XA_MP3DEC_CONFIG_PARAM_NONSTD_STRM_SUPPORT = 19 +}; + +enum xa_mp3_dec_nonstd_strm_support { + XA_MP3DEC_RELAX_BITRATE_MODE_COMBO_CHECK = 1, + XA_MP3DEC_NUM_RELAX_CHECKS = 1 +}; + +enum xa_mp3_dec_mch_status { + XA_MP3DEC_MCH_STATUS_UNSUPPORTED = 0, + XA_MP3DEC_MCH_STATUS_DISABLED = 1, + XA_MP3DEC_MCH_STATUS_NOT_PRESENT = 2, + XA_MP3DEC_MCH_STATUS_PRESENT = 3 +}; + +/* commands */ +#include "xa_apicmd_standards.h" + +/* mp3_dec-specific commands */ +/* (none) */ + +/* mp3_dec-specific command types */ +/* (none) */ + +/* error codes */ +#include "xa_error_standards.h" + +#define XA_CODEC_MP3_DEC 1 + +/* mp3_dec-specific error codes */ +/*****************************************************************************/ +/* Class 1: Configuration Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_config_mp3_dec { + XA_MP3DEC_CONFIG_NONFATAL_MP3_PCM_ADJUST_16 = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MP3_DEC, 0), + XA_MP3DEC_CONFIG_NONFATAL_MP3_PCM_ADJUST_24 = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MP3_DEC, 1), + XA_MP3DEC_CONFIG_NONFATAL_INVALID_GEN_STRM_POS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MP3_DEC, 2), + XA_MP3DEC_CONFIG_NONFATAL_MCH_NOT_SUPPORTED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MP3_DEC, 3), + XA_MP3DEC_CONFIG_NONFATAL_INVALID_PARAM_VALUE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MP3_DEC, 4) +}; + +/* Fatal Errors */ +enum xa_error_fatal_config_mp3_dec { + XA_MP3DEC_CONFIG_FATAL_SAMP_FREQ = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MP3_DEC, 0), + XA_MP3DEC_CONFIG_FATAL_NUM_CHANNELS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MP3_DEC, 1) +}; + +/*****************************************************************************/ +/* Class 2: Execution Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_execute_mp3_dec { + XA_MP3DEC_EXECUTE_NONFATAL_NEED_MORE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 0), + XA_MP3DEC_EXECUTE_NONFATAL_CANNOT_REWIND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 1), + XA_MP3DEC_EXECUTE_NONFATAL_CHANGED_CHANNELS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 2), + XA_MP3DEC_EXECUTE_NONFATAL_CHANGED_LAYER = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 3), + XA_MP3DEC_EXECUTE_NONFATAL_CHANGED_SAMP_FREQ = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 4), + XA_MP3DEC_EXECUTE_NONFATAL_NEXT_SYNC_NOT_FOUND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 5), + XA_MP3DEC_EXECUTE_NONFATAL_CRC_FAILED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 6), + XA_MP3DEC_EXECUTE_NONFATAL_NO_MAIN_AUDIO_INPUT = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 7), + XA_MP3DEC_EXECUTE_NONFATAL_MCH_CRC_ERROR = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 8), + XA_MP3DEC_EXECUTE_NONFATAL_MCH_EXT_NOTFOUND = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 9) + ,XA_MP3DEC_EXECUTE_NONFATAL_INVALID_BITRATE_MODE_COMB = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 10) +#ifdef ENABLE_SCF_CRC + ,XA_MP3DEC_EXECUTE_NONFATAL_SCF_CRC_FAILED1 = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 17), + XA_MP3DEC_EXECUTE_NONFATAL_SCF_CRC_FAILED2 = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 18), + XA_MP3DEC_EXECUTE_NONFATAL_SCF_CRC_FAILED3 = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 19), + XA_MP3DEC_EXECUTE_NONFATAL_SCF_CRC_FAILED4 = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_MP3_DEC, 20) +#endif +}; + +/* Fatal Errors */ +enum xa_error_fatal_execute_mp3_dec { + XA_MP3DEC_EXECUTE_FATAL_MPEG1_NOT_SUPPORTED = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_MP3_DEC, 0), /* apparently unused */ + XA_MP3DEC_EXECUTE_FATAL_UNSUPPORTED_LAYER = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_MP3_DEC, 1), + XA_MP3DEC_EXECUTE_FATAL_OVERLOADED_IN_BUF = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_MP3_DEC, 2), + XA_MP3DEC_EXECUTE_FATAL_STREAM_ERROR = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_MP3_DEC, 3) +}; + +#include "xa_type_def.h" + +/* metadata information api-interface structure */ +typedef struct _xa_mc_ext_hdr_info_t +{ + /* mc header decoded here*/ + WORD ext_bit_stream_present; + WORD n_ad_bytes; + WORD center; + WORD surround; + WORD lfe; + WORD audio_mix; + WORD dematrix_procedure; + WORD no_of_multi_lingual_ch; + WORD multi_lingual_fs; + WORD multi_lingual_layer; +} xa_mch_ext_hdr_info_t; + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ +xa_codec_func_t xa_mp3_dec; +#if defined(__cplusplus) +} +#endif /* __cplusplus */ +#endif /* __XA_MP3_DEC_API_H__ */ diff --git a/src/include/sof/audio/cadence/mp3_enc/xa_mp3_enc_api.h b/src/include/sof/audio/cadence/mp3_enc/xa_mp3_enc_api.h new file mode 100644 index 000000000000..aac961e63cf9 --- /dev/null +++ b/src/include/sof/audio/cadence/mp3_enc/xa_mp3_enc_api.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022-2025 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. + */ + + + +#ifndef __XA_MP3ENC_CONFIG_PARAMS_H__ +#define __XA_MP3ENC_CONFIG_PARAMS_H__ + +/* mp3_enc-specific configuration parameters */ +enum xa_config_param_mp3_enc { + XA_MP3ENC_CONFIG_PARAM_PCM_WDSZ = 0, + XA_MP3ENC_CONFIG_PARAM_SAMP_FREQ = 1, + XA_MP3ENC_CONFIG_PARAM_NUM_CHANNELS = 2, + XA_MP3ENC_CONFIG_PARAM_BITRATE = 3 +#ifdef ENABLE_CUT_OFF_FREQ_CONFIG + , XA_MP3ENC_CONFIG_FATAL_FRAC_BANDWIDTH = 4 +#endif // ENABLE_CUT_OFF_FREQ_CONFIG +}; + +/* commands */ +#include "xa_apicmd_standards.h" + +/* mp3_enc-specific commands */ +/* (none) */ + +/* mp3_enc-specific command types */ +/* (none) */ + +/* error codes */ +#include "xa_error_standards.h" + +#define XA_CODEC_MP3_ENC 2 + +/* mp3_enc-specific error_codes */ +/*****************************************************************************/ +/* Class 0: API Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +/* (none) */ +/* Fatal Errors */ +/* (none) */ + +/*****************************************************************************/ +/* Class 1: Configuration Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_config_mp3_enc { + XA_MP3ENC_CONFIG_NONFATAL_INVALID_BITRATE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_MP3_ENC, 0) +}; + +/* Fatal Errors */ +enum xa_error_fatal_config_mp3_enc { + XA_MP3ENC_CONFIG_FATAL_SAMP_FREQ = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MP3_ENC, 0), + XA_MP3ENC_CONFIG_FATAL_NUM_CHANNELS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MP3_ENC, 1), + XA_MP3ENC_CONFIG_FATAL_PCM_WDSZ = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MP3_ENC, 2) +#ifdef ENABLE_CUT_OFF_FREQ_CONFIG + , XA_MP3ENC_CONFIG_PARAM_FRAC_BANDWIDTH = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_MP3_ENC, 3) +#endif // ENABLE_CUT_OFF_FREQ_CONFIG +}; +/* (none) */ + +#include "xa_type_def.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ +xa_codec_func_t xa_mp3_enc; +#if defined(__cplusplus) +} +#endif /* __cplusplus */ +#endif /* __XA_MP3ENC_CONFIG_PARAMS_H__ */ diff --git a/src/include/sof/audio/cadence/src_pp/xa_src_pp_api.h b/src/include/sof/audio/cadence/src_pp/xa_src_pp_api.h new file mode 100644 index 000000000000..18ef23e01c6d --- /dev/null +++ b/src/include/sof/audio/cadence/src_pp/xa_src_pp_api.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011-2021 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. + */ + + +#ifndef _XA_SRC_PP_API_H_ +#define _XA_SRC_PP_API_H_ + +#include "xa_type_def.h" + +/* Sample Rate Convrter configuration parameters */ +enum xa_config_param_src_pp +{ + XA_SRC_PP_CONFIG_PARAM_INPUT_SAMPLE_RATE = 0, + XA_SRC_PP_CONFIG_PARAM_OUTPUT_SAMPLE_RATE = 1, + XA_SRC_PP_CONFIG_PARAM_INPUT_CHUNK_SIZE = 2, + XA_SRC_PP_CONFIG_PARAM_OUTPUT_CHUNK_SIZE = 3, + XA_SRC_PP_CONFIG_PARAM_INPUT_CHANNELS = 4, + XA_SRC_PP_CONFIG_PARAM_SET_INPUT_BUF_PTR = 5, + XA_SRC_PP_CONFIG_PARAM_SET_OUTPUT_BUF_PTR = 6, + XA_SRC_PP_CONFIG_PARAM_GET_NUM_STAGES = 7, + XA_SRC_PP_CONFIG_PARAM_BYTES_PER_SAMPLE = 8, + XA_SRC_PP_CONFIG_PARAM_ENABLE_ASRC = 9, // Only available when the library is build with ASRC_ENABLE + XA_SRC_PP_CONFIG_PARAM_DRIFT_ASRC = 10, // Only available when the library is build with ASRC_ENABLE + XA_SRC_PP_CONFIG_PARAM_GET_DRIFT_FRACT_ASRC = 11, // Only available when the library is build with ASRC_ENABLE + XA_SRC_PP_CONFIG_PARAM_ENABLE_CUBIC = 12, // Only available when the library is build with POLYPHASE_CUBIC_INTERPOLATION + XA_SRC_PP_CONFIG_PARAM_CUSTOM_MODE = 20 /* Only available for HiFi2 based libraries built with compiler switch "XA_CUSTOM_SRC_IMPL" on */ +}; + +#define XA_SRC_PP 3 + +/* Define for the number of PCM Width */ +#define TWO_BYTES_PER_SAMPLE 2 +#define THREE_BYTES_PER_SAMPLE 3 + +/*****************************************************************************/ +/* Class 1: Configuration Errors */ +/*****************************************************************************/ +/* Non-Fatal Errors */ +enum xa_error_nonfatal_config_src_pp +{ + XA_SRC_PP_CONFIG_NON_FATAL_INVALID_CONFIG_TYPE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_SRC_PP, 0), + XA_SRC_PP_CONFIG_NON_FATAL_INVALID_ENABLE_ASRC = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_SRC_PP, 1), + XA_SRC_PP_CONFIG_NON_FATAL_INVALID_DRIFT_ASRC = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_SRC_PP, 2), + XA_SRC_PP_CONFIG_NON_FATAL_INVALID_ENABLE_CUBIC = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_SRC_PP, 3), +}; +/* Fatal Errors */ +enum xa_error_fatal_config_src_pp +{ + XA_SRC_PP_CONFIG_FATAL_INVALID_INPUT_RATE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 0), + XA_SRC_PP_CONFIG_FATAL_INVALID_OUTPUT_RATE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 1), + XA_SRC_PP_CONFIG_FATAL_INVALID_INPUT_CHUNK_SIZE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 2), + XA_SRC_PP_CONFIG_FATAL_INVALID_INPUT_CHANNELS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 3), + XA_SRC_PP_CONFIG_FATAL_INVALID_INPUT_PTR = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 4), + XA_SRC_PP_CONFIG_FATAL_INVALID_OUTPUT_PTR = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 5), + XA_SRC_PP_CONFIG_FATAL_INVALID_BYTES_PER_SAMPLE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_SRC_PP, 6), +}; + +/*****************************************************************************/ +/* Class 2: Execution Class Errors */ +/*****************************************************************************/ +/* Non Fatal Errors */ +enum xa_error_nonfatal_execute_src_pp +{ + XA_SRC_PP_EXECUTE_NON_FATAL_INVALID_CONFIG_SEQ = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_SRC_PP, 0), + XA_SRC_PP_EXECUTE_NON_FATAL_INVALID_API_SEQ = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_SRC_PP, 1), +}; + +/* Fatal Errors */ +enum xa_error_fatal_execute_src_pp +{ + XA_SRC_PP_EXECUTE_FATAL_ERR_POST_CONFIG_INIT = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_SRC_PP, 0), + XA_SRC_PP_EXECUTE_FATAL_ERR_INIT = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_SRC_PP, 1), + XA_SRC_PP_EXECUTE_FATAL_ERR_EXECUTE = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_SRC_PP, 2), +}; + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + /* Either one of the following is available in any library */ +xa_codec_func_t xa_src_pp; // Standard SRC / SRCPlus +xa_codec_func_t xa_src384k_pp; // Trimmed src384k +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#endif /*_XA_SRC_PP_API_H_*/ diff --git a/src/include/sof/audio/cadence/vorbis_dec/xa_vorbis_dec_api.h b/src/include/sof/audio/cadence/vorbis_dec/xa_vorbis_dec_api.h new file mode 100644 index 000000000000..f287e5caaf05 --- /dev/null +++ b/src/include/sof/audio/cadence/vorbis_dec/xa_vorbis_dec_api.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2006-2021 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. + */ + + +#ifndef __XA_VORBIS_DEC_API_H__ +#define __XA_VORBIS_DEC_API_H__ + +#include <xa_memory_standards.h> + +/* vorbis_dec-specific configuration parameters */ +enum xa_config_param_vorbis_dec +{ + XA_VORBISDEC_CONFIG_PARAM_SAMP_FREQ = 0, + XA_VORBISDEC_CONFIG_PARAM_NUM_CHANNELS = 1, + XA_VORBISDEC_CONFIG_PARAM_PCM_WDSZ = 2, + XA_VORBISDEC_CONFIG_PARAM_COMMENT_MEM_PTR = 3, + XA_VORBISDEC_CONFIG_PARAM_COMMENT_MEM_SIZE = 4, + XA_VORBISDEC_CONFIG_PARAM_GET_CUR_BITRATE = 5, + XA_VORBISDEC_CONFIG_PARAM_RAW_VORBIS_FILE_MODE = 6, + XA_VORBISDEC_CONFIG_PARAM_RAW_VORBIS_LAST_PKT_GRANULE_POS = 7, + XA_VORBISDEC_CONFIG_PARAM_OGG_MAX_PAGE_SIZE = 8, + XA_VORBISDEC_CONFIG_PARAM_RUNTIME_MEM = 9 +}; + +/* commands */ +#include <xa_apicmd_standards.h> + +/* vorbis_dec-specific command types */ +/* (none) */ + +/* error codes */ +#include <xa_error_standards.h> +#define XA_CODEC_VORBIS_DEC 7 + +/* vorbis_dec-specific error codes */ + +/*****************************************************************************/ +/* Class 1: Configuration Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_config_vorbis_dec +{ + XA_VORBISDEC_CONFIG_NONFATAL_GROUPED_STREAM = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_CONFIG_NONFATAL_BAD_PARAM = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_config, XA_CODEC_VORBIS_DEC, 1) +}; + +/* Fatal Errors */ +enum xa_error_fatal_config_vorbis_dec +{ + XA_VORBISDEC_CONFIG_FATAL_BADHDR = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_CONFIG_FATAL_NOTVORBIS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 1), + XA_VORBISDEC_CONFIG_FATAL_BADINFO = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 2), + XA_VORBISDEC_CONFIG_FATAL_BADVERSION = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 3), + XA_VORBISDEC_CONFIG_FATAL_BADBOOKS = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 4), + XA_VORBISDEC_CONFIG_FATAL_CODEBOOK_DECODE = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 5), + XA_VORBISDEC_CONFIG_FATAL_INVALID_PARAM = XA_ERROR_CODE(xa_severity_fatal, xa_class_config, XA_CODEC_VORBIS_DEC, 6) +}; + +/*****************************************************************************/ +/* Class 2: Execution Errors */ +/*****************************************************************************/ +/* Nonfatal Errors */ +enum xa_error_nonfatal_execute_vorbis_dec +{ + XA_VORBISDEC_EXECUTE_NONFATAL_OV_HOLE = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_NOTAUDIO = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 1), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_BADPACKET = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 2), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_RUNTIME_DECODE_FLUSH_IN_PROGRESS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 3), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_INVALID_STRM_POS = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 4), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_INSUFFICIENT_DATA = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 5), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_UNEXPECTED_IDENT_PKT_RECEIVED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 6), + XA_VORBISDEC_EXECUTE_NONFATAL_OV_UNEXPECTED_HEADER_PKT_RECEIVED = XA_ERROR_CODE(xa_severity_nonfatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 7) +}; +/* Fatal Errors */ +enum xa_error_fatal_execute_vorbis_dec +{ + XA_VORBISDEC_EXECUTE_FATAL_PERSIST_ALLOC = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 0), + XA_VORBISDEC_EXECUTE_FATAL_SCRATCH_ALLOC = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 1), + XA_VORBISDEC_EXECUTE_FATAL_CORRUPT_STREAM = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 2), + XA_VORBISDEC_EXECUTE_FATAL_INSUFFICIENT_INP_BUF_SIZE = XA_ERROR_CODE(xa_severity_fatal, xa_class_execute, XA_CODEC_VORBIS_DEC, 3) +}; + +#include "xa_type_def.h" + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + + xa_codec_func_t xa_vorbis_dec; + +#ifdef __cplusplus + } +#endif /* __cplusplus */ + +#endif /* __XA_VORBIS_DEC_API_H__ */ diff --git a/src/include/sof/audio/cadence/xa_apicmd_standards.h b/src/include/sof/audio/cadence/xa_apicmd_standards.h new file mode 100644 index 000000000000..8eb0d73f0386 --- /dev/null +++ b/src/include/sof/audio/cadence/xa_apicmd_standards.h @@ -0,0 +1,106 @@ +/* +* The components of this software package from Cadence Design Systems, +* Inc. are subject to the licenses below. By using the software package, +* you agree to the legal terms of each license. +* +* Copyright (c) 1999-2018 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. +*/ + + +#ifndef __XA_API_CMD_STANDARDS_H__ +#define __XA_API_CMD_STANDARDS_H__ + +/*****************************************************************************/ +/* Standard API commands */ +/*****************************************************************************/ + +enum xa_api_cmd_generic { + XA_API_CMD_GET_LIB_ID_STRINGS = 0x0001, + + XA_API_CMD_GET_API_SIZE = 0x0002, + XA_API_CMD_INIT = 0x0003, + + XA_API_CMD_SET_CONFIG_PARAM = 0x0004, + XA_API_CMD_GET_CONFIG_PARAM = 0x0005, + + XA_API_CMD_GET_MEMTABS_SIZE = 0x0006, + XA_API_CMD_SET_MEMTABS_PTR = 0x0007, + XA_API_CMD_GET_N_MEMTABS = 0x0008, + + XA_API_CMD_EXECUTE = 0x0009, + + XA_API_CMD_PUT_INPUT_QUERY = 0x000A, + XA_API_CMD_GET_CURIDX_INPUT_BUF = 0x000B, + XA_API_CMD_SET_INPUT_BYTES = 0x000C, + XA_API_CMD_GET_OUTPUT_BYTES = 0x000D, + XA_API_CMD_INPUT_OVER = 0x000E, + + XA_API_CMD_GET_MEM_INFO_SIZE = 0x0010, + XA_API_CMD_GET_MEM_INFO_ALIGNMENT = 0x0011, + XA_API_CMD_GET_MEM_INFO_TYPE = 0x0012, + XA_API_CMD_GET_MEM_INFO_PLACEMENT = 0x0013, + XA_API_CMD_GET_MEM_INFO_PRIORITY = 0x0014, + XA_API_CMD_SET_MEM_PTR = 0x0015, + XA_API_CMD_SET_MEM_INFO_SIZE = 0x0016, + XA_API_CMD_SET_MEM_PLACEMENT = 0x0017, + + XA_API_CMD_GET_N_TABLES = 0x0018, + XA_API_CMD_GET_TABLE_INFO_SIZE = 0x0019, + XA_API_CMD_GET_TABLE_INFO_ALIGNMENT = 0x001A, + XA_API_CMD_GET_TABLE_INFO_PRIORITY = 0x001B, + XA_API_CMD_SET_TABLE_PTR = 0x001C, + XA_API_CMD_GET_TABLE_PTR = 0x001D +}; + +/*****************************************************************************/ +/* Standard API command indices */ +/*****************************************************************************/ + +enum xa_cmd_type_generic { + /* XA_API_CMD_GET_LIB_ID_STRINGS indices */ + XA_CMD_TYPE_LIB_NAME = 0x0100, + XA_CMD_TYPE_LIB_VERSION = 0x0200, + XA_CMD_TYPE_API_VERSION = 0x0300, + + /* XA_API_CMD_INIT indices */ + XA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS = 0x0100, + XA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS = 0x0200, + XA_CMD_TYPE_INIT_PROCESS = 0x0300, + XA_CMD_TYPE_INIT_DONE_QUERY = 0x0400, + + /* XA_API_CMD_EXECUTE indices */ + XA_CMD_TYPE_DO_EXECUTE = 0x0100, + XA_CMD_TYPE_DONE_QUERY = 0x0200, + XA_CMD_TYPE_DO_RUNTIME_INIT = 0x0300 +}; + + +/*****************************************************************************/ +/* Standard API configuration parameters */ +/*****************************************************************************/ + +enum xa_config_param_generic { + XA_CONFIG_PARAM_CUR_INPUT_STREAM_POS = 0x0100, + XA_CONFIG_PARAM_GEN_INPUT_STREAM_POS = 0x0200, +}; + +#endif /* __XA_API_CMD_STANDARDS_H__ */ diff --git a/src/include/sof/audio/cadence/xa_error_standards.h b/src/include/sof/audio/cadence/xa_error_standards.h new file mode 100644 index 000000000000..2e5a2ca300a7 --- /dev/null +++ b/src/include/sof/audio/cadence/xa_error_standards.h @@ -0,0 +1,76 @@ +/* +* The components of this software package from Cadence Design Systems, +* Inc. are subject to the licenses below. By using the software package, +* you agree to the legal terms of each license. +* +* Copyright (c) 1999-2018 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. +*/ + +#ifndef __XA_ERROR_STANDARDS_H__ +#define __XA_ERROR_STANDARDS_H__ + +/*****************************************************************************/ +/* File includes */ +/* xa_type_def.h */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Constant hash defines */ +/*****************************************************************************/ +#define XA_NO_ERROR 0 +#define XA_FATAL_ERROR 0x80000000 + +enum xa_error_severity { + xa_severity_nonfatal = 0, + xa_severity_fatal = (int)0xffffffff +}; + +enum xa_error_class { + xa_class_api = 0, + xa_class_config = 1, + xa_class_execute = 2 +}; + +#define XA_CODEC_GENERIC 0 + +#define XA_ERROR_CODE(severity, class, codec, index) ((severity << 15) | (class << 11) | (codec << 6) | index) +#define XA_ERROR_SEVERITY(code) (((code) & XA_FATAL_ERROR) != 0) +#define XA_ERROR_CLASS(code) (((code) >> 11) & 0x0f) +#define XA_ERROR_CODEC(code) (((code) >> 6) & 0x1f) +#define XA_ERROR_SUBCODE(code) (((code) >> 0) & 0x3f) + +/* Our convention is that only api-class errors can be generic ones. */ + +/*****************************************************************************/ +/* Class 0: API Errors */ +/*****************************************************************************/ +/* Non Fatal Errors */ +/* (none) */ +/* Fatal Errors */ +enum xa_error_fatal_api_generic { + XA_API_FATAL_MEM_ALLOC = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 0), + XA_API_FATAL_MEM_ALIGN = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 1), + XA_API_FATAL_INVALID_CMD = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 2), + XA_API_FATAL_INVALID_CMD_TYPE = XA_ERROR_CODE(xa_severity_fatal, xa_class_api, XA_CODEC_GENERIC, 3) +}; + +#endif /* __XA_ERROR_STANDARDS_H__ */ diff --git a/src/include/sof/audio/cadence/xa_memory_standards.h b/src/include/sof/audio/cadence/xa_memory_standards.h new file mode 100644 index 000000000000..b6606bc61b7e --- /dev/null +++ b/src/include/sof/audio/cadence/xa_memory_standards.h @@ -0,0 +1,103 @@ +/* +* The components of this software package from Cadence Design Systems, +* Inc. are subject to the licenses below. By using the software package, +* you agree to the legal terms of each license. +* +* Copyright (c) 1999-2018 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. +*/ + + +#ifndef __XA_MEMORY_STANDARDS_H__ +#define __XA_MEMORY_STANDARDS_H__ + +/*****************************************************************************/ +/* Constant hash defines */ +/*****************************************************************************/ +/* when you don't need alignment, pass this to memory library */ +#define XA_MEM_NO_ALIGN 0x01 + +/* standard memory types */ +/* to be used inter frames */ +#define XA_MEMTYPE_PERSIST 0x00 +/* read write, to be used intra frames */ +#define XA_MEMTYPE_SCRATCH 0x01 +/* read only memory, intra frame */ +#define XA_MEMTYPE_INPUT 0x02 +/* read-write memory, for usable output, intra frame */ +#define XA_MEMTYPE_OUTPUT 0x03 +/* readonly memory, inter frame */ +#define XA_MEMTYPE_TABLE 0x04 +/* input buffer before mem tabs allocation */ +#define XA_MEMTYPE_PRE_FRAME_INPUT 0x05 +/* input buffer before mem tabs allocation */ +#define XA_MEMTYPE_PRE_FRAME_SCRATCH 0x06 +/* for local variables */ +#define XA_MEMTYPE_AUTO_VAR 0x80 + +/* standard memory priorities */ +#define XA_MEMPRIORITY_ANYWHERE 0x00 +#define XA_MEMPRIORITY_LOWEST 0x01 +#define XA_MEMPRIORITY_LOW 0x02 +#define XA_MEMPRIORITY_NORM 0x03 +#define XA_MEMPRIORITY_ABOVE_NORM 0x04 +#define XA_MEMPRIORITY_HIGH 0x05 +#define XA_MEMPRIORITY_HIGHER 0x06 +#define XA_MEMPRIORITY_CRITICAL 0x07 + +/* standard memory placements */ +/* placement is defined by 64 bits */ + +#define XA_MEMPLACE_FAST_RAM_0 0x000001 +#define XA_MEMPLACE_FAST_RAM_1 0x000002 +#define XA_MEMPLACE_FAST_RAM_2 0x000004 +#define XA_MEMPLACE_FAST_RAM_3 0x000008 +#define XA_MEMPLACE_FAST_RAM_4 0x000010 +#define XA_MEMPLACE_FAST_RAM_5 0x000020 +#define XA_MEMPLACE_FAST_RAM_6 0x000040 +#define XA_MEMPLACE_FAST_RAM_7 0x000080 + +#define XA_MEMPLACE_INT_RAM_0 0x000100 +#define XA_MEMPLACE_INT_RAM_1 0x000200 +#define XA_MEMPLACE_INT_RAM_2 0x000400 +#define XA_MEMPLACE_INT_RAM_3 0x000800 +#define XA_MEMPLACE_INT_RAM_4 0x001000 +#define XA_MEMPLACE_INT_RAM_5 0x002000 +#define XA_MEMPLACE_INT_RAM_6 0x004000 +#define XA_MEMPLACE_INT_RAM_7 0x008000 + +#define XA_MEMPLACE_EXT_RAM_0 0x010000 +#define XA_MEMPLACE_EXT_RAM_1 0x020000 +#define XA_MEMPLACE_EXT_RAM_2 0x040000 +#define XA_MEMPLACE_EXT_RAM_3 0x080000 +#define XA_MEMPLACE_EXT_RAM_4 0x100000 +#define XA_MEMPLACE_EXT_RAM_5 0x200000 +#define XA_MEMPLACE_EXT_RAM_6 0x400000 +#define XA_MEMPLACE_EXT_RAM_7 0x800000 + +#define XA_MEMPLACE_DONTCARE_H 0xFFFFFFFF +#define XA_MEMPLACE_DONTCARE_L 0xFFFFFFFF + +/* the simple common PC RAM */ +#define XA_PC_RAM_H 0x00000000 +#define XA_PC_RAM_L XA_MEMPLACE_EXT_RAM_0 + +#endif /* __XA_MEMORY_STANDARDS_H__ */ diff --git a/src/include/sof/audio/cadence/xa_type_def.h b/src/include/sof/audio/cadence/xa_type_def.h new file mode 100644 index 000000000000..43160610aa38 --- /dev/null +++ b/src/include/sof/audio/cadence/xa_type_def.h @@ -0,0 +1,99 @@ +/* +* The components of this software package from Cadence Design Systems, +* Inc. are subject to the licenses below. By using the software package, +* you agree to the legal terms of each license. +* +* Copyright (c) 1999-2018 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. +*/ + +#ifndef __XA_TYPE_DEF_H__ +#define __XA_TYPE_DEF_H__ + +/****************************************************************************/ +/* types type define prefix examples bytes */ +/************************ *********** ****** **************** ***** */ +typedef char WORD8 ;/* b WORD8 b_name 1 */ +typedef char * pWORD8 ;/* pb pWORD8 pb_nmae 1 */ +typedef unsigned char UWORD8 ;/* ub UWORD8 ub_count 1 */ +typedef unsigned char * pUWORD8 ;/* pub pUWORD8 pub_count 1 */ + +typedef signed short WORD16 ;/* s WORD16 s_count 2 */ +typedef signed short * pWORD16 ;/* ps pWORD16 ps_count 2 */ +typedef unsigned short UWORD16 ;/* us UWORD16 us_count 2 */ +typedef unsigned short * pUWORD16;/* pus pUWORD16 pus_count 2 */ + +#if !defined(WORD24_H) +#define WORD24_H +typedef signed long WORD24 ;/* k WORD24 k_count 3 */ +typedef signed long * pWORD24 ;/* pk pWORD24 pk_count 3 */ +typedef unsigned long UWORD24 ;/* uk UWORD24 uk_count 3 */ +typedef unsigned long * pUWORD24;/* puk pUWORD24 puk_count 3 */ +#endif /* WORD24_H */ + +typedef signed int WORD32 ;/* i WORD32 i_count 4 */ +typedef signed int * pWORD32 ;/* pi pWORD32 pi_count 4 */ +typedef unsigned int UWORD32 ;/* ui UWORD32 ui_count 4 */ +typedef unsigned int * pUWORD32;/* pui pUWORD32 pui_count 4 */ + +typedef signed long long WORD40 ;/* m WORD40 m_count 5 */ +typedef signed long long * pWORD40 ;/* pm pWORD40 pm_count 5 */ +typedef unsigned long long UWORD40 ;/* um UWORD40 um_count 5 */ +typedef unsigned long long * pUWORD40;/* pum pUWORD40 pum_count 5 */ + +typedef signed long long WORD64 ;/* h WORD64 h_count 8 */ +typedef signed long long * pWORD64 ;/* ph pWORD64 ph_count 8 */ +typedef unsigned long long UWORD64 ;/* uh UWORD64 uh_count 8 */ +typedef unsigned long long * pUWORD64;/* puh pUWORD64 puh_count 8 */ + +typedef float FLOAT32 ;/* f FLOAT32 f_count 4 */ +typedef float * pFLOAT32;/* pf pFLOAT32 pf_count 4 */ +typedef double FLOAT64 ;/* d UFLOAT64 d_count 8 */ +typedef double * pFlOAT64;/* pd pFLOAT64 pd_count 8 */ + +typedef void VOID ;/* v VOID v_flag 4 */ +typedef void * pVOID ;/* pv pVOID pv_flag 4 */ + +/* variable size types: platform optimized implementation */ +typedef signed int BOOL ;/* bool BOOL bool_true */ +typedef unsigned int UBOOL ;/* ubool BOOL ubool_true */ +typedef signed int FLAG ;/* flag FLAG flag_false */ +typedef unsigned int UFLAG ;/* uflag FLAG uflag_false */ +typedef signed int LOOPIDX ;/* lp LOOPIDX lp_index */ +typedef unsigned int ULOOPIDX;/* ulp SLOOPIDX ulp_index */ +typedef signed int WORD ;/* lp LOOPIDX lp_index */ +typedef unsigned int UWORD ;/* ulp SLOOPIDX ulp_index */ + +typedef LOOPIDX LOOPINDEX; /* lp LOOPIDX lp_index */ +typedef ULOOPIDX ULOOPINDEX;/* ulp SLOOPIDX ulp_index */ + +#define PLATFORM_INLINE __inline + +typedef struct xa_codec_opaque { WORD32 _; } *xa_codec_handle_t; + +typedef int XA_ERRORCODE; + +typedef XA_ERRORCODE xa_codec_func_t(xa_codec_handle_t p_xa_module_obj, + WORD32 i_cmd, + WORD32 i_idx, + pVOID pv_value); + +#endif /* __XA_TYPE_DEF_H__ */ diff --git a/src/include/sof/audio/coefficients/fft/twiddle_16.h b/src/include/sof/audio/coefficients/fft/twiddle_16.h new file mode 100644 index 000000000000..e67df9d929a7 --- /dev/null +++ b/src/include/sof/audio/coefficients/fft/twiddle_16.h @@ -0,0 +1,2072 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/* Twiddle factors in Q1.15 format */ + +#ifndef __INCLUDE_TWIDDLE_16_H__ +#define __INCLUDE_TWIDDLE_16_H__ + +#include <stdint.h> + +#define FFT_SIZE_MAX 1024 + +/* in Q1.15, generated from cos(i * 2 * pi / FFT_SIZE_MAX) */ +const int16_t twiddle_real_16[FFT_SIZE_MAX] = { + 32767, + 32767, + 32766, + 32762, + 32758, + 32753, + 32746, + 32738, + 32729, + 32718, + 32706, + 32693, + 32679, + 32664, + 32647, + 32629, + 32610, + 32590, + 32568, + 32546, + 32522, + 32496, + 32470, + 32442, + 32413, + 32383, + 32352, + 32319, + 32286, + 32251, + 32214, + 32177, + 32138, + 32099, + 32058, + 32015, + 31972, + 31927, + 31881, + 31834, + 31786, + 31737, + 31686, + 31634, + 31581, + 31527, + 31471, + 31415, + 31357, + 31298, + 31238, + 31177, + 31114, + 31050, + 30986, + 30920, + 30853, + 30784, + 30715, + 30644, + 30572, + 30499, + 30425, + 30350, + 30274, + 30196, + 30118, + 30038, + 29957, + 29875, + 29792, + 29707, + 29622, + 29535, + 29448, + 29359, + 29269, + 29178, + 29086, + 28993, + 28899, + 28803, + 28707, + 28610, + 28511, + 28411, + 28311, + 28209, + 28106, + 28002, + 27897, + 27791, + 27684, + 27576, + 27467, + 27357, + 27246, + 27133, + 27020, + 26906, + 26791, + 26674, + 26557, + 26439, + 26320, + 26199, + 26078, + 25956, + 25833, + 25708, + 25583, + 25457, + 25330, + 25202, + 25073, + 24943, + 24812, + 24680, + 24548, + 24414, + 24279, + 24144, + 24008, + 23870, + 23732, + 23593, + 23453, + 23312, + 23170, + 23028, + 22884, + 22740, + 22595, + 22449, + 22302, + 22154, + 22006, + 21856, + 21706, + 21555, + 21403, + 21251, + 21097, + 20943, + 20788, + 20632, + 20475, + 20318, + 20160, + 20001, + 19841, + 19681, + 19520, + 19358, + 19195, + 19032, + 18868, + 18703, + 18538, + 18372, + 18205, + 18037, + 17869, + 17700, + 17531, + 17361, + 17190, + 17018, + 16846, + 16673, + 16500, + 16326, + 16151, + 15976, + 15800, + 15624, + 15447, + 15269, + 15091, + 14912, + 14733, + 14553, + 14373, + 14192, + 14010, + 13828, + 13646, + 13463, + 13279, + 13095, + 12910, + 12725, + 12540, + 12354, + 12167, + 11980, + 11793, + 11605, + 11417, + 11228, + 11039, + 10850, + 10660, + 10469, + 10279, + 10088, + 9896, + 9704, + 9512, + 9319, + 9127, + 8933, + 8740, + 8546, + 8351, + 8157, + 7962, + 7767, + 7571, + 7376, + 7180, + 6983, + 6787, + 6590, + 6393, + 6195, + 5998, + 5800, + 5602, + 5404, + 5205, + 5007, + 4808, + 4609, + 4410, + 4211, + 4011, + 3812, + 3612, + 3412, + 3212, + 3012, + 2811, + 2611, + 2411, + 2210, + 2009, + 1809, + 1608, + 1407, + 1206, + 1005, + 804, + 603, + 402, + 201, + 0, + -201, + -402, + -603, + -804, + -1005, + -1206, + -1407, + -1608, + -1809, + -2009, + -2210, + -2411, + -2611, + -2811, + -3012, + -3212, + -3412, + -3612, + -3812, + -4011, + -4211, + -4410, + -4609, + -4808, + -5007, + -5205, + -5404, + -5602, + -5800, + -5998, + -6195, + -6393, + -6590, + -6787, + -6983, + -7180, + -7376, + -7571, + -7767, + -7962, + -8157, + -8351, + -8546, + -8740, + -8933, + -9127, + -9319, + -9512, + -9704, + -9896, + -10088, + -10279, + -10469, + -10660, + -10850, + -11039, + -11228, + -11417, + -11605, + -11793, + -11980, + -12167, + -12354, + -12540, + -12725, + -12910, + -13095, + -13279, + -13463, + -13646, + -13828, + -14010, + -14192, + -14373, + -14553, + -14733, + -14912, + -15091, + -15269, + -15447, + -15624, + -15800, + -15976, + -16151, + -16326, + -16500, + -16673, + -16846, + -17018, + -17190, + -17361, + -17531, + -17700, + -17869, + -18037, + -18205, + -18372, + -18538, + -18703, + -18868, + -19032, + -19195, + -19358, + -19520, + -19681, + -19841, + -20001, + -20160, + -20318, + -20475, + -20632, + -20788, + -20943, + -21097, + -21251, + -21403, + -21555, + -21706, + -21856, + -22006, + -22154, + -22302, + -22449, + -22595, + -22740, + -22884, + -23028, + -23170, + -23312, + -23453, + -23593, + -23732, + -23870, + -24008, + -24144, + -24279, + -24414, + -24548, + -24680, + -24812, + -24943, + -25073, + -25202, + -25330, + -25457, + -25583, + -25708, + -25833, + -25956, + -26078, + -26199, + -26320, + -26439, + -26557, + -26674, + -26791, + -26906, + -27020, + -27133, + -27246, + -27357, + -27467, + -27576, + -27684, + -27791, + -27897, + -28002, + -28106, + -28209, + -28311, + -28411, + -28511, + -28610, + -28707, + -28803, + -28899, + -28993, + -29086, + -29178, + -29269, + -29359, + -29448, + -29535, + -29622, + -29707, + -29792, + -29875, + -29957, + -30038, + -30118, + -30196, + -30274, + -30350, + -30425, + -30499, + -30572, + -30644, + -30715, + -30784, + -30853, + -30920, + -30986, + -31050, + -31114, + -31177, + -31238, + -31298, + -31357, + -31415, + -31471, + -31527, + -31581, + -31634, + -31686, + -31737, + -31786, + -31834, + -31881, + -31927, + -31972, + -32015, + -32058, + -32099, + -32138, + -32177, + -32214, + -32251, + -32286, + -32319, + -32352, + -32383, + -32413, + -32442, + -32470, + -32496, + -32522, + -32546, + -32568, + -32590, + -32610, + -32629, + -32647, + -32664, + -32679, + -32693, + -32706, + -32718, + -32729, + -32738, + -32746, + -32753, + -32758, + -32762, + -32766, + -32767, + -32767, + -32767, + -32766, + -32762, + -32758, + -32753, + -32746, + -32738, + -32729, + -32718, + -32706, + -32693, + -32679, + -32664, + -32647, + -32629, + -32610, + -32590, + -32568, + -32546, + -32522, + -32496, + -32470, + -32442, + -32413, + -32383, + -32352, + -32319, + -32286, + -32251, + -32214, + -32177, + -32138, + -32099, + -32058, + -32015, + -31972, + -31927, + -31881, + -31834, + -31786, + -31737, + -31686, + -31634, + -31581, + -31527, + -31471, + -31415, + -31357, + -31298, + -31238, + -31177, + -31114, + -31050, + -30986, + -30920, + -30853, + -30784, + -30715, + -30644, + -30572, + -30499, + -30425, + -30350, + -30274, + -30196, + -30118, + -30038, + -29957, + -29875, + -29792, + -29707, + -29622, + -29535, + -29448, + -29359, + -29269, + -29178, + -29086, + -28993, + -28899, + -28803, + -28707, + -28610, + -28511, + -28411, + -28311, + -28209, + -28106, + -28002, + -27897, + -27791, + -27684, + -27576, + -27467, + -27357, + -27246, + -27133, + -27020, + -26906, + -26791, + -26674, + -26557, + -26439, + -26320, + -26199, + -26078, + -25956, + -25833, + -25708, + -25583, + -25457, + -25330, + -25202, + -25073, + -24943, + -24812, + -24680, + -24548, + -24414, + -24279, + -24144, + -24008, + -23870, + -23732, + -23593, + -23453, + -23312, + -23170, + -23028, + -22884, + -22740, + -22595, + -22449, + -22302, + -22154, + -22006, + -21856, + -21706, + -21555, + -21403, + -21251, + -21097, + -20943, + -20788, + -20632, + -20475, + -20318, + -20160, + -20001, + -19841, + -19681, + -19520, + -19358, + -19195, + -19032, + -18868, + -18703, + -18538, + -18372, + -18205, + -18037, + -17869, + -17700, + -17531, + -17361, + -17190, + -17018, + -16846, + -16673, + -16500, + -16326, + -16151, + -15976, + -15800, + -15624, + -15447, + -15269, + -15091, + -14912, + -14733, + -14553, + -14373, + -14192, + -14010, + -13828, + -13646, + -13463, + -13279, + -13095, + -12910, + -12725, + -12540, + -12354, + -12167, + -11980, + -11793, + -11605, + -11417, + -11228, + -11039, + -10850, + -10660, + -10469, + -10279, + -10088, + -9896, + -9704, + -9512, + -9319, + -9127, + -8933, + -8740, + -8546, + -8351, + -8157, + -7962, + -7767, + -7571, + -7376, + -7180, + -6983, + -6787, + -6590, + -6393, + -6195, + -5998, + -5800, + -5602, + -5404, + -5205, + -5007, + -4808, + -4609, + -4410, + -4211, + -4011, + -3812, + -3612, + -3412, + -3212, + -3012, + -2811, + -2611, + -2411, + -2210, + -2009, + -1809, + -1608, + -1407, + -1206, + -1005, + -804, + -603, + -402, + -201, + 0, + 201, + 402, + 603, + 804, + 1005, + 1206, + 1407, + 1608, + 1809, + 2009, + 2210, + 2411, + 2611, + 2811, + 3012, + 3212, + 3412, + 3612, + 3812, + 4011, + 4211, + 4410, + 4609, + 4808, + 5007, + 5205, + 5404, + 5602, + 5800, + 5998, + 6195, + 6393, + 6590, + 6787, + 6983, + 7180, + 7376, + 7571, + 7767, + 7962, + 8157, + 8351, + 8546, + 8740, + 8933, + 9127, + 9319, + 9512, + 9704, + 9896, + 10088, + 10279, + 10469, + 10660, + 10850, + 11039, + 11228, + 11417, + 11605, + 11793, + 11980, + 12167, + 12354, + 12540, + 12725, + 12910, + 13095, + 13279, + 13463, + 13646, + 13828, + 14010, + 14192, + 14373, + 14553, + 14733, + 14912, + 15091, + 15269, + 15447, + 15624, + 15800, + 15976, + 16151, + 16326, + 16500, + 16673, + 16846, + 17018, + 17190, + 17361, + 17531, + 17700, + 17869, + 18037, + 18205, + 18372, + 18538, + 18703, + 18868, + 19032, + 19195, + 19358, + 19520, + 19681, + 19841, + 20001, + 20160, + 20318, + 20475, + 20632, + 20788, + 20943, + 21097, + 21251, + 21403, + 21555, + 21706, + 21856, + 22006, + 22154, + 22302, + 22449, + 22595, + 22740, + 22884, + 23028, + 23170, + 23312, + 23453, + 23593, + 23732, + 23870, + 24008, + 24144, + 24279, + 24414, + 24548, + 24680, + 24812, + 24943, + 25073, + 25202, + 25330, + 25457, + 25583, + 25708, + 25833, + 25956, + 26078, + 26199, + 26320, + 26439, + 26557, + 26674, + 26791, + 26906, + 27020, + 27133, + 27246, + 27357, + 27467, + 27576, + 27684, + 27791, + 27897, + 28002, + 28106, + 28209, + 28311, + 28411, + 28511, + 28610, + 28707, + 28803, + 28899, + 28993, + 29086, + 29178, + 29269, + 29359, + 29448, + 29535, + 29622, + 29707, + 29792, + 29875, + 29957, + 30038, + 30118, + 30196, + 30274, + 30350, + 30425, + 30499, + 30572, + 30644, + 30715, + 30784, + 30853, + 30920, + 30986, + 31050, + 31114, + 31177, + 31238, + 31298, + 31357, + 31415, + 31471, + 31527, + 31581, + 31634, + 31686, + 31737, + 31786, + 31834, + 31881, + 31927, + 31972, + 32015, + 32058, + 32099, + 32138, + 32177, + 32214, + 32251, + 32286, + 32319, + 32352, + 32383, + 32413, + 32442, + 32470, + 32496, + 32522, + 32546, + 32568, + 32590, + 32610, + 32629, + 32647, + 32664, + 32679, + 32693, + 32706, + 32718, + 32729, + 32738, + 32746, + 32753, + 32758, + 32762, + 32766, + 32767, +}; + +/* in Q1.15, generated from sin(i * 2 * pi / FFT_SIZE_MAX) */ +const int16_t twiddle_imag_16[FFT_SIZE_MAX] = { + 0, + -201, + -402, + -603, + -804, + -1005, + -1206, + -1407, + -1608, + -1809, + -2009, + -2210, + -2411, + -2611, + -2811, + -3012, + -3212, + -3412, + -3612, + -3812, + -4011, + -4211, + -4410, + -4609, + -4808, + -5007, + -5205, + -5404, + -5602, + -5800, + -5998, + -6195, + -6393, + -6590, + -6787, + -6983, + -7180, + -7376, + -7571, + -7767, + -7962, + -8157, + -8351, + -8546, + -8740, + -8933, + -9127, + -9319, + -9512, + -9704, + -9896, + -10088, + -10279, + -10469, + -10660, + -10850, + -11039, + -11228, + -11417, + -11605, + -11793, + -11980, + -12167, + -12354, + -12540, + -12725, + -12910, + -13095, + -13279, + -13463, + -13646, + -13828, + -14010, + -14192, + -14373, + -14553, + -14733, + -14912, + -15091, + -15269, + -15447, + -15624, + -15800, + -15976, + -16151, + -16326, + -16500, + -16673, + -16846, + -17018, + -17190, + -17361, + -17531, + -17700, + -17869, + -18037, + -18205, + -18372, + -18538, + -18703, + -18868, + -19032, + -19195, + -19358, + -19520, + -19681, + -19841, + -20001, + -20160, + -20318, + -20475, + -20632, + -20788, + -20943, + -21097, + -21251, + -21403, + -21555, + -21706, + -21856, + -22006, + -22154, + -22302, + -22449, + -22595, + -22740, + -22884, + -23028, + -23170, + -23312, + -23453, + -23593, + -23732, + -23870, + -24008, + -24144, + -24279, + -24414, + -24548, + -24680, + -24812, + -24943, + -25073, + -25202, + -25330, + -25457, + -25583, + -25708, + -25833, + -25956, + -26078, + -26199, + -26320, + -26439, + -26557, + -26674, + -26791, + -26906, + -27020, + -27133, + -27246, + -27357, + -27467, + -27576, + -27684, + -27791, + -27897, + -28002, + -28106, + -28209, + -28311, + -28411, + -28511, + -28610, + -28707, + -28803, + -28899, + -28993, + -29086, + -29178, + -29269, + -29359, + -29448, + -29535, + -29622, + -29707, + -29792, + -29875, + -29957, + -30038, + -30118, + -30196, + -30274, + -30350, + -30425, + -30499, + -30572, + -30644, + -30715, + -30784, + -30853, + -30920, + -30986, + -31050, + -31114, + -31177, + -31238, + -31298, + -31357, + -31415, + -31471, + -31527, + -31581, + -31634, + -31686, + -31737, + -31786, + -31834, + -31881, + -31927, + -31972, + -32015, + -32058, + -32099, + -32138, + -32177, + -32214, + -32251, + -32286, + -32319, + -32352, + -32383, + -32413, + -32442, + -32470, + -32496, + -32522, + -32546, + -32568, + -32590, + -32610, + -32629, + -32647, + -32664, + -32679, + -32693, + -32706, + -32718, + -32729, + -32738, + -32746, + -32753, + -32758, + -32762, + -32766, + -32767, + -32767, + -32767, + -32766, + -32762, + -32758, + -32753, + -32746, + -32738, + -32729, + -32718, + -32706, + -32693, + -32679, + -32664, + -32647, + -32629, + -32610, + -32590, + -32568, + -32546, + -32522, + -32496, + -32470, + -32442, + -32413, + -32383, + -32352, + -32319, + -32286, + -32251, + -32214, + -32177, + -32138, + -32099, + -32058, + -32015, + -31972, + -31927, + -31881, + -31834, + -31786, + -31737, + -31686, + -31634, + -31581, + -31527, + -31471, + -31415, + -31357, + -31298, + -31238, + -31177, + -31114, + -31050, + -30986, + -30920, + -30853, + -30784, + -30715, + -30644, + -30572, + -30499, + -30425, + -30350, + -30274, + -30196, + -30118, + -30038, + -29957, + -29875, + -29792, + -29707, + -29622, + -29535, + -29448, + -29359, + -29269, + -29178, + -29086, + -28993, + -28899, + -28803, + -28707, + -28610, + -28511, + -28411, + -28311, + -28209, + -28106, + -28002, + -27897, + -27791, + -27684, + -27576, + -27467, + -27357, + -27246, + -27133, + -27020, + -26906, + -26791, + -26674, + -26557, + -26439, + -26320, + -26199, + -26078, + -25956, + -25833, + -25708, + -25583, + -25457, + -25330, + -25202, + -25073, + -24943, + -24812, + -24680, + -24548, + -24414, + -24279, + -24144, + -24008, + -23870, + -23732, + -23593, + -23453, + -23312, + -23170, + -23028, + -22884, + -22740, + -22595, + -22449, + -22302, + -22154, + -22006, + -21856, + -21706, + -21555, + -21403, + -21251, + -21097, + -20943, + -20788, + -20632, + -20475, + -20318, + -20160, + -20001, + -19841, + -19681, + -19520, + -19358, + -19195, + -19032, + -18868, + -18703, + -18538, + -18372, + -18205, + -18037, + -17869, + -17700, + -17531, + -17361, + -17190, + -17018, + -16846, + -16673, + -16500, + -16326, + -16151, + -15976, + -15800, + -15624, + -15447, + -15269, + -15091, + -14912, + -14733, + -14553, + -14373, + -14192, + -14010, + -13828, + -13646, + -13463, + -13279, + -13095, + -12910, + -12725, + -12540, + -12354, + -12167, + -11980, + -11793, + -11605, + -11417, + -11228, + -11039, + -10850, + -10660, + -10469, + -10279, + -10088, + -9896, + -9704, + -9512, + -9319, + -9127, + -8933, + -8740, + -8546, + -8351, + -8157, + -7962, + -7767, + -7571, + -7376, + -7180, + -6983, + -6787, + -6590, + -6393, + -6195, + -5998, + -5800, + -5602, + -5404, + -5205, + -5007, + -4808, + -4609, + -4410, + -4211, + -4011, + -3812, + -3612, + -3412, + -3212, + -3012, + -2811, + -2611, + -2411, + -2210, + -2009, + -1809, + -1608, + -1407, + -1206, + -1005, + -804, + -603, + -402, + -201, + 0, + 201, + 402, + 603, + 804, + 1005, + 1206, + 1407, + 1608, + 1809, + 2009, + 2210, + 2411, + 2611, + 2811, + 3012, + 3212, + 3412, + 3612, + 3812, + 4011, + 4211, + 4410, + 4609, + 4808, + 5007, + 5205, + 5404, + 5602, + 5800, + 5998, + 6195, + 6393, + 6590, + 6787, + 6983, + 7180, + 7376, + 7571, + 7767, + 7962, + 8157, + 8351, + 8546, + 8740, + 8933, + 9127, + 9319, + 9512, + 9704, + 9896, + 10088, + 10279, + 10469, + 10660, + 10850, + 11039, + 11228, + 11417, + 11605, + 11793, + 11980, + 12167, + 12354, + 12540, + 12725, + 12910, + 13095, + 13279, + 13463, + 13646, + 13828, + 14010, + 14192, + 14373, + 14553, + 14733, + 14912, + 15091, + 15269, + 15447, + 15624, + 15800, + 15976, + 16151, + 16326, + 16500, + 16673, + 16846, + 17018, + 17190, + 17361, + 17531, + 17700, + 17869, + 18037, + 18205, + 18372, + 18538, + 18703, + 18868, + 19032, + 19195, + 19358, + 19520, + 19681, + 19841, + 20001, + 20160, + 20318, + 20475, + 20632, + 20788, + 20943, + 21097, + 21251, + 21403, + 21555, + 21706, + 21856, + 22006, + 22154, + 22302, + 22449, + 22595, + 22740, + 22884, + 23028, + 23170, + 23312, + 23453, + 23593, + 23732, + 23870, + 24008, + 24144, + 24279, + 24414, + 24548, + 24680, + 24812, + 24943, + 25073, + 25202, + 25330, + 25457, + 25583, + 25708, + 25833, + 25956, + 26078, + 26199, + 26320, + 26439, + 26557, + 26674, + 26791, + 26906, + 27020, + 27133, + 27246, + 27357, + 27467, + 27576, + 27684, + 27791, + 27897, + 28002, + 28106, + 28209, + 28311, + 28411, + 28511, + 28610, + 28707, + 28803, + 28899, + 28993, + 29086, + 29178, + 29269, + 29359, + 29448, + 29535, + 29622, + 29707, + 29792, + 29875, + 29957, + 30038, + 30118, + 30196, + 30274, + 30350, + 30425, + 30499, + 30572, + 30644, + 30715, + 30784, + 30853, + 30920, + 30986, + 31050, + 31114, + 31177, + 31238, + 31298, + 31357, + 31415, + 31471, + 31527, + 31581, + 31634, + 31686, + 31737, + 31786, + 31834, + 31881, + 31927, + 31972, + 32015, + 32058, + 32099, + 32138, + 32177, + 32214, + 32251, + 32286, + 32319, + 32352, + 32383, + 32413, + 32442, + 32470, + 32496, + 32522, + 32546, + 32568, + 32590, + 32610, + 32629, + 32647, + 32664, + 32679, + 32693, + 32706, + 32718, + 32729, + 32738, + 32746, + 32753, + 32758, + 32762, + 32766, + 32767, + 32767, + 32767, + 32766, + 32762, + 32758, + 32753, + 32746, + 32738, + 32729, + 32718, + 32706, + 32693, + 32679, + 32664, + 32647, + 32629, + 32610, + 32590, + 32568, + 32546, + 32522, + 32496, + 32470, + 32442, + 32413, + 32383, + 32352, + 32319, + 32286, + 32251, + 32214, + 32177, + 32138, + 32099, + 32058, + 32015, + 31972, + 31927, + 31881, + 31834, + 31786, + 31737, + 31686, + 31634, + 31581, + 31527, + 31471, + 31415, + 31357, + 31298, + 31238, + 31177, + 31114, + 31050, + 30986, + 30920, + 30853, + 30784, + 30715, + 30644, + 30572, + 30499, + 30425, + 30350, + 30274, + 30196, + 30118, + 30038, + 29957, + 29875, + 29792, + 29707, + 29622, + 29535, + 29448, + 29359, + 29269, + 29178, + 29086, + 28993, + 28899, + 28803, + 28707, + 28610, + 28511, + 28411, + 28311, + 28209, + 28106, + 28002, + 27897, + 27791, + 27684, + 27576, + 27467, + 27357, + 27246, + 27133, + 27020, + 26906, + 26791, + 26674, + 26557, + 26439, + 26320, + 26199, + 26078, + 25956, + 25833, + 25708, + 25583, + 25457, + 25330, + 25202, + 25073, + 24943, + 24812, + 24680, + 24548, + 24414, + 24279, + 24144, + 24008, + 23870, + 23732, + 23593, + 23453, + 23312, + 23170, + 23028, + 22884, + 22740, + 22595, + 22449, + 22302, + 22154, + 22006, + 21856, + 21706, + 21555, + 21403, + 21251, + 21097, + 20943, + 20788, + 20632, + 20475, + 20318, + 20160, + 20001, + 19841, + 19681, + 19520, + 19358, + 19195, + 19032, + 18868, + 18703, + 18538, + 18372, + 18205, + 18037, + 17869, + 17700, + 17531, + 17361, + 17190, + 17018, + 16846, + 16673, + 16500, + 16326, + 16151, + 15976, + 15800, + 15624, + 15447, + 15269, + 15091, + 14912, + 14733, + 14553, + 14373, + 14192, + 14010, + 13828, + 13646, + 13463, + 13279, + 13095, + 12910, + 12725, + 12540, + 12354, + 12167, + 11980, + 11793, + 11605, + 11417, + 11228, + 11039, + 10850, + 10660, + 10469, + 10279, + 10088, + 9896, + 9704, + 9512, + 9319, + 9127, + 8933, + 8740, + 8546, + 8351, + 8157, + 7962, + 7767, + 7571, + 7376, + 7180, + 6983, + 6787, + 6590, + 6393, + 6195, + 5998, + 5800, + 5602, + 5404, + 5205, + 5007, + 4808, + 4609, + 4410, + 4211, + 4011, + 3812, + 3612, + 3412, + 3212, + 3012, + 2811, + 2611, + 2411, + 2210, + 2009, + 1809, + 1608, + 1407, + 1206, + 1005, + 804, + 603, + 402, + 201, +}; + +#endif diff --git a/src/include/sof/audio/coefficients/fft/twiddle_3072_32.h b/src/include/sof/audio/coefficients/fft/twiddle_3072_32.h new file mode 100644 index 000000000000..3024c7b49cff --- /dev/null +++ b/src/include/sof/audio/coefficients/fft/twiddle_3072_32.h @@ -0,0 +1,4120 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +/* Twiddle factors in Q1.31 format */ + +#ifndef __INCLUDE_TWIDDLE_3072_32_H__ +#define __INCLUDE_TWIDDLE_3072_32_H__ + +#include <stdint.h> + +#define FFT_MULTI_TWIDDLE_SIZE 2048 + +/* in Q1.31, generated from cos(i * 2 * pi / FFT_SIZE_MAX) */ +const int32_t multi_twiddle_real_32[FFT_MULTI_TWIDDLE_SIZE] = { + 2147483647, + 2147479156, + 2147465681, + 2147443222, + 2147411780, + 2147371355, + 2147321946, + 2147263555, + 2147196181, + 2147119825, + 2147034487, + 2146940167, + 2146836866, + 2146724584, + 2146603322, + 2146473080, + 2146333858, + 2146185658, + 2146028480, + 2145862324, + 2145687192, + 2145503083, + 2145310000, + 2145107942, + 2144896910, + 2144676905, + 2144447929, + 2144209982, + 2143963065, + 2143707180, + 2143442326, + 2143168506, + 2142885721, + 2142593971, + 2142293258, + 2141983583, + 2141664948, + 2141337354, + 2141000801, + 2140655293, + 2140300829, + 2139937412, + 2139565043, + 2139183723, + 2138793455, + 2138394240, + 2137986079, + 2137568974, + 2137142927, + 2136707940, + 2136264015, + 2135811153, + 2135349356, + 2134878626, + 2134398966, + 2133910377, + 2133412861, + 2132906420, + 2132391057, + 2131866773, + 2131333572, + 2130791454, + 2130240422, + 2129680480, + 2129111628, + 2128533869, + 2127947206, + 2127351642, + 2126747178, + 2126133817, + 2125511562, + 2124880416, + 2124240380, + 2123591458, + 2122933653, + 2122266967, + 2121591402, + 2120906963, + 2120213651, + 2119511470, + 2118800422, + 2118080511, + 2117351739, + 2116614110, + 2115867626, + 2115112291, + 2114348108, + 2113575080, + 2112793210, + 2112002502, + 2111202959, + 2110394584, + 2109577380, + 2108751352, + 2107916502, + 2107072834, + 2106220352, + 2105359059, + 2104488958, + 2103610054, + 2102722350, + 2101825849, + 2100920556, + 2100006474, + 2099083608, + 2098151960, + 2097211535, + 2096262337, + 2095304370, + 2094337637, + 2093362143, + 2092377892, + 2091384888, + 2090383135, + 2089372638, + 2088353400, + 2087325426, + 2086288720, + 2085243286, + 2084189130, + 2083126254, + 2082054665, + 2080974365, + 2079885360, + 2078787655, + 2077681253, + 2076566160, + 2075442379, + 2074309917, + 2073168777, + 2072018965, + 2070860485, + 2069693342, + 2068517540, + 2067333086, + 2066139983, + 2064938237, + 2063727853, + 2062508835, + 2061281190, + 2060044922, + 2058800036, + 2057546537, + 2056284431, + 2055013723, + 2053734418, + 2052446522, + 2051150040, + 2049844978, + 2048531340, + 2047209133, + 2045878362, + 2044539032, + 2043191150, + 2041834720, + 2040469748, + 2039096241, + 2037714204, + 2036323642, + 2034924562, + 2033516969, + 2032100869, + 2030676269, + 2029243173, + 2027801589, + 2026351522, + 2024892978, + 2023425963, + 2021950484, + 2020466546, + 2018974156, + 2017473321, + 2015964045, + 2014446336, + 2012920201, + 2011385644, + 2009842674, + 2008291295, + 2006731516, + 2005163342, + 2003586779, + 2002001835, + 2000408516, + 1998806829, + 1997196780, + 1995578377, + 1993951625, + 1992316532, + 1990673105, + 1989021350, + 1987361274, + 1985692885, + 1984016189, + 1982331193, + 1980637905, + 1978936331, + 1977226479, + 1975508355, + 1973781967, + 1972047323, + 1970304428, + 1968553292, + 1966793920, + 1965026321, + 1963250501, + 1961466469, + 1959674231, + 1957873796, + 1956065170, + 1954248361, + 1952423377, + 1950590226, + 1948748914, + 1946899451, + 1945041843, + 1943176098, + 1941302225, + 1939420231, + 1937530123, + 1935631910, + 1933725600, + 1931811201, + 1929888720, + 1927958166, + 1926019547, + 1924072871, + 1922118145, + 1920155379, + 1918184581, + 1916205758, + 1914218919, + 1912224073, + 1910221227, + 1908210390, + 1906191570, + 1904164776, + 1902130017, + 1900087301, + 1898036636, + 1895978031, + 1893911494, + 1891837035, + 1889754661, + 1887664383, + 1885566207, + 1883460144, + 1881346202, + 1879224389, + 1877094716, + 1874957189, + 1872811820, + 1870658615, + 1868497586, + 1866328740, + 1864152086, + 1861967634, + 1859775393, + 1857575372, + 1855367581, + 1853152028, + 1850928722, + 1848697674, + 1846458892, + 1844212386, + 1841958164, + 1839696238, + 1837426615, + 1835149306, + 1832864320, + 1830571667, + 1828271356, + 1825963397, + 1823647799, + 1821324572, + 1818993726, + 1816655271, + 1814309216, + 1811955572, + 1809594347, + 1807225553, + 1804849198, + 1802465294, + 1800073849, + 1797674873, + 1795268378, + 1792854372, + 1790432867, + 1788003871, + 1785567396, + 1783123452, + 1780672048, + 1778213194, + 1775746903, + 1773273182, + 1770792044, + 1768303498, + 1765807555, + 1763304224, + 1760793518, + 1758275445, + 1755750017, + 1753217244, + 1750677137, + 1748129707, + 1745574963, + 1743012918, + 1740443581, + 1737866963, + 1735283075, + 1732691928, + 1730093532, + 1727487899, + 1724875040, + 1722254965, + 1719627685, + 1716993211, + 1714351555, + 1711702727, + 1709046739, + 1706383601, + 1703713325, + 1701035922, + 1698351403, + 1695659779, + 1692961062, + 1690255263, + 1687542393, + 1684822463, + 1682095486, + 1679361471, + 1676620432, + 1673872378, + 1671117323, + 1668355276, + 1665586251, + 1662810258, + 1660027308, + 1657237415, + 1654440588, + 1651636841, + 1648826185, + 1646008631, + 1643184191, + 1640352877, + 1637514702, + 1634669676, + 1631817811, + 1628959121, + 1626093616, + 1623221309, + 1620342211, + 1617456335, + 1614563692, + 1611664296, + 1608758157, + 1605845289, + 1602925703, + 1599999411, + 1597066426, + 1594126760, + 1591180426, + 1588227435, + 1585267800, + 1582301533, + 1579328647, + 1576349155, + 1573363068, + 1570370399, + 1567371161, + 1564365367, + 1561353028, + 1558334157, + 1555308768, + 1552276872, + 1549238483, + 1546193612, + 1543142274, + 1540084480, + 1537020244, + 1533949577, + 1530872494, + 1527789007, + 1524699129, + 1521602872, + 1518500250, + 1515391276, + 1512275962, + 1509154322, + 1506026369, + 1502892116, + 1499751576, + 1496604762, + 1493451687, + 1490292364, + 1487126808, + 1483955030, + 1480777044, + 1477592864, + 1474402503, + 1471205974, + 1468003290, + 1464794466, + 1461579514, + 1458358447, + 1455131280, + 1451898025, + 1448658697, + 1445413309, + 1442161874, + 1438904406, + 1435640919, + 1432371426, + 1429095941, + 1425814478, + 1422527051, + 1419233672, + 1415934356, + 1412629117, + 1409317969, + 1406000925, + 1402678000, + 1399349206, + 1396014559, + 1392674072, + 1389327759, + 1385975633, + 1382617710, + 1379254004, + 1375884527, + 1372509294, + 1369128320, + 1365741619, + 1362349204, + 1358951090, + 1355547292, + 1352137822, + 1348722696, + 1345301929, + 1341875533, + 1338443524, + 1335005916, + 1331562723, + 1328113960, + 1324659641, + 1321199781, + 1317734393, + 1314263493, + 1310787095, + 1307305214, + 1303817864, + 1300325060, + 1296826816, + 1293323147, + 1289814068, + 1286299593, + 1282779738, + 1279254516, + 1275723942, + 1272188032, + 1268646800, + 1265100260, + 1261548429, + 1257991320, + 1254428948, + 1250861329, + 1247288478, + 1243710408, + 1240127136, + 1236538675, + 1232945043, + 1229346252, + 1225742318, + 1222133257, + 1218519084, + 1214899813, + 1211275460, + 1207646039, + 1204011567, + 1200372058, + 1196727527, + 1193077991, + 1189423463, + 1185763960, + 1182099496, + 1178430087, + 1174755748, + 1171076495, + 1167392344, + 1163703308, + 1160009405, + 1156310649, + 1152607055, + 1148898640, + 1145185419, + 1141467408, + 1137744621, + 1134017074, + 1130284784, + 1126547765, + 1122806034, + 1119059606, + 1115308496, + 1111552721, + 1107792296, + 1104027237, + 1100257559, + 1096483278, + 1092704411, + 1088920972, + 1085132978, + 1081340445, + 1077543388, + 1073741824, + 1069935768, + 1066125236, + 1062310244, + 1058490808, + 1054666944, + 1050838668, + 1047005996, + 1043168945, + 1039327529, + 1035481766, + 1031631671, + 1027777260, + 1023918550, + 1020055556, + 1016188296, + 1012316784, + 1008441038, + 1004561072, + 1000676905, + 996788551, + 992896028, + 988999351, + 985098537, + 981193602, + 977284562, + 973371434, + 969454234, + 965532978, + 961607684, + 957678367, + 953745043, + 949807730, + 945866443, + 941921200, + 937972016, + 934018909, + 930061894, + 926100989, + 922136209, + 918167572, + 914195094, + 910218791, + 906238681, + 902254780, + 898267104, + 894275671, + 890280497, + 886281598, + 882278992, + 878272695, + 874262724, + 870249095, + 866231826, + 862210934, + 858186435, + 854158345, + 850126682, + 846091463, + 842052705, + 838010424, + 833964638, + 829915362, + 825862615, + 821806413, + 817746774, + 813683713, + 809617249, + 805547397, + 801474176, + 797397602, + 793317693, + 789234464, + 785147934, + 781058120, + 776965038, + 772868706, + 768769141, + 764666360, + 760560380, + 756451218, + 752338892, + 748223418, + 744104815, + 739983099, + 735858287, + 731730397, + 727599446, + 723465451, + 719328430, + 715188400, + 711045377, + 706899381, + 702750427, + 698598533, + 694443717, + 690285996, + 686125387, + 681961908, + 677795576, + 673626408, + 669454423, + 665279637, + 661102068, + 656921734, + 652738651, + 648552838, + 644364312, + 640173090, + 635979190, + 631782630, + 627583426, + 623381598, + 619177161, + 614970135, + 610760536, + 606548381, + 602333690, + 598116479, + 593896765, + 589674567, + 585449903, + 581222789, + 576993244, + 572761285, + 568526931, + 564290197, + 560051104, + 555809667, + 551565905, + 547319836, + 543071478, + 538820847, + 534567963, + 530312842, + 526055503, + 521795963, + 517534240, + 513270353, + 509004318, + 504736154, + 500465878, + 496193509, + 491919064, + 487642562, + 483364019, + 479083454, + 474800886, + 470516330, + 466229807, + 461941333, + 457650927, + 453358607, + 449064389, + 444768294, + 440470337, + 436170538, + 431868915, + 427565485, + 423260266, + 418953276, + 414644534, + 410334058, + 406021865, + 401707973, + 397392401, + 393075166, + 388756287, + 384435782, + 380113669, + 375789965, + 371464690, + 367137861, + 362809495, + 358479612, + 354148230, + 349815365, + 345481038, + 341145265, + 336808065, + 332469456, + 328129457, + 323788084, + 319445358, + 315101295, + 310755913, + 306409232, + 302061269, + 297712042, + 293361570, + 289009871, + 284656963, + 280302863, + 275947592, + 271591166, + 267233603, + 262874923, + 258515144, + 254154282, + 249792358, + 245429388, + 241065392, + 236700388, + 232334393, + 227967426, + 223599506, + 219230650, + 214860878, + 210490206, + 206118654, + 201746240, + 197372981, + 192998897, + 188624006, + 184248325, + 179871874, + 175494670, + 171116733, + 166738079, + 162358728, + 157978697, + 153598006, + 149216672, + 144834714, + 140452151, + 136068999, + 131685278, + 127301007, + 122916203, + 118530885, + 114145071, + 109758779, + 105372028, + 100984837, + 96597223, + 92209205, + 87820801, + 83432030, + 79042909, + 74653459, + 70263695, + 65873638, + 61483306, + 57092716, + 52701887, + 48310838, + 43919586, + 39528151, + 35136551, + 30744804, + 26352928, + 21960942, + 17568864, + 13176712, + 8784505, + 4392262, + 0, + -4392262, + -8784505, + -13176712, + -17568864, + -21960942, + -26352928, + -30744804, + -35136551, + -39528151, + -43919586, + -48310838, + -52701887, + -57092716, + -61483306, + -65873638, + -70263695, + -74653459, + -79042909, + -83432030, + -87820801, + -92209205, + -96597223, + -100984837, + -105372028, + -109758779, + -114145071, + -118530885, + -122916203, + -127301007, + -131685278, + -136068999, + -140452151, + -144834714, + -149216672, + -153598006, + -157978697, + -162358728, + -166738079, + -171116733, + -175494670, + -179871874, + -184248325, + -188624006, + -192998897, + -197372981, + -201746240, + -206118654, + -210490206, + -214860878, + -219230650, + -223599506, + -227967426, + -232334393, + -236700388, + -241065392, + -245429388, + -249792358, + -254154282, + -258515144, + -262874923, + -267233603, + -271591166, + -275947592, + -280302863, + -284656963, + -289009871, + -293361570, + -297712042, + -302061269, + -306409232, + -310755913, + -315101295, + -319445358, + -323788084, + -328129457, + -332469456, + -336808065, + -341145265, + -345481038, + -349815365, + -354148230, + -358479612, + -362809495, + -367137861, + -371464690, + -375789965, + -380113669, + -384435782, + -388756287, + -393075166, + -397392401, + -401707973, + -406021865, + -410334058, + -414644534, + -418953276, + -423260266, + -427565485, + -431868915, + -436170538, + -440470337, + -444768294, + -449064389, + -453358607, + -457650927, + -461941333, + -466229807, + -470516330, + -474800886, + -479083454, + -483364019, + -487642562, + -491919064, + -496193509, + -500465878, + -504736154, + -509004318, + -513270353, + -517534240, + -521795963, + -526055503, + -530312842, + -534567963, + -538820847, + -543071478, + -547319836, + -551565905, + -555809667, + -560051104, + -564290197, + -568526931, + -572761285, + -576993244, + -581222789, + -585449903, + -589674567, + -593896765, + -598116479, + -602333690, + -606548381, + -610760536, + -614970135, + -619177161, + -623381598, + -627583426, + -631782630, + -635979190, + -640173090, + -644364312, + -648552838, + -652738651, + -656921734, + -661102068, + -665279637, + -669454423, + -673626408, + -677795576, + -681961908, + -686125387, + -690285996, + -694443717, + -698598533, + -702750427, + -706899381, + -711045377, + -715188400, + -719328430, + -723465451, + -727599446, + -731730397, + -735858287, + -739983099, + -744104815, + -748223418, + -752338892, + -756451218, + -760560380, + -764666360, + -768769141, + -772868706, + -776965038, + -781058120, + -785147934, + -789234464, + -793317693, + -797397602, + -801474176, + -805547397, + -809617249, + -813683713, + -817746774, + -821806413, + -825862615, + -829915362, + -833964638, + -838010424, + -842052705, + -846091463, + -850126682, + -854158345, + -858186435, + -862210934, + -866231826, + -870249095, + -874262724, + -878272695, + -882278992, + -886281598, + -890280497, + -894275671, + -898267104, + -902254780, + -906238681, + -910218791, + -914195094, + -918167572, + -922136209, + -926100989, + -930061894, + -934018909, + -937972016, + -941921200, + -945866443, + -949807730, + -953745043, + -957678367, + -961607684, + -965532978, + -969454234, + -973371434, + -977284562, + -981193602, + -985098537, + -988999351, + -992896028, + -996788551, + -1000676905, + -1004561072, + -1008441038, + -1012316784, + -1016188296, + -1020055556, + -1023918550, + -1027777260, + -1031631671, + -1035481766, + -1039327529, + -1043168945, + -1047005996, + -1050838668, + -1054666944, + -1058490808, + -1062310244, + -1066125236, + -1069935768, + -1073741824, + -1077543388, + -1081340445, + -1085132978, + -1088920972, + -1092704411, + -1096483278, + -1100257559, + -1104027237, + -1107792296, + -1111552721, + -1115308496, + -1119059606, + -1122806034, + -1126547765, + -1130284784, + -1134017074, + -1137744621, + -1141467408, + -1145185419, + -1148898640, + -1152607055, + -1156310649, + -1160009405, + -1163703308, + -1167392344, + -1171076495, + -1174755748, + -1178430087, + -1182099496, + -1185763960, + -1189423463, + -1193077991, + -1196727527, + -1200372058, + -1204011567, + -1207646039, + -1211275460, + -1214899813, + -1218519084, + -1222133257, + -1225742318, + -1229346252, + -1232945043, + -1236538675, + -1240127136, + -1243710408, + -1247288478, + -1250861329, + -1254428948, + -1257991320, + -1261548429, + -1265100260, + -1268646800, + -1272188032, + -1275723942, + -1279254516, + -1282779738, + -1286299593, + -1289814068, + -1293323147, + -1296826816, + -1300325060, + -1303817864, + -1307305214, + -1310787095, + -1314263493, + -1317734393, + -1321199781, + -1324659641, + -1328113960, + -1331562723, + -1335005916, + -1338443524, + -1341875533, + -1345301929, + -1348722696, + -1352137822, + -1355547292, + -1358951090, + -1362349204, + -1365741619, + -1369128320, + -1372509294, + -1375884527, + -1379254004, + -1382617710, + -1385975633, + -1389327759, + -1392674072, + -1396014559, + -1399349206, + -1402678000, + -1406000925, + -1409317969, + -1412629117, + -1415934356, + -1419233672, + -1422527051, + -1425814478, + -1429095941, + -1432371426, + -1435640919, + -1438904406, + -1442161874, + -1445413309, + -1448658697, + -1451898025, + -1455131280, + -1458358447, + -1461579514, + -1464794466, + -1468003290, + -1471205974, + -1474402503, + -1477592864, + -1480777044, + -1483955030, + -1487126808, + -1490292364, + -1493451687, + -1496604762, + -1499751576, + -1502892116, + -1506026369, + -1509154322, + -1512275962, + -1515391276, + -1518500250, + -1521602872, + -1524699129, + -1527789007, + -1530872494, + -1533949577, + -1537020244, + -1540084480, + -1543142274, + -1546193612, + -1549238483, + -1552276872, + -1555308768, + -1558334157, + -1561353028, + -1564365367, + -1567371161, + -1570370399, + -1573363068, + -1576349155, + -1579328647, + -1582301533, + -1585267800, + -1588227435, + -1591180426, + -1594126760, + -1597066426, + -1599999411, + -1602925703, + -1605845289, + -1608758157, + -1611664296, + -1614563692, + -1617456335, + -1620342211, + -1623221309, + -1626093616, + -1628959121, + -1631817811, + -1634669676, + -1637514702, + -1640352877, + -1643184191, + -1646008631, + -1648826185, + -1651636841, + -1654440588, + -1657237415, + -1660027308, + -1662810258, + -1665586251, + -1668355276, + -1671117323, + -1673872378, + -1676620432, + -1679361471, + -1682095486, + -1684822463, + -1687542393, + -1690255263, + -1692961062, + -1695659779, + -1698351403, + -1701035922, + -1703713325, + -1706383601, + -1709046739, + -1711702727, + -1714351555, + -1716993211, + -1719627685, + -1722254965, + -1724875040, + -1727487899, + -1730093532, + -1732691928, + -1735283075, + -1737866963, + -1740443581, + -1743012918, + -1745574963, + -1748129707, + -1750677137, + -1753217244, + -1755750017, + -1758275445, + -1760793518, + -1763304224, + -1765807555, + -1768303498, + -1770792044, + -1773273182, + -1775746903, + -1778213194, + -1780672048, + -1783123452, + -1785567396, + -1788003871, + -1790432867, + -1792854372, + -1795268378, + -1797674873, + -1800073849, + -1802465294, + -1804849198, + -1807225553, + -1809594347, + -1811955572, + -1814309216, + -1816655271, + -1818993726, + -1821324572, + -1823647799, + -1825963397, + -1828271356, + -1830571667, + -1832864320, + -1835149306, + -1837426615, + -1839696238, + -1841958164, + -1844212386, + -1846458892, + -1848697674, + -1850928722, + -1853152028, + -1855367581, + -1857575372, + -1859775393, + -1861967634, + -1864152086, + -1866328740, + -1868497586, + -1870658615, + -1872811820, + -1874957189, + -1877094716, + -1879224389, + -1881346202, + -1883460144, + -1885566207, + -1887664383, + -1889754661, + -1891837035, + -1893911494, + -1895978031, + -1898036636, + -1900087301, + -1902130017, + -1904164776, + -1906191570, + -1908210390, + -1910221227, + -1912224073, + -1914218919, + -1916205758, + -1918184581, + -1920155379, + -1922118145, + -1924072871, + -1926019547, + -1927958166, + -1929888720, + -1931811201, + -1933725600, + -1935631910, + -1937530123, + -1939420231, + -1941302225, + -1943176098, + -1945041843, + -1946899451, + -1948748914, + -1950590226, + -1952423377, + -1954248361, + -1956065170, + -1957873796, + -1959674231, + -1961466469, + -1963250501, + -1965026321, + -1966793920, + -1968553292, + -1970304428, + -1972047323, + -1973781967, + -1975508355, + -1977226479, + -1978936331, + -1980637905, + -1982331193, + -1984016189, + -1985692885, + -1987361274, + -1989021350, + -1990673105, + -1992316532, + -1993951625, + -1995578377, + -1997196780, + -1998806829, + -2000408516, + -2002001835, + -2003586779, + -2005163342, + -2006731516, + -2008291295, + -2009842674, + -2011385644, + -2012920201, + -2014446336, + -2015964045, + -2017473321, + -2018974156, + -2020466546, + -2021950484, + -2023425963, + -2024892978, + -2026351522, + -2027801589, + -2029243173, + -2030676269, + -2032100869, + -2033516969, + -2034924562, + -2036323642, + -2037714204, + -2039096241, + -2040469748, + -2041834720, + -2043191150, + -2044539032, + -2045878362, + -2047209133, + -2048531340, + -2049844978, + -2051150040, + -2052446522, + -2053734418, + -2055013723, + -2056284431, + -2057546537, + -2058800036, + -2060044922, + -2061281190, + -2062508835, + -2063727853, + -2064938237, + -2066139983, + -2067333086, + -2068517540, + -2069693342, + -2070860485, + -2072018965, + -2073168777, + -2074309917, + -2075442379, + -2076566160, + -2077681253, + -2078787655, + -2079885360, + -2080974365, + -2082054665, + -2083126254, + -2084189130, + -2085243286, + -2086288720, + -2087325426, + -2088353400, + -2089372638, + -2090383135, + -2091384888, + -2092377892, + -2093362143, + -2094337637, + -2095304370, + -2096262337, + -2097211535, + -2098151960, + -2099083608, + -2100006474, + -2100920556, + -2101825849, + -2102722350, + -2103610054, + -2104488958, + -2105359059, + -2106220352, + -2107072834, + -2107916502, + -2108751352, + -2109577380, + -2110394584, + -2111202959, + -2112002502, + -2112793210, + -2113575080, + -2114348108, + -2115112291, + -2115867626, + -2116614110, + -2117351739, + -2118080511, + -2118800422, + -2119511470, + -2120213651, + -2120906963, + -2121591402, + -2122266967, + -2122933653, + -2123591458, + -2124240380, + -2124880416, + -2125511562, + -2126133817, + -2126747178, + -2127351642, + -2127947206, + -2128533869, + -2129111628, + -2129680480, + -2130240422, + -2130791454, + -2131333572, + -2131866773, + -2132391057, + -2132906420, + -2133412861, + -2133910377, + -2134398966, + -2134878626, + -2135349356, + -2135811153, + -2136264015, + -2136707940, + -2137142927, + -2137568974, + -2137986079, + -2138394240, + -2138793455, + -2139183723, + -2139565043, + -2139937412, + -2140300829, + -2140655293, + -2141000801, + -2141337354, + -2141664948, + -2141983583, + -2142293258, + -2142593971, + -2142885721, + -2143168506, + -2143442326, + -2143707180, + -2143963065, + -2144209982, + -2144447929, + -2144676905, + -2144896910, + -2145107942, + -2145310000, + -2145503083, + -2145687192, + -2145862324, + -2146028480, + -2146185658, + -2146333858, + -2146473080, + -2146603322, + -2146724584, + -2146836866, + -2146940167, + -2147034487, + -2147119825, + -2147196181, + -2147263555, + -2147321946, + -2147371355, + -2147411780, + -2147443222, + -2147465681, + -2147479156, + -2147483647, + -2147479156, + -2147465681, + -2147443222, + -2147411780, + -2147371355, + -2147321946, + -2147263555, + -2147196181, + -2147119825, + -2147034487, + -2146940167, + -2146836866, + -2146724584, + -2146603322, + -2146473080, + -2146333858, + -2146185658, + -2146028480, + -2145862324, + -2145687192, + -2145503083, + -2145310000, + -2145107942, + -2144896910, + -2144676905, + -2144447929, + -2144209982, + -2143963065, + -2143707180, + -2143442326, + -2143168506, + -2142885721, + -2142593971, + -2142293258, + -2141983583, + -2141664948, + -2141337354, + -2141000801, + -2140655293, + -2140300829, + -2139937412, + -2139565043, + -2139183723, + -2138793455, + -2138394240, + -2137986079, + -2137568974, + -2137142927, + -2136707940, + -2136264015, + -2135811153, + -2135349356, + -2134878626, + -2134398966, + -2133910377, + -2133412861, + -2132906420, + -2132391057, + -2131866773, + -2131333572, + -2130791454, + -2130240422, + -2129680480, + -2129111628, + -2128533869, + -2127947206, + -2127351642, + -2126747178, + -2126133817, + -2125511562, + -2124880416, + -2124240380, + -2123591458, + -2122933653, + -2122266967, + -2121591402, + -2120906963, + -2120213651, + -2119511470, + -2118800422, + -2118080511, + -2117351739, + -2116614110, + -2115867626, + -2115112291, + -2114348108, + -2113575080, + -2112793210, + -2112002502, + -2111202959, + -2110394584, + -2109577380, + -2108751352, + -2107916502, + -2107072834, + -2106220352, + -2105359059, + -2104488958, + -2103610054, + -2102722350, + -2101825849, + -2100920556, + -2100006474, + -2099083608, + -2098151960, + -2097211535, + -2096262337, + -2095304370, + -2094337637, + -2093362143, + -2092377892, + -2091384888, + -2090383135, + -2089372638, + -2088353400, + -2087325426, + -2086288720, + -2085243286, + -2084189130, + -2083126254, + -2082054665, + -2080974365, + -2079885360, + -2078787655, + -2077681253, + -2076566160, + -2075442379, + -2074309917, + -2073168777, + -2072018965, + -2070860485, + -2069693342, + -2068517540, + -2067333086, + -2066139983, + -2064938237, + -2063727853, + -2062508835, + -2061281190, + -2060044922, + -2058800036, + -2057546537, + -2056284431, + -2055013723, + -2053734418, + -2052446522, + -2051150040, + -2049844978, + -2048531340, + -2047209133, + -2045878362, + -2044539032, + -2043191150, + -2041834720, + -2040469748, + -2039096241, + -2037714204, + -2036323642, + -2034924562, + -2033516969, + -2032100869, + -2030676269, + -2029243173, + -2027801589, + -2026351522, + -2024892978, + -2023425963, + -2021950484, + -2020466546, + -2018974156, + -2017473321, + -2015964045, + -2014446336, + -2012920201, + -2011385644, + -2009842674, + -2008291295, + -2006731516, + -2005163342, + -2003586779, + -2002001835, + -2000408516, + -1998806829, + -1997196780, + -1995578377, + -1993951625, + -1992316532, + -1990673105, + -1989021350, + -1987361274, + -1985692885, + -1984016189, + -1982331193, + -1980637905, + -1978936331, + -1977226479, + -1975508355, + -1973781967, + -1972047323, + -1970304428, + -1968553292, + -1966793920, + -1965026321, + -1963250501, + -1961466469, + -1959674231, + -1957873796, + -1956065170, + -1954248361, + -1952423377, + -1950590226, + -1948748914, + -1946899451, + -1945041843, + -1943176098, + -1941302225, + -1939420231, + -1937530123, + -1935631910, + -1933725600, + -1931811201, + -1929888720, + -1927958166, + -1926019547, + -1924072871, + -1922118145, + -1920155379, + -1918184581, + -1916205758, + -1914218919, + -1912224073, + -1910221227, + -1908210390, + -1906191570, + -1904164776, + -1902130017, + -1900087301, + -1898036636, + -1895978031, + -1893911494, + -1891837035, + -1889754661, + -1887664383, + -1885566207, + -1883460144, + -1881346202, + -1879224389, + -1877094716, + -1874957189, + -1872811820, + -1870658615, + -1868497586, + -1866328740, + -1864152086, + -1861967634, + -1859775393, + -1857575372, + -1855367581, + -1853152028, + -1850928722, + -1848697674, + -1846458892, + -1844212386, + -1841958164, + -1839696238, + -1837426615, + -1835149306, + -1832864320, + -1830571667, + -1828271356, + -1825963397, + -1823647799, + -1821324572, + -1818993726, + -1816655271, + -1814309216, + -1811955572, + -1809594347, + -1807225553, + -1804849198, + -1802465294, + -1800073849, + -1797674873, + -1795268378, + -1792854372, + -1790432867, + -1788003871, + -1785567396, + -1783123452, + -1780672048, + -1778213194, + -1775746903, + -1773273182, + -1770792044, + -1768303498, + -1765807555, + -1763304224, + -1760793518, + -1758275445, + -1755750017, + -1753217244, + -1750677137, + -1748129707, + -1745574963, + -1743012918, + -1740443581, + -1737866963, + -1735283075, + -1732691928, + -1730093532, + -1727487899, + -1724875040, + -1722254965, + -1719627685, + -1716993211, + -1714351555, + -1711702727, + -1709046739, + -1706383601, + -1703713325, + -1701035922, + -1698351403, + -1695659779, + -1692961062, + -1690255263, + -1687542393, + -1684822463, + -1682095486, + -1679361471, + -1676620432, + -1673872378, + -1671117323, + -1668355276, + -1665586251, + -1662810258, + -1660027308, + -1657237415, + -1654440588, + -1651636841, + -1648826185, + -1646008631, + -1643184191, + -1640352877, + -1637514702, + -1634669676, + -1631817811, + -1628959121, + -1626093616, + -1623221309, + -1620342211, + -1617456335, + -1614563692, + -1611664296, + -1608758157, + -1605845289, + -1602925703, + -1599999411, + -1597066426, + -1594126760, + -1591180426, + -1588227435, + -1585267800, + -1582301533, + -1579328647, + -1576349155, + -1573363068, + -1570370399, + -1567371161, + -1564365367, + -1561353028, + -1558334157, + -1555308768, + -1552276872, + -1549238483, + -1546193612, + -1543142274, + -1540084480, + -1537020244, + -1533949577, + -1530872494, + -1527789007, + -1524699129, + -1521602872, + -1518500250, + -1515391276, + -1512275962, + -1509154322, + -1506026369, + -1502892116, + -1499751576, + -1496604762, + -1493451687, + -1490292364, + -1487126808, + -1483955030, + -1480777044, + -1477592864, + -1474402503, + -1471205974, + -1468003290, + -1464794466, + -1461579514, + -1458358447, + -1455131280, + -1451898025, + -1448658697, + -1445413309, + -1442161874, + -1438904406, + -1435640919, + -1432371426, + -1429095941, + -1425814478, + -1422527051, + -1419233672, + -1415934356, + -1412629117, + -1409317969, + -1406000925, + -1402678000, + -1399349206, + -1396014559, + -1392674072, + -1389327759, + -1385975633, + -1382617710, + -1379254004, + -1375884527, + -1372509294, + -1369128320, + -1365741619, + -1362349204, + -1358951090, + -1355547292, + -1352137822, + -1348722696, + -1345301929, + -1341875533, + -1338443524, + -1335005916, + -1331562723, + -1328113960, + -1324659641, + -1321199781, + -1317734393, + -1314263493, + -1310787095, + -1307305214, + -1303817864, + -1300325060, + -1296826816, + -1293323147, + -1289814068, + -1286299593, + -1282779738, + -1279254516, + -1275723942, + -1272188032, + -1268646800, + -1265100260, + -1261548429, + -1257991320, + -1254428948, + -1250861329, + -1247288478, + -1243710408, + -1240127136, + -1236538675, + -1232945043, + -1229346252, + -1225742318, + -1222133257, + -1218519084, + -1214899813, + -1211275460, + -1207646039, + -1204011567, + -1200372058, + -1196727527, + -1193077991, + -1189423463, + -1185763960, + -1182099496, + -1178430087, + -1174755748, + -1171076495, + -1167392344, + -1163703308, + -1160009405, + -1156310649, + -1152607055, + -1148898640, + -1145185419, + -1141467408, + -1137744621, + -1134017074, + -1130284784, + -1126547765, + -1122806034, + -1119059606, + -1115308496, + -1111552721, + -1107792296, + -1104027237, + -1100257559, + -1096483278, + -1092704411, + -1088920972, + -1085132978, + -1081340445, + -1077543388, +}; + +/* in Q1.31, generated from sin(i * 2 * pi / FFT_SIZE_MAX) */ +const int32_t multi_twiddle_imag_32[FFT_MULTI_TWIDDLE_SIZE] = { + 0, + -4392262, + -8784505, + -13176712, + -17568864, + -21960942, + -26352928, + -30744804, + -35136551, + -39528151, + -43919586, + -48310838, + -52701887, + -57092716, + -61483306, + -65873638, + -70263695, + -74653459, + -79042909, + -83432030, + -87820801, + -92209205, + -96597223, + -100984837, + -105372028, + -109758779, + -114145071, + -118530885, + -122916203, + -127301007, + -131685278, + -136068999, + -140452151, + -144834714, + -149216672, + -153598006, + -157978697, + -162358728, + -166738079, + -171116733, + -175494670, + -179871874, + -184248325, + -188624006, + -192998897, + -197372981, + -201746240, + -206118654, + -210490206, + -214860878, + -219230650, + -223599506, + -227967426, + -232334393, + -236700388, + -241065392, + -245429388, + -249792358, + -254154282, + -258515144, + -262874923, + -267233603, + -271591166, + -275947592, + -280302863, + -284656963, + -289009871, + -293361570, + -297712042, + -302061269, + -306409232, + -310755913, + -315101295, + -319445358, + -323788084, + -328129457, + -332469456, + -336808065, + -341145265, + -345481038, + -349815365, + -354148230, + -358479612, + -362809495, + -367137861, + -371464690, + -375789965, + -380113669, + -384435782, + -388756287, + -393075166, + -397392401, + -401707973, + -406021865, + -410334058, + -414644534, + -418953276, + -423260266, + -427565485, + -431868915, + -436170538, + -440470337, + -444768294, + -449064389, + -453358607, + -457650927, + -461941333, + -466229807, + -470516330, + -474800886, + -479083454, + -483364019, + -487642562, + -491919064, + -496193509, + -500465878, + -504736154, + -509004318, + -513270353, + -517534240, + -521795963, + -526055503, + -530312842, + -534567963, + -538820847, + -543071478, + -547319836, + -551565905, + -555809667, + -560051104, + -564290197, + -568526931, + -572761285, + -576993244, + -581222789, + -585449903, + -589674567, + -593896765, + -598116479, + -602333690, + -606548381, + -610760536, + -614970135, + -619177161, + -623381598, + -627583426, + -631782630, + -635979190, + -640173090, + -644364312, + -648552838, + -652738651, + -656921734, + -661102068, + -665279637, + -669454423, + -673626408, + -677795576, + -681961908, + -686125387, + -690285996, + -694443717, + -698598533, + -702750427, + -706899381, + -711045377, + -715188400, + -719328430, + -723465451, + -727599446, + -731730397, + -735858287, + -739983099, + -744104815, + -748223418, + -752338892, + -756451218, + -760560380, + -764666360, + -768769141, + -772868706, + -776965038, + -781058120, + -785147934, + -789234464, + -793317693, + -797397602, + -801474176, + -805547397, + -809617249, + -813683713, + -817746774, + -821806413, + -825862615, + -829915362, + -833964638, + -838010424, + -842052705, + -846091463, + -850126682, + -854158345, + -858186435, + -862210934, + -866231826, + -870249095, + -874262724, + -878272695, + -882278992, + -886281598, + -890280497, + -894275671, + -898267104, + -902254780, + -906238681, + -910218791, + -914195094, + -918167572, + -922136209, + -926100989, + -930061894, + -934018909, + -937972016, + -941921200, + -945866443, + -949807730, + -953745043, + -957678367, + -961607684, + -965532978, + -969454234, + -973371434, + -977284562, + -981193602, + -985098537, + -988999351, + -992896028, + -996788551, + -1000676905, + -1004561072, + -1008441038, + -1012316784, + -1016188296, + -1020055556, + -1023918550, + -1027777260, + -1031631671, + -1035481766, + -1039327529, + -1043168945, + -1047005996, + -1050838668, + -1054666944, + -1058490808, + -1062310244, + -1066125236, + -1069935768, + -1073741824, + -1077543388, + -1081340445, + -1085132978, + -1088920972, + -1092704411, + -1096483278, + -1100257559, + -1104027237, + -1107792296, + -1111552721, + -1115308496, + -1119059606, + -1122806034, + -1126547765, + -1130284784, + -1134017074, + -1137744621, + -1141467408, + -1145185419, + -1148898640, + -1152607055, + -1156310649, + -1160009405, + -1163703308, + -1167392344, + -1171076495, + -1174755748, + -1178430087, + -1182099496, + -1185763960, + -1189423463, + -1193077991, + -1196727527, + -1200372058, + -1204011567, + -1207646039, + -1211275460, + -1214899813, + -1218519084, + -1222133257, + -1225742318, + -1229346252, + -1232945043, + -1236538675, + -1240127136, + -1243710408, + -1247288478, + -1250861329, + -1254428948, + -1257991320, + -1261548429, + -1265100260, + -1268646800, + -1272188032, + -1275723942, + -1279254516, + -1282779738, + -1286299593, + -1289814068, + -1293323147, + -1296826816, + -1300325060, + -1303817864, + -1307305214, + -1310787095, + -1314263493, + -1317734393, + -1321199781, + -1324659641, + -1328113960, + -1331562723, + -1335005916, + -1338443524, + -1341875533, + -1345301929, + -1348722696, + -1352137822, + -1355547292, + -1358951090, + -1362349204, + -1365741619, + -1369128320, + -1372509294, + -1375884527, + -1379254004, + -1382617710, + -1385975633, + -1389327759, + -1392674072, + -1396014559, + -1399349206, + -1402678000, + -1406000925, + -1409317969, + -1412629117, + -1415934356, + -1419233672, + -1422527051, + -1425814478, + -1429095941, + -1432371426, + -1435640919, + -1438904406, + -1442161874, + -1445413309, + -1448658697, + -1451898025, + -1455131280, + -1458358447, + -1461579514, + -1464794466, + -1468003290, + -1471205974, + -1474402503, + -1477592864, + -1480777044, + -1483955030, + -1487126808, + -1490292364, + -1493451687, + -1496604762, + -1499751576, + -1502892116, + -1506026369, + -1509154322, + -1512275962, + -1515391276, + -1518500250, + -1521602872, + -1524699129, + -1527789007, + -1530872494, + -1533949577, + -1537020244, + -1540084480, + -1543142274, + -1546193612, + -1549238483, + -1552276872, + -1555308768, + -1558334157, + -1561353028, + -1564365367, + -1567371161, + -1570370399, + -1573363068, + -1576349155, + -1579328647, + -1582301533, + -1585267800, + -1588227435, + -1591180426, + -1594126760, + -1597066426, + -1599999411, + -1602925703, + -1605845289, + -1608758157, + -1611664296, + -1614563692, + -1617456335, + -1620342211, + -1623221309, + -1626093616, + -1628959121, + -1631817811, + -1634669676, + -1637514702, + -1640352877, + -1643184191, + -1646008631, + -1648826185, + -1651636841, + -1654440588, + -1657237415, + -1660027308, + -1662810258, + -1665586251, + -1668355276, + -1671117323, + -1673872378, + -1676620432, + -1679361471, + -1682095486, + -1684822463, + -1687542393, + -1690255263, + -1692961062, + -1695659779, + -1698351403, + -1701035922, + -1703713325, + -1706383601, + -1709046739, + -1711702727, + -1714351555, + -1716993211, + -1719627685, + -1722254965, + -1724875040, + -1727487899, + -1730093532, + -1732691928, + -1735283075, + -1737866963, + -1740443581, + -1743012918, + -1745574963, + -1748129707, + -1750677137, + -1753217244, + -1755750017, + -1758275445, + -1760793518, + -1763304224, + -1765807555, + -1768303498, + -1770792044, + -1773273182, + -1775746903, + -1778213194, + -1780672048, + -1783123452, + -1785567396, + -1788003871, + -1790432867, + -1792854372, + -1795268378, + -1797674873, + -1800073849, + -1802465294, + -1804849198, + -1807225553, + -1809594347, + -1811955572, + -1814309216, + -1816655271, + -1818993726, + -1821324572, + -1823647799, + -1825963397, + -1828271356, + -1830571667, + -1832864320, + -1835149306, + -1837426615, + -1839696238, + -1841958164, + -1844212386, + -1846458892, + -1848697674, + -1850928722, + -1853152028, + -1855367581, + -1857575372, + -1859775393, + -1861967634, + -1864152086, + -1866328740, + -1868497586, + -1870658615, + -1872811820, + -1874957189, + -1877094716, + -1879224389, + -1881346202, + -1883460144, + -1885566207, + -1887664383, + -1889754661, + -1891837035, + -1893911494, + -1895978031, + -1898036636, + -1900087301, + -1902130017, + -1904164776, + -1906191570, + -1908210390, + -1910221227, + -1912224073, + -1914218919, + -1916205758, + -1918184581, + -1920155379, + -1922118145, + -1924072871, + -1926019547, + -1927958166, + -1929888720, + -1931811201, + -1933725600, + -1935631910, + -1937530123, + -1939420231, + -1941302225, + -1943176098, + -1945041843, + -1946899451, + -1948748914, + -1950590226, + -1952423377, + -1954248361, + -1956065170, + -1957873796, + -1959674231, + -1961466469, + -1963250501, + -1965026321, + -1966793920, + -1968553292, + -1970304428, + -1972047323, + -1973781967, + -1975508355, + -1977226479, + -1978936331, + -1980637905, + -1982331193, + -1984016189, + -1985692885, + -1987361274, + -1989021350, + -1990673105, + -1992316532, + -1993951625, + -1995578377, + -1997196780, + -1998806829, + -2000408516, + -2002001835, + -2003586779, + -2005163342, + -2006731516, + -2008291295, + -2009842674, + -2011385644, + -2012920201, + -2014446336, + -2015964045, + -2017473321, + -2018974156, + -2020466546, + -2021950484, + -2023425963, + -2024892978, + -2026351522, + -2027801589, + -2029243173, + -2030676269, + -2032100869, + -2033516969, + -2034924562, + -2036323642, + -2037714204, + -2039096241, + -2040469748, + -2041834720, + -2043191150, + -2044539032, + -2045878362, + -2047209133, + -2048531340, + -2049844978, + -2051150040, + -2052446522, + -2053734418, + -2055013723, + -2056284431, + -2057546537, + -2058800036, + -2060044922, + -2061281190, + -2062508835, + -2063727853, + -2064938237, + -2066139983, + -2067333086, + -2068517540, + -2069693342, + -2070860485, + -2072018965, + -2073168777, + -2074309917, + -2075442379, + -2076566160, + -2077681253, + -2078787655, + -2079885360, + -2080974365, + -2082054665, + -2083126254, + -2084189130, + -2085243286, + -2086288720, + -2087325426, + -2088353400, + -2089372638, + -2090383135, + -2091384888, + -2092377892, + -2093362143, + -2094337637, + -2095304370, + -2096262337, + -2097211535, + -2098151960, + -2099083608, + -2100006474, + -2100920556, + -2101825849, + -2102722350, + -2103610054, + -2104488958, + -2105359059, + -2106220352, + -2107072834, + -2107916502, + -2108751352, + -2109577380, + -2110394584, + -2111202959, + -2112002502, + -2112793210, + -2113575080, + -2114348108, + -2115112291, + -2115867626, + -2116614110, + -2117351739, + -2118080511, + -2118800422, + -2119511470, + -2120213651, + -2120906963, + -2121591402, + -2122266967, + -2122933653, + -2123591458, + -2124240380, + -2124880416, + -2125511562, + -2126133817, + -2126747178, + -2127351642, + -2127947206, + -2128533869, + -2129111628, + -2129680480, + -2130240422, + -2130791454, + -2131333572, + -2131866773, + -2132391057, + -2132906420, + -2133412861, + -2133910377, + -2134398966, + -2134878626, + -2135349356, + -2135811153, + -2136264015, + -2136707940, + -2137142927, + -2137568974, + -2137986079, + -2138394240, + -2138793455, + -2139183723, + -2139565043, + -2139937412, + -2140300829, + -2140655293, + -2141000801, + -2141337354, + -2141664948, + -2141983583, + -2142293258, + -2142593971, + -2142885721, + -2143168506, + -2143442326, + -2143707180, + -2143963065, + -2144209982, + -2144447929, + -2144676905, + -2144896910, + -2145107942, + -2145310000, + -2145503083, + -2145687192, + -2145862324, + -2146028480, + -2146185658, + -2146333858, + -2146473080, + -2146603322, + -2146724584, + -2146836866, + -2146940167, + -2147034487, + -2147119825, + -2147196181, + -2147263555, + -2147321946, + -2147371355, + -2147411780, + -2147443222, + -2147465681, + -2147479156, + -2147483647, + -2147479156, + -2147465681, + -2147443222, + -2147411780, + -2147371355, + -2147321946, + -2147263555, + -2147196181, + -2147119825, + -2147034487, + -2146940167, + -2146836866, + -2146724584, + -2146603322, + -2146473080, + -2146333858, + -2146185658, + -2146028480, + -2145862324, + -2145687192, + -2145503083, + -2145310000, + -2145107942, + -2144896910, + -2144676905, + -2144447929, + -2144209982, + -2143963065, + -2143707180, + -2143442326, + -2143168506, + -2142885721, + -2142593971, + -2142293258, + -2141983583, + -2141664948, + -2141337354, + -2141000801, + -2140655293, + -2140300829, + -2139937412, + -2139565043, + -2139183723, + -2138793455, + -2138394240, + -2137986079, + -2137568974, + -2137142927, + -2136707940, + -2136264015, + -2135811153, + -2135349356, + -2134878626, + -2134398966, + -2133910377, + -2133412861, + -2132906420, + -2132391057, + -2131866773, + -2131333572, + -2130791454, + -2130240422, + -2129680480, + -2129111628, + -2128533869, + -2127947206, + -2127351642, + -2126747178, + -2126133817, + -2125511562, + -2124880416, + -2124240380, + -2123591458, + -2122933653, + -2122266967, + -2121591402, + -2120906963, + -2120213651, + -2119511470, + -2118800422, + -2118080511, + -2117351739, + -2116614110, + -2115867626, + -2115112291, + -2114348108, + -2113575080, + -2112793210, + -2112002502, + -2111202959, + -2110394584, + -2109577380, + -2108751352, + -2107916502, + -2107072834, + -2106220352, + -2105359059, + -2104488958, + -2103610054, + -2102722350, + -2101825849, + -2100920556, + -2100006474, + -2099083608, + -2098151960, + -2097211535, + -2096262337, + -2095304370, + -2094337637, + -2093362143, + -2092377892, + -2091384888, + -2090383135, + -2089372638, + -2088353400, + -2087325426, + -2086288720, + -2085243286, + -2084189130, + -2083126254, + -2082054665, + -2080974365, + -2079885360, + -2078787655, + -2077681253, + -2076566160, + -2075442379, + -2074309917, + -2073168777, + -2072018965, + -2070860485, + -2069693342, + -2068517540, + -2067333086, + -2066139983, + -2064938237, + -2063727853, + -2062508835, + -2061281190, + -2060044922, + -2058800036, + -2057546537, + -2056284431, + -2055013723, + -2053734418, + -2052446522, + -2051150040, + -2049844978, + -2048531340, + -2047209133, + -2045878362, + -2044539032, + -2043191150, + -2041834720, + -2040469748, + -2039096241, + -2037714204, + -2036323642, + -2034924562, + -2033516969, + -2032100869, + -2030676269, + -2029243173, + -2027801589, + -2026351522, + -2024892978, + -2023425963, + -2021950484, + -2020466546, + -2018974156, + -2017473321, + -2015964045, + -2014446336, + -2012920201, + -2011385644, + -2009842674, + -2008291295, + -2006731516, + -2005163342, + -2003586779, + -2002001835, + -2000408516, + -1998806829, + -1997196780, + -1995578377, + -1993951625, + -1992316532, + -1990673105, + -1989021350, + -1987361274, + -1985692885, + -1984016189, + -1982331193, + -1980637905, + -1978936331, + -1977226479, + -1975508355, + -1973781967, + -1972047323, + -1970304428, + -1968553292, + -1966793920, + -1965026321, + -1963250501, + -1961466469, + -1959674231, + -1957873796, + -1956065170, + -1954248361, + -1952423377, + -1950590226, + -1948748914, + -1946899451, + -1945041843, + -1943176098, + -1941302225, + -1939420231, + -1937530123, + -1935631910, + -1933725600, + -1931811201, + -1929888720, + -1927958166, + -1926019547, + -1924072871, + -1922118145, + -1920155379, + -1918184581, + -1916205758, + -1914218919, + -1912224073, + -1910221227, + -1908210390, + -1906191570, + -1904164776, + -1902130017, + -1900087301, + -1898036636, + -1895978031, + -1893911494, + -1891837035, + -1889754661, + -1887664383, + -1885566207, + -1883460144, + -1881346202, + -1879224389, + -1877094716, + -1874957189, + -1872811820, + -1870658615, + -1868497586, + -1866328740, + -1864152086, + -1861967634, + -1859775393, + -1857575372, + -1855367581, + -1853152028, + -1850928722, + -1848697674, + -1846458892, + -1844212386, + -1841958164, + -1839696238, + -1837426615, + -1835149306, + -1832864320, + -1830571667, + -1828271356, + -1825963397, + -1823647799, + -1821324572, + -1818993726, + -1816655271, + -1814309216, + -1811955572, + -1809594347, + -1807225553, + -1804849198, + -1802465294, + -1800073849, + -1797674873, + -1795268378, + -1792854372, + -1790432867, + -1788003871, + -1785567396, + -1783123452, + -1780672048, + -1778213194, + -1775746903, + -1773273182, + -1770792044, + -1768303498, + -1765807555, + -1763304224, + -1760793518, + -1758275445, + -1755750017, + -1753217244, + -1750677137, + -1748129707, + -1745574963, + -1743012918, + -1740443581, + -1737866963, + -1735283075, + -1732691928, + -1730093532, + -1727487899, + -1724875040, + -1722254965, + -1719627685, + -1716993211, + -1714351555, + -1711702727, + -1709046739, + -1706383601, + -1703713325, + -1701035922, + -1698351403, + -1695659779, + -1692961062, + -1690255263, + -1687542393, + -1684822463, + -1682095486, + -1679361471, + -1676620432, + -1673872378, + -1671117323, + -1668355276, + -1665586251, + -1662810258, + -1660027308, + -1657237415, + -1654440588, + -1651636841, + -1648826185, + -1646008631, + -1643184191, + -1640352877, + -1637514702, + -1634669676, + -1631817811, + -1628959121, + -1626093616, + -1623221309, + -1620342211, + -1617456335, + -1614563692, + -1611664296, + -1608758157, + -1605845289, + -1602925703, + -1599999411, + -1597066426, + -1594126760, + -1591180426, + -1588227435, + -1585267800, + -1582301533, + -1579328647, + -1576349155, + -1573363068, + -1570370399, + -1567371161, + -1564365367, + -1561353028, + -1558334157, + -1555308768, + -1552276872, + -1549238483, + -1546193612, + -1543142274, + -1540084480, + -1537020244, + -1533949577, + -1530872494, + -1527789007, + -1524699129, + -1521602872, + -1518500250, + -1515391276, + -1512275962, + -1509154322, + -1506026369, + -1502892116, + -1499751576, + -1496604762, + -1493451687, + -1490292364, + -1487126808, + -1483955030, + -1480777044, + -1477592864, + -1474402503, + -1471205974, + -1468003290, + -1464794466, + -1461579514, + -1458358447, + -1455131280, + -1451898025, + -1448658697, + -1445413309, + -1442161874, + -1438904406, + -1435640919, + -1432371426, + -1429095941, + -1425814478, + -1422527051, + -1419233672, + -1415934356, + -1412629117, + -1409317969, + -1406000925, + -1402678000, + -1399349206, + -1396014559, + -1392674072, + -1389327759, + -1385975633, + -1382617710, + -1379254004, + -1375884527, + -1372509294, + -1369128320, + -1365741619, + -1362349204, + -1358951090, + -1355547292, + -1352137822, + -1348722696, + -1345301929, + -1341875533, + -1338443524, + -1335005916, + -1331562723, + -1328113960, + -1324659641, + -1321199781, + -1317734393, + -1314263493, + -1310787095, + -1307305214, + -1303817864, + -1300325060, + -1296826816, + -1293323147, + -1289814068, + -1286299593, + -1282779738, + -1279254516, + -1275723942, + -1272188032, + -1268646800, + -1265100260, + -1261548429, + -1257991320, + -1254428948, + -1250861329, + -1247288478, + -1243710408, + -1240127136, + -1236538675, + -1232945043, + -1229346252, + -1225742318, + -1222133257, + -1218519084, + -1214899813, + -1211275460, + -1207646039, + -1204011567, + -1200372058, + -1196727527, + -1193077991, + -1189423463, + -1185763960, + -1182099496, + -1178430087, + -1174755748, + -1171076495, + -1167392344, + -1163703308, + -1160009405, + -1156310649, + -1152607055, + -1148898640, + -1145185419, + -1141467408, + -1137744621, + -1134017074, + -1130284784, + -1126547765, + -1122806034, + -1119059606, + -1115308496, + -1111552721, + -1107792296, + -1104027237, + -1100257559, + -1096483278, + -1092704411, + -1088920972, + -1085132978, + -1081340445, + -1077543388, + -1073741824, + -1069935768, + -1066125236, + -1062310244, + -1058490808, + -1054666944, + -1050838668, + -1047005996, + -1043168945, + -1039327529, + -1035481766, + -1031631671, + -1027777260, + -1023918550, + -1020055556, + -1016188296, + -1012316784, + -1008441038, + -1004561072, + -1000676905, + -996788551, + -992896028, + -988999351, + -985098537, + -981193602, + -977284562, + -973371434, + -969454234, + -965532978, + -961607684, + -957678367, + -953745043, + -949807730, + -945866443, + -941921200, + -937972016, + -934018909, + -930061894, + -926100989, + -922136209, + -918167572, + -914195094, + -910218791, + -906238681, + -902254780, + -898267104, + -894275671, + -890280497, + -886281598, + -882278992, + -878272695, + -874262724, + -870249095, + -866231826, + -862210934, + -858186435, + -854158345, + -850126682, + -846091463, + -842052705, + -838010424, + -833964638, + -829915362, + -825862615, + -821806413, + -817746774, + -813683713, + -809617249, + -805547397, + -801474176, + -797397602, + -793317693, + -789234464, + -785147934, + -781058120, + -776965038, + -772868706, + -768769141, + -764666360, + -760560380, + -756451218, + -752338892, + -748223418, + -744104815, + -739983099, + -735858287, + -731730397, + -727599446, + -723465451, + -719328430, + -715188400, + -711045377, + -706899381, + -702750427, + -698598533, + -694443717, + -690285996, + -686125387, + -681961908, + -677795576, + -673626408, + -669454423, + -665279637, + -661102068, + -656921734, + -652738651, + -648552838, + -644364312, + -640173090, + -635979190, + -631782630, + -627583426, + -623381598, + -619177161, + -614970135, + -610760536, + -606548381, + -602333690, + -598116479, + -593896765, + -589674567, + -585449903, + -581222789, + -576993244, + -572761285, + -568526931, + -564290197, + -560051104, + -555809667, + -551565905, + -547319836, + -543071478, + -538820847, + -534567963, + -530312842, + -526055503, + -521795963, + -517534240, + -513270353, + -509004318, + -504736154, + -500465878, + -496193509, + -491919064, + -487642562, + -483364019, + -479083454, + -474800886, + -470516330, + -466229807, + -461941333, + -457650927, + -453358607, + -449064389, + -444768294, + -440470337, + -436170538, + -431868915, + -427565485, + -423260266, + -418953276, + -414644534, + -410334058, + -406021865, + -401707973, + -397392401, + -393075166, + -388756287, + -384435782, + -380113669, + -375789965, + -371464690, + -367137861, + -362809495, + -358479612, + -354148230, + -349815365, + -345481038, + -341145265, + -336808065, + -332469456, + -328129457, + -323788084, + -319445358, + -315101295, + -310755913, + -306409232, + -302061269, + -297712042, + -293361570, + -289009871, + -284656963, + -280302863, + -275947592, + -271591166, + -267233603, + -262874923, + -258515144, + -254154282, + -249792358, + -245429388, + -241065392, + -236700388, + -232334393, + -227967426, + -223599506, + -219230650, + -214860878, + -210490206, + -206118654, + -201746240, + -197372981, + -192998897, + -188624006, + -184248325, + -179871874, + -175494670, + -171116733, + -166738079, + -162358728, + -157978697, + -153598006, + -149216672, + -144834714, + -140452151, + -136068999, + -131685278, + -127301007, + -122916203, + -118530885, + -114145071, + -109758779, + -105372028, + -100984837, + -96597223, + -92209205, + -87820801, + -83432030, + -79042909, + -74653459, + -70263695, + -65873638, + -61483306, + -57092716, + -52701887, + -48310838, + -43919586, + -39528151, + -35136551, + -30744804, + -26352928, + -21960942, + -17568864, + -13176712, + -8784505, + -4392262, + 0, + 4392262, + 8784505, + 13176712, + 17568864, + 21960942, + 26352928, + 30744804, + 35136551, + 39528151, + 43919586, + 48310838, + 52701887, + 57092716, + 61483306, + 65873638, + 70263695, + 74653459, + 79042909, + 83432030, + 87820801, + 92209205, + 96597223, + 100984837, + 105372028, + 109758779, + 114145071, + 118530885, + 122916203, + 127301007, + 131685278, + 136068999, + 140452151, + 144834714, + 149216672, + 153598006, + 157978697, + 162358728, + 166738079, + 171116733, + 175494670, + 179871874, + 184248325, + 188624006, + 192998897, + 197372981, + 201746240, + 206118654, + 210490206, + 214860878, + 219230650, + 223599506, + 227967426, + 232334393, + 236700388, + 241065392, + 245429388, + 249792358, + 254154282, + 258515144, + 262874923, + 267233603, + 271591166, + 275947592, + 280302863, + 284656963, + 289009871, + 293361570, + 297712042, + 302061269, + 306409232, + 310755913, + 315101295, + 319445358, + 323788084, + 328129457, + 332469456, + 336808065, + 341145265, + 345481038, + 349815365, + 354148230, + 358479612, + 362809495, + 367137861, + 371464690, + 375789965, + 380113669, + 384435782, + 388756287, + 393075166, + 397392401, + 401707973, + 406021865, + 410334058, + 414644534, + 418953276, + 423260266, + 427565485, + 431868915, + 436170538, + 440470337, + 444768294, + 449064389, + 453358607, + 457650927, + 461941333, + 466229807, + 470516330, + 474800886, + 479083454, + 483364019, + 487642562, + 491919064, + 496193509, + 500465878, + 504736154, + 509004318, + 513270353, + 517534240, + 521795963, + 526055503, + 530312842, + 534567963, + 538820847, + 543071478, + 547319836, + 551565905, + 555809667, + 560051104, + 564290197, + 568526931, + 572761285, + 576993244, + 581222789, + 585449903, + 589674567, + 593896765, + 598116479, + 602333690, + 606548381, + 610760536, + 614970135, + 619177161, + 623381598, + 627583426, + 631782630, + 635979190, + 640173090, + 644364312, + 648552838, + 652738651, + 656921734, + 661102068, + 665279637, + 669454423, + 673626408, + 677795576, + 681961908, + 686125387, + 690285996, + 694443717, + 698598533, + 702750427, + 706899381, + 711045377, + 715188400, + 719328430, + 723465451, + 727599446, + 731730397, + 735858287, + 739983099, + 744104815, + 748223418, + 752338892, + 756451218, + 760560380, + 764666360, + 768769141, + 772868706, + 776965038, + 781058120, + 785147934, + 789234464, + 793317693, + 797397602, + 801474176, + 805547397, + 809617249, + 813683713, + 817746774, + 821806413, + 825862615, + 829915362, + 833964638, + 838010424, + 842052705, + 846091463, + 850126682, + 854158345, + 858186435, + 862210934, + 866231826, + 870249095, + 874262724, + 878272695, + 882278992, + 886281598, + 890280497, + 894275671, + 898267104, + 902254780, + 906238681, + 910218791, + 914195094, + 918167572, + 922136209, + 926100989, + 930061894, + 934018909, + 937972016, + 941921200, + 945866443, + 949807730, + 953745043, + 957678367, + 961607684, + 965532978, + 969454234, + 973371434, + 977284562, + 981193602, + 985098537, + 988999351, + 992896028, + 996788551, + 1000676905, + 1004561072, + 1008441038, + 1012316784, + 1016188296, + 1020055556, + 1023918550, + 1027777260, + 1031631671, + 1035481766, + 1039327529, + 1043168945, + 1047005996, + 1050838668, + 1054666944, + 1058490808, + 1062310244, + 1066125236, + 1069935768, + 1073741824, + 1077543388, + 1081340445, + 1085132978, + 1088920972, + 1092704411, + 1096483278, + 1100257559, + 1104027237, + 1107792296, + 1111552721, + 1115308496, + 1119059606, + 1122806034, + 1126547765, + 1130284784, + 1134017074, + 1137744621, + 1141467408, + 1145185419, + 1148898640, + 1152607055, + 1156310649, + 1160009405, + 1163703308, + 1167392344, + 1171076495, + 1174755748, + 1178430087, + 1182099496, + 1185763960, + 1189423463, + 1193077991, + 1196727527, + 1200372058, + 1204011567, + 1207646039, + 1211275460, + 1214899813, + 1218519084, + 1222133257, + 1225742318, + 1229346252, + 1232945043, + 1236538675, + 1240127136, + 1243710408, + 1247288478, + 1250861329, + 1254428948, + 1257991320, + 1261548429, + 1265100260, + 1268646800, + 1272188032, + 1275723942, + 1279254516, + 1282779738, + 1286299593, + 1289814068, + 1293323147, + 1296826816, + 1300325060, + 1303817864, + 1307305214, + 1310787095, + 1314263493, + 1317734393, + 1321199781, + 1324659641, + 1328113960, + 1331562723, + 1335005916, + 1338443524, + 1341875533, + 1345301929, + 1348722696, + 1352137822, + 1355547292, + 1358951090, + 1362349204, + 1365741619, + 1369128320, + 1372509294, + 1375884527, + 1379254004, + 1382617710, + 1385975633, + 1389327759, + 1392674072, + 1396014559, + 1399349206, + 1402678000, + 1406000925, + 1409317969, + 1412629117, + 1415934356, + 1419233672, + 1422527051, + 1425814478, + 1429095941, + 1432371426, + 1435640919, + 1438904406, + 1442161874, + 1445413309, + 1448658697, + 1451898025, + 1455131280, + 1458358447, + 1461579514, + 1464794466, + 1468003290, + 1471205974, + 1474402503, + 1477592864, + 1480777044, + 1483955030, + 1487126808, + 1490292364, + 1493451687, + 1496604762, + 1499751576, + 1502892116, + 1506026369, + 1509154322, + 1512275962, + 1515391276, + 1518500250, + 1521602872, + 1524699129, + 1527789007, + 1530872494, + 1533949577, + 1537020244, + 1540084480, + 1543142274, + 1546193612, + 1549238483, + 1552276872, + 1555308768, + 1558334157, + 1561353028, + 1564365367, + 1567371161, + 1570370399, + 1573363068, + 1576349155, + 1579328647, + 1582301533, + 1585267800, + 1588227435, + 1591180426, + 1594126760, + 1597066426, + 1599999411, + 1602925703, + 1605845289, + 1608758157, + 1611664296, + 1614563692, + 1617456335, + 1620342211, + 1623221309, + 1626093616, + 1628959121, + 1631817811, + 1634669676, + 1637514702, + 1640352877, + 1643184191, + 1646008631, + 1648826185, + 1651636841, + 1654440588, + 1657237415, + 1660027308, + 1662810258, + 1665586251, + 1668355276, + 1671117323, + 1673872378, + 1676620432, + 1679361471, + 1682095486, + 1684822463, + 1687542393, + 1690255263, + 1692961062, + 1695659779, + 1698351403, + 1701035922, + 1703713325, + 1706383601, + 1709046739, + 1711702727, + 1714351555, + 1716993211, + 1719627685, + 1722254965, + 1724875040, + 1727487899, + 1730093532, + 1732691928, + 1735283075, + 1737866963, + 1740443581, + 1743012918, + 1745574963, + 1748129707, + 1750677137, + 1753217244, + 1755750017, + 1758275445, + 1760793518, + 1763304224, + 1765807555, + 1768303498, + 1770792044, + 1773273182, + 1775746903, + 1778213194, + 1780672048, + 1783123452, + 1785567396, + 1788003871, + 1790432867, + 1792854372, + 1795268378, + 1797674873, + 1800073849, + 1802465294, + 1804849198, + 1807225553, + 1809594347, + 1811955572, + 1814309216, + 1816655271, + 1818993726, + 1821324572, + 1823647799, + 1825963397, + 1828271356, + 1830571667, + 1832864320, + 1835149306, + 1837426615, + 1839696238, + 1841958164, + 1844212386, + 1846458892, + 1848697674, + 1850928722, + 1853152028, + 1855367581, + 1857575372, +}; + +#endif diff --git a/src/include/sof/audio/coefficients/fft/twiddle_32.h b/src/include/sof/audio/coefficients/fft/twiddle_32.h new file mode 100644 index 000000000000..2d73dda1d0f4 --- /dev/null +++ b/src/include/sof/audio/coefficients/fft/twiddle_32.h @@ -0,0 +1,2072 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +/* Twiddle factors in Q1.31 format */ + +#ifndef __INCLUDE_TWIDDLE_32_H__ +#define __INCLUDE_TWIDDLE_32_H__ + +#include <stdint.h> + +#define FFT_SIZE_MAX 1024 + +/* in Q1.31, generated from cos(i * 2 * pi / FFT_SIZE_MAX) */ +const int32_t twiddle_real_32[FFT_SIZE_MAX] = { + 2147483647, + 2147443222, + 2147321946, + 2147119825, + 2146836866, + 2146473080, + 2146028480, + 2145503083, + 2144896910, + 2144209982, + 2143442326, + 2142593971, + 2141664948, + 2140655293, + 2139565043, + 2138394240, + 2137142927, + 2135811153, + 2134398966, + 2132906420, + 2131333572, + 2129680480, + 2127947206, + 2126133817, + 2124240380, + 2122266967, + 2120213651, + 2118080511, + 2115867626, + 2113575080, + 2111202959, + 2108751352, + 2106220352, + 2103610054, + 2100920556, + 2098151960, + 2095304370, + 2092377892, + 2089372638, + 2086288720, + 2083126254, + 2079885360, + 2076566160, + 2073168777, + 2069693342, + 2066139983, + 2062508835, + 2058800036, + 2055013723, + 2051150040, + 2047209133, + 2043191150, + 2039096241, + 2034924562, + 2030676269, + 2026351522, + 2021950484, + 2017473321, + 2012920201, + 2008291295, + 2003586779, + 1998806829, + 1993951625, + 1989021350, + 1984016189, + 1978936331, + 1973781967, + 1968553292, + 1963250501, + 1957873796, + 1952423377, + 1946899451, + 1941302225, + 1935631910, + 1929888720, + 1924072871, + 1918184581, + 1912224073, + 1906191570, + 1900087301, + 1893911494, + 1887664383, + 1881346202, + 1874957189, + 1868497586, + 1861967634, + 1855367581, + 1848697674, + 1841958164, + 1835149306, + 1828271356, + 1821324572, + 1814309216, + 1807225553, + 1800073849, + 1792854372, + 1785567396, + 1778213194, + 1770792044, + 1763304224, + 1755750017, + 1748129707, + 1740443581, + 1732691928, + 1724875040, + 1716993211, + 1709046739, + 1701035922, + 1692961062, + 1684822463, + 1676620432, + 1668355276, + 1660027308, + 1651636841, + 1643184191, + 1634669676, + 1626093616, + 1617456335, + 1608758157, + 1599999411, + 1591180426, + 1582301533, + 1573363068, + 1564365367, + 1555308768, + 1546193612, + 1537020244, + 1527789007, + 1518500250, + 1509154322, + 1499751576, + 1490292364, + 1480777044, + 1471205974, + 1461579514, + 1451898025, + 1442161874, + 1432371426, + 1422527051, + 1412629117, + 1402678000, + 1392674072, + 1382617710, + 1372509294, + 1362349204, + 1352137822, + 1341875533, + 1331562723, + 1321199781, + 1310787095, + 1300325060, + 1289814068, + 1279254516, + 1268646800, + 1257991320, + 1247288478, + 1236538675, + 1225742318, + 1214899813, + 1204011567, + 1193077991, + 1182099496, + 1171076495, + 1160009405, + 1148898640, + 1137744621, + 1126547765, + 1115308496, + 1104027237, + 1092704411, + 1081340445, + 1069935768, + 1058490808, + 1047005996, + 1035481766, + 1023918550, + 1012316784, + 1000676905, + 988999351, + 977284562, + 965532978, + 953745043, + 941921200, + 930061894, + 918167572, + 906238681, + 894275671, + 882278992, + 870249095, + 858186435, + 846091463, + 833964638, + 821806413, + 809617249, + 797397602, + 785147934, + 772868706, + 760560380, + 748223418, + 735858287, + 723465451, + 711045377, + 698598533, + 686125387, + 673626408, + 661102068, + 648552838, + 635979190, + 623381598, + 610760536, + 598116479, + 585449903, + 572761285, + 560051104, + 547319836, + 534567963, + 521795963, + 509004318, + 496193509, + 483364019, + 470516330, + 457650927, + 444768294, + 431868915, + 418953276, + 406021865, + 393075166, + 380113669, + 367137861, + 354148230, + 341145265, + 328129457, + 315101295, + 302061269, + 289009871, + 275947592, + 262874923, + 249792358, + 236700388, + 223599506, + 210490206, + 197372981, + 184248325, + 171116733, + 157978697, + 144834714, + 131685278, + 118530885, + 105372028, + 92209205, + 79042909, + 65873638, + 52701887, + 39528151, + 26352928, + 13176712, + 0, + -13176712, + -26352928, + -39528151, + -52701887, + -65873638, + -79042909, + -92209205, + -105372028, + -118530885, + -131685278, + -144834714, + -157978697, + -171116733, + -184248325, + -197372981, + -210490206, + -223599506, + -236700388, + -249792358, + -262874923, + -275947592, + -289009871, + -302061269, + -315101295, + -328129457, + -341145265, + -354148230, + -367137861, + -380113669, + -393075166, + -406021865, + -418953276, + -431868915, + -444768294, + -457650927, + -470516330, + -483364019, + -496193509, + -509004318, + -521795963, + -534567963, + -547319836, + -560051104, + -572761285, + -585449903, + -598116479, + -610760536, + -623381598, + -635979190, + -648552838, + -661102068, + -673626408, + -686125387, + -698598533, + -711045377, + -723465451, + -735858287, + -748223418, + -760560380, + -772868706, + -785147934, + -797397602, + -809617249, + -821806413, + -833964638, + -846091463, + -858186435, + -870249095, + -882278992, + -894275671, + -906238681, + -918167572, + -930061894, + -941921200, + -953745043, + -965532978, + -977284562, + -988999351, + -1000676905, + -1012316784, + -1023918550, + -1035481766, + -1047005996, + -1058490808, + -1069935768, + -1081340445, + -1092704411, + -1104027237, + -1115308496, + -1126547765, + -1137744621, + -1148898640, + -1160009405, + -1171076495, + -1182099496, + -1193077991, + -1204011567, + -1214899813, + -1225742318, + -1236538675, + -1247288478, + -1257991320, + -1268646800, + -1279254516, + -1289814068, + -1300325060, + -1310787095, + -1321199781, + -1331562723, + -1341875533, + -1352137822, + -1362349204, + -1372509294, + -1382617710, + -1392674072, + -1402678000, + -1412629117, + -1422527051, + -1432371426, + -1442161874, + -1451898025, + -1461579514, + -1471205974, + -1480777044, + -1490292364, + -1499751576, + -1509154322, + -1518500250, + -1527789007, + -1537020244, + -1546193612, + -1555308768, + -1564365367, + -1573363068, + -1582301533, + -1591180426, + -1599999411, + -1608758157, + -1617456335, + -1626093616, + -1634669676, + -1643184191, + -1651636841, + -1660027308, + -1668355276, + -1676620432, + -1684822463, + -1692961062, + -1701035922, + -1709046739, + -1716993211, + -1724875040, + -1732691928, + -1740443581, + -1748129707, + -1755750017, + -1763304224, + -1770792044, + -1778213194, + -1785567396, + -1792854372, + -1800073849, + -1807225553, + -1814309216, + -1821324572, + -1828271356, + -1835149306, + -1841958164, + -1848697674, + -1855367581, + -1861967634, + -1868497586, + -1874957189, + -1881346202, + -1887664383, + -1893911494, + -1900087301, + -1906191570, + -1912224073, + -1918184581, + -1924072871, + -1929888720, + -1935631910, + -1941302225, + -1946899451, + -1952423377, + -1957873796, + -1963250501, + -1968553292, + -1973781967, + -1978936331, + -1984016189, + -1989021350, + -1993951625, + -1998806829, + -2003586779, + -2008291295, + -2012920201, + -2017473321, + -2021950484, + -2026351522, + -2030676269, + -2034924562, + -2039096241, + -2043191150, + -2047209133, + -2051150040, + -2055013723, + -2058800036, + -2062508835, + -2066139983, + -2069693342, + -2073168777, + -2076566160, + -2079885360, + -2083126254, + -2086288720, + -2089372638, + -2092377892, + -2095304370, + -2098151960, + -2100920556, + -2103610054, + -2106220352, + -2108751352, + -2111202959, + -2113575080, + -2115867626, + -2118080511, + -2120213651, + -2122266967, + -2124240380, + -2126133817, + -2127947206, + -2129680480, + -2131333572, + -2132906420, + -2134398966, + -2135811153, + -2137142927, + -2138394240, + -2139565043, + -2140655293, + -2141664948, + -2142593971, + -2143442326, + -2144209982, + -2144896910, + -2145503083, + -2146028480, + -2146473080, + -2146836866, + -2147119825, + -2147321946, + -2147443222, + -2147483647, + -2147443222, + -2147321946, + -2147119825, + -2146836866, + -2146473080, + -2146028480, + -2145503083, + -2144896910, + -2144209982, + -2143442326, + -2142593971, + -2141664948, + -2140655293, + -2139565043, + -2138394240, + -2137142927, + -2135811153, + -2134398966, + -2132906420, + -2131333572, + -2129680480, + -2127947206, + -2126133817, + -2124240380, + -2122266967, + -2120213651, + -2118080511, + -2115867626, + -2113575080, + -2111202959, + -2108751352, + -2106220352, + -2103610054, + -2100920556, + -2098151960, + -2095304370, + -2092377892, + -2089372638, + -2086288720, + -2083126254, + -2079885360, + -2076566160, + -2073168777, + -2069693342, + -2066139983, + -2062508835, + -2058800036, + -2055013723, + -2051150040, + -2047209133, + -2043191150, + -2039096241, + -2034924562, + -2030676269, + -2026351522, + -2021950484, + -2017473321, + -2012920201, + -2008291295, + -2003586779, + -1998806829, + -1993951625, + -1989021350, + -1984016189, + -1978936331, + -1973781967, + -1968553292, + -1963250501, + -1957873796, + -1952423377, + -1946899451, + -1941302225, + -1935631910, + -1929888720, + -1924072871, + -1918184581, + -1912224073, + -1906191570, + -1900087301, + -1893911494, + -1887664383, + -1881346202, + -1874957189, + -1868497586, + -1861967634, + -1855367581, + -1848697674, + -1841958164, + -1835149306, + -1828271356, + -1821324572, + -1814309216, + -1807225553, + -1800073849, + -1792854372, + -1785567396, + -1778213194, + -1770792044, + -1763304224, + -1755750017, + -1748129707, + -1740443581, + -1732691928, + -1724875040, + -1716993211, + -1709046739, + -1701035922, + -1692961062, + -1684822463, + -1676620432, + -1668355276, + -1660027308, + -1651636841, + -1643184191, + -1634669676, + -1626093616, + -1617456335, + -1608758157, + -1599999411, + -1591180426, + -1582301533, + -1573363068, + -1564365367, + -1555308768, + -1546193612, + -1537020244, + -1527789007, + -1518500250, + -1509154322, + -1499751576, + -1490292364, + -1480777044, + -1471205974, + -1461579514, + -1451898025, + -1442161874, + -1432371426, + -1422527051, + -1412629117, + -1402678000, + -1392674072, + -1382617710, + -1372509294, + -1362349204, + -1352137822, + -1341875533, + -1331562723, + -1321199781, + -1310787095, + -1300325060, + -1289814068, + -1279254516, + -1268646800, + -1257991320, + -1247288478, + -1236538675, + -1225742318, + -1214899813, + -1204011567, + -1193077991, + -1182099496, + -1171076495, + -1160009405, + -1148898640, + -1137744621, + -1126547765, + -1115308496, + -1104027237, + -1092704411, + -1081340445, + -1069935768, + -1058490808, + -1047005996, + -1035481766, + -1023918550, + -1012316784, + -1000676905, + -988999351, + -977284562, + -965532978, + -953745043, + -941921200, + -930061894, + -918167572, + -906238681, + -894275671, + -882278992, + -870249095, + -858186435, + -846091463, + -833964638, + -821806413, + -809617249, + -797397602, + -785147934, + -772868706, + -760560380, + -748223418, + -735858287, + -723465451, + -711045377, + -698598533, + -686125387, + -673626408, + -661102068, + -648552838, + -635979190, + -623381598, + -610760536, + -598116479, + -585449903, + -572761285, + -560051104, + -547319836, + -534567963, + -521795963, + -509004318, + -496193509, + -483364019, + -470516330, + -457650927, + -444768294, + -431868915, + -418953276, + -406021865, + -393075166, + -380113669, + -367137861, + -354148230, + -341145265, + -328129457, + -315101295, + -302061269, + -289009871, + -275947592, + -262874923, + -249792358, + -236700388, + -223599506, + -210490206, + -197372981, + -184248325, + -171116733, + -157978697, + -144834714, + -131685278, + -118530885, + -105372028, + -92209205, + -79042909, + -65873638, + -52701887, + -39528151, + -26352928, + -13176712, + 0, + 13176712, + 26352928, + 39528151, + 52701887, + 65873638, + 79042909, + 92209205, + 105372028, + 118530885, + 131685278, + 144834714, + 157978697, + 171116733, + 184248325, + 197372981, + 210490206, + 223599506, + 236700388, + 249792358, + 262874923, + 275947592, + 289009871, + 302061269, + 315101295, + 328129457, + 341145265, + 354148230, + 367137861, + 380113669, + 393075166, + 406021865, + 418953276, + 431868915, + 444768294, + 457650927, + 470516330, + 483364019, + 496193509, + 509004318, + 521795963, + 534567963, + 547319836, + 560051104, + 572761285, + 585449903, + 598116479, + 610760536, + 623381598, + 635979190, + 648552838, + 661102068, + 673626408, + 686125387, + 698598533, + 711045377, + 723465451, + 735858287, + 748223418, + 760560380, + 772868706, + 785147934, + 797397602, + 809617249, + 821806413, + 833964638, + 846091463, + 858186435, + 870249095, + 882278992, + 894275671, + 906238681, + 918167572, + 930061894, + 941921200, + 953745043, + 965532978, + 977284562, + 988999351, + 1000676905, + 1012316784, + 1023918550, + 1035481766, + 1047005996, + 1058490808, + 1069935768, + 1081340445, + 1092704411, + 1104027237, + 1115308496, + 1126547765, + 1137744621, + 1148898640, + 1160009405, + 1171076495, + 1182099496, + 1193077991, + 1204011567, + 1214899813, + 1225742318, + 1236538675, + 1247288478, + 1257991320, + 1268646800, + 1279254516, + 1289814068, + 1300325060, + 1310787095, + 1321199781, + 1331562723, + 1341875533, + 1352137822, + 1362349204, + 1372509294, + 1382617710, + 1392674072, + 1402678000, + 1412629117, + 1422527051, + 1432371426, + 1442161874, + 1451898025, + 1461579514, + 1471205974, + 1480777044, + 1490292364, + 1499751576, + 1509154322, + 1518500250, + 1527789007, + 1537020244, + 1546193612, + 1555308768, + 1564365367, + 1573363068, + 1582301533, + 1591180426, + 1599999411, + 1608758157, + 1617456335, + 1626093616, + 1634669676, + 1643184191, + 1651636841, + 1660027308, + 1668355276, + 1676620432, + 1684822463, + 1692961062, + 1701035922, + 1709046739, + 1716993211, + 1724875040, + 1732691928, + 1740443581, + 1748129707, + 1755750017, + 1763304224, + 1770792044, + 1778213194, + 1785567396, + 1792854372, + 1800073849, + 1807225553, + 1814309216, + 1821324572, + 1828271356, + 1835149306, + 1841958164, + 1848697674, + 1855367581, + 1861967634, + 1868497586, + 1874957189, + 1881346202, + 1887664383, + 1893911494, + 1900087301, + 1906191570, + 1912224073, + 1918184581, + 1924072871, + 1929888720, + 1935631910, + 1941302225, + 1946899451, + 1952423377, + 1957873796, + 1963250501, + 1968553292, + 1973781967, + 1978936331, + 1984016189, + 1989021350, + 1993951625, + 1998806829, + 2003586779, + 2008291295, + 2012920201, + 2017473321, + 2021950484, + 2026351522, + 2030676269, + 2034924562, + 2039096241, + 2043191150, + 2047209133, + 2051150040, + 2055013723, + 2058800036, + 2062508835, + 2066139983, + 2069693342, + 2073168777, + 2076566160, + 2079885360, + 2083126254, + 2086288720, + 2089372638, + 2092377892, + 2095304370, + 2098151960, + 2100920556, + 2103610054, + 2106220352, + 2108751352, + 2111202959, + 2113575080, + 2115867626, + 2118080511, + 2120213651, + 2122266967, + 2124240380, + 2126133817, + 2127947206, + 2129680480, + 2131333572, + 2132906420, + 2134398966, + 2135811153, + 2137142927, + 2138394240, + 2139565043, + 2140655293, + 2141664948, + 2142593971, + 2143442326, + 2144209982, + 2144896910, + 2145503083, + 2146028480, + 2146473080, + 2146836866, + 2147119825, + 2147321946, + 2147443222, +}; + +/* in Q1.31, generated from sin(i * 2 * pi / FFT_SIZE_MAX) */ +const int32_t twiddle_imag_32[FFT_SIZE_MAX] = { + 0, + -13176712, + -26352928, + -39528151, + -52701887, + -65873638, + -79042909, + -92209205, + -105372028, + -118530885, + -131685278, + -144834714, + -157978697, + -171116733, + -184248325, + -197372981, + -210490206, + -223599506, + -236700388, + -249792358, + -262874923, + -275947592, + -289009871, + -302061269, + -315101295, + -328129457, + -341145265, + -354148230, + -367137861, + -380113669, + -393075166, + -406021865, + -418953276, + -431868915, + -444768294, + -457650927, + -470516330, + -483364019, + -496193509, + -509004318, + -521795963, + -534567963, + -547319836, + -560051104, + -572761285, + -585449903, + -598116479, + -610760536, + -623381598, + -635979190, + -648552838, + -661102068, + -673626408, + -686125387, + -698598533, + -711045377, + -723465451, + -735858287, + -748223418, + -760560380, + -772868706, + -785147934, + -797397602, + -809617249, + -821806413, + -833964638, + -846091463, + -858186435, + -870249095, + -882278992, + -894275671, + -906238681, + -918167572, + -930061894, + -941921200, + -953745043, + -965532978, + -977284562, + -988999351, + -1000676905, + -1012316784, + -1023918550, + -1035481766, + -1047005996, + -1058490808, + -1069935768, + -1081340445, + -1092704411, + -1104027237, + -1115308496, + -1126547765, + -1137744621, + -1148898640, + -1160009405, + -1171076495, + -1182099496, + -1193077991, + -1204011567, + -1214899813, + -1225742318, + -1236538675, + -1247288478, + -1257991320, + -1268646800, + -1279254516, + -1289814068, + -1300325060, + -1310787095, + -1321199781, + -1331562723, + -1341875533, + -1352137822, + -1362349204, + -1372509294, + -1382617710, + -1392674072, + -1402678000, + -1412629117, + -1422527051, + -1432371426, + -1442161874, + -1451898025, + -1461579514, + -1471205974, + -1480777044, + -1490292364, + -1499751576, + -1509154322, + -1518500250, + -1527789007, + -1537020244, + -1546193612, + -1555308768, + -1564365367, + -1573363068, + -1582301533, + -1591180426, + -1599999411, + -1608758157, + -1617456335, + -1626093616, + -1634669676, + -1643184191, + -1651636841, + -1660027308, + -1668355276, + -1676620432, + -1684822463, + -1692961062, + -1701035922, + -1709046739, + -1716993211, + -1724875040, + -1732691928, + -1740443581, + -1748129707, + -1755750017, + -1763304224, + -1770792044, + -1778213194, + -1785567396, + -1792854372, + -1800073849, + -1807225553, + -1814309216, + -1821324572, + -1828271356, + -1835149306, + -1841958164, + -1848697674, + -1855367581, + -1861967634, + -1868497586, + -1874957189, + -1881346202, + -1887664383, + -1893911494, + -1900087301, + -1906191570, + -1912224073, + -1918184581, + -1924072871, + -1929888720, + -1935631910, + -1941302225, + -1946899451, + -1952423377, + -1957873796, + -1963250501, + -1968553292, + -1973781967, + -1978936331, + -1984016189, + -1989021350, + -1993951625, + -1998806829, + -2003586779, + -2008291295, + -2012920201, + -2017473321, + -2021950484, + -2026351522, + -2030676269, + -2034924562, + -2039096241, + -2043191150, + -2047209133, + -2051150040, + -2055013723, + -2058800036, + -2062508835, + -2066139983, + -2069693342, + -2073168777, + -2076566160, + -2079885360, + -2083126254, + -2086288720, + -2089372638, + -2092377892, + -2095304370, + -2098151960, + -2100920556, + -2103610054, + -2106220352, + -2108751352, + -2111202959, + -2113575080, + -2115867626, + -2118080511, + -2120213651, + -2122266967, + -2124240380, + -2126133817, + -2127947206, + -2129680480, + -2131333572, + -2132906420, + -2134398966, + -2135811153, + -2137142927, + -2138394240, + -2139565043, + -2140655293, + -2141664948, + -2142593971, + -2143442326, + -2144209982, + -2144896910, + -2145503083, + -2146028480, + -2146473080, + -2146836866, + -2147119825, + -2147321946, + -2147443222, + -2147483647, + -2147443222, + -2147321946, + -2147119825, + -2146836866, + -2146473080, + -2146028480, + -2145503083, + -2144896910, + -2144209982, + -2143442326, + -2142593971, + -2141664948, + -2140655293, + -2139565043, + -2138394240, + -2137142927, + -2135811153, + -2134398966, + -2132906420, + -2131333572, + -2129680480, + -2127947206, + -2126133817, + -2124240380, + -2122266967, + -2120213651, + -2118080511, + -2115867626, + -2113575080, + -2111202959, + -2108751352, + -2106220352, + -2103610054, + -2100920556, + -2098151960, + -2095304370, + -2092377892, + -2089372638, + -2086288720, + -2083126254, + -2079885360, + -2076566160, + -2073168777, + -2069693342, + -2066139983, + -2062508835, + -2058800036, + -2055013723, + -2051150040, + -2047209133, + -2043191150, + -2039096241, + -2034924562, + -2030676269, + -2026351522, + -2021950484, + -2017473321, + -2012920201, + -2008291295, + -2003586779, + -1998806829, + -1993951625, + -1989021350, + -1984016189, + -1978936331, + -1973781967, + -1968553292, + -1963250501, + -1957873796, + -1952423377, + -1946899451, + -1941302225, + -1935631910, + -1929888720, + -1924072871, + -1918184581, + -1912224073, + -1906191570, + -1900087301, + -1893911494, + -1887664383, + -1881346202, + -1874957189, + -1868497586, + -1861967634, + -1855367581, + -1848697674, + -1841958164, + -1835149306, + -1828271356, + -1821324572, + -1814309216, + -1807225553, + -1800073849, + -1792854372, + -1785567396, + -1778213194, + -1770792044, + -1763304224, + -1755750017, + -1748129707, + -1740443581, + -1732691928, + -1724875040, + -1716993211, + -1709046739, + -1701035922, + -1692961062, + -1684822463, + -1676620432, + -1668355276, + -1660027308, + -1651636841, + -1643184191, + -1634669676, + -1626093616, + -1617456335, + -1608758157, + -1599999411, + -1591180426, + -1582301533, + -1573363068, + -1564365367, + -1555308768, + -1546193612, + -1537020244, + -1527789007, + -1518500250, + -1509154322, + -1499751576, + -1490292364, + -1480777044, + -1471205974, + -1461579514, + -1451898025, + -1442161874, + -1432371426, + -1422527051, + -1412629117, + -1402678000, + -1392674072, + -1382617710, + -1372509294, + -1362349204, + -1352137822, + -1341875533, + -1331562723, + -1321199781, + -1310787095, + -1300325060, + -1289814068, + -1279254516, + -1268646800, + -1257991320, + -1247288478, + -1236538675, + -1225742318, + -1214899813, + -1204011567, + -1193077991, + -1182099496, + -1171076495, + -1160009405, + -1148898640, + -1137744621, + -1126547765, + -1115308496, + -1104027237, + -1092704411, + -1081340445, + -1069935768, + -1058490808, + -1047005996, + -1035481766, + -1023918550, + -1012316784, + -1000676905, + -988999351, + -977284562, + -965532978, + -953745043, + -941921200, + -930061894, + -918167572, + -906238681, + -894275671, + -882278992, + -870249095, + -858186435, + -846091463, + -833964638, + -821806413, + -809617249, + -797397602, + -785147934, + -772868706, + -760560380, + -748223418, + -735858287, + -723465451, + -711045377, + -698598533, + -686125387, + -673626408, + -661102068, + -648552838, + -635979190, + -623381598, + -610760536, + -598116479, + -585449903, + -572761285, + -560051104, + -547319836, + -534567963, + -521795963, + -509004318, + -496193509, + -483364019, + -470516330, + -457650927, + -444768294, + -431868915, + -418953276, + -406021865, + -393075166, + -380113669, + -367137861, + -354148230, + -341145265, + -328129457, + -315101295, + -302061269, + -289009871, + -275947592, + -262874923, + -249792358, + -236700388, + -223599506, + -210490206, + -197372981, + -184248325, + -171116733, + -157978697, + -144834714, + -131685278, + -118530885, + -105372028, + -92209205, + -79042909, + -65873638, + -52701887, + -39528151, + -26352928, + -13176712, + 0, + 13176712, + 26352928, + 39528151, + 52701887, + 65873638, + 79042909, + 92209205, + 105372028, + 118530885, + 131685278, + 144834714, + 157978697, + 171116733, + 184248325, + 197372981, + 210490206, + 223599506, + 236700388, + 249792358, + 262874923, + 275947592, + 289009871, + 302061269, + 315101295, + 328129457, + 341145265, + 354148230, + 367137861, + 380113669, + 393075166, + 406021865, + 418953276, + 431868915, + 444768294, + 457650927, + 470516330, + 483364019, + 496193509, + 509004318, + 521795963, + 534567963, + 547319836, + 560051104, + 572761285, + 585449903, + 598116479, + 610760536, + 623381598, + 635979190, + 648552838, + 661102068, + 673626408, + 686125387, + 698598533, + 711045377, + 723465451, + 735858287, + 748223418, + 760560380, + 772868706, + 785147934, + 797397602, + 809617249, + 821806413, + 833964638, + 846091463, + 858186435, + 870249095, + 882278992, + 894275671, + 906238681, + 918167572, + 930061894, + 941921200, + 953745043, + 965532978, + 977284562, + 988999351, + 1000676905, + 1012316784, + 1023918550, + 1035481766, + 1047005996, + 1058490808, + 1069935768, + 1081340445, + 1092704411, + 1104027237, + 1115308496, + 1126547765, + 1137744621, + 1148898640, + 1160009405, + 1171076495, + 1182099496, + 1193077991, + 1204011567, + 1214899813, + 1225742318, + 1236538675, + 1247288478, + 1257991320, + 1268646800, + 1279254516, + 1289814068, + 1300325060, + 1310787095, + 1321199781, + 1331562723, + 1341875533, + 1352137822, + 1362349204, + 1372509294, + 1382617710, + 1392674072, + 1402678000, + 1412629117, + 1422527051, + 1432371426, + 1442161874, + 1451898025, + 1461579514, + 1471205974, + 1480777044, + 1490292364, + 1499751576, + 1509154322, + 1518500250, + 1527789007, + 1537020244, + 1546193612, + 1555308768, + 1564365367, + 1573363068, + 1582301533, + 1591180426, + 1599999411, + 1608758157, + 1617456335, + 1626093616, + 1634669676, + 1643184191, + 1651636841, + 1660027308, + 1668355276, + 1676620432, + 1684822463, + 1692961062, + 1701035922, + 1709046739, + 1716993211, + 1724875040, + 1732691928, + 1740443581, + 1748129707, + 1755750017, + 1763304224, + 1770792044, + 1778213194, + 1785567396, + 1792854372, + 1800073849, + 1807225553, + 1814309216, + 1821324572, + 1828271356, + 1835149306, + 1841958164, + 1848697674, + 1855367581, + 1861967634, + 1868497586, + 1874957189, + 1881346202, + 1887664383, + 1893911494, + 1900087301, + 1906191570, + 1912224073, + 1918184581, + 1924072871, + 1929888720, + 1935631910, + 1941302225, + 1946899451, + 1952423377, + 1957873796, + 1963250501, + 1968553292, + 1973781967, + 1978936331, + 1984016189, + 1989021350, + 1993951625, + 1998806829, + 2003586779, + 2008291295, + 2012920201, + 2017473321, + 2021950484, + 2026351522, + 2030676269, + 2034924562, + 2039096241, + 2043191150, + 2047209133, + 2051150040, + 2055013723, + 2058800036, + 2062508835, + 2066139983, + 2069693342, + 2073168777, + 2076566160, + 2079885360, + 2083126254, + 2086288720, + 2089372638, + 2092377892, + 2095304370, + 2098151960, + 2100920556, + 2103610054, + 2106220352, + 2108751352, + 2111202959, + 2113575080, + 2115867626, + 2118080511, + 2120213651, + 2122266967, + 2124240380, + 2126133817, + 2127947206, + 2129680480, + 2131333572, + 2132906420, + 2134398966, + 2135811153, + 2137142927, + 2138394240, + 2139565043, + 2140655293, + 2141664948, + 2142593971, + 2143442326, + 2144209982, + 2144896910, + 2145503083, + 2146028480, + 2146473080, + 2146836866, + 2147119825, + 2147321946, + 2147443222, + 2147483647, + 2147443222, + 2147321946, + 2147119825, + 2146836866, + 2146473080, + 2146028480, + 2145503083, + 2144896910, + 2144209982, + 2143442326, + 2142593971, + 2141664948, + 2140655293, + 2139565043, + 2138394240, + 2137142927, + 2135811153, + 2134398966, + 2132906420, + 2131333572, + 2129680480, + 2127947206, + 2126133817, + 2124240380, + 2122266967, + 2120213651, + 2118080511, + 2115867626, + 2113575080, + 2111202959, + 2108751352, + 2106220352, + 2103610054, + 2100920556, + 2098151960, + 2095304370, + 2092377892, + 2089372638, + 2086288720, + 2083126254, + 2079885360, + 2076566160, + 2073168777, + 2069693342, + 2066139983, + 2062508835, + 2058800036, + 2055013723, + 2051150040, + 2047209133, + 2043191150, + 2039096241, + 2034924562, + 2030676269, + 2026351522, + 2021950484, + 2017473321, + 2012920201, + 2008291295, + 2003586779, + 1998806829, + 1993951625, + 1989021350, + 1984016189, + 1978936331, + 1973781967, + 1968553292, + 1963250501, + 1957873796, + 1952423377, + 1946899451, + 1941302225, + 1935631910, + 1929888720, + 1924072871, + 1918184581, + 1912224073, + 1906191570, + 1900087301, + 1893911494, + 1887664383, + 1881346202, + 1874957189, + 1868497586, + 1861967634, + 1855367581, + 1848697674, + 1841958164, + 1835149306, + 1828271356, + 1821324572, + 1814309216, + 1807225553, + 1800073849, + 1792854372, + 1785567396, + 1778213194, + 1770792044, + 1763304224, + 1755750017, + 1748129707, + 1740443581, + 1732691928, + 1724875040, + 1716993211, + 1709046739, + 1701035922, + 1692961062, + 1684822463, + 1676620432, + 1668355276, + 1660027308, + 1651636841, + 1643184191, + 1634669676, + 1626093616, + 1617456335, + 1608758157, + 1599999411, + 1591180426, + 1582301533, + 1573363068, + 1564365367, + 1555308768, + 1546193612, + 1537020244, + 1527789007, + 1518500250, + 1509154322, + 1499751576, + 1490292364, + 1480777044, + 1471205974, + 1461579514, + 1451898025, + 1442161874, + 1432371426, + 1422527051, + 1412629117, + 1402678000, + 1392674072, + 1382617710, + 1372509294, + 1362349204, + 1352137822, + 1341875533, + 1331562723, + 1321199781, + 1310787095, + 1300325060, + 1289814068, + 1279254516, + 1268646800, + 1257991320, + 1247288478, + 1236538675, + 1225742318, + 1214899813, + 1204011567, + 1193077991, + 1182099496, + 1171076495, + 1160009405, + 1148898640, + 1137744621, + 1126547765, + 1115308496, + 1104027237, + 1092704411, + 1081340445, + 1069935768, + 1058490808, + 1047005996, + 1035481766, + 1023918550, + 1012316784, + 1000676905, + 988999351, + 977284562, + 965532978, + 953745043, + 941921200, + 930061894, + 918167572, + 906238681, + 894275671, + 882278992, + 870249095, + 858186435, + 846091463, + 833964638, + 821806413, + 809617249, + 797397602, + 785147934, + 772868706, + 760560380, + 748223418, + 735858287, + 723465451, + 711045377, + 698598533, + 686125387, + 673626408, + 661102068, + 648552838, + 635979190, + 623381598, + 610760536, + 598116479, + 585449903, + 572761285, + 560051104, + 547319836, + 534567963, + 521795963, + 509004318, + 496193509, + 483364019, + 470516330, + 457650927, + 444768294, + 431868915, + 418953276, + 406021865, + 393075166, + 380113669, + 367137861, + 354148230, + 341145265, + 328129457, + 315101295, + 302061269, + 289009871, + 275947592, + 262874923, + 249792358, + 236700388, + 223599506, + 210490206, + 197372981, + 184248325, + 171116733, + 157978697, + 144834714, + 131685278, + 118530885, + 105372028, + 92209205, + 79042909, + 65873638, + 52701887, + 39528151, + 26352928, + 13176712, +}; + +#endif diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4288_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4288_5100_010_095.h deleted file mode 100644 index 7baea26f967a..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4288_5100_010_095.h +++ /dev/null @@ -1,107 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#include <stdint.h> - -const int32_t fir_int32_02_4288_5100_010_095[91] = { - -193886, - 104552, - 2140521, - 5355562, - 5945318, - 1216991, - -4511367, - -3527243, - 3415937, - 5526880, - -1935806, - -7515849, - -386524, - 9252379, - 3862172, - -10093681, - -8251552, - 9738620, - 13536988, - -7464432, - -19100785, - 2935187, - 24375729, - 4314479, - -28271418, - -14141458, - 29999307, - 26636531, - -28180625, - -41208987, - 21649022, - 57264356, - -8757879, - -73520802, - -12043366, - 88868414, - 43784598, - -101162825, - -91853580, - 106519993, - 169110273, - -94206010, - -317139630, - 5894310, - 739661049, - 1132200744, - 739661049, - 5894310, - -317139630, - -94206010, - 169110273, - 106519993, - -91853580, - -101162825, - 43784598, - 88868414, - -12043366, - -73520802, - -8757879, - 57264356, - 21649022, - -41208987, - -28180625, - 26636531, - 29999307, - -14141458, - -28271418, - 4314479, - 24375729, - 2935187, - -19100785, - -7464432, - 13536988, - 9738620, - -8251552, - -10093681, - 3862172, - 9252379, - -386524, - -7515849, - -1935806, - 5526880, - 3415937, - -3527243, - -4511367, - 1216991, - 5945318, - 5355562, - 2140521, - 104552, - -193886 - -}; - -struct pdm_decim pdm_decim_int32_02_4288_5100_010_095 = { - 2, 91, 0, 4288, 5100, 10, 95, fir_int32_02_4288_5100_010_095 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4323_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4323_5100_010_095.h new file mode 100644 index 000000000000..957e9334cf83 --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4323_5100_010_095.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_02_4323_5100_010_095[95] = { + 178179, + -158757, + -2195582, + -5296650, + -5737416, + -1057695, + 4405719, + 3336648, + -3249588, + -5061179, + 1984305, + 6895125, + 68826, + -8433396, + -2933479, + 9499107, + 6882087, + -9330152, + -11397510, + 7807097, + 16376076, + -4402338, + -21239788, + -1118085, + 25423993, + 9062534, + -27935015, + -19203927, + 28049586, + 31500423, + -24524863, + -45191501, + 16582731, + 59861920, + -2808306, + -74639091, + -18696113, + 88054673, + 50505898, + -98266320, + -97865783, + 101816481, + 173879965, + -88042495, + -320187025, + -1193013, + 740698712, + 1139586920, + 740698712, + -1193013, + -320187025, + -88042495, + 173879965, + 101816481, + -97865783, + -98266320, + 50505898, + 88054673, + -18696113, + -74639091, + -2808306, + 59861920, + 16582731, + -45191501, + -24524863, + 31500423, + 28049586, + -19203927, + -27935015, + 9062534, + 25423993, + -1118085, + -21239788, + -4402338, + 16376076, + 7807097, + -11397510, + -9330152, + 6882087, + 9499107, + -2933479, + -8433396, + 68826, + 6895125, + 1984305, + -5061179, + -3249588, + 3336648, + 4405719, + -1057695, + -5737416, + -5296650, + -2195582, + -158757, + 178179 + +}; + +struct pdm_decim pdm_decim_int32_02_4323_5100_010_095 = { + 2, 95, 0, 4323, 5100, 10, 95, fir_int32_02_4323_5100_010_095 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4375_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4375_5100_010_095.h index 1e31919fb569..d4d480b5a41e 100644 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4375_5100_010_095.h +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_02_4375_5100_010_095.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> */ #include <stdint.h> @@ -12,99 +10,99 @@ const int32_t fir_int32_02_4375_5100_010_095[101] = { -2653881, -5154608, -4845367, - -226473, + -226474, 4220832, 2571159, - -3184701, + -3184700, -4043579, 2206821, 5554546, - -750496, - -6923900, - -1268584, - 8073360, - 4085183, - -8546477, - -7505364, - 8176185, + -750495, + -6923897, + -1268580, + 8073364, + 4085184, + -8546479, + -7505366, + 8176184, 11533751, -6471060, - -15704256, - 3359707, - 19852409, - 1635593, + -15704257, + 3359705, + 19852407, + 1635592, -23144509, -8252640, - 25285013, - 16574479, + 25285011, + 16574477, -25723227, - -26663304, + -26663303, 23549736, - 38139664, - -17943366, - -50446983, - 8141043, - 63090267, - 7051351, - -75166959, - -29039894, - 85772627, - 60568979, - -93167356, - -106799776, - 94198973, - 180962815, - -78385592, - -324820245, + 38139662, + -17943368, + -50446982, + 8141045, + 63090266, + 7051348, + -75166961, + -29039893, + 85772628, + 60568976, + -93167361, + -106799777, + 94198977, + 180962817, + -78385599, + -324820256, -12243140, - 742491441, - 1151461281, - 742491441, + 742491464, + 1151461314, + 742491464, -12243140, - -324820245, - -78385592, - 180962815, - 94198973, - -106799776, - -93167356, - 60568979, - 85772627, - -29039894, - -75166959, - 7051351, - 63090267, - 8141043, - -50446983, - -17943366, - 38139664, + -324820256, + -78385599, + 180962817, + 94198977, + -106799777, + -93167361, + 60568976, + 85772628, + -29039893, + -75166961, + 7051348, + 63090266, + 8141045, + -50446982, + -17943368, + 38139662, 23549736, - -26663304, + -26663303, -25723227, - 16574479, - 25285013, + 16574477, + 25285011, -8252640, -23144509, - 1635593, - 19852409, - 3359707, - -15704256, + 1635592, + 19852407, + 3359705, + -15704257, -6471060, 11533751, - 8176185, - -7505364, - -8546477, - 4085183, - 8073360, - -1268584, - -6923900, - -750496, + 8176184, + -7505366, + -8546479, + 4085184, + 8073364, + -1268580, + -6923897, + -750495, 5554546, 2206821, -4043579, - -3184701, + -3184700, 2571159, 4220832, - -226473, + -226474, -4845367, -5154608, -2653881, diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_3850_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_3850_5100_010_095.h deleted file mode 100644 index 9c18842584ed..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_3850_5100_010_095.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#include <stdint.h> - -const int32_t fir_int32_03_3850_5100_010_095[93] = { - 44212, - -302176, - -1360920, - -3291119, - -5495374, - -6588668, - -5102927, - -753403, - 4644861, - 7677973, - 5490212, - -1618066, - -9302333, - -11445730, - -4732005, - 7709057, - 17063964, - 14699335, - -457541, - -18980508, - -26202607, - -13319132, - 13695670, - 35545996, - 32740745, - 1994202, - -37267233, - -54079734, - -29355959, - 25448678, - 71128406, - 67328423, - 5964667, - -74773313, - -111583346, - -62643893, - 52737606, - 154899783, - 153311689, - 16759099, - -184962926, - -304661987, - -201939017, - 160731847, - 673585388, - 1122541471, - 1300561761, - 1122541471, - 673585388, - 160731847, - -201939017, - -304661987, - -184962926, - 16759099, - 153311689, - 154899783, - 52737606, - -62643893, - -111583346, - -74773313, - 5964667, - 67328423, - 71128406, - 25448678, - -29355959, - -54079734, - -37267233, - 1994202, - 32740745, - 35545996, - 13695670, - -13319132, - -26202607, - -18980508, - -457541, - 14699335, - 17063964, - 7709057, - -4732005, - -11445730, - -9302333, - -1618066, - 5490212, - 7677973, - 4644861, - -753403, - -5102927, - -6588668, - -5495374, - -3291119, - -1360920, - -302176, - 44212 - -}; - -struct pdm_decim pdm_decim_int32_03_3850_5100_010_095 = { - 3, 93, 1, 3850, 5100, 10, 95, fir_int32_03_3850_5100_010_095 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_4375_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_4375_5100_010_095.h index a65a15a0481e..a4a4337b3f13 100644 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_4375_5100_010_095.h +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_03_4375_5100_010_095.h @@ -1,170 +1,168 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> */ #include <stdint.h> const int32_t fir_int32_03_4375_5100_010_095[157] = { - 350904, - 1127891, - 2233546, - 3059556, - 2752177, - 818057, - -2252661, - -4944515, - -5550704, - -3466227, - 53089, - 2496755, - 1904111, - -1421730, - -4818556, - -5204443, - -1721082, - 3155305, - 5311444, - 2454515, - -3518616, - -7589471, - -5713308, - 1327821, - 7901341, - 7958087, - 527903, - -8633996, - -11354795, - -4214518, - 7627116, - 13970242, - 8263364, - -5861946, - -16549651, - -13529964, - 2213919, - 17870757, - 19056207, - 2854066, - -18029728, - -24979102, - -9860164, - 16175117, - 30545984, - 18605951, - -11894271, - -35172531, - -28918160, - 4746528, - 38201092, - 40590666, - 5825429, - -38712951, - -53159148, - -20283384, - 35723256, - 66120531, - 39265868, - -27910967, - -78795928, - -63663750, - 13458962, - 90416047, - 95193346, - 10755142, - -99897049, - -137497231, - -51075841, - 105457455, - 200047804, - 124561003, - -101612190, - -313384381, - -297343743, - 53701878, - 639681661, - 1187800564, - 1411050887, - 1187800564, - 639681661, - 53701878, - -297343743, - -313384381, - -101612190, - 124561003, - 200047804, - 105457455, - -51075841, - -137497231, - -99897049, - 10755142, - 95193346, - 90416047, - 13458962, - -63663750, - -78795928, - -27910967, - 39265868, - 66120531, - 35723256, - -20283384, - -53159148, - -38712951, - 5825429, - 40590666, - 38201092, - 4746528, - -28918160, - -35172531, - -11894271, - 18605951, - 30545984, - 16175117, - -9860164, - -24979102, - -18029728, - 2854066, - 19056207, - 17870757, - 2213919, - -13529964, - -16549651, - -5861946, - 8263364, - 13970242, - 7627116, - -4214518, - -11354795, - -8633996, - 527903, - 7958087, - 7901341, - 1327821, - -5713308, - -7589471, - -3518616, - 2454515, - 5311444, - 3155305, - -1721082, - -5204443, - -4818556, - -1421730, - 1904111, - 2496755, - 53089, - -3466227, - -5550704, - -4944515, - -2252661, - 818057, - 2752177, - 3059556, - 2233546, - 1127891, - 350904 + 350908, + 1127906, + 2233575, + 3059598, + 2752218, + 818077, + -2252677, + -4944563, + -5550761, + -3466262, + 53093, + 2496787, + 1904133, + -1421749, + -4818616, + -5204506, + -1721103, + 3155344, + 5311508, + 2454543, + -3518663, + -7589567, + -5713379, + 1327838, + 7901439, + 7958184, + 527907, + -8634105, + -11354937, + -4214569, + 7627213, + 13970417, + 8263468, + -5862019, + -16549858, + -13530131, + 2213952, + 17870989, + 19056458, + 2854116, + -18029944, + -24979416, + -9860304, + 16175288, + 30546328, + 18606151, + -11894439, + -35172976, + -28918520, + 4746588, + 38201563, + 40591159, + 5825487, + -38713444, + -53159813, + -20283635, + 35723701, + 66121349, + 39266346, + -27911327, + -78796917, + -63664545, + 13459132, + 90417174, + 95194527, + 10755265, + -99898306, + -137498952, + -51076476, + 105458775, + 200050300, + 124562550, + -101613472, + -313388303, + -297347454, + 53702567, + 639689683, + 1187815441, + 1411068556, + 1187815441, + 639689683, + 53702567, + -297347454, + -313388303, + -101613472, + 124562550, + 200050300, + 105458775, + -51076476, + -137498952, + -99898306, + 10755265, + 95194527, + 90417174, + 13459132, + -63664545, + -78796917, + -27911327, + 39266346, + 66121349, + 35723701, + -20283635, + -53159813, + -38713444, + 5825487, + 40591159, + 38201563, + 4746588, + -28918520, + -35172976, + -11894439, + 18606151, + 30546328, + 16175288, + -9860304, + -24979416, + -18029944, + 2854116, + 19056458, + 17870989, + 2213952, + -13530131, + -16549858, + -5862019, + 8263468, + 13970417, + 7627213, + -4214569, + -11354937, + -8634105, + 527907, + 7958184, + 7901439, + 1327838, + -5713379, + -7589567, + -3518663, + 2454543, + 5311508, + 3155344, + -1721103, + -5204506, + -4818616, + -1421749, + 1904133, + 2496787, + 53093, + -3466262, + -5550761, + -4944563, + -2252677, + 818077, + 2752218, + 3059598, + 2233575, + 1127906, + 350908 }; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_04_4318_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_04_4318_5100_010_095.h new file mode 100644 index 000000000000..fc0eb0be8dac --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_04_4318_5100_010_095.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_04_4318_5100_010_095[195] = { + 111466, + 733409, + 1749250, + 3319696, + 5129378, + 6676209, + 7309490, + 6506584, + 4154756, + 734975, + -2729377, + -4998637, + -5126868, + -2945573, + 726080, + 4306371, + 6084832, + 5022201, + 1343898, + -3405897, + -6962146, + -7384707, + -4083477, + 1706504, + 7322247, + 9858386, + 7634375, + 1218279, + -6584983, + -11909667, + -11705999, + -5426216, + 4387589, + 13057254, + 15953274, + 10914694, + -336708, + -12649310, + -19740590, + -17350504, + -5691816, + 10168034, + 22423979, + 24315225, + 13770305, + -5012695, + -23099234, + -30992981, + -23541145, + -3074594, + 21044646, + 36602258, + 34627991, + 14410179, + -15304906, + -39942350, + -46136506, + -28837515, + 5227124, + 39904111, + 57125295, + 46160603, + 9951610, + -35069112, + -66221384, + -65802058, + -30833475, + 23892424, + 71729303, + 86873627, + 57925919, + -4643620, + -71630929, + -108312985, + -91957579, + -25024430, + 63233146, + 128873180, + 134384678, + 69003997, + -42277605, + -146972769, + -188542432, + -135065835, + 625004, + 160544910, + 263771211, + 243538822, + 83417905, + -164654723, + -391259178, + -468017530, + -299941690, + 129616412, + 741218294, + 1378462855, + 1858765025, + 2037199780, + 1858765025, + 1378462855, + 741218294, + 129616412, + -299941690, + -468017530, + -391259178, + -164654723, + 83417905, + 243538822, + 263771211, + 160544910, + 625004, + -135065835, + -188542432, + -146972769, + -42277605, + 69003997, + 134384678, + 128873180, + 63233146, + -25024430, + -91957579, + -108312985, + -71630929, + -4643620, + 57925919, + 86873627, + 71729303, + 23892424, + -30833475, + -65802058, + -66221384, + -35069112, + 9951610, + 46160603, + 57125295, + 39904111, + 5227124, + -28837515, + -46136506, + -39942350, + -15304906, + 14410179, + 34627991, + 36602258, + 21044646, + -3074594, + -23541145, + -30992981, + -23099234, + -5012695, + 13770305, + 24315225, + 22423979, + 10168034, + -5691816, + -17350504, + -19740590, + -12649310, + -336708, + 10914694, + 15953274, + 13057254, + 4387589, + -5426216, + -11705999, + -11909667, + -6584983, + 1218279, + 7634375, + 9858386, + 7322247, + 1706504, + -4083477, + -7384707, + -6962146, + -3405897, + 1343898, + 5022201, + 6084832, + 4306371, + 726080, + -2945573, + -5126868, + -4998637, + -2729377, + 734975, + 4154756, + 6506584, + 7309490, + 6676209, + 5129378, + 3319696, + 1749250, + 733409, + 111466 + +}; + +struct pdm_decim pdm_decim_int32_04_4318_5100_010_095 = { + 4, 195, 2, 4318, 5100, 10, 95, fir_int32_04_4318_5100_010_095 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_04_4375_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_04_4375_5100_010_095.h deleted file mode 100644 index ece85fabaf74..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_04_4375_5100_010_095.h +++ /dev/null @@ -1,227 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#include <stdint.h> - -const int32_t fir_int32_04_4375_5100_010_095[211] = { - 126017, - 745791, - 1735783, - 3250059, - 4963537, - 6400069, - 6949502, - 6142229, - 3902336, - 705842, - -2485787, - -4540607, - -4626085, - -2636100, - 646448, - 3784383, - 5275090, - 4259502, - 1015665, - -3045153, - -5950963, - -6099091, - -3115593, - 1807814, - 6342508, - 8093924, - 5838000, - 296533, - -6011752, - -9879686, - -9013045, - -3339610, - 4700101, - 11152288, - 12461593, - 7387989, - -2085667, - -11448775, - -15769545, - -12252662, - -1940150, - 10437445, - 18576639, - 17768944, - 7550319, - -7626200, - -20251921, - -23428157, - -14572076, - 2797464, - 20329234, - 28790530, - 22864155, - 4330980, - -18201801, - -33211863, - -32081436, - -13923851, - 13233081, - 35870337, - 41620943, - 25914222, - -4896316, - -35895437, - -50712381, - -40042952, - -7212823, - 32428935, - 58525317, - 56015029, - 23582638, - -24374765, - -63897455, - -73234460, - -44550852, - 10604843, - 65540282, - 91054416, - 70624752, - 10408242, - -61706258, - -108584856, - -102490195, - -40744453, - 50090298, - 124919090, - 141743373, - 84173003, - -26760833, - -138851415, - -191966143, - -148464813, - -16173880, - 148695193, - 262835505, - 254088691, - 100293640, - -149816104, - -385869984, - -474827254, - -315628113, - 112831849, - 731720961, - 1381072959, - 1872325415, - 2055132469, - 1872325415, - 1381072959, - 731720961, - 112831849, - -315628113, - -474827254, - -385869984, - -149816104, - 100293640, - 254088691, - 262835505, - 148695193, - -16173880, - -148464813, - -191966143, - -138851415, - -26760833, - 84173003, - 141743373, - 124919090, - 50090298, - -40744453, - -102490195, - -108584856, - -61706258, - 10408242, - 70624752, - 91054416, - 65540282, - 10604843, - -44550852, - -73234460, - -63897455, - -24374765, - 23582638, - 56015029, - 58525317, - 32428935, - -7212823, - -40042952, - -50712381, - -35895437, - -4896316, - 25914222, - 41620943, - 35870337, - 13233081, - -13923851, - -32081436, - -33211863, - -18201801, - 4330980, - 22864155, - 28790530, - 20329234, - 2797464, - -14572076, - -23428157, - -20251921, - -7626200, - 7550319, - 17768944, - 18576639, - 10437445, - -1940150, - -12252662, - -15769545, - -11448775, - -2085667, - 7387989, - 12461593, - 11152288, - 4700101, - -3339610, - -9013045, - -9879686, - -6011752, - 296533, - 5838000, - 8093924, - 6342508, - 1807814, - -3115593, - -6099091, - -5950963, - -3045153, - 1015665, - 4259502, - 5275090, - 3784383, - 646448, - -2636100, - -4626085, - -4540607, - -2485787, - 705842, - 3902336, - 6142229, - 6949502, - 6400069, - 4963537, - 3250059, - 1735783, - 745791, - 126017 - -}; - -struct pdm_decim pdm_decim_int32_04_4375_5100_010_095 = { - 4, 211, 2, 4375, 5100, 10, 95, fir_int32_04_4375_5100_010_095 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_05_4325_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_05_4325_5100_010_095.h new file mode 100644 index 000000000000..4e5bf169a025 --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_05_4325_5100_010_095.h @@ -0,0 +1,263 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_05_4325_5100_010_095[249] = { + -207469, + -340409, + -498144, + -558705, + -409384, + 55040, + 891125, + 2067198, + 3439775, + 4759611, + 5714914, + 6006588, + 5438767, + 3999938, + 1904139, + -429386, + -2461501, + -3672469, + -3715731, + -2543409, + -455850, + 1949813, + 3931230, + 4816572, + 4223058, + 2208032, + -705100, + -3649781, + -5664341, + -5997954, + -4379534, + -1155856, + 2760627, + 6138124, + 7803235, + 7038238, + 3865643, + -886573, + -5783539, + -9205487, + -9873081, + -7309023, + -2074085, + 4324112, + 9849851, + 12575185, + 11338304, + 6203771, + -1449001, + -9273272, + -14659745, + -15592551, + -11379919, + -3001447, + 7079011, + 15617750, + 19618936, + 17365380, + 9103870, + -2875883, + -14845719, + -22779047, + -23684744, + -16699479, + -3549687, + 11824128, + 24420688, + 29781202, + 25536278, + 12369331, + -5975020, + -23715313, + -34825066, + -35046780, + -23465500, + -3076561, + 19921841, + 37971240, + 44596949, + 36675890, + 15750350, + -12128842, + -38090537, + -53213360, + -51529430, + -32269554, + -535756, + 33948414, + 59741809, + 67400482, + 52822241, + 19070165, + -24058950, + -62761384, + -83526757, + -77707237, + -44854657, + 6391470, + 60372631, + 99010031, + 107635426, + 80237884, + 22341840, + -49653145, + -112793869, + -144502927, + -130123093, + -68698546, + 25049444, + 123586766, + 193887099, + 207405271, + 149914650, + 28201854, + -128717667, + -274782040, + -357589632, + -332094228, + -173714910, + 112793207, + 491412574, + 900833942, + 1267184732, + 1520519220, + 1610979079, + 1520519220, + 1267184732, + 900833942, + 491412574, + 112793207, + -173714910, + -332094228, + -357589632, + -274782040, + -128717667, + 28201854, + 149914650, + 207405271, + 193887099, + 123586766, + 25049444, + -68698546, + -130123093, + -144502927, + -112793869, + -49653145, + 22341840, + 80237884, + 107635426, + 99010031, + 60372631, + 6391470, + -44854657, + -77707237, + -83526757, + -62761384, + -24058950, + 19070165, + 52822241, + 67400482, + 59741809, + 33948414, + -535756, + -32269554, + -51529430, + -53213360, + -38090537, + -12128842, + 15750350, + 36675890, + 44596949, + 37971240, + 19921841, + -3076561, + -23465500, + -35046780, + -34825066, + -23715313, + -5975020, + 12369331, + 25536278, + 29781202, + 24420688, + 11824128, + -3549687, + -16699479, + -23684744, + -22779047, + -14845719, + -2875883, + 9103870, + 17365380, + 19618936, + 15617750, + 7079011, + -3001447, + -11379919, + -15592551, + -14659745, + -9273272, + -1449001, + 6203771, + 11338304, + 12575185, + 9849851, + 4324112, + -2074085, + -7309023, + -9873081, + -9205487, + -5783539, + -886573, + 3865643, + 7038238, + 7803235, + 6138124, + 2760627, + -1155856, + -4379534, + -5997954, + -5664341, + -3649781, + -705100, + 2208032, + 4223058, + 4816572, + 3931230, + 1949813, + -455850, + -2543409, + -3715731, + -3672469, + -2461501, + -429386, + 1904139, + 3999938, + 5438767, + 6006588, + 5714914, + 4759611, + 3439775, + 2067198, + 891125, + 55040, + -409384, + -558705, + -498144, + -340409, + -207469 + +}; + +struct pdm_decim pdm_decim_int32_05_4325_5100_010_095 = { + 5, 249, 2, 4325, 5100, 10, 95, fir_int32_05_4325_5100_010_095 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_05_4331_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_05_4331_5100_010_095.h deleted file mode 100644 index 9c746b0ab1fc..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_05_4331_5100_010_095.h +++ /dev/null @@ -1,267 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#include <stdint.h> - -const int32_t fir_int32_05_4331_5100_010_095[251] = { - -250963, - -530472, - -956449, - -1440505, - -1861966, - -2058350, - -1862594, - -1155766, - 78930, - 1719645, - 3501958, - 5061143, - 6013975, - 6066039, - 5113131, - 3303104, - 1032343, - -1135681, - -2614668, - -2968117, - -2057986, - -118896, - 2276521, - 4363476, - 5409644, - 4953617, - 2982225, - -20415, - -3181416, - -5487913, - -6107986, - -4685208, - -1505051, - 2535666, - 6167372, - 8134966, - 7619351, - 4554012, - -280001, - -5435156, - -9220394, - -10246686, - -7922490, - -2726786, - 3853867, - 9734139, - 12878468, - 11991508, - 7020539, - -717311, - -8859727, - -14705610, - -16097433, - -12195790, - -3874308, - 6431337, - 15415517, - 19946809, - 18139792, - 10093658, - -1980159, - -14334496, - -22829097, - -24298020, - -17696570, - -4621840, - 11019276, - 24149376, - 30144976, - 26434112, - 13524367, - -4930822, - -23124320, - -34892082, - -35768599, - -24626114, - -4311380, - 19011680, - 37690383, - 45054463, - 37744852, - 17102968, - -10919933, - -37416293, - -53300866, - -52364722, - -33596881, - -1935268, - 32928131, - 59438198, - 67925581, - 54022129, - 20569914, - -22737901, - -62048140, - -83661289, - -78659667, - -46330665, - 4859442, - 59276671, - 98707953, - 108233225, - 81552245, - 23955872, - -48257755, - -112070264, - -144691658, - -131171943, - -70276392, - 23448172, - 122479978, - 193637242, - 208100323, - 151336952, - 29895897, - -127299559, - -274102498, - -357874627, - -333256339, - -175377009, - 111180608, - 490397234, - 900786668, - 1268179136, - 1522305381, - 1613059887, - 1522305381, - 1268179136, - 900786668, - 490397234, - 111180608, - -175377009, - -333256339, - -357874627, - -274102498, - -127299559, - 29895897, - 151336952, - 208100323, - 193637242, - 122479978, - 23448172, - -70276392, - -131171943, - -144691658, - -112070264, - -48257755, - 23955872, - 81552245, - 108233225, - 98707953, - 59276671, - 4859442, - -46330665, - -78659667, - -83661289, - -62048140, - -22737901, - 20569914, - 54022129, - 67925581, - 59438198, - 32928131, - -1935268, - -33596881, - -52364722, - -53300866, - -37416293, - -10919933, - 17102968, - 37744852, - 45054463, - 37690383, - 19011680, - -4311380, - -24626114, - -35768599, - -34892082, - -23124320, - -4930822, - 13524367, - 26434112, - 30144976, - 24149376, - 11019276, - -4621840, - -17696570, - -24298020, - -22829097, - -14334496, - -1980159, - 10093658, - 18139792, - 19946809, - 15415517, - 6431337, - -3874308, - -12195790, - -16097433, - -14705610, - -8859727, - -717311, - 7020539, - 11991508, - 12878468, - 9734139, - 3853867, - -2726786, - -7922490, - -10246686, - -9220394, - -5435156, - -280001, - 4554012, - 7619351, - 8134966, - 6167372, - 2535666, - -1505051, - -4685208, - -6107986, - -5487913, - -3181416, - -20415, - 2982225, - 4953617, - 5409644, - 4363476, - 2276521, - -118896, - -2057986, - -2968117, - -2614668, - -1135681, - 1032343, - 3303104, - 5113131, - 6066039, - 6013975, - 5061143, - 3501958, - 1719645, - 78930, - -1155766, - -1862594, - -2058350, - -1861966, - -1440505, - -956449, - -530472, - -250963 - -}; - -struct pdm_decim pdm_decim_int32_05_4331_5100_010_095 = { - 5, 251, 2, 4331, 5100, 10, 95, fir_int32_05_4331_5100_010_095 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_06_4156_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_06_4156_5100_010_095.h deleted file mode 100644 index b949ff23ed90..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_06_4156_5100_010_095.h +++ /dev/null @@ -1,265 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#include <stdint.h> - -const int32_t fir_int32_06_4156_5100_010_095[249] = { - -145670, - -159762, - -183049, - -132077, - 40047, - 375196, - 897258, - 1599108, - 2433074, - 3308273, - 4097062, - 4651618, - 4829700, - 4525669, - 3700263, - 2402258, - 776038, - -950161, - -2496541, - -3579851, - -3970442, - -3547641, - -2337956, - -529617, - 1547925, - 3476297, - 4827277, - 5253398, - 4572039, - 2823110, - 284249, - -2564887, - -5127174, - -6808166, - -7148614, - -5940791, - -3300873, - 324045, - 4222816, - 7553233, - 9518313, - 9550081, - 7459490, - 3515883, - -1570147, - -6764980, - -10915019, - -12995804, - -12355318, - -8895306, - -3143626, - 3808819, - 10504528, - 15416643, - 17288185, - 15439779, - 9973227, - 1815303, - -7421871, - -15747713, - -21211963, - -22349384, - -18551421, - -10274491, - 976318, - 12902423, - 22867792, - 28468157, - 28093650, - 21356476, - 9275878, - -5840836, - -20818261, - -32262581, - -37311768, - -34324420, - -23346677, - -6234152, - 13625405, - 31957173, - 44495096, - 47945809, - 40808741, - 23856504, - 140921, - -25513494, - -47455167, - -60412143, - -60710132, - -47229950, - -21869611, - 10631696, - 43519737, - 69370312, - 81696614, - 76484113, - 53307373, - 15747228, - -29042608, - -71597234, - -102026296, - -112167649, - -97565632, - -58831316, - -2036750, - 62029440, - 119693403, - 157031723, - 162840122, - 131357475, - 64171528, - -29147598, - -131921532, - -222701994, - -278742412, - -280032642, - -213184166, - -74440208, - 128790505, - 378234661, - 646928572, - 902966510, - 1114231037, - 1253321369, - 1301843153, - 1253321369, - 1114231037, - 902966510, - 646928572, - 378234661, - 128790505, - -74440208, - -213184166, - -280032642, - -278742412, - -222701994, - -131921532, - -29147598, - 64171528, - 131357475, - 162840122, - 157031723, - 119693403, - 62029440, - -2036750, - -58831316, - -97565632, - -112167649, - -102026296, - -71597234, - -29042608, - 15747228, - 53307373, - 76484113, - 81696614, - 69370312, - 43519737, - 10631696, - -21869611, - -47229950, - -60710132, - -60412143, - -47455167, - -25513494, - 140921, - 23856504, - 40808741, - 47945809, - 44495096, - 31957173, - 13625405, - -6234152, - -23346677, - -34324420, - -37311768, - -32262581, - -20818261, - -5840836, - 9275878, - 21356476, - 28093650, - 28468157, - 22867792, - 12902423, - 976318, - -10274491, - -18551421, - -22349384, - -21211963, - -15747713, - -7421871, - 1815303, - 9973227, - 15439779, - 17288185, - 15416643, - 10504528, - 3808819, - -3143626, - -8895306, - -12355318, - -12995804, - -10915019, - -6764980, - -1570147, - 3515883, - 7459490, - 9550081, - 9518313, - 7553233, - 4222816, - 324045, - -3300873, - -5940791, - -7148614, - -6808166, - -5127174, - -2564887, - 284249, - 2823110, - 4572039, - 5253398, - 4827277, - 3476297, - 1547925, - -529617, - -2337956, - -3547641, - -3970442, - -3579851, - -2496541, - -950161, - 776038, - 2402258, - 3700263, - 4525669, - 4829700, - 4651618, - 4097062, - 3308273, - 2433074, - 1599108, - 897258, - 375196, - 40047, - -132077, - -183049, - -159762, - -145670 - -}; - -struct pdm_decim pdm_decim_int32_06_4156_5100_010_095 = { - 6, 249, 2, 4156, 5100, 10, 95, fir_int32_06_4156_5100_010_095 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_06_4172_5100_010_095.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_06_4172_5100_010_095.h new file mode 100644 index 000000000000..b34905dc3bba --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_06_4172_5100_010_095.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_06_4172_5100_010_095[247] = { + -128632, + -59497, + 27046, + 238561, + 615381, + 1180391, + 1925670, + 2802557, + 3718091, + 4541067, + 5118546, + 5302088, + 4979296, + 4105097, + 2725202, + 985340, + -879509, + -2576724, + -3805615, + -4316339, + -3968132, + -2772637, + -910841, + 1284350, + 3378797, + 4918713, + 5524148, + 4978750, + 3294285, + 731418, + -2230825, + -4978575, + -6884637, + -7446661, + -6411304, + -3856078, + -204820, + 3832851, + 7392855, + 9635554, + 9937191, + 8050966, + 4198476, + -936294, + -6318030, + -10761631, + -13186246, + -12869044, + -9641051, + -3974915, + 3065409, + 10013209, + 15296510, + 17584632, + 16110734, + 10893393, + 2799042, + -6583403, + -15242334, + -21164579, + -22791637, + -19410411, + -11383563, + -154458, + 11993186, + 22385766, + 28535081, + 28717126, + 22423602, + 10572914, + -4585854, + -19878539, + -31852959, + -37539801, + -35162895, + -24634855, + -7708109, + 12278651, + 31033082, + 44206560, + 48374146, + 41881953, + 25360406, + 1761722, + -24123604, + -46603137, + -60296121, + -61373509, + -48548023, + -23572693, + 8903015, + 42138419, + 68642074, + 81792054, + 77398921, + 54859810, + 17614341, + -27257528, + -70279853, + -101467545, + -112499312, + -98729567, + -60589492, + -4020371, + 60241948, + 118486175, + 156668601, + 163407087, + 132743110, + 66089855, + -27096695, + -130167425, + -221612366, + -278546163, + -280773282, + -214713860, + -76455494, + 126679457, + 376416772, + 645705969, + 902489232, + 1114466646, + 1254066162, + 1302772250, + 1254066162, + 1114466646, + 902489232, + 645705969, + 376416772, + 126679457, + -76455494, + -214713860, + -280773282, + -278546163, + -221612366, + -130167425, + -27096695, + 66089855, + 132743110, + 163407087, + 156668601, + 118486175, + 60241948, + -4020371, + -60589492, + -98729567, + -112499312, + -101467545, + -70279853, + -27257528, + 17614341, + 54859810, + 77398921, + 81792054, + 68642074, + 42138419, + 8903015, + -23572693, + -48548023, + -61373509, + -60296121, + -46603137, + -24123604, + 1761722, + 25360406, + 41881953, + 48374146, + 44206560, + 31033082, + 12278651, + -7708109, + -24634855, + -35162895, + -37539801, + -31852959, + -19878539, + -4585854, + 10572914, + 22423602, + 28717126, + 28535081, + 22385766, + 11993186, + -154458, + -11383563, + -19410411, + -22791637, + -21164579, + -15242334, + -6583403, + 2799042, + 10893393, + 16110734, + 17584632, + 15296510, + 10013209, + 3065409, + -3974915, + -9641051, + -12869044, + -13186246, + -10761631, + -6318030, + -936294, + 4198476, + 8050966, + 9937191, + 9635554, + 7392855, + 3832851, + -204820, + -3856078, + -6411304, + -7446661, + -6884637, + -4978575, + -2230825, + 731418, + 3294285, + 4978750, + 5524148, + 4918713, + 3378797, + 1284350, + -910841, + -2772637, + -3968132, + -4316339, + -3805615, + -2576724, + -879509, + 985340, + 2725202, + 4105097, + 4979296, + 5302088, + 5118546, + 4541067, + 3718091, + 2802557, + 1925670, + 1180391, + 615381, + 238561, + 27046, + -59497, + -128632 + +}; + +struct pdm_decim pdm_decim_int32_06_4172_5100_010_095 = { + 6, 247, 2, 4172, 5100, 10, 95, fir_int32_06_4172_5100_010_095 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_08_4156_5301_010_090.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_08_4156_5301_010_090.h new file mode 100644 index 000000000000..aa15e7b741ab --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_08_4156_5301_010_090.h @@ -0,0 +1,263 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_08_4156_5301_010_090[249] = { + -436533, + -30097, + 185136, + 599151, + 1249127, + 2156309, + 3316125, + 4690126, + 6201703, + 7736149, + 9146691, + 10266194, + 10924643, + 10970009, + 10291237, + 8839410, + 6645091, + 3827796, + 595625, + -2767301, + -5925074, + -8524488, + -10235869, + -10797193, + -10055131, + -7997758, + -4771108, + -678235, + 3841448, + 8252025, + 11985305, + 14503017, + 15375105, + 14342998, + 11370408, + 6669744, + 697166, + -5883789, + -12270613, + -17614188, + -21126754, + -22191034, + -20457484, + -15913860, + -8916788, + -176408, + 9306801, + 18349873, + 25728753, + 30337331, + 31343834, + 28324134, + 21351665, + 11028693, + -1551253, + -14908738, + -27343830, + -37144407, + -42813431, + -43283070, + -38091954, + -27492154, + -12471488, + 5321162, + 23744416, + 40410795, + 52985294, + 59498920, + 58637630, + 49965561, + 34048834, + 12455105, + -12379340, + -37407904, + -59331472, + -75016381, + -81921345, + -78477412, + -64367569, + -40661743, + -9779029, + 24730505, + 58569248, + 87201632, + 106433026, + 112987295, + 105007254, + 82406938, + 47020690, + 2512109, + -45960354, + -92298012, + -130180961, + -153871591, + -159007197, + -143278921, + -106903512, + -52811885, + 13489989, + 84396518, + 150980417, + 204001696, + 235041565, + 237634873, + 208265018, + 147093489, + 58319704, + -49897266, + -165975625, + -275876513, + -364417203, + -416806765, + -420248734, + -365439450, + -247794421, + -68258347, + 166406038, + 443903891, + 747260153, + 1056170460, + 1348727100, + 1603354585, + 1800763975, + 1925728602, + 1968501522, + 1925728602, + 1800763975, + 1603354585, + 1348727100, + 1056170460, + 747260153, + 443903891, + 166406038, + -68258347, + -247794421, + -365439450, + -420248734, + -416806765, + -364417203, + -275876513, + -165975625, + -49897266, + 58319704, + 147093489, + 208265018, + 237634873, + 235041565, + 204001696, + 150980417, + 84396518, + 13489989, + -52811885, + -106903512, + -143278921, + -159007197, + -153871591, + -130180961, + -92298012, + -45960354, + 2512109, + 47020690, + 82406938, + 105007254, + 112987295, + 106433026, + 87201632, + 58569248, + 24730505, + -9779029, + -40661743, + -64367569, + -78477412, + -81921345, + -75016381, + -59331472, + -37407904, + -12379340, + 12455105, + 34048834, + 49965561, + 58637630, + 59498920, + 52985294, + 40410795, + 23744416, + 5321162, + -12471488, + -27492154, + -38091954, + -43283070, + -42813431, + -37144407, + -27343830, + -14908738, + -1551253, + 11028693, + 21351665, + 28324134, + 31343834, + 30337331, + 25728753, + 18349873, + 9306801, + -176408, + -8916788, + -15913860, + -20457484, + -22191034, + -21126754, + -17614188, + -12270613, + -5883789, + 697166, + 6669744, + 11370408, + 14342998, + 15375105, + 14503017, + 11985305, + 8252025, + 3841448, + -678235, + -4771108, + -7997758, + -10055131, + -10797193, + -10235869, + -8524488, + -5925074, + -2767301, + 595625, + 3827796, + 6645091, + 8839410, + 10291237, + 10970009, + 10924643, + 10266194, + 9146691, + 7736149, + 6201703, + 4690126, + 3316125, + 2156309, + 1249127, + 599151, + 185136, + -30097, + -436533 + +}; + +struct pdm_decim pdm_decim_int32_08_4156_5301_010_090 = { + 8, 249, 3, 4156, 5301, 10, 90, fir_int32_08_4156_5301_010_090 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_08_4156_5380_010_090.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_08_4156_5380_010_090.h deleted file mode 100644 index 7d2a880b15f8..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_08_4156_5380_010_090.h +++ /dev/null @@ -1,263 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#include <stdint.h> - -const int32_t fir_int32_08_4156_5380_010_090[247] = { - -337052, - -90075, - 37780, - 310298, - 762602, - 1418014, - 2279975, - 3324413, - 4495298, - 5703536, - 6831280, - 7740936, - 8289504, - 8346168, - 7812523, - 6641741, - 4854841, - 2549644, - -98570, - -2847418, - -5407472, - -7472951, - -8758755, - -9040926, - -8192669, - -6213693, - -3246278, - 424677, - 4395972, - 8180309, - 11265189, - 13176475, - 13545386, - 12170147, - 9059463, - 4454447, - -1180491, - -7196755, - -12830960, - -17296055, - -19885729, - -20077500, - -17621714, - -12601266, - -5452197, - 3062539, - 11925735, - 19980775, - 26075722, - 29220338, - 28734576, - 24368837, - 16375791, - 5519930, - -6982346, - -19587960, - -30609997, - -38433685, - -41741838, - -39718804, - -32202058, - -19758650, - -3667506, - 14195787, - 31565234, - 46060011, - 55497992, - 58207057, - 53292128, - 40817642, - 21874421, - -1487369, - -26460171, - -49799428, - -68227825, - -78875217, - -79697543, - -69816864, - -49730377, - -21350328, - 12143051, - 46630130, - 77532435, - 100390923, - 111473843, - 108334402, - 90240198, - 58408793, - 16001822, - -32138446, - -79996329, - -121085165, - -149268412, - -159601418, - -149086287, - -117235239, - -66355092, - -1494553, - 69965597, - 139055884, - 196228005, - 232526458, - 240790250, - 216740138, - 159811182, - 73611998, - -34070591, - -151754583, - -265210746, - -358796902, - -417052464, - -426388521, - -376691518, - -262659116, - -84707915, - 150664267, - 431125422, - 739363099, - 1054476937, - 1353781691, - 1614844650, - 1817552687, - 1945997296, - 1989982406, - 1945997296, - 1817552687, - 1614844650, - 1353781691, - 1054476937, - 739363099, - 431125422, - 150664267, - -84707915, - -262659116, - -376691518, - -426388521, - -417052464, - -358796902, - -265210746, - -151754583, - -34070591, - 73611998, - 159811182, - 216740138, - 240790250, - 232526458, - 196228005, - 139055884, - 69965597, - -1494553, - -66355092, - -117235239, - -149086287, - -159601418, - -149268412, - -121085165, - -79996329, - -32138446, - 16001822, - 58408793, - 90240198, - 108334402, - 111473843, - 100390923, - 77532435, - 46630130, - 12143051, - -21350328, - -49730377, - -69816864, - -79697543, - -78875217, - -68227825, - -49799428, - -26460171, - -1487369, - 21874421, - 40817642, - 53292128, - 58207057, - 55497992, - 46060011, - 31565234, - 14195787, - -3667506, - -19758650, - -32202058, - -39718804, - -41741838, - -38433685, - -30609997, - -19587960, - -6982346, - 5519930, - 16375791, - 24368837, - 28734576, - 29220338, - 26075722, - 19980775, - 11925735, - 3062539, - -5452197, - -12601266, - -17621714, - -20077500, - -19885729, - -17296055, - -12830960, - -7196755, - -1180491, - 4454447, - 9059463, - 12170147, - 13545386, - 13176475, - 11265189, - 8180309, - 4395972, - 424677, - -3246278, - -6213693, - -8192669, - -9040926, - -8758755, - -7472951, - -5407472, - -2847418, - -98570, - 2549644, - 4854841, - 6641741, - 7812523, - 8346168, - 8289504, - 7740936, - 6831280, - 5703536, - 4495298, - 3324413, - 2279975, - 1418014, - 762602, - 310298, - 37780, - -90075, - -337052 - -}; - -struct pdm_decim pdm_decim_int32_08_4156_5380_010_090 = { - 8, 247, 3, 4156, 5380, 10, 90, fir_int32_08_4156_5380_010_090 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_10_4156_5345_010_090.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_10_4156_5345_010_090.h new file mode 100644 index 000000000000..40b73ee3c2f2 --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_10_4156_5345_010_090.h @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_10_4156_5345_010_090[250] = { + 1523665, + 1033186, + 1237912, + 1334775, + 1259136, + 945771, + 330804, + -639430, + -2007230, + -3782603, + -5951062, + -8464725, + -11233139, + -14135396, + -17013193, + -19685639, + -21953913, + -23620153, + -24499971, + -24438406, + -23328862, + -21124651, + -17851431, + -13614282, + -8597813, + -3061758, + 2673313, + 8241850, + 13260214, + 17352951, + 20183225, + 21483036, + 21079871, + 18918865, + 15076270, + 9764507, + 3325641, + -3786831, + -11034844, + -17834361, + -23598518, + -27786005, + -29948197, + -29773031, + -27120493, + -22045821, + -14809184, + -5868041, + 4147420, + 14474606, + 24273606, + 32691772, + 38934943, + 42337380, + 42426833, + 38977193, + 32043932, + 21978645, + 9419218, + -4744590, + -19429341, + -33436251, + -45544284, + -54611932, + -59678078, + -60055175, + -55404949, + -45789928, + -31694490, + -14011800, + 6004287, + 26821132, + 46737621, + 64015881, + 77024918, + 84384267, + 85096503, + 78655977, + 65124057, + 45161629, + 20014065, + -8553289, + -38367257, + -66999907, + -91952963, + -110860336, + -121693302, + -122951962, + -113826153, + -94311463, + -65267325, + -28409399, + 13767679, + 58135590, + 101138413, + 139047421, + 168247614, + 185536046, + 188409622, + 175319624, + 145872050, + 100954938, + 42779310, + -25174601, + -98307054, + -171138928, + -237629824, + -291555223, + -326919157, + -338374861, + -321624361, + -273768560, + -193581379, + -81686484, + 59379271, + 225223665, + 409778420, + 605591661, + 804217132, + 996677146, + 1173970423, + 1327592623, + 1450036054, + 1535235882, + 1578933611, + 1578933611, + 1535235882, + 1450036054, + 1327592623, + 1173970423, + 996677146, + 804217132, + 605591661, + 409778420, + 225223665, + 59379271, + -81686484, + -193581379, + -273768560, + -321624361, + -338374861, + -326919157, + -291555223, + -237629824, + -171138928, + -98307054, + -25174601, + 42779310, + 100954938, + 145872050, + 175319624, + 188409622, + 185536046, + 168247614, + 139047421, + 101138413, + 58135590, + 13767679, + -28409399, + -65267325, + -94311463, + -113826153, + -122951962, + -121693302, + -110860336, + -91952963, + -66999907, + -38367257, + -8553289, + 20014065, + 45161629, + 65124057, + 78655977, + 85096503, + 84384267, + 77024918, + 64015881, + 46737621, + 26821132, + 6004287, + -14011800, + -31694490, + -45789928, + -55404949, + -60055175, + -59678078, + -54611932, + -45544284, + -33436251, + -19429341, + -4744590, + 9419218, + 21978645, + 32043932, + 38977193, + 42426833, + 42337380, + 38934943, + 32691772, + 24273606, + 14474606, + 4147420, + -5868041, + -14809184, + -22045821, + -27120493, + -29773031, + -29948197, + -27786005, + -23598518, + -17834361, + -11034844, + -3786831, + 3325641, + 9764507, + 15076270, + 18918865, + 21079871, + 21483036, + 20183225, + 17352951, + 13260214, + 8241850, + 2673313, + -3061758, + -8597813, + -13614282, + -17851431, + -21124651, + -23328862, + -24438406, + -24499971, + -23620153, + -21953913, + -19685639, + -17013193, + -14135396, + -11233139, + -8464725, + -5951062, + -3782603, + -2007230, + -639430, + 330804, + 945771, + 1259136, + 1334775, + 1237912, + 1033186, + 1523665 + +}; + +struct pdm_decim pdm_decim_int32_10_4156_5345_010_090 = { + 10, 250, 3, 4156, 5345, 10, 90, fir_int32_10_4156_5345_010_090 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_12_4156_5345_010_090.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_12_4156_5345_010_090.h new file mode 100644 index 000000000000..bb8de44010b6 --- /dev/null +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_12_4156_5345_010_090.h @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + */ + +#include <stdint.h> + +const int32_t fir_int32_12_4156_5345_010_090[250] = { + 3388064, + 2103678, + 2588621, + 3003201, + 3289311, + 3375616, + 3187681, + 2654590, + 1715972, + 309000, + -1610211, + -4055571, + -7035886, + -10511174, + -14426105, + -18683424, + -23158811, + -27697959, + -32125744, + -36244313, + -39850668, + -42739502, + -44716782, + -45614286, + -45293362, + -43663492, + -40685637, + -36382432, + -30840569, + -24214188, + -16719141, + -8631481, + -273616, + 7996830, + 15802429, + 22766807, + 28531588, + 32779134, + 35250465, + 35763733, + 34227329, + 30653000, + 25158397, + 17970176, + 9416017, + -86479, + -10047026, + -19926252, + -29162149, + -37200047, + -43523733, + -47686853, + -49340539, + -48260145, + -44362718, + -37720992, + -28567244, + -17289156, + -4416600, + 9400589, + 23423041, + 36858656, + 48904650, + 58793401, + 65836995, + 69472264, + 69298737, + 65111461, + 56923398, + 44977350, + 29744904, + 11913285, + -7641844, + -27894994, + -47720356, + -65950400, + -81438916, + -93127908, + -100112283, + -101700449, + -97465921, + -87287745, + -71375413, + -50277965, + -24873838, + 3657557, + 33882414, + 64176403, + 92802029, + 117997525, + 138071930, + 151502587, + 157029100, + 153740023, + 141145505, + 119233461, + 88503690, + 49978361, + 5186664, + -43876910, + -94819563, + -144940463, + -191340721, + -231048840, + -261155504, + -278952672, + -282068987, + -268596392, + -237200378, + -187208906, + -118674579, + -32406655, + 70029801, + 186348178, + 313607557, + 448310730, + 586528751, + 724047761, + 856530828, + 979688864, + 1089452098, + 1182135271, + 1254588364, + 1304326765, + 1329634160, + 1329634160, + 1304326765, + 1254588364, + 1182135271, + 1089452098, + 979688864, + 856530828, + 724047761, + 586528751, + 448310730, + 313607557, + 186348178, + 70029801, + -32406655, + -118674579, + -187208906, + -237200378, + -268596392, + -282068987, + -278952672, + -261155504, + -231048840, + -191340721, + -144940463, + -94819563, + -43876910, + 5186664, + 49978361, + 88503690, + 119233461, + 141145505, + 153740023, + 157029100, + 151502587, + 138071930, + 117997525, + 92802029, + 64176403, + 33882414, + 3657557, + -24873838, + -50277965, + -71375413, + -87287745, + -97465921, + -101700449, + -100112283, + -93127908, + -81438916, + -65950400, + -47720356, + -27894994, + -7641844, + 11913285, + 29744904, + 44977350, + 56923398, + 65111461, + 69298737, + 69472264, + 65836995, + 58793401, + 48904650, + 36858656, + 23423041, + 9400589, + -4416600, + -17289156, + -28567244, + -37720992, + -44362718, + -48260145, + -49340539, + -47686853, + -43523733, + -37200047, + -29162149, + -19926252, + -10047026, + -86479, + 9416017, + 17970176, + 25158397, + 30653000, + 34227329, + 35763733, + 35250465, + 32779134, + 28531588, + 22766807, + 15802429, + 7996830, + -273616, + -8631481, + -16719141, + -24214188, + -30840569, + -36382432, + -40685637, + -43663492, + -45293362, + -45614286, + -44716782, + -42739502, + -39850668, + -36244313, + -32125744, + -27697959, + -23158811, + -18683424, + -14426105, + -10511174, + -7035886, + -4055571, + -1610211, + 309000, + 1715972, + 2654590, + 3187681, + 3375616, + 3289311, + 3003201, + 2588621, + 2103678, + 3388064 + +}; + +struct pdm_decim pdm_decim_int32_12_4156_5345_010_090 = { + 12, 250, 3, 4156, 5345, 10, 90, fir_int32_12_4156_5345_010_090 +}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_12_4156_6018_010_090.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_12_4156_6018_010_090.h deleted file mode 100644 index 8662af709b07..000000000000 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_int32_12_4156_6018_010_090.h +++ /dev/null @@ -1,255 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -const int32_t fir_int32_12_4156_6018_010_090[241] = { - 314962, - 709564, - 816474, - 1395294, - 1841297, - 2523842, - 3198174, - 3983930, - 4760567, - 5540984, - 6242495, - 6830948, - 7236018, - 7409213, - 7294862, - 6855241, - 6062372, - 4910076, - 3412857, - 1611207, - -429417, - -2618584, - -4844101, - -6976185, - -8874470, - -10396503, - -11407299, - -11789121, - -11451868, - -10342980, - -8455043, - -5831394, - -2568927, - 1181866, - 5222520, - 9314693, - 13192098, - 16575721, - 19192718, - 20794900, - 21178214, - 20201702, - 17803225, - 14010668, - 8949436, - 2842879, - -3994726, - -11170475, - -18232780, - -24697913, - -30079321, - -33921136, - -35832583, - -35519729, - -32814338, - -27696482, - -20307627, - -10955587, - -107030, - 11631605, - 23543158, - 34839849, - 44711664, - 52378576, - 57147364, - 58464306, - 55964858, - 49513162, - 39229018, - 25500353, - 8978376, - -9446673, - -28685271, - -47507955, - -64615363, - -78721214, - -88638504, - -93366828, - -92173696, - -84664063, - -70832479, - -51094971, - -26293298, - 2325527, - 33160341, - 64331225, - 93780584, - 119392064, - 139122267, - 151138511, - 153952683, - 146544581, - 128465090, - 99912102, - 61773380, - 15630736, - -36276081, - -91126422, - -145634732, - -196199513, - -239081694, - -270597744, - -287325458, - -286302172, - -265212584, - -222548033, - -157732643, - -71204480, - 35552627, - 160030161, - 298770593, - 447493387, - 601268344, - 754725438, - 902293927, - 1038455989, - 1158003615, - 1256284590, - 1329424450, - 1374513457, - 1389746873, - 1374513457, - 1329424450, - 1256284590, - 1158003615, - 1038455989, - 902293927, - 754725438, - 601268344, - 447493387, - 298770593, - 160030161, - 35552627, - -71204480, - -157732643, - -222548033, - -265212584, - -286302172, - -287325458, - -270597744, - -239081694, - -196199513, - -145634732, - -91126422, - -36276081, - 15630736, - 61773380, - 99912102, - 128465090, - 146544581, - 153952683, - 151138511, - 139122267, - 119392064, - 93780584, - 64331225, - 33160341, - 2325527, - -26293298, - -51094971, - -70832479, - -84664063, - -92173696, - -93366828, - -88638504, - -78721214, - -64615363, - -47507955, - -28685271, - -9446673, - 8978376, - 25500353, - 39229018, - 49513162, - 55964858, - 58464306, - 57147364, - 52378576, - 44711664, - 34839849, - 23543158, - 11631605, - -107030, - -10955587, - -20307627, - -27696482, - -32814338, - -35519729, - -35832583, - -33921136, - -30079321, - -24697913, - -18232780, - -11170475, - -3994726, - 2842879, - 8949436, - 14010668, - 17803225, - 20201702, - 21178214, - 20794900, - 19192718, - 16575721, - 13192098, - 9314693, - 5222520, - 1181866, - -2568927, - -5831394, - -8455043, - -10342980, - -11451868, - -11789121, - -11407299, - -10396503, - -8874470, - -6976185, - -4844101, - -2618584, - -429417, - 1611207, - 3412857, - 4910076, - 6062372, - 6855241, - 7294862, - 7409213, - 7236018, - 6830948, - 6242495, - 5540984, - 4760567, - 3983930, - 3198174, - 2523842, - 1841297, - 1395294, - 816474, - 709564, - 314962 - -}; - -struct pdm_decim pdm_decim_int32_12_4156_6018_010_090 = { - 12, 241, 3, 4156, 6018, 10, 90, fir_int32_12_4156_6018_010_090 -}; diff --git a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_table.h b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_table.h index c1d01d30ceb2..cfd4368bba3e 100644 --- a/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_table.h +++ b/src/include/sof/audio/coefficients/pdm_decim/pdm_decim_table.h @@ -11,61 +11,73 @@ #define __SOF_AUDIO_COEFFICIENTS_PDM_DECIM_PDM_DECIM_TABLE_H__ #include "pdm_decim_fir.h" -#include <config.h> + #include <stddef.h> -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_2 -#include "pdm_decim_int32_02_4288_5100_010_095.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_2 +#include "pdm_decim_int32_02_4323_5100_010_095.h" #include "pdm_decim_int32_02_4375_5100_010_095.h" #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_3 -#include "pdm_decim_int32_03_3850_5100_010_095.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_3 #include "pdm_decim_int32_03_4375_5100_010_095.h" #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_4 -#include "pdm_decim_int32_04_4375_5100_010_095.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_4 +#include "pdm_decim_int32_04_4318_5100_010_095.h" +#endif +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_5 +#include "pdm_decim_int32_05_4325_5100_010_095.h" #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_5 -#include "pdm_decim_int32_05_4331_5100_010_095.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_6 +#include "pdm_decim_int32_06_4172_5100_010_095.h" #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_6 -#include "pdm_decim_int32_06_4156_5100_010_095.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_8 +#include "pdm_decim_int32_08_4156_5301_010_090.h" #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_8 -#include "pdm_decim_int32_08_4156_5380_010_090.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_10 +#include "pdm_decim_int32_10_4156_5345_010_090.h" #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_12 -#include "pdm_decim_int32_12_4156_6018_010_090.h" +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_12 +#include "pdm_decim_int32_12_4156_5345_010_090.h" #endif -/* Note: Higher spec filter must be before lower spec filter - * if there are multiple filters for a decimation factor. The naming - * scheme of coefficients set is: +/* Note 1: Higher spec filter must be before lower spec filter + * if there are multiple filters for a decimation factor. The first + * filter is skipped if the length is too much vs. overrun limit. If + * other order the better filter would be never selected. + * + * Note 2: The introduction order of FIR decimation factors is the selection + * preference order. The decimation factor 5 and 10 (2*5) cause a often less + * compatible output sample rate for CIC so they are not used if there other + * suitable nearby values. + * + * The naming scheme of coefficients set is: * <type>_<decim factor>_<rel passband>_<rel stopband>_<ripple>_<attenuation> */ struct pdm_decim *fir_list[] = { -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_2 +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_2 &pdm_decim_int32_02_4375_5100_010_095, - &pdm_decim_int32_02_4288_5100_010_095, + &pdm_decim_int32_02_4323_5100_010_095, #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_3 +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_3 &pdm_decim_int32_03_4375_5100_010_095, - &pdm_decim_int32_03_3850_5100_010_095, #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_4 - &pdm_decim_int32_04_4375_5100_010_095, +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_4 + &pdm_decim_int32_04_4318_5100_010_095, +#endif +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_6 + &pdm_decim_int32_06_4172_5100_010_095, #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_5 - &pdm_decim_int32_05_4331_5100_010_095, +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_5 + &pdm_decim_int32_05_4325_5100_010_095, #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_6 - &pdm_decim_int32_06_4156_5100_010_095, +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_8 + &pdm_decim_int32_08_4156_5301_010_090, #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_8 - &pdm_decim_int32_08_4156_5380_010_090, +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_12 + &pdm_decim_int32_12_4156_5345_010_090, #endif -#if CONFIG_CAVS_DMIC_FIR_DECIMATE_BY_12 - &pdm_decim_int32_12_4156_6018_010_090, +#if CONFIG_INTEL_DMIC_FIR_DECIMATE_BY_10 + &pdm_decim_int32_10_4156_5345_010_090, #endif NULL, /* This marks the end of coefficients */ }; diff --git a/src/include/sof/audio/coefficients/src/src_std_int32_table.h b/src/include/sof/audio/coefficients/src/src_std_int32_table.h deleted file mode 100644 index 06a7965a382c..000000000000 --- a/src/include/sof/audio/coefficients/src/src_std_int32_table.h +++ /dev/null @@ -1,227 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_STD_INT32_TABLE_H__ -#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_STD_INT32_TABLE_H__ - -/* SRC conversions */ -#include <sof/audio/coefficients/src/src_std_int32_1_2_2268_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_1_2_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_1_3_2268_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_1_3_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_2_1_2268_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_2_1_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_2_3_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_3_1_2268_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_3_1_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_3_2_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_3_4_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_4_3_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_4_5_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_5_4_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_5_6_4354_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_5_7_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_6_5_4354_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_7_8_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_8_7_2468_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_8_7_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_8_21_3239_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_10_21_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_20_7_2976_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_20_21_4167_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_21_20_4167_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_21_40_3968_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_21_80_3968_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_32_21_4535_5000.h> -#include <sof/audio/coefficients/src/src_std_int32_40_21_3968_5000.h> -#include <sof/audio/src/src.h> -#include <stdint.h> - -/* SRC table */ -int32_t fir_one = 1073741824; -struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; -struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; -int src_in_fs[15] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, - 48000, 50000, 64000, 88200, 96000, 176400, 192000}; -int src_out_fs[10] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, - 48000, 50000}; -struct src_stage *src_table1[10][15] = { - { &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_1_2_4535_5000, - &src_int32_0_0_0_0, &src_int32_1_3_4535_5000, - &src_int32_1_2_2268_5000, &src_int32_0_0_0_0, - &src_int32_1_3_2268_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_21_80_3968_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_2_2268_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_2_1_4535_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_2_3_4535_5000, &src_int32_1_2_4535_5000, - &src_int32_0_0_0_0, &src_int32_1_3_4535_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_21_40_3968_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_3_1_4535_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_3_2_4535_5000, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_3_4_4535_5000, - &src_int32_0_0_0_0, &src_int32_1_2_4535_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_2_1_4535_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_2_1_4535_5000, - &src_int32_0_0_0_0, &src_int32_4_3_4535_5000, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_2_3_4535_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_21_20_4167_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_2_1_4535_5000, &src_int32_32_21_4535_5000, - &src_int32_2_1_4535_5000, &src_int32_3_1_4535_5000, - &src_int32_8_7_4535_5000, &src_int32_2_1_4535_5000, - &src_int32_3_2_4535_5000, &src_int32_8_7_4535_5000, - &src_int32_1_1_0_0, &src_int32_6_5_4354_5000, - &src_int32_3_4_4535_5000, &src_int32_8_7_2468_5000, - &src_int32_1_2_4535_5000, &src_int32_8_21_3239_5000, - &src_int32_1_2_2268_5000}, - { &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_5_4_4535_5000, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - } -}; -struct src_stage *src_table2[10][15] = { - { &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_1_1_0_0, - &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, - &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_7_8_4535_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_2_4535_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_7_8_4535_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_2_1_2268_5000, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_1_1_0_0, - &src_int32_0_0_0_0, &src_int32_1_1_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0}, - { &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_1_1_0_0, &src_int32_7_8_4535_5000, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - }, - { &src_int32_3_1_2268_5000, &src_int32_20_7_2976_5000, - &src_int32_2_1_2268_5000, &src_int32_1_1_0_0, - &src_int32_40_21_3968_5000, &src_int32_1_1_0_0, - &src_int32_1_1_0_0, &src_int32_20_21_4167_5000, - &src_int32_1_1_0_0, &src_int32_4_5_4535_5000, - &src_int32_1_1_0_0, &src_int32_10_21_4535_5000, - &src_int32_1_1_0_0, &src_int32_5_7_4535_5000, - &src_int32_1_2_4535_5000}, - { &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_5_6_4354_5000, - &src_int32_1_1_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0, - &src_int32_0_0_0_0, &src_int32_0_0_0_0 - } -}; - -#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_STD_INT32_TABLE_H__ */ diff --git a/src/include/sof/audio/coefficients/src/src_tiny_int16_table.h b/src/include/sof/audio/coefficients/src/src_tiny_int16_table.h deleted file mode 100644 index 49b2ba08e7e4..000000000000 --- a/src/include/sof/audio/coefficients/src/src_tiny_int16_table.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_TABLE_H__ -#define __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_TABLE_H__ - -/* SRC conversions */ -#include <sof/audio/coefficients/src/src_tiny_int16_1_3_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_1_6_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_2_3_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_3_1_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_3_2_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_6_1_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_7_8_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_8_7_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_20_21_1667_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_21_20_1667_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_24_25_1814_5000.h> -#include <sof/audio/coefficients/src/src_tiny_int16_25_24_1814_5000.h> -#include <sof/audio/src/src.h> -#include <stdint.h> - -/* SRC table */ -int16_t fir_one = 16384; -struct src_stage src_int16_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one }; -struct src_stage src_int16_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one }; -int src_in_fs[6] = { 8000, 16000, 32000, 44100, 48000, 50000}; -int src_out_fs[6] = { 8000, 16000, 32000, 44100, 48000, 50000}; -struct src_stage *src_table1[6][6] = { - { &src_int16_1_1_0_0, &src_int16_0_0_0_0, - &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_6_1814_5000, &src_int16_0_0_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_1_1_0_0, - &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_3_1814_5000, &src_int16_0_0_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_1_0_0, &src_int16_0_0_0_0, - &src_int16_2_3_1814_5000, &src_int16_0_0_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_0_0_0_0, &src_int16_1_1_0_0, - &src_int16_21_20_1667_5000, &src_int16_0_0_0_0 - }, - { &src_int16_6_1_1814_5000, &src_int16_3_1_1814_5000, - &src_int16_3_2_1814_5000, &src_int16_8_7_1814_5000, - &src_int16_1_1_0_0, &src_int16_24_25_1814_5000 - }, - { &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_25_24_1814_5000, &src_int16_1_1_0_0 - } -}; -struct src_stage *src_table2[6][6] = { - { &src_int16_1_1_0_0, &src_int16_0_0_0_0, - &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_1_0_0, &src_int16_0_0_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_1_1_0_0, - &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_1_0_0, &src_int16_0_0_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_1_0_0, &src_int16_0_0_0_0, - &src_int16_1_1_0_0, &src_int16_0_0_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_0_0_0_0, &src_int16_1_1_0_0, - &src_int16_7_8_1814_5000, &src_int16_0_0_0_0 - }, - { &src_int16_1_1_0_0, &src_int16_1_1_0_0, - &src_int16_1_1_0_0, &src_int16_20_21_1667_5000, - &src_int16_1_1_0_0, &src_int16_1_1_0_0 - }, - { &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_0_0_0_0, &src_int16_0_0_0_0, - &src_int16_1_1_0_0, &src_int16_1_1_0_0 - } -}; - -#endif /* __SOF_AUDIO_COEFFICIENTS_SRC_SRC_TINY_INT16_TABLE_H__ */ diff --git a/src/include/sof/audio/coefficients/volume/windows_fade.h b/src/include/sof/audio/coefficients/volume/windows_fade.h new file mode 100644 index 000000000000..3d065a93b919 --- /dev/null +++ b/src/include/sof/audio/coefficients/volume/windows_fade.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#include <sof/audio/format.h> +#include <stdint.h> + +#if CONFIG_COMP_VOLUME_WINDOWS_FADE + +#define WINDOWS_FADE_LUT_SIZE 128 +#define WINDOWS_FADE_LUT_STEP \ + Q_CONVERT_FLOAT(1.0 / (WINDOWS_FADE_LUT_SIZE - 1), 30) /* Q2.30 */ + +/* Calculate power y = x^1.75, input and output are in Q2.30 format */ + +static const int16_t windows_fade_lookup[WINDOWS_FADE_LUT_SIZE] = { + 0x0000, 0x0007, 0x0017, 0x002f, 0x004d, 0x0072, 0x009d, 0x00cd, + 0x0104, 0x013f, 0x0180, 0x01c5, 0x0210, 0x025f, 0x02b3, 0x030c, + 0x0369, 0x03cb, 0x0431, 0x049b, 0x050a, 0x057d, 0x05f4, 0x066f, + 0x06ef, 0x0772, 0x07fa, 0x0885, 0x0914, 0x09a8, 0x0a3f, 0x0ada, + 0x0b78, 0x0c1b, 0x0cc1, 0x0d6b, 0x0e18, 0x0eca, 0x0f7f, 0x1037, + 0x10f3, 0x11b3, 0x1276, 0x133d, 0x1407, 0x14d4, 0x15a5, 0x167a, + 0x1752, 0x182d, 0x190c, 0x19ee, 0x1ad4, 0x1bbc, 0x1ca8, 0x1d98, + 0x1e8a, 0x1f80, 0x207a, 0x2176, 0x2276, 0x2379, 0x247f, 0x2588, + 0x2695, 0x27a4, 0x28b7, 0x29cd, 0x2ae6, 0x2c02, 0x2d22, 0x2e44, + 0x2f69, 0x3092, 0x31be, 0x32ec, 0x341e, 0x3553, 0x368a, 0x37c5, + 0x3903, 0x3a44, 0x3b87, 0x3cce, 0x3e18, 0x3f64, 0x40b4, 0x4207, + 0x435c, 0x44b4, 0x4610, 0x476e, 0x48cf, 0x4a33, 0x4b9a, 0x4d04, + 0x4e70, 0x4fe0, 0x5152, 0x52c7, 0x543f, 0x55ba, 0x5738, 0x58b8, + 0x5a3b, 0x5bc2, 0x5d4a, 0x5ed6, 0x6065, 0x61f6, 0x638a, 0x6521, + 0x66ba, 0x6856, 0x69f5, 0x6b97, 0x6d3c, 0x6ee3, 0x708d, 0x723a, + 0x73e9, 0x759b, 0x7750, 0x7907, 0x7ac1, 0x7c7e, 0x7e3e, 0x7fff, +}; + +static inline int32_t volume_pow_175(int32_t val) +{ + int32_t y0; + int32_t y1; + int32_t dx; + int32_t c; + int32_t y; + int i; + + if (val == 0) + return 0; + + i = Q_MULTS_32X32((int64_t)val, WINDOWS_FADE_LUT_SIZE - 1, 30, 0, 0); + if (i >= WINDOWS_FADE_LUT_SIZE - 1) + return Q_CONVERT_FLOAT(1, 30); + + y0 = windows_fade_lookup[i]; + y1 = windows_fade_lookup[i + 1]; + c = (y1 - y0) * (WINDOWS_FADE_LUT_SIZE - 1); /* Q1.15 */ + dx = val - i * WINDOWS_FADE_LUT_STEP; /* Q2.30 */ + y = Q_SHIFT_LEFT(y0, 15, 30) + Q_MULTSR_32X32((int64_t)dx, c, 30, 15, 30); + return y; +} + +#endif /* CONFIG_COMP_VOLUME_WINDOWS_FADE */ + diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 084c05fb1223..7fc9feb53736 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -19,32 +19,23 @@ #include <sof/audio/buffer.h> #include <sof/audio/format.h> #include <sof/audio/pipeline.h> -#include <sof/debug/panic.h> -#include <sof/drivers/idc.h> -#include <sof/list.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cpu.h> +#include <sof/debug/telemetry/telemetry.h> +#include <rtos/idc.h> +#include <rtos/mutex.h> +#include <rtos/userspace_helper.h> #include <sof/lib/dai.h> -#include <sof/lib/memory.h> -#include <sof/math/numbers.h> #include <sof/schedule/schedule.h> -#include <sof/sof.h> -#include <sof/trace/trace.h> #include <ipc/control.h> -#include <ipc/stream.h> -#include <ipc/topology.h> +#include <sof/ipc/topology.h> #include <kernel/abi.h> -#include <user/trace.h> -#include <config.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> + +#include <limits.h> struct comp_dev; -struct sof_ipc_dai_config; struct sof_ipc_stream_posn; struct dai_hw_params; +struct timestamp_data; +struct dai_ts_data; /** \addtogroup component_api Component API * @{ @@ -57,27 +48,41 @@ struct dai_hw_params; /** \name Audio Component States * @{ */ -#define COMP_STATE_INIT 0 /**< Component being initialised */ -#define COMP_STATE_READY 1 /**< Component inactive, but ready */ -#define COMP_STATE_SUSPEND 2 /**< Component suspended */ -#define COMP_STATE_PREPARE 3 /**< Component prepared */ -#define COMP_STATE_PAUSED 4 /**< Component paused */ -#define COMP_STATE_ACTIVE 5 /**< Component active */ +#define COMP_STATE_NOT_EXIST 0 /**< Component does not exist */ +#define COMP_STATE_INIT 1 /**< Component being initialised */ +#define COMP_STATE_READY 2 /**< Component inactive, but ready */ +#define COMP_STATE_SUSPEND 3 /**< Component suspended */ +#define COMP_STATE_PREPARE 4 /**< Component prepared */ +#define COMP_STATE_PAUSED 5 /**< Component paused */ +#define COMP_STATE_ACTIVE 6 /**< Component active */ +#define COMP_STATE_PRE_ACTIVE 7 /**< Component after early initialisation */ /** @}*/ /** \name Standard Component Stream Commands * TODO: use IPC versions after 1.1 + * + * Most component stream commands match one-to-one IPC stream trigger commands. + * However we add two PRE_ and two POST_ commands to the set. They are issued + * internally without matching IPC commands. A single START IPC command is + * translated into a sequence of PRE_START and START component commands, etc. + * POST_* commands aren't used so far. + * * @{ */ -#define COMP_TRIGGER_STOP 0 /**< Stop component stream */ -#define COMP_TRIGGER_START 1 /**< Start component stream */ -#define COMP_TRIGGER_PAUSE 2 /**< Pause the component stream */ -#define COMP_TRIGGER_RELEASE 3 /**< Release paused component stream */ -#define COMP_TRIGGER_SUSPEND 4 /**< Suspend component */ -#define COMP_TRIGGER_RESUME 5 /**< Resume component */ -#define COMP_TRIGGER_RESET 6 /**< Reset component */ -#define COMP_TRIGGER_PREPARE 7 /**< Prepare component */ -#define COMP_TRIGGER_XRUN 8 /**< XRUN component */ +enum { + COMP_TRIGGER_STOP, /**< Stop component stream */ + COMP_TRIGGER_START, /**< Start component stream */ + COMP_TRIGGER_PAUSE, /**< Pause the component stream */ + COMP_TRIGGER_RELEASE, /**< Release paused component stream */ + COMP_TRIGGER_RESET, /**< Reset component */ + COMP_TRIGGER_PREPARE, /**< Prepare component */ + COMP_TRIGGER_XRUN, /**< XRUN component */ + COMP_TRIGGER_PRE_START, /**< Prepare to start component stream */ + COMP_TRIGGER_PRE_RELEASE, /**< Prepare to release paused component stream */ + COMP_TRIGGER_POST_STOP, /**< Finalize stop component stream */ + COMP_TRIGGER_POST_PAUSE, /**< Finalize pause component stream */ + COMP_TRIGGER_NO_ACTION, /**< No action required */ +}; /** @}*/ /** \name Standard Component Control Commands @@ -113,14 +118,18 @@ struct dai_hw_params; */ #define COMP_ATTR_COPY_TYPE 0 /**< Comp copy type attribute */ #define COMP_ATTR_HOST_BUFFER 1 /**< Comp host buffer attribute */ +#define COMP_ATTR_COPY_DIR 2 /**< Comp copy direction */ +#define COMP_ATTR_VDMA_INDEX 3 /**< Comp index of the virtual DMA at the gateway. */ +#define COMP_ATTR_BASE_CONFIG 4 /**< Component base config */ +#define COMP_ATTR_IPC4_CONFIG 5 /**< Component ipc4 set/get config */ /** @}*/ /** \name Trace macros * @{ */ -/** \brief Retrieves uid from the component driver */ -#define trace_comp_drv_get_uid(drv_p) ((drv_p)->uid) +/** \brief Retrieves trace context from the component driver */ +#define trace_comp_drv_get_tr_ctx(drv_p) ((drv_p)->tctx) /** \brief Retrieves id (-1 = undefined) from the component driver */ #define trace_comp_drv_get_id(drv_p) (-1) @@ -128,75 +137,116 @@ struct dai_hw_params; /** \brief Retrieves subid (-1 = undefined) from the component driver */ #define trace_comp_drv_get_subid(drv_p) (-1) -/** \brief Retrieves uid from the component device */ -#define trace_comp_get_uid(comp_p) ((comp_p)->drv->uid) +/** \brief Retrieves trace context from the component device */ +#define trace_comp_get_tr_ctx(comp_p) (&(comp_p)->tctx) /** \brief Retrieves id (pipe id) from the component device */ -#define trace_comp_get_id(comp_p) ((comp_p)->comp.pipeline_id) +#define trace_comp_get_id(comp_p) ((comp_p)->ipc_config.pipeline_id) /** \brief Retrieves subid (comp id) from the component device */ -#define trace_comp_get_subid(comp_p) ((comp_p)->comp.id) +#define trace_comp_get_subid(comp_p) ((comp_p)->ipc_config.id) +#if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) +/* class (driver) level (no device object) tracing */ +#define comp_cl_err(drv_p, __e, ...) LOG_ERR(__e, ##__VA_ARGS__) + +#define comp_cl_warn(drv_p, __e, ...) LOG_WRN(__e, ##__VA_ARGS__) + +#define comp_cl_info(drv_p, __e, ...) LOG_INF(__e, ##__VA_ARGS__) + +#define comp_cl_dbg(drv_p, __e, ...) LOG_DBG(__e, ##__VA_ARGS__) + +/* device level tracing */ + +#if CONFIG_IPC_MAJOR_4 +#define __COMP_FMT "comp:%u %#x " +#else +#define __COMP_FMT "comp:%u.%u " +#endif + +#define comp_err(comp_p, __e, ...) LOG_ERR(__COMP_FMT __e, trace_comp_get_id(comp_p), \ + trace_comp_get_subid(comp_p), ##__VA_ARGS__) + +#define comp_warn(comp_p, __e, ...) LOG_WRN(__COMP_FMT __e, trace_comp_get_id(comp_p), \ + trace_comp_get_subid(comp_p), ##__VA_ARGS__) + +#define comp_info(comp_p, __e, ...) LOG_INF(__COMP_FMT __e, trace_comp_get_id(comp_p), \ + trace_comp_get_subid(comp_p), ##__VA_ARGS__) + +#define comp_dbg(comp_p, __e, ...) LOG_DBG(__COMP_FMT __e, trace_comp_get_id(comp_p), \ + trace_comp_get_subid(comp_p), ##__VA_ARGS__) + +#else /* class (driver) level (no device object) tracing */ /** \brief Trace error message from component driver (no comp instance) */ -#define comp_cl_err(drv_p, __e, ...) \ - trace_dev_err(TRACE_CLASS_COMP, \ - trace_comp_drv_get_uid, \ - trace_comp_drv_get_id, \ - trace_comp_drv_get_subid, \ - drv_p, \ +#define comp_cl_err(drv_p, __e, ...) \ + trace_dev_err(trace_comp_drv_get_tr_ctx, \ + trace_comp_drv_get_id, \ + trace_comp_drv_get_subid, \ + drv_p, \ __e, ##__VA_ARGS__) /** \brief Trace warning message from component driver (no comp instance) */ -#define comp_cl_warn(drv_p, __e, ...) \ - trace_dev_warn(TRACE_CLASS_COMP, \ - trace_comp_drv_get_uid, \ - trace_comp_drv_get_id, \ - trace_comp_drv_get_subid,\ - drv_p, \ +#define comp_cl_warn(drv_p, __e, ...) \ + trace_dev_warn(trace_comp_drv_get_tr_ctx, \ + trace_comp_drv_get_id, \ + trace_comp_drv_get_subid, \ + drv_p, \ __e, ##__VA_ARGS__) /** \brief Trace info message from component driver (no comp instance) */ -#define comp_cl_info(drv_p, __e, ...) \ - trace_dev_info(TRACE_CLASS_COMP, \ - trace_comp_drv_get_uid, \ - trace_comp_drv_get_id, \ - trace_comp_drv_get_subid,\ - drv_p, \ +#define comp_cl_info(drv_p, __e, ...) \ + trace_dev_info(trace_comp_drv_get_tr_ctx, \ + trace_comp_drv_get_id, \ + trace_comp_drv_get_subid, \ + drv_p, \ __e, ##__VA_ARGS__) /** \brief Trace debug message from component driver (no comp instance) */ -#define comp_cl_dbg(drv_p, __e, ...) \ - trace_dev_dbg(TRACE_CLASS_COMP, \ - trace_comp_drv_get_uid, \ - trace_comp_drv_get_id, \ - trace_comp_drv_get_subid, \ - drv_p, \ +#define comp_cl_dbg(drv_p, __e, ...) \ + trace_dev_dbg(trace_comp_drv_get_tr_ctx, \ + trace_comp_drv_get_id, \ + trace_comp_drv_get_subid, \ + drv_p, \ __e, ##__VA_ARGS__) /* device tracing */ /** \brief Trace error message from component device */ #define comp_err(comp_p, __e, ...) \ - trace_dev_err(TRACE_CLASS_COMP, trace_comp_get_uid, trace_comp_get_id, \ + trace_dev_err(trace_comp_get_tr_ctx, trace_comp_get_id, \ trace_comp_get_subid, comp_p, __e, ##__VA_ARGS__) /** \brief Trace warning message from component device */ #define comp_warn(comp_p, __e, ...) \ - trace_dev_warn(TRACE_CLASS_COMP, trace_comp_get_uid, trace_comp_get_id,\ + trace_dev_warn(trace_comp_get_tr_ctx, trace_comp_get_id, \ trace_comp_get_subid, comp_p, __e, ##__VA_ARGS__) /** \brief Trace info message from component device */ #define comp_info(comp_p, __e, ...) \ - trace_dev_info(TRACE_CLASS_COMP, trace_comp_get_uid, trace_comp_get_id,\ + trace_dev_info(trace_comp_get_tr_ctx, trace_comp_get_id, \ trace_comp_get_subid, comp_p, __e, ##__VA_ARGS__) /** \brief Trace debug message from component device */ #define comp_dbg(comp_p, __e, ...) \ - trace_dev_dbg(TRACE_CLASS_COMP, trace_comp_get_uid, trace_comp_get_id, \ + trace_dev_dbg(trace_comp_get_tr_ctx, trace_comp_get_id, \ trace_comp_get_subid, comp_p, __e, ##__VA_ARGS__) +#endif /* #if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) */ + +#define comp_perf_info(pcd, comp_p) \ + comp_info(comp_p, "perf comp_copy peak plat %u cpu %u", \ + (uint32_t)((pcd)->plat_delta_peak), \ + (uint32_t)((pcd)->cpu_delta_peak)) + +#define comp_perf_avg_info(pcd, comp_p) \ + comp_info(comp_p, "perf comp_copy samples %u period %u cpu avg %u peak %u %u",\ + (uint32_t)((comp_p)->frames), \ + (uint32_t)((comp_p)->period), \ + (uint32_t)((pcd)->cpu_delta_sum), \ + (uint32_t)((pcd)->cpu_delta_peak), \ + (uint32_t)((pcd)->peak_mcps_period_cnt)) /** @}*/ @@ -214,12 +264,49 @@ enum comp_endpoint_type { * to comp_set_attribute(). */ enum comp_copy_type { + COMP_COPY_INVALID = -1, /**< Invalid */ COMP_COPY_NORMAL = 0, /**< Normal */ COMP_COPY_BLOCKING, /**< Blocking */ COMP_COPY_ONE_SHOT, /**< One-shot */ }; struct comp_driver; +struct comp_ipc_config; +union ipc_config_specific; +struct ipc4_module_bind_unbind; + +enum bind_type { + COMP_BIND_TYPE_SOURCE, + COMP_BIND_TYPE_SINK +}; + +struct bind_info { + /* pointer to IPC4 bind/unbind data */ + struct ipc4_module_bind_unbind *ipc4_data; + + /* type of binding + * bind call will be called twice for every component, first when binding a data source, + * than when binding data sink. + * + * bind_type is indicating type of binding + */ + enum bind_type bind_type; + + /* pointers to sink or source API of the data provider/consumer + * that is being bound to the module + * + * if bind_type == COMP_BIND_TYPE_SOURCE, the pointer points to source being bound/unbound + * if bind_type == COMP_BIND_TYPE_SINK, the pointer points to sink being bound/unbound + * + * NOTE! As in pipeline2.0 there may be a binding between modules, + * without a buffer in between, it cannot be a pointer to any buffer type, module should + * use sink/source API + */ + union { + struct sof_source *source; + struct sof_sink *sink; + }; +}; /** * Audio component operations. @@ -232,19 +319,20 @@ struct comp_ops { /** * Creates a new component device. * @param drv Parent component driver. - * @param comp Component parameters. + * @param ipc_config Component parameters. + * @param spec Pointer to initialization data * @return Pointer to the new component device. * - * All required data objects should be allocated from the run-time - * heap (RZONE_RUNTIME). * Any component-specific private data is allocated separately and * pointer is connected to the comp_dev::private by using * comp_set_drvdata() and later retrieved by comp_get_drvdata(). * * All parameters should be initialized to their default values. + * Usually can be __cold. */ - struct comp_dev *(*new)(const struct comp_driver *drv, - struct sof_ipc_comp *comp); + struct comp_dev *(*create)(const struct comp_driver *drv, + const struct comp_ipc_config *ipc_config, + const void *spec); /** * Called to delete the specified component device. @@ -252,6 +340,7 @@ struct comp_ops { * * All data structures previously allocated on the run-time heap * must be freed by the implementation of <code>free()</code>. + * Usually can be __cold. */ void (*free)(struct comp_dev *dev); @@ -259,6 +348,11 @@ struct comp_ops { * Sets component audio stream parameters. * @param dev Component device. * @param params Audio (PCM) stream parameters to be set. + * + * Infrastructure calls comp_verify_params() if this handler is not + * defined, therefore it should be left NULL if no extra steps are + * required. + * Usually shouldn't be __cold. */ int (*params)(struct comp_dev *dev, struct sof_ipc_stream_params *params); @@ -271,6 +365,7 @@ struct comp_ops { * @param dir Stream direction (see enum sof_ipc_stream_direction). * * Mandatory for components that allocate DAI. + * Usually can be __cold. */ int (*dai_get_hw_params)(struct comp_dev *dev, struct sof_ipc_stream_params *params, int dir); @@ -281,10 +376,12 @@ struct comp_ops { * @param dai_config DAI configuration. * * Mandatory for components that allocate DAI. + * Usually can be __cold. */ - int (*dai_config)(struct comp_dev *dev, - struct sof_ipc_dai_config *dai_config); + int (*dai_config)(struct dai_data *dd, struct comp_dev *dev, + struct ipc_config_dai *dai_config, const void *dai_spec_config); +#if CONFIG_IPC_MAJOR_3 || CONFIG_LIBRARY /** * Used to pass standard and bespoke commands (with optional data). * @param dev Component device. @@ -295,23 +392,34 @@ struct comp_ops { */ int (*cmd)(struct comp_dev *dev, int cmd, void *data, int max_data_size); +#endif /** * Trigger, atomic - used to start/stop/pause stream operations. * @param dev Component device. * @param cmd Command, one of COMP_TRIGGER_... + * + * Usually shouldn't be __cold. */ int (*trigger)(struct comp_dev *dev, int cmd); /** * Prepares component after params are set. * @param dev Component device. + * + * Prepare should be used to get the component ready for starting + * processing after it's hw_params are known or after an XRUN. + * Usually shouldn't be __cold. */ int (*prepare)(struct comp_dev *dev); /** * Resets component. * @param dev Component device. + * + * Resets the component state and any hw_params to default component + * state. Should also free any resources acquired during hw_params. + * Usually shouldn't be __cold. */ int (*reset)(struct comp_dev *dev); @@ -319,6 +427,8 @@ struct comp_ops { * Copy and process stream data from source to sink buffers. * @param dev Component device. * @return Number of copied frames. + * + * Usually shouldn't be __cold. */ int (*copy)(struct comp_dev *dev); @@ -326,16 +436,32 @@ struct comp_ops { * Retrieves component rendering position. * @param dev Component device. * @param posn Receives reported position. + * + * Usually shouldn't be __cold. */ int (*position)(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); + /** + * Gets attribute in component. + * @param dev Component device. + * @param type Attribute type. + * @param value Attribute value. + * @return 0 if succeeded, error code otherwise. + * + * Usually can be __cold. + */ + int (*get_attribute)(struct comp_dev *dev, uint32_t type, + void *value); + /** * Sets attribute in component. * @param dev Component device. * @param type Attribute type. * @param value Attribute value. * @return 0 if succeeded, error code otherwise. + * + * Usually can be __cold. */ int (*set_attribute)(struct comp_dev *dev, uint32_t type, void *value); @@ -345,6 +471,7 @@ struct comp_ops { * @param dev Component device. * * Mandatory for components that allocate DAI. + * Usually can be __cold. */ int (*dai_ts_config)(struct comp_dev *dev); @@ -353,6 +480,7 @@ struct comp_ops { * @param dev Component device. * * Mandatory for components that allocate DAI. + * Usually can be __cold. */ int (*dai_ts_start)(struct comp_dev *dev); @@ -361,6 +489,7 @@ struct comp_ops { * @param dev Component device. * * Mandatory for components that allocate DAI. + * Usually can be __cold. */ int (*dai_ts_stop)(struct comp_dev *dev); @@ -370,9 +499,91 @@ struct comp_ops { * @param tsd Receives timestamp data. * * Mandatory for components that allocate DAI. + * Usually shouldn't be __cold. */ +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + int (*dai_ts_get)(struct comp_dev *dev, struct dai_ts_data *tsd); +#else int (*dai_ts_get)(struct comp_dev *dev, struct timestamp_data *tsd); +#endif + + /** + * Bind, atomic - used to notify component of bind event. + * @param dev Component device. + * @param data Bind info + * + * Usually can be __cold. + */ + int (*bind)(struct comp_dev *dev, struct bind_info *bind_data); + + /** + * Unbind, atomic - used to notify component of unbind event. + * @param dev Component device. + * @param data unBind info + * + * Usually can be __cold. + */ + int (*unbind)(struct comp_dev *dev, struct bind_info *unbind_data); + + /** + * Gets config in component. + * @param dev Component device + * @param param_id param id for each component + * @param first_block first block of large block. + * @param last_block last block of large block. + * @param data_offset block offset filled by callee. + * @param data block data. + * @return 0 if succeeded, error code otherwise. + * + * Callee fills up *data with config data and save the config + * size in *data_offset for host to reconstruct the config + * Usually can be __cold. + */ + int (*get_large_config)(struct comp_dev *dev, uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data); + + /** + * Set config in component. + * @param dev Component device + * @param param_id param id for each component + * @param first_block first block of large block. + * @param last_block last block of large block. + * @param data_offset block offset in large block. + * @param data block data. + * @return 0 if succeeded, error code otherwise. + * + * Host divides large block into small blocks and sends them + * to fw. The data_offset indicates the offset in the large + * block data. + * Usually can be __cold. + */ + int (*set_large_config)(struct comp_dev *dev, uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data); + + /** + * Returns total data processed in number bytes. + * @param dev Component device + * @param stream_no Index of input/output stream + * @param input Selects between input (true) or output (false) stream direction + * @return total data processed if succeeded, 0 otherwise. + * + * Usually shouldn't be __cold. + */ + uint64_t (*get_total_data_processed)(struct comp_dev *dev, uint32_t stream_no, bool input); +}; + +struct k_heap; +struct vregion; +struct mod_alloc_ctx { + struct k_heap *heap; + struct vregion *vreg; }; /** @@ -380,15 +591,56 @@ struct comp_ops { * - used by all other component types. */ struct comp_driver { - uint32_t type; /**< SOF_COMP_ for driver */ - uint32_t uid; /**< Address of uuid_entry */ - struct comp_ops ops; /**< component operations */ + uint32_t type; /**< SOF_COMP_ for driver */ + const struct sof_uuid *uid; /**< Address to UUID value */ + struct tr_ctx *tctx; /**< Pointer to trace context */ + struct comp_ops ops; /**< component operations */ + const struct module_interface *adapter_ops; /**< module specific operations. + * Intended to replace the ops field. + * Currently used by module_adapter. + */ + struct k_heap *user_heap; /**< Userspace heap */ }; /** \brief Holds constant pointer to component driver */ struct comp_driver_info { - const struct comp_driver *drv; /**< pointer to component driver */ - struct list_item list; /**< list of component drivers */ + const struct comp_driver *drv; /**< pointer to component driver */ + const struct module_interface **adapter_ops; /**< pointer for updating ops */ + struct list_item list; /**< list of component drivers */ +}; + +#define COMP_PROCESSING_DOMAIN_LL 0 +#define COMP_PROCESSING_DOMAIN_DP 1 + +/** + * Audio component base configuration from IPC at creation. + */ +struct comp_ipc_config { + uint32_t core; /**< core we run on */ + uint32_t id; /**< component id */ + uint32_t pipeline_id; /**< component pipeline id */ + uint32_t proc_domain; /**< processing domain - LL or DP */ + enum sof_comp_type type; /**< component type */ + uint32_t periods_sink; /**< 0 means variable */ + uint32_t periods_source; /**< 0 means variable */ + uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */ + uint32_t xrun_action; /**< action we should take on XRUN */ +#if CONFIG_IPC_MAJOR_4 + bool ipc_extended_init; /**< true if extended init is included in ipc payload */ + uint32_t ipc_config_size; /**< size of a config received by ipc */ +#endif +}; + +struct comp_perf_data { + /* maximum measured cpc on run-time. + * + * if current measured cpc exceeds peak_of_measured_cpc_ then + * ResoruceEvent(BUDGET_VIOLATION) notification must be send. + * Otherwise there is no new information for host to care about + */ + size_t peak_of_measured_cpc; + /* Pointer to performance data structure. */ + struct perf_data_item_comp *perf_data_item; }; /** @@ -399,49 +651,167 @@ struct comp_dev { /* runtime */ uint16_t state; /**< COMP_STATE_ */ - uint64_t position; /**< component rendering position */ uint32_t frames; /**< number of frames we copy to sink */ struct pipeline *pipeline; /**< pipeline we belong to */ - uint32_t min_sink_bytes; /**< min free sink buffer size measured in - * bytes required to run component's - * processing - */ - uint32_t min_source_bytes; /**< amount of data measured in bytes - * available at source buffer required - * to run component's processing - */ - - struct task *task; /**< component's processing task used only - * for components running on different core - * than the rest of the pipeline + struct task *task; /**< component's processing task used + * 1) for components running on different core + * than the rest of the pipeline + * 2) for all DP tasks */ uint32_t size; /**< component's allocated size */ - uint32_t period; /**< component's processing period */ + uint32_t period; /**< component's processing period + * for LL modules is set to LL pipeline's period + * for DP module its meaning is "the time the module MUST + * provide data that allows the following module to perform + * without glitches" + */ uint32_t priority; /**< component's processing priority */ bool is_shared; /**< indicates whether component is shared * across cores */ + struct comp_ipc_config ipc_config; /**< Component IPC configuration */ + struct tr_ctx tctx; /**< trace settings */ /* common runtime configuration for downstream/upstream */ uint32_t direction; /**< enum sof_ipc_stream_direction */ + bool direction_set; /**< flag indicating that the direction has been set */ const struct comp_driver *drv; /**< driver */ + struct processing_module *mod; /**< self->mod->dev == self, NULL if component is not using + * module adapter + */ + /* lists */ struct list_item bsource_list; /**< list of source buffers */ struct list_item bsink_list; /**< list of sink buffers */ +#ifdef CONFIG_SOF_USERSPACE_LL + struct sys_mutex list_mutex; /**< protect lists of source/sinks */ +#endif + + /* performance data*/ + struct comp_perf_data perf_data; + /* Input Buffer Size for pin 0, add array for other pins if needed */ + size_t ibs; + /* Output Buffers Size for pin 0, add array for other pins if needed */ + size_t obs; + /* max dsp cycles per chunk */ + size_t cpc; + /* size of 1ms for input format in bytes */ + size_t ll_chunk_size : 16; + /* private data - core does not touch this */ - void *private; /**< private data */ + void *priv_data; /**< private data */ - /** - * IPC config object header - MUST be at end as it's - * variable size/type - */ - struct sof_ipc_comp comp; +#if CONFIG_PERFORMANCE_COUNTERS_COMPONENT + struct perf_cnt_data pcd; +#endif + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + int32_t kcps_inc[CONFIG_CORE_COUNT]; +#endif }; +/** + * Get a pointer to the first comp_buffer object providing data to the component + * The function will return NULL if there's no data provider + */ +static inline struct comp_buffer *comp_dev_get_first_data_producer(struct comp_dev *component) +{ + return list_is_empty(&component->bsource_list) ? NULL : + list_first_item(&component->bsource_list, struct comp_buffer, sink_list); +} + +/** + * Get a pointer to the next comp_buffer object providing data to the component + * The function will return NULL if there're no more data providers + * _save version also checks if producer != NULL + */ +static inline struct comp_buffer *comp_dev_get_next_data_producer(struct comp_dev *component, + struct comp_buffer *producer) +{ + return producer->sink_list.next == &component->bsource_list ? NULL : + list_item(producer->sink_list.next, struct comp_buffer, sink_list); +} + +static inline struct comp_buffer *comp_dev_get_next_data_producer_safe(struct comp_dev *component, + struct comp_buffer *producer) +{ + return producer ? comp_dev_get_next_data_producer(component, producer) : NULL; +} + +/** + * Get a pointer to the first comp_buffer object receiving data from the component + * The function will return NULL if there's no data consumers + */ +static inline struct comp_buffer *comp_dev_get_first_data_consumer(struct comp_dev *component) +{ + return list_is_empty(&component->bsink_list) ? NULL : + list_first_item(&component->bsink_list, struct comp_buffer, source_list); +} + +/** + * Get a pointer to the next comp_buffer object receiving data from the component + * The function will return NULL if there're no more data consumers + * _safe version also checks if consumer is != NULL + */ +static inline struct comp_buffer *comp_dev_get_next_data_consumer(struct comp_dev *component, + struct comp_buffer *consumer) +{ + return consumer->source_list.next == &component->bsink_list ? NULL : + list_item(consumer->source_list.next, struct comp_buffer, source_list); +} + +static inline struct comp_buffer *comp_dev_get_next_data_consumer_safe(struct comp_dev *component, + struct comp_buffer *consumer) +{ + return consumer ? comp_dev_get_next_data_consumer(component, consumer) : NULL; +} + +/* + * a macro for easy iteration through component's list of producers + */ +#define comp_dev_for_each_producer(_dev, _producer) \ + for (_producer = comp_dev_get_first_data_producer(_dev); \ + _producer != NULL; \ + _producer = comp_dev_get_next_data_producer(_dev, _producer)) + +/* + * a macro for easy iteration through component's list of producers + * allowing deletion of a buffer during iteration + * + * additional "safe storage" pointer to struct comp_buffer must be provided + */ +#define comp_dev_for_each_producer_safe(_dev, _producer, _next_producer) \ + for (_producer = comp_dev_get_first_data_producer(_dev), \ + _next_producer = comp_dev_get_next_data_producer_safe(_dev, _producer); \ + _producer != NULL; \ + _producer = _next_producer, \ + _next_producer = comp_dev_get_next_data_producer_safe(_dev, _producer)) + +/* + * a macro for easy iteration through component's list of consumers + */ +#define comp_dev_for_each_consumer(_dev, _consumer) \ + for (_consumer = comp_dev_get_first_data_consumer(_dev); \ + _consumer != NULL; \ + _consumer = comp_dev_get_next_data_consumer(_dev, _consumer)) \ + +/* + * a macro for easy iteration through component's list of consumers + * allowing deletion of a buffer during iteration + * + * additional "safe storage" pointer to struct comp_buffer must be provided + */ +#define comp_dev_for_each_consumer_safe(_dev, _consumer, _next_consumer) \ + for (_consumer = comp_dev_get_first_data_consumer(_dev), \ + _next_consumer = comp_dev_get_next_data_consumer_safe(_dev, _consumer); \ + _consumer != NULL; \ + _consumer = _next_consumer, \ + _next_consumer = comp_dev_get_next_data_consumer_safe(_dev, _consumer)) + /** @}*/ /* Common helper function used internally by the component implementations @@ -461,24 +831,6 @@ struct comp_copy_limits { int sink_frame_bytes; }; -/** \brief Computes size of the component device including ipc config. */ -#define COMP_SIZE(x) \ - (sizeof(struct comp_dev) - sizeof(struct sof_ipc_comp) + sizeof(x)) - -/** \brief Retrieves component device IPC configuration. */ -#define COMP_GET_IPC(dev, type) \ - (struct type *)(&dev->comp) - -/** - * Retrieves component from device. - * @param dev Device. - * @return Pointer to the component. - */ -static inline struct sof_ipc_comp *dev_comp(struct comp_dev *dev) -{ - return &dev->comp; -} - /** * Retrieves Component id from device. * @param dev Device. @@ -486,7 +838,7 @@ static inline struct sof_ipc_comp *dev_comp(struct comp_dev *dev) */ static inline uint32_t dev_comp_id(const struct comp_dev *dev) { - return dev->comp.id; + return dev->ipc_config.id; } /** @@ -496,7 +848,7 @@ static inline uint32_t dev_comp_id(const struct comp_dev *dev) */ static inline uint32_t dev_comp_pipe_id(const struct comp_dev *dev) { - return dev->comp.pipeline_id; + return dev->ipc_config.pipeline_id; } /** @@ -506,27 +858,75 @@ static inline uint32_t dev_comp_pipe_id(const struct comp_dev *dev) */ static inline enum sof_comp_type dev_comp_type(const struct comp_dev *dev) { - return dev->comp.type; + return dev->ipc_config.type; } /** - * Retrieves component config data from device. + * Initialize common part of a component device + * @param drv Parent component driver. * @param dev Device. - * @return Pointer to the component data. + * @param bytes Size of the component device in bytes. + */ +static inline void comp_init(const struct comp_driver *drv, + struct comp_dev *dev, size_t bytes) +{ + dev->size = bytes; + dev->drv = drv; + dev->state = COMP_STATE_INIT; + list_init(&dev->bsink_list); + list_init(&dev->bsource_list); +#ifdef CONFIG_SOF_USERSPACE_LL + sys_mutex_init(&dev->list_mutex); +#endif + memcpy_s(&dev->tctx, sizeof(dev->tctx), + trace_comp_drv_get_tr_ctx(dev->drv), sizeof(struct tr_ctx)); +} + +/** + * Allocates memory for the component device and initializes common part. + * @param drv Parent component driver. + * @param bytes Size of the component device in bytes. + * @return Pointer to the component device. + */ +static inline struct comp_dev *comp_alloc(const struct comp_driver *drv, size_t bytes) +{ + /* + * Use uncached address everywhere to access components to rule out + * multi-core failures. TODO: verify if cached alias may be used in some cases + */ + struct comp_dev *dev = sof_heap_alloc(drv->user_heap, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + bytes, 0); + + if (!dev) + return NULL; + + memset(dev, 0, sizeof(*dev)); + comp_init(drv, dev, bytes); + + return dev; +} + +/** + * Frees memory allocated for component device. + * + * This is a counterpart to comp_alloc() and not to be confused with + * comp_free(). + * + * @param dev Pointer to the component device. */ -static inline struct sof_ipc_comp_config *dev_comp_config(struct comp_dev *dev) +static inline void comp_free_device(struct comp_dev *dev) { - return (struct sof_ipc_comp_config *)(&dev->comp + 1); + sof_heap_free(dev->drv->user_heap, dev); } /** - * Retrieves component config data from component ipc. - * @param comp Component ipc data. - * @return Pointer to the component config data. + * \brief Module adapter associated with a component + * @param dev Component device */ -static inline struct sof_ipc_comp_config *comp_config(struct sof_ipc_comp *comp) +static inline struct processing_module *comp_mod(const struct comp_dev *dev) { - return (struct sof_ipc_comp_config *)(comp + 1); + return dev->mod; } /** @@ -535,7 +935,7 @@ static inline struct sof_ipc_comp_config *comp_config(struct sof_ipc_comp *comp) * @param data Private data. */ #define comp_set_drvdata(c, data) \ - (c->private = data) + (c->priv_data = data) /** * \brief Retrieves driver private data from component device. @@ -543,20 +943,64 @@ static inline struct sof_ipc_comp_config *comp_config(struct sof_ipc_comp *comp) * @return Private data. */ #define comp_get_drvdata(c) \ - c->private + (c->priv_data) -#ifdef UNIT_TEST +#if defined UNIT_TEST || defined __ZEPHYR__ || CONFIG_LIBRARY_STATIC #define DECLARE_MODULE(init) + +/* declared modules */ +void sys_comp_dai_init(void); +void sys_comp_host_init(void); +void sys_comp_kpb_init(void); +void sys_comp_selector_init(void); + +/* Start of modules in alphabetical order */ +void sys_comp_module_aria_interface_init(void); +void sys_comp_module_asrc_interface_init(void); +void sys_comp_module_copier_interface_init(void); +void sys_comp_module_crossover_interface_init(void); +void sys_comp_module_dcblock_interface_init(void); +void sys_comp_module_demux_interface_init(void); +void sys_comp_module_dolby_dax_audio_processing_interface_init(void); +void sys_comp_module_drc_interface_init(void); +void sys_comp_module_dts_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_gain_interface_init(void); +void sys_comp_module_google_rtc_audio_processing_interface_init(void); +void sys_comp_module_google_ctc_audio_processing_interface_init(void); +void sys_comp_module_igo_nr_interface_init(void); +void sys_comp_module_level_multiplier_interface_init(void); +void sys_comp_module_mfcc_interface_init(void); +void sys_comp_module_mixer_interface_init(void); +void sys_comp_module_mixin_interface_init(void); +void sys_comp_module_mixout_interface_init(void); +void sys_comp_module_multiband_drc_interface_init(void); +void sys_comp_module_mux_interface_init(void); +void sys_comp_module_nxp_eap_interface_init(void); +void sys_comp_module_rtnr_interface_init(void); +void sys_comp_module_selector_interface_init(void); +void sys_comp_module_sound_dose_interface_init(void); +void sys_comp_module_src_interface_init(void); +void sys_comp_module_src_lite_interface_init(void); +void sys_comp_module_stft_process_interface_init(void); +void sys_comp_module_tdfb_interface_init(void); +void sys_comp_module_tone_interface_init(void); +void sys_comp_module_template_interface_init(void); +void sys_comp_module_tester_interface_init(void); +void sys_comp_module_volume_interface_init(void); +/* End of modules in alphabetical order */ + #elif CONFIG_LIBRARY /* In case of shared libs components are initialised in dlopen */ #define DECLARE_MODULE(init) __attribute__((constructor)) \ - static void _module_init(void) { init(); } + static void _module_##init(void) { init(); } #else /** \brief Usage at the end of an independent module file: * DECLARE_MODULE(sys_*_init); */ #define DECLARE_MODULE(init) __attribute__((__used__)) \ - __section(".module_init") static void(*f)(void) = init + __section(".initcall") static void(*f##init)(void) = init #endif /** \name Component registration @@ -576,6 +1020,15 @@ int comp_register(struct comp_driver_info *drv); */ void comp_unregister(struct comp_driver_info *drv); +/** + * Set adapter ops for a dynamically created driver. + * + * @param drv Component driver to update. + * @param ops Module interface operations. + * @return 0 or a negative error code + */ +int comp_set_adapter_ops(const struct comp_driver *drv, const struct module_interface *ops); + /** @}*/ /** @@ -600,14 +1053,37 @@ void comp_unregister(struct comp_driver_info *drv); int comp_set_state(struct comp_dev *dev, int cmd); /* \brief Set component period frames */ -static inline void component_set_period_frames(struct comp_dev *current, - uint32_t rate) +static inline void component_set_nearest_period_frames(struct comp_dev *current, + uint32_t rate) { - /* Samplerate is in Hz and period in microseconds. + 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. + * dma buffer size should align with 32bytes which can't be + * compatible with current 45K adjustment. 48K is a suitable + * adjustment. */ - current->frames = ceil_divide(rate * current->period, 1000000); + + switch (rate) { + case 44100: + rate = 48000; + break; + case 88200: + rate = 96000; + break; + case 176400: + rate = 192000; + break; + default: + break; + } + + frames = SOF_DIV_ROUND_UP((uint64_t)rate * current->period, 1000000); + + assert(frames <= UINT_MAX); + current->frames = (uint32_t)frames; } /** \name XRUN handling. @@ -624,11 +1100,14 @@ static inline void comp_underrun(struct comp_dev *dev, struct comp_buffer *source, uint32_t copy_bytes) { - int32_t bytes = (int32_t)source->stream.avail - copy_bytes; + LOG_MODULE_DECLARE(component, CONFIG_SOF_LOG_LEVEL); + + int32_t bytes = (int32_t)audio_stream_get_avail_bytes(&source->stream) - + copy_bytes; - comp_err(dev, "comp_underrun() error: dev->comp.id = %u, source->avail = %u, copy_bytes = %u", + comp_err(dev, "comp_underrun(): dev->comp.id = %u, source->avail = %u, copy_bytes = %u", dev_comp_id(dev), - source->stream.avail, + audio_stream_get_avail_bytes(&source->stream), copy_bytes); pipeline_xrun(dev->pipeline, dev, bytes); @@ -643,10 +1122,13 @@ static inline void comp_underrun(struct comp_dev *dev, static inline void comp_overrun(struct comp_dev *dev, struct comp_buffer *sink, uint32_t copy_bytes) { - int32_t bytes = (int32_t)copy_bytes - sink->stream.free; + LOG_MODULE_DECLARE(component, CONFIG_SOF_LOG_LEVEL); + + int32_t bytes = (int32_t)copy_bytes - + audio_stream_get_free_bytes(&sink->stream); - comp_err(dev, "comp_overrun() error: sink->free = %u, copy_bytes = %u", - sink->stream.free, copy_bytes); + comp_err(dev, "comp_overrun(): sink->free = %u, copy_bytes = %u", + audio_stream_get_free_bytes(&sink->stream), copy_bytes); pipeline_xrun(dev->pipeline, dev, bytes); } @@ -654,20 +1136,81 @@ static inline void comp_overrun(struct comp_dev *dev, struct comp_buffer *sink, /** @}*/ /** - * Called by component in copy. - * @param source Source buffer. - * @param sink Sink buffer. - * @param cl Struct of parameters for use in copy function. + * Computes source to sink copy operation boundaries including maximum number + * of frames that can be transferred (data available in source vs. free space + * available in sink). + * + * @param[in] source Source buffer. + * @param[in] sink Sink buffer. + * @param[out] cl Current copy limits. */ -void comp_get_copy_limits(struct comp_buffer *source, struct comp_buffer *sink, +void comp_get_copy_limits(struct comp_buffer *source, + struct comp_buffer *sink, struct comp_copy_limits *cl); /** + * Computes source to sink copy operation boundaries including maximum number + * of frames aligned with requirement that can be transferred (data available in + * source vs. free space available in sink). + * + * @param[in] source Buffer of source. + * @param[in] sink Buffer of sink. + * @param[out] cl Current copy limits. + */ +void comp_get_copy_limits_frame_aligned(const struct comp_buffer *source, + const struct comp_buffer *sink, + struct comp_copy_limits *cl); + +/** + * Get component state. + * + * @param dev Component from which user wants to read status. + * + * @retval COMP_STATE_NOT_EXIST if there's no connected component + * @return state of the component + */ +static inline int comp_get_state(const struct comp_dev *dev) +{ + if (!dev) + return COMP_STATE_NOT_EXIST; + return dev->state; +} + +/** + * @brief helper, provide state of a component connected to a buffer as a data provider + * + * @param buffer a buffer to be checked + * + * @retval COMP_STATE_NOT_EXIST if there's no connected component + * @return state of the component + */ +static inline int comp_buffer_get_source_state(const struct comp_buffer *buffer) +{ + return comp_get_state(comp_buffer_get_source_component(buffer)); +} + +/** + * @brief helper, provide state of a component connected to a buffer as a data consumer + * + * @param buffer a buffer to be checked + * + * @retval COMP_STATE_NOT_EXIST if there's no connected component + * @return state of the component + */ +static inline int comp_buffer_get_sink_state(const struct comp_buffer *buffer) +{ + return comp_get_state(comp_buffer_get_sink_component(buffer)); +} + +/** + * Warning: duplicate declaration in topology.h + * * Called by component in params() function in order to set and update some of * downstream (playback) or upstream (capture) buffer parameters with pcm * parameters. There is a possibility to specify which of parameters won't be * overwritten (e.g. SRC component should not overwrite rate parameter, because * it is able to change it). + * * @param dev Component device * @param flag Specifies which parameter should not be updated * @param params pcm params @@ -677,4 +1220,35 @@ int comp_verify_params(struct comp_dev *dev, uint32_t flag, /** @}*/ +/** + * Update ibs, obs, cpc, ll chunk size for component. + * + * @param dev Component to update. + */ +void comp_update_ibs_obs_cpc(struct comp_dev *dev); + +/** + * If component has assigned slot in performance measurement window, + * initialize its fields. + * @param dev Component to init. + */ +void comp_init_performance_data(struct comp_dev *dev); + +/** + * Update performance data entry for component. Also checks for budget violation. + * + * @param dev Component to update. + * @param cycles_used Execution time. + * @return true if budget violation occurred + */ +bool comp_update_performance_data(struct comp_dev *dev, uint32_t cycles_used); + +static inline int user_get_buffer_memory_region(const struct comp_driver *drv) +{ +#if CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP + return drv->user_heap ? SOF_MEM_FLAG_USER_SHARED_BUFFER : SOF_MEM_FLAG_USER; +#else + return SOF_MEM_FLAG_USER; +#endif +} #endif /* __SOF_AUDIO_COMPONENT_H__ */ diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index ee29a5f7fc4e..d2bbf87a7764 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -17,11 +17,7 @@ #define __SOF_AUDIO_COMPONENT_INT_H__ #include <sof/audio/component.h> -#include <sof/drivers/idc.h> -#include <sof/list.h> #include <ipc/topology.h> -#include <kernel/abi.h> -#include <stdbool.h> /** \addtogroup component_api_helpers Component Mgmt API * @{ @@ -30,38 +26,33 @@ /** \brief Holds list of registered components' drivers */ struct comp_driver_list { struct list_item list; /**< list of component drivers */ + struct k_spinlock lock; /**< list lock */ }; /** \brief Retrieves the component device buffer list. */ #define comp_buffer_list(comp, dir) \ - ((dir) == PPL_DIR_DOWNSTREAM ? &comp->bsink_list : \ - &comp->bsource_list) + ((dir) == PPL_DIR_DOWNSTREAM ? &(comp)->bsink_list : \ + &(comp)->bsource_list) /** See comp_ops::new */ +#if CONFIG_IPC_MAJOR_3 struct comp_dev *comp_new(struct sof_ipc_comp *comp); +#elif CONFIG_IPC_MAJOR_4 +struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init); +#endif /** See comp_ops::free */ static inline void comp_free(struct comp_dev *dev) { - assert(dev->drv->ops.free); + const struct comp_driver *drv = dev->drv; - /* free task if shared component */ - if (dev->is_shared && dev->task) { - schedule_task_free(dev->task); - rfree(dev->task); - } - - dev->drv->ops.free(dev); -} + assert(drv->ops.free); -/** - * Commits component's memory if it's shared. - * @param dev Component device. - */ -static inline void comp_shared_commit(struct comp_dev *dev) -{ - if (dev->is_shared) - platform_shared_commit(dev, sizeof(*dev)); + /* + * In DP case this will run in DP thread context, so the task can only + * be freed after this. + */ + drv->ops.free(dev); } /** @@ -73,8 +64,8 @@ static inline void comp_shared_commit(struct comp_dev *dev) static inline int comp_params_remote(struct comp_dev *dev, struct sof_ipc_stream_params *params) { - struct idc_msg msg = { IDC_MSG_PARAMS, IDC_MSG_PARAMS_EXT(dev->comp.id), - dev->comp.core, sizeof(*params), params, }; + struct idc_msg msg = { IDC_MSG_PARAMS, IDC_MSG_PARAMS_EXT(dev->ipc_config.id), + dev->ipc_config.core, sizeof(*params), params, }; return idc_send_msg(&msg, IDC_BLOCKING); } @@ -85,12 +76,24 @@ static inline int comp_params(struct comp_dev *dev, { int ret = 0; - if (dev->drv->ops.params) - ret = (dev->is_shared && !cpu_is_me(dev->comp.core)) ? - comp_params_remote(dev, params) : - dev->drv->ops.params(dev, params); - - comp_shared_commit(dev); + if (dev->is_shared && !cpu_is_me(dev->ipc_config.core)) { + ret = comp_params_remote(dev, params); + } else { + if (dev->drv->ops.params) { + ret = dev->drv->ops.params(dev, params); + } else { + /* not defined, run the default handler */ + ret = comp_verify_params(dev, 0, params); + +/* BugLink: https://github.com/zephyrproject-rtos/zephyr/issues/43786 + * TODO: Remove this once the bug gets fixed. + */ +#ifndef __ZEPHYR__ + if (ret < 0) + comp_err(dev, "pcm params verification failed"); +#endif + } + } return ret; } @@ -100,39 +103,35 @@ static inline int comp_dai_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, int dir) { - int ret = -EINVAL; - if (dev->drv->ops.dai_get_hw_params) - ret = dev->drv->ops.dai_get_hw_params(dev, params, dir); - - comp_shared_commit(dev); + return dev->drv->ops.dai_get_hw_params(dev, params, dir); - return ret; + return -EINVAL; } +#if CONFIG_IPC_MAJOR_3 /** See comp_ops::cmd */ static inline int comp_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) { - struct sof_ipc_ctrl_data *cdata = data; - int ret = -EINVAL; + LOG_MODULE_DECLARE(component, CONFIG_SOF_LOG_LEVEL); + + struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); if (cmd == COMP_CMD_SET_DATA && (cdata->data->magic != SOF_ABI_MAGIC || SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi))) { - comp_err(dev, "comp_cmd() error: invalid version, data->magic = %u, data->abi = %u", + comp_err(dev, "comp_cmd(): invalid version, data->magic = %u, data->abi = %u", cdata->data->magic, cdata->data->abi); - goto out; + return -EINVAL; } if (dev->drv->ops.cmd) - ret = dev->drv->ops.cmd(dev, cmd, data, max_data_size); - -out: - comp_shared_commit(dev); + return dev->drv->ops.cmd(dev, cmd, data, max_data_size); - return ret; + return -EINVAL; } +#endif /** * Runs comp_ops::trigger on the core the target component is assigned to. @@ -140,23 +139,48 @@ static inline int comp_cmd(struct comp_dev *dev, int cmd, void *data, static inline int comp_trigger_remote(struct comp_dev *dev, int cmd) { struct idc_msg msg = { IDC_MSG_TRIGGER, - IDC_MSG_TRIGGER_EXT(dev->comp.id), dev->comp.core, sizeof(cmd), + IDC_MSG_TRIGGER_EXT(dev->ipc_config.id), dev->ipc_config.core, sizeof(cmd), &cmd, }; return idc_send_msg(&msg, IDC_BLOCKING); } +static inline int comp_trigger_local(struct comp_dev *dev, int cmd) +{ + int ret; + + ret = dev->drv->ops.trigger(dev, cmd); + if (ret) + return ret; + + /* start a thread in case of shared component or DP scheduling */ + if (dev->task) { + /* schedule or cancel task */ + switch (cmd) { + case COMP_TRIGGER_START: + ret = schedule_task(dev->task, 0, dev->period); + break; + case COMP_TRIGGER_RELEASE: + case COMP_TRIGGER_XRUN: + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + break; + } + } + + return ret; +} + /** See comp_ops::trigger */ static inline int comp_trigger(struct comp_dev *dev, int cmd) { - int ret = 0; - + int ret; assert(dev->drv->ops.trigger); - ret = (dev->is_shared && !cpu_is_me(dev->comp.core)) ? - comp_trigger_remote(dev, cmd) : dev->drv->ops.trigger(dev, cmd); - - comp_shared_commit(dev); + if (dev->is_shared && !cpu_is_me(dev->ipc_config.core)) + ret = comp_trigger_remote(dev, cmd); + else + ret = comp_trigger_local(dev, cmd); return ret; } @@ -165,7 +189,7 @@ static inline int comp_trigger(struct comp_dev *dev, int cmd) static inline int comp_prepare_remote(struct comp_dev *dev) { struct idc_msg msg = { IDC_MSG_PREPARE, - IDC_MSG_PREPARE_EXT(dev->comp.id), dev->comp.core, }; + IDC_MSG_PREPARE_EXT(dev->ipc_config.id), dev->ipc_config.core, }; return idc_send_msg(&msg, IDC_BLOCKING); } @@ -173,52 +197,87 @@ static inline int comp_prepare_remote(struct comp_dev *dev) /** See comp_ops::prepare */ static inline int comp_prepare(struct comp_dev *dev) { - int ret = 0; - if (dev->drv->ops.prepare) - ret = (dev->is_shared && !cpu_is_me(dev->comp.core)) ? + return (dev->is_shared && !cpu_is_me(dev->ipc_config.core)) ? comp_prepare_remote(dev) : dev->drv->ops.prepare(dev); - comp_shared_commit(dev); - - return ret; + return 0; } -/** See comp_ops::copy */ -static inline int comp_copy(struct comp_dev *dev) +int comp_copy(struct comp_dev *dev); + +#if CONFIG_IPC_MAJOR_4 +struct get_attribute_remote_payload { + uint32_t type; + void *value; +}; + +static inline int comp_ipc4_get_attribute_remote(struct comp_dev *dev, uint32_t type, + void *value) { - int ret = 0; + struct ipc4_base_module_cfg *base_cfg; + struct get_attribute_remote_payload payload = {}; + struct idc_msg msg = { IDC_MSG_GET_ATTRIBUTE, + IDC_EXTENSION(dev->ipc_config.id), dev->ipc_config.core, + sizeof(payload), &payload}; + int ret; - assert(dev->drv->ops.copy); + /* Only COMP_ATTR_BASE_CONFIG is supported for remote access */ + if (type != COMP_ATTR_BASE_CONFIG) + return -EINVAL; - /* copy only if we are the owner of the component */ - if (cpu_is_me(dev->comp.core)) - ret = dev->drv->ops.copy(dev); + base_cfg = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*base_cfg)); + if (!base_cfg) + return -ENOMEM; - comp_shared_commit(dev); + payload.type = type; + payload.value = base_cfg; + ret = idc_send_msg(&msg, IDC_BLOCKING); + + if (ret == 0) + memcpy_s(value, sizeof(struct ipc4_base_module_cfg), + base_cfg, sizeof(struct ipc4_base_module_cfg)); + + rfree(base_cfg); return ret; } +#endif /* CONFIG_IPC_MAJOR_4 */ + +/** See comp_ops::get_attribute */ +static inline int comp_get_attribute(struct comp_dev *dev, uint32_t type, + void *value) +{ +#if CONFIG_IPC_MAJOR_4 + if (dev->drv->ops.get_attribute) + return cpu_is_me(dev->ipc_config.core) ? + dev->drv->ops.get_attribute(dev, type, value) : + comp_ipc4_get_attribute_remote(dev, type, value); + + return 0; +#else + if (dev->drv->ops.get_attribute) + return dev->drv->ops.get_attribute(dev, type, value); + + return 0; +#endif +} /** See comp_ops::set_attribute */ static inline int comp_set_attribute(struct comp_dev *dev, uint32_t type, void *value) { - int ret = 0; - if (dev->drv->ops.set_attribute) - ret = dev->drv->ops.set_attribute(dev, type, value); - - comp_shared_commit(dev); + return dev->drv->ops.set_attribute(dev, type, value); - return ret; + return 0; } /** Runs comp_ops::reset on the target component's core */ static inline int comp_reset_remote(struct comp_dev *dev) { struct idc_msg msg = { IDC_MSG_RESET, - IDC_MSG_RESET_EXT(dev->comp.id), dev->comp.core, }; + IDC_MSG_RESET_EXT(dev->ipc_config.id), dev->ipc_config.core, }; return idc_send_msg(&msg, IDC_BLOCKING); } @@ -230,43 +289,42 @@ static inline int comp_reset_remote(struct comp_dev *dev) */ static inline int comp_reset(struct comp_dev *dev) { - int ret = 0; - if (dev->drv->ops.reset) - ret = (dev->is_shared && !cpu_is_me(dev->comp.core)) ? + return (dev->is_shared && !cpu_is_me(dev->ipc_config.core)) ? comp_reset_remote(dev) : dev->drv->ops.reset(dev); - comp_shared_commit(dev); - - return ret; + return 0; } +#if CONFIG_IPC_MAJOR_3 /** See comp_ops::dai_config */ -static inline int comp_dai_config(struct comp_dev *dev, - struct sof_ipc_dai_config *config) +static inline int comp_dai_config(struct comp_dev *dev, struct ipc_config_dai *config, + const void *spec_config) { - int ret = 0; + struct dai_data *dd = comp_get_drvdata(dev); if (dev->drv->ops.dai_config) - ret = dev->drv->ops.dai_config(dev, config); + return dev->drv->ops.dai_config(dd, dev, config, spec_config); - comp_shared_commit(dev); - - return ret; + 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) { - int ret = 0; - if (dev->drv->ops.position) - ret = dev->drv->ops.position(dev, posn); - - comp_shared_commit(dev); + return dev->drv->ops.position(dev, posn); - return ret; + return 0; } /** @@ -322,7 +380,9 @@ static inline int comp_get_requested_state(int cmd) case COMP_TRIGGER_RESET: state = COMP_STATE_READY; break; - default: + case COMP_TRIGGER_PRE_START: + case COMP_TRIGGER_PRE_RELEASE: + state = COMP_STATE_PRE_ACTIVE; break; } @@ -357,17 +417,101 @@ static inline bool comp_is_scheduling_source(struct comp_dev *dev) } /** - * Called to reallocate component in shared memory. + * Called to mark component as shared between cores * @param dev Component device. - * @return Pointer to reallocated component device. */ -struct comp_dev *comp_make_shared(struct comp_dev *dev); +static inline void comp_make_shared(struct comp_dev *dev) +{ + dev->is_shared = true; +} static inline struct comp_driver_list *comp_drivers_get(void) { return sof_get()->comp_drivers; } +#if CONFIG_IPC_MAJOR_4 +static inline int comp_ipc4_bind_remote(struct comp_dev *dev, struct bind_info *bind_data) +{ + struct idc_msg msg = { IDC_MSG_BIND, + IDC_EXTENSION(dev->ipc_config.id), dev->ipc_config.core, + sizeof(*bind_data), bind_data}; + + return idc_send_msg(&msg, IDC_BLOCKING); +} +#endif + +static inline int comp_bind(struct comp_dev *dev, struct bind_info *bind_data) +{ +#if CONFIG_IPC_MAJOR_4 + if (dev->drv->ops.bind) + return cpu_is_me(dev->ipc_config.core) ? + dev->drv->ops.bind(dev, bind_data) : comp_ipc4_bind_remote(dev, bind_data); + + return 0; +#else + int ret = 0; + + if (dev->drv->ops.bind) + ret = dev->drv->ops.bind(dev, bind_data); + + return ret; +#endif +} + +#if CONFIG_IPC_MAJOR_4 +static inline int comp_ipc4_unbind_remote(struct comp_dev *dev, struct bind_info *unbind_data) +{ + struct idc_msg msg = { IDC_MSG_UNBIND, + IDC_EXTENSION(dev->ipc_config.id), dev->ipc_config.core, + sizeof(*unbind_data), unbind_data}; + + return idc_send_msg(&msg, IDC_BLOCKING); +} +#endif + +static inline int comp_unbind(struct comp_dev *dev, struct bind_info *unbind_data) +{ +#if CONFIG_IPC_MAJOR_4 + if (dev->drv->ops.unbind) + return cpu_is_me(dev->ipc_config.core) ? + dev->drv->ops.unbind(dev, unbind_data) : + comp_ipc4_unbind_remote(dev, unbind_data); + + return 0; +#else + int ret = 0; + + if (dev->drv->ops.unbind) + ret = dev->drv->ops.unbind(dev, unbind_data); + + return ret; +#endif +} + +static inline uint64_t comp_get_total_data_processed(struct comp_dev *dev, uint32_t stream_no, + bool input) +{ + uint64_t ret = 0; + + if (dev->drv->ops.get_total_data_processed) + ret = dev->drv->ops.get_total_data_processed(dev, stream_no, input); + + return ret; +} + +/** Returns true if the component's pipeline matches the specified direction */ +static inline bool comp_same_dir(struct comp_dev *comp, enum sof_ipc_stream_direction dir) +{ + int end_type = comp_get_endpoint_type(comp->pipeline->sink_comp); + + if (dir == SOF_IPC_STREAM_PLAYBACK && end_type != COMP_ENDPOINT_DAI) + return false; + if (dir == SOF_IPC_STREAM_CAPTURE && end_type != COMP_ENDPOINT_HOST) + return false; + return true; +} + /** @}*/ #endif /* __SOF_AUDIO_COMPONENT_INT_H__ */ diff --git a/src/include/sof/audio/data_blob.h b/src/include/sof/audio/data_blob.h new file mode 100644 index 000000000000..d2eb8a74d66d --- /dev/null +++ b/src/include/sof/audio/data_blob.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jyri Sarha <jyri.sarha@intel.com> + */ + +#ifndef __SOF_AUDIO_DATA_BLOB_H__ +#define __SOF_AUDIO_DATA_BLOB_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/sof.h> + +struct comp_dev; + +struct comp_data_blob_handler; + +/** + * Returns data blob. In case when new data blob is available it returns new + * one. Function returns also data blob size in case when size pointer is given. + * + * @param blob_handler Data blob handler + * @param size Pointer to data blob size variable + * @param crc Pointer to data blolb crc value + */ +void *comp_get_data_blob(struct comp_data_blob_handler *blob_handler, + size_t *size, uint32_t *crc); + +/** + * Checks whether new data blob is available. Function allows to check (even + * during streaming - in copy() function) whether new config is available and + * if it is, component can perform reconfiguration. + * + * @param blob_handler Data blob handler + */ +bool comp_is_new_data_blob_available(struct comp_data_blob_handler + *blob_handler); + +/** + * Checks whether there is a valid data blob is available. + * + * @param blob_handler Data blob handler + */ +bool comp_is_current_data_blob_valid(struct comp_data_blob_handler + *blob_handler); + +/** + * Initializes data blob with given value. If init_data is not specified, + * function will zero data blob. + * + * @param blob_handler Data blob handler + * @param size Data blob size + * @param init_data Initial data blob values + */ +int comp_init_data_blob(struct comp_data_blob_handler *blob_handler, + uint32_t size, const void *init_data); + +/** + * Handles IPC set command. + * + * @param blob_handler Data blob handler + * @param cdata IPC ctrl data + */ +int comp_data_blob_set_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata); + +/** + * Handles IPC set command. + * + * @param blob_handler: Data blob handler + * @param pos position: of the data fragment + * @param data_offset_size: offset of the fragment in the whole data + * @param fragment: pointer to the fragment data + * @param fragment_size: size of the fragment data + */ +int comp_data_blob_set(struct comp_data_blob_handler *blob_handler, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size); + +/** + * Handles IPC4 set large config. + * + * @param blob_handler: Data blob handler + * @param first_block: Flag indicates it is a first block of data + * @param last_block: Flag indicates it is a last block of data + * @param data_offset: Size/offset of the data being sent + * @param data: Pointer to the data array + */ +int ipc4_comp_data_blob_set(struct comp_data_blob_handler *blob_handler, + bool first_block, bool last_block, + uint32_t data_offset, const char *data); +/** + * Handles IPC get command. + * @param blob_handler Data blob handler + * @param cdata IPC ctrl data + * @param size Required size + */ +int comp_data_blob_get_cmd(struct comp_data_blob_handler *blob_handler, + struct sof_ipc_ctrl_data *cdata, int size); + +/** + * Returns new data blob handler. + * + * Data blob handler has two modes of operation, single_blob == false + * stands for double blob mode that allow seamless configuration + * updates on the fly. In single_blob == true mode there is at most + * one blob allocated at one time and configuration update is not + * allowed if the component is active. The single blob mode should be + * used with components with very big configuration blobs to save DSP + * memory. + * + * @param dev Component device + * @param single_blob Set true for single configuration blob operation + * @param alloc Optional blob memory allocator function pointer + * @param free Optional blob memory free function pointer + */ +struct comp_data_blob_handler * +comp_data_blob_handler_new_ext(struct comp_dev *dev, bool single_blob, + void *(*alloc)(size_t size), + void (*free)(void *buf)); + +/** + * Returns new data blob handler. + * + * This is a simplified version of comp_data_blob_handler_new_ext() using + * default memory allocator and double blob mode for on the fly updates. + * + * @param dev Component device + */ +static inline +struct comp_data_blob_handler *comp_data_blob_handler_new(struct comp_dev *dev) +{ + return comp_data_blob_handler_new_ext(dev, false, NULL, NULL); +} + +/** + * Free data blob handler. + * + * @param blob_handler Data blob handler + */ +void comp_data_blob_handler_free(struct comp_data_blob_handler *blob_handler); + +/** + * Add a validator to check that the new data blob is valid for the given component. + * + * If the given validator is null (the default value), then any data blob will be considered valid. + * + * @param blob_handler Data blob handler + * @param validator Function used to validate the new data blob + */ +void comp_data_blob_set_validator(struct comp_data_blob_handler *blob_handler, + int (*validator)(struct comp_dev *dev, void *new_data, + uint32_t new_data_size)); + +#endif /* __SOF_AUDIO_DATA_BLOB_H__ */ diff --git a/src/include/sof/audio/eq_fir/fir.h b/src/include/sof/audio/eq_fir/fir.h deleted file mode 100644 index fdf9abcf0fdd..000000000000 --- a/src/include/sof/audio/eq_fir/fir.h +++ /dev/null @@ -1,115 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - * Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_EQ_FIR_FIR_H__ -#define __SOF_AUDIO_EQ_FIR_FIR_H__ - -#include <sof/audio/eq_fir/fir_config.h> - -#if FIR_GENERIC - -#include <sof/audio/format.h> -#include <stdint.h> - -struct comp_buffer; -struct sof_eq_fir_coef_data; - -struct fir_state_32x16 { - int rwi; /* Circular read and write index */ - int taps; /* Number of FIR taps */ - int length; /* Number of FIR taps */ - int out_shift; /* Amount of right shifts at output */ - int16_t *coef; /* Pointer to FIR coefficients */ - int32_t *delay; /* Pointer to FIR delay line */ -}; - -void fir_reset(struct fir_state_32x16 *fir); - -int fir_delay_size(struct sof_eq_fir_coef_data *config); - -int fir_init_coef(struct fir_state_32x16 *fir, - struct sof_eq_fir_coef_data *config); - -void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data); - -#if CONFIG_FORMAT_S16LE -void eq_fir_s16(struct fir_state_32x16 *fir, const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); -#endif /* CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S24LE -void eq_fir_s24(struct fir_state_32x16 *fir, const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); -#endif /* CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S32LE -void eq_fir_s32(struct fir_state_32x16 *fir, const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); -#endif /* CONFIG_FORMAT_S32LE */ - -/* The next functions are inlined to optmize execution speed */ - -static inline int32_t fir_32x16(struct fir_state_32x16 *fir, int32_t x) -{ - int64_t y = 0; - int32_t *data = &fir->delay[fir->rwi]; - int16_t *coef = &fir->coef[0]; - int n1; - int n2; - int n; - - /* Bypass is set with length set to zero. */ - if (!fir->length) - return x; - - /* Write sample to delay */ - *data = x; - - /* Advance write pointer and calculate into n1 max. number of taps - * to process before circular wrap. - */ - n1 = ++fir->rwi; - if (fir->rwi == fir->length) - fir->rwi = 0; - - /* Check if no need to un-wrap FIR data. */ - if (n1 > fir->length) { - /* Data is Q1.31, coef is Q1.15, product is Q2.46 */ - for (n = 0; n < fir->length; n++) { - y += (int64_t)(*coef) * (*data); - coef++; - data--; - } - - /* Q2.46 -> Q2.31, saturate to Q1.31 */ - return sat_int32(y >> (15 + fir->out_shift)); - } - - /* Part 1, loop n1 times */ - for (n = 0; n < n1; n++) { - y += (int64_t)(*coef) * (*data); - coef++; - data--; - } - - /* Part 2, un-wrap data, continue n2 times */ - n2 = fir->length - n1; - data = &fir->delay[fir->length - 1]; - for (n = 0; n < n2; n++) { - y += (int64_t)(*coef) * (*data); - coef++; - data--; - } - - /* Q2.46 -> Q2.31, saturate to Q1.31 */ - return sat_int32(y >> (15 + fir->out_shift)); -} - -#endif -#endif /* __SOF_AUDIO_EQ_FIR_FIR_H__ */ diff --git a/src/include/sof/audio/eq_fir/fir_config.h b/src/include/sof/audio/eq_fir/fir_config.h deleted file mode 100644 index c40f487c6085..000000000000 --- a/src/include/sof/audio/eq_fir/fir_config.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - * Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_EQ_FIR_FIR_CONFIG_H__ -#define __SOF_AUDIO_EQ_FIR_FIR_CONFIG_H__ - -/* Prevent xtensa gcc built firmware to be configured for longer - * filter that it can process. This length limitation (# of taps) is for one - * channel, for stereo the channel specific limit is this divided by two, - * etc. - */ -#ifndef __XCC__ -#ifdef __XTENSA__ -#define FIR_MAX_LENGTH_BUILD_SPECIFIC 80 -#endif -#endif - -/* If next defines are set to 1 the EQ is configured automatically. Setting - * to zero temporarily is useful is for testing needs. - * Setting EQ_FIR_AUTOARCH to 0 allows to manually set the code variant. - */ -#define FIR_AUTOARCH 1 - -/* Force manually some code variant when EQ_FIR_AUTODSP is set to zero. These - * are useful in code debugging. - */ -#if FIR_AUTOARCH == 0 -#define FIR_GENERIC 0 -#define FIR_HIFIEP 0 -#define FIR_HIFI3 1 -#endif - -/* Select optimized code variant when xt-xcc compiler is used */ -#if FIR_AUTOARCH == 1 -#if defined __XCC__ -#include <xtensa/config/core-isa.h> -#define FIR_GENERIC 0 -#if XCHAL_HAVE_HIFI2EP == 1 -#define FIR_HIFIEP 1 -#define FIR_HIFI3 0 -#elif XCHAL_HAVE_HIFI3 == 1 -#define FIR_HIFI3 1 -#define FIR_HIFIEP 0 -#else -#error "No HIFIEP or HIFI3 found. Cannot build FIR module." -#endif -#else -/* GCC */ -#define FIR_GENERIC 1 -#define FIR_HIFIEP 0 -#define FIR_HIFI3 0 -#endif -#endif - -#endif /* __SOF_AUDIO_EQ_FIR_FIR_CONFIG_H__ */ diff --git a/src/include/sof/audio/eq_fir/fir_hifi2ep.h b/src/include/sof/audio/eq_fir/fir_hifi2ep.h deleted file mode 100644 index ba78f133ca36..000000000000 --- a/src/include/sof/audio/eq_fir/fir_hifi2ep.h +++ /dev/null @@ -1,250 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_EQ_FIR_FIR_HIFI2EP_H__ -#define __SOF_AUDIO_EQ_FIR_FIR_HIFI2EP_H__ - -#include <sof/audio/eq_fir/fir_config.h> - -#if FIR_HIFIEP - -#include <xtensa/config/defs.h> -#include <xtensa/tie/xt_hifi2.h> -#include <stdint.h> - -struct comp_buffer; -struct sof_eq_fir_coef_data; - -struct fir_state_32x16 { - ae_p24x2f *rwp; /* Circular read and write pointer */ - ae_p24f *delay; /* Pointer to FIR delay line */ - ae_p24f *delay_end; /* Pointer to FIR delay line end */ - ae_p16x2s *coef; /* Pointer to FIR coefficients */ - int taps; /* Number of FIR taps */ - int length; /* Number of FIR taps plus input length (even) */ - int in_shift; /* Amount of right shifts at input */ - int out_shift; /* Amount of right shifts at output */ -}; - -void fir_reset(struct fir_state_32x16 *fir); - -int fir_delay_size(struct sof_eq_fir_coef_data *config); - -int fir_init_coef(struct fir_state_32x16 *fir, - struct sof_eq_fir_coef_data *config); - -void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data); - -void eq_fir_s16_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); - -void eq_fir_2x_s16_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch); - -void eq_fir_s24_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); - -void eq_fir_2x_s24_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch); - -void eq_fir_s32_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); - -void eq_fir_2x_s32_hifiep(struct fir_state_32x16 fir[], - const struct audio_stream *source, - struct audio_stream *sink, - int frames, int nch); - -/* Setup circular buffer for FIR input data delay */ -static inline void fir_hifiep_setup_circular(struct fir_state_32x16 *fir) -{ - AE_SETCBEGIN0(fir->delay); - AE_SETCEND0(fir->delay_end); -} - -void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, - int *rshift); - -/* The next functions are inlined to optmize execution speed */ - -/* HiFi EP has the follow number of reqisters that should not be exceeded - * 4x 56 bit registers in register file Q - * 8x 48 bit registers in register file P - */ - -static inline void fir_32x16_hifiep(struct fir_state_32x16 *fir, int32_t x, - int32_t *y, int lshift, int rshift) -{ - /* This function uses - * 1x 56 bit registers Q, - * 4x 48 bit registers P - * 3x integers - * 2x address pointers, - */ - ae_q56s a; - ae_p24x2f data2; - ae_p24x2f coef2; - ae_p24x2f d0; - ae_p24x2f d1; - int i; - ae_p24x2f *dp = fir->rwp; - ae_p16x2s *coefp = fir->coef; - const int taps_div_4 = fir->taps >> 2; - const int inc = sizeof(int32_t); - - /* Bypass samples if taps count is zero. */ - if (!taps_div_4) { - *y = x; - return; - } - - /* Write sample to delay */ - a = AE_CVTQ48A32S(x); - AE_SQ32F_C(a, (ae_q32s *)fir->rwp, -sizeof(int32_t)); - - /* Note: If the next function is converted to handle two samples - * per call the data load can be done with single instruction - * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); - */ - a = AE_ZEROQ56(); - for (i = 0; i < taps_div_4; i++) { - /* Load two coefficients. Coef2_h contains tap coefp[n] - * and coef2_l contains coef[n+1]. - */ - coef2 = AE_LP16X2F_I(coefp, 0); - - /* Load two data samples and pack to d0 to data2_h and - * d1 to data2_l. - */ - AE_LP24F_C(d0, dp, inc); - AE_LP24F_C(d1, dp, inc); - data2 = AE_SELP24_LL(d0, d1); - - /* Accumulate - * data2_h * coef2_h + data2_l * coef2_l. The Q1.31 - * data and Q1.15 coefficients are used as 24 bits as - * Q1.23 values. - */ - AE_MULAAFP24S_HH_LL(a, data2, coef2); - - /* Repeat the same for next two taps and increase coefp. */ - coef2 = AE_LP16X2F_I(coefp, sizeof(ae_p16x2s)); - AE_LP24F_C(d0, dp, inc); - AE_LP24F_C(d1, dp, inc); - data2 = AE_SELP24_LL(d0, d1); - AE_MULAAFP24S_HH_LL(a, data2, coef2); - coefp += 2; - } - - /* Do scaling shifts and store sample. */ - a = AE_SRAAQ56(AE_SLLASQ56S(a, lshift), rshift); - AE_SQ32F_I(AE_ROUNDSQ32SYM(a), (ae_q32s *)y, 0); -} - -/* HiFi EP has the follow number of reqisters that should not be exceeded - * 4x 56 bit registers in register file Q - * 8x 48 bit registers in register file P - */ - -static inline void fir_32x16_2x_hifiep(struct fir_state_32x16 *fir, int32_t x0, - int32_t x1, int32_t *y0, int32_t *y1, - int lshift, int rshift) -{ - /* This function uses - * 2x 56 bit registers Q, - * 4x 48 bit registers P - * 3x integers - * 2x address pointers, - */ - ae_q56s a; - ae_q56s b; - ae_p24x2f d0; - ae_p24x2f d1; - ae_p24x2f d3; - ae_p24x2f coefs; - int i; - ae_p24x2f *dp; - ae_p16x2s *coefp = fir->coef; - const int taps_div_4 = fir->taps >> 2; - const int inc = 2 * sizeof(int32_t); - - /* Bypass samples if taps count is zero. */ - if (!taps_div_4) { - *y0 = x0; - *y1 = x1; - return; - } - - /* Write samples to delay */ - a = AE_CVTQ48A32S(x0); - AE_SQ32F_C(a, (ae_q32s *)fir->rwp, -sizeof(int32_t)); - a = AE_CVTQ48A32S(x1); - dp = fir->rwp; - AE_SQ32F_C(a, (ae_q32s *)fir->rwp, -sizeof(int32_t)); - - /* Note: If the next function is converted to handle two samples - * per call the data load can be done with single instruction - * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); - */ - a = AE_ZEROQ56(); - b = AE_ZEROQ56(); - /* Load two data samples and pack to d0 to data2_h and - * d1 to data2_l. - */ - AE_LP24X2F_C(d0, dp, inc); - for (i = 0; i < taps_div_4; i++) { - /* Load two coefficients. Coef2_h contains tap coefp[n] - * and coef2_l contains coef[n+1]. - */ - coefs = AE_LP16X2F_I(coefp, 0); - - /* Load two data samples. Upper part d1_h is x[n+1] and - * lower part d1_l is x[n]. - */ - AE_LP24X2F_C(d1, dp, inc); - - /* Accumulate - * b += d0_h * coefs_h + d0_l * coefs_l. The Q1.31 data - * and Q1.15 coefficients are converted to 24 bits as - * Q1.23 values. - */ - AE_MULAAFP24S_HH_LL(b, d0, coefs); - - /* Pack d0_l and d1_h to d3. Then accumulate - * a += d3_h * coefs_h + d3_l * coefs_l. Pass d1 to d1 for - * next unrolled iteration. - */ - d3 = AE_SELP24_LH(d0, d1); - AE_MULAAFP24S_HH_LL(a, d3, coefs); - d0 = d1; - - /* Repeat the same for next two taps and increase coefp. */ - coefs = AE_LP16X2F_I(coefp, sizeof(ae_p16x2s)); - AE_LP24X2F_C(d1, dp, inc); - AE_MULAAFP24S_HH_LL(b, d0, coefs); - d3 = AE_SELP24_LH(d0, d1); - AE_MULAAFP24S_HH_LL(a, d3, coefs); - d0 = d1; - coefp += 2; - } - - /* Do scaling shifts and store sample. */ - b = AE_SRAAQ56(AE_SLLASQ56S(b, lshift), rshift); - a = AE_SRAAQ56(AE_SLLASQ56S(a, lshift), rshift); - AE_SQ32F_I(AE_ROUNDSQ32SYM(b), (ae_q32s *)y1, 0); - AE_SQ32F_I(AE_ROUNDSQ32SYM(a), (ae_q32s *)y0, 0); -} - -#endif -#endif /* __SOF_AUDIO_EQ_FIR_FIR_HIFI2EP_H__ */ diff --git a/src/include/sof/audio/eq_fir/fir_hifi3.h b/src/include/sof/audio/eq_fir/fir_hifi3.h deleted file mode 100644 index c584272a2ea5..000000000000 --- a/src/include/sof/audio/eq_fir/fir_hifi3.h +++ /dev/null @@ -1,259 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_EQ_FIR_FIR_HIFI3_H__ -#define __SOF_AUDIO_EQ_FIR_FIR_HIFI3_H__ - -#include <sof/audio/eq_fir/fir_config.h> - -#if FIR_HIFI3 - -#include <sof/audio/buffer.h> -#include <xtensa/config/defs.h> -#include <xtensa/tie/xt_hifi3.h> - -struct sof_eq_fir_coef_data; - -struct fir_state_32x16 { - ae_int32 *rwp; /* Circular read and write pointer */ - ae_int32 *delay; /* Pointer to FIR delay line */ - ae_int32 *delay_end; /* Pointer to FIR delay line end */ - ae_f16x4 *coef; /* Pointer to FIR coefficients */ - int taps; /* Number of FIR taps */ - int length; /* Number of FIR taps plus input length (even) */ - int in_shift; /* Amount of right shifts at input */ - int out_shift; /* Amount of right shifts at output */ -}; - -void fir_reset(struct fir_state_32x16 *fir); - -int fir_delay_size(struct sof_eq_fir_coef_data *config); - -int fir_init_coef(struct fir_state_32x16 *fir, - struct sof_eq_fir_coef_data *config); - -void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data); - -#if CONFIG_FORMAT_S16LE -void eq_fir_s16_hifi3(struct fir_state_32x16 *fir, - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); - -void eq_fir_2x_s16_hifi3(struct fir_state_32x16 *fir, - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); -#endif /* CONFIG_FORMAT_S16LE */ - -#if CONFIG_FORMAT_S24LE -void eq_fir_s24_hifi3(struct fir_state_32x16 *fir, - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); - -void eq_fir_2x_s24_hifi3(struct fir_state_32x16 *fir, - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); -#endif /* CONFIG_FORMAT_S24LE */ - -#if CONFIG_FORMAT_S32LE -void eq_fir_s32_hifi3(struct fir_state_32x16 *fir, - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); - -void eq_fir_2x_s32_hifi3(struct fir_state_32x16 *fir, - const struct audio_stream *source, - struct audio_stream *sink, int frames, int nch); -#endif /* CONFIG_FORMAT_S32LE */ - -/* Setup circular buffer for FIR input data delay */ -static inline void fir_core_setup_circular(struct fir_state_32x16 *fir) -{ - AE_SETCBEGIN0(fir->delay); - AE_SETCEND0(fir->delay_end); -} - -/* Setup circular for component buffer */ -static inline void fir_comp_setup_circular(const struct audio_stream *buffer) -{ - AE_SETCBEGIN0(buffer->addr); - AE_SETCEND0(buffer->end_addr); -} - -void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, - int *rshift); - -/* The next functions are inlined to optmize execution speed */ - -/* HiFi EP has the follow number of reqisters that should not be exceeded - * 4x 56 bit registers in register file Q - * 8x 48 bit registers in register file P - */ - -static inline void fir_32x16_hifi3(struct fir_state_32x16 *fir, ae_int32 x, - ae_int32 *y, int shift) -{ - /* This function uses - * 1x 56 bit registers Q, - * 4x 48 bit registers P - * 3x integers - * 2x address pointers, - */ - ae_f64 a; - ae_valign u; - ae_f32x2 data2; - ae_f16x4 coefs; - ae_f32x2 d0; - ae_f32x2 d1; - int i; - ae_int32 *dp = fir->rwp; - ae_int16x4 *coefp = (ae_int16x4 *)fir->coef; - const int taps_div_4 = fir->taps >> 2; - const int inc = sizeof(int32_t); - - /* Bypass samples if taps count is zero. */ - if (!taps_div_4) { - *y = x; - return; - } - - /* Write sample to delay */ - AE_S32_L_XC(x, fir->rwp, -sizeof(int32_t)); - - /* Prime the coefficients stream */ - u = AE_LA64_PP(coefp); - - /* Note: If the next function is converted to handle two samples - * per call the data load can be done with single instruction - * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); - */ - a = AE_ZEROQ56(); - for (i = 0; i < taps_div_4; i++) { - /* Load four coefficients. Coef_3 contains tap h[n], - * coef_2 contains h[n+1], coef_1 contains h[n+2], and - * coef_0 contains h[n+3]; - */ - AE_LA16X4_IP(coefs, u, coefp); - - /* Load two data samples and pack to d0 to data2_h and - * d1 to data2_l. - */ - AE_L32_XC(d0, dp, inc); - AE_L32_XC(d1, dp, inc); - data2 = AE_SEL32_LL(d0, d1); - - /* Accumulate - * a += data2_h * coefs_3 + data2_l * coefs_2. The Q1.31 - * data and Q1.15 coefficients are used as 24 bits as - * Q1.23 values. - */ - AE_MULAAFD32X16_H3_L2(a, data2, coefs); - - /* Repeat the same for next two taps and increase coefp. - * a += data2_h * coefs_1 + data2_l * coefs_0. - */ - AE_L32_XC(d0, dp, inc); - AE_L32_XC(d1, dp, inc); - data2 = AE_SEL32_LL(d0, d1); - AE_MULAAFD32X16_H1_L0(a, data2, coefs); - } - - /* Do scaling shifts and store sample. */ - a = AE_SLAA64S(a, shift); - AE_S32_L_I(AE_ROUND32F48SSYM(a), (ae_int32 *)y, 0); -} - -/* HiFi EP has the follow number of reqisters that should not be exceeded - * 4x 56 bit registers in register file Q - * 8x 48 bit registers in register file P - */ - -static inline void fir_32x16_2x_hifi3(struct fir_state_32x16 *fir, ae_int32 x0, - ae_int32 x1, ae_int32 *y0, ae_int32 *y1, - int shift) -{ - /* This function uses - * 2x 56 bit registers Q, - * 4x 48 bit registers P - * 3x integers - * 2x address pointers, - */ - ae_f64 a; - ae_f64 b; - ae_valign u; - ae_f32x2 d0; - ae_f32x2 d1; - ae_f16x4 coefs; - int i; - ae_f32x2 *dp; - ae_f16x4 *coefp = fir->coef; - const int taps_div_4 = fir->taps >> 2; - const int inc = 2 * sizeof(int32_t); - - /* Bypass samples if taps count is zero. */ - if (!taps_div_4) { - *y0 = x0; - *y1 = x1; - return; - } - - /* Write samples to delay */ - AE_S32_L_XC(x0, fir->rwp, -sizeof(int32_t)); - dp = (ae_f32x2 *)fir->rwp; - AE_S32_L_XC(x1, fir->rwp, -sizeof(int32_t)); - - /* Note: If the next function is converted to handle two samples - * per call the data load can be done with single instruction - * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); - */ - a = AE_ZERO64(); - b = AE_ZERO64(); - - /* Prime the coefficients stream */ - u = AE_LA64_PP(coefp); - - /* Load two data samples and pack to d0 to data2_h and - * d1 to data2_l. - */ - AE_L32X2_XC(d0, dp, inc); - for (i = 0; i < taps_div_4; i++) { - /* Load four coefficients. Coef_3 contains tap h[n], - * coef_2 contains h[n+1], coef_1 contains h[n+2], and - * coef_0 contains h[n+3]; - */ - AE_LA16X4_IP(coefs, u, coefp); - - /* Load two data samples. Upper part d1_h is x[n+1] and - * lower part d1_l is x[n]. - */ - AE_L32X2_XC(d1, dp, inc); - - /* Quad MAC (HH) - * b += d0_h * coefs_3 + d0_l * coefs_2 - * a += d0_l * coefs_3 + d1_h * coefs_2 - */ - AE_MULAFD32X16X2_FIR_HH(b, a, d0, d1, coefs); - d0 = d1; - - /* Repeat the same for next two taps and increase coefp. */ - AE_L32X2_XC(d1, dp, inc); - - /* Quad MAC (HL) - * b += d0_h * coefs_1 + d0_l * coefs_0 - * a += d0_l * coefs_1 + d1_h * coefs_0 - */ - AE_MULAFD32X16X2_FIR_HL(b, a, d0, d1, coefs); - d0 = d1; - } - - /* Do scaling shifts and store sample. */ - b = AE_SLAA64S(b, shift); - a = AE_SLAA64S(a, shift); - AE_S32_L_I(AE_ROUND32F48SSYM(b), (ae_int32 *)y1, 0); - AE_S32_L_I(AE_ROUND32F48SSYM(a), (ae_int32 *)y0, 0); -} - -#endif -#endif /* __SOF_AUDIO_EQ_FIR_FIR_HIFI3_H__ */ diff --git a/src/include/sof/audio/eq_iir/eq_iir.h b/src/include/sof/audio/eq_iir/eq_iir.h deleted file mode 100644 index ac17190843d5..000000000000 --- a/src/include/sof/audio/eq_iir/eq_iir.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - * Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_EQ_IIR_EQ_IIR_H__ -#define __SOF_AUDIO_EQ_IIR_EQ_IIR_H__ - -#include <stdint.h> - -struct audio_stream; -struct comp_dev; - -/** \brief Type definition for processing function select return value. */ -typedef void (*eq_iir_func)(const struct comp_dev *dev, - const struct audio_stream *source, - struct audio_stream *sink, - uint32_t frames); - -/** \brief IIR EQ processing functions map item. */ -struct eq_iir_func_map { - uint8_t source; /**< source frame format */ - uint8_t sink; /**< sink frame format */ - eq_iir_func func; /**< processing function */ -}; - -#endif /* __SOF_AUDIO_EQ_IIR_EQ_IIR_H__ */ diff --git a/src/include/sof/audio/eq_iir/iir.h b/src/include/sof/audio/eq_iir/iir.h deleted file mode 100644 index 86d39fed104a..000000000000 --- a/src/include/sof/audio/eq_iir/iir.h +++ /dev/null @@ -1,79 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - * Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_EQ_IIR_IIR_H__ -#define __SOF_AUDIO_EQ_IIR_IIR_H__ - -#include <stddef.h> -#include <stdint.h> - -struct sof_eq_iir_header_df2t; - -/* Get platforms configuration */ -#include <config.h> - -/* If next defines are set to 1 the EQ is configured automatically. Setting - * to zero temporarily is useful is for testing needs. - * Setting EQ_FIR_AUTOARCH to 0 allows to manually set the code variant. - */ -#define IIR_AUTOARCH 1 - -/* Force manually some code variant when IIR_AUTOARCH is set to zero. These - * are useful in code debugging. - */ -#if IIR_AUTOARCH == 0 -#define IIR_GENERIC 1 -#define IIR_HIFI3 0 -#endif - -/* Select optimized code variant when xt-xcc compiler is used */ -#if IIR_AUTOARCH == 1 -#if defined __XCC__ -#include <xtensa/config/core-isa.h> -#if XCHAL_HAVE_HIFI3 == 1 -#define IIR_GENERIC 0 -#define IIR_HIFI3 1 -#else -#define IIR_GENERIC 1 -#define IIR_HIFI3 0 -#endif /* XCHAL_HAVE_HIFI3 */ -#else -/* GCC */ -#define IIR_GENERIC 1 -#define IIR_HIFI3 0 -#endif /* __XCC__ */ -#endif /* IIR_AUTOARCH */ - -#define IIR_DF2T_NUM_DELAYS 2 - -struct iir_state_df2t { - unsigned int biquads; /* Number of IIR 2nd order sections total */ - unsigned int biquads_in_series; /* Number of IIR 2nd order sections - * in series. - */ - int32_t *coef; /* Pointer to IIR coefficients */ - int64_t *delay; /* Pointer to IIR delay line */ -}; - -int32_t iir_df2t(struct iir_state_df2t *iir, int32_t x); - -int iir_init_coef_df2t(struct iir_state_df2t *iir, - struct sof_eq_iir_header_df2t *config); - -int iir_delay_size_df2t(struct sof_eq_iir_header_df2t *config); - -void iir_init_delay_df2t(struct iir_state_df2t *iir, int64_t **delay); - -void iir_mute_df2t(struct iir_state_df2t *iir); - -void iir_unmute_df2t(struct iir_state_df2t *iir); - -void iir_reset_df2t(struct iir_state_df2t *iir); - -#endif /* __SOF_AUDIO_EQ_IIR_IIR_H__ */ diff --git a/src/include/sof/audio/format.h b/src/include/sof/audio/format.h index 1c14d4efa490..a468278531f3 100644 --- a/src/include/sof/audio/format.h +++ b/src/include/sof/audio/format.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2016 Intel Corporation. All rights reserved. + * Copyright(c) 2016 - 2023 Intel Corporation. All rights reserved. * * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> * Liam Girdwood <liam.r.girdwood@linux.intel.com> @@ -10,6 +10,22 @@ #ifndef __SOF_AUDIO_FORMAT_H__ #define __SOF_AUDIO_FORMAT_H__ +#if defined __XCC__ +#include <xtensa/config/core-isa.h> +#if XCHAL_HAVE_HIFI3 == 1 +#define __AUDIO_FORMAT_GENERIC__ 0 +#define __AUDIO_FORMAT_HIFI3__ 1 +#else +/* Generic build for e.g. hifi2 */ +#define __AUDIO_FORMAT_GENERIC__ 1 +#define __AUDIO_FORMAT_HIFI3__ 0 +#endif /* !XCHAL_HAVE_HIFI3 */ +#else +/* GCC */ +#define __AUDIO_FORMAT_GENERIC__ 1 +#define __AUDIO_FORMAT_HIFI3__ 0 +#endif /* !__XCC__ */ + #include <ipc/stream.h> #include <stdint.h> @@ -17,7 +33,6 @@ #define INT24_MAXVALUE 8388607 #define INT24_MINVALUE -8388608 - /* Collection of common fractional numbers */ #define ONE_Q2_30 1073741824 /* Q2.30 1.0 */ #define ONE_Q1_31 2147483647 /* Q1.31 ~1.0 */ @@ -55,6 +70,9 @@ /* Convert fractional Qnx.ny number x to float */ #define Q_CONVERT_QTOF(x, ny) ((float)(x) / ((int64_t)1 << (ny))) +/* Convert fractional Qnx.ny number x to double */ +#define Q_CONVERT_QTOD(x, ny) ((double)(x) / ((int64_t)1 << (ny))) + /* A more clever macro for Q-shifts */ #define Q_SHIFT(x, src_q, dst_q) ((x) >> ((src_q) - (dst_q))) #define Q_SHIFT_RND(x, src_q, dst_q) \ @@ -63,6 +81,18 @@ /* Alternative version since compiler does not allow (x >> -1) */ #define Q_SHIFT_LEFT(x, src_q, dst_q) ((x) << ((dst_q) - (src_q))) +/* Fractional multiplication with shift + * Note that the parameters px and py must be cast to (int32_t) if other type. + */ +#define Q_MULTS_16X16(px, py, qx, qy, qp) \ + ((px) * (py) >> (((qx) + (qy) - (qp)))) + +/* Fractional multiplication with shift and round + * Note that the parameters px and py must be cast to (int32_t) if other type. + */ +#define Q_MULTSR_16X16(px, py, qx, qy, qp) \ + ((((px) * (py) >> ((qx) + (qy) - (qp) - 1)) + 1) >> 1) + /* Fractional multiplication with shift * Note that the parameters px and py must be cast to (int64_t) if other type. */ @@ -79,6 +109,15 @@ #define SATP_INT32(x) (((x) > INT32_MAX) ? INT32_MAX : (x)) #define SATM_INT32(x) (((x) < INT32_MIN) ? INT32_MIN : (x)) +/* Inline functions */ + +#if __AUDIO_FORMAT_GENERIC__ +#include "format_generic.h" +#endif +#if __AUDIO_FORMAT_HIFI3__ +#include "format_hifi3.h" +#endif + static inline int64_t q_mults_32x32(int32_t x, int32_t y, const int shift_bits) { return ((int64_t)x * y) >> shift_bits; @@ -99,38 +138,6 @@ static inline int16_t q_multsr_16x16(int16_t x, int32_t y, const int shift_bits) return ((((int32_t)x * y) >> (shift_bits - 1)) + 1) >> 1; } -/* Saturation inline functions */ - -static inline int32_t sat_int32(int64_t x) -{ - if (x > INT32_MAX) - return INT32_MAX; - else if (x < INT32_MIN) - return INT32_MIN; - else - return (int32_t)x; -} - -static inline int32_t sat_int24(int32_t x) -{ - if (x > INT24_MAXVALUE) - return INT24_MAXVALUE; - else if (x < INT24_MINVALUE) - return INT24_MINVALUE; - else - return x; -} - -static inline int16_t sat_int16(int32_t x) -{ - if (x > INT16_MAX) - return INT16_MAX; - else if (x < INT16_MIN) - return INT16_MIN; - else - return (int16_t)x; -} - /* Fractional multiplication with shift and saturation */ static inline int32_t q_multsr_sat_32x32(int32_t x, int32_t y, const int shift_bits) @@ -161,15 +168,4 @@ static inline int32_t sign_extend_s24(int32_t x) return (x << 8) >> 8; } -static inline uint32_t get_sample_bytes(enum sof_ipc_frame fmt) -{ - return fmt == SOF_IPC_FRAME_S16_LE ? 2 : 4; -} - -static inline uint32_t get_frame_bytes(enum sof_ipc_frame fmt, - uint32_t channels) -{ - return get_sample_bytes(fmt) * channels; -} - #endif /* __SOF_AUDIO_FORMAT_H__ */ diff --git a/src/include/sof/audio/format_generic.h b/src/include/sof/audio/format_generic.h new file mode 100644 index 000000000000..b63284cb872e --- /dev/null +++ b/src/include/sof/audio/format_generic.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_AUDIO_FORMAT_GENERIC_H__ +#define __SOF_AUDIO_FORMAT_GENERIC_H__ + +#include <stdint.h> + +/* Saturation inline functions */ + +static inline int32_t sat_int32(int64_t x) +{ + if (x > INT32_MAX) + return INT32_MAX; + else if (x < INT32_MIN) + return INT32_MIN; + else + return (int32_t)x; +} + +static inline int32_t sat_int24(int32_t x) +{ + if (x > INT24_MAXVALUE) + return INT24_MAXVALUE; + else if (x < INT24_MINVALUE) + return INT24_MINVALUE; + else + return x; +} + +static inline int16_t sat_int16(int32_t x) +{ + if (x > INT16_MAX) + return INT16_MAX; + else if (x < INT16_MIN) + return INT16_MIN; + else + return (int16_t)x; +} + +static inline int8_t sat_int8(int32_t x) +{ + if (x > INT8_MAX) + return INT8_MAX; + else if (x < INT8_MIN) + return INT8_MIN; + else + return (int8_t)x; +} + +#endif /* __SOF_AUDIO_FORMAT_GENERIC_H__ */ diff --git a/src/include/sof/audio/format_hifi3.h b/src/include/sof/audio/format_hifi3.h new file mode 100644 index 000000000000..762d57ab41ff --- /dev/null +++ b/src/include/sof/audio/format_hifi3.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_FORMAT_HIFI3_H__ +#define __SOF_AUDIO_FORMAT_HIFI3_H__ + +#include <stdint.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi3.h> + +/* Saturation inline functions */ + +/** + * @brief Saturate a 64-bit integer to 32-bit. + * + * @param x 64-bit integer. + * @return 32-bit saturated integer. + * + * This function takes a 64-bit integer, performs bitwise shifting, + * and returns a saturated 32-bit integer. + */ +static inline int32_t sat_int32(int64_t x) +{ + /* Shift left by 32 bits with saturation */ + ae_f64 shifted = AE_SLAI64S(x, 32); + + /* Shift right by 32 bits */ + return (int32_t)AE_MOVINT32_FROMINT64(AE_SRAI64(shifted, 32)); +} + +/** + * @brief Saturate and round two 64-bit integers to 32-bit packed into a 32x2 vector. + * + * @param x 64-bit integer. + * @param y 64-bit integer. + * @return Packed 32-bit saturated integers. + * + * This function takes two 64-bit integers, converts them to ae_f64 format, + * and returns them as a packed ae_int32x2 vector after saturation. + */ +static inline ae_int32x2 vec_sat_int32x2(int64_t x, int64_t y) +{ + ae_f64 d0, d1; + + /* Convert 64-bit integers to ae_f64 format */ + d0 = (ae_f64)x; + d1 = (ae_f64)y; + + /* Round and saturate both 64-bit values to 32-bit and pack them */ + return (ae_int32x2)AE_ROUND32X2F64SSYM(d0, d1); +} + +/** + * @brief Saturate and round a 32-bit integer to 24-bit. + * + * @param x 32-bit integer. + * @return 24-bit saturated integer. + * + * This function takes a 32-bit integer and saturates it to a 24-bit integer + * using saturating arithmetic instructions. + */ +static inline int32_t sat_int24(int32_t x) +{ + /* Move 32-bit value to ae_f32x2 type */ + ae_f32x2 d0 = AE_MOVDA32(x); + + /* Saturate to 24-bit */ + return (ae_int32)AE_SAT24S(d0); +} + +/** + * @brief Saturate and round two 32-bit integers to 24-bit packed into a 32x2 vector. + * + * @param x 32-bit integer. + * @param y 32-bit integer. + * @return Packed 24-bit saturated integers. + * + * This function takes two 32-bit integers, packs them into a 32x2 vector, + * and performs saturation to 24-bit on each element. + */ +static inline ae_int32x2 vec_sat_int24x2(int32_t x, int32_t y) +{ + /* Move two 32-bit values to ae_f32x2 type */ + ae_f32x2 d0 = AE_MOVDA32X2(x, y); + + /* Saturate both values to 24-bit and pack them */ + return (ae_int32x2)AE_SAT24S(d0); +} + +/** + * @brief Saturate a 32-bit integer to 16-bit. + * + * @param x 32-bit integer. + * @return 16-bit saturated integer. + * + * This function takes a 32-bit integer, packs it into a vector, + * and performs saturation to 16-bit on each element. + */ +static inline int16_t sat_int16(int32_t x) +{ + /* Move 32-bit value to ae_int32x2 type */ + ae_int32x2 d0 = AE_MOVDA32(x); + + /* Saturate both values to 16-bit and pack them */ + ae_int16x4 result = AE_SAT16X4(d0, d0); + + /* Use AE_MOVAD16_0 to extract the first 16-bit value */ + return AE_MOVAD16_0(result); +} + +/** + * @brief Saturate and round four 32-bit integers to 16-bit packed into a 16x4 vector. + * + * @param x 32-bit integer. + * @param y 32-bit integer. + * @param z 32-bit integer. + * @param q 32-bit integer. + * @return Packed 16-bit saturated integers. + * + * This function takes four 32-bit integers, packs them into two 32x2 vectors, + * and performs 16-bit saturation on each element, returning the result in a 16x4 vector. + */ +static inline ae_int16x4 vec_sat_int16x4(int32_t x, int32_t y, int32_t z, int32_t q) +{ + /* Move four 32-bit values to ae_int32x2 type */ + ae_int32x2 d0 = AE_MOVDA32X2(x, y); + ae_int32x2 d1 = AE_MOVDA32X2(z, q); + + /* Saturate all values to 16-bit and pack them */ + return AE_SAT16X4(d0, d1); +} + +/** + * @brief Saturate and round a 32-bit integer to 8-bit. + * + * @param x 32-bit integer. + * @return 8-bit saturated integer. + * + * This function takes a 32-bit integer, performs bitwise operations to extract the lower 8 + * bits, and returns an 8-bit saturated integer. + */ +static inline int8_t sat_int8(int32_t x) +{ + /* Shift left by 24 bits */ + ae_f32x2 a_i = AE_SLAI32S(x, 24); + + /* Shift right by 24 bits to sign-extend the 8-bit value */ + a_i = AE_SRAI32(a_i, 24); + + /* Extract the lower 8 bits as an int8_t */ + return (int8_t)AE_MOVAD32_L(a_i); +} + +/** + * @brief Saturate and round two 32-bit integers to 8-bit packed into an 8x2 vector. + * + * @param x 32-bit integer. + * @param y 32-bit integer. + * @return Packed 8-bit saturated integers. + * + * This function takes two 32-bit integers, packs them into a 32x2 vector, + * and performs 8-bit saturation on each element, returning the result in an 8x2 vector. + */ +static inline ae_int32x2 vec_sat_int8x2(int32_t x, int32_t y) +{ + /* Move two 32-bit values to ae_f32x2 type */ + ae_f32x2 d0 = AE_MOVDA32X2(x, y); + + /* Shift left by 24 bits and then right by 24 bits to sign-extend and saturate */ + return AE_F32X2_SRAI(AE_F32X2_SLAIS(d0, 24), 24); +} + +#endif /* __SOF_AUDIO_FORMAT_HIFI3_H__ */ diff --git a/src/include/sof/audio/igo_nr/igo_lib.h b/src/include/sof/audio/igo_nr/igo_lib.h new file mode 100644 index 000000000000..1348c821bbdb --- /dev/null +++ b/src/include/sof/audio/igo_nr/igo_lib.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intelligo Technology Inc. All rights reserved. + * + * Author: Fu-Yun TSUO <fy.tsuo@intelli-go.com> + */ + +/******************************************************************************* + * [2017] - [2021] Copyright (c) Intelligo Technology Inc. + * + * This unpublished material is proprietary to Intelligo Technology Inc. + * All rights reserved. The methods and techniques described herein are + * considered trade secrets and/or confidential. Reproduction or + * distribution, in whole or in part, is forbidden except by express written + * permission of Intelligo Technology Inc. + * + *******************************************************************************/ + +#ifndef _IGO_LIB_H_ +#define _IGO_LIB_H_ + +#include <stdint.h> + +enum IgoRet { + IGO_RET_OK = 0, + IGO_RET_ERR, + IGO_RET_NO_SERVICE, + IGO_RET_INVL_ARG, + IGO_RET_NO_MEMORY, + IGO_RET_NOT_SUPPORT, + IGO_RET_ALGO_NAME_NOT_FOUND, + IGO_RET_CH_NUM_ERR, + IGO_RET_SAMPLING_RATE_NOT_SUPPORT, + IGO_RET_IN_DATA_ERR, + IGO_RET_REF_DATA_ERR, + IGO_RET_OUT_DATA_ERR, + IGO_RET_PARAM_NOT_FOUND, + IGO_RET_PARAM_READ_ONLY, + IGO_RET_PARAM_WRITE_ONLY, + IGO_RET_PARAM_INVALID_VAL, + IGO_RET_LAST +}; + +enum IgoDataWidth { + IGO_DATA_16BIT = 0, + IGO_DATA_24BIT, + IGO_DATA_LAST +}; + +/** + * @brief IgoLibInfo is used to keep information for iGo library. + * + */ +struct IgoLibInfo { + uint32_t major_version; /* Major version */ + uint32_t minor_version; /* Minor version */ + uint32_t build_version; /* Build version */ + uint32_t ext_version; /* Extension version */ + uint32_t handle_size; /* Size of handle structure */ +}; + +/** + * @brief IgoStreamData is used to keep audio data for iGo library. + * + */ +struct IgoStreamData { + void *data; /* Data array */ + enum IgoDataWidth data_width; /* Specify audio data bit width */ + uint16_t sample_num; /* Sample number in this data bulk */ + uint16_t sampling_rate; /* Sampling rate for the data stream */ +}; + +/** + * @brief IgoLibConfig is used to keep lib configuration for lib instance + * initialization. + * + */ +struct IgoLibConfig { + const char *algo_name; /* Algorithm name */ + uint8_t in_ch_num; /* Input channel number for the algo instance */ + uint8_t ref_ch_num; /* Reference channel number for the algo instance */ + uint8_t out_ch_num; /* Output channel number for the algo instance */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief IgoLibGetInfo() - Retrieve the lib information. + * @param[out] info Lib information. + * + * This API is used to get library detail information. + * + * @return iGo defined return value. + */ +enum IgoRet IgoLibGetInfo(struct IgoLibInfo *info); + +/** + * @brief IgoLibInit() - Initialize iGo lib instance. + * @param[out] handle iGo lib handle. + * @param[in] config Lib configuration for initialization. + * @param[in] param the point of iGO Parameter for initialization. + * + * This API is used to initialize iGo lib instance and get a handle which is + * for control the iGo lib instance. + * + * P.S. The channel number in the config is algorithm dependent. + * + * @return iGo defined return value. + */ +enum IgoRet IgoLibInit(void *handle, + const struct IgoLibConfig *config, + void *param); + +/** + * @brief IgoLibProcess() - Process audio stream. + * @param[in] handle iGo lib handle. + * @param[in] in input audio stream. + * @param[in] ref reference audio stream. + * @param[out] out output audio stream. + * + * This API is used to process audio stream. The default audio sample is 16bit. + * The sampling rate and sample number should be specified in IgoStreamData + * structure. If the channel number > 1 for IgoStreamData, the data should be + * interleaved sample by sample. + * + * Note: IgoLibProcess supports 16k/48k 16bit data only by default. + * If other data format or sampling rate is required, please + * ask intelliGo for support. + * + * @return iGo defined return value. + */ +enum IgoRet IgoLibProcess(void *handle, + const struct IgoStreamData *in, + const struct IgoStreamData *ref, + const struct IgoStreamData *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/sof/audio/igo_nr/igo_nr_comp.h b/src/include/sof/audio/igo_nr/igo_nr_comp.h new file mode 100644 index 000000000000..d494baf32c6b --- /dev/null +++ b/src/include/sof/audio/igo_nr/igo_nr_comp.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intelligo Technology Inc. All rights reserved. + * + * Author: Fu-Yun TSUO <fy.tsuo@intelli-go.com> + */ + +#ifndef __SOF_AUDIO_IGO_NR_CONFIG_H__ +#define __SOF_AUDIO_IGO_NR_CONFIG_H__ + +#include <sof/platform.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/igo_nr/igo_lib.h> +#include <user/igo_nr.h> + +#define IGO_FRAME_SIZE (768) +#define IGO_NR_IN_BUF_LENGTH (IGO_FRAME_SIZE) +#define IGO_NR_OUT_BUF_LENGTH (IGO_FRAME_SIZE) + +/* IGO_NR component private data */ +struct comp_data { + void *p_handle; + struct IgoLibInfo igo_lib_info; + struct IgoLibConfig igo_lib_config; + struct IgoStreamData igo_stream_data_in; + struct IgoStreamData igo_stream_data_ref; + struct IgoStreamData igo_stream_data_out; + struct comp_data_blob_handler *model_handler; + int16_t in[IGO_NR_IN_BUF_LENGTH]; /**< input samples buffer */ + int16_t out[IGO_NR_IN_BUF_LENGTH]; /**< output samples mix buffer */ + bool process_enable[SOF_IPC_MAX_CHANNELS]; /**< set if channel process is enabled */ + bool invalid_param; /**< sample rate != 16000 */ + uint32_t sink_rate; /* Sample rate in Hz */ + uint32_t source_rate; /* Sample rate in Hz */ + uint32_t sink_format; /* For used PCM sample format */ + uint32_t source_format; /* For used PCM sample format */ + int (*igo_nr_func)(struct comp_data *cd, + struct sof_source *source, + struct sof_sink *sink, + int32_t frames); + struct sof_igo_nr_config config; /**< blob data buffer */ +}; + +#endif /* __SOF_AUDIO_IGO_NR_CONFIG_H__ */ diff --git a/src/include/sof/audio/ipc-config.h b/src/include/sof/audio/ipc-config.h new file mode 100644 index 000000000000..1eb6b9cca555 --- /dev/null +++ b/src/include/sof/audio/ipc-config.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_AUDIO_IPC_CONFIG_H__ +#define __SOF_AUDIO_IPC_CONFIG_H__ + +#include <stdint.h> +#include <stdbool.h> + +/* 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. + */ + +/* generic host component */ +struct ipc_config_host { + uint32_t direction; /**< SOF_IPC_STREAM_ */ + uint32_t no_irq; /**< don't send periodic IRQ to host/DSP */ + uint32_t dmac_config; /**< DMA engine specific */ + uint32_t dma_buffer_size; /**< Requested DMA buffer size */ + uint32_t feature_mask; /**< copier feature mask (set directly from + * ipc4_copier_module_cfg on init) + */ +}; + +/* generic DAI component */ +struct ipc_config_dai { + uint32_t direction; /**< SOF_IPC_STREAM_ */ + uint32_t dai_index; /**< index of this type dai */ + uint32_t type; /**< DAI type - SOF_DAI_ */ + uint32_t dma_buffer_size; /**< Requested DMA buffer size */ + /* physical protocol and clocking */ + uint32_t sampling_frequency; /**< DAI sampling frequency - required only with IPC4 */ + uint16_t format; /**< SOF_DAI_FMT_ */ + uint16_t group_id; /**< group ID, 0 means no group (ABI 3.17) */ + bool is_config_blob; /**< DAI specific configuration is a blob */ + uint32_t feature_mask; /**< copier feature mask (set directly from + * ipc4_copier_module_cfg on init) + */ + /**< DMA configs - required for ACE 2.0 and newer */ + struct ipc_dma_config *host_dma_config[GTW_DMA_DEVICE_MAX_COUNT]; + const struct ipc4_audio_format *gtw_fmt;/**< audio format for gateway DMA data - required + * for ACE 2.0 and newer + */ + /* Gain feature flag */ + bool apply_gain; +}; + +/* generic volume component */ +struct ipc_config_volume { + uint32_t channels; + uint32_t min_value; + uint32_t max_value; + uint32_t ramp; /**< SOF_VOLUME_ */ + uint32_t initial_ramp; /**< ramp space in ms */ +}; + +/* generic SRC component */ +struct ipc_config_src { + /* either source or sink rate must be non zero */ + uint32_t source_rate; /**< source rate or 0 for variable */ + uint32_t sink_rate; /**< sink rate or 0 for variable */ + uint32_t rate_mask; /**< SOF_RATE_ supported rates */ +}; + +/* generic ASRC component */ +struct ipc_config_asrc { + /* either source or sink rate must be non zero */ + uint32_t source_rate; /**< Define fixed source rate or */ + /**< use 0 to indicate need to get */ + /**< the rate from stream */ + uint32_t sink_rate; /**< Define fixed sink rate or */ + /**< use 0 to indicate need to get */ + /**< the rate from stream */ + uint32_t asynchronous_mode; /**< synchronous 0, asynchronous 1 */ + /**< When 1 the ASRC tracks and */ + /**< compensates for drift. */ + uint32_t operation_mode; /**< push 0, pull 1, In push mode the */ + /**< ASRC consumes a defined number */ + /**< of frames at input, with varying */ + /**< number of frames at output. */ + /**< In pull mode the ASRC outputs */ + /**< a defined number of frames while */ + /**< number of input frames varies. */ +}; + +/* generic tone generator component */ +struct ipc_config_tone { + int32_t sample_rate; + int32_t frequency; + int32_t amplitude; + int32_t freq_mult; + int32_t ampl_mult; + int32_t length; + int32_t period; + int32_t repeats; + int32_t ramp_step; +}; + +/* generic "effect", "codec" or proprietary processing component */ +struct ipc_config_process { + uint32_t size; /**< size of bespoke data section in bytes */ + uint32_t type; /**< sof_ipc_process_type */ + + const unsigned char *data; +}; + +/* file IO ipc comp */ +struct ipc_comp_file { + struct ipc_config_process module_header; /* Needed for module_adapter_init_data() */ + uint32_t rate; + uint32_t channels; + char *fn; + uint32_t mode; + uint32_t frame_fmt; + uint32_t direction; /**< SOF_IPC_STREAM_ */ +} __attribute__((packed, aligned(4))); + +#endif diff --git a/src/include/sof/audio/kpb.h b/src/include/sof/audio/kpb.h index 8ee2f7fa52ca..14c7b33a38e9 100644 --- a/src/include/sof/audio/kpb.h +++ b/src/include/sof/audio/kpb.h @@ -12,39 +12,72 @@ #include <user/trace.h> #include <stdint.h> +#if defined(__XCC__) + +#include <xtensa/config/core-isa.h> +#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4 +#define KPB_HIFI3 +#endif + +#endif struct comp_buffer; /* KPB internal defines */ + +#if CONFIG_TIGERLAKE +#define KPB_MAX_BUFF_TIME 3000 /**< time of buffering in miliseconds */ +#define HOST_WAKEUP_TIME 1000 /* aprox. time of host DMA wakup from suspend [ms] */ +#else +/** Due to memory constraints on non-TGL platforms, the buffers are smaller. */ #define KPB_MAX_BUFF_TIME 2100 /**< time of buffering in miliseconds */ -#define KPB_MAX_SUPPORTED_CHANNELS 2 /**< number of supported channels */ +#define HOST_WAKEUP_TIME 0 /* aprox. time of host DMA wakup from suspend [ms] */ +#endif + +#define KPB_MAX_DRAINING_REQ (KPB_MAX_BUFF_TIME - HOST_WAKEUP_TIME) +#define KPB_MAX_SUPPORTED_CHANNELS 6 /**< number of supported channels */ /**< number of samples taken each milisecond */ #define KPB_SAMPLES_PER_MS (KPB_SAMPLNG_FREQUENCY / 1000) #define KPB_SAMPLNG_FREQUENCY 16000 /**< supported sampling frequency in Hz */ -#define KPB_NUM_OF_CHANNELS 2 #define KPB_SAMPLE_CONTAINER_SIZE(sw) ((sw == 16) ? 16 : 32) -#define KPB_MAX_BUFFER_SIZE(sw) ((KPB_SAMPLNG_FREQUENCY / 1000) * \ +#define KPB_MAX_BUFFER_SIZE(sw, channels_number) ((KPB_SAMPLNG_FREQUENCY / 1000) * \ (KPB_SAMPLE_CONTAINER_SIZE(sw) / 8) * KPB_MAX_BUFF_TIME * \ - KPB_NUM_OF_CHANNELS) -#define KPB_MAX_NO_OF_CLIENTS 2 + (channels_number)) +#define KPB_MAX_NO_OF_CLIENTS 4 +#define KPB_MAX_SINK_CNT (1 + KPB_MAX_NO_OF_CLIENTS) #define KPB_NO_OF_HISTORY_BUFFERS 2 /**< no of internal buffers */ #define KPB_ALLOCATION_STEP 0x100 -#define KPB_NO_OF_MEM_POOLS 3 -#define KPB_BYTES_TO_FRAMES(bytes, sample_width) \ - (bytes / ((KPB_SAMPLE_CONTAINER_SIZE(sample_width) / 8) * \ - KPB_NUM_OF_CHANNELS)) +#define KPB_NO_OF_MEM_POOLS 5 +#define KPB_BYTES_TO_FRAMES(bytes, sample_width, channels_number) \ + ((bytes) / ((KPB_SAMPLE_CONTAINER_SIZE(sample_width) / 8) * \ + (channels_number))) /**< Defines how much faster draining is in comparison to pipeline copy. */ #define KPB_DRAIN_NUM_OF_PPL_PERIODS_AT_ONCE 2 /**< Host buffer shall be at least two times bigger than history buffer. */ -#define HOST_BUFFER_MIN_SIZE(hb) (hb * 2) +#define HOST_BUFFER_MIN_SIZE(hb, channels_number) ((hb) * (channels_number)) + +/**< Convert with right shift a bytes count to samples count */ +#define KPB_BYTES_TO_S16_SAMPLES(s) ((s) >> 1) +#define KPB_BYTES_TO_S32_SAMPLES(s) ((s) >> 2) + +/* Macro that returns mask with selected bits set */ +#define KPB_COUNT_TO_BITMASK(cnt) (((0x1 << (cnt)) - 1)) +#define KPB_IS_BIT_SET(value, idx) ((value) & (1 << (idx))) +#define KPB_REFERENCE_SUPPORT_CHANNELS 2 +/* Maximum number of channels in the micsel mask is 4, + * i.e. number of max supported channels - reference channels) + */ +#define KPB_MAX_MICSEL_CHANNELS 4 +/* Used in FMT */ +#define FAST_MODE_TASK_MAX_MODULES_COUNT 16 +#define REALTIME_PIN_ID 0 /** All states below as well as relations between them are documented in * the sof-dosc in [kpbm-state-diagram] * Therefore any addition of new states or modification of existing ones * should have a corresponding update in the sof-docs. - * [kpbm-state-diagram]: https://thesofproject.github.io/latest/ - * developer_guides/firmware/kd_integration/ - * kd-integration.html#kpbm-state-diagram "Keyphrase buffer manager state - * diagram" + * [kpbm-state-diagram]: +https://thesofproject.github.io/latest/developer_guides/firmware/kd_integration/kd-integration.html#kpbm-state-diagram +"Keyphrase buffer manager state diagram" */ enum kpb_state { KPB_STATE_DISABLED = 0, @@ -81,7 +114,7 @@ enum kpb_client_state { struct kpb_client { uint8_t id; /**< id associated with output sink */ - uint32_t history_depth; /**< normalized value of buffered bytes */ + uint32_t drain_req; /**< normalized value of buffered bytes */ enum kpb_client_state state; /**< current state of a client */ void *r_ptr; /**< current read position */ struct comp_buffer *sink; /**< client's sink */ @@ -98,27 +131,126 @@ enum kpb_id { KPB_HP, }; -struct hb { +struct history_buffer { enum buffer_state state; /**< state of the buffer */ void *start_addr; /**< buffer start address */ void *end_addr; /**< buffer end address */ void *w_ptr; /**< buffer write pointer */ void *r_ptr; /**< buffer read pointer */ - struct hb *next; /**< next history buffer */ - struct hb *prev; /**< next history buffer */ + struct history_buffer *next; /**< next history buffer */ + struct history_buffer *prev; /**< next history buffer */ }; -struct dd { +/* Draining task data */ +struct draining_data { struct comp_buffer *sink; - struct hb *history_buffer; - size_t history_depth; + struct history_buffer *hb; + size_t drain_req; + size_t drained; uint8_t is_draining_active; size_t sample_width; size_t buffered_while_draining; + uint64_t draining_time_start; size_t drain_interval; + uint64_t period_copy_start; size_t pb_limit; /**< Period bytes limit */ + size_t period_bytes; + uint64_t next_copy_time; struct comp_dev *dev; bool sync_mode_on; + enum comp_copy_type copy_type; + size_t task_iteration; + uint64_t prev_adjustment_time; + size_t prev_adjustment_drained; +}; + +struct history_data { + size_t buffer_size; /**< size of internal history buffer */ + size_t buffered; /**< amount of buffered data */ + size_t free; /** spce we can use to write new data */ + struct history_buffer *c_hb; /**< current buffer used for writing */ +}; + +/* moved to ipc4/kpb.h */ +/* enum ipc4_kpb_module_config_params */ + +/* Stores KPB mic selector config */ +struct kpb_micselector_config { + /* channel bit set to 1 implies channel selection */ + uint32_t mask; +}; + +struct kpb_task_params { + /* If largeconfigset is set to KP_POS_IN_BUFFER then number of modules must + * correspond to number of modules between kpb and copier attached to hostdma. + * Once draining path is configured, cannot be reinitialized/changed. + */ + uint32_t number_of_modules; + struct { + uint16_t module_id; + uint16_t instance_id; + } dev_ids[1]; +}; + +/* fmt namespace: */ +#define FAST_MODE_TASK_MAX_LIST_COUNT 5 + +struct fast_mode_task { + /*! Array of pointers to all module lists to be processed. */ + struct device_list *device_list[FAST_MODE_TASK_MAX_LIST_COUNT]; +}; + +/* The +1 is here because we also push the kbp device + * handle in addition to the max number of modules + */ +#define DEVICE_LIST_SIZE (FAST_MODE_TASK_MAX_MODULES_COUNT + 1) + +/* Devicelist type + * In Reference FW KPB used Bi-dir lists to store modules for FMT. It is possible that lists are + * not necessary, but in case it might be wrong, here we use an array + * with a list interface to switch it to a list easily. + */ +struct device_list { + struct comp_dev **devs[DEVICE_LIST_SIZE]; + /* number of items AND index of next empty box */ + size_t count; +}; + +/* + * + * + * KPB FMT config set steps: + * 1. Get dev_ids of module instances from IPC + * 2. Alloc this kpb module instance on kpb_list_item, save address of where it was allocated + * 3. Push the address on dev_list.device_list + * 2. For each dev_id get device handler(module instance) + * 3. Alloc device handler in modules_list_item, save address of where it was allocated + * 4. Register this address in fmt.device_list + * + * Pointer structure: + * + * COMP_DEVS + * ^ + * | + * dev_list.modules_list_item(comp_dev* ) + * ^ + * | + * dev_list.device_list(comp_dev**) + * ^ + * | + * fmt.device_list(device_list*) + * + * + */ + +/* KpbFastModeTaskModulesList Namespace */ +struct kpb_fmt_dev_list { + /*! Array of all module lists to be processed. */ + struct device_list device_list[FAST_MODE_TASK_MAX_LIST_COUNT]; + /* One for each sinkpin. */ + struct comp_dev *kpb_list_item[KPB_MAX_SINK_CNT]; + struct comp_dev *modules_list_item[FAST_MODE_TASK_MAX_MODULES_COUNT]; + struct comp_dev *kpb_mi_ptr; }; #ifdef UNIT_TEST diff --git a/src/include/sof/audio/mfcc/mfcc_comp.h b/src/include/sof/audio/mfcc/mfcc_comp.h new file mode 100644 index 000000000000..025eef116752 --- /dev/null +++ b/src/include/sof/audio/mfcc/mfcc_comp.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2026 Intel Corporation. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_MFCC_MFCC_COMP_H__ +#define __SOF_AUDIO_MFCC_MFCC_COMP_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/auditory.h> +#include <sof/math/dct.h> +#include <sof/math/fft.h> +#include <stddef.h> +#include <stdint.h> + +/* __XCC__ is both for xt_xcc and xt_clang */ +#if defined(__XCC__) +# include <xtensa/config/core-isa.h> +# if XCHAL_HAVE_HIFI4 || XCHAL_HAVE_HIFI5 +# define MFCC_HIFI4 +# elif XCHAL_HAVE_HIFI3 +# define MFCC_HIFI3 +# else +# define MFCC_GENERIC +# endif +#else +# define MFCC_GENERIC +#endif + +#define MFCC_MAGIC 0x6d666363 /* ASCII for "mfcc" */ +#define MFCC_FFT_BITS 32 + +/** \brief Type definition for processing function select return value. */ +typedef void (*mfcc_func)(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, + int frames); + +/** \brief MFCC processing functions map item. */ +struct mfcc_func_map { + uint8_t source; /**< source frame format */ + mfcc_func func; /**< processing function */ +}; + +struct mfcc_buffer { + int16_t *addr; + int16_t *end_addr; + int16_t *r_ptr; + int16_t *w_ptr; + int s_avail; /**< samples count */ + int s_free; /**< samples count */ + int s_length; /**< length in samples for wrap */ +}; + +struct mfcc_pre_emph { + int16_t coef; + int16_t delay; + int enable; +}; + +struct mfcc_fft { + struct icomplex32 *fft_buf; /**< fft_padded_size */ + struct icomplex32 *fft_out; /**< fft_padded_size */ + struct fft_plan *fft_plan; + int fft_fill_start_idx; /**< Set to 0 for pad left, etc. */ + int fft_size; + int fft_padded_size; + int fft_hop_size; + int fft_buf_size; + int half_fft_size; + size_t fft_buffer_size; /**< bytes */ +}; + +struct mfcc_cepstral_lifter { + struct mat_matrix_16b *matrix; + int16_t cepstral_lifter; + int num_ceps; +}; + +struct mfcc_state { + struct mfcc_buffer buf; /**< Circular buffer for input data */ + struct mfcc_pre_emph emph; /**< Pre-emphasis filter */ + struct mfcc_fft fft; /**< FFT related */ + struct dct_plan_16 dct; /**< DCT related */ + struct psy_mel_filterbank melfb; /**< Mel filter bank */ + struct mfcc_cepstral_lifter lifter; /**< Cepstral lifter coefficients */ + struct mat_matrix_16b *mel_spectra; /**< Pointer to scratch */ + struct mat_matrix_16b *cepstral_coef; /**< Pointer to scratch */ + int32_t *power_spectra; /**< Pointer to scratch */ + int32_t *mel_log_32; /**< Pointer to scratch for 32-bit Mel output Q9.23 */ + int32_t mmax; /**< Maximum Mel value in Q9.23 */ + int16_t buf_avail; + int16_t *buffers; + int16_t *prev_data; /**< prev_data_size */ + int16_t *window; /**< fft_size */ + int16_t *triangles; + int source_channel; + int buffer_size; + int prev_data_size; + int low_freq; + int high_freq; + int sample_rate; + bool mel_only; /**< When true, output Mel spectra instead of cepstral coefficients */ + bool waiting_fill; /**< booleans */ + bool prev_samples_valid; + bool magic_pending; /**< True when magic word not yet written for current output */ + size_t sample_buffers_size; /**< bytes */ + int16_t *out_data_ptr; /**< Read pointer into scratch data for multi-period output */ + int32_t *out_data_ptr_32; /**< Read pointer for 32-bit mel-only output */ + int out_remain; /**< Remaining int16_t samples to write to sink from scratch */ +}; + +/* MFCC component private data */ +struct mfcc_comp_data { + struct mfcc_state state; + struct comp_data_blob_handler *model_handler; + struct sof_mfcc_config *config; + int max_frames; + mfcc_func mfcc_func; /**< processing function */ +}; + +static inline int mfcc_buffer_samples_without_wrap(struct mfcc_buffer *buffer, int16_t *ptr) +{ + return buffer->end_addr - ptr; +} + +static inline int16_t *mfcc_buffer_wrap(struct mfcc_buffer *buffer, int16_t *ptr) +{ + if (ptr >= buffer->end_addr) + ptr -= buffer->s_length; + + return ptr; +} + +int mfcc_setup(struct processing_module *mod, int max_frames, int rate, int channels); + +void mfcc_free_buffers(struct processing_module *mod); + +void mfcc_fill_prev_samples(struct mfcc_buffer *buf, int16_t *prev_data, + int prev_data_length); + +void mfcc_fill_fft_buffer(struct mfcc_state *state); + +void mfcc_apply_window(struct mfcc_state *state, int input_shift); + +#if CONFIG_FORMAT_S16LE + +void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel); + +void mfcc_s16_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif + +#if CONFIG_FORMAT_S24LE + +void mfcc_source_copy_s24(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel); + +void mfcc_s24_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif + +#if CONFIG_FORMAT_S32LE + +void mfcc_source_copy_s32(struct input_stream_buffer *bsource, struct mfcc_buffer *buf, + struct mfcc_pre_emph *emph, int frames, int source_channel); + +void mfcc_s32_default(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, int frames); +#endif + +#ifdef UNIT_TEST +void sys_comp_module_mfcc_interface_init(void); +#endif + +#endif /* __SOF_AUDIO_MFCC_MFCC_COMP_H__ */ diff --git a/src/include/sof/audio/mic_privacy_manager.h b/src/include/sof/audio/mic_privacy_manager.h new file mode 100644 index 000000000000..61689343a37e --- /dev/null +++ b/src/include/sof/audio/mic_privacy_manager.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + */ + +#ifndef ADSP_FW_MIC_PRIVACY_MANAGER_H +#define ADSP_FW_MIC_PRIVACY_MANAGER_H + +#include <zephyr/drivers/mic_privacy/intel/mic_privacy.h> +#include <sof/lib/notifier.h> +#include <ipc4/base-config.h> +#include "../audio/copier/copier_gain.h" + +#define ADSP_RTC_FREQUENCY 32768 + +struct mic_privacy_data { + enum ipc4_sampling_frequency audio_freq; + uint32_t mic_privacy_state; + bool dma_data_zeroing; + uint32_t fade_in_out_bytes; + uint32_t max_ramp_time_in_ms; + + struct copier_gain_params mic_priv_gain_params; +}; + +struct mic_privacy_settings { + enum mic_privacy_policy mic_privacy_mode; + /* 0-Mic Unmute, 1-Mic Mute */ + uint32_t mic_privacy_state; + uint32_t max_ramp_time; + union mic_privacy_mask privacy_mask_bits; +}; + +struct privacy_capabilities { + uint32_t privacy_version; + uint32_t capabilities_length; + uint32_t capabilities[1]; +}; + +enum mic_privacy_state { + MIC_PRIV_UNMUTED, + MIC_PRIV_FADE_IN, + MIC_PRIV_FADE_OUT, + MIC_PRIV_MUTED, +}; + +int mic_privacy_manager_init(void); +int mic_privacy_manager_get_policy(void); +uint32_t mic_privacy_get_policy_register(void); +void mic_privacy_propagate_settings(struct mic_privacy_settings *settings); +uint32_t mic_privacy_get_dma_zeroing_wait_time(void); +uint32_t mic_privacy_get_privacy_mask(void); +uint32_t mic_privacy_get_mic_disable_status(void); +void mic_privacy_enable_dmic_irq(bool enable_irq); +void mic_privacy_fill_settings(struct mic_privacy_settings *settings, uint32_t mic_disable_status); +void mic_privacy_set_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t mic_disable_status); +void mic_privacy_update_gtw_mic_state(struct mic_privacy_data *mic_priv_data, + uint32_t hw_mic_disable_status); +void mic_privacy_process(struct comp_dev *dev, struct mic_privacy_data *mic_priv, + struct comp_buffer *buffer, uint32_t copy_samples); +void mic_privacy_gain_input(uint8_t *buff, uint32_t buff_size, uint32_t mic_priv_state, + const struct ipc4_audio_format *in_fmt); + +#endif /* ADSP_FW_MIC_PRIVACY_MANAGER_H */ diff --git a/src/include/sof/audio/mixer.h b/src/include/sof/audio/mixer.h deleted file mode 100644 index 65e9e27a8884..000000000000 --- a/src/include/sof/audio/mixer.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_MIXER_H__ -#define __SOF_AUDIO_MIXER_H__ - -#ifdef UNIT_TEST -void sys_comp_mixer_init(void); -#endif - -#endif /* __SOF_AUDIO_MIXER_H__ */ diff --git a/src/include/sof/audio/module_adapter/iadk/adsp_stddef.h b/src/include/sof/audio/module_adapter/iadk/adsp_stddef.h new file mode 100644 index 000000000000..b7ea435a3346 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/adsp_stddef.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 - 2024 Intel Corporation. All rights reserved. + */ + +#ifndef _ADSP_STDDEF_H_ +#define _ADSP_STDDEF_H_ + +#include <stddef.h> +#include <stdint.h> +#include <rtos/string.h> + +#ifdef __ZEPHYR__ +#include <zephyr/sys/util.h> +#endif /* __ZEPHYR__ */ + +#include <module/module/logger.h> + +/*! Log level priority enumeration. */ +typedef enum log_priority AdspLogPriority, log_priority_e; +typedef struct log_handle AdspLogHandle; + +#ifdef __cplusplus +namespace intel_adsp +{ +struct ModulePlaceholder {}; +} +inline void *operator new(size_t size, intel_adsp::ModulePlaceholder * placeholder) throw() +{ + (void)size; + return placeholder; +} +#endif /* #ifdef __cplusplus */ + +#endif /*_ADSP_STDDEF_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/api_version.h b/src/include/sof/audio/module_adapter/iadk/api_version.h new file mode 100644 index 000000000000..4d6be24e461d --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/api_version.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_ADAPTER_IADK_API_VERSION_H__ +#define __MODULE_ADAPTER_IADK_API_VERSION_H__ + +#include <module/module/api_ver.h> + +#define IADK_MODULE_API_BUILD_INFO_FORMAT 0 + +#define IADK_MODULE_API_MAJOR_VERSION 4 +#define IADK_MODULE_API_MIDDLE_VERSION 5 +#define IADK_MODULE_API_MINOR_VERSION 0 + +#define IADK_MODULE_API_CURRENT_VERSION MODULE_API_VERSION_ENCODE(IADK_MODULE_API_MAJOR_VERSION, \ + IADK_MODULE_API_MIDDLE_VERSION, IADK_MODULE_API_MINOR_VERSION) + +/* Defines the size of the space reserved within ModuleHandle for SOF to store its private data. + * This size comes from the IADK header files and must match the IADK API version. + * Please do not modify this value! + */ +#define IADK_MODULE_PASS_BUFFER_SIZE 320 + +#endif /* __MODULE_ADAPTER_IADK_API_VERSION_H__ */ diff --git a/src/include/sof/audio/module_adapter/iadk/fixed_array.h b/src/include/sof/audio/module_adapter/iadk/fixed_array.h new file mode 100644 index 000000000000..44d249fe357c --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/fixed_array.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \file fixed_array.h */ + +#ifndef _ADSP_FIXED_ARRAY_H_ +#define _ADSP_FIXED_ARRAY_H_ + +#include <stddef.h> + +namespace intel_adsp +{ + /* \brief Fixed-size container of continuous elements whose size is specified at runtime. + * + * This container is very similar to the C-array except that its fixed-size is specified at + * runtime. + * It acts as a facade to expose a memory buffer as a array of elements with same type. + * + * \tparam VALUE type of the array elements. + */ + template < class VALUE > + struct FixedArray { + typedef VALUE ValueType; + + /*! \brief Initializes a new instance of FixedArray. + */ + explicit FixedArray(ValueType *array, size_t length) : + array_(array), length_(length) + {} + + /*! \brief Gets value at the given index of the array. + * \param index index of the value to retrieve. By default index is set to 0. + * \note If index is out of range (i.e. is equal or greater than value returned by + * GetLength()) the returned value is mal-formed. + * \remarks Return is by value rather than reference to prevent client code from + * working with dangling reference. + * Indeed a FixedArray object does not own the underlying associated buffer. + */ + ValueType GetValue(int index = 0) const + { + return array_[index]; + } + + /*! \brief Subscript operator. + * + * This method actually returns the result of GetValue() + */ + ValueType operator[](int index) const + { + return GetValue(index); + } + + /*! \brief Gets the number of elements + */ + size_t GetLength(void) const + { + return length_; + } + + /*! \brief Copies the values wrapped by the FixedArray into the given C-array + */ + void Copy(ValueType *array, size_t length) const + { + length = MIN(length, length_); + for (int i = 0 ; i < length ; i++) + array[i] = array_[i]; + } + + private: + ValueType * const array_; + size_t const length_; + }; + +} /* namespace intel_adsp */ + +#endif /* #ifndef _ADSP_FIXED_ARRAY_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h b/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h new file mode 100644 index 000000000000..e01a51f8805b --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/iadk_module_adapter.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * + */ + +#ifndef _IADK_MODULE_ADAPTER_H +#define _IADK_MODULE_ADAPTER_H + +#ifdef __cplusplus + +#include <processing_module_interface.h> +#include <module_initial_settings.h> +#include <adsp_stddef.h> +#include <system_error.h> +#include <sof/common.h> +#include <api_version.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sof/audio/module_adapter/module/module_interface.h> + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +extern "C" { +namespace dsp_fw +{ + /*! + * \brief This ModuleAdapter class can adapt a ProcessingModuleInterface instance into + * a ModuleInstance instance. + * + * The overall base FW can only handle ModuleInstance object. Purpose of this adapter is + * to turn an intel_adsp::ProcessingModuleInterface object into a ModuleInstance object. + */ + class IadkModuleAdapter + { + public: + IadkModuleAdapter(intel_adsp::ProcessingModuleInterface &processing_module, + void *comp_dev_instance, + uint32_t module_id, + uint32_t instance_id, + uint32_t core_id, + size_t module_size); + + /** + * Module specific initialization procedure, called as part of + * + */ + int IadkModuleAdapter_Init(void); + + /** + * Module specific prepare procedure, called as part of codec_adapter + * component preparation in .prepare() + */ + int IadkModuleAdapter_Prepare(void); + + /** + * Module specific processing procedure, called as part of codec_adapter + * component copy in .copy(). This procedure is responsible to consume + * samples provided by the codec_adapter and produce/output the processed + * ones back to codec_adapter. + */ + int IadkModuleAdapter_Process(struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks); + + /** + * Module specific apply config procedure, called by codec_adapter every time + * a new RUNTIME configuration has been sent if the adapter has been + * prepared. This will not be called for SETUP cfg. + */ + AdspErrorCode + IadkModuleAdapter_SetConfiguration(uint32_t config_id, + enum module_cfg_fragment_position fragment_position, + uint32_t data_offset_size, + const uint8_t *fragment_buffer, + size_t fragment_size, + uint8_t *response, + size_t &response_size) /*override*/; + + /** + * Retrieves the configuration message for the given configuration ID. + */ + AdspErrorCode + IadkModuleAdapter_GetConfiguration(uint32_t config_id, + enum module_cfg_fragment_position fragment_position, + uint32_t &data_offset_size, + uint8_t *fragment_buffer, + size_t &fragment_size); + /** + * Module specific reset procedure, called as part of codec_adapter component + * reset in .reset(). This should reset all parameters to their initial stage + * but leave allocated memory intact. + */ + void IadkModuleAdapter_Reset(void); + /** + * Module specific free procedure, called as part of codec_adapter component + * free in .free(). This should free all memory allocated by module. + */ + int IadkModuleAdapter_Free(void); + void IadkModuleAdapter_SetProcessingMode(enum module_processing_mode sof_mode); + + enum module_processing_mode IadkModuleAdapter_GetProcessingMode(void); + + private: + + intel_adsp::ProcessingModuleInterface &processing_module_; + }; + +STATIC_ASSERT(sizeof(IadkModuleAdapter) <= IADK_MODULE_PASS_BUFFER_SIZE, IadkModuleAdapter_too_big); + +} /* namespace dsp_fw */ + +} /* extern "C" */ + +void *operator new(size_t size, intel_adsp::InputStreamBuffer *placeholder) throw(); +void *operator new(size_t size, intel_adsp::OutputStreamBuffer *placeholder) throw(); + +#else /* __cplusplus */ + +/* C wrappers for C++ ProcessingModuleInterface() methods. */ +int iadk_wrapper_init(void *md); + +int iadk_wrapper_prepare(void *md); + +int iadk_wrapper_set_processing_mode(void *md, enum module_processing_mode mode); + +enum module_processing_mode iadk_wrapper_get_processing_mode(void *md); + +int iadk_wrapper_reset(void *md); + +int iadk_wrapper_free(void *md); + +int iadk_wrapper_set_configuration(void *md, 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); + +/* + * \brief Retrieve module configuration + * \param[in] md - struct IadkModuleAdapter pointer + * \param[in] config_id - Configuration ID + * \param[in] pos - position of the fragment in the large message + * \param[in] data_offset_size: size of the whole configuration if it is the first fragment or the + * only fragment. Otherwise, it is the offset of the fragment in the whole configuration. + * \param[in] fragment: configuration fragment buffer + * \param[in,out] fragment_size: size of @fragment + * + * \return: 0 upon success or error upon failure + */ +int iadk_wrapper_get_configuration(void *md, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t *data_offset_size, + uint8_t *fragment, size_t *fragment_size); + +int iadk_wrapper_process(void *md, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + +#endif /* __cplusplus */ + +#endif /*_IADK_MODULE_ADAPTER_H */ diff --git a/src/include/sof/audio/module_adapter/iadk/module_initial_settings.h b/src/include/sof/audio/module_adapter/iadk/module_initial_settings.h new file mode 100644 index 000000000000..5fc6dd3488ea --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/module_initial_settings.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \file module_initial_settings.h */ + +#ifndef _ADSP_MODULE_INITIAL_SETTINGS_H_ +#define _ADSP_MODULE_INITIAL_SETTINGS_H_ + +#include "adsp_stddef.h" +#include "fixed_array.h" +#include <ipc4/base-config.h> + +/* Mapping of IPC4 definitions into IADK naming counterpart */ +typedef struct ipc4_base_module_cfg BaseModuleCfg; +typedef struct ipc4_base_module_cfg LegacyModuleInitialSettings; +typedef struct ipc4_input_pin_format InputPinFormat; +typedef struct ipc4_output_pin_format OutputPinFormat; +typedef struct ipc4_audio_format AudioFormat; + +#define INPUT_PIN_COUNT (1 << 3) +#define OUTPUT_PIN_COUNT (1 << 3) + +namespace intel_adsp +{ + /*! \brief Enumeration values of keys to access to the ModuleInitialSettings items */ + enum ModuleInitialSettingsKey { + /*! \brief Key value to retrieve the LegacyModuleInitialSettings item from the + * ModuleInitialSettings. + * \deprecated New module shall not work with this item as it will be removed + * in next API release. + */ + LEGACY_STRUCT = 0, + /*! \brief Key value to retrieve the array of InputPinFormat item from + * the ModuleInitialSettings. + */ + IN_PINS_FORMAT, + /*! \brief Key value to retrieve the array of OutputPinFormat item from + * the ModuleInitialSettings. + */ + OUT_PINS_FORMAT + }; + + /*! \brief Helps to identify type of a ModuleInitialSettings item referenced by its KEY + * \tparam KEY identifying the settings item + */ + template < ModuleInitialSettingsKey KEY > struct ModuleInitialSettingsItem + { + /*! \brief value type of the SETTINGS item for the given KEY value. + * \note ValueType shall have copy constructor + */ + typedef void ValueType; + }; + + /*! \brief Defines the interface to retrieve untyped items based + * on ModuleInitialSettingsKey values. + * \internal + */ + struct ModuleInitialSettingsInterface { + /*! \internal */ + virtual void const *GetUntypedItem(ModuleInitialSettingsKey key, + size_t & length) = 0; + }; + + namespace system + { class SystemAgent; } + + /*! \brief The set of settings item given for initialization of a Module instance. + * + * The ModuleInitialSettings is a container of heterogeneous typed value items. Each item + * is a key-value pair where key is an enumeration value of ModuleInitialSettingsKey + */ + class ModuleInitialSettings + { + template < class DERIVED, class PROCESSING_MODULE > + friend class ProcessingModuleFactory; + friend class system::SystemAgent; + + public: + /*! \brief A FixedArray whose construction is only granted to + * ModuleInitialSettings + */ + template < class VALUE > + struct Array : public FixedArray < VALUE > + { + friend class ModuleInitialSettings; + typedef VALUE ValueType; + + /*! \brief Initializes a new instance of Array. + */ + explicit Array(ValueType *array, size_t length) : + FixedArray < ValueType > (array, length) + {} + + private: + /*! \brief copy constructor is invalidated to prevent client code from + * working with dangling reference. Consider the Copy() operation if + * a copy of the settings item array is required. + */ + Array(Array < ValueType > const &); + + /*! \brief copy-assignment operator is invalidated to prevent client code + * from working with dangling reference. Consider the Copy() operation if + * a copy of the settings item array is required. + */ + Array < ValueType > &operator = (Array < ValueType > const &); + }; + + /*! \brief the type of keys to access to the ModuleInitialSettings items */ + typedef ModuleInitialSettingsKey Key; + + /*! \brief Initializes a new instance of ModuleInitialSettings given some + * ModuleInitialSettingsInterface object + */ + explicit ModuleInitialSettings(ModuleInitialSettingsInterface & performer) : + performer_(performer) + {} + + /*! \brief Retrieves the item as an array of values for the given key. + * \note Any item is represented as a value array even if it has a single value. + * \remarks If no item is found for the given key, the returned array will + * have null length. + * \tparam key value of the Key to retrieve the item. + */ + template < Key key > + const Array < typename ModuleInitialSettingsItem < key > + :: ValueType const > GetItem() + { + size_t length; + + return Array < typename ModuleInitialSettingsItem < key > + :: ValueType const > ( + reinterpret_cast < typename ModuleInitialSettingsItem < key > + :: ValueType const *> + (performer_.GetUntypedItem(key, length)), length); + } + + private: + /*! \brief For sake of safety ModuleInitialSettings is not "publicly" copy-able. + * Indeed, ModuleInitialSettings instance holds references on some ADSP System + * resources which are only available for a temporary lifetime. + */ + ModuleInitialSettings(ModuleInitialSettings const &src) : + performer_(src.performer_) { } + /*! ModuleInitialSettings(ModuleInitialSettings const&) */ + ModuleInitialSettings operator = (ModuleInitialSettings const &src); + + ModuleInitialSettingsInterface & performer_; + }; + + /*! \brief Boilerplate to identify type of the ModuleInitialSettings item associated + * to the "LEGACY_STRUCT" key + * \internal + */ + template < > struct ModuleInitialSettingsItem < LEGACY_STRUCT > + { + typedef LegacyModuleInitialSettings ValueType; + }; + + /*! \brief Boilerplate to identify type of the ModuleInitialSettings item associated + * to the "IN_PINS_FORMAT" key + * \internal + */ + template < > struct ModuleInitialSettingsItem < IN_PINS_FORMAT > + { + typedef InputPinFormat ValueType; + }; + + /*! \brief Boilerplate to identify type of the ModuleInitialSettings item associated + * to the "OUT_PINS_FORMAT" key + * \internal + */ + template < > struct ModuleInitialSettingsItem < OUT_PINS_FORMAT > + { + typedef OutputPinFormat ValueType; + }; + +} /*namespace intel_adsp */ + +#endif /* #ifndef _ADSP_MODULE_INITIAL_SETTINGS_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/module_initial_settings_concrete.h b/src/include/sof/audio/module_adapter/iadk/module_initial_settings_concrete.h new file mode 100644 index 000000000000..a6dd10f72b62 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/module_initial_settings_concrete.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef _MODULE_INITIAL_SETTINGS_CONCRETE_H +#define _MODULE_INITIAL_SETTINGS_CONCRETE_H + +#include "module_initial_settings.h" +#include <utilities/array.h> +#include <sof/compiler_attributes.h> + +#include <stddef.h> + +#pragma pack(push, 4) +struct BaseModuleCfgExt { + /*! + * \brief Specifies number of items in input_pins array. Maximum size is 8. + */ + uint16_t nb_input_pins; + /*! + * \brief Specifies number of items in output_pins array. Maximum size is 8. + */ + uint16_t nb_output_pins; + /*! + * \brief Not used, set to 0. + */ + uint8_t reserved[12]; + /*! + * \brief Specifies format of input pins. + * \remarks Pin format arrays may be non-continuous i.e. may contain pin #0 + * format followed by pin #2 format + * in case pin #1 will not be in use. FW assigned format of the pin based + * on pin_index, not on a position of the item in the array. + * Applies to both input and output pins. + */ + InputPinFormat input_pins[1]; + /*! + * \brief Specifies format of output pins. + */ + OutputPinFormat output_pins[1]; +}; +#pragma pack(pop) + +namespace dsp_fw +{ +/*! \brief concrete implementation of the intel_adsp::ModuleInitialSettingsInterface + * + * Allow to retrieve the settings items in the INIT_INSTANCE IPC message + */ +struct ModuleInitialSettingsConcrete : public intel_adsp::ModuleInitialSettingsInterface +{ + /*! \brief Initializes a new ModuleInitialSettingsConcrete instance given + * an INIT_INSTANCE IPC message blob + */ + explicit ModuleInitialSettingsConcrete(DwordArray const &cfg_ipc_msg); + + /*! \brief Extrapolates some hard-coded BaseModuleCfgExt based on the legacy + * BaseModuleCfg and the given input count and output count. + * \remarks If BaseModuleCfgExt was actually already part of + * the INIT_INSTANCE IPC message, nothing is performed. + */ + void DeduceBaseModuleCfgExt(size_t in_pins_count, size_t out_pins_count); + + /*! \brief Gets the untyped value array of the settings item for the given key + * \note In this methods it is assumed that the given INIT_INSTANCE IPC message + * has a valid content + * \warning IsParsable() result shall have been checked before invoking this method. + */ + virtual void const *GetUntypedItem(intel_adsp::ModuleInitialSettingsKey key, + size_t &length); + + /*! \brief Indicates if the given INIT_INSTANCE IPC message is parse-able */ + bool IsParsable(void) const + { + return ((cfg_ != NULL) || (cfg_ext_ != NULL)); + } + + /*! \brief Gets pointer on the BaseModuleCfg data retrieved from the IPC message */ + BaseModuleCfg const *GetBaseModuleCfg(void) const + { + return cfg_; + } + + /*! \brief Gets pointer on the BaseModuleCfgExt data retrieved from the IPC message */ + BaseModuleCfgExt const *GetBaseModuleCfgExt(void) const + { + return cfg_ext_; + } + +private: + BaseModuleCfg const *cfg_; + BaseModuleCfgExt const *cfg_ext_; + /* temporary extended module config for case where it is not part of + * the INIT_INSTANCE IPC message + */ + union { + BaseModuleCfgExt tlv; + /* struct below reserved the placeholder for the biggest possible BaseModuleCfgExt + * block. + */ + struct { + uint16_t do_not_use1; + uint16_t do_not_use2; + uint8_t do_not_use3[8]; + uint32_t do_not_use4; + InputPinFormat do_not_use5[INPUT_PIN_COUNT]; + OutputPinFormat do_not_use6[OUTPUT_PIN_COUNT]; + } placeholder; + } tmp_cfg_ext_; +}; +} + +#endif /*_MODULE_INITIAL_SETTINGS_CONCRETE_H */ diff --git a/src/include/sof/audio/module_adapter/iadk/processing_module_factory_interface.h b/src/include/sof/audio/module_adapter/iadk/processing_module_factory_interface.h new file mode 100644 index 000000000000..5c974b24e0d9 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/processing_module_factory_interface.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \file processing_module_factory_interface.h */ + +#ifndef _PROCESSING_MODULE_FACTORY_INTERFACE_H_ +#define _PROCESSING_MODULE_FACTORY_INTERFACE_H_ + +#include "processing_module_interface.h" +#include "system_agent_interface.h" +#include "processing_module_prerequisites.h" +#include "module_initial_settings.h" + +namespace intel_adsp +{ + /*! \brief defines type of the pin endpoint. + * + * A custom module is required to provide to the ADSP System some PinEndpoint value arrays. + * Arrays length shall be as long as it has input and output pins. + * (ref \ref ProcessingModuleFactoryInterface::Create()). + */ + typedef void *PinEndpoint; + typedef struct { void *prt[2]; } FwdEvent; + + /*! \brief holds information about pins of a module. + * + * For each custom module, + * input pins of a module are associated to some "sources" PinEndPoint and + * output pins are associated to some sinks "PinEndPoint" objects. + * Those sinks and sources objects shall be instantiated by the custom module and delivered + * to the ADSP System with this IoPinsInfo structure + * (through \ref ProcessingModuleFactoryInterface::Create()). + * + * \note The "pin" of a module is purely conceptual and has no programmatic correspondence. + * A module has as many input/output pins as input/output streams which can be + * driven through it. + */ + struct IoPinsInfo { + /*! + * \brief pointer on a PinEndpoint array with "sources_count" elements + * + * A module is required to provide some PinEndpoint arrays to allow + * the ADSP System to drive streams into the module. + */ + PinEndpoint *sources; + /*! + * \brief pointer on a PinEndpoint array with "sinks_count" elements + * + * A module is required to provide some PinEndpoint arrays to allow + * the ADSP System to drive stream out of the module. + */ + PinEndpoint *sinks; + /*! + * \brief pointer on a FwdEvents array with "events_count" elements + * + * A module is required to provide some FwdEvents arrays to allow + * the ADSP System to handle key phrase detection. + */ + FwdEvent *events; + + /*! \brief description of buffer reserved for DP queue objects and buffers + * used for all additional input and output pins (e.g. reference pin) + */ + uint8_t *pins_mem_pool; + size_t pins_mem_pool_size; + }; + + /*! + * \brief The ProcessingModuleFactoryInterface class defines requirements for creating + * a processing module controllable by the ADSP System. + */ + class ProcessingModuleFactoryInterface + { + public: + /*! + * \brief Scoped enumeration of error code value which can be reported by + * a ProcessingModuleFactoryInterface object + */ + struct ErrorCode : intel_adsp::ErrorCode { + /*! \brief list of named error codes specific to + * the ProcessingModuleFactoryInterface + */ + enum Enum { + /*!< Reports that the given value of Input Buffer Size is invalid */ + INVALID_IBS = intel_adsp::ErrorCode::MaxValue + 1, + /*!< Reports that the given value of Output Buffer Size is invalid*/ + INVALID_OBS, + /*!< Reports that the given value of Cycles Per Chunk processing + * is invalid + */ + INVALID_CPC, + /*!< Reports that the settings provided for module creation + * are invalid + */ + INVALID_SETTINGS + }; + /*! \brief Indicates the minimal value of the enumeration */ + static Enum const MinValue = INVALID_IBS; + /*! \brief Indicates the maximal value of the enumeration */ + static Enum const MaxValue = INVALID_SETTINGS; + + /*! + * \brief Initializes a new instance of ErrorCode given a value + */ + explicit ErrorCode(Type value) + : intel_adsp::ErrorCode(value) + {} + }; + + /*! + * \brief Indicates the prerequisites for module instance creation. + * + * ADSP System calls this method before each module instance creation. + * \param [out] module_prereqs reports module prerequisites + * that ADSP System needs to prepare the module creation. + */ + virtual void GetPrerequisites(ProcessingModulePrerequisites & module_prereqs + ) = 0; + /*! + * \brief Creates a ProcessingModuleInstance instance in the given placeholder. + * + * The custom implementation of the Create method is expected to handle + * initialization of the custom module instances. + * \note The ADSP System will provide a dedicated memory \e placeholder for every + * module instance to create. + * + * \param [in] system_agent the SystemAgentInterface object which can register the + * module instance which is being initialized + * \param [in] module_placeholder the pointer to the memory location where the + * module instance can be initialized using the "new placement syntax". + * Note that the size of the placeholder given by the System is worth + * the size of the processing module class given as parameter of the + * DECLARE_LOADABLE_MODULE macro + * \param [in] initial_settings initial settings for module startup. + * \param [out] pins_info will report the IoPinsInfo data that ADSP System + * requires to bind the input and output streams to the module. + * \return some ErrorCode value upon creation status. + */ + virtual ErrorCode::Type Create(SystemAgentInterface & system_agent, + ModulePlaceholder * module_placeholder, + ModuleInitialSettings initial_settings, + IoPinsInfo & pins_info + ) = 0; + }; /* class ProcessingModuleFactoryInterface */ + +} /* namespace intel_adsp */ + +#endif /* #ifndef _PROCESSING_MODULE_FACTORY_INTERFACE_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h b/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h new file mode 100644 index 000000000000..3b725a23a095 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/processing_module_interface.h @@ -0,0 +1,405 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \file processing_module_interface.h */ + +#ifndef _ADSP_PROCESSING_MODULE_INTERFACE_H_ +#define _ADSP_PROCESSING_MODULE_INTERFACE_H_ + +#include "system_error.h" + +#include <stdint.h> +#include <stddef.h> + +namespace intel_adsp +{ + /*! \brief Scoped enumeration which defines processing mode values + * \see ProcessingModuleInterface::SetProcessingMode() + */ + struct ProcessingMode { + /*! \brief enumeration values of processing mode */ + enum Enum { + NORMAL = 0,/*!< Indicates that module is expected to apply its custom + * processing on signal. + */ + BYPASS /*!< Indicates that module is expected to not apply its custom + * processing on signal. The module is expected to forward as far + * as possible the input signals unmodified + * with respect of the signal continuity at the mode transition. + */ + }; + + /*! \brief Underlying type for storing of ProcessingMode value */ + typedef int Type; + + /*! \brief Initializes a new instance of ProcessingMode with the NORMAL + * as default value + */ + ProcessingMode(void) + : value_(NORMAL) + {} + + /*! \brief Implicitly initializes a new instance of ProcessingMode given + * an Enum value + */ + ProcessingMode(Enum mode_value) + : value_(mode_value) + {} + + /*! \brief Implicitly converts a ProcessingMode object into an Enum value */ + operator Enum(void) + { + return (Enum) value_; + } + + private: + Type value_; + }; + + /*! \brief defines the bitfield structure of flags associated to an InputStreamBuffer + */ + struct InputStreamFlags { + /*!< indicates that End Of Stream condition has occurred on the input stream */ + bool end_of_stream : 1; + }; + + /*! \brief Descriptor of the data stream buffer extracted from a input module pin + * \see ProcessingModuleInterface::Process() + */ + struct InputStreamBuffer { + InputStreamBuffer() : data(), size(), flags() {} + InputStreamBuffer(uint8_t *_data, size_t _size, + InputStreamFlags _flags) : data(_data), size(_size), flags(_flags) {} + uint8_t *const data; /*!< data stream buffer */ + /*! + * \brief size indicator about the data in the stream buffer + * + * - When read, it indicates the size of available data in the data stream buffer + * - When written, it reports the size of data which has actually be considered + * during the buffer processing + * (can be less than the given available data size) + */ + size_t size; + const InputStreamFlags flags; /*!< readonly status flags about the input stream */ + }; + + /*! \brief Descriptor of the data stream buffer to inject into an output module pin + * \see ProcessingModuleInterface::Process() + */ + struct OutputStreamBuffer { + OutputStreamBuffer() : data(), size() {} + OutputStreamBuffer(uint8_t *_data, size_t _size) : data(_data), size(_size) {} + uint8_t *const data; /*!< data stream buffer */ + /*! + * \brief size indicator about the data in the stream buffer + * + * - When read, it indicates the size of available room in the stream buffer + * - When written, it reports the size of data which has actually be produced + * into the buffer during the buffer processing + * (can be less than the given available room size) + */ + size_t size; + }; + + /*! \brief Scoped enumeration which defines location of a configuration message fragment + * in the whole message + * + * \see + * - ProcessingModuleInterface::SetConfiguration() + * - ProcessingModuleInterface::GetConfiguration() + */ + struct ConfigurationFragmentPosition { + /*! \brief enumeration values of fragment position tag */ + enum Enum { + /*!< Indicates that the associacted fragment is in the middle of message + * transmission (nor first neither last one) + */ + MIDDLE = 0, + /*!< Indicates that the associacted fragment is the first one of + * a multi-fragment message transmission + */ + FIRST = 1, + /*!< Indicates that the associacted fragment is the last one of + * a multi-fragment message transmission + */ + LAST = 2, + /*!< Indicates that the associacted fragment is the single one of + * the message transmission + */ + SINGLE = 3 + }; + + /*! \brief Underlying type for storing of ConfigurationFragmentPosition value */ + typedef int Type; + + /*! \brief Implicitly initializes a new instance of ConfigurationFragmentPosition + * given an Enum value + */ + ConfigurationFragmentPosition(Enum mode_value) + : value_(mode_value) + {} + + /*! \brief Implicitly converts a ConfigurationFragmentPosition object + * into an Enum value + */ + operator Enum(void) + { + return (Enum) value_; + } + + private: + Type value_; + }; + + /*! + * \brief The ProcessingModuleInterface class defines the interface that user-defined module + * shall comply with to be manageable by the ADSP System. + * + * It is also configurable through the couple of method + * SetConfiguration() / GetConfiguration(). + * A ProcessingModuleInterface object consumes data stream from its input pins and produces + * data stream into its output pins. + */ + class ProcessingModuleInterface + { + public: + /*! + * \brief Scoped enumeration of error code value which can be reported by + * a ProcessingModuleInterface object + */ + struct ErrorCode : intel_adsp::ErrorCode { + /*! \brief list of named error codes specific to the + * ProcessingModuleInterface + */ + enum Enum { + /*!< Reports that the message content given for configuration + * is invalid + */ + INVALID_CONFIGURATION = intel_adsp::ErrorCode::MaxValue + 1, + /*!< Reports that the module does not support retrieval of its + * current configuration information + */ + NO_CONFIGURATION + }; + /*! \brief Indicates the minimal value of the enumeration */ + static Enum const MinValue = INVALID_CONFIGURATION; + /*! \brief Indicates the maximal value of the enumeration */ + static Enum const MaxValue = NO_CONFIGURATION; + + /*! + * \brief Initializes a new instance of ErrorCode given a value + */ + explicit ErrorCode(Type value) + : intel_adsp::ErrorCode(value) + {} + }; + /*! + * \brief Additional method called after module initialization + */ + virtual ErrorCode::Type Init(void) = 0; + /*! + * \brief Destructor that may contain logic executed on module destruction + */ + virtual ErrorCode::Type Delete(void) = 0; + + /*! + * \brief Processes the stream buffers extracted from the input pins and produces + * the resulting signal in stream buffer of the output pins. + * + * The user-defined implementation of Process() is generally expected to consume + * all the samples available in the input stream buffers and should produce the + * samples for all free room available in the output stream buffers. Note that + * in normal condition all connected input pins will receive "ibs" + * (i.e. "Input Buffer Size") data bytes in their input stream buffers and output + * pins should produce "obs" (i.e. "Output Buffer Size") data bytes in their + * output stream buffers. ("ibs" and "obs" values are given to module at + * construction time within the \ref ModuleInitialSettings parameter). + * However in "end of stream" condition input stream buffers may be filled with + * less data count than "ibs". + * Therefore less data count than "obs" can be put in the output buffers. + * + * \remarks Length of input_stream_buffers and output_stream_buffers C-arrays + * don't need to be part of the Process() prototype as those lengths are + * well-known by the user-defined implementation of the ProcessingModuleInterface. + * \return Custom implementation can return a user-defined error code value. + * This user-defined error code will be transmitted to + * host driver if the value is different from 0 (0 is considered as + * a "no-error value") + */ + virtual uint32_t Process( + InputStreamBuffer * input_stream_buffers, + /*!< [in,out] C-array of input buffers to process. "data" field value can + * be NULL if the associated pin is not connected + */ + OutputStreamBuffer * output_stream_buffers + /*!< [in,out] C-array of output buffers to produce. "data" field value + * can be NULL if the associated pin is not connected + * \note "size" field value is set with the total room available in + * the output buffers at Process() method call. + * It shall be updated within the method to report to the ADSP System + * the actual data size put in the output buffers. + */ + ) = 0; + /*! + * \brief Upon call to this method the ADSP system requires the module to reset its + * internal state into a well-known initial value. + * + * Parameters which may have been set through SetConfiguration() are supposed to be + * left unchanged. + * \remarks E.g. a configurable FIR filter module will reset its internal samples + * history buffer but not the taps values + * (which may have been configured through SetConfiguration()) + */ + virtual void Reset(void) = 0; + + /*! + * \brief Sets the processing mode for the module. + * + * Upon the transition from one processing mode to another, the module is required + * to handle enabling/disabling of its custom processing + * as smoothly as possible (no glitch, no signal discontinuity). + * + * \note This method is actually only relevant for modules which only manipulate + * PCM signal streams. + * Thus, the ADSP System will only fire the SetProcessingMode() method for + * those kind of modules. (e.g. not for signal decoders, encoders etc.) + * Moreover, disabling the processing of modules which convert the trait of + * the signal samples (bit depth, sampling rate, etc.) + * would make the resulting stream(s) unsuitable for the downstream modules. + * Therefore ADSP System will not fire this method for such modules too. + */ + virtual void SetProcessingMode(ProcessingMode mode) = 0; + /*! + * \brief Gets the processing mode for the module. + */ + virtual ProcessingMode GetProcessingMode(void) = 0; + /*! + * \brief Applies the upcoming configuration message for the given + * configuration ID. + * + * If the complete configuration message is greater than 4096 bytes, + * the transmission will be split into several fragments (lesser or equal + * to 4096 bytes). In this case the ADSP System will perform multiple calls + * to SetConfiguration() until completion of the configuration message sending. + * \note config_id indicates ID of the configuration message only on the first + * fragment sending otherwise it is set to 0. + */ + virtual ErrorCode::Type SetConfiguration( + uint32_t config_id, + /*!< [in] indicates ID of the configuration message that + * is provided + */ + ConfigurationFragmentPosition fragment_position, + /*!< [in] indicates position of the fragment in the + * whole message transmission + */ + uint32_t data_offset_size, + /*!< [in] Meaning of parameter depends on the fragment_position + * value: + * - if fragment_position is worth + * ConfigurationFragmentPosition::FIRST or + * ConfigurationFragmentPosition::SINGLE + * data_offset_size indicates the data size of the full message + * - if fragment_position is worth + * ConfigurationFragmentPosition::MIDDLE or + * ConfigurationFragmentPosition::LAST + * data_offset_size indicates the position offset of the received + * fragment in the full message. + */ + const uint8_t *fragment_buffer, + /*!< [in] the configuration fragment buffer */ + size_t fragment_size, + /*!< [in] the fragment buffer size. + * As per ADSP System design the fragment_size value will not + * exceed 4096 bytes. + */ + uint8_t *response, + /*!< [out] the response message buffer to optionally fill */ + size_t & response_size + /** [in,out] the response message size. + * As per ADSP System design the response_size value shall not + * exceed 2048 bytes. + * Implementation of SetConfiguration shall set response_size + * value to the actual size (in bytes) of the response message + */ + + ) = 0; + /*! + * \brief Retrieves the configuration message for the given configuration ID. + * + * If the complete configuration message is greater than 4096 bytes, + * the transmission will be split into several fragments (lesser or equal + * to 4096 bytes). In this case the ADSP System will perform multiple call to + * GetConfiguration() until completion of the configuration message retrieval. + * \note config_id indicates ID of the configuration message only on first + * fragment retrieval otherwise it is set to 0. + */ + virtual ErrorCode::Type GetConfiguration( + uint32_t config_id, + /*!< [in] indicates ID of the configuration message that is + * requested to be returned + */ + ConfigurationFragmentPosition fragment_position, + /*!< [in] indicates position of the fragment in the whole + * message transmission + */ + uint32_t & data_offset_size, + /*!< [in,out] Meaning of parameter depends on the + * fragment_position value. + * - if fragment_position is worth + * ConfigurationFragmentPosition::FIRST or + * ConfigurationFragmentPosition::SINGLE + * data_offset_size shall report the data size of the + * full message + * - if fragment_position is worth + * ConfigurationFragmentPosition::MIDDLE or + * ConfigurationFragmentPosition::LAST + * data_offset_size indicates the position offset of the + * received fragment in the full message + */ + uint8_t *fragment_buffer, + /*!< [out] the fragment buffer to fill */ + size_t & fragment_size + /*!< [in,out] the fragment buffer size. + * The actual size of data written into the fragment buffer + * shall be reported to the ADSP System. + */ + ) = 0; + }; + /*! \class ProcessingModuleInterface + * See also + * -------- + * - the ProcessingModuleFactoryInterface interface which defines the factory for custom + * processing module (in processing_module_factory_interface.h) + * - the template class ProcessingModule which provides a partial default implementation + * for ProcessingModuleInterface suitable for most of custom processing modules + * (in processing_module.h). + */ + + class DetectorModuleInterface : public ProcessingModuleInterface + { + public: + + /*! Object processing state */ + typedef enum { + /*! Data are processed */ + PROCESSING = 0, + /*! No data are processed */ + IDLE = 1, + } State; + + /*! Get processing state of module. */ + virtual State GetState(void) = 0; + + /*! Get idle period that the module processing are not required */ + virtual uint64_t GetIdlePeriod(void) = 0; + + /*! Method for handle stream processing */ + virtual void OnStreamState(uint64_t counter, + uint32_t stream_index, + State state) = 0; + }; +} /*namespace intel_adsp */ + +#endif /* #ifndef _ADSP_PROCESSING_MODULE_INTERFACE_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/processing_module_prerequisites.h b/src/include/sof/audio/module_adapter/iadk/processing_module_prerequisites.h new file mode 100644 index 000000000000..d90f2205a786 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/processing_module_prerequisites.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \file processing_module_prerequisites.h */ + +#ifndef _PROCESSING_MODULE_PREREQUISITES_H_ +#define _PROCESSING_MODULE_PREREQUISITES_H_ + +#include <stdint.h> +#include <stddef.h> + +namespace intel_adsp +{ + /*! + * \brief "Scoped enumeration" of values which specify data buffer alignment of input or + * output stream buffer. + */ + struct StreamBufferAlignment { + /*! \brief the enumeration type of StreamBufferAlignment "scoped enumeration" */ + enum WordSize { + /*! \brief enumeration tag for 4-bytes aligned buffer */ + _4_BYTES = 4, + /*! \brief enumeration tag for 8-bytes aligned buffer */ + _8_BYTES = 8 + }; + + /*! \brief Type of the inner integral value */ + typedef uint8_t Type; + + /*! \brief Initializes a new instance of StreamBufferAlignment with value set + * to _4_BYTES + */ + StreamBufferAlignment(void) + : value(_4_BYTES) + {} + + /*! \brief Initializes a new instance of StreamBufferAlignment given + * a StreamBufferAlignment::WordSize value + */ + StreamBufferAlignment(WordSize val) + : value(val) + {} + + /*! \brief Initializes a new instance of StreamBufferAlignment given + * a StreamBufferAlignment::Type value + */ + explicit StreamBufferAlignment(Type val) + : value(val) + {} + + /*! \brief Copy constructor */ + StreamBufferAlignment(const StreamBufferAlignment &ref) + : value(ref.value) + {} + + /*! \brief Implicit cast operator to IoChunkAligment::WordSize */ + operator WordSize(void) + { + return (WordSize) value; + } + + /*! \brief Implicit cast operator to IoChunkAligment::Type */ + operator Type(void) + { + return value; + } + + /*! \brief default assignment operator */ + StreamBufferAlignment &operator = (const StreamBufferAlignment &src) + { + value = src.value; + return *this; + } + + /*! \brief assignment operator given a StreamBufferAlignment::WordSize value */ + StreamBufferAlignment &operator = (const StreamBufferAlignment::WordSize &src) + { + value = src; + return *this; + } + + /*! \brief implement comparison operator */ + bool operator>(const StreamBufferAlignment &r) const + { return value > r.value; } + + /*! \brief implement comparison operator */ + bool operator<(const StreamBufferAlignment &r) const + { return value < r.value; } + + /*! \brief implement comparison operator */ + bool operator == (const StreamBufferAlignment &r) const + { return value == r.value; } + + /*! \brief implement comparison operator */ + bool operator != (const StreamBufferAlignment &r) const + { return value != r.value; } + + private: + /*! \brief inner integral value for the StreamBufferAlignment */ + Type value; + }; + + /*! + * \brief Descriptor on prerequisites for ProcessingModuleInterface instance creation. + */ + struct ProcessingModulePrerequisites { + public: + /*! \brief Initializes a new instance of ProcessingModulePrerequisites + * with default values + */ + ProcessingModulePrerequisites() + : stream_buffer_alignment(StreamBufferAlignment::_4_BYTES), + input_pins_count(0), output_pins_count(0), event_count(0) + {} + + /*! \brief holds the buffer alignment constraint in size of bytes for input + * or output chunk buffer + * + * Default constructor set this field value to StreamBufferAlignment::_4_BYTES. + */ + StreamBufferAlignment stream_buffer_alignment; + + /*! \brief Indicates the count of input pins for the module type about + * to be created. + */ + size_t input_pins_count; + /*! \brief Indicates the count of output pins for the module type about + * to be created. + */ + size_t output_pins_count; + /*! \brief Indicates the count of events for the module type about + * to be created. + */ + size_t event_count; + }; +} + +#endif /* _PROCESSING_MODULE_PREREQUISITES_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/system_agent.h b/src/include/sof/audio/module_adapter/iadk/system_agent.h new file mode 100644 index 000000000000..e7aab98c748c --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/system_agent.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef _SYSTEM_AGENT_H +#define _SYSTEM_AGENT_H + +#ifdef __cplusplus + +#include <processing_module_factory_interface.h> +#include <system_service.h> + +namespace intel_adsp +{ +namespace system +{ + /*! \brief The SystemAgent is a mediator to allow the custom module to interact + * with the base FW + * + * A SystemAgent can only be delivered by the ADSP System. + * Once registered, a ModuleHandle instance can be handled by the ADSP System. + */ + class SystemAgent : public intel_adsp::SystemAgentInterface + { + public: + SystemAgent(uint32_t module_id, + uint32_t instance_id, + uint32_t core_id, + uint32_t log_handle); + + /*! \brief Initializes a new instance of ModuleAdapter in the ModuleHandle buffer*/ + virtual void CheckIn(intel_adsp::ProcessingModuleInterface & processing_module, + intel_adsp::ModuleHandle & module_handle, + intel_adsp::LogHandle * &log_handle) /*override*/; + + /*! \return a value part of error code list defined within the adsp_error.h*/ + virtual int CheckIn(intel_adsp::ProcessingModuleFactoryInterface & module_factory, + intel_adsp::ModulePlaceholder * module_placeholder, + size_t processing_module_size, + uint32_t core_id, + const void *obfuscated_mod_cfg, + void *obfuscated_parent_ppl, + void **obfuscated_modinst_p) /*override*/; + + virtual intel_adsp::SystemService const &GetSystemService() /*override*/ + { + return + reinterpret_cast<intel_adsp::SystemService const &>(system_service_); + } + + virtual intel_adsp::LogHandle const &GetLogHandle() /*override*/ + { + return *reinterpret_cast<intel_adsp::LogHandle const *>(&log_handle_); + } + + private: + static const AdspSystemService system_service_; + uint32_t log_handle_; + uint32_t const core_id_; + uint32_t module_id_; + uint32_t instance_id_; + uint32_t module_size_; + intel_adsp::ModuleHandle * module_handle_; + + }; /* class SystemAgent */ +} /* namespace system */ +} /* namespace intel_adsp */ + +#endif /* #ifdef __cplusplus */ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * The process of loading a IADK module is quite complicated. The function call stack is as follows: + * + * 1. IADK module adapter initialization function (modules_init) pass module entry point to the + * system_agent_start function. + * + * 2. system_agent_start: This function creates an instance of the SystemAgent class on the stack + * and then calls the module entry point function (ModuleEntryPoint) passing a pointer to the + * SystemAgent object as a parameter. + * + * 3. ModuleEntryPoint(system_agent): Creates a ModuleFactory object of the module on the stack + * (inheriting from ProcessingModuleFactoryInterface) and then calls the + * LoadableModuleMain(system_agent, module_factory, placeholder) function, which is the default + * entry point for all IADK modules. Placeholder is part of the .bss section intended for + * a given module instance, with its address is determined based on the instance ID. + * + * 4. LoadableModuleMain(system_agent, module_factory, placeholder): Calls the CheckIn method + * (variant with 7 parameters) of the SystemAgent class. + * + * 5. SystemAgent.CheckIn(7): Calls the Create method from the ModuleFactory object. + * + * 6. ModuleFactory.Create(system_agent, placeholder): Creates an instance of the module class + * (inheriting from ProcessingModule) at the address pointed to by placeholder. + * The ProcessingModule class contains a module_handle field, which reserves an area in memory + * of size IADK_MODULE_PASS_BUFFER_SIZE bytes. The constructor of this class calls the CheckIn + * method (the variant with 3 parameters) from the SystemAgent class, passing a pointer to self + * and a pointer to module_handle. + * + * 7. SystemAgent.CheckIn(3): Stores the address of module_handle in a private variable and + * creates an instance of the IadkModuleAdapter class in this location. + * + * The saved address of the module_handle (the adapter's IADK instance) is returned in the CheckIn + * method (the variant with 7 parameters) via a parameter that initially contained the address to + * the agent system. The system_agent_start function returns it in the variable adapter. + */ +struct system_agent_params; + +int system_agent_start(const struct system_agent_params *params, const void **adapter); +#ifdef __cplusplus +} +#endif + +#endif /* _SYSTEM_AGENT_H */ diff --git a/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h b/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h new file mode 100644 index 000000000000..3719c758ce23 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/system_agent_interface.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \internal \file system_agent_interface.h */ + +#ifndef _ADSP_SYSTEM_AGENT_INTERFACE_H_ +#define _ADSP_SYSTEM_AGENT_INTERFACE_H_ + +#include "system_service.h" +#include "system_error.h" + +#include <stdint.h> +#include <stddef.h> + +namespace intel_adsp +{ + struct ModulePlaceholder; + class ProcessingModuleFactoryInterface; + class ProcessingModuleInterface; + class DetectorModuleInterface; + class ModuleInitialSettings; + struct ProcessingModulePrerequisites; + struct IoPinsInfo; + class ModuleHandle; + struct LogHandle; + +namespace internal +{ + class Endpoint; +} /* namespace internal */ + + /*! \brief The SystemAgentInterface is a mediator to allow loadable module to interact + * with the ADSP System. + * + * It allows loadable module and factory to register themselves + * and provide the list of the service functions exposed by the ADSP System. + * \note user-defined code should not directly interact with the SystemAgentInterface + * and rather should take leverage of the ProcessingModule and ProcessingModuleInterface + * base classes. + */ + class SystemAgentInterface + { + public: + /*! + * \brief Scoped enumeration of error code value which can be reported by + * a SystemAgentInterface object + */ + struct ErrorCode : intel_adsp::ErrorCode + { + /*! \brief list of named error codes specific to the SystemAgentInterface */ + enum Enum { + /*!< Reports that ProcessingModuleFactoryInterface::Create() + * has exited with error + */ + MODULE_CREATION_FAILURE = intel_adsp::ErrorCode::MaxValue + 1 + }; + /*! \brief Indicates the minimal value of the enumeration */ + static Enum const MinValue = MODULE_CREATION_FAILURE; + /*! \brief Indicates the maximal value of the enumeration */ + static Enum const MaxValue = MODULE_CREATION_FAILURE; + + /*! + * \brief Initializes a new instance of ErrorCode given a value + */ + explicit ErrorCode(Type value) + : intel_adsp::ErrorCode(value) + {} + }; + + /*! \brief Allows a ProcessingModuleInterface instance to be registered in + * the ADSP System + * + * internal purpose. + */ + virtual void CheckIn(ProcessingModuleInterface & processing_module, + /**< the instance to register for later use in processing + * pipeline + */ + ModuleHandle & module_handle, + /**< the object that is required by the ADSP System to handle + * the module + */ + LogHandle * &log_handle /**< module logging context */ + ) = 0; + + /*! \brief Allows a ProcessingModuleFactoryInterface instance to be registered in + * the ADSP System + * + * internal purpose. + */ + virtual int CheckIn(ProcessingModuleFactoryInterface & module_factory, + /*!< the instance to register */ + ModulePlaceholder * module_placeholder, + /*!< the place holder in memory for instantiation of + * a ProcessingModuleInterface instance + */ + size_t, + uint32_t, + const void*, + void*, + void**) = 0; + + /*! + * \brief Gets the SystemService instance which contains all the service functions + */ + virtual SystemService const &GetSystemService(void) = 0; + + /*! + * \brief Gets the LogHandle required to send some log message + */ + virtual LogHandle const &GetLogHandle(void) = 0; + }; + + class SystemAgentInterface2 : public SystemAgentInterface + { + public: + + /*! \brief Allows a ProcessingModuleInterface instance to be registered in + * the ADSP System as detector module + * + * internal purpose. + */ + virtual void CheckInDetector(DetectorModuleInterface & processing_module, + /*!< the instance to register for later use in + * processing pipeline + */ + ModuleHandle & module_handle, + /*!< the object that is required by the ADSP System + * to handle the module + */ + LogHandle * &log_handle + /*!< module logging context */ + ) = 0; + }; + +} /* namespace intel_adsp */ + +#endif /* _ADSP_SYSTEM_AGENT_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/system_error.h b/src/include/sof/audio/module_adapter/iadk/system_error.h new file mode 100644 index 000000000000..821f136694bb --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/system_error.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ +/*! \file system_error.h */ + +#ifndef _ADSP_SYSTEM_ERROR_H_ +#define _ADSP_SYSTEM_ERROR_H_ + +#include <module/iadk/adsp_error_code.h> + +namespace intel_adsp +{ + /*! + * \brief Scoped enumeration of common error code values which can be reported + * to ADSP System + */ + struct ErrorCode { + /*! \brief type of the error code value */ + typedef int Type; + + /*! \brief list of named error codes */ + enum Enum { + NO_ERROR = ADSP_NO_ERROR, + INVALID_PARAMETERS = ADSP_INVALID_PARAMETERS, + BUSY = ADSP_BUSY_RESOURCE, + FATAL_FAILURE = ADSP_FATAL_FAILURE, + + }; + /*! \brief Indicates the minimal value in the enumeration list */ + static Enum const MinValue = NO_ERROR; + /*! \brief Indicates the maximal value in the enumeration list */ + static Enum const MaxValue = FATAL_FAILURE; + + /*! \brief Initializes a new ErrorCode instance given a value of error code */ + explicit ErrorCode(Type value) + : value_(value) { } + + /*! \brief Returns the current value of the ErrorCode */ + Type operator()() const + { + return value_; + } + + /*! \brief Converts the ErrorCode instance into its code value */ + operator Type(void) const + { + return value_; + } + + /*! \brief Evaluates the ErrorCode value against a given value */ + bool operator == (Type a) + { + return value_ == a; + } + + /*! + * \brief Gets a const reference on the error code value + */ + const Type & Value() const + { + return value_; + } + + protected: + /*! + * \brief Gets a reference on the error code value + */ + Type & Value() + { + return value_; + } + + private: + Type value_; + }; +} + +#endif /*_ADSP_SYSTEM_ERROR_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/system_service.h b/src/include/sof/audio/module_adapter/iadk/system_service.h new file mode 100644 index 000000000000..716105de418a --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/system_service.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 - 2024 Intel Corporation. All rights reserved. + */ +/*! \file system_service.h */ + +#ifndef _ADSP_SYSTEM_SERVICE_H_ +#define _ADSP_SYSTEM_SERVICE_H_ + +#include <stdint.h> +#include "adsp_stddef.h" +#include <module/iadk/adsp_error_code.h> +#include <native_system_service.h> + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextern-c-compat" +#endif //__clang__ + +#ifdef __cplusplus +namespace intel_adsp +{ +typedef struct system_service AdspSystemService; + +/*! \brief Alias type of AdspSystemService which can be used in C++. + */ +struct SystemService : public AdspSystemService {}; +} +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop // ignored "-Wextern-c-compat" +#endif //__clang__ + +#endif /* _ADSP_SYSTEM_SERVICE_H_ */ diff --git a/src/include/sof/audio/module_adapter/iadk/utilities/array.h b/src/include/sof/audio/module_adapter/iadk/utilities/array.h new file mode 100644 index 000000000000..07b716f59437 --- /dev/null +++ b/src/include/sof/audio/module_adapter/iadk/utilities/array.h @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef DSP_FW_FW_ARRAY_H_ +#define DSP_FW_FW_ARRAY_H_ + +#include <stdint.h> +#include <stddef.h> + +#include <rtos/panic.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! Wrapper for buffer descriptor. */ +typedef struct byte_array { + /*! Pointer to buffer begin. */ + uint8_t *data; + /*! Size of buffer (in number of elements, typically bytes). */ + size_t size; +} byte_array_t; + +static inline uint8_t *array_get_data(const byte_array_t *ba) +{ + return (uint8_t *)ba->data; +} + +static inline uint8_t *array_get_data_end(const byte_array_t *ba) +{ + return array_get_data(ba) + ba->size; +} + + +static inline size_t array_get_size(const byte_array_t *ba) +{ + return ba->size; +} + +static inline uint8_t *array_alloc_from(byte_array_t *ba, + size_t required_size) +{ + /* TODO: add alignment */ + /* TODO: validate inputs */ + /* TODO: move this to more appropriate file */ + + uint8_t *cached_data = array_get_data(ba); + + ba->data += required_size; + ba->size -= required_size; + + return cached_data; +} +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#ifdef __cplusplus + +static inline uint8_t *array_get_data(const byte_array_t &ba) +{ + return (uint8_t *)ba.data; +} + +static inline size_t array_get_size(const byte_array_t &ba) +{ + return ba.size; +} + +namespace dsp_fw +{ +/*! + * Provides a safe wrapper around array allocated in continuous memory. + * Size of the array specified by the client is checked on any attempt + * to access the array data. + * + * \note Wrapper does not take over ownership of the array. The array + * must be deallocated elsewhere by its proper owner. + * + * \note All copy operations are shallow bit copies of the array. + * The array is expected to keep built-in types or pointers, so + * there is no assignment operator called for each copied entry. + * + * \note Array (especially Array<uint8_t>/ByteArray) can be casted to + * byte_array_t as there are binary compatible + */ +template < class T > +class Array /*: public byte_array*/ +{ +public: + +/*! + * Default ctor to provide two-stage initialization completed by Init() call. + */ +Array() +{ + data_ = NULL; + size_ = 0; +} + +/*! + * Constructs the object and initializes pointer and size to the provided + * values. + * + * \param ptr - Pointer to the array. + * \param size - Size of the array pointed by the ptr. + */ +Array(T * ptr, size_t size) +{ + data_ = (T *)ptr; + size_ = size; +} + +/*! + * Completes two-stage object initialization when initialized by the default + * ctor. + * + * \param ptr - Pointer to the array. + * \param size - Size of the array pointed by the ptr. + */ +void Init(T *ptr, size_t size) +{ + data_ = (T *)ptr; + size_ = size; +} + +/*! + * Completes two-stage object initialization when initialized by the default + * ctor. + * + * \param ptr - Pointer to the array. + * \param end - Pointer to the end of the array. + */ +void InitWithRange(T *ptr, T *ptr_end) +{ + assert(ptr_end >= ptr); + data_ = (T *)ptr; + size_ = ptr_end - ptr; +} + +/*! + * Detaches the wrapper from the array object. Provided for the sake of + * completeness since array lifetime is not bound to the wrapper lifetime. + */ +void Detach(void) { data_ = NULL; size_ = 0; } +/*! + * Retrieves the size of the array. + * + * \return Size of the array. It may be zero if the wrapper is not fully + * initialized. + */ +size_t size(void) const { return size_; } +/*! + * Retrieves allocated size of buffer in bytes. + */ +size_t alloc_size(void) const { return size()*sizeof(T); } +/*! + * Resizes the array. + */ +void Resize(size_t new_size) { size_ = new_size; } +/*! + * Retrieves address of the array (const version). + * \return Address of the array. It may be null if the wrapper is not fully + * initialized. + */ +const T *data(void) const { return (const T *)data_; } +/*! + * Retrieves address of the array (modifiable version). + * + * \return Address of the array. It may be null if the wrapper is not fully + * initialized. + */ +T *data(void) { return (T *)data_; } +/*! + * Retrieves address of end of the array (const version). + * \return Address of the array. + */ +const T *data_end(void) const { return data() + size_; } +/*! + * Retrieves address of end of the array (modifiable version). + * \return Address of end of the array. + */ +T *data_end(void) { return data() + size_; } +/*! + * Safe (in debug) operator to access element of the array (const version). + * + * \param idx Index of the element to be accessed. + * \return Reference to the element. + */ +const T & operator[](size_t idx) const { + /*assert(idx < size()); //TODO: no exceptions, release err handling req */ + return data()[idx]; +} + +/*! + * Safe (in debug) operator to access element of the array (modifiable version). + * + * \param idx Index of the element to be accessed. + * \return Reference to the element. + */ +T & operator[](size_t idx) { + /*assert(idx < size()); //TODO: no exceptions, release err handling req */ + return data()[idx]; +} + +/*! + * Safe copy-from operation that verifies size of source and this. + * + * \param src Address of the source array to be copied into this. + * \param srcSize Size of the source array. + * \param dst_offset Offset in the destination array to start copying data at + * (expressed in number of items). + */ +void copyFrom(const T *src, size_t srcSize, size_t dst_offset = 0) +{ + assert(data() != NULL); + assert(size() > dst_offset); + assert((size() - dst_offset) >= srcSize); + memcpy_s(data() + dst_offset, alloc_size() - dst_offset * sizeof(T), + src, srcSize * sizeof(T)); +} + +/*! + * Safe copy-from operation that verifies size of source and this. + * + * \param src The source array to be copied into this. + * \param dst_offset Offset in the destination array to start copying data at + * (expressed in number of items). + */ +void copyFrom(const Array < T > &src, size_t dst_offset = 0) +{ + assert(data() != 0); + assert(size() > dst_offset); + assert((size() - dst_offset) >= src.size()); + memcpy_s(data() + dst_offset, alloc_size() - dst_offset * sizeof(T), + src.data(), src.alloc_size()); +} + +/*! + * Safe copy-to operation that verifies size of the destination and this. + * \param dst Address of the destination array to be overwritten by this. + * \param dstSize Size of the destination array. + */ +void copyTo(T *dst, size_t dstSize) const { + assert(data() != 0); + assert(size() <= dstSize); + memcpy_s(dst, dstSize * sizeof(T), data(), alloc_size()); +} + +/*! + * Safe copy-to operation that verifies size of the destination and this. + * \param dst The destination array to be overwritten by this. + */ +void copyTo(Array < T > &dst) const { + assert(data() != 0); + assert(size() <= dst.size()); + memcpy_s(dst.data(), dst.alloc_size(), data(), alloc_size()); +} + +/*! + * Copies as much as specified size starting from specified offset. + * \param dst Destination buffer. + * \param copy_size Number of items to be copied. + * \param src_offset Offset in the source buffer (in number of items). + */ +void copyFragmentTo(Array < T > &dst, size_t copy_size, size_t src_offset = 0) const { + assert(data() != 0); + assert((src_offset + copy_size) <= size()); + assert(copy_size <= dst.size()); + memcpy_s(dst.data(), dst.alloc_size(), data() + src_offset, copy_size * sizeof(T)); +} + +/*! + * Safe cast of the content of the array to the specified type (modifiable + * version). + * \return Pointer to the requested type if array is large enough to be + * casted, NULL otherwise. + */ +template < class TC > +TC *dataAs(void) +{ + if (alloc_size() < sizeof(TC)) { + assert(false); + return NULL; + } + return reinterpret_cast < TC * > (data()); +} + +template < class TC > +TC *dataAsArray(size_t size) +{ + if (alloc_size() < sizeof(TC)*size) { + assert(false); + return NULL; + } + return reinterpret_cast < TC * > (data()); +} + +/*! + * Safe cast of the content of the array to the specified type (const version). + * \return Pointer to the requested type if array is large enough to be + * casted, NULL otherwise. + */ +template < class TC > +const TC *dataAs(void) const { + if (alloc_size() < sizeof(TC)) { + assert(false); + return NULL; + } + return reinterpret_cast < const TC * > (data()); +} + +/*! + * Inserts object of specified type into the buffer. + * Use this explicit call instead of operator=(TC) or stream-like <<. + */ +template < class TC > +void setDataAs(const TC & d) +{ + TC *t = dataAs < TC > (); + + if (t == NULL) { + assert(false); + return; + } + *t = d; /* using operator=, not shallow copy */ + Resize(sizeof(TC)); +} + +/*! + * Safe zero-memory on the underlying buffer. + */ +void clear(void) +{ + memset(data(), 0x00, alloc_size()); +} + +void Swap(Array < T > *array) +{ + Array < T > temp(*array); + array->data_ = data_; + array->size_ = size_; + this->data_ = temp.data_; + this->size_ = temp.size_; +} + +void Swap(Array < T > &array) +{ + Array < T > temp(array); + array.data_ = data_; + array.size_ = size_; + this->data_ = temp.data_; + this->size_ = temp.size_; +} +private: + T *data_; + size_t size_; +}; + +/*! + * Predefined type of array of bytes. + */ +typedef Array < uint8_t > ByteArray; + +/*! + * Predefined type of array of dwords. + */ +typedef Array < uint32_t > DwordArray; + +} /* end of namespace dsp_fw */ + +#endif /* __cplusplus */ +/* clang-format on */ +#endif /* #ifndef DSP_FW_FW_ARRAY_H_ */ diff --git a/src/include/sof/audio/module_adapter/library/native_system_agent.h b/src/include/sof/audio/module_adapter/library/native_system_agent.h new file mode 100644 index 000000000000..70c0f6b1aad1 --- /dev/null +++ b/src/include/sof/audio/module_adapter/library/native_system_agent.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ + +#ifndef __NATIVE_SYSTEM_AGENT_H__ +#define __NATIVE_SYSTEM_AGENT_H__ + +#include <sof/audio/module_adapter/module/module_interface.h> +#include <native_system_service.h> + +struct system_agent_params { + uintptr_t entry_point; /* The module entry point function address. */ + uint32_t module_id; /* The identifier for the module. */ + uint32_t instance_id; /* The instance identifier of the module. */ + uint32_t core_id; /* Core on which the module will run. */ + uint32_t log_handle; /* The handle for logging purposes. */ + void *mod_cfg; /* Pointer to the module configuration data. */ +}; + +typedef int (*system_agent_start_fn)(const struct system_agent_params *params, + const void **adapter); + +struct native_system_agent { + struct system_service system_service; + uint32_t log_handle; + uint32_t core_id; + uint32_t module_id; + uint32_t instance_id; + uint32_t module_size; +}; + +/** + * @brief Starts the native system agent. + * + * This function initializes and starts the native system agent with the provided parameters. + * + * @param[in] params - Pointer to the system agent parameter structure + * @param[out] iface - Pointer to the module interface. + * + * @return Returns 0 on success or an error code on failure. + */ +int native_system_agent_start(const struct system_agent_params *params, + const void **iface); + +#endif /* __NATIVE_SYSTEM_AGENT_H__ */ diff --git a/src/include/sof/audio/module_adapter/library/native_system_service.h b/src/include/sof/audio/module_adapter/library/native_system_service.h new file mode 100644 index 000000000000..ab8188a2eca4 --- /dev/null +++ b/src/include/sof/audio/module_adapter/library/native_system_service.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 - 2024 Intel Corporation. All rights reserved. + */ + +#ifndef NATIVE_SYSTEM_SERVICE_H +#define NATIVE_SYSTEM_SERVICE_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <module/module/system_service.h> + +struct native_system_service { + struct system_service basic; +}; + +void native_system_service_log_message(enum log_priority log_priority, uint32_t log_entry, + struct log_handle const *log_handle, uint32_t param1, + uint32_t param2, uint32_t param3, uint32_t param4); + +AdspErrorCode native_system_service_safe_memcpy(void *RESTRICT dst, size_t maxlen, + const void *RESTRICT src, size_t len); + +AdspErrorCode native_system_service_safe_memmove(void *dst, size_t maxlen, + const void *src, size_t len); + +void *native_system_service_vec_memset(void *dst, int c, size_t len); + +AdspErrorCode native_system_service_create_notification(struct notification_params *params, + uint8_t *notification_buffer, + uint32_t notification_buffer_size, + struct notification_handle **handle); + +AdspErrorCode native_system_service_send_notif_msg(enum notification_target notification_target, + struct notification_handle *message, + uint32_t actual_payload_size); + +AdspErrorCode native_system_service_get_interface(enum interface_id id, + struct system_service_iface **iface); + +extern const struct native_system_service native_system_service; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* NATIVE_SYSTEM_SERVICE_H */ diff --git a/src/include/sof/audio/module_adapter/library/userspace_proxy.h b/src/include/sof/audio/module_adapter/library/userspace_proxy.h new file mode 100644 index 000000000000..482590caf67f --- /dev/null +++ b/src/include/sof/audio/module_adapter/library/userspace_proxy.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __SOF_AUDIO_USERSPACE_PROXY_H__ +#define __SOF_AUDIO_USERSPACE_PROXY_H__ + +#if CONFIG_USERSPACE +#include <stdint.h> +#include <stdbool.h> + +#include <zephyr/kernel.h> +#include <zephyr/app_memory/app_memdomain.h> +#include <utilities/array.h> + +#include <native_system_agent.h> +#include <module/module/interface.h> +#include <sof/audio/module_adapter/library/userspace_proxy_user.h> + +struct module_interface; +struct comp_driver; +struct sof_man_module; +struct system_agent_params; + +/* Processing module structure fields needed for user mode */ +struct userspace_context { + struct k_mem_domain *comp_dom; /* Module specific memory domain */ + const struct module_interface *interface; /* Userspace module interface */ + struct user_work_item *work_item; /* work item for user worker thread */ + struct k_event *dp_event; /* DP thread event */ +}; +#endif /* CONFIG_USERSPACE */ + +#if CONFIG_SOF_USERSPACE_PROXY +/** + * Creates userspace module proxy + * + * @param user_ctx - pointer to pointer of userspace module context + * @param drv - pointer to component driver + * @param manifest - pointer to module manifest + * @param start_fn - pointer to system agent start function + * @param agent_params - pointer to system_agent_params + * @param agent_interface - pointer to variable to store module interface created by agent + * @param ops - Pointer to a variable that will hold the address of the module interface + * structure. The function stores a pointer to its own userspace proxy + * interface structure in this variable. + * + * @return 0 for success, error otherwise. + */ +int userspace_proxy_create(struct userspace_context **user_ctx, const struct comp_driver *drv, + const struct sof_man_module *manifest, system_agent_start_fn start_fn, + const struct system_agent_params *agent_params, + const void **agent_interface, const struct module_interface **ops); + +/** + * Destroy userspace module proxy + * + * @param drv - pointer to component driver + * @param user_ctx - pointer to userspace module context + */ +void userspace_proxy_destroy(const struct comp_driver *drv, struct userspace_context *user_ctx); + +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) +/** + * Register a k_event object used to notify the DP thread about a pending userspace module IPC + * request to process. + * + * @param mod Pointer to the processing module. + * @param event Pointer to the event to signal incoming IPC. + * + * @return Pointer to a k_work_user work item for userspace modules, or NULL for non-userspace + * modules. + */ +struct k_work_user *userspace_proxy_register_ipc_handler(struct processing_module *mod, + struct k_event *event); +#endif + +#endif /* CONFIG_SOF_USERSPACE_PROXY */ + +#endif /* __SOF_AUDIO_USERSPACE_PROXY_H__ */ diff --git a/src/include/sof/audio/module_adapter/library/userspace_proxy_user.h b/src/include/sof/audio/module_adapter/library/userspace_proxy_user.h new file mode 100644 index 000000000000..e571705cec17 --- /dev/null +++ b/src/include/sof/audio/module_adapter/library/userspace_proxy_user.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __SOF_AUDIO_USERSPACE_PROXY_USER_H__ +#define __SOF_AUDIO_USERSPACE_PROXY_USER_H__ + +#if CONFIG_SOF_USERSPACE_PROXY +struct module_agent_params { + system_agent_start_fn start_fn; + struct system_agent_params params; + byte_array_t mod_cfg; + const void *out_interface; +}; + +struct module_large_cfg_set_params { + uint32_t config_id; + enum module_cfg_fragment_position pos; + uint32_t data_off_size; + const uint8_t *fragment; + size_t fragment_size; + uint8_t *response; + size_t response_size; +}; + +struct module_large_cfg_get_params { + uint32_t config_id; + uint32_t *data_off_size; + uint8_t *fragment; + size_t fragment_size; +}; + +struct module_processing_mode_params { + enum module_processing_mode mode; +}; + +struct module_process_params { + struct sof_source **sources; + int num_of_sources; + struct sof_sink **sinks; + int num_of_sinks; +}; + +enum userspace_proxy_cmd { + USER_PROXY_MOD_CMD_AGENT_START, + USER_PROXY_MOD_CMD_INIT, + USER_PROXY_MOD_CMD_PREPARE, + USER_PROXY_MOD_CMD_PROC_READY, + USER_PROXY_MOD_CMD_SET_PROCMOD, + USER_PROXY_MOD_CMD_GET_PROCMOD, + USER_PROXY_MOD_CMD_SET_CONF, + USER_PROXY_MOD_CMD_GET_CONF, + USER_PROXY_MOD_CMD_BIND, + USER_PROXY_MOD_CMD_UNBIND, + USER_PROXY_MOD_CMD_RESET, + USER_PROXY_MOD_CMD_FREE, + USER_PROXY_MOD_CMD_TRIGGER +}; + +struct module_params { + enum userspace_proxy_cmd cmd; + int status; + struct processing_module *mod; + struct userspace_context *context; + /* The field used in the union depends on the value of cmd */ + union { + struct module_agent_params agent; + struct module_large_cfg_set_params set_conf; + struct module_large_cfg_get_params get_conf; + struct module_processing_mode_params proc_mode; + struct module_process_params proc; + struct bind_info *bind_data; + int trigger_data; + } ext; +}; + +struct user_work_item { + struct k_work_user work_item; /* ipc worker workitem */ + struct k_event *event; /* ipc worker done event */ + struct module_params params; +}; + +void userspace_proxy_handle_request(struct processing_module *mod, struct module_params *params); + +void userspace_proxy_worker_handler(struct k_work_user *work_item); + +#endif /* CONFIG_SOF_USERSPACE_PROXY */ + +#endif /* __SOF_AUDIO_USERSPACE_PROXY_USER_H__ */ diff --git a/src/include/sof/audio/module_adapter/module/cadence.h b/src/include/sof/audio/module_adapter/module/cadence.h new file mode 100644 index 000000000000..8ba658749c05 --- /dev/null +++ b/src/include/sof/audio/module_adapter/module/cadence.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_CADENCE_CODEC__ +#define __SOF_AUDIO_CADENCE_CODEC__ + +#include <sof/audio/cadence/xa_type_def.h> +#include <sof/audio/cadence/xa_apicmd_standards.h> +#include <sof/audio/cadence/xa_error_standards.h> +#include <sof/audio/cadence/xa_memory_standards.h> + +#define LIB_NAME_MAX_LEN 30 +#define LIB_NO_ERROR XA_NO_ERROR +#define LIB_IS_FATAL_ERROR(e) ((e) & XA_FATAL_ERROR) +#define CODEC_GET_API_ID(id) ((id) & 0xFF) +#define CADENCE_MP3_ENCODER_DEFAULT_BITRATE 320 + +/*****************************************************************************/ +/* Cadence API functions */ +/*****************************************************************************/ +extern xa_codec_func_t cadence_api_function; +extern xa_codec_func_t xa_aac_dec; +extern xa_codec_func_t xa_bsac_dec; +extern xa_codec_func_t xa_dabplus_dec; +extern xa_codec_func_t xa_drm_dec; +extern xa_codec_func_t xa_mp3_dec; +extern xa_codec_func_t xa_mp3_enc; +extern xa_codec_func_t xa_sbc_dec; +extern xa_codec_func_t xa_vorbis_dec; +extern xa_codec_func_t xa_src_pp; + +#define DEFAULT_CODEC_ID CADENCE_CODEC_WRAPPER_ID + +#define API_CALL(cd, cmd, sub_cmd, value, ret) \ + do { \ + ret = (cd)->api((cd)->self, \ + (cmd), \ + (sub_cmd), \ + (value)); \ + } while (0) + +/*****************************************************************************/ +/* Cadence private data types */ +/*****************************************************************************/ +struct cadence_api { + uint32_t id; + xa_codec_func_t *api; +}; + +struct cadence_codec_data { +#if CONFIG_IPC_MAJOR_4 + struct ipc4_base_module_cfg base_cfg; + uint32_t direction; +#endif + char name[LIB_NAME_MAX_LEN]; + void *self; + xa_codec_func_t *api; + void *mem_tabs; + size_t mem_to_be_freed_len; + void **mem_to_be_freed; + uint32_t api_id; + struct module_config setup_cfg; +}; + +enum cadence_api_id { + CADENCE_CODEC_WRAPPER_ID = 0x01, + CADENCE_CODEC_AAC_DEC_ID = 0x02, + CADENCE_CODEC_BSAC_DEC_ID = 0x03, + CADENCE_CODEC_DAB_DEC_ID = 0x04, + CADENCE_CODEC_DRM_DEC_ID = 0x05, + CADENCE_CODEC_MP3_DEC_ID = 0x06, + CADENCE_CODEC_SBC_DEC_ID = 0x07, + CADENCE_CODEC_VORBIS_DEC_ID = 0x08, + CADENCE_CODEC_SRC_PP_ID = 0x09, + CADENCE_CODEC_MP3_ENC_ID = 0x0A, +}; + +#if CONFIG_IPC_MAJOR_4 +struct ipc4_cadence_module_cfg { + struct ipc4_base_module_cfg base_cfg; + uint32_t param_size; + struct module_param param[]; +} __packed __aligned(4); +#endif + +extern struct cadence_api cadence_api_table[]; + +int cadence_codec_set_configuration(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, + uint32_t data_offset_size, const uint8_t *fragment, + size_t fragment_size, uint8_t *response, size_t response_size); +int cadence_codec_resolve_api_with_id(struct processing_module *mod, uint32_t codec_id, + uint32_t direction); +int cadence_codec_apply_params(struct processing_module *mod, int size, void *data); +int cadence_codec_process_data(struct processing_module *mod, + XA_ERRORCODE *api_error_code); +int cadence_codec_apply_config(struct processing_module *mod); +void cadence_codec_free_memory_tables(struct processing_module *mod); +int cadence_codec_init_memory_tables(struct processing_module *mod); +int cadence_codec_get_samples(struct processing_module *mod); +int cadence_codec_init_process(struct processing_module *mod); +int cadence_init_codec_object(struct processing_module *mod); +int cadence_codec_resolve_api(struct processing_module *mod); +int cadence_codec_free(struct processing_module *mod); +size_t cadence_api_table_size(void); + +#endif /* __SOF_AUDIO_CADENCE_CODEC__ */ diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h new file mode 100644 index 000000000000..91bdce96b1c7 --- /dev/null +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -0,0 +1,487 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * + * \file generic.h + * \brief Generic Module API header file + * \author Marcin Rajwa <marcin.rajwa@linux.intel.com> + * \author Adrian Warecki <adrian.warecki@intel.com> + * + */ + +#ifndef __SOF_AUDIO_MODULE_GENERIC__ +#define __SOF_AUDIO_MODULE_GENERIC__ + +#include <sof/objpool.h> +#include <sof/ut.h> +#include <sof/audio/component.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include "module_interface.h" + +/* The __ZEPHYR__ condition is to keep cmocka tests working */ +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) +#include <zephyr/kernel/thread.h> +#endif +#include <sof/compiler_attributes.h> + +/* + * helpers to determine processing type + * Needed till all the modules use PROCESSING_MODE_SINK_SOURCE + */ +#define IS_PROCESSING_MODE_AUDIO_STREAM(mod) ((mod)->proc_type == MODULE_PROCESS_TYPE_STREAM) +#define IS_PROCESSING_MODE_RAW_DATA(mod) ((mod)->proc_type == MODULE_PROCESS_TYPE_RAW) +#define IS_PROCESSING_MODE_SINK_SOURCE(mod) ((mod)->proc_type == MODULE_PROCESS_TYPE_SOURCE_SINK) + +#if CONFIG_IPC_MAJOR_4 +#define IPC_MOD_CMD(v) +#elif CONFIG_IPC_MAJOR_3 +#define IPC_MOD_CMD(v) .cmd = v, +#endif + +/* + * \brief Macro to declare a module adapter component. + * \param adapter - name of the module. + * \param uuid - UUID of the module. + * \param tr - trace context for the module. + * + * This macro declares a module component with the specified name, UUID, and trace context. + * It initializes the component module structure with the appropriate type, UID, and + * struct module_interface operations. + */ +#define DECLARE_MODULE_ADAPTER(adapter, uuid, tr) \ +static const struct comp_driver comp_##adapter##_module = { \ + .type = SOF_COMP_MODULE_ADAPTER, \ + .uid = SOF_RT_UUID(uuid), \ + .tctx = &(tr), \ + .ops = { \ + .create = module_adapter_new, \ + .prepare = module_adapter_prepare, \ + .params = module_adapter_params, \ + .copy = module_adapter_copy, \ + IPC_MOD_CMD(module_adapter_cmd) \ + .trigger = module_adapter_trigger, \ + .reset = module_adapter_reset, \ + .free = module_adapter_free, \ + .set_large_config = module_set_large_config,\ + .get_large_config = module_get_large_config,\ + .get_attribute = module_adapter_get_attribute,\ + .set_attribute = module_adapter_set_attribute,\ + .bind = module_adapter_bind,\ + .unbind = module_adapter_unbind,\ + .get_total_data_processed = module_adapter_get_total_data_processed,\ + .dai_get_hw_params = module_adapter_get_hw_params,\ + .position = module_adapter_position,\ + .dai_ts_config = module_adapter_ts_config_op,\ + .dai_ts_start = module_adapter_ts_start_op,\ + .dai_ts_stop = module_adapter_ts_stop_op,\ + .dai_ts_get = module_adapter_ts_get_op,\ + }, \ + .adapter_ops = &(adapter), \ +}; \ +\ +static SHARED_DATA struct comp_driver_info comp_module_##adapter##_info = { \ + .drv = &comp_##adapter##_module, \ +}; \ +\ +UT_STATIC void sys_comp_module_##adapter##_init(void) \ +{ \ + comp_register(platform_shared_get(&comp_module_##adapter##_info, \ + sizeof(comp_module_##adapter##_info))); \ +} \ +\ +DECLARE_MODULE(sys_comp_module_##adapter##_init) + +/** + * \enum module_state + * \brief Module-specific states + */ +enum module_state { + MODULE_DISABLED, /**< Module isn't initialized yet or has been freed.*/ + MODULE_INITIALIZED, /**< Module initialized or reset. */ + MODULE_IDLE, /**< Module is idle now. */ + MODULE_PROCESSING, /**< Module is processing samples now. */ +}; + +/** + * \struct module_param + * \brief Module TLV parameters container - used for both config types. + * For example if one want to set the sample_rate to 16 [kHz] and this + * parameter was assigned to id 0x01, its max size is four bytes then the + * configuration filed should look like this (note little-endian format): + * 0x01 0x00 0x00 0x00, 0x0C 0x00 0x00 0x00, 0x10 0x00 0x00 0x00. + */ +struct module_param { + /** + * Specifies the unique id of a parameter. For example the parameter + * sample_rate may have an id of 0x01. + */ + uint32_t id; + uint32_t size; /**< The size of whole parameter - id + size + data */ + int32_t data[]; /**< A pointer to memory where config is stored.*/ +}; + +/** + * \struct module_resources + * \brief module resources block - used for module allocation records + * The allocations are recorded so that they can be automatically freed + * when the module unloads. + */ +struct module_resources { + struct objpool_head objpool; + size_t heap_usage; + size_t heap_high_water_mark; + struct mod_alloc_ctx *alloc; +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) + k_tid_t rsrc_mngr; +#endif +}; + +enum mod_resource_type { + MOD_RES_UNINITIALIZED = 0, + MOD_RES_HEAP, + MOD_RES_BLOB_HANDLER, + MOD_RES_FAST_GET, +}; + +/** + * \struct module_resource + * \brief module memory container - used for every memory allocated by module + */ +struct module_resource { + union { + void *ptr; /**< Pointer to heap allocated memory */ + struct comp_data_blob_handler *bhp; /**< Blob handler ptr */ + const void *sram_ptr; /**< SRAM ptr from fast_get() */ + }; + struct list_item list; /**< list element */ + size_t size; /**< Size of allocated heap memory, 0 if not from heap */ + enum mod_resource_type type; /**< Resource type */ +}; + +/** + * \struct module_processing_data + * \brief Processing data shared between particular module & module_adapter + */ +struct module_processing_data { + uint32_t in_buff_size; /**< Specifies the size of module input buffer. */ + uint32_t out_buff_size; /**< Specifies the size of module output buffer.*/ + uint32_t avail; /**< Specifies how much data is available for module to process.*/ + uint32_t produced; /**< Specifies how much data the module produced in its last task.*/ + uint32_t consumed; /**< Specified how much data the module consumed in its last task */ + uint32_t init_done; /**< Specifies if the module initialization is finished */ + bool eos_reached; /**< End of stream processing is reached */ + bool eos_notification_sent; /**< EOS notification is sent to host */ + void *in_buff; /**< A pointer to module input buffer. */ + void *out_buff; /**< A pointer to module output buffer. */ +}; + +/* + * Definition used to extend structure definitions to include fields for exclusive use by SOF. + * This is a temporary solution used until work on separating a common interface for loadable + * modules is completed. + */ +#define SOF_MODULE_API_PRIVATE + +#include <module/module/base.h> + +/*****************************************************************************/ +/* Module generic interfaces */ +/*****************************************************************************/ +int module_load_config(struct comp_dev *dev, const void *cfg, size_t size); +int module_init(struct processing_module *mod); +void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment); +void mod_resource_init(struct processing_module *mod); +void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start); +#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION) +__syscall void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, + size_t alignment); +__syscall int mod_free(struct processing_module *mod, const void *ptr); +#else +void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, + size_t alignment); +int z_impl_mod_free(struct processing_module *mod, const void *ptr); +#define mod_alloc_ext z_impl_mod_alloc_ext +#define mod_free z_impl_mod_free +#endif + +/** + * Allocates aligned memory block for module. + * @param mod Pointer to the module this memory block is allocated for. + * @param size Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + * + * The allocated memory is automatically freed when the module is unloaded. + */ +static inline void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment) +{ + return mod_alloc_ext(mod, SOF_MEM_FLAG_USER, size, alignment); +} + +static inline void *mod_balloc(struct processing_module *mod, size_t size) +{ + return mod_balloc_align(mod, size, 0); +} + +static inline void *mod_alloc(struct processing_module *mod, size_t size) +{ + return mod_alloc_align(mod, size, 0); +} + +static inline void *mod_zalloc(struct processing_module *mod, size_t size) +{ + void *ret = mod_alloc(mod, size); + + if (ret) + memset(ret, 0, size); + + return ret; +} + +#if CONFIG_COMP_BLOB +struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod); +void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh); +#endif +#if CONFIG_FAST_GET +#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION) +__syscall const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr, + size_t size); +#else +const void *z_impl_mod_fast_get(struct processing_module *mod, const void * const dram_ptr, + size_t size); +#define mod_fast_get z_impl_mod_fast_get +#endif +void mod_fast_put(struct processing_module *mod, const void *sram_ptr); +#endif +void mod_free_all(struct processing_module *mod); +int module_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); + +static inline +bool generic_module_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + int i; + + for (i = 0; i < num_of_sources; i++) + if (source_get_data_available(sources[i]) < source_get_min_available(sources[i])) + return false; + + for (i = 0; i < num_of_sinks; i++) + if (sink_get_free_size(sinks[i]) < sink_get_min_free_space(sinks[i])) + return false; + + return true; +} + +static inline +bool module_is_ready_to_process(struct processing_module *mod, + struct sof_source **sources, + int num_of_sources, + struct sof_sink **sinks, + int num_of_sinks) +{ + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + /* LL module has to be always ready for processing */ + if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + return true; + + if (ops->is_ready_to_process) + return ops->is_ready_to_process(mod, sources, num_of_sources, sinks, num_of_sinks); + /* default action - the module is ready if there's enough data for processing and enough + * space to store result. IBS/OBS as declared in init_instance + */ + return generic_module_is_ready_to_process(mod, sources, num_of_sources, sinks, + num_of_sinks); +} + +int module_process_sink_src(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks); +int module_process_legacy(struct processing_module *mod, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers); +int module_reset(struct processing_module *mod); +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, + size_t response_size); +int module_bind(struct processing_module *mod, struct bind_info *bind_data); +int module_unbind(struct processing_module *mod, struct bind_info *unbind_data); + +struct comp_dev *module_adapter_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, const void *spec); +struct userspace_context; +struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, + const struct comp_ipc_config *config, const void *spec, + void *mod_priv, struct userspace_context *user_ctx); +int module_adapter_prepare(struct comp_dev *dev); +int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *params); +int module_adapter_copy(struct comp_dev *dev); +int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size); +int module_adapter_trigger(struct comp_dev *dev, int cmd); +void module_adapter_free(struct comp_dev *dev); +int module_adapter_reset(struct comp_dev *dev); + +size_t module_adapter_heap_usage(struct processing_module *mod, size_t *hwm); + +#if CONFIG_IPC_MAJOR_3 +static inline +int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value) +{ + return -EINVAL; +} + +static inline +int module_adapter_set_attribute(struct comp_dev *dev, uint32_t type, void *value) +{ + return -EINVAL; +} + +static inline +int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, + bool last_block, uint32_t data_offset, const char *data) +{ + return 0; +} + +static inline +int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, + bool last_block, uint32_t *data_offset, char *data) +{ + return 0; +} + +static inline +int module_adapter_bind(struct comp_dev *dev, struct bind_info *bind_data) +{ + return 0; +} + +static inline +int module_adapter_unbind(struct comp_dev *dev, struct bind_info *unbind_data) +{ + return 0; +} + +static inline +uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, + uint32_t stream_no, bool input) +{ + return 0; +} + +static inline int module_process_endpoint(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers) +{ + return module_process_legacy(mod, input_buffers, num_input_buffers, + output_buffers, num_output_buffers); +} + +#else +int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, + bool last_block, uint32_t data_offset, const char *data); +int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, + bool last_block, uint32_t *data_offset, char *data); +int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value); +int module_adapter_set_attribute(struct comp_dev *dev, uint32_t type, void *value); +int module_adapter_bind(struct comp_dev *dev, struct bind_info *bind_data); +int module_adapter_unbind(struct comp_dev *dev, struct bind_info *unbind_data); +uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, + uint32_t stream_no, bool input); + +static inline int module_process_endpoint(struct processing_module *mod, + struct input_stream_buffer *input_buffers, + int num_input_buffers, + struct output_stream_buffer *output_buffers, + int num_output_buffers) +{ + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + + return ops->process_audio_stream(mod, input_buffers, num_input_buffers, + output_buffers, num_output_buffers); +} + +#endif + +int module_adapter_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir); +int module_adapter_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); +int module_adapter_ts_config_op(struct comp_dev *dev); +int module_adapter_ts_start_op(struct comp_dev *dev); +int module_adapter_ts_stop_op(struct comp_dev *dev); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +int module_adapter_ts_get_op(struct comp_dev *dev, struct dai_ts_data *tsd); +#else +int module_adapter_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd); +#endif + +void module_update_buffer_position(struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + uint32_t frames); +struct module_ext_init_data; +#if CONFIG_IPC_MAJOR_4 +int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init_data *ext_data, + struct ipc_config_process *spec); +#else +static inline +int module_ext_init_decode(const struct comp_driver *drv, struct module_ext_init_data *ext_data, + struct ipc_config_process *spec) +{ + return 0; +} +#endif +int module_adapter_init_data(struct comp_dev *dev, + struct module_config *dst, + const struct comp_ipc_config *config, + const void *spec); +void module_adapter_reset_data(struct module_config *dst); +void module_adapter_check_data(struct processing_module *mod, struct comp_dev *dev, + struct comp_buffer *sink); +void module_adapter_set_params(struct processing_module *mod, struct sof_ipc_stream_params *params); +int module_adapter_set_state(struct processing_module *mod, struct comp_dev *dev, + int cmd); +int module_adapter_sink_src_prepare(struct comp_dev *dev); + +/** + * Get a deadline based on current LFT reported by all sinks + * it returns a value >= UINT32_MAX / 2 in case the deadline cannot be calculated: + * - if a module is in a dealayed start + * - if there's no sink - i.e. DP module is a pure data consumer (like key phrare detector) + * + * @return a deadline the module must finish processing since NOW [in us] + */ +uint32_t module_get_deadline(struct processing_module *mod); + +/** + * Get a Longest Processing Time estimation for the module, in us + * It is either + * - a value taken from the manifest or estimated from module period (TODO) + * - or a value taken from IPC call (TODO) + * - a worst case - module period + * note that module period may be calculated reasonably late, i.e. in prepare() method + */ +static inline uint32_t module_get_lpt(struct processing_module *mod) +{ + /* return worst case of LPT - a module period. See zephyr_dp_schedule.c for description */ + return mod->dev->period; +} + +#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION) +#include <zephyr/syscalls/generic.h> +#endif + +#endif /* __SOF_AUDIO_MODULE_GENERIC__ */ diff --git a/src/include/sof/audio/module_adapter/module/module_interface.h b/src/include/sof/audio/module_adapter/module/module_interface.h new file mode 100644 index 000000000000..ccddcf6fda0a --- /dev/null +++ b/src/include/sof/audio/module_adapter/module/module_interface.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2020 - 2023 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + */ + +#ifndef __SOF_MODULE_INTERFACE__ +#define __SOF_MODULE_INTERFACE__ + +#include <sof/compiler_attributes.h> +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> + +/* + * Definition used to extend structure definitions to include fields for exclusive use by SOF. + * This is a temporary solution used until work on separating a common interface for loadable + * modules is completed. + */ +#define SOF_MODULE_API_PRIVATE + +#include <module/module/interface.h> + +struct comp_dev; +struct timestamp_data; +struct dai_ts_data; +struct sof_ipc_stream_posn; + +/** + * \struct module_endpoint_ops + * \brief Ops relevant only for the endpoint devices such as the host copier or DAI copier. + * Other modules should not implement these. + */ +struct module_endpoint_ops { + /** + * Returns total data processed in number bytes. + * @param dev Component device + * @param stream_no Index of input/output stream + * @param input Selects between input (true) or output (false) stream direction + * @return total data processed if succeeded, 0 otherwise. + */ + uint64_t (*get_total_data_processed)(struct comp_dev *dev, uint32_t stream_no, bool input); + /** + * Retrieves component rendering position. + * @param dev Component device. + * @param posn Receives reported position. + */ + int (*position)(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); + /** + * Configures timestamping in attached DAI. + * @param dev Component device. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_config)(struct comp_dev *dev); + + /** + * Starts timestamping. + * @param dev Component device. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_start)(struct comp_dev *dev); + + /** + * Stops timestamping. + * @param dev Component device. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_stop)(struct comp_dev *dev); + + /** + * Gets timestamp. + * @param dev Component device. + * @param tsd Receives timestamp data. + * + * Mandatory for components that allocate DAI. + */ +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + int (*dai_ts_get)(struct comp_dev *dev, struct dai_ts_data *tsd); +#else + int (*dai_ts_get)(struct comp_dev *dev, struct timestamp_data *tsd); +#endif + + /** + * Fetches hardware stream parameters. + * @param dev Component device. + * @param params Receives copy of stream parameters retrieved from + * DAI hw settings. + * @param dir Stream direction (see enum sof_ipc_stream_direction). + * + * Mandatory for components that allocate DAI. + */ + int (*dai_get_hw_params)(struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir); + + /** + * Triggers device state. + * @param dev Component device. + * @param cmd Trigger command. + */ + int (*trigger)(struct comp_dev *dev, int cmd); +}; + +/* Convert first_block/last_block indicator to fragment position */ +static inline enum module_cfg_fragment_position +first_last_block_to_frag_pos(bool first_block, bool last_block) +{ + int frag_position = (last_block << 1) | first_block; + + return (enum module_cfg_fragment_position)frag_position; +} + +#endif /* __SOF_MODULE_INTERFACE__ */ diff --git a/src/include/sof/audio/module_adapter/module/modules.h b/src/include/sof/audio/module_adapter/module/modules.h new file mode 100644 index 000000000000..b718c1216d00 --- /dev/null +++ b/src/include/sof/audio/module_adapter/module/modules.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + */ + +#ifndef __SOF_AUDIO_MODULES__ +#define __SOF_AUDIO_MODULES__ + +#include <sof/audio/module_adapter/module/generic.h> + +/* Intel module adapter is an extension to SOF module adapter component that allows to integrate + * modules developed under IADK (Intel Audio Development Kit) + * and LMDK (Loadable Modules Dev Kit) Framework. Modules uses uniform + * set of interfaces and are linked into separate library. These modules are loaded in runtime + * through library_manager and then after registration into SOF component infrastructure are + * interfaced through module adapter API. + * Since IADK modules uses ProcessingModuleInterface to control/data transfer and AdspSystemService + * to use base FW services from internal module code, there is a communication shim layer defined + * in intel directory. + * + * Since ProcessingModuleInterface consists of virtual functions, there are C++ -> C wrappers + * defined to access the interface calls from SOF code. + * + * The main assumption here was to load IADK Modules without any code modifications. Therefore C++ + * function, structures and variables definition are here kept with original form from + * IADK Framework. This provides binary compatibility for already developed 3rd party modules. + * + * There are three entities in intel module adapter package: + * - System Agent - A mediator to allow the custom module to interact with the base SOF FW. + * It calls IADK module entry point and provides all necessary information to + * connect both sides of ProcessingModuleInterface and System Service. + * - System Service - exposes of SOF base FW services to the module. + * - Processing Module Adapter - SOF base FW side of ProcessingModuleInterface API + * + * Using the same philosofy loadable modules are using module adapter to interact with SOF FW. + * Module recognision is done by checking module API version defined in module/module/api_ver.h + * with version read from elf file. + */ + +/* Processing Module Adapter API */ +extern const struct module_interface processing_module_adapter_interface; + +#endif /* __SOF_AUDIO_MODULES__ */ diff --git a/src/include/sof/audio/mux.h b/src/include/sof/audio/mux.h deleted file mode 100644 index 7d00e125c0d0..000000000000 --- a/src/include/sof/audio/mux.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com> - */ - -/** - * \file include/sof/audio/mux.h - * \brief Multiplexer component header file - * \authors Artur Kloniecki <arturx.kloniecki@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_MUX_H__ -#define __SOF_AUDIO_MUX_H__ - -#include <config.h> - -#if CONFIG_COMP_MUX - -#include <sof/common.h> -#include <sof/platform.h> -#include <sof/trace/trace.h> -#include <sof/ut.h> -#include <user/trace.h> -#include <stdint.h> - -struct comp_buffer; -struct comp_dev; - -/** \brief Supported streams count. */ -#define MUX_MAX_STREAMS 4 - -/** guard against invalid amount of streams defined */ -STATIC_ASSERT(MUX_MAX_STREAMS < PLATFORM_MAX_STREAMS, - unsupported_amount_of_streams_for_mux); - -struct mux_stream_data { - uint32_t pipeline_id; - uint8_t num_channels; - uint8_t mask[PLATFORM_MAX_CHANNELS]; - - uint8_t reserved[(20 - PLATFORM_MAX_CHANNELS - 1) % 4]; // padding to ensure proper alignment of following instances -}; - -typedef void(*demux_func)(const struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, uint32_t frames, - struct mux_stream_data *data); -typedef void(*mux_func)(const struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream **sources, uint32_t frames, - struct mux_stream_data *data); - -struct sof_mux_config { - uint16_t frame_format; - uint16_t num_channels; - uint16_t num_streams; - - uint16_t reserved; // padding to ensure proper alignment - - struct mux_stream_data streams[]; -}; - -struct comp_data { - union { - mux_func mux; - demux_func demux; - }; - - struct sof_mux_config config; -}; - -struct comp_func_map { - uint16_t frame_format; - mux_func mux_proc_func; - demux_func demux_proc_func; -}; - -extern const struct comp_func_map mux_func_map[]; - -mux_func mux_get_processing_function(struct comp_dev *dev); -demux_func demux_get_processing_function(struct comp_dev *dev); - -#ifdef UNIT_TEST -void sys_comp_mux_init(void); - -#if CONFIG_FORMAT_S16LE -int32_t calc_sample_s16le(const struct audio_stream *source, - uint8_t num_ch, uint32_t offset, - uint8_t mask); -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE -int32_t calc_sample_s24le(const struct audio_stream *source, - uint8_t num_ch, uint32_t offset, - uint8_t mask); -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE -int64_t calc_sample_s32le(const struct audio_stream *source, - uint8_t num_ch, uint32_t offset, - uint8_t mask); -#endif /* CONFIG_FORMAT_S32LE */ -#endif /* UNIT_TEST */ - -#endif /* CONFIG_COMP_MUX */ - -#endif /* __SOF_AUDIO_MUX_H__ */ diff --git a/src/include/sof/audio/nxp/eap/EAP_Parameter_presets.h b/src/include/sof/audio/nxp/eap/EAP_Parameter_presets.h new file mode 100644 index 000000000000..745db5579fd0 --- /dev/null +++ b/src/include/sof/audio/nxp/eap/EAP_Parameter_presets.h @@ -0,0 +1,25 @@ +#ifndef EAP_PARAMETER_PRESETS_H_ +#define EAP_PARAMETER_PRESETS_H_ + +#include <nxp/eap/EAP_Includes/EAP16.h> + +#ifndef CONFIG_COMP_NXP_EAP_STUB +#include <Example_Application/CONFIG_HEADER/EAP_Parameter_AllEffectOff.h> +#include <Example_Application/CONFIG_HEADER/EAP_Parameter_AutoVolumeLeveler.h> +#include <Example_Application/CONFIG_HEADER/EAP_Parameter_ConcertSound.h> +#include <Example_Application/CONFIG_HEADER/EAP_Parameter_LoudnessMaximiser.h> +#include <Example_Application/CONFIG_HEADER/EAP_Parameter_MusicEnhancerRMSLimiter.h> +#include <Example_Application/CONFIG_HEADER/EAP_Parameter_VoiceEnhancer.h> + +#else + +uint8_t InstParams_allEffectOff[28] = {}; +uint8_t ControlParamSet_allEffectOff[216] = {}; +uint8_t ControlParamSet_autoVolumeLeveler[216] = {}; +uint8_t ControlParamSet_concertSound[216] = {}; +uint8_t ControlParamSet_loudnessMaximiser[216] = {}; +uint8_t ControlParamSet_musicEnhancerRmsLimiter[216] = {}; +uint8_t ControlParamSet_voiceEnhancer[216] = {}; +#endif + +#endif /* EAP_PARAMETER_PRESETS_H_ */ diff --git a/src/include/sof/audio/nxp/eap/eap_lib_defines.h b/src/include/sof/audio/nxp/eap/eap_lib_defines.h new file mode 100644 index 000000000000..5ccee83c5605 --- /dev/null +++ b/src/include/sof/audio/nxp/eap/eap_lib_defines.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2025 NXP + */ + +#ifndef EAP_LIB_DEFINES_H_ +#define EAP_LIB_DEFINES_H_ + +#define LVCS_MS_COEFFS_SMALL 1 +#define ALGORITHM_CS 1 +#define ALGORITHM_DBE 1 +#define ALGORITHM_EQNB 1 +#define ALGORITHM_PR_EQNB 1 +#define ALGORITHM_LM 1 +#define ALGORITHM_TE 1 +#define ALGORITHM_TG 1 +#define ALGORITHM_AVL 1 +#define ALGORITHM_PSA 1 +#define ALGORITHM_VC 1 +#define ALGORITHM_LIMP 1 +#define ALGORITHM_LIMR 1 +#define ALGORITHM_XO 1 +#define NXP_PLATFORM_PROTECTION 0 + +#endif /* EAP_LIB_DEFINES_H_ */ diff --git a/src/include/sof/audio/pcm_converter.h b/src/include/sof/audio/pcm_converter.h index 67d4a1dbbb3f..3563a0d6557e 100644 --- a/src/include/sof/audio/pcm_converter.h +++ b/src/include/sof/audio/pcm_converter.h @@ -15,26 +15,26 @@ #define __SOF_AUDIO_PCM_CONVERTER_H__ #include <ipc/stream.h> -#include <config.h> +#include <ipc4/gateway.h> + +#include <sof/compiler_attributes.h> + #include <stddef.h> #include <stdint.h> struct audio_stream; -#define PCM_CONVERTER_GENERIC - #if __XCC__ - #include <xtensa/config/core-isa.h> - -#if XCHAL_HAVE_HIFI3 && CONFIG_FORMAT_CONVERT_HIFI3 - -#undef PCM_CONVERTER_GENERIC -#define PCM_CONVERTER_HIFI3 - #endif +#ifndef UNIT_TEST +#if __XCC__ && XCHAL_HAVE_HIFI3 && CONFIG_FORMAT_CONVERT_HIFI3 +#define PCM_CONVERTER_HIFI3 +#else +#define PCM_CONVERTER_GENERIC #endif +#endif /* UNIT_TEST */ /** * \brief PCM conversion function interface for data in circular buffer @@ -42,11 +42,25 @@ struct audio_stream; * \param ioffset offset to first sample in source stream * \param sink output buffer, write pointer is not modified * \param ooffset offset to first sample in sink stream + * \param source_samples number of samples to convert, for remapping -- number of source samples + * \param chmap channel map for remapping, ignored by non-remapping conversion func + * \return error code or number of processed samples (source samples in case of remapping). + */ +typedef int (*pcm_converter_func)(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t source_samples, uint32_t chmap); + +/* A channel map that does not perform any remapping. */ +#define DUMMY_CHMAP 0x76543210 + +/** + * \brief PCM conversion function interface for data in linear buffer + * \param psrc linear memory region with samples to process + * \param pdst linear memory region for output * \param samples number of samples to convert */ -typedef void (*pcm_converter_func)(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t samples); +typedef void (*pcm_converter_lin_func)(const void *psrc, void *pdst, + uint32_t samples); /** \brief PCM conversion functions map. */ struct pcm_func_map { @@ -59,7 +73,15 @@ struct pcm_func_map { extern const struct pcm_func_map pcm_func_map[]; /** \brief Number of conversion functions. */ -extern const uint32_t pcm_func_count; +extern const size_t pcm_func_count; + +#if CONFIG_PCM_REMAPPING_CONVERTERS +/** \brief Map of formats with dedicated remap with conversion functions. */ +extern const struct pcm_func_map pcm_remap_func_map[]; + +/** \brief Number of remap with conversion functions. */ +extern const size_t pcm_remap_func_count; +#endif /** * \brief Retrieves PCM conversion function. @@ -84,4 +106,98 @@ pcm_get_conversion_function(enum sof_ipc_frame in, return NULL; } +#if CONFIG_PCM_REMAPPING_CONVERTERS +/** + * \brief Retrieves PCM remap with conversion function. + * \param[in] in Source frame format. + * \param[in] out Sink frame format. + */ +static inline pcm_converter_func +pcm_get_remap_function(enum sof_ipc_frame in, enum sof_ipc_frame out) +{ + int i; + + for (i = 0; i < pcm_remap_func_count; i++) { + if (in != pcm_remap_func_map[i].source) + continue; + if (out != pcm_remap_func_map[i].sink) + continue; + + return pcm_remap_func_map[i].func; + } + + return NULL; +} +#endif + +/** \brief PCM conversion functions mapfor different size of valid bit and container. */ +struct pcm_func_vc_map { + enum sof_ipc_frame source; /**< source frame container format */ + enum sof_ipc_frame valid_src_bits; /**< source frame format */ + enum sof_ipc_frame sink; /**< sink frame container format */ + enum sof_ipc_frame valid_sink_bits; /**< sink frame format */ + + pcm_converter_func func; /**< PCM conversion function */ +}; + +/** \brief Map of formats with dedicated conversion functions. */ +extern const struct pcm_func_vc_map pcm_func_vc_map[]; + +/** \brief Number of conversion functions. */ +extern const size_t pcm_func_vc_count; + +/** + * \brief Retrieves PCM conversion function for different container size. + * \param in_bits is source container format. + * \param valid_in_bits is source valid sample format. + * \param out_bits is sink container format. + * \param valid_out_bits is sink valid sample format. + * \param type is gateway type + * \param dir is playback or capture + */ +static inline pcm_converter_func +pcm_get_conversion_vc_function(enum sof_ipc_frame in_bits, + enum sof_ipc_frame valid_in_bits, + enum sof_ipc_frame out_bits, + enum sof_ipc_frame valid_out_bits, + enum ipc4_gateway_type type, + enum ipc4_direction_type dir) +{ + uint32_t i; + + for (i = 0; i < pcm_func_vc_count; i++) { + if (in_bits != pcm_func_vc_map[i].source) + continue; + if (valid_in_bits != pcm_func_vc_map[i].valid_src_bits) + continue; + if (out_bits != pcm_func_vc_map[i].sink) + continue; + if (valid_out_bits != pcm_func_vc_map[i].valid_sink_bits) + continue; + + return pcm_func_vc_map[i].func; + } + + return NULL; +} + +/** + * \brief Convert data from circular buffer using converter working on linear + * memory space + * \param source buffer with samples to process, read pointer is not modified + * \param ioffset offset to first sample in source stream + * \param sink output buffer, write pointer is not modified + * \param ooffset offset to first sample in sink stream + * \param samples number of samples to convert + * \param converter core conversion function working on linear memory regions + * \return error code or number of processed samples + */ +int pcm_convert_as_linear(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, + uint32_t samples, pcm_converter_lin_func converter); + +/* Copy stream without conversion. chmap parameter is ignored. */ +int just_copy(const struct audio_stream *source, uint32_t ioffset, + struct audio_stream *sink, uint32_t ooffset, uint32_t samples, uint32_t chmap); + #endif /* __SOF_AUDIO_PCM_CONVERTER_H__ */ diff --git a/src/include/sof/audio/pipeline-trace.h b/src/include/sof/audio/pipeline-trace.h new file mode 100644 index 000000000000..d1f89583ad45 --- /dev/null +++ b/src/include/sof/audio/pipeline-trace.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_PIPELINE_TRACE_H__ +#define __SOF_AUDIO_PIPELINE_TRACE_H__ + +#include <rtos/sof.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> + +/* pipeline tracing */ +extern struct tr_ctx pipe_tr; + +#define trace_pipe_get_tr_ctx(pipe_p) (&(pipe_p)->tctx) +#define trace_pipe_get_id(pipe_p) ((pipe_p)->pipeline_id) +#define trace_pipe_get_subid(pipe_p) ((pipe_p)->comp_id) + +/* class (driver) level (no device object) tracing */ + +#define pipe_cl_err(__e, ...) \ + tr_err(&pipe_tr, __e, ##__VA_ARGS__) + +#define pipe_cl_warn(__e, ...) \ + tr_warn(&pipe_tr, __e, ##__VA_ARGS__) + +#define pipe_cl_info(__e, ...) \ + tr_info(&pipe_tr, __e, ##__VA_ARGS__) + +#define pipe_cl_dbg(__e, ...) \ + tr_dbg(&pipe_tr, __e, ##__VA_ARGS__) + +/* device tracing */ +#if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) + +#if CONFIG_IPC_MAJOR_4 +#define __PIPE_FMT "pipe:%u %#x " +#else +#define __PIPE_FMT "pipe:%u.%u " +#endif + +#define pipe_err(pipe_p, __e, ...) LOG_ERR(__PIPE_FMT __e, trace_pipe_get_id(pipe_p), \ + trace_pipe_get_subid(pipe_p), ##__VA_ARGS__) + +#define pipe_warn(pipe_p, __e, ...) LOG_WRN(__PIPE_FMT __e, trace_pipe_get_id(pipe_p), \ + trace_pipe_get_subid(pipe_p), ##__VA_ARGS__) + +#define pipe_info(pipe_p, __e, ...) LOG_INF(__PIPE_FMT __e, trace_pipe_get_id(pipe_p), \ + trace_pipe_get_subid(pipe_p), ##__VA_ARGS__) + +#define pipe_dbg(pipe_p, __e, ...) LOG_DBG(__PIPE_FMT __e, trace_pipe_get_id(pipe_p), \ + trace_pipe_get_subid(pipe_p), ##__VA_ARGS__) + +#else + +#define pipe_err(pipe_p, __e, ...) \ + trace_dev_err(trace_pipe_get_tr_ctx, trace_pipe_get_id, \ + trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) + +#define pipe_warn(pipe_p, __e, ...) \ + trace_dev_warn(trace_pipe_get_tr_ctx, trace_pipe_get_id, \ + trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) + +#define pipe_info(pipe_p, __e, ...) \ + trace_dev_info(trace_pipe_get_tr_ctx, trace_pipe_get_id, \ + trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) + +#define pipe_dbg(pipe_p, __e, ...) \ + trace_dev_dbg(trace_pipe_get_tr_ctx, trace_pipe_get_id, \ + trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) + +#endif /* #if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) */ + +#endif diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 179feaa011fd..913a569c208c 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -8,14 +8,13 @@ #ifndef __SOF_AUDIO_PIPELINE_H__ #define __SOF_AUDIO_PIPELINE_H__ -#include <sof/drivers/ipc.h> #include <sof/lib/cpu.h> #include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/stream.h> +#include <sof/list.h> +#include <rtos/task.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/audio/pipeline-trace.h> #include <ipc/topology.h> #include <user/trace.h> #include <errno.h> @@ -25,56 +24,22 @@ struct comp_buffer; struct comp_dev; struct ipc; -struct sof_ipc_buffer; -struct sof_ipc_pcm_params; -struct task; +struct ipc_msg; +struct k_heap; /* - * This flag disables firmware-side xrun recovery. - * It should remain enabled in the situation when the - * recovery is delegated to the outside of firmware. + * Pipeline status to stop execution of current path, but to keep the + * pipeline alive, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE */ -#define NO_XRUN_RECOVERY 1 - -/* pipeline tracing */ -#define trace_pipe_get_uid(pipe_p) (0) -#define trace_pipe_get_id(pipe_p) ((pipe_p)->ipc_pipe.pipeline_id) -#define trace_pipe_get_subid(pipe_p) ((pipe_p)->ipc_pipe.comp_id) - -/* class (driver) level (no device object) tracing */ - -#define pipe_cl_err(__e, ...) \ - trace_error(TRACE_CLASS_PIPE, __e, ##__VA_ARGS__) - -#define pipe_cl_warn(__e, ...) \ - trace_warn(TRACE_CLASS_PIPE, __e, ##__VA_ARGS__) - -#define pipe_cl_info(__e, ...) \ - trace_event(TRACE_CLASS_PIPE, __e, ##__VA_ARGS__) - -#define pipe_cl_dbg(__e, ...) \ - tracev_event(TRACE_CLASS_PIPE, __e, ##__VA_ARGS__) - -/* device tracing */ - -#define pipe_err(pipe_p, __e, ...) \ - trace_dev_err(TRACE_CLASS_PIPE, trace_pipe_get_uid, trace_pipe_get_id,\ - trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) - -#define pipe_warn(pipe_p, __e, ...) \ - trace_dev_warn(TRACE_CLASS_PIPE, trace_pipe_get_uid, trace_pipe_get_id,\ - trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) - -#define pipe_info(pipe_p, __e, ...) \ - trace_dev_info(TRACE_CLASS_PIPE, trace_pipe_get_uid, trace_pipe_get_id,\ - trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) - -#define pipe_dbg(pipe_p, __e, ...) \ - trace_dev_dbg(TRACE_CLASS_PIPE, trace_pipe_get_uid, trace_pipe_get_id,\ - trace_pipe_get_subid, pipe_p, __e, ##__VA_ARGS__) +#define PPL_STATUS_PATH_STOP 1 +/* + * Pipeline status to stop execution of current path, and to terminate the + * pipeline, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE + */ +#define PPL_STATUS_PATH_TERMINATE 2 -/* Pipeline status to stop execution of current path */ -#define PPL_STATUS_PATH_STOP 1 +/* Pipeline scheduled in another thread other than ipc thread */ +#define PPL_STATUS_SCHEDULED 2 /* pipeline connection directions */ #define PPL_CONN_DIR_COMP_TO_BUFFER 0 @@ -84,21 +49,33 @@ struct task; #define PPL_DIR_DOWNSTREAM 0 #define PPL_DIR_UPSTREAM 1 -#define PPL_POSN_OFFSETS \ - (MAILBOX_STREAM_SIZE / sizeof(struct sof_ipc_stream_posn)) - /* * Audio pipeline. */ struct pipeline { - struct sof_ipc_pipe_new ipc_pipe; + struct k_heap *heap; /**< heap used for allocating this pipeline */ + uint32_t comp_id; /**< component id for pipeline */ + uint32_t pipeline_id; /**< pipeline id */ + uint32_t sched_id; /**< Scheduling component id */ + uint32_t core; /**< core we run on */ + uint32_t period; /**< execution period in us*/ + uint32_t priority; /**< priority level 0 (low) to 10 (max) */ + uint32_t period_mips; /**< worst case instruction count per period */ + uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */ + uint32_t xrun_limit_usecs; /**< report xruns greater than limit */ + uint32_t time_domain; /**< scheduling time domain */ + uint32_t attributes; /**< pipeline attributes from IPC extension msg/ */ /* runtime status */ int32_t xrun_bytes; /* last xrun length */ uint32_t status; /* pipeline status */ + struct tr_ctx tctx; /* trace settings */ + bool expect_eos; /* pipeline is expecting end of stream */ /* scheduling */ struct task *pipe_task; /* pipeline processing task */ + struct pipeline *sched_next; /* pipeline scheduled after this */ + struct pipeline *sched_prev; /* pipeline scheduled before this */ /* component that drives scheduling in this pipe */ struct comp_dev *sched_comp; @@ -107,27 +84,121 @@ struct pipeline { /* sink component for this pipe */ struct comp_dev *sink_comp; + struct list_item list; /**< list in walk context */ + /* position update */ uint32_t posn_offset; /* position update array offset*/ struct ipc_msg *msg; + struct { + int cmd; + struct comp_dev *host; + unsigned int delay; /* period count */ + bool aborted; /* STOP or PAUSE failed, stay active */ + bool pending; /* trigger scheduled but not executed yet */ + } trigger; +}; + +struct pipeline_walk_context { + int (*comp_func)(struct comp_dev *cd, struct comp_buffer *buffer, + struct pipeline_walk_context *ctx, int dir); + void *comp_data; + void (*buff_func)(struct comp_buffer *buffer, void *data); + void *buff_data; + struct comp_buffer *incoming; + /**< pipelines to be scheduled after trigger walk */ + struct list_item pipelines; + /* + * If this flag is set, pipeline_for_each_comp() will skip all + * incompletely initialised components, i.e. those, whose .pipeline == + * NULL. Such components should not be skipped during initialisation + * and clean up, but they should be skipped during streaming. + */ + bool skip_incomplete; }; -/* static pipeline */ -extern struct pipeline *pipeline_static; +/* generic pipeline data used by pipeline_comp_* functions */ +struct pipeline_data { + struct comp_dev *start; + struct sof_ipc_pcm_params *params; + struct sof_ipc_stream_posn *posn; + struct pipeline *p; + int cmd; + uint32_t delay_ms; /* between PRE_{START,RELEASE} and {START,RELEASE} */ +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + int32_t kcps[CONFIG_CORE_COUNT]; /**< the max count of KCPS */ +#endif +}; -struct pipeline_posn { - bool posn_offset[PPL_POSN_OFFSETS]; /**< available offsets */ - spinlock_t lock; /**< lock mechanism */ +/** \brief Task type registered by pipelines. */ +struct pipeline_task { + struct task task; /**< parent structure */ + bool registrable; /**< should task be registered on irq */ + struct comp_dev *sched_comp; /**< pipeline scheduling component */ }; +struct ipc4_pipeline_ext_obj_mem_data; + +/** \brief For storing IPC payload data. */ +struct create_pipeline_params { + const struct ipc4_pipeline_ext_obj_mem_data *mem_data; +}; + +#define pipeline_task_get(t) container_of(t, struct pipeline_task, task) + +/* + * Pipeline Graph APIs + * + * These APIs are used to construct and bind pipeline graphs. They are also + * used to query pipeline fundamental configuration. + */ + /** - * \brief Retrieves pipeline position structure. - * \return Pointer to pipeline position structure. + * \brief Creates a new pipeline. + * \param[in] heap Heap to allocate the pipeline on, or NULL for default. + * \param[in] pipeline_id Pipeline ID number. + * \param[in] priority Pipeline scheduling priority. + * \param[in] comp_id Pipeline component ID number. + * \param[in] pparams Pipeline parameters from IPC payload, maybe NULL. + * \return New pipeline pointer or NULL. */ -static inline struct pipeline_posn *pipeline_posn_get(void) -{ - return sof_get()->pipeline_posn; -} +struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority, + uint32_t comp_id, struct create_pipeline_params *pparams); + +/** + * \brief Free's a pipeline. + * \param[in] p pipeline. + * \return 0 on success. + */ +int pipeline_free(struct pipeline *p); + +/** + * \brief Connect components in a pipeline. + * \param[in] comp connecting component. + * \param[in] buffer connecting buffer. + * \param[in] dir Connection direction. + * \return 0 on success. + */ +int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer, + int dir); + +/** + * \brief Creates a new pipeline. + * \param[in] comp connecting component. + * \param[in] buffer connecting buffer. + * \param[in] dir Connection direction. + */ +void pipeline_disconnect(struct comp_dev *comp, struct comp_buffer *buffer, + int dir); + +/** + * \brief Completes a pipeline. + * \param[in] p pipeline. + * \param[in] source Pipeline component device. + * \param[in] sink Pipeline component device. + * \return 0 on success. + */ +int pipeline_complete(struct pipeline *p, struct comp_dev *source, + struct comp_dev *sink); /** * \brief Initializes pipeline position structure. @@ -136,119 +207,248 @@ static inline struct pipeline_posn *pipeline_posn_get(void) void pipeline_posn_init(struct sof *sof); /** - * \brief Retrieves first free pipeline position offset. - * \param[in,out] posn_offset Pipeline position offset to be set. - * \return Error code. + * \brief Resets the pipeline and free runtime resources. + * \param[in] p pipeline. + * \param[in] host_cd Host DMA component device. + * \return 0 on success. */ -static inline int pipeline_posn_offset_get(uint32_t *posn_offset) -{ - struct pipeline_posn *pipeline_posn = pipeline_posn_get(); - int ret = -EINVAL; - uint32_t i; - - spin_lock(&pipeline_posn->lock); +int pipeline_reset(struct pipeline *p, struct comp_dev *host_cd); - for (i = 0; i < PPL_POSN_OFFSETS; ++i) { - if (!pipeline_posn->posn_offset[i]) { - *posn_offset = i * sizeof(struct sof_ipc_stream_posn); - pipeline_posn->posn_offset[i] = true; - ret = 0; - break; - } - } +/** + * \brief Walks the pipeline graph for each component. + * \param[in] current Current pipeline component. + * \param[in] ctx Pipeline graph walk context. + * \param[in] dir Walk direction. + * \return 0 on success. + */ +int pipeline_for_each_comp(struct comp_dev *current, + struct pipeline_walk_context *ctx, int dir); - platform_shared_commit(pipeline_posn, sizeof(*pipeline_posn)); +/** + * \brief Walks pipeline graph to find dai component. + * \param[in] pipeline_id is the start pipeline id. + * \param[in] dir is the direction of the traversal. + * \return dai component. + */ +struct comp_dev *pipeline_get_dai_comp(uint32_t pipeline_id, int dir); - spin_unlock(&pipeline_posn->lock); +#if CONFIG_IPC_MAJOR_4 +/** + * \brief Walks pipeline graph to find dai component and latency. + * \param[in] pipeline_id is the start pipeline id. + * \param[out] latency to dai. + * \return dai component. + */ +struct comp_dev *pipeline_get_dai_comp_latency(uint32_t pipeline_id, uint32_t *latency); +#endif - return ret; +/** + * Retrieves pipeline id from pipeline. + * @param p pipeline. + * @return pipeline id. + */ +static inline uint32_t pipeline_id(struct pipeline *p) +{ + return p->pipeline_id; } +/* + * Pipeline configuration APIs + * + * These APIs are used to configure the runtime parameters of a pipeline. + */ + /** - * \brief Frees pipeline position offset. - * \param[in] posn_offset Pipeline position offset to be freed. + * \brief Creates a new pipeline. + * \param[in] p pipeline. + * \param[in] cd Pipeline component device. + * \param[in] params Pipeline parameters. + * \return 0 on success. */ -static inline void pipeline_posn_offset_put(uint32_t posn_offset) -{ - struct pipeline_posn *pipeline_posn = pipeline_posn_get(); - int i = posn_offset / sizeof(struct sof_ipc_stream_posn); +int pipeline_params(struct pipeline *p, struct comp_dev *cd, + struct sof_ipc_pcm_params *params); - spin_lock(&pipeline_posn->lock); +/** + * \brief Prepares pipeline for processing. + * \param[in] p pipeline. + * \param[in,out] cd Pipeline component device. + * \return 0 on success. + */ +int pipeline_prepare(struct pipeline *p, struct comp_dev *cd); - pipeline_posn->posn_offset[i] = false; +/* + * Pipeline stream APIs + * + * These APIs are used to control pipeline processing work. + */ - platform_shared_commit(pipeline_posn, sizeof(*pipeline_posn)); +/** + * \brief Trigger pipeline - IPC context + * \param[in] p pipeline. + * \param[in] host Host DMA component. + * \param[in] cmd Pipeline trigger command. + * \return 0 on success. + */ +int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd); - spin_unlock(&pipeline_posn->lock); -} +/** + * \brief Trigger pipeline - either IPC or pipeline task context + * \param[in] p pipeline. + * \param[in] host Host DMA component. + * \param[in] cmd Pipeline trigger command. + * \return 0 on success. + */ +int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd); + +/** + * \brief Copy data along a pipeline. + * \param[in] p pipeline. + * \return 0 on success. + */ +int pipeline_copy(struct pipeline *p); + +/** + * \brief Get time pipeline timestamps from host to dai. + * \param[in] p pipeline. + * \param[in] host_dev Host DMA component. + * \param[in,out] posn Pipeline stream position. + */ +void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev, + struct sof_ipc_stream_posn *posn); + +/* + * Pipeline scheduling APIs + * + * These APIs are used to schedule pipeline processing work. + */ -/* checks if two pipelines have the same scheduling component */ +/** + * \brief Checks if two pipelines have the same scheduling component. + * \param[in] current This pipeline. + * \param[in] previous Other pipeline. + * \return true if both pipelines are scheduled together. + */ static inline bool pipeline_is_same_sched_comp(struct pipeline *current, struct pipeline *previous) { return current->sched_comp == previous->sched_comp; } -/* checks if pipeline is scheduled with timer */ +/** + * \brief Is pipeline is scheduled with timer. + * \param[in] p pipeline. + * \return true if pipeline uses timer based scheduling. + */ static inline bool pipeline_is_timer_driven(struct pipeline *p) { - return p->ipc_pipe.time_domain == SOF_TIME_DOMAIN_TIMER; + return p->time_domain == SOF_TIME_DOMAIN_TIMER; } -/* checks if pipeline is scheduled on this core */ +/** + * \brief Is pipeline is scheduled on this core. + * \param[in] p pipeline. + * \return true if pipeline core ID == current core ID. + */ static inline bool pipeline_is_this_cpu(struct pipeline *p) { - return p->ipc_pipe.core == cpu_get_id(); + return p->core == cpu_get_id(); } -/* pipeline creation and destruction */ -struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc, - struct comp_dev *cd); -int pipeline_free(struct pipeline *p); - -/* pipeline buffer creation and destruction */ -struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc); -void buffer_free(struct comp_buffer *buffer); - -/* insert component in pipeline */ -int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer, - int dir); +/** + * \brief Init an LL task for a pipeline. + * \param[in] p pipeline. + * \return 0 on success. + */ +int pipeline_comp_ll_task_init(struct pipeline *p); -/* complete the pipeline */ -int pipeline_complete(struct pipeline *p, struct comp_dev *source, - struct comp_dev *sink); +/** + * \brief Init a DP task for a component + * \param[in] comp a component the task is created for + * \return 0 on success. + */ +int pipeline_comp_dp_task_init(struct comp_dev *comp); -/* pipeline parameters */ -int pipeline_params(struct pipeline *p, struct comp_dev *cd, - struct sof_ipc_pcm_params *params); +/** + * \brief Schedule a pipeline copy to run after a delay + * \param[in] p pipeline. + * \param[in] start Pipeline start time in microseconds. + */ +void pipeline_schedule_copy(struct pipeline *p, uint64_t start); -/* prepare the pipeline for usage */ -int pipeline_prepare(struct pipeline *p, struct comp_dev *cd); +/** + * \brief Trigger pipeline's scheduling component. + * \param[in] p pipeline. + * \param[in,out] comp Pipeline component device. + * \param[in] ctx Pipeline graph walk context. + */ +void pipeline_comp_trigger_sched_comp(struct pipeline *p, + struct comp_dev *comp, + struct pipeline_walk_context *ctx); -/* reset the pipeline and free resources */ -int pipeline_reset(struct pipeline *p, struct comp_dev *host_cd); +/** + * \brief Schedule all triggered pipelines. + * \param[in] ctx Pipeline graph walk context. + * \param[in] cmd Trigger command. + */ +void pipeline_schedule_triggered(struct pipeline_walk_context *ctx, + int cmd); -/* perform selected cache command on pipeline */ -void pipeline_cache(struct pipeline *p, struct comp_dev *dev, int cmd); +/** + * \brief Configure pipeline scheduling. + * \param[in] p pipeline. + * \param[in] sched_id Scheduling component ID. + * \param[in] core DSP core pipeline runs on. + * \param[in] period Pipeline scheduling period in us. + * \param[in] period_mips Pipeline worst case MCPS per period. + * \param[in] frames_per_sched Pipeline frames processed per schedule. + * \param[in] time_domain Pipeline scheduling time domain. + */ +void pipeline_schedule_config(struct pipeline *p, uint32_t sched_id, + uint32_t core, uint32_t period, + uint32_t period_mips, uint32_t frames_per_sched, + uint32_t time_domain); -/* trigger pipeline - atomic */ -int pipeline_trigger(struct pipeline *p, struct comp_dev *host_cd, int cmd); +/* + * Pipeline error handling APIs + * + * These APIs are used to handle, report and recover from pipeline errors. + */ -/* static pipeline creation */ -int init_static_pipeline(struct ipc *ipc); +/** + * \brief Recover the pipeline from a XRUN condition. + * \param[in] p pipeline. + * \return 0 on success. + */ +int pipeline_xrun_recover(struct pipeline *p); -/* pipeline creation */ -int init_pipeline(void); +/** + * \brief Perform xrun recovery. + * \param[in] p pipeline. + * \param[in] cmd Trigger command. + * \return 0 on success. + */ +int pipeline_xrun_handle_trigger(struct pipeline *p, int cmd); -/* schedule a copy operation for this pipeline */ -void pipeline_schedule_copy(struct pipeline *p, uint64_t start); -void pipeline_schedule_cancel(struct pipeline *p); +/** + * \brief notify host that we have XRUN. + * \param[in] p pipeline. + * \param[in] dev Pipeline component device. + * \param[in] bytes Number of bytes we have over or under run. + */ +void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes); -/* get time pipeline timestamps from host to dai */ -void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev, - struct sof_ipc_stream_posn *posn); +/** + * \brief Set tolerance for pipeline xrun handling. + * \param[in] p pipeline. + * \param[in] xrun_limit_usecs Limit in micro secs that pipeline will tolerate. + */ +int pipeline_xrun_set_limit(struct pipeline *p, uint32_t xrun_limit_usecs); -/* notify host that we have XRUN */ -void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes); +/** + * \brief Sends an ipc notification that an error occurred in the module's processing function. + * \param[in] component The component in which the error occurred. + * \param[in] error_code Error code. + */ +void pipeline_comp_copy_error_notify(const struct comp_dev *component, int error_code); #endif /* __SOF_AUDIO_PIPELINE_H__ */ diff --git a/src/include/sof/audio/ring_buffer.h b/src/include/sof/audio/ring_buffer.h new file mode 100644 index 000000000000..1ef712a56743 --- /dev/null +++ b/src/include/sof/audio/ring_buffer.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_RING_BUFFER_H__ +#define __SOF_RING_BUFFER_H__ + +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> +#include <sof/audio/audio_stream.h> +#include <sof/audio/audio_buffer.h> +#include <rtos/bit.h> +#include <sof/common.h> +#include <ipc/topology.h> +#include <sof/coherent.h> + +/** + * ring_buffer is a lockless async circular buffer + * providing safe consumer/producer cached operations cross cores that may be write/read + * at any time + * + * prerequisites: + * 1) incoming and outgoing data rate MUST be the same + * 2) Both data consumer and data producer declare max chunk sizes they want to use (IBS/OBS) + * + * required Buffer size is 2*MAX(IBS,OBS) to allow free read/write in various data chunk sizes + * and execution periods (of course in/out data rates must be same) + * example: + * Consumer reads 5bytes each 3 cycles (IBS = 5) + * producer writes 3bytes every 5 cycles (OBS = 3) + * - cycle0 buffer empty, producer starting processing, consumer must wait + * - cycle3 produce 3 bytes (buf occupation = 3) + * - cycle6 produce 3 bytes (buf occupation = 6), consumer becomes ready + * in consumer thread will start now - asyn to producer cycles + * in this example assuming it consumes data in next cycle + * - cycle7 consume 5 bytes, (buf occupation = 1) + * - cycle9 produce 3 bytes (buf occupation = 4) + * - cycle12 (producer goes first) produce 3 bytes (buf occupation = 7) + * consume 5 bytes (buf occupation = 2) + * - cycle15 produce 3 bytes (buf occupation = 5) + * consumer has enough data, but is busy processing prev data + * - cycle15 consume 5 bytes (buf occupation = 0) + * + * ===> max buf occupation = 7 + * + * The worst case is when IBS=OBS and equal periods of consumer/producer + * the buffer must be 2*MAX(IBS,OBS) as we do not know who goes first - consumer or producer, + * especially when both are located on separate cores and EDF scheduling is used + * + * Consumer reads 5 bytes every cycle (IBS = 5) + * producer writes 5 bytes every cycle (OBS = 5) + * - cycle0 consumer goes first - must wait (buf occupation = 0) + * producer produce 5 bytes (buf occupation = 5) + * - cycle1 producer goes first - produce 5 bytes (buf occupation = 10) + * consumer consumes 5 bytes (buf occupation = 5) + * ===> max buf occupation = 10 + * + * + * The queue may work in 2 modes + * 1) local mode + * in case both receiver and sender are located on the same core and cache coherency + * does not matter. ring_buffer structure is located in cached memory + * + * 2) shared mode + * In this case we need to writeback cache when new data arrive and invalidate cache on + * secondary core. ring_buffer structure is located in shared memory + * + * + * ring_buffer is a lockless consumer/producer safe buffer. It is achieved by having only 2 shared + * variables: + * _write_offset - can be modified by data producer only + * _read_offset - can be modified by data consumer only + * + * as 32 bit operations are atomic, it is multi-thread and multi-core save + * + * There some explanation needed how free_space and available_data are calculated + * + * number of avail data in circular buffer may be calculated as: + * data_avail = _write_offset - _read_offset + * and check for wrap around + * if (data_avail < 0) data_avail = buffer_size - data_avail + * + * The problem is when _write_offset == _read_offset, + * !!! it may mean either that the buffer is empty or the buffer is completely filled !!! + * + * To solve the above issue having only 2 variables mentioned before: + * - allow both offsets to point from 0 to DOUBLE buffer_size + * - when calculating pointers to data, use: data_bufer[offset % buffer_size] + * - use double buffer size in wrap around check when calculating available data + * + * And now: + * - _write_offset == _read_offset + * always means "buffer empty" + * - _write_offset == _read_offset + buffer_size + * always means "buffer full" + */ + +struct comp_dev; +struct ring_buffer; +struct sof_audio_stream_params; + +/* the ring_buffer structure */ +struct ring_buffer { + /* public: read only */ + struct sof_audio_buffer audio_buffer; + + size_t data_buffer_size; + + uint8_t __sparse_cache *_data_buffer; + size_t _write_offset; /* private: to be modified by data producer using API */ + size_t _read_offset; /* private: to be modified by data consumer using API */ +}; + +/** + * + * @param dev pointer to the DP module device structure + * @param min_available minimum data available in queue required by the module using + * ring_buffer's source api + * @param min_free_space minimum buffer space in queue required by the module using + * ring_buffer's sink api + * @param is_shared indicates if the buffer will be shared between cores + * @param id a stream ID, accessible later by sink_get_id/source_get_id + * + */ +struct ring_buffer *ring_buffer_create(struct comp_dev *dev, size_t min_available, + size_t min_free_space, bool is_shared, + uint32_t id); + +#endif /* __SOF_RING_BUFFER_H__ */ diff --git a/src/include/sof/audio/rtnr/rtklib/include/README.txt b/src/include/sof/audio/rtnr/rtklib/include/README.txt new file mode 100644 index 000000000000..eaa308a39357 --- /dev/null +++ b/src/include/sof/audio/rtnr/rtklib/include/README.txt @@ -0,0 +1 @@ +Put RTK_MA_API.h in this directory. diff --git a/src/include/sof/audio/rtnr/rtklib/include/RTK_MA_API.h b/src/include/sof/audio/rtnr/rtklib/include/RTK_MA_API.h new file mode 100644 index 000000000000..312378cdd6fd --- /dev/null +++ b/src/include/sof/audio/rtnr/rtklib/include/RTK_MA_API.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Realtek Corporation. All rights reserved. + * + * Author: Antz Cheng <antz0525@realtek.com> + */ +#ifndef _RTK_MA_API_H_ +#define _RTK_MA_API_H_ + +#include <sof/audio/rtnr/rtnr.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void RTKMA_API_S16_Default(void *Context, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames, + _Bool ref_active, int in_idx, int ref_idx, + int ref_32bits, int ref_shift); +void RTKMA_API_S24_Default(void *Context, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames, + _Bool ref_active, int in_idx, int ref_idx, + int ref_32bits, int ref_shift); +void RTKMA_API_S32_Default(void *Context, struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, int frames, + _Bool ref_active, int in_idx, int ref_idx, + int ref_32bits, int ref_shift); + +void RTKMA_API_First_Copy(void *Context, int SampleRate, int MicCh); + +void RTKMA_API_Bypass(void *Context, _Bool Bypass); + +void RTKMA_API_Process(void *Context, _Bool has_ref, int SampleRate, int MicCh); + +void RTKMA_API_Prepare(void *Context); + +void *RTKMA_API_Context_Create(int sample_rate); + +void RTKMA_API_Context_Free(void *Context); + +void RTKMA_API_Set_Default_Parameter(void *Context); + +int RTKMA_API_Parameter_Size(void *Context, unsigned int IDs); + +int RTKMA_API_Set(void *Context, const void *pParameters, int size, unsigned int IDs); + +int RTKMA_API_Get(void *Context, void *pParameters, int size, unsigned int IDs); + +int RTKMA_API_Set_Preset_Data(void *Context, unsigned int *data, + unsigned int msg_index, unsigned int num_elms, + unsigned int elems_remaining); + +int RTKMA_API_Set_Model_Data(void *Context, unsigned int *data, + unsigned int msg_index, unsigned int num_elms, + unsigned int elems_remaining); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTK_MA_API_H_ */ + diff --git a/src/include/sof/audio/rtnr/rtnr.h b/src/include/sof/audio/rtnr/rtnr.h new file mode 100644 index 000000000000..19f9fb403e18 --- /dev/null +++ b/src/include/sof/audio/rtnr/rtnr.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. + * + * Author: Ming Jen Tai <mingjen_tai@realtek.com> + */ + +#ifndef __SOF_AUDIO_RTNR_RTNR_H__ +#define __SOF_AUDIO_RTNR_RTNR_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component.h> +#include <sof/platform.h> +#include <ipc/stream.h> +#include <user/rtnr.h> +#include <stdint.h> +#include <stdbool.h> + +/** + * \brief Type definition for the RTNR processing function + * + */ + +/* for RTNR internal use */ +struct audio_stream_rtnr { + /* runtime data */ + uint32_t size; /**< Runtime buffer size in bytes (period multiple) */ + uint32_t avail; /**< Available bytes for reading */ + uint32_t free; /**< Free bytes for writing */ + void *w_ptr; /**< Buffer write pointer */ + void *r_ptr; /**< Buffer read position */ + void *addr; /**< Buffer base address */ + void *end_addr; /**< Buffer end address */ + + /* runtime stream params */ + enum sof_ipc_frame frame_fmt; /**< Sample data format */ + + uint32_t rate; /**< Number of data frames per second [Hz] */ + uint16_t channels; /**< Number of samples in each frame */ + + bool overrun_permitted; /**< indicates whether overrun is permitted */ + bool underrun_permitted; /**< indicates whether underrun is permitted */ +}; + +typedef void (*rtnr_func)(struct processing_module *mod, + struct audio_stream_rtnr **sources, + struct audio_stream_rtnr *sink, + int frames); + +#define RTNR_MAX_SOURCES 1 /* Microphone stream */ + +/* RTNR component private data */ +struct comp_data { + struct comp_data_blob_handler *model_handler; + struct sof_rtnr_config config; /**< config */ + enum sof_ipc_frame source_format; + enum sof_ipc_frame sink_format; + enum sof_ipc_frame ref_format; + int source_channel; + int reference_channel; + uint32_t sink_rate; + uint32_t source_rate; + bool process_enable; + uint32_t process_sample_rate; + int ref_shift; + bool ref_32bits; + bool ref_active; + rtnr_func rtnr_func; /** Processing function */ + void *rtk_agl; + struct audio_stream_rtnr sources_stream[RTNR_MAX_SOURCES]; + struct audio_stream_rtnr sink_stream; + bool reconfigure; +}; + +/* Called by the processing library for debugging purpose */ +void rtnr_printf(int a, int b, int c, int d, int e); + +/* + * Called by the processing library to redirect memory allocation/deallocation to + * sof memory APIs + */ +void *rtk_rballoc(unsigned int flags, unsigned int caps, unsigned int bytes); +void rtk_rfree(void *ptr); + +/* For stub processing functions */ +void rtnr_copy_from_sof_stream(struct audio_stream_rtnr *dst, struct audio_stream *src); +void rtnr_copy_to_sof_stream(struct audio_stream *dst, struct audio_stream_rtnr *src); + +#endif /* __SOF_AUDIO_RTNR_RTNR_H__ */ diff --git a/src/include/sof/audio/selector.h b/src/include/sof/audio/selector.h index 04d71fbdd588..e977a47af9a9 100644 --- a/src/include/sof/audio/selector.h +++ b/src/include/sof/audio/selector.h @@ -14,8 +14,12 @@ #ifndef __SOF_AUDIO_SELECTOR_H__ #define __SOF_AUDIO_SELECTOR_H__ +#include <sof/audio/module_adapter/module/generic.h> #include <sof/trace/trace.h> #include <ipc/stream.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/base-config.h> +#endif #include <user/selector.h> #include <user/trace.h> #include <stdint.h> @@ -23,6 +27,10 @@ struct comp_buffer; struct comp_dev; +/** \brief Default mix gain. */ +#define SEL_COEF_ONE_Q10 1024 /* int16(1 * 2^10) */ + +#if CONFIG_IPC_MAJOR_3 /** \brief Supported channel count on input. */ #define SEL_SOURCE_2CH 2 #define SEL_SOURCE_4CH 4 @@ -31,19 +39,97 @@ struct comp_dev; #define SEL_SINK_1CH 1 #define SEL_SINK_2CH 2 #define SEL_SINK_4CH 4 +#else +/** \brief Maximum supported channel count on input. */ +#define SEL_SOURCE_CHANNELS_MAX 8 + +/** \brief Maximum supported channel count on output. */ +#define SEL_SINK_CHANNELS_MAX 8 + +/** \brief Maximum number of configurations in the blob received with set_config() */ +#define SEL_MAX_NUM_CONFIGS 8 +#define SEL_NUM_IN_PIN_FMTS 1 +#define SEL_NUM_OUT_PIN_FMTS 1 + +#endif + +#if CONFIG_IPC_MAJOR_4 /** \brief selector processing function interface */ +typedef void (*sel_func)(struct processing_module *mod, struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames); + +/** \brief IPC4 configuration IDs for selector. */ +enum ipc4_selector_config_id { + IPC4_SELECTOR_COEFFS_CONFIG_ID = 0, /**< Mixing coefficients config ID */ +}; + +/** \brief IPC4 mixing coefficients configuration. */ +struct ipc4_selector_coeffs_config { + uint8_t source_channels_count; /**< Used when multiple profiles are packed into one blob. */ + uint8_t sink_channels_count; /**< Used when multiple profiles are packed into one blob. */ + uint8_t source_channel_config; /**< Used when multiple profiles are packed into one blob. */ + uint8_t sink_channel_config; /**< Used when multiple profiles are packed into one blob. */ + + /** Mixing coefficients in Q10 fixed point format */ + int16_t coeffs[SEL_SINK_CHANNELS_MAX][SEL_SOURCE_CHANNELS_MAX]; +}; + +enum ipc4_selector_init_payload_fmt { + IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT, + IPC4_SEL_INIT_PAYLOAD_BASE_WITH_OUT_FMT, +}; + +struct sof_selector_ipc4_pin_config { + struct ipc4_input_pin_format in_pin; + struct ipc4_output_pin_format out_pin; +}; + +/* + * Base module config is not added in this structure because it is handled + * by module adapter. + */ +struct sof_selector_ipc4_config { + /* + * Windows will send the base_config + output_format payload, but Linux will + * send the base_config + base_config_ext payload, use a union to make the + * selector module be compatible for both OSes. + */ + union { + struct sof_selector_ipc4_pin_config pin_cfg; + struct ipc4_audio_format output_format; + }; + enum ipc4_selector_init_payload_fmt init_payload_fmt; +}; + +struct sof_selector_avs_ipc4_config { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_audio_format output_format; +}; + +#else typedef void (*sel_func)(struct comp_dev *dev, struct audio_stream *sink, const struct audio_stream *source, uint32_t frames); +#endif /** \brief Selector component private data. */ struct comp_data { +#if CONFIG_IPC_MAJOR_4 + struct sof_selector_ipc4_config sel_ipc4_cfg; + struct ipc4_selector_coeffs_config coeffs_config; + struct ipc4_selector_coeffs_config *multi_coeffs_config; + size_t multi_coeffs_config_size; +#endif + uint32_t source_period_bytes; /**< source number of period bytes */ uint32_t sink_period_bytes; /**< sink number of period bytes */ enum sof_ipc_frame source_format; /**< source frame format */ enum sof_ipc_frame sink_format; /**< sink frame format */ struct sof_sel_config config; /**< component configuration data */ sel_func sel_func; /**< channel selector processing function */ + int num_configs; /**< Number of coefficients sets in configuration blob. */ + bool passthrough; /**< Use a passthrough copy function when no up/down mix. */ + bool new_config; /**< True if new configuration has been received */ }; /** \brief Selector processing functions map. */ @@ -56,7 +142,17 @@ struct comp_func_map { /** \brief Map of formats with dedicated processing functions. */ extern const struct comp_func_map func_map[]; +#if CONFIG_IPC_MAJOR_4 +/** + * \brief Retrieves selector processing function. + * \param[in,out] mod Selector module adapter. + */ +sel_func sel_get_processing_function(struct processing_module *mod); +#ifdef UNIT_TEST +void sys_comp_module_selector_interface_init(void); +#endif +#else /** * \brief Retrieves selector processing function. * \param[in,out] dev Selector base component device. @@ -66,5 +162,6 @@ sel_func sel_get_processing_function(struct comp_dev *dev); #ifdef UNIT_TEST void sys_comp_selector_init(void); #endif +#endif #endif /* __SOF_AUDIO_SELECTOR_H__ */ diff --git a/src/include/sof/audio/sink_api.h b/src/include/sof/audio/sink_api.h new file mode 100644 index 000000000000..11ffc6e08c3d --- /dev/null +++ b/src/include/sof/audio/sink_api.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_SINK_API_H__ +#define __SOF_SINK_API_H__ + +#include <module/audio/sink_api.h> + +/** + * Init of the API, must be called before any operation + * + * @param sink pointer to the structure + * @param ops pointer to API operations + * @param audio_stream_params pointer to structure with audio parameters + * note that the audio_stream_params must be accessible by the caller core + * the implementation must ensure coherent access to the parameteres + * in case of i.e. cross core shared queue, it must be located in non-cached memory + */ +void sink_init(struct sof_sink *sink, const struct sink_ops *ops, + struct sof_audio_stream_params *audio_stream_params); + +/** + * Get total number of bytes processed by the sink (meaning - committed by sink_commit_buffer()) + * + * @param sink a handler to sink + * @return total number of processed data + */ +size_t sink_get_num_of_processed_bytes(struct sof_sink *sink); + +/** + * sets counter of total number of bytes processed to zero + */ +void sink_reset_num_of_processed_bytes(struct sof_sink *sink); + +/** set of functions for retrieve audio parameters */ +bool sink_get_overrun(struct sof_sink *sink); + +/** set of functions for setting audio parameters */ +void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space); + +#endif /* __SOF_SINK_API_H__ */ diff --git a/src/include/sof/audio/sink_source_utils.h b/src/include/sof/audio/sink_source_utils.h new file mode 100644 index 000000000000..818f29444c22 --- /dev/null +++ b/src/include/sof/audio/sink_source_utils.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef SINK_SOURCE_UTILS_H +#define SINK_SOURCE_UTILS_H + +#include <sof/audio/sink_api.h> +#include <sof/audio/source_api.h> + +/** + * copy bytes from source to sink + * + * @param source the data source + * @param sink the data target + * @param free if true, data from source will be freed + * if false, data will remain in the source + * @param size number of bytes to be copied + */ +int source_to_sink_copy(struct sof_source *source, + struct sof_sink *sink, bool free, size_t size); + +/** + * fill sink with silence (zeros) + * + * @param sink the target to be filled with silence + * @param size number of bytes to be filled + */ +int sink_fill_with_silence(struct sof_sink *sink, size_t size); + +/** + * drop data from source + * + * @param source the source of data to be dropped + * @param size number of bytes to be dropped + */ +int source_drop_data(struct sof_source *source, size_t size); + +#endif /* SINK_SOURCE_UTILS_H */ diff --git a/src/include/sof/audio/smart_amp/smart_amp.h b/src/include/sof/audio/smart_amp/smart_amp.h new file mode 100644 index 000000000000..e6007bf28729 --- /dev/null +++ b/src/include/sof/audio/smart_amp/smart_amp.h @@ -0,0 +1,323 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Maxim Integrated All rights reserved. + * + * Author: Ryan Lee <ryans.lee@maximintegrated.com> + * + * Copyright(c) 2023 Google LLC. + * + * Author: Pin-chih Lin <johnylin@google.com> + */ + +#ifndef __SOF_AUDIO_DSM_H__ +#define __SOF_AUDIO_DSM_H__ + +#include <sof/platform.h> +#include <sof/audio/component.h> + +/* Smart Amplifier component is a two-layer structured design, i.e. generic + * layer and inner model layer. The latter can have various implementations + * respectively for Amplifier solution suppliers, while the former is the common + * part of Smart Amp process adaptable for all solutions. + * + * In structural aspect, one can regard generic layer as the glue code that + * wraps inner model in a SOF component. Ops are defined for interaction between + * two layers. Inner model is the solution-specific modular code, which may have + * static libraries linked as needed. The structure is figured below: + * + * SRC(FF) SINK(OUT) +-SRC(FB) bytectl + * +- SMART_AMP |^ comp ops | ^ | ^| + * | +------------------v|-------------v---------|------v-----------|v---------+ + * | | Generic Layer (chan remap/fmt conv) || | + * | | (memory mgr)--+------> :::::::::BUFFERS::::::::::::: |+> CONFIG | + * | +------------------|-|^-----------|---------^------|-----------^|---------+ + * | | || mod ops | | | || + * | +------------------v-v|-----------v---------|------v-----------|v---------+ + * | | Inner Model :::::::::::::::::::::BUFFERS::::::::::::::::::::::: | + * | | (solution-specific impl/wrapper) |+> MODEL | + * | +------------------------------|^------------------------------^----------+ + * +--- v| lib ops | CALDATA + * Static Libs (as needed) ----------+ + * Note: + * - FF(Feed-Forward): un-processed playback frame source + * - FB(Feedback): feedback reference frame source (from the capture pipeline) + * + * As illustrated above, generic layer handles the cross-communication for inner + * model and SOF pipeline flow, as well as the smart-amp common tasks including: + * 1. Channel remapping for input/output frames + * 2. Frame format conversion for input/output frames. It allows inner model to + * work with different format from SOF audio stream. + * (Now it only allows the bitdepth of inner model format >= SOF stream, + * e.g. inner model: S32_LE, SOF stream: S16_LE) + * 3. Full-management of runtime memory. That is, dynamic memory buffers either + * required by generic layer or inner model will be allocated/owned/released + * by generic layer. + * More details are stated in the comment of each struct/function later. + */ + +/* Maximum number of channels for algorithm in */ +#define SMART_AMP_FF_MAX_CH_NUM 2 +/* Maximum number of channels for algorithm out */ +#define SMART_AMP_FF_OUT_MAX_CH_NUM 4 +/* Maximum number of channels for feedback */ +#define SMART_AMP_FB_MAX_CH_NUM 4 + +#define SMART_AMP_FRM_SZ 48 /* frames per 1ms */ +#define SMART_AMP_FF_BUF_SZ (SMART_AMP_FRM_SZ * SMART_AMP_FF_MAX_CH_NUM) +#define SMART_AMP_FB_BUF_SZ (SMART_AMP_FRM_SZ * SMART_AMP_FB_MAX_CH_NUM) + +#define SMART_AMP_FF_BUF_DB_SZ\ + (SMART_AMP_FF_BUF_SZ * SMART_AMP_FF_MAX_CH_NUM) +#define SMART_AMP_FB_BUF_DB_SZ\ + (SMART_AMP_FB_BUF_SZ * SMART_AMP_FB_MAX_CH_NUM) + +struct inner_model_ops; + +/* The common base for inner model data structs. Inner model should declare its + * model data struct while putting this base as the leading member of struct, e.g. + * struct solution_foo_mod_data { + * struct smart_amp_mod_data_base base; + * uint32_t foo_version; + * struct foo_parameter_set; + * ... + * }; + * + * Then implement mod_data_create() in its own C file, e.g. + * struct smart_amp_mod_data_base *mod_data_create(const struct comp_dev *dev) + * { + * struct solution_foo_mod_data *foo; + * foo = rzalloc(SOF_MEM_FLAG_USER, sizeof(*foo)); + * assert(foo); + * foo->base.dev = dev; + * foo->base.mod_ops = foo_ops; // declared somewhere as static const + * ... + * return &foo->base; + * } + */ +struct smart_amp_mod_data_base { + const struct comp_dev *dev; /* for logger tracing use only */ + const struct inner_model_ops *mod_ops; +}; + +/* The struct of memory buffer managed by generic layer. */ +struct smart_amp_buf { + void *data; + uint32_t size; +}; + +/* For memory allocation, generic layer plays the active role that queries the + * required memory size for inner model (then allocate and assign back) in + * some specific moments, i.e. once before and after model initialized. Inner + * model should consider buffers located and allocated onto 3 memory blocks in + * terms of usage: + * PRIVATE - allocated before model init - for libraries internal usage + * FRAME - allocated after model init - for audio frame buffer usage + * PARAM - allocated after model init - for parameter blob usage + */ +enum smart_amp_mod_memblk { + MOD_MEMBLK_PRIVATE = 0, + MOD_MEMBLK_FRAME, + MOD_MEMBLK_PARAM, + MOD_MEMBLK_MAX +}; + +/* The intermediate audio data buffer in generic layer. */ +struct smart_amp_mod_stream { + struct smart_amp_buf buf; + uint32_t channels; + uint16_t frame_fmt; + union { + uint32_t consumed; /* for source (in frames) */ + uint32_t produced; /* for sink (in frames) */ + }; +}; + +/****************************************************************************** + * Generic functions: * + * The implementation is placed in smart_amp_generic.c * + ******************************************************************************/ + +typedef void (*smart_amp_src_func)(struct smart_amp_mod_stream *src_mod, + uint32_t frames, + const struct audio_stream __sparse_cache *src, + const int8_t *chan_map); + +typedef void (*smart_amp_sink_func)(const struct smart_amp_mod_stream *sink_mod, + uint32_t frames, + const struct audio_stream __sparse_cache *sink); + +struct smart_amp_func_map { + uint16_t comp_fmt; + uint16_t mod_fmt; + smart_amp_src_func src_func; + smart_amp_sink_func sink_func; +}; + +extern const struct smart_amp_func_map src_sink_func_map[]; + +smart_amp_src_func smart_amp_get_src_func(uint16_t comp_fmt, uint16_t mod_fmt); +smart_amp_sink_func smart_amp_get_sink_func(uint16_t comp_fmt, uint16_t mod_fmt); + +/****************************************************************************** + * Inner model operations (mod ops): * + * Model implementations are mutual exclusive (separated by Kconfig). It * + * must be only one solution applicable per build. The solution-specific * + * implementation is placed in its own C file smart_amp_${SOLUTION}.c * + ******************************************************************************/ + +/** + * Creates the self-declared model data struct. + * Refer to "struct smart_amp_mod_data_base" for details of declaration. + * Args: + * dev - the comp_dev object for logger tracing use only. + * Returns: + * The pointer of "smart_amp_mod_data_base" which is the leading member in + * the created model data struct. + */ +struct smart_amp_mod_data_base *mod_data_create(const struct comp_dev *dev); + +/* All ops are mandatory. */ +struct inner_model_ops { + /** + * Initializes model. + * It will be called on comp_ops.create() by generic layer. + * Args: + * mod - the pointer of model data struct object. + * Returns: + * 0 or negative error code. + */ + int (*init)(struct smart_amp_mod_data_base *mod); + + /** + * Returns the required bytesize for the specific memblk. + * It will be called on comp_ops.create() by generic layer, before or after + * mod_ops.init() according to the memblk usage. + * Args: + * mod - the pointer of model data struct object. + * blk - the memblk usage type. + * Returns: + * The bytesize or negative error code. + * 0 means no memory required + */ + int (*query_memblk_size)(struct smart_amp_mod_data_base *mod, + enum smart_amp_mod_memblk blk); + + /** + * Sets the allocated memblk info. + * It should be called in sequence after mod_ops.query_memblk_size(). + * Args: + * mod - the pointer of model data struct object. + * blk - the memblk usage type. + * buf - the pointer of smart_amp_buf object including allocated memory. + * Returns: + * 0 or negative error code. + */ + int (*set_memblk)(struct smart_amp_mod_data_base *mod, + enum smart_amp_mod_memblk blk, + struct smart_amp_buf *buf); + + /** + * Returns the list of supported frame formats. + * It will be called on comp_ops.prepare() by generic layer. + * + * Inner model should report all supported formats in the list at once. + * Generic layer will resolve the applicable format according to this list and + * the formats requested from external source/sink stream buffers. If it turns + * out to be no format applicable, generic layer will report errors which will + * force the early-termination of the starting process for the whole pipeline. + * Args: + * mod - the pointer of model data struct object. + * mod_fmts - the pointer for returning the supported format list. + * Format values should be aligned to "enum sof_ipc_frame" and + * put in ascending order. + * num_mod_fmts - the pointer for returning the length of mod_fmts. + * Returns: + * 0 or negative error code. + */ + int (*get_supported_fmts)(struct smart_amp_mod_data_base *mod, + const uint16_t **mod_fmts, int *num_mod_fmts); + + /** + * Sets the frame format after resolved. + * It will be called on comp_ops.prepare() by generic layer, in sequence after + * mod_ops.get_supported_fmts() if the format is resolvable. + * + * Inner model should honor the received format on processing. The FF and FB + * frames (if available) will be put to the input buffers in the same format. + * It will be the last function called before audio stream starts processing. + * needed, inner model should execute the preparing tasks as soon as it is + * called. + * Args: + * mod - the pointer of model data struct object. + * mod_fmt - the frame format to be applied.. + * Returns: + * 0 or negative error code. + */ + int (*set_fmt)(struct smart_amp_mod_data_base *mod, uint16_t mod_fmt); + + /** + * Runs the feed-forward process. + * Args: + * mod - the pointer of model data struct object. + * frames - the number of frames to be processed. + * in - the pointer of input stream buffer object. Inner model should set + * "consumed" to the number of conusmed frames. + * out - the pointer of output stream buffer object. Inner model should set + * "produced" to the number of produced frames. + * Returns: + * 0 or negative error code. + */ + int (*ff_proc)(struct smart_amp_mod_data_base *mod, + uint32_t frames, + struct smart_amp_mod_stream *in, + struct smart_amp_mod_stream *out); + + /** + * Runs the feedback process. + * Args: + * mod - the pointer of model data struct object. + * frames - the number of frames to be processed. + * in - the pointer of input stream buffer object. Inner model should set + * "consumed" to the number of conusmed frames. + * Returns: + * 0 or negative error code. + */ + int (*fb_proc)(struct smart_amp_mod_data_base *mod, + uint32_t frames, + struct smart_amp_mod_stream *in); + + /** + * Gets config data from model. + * Args: + * mod - the pointer of model data struct object. + * cdata - the pointer of sof_ipc_ctrl_data object. + * size - the maximal size for config data to read. + * Returns: + * 0 or negative error code. + */ + int (*get_config)(struct smart_amp_mod_data_base *mod, + struct sof_ipc_ctrl_data *cdata, uint32_t size); + + /** + * Sets config data to model. + * Args: + * mod - the pointer of model data struct object. + * cdata - the pointer of sof_ipc_ctrl_data object. + * Returns: + * 0 or negative error code. + */ + int (*set_config)(struct smart_amp_mod_data_base *mod, + struct sof_ipc_ctrl_data *cdata); + + /** + * Resets model. + * It will be called on comp_ops.reset() by generic layer. + * Args: + * mod - the pointer of model data struct object. + * Returns: + * 0 or negative error code. + */ + int (*reset)(struct smart_amp_mod_data_base *mod); +}; + +#endif diff --git a/src/include/sof/audio/source_api.h b/src/include/sof/audio/source_api.h new file mode 100644 index 000000000000..2f84e1948ebe --- /dev/null +++ b/src/include/sof/audio/source_api.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + */ + +#ifndef __SOF_SOURCE_API_H__ +#define __SOF_SOURCE_API_H__ + +#include <module/audio/source_api.h> + +/** + * Init of the API, must be called before any operation + * + * @param source pointer to the structure + * @param ops pointer to API operations + * @param audio_stream_params pointer to structure with audio parameters + * note that the audio_stream_params must be accessible by the caller core + * the implementation must ensure coherent access to the parameteres + * in case of i.e. cross core shared queue, it must be located in non-cached memory + */ +void source_init(struct sof_source *source, const struct source_ops *ops, + struct sof_audio_stream_params *audio_stream_params); + +/** + * Get total number of bytes processed by the source (meaning - freed by source_release_data()) + */ +size_t source_get_num_of_processed_bytes(struct sof_source *source); + +/** + * sets counter of total number of bytes processed to zero + */ +void source_reset_num_of_processed_bytes(struct sof_source *source); + +/** set of functions for retrieve audio parameters */ +bool source_get_underrun(struct sof_source *source); +uint32_t source_get_id(struct sof_source *source); + +/** set of functions for setting audio parameters */ +int source_set_frm_fmt(struct sof_source *source, enum sof_ipc_frame frm_fmt); +int source_set_valid_fmt(struct sof_source *source, + enum sof_ipc_frame valid_sample_fmt); +int source_set_rate(struct sof_source *source, unsigned int rate); +int source_set_channels(struct sof_source *source, unsigned int channels); +int source_set_underrun(struct sof_source *source, bool underrun_permitted); +int source_set_buffer_fmt(struct sof_source *source, uint32_t buffer_fmt); +void source_set_min_available(struct sof_source *source, size_t min_available); + +/** + * initial set of audio parameters, provided in sof_ipc_stream_params + * + * @param source a handler to source + * @param params the set of parameters + * @param force_update tells the implementation that the params should override actual settings + * @return 0 if success + */ +int source_set_params(struct sof_source *source, + struct sof_ipc_stream_params *params, bool force_update); + +/** + * Set frame_align_shift and frame_align of stream according to byte_align and + * frame_align_req alignment requirement. Once the channel number,frame size + * are determined, the frame_align and frame_align_shift are determined too. + * these two feature will be used in audio_stream_get_avail_frames_aligned + * to calculate the available frames. it should be called in component prepare + * or param functions only once before stream copy. if someone forgets to call + * this first, there would be unexampled error such as nothing is copied at all. + * + * @param source a handler to source + * @param byte_align Processing byte alignment requirement. + * @param frame_align_req Processing frames alignment requirement. + * + * @return 0 if success + */ +int source_set_alignment_constants(struct sof_source *source, + const uint32_t byte_align, + const uint32_t frame_align_req); + +#endif /* __SOF_SOURCE_API_H__ */ diff --git a/src/include/sof/audio/src/src.h b/src/include/sof/audio/src/src.h deleted file mode 100644 index 03d1a345d1d5..000000000000 --- a/src/include/sof/audio/src/src.h +++ /dev/null @@ -1,125 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_SRC_SRC_H__ -#define __SOF_AUDIO_SRC_SRC_H__ - -#include <stddef.h> -#include <stdint.h> - -struct src_param { - int fir_s1; - int fir_s2; - int out_s1; - int out_s2; - int sbuf_length; - int src_multich; - int total; - int blk_in; - int blk_out; - int stage1_times; - int stage2_times; - int idx_in; - int idx_out; - int nch; -}; - -struct src_stage { - const int idm; - const int odm; - const int num_of_subfilters; - const int subfilter_length; - const int filter_length; - const int blk_in; - const int blk_out; - const int halfband; - const int shift; - const void *coefs; /* Can be int16_t or int32_t depending on config */ -}; - -struct src_state { - int fir_delay_size; /* samples */ - int out_delay_size; /* samples */ - int32_t *fir_delay; - int32_t *out_delay; - int32_t *fir_wp; - int32_t *out_rp; -}; - -struct polyphase_src { - int number_of_stages; - struct src_stage *stage1; - struct src_stage *stage2; - struct src_state state1; - struct src_state state2; -}; - -struct src_stage_prm { - int nch; - int times; - void *x_rptr; - void *x_end_addr; - size_t x_size; - void *y_wptr; - void *y_addr; - void *y_end_addr; - size_t y_size; - int shift; - struct src_state *state; - struct src_stage *stage; -}; - -static inline void src_inc_wrap(int32_t **ptr, int32_t *end, size_t size) -{ - if (*ptr >= end) - *ptr = (int32_t *)((uint8_t *)*ptr - size); -} - -static inline void src_dec_wrap(int32_t **ptr, int32_t *addr, size_t size) -{ - if (*ptr < addr) - *ptr = (int32_t *)((uint8_t *)*ptr + size); -} - -#if CONFIG_FORMAT_S16LE -static inline void src_inc_wrap_s16(int16_t **ptr, int16_t *end, size_t size) -{ - if (*ptr >= end) - *ptr = (int16_t *)((uint8_t *)*ptr - size); -} - -static inline void src_dec_wrap_s16(int16_t **ptr, int16_t *addr, size_t size) -{ - if (*ptr < addr) - *ptr = (int16_t *)((uint8_t *)*ptr + size); -} -#endif /* CONFIG_FORMAT_S16LE */ - -void src_polyphase_reset(struct polyphase_src *src); - -int src_polyphase_init(struct polyphase_src *src, struct src_param *p, - int32_t *delay_lines_start); - -int src_polyphase(struct polyphase_src *src, int32_t x[], int32_t y[], - int n_in); - -#if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE -void src_polyphase_stage_cir(struct src_stage_prm *s); -#endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ - -#if CONFIG_FORMAT_S16LE -void src_polyphase_stage_cir_s16(struct src_stage_prm *s); -#endif /* CONFIG_FORMAT_S16LE */ - -int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, - int source_frames); - -int32_t src_input_rates(void); - -int32_t src_output_rates(void); - -#endif /* __SOF_AUDIO_SRC_SRC_H__ */ diff --git a/src/include/sof/audio/src/src_config.h b/src/include/sof/audio/src/src_config.h deleted file mode 100644 index b8feade700f3..000000000000 --- a/src/include/sof/audio/src/src_config.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_SRC_SRC_CONFIG_H__ -#define __SOF_AUDIO_SRC_SRC_CONFIG_H__ - -#include <config.h> - -/* If next define is set to 1 the SRC is configured automatically. Setting - * to zero temporarily is useful is for testing needs. - */ -#define SRC_AUTOARCH 1 - -/* Force manually some code variant when SRC_AUTODSP is set to zero. These - * are useful in code debugging. - */ -#if SRC_AUTOARCH == 0 -#define SRC_SHORT 0 -#define SRC_GENERIC 1 -#define SRC_HIFIEP 0 -#define SRC_HIFI3 0 -#endif - -/* Select optimized code variant when xt-xcc compiler is used */ -#if SRC_AUTOARCH == 1 -#if defined __XCC__ -#include <xtensa/config/core-isa.h> -#define SRC_GENERIC 0 -#if XCHAL_HAVE_HIFI2EP == 1 -#define SRC_SHORT 1 /* Select 16 bit coefficients to save RAM */ -#define SRC_HIFIEP 1 -#define SRC_HIFI3 0 -#endif -#if XCHAL_HAVE_HIFI3 == 1 -#define SRC_SHORT 0 /* Select 32 bit default quality coefficients */ -#define SRC_HIFI3 1 -#define SRC_HIFIEP 0 -#endif -#else -/* GCC */ -#if CONFIG_LIBRARY -#define SRC_SHORT 0 /* Use high quality 32 bit filter coefficients */ -#else -#define SRC_SHORT 1 /* Use 16 bit filter coefficients for speed */ -#endif -#define SRC_GENERIC 1 -#define SRC_HIFIEP 0 -#define SRC_HIFI3 0 -#endif -#endif - -#endif /* __SOF_AUDIO_SRC_SRC_CONFIG_H__ */ diff --git a/src/include/sof/audio/volume.h b/src/include/sof/audio/volume.h deleted file mode 100644 index 8f21b3944dc9..000000000000 --- a/src/include/sof/audio/volume.h +++ /dev/null @@ -1,145 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file audio/volume.h - * \brief Volume component header file - * \authors Liam Girdwood <liam.r.girdwood@linux.intel.com>\n - * Keyon Jie <yang.jie@linux.intel.com>\n - * Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __SOF_AUDIO_VOLUME_H__ -#define __SOF_AUDIO_VOLUME_H__ - -#include <sof/audio/component.h> -#include <sof/bit.h> -#include <sof/schedule/task.h> -#include <sof/trace/trace.h> -#include <ipc/stream.h> -#include <user/trace.h> -#include <stddef.h> -#include <stdint.h> - -struct comp_buffer; -struct sof_ipc_ctrl_value_chan; - -#define CONFIG_GENERIC - -#if defined(__XCC__) -#include <xtensa/config/core-isa.h> - -#if XCHAL_HAVE_HIFI3 -#undef CONFIG_GENERIC -#endif - -#endif - -//** \brief Volume gain Qx.y integer x number of bits including sign bit. */ -#define VOL_QXY_X 8 - -//** \brief Volume gain Qx.y fractional y number of bits. */ -#define VOL_QXY_Y 16 - -/** - * \brief Volume ramp update rate in microseconds. - * Update volume gain value every 1 ms. - */ -#define VOL_RAMP_UPDATE_US 1000 - -/** - * \brief Macro for volume linear gain ramp step computation - * Volume gain ramp step as Q1.16 is computed with equation - * step = VOL_RAMP_STEP_CONST / SOF_TKN_VOLUME_RAMP_STEP_MS. This - * macro defines as Q1.16 value the constant term - * VOL_RAMP_UPDATE / 1000.0 for step calculation. The value 1000 - * is used to to convert microseconds to milliseconds. - */ -#define VOL_RAMP_STEP_CONST \ - Q_CONVERT_FLOAT(VOL_RAMP_UPDATE_US / 1000.0, VOL_QXY_Y) - -/** - * \brief Volume maximum value. - * TODO: This should be 1 << (VOL_QX_BITS + VOL_QY_BITS - 1) - 1 but - * the current volume code cannot handle the full Q1.16 range correctly. - */ -#define VOL_MAX ((1 << (VOL_QXY_X + VOL_QXY_Y - 1)) - 1) - -/** \brief Volume 0dB value. */ -#define VOL_ZERO_DB BIT(VOL_QXY_Y) - -/** \brief Volume minimum value. */ -#define VOL_MIN 0 - -/** - * \brief volume processing function interface - */ -typedef void (*vol_scale_func)(struct comp_dev *dev, struct audio_stream *sink, - const struct audio_stream *source, - uint32_t frames); -/** - * \brief Volume component private data. - * - * Gain amplitude value is between 0 (mute) ... 2^16 (0dB) ... 2^24 (~+48dB). - */ -struct comp_data { - struct task *volwork; /**< volume scheduled work function */ - struct sof_ipc_ctrl_value_chan *hvol; /**< host volume readback */ - int32_t volume[SOF_IPC_MAX_CHANNELS]; /**< current volume */ - int32_t tvolume[SOF_IPC_MAX_CHANNELS]; /**< target volume */ - int32_t mvolume[SOF_IPC_MAX_CHANNELS]; /**< mute volume */ - int32_t ramp_increment[SOF_IPC_MAX_CHANNELS]; /**< for linear ramp */ - int32_t vol_min; /**< minimum volume */ - int32_t vol_max; /**< maximum volume */ - int32_t vol_ramp_range; /**< max ramp transition */ - unsigned int channels; /**< current channels count */ - bool muted[SOF_IPC_MAX_CHANNELS]; /**< set if channel is muted */ - bool vol_ramp_active; /**< set if volume is ramped */ - bool ramp_started; /**< control ramp launch */ - vol_scale_func scale_vol; /**< volume processing function */ -}; - -/** \brief Volume processing functions map. */ -struct comp_func_map { - uint16_t frame_fmt; /**< frame format */ - vol_scale_func func; /**< volume processing function */ -}; - -/** \brief Map of formats with dedicated processing functions. */ -extern const struct comp_func_map func_map[]; - -/** \brief Number of processing functions. */ -extern const size_t func_count; - -/** - * \brief Retrievies volume processing function. - * \param[in,out] dev Volume base component device. - */ -static inline vol_scale_func vol_get_processing_function(struct comp_dev *dev) -{ - struct comp_buffer *sinkb; - int i; - - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - /* map the volume function for source and sink buffers */ - for (i = 0; i < func_count; i++) { - if (sinkb->stream.frame_fmt != func_map[i].frame_fmt) - continue; - - return func_map[i].func; - } - - return NULL; -} - -#ifdef UNIT_TEST -void sys_comp_volume_init(void); -#endif - -#endif /* __SOF_AUDIO_VOLUME_H__ */ diff --git a/src/include/sof/auth_api_iface.h b/src/include/sof/auth_api_iface.h new file mode 100644 index 000000000000..ff8b1006076a --- /dev/null +++ b/src/include/sof/auth_api_iface.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ +#ifndef __AUTH_API_IFACE_H__ +#define __AUTH_API_IFACE_H__ + +#include <auth/intel_status_logger_iface.h> +#include <stdint.h> +#include <stddef.h> + +#define AUTH_API_VERSION_MAJOR (2) +#define AUTH_API_VERSION_MINOR (0) +#define AUTH_API_VERSION_PATCH (0) + +#define AUTH_SCRATCH_BUFF_SZ (0xA000) // 40kB + +/* + * Return codes supported by authentication engine: + * ADSP_AUTH_IMAGE_UNTRUSTED = 9040, + * ADSP_AUTH_CANNOT_ALLOCATE_SCRATCH_BUFF = 9041, + * ADSP_AUTH_INVALID_AUTH_API_CTX_PTR = 9042, + * ADSP_AUTH_SVN_VERIFICATION_FAIL = 9043, + * ADSP_AUTH_IFWI_PARTITION_FAIL = 9044, + * ADSP_AUTH_VERIFY_IMAGE_TYPE_FAIL = 9045, + * ADSP_AUTH_UNSUPPORTED_VERSION = 9046, + * ADSP_AUTH_INCOMPATIBLE_MANIFEST_VERSION = 9047, + */ + +struct auth_api_version_num { + uint8_t patch; + uint8_t minor; + uint8_t major; + uint8_t rsvd; +} __packed __aligned(4); + +enum auth_phase { + AUTH_PHASE_FIRST = 0, + AUTH_PHASE_MID = 1, + AUTH_PHASE_LAST = 2 +}; + +enum auth_result { + AUTH_NOT_COMPLETED = 0, + AUTH_IMAGE_TRUSTED = 1, + AUTH_IMAGE_UNTRUSTED = 2 +}; + +enum auth_image_type { + IMG_TYPE_ROM_EXT = 0, + IMG_TYPE_MAIN_FW = 1, + IMG_TYPE_LIB = 2 +}; + +struct auth_api_ctx; + +struct auth_api_version { + /* Interface to return authentication API version. + * Return value: version number represented by auth_api_version_num structure. + */ + struct auth_api_version_num (*version)(); +}; + +struct auth_api { + /* Interface to initialize authentication API and context. + * Parameters: + * ctx - pointer to the context instance of type auth_api_ctx. + * scratch_buff - pointer to scratch buffer. + * Scratch buffer must be located in L2 Local Memory (SHA Engine limitation). + * Caller is responsible to power up necessary L2 Local Memory banks. + * Address alignment must correspond to SHA384_IO_BUF_ALIGNMENT. + * scratch_buff_size – size must be the same as AUTH_SCRATCH_BUFF_SZ. + * Return value: + * ADSP_SUCCESS - successful initialization. + */ + int (*init)(struct auth_api_ctx *ctx, void *scratch_buff, size_t scratch_buff_size, + enum auth_image_type image_type); + + /* Interface to cleanup authentication API. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + */ + void (*cleanup)(struct auth_api_ctx *ctx); + + /* Interface for initiating signed FW image (async) authentication process. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * chunk - pointer to the chunk of signed FW image. + * chunk_size - chunk size in bytes. + * phase - authentication phase. + * Must corresponds to one of the AuthPhase values. + * In case of one time FW authentication, where signed FW image size must be + * less or equal to scratch_buff_size, the caller must pass AUTH_PHASE_LAST. + * Return value: ADSP_SUCCESS when authentication process has been initiated + * successfully, or one of ADSP_FLV_* error codes in case of failure. + */ + int (*init_auth_proc)(struct auth_api_ctx *ctx, const void *chunk, size_t chunk_size, + enum auth_phase phase); + + /* Interface to return if authentication process is busy. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * This function can be used for authentication process synchronization. + * Return value: true if authentication process is busy. + */ + bool (*busy)(struct auth_api_ctx *ctx); + + /* Interface to return authentication result + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * Return value: + * AUTH_NOT_COMPLETED - authentication is not completed, + * AUTH_IMAGE_TRUSTED - authentication completed and signed FW image is + * trusted, + * AUTH_IMAGE_UNTRUSTED - authentication completed, but signed FW image is + * untrusted. + */ + enum auth_result (*result)(struct auth_api_ctx *ctx); + + /* Interface to register status/error code logger. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * sts_logger - pointer to status logger. + * Return value: ADSP_SUCCESS when logger has been registered successfully. + */ + int (*register_status_logger)(struct auth_api_ctx *ctx, + struct status_logger_ctx *status_logger); + + /* Interface to unregister status/error code logger. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + */ + void (*unregister_status_logger)(struct auth_api_ctx *ctx); +}; + +struct auth_api_ctx { + struct auth_api_version *version_api; + void *scratch_buff; + size_t scratch_buff_size; + enum auth_result result; + struct auth_api *auth_api; + enum auth_image_type image_type; + struct status_logger_ctx *status_logger; +}; + +#endif /* __SOF_LIB_MANAGER_H__ */ diff --git a/src/include/sof/bit.h b/src/include/sof/bit.h deleted file mode 100644 index 9a233d3f11a4..000000000000 --- a/src/include/sof/bit.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_BIT_H__ -#define __SOF_BIT_H__ - -#if ASSEMBLY -#define BIT(b) (1 << (b)) -#else -#define BIT(b) (1UL << (b)) -#endif - -#define MASK(b_hi, b_lo) \ - (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) -#define SET_BIT(b, x) (((x) & 1) << (b)) -#define SET_BITS(b_hi, b_lo, x) \ - (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) - -#endif /* __SOF_BIT_H__ */ diff --git a/src/include/sof/boot_test.h b/src/include/sof/boot_test.h new file mode 100644 index 000000000000..1af6e7f2d8e0 --- /dev/null +++ b/src/include/sof/boot_test.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_BOOT_TEST_H__ +#define __SOF_BOOT_TEST_H__ + +#if !CONFIG_LIBRARY +#include <zephyr/logging/log.h> +#else +#define LOG_ERR(...) do {} while (0) +#endif +#include <stdbool.h> + +#if CONFIG_SOF_BOOT_TEST +#define TEST_RUN_ONCE(fn, ...) do { \ + static bool once; \ + if (!once) { \ + once = true; \ + fn(__VA_ARGS__); \ + } \ +} while (0) +#else +#define TEST_RUN_ONCE(fn, ...) do {} while (0) +#endif + +#define TEST_CHECK_RET(ret, testname) do { \ + if ((ret) < 0) { \ + LOG_ERR(testname " failed: %d", (ret)); \ + ztest_test_fail(); \ + } else { \ + ztest_test_pass(); \ + } \ +} while (0) + +void sof_run_boot_tests(void); + +#endif diff --git a/src/include/sof/coherent.h b/src/include/sof/coherent.h new file mode 100644 index 000000000000..172e45b4ed92 --- /dev/null +++ b/src/include/sof/coherent.h @@ -0,0 +1,448 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __SOF_COHERENT_H__ +#define __SOF_COHERENT_H__ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <rtos/spinlock.h> +#include <sof/list.h> +#include <sof/lib/memory.h> +#include <sof/lib/cpu.h> + +#define __coherent __aligned(PLATFORM_DCACHE_ALIGN) + +/* + * The coherent API allows optimized access to memory by multiple cores, using + * cache, taking care about coherence. The intended use is to let cores acquire + * ownership of such shared objects, use them, and then release them, possibly + * to be re-acquired by other cores. Such shared objects must only be accessed + * via this API. It's designed to be primarily used with dynamically allocated + * objects because of their well-defined life span. It can also be used with + * objects from .data or .bss sections but greater care must be takenwith them + * to strictly follow the API flow. + * + * The API assumes, that in the beginning no core has cache lines associated + * with the memory area, used with it. That is true for dynamically allocated + * memory, because when such memory is freed, its cache is invalidated - as long + * as that memory was never accessed by other cores, except by using this API. + * The first call must be coherent_init(), which initializes the header. If the + * object will be used by multiple cores, next coherent_shared() must be called. + * After that to use that memory, coherent_acquire() must be called, which + * acquires ownership of the object and returns a cached address of the memory. + * After that the user can perform cached access to the memory. To release the + * memory, coherent_release() must be called. The only time when the memory is + * accessed using cache is between those two calls, so only when releasing the + * memory we have to write back and invalidate caches to make sure, that next + * time we acquire this memory, our uncached header access will not be + * overwritten! When memory is not needed any more, typically before freeing the + * memory, coherent_free() should be called. + * + * This structure needs to be embedded at the start of any container to ensure + * container object cache alignment and to minimise non cache access when + * acquiring ownership. + * + * This structure must not be accessed outside of these APIs. + * The shared flag is only set at coherent init and thereafter it's RO. + */ +struct coherent { + union { + struct { + struct k_spinlock lock; /* locking mechanism */ + k_spinlock_key_t key; /* lock flags */ + }; +#ifdef __ZEPHYR__ + struct k_mutex mutex; +#endif + }; + uint8_t sleep_allowed; /* the object will never be acquired or released + * in atomic context */ + uint8_t shared; /* shared on other non coherent cores */ + uint16_t core; /* owner core if not shared */ + struct list_item list; /* coherent list iteration */ +} __coherent; + +#if CONFIG_INCOHERENT +# ifdef __ZEPHYR__ +BUILD_ASSERT(sizeof(struct coherent) <= DCACHE_LINE_SIZE, "DCACHE_LINE_SIZE too small"); +# else +STATIC_ASSERT(sizeof(struct coherent) <= DCACHE_LINE_SIZE, DCACHE_LINE_SIZE_too_small); +# endif +#endif + +/* debug address aliases */ +#ifdef COHERENT_CHECK_ALIAS +#define ADDR_IS_INCOHERENT(_c) assert(!is_uncached(_c)) +#define ADDR_IS_COHERENT(_c) assert(is_uncached(_c)) +#else +#define ADDR_IS_INCOHERENT(_c) +#define ADDR_IS_COHERENT(_c) +#endif + +/* debug sharing amongst cores */ +#ifdef COHERENT_CHECK_NONSHARED_CORES + +#define CORE_CHECK_STRUCT_FIELD uint32_t __core; bool __is_shared +#define CORE_CHECK_STRUCT_INIT(_c, is_shared) { (_c)->__core = cpu_get_id(); \ + (_c)->__is_shared = is_shared; } +#define CORE_CHECK_STRUCT(_c) { assert(!!(_c)->__is_shared == !!is_uncached(_c)); \ + assert(cpu_get_id() == (_c)->__core || (_c)->__is_shared); } + +#define CHECK_COHERENT_CORE(_c) assert((_c)->core == cpu_get_id()) + +#else + +#define CORE_CHECK_STRUCT_FIELD +#define CORE_CHECK_STRUCT_INIT(_c, is_shared) +#define CORE_CHECK_STRUCT(_c) + +#define CHECK_COHERENT_CORE(_c) + +#endif + +#ifdef __ZEPHYR__ +#define CHECK_ISR() __ASSERT(!k_is_in_isr(), "Attempt to sleep in ISR!") +#define CHECK_SLEEP(_c) __ASSERT((_c)->sleep_allowed, \ + "This context hasn't been initialized for sleeping!") +#define CHECK_ATOMIC(_c) __ASSERT(!(_c)->sleep_allowed, \ + "This context has been initialized for sleeping!") +#else +#define CHECK_ISR() assert(!k_is_in_isr()) +#define CHECK_SLEEP(_c) assert((_c)->sleep_allowed) +#define CHECK_ATOMIC(_c) assert(!(_c)->sleep_allowed) +#endif + +#if CONFIG_INCOHERENT +/* When coherent_acquire() is called, we are sure not to have cache for this memory */ +__must_check static inline struct coherent __sparse_cache *coherent_acquire(struct coherent *c, + const size_t size) +{ + struct coherent __sparse_cache *cc = uncache_to_cache(c); + + /* assert if someone passes a cache/local address in here. */ + ADDR_IS_COHERENT(c); + CHECK_ATOMIC(c); + + /* access the shared coherent object */ + if (c->shared) { + CHECK_COHERENT_CORE(c); + + c->key = k_spin_lock(&c->lock); + + /* + * FIXME: This is wrong. dcache_invalidate_region() only makes + * sense if we assume, that dirty cache lines might exist for + * this object. But in that case those lines could be written + * back here thus overwriting either user data, or the coherent + * header or both. When coherent_acquire() is called it must be + * guaranteed that the object isn't in cache. Before it is + * acquired no cached access to it is allowed. This has to be + * fixed here and on multiple further occasions below. + */ + + /* invalidate local copy */ + dcache_invalidate_region(cc, size); + } + + /* client can now use cached object safely */ + return cc; +} + +static inline void coherent_release(struct coherent __sparse_cache *c, + const size_t size) +{ + /* assert if someone passes a coherent address in here. */ + ADDR_IS_INCOHERENT(c); + CHECK_ATOMIC(c); + + /* access the local copy of object */ + if (c->shared) { + struct coherent *uc = cache_to_uncache(c); + CHECK_COHERENT_CORE(c); + + /* wtb and inv local data to coherent object */ + dcache_writeback_invalidate_region(c, size); + + /* unlock on uncache alias */ + k_spin_unlock(&uc->lock, uc->key); + } +} + +static inline void *__coherent_init(size_t offset, const size_t size) +{ + /* + * Allocate an object with an uncached alias but align size on a cache- + * line boundary to avoid sharing a cache line with the adjacent + * allocation + */ + void *object = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + ALIGN_UP(size, PLATFORM_DCACHE_ALIGN)); + struct coherent *c; + + if (!object) + return NULL; + + c = (struct coherent *)((uint8_t *)object + offset); + + /* TODO static assert if we are not cache aligned */ + k_spinlock_init(&c->lock); + c->sleep_allowed = false; + c->shared = false; + c->core = cpu_get_id(); + list_init(&c->list); + /* inv local data to coherent object */ + dcache_invalidate_region(uncache_to_cache(object), size); + + return object; +} + +#define coherent_init(type, member) __coherent_init(offsetof(type, member), \ + sizeof(type)) + +/* set the object to shared mode with coherency managed by SW */ +static inline void __coherent_shared(struct coherent *c, const size_t size) +{ + /* assert if someone passes a cache/local address in here. */ + ADDR_IS_COHERENT(c); + CHECK_ATOMIC(c); + + c->key = k_spin_lock(&c->lock); + c->shared = true; + dcache_invalidate_region(uncache_to_cache(c), size); + k_spin_unlock(&c->lock, c->key); +} + +#define coherent_shared(object, member) __coherent_shared(&(object)->member, \ + sizeof(*object)) + +#ifdef __ZEPHYR__ + +__must_check static inline struct coherent __sparse_cache *coherent_acquire_thread( + struct coherent *c, const size_t size) +{ + struct coherent __sparse_cache *cc = uncache_to_cache(c); + + /* assert if someone passes a cache/local address in here. */ + ADDR_IS_COHERENT(c); + CHECK_SLEEP(c); + CHECK_ISR(); + + /* access the shared coherent object */ + if (c->shared) { + CHECK_COHERENT_CORE(c); + + k_mutex_lock(&c->mutex, K_FOREVER); + + /* invalidate local copy */ + dcache_invalidate_region(cc, size); + } + + /* client can now use cached object safely */ + return cc; +} + +static inline void coherent_release_thread(struct coherent __sparse_cache *c, + const size_t size) +{ + /* assert if someone passes a coherent address in here. */ + ADDR_IS_INCOHERENT(c); + CHECK_SLEEP(c); + CHECK_ISR(); + + /* access the local copy of object */ + if (c->shared) { + struct coherent *uc = cache_to_uncache(c); + CHECK_COHERENT_CORE(c); + + /* wtb and inv local data to coherent object */ + dcache_writeback_invalidate_region(c, size); + + /* unlock on uncache alias */ + k_mutex_unlock(&uc->mutex); + } +} + +static inline void *__coherent_init_thread(size_t offset, const size_t size) +{ + /* As above - prevent cache line sharing */ + void *object = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + ALIGN_UP(size, PLATFORM_DCACHE_ALIGN)); + struct coherent *c; + + if (!object) + return NULL; + + c = (struct coherent *)((uint8_t *)object + offset); + + /* TODO static assert if we are not cache aligned */ + k_mutex_init(&c->mutex); + c->sleep_allowed = true; + c->shared = false; + c->core = cpu_get_id(); + list_init(&c->list); + /* inv local data to coherent object */ + dcache_invalidate_region(uncache_to_cache(object), size); + + return object; +} + +#define coherent_init_thread(type, member) __coherent_init_thread(offsetof(type, member), \ + sizeof(type)) + +static inline void __coherent_shared_thread(struct coherent *c, const size_t size) +{ + /* assert if someone passes a cache/local address in here. */ + ADDR_IS_COHERENT(c); + CHECK_SLEEP(c); + CHECK_ISR(); + + k_mutex_lock(&c->mutex, K_FOREVER); + c->shared = true; + dcache_invalidate_region(uncache_to_cache(c), size); + k_mutex_unlock(&c->mutex); +} + +#define coherent_shared_thread(object, member) __coherent_shared_thread(&(object)->member, \ + sizeof(*object)) + +#endif /* __ZEPHYR__ */ + +#define coherent_free(object, member) \ + do { \ + /* assert if someone passes a cache address in here. */ \ + ADDR_IS_COHERENT(object); \ + /* wtb and inv local data to coherent object */ \ + dcache_writeback_invalidate_region(uncache_to_cache(object), \ + sizeof(*object)); \ + rfree(object); \ + } while (0) + +#else /* CONFIG_INCOHERENT */ + +/* + * Coherent devices only require locking to manage shared access. + */ +__must_check static inline struct coherent __sparse_cache *coherent_acquire(struct coherent *c, + const size_t size) +{ + if (c->shared) + c->key = k_spin_lock(&c->lock); + + return (__sparse_force struct coherent __sparse_cache *)c; +} + +static inline void coherent_release(struct coherent __sparse_cache *c, + const size_t size) +{ + if (c->shared) + k_spin_unlock(&c->lock, c->key); +} + +static inline void *__coherent_init(size_t offset, const size_t size) +{ + /* As in CONFIG_INCOHERENT case - prevent cache line sharing */ + void *object = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + ALIGN_UP(size, PLATFORM_DCACHE_ALIGN)); + struct coherent *c; + + if (!object) + return NULL; + + c = (struct coherent *)((uint8_t *)object + offset); + + /* TODO static assert if we are not cache aligned */ + k_spinlock_init(&c->lock); + c->shared = 0; + c->core = cpu_get_id(); + list_init(&c->list); + + return object; +} + +#define coherent_init(type, member) __coherent_init(offsetof(type, member), \ + sizeof(type)) + +#define coherent_free(object, member) rfree(object) + +static inline void __coherent_shared(struct coherent *c, const size_t size) +{ + c->key = k_spin_lock(&c->lock); + c->shared = true; + k_spin_unlock(&c->lock, c->key); +} + +#define coherent_shared(object, member) __coherent_shared(&(object)->member, \ + sizeof(*object)) + +#ifdef __ZEPHYR__ +__must_check static inline struct coherent __sparse_cache *coherent_acquire_thread( + struct coherent *c, const size_t size) +{ + if (c->shared) + k_mutex_lock(&c->mutex, K_FOREVER); + + return (__sparse_force struct coherent __sparse_cache *)c; +} + +static inline void coherent_release_thread(struct coherent __sparse_cache *c, + const size_t size) +{ + if (c->shared) + k_mutex_unlock(&c->mutex); +} + +static inline void *__coherent_init_thread(size_t offset, const size_t size) +{ + /* As above - prevent cache line sharing */ + void *object = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + ALIGN_UP(size, PLATFORM_DCACHE_ALIGN)); + struct coherent *c; + + if (!object) + return NULL; + + c = (struct coherent *)((uint8_t *)object + offset); + + /* TODO static assert if we are not cache aligned */ + k_mutex_init(&c->mutex); + c->shared = 0; + c->core = cpu_get_id(); + list_init(&c->list); + + return object; +} + +#define coherent_init_thread(type, member) __coherent_init_thread(offsetof(type, member), \ + sizeof(type)) + +static inline void __coherent_shared_thread(struct coherent *c, const size_t size) +{ + k_mutex_lock(&c->mutex, K_FOREVER); + c->shared = true; + k_mutex_unlock(&c->mutex); +} + +#define coherent_shared_thread(object, member) __coherent_shared_thread(&(object)->member, \ + sizeof(*object)) +#endif /* __ZEPHYR__ */ + +#endif /* CONFIG_INCOHERENT */ + +#ifndef __ZEPHYR__ +#define coherent_acquire_thread coherent_acquire +#define coherent_release_thread coherent_release +#define coherent_init_thread coherent_init +#define coherent_shared_thread coherent_shared +#endif + +#define coherent_free_thread coherent_free + +#define is_coherent_shared(object, member) ((object)->member.shared) +#endif diff --git a/src/include/sof/common.h b/src/include/sof/common.h index 4fa01c6fc3f4..d7aa9a7989cb 100644 --- a/src/include/sof/common.h +++ b/src/include/sof/common.h @@ -9,40 +9,155 @@ #ifndef __SOF_COMMON_H__ #define __SOF_COMMON_H__ +#if !defined(LINKER) + +/* callers must check/use the return value */ +#define __must_check __attribute__((warn_unused_result)) + +#ifdef __ZEPHYR__ +#include <zephyr/sys/util.h> +#endif + /* Align the number to the nearest alignment value */ +#ifndef IS_ALIGNED #define IS_ALIGNED(size, alignment) ((size) % (alignment) == 0) -#define ALIGN_UP(size, alignment) \ - ((size) + (((alignment) - ((size) % (alignment))) % (alignment))) -#define ALIGN_DOWN(size, alignment) \ - ((size) - ((size) % (alignment))) -#define ALIGN ALIGN_UP +#endif + +/* Treat zero as a special case because it wraps around */ +#define is_power_of_2(x) ((x) && !((x) & ((x) - 1))) + +#define compile_check(x) (sizeof(struct { int _f[2 * (x) - 1]; }) != 0) + +#define ALIGN_UP_INTERNAL(val, align) (((val) + (align) - 1) & ~((align) - 1)) + +#if !defined(__ASSEMBLER__) && defined(__XTENSA__) + +#include <ipc/trace.h> +#include <rtos/panic.h> +#define VERIFY_ALIGN + +#endif + +#ifdef VERIFY_ALIGN + +/* Using this when 'alignment' is a constant and when compiling with gcc + * -O0 saves about 30 bytes of .text and a few CPU cycles compared to + * the ALIGN_UP() combined check. There's no .text difference when + * optimizing. + */ +#define ALIGN_UP_COMPILE(size, alignment) \ + (compile_check(is_power_of_2(alignment)) ? \ + ALIGN_UP_INTERNAL(size, alignment) : 0xBADCAFE) + +#if defined(__XCC__) || defined(__clang__) + +/* + * xcc doesn't support __builtin_constant_p() so we can only do run-time + * verification + */ + +#define ALIGN_UP(size, alignment) ({ \ + if (!is_power_of_2(alignment)) \ + sof_panic(SOF_IPC_PANIC_ASSERT); \ + ALIGN_UP_INTERNAL(size, alignment); \ +}) + +#define ALIGN_DOWN(size, alignment) ({ \ + if (!is_power_of_2(alignment)) \ + sof_panic(SOF_IPC_PANIC_ASSERT); \ + (size) & ~((alignment) - 1); \ +}) + +#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) || \ + is_power_of_2(align)) + +#define ALIGN_UP(size, alignment) ({ \ + if (!compile_check(COMPILE_TIME_ALIGNED(alignment)) || \ + !is_power_of_2(alignment)) \ + sof_panic(SOF_IPC_PANIC_ASSERT); \ + ALIGN_UP_INTERNAL(size, alignment); \ +}) + +#define ALIGN_DOWN(size, alignment) ({ \ + if (!compile_check(COMPILE_TIME_ALIGNED(alignment)) || \ + !is_power_of_2(alignment)) \ + sof_panic(SOF_IPC_PANIC_ASSERT); \ + (size) & ~((alignment) - 1); \ +}) + +#endif /* not __XCC__ or __clang__ */ -#ifndef __ASSEMBLER__ +#else /* not VERIFY_ALIGN */ -#include <sof/trace/preproc.h> +#define ALIGN_UP(size, alignment) ALIGN_UP_INTERNAL(size, alignment) +#define ALIGN_UP_COMPILE ALIGN_UP +#define ALIGN_DOWN(size, alignment) ((size) & ~((alignment) - 1)) + +#endif + +/* This most basic ALIGN() must be used in header files that are + * included in both C and assembly code. memory.h files require this + * exact spelling matching the linker function because memory.h values + * are _also_ copied unprocessed to the .x[.in] linker script + */ +#define ALIGN(val, align) ALIGN_UP_INTERNAL(val, align) +#define SOF_DIV_ROUND_UP(val, div) (((val) + (div) - 1) / (div)) + +#if !defined(__ASSEMBLER__) + +#include <rtos/string_macro.h> #include <sof/compiler_attributes.h> #include <stddef.h> /* use same syntax as Linux for simplicity */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#ifndef __ZEPHYR__ /* Already present and compatible via Zephyr headers */ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif #define container_of(ptr, type, member) \ - ({const typeof(((type *)0)->member)*__memberptr = (ptr); \ + ({const __typeof__(((type *)0)->member)*__memberptr = (ptr); \ (type *)((char *)__memberptr - offsetof(type, member)); }) +/* + * typeof() doesn't preserve __attribute__((address_space(x))) sparse + * annotations, so if an object belongs to such an address space, using the + * original form of container_of() will lose that annotation, which then will + * lead to sparse "different address spaces" warnings. We need to explicitly + * re-inforce the address space onto the new pointer. + */ +#define attr_container_of(ptr, type, member, attr) \ + ({const __typeof__(((type *)0)->member) attr *__memberptr = (ptr); \ + (type *)((char attr *)__memberptr - offsetof(type, member)); }) #define ffs(i) __builtin_ffs(i) #define ffsl(i) __builtin_ffsl(i) #define ffsll(i) __builtin_ffsll(i) +#define clz(i) __builtin_clz(i) +#define clzl(i) __builtin_clzl(i) +#define clzll(i) __builtin_clzll(i) + #define popcount(x) __builtin_popcount(x) /* count number of var args */ #define PP_NARG(...) (sizeof((unsigned int[]){0, ##__VA_ARGS__}) \ / sizeof(unsigned int) - 1) -/* compile-time assertion */ +/* Compile-time assertion. + * + * The first, typedef-based solution silently succeeds with variables, + * for instance STATIC_ASSERT(n == 42, always_succeeds) when 'n' is a + * variable in a function. The second, array-based solution is not + * fooled by variables but it increases the .bss size at the -O0 + * optimization level (no difference with any real -O). As we're often + * short on space, use the typedef-based version by default. If you're + * afraid that some assertions are being fooled by variables then + * temporarily and locally switch to the second one. + */ #define STATIC_ASSERT(COND, MESSAGE) \ __attribute__((unused)) \ - typedef char META_CONCAT(assertion_failed_, MESSAGE)[(COND) ? 1 : -1] + typedef char _CONCAT(assertion_failed_, MESSAGE)[(COND) ? 1 : -1] /* Allows checking preprocessor symbols in compile-time. * Returns true for config with value 1, false for undefined or any other value. @@ -54,13 +169,68 @@ * error for other types, except positive integers, but it shouldn't be * used with them. */ +#ifndef __ZEPHYR__ /* Already present and compatible via Zephyr headers */ #define IS_ENABLED(config) IS_ENABLED_STEP_1(config) #define IS_ENABLED_DUMMY_1 0, #define IS_ENABLED_STEP_1(config) IS_ENABLED_STEP_2(IS_ENABLED_DUMMY_ ## config) #define IS_ENABLED_STEP_2(values) IS_ENABLED_STEP_3(values 1, 0) #define IS_ENABLED_STEP_3(ignore, value, ...) (!!(value)) +#endif + +#define SOF_CONFIG_HIFI(level, component) (CONFIG_ ## component ## _HIFI_ ## level) + +/* True if: + * (1) EITHER this particular level was manually forced in Kconfig, + * (2) OR: - this component defaulted to "MAX" + * - AND this level is the max available in the XC HAL. + */ +#define SOF_USE_HIFI(level, component) (SOF_CONFIG_HIFI(level, component) || \ + (SOF_CONFIG_HIFI(MAX, component) && level == SOF_MAX_XCHAL_HIFI)) + +/* True if: + * (1) EITHER this particular level was manually forced in Kconfig, + * (2) OR: - this component defaulted to "MAX" + * - AND this level is less or equal to max available in the XC HAL. + * + * Use e.g. for highest optimization level source file, e.g. SOF_USE_MIN_HIFI(4, component) + * for HiFi4 code version that can be built with HiFi4 or HiFi5 tool chain. + */ +#define SOF_USE_MIN_HIFI(minlevel, component) (SOF_CONFIG_HIFI(minlevel, component) || \ + (SOF_CONFIG_HIFI(MAX, component) && minlevel <= SOF_MAX_XCHAL_HIFI)) + +#ifndef __XCC__ // Cadence toolchains: either xt-xcc or xt-clang. +# define SOF_MAX_XCHAL_HIFI NONE +#else +# include <xtensa/config/core-isa.h> +// Maybe we could make this fully generic (and less readable!) using +// IS_ENABLED() above. +# if XCHAL_HAVE_HIFI5 +# define SOF_MAX_XCHAL_HIFI 5 +# define SOF_FRAME_BYTE_ALIGN 16 +# elif XCHAL_HAVE_HIFI4 +# define SOF_MAX_XCHAL_HIFI 4 +# define SOF_FRAME_BYTE_ALIGN 8 +# elif XCHAL_HAVE_HIFI3 +# define SOF_MAX_XCHAL_HIFI 3 +# define SOF_FRAME_BYTE_ALIGN 8 +# else +# define SOF_MAX_XCHAL_HIFI NONE +# endif +#endif -#if defined __XCC__ +/* Keep this last after all platform specific align defaults */ +#ifndef SOF_FRAME_BYTE_ALIGN +# define SOF_FRAME_BYTE_ALIGN 4 +#endif + +/* Default frame-count alignment is 1 */ +#define SOF_FRAME_COUNT_ALIGN 1 + +#ifndef __GLIBC_USE +#define __GLIBC_USE(x) 0 +#endif + +#if defined(__XCC__) || defined(__CHECKER__) /* XCC does not currently check alignment for packed data so no need for any * compiler hints. */ @@ -71,8 +241,13 @@ * alignment. This compiler builtin may not be available on all compilers so * this macro can be defined as NULL if needed. */ -#define ASSUME_ALIGNED(x, a) __builtin_assume_aligned(x, a) +#define ASSUME_ALIGNED(x, a) ((__typeof__(x))__builtin_assume_aligned((x), a)) #endif /* __XCC__ */ #endif /* __ASSEMBLER__ */ +#else /* LINKER */ + +#define ALIGN_UP_INTERNAL(val, align) (((val) + (align) - 1) & ~((align) - 1)) + +#endif /* LINKER */ #endif /* __SOF_COMMON_H__ */ diff --git a/src/include/sof/compiler_attributes.h b/src/include/sof/compiler_attributes.h deleted file mode 100644 index 97bd6dbb0bb2..000000000000 --- a/src/include/sof/compiler_attributes.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> - */ - -#define __packed __attribute__((packed)) - -#define __aligned(x) __attribute__((__aligned__(x))) - -#define __section(x) __attribute__((section(x))) diff --git a/src/include/sof/compiler_info.h b/src/include/sof/compiler_info.h deleted file mode 100644 index 4a3e2e514d90..000000000000 --- a/src/include/sof/compiler_info.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> - */ - -/** - * \file include/sof/compiler_info.h - * \brief Compiler version and name descriptor - * \author Karol Trzcinski <karolx.trzcinski@linux.intel.com> - */ - -#ifndef __SOF_COMPILER_INFO_H__ -#define __SOF_COMPILER_INFO_H__ - -#include <arch/compiler_info.h> - -#endif /* __SOF_COMPILER_INFO_H__ */ diff --git a/src/include/sof/debug/backtrace.h b/src/include/sof/debug/backtrace.h new file mode 100644 index 000000000000..d0f67161c3fb --- /dev/null +++ b/src/include/sof/debug/backtrace.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_DEBUG_BACKTRACE_H__ +#define __SOF_DEBUG_BACKTRACE_H__ + +#include <arch/debug/backtrace.h> + +#endif diff --git a/src/include/sof/debug/debug.h b/src/include/sof/debug/debug.h index af21639be1e9..76eec7062de3 100644 --- a/src/include/sof/debug/debug.h +++ b/src/include/sof/debug/debug.h @@ -10,14 +10,14 @@ #define __SOF_DEBUG_DEBUG_H__ #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/lib/cache.h> +#include <rtos/panic.h> +#include <rtos/cache.h> #include <sof/lib/cpu.h> -#include <sof/sof.h> -#include <sof/string.h> +#include <rtos/sof.h> +#include <rtos/string.h> #include <ipc/info.h> #include <ipc/trace.h> -#include <config.h> + #include <stddef.h> #include <stdint.h> @@ -33,9 +33,7 @@ #define DEBUG_SET_FW_READY_FLAGS \ ( \ SOF_IPC_INFO_BUILD | \ - (IS_ENABLED(CONFIG_DEBUG_LOCKS) ? SOF_IPC_INFO_LOCKS : 0) | \ - (IS_ENABLED(CONFIG_DEBUG_LOCKS_VERBOSE) ? SOF_IPC_INFO_LOCKSV : 0) | \ - (IS_ENABLED(CONFIG_GDB_DEBUG) ? SOF_IPC_INFO_GDB : 0) \ + (IS_ENABLED(CONFIG_GDB_DEBUG) ? SOF_IPC_INFO_GDB : 0) \ ) /* dump file and line to start of mailbox or shared memory */ @@ -124,9 +122,7 @@ #define DEBUG_SET_FW_READY_FLAGS \ ( \ - (IS_ENABLED(CONFIG_DEBUG_LOCKS) ? SOF_IPC_INFO_LOCKS : 0) | \ - (IS_ENABLED(CONFIG_DEBUG_LOCKS_VERBOSE) ? SOF_IPC_INFO_LOCKSV : 0) | \ - (IS_ENABLED(CONFIG_GDB_DEBUG) ? SOF_IPC_INFO_GDB : 0) \ + (IS_ENABLED(CONFIG_GDB_DEBUG) ? SOF_IPC_INFO_GDB : 0) \ ) #define dbg() do {} while (0) @@ -138,36 +134,42 @@ #define dump_object_ptr(__o) do {} while (0) #endif -/* dump stack as part of panic */ -static inline uint32_t dump_stack(uint32_t p, void *addr, size_t offset, - size_t limit, uintptr_t *stack_ptr) -{ - uintptr_t stack_limit = (uintptr_t)arch_get_stack_entry(); - uintptr_t stack_bottom = stack_limit + arch_get_stack_size() - - sizeof(void *); - uintptr_t stack_top = (uintptr_t)arch_get_stack_ptr() + offset; - size_t size = stack_bottom - stack_top; - int ret; - - *stack_ptr = stack_top; - - /* is stack smashed ? */ - if (stack_top - offset <= stack_limit) { - stack_bottom = stack_limit; - p = SOF_IPC_PANIC_STACK; - return p; - } - - /* make sure stack size won't overflow dump area */ - if (size > limit) - size = limit; - - /* copy stack contents and writeback */ - ret = memcpy_s(addr, limit, (void *)stack_top, size - sizeof(void *)); - assert(!ret); - dcache_writeback_region(addr, size - sizeof(void *)); - - return p; -} +/* swap an endianness of 32-bit word */ +#define bswap32(N) ({ \ + __typeof__(N) n = (N); \ + ((n & 0x000000FF) << 24) | \ + ((n & 0x0000FF00) << 8) | \ + ((n & 0x00FF0000) >> 8) | \ + ((n & 0xFF000000) >> 24); }) + +#if CONFIG_TRACE +/* dump up to 4 32-bit words into trace starting in ptr, idx is incremented inside + * unconditionally swaps endianness of data + * todo: use cpu_to_endianness so trace data will be independent of platform + */ +#define dump_hex(ptr, idx, len) \ + do { \ + __typeof__(idx) __i = (idx); \ + __typeof__(ptr) __p = (ptr) + __i; \ + __typeof__(idx) __l = (len) - __i; \ + __typeof__(idx) __n = __l > 4 ? 4 : __l; \ + if (__n == 4) { \ + comp_info(dev, "%08x%08x%08x%08x", bswap32(__p[0]), bswap32(__p[1]), \ + bswap32(__p[2]), bswap32(__p[3])); \ + } else if (__n == 3) { \ + comp_info(dev, "%08x%08x%08x", bswap32(__p[0]), bswap32(__p[1]), \ + bswap32(__p[2])); \ + } else if (__n == 2) { \ + comp_info(dev, "%08x%08x", bswap32(__p[0]), bswap32(__p[1])); \ + } else if (__n == 1) { \ + comp_info(dev, "%08x", bswap32(__p[0])); \ + } \ + idx += __n; \ + } while (0) +#else + +#define dump_hex() do {} while (0) + +#endif #endif /* __SOF_DEBUG_DEBUG_H__ */ diff --git a/src/include/sof/debug/gdb/gdb.h b/src/include/sof/debug/gdb/gdb.h index ac6abfb9a4a3..338b97b27541 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 <arch/debug/gdb/init.h> #include <arch/debug/gdb/utilities.h> @@ -28,6 +38,9 @@ void gdb_handle_exception(void); void gdb_debug_info(unsigned char *str); void gdb_init_debug_exception(void); + +#endif /* CONFIG_GDB_DEBUG */ + void gdb_init(void); #endif /* __SOF_DEBUG_GDB_GDB_H__ */ diff --git a/src/include/sof/debug/panic.h b/src/include/sof/debug/panic.h deleted file mode 100644 index 382ee23e1909..000000000000 --- a/src/include/sof/debug/panic.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_DEBUG_PANIC_H__ -#define __SOF_DEBUG_PANIC_H__ - -#include <arch/debug/panic.h> -#include <ipc/trace.h> -#include <stdint.h> - -#ifndef RELATIVE_FILE -#error "This file requires RELATIVE_FILE to be defined. " \ - "Add it to CMake's target with sof_append_relative_path_definitions." -#endif - -void dump_panicinfo(void *addr, struct sof_ipc_panic_info *panic_info); -void panic_rewind(uint32_t p, uint32_t stack_rewind_frames, - struct sof_ipc_panic_info *panic_info, uintptr_t *data); -#if __clang_analyzer__ -void __panic(uint32_t p, char *filename, uint32_t linenum) - __attribute__((analyzer_noreturn)); -#else -void __panic(uint32_t p, char *filename, uint32_t linenum); -#endif - -/* panic dump filename and linenumber of the call */ -#define panic(x) __panic((x), (RELATIVE_FILE), (__LINE__)) - -/* runtime assertion */ -#define assert(cond) (void)((cond) || (panic(SOF_IPC_PANIC_ASSERT), 0)) - -#endif /* __SOF_DEBUG_PANIC_H__ */ diff --git a/src/include/sof/debug/telemetry/performance_monitor.h b/src/include/sof/debug/telemetry/performance_monitor.h new file mode 100644 index 000000000000..337e353dafc4 --- /dev/null +++ b/src/include/sof/debug/telemetry/performance_monitor.h @@ -0,0 +1,295 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Tobiasz Dryjanski <tobiaszx.dryjanski@intel.com> + */ + +#ifndef __SOF_PERFORMANCE_MONITOR_H__ +#define __SOF_PERFORMANCE_MONITOR_H__ + +#include <ipc4/base_fw.h> + +/* to be moved to Zephyr */ +#define WIN3_MBASE DT_REG_ADDR(DT_PHANDLE(DT_NODELABEL(mem_window3), memory)) +#define ADSP_PMW ((volatile uint32_t *) \ + (sys_cache_uncached_ptr_get((__sparse_force void __sparse_cache *) \ + (WIN3_MBASE + WIN3_OFFSET)))) + +#if IS_ENABLED(CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS) +/** + * Initializer for struct perf_data_item_comp + * + * @param[out] perf Struct to be initialized + * @param[in] resource_id + * @param[in] power_mode + */ +void perf_data_item_comp_init(struct perf_data_item_comp *perf, uint32_t resource_id, + uint32_t power_mode); + +/** + * Get next free performance data slot from Memory Window 3 + * + * @return performance data record + */ +struct perf_data_item_comp *perf_data_getnext(void); + +/** + * Free a performance data slot in Memory Window 3 + * + * @return 0 if succeeded, in other case the slot is already free + */ +int free_performance_data(struct perf_data_item_comp *item); + +/** + * Set performance measurements state + * + * @param[in] state Value to be set. + */ +void perf_meas_set_state(enum ipc4_perf_measurements_state_set state); + +/** + * Get performance measurements state + * + * @return performance measurements state + */ +enum ipc4_perf_measurements_state_set perf_meas_get_state(void); + +/** + * Get global performance data entries. + * + * @param[out] global_perf_data Struct to be filled with data + * @return 0 if succeeded, error code otherwise. + */ +int get_performance_data(struct global_perf_data * const global_perf_data); + +/** + * Get extended global performance data entries. + * + * @param[out] ext_global_perf_data Struct to be filled with data + * @return 0 if succeeded, error code otherwise. + */ +int get_extended_performance_data(struct extended_global_perf_data * const ext_global_perf_data); + +/** + * Reset performance data values for all records. + * + * @return 0 if succeeded, error code otherwise. + */ +int reset_performance_counters(void); + +/** + * Reinitialize performance data values for all created components; + * + * @return 0 if succeeded, error code otherwise. + */ +int enable_performance_counters(void); + +/** + * Unregister performance data records marked for removal. + */ +void disable_performance_counters(void); + +#else + +static inline +void perf_data_item_comp_init(struct perf_data_item_comp *perf, uint32_t resource_id, + uint32_t power_mode) +{} + +static inline struct perf_data_item_comp *perf_data_getnext(void) +{ + return NULL; +} + +static inline +int free_performance_data(struct perf_data_item_comp *item) +{ + return 0; +} + +static inline void perf_meas_set_state(enum ipc4_perf_measurements_state_set state) {} + +static inline enum ipc4_perf_measurements_state_set perf_meas_get_state(void) +{ + return IPC4_PERF_MEASUREMENTS_DISABLED; +} + +static inline int get_performance_data(struct global_perf_data * const global_perf_data) +{ + return 0; +} + +static inline +int get_extended_performance_data(struct extended_global_perf_data * const ext_global_perf_data) +{ + return 0; +} + +static inline int reset_performance_counters(void) +{ + return 0; +} + +static inline int enable_performance_counters(void) +{ + return 0; +} + +static inline void disable_performance_counters(void) {} + +#endif + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + +struct io_perf_data_item { + /* ID of interface */ + uint32_t id : 8; + /* Instance of interface / bus */ + uint32_t instance : 8; + /* I/O direction from ACE perspective: 0 - Input, 1 - Output */ + uint32_t direction : 1; + /* I/O state: 0 - powered down / disabled, 1 - powered up / enabled */ + uint32_t state : 1; + /* Power Mode: 0 - D0, 1 - D0ix (clock gating enabled), */ + uint32_t power_mode : 2; + uint32_t rsvd : 11; + /* The component still exists (0) or has been already deleted (1) */ + uint32_t is_removed : 1; + /* Performance data */ + /* + * I/O (id) - ID - Units - Description + * + * Host IPC - 0 - Count - Counter of Host IPC messages incoming and outcoming + * IDC - 1 - Count - Counter of IDC messages incoming and outcoming per DSP core + * DMIC - 2 - Bytes - Counter of bytes transferred over DMIC interface + * I2S - 3 - Bytes - Counter of bytes transferred over I2S interface + * SoundWire - 4 - Bytes - Counter of bytes transferred over SoundWire interface + * HD/A - 5 - Bytes - Counter of bytes transferred over HD/A interface + * USB - 6 - Bytes - Counter of bytes transferred over USB interface + * GPIO - 7 - Count - Counter of GPIO interrupts or triggers + * I2C - 8 - Bytes - Counter of bytes transferred over I2C interface + * I3C - 9 - Bytes - Counter of bytes transferred over I3C interface + * I3C interrupt - 10 - Bytes - Counter of I3C interrupts + * UART - 11 - Bytes - Counter of bytes transferred over UART interface + * SPI - 12 - Bytes - Counter of bytes transferred over SPI interface + * CSI-2 - 13 - Bytes - Counter of bytes transferred over CSI-2 interface + * DTF - 14 - Bytes - Counter of bytes transferred over DTF interface + */ + uint64_t data; +} __packed; + +/* those below are used for bits in io_perf_data_item, it just uses 32bit vars specifically */ +enum io_perf_data_item_dir { + IO_PERF_INPUT_DIRECTION = 0, + IO_PERF_OUTPUT_DIRECTION = 1, +}; + +enum io_perf_data_item_state { + IO_PERF_POWERED_DOWN_DISABLED = 0, + IO_PERF_POWERED_UP_ENABLED = 1, +}; + +enum io_perf_data_item_power_mode { + IO_PERF_D0_POWER_MODE = 0, + IO_PERF_D0IX_POWER_MODE = 1, +}; + +enum io_perf_data_item_id { + IO_PERF_IPC_ID = 0, + IO_PERF_IDC_ID = 1, + IO_PERF_DMIC_ID = 2, + IO_PERF_I2S_ID = 3, + IO_PERF_SOUND_WIRE_ID = 4, + IO_PERF_HDA_ID = 5, + IO_PERF_USB_ID = 6, + IO_PERF_GPIO_ID = 7, + IO_PERF_I2C_ID = 8, + IO_PERF_I3C_ID = 9, + IO_PERF_I3C_INTERRUPT_ID = 10, + IO_PERF_UART_ID = 11, + IO_PERF_SPI_ID = 12, + IO_PERF_CSI_2_ID = 13, + IO_PERF_DTF_ID = 14, + IO_PERF_INVALID_ID = 0xFF +}; + +struct io_global_perf_data { + /* Number of statistics */ + uint32_t perf_item_count; + /* Performance statistics per I/O */ + struct io_perf_data_item perf_items[0]; +}; + +/* I/O Performance Monitor initialization. */ +/* + * @return ErrorCode + */ +int io_perf_monitor_init(void); + +/* Release slot */ +/* + * @param [in] slot_id pointer to io_perf_data_item + * @return ErrorCode + */ +int io_perf_monitor_release_slot(struct io_perf_data_item *slot_id); + +/* Get I/O performance data */ +/* + * @param [in] io_global_perf_data point to io_global_perf_data + * @return ErrorCode + */ +int +io_perf_monitor_get_performance_data(struct io_global_perf_data *io_global_perf_data); + +/* Set control state of I/o performance measurements process */ +/* + * @param [in] state a state to set + * @return ErrorCode + */ +int +io_perf_monitor_set_state(enum ipc4_perf_measurements_state_set state); + +/* Get control state of I/o performance measurements process */ +/* + * @return ipc4_perf_measurements_state_set + */ +enum ipc4_perf_measurements_state_set io_perf_monitor_get_state(void); + +/* Initialization of I/O performance data */ +/* + * @param [out] slot_id pointer to io_perf_data_item + * @param [in] init_data pointer to init data + */ +int io_perf_monitor_init_data(struct io_perf_data_item **slot_id, + struct io_perf_data_item *init_data); + +/* Update of I/O performance data */ +/* + * @param [in] slot_id pointer to io_perf_data_item + * @param [in] increment + * @note IMPORTANT: this function assumes each perf slot has only one user + * (use this only once per slot) + */ +void io_perf_monitor_update_data(struct io_perf_data_item *slot_id, + uint32_t increment); + +/* Update of I/0 state */ +/* + * @param [in] slot_id pointer to io_perf_data_item + * @param [in] power_up 0 - powered down / disabled, 1 - powered up / enabled + */ +void io_perf_monitor_update_io_state(struct io_perf_data_item *slot_id, + bool const power_up); + +/* Update of I/0 power mode */ +/* + * @param [in] slot_id pointer to io_perf_data_item + * @param [in] power_mode 0 - D0, 1 - D0ix (clock gating enabled) + */ +void io_perf_monitor_update_power_mode(struct io_perf_data_item *slot_id, + bool const power_mode); + +#endif //SUPPORTED(IO_PERFORMANCE_MEASUREMENTS) + +#endif diff --git a/src/include/sof/debug/telemetry/telemetry.h b/src/include/sof/debug/telemetry/telemetry.h new file mode 100644 index 000000000000..6c2d5fdf8cb7 --- /dev/null +++ b/src/include/sof/debug/telemetry/telemetry.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_TELEMETRY_H__ +#define __SOF_TELEMETRY_H__ + +#include <ipc4/base_fw.h> +#ifdef __ZEPHYR__ +#include <zephyr/timing/timing.h> +#endif + +#ifndef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +/* Slot in memory window 2 (Debug Window) to be used as telemetry slot */ +#define SOF_DW_TELEMETRY_SLOT 1 +#endif + +/* Memory of average algorithm of performance queue */ +#define SOF_AVG_PERF_MEAS_DEPTH 64 +/* Number of runs taken to calculate average (algorithm resolution) */ +#define SOF_AVG_PERF_MEAS_PERIOD 16 + +/* Systick here is not to be confused with neither Zephyr tick nor SOF scheduler tick, + * it's a legacy name for counting execution time + */ +struct system_tick_info { + uint32_t count; + uint32_t last_time_elapsed; + uint32_t max_time_elapsed; + uint32_t last_ccount; + uint32_t avg_utilization; + uint32_t peak_utilization; + uint32_t peak_utilization_4k; + uint32_t peak_utilization_8k; + uint32_t rsvd[2]; +} __packed; + +/* + * This is the structure of telemetry data in memory window. + * If you need to define a field, you should also define the fields before it to + * keep the internal structures aligned with each other. + */ +struct telemetry_wnd_data { + uint32_t separator_1; + struct system_tick_info system_tick_info[CONFIG_MAX_CORE_COUNT]; + /* + * uint32_t separator_2; + * deadlock_info_s deadlock_info[FW_REPORTED_MAX_CORES_COUNT]; + * uint32_t separator_3; + * assert_info_s assert_info; + * uint32_t separator_4; + * xxxruns_info_s xxxruns_info; + * uint32_t separator_5; + * performance_info_s performance_info; + * uint32_t separator_6; + * mem_pools_info_s mem_pools_info; + * uint32_t separator_7; + * timeout_info_s timeout_info; + * uint32_t separator_8; + * ulp_telemetry_s ulp_telemetry; + * uint32_t separator_9; + * transition_info_s evad_transition_info; + * uint32_t separator_10; + * task_info_s task_info[FW_MAX_REPORTED_TASKS]; + * uint32_t separator_11; + * transition_info_s d0i3_info[FW_REPORTED_MAX_CORES_COUNT]; + * uint32_t separator_12; + * interrupt_stats_info_s interrupt_stats; + * uint32_t separator_13; + * loaded_libraries_s loaded_libraries; + * //uint32_t __pad_for_exception_record; + * uint32_t separator_exception; + * CoreExceptionRecord core_exception_record[FW_REPORTED_MAX_CORES_COUNT]; + */ +} __packed; + +/* Reference FW used a normal Queue here. + * Implementing simplified queue just for avg calculation. + * Queue is circular, oldest element replaced by latest + */ +struct telemetry_perf_queue { + size_t elements[SOF_AVG_PERF_MEAS_DEPTH]; + /* next empty element, head if queue is full, else tail */ + size_t index; + uint8_t full; + /* number of items AND index of next empty box */ + size_t size; + size_t sum; +}; + +void telemetry_update(uint32_t begin_ccount, uint32_t current_ccount); +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +struct system_tick_info *telemetry_get_systick_info_ptr(void); +#endif + +#ifdef CONFIG_TIMING_FUNCTIONS +#define telemetry_timestamp timing_counter_get +#else +#define telemetry_timestamp sof_cycle_get_64 +#endif + +#endif /*__SOF_TELEMETRY_H__ */ diff --git a/src/include/sof/drivers/acp_dai_dma.h b/src/include/sof/drivers/acp_dai_dma.h new file mode 100644 index 000000000000..27dd08965516 --- /dev/null +++ b/src/include/sof/drivers/acp_dai_dma.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni<anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifndef __SOF_DRIVERS_ACPDMA_H__ +#define __SOF_DRIVERS_ACPDMA_H__ + +#include <ipc/dai.h> +#include <ipc/dai-amd.h> +#include <sof/lib/dai.h> +#include <rtos/bit.h> +#include <sof/trace/trace.h> +#include <user/trace.h> + +#if CONFIG_AMD_BT + #define ACP_BT_ENABLE +#endif + +#if CONFIG_AMD_SP + #define ACP_SP_ENABLE +#endif + +int acp_dma_init(struct sof *sof); + +#define ACP_DMA_BUFFER_PERIOD_COUNT 2 + +/* default max number of channels supported */ +#define ACP_DEFAULT_NUM_CHANNELS 2 + +/* default sample rate */ +#define ACP_DEFAULT_SAMPLE_RATE 48000 + +#define ACP_DMA_BUFFER_ALIGN 64 +#define ACP_DMA_BUFFER_ALIGN_128 128 +#define ACP_DMA_TRANS_SIZE 64 +#define ACP_DMA_TRANS_SIZE_128 128 +#define ACP_DAI_DMA_BUFFER_PERIOD_COUNT 2 +#define ACP_DRAM_ADDRESS_MASK 0x0FFFFFFF +#define ACP_ACLK_CLK_SEL 0x3 +#define ACP_INTERNAL_CLK_SEL 0x0 +#define ACP_DRAM_ADDR_TRNS 0x01000000 + +extern const struct dai_driver acp_spdai_driver; +extern const struct dai_driver acp_sp_virtual_dai_driver; +extern const struct dai_driver acp_btdai_driver; +extern const struct dai_driver acp_dmic_dai_driver; +extern const struct dai_driver acp_hsdai_driver; +extern const struct dai_driver acp_hs_virtual_dai_driver; +extern const struct dai_driver acp_swaudiodai_driver; + +/* ACP private data */ +struct acp_pdata { + struct sof_ipc_dai_config config; + struct sof_ipc_dai_acpdmic_params dmic_params; + struct sof_ipc_dai_acp_params params; + struct sof_ipc_dai_acp_sdw_params sdw_params; +}; +#endif /* __SOF_DRIVERS_ACPDMA_H__ */ diff --git a/src/include/sof/drivers/afe-dai.h b/src/include/sof/drivers/afe-dai.h new file mode 100644 index 000000000000..c40cb5ed8985 --- /dev/null +++ b/src/include/sof/drivers/afe-dai.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * YC Hung <yc.hung@mediatek.com> + */ + +#ifndef __SOF_DRIVERS_AFE_DAI_H__ +#define __SOF_DRIVERS_AFE_DAI_H__ + +#include <rtos/bit.h> +#include <sof/common.h> +#include <sof/lib/dma.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <stdint.h> + +#define AFE_HS_GET_DAI(hs) (((hs) & MASK(7, 0)) >> 0) +#define AFE_HS_SET_DAI(dai) SET_BITS(7, 0, dai) +#define AFE_HS_GET_IRQ(hs) (((hs) & MASK(15, 8)) >> 8) +#define AFE_HS_SET_IRQ(irq) SET_BITS(15, 8, irq) +#define AFE_HS_GET_CHAN(hs) (((hs) & MASK(23, 16)) >> 16) +#define AFE_HS_SET_CHAN(chan) SET_BITS(23, 16, chan) +#define AFE_HANDSHAKE(dai, irq, channel)\ + (AFE_HS_SET_DAI(dai) | AFE_HS_SET_CHAN(channel) | AFE_HS_SET_IRQ(irq)) + +extern const struct dai_driver afe_dai_driver; +#endif /* __SOF_DRIVERS_AFE_MEMIF_H__ */ + diff --git a/src/include/sof/drivers/afe-drv.h b/src/include/sof/drivers/afe-drv.h new file mode 100644 index 000000000000..cba2259b8e90 --- /dev/null +++ b/src/include/sof/drivers/afe-drv.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * YC Hung <yc.hung@mediatek.com> + */ + +#ifndef __SOF_DRIVERS_AFE_DRV_H__ +#define __SOF_DRIVERS_AFE_DRV_H__ + +struct mtk_base_memif_data { + int id; + const char *name; + int reg_ofs_base; + int reg_ofs_cur; + int reg_ofs_end; + int reg_ofs_base_msb; + int reg_ofs_cur_msb; + int reg_ofs_end_msb; + int fs_reg; + int fs_shift; + int fs_maskbit; + int mono_reg; + int mono_shift; + int mono_invert; + int quad_ch_reg; + int quad_ch_mask; + int quad_ch_shift; + int int_odd_flag_reg; + int int_odd_flag_shift; + int enable_reg; + int enable_shift; + int hd_reg; + int hd_shift; + int hd_align_reg; + int hd_align_mshift; + int msb_reg; + int msb_shift; + int msb2_reg; + int msb2_shift; + int agent_disable_reg; + int agent_disable_shift; + int ch_num_reg; + int ch_num_shift; + int ch_num_maskbit; + /* playback memif only */ + int pbuf_reg; + int pbuf_mask; + int pbuf_shift; + int minlen_reg; + int minlen_mask; + int minlen_shift; +}; + +struct mtk_base_irq_data { + int id; + int irq_cnt_reg; + int irq_cnt_shift; + int irq_cnt_maskbit; + int irq_fs_reg; + int irq_fs_shift; + int irq_fs_maskbit; + int irq_en_reg; + int irq_en_shift; + int irq_clr_reg; + int irq_clr_shift; + int irq_ap_en_reg; + int irq_ap_en_shift; + int irq_scp_en_reg; + int irq_scp_en_shift; +}; + +struct mtk_base_afe_memif { + unsigned int dma_addr; + unsigned int afe_addr; + unsigned int buffer_size; + + const struct mtk_base_memif_data *data; + int irq_usage; +}; + +struct mtk_base_afe_dai { + int id; + unsigned int channel; + unsigned int rate; + unsigned int format; + /* other? */ +}; + +struct mtk_base_afe_irq { + const struct mtk_base_irq_data *irq_data; + int mask; + int irq_occupyed; +}; + +struct mtk_base_afe { + int ref_count; + unsigned int base; + + struct mtk_base_afe_memif *memif; + int memifs_size; + int memif_32bit_supported; + int memif_dl_num; + + struct mtk_base_afe_irq *irqs; + int irqs_size; + + struct mtk_base_afe_dai *dais; + int dais_size; + + unsigned int (*afe2adsp_addr)(unsigned int addr); + unsigned int (*adsp2afe_addr)(unsigned int addr); + unsigned int (*afe_fs)(unsigned int rate, int aud_blk); + unsigned int (*irq_fs)(unsigned int rate); + + int base_end_offset; + + void *platform_priv; +}; + +/* platform information */ +struct mtk_base_afe_platform { + unsigned int base_addr; + const struct mtk_base_memif_data *memif_datas; + int memif_size; + int memif_32bit_supported; + int memif_dl_num; + + struct mtk_base_irq_data *irq_datas; + int irqs_size; + int dais_size; + + int base_end_offset; + + /* misc */ + unsigned int (*afe2adsp_addr)(unsigned int addr); + unsigned int (*adsp2afe_addr)(unsigned int addr); + unsigned int (*afe_fs)(unsigned int rate, int aud_blk); + unsigned int (*irq_fs)(unsigned int rate); +}; + +extern struct mtk_base_afe_platform mtk_afe_platform; + +struct mtk_base_afe *afe_get(void); +int afe_probe(struct mtk_base_afe *afe); +void afe_remove(struct mtk_base_afe *afe); + +/* dai operation */ +int afe_dai_get_config(struct mtk_base_afe *afe, int id, unsigned int *channel, unsigned int *rate, + unsigned int *format); +int afe_dai_set_config(struct mtk_base_afe *afe, int id, unsigned int channel, unsigned int rate, + unsigned int format); + +/* memif operation */ +int afe_memif_set_params(struct mtk_base_afe *afe, int id, unsigned int channel, unsigned int rate, + unsigned int format); +int afe_memif_set_addr(struct mtk_base_afe *afe, int id, unsigned int dma_addr, + unsigned int dma_bytes); +int afe_memif_set_enable(struct mtk_base_afe *afe, int id, int enable); +unsigned int afe_memif_get_cur_position(struct mtk_base_afe *afe, int id); +int afe_memif_get_direction(struct mtk_base_afe *afe, int id); + +/* irq opeartion */ +int afe_irq_get_status(struct mtk_base_afe *afe, int id); +int afe_irq_clear(struct mtk_base_afe *afe, int id); +int afe_irq_config(struct mtk_base_afe *afe, int id, unsigned int rate, unsigned int period); +int afe_irq_enable(struct mtk_base_afe *afe, int id); +int afe_irq_disable(struct mtk_base_afe *afe, int id); + +#endif /* __SOF_DRIVERS_AFE_DRV_H__ */ + diff --git a/src/include/sof/drivers/afe-memif.h b/src/include/sof/drivers/afe-memif.h new file mode 100644 index 000000000000..dba64f5d53fc --- /dev/null +++ b/src/include/sof/drivers/afe-memif.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * YC Hung <yc.hung@mediatek.com> + */ + +#ifndef __SOF_DRIVERS_AFE_MEMIF_H__ +#define __SOF_DRIVERS_AFE_MEMIF_H__ + +#include <rtos/bit.h> +#include <sof/common.h> +#include <sof/lib/dma.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <stdint.h> + +enum { + MEM_DIR_CAPTURE = 0, + MEM_DIR_PLAYBACK, +}; + +extern const struct dma_ops memif_ops; + +#endif /* __SOF_DRIVERS_AFE_MEMIF_H__ */ + diff --git a/src/include/sof/drivers/afe-sgen.h b/src/include/sof/drivers/afe-sgen.h new file mode 100644 index 000000000000..9d9919901daf --- /dev/null +++ b/src/include/sof/drivers/afe-sgen.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef __SOF_DRIVERS_AFE_SGEN_H__ +#define __SOF_DRIVERS_AFE_SGEN_H__ + +void afe_sinegen_enable(void); +void afe_sinegen_disable(void); + +#endif /* __SOF_DRIVERS_AFE_SGEN_H__ */ + diff --git a/src/include/sof/drivers/alh.h b/src/include/sof/drivers/alh.h deleted file mode 100644 index 189463bf1306..000000000000 --- a/src/include/sof/drivers/alh.h +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#ifndef __SOF_DRIVERS_ALH__ -#define __SOF_DRIVERS_ALH__ - -#include <platform/drivers/alh.h> -#include <sof/lib/dai.h> - -extern const struct dai_driver alh_driver; - -#endif /* __SOF_DRIVERS_ALH__ */ diff --git a/src/include/sof/drivers/cache_attr.h b/src/include/sof/drivers/cache_attr.h new file mode 100644 index 000000000000..1d7a156429ac --- /dev/null +++ b/src/include/sof/drivers/cache_attr.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Iuliana Prodan <iuliana.prodan@nxp.com> + */ + +#ifndef __SOF_DRIVERS_CACHE_ATTR_H__ +#define __SOF_DRIVERS_CACHE_ATTR_H__ + +#ifdef CONFIG_COMPILER_WORKAROUND_CACHE_ATTR + +#include <stdint.h> + +uint32_t glb_addr_attr(void *address); +uint32_t glb_is_cached(void *address); + +#endif /* CONFIG_COMPILER_WORKAROUND_CACHE_ATTR */ +#endif /* __SOF_DRIVERS_CACHE_ATTR_H__ */ diff --git a/src/include/sof/drivers/dmic.h b/src/include/sof/drivers/dmic.h index ad85ac977f23..154fd99351af 100644 --- a/src/include/sof/drivers/dmic.h +++ b/src/include/sof/drivers/dmic.h @@ -8,9 +8,24 @@ #ifndef __SOF_DRIVERS_DMIC_H__ #define __SOF_DRIVERS_DMIC_H__ -#include <config.h> +#if CONFIG_INTEL_DMIC -#if CONFIG_CAVS_DMIC +/* Let find up to 50 mode candidates to choose from */ +#define DMIC_MAX_MODES 50 + +/* Minimum OSR is always applied for 48 kHz and less sample rates */ +#define DMIC_MIN_OSR 50 + +/* These are used as guideline for configuring > 48 kHz sample rates. The + * minimum OSR can be relaxed down to 40 (use 3.84 MHz clock for 96 kHz). + */ +#define DMIC_HIGH_RATE_MIN_FS 64000 +#define DMIC_HIGH_RATE_OSR_MIN 40 + +/* HW FIR pipeline needs 5 additional cycles per channel for internal + * operations. This is used in MAX filter length check. + */ +#define DMIC_FIR_PIPELINE_OVERHEAD 5 /* The microphones create a low frequecy thump sound when clock is enabled. * The unmute linear gain ramp chacteristic is defined here. @@ -20,43 +35,25 @@ #define DMIC_UNMUTE_CIC 1 /* Unmute CIC at 1 ms */ #define DMIC_UNMUTE_FIR 2 /* Unmute FIR at 2 ms */ -#if CONFIG_APOLLOLAKE +#if CONFIG_TIGERLAKE #define DMIC_HW_VERSION 1 #define DMIC_HW_CONTROLLERS 2 -#define DMIC_HW_IOCLK 19200000 #define DMIC_HW_FIFOS 2 #endif -#if CONFIG_CANNONLAKE -#define DMIC_HW_VERSION 1 -#define DMIC_HW_CONTROLLERS 2 -#define DMIC_HW_IOCLK 24000000 -#define DMIC_HW_FIFOS 2 -#endif - -#if CONFIG_SUECREEK -#define DMIC_HW_VERSION 2 -#define DMIC_HW_CONTROLLERS 4 -#define DMIC_HW_IOCLK 19200000 -#define DMIC_HW_FIFOS 2 -#endif - -#if CONFIG_ICELAKE || CONFIG_TIGERLAKE -#define DMIC_HW_VERSION 1 -#define DMIC_HW_CONTROLLERS 2 -#define DMIC_HW_IOCLK 38400000 -#define DMIC_HW_FIFOS 2 -#endif +/* For NHLT DMIC configuration parsing */ +#define DMIC_HW_CONTROLLERS_MAX 4 +#define DMIC_HW_FIFOS_MAX 2 #endif #if DMIC_HW_VERSION +#include <ipc/dai-intel.h> #include <sof/audio/format.h> -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/lib/dai.h> -#include <sof/lib/wait.h> -#include <sof/schedule/task.h> +#include <rtos/wait.h> #include <stdint.h> /* Parameters used in modes computation */ @@ -124,7 +121,18 @@ /* Register bits */ -#if DMIC_HW_VERSION == 1 +/* OUTCONTROLx IPM bit fields style */ +#if DMIC_HW_VERSION == 1 || (DMIC_HW_VERSION == 2 && DMIC_HW_CONTROLLERS <= 2) +#define DMIC_IPM_VER1 +#elif DMIC_HW_VERSION == 2 && DMIC_HW_CONTROLLERS > 2 +#define DMIC_IPM_VER2 +#else +#error Not supported HW version +#endif + +#define OUTCONTROL0_BFTH_MAX 4 /* Max depth 16 */ + +#if defined DMIC_IPM_VER1 /* OUTCONTROL0 bits */ #define OUTCONTROL0_TIE_BIT BIT(27) #define OUTCONTROL0_SIP_BIT BIT(26) @@ -139,6 +147,15 @@ #define OUTCONTROL0_IPM(x) SET_BITS(17, 16, x) #define OUTCONTROL0_TH(x) SET_BITS(5, 0, x) +#define OUTCONTROL0_TIE_GET(x) GET_BIT(27, x) +#define OUTCONTROL0_SIP_GET(x) GET_BIT(26, x) +#define OUTCONTROL0_FINIT_GET(x) GET_BIT(25, x) +#define OUTCONTROL0_FCI_GET(x) GET_BIT(24, x) +#define OUTCONTROL0_BFTH_GET(x) GET_BITS(23, 20, x) +#define OUTCONTROL0_OF_GET(x) GET_BITS(19, 18, x) +#define OUTCONTROL0_IPM_GET(x) GET_BITS(17, 16, x) +#define OUTCONTROL0_TH_GET(x) GET_BITS(5, 0, x) + /* OUTCONTROL1 bits */ #define OUTCONTROL1_TIE_BIT BIT(27) #define OUTCONTROL1_SIP_BIT BIT(26) @@ -152,9 +169,18 @@ #define OUTCONTROL1_OF(x) SET_BITS(19, 18, x) #define OUTCONTROL1_IPM(x) SET_BITS(17, 16, x) #define OUTCONTROL1_TH(x) SET_BITS(5, 0, x) + +#define OUTCONTROL1_TIE_GET(x) GET_BIT(27, x) +#define OUTCONTROL1_SIP_GET(x) GET_BIT(26, x) +#define OUTCONTROL1_FINIT_GET(x) GET_BIT(25, x) +#define OUTCONTROL1_FCI_GET(x) GET_BIT(24, x) +#define OUTCONTROL1_BFTH_GET(x) GET_BITS(23, 20, x) +#define OUTCONTROL1_OF_GET(x) GET_BITS(19, 18, x) +#define OUTCONTROL1_IPM_GET(x) GET_BITS(17, 16, x) +#define OUTCONTROL1_TH_GET(x) GET_BITS(5, 0, x) #endif -#if DMIC_HW_VERSION == 2 +#if defined DMIC_IPM_VER2 /* OUTCONTROL0 bits */ #define OUTCONTROL0_TIE_BIT BIT(27) #define OUTCONTROL0_SIP_BIT BIT(26) @@ -171,7 +197,21 @@ #define OUTCONTROL0_IPM_SOURCE_2(x) SET_BITS(12, 11, x) #define OUTCONTROL0_IPM_SOURCE_3(x) SET_BITS(10, 9, x) #define OUTCONTROL0_IPM_SOURCE_4(x) SET_BITS(8, 7, x) +#define OUTCONTROL0_IPM_SOURCE_MODE(x) SET_BIT(6, x) #define OUTCONTROL0_TH(x) SET_BITS(5, 0, x) +#define OUTCONTROL0_TIE_GET(x) GET_BIT(27, x) +#define OUTCONTROL0_SIP_GET(x) GET_BIT(26, x) +#define OUTCONTROL0_FINIT_GET(x) GET_BIT(25, x) +#define OUTCONTROL0_FCI_GET(x) GET_BIT(24, x) +#define OUTCONTROL0_BFTH_GET(x) GET_BITS(23, 20, x) +#define OUTCONTROL0_OF_GET(x) GET_BITS(19, 18, x) +#define OUTCONTROL0_IPM_GET(x) GET_BITS(17, 15, x) +#define OUTCONTROL0_IPM_SOURCE_1_GET(x) GET_BITS(14, 13, x) +#define OUTCONTROL0_IPM_SOURCE_2_GET(x) GET_BITS(12, 11, x) +#define OUTCONTROL0_IPM_SOURCE_3_GET(x) GET_BITS(10, 9, x) +#define OUTCONTROL0_IPM_SOURCE_4_GET(x) GET_BITS(8, 7, x) +#define OUTCONTROL0_IPM_SOURCE_MODE_GET(x) GET_BIT(6, x) +#define OUTCONTROL0_TH_GET(x) GET_BITS(5, 0, x) /* OUTCONTROL1 bits */ #define OUTCONTROL1_TIE_BIT BIT(27) @@ -189,7 +229,21 @@ #define OUTCONTROL1_IPM_SOURCE_2(x) SET_BITS(12, 11, x) #define OUTCONTROL1_IPM_SOURCE_3(x) SET_BITS(10, 9, x) #define OUTCONTROL1_IPM_SOURCE_4(x) SET_BITS(8, 7, x) +#define OUTCONTROL1_IPM_SOURCE_MODE(x) SET_BIT(6, x) #define OUTCONTROL1_TH(x) SET_BITS(5, 0, x) +#define OUTCONTROL1_TIE_GET(x) GET_BIT(27, x) +#define OUTCONTROL1_SIP_GET(x) GET_BIT(26, x) +#define OUTCONTROL1_FINIT_GET(x) GET_BIT(25, x) +#define OUTCONTROL1_FCI_GET(x) GET_BIT(24, x) +#define OUTCONTROL1_BFTH_GET(x) GET_BITS(23, 20, x) +#define OUTCONTROL1_OF_GET(x) GET_BITS(19, 18, x) +#define OUTCONTROL1_IPM_GET(x) GET_BITS(17, 15, x) +#define OUTCONTROL1_IPM_SOURCE_1_GET(x) GET_BITS(14, 13, x) +#define OUTCONTROL1_IPM_SOURCE_2_GET(x) GET_BITS(12, 11, x) +#define OUTCONTROL1_IPM_SOURCE_3_GET(x) GET_BITS(10, 9, x) +#define OUTCONTROL1_IPM_SOURCE_4_GET(x) GET_BITS(8, 7, x) +#define OUTCONTROL1_IPM_SOURCE_MODE_GET(x) GET_BIT(6, x) +#define OUTCONTROL1_TH_GET(x) GET_BITS(5, 0, x) #define OUTCONTROLX_IPM_NUMSOURCES 4 @@ -226,10 +280,25 @@ #define CIC_CONTROL_MIC_MUTE(x) SET_BIT(1, x) #define CIC_CONTROL_STEREO_MODE(x) SET_BIT(0, x) +#define CIC_CONTROL_SOFT_RESET_GET(x) GET_BIT(16, x) +#define CIC_CONTROL_CIC_START_B_GET(x) GET_BIT(15, x) +#define CIC_CONTROL_CIC_START_A_GET(x) GET_BIT(14, x) +#define CIC_CONTROL_MIC_B_POLARITY_GET(x) GET_BIT(3, x) +#define CIC_CONTROL_MIC_A_POLARITY_GET(x) GET_BIT(2, x) +#define CIC_CONTROL_MIC_MUTE_GET(x) GET_BIT(1, x) +#define CIC_CONTROL_STEREO_MODE_GET(x) GET_BIT(0, x) + /* CIC_CONFIG bits */ #define CIC_CONFIG_CIC_SHIFT(x) SET_BITS(27, 24, x) #define CIC_CONFIG_COMB_COUNT(x) SET_BITS(15, 8, x) +/* CIC_CONFIG masks */ +#define CIC_CONFIG_CIC_SHIFT_MASK MASK(27, 24) +#define CIC_CONFIG_COMB_COUNT_MASK MASK(15, 8) + +#define CIC_CONFIG_CIC_SHIFT_GET(x) GET_BITS(27, 24, x) +#define CIC_CONFIG_COMB_COUNT_GET(x) GET_BITS(15, 8, x) + /* MIC_CONTROL bits */ #define MIC_CONTROL_PDM_EN_B_BIT BIT(1) #define MIC_CONTROL_PDM_EN_A_BIT BIT(0) @@ -239,6 +308,15 @@ #define MIC_CONTROL_PDM_EN_B(x) SET_BIT(1, x) #define MIC_CONTROL_PDM_EN_A(x) SET_BIT(0, x) +/* MIC_CONTROL masks */ +#define MIC_CONTROL_PDM_CLKDIV_MASK MASK(15, 8) + +#define MIC_CONTROL_PDM_CLKDIV_GET(x) GET_BITS(15, 8, x) +#define MIC_CONTROL_PDM_SKEW_GET(x) GET_BITS(7, 4, x) +#define MIC_CONTROL_PDM_CLK_EDGE_GET(x) GET_BIT(3, x) +#define MIC_CONTROL_PDM_EN_B_GET(x) GET_BIT(1, x) +#define MIC_CONTROL_PDM_EN_A_GET(x) GET_BIT(0, x) + /* FIR_CONTROL_A bits */ #define FIR_CONTROL_A_START_BIT BIT(7) #define FIR_CONTROL_A_ARRAY_START_EN_BIT BIT(6) @@ -249,11 +327,21 @@ #define FIR_CONTROL_A_MUTE(x) SET_BIT(1, x) #define FIR_CONTROL_A_STEREO(x) SET_BIT(0, x) +#define FIR_CONTROL_A_START_GET(x) GET_BIT(7, x) +#define FIR_CONTROL_A_ARRAY_START_EN_GET(x) GET_BIT(6, x) +#define FIR_CONTROL_A_DCCOMP_GET(x) GET_BIT(4, x) +#define FIR_CONTROL_A_MUTE_GET(x) GET_BIT(1, x) +#define FIR_CONTROL_A_STEREO_GET(x) GET_BIT(0, x) + /* FIR_CONFIG_A bits */ #define FIR_CONFIG_A_FIR_DECIMATION(x) SET_BITS(20, 16, x) #define FIR_CONFIG_A_FIR_SHIFT(x) SET_BITS(11, 8, x) #define FIR_CONFIG_A_FIR_LENGTH(x) SET_BITS(7, 0, x) +#define FIR_CONFIG_A_FIR_DECIMATION_GET(x) GET_BITS(20, 16, x) +#define FIR_CONFIG_A_FIR_SHIFT_GET(x) GET_BITS(11, 8, x) +#define FIR_CONFIG_A_FIR_LENGTH_GET(x) GET_BITS(7, 0, x) + /* DC offset compensation time constants */ #define DCCOMP_TC0 0 #define DCCOMP_TC1 1 @@ -286,11 +374,21 @@ #define FIR_CONTROL_B_MUTE(x) SET_BIT(1, x) #define FIR_CONTROL_B_STEREO(x) SET_BIT(0, x) +#define FIR_CONTROL_B_START_GET(x) GET_BIT(7, x) +#define FIR_CONTROL_B_ARRAY_START_EN_GET(x) GET_BIT(6, x) +#define FIR_CONTROL_B_DCCOMP_GET(x) GET_BIT(4, x) +#define FIR_CONTROL_B_MUTE_GET(x) GET_BIT(1, x) +#define FIR_CONTROL_B_STEREO_GET(x) GET_BIT(0, x) + /* FIR_CONFIG_B bits */ #define FIR_CONFIG_B_FIR_DECIMATION(x) SET_BITS(20, 16, x) #define FIR_CONFIG_B_FIR_SHIFT(x) SET_BITS(11, 8, x) #define FIR_CONFIG_B_FIR_LENGTH(x) SET_BITS(7, 0, x) +#define FIR_CONFIG_B_FIR_DECIMATION_GET(x) GET_BITS(20, 16, x) +#define FIR_CONFIG_B_FIR_SHIFT_GET(x) GET_BITS(11, 8, x) +#define FIR_CONFIG_B_FIR_LENGTH_GET(x) GET_BITS(7, 0, x) + /* DC_OFFSET_LEFT_B bits */ #define DC_OFFSET_LEFT_B_DC_OFFS(x) SET_BITS(21, 0, x) @@ -307,21 +405,158 @@ #define FIR_COEF_A(x) SET_BITS(19, 0, x) #define FIR_COEF_B(x) SET_BITS(19, 0, x) +/* Used for scaling FIR coefficients for HW */ +#define DMIC_HW_FIR_COEF_MAX ((1 << (DMIC_HW_BITS_FIR_COEF - 1)) - 1) +#define DMIC_HW_FIR_COEF_Q (DMIC_HW_BITS_FIR_COEF - 1) + +/* Internal precision in gains computation, e.g. Q4.28 in int32_t */ +#define DMIC_FIR_SCALE_Q 28 + +/* Used in unmute ramp values calculation */ +#define DMIC_HW_FIR_GAIN_MAX ((1 << (DMIC_HW_BITS_FIR_GAIN - 1)) - 1) + +/* Hardwired log ramp parameters. The first value is the initial gain in + * decibels. The default ramp time is provided by 1st order equation + * ramp time = coef * samplerate + offset. The default ramp is 200 ms for + * 48 kHz and 400 ms for 16 kHz. + */ +#define LOGRAMP_START_DB Q_CONVERT_FLOAT(-90, DB2LIN_FIXED_INPUT_QY) +#define LOGRAMP_TIME_COEF_Q15 -205 /* dy/dx (16000,400) (48000,200) */ +#define LOGRAMP_TIME_OFFS_Q0 500 /* Offset for line slope */ + +/* Limits for ramp time from topology */ +#define LOGRAMP_TIME_MIN_MS 10 /* Min. 10 ms */ +#define LOGRAMP_TIME_MAX_MS 1000 /* Max. 1s */ + +/* Simplify log ramp step calculation equation with this constant term */ +#define LOGRAMP_CONST_TERM ((int32_t) \ + ((int64_t)-LOGRAMP_START_DB * DMIC_UNMUTE_RAMP_US / 1000)) + +/* Fractional shift for gain update. Gain format is Q2.30. */ +#define Q_SHIFT_GAIN_X_GAIN_COEF \ + (Q_SHIFT_BITS_32(30, DB2LIN_FIXED_OUTPUT_QY, 30)) + #define dmic_irq(dmic) dmic->plat_data.irq #define dmic_irq_name(dmic) dmic->plat_data.irq_name +/* Common data for all DMIC DAI instances */ +struct dmic_global_shared { + struct sof_ipc_dai_dmic_params prm[DMIC_HW_FIFOS]; /* Configuration requests */ + uint32_t active_fifos_mask; /* Bits (dai->index) are set to indicate active FIFO */ + uint32_t pause_mask; /* Bits (dai->index) are set to indicate driver pause */ +}; + /* DMIC private data */ struct dmic_pdata { - uint16_t enable[DMIC_HW_CONTROLLERS]; - uint32_t state; - struct task dmicwork; - int32_t startcount; - int32_t gain; - int32_t gain_coef; - int irq; + struct dmic_global_shared *global; /* Common data for all DMIC DAI instances */ + uint16_t enable[DMIC_HW_CONTROLLERS]; /* Mic 0 and 1 enable bits array for PDMx */ + uint32_t state; /* Driver component state */ + int32_t startcount; /* Counter that controls HW unmute */ + int32_t gain_coef; /* Gain update constant */ + int32_t gain; /* Gain value to be applied to HW */ + int32_t unmute_ramp_time_ms; /* Unmute ramp time in milliseconds */ + int irq; /* Interrupt number used */ + enum sof_ipc_frame dai_format; /* PCM format s32_le etc. */ + int dai_channels; /* Channels count */ + int dai_rate; /* Sample rate in Hz */ +}; + +struct decim_modes { + int16_t clkdiv[DMIC_MAX_MODES]; + int16_t mcic[DMIC_MAX_MODES]; + int16_t mfir[DMIC_MAX_MODES]; + int num_of_modes; +}; + +struct matched_modes { + int16_t clkdiv[DMIC_MAX_MODES]; + int16_t mcic[DMIC_MAX_MODES]; + int16_t mfir_a[DMIC_MAX_MODES]; + int16_t mfir_b[DMIC_MAX_MODES]; + int num_of_modes; +}; + +struct dmic_configuration { + struct pdm_decim *fir_a; + struct pdm_decim *fir_b; + int clkdiv; + int mcic; + int mfir_a; + int mfir_b; + int cic_shift; + int fir_a_shift; + int fir_b_shift; + int fir_a_length; + int fir_b_length; + int32_t fir_a_scale; + int32_t fir_b_scale; +}; + +struct nhlt_dmic_gateway_attributes { + uint32_t dw; +}; + +struct nhlt_dmic_ts_group { + uint32_t ts_group[4]; }; +struct nhlt_dmic_clock_on_delay { + uint32_t clock_on_delay; +}; + +struct nhlt_dmic_channel_ctrl_mask { + uint32_t channel_ctrl_mask; +}; + +struct nhlt_pdm_ctrl_mask { + uint32_t pdm_ctrl_mask; +}; + +struct nhlt_pdm_ctrl_cfg { + uint32_t cic_control; + uint32_t cic_config; + uint32_t reserved0; + uint32_t mic_control; + uint32_t pdm_sdw_map; + uint32_t reuse_fir_from_pdm; + uint32_t reserved1[2]; +}; + +struct nhlt_pdm_ctrl_fir_cfg { + uint32_t fir_control; + uint32_t fir_config; + int32_t dc_offset_left; + int32_t dc_offset_right; + int32_t out_gain_left; + int32_t out_gain_right; + uint32_t reserved[2]; +}; + +struct nhlt_pdm_fir_coeffs { + int32_t fir_coeffs[0]; +}; + +int dmic_set_config_computed(struct dai *dai); +int dmic_get_hw_params_computed(struct dai *dai, struct sof_ipc_stream_params *params, int dir); +int dmic_set_config_nhlt(struct dai *dai, const void *spec_config); +int dmic_get_hw_params_nhlt(struct dai *dai, struct sof_ipc_stream_params *params, int dir); + extern const struct dai_driver dmic_driver; +static inline int dmic_get_unmute_ramp_from_samplerate(int rate) +{ + int32_t time_ms; + + time_ms = sat_int32(Q_MULTSR_32X32((int64_t)rate, LOGRAMP_TIME_COEF_Q15, 0, 15, 0) + + LOGRAMP_TIME_OFFS_Q0); + if (time_ms > LOGRAMP_TIME_MAX_MS) + return LOGRAMP_TIME_MAX_MS; + + if (time_ms < LOGRAMP_TIME_MIN_MS) + return LOGRAMP_TIME_MIN_MS; + + return time_ms; +} + #endif /* DMIC_HW_VERSION */ #endif /* __SOF_DRIVERS_DMIC_H__ */ diff --git a/src/include/sof/drivers/dw-dma.h b/src/include/sof/drivers/dw-dma.h index 92205e9079ff..fb4d9e5b0ba4 100644 --- a/src/include/sof/drivers/dw-dma.h +++ b/src/include/sof/drivers/dw-dma.h @@ -10,7 +10,7 @@ #define __SOF_DRIVERS_DW_DMA_H__ #include <platform/drivers/dw-dma.h> -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/common.h> #include <sof/lib/dma.h> #include <sof/trace/trace.h> @@ -127,16 +127,6 @@ #define DW_DMA_LLI_ADDRESS(lli, dir) \ (((dir) == DMA_DIR_MEM_TO_DEV) ? ((lli)->sar) : ((lli)->dar)) -/* tracing */ -#define trace_dwdma(__e, ...) \ - trace_event(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define trace_dwdma_atomic(__e, ...) \ - trace_event_atomic(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define tracev_dwdma(__e, ...) \ - tracev_event(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) -#define trace_dwdma_error(__e, ...) \ - trace_error(TRACE_CLASS_DMA, __e, ##__VA_ARGS__) - #define DW_DMA_BUFFER_ALIGNMENT 0x4 #define DW_DMA_COPY_ALIGNMENT 0x4 diff --git a/src/include/sof/drivers/edma.h b/src/include/sof/drivers/edma.h index f3a373a9874c..26039c188648 100644 --- a/src/include/sof/drivers/edma.h +++ b/src/include/sof/drivers/edma.h @@ -8,7 +8,7 @@ #ifndef __SOF_DRIVERS_EDMA_H__ #define __SOF_DRIVERS_EDMA_H__ -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/trace/trace.h> #include <user/trace.h> @@ -20,6 +20,7 @@ #define EDMA_CH_INT 0x08 #define EDMA_CH_SBR 0x0C #define EDMA_CH_PRI 0x10 +#define EDMA_CH_MUX 0x14 #define EDMA_TCD_SADDR 0x20 #define EDMA_TCD_SOFF 0x24 #define EDMA_TCD_ATTR 0x26 @@ -81,15 +82,10 @@ #define EDMA_HS_SET_IRQ(irq) SET_BITS(8, 0, irq) #define EDMA_HS_GET_CHAN(hs) (((hs) & MASK(13, 9)) >> 9) #define EDMA_HS_SET_CHAN(chan) SET_BITS(13, 9, chan) -#define EDMA_HANDSHAKE(irq, channel)\ - (EDMA_HS_SET_CHAN(channel) | EDMA_HS_SET_IRQ(irq)) - -#define trace_edma(format, ...) trace_event(TRACE_CLASS_DMA,\ - format, ##__VA_ARGS__) -#define tracev_edma(format, ...) tracev_event(TRACE_CLASS_DMA,\ - format, ##__VA_ARGS__) -#define trace_edma_error(format, ...) trace_error(TRACE_CLASS_DMA,\ - format, ##__VA_ARGS__) +#define EDMA_HS_GET_DMAMUX_CFG(hs) (((hs) & MASK(21, 14)) >> 14) +#define EDMA_HS_SET_DMAMUX_CFG(cfg) SET_BITS(21, 14, cfg) +#define EDMA_HANDSHAKE(irq, channel, cfg)\ + (EDMA_HS_SET_CHAN(channel) | EDMA_HS_SET_IRQ(irq) | EDMA_HS_SET_DMAMUX_CFG(cfg)) #define EDMA0_ESAI_CHAN_RX 6 #define EDMA0_ESAI_CHAN_TX 7 @@ -102,4 +98,54 @@ #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 +#define IMX8ULP_EDMA2_CHAN_MAX 8 + +/* EDMA provides one interrupt per channel */ +#define IMX8ULP_EDMA2_CHAN0_IRQ 6 +#define IMX8ULP_EDMA2_CHAN1_IRQ 7 +#define IMX8ULP_EDMA2_CHAN2_IRQ 8 +#define IMX8ULP_EDMA2_CHAN3_IRQ 9 +#define IMX8ULP_EDMA2_CHAN4_IRQ 10 +#define IMX8ULP_EDMA2_CHAN5_IRQ 11 +#define IMX8ULP_EDMA2_CHAN6_IRQ 12 +#define IMX8ULP_EDMA2_CHAN7_IRQ 13 + +/* i.MXULP uses a MUX configuration to map EDMA channels to IPs. + * This is a list with DMAMUX configuration for IPs used by SOF + */ +#define IMX8ULP_DMAMUX2_SAI5_RX 69 +#define IMX8ULP_DMAMUX2_SAI5_TX 70 +#define IMX8ULP_DMAMUX2_SAI6_RX 71 +#define IMX8ULP_DMAMUX2_SAI6_TX 72 + #endif /* __SOF_DRIVERS_EDMA_H__ */ diff --git a/src/include/sof/drivers/esai.h b/src/include/sof/drivers/esai.h index 7a49357f7aab..c71a2a566867 100644 --- a/src/include/sof/drivers/esai.h +++ b/src/include/sof/drivers/esai.h @@ -8,7 +8,7 @@ #ifndef __SOF_DRIVERS_ESAI_H__ #define __SOF_DRIVERS_ESAI_H__ -#include <sof/bit.h> +#include <rtos/bit.h> #include <sof/lib/dai.h> #include <sof/trace/trace.h> #include <user/trace.h> @@ -191,12 +191,5 @@ #define EDMA_ESAI_TX_CHAN 7 #define EDMA_ESAI_RX_CHAN 6 -#define trace_esai(format, ...) \ - trace_event(TRACE_CLASS_DAI, format, ##__VA_ARGS__) -#define tracev_esai(format, ...) \ - tracev_event(TRACE_CLASS_DAI, format, ##__VA_ARGS__) -#define trace_esai_error(format, ...) \ - trace_error(TRACE_CLASS_DAI, format, ##__VA_ARGS__) - extern const struct dai_driver esai_driver; #endif /* __SOF_DRIVERS_ESAI_H__ */ diff --git a/src/include/sof/drivers/hda.h b/src/include/sof/drivers/hda.h index fa8c5637efbc..a78bac3b624d 100644 --- a/src/include/sof/drivers/hda.h +++ b/src/include/sof/drivers/hda.h @@ -8,8 +8,13 @@ #ifndef __SOF_DRIVERS_HDA_H__ #define __SOF_DRIVERS_HDA_H__ +#include <ipc/dai-intel.h> #include <sof/lib/dai.h> +struct hda_pdata { + struct sof_ipc_dai_hda_params params; +}; + extern const struct dai_driver hda_driver; #endif /* __SOF_DRIVERS_HDA_H__ */ diff --git a/src/include/sof/drivers/idc.h b/src/include/sof/drivers/idc.h deleted file mode 100644 index 26350ba239a4..000000000000 --- a/src/include/sof/drivers/idc.h +++ /dev/null @@ -1,139 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file include/sof/drivers/idc.h - * \brief IDC header file - * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __SOF_DRIVERS_IDC_H__ -#define __SOF_DRIVERS_IDC_H__ - -#include <platform/drivers/idc.h> -#include <sof/lib/cpu.h> -#include <sof/schedule/task.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <stdbool.h> -#include <stdint.h> - -/** \brief IDC trace function. */ -#define trace_idc(__e, ...) \ - trace_event(TRACE_CLASS_IDC, __e, ##__VA_ARGS__) - -/** \brief IDC trace value function. */ -#define tracev_idc(__e, ...) \ - tracev_event(TRACE_CLASS_IDC, __e, ##__VA_ARGS__) - -/** \brief IDC trace error function. */ -#define trace_idc_error(__e, ...) \ - trace_error(TRACE_CLASS_IDC, __e, ##__VA_ARGS__) - -/** \brief IDC send blocking flag. */ -#define IDC_BLOCKING 0 - -/** \brief IDC send non-blocking flag. */ -#define IDC_NON_BLOCKING 1 - -/** \brief IDC send timeout in microseconds. */ -#define IDC_TIMEOUT 10000 - -/** \brief IDC task deadline. */ -#define IDC_DEADLINE 100 - -/** \brief ROM wake version parsed by ROM during core wake up. */ -#define IDC_ROM_WAKE_VERSION 0x2 - -/** \brief IDC message type. */ -#define IDC_TYPE_SHIFT 24 -#define IDC_TYPE_MASK 0x7f -#define IDC_TYPE(x) (((x) & IDC_TYPE_MASK) << IDC_TYPE_SHIFT) - -/** \brief IDC message header. */ -#define IDC_HEADER_MASK 0xffffff -#define IDC_HEADER(x) ((x) & IDC_HEADER_MASK) - -/** \brief IDC message extension. */ -#define IDC_EXTENSION_MASK 0x3fffffff -#define IDC_EXTENSION(x) ((x) & IDC_EXTENSION_MASK) - -/** \brief IDC power up message. */ -#define IDC_MSG_POWER_UP (IDC_TYPE(0x1) | \ - IDC_HEADER(IDC_ROM_WAKE_VERSION)) -#define IDC_MSG_POWER_UP_EXT IDC_EXTENSION(SOF_TEXT_START >> 2) - -/** \brief IDC power down message. */ -#define IDC_MSG_POWER_DOWN IDC_TYPE(0x2) -#define IDC_MSG_POWER_DOWN_EXT IDC_EXTENSION(0x0) - -/** \brief IDC notify message. */ -#define IDC_MSG_NOTIFY IDC_TYPE(0x3) -#define IDC_MSG_NOTIFY_EXT IDC_EXTENSION(0x0) - -/** \brief IDC IPC processing message. */ -#define IDC_MSG_IPC IDC_TYPE(0x4) -#define IDC_MSG_IPC_EXT IDC_EXTENSION(0x0) - -/** \brief IDC component params message. */ -#define IDC_MSG_PARAMS IDC_TYPE(0x5) -#define IDC_MSG_PARAMS_EXT(x) IDC_EXTENSION(x) - -/** \brief IDC component prepare message. */ -#define IDC_MSG_PREPARE IDC_TYPE(0x6) -#define IDC_MSG_PREPARE_EXT(x) IDC_EXTENSION(x) - -/** \brief IDC component trigger message. */ -#define IDC_MSG_TRIGGER IDC_TYPE(0x7) -#define IDC_MSG_TRIGGER_EXT(x) IDC_EXTENSION(x) - -/** \brief IDC component reset message. */ -#define IDC_MSG_RESET IDC_TYPE(0x8) -#define IDC_MSG_RESET_EXT(x) IDC_EXTENSION(x) - -/** \brief Decodes IDC message type. */ -#define iTS(x) (((x) >> IDC_TYPE_SHIFT) & IDC_TYPE_MASK) - -/** \brief Max IDC message payload size in bytes. */ -#define IDC_MAX_PAYLOAD_SIZE 96 - -/** \brief IDC message payload. */ -struct idc_payload { - uint8_t data[IDC_MAX_PAYLOAD_SIZE]; -}; - -/** \brief IDC message. */ -struct idc_msg { - uint32_t header; /**< header value */ - uint32_t extension; /**< extension value */ - uint32_t core; /**< core id */ - uint32_t size; /**< payload size in bytes */ - void *payload; /**< pointer to payload data */ -}; - -/** \brief IDC data. */ -struct idc { - uint32_t busy_bit_mask; /**< busy interrupt mask */ - uint32_t done_bit_mask; /**< done interrupt mask */ - struct idc_msg received_msg; /**< received message */ - struct task idc_task; /**< IDC processing task */ - bool msg_processed[PLATFORM_CORE_COUNT]; - struct idc_payload *payload; - int irq; -}; - -static inline struct idc_payload *idc_payload_get(struct idc *idc, - uint32_t core) -{ - return idc->payload + core; -} - -void idc_enable_interrupts(int target_core, int source_core); - -void idc_free(void); - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/include/sof/drivers/interrupt-map.h b/src/include/sof/drivers/interrupt-map.h index 5cf9d1bcc1dc..7a2a6fd314bd 100644 --- a/src/include/sof/drivers/interrupt-map.h +++ b/src/include/sof/drivers/interrupt-map.h @@ -8,8 +8,6 @@ #ifndef __SOF_DRIVERS_INTERRUPT_MAP_H__ #define __SOF_DRIVERS_INTERRUPT_MAP_H__ -#include <config.h> - #define SOF_IRQ_PASSIVE_LEVEL 0 #define SOF_IRQ_ID_SHIFT 29 #define SOF_IRQ_BIT_SHIFT 24 @@ -40,7 +38,7 @@ | ((_cpu) << SOF_IRQ_CPU_SHIFT) \ | ((_number) << SOF_IRQ_NUM_SHIFT)) -#if CONFIG_IRQ_MAP +#if CONFIG_XT_IRQ_MAP /* * IRQs are mapped on 4 levels. * diff --git a/src/include/sof/drivers/interrupt.h b/src/include/sof/drivers/interrupt.h deleted file mode 100644 index d1233e9632b8..000000000000 --- a/src/include/sof/drivers/interrupt.h +++ /dev/null @@ -1,182 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifndef __SOF_DRIVERS_INTERRUPT_H__ -#define __SOF_DRIVERS_INTERRUPT_H__ - -#include <arch/drivers/interrupt.h> -#include <platform/drivers/interrupt.h> -#include <sof/lib/cpu.h> -#include <sof/list.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <stdbool.h> -#include <stdint.h> - -#define trace_irq(__e) trace_event(TRACE_CLASS_IRQ, __e) -#define trace_irq_error(__e, ...) \ - trace_error(TRACE_CLASS_IRQ, __e, ##__VA_ARGS__) - -/** - * \brief child IRQ descriptor for cascading IRQ controllers. - */ -struct irq_child { - int enable_count[PLATFORM_CORE_COUNT]; /**< IRQ enable counter */ - struct list_item list; /**< head for IRQ descriptors, - * sharing this interrupt - */ -}; - -/** - * \brief interrupt client descriptor - */ -struct irq_desc { - int irq; /**< virtual IRQ number */ - void (*handler)(void *arg); /**< interrupt handler function */ - void *handler_arg; /**< interrupt handler argument */ - uint32_t cpu_mask; /**< a mask of CPUs on which this - * interrupt is enabled - */ - struct list_item irq_list; /**< to link to other irq_desc */ -}; - -/** - * \brief cascading IRQ controller operations. - */ -struct irq_cascade_ops { - void (*mask)(struct irq_desc *desc, uint32_t irq, - unsigned int cpu); /**< mask */ - void (*unmask)(struct irq_desc *desc, uint32_t irq, - unsigned int cpu); /**< unmask */ -}; - -/** - * \brief cascading interrupt controller descriptor. - */ -struct irq_cascade_desc { - const char *name; /**< name of the - * controller - */ - int irq_base; /**< first virtual IRQ - * number, assigned to - * this controller - */ - const struct irq_cascade_ops *ops; /**< cascading interrupt - * controller driver - * operations - */ - struct irq_desc desc; /**< the interrupt, that - * this controller is - * generating - */ - struct irq_cascade_desc *next; /**< link to the global - * list of interrupt - * controllers - */ - bool global_mask; /**< the controller - * cannot mask input - * interrupts per core - */ - spinlock_t lock; /**< protect child - * lists, enable and - * child counters - */ - int enable_count[PLATFORM_CORE_COUNT]; /**< enabled child - * interrupt counter - */ - unsigned int num_children[PLATFORM_CORE_COUNT]; /**< number of children - */ - struct irq_child child[PLATFORM_IRQ_CHILDREN]; /**< array of child - * lists - one per - * multiplexed IRQ - */ -}; - -/* A descriptor for cascading interrupt controller template */ -struct irq_cascade_tmpl { - const char *name; - const struct irq_cascade_ops *ops; - int irq; - void (*handler)(void *arg); - bool global_mask; -}; - -/** - * \brief Cascading interrupt controller root. - */ -struct cascade_root { - spinlock_t lock; /**< locking mechanism */ - struct irq_cascade_desc *list; /**< list of child cascade irqs */ - int last_irq; /**< last registered cascade irq */ -}; - -static inline struct cascade_root *cascade_root_get(void) -{ - return sof_get()->cascade_root; -} - -int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); -void interrupt_unregister(uint32_t irq, const void *arg); -uint32_t interrupt_enable(uint32_t irq, void *arg); -uint32_t interrupt_disable(uint32_t irq, void *arg); - -void platform_interrupt_init(void); - -void platform_interrupt_set(uint32_t irq); -void platform_interrupt_clear(uint32_t irq, uint32_t mask); -uint32_t platform_interrupt_get_enabled(void); -void interrupt_mask(uint32_t irq, unsigned int cpu); -void interrupt_unmask(uint32_t irq, unsigned int cpu); - -/* - * On platforms, supporting cascading interrupts cascaded interrupt numbers - * are greater than or equal to PLATFORM_IRQ_HW_NUM - */ -#define interrupt_is_dsp_direct(irq) (!PLATFORM_IRQ_CHILDREN || \ - irq < PLATFORM_IRQ_HW_NUM) - -void interrupt_init(struct sof *sof); -int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl); -struct irq_cascade_desc *interrupt_get_parent(uint32_t irq); -int interrupt_get_irq(unsigned int irq, const char *cascade); - -static inline void interrupt_set(int irq) -{ - platform_interrupt_set(irq); -} - -static inline void interrupt_clear_mask(int irq, uint32_t mask) -{ - platform_interrupt_clear(irq, mask); -} - -static inline void interrupt_clear(int irq) -{ - interrupt_clear_mask(irq, 1); -} - -static inline uint32_t interrupt_global_disable(void) -{ - return arch_interrupt_global_disable(); -} - -static inline void interrupt_global_enable(uint32_t flags) -{ - arch_interrupt_global_enable(flags); -} - -/* disables all IRQ sources on current core */ -#define irq_local_disable(flags) \ - (flags = interrupt_global_disable()) - -/* re-enables IRQ sources on current core */ -#define irq_local_enable(flags) \ - interrupt_global_enable(flags) - -#endif /* __SOF_DRIVERS_INTERRUPT_H__ */ diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h deleted file mode 100644 index 67d2479e0e23..000000000000 --- a/src/include/sof/drivers/ipc.h +++ /dev/null @@ -1,359 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_DRIVERS_IPC_H__ -#define __SOF_DRIVERS_IPC_H__ - -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/control.h> -#include <ipc/header.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <ipc/trace.h> -#include <user/trace.h> -#include <stdbool.h> -#include <stdint.h> - -struct comp_buffer; -struct comp_dev; -struct dai_config; -struct dma; -struct dma_sg_elem_array; -struct pipeline; -struct sof; -struct sof_ipc_buffer; -struct sof_ipc_comp; -struct sof_ipc_comp_event; -struct sof_ipc_dai_config; -struct sof_ipc_host_buffer; -struct sof_ipc_pipe_comp_connect; -struct sof_ipc_pipe_new; -struct sof_ipc_stream_posn; -struct ipc_msg; - -#define trace_ipc(format, ...) \ - trace_event(TRACE_CLASS_IPC, format, ##__VA_ARGS__) -#define tracev_ipc(format, ...) \ - tracev_event(TRACE_CLASS_IPC, format, ##__VA_ARGS__) -#define trace_ipc_error(format, ...) \ - trace_error(TRACE_CLASS_IPC, format, ##__VA_ARGS__) - -#define COMP_TYPE_COMPONENT 1 -#define COMP_TYPE_BUFFER 2 -#define COMP_TYPE_PIPELINE 3 - -/* validates internal non tail structures within IPC command structure */ -#define IPC_IS_SIZE_INVALID(object) \ - (object).hdr.size == sizeof(object) ? 0 : 1 - -/* convenience error trace for mismatched internal structures */ -#define IPC_SIZE_ERROR_TRACE(class, object) \ - trace_error(class, "ipc: size %d expected %d", \ - (object).hdr.size, sizeof(object)) - -/* IPC generic component device */ -struct ipc_comp_dev { - uint16_t type; /* COMP_TYPE_ */ - uint16_t core; - uint32_t id; - - /* component type data */ - union { - struct comp_dev *cd; - struct comp_buffer *cb; - struct pipeline *pipeline; - }; - - /* lists */ - struct list_item list; /* list in components */ -}; - -struct ipc_msg { - uint32_t header; /* specific to platform */ - uint32_t tx_size; /* payload size in bytes */ - void *tx_data; /* pointer to payload data */ - struct list_item list; -}; - -struct ipc { - spinlock_t lock; /* locking mechanism */ - void *comp_data; - - /* PM */ - int pm_prepare_D3; /* do we need to prepare for D3 */ - - struct list_item msg_list; /* queue of messages to be sent */ - bool is_notification_pending; /* notification is being sent to host */ - - struct list_item comp_list; /* list of component devices */ - - /* processing task */ - struct task ipc_task; - - void *private; -}; - -#define ipc_set_drvdata(ipc, data) \ - ((ipc)->private = data) -#define ipc_get_drvdata(ipc) \ - ((ipc)->private) - -extern struct task_ops ipc_task_ops; - -static inline struct ipc *ipc_get(void) -{ - return sof_get()->ipc; -} - -static inline uint64_t ipc_task_deadline(void *data) -{ - /* TODO: Currently it's a workaround to execute IPC tasks ASAP. - * In the future IPCs should have a cycle budget and deadline - * should be calculated based on that value. This means every - * IPC should have its own maximum number of cycles that is required - * to finish processing. This will allow us to calculate task deadline. - */ - return SOF_TASK_DEADLINE_NOW; -} - -static inline void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, - uint32_t type, uint32_t id) -{ - posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | type | id; - posn->rhdr.hdr.size = sizeof(*posn); - posn->comp_id = id; -} - -static inline void ipc_build_comp_event(struct sof_ipc_comp_event *event, - uint32_t type, uint32_t id) -{ - event->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | SOF_IPC_COMP_NOTIFICATION | - id; - event->rhdr.hdr.size = sizeof(*event); - event->src_comp_type = type; - event->src_comp_id = id; -} - -static inline void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn) -{ - posn->rhdr.hdr.cmd = SOF_IPC_GLB_TRACE_MSG | - SOF_IPC_TRACE_DMA_POSITION; - posn->rhdr.hdr.size = sizeof(*posn); -} - -static inline struct ipc_msg *ipc_msg_init(uint32_t header, uint32_t size) -{ - struct ipc_msg *msg; - - msg = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*msg)); - if (!msg) - return NULL; - - msg->tx_data = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, size); - if (!msg->tx_data) { - rfree(msg); - return NULL; - } - - msg->header = header; - msg->tx_size = size; - list_init(&msg->list); - - platform_shared_commit(msg, sizeof(*msg)); - - return msg; -} - -static inline void ipc_msg_free(struct ipc_msg *msg) -{ - if (!msg) - return; - - struct ipc *ipc = ipc_get(); - uint32_t flags; - - spin_lock_irq(&ipc->lock, flags); - - list_item_del(&msg->list); - rfree(msg->tx_data); - rfree(msg); - - platform_shared_commit(ipc, sizeof(*ipc)); - - spin_unlock_irq(&ipc->lock, flags); -} - -int ipc_init(struct sof *sof); - -/** - * \brief Provides platform specific IPC initialization. - * @param ipc Global IPC context - * @return 0 if succeeded, error code otherwise. - * - * This function must be implemented by the platform. It is called from the - * main IPC code, at the end of ipc_init(). - * - * If the platform requires any private data to be associated with the IPC - * context, it may allocate it here and attach to the global context using - * ipc_set_drvdata(). Other platform specific IPC functions, like - * ipc_platform_do_cmd(), may obtain it later from the context using - * ipc_get_drvdata(). - */ -int platform_ipc_init(struct ipc *ipc); - -enum task_state ipc_platform_do_cmd(void *data); - -void ipc_platform_complete_cmd(void *data); - -void ipc_free(struct ipc *ipc); - -void ipc_schedule_process(struct ipc *ipc); - -int ipc_platform_send_msg(struct ipc_msg *msg); - -void ipc_send_queued_msg(void); - -void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority); - -/** - * \brief Data provided by the platform which use ipc...page_descriptors(). - * - * Note: this should be made private for ipc-host-ptable.c and ipc - * drivers for platforms that use ptables. - */ -struct ipc_data_host_buffer { - /* DMA */ - struct dma *dmac; - uint8_t *page_table; -}; - -/** - * \brief Retrieves the ipc_data_host_buffer allocated by the platform ipc. - * @return Pointer to the data. - * - * This function must be implemented by platforms which use - * ipc...page_descriptors() while processing host page tables. - */ -struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc); - -/** - * \brief Processes page tables for the host buffer. - * @param[in] ipc Ipc - * @param[in] ring Ring description sent via Ipc - * @param[in] direction Direction (playback/capture) - * @param[out] elem_array Array of SG elements - * @param[out] ring_size Size of the ring - * @return Status, 0 if successful, error code otherwise. - */ -int ipc_process_host_buffer(struct ipc *ipc, - struct sof_ipc_host_buffer *ring, - uint32_t direction, - struct dma_sg_elem_array *elem_array, - uint32_t *ring_size); - -/* - * IPC Component creation and destruction. - */ -int ipc_comp_new(struct ipc *ipc, struct sof_ipc_comp *new); -int ipc_comp_free(struct ipc *ipc, uint32_t comp_id); - -/* - * IPC Buffer creation and destruction. - */ -int ipc_buffer_new(struct ipc *ipc, struct sof_ipc_buffer *buffer); -int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id); - -/* - * IPC Pipeline creation and destruction. - */ -int ipc_pipeline_new(struct ipc *ipc, struct sof_ipc_pipe_new *pipeline); -int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id); -int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id); - -/* - * Pipeline component and buffer connections. - */ -int ipc_comp_connect(struct ipc *ipc, - struct sof_ipc_pipe_comp_connect *connect); - -/* - * Get component by ID. - */ -struct ipc_comp_dev *ipc_get_comp_by_id(struct ipc *ipc, uint32_t id); - -/* - * Get component by pipeline ID. - */ -struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, - uint32_t ppl_id); - -/* - * Configure all DAI components attached to DAI. - */ -int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config); - -/* send DMA trace host buffer position to host */ -int ipc_dma_trace_send_position(void); - -struct sof_ipc_cmd_hdr *mailbox_validate(void); - -/** - * Generic IPC command handler. Expects that IPC command (the header plus - * any optional payload) is deserialized from the IPC HW by the platform - * specific method. - * - * @param hdr Points to the IPC command header. - */ -void ipc_cmd(struct sof_ipc_cmd_hdr *hdr); - -/** - * \brief IPC message to be processed on other core. - * @param[in] core Core id for IPC to be processed on. - * @return 1 if successful (reply sent by other core), error code otherwise. - */ -int ipc_process_on_core(uint32_t core); - -/** - * \brief Initialise IPC hardware for polling mode. - * @return 0 if successful error code otherwise. - */ -int ipc_platform_poll_init(void); - -/** - * \brief Tell host DSP has completed command. - */ -void ipc_platform_poll_set_cmd_done(void); - -/** - * \brief Check whether there is a new IPC command from host. - * @return 1 if new command is pending from host. - */ -int ipc_platform_poll_is_cmd_pending(void); - -/** - * \brief Check whether host is ready for new IPC from DSP. - * @return 1 if host is ready for a new command from DSP. - */ -int ipc_platform_poll_is_host_ready(void); - -/** - * \brief Transmit new message to host. - * @return 0 if successful error code otherwise. - */ -int ipc_platform_poll_tx_host_msg(struct ipc_msg *msg); - -#endif /* __SOF_DRIVERS_IPC_H__ */ diff --git a/src/include/sof/drivers/micfil.h b/src/include/sof/drivers/micfil.h new file mode 100644 index 000000000000..5d6828102c97 --- /dev/null +++ b/src/include/sof/drivers/micfil.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + * + * Author: Daniel Baluta <daniel.baluta@nxp.com> + */ + +#ifndef __SOF_DRIVERS_MICFIL_H__ +#define __SOF_DRIVERS_MICFIL_H__ + +#include <rtos/bit.h> +#include <ipc/dai.h> +#include <ipc/dai-imx.h> +#include <sof/lib/dai.h> +#include <sof/trace/trace.h> +#include <user/trace.h> + +extern const struct dai_driver micfil_driver; + +/* MICFIL private data */ +struct micfil_pdata { + int quality; + struct sof_ipc_dai_config config; + struct sof_ipc_dai_micfil_params params; +}; + +/* MICFIL Register Map */ +#define REG_MICFIL_CTRL1 0x00 +#define REG_MICFIL_CTRL2 0x04 +#define REG_MICFIL_STAT 0x08 +#define REG_MICFIL_FIFO_CTRL 0x10 +#define REG_MICFIL_FIFO_STAT 0x14 +#define REG_MICFIL_DATACH0 0x24 +#define REG_MICFIL_DATACH1 0x28 +#define REG_MICFIL_DATACH2 0x2C +#define REG_MICFIL_DATACH3 0x30 +#define REG_MICFIL_DATACH4 0x34 +#define REG_MICFIL_DATACH5 0x38 +#define REG_MICFIL_DATACH6 0x3C +#define REG_MICFIL_DATACH7 0x40 +#define REG_MICFIL_DC_CTRL 0x64 +#define REG_MICFIL_OUT_CTRL 0x74 +#define REG_MICFIL_OUT_STAT 0x7C +#define REG_MICFIL_VAD0_CTRL1 0x90 +#define REG_MICFIL_VAD0_CTRL2 0x94 + +#define REG_MICFIL_VAD0_STAT 0x98 +#define REG_MICFIL_VAD0_SCONFIG 0x9C +#define REG_MICFIL_VAD0_NCONFIG 0xA0 +#define REG_MICFIL_VAD0_NDATA 0xA4 +#define REG_MICFIL_VAD0_ZCD 0xA8 + +/* MICFIL Control Register 1 -- REG_MICFILL_CTRL1 0x00 */ +#define MICFIL_CTRL1_MDIS BIT(31) +#define MICFIL_CTRL1_DOZEN BIT(30) +#define MICFIL_CTRL1_PDMIEN BIT(29) +#define MICFIL_CTRL1_DBG BIT(28) +#define MICFIL_CTRL1_SRES BIT(27) +#define MICFIL_CTRL1_DBGE BIT(26) +#define MICFIL_CTRL1_CHNEN MASK(7, 0) + +#define MICFIL_CTRL1_DISEL_DISABLE 0 +#define MICFIL_CTRL1_DISEL_DMA 1 +#define MICFIL_CTRL1_DISEL_IRQ 2 +#define MICFIL_CTRL1_DISEL_BITS(x) SET_BITS(25, 24, x) +#define MICFIL_CTRL1_DISEL MASK(25, 24) +#define MICFIL_CTRL1_ERREN BIT(23) +#define MICFIL_CTRL1_CHEN(ch) BIT(ch) + +/* MICFIL Control Register 2 -- REG_MICFILL_CTRL2 0x04 */ +#define MICFIL_CTRL2_QSEL_SHIFT 25 +#define MICFIL_CTRL2_QSEL MASK(27, 25) +#define MICFIL_CTRL2_QSEL_BITS(x) SET_BITS(27, 25, x) +#define MICFIL_QSEL_MEDIUM_QUALITY 0 +#define MICFIL_QSEL_HIGH_QUALITY 1 +#define MICFIL_QSEL_LOW_QUALITY 7 +#define MICFIL_QSEL_VLOW0_QUALITY 6 +#define MICFIL_QSEL_VLOW1_QUALITY 5 +#define MICFIL_QSEL_VLOW2_QUALITY 4 + +#define MICFIL_CTRL2_CICOSR MASK(19, 16) +#define MICFIL_CTRL2_CICOSR_SHIFT 16 +#define MICFIL_CTRL2_CICOSR_BITS(x) SET_BITS(19, 16, x) +#define MICFIL_CTRL2_CLKDIV MASK(7, 0) +#define MICFIL_CTRL2_CLKDIV_BITS(x) SET_BITS(7, 0, x) + +/* MICFIL Status Register -- REG_MICFIL_STAT 0x08 */ +#define MICFIL_STAT_BSY_FIL BIT(31) +#define MICFIL_STAT_FIR_RDY BIT(30) +#define MICFIL_STAT_LOWFREQF BIT(29) +#define MICFIL_STAT_CHXF(ch) BIT(ch) + +/* MICFIL FIFO Control Register -- REG_MICFIL_FIFO_CTRL 0x10 */ +#define MICFIL_FIFO_CTRL_FIFOWMK MASK(2, 0) +#define MICFIL_FIFO_CTRL_FIFOWMK_BITS(x) SET_BITS(2, 0, x) + +/* MICFIL FIFO Status Register -- REG_MICFIL_FIFO_STAT 0x14 */ +#define MICFIL_FIFO_STAT_FIFOX_OVER(ch) BIT(ch) +#define MICFIL_FIFO_STAT_FIFOX_UNDER(ch) BIT((ch) + 8) + +/* MICFIL DC Remover Control Register -- REG_MICFIL_DC_CTRL */ +#define MICFIL_DC_CTRL_CONFIG MASK(15, 0) +#define MICFIL_DC_CHX_SHIFT(ch) ((ch) << 1) +#define MICFIL_DC_CHX(ch) MASK((((ch) << 1) + 1), ((ch) << 1)) +#define MICFIL_DC_CUTOFF_21HZ 0 +#define MICFIL_DC_CUTOFF_83HZ 1 +#define MICFIL_DC_CUTOFF_152Hz 2 +#define MICFIL_DC_BYPASS 3 + +/* MICFIL HWVAD0 Control 1 Register -- REG_MICFIL_VAD0_CTRL1*/ +#define MICFIL_VAD0_CTRL1_CHSEL MASK(26, 24) +#define MICFIL_VAD0_CTRL1_CICOSR MASK(19, 16) +#define MICFIL_VAD0_CTRL1_INITT MASK(12, 8) +#define MICFIL_VAD0_CTRL1_ST10 BIT(4) +#define MICFIL_VAD0_CTRL1_ERIE BIT(3) +#define MICFIL_VAD0_CTRL1_IE BIT(2) +#define MICFIL_VAD0_CTRL1_RST BIT(1) +#define MICFIL_VAD0_CTRL1_EN BIT(0) + +/* MICFIL HWVAD0 Control 2 Register -- REG_MICFIL_VAD0_CTRL2*/ +#define MICFIL_VAD0_CTRL2_FRENDIS BIT(31) +#define MICFIL_VAD0_CTRL2_PREFEN BIT(30) +#define MICFIL_VAD0_CTRL2_FOUTDIS BIT(28) +#define MICFIL_VAD0_CTRL2_FRAMET MASK(21, 16) +#define MICFIL_VAD0_CTRL2_INPGAIN MASK(11, 8) +#define MICFIL_VAD0_CTRL2_HPF MASK(1, 0) + +/* MICFIL HWVAD0 Signal CONFIG Register -- REG_MICFIL_VAD0_SCONFIG */ +#define MICFIL_VAD0_SCONFIG_SFILEN BIT(31) +#define MICFIL_VAD0_SCONFIG_SMAXEN BIT(30) +#define MICFIL_VAD0_SCONFIG_SGAIN MASK(3, 0) + +/* MICFIL HWVAD0 Noise CONFIG Register -- REG_MICFIL_VAD0_NCONFIG */ +#define MICFIL_VAD0_NCONFIG_NFILAUT BIT(31) +#define MICFIL_VAD0_NCONFIG_NMINEN BIT(30) +#define MICFIL_VAD0_NCONFIG_NDECEN BIT(29) +#define MICFIL_VAD0_NCONFIG_NOREN BIT(28) +#define MICFIL_VAD0_NCONFIG_NFILADJ MASK(12, 8) +#define MICFIL_VAD0_NCONFIG_NGAIN MASK(3, 0) + +/* MICFIL HWVAD0 Zero-Crossing Detector - REG_MICFIL_VAD0_ZCD */ +#define MICFIL_VAD0_ZCD_ZCDTH MASK(25, 16) +#define MICFIL_VAD0_ZCD_ZCDADJ MASK(11, 8) +#define MICFIL_VAD0_ZCD_ZCDAND BIT(4) +#define MICFIL_VAD0_ZCD_ZCDAUT BIT(2) +#define MICFIL_VAD0_ZCD_ZCDEN BIT(0) + +/* MICFIL HWVAD0 Status Register - REG_MICFIL_VAD0_STAT */ +#define MICFIL_VAD0_STAT_INITF BIT(31) +#define MICFIL_VAD0_STAT_INSATF BIT(16) +#define MICFIL_VAD0_STAT_EF BIT(15) +#define MICFIL_VAD0_STAT_IF BIT(0) + +/* MICFIL Output Control Register */ +#define MICFIL_OUTGAIN_CHX_SHIFT(v) (4 * (v)) + +/* Constants */ +#define MICFIL_OUTPUT_CHANNELS 8 +#define MICFIL_FIFO_NUM 8 + +#define FIFO_PTRWID 3 +#define FIFO_LEN BIT(FIFO_PTRWID) + +#define MICFIL_IRQ_LINES 4 +#define MICFIL_MAX_RETRY 25 +#define MICFIL_SLEEP_MIN 90000 /* in us */ +#define MICFIL_SLEEP_MAX 100000 /* in us */ +#define MICFIL_DMA_MAXBURST_RX 6 + +/* HWVAD Constants */ +#define MICFIL_HWVAD_ENVELOPE_MODE 0 +#define MICFIL_HWVAD_ENERGY_MODE 1 + +#endif /* __SOF_DRIVERS_MICFIL_H__ */ diff --git a/src/include/sof/drivers/mn.h b/src/include/sof/drivers/mn.h deleted file mode 100644 index 3e383d34f97f..000000000000 --- a/src/include/sof/drivers/mn.h +++ /dev/null @@ -1,90 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2020 Intel Corporation. All rights reserved. - * - * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifndef __SOF_DRIVERS_MN_H__ -#define __SOF_DRIVERS_MN_H__ - -#include <sof/sof.h> -#include <stdbool.h> -#include <stdint.h> - -/** \brief Offset of MCLK Divider Control Register. */ -#define MN_MDIVCTRL 0x0 - -/** \brief Enables the output of MCLK Divider. */ -#define MN_MDIVCTRL_M_DIV_ENABLE BIT(0) - -/** \brief Offset of MCLK Divider x Ratio Register. */ -#define MN_MDIVR(x) (0x80 + (x) * 0x4) - -/** \brief Offset of BCLK x M/N Divider M Value Register. */ -#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) - -/** \brief Offset of BCLK x M/N Divider N Value Register. */ -#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) - -/** - * \brief Initializes MN driver. - */ -void mn_init(struct sof *sof); - -/** - * \brief Finds and sets valid combination of MCLK source and divider to - * achieve requested MCLK rate. - * User should release clock when it is no longer needed to allow - * driver to change MCLK M/N source when user count drops to 0. - * M value of M/N is not supported for MCLK, only divider can be used. - * \param[in] mclk_id id of master clock for which rate should be set. - * \param[in] mclk_rate master clock frequency. - * \return 0 on success otherwise a negative error code. - */ -int mn_set_mclk(uint16_t mclk_id, uint32_t mclk_rate); - -/** - * \brief Release previously requested MCLK for given MCLK ID. - * \param[in] mclk_id id of master clock. - */ -void mn_release_mclk(uint32_t mclk_id); - -/** - * \brief Finds and sets valid combination of BCLK source and M/N to - * achieve requested BCLK rate. - * User should release clock when it is no longer needed to allow - * driver to change M/N source when user count drops to 0. - * \param[in] dai_index DAI index (SSP port). - * \param[in] bclk_rate Bit clock frequency. - * \param[out] out_scr_div SCR divisor that should be set by caller to achieve - * requested BCLK rate. - * \param[out] out_need_ecs If set to true, the caller should configure ECS. - * \return 0 on success otherwise a negative error code. - * \see mn_release_bclk() - */ -int mn_set_bclk(uint32_t dai_index, uint32_t bclk_rate, - uint32_t *out_scr_div, bool *out_need_ecs); - -/** - * \brief Release previously requested BCLK for given DAI. - * \param[in] dai_index DAI index (SSP port). - */ -void mn_release_bclk(uint32_t dai_index); - -/** - * \brief Resets M & N values of M/N divider for given DAI index. - * \param[in] dai_index DAI index (SSP port). - */ -void mn_reset_bclk_divider(uint32_t dai_index); - -/** - * \brief Retrieves M/N dividers structure. - * \return Pointer to M/N dividers structure. - */ -static inline struct mn *mn_get(void) -{ - return sof_get()->mn; -} - -#endif /* __SOF_DRIVERS_MN_H__ */ diff --git a/src/include/sof/drivers/mu.h b/src/include/sof/drivers/mu.h index 3ad5781a7c05..9707dd32fb5c 100644 --- a/src/include/sof/drivers/mu.h +++ b/src/include/sof/drivers/mu.h @@ -10,30 +10,65 @@ #ifndef __SOF_DRIVERS_MU_H__ #define __SOF_DRIVERS_MU_H__ -#include <sof/bit.h> +#include <rtos/bit.h> +#include <rtos/clk.h> #include <stdint.h> +enum imx_mu_type { + IMX_MU_V1, + IMX_MU_V2, +}; + +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) || defined(CONFIG_IMX95) +#define IMX_MU_VERSION IMX_MU_V2 +#else +#define IMX_MU_VERSION IMX_MU_V1 +#endif + +enum imx_mu_xcr { + IMX_MU_GIER = 0x110, + IMX_MU_GCR = 0x114, + IMX_MU_TCR = 0x120, + IMX_MU_RCR = 0x128, +}; + +enum imx_mu_xsr { + IMX_MU_SR = 0x0c, + IMX_MU_GSR = 0x118, + IMX_MU_TSR = 0x124, + IMX_MU_RSR = 0x12c, +}; + +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) +/* Transmit Register */ +#define IMX_MU_xTRn(x) (0x200 + 4 * (x)) +/* Receive Register */ +#define IMX_MU_xRRn(x) (0x280 + 4 * (x)) + +#else /* Transmit Register */ #define IMX_MU_xTRn(x) (0x00 + 4 * (x)) /* Receive Register */ #define IMX_MU_xRRn(x) (0x10 + 4 * (x)) +#endif + /* Status Register */ -#define IMX_MU_xSR 0x20 -#define IMX_MU_xSR_GIPn(x) BIT(28 + (3 - (x))) -#define IMX_MU_xSR_RFn(x) BIT(24 + (3 - (x))) -#define IMX_MU_xSR_TEn(x) BIT(20 + (3 - (x))) +#define IMX_MU_xSR(type, index) (type == IMX_MU_V2 ? index : 0x20) +#define IMX_MU_xSR_GIPn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x)))) +#define IMX_MU_xSR_RFn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x)))) +#define IMX_MU_xSR_TEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x)))) #define IMX_MU_xSR_BRDIP BIT(9) /* Control Register */ -#define IMX_MU_xCR 0x24 +#define IMX_MU_xCR(type, index) (type == IMX_MU_V2 ? index : 0x24) /* General Purpose Interrupt Enable */ -#define IMX_MU_xCR_GIEn(x) BIT(28 + (3 - (x))) +#define IMX_MU_xCR_GIEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x)))) /* Receive Interrupt Enable */ -#define IMX_MU_xCR_RIEn(x) BIT(24 + (3 - (x))) +#define IMX_MU_xCR_RIEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(24 + (3 - (x)))) /* Transmit Interrupt Enable */ -#define IMX_MU_xCR_TIEn(x) BIT(20 + (3 - (x))) +#define IMX_MU_xCR_TIEn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(20 + (3 - (x)))) /* General Purpose Interrupt Request */ -#define IMX_MU_xCR_GIRn(x) BIT(16 + (3 - (x))) +#define IMX_MU_xCR_GIRn(type, x) (type == IMX_MU_V2 ? BIT(x) : BIT(16 + (3 - (x)))) static inline uint32_t imx_mu_read(uint32_t reg) { @@ -45,26 +80,26 @@ static inline void imx_mu_write(uint32_t val, uint32_t reg) *((volatile uint32_t*)(MU_BASE + reg)) = val; } -static inline uint32_t imx_mu_xcr_rmw(uint32_t set, uint32_t clr) +static inline uint32_t imx_mu_xcr_rmw(int type, int idx, uint32_t set, uint32_t clr) { volatile uint32_t val; - val = imx_mu_read(IMX_MU_xCR); + val = imx_mu_read(IMX_MU_xCR(type, idx)); val &= ~clr; val |= set; - imx_mu_write(val, IMX_MU_xCR); + imx_mu_write(val, IMX_MU_xCR(type, idx)); return val; } -static inline uint32_t imx_mu_xsr_rmw(uint32_t set, uint32_t clr) +static inline uint32_t imx_mu_xsr_rmw(int type, int idx, uint32_t set, uint32_t clr) { volatile uint32_t val; - val = imx_mu_read(IMX_MU_xSR); + val = imx_mu_read(IMX_MU_xSR(type, idx)); val &= ~clr; val |= set; - imx_mu_write(val, IMX_MU_xSR); + imx_mu_write(val, IMX_MU_xSR(type, idx)); return val; } diff --git a/src/include/sof/drivers/sai.h b/src/include/sof/drivers/sai.h index a932a0f901ef..10405298322d 100644 --- a/src/include/sof/drivers/sai.h +++ b/src/include/sof/drivers/sai.h @@ -9,12 +9,14 @@ #ifndef __SOF_DRIVERS_SAI_H__ #define __SOF_DRIVERS_SAI_H__ -#include <sof/bit.h> +#include <ipc/dai.h> +#include <ipc/dai-imx.h> +#include <rtos/bit.h> #include <sof/lib/dai.h> #include <sof/trace/trace.h> #include <user/trace.h> -#ifdef CONFIG_IMX8M +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) #define SAI_OFS 8 #else #define SAI_OFS 0 @@ -127,7 +129,11 @@ #define REG_SAI_CSR_FRDE BIT(0) /* SAI Transmit and Receive Configuration 1 Register */ +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) +#define REG_SAI_CR1_RFW_MASK 0x7f +#else #define REG_SAI_CR1_RFW_MASK 0x3f +#endif /* SAI Transmit and Receive Configuration 2 Register */ #define REG_SAI_CR2_SYNC SET_BITS(31, 30, 1) @@ -141,6 +147,7 @@ #define REG_SAI_CR2_BCP BIT(25) #define REG_SAI_CR2_BCD_MSTR BIT(24) #define REG_SAI_CR2_BYP BIT(23) /* BCLK bypass */ +#define REG_SAI_CR2_BYP_MASK BIT(23) #define REG_SAI_CR2_DIV_MASK 0xff /* SAI Transmit and Receive Configuration 3 Register */ @@ -157,6 +164,7 @@ #define REG_SAI_CR4_FCOMB_MASK MASK(27, 26) #define REG_SAI_CR4_FPACK_8 (0x2 << 24) #define REG_SAI_CR4_FPACK_16 (0x3 << 24) +#define REG_SAI_CR4_FPACK_MASK MASK(25, 24) #define REG_SAI_CR4_FRSZ(x) (((x) - 1) << 16) #define REG_SAI_CR4_FRSZ_MASK MASK(20, 16) #define REG_SAI_CR4_SYWD(x) (((x) - 1) << 8) @@ -231,19 +239,20 @@ #define SAI_FLAG_PMQOS BIT(0) +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) +#define SAI_FIFO_WORD_SIZE 128 +#elif defined CONFIG_IMX8ULP +#define SAI_FIFO_WORD_SIZE 16 +#else #define SAI_FIFO_WORD_SIZE 64 -/* Divides down the audio master clock to generate the bit clock when - * configured for an internal bit clock. - * The division value is (DIV + 1) * 2. - */ -#define SAI_CLOCK_DIV 0x7 -#define SAI_TDM_SLOTS 2 +#endif extern const struct dai_driver sai_driver; -#define trace_sai(format, ...) trace_event(TRACE_CLASS_DAI, format, \ -##__VA_ARGS__) -#define tracev_sai(format, ...) tracev_event(TRACE_CLASS_DAI, format, \ -##__VA_ARGS__) -#define trace_sai_error(format, ...) trace_error(TRACE_CLASS_DAI, format, \ -##__VA_ARGS__) + +/* SAI private data */ +struct sai_pdata { + struct sof_ipc_dai_config config; + struct sof_ipc_dai_sai_params params; +}; + #endif /*__SOF_DRIVERS_SAI_H__ */ diff --git a/src/include/sof/drivers/sdma.h b/src/include/sof/drivers/sdma.h index 2beeacaed298..62f1f1c4101d 100644 --- a/src/include/sof/drivers/sdma.h +++ b/src/include/sof/drivers/sdma.h @@ -89,6 +89,15 @@ #define SDMA_DONE0_CONFIG 0x1000 #define SDMA_DONE1_CONFIG 0x1004 +#define SDMA_DONE0_CONFIG_DONE_SEL BIT(7) +#define SDMA_DONE0_CONFIG_DONE_DIS BIT(6) + +#define SDMA_WATERMARK_LEVEL_N_FIFOS(x) SET_BITS(15, 12, x) +#define SDMA_WATERMARK_LEVEL_OFF_FIFOS(x) SET_BITS(19, 16, x) +#define SDMA_WATERMARK_LEVEL_WORDS_PER_FIFO(x) SET_BITS(31, 28, x) +#define SDMA_WATERMARK_LEVEL_SW_DONE BIT(23) +#define SDMA_WATERMARK_LEVEL_SW_DONE_SEL_OFF 24 + /* Buffer descriptor first word */ /* Count: Data buffer size, in words */ #define SDMA_BD_COUNT_MASK MASK(15, 0) @@ -143,12 +152,195 @@ /* SHP2MCU is host to DAI, faster but only works with SDRAM */ #define SDMA_CHAN_TYPE_SHP2MCU 3 #define SDMA_CHAN_TYPE_MCU2SHP 4 +/* used for multi-fifo script */ +#define SDMA_CHAN_TYPE_SAI2MCU 5 /* TODO check and move these to platform data */ #define SDMA_SCRIPT_AP2AP_OFF 644 #define SDMA_SCRIPT_AP2MCU_OFF 685 #define SDMA_SCRIPT_MCU2AP_OFF 749 -#define SDMA_SCRIPT_SHP2MCU_OFF 979 -#define SDMA_SCRIPT_MCU2SHP_OFF 1048 +#define SDMA_SCRIPT_SHP2MCU_OFF 893 +#define SDMA_SCRIPT_MCU2SHP_OFF 962 +#define SDMA_SCRIPT_SAI2MCU_OFF 6710 + +#if CONFIG_HAVE_SDMA_FIRMWARE + +/* + * From "sdma_script_code_imx7d_4_5.h" + */ + +/* SDMA RAM image start address and size */ +#define RAM_CODE_START_ADDR 6144 +#define RAM_CODE_SIZE 1315 + +/* buffer that holds the SDMA RAM image */ +static const short sdma_code[] = { +0xc1e5, 0x57db, 0x52f3, 0x6a01, 0x52fb, 0x6ad3, 0x52fb, 0x1a1c, +0x6ac3, 0x62e8, 0x0211, 0x3aff, 0x0830, 0x02d0, 0x7c3f, 0x008f, +0x003f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x0478, 0x7d03, +0x0479, 0x7d1c, 0x7c20, 0x0479, 0x7c15, 0x56ee, 0x0660, 0x7d05, +0x6509, 0x7e33, 0x620a, 0x7e31, 0x9829, 0x620a, 0x7e2e, 0x6509, +0x7e2c, 0x0512, 0x0512, 0x02ad, 0x6ac8, 0x7f27, 0x2003, 0x4800, +0x7ced, 0x9841, 0x7802, 0x6209, 0x6ac8, 0x9840, 0x0015, 0x7802, +0x620a, 0x6ac8, 0x9840, 0x0015, 0x0015, 0x7802, 0x620b, 0x6ac8, +0x7c14, 0x6ddf, 0x7f12, 0x077f, 0x7d09, 0x52fb, 0x1a04, 0x6ac3, +0x6ad3, 0x62c8, 0x2a04, 0x6ac8, 0x52fb, 0x6ad3, 0x0000, 0x55eb, +0x4d00, 0x7d07, 0xc1fc, 0x57db, 0x9806, 0x0007, 0x68cc, 0x680c, +0xc215, 0xc20c, 0x9801, 0xc1d9, 0xc1e5, 0x57db, 0x52f3, 0x6a01, +0x080f, 0x0011, 0x18ff, 0x00bf, 0x5ce3, 0x00d5, 0x7d01, 0x008d, +0x05a0, 0x5deb, 0x56fb, 0x0478, 0x7d03, 0x0479, 0x7d28, 0x7c33, +0x0479, 0x7c1a, 0x0b70, 0x0311, 0x53eb, 0x0360, 0x7d05, 0x6509, +0x7e5f, 0x620a, 0x7e5d, 0x9880, 0x620a, 0x7e5a, 0x6509, 0x7e58, +0x0512, 0x0512, 0x02ad, 0x5a06, 0x7f53, 0x2003, 0x4800, 0x7ced, +0x0b70, 0x0311, 0x5313, 0x98b0, 0xd8c8, 0x6209, 0x5a06, 0x069c, +0x2701, 0x2001, 0x4f00, 0x7cf9, 0x4800, 0x7cf6, 0x98af, 0x0015, +0xd8c8, 0x620a, 0x5a06, 0x069c, 0x2701, 0x2001, 0x4f00, 0x7cf9, +0x4800, 0x7cf6, 0x98af, 0x0015, 0x0015, 0xd8c8, 0x620b, 0x5a06, +0x069c, 0x2701, 0x2001, 0x4f00, 0x7cf9, 0x4800, 0x7cf6, 0x7c28, +0x57db, 0x0777, 0x7c0c, 0x0710, 0x3f0f, 0x0717, 0x0717, 0x0e70, +0x0611, 0x0c70, 0x0411, 0x069c, 0x069f, 0x0c01, 0x5c06, 0x0000, +0x54e3, 0x57db, 0x55eb, 0x4d00, 0x7d16, 0xc1fc, 0x57db, 0x9860, +0x56fb, 0x57db, 0x048f, 0x0711, 0x3ff0, 0x0715, 0x0715, 0x0715, +0x0715, 0x0410, 0x0411, 0x3c0f, 0x1c01, 0x0417, 0x0417, 0x0006, +0x0007, 0x680c, 0xc215, 0xc20c, 0x985d, 0xc1d9, 0xc1e5, 0x57db, +0x5fe3, 0x57e3, 0x52f3, 0x6a21, 0x008f, 0x00d5, 0x7d01, 0x008d, +0x05a0, 0x5deb, 0x56fb, 0x0478, 0x7d03, 0x0479, 0x7d2a, 0x7c31, +0x0479, 0x7c20, 0x0b70, 0x0311, 0x53eb, 0x0f00, 0x0360, 0x7d05, +0x6509, 0x7e37, 0x620a, 0x7e35, 0x9901, 0x620a, 0x7e32, 0x6509, +0x7e30, 0x0512, 0x0512, 0x02ad, 0x0760, 0x7c02, 0x5a06, 0x9909, +0x5a26, 0x7f27, 0x1f01, 0x2003, 0x4800, 0x7ce8, 0x0b70, 0x0311, +0x5313, 0x992a, 0x0015, 0x7804, 0x6209, 0x5a06, 0x6209, 0x5a26, +0x9929, 0x0015, 0x0015, 0x7804, 0x620a, 0x5a06, 0x620a, 0x5a26, +0x9929, 0x0015, 0x0015, 0x0015, 0x7804, 0x620b, 0x5a06, 0x620b, +0x5a26, 0x7c07, 0x0000, 0x55eb, 0x4d00, 0x7d06, 0xc1fc, 0x57e3, +0x98e4, 0x0007, 0x680c, 0xc215, 0xc20c, 0x98e1, 0x0b70, 0x0311, +0x5313, 0x076c, 0x7c01, 0xc1d9, 0x5efb, 0x068a, 0x076b, 0x7c01, +0xc1d9, 0x5ef3, 0x59db, 0x58d3, 0x018f, 0x0110, 0x390f, 0x008b, +0xc13c, 0x7d2b, 0x5ac0, 0x5bc8, 0xc14e, 0x7c27, 0x0388, 0x0689, +0x5ce3, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x073e, 0x4d00, 0x7d18, +0x0870, 0x0011, 0x077e, 0x7d09, 0x077d, 0x7d02, 0x5228, 0x9961, +0x52f8, 0x54db, 0x02bc, 0x02cc, 0x7c09, 0x077c, 0x7d02, 0x5228, +0x996a, 0x52f8, 0x54d3, 0x02bc, 0x02cc, 0x7d09, 0x0400, 0x9958, +0x008b, 0x52c0, 0x53c8, 0xc159, 0x7dd6, 0x0200, 0x9948, 0x08ff, +0x00bf, 0x077f, 0x7d15, 0x0488, 0x00d5, 0x7d01, 0x008d, 0x05a0, +0x5deb, 0x028f, 0x0212, 0x0212, 0x3aff, 0x05da, 0x7c02, 0x073e, +0x9995, 0x02a4, 0x02dd, 0x7d02, 0x073e, 0x9995, 0x075e, 0x9995, +0x55eb, 0x4d00, 0x7c02, 0x0598, 0x5deb, 0x52f3, 0x54fb, 0x076a, +0x7d26, 0x076c, 0x7d01, 0x99d2, 0x076b, 0x7c57, 0x0769, 0x7d04, +0x0768, 0x7d02, 0x0e01, 0x99ac, 0x5893, 0x00d6, 0x7d01, 0x008e, +0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802, 0x5502, 0x5d04, 0x7c1d, +0x4e00, 0x7c08, 0x0769, 0x7d03, 0x5502, 0x7e17, 0x99b9, 0x5d04, +0x7f14, 0x0689, 0x5093, 0x4800, 0x7d01, 0x99a4, 0x9a1d, 0x0015, +0x7806, 0x5502, 0x5d04, 0x074f, 0x5502, 0x5d24, 0x072f, 0x7c01, +0x9a1d, 0x0017, 0x076f, 0x7c01, 0x2001, 0x5593, 0x009d, 0x0007, +0xda24, 0x9970, 0x6cd3, 0x0769, 0x7d04, 0x0768, 0x7d02, 0x0e01, +0x99e1, 0x5893, 0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, 0x5d93, +0x06a0, 0x7802, 0x5502, 0x6dc8, 0x7c0f, 0x4e00, 0x7c08, 0x0769, +0x7d03, 0x5502, 0x7e09, 0x99ee, 0x6dc8, 0x7f06, 0x0689, 0x5093, +0x4800, 0x7d01, 0x99d9, 0x9a1d, 0x9a17, 0x6ac3, 0x0769, 0x7d04, +0x0768, 0x7d02, 0x0e01, 0x9a04, 0x5893, 0x00d6, 0x7d01, 0x008e, +0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802, 0x65c8, 0x5d04, 0x7c0f, +0x4e00, 0x7c08, 0x0769, 0x7d03, 0x65c8, 0x7e09, 0x9a11, 0x5d04, +0x7f06, 0x0689, 0x5093, 0x4800, 0x7d01, 0x99fc, 0x9a1d, 0x5593, +0x009d, 0x0007, 0x6cff, 0xda24, 0x9970, 0x0000, 0x54e3, 0x55eb, +0x4d00, 0x7c01, 0x9970, 0x9958, 0x54e3, 0x55eb, 0x0aff, 0x0211, +0x1aff, 0x077f, 0x7c02, 0x05a0, 0x9a31, 0x009d, 0x058c, 0x05ba, +0x05a0, 0x0210, 0x04ba, 0x04ad, 0x0454, 0x0006, 0xc1d9, 0xc1e5, +0x57db, 0x52f3, 0x6a05, 0x5ce3, 0x080f, 0x0011, 0x18ff, 0x00bf, +0x00d5, 0x7d01, 0x008d, 0x05a0, 0x56fb, 0x0478, 0x7d03, 0x0479, +0x7d28, 0x7c1a, 0x0479, 0x7c31, 0x0b70, 0x0311, 0x53eb, 0x5206, +0x7e60, 0x0360, 0x7d02, 0x0210, 0x0212, 0x6a09, 0x7f5a, 0x0212, +0x6a09, 0x7f57, 0x0212, 0x6a09, 0x7f54, 0x2003, 0x4800, 0x7cef, +0x0b70, 0x0311, 0x5313, 0x9a88, 0x0015, 0x0015, 0xdaa1, 0x5206, +0x6a0b, 0x069c, 0x2001, 0x2701, 0x4f00, 0x7cf9, 0x4800, 0x7cf6, +0x9a87, 0x0015, 0xdaa1, 0x5206, 0x6a0a, 0x069c, 0x2001, 0x2701, +0x4f00, 0x7cf9, 0x4800, 0x7cf6, 0x9a87, 0xdaa1, 0x5206, 0x6a09, +0x069c, 0x2001, 0x2701, 0x4f00, 0x7cf9, 0x4800, 0x7cf6, 0x7c29, +0x6a28, 0x7f27, 0x57db, 0x0777, 0x7c0c, 0x0710, 0x3f0f, 0x0717, +0x0717, 0x0e70, 0x0611, 0x0c70, 0x0411, 0x069c, 0x069f, 0x0c01, +0x5c06, 0x0000, 0x54e3, 0x57db, 0x4d00, 0x7d15, 0xc1fc, 0x57db, +0x9a3b, 0x56fb, 0x57db, 0x048f, 0x0711, 0x3ff0, 0x0715, 0x0715, +0x0715, 0x0715, 0x0410, 0x0411, 0x3c0f, 0x1c01, 0x0417, 0x0417, +0x0006, 0xc279, 0x0454, 0xc20c, 0x9a38, 0xc1d9, 0xc1e5, 0x57db, +0x52f3, 0x6a05, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x56fb, +0x0478, 0x7d03, 0x0479, 0x7d29, 0x7c1f, 0x0479, 0x7c2e, 0x5de3, +0x0d70, 0x0511, 0x55ed, 0x0f00, 0x0760, 0x7d02, 0x5206, 0x9ad1, +0x5226, 0x7e33, 0x0560, 0x7d02, 0x0210, 0x0212, 0x6a09, 0x7f2d, +0x0212, 0x6a09, 0x7f2a, 0x0212, 0x6a09, 0x7f27, 0x1f01, 0x2003, +0x4800, 0x7cea, 0x55e3, 0x9afc, 0x0015, 0x0015, 0x0015, 0x7804, +0x5206, 0x6a0b, 0x5226, 0x6a0b, 0x9afb, 0x0015, 0x0015, 0x7804, +0x5206, 0x6a0a, 0x5226, 0x6a0a, 0x9afb, 0x0015, 0x7804, 0x5206, +0x6a09, 0x5226, 0x6a09, 0x7c09, 0x6a28, 0x7f07, 0x0000, 0x57db, +0x4d00, 0x7d05, 0xc1fc, 0x57db, 0x9aba, 0xc279, 0x0454, 0xc20c, +0x9ab7, 0xc1e5, 0x57db, 0x52f3, 0x6a05, 0x56fb, 0x028e, 0x1a94, +0x6ac3, 0x62c8, 0x0269, 0x7d26, 0x1e94, 0x6ec3, 0x6ed3, 0x62c8, +0x0a01, 0x0211, 0x6ac8, 0x2694, 0x1e98, 0x6ec3, 0x62c8, 0x2698, +0x6ec3, 0x0260, 0x7d0f, 0x1e98, 0x6ec3, 0x62c8, 0x026c, 0x7d03, +0x2698, 0x6ec3, 0x9b48, 0x0a10, 0x0211, 0x6ed3, 0x6ac8, 0x2698, +0x6ec3, 0x9b58, 0x62c8, 0x9b34, 0x6a09, 0x7f18, 0x2501, 0x4d00, +0x7d1f, 0x9b1c, 0x6ee3, 0x008f, 0x05d8, 0x7d01, 0x008d, 0x62c8, +0x6a09, 0x7f0c, 0x2501, 0x2001, 0x7cfa, 0x57db, 0x4d00, 0x7d10, +0x6a28, 0x7f04, 0x0000, 0xc1fc, 0x57db, 0x9b0d, 0x0007, 0x6204, +0x6a0c, 0x9b55, 0x6a28, 0x7ffa, 0x6204, 0xc27c, 0x0458, 0x0454, +0x08ff, 0x0011, 0x18ff, 0x00bc, 0x00cd, 0x7c01, 0x9b48, 0x6a28, +0x7fed, 0x6204, 0xc27c, 0xc20c, 0x9b0a, 0xc1d9, 0xc1e5, 0x57db, +0x52f3, 0x6a05, 0x56fb, 0x028e, 0x1a94, 0x5202, 0x0269, 0x7d1d, +0x1e94, 0x5206, 0x0248, 0x5a06, 0x2694, 0x1e98, 0x5206, 0x024c, +0x5a06, 0x2698, 0x1e98, 0x5206, 0x0260, 0x7c0a, 0x2698, 0x5206, +0x026e, 0x7d23, 0x6a09, 0x7f1d, 0x2501, 0x4d00, 0x7d24, 0x9b7a, +0x6a28, 0x7f17, 0x6204, 0xc27c, 0x9bab, 0x008f, 0x05d8, 0x7d01, +0x008d, 0x05a0, 0x5206, 0x026e, 0x7d10, 0x6a09, 0x7f0a, 0x2001, +0x7cf9, 0x6a28, 0x7f06, 0x0000, 0x4d00, 0x7d0d, 0xc1fc, 0x57db, +0x9b6a, 0x0007, 0x6204, 0x6a0c, 0x9ba8, 0x6a28, 0x7ffa, 0x6204, +0xc27c, 0x0458, 0x0454, 0x6a28, 0x7ff4, 0xc20c, 0x9b67, 0xdbf3, +0x57db, 0x52f3, 0x6a05, 0x69c7, 0x008f, 0x00d5, 0x7d01, 0x008d, +0x05a0, 0x0478, 0x7d03, 0x0479, 0x7d1c, 0x7c15, 0x0479, 0x7c1e, +0x56ee, 0x62c8, 0x7e28, 0x0660, 0x7d02, 0x0210, 0x0212, 0x6a09, +0x7f22, 0x0212, 0x6a09, 0x7f1f, 0x0212, 0x6a09, 0x7f1c, 0x2003, +0x4800, 0x7cef, 0x9be2, 0x0015, 0x0015, 0x7802, 0x62c8, 0x6a0b, +0x9be1, 0x0015, 0x7802, 0x62c8, 0x6a0a, 0x9be1, 0x7802, 0x62c8, +0x6a09, 0x7c09, 0x6a28, 0x7f07, 0x4d00, 0x7d07, 0x52d3, 0x0801, +0x5802, 0x0400, 0x9bb3, 0xc279, 0x0454, 0x52d3, 0x0801, 0x5802, +0x0401, 0xdc0b, 0x9bb0, 0x0b70, 0x0311, 0x5313, 0x5fdb, 0x070a, +0x58d3, 0x008b, 0x5efb, 0xc13c, 0x7d15, 0x5ac0, 0x5bc8, 0xc14e, +0x7c11, 0x0388, 0x5df0, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, +0x7d04, 0x9c0a, 0x0708, 0x5fdb, 0x070a, 0x008b, 0x52c3, 0x53cb, +0xc159, 0x7dec, 0x0200, 0x9bfb, 0x6e01, 0x610b, 0x7e2f, 0x620b, +0x7e2d, 0x630b, 0x7e2b, 0x0d0c, 0x0417, 0x0417, 0x0417, 0x049d, +0x1d08, 0x05cc, 0x7c01, 0x0d0c, 0x6ad1, 0x0f00, 0x0742, 0x6fc8, +0x6fdd, 0x7f1c, 0x008e, 0x009d, 0x6801, 0x670b, 0x7e17, 0x6bd5, +0x0804, 0x7802, 0x6fc8, 0x0712, 0x7c11, 0x670b, 0x7e0f, 0x0804, +0x7802, 0x6fc8, 0x0712, 0x7c0a, 0x6fdd, 0x7f08, 0x69d1, 0x0f01, +0x6fc8, 0x6fdd, 0x7f03, 0x0101, 0x0400, 0x9c20, 0x0007, 0x68ff, +0x680c, 0x0200, 0x9c20, 0xdc90, 0x57db, 0x52f3, 0x6a05, 0x52fb, +0x6ac7, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x0478, 0x7d03, +0x0479, 0x7d1c, 0x7c15, 0x0479, 0x7c1e, 0x56ee, 0x62c8, 0x7e28, +0x0660, 0x7d02, 0x0210, 0x0212, 0x6a09, 0x7f22, 0x0212, 0x6a09, +0x7f1f, 0x0212, 0x6a09, 0x7f1c, 0x2003, 0x4800, 0x7cef, 0x9c7f, +0x0015, 0x0015, 0x7802, 0x62c8, 0x6a0b, 0x9c7e, 0x0015, 0x7802, +0x62c8, 0x6a0a, 0x9c7e, 0x7802, 0x62c8, 0x6a09, 0x7c09, 0x6a28, +0x7f07, 0x4d00, 0x7d07, 0x52d3, 0x0801, 0x5802, 0x0400, 0x9c4f, +0xc279, 0x0454, 0x52d3, 0x0801, 0x5802, 0x0401, 0xdca8, 0x9c4c, +0x0b70, 0x0311, 0x5313, 0x5fdb, 0x070a, 0x58d3, 0x008b, 0x5efb, +0xc13c, 0x7d15, 0x5ac0, 0x5bc8, 0xc14e, 0x7c11, 0x0388, 0x5df0, +0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d04, 0x9ca7, 0x0708, +0x5fdb, 0x070a, 0x008b, 0x52c3, 0x53cb, 0xc159, 0x7dec, 0x0200, +0x9c98, 0xdd02, 0x52f3, 0x6a01, 0x57db, 0x52fb, 0x077f, 0x7d02, +0x6ad3, 0x9cbb, 0x6ad7, 0x008f, 0x38ff, 0x00d5, 0x7d01, 0x008d, +0x05a0, 0x5deb, 0x0478, 0x7d03, 0x0479, 0x7d1c, 0x7c20, 0x0479, +0x7c15, 0x56ee, 0x0660, 0x7d05, 0x6509, 0x7e2a, 0x620a, 0x7e28, +0x9cd5, 0x620a, 0x7e25, 0x6509, 0x7e23, 0x0512, 0x0512, 0x02ad, +0x6ac8, 0x7f1e, 0x2003, 0x4800, 0x7ced, 0x9ced, 0x7802, 0x6209, +0x6ac8, 0x9cec, 0x0015, 0x7802, 0x620a, 0x6ac8, 0x9cec, 0x0015, +0x0015, 0x7802, 0x620b, 0x6ac8, 0x7c0b, 0x6ddf, 0x7f09, 0x0000, +0x55eb, 0x4d00, 0x7d09, 0x52d3, 0x0801, 0x5802, 0x0400, 0x9cb4, +0x0007, 0x68cc, 0x680c, 0xc215, 0x52d3, 0x0801, 0x5802, 0x0401, +0xdd1a, 0x9cb2, 0x0b70, 0x0311, 0x5313, 0x5fdb, 0x070a, 0x58d3, +0x008b, 0x5efb, 0xc13c, 0x7d15, 0x5ac0, 0x5bc8, 0xc14e, 0x7c11, +0x0388, 0x5df0, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x4d00, 0x7d04, +0x9d19, 0x0708, 0x5fdb, 0x070a, 0x008b, 0x52c3, 0x53cb, 0xc159, +0x7dec, 0x0200, 0x9d0a +}; +#endif #endif /* __SOF_DRIVERS_SDMA_H__ */ diff --git a/src/include/sof/drivers/ssp.h b/src/include/sof/drivers/ssp.h index ef144c35d7ff..f057e7147747 100644 --- a/src/include/sof/drivers/ssp.h +++ b/src/include/sof/drivers/ssp.h @@ -8,15 +8,15 @@ #ifndef __SOF_DRIVERS_SSP_H__ #define __SOF_DRIVERS_SSP_H__ -#include <sof/bit.h> -#include <sof/lib/clk.h> +#include <rtos/bit.h> +#include <rtos/clk.h> #include <sof/lib/dai.h> -#include <sof/lib/wait.h> +#include <rtos/wait.h> #include <sof/trace/trace.h> #include <ipc/dai.h> #include <ipc/dai-intel.h> #include <user/trace.h> -#include <config.h> + #include <stdint.h> #define SSP_CLOCK_XTAL_OSCILLATOR 0x0 @@ -39,18 +39,11 @@ extern const uint32_t *ssp_freq_sources; #define SSTSS 0x38 #define SSCR2 0x40 -#if CONFIG_BAYTRAIL || CONFIG_CHERRYTRAIL || CONFIG_BROADWELL || CONFIG_HASWELL -#define SFIFOL 0x68 -#define SFIFOTT 0x6C -#define SSCR3 0x70 -#define SSCR4 0x74 -#define SSCR5 0x78 -#endif - extern const struct dai_driver ssp_driver; /* SSCR0 bits */ #define SSCR0_DSIZE(x) SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & MASK(3, 0)) + 1) #define SSCR0_FRF MASK(5, 4) #define SSCR0_MOT SET_BITS(5, 4, 0) #define SSCR0_TI SET_BITS(5, 4, 1) @@ -65,6 +58,7 @@ extern const struct dai_driver ssp_driver; #define SSCR0_RIM BIT(22) #define SSCR0_TIM BIT(23) #define SSCR0_FRDC(x) SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & MASK(26, 24)) >> 24) + 1) #define SSCR0_ACS BIT(30) #define SSCR0_MOD BIT(31) @@ -97,19 +91,7 @@ extern const struct dai_driver ssp_driver; #define SSCR1_TTE BIT(30) #define SSCR1_TTELP BIT(31) -#if CONFIG_BAYTRAIL || CONFIG_CHERRYTRAIL -/* SSCR2 bits */ -#define SSCR2_URUN_FIX0 BIT(0) -#define SSCR2_URUN_FIX1 BIT(1) -#define SSCR2_SLV_EXT_CLK_RUN_EN BIT(2) -#define SSCR2_CLK_DEL_EN BIT(3) -#define SSCR2_UNDRN_FIX_EN BIT(6) -#define SSCR2_FIFO_EMPTY_FIX_EN BIT(7) -#define SSCR2_ASRC_CNTR_EN BIT(8) -#define SSCR2_ASRC_CNTR_CLR BIT(9) -#define SSCR2_ASRC_FRM_CNRT_EN BIT(10) -#define SSCR2_ASRC_INTR_MASK BIT(11) -#elif CONFIG_CAVS || CONFIG_HASWELL || CONFIG_BROADWELL +#if CONFIG_CAVS #define SSCR2_TURM1 BIT(1) #define SSCR2_PSPSRWFDFD BIT(3) #define SSCR2_PSPSTWFDFD BIT(4) @@ -120,7 +102,6 @@ extern const struct dai_driver ssp_driver; #define SSCR2_SMTATF BIT(19) #endif - /* SSR bits */ #define SSSR_TNF BIT(2) #define SSSR_RNE BIT(3) @@ -156,10 +137,12 @@ extern const struct dai_driver ssp_driver; /* SSTSA bits */ #define SSTSA_SSTSA(x) SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & MASK(7, 0)) #define SSTSA_TXEN BIT(8) /* SSRSA bits */ #define SSRSA_SSRSA(x) SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & MASK(7, 0)) #define SSRSA_RXEN BIT(8) /* SSCR3 bits */ @@ -176,7 +159,6 @@ extern const struct dai_driver ssp_driver; #define SSCR3_MST_CLK_EN BIT(16) #define SSCR3_SYN_FIX_EN BIT(17) - /* SSCR4 bits */ #define SSCR4_TOT_FRM_PRD(x) ((x) << 7) @@ -192,7 +174,7 @@ extern const struct dai_driver ssp_driver; #define SFIFOL_TFL(x) ((x) & 0xFFFF) #define SFIFOL_RFL(x) ((x) >> 16) -#if CONFIG_CAVS || CONFIG_HASWELL || CONFIG_BROADWELL +#if CONFIG_CAVS #define SSTSA_TSEN BIT(8) #define SSRSA_RSEN BIT(8) @@ -208,29 +190,37 @@ extern const struct dai_driver ssp_driver; #define SSIOC_SCOE BIT(5) #endif -#if CONFIG_CAVS -#define MNDSS(x) SET_BITS(21, 20, x) -#define MCDSS(x) SET_BITS(17, 16, x) -#endif - #if CONFIG_CAVS -#include <sof/lib/clk.h> +#include <rtos/clk.h> /* max possible index in ssp_freq array */ #define MAX_SSP_FREQ_INDEX (NUM_SSP_FREQ - 1) #endif +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define SSP_RX_FLUSH_RETRY_MAX 16 + #define ssp_irq(ssp) \ ssp->plat_data.irq +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) +#define SSP_CLK_MCLK_AON_REQ BIT(4) + /* SSP private data */ struct ssp_pdata { uint32_t sscr0; uint32_t sscr1; uint32_t psp; uint32_t state[2]; /* SSP_STATE_ for each direction */ + uint32_t clk_active; struct sof_ipc_dai_config config; struct sof_ipc_dai_ssp_params params; }; diff --git a/src/include/sof/drivers/timer.h b/src/include/sof/drivers/timer.h deleted file mode 100644 index 92370d48fd6e..000000000000 --- a/src/include/sof/drivers/timer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifndef __SOF_DRIVERS_TIMER_H__ -#define __SOF_DRIVERS_TIMER_H__ - -#include <arch/drivers/timer.h> -#include <sof/sof.h> -#include <stdint.h> - -struct comp_dev; -struct sof_ipc_stream_posn; - -#define TIMER0 0 -#define TIMER1 1 -#define TIMER2 2 -#define TIMER3 3 -#define TIMER4 4 - -int timer_register(struct timer *timer, void (*handler)(void *arg), void *arg); -void timer_unregister(struct timer *timer, void *arg); -void timer_enable(struct timer *timer, void *arg, int core); -void timer_disable(struct timer *timer, void *arg, int core); - -static inline struct timer *timer_get(void) -{ - return sof_get()->platform_timer; -} - -static inline struct timer *cpu_timer_get(void) -{ - return sof_get()->cpu_timer; -} - -static inline int64_t timer_set(struct timer *timer, uint64_t ticks) -{ - return arch_timer_set(timer, ticks); -} - -void timer_set_ms(struct timer *timer, unsigned int ms); - -static inline void timer_clear(struct timer *timer) -{ - arch_timer_clear(timer); -} - -unsigned int timer_get_count(struct timer *timer); - -unsigned int timer_get_count_delta(struct timer *timer); - -static inline uint64_t timer_get_system(struct timer *timer) -{ - return arch_timer_get_system(timer); -} - -int64_t platform_timer_set(struct timer *timer, uint64_t ticks); -void platform_timer_clear(struct timer *timer); -uint64_t platform_timer_get(struct timer *timer); -void platform_timer_start(struct timer *timer); -void platform_timer_stop(struct timer *timer); - -/* get timestamp for host stream DMA position */ -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn); - -/* get timestamp for DAI stream DMA position */ -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn); - -/* get current wallclock for componnent */ -void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock); - -#endif /* __SOF_DRIVERS_TIMER_H__ */ diff --git a/src/include/sof/drivers/timestamp.h b/src/include/sof/drivers/timestamp.h deleted file mode 100644 index 3e68afbbda59..000000000000 --- a/src/include/sof/drivers/timestamp.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - */ - -#ifndef __SOF_DRIVERS_TIMESTAMP_H__ -#define __SOF_DRIVERS_TIMESTAMP_H__ - -/* cAVS1.5 platforms have discontinuous registers space for SSP - * timestamping while other platforms don't have this. - */ -#if CONFIG_APOLLOLAKE -#define TS_DMIC_LOCAL_TSCTRL 0x000 -#define TS_DMIC_LOCAL_OFFS 0x004 -#define TS_DMIC_LOCAL_SAMPLE 0x008 -#define TS_DMIC_LOCAL_WALCLK 0x010 -#define TS_DMIC_TSCC 0x018 -#define TS_HDA_LOCAL_TSCTRL (0x0e0 + 0x000) -#define TS_HDA_LOCAL_OFFS (0x0e0 + 0x004) -#define TS_HDA_LOCAL_SAMPLE (0x0e0 + 0x008) -#define TS_HDA_LOCAL_WALCLK (0x0e0 + 0x010) -#define TS_HDA_TSCC (0x0e0 + 0x018) -#define TS_I2S_LOCAL_TSCTRL(y) (0x40 + 0x20 * (y) + 0x000) -#define TS_I2S_LOCAL_OFFS(y) (0x40 + 0x20 * (y) + 0x004) -#define TS_I2S_LOCAL_SAMPLE(y) (0x40 + 0x20 * (y) + 0x008) -#define TS_I2S_LOCAL_WALCLK(y) (0x40 + 0x20 * (y) + 0x010) -#define TS_I2S_TSCC(y) (0x40 + 0x20 * (y) + 0x018) -#define TS_I2SE_LOCAL_TSCTRL(w) (0x120 + 0x20 * ((w) - 4) + 0x000) -#define TS_I2SE_LOCAL_OFFS(w) (0x120 + 0x20 * ((w) - 4) + 0x004) -#define TS_I2SE_LOCAL_SAMPLE(w) (0x120 + 0x20 * ((w) - 4) + 0x008) -#define TS_I2SE_LOCAL_WALCLK(w) (0x120 + 0x20 * ((w) - 4) + 0x010) -#define TS_I2SE_TSCC(w) (0x120 + 0x20 * ((w) - 4) + 0x018) - -#elif CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_SUECREEK || \ - CONFIG_TIGERLAKE - -#define TS_DMIC_LOCAL_TSCTRL 0x000 -#define TS_DMIC_LOCAL_OFFS 0x004 -#define TS_DMIC_LOCAL_SAMPLE 0x008 -#define TS_DMIC_LOCAL_WALCLK 0x010 -#define TS_DMIC_TSCC 0x018 -#define TS_HDA_LOCAL_TSCTRL (0x0e0 + 0x000) -#define TS_HDA_LOCAL_OFFS (0x0e0 + 0x004) -#define TS_HDA_LOCAL_SAMPLE (0x0e0 + 0x008) -#define TS_HDA_LOCAL_WALCLK (0x0e0 + 0x010) -#define TS_HDA_TSCC (0x0e0 + 0x018) -#define TS_I2S_LOCAL_TSCTRL(y) (0x100 + 0x20 * (y) + 0x000) -#define TS_I2S_LOCAL_OFFS(y) (0x100 + 0x20 * (y) + 0x004) -#define TS_I2S_LOCAL_SAMPLE(y) (0x100 + 0x20 * (y) + 0x008) -#define TS_I2S_LOCAL_WALCLK(y) (0x100 + 0x20 * (y) + 0x010) -#define TS_I2S_TSCC(y) (0x100 + 0x20 * (y) + 0x018) -#endif - -#define TS_LOCAL_TSCTRL_NTK_BIT BIT(31) -#define TS_LOCAL_TSCTRL_IONTE_BIT BIT(30) -#define TS_LOCAL_TSCTRL_SIP_BIT BIT(8) -#define TS_LOCAL_TSCTRL_HHTSE_BIT BIT(7) -#define TS_LOCAL_TSCTRL_ODTS_BIT BIT(5) -#define TS_LOCAL_TSCTRL_CDMAS(x) SET_BITS(4, 0, x) -#define TS_LOCAL_OFFS_FRM GET_BITS(15, 12) -#define TS_LOCAL_OFFS_CLK GET_BITS(11, 0) - -#elif CONFIG_BAYTRAIL || CONFIG_CHERRYTRAIL || CONFIG_BROADWELL || - CONFIG_HASWELL - -/* There's no timestamping support in pre-cAVS platforms. */ - -#else - -#error "Unknown platform" - -#endif diff --git a/src/include/sof/fw-ready-metadata.h b/src/include/sof/fw-ready-metadata.h index 87888c148b57..ff7c6929c60f 100644 --- a/src/include/sof/fw-ready-metadata.h +++ b/src/include/sof/fw-ready-metadata.h @@ -10,8 +10,4 @@ #include <ipc/info.h> -extern const struct sof_ipc_cc_version cc_version; -extern const struct sof_ipc_probe_support probe_support; -extern const struct sof_ipc_user_abi_version user_abi_version; - #endif /* __IPC_FW_READY_METADATA_H__ */ diff --git a/src/include/sof/init.h b/src/include/sof/init.h deleted file mode 100644 index 40ed16842891..000000000000 --- a/src/include/sof/init.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_INIT_H__ -#define __SOF_INIT_H__ - -#include <arch/init.h> - -struct sof; - -/* main firmware entry point - argc and argv not currently used */ -int main(int argc, char *argv[]); - -int master_core_init(int argc, char *argv[], struct sof *sof); - -int arch_init(void); - -#endif /* __SOF_INIT_H__ */ diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h new file mode 100644 index 000000000000..e46fc10b9521 --- /dev/null +++ b/src/include/sof/ipc/common.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_IPC_COMMON_H__ +#define __SOF_IPC_COMMON_H__ + +#include <rtos/bit.h> +#include <rtos/alloc.h> +#include <sof/list.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <rtos/sof.h> +#include <user/trace.h> +#include <ipc/header.h> +#include <ipc/stream.h> + +#include <stdbool.h> +#include <stdint.h> + +struct dma_sg_elem_array; +struct ipc_msg; + +/* validates internal non tail structures within IPC command structure */ +#define IPC_IS_SIZE_INVALID(object) \ + ((object).hdr.size != sizeof(object)) + +#define IPC_TAIL_IS_SIZE_INVALID(object) \ + ((object).comp.hdr.size + (object).comp.ext_data_length < sizeof(object)) + +/* ipc trace context, used by multiple units */ +extern struct tr_ctx ipc_tr; + +/* convenience error trace for mismatched internal structures */ +#define IPC_SIZE_ERROR_TRACE(ctx, object) \ + tr_err(ctx, "ipc: size %d expected %zu", \ + (object).hdr.size, sizeof(object)) + +/* Returns pipeline source component */ +#define ipc_get_ppl_src_comp(ipc, ppl_id) \ + ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_UPSTREAM) + +/* Returns pipeline sink component */ +#define ipc_get_ppl_sink_comp(ipc, ppl_id) \ + ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_DOWNSTREAM) + +#define IPC_TASK_INLINE BIT(0) +#define IPC_TASK_IN_THREAD BIT(1) +#define IPC_TASK_SECONDARY_CORE BIT(2) +#define IPC_TASK_POWERDOWN BIT(3) + +struct ipc { + struct k_spinlock lock; /* locking mechanism */ + void *comp_data; + + /* PM */ + int pm_prepare_D3; /* do we need to prepare for D3 */ + + struct list_item msg_list; /* queue of messages to be sent */ + bool is_notification_pending; /* notification is being sent to host */ + uint32_t task_mask; /* tasks to be completed by this IPC */ + unsigned int core; /* core, processing the IPC */ + + struct list_item comp_list; /* list of component devices */ + + /* processing task */ +#if CONFIG_TWB_IPC_TASK + struct task *ipc_task; +#else + struct task ipc_task; +#endif + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* io performance measurement */ + struct io_perf_data_item *io_perf_in_msg_count; + struct io_perf_data_item *io_perf_out_msg_count; +#endif + +#ifdef __ZEPHYR__ + struct k_work_delayable z_delayed_work; + struct k_work_q ipc_send_wq; +#endif + + void *private; +}; + +#define ipc_set_drvdata(ipc, data) \ + ((ipc)->private = data) +#define ipc_get_drvdata(ipc) \ + ((ipc)->private) + +extern struct task_ops ipc_task_ops; + +/** + * \brief Get the IPC global context. + * @return The global IPC context. + */ +static inline struct ipc *ipc_get(void) +{ + return sof_get()->ipc; +} + +/** + * \brief Initialise global IPC context. + * @param[in,out] sof Global SOF context. + * @return 0 on success. + */ +int ipc_init(struct sof *sof); + +/** + * \brief Free global IPC context. + * @param[in] ipc Global IPC context. + */ +void ipc_free(struct ipc *ipc); + +/** + * \brief Data provided by the platform which use ipc...page_descriptors(). + * + * Note: this should be made private for ipc-host-ptable.c and ipc + * drivers for platforms that use ptables. + */ +struct ipc_data_host_buffer { + /* DMA */ +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + struct sof_dma *dmac; +#else + struct dma *dmac; +#endif + uint8_t *page_table; +}; + +/** + * \brief Processes page tables for the host buffer. + * @param[in] ipc Ipc + * @param[in] ring Ring description sent via Ipc + * @param[in] direction Direction (playback/capture) + * @param[out] elem_array Array of SG elements + * @param[out] ring_size Size of the ring + * @return Status, 0 if successful, error code otherwise. + */ +int ipc_process_host_buffer(struct ipc *ipc, + struct sof_ipc_host_buffer *ring, + uint32_t direction, + struct dma_sg_elem_array *elem_array, + uint32_t *ring_size); + +/** + * \brief Send DMA trace host buffer position to host. + * @return 0 on success. + */ +int ipc_dma_trace_send_position(void); + +/** + * \brief send a IPC buffer status notify message + */ +void ipc_send_buffer_status_notify(void); + +struct dai_data; +/** + * \brief Configure DAI. + * @return 0 on success. + */ +int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev); + +/** + * \brief create a IPC boot complete message. + * @param[in] header header. + * @param[in] data data. + */ +void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data); + +#if defined(CONFIG_PM_DEVICE) && defined(CONFIG_INTEL_ADSP_IPC) +/** + * @brief Send an IPC response to Host power transition request informing + * that power transition failed. + * @note Normally an reply to the Host IPC message is performed in the + * low level assembly code to make sure DSP completed all operations before + * power cut-off. + * However, when power transition fails for some reason, we should send the + * IPC response informing about the failure. + * This happens in abnormal circumstances since the response is send not during + * IPC task but during power transition logic in the Idle thread. + */ +void ipc_send_failed_power_transition_response(void); +#endif /* CONFIG_PM_DEVICE && CONFIG_INTEL_ADSP_IPC */ +/** + * \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. + */ +struct ipc_cmd_hdr *ipc_compact_read_msg(void); + +/** + * \brief Write a compact IPC message. + * @param[in] hdr Compact message header data. + * @return Number of words written. + */ +int ipc_compact_write_msg(struct ipc_cmd_hdr *hdr); + +/** + * \brief Prepare an IPC message for sending. + * @param[in] msg The ipc msg. + * @return pointer to raw header or NULL. + */ +struct ipc_cmd_hdr *ipc_prepare_to_send(const struct ipc_msg *msg); + +/** + * \brief Validate mailbox contents for valid IPC header. + * @return pointer to header if valid or NULL. + */ +struct ipc_cmd_hdr *mailbox_validate(void); + +/** + * Generic IPC command handler. Expects that IPC command (the header plus + * any optional payload) is deserialized from the IPC HW by the platform + * specific method. + * + * @param _hdr Points to the IPC command header. + */ +void ipc_cmd(struct ipc_cmd_hdr *_hdr); + +/** + * \brief IPC message to be processed on other core. + * @param[in] core Core id for IPC to be processed on. + * @param[in] blocking Process in blocking mode: wait for completion. + * @return 1 if successful (reply sent by other core), error code otherwise. + */ +int ipc_process_on_core(uint32_t core, bool blocking); + +/** + * \brief reply to an IPC message. + * @param[in] reply pointer to the reply structure. + */ +void ipc_msg_reply(struct sof_ipc_reply *reply); + +/** + * \brief Call platform-specific IPC completion function. + */ +void ipc_complete_cmd(struct ipc *ipc); + +/* GDB stub: should enter GDB after completing the IPC processing */ +extern bool ipc_enter_gdb; + +#endif /* __SOF_DRIVERS_IPC_H__ */ diff --git a/src/include/sof/ipc/driver.h b/src/include/sof/ipc/driver.h new file mode 100644 index 000000000000..9b6506a7c1e8 --- /dev/null +++ b/src/include/sof/ipc/driver.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_IPC_DRIVER_H__ +#define __SOF_IPC_DRIVER_H__ + +#include <sof/platform.h> +#include <rtos/sof.h> +#include <sof/ipc/common.h> +#include <rtos/task.h> +#include <stdbool.h> +#include <stdint.h> + +struct ipc_msg; + +/** + * \brief Provides platform specific IPC initialization. + * @param ipc Global IPC context + * @return 0 if succeeded, error code otherwise. + * + * This function must be implemented by the platform. It is called from the + * main IPC code, at the end of ipc_init(). + * + * If the platform requires any private data to be associated with the IPC + * context, it may allocate it here and attach to the global context using + * ipc_set_drvdata(). Other platform specific IPC functions, like + * ipc_platform_do_cmd(), may obtain it later from the context using + * ipc_get_drvdata(). + */ +int platform_ipc_init(struct ipc *ipc); + +/** + * \brief Perform IPC command from host. + * @return The task state of the IPC command work. + */ +enum task_state ipc_platform_do_cmd(struct ipc *ipc); + +/** + * \brief Tell host we have completed the last IPC command. + */ +void ipc_platform_complete_cmd(struct ipc *ipc); + +/** + * \brief Send IPC message to host. + * @param msg The IPC message to send to host. + * @return 0 on success. + */ +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. + * + * This function must be implemented by platforms which use + * ipc...page_descriptors() while processing host page tables. + */ +struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc); + +/** + * \brief Read a compact IPC message from hardware. + * @param[in] hdr IPC header data + * @param[in] words Number of words to read in header. + * @return Number of word written. + */ +int ipc_platform_compact_read_msg(struct ipc_cmd_hdr *hdr, int words); + +/** + * \brief Write a compact IPC message to hardware. + * @param[in] hdr Compact message header data. + * @param[in] words Number of words to be written from header. + * @return Number of word written. + */ +int ipc_platform_compact_write_msg(struct ipc_cmd_hdr *hdr, int words); + +/** + * \brief Initialise IPC hardware for polling mode. + * @return 0 if successful error code otherwise. + */ +int ipc_platform_poll_init(void); + +/** + * \brief Tell host DSP has completed command. + */ +void ipc_platform_poll_set_cmd_done(void); + +/** + * \brief Check whether there is a new IPC command from host. + * @return 1 if new command is pending from host. + */ +int ipc_platform_poll_is_cmd_pending(void); + +/** + * \brief Check whether host is ready for new IPC from DSP. + * @return 1 if host is ready for a new command from DSP. + */ +int ipc_platform_poll_is_host_ready(void); + +/** + * \brief Transmit new message to host. + * @return 0 if successful error code otherwise. + */ +int ipc_platform_poll_tx_host_msg(struct ipc_msg *msg); + +/** + * \brief wait for host acknowledgment to an IPC message + */ +void ipc_platform_wait_ack(struct ipc *ipc); + +#endif diff --git a/src/include/sof/ipc/msg.h b/src/include/sof/ipc/msg.h new file mode 100644 index 000000000000..160a9be9ec7c --- /dev/null +++ b/src/include/sof/ipc/msg.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_IPC_MSG_H__ +#define __SOF_IPC_MSG_H__ + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/pipeline.h> +#include <rtos/alloc.h> +#include <sof/lib/memory.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/task.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/trace/trace.h> +#include <sof/ipc/common.h> +#include <ipc/trace.h> + +#include <stdbool.h> +#include <stdint.h> + +struct dai_config; +struct dma; +struct dma_sg_elem_array; + +struct ipc_msg { + uint32_t header; /* specific to platform */ + uint32_t extension; /* extension specific to platform */ + uint32_t tx_size; /* payload size in bytes */ + void *tx_data; /* pointer to payload data, must be in a non-cached memory */ + struct list_item list; + void (*callback)(struct ipc_msg *msg); /* Function called after sending the message */ +}; + +/** + * \brief Initialize a new IPC message. + * @param header Message header metadata + * @param extension Message header extension metadata + * @param size Message data size in bytes. + * @return New IPC message. + */ +static inline struct ipc_msg *ipc_msg_w_ext_init(uint32_t header, uint32_t extension, + uint32_t size) +{ + struct ipc_msg *msg; + + msg = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*msg)); + if (!msg) + return NULL; + + if (size) { + msg->tx_data = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, size); + if (!msg->tx_data) { + rfree(msg); + return NULL; + } + } + + msg->header = header; + msg->extension = extension; + msg->tx_size = size; + list_init(&msg->list); + + return msg; +} + +/** + * \brief Initialise a new IPC message. + * @param header Message header metadata + * @param size Message data size in bytes. + * @return New IPC message. + */ +static inline struct ipc_msg *ipc_msg_init(uint32_t header, uint32_t size) +{ + return ipc_msg_w_ext_init(header, 0, size); +} + +/** + * \brief Frees IPC message header and data. + * @param msg The IPC message to be freed. + */ +static inline void ipc_msg_free(struct ipc_msg *msg) +{ + if (!msg) + return; + + struct ipc *ipc = ipc_get(); + k_spinlock_key_t key; + + key = k_spin_lock(&ipc->lock); + + list_item_del(&msg->list); + rfree(msg->tx_data); + rfree(msg); + + k_spin_unlock(&ipc->lock, key); +} + +/** + * \brief Sends the next message in the IPC message queue. + */ +void ipc_send_queued_msg(void); + +/** + * \brief Queues an IPC message for transmission. + * @param msg The IPC message to be freed. + * @param data The message data. + * @param high_priority True if a high priortity message. + */ +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 + * @param[in] type Stream message type + * @param[in] id Stream ID. + */ +void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, uint32_t type, + uint32_t id); + +/** + * \brief Build component event IPC message. + * @param[in,out] event Component event message + * @param[in] type Component event type + * @param[in] id Component ID. + */ +void ipc_build_comp_event(struct sof_ipc_comp_event *event, uint32_t type, + uint32_t id); + +/** + * \brief Check if trace buffer is ready for transmission. + * @param[in,out] avail Data available in trace buffer + */ +bool ipc_trigger_trace_xfer(uint32_t avail); + +/** + * \brief Build trace position IPC message. + * @param[in,out] posn Trace position message + */ +void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn); + +#endif diff --git a/src/include/sof/ipc/notification_pool.h b/src/include/sof/ipc/notification_pool.h new file mode 100644 index 000000000000..835399307ae2 --- /dev/null +++ b/src/include/sof/ipc/notification_pool.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __SOF_IPC_NOTIFICATION_POOL_H__ +#define __SOF_IPC_NOTIFICATION_POOL_H__ + +#include <stdint.h> +#include <sof/ipc/msg.h> + +/** + * @brief Retrieves an IPC notification message from the pool. + * + * This function retrieves and returns an IPC notification message + * of the specified size from the notification pool. The size of the + * message is limited by the maximum size available in the pool. + * + * @param size The size of the IPC message to retrieve. + * @return A pointer to the retrieved IPC message, or NULL if retrieval fails. + */ +struct ipc_msg *ipc_notification_pool_get(size_t size); + +#if CONFIG_LIBRARY +/** + * @brief Frees all IPC notification messages in the pool. + * + * This function frees all notification messages currently held in + * the pool free list and resets the pool depth counter. It is + * required only in library (testbench) build. + */ +void ipc_notification_pool_free(void); +#endif /* CONFIG_LIBRARY */ + +#endif /* __SOF_IPC_NOTIFICATION_POOL_H__ */ diff --git a/src/include/sof/ipc/schedule.h b/src/include/sof/ipc/schedule.h new file mode 100644 index 000000000000..3f3e12059701 --- /dev/null +++ b/src/include/sof/ipc/schedule.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_IPC_SCHEDULE_H__ +#define __SOF_IPC_SCHEDULE_H__ + +#include <rtos/task.h> +#include <rtos/sof.h> +#include <stdbool.h> +#include <stdint.h> + +/** \brief Scheduling period for IPC task in microseconds. */ +#define IPC_PERIOD_USEC 100 + +struct ipc; + +/** + * \brief Get IPC command processing deadline. + * @param data Task structure. + */ +static inline uint64_t ipc_task_deadline(void *data) +{ + /* TODO: Currently it's a workaround to execute IPC tasks ASAP. + * In the future IPCs should have a cycle budget and deadline + * should be calculated based on that value. This means every + * IPC should have its own maximum number of cycles that is required + * to finish processing. This will allow us to calculate task deadline. + */ + return SOF_TASK_DEADLINE_NOW; +} + +/** + * \brief Schedule processing of the next IPC command from host. + * @param ipc The global IPC context. + */ +void ipc_schedule_process(struct ipc *ipc); + +#endif diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h new file mode 100644 index 000000000000..3503c7a407d8 --- /dev/null +++ b/src/include/sof/ipc/topology.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_IPC_TOPOLOGY_H__ +#define __SOF_IPC_TOPOLOGY_H__ + +#include <sof/audio/buffer.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/pipeline.h> +#include <rtos/alloc.h> +#include <sof/lib/memory.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/task.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/trace/trace.h> +#include <sof/ipc/common.h> +#include <stdbool.h> +#include <stdint.h> + +/* generic IPC pipeline regardless of ABI MAJOR type that is always 4 byte aligned */ +typedef uint32_t ipc_pipe_new; +typedef uint32_t ipc_pipe_comp_connect; +typedef uint32_t ipc_comp; + +/* + * Topology IPC logic uses standard types for abstract IPC features. This means all ABI MAJOR + * abstraction is done in the IPC layer only and not in the surrounding infrastructure. + */ +#if CONFIG_IPC_MAJOR_3 +#include <ipc/topology.h> +#define ipc_from_pipe_new(x) ((struct sof_ipc_pipe_new *)x) +#define ipc_from_pipe_connect(x) ((struct sof_ipc_pipe_comp_connect *)x) +#define ipc_from_comp_new(x) ((struct sof_ipc_comp *)x) +#define ipc_from_dai_config(x) ((struct sof_ipc_dai_config *)x) +#elif CONFIG_IPC_MAJOR_4 +#include <ipc4/pipeline.h> +#include <ipc4/module.h> +#include <ipc4/gateway.h> +#define ipc_from_pipe_new(x) ((struct ipc4_pipeline_create *)x) +#define ipc_from_pipe_connect(x) ((struct ipc4_module_bind_unbind *)x) + +struct ipc_comp_dev; +const struct comp_driver *ipc4_get_comp_drv(uint32_t module_id); +struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id); +int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma); +int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma); +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, uint32_t cmd); +int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size); +int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd); +int ipc4_pipeline_trigger(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *delayed); +int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer, + uint32_t size, uint32_t device_id, int dma_cfg_idx); +const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data_wrapper(void); + +#else +#error "No or invalid IPC MAJOR version selected." +#endif + +#define ipc_to_pipe_new(x) ((ipc_pipe_new *)x) +#define ipc_to_pipe_connect(x) ((ipc_pipe_comp_connect *)x) +#define ipc_to_comp_new(x) ((ipc_comp *)x) + +struct ipc_msg; + +#define COMP_TYPE_ANY 0 +#define COMP_TYPE_COMPONENT 1 +#define COMP_TYPE_BUFFER 2 +#define COMP_TYPE_PIPELINE 3 + +#define IPC_COMP_ALL 0 +#define IPC_COMP_IGNORE_REMOTE 1 + +/* IPC generic component device */ +struct ipc_comp_dev { + uint16_t type; /* COMP_TYPE_ */ + uint16_t core; + uint32_t id; + + /* component type data */ + union { + struct comp_dev *cd; + struct comp_buffer *cb; + struct pipeline *pipeline; + }; + + /* lists */ + struct list_item list; /* list in components */ +}; + +/** + * \brief Create a new IPC component. + * @param ipc The global IPC context. + * @param new New IPC component descriptor. + * @return 0 on success or negative error. + */ +int ipc_comp_new(struct ipc *ipc, ipc_comp *new); + +/** + * \brief Free an IPC component. + * @param ipc The global IPC context. + * @param comp_id Component ID to free. + * @return 0 on success or negative error. + */ +int ipc_comp_free(struct ipc *ipc, uint32_t comp_id); + +/** + * \brief Create a new IPC buffer. + * @param ipc The global IPC context. + * @param buffer New IPC buffer descriptor. + * @return 0 on success or negative error. + */ +int ipc_buffer_new(struct ipc *ipc, const struct sof_ipc_buffer *buffer); + +/** + * \brief Free an IPC buffer. + * @param ipc The global IPC context. + * @param buffer_id buffer ID to free. + * @return 0 on success or negative error. + */ +int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id); + +/** + * \brief Create a new IPC pipeline. + * @param ipc The global IPC context. + * @param pipeline New IPC pipeline descriptor. + * @return 0 on success or negative error. + */ +int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *pipeline); + +/** + * \brief Free an IPC pipeline. + * @param ipc The global IPC context. + * @param comp_id Pipeline ID to free. + * @return 0 on success or negative error. + */ +int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id); + +/** + * \brief Complete an IPC pipeline. + * @param ipc The global IPC context. + * @param comp_id Pipeline ID to complete. + * @return 0 on success or negative error. + */ +int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id); + +/** + * \brief Connect components together on a pipeline. + * @param ipc The global IPC context. + * @param connect Components to connect together.. + * @return 0 on success or negative error. + */ +int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *connect); + +/** + * \brief Disconnect components in a pipeline. + * @param ipc The global IPC context. + * @param connect Components. + * @return 0 on success or negative error. + */ +int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *connect); + +/** + * \brief Get component device from component type and ID. + * @param ipc The global IPC context. + * @param type The component type + * @param id The component ID. + * @return Component device or NULL. + */ +struct ipc_comp_dev *ipc_get_comp_dev(struct ipc *ipc, uint16_t type, uint32_t id); + +/** + * \brief Get component device from pipeline ID and type. + * @param ipc The global IPC context. + * @param type The component type. + * @param ppl_id The pipeline ID. + * @param ignore_remote Omit component from different core if set to IPC_COMP_IGNORE_REMOTE + * @return component device or NULL. + */ +struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, + uint32_t ppl_id, uint32_t ignore_remote); +/** + * \brief Get buffer device from pipeline ID. + * @param ipc The global IPC context. + * @param pipeline_id The pipeline ID. + * @param dir Pipeline stream direction. + * @return Pipeline device or NULL. + */ +struct ipc_comp_dev *ipc_get_ppl_comp(struct ipc *ipc, + uint32_t pipeline_id, int dir); + +/** + * \brief Get pipeline ID from component. + * @param icd The component device. + * @return Pipeline ID or negative error. + */ +int32_t ipc_comp_pipe_id(const struct ipc_comp_dev *icd); + +/** + * \brief Configure all DAI components attached to DAI. + * @param ipc Global IPC context. + * @param common_config Common DAI configuration. + * @param spec_config Specific DAI configuration. + * @return 0 on success or negative error. + */ +int ipc_comp_dai_config(struct ipc *ipc, struct ipc_config_dai *common_config, + void *spec_config); + +/* + * Warning: duplicate declaration in component.h + */ +int comp_verify_params(struct comp_dev *dev, uint32_t flag, + struct sof_ipc_stream_params *params); + +/** + * \brief connect component and buffer + * @param comp Component dev + * @param comp_core comp core id + * @param buffer Component buffer + * @param dir connection direction + * @return connection status + */ +int comp_buffer_connect(struct comp_dev *comp, uint32_t comp_core, + struct comp_buffer *buffer, uint32_t dir); + +#define ipc_get_comp_by_id(ipc, comp_id) ipc_get_comp_dev(ipc, COMP_TYPE_COMPONENT, comp_id) +#define ipc_get_pipeline_by_id(ipc, ppln_id) ipc_get_comp_dev(ipc, COMP_TYPE_PIPELINE, ppln_id) +#define ipc_get_buffer_by_id(ipc, buf_id) ipc_get_comp_dev(ipc, COMP_TYPE_BUFFER, buf_id) + +#endif diff --git a/src/include/sof/lib/agent.h b/src/include/sof/lib/agent.h index 041fc6840982..6e70a4ce997d 100644 --- a/src/include/sof/lib/agent.h +++ b/src/include/sof/lib/agent.h @@ -8,9 +8,12 @@ #ifndef __SOF_LIB_AGENT_H__ #define __SOF_LIB_AGENT_H__ +#include <rtos/atomic.h> +#include <sof/lib/memory.h> #include <sof/lib/perf_cnt.h> -#include <sof/schedule/task.h> -#include <config.h> +#include <rtos/task.h> +#include <rtos/sof.h> + #include <stdbool.h> #include <stdint.h> @@ -25,15 +28,38 @@ struct sa { struct perf_cnt_data pcd; #endif struct task work; + atomic_t panic_cnt; /**< ref counter for panic_on_delay property */ + bool panic_on_delay; /**< emits panic on delay if true */ }; #if CONFIG_HAVE_AGENT +/** + * Enables or disables panic on agent delay. + * @param enabled True for panic enabling, false otherwise. + */ +static inline void sa_set_panic_on_delay(bool enabled) +{ + struct sa *sa = sof_get()->sa; + + if (enabled) + atomic_add(&sa->panic_cnt, 1); + else + atomic_sub(&sa->panic_cnt, 1); + + /* enable panic only if no refs */ + sa->panic_on_delay = !atomic_read(&sa->panic_cnt); + +} + void sa_init(struct sof *sof, uint64_t timeout); +void sa_exit(struct sof *sof); #else static inline void sa_init(struct sof *sof, uint64_t timeout) { } +static inline void sa_exit(struct sof *sof) { } +static inline void sa_set_panic_on_delay(bool enabled) { } #endif diff --git a/src/include/sof/lib/alloc.h b/src/include/sof/lib/alloc.h deleted file mode 100644 index d75059b4b2f6..000000000000 --- a/src/include/sof/lib/alloc.h +++ /dev/null @@ -1,264 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_LIB_ALLOC_H__ -#define __SOF_LIB_ALLOC_H__ - -#include <sof/bit.h> -#include <sof/common.h> -#include <sof/lib/cache.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/string.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <config.h> -#include <stddef.h> -#include <stdint.h> - -struct dma_copy; -struct dma_sg_config; - -#define trace_mem_error(__e, ...) \ - trace_error(TRACE_CLASS_MEM, __e, ##__VA_ARGS__) -#define trace_mem_init(__e, ...) \ - trace_event(TRACE_CLASS_MEM, __e, ##__VA_ARGS__) - -/* Heap Memory Zones - * - * The heap has three different zones from where memory can be allocated :- - * - * 1) System Zone. Fixed size heap where alloc always succeeds and is never - * freed. Used by any init code that will never give up the memory. - * - * 2) Runtime Zone. Main and larger heap zone where allocs are not guaranteed to - * succeed. Memory can be freed here. - * - * 3) Buffer Zone. Largest heap zone intended for audio buffers. - * - * 4) System Runtime Zone. Heap zone intended for runtime objects allocated - * by the kernel part of the code. - * - * See platform/memory.h for heap size configuration and mappings. - */ - -/* heap zone types */ -enum mem_zone { - SOF_MEM_ZONE_SYS = 0, - SOF_MEM_ZONE_SYS_RUNTIME, - SOF_MEM_ZONE_RUNTIME, - SOF_MEM_ZONE_BUFFER, -}; - -/* heap zone flags */ -#define SOF_MEM_FLAG_SHARED BIT(0) - -struct mm_info { - uint32_t used; - uint32_t free; -}; - -struct block_hdr { - uint16_t size; /* size in blocks for continuous allocation */ - uint16_t used; /* usage flags for page */ - void *unaligned_ptr; /* align ptr */ -} __packed; - -struct block_map { - uint16_t block_size; /* size of block in bytes */ - uint16_t count; /* number of blocks in map */ - uint16_t free_count; /* number of free blocks */ - uint16_t first_free; /* index of first free block */ - struct block_hdr *block; /* base block header */ - uint32_t base; /* base address of space */ -}; - -#define BLOCK_DEF(sz, cnt, hdr) \ - {.block_size = sz, .count = cnt, .free_count = cnt, .block = hdr, \ - .first_free = 0} - -struct mm_heap { - uint32_t blocks; - struct block_map *map; - uint32_t heap; - uint32_t size; - uint32_t caps; - struct mm_info info; -}; - -/* heap block memory map */ -struct mm { - /* system heap - used during init cannot be freed */ - struct mm_heap system[PLATFORM_HEAP_SYSTEM]; - /* system runtime heap - used for runtime system components */ - struct mm_heap system_runtime[PLATFORM_HEAP_SYSTEM_RUNTIME]; - /* general heap for components */ - struct mm_heap runtime[PLATFORM_HEAP_RUNTIME]; - /* general component buffer heap */ - struct mm_heap buffer[PLATFORM_HEAP_BUFFER]; - - struct mm_info total; - uint32_t heap_trace_updated; /* updates that can be presented */ - spinlock_t lock; /* all allocs and frees are atomic */ -}; - -/* heap allocation and free */ -void *_malloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes); -void *_zalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes); -void *_balloc(uint32_t flags, uint32_t caps, size_t bytes, uint32_t alignment); -void *_realloc(void *ptr, enum mem_zone zone, uint32_t flags, uint32_t caps, - size_t bytes); -void *_brealloc(void *ptr, uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment); -void rfree(void *ptr); - -#if CONFIG_DEBUG_HEAP - -#include <sof/trace/trace.h> - -#define rmalloc(zone, flags, caps, bytes) \ - ({void *_ptr; \ - do { \ - _ptr = _malloc(zone, flags, caps, bytes); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_runtime_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -#define rzalloc(zone, flags, caps, bytes) \ - ({void *_ptr; \ - do { \ - _ptr = _zalloc(zone, flags, caps, bytes); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_runtime_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -#define rballoc(flags, caps, bytes) \ - ({void *_ptr; \ - do { \ - _ptr = _balloc(flags, caps, bytes, \ - PLATFORM_DCACHE_ALIGN); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_buffer_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -#define rrealloc(ptr, zone, flags, caps, bytes) \ - ({void *_ptr; \ - do { \ - _ptr = _realloc(ptr, zone, flags, caps, bytes); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_buffer_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -#define rbrealloc(ptr, flags, caps, bytes) \ - ({void *_ptr; \ - do { \ - _ptr = _brealloc(ptr, flags, caps, bytes, \ - PLATFORM_DCACHE_ALIGN); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_buffer_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -#define rbrealloc_align(ptr, flags, caps, bytes, alignment) \ - ({void *_ptr; \ - do { \ - _ptr = _brealloc(ptr, flags, caps, bytes, alignment); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_buffer_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -#define rballoc_align(flags, caps, bytes, alignment) \ - ({void *_ptr; \ - do { \ - _ptr = _balloc(flags, caps, bytes, alignment); \ - if (!_ptr) { \ - trace_mem_error("failed to alloc 0x%x bytes caps 0x%x flags 0x%x",\ - bytes, caps, flags); \ - alloc_trace_buffer_heap(caps, bytes); \ - } \ - } while (0); \ - _ptr; }) - -void alloc_trace_runtime_heap(uint32_t caps, size_t bytes); -void alloc_trace_buffer_heap(uint32_t caps, size_t bytes); - -#else - -#define rmalloc(zone, flags, caps, bytes) \ - _malloc(zone, flags, caps, bytes) -#define rzalloc(zone, flags, caps, bytes) \ - _zalloc(zone, flags, caps, bytes) -#define rballoc(flags, caps, bytes) \ - _balloc(flags, caps, bytes, PLATFORM_DCACHE_ALIGN) -#define rballoc_align(flags, caps, bytes, alignment) \ - _balloc(flags, caps, bytes, alignment) -#define rrealloc(ptr, zone, flags, caps, bytes) \ - _realloc(ptr, zone, flags, caps, bytes) -#define rbrealloc(ptr, flags, caps, bytes) \ - _brealloc(ptr, flags, caps, bytes, PLATFORM_DCACHE_ALIGN) -#define rbrealloc_align(ptr, flags, caps, bytes, alignment) \ - _brealloc(ptr, flags, caps, bytes, alignment) - -#endif - -/* system heap allocation for specific core */ -void *rzalloc_core_sys(int core, size_t bytes); - -/* utility */ -#define bzero(ptr, size) \ - arch_bzero(ptr, size) - -int rstrlen(const char *s); -int rstrcmp(const char *s1, const char *s2); - -/* Heap save/restore contents and context for PM D0/D3 events */ -uint32_t mm_pm_context_size(void); -int mm_pm_context_save(struct dma_copy *dc, struct dma_sg_config *sg); -int mm_pm_context_restore(struct dma_copy *dc, struct dma_sg_config *sg); - -/* heap initialisation */ -void init_heap(struct sof *sof); - -/* frees entire heap (supported for slave core system heap atm) */ -void free_heap(enum mem_zone zone); - -/* status */ -void heap_trace_all(int force); -void heap_trace(struct mm_heap *heap, int size); - -/* retrieve memory map pointer */ -static inline struct mm *memmap_get(void) -{ - return sof_get()->memory_map; -} - -#endif /* __SOF_LIB_ALLOC_H__ */ diff --git a/src/include/sof/lib/ams.h b/src/include/sof/lib/ams.h new file mode 100644 index 000000000000..8cb3ae217400 --- /dev/null +++ b/src/include/sof/lib/ams.h @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2023 Intel Corporation + * + * Author: Krzysztof Frydryk <krzysztofx.frydryk@intel.com> + */ + +#ifndef __SOF_LIB_AMS_H__ +#define __SOF_LIB_AMS_H__ + +#include <errno.h> +#include <rtos/task.h> +#include <ipc/topology.h> +#include <rtos/alloc.h> +#include <sof/coherent.h> +#include <sof/lib/uuid.h> + +/* Reserved value "does not exist" or "unassigned" value for msg types */ +#define AMS_INVALID_MSG_TYPE 0 +/* Reserved value "does not exist" or "unassigned" value for slots */ +#define AMS_INVALID_SLOT 0xFF +/* Wildcard for module_id and instance_id values */ +#define AMS_ANY_ID 0xFFFF + +/* max number of message UUIDs */ +#define AMS_SERVICE_UUID_TABLE_SIZE 16 +/* max number of async message routes */ +#define AMS_ROUTING_TABLE_SIZE 16 +/* Space allocated for async message content*/ +#define AMS_MAX_MSG_SIZE 0x1000 + +/* Size of slots message, module id and instance id */ +#define AMS_SLOT_SIZE(msg) (AMS_MESSAGE_SIZE(msg) + sizeof(uint16_t) * 2) +#define AMS_MESSAGE_SIZE(msg) (sizeof(*msg) - sizeof(char) + (sizeof(char) * (msg->message_length))) + +/** + * \brief IXC message payload + * + * ams_message_payload - contains the actual Async Msg payload + */ +struct ams_message_payload { + /* Message IDs are assigned dynamically on new message entry creation + * For a new payload should be acquired by ams_get_message_type_id + */ + uint32_t message_type_id; + /* Producers module ID */ + uint16_t producer_module_id; + /* Producers instance ID */ + uint16_t producer_instance_id; + /* Message length */ + uint32_t message_length; + /* Message payload */ + uint8_t *message; +}; + +struct ams_slot { + uint16_t module_id; + uint16_t instance_id; + union { + struct ams_message_payload msg; + uint8_t msg_raw[AMS_MAX_MSG_SIZE]; + } u; + uint32_t __aligned(PLATFORM_DCACHE_ALIGN) pad[]; +}; + +/** + * \brief ams_msg_callback_fn + * + * Each subscriber provides this handler function for each message ID + */ +typedef void (*ams_msg_callback_fn)(const struct ams_message_payload *const ams_message_payload, + void *ctx); + +/** + * \brief Internal struct ams_consumer_entry + * + * Describes a single consumer's subscription to a single message. + * Array of 'ams_consumer_entry' structs forms AsyncMessageService's routing + * table which allows for message dispatch. + */ +struct ams_consumer_entry { + /* Message ID that will be routed via this entry */ + uint32_t message_type_id; + /* Callback provided by the subscribed consumer */ + ams_msg_callback_fn consumer_callback; + /* Additional context for consumer_callback (optional) */ + void *ctx; + /* Subscribed consumer's Module ID */ + uint16_t consumer_module_id; + /* Subscribed consumer's Module Instance ID */ + uint8_t consumer_instance_id; + /* Subscribed consumer's Module core id. Saved to speed up routing */ + uint8_t consumer_core_id; +}; + +struct ams_producer { + /* Message ID that will be routed via this entry */ + uint32_t message_type_id; + /* Subscribed producer's Module ID */ + uint16_t producer_module_id; + /* Subscribed producer's Module Instance ID */ + uint8_t producer_instance_id; +}; + +struct uuid_idx { + uint32_t message_type_id; + uint8_t message_uuid[UUID_SIZE]; +}; + +struct ams_shared_context { + /* should be only used with ams_acquire/release function, not generic ones */ + struct coherent c; + + uint32_t last_used_msg_id; + struct ams_consumer_entry rt_table[AMS_ROUTING_TABLE_SIZE]; + struct ams_producer producer_table[AMS_ROUTING_TABLE_SIZE]; + struct uuid_idx uuid_table[AMS_SERVICE_UUID_TABLE_SIZE]; + + uint32_t slot_uses[CONFIG_CORE_COUNT]; + /* marks which core already processed slot */ + uint32_t slot_done[CONFIG_CORE_COUNT]; + + struct ams_slot slots[CONFIG_CORE_COUNT]; +}; + +struct ams_context { + /* shared context must be always accessed with shared->c taken */ + struct ams_shared_context *shared; +}; + +struct ams_task { + struct task ams_task; + struct async_message_service *ams; + uint32_t pending_slots; +}; + +struct async_message_service { +#if CONFIG_SMP + struct ams_task ams_task; +#endif /* CONFIG_SMP */ + struct ams_context *ams_context; +}; + +#if CONFIG_AMS +int ams_init(void); + +/** + * \brief Get Message Type ID + * + * assigns and returns a message type ID for specified message UUID. + * The value of message type ID is dynamically assigned and it will change between runs. + * + * \param[in] message_uuid UUID of message type + * \param[in] message_type_id Unique message type ID assigned by AMS + */ +int ams_get_message_type_id(const uint8_t *message_uuid, + uint32_t *message_type_id); + +/** + * \brief Producer Register + * + * registers a producer of asynchronous messages of given message type. + * When a module instance calls this function, + * it informs the Asynchronous Messaging Service that it will be sending asynchronous messages. + * + * \param[in] message_type_id unique message type ID assigned during ams_get_message_type_id + * \param[in] module_id Module ID of module calling function + * \param[in] instance_id Instance ID of module calling function + */ +int ams_register_producer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id); + +/** + * \brief Producer Unregister + * + * unregisters a producer of asynchronous messages of given type. + * When a module instance calls this function, + * it informs the Asynchronous Messaging Service + * that it will not be sending asynchronous messages anymore. + * + * \param[in] message_type_id unique message type ID assigned during ams_get_message_type_id + * \param[in] module_id Module ID of module calling function + * \param[in] instance_id Instance ID of module calling function + */ +int ams_unregister_producer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id); + +/** + * \brief Register Consumer + * + * Registers a module instance as a consumer of specified message type. + * When specified message type is sent, + * a callback is called that was provided during registration process. + * + * The consumer callback is triggered when ams_send function was used to send a message + * and/or when ams_send_mi function with consumer's module ID and instance ID was used + * to send a message. + * + * \param[in] message_type_id unique message type ID assigned during ams_get_message_type_id + * \param[in] module_id Module ID of module calling function + * \param[in] instance_id Instance ID of module calling function + * \param[in] function callback that should be called when message is received + * \param[in] ctx Optional context that is passed to callback + */ +int ams_register_consumer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id, + ams_msg_callback_fn function, + void *ctx); + +/** + * \brief Unegister Consumer + * + * Unregisters a consumer of specified message type + * + * \param[in] message_type_id unique message type ID assigned during ams_get_message_type_id + * \param[in] module_id Module ID of module calling function + * \param[in] instance_id Instance ID of module calling function + * \param[in] function callback that should be called when message is received + */ +int ams_unregister_consumer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id, + ams_msg_callback_fn function); + +/** + * \brief Message Send + * + * Sends asynchronous message to all registered consumers by registered producer. + * The consumers registered on the same core may be called in context of a message producer + * + * \param[in] payload Message payload + */ +int ams_send(const struct ams_message_payload *payload); + +/** + * \brief Message Send to Module Instance + * + * Sends asynchronous message to specified module instance. + * The consumer registered on the same core may be called in context of a message producer + * + * \param[in] payload Message payload + * \param[in] module_id Module ID of consumer that messages is sent to + * \param[in] instance_id Instance ID of consumer that messages is sent to + */ +int ams_send_mi(const struct ams_message_payload *payload, + uint16_t module_id, uint16_t instance_id); + +static inline struct ams_shared_context *ams_ctx_get(void) +{ + return sof_get()->ams_shared_ctx; +} +#else +static inline int ams_init(void) { return 0; } +static inline int ams_get_message_type_id(const uint8_t *message_uuid, + uint32_t *message_type_id) { return 0; } + +static inline int ams_register_producer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id) { return 0; } + +static inline int ams_unregister_producer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id) { return 0; } + +static inline int ams_register_consumer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id, + ams_msg_callback_fn function, + void *ctx) { return 0; } + +static inline int ams_unregister_consumer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id, + ams_msg_callback_fn function) { return 0; } + +static inline int ams_send(const struct ams_message_payload *payload) { return 0; } + +static inline int ams_send_mi(const struct ams_message_payload *payload, uint16_t module_id, + uint16_t instance_id) { return 0; } + +static inline struct ams_shared_context *ams_ctx_get(void) +{ + return NULL; +} + +#endif /* CONFIG_AMS */ + +#if CONFIG_SMP && CONFIG_AMS +int process_incoming_message(uint32_t slot); +#else +static inline int process_incoming_message(uint32_t slot) { return 0; } +#endif /* CONFIG_SMP && CONFIG_AMS */ + +struct async_message_service **arch_ams_get(void); + +#endif /* __SOF_LIB_AMS_H__ */ 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 <ievgen.ganakov@intel.com> + */ + +#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/cache.h b/src/include/sof/lib/cache.h deleted file mode 100644 index 1418845fc096..000000000000 --- a/src/include/sof/lib/cache.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file include/sof/lib/cache.h - * \brief Cache header file - * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __SOF_LIB_CACHE_H__ -#define __SOF_LIB_CACHE_H__ - -#include <arch/lib/cache.h> - -/* writeback and invalidate data */ -#define CACHE_WRITEBACK_INV 0 - -/* invalidate data */ -#define CACHE_INVALIDATE 1 - -#endif /* __SOF_LIB_CACHE_H__ */ diff --git a/src/include/sof/lib/clk.h b/src/include/sof/lib/clk.h deleted file mode 100644 index 0d80dcd78843..000000000000 --- a/src/include/sof/lib/clk.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifndef __SOF_LIB_CLK_H__ -#define __SOF_LIB_CLK_H__ - -#include <platform/lib/clk.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <stdint.h> - -struct timer; - -#define CLOCK_NOTIFY_PRE 0 -#define CLOCK_NOTIFY_POST 1 - -struct clock_notify_data { - uint32_t old_freq; - uint32_t old_ticks_per_msec; - uint32_t freq; - uint32_t ticks_per_msec; - uint32_t message; -}; - -struct freq_table { - uint32_t freq; - uint32_t ticks_per_msec; -}; - -struct clock_info { - uint32_t freqs_num; - const struct freq_table *freqs; - uint32_t default_freq_idx; - uint32_t current_freq_idx; - uint32_t notification_id; - uint32_t notification_mask; - spinlock_t lock; - int (*set_freq)(int clock, int freq_idx); -}; - -uint32_t clock_get_freq(int clock); - -void clock_set_freq(int clock, uint32_t hz); - -uint64_t clock_ms_to_ticks(int clock, uint64_t ms); - -void platform_timer_set_delta(struct timer *timer, uint64_t ns); - -static inline struct clock_info *clocks_get(void) -{ - return sof_get()->clocks; -} - -#endif /* __SOF_LIB_CLK_H__ */ diff --git a/src/include/sof/lib/cpu-clk-manager.h b/src/include/sof/lib/cpu-clk-manager.h new file mode 100644 index 000000000000..1ea26b2c4f85 --- /dev/null +++ b/src/include/sof/lib/cpu-clk-manager.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Krzysztof Frydryk <frydryk.krzysztof@intel.com> + */ + +/** + * \file include/sof/lib/cpu-clk-manager.h + * \brief CPU clk manager definition + * \author Krzysztof Frydryk <krzysztofx.frydryk@intel.com> + */ + +#ifndef __SOF_LIB_CPU_CLK_MANAGER_H__ +#define __SOF_LIB_CPU_CLK_MANAGER_H__ + +#include <rtos/spinlock.h> +#include <rtos/sof.h> +#include <stdint.h> + +/** + * \brief CPS budget data. + */ +struct kcps_budget_data { + /* uncache only */ + int kcps_consumption[CONFIG_CORE_COUNT]; /* Sum of declared consumptions on core */ + struct k_spinlock lock; +}; + +/** + * \brief Declare KCPS usage on core + * + * Declare KCPS (kilo cycles per second) CPU usage on core and adjust + * CPU clock according to sum of declared consumptions. + * + * Declared consumption can be negative in case of freeing CPS. + * + * @param core The core to which consumption should be pinned + * @param kcps_delta declared usage. Can be negative. + */ +int core_kcps_adjust(int core, int kcps_delta); + +/** + * \brief Get KCPS usage on core + * + * Get declared KCPS usage on core + * + * @param core The core which consumption should be returned + */ +int core_kcps_get(int core); + +/** + * \brief Init KCPS budget mechanism + */ +int kcps_budget_init(void); + +#endif /*__SOF_LIB_CPU_CLK_MANAGER_H__ */ diff --git a/src/include/sof/lib/cpu.h b/src/include/sof/lib/cpu.h deleted file mode 100644 index 972c63118506..000000000000 --- a/src/include/sof/lib/cpu.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file include/sof/lib/cpu.h - * \brief CPU header file - * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __SOF_LIB_CPU_H__ -#define __SOF_LIB_CPU_H__ - -#include <platform/lib/cpu.h> - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <arch/lib/cpu.h> -#include <stdbool.h> - -#if PLATFORM_CORE_COUNT > MAX_CORE_COUNT -#error "Invalid core count - exceeding core limit" -#endif - -static inline int cpu_get_id(void) -{ - return arch_cpu_get_id(); -} - -static inline bool cpu_is_slave(int id) -{ - return id != PLATFORM_MASTER_CORE_ID; -} - -static inline bool cpu_is_me(int id) -{ - return id == cpu_get_id(); -} - -static inline void cpu_enable_core(int id) -{ - arch_cpu_enable_core(id); -} - -static inline void cpu_disable_core(int id) -{ - arch_cpu_disable_core(id); -} - -static inline int cpu_is_core_enabled(int id) -{ - return arch_cpu_is_core_enabled(id); -} - -#endif - -#endif /* __SOF_LIB_CPU_H__ */ diff --git a/src/include/sof/lib/dai-legacy.h b/src/include/sof/lib/dai-legacy.h new file mode 100644 index 000000000000..c1b7c0a28653 --- /dev/null +++ b/src/include/sof/lib/dai-legacy.h @@ -0,0 +1,602 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * + * Renamed from dai.h to dai-legacy.h because of Zephyr refactoring and + * the file content has not changed. + */ + +/** + * \cond XTOS_DUP_FIXME + * + * \file include/sof/lib/dai.h + * \brief DAI Drivers definition + * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> + * \author Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_LIB_DAI_LEGACY_H__ +#define __SOF_LIB_DAI_LEGACY_H__ + +#include <platform/lib/dai.h> +#include <rtos/bit.h> +#include <sof/list.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/dma.h> +#include <sof/list.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/trace/trace.h> +#include <sof/ipc/topology.h> +#include <sof/audio/pcm_converter.h> +#include <sof/audio/ipc-config.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +struct dai; +struct sof_ipc_stream_params; + +/** \addtogroup sof_dai_drivers DAI Drivers + * DAI Drivers API specification. + * @{ + */ + +#define DAI_CLOCK_IN 0 +#define DAI_CLOCK_OUT 1 + +#define DAI_DIR_PLAYBACK 0 +#define DAI_DIR_CAPTURE 1 + +#define DAI_NUM_SLOT_MAPS 8 + +#define DAI_INFO_TYPE 0 +#define DAI_INFO_DMA_CAPS 1 +#define DAI_INFO_DMA_DEV 2 + +/* DAI flags */ + +/** \brief IRQ used for copy() timer */ +#define DAI_FLAGS_IRQ_CB BIT(0) + +/* DAI get() flags */ + +/** \brief If the device does not exist it will be created */ +#define DAI_CREAT BIT(0) + +/** + * \brief DAI operations - all optional + * + * DAI drivers may allocate private data, + * which can be set with 'dai_set_drvdata' and retrieved with 'dai_get_drvdata'. + * If a single DAI instance can have multiple DMA links and/or there is + * some other possibility of the same instance being used in multiple + * contexts at the same time, the private data should be allocated in the + * SOF_MEM_FLAG_COHERENT. + */ +struct dai_ops { + int (*set_config)(struct dai *dai, struct ipc_config_dai *config, + const void *spec_config); + int (*trigger)(struct dai *dai, int cmd, int direction); + int (*get_hw_params)(struct dai *dai, + struct sof_ipc_stream_params *params, int dir); + int (*hw_params)(struct dai *dai, struct sof_ipc_stream_params *params); + int (*get_handshake)(struct dai *dai, int direction, int stream_id); + int (*get_fifo)(struct dai *dai, int direction, int stream_id); + int (*probe)(struct dai *dai); + int (*remove)(struct dai *dai); + uint32_t (*get_init_delay_ms)(struct dai *dai); + int (*get_fifo_depth)(struct dai *dai, int direction); + void (*copy)(struct dai *dai); /* Can be used by DAIs to prepare for data copying */ +}; + +struct timestamp_cfg { + uint32_t walclk_rate; /* Rate in Hz, e.g. 19200000 */ + int type; /* SSP, DMIC, HDA, etc. */ + int direction; /* Playback, capture */ + int index; /* For SSPx to select correct timestamp register */ + int dma_id; /* GPDMA id*/ + int dma_chan_index; /* Used GPDMA channel */ + int dma_chan_count; /* Channels in single GPDMA */ +}; + +struct timestamp_data { + uint64_t walclk; /* Wall clock */ + uint64_t sample; /* Sample count */ + uint32_t walclk_rate; /* Rate in Hz, e.g. 19200000 */ +}; + +struct timestamp_ops { + int (*ts_config)(struct dai *dai, struct timestamp_cfg *cfg); + int (*ts_start)(struct dai *dai, struct timestamp_cfg *cfg); + int (*ts_stop)(struct dai *dai, struct timestamp_cfg *cfg); + int (*ts_get)(struct dai *dai, struct timestamp_cfg *cfg, + struct timestamp_data *tsd); +}; + +struct dai_driver { + uint32_t type; /**< type, one of SOF_DAI_... */ + const struct sof_uuid_entry *uid; + struct tr_ctx *tctx; + uint32_t dma_caps; + uint32_t dma_dev; + struct dai_ops ops; + struct timestamp_ops ts_ops; +}; + +/** + * \brief DAI slot map to audio channel + */ +struct dai_slot_map { + uint32_t channel; /**< channel ID - CHAN_ID_ */ + uint32_t slot; /**< physical slot index */ +}; + +struct dai_plat_fifo_data { + uint32_t offset; + uint32_t width; + uint32_t depth; + uint32_t watermark; + uint32_t handshake; +}; + +/** + * \brief DAI platform data + */ +struct dai_plat_data { + uint32_t base; + int irq; + const char *irq_name; + uint32_t flags; + struct dai_plat_fifo_data fifo[2]; +}; + +/** + * \brief llp slot info for memory window + */ +struct llp_slot_info { + uint32_t node_id; + uint32_t reg_offset; +}; + +typedef int (*channel_copy_func)(const struct audio_stream *src, unsigned int src_channel, + struct audio_stream *dst, unsigned int dst_channel, + unsigned int frames); + +/** + * \brief DAI runtime data + */ +struct dai_data { + /* local DMA config */ + struct dma_chan_data *chan; + uint32_t stream_id; + struct dma_sg_config config; + struct comp_dev *dai_dev; + struct comp_buffer *dma_buffer; + struct comp_buffer *local_buffer; + struct timestamp_cfg ts_config; + struct dai *dai; + struct dma *dma; + struct dai_group *group; /* NULL if no group assigned */ + int xrun; /* true if we are doing xrun recovery */ + + pcm_converter_func process; /* processing function */ + uint32_t chmap; + channel_copy_func channel_copy; /* channel copy func used by multi-endpoint + * gateway to mux/demux stream from/to multiple + * DMA buffers + */ + + uint32_t period_bytes; /* number of bytes per one period */ + uint64_t total_data_processed; + + struct ipc_config_dai ipc_config; /* generic common config */ + void *dai_spec_config; /* dai specific config from the host */ + + uint64_t wallclock; /* wall clock at stream start */ + + /* + * flag indicating two-step stop/pause for DAI comp and DAI DMA. + * DAI stop occurs during STREAM_TRIG_STOP IPC and DMA stop during DAI_CONFIG IPC with + * the SOF_DAI_CONFIG_FLAGS_HW_FREE flag. + * DAI pause occurs during STREAM_TRIG_PAUSE IPC and DMA pause during DAI_CONFIG IPC with + * the SOF_DAI_CONFIG_FLAGS_PAUSE flag. + */ + bool delayed_dma_stop; + + /* llp slot info in memory windows */ + struct llp_slot_info slot_info; + + /* Copier gain params */ + struct copier_gain_params *gain_data; +}; + +struct dai { + uint32_t index; /**< index */ + uint32_t type; /**< added for dai-zephyr.h compatibility */ + struct k_spinlock lock; /**< locking mechanism */ + int sref; /**< simple ref counter, guarded by lock */ + struct dai_plat_data plat_data; + const struct dai_driver *drv; + const struct dai_data *dd; + void *priv_data; +}; + +/** + * \brief Array of DAIs grouped by type. + */ +struct dai_type_info { + uint32_t type; /**< Type */ + struct dai *dai_array; /**< Array of DAIs */ + size_t num_dais; /**< Number of elements in dai_array */ +}; + +/* dai tracing */ +#define trace_dai_drv_get_tr_ctx(drv_p) ((drv_p)->tctx) +#define trace_dai_drv_get_id(drv_p) (-1) +#define trace_dai_drv_get_subid(drv_p) (-1) + +#define trace_dai_get_tr_ctx(dai_p) ((dai_p)->drv->tctx) +#define trace_dai_get_id(dai_p) ((dai_p)->drv->type) +#define trace_dai_get_subid(dai_p) ((dai_p)->index) + +#if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) +/* driver level tracing */ +#define dai_cl_err(drv_p, __e, ...) LOG_ERR(__e, ##__VA_ARGS__) + +#define dai_cl_warn(drv_p, __e, ...) LOG_WRN(__e, ##__VA_ARGS__) + +#define dai_cl_info(drv_p, __e, ...) LOG_INF(__e, ##__VA_ARGS__) + +#define dai_cl_dbg(drv_p, __e, ...) LOG_DBG(__e, ##__VA_ARGS__) + +/* device level tracing */ +#define dai_err(dai_p, __e, ...) LOG_ERR(__e, ##__VA_ARGS__) + +#define dai_warn(dai_p, __e, ...) LOG_WRN(__e, ##__VA_ARGS__) + +#define dai_info(dai_p, __e, ...) LOG_INF(__e, ##__VA_ARGS__) + +#define dai_dbg(dai_p, __e, ...) LOG_DBG(__e, ##__VA_ARGS__) + +#else +/* class (driver) level (no device object) tracing */ + +#define dai_cl_err(drv_p, __e, ...) \ + trace_dev_err(trace_dai_drv_get_tr_ctx, \ + trace_dai_drv_get_id, \ + trace_dai_drv_get_subid, \ + drv_p, __e, ##__VA_ARGS__) + +#define dai_cl_warn(drv_p, __e, ...) \ + trace_dev_warn(trace_dai_drv_get_tr_ctx,\ + trace_dai_drv_get_id, \ + trace_dai_drv_get_subid, \ + drv_p, __e, ##__VA_ARGS__) + +#define dai_cl_info(drv_p, __e, ...) \ + trace_dev_info(trace_dai_drv_get_tr_ctx,\ + trace_dai_drv_get_id, \ + trace_dai_drv_get_subid, \ + drv_p, __e, ##__VA_ARGS__) + +#define dai_cl_dbg(drv_p, __e, ...) \ + trace_dev_dbg(trace_dai_drv_get_tr_ctx, \ + trace_dai_drv_get_id, \ + trace_dai_drv_get_subid, \ + drv_p, __e, ##__VA_ARGS__) + +/* device tracing */ + +#define dai_err(dai_p, __e, ...) \ + trace_dev_err(trace_dai_get_tr_ctx, \ + trace_dai_get_id, \ + trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) + +#define dai_warn(dai_p, __e, ...) \ + trace_dev_warn(trace_dai_get_tr_ctx, \ + trace_dai_get_id, \ + trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) + +#define dai_info(dai_p, __e, ...) \ + trace_dev_info(trace_dai_get_tr_ctx, \ + trace_dai_get_id, \ + trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) + +#define dai_dbg(dai_p, __e, ...) \ + trace_dev_dbg(trace_dai_get_tr_ctx, \ + trace_dai_get_id, \ + trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) + +#endif /* #if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) */ + +/** + * \brief API to request DAI group + * + * Returns a DAI group for the given ID and + * increments the counter of DAIs in the group. + * + * If a group for the given ID doesn't exist, + * it will either return NULL or allocate a new group structure + * if the CREATE flag is supplied. + * + * \param[in] group_id Group ID + * \param[in] flags Flags (CREATE) + */ +struct dai_group *dai_group_get(uint32_t group_id, uint32_t flags); + +/** + * \brief API to release DAI group + * + * Decrements the DAI counter inside the group. + * + * \param[in] group Group + */ +void dai_group_put(struct dai_group *group); + +/** + * \brief DAI group information + */ +struct dai_group { + /** + * Group ID + */ + uint32_t group_id; + + /** + * Number of DAIs in this group + */ + uint32_t num_dais; + + /** + * Number of DAIs to receive a trigger before processing begins + */ + uint32_t trigger_counter; + + /** + * Trigger command to propagate + */ + int trigger_cmd; + + /** + * Last trigger error + */ + int trigger_ret; + + /** + * Group list + */ + struct list_item list; +}; + +/** + * \brief Holds information about array of DAIs grouped by type. + */ +struct dai_info { + const struct dai_type_info *dai_type_array; + size_t num_dai_types; +}; + +/** + * \brief API to initialize a platform DAI. + * + * \param[in] sof Pointer to firmware main context. + */ +int dai_init(struct sof *sof); + +/** + * \brief API to request a platform DAI. + * + * \param[in] type Type of requested DAI. + * \param[in] index Index of requested DAI. + * \param[in] flags Flags (CREATE) + */ +struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags); + +/** + * \brief API to release a platform DAI. + * + * @param[in] dai DAI to relese. + */ +void dai_put(struct dai *dai); + +#define dai_set_drvdata(dai, data) \ + (dai->priv_data = data) +#define dai_get_drvdata(dai) \ + dai->priv_data +#define dai_base(dai) \ + dai->plat_data.base +#define dai_irq(dai) \ + dai->plat_data.irq +#define dai_fifo(dai, direction) \ + dai->plat_data.fifo[direction].offset + +/** + * \brief Digital Audio interface formatting + */ +static inline int dai_set_config(struct dai *dai, struct ipc_config_dai *config, + const void *spec_config, size_t size) +{ + return dai->drv->ops.set_config(dai, config, spec_config); +} + +/** + * \brief Digital Audio interface trigger + */ +static inline int dai_trigger(struct dai *dai, int cmd, int direction) +{ + return dai->drv->ops.trigger(dai, cmd, direction); +} + +/** + * \brief Get Digital Audio interface stream parameters + */ +static inline int dai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, + int dir) +{ + return dai->drv->ops.get_hw_params(dai, params, dir); +} + +/** + * \brief Configure Digital Audio interface stream parameters + */ +static inline int dai_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params) +{ + if (dai->drv->ops.hw_params) + return dai->drv->ops.hw_params(dai, params); + + return 0; +} + +/** + * \brief Get Digital Audio interface DMA Handshake + */ +static inline int dai_get_handshake(struct dai *dai, int direction, + int stream_id) +{ + return dai->drv->ops.get_handshake(dai, direction, stream_id); +} + +/** + * \brief Get Digital Audio interface FIFO address + */ +static inline int dai_get_fifo(struct dai *dai, int direction, + int stream_id) +{ + return dai->drv->ops.get_fifo(dai, direction, stream_id); +} + +/** + * \brief Digital Audio interface Probe + */ +static inline int dai_probe(struct dai *dai) +{ + return dai->drv->ops.probe(dai); +} + +/** + * \brief Digital Audio interface Remove + */ +static inline int dai_remove(struct dai *dai) +{ + return dai->drv->ops.remove(dai); +} + +/** + * \brief Get DAI initial delay in milliseconds + */ +static inline uint32_t dai_get_init_delay_ms(struct dai *dai) +{ + if (dai && dai->drv->ops.get_init_delay_ms) + return dai->drv->ops.get_init_delay_ms(dai); + + return 0; +} + +static inline int dai_get_fifo_depth(struct dai *dai, int direction) +{ + if (dai && dai->drv->ops.get_fifo_depth) + return dai->drv->ops.get_fifo_depth(dai, direction); + + return 0; +} + +/** + * \brief Get driver specific DAI information + */ +static inline int dai_get_info(struct dai *dai, int info) +{ + int ret; + + switch (info) { + case DAI_INFO_TYPE: + ret = dai->drv->type; + break; + case DAI_INFO_DMA_CAPS: + ret = dai->drv->dma_caps; + break; + case DAI_INFO_DMA_DEV: + ret = dai->drv->dma_dev; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static inline void dai_write(struct dai *dai, uint32_t reg, uint32_t value) +{ + io_reg_write(dai_base(dai) + reg, value); +} + +static inline uint32_t dai_read(struct dai *dai, uint32_t reg) +{ + return io_reg_read(dai_base(dai) + reg); +} + +static inline void dai_update_bits(struct dai *dai, uint32_t reg, + uint32_t mask, uint32_t value) +{ + io_reg_update_bits(dai_base(dai) + reg, mask, value); +} + +static inline const struct dai_info *dai_info_get(void) +{ + return sof_get()->dai_info; +} + +/** + * \brief Configure DMA channel for DAI + */ +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 dai_data *dd, struct comp_dev *dev); + +/** + * \brief Configure DAI physical interface. + */ +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 dai_data *dd, struct comp_dev *dev, uint32_t group_id); + +/** + * \brief dai position for host driver. + */ +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 dai_data *dd, struct comp_dev *dev); + +/** + * \brief release llp slot + */ +void dai_release_llp_slot(struct dai_data *dd); +/** @}*/ + +#endif /* __SOF_LIB_DAI_LEGACY_H__ */ + +/** \endcond */ diff --git a/src/include/sof/lib/dai-zephyr.h b/src/include/sof/lib/dai-zephyr.h new file mode 100644 index 000000000000..d25474c4816d --- /dev/null +++ b/src/include/sof/lib/dai-zephyr.h @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +/** + * \file include/sof/lib/dai-zephyr.h + * \brief DAI Drivers definition + * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> + * \author Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_LIB_DAI_ZEPHYR_H__ +#define __SOF_LIB_DAI_ZEPHYR_H__ + +#include <rtos/bit.h> +#include <sof/list.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/dma.h> +#include <sof/list.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/trace/trace.h> +#include <sof/ipc/topology.h> +#include <sof/audio/pcm_converter.h> +#include <sof/audio/ipc-config.h> +#include <ipc/dai.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <zephyr/device.h> +#include <zephyr/drivers/dai.h> + +#include <sof/debug/telemetry/performance_monitor.h> + +/** \addtogroup sof_dai_drivers DAI Drivers + * DAI Drivers API specification. + * @{ + */ + +/** \brief If the device does not exist it will be created */ +#define DAI_CREAT BIT(0) + +struct dai { + uint32_t index; + uint32_t type; + uint32_t dma_caps; + uint32_t dma_dev; + const struct device *dev; + const struct dai_data *dd; + struct k_spinlock lock; /* protect properties */ +}; + +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 + */ +struct dai_group { + /** + * Group ID + */ + uint32_t group_id; + + /** + * Number of DAIs in this group + */ + uint32_t num_dais; + + /** + * Number of DAIs to receive a trigger before processing begins + */ + uint32_t trigger_counter; + + /** + * Trigger command to propagate + */ + int trigger_cmd; + + /** + * Last trigger error + */ + int trigger_ret; + + /** + * Group list + */ + struct list_item list; +}; + +/** + * \brief llp slot info for memory window + */ +struct llp_slot_info { + uint32_t node_id; + uint32_t reg_offset; +}; + +typedef int (*channel_copy_func)(const struct audio_stream *src, unsigned int src_channel, + struct audio_stream *dst, unsigned int dst_channel, + unsigned int frames); + +/** + * \brief DAI runtime data + */ +struct dai_data { + /* local DMA config */ + int chan_index; + uint32_t stream_id; + struct dma_sg_config config; + struct dma_config *z_config; + struct comp_dev *dai_dev; + struct comp_buffer *dma_buffer; + struct comp_buffer *local_buffer; + struct dai_ts_cfg ts_config; + struct dai *dai; + struct sof_dma *dma; + struct dai_group *group; /* NULL if no group assigned */ + int xrun; /* true if we are doing xrun recovery */ + + pcm_converter_func process; /* processing function */ + uint32_t chmap; + + channel_copy_func channel_copy; /* channel copy func used by multi-endpoint + * gateway to mux/demux stream from/to multiple + * DMA buffers + */ + + uint32_t period_bytes; /* number of DMA bytes per one period */ + uint64_t total_data_processed; + + struct ipc_config_dai ipc_config; /* generic common config */ + void *dai_spec_config; /* dai specific config from the host */ + + uint64_t wallclock; /* wall clock at stream start */ + + /* + * flag indicating two-step stop/pause for DAI comp and DAI DMA. + * DAI stop occurs during STREAM_TRIG_STOP IPC and DMA stop during DAI_CONFIG IPC with + * the SOF_DAI_CONFIG_FLAGS_HW_FREE flag. + * DAI pause occurs during STREAM_TRIG_PAUSE IPC and DMA pause during DAI_CONFIG IPC with + * the SOF_DAI_CONFIG_FLAGS_PAUSE flag. + */ + bool delayed_dma_stop; + + /* llp slot info in memory windows */ + struct llp_slot_info slot_info; + /* fast mode, use one byte memory to save repreated cycles */ + bool fast_mode; +#if CONFIG_XRUN_NOTIFICATIONS_ENABLE + bool xrun_notification_sent; +#endif +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* io performance measurement */ + struct io_perf_data_item *io_perf_dai_byte_count; +#endif + /* Copier gain params */ + struct copier_gain_params *gain_data; +}; + +/* these 3 are here to satisfy clk.c and ssp.h interconnection, will be removed leter */ +static inline void dai_write(struct dai *dai, uint32_t reg, uint32_t value) +{ +} + +static inline uint32_t dai_read(struct dai *dai, uint32_t reg) +{ + return 0; +} + +static inline void dai_update_bits(struct dai *dai, uint32_t reg, + uint32_t mask, uint32_t value) +{ +} + +/** + * \brief API to request DAI group + * + * Returns a DAI group for the given ID and + * increments the counter of DAIs in the group. + * + * If a group for the given ID doesn't exist, + * it will either return NULL or allocate a new group structure + * if the CREATE flag is supplied. + * + * \param[in] group_id Group ID + * \param[in] flags Flags (CREATE) + */ +struct dai_group *dai_group_get(uint32_t group_id, uint32_t flags); + +/** + * \brief API to release DAI group + * + * Decrements the DAI counter inside the group. + * + * \param[in] group Group + */ +void dai_group_put(struct dai_group *group); + +/** + * \brief API to initialize a platform DAI. + * + * \param[in] sof Pointer to firmware main context. + */ +static inline int dai_init(struct sof *sof) +{ + return 0; +} + +/** + * \brief API to request a platform DAI. + * + * \param[in] type Type of requested DAI. + * \param[in] index Index of requested DAI. + * \param[in] flags Flags (CREATE) + */ +struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags); + +/** + * \brief API to release a platform DAI. + * + * @param[in] dai DAI to relese. + */ +void dai_put(struct dai *dai); + +/** + * \brief Digital Audio interface formatting + */ +int dai_set_config(struct dai *dai, struct ipc_config_dai *config, + const void *spec_config, size_t size); + +/** + * \brief Get Digital Audio interface DMA Handshake + */ +int dai_get_handshake(struct dai *dai, int direction, int stream_id); + +/** + * \brief Get Digital Audio interface fifo depth + */ +int dai_get_fifo_depth(struct dai *dai, int direction); + +/** + * \brief Get DAI initial delay in milliseconds + */ +uint32_t dai_get_init_delay_ms(struct dai *dai); + +/** + * \brief Get DAI stream id + */ +int dai_get_stream_id(struct dai *dai, int direction); + +/** + * \brief Configure DMA channel for DAI + */ +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 dai_data *dd, struct comp_dev *dev); + +/** + * \brief Configure DAI physical interface. + */ +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 dai_data *dd, struct comp_dev *dev, uint32_t group_id); + +/** + * \brief dai position for host driver. + */ +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 dai_data *dd, struct comp_dev *dev); + +/** + * \brief release llp slot + */ +void dai_release_llp_slot(struct dai_data *dd); + +/** + * \brief Retrieve a pointer to the Zephyr device structure for a DAI of a given type and index. + */ +const struct device *dai_get_device(enum sof_ipc_dai_type type, uint32_t index); + +/** + * \brief Retrieve the list of all DAI devices. + * \param count Pointer to store the number of devices in the list. + * \return Pointer to the array of device pointers. + */ +const struct device **dai_get_device_list(size_t *count); +/** @}*/ + +#endif /* __SOF_LIB_DAI_ZEPHYR_H__ */ diff --git a/src/include/sof/lib/dai.h b/src/include/sof/lib/dai.h deleted file mode 100644 index 8aedc9941cdc..000000000000 --- a/src/include/sof/lib/dai.h +++ /dev/null @@ -1,429 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -/** - * \file include/sof/lib/dai.h - * \brief DAI Drivers definition - * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> - * \author Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_LIB_DAI_H__ -#define __SOF_LIB_DAI_H__ - -#include <platform/lib/dai.h> -#include <sof/bit.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -struct dai; -struct sof_ipc_dai_config; -struct sof_ipc_stream_params; - -/** \addtogroup sof_dai_drivers DAI Drivers - * DAI Drivers API specification. - * @{ - */ - -#define DAI_CLOCK_IN 0 -#define DAI_CLOCK_OUT 1 - -#define DAI_DIR_PLAYBACK 0 -#define DAI_DIR_CAPTURE 1 - -#define DAI_NUM_SLOT_MAPS 8 - -#define DAI_INFO_TYPE 0 -#define DAI_INFO_DMA_CAPS 1 -#define DAI_INFO_DMA_DEV 2 - -/* DAI flags */ - -/** \brief IRQ used for copy() timer */ -#define DAI_FLAGS_IRQ_CB BIT(0) - -/* DAI get() flags */ - -/** \brief If the device does not exist it will be created */ -#define DAI_CREAT BIT(0) - -/** - * \brief DAI operations - all optional - */ -struct dai_ops { - int (*set_config)(struct dai *dai, struct sof_ipc_dai_config *config); - int (*trigger)(struct dai *dai, int cmd, int direction); - int (*pm_context_restore)(struct dai *dai); - int (*pm_context_store)(struct dai *dai); - int (*get_hw_params)(struct dai *dai, - struct sof_ipc_stream_params *params, int dir); - int (*get_handshake)(struct dai *dai, int direction, int stream_id); - int (*get_fifo)(struct dai *dai, int direction, int stream_id); - int (*probe)(struct dai *dai); - int (*remove)(struct dai *dai); -}; - -struct timestamp_cfg { - uint32_t walclk_rate; /* Rate in Hz, e.g. 19200000 */ - int type; /* SSP, DMIC, HDA, etc. */ - int direction; /* Playback, capture */ - int index; /* For SSPx to select correct timestamp register */ - int dma_id; /* GPDMA id*/ - int dma_chan_index; /* Used GPDMA channel */ - int dma_chan_count; /* Channels in single GPDMA */ -}; - -struct timestamp_data { - uint64_t walclk; /* Wall clock */ - uint64_t sample; /* Sample count */ - uint32_t walclk_rate; /* Rate in Hz, e.g. 19200000 */ -}; - -struct timestamp_ops { - int (*ts_config)(struct dai *dai, struct timestamp_cfg *cfg); - int (*ts_start)(struct dai *dai, struct timestamp_cfg *cfg); - int (*ts_stop)(struct dai *dai, struct timestamp_cfg *cfg); - int (*ts_get)(struct dai *dai, struct timestamp_cfg *cfg, - struct timestamp_data *tsd); -}; - -struct dai_driver { - uint32_t type; /**< type, one of SOF_DAI_... */ - uint32_t uid; - uint32_t dma_caps; - uint32_t dma_dev; - struct dai_ops ops; - struct timestamp_ops ts_ops; -}; - -/** - * \brief DAI slot map to audio channel - */ -struct dai_slot_map { - uint32_t channel; /**< channel ID - CHAN_ID_ */ - uint32_t slot; /**< physical slot index */ -}; - -struct dai_plat_fifo_data { - uint32_t offset; - uint32_t width; - uint32_t depth; - uint32_t watermark; - uint32_t handshake; -}; - -/** - * \brief DAI platform data - */ -struct dai_plat_data { - uint32_t base; - int irq; - const char *irq_name; - uint32_t flags; - struct dai_plat_fifo_data fifo[2]; -}; - -struct dai { - uint32_t index; /**< index */ - spinlock_t lock; /**< locking mechanism */ - int sref; /**< simple ref counter, guarded by lock */ - struct dai_plat_data plat_data; - const struct dai_driver *drv; - void *private; -}; - -/** - * \brief Array of DAIs grouped by type. - */ -struct dai_type_info { - uint32_t type; /**< Type */ - struct dai *dai_array; /**< Array of DAIs */ - size_t num_dais; /**< Number of elements in dai_array */ -}; - -/* dai tracing */ -#define trace_dai_drv_get_uid(drv_p) ((drv_p)->uid) -#define trace_dai_drv_get_id(drv_p) (-1) -#define trace_dai_drv_get_subid(drv_p) (-1) - -#define trace_dai_get_uid(dai_p) ((dai_p)->drv->uid) -#define trace_dai_get_id(dai_p) ((dai_p)->drv->type) -#define trace_dai_get_subid(dai_p) ((dai_p)->index) - -/* class (driver) level (no device object) tracing */ - -#define dai_cl_err(drv_p, __e, ...) \ - trace_dev_err(TRACE_CLASS_DAI, \ - trace_dai_drv_get_uid, \ - trace_dai_drv_get_id, \ - trace_dai_drv_get_subid, \ - drv_p, __e, ##__VA_ARGS__) - -#define dai_cl_warn(drv_p, __e, ...) \ - trace_dev_warn(TRACE_CLASS_DAI, \ - trace_dai_drv_get_uid, \ - trace_dai_drv_get_id, \ - trace_dai_drv_get_subid, \ - drv_p, __e, ##__VA_ARGS__) - -#define dai_cl_info(drv_p, __e, ...) \ - trace_dev_info(TRACE_CLASS_DAI, \ - trace_dai_drv_get_uid, \ - trace_dai_drv_get_id, \ - trace_dai_drv_get_subid, \ - drv_p, __e, ##__VA_ARGS__) - -#define dai_cl_dbg(drv_p, __e, ...) \ - trace_dev_dbg(TRACE_CLASS_DAI, \ - trace_dai_drv_get_uid, \ - trace_dai_drv_get_id, \ - trace_dai_drv_get_subid, \ - drv_p, __e, ##__VA_ARGS__) - -/* device tracing */ - -#define dai_err(dai_p, __e, ...) \ - trace_dev_err(TRACE_CLASS_DAI, trace_dai_get_uid, \ - trace_dai_get_id, \ - trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) - -#define dai_warn(dai_p, __e, ...) \ - trace_dev_warn(TRACE_CLASS_DAI, trace_dai_get_uid, \ - trace_dai_get_id, \ - trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) - -#define dai_info(dai_p, __e, ...) \ - trace_dev_info(TRACE_CLASS_DAI, trace_dai_get_uid, \ - trace_dai_get_id, \ - trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) - -#define dai_dbg(dai_p, __e, ...) \ - trace_dev_dbg(TRACE_CLASS_DAI, trace_dai_get_uid, \ - trace_dai_get_id, \ - trace_dai_get_subid, dai_p, __e, ##__VA_ARGS__) - -/** - * \brief Holds information about array of DAIs grouped by type. - */ -struct dai_info { - const struct dai_type_info *dai_type_array; - size_t num_dai_types; -}; - -/** - * \brief API to initialize a platform DAI. - * - * \param[in] sof Pointer to firmware main context. - */ -int dai_init(struct sof *sof); - -/** - * \brief API to request a platform DAI. - * - * \param[in] type Type of requested DAI. - * \param[in] index Index of requested DAI. - * \param[in] flags Flags (CREATE) - */ -struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags); - -/** - * \brief API to release a platform DAI. - * - * @param[in] dai DAI to relese. - */ -void dai_put(struct dai *dai); - -#define dai_set_drvdata(dai, data) \ - (dai->private = data) -#define dai_get_drvdata(dai) \ - dai->private -#define dai_base(dai) \ - dai->plat_data.base -#define dai_irq(dai) \ - dai->plat_data.irq -#define dai_fifo(dai, direction) \ - dai->plat_data.fifo[direction].offset - -/** - * \brief Digital Audio interface formatting - */ -static inline int dai_set_config(struct dai *dai, - struct sof_ipc_dai_config *config) -{ - int ret = dai->drv->ops.set_config(dai, config); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Digital Audio interface trigger - */ -static inline int dai_trigger(struct dai *dai, int cmd, int direction) -{ - int ret = dai->drv->ops.trigger(dai, cmd, direction); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Digital Audio interface PM context store - */ -static inline int dai_pm_context_store(struct dai *dai) -{ - int ret = dai->drv->ops.pm_context_store(dai); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Digital Audio interface PM context restore - */ -static inline int dai_pm_context_restore(struct dai *dai) -{ - int ret = dai->drv->ops.pm_context_restore(dai); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Get Digital Audio interface stream parameters - */ -static inline int dai_get_hw_params(struct dai *dai, - struct sof_ipc_stream_params *params, - int dir) -{ - int ret = dai->drv->ops.get_hw_params(dai, params, dir); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Get Digital Audio interface DMA Handshake - */ -static inline int dai_get_handshake(struct dai *dai, int direction, - int stream_id) -{ - int ret = dai->drv->ops.get_handshake(dai, direction, stream_id); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Get Digital Audio interface FIFO address - */ -static inline int dai_get_fifo(struct dai *dai, int direction, - int stream_id) -{ - int ret = dai->drv->ops.get_fifo(dai, direction, stream_id); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Digital Audio interface Probe - */ -static inline int dai_probe(struct dai *dai) -{ - int ret = dai->drv->ops.probe(dai); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Digital Audio interface Remove - */ -static inline int dai_remove(struct dai *dai) -{ - int ret = dai->drv->ops.remove(dai); - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -/** - * \brief Get driver specific DAI information - */ -static inline int dai_get_info(struct dai *dai, int info) -{ - int ret; - - switch (info) { - case DAI_INFO_TYPE: - ret = dai->drv->type; - break; - case DAI_INFO_DMA_CAPS: - ret = dai->drv->dma_caps; - break; - case DAI_INFO_DMA_DEV: - ret = dai->drv->dma_dev; - break; - default: - ret = -EINVAL; - break; - } - - platform_shared_commit(dai, sizeof(*dai)); - - return ret; -} - -static inline void dai_write(struct dai *dai, uint32_t reg, uint32_t value) -{ - io_reg_write(dai_base(dai) + reg, value); - - platform_shared_commit(dai, sizeof(*dai)); -} - -static inline uint32_t dai_read(struct dai *dai, uint32_t reg) -{ - uint32_t val = io_reg_read(dai_base(dai) + reg); - - platform_shared_commit(dai, sizeof(*dai)); - - return val; -} - -static inline void dai_update_bits(struct dai *dai, uint32_t reg, - uint32_t mask, uint32_t value) -{ - io_reg_update_bits(dai_base(dai) + reg, mask, value); - - platform_shared_commit(dai, sizeof(*dai)); -} - -static inline const struct dai_info *dai_info_get(void) -{ - return sof_get()->dai_info; -} - -/** @}*/ - -#endif /* __SOF_LIB_DAI_H__ */ diff --git a/src/include/sof/lib/dma.h b/src/include/sof/lib/dma.h deleted file mode 100644 index 95fe9d4ad574..000000000000 --- a/src/include/sof/lib/dma.h +++ /dev/null @@ -1,649 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -/** - * \file include/sof/lib/dma.h - * \brief DMA Drivers definition - * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> - * \author Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifndef __SOF_LIB_DMA_H__ -#define __SOF_LIB_DMA_H__ - -#include <platform/lib/dma.h> -#include <sof/atomic.h> -#include <sof/bit.h> -#include <sof/lib/alloc.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -struct comp_buffer; - -/** \addtogroup sof_dma_drivers DMA Drivers - * DMA Drivers API specification. - * @{ - */ - -/* DMA direction bitmasks used to define DMA copy direction */ -#define DMA_DIR_MEM_TO_MEM BIT(0) /**< local memory copy */ -#define DMA_DIR_HMEM_TO_LMEM BIT(1) /**< host memory to local mem copy */ -#define DMA_DIR_LMEM_TO_HMEM BIT(2) /**< local mem to host mem copy */ -#define DMA_DIR_MEM_TO_DEV BIT(3) /**< local mem to dev copy */ -#define DMA_DIR_DEV_TO_MEM BIT(4) /**< dev to local mem copy */ -#define DMA_DIR_DEV_TO_DEV BIT(5) /**< dev to dev copy */ - -/* DMA capabilities bitmasks used to define the type of DMA */ -#define DMA_CAP_HDA BIT(0) /**< HDA DMA */ -#define DMA_CAP_GP_LP BIT(1) /**< GP LP DMA */ -#define DMA_CAP_GP_HP BIT(2) /**< GP HP DMA */ - -/* DMA dev type bitmasks used to define the type of DMA */ - -#define DMA_DEV_HOST BIT(0) /**< connectable to host */ -#define DMA_DEV_HDA BIT(1) /**< connectable to HD/A link */ -#define DMA_DEV_SSP BIT(2) /**< connectable to SSP fifo */ -#define DMA_DEV_DMIC BIT(3) /**< connectable to DMIC fifo */ -#define DMA_DEV_SSI BIT(4) /**< connectable to SSI / SPI fifo */ -#define DMA_DEV_ALH BIT(5) /**< connectable to ALH link */ -#define DMA_DEV_SAI BIT(6) /**< connectable to SAI fifo */ -#define DMA_DEV_ESAI BIT(7) /**< connectable to ESAI fifo */ - -/* DMA access privilege flag */ -#define DMA_ACCESS_EXCLUSIVE 1 -#define DMA_ACCESS_SHARED 0 - -/* DMA copy flags */ -#define DMA_COPY_BLOCKING BIT(0) -#define DMA_COPY_ONE_SHOT BIT(1) - -/* We will use this enum in cb handler to inform dma what - * action we need to perform. - */ -enum dma_cb_status { - DMA_CB_STATUS_RELOAD = 0, - DMA_CB_STATUS_END, -}; - -/* DMA interrupt commands */ -enum dma_irq_cmd { - DMA_IRQ_STATUS_GET = 0, - DMA_IRQ_CLEAR, - DMA_IRQ_MASK, - DMA_IRQ_UNMASK -}; - -#define DMA_CHAN_INVALID 0xFFFFFFFF -#define DMA_CORE_INVALID 0xFFFFFFFF - -/* DMA attributes */ -#define DMA_ATTR_BUFFER_ALIGNMENT 0 -#define DMA_ATTR_COPY_ALIGNMENT 1 -#define DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT 2 -#define DMA_ATTR_BUFFER_PERIOD_COUNT 3 - -struct dma; - -/** - * \brief Element of SG list (as array item). - */ -struct dma_sg_elem { - uint32_t src; /**< source address */ - uint32_t dest; /**< destination address */ - uint32_t size; /**< size (in bytes) */ -}; - -/** - * \brief Data used in DMA callbacks. - */ -struct dma_cb_data { - struct dma_chan_data *channel; - struct dma_sg_elem elem; - enum dma_cb_status status; -}; - -/** - * \brief SG elem array. - */ -struct dma_sg_elem_array { - uint32_t count; /**< number of elements in elems */ - struct dma_sg_elem *elems; /**< elements */ -}; - -/* DMA physical SG params */ -struct dma_sg_config { - uint32_t src_width; /* in bytes */ - uint32_t dest_width; /* in bytes */ - uint32_t burst_elems; - uint32_t direction; - uint32_t src_dev; - uint32_t dest_dev; - uint32_t cyclic; /* circular buffer */ - uint64_t period; - struct dma_sg_elem_array elem_array; /* array of dma_sg elems */ - bool scatter; - bool irq_disabled; - /* true if configured DMA channel is the scheduling source */ - bool is_scheduling_source; -}; - -struct dma_chan_status { - uint32_t state; - uint32_t flags; - uint32_t w_pos; - uint32_t r_pos; - uint32_t timestamp; -}; - -/* DMA operations */ -struct dma_ops { - - struct dma_chan_data *(*channel_get)(struct dma *dma, - unsigned int req_channel); - void (*channel_put)(struct dma_chan_data *channel); - - int (*start)(struct dma_chan_data *channel); - int (*stop)(struct dma_chan_data *channel); - int (*copy)(struct dma_chan_data *channel, int bytes, uint32_t flags); - int (*pause)(struct dma_chan_data *channel); - int (*release)(struct dma_chan_data *channel); - int (*status)(struct dma_chan_data *channel, - struct dma_chan_status *status, uint8_t direction); - - int (*set_config)(struct dma_chan_data *channel, - struct dma_sg_config *config); - - int (*pm_context_restore)(struct dma *dma); - int (*pm_context_store)(struct dma *dma); - - int (*probe)(struct dma *dma); - int (*remove)(struct dma *dma); - - int (*get_data_size)(struct dma_chan_data *channel, uint32_t *avail, - uint32_t *free); - - int (*get_attribute)(struct dma *dma, uint32_t type, uint32_t *value); - - int (*interrupt)(struct dma_chan_data *channel, enum dma_irq_cmd cmd); -}; - -/* DMA platform data */ -struct dma_plat_data { - uint32_t id; - uint32_t dir; /* bitmask of supported copy directions */ - uint32_t caps; /* bitmask of supported capabilities */ - uint32_t devs; /* bitmask of supported devs */ - uint32_t base; - uint32_t channels; - int irq; - const char *irq_name; - uint32_t chan_size; - const void *drv_plat_data; -}; - -struct dma { - struct dma_plat_data plat_data; - spinlock_t lock; /**< locking mechanism */ - int sref; /**< simple ref counter, guarded by lock */ - const struct dma_ops *ops; - atomic_t num_channels_busy; /* number of busy channels */ - struct dma_chan_data *chan; /* channels array */ - void *private; -}; - -struct dma_chan_data { - struct dma *dma; - - uint32_t status; - uint32_t direction; - uint32_t desc_count; - uint32_t index; - uint32_t core; - uint64_t period; /* DMA channel's transfer period in us */ - /* true if this DMA channel is the scheduling source */ - bool is_scheduling_source; - - void *private; -}; - -struct dma_info { - struct dma *dma_array; - size_t num_dmas; -}; - -struct audio_stream; -typedef void (*dma_process_func)(const struct audio_stream *source, - uint32_t ioffset, struct audio_stream *sink, - uint32_t ooffset, uint32_t frames); - -/** - * \brief API to initialize a platform DMA controllers. - * - * \param[in] sof Pointer to firmware main context. - */ -int dmac_init(struct sof *sof); - -/** - * \brief API to request a platform DMAC. - * - * Users can request DMAC based on dev type, copy direction, capabilities - * and access privilege. - * For exclusive access, ret DMAC with no channels draining. - * For shared access, ret DMAC with the least number of channels draining. - */ -struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags); - -/** - * \brief API to release a platform DMAC. - * - * @param[in] dma DMAC to relese. - */ -void dma_put(struct dma *dma); - -#define dma_set_drvdata(dma, data) \ - (dma->private = data) -#define dma_get_drvdata(dma) \ - dma->private -#define dma_base(dma) \ - dma->plat_data.base -#define dma_irq(dma) \ - dma->plat_data.irq -#define dma_irq_name(dma) \ - dma->plat_data.irq_name -#define dma_chan_size(dma) \ - dma->plat_data.chan_size -#define dma_chan_base(dma, chan) \ - (dma->plat_data.base + chan * dma->plat_data.chan_size) -#define dma_chan_get_data(chan) \ - ((chan)->private) -#define dma_chan_set_data(chan, data) \ - ((chan)->private = data) - -/* DMA API - * Programming flow is :- - * - * 1) dma_channel_get() - * 2) notifier_register() - * 3) dma_set_config() - * 4) dma_start() - * ... DMA now running ... - * 5) dma_stop() - * 6) dma_channel_put() - */ - -static inline struct dma_chan_data *dma_channel_get(struct dma *dma, - int req_channel) -{ - struct dma_chan_data *chan = dma->ops->channel_get(dma, req_channel); - - platform_shared_commit(dma, sizeof(*dma)); - - return chan; -} - -static inline void dma_channel_put(struct dma_chan_data *channel) -{ - channel->dma->ops->channel_put(channel); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); -} - -static inline int dma_start(struct dma_chan_data *channel) -{ - int ret = channel->dma->ops->start(channel); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_stop(struct dma_chan_data *channel) -{ - int ret = channel->dma->ops->stop(channel); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_copy(struct dma_chan_data *channel, int bytes, - uint32_t flags) -{ - int ret = channel->dma->ops->copy(channel, bytes, flags); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_pause(struct dma_chan_data *channel) -{ - int ret = channel->dma->ops->pause(channel); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_release(struct dma_chan_data *channel) -{ - int ret = channel->dma->ops->release(channel); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_status(struct dma_chan_data *channel, - struct dma_chan_status *status, uint8_t direction) -{ - int ret = channel->dma->ops->status(channel, status, direction); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_set_config(struct dma_chan_data *channel, - struct dma_sg_config *config) -{ - int ret = channel->dma->ops->set_config(channel, config); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_pm_context_restore(struct dma *dma) -{ - int ret = dma->ops->pm_context_restore(dma); - - platform_shared_commit(dma, sizeof(*dma)); - - return ret; -} - -static inline int dma_pm_context_store(struct dma *dma) -{ - int ret = dma->ops->pm_context_store(dma); - - platform_shared_commit(dma, sizeof(*dma)); - - return ret; -} - -static inline int dma_probe(struct dma *dma) -{ - int ret = dma->ops->probe(dma); - - platform_shared_commit(dma->chan, sizeof(*dma->chan) * - dma->plat_data.channels); - platform_shared_commit(dma, sizeof(*dma)); - - return ret; -} - -static inline int dma_remove(struct dma *dma) -{ - int ret = dma->ops->remove(dma); - - platform_shared_commit(dma, sizeof(*dma)); - - return ret; -} - -static inline int dma_get_data_size(struct dma_chan_data *channel, - uint32_t *avail, uint32_t *free) -{ - int ret = channel->dma->ops->get_data_size(channel, avail, free); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline int dma_get_attribute(struct dma *dma, uint32_t type, - uint32_t *value) -{ - int ret = dma->ops->get_attribute(dma, type, value); - - platform_shared_commit(dma, sizeof(*dma)); - - return ret; -} - -static inline int dma_interrupt(struct dma_chan_data *channel, - enum dma_irq_cmd cmd) -{ - int ret = channel->dma->ops->interrupt(channel, cmd); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -/* DMA hardware register operations */ -static inline uint32_t dma_reg_read(struct dma *dma, uint32_t reg) -{ - uint32_t val; - - val = io_reg_read(dma_base(dma) + reg); - - platform_shared_commit(dma, sizeof(*dma)); - - return val; -} - -static inline uint16_t dma_reg_read16(struct dma *dma, uint32_t reg) -{ - uint16_t val; - - val = io_reg_read16(dma_base(dma) + reg); - - platform_shared_commit(dma, sizeof(*dma)); - - return val; -} - -static inline void dma_reg_write(struct dma *dma, uint32_t reg, uint32_t value) -{ - io_reg_write(dma_base(dma) + reg, value); - - platform_shared_commit(dma, sizeof(*dma)); -} - -static inline void dma_reg_write16(struct dma *dma, uint32_t reg, - uint16_t value) -{ - io_reg_write16(dma_base(dma) + reg, value); - - platform_shared_commit(dma, sizeof(*dma)); -} - -static inline void dma_reg_update_bits(struct dma *dma, uint32_t reg, - uint32_t mask, uint32_t value) -{ - io_reg_update_bits(dma_base(dma) + reg, mask, value); - - platform_shared_commit(dma, sizeof(*dma)); -} - -static inline uint32_t dma_chan_reg_read(struct dma_chan_data *channel, - uint32_t reg) -{ - uint32_t val; - - val = io_reg_read(dma_chan_base(channel->dma, channel->index) + reg); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return val; -} - -static inline uint16_t dma_chan_reg_read16(struct dma_chan_data *channel, - uint32_t reg) -{ - uint16_t val; - - val = io_reg_read16(dma_chan_base(channel->dma, channel->index) + reg); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); - - return val; -} - -static inline void dma_chan_reg_write(struct dma_chan_data *channel, - uint32_t reg, uint32_t value) -{ - io_reg_write(dma_chan_base(channel->dma, channel->index) + reg, value); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); -} - -static inline void dma_chan_reg_write16(struct dma_chan_data *channel, - uint32_t reg, uint16_t value) -{ - io_reg_write16(dma_chan_base(channel->dma, channel->index) + reg, - value); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); -} - -static inline void dma_chan_reg_update_bits(struct dma_chan_data *channel, - uint32_t reg, uint32_t mask, - uint32_t value) -{ - io_reg_update_bits(dma_chan_base(channel->dma, channel->index) + reg, - mask, value); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); -} - -static inline void dma_chan_reg_update_bits16(struct dma_chan_data *channel, - uint32_t reg, uint16_t mask, - uint16_t value) -{ - io_reg_update_bits16(dma_chan_base(channel->dma, channel->index) + reg, - mask, value); - - platform_shared_commit(channel->dma, sizeof(*channel->dma)); - platform_shared_commit(channel, sizeof(*channel)); -} - -static inline bool dma_is_scheduling_source(struct dma_chan_data *channel) -{ - bool ret = channel->is_scheduling_source; - - platform_shared_commit(channel, sizeof(*channel)); - - return ret; -} - -static inline void dma_sg_init(struct dma_sg_elem_array *ea) -{ - ea->count = 0; - ea->elems = NULL; -} - -int dma_sg_alloc(struct dma_sg_elem_array *ea, - enum mem_zone zone, - uint32_t direction, - uint32_t buffer_count, uint32_t buffer_bytes, - uintptr_t dma_buffer_addr, uintptr_t external_addr); - -void dma_sg_free(struct dma_sg_elem_array *ea); - -/** - * \brief Get the total size of SG buffer - * - * \param ea Array of SG elements. - * \return Size of the buffer. - */ -static inline uint32_t dma_sg_get_size(struct dma_sg_elem_array *ea) -{ - int i; - uint32_t size = 0; - - for (i = 0 ; i < ea->count; i++) - size += ea->elems[i].size; - - return size; -} - -struct audio_stream; -typedef void (*dma_process)(const struct audio_stream *, - struct audio_stream *, uint32_t); - -/* copies data from DMA buffer using provided processing function */ -void dma_buffer_copy_from(struct comp_buffer *source, uint32_t source_bytes, - struct comp_buffer *sink, uint32_t sink_bytes, - dma_process_func process, uint32_t samples); - -/* copies data to DMA buffer using provided processing function */ -void dma_buffer_copy_to(struct comp_buffer *source, uint32_t source_bytes, - struct comp_buffer *sink, uint32_t sink_bytes, - dma_process_func process, uint32_t samples); - -/* generic DMA DSP <-> Host copier */ - -struct dma_copy { - struct dma_chan_data *chan; - struct dma *dmac; -}; - -/* init dma copy context */ -int dma_copy_new(struct dma_copy *dc); - -/* free dma copy context resources */ -static inline void dma_copy_free(struct dma_copy *dc) -{ - dma_channel_put(dc->chan); -} - -/* DMA copy data from host to DSP */ -int dma_copy_from_host(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size); -int dma_copy_from_host_nowait(struct dma_copy *dc, - struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, - int32_t size); - -/* DMA copy data from DSP to host */ -int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size); - -int dma_copy_set_stream_tag(struct dma_copy *dc, uint32_t stream_tag); - -static inline const struct dma_info *dma_info_get(void) -{ - return sof_get()->dma_info; -} - -/** @}*/ - -#endif /* __SOF_LIB_DMA_H__ */ diff --git a/src/include/sof/lib/fast-get.h b/src/include/sof/lib/fast-get.h new file mode 100644 index 000000000000..05f098a752cc --- /dev/null +++ b/src/include/sof/lib/fast-get.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Jyri Sarha <jyri.sarha@linux.intel.com> + */ + +#ifndef __SOF_LIB_FAST_GET_H__ +#define __SOF_LIB_FAST_GET_H__ + +#include <stddef.h> + +struct k_mem_domain; +struct mod_alloc_ctx; + +/* + * When built for SOF, fast_get() and fast_put() are only needed when DRAM + * storage and execution is enabled (CONFIG_COLD_STORE_EXECUTE_DRAM=y), but not + * when building LLEXT extensions (!defined(LL_EXTENSION_BUILD)), using Zephyr + * SDK (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=n while + * CONFIG_LLEXT_TYPE_ELF_SHAREDLIB=y). + * For unit-testing full versions of fast_get() and fast_put() are checked by + * test/ztest/unit/fast-get/ and test/cmocka/src/lib/fast-get/ + */ +#if (CONFIG_COLD_STORE_EXECUTE_DRAM && \ + (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD))) || \ + !CONFIG_SOF_FULL_ZEPHYR_APPLICATION +const void *fast_get(struct mod_alloc_ctx *alloc, const void * const dram_ptr, size_t size); +void fast_put(struct mod_alloc_ctx *alloc, struct k_mem_domain *mdom, const void *sram_ptr); +#else +static inline const void *fast_get(struct mod_alloc_ctx *alloc, const void * const dram_ptr, + size_t size) +{ + return dram_ptr; +} +static inline void fast_put(struct mod_alloc_ctx *alloc, struct k_mem_domain *mdom, + const void *sram_ptr) {} +#endif + +#endif /* __SOF_LIB_FAST_GET_H__ */ diff --git a/src/include/sof/lib/io.h b/src/include/sof/lib/io.h deleted file mode 100644 index 8b9b995ecd87..000000000000 --- a/src/include/sof/lib/io.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_LIB_IO_H__ -#define __SOF_LIB_IO_H__ - -#include <config.h> -#include <stdint.h> - -#if CONFIG_LIBRARY - -static inline uint32_t io_reg_read(uint32_t reg) { return 0; } -static inline void io_reg_write(uint32_t reg, uint32_t val) {} -static inline void io_reg_update_bits(uint32_t reg, uint32_t mask, - uint32_t value) {} -static inline uint16_t io_reg_read16(uint32_t reg) { return 0; } -static inline void io_reg_write16(uint32_t reg, uint16_t val) {} -static inline void io_reg_update_bits16(uint32_t reg, uint16_t mask, - uint16_t value) {} - -#else - -static inline uint32_t io_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)reg); -} - -static inline void io_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)reg) = val; -} - -static inline void io_reg_update_bits(uint32_t reg, uint32_t mask, - uint32_t value) -{ - io_reg_write(reg, (io_reg_read(reg) & (~mask)) | (value & mask)); -} - -static inline uint16_t io_reg_read16(uint32_t reg) -{ - return *((volatile uint16_t*)reg); -} - -static inline void io_reg_write16(uint32_t reg, uint16_t val) -{ - *((volatile uint16_t*)reg) = val; -} - -static inline uint64_t io_reg_read_64(uint32_t reg) -{ - return (uint64_t)io_reg_read(reg) + - (((uint64_t)io_reg_read(reg + 4)) << 32); -} - -static inline void io_reg_update_bits16(uint32_t reg, uint16_t mask, - uint16_t value) -{ - io_reg_write16(reg, (io_reg_read16(reg) & (~mask)) | (value & mask)); -} - -#endif - -#endif /* __SOF_LIB_IO_H__ */ diff --git a/src/include/sof/lib/mailbox.h b/src/include/sof/lib/mailbox.h index cc668d5159cf..ae667f0d0c4c 100644 --- a/src/include/sof/lib/mailbox.h +++ b/src/include/sof/lib/mailbox.h @@ -9,10 +9,13 @@ #ifndef __SOF_LIB_MAILBOX_H__ #define __SOF_LIB_MAILBOX_H__ +#include <sof/common.h> +#include <kernel/mailbox.h> #include <platform/lib/mailbox.h> -#include <sof/debug/panic.h> -#include <sof/lib/cache.h> -#include <sof/string.h> +#include <rtos/panic.h> +#include <rtos/cache.h> +#include <sof/lib/memory.h> +#include <rtos/string.h> #include <stddef.h> #include <stdint.h> @@ -43,58 +46,78 @@ static inline void mailbox_dspbox_write(size_t offset, const void *src, size_t bytes) { - int ret = memcpy_s((void *)(MAILBOX_DSPBOX_BASE + offset), - MAILBOX_DSPBOX_SIZE - offset, src, bytes); + int dsp_write_err __unused = memcpy_s((void *)(MAILBOX_DSPBOX_BASE + offset), + MAILBOX_DSPBOX_SIZE - offset, src, bytes); - assert(!ret); - dcache_writeback_region((void *)(MAILBOX_DSPBOX_BASE + offset), bytes); + assert(!dsp_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_DSPBOX_BASE + + offset), bytes); } static inline void mailbox_dspbox_read(void *dest, size_t dest_size, size_t offset, size_t bytes) { - int ret; + int dsp_read_err __unused; - dcache_invalidate_region((void *)(MAILBOX_DSPBOX_BASE + offset), - bytes); - ret = memcpy_s(dest, dest_size, - (void *)(MAILBOX_DSPBOX_BASE + offset), bytes); - assert(!ret); + dcache_invalidate_region((__sparse_force void __sparse_cache *)(MAILBOX_DSPBOX_BASE + + offset), bytes); + dsp_read_err = memcpy_s(dest, dest_size, + (void *)(MAILBOX_DSPBOX_BASE + offset), bytes); + assert(!dsp_read_err); } +#if CONFIG_LIBRARY + +#define mailbox_hostbox_write(_offset, _src, _bytes) \ + memcpy((char *)ipc->comp_data + _offset, _src, _bytes) + +#else + static inline void mailbox_hostbox_write(size_t offset, const void *src, size_t bytes) { - int ret = memcpy_s((void *)(MAILBOX_HOSTBOX_BASE + offset), - MAILBOX_HOSTBOX_SIZE - offset, src, bytes); + int host_write_err __unused = memcpy_s((void *)(MAILBOX_HOSTBOX_BASE + offset), + MAILBOX_HOSTBOX_SIZE - offset, src, bytes); - assert(!ret); - dcache_writeback_region((void *)(MAILBOX_HOSTBOX_BASE + offset), bytes); + assert(!host_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_HOSTBOX_BASE + + offset), bytes); } +#endif + static inline void mailbox_hostbox_read(void *dest, size_t dest_size, size_t offset, size_t bytes) { - int ret; + int host_read_err __unused; - dcache_invalidate_region((void *)(MAILBOX_HOSTBOX_BASE + offset), - bytes); - ret = memcpy_s(dest, dest_size, - (void *)(MAILBOX_HOSTBOX_BASE + offset), bytes); - assert(!ret); + dcache_invalidate_region((__sparse_force void __sparse_cache *)(MAILBOX_HOSTBOX_BASE + + offset), bytes); + host_read_err = memcpy_s(dest, dest_size, + (void *)(MAILBOX_HOSTBOX_BASE + offset), bytes); + assert(!host_read_err); } +#if CONFIG_IPC_MAJOR_4 +static inline +void mailbox_stream_write(size_t offset, const void *src, size_t bytes) +{ + /* in IPC4, the stream mailbox must not be used */ + assert(false); +} +#else static inline void mailbox_stream_write(size_t offset, const void *src, size_t bytes) { - int ret = memcpy_s((void *)(MAILBOX_STREAM_BASE + offset), - MAILBOX_STREAM_SIZE - offset, src, bytes); + int stream_write_err __unused = memcpy_s((void *)(MAILBOX_STREAM_BASE + offset), + MAILBOX_STREAM_SIZE - offset, src, bytes); - assert(!ret); - dcache_writeback_region((void *)(MAILBOX_STREAM_BASE + offset), - bytes); + assert(!stream_write_err); + dcache_writeback_region((__sparse_force void __sparse_cache *)(MAILBOX_STREAM_BASE + + offset), bytes); } +#endif #endif /* __SOF_LIB_MAILBOX_H__ */ diff --git a/src/include/sof/lib/memory.h b/src/include/sof/lib/memory.h deleted file mode 100644 index 8fcbc1f9adbe..000000000000 --- a/src/include/sof/lib/memory.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __SOF_LIB_MEMORY_H__ -#define __SOF_LIB_MEMORY_H__ - -#include <platform/lib/memory.h> - -#endif /* __SOF_LIB_MEMORY_H__ */ diff --git a/src/include/sof/lib/notifier.h b/src/include/sof/lib/notifier.h index 1fe44802ee76..87ca2cd40265 100644 --- a/src/include/sof/lib/notifier.h +++ b/src/include/sof/lib/notifier.h @@ -8,8 +8,10 @@ #ifndef __SOF_LIB_NOTIFIER_H__ #define __SOF_LIB_NOTIFIER_H__ +#include <rtos/bit.h> #include <sof/list.h> -#include <sof/sof.h> +#include <rtos/spinlock.h> +#include <rtos/sof.h> #include <stdint.h> /* notifier target core masks */ @@ -17,21 +19,25 @@ #define NOTIFIER_TARGET_CORE_LOCAL NOTIFIER_TARGET_CORE_MASK(cpu_get_id()) #define NOTIFIER_TARGET_CORE_ALL_MASK 0xFFFFFFFF +/** \brief Notifier flags. */ +#define NOTIFIER_FLAG_AGGREGATE BIT(0) + enum notify_id { NOTIFIER_ID_CPU_FREQ = 0, /* struct clock_notify_data * */ NOTIFIER_ID_SSP_FREQ, /* struct clock_notify_data * */ NOTIFIER_ID_KPB_CLIENT_EVT, /* struct kpb_event_data * */ NOTIFIER_ID_DMA_DOMAIN_CHANGE, /* struct dma_chan_data * */ - NOTIFIER_ID_BUFFER_PRODUCE, /* struct buffer_cb_transact* */ - NOTIFIER_ID_BUFFER_CONSUME, /* struct buffer_cb_transact* */ - NOTIFIER_ID_BUFFER_FREE, /* struct buffer_cb_free* */ NOTIFIER_ID_DMA_COPY, /* struct dma_cb_data* */ + NOTIFIER_ID_LL_POST_RUN, /* NULL */ NOTIFIER_ID_DMA_IRQ, /* struct dma_chan_data * */ + NOTIFIER_ID_DAI_TRIGGER, /* struct dai_group * */ + NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, /* struct mic_privacy_settings * */ NOTIFIER_ID_COUNT }; struct notify { struct list_item list[NOTIFIER_ID_COUNT]; /* list of callback handles */ + struct k_spinlock lock; /* list lock */ }; struct notify_data { @@ -50,14 +56,44 @@ struct notify_data { struct notify **arch_notify_get(void); -int notifier_register(void *receiver, void *caller, enum notify_id type, - void (*cb)(void *arg, enum notify_id type, void *data)); -void notifier_unregister(void *receiver, void *caller, enum notify_id type); -void notifier_unregister_all(void *receiver, void *caller); +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, + * caller_id_filter, event_type), the callback argument is not part of + * it. + * + * caller_data argument from notifier_event() + * + * @param receiver_data private data passed to the callback. + * @param caller_id_filter optional, can be used to be notified only by + * some specific notifier_event() calls when not NULL. + * @param event_type list of callbacks to be added to + * @param callback callback function + * @param flags see NOTIFIER_FLAG_* above + */ +int notifier_register(void *receiver_data, void *caller_id_filter, enum notify_id event_type, + notifier_callback_t callback, uint32_t flags); + +/** Unregister all callbacks matching that arguments tuple. NULL acts + * as a wildcard. + */ +void notifier_unregister(void *receiver_data_filter, void *caller_id_filter, enum notify_id type); + +/** Unregister callbacks matching the arguments for every notify_id. + * A NULL parameter acts as a wildcard. + */ +void notifier_unregister_all(void *receiver_data_filter, void *caller_id_filter); void notifier_notify_remote(void); -void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask, - void *data, uint32_t data_size); + +/* data_size is required to manage cache coherency for notifications + * across cores. + */ +void notifier_event(const void *caller_id, enum notify_id event_type, uint32_t core_mask, + void *caller_data, uint32_t data_size); void init_system_notify(struct sof *sof); diff --git a/src/include/sof/lib/perf_cnt.h b/src/include/sof/lib/perf_cnt.h index 70c358644f04..bcb2a0769630 100644 --- a/src/include/sof/lib/perf_cnt.h +++ b/src/include/sof/lib/perf_cnt.h @@ -14,56 +14,183 @@ #ifndef __SOF_LIB_PERF_CNT_H__ #define __SOF_LIB_PERF_CNT_H__ -#include <sof/drivers/timer.h> +#include <rtos/timer.h> struct perf_cnt_data { - uint64_t plat_ts; - uint64_t cpu_ts; - uint64_t plat_delta_last; - uint64_t plat_delta_peak; - uint64_t cpu_delta_last; - uint64_t cpu_delta_peak; + /* current platform clock */ + uint32_t plat_ts; + /* current cpu clock */ + uint32_t cpu_ts; + /* one period module cycles */ + uint32_t plat_delta_last; + /* period module peak cycles within period_cnt */ + uint32_t plat_delta_peak; + /* one period module cycles from cpu clock */ + uint32_t cpu_delta_last; + /* period module peak cycles within period_cnt from cpu clock */ + uint32_t cpu_delta_peak; + /* total cycles within period_cnt */ + uint32_t cpu_delta_sum; + /* accumulate period passed and calculate avg cycles */ + uint32_t period_cnt; + /* indicate which period have peak mcps in current module */ + uint32_t peak_mcps_period_cnt; }; #if CONFIG_PERFORMANCE_COUNTERS -#define perf_cnt_trace(tclass, pcd) \ - trace_event(tclass, "perf plat last %lu peak %lu cpu last %lu, peak %lu", \ - (pcd)->plat_delta_last, \ - (pcd)->plat_delta_peak, \ - (pcd)->cpu_delta_last, \ - (pcd)->cpu_delta_peak) +#define perf_cnt_trace(ctx, pcd) \ + tr_info(ctx, "perf plat last %u peak %u cpu last %u, peak %u", \ + (uint32_t)((pcd)->plat_delta_last), \ + (uint32_t)((pcd)->plat_delta_peak), \ + (uint32_t)((pcd)->cpu_delta_last), \ + (uint32_t)((pcd)->cpu_delta_peak)) +/** \brief Clears performance counters data. */ #define perf_cnt_clear(pcd) memset((pcd), 0, sizeof(struct perf_cnt_data)) +/* NOTE: Zephyr's arch_timing_counter_get() might not be implemented + * for a particular platform. In this case let's fallback to use + * Zephyr's k_cycle_get_64(). This will result in both "platform" and + * "cpu" timestamps to be equal. + */ +#ifdef __ZEPHYR__ + #include <zephyr/timing/timing.h> + #ifdef CONFIG_TIMING_FUNCTIONS + #define perf_cnt_get_cpu_ts timing_counter_get + #else + #define perf_cnt_get_cpu_ts sof_cycle_get_64 + #endif /* CONFIG_TIMING_FUNCTIONS */ +#else + #define perf_cnt_get_cpu_ts() timer_get_system(cpu_timer_get()) +#endif /* __ZEPHYR__ */ + +/** \brief Initializes timestamps with current timer values. */ #define perf_cnt_init(pcd) do { \ - (pcd)->plat_ts = platform_timer_get(timer_get()); \ - (pcd)->cpu_ts = arch_timer_get_system(cpu_timer_get()); \ + (pcd)->plat_ts = sof_cycle_get_64(); \ + (pcd)->cpu_ts = perf_cnt_get_cpu_ts(); \ + } while (0) + +/* Trace macros that can be used as trace_m argument of the perf_cnt_stamp() + * to trace PCD values if the last arch timer reading exceeds the previous + * peak value. + * + * arg passed to perf_cnt_stamp() is forwarded to the trace_m() macro + * as the second argument. + */ + +/** \brief No trace when detecting peak value. */ +#define perf_trace_null(pcd, arg) + +/** \brief Simple trace, all values are printed, arg should be a tr_ctx address. + */ +#define perf_trace_simple(pcd, arg) perf_cnt_trace(arg, pcd) + +/* perf measurement windows size 2^x */ +#define PERF_CNT_CHECK_WINDOW_SIZE 10 +#define task_perf_avg_info(pcd, task_p, class) \ + tr_info(task_p, "perf_cycle task %p, %pU cpu avg %u peak %u",\ + class, (class)->uid, \ + (uint32_t)((pcd)->cpu_delta_sum), \ + (uint32_t)((pcd)->cpu_delta_peak)) +#define task_perf_cnt_avg(pcd, trace_m, arg, class) do { \ + (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \ + if (!(++(pcd)->period_cnt & MASK(PERF_CNT_CHECK_WINDOW_SIZE - 1, 0))) { \ + (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \ + if ((pcd)->period_cnt & BIT(PERF_CNT_CHECK_WINDOW_SIZE)) \ + trace_m(pcd, arg, class); \ + (pcd)->cpu_delta_sum = 0; \ + (pcd)->plat_delta_peak = 0; \ + (pcd)->cpu_delta_peak = 0; \ + } \ + } while (0) + +/** \brief Accumulates cpu timer delta samples calculated by perf_cnt_stamp(). + * + * If current sample count reaches the window size, compute the average and run trace_m. + * \param pcd Performance counters data. + * \param trace_m Trace function trace_m(pcd, arg) or trace macro if a + * more precise line number is desired in the logs. + * \param arg Argument passed to trace_m as arg. + */ +#define perf_cnt_average(pcd, trace_m, arg) do { \ + (pcd)->cpu_delta_sum += (pcd)->cpu_delta_last; \ + if (!(++(pcd)->period_cnt & MASK(PERF_CNT_CHECK_WINDOW_SIZE - 1, 0))) { \ + (pcd)->cpu_delta_sum >>= PERF_CNT_CHECK_WINDOW_SIZE; \ + (pcd)->peak_mcps_period_cnt &= MASK(PERF_CNT_CHECK_WINDOW_SIZE - 1, 0); \ + if ((pcd)->period_cnt & BIT(PERF_CNT_CHECK_WINDOW_SIZE)) { \ + trace_m(pcd, arg); \ + } \ + (pcd)->cpu_delta_sum = 0; \ + (pcd)->plat_delta_peak = 0; \ + (pcd)->cpu_delta_peak = 0; \ + (pcd)->peak_mcps_period_cnt = 0; \ + } \ } while (0) -#define perf_cnt_stamp(tclass, pcd, log_peak) do { \ - uint64_t plat_ts = platform_timer_get(timer_get()); \ - uint64_t cpu_ts = arch_timer_get_system(cpu_timer_get()); \ - if ((pcd)->plat_ts) { \ - (pcd)->plat_delta_last = plat_ts - (pcd)->plat_ts;\ - (pcd)->cpu_delta_last = cpu_ts - (pcd)->cpu_ts; \ - } \ - (pcd)->plat_ts = plat_ts; \ - (pcd)->cpu_ts = cpu_ts; \ - if ((pcd)->plat_delta_last > (pcd)->plat_delta_peak) \ - (pcd)->plat_delta_peak = (pcd)->plat_delta_last; \ - if ((pcd)->cpu_delta_last > (pcd)->cpu_delta_peak) { \ - (pcd)->cpu_delta_peak = (pcd)->cpu_delta_last; \ - if (log_peak) \ - perf_cnt_trace(tclass, pcd); \ - } \ +/** \brief Reads the timers and computes delta to the previous readings. + * + * If current arch delta exceeds the previous peak value, trace_m is run. + * \param pcd Performance counters data. + * \param trace_m Trace function trace_m(pcd, arg) or trace macro if a + * more precise line number is desired in the logs. + * \param arg Argument passed to trace_m as arg. + */ +#define perf_cnt_stamp(pcd, trace_m, arg) do { \ + uint32_t plat_ts = \ + (uint32_t)sof_cycle_get_64(); \ + uint32_t cpu_ts = \ + (uint32_t)perf_cnt_get_cpu_ts(); \ + (pcd)->plat_delta_last = plat_ts - (pcd)->plat_ts; \ + (pcd)->cpu_delta_last = cpu_ts - (pcd)->cpu_ts; \ + if ((pcd)->plat_delta_last > (pcd)->plat_delta_peak) { \ + (pcd)->plat_delta_peak = (pcd)->plat_delta_last; \ + (pcd)->peak_mcps_period_cnt = (pcd)->period_cnt; \ + } \ + if ((pcd)->cpu_delta_last > (pcd)->cpu_delta_peak) { \ + (pcd)->cpu_delta_peak = (pcd)->cpu_delta_last; \ + trace_m(pcd, arg); \ + } \ + } while (0) + +/** + * For simple performance measurement and optimization in development stage, + * tic-toc api is provided. Performance data are traced at each tok call, + * to allow fast clocks usage deviation estimation. Example: + * + * \code{.c} + * void foo(struct comp_dev *dev) { + * static struct perf_cnt_data pcd; + * + * perf_tic(&pcd); + * bar(); + * perf_toc(&pcd, dev); + * } + * \endcode + */ + +/** \brief Save start timestamp in pcd structure + * + * \param pcd Performance counters data. + */ +#define perf_tic(pcd) \ + perf_cnt_init(pcd) + +/** \brief Save start timestamp in pcd structure + * + * \param pcd Performance counters data. + * \param comp Component used to get corresponding trace context. + */ +#define perf_toc(pcd, comp) do { \ + perf_cnt_stamp(pcd, perf_trace_null, NULL); \ + perf_trace_simple(pcd, trace_comp_get_tr_ctx(comp)); \ } while (0) #else -#define perf_cnt_trace(tclass, pcd) #define perf_cnt_clear(pcd) #define perf_cnt_init(pcd) -#define perf_cnt_stamp(tclass, pcd, log_peak) +#define perf_cnt_stamp(pcd, trace_m, arg) +#define perf_cnt_average(pcd, trace_m, arg) #endif #endif /* __SOF_LIB_PERF_CNT_H__ */ diff --git a/src/include/sof/lib/pm_memory.h b/src/include/sof/lib/pm_memory.h deleted file mode 100644 index 5db7a2e68edb..000000000000 --- a/src/include/sof/lib/pm_memory.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Jakub Dabek <jakub.dabek@linux.intel.com> - */ - -/** - * \file include/sof/lib/pm_memory.h - * \brief Runtime power management header file - * \author Jakub Dabek <jakub.dabek@linux.intel.com> - */ - -#ifndef __SOF_LIB_PM_MEMORY_H__ -#define __SOF_LIB_PM_MEMORY_H__ - -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <stdint.h> - -/** \brief Memory banks pm masks data. */ -struct ebb_data { - uint32_t current_mask0; - uint32_t current_mask1; - uint32_t new_mask0; - uint32_t new_mask1; - uint32_t change_mask0; - uint32_t change_mask1; - uint32_t start_bank_id; - uint32_t ending_bank_id; - uint32_t start_bank_id_high; - uint32_t ending_bank_id_high; -}; - -/** - * \brief Set power gating of memory banks in the address range - * - * Power gates address range only on full banks if given address form mid block - * it will try to narrow down power gate to nearest full banks - * - * \param[in] ptr Ptr to address from which to start gating. - * \param[in] size Size of memory to manage. - * \param[in] enabled Boolean deciding banks desired state (1 powered 0 gated). - */ -void set_power_gate_for_memory_address_range(void *ptr, - uint32_t size, uint32_t enabled); - -#endif /* __SOF_LIB_PM_MEMORY_H__ */ diff --git a/src/include/sof/lib/pm_runtime.h b/src/include/sof/lib/pm_runtime.h deleted file mode 100644 index 4418be726103..000000000000 --- a/src/include/sof/lib/pm_runtime.h +++ /dev/null @@ -1,133 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - * Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -/** - * \file include/sof/lib/pm_runtime.h - * \brief Runtime power management header file - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifndef __SOF_LIB_PM_RUNTIME_H__ -#define __SOF_LIB_PM_RUNTIME_H__ - -#include <platform/lib/pm_runtime.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <stdint.h> - -/** \addtogroup pm_runtime PM Runtime - * PM runtime specification. - * @{ - */ - -/** \brief Power management trace function. */ -#define trace_pm(__e, ...) \ - trace_event(TRACE_CLASS_POWER, __e, ##__VA_ARGS__) -#define tracev_pm(__e, ...) \ - tracev_event(TRACE_CLASS_POWER, __e, ##__VA_ARGS__) - -/* PM runtime flags */ - -#define RPM_ASYNC 0x01 /**< Request is asynchronous */ - -/** \brief Runtime power management context */ -enum pm_runtime_context { - PM_RUNTIME_HOST_DMA_L1 = 0, /**< Host DMA L1 Exit */ - SSP_CLK, /**< SSP Clock */ - SSP_POW, /**< SSP Power */ - DMIC_CLK, /**< DMIC Clock */ - DMIC_POW, /**< DMIC Power */ - DW_DMAC_CLK, /**< DW DMAC Clock */ - CORE_MEMORY_POW, /**< Core Memory power */ - PM_RUNTIME_DSP /**< DSP */ -}; - -/** \brief Runtime power management data. */ -struct pm_runtime_data { - spinlock_t lock; /**< lock mechanism */ - void *platform_data; /**< platform specific data */ -}; - -/** - * \brief Initializes runtime power management. - */ -void pm_runtime_init(struct sof *sof); - -/** - * \brief Retrieves power management resource (async). - * - * \param[in] context Type of power management context. - * \param[in] index Index of the device. - */ -void pm_runtime_get(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Retrieves power management resource. - * - * \param[in] context Type of power management context. - * \param[in] index Index of the device. - */ -void pm_runtime_get_sync(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Releases power management resource (async). - * - * \param[in] context Type of power management context. - * \param[in] index Index of the device. - */ -void pm_runtime_put(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Releases power management resource. - * - * \param[in] context Type of power management context. - * \param[in] index Index of the device. - */ -void pm_runtime_put_sync(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Enables power management operations for the resource. - * - * \param[in] context Type of power management context. - * \param[in] index Index of the device. - */ -void pm_runtime_enable(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Disables power management operations for the resource. - * - * \param[in] context Type of power management context. - * \param[in] index Index of the device. - */ -void pm_runtime_disable(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Reports state of the power managed resource. - * - * @param context Type of power management context. - * @param index Index of the resource. - * - * @return true if the resource is active or pm disabled, false otherwise. - */ -bool pm_runtime_is_active(enum pm_runtime_context context, uint32_t index); - -/** - * \brief Retrieves pointer to runtime power management data. - * - * @return Runtime power management data pointer. - */ -static inline struct pm_runtime_data *pm_runtime_data_get(void) -{ - return sof_get()->prd; -} - -/** @}*/ - -#endif /* __SOF_LIB_PM_RUNTIME_H__ */ diff --git a/src/include/sof/lib/uuid.h b/src/include/sof/lib/uuid.h index 9393a45baee2..d45f821613d7 100644 --- a/src/include/sof/lib/uuid.h +++ b/src/include/sof/lib/uuid.h @@ -9,6 +9,13 @@ #define __SOF_LIB_UUID_H__ #include <sof/common.h> +#include <uuid-registry.h> + +#ifdef __ZEPHYR__ +#include <zephyr/sys/iterable_sections.h> +#endif + +#include <stdint.h> /** \addtogroup uuid_api UUID API * UUID API specification. @@ -18,6 +25,9 @@ /** \brief UUID is 16 bytes long */ #define UUID_SIZE 16 +/** \brief UUID name string max length in bytes, including null termination */ +#define UUID_NAME_MAX_LEN 32 + /** * \brief UUID (Universally Unique IDentifier) structure. * @@ -32,27 +42,79 @@ * * UUID for a new component may be generated with uuidgen Linux tool, part * of the util-linux package. + * + * FIXME: this struct scheme has an endianness bug. On BE systems, + * the same initialier for the a/b/c fields will produce different + * memory layout than on LE systems. Within C code, that's fine, but + * when compared with external representations (c.f. topology) that + * pass UUIDs as a linear array of bytes, only one endianness will + * work. If SOF ever ships on a BE system all use of sof_uuid will + * need to be modified to byte swap the a/b/c values. + * + * Some identifiers are taken from the module manifest. Since the module + * manifest structure (sof_man_module) is marked as packed, the pointer + * to the sof_uuid structure may not be properly aligned. To avoid possible + * problems with accessing fields of this structure from unaligned addresses, + * it has been marked as packed. */ struct sof_uuid { uint32_t a; uint16_t b; uint16_t c; uint8_t d[8]; -}; +} __packed; -#if CONFIG_LIBRARY -#define DECLARE_SOF_UUID(entity_name, uuid_name, \ - va, vb, vc, \ - vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7) +#define _UUID_INIT(va, vb, vc, d0, d1, d2, d3, d4, d5, d6, d7) \ + { va, vb, vc, { d0, d1, d2, d3, d4, d5, d6, d7 } } -#define SOF_UUID(uuid_name) 0 +/** + * \brief Connects UUID with component description + * + * Declaration of this structure should be done by DECLARE_SOF_UUID(), + * then declaration will be part of `.static_uuids` section and `SMEX` tool + * use it during `ldc` file creation. + */ +struct sof_uuid_entry { + struct sof_uuid id; + const char name[UUID_NAME_MAX_LEN]; +}; + +#ifdef __ZEPHYR__ +/* Zephyr puts all the UUID structs into the firmware .rodata as an + * ITERABLE array. Note the alias emitted to get the typing correct, + * Zephyr defines the full suf_uuid_entry struct, where the API + * demands that the symbol name refer to a struct sof_uuid. + */ +#define _UUID(uuid_name) (&_##uuid_name) +#define _RT_UUID(uuid_name) (&uuid_name) +#define _DEF_UUID(entity_name, uuid_name, initializer) \ + const STRUCT_SECTION_ITERABLE(sof_uuid_entry, _##uuid_name) = \ + { .id = initializer, .name = entity_name }; \ + extern const struct sof_uuid \ + __attribute__((alias("_" #uuid_name))) uuid_name #else +/* XTOS SOF emits two definitions, one into the runtime (which may not + * be linked if unreferenced) and a separate one that goes into a + * special section via handling in the linker script. + */ +#define _UUID(uuid_name) (&(uuid_name ## _ldc)) +#define _RT_UUID(uuid_name) (&(uuid_name)) +#define _DEF_UUID(entity_name, uuid_name, initializer) \ + __section(".static_uuids") \ + static const struct sof_uuid_entry uuid_name ## _ldc \ + = { .id = initializer, .name = entity_name }; \ + const struct sof_uuid uuid_name = initializer + +#endif /* __ZEPHYR__ */ -/** \brief Declares UUID (aaaaaaaa-bbbb-cccc-d0d1-d2d3d4d5d6d7) and name. +/** \brief Declares runtime UUID (aaaaaaaa-bbbb-cccc-d0d1-d2d3d4d5d6d7) and name. + * + * UUID value from variables declared with this macro are accessible in + * runtime code - to dereference use SOF_RT_UUID() * * \param entity_name Name of the object pinted by the software tools. - * \param uuid_name Uuid symbol name used with SOF_UUID(). + * \param uuid_name Uuid symbol name used with SOF_UUID() and SOF_RT_UUID(). * \param va aaaaaaaa value. * \param vb bbbb value. * \param vc cccc value. @@ -65,27 +127,47 @@ struct sof_uuid { * \param vd6 d6 value. * \param vd7 d7 value. */ -#define DECLARE_SOF_UUID(entity_name, uuid_name, \ - va, vb, vc, \ - vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7) \ - __section(".static_uuids") \ - static const struct { \ - struct sof_uuid id; \ - uint32_t name_len; \ - const char name[sizeof(entity_name)]; \ - } uuid_name = { \ - {.a = va, .b = vb, .c = vc, \ - .d = {vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7}}, \ - sizeof(entity_name), \ - entity_name \ - } +#define SOF_DEFINE_UUID(entity_name, uuid_name, va, vb, vc, \ + vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7) \ + _DEF_UUID(entity_name, uuid_name, \ + _UUID_INIT(va, vb, vc, vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7)) + +/** \brief Get UUID value sourced from the fixed SOF registry + * + * The ID value is sourced by name from the uuid-registry.txt file distributed with the source tree. + * + * \param name Name of the UUID, must match an entry in uuid-registry.txt + */ +#define SOF_REG_UUID(name) _UUIDREG_##name + +/** \brief Defines UUID sourced from the fixed SOF registry + * + * As for SOF_DEFINE_UUID(), but the ID value is sourced by name from + * the uuid-registry.txt file distributed with the source tree. The + * string name field will be identical with the name passed (which is + * passed as a symbol!), runtime symbol (e.g. the "uuid_name" argument + * to SOF_DEFINE_UUID()) will be the same, postfixed with a "_uuid". + * + * \param name Name of the UUID, must match an entry in uuid-registry.txt + */ +#define SOF_DEFINE_REG_UUID(name) _DEF_UUID(#name, name##_uuid, SOF_REG_UUID(name)) /** \brief Creates local unique 32-bit representation of UUID structure. * - * \param uuid_name UUID symbol name declared with DECLARE_SOF_UUID(). + * In Zephyr builds, this has the same address as the result of + * SOF_RT_UUID, but has type of "struct sof_uuid *" and not "struct + * sof_uid_record *" + * + * \param uuid_name UUID symbol name declared with DECLARE_SOF_UUID() or + * DECLARE_SOF_RT_UUID(). */ -#define SOF_UUID(uuid_name) ((uintptr_t)&(uuid_name)) -#endif +#define SOF_UUID(uuid_name) _UUID(uuid_name) + +/** \brief Dereference unique 32-bit representation of UUID structure in runtime. + * + * \param uuid_name UUID symbol name declared with DECLARE_SOF_RT_UUID(). + */ +#define SOF_RT_UUID(uuid_name) _RT_UUID(uuid_name) /** @}*/ diff --git a/src/include/sof/lib/vregion.h b/src/include/sof/lib/vregion.h new file mode 100644 index 000000000000..612443f5bc48 --- /dev/null +++ b/src/include/sof/lib/vregion.h @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2025 Intel Corporation. + +/* Pre Allocated Contiguous Virtual Region */ +#ifndef __SOF_LIB_VREGION_H__ +#define __SOF_LIB_VREGION_H__ + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct vregion; + +/** + * @brief Memory types for virtual region allocations. + * Used to specify the type of memory allocation within a virtual region. + * + * @note + * - interim: allocation that can be freed i.e. get/set large config, kcontrols. + * - lifetime: allocation that cannot be freed i.e. init data, pipeline data. + */ +enum vregion_mem_type { + VREGION_MEM_TYPE_INTERIM, /* interim allocation that can be freed */ + VREGION_MEM_TYPE_LIFETIME, /* lifetime allocation */ +}; + +#if CONFIG_SOF_VREGIONS + +/** + * @brief Create a new virtual region instance. + * + * Create a new virtual region instance with specified static and dynamic partitions. + * Total size is the sum of static and dynamic sizes. + * + * @param[in] lifetime_size Size of the virtual region lifetime partition. + * @param[in] interim_size Size of the virtual region interim partition. + * @return struct vregion* Pointer to the new virtual region instance, or NULL on failure. + */ +struct vregion *vregion_create(size_t lifetime_size, size_t interim_size); + +/** + * @brief Increment virtual region's user count. + * + * The creator of the virtual region is its first user, for any additional users + * increment the region's use-count. + * + * @param[in] vr Pointer to the virtual region instance to release. + * @return struct vregion* Pointer to the virtual region instance. + */ +struct vregion *vregion_get(struct vregion *vr); + +/** + * @brief Decrement virtual region's user count or destroy it. + * + * Decrement virtual region's user count, when it reaches 0 free all associated + * resources. + * + * @param[in] vr Pointer to the virtual region instance to release. + * @return struct vregion* Pointer to the virtual region instance or NULL if it has been destroyed. + */ +struct vregion *vregion_put(struct vregion *vr); + +/** + * @brief Allocate memory from the specified virtual region. + * + * @param[in] vr Pointer to the virtual region instance. + * @param[in] type Type of memory to allocate (lifetime or interim). + * @param[in] size Size of memory to allocate in bytes. + * @return void* Pointer to the allocated memory, or NULL on failure. + */ +void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size); + +/** + * @brief like vregion_alloc() but allocates coherent memory + */ +void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size); + +/** + * @brief Allocate aligned memory from the specified virtual region. + * + * Allocate aligned memory from the specified virtual region based on the memory type. + * + * @param[in] vr Pointer to the virtual region instance. + * @param[in] type Type of memory to allocate (lifetime or interim). + * @param[in] size Size of memory to allocate in bytes. + * @param[in] alignment Alignment of memory to allocate in bytes. + * @return void* Pointer to the allocated memory, or NULL on failure. + */ +void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type, + size_t size, size_t alignment); + +/** + * @brief like vregion_alloc_align() but allocates coherent memory + */ +void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type, + size_t size, size_t alignment); + +/** + * @brief Free memory allocated from the specified virtual region. + * + * Free memory previously allocated from the specified virtual region. + * + * @param[in] vr Pointer to the virtual region instance. + * @param[in] ptr Pointer to the memory to free. + */ +void vregion_free(struct vregion *vr, void *ptr); + +/** + * @brief Log virtual region memory usage. + * + * @param[in] vr Pointer to the virtual region instance. + */ +void vregion_info(struct vregion *vr); + +/** + * @brief Get virtual region memory start and size. + * + * @param[in] vr Pointer to the virtual region instance. + * @param[in] size Pointer to size + * @param[in] start Pointer to start + */ +void vregion_mem_info(struct vregion *vr, size_t *size, uintptr_t *start); + +#else /* CONFIG_SOF_VREGIONS */ + +#include <rtos/alloc.h> + +struct vregion { + unsigned int use_count; +}; + +static inline struct vregion *vregion_create(size_t lifetime_size, size_t interim_size) +{ + struct vregion *vr = rmalloc(0, sizeof(*vr)); + + vr->use_count = 1; + return vr; +} +static inline struct vregion *vregion_get(struct vregion *vr) +{ + if (vr) + vr->use_count++; + return vr; +} +static inline struct vregion *vregion_put(struct vregion *vr) +{ + if (vr && !--vr->use_count) + rfree(vr); + return vr; +} +static inline void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size) +{ + return NULL; +} +static inline void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, + size_t size) +{ + return NULL; +} +static inline void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type, + size_t size, size_t alignment) +{ + return NULL; +} +static inline void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type, + size_t size, size_t alignment) +{ + return NULL; +} +static inline void vregion_free(struct vregion *vr, void *ptr) {} +static inline void vregion_info(struct vregion *vr) {} +static inline void vregion_mem_info(struct vregion *vr, size_t *size, uintptr_t *start) +{ + if (size) + *size = 0; +} + +#endif /* CONFIG_SOF_VREGIONS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SOF_LIB_VREGION_H__ */ diff --git a/src/include/sof/lib/wait.h b/src/include/sof/lib/wait.h deleted file mode 100644 index b8661ba59e14..000000000000 --- a/src/include/sof/lib/wait.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -/* - * Simple wait for event completion and signaling with timeouts. - */ - -#ifndef __SOF_LIB_WAIT_H__ -#define __SOF_LIB_WAIT_H__ - -#include <arch/lib/wait.h> -#include <sof/drivers/timer.h> -#include <sof/platform.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <config.h> -#include <stddef.h> -#include <stdint.h> - -static inline void wait_for_interrupt(int level) -{ - tracev_event(TRACE_CLASS_WAIT, "WFE"); -#if CONFIG_DEBUG_LOCKS - if (lock_dbg_atomic) - trace_error_atomic(TRACE_CLASS_WAIT, "atm"); -#endif - platform_wait_for_interrupt(level); - tracev_event(TRACE_CLASS_WAIT, "WFX"); -} - -/** - * \brief Waits at least passed number of clocks. - * \param[in] number_of_clks Minimum number of clocks to wait. - */ -void wait_delay(uint64_t number_of_clks); - -int poll_for_register_delay(uint32_t reg, uint32_t mask, - uint32_t val, uint64_t us); - -#endif /* __SOF_LIB_WAIT_H__ */ diff --git a/src/include/sof/lib/watchdog.h b/src/include/sof/lib/watchdog.h new file mode 100644 index 000000000000..6eedaa4fd5c6 --- /dev/null +++ b/src/include/sof/lib/watchdog.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +/* + * A set of functions that allows implement a watchdog protection for ll scheduler tasks. The + * watchdog_enable function is called after creating a ll thread for specified core. Its task is to + * start the watchdog for a given core. When all tasks are finished, function watchdog_disable will + * be called before stopping the thread. It should stop the watchdog on the given core. + * Periodically, after each tick has been handled, the watchdog counter is reseted by calling + * watchdog_feed. + */ + +#ifndef __SOF_LIB_WATCHDOG_H__ +#define __SOF_LIB_WATCHDOG_H__ + +#include <sof/common.h> + +#if IS_ENABLED(CONFIG_LL_WATCHDOG) +/** + * \brief Enable a watchdog timer for specified core + * \param[in] core Core id + */ +void watchdog_enable(int core); + +/** + * \brief Disable a watchdog timer for specified core + * \param[in] core Core id + */ +void watchdog_disable(int core); + +/** + * \brief Feed a watchdog timer for specified core + * \param[in] core Core id + */ +void watchdog_feed(int core); + +/** + * \brief ll watchdog infrastructure initialization + */ +void watchdog_init(void); + +/** + * \brief Watchdog timeout notification on secondary core + * + * This function is called by the idc handler after receiving a watchdog timeout notification for + * secondary core. Executes on primary core. + * + * \param[in] core Core id + */ +void watchdog_secondary_core_timeout(int core); +#else /* IS_ENABLED(CONFIG_LL_WATCHDOG) */ +static inline void watchdog_enable(int core) {} +static inline void watchdog_disable(int core) {} +static inline void watchdog_feed(int core) {} +static inline void watchdog_init(void) {} +static inline void watchdog_secondary_core_timeout(int core) {} +#endif /* IS_ENABLED(CONFIG_LL_WATCHDOG) */ + +#endif /* __SOF_LIB_WATCHDOG_H__ */ diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h new file mode 100644 index 000000000000..29c226eb61a7 --- /dev/null +++ b/src/include/sof/lib_manager.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ + +/* + * Library manager implementation for SOF is using module adapter API for + * loadable native and external libraries. Depends of information received from + * it manages memory and locate accordingly to available space. + * + * Driver IPC4 Library MEMORY ENTITY + * Handler Manager VERIF. + * | | | | | + * | IPC4_GLB_LOAD_LIBRARY | | | | + * | --------------------> | lib_manager_load_library() | | | + * | | -------------------------> | Prepare DMA transfer | | + * | | | ------- | | + * | | | | | | + * | | | <------ | | + * | | | -----------------------> | | + * | | | | | + * | | | (IF AUTH_API_ENABLED) | | + * | | | Verify Manifest | | + * | | | -------------------------|-------> | + * | | | results | | + * | | | <------------------------|-------- | + * | | | (IF AUTH_API_ENABLED) | | + * | | | | | + * | | | Parse Manifest | | + * | | | Prepare Storage Memory | | + * | | | ------- | | + * | | | | | | + * | | | <------ | | + * | | | | | + * | | | Copy Library Data | | + * | | | -----------------------> | | + * | | | | | + * | | | (IF AUTH_API_ENABLED) | | + * | | | Verify Manifest | | + * | | | -------------------------|-------> | + * | | | results | | + * | | | <------------------------|-------- | + * | | | (IF AUTH_API_ENABLED) | | + * | | | | | + * | | | Update Library | | + * | | | descriptors table | | + * | | | ------- | | + * | | | | | | + * | | | <------ | | + * | | return status | | | + * | | <------------------------- | | | + * | Complete IPC request | | | | + * | <------------------- | | | | + * + * Driver IPC4 Library MEMORY ENTITY + * Handler Manager VERIF. + */ + +#ifndef __SOF_LIB_MANAGER_H__ +#define __SOF_LIB_MANAGER_H__ + +#include <stdint.h> +#include <sof/list.h> +#include <sof/audio/component.h> +#include <rimage/sof/user/manifest.h> +#if CONFIG_LIBRARY_AUTH_SUPPORT +#include <sof/auth_api_iface.h> +#endif +#include <sof/list.h> + +#define LIB_MANAGER_MAX_LIBS 16 +#define LIB_MANAGER_LIB_ID_SHIFT 12 +#define LIB_MANAGER_LIB_NOTIX_MAX_COUNT 4 + +#define LIB_MANAGER_GET_LIB_ID(module_id) (((module_id) & 0xF000) >> LIB_MANAGER_LIB_ID_SHIFT) +#define LIB_MANAGER_GET_MODULE_INDEX(module_id) ((module_id) & 0xFFF) +#define LIB_MANAGER_PACK_MODULE_ID(lib_index, module_index) (((module_index) & 0xFFF) | \ + (((lib_index) << LIB_MANAGER_LIB_ID_SHIFT) & 0xF000)) +#define LIB_MANAGER_PACK_LIB_ID(lib_index) LIB_MANAGER_PACK_MODULE_ID(lib_index, 0x0) + +#ifdef CONFIG_LIBRARY_MANAGER +struct ipc_lib_msg { + struct ipc_msg *msg; + struct list_item list; +}; + +struct sof_man_module_manifest; + +enum { + LIB_MANAGER_TEXT, + LIB_MANAGER_DATA, + LIB_MANAGER_RODATA, + LIB_MANAGER_BSS, + LIB_MANAGER_COLD, + LIB_MANAGER_COLDRODATA, + LIB_MANAGER_N_SEGMENTS, +}; + +struct lib_manager_segment_desc { + uintptr_t addr; + size_t size; +}; + +struct llext; +struct llext_buf_loader; + +struct lib_manager_module { + unsigned int start_idx; /* Index of the first driver from this module in + * the library-global driver list */ + const struct sof_man_module_manifest *mod_manifest; + struct llext *llext; /* Zephyr loadable extension context */ + struct llext_buf_loader *ebl; /* Zephyr loadable extension buffer loader */ + unsigned int n_dependent; /* For auxiliary modules: number of dependents */ + bool mapped; + struct lib_manager_segment_desc segment[LIB_MANAGER_N_SEGMENTS]; +}; + +struct lib_manager_mod_ctx { + void *base_addr; /* library cold storage address (e.g. DRAM) */ + unsigned int n_mod; + struct lib_manager_module *mod; +}; + +struct ext_library { + struct k_spinlock lock; /* last locking CPU record */ + struct lib_manager_mod_ctx *desc[LIB_MANAGER_MAX_LIBS]; +#ifdef CONFIG_LIBCODE_MODULE_SUPPORT + uint32_t mods_exec_load_cnt; +#endif + struct ipc_lib_msg *lib_notif_pool; + uint32_t lib_notif_count; + + /* Only needed from SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE to SOF_IPC4_GLB_LOAD_LIBRARY */ + void *runtime_data; +}; + +/* lib manager context, used by lib_notification */ +extern struct tr_ctx lib_manager_tr; + +static inline struct ext_library *ext_lib_get(void) +{ + return sof_get()->ext_library; +} + +static inline struct lib_manager_mod_ctx *lib_manager_get_mod_ctx(int module_id) +{ + uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); + struct ext_library *_ext_lib = ext_lib_get(); + + if (!_ext_lib || lib_id >= LIB_MANAGER_MAX_LIBS) + return NULL; + + return _ext_lib->desc[lib_id]; +} + +/* + * \brief Get module manifest for given module id + * + * param[in] module_id - used to get library manifest + * + * Gets library manifest descriptor using module_id to locate it + */ +const struct sof_man_module *lib_manager_get_module_manifest(const uint32_t module_id); +#endif + +/* + * \brief Initialize library manager + */ +void lib_manager_init(void); + +/* + * \brief Register module on driver list + * + * param[in] component_id - component id coming from ipc config. This function reguires valid + * lib_id and module_id fields of component id. + * + * Creates new comp_driver_info and initialize it for module from library + * Adds new module to sof_get()->comp_drivers list + */ +int lib_manager_register_module(const uint32_t component_id); + +/* + * \brief Get library module manifest descriptor + * + * param[in] module_id - used to get text manifest offset + * + * Gets firmware manifest descriptor using module_id to locate it + */ +const struct sof_man_fw_desc *lib_manager_get_library_manifest(int module_id); + +/* + * \brief Get address and size of the bss section for given module instance + * + * param[in] instance_id - instance id + * param[in] mod - module manifest + * param[out] va_addr - address of the bss section + * param[out] size - size of the bss section + */ +void lib_manager_get_instance_bss_address(uint32_t instance_id, + const struct sof_man_module *mod, + void __sparse_cache **va_addr, size_t *size); + +/* + * \brief Load library + * + * param[in] dma_id - channel used to transfer binary from host + * param[in] lib_id + * param[in] type - ipc command type + * (SOF_IPC4_GLB_LOAD_LIBRARY or SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE) + * + * Function will load library manifest into temporary buffer. + * Then it will read library parameters, allocate memory for library and load it into + * destination memory region. + */ +int lib_manager_load_library(uint32_t dma_id, uint32_t lib_id, uint32_t type); + +/* + * \brief Initialize message + * + * param[in] header - IPC header provided by caller + * param[in] size - size of data buffer for messege to be send + * + * Function search lib_notif_pool for free message handler. + * If not found allocates new message handle and returns it to + * caller. + */ +struct ipc_msg *lib_notif_msg_init(uint32_t header, uint32_t size); + +/* + * \brief Send message + * + * param[in] msg - IPC message handler + * + * Function sends IPC message and calls lib_notif_msg_clean() to + * free unused message handlers. Only single message handle will + * be kept in list while at least one loadable module is loaded. + */ +void lib_notif_msg_send(struct ipc_msg *msg); + +/* + * \brief Clean unused message handles + * + * param[in] leave_one_handle - remove all unused or keep one + * + * Function search lib_notif_pool list for unused message handles. + * Remove them keeping one if leave_one_handle == true. + */ +void lib_notif_msg_clean(bool leave_one_handle); + +#endif /* __SOF_LIB_MANAGER_H__ */ diff --git a/src/include/sof/list.h b/src/include/sof/list.h index ce85467f1cc3..048c28633ef3 100644 --- a/src/include/sof/list.h +++ b/src/include/sof/list.h @@ -18,6 +18,9 @@ struct list_item { struct list_item *prev; }; +/* a static list head initialiser */ +#define LIST_INIT(head) {&head, &head} + /* initialise list before any use - list will point to itself */ static inline void list_init(struct list_item *list) { @@ -83,7 +86,7 @@ static inline int list_item_is_last(struct list_item *item, /* get the next container object in the list */ #define list_next_item(object, member) \ - list_item((object)->member.next, typeof(*(object)), member) + list_item((object)->member.next, __typeof__(*(object)), member) /* list iterator */ #define list_for_item(item, list) \ @@ -98,4 +101,27 @@ static inline int list_item_is_last(struct list_item *item, for (item = (list)->next, tmp = item->next;\ item != (list); \ item = tmp, tmp = item->next) + +/** + * Re-links the list when head address changed (list moved). + * @param new_list New address of the head. + * @param old_list Old address of the head. + */ +static inline void list_relink(struct list_item *new_list, + struct list_item *old_list) +{ + struct list_item *li; + + if (new_list->next == old_list) { + list_init(new_list); + } else { + list_for_item(li, new_list) + if (li->next == old_list) + li->next = new_list; /* for stops here */ + list_for_item_prev(li, new_list) + if (li->prev == old_list) + li->prev = new_list; /* for stops here */ + } +} + #endif /* __SOF_LIST_H__ */ diff --git a/src/include/sof/llext_manager.h b/src/include/sof/llext_manager.h new file mode 100644 index 000000000000..525fa50b1506 --- /dev/null +++ b/src/include/sof/llext_manager.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_LLEXT_MANAGER_H__ +#define __SOF_LLEXT_MANAGER_H__ + +#include <stdbool.h> +#include <stdint.h> + +#if CONFIG_LLEXT +#include <rimage/sof/user/manifest.h> + +struct comp_dev; +struct comp_driver; +struct comp_ipc_config; +struct k_mem_domain; + +static inline bool module_is_llext(const struct sof_man_module *mod) +{ + return mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT || + mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT_AUX; +} + +uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config); + +int llext_manager_free_module(const uint32_t component_id); + +int llext_manager_add_library(uint32_t module_id); + +int llext_manager_add_domain(const uint32_t component_id, struct k_mem_domain *domain); +int llext_manager_rm_domain(const uint32_t component_id, struct k_mem_domain *domain); + +bool comp_is_llext(struct comp_dev *comp); +#else +#define module_is_llext(mod) false +#define llext_manager_allocate_module(ipc_config, ipc_specific_config) 0 +#define llext_manager_free_module(component_id) 0 +#define llext_manager_add_library(module_id) 0 +#define llext_manager_add_domain(component_id, domain) 0 +#define comp_is_llext(comp) false +#endif + +#if CONFIG_LLEXT_EXPERIMENTAL && !CONFIG_ADSP_IMR_CONTEXT_SAVE +int llext_manager_store_to_dram(void); +int llext_manager_restore_from_dram(void); +#else +#define llext_manager_store_to_dram() 0 +#define llext_manager_restore_from_dram() -ENOSYS +#endif + +#endif diff --git a/src/include/sof/math/a_law.h b/src/include/sof/math/a_law.h new file mode 100644 index 000000000000..1b7cac744438 --- /dev/null +++ b/src/include/sof/math/a_law.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +#ifndef __SOF_MATH_A_LAW_H__ +#define __SOF_MATH_A_LAW_H__ + +#include <stdint.h> + +/** + * sofm_a_law_encode() - Encode sample with A-law coding + * @param sample: A s16 sample value + * + * The A-law codec is defined in ITU-T G.711 standard and has been used + * in telecommunications in e.g. Europe. The A-law coding compresses 13 bit + * samples to 8 bit data stream. In SOF the high 13 bits of s16 format are + * used for compatibility with normal audios. + * + * @return: Compressed 8 bit code value + */ +uint8_t sofm_a_law_encode(int16_t sample); + +/** + * sofm_a_law_decode() - Decode A-law encoded code word + * @param byte: Encoded code word + * + * The A-law decoder expands a 8 bit code word into a 13 bit sample value. + * In the SOF the high 13 bits are aligned to the most significant bits + * to be compatible with normal s16 Q1.15 samples. + * + * @return: Sample value in s16 format + */ +int16_t sofm_a_law_decode(int8_t byte); + +#endif /* __SOF_MATH_A_LAW_H__ */ diff --git a/src/include/sof/math/auditory.h b/src/include/sof/math/auditory.h new file mode 100644 index 000000000000..bd707dc5079a --- /dev/null +++ b/src/include/sof/math/auditory.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +/* Psychoacoustics related functions */ + +#ifndef __SOF_MATH_AUDITORY_H__ +#define __SOF_MATH_AUDITORY_H__ + +#include <sof/math/fft.h> +#include <sof/math/log.h> +#include <stdint.h> + +#define AUDITORY_EPS_Q31 1 /* Smallest nonzero Q1.31 value */ +#define AUDITORY_LOG2_2P25_Q16 Q_CONVERT_FLOAT(25.0, 16) /* log2(2^25) */ + +enum psy_mel_log_scale { + MEL_LOG = 0, + MEL_LOG10, + MEL_DB, +}; + +/* Struct to define Mel filterback calculation. The filterbank data is compressed into + * a single vector from normal (half_fft_bins, mel_bins) size by storing only non-zero + * weights values. + * + * Triangles data Number triangles is mel_bins + * then for each triangle: + * index to next triangle 0, start fft_bin 1, length of this triangle 2, + * triangle weight values 3..N + */ +struct psy_mel_filterbank { + int32_t log_mult; /**< Out, QX.Y scale for log, log10, or dB format */ + int32_t scale_log2; /**< Out, Scale as log2 Q16.16 to apply to Mel energies */ + int32_t samplerate; /**< In, Hz Q0*/ + int16_t start_freq; /**< In, Hz Q0*/ + int16_t end_freq; /**< In, Hz Q0*/ + int16_t *scratch_data1; /**< Scratch, At least half_fft_bins size */ + int16_t *scratch_data2; /**< Scratch, Packed triangles data */ + int16_t *data; /**< Out, Packed triangles data */ + int scratch_length1; /**< In, Length of first scratch */ + int scratch_length2; /**< In, Length of second scratch */ + int fft_bins; /**< In, Number of FFT bins */ + int half_fft_bins; /**< In, fft_bins / 2 + 1 */ + int mel_bins; /**< In, Number of Mel frequency bins */ + int data_length; /**< Out, Number of int16_t words in triangles data */ + enum psy_mel_log_scale mel_log_scale; /**< In, LOG, LOG10 or DB to select Mel format */ + bool slaney_normalize; /**< In, Apply Slaney type normalization for filterbank if true */ +}; + +/** + * \brief Convert Hz to Mel + * \param[in] hz Frequency as Q16.0 Hz. + * \return Value as Q14.2 Mel. + */ +int16_t psy_hz_to_mel(int16_t hz); + +/** + * \brief Convert Mel to Hz + * See Wikipedia https://en.wikipedia.org/wiki/Mel_scale + * hz = 700 * (exp(mel / 1126.9941805389) - 1) + * + * \param[in] mel Value as Q14.2 Mel, max 4358.4 Mel. + * \return hz Frequency as Q16.0 Hz, max 32767 Hz. + */ +int16_t psy_mel_to_hz(int16_t mel); + +/** + * \brief Get a Mel frequency filterbank + * See Wikipedia https://en.wikipedia.org/wiki/Mel_scale + * + * \param[in, out] mel_fb Struct with filterbank input parameters, in return the band + * filter coefficients. + * \return Zero when success, otherwise error code. + */ +struct processing_module; +int mod_psy_get_mel_filterbank(struct processing_module *mod, struct psy_mel_filterbank *mel_fb); +int mod_psy_free_mel_filterbank(struct processing_module *mod, struct psy_mel_filterbank *mel_fb); + +/** + * \brief Convert linear complex spectra from FFT into Mel band energies in desired + * logarithmic format. + * + * \param[in] mel_fb Struct with filterbank parameters and filter coefficients to apply. + * \param[in] fft_out Array of complex numbers from FFT in Q1.15 format. + * \param[out] power_spectra Array of linear power spectra, needed scratch are that is half + 1 + * side of fft_out. The data can be discarded after if no use. + * \param[out] mel_log Array of Q9.7 log/log10/10log10 format Mel band energies. + * \param[in] bitshift A shift left scale that has been possibly applied to FFT. This will + * be subtracted from the log or decibels notation. + */ +void psy_apply_mel_filterbank_16(struct psy_mel_filterbank *mel_fb, struct icomplex16 *fft_out, + int32_t *power_spectra, int16_t *mel_log, int bitshift); + +/** + * \brief Convert linear complex spectra from FFT into Mel band energies in desired + * logarithmic format. + * + * \param[in] mel_fb Struct with filterbank parameters and filter coefficients to apply. + * \param[in] fft_out Array of complex numbers from FFT in Q1.31 format. + * \param[out] power_spectra Array of linear power spectra, needed scratch are that is half + 1 + * side of fft_out. The data can be discarded after if no use. + * \param[out] mel_log Array of Q9.23 log/log10/10log10 format Mel band energies. + * \param[in] bitshift A shift left scale that has been possibly applied to FFT. This will + * be subtracted from the log or decibels notation. + */ +void psy_apply_mel_filterbank_32(struct psy_mel_filterbank *mel_fb, struct icomplex32 *fft_out, + int32_t *power_spectra, int32_t *mel_log, int bitshift); + +#endif /* __SOF_MATH_AUDITORY_H__ */ diff --git a/src/include/sof/math/cordic.h b/src/include/sof/math/cordic.h new file mode 100644 index 000000000000..d56e3316484f --- /dev/null +++ b/src/include/sof/math/cordic.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * + */ + +#ifndef __SOF_MATH_CORDIC_H__ +#define __SOF_MATH_CORDIC_H__ + +#include <stdint.h> + +/** + * cordic_atan2_lookup_table = atan(2.^-(0:N-1)) N = 31/16 + * CORDIC Gain is cordic_gain = prod(sqrt(1 + 2.^(-2*(0:31/16-1)))) + * Inverse CORDIC Gain,inverse_cordic_gain = 1 / cordic_gain + */ +static const int32_t cordic_lookup[CORDIC_31B_TABLE_SIZE] = { 843314857, 497837829, + 263043837, 133525159, 67021687, 33543516, 16775851, 8388437, 4194283, 2097149, + 1048576, 524288, 262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, + 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 }; + /* calculate LUT = 2*atan(2.^(-1:-1:(nIters)+1)) */ +static const int32_t cordic_ilookup[CORDIC_30B_ITABLE_SIZE] = { + 497837829, 263043836, 133525158, 67021686, 33543515, 16775850, + 8388437, 4194282, 2097149, 1048575, 524287, 262143, + 131071, 65535, 32767, 16383, 8191, 4095, + 2047, 1023, 511, 255, 127, 63, + 31, 15, 8, 4, 2, 1}; + +#endif /* __SOF_MATH_CORDIC_H__ */ diff --git a/src/include/sof/math/dct.h b/src/include/sof/math/dct.h new file mode 100644 index 000000000000..7c754f448c21 --- /dev/null +++ b/src/include/sof/math/dct.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +/* Matrix calculation related functions */ + +#ifndef __SOF_MATH_DCT_H__ +#define __SOF_MATH_DCT_H__ + +#include <sof/math/matrix.h> +#include <stdint.h> +#include <string.h> + +#define DCT_MATRIX_SIZE_MAX 42 /* Max matrix size where cos() argument fits Q7.24 */ + +enum dct_type { + DCT_I = 0, + DCT_II, +}; + +struct dct_plan_16 { + struct mat_matrix_16b *matrix; + int num_in; + int num_out; + enum dct_type type; + bool ortho; +}; + +int mod_dct_initialize_16(struct processing_module *mod, struct dct_plan_16 *dct); + +int mod_dct_free_16(struct processing_module *mod, struct dct_plan_16 *dct); + +#endif /* __SOF_MATH_DCT_H__ */ diff --git a/src/include/sof/math/exp_fcn.h b/src/include/sof/math/exp_fcn.h new file mode 100644 index 000000000000..40acd347ed1f --- /dev/null +++ b/src/include/sof/math/exp_fcn.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2025 Intel Corporation. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Pasca, Bogdan <bogdan.pasca@intel.com> + */ + +#ifndef __SOFM_EXP_FCN_H__ +#define __SOFM_EXP_FCN_H__ + +#include <stdint.h> + +#if defined(__XCC__) +/* HiFi */ +#include <xtensa/config/core-isa.h> +#if XCHAL_HAVE_HIFI5 == 1 +#define SOFM_EXPONENTIAL_HIFI5 1 +#elif XCHAL_HAVE_HIFI4 == 1 +#define SOFM_EXPONENTIAL_HIFI4 1 +#elif XCHAL_HAVE_HIFI3 == 1 +#define SOFM_EXPONENTIAL_HIFI3 1 +#endif +#else +/* !XCC */ +#define EXPONENTIAL_GENERIC 1 + +#endif + +/* Q5.27 int32(round(log((2^31 - 1)/2^20) * 2^27)) */ +#define SOFM_EXP_FIXED_INPUT_MAX 1023359037 + +/* Q8.24 int32(round((log((2^31 - 1)/2^20) * 20 / log(10)) * 2^24)) */ +#define SOFM_DB2LIN_INPUT_MAX 1111097957 + +/** + * Calculates exponent function exp(x) = e^x with accurate and efficient technique that + * includes range reduction operations, approximation with Taylor series, and reconstruction + * operations to compensate the range reductions. + * @param x The input argument as Q4.28 from -8 to +8 + * @return The calculated e^x value as Q13.19 from 3.3546e-04 to 2981.0 + */ +int32_t sofm_exp_approx(int32_t x); + +/** + * Calculated exponent function exp(x) = e^x by using sofm_exp_approx(). The input range for + * large arguments is internally reduced to -8 to +8 with rule exp(x) = exp(x/2) * exp(x/2) + * and reconstructed back. This function is essentially a wrapper for compatibility with + * existing usage of exp() function and Q-format choice. Note that the return value saturates + * to INT32_MAX with input arguments larger than 7.6246. + * @param x The input argument as Q5.27 from -16 to +16 + * @return The calculated e^x value as Q12.20 + */ +int32_t sofm_exp_fixed(int32_t x); + + +/** + * Converts a decibels value to liner amplitude lin = 10^(db/20) value with optimized + * equation exp(db * log(10)/20). Note that due to range limitation of sofm_exp_fixed() + * the output saturates to maximum with about +66 dB input. + * @param db Decibels value in Q8.24 format, from -128 to +66.226 + * @return Linear value in Q12.20 format, from 3.9811e-07 to 2048 + */ +int32_t sofm_db2lin_fixed(int32_t db); + +#endif /* __SOFM_EXP_FCN_H__ */ diff --git a/src/include/sof/math/fft.h b/src/include/sof/math/fft.h new file mode 100644 index 000000000000..df06baf47c81 --- /dev/null +++ b/src/include/sof/math/fft.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Amery Song <chao.song@intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_FFT_H__ +#define __SOF_FFT_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/format.h> +#include <sof/math/icomplex32.h> +#include <sof/common.h> +#include <stdbool.h> +#include <stdint.h> + +#define FFT_GENERIC +#if defined(__XCC__) + +#include <xtensa/config/core-isa.h> +#if XCHAL_HAVE_HIFI3 || XCHAL_HAVE_HIFI4 +#undef FFT_GENERIC +#define FFT_HIFI3 +#endif + +#endif + +#define FFT_SIZE_MIN 1 +#define FFT_SIZE_MAX 1024 +#define FFT_MULTI_COUNT_MAX 3 + +struct fft_plan { + uint32_t size; /* fft size */ + uint32_t len; /* fft length in exponent of 2 */ + uint16_t *bit_reverse_idx; /* pointer to bit reverse index array */ + struct icomplex32 *inb32; /* pointer to input integer complex buffer */ + struct icomplex32 *outb32; /* pointer to output integer complex buffer */ + struct icomplex16 *inb16; /* pointer to input integer complex buffer */ + struct icomplex16 *outb16; /* pointer to output integer complex buffer */ +}; + +struct fft_multi_plan { + struct fft_plan *fft_plan[FFT_MULTI_COUNT_MAX]; + struct icomplex32 *tmp_i32[FFT_MULTI_COUNT_MAX]; /* pointer to input buffer */ + struct icomplex32 *tmp_o32[FFT_MULTI_COUNT_MAX]; /* pointer to output buffer */ + struct icomplex32 *inb32; /* pointer to input integer complex buffer */ + struct icomplex32 *outb32; /* pointer to output integer complex buffer */ + uint16_t *bit_reverse_idx; + uint32_t total_size; + uint32_t fft_size; + int num_ffts; +}; + +/* interfaces of the library */ +struct fft_plan *mod_fft_plan_new(struct processing_module *mod, void *inb, + void *outb, uint32_t size, int bits); +void fft_execute_16(struct fft_plan *plan, bool ifft); +void fft_execute_32(struct fft_plan *plan, bool ifft); +void mod_fft_plan_free(struct processing_module *mod, struct fft_plan *plan); + +/** + * mod_fft_multi_plan_new() - Prepare FFT for 2^N size and some other FFT sizes + * @param mod: Pointer to module + * @param inb: Buffer to use for complex input data + * @param outb: Buffer to use for complex output data + * @param size: Size of FFT as number of bins + * @param bits: World length of FFT. Currently only 32 is supported. + * @return Pointer to allocated FFT plan + * + * This function does the preparations to calculate FFT. If the size is power of two + * the operation is similar to mod_fft_plan_new(). Some other FFT sizes like 1536 is + * supported by allocated multiple FFT plans and by wrapping all needed for similar + * usage as power of two size FFT. + */ + +struct fft_multi_plan *mod_fft_multi_plan_new(struct processing_module *mod, void *inb, + void *outb, uint32_t size, int bits); +/** + * fft_multi_execute_32() - Calculate Fast Fourier Transform (FFT) for 2^size and other + * @param plan: Pointer to FFT plan created with mod_fft_multi_plan_new() + * @param ifft: Value 0 calculates FFT, value 1 calculates IFFT + * + * This function calculates the FFT with the buffers defined with mod_fft_multi_plan_new(). + */ +void fft_multi_execute_32(struct fft_multi_plan *plan, bool ifft); + +/** + * mod_fft_multi_plan_free() - Free the FFT plan + * @param mod: Pointer to module + * @param plan: Pointe to FFT plan + * + * This function frees the allocations done internally by the function mod_fft_multi_plan_new(). + * The input and output buffers need to be freed separately. + */ +void mod_fft_multi_plan_free(struct processing_module *mod, struct fft_multi_plan *plan); + +/** + * dft3_32() - Discrete Fourier Transform (DFT) for size 3. + * @param input: Pointer to complex values input array, Q1.31. + * @param output: Pointer to complex values output array, Q1.31, scaled down by 1/3. + * + * This function is useful for calculating some non power of two FFTs. E.g. the + * FFT for size 1536 is done with three 512 size FFTs and one 3 size DFT. + */ +void dft3_32(struct icomplex32 *input, struct icomplex32 *output); + +#endif /* __SOF_FFT_H__ */ diff --git a/src/include/sof/math/fir_config.h b/src/include/sof/math/fir_config.h new file mode 100644 index 000000000000..4818118253f6 --- /dev/null +++ b/src/include/sof/math/fir_config.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_EQ_FIR_FIR_CONFIG_H__ +#define __SOF_AUDIO_EQ_FIR_FIR_CONFIG_H__ + +/* Prevent xtensa gcc built firmware to be configured for longer + * filter that it can process. This length limitation (# of taps) is for one + * channel, for stereo the channel specific limit is this divided by two, + * etc. + */ +#ifndef __XCC__ +#ifdef __XTENSA__ +#define FIR_MAX_LENGTH_BUILD_SPECIFIC 80 +#endif +#endif + +#endif /* __SOF_AUDIO_EQ_FIR_FIR_CONFIG_H__ */ diff --git a/src/include/sof/math/fir_generic.h b/src/include/sof/math/fir_generic.h new file mode 100644 index 000000000000..79be1f575ff7 --- /dev/null +++ b/src/include/sof/math/fir_generic.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_MATH_FIR_GENERIC_H__ +#define __SOF_MATH_FIR_GENERIC_H__ + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(NONE, FILTER) + +#include <sof/audio/audio_stream.h> +#include <sof/audio/format.h> +#include <user/fir.h> +#include <stdint.h> + +struct comp_buffer; +struct sof_eq_fir_coef_data; + +struct fir_state_32x16 { + int rwi; /* Circular read and write index */ + int taps; /* Number of FIR taps */ + int length; /* Number of FIR taps plus input length (even) */ + int out_shift; /* Amount of right shifts at output */ + int16_t *coef; /* Pointer to FIR coefficients */ + int32_t *delay; /* Pointer to FIR delay line */ +}; + +void fir_reset(struct fir_state_32x16 *fir); + +int fir_delay_size(struct sof_fir_coef_data *config); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data); + +int32_t fir_32x16(struct fir_state_32x16 *fir, int32_t x); + +void fir_32x16_2x(struct fir_state_32x16 *fir, int32_t x0, int32_t x1, int32_t *y0, int32_t *y1); + +#endif +#endif /* __SOF_MATH_FIR_GENERIC_H__ */ diff --git a/src/include/sof/math/fir_hifi2ep.h b/src/include/sof/math/fir_hifi2ep.h new file mode 100644 index 000000000000..f3625104b3dc --- /dev/null +++ b/src/include/sof/math/fir_hifi2ep.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_MATH_FIR_HIFI2EP_H__ +#define __SOF_MATH_FIR_HIFI2EP_H__ + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(2, FILTER) + +#include <sof/audio/audio_stream.h> +#include <sof/audio/buffer.h> +#include <user/fir.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi2.h> +#include <stdint.h> + +struct comp_buffer; +struct sof_eq_fir_coef_data; + +struct fir_state_32x16 { + ae_p24x2f *rwp; /* Circular read and write pointer */ + ae_p24f *delay; /* Pointer to FIR delay line */ + ae_p24f *delay_end; /* Pointer to FIR delay line end */ + ae_p16x2s *coef; /* Pointer to FIR coefficients */ + int taps; /* Number of FIR taps */ + int length; /* Number of FIR taps plus input length (even) */ + int out_shift; /* Amount of right shifts at output */ +}; + +void fir_reset(struct fir_state_32x16 *fir); + +int fir_delay_size(struct sof_fir_coef_data *config); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data); + +/* Setup circular buffer for FIR input data delay */ +static inline void fir_hifiep_setup_circular(struct fir_state_32x16 *fir) +{ + AE_SETCBEGIN0(fir->delay); + AE_SETCEND0(fir->delay_end); +} + +void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, + int *rshift); + +void fir_32x16(struct fir_state_32x16 *fir, int32_t x, int32_t *y, int lshift, int rshift); + +void fir_32x16_2x(struct fir_state_32x16 *fir, int32_t x0, int32_t x1, + int32_t *y0, int32_t *y1, int lshift, int rshift); + +#endif +#endif /* __SOF_MATH_FIR_HIFI2EP_H__ */ diff --git a/src/include/sof/math/fir_hifi3.h b/src/include/sof/math/fir_hifi3.h new file mode 100644 index 000000000000..abcf46df5f6f --- /dev/null +++ b/src/include/sof/math/fir_hifi3.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_MATH_FIR_HIFI3_H__ +#define __SOF_MATH_FIR_HIFI3_H__ + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_MIN_HIFI(3, FILTER) + +#include <sof/audio/audio_stream.h> +#include <sof/audio/buffer.h> +#include <user/fir.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi3.h> + +struct sof_eq_fir_coef_data; + +struct fir_state_32x16 { + ae_int32 *rwp; /* Circular read and write pointer */ + ae_int32 *delay; /* Pointer to FIR delay line */ + ae_int32 *delay_end; /* Pointer to FIR delay line end */ + ae_f16x4 *coef; /* Pointer to FIR coefficients */ + int taps; /* Number of FIR taps */ + int length; /* Number of FIR taps plus input length (even) */ + int out_shift; /* Amount of right shifts at output */ +}; + +void fir_reset(struct fir_state_32x16 *fir); + +int fir_delay_size(struct sof_fir_coef_data *config); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data); + +/* Setup circular buffer for FIR input data delay */ +static inline void fir_core_setup_circular(struct fir_state_32x16 *fir) +{ + AE_SETCBEGIN0(fir->delay); + AE_SETCEND0(fir->delay_end); +} + +/* Setup circular for component buffer */ +static inline void fir_comp_setup_circular(const struct audio_stream *buffer) +{ + 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, int *rshift); + +void fir_32x16(struct fir_state_32x16 *fir, ae_int32 x, ae_int32 *y, int shift); + +void fir_32x16_2x(struct fir_state_32x16 *fir, ae_int32 x0, ae_int32 x1, + ae_int32 *y0, ae_int32 *y1, int shift); + +#endif +#endif /* __SOF_MATH_FIR_HIFI3_H__ */ diff --git a/src/include/sof/math/icomplex16.h b/src/include/sof/math/icomplex16.h new file mode 100644 index 000000000000..a2ade94660ba --- /dev/null +++ b/src/include/sof/math/icomplex16.h @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020-2026 Intel Corporation. +// +// Author: Amery Song <chao.song@intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/common.h> +#include <stdint.h> + +#ifndef __SOF_ICOMPLEX16_H__ +#define __SOF_ICOMPLEX16_H__ + +/* Note: the add of packed attribute to icmplex16 would significantly increase + * processing time of fft_execute_16() so it is not done. The optimized versions of + * FFT for HiFi will need a different packed data structure vs. generic C. + * + * TODO: Use with care with other than 16-bit FFT internals. Access with intrinsics + * will requires packed and aligned data. Currently there is no such usage in SOF. + */ + +/** + * struct icomplex16 - Storage for a normal complex number. + * @param real The real part in Q1.15 fractional format. + * @param imag The imaginary part in Q1.15 fractional format. + */ +struct icomplex16 { + int16_t real; + int16_t imag; +}; + +/* + * Helpers for 16 bit FFT calculation + */ +static inline void icomplex16_add(const struct icomplex16 *in1, const struct icomplex16 *in2, + struct icomplex16 *out) +{ + out->real = in1->real + in2->real; + out->imag = in1->imag + in2->imag; +} + +static inline void icomplex16_sub(const struct icomplex16 *in1, const struct icomplex16 *in2, + struct icomplex16 *out) +{ + out->real = in1->real - in2->real; + out->imag = in1->imag - in2->imag; +} + +static inline void icomplex16_mul(const struct icomplex16 *in1, const struct icomplex16 *in2, + struct icomplex16 *out) +{ + int32_t real = (int32_t)in1->real * in2->real - (int32_t)in1->imag * in2->imag; + int32_t imag = (int32_t)in1->real * in2->imag + (int32_t)in1->imag * in2->real; + + out->real = Q_SHIFT_RND(real, 30, 15); + out->imag = Q_SHIFT_RND(imag, 30, 15); +} + +/* complex conjugate */ +static inline void icomplex16_conj(struct icomplex16 *comp) +{ + comp->imag = sat_int16(-((int32_t)comp->imag)); +} + +/* shift a complex n bits, n > 0: left shift, n < 0: right shift */ +static inline void icomplex16_shift(const struct icomplex16 *input, int16_t n, + struct icomplex16 *output) +{ + int n1, n2; + + if (n >= 0) { + /* need saturation handling */ + output->real = sat_int16((int32_t)input->real << n); + output->imag = sat_int16((int32_t)input->imag << n); + } else { + n1 = -n; + n2 = 1 << (n1 - 1); + output->real = sat_int16(((int32_t)input->real + n2) >> n1); + output->imag = sat_int16(((int32_t)input->imag + n2) >> n1); + } +} + +#endif /* __SOF_ICOMPLEX16_H__ */ diff --git a/src/include/sof/math/icomplex32.h b/src/include/sof/math/icomplex32.h new file mode 100644 index 000000000000..29d22daadab8 --- /dev/null +++ b/src/include/sof/math/icomplex32.h @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020-2026 Intel Corporation. +// +// Author: Amery Song <chao.song@intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/log.h> +#include <sof/math/trig.h> +#include <sof/common.h> +#include <stdint.h> + +#ifndef __SOF_ICOMPLEX32_H__ +#define __SOF_ICOMPLEX32_H__ + +/** + * struct icomplex32 - Storage for a normal complex number. + * @param real The real part in Q1.31 fractional format. + * @param imag The imaginary part in Q1.31 fractional format. + */ +struct icomplex32 { + int32_t real; + int32_t imag; +}; + +/** + * struct ipolar32 - Storage for complex number in polar format. + * @param magnitude The length of vector in Q2.30 format. + * @param angle The phase angle of the vector -pi to +pi in Q3.29 format. + */ +struct ipolar32 { + int32_t magnitude; + int32_t angle; +}; + +/* + * These helpers are optimized for FFT calculation only. + * e.g. _add/sub() assume the output won't be saturate so no check needed, + * and _mul() assumes Q1.31 * Q1.31 so the output will be shifted to be Q1.31. + */ + +static inline void icomplex32_add(const struct icomplex32 *in1, const struct icomplex32 *in2, + struct icomplex32 *out) +{ + out->real = in1->real + in2->real; + out->imag = in1->imag + in2->imag; +} + +static inline void icomplex32_adds(const struct icomplex32 *in1, const struct icomplex32 *in2, + struct icomplex32 *out) +{ + out->real = sat_int32((int64_t)in1->real + in2->real); + out->imag = sat_int32((int64_t)in1->imag + in2->imag); +} + +static inline void icomplex32_sub(const struct icomplex32 *in1, const struct icomplex32 *in2, + struct icomplex32 *out) +{ + out->real = in1->real - in2->real; + out->imag = in1->imag - in2->imag; +} + +static inline void icomplex32_mul(const struct icomplex32 *in1, const struct icomplex32 *in2, + struct icomplex32 *out) +{ + out->real = ((int64_t)in1->real * in2->real - (int64_t)in1->imag * in2->imag) >> 31; + out->imag = ((int64_t)in1->real * in2->imag + (int64_t)in1->imag * in2->real) >> 31; +} + +/* complex conjugate */ +static inline void icomplex32_conj(struct icomplex32 *comp) +{ + comp->imag = SATP_INT32((int64_t)-1 * comp->imag); +} + +/* shift a complex n bits, n > 0: left shift, n < 0: right shift */ +static inline void icomplex32_shift(const struct icomplex32 *input, int32_t n, + struct icomplex32 *output) +{ + if (n > 0) { + /* need saturation handling */ + output->real = SATP_INT32(SATM_INT32((int64_t)input->real << n)); + output->imag = SATP_INT32(SATM_INT32((int64_t)input->imag << n)); + } else { + output->real = input->real >> -n; + output->imag = input->imag >> -n; + } +} + +/** + * sofm_icomplex32_to_polar() - Convert (re, im) complex number to polar. + * @param complex Pointer to input complex number in Q1.31 format. + * @param polar Pointer to output complex number in Q2.30 format for + * magnitude and Q3.29 for phase angle. + * + * The function can be used to convert data in-place with same address for + * input and output. It can be useful to save scratch memory. + */ +void sofm_icomplex32_to_polar(struct icomplex32 *complex, struct ipolar32 *polar); + +/** + * sofm_ipolar32_to_complex() - Convert complex number from polar to normal (re, im) format. + * @param polar Pointer to input complex number in polar format. + * @param complex Pointer to output complex number in normal format in Q1.31. + * + * This function can be used to convert data in-place with same address for input + * and output. It can be useful to save scratch memory. + */ +void sofm_ipolar32_to_complex(struct ipolar32 *polar, struct icomplex32 *complex); + +#endif /* __SOF_ICOMPLEX32_H__ */ diff --git a/src/include/sof/math/iir_df1.h b/src/include/sof/math/iir_df1.h new file mode 100644 index 000000000000..24653f690ea3 --- /dev/null +++ b/src/include/sof/math/iir_df1.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Andrula Song <andrula.song@intel.com> + */ + +#ifndef __SOF_MATH_IIR_DF1_H__ +#define __SOF_MATH_IIR_DF1_H__ + +#include <stddef.h> +#include <stdint.h> +#include <sof/common.h> + +#define IIR_DF1_NUM_STATE 4 +#define SOF_IIR_DF1_4TH_NUM_BIQUADS 2 + +struct iir_state_df1 { + unsigned int biquads; /* Number of IIR 2nd order sections total */ + unsigned int biquads_in_series; /* Number of IIR 2nd order sections + * in series. + */ + int32_t *coef; /* Pointer to IIR coefficients */ + int32_t *delay; /* Pointer to IIR delay line */ +}; + +struct sof_eq_iir_header; + +int iir_init_coef_df1(struct iir_state_df1 *iir, + struct sof_eq_iir_header *config); + +int iir_delay_size_df1(struct sof_eq_iir_header *config); + +void iir_init_delay_df1(struct iir_state_df1 *iir, int32_t **state); + +void iir_reset_df1(struct iir_state_df1 *iir); + +/** + * Calculate IIR filter consisting of biquads + * @param iir IIR state with configured biquad coefficients and delay lines data + * @param x Single s32 Q1.31 format input sample + * @return Single s32 Q1.31 format output samples + */ +int32_t iir_df1(struct iir_state_df1 *iir, int32_t x); + +/** + * Calculate IIR filter consisting of biquads, special simplified version for + * 4th order filter with two biquads in series. Note: There are no checks for + * iir struct members. + * @param iir IIR state with configured biquad coefficients and delay lines data + * @param x Single s32 Q1.31 format input sample + * @return Single s32 Q1.31 format output samples + */ +int32_t iir_df1_4th(struct iir_state_df1 *iir, int32_t x); + +/* Inline functions */ +#if SOF_USE_MIN_HIFI(3, FILTER) +#include "iir_df1_hifi3.h" +#else +#include "iir_df1_generic.h" +#endif + +#endif diff --git a/src/include/sof/math/iir_df1_generic.h b/src/include/sof/math/iir_df1_generic.h new file mode 100644 index 000000000000..aaf38286537a --- /dev/null +++ b/src/include/sof/math/iir_df1_generic.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Andrula Song <andrula.song@intel.com> + */ + +#ifndef __IIR_DF1_GENERIC_H__ +#define __IIR_DF1_GENERIC_H__ + +#include <stdint.h> + +static inline int16_t iir_df1_s16(struct iir_state_df1 *iir, int16_t x) +{ + return sat_int16(Q_SHIFT_RND(iir_df1(iir, ((int32_t)x) << 16), 31, 15)); +} + +static inline int32_t iir_df1_s24(struct iir_state_df1 *iir, int32_t x) +{ + return sat_int24(Q_SHIFT_RND(iir_df1(iir, x << 8), 31, 23)); +} + +static inline int16_t iir_df1_s32_s16(struct iir_state_df1 *iir, int32_t x) +{ + return sat_int16(Q_SHIFT_RND(iir_df1(iir, x), 31, 15)); +} + +static inline int32_t iir_df1_s32_s24(struct iir_state_df1 *iir, int32_t x) +{ + return sat_int24(Q_SHIFT_RND(iir_df1(iir, x), 31, 23)); +} + +#endif /* __IIR_DF1_GENERIC_H__ */ + diff --git a/src/include/sof/math/iir_df1_hifi3.h b/src/include/sof/math/iir_df1_hifi3.h new file mode 100644 index 000000000000..6188be94c00d --- /dev/null +++ b/src/include/sof/math/iir_df1_hifi3.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Andrula Song <andrula.song@intel.com> + */ + +#ifndef __IIR_DF1_HIFI3_H__ +#define __IIR_DF1_HIFI3_H__ + +#include <xtensa/tie/xt_hifi3.h> +#include <stdint.h> + +static inline int16_t iir_df1_s16(struct iir_state_df1 *iir, int16_t x) +{ + ae_f32x2 y = iir_df1(iir, ((int32_t)x) << 16); + + return AE_ROUND16X4F32SSYM(y, y); +} + +static inline int32_t iir_df1_s24(struct iir_state_df1 *iir, int32_t x) +{ + ae_f32x2 y = iir_df1(iir, x << 8); + + return AE_SRAI32(AE_SLAI32S(AE_SRAI32R(y, 8), 8), 8); +} + +static inline int16_t iir_df1_s32_s16(struct iir_state_df1 *iir, int32_t x) +{ + ae_f32x2 y = iir_df1(iir, x); + + return AE_ROUND16X4F32SSYM(y, y); +} + +static inline int32_t iir_df1_s32_s24(struct iir_state_df1 *iir, int32_t x) +{ + ae_f32x2 y = iir_df1(iir, x); + + return AE_SRAI32(AE_SLAI32S(AE_SRAI32R(y, 8), 8), 8); +} + +#endif /* __IIR_DF1_HIFI3_H__ */ + diff --git a/src/include/sof/math/iir_df2t.h b/src/include/sof/math/iir_df2t.h new file mode 100644 index 000000000000..bf342520cb03 --- /dev/null +++ b/src/include/sof/math/iir_df2t.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifndef __SOF_MATH_IIR_DF2T_H__ +#define __SOF_MATH_IIR_DF2T_H__ + +#include <stddef.h> +#include <stdint.h> +#include <sof/common.h> + +#define IIR_DF2T_NUM_DELAYS 2 + +struct iir_state_df2t { + unsigned int biquads; /* Number of IIR 2nd order sections total */ + unsigned int biquads_in_series; /* Number of IIR 2nd order sections + * in series. + */ + int32_t *coef; /* Pointer to IIR coefficients */ + int64_t *delay; /* Pointer to IIR delay line */ +}; + +struct sof_eq_iir_header; + +int iir_init_coef_df2t(struct iir_state_df2t *iir, + struct sof_eq_iir_header *config); + +int iir_delay_size_df2t(struct sof_eq_iir_header *config); + +void iir_init_delay_df2t(struct iir_state_df2t *iir, int64_t **delay); + +void iir_mute_df2t(struct iir_state_df2t *iir); + +void iir_unmute_df2t(struct iir_state_df2t *iir); + +void iir_reset_df2t(struct iir_state_df2t *iir); + +int32_t iir_df2t(struct iir_state_df2t *iir, int32_t x); + +/* Inline functions with or without HiFi3 intrinsics */ +#if SOF_USE_HIFI(3, FILTER) || SOF_USE_HIFI(4, FILTER) +#include "iir_df2t_hifi3.h" +#else +#include "iir_df2t_generic.h" +#endif + +#endif /* __SOF_MATH_IIR_DF2T_H__ */ diff --git a/src/include/sof/math/iir_df2t_generic.h b/src/include/sof/math/iir_df2t_generic.h new file mode 100644 index 000000000000..579e937edeb9 --- /dev/null +++ b/src/include/sof/math/iir_df2t_generic.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __IIR_DF2T_GENERIC_H__ +#define __IIR_DF2T_GENERIC_H__ + +#include <stdint.h> + +static inline int16_t iir_df2t_s16(struct iir_state_df2t *iir, int16_t x) +{ + return sat_int16(Q_SHIFT_RND(iir_df2t(iir, ((int32_t)x) << 16), 31, 15)); +} + +static inline int32_t iir_df2t_s24(struct iir_state_df2t *iir, int32_t x) +{ + return sat_int24(Q_SHIFT_RND(iir_df2t(iir, x << 8), 31, 23)); +} + +static inline int16_t iir_df2t_s32_s16(struct iir_state_df2t *iir, int32_t x) +{ + return sat_int16(Q_SHIFT_RND(iir_df2t(iir, x), 31, 15)); +} + +static inline int32_t iir_df2t_s32_s24(struct iir_state_df2t *iir, int32_t x) +{ + return sat_int24(Q_SHIFT_RND(iir_df2t(iir, x), 31, 23)); +} + +#endif /* __IIR_DF2T_GENERIC_H__ */ + diff --git a/src/include/sof/math/iir_df2t_hifi3.h b/src/include/sof/math/iir_df2t_hifi3.h new file mode 100644 index 000000000000..b2f4547bb7b9 --- /dev/null +++ b/src/include/sof/math/iir_df2t_hifi3.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __IIR_DF2T_HIFI3_H__ +#define __IIR_DF2T_HIFI3_H__ + +#include <xtensa/tie/xt_hifi3.h> +#include <stdint.h> + +static inline int16_t iir_df2t_s16(struct iir_state_df2t *iir, int16_t x) +{ + ae_f32x2 y = iir_df2t(iir, ((int32_t)x) << 16); + + return AE_ROUND16X4F32SSYM(y, y); +} + +static inline int32_t iir_df2t_s24(struct iir_state_df2t *iir, int32_t x) +{ + ae_f32x2 y = iir_df2t(iir, x << 8); + + return AE_SRAI32(AE_SLAI32S(AE_SRAI32R(y, 8), 8), 8); +} + +static inline int16_t iir_df2t_s32_s16(struct iir_state_df2t *iir, int32_t x) +{ + ae_f32x2 y = iir_df2t(iir, x); + + return AE_ROUND16X4F32SSYM(y, y); +} + +static inline int32_t iir_df2t_s32_s24(struct iir_state_df2t *iir, int32_t x) +{ + ae_f32x2 y = iir_df2t(iir, x); + + return AE_SRAI32(AE_SLAI32S(AE_SRAI32R(y, 8), 8), 8); +} + +#endif /* __IIR_DF2T_HIFI3_H__ */ + diff --git a/src/include/sof/math/log.h b/src/include/sof/math/log.h new file mode 100644 index 000000000000..78ab8ce64c3c --- /dev/null +++ b/src/include/sof/math/log.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * + */ + +#ifndef __SOF_MATH_BASE_LOGARITHM_H__ +#define __SOF_MATH_BASE_LOGARITHM_H__ + +#include <stdint.h> + +#define ONE_OVER_LOG2_10 2647887844335ULL /* 1/log2(10),Q1.43 */ +#define ONE_OVER_LOG2_E 6096987078286ULL /* 1/log2(exp(1)), Q1.43 */ +/* Function Declarations */ +int32_t base2_logarithm(uint32_t u); +uint32_t ln_int32(uint32_t numerator); +uint32_t log10_int32(uint32_t numerator); + +#endif diff --git a/src/include/sof/math/lut_trig.h b/src/include/sof/math/lut_trig.h new file mode 100644 index 000000000000..7cf8f48ab602 --- /dev/null +++ b/src/include/sof/math/lut_trig.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016-2023 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __SOF_MATH_LUT_TRIG_H__ +#define __SOF_MATH_LUT_TRIG_H__ + +#include <stdint.h> + +int16_t sofm_lut_sin_fixed_16b(int32_t w); /* Input is Q4.28, output is Q1.15 */ + +#endif /* __SOF_MATH_LUT_TRIG_H__ */ diff --git a/src/include/sof/math/matrix.h b/src/include/sof/math/matrix.h new file mode 100644 index 000000000000..f48f1ca4960d --- /dev/null +++ b/src/include/sof/math/matrix.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +/* Matrix calculation related functions */ + +#ifndef __SOF_MATH_MATRIX_H__ +#define __SOF_MATH_MATRIX_H__ + +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/alloc.h> +#include <ipc/topology.h> +#include <stdint.h> +#include <string.h> + +struct mat_matrix_16b { + int16_t rows; + int16_t columns; + int16_t fractions; + int16_t reserved; + int16_t data[]; +}; + +static inline void mat_init_16b(struct mat_matrix_16b *mat, int16_t rows, int16_t columns, + int16_t fractions) +{ + mat->rows = rows; + mat->columns = columns; + mat->fractions = fractions; +} + +static inline struct mat_matrix_16b *mat_matrix_alloc_16b(int16_t rows, int16_t columns, + int16_t fractions) +{ + struct mat_matrix_16b *mat; + const int mat_size = sizeof(int16_t) * rows * columns + sizeof(struct mat_matrix_16b); + + mat = rzalloc(SOF_MEM_FLAG_USER, mat_size); + if (mat) + mat_init_16b(mat, rows, columns, fractions); + + return mat; +} + +static inline struct mat_matrix_16b *mod_mat_matrix_alloc_16b(struct processing_module *mod, + int16_t rows, int16_t columns, + int16_t fractions) +{ + struct mat_matrix_16b *mat; + const int mat_size = sizeof(int16_t) * rows * columns + sizeof(struct mat_matrix_16b); + + mat = mod_zalloc(mod, mat_size); + if (mat) + mat_init_16b(mat, rows, columns, fractions); + + return mat; +} + +static inline void mat_copy_from_linear_16b(struct mat_matrix_16b *mat, const int16_t *lin_data) +{ + size_t bytes = sizeof(int16_t) * mat->rows * mat->columns; + + memcpy_s(mat->data, bytes, lin_data, bytes); +} + +static inline void mat_set_all_16b(struct mat_matrix_16b *mat, int16_t val) +{ + const int n = mat->rows * mat->columns; + int i; + + for (i = 0; i < n; i++) + mat->data[i] = val; +} + +static inline int16_t mat_get_scalar_16b(struct mat_matrix_16b *mat, int row, int col) +{ + return mat->data[col + row * mat->columns]; +} + +static inline void mat_set_scalar_16b(struct mat_matrix_16b *mat, int row, int col, int16_t val) +{ + mat->data[col + row * mat->columns] = val; +} + +static inline int16_t *mat_get_row_vector_16b(struct mat_matrix_16b *mat, int row) +{ + return mat->data + row * mat->columns; +} + +int mat_multiply(struct mat_matrix_16b *a, struct mat_matrix_16b *b, struct mat_matrix_16b *c); + +int mat_multiply_elementwise(struct mat_matrix_16b *a, struct mat_matrix_16b *b, + struct mat_matrix_16b *c); + +#endif /* __SOF_MATH_MATRIX_H__ */ diff --git a/src/include/sof/math/mu_law.h b/src/include/sof/math/mu_law.h new file mode 100644 index 000000000000..b8aaec5b5e3b --- /dev/null +++ b/src/include/sof/math/mu_law.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +#ifndef __SOF_MATH_MU_LAW_H__ +#define __SOF_MATH_MU_LAW_H__ + +#include <stdint.h> + +/** + * sofm_mu_law_encode() - Encode sample with mu-law coding + * @param sample: A s16 sample value + * + * The mu-law codec is defined in ITU-T G.711 standard and has been used + * in telecommunications in USA and Japan. The mu-law coding compresses + * 14 bit samples to 8 bit data stream. In SOF the high 14 bits of s16 + * format are used for compatibility with normal audios. + * + * @return: Compressed 8 bit code value + */ +uint8_t sofm_mu_law_encode(int16_t sample); + +/** + * sofm_mu_law_decode() - Decode mu-law encoded code word + * @param byte: Encoded code word + * + * The mu-law decoder expands a 8 bit code word into a 14 bit sample value. + * In the SOF the high 14 bits are aligned to the most significant bits + * to be compatible with normal s16 Q1.15 samples. + * + * @return: Sample value in s16 format + */ +int16_t sofm_mu_law_decode(int8_t byte); + +#endif /* __SOF_MATH_MU_LAW_H__ */ diff --git a/src/include/sof/math/numbers.h b/src/include/sof/math/numbers.h index 616c791f5d6c..80d4eba1a639 100644 --- a/src/include/sof/math/numbers.h +++ b/src/include/sof/math/numbers.h @@ -12,27 +12,35 @@ #include <stdint.h> -#define MIN(a, b) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - __a > __b ? __b : __a; \ -}) -#define MAX(a, b) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - __a < __b ? __b : __a; \ +#ifndef __ZEPHYR__ +/* Unsafe and portable macros for consistency with Zephyr. + * See SEI CERT-C PRE31-C + */ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) + +#define ROUND_DOWN(size, alignment) ({ \ + __typeof__(size) __size = (size); \ + __typeof__(alignment) __alignment = (alignment); \ + __size - (__size % __alignment); \ }) +#endif /* ! __ZEPHYR__ */ + #define ABS(a) ({ \ - typeof(a) __a = (a); \ + __typeof__(a) __a = (a); \ __a < 0 ? -__a : __a; \ }) #define SGN(a) ({ \ - typeof(a) __a = (a); \ + __typeof__(a) __a = (a); \ __a < 0 ? -1 : \ __a > 0 ? 1 : 0; \ }) +/* Zephyr added gcd() in 2025/Nov to sys/util.h */ +#ifndef gcd +#define USE_SOF_GCD 1 int gcd(int a, int b); /* Calculate greatest common divisor for a and b */ +#endif /* This is a divide function that returns ceil of the quotient. * E.g. ceil_divide(9, 3) returns 3, ceil_divide(10, 3) returns 4. @@ -50,12 +58,38 @@ static inline int ceil_divide(int a, int b) * If the signs are the same, we check if there was any remainder in * the division by multiplying the number back. */ - if (!((a ^ b) & (1 << ((sizeof(int) * 8) - 1))) && c * b != a) + if (!((a ^ b) & (1U << ((sizeof(int) * 8) - 1))) && c * b != a) c++; return c; } +/** + * \brief Cross product function + * + * Calculate cross product for vectors AB(a, b, c) and AC(d, e, f), where A, B, and C + * are points of a triangle in 3D space. Cross product is used in computational + * geometry. Cross product AB x AC is (b * f - c * e, c * d - a * f, a * e - b * d) + * + * \param[out] px x-axis component of cross product vector + * \param[out] py y-axis component of cross product vector + * \param[out] pz z-axis component of cross product vector + * \param[in] a x-axis component of vector AB + * \param[in] b y-axis component of vector AB + * \param[in] c z-axis component of vector AB + * \param[in] d x-axis component of vector AC + * \param[in] e y-axis component of vector AC + * \param[in] f z-axis component of vector AC + */ +static inline void cross_product_s16(int32_t *px, int32_t *py, int32_t *pz, + int16_t a, int16_t b, int16_t c, + int16_t d, int16_t e, int16_t f) +{ + *px = (int32_t)b * f - (int32_t)c * e; + *py = (int32_t)c * d - (int32_t)a * f; + *pz = (int32_t)a * e - (int32_t)b * d; +} + /* Find indices of equal values in a vector of integer values */ int find_equal_int16(int16_t idx[], int16_t vec[], int n, int vec_length, int max_results); @@ -81,4 +115,12 @@ uint32_t crc32(uint32_t base, const void *data, uint32_t bytes); #define merge_4b4b(high, low) (((uint8_t)(high) << 4) | \ ((low) & 0xF)) +/* Get max and min signed integer values for N bits word length */ +#define INT_MAX_FOR_NUMBER_OF_BITS(N) ((int64_t)((1ULL << ((N) - 1)) - 1)) +#define INT_MIN_FOR_NUMBER_OF_BITS(N) ((int64_t)(-((1ULL << ((N) - 1)) - 1) - 1)) + +/* Speed of sound (m/s) in 20 C temperature at standard atmospheric pressure */ +#define SPEED_OF_SOUND 343 +#define RECIPROCAL_SPEED_OF_SOUND_Q31 6260885 /* Q1.31 */ + #endif /* __SOF_MATH_NUMBERS_H__ */ diff --git a/src/include/sof/math/power.h b/src/include/sof/math/power.h new file mode 100644 index 000000000000..2444e3678ee4 --- /dev/null +++ b/src/include/sof/math/power.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * + */ +#ifndef __SOF_MATH_POWER_H__ +#define __SOF_MATH_POWER_H__ + +/* Include Files */ +#include <stdint.h> +/* Function Declarations */ +int32_t power_int32(int32_t b, int32_t e); + +#endif diff --git a/src/include/sof/math/sqrt.h b/src/include/sof/math/sqrt.h new file mode 100644 index 000000000000..3d8fd0df72fe --- /dev/null +++ b/src/include/sof/math/sqrt.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021-2026 Intel Corporation. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * + */ + +#ifndef __SOF_MATH_SQRT_H__ +#define __SOF_MATH_SQRT_H__ + +#include <stdint.h> + +/** + * sofm_sqrt_int16() - Calculate 16-bit fractional square root function. + * @param u Input value in Q4.12 format, from 0 to 16.0. + * @return Calculated square root of n in Q4.12 format, from 0 to 4.0. + */ +uint16_t sofm_sqrt_int16(uint16_t u); + +/** + * sofm_sqrt_int32() - Calculate 32-bit fractional square root function. + * @param n Input value in Q2.30 format, from 0 to 2.0. + * @return Calculated square root of n in Q2.30 format. + * + * The input range of square root function is matched with Q1.31 + * complex numbers range where the magnitude squared can be to 2.0. + * The function returns zero for non-positive input values. + */ +int32_t sofm_sqrt_int32(int32_t n); + +#endif /* __SOF_MATH_SQRT_H__ */ diff --git a/src/include/sof/math/trig.h b/src/include/sof/math/trig.h index ffa2f9b61a2c..67428cac494a 100644 --- a/src/include/sof/math/trig.h +++ b/src/include/sof/math/trig.h @@ -5,6 +5,7 @@ * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> * Liam Girdwood <liam.r.girdwood@linux.intel.com> * Keyon Jie <yang.jie@linux.intel.com> + * Shriram Shastry <malladi.sastry@linux.intel.com> */ #ifndef __SOF_MATH_TRIG_H__ @@ -12,10 +13,388 @@ #include <stdint.h> -#define PI_DIV2_Q4_28 421657428 -#define PI_Q4_28 843314857 -#define PI_MUL2_Q4_28 1686629713 +#define PI_Q4_28 843314857 /* int32(pi * 2^28) */ +#define PI_MUL2_Q4_28 1686629713 /* int32(2 * pi * 2^28) */ +#define PI_DIV2_Q3_29 843314857 /* int32(pi / 2 * 2^29) */ +#define PI_Q3_29 1686629713 /* int32(pi * 2^29) */ -int32_t sin_fixed(int32_t w); /* Input is Q4.28, output is Q1.31 */ +#define CORDIC_31B_TABLE_SIZE 31 +#define CORDIC_15B_TABLE_SIZE 15 +#define CORDIC_30B_ITABLE_SIZE 30 +#define CORDIC_16B_ITABLE_SIZE 16 +#define CORDIC_31B_ITERATIONS (CORDIC_31B_TABLE_SIZE - 1) +#define CORDIC_16B_ITERATIONS (CORDIC_16B_ITABLE_SIZE - 1) + +typedef enum { + EN_32B_CORDIC_SINE, + EN_32B_CORDIC_COSINE, + EN_32B_CORDIC_CEXP, + EN_16B_CORDIC_SINE, + EN_16B_CORDIC_COSINE, + EN_16B_CORDIC_CEXP, +} cordic_cfg; + +struct cordic_cmpx { + int32_t re; + int32_t im; +}; + +/** + * cordic_approx() - CORDIC-based approximation of sine and cosine + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @param a_idx Used LUT size. + * @param sign Output pointer to sine/cosine sign. + * @param b_yn Output pointer to sine value in Q2.30 format. + * @param xn Output pointer to cosine value in Q2.30 format. + * @param th_cdc_fxp Output pointer to the residual angle in Q2.30 format. + */ +void cordic_approx(int32_t th_rad_fxp, int32_t a_idx, int32_t *sign, int32_t *b_yn, int32_t *xn, + int32_t *th_cdc_fxp); + +/** + * is_scalar_cordic_acos() - CORDIC-based approximation for inverse cosine + * @param realvalue Input cosine value in Q2.30 format. + * @param numiters_minus_one Number of iterations minus one. + * @return Inverse cosine angle in Q3.29 format. + */ +int32_t is_scalar_cordic_acos(int32_t realvalue, int numiters_minus_one); + +/** + * is_scalar_cordic_asin() - CORDIC-based approximation for inverse sine + * @param realvalue Input sine value in Q2.30 format. + * @param numiters_minus_one Number of iterations minus one. + * @return Inverse sine angle in Q2.30 format. + */ +int32_t is_scalar_cordic_asin(int32_t realvalue, int numiters_minus_one); + +/** + * cmpx_cexp() - CORDIC-based approximation of complex exponential e^(j*THETA) + * @param sign Sine sign + * @param b_yn Sine value in Q2.30 format + * @param xn Cosine value in Q2.30 format + * @param type CORDIC type + * @param cexp Output pointer to complex result in struct cordic_cmpx + */ +void cmpx_cexp(int32_t sign, int32_t b_yn, int32_t xn, cordic_cfg type, struct cordic_cmpx *cexp); + +/** + * sin_fixed_32b() - Sine function using CORDIC algorithm + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @return Sine value in Q1.31 format. + * + * Compute fixed point cordicsine with table lookup and interpolation + * The cordic sine algorithm converges, when the angle is in the range + * [-pi/2, pi/2).If an angle is outside of this range, then a multiple of + * pi/2 is added or subtracted from the angle until it is within the range + * [-pi/2,pi/2).Start with the angle in the range [-2*pi, 2*pi) and output + * has range in [-1.0 to 1.0] + * +------------------+-----------------+--------+--------+ + * | thRadFxp | cdcsinth |thRadFxp|cdcsinth| + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 28 | 1 | 32 | 31 | 1 | 4.28 | 1.31 | + * +------------------+-----------------+--------+--------+ + */ +static inline int32_t sin_fixed_32b(int32_t th_rad_fxp) +{ + int32_t th_cdc_fxp; + int32_t sign; + int32_t b_yn; + int32_t xn; + cordic_approx(th_rad_fxp, CORDIC_31B_TABLE_SIZE, &sign, &b_yn, &xn, &th_cdc_fxp); + + th_cdc_fxp = sign * b_yn; + /*convert Q2.30 to Q1.31 format*/ + return sat_int32(Q_SHIFT_LEFT((int64_t)th_cdc_fxp, 30, 31)); +} + +/** + * cos_fixed_32b() - Cosine function using CORDIC algorithm + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @return Cosine value in Q1.31 format. + * + * Compute fixed point cordicsine with table lookup and interpolation + * The cordic cosine algorithm converges, when the angle is in the range + * [-pi/2, pi/2).If an angle is outside of this range, then a multiple of + * pi/2 is added or subtracted from the angle until it is within the range + * [-pi/2,pi/2).Start with the angle in the range [-2*pi, 2*pi) and output + * has range in [-1.0 to 1.0] + * +------------------+-----------------+--------+--------+ + * | thRadFxp | cdccosth |thRadFxp|cdccosth| + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 28 | 1 | 32 | 31 | 1 | 4.28 | 1.31 | + * +------------------+-----------------+--------+--------+ + */ +static inline int32_t cos_fixed_32b(int32_t th_rad_fxp) +{ + int32_t th_cdc_fxp; + int32_t sign; + int32_t b_yn; + int32_t xn; + cordic_approx(th_rad_fxp, CORDIC_31B_TABLE_SIZE, &sign, &b_yn, &xn, &th_cdc_fxp); + + th_cdc_fxp = sign * xn; + /*convert Q2.30 to Q1.31 format*/ + return sat_int32(Q_SHIFT_LEFT((int64_t)th_cdc_fxp, 30, 31)); +} + +/** + * sin_fixed_16b() - Sine function using CORDIC algorithm + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @return Sine value in Q1.15 format + * + * Compute fixed point cordic sine with table lookup and interpolation + * The cordic sine algorithm converges, when the angle is in the range + * [-pi/2, pi/2).If an angle is outside of this range, then a multiple of + * pi/2 is added or subtracted from the angle until it is within the range + * [-pi/2,pi/2).Start with the angle in the range [-2*pi, 2*pi) and output + * has range in [-1.0 to 1.0] + * +------------------+-----------------+--------+------------+ + * | thRadFxp | cdcsinth |thRadFxp| cdcsinth| + * +----+-----+-------+----+----+-------+--------+------------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat | + * +----+-----+-------+----+----+-------+--------+------------+ + * | 32 | 28 | 1 | 32 | 15 | 1 | 4.28 | 1.15 | + * +------------------+-----------------+--------+------------+ + */ +static inline int16_t sin_fixed_16b(int32_t th_rad_fxp) +{ + int32_t th_cdc_fxp; + int32_t sign; + int32_t b_yn; + int32_t xn; + + cordic_approx(th_rad_fxp, CORDIC_15B_TABLE_SIZE, &sign, &b_yn, &xn, &th_cdc_fxp); + + th_cdc_fxp = sign * b_yn; + /*convert Q2.30 to Q1.15 format*/ + return sat_int16(Q_SHIFT_RND(th_cdc_fxp, 30, 15)); +} + +/** + * cos_fixed_16b() - Cosine function using CORDIC algorithm + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @return Cosine value in Q1.15 format. + * + * Compute fixed point cordic cosine with table lookup and interpolation + * The cordic cos algorithm converges, when the angle is in the range + * [-pi/2, pi/2).If an angle is outside of this range, then a multiple of + * pi/2 is added or subtracted from the angle until it is within the range + * [-pi/2,pi/2).Start with the angle in the range [-2*pi, 2*pi) and output + * has range in [-1.0 to 1.0] + * +------------------+-----------------+--------+------------+ + * | thRadFxp | cdccosth |thRadFxp| cdccosth| + * +----+-----+-------+----+----+-------+--------+------------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat | + * +----+-----+-------+----+----+-------+--------+------------+ + * | 32 | 28 | 1 | 32 | 15 | 1 | 4.28 | 1.15 | + * +------------------+-----------------+--------+------------+ + */ +static inline int16_t cos_fixed_16b(int32_t th_rad_fxp) +{ + int32_t th_cdc_fxp; + int32_t sign; + int32_t b_yn; + int32_t xn; + + cordic_approx(th_rad_fxp, CORDIC_15B_TABLE_SIZE, &sign, &b_yn, &xn, &th_cdc_fxp); + + th_cdc_fxp = sign * xn; + /*convert Q2.30 to Q1.15 format*/ + return sat_int16(Q_SHIFT_RND(th_cdc_fxp, 30, 15)); +} + +/** + * cmpx_exp_32b() - CORDIC-based approximation of complex exponential e^(j*THETA). + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @param cexp Output pointer to complex result in struct cordic_cmpx in Q2.30 format. + * + * computes COS(THETA) + j*SIN(THETA) using CORDIC algorithm + * approximation and returns the complex result. + * THETA values must be in the range [-2*pi, 2*pi). The cordic + * exponential algorithm converges, when the angle is in the + * range [-pi/2, pi/2).If an angle is outside of this range, + * then a multiple of pi/2 is added or subtracted from the + * angle until it is within the range [-pi/2,pi/2).Start + * with the angle in the range [-2*pi, 2*pi) and output has + * range in [-1.0 to 1.0] + * Error (max = 0.000000015832484), THD+N = -167.082852232808847 + * +------------------+-----------------+--------+------------+ + * | thRadFxp |cdccexpth |thRadFxp| cdccexpth| + * +----+-----+-------+----+----+-------+--------+------------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat | + * +----+-----+-------+----+----+-------+--------+------------+ + * | 32 | 28 | 1 | 32 | 15 | 1 | 4.28 | 2.30 | + * +------------------+-----------------+--------+------------+ + */ +static inline void cmpx_exp_32b(int32_t th_rad_fxp, struct cordic_cmpx *cexp) +{ + int32_t th_cdc_fxp; + int32_t sign; + int32_t b_yn; + int32_t xn; + + cordic_approx(th_rad_fxp, CORDIC_31B_TABLE_SIZE, &sign, &b_yn, &xn, &th_cdc_fxp); + cmpx_cexp(sign, b_yn, xn, EN_32B_CORDIC_CEXP, cexp); + /* return the complex(re & im) result in Q2.30*/ +} + +/** + * cmpx_exp_16b() - CORDIC-based approximation of complex exponential e^(j*THETA). + * @param th_rad_fxp Input angle in radian Q4.28 format. + * @param cexp Output pointer to complex result in struct cordic_cmpx in Q1.15 format. + * + * computes COS(THETA) + j*SIN(THETA) using CORDIC algorithm + * approximation and returns the complex result. + * THETA values must be in the range [-2*pi, 2*pi). The cordic + * exponential algorithm converges, when the angle is in the + * range [-pi/2, pi/2).If an angle is outside of this range, + * then a multiple of pi/2 is added or subtracted from the + * angle until it is within the range [-pi/2,pi/2).Start + * with the angle in the range [-2*pi, 2*pi) and output has + * range in [-1.0 to 1.0] + * Error (max = 0.000060862861574), THD+N = -89.049303454077403 + * +------------------+-----------------+--------+------------+ + * | thRadFxp |cdccexpth |thRadFxp| cdccexpth| + * +----+-----+-------+----+----+-------+--------+------------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat | + * +----+-----+-------+----+----+-------+--------+------------+ + * | 32 | 28 | 1 | 32 | 15 | 1 | 4.28 | 1.15 | + * +------------------+-----------------+--------+------------+ + */ +static inline void cmpx_exp_16b(int32_t th_rad_fxp, struct cordic_cmpx *cexp) +{ + int32_t th_cdc_fxp; + int32_t sign; + int32_t b_yn; + int32_t xn; + + /* compute coeff from angles */ + cordic_approx(th_rad_fxp, CORDIC_15B_TABLE_SIZE, &sign, &b_yn, &xn, &th_cdc_fxp); + cmpx_cexp(sign, b_yn, xn, EN_16B_CORDIC_CEXP, cexp); + /* return the complex(re & im) result in Q1.15*/ +} + +/** + * asin_fixed_32b() - CORDIC-based approximation of inverse sine + * @param cdc_asin_th Input value in Q2.30 format. + * @return Inverse sine angle in Q2.30 format. + * + * inverse sine of cdc_asin_theta based on a CORDIC approximation. + * asin(cdc_asin_th) inverse sine angle values in radian produces using the DCORDIC + * (Double CORDIC) algorithm. + * Inverse sine angle values in rad + * Q2.30 cdc_asin_th, value in between range of [-1 to 1] + * Q2.30 th_asin_fxp, output value range [-1.5707963258028 to 1.5707963258028] + * LUT size set type 15 + * Error (max = 0.000000027939677), THD+N = -157.454534077921551 (dBc) + */ +static inline int32_t asin_fixed_32b(int32_t cdc_asin_th) +{ + int32_t th_asin_fxp; + + if (cdc_asin_th >= 0) + th_asin_fxp = is_scalar_cordic_asin(cdc_asin_th, CORDIC_31B_ITERATIONS); + else + th_asin_fxp = -is_scalar_cordic_asin(-cdc_asin_th, CORDIC_31B_ITERATIONS); + + return th_asin_fxp; /* Q2.30 */ +} + +/** + * acos_fixed_32b() - CORDIC-based approximation of inverse cosine + * @param cdc_acos_th Input value in Q2.30 format. + * @return Inverse cosine angle in Q3.29 format. + * + * inverse cosine of cdc_acos_theta based on a CORDIC approximation + * acos(cdc_acos_th) inverse cosine angle values in radian produces using the DCORDIC + * (Double CORDIC) algorithm. + * Q2.30 cdc_acos_th , input value range [-1 to 1] + * Q3.29 th_acos_fxp, output value range [3.14159265346825 to 0] + * LUT size set type 31 + * Error (max = 0.000000026077032), THD+N = -157.948952635422842 (dBc) + */ +static inline int32_t acos_fixed_32b(int32_t cdc_acos_th) +{ + int32_t th_acos_fxp; + + if (cdc_acos_th >= 0) + th_acos_fxp = is_scalar_cordic_acos(cdc_acos_th, CORDIC_31B_ITERATIONS); + else + th_acos_fxp = PI_Q3_29 - is_scalar_cordic_acos(-cdc_acos_th, CORDIC_31B_ITERATIONS); + + return th_acos_fxp; /* Q3.29 */ +} + +/** + * asin_fixed_16b() - CORDIC-based approximation of inverse sine + * @param cdc_asin_th Input value in Q2.30 format. + * @return Inverse sine angle in Q2.14 format. + * + * inverse sine of cdc_asin_theta based on a CORDIC approximation. + * asin(cdc_asin_th) inverse sine angle values in radian produces using the DCORDIC + * (Double CORDIC) algorithm. + * Inverse sine angle values in rad + * Q2.30 cdc_asin_th, value in between range of [-1 to 1] + * Q2.14 th_asin_fxp, output value range [-1.5707963258028 to 1.5707963258028] + * LUT size set type 31 + * number of iteration 15 + * Error (max = 0.000059800222516), THD+N = -89.824282520774048 (dBc) + */ +static inline int16_t asin_fixed_16b(int32_t cdc_asin_th) +{ + int32_t th_asin_fxp; + + if (cdc_asin_th >= 0) + th_asin_fxp = is_scalar_cordic_asin(cdc_asin_th, CORDIC_16B_ITERATIONS); + else + th_asin_fxp = -is_scalar_cordic_asin(-cdc_asin_th, CORDIC_16B_ITERATIONS); + /*convert Q2.30 to Q2.14 format*/ + return sat_int16(Q_SHIFT_RND(th_asin_fxp, 30, 14)); +} + +/** + * acos_fixed_16b() - CORDIC-based approximation of inverse cosine + * @param cdc_acos_th Input value in Q2.30 format. + * @return Inverse cosine angle in Q3.13 format. + * + * inverse cosine of cdc_acos_theta based on a CORDIC approximation + * acos(cdc_acos_th) inverse cosine angle values in radian produces using the DCORDIC + * (Double CORDIC) algorithm. + * Q2.30 cdc_acos_th , input value range [-1 to 1] + * Q3.13 th_acos_fxp, output value range [3.14159265346825 to 0] + * LUT size set type 31 + * number of iteration 15 + * Error (max = 0.000059799232976), THD+N = -89.824298401466635 (dBc) + */ +static inline int16_t acos_fixed_16b(int32_t cdc_acos_th) +{ + int32_t th_acos_fxp; + + if (cdc_acos_th >= 0) + th_acos_fxp = is_scalar_cordic_acos(cdc_acos_th, CORDIC_16B_ITERATIONS); + else + th_acos_fxp = PI_Q3_29 - is_scalar_cordic_acos(-cdc_acos_th, CORDIC_16B_ITERATIONS); + + /*convert Q3.29 to Q3.13 format*/ + return sat_int16(Q_SHIFT_RND(th_acos_fxp, 29, 13)); +} + +/** + * sofm_atan2_32b() - Four-quadrant arctangent using degree-9 Remez minimax polynomial + * @param y Imaginary component (sine) in Q1.31 format. + * @param x Real component (cosine) in Q1.31 format. + * @return Angle in Q3.29 radians, range [-pi, +pi]. + * + * Uses the Horner-form polynomial: + * atan(z) = z * (C0 + z^2 * (C1 + z^2 * (C2 + z^2 * (C3 + z^2 * C4)))) + * + * with Remez minimax coefficients on [0, 1]. + * Maximum error ~0.001 degrees (1.94e-5 radians). + */ +int32_t sofm_atan2_32b(int32_t y, int32_t x); #endif /* __SOF_MATH_TRIG_H__ */ diff --git a/src/include/sof/math/window.h b/src/include/sof/math/window.h new file mode 100644 index 000000000000..d72d00b3bd87 --- /dev/null +++ b/src/include/sof/math/window.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2025 Intel Corporation. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +/* Window functions related functions */ + +#ifndef __SOF_MATH_WINDOW_H__ +#define __SOF_MATH_WINDOW_H__ + +#include <sof/audio/format.h> +#include <stdint.h> + +#define WIN_BLACKMAN_A0_Q15 Q_CONVERT_FLOAT(7938.0 / 18608.0, 15) /* For "exact" blackman 16bit */ +#define WIN_BLACKMAN_A0_Q31 Q_CONVERT_FLOAT(7938.0 / 18608.0, 31) /* For "exact" blackman 32bit */ + +/** + * Returns a rectangular window with 16 bits, simply a values of ones vector + * @param win Pointer to output vector with Q1.15 coefficients + * @param length Length of coefficients vector + */ +void win_rectangular_16b(int16_t win[], int length); + +/** + * Returns a rectangular window with 32 bits, simply a values of ones vector + * @param win Pointer to output vector with Q1.31 coefficients + * @param length Length of coefficients vector + */ +void win_rectangular_32b(int32_t win[], int length); + +/** + * Calculates a Blackman window function with 16 bits, reference + * https://en.wikipedia.org/wiki/Window_function#Blackman_window + * + * @param win Pointer to output vector with Q1.15 coefficients + * @param length Length of coefficients vector + * @param a0 Parameter for window shape, use e.g. 0.42 as Q1.15 + */ +void win_blackman_16b(int16_t win[], int length, int16_t a0); + +/** + * Calculates a Blackman window function with 32 bits, reference + * https://en.wikipedia.org/wiki/Window_function#Blackman_window + * + * @param win Pointer to output vector with Q1.31 coefficients + * @param length Length of coefficients vector + * @param a0 Parameter for window shape, use e.g. 0.42 as Q1.31 + */ +void win_blackman_32b(int32_t win[], int length, int32_t a0); + +/** + * Calculates a Hann window function with 16 bits, reference + * https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows + * + * @param win Pointer to output vector with Q1.15 coefficients + * @param length Length of coefficients vector + */ +void win_hann_16b(int16_t win[], int length); + +/** + * Calculates a Hann window function with 32 bits, reference + * https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows + * + * @param win Pointer to output vector with Q1.31 coefficients + * @param length Length of coefficients vector + */ +void win_hann_32b(int32_t win[], int length); + +/** + * Calculates a Hamming window function with 16 bits, reference + * https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows + * + * @param win Pointer to output vector with Q1.15 coefficients + * @param length Length of coefficients vector + */ +void win_hamming_16b(int16_t win[], int length); + +/** + * Calculates a Hamming window function with 32 bits, reference + * https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows + * + * @param win Pointer to output vector with Q1.31 coefficients + * @param length Length of coefficients vector + */ +void win_hamming_32b(int32_t win[], int length); + +/** + * Calculates a Povey window function with 16 bits. It's a window function + * used in Pytorch and Kaldi. + * + * @param win Output vector with coefficients + * @param length Length of coefficients vector + */ +void win_povey_16b(int16_t win[], int length); + +#endif /* __SOF_MATH_WINDOW_H__ */ diff --git a/src/include/sof/objpool.h b/src/include/sof/objpool.h new file mode 100644 index 000000000000..0821fec8786b --- /dev/null +++ b/src/include/sof/objpool.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +#ifndef __ZEPHYR_OBJPOOL_H__ +#define __ZEPHYR_OBJPOOL_H__ + +#include <sof/list.h> + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +struct vregion; +struct k_heap; +struct objpool_head { + struct list_item list; + struct vregion *vreg; + struct k_heap *heap; + uint32_t flags; +}; + +/** + * Allocate memory tracked as part of an object pool. + * + * @param head Pointer to the object pool head. + * @param size Size in bytes of memory blocks to allocate. + * @param flags Memory allocation flags. + * + * @return a pointer to the allocated memory on success, NULL on failure. + * + * Allocate a memory block of @a size bytes. @a size is used upon the first + * invocation to allocate memory on the heap, all consequent allocations with + * the same @a head must use the same @a size value. First allocation with an + * empty @a head allocates 2 blocks. After both blocks are taken and a third one + * is requested, the next call allocates 4 blocks, then 8, 16 and 32. After that + * 32 blocks are allocated every time. Note, that by design allocated blocks are + * never freed. See more below. + * TODO: @a flags are currently only used when allocating new object sets. + * Should add a check that they're consistent with already allocated objects. + */ +void *objpool_alloc(struct objpool_head *head, size_t size, uint32_t flags); + +/** + * Return a block to the object pool + * + * @param head Pointer to the object pool head. + * @param data Pointer to the object to return (can be NULL) + * + * @return 0 on success or a negative error code. + * + * Return a block to the object pool. Memory is never freed by design, unused + * blocks are kept in the object pool for future re-use. + */ +int objpool_free(struct objpool_head *head, void *data); + +/** + * Free all of the object pool memory + * + * @param head Pointer to the object pool head. + */ +void objpool_prune(struct objpool_head *head); + +/* returns true to stop */ +typedef bool (*objpool_iterate_cb)(void *data, void *arg); + +/** + * Iterate over object pool entries until stopped + * + * @param head Pointer to the object pool head. + * @param cb Callback function + * @param arg Callback function argument + * + * @return 0 on success or a negative error code. + * + * Call the callback function for each entry in the pool, until it returns true. + * If the callback never returns true, return an error. + */ +int objpool_iterate(struct objpool_head *head, objpool_iterate_cb cb, void *arg); + +#endif diff --git a/src/include/sof/platform.h b/src/include/sof/platform.h index dfb7b054bdd0..80fdff077500 100644 --- a/src/include/sof/platform.h +++ b/src/include/sof/platform.h @@ -45,6 +45,13 @@ int platform_boot_complete(uint32_t boot_message); */ int platform_init(struct sof *sof); +/** + * \brief Platform specific context saving routine, called during DSP suspending. + * \param[in] sof Context. + * \return 0 if successful, error code otherwise. + */ +int platform_context_save(struct sof *sof); + /** @}*/ #endif diff --git a/src/include/sof/probe/probe.h b/src/include/sof/probe/probe.h index 21e6bc449f23..de8873ad0a67 100644 --- a/src/include/sof/probe/probe.h +++ b/src/include/sof/probe/probe.h @@ -8,11 +8,26 @@ #ifndef __SOF_PROBE_PROBE_H__ #define __SOF_PROBE_PROBE_H__ -#include <config.h> +#include <ipc/probe.h> +#include <sys/types.h> -#if CONFIG_PROBE +/** + * A buffer of logging data is available for processing. + */ +typedef ssize_t(*probe_logging_hook_t)(uint8_t *buffer, size_t length); -#include <ipc/probe.h> +#if CONFIG_LOG_BACKEND_SOF_PROBE +const struct log_backend *log_backend_probe_get(void); +bool probe_is_backend_configured(void); +#endif + +/** + * @brief Initialize the probe logging backend. + * + * @param hook Function is called when new logging data is written + * out by the logger. + */ +void probe_logging_init(probe_logging_hook_t hook); /* * \brief Initialize probes subsystem @@ -21,7 +36,7 @@ * In case extraction_probe_dma is NULL, extraction probes * are unavailable. */ -int probe_init(struct probe_dma *extraction_probe_dma); +int probe_init(const struct probe_dma *extraction_probe_dma); /* * \brief Deinitialize probes subsystem. @@ -37,7 +52,7 @@ int probe_deinit(void); * param[in] count - number of DMAs configured during this call * param[in] probe_dma - Array of size 'count' with configuration data for DMAs */ -int probe_dma_add(uint32_t count, struct probe_dma *probe_dma); +int probe_dma_add(uint32_t count, const struct probe_dma *probe_dma); /* * \brief Get info about connected injection DMAs @@ -54,7 +69,7 @@ int probe_dma_info(struct sof_ipc_probe_info_params *data, uint32_t max_size); * param[in] stream_tag - array for size 'count' with stream tags associated * with DMAs to be removed */ -int probe_dma_remove(uint32_t count, uint32_t *stream_tag); +int probe_dma_remove(uint32_t count, const uint32_t *stream_tag); /* * \brief Set probe points @@ -62,7 +77,7 @@ int probe_dma_remove(uint32_t count, uint32_t *stream_tag); * param[in] count - number of probe points configured this call * param[in] probe - array of size 'count' with configuration of probe points */ -int probe_point_add(uint32_t count, struct probe_point *probe); +int probe_point_add(uint32_t count, const struct probe_point *probe); /* * \brief Get info about connected probe points @@ -79,7 +94,7 @@ int probe_point_info(struct sof_ipc_probe_info_params *data, uint32_t max_size); * param[in] buffer_id - array of size 'count' with IDs of buffers to which * probes were attached */ -int probe_point_remove(uint32_t count, uint32_t *buffer_id); +int probe_point_remove(uint32_t count, const uint32_t *buffer_id); /** * \brief Retrieves probes structure. @@ -90,6 +105,4 @@ static inline struct probe_pdata *probe_get(void) return sof_get()->probe; } -#endif /* CONFIG_PROBE */ - #endif /* __SOF_PROBE_PROBE_H__ */ diff --git a/src/include/sof/samples/audio/detect_test.h b/src/include/sof/samples/audio/detect_test.h new file mode 100644 index 000000000000..7c78c35dcc69 --- /dev/null +++ b/src/include/sof/samples/audio/detect_test.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + */ + +#ifndef __USER_DETECT_TEST_H__ +#define __USER_DETECT_TEST_H__ + +#include <stdint.h> + +/** IPC blob types */ +#define SOF_DETECT_TEST_CONFIG 0 +#define SOF_DETECT_TEST_MODEL 1 + +struct sof_detect_test_config { + uint32_t size; + + /** synthetic system load settings */ + uint32_t load_mips; + uint32_t load_memory_size; + /** time in ms after which detection is activated */ + uint32_t preamble_time; + + /** activation right shift, determines the speed of activation */ + uint16_t activation_shift; + + /** sample width in bits - ignored with IPC4 */ + int16_t sample_width; + + /** activation threshold */ + int32_t activation_threshold; + + /** default draining size in bytes */ + uint32_t drain_req; + + /** reserved for future use */ + uint32_t reserved[1]; +} __packed; + +uint16_t test_keyword_get_sample_valid_bytes(struct comp_dev *dev); + +uint32_t test_keyword_get_detected(struct comp_dev *dev); +void test_keyword_set_detected(struct comp_dev *dev, uint32_t detected); + +#if CONFIG_KWD_NN_SAMPLE_KEYPHRASE +const int16_t *test_keyword_get_input(struct comp_dev *dev); + +int16_t test_keyword_get_input_byte(struct comp_dev *dev, uint32_t index); +int16_t test_keyword_get_input_elem(struct comp_dev *dev, uint32_t index); +int test_keyword_set_input_elem(struct comp_dev *dev, uint32_t index, int16_t val); + +size_t test_keyword_get_input_size(struct comp_dev *dev); +void test_keyword_set_input_size(struct comp_dev *dev, size_t input_size); +#endif + +uint32_t test_keyword_get_drain_req(struct comp_dev *dev); +void test_keyword_set_drain_req(struct comp_dev *dev, uint32_t drain_req); + +void detect_test_notify(const struct comp_dev *dev); + +/** used for binary blob size sanity checks */ +#define SOF_DETECT_TEST_MAX_CFG_SIZE sizeof(struct sof_detect_test_config) + +#endif /* __USER_DETECT_TEST_H__ */ diff --git a/src/include/sof/samples/audio/kwd_nn/kwd_nn_config.h b/src/include/sof/samples/audio/kwd_nn/kwd_nn_config.h new file mode 100644 index 000000000000..b400a378ca38 --- /dev/null +++ b/src/include/sof/samples/audio/kwd_nn/kwd_nn_config.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Mihai Despotovici <mihai.despotovici@nxp.com> + */ + +#ifndef __KWD_NN_CONFIG_H__ +#define __KWD_NN_CONFIG_H__ + +/* RAW AUDIO DATA CONFIGURATION */ +#define KWD_NN_MS_TO_SAMPLES(samplerate, time) ((samplerate) * (time) / 1000) +#define KWD_NN_SIZE_FROM_STRIDE_SIZE(stride, size, no_windows) \ + (((no_windows) - 1) * (stride) + (size)) + +#define KWD_NN_CONFIG_SAMPLERATE 16000 +#define KWD_NN_CONFIG_NO_CHANNELS 1 + +#define KWD_NN_CONFIG_WINDOW_STRIDE KWD_NN_MS_TO_SAMPLES(KWD_NN_CONFIG_SAMPLERATE, 20) +#define KWD_NN_CONFIG_WINDOW_SIZE KWD_NN_MS_TO_SAMPLES(KWD_NN_CONFIG_SAMPLERATE, 30) +#define KWD_NN_CONFIG_NO_WINDOWS 49 + +#define KWD_NN_CONFIG_RAW_SIZE (KWD_NN_CONFIG_NO_CHANNELS * \ + KWD_NN_SIZE_FROM_STRIDE_SIZE( \ + KWD_NN_CONFIG_WINDOW_STRIDE, \ + KWD_NN_CONFIG_WINDOW_SIZE, \ + KWD_NN_CONFIG_NO_WINDOWS)) + +/* PREPROCESSED DATA CONFIGURATION */ +#define KWD_NN_CONFIG_PREPROCESSED_HEIGHT KWD_NN_CONFIG_NO_WINDOWS +#define KWD_NN_CONFIG_SPECTROGRAM_SIZE 256 +#define KWD_NN_CONFIG_PREPROCESSED_AVGPOOL_WIDTH 6 +#define KWD_NN_CONFIG_PREPROCESSED_WIDTH 43 +#define KWD_NN_CONFIG_PREPROCESSED_SIZE (KWD_NN_CONFIG_PREPROCESSED_HEIGHT * \ + KWD_NN_CONFIG_PREPROCESSED_WIDTH) + +/* NN can report one of the following 4 answers + * after applying inference: YES, NO, UNKNOWN or + * SILENCE. The function computes confidence + * value for each possible answer + */ +#define KWD_NN_CONFIDENCES_SIZE 4 + +/* if confidence of the NN result is lower than + * this threshold, the probability to be a + * false-positive is high + */ +#define KWD_NN_MIN_ACCEPTABLE_CONFIDENCE 128 + +#endif /* __KWD_NN_CONFIG_H__ */ diff --git a/src/include/sof/samples/audio/kwd_nn/kwd_nn_preprocess.h b/src/include/sof/samples/audio/kwd_nn/kwd_nn_preprocess.h new file mode 100644 index 000000000000..098e2b8650e4 --- /dev/null +++ b/src/include/sof/samples/audio/kwd_nn/kwd_nn_preprocess.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Mihai Despotovici <mihai.despotovici@nxp.com> + */ + +#ifndef __KWD_NN_PREPROCESS_H__ +#define __KWD_NN_PREPROCESS_H__ + +#include <stdint.h> + +int kwd_nn_preprocess(const int16_t *input, uint8_t *output); + +void kwd_nn_preprocess_1s(const int16_t *raw_data, uint8_t *preprocessed_data); + +#endif /* __KWD_NN_PREPROCESS_H__ */ diff --git a/src/include/sof/samples/audio/kwd_nn/kwd_nn_process.h b/src/include/sof/samples/audio/kwd_nn/kwd_nn_process.h new file mode 100644 index 000000000000..9033171a8a05 --- /dev/null +++ b/src/include/sof/samples/audio/kwd_nn/kwd_nn_process.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Mihai Despotovici <mihai.despotovici@nxp.com> + */ + +#ifndef __KWD_NN_PROCESS_H__ +#define __KWD_NN_PROCESS_H__ + +#include "kwd_nn_config.h" + +void kwd_nn_process_data + (uint8_t preprocessed_data[KWD_NN_CONFIG_PREPROCESSED_SIZE], + uint8_t confidences[KWD_NN_CONFIDENCES_SIZE]); + +#endif /* __KWD_NN_PROCESS_H__ */ diff --git a/src/include/sof/samples/audio/kwd_nn_detect_test.h b/src/include/sof/samples/audio/kwd_nn_detect_test.h new file mode 100644 index 000000000000..e856e0866511 --- /dev/null +++ b/src/include/sof/samples/audio/kwd_nn_detect_test.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Cristina Feies <cristina.ilie@nxp.com> + * Author: Viorel Suman <viorel.suman@nxp.com> + */ + +#ifndef __USER_KWD_NN_DETECT_TEST_H__ +#define __USER_KWD_NN_DETECT_TEST_H__ + +#include "kwd_nn/kwd_nn_config.h" +#include <sof/audio/component.h> + +#define KWD_NN_SILENCE 0 +#define KWD_NN_UNKNOWN 1 +#define KWD_NN_YES_KEYWORD 2 +#define KWD_NN_NO_KEYWORD 3 + +/* 990 ms of data considering frame rate 16KHz */ +#define KWD_NN_KEY_LEN (990 * 16 * 1) +#define KWD_NN_NUM_OF_CHANNELS 1 +/* ~2 seconds of samples */ +#define KWD_NN_IN_BUFF_SIZE (2 * KWD_NN_KEY_LEN * KWD_NN_NUM_OF_CHANNELS) + +int kwd_nn_postprocess(uint8_t confidences[KWD_NN_CONFIDENCES_SIZE]); +void kwd_nn_detect_test(struct comp_dev *dev, + const struct audio_stream *source, + uint32_t frames); + +#endif /* __USER_KWD_NN_DETECT_TEST_H__ */ diff --git a/src/include/sof/samples/audio/smart_amp_test.h b/src/include/sof/samples/audio/smart_amp_test.h new file mode 100644 index 000000000000..3feda5005125 --- /dev/null +++ b/src/include/sof/samples/audio/smart_amp_test.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> + */ + +#ifndef __SOF_AUDIO_SMART_AMP_H__ +#define __SOF_AUDIO_SMART_AMP_H__ + +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> + +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/base-config.h> + +#define SOF_SMART_AMP_FEEDBACK_QUEUE_ID 1 +#endif + +#define SMART_AMP_MAX_STREAM_CHAN 8 + +/** IPC blob types */ +#define SOF_SMART_AMP_CONFIG 0 +#define SOF_SMART_AMP_MODEL 1 + +struct smart_amp_model_data { + uint32_t data_size; + void *data; + uint32_t crc; + uint32_t data_pos; +}; + +/* 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 + * channel. Value -1 means that for this output channel we will not take any + * channel from specific input. + * + * E.g. assuming that a smart amplifier input stream is configured + * with channels parameter set to 2, feedback stream with channels set to 8 + * and smart amplifier output stream with channels set to 4 (smart amplifier + * converts stream from 2 to 4 channels) and source/feedback_ch_map's are as + * follows: + * + * source_ch_map = [0, 1, -1, -1, -1 ,-1 ,-1, -1] + * feedback_ch_map = [-1, -1, 0, 1, -1, -1, -1, -1] + * + * As a result smart amplifier test component will procces source and feedback + * streams in following way: + * + * + * + * PLAYBACK + * STREAM +---+ + * | 0 +------------+ + * +---+ | SMART AMPLIFIER + * | 1 +---------+ | OUTPUT + * +---+ | | +---+ + * | +-->+ 0 | + * | +---+ + * +----->+ 1 | + * +---+ + * +---+ +--->+ 2 | + * FEEDBACK | 0 +-----------+ +---+ + * STREAM +---+ +->| 3 | + * | 1 +-------------+ +---+ + * +---+ | 4 | + * | 2 | +---+ + * +---+ | 5 | + * | 3 | +---+ + * +---+ | 6 | + * | 4 | +---+ + * +---+ | 7 | + * | 5 | +---+ + * +---+ + * | 6 | + * +---+ + * | 7 | + * +---+ + * + */ + +struct sof_smart_amp_config { + uint32_t size; + uint32_t feedback_channels; + int8_t source_ch_map[PLATFORM_MAX_CHANNELS]; + int8_t feedback_ch_map[PLATFORM_MAX_CHANNELS]; +}; + +#if CONFIG_IPC_MAJOR_4 + +#define SMART_AMP_NUM_IN_PINS 2 +#define SMART_AMP_NUM_OUT_PINS 1 + +struct sof_smart_amp_ipc4_config { + struct ipc4_input_pin_format input_pins[SMART_AMP_NUM_IN_PINS]; + struct ipc4_output_pin_format output_pin; +}; + +enum smart_amp_config_params { + SMART_AMP_SET_MODEL = 1, + SMART_AMP_SET_CONFIG = 2, + SMART_AMP_GET_CONFIG = 3 +}; + +#endif + +#endif /* __SOF_AUDIO_SMART_AMP_H__ */ diff --git a/src/include/sof/schedule/dp_schedule.h b/src/include/sof/schedule/dp_schedule.h new file mode 100644 index 000000000000..2267d676fb8a --- /dev/null +++ b/src/include/sof/schedule/dp_schedule.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Szkudlinski + */ + +#ifndef __SOF_SCHEDULE_DP_SCHEDULE_H__ +#define __SOF_SCHEDULE_DP_SCHEDULE_H__ + +#include <rtos/task.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <stdint.h> +#include <ipc4/base_fw.h> +#include <ipc4/module.h> +#include <ipc4/pipeline.h> + +struct processing_module; + +/** + * + * DP scheduler is a scheduler that creates a separate preemptible Zephyr thread for each SOF task + * + * The task execution may be delayed and task may be re-scheduled periodically + * NOTE: delayed start and rescheduling takes place in sync with LL scheduler, meaning the + * DP scheduler is triggered on each core after all LL task have been completed + * + * Task run() may return: + * SOF_TASK_STATE_RESCHEDULE - the task will be rescheduled as specified in scheduler period + * note that task won't ever be rescheduled if LL is not running + * SOF_TASK_STATE_COMPLETED - the task will be removed from scheduling, + * calling schedule_task will add the task to processing again + * task_complete() will be called + * SOF_TASK_STATE_CANCEL - the task will be removed from scheduling, + * calling schedule_task will add the task to processing again + * task_complete() won't be called + * other statuses - assert will go off + * + * NOTE: task - means a SOF task + * thread - means a Zephyr preemptible thread + * + * TODO - EDF: + * Threads run on the same priority, lower than thread running LL tasks. Zephyr EDF mechanism + * is used for decision which thread/task is to be scheduled next. The DP scheduler calculates + * the task deadline and set it in Zephyr thread properties, the final scheduling decision is made + * by Zephyr. + * + * Each time tick the scheduler iterates through the list of all active tasks and calculates + * a deadline based on + * - knowledge how the modules are bound + * - declared time required by a task to complete processing + * - the deadline of the last module + * + */ + +/** + * \brief Init the Data Processing scheduler + */ +int scheduler_dp_init(void); + +/** + * \brief initialize a DP task and add it to scheduling + * It must be called on core the task is declared to run on + * + * \param[out] task pointer, pointer to allocated task structure will be return + * \param[in] uid pointer to UUID of the task + * \param[in] ops pointer to task functions + * \param[in] mod pointer to the module to be run + * \param[in] core CPU the thread should run on + * \param[in] stack_size size of stack for a zephyr task + * \param[in] options task options used for creation + */ +int scheduler_dp_task_init(struct task **task, + const struct sof_uuid_entry *uid, + const struct task_ops *ops, + struct processing_module *mod, + uint16_t core, + size_t stack_size, + uint32_t options); + +/** + * \brief Extract information about scheduler's tasks + * + * \param scheduler_props Structure to be filled + * \param data_off_size Pointer to the current size of the scheduler_props, to be updated + */ +void scheduler_get_task_info_dp(struct scheduler_props *scheduler_props, + uint32_t *data_off_size); + +enum { + DP_TASK_EVENT_PROCESS = BIT(0), /* Need to process data */ + DP_TASK_EVENT_CANCEL = BIT(1), /* Thread cancellation */ + DP_TASK_EVENT_IPC = BIT(2), /* IPC message */ + DP_TASK_EVENT_IPC_DONE = BIT(3), /* IPC processing has completed. */ +}; + +struct bind_info; +struct sof_source; +struct sof_sink; +/* + * Keeps the scheduler_dp_thread_ipc() flow simple - just one call that does all + * the IPC-message specific parameter packing internally. This is slightly + * suboptimal because IPC parameters first have to be collected in this + * structure and then packed in DP-accessible memory inside + * scheduler_dp_thread_ipc(). This could be split into two levels, by adding + * IPC-specific functions like ipc_flatten_pipeline_state() and similar, but + * that would add multiple functions to the API. + */ +union scheduler_dp_thread_ipc_param { + struct bind_info *bind_data; + struct { + unsigned int trigger_cmd; + enum ipc4_pipeline_state state; + int n_sources; + struct sof_source **sources; + int n_sinks; + struct sof_sink **sinks; + } pipeline_state; +}; + +#if CONFIG_ZEPHYR_DP_SCHEDULER +int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd, + const union scheduler_dp_thread_ipc_param *param); +#else +static inline int scheduler_dp_thread_ipc(struct processing_module *pmod, + unsigned int cmd, + const union scheduler_dp_thread_ipc_param *param) +{ + return 0; +} +#endif + +#endif /* __SOF_SCHEDULE_DP_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/edf_schedule.h b/src/include/sof/schedule/edf_schedule.h index 65155dad9262..aeb10d5b57c3 100644 --- a/src/include/sof/schedule/edf_schedule.h +++ b/src/include/sof/schedule/edf_schedule.h @@ -8,25 +8,15 @@ #ifndef __SOF_SCHEDULE_EDF_SCHEDULE_H__ #define __SOF_SCHEDULE_EDF_SCHEDULE_H__ -#include <sof/schedule/task.h> +#include <rtos/task.h> #include <sof/trace/trace.h> #include <user/trace.h> #include <stdint.h> -/* schedule tracing */ -#define trace_edf_sch(format, ...) \ - trace_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) - -#define trace_edf_sch_error(format, ...) \ - trace_error(TRACE_CLASS_EDF, format, ##__VA_ARGS__) - -#define tracev_edf_sch(format, ...) \ - tracev_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) - #define edf_sch_set_pdata(task, data) \ - (task->private = data) + (task->priv_data = data) -#define edf_sch_get_pdata(task) task->private +#define edf_sch_get_pdata(task) task->priv_data struct edf_task_pdata { void *ctx; @@ -34,7 +24,7 @@ struct edf_task_pdata { int scheduler_init_edf(void); -int schedule_task_init_edf(struct task *task, uint32_t uid, +int schedule_task_init_edf(struct task *task, const struct sof_uuid_entry *uid, const struct task_ops *ops, void *data, uint16_t core, uint32_t flags); diff --git a/src/include/sof/schedule/ll_schedule.h b/src/include/sof/schedule/ll_schedule.h index 5ba49eb4ce07..241a20daff40 100644 --- a/src/include/sof/schedule/ll_schedule.h +++ b/src/include/sof/schedule/ll_schedule.h @@ -13,37 +13,55 @@ #ifndef __SOF_SCHEDULE_LL_SCHEDULE_H__ #define __SOF_SCHEDULE_LL_SCHEDULE_H__ -#include <sof/schedule/task.h> +#include <rtos/task.h> #include <sof/trace/trace.h> #include <user/trace.h> #include <stdint.h> +#include <ipc4/base_fw.h> struct ll_schedule_domain; /* ll tracing */ -#define trace_ll(format, ...) \ - trace_event(TRACE_CLASS_SCHEDULE_LL, format, ##__VA_ARGS__) - -#define trace_ll_error(format, ...) \ - trace_error(TRACE_CLASS_SCHEDULE_LL, format, ##__VA_ARGS__) - -#define tracev_ll(format, ...) \ - tracev_event(TRACE_CLASS_SCHEDULE_LL, format, ##__VA_ARGS__) +extern struct tr_ctx ll_tr; #define ll_sch_set_pdata(task, data) \ - do { (task)->private = (data); } while (0) + do { (task)->priv_data = (data); } while (0) -#define ll_sch_get_pdata(task) ((task)->private) +#define ll_sch_get_pdata(task) ((task)->priv_data) struct ll_task_pdata { uint64_t period; + uint16_t ratio; /**< ratio of periods compared to the registrable task */ + uint16_t skip_cnt; /**< how many times the task was skipped for execution */ }; +#if !defined(__ZEPHYR__) int scheduler_init_ll(struct ll_schedule_domain *domain); int schedule_task_init_ll(struct task *task, - uint32_t uid, uint16_t type, uint16_t priority, - enum task_state (*run)(void *data), void *data, - uint16_t core, uint32_t flags); + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags); +#else +int zephyr_ll_scheduler_init(struct ll_schedule_domain *domain); + +int zephyr_ll_task_init(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags); + +#define scheduler_init_ll zephyr_ll_scheduler_init +#define schedule_task_init_ll zephyr_ll_task_init + +#endif + +/** + * \brief Extract information about scheduler's tasks + * + * \param scheduler_props Structure to be filled + * \param data_off_size Pointer to the current size of the scheduler_props, to be updated + */ +void scheduler_get_task_info_ll(struct scheduler_props *scheduler_props, + uint32_t *data_off_size); #endif /* __SOF_SCHEDULE_LL_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/ll_schedule_domain.h b/src/include/sof/schedule/ll_schedule_domain.h index 2d20313858fc..dc28e43c7461 100644 --- a/src/include/sof/schedule/ll_schedule_domain.h +++ b/src/include/sof/schedule/ll_schedule_domain.h @@ -8,56 +8,84 @@ #ifndef __SOF_SCHEDULE_LL_SCHEDULE_DOMAIN_H__ #define __SOF_SCHEDULE_LL_SCHEDULE_DOMAIN_H__ -#include <sof/atomic.h> -#include <sof/debug/panic.h> -#include <sof/lib/alloc.h> +#include <rtos/atomic.h> +#include <rtos/panic.h> +#include <rtos/alloc.h> #include <sof/lib/cpu.h> -#include <sof/lib/clk.h> +#include <rtos/clk.h> #include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> #include <sof/trace/trace.h> #include <ipc/topology.h> #include <user/trace.h> #include <stdbool.h> #include <stdint.h> +#define LL_TIMER_PERIOD_US 1000ULL /* default period in microseconds */ + +/* Default ll watchdog timeout in microseconds. + * It was decided to have a timeout of two periods to give a safe margin of time between the start + * of the watchdog and its first feeding. + */ +#define LL_WATCHDOG_TIMEOUT_US (2 * LL_TIMER_PERIOD_US) + + struct dma; struct ll_schedule_domain; struct task; struct timer; +struct comp_dev; struct ll_schedule_domain_ops { int (*domain_register)(struct ll_schedule_domain *domain, - uint64_t period, struct task *task, + struct task *task, void (*handler)(void *arg), void *arg); - void (*domain_unregister)(struct ll_schedule_domain *domain, - struct task *task, uint32_t num_tasks); + int (*domain_unregister)(struct ll_schedule_domain *domain, + struct task *task, uint32_t num_tasks); void (*domain_enable)(struct ll_schedule_domain *domain, int core); void (*domain_disable)(struct ll_schedule_domain *domain, int core); +#if CONFIG_CROSS_CORE_STREAM + /* + * Unlike domain_disable(), these are intended to temporary block LL from + * starting its next cycle. Triggering (e.g., by means of timer interrupt) + * is still enabled and registered but execution of next cycle is blocked. + * Once unblocked, if triggering were previously registered in a blocked + * state -- next cycle execution could start immediately. + */ + void (*domain_block)(struct ll_schedule_domain *domain); + void (*domain_unblock)(struct ll_schedule_domain *domain); +#endif void (*domain_set)(struct ll_schedule_domain *domain, uint64_t start); void (*domain_clear)(struct ll_schedule_domain *domain); bool (*domain_is_pending)(struct ll_schedule_domain *domain, - struct task *task); + struct task *task, struct comp_dev **comp); + void (*domain_task_cancel)(struct ll_schedule_domain *domain, struct task *task); }; struct ll_schedule_domain { - uint64_t last_tick; /**< timestamp of last run */ - spinlock_t lock; /**< standard lock */ + uint64_t next_tick; /**< ticks just set for next run */ + uint64_t new_target_tick; /**< for the next set, used during the reschedule stage */ +#ifdef CONFIG_SOF_USERSPACE_LL + struct k_mutex *lock; /**< standard lock */ +#else + struct k_spinlock lock; /**< standard lock */ +#endif atomic_t total_num_tasks; /**< total number of registered tasks */ - atomic_t num_clients; /**< number of registered cores */ + atomic_t enabled_cores; /**< number of enabled cores */ uint32_t ticks_per_ms; /**< number of clock ticks per ms */ int type; /**< domain type */ int clk; /**< source clock */ bool synchronous; /**< are tasks should be synchronous */ - void *private; /**< pointer to private data */ - bool registered[PLATFORM_CORE_COUNT]; /**< registered cores */ + bool full_sync; /**< tasks should be full synchronous, no time dependent */ + void *priv_data; /**< pointer to private data */ + bool enabled[CONFIG_CORE_COUNT]; /**< enabled cores */ const struct ll_schedule_domain_ops *ops; /**< domain ops */ }; -#define ll_sch_domain_set_pdata(domain, data) ((domain)->private = (data)) +#define ll_sch_domain_set_pdata(domain, data) ((domain)->priv_data = (data)) -#define ll_sch_domain_get_pdata(domain) ((domain)->private) +#define ll_sch_domain_get_pdata(domain) ((domain)->priv_data) static inline struct ll_schedule_domain *timer_domain_get(void) { @@ -69,40 +97,99 @@ static inline struct ll_schedule_domain *dma_domain_get(void) return sof_get()->platform_dma_domain; } +#ifdef CONFIG_SOF_USERSPACE_LL +struct task *zephyr_ll_task_alloc(void); +struct k_heap *zephyr_ll_user_heap(void); +void zephyr_ll_user_resources_init(void); +#endif /* CONFIG_SOF_USERSPACE_LL */ + static inline struct ll_schedule_domain *domain_init (int type, int clk, bool synchronous, const struct ll_schedule_domain_ops *ops) { struct ll_schedule_domain *domain; - domain = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*domain)); +#ifdef CONFIG_SOF_USERSPACE_LL + domain = sof_heap_alloc(zephyr_ll_user_heap(), SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*domain), sizeof(void *)); + if (domain) + memset(domain, 0, sizeof(*domain)); +#else + domain = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*domain)); +#endif + if (!domain) + return NULL; domain->type = type; domain->clk = clk; domain->synchronous = synchronous; + domain->full_sync = false; +#ifdef __ZEPHYR__ + domain->ticks_per_ms = k_ms_to_cyc_ceil64(1); +#else domain->ticks_per_ms = clock_ms_to_ticks(clk, 1); +#endif domain->ops = ops; - - spinlock_init(&domain->lock); + /* maximum value means no tick has been set to timer */ + domain->next_tick = UINT64_MAX; + domain->new_target_tick = UINT64_MAX; + +#ifdef CONFIG_SOF_USERSPACE_LL + /* Allocate mutex dynamically for userspace access */ + domain->lock = k_object_alloc(K_OBJ_MUTEX); + if (!domain->lock) { + sof_heap_free(zephyr_ll_user_heap(), domain); + return NULL; + } + k_mutex_init(domain->lock); +#else + k_spinlock_init(&domain->lock); +#endif atomic_init(&domain->total_num_tasks, 0); - atomic_init(&domain->num_clients, 0); - - platform_shared_commit(domain, sizeof(*domain)); + atomic_init(&domain->enabled_cores, 0); return domain; } +/* configure the next interrupt for domain */ +static inline void domain_set(struct ll_schedule_domain *domain, uint64_t start) +{ + if (domain->ops->domain_set) + domain->ops->domain_set(domain, start); + else + domain->next_tick = start; +} + +/* clear the interrupt for domain */ +static inline void domain_clear(struct ll_schedule_domain *domain) +{ + if (domain->ops->domain_clear) + domain->ops->domain_clear(domain); + + /* reset to denote no tick/interrupt is set */ + domain->next_tick = UINT64_MAX; +} + +/* let the domain know that a task has been cancelled */ +static inline void domain_task_cancel(struct ll_schedule_domain *domain, + struct task *task) +{ + if (domain->ops->domain_task_cancel) + domain->ops->domain_task_cancel(domain, task); +} + static inline int domain_register(struct ll_schedule_domain *domain, - uint64_t period, struct task *task, + struct task *task, void (*handler)(void *arg), void *arg) { int ret; assert(domain->ops->domain_register); - ret = domain->ops->domain_register(domain, period, task, handler, arg); + ret = domain->ops->domain_register(domain, task, handler, arg); - platform_shared_commit(domain, sizeof(*domain)); + if (!ret) + /* registered one more task, increase the count */ + atomic_add(&domain->total_num_tasks, 1); return ret; } @@ -110,61 +197,87 @@ static inline int domain_register(struct ll_schedule_domain *domain, static inline void domain_unregister(struct ll_schedule_domain *domain, struct task *task, uint32_t num_tasks) { - assert(domain->ops->domain_unregister); + int ret; - domain->ops->domain_unregister(domain, task, num_tasks); + assert(domain->ops->domain_unregister); - platform_shared_commit(domain, sizeof(*domain)); + /* unregistering a task, decrement the count */ + if (task) + atomic_sub(&domain->total_num_tasks, 1); + + /* + * In some cases .domain_unregister() might not return, terminating the + * current thread, that's why we had to update state before calling it. + */ + ret = domain->ops->domain_unregister(domain, task, num_tasks); + if (ret < 0 && task) + /* Failed to unregister the domain, restore state */ + atomic_add(&domain->total_num_tasks, 1); } static inline void domain_enable(struct ll_schedule_domain *domain, int core) { - if (domain->ops->domain_enable) + if (!domain->enabled[core] && domain->ops->domain_enable) { domain->ops->domain_enable(domain, core); - - platform_shared_commit(domain, sizeof(*domain)); + domain->enabled[core] = true; + atomic_add(&domain->enabled_cores, 1); + } } static inline void domain_disable(struct ll_schedule_domain *domain, int core) { - if (domain->ops->domain_disable) + if (domain->enabled[core] && domain->ops->domain_disable) { domain->ops->domain_disable(domain, core); - - platform_shared_commit(domain, sizeof(*domain)); + domain->enabled[core] = false; + atomic_sub(&domain->enabled_cores, 1); + } } -static inline void domain_set(struct ll_schedule_domain *domain, uint64_t start) +#if CONFIG_CROSS_CORE_STREAM +static inline void domain_block(struct ll_schedule_domain *domain) { - if (domain->ops->domain_set) - domain->ops->domain_set(domain, start); - - platform_shared_commit(domain, sizeof(*domain)); + if (domain->ops->domain_block) + domain->ops->domain_block(domain); } -static inline void domain_clear(struct ll_schedule_domain *domain) +static inline void domain_unblock(struct ll_schedule_domain *domain) { - if (domain->ops->domain_clear) - domain->ops->domain_clear(domain); - - platform_shared_commit(domain, sizeof(*domain)); + if (domain->ops->domain_unblock) + domain->ops->domain_unblock(domain); } +#endif static inline bool domain_is_pending(struct ll_schedule_domain *domain, - struct task *task) + struct task *task, struct comp_dev **comp) { bool ret; assert(domain->ops->domain_is_pending); - ret = domain->ops->domain_is_pending(domain, task); - - platform_shared_commit(domain, sizeof(*domain)); + ret = domain->ops->domain_is_pending(domain, task, comp); return ret; } -struct ll_schedule_domain *timer_domain_init(struct timer *timer, int clk, - uint64_t timeout); + +#ifndef __ZEPHYR__ +struct ll_schedule_domain *timer_domain_init(struct timer *timer, int clk); +#else +#if CONFIG_DMA_DOMAIN +#define dma_multi_chan_domain_init(dma_array, num_dma, clk, aggregated_irq)\ + zephyr_dma_domain_init(dma_array, num_dma, clk) +struct ll_schedule_domain *zephyr_dma_domain_init(struct dma *dma_array, + uint32_t num_dma, + int clk); +#endif /* CONFIG_DMA_DOMAIN */ +struct ll_schedule_domain *zephyr_ll_domain(void); +struct ll_schedule_domain *zephyr_domain_init(int clk); +#define timer_domain_init(timer, clk) zephyr_domain_init(clk) +#ifdef CONFIG_SOF_USERSPACE_LL +struct k_thread *zephyr_domain_thread_tid(struct ll_schedule_domain *domain); +struct k_mem_domain *zephyr_ll_mem_domain(void); +#endif /* CONFIG_SOF_USERSPACE_LL */ +#endif /* __ZEPHYR__ */ struct ll_schedule_domain *dma_multi_chan_domain_init(struct dma *dma_array, uint32_t num_dma, int clk, diff --git a/src/include/sof/schedule/schedule.h b/src/include/sof/schedule/schedule.h index 04016b5c2cb3..bbdcbbecf3b4 100644 --- a/src/include/sof/schedule/schedule.h +++ b/src/include/sof/schedule/schedule.h @@ -9,67 +9,181 @@ #ifndef __SOF_SCHEDULE_SCHEDULE_H__ #define __SOF_SCHEDULE_SCHEDULE_H__ -#include <sof/bit.h> #include <sof/common.h> #include <sof/list.h> -#include <sof/schedule/task.h> +#include <rtos/task.h> #include <sof/trace/trace.h> #include <user/trace.h> +#include <errno.h> #include <stddef.h> #include <stdint.h> +#include <ipc4/base_fw.h> -/* schedule tracing */ -#define trace_schedule(format, ...) \ - trace_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) - -#define trace_schedule_error(format, ...) \ - trace_error(TRACE_CLASS_EDF, format, ##__VA_ARGS__) - -#define tracev_schedule(format, ...) \ - tracev_event(TRACE_CLASS_EDF, format, ##__VA_ARGS__) +/** \addtogroup schedule_api Schedule API + * @{ + */ -/* SOF_SCHEDULE_ type comes from topology */ +/** \brief Type of scheduler, comes from topology. */ enum { - /* EDF scheduler - schedules based on task's deadline */ - SOF_SCHEDULE_EDF = 0, - - /* Low latency timer scheduler - schedules immediately on selected - * timer's tick - */ - SOF_SCHEDULE_LL_TIMER, - - /* Low latency DMA scheduler - schedules immediately on scheduling - * component's DMA interrupt - */ - SOF_SCHEDULE_LL_DMA, - SOF_SCHEDULE_COUNT + SOF_SCHEDULE_EDF = 0, /**< EDF, schedules based on task's deadline */ + SOF_SCHEDULE_LL_TIMER, /**< Low latency timer, schedules immediately + * on selected timer's tick + */ + SOF_SCHEDULE_LL_DMA, /**< Low latency DMA, schedules immediately + * on scheduling component's DMA interrupt + */ + SOF_SCHEDULE_DP, /**< DataProcessing scheduler + * Scheduler based on Zephyr peemptive threads + * TODO: DP will become the Zephyr EDF scheduler type + * and will be unified with SOF_SCHEDULE_EDF for Zephyr builds + * current implementation of Zephyr based EDF is depreciated now + */ + SOF_SCHEDULE_TWB, /**< Tasks With Budget scheduler based on Zephyr peemptive threads + * for each SOF task that has pre-allocated MCPS budget + * renewed with every system tick. + */ + SOF_SCHEDULE_COUNT /**< indicates number of scheduler types */ }; +/** \brief Scheduler free available flags */ +#define SOF_SCHEDULER_FREE_IRQ_ONLY BIT(0) /**< Free function disables only + * interrupts + */ +/** + * Scheduler operations. + * + * Almost all schedule operations must return 0 for success and negative values + * for errors. Only the scheduler_free operation is allowed to not return any + * status. + */ struct scheduler_ops { - void (*schedule_task)(void *data, struct task *task, uint64_t start, - uint64_t period); - void (*schedule_task_running)(void *data, struct task *task); - void (*schedule_task_complete)(void *data, struct task *task); - void (*reschedule_task)(void *data, struct task *task, uint64_t start); - void (*schedule_task_cancel)(void *data, struct task *task); - void (*schedule_task_free)(void *data, struct task *task); - void (*scheduler_free)(void *data); - void (*scheduler_run)(void *data); + /** + * Schedules task with given scheduling parameters. + * @param data Private data of selected scheduler. + * @param task Task to be scheduled. + * @param start Start time of given task (in microseconds). + * @param period Scheduling period of given task (in microseconds). + * @return 0 if succeeded, error code otherwise. + * + * This operation is mandatory. + */ + int (*schedule_task)(void *data, struct task *task, uint64_t start, + uint64_t period); + + /** + * Schedules task with given scheduling parameters. + * @param data Private data of selected scheduler. + * @param task Task to be scheduled. + * @param start Start time of given task (in microseconds). + * @param period Scheduling period of given task (in microseconds). + * @param before Task to be scheduled before + * @return 0 if succeeded, error code otherwise. + * + * This operation is optional. + */ + int (*schedule_task_before)(void *data, struct task *task, uint64_t start, + uint64_t period, struct task *before); + + /** + * Schedules task with given scheduling parameters. + * @param data Private data of selected scheduler. + * @param task Task to be scheduled. + * @param start Start time of given task (in microseconds). + * @param period Scheduling period of given task (in microseconds). + * @param after Task to be scheduled after + * @return 0 if succeeded, error code otherwise. + * + * This operation is optional. + */ + int (*schedule_task_after)(void *data, struct task *task, uint64_t start, + uint64_t period, struct task *after); + + /** + * Sets task into running state along with executing additional + * scheduler specific operations. + * @param data Private data of selected scheduler. + * @param task Task to be set into running state. + * @return 0 if succeeded, error code otherwise. + * + * This operation is optional. + */ + int (*schedule_task_running)(void *data, struct task *task); + + /** + * Reschedules already scheduled task with new start time. + * @param data Private data of selected scheduler. + * @param task Task to be rescheduled. + * @param start New start time of given task (in microseconds). + * @return 0 if succeeded, error code otherwise. + * + * This operation is optional. + */ + int (*reschedule_task)(void *data, struct task *task, uint64_t start); + + /** + * Cancels previously scheduled task. + * @param data Private data of selected scheduler. + * @param task Task to be canceled. + * @return 0 if succeeded, error code otherwise. + * + * This operation is mandatory. + */ + int (*schedule_task_cancel)(void *data, struct task *task); + + /** + * Frees task's resources. + * @param data Private data of selected scheduler. + * @param task Task to be freed. + * @return 0 if succeeded, error code otherwise. + * + * This operation is mandatory. + */ + int (*schedule_task_free)(void *data, struct task *task); + + /** + * Frees scheduler's resources. + * @param data Private data of selected scheduler. + * @param flags Function specific flags. + * @return 0 if succeeded, error code otherwise. + * + * This operation is optional. + */ + void (*scheduler_free)(void *data, uint32_t flags); + + /** + * Restores scheduler's resources. + * @param data Private data of selected scheduler. + * @return 0 if succeeded, error code otherwise. + * + * This operation is optional. + */ + int (*scheduler_restore)(void *data); }; +/** \brief Holds information about scheduler. */ struct schedule_data { - struct list_item list; - int type; - const struct scheduler_ops *ops; - void *data; + struct list_item list; /**< list of schedulers */ + int type; /**< SOF_SCHEDULE_ type */ + const struct scheduler_ops *ops; /**< scheduler operations */ + void *data; /**< pointer to private data */ }; +/** \brief Holds list of all registered schedulers. */ struct schedulers { - struct list_item list; + struct list_item list; /**< list of schedulers */ }; +/** + * Retrieves registered schedulers. + * @return List of registered schedulers. + */ struct schedulers **arch_schedulers_get(void); +/** + * Retrieves scheduler's data. + * @param type SOF_SCHEDULE_ type. + * @return Pointer to scheduler's data. + */ static inline void *scheduler_get_data(uint16_t type) { struct schedulers *schedulers = *arch_schedulers_get(); @@ -85,47 +199,102 @@ static inline void *scheduler_get_data(uint16_t type) return NULL; } -static inline void schedule_task_running(struct task *task) +/** See scheduler_ops::schedule_task_running */ +static inline int schedule_task_running(struct task *task) +{ + struct schedulers *schedulers = *arch_schedulers_get(); + struct schedule_data *sch; + struct list_item *slist; + + list_for_item(slist, &schedulers->list) { + sch = container_of(slist, struct schedule_data, list); + if (task->type == sch->type) { + /* optional operation */ + if (!sch->ops->schedule_task_running) + return 0; + + return sch->ops->schedule_task_running(sch->data, task); + } + } + + return -ENODEV; +} + +/** See scheduler_ops::schedule_task */ +static inline int schedule_task(struct task *task, uint64_t start, + uint64_t period) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; struct list_item *slist; + if (!task) + return -EINVAL; + list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (task->type == sch->type && sch->ops->schedule_task_running) - sch->ops->schedule_task_running(sch->data, task); + if (task->type == sch->type) + return sch->ops->schedule_task(sch->data, task, start, + period); } + + return -ENODEV; } -static inline void schedule_task_complete(struct task *task) +/** See scheduler_ops::schedule_task_before */ +static inline int schedule_task_before(struct task *task, uint64_t start, + uint64_t period, struct task *before) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; struct list_item *slist; + if (!task || !before) + return -EINVAL; + list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (task->type == sch->type && sch->ops->schedule_task_complete) - sch->ops->schedule_task_complete(sch->data, task); + if (task->type == sch->type) { + if (sch->ops->schedule_task_before) + return sch->ops->schedule_task_before(sch->data, task, start, + period, before); + + return sch->ops->schedule_task(sch->data, task, start, + period); + } } + + return -ENODEV; } -static inline void schedule_task(struct task *task, uint64_t start, - uint64_t period) +/** See scheduler_ops::schedule_task_after */ +static inline int schedule_task_after(struct task *task, uint64_t start, + uint64_t period, struct task *after) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; struct list_item *slist; + if (!task || !after) + return -EINVAL; + list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (task->type == sch->type && sch->ops->schedule_task) - sch->ops->schedule_task(sch->data, task, start, period); + if (task->type == sch->type) { + if (sch->ops->schedule_task_after) + return sch->ops->schedule_task_after(sch->data, task, start, + period, after); + + return sch->ops->schedule_task(sch->data, task, start, + period); + } } + + return -ENODEV; } -static inline void reschedule_task(struct task *task, uint64_t start) +/** See scheduler_ops::reschedule_task */ +static inline int reschedule_task(struct task *task, uint64_t start) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; @@ -133,12 +302,21 @@ static inline void reschedule_task(struct task *task, uint64_t start) list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (task->type == sch->type && sch->ops->reschedule_task) - sch->ops->reschedule_task(sch->data, task, start); + if (task->type == sch->type) { + /* optional operation */ + if (!sch->ops->reschedule_task) + return 0; + + return sch->ops->reschedule_task(sch->data, task, + start); + } } + + return -ENODEV; } -static inline void schedule_task_cancel(struct task *task) +/** See scheduler_ops::schedule_task_cancel */ +static inline int schedule_task_cancel(struct task *task) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; @@ -146,12 +324,15 @@ static inline void schedule_task_cancel(struct task *task) list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (task->type == sch->type && sch->ops->schedule_task_cancel) - sch->ops->schedule_task_cancel(sch->data, task); + if (task->type == sch->type) + return sch->ops->schedule_task_cancel(sch->data, task); } + + return -ENODEV; } -static inline void schedule_task_free(struct task *task) +/** See scheduler_ops::schedule_task_free */ +static inline int schedule_task_free(struct task *task) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; @@ -159,12 +340,15 @@ static inline void schedule_task_free(struct task *task) list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (task->type == sch->type && sch->ops->schedule_task_free) - sch->ops->schedule_task_free(sch->data, task); + if (task->type == sch->type) + return sch->ops->schedule_task_free(sch->data, task); } + + return -ENODEV; } -static inline void schedule_free(void) +/** See scheduler_ops::scheduler_free */ +static inline void schedule_free(uint32_t flags) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; @@ -173,29 +357,62 @@ static inline void schedule_free(void) list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); if (sch->ops->scheduler_free) - sch->ops->scheduler_free(sch->data); + sch->ops->scheduler_free(sch->data, flags); } } -static inline void schedule(void) +/** See scheduler_ops::scheduler_restore */ +static inline int schedulers_restore(void) { struct schedulers *schedulers = *arch_schedulers_get(); struct schedule_data *sch; struct list_item *slist; + assert(schedulers); + list_for_item(slist, &schedulers->list) { sch = container_of(slist, struct schedule_data, list); - if (sch->ops->scheduler_run) - sch->ops->scheduler_run(sch->data); + if (sch->ops->scheduler_restore) + return sch->ops->scheduler_restore(sch->data); } + + return 0; } +/** + * Initializes scheduling task. + * @param task Task to be initialized. + * @param uid Statically assigned task uuid. + * @param type SOF_SCHEDULE_ type. + * @param priority Task's priority. + * @param run Pointer to task's execution function. + * @param data Pointer to task's execution data. + * @param core Core on which task should be run. + * @param flags Special scheduling flags. + * @return 0 if succeeded, error code otherwise. + */ int schedule_task_init(struct task *task, - uint32_t uid, uint16_t type, uint16_t priority, - enum task_state (*run)(void *data), void *data, - uint16_t core, uint32_t flags); + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags); + +/** + * Initializes scheduler + * @param type SOF_SCHEDULE_ type. + * @param ops Pointer to scheduler's operations. + * @param data Scheduler's private data. + */ +void scheduler_init(int type, const struct scheduler_ops *ops, void *data); +/** + * Extract scheduler's task information from tasks + * @param scheduler_props Structure to be filled + * @param data_off_size Pointer to the current size of the scheduler_props, to be updated + * @param tasks Scheduler's task list + */ +void scheduler_get_task_info(struct scheduler_props *scheduler_props, + uint32_t *data_off_size, struct list_item *tasks); -void scheduler_init(int type, const struct scheduler_ops *ops, void *data); +/** @}*/ #endif /* __SOF_SCHEDULE_SCHEDULE_H__ */ diff --git a/src/include/sof/schedule/task.h b/src/include/sof/schedule/task.h deleted file mode 100644 index c8edb3ec6f56..000000000000 --- a/src/include/sof/schedule/task.h +++ /dev/null @@ -1,104 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_SCHEDULE_TASK_H__ -#define __SOF_SCHEDULE_TASK_H__ - -#include <arch/schedule/task.h> -#include <sof/debug/panic.h> -#include <sof/list.h> -#include <stdbool.h> -#include <stdint.h> - -struct comp_dev; -struct sof; - -/** \brief Predefined LL task priorities. */ -#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */ -#define SOF_TASK_PRI_MED 4 /* priority level 4 - medium */ -#define SOF_TASK_PRI_LOW 9 /* priority level 9 - low */ - -/** \brief Predefined EDF task deadlines. */ -#define SOF_TASK_DEADLINE_IDLE UINT64_MAX -#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1) -#define SOF_TASK_DEADLINE_NOW 0 - -/** \brief Task states. */ -enum task_state { - SOF_TASK_STATE_INIT = 0, - SOF_TASK_STATE_QUEUED, - SOF_TASK_STATE_PENDING, - SOF_TASK_STATE_RUNNING, - SOF_TASK_STATE_PREEMPTED, - SOF_TASK_STATE_COMPLETED, - SOF_TASK_STATE_FREE, - SOF_TASK_STATE_CANCEL, - SOF_TASK_STATE_RESCHEDULE, -}; - -/** \brief Task operations. */ -struct task_ops { - enum task_state (*run)(void *data); /**< task's main operation */ - void (*complete)(void *data); /**< executed on completion */ - uint64_t (*get_deadline)(void *data); /**< returns current deadline */ -}; - -/** \brief Task used by schedulers. */ -struct task { - uint64_t start; /**< start time */ - uint32_t uid; /**< Uuid */ - uint16_t type; /**< type of the task (LL or EDF) */ - uint16_t priority; /**< priority of the task (used by LL) */ - uint16_t core; /**< execution core */ - uint16_t flags; /**< custom flags */ - enum task_state state; /**< current state */ - void *data; /**< custom data passed to all ops */ - struct list_item list; /**< used by schedulers to hold tasks */ - void *private; /**< task private data */ - struct task_ops ops; /**< task operations */ -}; - -/** \brief Task type registered by pipelines. */ -struct pipeline_task { - struct task task; /**< parent structure */ - bool registrable; /**< should task be registered on irq */ - struct comp_dev *sched_comp; /**< pipeline scheduling component */ -}; - -#define pipeline_task_get(task) ((struct pipeline_task *)(task)) - -static inline enum task_state task_run(struct task *task) -{ - assert(task->ops.run); - - return task->ops.run(task->data); -} - -static inline void task_complete(struct task *task) -{ - if (task->ops.complete) - task->ops.complete(task->data); -} - -static inline uint64_t task_get_deadline(struct task *task) -{ - assert(task->ops.get_deadline); - - return task->ops.get_deadline(task->data); -} - -enum task_state task_main_master_core(void *data); - -enum task_state task_main_slave_core(void *data); - -void task_main_init(void); - -void task_main_free(void); - -int task_main_start(struct sof *sof); - -#endif /* __SOF_SCHEDULE_TASK_H__ */ diff --git a/src/include/sof/schedule/twb_schedule.h b/src/include/sof/schedule/twb_schedule.h new file mode 100644 index 000000000000..be7c06d0706f --- /dev/null +++ b/src/include/sof/schedule/twb_schedule.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + */ + +#ifndef __SOF_SCHEDULE_TWB_SCHEDULE_H__ +#define __SOF_SCHEDULE_TWB_SCHEDULE_H__ + +#include <rtos/task.h> +#include <stdint.h> + +/** + * @brief Task With Budget (TWB) Scheduler + * + * TWB scheduler is a scheduler that creates a separate preemptible Zephyr thread + * for each SOF task that has a pre-allocated MCPS budget renewed with every system tick. + * The TWB scheduler assigns either MEDIUM_PRIORITY or LOW_PRIORITY to the task thread + * based on the budget left in the current system tick. + * It allows for opportunistic execution if there is no other ready task + * with a higher priority while the budget is already spent. + * + * Examples of tasks with budget include IPC Task and IDC Task. + * + * The TWB scheduler has two key parameters assigned: + * - cycles granted: the budget per system tick + * - cycles consumed: the number of cycles consumed in a given system tick for task execution + * + * The number of cycles consumed is reset to 0 at the beginning of each system tick, + * renewing the TWB budget. + * When the number of cycles consumed exceeds the cycles granted, + * the task is switchedfrom MEDIUM to LOW priority. + * When the task with budget thread is created, the MPP Scheduling is responsible + * for setting the thread time slice equal to the task budget, along with + * setting a callback on time slice timeout. + * Thread time slicing guarantees that the Zephyr scheduler will interrupt execution + * when the budget is spent, + * so the MPP Scheduling timeout callback can re-evaluate the task priority. + * + * If there is a budget left in some system tick + * (i.e., the task spent less time or started executing closeto the system tick + * that preempts execution), it is reset and not carried over to the next tick. + * + * More info: + * https://thesofproject.github.io/latest/architectures/firmware/sof-zephyr/mpp_layer/mpp_scheduling.html + */ + +/** + * \brief default static stack size for each TWB thread + */ +#define ZEPHYR_TWB_STACK_SIZE 8192 + +/** + * \brief max budget limit + */ +#define ZEPHYR_TWB_BUDGET_MAX (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000) + +#define SYS_TICKS_TO_HW_CYCLES(x) (x * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#define HW_CYCLES_TO_SYS_TICKS(x) (x * CONFIG_SYS_CLOCK_TICKS_PER_SEC / CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) + +/** + * \brief Init the Tasks with Budget scheduler + */ +int scheduler_twb_init(void); + +/** + * \brief initialize a TWB task and add it to scheduling + * It must be called on core the task is declared to run on + * + * \param[out] task pointer, pointer to allocated task structure will be return + * \param[in] uid pointer to UUID of the task + * \param[in] ops pointer to task functions + * \param[in] data pointer to the task data + * \param[in] core CPU the thread should run on + * \param[in] name zephyr thread name + * \param[in] stack_size size of stack for a zephyr thread + * \param[in] thread_priority priority of the zephyr thread + * \param[in] cycles_granted cycles budget for the zephyr thread + */ +int scheduler_twb_task_init(struct task **task, + const struct sof_uuid_entry *uid, + const struct task_ops *ops, + void *data, + int32_t core, + const char *name, + size_t stack_size, + int32_t thread_priority, + uint32_t cycles_granted); + +#endif /* __SOF_SCHEDULE_TWB_SCHEDULE_H__ */ diff --git a/src/include/sof/sof.h b/src/include/sof/sof.h deleted file mode 100644 index 9d9bedd38f88..000000000000 --- a/src/include/sof/sof.h +++ /dev/null @@ -1,107 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_SOF_H__ -#define __SOF_SOF_H__ - -#include <arch/sof.h> -#include <sof/common.h> -#include <sof/lib/memory.h> - -struct cascade_root; -struct clock_info; -struct comp_driver_list; -struct dai_info; -struct dma_info; -struct dma_trace_data; -struct ipc; -struct ll_schedule_domain; -struct mm; -struct mn; -struct notify_data; -struct pm_runtime_data; -struct sa; -struct timer; -struct trace; -struct pipeline_posn; -struct probe_pdata; - -/** - * \brief General firmware context. - * This structure holds all the global pointers, which can potentially - * be accessed by SMP code, hence it should be aligned to platform's - * data cache line size. Alignments in the both beginning and end are needed - * to avoid potential before and after data evictions. - */ -struct sof { - /* init data */ - int argc; - char **argv; - - /* ipc */ - struct ipc *ipc; - - /* system agent */ - struct sa *sa; - - /* DMA for Trace*/ - struct dma_trace_data *dmat; - - /* generic trace structure */ - struct trace *trace; - - /* platform clock information */ - struct clock_info *clocks; - - /* default platform timer */ - struct timer *platform_timer; - - /* cpu (arch) timer */ - struct timer *cpu_timer; - - /* timer domain for driving timer LL scheduler */ - struct ll_schedule_domain *platform_timer_domain; - - /* DMA domain for driving DMA LL scheduler */ - struct ll_schedule_domain *platform_dma_domain; - - /* memory map */ - struct mm *memory_map; - - /* runtime power management data */ - struct pm_runtime_data *prd; - - /* shared notifier data */ - struct notify_data *notify_data; - - /* platform dai information */ - const struct dai_info *dai_info; - - /* platform DMA information */ - const struct dma_info *dma_info; - - /* cascading interrupt controller root */ - struct cascade_root *cascade_root; - - /* list of registered component drivers */ - struct comp_driver_list *comp_drivers; - - /* M/N dividers */ - struct mn *mn; - - /* probes */ - struct probe_pdata *probe; - - /* pipelines stream position */ - struct pipeline_posn *pipeline_posn; - - __aligned(PLATFORM_DCACHE_ALIGN) int alignment[0]; -} __aligned(PLATFORM_DCACHE_ALIGN); - -struct sof *sof_get(void); - -#endif /* __SOF_SOF_H__ */ diff --git a/src/include/sof/spinlock.h b/src/include/sof/spinlock.h deleted file mode 100644 index fadeda9c9a01..000000000000 --- a/src/include/sof/spinlock.h +++ /dev/null @@ -1,206 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -/* - * Simple spinlock implementation for SOF. - */ - -#ifndef __SOF_SPINLOCK_H__ -#define __SOF_SPINLOCK_H__ - -#include <arch/spinlock.h> -#include <sof/lib/memory.h> -#include <config.h> -#include <stdint.h> - -/* - * Lock debugging provides a simple interface to debug deadlocks. The rmbox - * trace output will show an output :- - * - * 0xd70 [41.306406] delta [0.359638] lock eal - * 0xd80 [41.306409] delta [0.000002] value 0x00000000000001b7 - * 0xd90 [41.306411] delta [0.000002] value 0x0000000000000001 - * 0xda0 [41.306413] delta [0.000002] value 0x0000000001000348 - * - * "eal" indicates we are holding a lock with interrupts OFF. The next value - * is the line number of where the lock was acquired. The second number is the - * number of other locks held whilst this lock is held and the subsequent - * numbers list each lock and the line number of it's holder. e.g. to find - * the locks :- - * - * grep -rn lock --include *.c | grep 840 (search for lock at line 0x348) - * src/drivers/dw-dma.c:840: spinlock_init(&dma->lock); - * - * grep -rn lock --include *.c | grep 439 - * src/lib/alloc.c:439: spin_lock_irq(&memmap.lock, flags); - * - * Every lock entry and exit shows LcE and LcX in trace alongside the lock - * line numbers in hex. e.g. - * - * 0xfd60 [11032.730567] delta [0.000004] lock LcE - * 0xfd70 [11032.730569] delta [0.000002] value 0x00000000000000ae - * - * Deadlock can be confirmed in rmbox :- - * - * Debug log: - * debug: 0x0 (00) = 0xdead0007 (-559087609) |....| - * .... - * Error log: - * using 19.20MHz timestamp clock - * 0xc30 [26.247240] delta [26.245851] lock DED - * 0xc40 [26.247242] delta [0.000002] value 0x00000000000002b4 - * 0xc50 [26.247244] delta [0.000002] value 0x0000000000000109 - * - * DED means deadlock has been detected and the DSP is now halted. The first - * value after DEA is the line number where deadlock occurs and the second - * number is the line number where the lock is allocated. These can be grepped - * like above. - */ - -#if CONFIG_DEBUG_LOCKS - -#include <sof/debug/panic.h> -#include <sof/trace/trace.h> -#include <ipc/trace.h> -#include <user/trace.h> - -#define DBG_LOCK_USERS 8 -#define DBG_LOCK_TRIES 10000 - -#define trace_lock(__e, ...) trace_error_atomic(TRACE_CLASS_LOCK,\ - __e, ##__VA_ARGS__) -#define tracev_lock(__e, ...) tracev_event_atomic(TRACE_CLASS_LOCK,\ - __e, ##__VA_ARGS__) -#define trace_lock_error(__e, ...) trace_error_atomic(TRACE_CLASS_LOCK, \ - __e, ##__VA_ARGS__) - -extern uint32_t lock_dbg_atomic; -extern uint32_t lock_dbg_user[DBG_LOCK_USERS]; - -/* panic on deadlock */ -#define spin_try_lock_dbg(lock, line) \ - do { \ - int __tries; \ - for (__tries = DBG_LOCK_TRIES; __tries > 0; __tries--) { \ - if (arch_try_lock(lock)) \ - break; /* lock acquired */ \ - } \ - if (__tries == 0) { \ - trace_lock_error("DED"); \ - trace_lock_error("line: %d", line); \ - trace_lock_error("user: %d", (lock)->user); \ - panic(SOF_IPC_PANIC_DEADLOCK); /* lock not acquired */ \ - } \ - } while (0) - -#if CONFIG_DEBUG_LOCKS_VERBOSE -#define spin_lock_log(lock, line) \ - do { \ - if (lock_dbg_atomic) { \ - int __i = 0; \ - int __count = lock_dbg_atomic >= DBG_LOCK_USERS \ - ? DBG_LOCK_USERS : lock_dbg_atomic; \ - trace_lock_error("eal"); \ - trace_lock_error("line: %d", line); \ - trace_lock_error("dbg_atomic: %d", lock_dbg_atomic); \ - for (__i = 0; __i < __count; __i++) { \ - trace_lock_error("value: %d", \ - (lock_dbg_atomic << 24) | \ - lock_dbg_user[__i]); \ - } \ - } \ - } while (0) - -#define spin_lock_dbg(line) \ - do { \ - trace_lock("LcE"); \ - trace_lock("line: %d", line); \ - } while (0) - -#define spin_unlock_dbg(line) \ - do { \ - trace_lock("LcX"); \ - trace_lock("line: %d", line); \ - } while (0) - -#else -#define spin_lock_log(lock, line) do {} while (0) -#define spin_lock_dbg(line) do {} while (0) -#define spin_unlock_dbg(line) do {} while (0) -#endif - -#else - -#define trace_lock(__e) do {} while (0) -#define tracev_lock(__e) do {} while (0) - -#define spin_lock_dbg(line) do {} while (0) -#define spin_unlock_dbg(line) do {} while (0) - -#endif - -static inline int _spin_try_lock(spinlock_t *lock, int line) -{ - spin_lock_dbg(line); - return arch_try_lock(lock); -} - -#define spin_try_lock(lock) _spin_try_lock(lock, __LINE__) - -/* all SMP spinlocks need init, nothing todo on UP */ -static inline void _spinlock_init(spinlock_t *lock, int line) -{ - arch_spinlock_init(lock); -#if CONFIG_DEBUG_LOCKS - lock->user = line; -#endif -} - -#define spinlock_init(lock) _spinlock_init(lock, __LINE__) - -/* does nothing on UP systems */ -static inline void _spin_lock(spinlock_t *lock, int line) -{ - spin_lock_dbg(line); -#if CONFIG_DEBUG_LOCKS - spin_lock_log(lock, line); - spin_try_lock_dbg(lock, line); -#else - arch_spin_lock(lock); -#endif - - /* spinlock has to be in a shared memory */ - platform_shared_commit(lock, sizeof(*lock)); -} - -#define spin_lock(lock) _spin_lock(lock, __LINE__) - -/* disables all IRQ sources and takes lock - enter atomic context */ -uint32_t _spin_lock_irq(spinlock_t *lock); - -#define spin_lock_irq(lock, flags) (flags = _spin_lock_irq(lock)) - -static inline void _spin_unlock(spinlock_t *lock, int line) -{ - arch_spin_unlock(lock); -#if CONFIG_DEBUG_LOCKS - spin_unlock_dbg(line); -#endif - - /* spinlock has to be in a shared memory */ - platform_shared_commit(lock, sizeof(*lock)); -} - -#define spin_unlock(lock) _spin_unlock(lock, __LINE__) - -/* re-enables current IRQ sources and releases lock - leave atomic context */ -void _spin_unlock_irq(spinlock_t *lock, uint32_t flags, int line); - -#define spin_unlock_irq(lock, flags) _spin_unlock_irq(lock, flags, __LINE__) - -#endif /* __SOF_SPINLOCK_H__ */ diff --git a/src/include/sof/string.h b/src/include/sof/string.h deleted file mode 100644 index 787f73ffef9a..000000000000 --- a/src/include/sof/string.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_STRING_H__ -#define __SOF_STRING_H__ - -#include <arch/string.h> -#include <stddef.h> - -/* C memcpy for arch that don't have arch_memcpy() */ -void cmemcpy(void *dest, void *src, size_t size); -int rstrlen(const char *s); -int rstrcmp(const char *s1, const char *s2); - -#if defined(arch_memcpy) -#define rmemcpy(dest, src, size) \ - arch_memcpy(dest, src, size) -#else -#define rmemcpy(dest, src, size) \ - cmemcpy(dest, src, size) -#endif - -#endif /* __SOF_STRING_H__ */ diff --git a/src/include/sof/tlv.h b/src/include/sof/tlv.h new file mode 100644 index 000000000000..442c03a5fc69 --- /dev/null +++ b/src/include/sof/tlv.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Tomasz Leman <tomasz.m.leman@intel.com> + */ + +#ifndef __SOF_TLV_H__ +#define __SOF_TLV_H__ + +#include <stdint.h> +#include <string.h> +#include <sof/compiler_attributes.h> + +/** + * @brief Type–length–value struct. + * + * The TLV structure is used to pass data between the SW and FW. The data block may include TLV + * sequences of variable size and in random order. Data sequences can be easily search using + * generalized parsing function. + */ +struct sof_tlv { + uint32_t type; + uint32_t length; + char value[]; +} __packed __aligned(4); + +struct sof_tl { + uint32_t type; + uint32_t max_length; +} __packed __aligned(4); + +/** + * @brief Allows to step through successive values in a sequence of TLV structures. + * + * @param tlv Pointer to the base TLV. + * @return struct sof_tlv* Pointer to the next TLV. + */ +static inline struct sof_tlv *tlv_next(const struct sof_tlv *tlv) +{ + if (tlv->length % sizeof(uint32_t) != 0) + return NULL; + + return (struct sof_tlv *)((char *)(tlv) + sizeof(*tlv) + tlv->length); +} + +/** + * @brief Fills the TLV Structure (version for 32-bit values). + * + * @param tlv TLV struct pointer. + * @param type Value type. + * @param value The value. + */ +static inline void tlv_value_uint32_set(struct sof_tlv *tlv, uint32_t type, uint32_t value) +{ + tlv->type = type; + tlv->length = sizeof(uint32_t); + memcpy_s(tlv->value, tlv->length, &value, tlv->length); +} + +/** + * @brief Fills the TLV Structure (general purpose version). + * + * @param tlv TLV struct pointer. + * @param type Value type. + * @param length Value size. + * @param value Pointer to the value. + */ +static inline void tlv_value_set(struct sof_tlv *tlv, uint32_t type, uint32_t length, void *value) +{ + tlv->type = type; + tlv->length = length; + memcpy_s(tlv->value, length, value, length); +} + +/** + * @brief Searches a sequence of TLV structures for values of the specified type. + * + * @param data Pointer to the beginning of the TLV sequence. + * @param size The size of the data block containing the TLV structure sequences. + * @param type The type of the searched value. + * @param value A pointer that will point to the found value. + * @param length The size of the found value. + */ +static inline void tlv_value_get(const void *data, + uint32_t size, + uint32_t type, + void **value, + uint32_t *length) +{ + const struct sof_tlv *tlv = (const struct sof_tlv *)data; + const uint32_t end_addr = (uint32_t)data + size; + + while (tlv && (uint32_t)tlv < end_addr) { + if (tlv->type == type) { + *value = (void *)tlv->value; + *length = tlv->length; + break; + } + + tlv = tlv_next(tlv); + } +} + +/** + * @brief Retrieves pointer to the TLV Structure value of the specified type + * + * @param tlv TLV struct pointer. + * @param type Value type. + * @return Value pointer + */ +static inline void *tlv_value_ptr_get(struct sof_tlv *tlv, uint32_t type) +{ + if ((uintptr_t)tlv % sizeof(uint32_t) != 0) + return NULL; + + if (tlv->type != type) + return NULL; + + return (void *)tlv->value; +} + +#endif /* __SOF_TLV_H__ */ diff --git a/src/include/sof/trace/dma-trace.h b/src/include/sof/trace/dma-trace.h index 947aeb6cce67..dbc9e666da47 100644 --- a/src/include/sof/trace/dma-trace.h +++ b/src/include/sof/trace/dma-trace.h @@ -9,9 +9,9 @@ #define __SOF_TRACE_DMA_TRACE_H__ #include <sof/lib/dma.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/task.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> #include <ipc/trace.h> #include <stdint.h> @@ -24,7 +24,7 @@ struct dma_trace_buf { void *addr; /* buffer base address */ void *end_addr; /* buffer end address */ uint32_t size; /* size of buffer in bytes */ - uint32_t avail; /* avail bytes in buffer */ + uint32_t avail; /* bytes available to read */ }; struct dma_trace_data { @@ -33,17 +33,18 @@ struct dma_trace_data { struct dma_copy dc; struct sof_ipc_dma_trace_posn posn; struct ipc_msg *msg; - uint32_t old_host_offset; uint32_t host_size; struct task dmat_work; uint32_t enabled; uint32_t copy_in_progress; uint32_t stream_tag; - uint32_t dma_copy_align; /**< Minimal chunk of data possible to be - * copied by dma connected to host - */ - uint32_t dropped_entries; /* amount of dropped entries */ - spinlock_t lock; /* dma trace lock */ + uint32_t active_stream_tag; + uint32_t dma_copy_align; /* Minimal chunk of data possible to be + * copied by dma connected to host + */ + uint32_t dropped_entries; /* amount of dropped entries */ + struct k_spinlock lock; /* dma trace lock */ + uint64_t time_delta; /* difference between the host time */ }; int dma_trace_init_early(struct sof *sof); @@ -52,13 +53,19 @@ int dma_trace_host_buffer(struct dma_trace_data *d, struct dma_sg_elem_array *elem_array, uint32_t host_size); int dma_trace_enable(struct dma_trace_data *d); -void dma_trace_flush(void *t); +void dma_trace_disable(struct dma_trace_data *d); +void dma_trace_flush(void *destination); void dma_trace_on(void); void dma_trace_off(void); void dtrace_event(const char *e, uint32_t size); void dtrace_event_atomic(const char *e, uint32_t length); +static inline bool dma_trace_initialized(const struct dma_trace_data *d) +{ + return d && d->dmatb.addr; +} + static inline struct dma_trace_data *dma_trace_data_get(void) { return sof_get()->dmat; diff --git a/src/include/sof/trace/preproc.h b/src/include/sof/trace/preproc.h deleted file mode 100644 index 4a0ff8bc7833..000000000000 --- a/src/include/sof/trace/preproc.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@intel.com> - */ - -#ifndef __SOF_TRACE_PREPROC_H__ -#define __SOF_TRACE_PREPROC_H__ - -/* Macros in this file are to be invoked directly from code. - * In order to work, they require a number of other macros that are - * defined in the header file specified below. - * Macros from the file specified below are not to meant to be used - * directly / independently. - * For more detailed commentary of innards of macros in this file, - * see file specified below. - */ -#include <sof/trace/preproc-private.h> -#include <stdint.h> - -/* count number of var args - during preprocesing - * works for predefined number of args - * META_COUNT_VARAGS_BEFORE_COMPILE(A,B,C,D) evaluates to 4 - */ -#define META_COUNT_VARAGS_BEFORE_COMPILE(...)\ - META_DEC(\ - _META_PP_NARG_BEFORE_COMPILE_(\ - _, ##__VA_ARGS__, _META_PP_RSEQ_N()\ - )\ - ) - -/* treat x as string while forcing x expansion beforehand */ -#define META_QUOTE(x) _META_QUOTE(x) - -/* concat x and y while forcing x and y expansion beforehand */ -#define META_CONCAT(x, y) _META_CONCAT_BASE(x, y) - -/* discard first x-1 args in vararg and return the xth arg */ - -#define META_GET_ARG_N(n, ...) META_CONCAT(_META_GET_ARG_, n)(__VA_ARGS__) - -#define META_HAS_ARGS(...) META_BOOL(\ - _META_GET_ARG_1(_META_NO_ARGS __VA_ARGS__)()\ -) - -/* Only META_NOT(0) evaulates to 1 - * notice, that any x!=0 would also result in 0 - * e.x. META_NOT(123) evaluates to 0 - */ -#define META_NOT(x) _META_IS_PROBE(META_CONCAT(_META_NOT_, x)) -/* hacky way to convert tokens into 0 1*/ -#define META_BOOL(x) META_NOT(META_NOT(x)) - -/* META_IF_ELSE(X)(a)(b) expands to - * b for X == 0 - * a for X != 0 - */ -#define META_IF_ELSE(condition) _META_IF_ELSE(META_BOOL(condition)) - -/* same story with indirection as META_IF_ELSE */ -#define META_IF(condition) _META_IIF(META_BOOL(condition)) - -/* primitive recursion - * default depth is 1024 - */ -#define META_RECURSE(...) _META_REQRS_1024(__VA_ARGS__) -/* choose explicitly depth of recursion - */ -#define META_RECURSE_N(depth, ...)\ - META_CONCAT(_META_REQRS_, depth)(__VA_ARGS__) - -/* The only sane way I found to increment values in cpreproc */ -#define META_INC(x) META_CONCAT(_META_INC_, x) - -/* The only sane way I found to decrement values in cpreproc */ -#define META_DEC(x) META_CONCAT(_META_DEC_, x) - -/* Delay macro m expansion depth times - * by writing META_DEFER(0, m)(args) we expand it in 1st scan - * by writing META_DEFER(1, m)(args) we expand it in 2nd scan - * ... - * by writing META_DEFER(n, m)(args) we expand it in n+1nth scan - */ -#define META_DEFER(depth, m) m _META_DEFER_N(depth) - -/* while(count--!=0) do - * uses DEC so count == N can only work if all following exist - * DEC_0, DEC_1, ..., DEC_N-1, DEC_N - */ -#define META_REPEAT(count, macro, ...)\ - _META_WHEN(count)\ - (\ - _META_DEFER_2(_META_REPEAT_INDIRECT) () \ - (META_DEC(count), macro, __VA_ARGS__)\ - _META_DEFER_2(macro)\ - (META_DEC(count), __VA_ARGS__)\ - ) - -/* map every group of arg_count arguments onto function m - * i.e. arg_count=2;m=ADD;args=1,2,3,4,5,6,7... - * results in ADD(1,2) ADD(3,4) ADD(5,6) and so on - * MAP##N must exist for arg_count == N to work - */ -#define META_MAP(arg_count, m, ...)\ - META_CONCAT(_META_MAP_, arg_count)(m, __VA_ARGS__) - -/* map aggregator and every group of arg_count arguments onto function m - * i.e. aggr=x;arg_count=1;m=ADD;args=1,2,3,4,5,6,7... - * results in x = ... ADD(7,ADD(6,ADD(5,ADD(4,ADD(3,ADD(2,ADD(1,x))))))) ... - * MAP##N must exist for arg_count == N to work - */ -#define META_MAP_AGGREGATE(arg_count, m, aggr, ...)\ - META_CONCAT(_META_MAP_AGGREGATE_, arg_count)(m, aggr, __VA_ARGS__) - -/* META_CONCAT_SEQ is basicaly variadic version of macro META_CONCAT - * META_CONCAT_SEQ(A,B,C,D) tokenizes to ABCD - */ -#define META_CONCAT_SEQ(aggr, ...) META_RECURSE(\ - META_MAP_AGGREGATE(1, META_CONCAT, aggr, __VA_ARGS__)) - -/* META_CONCAT with parametrised delimeter between concatenised tokens - * META_CONCAT_SEQ_DELIM_(A,B,C,D) tokenizes as A_B_C_D - */ -#define META_CONCAT_SEQ_DELIM_(aggr, ...) META_RECURSE(\ - META_MAP_AGGREGATE(1, _META_CONCAT_DELIM_, aggr, __VA_ARGS__)) - -/* META_SEQ_FROM_0_TO(3, META_SEQ_STEP_param) - * produces , param0 , param1 , param2 - */ -#define META_SEQ_FROM_0_TO(arg_count, func)\ - META_RECURSE(META_REPEAT(arg_count, func, ~)) - -/* Macros to be used as 2nd argument of macro META_SEQ_FROM_0_TO - * for instance - * META_SEQ_FROM_0_TO(arg_count, META_SEQ_STEP) - * produces - * 0 1 2 3 4 - */ -#define META_SEQ_STEP(i, _) i -#define META_SEQ_STEP_param(i, _) , META_CONCAT(param, i) -#define META_SEQ_STEP_param_uint32_t(i, _) , uint32_t META_CONCAT(param, i) -#define META_SEQ_STEP_param_uint64_t(i, _) , uint64_t META_CONCAT(param, i) -#define META_SEQ_STEP_param_int32_t( i, _) , int32_t META_CONCAT(param, i) -#define META_SEQ_STEP_param_int64_t( i, _) , int64_t META_CONCAT(param, i) - -#define META_SEQ_STEP_id(i, _) , META_CONCAT(id_, i) -#define META_SEQ_STEP_id_uint32_t(i, _) , uint32_t META_CONCAT(id_, i) - -/* generates function signature - * for instance with: - * prefix=foo ; postfix=__bar ; return_t=void - * args=(int x, int y) - * will produce: - * void foo_bar(int x, int y) - */ -#define META_FUNC_WITH_VARARGS(prefix, postfix, return_t, args)\ - return_t META_CONCAT(prefix, postfix) (args) - -/* counteract compiler warning about unused variables */ -#define UNUSED(arg1, ...) do { META_RECURSE( \ - META_MAP_AGGREGATE(1, _META_VOID2, _META_VOID(arg1), __VA_ARGS__)); \ - } while (0) - -#endif /* __SOF_TRACE_PREPROC_H__ */ diff --git a/src/include/sof/trace/trace-boot.h b/src/include/sof/trace/trace-boot.h new file mode 100644 index 000000000000..abb2e9e4ddb3 --- /dev/null +++ b/src/include/sof/trace/trace-boot.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016,2024 Intel Corporation. + */ + +#ifndef __SOF_TRACE_TRACE_BOOT_H__ +#define __SOF_TRACE_TRACE_BOOT_H__ + +/* bootloader trace values */ +#define TRACE_BOOT_LDR_ENTRY 0x100 +#define TRACE_BOOT_LDR_HPSRAM 0x110 +#define TRACE_BOOT_LDR_MANIFEST 0x120 +#define TRACE_BOOT_LDR_LPSRAM 0x130 +#define TRACE_BOOT_LDR_L1DRAM 0x140 +#define TRACE_BOOT_LDR_JUMP 0x150 + +#define TRACE_BOOT_LDR_PARSE_MODULE 0x210 +#define TRACE_BOOT_LDR_PARSE_SEGMENT 0x220 + +/* general trace init codes - only used at boot + * when main trace is not available + */ +#define TRACE_BOOT_START 0x1000 +#define TRACE_BOOT_ARCH 0x2000 +#define TRACE_BOOT_SYS 0x3000 +#define TRACE_BOOT_PLATFORM 0x4000 + +/* system specific codes */ +#define TRACE_BOOT_SYS_HEAP (TRACE_BOOT_SYS + 0x100) +#define TRACE_BOOT_SYS_TRACES (TRACE_BOOT_SYS + 0x200) +#define TRACE_BOOT_SYS_NOTIFIER (TRACE_BOOT_SYS + 0x300) +#define TRACE_BOOT_SYS_POWER (TRACE_BOOT_SYS + 0x400) + +/* platform/device specific codes */ +#define TRACE_BOOT_PLATFORM_ENTRY (TRACE_BOOT_PLATFORM + 0x100) +#define TRACE_BOOT_PLATFORM_IRQ (TRACE_BOOT_PLATFORM + 0x110) +#define TRACE_BOOT_PLATFORM_MBOX (TRACE_BOOT_PLATFORM + 0x120) +#define TRACE_BOOT_PLATFORM_SHIM (TRACE_BOOT_PLATFORM + 0x130) +#define TRACE_BOOT_PLATFORM_PMC (TRACE_BOOT_PLATFORM + 0x140) +#define TRACE_BOOT_PLATFORM_TIMER (TRACE_BOOT_PLATFORM + 0x150) +#define TRACE_BOOT_PLATFORM_CLOCK (TRACE_BOOT_PLATFORM + 0x160) +#define TRACE_BOOT_PLATFORM_SCHED (TRACE_BOOT_PLATFORM + 0x170) +#define TRACE_BOOT_PLATFORM_AGENT (TRACE_BOOT_PLATFORM + 0x180) +#define TRACE_BOOT_PLATFORM_CPU_FREQ (TRACE_BOOT_PLATFORM + 0x190) +#define TRACE_BOOT_PLATFORM_SSP_FREQ (TRACE_BOOT_PLATFORM + 0x1A0) +#define TRACE_BOOT_PLATFORM_DMA (TRACE_BOOT_PLATFORM + 0x1B0) +#define TRACE_BOOT_PLATFORM_IPC (TRACE_BOOT_PLATFORM + 0x1C0) +#define TRACE_BOOT_PLATFORM_IDC (TRACE_BOOT_PLATFORM + 0x1D0) +#define TRACE_BOOT_PLATFORM_DAI (TRACE_BOOT_PLATFORM + 0x1E0) +#define TRACE_BOOT_PLATFORM_SSP (TRACE_BOOT_PLATFORM + 0x1F0) +#define TRACE_BOOT_PLATFORM_SPI (TRACE_BOOT_PLATFORM + 0x200) +#define TRACE_BOOT_PLATFORM_DMA_TRACE (TRACE_BOOT_PLATFORM + 0x210) + +#endif /* __SOF_TRACE_TRACE_BOOT_H__ */ diff --git a/src/include/sof/trace/trace-soflogger.h b/src/include/sof/trace/trace-soflogger.h new file mode 100644 index 000000000000..c357239555ef --- /dev/null +++ b/src/include/sof/trace/trace-soflogger.h @@ -0,0 +1,375 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016,2024 Intel Corporation. + */ + +#ifndef __SOF_TRACE_TRACE_SOFLOGGER_H__ +#define __SOF_TRACE_TRACE_SOFLOGGER_H__ + +#if !CONFIG_LIBRARY +#include <platform/trace/trace.h> +#endif + +#if CONFIG_LIBRARY +#include <stdio.h> +#endif + +struct sof; +struct trace; +struct tr_ctx; + +struct trace_filter { + uint32_t uuid_id; /**< type id, or 0 when not important */ + int32_t comp_id; /**< component id or -1 when not important */ + int32_t pipe_id; /**< pipeline id or -1 when not important */ + int32_t log_level; /**< new log level value */ +}; + +/** The start of this linker output MUST match the 'ldc_entry_header' + * struct defined in the logger program running in user space. + */ +#define _DECLARE_LOG_ENTRY(lvl, format, comp_class, n_params) \ + __section(".static_log." #lvl) \ + static const struct { \ + uint32_t level; \ + uint32_t component_class; \ + uint32_t params_num; \ + uint32_t line_idx; \ + uint32_t file_name_len; \ + uint32_t text_len; \ + const char file_name[sizeof(RELATIVE_FILE)]; \ + const char text[sizeof(format)]; \ + } log_entry = { \ + lvl, \ + comp_class, \ + n_params, \ + __LINE__, \ + sizeof(RELATIVE_FILE), \ + sizeof(format), \ + RELATIVE_FILE, \ + format \ + } + +#define _TRACE_EVENT_MAX_ARGUMENT_COUNT 4 + +static inline struct trace *trace_get(void) +{ + return sof_get()->trace; +} + +#include <stdarg.h> +#include <user/trace.h> /* LOG_LEVEL_... */ + +/* + * trace_event macro definition + * + * trace_event() macro is used for logging events that occur at runtime. + * It comes in 2 main flavours, atomic and non-atomic. Depending of definitions + * above, it might also propagate log messages to mbox if desired. + * + * First argument is always class of event being logged, as defined in + * user/trace.h - TRACE_CLASS_* (deprecated - do not use). + * Second argument is string literal in printf format, followed by up to 4 + * parameters (uint32_t), that are used to expand into string fromat when + * parsing log data. + * + * All compile-time accessible data (verbosity, class, source file name, line + * index and string literal) are linked into .static_log_entries section + * of binary and then extracted by smex, so they do not contribute to loadable + * image size. This way more elaborate log messages are possible and encouraged, + * for better debugging experience, without worrying about runtime performance. + */ + +/* Map the different trace_xxxx_with_ids(... ) levels to the + * _trace_event_with_ids(level_xxxx, ...) macro shared across log + * levels. + */ +#define trace_event_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_event_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \ + format, ##__VA_ARGS__) + +#define trace_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_event_atomic_with_ids(LOG_LEVEL_INFO, class, ctx, id_1, id_2, \ + format, ##__VA_ARGS__) + +#define trace_warn_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_event_with_ids(LOG_LEVEL_WARNING, class, ctx, id_1, id_2, \ + format, ##__VA_ARGS__) + +#define trace_warn_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_event_atomic_with_ids(LOG_LEVEL_WARNING, class, \ + ctx, id_1, id_2, \ + format, ##__VA_ARGS__) + +void trace_flush_dma_to_mbox(void); +void trace_on(void); +void trace_off(void); +void trace_init(struct sof *sof); + +/* All tracing macros in this file end up calling these functions in the end. */ +typedef void (*log_func_t)(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args); + +void trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args); +void trace_log_unfiltered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list args); +struct sof_ipc_trace_filter_elem *trace_filter_fill(struct sof_ipc_trace_filter_elem *elem, + struct sof_ipc_trace_filter_elem *end, + struct trace_filter *filter); +int trace_filter_update(const struct trace_filter *elem); + +#define _trace_event_with_ids(lvl, class, ctx, id_1, id_2, format, ...) \ + _log_message(trace_log_filtered, false, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__) + +#define _trace_event_atomic_with_ids(lvl, class, ctx, id_1, id_2, format, ...) \ + _log_message(trace_log_filtered, true, lvl, class, ctx, id_1, id_2, format, ##__VA_ARGS__) + +/** + * Appends one SOF dictionary entry and log statement to the ring buffer + * implementing the 'etrace' in shared memory. + * + * @param atomic_context Take the trace->lock if false. + * @param log_entry_pointer dictionary index produced by the + * _DECLARE_LOG_ENTRY macro. + * @param n_args number of va_args + */ +void mtrace_dict_entry(bool atomic_context, uint32_t log_entry_pointer, int n_args, ...); + +/** Posts a fully prepared log header + log entry */ +void mtrace_event(const char *complete_packet, uint32_t length); + +#ifdef CONFIG_TRACEM /* Send everything to shared memory too */ +# ifdef __ZEPHYR__ +/* We don't use Zephyr's dictionary yet so there's not enough space for + * DEBUG messages + */ +# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_INFO +# else +# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_DEBUG +# endif +#else /* copy only ERRORS */ +# define MTRACE_DUPLICATION_LEVEL LOG_LEVEL_ERROR +#endif /* CONFIG_TRACEM */ + +/* This function is _not_ passed the format string to save space */ +void _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry, + const struct tr_ctx *ctx, const uint32_t lvl, + uint32_t id_1, uint32_t id_2, int arg_count, ...); + +/* _log_message() */ + +#ifdef CONFIG_LIBRARY + +#include <sys/time.h> + +/* trace level used on host configurations */ +extern int host_trace_level; + +char *get_trace_class(uint32_t trace_class); +#define _log_message(ignored_log_func, atomic, level, comp_class, ctx, id_1, id_2, format, ...) \ +do { \ + (void)ctx; \ + (void)id_1; \ + (void)id_2; \ + struct timeval tv; \ + char slevel[5][4] = {"dis", "err", "wrn", "inf", "dbg"}; \ + char *msg = "(%s:%d) " format; \ + if (level <= host_trace_level) { \ + gettimeofday(&tv, NULL); \ + fprintf(stderr, "trace: [%ld.%6.6ld] <%s> ", tv.tv_sec, tv.tv_usec, \ + slevel[level]); \ + fprintf(stderr, msg, strrchr(__FILE__, '/') + 1, \ + __LINE__, ##__VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } \ +} while (0) + +#define trace_point(x) do {} while (0) + +#else /* CONFIG_LIBRARY */ + +#define trace_point(x) platform_trace_point(x) + +#define BASE_LOG_ASSERT_FAIL_MSG \ +unsupported_amount_of_params_in_trace_event\ +_thrown_from_macro_BASE_LOG_in_trace_h + +#define CT_ASSERT(COND, MESSAGE) \ + ((void)sizeof(char[1 - 2 * !(COND)])) + +#define trace_check_size_uint32(a) \ + CT_ASSERT(sizeof(a) <= sizeof(uint32_t), "error: trace argument is bigger than a uint32_t"); + +#define STATIC_ASSERT_ARG_SIZE(...) \ + META_MAP(1, trace_check_size_uint32, __VA_ARGS__) + +/** _log_message is where the memory-saving dictionary magic described + * above happens: the "format" string argument is moved to a special + * linker section and replaced by a &log_entry pointer to it. This must + * be a macro for the source location to be meaningful. + */ +#define _log_message(log_func, atomic, lvl, comp_class, ctx, id_1, id_2, format, ...) \ +do { \ + _DECLARE_LOG_ENTRY(lvl, format, comp_class, \ + META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \ + STATIC_ASSERT_ARG_SIZE(__VA_ARGS__); \ + STATIC_ASSERT(_TRACE_EVENT_MAX_ARGUMENT_COUNT >= \ + META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \ + BASE_LOG_ASSERT_FAIL_MSG \ + ); \ + _log_sofdict(log_func, atomic, &log_entry, ctx, lvl, id_1, id_2, \ + META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), ##__VA_ARGS__); \ + _log_nodict(atomic, META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \ + lvl, format, ##__VA_ARGS__); \ +} while (0) + +#ifdef __ZEPHYR__ +/* Just like XTOS, only the most urgent messages go to limited + * shared memory. + */ +#define _log_nodict(atomic, arg_count, lvl, format, ...) \ +do { \ + if ((lvl) <= MTRACE_DUPLICATION_LEVEL) \ + printk("%llu " format "\n", k_cycle_get_64(), \ + ##__VA_ARGS__); \ +} while (0) +#else +#define _log_nodict(atomic, n_args, lvl, format, ...) +#endif + +#endif /* CONFIG_LIBRARY */ + +#if CONFIG_TRACEV +/* Enable tr_dbg() statements by defining tracev_...() */ +#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_event_with_ids(LOG_LEVEL_VERBOSE, class, \ + ctx, id_1, id_2, \ + format, ##__VA_ARGS__) + +#define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_event_atomic_with_ids(LOG_LEVEL_VERBOSE, class, \ + ctx, id_1, id_2, \ + format, ##__VA_ARGS__) + +#else /* CONFIG_TRACEV */ +#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) +#define tracev_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) + +#endif /* CONFIG_TRACEV */ + +/* The _error_ level has 2, 1 or 0 backends depending on Kconfig */ +#if CONFIG_TRACEE +/* LOG_LEVEL_CRITICAL messages are duplicated to the mail box */ +#define _trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \ + _log_message(trace_log_filtered, true, LOG_LEVEL_CRITICAL, class, ctx, id_1, \ + id_2, format, ##__VA_ARGS__) +#define trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \ + _trace_error_with_ids(class, ctx, id_1, id_2, format, ##__VA_ARGS__) +#define trace_error_atomic_with_ids(...) trace_error_with_ids(__VA_ARGS__) + +#elif CONFIG_TRACE +/* Goes to trace_log_filtered() too but with a downgraded, LOG_INFO level */ +#define trace_error_with_ids(...) trace_event_with_ids(__VA_ARGS__) +#define trace_error_atomic_with_ids(...) \ + trace_event_atomic_with_ids(__VA_ARGS__) + +#endif /* CONFIG_TRACEE, CONFIG_TRACE */ + +/* tracing from device (component, pipeline, dai, ...) */ + +/** \brief Trace from a device on err level. + * + * @param get_ctx_m Macro that can retrieve trace context from dev + * @param get_id_m Macro that can retrieve device's id0 from the dev + * @param get_subid_m Macro that can retrieve device's id1 from the dev + * @param dev Device + * @param fmt Format followed by parameters + * @param ... Parameters + */ +#define trace_dev_err(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_error_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) + +/** \brief Trace from a device on warning level. */ +#define trace_dev_warn(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_warn_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) + +/** \brief Trace from a device on info level. */ +#define trace_dev_info(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) + +/** \brief Trace from a device on dbg level. */ +#define trace_dev_dbg(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + tracev_event_with_ids(_TRACE_INV_CLASS, \ + get_ctx_m(dev), get_id_m(dev), \ + get_subid_m(dev), fmt, ##__VA_ARGS__) + +/* tracing from infrastructure part */ + +#define tr_err_atomic(ctx, fmt, ...) \ + trace_error_atomic_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, \ + fmt, ##__VA_ARGS__) + +#define tr_warn_atomic(ctx, fmt, ...) \ + trace_warn_atomic_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, \ + fmt, ##__VA_ARGS__) + +#define tr_info_atomic(ctx, fmt, ...) \ + trace_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, \ + fmt, ##__VA_ARGS__) + +#define tr_dbg_atomic(ctx, fmt, ...) \ + tracev_event_atomic_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, \ + fmt, ##__VA_ARGS__) + +#define tr_err(ctx, fmt, ...) \ + trace_error_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) + +#define tr_warn(ctx, fmt, ...) \ + trace_warn_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) + +#define tr_info(ctx, fmt, ...) \ + trace_event_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) + +/* tracev_ output depends on CONFIG_TRACEV=y */ +#define tr_dbg(ctx, fmt, ...) \ + tracev_event_with_ids(_TRACE_INV_CLASS, ctx, \ + _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) + +/** Direct, low-level access to mbox / shared memory logging when DMA + * tracing is either not initialized yet or disabled or found broken for + * any reason. + * To keep it simpler than and with minimal dependencies on + * the huge number of lines above, this does not check arguments at compile + * time. + * There is neither log level filtering, throttling or any other + * advanced feature. + */ +#define mtrace_printf(log_level, format_str, ...) \ + do { \ + STATIC_ASSERT(META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__) \ + <= _TRACE_EVENT_MAX_ARGUMENT_COUNT, \ + too_many_mtrace_printf_arguments); \ + _DECLARE_LOG_ENTRY(log_level, format_str, _TRACE_INV_CLASS, \ + META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \ + mtrace_dict_entry(true, (uint32_t)&log_entry, \ + META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \ + ##__VA_ARGS__); \ + } while (0) + +#endif diff --git a/src/include/sof/trace/trace.h b/src/include/sof/trace/trace.h index e065efc4f24a..fc3aa324f847 100644 --- a/src/include/sof/trace/trace.h +++ b/src/include/sof/trace/trace.h @@ -5,6 +5,7 @@ * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> * Keyon Jie <yang.jie@linux.intel.com> * Artur Kloniecki <arturx.kloniecki@linux.intel.com> + * Karol Trzcinski <karolx.trzcinski@linux.intel.com> */ #ifndef __SOF_TRACE_TRACE_H__ @@ -15,432 +16,151 @@ "Add it to CMake's target with sof_append_relative_path_definitions." #endif -#if !CONFIG_LIBRARY && CONFIG_TRACE -#include <platform/trace/trace.h> -#endif -#include <sof/common.h> -#include <sof/sof.h> -#include <sof/trace/preproc.h> -#include <config.h> +#include <rtos/sof.h> +#include <stdbool.h> #include <stdint.h> -#if CONFIG_LIBRARY -#include <stdio.h> -#endif - -struct sof; -struct trace; - -/* bootloader trace values */ -#define TRACE_BOOT_LDR_ENTRY 0x100 -#define TRACE_BOOT_LDR_HPSRAM 0x110 -#define TRACE_BOOT_LDR_MANIFEST 0x120 -#define TRACE_BOOT_LDR_LPSRAM 0x130 -#define TRACE_BOOT_LDR_JUMP 0x150 - -#define TRACE_BOOT_LDR_PARSE_MODULE 0x210 -#define TRACE_BOOT_LDR_PARSE_SEGMENT 0x220 +#include <string.h> -/* general trace init codes - only used at boot - * when main trace is not available - */ -#define TRACE_BOOT_START 0x1000 -#define TRACE_BOOT_ARCH 0x2000 -#define TRACE_BOOT_SYS 0x3000 -#define TRACE_BOOT_PLATFORM 0x4000 - -/* system specific codes */ -#define TRACE_BOOT_SYS_HEAP (TRACE_BOOT_SYS + 0x100) -#define TRACE_BOOT_SYS_TRACES (TRACE_BOOT_SYS + 0x200) -#define TRACE_BOOT_SYS_NOTIFIER (TRACE_BOOT_SYS + 0x300) -#define TRACE_BOOT_SYS_POWER (TRACE_BOOT_SYS + 0x400) - -/* platform/device specific codes */ -#define TRACE_BOOT_PLATFORM_ENTRY (TRACE_BOOT_PLATFORM + 0x100) -#define TRACE_BOOT_PLATFORM_IRQ (TRACE_BOOT_PLATFORM + 0x110) -#define TRACE_BOOT_PLATFORM_MBOX (TRACE_BOOT_PLATFORM + 0x120) -#define TRACE_BOOT_PLATFORM_SHIM (TRACE_BOOT_PLATFORM + 0x130) -#define TRACE_BOOT_PLATFORM_PMC (TRACE_BOOT_PLATFORM + 0x140) -#define TRACE_BOOT_PLATFORM_TIMER (TRACE_BOOT_PLATFORM + 0x150) -#define TRACE_BOOT_PLATFORM_CLOCK (TRACE_BOOT_PLATFORM + 0x160) -#define TRACE_BOOT_PLATFORM_SCHED (TRACE_BOOT_PLATFORM + 0x170) -#define TRACE_BOOT_PLATFORM_AGENT (TRACE_BOOT_PLATFORM + 0x180) -#define TRACE_BOOT_PLATFORM_CPU_FREQ (TRACE_BOOT_PLATFORM + 0x190) -#define TRACE_BOOT_PLATFORM_SSP_FREQ (TRACE_BOOT_PLATFORM + 0x1A0) -#define TRACE_BOOT_PLATFORM_DMA (TRACE_BOOT_PLATFORM + 0x1B0) -#define TRACE_BOOT_PLATFORM_IPC (TRACE_BOOT_PLATFORM + 0x1C0) -#define TRACE_BOOT_PLATFORM_IDC (TRACE_BOOT_PLATFORM + 0x1D0) -#define TRACE_BOOT_PLATFORM_DAI (TRACE_BOOT_PLATFORM + 0x1E0) -#define TRACE_BOOT_PLATFORM_SSP (TRACE_BOOT_PLATFORM + 0x1F0) -#define TRACE_BOOT_PLATFORM_SPI (TRACE_BOOT_PLATFORM + 0x200) -#define TRACE_BOOT_PLATFORM_DMA_TRACE (TRACE_BOOT_PLATFORM + 0x210) - -#if CONFIG_LIBRARY - -extern int test_bench_trace; -char *get_trace_class(uint32_t trace_class); -#define _log_message(mbox, atomic, level, comp_class, id_0, id_1, id_2, \ - format, ...) \ -do { \ - (void)id_0; \ - (void)id_1; \ - (void)id_2; \ - if (test_bench_trace) { \ - char *msg = "%s " format; \ - fprintf(stderr, msg, get_trace_class(comp_class), \ - ##__VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } \ -} while (0) +#ifdef __ZEPHYR__ +#include <zephyr/kernel.h> +#include <zephyr/logging/log.h> +#endif +#if !CONFIG_LIBRARY +#include <platform/trace/trace.h> #endif +#include <sof/common.h> -#define _TRACE_EVENT_NTH_PARAMS(id_count, param_count) \ - uintptr_t log_entry \ - META_SEQ_FROM_0_TO(id_count , META_SEQ_STEP_id_uint32_t) \ - META_SEQ_FROM_0_TO(param_count, META_SEQ_STEP_param_uint32_t) - -#define _TRACE_EVENT_NTH(postfix, param_count) \ - META_FUNC_WITH_VARARGS( \ - _trace_event, META_CONCAT(postfix, param_count),\ - void, _TRACE_EVENT_NTH_PARAMS(3, param_count) \ - ) - -#define _TRACE_EVENT_NTH_DECLARE_GROUP(arg_count) \ - _TRACE_EVENT_NTH( , arg_count); \ - _TRACE_EVENT_NTH(_mbox , arg_count); \ - _TRACE_EVENT_NTH(_atomic , arg_count); \ - _TRACE_EVENT_NTH(_mbox_atomic , arg_count); - -/* Declaration of - * void _trace_event0 (uint32_t log_entry, uint32_t ids...); - * void _trace_event_mbox0 (uint32_t log_entry, uint32_t ids...); - * void _trace_event_atomic0 (uint32_t log_entry, uint32_t ids...); - * void _trace_event_mbox_atomic0(uint32_t log_entry, uint32_t ids...); - */ -_TRACE_EVENT_NTH_DECLARE_GROUP(0) - -/* Declaration of - * void _trace_event1 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox1 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_atomic1 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox_atomic1(uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - */ -_TRACE_EVENT_NTH_DECLARE_GROUP(1) - -/* Declaration of - * void _trace_event2 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox2 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_atomic2 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox_atomic2(uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - */ -_TRACE_EVENT_NTH_DECLARE_GROUP(2) - -/* Declaration of - * void _trace_event3 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox3 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_atomic3 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox_atomic3(uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - */ -_TRACE_EVENT_NTH_DECLARE_GROUP(3) - -/* Declaration of - * void _trace_event4 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox4 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_atomic4 (uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - * void _trace_event_mbox_atomic4(uint32_t log_entry, uint32_t ids..., - * uint32_t params...); - */ -_TRACE_EVENT_NTH_DECLARE_GROUP(4) +#if CONFIG_ZEPHYR_LOG || CONFIG_LIBRARY || CONFIG_ARCH_POSIX_LIBFUZZER +#include <sof/lib/uuid.h> +#endif +#include <sof/trace/preproc.h> +#include <sof/trace/trace-boot.h> -#define _TRACE_EVENT_MAX_ARGUMENT_COUNT 4 +/* Silences compiler warnings about unused variables */ +#define trace_unused(class, ctx, id_1, id_2, format, ...) \ + SOF_TRACE_UNUSED(ctx, id_1, id_2, ##__VA_ARGS__) -void trace_flush(void); -void trace_on(void); -void trace_off(void); -void trace_init(struct sof *sof); +#if defined(__ZEPHYR__) && defined(CONFIG_ZEPHYR_LOG) -static inline struct trace *trace_get(void) -{ - return sof_get()->trace; -} +#define tr_err(ctx, fmt, ...) LOG_ERR(fmt, ##__VA_ARGS__) +#define tr_warn(ctx, fmt, ...) LOG_WRN(fmt, ##__VA_ARGS__) +#define tr_info(ctx, fmt, ...) LOG_INF(fmt, ##__VA_ARGS__) +#define tr_dbg(ctx, fmt, ...) LOG_DBG(fmt, ##__VA_ARGS__) -#define trace_unused(class, id_0, id_1, id_2, format, ...) \ - UNUSED(id_0, id_1, id_2, ##__VA_ARGS__) +#elif CONFIG_TRACE -#if CONFIG_TRACE +#include "trace-soflogger.h" -/* - * trace_event macro definition - * - * trace_event() macro is used for logging events that occur at runtime. - * It comes in 2 main flavours, atomic and non-atomic. Depending of definitions - * above, it might also propagate log messages to mbox if desired. - * - * First argument is always class of event being logged, as defined in - * uapi/logging.h. - * Second argument is string literal in printf format, followed by up to 4 - * parameters (uint32_t), that are used to expand into string fromat when - * parsing log data. - * - * All compile-time accessible data (verbosity, class, source file name, line - * index and string literal) are linked into .static_log_entries section - * of binary and then extracted by rimage, so they do not contribute to loadable - * image size. This way more elaborate log messages are possible and encouraged, - * for better debugging experience, without worrying about runtime performance. - */ -#define trace_event(class, format, ...) \ - _trace_event_with_ids(LOG_LEVEL_INFO, class, 0, -1, -1, \ - format, ##__VA_ARGS__) - -#define trace_event_atomic(class, format, ...) \ - _trace_event_atomic_with_ids(LOG_LEVEL_INFO, class, 0, -1, -1, \ - format, ##__VA_ARGS__) - -#define trace_event_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_event_with_ids(LOG_LEVEL_INFO, class, id_0, id_1, id_2, \ - format, ##__VA_ARGS__) - -#define trace_event_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_event_atomic_with_ids(LOG_LEVEL_INFO, class, id_0, id_1, id_2, \ - format, ##__VA_ARGS__) - -#define trace_warn(class, format, ...) \ - _trace_event_with_ids(LOG_LEVEL_WARNING, class, 0, -1, -1, \ - format, ##__VA_ARGS__) - -#define trace_warn_atomic(class, format, ...) \ - _trace_event_atomic_with_ids(LOG_LEVEL_WARNING, class, 0, -1, -1, \ - format, ##__VA_ARGS__) - -#define trace_warn_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_event_with_ids(LOG_LEVEL_WARNING, class, id_0, id_1, id_2, \ - format, ##__VA_ARGS__) - -#define trace_warn_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_event_atomic_with_ids(LOG_LEVEL_WARNING, class, \ - id_0, id_1, id_2, \ - format, ##__VA_ARGS__) - -#if CONFIG_TRACEM -/* send all trace to mbox and local trace buffer */ -#define __mbox _mbox #else -/* send trace events only to the local trace buffer */ -#define __mbox -#endif -#define _trace_event_with_ids(lvl, class, id_0, id_1, id_2, format, ...) \ - _log_message(__mbox,, lvl, class, id_0, id_1, id_2, \ - format, ##__VA_ARGS__) - -#define _trace_event_atomic_with_ids(lvl, class, id_0, id_1, id_2, format, ...)\ - _log_message(__mbox, _atomic, lvl, class, id_0, id_1, \ - id_2, format, ##__VA_ARGS__) - -#define trace_point(x) platform_trace_point(x) - -#ifndef CONFIG_LIBRARY - -#define _DECLARE_LOG_ENTRY(lvl, format, comp_class, params) \ - __section(".static_log." #lvl) \ - static const struct { \ - uint32_t level; \ - uint32_t component_class; \ - uint32_t params_num; \ - uint32_t line_idx; \ - uint32_t file_name_len; \ - uint32_t text_len; \ - const char file_name[sizeof(RELATIVE_FILE)]; \ - const char text[sizeof(format)]; \ - } log_entry = { \ - lvl, \ - comp_class, \ - params, \ - __LINE__, \ - sizeof(RELATIVE_FILE), \ - sizeof(format), \ - RELATIVE_FILE, \ - format \ - } +#define tr_err(ctx, fmt, ...) \ + trace_unused(_TRACE_INV_CLASS, ctx, _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) +#define tr_warn(ctx, fmt, ...) \ + trace_unused(_TRACE_INV_CLASS, ctx, _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) +#define tr_info(ctx, fmt, ...) \ + trace_unused(_TRACE_INV_CLASS, ctx, _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) +#define tr_dbg(ctx, fmt, ...) \ + trace_unused(_TRACE_INV_CLASS, ctx, _TRACE_INV_ID, _TRACE_INV_ID, fmt, ##__VA_ARGS__) -#define BASE_LOG_ASSERT_FAIL_MSG \ -unsupported_amount_of_params_in_trace_event\ -_thrown_from_macro_BASE_LOG_in_trace_h - -#define BASE_LOG(function_name, id_0, id_1, id_2, entry, ...) \ -{ \ - STATIC_ASSERT( \ - _TRACE_EVENT_MAX_ARGUMENT_COUNT >= \ - META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__), \ - BASE_LOG_ASSERT_FAIL_MSG \ - ); \ - META_CONCAT(function_name, \ - META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)) \ - ((uint32_t)entry, id_0, id_1, id_2, ##__VA_ARGS__); \ -} - -#define __log_message(func_name, lvl, comp_class, id_0, id_1, id_2, \ - format, ...) \ -do { \ - _DECLARE_LOG_ENTRY(lvl, format, comp_class, \ - PP_NARG(__VA_ARGS__)); \ - BASE_LOG(func_name, id_0, id_1, id_2, &log_entry, ##__VA_ARGS__) \ -} while (0) - -#define _log_message(mbox, atomic, level, comp_class, id_0, id_1, id_2, \ - format, ...) \ - __log_message(META_CONCAT_SEQ(_trace_event, mbox, atomic), \ - level, comp_class, id_0, id_1, id_2, format, \ - ##__VA_ARGS__) -#else -#define _DECLARE_LOG_ENTRY(lvl, format, comp_class, params) \ - static const struct { \ - uint32_t level; \ - uint32_t component_class; \ - uint32_t params_num; \ - uint32_t line_idx; \ - uint32_t file_name_len; \ - uint32_t text_len; \ - const char file_name[sizeof(RELATIVE_FILE)]; \ - const char text[sizeof(format)]; \ - } log_entry = { \ - lvl, \ - comp_class, \ - params, \ - __LINE__, \ - sizeof(RELATIVE_FILE), \ - sizeof(format), \ - RELATIVE_FILE, \ - format \ - } #endif -#else -#define trace_event(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_event_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) -#define trace_event_atomic(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_event_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) - -#define trace_warn(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_warn_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) -#define trace_warn_atomic(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_warn_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) +#ifndef CONFIG_TRACE -#define trace_point(x) do {} while (0) +struct trace_filter; +struct sof; -#endif +#define trace_event_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) +#define trace_event_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) -/* verbose tracing */ -#if CONFIG_TRACEV -#define tracev_event(class, format, ...) \ - _trace_event_with_ids(LOG_LEVEL_VERBOSE, class, 0, -1, -1, \ - format, ##__VA_ARGS__) +#define trace_warn_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) +#define trace_warn_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) -#define tracev_event_atomic(class, format, ...) \ - _trace_event_atomic_with_ids(LOG_LEVEL_VERBOSE, class, 0, -1, -1, \ - format, ##__VA_ARGS__) +#define tracev_event_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) -#define tracev_event_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_event_with_ids(LOG_LEVEL_VERBOSE, class, id_0, id_1, id_2, \ - format, ##__VA_ARGS__) +#define trace_point(x) do {} while (0) -#define tracev_event_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_event_atomic_with_ids(LOG_LEVEL_VERBOSE, class, \ - id_0, id_1, id_2, \ - format, ##__VA_ARGS__) +static inline void trace_flush_dma_to_mbox(void) { } +static inline void trace_on(void) { } +static inline void trace_off(void) { } +static inline void trace_init(struct sof *sof) { } +static inline int trace_filter_update(const struct trace_filter *filter) + { return 0; } + +#define trace_error_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) +#define trace_error_atomic_with_ids(class, ctx, id_1, id_2, format, ...) \ + trace_unused(class, ctx, id_1, id_2, format, ##__VA_ARGS__) + +#define trace_dev_err(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) +#define trace_dev_warn(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) +#define trace_dev_info(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) +#define trace_dev_dbg(get_ctx_m, get_id_m, get_subid_m, dev, fmt, ...) \ + trace_event_with_ids(_TRACE_INV_CLASS, get_ctx_m(dev), \ + get_id_m(dev), get_subid_m(dev), \ + fmt, ##__VA_ARGS__) + +static inline void mtrace_printf(int log_level, const char *format_str, ...) +{ +}; -#else -#define tracev_event(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define tracev_event_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) -#define tracev_event_atomic(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define tracev_event_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) +#endif /* !CONFIG_TRACE */ -#endif +/** Default value when there is no specific pipeline, dev, dai, etc. */ +#define _TRACE_INV_ID -1 -/* error tracing */ -#if CONFIG_TRACEE -#define _trace_error_with_ids(class, id_0, id_1, id_2, format, ...) \ - _log_message(_mbox, _atomic, LOG_LEVEL_CRITICAL, class, id_0, id_1, \ - id_2, format, ##__VA_ARGS__) -#define trace_error(class, format, ...) \ - _trace_error_with_ids(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_error_with_ids(class, id_0, id_1, id_2, format, ...) \ - _trace_error_with_ids(class, id_0, id_1, id_2, format, ##__VA_ARGS__) -#define trace_error_atomic(...) trace_error(__VA_ARGS__) -#define trace_error_atomic_with_ids(...) trace_error_with_ids(__VA_ARGS__) -#elif CONFIG_TRACE -#define trace_error(...) trace_event(__VA_ARGS__) -#define trace_error_with_ids(...) trace_event_with_ids(__VA_ARGS__) -#define trace_error_atomic(...) trace_event_atomic(__VA_ARGS__) -#define trace_error_atomic_with_ids(...) \ - trace_event_atomic_with_ids(__VA_ARGS__) +/** This has been replaced in commits 6ce635aa82 and earlier by the + * DECLARE_TR_CTX, tr_ctx and component UUID system below + */ +#define _TRACE_INV_CLASS TRACE_CLASS_DEPRECATED + +/** + * Trace context. + */ +struct sof_uuid_entry; +struct tr_ctx { + const struct sof_uuid_entry *uuid_p; /**< UUID pointer, use SOF_UUID() to init */ + uint32_t level; /**< Default log level */ +}; + +#if defined(UNIT_TEST) || !defined(CONFIG_TRACE) +#define TRACE_CONTEXT_SECTION #else -#define trace_error(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_error_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) -#define trace_error_atomic(class, format, ...) \ - trace_unused(class, 0, -1, -1, format, ##__VA_ARGS__) -#define trace_error_atomic_with_ids(class, id_0, id_1, id_2, format, ...) \ - trace_unused(class, id_0, id_1, id_2, format, ##__VA_ARGS__) +#define TRACE_CONTEXT_SECTION __section(".trace_ctx") #endif -/* tracing from device (component, pipeline, dai, ...) */ +/** + * Declares trace context. + * @param ctx_name (Symbol) name. + * @param uuid UUID pointer, use SOF_UUID() to inititalize. + * @param default_log_level Default log level. + */ +#define DECLARE_TR_CTX(ctx_name, uuid, default_log_level) \ + struct tr_ctx ctx_name TRACE_CONTEXT_SECTION = { \ + .uuid_p = uuid, \ + .level = default_log_level, \ + } -/** \brief Trace from a device on err level. - * - * @param class Trace class, one of TRACE_CLASS_... - * @param get_uid_m Macro that can retrieve device's uid from the dev - * @param get_id_m Macro that can retrieve device's id0 from the dev - * @param get_subid_m Macro that can retrieve device's id1 from the dev - * @param dev Device - * @param fmt Format followed by parameters - * @param ... Parameters +/* Only define these two macros for XTOS to avoid the collision with + * zephyr/include/zephyr/logging/log.h */ -#define trace_dev_err(class, get_uid_m, get_id_m, get_subid_m, dev, fmt, ...) \ - trace_error_with_ids(class, get_uid_m(dev), get_id_m(dev), \ - get_subid_m(dev), fmt, ##__VA_ARGS__) - -/** \brief Trace from a device on warning level. */ -#define trace_dev_warn(class, get_uid_m, get_id_m, get_subid_m, dev, fmt, ...) \ - trace_warn_with_ids(class, get_uid_m(dev), get_id_m(dev), \ - get_subid_m(dev), fmt, ##__VA_ARGS__) - -/** \brief Trace from a device on info level. */ -#define trace_dev_info(class, get_uid_m, get_id_m, get_subid_m, dev, fmt, ...) \ - trace_event_with_ids(class, get_uid_m(dev), get_id_m(dev), \ - get_subid_m(dev), fmt, ##__VA_ARGS__) - -/** \brief Trace from a device on dbg level. */ -#define trace_dev_dbg(class, get_uid_m, get_id_m, get_subid_m, dev, fmt, ...) \ - tracev_event_with_ids(class, get_uid_m(dev), get_id_m(dev), \ - get_subid_m(dev), fmt, ##__VA_ARGS__) +#ifndef __ZEPHYR__ +#define LOG_MODULE_REGISTER(ctx, level) +#define LOG_MODULE_DECLARE(ctx, level) +#endif #endif /* __SOF_TRACE_TRACE_H__ */ diff --git a/src/include/sof/ut.h b/src/include/sof/ut.h index 10420588def3..9fa30fbf3a59 100644 --- a/src/include/sof/ut.h +++ b/src/include/sof/ut.h @@ -10,7 +10,7 @@ /* UT_STATIC makes function unit-testable (non-static) when built for unit tests */ -#ifdef UNIT_TEST +#if defined UNIT_TEST || defined __ZEPHYR__ || CONFIG_LIBRARY_STATIC #define UT_STATIC #else #define UT_STATIC static diff --git a/src/include/user/abi_dbg.h b/src/include/user/abi_dbg.h index 1563410c3edf..fbe1115ac81d 100644 --- a/src/include/user/abi_dbg.h +++ b/src/include/user/abi_dbg.h @@ -18,8 +18,8 @@ #ifndef __USER_ABI_DBG_H__ #define __USER_ABI_DBG_H__ -#define SOF_ABI_DBG_MAJOR 4 -#define SOF_ABI_DBG_MINOR 2 +#define SOF_ABI_DBG_MAJOR 5 +#define SOF_ABI_DBG_MINOR 3 #define SOF_ABI_DBG_PATCH 0 #define SOF_ABI_DBG_VERSION SOF_ABI_VER(SOF_ABI_DBG_MAJOR, \ diff --git a/src/include/user/audio_feature.h b/src/include/user/audio_feature.h new file mode 100644 index 000000000000..8e7791c0f3db --- /dev/null +++ b/src/include/user/audio_feature.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + */ + +#ifndef __USER_AUDIO_FEATURE_H__ +#define __USER_AUDIO_FEATURE_H__ + +/** \brief Audio feature data types. */ +enum sof_audio_feature_type { + SOF_AUDIO_FEATURE_MFCC, /**< For Mel Frequency Cepstral Coefficients */ + SOF_AUDIO_FEATURE_SOUND_DOSE_MEL, /**< For Sound Dose MEL (loudness) values */ +}; + +/** \brief Header for audio features data. */ +struct sof_audio_feature { + uint64_t stream_time_us; /**< Timestamp, relative time in microseconds */ + enum sof_audio_feature_type type; /**< Type of audio feature, as above*/ + uint32_t num_audio_features; /**< Number of audio feature structs in data */ + size_t data_size; /**< Size of data without this header */ + uint32_t reserved[4]; /**< Reserved for future use */ + int32_t data[]; /**< Start of data */ +} __attribute__((packed)); + +#endif /* __USER_AUDIO_FEATURE_H__ */ diff --git a/src/include/user/debug_stream.h b/src/include/user/debug_stream.h new file mode 100644 index 000000000000..b6d8c08cf43a --- /dev/null +++ b/src/include/user/debug_stream.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOC_DEBUG_STREAM_H__ +#define __SOC_DEBUG_STREAM_H__ + +/* + * Debug Stream is a stream protocol for passing real-time debug + * information from SOF system. It provides the framework for + * passing pieces of abstract data objects from DSP side to host side + * debugging tools. + * + * The details of Debug Stream protocol varies depending on transfer + * method, but the stream should always start with a header that + * consists of DEBUG_STREAM_IDENTIFIER and header size. + */ + +#define DEBUG_STREAM_IDENTIFIER 0x1ED15EED /* value for 'magic' */ + +struct debug_stream_hdr { + uint32_t magic; /* Magic number to recognize stream start */ + uint32_t hdr_size; /* Header size */ +} __packed; + +/* + * After the header ('hdr_size' bytes from beginning of 'magic') a + * stream of Debug Stream records should follow. Each record will + * start with a record identifier and record size, after which the + * record payload will follow. + * + * The abstract data is application specific and is passed from DSP + * debug entity to user space debug tool for decoding and + * presentation. The data is recognized by the 'id' and the 'size_words' + * describes the amount of data. The 'seqno' is a running number of sent + * record, increased by one after each record. The protocol is + * agnostic about the contents of the records. + */ + +struct debug_stream_record { + uint32_t id; /* Record id of abstract data record */ + uint32_t seqno; /* Increments after each record */ + uint32_t size_words; /* Size of the whole record in words */ + uint32_t data[]; +} __packed; + +/* Debug Stream record identifiers */ +#define DEBUG_STREAM_RECORD_ID_UNINITIALIZED 0 /* invalid record marker */ +#define DEBUG_STREAM_RECORD_ID_THREAD_INFO 1 /* Thread info record */ +#define DEBUG_STREAM_RECORD_ID_TEXT_MSG 2 /* Text message */ + +#endif /* __SOC_DEBUG_STREAM_H__ */ diff --git a/src/include/user/debug_stream_slot.h b/src/include/user/debug_stream_slot.h new file mode 100644 index 000000000000..4464c9ed56b8 --- /dev/null +++ b/src/include/user/debug_stream_slot.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOC_DEBUG_WINDOW_SLOT_H__ +#define __SOC_DEBUG_WINDOW_SLOT_H__ + +#include <user/debug_stream.h> + +/* + * This file describes how Debug Stream can be transported over debug + * window memory slot. The debug stream is an abstract media API for + * passing debug data records from SOF DSP to the host system for + * presentation. The debug stream records are described in debug_stream.h. + * + * This example describes how Debug Stream data is transferred from + * DSP to host side using a debug memory window slot. To learn more + * see soc/intel/intel_adsp/common/include/adsp_debug_window.h + * under Zephyr source tree. + * + * DEBUG_STREAM slot is reserved from SRAM window and a header is + * written in the beginning of the slot. The header is a static data + * structure that is initialized once at DSP boot time. All elements + * in bellow example are 32-bit unsigned integers: + * + * -------------------------------------------------- + * | id = DEBUG_STREAM_IDENTIFIER | + * | total_size = 4096 | + * | num_sections = CONFIG_MP_MAX_NUM_CPUS * | + * | section_descriptor [] = { | + * | { | + * | core_id = 0 | + * | size = 1344 | + * | offset = 64 | + * | } | + * | { | + * | core_id = 1 | + * | size = 1344 | + * | offset = 1344+64 | + * | } | + * | { | + * | core_id = 2 | + * | size = 1344 | + * | offset = 2*1344+64 | + * | } | + * | } | + * | <padding> | + * -------------------------------------------------- n * 64 bytes + * * CONFIG_MP_MAX_NUM_CPUS is 3 in this example + * + * The header contains generic information like identifier, total + * size, and number of sections. After the generic fields there is an + * array of section descriptors. The array has 'num_sections' number + * of elements. Each element in the array describes a circular buffer, + * one for each DSP core. + * + * The remaining memory in the debug window slot is divided between + * those sections. The buffers are not necessarily of equal size, like + * in this example. The circular buffers are all cache line aligned, + * 64 in this example. One section looks like this: + * + * -------------------------------------------------- --- + * | next_seqno = <counter for written objects> | | + * | w_ptr = <write position in 32-bit words> | 1344 bytes + * | buffer_data[1344/4-2] = { | | + * | <debug data records> | | + * | } | | + * -------------------------------------------------- --- + * + * The data records are described in debug_strem.h. In the case of + * debug window memory slot the next record should always be aligned + * to word (4-byte) boundary. + * + * The debug stream writes the records of abstract data to the + * circular buffer, and updates the w_ptr when the record is + * completely written. The host side receiver tries to keep up with the + * w_ptr and keeps track of its read position. + * + * The size of the record is written - again - after each record and + * before the next. This is to allow parsing the stream backwards in + * an overrun recovery situation. The w_ptr value is updated last, + * when the record is completely written. + */ + +#include <stdint.h> + +/* Core specific section descriptor + * + * Section descriptor defines core ID, offset and size of the circular + * buffer in the debug window slot. + */ +struct debug_stream_section_descriptor { + uint32_t core_id; /* Core ID */ + uint32_t buf_words; /* Circular buffer size in 32-bit words */ + uint32_t offset; /* Core section offset */ +} __packed; + +/* Debug window slot header for Debug Stream. + * + * The header should be written in the beginning of the slot. + */ +struct debug_stream_slot_hdr { + struct debug_stream_hdr hdr; + uint32_t total_size; /* total size of payload including all sections */ + uint32_t num_sections; /* number of core specific sections */ + struct debug_stream_section_descriptor section_desc[]; +} __packed; + +struct debug_stream_circular_buf { + uint32_t next_seqno; + uint32_t w_ptr; + uint32_t data[]; +} __aligned(CONFIG_DCACHE_LINE_SIZE); + +struct debug_stream_record; +/** + * \brief Send debug stream records over debug window slot + * + * \param[in] rec the record to be written to circular buffer + * + * The debug window slot is initialized automatically at DSP boot + * time, and the core specific circular buffer is selected + * automatically. + * + * \return 0 on success + * -ENODEV if debug stream slot is not configured + * -ENOMEM if the record is too big + */ +int debug_stream_slot_send_record(struct debug_stream_record *rec); + +#endif /* __SOC_DEBUG_WINDOW_SLOT_H__ */ diff --git a/src/include/user/debug_stream_text_msg.h b/src/include/user/debug_stream_text_msg.h new file mode 100644 index 000000000000..debfaad7042e --- /dev/null +++ b/src/include/user/debug_stream_text_msg.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOC_DEBUG_STREAM_TEXT_MSG_H__ +#define __SOC_DEBUG_STREAM_TEXT_MSG_H__ + +#include <user/debug_stream_slot.h> +#include <stdarg.h> + +/* + * Debug Stream text message. + */ +struct debug_stream_text_msg { + struct debug_stream_record hdr; + char msg[]; +} __packed; + +/* + * To send debug messages over debug stream. Enable + * CONFIG_SOF_DEBUG_STREAM_TEXT_MSG to enable this function. + */ +void ds_msg(const char *format, ...); +void ds_vamsg(const char *format, va_list ap); + +#endif /* __SOC_DEBUG_STREAM_TEXT_MSG_H__ */ diff --git a/src/include/user/debug_stream_thread_info.h b/src/include/user/debug_stream_thread_info.h new file mode 100644 index 000000000000..02990e9a1c94 --- /dev/null +++ b/src/include/user/debug_stream_thread_info.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOC_DEBUG_STREAM_THREAD_INFO_H__ +#define __SOC_DEBUG_STREAM_THREAD_INFO_H__ + +#include <user/debug_stream_slot.h> + +/* + * Debug Stream Thread Info record header, including the cpu load for the + * core, and followed by thread_count. Immediately after the header + * follows the thread fields. The thread_count indicates the number of + * thread fields. + */ +struct thread_info_record_hdr { + struct debug_stream_record hdr; + uint8_t load; /* Core's load U(0,8) fixed point value */ + uint8_t thread_count; +} __packed; + +/* + * Debug Stream Thread Info field for a single thread. + */ +struct thread_info { + uint8_t stack_usage; /* Relative stack usage U(0,8) fixed point value */ + uint8_t cpu_usage; /* Relative cpu usage U(0,8) fixed point value */ + uint8_t name_len; /* Length of name string */ + char name[]; +} __packed; + +#endif /* __SOC_DEBUG_STREAM_THREAD_INFO_H__ */ diff --git a/src/include/user/detect_test.h b/src/include/user/detect_test.h deleted file mode 100644 index 46d52af9b4a3..000000000000 --- a/src/include/user/detect_test.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - */ - -#ifndef __USER_DETECT_TEST_H__ -#define __USER_DETECT_TEST_H__ - -#include <stdint.h> - -/** IPC blob types */ -#define SOF_DETECT_TEST_CONFIG 0 -#define SOF_DETECT_TEST_MODEL 1 - -struct sof_detect_test_config { - uint32_t size; - - /** synthetic system load settings */ - uint32_t load_mips; - uint32_t load_memory_size; - /** time in ms after which detection is activated */ - uint32_t preamble_time; - - /** activation right shift, determines the speed of activation */ - uint16_t activation_shift; - - /** sample width in bits */ - int16_t sample_width; - - /** activation threshold */ - int32_t activation_threshold; - - /** default draining size in bytes */ - uint32_t history_depth; - - /** reserved for future use */ - uint32_t reserved[1]; -} __attribute__((packed)); - -/** used for binary blob size sanity checks */ -#define SOF_DETECT_TEST_MAX_CFG_SIZE sizeof(struct sof_detect_test_config) - -#endif /* __USER_DETECT_TEST_H__ */ diff --git a/src/include/user/eq.h b/src/include/user/eq.h index 57c45fcc1730..d9b49d2f9862 100644 --- a/src/include/user/eq.h +++ b/src/include/user/eq.h @@ -16,8 +16,6 @@ #define SOF_EQ_FIR_MAX_SIZE 4096 /* Max size allowed for coef data in bytes */ -#define SOF_EQ_FIR_MAX_LENGTH 192 /* Max length for individual filter */ - #define SOF_EQ_FIR_MAX_RESPONSES 8 /* A blob can define max 8 FIR EQs */ /* @@ -62,23 +60,6 @@ struct sof_eq_fir_config { int16_t data[]; } __attribute__((packed)); -struct sof_eq_fir_coef_data { - int16_t length; /* Number of FIR taps */ - int16_t out_shift; /* Amount of right shifts at output */ - - /* reserved */ - uint32_t reserved[4]; - - int16_t coef[]; /* FIR coefficients */ -} __attribute__((packed)); - -/* In the struct above there's two 16 bit words (length, shift) and four - * reserved 32 bit words before the actual FIR coefficients. This information - * is used in parsing of the configuration blob. - */ -#define SOF_EQ_FIR_COEF_NHEADER \ - (sizeof(struct sof_eq_fir_coef_data) / sizeof(int16_t)) - /* IIR EQ type */ #define SOF_EQ_IIR_IDX_SWITCH 0 @@ -133,7 +114,7 @@ struct sof_eq_iir_config { int32_t data[]; /* eq_assign[channels], eq 0, eq 1, ... */ } __attribute__((packed)); -struct sof_eq_iir_header_df2t { +struct sof_eq_iir_header { uint32_t num_sections; uint32_t num_sections_in_series; @@ -143,7 +124,7 @@ struct sof_eq_iir_header_df2t { int32_t biquads[]; /* Repeated biquad coefficients */ } __attribute__((packed)); -struct sof_eq_iir_biquad_df2t { +struct sof_eq_iir_biquad { int32_t a2; /* Q2.30 */ int32_t a1; /* Q2.30 */ int32_t b2; /* Q2.30 */ @@ -154,20 +135,20 @@ struct sof_eq_iir_biquad_df2t { } __attribute__((packed)); /* A full 22th order equalizer with 11 biquads cover octave bands 1-11 in - * in the 0 - 20 kHz bandwidth. + * the 0 - 20 kHz bandwidth. */ -#define SOF_EQ_IIR_DF2T_BIQUADS_MAX 11 +#define SOF_EQ_IIR_BIQUADS_MAX 11 -/* The number of int32_t words in sof_eq_iir_header_df2t: +/* The number of int32_t words in sof_eq_iir_header: * num_sections, num_sections_in_series, reserved[4] */ -#define SOF_EQ_IIR_NHEADER_DF2T \ - (sizeof(struct sof_eq_iir_header_df2t) / sizeof(int32_t)) +#define SOF_EQ_IIR_NHEADER \ + (sizeof(struct sof_eq_iir_header) / sizeof(int32_t)) -/* The number of int32_t words in sof_eq_iir_biquad_df2t: +/* The number of int32_t words in sof_eq_iir_biquad: * a2, a1, b2, b1, b0, output_shift, output_gain */ -#define SOF_EQ_IIR_NBIQUAD_DF2T \ - (sizeof(struct sof_eq_iir_biquad_df2t) / sizeof(int32_t)) +#define SOF_EQ_IIR_NBIQUAD \ + (sizeof(struct sof_eq_iir_biquad) / sizeof(int32_t)) #endif /* __USER_EQ_H__ */ diff --git a/src/include/user/fir.h b/src/include/user/fir.h new file mode 100644 index 000000000000..4536a469eee0 --- /dev/null +++ b/src/include/user/fir.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __USER_FIR_H__ +#define __USER_FIR_H__ + +#include <stdint.h> + +#define SOF_FIR_MAX_LENGTH 256 /* Max length for individual filter */ + +struct sof_fir_coef_data { + int16_t length; /* Number of FIR taps */ + int16_t out_shift; /* Amount of right shifts at output */ + + /* reserved */ + uint32_t reserved[4]; + + int16_t coef[]; /* FIR coefficients */ +} __attribute__((packed)); + +/* In the struct above there's two 16 bit words (length, shift) and four + * reserved 32 bit words before the actual FIR coefficients. This information + * is used in parsing of the configuration blob. + */ +#define SOF_FIR_COEF_NHEADER \ + (sizeof(struct sof_fir_coef_data) / sizeof(int16_t)) + +#endif /* __USER_FIR_H__ */ diff --git a/src/include/user/igo_nr.h b/src/include/user/igo_nr.h new file mode 100644 index 000000000000..85c3756884d8 --- /dev/null +++ b/src/include/user/igo_nr.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intelligo Technology Inc. All rights reserved. + * + * Author: Fu-Yun TSUO <fy.tsuo@intelli-go.com> + */ + +#ifndef __USER_IGO_NR_H__ +#define __USER_IGO_NR_H__ + +#include <stdint.h> + +struct IGO_PARAMS { + uint32_t igo_params_ver; + uint32_t dump_data; + uint32_t nr_bypass; + uint32_t nr_mode1_en; + uint32_t nr_mode3_en; + uint32_t nr_ul_enable; + uint32_t agc_gain; + uint32_t nr_voice_str; + uint32_t nr_level; + uint32_t nr_mode1_floor; + uint32_t nr_mode1_od; + uint32_t nr_mode1_pp_param7; + uint32_t nr_mode1_pp_param8; + uint32_t nr_mode1_pp_param10; + uint32_t nr_mode3_floor; + uint32_t nr_mode1_pp_param53; +} __attribute__((packed)); + +struct sof_igo_nr_config { + /* reserved */ + struct IGO_PARAMS igo_params; + uint32_t active_channel_idx; + int16_t data[]; +} __attribute__((packed)); + +#endif /* __USER_IGO_NR_H__ */ diff --git a/src/include/user/manifest.h b/src/include/user/manifest.h deleted file mode 100644 index bd598f907efe..000000000000 --- a/src/include/user/manifest.h +++ /dev/null @@ -1,228 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -/** - * \file include/user/manifest.h - * \brief FW Image Manifest definitions. - * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __USER_MANIFEST_H__ -#define __USER_MANIFEST_H__ - -#include <stdint.h> - -/* start offset for base FW module */ -#define SOF_MAN_ELF_TEXT_OFFSET 0x2000 - -/* FW Extended Manifest Header id = $AE1 */ -#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124 - -/* module type load type */ -#define SOF_MAN_MOD_TYPE_BUILTIN 0 -#define SOF_MAN_MOD_TYPE_MODULE 1 - -struct sof_man_module_type { - uint32_t load_type:4; /* SOF_MAN_MOD_TYPE_ */ - uint32_t auto_start:1; - uint32_t domain_ll:1; - uint32_t domain_dp:1; - uint32_t rsvd_:25; -}; - -/* segment flags.type */ -#define SOF_MAN_SEGMENT_TEXT 0 -#define SOF_MAN_SEGMENT_RODATA 1 -#define SOF_MAN_SEGMENT_DATA 1 -#define SOF_MAN_SEGMENT_BSS 2 -#define SOF_MAN_SEGMENT_EMPTY 15 - -union sof_man_segment_flags { - uint32_t ul; - struct { - uint32_t contents:1; - uint32_t alloc:1; - uint32_t load:1; - uint32_t readonly:1; - uint32_t code:1; - uint32_t data:1; - uint32_t _rsvd0:2; - uint32_t type:4; /* MAN_SEGMENT_ */ - uint32_t _rsvd1:4; - uint32_t length:16; /* of segment in pages */ - } r; -} __attribute__((packed)); - -/* - * Module segment descriptor. Used by ROM - Immutable. - */ -struct sof_man_segment_desc { - union sof_man_segment_flags flags; - uint32_t v_base_addr; - uint32_t file_offset; -} __attribute__((packed)); - -/* - * The firmware binary can be split into several modules. - */ - -#define SOF_MAN_MOD_ID_LEN 4 -#define SOF_MAN_MOD_NAME_LEN 8 -#define SOF_MAN_MOD_SHA256_LEN 32 -#define SOF_MAN_MOD_ID {'$', 'A', 'M', 'E'} - -/* - * Each module has an entry in the FW header. Used by ROM - Immutable. - */ -struct sof_man_module { - uint8_t struct_id[SOF_MAN_MOD_ID_LEN]; /* SOF_MAN_MOD_ID */ - uint8_t name[SOF_MAN_MOD_NAME_LEN]; - uint8_t uuid[16]; - struct sof_man_module_type type; - uint8_t hash[SOF_MAN_MOD_SHA256_LEN]; - uint32_t entry_point; - uint16_t cfg_offset; - uint16_t cfg_count; - uint32_t affinity_mask; - uint16_t instance_max_count; /* max number of instances */ - uint16_t instance_bss_size; /* instance (pages) */ - struct sof_man_segment_desc segment[3]; -} __attribute__((packed)); - -/* - * Each module has a configuration in the FW header. Used by ROM - Immutable. - */ -struct sof_man_mod_config { - uint32_t par[4]; /* module parameters */ - uint32_t is_pages; /* actual size of instance .bss (pages) */ - uint32_t cps; /* cycles per second */ - uint32_t ibs; /* input buffer size (bytes) */ - uint32_t obs; /* output buffer size (bytes) */ - uint32_t module_flags; /* flags, reserved for future use */ - uint32_t cpc; /* cycles per single run */ - uint32_t obls; /* output block size, reserved for future use */ -} __attribute__((packed)); - -/* - * FW Manifest Header - */ - -#define SOF_MAN_FW_HDR_FW_NAME_LEN 8 -#define SOF_MAN_FW_HDR_ID {'$', 'A', 'M', '1'} -#define SOF_MAN_FW_HDR_NAME "ADSPFW" -#define SOF_MAN_FW_HDR_FLAGS 0x0 -#define SOF_MAN_FW_HDR_FEATURES 0x1ff - -/* - * The firmware has a standard header that is checked by the ROM on firmware - * loading. preload_page_count is used by DMA code loader and is entire - * image size on CNL. i.e. CNL: total size of the binary’s .text and .rodata - * Used by ROM - Immutable. - */ -struct sof_man_fw_header { - uint8_t header_id[4]; - uint32_t header_len; - uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN]; - /* number of pages of preloaded image loaded by driver */ - uint32_t preload_page_count; - uint32_t fw_image_flags; - uint32_t feature_mask; - uint16_t major_version; - uint16_t minor_version; - uint16_t hotfix_version; - uint16_t build_version; - uint32_t num_module_entries; - uint32_t hw_buf_base_addr; - uint32_t hw_buf_length; - /* target address for binary loading as offset in IMR - must be == base offset */ - uint32_t load_offset; -} __attribute__((packed)); - -/* - * Firmware manifest descriptor. This can contain N modules and N module - * configs. Used by ROM - Immutable. - */ -struct sof_man_fw_desc { - struct sof_man_fw_header header; - - /* Warning - hack for module arrays. For some unknown reason the we - * have a variable size array of struct man_module followed by a - * variable size array of struct mod_config. These should have been - * merged into a variable array of a parent structure. We have to hack - * around this in many places.... - * - * struct sof_man_module man_module[]; - * struct sof_man_mod_config mod_config[]; - */ - -} __attribute__((packed)); - -#define SOF_MAN_COMP_SHA256_LEN 32 -#define SOF_MAN_COMP_SHA384_LEN 48 - -/* - * Component Descriptor for manifest v1.8. Used by ROM - Immutable. - */ -struct sof_man_component_desc_v1_8 { - uint32_t reserved[2]; /* all 0 */ - uint32_t version; - uint8_t hash[SOF_MAN_COMP_SHA256_LEN]; - uint32_t base_offset; - uint32_t limit_offset; - uint32_t attributes[4]; -} __attribute__((packed)); - -/* - * Audio DSP extended metadata for manifest v1.8. Used by ROM - Immutable. - */ -struct sof_man_adsp_meta_file_ext_v1_8 { - uint32_t ext_type; /* always 17 for ADSP extension */ - uint32_t ext_len; - uint32_t imr_type; - uint8_t reserved[16]; /* all 0 */ - struct sof_man_component_desc_v1_8 comp_desc[1]; -} __attribute__((packed)); - -/* - * Component Descriptor for manifest v2.5. Used by ROM - Immutable. - */ -struct sof_man_component_desc_v2_5 { - uint32_t reserved[2]; /* all 0 */ - uint32_t version; - uint8_t hash[SOF_MAN_COMP_SHA384_LEN]; - uint32_t base_offset; - uint32_t limit_offset; - uint32_t attributes[4]; -} __attribute__((packed)); - -/* - * Audio DSP extended metadata for manifest v2.5. Used by ROM - Immutable. - */ -struct sof_man_adsp_meta_file_ext_v2_5 { - uint32_t ext_type; /* always 17 for ADSP extension */ - uint32_t ext_len; - uint32_t imr_type; - uint8_t reserved[16]; /* all 0 */ - struct sof_man_component_desc_v2_5 comp_desc[1]; -} __attribute__((packed)); - -/* - * Module Manifest for rimage module metadata. Not used by ROM. - */ -struct sof_man_module_manifest { - struct sof_man_module module; - uint32_t text_size; -}; - -/* - * Module offset in manifest. - */ -#define SOF_MAN_MODULE_OFFSET(index) \ - (sizeof(struct sof_man_fw_header) + \ - (index) * sizeof(struct sof_man_module)) - -#endif /* __USER_MANIFEST_H__ */ diff --git a/src/include/user/mfcc.h b/src/include/user/mfcc.h new file mode 100644 index 000000000000..8a0defcd9883 --- /dev/null +++ b/src/include/user/mfcc.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#ifndef __USER_MFCC_H__ +#define __USER_MFCC_H__ + +#include <stdbool.h> +#include <stdint.h> + +#define MFCC_BLACKMAN_A0 Q_CONVERT_FLOAT(0.42, 15) /* For MFCC */ + +#define SOF_MFCC_CONFIG_MAX_SIZE 256 /* Max size for configuration data in bytes */ + +enum sof_mfcc_fft_pad_type { + MFCC_PAD_END = 0, + MFCC_PAD_CENTER = 1, + MFCC_PAD_START = 2, +}; + +enum sof_mfcc_fft_window_type { + MFCC_RECTANGULAR_WINDOW = 0, + MFCC_BLACKMAN_WINDOW = 1, + MFCC_HAMMING_WINDOW = 2, + MFCC_HANN_WINDOW = 3, + MFCC_POVEY_WINDOW = 4, +}; + +enum sof_mfcc_mel_log_type { + MEL_LOG_IS_LOG = 0, + MEL_LOG_IS_LOG10 = 1, + MEL_LOG_IS_DB = 2 +}; + +enum sof_mfcc_mel_norm_type { + MFCC_MEL_NORM_NONE = 0, + MFCC_MEL_NORM_SLANEY = 1, +}; + +enum sof_mfcc_dct_type { + MFCC_DCT_I = 0, + MFCC_DCT_II = 1, +}; + +/* + * Configuration blob + */ +struct sof_mfcc_config { + uint32_t size; /**< Size of this struct in bytes */ + int16_t mel_offset; /**< Q8.7 default 0, use 4.0 for Whisper */ + int16_t mel_scale; /**< Q4.12 default 1.0, use 0.25 for Whisper */ + int16_t mmax_init; /**< Q8.7 default 0, with dynamic_mmax false, can sim. Whisper mmax */ + int16_t mmax_coef; /**< Q1.15 decay coefficient for dynamic mmax, a small value for slow */ + uint32_t reserved[6]; + int32_t sample_frequency; /**< Hz. e.g. 16000 */ + int32_t pmin; /**< Q1.31 linear power, limit minimum Mel energy, e.g. 1e-9 */ + enum sof_mfcc_mel_log_type mel_log; /**< Use MEL_LOG_IS_LOG, LOG10 or DB*/ + enum sof_mfcc_mel_norm_type norm; /**< Use MEL_NORM_SLANEY or MEL_NORM_NONE */ + enum sof_mfcc_fft_pad_type pad; /**< Use PAD_END, PAD_CENTER, PAD_START */ + enum sof_mfcc_fft_window_type window; /**< Use RECTANGULAR_WINDOW, BLACKMAN_WINDOW, etc. */ + enum sof_mfcc_dct_type dct; /**< Must be DCT_II */ + int16_t blackman_coef; /**< Q1.15, typically set to 0.42 for BLACKMAN_WINDOW */ + int16_t cepstral_lifter; /**< Q7.9, e.g. 22.0 */ + int16_t channel; /**< -1 expect mono, 0 left, 1 right, ... */ + int16_t dither; /**< Reserved, no support */ + int16_t frame_length; /**< samples, e.g. 400 for 25 ms @ 16 kHz*/ + int16_t frame_shift; /**< samples, e.g. 160 for 10 ms @ 16 kHz */ + int16_t high_freq; /**< Hz, set 0 for Nyquist frequency */ + int16_t low_freq; /**< Hz, eg. 20 */ + int16_t num_ceps; /**< Number of cepstral coefficients, e.g. 13 */ + int16_t num_mel_bins; /**< Number of internal Mel bands, e.g. 23 */ + int16_t preemphasis_coefficient; /**< Q1.15, e.g. 0.97, or 0 for disable */ + int16_t top_db; /**< Q8.7 dB, limit min. Mel energies to chunk max - top_dB, e.g. 80 */ + int16_t vtln_high; /**< Reserved, no support */ + int16_t vtln_low; /**< Reserved, no support */ + int16_t vtln_warp; /**< Reserved, no support */ + bool htk_compat; /**< Must be false */ + bool raw_energy; /**< Reserved, no support */ + bool remove_dc_offset; /**< Reserved, no support */ + bool round_to_power_of_two; /**< Must be true (1) */ + bool snip_edges; /**< Must be true (1) */ + bool subtract_mean; /**< Must be false (0) */ + bool use_energy; /**< Must be false (0) */ + bool dynamic_mmax; /**< Track max Mel value for clamp with top_db value */ + bool reserved_bool2; + bool reserved_bool3; +} __attribute__((packed)); + +#endif /* __USER_MFCC_H__ */ diff --git a/src/include/user/rtnr.h b/src/include/user/rtnr.h new file mode 100644 index 000000000000..f76ffb175e5a --- /dev/null +++ b/src/include/user/rtnr.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. + * + * Author: Ming Jen Tai <mingjen_tai@realtek.com> + */ + +#ifndef __USER_RTNR_H__ +#define __USER_RTNR_H__ + +#include <stdint.h> + +#define SOF_RTNR_MAX_SIZE 256 + +struct sof_rtnr_params { + /* 1 to enable RTNR, 0 to disable it */ + int32_t enabled; + uint32_t sample_rate; + int32_t reserved; +} __attribute__((packed, aligned(4))); + +struct sof_rtnr_config { + uint32_t size; + + /* reserved */ + uint32_t reserved[4]; + + struct sof_rtnr_params params; +} __attribute__((packed, aligned(4))); + +#endif /* __USER_RTNR_H__ */ + diff --git a/src/include/user/smart_amp.h b/src/include/user/smart_amp.h new file mode 100644 index 000000000000..d555b9265c90 --- /dev/null +++ b/src/include/user/smart_amp.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Maxim Integrated. All rights reserved. + * + * Author: Ryan Lee <ryans.lee@maximintegrated.com> + */ + +#ifndef __USER_SMART_AMP_H__ +#define __USER_SMART_AMP_H__ + +#include <stdint.h> + +/* smart amp component configuration data. */ +struct sof_smart_amp_config { + /* total config size in bytes */ + uint32_t size; + /* Number of smart amp feedback channel */ + uint32_t feedback_channels; + /* channel map for audio source */ + int8_t source_ch_map[PLATFORM_MAX_CHANNELS]; + /* channel map for audio feedback */ + int8_t feedback_ch_map[PLATFORM_MAX_CHANNELS]; +}; + +#endif /* __USER_SMART_AMP_H__ */ diff --git a/src/include/user/sound_dose.h b/src/include/user/sound_dose.h new file mode 100644 index 000000000000..a2479eb79951 --- /dev/null +++ b/src/include/user/sound_dose.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + * + */ + +#include <kernel/abi.h> +#include <kernel/header.h> +#include <user/audio_feature.h> + +#ifndef __USER_SOUND_DOSE_H__ +#define __USER_SOUND_DOSE_H__ + +#define SOF_SOUND_DOSE_SETUP_PARAM_ID 0 +#define SOF_SOUND_DOSE_VOLUME_PARAM_ID 1 +#define SOF_SOUND_DOSE_GAIN_PARAM_ID 2 +#define SOF_SOUND_DOSE_PAYLOAD_PARAM_ID 3 + +#define SOF_SOUND_DOSE_SENS_MIN_DB (-10 * 100) /* -10 to +130 dB */ +#define SOF_SOUND_DOSE_SENS_MAX_DB (130 * 100) +#define SOF_SOUND_DOSE_VOLUME_MIN_DB (-100 * 100) /* -100 to +40 dB */ +#define SOF_SOUND_DOSE_VOLUME_MAX_DB (40 * 100) +#define SOF_SOUND_DOSE_GAIN_MIN_DB (-100 * 100) /* -100 to 0 dB */ +#define SOF_SOUND_DOSE_GAIN_MAX_DB (0 * 100) + +struct sof_sound_dose { + int16_t mel_value; /* Decibels x100, e.g. 85 dB is 8500 */ + int16_t dbfs_value; /* Decibels x100 */ + int16_t current_sens_dbfs_dbspl; /* Decibels x100 */ + int16_t current_volume_offset; /* Decibels x100 */ + int16_t current_gain; /* Decibels x100 */ + uint16_t reserved16; /**< reserved for future use */ + uint32_t reserved32[4]; /**< reserved for future use */ +} __attribute__((packed)); + +struct sound_dose_setup_config { + int16_t sens_dbfs_dbspl; /* Decibels x100 */ + int16_t reserved; +} __attribute__((packed)); + +struct sound_dose_volume_config { + int16_t volume_offset; /* Decibels x100 */ + int16_t reserved; +} __attribute__((packed)); + +struct sound_dose_gain_config { + int16_t gain; /* Decibels x100 */ + int16_t reserved; +} __attribute__((packed)); + +#endif /* __USER_SOUND_DOSE_H__ */ diff --git a/src/include/user/trace.h b/src/include/user/trace.h index b04996ab45d7..6550a91ba6ee 100644 --- a/src/include/user/trace.h +++ b/src/include/user/trace.h @@ -11,60 +11,8 @@ #include <stdint.h> -/* - * Host system time. - * - * This property is used by the driver to pass down information about - * current system time. It is expressed in us. - * FW translates timestamps (in log entries, probe pockets) to this time - * domain. - * - * (cavs: SystemTime). - */ -struct system_time { - uint32_t val_l; /* Lower dword of current host time value */ - uint32_t val_u; /* Upper dword of current host time value */ -} __attribute__((packed)); - /* trace event classes - high 8 bits*/ -#define TRACE_CLASS_IRQ (1 << 24) -#define TRACE_CLASS_IPC (2 << 24) -#define TRACE_CLASS_PIPE (3 << 24) -#define _TRACE_UNUSED_4 (4 << 24) -#define TRACE_CLASS_DAI (5 << 24) -#define TRACE_CLASS_DMA (6 << 24) -#define _TRACE_UNUSED_7 (7 << 24) -#define TRACE_CLASS_COMP (8 << 24) -#define TRACE_CLASS_WAIT (9 << 24) -#define TRACE_CLASS_LOCK (10 << 24) -#define TRACE_CLASS_MEM (11 << 24) -#define _TRACE_UNUSED_12 (12 << 24) -#define TRACE_CLASS_BUFFER (13 << 24) -#define _TRACE_UNUSED_14 (14 << 24) -#define _TRACE_UNUSED_15 (15 << 24) -#define _TRACE_UNUSED_16 (16 << 24) -#define _TRACE_UNUSED_17 (17 << 24) -#define _TRACE_UNUSED_18 (18 << 24) -#define _TRACE_UNUSED_19 (19 << 24) -#define _TRACE_UNUSED_20 (20 << 24) -#define TRACE_CLASS_SA (21 << 24) -#define _TRACE_UNUSED_22 (22 << 24) -#define TRACE_CLASS_POWER (23 << 24) -#define TRACE_CLASS_IDC (24 << 24) -#define TRACE_CLASS_CPU (25 << 24) -#define TRACE_CLASS_CLK (26 << 24) -#define TRACE_CLASS_EDF (27 << 24) -#define _TRACE_UNUSED_28 (28 << 24) -#define _TRACE_UNUSED_29 (29 << 24) -#define TRACE_CLASS_SCHEDULE (30 << 24) -#define TRACE_CLASS_SCHEDULE_LL (31 << 24) -#define _TRACE_UNUSED_32 (32 << 24) -#define _TRACE_UNUSED_33 (33 << 24) -#define TRACE_CLASS_CHMAP (34 << 24) -#define _TRACE_UNUSED_35 (35 << 24) -#define TRACE_CLASS_NOTIFIER (36 << 24) -#define TRACE_CLASS_MN (37 << 24) -#define TRACE_CLASS_PROBE (38 << 24) +#define TRACE_CLASS_DEPRECATED (0) #define LOG_ENABLE 1 /* Enable logging */ #define LOG_DISABLE 0 /* Disable logging */ @@ -76,26 +24,10 @@ struct system_time { #define LOG_LEVEL_DEBUG 4 #define LOG_LEVEL_VERBOSE LOG_LEVEL_DEBUG -/* - * Layout of a log fifo. - */ -struct log_buffer_layout { - uint32_t read_ptr; /*read pointer */ - uint32_t write_ptr; /* write pointer */ - uint32_t buffer[0]; /* buffer */ -} __attribute__((packed)); - -/* - * Log buffer status reported by FW. - */ -struct log_buffer_status { - uint32_t core_id; /* ID of core that logged to other half */ -} __attribute__((packed)); - -#define TRACE_ID_LENGTH 12 +#define TRACE_ID_LENGTH 12 /* bit field length */ /* - * Log entry header. + * Log entry protocol header. * * The header is followed by an array of arguments (uint32_t[]). * Number of arguments is specified by the params_num field of log_entry diff --git a/src/init/CMakeLists.txt b/src/init/CMakeLists.txt index 17dab5792dd9..5bf15761fa29 100644 --- a/src/init/CMakeLists.txt +++ b/src/init/CMakeLists.txt @@ -1,3 +1,11 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof init.c) +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + +zephyr_library_sources( + init.c + ext_manifest.c +) + +endif() # Zephyr diff --git a/src/init/README.md b/src/init/README.md new file mode 100644 index 000000000000..1df29a7b6223 --- /dev/null +++ b/src/init/README.md @@ -0,0 +1,156 @@ +# DSP Initialization (`src/init`) + +The `src/init` directory contains the generic digital signal processor (DSP) initialization code and firmware metadata structures for Sound Open Firmware (SOF). It acts as the bridge between the underlying RTOS (Zephyr) boot phase and the SOF-specific task scheduling and processing pipelines. + +## Architecture and Boot Flow + +The firmware initialization architecture relies on the Zephyr RTOS boot sequence. Zephyr handles the very early hardware setup and kernel initialization before invoking SOF-specific routines via Zephyr's `SYS_INIT` macros. + +### Primary Core Boot Sequence + +The primary entry point for SOF system initialization is `sof_init()`, registered to run at Zephyr's `POST_KERNEL` initialization level. This ensures basic OS primitives (like memory allocators and threads) are available before SOF starts. + +`sof_init()` delegates to `primary_core_init()`, which executes the following sequence: + +```mermaid +sequenceDiagram + participant Zephyr as Zephyr RTOS + participant sof_init as sof_init (src/init.c) + participant primary_core as primary_core_init + participant trace as trace_init + participant notify as init_system_notify + participant pm as pm_runtime_init + participant platform as platform_init + participant ams as ams_init + participant mbox as mailbox (IPC4) + participant task as task_main_start + + Zephyr->>sof_init: SYS_INIT (POST_KERNEL) + sof_init->>primary_core: Initialize Primary Core Context + + primary_core->>trace: Setup DMA Tracing & Logging + primary_core->>notify: Setup System Notifiers + primary_core->>pm: Initialize Runtime Power Management + + primary_core->>platform: Platform-Specific HW Config + note right of platform: e.g., interrupts, IPC windows (Intel, i.MX) + + primary_core->>ams: Init Asynchronous Messaging Service + + primary_core->>mbox: Set Firmware Registers ABI Version + + primary_core->>task: Start SOF Main Processing Task Loop +``` + +1. **Context Initialization**: Sets up the global `struct sof` context. +2. **Logging and Tracing**: Initializes Zephyr's logging timestamps and SOF's DMA trace infrastructure (`trace_init()`), printing the firmware version and ABI banner. +3. **System Subsystems**: + - Initializes the system notifier (`init_system_notify()`) for inter-component messaging. + - Sets up runtime power management (`pm_runtime_init()`). +4. **Platform-Specific Initialization**: Calls `platform_init()` to allow the specific hardware platform (e.g., Intel cAVS, i.MX) to configure its hardware IPs, interrupts, and IPC mailbox memory windows. +5. **Architectural Handoff**: For IPC4, it sets the Firmware Registers ABI version in the mailbox. It may also unpack boot manifests if configured. +6. **Task Scheduler**: Finally, it calls `task_main_start()` to kick off the main SOF processing task loop. + +### Secondary Core Boot Sequence + +For multi-core DSP platforms, secondary cores execute `secondary_core_init()`: + +```mermaid +sequenceDiagram + participant ZephyrN as Zephyr RTOS (Core N) + participant sci as secondary_core_init + participant check as check_restore + participant notify as init_system_notify + participant ll as scheduler_init_ll + participant dp as scheduler_dp_init + participant idc as idc_init + + ZephyrN->>sci: Core Wake/Boot + sci->>check: Cold boot or power restore? + + alt is Power Restore (e.g. D0ix wake) + sci->>sci: secondary_core_restore()<br>(Skip full init) + else is Cold Boot + sci->>notify: Setup Local Core Notifiers + + sci->>ll: Init Low-Latency (LL) Timer Domain + sci->>ll: Init LL DMA Domain (if applicable) + sci->>dp: Init Data Processing (DP) Scheduler + + sci->>idc: Init Inter-Domain Communication (IDC) + end +``` + +1. **Power State Checking**: It checks if the core is cold booting or resuming from a low-power retention/restore state (e.g., D0ix) via `check_restore()`. In the restore case, it restores state without re-allocating core structures; in the cold-boot case, it follows the full initialization path described below. +2. **Local Subsystem Setup**: Sets up system notifiers for the local core. +3. **Scheduler Setup**: Initializes the Low-Latency (LL) and Data Processing (DP) schedulers on the secondary core. +4. **Inter-Core Communication**: Initializes the Inter-Domain Communication (IDC) mechanism (`idc_init()`), allowing cross-core messaging. + +### Firmware Extended Manifest (`ext_manifest.c`) + +This directory also provides the extended manifest implementation. The manifest consists of structured metadata embedded into the `.fw_metadata` section of the firmware binary. + +```mermaid +classDiagram + direction LR + + class fw_metadata { + <<Section>> + +ext_man_fw_ver + +ext_man_cc_ver + +ext_man_probe + +ext_man_dbg_info + +ext_man_config + } + + class ext_man_elem_header { + +uint32_t type + +uint32_t elem_size + } + + class ext_man_fw_version { + +ext_man_elem_header hdr + +sof_ipc_fw_version version + +uint32_t flags + } + + class ext_man_cc_version { + +ext_man_elem_header hdr + +sof_ipc_cc_version cc_version + } + + class ext_man_probe_support { + +ext_man_elem_header hdr + +sof_ipc_probe_support probe + } + + class ext_man_dbg_abi { + +ext_man_elem_header hdr + +sof_ipc_user_abi_version dbg_abi + } + + class ext_man_config_data { + +ext_man_elem_header hdr + +config_elem elems[] + } + + fw_metadata *-- ext_man_fw_version + fw_metadata *-- ext_man_cc_version + fw_metadata *-- ext_man_probe_support + fw_metadata *-- ext_man_dbg_abi + fw_metadata *-- ext_man_config_data + + ext_man_fw_version *-- ext_man_elem_header + ext_man_cc_version *-- ext_man_elem_header + ext_man_probe_support *-- ext_man_elem_header + ext_man_dbg_abi *-- ext_man_elem_header + ext_man_config_data *-- ext_man_elem_header +``` + +When the host OS (e.g., Linux SOF driver) parses the firmware binary before loading it, it reads these manifest structures to discover firmware capabilities dynamically. The manifest includes: + +- **Firmware Version**: Major, minor, micro, tag, and build hashes (`ext_man_fw_ver`). +- **Compiler Version**: Details of the toolchain used to compile the firmware (`ext_man_cc_ver`). +- **Probe Info**: Extraction probe configurations and limits (`ext_man_probe`). +- **Debug ABI**: Supported debugger ABI versions (`ext_man_dbg_info`). +- **Configuration Dictionary**: Compile-time enabled features and sizing parameters (e.g., `SOF_IPC_MSG_MAX_SIZE`). diff --git a/src/init/ext_manifest.c b/src/init/ext_manifest.c new file mode 100644 index 000000000000..5c57d53d748e --- /dev/null +++ b/src/init/ext_manifest.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> +// + +#include <rtos/bit.h> +#include <sof/common.h> +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <user/abi_dbg.h> +#include <sof_versions.h> + +const struct ext_man_fw_version ext_man_fw_ver + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { + .hdr.type = EXT_MAN_ELEM_FW_VERSION, + .hdr.elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_fw_version), + EXT_MAN_ALIGN), + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +/* opt-in; reproducible build by default */ +#if BLD_COUNTERS + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#else + .build = -1, + .date = "dtermin.\0", + .time = "extman\0", +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +const struct ext_man_cc_version ext_man_cc_ver + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { + .hdr.type = EXT_MAN_ELEM_CC_VERSION, + .hdr.elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_cc_version), + EXT_MAN_ALIGN), + .cc_version = { + .ext_hdr.hdr.size = sizeof(struct sof_ipc_cc_version), + .ext_hdr.hdr.cmd = SOF_IPC_FW_READY, + .ext_hdr.type = SOF_IPC_EXT_CC_INFO, + .micro = CC_MICRO, + .minor = CC_MINOR, + .major = CC_MAJOR, + .name = CC_NAME "\0", ///< eg. "XCC", "\0" is needed when + ///< sizeof(CC_NAME)-1 == sizeof(.name) + .optim = CC_OPTIMIZE_FLAGS "\0", ///< eg. "O2" + .desc = CC_DESC "\0", ///< eg. " RG-2017.8-linux" + }, +}; + +#if CONFIG_PROBE +const struct ext_man_probe_support ext_man_probe + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { + .hdr.type = EXT_MAN_ELEM_PROBE_INFO, + .hdr.elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_probe_support), + EXT_MAN_ALIGN), + .probe = { + .ext_hdr.hdr.size = sizeof(struct sof_ipc_probe_support), + .ext_hdr.hdr.cmd = SOF_IPC_FW_READY, + .ext_hdr.type = SOF_IPC_EXT_PROBE_INFO, + .probe_points_max = CONFIG_PROBE_POINTS_MAX, + .injection_dmas_max = CONFIG_PROBE_DMA_MAX + }, +}; +#endif + +const struct ext_man_dbg_abi ext_man_dbg_info + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { + .hdr.type = EXT_MAN_ELEM_DBG_ABI, + .hdr.elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_dbg_abi), + EXT_MAN_ALIGN), + .dbg_abi = { + .ext_hdr.hdr.size = sizeof(struct sof_ipc_user_abi_version), + .ext_hdr.hdr.cmd = SOF_IPC_FW_READY, + .ext_hdr.type = SOF_IPC_EXT_USER_ABI_INFO, + .abi_dbg_version = SOF_ABI_DBG_VERSION, + }, +}; + +/* increment this value after adding any element to ext_man_config dictionary */ +#define CONFIG_ELEM_CNT (EXT_MAN_CONFIG_LAST_ELEM - 1) + +const struct ext_man_config_data ext_man_config + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { + .hdr.type = EXT_MAN_ELEM_CONFIG_DATA, + .hdr.elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_config_data) + + sizeof(struct config_elem) * CONFIG_ELEM_CNT, + EXT_MAN_ALIGN), + .elems = { + {EXT_MAN_CONFIG_IPC_MSG_SIZE, SOF_IPC_MSG_MAX_SIZE}, + {EXT_MAN_CONFIG_MEMORY_USAGE_SCAN, IS_ENABLED(CONFIG_DEBUG_MEMORY_USAGE_SCAN)}, + }, +}; diff --git a/src/init/init.c b/src/init/init.c index 423b5ab80f22..e8d374c810ad 100644 --- a/src/init/init.c +++ b/src/init/init.c @@ -9,19 +9,43 @@ * initialisation functions. */ -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> +#include <rtos/panic.h> +#include <rtos/init.h> +#include <rtos/interrupt.h> #include <sof/init.h> -#include <sof/lib/alloc.h> #include <sof/lib/cpu.h> +#include <sof/lib/cpu-clk-manager.h> #include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> #include <sof/lib/notifier.h> #include <sof/lib/pm_runtime.h> +#include <rtos/wait.h> #include <sof/platform.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> +#include <rtos/task.h> +#include <rtos/sof.h> #include <sof/trace/trace.h> +#include <rtos/idc.h> +#include <rtos/string_macro.h> +#include <rtos/symbol.h> +#include <sof/schedule/schedule.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> #include <ipc/trace.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/fw_reg.h> +#include <sof/lib/mailbox.h> +#endif +#ifdef CONFIG_ZEPHYR_LOG +#include <zephyr/logging/log_ctrl.h> +#include <user/abi_dbg.h> +#include <sof_versions.h> +#include <version.h> +#endif +#include <sof/lib/ams.h> + +LOG_MODULE_REGISTER(init, CONFIG_SOF_LOG_LEVEL); /* main firmware context */ static struct sof sof; @@ -30,64 +54,212 @@ struct sof *sof_get(void) { return &sof; } +EXPORT_SYMBOL(sof_get); -int master_core_init(int argc, char *argv[], struct sof *sof) +#if CONFIG_NO_SECONDARY_CORE_ROM +/** + * \brief This function will unpack lpsram text sections from AltBootManifest + created in linker script. + AltBootManifest structure: + - number of entries + and for each entry: + - source pointer + - destination pointer + - size + */ +static inline void lp_sram_unpack(void) +{ + extern uintptr_t _loader_storage_manifest_start; + + uint32_t *src, *dst; + uint32_t size, i; + + uint32_t *ptr = (uint32_t *)&_loader_storage_manifest_start; + uint32_t entries = *ptr++; + + for (i = 0; i < entries; i++) { + src = (uint32_t *)*ptr++; + dst = (uint32_t *)*ptr++; + size = *ptr++; + + memcpy_s(dst, size, src, size); + dcache_writeback_region((__sparse_force void __sparse_cache *)dst, size); + } +} +#endif + +#if CONFIG_MULTICORE + +static bool check_restore(void) +{ + struct idc *idc = *idc_get(); + struct notify *notifier = *arch_notify_get(); + struct schedulers *schedulers = *arch_schedulers_get(); + + /* check whether basic core structures has been already allocated. If they + * are available in memory, it means that this is not cold boot and memory + * has not been powered off. + */ + return !!idc && !!notifier && !!schedulers; +} + +static inline int secondary_core_restore(void) { return 0; }; + +__cold int secondary_core_init(struct sof *sof) { int err; + struct ll_schedule_domain *dma_domain; - /* setup context */ - sof->argc = argc; - sof->argv = argv; + /* check whether we are in a cold boot process or not (e.g. D0->D0ix + * flow when primary core disables all secondary cores). If not, we do + * not have allocate basic structures like e.g. schedulers, notifier, + * because they have been already allocated. In that case we have to + * register and enable required interrupts. + */ + if (check_restore()) + return secondary_core_restore(); + + trace_point(TRACE_BOOT_SYS_NOTIFIER); + init_system_notify(sof); + + trace_point(TRACE_BOOT_PLATFORM_SCHED); + scheduler_init_ll(timer_domain_get()); + + dma_domain = dma_domain_get(); + if (dma_domain) + scheduler_init_ll(dma_domain); + +#if CONFIG_ZEPHYR_DP_SCHEDULER + err = scheduler_dp_init(); + if (err < 0) + return err; +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ - /* init architecture */ - trace_point(TRACE_BOOT_ARCH); - err = arch_init(); + /* initialize IDC mechanism */ + trace_point(TRACE_BOOT_PLATFORM_IDC); + err = idc_init(); if (err < 0) - panic(SOF_IPC_PANIC_ARCH); + return err; - /* initialise system services */ - trace_point(TRACE_BOOT_SYS_HEAP); - platform_init_memmap(sof); - init_heap(sof); +#if CONFIG_AMS + err = ams_init(); + if (err < 0) + return err; +#endif +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + err = core_kcps_adjust(cpu_get_id(), SECONDARY_CORE_BASE_CPS_USAGE); + if (err < 0) + return err; +#endif - interrupt_init(sof); + trace_point(TRACE_BOOT_PLATFORM); + + LOG_INF("init done"); + + return err; +} + +#endif + +__cold static void print_version_banner(void) +{ + /* + * Non-Zephyr builds emit the version banner in DMA-trace + * init and this is done at a later time as otherwise the + * banner would be lost. With Zephyr logging subsystem in use, + * we can simply print the banner at boot. + * + * STRINGIFY(SOF_SRC_HASH) is part of the format string so it + * is part of log dictionary meta data and does not go to + * the firmware binary (in case dictionary logging is used). + * The value printed to log will be different from + * SOF_SRC_HASH in case of mismatch. + */ +#ifdef CONFIG_ZEPHYR_LOG + LOG_INF("FW ABI 0x%x DBG ABI 0x%x tags SOF:" SOF_GIT_TAG " zephyr:" \ + STRINGIFY(BUILD_VERSION) " src hash 0x%08x (ref hash " \ + STRINGIFY(SOF_SRC_HASH) ")", + SOF_ABI_VERSION, SOF_ABI_DBG_VERSION, SOF_SRC_HASH); +#endif +} + +#ifdef CONFIG_ZEPHYR_LOG +static log_timestamp_t default_get_timestamp(void) +{ + return IS_ENABLED(CONFIG_LOG_TIMESTAMP_64BIT) ? + sys_clock_tick_get() : k_cycle_get_32(); +} +#endif + +__cold static int primary_core_init(int argc, char *argv[], struct sof *sof) +{ + /* setup context */ + sof->argc = argc; + sof->argv = argv; + +#if defined(CONFIG_ZEPHYR_LOG) && !defined(CONFIG_LOG_MODE_MINIMAL) + log_set_timestamp_func(default_get_timestamp, + sys_clock_hw_cycles_per_sec()); +#endif #if CONFIG_TRACE trace_point(TRACE_BOOT_SYS_TRACES); trace_init(sof); #endif + print_version_banner(); + trace_point(TRACE_BOOT_SYS_NOTIFIER); init_system_notify(sof); trace_point(TRACE_BOOT_SYS_POWER); pm_runtime_init(sof); +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* init I/O performance before any I/O interfaces */ + io_perf_monitor_init(); +#endif + +#if CONFIG_SOF_USERSPACE_LL + zephyr_ll_user_resources_init(); +#endif + /* init the platform */ - err = platform_init(sof); - if (err < 0) - panic(SOF_IPC_PANIC_PLATFORM); + if (platform_init(sof) < 0) + sof_panic(SOF_IPC_PANIC_PLATFORM); + +#if CONFIG_AMS + if (ams_init()) + LOG_ERR("AMS Init failed!"); +#endif + +#if CONFIG_IPC_MAJOR_4 + /* Set current abi version of the IPC4 FwRegisters layout */ + size_t ipc4_abi_ver_offset = offsetof(struct ipc4_fw_registers, abi_ver); + + mailbox_sw_reg_write(ipc4_abi_ver_offset, IPC4_FW_REGS_ABI_VER); +#endif trace_point(TRACE_BOOT_PLATFORM); - /* should not return */ - err = task_main_start(sof); +#if CONFIG_NO_SECONDARY_CORE_ROM + lp_sram_unpack(); +#endif - return err; + /* should not return, except with Zephyr */ + return task_main_start(sof); } -int main(int argc, char *argv[]) +int sof_main(int argc, char *argv[]) { - int err; - trace_point(TRACE_BOOT_START); - if (cpu_get_id() == PLATFORM_MASTER_CORE_ID) - err = master_core_init(argc, argv, &sof); - else - err = slave_core_init(&sof); + return start_complete(); +} - /* should never get here */ - panic(SOF_IPC_PANIC_TASK); - return err; +static int sof_init(void) +{ + return primary_core_init(0, NULL, &sof); } + +SYS_INIT(sof_init, POST_KERNEL, 99); diff --git a/src/ipc/CMakeLists.txt b/src/ipc/CMakeLists.txt index 7423a2eac72b..15fab54b3c30 100644 --- a/src/ipc/CMakeLists.txt +++ b/src/ipc/CMakeLists.txt @@ -1,44 +1,35 @@ # SPDX-License-Identifier: BSD-3-Clause -if(BUILD_LIBRARY) - add_local_sources(sof - ipc.c - ) - return() +if (CONFIG_IPC_MAJOR_3) + add_subdirectory(ipc3) +elseif (CONFIG_IPC_MAJOR_4) + add_subdirectory(ipc4) endif() +# Common to Zephyr and XTOS add_local_sources(sof - ipc.c - handler.c + ipc-common.c + ipc-helper.c + notification_pool.c ) -if (CONFIG_TRACE) - add_local_sources(sof - dma-copy.c) -endif() +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### -if (CONFIG_HOST_PTABLE) - add_local_sources(sof - ipc-host-ptable.c) -endif() +# dma-copy only used for dma-trace +zephyr_library_sources_ifdef(CONFIG_TRACE dma-copy.c) -add_library(data_structs STATIC "") - -# define compiler version -set_property(TARGET data_structs APPEND - PROPERTY COMPILE_DEFINITIONS - XCC_TOOLS_VERSION="${XCC_TOOLS_VERSION}") +if (CONFIG_SOC_SERIES_INTEL_CAVS_V25 OR CONFIG_SOC_SERIES_INTEL_ADSP_ACE) + zephyr_library_sources( + ipc-zephyr.c + ) +endif() -# and optimization settings -get_optimization_flag(optimization_flag) -set_property(TARGET data_structs APPEND - PROPERTY COMPILE_DEFINITIONS - CC_OPTIMIZE_FLAGS="${optimization_flag}") +else() ### Not Zephyr ### -add_local_sources(data_structs - cc_version.c - probe_support.c - user_abi_version.c) +if (CONFIG_TRACE) + add_local_sources(sof + dma-copy.c) +endif() -target_link_libraries(data_structs sof_options) -target_link_libraries(sof_static_libraries INTERFACE data_structs) +endif() # Zephyr diff --git a/src/ipc/Kconfig b/src/ipc/Kconfig new file mode 100644 index 000000000000..3cde2ddeabfe --- /dev/null +++ b/src/ipc/Kconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "IPC Major Version" + +choice + prompt "IPC Major Version" + default IPC_MAJOR_3 + +config IPC_MAJOR_3 + bool "IPC Major Version 3" + help + This is the default IPC version used on most SOF based devices. + If unsure say Y. + +config IPC_MAJOR_4 + bool "IPC Major Version 4" + depends on ZEPHYR_NATIVE_DRIVERS || LIBRARY + help + This is an IPC version used by certain middleware on some IOT + Intel devices. Not for general use. + NOTE: This IPC ABI is not guranteed to work on any platforms other + than a specific Intel platform due to use of bit fields in the IPC ABI. + If unsure say N. + +endchoice + +endmenu diff --git a/src/ipc/README.md b/src/ipc/README.md new file mode 100644 index 000000000000..7389e6ae4a54 --- /dev/null +++ b/src/ipc/README.md @@ -0,0 +1,98 @@ +# Inter-Processor Communication (IPC) Core Architecture + +This directory contains the common foundation for all Inter-Processor Communication (IPC) within the Sound Open Firmware (SOF) project. It bridges the gap between hardware mailbox interrupts and the version-specific (IPC3/IPC4) message handlers. + +## Overview + +The Core IPC layer is completely agnostic to the specific structure or content of the messages (whether they are IPC3 stream commands or IPC4 pipeline messages). Its primary responsibilities are: + +1. **Message State Management**: Tracking if a message is being processed, queued, or completed. +2. **Interrupt Bridging**: Routing incoming platform interrupts into the Zephyr or SOF thread-domain scheduler. +3. **Queueing**: Safe traversal and delayed processing capabilities via `k_work` items or SOF scheduler tasks. +4. **Platform Acknowledgment**: Signaling the hardware mailbox layers to confirm receipt or signal completion out entirely. + +## Architecture Diagram + +The basic routing of any IPC message moves from a hardware interrupt, through the platform driver, into the core IPC handlers, and ultimately up to version-specific handlers. + +```mermaid +graph TD + Platform[Platform / Mailbox HW] -->|IRQ| CoreIPC[Core IPC Framework] + + subgraph CoreIPC [src/ipc/ipc-common.c] + Queue[Msg Queue / Worker Task] + Dispatcher[IPC Message Dispatcher] + PM[Power Management Wait/Wake] + + Queue --> Dispatcher + Dispatcher --> PM + end + + Dispatcher -->|Version Specific Parsing| IPC3[IPC3 Handler] + Dispatcher -->|Version Specific Parsing| IPC4[IPC4 Handler] + + IPC3 -.-> CoreIPC + IPC4 -.-> CoreIPC + CoreIPC -.->|Ack| Platform +``` + +## Processing Flow + +When the host writes a command to the IPC mailbox and triggers an interrupt, the hardware-specific driver (`src/platform/...`) catches the IRQ and eventually calls down into the IPC framework. + +Different RTOS environments (Zephyr vs. bare metal SOF native) handle the thread handoff differently. In Zephyr, this leverages the `k_work` queues heavily for `ipc_work_handler`. + +### Receiving Messages (Host -> DSP) + +```mermaid +sequenceDiagram + participant Host + participant Platform as Platform Mailbox (IRQ) + participant CoreIPC as Core IPC Worker + participant Handler as Version-Specific Handler (IPC3/4) + + Host->>Platform: Writes Mailbox, Triggers Interrupt + activate Platform + Platform->>CoreIPC: ipc_schedule_process() + deactivate Platform + + Note over CoreIPC: Worker thread wakes up + + activate CoreIPC + CoreIPC->>Platform: ipc_platform_wait_ack() (Optional blocking) + CoreIPC->>Handler: version_specific_command_handler() + + Handler-->>CoreIPC: Command Processed (Status Header) + CoreIPC->>Platform: ipc_complete_cmd() + Platform-->>Host: Signals Completion Mailbox / IRQ + deactivate CoreIPC +``` + +### Sending Messages (DSP -> Host) + +Firmware-initiated messages (like notifications for position updates, traces, or XRUNs) rely on a queue if the hardware is busy. + +```mermaid +sequenceDiagram + participant DSP as DSP Component (e.g. Pipeline Tracker) + participant Queue as IPC Message Queue + participant Platform as Platform Mailbox + + DSP->>Queue: ipc_msg_send() / ipc_msg_send_direct() + activate Queue + Queue-->>Queue: Add to Tx list (if BUSY) + Queue->>Platform: Copy payload to mailbox and send + + alt If host is ready + Platform-->>Queue: Success + Queue->>Platform: Triggers IRQ to Host + else If host requires delayed ACKs + Queue-->>DSP: Queued pending prior completion + end + deactivate Queue +``` + +## Global IPC Objects and Helpers + +* `ipc_comp_dev`: Wrapper structure linking generic devices (`comp_dev`) specifically to their IPC pipeline and endpoint identifiers. +* `ipc_get_comp_dev` / `ipc_get_ppl_comp`: Lookup assistants utilizing the central graph tracking to find specific components either directly by component ID or by traversing the pipeline graph starting from a given `pipeline_id` and direction (upstream/downstream). diff --git a/src/ipc/cc_version.c b/src/ipc/cc_version.c deleted file mode 100644 index a32c45b34e1c..000000000000 --- a/src/ipc/cc_version.c +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> - -#include <ipc/info.h> -#include <sof/fw-ready-metadata.h> -#include <sof/common.h> -#include <sof/compiler_info.h> - -/* copy CC_NAME to const arrays during compilation time */ -#define CC_NAME_COPY(field) \ - field = CC_NAME, \ - field[ARRAY_SIZE(((struct sof_ipc_cc_version *)(0))->name) - 1] = 0 - -/* copy CC_OPTIM to const arrays during compilation time */ -#define CC_OPTIM_COPY(field) \ - field = CC_OPTIMIZE_FLAGS, \ - field[ARRAY_SIZE(((struct sof_ipc_cc_version *)(0))->optim) - 1] = 0 - -const struct sof_ipc_cc_version cc_version - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = ALIGN_UP(sizeof(struct sof_ipc_cc_version) - + sizeof(CC_DESC), 4), - .type = SOF_IPC_EXT_CC_INFO, - }, - .micro = CC_MICRO, - .minor = CC_MINOR, - .major = CC_MAJOR, - CC_NAME_COPY(.name), - CC_OPTIM_COPY(.optim), - .desc = CC_DESC, -}; diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index 21b9affd46d8..3e8834474e82 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -5,23 +5,24 @@ // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> // Keyon Jie <yang.jie@linux.intel.com> -#include <sof/drivers/ipc.h> +#include <sof/ipc/msg.h> #include <sof/lib/dma.h> +#include <sof/lib/uuid.h> #include <sof/platform.h> -#include <sof/trace/dma-trace.h> #include <sof/trace/trace.h> #include <user/trace.h> -#include <config.h> + #include <errno.h> #include <stddef.h> #include <stdint.h> /* tracing */ -#define trace_dma(__e) trace_event(TRACE_CLASS_DMA, __e) -#define trace_dma_error(__e) trace_error(TRACE_CLASS_DMA, __e) -#define tracev_dma(__e) tracev_event(TRACE_CLASS_DMA, __e) +LOG_MODULE_REGISTER(dma_copy, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dma_copy); + +DECLARE_TR_CTX(dmacpy_tr, SOF_UUID(dma_copy_uuid), LOG_LEVEL_INFO); -#if !CONFIG_DMA_GW static struct dma_sg_elem *sg_get_elem_at(struct dma_sg_config *host_sg, int32_t *offset) { @@ -44,38 +45,20 @@ static struct dma_sg_elem *sg_get_elem_at(struct dma_sg_config *host_sg, } /* host offset in beyond end of SG buffer */ - trace_dma_error("sg_get_elem_at() error: " - "host offset in beyond end of SG buffer"); + tr_err(&dmacpy_tr, "host offset in beyond end of SG buffer"); return NULL; } -#endif /* Copy DSP memory to host memory. * Copies DSP memory to host in a single PAGE_SIZE or smaller block. Does not * waits/sleeps and can be used in IRQ context. */ -#if CONFIG_DMA_GW - -int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size) -{ - int ret; - - /* tell gateway to copy */ - ret = dma_copy(dc->chan, size, 0); - if (ret < 0) - return ret; - - /* bytes copied */ - return size; -} - -#else -int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, - int32_t host_offset, void *local_ptr, int32_t size) +static int +dma_copy_to_host_flags(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size, + uint32_t flags) { - struct dma_trace_data *dmat = dma_trace_data_get(); struct dma_sg_config config; struct dma_sg_elem *host_sg_elem; struct dma_sg_elem local_sg_elem; @@ -87,7 +70,7 @@ int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, /* find host element with host_offset */ host_sg_elem = sg_get_elem_at(host_sg, &offset); - if (host_sg_elem == NULL) + if (!host_sg_elem) return -EINVAL; /* set up DMA configuration */ @@ -100,7 +83,7 @@ int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, /* configure local DMA elem */ local_sg_elem.dest = host_sg_elem->dest + offset; - local_sg_elem.src = (uint32_t)local_ptr; + local_sg_elem.src = (uintptr_t)local_ptr; if (size >= HOST_PAGE_SIZE - offset) local_sg_elem.size = HOST_PAGE_SIZE - offset; else @@ -110,24 +93,32 @@ int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, config.elem_array.count = 1; /* start the DMA */ - err = dma_set_config(dc->chan, &config); + err = dma_set_config_legacy(dc->chan, &config); if (err < 0) return err; - err = dma_copy(dc->chan, local_sg_elem.size, - DMA_COPY_ONE_SHOT | DMA_COPY_BLOCKING); + err = dma_copy_legacy(dc->chan, local_sg_elem.size, + flags); if (err < 0) return err; - ipc_msg_send(dmat->msg, &dmat->posn, false); - - platform_shared_commit(dmat, sizeof(*dmat)); - /* bytes copied */ return local_sg_elem.size; } -#endif +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size) +{ + return dma_copy_to_host_flags(dc, host_sg, host_offset, local_ptr, size, + DMA_COPY_ONE_SHOT | DMA_COPY_BLOCKING); +} + +int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size) +{ + return dma_copy_to_host_flags(dc, host_sg, host_offset, local_ptr, size, + DMA_COPY_ONE_SHOT); +} int dma_copy_new(struct dma_copy *dc) { @@ -138,36 +129,30 @@ int dma_copy_new(struct dma_copy *dc) dev = DMA_DEV_HOST; cap = 0; dc->dmac = dma_get(dir, cap, dev, DMA_ACCESS_SHARED); - if (dc->dmac == NULL) { - trace_dma_error("dma_copy_new() error: dc->dmac = NULL"); + if (!dc->dmac) { + tr_err(&dmacpy_tr, "dc->dmac = NULL"); return -ENODEV; } -#if !CONFIG_DMA_GW /* get DMA channel from DMAC0 */ - dc->chan = dma_channel_get(dc->dmac, 0); + dc->chan = dma_channel_get_legacy(dc->dmac, CONFIG_TRACE_CHANNEL); if (!dc->chan) { - trace_dma_error("dma_copy_new() error: dc->chan is NULL"); + tr_err(&dmacpy_tr, "dc->chan is NULL"); return -ENODEV; } -#endif return 0; } -#if CONFIG_DMA_GW - int dma_copy_set_stream_tag(struct dma_copy *dc, uint32_t stream_tag) { /* get DMA channel from DMAC */ - dc->chan = dma_channel_get(dc->dmac, stream_tag - 1); + dc->chan = dma_channel_get_legacy(dc->dmac, stream_tag - 1); if (!dc->chan) { - trace_dma_error("dma_copy_set_stream_tag() error: " - "dc->chan is NULL"); + tr_err(&dmacpy_tr, "dc->chan is NULL"); return -EINVAL; } return 0; } -#endif diff --git a/src/ipc/handler.c b/src/ipc/handler.c deleted file mode 100644 index 17da91f9eadb..000000000000 --- a/src/ipc/handler.c +++ /dev/null @@ -1,1352 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -/* - * IPC (InterProcessor Communication) provides a method of two way - * communication between the host processor and the DSP. The IPC used here - * utilises a shared mailbox and door bell between the host and DSP. - * - */ - -#include <sof/audio/buffer.h> -#include <sof/audio/component_ext.h> -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/debug/gdb/gdb.h> -#include <sof/debug/panic.h> -#include <sof/drivers/idc.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/cpu.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_runtime.h> -#include <sof/list.h> -#include <sof/math/numbers.h> -#include <sof/platform.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <sof/string.h> -#include <sof/trace/dma-trace.h> -#include <sof/trace/trace.h> -#include <ipc/control.h> -#include <ipc/dai.h> -#include <ipc/header.h> -#include <ipc/pm.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <ipc/trace.h> -#include <user/trace.h> -#include <ipc/probe.h> -#include <sof/probe/probe.h> -#include <config.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#define iGS(x) ((x) & SOF_GLB_TYPE_MASK) -#define iCS(x) ((x) & SOF_CMD_TYPE_MASK) - -/* - * IPC ABI version compatibility rules :- - * - * 1) FW binaries will only support one MAJOR ABI version which is advertised - * to host at FW boot. - * - * 2) Host drivers will support the current and older MAJOR ABI versions of - * the IPC ABI (up to a certain age to be determined by market information). - * - * 3) MINOR and PATCH ABI versions can differ between host and FW but must be - * backwards compatible on both host and FW. - * - * IPC messages sizes can be different for sender and receiver if MINOR or - * PATCH ABI versions differ as new fields can be added to the end of - * messages. - * - * i) Sender > receiver: receiver only copies it's own ABI structure size. - * - * ii) Receiver > sender: receiver copies its's own ABI size and zero pads - * new fields. i.e. new structure fields must be non - * zero to be activated. - * - * Guidelines for extending ABI compatible messages :- - * - * i) Use reserved fields. - * ii) Grow structure at the end. - * iii) Iff (i) and (ii) are not possible then MAJOR ABI is bumped. - */ - -#define _IPC_COPY_CMD(rx, tx, rx_size) \ - do { \ - int ___ret; \ - if (rx_size > tx->size) { \ - ___ret = memcpy_s(rx, rx_size, tx, tx->size); \ - assert(!___ret); \ - bzero((char *)rx + tx->size, rx_size - tx->size);\ - trace_ipc("ipc: hdr 0x%x rx (%d) > tx (%d)", \ - rx->cmd, rx_size, tx->size); \ - } else if (tx->size > rx_size) { \ - ___ret = memcpy_s(rx, rx_size, tx, rx_size); \ - assert(!___ret); \ - trace_ipc("ipc: hdr 0x%x tx (%d) > rx (%d)", \ - rx->cmd, tx->size, rx_size); \ - } else { \ - ___ret = memcpy_s(rx, rx_size, tx, rx_size); \ - assert(!___ret); \ - } \ - } while (0) - -/* copies whole message from Tx to Rx, follows above ABI rules */ -#define IPC_COPY_CMD(rx, tx) \ - _IPC_COPY_CMD(((struct sof_ipc_cmd_hdr *)&rx), \ - ((struct sof_ipc_cmd_hdr *)tx), \ - sizeof(rx)) - -struct sof_ipc_cmd_hdr *mailbox_validate(void) -{ - struct sof_ipc_cmd_hdr *hdr = ipc_get()->comp_data; - - /* read component values from the inbox */ - mailbox_hostbox_read(hdr, SOF_IPC_MSG_MAX_SIZE, 0, sizeof(*hdr)); - - /* validate component header */ - if (hdr->size > SOF_IPC_MSG_MAX_SIZE) { - trace_ipc_error("ipc: msg too big at 0x%x", hdr->size); - return NULL; - } - - /* read rest of component data */ - mailbox_hostbox_read(hdr + 1, SOF_IPC_MSG_MAX_SIZE - sizeof(*hdr), - sizeof(*hdr), hdr->size - sizeof(*hdr)); - - platform_shared_commit(hdr, hdr->size); - - return hdr; -} - -/* - * Stream IPC Operations. - */ - -#if CONFIG_HOST_PTABLE -/* check if a pipeline is hostless when walking downstream */ -static bool is_hostless_downstream(struct comp_dev *current) -{ - struct list_item *clist; - - /* check if current is a HOST comp */ - if (current->comp.type == SOF_COMP_HOST || - current->comp.type == SOF_COMP_SG_HOST) - return false; - - /* check if the pipeline has a HOST comp downstream */ - list_for_item(clist, ¤t->bsink_list) { - struct comp_buffer *buffer; - - buffer = container_of(clist, struct comp_buffer, source_list); - - /* don't go downstream if this component is not connected */ - if (!buffer->sink) - continue; - - /* dont go downstream if this comp belongs to another pipe */ - if (buffer->sink->comp.pipeline_id != current->comp.pipeline_id) - continue; - - /* return if there's a host comp downstream */ - if (!is_hostless_downstream(buffer->sink)) - return false; - } - - return true; -} - -/* check if a pipeline is hostless when walking upstream */ -static bool is_hostless_upstream(struct comp_dev *current) -{ - struct list_item *clist; - - /* check if current is a HOST comp */ - if (current->comp.type == SOF_COMP_HOST || - current->comp.type == SOF_COMP_SG_HOST) - return false; - - /* check if the pipeline has a HOST comp upstream */ - list_for_item(clist, ¤t->bsource_list) { - struct comp_buffer *buffer; - - buffer = container_of(clist, struct comp_buffer, sink_list); - - /* don't go upstream if this component is not connected */ - if (!buffer->source) - continue; - - /* dont go upstream if this comp belongs to another pipeline */ - if (buffer->source->comp.pipeline_id != - current->comp.pipeline_id) - continue; - - /* return if there is a host comp upstream */ - if (!is_hostless_upstream(buffer->source)) - return false; - } - - return true; -} -#endif - -/* allocate a new stream */ -static int ipc_stream_pcm_params(uint32_t stream) -{ -#if CONFIG_HOST_PTABLE - struct sof_ipc_comp_host *host = NULL; - struct dma_sg_elem_array elem_array; - uint32_t ring_size; - enum comp_copy_type copy_type = COMP_COPY_ONE_SHOT; - struct comp_dev *cd; -#endif - struct ipc *ipc = ipc_get(); - struct sof_ipc_pcm_params pcm_params; - struct sof_ipc_pcm_params_reply reply; - struct ipc_comp_dev *pcm_dev; - int err, reset_err; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(pcm_params, ipc->comp_data); - - /* get the pcm_dev */ - pcm_dev = ipc_get_comp_by_id(ipc, pcm_params.comp_id); - if (pcm_dev == NULL) { - trace_ipc_error("ipc: comp %d not found", pcm_params.comp_id); - return -ENODEV; - } - - /* check core */ - if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); - - trace_ipc("ipc: comp %d -> params", pcm_params.comp_id); - - /* sanity check comp */ - if (pcm_dev->cd->pipeline == NULL) { - trace_ipc_error("ipc: comp %d pipeline not found", - pcm_params.comp_id); - return -EINVAL; - } - - if (IPC_IS_SIZE_INVALID(pcm_params.params)) { - IPC_SIZE_ERROR_TRACE(TRACE_CLASS_IPC, pcm_params.params); - return -EINVAL; - } - -#if CONFIG_HOST_PTABLE - cd = pcm_dev->cd; - - /* - * walk in both directions to check if the pipeline is hostless - * skip page table set up if it is - */ - if (is_hostless_downstream(cd) && is_hostless_upstream(cd)) - goto pipe_params; - - /* Parse host tables */ - host = (struct sof_ipc_comp_host *)&cd->comp; - if (IPC_IS_SIZE_INVALID(host->config)) { - IPC_SIZE_ERROR_TRACE(TRACE_CLASS_IPC, host->config); - err = -EINVAL; - goto error; - } - - err = ipc_process_host_buffer(ipc, &pcm_params.params.buffer, - host->direction, - &elem_array, - &ring_size); - if (err < 0) - goto error; - - err = comp_set_attribute(cd, COMP_ATTR_HOST_BUFFER, &elem_array); - if (err < 0) { - trace_ipc_error("ipc: comp %d host buffer failed %d", - pcm_params.comp_id, err); - goto error; - } - - /* TODO: should be extracted to platform specific code */ - err = comp_set_attribute(cd, COMP_ATTR_COPY_TYPE, ©_type); - if (err < 0) { - trace_ipc_error("ipc: comp %d setting copy type failed %d", - pcm_params.comp_id, err); - goto error; - } - -pipe_params: -#endif - - /* configure pipeline audio params */ - err = pipeline_params(pcm_dev->cd->pipeline, pcm_dev->cd, - (struct sof_ipc_pcm_params *)ipc_get()->comp_data); - if (err < 0) { - trace_ipc_error("ipc: pipe %d comp %d params failed %d", - pcm_dev->cd->pipeline->ipc_pipe.pipeline_id, - pcm_params.comp_id, err); - goto error; - } - - /* prepare pipeline audio params */ - err = pipeline_prepare(pcm_dev->cd->pipeline, pcm_dev->cd); - if (err < 0) { - trace_ipc_error("ipc: pipe %d comp %d prepare failed %d", - pcm_dev->cd->pipeline->ipc_pipe.pipeline_id, - pcm_params.comp_id, err); - goto error; - } - - /* write component values to the outbox */ - reply.rhdr.hdr.size = sizeof(reply); - reply.rhdr.hdr.cmd = stream; - reply.rhdr.error = 0; - reply.comp_id = pcm_params.comp_id; - reply.posn_offset = pcm_dev->cd->pipeline->posn_offset; - mailbox_hostbox_write(0, &reply, sizeof(reply)); - platform_shared_commit(pcm_dev, sizeof(*pcm_dev)); - return 1; - -error: - reset_err = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); - if (reset_err < 0) - trace_ipc_error("ipc: pipe %d comp %d reset failed %d", - pcm_dev->cd->pipeline->ipc_pipe.pipeline_id, - pcm_params.comp_id, reset_err); - platform_shared_commit(pcm_dev, sizeof(*pcm_dev)); - return err; -} - -/* free stream resources */ -static int ipc_stream_pcm_free(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_stream free_req; - struct ipc_comp_dev *pcm_dev; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(free_req, ipc->comp_data); - - /* get the pcm_dev */ - pcm_dev = ipc_get_comp_by_id(ipc, free_req.comp_id); - if (pcm_dev == NULL) { - trace_ipc_error("ipc: comp %d not found", free_req.comp_id); - return -ENODEV; - } - - /* check core */ - if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); - - trace_ipc("ipc: comp %d -> free", free_req.comp_id); - - /* sanity check comp */ - if (pcm_dev->cd->pipeline == NULL) { - trace_ipc_error("ipc: comp %d pipeline not found", - free_req.comp_id); - return -EINVAL; - } - - /* reset the pipeline */ - ret = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); - - platform_shared_commit(pcm_dev, sizeof(*pcm_dev)); - - return ret; -} - -/* get stream position */ -static int ipc_stream_position(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_stream stream; - struct sof_ipc_stream_posn posn; - struct ipc_comp_dev *pcm_dev; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(stream, ipc->comp_data); - - /* get the pcm_dev */ - pcm_dev = ipc_get_comp_by_id(ipc, stream.comp_id); - if (pcm_dev == NULL) { - trace_ipc_error("ipc: comp %d not found", stream.comp_id); - return -ENODEV; - } - - /* check core */ - if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); - - trace_ipc("ipc: comp %d -> position", stream.comp_id); - - memset(&posn, 0, sizeof(posn)); - - /* set message fields - TODO; get others */ - posn.rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION | - stream.comp_id; - posn.rhdr.hdr.size = sizeof(posn); - posn.comp_id = stream.comp_id; - - /* get the stream positions and timestamps */ - pipeline_get_timestamp(pcm_dev->cd->pipeline, pcm_dev->cd, &posn); - - /* copy positions to stream region */ - mailbox_stream_write(pcm_dev->cd->pipeline->posn_offset, - &posn, sizeof(posn)); - - platform_shared_commit(pcm_dev, sizeof(*pcm_dev)); - - return 1; -} - -static int ipc_stream_trigger(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *pcm_dev; - struct sof_ipc_stream stream; - uint32_t ipc_cmd = iCS(header); - uint32_t cmd; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(stream, ipc->comp_data); - - /* get the pcm_dev */ - pcm_dev = ipc_get_comp_by_id(ipc, stream.comp_id); - if (pcm_dev == NULL) { - trace_ipc_error("ipc: comp %d not found", stream.comp_id); - return -ENODEV; - } - - /* check core */ - if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); - - trace_ipc("ipc: comp %d -> trigger cmd 0x%x", stream.comp_id, ipc_cmd); - - switch (ipc_cmd) { - case SOF_IPC_STREAM_TRIG_START: - cmd = COMP_TRIGGER_START; - break; - case SOF_IPC_STREAM_TRIG_STOP: - cmd = COMP_TRIGGER_STOP; - break; - case SOF_IPC_STREAM_TRIG_PAUSE: - cmd = COMP_TRIGGER_PAUSE; - break; - case SOF_IPC_STREAM_TRIG_RELEASE: - cmd = COMP_TRIGGER_RELEASE; - break; - /* XRUN is special case- TODO */ - case SOF_IPC_STREAM_TRIG_XRUN: - return 0; - default: - trace_ipc_error("ipc: invalid trigger cmd 0x%x", ipc_cmd); - return -ENODEV; - } - - /* trigger the component */ - ret = pipeline_trigger(pcm_dev->cd->pipeline, pcm_dev->cd, cmd); - if (ret < 0) { - trace_ipc_error("ipc: comp %d trigger 0x%x failed %d", - stream.comp_id, ipc_cmd, ret); - } - - platform_shared_commit(pcm_dev, sizeof(*pcm_dev)); - - return ret; -} - -static int ipc_glb_stream_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - switch (cmd) { - case SOF_IPC_STREAM_PCM_PARAMS: - return ipc_stream_pcm_params(header); - case SOF_IPC_STREAM_PCM_FREE: - return ipc_stream_pcm_free(header); - case SOF_IPC_STREAM_TRIG_START: - case SOF_IPC_STREAM_TRIG_STOP: - case SOF_IPC_STREAM_TRIG_PAUSE: - case SOF_IPC_STREAM_TRIG_RELEASE: - case SOF_IPC_STREAM_TRIG_DRAIN: - case SOF_IPC_STREAM_TRIG_XRUN: - return ipc_stream_trigger(header); - case SOF_IPC_STREAM_POSITION: - return ipc_stream_position(header); - default: - trace_ipc_error("ipc: unknown stream cmd 0x%x", cmd); - return -EINVAL; - } -} - -/* - * DAI IPC Operations. - */ - -static int ipc_dai_config(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_dai_config config; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(config, ipc->comp_data); - - trace_ipc("ipc: dai %d.%d -> config ", config.type, - config.dai_index); - - /* send params to all DAI components who use that physical DAI */ - return ipc_comp_dai_config(ipc, - (struct sof_ipc_dai_config *)ipc->comp_data); -} - -static int ipc_glb_dai_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - switch (cmd) { - case SOF_IPC_DAI_CONFIG: - return ipc_dai_config(header); - case SOF_IPC_DAI_LOOPBACK: - //return ipc_comp_set_value(header, COMP_CMD_LOOPBACK); - default: - trace_ipc_error("ipc: unknown DAI cmd 0x%x", cmd); - return -EINVAL; - } -} - -/* - * PM IPC Operations. - */ - -static int ipc_pm_context_size(uint32_t header) -{ - struct sof_ipc_pm_ctx pm_ctx; - - trace_ipc("ipc: pm -> size"); - - bzero(&pm_ctx, sizeof(pm_ctx)); - - /* TODO: calculate the context and size of host buffers required */ - - /* write the context to the host driver */ - //mailbox_hostbox_write(0, &pm_ctx, sizeof(pm_ctx)); - - return 0; -} - -static int ipc_pm_context_save(uint32_t header) -{ - //struct sof_ipc_pm_ctx *pm_ctx = _ipc->comp_data; - - trace_ipc("ipc: pm -> save"); - - /* TODO: check we are inactive - all streams are suspended */ - - /* TODO: mask ALL platform interrupts except DMA */ - - /* TODO now save the context - create SG buffer config using */ - //mm_pm_context_save(struct dma_sg_config *sg); - - /* mask all DSP interrupts */ - arch_interrupt_disable_mask(0xffffffff); - - /* TODO: mask ALL platform interrupts inc DMA */ - - /* TODO: clear any outstanding platform IRQs - TODO refine */ - - /* TODO: stop ALL timers */ - platform_timer_stop(timer_get()); - - /* TODO: disable SSP and DMA HW */ - - /* TODO: save the context */ - //reply.entries_no = 0; - - /* write the context to the host driver */ - //mailbox_hostbox_write(0, pm_ctx, sizeof(*pm_ctx)); - - ipc_get()->pm_prepare_D3 = 1; - - return 0; -} - -static int ipc_pm_context_restore(uint32_t header) -{ - //struct sof_ipc_pm_ctx *pm_ctx = _ipc->comp_data; - - trace_ipc("ipc: pm -> restore"); - - ipc_get()->pm_prepare_D3 = 0; - - /* restore context placeholder */ - //mailbox_hostbox_write(0, pm_ctx, sizeof(*pm_ctx)); - - return 0; -} - -static int ipc_pm_core_enable(uint32_t header) -{ - struct sof_ipc_pm_core_config pm_core_config; - int i = 0; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(pm_core_config, ipc_get()->comp_data); - - trace_ipc("ipc: pm core mask 0x%x -> enable", - pm_core_config.enable_mask); - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - if (i != PLATFORM_MASTER_CORE_ID) { - if (pm_core_config.enable_mask & (1 << i)) - cpu_enable_core(i); - else - cpu_disable_core(i); - } - } - - return 0; -} - -static int ipc_pm_gate(uint32_t header) -{ - struct sof_ipc_pm_gate pm_gate; - - IPC_COPY_CMD(pm_gate, ipc_get()->comp_data); - - /* pause dma trace firstly if needed */ - if (pm_gate.flags & SOF_PM_NO_TRACE) - trace_off(); - - if (pm_gate.flags & SOF_PM_PPG) - pm_runtime_disable(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); - else - pm_runtime_enable(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); - - /* resume dma trace if needed */ - if (!(pm_gate.flags & SOF_PM_NO_TRACE)) - trace_on(); - - return 0; -} - -static int ipc_glb_pm_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - switch (cmd) { - case SOF_IPC_PM_CTX_SAVE: - return ipc_pm_context_save(header); - case SOF_IPC_PM_CTX_RESTORE: - return ipc_pm_context_restore(header); - case SOF_IPC_PM_CTX_SIZE: - return ipc_pm_context_size(header); - case SOF_IPC_PM_CORE_ENABLE: - return ipc_pm_core_enable(header); - case SOF_IPC_PM_GATE: - return ipc_pm_gate(header); - case SOF_IPC_PM_CLK_SET: - case SOF_IPC_PM_CLK_GET: - case SOF_IPC_PM_CLK_REQ: - default: - trace_ipc_error("ipc: unknown pm cmd 0x%x", cmd); - return -EINVAL; - } -} - -#if CONFIG_TRACE -/* - * Debug IPC Operations. - */ -static int ipc_dma_trace_config(uint32_t header) -{ -#if CONFIG_HOST_PTABLE - struct dma_sg_elem_array elem_array; - uint32_t ring_size; -#endif - struct dma_trace_data *dmat = dma_trace_data_get(); - struct ipc *ipc = ipc_get(); - struct sof_ipc_dma_trace_params_ext params; - struct timer *timer = timer_get(); - int err; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(params, ipc->comp_data); - - if (iCS(header) == SOF_IPC_TRACE_DMA_PARAMS_EXT) - platform_timer_set_delta(timer, params.timestamp_ns); - else - timer->delta = 0; - - platform_shared_commit(timer, sizeof(*timer)); - -#if CONFIG_SUECREEK - return 0; -#endif - -#if CONFIG_HOST_PTABLE - err = ipc_process_host_buffer(ipc, ¶ms.buffer, - SOF_IPC_STREAM_CAPTURE, - &elem_array, - &ring_size); - if (err < 0) - goto error; - - err = dma_trace_host_buffer(dmat, &elem_array, ring_size); - if (err < 0) { - trace_ipc_error("ipc: trace failed to set host buffers %d", - err); - goto error; - } -#else - /* stream tag of capture stream for DMA trace */ - dmat->stream_tag = params.stream_tag; - - /* host buffer size for DMA trace */ - dmat->host_size = params.buffer.size; -#endif - - err = dma_trace_enable(dmat); - if (err < 0) { - trace_ipc_error("ipc: failed to enable trace %d", err); - goto error; - } - - return 0; - -error: - return err; -} - -static int ipc_glb_debug_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - trace_ipc("ipc: debug cmd 0x%x", cmd); - - switch (cmd) { - case SOF_IPC_TRACE_DMA_PARAMS: - case SOF_IPC_TRACE_DMA_PARAMS_EXT: - return ipc_dma_trace_config(header); - default: - trace_ipc_error("ipc: unknown debug cmd 0x%x", cmd); - return -EINVAL; - } -} -#else -static int ipc_glb_debug_message(uint32_t header) -{ - /* traces are disabled - CONFIG_TRACE is not set */ - - return -EINVAL; -} -#endif - -static int ipc_glb_gdb_debug(uint32_t header) -{ - /* no furher information needs to be extracted form header */ - (void) header; - -#if CONFIG_GDB_DEBUG - gdb_init_debug_exception(); - gdb_init(); - /* TODO: this asm should be in arch/include/debug/debug.h - * with a generic name and trigger debug exception - */ - asm volatile("_break 0, 0"); - return 0; -#else - return -EINVAL; -#endif - -} - -#if CONFIG_PROBE -static inline int ipc_probe_init(uint32_t header) -{ - struct sof_ipc_probe_dma_add_params *params = ipc_get()->comp_data; - int dma_provided = params->num_elems; - - tracev_ipc("ipc_probe_init()"); - - if (dma_provided > 1 || dma_provided < 0) { - trace_ipc_error("ipc_probe_init() error: Invalid amount of extraction DMAs specified = %d", - dma_provided); - return -EINVAL; - } - - return probe_init(dma_provided ? params->probe_dma : NULL); -} - -static inline int ipc_probe_deinit(uint32_t header) -{ - tracev_ipc("ipc_probe_deinit()"); - - return probe_deinit(); -} - -static inline int ipc_probe_dma_add(uint32_t header) -{ - struct sof_ipc_probe_dma_add_params *params = ipc_get()->comp_data; - int dmas_count = params->num_elems; - - tracev_ipc("ipc_probe_dma_add()"); - - if (dmas_count > CONFIG_PROBE_DMA_MAX) { - trace_ipc_error("ipc_probe_dma_add() error: Invalid amount of injection DMAs specified = %d. Max is " META_QUOTE(CONFIG_PROBE_DMA_MAX) ".", - dmas_count); - return -EINVAL; - } - - if (dmas_count <= 0) { - trace_ipc_error("ipc_probe_dma_add() error: Inferred amount of incjection DMAs in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", - dmas_count); - return -EINVAL; - } - - return probe_dma_add(dmas_count, params->probe_dma); -} - -static inline int ipc_probe_dma_remove(uint32_t header) -{ - struct sof_ipc_probe_dma_remove_params *params = ipc_get()->comp_data; - int tags_count = params->num_elems; - - tracev_ipc("ipc_probe_dma_remove()"); - - if (tags_count > CONFIG_PROBE_DMA_MAX) { - trace_ipc_error("ipc_probe_dma_remove() error: Invalid amount of injection DMAs specified = %d. Max is " META_QUOTE(CONFIG_PROBE_DMA_MAX) ".", - tags_count); - return -EINVAL; - } - - if (tags_count <= 0) { - trace_ipc_error("ipc_probe_dma_remove() error: Inferred amount of incjection DMAs in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", - tags_count); - return -EINVAL; - } - - return probe_dma_remove(tags_count, params->stream_tag); -} - -static inline int ipc_probe_point_add(uint32_t header) -{ - struct sof_ipc_probe_point_add_params *params = ipc_get()->comp_data; - int probes_count = params->num_elems; - - tracev_ipc("ipc_probe_point_add()"); - - if (probes_count > CONFIG_PROBE_POINTS_MAX) { - trace_ipc_error("ipc_probe_point_add() error: Invalid amount of Probe Points specified = %d. Max is " META_QUOTE(CONFIG_PROBE_POINT_MAX) ".", - probes_count); - return -EINVAL; - } - - if (probes_count <= 0) { - trace_ipc_error("ipc_probe_point_add() error: Inferred amount of Probe Points in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", - probes_count); - return -EINVAL; - } - - return probe_point_add(probes_count, params->probe_point); -} - -static inline int ipc_probe_point_remove(uint32_t header) -{ - struct sof_ipc_probe_point_remove_params *params = ipc_get()->comp_data; - int probes_count = params->num_elems; - - tracev_ipc("ipc_probe_point_remove()"); - - if (probes_count > CONFIG_PROBE_POINTS_MAX) { - trace_ipc_error("ipc_probe_point_remove() error: Invalid amount of Probe Points specified = %d. Max is " META_QUOTE(CONFIG_PROBE_POINT_MAX) ".", - probes_count); - return -EINVAL; - } - - if (probes_count <= 0) { - trace_ipc_error("ipc_probe_point_remove() error: Inferred amount of Probe Points in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", - probes_count); - return -EINVAL; - } - return probe_point_remove(probes_count, params->buffer_id); -} - -static int ipc_probe_info(uint32_t header) -{ - uint32_t cmd = iCS(header); - struct sof_ipc_probe_info_params *params = ipc_get()->comp_data; - int ret; - - tracev_ipc("ipc_probe_get_data()"); - - switch (cmd) { - case SOF_IPC_PROBE_DMA_INFO: - ret = probe_dma_info(params, SOF_IPC_MSG_MAX_SIZE); - break; - case SOF_IPC_PROBE_POINT_INFO: - ret = probe_point_info(params, SOF_IPC_MSG_MAX_SIZE); - break; - default: - trace_ipc_error("ipc_probe_info() error: Invalid probe INFO command = %u", - cmd); - ret = -EINVAL; - } - - if (ret < 0) { - trace_ipc_error("ipc_probe_info() error: cmd %u failed", cmd); - return ret; - } - - /* write data to the outbox */ - if (params->rhdr.hdr.size <= MAILBOX_HOSTBOX_SIZE && - params->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) { - params->rhdr.error = ret; - mailbox_hostbox_write(0, params, params->rhdr.hdr.size); - ret = 1; - } else { - trace_ipc_error("ipc_probe_get_data() error: probes module returned too much payload for cmd %u - returned %d bytes, max %d", - cmd, params->rhdr.hdr.size, - MIN(MAILBOX_HOSTBOX_SIZE, - SOF_IPC_MSG_MAX_SIZE)); - ret = -EINVAL; - } - - return ret; -} - -static int ipc_glb_probe(uint32_t header) -{ - uint32_t cmd = iCS(header); - - tracev_ipc("ipc: probe cmd 0x%x", cmd); - - switch (cmd) { - case SOF_IPC_PROBE_INIT: - return ipc_probe_init(header); - case SOF_IPC_PROBE_DEINIT: - return ipc_probe_deinit(header); - case SOF_IPC_PROBE_DMA_ADD: - return ipc_probe_dma_add(header); - case SOF_IPC_PROBE_DMA_REMOVE: - return ipc_probe_dma_remove(header); - case SOF_IPC_PROBE_POINT_ADD: - return ipc_probe_point_add(header); - case SOF_IPC_PROBE_POINT_REMOVE: - return ipc_probe_point_remove(header); - case SOF_IPC_PROBE_DMA_INFO: - case SOF_IPC_PROBE_POINT_INFO: - return ipc_probe_info(header); - default: - trace_ipc_error("ipc: unknown probe cmd 0x%x", cmd); - return -EINVAL; - } -} -#else -static inline int ipc_glb_probe(uint32_t header) -{ - trace_ipc_error("ipc_glb_probe() error: Probes not enabled by Kconfig."); - - return -EINVAL; -} -#endif - -/* - * Topology IPC Operations. - */ - -/* get/set component values or runtime data */ -static int ipc_comp_value(uint32_t header, uint32_t cmd) -{ - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *comp_dev; - struct sof_ipc_ctrl_data data, *_data = ipc->comp_data; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(data, ipc->comp_data); - - /* get the component */ - comp_dev = ipc_get_comp_by_id(ipc, data.comp_id); - if (!comp_dev) { - trace_ipc_error("ipc: comp %d not found", data.comp_id); - return -ENODEV; - } - - /* check core */ - if (!cpu_is_me(comp_dev->core)) - return ipc_process_on_core(comp_dev->core); - - trace_ipc("ipc: comp %d -> cmd %d", data.comp_id, data.cmd); - - /* get component values */ - ret = comp_cmd(comp_dev->cd, cmd, _data, SOF_IPC_MSG_MAX_SIZE); - if (ret < 0) { - trace_ipc_error("ipc: comp %d cmd %u failed %d", data.comp_id, - data.cmd, ret); - return ret; - } - - platform_shared_commit(comp_dev, sizeof(*comp_dev)); - - /* write component values to the outbox */ - if (_data->rhdr.hdr.size <= MAILBOX_HOSTBOX_SIZE && - _data->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) { - mailbox_hostbox_write(0, _data, data.rhdr.hdr.size); - ret = 1; - } else { - trace_ipc_error("ipc: comp %d cmd %u returned %d bytes max %d", - data.comp_id, data.cmd, _data->rhdr.hdr.size, - MIN(MAILBOX_HOSTBOX_SIZE, - SOF_IPC_MSG_MAX_SIZE)); - ret = -EINVAL; - } - - return ret; -} - -static int ipc_glb_comp_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - switch (cmd) { - case SOF_IPC_COMP_SET_VALUE: - return ipc_comp_value(header, COMP_CMD_SET_VALUE); - case SOF_IPC_COMP_GET_VALUE: - return ipc_comp_value(header, COMP_CMD_GET_VALUE); - case SOF_IPC_COMP_SET_DATA: - return ipc_comp_value(header, COMP_CMD_SET_DATA); - case SOF_IPC_COMP_GET_DATA: - return ipc_comp_value(header, COMP_CMD_GET_DATA); - default: - trace_ipc_error("ipc: unknown comp cmd 0x%x", cmd); - return -EINVAL; - } -} - -static int ipc_glb_tplg_comp_new(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_comp comp; - struct sof_ipc_comp_reply reply; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(comp, ipc->comp_data); - - /* check core */ - if (!cpu_is_me(comp.core)) - return ipc_process_on_core(comp.core); - - trace_ipc("ipc: pipe %d comp %d -> new (type %d)", comp.pipeline_id, - comp.id, comp.type); - - /* register component */ - ret = ipc_comp_new(ipc, (struct sof_ipc_comp *)ipc->comp_data); - if (ret < 0) { - trace_ipc_error("ipc: pipe %d comp %d creation failed %d", - comp.pipeline_id, comp.id, ret); - return ret; - } - - /* write component values to the outbox */ - reply.rhdr.hdr.size = sizeof(reply); - reply.rhdr.hdr.cmd = header; - reply.rhdr.error = 0; - reply.offset = 0; /* TODO: set this up for mmaped components */ - mailbox_hostbox_write(0, &reply, sizeof(reply)); - return 1; -} - -static int ipc_glb_tplg_buffer_new(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_buffer ipc_buffer; - struct sof_ipc_comp_reply reply; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(ipc_buffer, ipc->comp_data); - - /* check core */ - if (!cpu_is_me(ipc_buffer.comp.core)) - return ipc_process_on_core(ipc_buffer.comp.core); - - trace_ipc("ipc: pipe %d buffer %d -> new (0x%x bytes)", - ipc_buffer.comp.pipeline_id, ipc_buffer.comp.id, - ipc_buffer.size); - - ret = ipc_buffer_new(ipc, (struct sof_ipc_buffer *)ipc->comp_data); - if (ret < 0) { - trace_ipc_error("ipc: pipe %d buffer %d creation failed %d", - ipc_buffer.comp.pipeline_id, - ipc_buffer.comp.id, ret); - return ret; - } - - /* write component values to the outbox */ - reply.rhdr.hdr.size = sizeof(reply); - reply.rhdr.hdr.cmd = header; - reply.rhdr.error = 0; - reply.offset = 0; /* TODO: set this up for mmaped components */ - mailbox_hostbox_write(0, &reply, sizeof(reply)); - return 1; -} - -static int ipc_glb_tplg_pipe_new(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_pipe_new ipc_pipeline; - struct sof_ipc_comp_reply reply; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(ipc_pipeline, ipc->comp_data); - - /* check core */ - if (!cpu_is_me(ipc_pipeline.core)) - return ipc_process_on_core(ipc_pipeline.core); - - trace_ipc("ipc: pipe %d -> new", ipc_pipeline.pipeline_id); - - ret = ipc_pipeline_new(ipc, - (struct sof_ipc_pipe_new *)ipc->comp_data); - if (ret < 0) { - trace_ipc_error("ipc: pipe %d creation failed %d", - ipc_pipeline.pipeline_id, ret); - return ret; - } - - /* write component values to the outbox */ - reply.rhdr.hdr.size = sizeof(reply); - reply.rhdr.hdr.cmd = header; - reply.rhdr.error = 0; - reply.offset = 0; /* TODO: set this up for mmaped components */ - mailbox_hostbox_write(0, &reply, sizeof(reply)); - return 1; -} - -static int ipc_glb_tplg_pipe_complete(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_pipe_ready ipc_pipeline; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(ipc_pipeline, ipc->comp_data); - - return ipc_pipeline_complete(ipc, ipc_pipeline.comp_id); -} - -static int ipc_glb_tplg_comp_connect(uint32_t header) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_pipe_comp_connect connect; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(connect, ipc->comp_data); - - return ipc_comp_connect(ipc, - (struct sof_ipc_pipe_comp_connect *)ipc->comp_data); -} - -static int ipc_glb_tplg_free(uint32_t header, - int (*free_func)(struct ipc *ipc, uint32_t id)) -{ - struct ipc *ipc = ipc_get(); - struct sof_ipc_free ipc_free; - int ret; - - /* copy message with ABI safe method */ - IPC_COPY_CMD(ipc_free, ipc->comp_data); - - trace_ipc("ipc: comp %d -> free", ipc_free.id); - - /* free the object */ - ret = free_func(ipc, ipc_free.id); - - if (ret < 0) { - trace_ipc_error("ipc: comp %d free failed %d", - ipc_free.id, ret); - } - - return ret; -} - -static int ipc_glb_tplg_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - switch (cmd) { - case SOF_IPC_TPLG_COMP_NEW: - return ipc_glb_tplg_comp_new(header); - case SOF_IPC_TPLG_COMP_FREE: - return ipc_glb_tplg_free(header, ipc_comp_free); - case SOF_IPC_TPLG_COMP_CONNECT: - return ipc_glb_tplg_comp_connect(header); - case SOF_IPC_TPLG_PIPE_NEW: - return ipc_glb_tplg_pipe_new(header); - case SOF_IPC_TPLG_PIPE_COMPLETE: - return ipc_glb_tplg_pipe_complete(header); - case SOF_IPC_TPLG_PIPE_FREE: - return ipc_glb_tplg_free(header, ipc_pipeline_free); - case SOF_IPC_TPLG_BUFFER_NEW: - return ipc_glb_tplg_buffer_new(header); - case SOF_IPC_TPLG_BUFFER_FREE: - return ipc_glb_tplg_free(header, ipc_buffer_free); - default: - trace_ipc_error("ipc: unknown tplg header 0x%x", header); - return -EINVAL; - } -} - -#if CONFIG_DEBUG -static int ipc_glb_test_message(uint32_t header) -{ - uint32_t cmd = iCS(header); - - switch (cmd) { - case SOF_IPC_TEST_IPC_FLOOD: - return 0; /* just return so next IPC can be sent */ - default: - trace_ipc_error("ipc: unknown test header 0x%x", header); - return -EINVAL; - } -} -#endif - -/* - * Global IPC Operations. - */ - -void ipc_cmd(struct sof_ipc_cmd_hdr *hdr) -{ - struct sof_ipc_reply reply; - uint32_t type = 0; - int ret; - - if (hdr == NULL) { - trace_ipc_error("ipc: invalid IPC header."); - ret = -EINVAL; - goto out; - } - - type = iGS(hdr->cmd); - - switch (type) { - case SOF_IPC_GLB_REPLY: - ret = 0; - break; - case SOF_IPC_GLB_COMPOUND: - ret = -EINVAL; /* TODO */ - break; - case SOF_IPC_GLB_TPLG_MSG: - ret = ipc_glb_tplg_message(hdr->cmd); - break; - case SOF_IPC_GLB_PM_MSG: - ret = ipc_glb_pm_message(hdr->cmd); - break; - case SOF_IPC_GLB_COMP_MSG: - ret = ipc_glb_comp_message(hdr->cmd); - break; - case SOF_IPC_GLB_STREAM_MSG: - ret = ipc_glb_stream_message(hdr->cmd); - break; - case SOF_IPC_GLB_DAI_MSG: - ret = ipc_glb_dai_message(hdr->cmd); - break; - case SOF_IPC_GLB_TRACE_MSG: - ret = ipc_glb_debug_message(hdr->cmd); - break; - case SOF_IPC_GLB_GDB_DEBUG: - ret = ipc_glb_gdb_debug(hdr->cmd); - break; - case SOF_IPC_GLB_PROBE: - ret = ipc_glb_probe(hdr->cmd); - break; -#if CONFIG_DEBUG - case SOF_IPC_GLB_TEST: - ret = ipc_glb_test_message(hdr->cmd); - break; -#endif - default: - trace_ipc_error("ipc: unknown command type %u", type); - ret = -EINVAL; - break; - } - - platform_shared_commit(hdr, hdr->size); - -out: - tracev_ipc("ipc: last request %d returned %d", type, ret); - - /* if ret > 0, reply created and copied by cmd() */ - if (ret <= 0) { - /* send std error/ok reply */ - reply.error = ret; - - reply.hdr.cmd = SOF_IPC_GLB_REPLY; - reply.hdr.size = sizeof(reply); - mailbox_hostbox_write(0, &reply, sizeof(reply)); - } -} - -void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) -{ - struct ipc *ipc = ipc_get(); - uint32_t flags; - int ret; - - spin_lock_irq(&ipc->lock, flags); - - /* copy mailbox data to message */ - if (msg->tx_size > 0 && msg->tx_size < SOF_IPC_MSG_MAX_SIZE) { - ret = memcpy_s(msg->tx_data, msg->tx_size, data, msg->tx_size); - assert(!ret); - } - - /* try to send critical notifications right away */ - if (high_priority) { - ret = ipc_platform_send_msg(msg); - if (!ret) - goto out; - } - - /* add to queue unless already there */ - if (list_is_empty(&msg->list)) { - if (high_priority) - list_item_prepend(&msg->list, &ipc->msg_list); - else - list_item_append(&msg->list, &ipc->msg_list); - } - -out: - platform_shared_commit(msg->tx_data, msg->tx_size); - platform_shared_commit(msg, sizeof(*msg)); - platform_shared_commit(ipc, sizeof(*ipc)); - - spin_unlock_irq(&ipc->lock, flags); -} - -void ipc_schedule_process(struct ipc *ipc) -{ - schedule_task(&ipc->ipc_task, 0, 100); - - platform_shared_commit(ipc, sizeof(*ipc)); -} diff --git a/src/ipc/ipc-common.c b/src/ipc/ipc-common.c new file mode 100644 index 000000000000..d0d248c9ec77 --- /dev/null +++ b/src/ipc/ipc-common.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/debug/gdb/gdb.h> +#include <rtos/idc.h> +#include <rtos/symbol.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <sof/debug/telemetry/performance_monitor.h> + +LOG_MODULE_REGISTER(ipc, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(ipc); + +DECLARE_TR_CTX(ipc_tr, SOF_UUID(ipc_uuid), LOG_LEVEL_INFO); + +int ipc_process_on_core(uint32_t core, bool blocking) +{ + struct ipc *ipc = ipc_get(); + struct idc_msg msg = { .header = IDC_MSG_IPC, .core = core, }; + int ret; + + /* check if requested core is enabled */ + if (!cpu_is_core_enabled(core)) { + tr_err(&ipc_tr, "core #%d is disabled", core); + return -EACCES; + } + +#if CONFIG_IPC_MAJOR_3 + /* The other core will write there its response */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, + ((struct sof_ipc_cmd_hdr *)ipc->comp_data)->size); +#endif + + /* + * If the primary core is waiting for secondary cores to complete, it + * will also reply to the host + */ + if (!blocking) { + k_spinlock_key_t key; + + ipc->core = core; + key = k_spin_lock(&ipc->lock); + ipc->task_mask |= IPC_TASK_SECONDARY_CORE; + k_spin_unlock(&ipc->lock, key); + } + + /* send IDC message */ + ret = idc_send_msg(&msg, blocking ? IDC_BLOCKING : IDC_NON_BLOCKING); + if (ret < 0) + return ret; + + /* reply written by other core */ + return 1; +} + +/* + * Components, buffers and pipelines are stored in the same lists, hence + * type and ID have to be used for the identification. + */ +struct ipc_comp_dev *ipc_get_comp_dev(struct ipc *ipc, uint16_t type, uint32_t id) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->id == id && (type == icd->type || type == COMP_TYPE_ANY)) + return icd; + } + + return NULL; +} +EXPORT_SYMBOL(ipc_get_comp_dev); + +/* Walks through the list of components looking for a sink/source endpoint component + * of the given pipeline + */ +struct ipc_comp_dev *ipc_get_ppl_comp(struct ipc *ipc, uint32_t pipeline_id, int dir) +{ + struct ipc_comp_dev *icd; + struct comp_buffer *buffer; + struct comp_dev *buff_comp; + struct list_item *clist, *blist; + struct ipc_comp_dev *next_ppl_icd = NULL; + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + /* first try to find the module in the pipeline */ + if (dev_comp_pipe_id(icd->cd) == pipeline_id) { + struct list_item *buffer_list = comp_buffer_list(icd->cd, dir); + bool last_in_pipeline = true; + + /* The component has no buffer in the given direction */ + if (list_is_empty(buffer_list)) + return icd; + + /* check all connected modules to see if they are on different pipelines */ + list_for_item(blist, buffer_list) { + buffer = buffer_from_list(blist, dir); + buff_comp = buffer_get_comp(buffer, dir); + + if (buff_comp && dev_comp_pipe_id(buff_comp) == pipeline_id) + last_in_pipeline = false; + } + /* all connected components placed on another pipeline */ + if (last_in_pipeline) + next_ppl_icd = icd; + } + } + + return next_ppl_icd; +} + +void ipc_send_queued_msg(void) +{ + struct ipc *ipc = ipc_get(); + struct ipc_msg *msg; + k_spinlock_key_t key; + + key = k_spin_lock(&ipc->lock); + + if (ipc->pm_prepare_D3) + goto out; + + /* any messages to send ? */ + if (list_is_empty(&ipc->msg_list)) + goto out; + + msg = list_first_item(&ipc->msg_list, struct ipc_msg, + list); + + if (ipc_platform_send_msg(msg) == 0) { + /* Remove the message from the list if it has been successfully sent. */ + list_item_del(&msg->list); + /* Invoke a callback to notify that the message has been sent. */ + if (msg->callback) + msg->callback(msg); +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Increment performance counters */ + io_perf_monitor_update_data(ipc->io_perf_out_msg_count, 1); +#endif + } +out: + k_spin_unlock(&ipc->lock, key); +} + +#ifdef __ZEPHYR__ +static K_THREAD_STACK_DEFINE(ipc_send_wq_stack, CONFIG_STACK_SIZE_IPC_TX); +#endif + +static void schedule_ipc_worker(void) +{ + /* + * note: in XTOS builds, this is handled in + * task_main_primary_core() + */ +#ifdef __ZEPHYR__ + struct ipc *ipc = ipc_get(); + + k_work_schedule_for_queue(&ipc->ipc_send_wq, &ipc->z_delayed_work, K_USEC(IPC_PERIOD_USEC)); +#endif +} + +__cold void ipc_msg_send_direct(struct ipc_msg *msg, void *data) +{ + struct ipc *ipc = ipc_get(); + k_spinlock_key_t key; + int ret; + + assert_can_be_cold(); + + key = k_spin_lock(&ipc->lock); + + /* copy mailbox data to message if not already copied */ + if (data && 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(); + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&ipc->lock); + + /* copy mailbox data to message if not already copied */ + if (data && (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); + } + + /* + * note: This function can be executed in LL or EDF context, from any core. + * In Zephyr builds, there is IPC queue that is always handled by the primary core, + * whereas submitting to the queue is allowed from any core. Therefore disable option + * of sending IPC immediately by any context/core to secure IPC registers/mailbox + * access. + */ +#ifndef __ZEPHYR__ + /* try to send critical notifications right away */ + if (high_priority) { + ret = ipc_platform_send_msg(msg); + if (!ret) { + k_spin_unlock(&ipc->lock, key); + return; + } + } +#endif + /* add to queue unless already there */ + if (list_is_empty(&msg->list)) { + if (high_priority) + list_item_prepend(&msg->list, &ipc->msg_list); + else + list_item_append(&msg->list, &ipc->msg_list); + } + + schedule_ipc_worker(); + + k_spin_unlock(&ipc->lock, key); +} +EXPORT_SYMBOL(ipc_msg_send); + +#ifdef __ZEPHYR__ +static void ipc_work_handler(struct k_work *work) +{ + struct ipc *ipc = ipc_get(); + k_spinlock_key_t key; + + ipc_send_queued_msg(); + + key = k_spin_lock(&ipc->lock); + + if (!list_is_empty(&ipc->msg_list) && !ipc->pm_prepare_D3) + schedule_ipc_worker(); + + k_spin_unlock(&ipc->lock, key); +} +#endif + +void ipc_schedule_process(struct ipc *ipc) +{ +#if CONFIG_TWB_IPC_TASK + schedule_task(ipc->ipc_task, 0, IPC_PERIOD_USEC); +#else + schedule_task(&ipc->ipc_task, 0, IPC_PERIOD_USEC); +#endif +} + +__cold int ipc_init(struct sof *sof) +{ + assert_can_be_cold(); + + tr_dbg(&ipc_tr, "entry"); + +#if CONFIG_SOF_BOOT_TEST_STANDALONE + LOG_INF("SOF_BOOT_TEST_STANDALONE, disabling IPC."); + return 0; +#endif + + /* init ipc data */ + sof->ipc = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*sof->ipc)); + if (!sof->ipc) { + tr_err(&ipc_tr, "Unable to allocate IPC data"); + return -ENOMEM; + } + sof->ipc->comp_data = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + SOF_IPC_MSG_MAX_SIZE); + if (!sof->ipc->comp_data) { + tr_err(&ipc_tr, "Unable to allocate IPC component data"); + rfree(sof->ipc); + return -ENOMEM; + } + + k_spinlock_init(&sof->ipc->lock); + list_init(&sof->ipc->msg_list); + list_init(&sof->ipc->comp_list); + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + struct io_perf_data_item init_data = {IO_PERF_IPC_ID, + cpu_get_id(), + IO_PERF_INPUT_DIRECTION, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 }; + io_perf_monitor_init_data(&sof->ipc->io_perf_in_msg_count, &init_data); + init_data.direction = IO_PERF_OUTPUT_DIRECTION; + io_perf_monitor_init_data(&sof->ipc->io_perf_out_msg_count, &init_data); +#endif + +#ifdef __ZEPHYR__ + struct k_thread *thread = &sof->ipc->ipc_send_wq.thread; + + k_work_queue_start(&sof->ipc->ipc_send_wq, ipc_send_wq_stack, + K_THREAD_STACK_SIZEOF(ipc_send_wq_stack), 1, NULL); + + k_thread_suspend(thread); + +#ifdef CONFIG_SCHED_CPU_MASK + k_thread_cpu_pin(thread, PLATFORM_PRIMARY_CORE_ID); +#endif + k_thread_name_set(thread, "ipc_send_wq"); + + k_thread_resume(thread); + + k_work_init_delayable(&sof->ipc->z_delayed_work, ipc_work_handler); +#endif + + return platform_ipc_init(sof->ipc); +} + +/* Locking: call with ipc->lock held and interrupts disabled */ +void ipc_complete_cmd(struct ipc *ipc) +{ + /* + * We have up to three contexts, attempting to complete IPC processing: + * the original IPC EDF task, the IDC EDF task on a secondary core, or + * an LL pipeline thread, running either on the primary or one of + * secondary cores. All these three contexts execute asynchronously. It + * is important to only signal the host that the IPC processing has + * completed after *all* tasks have completed. Therefore only the last + * context should do that. We accomplish this by setting IPC_TASK_* bits + * in ipc->task_mask for each used IPC context and by clearing them when + * each of those contexts completes. Only when the mask is 0 we can + * signal the host. + */ + if (ipc->task_mask) + return; + + ipc_platform_complete_cmd(ipc); +} + +bool ipc_enter_gdb; + +__attribute__((weak)) void ipc_platform_wait_ack(struct ipc *ipc) +{ + k_msleep(1); +} + +static void ipc_complete_task(void *data) +{ + struct ipc *ipc = data; + k_spinlock_key_t key; + + key = k_spin_lock(&ipc->lock); + ipc->task_mask &= ~IPC_TASK_INLINE; + ipc_complete_cmd(ipc); + k_spin_unlock(&ipc->lock, key); +#if CONFIG_GDBSTUB + if (ipc_enter_gdb) { + ipc_enter_gdb = false; + ipc_platform_wait_ack(ipc); + gdb_init(); + } +#endif +} + +static enum task_state ipc_do_cmd(void *data) +{ + struct ipc *ipc = data; + +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Increment performance counters */ + io_perf_monitor_update_data(ipc->io_perf_in_msg_count, 1); +#endif + + /* + * 32-bit writes are atomic and at the moment no IPC processing is + * taking place, so, no need for a lock. + */ + ipc->task_mask = IPC_TASK_INLINE; + + return ipc_platform_do_cmd(ipc); +} + +struct task_ops ipc_task_ops = { + .run = ipc_do_cmd, + .complete = ipc_complete_task, + .get_deadline = ipc_task_deadline, +}; diff --git a/src/ipc/ipc-helper.c b/src/ipc/ipc-helper.c new file mode 100644 index 000000000000..ad7b3771a16b --- /dev/null +++ b/src/ipc/ipc-helper.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Author: Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/debug/telemetry/performance_monitor.h> +#include <rtos/idc.h> +#include <rtos/interrupt.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/schedule.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <rtos/symbol.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +__cold static bool valid_ipc_buffer_desc(const struct sof_ipc_buffer *desc) +{ + assert_can_be_cold(); + + if (desc->caps >= SOF_MEM_CAPS_LOWEST_INVALID) + return false; + + /* TODO: check desc->size and maybe other things */ + return true; +} + +/* create a new component in the pipeline */ +__cold struct comp_buffer *buffer_new(struct mod_alloc_ctx *alloc, + const struct sof_ipc_buffer *desc, bool is_shared) +{ + struct comp_buffer *buffer; + uint32_t flags = desc->flags; + + assert_can_be_cold(); + + tr_info(&buffer_tr, "buffer new size 0x%x id %d.%d flags 0x%x", + desc->size, desc->comp.pipeline_id, desc->comp.id, desc->flags); + + if (!valid_ipc_buffer_desc(desc)) { + tr_err(&buffer_tr, "Invalid buffer desc! New size 0x%x id %d.%d caps 0x%x", + desc->size, desc->comp.pipeline_id, desc->comp.id, desc->caps); + return NULL; + } + + /* memory zones and caps are deprecated - convert to flags */ + if (desc->caps & SOF_MEM_CAPS_DMA) + flags |= SOF_MEM_FLAG_DMA; + if (desc->caps & SOF_MEM_CAPS_LP) + flags |= SOF_MEM_FLAG_LOW_POWER; + if (desc->caps & SOF_MEM_CAPS_L3) + flags |= SOF_MEM_FLAG_L3; + if (desc->caps) + tr_warn(&buffer_tr, "Deprecated buffer caps 0x%x used, convert to flags 0x%x", + desc->caps, flags); + + /* allocate buffer */ + buffer = buffer_alloc(alloc, desc->size, flags, PLATFORM_DCACHE_ALIGN, + is_shared); + if (buffer) { + buffer->stream.runtime_stream_params.id = desc->comp.id; + buffer->stream.runtime_stream_params.pipeline_id = desc->comp.pipeline_id; + buffer->core = desc->comp.core; + + memcpy_s(&buffer->tctx, sizeof(struct tr_ctx), + &buffer_tr, sizeof(struct tr_ctx)); + } + + return buffer; +} + +/* Called from multiple locations, including ipc_get_comp_by_ppl_id(), so cannot be cold */ +int32_t ipc_comp_pipe_id(const struct ipc_comp_dev *icd) +{ + switch (icd->type) { + case COMP_TYPE_COMPONENT: + return dev_comp_pipe_id(icd->cd); + case COMP_TYPE_BUFFER: + return buffer_pipeline_id(icd->cb); + case COMP_TYPE_PIPELINE: + return icd->pipeline->pipeline_id; + default: + tr_err(&ipc_tr, "Unknown ipc component type %u", icd->type); + return -EINVAL; + }; + + return 0; +} + +/* Function overwrites PCM parameters (frame_fmt, buffer_fmt, channels, rate) + * with buffer parameters when specific flag is set. + */ +static void comp_update_params(uint32_t flag, + struct sof_ipc_stream_params *params, + struct comp_buffer *buffer) +{ + if (flag & BUFF_PARAMS_FRAME_FMT) + params->frame_fmt = audio_stream_get_frm_fmt(&buffer->stream); + + if (flag & BUFF_PARAMS_BUFFER_FMT) + params->buffer_fmt = audio_stream_get_buffer_fmt(&buffer->stream); + + if (flag & BUFF_PARAMS_CHANNELS) + params->channels = audio_stream_get_channels(&buffer->stream); + + if (flag & BUFF_PARAMS_RATE) + params->rate = audio_stream_get_rate(&buffer->stream); +} + +int comp_verify_params(struct comp_dev *dev, uint32_t flag, + struct sof_ipc_stream_params *params) +{ + struct list_item *source_list; + struct list_item *sink_list; + struct comp_buffer *sinkb; + struct comp_buffer *buf; + int dir = dev->direction; + + if (!params) { + comp_err(dev, "!params"); + return -EINVAL; + } + + source_list = comp_buffer_list(dev, PPL_DIR_UPSTREAM); + sink_list = comp_buffer_list(dev, PPL_DIR_DOWNSTREAM); + + /* searching for endpoint component e.g. HOST, DETECT_TEST, which + * has only one sink or one source buffer. + */ + if (list_is_empty(source_list) != list_is_empty(sink_list)) { + if (list_is_empty(sink_list)) + buf = comp_dev_get_first_data_producer(dev); + else + buf = comp_dev_get_first_data_consumer(dev); + + /* update specific pcm parameter with buffer parameter if + * specific flag is set. + */ + comp_update_params(flag, params, buf); + + /* overwrite buffer parameters with modified pcm + * parameters + */ + buffer_set_params(buf, params, BUFFER_UPDATE_FORCE); + + /* set component period frames */ + component_set_nearest_period_frames(dev, audio_stream_get_rate(&buf->stream)); + } else if (list_is_empty(source_list)) { + /* + * both lists are empty, e.g. if it's the single component in a + * pipeline and no other pipelines are currently connected, then + * there's just nothing to update + */ + comp_dbg(dev, "no connected buffers"); + } else { + /* for other components we iterate over all downstream buffers + * (for playback) or upstream buffers (for capture). + */ + if (dir == PPL_DIR_DOWNSTREAM) { + comp_dev_for_each_consumer(dev, buf) { + comp_update_params(flag, params, buf); + buffer_set_params(buf, params, + BUFFER_UPDATE_FORCE); + } + } else { + comp_dev_for_each_producer(dev, buf) { + comp_update_params(flag, params, buf); + buffer_set_params(buf, params, + BUFFER_UPDATE_FORCE); + } + } + + /* fetch sink buffer in order to calculate period frames */ + sinkb = comp_dev_get_first_data_consumer(dev); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&sinkb->stream)); + } + + return 0; +} +EXPORT_SYMBOL(comp_verify_params); + +__cold int comp_buffer_connect(struct comp_dev *comp, uint32_t comp_core, + struct comp_buffer *buffer, uint32_t dir) +{ + assert_can_be_cold(); + + /* check if it's a connection between cores */ + if (buffer->core != comp_core) { +#if CONFIG_INCOHERENT + /* buffer must be shared */ + assert(audio_buffer_is_shared(&buffer->audio_buffer)); +#else + buffer->audio_buffer.is_shared = true; +#endif + if (!comp->is_shared) + comp_make_shared(comp); + } + + return pipeline_connect(comp, buffer, dir); +} + +int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_pipe; + struct ipc_comp_dev *icd; + struct pipeline *p; + uint32_t pipeline_id; + struct ipc_comp_dev *ipc_ppl_source; + struct ipc_comp_dev *ipc_ppl_sink; + + /* check whether pipeline exists */ + ipc_pipe = ipc_get_pipeline_by_id(ipc, comp_id); + if (!ipc_pipe) { + tr_err(&ipc_tr, "ipc: looking for pipe component id 0x%x failed", + comp_id); + return -EINVAL; + } + + /* check core */ + if (!cpu_is_me(ipc_pipe->core)) + return ipc_process_on_core(ipc_pipe->core, false); + + p = ipc_pipe->pipeline; + + /* get pipeline source component */ + ipc_ppl_source = ipc_get_ppl_src_comp(ipc, p->pipeline_id); + if (!ipc_ppl_source) { + tr_err(&ipc_tr, "ipc: looking for pipeline source failed"); + return -EINVAL; + } + + /* get pipeline sink component */ + ipc_ppl_sink = ipc_get_ppl_sink_comp(ipc, p->pipeline_id); + if (!ipc_ppl_sink) { + tr_err(&ipc_tr, "ipc: looking for pipeline sink failed"); + return -EINVAL; + } + + /* find the scheduling component */ + icd = ipc_get_comp_by_id(ipc, p->sched_id); + if (!icd) { + tr_warn(&ipc_tr, "no scheduling component specified, use comp 0x%x", + ipc_ppl_sink->id); + + icd = ipc_ppl_sink; + } + + if (icd->core != ipc_pipe->core) { + tr_err(&ipc_tr, "icd->core (%d) != ipc_pipe->core (%d) for pipeline scheduling component icd->id 0x%x", + icd->core, ipc_pipe->core, icd->id); + return -EINVAL; + } + + p->sched_comp = icd->cd; + + pipeline_id = ipc_pipe->pipeline->pipeline_id; + + tr_dbg(&ipc_tr, "ipc: pipe %d -> complete on comp 0x%x", pipeline_id, + comp_id); + + return pipeline_complete(ipc_pipe->pipeline, ipc_ppl_source->cd, + ipc_ppl_sink->cd); +} + +__cold int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) +{ + struct ipc_comp_dev *icd; + struct comp_buffer *buffer; + struct comp_buffer *safe; + uint32_t flags; + + assert_can_be_cold(); + + /* check whether component exists */ + icd = ipc_get_comp_by_id(ipc, comp_id); + if (!icd) { + tr_err(&ipc_tr, "comp id: 0x%x is not found", + comp_id); + return -ENODEV; + } + + /* check core */ + if (!cpu_is_me(icd->core)) + return ipc_process_on_core(icd->core, false); + + /* check state */ + if (icd->cd->state != COMP_STATE_READY) { + tr_err(&ipc_tr, "comp id: 0x%x state is %d cannot be freed", + comp_id, icd->cd->state); + return -EINVAL; + } + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + free_performance_data(icd->cd->perf_data.perf_data_item); +#endif + + if (!icd->cd->bsource_list.next || !icd->cd->bsink_list.next) { + /* Unfortunate: the buffer list node gets initialized + * at the component level and thus can contain NULLs + * (which is an invalid list!) if the component's + * lifecycle hasn't reached that point. There's no + * single place to ensure a valid/empty list, so we + * have to do it here and eat the resulting memory + * leak on error. Bug-free host drivers won't do + * this, this was found via fuzzing. + */ + tr_err(&ipc_tr, "uninitialized buffer lists on comp 0x%x\n", + icd->id); + return -EINVAL; + } + + irq_local_disable(flags); + comp_dev_for_each_producer_safe(icd->cd, buffer, safe) { + comp_buffer_set_sink_component(buffer, NULL); + /* This breaks the list, but we anyway delete all buffers */ + comp_buffer_reset_sink_list(buffer); + } + + comp_dev_for_each_consumer_safe(icd->cd, buffer, safe) { + comp_buffer_set_source_component(buffer, NULL); + /* This breaks the list, but we anyway delete all buffers */ + comp_buffer_reset_source_list(buffer); + } + + irq_local_enable(flags); + + /* free component and remove from list */ + comp_free(icd->cd); + + icd->cd = NULL; + + list_item_del(&icd->list); + rfree(icd); + + return 0; +} diff --git a/src/ipc/ipc-host-ptable.c b/src/ipc/ipc-host-ptable.c deleted file mode 100644 index db14f286886d..000000000000 --- a/src/ipc/ipc-host-ptable.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dma.h> -#include <sof/platform.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stdint.h> - -/* - * Parse the host page tables and create the audio DMA SG configuration - * for host audio DMA buffer. This involves creating a dma_sg_elem for each - * page table entry and adding each elem to a list in struct dma_sg_config. - */ -static int ipc_parse_page_descriptors(uint8_t *page_table, - struct sof_ipc_host_buffer *ring, - struct dma_sg_elem_array *elem_array, - uint32_t direction) -{ - int i; - uint32_t idx; - uint32_t phy_addr; - struct dma_sg_elem *e; - - /* the ring size may be not multiple of the page size, the last - * page may be not full used. The used size should be in range - * of (ring->pages - 1, ring->pages] * PAGES. - */ - if ((ring->size <= HOST_PAGE_SIZE * (ring->pages - 1)) || - (ring->size > HOST_PAGE_SIZE * ring->pages)) { - /* error buffer size */ - trace_ipc_error("ipc_parse_page_descriptors() error: " - "error buffer size"); - return -EINVAL; - } - - elem_array->elems = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(struct dma_sg_elem) * ring->pages); - if (!elem_array->elems) { - trace_ipc_error("ipc_parse_page_descriptors() error: " - "There is no heap free with this block size: %d", - sizeof(struct dma_sg_elem) * ring->pages); - return -ENOMEM; - } - - elem_array->count = ring->pages; - - for (i = 0; i < ring->pages; i++) { - idx = (((i << 2) + i)) >> 1; - phy_addr = page_table[idx] | (page_table[idx + 1] << 8) - | (page_table[idx + 2] << 16); - - if (i & 0x1) - phy_addr <<= 8; - else - phy_addr <<= 12; - phy_addr &= 0xfffff000; - - e = elem_array->elems + i; - - if (direction == SOF_IPC_STREAM_PLAYBACK) - e->src = phy_addr; - else - e->dest = phy_addr; - - /* the last page may be not full used */ - if (i == (ring->pages - 1)) - e->size = ring->size - HOST_PAGE_SIZE * i; - else - e->size = HOST_PAGE_SIZE; - } - - return 0; -} - -/* - * Copy the audio buffer page tables from the host to the DSP max of 4K. - */ -static int ipc_get_page_descriptors(struct dma *dmac, uint8_t *page_table, - struct sof_ipc_host_buffer *ring) -{ - struct dma_sg_config config; - struct dma_sg_elem elem; - struct dma_chan_data *chan; - int ret = 0; - - /* get DMA channel from DMAC */ - chan = dma_channel_get(dmac, 0); - if (!chan) { - trace_ipc_error("ipc_get_page_descriptors() error: chan is " - "NULL"); - return -ENODEV; - } - - /* set up DMA configuration */ - config.direction = DMA_DIR_HMEM_TO_LMEM; - config.src_width = sizeof(uint32_t); - config.dest_width = sizeof(uint32_t); - config.cyclic = 0; - config.irq_disabled = false; - dma_sg_init(&config.elem_array); - - /* set up DMA descriptor */ - elem.dest = (uint32_t)page_table; - elem.src = ring->phy_addr; - - /* source buffer size is always PAGE_SIZE bytes */ - /* 20 bits for each page, round up to 32 */ - elem.size = (ring->pages * 5 * 16 + 31) / 32; - config.elem_array.elems = &elem; - config.elem_array.count = 1; - - ret = dma_set_config(chan, &config); - if (ret < 0) { - trace_ipc_error("ipc_get_page_descriptors() error: " - "dma_set_config() failed"); - goto out; - } - - /* start the copy of page table to DSP */ - ret = dma_copy(chan, elem.size, DMA_COPY_ONE_SHOT | DMA_COPY_BLOCKING); - if (ret < 0) { - trace_ipc_error("ipc_get_page_descriptors() error: " - "dma_start() failed"); - goto out; - } - - /* compressed page tables now in buffer at _ipc->page_table */ -out: - dma_channel_put(chan); - return ret; -} - -int ipc_process_host_buffer(struct ipc *ipc, - struct sof_ipc_host_buffer *ring, - uint32_t direction, - struct dma_sg_elem_array *elem_array, - uint32_t *ring_size) -{ - struct ipc_data_host_buffer *data_host_buffer; - int err; - - data_host_buffer = ipc_platform_get_host_buffer(ipc); - dma_sg_init(elem_array); - - /* use DMA to read in compressed page table ringbuffer from host */ - err = ipc_get_page_descriptors(data_host_buffer->dmac, - data_host_buffer->page_table, - ring); - if (err < 0) { - trace_ipc_error("ipc: get descriptors failed %d", err); - goto error; - } - - *ring_size = ring->size; - - err = ipc_parse_page_descriptors(data_host_buffer->page_table, - ring, - elem_array, direction); - if (err < 0) { - trace_ipc_error("ipc: parse descriptors failed %d", err); - goto error; - } - - return 0; -error: - dma_sg_free(elem_array); - return err; -} diff --git a/src/ipc/ipc-zephyr.c b/src/ipc/ipc-zephyr.c new file mode 100644 index 000000000000..66ada4ddaa05 --- /dev/null +++ b/src/ipc/ipc-zephyr.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Rander Wang <rander.wang@intel.com> +// Serhiy Katsyuba <serhiy.katsyuba@intel.com> +// Andrey Borisovich <andrey.borisovich@intel.com> +// Adrian Warecki <adrian.warecki@intel.com> + +#include <autoconf.h> + +#include <zephyr/kernel.h> +#include <zephyr/ipc/ipc_service.h> +#ifdef CONFIG_INTEL_ADSP_IPC +#include <zephyr/ipc/backends/intel_adsp_host_ipc.h> +#include <intel_adsp_ipc.h> +#endif + +#include <sof/ipc/common.h> + +#include <sof/ipc/schedule.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#if defined(CONFIG_PM) +#include <sof/lib/cpu.h> +#include <zephyr/pm/device.h> +#include <zephyr/pm/state.h> +#include <zephyr/irq.h> +#include <zephyr/pm/policy.h> +#else +#include <sof/lib/pm_runtime.h> +#endif /* CONFIG_PM */ +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/twb_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/header.h> +#include <sof/ipc/msg.h> +#include <ipc4/notification.h> + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(zipc_task); + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +/** + * @brief Private data for IPC. + * + * Written in interrupt context to service incoming IPC message using registered + * cAVS IPC Message Handler Callback (message_handler function). + * Filled with content of TDR and TDD registers. + * When IPC message is read fills ipc_cmd_hdr. + */ +static uint32_t g_last_data, g_last_ext_data; +static struct ipc_ept sof_ipc_ept; +static struct ipc_ept_cfg sof_ipc_ept_cfg; + +BUILD_ASSERT(sizeof(struct ipc_cmd_hdr) == sizeof(uint32_t) * 2, + "ipc_cmd_hdr must be exactly two 32-bit words"); + +/** + * @brief SOF IPC receive callback for Zephyr IPC service. + * + * This callback is invoked by the Zephyr IPC service backend when a compact 2-word IPC message + * arrives from the host. It stores the raw header words in g_last_data/g_last_ext_data and + * schedules the SOF IPC task to process the command via ipc_platform_do_cmd(). + */ +static void sof_ipc_receive_cb(const void *data, size_t len, void *priv) +{ + struct ipc *ipc = (struct ipc *)priv; + const uint32_t *msg = data; + k_spinlock_key_t key; + + __ASSERT(len == sizeof(uint32_t) * 2, "Unexpected IPC message length: %zu", len); + __ASSERT(data, "IPC data pointer is NULL"); + + key = k_spin_lock(&ipc->lock); + + g_last_data = msg[0]; + g_last_ext_data = msg[1]; + +#if CONFIG_DEBUG_IPC_COUNTERS + increment_ipc_received_counter(); +#endif + ipc_schedule_process(ipc); + + k_spin_unlock(&ipc->lock, key); +} + +#ifdef CONFIG_PM_DEVICE +/** + * @brief IPC device suspend handler callback function. + * Checks whether device power state should be actually changed. + * + * @param dev IPC device. + * @param arg IPC struct pointer. + */ +static int ipc_device_suspend_handler(const struct device *dev, void *arg) +{ + struct ipc *ipc = (struct ipc *)arg; + + int ret = 0; + + if (!(ipc->task_mask & IPC_TASK_POWERDOWN)) { + tr_err(&ipc_tr, + "ipc task mask not set to IPC_TASK_POWERDOWN. Current value: %u", + ipc->task_mask); + ret = -ENOMSG; + } + + if (!ipc->pm_prepare_D3) { + tr_err(&ipc_tr, "power state D3 not requested"); + ret = -EBADMSG; + } + + if (!list_is_empty(&ipc->msg_list)) { + struct list_item *slist; + struct ipc_msg *msg; + /* The only possible message that can be added during power transition procedure is + * SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS. + */ + const uint32_t exp_hdr = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS); + bool only_buff_status = true; + + list_for_item(slist, &ipc->msg_list) { + msg = container_of(slist, struct ipc_msg, list); + + if (msg->header != exp_hdr) + only_buff_status = false; + } + + if (only_buff_status) { + tr_warn(&ipc_tr, "continuing D3 procedure with the msg in the queue"); + } else { + tr_err(&ipc_tr, "there are queued IPC messages to be sent"); + ret = -EINPROGRESS; + } + } + + if (ret != 0) + ipc_send_failed_power_transition_response(); + + return ret; +} + +/** + * @brief IPC device resume handler callback function. + * Resets IPC control after context restore. + * + * @param dev IPC device. + * @param arg IPC struct pointer. + */ +static int ipc_device_resume_handler(const struct device *dev, void *arg) +{ + struct ipc *ipc = (struct ipc *)arg; + + ipc_set_drvdata(ipc, NULL); + ipc->task_mask = 0; + ipc->pm_prepare_D3 = false; + + /* schedule task */ +#if CONFIG_TWB_IPC_TASK + scheduler_twb_task_init(&ipc->ipc_task, SOF_UUID(zipc_task_uuid), + &ipc_task_ops, ipc, 0, "IPC", ZEPHYR_TWB_STACK_SIZE, + CONFIG_TWB_THREAD_MEDIUM_PRIORITY, ZEPHYR_TWB_BUDGET_MAX / 2); +#else + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(zipc_task_uuid), + &ipc_task_ops, ipc, 0, 0); +#endif + return 0; +} +#endif /* CONFIG_PM_DEVICE */ + +#if CONFIG_DEBUG_IPC_COUNTERS + +static inline void increment_ipc_received_counter(void) +{ + static uint32_t ipc_received_counter; + + mailbox_sw_reg_write(SRAM_REG_FW_IPC_RECEIVED_COUNT, + ipc_received_counter++); +} + +static inline void increment_ipc_processed_counter(void) +{ + static uint32_t ipc_processed_counter; + uint32_t *uncache_counter = cache_to_uncache(&ipc_processed_counter); + + mailbox_sw_reg_write(SRAM_REG_FW_IPC_PROCESSED_COUNT, + (*uncache_counter)++); +} + +#endif /* CONFIG_DEBUG_IPC_COUNTERS */ + +int ipc_platform_compact_read_msg(struct ipc_cmd_hdr *hdr, int words) +{ + uint32_t *chdr = (uint32_t *)hdr; + + /* compact messages are 2 words on CAVS 1.8 onwards */ + if (words != 2) + return 0; + + chdr[0] = g_last_data; + chdr[1] = g_last_ext_data; + + return 2; /* number of words read */ +} + +int ipc_platform_compact_write_msg(struct ipc_cmd_hdr *hdr, int words) +{ + return 0; /* number of words read - not currently used on this platform */ +} + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + struct ipc_cmd_hdr *hdr; + + dbg_path_hot_start_watching(); + + hdr = ipc_compact_read_msg(); + + /* perform command */ + ipc_cmd(hdr); + + dbg_path_hot_stop_watching(); + + if (ipc->task_mask & IPC_TASK_POWERDOWN || + ipc_get()->pm_prepare_D3) { +#if defined(CONFIG_PM) + /** + * @note For primary core this function + * will only force set lower power state + * in power management settings. + * Core will enter D3 state after exit + * IPC thread during idle. + */ + cpu_disable_core(PLATFORM_PRIMARY_CORE_ID); +#else + /** + * @note no return - memory will be + * powered off and IPC sent. + */ + platform_pm_runtime_power_off(); +#endif /* CONFIG_PM */ + } + + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ + ARG_UNUSED(ipc); + int ret = ipc_service_release_rx_buffer(&sof_ipc_ept, NULL); + + if (ret < 0) + tr_warn(&ipc_tr, "ipc_service_release_rx_buffer() failed: %d", ret); + +#if CONFIG_DEBUG_IPC_COUNTERS + increment_ipc_processed_counter(); +#endif +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + if (ipc_service_get_tx_buffer_size(&sof_ipc_ept) == 0) + return -EBUSY; + + /* prepare the message and copy to mailbox */ + struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg); + + return ipc_service_send(&sof_ipc_ept, hdr, sizeof(*hdr)); +} + +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); + int ret = ipc_service_send_critical(&sof_ipc_ept, hdr, sizeof(*hdr)); + + if (ret < 0) + tr_err(&ipc_tr, "ipc_service_send_critical() failed: %d", ret); +} + +int ipc_platform_poll_is_host_ready(void) +{ + return ipc_service_get_tx_buffer_size(&sof_ipc_ept) > 0; +} + +int platform_ipc_init(struct ipc *ipc) +{ + int ret; + + ipc_set_drvdata(ipc, NULL); + + /* schedule task */ +#if CONFIG_TWB_IPC_TASK + scheduler_twb_task_init(&ipc->ipc_task, SOF_UUID(zipc_task_uuid), + &ipc_task_ops, ipc, 0, "IPC", ZEPHYR_TWB_STACK_SIZE, + CONFIG_TWB_THREAD_MEDIUM_PRIORITY, ZEPHYR_TWB_BUDGET_MAX / 2); +#else + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(zipc_task_uuid), + &ipc_task_ops, ipc, 0, 0); +#endif + /* configure interrupt - work is done internally by Zephyr API */ + + sof_ipc_ept_cfg.name = "sof_ipc"; + sof_ipc_ept_cfg.prio = 0; + sof_ipc_ept_cfg.cb.received = sof_ipc_receive_cb; + sof_ipc_ept_cfg.priv = ipc; + + /* + * TODO: INTEL_ADSP_IPC_HOST_DEV is currently hardcoded for Intel ADSP platform. + * This needs to be made generic/configurable when additional vendor IPC backends + * become available (e.g., via devicetree, Kconfig, or platform-specific device selection). + */ + ret = ipc_service_register_endpoint(INTEL_ADSP_IPC_HOST_DEV, + &sof_ipc_ept, &sof_ipc_ept_cfg); + if (ret < 0) + return ret; + +#if defined(CONFIG_PM) && defined(CONFIG_INTEL_ADSP_IPC) + intel_adsp_ipc_set_suspend_handler(INTEL_ADSP_IPC_HOST_DEV, + ipc_device_suspend_handler, ipc); + intel_adsp_ipc_set_resume_handler(INTEL_ADSP_IPC_HOST_DEV, + ipc_device_resume_handler, ipc); +#endif + + return 0; +} + +#ifdef CONFIG_INTEL_ADSP_IPC +static bool ipc_wait_complete(const struct device *dev, void *arg) +{ + k_sem_give(arg); + return false; +} + +void ipc_platform_wait_ack(struct ipc *ipc) +{ + static struct k_sem ipc_wait_sem; + + k_sem_init(&ipc_wait_sem, 0, 1); + + intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_wait_complete, &ipc_wait_sem); + + if (k_sem_take(&ipc_wait_sem, Z_TIMEOUT_MS(10)) == -EAGAIN) + tr_err(&ipc_tr, "Timeout waiting for host ack!"); + + intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_HOST_DEV, NULL, NULL); +} +#endif /* CONFIG_INTEL_ADSP_IPC */ diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c deleted file mode 100644 index 62a884b3c006..000000000000 --- a/src/ipc/ipc.c +++ /dev/null @@ -1,672 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/audio/buffer.h> -#include <sof/audio/component_ext.h> -#include <sof/audio/pipeline.h> -#include <sof/common.h> -#include <sof/drivers/idc.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/cpu.h> -#include <sof/lib/mailbox.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <ipc/dai.h> -#include <ipc/header.h> -#include <ipc/stream.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* Returns pipeline source component */ -#define ipc_get_ppl_src_comp(ipc, ppl_id) \ - ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_UPSTREAM) - -/* Returns pipeline sink component */ -#define ipc_get_ppl_sink_comp(ipc, ppl_id) \ - ipc_get_ppl_comp(ipc, ppl_id, PPL_DIR_DOWNSTREAM) - -int ipc_process_on_core(uint32_t core) -{ - struct idc_msg msg = { .header = IDC_MSG_IPC, .core = core, }; - int ret; - - /* check if requested core is enabled */ - if (!cpu_is_core_enabled(core)) - return -EINVAL; - - /* send IDC message */ - ret = idc_send_msg(&msg, IDC_BLOCKING); - if (ret < 0) - return ret; - - /* reply sent by other core */ - return 1; -} - -/* - * Components, buffers and pipelines all use the same set of monotonic ID - * numbers passed in by the host. They are stored in different lists, hence - * more than 1 list may need to be searched for the corresponding component. - */ - -struct ipc_comp_dev *ipc_get_comp_by_id(struct ipc *ipc, uint32_t id) -{ - struct ipc_comp_dev *icd; - struct list_item *clist; - - list_for_item(clist, &ipc->comp_list) { - icd = container_of(clist, struct ipc_comp_dev, list); - if (icd->id == id) - return icd; - - platform_shared_commit(icd, sizeof(*icd)); - } - - 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; - struct list_item *clist; - - list_for_item(clist, &ipc->comp_list) { - icd = container_of(clist, struct ipc_comp_dev, list); - if (icd->type != type) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (!cpu_is_me(icd->core)) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - switch (icd->type) { - case COMP_TYPE_COMPONENT: - if (dev_comp_pipe_id(icd->cd) == ppl_id) - return icd; - break; - case COMP_TYPE_BUFFER: - if (icd->cb->pipeline_id == ppl_id) - return icd; - break; - case COMP_TYPE_PIPELINE: - if (icd->pipeline->ipc_pipe.pipeline_id == ppl_id) - return icd; - break; - } - - platform_shared_commit(icd, sizeof(*icd)); - } - - return NULL; -} - -static struct ipc_comp_dev *ipc_get_ppl_comp(struct ipc *ipc, - uint32_t pipeline_id, int dir) -{ - struct ipc_comp_dev *icd; - struct comp_buffer *buffer; - struct comp_dev *buff_comp; - struct list_item *clist; - - /* first try to find the module in the pipeline */ - list_for_item(clist, &ipc->comp_list) { - icd = container_of(clist, struct ipc_comp_dev, list); - if (icd->type != COMP_TYPE_COMPONENT) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (!cpu_is_me(icd->core)) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (dev_comp_pipe_id(icd->cd) == pipeline_id && - list_is_empty(comp_buffer_list(icd->cd, dir))) - return icd; - - platform_shared_commit(icd, sizeof(*icd)); - } - - /* it's connected pipeline, so find the connected module */ - list_for_item(clist, &ipc->comp_list) { - icd = container_of(clist, struct ipc_comp_dev, list); - if (icd->type != COMP_TYPE_COMPONENT) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (!cpu_is_me(icd->core)) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (dev_comp_pipe_id(icd->cd) == pipeline_id) { - buffer = buffer_from_list - (comp_buffer_list(icd->cd, dir)->next, - struct comp_buffer, dir); - buff_comp = buffer_get_comp(buffer, dir); - if (buff_comp && - dev_comp_pipe_id(buff_comp) != pipeline_id) - return icd; - } - - platform_shared_commit(icd, sizeof(*icd)); - } - - return NULL; -} - -int ipc_comp_new(struct ipc *ipc, struct sof_ipc_comp *comp) -{ - struct comp_dev *cd; - struct ipc_comp_dev *icd; - int ret = 0; - - /* check whether component already exists */ - icd = ipc_get_comp_by_id(ipc, comp->id); - if (icd != NULL) { - trace_ipc_error("ipc_comp_new() error: comp->id = %u", - comp->id); - return -EINVAL; - } - - /* create component */ - cd = comp_new(comp); - if (cd == NULL) { - trace_ipc_error("ipc_comp_new() error: component cd = NULL"); - return -EINVAL; - } - - /* allocate the IPC component container */ - icd = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(struct ipc_comp_dev)); - if (icd == NULL) { - trace_ipc_error("ipc_comp_new() error: alloc failed"); - rfree(cd); - return -ENOMEM; - } - icd->cd = cd; - icd->type = COMP_TYPE_COMPONENT; - icd->core = comp->core; - icd->id = comp->id; - - /* add new component to the list */ - list_item_append(&icd->list, &ipc->comp_list); - - platform_shared_commit(icd, sizeof(*icd)); - - return ret; -} - -int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) -{ - struct ipc_comp_dev *icd; - - /* check whether component exists */ - icd = ipc_get_comp_by_id(ipc, comp_id); - if (icd == NULL) - return -ENODEV; - - /* check core */ - if (!cpu_is_me(icd->core)) - return ipc_process_on_core(icd->core); - - /* free component and remove from list */ - comp_free(icd->cd); - - /* set pipeline sink/source/sched pointers to NULL if needed */ - if (icd->cd->pipeline) { - if (icd->cd == icd->cd->pipeline->source_comp) - icd->cd->pipeline->source_comp = NULL; - if (icd->cd == icd->cd->pipeline->sink_comp) - icd->cd->pipeline->sink_comp = NULL; - if (icd->cd == icd->cd->pipeline->sched_comp) - icd->cd->pipeline->sched_comp = NULL; - } - - icd->cd = NULL; - - list_item_del(&icd->list); - rfree(icd); - - return 0; -} - -int ipc_buffer_new(struct ipc *ipc, struct sof_ipc_buffer *desc) -{ - struct ipc_comp_dev *ibd; - struct comp_buffer *buffer; - int ret = 0; - - /* check whether buffer already exists */ - ibd = ipc_get_comp_by_id(ipc, desc->comp.id); - if (ibd != NULL) { - trace_ipc_error("ipc_buffer_new() error: buffer already exists, desc->comp.id = %u", - desc->comp.id); - return -EINVAL; - } - - /* register buffer with pipeline */ - buffer = buffer_new(desc); - if (buffer == NULL) { - trace_ipc_error("ipc_buffer_new() error: buffer_new() failed"); - - return -ENOMEM; - } - - ibd = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(struct ipc_comp_dev)); - if (ibd == NULL) { - buffer_free(buffer); - return -ENOMEM; - } - ibd->cb = buffer; - ibd->type = COMP_TYPE_BUFFER; - ibd->core = desc->comp.core; - ibd->id = desc->comp.id; - - /* add new buffer to the list */ - list_item_append(&ibd->list, &ipc->comp_list); - - platform_shared_commit(ibd, sizeof(*ibd)); - - return ret; -} - -int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id) -{ - struct ipc_comp_dev *ibd; - - /* check whether buffer exists */ - ibd = ipc_get_comp_by_id(ipc, buffer_id); - if (ibd == NULL) - return -ENODEV; - - /* check core */ - if (!cpu_is_me(ibd->core)) - return ipc_process_on_core(ibd->core); - - /* free buffer and remove from list */ - buffer_free(ibd->cb); - list_item_del(&ibd->list); - rfree(ibd); - - return 0; -} - -static int ipc_comp_to_buffer_connect(struct ipc_comp_dev *comp, - struct ipc_comp_dev *buffer) -{ - int ret; - - if (!cpu_is_me(comp->core)) - return ipc_process_on_core(comp->core); - - trace_ipc("ipc: comp sink %d, source %d -> connect", buffer->id, - comp->id); - - /* check if it's a connection between cores */ - if (buffer->core != comp->core) { - dcache_invalidate_region(buffer->cb, sizeof(*buffer->cb)); - - buffer->cb->inter_core = true; - - if (!comp->cd->is_shared) { - comp->cd = comp_make_shared(comp->cd); - if (!comp->cd) - return -ENOMEM; - } - } - - ret = pipeline_connect(comp->cd, buffer->cb, - PPL_CONN_DIR_COMP_TO_BUFFER); - - dcache_writeback_invalidate_region(buffer->cb, sizeof(*buffer->cb)); - - platform_shared_commit(comp, sizeof(*comp)); - platform_shared_commit(buffer, sizeof(*buffer)); - - return ret; -} - -static int ipc_buffer_to_comp_connect(struct ipc_comp_dev *buffer, - struct ipc_comp_dev *comp) -{ - int ret; - - if (!cpu_is_me(comp->core)) - return ipc_process_on_core(comp->core); - - trace_ipc("ipc: comp sink %d, source %d -> connect", comp->id, - buffer->id); - - /* check if it's a connection between cores */ - if (buffer->core != comp->core) { - dcache_invalidate_region(buffer->cb, sizeof(*buffer->cb)); - - buffer->cb->inter_core = true; - - if (!comp->cd->is_shared) { - comp->cd = comp_make_shared(comp->cd); - if (!comp->cd) - return -ENOMEM; - } - } - - ret = pipeline_connect(comp->cd, buffer->cb, - PPL_CONN_DIR_BUFFER_TO_COMP); - - dcache_writeback_invalidate_region(buffer->cb, sizeof(*buffer->cb)); - - platform_shared_commit(comp, sizeof(*comp)); - platform_shared_commit(buffer, sizeof(*buffer)); - - return ret; -} - -int ipc_comp_connect(struct ipc *ipc, - struct sof_ipc_pipe_comp_connect *connect) -{ - struct ipc_comp_dev *icd_source; - struct ipc_comp_dev *icd_sink; - - /* check whether the components already exist */ - icd_source = ipc_get_comp_by_id(ipc, connect->source_id); - if (icd_source == NULL) { - trace_ipc_error("ipc_comp_connect() error: components already exist, connect->source_id = %u", - connect->source_id); - return -EINVAL; - } - - icd_sink = ipc_get_comp_by_id(ipc, connect->sink_id); - if (icd_sink == NULL) { - trace_ipc_error("ipc_comp_connect() error: components already exist, connect->sink_id = %u", - connect->sink_id); - return -EINVAL; - } - - /* check source and sink types */ - if (icd_source->type == COMP_TYPE_BUFFER && - icd_sink->type == COMP_TYPE_COMPONENT) - return ipc_buffer_to_comp_connect(icd_source, icd_sink); - else if (icd_source->type == COMP_TYPE_COMPONENT && - icd_sink->type == COMP_TYPE_BUFFER) - return ipc_comp_to_buffer_connect(icd_source, icd_sink); - else { - trace_ipc_error("ipc_comp_connect() error: invalid source and sink types, connect->source_id = %u, connect->sink_id = %u", - connect->source_id, connect->sink_id); - return -EINVAL; - } -} - - -int ipc_pipeline_new(struct ipc *ipc, - struct sof_ipc_pipe_new *pipe_desc) -{ - struct ipc_comp_dev *ipc_pipe; - struct pipeline *pipe; - struct ipc_comp_dev *icd; - - /* check whether the pipeline already exists */ - ipc_pipe = ipc_get_comp_by_id(ipc, pipe_desc->comp_id); - if (ipc_pipe != NULL) { - trace_ipc_error("ipc_pipeline_new() error: pipeline already exists, pipe_desc->comp_id = %u", - pipe_desc->comp_id); - return -EINVAL; - } - - /* check whether pipeline id is already taken */ - ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, - pipe_desc->pipeline_id); - if (ipc_pipe) { - trace_ipc_error("ipc_pipeline_new() error: pipeline id is already taken, pipe_desc->pipeline_id = %u", - pipe_desc->pipeline_id); - return -EINVAL; - } - - /* find the scheduling component */ - icd = ipc_get_comp_by_id(ipc, pipe_desc->sched_id); - if (icd == NULL) { - trace_ipc_error("ipc_pipeline_new() error: cannot find the scheduling component, pipe_desc->sched_id = %u", - pipe_desc->sched_id); - return -EINVAL; - } - - if (icd->type != COMP_TYPE_COMPONENT) { - trace_ipc_error("ipc_pipeline_new() error: icd->type != COMP_TYPE_COMPONENT"); - return -EINVAL; - } - - if (icd->core != pipe_desc->core) { - trace_ipc_error("ipc_pipeline_new() error: icd->core != pipe_desc->core"); - return -EINVAL; - } - - /* create the pipeline */ - pipe = pipeline_new(pipe_desc, icd->cd); - if (pipe == NULL) { - trace_ipc_error("ipc_pipeline_new() error: pipeline_new() failed"); - return -ENOMEM; - } - - /* allocate the IPC pipeline container */ - ipc_pipe = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(struct ipc_comp_dev)); - if (ipc_pipe == NULL) { - pipeline_free(pipe); - return -ENOMEM; - } - - ipc_pipe->pipeline = pipe; - ipc_pipe->type = COMP_TYPE_PIPELINE; - ipc_pipe->core = pipe_desc->core; - ipc_pipe->id = pipe_desc->comp_id; - - /* add new pipeline to the list */ - list_item_append(&ipc_pipe->list, &ipc->comp_list); - - platform_shared_commit(ipc_pipe, sizeof(*ipc_pipe)); - - return 0; -} - -int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) -{ - struct ipc_comp_dev *ipc_pipe; - int ret; - - /* check whether pipeline exists */ - ipc_pipe = ipc_get_comp_by_id(ipc, comp_id); - if (ipc_pipe == NULL) - return -ENODEV; - - /* check core */ - if (!cpu_is_me(ipc_pipe->core)) - return ipc_process_on_core(ipc_pipe->core); - - /* free buffer and remove from list */ - ret = pipeline_free(ipc_pipe->pipeline); - if (ret < 0) { - trace_ipc_error("ipc_pipeline_free() error: pipeline_free() failed"); - return ret; - } - ipc_pipe->pipeline = NULL; - list_item_del(&ipc_pipe->list); - rfree(ipc_pipe); - - return 0; -} - -int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) -{ - struct ipc_comp_dev *ipc_pipe; - uint32_t pipeline_id; - struct ipc_comp_dev *ipc_ppl_source; - struct ipc_comp_dev *ipc_ppl_sink; - int ret; - - /* check whether pipeline exists */ - ipc_pipe = ipc_get_comp_by_id(ipc, comp_id); - if (!ipc_pipe) - return -EINVAL; - - /* check core */ - if (!cpu_is_me(ipc_pipe->core)) - return ipc_process_on_core(ipc_pipe->core); - - trace_ipc("ipc: pipe %d -> complete", comp_id); - - pipeline_id = ipc_pipe->pipeline->ipc_pipe.pipeline_id; - - /* get pipeline source component */ - ipc_ppl_source = ipc_get_ppl_src_comp(ipc, pipeline_id); - if (!ipc_ppl_source) - return -EINVAL; - - /* get pipeline sink component */ - ipc_ppl_sink = ipc_get_ppl_sink_comp(ipc, pipeline_id); - if (!ipc_ppl_sink) - return -EINVAL; - - ret = pipeline_complete(ipc_pipe->pipeline, ipc_ppl_source->cd, - ipc_ppl_sink->cd); - - platform_shared_commit(ipc_pipe, sizeof(*ipc_pipe)); - platform_shared_commit(ipc_ppl_source, sizeof(*ipc_ppl_source)); - platform_shared_commit(ipc_ppl_sink, sizeof(*ipc_ppl_sink)); - - return ret; -} - -int ipc_comp_dai_config(struct ipc *ipc, struct sof_ipc_dai_config *config) -{ - bool comp_on_core[PLATFORM_CORE_COUNT] = { false }; - struct sof_ipc_comp_dai *dai; - struct sof_ipc_reply reply; - struct ipc_comp_dev *icd; - struct list_item *clist; - int ret = -ENODEV; - int i; - - /* for each component */ - list_for_item(clist, &ipc->comp_list) { - icd = container_of(clist, struct ipc_comp_dev, list); - /* make sure we only config DAI comps */ - if (icd->type != COMP_TYPE_COMPONENT) { - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (!cpu_is_me(icd->core)) { - comp_on_core[icd->core] = true; - ret = 0; - platform_shared_commit(icd, sizeof(*icd)); - continue; - } - - if (dev_comp_type(icd->cd) == SOF_COMP_DAI || - dev_comp_type(icd->cd) == SOF_COMP_SG_DAI) { - dai = COMP_GET_IPC(icd->cd, sof_ipc_comp_dai); - platform_shared_commit(icd, sizeof(*icd)); - /* - * set config if comp dai_index matches - * config dai_index. - */ - if (dai->dai_index == config->dai_index && - dai->type == config->type) { - ret = comp_dai_config(icd->cd, config); - platform_shared_commit(icd, sizeof(*icd)); - if (ret < 0) - break; - } - } - } - - if (ret < 0) { - trace_ipc_error("ipc_comp_dai_config() error: comp_dai_config() failed"); - return ret; - } - - /* message forwarded only by master core */ - if (!cpu_is_slave(cpu_get_id())) { - for (i = 0; i < PLATFORM_CORE_COUNT; ++i) { - if (!comp_on_core[i]) - continue; - - ret = ipc_process_on_core(i); - if (ret < 0) - return ret; - - /* check whether IPC failed on slave core */ - mailbox_hostbox_read(&reply, sizeof(reply), 0, - sizeof(reply)); - if (reply.error < 0) - /* error reply already written */ - return 1; - } - } - - return ret; -} - -void ipc_send_queued_msg(void) -{ - struct ipc *ipc = ipc_get(); - struct ipc_msg *msg; - uint32_t flags; - - spin_lock_irq(&ipc->lock, flags); - - /* any messages to send ? */ - if (list_is_empty(&ipc->msg_list)) - goto out; - - msg = list_first_item(&ipc->msg_list, struct ipc_msg, - list); - - ipc_platform_send_msg(msg); - -out: - platform_shared_commit(ipc, sizeof(*ipc)); - - spin_unlock_irq(&ipc->lock, flags); -} - -int ipc_init(struct sof *sof) -{ - trace_ipc("ipc_init()"); - - /* init ipc data */ - sof->ipc = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*sof->ipc)); - sof->ipc->comp_data = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, SOF_IPC_MSG_MAX_SIZE); - - spinlock_init(&sof->ipc->lock); - list_init(&sof->ipc->msg_list); - list_init(&sof->ipc->comp_list); - - return platform_ipc_init(sof->ipc); -} - -struct task_ops ipc_task_ops = { - .run = ipc_platform_do_cmd, - .complete = ipc_platform_complete_cmd, - .get_deadline = ipc_task_deadline, -}; diff --git a/src/ipc/ipc3/CMakeLists.txt b/src/ipc/ipc3/CMakeLists.txt new file mode 100644 index 000000000000..02a2d337c53d --- /dev/null +++ b/src/ipc/ipc3/CMakeLists.txt @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Files common to Zephyr and XTOS +add_local_sources(sof + handler.c + helper.c + dai.c +) + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + +zephyr_library_sources( + host-page-table.c +) + +endif() # Zephyr diff --git a/src/ipc/ipc3/README.md b/src/ipc/ipc3/README.md new file mode 100644 index 000000000000..8f3f7c68a24d --- /dev/null +++ b/src/ipc/ipc3/README.md @@ -0,0 +1,113 @@ +# IPC3 Architecture + +This directory houses the Version 3 Inter-Processor Communication handling components. IPC3 is the older, legacy framework structure used extensively across initial Sound Open Firmware releases before the transition to IPC4 compound pipeline commands. + +## Overview + +The IPC3 architecture treats streaming, DAI configurations, and pipeline management as distinct scalar events. Messages arrive containing a specific `sof_ipc_cmd_hdr` denoting the "Global Message Type" (e.g., Stream, DAI, Trace, PM) and the targeted command within that type. + +## Command Structure and Routing + +Every message received is placed into an Rx buffer and initially routed to `ipc_cmd()`. Based on the `cmd` inside the `sof_ipc_cmd_hdr`, it delegates to one of the handler subsystems: + +* `ipc_glb_stream_message`: Stream/Pipeline configuration and states +* `ipc_glb_dai_message`: DAI parameters and formats +* `ipc_glb_pm_message`: Power Management operations + +```mermaid +graph TD + Mailbox[IPC Mailbox Interrupt] --> Valid[mailbox_validate] + Valid --> Disp[IPC Core Dispatcher] + + Disp -->|Global Type 1| StreamMsg[ipc_glb_stream_message] + Disp -->|Global Type 2| DAIMsg[ipc_glb_dai_message] + Disp -->|Global Type 3| PMMsg[ipc_glb_pm_message] + Disp -->|Global Type ...| TraceMsg[ipc_glb_trace_message] + + subgraph Stream Commands + StreamMsg --> StreamAlloc[ipc_stream_pcm_params] + StreamMsg --> StreamTrig[ipc_stream_trigger] + StreamMsg --> StreamFree[ipc_stream_pcm_free] + StreamMsg --> StreamPos[ipc_stream_position] + end + + subgraph DAI Commands + DAIMsg --> DAIConf[ipc_msg_dai_config] + end + + subgraph PM Commands + PMMsg --> PMCore[ipc_pm_core_enable] + PMMsg --> PMContext[ipc_pm_context_save / restore] + end +``` + +## Processing Flows + +### Stream Triggering (`ipc_stream_trigger`) + +Triggering is strictly hierarchical via IPC3. It expects pipelines built and components fully parsed prior to active streaming commands. + +1. **Validation**: The IPC fetches the host component ID. +2. **Device Lookup**: It searches the components list (`ipc_get_comp_dev`) for the PCM device matching the pipeline. +3. **Execution**: If valid, the pipeline graph is crawled recursively and its state altered via `pipeline_trigger`. + +```mermaid +sequenceDiagram + participant Host + participant IPC3 as IPC3 Handler (ipc_stream_trigger) + participant Pipe as Pipeline Framework + participant Comp as Connected Component + + Host->>IPC3: Send SOF_IPC_STREAM_TRIG_START + activate IPC3 + IPC3->>IPC3: ipc_get_comp_dev(stream_id) + IPC3->>Pipe: pipeline_trigger(COMP_TRIGGER_START) + activate Pipe + Pipe->>Comp: pipeline_for_each_comp(COMP_TRIGGER_START) + Comp-->>Pipe: Success (Component ACTIVE) + Pipe-->>IPC3: Return Status + deactivate Pipe + + alt If Success + IPC3-->>Host: Acknowledge Success Header + else If Error + IPC3-->>Host: Acknowledge Error Header (EINVAL / EIO) + end + deactivate IPC3 +``` + +### DAI Configuration (`ipc_msg_dai_config`) + +DAI (Digital Audio Interface) configuration involves setting up physical I2S, ALH, SSP, or HDA parameters. + +1. **Format Unpacking**: Converts the `sof_ipc_dai_config` payload sent from the ALSA driver into an internal DSP structure `ipc_config_dai`. +2. **Device Selection**: Identifies the exact DAI interface and finds its tracking device ID via `dai_get`. +3. **Hardware Config**: Applies the unpacked settings directly to the hardware via the specific DAI driver's `set_config` function. + +```mermaid +sequenceDiagram + participant Host + participant IPC3 as IPC3 Handler (ipc_msg_dai_config) + participant DAIDev as DAI Framework (dai_get) + participant HWDriver as HW Specific Driver (e.g. SSP) + + Host->>IPC3: Send SOF_IPC_DAI_CONFIG (e.g., SSP1, I2S Format) + activate IPC3 + + IPC3->>IPC3: build_dai_config() + IPC3->>DAIDev: dai_get(type, index) + DAIDev-->>IPC3: pointer to dai instance + + IPC3->>HWDriver: dai_set_config() + activate HWDriver + HWDriver-->>HWDriver: configures registers + HWDriver-->>IPC3: hardware configured + deactivate HWDriver + + IPC3-->>Host: Acknowledged Setting + deactivate IPC3 +``` + +## Mailbox and Validation (`mailbox_validate`) + +All commands passing through this layer enforce rigid payload boundaries. `mailbox_validate()` reads the first word directly from the mailbox memory, identifying the command type before parsing parameters out of shared RAM to prevent host/DSP mismatches from cascading. diff --git a/src/ipc/ipc3/dai.c b/src/ipc/ipc3/dai.c new file mode 100644 index 000000000000..d208e0a884b9 --- /dev/null +++ b/src/ipc/ipc3/dai.c @@ -0,0 +1,462 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/component_ext.h> +#include <sof/audio/ipc-config.h> +#include <rtos/idc.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/lib/dai.h> +#include <sof/lib/notifier.h> +#include <sof/drivers/afe-dai.h> +#include <sof/drivers/edma.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +/* IPC3 headers */ +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +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) +{ + const struct sof_ipc_dai_config *config = spec_config; + struct ipc_config_dai *dai = &dd->ipc_config; + int channel; + int handshake; + + assert(config); + + switch (config->type) { + case SOF_DAI_INTEL_SSP: + COMPILER_FALLTHROUGH; + case SOF_DAI_INTEL_DMIC: + channel = 0; + break; + case SOF_DAI_INTEL_HDA: + channel = config->hda.link_dma_ch; + break; + case SOF_DAI_INTEL_ALH: + /* As with HDA, the DMA channel is assigned in runtime, + * not during topology parsing. + */ + channel = config->alh.stream_id; + break; + case SOF_DAI_IMX_SAI: + COMPILER_FALLTHROUGH; + case SOF_DAI_IMX_ESAI: + handshake = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); +/* TODO: remove this when transition to native drivers is complete on all NXP platforms */ +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS + channel = EDMA_HS_GET_CHAN(handshake); +#else + channel = handshake & GENMASK(7, 0); +#endif /* CONFIG_ZEPHYR_NATIVE_DRIVERS */ + break; + case SOF_DAI_IMX_MICFIL: + channel = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); +/* TODO: remove ifdef when transitioning to native drivers is complete on all NXP platforms */ +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + channel = channel & GENMASK(7, 0); +#endif + break; + case SOF_DAI_AMD_BT: + channel = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); + break; + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: + channel = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); + break; + case SOF_DAI_AMD_DMIC: + channel = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); + break; + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: + case SOF_DAI_AMD_SDW: + channel = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); +#if defined(CONFIG_SOC_ACP_7_0) + if (channel >= 64 && channel < 128) { + channel = channel - 64; + } +#endif + break; + case SOF_DAI_MEDIATEK_AFE: + handshake = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); + channel = AFE_HS_GET_CHAN(handshake); + break; + default: + /* other types of DAIs not handled for now */ + comp_err(dev, "Unknown dai type %d", + config->type); + channel = SOF_DMA_CHAN_INVALID; + break; + } + + return channel; +} + +int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) +{ + struct ipc_config_dai *dai = &dd->ipc_config; + struct sof_ipc_dai_config *config = ipc_from_dai_config(dd->dai_spec_config); + + if (!config) { + comp_err(dev, "no config set for dai %d type %d", + dai->dai_index, dai->type); + return -EINVAL; + } + + comp_info(dev, "dai_data_config() dai type = %d index = %d dd %p", + dai->type, dai->dai_index, dd); + + /* cannot configure DAI while active */ + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state."); + return 0; + } + + /* validate direction */ + if (dai->direction != SOF_IPC_STREAM_PLAYBACK && + dai->direction != SOF_IPC_STREAM_CAPTURE) { + comp_err(dev, "no direction set for dai %d type %d", + dai->dai_index, dai->type); + return -EINVAL; + } + + switch (config->type) { + case SOF_DAI_INTEL_SSP: + /* set dma burst elems to slot number */ + dd->config.burst_elems = config->ssp.tdm_slots; + break; + case SOF_DAI_INTEL_DMIC: + /* Depth is passed by DMIC driver that retrieves it from blob */ + dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); + comp_info(dev, "dai_data_config() burst_elems = %d", dd->config.burst_elems); + break; + case SOF_DAI_INTEL_HDA: + break; + case SOF_DAI_INTEL_ALH: + /* SDW HW FIFO always requires 32bit MSB aligned sample data for + * all formats, such as 8/16/24/32 bits. + */ + dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; + if (dd->dma_buffer) + audio_stream_set_frm_fmt(&dd->dma_buffer->stream, + dev->ipc_config.frame_fmt); + + dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); + /* As with HDA, the DMA channel is assigned in runtime, + * not during topology parsing. + */ + dd->stream_id = config->alh.stream_id; + break; + case SOF_DAI_IMX_MICFIL: + case SOF_DAI_IMX_SAI: + case SOF_DAI_IMX_ESAI: + dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); + break; + case SOF_DAI_AMD_BT: + dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S16_LE; + break; + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: + dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S16_LE; + break; + case SOF_DAI_AMD_DMIC: + dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; + if (dd->dma_buffer) + audio_stream_set_frm_fmt(&dd->dma_buffer->stream, + dev->ipc_config.frame_fmt); + break; + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: + case SOF_DAI_AMD_SDW: +#if defined(CONFIG_AMD) && !defined(CONFIG_SOC_ACP_6_0) + { + struct acp_dma_dev_data *dev_data = dd->dma->z_dev->data; + struct sdw_pin_data *pin_data; + + /* Allocate memory only if not already allocated */ + if (!dev_data->dai_index_ptr) { + pin_data = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*pin_data)); + dev_data->dai_index_ptr = pin_data; + } else { + pin_data = dev_data->dai_index_ptr; + } + pin_data->pin_num = dd->dai->index; + pin_data->pin_dir = dai->direction; +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + pin_data->dma_channel = dd->chan_index >= 0 ? dd->chan_index : 0xFFFF; +#else + pin_data->dma_channel = dd->chan ? dd->chan->index : 0xFFFF; +#endif + pin_data->index = 0xFFFF; + pin_data->instance = 0xFFFF; + dev_data->dai_index_ptr = pin_data; + } +#endif + break; + case SOF_DAI_MEDIATEK_AFE: + break; + default: + /* other types of DAIs not handled for now */ + comp_warn(dev, "Unknown dai type %d", + config->type); + break; + } + + /* some DAIs may not need extra config */ + return 0; +} + +int ipc_comp_dai_config(struct ipc *ipc, struct ipc_config_dai *common_config, + void *spec_config) +{ + struct sof_ipc_dai_config __maybe_unused *config = spec_config; + bool comp_on_core[CONFIG_CORE_COUNT] = { false }; + struct sof_ipc_reply reply; + struct ipc_comp_dev *icd; + struct list_item *clist; + int ret = -ENODEV; + int i; + + tr_info(&ipc_tr, "dai type = %d index = %d", + config->type, config->dai_index); + + /* for each component */ + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + /* make sure we only config DAI comps */ + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + if (!cpu_is_me(icd->core)) { + comp_on_core[icd->core] = true; + ret = 0; + continue; + } + + if (dev_comp_type(icd->cd) == SOF_COMP_DAI || + dev_comp_type(icd->cd) == SOF_COMP_SG_DAI) { + + ret = comp_dai_config(icd->cd, common_config, spec_config); + if (ret < 0) + break; + } + } + + if (ret < 0) { + tr_err(&ipc_tr, "comp_dai_config() failed"); + return ret; + } + + /* message forwarded only by primary core */ + if (cpu_is_primary(cpu_get_id())) { + for (i = 0; i < CONFIG_CORE_COUNT; ++i) { + if (!comp_on_core[i]) + continue; + + /* + * TODO: can secondary cores execute dai_config() in + * parallel? Then we could just wait for the last of + * them. For now execute them sequentially. + */ + ret = ipc_process_on_core(i, true); + if (ret < 0) + break; + + /* check whether IPC failed on secondary core */ + mailbox_hostbox_read(&reply, sizeof(reply), 0, + sizeof(reply)); + if (reply.error < 0) { + /* error reply already written */ + ret = 1; + break; + } + } + + /* We have waited until all secondary cores configured their DAIs */ + ipc->core = PLATFORM_PRIMARY_CORE_ID; + } + + return ret; +} + +void dai_dma_release(struct dai_data *dd, struct comp_dev *dev) +{ + /* cannot configure DAI while active */ + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state. Ignore resetting"); + return; + } + + /* put the allocated DMA channel first */ +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + if (dd->chan_index >= 0) { + /* remove callback */ + notifier_unregister(dev, &dd->dma->chan[dd->chan_index], + NOTIFIER_ID_DMA_COPY); + dma_release_channel(dd->dma->z_dev, dd->chan_index); + dd->chan_index = -EINVAL; + } +#else + if (dd->chan) { + /* remove callback */ + notifier_unregister(dev, dd->chan, NOTIFIER_ID_DMA_COPY); + dma_channel_put_legacy(dd->chan); + dd->chan->dev_data = NULL; + dd->chan = NULL; + } +#endif +} + +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; + int ret; + + /* ignore if message not for this DAI id/type */ + if (dd->ipc_config.dai_index != config->dai_index || + dd->ipc_config.type != config->type) + return 0; + + comp_info(dev, "dai type = %d index = %d dd %p", + config->type, config->dai_index, dd); + + /* cannot configure DAI while active */ + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state. Ignore config"); + return 0; + } + + dd->dai_dev = dev; + + switch (config->flags & SOF_DAI_CONFIG_FLAGS_CMD_MASK) { + case SOF_DAI_CONFIG_FLAGS_HW_PARAMS: + /* set the delayed_dma_stop flag */ + if (SOF_DAI_QUIRK_IS_SET(config->flags, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP)) + dd->delayed_dma_stop = true; + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + if (dd->chan_index >= 0) { + comp_info(dev, "Configured. dma channel index %d, ignore...", + dd->chan_index); + return 0; + } +#else + if (dd->chan) { + comp_info(dev, "Configured. dma channel index %d, ignore...", + dd->chan->index); + return 0; + } +#endif + break; + case SOF_DAI_CONFIG_FLAGS_HW_FREE: +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + if (dd->chan_index < 0) + return 0; +#else + if (!dd->chan) + return 0; +#endif + + /* stop DMA and reset config for two-step stop DMA */ + if (dd->delayed_dma_stop) { +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + ret = dma_stop(dd->dma->z_dev, dd->chan_index); +#else + ret = dma_stop_delayed_legacy(dd->chan); +#endif + if (ret < 0) + return ret; + + dai_dma_release(dd, dev); + } + + return 0; + case SOF_DAI_CONFIG_FLAGS_PAUSE: +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + if (dd->chan_index < 0) + return 0; + return dma_stop(dd->dma->z_dev, dd->chan_index); +#else + if (!dd->chan) + return 0; + return dma_stop_delayed_legacy(dd->chan); +#endif + default: + break; + } +#if CONFIG_COMP_DAI_GROUP + if (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(dd, dev, spec_config) == SOF_DMA_CHAN_INVALID) + return 0; + + /* allocated dai_config if not yet */ + if (!dd->dai_spec_config) { + dd->dai_spec_config = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct sof_ipc_dai_config)); + if (!dd->dai_spec_config) { + comp_err(dev, "No memory"); + return -ENOMEM; + } + } + + ret = memcpy_s(dd->dai_spec_config, sizeof(struct sof_ipc_dai_config), config, + sizeof(struct sof_ipc_dai_config)); + if (ret < 0) { + rfree(dd->dai_spec_config); + dd->dai_spec_config = NULL; + } + + return ret; +} + +int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + /* TODO: improve accuracy by adding current DMA position */ + posn->dai_posn = dd->total_data_processed; + + /* set stream start wallclock */ + posn->wallclock = dd->wallclock; + + return 0; +} + +void dai_dma_position_update(struct dai_data *dd, 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 new file mode 100644 index 000000000000..5bd5293c61b7 --- /dev/null +++ b/src/ipc/ipc3/handler.c @@ -0,0 +1,1634 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +/* + * IPC (InterProcessor Communication) provides a method of two way + * communication between the host processor and the DSP. The IPC used here + * utilises a shared mailbox and door bell between the host and DSP. + * + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/debug/gdb/gdb.h> +#include <rtos/panic.h> +#include <rtos/idc.h> +#include <rtos/interrupt.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/schedule.h> +#include <sof/lib/agent.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/pm_runtime.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/string.h> +#include <rtos/string_macro.h> +#if CONFIG_TRACE +#include <sof/trace/dma-trace.h> +#endif +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/dai.h> +#include <ipc/debug.h> +#include <ipc/header.h> +#include <ipc/pm.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc/trace.h> +#include <user/trace.h> +#include <ipc/probe.h> +#include <sof/probe/probe.h> + +#include <errno.h> +#include <math.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +/* 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); + +#if CONFIG_CAVS +#include <ipc/header-intel-cavs.h> +#include <cavs/drivers/sideband-ipc.h> +#define CAVS_IPC_TYPE_S(x) ((x) & CAVS_IPC_TYPE_MASK) +#endif + +#define iGS(x) ((x) & SOF_GLB_TYPE_MASK) +#define iCS(x) ((x) & SOF_CMD_TYPE_MASK) + +/* FIXME: assert() is most likely turned off in production builds + * https://open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm + */ +#define _IPC_COPY_CMD(rx, tx, rx_size) \ + do { \ + int ___ret; \ + if (rx_size > tx->size) { \ + ___ret = memcpy_s(rx, rx_size, tx, tx->size); \ + assert(!___ret); \ + bzero((char *)rx + tx->size, rx_size - tx->size);\ + tr_dbg(&ipc_tr, "ipc: hdr 0x%x rx (%zu) > tx (%d)",\ + rx->cmd, rx_size, tx->size); \ + } else if (tx->size > rx_size) { \ + ___ret = memcpy_s(rx, rx_size, tx, rx_size); \ + assert(!___ret); \ + tr_warn(&ipc_tr, "ipc: hdr 0x%x tx (%d) > rx (%zu)",\ + rx->cmd, tx->size, rx_size); \ + } else { \ + ___ret = memcpy_s(rx, rx_size, tx, rx_size); \ + assert(!___ret); \ + } \ + } while (0) + +/* copies whole message from Tx to Rx, follows above ABI rules */ +#define IPC_COPY_CMD(rx, tx) \ + _IPC_COPY_CMD(((struct sof_ipc_cmd_hdr *)&rx), \ + ((struct sof_ipc_cmd_hdr *)tx), \ + sizeof(rx)) + +struct ipc_cmd_hdr *mailbox_validate(void) +{ + struct sof_ipc_cmd_hdr *hdr = ipc_get()->comp_data; + + /* read component values from the inbox */ + mailbox_hostbox_read(hdr, SOF_IPC_MSG_MAX_SIZE, 0, sizeof(*hdr)); + + /* validate component header */ + if (hdr->size < sizeof(*hdr) || hdr->size > SOF_IPC_MSG_MAX_SIZE) { +#ifndef CONFIG_ARCH_POSIX_LIBFUZZER + ipc_cmd_err(&ipc_tr, "ipc: invalid size 0x%x", hdr->size); +#endif + return NULL; + } + + /* read rest of component data */ + mailbox_hostbox_read(hdr + 1, SOF_IPC_MSG_MAX_SIZE - sizeof(*hdr), + sizeof(*hdr), hdr->size - sizeof(*hdr)); + + return ipc_to_hdr(hdr); +} + +/* + * Stream IPC Operations. + */ + +#if CONFIG_HOST_PTABLE +/* check if a pipeline is hostless when walking downstream */ +static bool is_hostless_downstream(struct comp_dev *current) +{ + struct comp_buffer *buffer; + + /* check if current is a HOST comp */ + if (current->ipc_config.type == SOF_COMP_HOST || + current->ipc_config.type == SOF_COMP_SG_HOST) + return false; + + /* check if the pipeline has a HOST comp downstream */ + comp_dev_for_each_consumer(current, buffer) { + /* don't go downstream if this component is not connected */ + if (!comp_buffer_get_sink_component(buffer)) + continue; + + /* dont go downstream if this comp belongs to another pipe */ + if (comp_buffer_get_sink_component(buffer)->ipc_config.pipeline_id != + current->ipc_config.pipeline_id) + continue; + + /* return if there's a host comp downstream */ + if (!is_hostless_downstream(comp_buffer_get_sink_component(buffer))) + return false; + } + + return true; +} + +/* check if a pipeline is hostless when walking upstream */ +static bool is_hostless_upstream(struct comp_dev *current) +{ + struct comp_buffer *buffer; + + /* check if current is a HOST comp */ + if (current->ipc_config.type == SOF_COMP_HOST || + current->ipc_config.type == SOF_COMP_SG_HOST) + return false; + + /* check if the pipeline has a HOST comp upstream */ + comp_dev_for_each_producer(current, buffer) { + /* don't go upstream if this component is not connected */ + if (!comp_buffer_get_source_component(buffer)) + continue; + + /* dont go upstream if this comp belongs to another pipeline */ + if (comp_buffer_get_source_component(buffer)->ipc_config.pipeline_id != + current->ipc_config.pipeline_id) + continue; + + /* return if there is a host comp upstream */ + if (!is_hostless_upstream(comp_buffer_get_source_component(buffer))) + return false; + } + + return true; +} +#endif + +/* allocate a new stream */ +static int ipc_stream_pcm_params(uint32_t stream) +{ +#if CONFIG_HOST_PTABLE + struct dma_sg_elem_array elem_array; + uint32_t ring_size; + enum comp_copy_type copy_type = COMP_COPY_ONE_SHOT; + struct comp_dev *cd; + uint32_t direction; +#endif + struct ipc *ipc = ipc_get(); + struct sof_ipc_pcm_params pcm_params; + struct sof_ipc_pcm_params_reply reply; + struct ipc_comp_dev *pcm_dev; + struct sof_ipc_stream_posn posn; + int err, reset_err; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(pcm_params, ipc->comp_data); + + /* get the pcm_dev */ + pcm_dev = ipc_get_comp_by_id(ipc, pcm_params.comp_id); + if (!pcm_dev) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", pcm_params.comp_id); + return -ENODEV; + } + + /* check core */ + if (!cpu_is_me(pcm_dev->core)) + return ipc_process_on_core(pcm_dev->core, false); + + tr_dbg(&ipc_tr, "ipc: comp %d -> params", pcm_params.comp_id); + + /* sanity check comp */ + if (!pcm_dev->cd->pipeline) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d pipeline not found", + pcm_params.comp_id); + return -EINVAL; + } + + /* sanity check for pcm_params size */ + if (pcm_params.hdr.size != + sizeof(pcm_params) + pcm_params.params.ext_data_length) { + ipc_cmd_err(&ipc_tr, "pcm_params invalid size, hdr.size=%d, ext_data_len=%d", + pcm_params.hdr.size, pcm_params.params.ext_data_length); + return -EINVAL; + } + + /* sanity check for pcm_params.params size */ + if (pcm_params.params.hdr.size != + sizeof(pcm_params.params) + pcm_params.params.ext_data_length) { + ipc_cmd_err(&ipc_tr, "pcm_params.params invalid size, hdr.size=%d, ext_data_len=%d", + pcm_params.params.hdr.size, pcm_params.params.ext_data_length); + return -EINVAL; + } + + if (sizeof(pcm_params) + pcm_params.params.ext_data_length > SOF_IPC_MSG_MAX_SIZE) { + ipc_cmd_err(&ipc_tr, "pcm_params ext_data_length invalid size %d max allowed %zu", + pcm_params.params.ext_data_length, + SOF_IPC_MSG_MAX_SIZE - sizeof(pcm_params)); + return -EINVAL; + } + + switch (pcm_dev->cd->pipeline->status) { + case COMP_STATE_ACTIVE: + case COMP_STATE_PRE_ACTIVE: + /* + * IPC4 has a use-case when a PCM parameter change request can + * be sent on an active pipeline, ignore it + */ + pipe_dbg(pcm_dev->cd->pipeline, + "ipc: ignore PCM param change request on an active pipeline"); + return 0; + } + +#if CONFIG_HOST_PTABLE + cd = pcm_dev->cd; + + /* + * walk in both directions to check if the pipeline is hostless + * skip page table set up if it is + */ + if (is_hostless_downstream(cd) && is_hostless_upstream(cd)) + goto pipe_params; + + err = comp_get_attribute(cd, COMP_ATTR_COPY_DIR, &direction); + if (err < 0) + goto error; + + err = ipc_process_host_buffer(ipc, &pcm_params.params.buffer, + direction, + &elem_array, + &ring_size); + if (err < 0) + goto error; + + err = comp_set_attribute(cd, COMP_ATTR_HOST_BUFFER, &elem_array); + if (err < 0) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d host buffer failed %d", + pcm_params.comp_id, err); + goto error; + } + + /* TODO: should be extracted to platform specific code */ + err = comp_set_attribute(cd, COMP_ATTR_COPY_TYPE, ©_type); + if (err < 0) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d setting copy type failed %d", + pcm_params.comp_id, err); + goto error; + } + +pipe_params: +#endif + + /* configure pipeline audio params */ + err = pipeline_params(pcm_dev->cd->pipeline, pcm_dev->cd, + (struct sof_ipc_pcm_params *)ipc_get()->comp_data); + if (err < 0) { + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d params failed %d", + pcm_dev->cd->pipeline->pipeline_id, + pcm_params.comp_id, err); + goto error; + } + + /* prepare pipeline audio params */ + err = pipeline_prepare(pcm_dev->cd->pipeline, pcm_dev->cd); + if (err < 0) { + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d prepare failed %d", + pcm_dev->cd->pipeline->pipeline_id, + pcm_params.comp_id, err); + goto error; + } + + /* write component values to the outbox */ + reply.rhdr.hdr.size = sizeof(reply); + reply.rhdr.hdr.cmd = stream; + reply.rhdr.error = 0; + reply.comp_id = pcm_params.comp_id; + reply.posn_offset = pcm_dev->cd->pipeline->posn_offset; + + /* reset position value before send ipc */ + memset(&posn, 0, sizeof(posn)); + mailbox_stream_write(reply.posn_offset, &posn, sizeof(posn)); + + mailbox_hostbox_write(0, &reply, sizeof(reply)); + return 1; + +error: + reset_err = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + if (reset_err < 0) + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d reset failed %d", + pcm_dev->cd->pipeline->pipeline_id, + pcm_params.comp_id, reset_err); + return err; +} + +/* free stream resources */ +static int ipc_stream_pcm_free(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_stream free_req; + struct ipc_comp_dev *pcm_dev; + int ret; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(free_req, ipc->comp_data); + + /* get the pcm_dev */ + pcm_dev = ipc_get_comp_by_id(ipc, free_req.comp_id); + if (!pcm_dev) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", free_req.comp_id); + return -ENODEV; + } + + /* check core */ + if (!cpu_is_me(pcm_dev->core)) + return ipc_process_on_core(pcm_dev->core, false); + + tr_dbg(&ipc_tr, "ipc: comp %d -> free", free_req.comp_id); + + /* sanity check comp */ + if (!pcm_dev->cd->pipeline) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d pipeline not found", + free_req.comp_id); + return -EINVAL; + } + + /* reset the pipeline */ + ret = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + + return ret; +} + +/* get stream position */ +static int ipc_stream_position(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_stream stream; + struct sof_ipc_stream_posn posn; + struct ipc_comp_dev *pcm_dev; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(stream, ipc->comp_data); + + /* get the pcm_dev */ + pcm_dev = ipc_get_comp_by_id(ipc, stream.comp_id); + if (!pcm_dev) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", stream.comp_id); + return -ENODEV; + } + + /* check core */ + if (!cpu_is_me(pcm_dev->core)) + return ipc_process_on_core(pcm_dev->core, false); + + tr_info(&ipc_tr, "ipc: comp %d -> position", stream.comp_id); + + memset(&posn, 0, sizeof(posn)); + + /* set message fields - TODO; get others */ + posn.rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION | + stream.comp_id; + posn.rhdr.hdr.size = sizeof(posn); + posn.comp_id = stream.comp_id; + + if (!pcm_dev->cd->pipeline) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d pipeline not found", + stream.comp_id); + return -EINVAL; + } + + /* get the stream positions and timestamps */ + pipeline_get_timestamp(pcm_dev->cd->pipeline, pcm_dev->cd, &posn); + + /* copy positions to stream region */ + mailbox_stream_write(pcm_dev->cd->pipeline->posn_offset, + &posn, sizeof(posn)); + + return 1; +} + +static int ipc_stream_trigger(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *pcm_dev; + struct sof_ipc_stream stream; + uint32_t ipc_command = iCS(header); + uint32_t cmd; + int ret; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(stream, ipc->comp_data); + + /* get the pcm_dev */ + pcm_dev = ipc_get_comp_by_id(ipc, stream.comp_id); + if (!pcm_dev) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", stream.comp_id); + return -ENODEV; + } + + /* check core */ + if (!cpu_is_me(pcm_dev->core)) + return ipc_process_on_core(pcm_dev->core, false); + + tr_dbg(&ipc_tr, "ipc: comp %d -> trigger cmd 0x%x", + stream.comp_id, ipc_command); + + switch (ipc_command) { + case SOF_IPC_STREAM_TRIG_START: + cmd = COMP_TRIGGER_PRE_START; + break; + case SOF_IPC_STREAM_TRIG_STOP: + cmd = COMP_TRIGGER_STOP; + break; + case SOF_IPC_STREAM_TRIG_PAUSE: + cmd = COMP_TRIGGER_PAUSE; + break; + case SOF_IPC_STREAM_TRIG_RELEASE: + cmd = COMP_TRIGGER_PRE_RELEASE; + break; + /* XRUN is special case- TODO */ + case SOF_IPC_STREAM_TRIG_XRUN: + return 0; + default: + ipc_cmd_err(&ipc_tr, "ipc: invalid trigger cmd 0x%x", ipc_command); + return -ENODEV; + } + + if (!pcm_dev->cd->pipeline) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d pipeline not found", + stream.comp_id); + return -EINVAL; + } + + if (pcm_dev->type != COMP_TYPE_COMPONENT) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not stream (type %d)", + stream.comp_id, pcm_dev->type); + return -EINVAL; + } + + /* + * Trigger the component: timer domain pipelines offload some trigger + * operations in their pipeline tasks, in which case IPC response to + * the host can be delayed. DMA domain pipelines always trigger + * synchronously. + */ + if (pipeline_is_timer_driven(pcm_dev->cd->pipeline)) { + k_spinlock_key_t key; + + key = k_spin_lock(&ipc->lock); + ipc->task_mask |= IPC_TASK_IN_THREAD; + k_spin_unlock(&ipc->lock, key); + + ret = pipeline_trigger(pcm_dev->cd->pipeline, pcm_dev->cd, cmd); + if (ret <= 0) { + key = k_spin_lock(&ipc->lock); + ipc->task_mask &= ~IPC_TASK_IN_THREAD; + k_spin_unlock(&ipc->lock, key); + } + } else { + ret = pipeline_trigger_run(pcm_dev->cd->pipeline, pcm_dev->cd, cmd); + } + + if (ret < 0) + ipc_cmd_err(&ipc_tr, "ipc: comp %d trigger 0x%x failed %d", + stream.comp_id, ipc_command, ret); + + + return ret; +} + +static int ipc_glb_stream_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + case SOF_IPC_STREAM_PCM_PARAMS: + return ipc_stream_pcm_params(header); + case SOF_IPC_STREAM_PCM_FREE: + return ipc_stream_pcm_free(header); + case SOF_IPC_STREAM_TRIG_START: + case SOF_IPC_STREAM_TRIG_STOP: + case SOF_IPC_STREAM_TRIG_PAUSE: + case SOF_IPC_STREAM_TRIG_RELEASE: + case SOF_IPC_STREAM_TRIG_DRAIN: + case SOF_IPC_STREAM_TRIG_XRUN: + return ipc_stream_trigger(header); + case SOF_IPC_STREAM_POSITION: + return ipc_stream_position(header); + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown stream cmd 0x%x", cmd); + return -EINVAL; + } +} + +/* + * DAI IPC Operations. + */ + +static void build_dai_config(struct sof_ipc_dai_config *config, + struct ipc_config_dai *config_dai) +{ + memset(config_dai, 0, sizeof(*config_dai)); + + config_dai->dai_index = config->dai_index; + config_dai->direction = -1; + config_dai->format = config->format; + config_dai->group_id = config->group_id; + config_dai->type = config->type; +} + +static int ipc_dai_config_set(struct sof_ipc_dai_config *config, + struct ipc_config_dai *config_dai) +{ + struct dai *dai; + int ret; + + /* get DAI */ + dai = dai_get(config->type, config->dai_index, 0 /* existing only */); + if (!dai) { + ipc_cmd_err(&ipc_tr, "ipc: dai %d,%d not found", config->type, + config->dai_index); + return -ENODEV; + } + + /* configure DAI */ + ret = dai_set_config(dai, config_dai, config, sizeof(*config)); + dai_put(dai); /* free ref immediately */ + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "ipc: dai %d,%d config failed %d", config->type, + config->dai_index, ret); + return ret; + } + + return 0; +} + +/* + * DAI config occurs in several steps (and can be optimised) + * 1) IPC arrived from host + * 2) Primary core configures the DAI driver HW config via drv->set_config() + * 3) Target core then calls comp->dai_config() + * 4) Stream params IPC then calls dai_params() which calls + * ipc_dai_data_config() followed by dai_verify_params() to validate + * stream params with physical DAI HW config. + */ +static int ipc_msg_dai_config(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct ipc_config_dai config_dai; + struct sof_ipc_dai_config config; + int ret; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(config, ipc->comp_data); + + tr_info(&ipc_tr, "ipc: dai %d.%d -> config ", config.type, + config.dai_index); + + /* set common configuration */ + build_dai_config(&config, &config_dai); + + /* only primary core configures dai */ + if (cpu_get_id() == PLATFORM_PRIMARY_CORE_ID) { + ret = ipc_dai_config_set(&config, &config_dai); + if (ret < 0) + return ret; + } + + /* send params to all DAI components who use that physical DAI */ + return ipc_comp_dai_config(ipc, &config_dai, ipc->comp_data); +} + +static int ipc_glb_dai_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + case SOF_IPC_DAI_CONFIG: + return ipc_msg_dai_config(header); + case SOF_IPC_DAI_LOOPBACK: + //return ipc_comp_set_value(header, COMP_CMD_LOOPBACK); + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown DAI cmd 0x%x", cmd); + return -EINVAL; + } +} + +/* + * PM IPC Operations. + */ + +static int ipc_pm_context_size(uint32_t header) +{ + struct sof_ipc_pm_ctx pm_ctx; + + tr_info(&ipc_tr, "ipc: pm -> size"); + + bzero(&pm_ctx, sizeof(pm_ctx)); + + /* TODO: calculate the context and size of host buffers required */ + + /* write the context to the host driver */ + //mailbox_hostbox_write(0, &pm_ctx, sizeof(pm_ctx)); + + return 0; +} + +static int ipc_pm_context_save(uint32_t header) +{ + //struct sof_ipc_pm_ctx *pm_ctx = _ipc->comp_data; + + tr_info(&ipc_tr, "ipc: pm -> save"); + + sa_exit(sof_get()); + + /* do platform specific suspending */ + platform_context_save(sof_get()); + +#if !defined(CONFIG_LIBRARY) && !defined(CONFIG_ZEPHYR_POSIX) + /* TODO: check we are inactive - all streams are suspended */ + + /* TODO: mask ALL platform interrupts except DMA */ + + /* mask all DSP interrupts */ + arch_irq_lock(); + + /* TODO: mask ALL platform interrupts inc DMA */ + + /* TODO: clear any outstanding platform IRQs - TODO refine */ + + /* TODO: stop ALL timers */ + platform_timer_stop(timer_get()); + + /* TODO: disable SSP and DMA HW */ + + /* TODO: save the context */ + //reply.entries_no = 0; + + /* write the context to the host driver */ + //mailbox_hostbox_write(0, pm_ctx, sizeof(*pm_ctx)); +#endif + ipc_get()->pm_prepare_D3 = 1; + + return 0; +} + +static int ipc_pm_context_restore(uint32_t header) +{ + //struct sof_ipc_pm_ctx *pm_ctx = _ipc->comp_data; + + tr_info(&ipc_tr, "ipc: pm -> restore"); + + ipc_get()->pm_prepare_D3 = 0; + + /* restore context placeholder */ + //mailbox_hostbox_write(0, pm_ctx, sizeof(*pm_ctx)); + + return 0; +} + +static int ipc_pm_core_enable(uint32_t header) +{ + struct sof_ipc_pm_core_config pm_core_config; + int ret; + int i = 0; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(pm_core_config, ipc_get()->comp_data); + + /* check if core enable mask is valid */ + if (pm_core_config.enable_mask > MASK(CONFIG_CORE_COUNT - 1, 0)) { + ipc_cmd_err(&ipc_tr, "ipc: CONFIG_CORE_COUNT: %d < core enable mask: %d", + CONFIG_CORE_COUNT, pm_core_config.enable_mask); + return -EINVAL; + } + + tr_info(&ipc_tr, "ipc: pm core mask 0x%x -> enable", + pm_core_config.enable_mask); + + for (i = 0; i < CONFIG_CORE_COUNT; i++) { + if (i != PLATFORM_PRIMARY_CORE_ID) { + if (pm_core_config.enable_mask & (1 << i)) { + ret = cpu_enable_core(i); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "Failed to enable core %d", i); + return ret; + } + } else { + cpu_disable_core(i); + } + } + } + + return 0; +} + +static int ipc_pm_gate(uint32_t header) +{ + struct sof_ipc_pm_gate pm_gate; + + IPC_COPY_CMD(pm_gate, ipc_get()->comp_data); + + tr_info(&ipc_tr, "ipc: pm gate flags 0x%x", pm_gate.flags); + + /* pause dma trace firstly if needed */ + if (pm_gate.flags & SOF_PM_NO_TRACE) + trace_off(); + + if (pm_gate.flags & SOF_PM_PPG) { + pm_runtime_disable(PM_RUNTIME_DSP, PLATFORM_PRIMARY_CORE_ID); + } else { + /* before we enable pm runtime and perform D0->D0ix flow + * (primary core powers off secondary cores in + * platform_pg_int_handler) we have to prepare all secondary + * cores data for powering off (disable interrupt, perform + * cache writeback). + */ + pm_runtime_enable(PM_RUNTIME_DSP, PLATFORM_PRIMARY_CORE_ID); + } + + /* resume dma trace if needed */ + if (!(pm_gate.flags & SOF_PM_NO_TRACE)) + trace_on(); + + return 0; +} + +static int ipc_glb_pm_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + case SOF_IPC_PM_CTX_SAVE: + return ipc_pm_context_save(header); + case SOF_IPC_PM_CTX_RESTORE: + return ipc_pm_context_restore(header); + case SOF_IPC_PM_CTX_SIZE: + return ipc_pm_context_size(header); + case SOF_IPC_PM_CORE_ENABLE: + return ipc_pm_core_enable(header); + case SOF_IPC_PM_GATE: + return ipc_pm_gate(header); + case SOF_IPC_PM_CLK_SET: + case SOF_IPC_PM_CLK_GET: + case SOF_IPC_PM_CLK_REQ: + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown pm cmd 0x%x", cmd); + return -EINVAL; + } +} + +#if CONFIG_TRACE +/* + * Debug IPC Operations. + */ +static void ipc_dma_trace_free(uint32_t header) +{ + struct dma_trace_data *dmat = dma_trace_data_get(); + + dma_trace_disable(dmat); +} + +static int ipc_dma_trace_config(uint32_t header) +{ +#if CONFIG_HOST_PTABLE + struct dma_sg_elem_array elem_array; + uint32_t ring_size; +#endif + struct dma_trace_data *dmat = dma_trace_data_get(); + struct ipc *ipc = ipc_get(); + struct sof_ipc_dma_trace_params_ext params; + int err; + + if (!dmat) { + mtrace_printf(LOG_LEVEL_ERROR, + "failed: dmat not initialized"); + return -ENOMEM; + } + + /* copy message with ABI safe method */ + IPC_COPY_CMD(params, ipc->comp_data); + + if (iCS(header) == SOF_IPC_TRACE_DMA_PARAMS_EXT) + /* As version 5.12 Linux sends the monotonic + * ktime_get(). Search for + * "SOF_IPC_TRACE_DMA_PARAMS_EXT" in your particular + * kernel version. + */ + dmat->time_delta = k_ns_to_cyc_near64(params.timestamp_ns) - sof_cycle_get_64(); + else + dmat->time_delta = 0; + +#if CONFIG_HOST_PTABLE + err = ipc_process_host_buffer(ipc, ¶ms.buffer, + SOF_IPC_STREAM_CAPTURE, + &elem_array, + &ring_size); + if (err < 0) + goto processing_error; + + err = dma_trace_host_buffer(dmat, &elem_array, ring_size); + if (err < 0) { + ipc_cmd_err(&ipc_tr, "ipc: trace failed to set host buffers %d", + err); + goto error; + } +#else + /* stream tag of capture stream for DMA trace */ + dmat->stream_tag = params.stream_tag; + + /* host buffer size for DMA trace */ + dmat->host_size = params.buffer.size; +#endif + + err = dma_trace_enable(dmat); + if (err < 0) { + ipc_cmd_err(&ipc_tr, "ipc: failed to enable trace %d", err); + goto error; + } + + return 0; + +error: +#if CONFIG_HOST_PTABLE + dma_sg_free(NULL, &elem_array); + +processing_error: +#endif + + return err; +} + +static int ipc_trace_filter_update(uint32_t header) +{ + struct sof_ipc_trace_filter_elem *next_elem; + struct sof_ipc_trace_filter_elem *elem; + struct sof_ipc_trace_filter_elem *end; + struct sof_ipc_trace_filter *packet; + struct trace_filter filter; + struct ipc *ipc = ipc_get(); + int ret = 0; + int cnt; + + packet = ipc->comp_data; + + /* validation, packet->hdr.size has already been compared with SOF_IPC_MSG_MAX_SIZE */ + if (sizeof(*packet) + sizeof(*elem) * packet->elem_cnt != packet->hdr.size) { + ipc_cmd_err(&ipc_tr, "trace_filter_update failed, elem_cnt %d is inconsistent with hdr.size %d", + packet->elem_cnt, packet->hdr.size); + return -EINVAL; + } + + tr_info(&ipc_tr, "ipc: trace_filter_update received, size %d elems", + packet->elem_cnt); + + elem = packet->elems; + end = &packet->elems[packet->elem_cnt]; + + /* read each filter set and update selected components trace settings */ + while (elem != end) { + next_elem = trace_filter_fill(elem, end, &filter); + if (!next_elem) + return -EINVAL; + + cnt = trace_filter_update(&filter); + if (cnt < 0) { + ipc_cmd_err(&ipc_tr, "trace_filter_update failed for UUID key 0x%X, comp %d.%d and log level %d", + filter.uuid_id, filter.pipe_id, filter.comp_id, + filter.log_level); + ret = cnt; + } else { + tr_info(&ipc_tr, "trace_filter_update for UUID key 0x%X, comp %d.%d affected %d components", + filter.uuid_id, filter.pipe_id, filter.comp_id, + cnt); + } + + elem = next_elem; + } + + return ret; +} + +static int ipc_glb_trace_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + tr_info(&ipc_tr, "ipc: debug cmd 0x%x", cmd); + + switch (cmd) { + case SOF_IPC_TRACE_DMA_PARAMS: + case SOF_IPC_TRACE_DMA_PARAMS_EXT: + return ipc_dma_trace_config(header); + case SOF_IPC_TRACE_DMA_FREE: + ipc_dma_trace_free(header); + return 0; + case SOF_IPC_TRACE_FILTER_UPDATE: + return ipc_trace_filter_update(header); + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown debug cmd 0x%x", cmd); + return -EINVAL; + } +} +#else +static int ipc_glb_trace_message(uint32_t header) +{ + /* Return success, as the protocol provides no way to inform + * the kernel that we don't support dtrace. It will just see + * no output. + */ + return 0; +} +#endif + +static int ipc_glb_gdb_debug(uint32_t header) +{ + /* no further information needs to be extracted from header */ + (void) header; + +#if CONFIG_GDBSTUB + ipc_enter_gdb = true; + return 0; +// TODO: remove old GDB stub? +#elif CONFIG_GDB_DEBUG + gdb_init_debug_exception(); + gdb_init(); + /* TODO: this asm should be in arch/include/debug/debug.h + * with a generic name and trigger debug exception + */ + asm volatile("_break 0, 0"); + return 0; +#else + return -EINVAL; +#endif + +} + +#if CONFIG_PROBE +static inline int ipc_probe_init(uint32_t header) +{ + struct sof_ipc_probe_dma_add_params *params = ipc_get()->comp_data; + int dma_provided = params->num_elems; + + tr_dbg(&ipc_tr, "entry"); + + if (dma_provided > 1 || dma_provided < 0) { + ipc_cmd_err(&ipc_tr, "Invalid amount of extraction DMAs specified = %d", + dma_provided); + return -EINVAL; + } + + return probe_init(dma_provided ? params->probe_dma : NULL); +} + +static inline int ipc_probe_deinit(uint32_t header) +{ + tr_dbg(&ipc_tr, "entry"); + + return probe_deinit(); +} + +static inline int ipc_probe_dma_add(uint32_t header) +{ + struct sof_ipc_probe_dma_add_params *params = ipc_get()->comp_data; + int dmas_count = params->num_elems; + + tr_dbg(&ipc_tr, "entry"); + + if (dmas_count > CONFIG_PROBE_DMA_MAX) { + ipc_cmd_err(&ipc_tr, "Invalid amount of injection DMAs specified = %d. Max is " + STRINGIFY(CONFIG_PROBE_DMA_MAX) ".", + dmas_count); + return -EINVAL; + } + + if (dmas_count <= 0) { + ipc_cmd_err(&ipc_tr, "Inferred amount of incjection DMAs in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", + dmas_count); + return -EINVAL; + } + + return probe_dma_add(dmas_count, params->probe_dma); +} + +static inline int ipc_probe_dma_remove(uint32_t header) +{ + struct sof_ipc_probe_dma_remove_params *params = ipc_get()->comp_data; + int tags_count = params->num_elems; + + tr_dbg(&ipc_tr, "entry"); + + if (tags_count > CONFIG_PROBE_DMA_MAX) { + ipc_cmd_err(&ipc_tr, "Invalid amount of injection DMAs specified = %d. Max is " + STRINGIFY(CONFIG_PROBE_DMA_MAX) ".", + tags_count); + return -EINVAL; + } + + if (tags_count <= 0) { + ipc_cmd_err(&ipc_tr, "Inferred amount of incjection DMAs in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", + tags_count); + return -EINVAL; + } + + return probe_dma_remove(tags_count, params->stream_tag); +} + +static inline int ipc_probe_point_add(uint32_t header) +{ + struct sof_ipc_probe_point_add_params *params = ipc_get()->comp_data; + int probes_count = params->num_elems; + + tr_dbg(&ipc_tr, "entry"); + + if (probes_count > CONFIG_PROBE_POINTS_MAX) { + ipc_cmd_err(&ipc_tr, "Invalid amount of Probe Points specified = %d. Max is " + STRINGIFY(CONFIG_PROBE_POINT_MAX) ".", + probes_count); + return -EINVAL; + } + + if (probes_count <= 0) { + ipc_cmd_err(&ipc_tr, "Inferred amount of Probe Points in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", + probes_count); + return -EINVAL; + } + + return probe_point_add(probes_count, params->probe_point); +} + +static inline int ipc_probe_point_remove(uint32_t header) +{ + struct sof_ipc_probe_point_remove_params *params = ipc_get()->comp_data; + int probes_count = params->num_elems; + + tr_dbg(&ipc_tr, "entry"); + + if (probes_count > CONFIG_PROBE_POINTS_MAX) { + ipc_cmd_err(&ipc_tr, "Invalid amount of Probe Points specified = %d. Max is " + STRINGIFY(CONFIG_PROBE_POINT_MAX) ".", + probes_count); + return -EINVAL; + } + + if (probes_count <= 0) { + ipc_cmd_err(&ipc_tr, "Inferred amount of Probe Points in payload is %d. This could indicate corrupt size reported in header or invalid IPC payload.", + probes_count); + return -EINVAL; + } + return probe_point_remove(probes_count, params->buffer_id); +} + +static int ipc_probe_info(uint32_t header) +{ + uint32_t cmd = iCS(header); + struct sof_ipc_probe_info_params *params = ipc_get()->comp_data; + int ret; + + tr_dbg(&ipc_tr, "entry"); + + switch (cmd) { + case SOF_IPC_PROBE_DMA_INFO: + ret = probe_dma_info(params, SOF_IPC_MSG_MAX_SIZE); + break; + case SOF_IPC_PROBE_POINT_INFO: + ret = probe_point_info(params, SOF_IPC_MSG_MAX_SIZE); + break; + default: + ipc_cmd_err(&ipc_tr, "Invalid probe INFO command = %u", + cmd); + ret = -EINVAL; + } + + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "cmd %u failed", cmd); + return ret; + } + + /* write data to the outbox */ + if (params->rhdr.hdr.size <= MAILBOX_HOSTBOX_SIZE && + params->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) { + params->rhdr.error = ret; + mailbox_hostbox_write(0, params, params->rhdr.hdr.size); + ret = 1; + } else { + ipc_cmd_err(&ipc_tr, "probes module returned too much payload for cmd %u - returned %d bytes, max %d", + cmd, params->rhdr.hdr.size, + MIN(MAILBOX_HOSTBOX_SIZE, SOF_IPC_MSG_MAX_SIZE)); + ret = -EINVAL; + } + + return ret; +} + +static int ipc_glb_probe(uint32_t header) +{ + uint32_t cmd = iCS(header); + + tr_dbg(&ipc_tr, "ipc: probe cmd 0x%x", cmd); + + switch (cmd) { + case SOF_IPC_PROBE_INIT: + return ipc_probe_init(header); + case SOF_IPC_PROBE_DEINIT: + return ipc_probe_deinit(header); + case SOF_IPC_PROBE_DMA_ADD: + return ipc_probe_dma_add(header); + case SOF_IPC_PROBE_DMA_REMOVE: + return ipc_probe_dma_remove(header); + case SOF_IPC_PROBE_POINT_ADD: + return ipc_probe_point_add(header); + case SOF_IPC_PROBE_POINT_REMOVE: + return ipc_probe_point_remove(header); + case SOF_IPC_PROBE_DMA_INFO: + case SOF_IPC_PROBE_POINT_INFO: + return ipc_probe_info(header); + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown probe cmd 0x%x", cmd); + return -EINVAL; + } +} +#else +static inline int ipc_glb_probe(uint32_t header) +{ + ipc_cmd_err(&ipc_tr, "Probes not enabled by Kconfig."); + + return -EINVAL; +} +#endif + +/* + * Topology IPC Operations. + */ + +/* get/set component values or runtime data */ +static int ipc_comp_value(uint32_t header, uint32_t cmd) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *comp_dev; + struct sof_ipc_ctrl_data *data = ipc->comp_data; + int ret; + + /* get the component */ + comp_dev = ipc_get_comp_by_id(ipc, data->comp_id); + if (!comp_dev) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", data->comp_id); + return -ENODEV; + } + + /* check core */ + if (!cpu_is_me(comp_dev->core)) + return ipc_process_on_core(comp_dev->core, false); + + tr_dbg(&ipc_tr, "ipc: comp %d -> cmd %d", data->comp_id, data->cmd); + + /* get component values */ + ret = comp_cmd(comp_dev->cd, cmd, data, SOF_IPC_MSG_MAX_SIZE); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d cmd %u failed %d", data->comp_id, + data->cmd, ret); + return ret; + } + + /* write component values to the outbox */ + if (data->rhdr.hdr.size <= MAILBOX_HOSTBOX_SIZE && + data->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) { + mailbox_hostbox_write(0, data, data->rhdr.hdr.size); + ret = 1; + } else { + ipc_cmd_err(&ipc_tr, "ipc: comp %d cmd %u returned %d bytes max %d", + data->comp_id, data->cmd, data->rhdr.hdr.size, + MIN(MAILBOX_HOSTBOX_SIZE, SOF_IPC_MSG_MAX_SIZE)); + ret = -EINVAL; + } + + return ret; +} + +static int ipc_glb_comp_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + case SOF_IPC_COMP_SET_VALUE: + return ipc_comp_value(header, COMP_CMD_SET_VALUE); + case SOF_IPC_COMP_GET_VALUE: + return ipc_comp_value(header, COMP_CMD_GET_VALUE); + case SOF_IPC_COMP_SET_DATA: + return ipc_comp_value(header, COMP_CMD_SET_DATA); + case SOF_IPC_COMP_GET_DATA: + return ipc_comp_value(header, COMP_CMD_GET_DATA); + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown comp cmd 0x%x", cmd); + return -EINVAL; + } +} + +static int ipc_glb_tplg_comp_new(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_comp *comp = ipc->comp_data; + struct sof_ipc_comp_reply reply = { + .rhdr.hdr = { + .cmd = header, + .size = sizeof(reply), + }, + }; + int ret; + + /* check core */ + if (!cpu_is_me(comp->core)) + return ipc_process_on_core(comp->core, false); + + tr_dbg(&ipc_tr, "ipc: pipe %d comp %d -> new (type %d)", + comp->pipeline_id, comp->id, comp->type); + + /* register component */ + ret = ipc_comp_new(ipc, ipc_to_comp_new(comp)); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d creation failed %d", + comp->pipeline_id, comp->id, ret); + return ret; + } + + /* write component values to the outbox */ + mailbox_hostbox_write(0, &reply, sizeof(reply)); + + return 1; +} + +static int ipc_glb_tplg_buffer_new(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_buffer ipc_buffer; + struct sof_ipc_comp_reply reply = { + .rhdr.hdr = { + .cmd = header, + .size = sizeof(reply), + }, + }; + int ret; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(ipc_buffer, ipc->comp_data); + + /* check core */ + if (!cpu_is_me(ipc_buffer.comp.core)) + return ipc_process_on_core(ipc_buffer.comp.core, false); + + tr_dbg(&ipc_tr, "ipc: pipe %d buffer %d -> new (0x%x bytes)", + ipc_buffer.comp.pipeline_id, ipc_buffer.comp.id, + ipc_buffer.size); + + ret = ipc_buffer_new(ipc, (struct sof_ipc_buffer *)ipc->comp_data); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "ipc: pipe %d buffer %d creation failed %d", + ipc_buffer.comp.pipeline_id, + ipc_buffer.comp.id, ret); + return ret; + } + + /* write component values to the outbox */ + mailbox_hostbox_write(0, &reply, sizeof(reply)); + + return 1; +} + +static int ipc_glb_tplg_pipe_new(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_pipe_new ipc_pipeline; + struct sof_ipc_comp_reply reply = { + .rhdr.hdr = { + .cmd = header, + .size = sizeof(reply), + }, + }; + int ret; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(ipc_pipeline, ipc->comp_data); + + /* check core */ + if (!cpu_is_me(ipc_pipeline.core)) + return ipc_process_on_core(ipc_pipeline.core, false); + + tr_dbg(&ipc_tr, "ipc: pipe %d -> new", ipc_pipeline.pipeline_id); + + ret = ipc_pipeline_new(ipc, ipc->comp_data); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "ipc: pipe %d creation failed %d", + ipc_pipeline.pipeline_id, ret); + return ret; + } + + /* write component values to the outbox */ + mailbox_hostbox_write(0, &reply, sizeof(reply)); + + return 1; +} + +static int ipc_glb_tplg_pipe_complete(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_pipe_ready ipc_pipeline; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(ipc_pipeline, ipc->comp_data); + + return ipc_pipeline_complete(ipc, ipc_pipeline.comp_id); +} + +static int ipc_glb_tplg_comp_connect(uint32_t header) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_pipe_comp_connect connect; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(connect, ipc->comp_data); + + return ipc_comp_connect(ipc, ipc->comp_data); +} + +static int ipc_glb_tplg_free(uint32_t header, + int (*free_func)(struct ipc *ipc, uint32_t id)) +{ + struct ipc *ipc = ipc_get(); + struct sof_ipc_free ipc_free_msg; + int ret; + + /* copy message with ABI safe method */ + IPC_COPY_CMD(ipc_free_msg, ipc->comp_data); + + tr_info(&ipc_tr, "ipc: comp %d -> free", ipc_free_msg.id); + + /* free the object */ + ret = free_func(ipc, ipc_free_msg.id); + + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d free failed %d", + ipc_free_msg.id, ret); + } + + return ret; +} + +static int ipc_glb_tplg_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + case SOF_IPC_TPLG_COMP_NEW: + return ipc_glb_tplg_comp_new(header); + case SOF_IPC_TPLG_COMP_FREE: + return ipc_glb_tplg_free(header, ipc_comp_free); + case SOF_IPC_TPLG_COMP_CONNECT: + return ipc_glb_tplg_comp_connect(header); + case SOF_IPC_TPLG_PIPE_NEW: + return ipc_glb_tplg_pipe_new(header); + case SOF_IPC_TPLG_PIPE_COMPLETE: + return ipc_glb_tplg_pipe_complete(header); + case SOF_IPC_TPLG_PIPE_FREE: + return ipc_glb_tplg_free(header, ipc_pipeline_free); + case SOF_IPC_TPLG_BUFFER_NEW: + return ipc_glb_tplg_buffer_new(header); + case SOF_IPC_TPLG_BUFFER_FREE: + return ipc_glb_tplg_free(header, ipc_buffer_free); + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown tplg header 0x%x", header); + return -EINVAL; + } +} + +static int ipc_glb_debug_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + /* TODO: Zephyr heap debug needs to added for IPC3 using Zephyr APIs. */ + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown debug header 0x%x", header); + return -EINVAL; + } +} + +#if CONFIG_DEBUG +static int ipc_glb_test_message(uint32_t header) +{ + uint32_t cmd = iCS(header); + + switch (cmd) { + case SOF_IPC_TEST_IPC_FLOOD: + return 0; /* just return so next IPC can be sent */ + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown test header 0x%x", header); + return -EINVAL; + } +} +#endif + +#if CONFIG_CAVS +static struct ipc_cmd_hdr *ipc_cavs_read_set_d0ix(struct ipc_cmd_hdr *hdr) +{ + struct sof_ipc_pm_gate *cmd = ipc_get()->comp_data; + uint32_t *chdr = (uint32_t *)hdr; + + cmd->hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE; + cmd->hdr.size = sizeof(*cmd); + cmd->flags = chdr[1] & CAVS_IPC_MOD_SETD0IX_BIT_MASK; + + return ipc_to_hdr(&cmd->hdr); +} + +/* + * Read a compact IPC message or return NULL for normal message. + */ +struct ipc_cmd_hdr *ipc_compact_read_msg(void) +{ + uint32_t chdr[2]; + struct ipc_cmd_hdr *hdr = (struct ipc_cmd_hdr *)chdr; + int words; + + words = ipc_platform_compact_read_msg(hdr, 2); + if (!words) + return mailbox_validate(); + + /* if there is no cAVS module IPC in regs go the previous path */ + if (!(chdr[0] & CAVS_IPC_MSG_TGT)) + return mailbox_validate(); + + switch (CAVS_IPC_TYPE_S(chdr[0])) { + case CAVS_IPC_MOD_SET_D0IX: + return ipc_cavs_read_set_d0ix(hdr); + } + + return NULL; +} +#endif + +/* prepare the message using ABI major layout */ +struct ipc_cmd_hdr *ipc_prepare_to_send(const struct ipc_msg *msg) +{ + static uint32_t hdr[2]; + + hdr[0] = msg->header; + hdr[1] = 0; + + mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); + + return ipc_to_hdr(hdr); +} + +void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) +{ + header->dat[0] = SOF_IPC_FW_READY; + 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. + */ + +void ipc_cmd(struct ipc_cmd_hdr *_hdr) +{ + struct sof_ipc_cmd_hdr *hdr = ipc_from_hdr(_hdr); + struct ipc *ipc = ipc_get(); + struct sof_ipc_reply reply; + uint32_t type = 0; + int ret; + + if (!hdr) { + ipc_cmd_err(&ipc_tr, "ipc: invalid IPC header."); + ret = -EINVAL; + goto out; + } + + if (cpu_is_primary(cpu_get_id())) { + /* A new IPC from the host, delivered to the primary core */ + ipc->core = PLATFORM_PRIMARY_CORE_ID; + tr_info(&ipc_tr, "ipc: new cmd 0x%x", hdr->cmd); + } + + type = iGS(hdr->cmd); + + switch (type) { + case SOF_IPC_GLB_REPLY: + ret = 0; + break; + case SOF_IPC_GLB_COMPOUND: + ret = -EINVAL; /* TODO */ + break; + case SOF_IPC_GLB_TPLG_MSG: + ret = ipc_glb_tplg_message(hdr->cmd); + break; + case SOF_IPC_GLB_PM_MSG: + ret = ipc_glb_pm_message(hdr->cmd); + break; + case SOF_IPC_GLB_COMP_MSG: + ret = ipc_glb_comp_message(hdr->cmd); + break; + case SOF_IPC_GLB_STREAM_MSG: + ret = ipc_glb_stream_message(hdr->cmd); + break; + case SOF_IPC_GLB_DAI_MSG: + ret = ipc_glb_dai_message(hdr->cmd); + break; + case SOF_IPC_GLB_TRACE_MSG: + ret = ipc_glb_trace_message(hdr->cmd); + break; + case SOF_IPC_GLB_GDB_DEBUG: + ret = ipc_glb_gdb_debug(hdr->cmd); + break; + case SOF_IPC_GLB_PROBE: + ret = ipc_glb_probe(hdr->cmd); + break; + 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); + break; +#endif + default: + ipc_cmd_err(&ipc_tr, "ipc: unknown command type %u", type); + ret = -EINVAL; + break; + } + +out: + tr_dbg(&ipc_tr, "ipc: last request 0x%x returned %d", type, ret); + + /* if ret > 0, reply created and copied by cmd() */ + if (ret <= 0) { + /* send std error/ok reply */ + reply.error = ret; + + reply.hdr.cmd = SOF_IPC_GLB_REPLY; + reply.hdr.size = sizeof(reply); + mailbox_hostbox_write(0, &reply, sizeof(reply)); + } +} diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c new file mode 100644 index 000000000000..4d87f042dd1d --- /dev/null +++ b/src/ipc/ipc3/helper.c @@ -0,0 +1,724 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/idc.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <sof/lib/mailbox.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx comp_tr; + +/** + * Retrieves component config data from component ipc. + * @param comp Component ipc data. + * @return Pointer to the component config data. + */ +static inline struct sof_ipc_comp_config *comp_config(struct sof_ipc_comp *comp) +{ + return (struct sof_ipc_comp_config *)(comp + 1); +} + +void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, uint32_t type, + uint32_t id) +{ + posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | type | id; + posn->rhdr.hdr.size = sizeof(*posn); + posn->comp_id = id; +} + +void ipc_build_comp_event(struct sof_ipc_comp_event *event, uint32_t type, + uint32_t id) +{ + event->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | SOF_IPC_COMP_NOTIFICATION | + id; + event->rhdr.hdr.size = sizeof(*event); + event->src_comp_type = type; + event->src_comp_id = id; +} + +bool ipc_trigger_trace_xfer(uint32_t avail) +{ + return true; +} + +void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn) +{ + posn->rhdr.hdr.cmd = SOF_IPC_GLB_TRACE_MSG | + SOF_IPC_TRACE_DMA_POSITION; + posn->rhdr.hdr.size = sizeof(*posn); +} + +static const struct comp_driver *get_drv(struct sof_ipc_comp *comp) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct list_item *clist; + const struct comp_driver *drv = NULL; + struct comp_driver_info *info; + struct sof_ipc_comp_ext *comp_ext; + uintptr_t offset; + k_spinlock_key_t key; + + /* do we have extended data ? */ + if (!comp->ext_data_length) { + /* search driver list for driver type */ + list_for_item(clist, &drivers->list) { + info = container_of(clist, struct comp_driver_info, list); + if (info->drv->type == comp->type) { + drv = info->drv; + break; + } + } + + if (!drv) + tr_err(&comp_tr, "driver not found, comp->type = %u", + comp->type); + + goto out; + } + + /* Basic sanity check of the total size and extended data + * length. A bit lax because in this generic code we don't know + * which derived comp we have and how much its specific members + * add. + */ + if (comp->ext_data_length > SOF_IPC_MSG_MAX_SIZE || + comp->hdr.size < sizeof(*comp) + comp->ext_data_length) { + tr_err(&comp_tr, "Invalid size, hdr.size=0x%x, ext_data_length=0x%x\n", + comp->hdr.size, comp->ext_data_length); + goto out; + } + + offset = comp->hdr.size - comp->ext_data_length; + if (!IS_ALIGNED(offset, 4)) { + tr_err(&comp_tr, "Invalid ext data offset %lx", offset); + goto out; + } + + comp_ext = (struct sof_ipc_comp_ext *)((uint8_t *)comp + offset); + + /* UUID is first item in extended data - check its big enough */ + if (comp->ext_data_length < UUID_SIZE) { + tr_err(&comp_tr, "UUID is invalid!\n"); + goto out; + } + + /* search driver list with UUID */ + key = k_spin_lock(&drivers->lock); + + list_for_item(clist, &drivers->list) { + info = container_of(clist, struct comp_driver_info, + list); + if (!memcmp(info->drv->uid, comp_ext->uuid, + UUID_SIZE)) { + drv = info->drv; + break; + } + } + + if (!drv) + tr_err(&comp_tr, + "the provided UUID (%8x%8x%8x%8x) doesn't match to any driver!", + *(uint32_t *)(&comp_ext->uuid[0]), + *(uint32_t *)(&comp_ext->uuid[4]), + *(uint32_t *)(&comp_ext->uuid[8]), + *(uint32_t *)(&comp_ext->uuid[12])); + + k_spin_unlock(&drivers->lock, key); + +out: + if (drv) + tr_dbg(&comp_tr, "get_drv(), found driver type %d, uuid %pU", + drv->type, drv->tctx->uuid_p); + + return drv; +} + +/* build generic IPC data for all components */ +static void comp_common_builder(struct sof_ipc_comp *comp, + struct comp_ipc_config *config) +{ + struct sof_ipc_comp_config *ipc_config; + + /* create the new component */ + memset(config, 0, sizeof(*config)); + config->core = comp->core; + config->id = comp->id; + config->pipeline_id = comp->pipeline_id; + config->proc_domain = COMP_PROCESSING_DOMAIN_LL; + config->type = comp->type; + + /* buffers dont have the following data */ + if (comp->type != SOF_COMP_BUFFER) { + /* ipc common config is always after sof_ipc_comp */ + ipc_config = (struct sof_ipc_comp_config *)(comp + 1); + config->frame_fmt = ipc_config->frame_fmt; + config->periods_sink = ipc_config->periods_sink; + config->periods_source = ipc_config->periods_source; + config->xrun_action = ipc_config->xrun_action; + } +} +/* + * Stores all the "legacy" init IPC data locally. + */ +union ipc_config_specific { + struct ipc_config_host host; + struct ipc_config_dai dai; + struct ipc_config_volume volume; + struct ipc_config_src src; + struct ipc_config_asrc asrc; + struct ipc_config_tone tone; + struct ipc_config_process process; + struct ipc_comp_file file; +} __attribute__((packed, aligned(4))); + +/* build component specific data */ +static int comp_specific_builder(struct sof_ipc_comp *comp, + union ipc_config_specific *config) +{ +#if CONFIG_LIBRARY + struct sof_ipc_comp_file *file = (struct sof_ipc_comp_file *)comp; +#endif + struct sof_ipc_comp_host *host = (struct sof_ipc_comp_host *)comp; + struct sof_ipc_comp_dai *dai = (struct sof_ipc_comp_dai *)comp; + struct sof_ipc_comp_volume *vol = (struct sof_ipc_comp_volume *)comp; + struct sof_ipc_comp_process *proc = (struct sof_ipc_comp_process *)comp; + struct sof_ipc_comp_src *src = (struct sof_ipc_comp_src *)comp; + struct sof_ipc_comp_asrc *asrc = (struct sof_ipc_comp_asrc *)comp; + struct sof_ipc_comp_tone *tone = (struct sof_ipc_comp_tone *)comp; + + memset(config, 0, sizeof(*config)); + + switch (comp->type) { +#if CONFIG_LIBRARY + /* test bench maps host and DAIs to a file */ + case SOF_COMP_FILEREAD: + case SOF_COMP_FILEWRITE: + if (IPC_TAIL_IS_SIZE_INVALID(*file)) + return -EBADMSG; + + config->file.channels = file->channels; + config->file.fn = file->fn; + config->file.frame_fmt = file->frame_fmt; + config->file.mode = file->mode; + config->file.rate = file->rate; + config->file.direction = file->direction; + + /* For module_adapter_init_data() ipc_module_adapter compatibility */ + config->file.module_header.type = proc->type; + config->file.module_header.size = proc->size; + config->file.module_header.data = (uint8_t *)proc->data - + sizeof(struct ipc_config_process); + break; +#endif + case SOF_COMP_HOST: + case SOF_COMP_SG_HOST: + if (IPC_TAIL_IS_SIZE_INVALID(*host)) + return -EBADMSG; + config->host.direction = host->direction; + config->host.no_irq = host->no_irq; + config->host.dmac_config = host->dmac_config; + break; + case SOF_COMP_DAI: + case SOF_COMP_SG_DAI: + if (IPC_TAIL_IS_SIZE_INVALID(*dai)) + return -EBADMSG; + config->dai.dai_index = dai->dai_index; + config->dai.direction = dai->direction; + config->dai.type = dai->type; + break; + case SOF_COMP_VOLUME: + if (IPC_TAIL_IS_SIZE_INVALID(*vol)) + return -EBADMSG; + config->volume.channels = vol->channels; + config->volume.initial_ramp = vol->initial_ramp; + config->volume.max_value = vol->max_value; + config->volume.min_value = vol->min_value; + config->volume.ramp = vol->ramp; + break; + case SOF_COMP_SRC: + if (IPC_TAIL_IS_SIZE_INVALID(*src)) + return -EBADMSG; + config->src.rate_mask = src->rate_mask; + config->src.sink_rate = src->sink_rate; + config->src.source_rate = src->source_rate; + break; + case SOF_COMP_TONE: + if (IPC_TAIL_IS_SIZE_INVALID(*tone)) + return -EBADMSG; + config->tone.ampl_mult = tone->ampl_mult; + config->tone.amplitude = tone->amplitude; + config->tone.freq_mult = tone->freq_mult; + config->tone.frequency = tone->frequency; + config->tone.length = tone->length; + config->tone.period = tone->period; + config->tone.ramp_step = tone->ramp_step; + config->tone.repeats = tone->repeats; + config->tone.sample_rate = tone->sample_rate; + break; + case SOF_COMP_ASRC: + if (IPC_TAIL_IS_SIZE_INVALID(*asrc)) + return -EBADMSG; + config->asrc.source_rate = asrc->source_rate; + config->asrc.sink_rate = asrc->sink_rate; + config->asrc.asynchronous_mode = asrc->asynchronous_mode; + config->asrc.operation_mode = asrc->operation_mode; + break; + case SOF_COMP_EQ_IIR: + case SOF_COMP_EQ_FIR: + case SOF_COMP_KEYWORD_DETECT: + case SOF_COMP_KPB: + case SOF_COMP_SELECTOR: + case SOF_COMP_DEMUX: + case SOF_COMP_MUX: + case SOF_COMP_DCBLOCK: + case SOF_COMP_SMART_AMP: + case SOF_COMP_MODULE_ADAPTER: + case SOF_COMP_NONE: + if (IPC_TAIL_IS_SIZE_INVALID(*proc)) + return -EBADMSG; + + if (proc->comp.hdr.size + proc->size > SOF_IPC_MSG_MAX_SIZE) + return -EBADMSG; + + config->process.type = proc->type; + config->process.size = proc->size; +#if CONFIG_LIBRARY || UNIT_TEST + config->process.data = proc->data + comp->ext_data_length; +#else + config->process.data = proc->data; +#endif + break; + case SOF_COMP_MIXER: + break; + default: + return -EINVAL; + } + return 0; +} + +struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, + uint16_t type, uint32_t ppl_id, + uint32_t ignore_remote) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != type) + continue; + if ((!cpu_is_me(icd->core)) && ignore_remote) + continue; + if (ipc_comp_pipe_id(icd) == ppl_id) + return icd; + } + return NULL; +} + +struct comp_dev *comp_new(struct sof_ipc_comp *comp) +{ + struct comp_ipc_config config; + union ipc_config_specific spec; + struct comp_dev *cdev; + const struct comp_driver *drv; + + /* find the driver for our new component */ + drv = get_drv(comp); + if (!drv) + return NULL; + + /* validate size of ipc config */ + if (IPC_IS_SIZE_INVALID(*comp_config(comp))) { + IPC_SIZE_ERROR_TRACE(&comp_tr, *comp_config(comp)); + return NULL; + } + + tr_info(&comp_tr, "comp new %pU type %d id %d.%d", + drv->tctx->uuid_p, comp->type, comp->pipeline_id, comp->id); + + /* build the component */ + if (comp_specific_builder(comp, &spec) < 0) { + comp_cl_err(drv, "component type not recognized"); + return NULL; + } + comp_common_builder(comp, &config); + cdev = drv->ops.create(drv, &config, &spec); + if (!cdev) { + comp_cl_err(drv, "unable to create the new component"); + return NULL; + } + + list_init(&cdev->bsource_list); + list_init(&cdev->bsink_list); + + return cdev; +} + +int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) +{ + struct sof_ipc_pipe_new *pipe_desc = ipc_from_pipe_new(_pipe_desc); + struct ipc_comp_dev *ipc_pipe; + struct pipeline *pipe; + int ret; + + /* check whether the pipeline already exists */ + ipc_pipe = ipc_get_pipeline_by_id(ipc, pipe_desc->comp_id); + if (ipc_pipe != NULL) { + tr_err(&ipc_tr, "pipeline already exists, pipe_desc->comp_id = %u", + pipe_desc->comp_id); + return -EINVAL; + } + + /* create the pipeline */ + pipe = pipeline_new(NULL, pipe_desc->pipeline_id, pipe_desc->priority, + pipe_desc->comp_id, NULL); + if (!pipe) { + tr_err(&ipc_tr, "pipeline_new() failed"); + return -ENOMEM; + } + + /* configure pipeline */ + pipeline_schedule_config(pipe, pipe_desc->sched_id, + pipe_desc->core, pipe_desc->period, + pipe_desc->period_mips, + pipe_desc->frames_per_sched, + pipe_desc->time_domain); + + /* set xrun time limit */ + ret = pipeline_xrun_set_limit(pipe, pipe_desc->xrun_limit_usecs); + if (ret) { + tr_err(&ipc_tr, "pipeline_xrun_set_limit() failed"); + pipeline_free(pipe); + return ret; + } + + /* allocate the IPC pipeline container */ + ipc_pipe = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct ipc_comp_dev)); + if (!ipc_pipe) { + pipeline_free(pipe); + return -ENOMEM; + } + + ipc_pipe->pipeline = pipe; + ipc_pipe->type = COMP_TYPE_PIPELINE; + ipc_pipe->core = pipe_desc->core; + ipc_pipe->id = pipe_desc->comp_id; + + /* add new pipeline to the list */ + list_item_append(&ipc_pipe->list, &ipc->comp_list); + + return 0; +} + +int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_pipe; + int ret; + + /* check whether pipeline exists */ + ipc_pipe = ipc_get_pipeline_by_id(ipc, comp_id); + if (!ipc_pipe) + return -ENODEV; + + /* check type */ + if (ipc_pipe->type != COMP_TYPE_PIPELINE) { + tr_err(&ipc_tr, "comp id: %d is not a PIPELINE", + comp_id); + return -EINVAL; + } + + /* check core */ + if (!cpu_is_me(ipc_pipe->core)) + return ipc_process_on_core(ipc_pipe->core, false); + + /* free buffer and remove from list */ + ret = pipeline_free(ipc_pipe->pipeline); + if (ret < 0) { + tr_err(&ipc_tr, "pipeline_free() failed"); + return ret; + } + ipc_pipe->pipeline = NULL; + list_item_del(&ipc_pipe->list); + rfree(ipc_pipe); + + return 0; +} + +int ipc_buffer_new(struct ipc *ipc, const struct sof_ipc_buffer *desc) +{ + struct ipc_comp_dev *ibd; + struct comp_buffer *buffer; + int ret = 0; + + /* check whether buffer already exists */ + ibd = ipc_get_buffer_by_id(ipc, desc->comp.id); + if (ibd != NULL) { + tr_err(&ipc_tr, "buffer already exists, desc->comp.id = %u", + desc->comp.id); + return -EINVAL; + } + + /* register buffer with pipeline */ + buffer = buffer_new(NULL, desc, BUFFER_USAGE_NOT_SHARED); + if (!buffer) { + tr_err(&ipc_tr, "buffer_new() failed"); + return -ENOMEM; + } + + ibd = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct ipc_comp_dev)); + if (!ibd) { + buffer_free(buffer); + return -ENOMEM; + } + ibd->cb = buffer; + ibd->type = COMP_TYPE_BUFFER; + ibd->core = desc->comp.core; + ibd->id = desc->comp.id; + + /* add new buffer to the list */ + list_item_append(&ibd->list, &ipc->comp_list); + + return ret; +} + +int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id) +{ + struct ipc_comp_dev *ibd; + struct ipc_comp_dev *icd; + struct list_item *clist; + struct comp_dev *sink = NULL, *source = NULL; + struct comp_dev *active_comp; + unsigned int core; + bool sink_active = false; + bool source_active = false; + + /* check whether buffer exists */ + ibd = ipc_get_buffer_by_id(ipc, buffer_id); + if (!ibd) + return -ENODEV; + + /* check core */ + if (!cpu_is_me(ibd->core)) + return ipc_process_on_core(ibd->core, false); + + /* try to find sink/source components to check if they still exists */ + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + /* check comp state if sink and source are valid */ + if (comp_buffer_get_sink_component(ibd->cb) == icd->cd) { + sink = comp_buffer_get_sink_component(ibd->cb); + if (comp_buffer_get_sink_state(ibd->cb) != COMP_STATE_READY) + sink_active = true; + } + + if (comp_buffer_get_source_component(ibd->cb) == icd->cd) { + source = comp_buffer_get_source_component(ibd->cb); + if (comp_buffer_get_source_state(ibd->cb) != COMP_STATE_READY) + source_active = true; + } + } + + /* + * A buffer could be connected to 2 different pipelines. When one pipeline is freed, the + * buffer comp that belongs in this pipeline will need to be freed even when the other + * pipeline that the buffer is connected to is active. Check if both ends are active before + * freeing the buffer. + */ + if (sink_active && source_active) + return -EINVAL; + + /* + * If either component is active and is running on a different + * core, the free must be run in the context of the active + * pipeline. + */ + if (sink_active) + active_comp = sink; + else if (source_active) + active_comp = source; + else + active_comp = NULL; + + if (active_comp) { + core = active_comp->ipc_config.core; + + if (active_comp->state > COMP_STATE_READY && + core != ibd->core && core != cpu_get_id()) { + tr_dbg(&ipc_tr, "comp id: %d run on sink core %u", + buffer_id, core); + ibd->core = core; + return ipc_process_on_core(core, false); + } + } + + /* + * Disconnect the buffer from the active component before freeing it. + */ + if (sink) + pipeline_disconnect(sink, ibd->cb, PPL_CONN_DIR_BUFFER_TO_COMP); + + if (source) + pipeline_disconnect(source, ibd->cb, PPL_CONN_DIR_COMP_TO_BUFFER); + + /* free buffer and remove from list */ + buffer_free(ibd->cb); + list_item_del(&ibd->list); + rfree(ibd); + + return 0; +} + +static int ipc_comp_to_buffer_connect(struct ipc_comp_dev *comp, + struct ipc_comp_dev *buffer) +{ + tr_dbg(&ipc_tr, "ipc: comp sink %d, source %d -> connect", buffer->id, + comp->id); + +#if CONFIG_INCOHERENT + if (comp->core != buffer->cb->core) { + tr_err(&ipc_tr, "ipc: shared buffers are not supported for IPC3 incoherent architectures"); + return -ENOTSUP; + } +#endif + return comp_buffer_connect(comp->cd, comp->core, buffer->cb, + PPL_CONN_DIR_COMP_TO_BUFFER); +} + +static int ipc_buffer_to_comp_connect(struct ipc_comp_dev *buffer, + struct ipc_comp_dev *comp) +{ + tr_dbg(&ipc_tr, "ipc: comp sink %d, source %d -> connect", comp->id, + buffer->id); + +#if CONFIG_INCOHERENT + if (comp->core != buffer->cb->core) { + tr_err(&ipc_tr, "ipc: shared buffers are not supported for IPC3 incoherent architectures"); + return -ENOTSUP; + } +#endif + return comp_buffer_connect(comp->cd, comp->core, buffer->cb, + PPL_CONN_DIR_BUFFER_TO_COMP); +} + +int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) +{ + struct sof_ipc_pipe_comp_connect *connect = ipc_from_pipe_connect(_connect); + struct ipc_comp_dev *icd_source; + struct ipc_comp_dev *icd_sink; + + /* check whether the components already exist */ + icd_source = ipc_get_comp_dev(ipc, COMP_TYPE_ANY, connect->source_id); + if (!icd_source) { + tr_err(&ipc_tr, "source component does not exist, source_id = %u sink_id = %u", + connect->source_id, connect->sink_id); + return -EINVAL; + } + + icd_sink = ipc_get_comp_dev(ipc, COMP_TYPE_ANY, connect->sink_id); + if (!icd_sink) { + tr_err(&ipc_tr, "sink component does not exist, source_id = %d sink_id = %u", + connect->sink_id, connect->source_id); + return -EINVAL; + } + + /* check source and sink types */ + if (icd_source->type == COMP_TYPE_BUFFER && + icd_sink->type == COMP_TYPE_COMPONENT) + return ipc_buffer_to_comp_connect(icd_source, icd_sink); + else if (icd_source->type == COMP_TYPE_COMPONENT && + icd_sink->type == COMP_TYPE_BUFFER) + return ipc_comp_to_buffer_connect(icd_source, icd_sink); + else { + tr_err(&ipc_tr, "invalid source and sink types, connect->source_id = %u, connect->sink_id = %u", + connect->source_id, connect->sink_id); + return -EINVAL; + } +} + +int ipc_comp_new(struct ipc *ipc, ipc_comp *_comp) +{ + struct sof_ipc_comp *comp = ipc_from_comp_new(_comp); + struct comp_dev *cd; + struct ipc_comp_dev *icd; + + /* check core is valid */ + if (comp->core >= CONFIG_CORE_COUNT) { + tr_err(&ipc_tr, "comp->core = %u", comp->core); + return -EINVAL; + } + + /* check whether component already exists */ + icd = ipc_get_comp_by_id(ipc, comp->id); + if (icd != NULL) { + tr_err(&ipc_tr, "comp->id = %u", comp->id); + return -EINVAL; + } + + /* create component */ + cd = comp_new(comp); + if (!cd) { + tr_err(&ipc_tr, "component cd = NULL"); + return -EINVAL; + } + + /* allocate the IPC component container */ + icd = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct ipc_comp_dev)); + if (!icd) { + tr_err(&ipc_tr, "alloc failed"); + rfree(cd); + return -ENOMEM; + } + icd->cd = cd; + icd->type = COMP_TYPE_COMPONENT; + icd->core = comp->core; + icd->id = comp->id; + + /* add new component to the list */ + list_item_append(&icd->list, &ipc->comp_list); + + return 0; +} + +void ipc_msg_reply(struct sof_ipc_reply *reply) +{ + struct ipc *ipc = ipc_get(); + k_spinlock_key_t key; + + mailbox_hostbox_write(0, reply, reply->hdr.size); + + key = k_spin_lock(&ipc->lock); + ipc->task_mask &= ~IPC_TASK_IN_THREAD; + ipc_complete_cmd(ipc); + k_spin_unlock(&ipc->lock, key); +} diff --git a/src/ipc/ipc3/host-page-table.c b/src/ipc/ipc3/host-page-table.c new file mode 100644 index 000000000000..997ee6683352 --- /dev/null +++ b/src/ipc/ipc3/host-page-table.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/ipc/driver.h> +#include <rtos/alloc.h> +#include <sof/lib/dma.h> +#include <sof/platform.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +/* + * Parse the host page tables and create the audio DMA SG configuration + * for host audio DMA buffer. This involves creating a dma_sg_elem for each + * page table entry and adding each elem to a list in struct dma_sg_config. + */ +static int ipc_parse_page_descriptors(uint8_t *page_table, + struct sof_ipc_host_buffer *ring, + struct dma_sg_elem_array *elem_array, + uint32_t direction) +{ + int i; + uint32_t idx; + uint32_t phy_addr; + struct dma_sg_elem *e; + + /* the ring size may be not multiple of the page size, the last + * page may be not full used. The used size should be in range + * of (ring->pages - 1, ring->pages] * PAGES. + */ + if ((ring->size <= HOST_PAGE_SIZE * (ring->pages - 1)) || + (ring->size > HOST_PAGE_SIZE * ring->pages)) { + /* error buffer size */ + tr_err(&ipc_tr, "error buffer size"); + return -EINVAL; + } + + elem_array->elems = rzalloc(SOF_MEM_FLAG_USER, + sizeof(struct dma_sg_elem) * ring->pages); + if (!elem_array->elems) { + tr_err(&ipc_tr, "There is no heap free with this block size: %zu", + sizeof(struct dma_sg_elem) * ring->pages); + return -ENOMEM; + } + + elem_array->count = ring->pages; + + for (i = 0; i < ring->pages; i++) { + idx = (((i << 2) + i)) >> 1; + phy_addr = page_table[idx] | (page_table[idx + 1] << 8) + | (page_table[idx + 2] << 16); + + if (i & 0x1) + phy_addr <<= 8; + else + phy_addr <<= 12; + phy_addr &= 0xfffff000; + phy_addr = host_to_local(phy_addr); + + e = elem_array->elems + i; + + if (direction == SOF_IPC_STREAM_PLAYBACK) + e->src = phy_addr; + else + e->dest = phy_addr; + + /* the last page may be not full used */ + if (i == (ring->pages - 1)) + e->size = ring->size - HOST_PAGE_SIZE * i; + else + e->size = HOST_PAGE_SIZE; + } + + return 0; +} + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +/* + * Copy the audio buffer page tables from the host to the DSP max of 4K. + */ +static int ipc_get_page_descriptors(struct sof_dma *dmac, uint8_t *page_table, + struct sof_ipc_host_buffer *ring) +{ + struct dma_config cfg; + struct dma_block_config blk; + int channel, ret; + uint32_t align; + + /* TODO: ATM, all of this is somewhat NXP-specific as the + * DMA driver used by NXP performs the transfer via the + * reload() function which may not be the case for all + * vendors. + */ + if (!IS_ENABLED(CONFIG_DMA_NXP_SOF_HOST_DMA)) { + tr_err(&ipc_tr, "DMAC not supported for page transfer"); + return -ENOTSUP; + } + + channel = dma_request_channel(dmac->z_dev, 0); + if (channel < 0) { + tr_err(&ipc_tr, "failed to request channel"); + return channel; + } + + /* fetch copy alignment */ + ret = dma_get_attribute(dmac->z_dev, DMA_ATTR_COPY_ALIGNMENT, &align); + if (ret < 0) { + tr_err(&ipc_tr, "failed to fetch copy alignment"); + goto out_release_channel; + } + + /* prepare DMA configuration */ + cfg.source_data_size = sizeof(uint32_t); + cfg.dest_data_size = sizeof(uint32_t); + cfg.block_count = 1; + cfg.head_block = &blk; + cfg.channel_direction = HOST_TO_MEMORY; + + blk.source_address = POINTER_TO_UINT(host_to_local(ring->phy_addr)); + blk.dest_address = POINTER_TO_UINT(page_table); + blk.block_size = ALIGN_UP(SOF_DIV_ROUND_UP(ring->pages * 20, 8), align); + + /* commit configuration */ + ret = dma_config(dmac->z_dev, channel, &cfg); + if (ret < 0) { + tr_err(&ipc_tr, "failed to commit configuration"); + goto out_release_channel; + } + + /* do transfer */ + ret = dma_reload(dmac->z_dev, channel, 0, 0, 0); + if (ret < 0) + tr_err(&ipc_tr, "failed to perform transfer"); + +out_release_channel: + dma_release_channel(dmac->z_dev, channel); + + return ret; +} +#else +static int ipc_get_page_descriptors(struct dma *dmac, uint8_t *page_table, + struct sof_ipc_host_buffer *ring) +{ + struct dma_sg_config config; + struct dma_sg_elem elem; + struct dma_chan_data *chan; + uint32_t dma_copy_align; + int ret = 0; + + /* get DMA channel from DMAC */ + chan = dma_channel_get_legacy(dmac, 0); + if (!chan) { + tr_err(&ipc_tr, "chan is NULL"); + return -ENODEV; + } + + /* set up DMA configuration */ + config.direction = DMA_DIR_HMEM_TO_LMEM; + config.src_width = sizeof(uint32_t); + config.dest_width = sizeof(uint32_t); + config.cyclic = 0; + config.irq_disabled = false; + dma_sg_init(&config.elem_array); + + ring->phy_addr = host_to_local(ring->phy_addr); + /* set up DMA descriptor */ + elem.dest = (uintptr_t)page_table; + elem.src = ring->phy_addr; + + /* source buffer size is always PAGE_SIZE bytes */ + /* 20 bits for each page, round up to minimum DMA copy size */ + ret = dma_get_attribute_legacy(dmac, DMA_ATTR_COPY_ALIGNMENT, &dma_copy_align); + if (ret < 0) { + tr_err(&ipc_tr, "dma_get_attribute() failed"); + goto out; + } + elem.size = SOF_DIV_ROUND_UP(ring->pages * 20, 8); + elem.size = ALIGN_UP(elem.size, dma_copy_align); + config.elem_array.elems = &elem; + config.elem_array.count = 1; + + ret = dma_set_config_legacy(chan, &config); + if (ret < 0) { + tr_err(&ipc_tr, "dma_set_config() failed"); + goto out; + } + + /* start the copy of page table to DSP */ + ret = dma_copy_legacy(chan, elem.size, DMA_COPY_ONE_SHOT | DMA_COPY_BLOCKING); + if (ret < 0) { + tr_err(&ipc_tr, "dma_start() failed"); + goto out; + } + + /* compressed page tables now in buffer at _ipc->page_table */ +out: + dma_channel_put_legacy(chan); + return ret; +} +#endif /* CONFIG_ZEPHYR_NATIVE_DRIVERS */ + +int ipc_process_host_buffer(struct ipc *ipc, + struct sof_ipc_host_buffer *ring, + uint32_t direction, + struct dma_sg_elem_array *elem_array, + uint32_t *ring_size) +{ + struct ipc_data_host_buffer *data_host_buffer; + int err; + + data_host_buffer = ipc_platform_get_host_buffer(ipc); + dma_sg_init(elem_array); + + /* use DMA to read in compressed page table ringbuffer from host */ + err = ipc_get_page_descriptors(data_host_buffer->dmac, + data_host_buffer->page_table, + ring); + if (err < 0) { + tr_err(&ipc_tr, "ipc: get descriptors failed %d", err); + goto error; + } + + *ring_size = ring->size; + + err = ipc_parse_page_descriptors(data_host_buffer->page_table, + ring, + elem_array, direction); + if (err < 0) { + tr_err(&ipc_tr, "ipc: parse descriptors failed %d", err); + goto error; + } + + return 0; +error: + dma_sg_free(NULL, elem_array); + return err; +} diff --git a/src/ipc/ipc4/CMakeLists.txt b/src/ipc/ipc4/CMakeLists.txt new file mode 100644 index 000000000000..360a4e988650 --- /dev/null +++ b/src/ipc/ipc4/CMakeLists.txt @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Files common to Zephyr and XTOS +add_local_sources(sof + handler-user.c + handler-kernel.c + helper.c + logging.c + notification.c +) + +# The DAI interface is not implemented in library builds and +# code depends on Zephyr DAI driver definitions to be available. +if(NOT CONFIG_LIBRARY) + add_local_sources(sof dai.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + +zephyr_library_sources_ifdef(CONFIG_AMS + ams_helpers.c +) + +else() ### Not Zephyr #### + +target_include_directories(sof_options INTERFACE ${RIMAGE_TOP}/src/include) + +endif() # Zephyr diff --git a/src/ipc/ipc4/README.md b/src/ipc/ipc4/README.md new file mode 100644 index 000000000000..1b40195085b9 --- /dev/null +++ b/src/ipc/ipc4/README.md @@ -0,0 +1,104 @@ +# IPC4 Architecture + +This directory holds the handlers and topology parsing logic for Inter-Processor Communication Version 4. IPC4 introduces a significantly denser, compound-command structure heavily based around the concept of "pipelines" and dynamic "modules" rather than static DSP stream roles. + +## Overview + +Unlike older iterations (IPC3) which trigger single components via scalar commands, IPC4 uses compound structures. A single host interrupt might contain batch operations like building an entire processing chain, setting module parameters sequentially, and triggering a start across multiple interconnected blocks simultaneously. + +## Message Handling and Dispatch + +IPC4 messages are received via the generic IPC handler entry point `ipc_cmd()`. `ipc_cmd()` determines the IPC target and dispatches the message appropriately. Global messages are dispatched to `ipc4_process_glb_message()`, while module-specific messages are routed directly to `ipc4_process_module_message()`. + +```mermaid +graph TD + Mailbox[IPC Mailbox Interrupt] --> CoreIPC[ipc_cmd] + + CoreIPC --> TypeSel{Decode IPC Message Target} + TypeSel -->|FW_GEN_MSG| Glb[ipc4_process_glb_message] + TypeSel -->|MODULE_MSG| Mod[ipc4_process_module_message] + + subgraph Global Handler + Glb --> NewPipe[ipc4_new_pipeline] + Glb --> DelPipe[ipc4_delete_pipeline] + Glb --> MemMap[ipc4_process_chain_dma] + Glb --> SetPipe[ipc4_set_pipeline_state] + end + + subgraph Module Handler + Mod --> InitMod[ipc4_init_module_instance] + Mod --> SetMod[ipc4_set_module_params] + Mod --> GetMod[ipc4_get_module_params] + Mod --> Bind[ipc4_bind] + Mod --> Unbind[ipc4_unbind] + end +``` + +## Processing Flows + +### Pipeline State Management (`ipc4_set_pipeline_state`) + +The core driver of graph execution in IPC4 is `ipc4_set_pipeline_state()`. This accepts a multi-stage request (e.g., `START`, `PAUSE`, `RESET`) and coordinates triggering the internal pipelines. + +1. **State Translation**: It maps the incoming IPC4 state request to an internal SOF state (e.g., `IPC4_PIPELINE_STATE_RUNNING` -> `COMP_TRIGGER_START`). +2. **Graph Traversal**: It fetches the pipeline object associated with the command and begins preparing it (`ipc4_pipeline_prepare`). +3. **Trigger Execution**: It executes `ipc4_pipeline_trigger()`, recursively changing states across the internal graphs and alerting either the LL scheduler or DP threads. + +```mermaid +sequenceDiagram + participant Host + participant IPC4Set as ipc4_set_pipeline_state + participant PPLPrep as ipc4_pipeline_prepare + participant PPLTrig as ipc4_pipeline_trigger + participant Comp as Graph Components + + Host->>IPC4Set: IPC4_PIPELINE_STATE_RUNNING + activate IPC4Set + + IPC4Set->>PPLPrep: Maps to COMP_TRIGGER_START + PPLPrep->>Comp: Applies PCM params & formatting + Comp-->>PPLPrep: Components ready + + IPC4Set->>PPLTrig: execute trigger + PPLTrig->>Comp: pipeline_trigger(COMP_TRIGGER_START) + Comp-->>PPLTrig: Success + + IPC4Set-->>Host: Reply: ipc4_send_reply() + deactivate IPC4Set +``` + +### Module Instantiation and Binding (`ipc4_bind`) + +In IPC4, modules (components) are bound together dynamically rather than constructed statically by the firmware at boot time. + +1. **Instantiation**: `ipc4_init_module_instance()` allocates the module via the DSP heap arrays based on UUIDs. +2. **Binding**: `ipc4_bind()` takes two module IDs and dynamically connects their sink and source pins using intermediate `comp_buffer` objects. + +```mermaid +sequenceDiagram + participant Host + participant IPC4Bind as ipc4_bind + participant SrcMod as Source Module + participant SinkMod as Sink Module + participant Buff as Connection Buffer + + Host->>IPC4Bind: Bind Src(ID) -> Sink(ID) + activate IPC4Bind + + IPC4Bind->>SrcMod: Locate by ID + IPC4Bind->>SinkMod: Locate by ID + + IPC4Bind->>Buff: buffer_new() (Create Intermediate Storage) + + IPC4Bind->>SrcMod: Bind source pin to Buff (via comp_bind/comp_buffer_connect) + IPC4Bind->>SinkMod: Bind sink pin to Buff (via comp_bind/comp_buffer_connect) + + IPC4Bind-->>Host: Reply: Linked + deactivate IPC4Bind +``` + +## Compound Messages (`ipc_wait_for_compound_msg`) + +To accelerate initialization, IPC4 enables Compound commands. A host can send multiple IPC messages chained back-to-back using a single mailbox trigger flag before waiting for ACKs. + +`ipc_compound_pre_start` and `ipc_compound_post_start` manage this batch execution safely without overflowing the Zephyr work queues or breaking hardware configurations during intermediate states. 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 <ievgen.ganakov@intel.com> + */ + +#include <ipc4/ams_helpers.h> +#include <sof/audio/component.h> + +#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 new file mode 100644 index 000000000000..9724e7578c99 --- /dev/null +++ b/src/ipc/ipc4/dai.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Author: Rander Wang <rander.wang@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/ipc-config.h> +#include <sof/common.h> +#include <rtos/idc.h> +#include <rtos/alloc.h> +#include <rtos/mutex.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc4/gateway.h> +#include <ipc/header.h> +#include <ipc4/alh.h> +#include <ipc4/ssp.h> +#include <ipc4/fw_reg.h> +#include <ipc/dai.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <sof/audio/module_adapter/module/generic.h> + +#include "../audio/copier/copier.h" +#include "../audio/copier/dai_copier.h" + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +/* Protects IPC4 LLP reading-slot firmware registers used by DAI code. */ +static SYS_MUTEX_DEFINE(llp_reading_slots_lock); + +void dai_set_link_hda_config(uint16_t *link_config, + struct ipc_config_dai *common_config, + const void *spec_config) +{ +#if ACE_VERSION > ACE_VERSION_1_5 + const struct ipc4_audio_format *gtw_fmt = common_config->gtw_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[0]->stream_id; + break; + case SOF_DAI_INTEL_DMIC: + link_cfg.full = 0; + if (gtw_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 = (gtw_fmt->channels_count - 1) / 2; + } else { + link_cfg.part.hchan = gtw_fmt->channels_count - 1; + } + link_cfg.part.stream = common_config->host_dma_config[0]->stream_id; + break; + case SOF_DAI_INTEL_UAOL: + link_cfg.full = 0; + link_cfg.part.hchan = gtw_fmt->channels_count - 1; + link_cfg.part.dir = common_config->direction; + link_cfg.part.stream = common_config->host_dma_config[0]->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 ipc_config_dai *dai = &dd->ipc_config; + int channel; + + switch (dai->type) { + case SOF_DAI_INTEL_SSP: + COMPILER_FALLTHROUGH; + case SOF_DAI_INTEL_DMIC: + channel = 0; +#if ACE_VERSION > ACE_VERSION_1_5 + if (dai->host_dma_config[0]->pre_allocated_by_host) + channel = dai->host_dma_config[0]->dma_channel_id; +#endif + break; + case SOF_DAI_INTEL_HDA: +#if ACE_VERSION > ACE_VERSION_1_5 + if (copier_cfg->gtw_cfg.node_id.f.dma_type == ipc4_alh_link_output_class || + copier_cfg->gtw_cfg.node_id.f.dma_type == ipc4_alh_link_input_class) { + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + + channel = SOF_DMA_CHAN_INVALID; + const struct sof_alh_configuration_blob *alh_blob = + (void *)cd->config.gtw_cfg.config_data; + + for (int i = 0; i < alh_blob->alh_cfg.count; i++) { + if (dai->host_dma_config[i]->stream_id == dai->dai_index) { + channel = dai->host_dma_config[i]->dma_channel_id; + break; + } + } + break; + } +#endif /* ACE_VERSION > ACE_VERSION_1_5 */ + channel = copier_cfg->gtw_cfg.node_id.f.v_index; + break; + case SOF_DAI_INTEL_ALH: + /* As with HDA, the DMA channel is assigned in runtime, + * not during topology parsing. + */ + channel = 0; + break; +#if ACE_VERSION > ACE_VERSION_1_5 + case SOF_DAI_INTEL_UAOL: + channel = 0; + if (dai->host_dma_config[0]->pre_allocated_by_host) + channel = dai->host_dma_config[0]->dma_channel_id; + break; +#endif + default: + /* other types of DAIs not handled for now */ + comp_err(dev, "Unknown dai type %d", dai->type); + channel = SOF_DMA_CHAN_INVALID; + break; + } + + return channel; +} + +int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *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; + + if (!dai) { + comp_err(dev, "no dai!\n"); + return -EINVAL; + } + + comp_dbg(dev, "dai_data_config() dai type = %d index = %d dd %p", + dai->type, dai->dai_index, dd); + + /* cannot configure DAI while active */ + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state."); + return 0; + } + + switch (dai->type) { + case SOF_DAI_INTEL_SSP: + /* set dma burst elems to slot number */ + dd->config.burst_elems = copier_cfg->base.audio_fmt.channels_count; + break; + case SOF_DAI_INTEL_DMIC: + /* Depth is passed by DMIC driver that retrieves it from blob */ + dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); + comp_dbg(dev, "dai_data_config() burst_elems = %d", dd->config.burst_elems); + break; + case SOF_DAI_INTEL_HDA: + break; + case SOF_DAI_INTEL_ALH: + dd->stream_id = dai_get_stream_id(dai_p, dai->direction); + /* SDW HW FIFO always requires 32bit MSB aligned sample data for + * all formats, such as 8/16/24/32 bits. + */ + dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; + + dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); + + comp_dbg(dev, "dai_data_config() SOF_DAI_INTEL_ALH dev->ipc_config.frame_fmt: %d, stream_id: %d", + dev->ipc_config.frame_fmt, dd->stream_id); + + break; + case SOF_DAI_INTEL_UAOL: + break; + default: + /* other types of DAIs not handled for now */ + comp_warn(dev, "Unknown dai type %d", dai->type); + return -EINVAL; + } + + dai->dma_buffer_size = copier_cfg->gtw_cfg.dma_buffer_size; + + /* some DAIs may not need extra config */ + return 0; +} + +/* dai config is not sent by ipc message */ +int ipc_comp_dai_config(struct ipc *ipc, struct ipc_config_dai *common_config, + void *spec_config) +{ + return 0; +} + +void dai_dma_release(struct dai_data *dd, struct comp_dev *dev) +{ + int ret; + + /* cannot configure DAI while active */ + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state. Ignore resetting"); + return; + } + + /* put the allocated DMA channel first */ + if (dd->chan_index >= 0) { + struct ipc4_llp_reading_slot slot; + + if (dd->slot_info.node_id) { + /* reset llp position to 0 in memory window for reset state. */ + memset_s(&slot, sizeof(slot), 0, sizeof(slot)); + slot.node_id = dd->slot_info.node_id; + + ret = sys_mutex_lock(&llp_reading_slots_lock, K_FOREVER); + assert(!ret); + mailbox_sw_regs_write(dd->slot_info.reg_offset, &slot, sizeof(slot)); + ret = sys_mutex_unlock(&llp_reading_slots_lock); + assert(!ret); + } + + /* The stop sequnece of host driver is first pause and then reset + * dma is released for reset state and need to change dma state from + * pause to stop. + * TODO: refine power management when stream is paused + */ + /* if reset is after pause dma has already been stopped */ + dma_stop(dd->dma->z_dev, dd->chan_index); + + dma_release_channel(dd->dma->z_dev, dd->chan_index); + dd->chan_index = -EINVAL; + } +} + +void dai_release_llp_slot(struct dai_data *dd) +{ + struct ipc4_llp_reading_slot slot; + int ret; + + if (!dd->slot_info.node_id) + return; + + memset_s(&slot, sizeof(slot), 0, sizeof(slot)); + + /* clear node id for released llp slot */ + ret = sys_mutex_lock(&llp_reading_slots_lock, K_FOREVER); + assert(!ret); + mailbox_sw_regs_write(dd->slot_info.reg_offset, &slot, sizeof(slot)); + ret = sys_mutex_unlock(&llp_reading_slots_lock); + assert(!ret); + + dd->slot_info.reg_offset = 0; + dd->slot_info.node_id = 0; +} + +static int dai_get_unused_llp_slot(struct comp_dev *dev, + union ipc4_connector_node_id *node) +{ + struct ipc4_llp_reading_slot slot; + uint32_t max_slot; + uint32_t offset; + int ret; + int i; + + /* sdw with multiple gateways uses sndw_reading_slots */ + if (node->f.dma_type == ipc4_alh_link_output_class && is_multi_gateway(*node)) { + offset = SRAM_REG_LLP_SNDW_READING_SLOTS; + max_slot = IPC4_MAX_LLP_SNDW_READING_SLOTS - 1; + } else { + offset = SRAM_REG_LLP_GPDMA_READING_SLOTS; + max_slot = IPC4_MAX_LLP_GPDMA_READING_SLOTS; + } + + ret = sys_mutex_lock(&llp_reading_slots_lock, K_FOREVER); + assert(!ret); + + /* find unused llp slot offset with node_id of zero */ + for (i = 0; i < max_slot; i++, offset += sizeof(slot)) { + uint32_t node_id; + + node_id = mailbox_sw_reg_read(offset); + if (!node_id) + break; + } + + if (i >= max_slot) { + comp_err(dev, "can't find free slot"); + ret = sys_mutex_unlock(&llp_reading_slots_lock); + assert(!ret); + return -EINVAL; + } + + memset_s(&slot, sizeof(slot), 0, sizeof(slot)); + slot.node_id = node->dw & IPC4_NODE_ID_MASK; + mailbox_sw_regs_write(offset, &slot, sizeof(slot)); + + ret = sys_mutex_unlock(&llp_reading_slots_lock); + assert(!ret); + + return offset; +} + +static int dai_init_llp_info(struct dai_data *dd, struct comp_dev *dev) +{ + struct ipc4_copier_module_cfg *copier_cfg; + union ipc4_connector_node_id node; + int ret; + + copier_cfg = dd->dai_spec_config; + node = copier_cfg->gtw_cfg.node_id; + + /* HDA doesn't use llp slot */ + if (dd->ipc_config.type == SOF_DAI_INTEL_HDA) + return 0; + + /* don't support more gateway like EVAD */ + if (node.f.dma_type >= ipc4_max_connector_node_id_type) { + comp_err(dev, "unsupported gateway %d", (int)node.f.dma_type); + return -EINVAL; + } + + ret = dai_get_unused_llp_slot(dev, &node); + if (ret < 0) + return ret; + + dd->slot_info.node_id = node.dw & IPC4_NODE_ID_MASK; + dd->slot_info.reg_offset = ret; + + return 0; +} + +__cold 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; + int size; + int ret; + + assert_can_be_cold(); + + /* ignore if message not for this DAI id/type */ + if (dd->ipc_config.dai_index != common_config->dai_index || + dd->ipc_config.type != common_config->type) + return 0; + + comp_info(dev, "dai type = %d index = %d dd %p", + common_config->type, common_config->dai_index, dd); + + /* cannot configure DAI while active */ + if (dev->state == COMP_STATE_ACTIVE) { + comp_info(dev, "Component is in active state. Ignore config"); + return 0; + } + + if (dd->chan_index >= 0) { + comp_info(dev, "Configured. dma channel index %d, ignore...", + dd->chan_index); + return 0; + } + +#if CONFIG_COMP_DAI_GROUP + if (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(dd, dev, spec_config) == SOF_DMA_CHAN_INVALID) + return 0; + + dd->dai_dev = dev; + + /* allocated dai_config if not yet */ + if (!dd->dai_spec_config) { + size = sizeof(*copier_cfg); + dd->dai_spec_config = rzalloc(SOF_MEM_FLAG_USER, size); + if (!dd->dai_spec_config) { + comp_err(dev, "No memory for size %d", size); + return -ENOMEM; + } + + ret = memcpy_s(dd->dai_spec_config, size, copier_cfg, size); + if (ret < 0) { + rfree(dd->dai_spec_config); + dd->dai_spec_config = NULL; + return -EINVAL; + } + } + + ret = dai_init_llp_info(dd, dev); + if (ret < 0) + return ret; + + /* gtw_cfg.config_length is in words */ + size = copier_cfg->gtw_cfg.config_length << 2; + + return dai_set_config(dd->dai, common_config, + copier_cfg->gtw_cfg.config_data, size); +} + +int dai_common_position(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) +{ + struct dma_status status; + int ret; + + /* total processed bytes count */ + posn->dai_posn = dd->total_data_processed; + + platform_dai_wallclock(dev, &dd->wallclock); + posn->wallclock = dd->wallclock; + + ret = dma_get_status(dd->dma->z_dev, dd->chan_index, &status); + if (ret < 0) + return ret; + + posn->comp_posn = status.total_copied; + + return 0; +} + +int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_common_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; + + if (!dd->slot_info.node_id) + return; + + ret = dma_get_status(dd->dma->z_dev, dd->chan_index, &status); + if (ret < 0) + return; + + platform_dai_wallclock(dev, &dd->wallclock); + + slot.node_id = dd->slot_info.node_id; + slot.reading.llp_l = (uint32_t)status.total_copied; + slot.reading.llp_u = (uint32_t)(status.total_copied >> 32); + slot.reading.wclk_l = (uint32_t)dd->wallclock; + slot.reading.wclk_u = (uint32_t)(dd->wallclock >> 32); + + mailbox_sw_regs_write(dd->slot_info.reg_offset, &slot, sizeof(slot)); +} diff --git a/src/ipc/ipc4/handler-kernel.c b/src/ipc/ipc4/handler-kernel.c new file mode 100644 index 000000000000..ae75ebc87303 --- /dev/null +++ b/src/ipc/ipc4/handler-kernel.c @@ -0,0 +1,666 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Author: Rander Wang <rander.wang@linux.intel.com> +/* + * IPC (InterProcessor Communication) provides a method of two way + * communication between the host processor and the DSP. The IPC used here + * utilises a shared mailbox and door bell between the host and DSP. + * + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/boot_test.h> +#include <sof/common.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/pm_runtime.h> +#include <sof/llext_manager.h> +#include <sof/math/numbers.h> +#include <sof/tlv.h> +#include <sof/trace/trace.h> +#include <ipc4/error_status.h> +#include <ipc/header.h> +#include <ipc4/module.h> +#include <ipc4/pipeline.h> +#include <ipc4/notification.h> +#include <ipc4/handler.h> +#include <ipc/trace.h> +#include <user/trace.h> + +#include <rtos/atomic.h> +#include <rtos/kernel.h> +#include <rtos/string.h> +#include <sof/lib_manager.h> + +#if CONFIG_SOF_BOOT_TEST +/* CONFIG_SOF_BOOT_TEST depends on Zephyr */ +#include <zephyr/ztest.h> +#endif + +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include "../audio/copier/ipcgtw_copier.h" + +/* 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 { + struct ipc_cmd_hdr msg_in; /* local copy of current message from host header */ + struct ipc_cmd_hdr msg_out; /* local copy of current message to host header */ + atomic_t delayed_reply; + uint32_t delayed_error; +}; + +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 = {0, 0, 0, 0, LIST_INIT(msg_reply.list)}; + +static struct ipc_msg msg_notify = {0, 0, 0, 0, LIST_INIT(msg_notify.list)}; + +#if CONFIG_LIBRARY +static inline struct ipc4_message_request *ipc4_get_message_request(void) +{ + struct ipc *ipc = ipc_get(); + + return (struct ipc4_message_request *)ipc->comp_data; +} + +static inline void ipc4_send_reply(struct ipc4_message_reply *reply) +{ + struct ipc *ipc = ipc_get(); + int ret; + + /* copy the extension from the message reply */ + reply->extension.dat = msg_reply.extension; + ret = memcpy_s(ipc->comp_data, sizeof(*reply), reply, sizeof(*reply)); + assert(!ret); +} +#else +static inline struct ipc4_message_request *ipc4_get_message_request(void) +{ + /* ignoring _hdr as it does not contain valid data in IPC4/IDC case */ + return ipc_from_hdr(&msg_data.msg_in); +} + +static inline void ipc4_send_reply(struct ipc4_message_reply *reply) +{ + struct ipc *ipc = ipc_get(); + char *data = ipc->comp_data; + + ipc_msg_send(&msg_reply, data, true); +} + +#endif + +__cold static bool is_any_ppl_active(void) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + + assert_can_be_cold(); + + list_for_item(clist, &ipc_get()->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_PIPELINE) + continue; + + if (icd->pipeline->status == COMP_STATE_ACTIVE) + return true; + } + + return false; +} + +void ipc_compound_pre_start(int msg_id) +{ + /* ipc thread will wait for all scheduled tasks to be complete + * Use a reference count to check status of these tasks. + */ + atomic_add(&msg_data.delayed_reply, 1); +} + +void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed) +{ + if (ret) { + ipc_cmd_err(&ipc_tr, "failed to process msg %d status %d", msg_id, ret); + atomic_set(&msg_data.delayed_reply, 0); + return; + } + + /* decrease counter if it is not scheduled by another thread */ + if (!delayed) + atomic_sub(&msg_data.delayed_reply, 1); +} + +void ipc_compound_msg_done(uint32_t msg_id, int error) +{ + if (!atomic_read(&msg_data.delayed_reply)) { + ipc_cmd_err(&ipc_tr, "unexpected delayed reply"); + return; + } + + atomic_sub(&msg_data.delayed_reply, 1); + + /* error reported in delayed pipeline task */ + if (error < 0) { + if (msg_id == SOF_IPC4_GLB_SET_PIPELINE_STATE) + msg_data.delayed_error = IPC4_PIPELINE_STATE_NOT_SET; + } +} + +#if CONFIG_LIBRARY +/* There is no parallel execution in testbench for scheduler and pipelines, so the result would + * be always IPC4_FAILURE. Therefore the compound messages handling is simplified. The pipeline + * triggers will require an explicit scheduler call to get the components to desired state. + */ +int ipc_wait_for_compound_msg(void) +{ + atomic_set(&msg_data.delayed_reply, 0); + return IPC4_SUCCESS; +} +#else +int ipc_wait_for_compound_msg(void) +{ + int try_count = 30; + + while (atomic_read(&msg_data.delayed_reply)) { + k_sleep(Z_TIMEOUT_US(250)); + + if (!try_count--) { + atomic_set(&msg_data.delayed_reply, 0); + ipc_cmd_err(&ipc_tr, "ipc4: failed to wait schedule thread"); + return IPC4_FAILURE; + } + } + + return IPC4_SUCCESS; +} +#endif + +#if CONFIG_LIBRARY_MANAGER +__cold static int ipc4_load_library(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_load_library library; + int ret; + + assert_can_be_cold(); + + library.header.dat = ipc4->primary.dat; + + ret = lib_manager_load_library(library.header.r.dma_id, library.header.r.lib_id, + ipc4->primary.r.type); + if (ret != 0) + return (ret == -EINVAL) ? IPC4_ERROR_INVALID_PARAM : IPC4_FAILURE; + + return IPC4_SUCCESS; +} +#endif + +static int ipc4_process_glb_message(struct ipc4_message_request *ipc4) +{ + uint32_t type; + int ret; + + type = ipc4->primary.r.type; + + switch (type) { + + /* Loads library (using Code Load or HD/A Host Output DMA) */ +#ifdef CONFIG_LIBRARY_MANAGER + case SOF_IPC4_GLB_LOAD_LIBRARY: + ret = ipc4_load_library(ipc4); + break; + case SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE: + ret = ipc4_load_library(ipc4); + break; +#endif + /* not a kernel level IPC message */ + default: + /* try and handle as a user IPC message */ + ret = ipc4_user_process_glb_message(ipc4, &msg_reply); + break; + } + + return ret; +} + +/* disable power gating on core 0 */ +__cold static int ipc4_module_process_d0ix(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_set_d0ix d0ix; + uint32_t module_id, instance_id; + + assert_can_be_cold(); + + int ret = memcpy_s(&d0ix, sizeof(d0ix), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + module_id = d0ix.primary.r.module_id; + instance_id = d0ix.primary.r.instance_id; + + tr_dbg(&ipc_tr, "%x : %x", module_id, instance_id); + + /* only module 0 can be used to set d0ix state */ + if (d0ix.primary.r.module_id || d0ix.primary.r.instance_id) { + ipc_cmd_err(&ipc_tr, "invalid resource id %x : %x", module_id, instance_id); + return IPC4_INVALID_RESOURCE_ID; + } + + if (d0ix.extension.r.prevent_power_gating) + pm_runtime_disable(PM_RUNTIME_DSP, PLATFORM_PRIMARY_CORE_ID); + else + pm_runtime_enable(PM_RUNTIME_DSP, PLATFORM_PRIMARY_CORE_ID); + + return 0; +} + +/* enable/disable cores according to the state mask */ +__cold static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_set_dx dx; + struct ipc4_dx_state_info dx_info; + uint32_t module_id, instance_id; + uint32_t core_id; + + assert_can_be_cold(); + + int ret = memcpy_s(&dx, sizeof(dx), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + module_id = dx.primary.r.module_id; + instance_id = dx.primary.r.instance_id; + + /* only module 0 can be used to set dx state */ + if (module_id || instance_id) { + ipc_cmd_err(&ipc_tr, "invalid resource id %x : %x", module_id, instance_id); + return IPC4_INVALID_RESOURCE_ID; + } + + dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, + sizeof(dx_info)); + ret = memcpy_s(&dx_info, sizeof(dx_info), + (const void *)MAILBOX_HOSTBOX_BASE, sizeof(dx_info)); + if (ret < 0) + return IPC4_FAILURE; + + /* check if core enable mask is valid */ + if (dx_info.core_mask > MASK(CONFIG_CORE_COUNT - 1, 0)) { + ipc_cmd_err(&ipc_tr, "CONFIG_CORE_COUNT: %d < core enable mask: %d", + CONFIG_CORE_COUNT, dx_info.core_mask); + return IPC4_ERROR_INVALID_PARAM; + } + + /* check primary core first */ + 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 */ + ipc_cmd_err(&ipc_tr, "Core0 is already active"); + return IPC4_BAD_STATE; + } + + /* Activate/deactivate requested cores */ + for (core_id = 1; core_id < CONFIG_CORE_COUNT; core_id++) { + if ((dx_info.core_mask & BIT(core_id)) == 0) + continue; + + if (dx_info.dx_mask & BIT(core_id)) { + ret = cpu_enable_core(core_id); + if (ret != 0) { + 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)) { + ipc_cmd_err(&ipc_tr, "failed to disable core %d", core_id); + return IPC4_FAILURE; + } + } + } + + /* Deactivating primary core if requested. */ + if (dx_info.core_mask & BIT(PLATFORM_PRIMARY_CORE_ID)) { + if (cpu_enabled_cores() & ~BIT(PLATFORM_PRIMARY_CORE_ID)) { + ipc_cmd_err(&ipc_tr, "secondary cores 0x%x still active", + cpu_enabled_cores()); + return IPC4_BUSY; + } + + if (is_any_ppl_active()) { + ipc_cmd_err(&ipc_tr, "some pipelines are still active"); + return IPC4_BUSY; + } + +#if !CONFIG_ADSP_IMR_CONTEXT_SAVE + ret = llext_manager_store_to_dram(); + if (ret < 0) + ipc_cmd_err(&ipc_tr, "Error %d saving LLEXT context. Resume might fail.", + ret); + +#if CONFIG_L3_HEAP + l3_heap_save(); +#endif +#endif + +#if defined(CONFIG_PM) + ipc_get()->task_mask |= IPC_TASK_POWERDOWN; +#endif + /* do platform specific suspending */ + platform_context_save(sof_get()); + +#if !defined(CONFIG_LIBRARY) && !defined(CONFIG_ZEPHYR_NATIVE_DRIVERS) + arch_irq_lock(); + platform_timer_stop(timer_get()); +#endif + ipc_get()->pm_prepare_D3 = 1; + } + + return IPC4_SUCCESS; +} + +__cold static int ipc4_process_module_message(struct ipc4_message_request *ipc4) +{ + uint32_t type; + int ret; + + assert_can_be_cold(); + + type = ipc4->primary.r.type; + + switch (type) { + case SOF_IPC4_MOD_SET_D0IX: + ret = ipc4_module_process_d0ix(ipc4); + break; + case SOF_IPC4_MOD_SET_DX: + ret = ipc4_module_process_dx(ipc4); + break; + default: + /* try and handle as a user IPC message */ + ret = ipc4_user_process_module_message(ipc4, &msg_reply); + break; + } + + return ret; +} + +__cold struct ipc_cmd_hdr *mailbox_validate(void) +{ + struct ipc_cmd_hdr *hdr = ipc_get()->comp_data; + + assert_can_be_cold(); + + return hdr; +} + +struct ipc_cmd_hdr *ipc_compact_read_msg(void) +{ + int words; + + words = ipc_platform_compact_read_msg(&msg_data.msg_in, 2); + if (!words) + return mailbox_validate(); + + return &msg_data.msg_in; +} + +struct ipc_cmd_hdr *ipc_prepare_to_send(const struct ipc_msg *msg) +{ + msg_data.msg_out.pri = msg->header; + msg_data.msg_out.ext = msg->extension; + + if (msg->tx_size) + mailbox_dspbox_write(0, (uint32_t *)msg->tx_data, msg->tx_size); + + return &msg_data.msg_out; +} + +__cold void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) +{ + assert_can_be_cold(); + + header->pri = SOF_IPC4_FW_READY; + header->ext = 0; +} + +#if defined(CONFIG_PM_DEVICE) && defined(CONFIG_INTEL_ADSP_IPC) +__cold void ipc_send_failed_power_transition_response(void) +{ + struct ipc4_message_request *request = ipc_from_hdr(&msg_data.msg_in); + struct ipc4_message_reply response; + + assert_can_be_cold(); + + response.primary.r.status = IPC4_POWER_TRANSITION_FAILED; + response.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; + response.primary.r.msg_tgt = request->primary.r.msg_tgt; + response.primary.r.type = request->primary.r.type; + + msg_reply.header = response.primary.dat; + list_init(&msg_reply.list); + + ipc_msg_send_direct(&msg_reply, NULL); +} +#endif /* defined(CONFIG_PM_DEVICE) && defined(CONFIG_INTEL_ADSP_IPC) */ + +__cold void ipc_send_panic_notification(void) +{ + assert_can_be_cold(); + + 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(struct ipc_msg *msg) +{ + struct ipc *ipc = ipc_get(); + k_spinlock_key_t key; + bool queued = false; + + key = k_spin_lock(&ipc->lock); + if (!list_is_empty(&msg->list)) + queued = true; + k_spin_unlock(&ipc->lock, key); + + return queued; +} + +/* Called from ipc_send_buffer_status_notify(), which is currently "hot" */ +void ipc_send_buffer_status_notify(void) +{ + /* a single msg_notify object is used */ + if (is_notification_queued(&msg_notify)) + return; + + msg_notify.header = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS); + msg_notify.extension = 0; + msg_notify.tx_size = 0; + + tr_dbg(&ipc_tr, "tx-notify\t: %#x|%#x", msg_notify.header, msg_notify.extension); + + ipc_msg_send(&msg_notify, NULL, true); +} +#endif + +void ipc_msg_reply(struct sof_ipc_reply *reply) +{ + struct ipc4_message_request in; + + in.primary.dat = msg_data.msg_in.pri; + ipc_compound_msg_done(in.primary.r.type, reply->error); +} + +void ipc_cmd(struct ipc_cmd_hdr *_hdr) +{ + struct ipc4_message_request *in = ipc4_get_message_request(); + enum ipc4_message_target target; +#ifdef CONFIG_DEBUG_IPC_TIMINGS + struct ipc4_message_request req; + uint64_t tstamp; +#endif + int err; + +#ifdef CONFIG_DEBUG_IPC_TIMINGS + req = *in; + tstamp = sof_cycle_get_64(); +#else + if (cpu_is_primary(cpu_get_id())) + tr_info(&ipc_tr, "rx\t: %#x|%#x", in->primary.dat, in->extension.dat); +#endif + /* no process on scheduled thread */ + atomic_set(&msg_data.delayed_reply, 0); + msg_data.delayed_error = 0; + msg_reply.tx_data = NULL; + msg_reply.tx_size = 0; + msg_reply.header = in->primary.dat; + msg_reply.extension = in->extension.dat; + + target = in->primary.r.msg_tgt; + + switch (target) { + case SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG: + err = ipc4_process_glb_message(in); + if (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) + 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 */ + ipc_cmd_err(&ipc_tr, "ipc4: invalid target %d", target); + err = IPC4_UNKNOWN_MESSAGE_TYPE; + } + + /* FW sends an ipc message to host if request bit is clear */ + if (in->primary.r.rsp == SOF_IPC4_MESSAGE_DIR_MSG_REQUEST) { + struct ipc *ipc = ipc_get(); + struct ipc4_message_reply reply = {{0}}; + + /* Process flow and time stamp for IPC4 msg processed on secondary core : + * core 0 (primary core) core x (secondary core) + * # IPC msg thread #IPC delayed worker #core x idc thread + * ipc_task_ops.run() + * ipc_do_cmd() + * msg_reply.header = in->primary.dat + * ipc4_process_on_core(x) + * mask |= SECONDARY_CORE + * idc_send_message() + * Case 1: + * // Ipc msg processed by secondary core idc_ipc() + * if ((mask & SECONDARY_CORE)) ipc_cmd() + * return; ipc_msg_send() + * mask &= ~SECONDARY_CORE + * + * ipc_platform_send_msg + * ---------------------------------------------------------------------------- + * Case 2: + * idc_ipc() + * ipc_cmd() + * //Prepare reply msg + * msg_reply.header = + * reply.primary.dat; + * ipc_msg_send() + * mask &= ~SECONDARY_CORE + * + * if ((mask & IPC_TASK_SECONDARY_CORE)) + * return; + * // Ipc reply msg was prepared, so return + * if (msg_reply.header != in->primary.dat) + * return; + * ipc_platform_send_msg + * ---------------------------------------------------------------------------- + * Case 3: + * idc_ipc() + * ipc_cmd() + * //Prepare reply msg + * msg_reply.header = + * reply.primary.dat; + * ipc_msg_send() + * mask &= ~SECONDARY_CORE + * + * ipc_platform_send_msg + * + * if ((mask & IPC_TASK_SECONDARY_CORE)) + * return; + * // Ipc reply msg was prepared, so return + * if (msg_reply.header != in->primary.dat) + * return; + */ + + /* Reply prepared by secondary core */ + if ((ipc->task_mask & IPC_TASK_SECONDARY_CORE) && cpu_is_primary(cpu_get_id())) + return; + /* Reply has been prepared by secondary core */ + if (msg_reply.header != in->primary.dat) + return; + + /* Do not send reply for SET_DX if we are going to enter D3 + * The reply is going to be sent as part of the power down + * sequence + */ + if (ipc->task_mask & IPC_TASK_POWERDOWN) + return; + + if (ipc_wait_for_compound_msg() != 0) { + ipc_cmd_err(&ipc_tr, "ipc4: failed to send delayed reply"); + err = IPC4_FAILURE; + } + + /* copy contents of message received */ + reply.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; + reply.primary.r.msg_tgt = in->primary.r.msg_tgt; + reply.primary.r.type = in->primary.r.type; + if (msg_data.delayed_error) + reply.primary.r.status = msg_data.delayed_error; + else + reply.primary.r.status = err; + + msg_reply.header = reply.primary.dat; + +#ifdef CONFIG_DEBUG_IPC_TIMINGS + tr_info(&ipc_tr, "tx-reply\t: %#x|%#x to %#x|%#x in %llu us", msg_reply.header, + msg_reply.extension, req.primary.dat, req.extension.dat, + k_cyc_to_us_near64(sof_cycle_get_64() - tstamp)); +#else + tr_dbg(&ipc_tr, "tx-reply\t: %#x|%#x", msg_reply.header, + msg_reply.extension); +#endif + ipc4_send_reply(&reply); + } +} diff --git a/src/ipc/ipc4/handler-user.c b/src/ipc/ipc4/handler-user.c new file mode 100644 index 000000000000..2bfa31babce0 --- /dev/null +++ b/src/ipc/ipc4/handler-user.c @@ -0,0 +1,1289 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Author: Rander Wang <rander.wang@linux.intel.com> +/* + * IPC (InterProcessor Communication) provides a method of two way + * communication between the host processor and the DSP. The IPC used here + * utilises a shared mailbox and door bell between the host and DSP. + * + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/pm_runtime.h> +#include <sof/llext_manager.h> +#include <sof/math/numbers.h> +#include <sof/tlv.h> +#include <sof/trace/trace.h> +#include <ipc4/error_status.h> +#include <ipc/header.h> +#include <ipc4/module.h> +#include <ipc4/pipeline.h> +#include <ipc4/notification.h> +#include <ipc4/handler.h> +#include <ipc/trace.h> +#include <user/trace.h> + +#include <rtos/atomic.h> +#include <rtos/kernel.h> +#include <sof/lib_manager.h> + +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include "../audio/copier/ipcgtw_copier.h" + +/* 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); + +/* Userspace message context, copied in/out by kernel IPC thread. */ +/* fw sends a fw ipc message to send the status of the last host ipc message */ +static struct ipc_msg *msg_reply; + +#if CONFIG_LIBRARY + +static inline const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data(void) +{ + const struct ipc4_pipeline_set_state_data *ppl_data; + struct ipc *ipc = ipc_get(); + + ppl_data = (const struct ipc4_pipeline_set_state_data *)ipc->comp_data; + + return ppl_data; +} +#else + +static inline const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data(void) +{ + const struct ipc4_pipeline_set_state_data *ppl_data; + + ppl_data = (const struct ipc4_pipeline_set_state_data *)MAILBOX_HOSTBOX_BASE; + dcache_invalidate_region((__sparse_force void __sparse_cache *)ppl_data, + sizeof(*ppl_data)); + + return ppl_data; +} +#endif +/* + * Global IPC Operations. + */ +__cold static int ipc4_new_pipeline(struct ipc4_message_request *ipc4) +{ + struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + + return ipc_pipeline_new(ipc, (ipc_pipe_new *)ipc4); +} + +__cold static int ipc4_delete_pipeline(struct ipc4_message_request *ipc4) +{ + struct ipc4_pipeline_delete *pipe; + struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + + pipe = (struct ipc4_pipeline_delete *)ipc4; + tr_dbg(&ipc_tr, "ipc4 delete pipeline %x:", (uint32_t)pipe->primary.r.instance_id); + + return ipc_pipeline_free(ipc, pipe->primary.r.instance_id); +} + +static int ipc4_pcm_params(struct ipc_comp_dev *pcm_dev) +{ + int err, reset_err; + + /* sanity check comp */ + if (!pcm_dev->cd->pipeline) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d pipeline not found", pcm_dev->id); + return -EINVAL; + } + + /* prepare pipeline audio params */ + err = pipeline_prepare(pcm_dev->cd->pipeline, pcm_dev->cd); + if (err < 0) { + 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; + } + + return 0; + +error: + reset_err = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); + if (reset_err < 0) + 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; +} + +static struct ipc_comp_dev *pipeline_get_host_dev(struct ipc_comp_dev *ppl_icd) +{ + struct ipc_comp_dev *host_dev; + struct ipc *ipc = ipc_get(); + int host_id; + + /* If the source component's direction is not set but the sink's direction is, + * this block will copy the direction from the sink to the source component and + * mark the source's direction as set. + */ + if (!ppl_icd->pipeline->source_comp->direction_set && + ppl_icd->pipeline->sink_comp->direction_set) { + ppl_icd->pipeline->source_comp->direction = + ppl_icd->pipeline->sink_comp->direction; + ppl_icd->pipeline->source_comp->direction_set = true; + } + + /* If the sink component's direction is not set but the source's direction is, + * this block will copy the direction from the source to the sink component and + * mark the sink's direction as set. + */ + if (!ppl_icd->pipeline->sink_comp->direction_set && + ppl_icd->pipeline->source_comp->direction_set) { + ppl_icd->pipeline->sink_comp->direction = + ppl_icd->pipeline->source_comp->direction; + ppl_icd->pipeline->sink_comp->direction_set = true; + } + + if (ppl_icd->pipeline->source_comp->direction == SOF_IPC_STREAM_PLAYBACK) + host_id = ppl_icd->pipeline->source_comp->ipc_config.id; + else + host_id = ppl_icd->pipeline->sink_comp->ipc_config.id; + + host_dev = ipc_get_comp_by_id(ipc, host_id); + if (!host_dev) + ipc_cmd_err(&ipc_tr, "comp host with ID %d not found", host_id); + + return host_dev; +} + +/* Ipc4 pipeline message <------> ipc3 pipeline message + * RUNNING <-------> TRIGGER START + * INIT + PAUSED <-------> PIPELINE COMPLETE + * INIT + RESET <-------> PIPELINE COMPLETE + * PAUSED <-------> TRIGGER_PAUSE + * RESET <-------> TRIGGER_STOP + RESET + * EOS(end of stream) <-------> NOT SUPPORTED YET + * + * IPC4 pipeline state machine + * + * INIT + * | \ + * | __\| + * | + * | RESET + * | _ _ + * | /| |\ + * | / /\ + * \|/ |/_ / \ + * RUNNING <--> PAUSE _ / \ + * / \ /|\ |\ / \ + * / \ | \/ \ + * / \ | /\ \ + * / \ | / \ \ + * |/_ _\| | / \ _\| + * ERROR Stop EOS |______\ SAVE + * / + */ + +int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd) +{ + struct ipc_comp_dev *host = NULL; + struct ipc *ipc = ipc_get(); + int status; + int ret = 0; + + status = ppl_icd->pipeline->status; + tr_dbg(&ipc_tr, "pipeline %d: initial state: %d, cmd: %d", ppl_icd->id, + status, cmd); + + switch (cmd) { + case SOF_IPC4_PIPELINE_STATE_RUNNING: + if (ppl_icd->pipeline->expect_eos) { + ipc_cmd_err(&ipc_tr, "pipeline %d: Can't transition from EOS to RUNNING", + ppl_icd->id); + return IPC4_INVALID_REQUEST; + } + + /* init params when pipeline is complete or reset */ + switch (status) { + case COMP_STATE_ACTIVE: + case COMP_STATE_PAUSED: + /* No action needed */ + break; + case COMP_STATE_READY: + host = pipeline_get_host_dev(ppl_icd); + if (!host) + return IPC4_INVALID_RESOURCE_ID; + + tr_dbg(&ipc_tr, "pipeline %d: set params", ppl_icd->id); + ret = ipc4_pcm_params(host); + break; + default: + ipc_cmd_err(&ipc_tr, + "pipeline %d: Invalid state for RUNNING: %d", + ppl_icd->id, status); + return IPC4_INVALID_REQUEST; + } + break; + case SOF_IPC4_PIPELINE_STATE_RESET: + switch (status) { + case COMP_STATE_INIT: + tr_dbg(&ipc_tr, "pipeline %d: reset from init", ppl_icd->id); + ret = ipc4_pipeline_complete(ipc, ppl_icd->id, cmd); + break; + case COMP_STATE_READY: + case COMP_STATE_ACTIVE: + case COMP_STATE_PAUSED: + /* No action needed */ + break; + default: + ipc_cmd_err(&ipc_tr, + "pipeline %d: Invalid state for RESET: %d", + ppl_icd->id, status); + return IPC4_INVALID_REQUEST; + } + + break; + case SOF_IPC4_PIPELINE_STATE_PAUSED: + switch (status) { + case COMP_STATE_INIT: + tr_dbg(&ipc_tr, "pipeline %d: pause from init", ppl_icd->id); + ret = ipc4_pipeline_complete(ipc, ppl_icd->id, cmd); + break; + default: + /* No action needed */ + break; + } + + break; + case SOF_IPC4_PIPELINE_STATE_EOS: + if (status != COMP_STATE_ACTIVE) { + ipc_cmd_err(&ipc_tr, "pipeline %d: Invalid state for EOS: %d", + ppl_icd->id, status); + return IPC4_INVALID_REQUEST; + } + ppl_icd->pipeline->expect_eos = true; + return 0; /* Must return here. Any other transition clears expect_eos. */ + /* special case - TODO */ + case SOF_IPC4_PIPELINE_STATE_SAVED: + case SOF_IPC4_PIPELINE_STATE_ERROR_STOP: + default: + ipc_cmd_err(&ipc_tr, "pipeline %d: unsupported trigger cmd: %d", + ppl_icd->id, cmd); + return IPC4_INVALID_REQUEST; + } + + if (ret < 0) + return IPC4_INVALID_REQUEST; + + ppl_icd->pipeline->expect_eos = false; + + return ret; +} + +int ipc4_pipeline_trigger(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *delayed) +{ + struct ipc_comp_dev *host; + int status; + int ret; + + status = ppl_icd->pipeline->status; + tr_dbg(&ipc_tr, "pipeline %d: initial state: %d, cmd: %d", ppl_icd->id, + status, cmd); + + if (status == COMP_STATE_INIT) + return 0; + + host = pipeline_get_host_dev(ppl_icd); + if (!host) + return IPC4_INVALID_RESOURCE_ID; + + switch (cmd) { + case SOF_IPC4_PIPELINE_STATE_RUNNING: + /* init params when pipeline is complete or reset */ + switch (status) { + case COMP_STATE_ACTIVE: + /* nothing to do if the pipeline is already running */ + return 0; + case COMP_STATE_READY: + case COMP_STATE_PREPARE: + cmd = COMP_TRIGGER_PRE_START; + break; + case COMP_STATE_PAUSED: + cmd = COMP_TRIGGER_PRE_RELEASE; + break; + default: + ipc_cmd_err(&ipc_tr, + "pipeline %d: Invalid state for RUNNING: %d", + ppl_icd->id, status); + return IPC4_INVALID_REQUEST; + } + break; + case SOF_IPC4_PIPELINE_STATE_RESET: + switch (status) { + case COMP_STATE_ACTIVE: + case COMP_STATE_PAUSED: + cmd = COMP_TRIGGER_STOP; + break; + default: + return 0; + } + break; + case SOF_IPC4_PIPELINE_STATE_PAUSED: + switch (status) { + case COMP_STATE_INIT: + case COMP_STATE_READY: + case COMP_STATE_PAUSED: + return 0; + default: + cmd = COMP_TRIGGER_PAUSE; + break; + } + + break; + case SOF_IPC4_PIPELINE_STATE_EOS: + /* EOS handled in ipc4_pipeline_prepare */ + return 0; + default: + ipc_cmd_err(&ipc_tr, "pipeline %d: unsupported trigger cmd: %d", + ppl_icd->id, cmd); + return IPC4_INVALID_REQUEST; + } + + /* + * We're handling a pipeline-trigger event, this means that we're in a + * performance-critical context. Set a marker, so that if any cold code, + * calling assert_can_be_cold() is called on this flow between the + * mem_hot_path_start_watching() - mem_hot_path_stop_watching() + * brackets, the latter will generate an error / trigger a panic. + */ + dbg_path_hot_confirm(); + + /* trigger the component */ + ret = pipeline_trigger(host->cd->pipeline, host->cd, cmd); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "pipeline %d: trigger cmd %d failed with: %d", + ppl_icd->id, cmd, ret); + ret = IPC4_PIPELINE_STATE_NOT_SET; + } else if (ret == PPL_STATUS_SCHEDULED) { + tr_dbg(&ipc_tr, "pipeline %d: trigger cmd %d is delayed", + ppl_icd->id, cmd); + *delayed = true; + ret = 0; + } else if (cmd == COMP_TRIGGER_STOP) { + /* + * reset the pipeline components if STOP trigger is executed in + * the same thread. + * Otherwise, the pipeline will be reset after the STOP trigger + * has finished executing in the pipeline task. + */ + ret = pipeline_reset(host->cd->pipeline, host->cd); + if (ret < 0) + ret = IPC4_INVALID_REQUEST; + } + + return ret; +} + +__cold const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data_wrapper(void) +{ + assert_can_be_cold(); + + return ipc4_get_pipeline_data(); +} + +/* Entry point for ipc4_pipeline_trigger(), therefore cannot be cold */ +static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4) +{ + const struct ipc4_pipeline_set_state_data *ppl_data; + struct ipc4_pipeline_set_state state; + struct ipc_comp_dev *ppl_icd; + struct ipc *ipc = ipc_get(); + uint32_t cmd, ppl_count; + uint32_t id = 0; + const uint32_t *ppl_id; + bool use_idc = false; + uint32_t idx; + int ret = 0; + int i; + + state.primary.dat = ipc4->primary.dat; + state.extension.dat = ipc4->extension.dat; + cmd = state.primary.r.ppl_state; + ppl_data = ipc4_get_pipeline_data(); + + if (state.extension.r.multi_ppl) { + ppl_count = ppl_data->pipelines_count; + ppl_id = ppl_data->ppl_id; + dcache_invalidate_region((__sparse_force void __sparse_cache *)ppl_id, + sizeof(int) * ppl_count); + } else { + ppl_count = 1; + id = state.primary.r.ppl_id; + ppl_id = &id; + } + + for (i = 0; i < ppl_count; i++) { + ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, + ppl_id[i], IPC_COMP_IGNORE_REMOTE); + if (!ppl_icd) { + tr_err(&ipc_tr, "ipc: comp %d not found", ppl_id[i]); + return IPC4_INVALID_RESOURCE_ID; + } + + if (i) { + if (ppl_icd->core != idx) + use_idc = true; + } else { + idx = ppl_icd->core; + } + } + + /* Run the prepare phase on the pipelines */ + for (i = 0; i < ppl_count; i++) { + ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, + ppl_id[i], IPC_COMP_IGNORE_REMOTE); + if (!ppl_icd) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", ppl_id[i]); + return IPC4_INVALID_RESOURCE_ID; + } + + /* Pass IPC to target core + * or use idc if more than one core used + */ + if (!cpu_is_me(ppl_icd->core)) { + if (use_idc) { + struct idc_msg msg = { IDC_MSG_PPL_STATE, + IDC_MSG_PPL_STATE_EXT(ppl_id[i], + IDC_PPL_STATE_PHASE_PREPARE), + ppl_icd->core, + sizeof(cmd), &cmd, }; + + ret = idc_send_msg(&msg, IDC_BLOCKING); + } else { + return ipc4_process_on_core(ppl_icd->core, false); + } + } else { + ret = ipc4_pipeline_prepare(ppl_icd, cmd); + } + + if (ret != 0) + return ret; + } + + /* Run the trigger phase on the pipelines */ + for (i = 0; i < ppl_count; i++) { + bool delayed = false; + + ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, + ppl_id[i], IPC_COMP_IGNORE_REMOTE); + if (!ppl_icd) { + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", ppl_id[i]); + return IPC4_INVALID_RESOURCE_ID; + } + + /* Pass IPC to target core + * or use idc if more than one core used + */ + if (!cpu_is_me(ppl_icd->core)) { + if (use_idc) { + struct idc_msg msg = { IDC_MSG_PPL_STATE, + IDC_MSG_PPL_STATE_EXT(ppl_id[i], + IDC_PPL_STATE_PHASE_TRIGGER), + ppl_icd->core, + sizeof(cmd), &cmd, }; + + ret = idc_send_msg(&msg, IDC_BLOCKING); + } else { + return ipc4_process_on_core(ppl_icd->core, false); + } + } else { + ipc_compound_pre_start(state.primary.r.type); + ret = ipc4_pipeline_trigger(ppl_icd, cmd, &delayed); + ipc_compound_post_start(state.primary.r.type, ret, delayed); + if (delayed) { + /* To maintain pipeline order for triggers, we must + * do a blocking wait until trigger is processed. + * This will add a max delay of 'ppl_count' LL ticks + * to process the full trigger list. + */ + if (ipc_wait_for_compound_msg() != 0) { + ipc_cmd_err(&ipc_tr, "ipc4: fail with delayed trigger"); + return IPC4_FAILURE; + } + } + } + + if (ret != 0) + return ret; + } + + return ret; +} + +__cold static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4) +{ + assert_can_be_cold(); + +#if CONFIG_COMP_CHAIN_DMA + struct ipc_comp_dev *cdma_comp; + struct ipc *ipc = ipc_get(); + struct ipc4_chain_dma cdma; + int comp_id; + int ret; + + ret = memcpy_s(&cdma, sizeof(cdma), ipc4, sizeof(*ipc4)); + if (ret < 0) + return IPC4_FAILURE; + + comp_id = IPC4_COMP_ID(cdma.primary.r.host_dma_id + IPC4_MAX_MODULE_COUNT, 0); + cdma_comp = ipc_get_comp_by_id(ipc, comp_id); + + if (!cdma_comp) { + /* + * Nothing to do when the chainDMA is not allocated and asked to + * be freed + */ + if (!cdma.primary.r.allocate && !cdma.primary.r.enable) + return IPC4_SUCCESS; + + ret = ipc4_chain_manager_create(&cdma); + if (ret < 0) + return IPC4_FAILURE; + + cdma_comp = ipc_get_comp_by_id(ipc, comp_id); + if (!cdma_comp) { + return IPC4_FAILURE; + } + + ret = ipc4_chain_dma_state(cdma_comp->cd, &cdma); + if (ret < 0) { + comp_free(cdma_comp->cd); + return IPC4_FAILURE; + } + + return IPC4_SUCCESS; + } + + ret = ipc4_chain_dma_state(cdma_comp->cd, &cdma); + if (ret < 0) + return IPC4_INVALID_CHAIN_STATE_TRANSITION; + + if (!cdma.primary.r.allocate && !cdma.primary.r.enable) + list_item_del(&cdma_comp->list); + + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +__cold static int ipc4_process_ipcgtw_cmd(struct ipc4_message_request *ipc4) +{ + assert_can_be_cold(); + +#if CONFIG_IPC4_GATEWAY + struct ipc *ipc = ipc_get(); + uint32_t reply_size = 0; + int err; + + 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; + + if (reply_size > 0) { + msg_reply->tx_data = ipc->comp_data; + msg_reply->tx_size = reply_size; + } + + return err < 0 ? IPC4_FAILURE : IPC4_SUCCESS; +#else + ipc_cmd_err(&ipc_tr, "CONFIG_IPC4_GATEWAY is disabled"); + return IPC4_UNAVAILABLE; +#endif +} + +static int ipc_glb_gdb_debug(struct ipc4_message_request *ipc4) +{ +#if CONFIG_GDBSTUB + ipc_enter_gdb = true; + return IPC4_SUCCESS; +#else + return IPC4_UNAVAILABLE; +#endif +} + +int ipc4_user_process_glb_message(struct ipc4_message_request *ipc4, + struct ipc_msg *reply) +{ + uint32_t type; + int ret; + + type = ipc4->primary.r.type; + msg_reply = reply; + + switch (type) { + case SOF_IPC4_GLB_BOOT_CONFIG: + case SOF_IPC4_GLB_ROM_CONTROL: + case SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD: + case SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES: + case SOF_IPC4_GLB_UNLOAD_MULTIPLE_MODULES: + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); + ret = IPC4_UNAVAILABLE; + break; + + case SOF_IPC4_GLB_CHAIN_DMA: + ret = ipc4_process_chain_dma(ipc4); + break; + + /* pipeline settings */ + case SOF_IPC4_GLB_CREATE_PIPELINE: + ret = ipc4_new_pipeline(ipc4); + break; + case SOF_IPC4_GLB_DELETE_PIPELINE: + ret = ipc4_delete_pipeline(ipc4); + break; + case SOF_IPC4_GLB_SET_PIPELINE_STATE: + ret = ipc4_set_pipeline_state(ipc4); + break; + + case SOF_IPC4_GLB_GET_PIPELINE_STATE: + case SOF_IPC4_GLB_GET_PIPELINE_CONTEXT_SIZE: + case SOF_IPC4_GLB_SAVE_PIPELINE: + case SOF_IPC4_GLB_RESTORE_PIPELINE: + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); + ret = IPC4_UNAVAILABLE; + break; + + case SOF_IPC4_GLB_INTERNAL_MESSAGE: + 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: + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); + ret = IPC4_UNAVAILABLE; + break; + + case SOF_IPC4_GLB_IPCGATEWAY_CMD: + ret = ipc4_process_ipcgtw_cmd(ipc4); + break; + + case SOF_IPC4_GLB_ENTER_GDB: + ret = ipc_glb_gdb_debug(ipc4); + break; + + default: + ipc_cmd_err(&ipc_tr, "unsupported ipc message type %d", type); + ret = IPC4_UNAVAILABLE; + break; + } + + return ret; +} + +/* + * Ipc4 Module message <------> ipc3 module message + * init module <-------> create component + * bind modules <-------> connect components + * module set_large_config <-------> component cmd + * delete module <-------> free component + */ + +__cold static int ipc4_init_module_instance(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_init_instance module_init; + struct comp_dev *dev; + + assert_can_be_cold(); + + /* we only need the common header here, all we have from the IPC */ + int ret = memcpy_s(&module_init, sizeof(module_init), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + tr_dbg(&ipc_tr, + "%x : %x", + (uint32_t)module_init.primary.r.module_id, + (uint32_t)module_init.primary.r.instance_id); + + /* Pass IPC to target core */ + if (!cpu_is_me(module_init.extension.r.core_id)) + return ipc4_process_on_core(module_init.extension.r.core_id, false); + + dev = comp_new_ipc4(&module_init); + if (!dev) { + 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; + } + + return 0; +} + +__cold static int ipc4_bind_module_instance(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_bind_unbind bu; + struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + + int ret = memcpy_s(&bu, sizeof(bu), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + tr_dbg(&ipc_tr, "%x : %x with %x : %x", + (uint32_t)bu.primary.r.module_id, (uint32_t)bu.primary.r.instance_id, + (uint32_t)bu.extension.r.dst_module_id, (uint32_t)bu.extension.r.dst_instance_id); + + return ipc_comp_connect(ipc, (ipc_pipe_comp_connect *)&bu); +} + +__cold static int ipc4_unbind_module_instance(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_bind_unbind bu; + struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + + int ret = memcpy_s(&bu, sizeof(bu), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + tr_dbg(&ipc_tr, "%x : %x with %x : %x", + (uint32_t)bu.primary.r.module_id, (uint32_t)bu.primary.r.instance_id, + (uint32_t)bu.extension.r.dst_module_id, (uint32_t)bu.extension.r.dst_instance_id); + + return ipc_comp_disconnect(ipc, (ipc_pipe_comp_connect *)&bu); +} + +static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4, bool set) +{ + struct ipc4_module_config *config = (struct ipc4_module_config *)ipc4; + int (*function)(struct comp_dev *dev, uint32_t type, void *value); + const struct comp_driver *drv; + struct comp_dev *dev = NULL; + int ret; + + tr_dbg(&ipc_tr, "%x : %x, set %d", + (uint32_t)config->primary.r.module_id, (uint32_t)config->primary.r.instance_id, + !!set); + + /* get component dev for non-basefw since there is no component dev for basefw */ + if (config->primary.r.module_id) { + uint32_t comp_id; + + comp_id = IPC4_COMP_ID(config->primary.r.module_id, config->primary.r.instance_id); + dev = ipc4_get_comp_dev(comp_id); + if (!dev) + return IPC4_MOD_INVALID_ID; + + drv = dev->drv; + + /* Pass IPC to target core */ + if (!cpu_is_me(dev->ipc_config.core)) + return ipc4_process_on_core(dev->ipc_config.core, false); + } else { + drv = ipc4_get_comp_drv(config->primary.r.module_id); + } + + if (!drv) + return IPC4_MOD_INVALID_ID; + + function = set ? drv->ops.set_attribute : drv->ops.get_attribute; + if (!function) + return IPC4_INVALID_REQUEST; + + ret = function(dev, COMP_ATTR_IPC4_CONFIG, &config->extension.dat); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "%x : %x failed %d, set %u, param %x", + (uint32_t)config->primary.r.module_id, + (uint32_t)config->primary.r.instance_id, ret, !!set, + (uint32_t)config->extension.dat); + ret = IPC4_INVALID_CONFIG_PARAM_ID; + } + + if (!set) + msg_reply->extension = config->extension.dat; + + return ret; +} + +__cold static void ipc4_prepare_for_kcontrol_get(struct comp_dev *dev, uint8_t param_id, + char *data_out, uint32_t data_size) +{ + const char *hostbox; + +#if CONFIG_LIBRARY + hostbox = (const char *)ipc_get()->comp_data + sizeof(struct ipc4_module_large_config); +#else + hostbox = (const char *)MAILBOX_HOSTBOX_BASE; +#endif + + assert_can_be_cold(); + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + case SOF_IPC4_BYTES_CONTROL_PARAM_ID: + /* We have payload in hostbox */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, + data_size); + + /* Copy the control payload header from inbox to outbox */ + memcpy_s(data_out, data_size, hostbox, + sizeof(struct sof_ipc4_control_msg_payload)); + break; + default: + break; + } +} + +__cold static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, + const struct comp_driver *drv, + bool init_block, + bool final_block, + uint32_t *data_off_size, + char *data_out, + const char *data_in) +{ + const struct sof_tl * const input_tl = (struct sof_tl *)data_in; + int ret; + struct ipc4_vendor_error *error; + + assert_can_be_cold(); + + if (init_block && final_block) { + /* we use data_off_size as in/out, + * save value to new variable so it can be used as out size + */ + const int tl_count = *data_off_size / sizeof(struct sof_tl); + size_t produced_data = 0; + + for (int i = 0; i < tl_count; i++) { + /* we go to next output tlv with each iteration */ + uint32_t data_off_size_local; + struct sof_tlv *output_tlv = (struct sof_tlv *)(data_out + produced_data); + + if (produced_data + input_tl[i].max_length > MAILBOX_DSPBOX_SIZE) { + tr_err(&ipc_tr, "error: response payload bigger than DSPBOX size"); + return IPC4_FAILURE; + } + + /* local size is in/out: max msg len goes in, msg len goes out */ + data_off_size_local = input_tl[i].max_length; + ret = drv->ops.get_large_config(dev, input_tl[i].type, + true, + true, + &data_off_size_local, output_tlv->value); + if (ret) { + /* This is how the reference firmware handled error here. Currently + * no memory is allocated for output in case of error, + * so this may be obsolete. + */ + error = (struct ipc4_vendor_error *)data_out; + error->param_idx = input_tl[i].type; + error->err_code = IPC4_FAILURE; + *data_off_size = sizeof(*error); + ipc_cmd_err(&ipc_tr, "error: get_large_config returned %d", ret); + return IPC4_FAILURE; + } + + /* update header */ + output_tlv->type = input_tl[i].type; + output_tlv->length = data_off_size_local; + produced_data += data_off_size_local + sizeof(*output_tlv); + } + *data_off_size = produced_data; + } else { + char *output_buffer; + struct sof_tlv *tl_header; + + if (init_block) { + *data_off_size = input_tl->max_length; + output_buffer = data_out + sizeof(*tl_header); + } else { + output_buffer = data_out; + } + + ret = drv->ops.get_large_config(dev, input_tl->type, + init_block, + final_block, + data_off_size, output_buffer); + + /* on error report which param failed */ + if (ret) { + error = (struct ipc4_vendor_error *)data_out; + error->param_idx = input_tl->type; + error->err_code = IPC4_FAILURE; + *data_off_size = sizeof(*error); + ipc_cmd_err(&ipc_tr, "error: get_large_config returned %d", ret); + return IPC4_FAILURE; + } + + /* for initial block update TL header */ + if (init_block) { + /* we use tlv struct here for clarity, we have length not max_length */ + tl_header = (struct sof_tlv *)data_out; + tl_header->type = input_tl->type; + tl_header->length = *data_off_size; + /* for initial block data_off_size includes also size of TL */ + *data_off_size += sizeof(*tl_header); + } + } + return IPC4_SUCCESS; +} + +__cold static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_large_config_reply reply; + struct ipc4_module_large_config config; + char *data = ipc_get()->comp_data; + const struct comp_driver *drv; + struct comp_dev *dev = NULL; + uint32_t data_offset; + + assert_can_be_cold(); + + int ret = memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + tr_dbg(&ipc_tr, "%x : %x", + (uint32_t)config.primary.r.module_id, (uint32_t)config.primary.r.instance_id); + + /* get component dev for non-basefw since there is no + * component dev for basefw + */ + if (config.primary.r.module_id) { + uint32_t comp_id; + + comp_id = IPC4_COMP_ID(config.primary.r.module_id, + config.primary.r.instance_id); + dev = ipc4_get_comp_dev(comp_id); + if (!dev) + return IPC4_MOD_INVALID_ID; + + drv = dev->drv; + + /* Pass IPC to target core */ + if (!cpu_is_me(dev->ipc_config.core)) + return ipc4_process_on_core(dev->ipc_config.core, false); + } else { + drv = ipc4_get_comp_drv(config.primary.r.module_id); + } + + if (!drv) + return IPC4_MOD_INVALID_ID; + + if (!drv->ops.get_large_config) + return IPC4_INVALID_REQUEST; + + data_offset = config.extension.r.data_off_size; + + /* check for vendor param first */ + if (config.extension.r.large_param_id == VENDOR_CONFIG_PARAM) { + /* For now only vendor_config case uses payload from hostbox */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, + config.extension.r.data_off_size); + ret = ipc4_get_vendor_config_module_instance(dev, drv, + config.extension.r.init_block, + config.extension.r.final_block, + &data_offset, + data, + (const char *)MAILBOX_HOSTBOX_BASE); + } else { +#if CONFIG_LIBRARY + data += sizeof(reply); +#endif + ipc4_prepare_for_kcontrol_get(dev, config.extension.r.large_param_id, + data, data_offset); + + ret = drv->ops.get_large_config(dev, config.extension.r.large_param_id, + config.extension.r.init_block, + config.extension.r.final_block, + &data_offset, data); + } + + /* set up ipc4 error code for reply data */ + if (ret < 0) + ret = IPC4_MOD_INVALID_ID; + + /* Copy host config and overwrite */ + reply.extension.dat = config.extension.dat; + reply.extension.r.data_off_size = data_offset; + + /* The last block, no more data */ + if (!config.extension.r.final_block && data_offset < SOF_IPC_MSG_MAX_SIZE) + reply.extension.r.final_block = 1; + + /* Indicate last block if error occurs */ + if (ret) + reply.extension.r.final_block = 1; + + /* no need to allocate memory for reply msg */ + if (ret) + return ret; + + msg_reply->extension = reply.extension.dat; + msg_reply->tx_size = data_offset; + msg_reply->tx_data = data; + return ret; +} + +__cold static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev, + const struct comp_driver *drv, + uint32_t module_id, + uint32_t instance_id, + bool init_block, + bool final_block, + uint32_t data_off_size, + const char *data) +{ + int ret; + + assert_can_be_cold(); + + /* Old FW comment: bursted configs */ + if (init_block && final_block) { + const struct sof_tlv *tlv = (struct sof_tlv *)data; + /* if there is no payload in this large config set + * (4 bytes type | 4 bytes length=0 | no value) + * we do not handle such case + */ + if (data_off_size < sizeof(struct sof_tlv) || data_off_size > MAILBOX_HOSTBOX_SIZE) + return IPC4_INVALID_CONFIG_DATA_STRUCT; + + /* ===Iterate over payload=== + * Payload can have multiple sof_tlv structures inside, + * You can find how many by checking payload size (data_off_size) + * Here we just set pointer end_offset to the end of data + * and iterate until we reach that + */ + const uint8_t *end_offset = (const uint8_t *)data + data_off_size; + + while ((const uint8_t *)tlv < end_offset) { + size_t remaining = (size_t)(end_offset - (const uint8_t *)tlv); + + /* check for invalid length */ + if (!tlv->length) + return IPC4_INVALID_CONFIG_DATA_LEN; + + /* Validate TLV header + value fits within remaining + * payload to prevent OOB access and pointer wraparound + * on 32-bit arithmetic (CWE-190). Split into two checks + * to avoid overflow in the size_t addition itself. + */ + if (remaining < sizeof(struct sof_tlv) || + tlv->length > remaining - sizeof(struct sof_tlv)) + return IPC4_INVALID_REQUEST; + + ret = drv->ops.set_large_config(dev, tlv->type, init_block, + final_block, tlv->length, tlv->value); + if (ret < 0) { + ipc_cmd_err(&ipc_tr, "failed to set large_config_module_instance %x : %x", + (uint32_t)module_id, (uint32_t)instance_id); + return IPC4_INVALID_RESOURCE_ID; + } + /* Move pointer to the end of this tlv (aligned) */ + tlv = (struct sof_tlv *)((const uint8_t *)tlv + + sizeof(struct sof_tlv) + ALIGN_UP(tlv->length, 4)); + } + return IPC4_SUCCESS; + } + /* else, !(init_block && final_block) */ + const struct sof_tlv *tlv = (struct sof_tlv *)data; + uint32_t param_id = 0; + + if (init_block) { + /* for initial block use param_id from tlv + * move pointer and size to end of the tlv + */ + param_id = tlv->type; + data += sizeof(struct sof_tlv); + data_off_size -= sizeof(struct sof_tlv); + } + return drv->ops.set_large_config(dev, param_id, init_block, final_block, + data_off_size, data); +} + +__cold static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_large_config config; + struct comp_dev *dev = NULL; + const struct comp_driver *drv; + + assert_can_be_cold(); + + int ret = memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, + config.extension.r.data_off_size); + tr_dbg(&ipc_tr, "%x : %x", + (uint32_t)config.primary.r.module_id, (uint32_t)config.primary.r.instance_id); + + if (config.primary.r.module_id) { + uint32_t comp_id; + + comp_id = IPC4_COMP_ID(config.primary.r.module_id, config.primary.r.instance_id); + dev = ipc4_get_comp_dev(comp_id); + if (!dev) + return IPC4_MOD_INVALID_ID; + + drv = dev->drv; + + /* Pass IPC to target core */ + if (!cpu_is_me(dev->ipc_config.core)) + return ipc4_process_on_core(dev->ipc_config.core, false); + } else { + drv = ipc4_get_comp_drv(config.primary.r.module_id); + } + + if (!drv) + return IPC4_MOD_INVALID_ID; + + if (!drv->ops.set_large_config) + return IPC4_INVALID_REQUEST; + + /* check for vendor param first */ + if (config.extension.r.large_param_id == VENDOR_CONFIG_PARAM) { + ret = ipc4_set_vendor_config_module_instance(dev, drv, + (uint32_t)config.primary.r.module_id, + (uint32_t)config.primary.r.instance_id, + config.extension.r.init_block, + config.extension.r.final_block, + config.extension.r.data_off_size, + (const char *)MAILBOX_HOSTBOX_BASE); + } else { +#if CONFIG_LIBRARY + struct ipc *ipc = ipc_get(); + const char *data = (const char *)ipc->comp_data + sizeof(config); +#else + const char *data = (const char *)MAILBOX_HOSTBOX_BASE; +#endif + ret = drv->ops.set_large_config(dev, config.extension.r.large_param_id, + config.extension.r.init_block, config.extension.r.final_block, + config.extension.r.data_off_size, data); + if (ret < 0) { + 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; + } + } + + return ret; +} + +__cold static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4) +{ + struct ipc4_module_delete_instance module; + struct ipc *ipc = ipc_get(); + uint32_t comp_id; + + assert_can_be_cold(); + + int ret = memcpy_s(&module, sizeof(module), ipc4, sizeof(*ipc4)); + + if (ret < 0) + return IPC4_FAILURE; + + tr_dbg(&ipc_tr, "%x : %x", (uint32_t)module.primary.r.module_id, + (uint32_t)module.primary.r.instance_id); + + 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) { + 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; + } + + return ret; +} + +__cold int ipc4_user_process_module_message(struct ipc4_message_request *ipc4, + struct ipc_msg *reply) +{ + uint32_t type; + int ret; + + assert_can_be_cold(); + + type = ipc4->primary.r.type; + msg_reply = reply; + + switch (type) { + case SOF_IPC4_MOD_INIT_INSTANCE: + ret = ipc4_init_module_instance(ipc4); + break; + case SOF_IPC4_MOD_CONFIG_GET: + ret = ipc4_set_get_config_module_instance(ipc4, false); + break; + case SOF_IPC4_MOD_CONFIG_SET: + ret = ipc4_set_get_config_module_instance(ipc4, true); + break; + case SOF_IPC4_MOD_LARGE_CONFIG_GET: + ret = ipc4_get_large_config_module_instance(ipc4); + break; + case SOF_IPC4_MOD_LARGE_CONFIG_SET: + ret = ipc4_set_large_config_module_instance(ipc4); + break; + case SOF_IPC4_MOD_BIND: + ret = ipc4_bind_module_instance(ipc4); + break; + case SOF_IPC4_MOD_UNBIND: + ret = ipc4_unbind_module_instance(ipc4); + break; + case SOF_IPC4_MOD_DELETE_INSTANCE: + ret = ipc4_delete_module_instance(ipc4); + break; + case SOF_IPC4_MOD_ENTER_MODULE_RESTORE: + case SOF_IPC4_MOD_EXIT_MODULE_RESTORE: + ret = IPC4_UNAVAILABLE; + break; + default: + ret = IPC4_UNAVAILABLE; + break; + } + + return ret; +} diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c new file mode 100644 index 000000000000..892e704eb2e4 --- /dev/null +++ b/src/ipc/ipc4/helper.c @@ -0,0 +1,1421 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Author: Rander Wang <rander.wang@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/audio_buffer.h> +#include <sof/audio/ring_buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <module/module/base.h> +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/common.h> +#include <ipc/dai.h> +#include <sof/ipc/msg.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/vregion.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/symbol.h> +#include <rtos/wait.h> + +/* TODO: Remove platform-specific code, see https://github.com/thesofproject/sof/issues/7549 */ +#if defined(CONFIG_SOC_SERIES_INTEL_ADSP_ACE) || defined(CONFIG_INTEL_ADSP_CAVS) +#define RIMAGE_MANIFEST 1 +#endif + +#ifdef RIMAGE_MANIFEST +#include <adsp_memory.h> +#endif + +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <rimage/cavs/cavs_ext_manifest.h> +#include <rimage/sof/user/manifest.h> +#include <ipc4/base-config.h> +#include <ipc/header.h> +#include <ipc4/notification.h> +#include <ipc4/pipeline.h> +#include <ipc4/module.h> +#include <ipc4/error_status.h> +#include <sof/lib_manager.h> +#include <sof/tlv.h> + +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <sof/debug/telemetry/telemetry.h> +#include <sof/debug/telemetry/performance_monitor.h> + +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx comp_tr; + +static const struct comp_driver *ipc4_get_drv(const void *uuid); +static int ipc4_add_comp_dev(struct comp_dev *dev); + +void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, uint32_t type, + uint32_t id) +{ + memset(posn, 0, sizeof(*posn)); +} + +void ipc_build_comp_event(struct sof_ipc_comp_event *event, uint32_t type, + uint32_t id) +{ +} + +bool ipc_trigger_trace_xfer(uint32_t avail) +{ + return avail >= DMA_TRACE_LOCAL_SIZE / 2; +} + +void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn) +{ + posn->rhdr.hdr.cmd = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS); + posn->rhdr.hdr.size = 0; +} + +#if CONFIG_LIBRARY +static inline char *ipc4_get_comp_new_data(void) +{ + struct ipc *ipc = ipc_get(); + char *data = (char *)ipc->comp_data + sizeof(struct ipc4_module_init_instance); + + return data; +} + +static const struct comp_driver *ipc4_library_get_comp_drv(char *data) +{ + return ipc4_get_drv(data); +} +#else +__cold static inline char *ipc4_get_comp_new_data(void) +{ + assert_can_be_cold(); + + return (char *)MAILBOX_HOSTBOX_BASE; +} +#endif + +/* Only called from ipc4_init_module_instance(), which is __cold */ +__cold struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init) +{ + struct comp_ipc_config ipc_config; + const struct comp_driver *drv; + struct comp_dev *dev; + uint32_t comp_id; + char *data; + + assert_can_be_cold(); + + comp_id = IPC4_COMP_ID(module_init->primary.r.module_id, + module_init->primary.r.instance_id); + + if (ipc4_get_comp_dev(comp_id)) { + tr_err(&ipc_tr, "comp 0x%x exists", comp_id); + return NULL; + } + + if (module_init->extension.r.core_id >= CONFIG_CORE_COUNT) { + tr_err(&ipc_tr, "ipc: comp->core = %u", (uint32_t)module_init->extension.r.core_id); + return NULL; + } + + memset(&ipc_config, 0, sizeof(ipc_config)); + ipc_config.id = comp_id; + ipc_config.pipeline_id = module_init->extension.r.ppl_instance_id; + ipc_config.core = module_init->extension.r.core_id; + ipc_config.ipc_config_size = module_init->extension.r.param_block_size * sizeof(uint32_t); + ipc_config.ipc_extended_init = module_init->extension.r.extended_init; + if (ipc_config.ipc_config_size > MAILBOX_HOSTBOX_SIZE) { + tr_err(&ipc_tr, "IPC payload size %u too big for the message window", + ipc_config.ipc_config_size); + return NULL; + } +#ifdef CONFIG_DCACHE_LINE_SIZE + if (!IS_ENABLED(CONFIG_LIBRARY)) + sys_cache_data_invd_range((__sparse_force void __sparse_cache *) + MAILBOX_HOSTBOX_BASE, + ALIGN_UP(ipc_config.ipc_config_size, + CONFIG_DCACHE_LINE_SIZE)); +#endif + data = ipc4_get_comp_new_data(); +#if CONFIG_LIBRARY + ipc_config.ipc_config_size -= sizeof(struct sof_uuid); + drv = ipc4_library_get_comp_drv(data + ipc_config.ipc_config_size); +#else + drv = ipc4_get_comp_drv(IPC4_MOD_ID(comp_id)); +#endif + if (!drv) + return NULL; + +#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 0x%x", comp_id); + return NULL; + } + ipc_config.proc_domain = COMP_PROCESSING_DOMAIN_LL; +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + + if (drv->type == SOF_COMP_MODULE_ADAPTER) { + const struct ipc_config_process spec = { + .data = (const unsigned char *)data, + .size = ipc_config.ipc_config_size, + }; + + dev = drv->ops.create(drv, &ipc_config, (const void *)&spec); + } else { + dev = drv->ops.create(drv, &ipc_config, (const void *)data); + } + if (!dev) + return NULL; + + list_init(&dev->bsource_list); + list_init(&dev->bsink_list); + +#ifdef CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS + /* init global performance measurement */ + dev->perf_data.perf_data_item = perf_data_getnext(); + /* this can be null, just no performance measurements in this case */ + if (dev->perf_data.perf_data_item) { + dev->perf_data.perf_data_item->item.resource_id = comp_id; + if (perf_meas_get_state() != IPC4_PERF_MEASUREMENTS_DISABLED) + comp_init_performance_data(dev); + } +#endif + + ipc4_add_comp_dev(dev); + + comp_update_ibs_obs_cpc(dev); + + return dev; +} + +/* Called from ipc4_set_pipeline_state(), so cannot be cold */ +struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, + uint32_t ppl_id, + uint32_t ignore_remote) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != type) + continue; + + /* For IPC4, ipc_comp_dev.id field is equal to Pipeline ID + * in case of type COMP_TYPE_PIPELINE - can check directly here + */ + if (type == COMP_TYPE_PIPELINE) { + if (icd->id == ppl_id) + return icd; + } else { + if ((!cpu_is_me(icd->core)) && ignore_remote) + continue; + if (ipc_comp_pipe_id(icd) == ppl_id) + return icd; + } + } + return NULL; +} + +/* + * This function currently only decodes the payload and prints out + * data it finds, but it does not store it anywhere. + */ +__cold static int ipc4_create_pipeline_payload_decode(char *data, + struct create_pipeline_params *pparams) +{ + const struct ipc4_pipeline_ext_payload *hdr = + (struct ipc4_pipeline_ext_payload *)data; + const struct ipc4_pipeline_ext_object *obj; +#ifdef CONFIG_DCACHE_LINE_SIZE + size_t cache_line_size = CONFIG_DCACHE_LINE_SIZE; + size_t hdr_cache_size = ALIGN_UP(sizeof(*hdr), cache_line_size); +#endif + bool last_object; + size_t size; + +#ifdef CONFIG_DCACHE_LINE_SIZE + if (!IS_ENABLED(CONFIG_LIBRARY)) + sys_cache_data_invd_range((__sparse_force void __sparse_cache *)data, + hdr_cache_size); +#endif + size = hdr->payload_words * sizeof(uint32_t); + last_object = !hdr->data_obj_array; + + if (size < sizeof(*hdr)) { + tr_err(&ipc_tr, "Payload size too small: %u : %#x", hdr->payload_words, + *((uint32_t *)hdr)); + return -EINVAL; + } + if (size > MAILBOX_HOSTBOX_SIZE) { + tr_err(&ipc_tr, "Payload size too large: %u : %#x", hdr->payload_words, + *((uint32_t *)hdr)); + } + tr_info(&ipc_tr, "payload size %u array %u: %#x", hdr->payload_words, hdr->data_obj_array, + *((uint32_t *)hdr)); + +#ifdef CONFIG_DCACHE_LINE_SIZE + if (!IS_ENABLED(CONFIG_LIBRARY) && ALIGN_UP(size, cache_line_size) > hdr_cache_size) + sys_cache_data_invd_range((__sparse_force void __sparse_cache *) + ((char *)data + hdr_cache_size), + ALIGN_UP(size, cache_line_size) - hdr_cache_size); +#endif + + obj = (const struct ipc4_pipeline_ext_object *)(hdr + 1); + while (!last_object) { + const struct ipc4_pipeline_ext_object *next_obj; + + /* Check if there is space for the object header */ + if ((char *)(obj + 1) - data > size) { + tr_err(&ipc_tr, "obj header overflow, %u > %zu", + (char *)(obj + 1) - data, size); + return -EINVAL; + } + + /* Calculate would be next object position and check if current object fits */ + next_obj = (const struct ipc4_pipeline_ext_object *) + (((const uint32_t *)(obj + 1)) + obj->object_words); + if ((char *)next_obj - data > size) { + tr_err(&ipc_tr, "object size overflow, %u > %zu", + (char *)next_obj - data, size); + return -EINVAL; + } + + switch (obj->object_id) { + case IPC4_GLB_PIPE_EXT_OBJ_ID_MEM_DATA: + { + /* Get mem_data struct that follows the obj struct */ + const struct ipc4_pipeline_ext_obj_mem_data *mem_data = + (const struct ipc4_pipeline_ext_obj_mem_data *)(obj + 1); + + if (obj->object_words * sizeof(uint32_t) < sizeof(*mem_data)) { + tr_err(&ipc_tr, "mem_data object does not fit %zu < %zu", + obj->object_words * sizeof(uint32_t), sizeof(*mem_data)); + break; + } + pparams->mem_data = mem_data; + tr_info(&ipc_tr, + "init_ext_obj_mem_data domain %u stack %u interim %u lifetime %u shared %u", + mem_data->domain_id, mem_data->stack_bytes, + mem_data->interim_heap_bytes, mem_data->lifetime_heap_bytes, + mem_data->shared_bytes); + break; + } + default: + tr_warn(&ipc_tr, "Unknown ext init object id %u of %u words", + obj->object_id, obj->object_words); + } + /* Read the last object flag from obj header */ + last_object = obj->last_object; + /* Move to next object */ + obj = next_obj; + } + + return 0; +} + +__cold static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc, + struct create_pipeline_params *pparams) +{ + struct ipc_comp_dev *ipc_pipe; + struct pipeline *pipe; + struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + + /* check whether pipeline id is already taken or in use */ + ipc_pipe = ipc_get_pipeline_by_id(ipc, pipe_desc->primary.r.instance_id); + if (ipc_pipe) { + 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; + } + + /* create the pipeline */ + pipe = pipeline_new(NULL, pipe_desc->primary.r.instance_id, + pipe_desc->primary.r.ppl_priority, 0, pparams); + if (!pipe) { + tr_err(&ipc_tr, "ipc: pipeline_new() failed"); + return IPC4_OUT_OF_MEMORY; + } + + pipe->time_domain = SOF_TIME_DOMAIN_TIMER; + pipe->period = LL_TIMER_PERIOD_US; + + /* sched_id is set in FW so initialize it to a invalid value */ + pipe->sched_id = 0xFFFFFFFF; + + pipe->core = pipe_desc->extension.r.core_id; + + /* allocate the IPC pipeline container */ + ipc_pipe = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct ipc_comp_dev)); + if (!ipc_pipe) { + pipeline_free(pipe); + return IPC4_OUT_OF_MEMORY; + } + + ipc_pipe->pipeline = pipe; + ipc_pipe->type = COMP_TYPE_PIPELINE; + ipc_pipe->id = pipe_desc->primary.r.instance_id; + ipc_pipe->core = pipe_desc->extension.r.core_id; + ipc_pipe->pipeline->attributes = pipe_desc->extension.r.attributes; + + /* add new pipeline to the list */ + list_item_append(&ipc_pipe->list, &ipc->comp_list); + + return IPC4_SUCCESS; +} + +#if CONFIG_LIBRARY +static inline char *ipc4_get_pipe_create_data(void) +{ + struct ipc *ipc = ipc_get(); + char *data = (char *)ipc->comp_data + sizeof(struct ipc4_pipeline_create); + + return data; +} +#else +__cold static inline char *ipc4_get_pipe_create_data(void) +{ + assert_can_be_cold(); + + return (char *)MAILBOX_HOSTBOX_BASE; +} +#endif + +/* Only called from ipc4_new_pipeline(), which is __cold */ +__cold int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) +{ + struct ipc4_pipeline_create *pipe_desc = ipc_from_pipe_new(_pipe_desc); + struct create_pipeline_params pparams = { 0 }; + bool valid_pparams = false; + assert_can_be_cold(); + + tr_dbg(&ipc_tr, "ipc: pipeline id = %u", (uint32_t)pipe_desc->primary.r.instance_id); + + /* pass IPC to target core */ + if (!cpu_is_me(pipe_desc->extension.r.core_id)) + return ipc4_process_on_core(pipe_desc->extension.r.core_id, false); + + if (pipe_desc->extension.r.payload) { + char *data; + int ret; + + data = ipc4_get_pipe_create_data(); + + ret = ipc4_create_pipeline_payload_decode(data, &pparams); + if (ret == 0) + valid_pparams = true; + } + + return ipc4_create_pipeline(pipe_desc, valid_pparams ? &pparams : NULL); +} + +__cold static inline int ipc_comp_free_remote(struct comp_dev *dev) +{ + struct idc_msg msg = { IDC_MSG_FREE, IDC_MSG_FREE_EXT(dev->ipc_config.id), + dev->ipc_config.core,}; + + assert_can_be_cold(); + + return idc_send_msg(&msg, IDC_BLOCKING); +} + +__cold static int ipc_pipeline_module_free(uint32_t pipeline_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + int ret; + + assert_can_be_cold(); + + icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_COMPONENT, pipeline_id, IPC_COMP_ALL); + while (icd) { + struct comp_buffer *buffer; + struct comp_buffer *safe; + + /* free sink buffer allocated by current component in bind function */ + comp_dev_for_each_consumer_safe(icd->cd, buffer, safe) { + pipeline_disconnect(icd->cd, buffer, PPL_CONN_DIR_COMP_TO_BUFFER); + struct comp_dev *sink = comp_buffer_get_sink_component(buffer); + + /* free the buffer only when the sink module has also been disconnected */ + if (!sink) + buffer_free(buffer); + } + + /* free source buffer allocated by current component in bind function */ + comp_dev_for_each_producer_safe(icd->cd, buffer, safe) { + pipeline_disconnect(icd->cd, buffer, PPL_CONN_DIR_BUFFER_TO_COMP); + struct comp_dev *source = comp_buffer_get_source_component(buffer); + + /* free the buffer only when the source module has also been disconnected */ + if (!source) + buffer_free(buffer); + } + + if (!cpu_is_me(icd->core)) + ret = ipc_comp_free_remote(icd->cd); + else + ret = ipc_comp_free(ipc, icd->id); + + if (ret) + return IPC4_INVALID_RESOURCE_STATE; + + icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_COMPONENT, pipeline_id, IPC_COMP_ALL); + } + + return IPC4_SUCCESS; +} + +/* Only called from ipc4_delete_pipeline(), which is __cold */ +__cold int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) +{ + struct ipc_comp_dev *ipc_pipe; + int ret; + + assert_can_be_cold(); + + /* check whether pipeline exists */ + ipc_pipe = ipc_get_pipeline_by_id(ipc, comp_id); + if (!ipc_pipe) + return IPC4_INVALID_RESOURCE_ID; + + /* Pass IPC to target core */ + if (!cpu_is_me(ipc_pipe->core)) + return ipc4_process_on_core(ipc_pipe->core, false); + + ret = ipc_pipeline_module_free(ipc_pipe->pipeline->pipeline_id); + if (ret != IPC4_SUCCESS) { + tr_err(&ipc_tr, "module free () failed"); + return ret; + } + + /* free buffer, delete all tasks and remove from list */ + ret = pipeline_free(ipc_pipe->pipeline); + if (ret < 0) { + tr_err(&ipc_tr, "pipeline_free() failed"); + return IPC4_INVALID_RESOURCE_STATE; + } + + ipc_pipe->pipeline = NULL; + list_item_del(&ipc_pipe->list); + rfree(ipc_pipe); + + return IPC4_SUCCESS; +} + +__cold static struct comp_buffer *ipc4_create_buffer(struct comp_dev *src, bool is_shared, + uint32_t buf_size, uint32_t src_queue, + uint32_t dst_queue, struct mod_alloc_ctx *alloc) +{ + struct sof_ipc_buffer ipc_buf; + + assert_can_be_cold(); + + memset(&ipc_buf, 0, sizeof(ipc_buf)); + ipc_buf.size = buf_size; + ipc_buf.comp.id = IPC4_COMP_ID(src_queue, dst_queue); + ipc_buf.comp.pipeline_id = src->ipc_config.pipeline_id; + ipc_buf.comp.core = cpu_get_id(); + return buffer_new(alloc, &ipc_buf, is_shared); +} + +#if CONFIG_CROSS_CORE_STREAM +/* + * Disabling interrupts to block next LL cycle works much faster comparing using + * of condition variable and mutex. Since same core binding is the most typical + * case, let's use slower cond_var blocking mechanism only for not so typical + * cross-core binding. + * + * Note, disabling interrupts to block LL for cross-core binding case will not work + * as .bind() handlers are called on corresponding cores using IDC tasks. IDC requires + * interrupts to be enabled. Only disabling timer interrupt instead of all interrupts + * might work. However, as CPU could go to some power down mode while waiting for + * blocking IDC call response, it's not clear how safe is to assume CPU can wakeup + * without timer interrupt. It depends on blocking IDC waiting implementation. That + * is why additional cond_var mechanism to block LL was introduced which does not + * disable any interrupts. + */ + +#define ll_block(cross_core_bind, flags) \ + do { \ + if (cross_core_bind) \ + domain_block(sof_get()->platform_timer_domain); \ + else \ + irq_local_disable(flags); \ + } while (0) + +#define ll_unblock(cross_core_bind, flags) \ + do { \ + if (cross_core_bind) \ + domain_unblock(sof_get()->platform_timer_domain); \ + else \ + irq_local_enable(flags); \ + } while (0) + +/* Calling both ll_block() and ll_wait_finished_on_core() makes sure LL will not start its + * next cycle and its current cycle on specified core has finished. + */ +static int ll_wait_finished_on_core(struct comp_dev *dev) +{ + /* To make sure (blocked) LL has finished its current cycle, it is + * enough to send any blocking IDC to the core. Since IDC task has lower + * priority then LL thread and cannot preempt it, execution of IDC task + * happens when LL thread is not active waiting for its next cycle. + */ + + int ret; + struct ipc4_base_module_cfg dummy; + + if (cpu_is_me(dev->ipc_config.core)) + return 0; + + /* Any blocking IDC that does not change component state could be utilized */ + ret = comp_ipc4_get_attribute_remote(dev, COMP_ATTR_BASE_CONFIG, &dummy); + if (ret < 0) { + tr_err(&ipc_tr, "comp_ipc4_get_attribute_remote() failed for module %#x", + dev_comp_id(dev)); + return ret; + } + + return 0; +} + +#else + +#define ll_block(cross_core_bind, flags) irq_local_disable(flags) +#define ll_unblock(cross_core_bind, flags) irq_local_enable(flags) + +#endif + +/* Only called from ipc4_bind_module_instance(), which is __cold */ +__cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) +{ + struct ipc4_module_bind_unbind *bu; + struct bind_info bind_data; + struct comp_buffer *buffer; + struct comp_dev *source; + struct comp_dev *sink; + struct ipc4_base_module_cfg source_src_cfg; + struct ipc4_base_module_cfg sink_src_cfg; + uint32_t flags = 0; + uint32_t ibs = 0; + uint32_t obs = 0; + uint32_t buf_size; + int src_id, sink_id; + int ret; + + assert_can_be_cold(); + + bu = (struct ipc4_module_bind_unbind *)_connect; + src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); + sink_id = IPC4_COMP_ID(bu->extension.r.dst_module_id, bu->extension.r.dst_instance_id); + source = ipc4_get_comp_dev(src_id); + sink = ipc4_get_comp_dev(sink_id); + + if (!source || !sink) { + tr_err(&ipc_tr, "failed to find src %x, or dst %x", src_id, sink_id); + return IPC4_INVALID_RESOURCE_ID; + } + + struct mod_alloc_ctx *alloc; + +#if CONFIG_ZEPHYR_DP_SCHEDULER + if (source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP && + sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + tr_err(&ipc_tr, "DP to DP binding is not supported: can't bind %x to %x", + src_id, sink_id); + return IPC4_INVALID_REQUEST; + } + + struct comp_dev *dp; + + if (sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) + dp = sink; + else if (source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) + dp = source; + else + dp = NULL; + + alloc = dp && dp->mod ? dp->mod->priv.resources.alloc : NULL; +#else + alloc = NULL; +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + bool cross_core_bind = source->ipc_config.core != sink->ipc_config.core; + + /* If both components are on same core -- process IPC on that core, + * otherwise stay on core 0 + */ + if (!cpu_is_me(source->ipc_config.core) && !cross_core_bind) + return ipc4_process_on_core(source->ipc_config.core, false); + + if (source->drv->type == SOF_COMP_MODULE_ADAPTER) { + struct processing_module *srcmod = comp_mod(source); + struct module_config *srccfg = &srcmod->priv.cfg; + + /* get obs from the base config extension if the src queue ID is non-zero */ + if (bu->extension.r.src_queue && bu->extension.r.src_queue < srccfg->nb_output_pins) + obs = srccfg->output_pins[bu->extension.r.src_queue].obs; + } + + /* get obs from base config if src queue ID is 0 or if base config extn is missing */ + if (!obs) { + /* these might call comp_ipc4_get_attribute_remote() if necessary */ + ret = comp_get_attribute(source, COMP_ATTR_BASE_CONFIG, &source_src_cfg); + + if (ret < 0) { + tr_err(&ipc_tr, "failed to get base config for src module %#x", + dev_comp_id(source)); + return IPC4_FAILURE; + } + obs = source_src_cfg.obs; + } + + if (sink->drv->type == SOF_COMP_MODULE_ADAPTER) { + struct processing_module *dstmod = comp_mod(sink); + struct module_config *dstcfg = &dstmod->priv.cfg; + + /* get ibs from the base config extension if the sink queue ID is non-zero */ + if (bu->extension.r.dst_queue && bu->extension.r.dst_queue < dstcfg->nb_input_pins) + ibs = dstcfg->input_pins[bu->extension.r.dst_queue].ibs; + } + /* get ibs from base config if sink queue ID is 0 or if base config extn is missing */ + if (!ibs) { + ret = comp_get_attribute(sink, COMP_ATTR_BASE_CONFIG, &sink_src_cfg); + if (ret < 0) { + tr_err(&ipc_tr, "failed to get base config for sink module %#x", + dev_comp_id(sink)); + return IPC4_FAILURE; + } + + ibs = sink_src_cfg.ibs; + } + + /* create a buffer + * in case of LL -> LL or LL->DP + * The ibs / obs should be equal between components. However, some modules + * (like kpb) produce different data sizes on output pins. Unfortunately, only + * one ibs/obs can be specified in the modules configuration. To avoid creating + * too small a buffer, we choose the maximum value between ibs and obs. + * + * size = 2*max(obs of source module, ibs of destination module) + * (obs and ibs is single buffer size) + * in case of DP -> LL + * size = 2*ibs of destination (LL) module. DP queue will handle obs of DP module + */ + if (source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) + buf_size = MAX(ibs, obs) * 2; + else + buf_size = ibs * 2; + + buffer = ipc4_create_buffer(source, cross_core_bind, buf_size, bu->extension.r.src_queue, + bu->extension.r.dst_queue, alloc); + if (!buffer) { + tr_err(&ipc_tr, "failed to allocate buffer to bind %#x to %#x", src_id, sink_id); + return IPC4_OUT_OF_MEMORY; + } + +#if CONFIG_ZEPHYR_DP_SCHEDULER + if (alloc) + vregion_get(alloc->vreg); +#endif + + /* + * set min_free_space and min_available in sink/src api of created buffer. + * buffer is connected like: + * source_module -> (sink_ifc) BUFFER (source_ifc) -> sink_module + * + * source_module needs to set its OBS (out buffer size) + * as min_free_space in buffer's sink ifc + * sink_module needs to set its IBS (input buffer size) + * as min_available in buffer's source ifc + */ + sink_set_min_free_space(audio_buffer_get_sink(&buffer->audio_buffer), obs); + source_set_min_available(audio_buffer_get_source(&buffer->audio_buffer), ibs); + +#if CONFIG_ZEPHYR_DP_SCHEDULER + struct ring_buffer *ring_buffer = NULL; + + if (sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP || + source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { + struct processing_module *srcmod = comp_mod(source); + struct module_data *src_module_data = &srcmod->priv; + struct processing_module *dstmod = comp_mod(sink); + struct module_data *dst_module_data = &dstmod->priv; + + /* + * Handle cases where the size of the ring buffer depends on the + * in_buff_size/out_buff_size advertised by the module. E.g. in the case of the + * compressed decoder module, the in/out_buff_size is determined during module + * init based on the decoder implementation. Also note that the size passed here + * is only for the ring buffer. The size of intermediate buffer created above is + * unchanged. + */ + ring_buffer = ring_buffer_create(dp, MAX(ibs, dst_module_data->mpd.in_buff_size), + MAX(obs, src_module_data->mpd.out_buff_size), + audio_buffer_is_shared(&buffer->audio_buffer), + buf_get_id(buffer)); + if (!ring_buffer) { + buffer_free(buffer); + return IPC4_OUT_OF_MEMORY; + } + + /* data destination module needs to use ring_buffer */ + audio_buffer_attach_secondary_buffer(&buffer->audio_buffer, dp == source, + &ring_buffer->audio_buffer); + } + +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + /* + * Connect and bind the buffer to both source and sink components with LL processing been + * blocked on corresponding core(s) to prevent IPC or IDC task getting preempted which + * could result in buffers being only half connected when a pipeline task gets executed. + */ + ll_block(cross_core_bind, flags); + + if (cross_core_bind) { +#if CONFIG_CROSS_CORE_STREAM + /* Make sure LL has finished on both cores */ + if (!cpu_is_me(source->ipc_config.core)) + if (ll_wait_finished_on_core(source) < 0) + goto free; + if (!cpu_is_me(sink->ipc_config.core)) + if (ll_wait_finished_on_core(sink) < 0) + goto free; +#else + tr_err(&ipc_tr, "Cross-core binding is disabled"); + goto free; +#endif + } + + ret = comp_buffer_connect(source, source->ipc_config.core, buffer, + PPL_CONN_DIR_COMP_TO_BUFFER); + if (ret < 0) { + tr_err(&ipc_tr, "failed to connect src %#x to internal buffer", src_id); + goto free; + } + + ret = comp_buffer_connect(sink, sink->ipc_config.core, buffer, + PPL_CONN_DIR_BUFFER_TO_COMP); + if (ret < 0) { + tr_err(&ipc_tr, "failed to connect internal buffer to sink %#x", sink_id); + goto e_sink_connect; + } + + /* these might call comp_ipc4_bind_remote() if necessary */ + bind_data.ipc4_data = bu; + bind_data.bind_type = COMP_BIND_TYPE_SINK; + bind_data.sink = audio_buffer_get_sink(&buffer->audio_buffer); + ret = comp_bind(source, &bind_data); + if (ret < 0) + goto e_src_bind; + + bind_data.bind_type = COMP_BIND_TYPE_SOURCE; + bind_data.source = audio_buffer_get_source(&buffer->audio_buffer); + ret = comp_bind(sink, &bind_data); + if (ret < 0) + goto e_sink_bind; + + /* update direction for sink component if it is not set already */ + if (!sink->direction_set && source->direction_set) { + sink->direction = source->direction; + sink->direction_set = true; + } + + /* update direction for source component if it is not set already */ + if (!source->direction_set && sink->direction_set) { + source->direction = sink->direction; + source->direction_set = true; + } + + ll_unblock(cross_core_bind, flags); + + return IPC4_SUCCESS; + +e_sink_bind: + /* sink bind was already called */ + bind_data.bind_type = COMP_BIND_TYPE_SINK; + bind_data.sink = audio_buffer_get_sink(&buffer->audio_buffer); + comp_unbind(source, &bind_data); +e_src_bind: + pipeline_disconnect(sink, buffer, PPL_CONN_DIR_BUFFER_TO_COMP); +e_sink_connect: + pipeline_disconnect(source, buffer, PPL_CONN_DIR_COMP_TO_BUFFER); +free: + ll_unblock(cross_core_bind, flags); + buffer_free(buffer); + return IPC4_INVALID_RESOURCE_STATE; +} + +/* when both module instances are part of the same pipeline Unbind IPC would + * be ignored since FW does not support changing internal topology of pipeline + * during run-time. The only way to change pipeline topology is to delete the whole + * pipeline and create it in modified form. + */ +/* Only called from ipc4_unbind_module_instance(), which is __cold */ +__cold int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) +{ + struct ipc4_module_bind_unbind *bu; + struct comp_buffer *buffer = NULL; + struct comp_buffer *buf; + struct comp_dev *src, *sink; + uint32_t src_id, sink_id, buffer_id; + uint32_t flags = 0; + int ret, ret1; + bool cross_core_unbind; + struct bind_info unbind_data; + + assert_can_be_cold(); + + bu = (struct ipc4_module_bind_unbind *)_connect; + src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); + sink_id = IPC4_COMP_ID(bu->extension.r.dst_module_id, bu->extension.r.dst_instance_id); + src = ipc4_get_comp_dev(src_id); + sink = ipc4_get_comp_dev(sink_id); + if (!src || !sink) { + tr_err(&ipc_tr, "failed to find src %x, or dst %x", src_id, sink_id); + return IPC4_INVALID_RESOURCE_ID; + } + + cross_core_unbind = src->ipc_config.core != sink->ipc_config.core; + + /* Pass IPC to target core if both modules has the same target core, + * otherwise stay on core 0 + */ + if (!cpu_is_me(src->ipc_config.core) && !cross_core_unbind) + return ipc4_process_on_core(src->ipc_config.core, false); + + buffer_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue); + comp_dev_for_each_consumer(src, buf) { + bool found = buf_get_id(buf) == buffer_id; + if (found) { + buffer = buf; + break; + } + } + + if (!buffer) + return IPC4_INVALID_RESOURCE_ID; + + /* + * Disconnect and unbind buffer from source/sink components and continue to free the buffer + * even in case of errors. Block LL processing during disconnect and unbinding to prevent + * IPC or IDC task getting preempted which could result in buffers being only half connected + * when a pipeline task gets executed. + */ + ll_block(cross_core_unbind, flags); + + if (cross_core_unbind) { +#if CONFIG_CROSS_CORE_STREAM + /* Make sure LL has finished on both cores */ + if (!cpu_is_me(src->ipc_config.core)) + if (ll_wait_finished_on_core(src) < 0) { + ll_unblock(cross_core_unbind, flags); + return IPC4_FAILURE; + } + if (!cpu_is_me(sink->ipc_config.core)) + if (ll_wait_finished_on_core(sink) < 0) { + ll_unblock(cross_core_unbind, flags); + return IPC4_FAILURE; + } +#else + tr_err(&ipc_tr, "Cross-core binding is disabled"); + ll_unblock(cross_core_unbind, flags); + return IPC4_FAILURE; +#endif + } + + pipeline_disconnect(src, buffer, PPL_CONN_DIR_COMP_TO_BUFFER); + pipeline_disconnect(sink, buffer, PPL_CONN_DIR_BUFFER_TO_COMP); + /* these might call comp_ipc4_bind_remote() if necessary */ + unbind_data.ipc4_data = bu; + unbind_data.bind_type = COMP_BIND_TYPE_SINK; + unbind_data.sink = audio_buffer_get_sink(&buffer->audio_buffer); + ret = comp_unbind(src, &unbind_data); + + unbind_data.bind_type = COMP_BIND_TYPE_SOURCE; + unbind_data.source = audio_buffer_get_source(&buffer->audio_buffer); + ret1 = comp_unbind(sink, &unbind_data); + + ll_unblock(cross_core_unbind, flags); + + buffer_free(buffer); + + if (ret || ret1) + return IPC4_INVALID_RESOURCE_ID; + + return IPC4_SUCCESS; +} + +#if CONFIG_COMP_CHAIN_DMA +/* Only called from ipc4_process_chain_dma(), which is __cold */ +__cold int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma) +{ + const struct sof_uuid uuid = SOF_REG_UUID(chain_dma); + const struct comp_driver *drv; + struct comp_dev *dev; + + assert_can_be_cold(); + + drv = ipc4_get_drv(&uuid); + if (!drv) + return -EINVAL; + + dev = drv->ops.create(drv, NULL, cdma); + if (!dev) + return -EINVAL; + + /* differentiate instance by unique ids assignment */ + const uint32_t comp_id = IPC4_COMP_ID(cdma->primary.r.host_dma_id + + IPC4_MAX_MODULE_COUNT, 0); + dev->ipc_config.id = comp_id; + dev->ipc_config.pipeline_id = cdma->primary.r.host_dma_id + + IPC4_MAX_MODULE_COUNT; + + return ipc4_add_comp_dev(dev); +} + +/* Only called from ipc4_process_chain_dma(), which is __cold */ +__cold int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) +{ + const bool allocate = cdma->primary.r.allocate; + const bool enable = cdma->primary.r.enable; + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + struct list_item *clist, *_tmp; + int ret; + + assert_can_be_cold(); + + if (!dev) + return -EINVAL; + + if (allocate) { + if (enable) + ret = comp_trigger(dev, COMP_TRIGGER_START); + else + ret = comp_trigger(dev, COMP_TRIGGER_PAUSE); + } else { + if (enable) + return -EINVAL; + + /* remove chain part */ + ret = comp_trigger(dev, COMP_TRIGGER_PAUSE); + if (ret < 0) + return ret; + + list_for_item_safe(clist, _tmp, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->cd != dev) + continue; + list_item_del(&icd->list); + rfree(icd); + break; + } + comp_free(dev); + } + return ret; +} +#endif + +__cold static int ipc4_update_comps_direction(struct ipc *ipc, uint32_t ppl_id) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + struct comp_buffer *src_buf; + + assert_can_be_cold(); + + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + if (dev_comp_pipe_id(icd->cd) != ppl_id) + continue; + + if (icd->cd->direction_set) + continue; + + if (list_is_empty(&icd->cd->bsource_list)) + continue; + + src_buf = comp_dev_get_first_data_producer(icd->cd); + if (comp_buffer_get_source_component(src_buf)->direction_set) { + icd->cd->direction = comp_buffer_get_source_component(src_buf)->direction; + icd->cd->direction_set = true; + continue; + } + + return -EINVAL; + } + return 0; +} + +int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id, uint32_t cmd) +{ + struct ipc_comp_dev *ipc_pipe; + int ret; + + ipc_pipe = ipc_get_pipeline_by_id(ipc, comp_id); + if (!ipc_pipe) + return -EINVAL; + + /* Pass IPC to target core */ + if (!cpu_is_me(ipc_pipe->core)) + return ipc_process_on_core(ipc_pipe->core, false); + + /* Note: SOF driver cares to bind modules one by one from input to output gateway, so + * direction is always assigned in bind phase. We do not expect this call change anything. + * OED driver does not guarantee this approach, hence some module may be bound inside + * pipeline w/o connection to gateway, so direction is not configured in binding phase. + * Need to update direction for such modules when pipeline is completed. + */ + if (cmd != SOF_IPC4_PIPELINE_STATE_RESET) { + ret = ipc4_update_comps_direction(ipc, comp_id); + if (ret < 0) + return ret; + } + + return ipc_pipeline_complete(ipc, comp_id); +} + +int ipc4_process_on_core(uint32_t core, bool blocking) +{ + int ret; + + ret = ipc_process_on_core(core, blocking); + switch (ret) { + case 0: + case 1: + return IPC4_SUCCESS; + case -EACCES: + return IPC4_INVALID_CORE_ID; + case -ETIME: + case -EBUSY: + return IPC4_BUSY; + default: + return IPC4_FAILURE; + } + + return IPC4_SUCCESS; +} + +__cold static const struct comp_driver *ipc4_search_for_drv(const void *uuid) +{ + struct comp_driver_list *drivers = comp_drivers_get(); + struct list_item *clist; + const struct comp_driver *drv = NULL; + struct comp_driver_info *info; + uint32_t flags; + + assert_can_be_cold(); + + irq_local_disable(flags); + + /* search driver list with UUID */ + list_for_item(clist, &drivers->list) { + info = container_of(clist, struct comp_driver_info, + list); + if (!memcmp(info->drv->uid, uuid, UUID_SIZE)) { + tr_dbg(&comp_tr, + "found type %d, uuid %pU", + info->drv->type, + info->drv->tctx->uuid_p); + drv = info->drv; + break; + } + } + + irq_local_enable(flags); + return drv; +} + +__cold static const struct comp_driver *ipc4_get_drv(const void *uuid) +{ + const struct sof_uuid *const __maybe_unused sof_uuid = (const struct sof_uuid *)uuid; + const struct comp_driver *drv; + + assert_can_be_cold(); + + drv = ipc4_search_for_drv(uuid); + if (!drv) + tr_err(&comp_tr, + "the provided UUID (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x) can't be found!", + sof_uuid->a, sof_uuid->b, sof_uuid->c, sof_uuid->d[0], sof_uuid->d[1], + sof_uuid->d[2], sof_uuid->d[3], sof_uuid->d[4], sof_uuid->d[5], + sof_uuid->d[6], sof_uuid->d[7]); + + return drv; +} + +/* + * Called from + * - ipc4_get_large_config_module_instance() + * - ipc4_set_large_config_module_instance() + * - comp_new_ipc4() + * all of which are __cold + */ +__cold const struct comp_driver *ipc4_get_comp_drv(uint32_t module_id) +{ + const struct sof_man_fw_desc *desc = NULL; + const struct sof_man_module *mod; + uint32_t entry_index; + + assert_can_be_cold(); + +#ifdef RIMAGE_MANIFEST + desc = (const 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) { + /* module_id 0 is used for base fw which is in entry 1 or 2 */ + if (!module_id) + entry_index = 1 + IS_ENABLED(CONFIG_COLD_STORE_EXECUTE_DRAM); + else + entry_index = module_id; + + if (entry_index >= desc->header.num_module_entries) { + tr_err(&comp_tr, "Error: entry index %d out of bounds.", entry_index); + return NULL; + } + + mod = (const struct sof_man_module *)((const char *)desc + + SOF_MAN_MODULE_OFFSET(entry_index)); + } else { + /* Library index greater than 0 possible only when LIBRARY_MANAGER + * support enabled. + */ +#if CONFIG_LIBRARY_MANAGER + mod = lib_manager_get_module_manifest(module_id); + + if (!mod) { + tr_err(&comp_tr, "Error: Couldn't find loadable module with id %#x.", + module_id); + return NULL; + } +#else + tr_err(&comp_tr, "Error: lib index:%d, while loadable libraries are not supported!!!", + lib_idx); + return NULL; +#endif + } + +#if CONFIG_LIBRARY_MANAGER + /* Check already registered components */ + const struct comp_driver *drv = ipc4_search_for_drv(&mod->uuid); + + if (drv) + return drv; + + /* New module not registered yet. */ + lib_manager_register_module(module_id); +#endif + return ipc4_get_drv(&mod->uuid); +} + +struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id) +{ + struct ipc_comp_dev *icd = ipc_get_comp_by_id(ipc_get(), comp_id); + + return icd ? icd->cd : NULL; +} +EXPORT_SYMBOL(ipc4_get_comp_dev); + +__cold static int ipc4_add_comp_dev(struct comp_dev *dev) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + + assert_can_be_cold(); + + /* 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_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct ipc_comp_dev)); + if (!icd) { + tr_err(&ipc_tr, "alloc failed"); + return IPC4_OUT_OF_MEMORY; + } + + icd->cd = dev; + icd->type = COMP_TYPE_COMPONENT; + icd->core = dev->ipc_config.core; + icd->id = dev->ipc_config.id; + + tr_dbg(&ipc_tr, "add comp 0x%x", icd->id); + /* add new component to the list */ + list_item_append(&icd->list, &ipc->comp_list); + + return IPC4_SUCCESS; +}; + +int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size) +{ +#if ACE_VERSION > ACE_VERSION_1_5 + 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[0] = GET_IPC_DMA_CONFIG(data_buffer, size); +#endif + return IPC4_SUCCESS; +} + +int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer, + uint32_t size, uint32_t device_id, int dma_cfg_idx) +{ + uint32_t end_addr = (uint32_t)data_buffer + size; + struct ipc_dma_config *dma_cfg; + struct sof_tlv *tlvs; + + for (tlvs = (struct sof_tlv *)data_buffer; tlvs && (uint32_t)tlvs < end_addr; + tlvs = tlv_next(tlvs)) { + dma_cfg = tlv_value_ptr_get(tlvs, GTW_DMA_CONFIG_ID); + if (!dma_cfg) + continue; + + /* To be able to retrieve proper DMA config we need to check if + * device_id value (which is alh_id) is equal to device_address. + * They both contain SNDW master id and PDI. If they match then + * proper config is found. + */ + for (uint32_t i = 0; i < dma_cfg->channel_map.device_count; i++) { + if (dma_cfg->channel_map.map[i].device_address == device_id) { + dai->host_dma_config[dma_cfg_idx] = dma_cfg; + return IPC4_SUCCESS; + } + } + } + + return IPC4_INVALID_REQUEST; +} + +void ipc4_audio_format_to_stream_params(const struct ipc4_audio_format *audio_fmt, + struct sof_ipc_stream_params *params) +{ + enum sof_ipc_frame frame_fmt, valid_fmt; + int i; + + memset(params, 0, sizeof(struct sof_ipc_stream_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; + + audio_stream_fmt_conversion(audio_fmt->depth, + audio_fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, + audio_fmt->s_type); + params->frame_fmt = frame_fmt; + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + params->chmap[i] = (audio_fmt->ch_map >> i * 4) & 0xf; +} + +void ipc4_base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, + struct sof_ipc_stream_params *params) +{ + memset(params, 0, sizeof(struct sof_ipc_stream_params)); + params->buffer.size = base_cfg->obs * 2; + + ipc4_audio_format_to_stream_params(&base_cfg->audio_fmt, params); +} +EXPORT_SYMBOL(ipc4_base_module_cfg_to_stream_params); + +void ipc4_update_buffer_format(struct comp_buffer *buf_c, + const struct ipc4_audio_format *fmt) +{ + enum sof_ipc_frame valid_fmt, frame_fmt; + int i; + + audio_stream_set_channels(&buf_c->stream, fmt->channels_count); + audio_stream_set_rate(&buf_c->stream, fmt->sampling_frequency); + audio_stream_fmt_conversion(fmt->depth, + fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, + fmt->s_type); + + audio_stream_set_frm_fmt(&buf_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&buf_c->stream, valid_fmt); + audio_stream_set_buffer_fmt(&buf_c->stream, fmt->interleaving_style); + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + audio_buffer_set_chmap(&buf_c->audio_buffer, i, (fmt->ch_map >> i * 4) & 0xf); + + audio_buffer_set_hw_params_configured(&buf_c->audio_buffer); +} + +void ipc4_update_source_format(struct sof_source *source, + const struct ipc4_audio_format *fmt) +{ + enum sof_ipc_frame valid_fmt, frame_fmt; + + source_set_channels(source, fmt->channels_count); + source_set_rate(source, fmt->sampling_frequency); + audio_stream_fmt_conversion(fmt->depth, + fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, + fmt->s_type); + + source_set_frm_fmt(source, frame_fmt); + source_set_valid_fmt(source, valid_fmt); + source_set_buffer_fmt(source, fmt->interleaving_style); +} +EXPORT_SYMBOL(ipc4_update_source_format); + +void ipc4_update_sink_format(struct sof_sink *sink, + const struct ipc4_audio_format *fmt) +{ + enum sof_ipc_frame valid_fmt, frame_fmt; + + sink_set_channels(sink, fmt->channels_count); + sink_set_rate(sink, fmt->sampling_frequency); + audio_stream_fmt_conversion(fmt->depth, + fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, + fmt->s_type); + + sink_set_frm_fmt(sink, frame_fmt); + sink_set_valid_fmt(sink, valid_fmt); + sink_set_buffer_fmt(sink, fmt->interleaving_style); +} +EXPORT_SYMBOL(ipc4_update_buffer_format); diff --git a/src/ipc/ipc4/logging.c b/src/ipc/ipc4/logging.c new file mode 100644 index 000000000000..b5361ff5944e --- /dev/null +++ b/src/ipc/ipc4/logging.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Kai Vehmanen <kai.vehmanen@linux.intel.com> + +#if CONFIG_LOG_BACKEND_SOF_PROBE && CONFIG_LOG_BACKEND_ADSP_MTRACE +#error Cannot have both backends enabled +#endif + +#include <stdint.h> +#include <sof/boot_test.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/common.h> +#include <ipc4/base_fw.h> +#include <ipc4/error_status.h> +#include <ipc4/logging.h> +#include <rtos/kernel.h> +#if !CONFIG_LIBRARY +#include <zephyr/logging/log.h> +#include <zephyr/logging/log_ctrl.h> +#endif +#if CONFIG_LOG_BACKEND_SOF_PROBE +#include <sof/probe/probe.h> +#endif + +#ifdef CONFIG_LOG_BACKEND_ADSP_MTRACE + +#include <zephyr/logging/log_backend_adsp_mtrace.h> + +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> + +LOG_MODULE_REGISTER(mtrace, CONFIG_SOF_LOG_LEVEL); + +/** + * If mtrace log buffer has less space than + * the threshold, notify host with BUFFER_STATUS IPC4. + */ +#define NOTIFY_BUFFER_STATUS_THRESHOLD 2048 + +/** + * Default aging timer value. This time defines the maximum time to + * block IPC BUFFER STATUS notify messages. The notification is sent + * either due to amount of data available in the buffer, or by timeout + * in case logs are sent at slow rate. + */ +#define IPC4_MTRACE_NOTIFY_AGING_TIMER_MS 1000 + +/** + * Smallest possible aging timer value + */ +#define IPC4_MTRACE_AGING_TIMER_MIN_MS 100 + +static uint64_t mtrace_notify_last_sent; + +static uint32_t mtrace_bytes_pending; + +static uint32_t mtrace_aging_timer = IPC4_MTRACE_NOTIFY_AGING_TIMER_MS; + +#define MTRACE_IPC_CORE PLATFORM_PRIMARY_CORE_ID + +static K_MUTEX_DEFINE(log_mutex); +static struct k_work_delayable log_work; + +static void mtrace_log_hook_unlocked(size_t written, size_t space_left) +{ + uint64_t delta; + + mtrace_bytes_pending += written; + + /* TODO: if hook is called on non-zero core, logs + * maybe lost with too slow aging timer. need to + * figure out a safe way to wake up the mtrace task + * from another core. + */ + if (arch_proc_id() != MTRACE_IPC_CORE) + return; + + delta = k_uptime_get() - mtrace_notify_last_sent; + + if (space_left < NOTIFY_BUFFER_STATUS_THRESHOLD || + delta >= mtrace_aging_timer) { + ipc_send_buffer_status_notify(); + mtrace_notify_last_sent = k_uptime_get(); + mtrace_bytes_pending = 0; + } else if (mtrace_bytes_pending) { + k_work_schedule_for_queue(&ipc_get()->ipc_send_wq, &log_work, + K_MSEC(mtrace_aging_timer - delta)); + } +} + +static void mtrace_log_hook(size_t written, size_t space_left) +{ + k_mutex_lock(&log_mutex, K_FOREVER); + + mtrace_log_hook_unlocked(written, space_left); + + k_mutex_unlock(&log_mutex); +} + +static void log_work_handler(struct k_work *work) +{ + k_mutex_lock(&log_mutex, K_FOREVER); + + if (k_uptime_get() - mtrace_notify_last_sent >= mtrace_aging_timer && + mtrace_bytes_pending) + mtrace_log_hook_unlocked(0, 0); + + k_mutex_unlock(&log_mutex); +} + +static struct k_work_sync ipc4_log_work_sync; + +int ipc4_logging_enable_logs(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ + const struct log_backend *log_backend = log_backend_adsp_mtrace_get(); + const struct ipc4_log_state_info *log_state; + + if (!(first_block && last_block)) { + LOG_ERR("log_state data is expected to be sent as one chunk"); + return -EINVAL; + } + + if (data_offset_or_size < sizeof(struct ipc4_log_state_info)) { + LOG_ERR("log_state too small data size: %u", data_offset_or_size); + return -EINVAL; + } + + dcache_invalidate_region((__sparse_force void __sparse_cache *)data, data_offset_or_size); + + /* + * TODO: support is missing for extended log state info that + * allows to configure logging type + */ + log_state = (const struct ipc4_log_state_info *)data; + + if (log_state->enable) { + uint32_t log_level = LOG_LEVEL_NONE; /* Default if no bits set */ + uint32_t mask = log_state->logs_mask[0]; + + /* TODO: Improve mask handling for better code maintainability + * The logs_mask bits should be defined using proper macros or a struct + * to improve readability and maintainability. Current hardcoded bit + * positions are sufficient for now but should be refactored in the future. + * Possible improvements: + * - Define IPC4_LOG_MASK_* macros for each bit position + * - Create a struct with bitfields for each priority level + * - Add proper documentation in IPC4 specification headers + */ + + /* Determine log level from mask bits 0-4 (priority levels) + * bit 0: critical & error -> LOG_LEVEL_ERR + * bit 1: high & warning -> LOG_LEVEL_WRN + * bit 2: medium -> LOG_LEVEL_INF + * bit 3: low & info -> LOG_LEVEL_INF + * bit 4: verbose & debug -> LOG_LEVEL_DBG + * Check highest bit set to determine maximum log level + */ + if (mask & BIT(4)) + log_level = LOG_LEVEL_DBG; + else if (mask & (BIT(3) | BIT(2))) + log_level = LOG_LEVEL_INF; + else if (mask & BIT(1)) + log_level = LOG_LEVEL_WRN; + else if (mask & BIT(0)) + log_level = LOG_LEVEL_ERR; + + adsp_mtrace_log_init(mtrace_log_hook); + /* Initialize work queue if not already initialized */ + if (!log_work.work.handler) + k_work_init_delayable(&log_work, log_work_handler); + + /* Enable backend with determined log level + * + * Note: If CONFIG_LOG_RUNTIME_FILTERING is not enabled, the log_level + * parameter has no effect - all logs are filtered at compile-time only. + * + * Note: Setting log_level to LOG_LEVEL_NONE will result in no logs being + * output, as all runtime filters will be set to NONE. This behavior will + * be useful in the future when per-source filtering can be specified via + * IPC, allowing selective enabling of specific log sources while keeping + * others disabled. + */ + log_backend_enable(log_backend, mtrace_log_hook, log_level); + + mtrace_aging_timer = log_state->aging_timer_period; + if (mtrace_aging_timer < IPC4_MTRACE_AGING_TIMER_MIN_MS) { + mtrace_aging_timer = IPC4_MTRACE_AGING_TIMER_MIN_MS; + LOG_WRN("Too small aging timer value, limiting to %u\n", + mtrace_aging_timer); + } + + /* Logs enabled, this is the best place to run boot-tests */ + TEST_RUN_ONCE(sof_run_boot_tests); + } else { + /* Flush work queue if initialized */ + if (log_work.work.handler) { + k_work_flush_delayable(&log_work, &ipc4_log_work_sync); + log_work.work.handler = NULL; + } + + adsp_mtrace_log_init(NULL); + /* Disable backend if currently active */ + if (log_backend_is_active(log_backend)) + log_backend_disable(log_backend); + } + + return 0; +} + +#elif CONFIG_LOG_BACKEND_SOF_PROBE + +int ipc4_logging_enable_logs(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ + const struct log_backend *log_backend = log_backend_probe_get(); + const struct ipc4_log_state_info *log_state; + + if (!(first_block && last_block)) + return -EINVAL; + + if (data_offset_or_size < sizeof(struct ipc4_log_state_info)) + return -EINVAL; + + /* Make sure we work on correct ipc data by invalidating cache + * data may be taken from different core to the one we are working + * on right now. + */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)data, data_offset_or_size); + + log_state = (const struct ipc4_log_state_info *)data; + + if (log_state->enable) { + if (!probe_is_backend_configured()) + return -EINVAL; + + log_backend_enable(log_backend, NULL, CONFIG_SOF_LOG_LEVEL); + + } else { + log_backend_disable(log_backend); + } + + return 0; +} + +#else /* unsupported logging method */ + +int ipc4_logging_enable_logs(bool first_block, + bool last_block, + uint32_t data_offset_or_size, + const char *data) +{ + return IPC4_UNKNOWN_MESSAGE_TYPE; +} + +#endif + +int ipc4_logging_shutdown(void) +{ + struct ipc4_log_state_info log_state = { .enable = 0, }; + + return ipc4_logging_enable_logs(true, true, sizeof(log_state), (char *)&log_state); +} diff --git a/src/ipc/ipc4/notification.c b/src/ipc/ipc4/notification.c new file mode 100644 index 000000000000..9fd566ee1f93 --- /dev/null +++ b/src/ipc/ipc4/notification.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Piotr Makaruk <piotr.makaruk@intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <sof/common.h> +#include <sof/ipc/msg.h> +#include <stdbool.h> +#include <ipc4/notification.h> +#include <sof/ipc/notification_pool.h> + +#include <rtos/symbol.h> + +static uint32_t notification_mask = 0xFFFFFFFF; + +static bool is_notif_filtered_out(uint32_t event_type) +{ + uint32_t notif_idx; + + switch (event_type) { + case SOF_IPC4_GATEWAY_UNDERRUN_DETECTED: + notif_idx = IPC4_UNDERRUN_AT_GATEWAY_NOTIFICATION_MASK_IDX; + break; + case SOF_IPC4_MIXER_UNDERRUN_DETECTED: + notif_idx = IPC4_UNDERRUN_AT_MIXER_NOTIFICATION_MASK_IDX; + break; + case SOF_IPC4_GATEWAY_OVERRUN_DETECTED: + notif_idx = IPC4_OVERRUN_AT_GATEWAY_NOTIFICATION_MASK_IDX; + break; + default: + return false; + } + + return (notification_mask & BIT(notif_idx)) == 0; +} + +static bool send_resource_notif(uint32_t resource_id, uint32_t event_type, uint32_t resource_type, + void *data, uint32_t data_size) +{ + struct ipc_msg *msg; + + if (is_notif_filtered_out(event_type)) + return true; //silently ignore + + msg = ipc_notification_pool_get(IPC4_RESOURCE_EVENT_SIZE); + if (!msg) + return false; + + struct ipc4_resource_event_data_notification *notif = msg->tx_data; + union ipc4_notification_header header; + + header.r.notif_type = SOF_IPC4_NOTIFY_RESOURCE_EVENT; + header.r.type = SOF_IPC4_GLB_NOTIFICATION; + header.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + header.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg->header = header.dat; + + notif->resource_id = resource_id; + notif->event_type = event_type; + notif->resource_type = resource_type; + memset(¬if->event_data, 0, sizeof(notif->event_data)); + if (data && data_size) { + int ret = memcpy_s(¬if->event_data, sizeof(notif->event_data), data, data_size); + + if (ret) { + /* Most likely a simple coding mistake: + * Using a data type that is not included in the event_data union. + * Return true to prevent an infinite re-try loop in non-debug builds + */ + assert(false); + return true; + } + } + + ipc_msg_send(msg, msg->tx_data, false); + + return true; +} + +static enum sof_ipc4_resource_event_type dir_to_xrun_event(enum sof_ipc_stream_direction dir) +{ + return (dir == SOF_IPC_STREAM_PLAYBACK) ? SOF_IPC4_GATEWAY_UNDERRUN_DETECTED : + SOF_IPC4_GATEWAY_OVERRUN_DETECTED; +} + +void ipc4_update_notification_mask(uint32_t ntfy_mask, uint32_t enabled_mask) +{ + notification_mask &= enabled_mask | (~ntfy_mask); + notification_mask |= enabled_mask & ntfy_mask; +} + +bool send_copier_gateway_xrun_notif_msg(uint32_t pipeline_id, enum sof_ipc_stream_direction dir) +{ + return send_resource_notif(pipeline_id, dir_to_xrun_event(dir), SOF_IPC4_PIPELINE, NULL, + 0); +} + +bool send_gateway_xrun_notif_msg(uint32_t resource_id, enum sof_ipc_stream_direction dir) +{ + return send_resource_notif(resource_id, dir_to_xrun_event(dir), SOF_IPC4_GATEWAY, NULL, 0); +} + +void send_mixer_underrun_notif_msg(uint32_t resource_id, uint32_t eos_flag, uint32_t data_mixed, + uint32_t expected_data_mixed) +{ + struct ipc4_mixer_underrun_event_data mixer_underrun_data; + + mixer_underrun_data.eos_flag = eos_flag; + mixer_underrun_data.data_mixed = data_mixed; + mixer_underrun_data.expected_data_mixed = expected_data_mixed; + + send_resource_notif(resource_id, SOF_IPC4_MIXER_UNDERRUN_DETECTED, SOF_IPC4_PIPELINE, + &mixer_underrun_data, sizeof(mixer_underrun_data)); +} +EXPORT_SYMBOL(send_mixer_underrun_notif_msg); + +void send_process_data_error_notif_msg(uint32_t resource_id, uint32_t error_code) +{ + struct ipc4_process_data_error_event_data error_data; + + error_data.error_code = error_code; + + send_resource_notif(resource_id, SOF_IPC4_PROCESS_DATA_ERROR, SOF_IPC4_MODULE_INSTANCE, + &error_data, sizeof(error_data)); +} diff --git a/src/ipc/notification_pool.c b/src/ipc/notification_pool.c new file mode 100644 index 000000000000..5894fc499b99 --- /dev/null +++ b/src/ipc/notification_pool.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Adrian Warecki <adrian.warecki@intel.com> +// + +#include <stdint.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/ipc/notification_pool.h> + +#include <rtos/symbol.h> + +#define NOTIFICATION_POOL_MAX_PAYLOAD_SIZE 40 /* IPC4 Resource Event needs 10dw */ +#define NOTIFICATION_POOL_MAX_DEPTH 8 /* Maximum number of notifications + * in the pool + */ + +LOG_MODULE_REGISTER(notification_pool, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(notification_pool); + +DECLARE_TR_CTX(notif_tr, SOF_UUID(notification_pool_uuid), LOG_LEVEL_INFO); + +struct ipc_notif_pool_item { + struct ipc_msg msg; + uint32_t payload[SOF_DIV_ROUND_UP(NOTIFICATION_POOL_MAX_PAYLOAD_SIZE, sizeof(uint32_t))]; +}; + +static struct list_item pool_free_list = LIST_INIT(pool_free_list); +static struct k_spinlock pool_free_list_lock; +static int pool_depth; + +static void ipc_notif_free(struct ipc_msg *msg) +{ + struct ipc_notif_pool_item *item = container_of(msg, struct ipc_notif_pool_item, msg); + k_spinlock_key_t key; + + key = k_spin_lock(&pool_free_list_lock); + list_item_append(&item->msg.list, &pool_free_list); + k_spin_unlock(&pool_free_list_lock, key); +} + +static struct ipc_msg *ipc_notif_new(size_t size) +{ + struct ipc_notif_pool_item *item; + + item = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*item)); + if (!item) { + tr_err(¬if_tr, "Unable to allocate memory for notification message"); + return NULL; + } + + list_init(&item->msg.list); + item->msg.tx_data = item->payload; + item->msg.tx_size = size; + item->msg.callback = ipc_notif_free; + return &item->msg; +} + +struct ipc_msg *ipc_notification_pool_get(size_t size) +{ + struct ipc_notif_pool_item *item; + k_spinlock_key_t key; + struct ipc_msg *new_msg; + + if (size > NOTIFICATION_POOL_MAX_PAYLOAD_SIZE) { + tr_err(¬if_tr, "Requested size %zu exceeds maximum payload size %u", + size, NOTIFICATION_POOL_MAX_PAYLOAD_SIZE); + return NULL; + } + + /* check if we have a free message */ + key = k_spin_lock(&pool_free_list_lock); + if (list_is_empty(&pool_free_list)) { + /* allocate a new message */ + if (pool_depth >= NOTIFICATION_POOL_MAX_DEPTH) { + k_spin_unlock(&pool_free_list_lock, key); + tr_err(¬if_tr, "Pool depth exceeded"); + return NULL; + } + ++pool_depth; + k_spin_unlock(&pool_free_list_lock, key); + + new_msg = ipc_notif_new(size); + if (!new_msg) { + key = k_spin_lock(&pool_free_list_lock); + --pool_depth; + k_spin_unlock(&pool_free_list_lock, key); + } + return new_msg; + } + + /* take the first free message */ + item = list_first_item(&pool_free_list, struct ipc_notif_pool_item, msg.list); + list_item_del(&item->msg.list); + k_spin_unlock(&pool_free_list_lock, key); + + item->msg.tx_size = size; + return &item->msg; +} + +#if CONFIG_LIBRARY +void ipc_notification_pool_free(void) +{ + struct ipc_notif_pool_item *item; + k_spinlock_key_t key; + + key = k_spin_lock(&pool_free_list_lock); + while (!list_is_empty(&pool_free_list)) { + item = list_first_item(&pool_free_list, struct ipc_notif_pool_item, msg.list); + list_item_del(&item->msg.list); + --pool_depth; + k_spin_unlock(&pool_free_list_lock, key); + rfree(item); + key = k_spin_lock(&pool_free_list_lock); + } + k_spin_unlock(&pool_free_list_lock, key); +} +#endif /* CONFIG_LIBRARY */ diff --git a/src/ipc/probe_support.c b/src/ipc/probe_support.c deleted file mode 100644 index 979d5183975d..000000000000 --- a/src/ipc/probe_support.c +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2020 Intel Corporation. All rights reserved. -// -// Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com> - -#include <ipc/info.h> -#include <sof/fw-ready-metadata.h> -#include <sof/compiler_attributes.h> -#include <config.h> - -const struct sof_ipc_probe_support probe_support - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_probe_support), - .type = SOF_IPC_EXT_PROBE_INFO, - }, -#if CONFIG_PROBE - .probe_points_max = CONFIG_PROBE_POINTS_MAX, - .injection_dmas_max = CONFIG_PROBE_DMA_MAX -#endif -}; diff --git a/src/ipc/user_abi_version.c b/src/ipc/user_abi_version.c deleted file mode 100644 index b63c1ea66c37..000000000000 --- a/src/ipc/user_abi_version.c +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2020 Intel Corporation. All rights reserved. -// -// Author: Marcin Maka <marcin.maka@linux.intel.com> - -#include <ipc/info.h> -#include <user/abi_dbg.h> - -const struct sof_ipc_user_abi_version user_abi_version - __attribute__((section(".fw_ready_metadata"))) = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_user_abi_version), - .type = SOF_IPC_EXT_USER_ABI_INFO, - }, - .abi_dbg_version = SOF_ABI_DBG_VERSION, -}; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index d1450f7e6fed..707753635f69 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,23 +1,35 @@ # SPDX-License-Identifier: BSD-3-Clause -if(BUILD_LIBRARY) - add_local_sources(sof - lib.c - notifier.c) - return() +set(common_files notifier.c dma.c dai.c objpool.c) + +if(CONFIG_LIBRARY) + add_local_sources(sof + lib.c + agent.c + ${common_files} + ) + return() endif() if(CONFIG_HAVE_AGENT) - add_local_sources(sof agent.c) + add_local_sources(sof agent.c) +endif() + +if(CONFIG_AMS) + add_local_sources(sof ams.c) +endif() + +if(CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL) + add_local_sources(sof cpu-clk-manager.c) endif() -add_local_sources(sof - lib.c - alloc.c - notifier.c - pm_runtime.c - clk.c - dma.c - dai.c - wait.c -) +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + add_local_sources(sof ${common_files}) + + if(NOT CONFIG_SOF_ZEPHYR_NO_SOF_CLOCK) + add_local_sources(sof clk.c) + endif() + +endif() diff --git a/src/lib/agent.c b/src/lib/agent.c index 5c53a523e45e..1030e88dd7f2 100644 --- a/src/lib/agent.c +++ b/src/lib/agent.c @@ -13,32 +13,52 @@ * called. */ -#include <sof/drivers/timer.h> +#include <rtos/timer.h> #include <sof/lib/agent.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/memory.h> #include <sof/lib/uuid.h> -#include <sof/debug/panic.h> +#include <rtos/panic.h> #include <sof/platform.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> +#include <rtos/task.h> +#include <rtos/sof.h> #include <sof/trace/trace.h> #include <ipc/topology.h> #include <ipc/trace.h> #include <user/trace.h> +#include <limits.h> +#include <stdbool.h> #include <stddef.h> #include <stdint.h> +#include <rtos/kernel.h> -#define trace_sa(__e, ...) \ - trace_event_atomic(TRACE_CLASS_SA, __e, ##__VA_ARGS__) -#define trace_sa_error(__e, ...) \ - trace_error(TRACE_CLASS_SA, __e, ##__VA_ARGS__) +LOG_MODULE_REGISTER(sa, CONFIG_SOF_LOG_LEVEL); -/* c63c4e75-8f61-4420-9319-1395932efa9e */ -DECLARE_SOF_UUID("agent-work", agent_work_task_uuid, 0xc63c4e75, 0x8f61, 0x4420, - 0x93, 0x19, 0x13, 0x95, 0x93, 0x2e, 0xfa, 0x9e); +SOF_DEFINE_REG_UUID(sa); + +DECLARE_TR_CTX(sa_tr, SOF_UUID(sa_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(agent_work); + +#if CONFIG_PERFORMANCE_COUNTERS +static void perf_sa_trace(struct perf_cnt_data *pcd, int ignored) +{ + tr_info(&sa_tr, "perf sys_load peak plat %u cpu %u", + (uint32_t)((pcd)->plat_delta_peak), + (uint32_t)((pcd)->cpu_delta_peak)); +} + +static void perf_avg_sa_trace(struct perf_cnt_data *pcd, int ignored) +{ + tr_info(&sa_tr, "perf sys_load cpu avg %u (current peak %u)", + (uint32_t)((pcd)->cpu_delta_sum), + (uint32_t)((pcd)->cpu_delta_peak)); +} + +#endif static enum task_state validate(void *data) { @@ -46,19 +66,26 @@ static enum task_state validate(void *data) uint64_t current; uint64_t delta; - current = platform_timer_get(timer_get()); + current = sof_cycle_get_64(); delta = current - sa->last_check; - perf_cnt_stamp(TRACE_CLASS_SA, &sa->pcd, true); + perf_cnt_stamp(&sa->pcd, perf_sa_trace, 0 /* ignored */); + perf_cnt_average(&sa->pcd, perf_avg_sa_trace, 0 /* ignored */); +#if CONFIG_AGENT_PANIC_ON_DELAY /* panic timeout */ - if (delta > sa->panic_timeout) - panic(SOF_IPC_PANIC_IDLE); + if (sa->panic_on_delay && delta > sa->panic_timeout) + sof_panic(SOF_IPC_PANIC_IDLE); +#endif /* warning timeout */ - if (delta > sa->warn_timeout) - trace_sa_error("validate(), ll drift detected, delta = " - "%u", delta); + if (delta > sa->warn_timeout) { + if (delta > UINT_MAX) + tr_warn(&sa_tr, "ll drift detected, delta > %u", UINT_MAX); + else + tr_warn(&sa_tr, "ll drift detected, delta = %u", + (unsigned int)delta); + } /* update last_check to current */ sa->last_check = current; @@ -70,27 +97,45 @@ void sa_init(struct sof *sof, uint64_t timeout) { uint64_t ticks; - trace_sa("sa_init(), timeout = %u", timeout); + if (timeout > UINT_MAX) + tr_warn(&sa_tr, "timeout > %u", UINT_MAX); + else + tr_info(&sa_tr, "timeout = %u", (unsigned int)timeout); - sof->sa = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(*sof->sa)); + sof->sa = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*sof->sa)); /* set default timeouts */ - ticks = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * timeout / 1000; + ticks = k_us_to_cyc_ceil64(timeout); /* TODO: change values after minimal drifts will be assured */ sof->sa->panic_timeout = 2 * ticks; /* 100% delay */ sof->sa->warn_timeout = ticks + ticks / 20; /* 5% delay */ - trace_sa("sa_init(), ticks = %u, sof->sa->warn_timeout = %u, sof->sa->panic_timeout = %u", - ticks, sof->sa->warn_timeout, sof->sa->panic_timeout); + atomic_init(&sof->sa->panic_cnt, 0); + sof->sa->panic_on_delay = true; - schedule_task_init_ll(&sof->sa->work, SOF_UUID(agent_work_task_uuid), + if (ticks > UINT_MAX || sof->sa->warn_timeout > UINT_MAX || + sof->sa->panic_timeout > UINT_MAX) + tr_info(&sa_tr, + "some of the values are > %u", UINT_MAX); + else + tr_info(&sa_tr, + "ticks = %u, sof->sa->warn_timeout = %u, sof->sa->panic_timeout = %u", + (unsigned int)ticks, (unsigned int)sof->sa->warn_timeout, + (unsigned int)sof->sa->panic_timeout); + + schedule_task_init_ll(&sof->sa->work, SOF_UUID(agent_work_uuid), SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_HIGH, validate, sof->sa, 0, 0); schedule_task(&sof->sa->work, 0, timeout); /* set last check time to now to give time for boot completion */ - sof->sa->last_check = platform_timer_get(timer_get()); + sof->sa->last_check = sof_cycle_get_64(); + +} + +void sa_exit(struct sof *sof) +{ + schedule_task_cancel(&sof->sa->work); } diff --git a/src/lib/alloc.c b/src/lib/alloc.c index 2c0c00723e29..aa7edeea95fd 100644 --- a/src/lib/alloc.c +++ b/src/lib/alloc.c @@ -5,951 +5,37 @@ // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> // Keyon Jie <yang.jie@linux.intel.com> -#include <sof/debug/panic.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/cpu.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/spinlock.h> -#include <sof/string.h> -#include <ipc/topology.h> -#include <ipc/trace.h> -#include <config.h> +#include <rtos/alloc.h> +#include <sof/lib/mm_heap.h> + #include <errno.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> +#include <stdlib.h> -/* debug to set memory value on every allocation */ -#if CONFIG_DEBUG_BLOCK_FREE -#define DEBUG_BLOCK_FREE_VALUE_8BIT ((uint8_t)0xa5) -#define DEBUG_BLOCK_FREE_VALUE_32BIT ((uint32_t)0xa5a5a5a5) -#endif - -/* We have 3 memory pools - * - * 1) System memory pool does not have a map and it's size is fixed at build - * time. Memory cannot be freed from this pool. Used by device drivers - * and any system core. Saved as part of PM context. - * 2) Runtime memory pool has variable size allocation map and memory is freed - * on calls to rfree(). Saved as part of PM context. Global size - * set at build time. - * 3) Buffer memory pool has fixed size allocation map and can be freed on - * module removal or calls to rfree(). Saved as part of PM context. - */ - -#if CONFIG_DEBUG_BLOCK_FREE -/* Check whole memory region for debug pattern to find if memory was freed - * second time - */ -static void validate_memory(void *ptr, size_t size) -{ - uint32_t *ptr_32 = ptr; - int i, not_matching = 0; - - for (i = 0; i < size / 4; i++) { - if (ptr_32[i] != DEBUG_BLOCK_FREE_VALUE_32BIT) - not_matching = 1; - } - - if (not_matching) { - trace_mem_init("validate_memory() pointer:" - "%p freed pattern not detected", - (uintptr_t)ptr); - } else { - trace_mem_error( - "validate_memory() freeing pointer:" - "%p double free detected", - (uintptr_t)ptr); - } -} -#endif - -/* total size of block */ -static inline uint32_t block_get_size(struct block_map *map) -{ - uint32_t size = sizeof(*map) + map->count * - (map->block_size + sizeof(struct block_hdr)); - - platform_shared_commit(map, sizeof(*map)); - - return size; -} - -/* total size of heap */ -static inline uint32_t heap_get_size(struct mm_heap *heap) -{ - uint32_t size = sizeof(struct mm_heap); - int i; - - for (i = 0; i < heap->blocks; i++) - size += block_get_size(&heap->map[i]); - - platform_shared_commit(heap, sizeof(*heap)); - - return size; -} - -#if CONFIG_DEBUG_BLOCK_FREE -static void write_pattern(struct mm_heap *heap_map, int heap_depth, - uint8_t pattern) -{ - struct mm_heap *heap; - struct block_map *current_map; - int i, j; - - for (i = 0; i < heap_depth; i++) { - heap = &heap_map[i]; - - for (j = 0; j < heap->blocks; j++) { - current_map = &heap->map[j]; - memset( - (void *)current_map->base, pattern, - current_map->count * current_map->block_size); - platform_shared_commit(current_map, - sizeof(*current_map)); - } - - platform_shared_commit(heap, sizeof(*heap)); - } -} -#endif - -static void init_heap_map(struct mm_heap *heap, int count) -{ - struct block_map *next_map; - struct block_map *current_map; - int i; - int j; - - for (i = 0; i < count; i++) { - /* init the map[0] */ - current_map = &heap[i].map[0]; - current_map->base = heap[i].heap; - platform_shared_commit(current_map, sizeof(*current_map)); - - /* map[j]'s base is calculated based on map[j-1] */ - for (j = 1; j < heap[i].blocks; j++) { - next_map = &heap[i].map[j]; - next_map->base = current_map->base + - current_map->block_size * - current_map->count; - platform_shared_commit(next_map, sizeof(*next_map)); - platform_shared_commit(current_map, - sizeof(*current_map)); - - current_map = &heap[i].map[j]; - } - - platform_shared_commit(&heap[i], sizeof(heap[i])); - } -} - -/* allocate from system memory pool */ -static void *rmalloc_sys(uint32_t flags, int caps, int core, size_t bytes) -{ - struct mm *memmap = memmap_get(); - void *ptr; - struct mm_heap *cpu_heap; - size_t alignment = 0; - - /* use the heap dedicated for the selected core */ - cpu_heap = memmap->system + core; - if ((cpu_heap->caps & caps) != caps) - panic(SOF_IPC_PANIC_MEM); - - /* align address to dcache line size */ - if (cpu_heap->info.used % PLATFORM_DCACHE_ALIGN) - alignment = PLATFORM_DCACHE_ALIGN - - (cpu_heap->info.used % PLATFORM_DCACHE_ALIGN); - - /* always succeeds or panics */ - if (alignment + bytes > cpu_heap->info.free) { - trace_mem_error("rmalloc_sys() error: core = %d, bytes = %d", - core, bytes); - panic(SOF_IPC_PANIC_MEM); - } - cpu_heap->info.used += alignment; - - ptr = (void *)(cpu_heap->heap + cpu_heap->info.used); - - cpu_heap->info.used += bytes; - cpu_heap->info.free -= alignment + bytes; - - if (flags & SOF_MEM_FLAG_SHARED) - ptr = platform_shared_get(ptr, bytes); - - platform_shared_commit(cpu_heap, sizeof(*cpu_heap)); - platform_shared_commit(memmap, sizeof(*memmap)); - - return ptr; -} - -/* At this point the pointer we have should be unaligned - * (it was checked level higher) and be power of 2 - */ -static void *align_ptr(struct mm_heap *heap, uint32_t alignment, - void *ptr, struct block_hdr *hdr) -{ - int mod_align = 0; - - /* Save unaligned ptr to block hdr */ - hdr->unaligned_ptr = ptr; - - /* If ptr is not already aligned we calculate alignment shift */ - if (alignment && (uintptr_t)ptr % alignment) - mod_align = alignment - ((uintptr_t)ptr % alignment); - - /* Calculate aligned pointer */ - ptr = (char *)ptr + mod_align; - - return ptr; -} - -/* allocate single block */ -static void *alloc_block(struct mm_heap *heap, int level, - uint32_t caps, uint32_t alignment) -{ - struct block_map *map = &heap->map[level]; - struct block_hdr *hdr; - void *ptr; - int i; - - hdr = &map->block[map->first_free]; - - map->free_count--; - ptr = (void *)(map->base + map->first_free * map->block_size); - ptr = align_ptr(heap, alignment, ptr, hdr); - - hdr->size = 1; - hdr->used = 1; - - heap->info.used += map->block_size; - heap->info.free -= map->block_size; - - /* find next free */ - for (i = map->first_free; i < map->count; ++i) { - hdr = &map->block[i]; - - if (hdr->used == 0) { - map->first_free = i; - break; - } - } - - platform_shared_commit(map->block, sizeof(*map->block) * map->count); - platform_shared_commit(map, sizeof(*map)); - platform_shared_commit(heap, sizeof(*heap)); - - return ptr; -} - -/* allocates continuous blocks */ -static void *alloc_cont_blocks(struct mm_heap *heap, int level, - uint32_t caps, size_t bytes, uint32_t alignment) -{ - struct block_map *map = &heap->map[level]; - struct block_hdr *hdr; - void *ptr = NULL; - void *unaligned_ptr; - unsigned int start = map->first_free; - unsigned int current; - unsigned int count = bytes / map->block_size; - unsigned int remaining = 0; - - if (bytes % map->block_size) - count++; - - /* check if we have enough consecutive blocks for requested - * allocation size. - */ - for (current = map->first_free; current < map->count && - remaining < count; current++) { - hdr = &map->block[current]; - - if (hdr->used) - remaining = 0;/* used, not suitable, reset */ - else if (!remaining++) - start = current;/* new start */ - } - - if (count > map->count || remaining < count) { - trace_mem_error("error: %d blocks needed for allocation " - "but only %d blocks are remaining", - count, remaining); - goto out; - } - - /* we found enough space, let's allocate it */ - map->free_count -= count; - ptr = (void *)(map->base + start * map->block_size); - unaligned_ptr = ptr; - - hdr = &map->block[start]; - hdr->size = count; - - ptr = align_ptr(heap, alignment, ptr, hdr); +void *aligned_alloc(size_t alignment, size_t size); +void free_heap(void); - heap->info.used += count * map->block_size; - heap->info.free -= count * map->block_size; - /* update first_free if needed */ - if (map->first_free == start) - /* find first available free block */ - for (map->first_free += count; map->first_free < map->count; - map->first_free++) { - hdr = &map->block[map->first_free]; - - if (!hdr->used) - break; - } - - /* update each block */ - for (current = start; current < start + count; current++) { - hdr = &map->block[current]; - hdr->used = 1; - hdr->unaligned_ptr = unaligned_ptr; - } - -out: - platform_shared_commit(map->block, sizeof(*map->block) * map->count); - platform_shared_commit(map, sizeof(*map)); - platform_shared_commit(heap, sizeof(*heap)); - - return ptr; -} - -static struct mm_heap *get_heap_from_ptr(void *ptr) -{ - struct mm *memmap = memmap_get(); - struct mm_heap *heap; - int i; - - /* find mm_heap that ptr belongs to */ - heap = memmap->system_runtime + cpu_get_id(); - if ((uint32_t)ptr >= heap->heap && - (uint32_t)ptr < heap->heap + heap->size) - goto out; - - platform_shared_commit(heap, sizeof(*heap)); - - for (i = 0; i < PLATFORM_HEAP_RUNTIME; i++) { - heap = &memmap->runtime[i]; - - if ((uint32_t)ptr >= heap->heap && - (uint32_t)ptr < heap->heap + heap->size) - goto out; - - platform_shared_commit(heap, sizeof(*heap)); - } - - for (i = 0; i < PLATFORM_HEAP_BUFFER; i++) { - heap = &memmap->buffer[i]; - - if ((uint32_t)ptr >= heap->heap && - (uint32_t)ptr < heap->heap + heap->size) - goto out; - - platform_shared_commit(heap, sizeof(*heap)); - } - - platform_shared_commit(memmap, sizeof(*memmap)); - - return NULL; - -out: - platform_shared_commit(heap, sizeof(*heap)); - platform_shared_commit(memmap, sizeof(*memmap)); - - return heap; -} - -static struct mm_heap *get_heap_from_caps(struct mm_heap *heap, int count, - uint32_t caps) -{ - uint32_t mask; - int i; - - /* find first heap that support type */ - for (i = 0; i < count; i++) { - mask = heap[i].caps & caps; - platform_shared_commit(&heap[i], sizeof(heap[i])); - if (mask == caps) - return &heap[i]; - } - - return NULL; -} - -static void *get_ptr_from_heap(struct mm_heap *heap, uint32_t flags, - uint32_t caps, size_t bytes, uint32_t alignment) -{ - struct block_map *map; - int i, temp_bytes = bytes; - void *ptr = NULL; - - /* Only allow alignment as a power of 2 */ - if ((alignment & (alignment - 1)) != 0) - panic(SOF_IPC_PANIC_MEM); - - for (i = 0; i < heap->blocks; i++) { - map = &heap->map[i]; - - /* size of requested buffer is adjusted for alignment purposes - * we check if first free block is already aligned if not - * we need to allocate bigger size for alignment - */ - if (alignment && - ((map->base + (map->block_size * map->first_free)) % - alignment)) - temp_bytes += alignment; - - /* is block big enough */ - if (map->block_size < temp_bytes) { - platform_shared_commit(map, sizeof(*map)); - temp_bytes = bytes; - continue; - } - - /* does block have free space */ - if (map->free_count == 0) { - platform_shared_commit(map, sizeof(*map)); - temp_bytes = bytes; - continue; - } - - /* free block space exists */ - ptr = alloc_block(heap, i, caps, alignment); - - platform_shared_commit(map, sizeof(*map)); - - break; - } - - if (ptr && (flags & SOF_MEM_FLAG_SHARED)) - ptr = platform_shared_get(ptr, bytes); - - return ptr; -} - -/* free block(s) */ -static void free_block(void *ptr) -{ - struct mm_heap *heap; - struct block_map *block_map = NULL; - struct block_hdr *hdr; - int i; - int block; - int used_blocks; - bool heap_is_full; - - heap = get_heap_from_ptr(ptr); - if (!heap) { - trace_mem_error("free_block() error: invalid heap = %p, cpu = %d", - (uintptr_t)ptr, cpu_get_id()); - return; - } - - /* find block that ptr belongs to */ - for (i = 0; i < heap->blocks; i++) { - block_map = &heap->map[i]; - - /* is ptr in this block */ - if ((uint32_t)ptr < (block_map->base + - (block_map->block_size * block_map->count))) - break; - - platform_shared_commit(block_map, sizeof(*block_map)); - } - - if (i == heap->blocks) { - platform_shared_commit(heap, sizeof(*heap)); - - /* not found */ - trace_mem_error("free_block() error: invalid ptr = %p cpu = %d", - (uintptr_t)ptr, cpu_get_id()); - return; - } - - /* calculate block header */ - block = ((uint32_t)ptr - block_map->base) / block_map->block_size; - - hdr = &block_map->block[block]; - - /* bring back original unaligned pointer position - * and calculate correct hdr for free operation (it could - * be from different block since we got user pointer here - * or null if header was not set) - */ - if (hdr->unaligned_ptr != ptr && hdr->unaligned_ptr) { - ptr = hdr->unaligned_ptr; - block = ((uint32_t)ptr - block_map->base) - / block_map->block_size; - hdr = &block_map->block[block]; - } - - /* report an error if ptr is not aligned to block */ - if (block_map->base + block_map->block_size * block != (uint32_t)ptr) - panic(SOF_IPC_PANIC_MEM); - - heap_is_full = !block_map->free_count; - - /* free block header and continuous blocks */ - used_blocks = block + hdr->size; - - for (i = block; i < used_blocks; i++) { - hdr = &block_map->block[i]; - hdr->size = 0; - hdr->used = 0; - hdr->unaligned_ptr = NULL; - block_map->free_count++; - heap->info.used -= block_map->block_size; - heap->info.free += block_map->block_size; - } - - /* set first free block */ - if (block < block_map->first_free || heap_is_full) - block_map->first_free = block; - -#if CONFIG_DEBUG_BLOCK_FREE - /* memset the whole block in case of unaligned ptr */ - validate_memory( - (void *)(block_map->base + block_map->block_size * block), - block_map->block_size * (i - block)); - memset( - (void *)(block_map->base + block_map->block_size * block), - DEBUG_BLOCK_FREE_VALUE_8BIT, block_map->block_size * - (i - block)); -#endif - - platform_shared_commit(block_map->block, sizeof(*block_map->block) * - block_map->count); - platform_shared_commit(block_map, sizeof(*block_map)); - platform_shared_commit(heap, sizeof(*heap)); -} - -#if CONFIG_DEBUG_HEAP - -static void trace_heap_blocks(struct mm_heap *heap) +void *rmalloc(uint32_t flags, size_t bytes) { - struct block_map *block_map; - int i; - - trace_mem_error("heap: 0x%x size %d blocks %d caps 0x%x", heap->heap, - heap->size, heap->blocks, heap->caps); - trace_mem_error(" used %d free %d", heap->info.used, - heap->info.free); - - for (i = 0; i < heap->blocks; i++) { - block_map = &heap->map[i]; - - trace_mem_error(" block %d base 0x%x size %d count %d", i, - block_map->base, block_map->block_size, - block_map->count); - trace_mem_error(" free %d first at %d", - block_map->free_count, block_map->first_free); - - platform_shared_commit(block_map, sizeof(*block_map)); - } - - platform_shared_commit(heap, sizeof(*heap)); + return malloc(bytes); } -static void alloc_trace_heap(enum mem_zone zone, uint32_t caps, size_t bytes, - struct mm_heap *heap_base, - unsigned int heap_count) +void *rzalloc(uint32_t flags, size_t bytes) { - struct mm_heap *heap = heap_base; - unsigned int n = heap_count; - unsigned int i = 0; - int count = 0; - - while (i < heap_count) { - heap = get_heap_from_caps(heap, n, caps); - if (!heap) - break; - - trace_heap_blocks(heap); - count++; - i = heap - heap_base + 1; - n = heap_count - i; - heap++; - } - - if (count == 0) - trace_mem_error("heap: none found for zone %d caps 0x%x, " - "bytes 0x%x", zone, caps, bytes); + return calloc(bytes, 1); } -void alloc_trace_runtime_heap(uint32_t caps, size_t bytes) +void *rballoc_align(uint32_t flags, size_t bytes, + uint32_t alignment) { - struct mm *memmap = memmap_get(); - - /* check runtime heap for capabilities */ - trace_mem_init("heap: using runtime"); - - alloc_trace_heap(SOF_MEM_ZONE_RUNTIME, caps, bytes, - memmap->runtime, PLATFORM_HEAP_RUNTIME); - - platform_shared_commit(memmap, sizeof(*memmap)); -} - -void alloc_trace_buffer_heap(uint32_t caps, size_t bytes) -{ - struct mm *memmap = memmap_get(); - - /* check buffer heap for capabilities */ - trace_mem_init("heap: using buffer"); - - alloc_trace_heap(RZONE_BUFFER, caps, bytes, memmap->buffer, - PLATFORM_HEAP_BUFFER); - - platform_shared_commit(memmap, sizeof(*memmap)); -} - -#endif - -/* allocate single block for system runtime */ -static void *rmalloc_sys_runtime(uint32_t flags, int caps, int core, - size_t bytes) -{ - struct mm *memmap = memmap_get(); - struct mm_heap *cpu_heap; - void *ptr; - - /* use the heap dedicated for the selected core */ - cpu_heap = memmap->system_runtime + core; - if ((cpu_heap->caps & caps) != caps) - panic(SOF_IPC_PANIC_MEM); - - ptr = get_ptr_from_heap(cpu_heap, flags, caps, bytes, - PLATFORM_DCACHE_ALIGN); - - platform_shared_commit(cpu_heap, sizeof(*cpu_heap)); - platform_shared_commit(memmap, sizeof(*memmap)); - - return ptr; -} - -/* allocate single block for runtime */ -static void *rmalloc_runtime(uint32_t flags, uint32_t caps, size_t bytes) -{ - struct mm *memmap = memmap_get(); - struct mm_heap *heap; - - /* check runtime heap for capabilities */ - heap = get_heap_from_caps(memmap->runtime, PLATFORM_HEAP_RUNTIME, caps); - if (!heap) { - /* next check buffer heap for capabilities */ - heap = get_heap_from_caps(memmap->buffer, PLATFORM_HEAP_BUFFER, - caps); - if (!heap) { - platform_shared_commit(memmap, sizeof(*memmap)); - - trace_mem_error("rmalloc_runtime() error: caps = %x, bytes = %d", - caps, bytes); - - return NULL; - } - } - - platform_shared_commit(memmap, sizeof(*memmap)); - - return get_ptr_from_heap(heap, flags, caps, bytes, - PLATFORM_DCACHE_ALIGN); -} - -static void *_malloc_unlocked(enum mem_zone zone, uint32_t flags, uint32_t caps, - size_t bytes) -{ - struct mm *memmap = memmap_get(); - void *ptr = NULL; - - switch (zone) { - case SOF_MEM_ZONE_SYS: - ptr = rmalloc_sys(flags, caps, cpu_get_id(), bytes); - break; - case SOF_MEM_ZONE_SYS_RUNTIME: - ptr = rmalloc_sys_runtime(flags, caps, cpu_get_id(), bytes); - break; - case SOF_MEM_ZONE_RUNTIME: - ptr = rmalloc_runtime(flags, caps, bytes); - break; - default: - trace_mem_error("rmalloc() error: invalid zone"); - panic(SOF_IPC_PANIC_MEM); /* logic non recoverable problem */ - break; - } - -#if CONFIG_DEBUG_BLOCK_FREE - if (ptr) - bzero(ptr, bytes); -#endif - - memmap->heap_trace_updated = 1; - - platform_shared_commit(memmap, sizeof(*memmap)); - - return ptr; -} - -/* allocates memory - not for direct use, clients use rmalloc() */ -void *_malloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - struct mm *memmap = memmap_get(); - uint32_t lock_flags; - void *ptr = NULL; - - spin_lock_irq(&memmap->lock, lock_flags); - - ptr = _malloc_unlocked(zone, flags, caps, bytes); - - spin_unlock_irq(&memmap->lock, lock_flags); - - return ptr; -} - -/* allocates and clears memory - not for direct use, clients use rzalloc() */ -void *_zalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - void *ptr; - - ptr = _malloc(zone, flags, caps, bytes); - if (ptr) - bzero(ptr, bytes); - - return ptr; -} - -void *rzalloc_core_sys(int core, size_t bytes) -{ - struct mm *memmap = memmap_get(); - uint32_t flags; - void *ptr = NULL; - - spin_lock_irq(&memmap->lock, flags); - - ptr = rmalloc_sys(0, 0, core, bytes); - if (ptr) - bzero(ptr, bytes); - - spin_unlock_irq(&memmap->lock, flags); - - return ptr; -} - -/* allocates continuous buffers - not for direct use, clients use rballoc() */ -static void *alloc_heap_buffer(struct mm_heap *heap, uint32_t flags, - uint32_t caps, size_t bytes, uint32_t alignment) -{ - struct block_map *map; - int i, temp_bytes = bytes; - void *ptr = NULL; - - /* Only allow alignment as a power of 2 */ - if ((alignment & (alignment - 1)) != 0) - panic(SOF_IPC_PANIC_MEM); - - /* will request fit in single block */ - for (i = 0; i < heap->blocks; i++) { - map = &heap->map[i]; - - /* size of requested buffer is adjusted for alignment purposes - * we check if first free block is already aligned if not - * we need to allocate bigger size for alignment - */ - if ((map->base + (map->block_size * map->first_free)) - % alignment) - temp_bytes += alignment; - - /* Check if blocks are big enough and at least one is free */ - if (map->block_size >= temp_bytes && map->free_count) { - platform_shared_commit(map, sizeof(*map)); - - /* found: grab a block */ - ptr = alloc_block(heap, i, caps, alignment); - break; - } - temp_bytes = bytes; - - platform_shared_commit(map, sizeof(*map)); - } - - /* size of requested buffer is adjusted for alignment purposes - * since we span more blocks we have to assume worst case scenario - */ - bytes += alignment; - - /* request spans > 1 block */ - if (!ptr) { - /* - * Find the best block size for request. We know, that we failed - * to find a single large enough block, so, skip those. - */ - for (i = heap->blocks - 1; i >= 0; i--) { - map = &heap->map[i]; - - /* allocate if block size is smaller than request */ - if (heap->size >= bytes && map->block_size < bytes) { - ptr = alloc_cont_blocks(heap, i, caps, - bytes, alignment); - if (ptr) { - platform_shared_commit(map, - sizeof(*map)); - break; - } - } - - platform_shared_commit(map, sizeof(*map)); - } - } - - if (ptr && (flags & SOF_MEM_FLAG_SHARED)) - ptr = platform_shared_get(ptr, bytes); - -#if CONFIG_DEBUG_BLOCK_FREE - if (ptr) - bzero(ptr, temp_bytes); -#endif - - platform_shared_commit(heap, sizeof(*heap)); - - return ptr; -} - -static void *_balloc_unlocked(uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment) -{ - struct mm *memmap = memmap_get(); - struct mm_heap *heap; - unsigned int i, n; - void *ptr = NULL; - - for (i = 0, n = PLATFORM_HEAP_BUFFER, heap = memmap->buffer; - i < PLATFORM_HEAP_BUFFER; - i = heap - memmap->buffer + 1, n = PLATFORM_HEAP_BUFFER - i, - heap++) { - heap = get_heap_from_caps(heap, n, caps); - if (!heap) - break; - - ptr = alloc_heap_buffer(heap, flags, caps, bytes, alignment); - if (ptr) - break; - - /* Continue from the next heap */ - } - - platform_shared_commit(memmap, sizeof(*memmap)); - - return ptr; -} - -/* allocates continuous buffers - not for direct use, clients use rballoc() */ -void *_balloc(uint32_t flags, uint32_t caps, size_t bytes, uint32_t alignment) -{ - struct mm *memmap = memmap_get(); - void *ptr = NULL; - uint32_t lock_flags; - - spin_lock_irq(&memmap->lock, lock_flags); - - ptr = _balloc_unlocked(flags, caps, bytes, alignment); - - spin_unlock_irq(&memmap->lock, lock_flags); - - return ptr; -} - -static void _rfree_unlocked(void *ptr) -{ - struct mm *memmap = memmap_get(); - struct mm_heap *cpu_heap; - - /* sanity check - NULL ptrs are fine */ - if (!ptr) - return; - - /* prepare pointer if it's platform requirement */ - ptr = platform_rfree_prepare(ptr); - - /* use the heap dedicated for the selected core */ - cpu_heap = memmap->system + cpu_get_id(); - - /* panic if pointer is from system heap */ - if (ptr >= (void *)cpu_heap->heap && - (char *)ptr < (char *)cpu_heap->heap + cpu_heap->size) { - trace_mem_error("rfree() error: attempt to free system heap = %p, cpu = %d", - (uintptr_t)ptr, cpu_get_id()); - panic(SOF_IPC_PANIC_MEM); - } - - /* free the block */ - free_block(ptr); - memmap->heap_trace_updated = 1; - - platform_shared_commit(cpu_heap, sizeof(*cpu_heap)); - platform_shared_commit(memmap, sizeof(*memmap)); + return aligned_alloc(alignment, bytes); } void rfree(void *ptr) { - struct mm *memmap = memmap_get(); - uint32_t flags; - - spin_lock_irq(&memmap->lock, flags); - _rfree_unlocked(ptr); - spin_unlock_irq(&memmap->lock, flags); -} - -void *_realloc(void *ptr, enum mem_zone zone, uint32_t flags, uint32_t caps, - size_t bytes) -{ - struct mm *memmap = memmap_get(); - void *new_ptr = NULL; - uint32_t lock_flags; - - if (!bytes) - return new_ptr; - - spin_lock_irq(&memmap->lock, lock_flags); - - new_ptr = _malloc_unlocked(zone, flags, caps, bytes); - - if (new_ptr && ptr) - memcpy_s(new_ptr, bytes, ptr, bytes); - - if (new_ptr) - _rfree_unlocked(ptr); - - spin_unlock_irq(&memmap->lock, lock_flags); - - return new_ptr; -} - -void *_brealloc(void *ptr, uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment) -{ - struct mm *memmap = memmap_get(); - void *new_ptr = NULL; - uint32_t lock_flags; - - if (!bytes) - return new_ptr; - - spin_lock_irq(&memmap->lock, lock_flags); - - new_ptr = _balloc_unlocked(flags, caps, bytes, alignment); - - if (new_ptr && ptr) - memcpy_s(new_ptr, bytes, ptr, bytes); - - if (new_ptr) - _rfree_unlocked(ptr); - - spin_unlock_irq(&memmap->lock, lock_flags); - - return new_ptr; + free(ptr); } /* TODO: all mm_pm_...() routines to be implemented for IMR storage */ @@ -958,127 +44,29 @@ uint32_t mm_pm_context_size(void) return 0; } -/* - * Save the DSP memories that are in use the system and modules. - * All pipeline and modules must be disabled before calling this functions. - * No allocations are permitted after calling this and before calling restore. - */ -int mm_pm_context_save(struct dma_copy *dc, struct dma_sg_config *sg) +void free_heap(void) { - return -ENOTSUP; } -/* - * Restore the DSP memories to modules and the system. - * This must be called immediately after booting before any pipeline work. - */ -int mm_pm_context_restore(struct dma_copy *dc, struct dma_sg_config *sg) -{ - return -ENOTSUP; -} - -void free_heap(enum mem_zone zone) +/* initialise map */ +void init_heap(struct sof *sof) { - struct mm *memmap = memmap_get(); - struct mm_heap *cpu_heap; - - /* to be called by slave cores only for sys heap, - * otherwise this is critical flow issue. - */ - if (cpu_get_id() == PLATFORM_MASTER_CORE_ID || - zone != SOF_MEM_ZONE_SYS) { - trace_mem_error("free_heap() error: critical flow issue"); - panic(SOF_IPC_PANIC_MEM); - } - - cpu_heap = memmap->system + cpu_get_id(); - cpu_heap->info.used = 0; - cpu_heap->info.free = cpu_heap->size; - - platform_shared_commit(cpu_heap, sizeof(*cpu_heap)); - platform_shared_commit(memmap, sizeof(*memmap)); } -#if CONFIG_TRACE -void heap_trace(struct mm_heap *heap, int size) +#if CONFIG_DEBUG_MEMORY_USAGE_SCAN +int heap_info(int index, struct mm_info *out) { - struct block_map *current_map; - int i; - int j; - - for (i = 0; i < size; i++) { - trace_mem_init(" heap: 0x%x size %d blocks %d caps 0x%x", - heap->heap, heap->size, heap->blocks, - heap->caps); - trace_mem_init(" used %d free %d", heap->info.used, - heap->info.free); - - /* map[j]'s base is calculated based on map[j-1] */ - for (j = 1; j < heap->blocks; j++) { - current_map = &heap->map[j]; - - trace_mem_init(" block %d base 0x%x size %d", - j, current_map->base, - current_map->block_size); - trace_mem_init(" count %d free %d", - current_map->count, - current_map->free_count); - - platform_shared_commit(current_map, - sizeof(*current_map)); - } - - platform_shared_commit(heap, sizeof(*heap)); - - heap++; - } + return 0; } +#endif -void heap_trace_all(int force) +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) { - struct mm *memmap = memmap_get(); - - /* has heap changed since last shown */ - if (memmap->heap_trace_updated || force) { - trace_mem_init("heap: buffer status"); - heap_trace(memmap->buffer, PLATFORM_HEAP_BUFFER); - trace_mem_init("heap: runtime status"); - heap_trace(memmap->runtime, PLATFORM_HEAP_RUNTIME); - } - - memmap->heap_trace_updated = 0; - - platform_shared_commit(memmap, sizeof(*memmap)); + return malloc(bytes); } -#else -void heap_trace_all(int force) { } -void heap_trace(struct mm_heap *heap, int size) { } -#endif -/* initialise map */ -void init_heap(struct sof *sof) +void sof_heap_free(struct k_heap *heap, void *addr) { - struct mm *memmap = sof->memory_map; - extern uintptr_t _system_heap_start; - - /* sanity check for malformed images or loader issues */ - if (memmap->system[0].heap != (uintptr_t)&_system_heap_start) - panic(SOF_IPC_PANIC_MEM); - - init_heap_map(memmap->system_runtime, PLATFORM_HEAP_SYSTEM_RUNTIME); - - init_heap_map(memmap->runtime, PLATFORM_HEAP_RUNTIME); - - init_heap_map(memmap->buffer, PLATFORM_HEAP_BUFFER); - -#if CONFIG_DEBUG_BLOCK_FREE - write_pattern((struct mm_heap *)&memmap->buffer, PLATFORM_HEAP_BUFFER, - DEBUG_BLOCK_FREE_VALUE_8BIT); - write_pattern((struct mm_heap *)&memmap->runtime, PLATFORM_HEAP_RUNTIME, - DEBUG_BLOCK_FREE_VALUE_8BIT); -#endif - - spinlock_init(&memmap->lock); - - platform_shared_commit(memmap, sizeof(*memmap)); + free(addr); } diff --git a/src/lib/ams.c b/src/lib/ams.c new file mode 100644 index 000000000000..31bca13ce833 --- /dev/null +++ b/src/lib/ams.c @@ -0,0 +1,619 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2023 Intel Corporation + * + * Author: Krzysztof Frydryk <krzysztofx.frydryk@intel.com> + */ + +#include <sof/lib/memory.h> +#include <sof/lib/cpu.h> +#include <rtos/interrupt.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/task.h> +#include <sof/ipc/topology.h> +#include <rtos/idc.h> +#include <rtos/alloc.h> +#include <sof/lib/memory.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <sof/lib/ams.h> +#include <zephyr/kernel.h> + +LOG_MODULE_REGISTER(ams, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(ams); + +DECLARE_TR_CTX(ams_tr, SOF_UUID(ams_uuid), LOG_LEVEL_INFO); + +static struct ams_context ctx[CONFIG_CORE_COUNT]; + +static struct ams_shared_context __sparse_cache *ams_acquire(struct ams_shared_context *shared) +{ + struct coherent __sparse_cache *c = coherent_acquire(&shared->c, + sizeof(*shared)); + + return attr_container_of(c, struct ams_shared_context __sparse_cache, + c, __sparse_cache); +} + +static void ams_release(struct ams_shared_context __sparse_cache *shared) +{ + coherent_release(&shared->c, sizeof(*shared)); +} + +static struct uuid_idx __sparse_cache *ams_find_uuid_entry_by_uuid(struct ams_shared_context __sparse_cache *ctx_shared, + uint8_t const *uuid) +{ + unsigned int index; + struct uuid_idx __sparse_cache *uuid_table = ctx_shared->uuid_table; + + if (!uuid) + return NULL; + + /* try to find existing entry */ + for (index = 0; index < AMS_SERVICE_UUID_TABLE_SIZE; index++) { + 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((__sparse_force void *)uuid_table[index].message_uuid, + sizeof(uuid_table[index].message_uuid), + uuid, UUID_SIZE); + if (ec != 0) { + tr_err(&ams_tr, "Failed to create UUID entry: %u", index); + return NULL; + } + + uuid_table[index].message_type_id = ++ctx_shared->last_used_msg_id; + return &uuid_table[index]; + } + } + + tr_err(&ams_tr, "No space to create UUID entry"); + return NULL; +} + +int ams_get_message_type_id(const uint8_t *message_uuid, + uint32_t *message_type_id) +{ + struct async_message_service *ams = *arch_ams_get(); + struct uuid_idx __sparse_cache *uuid_entry; + struct ams_shared_context __sparse_cache *shared_c; + + if (!ams->ams_context) + return -EINVAL; + + *message_type_id = AMS_INVALID_MSG_TYPE; + + shared_c = ams_acquire(ams->ams_context->shared); + + uuid_entry = ams_find_uuid_entry_by_uuid(shared_c, message_uuid); + if (!uuid_entry) { + ams_release(shared_c); + return -EINVAL; + } + + *message_type_id = uuid_entry->message_type_id; + ams_release(shared_c); + + return 0; +} + +static int ams_find_uuid_index_by_msg_type_id(struct ams_shared_context __sparse_cache *ctx_shared, + uint32_t const message_type_id) +{ + struct uuid_idx __sparse_cache *iter; + + if (message_type_id == AMS_INVALID_MSG_TYPE) + return -EINVAL; + + for (int i = 0; i < AMS_SERVICE_UUID_TABLE_SIZE; i++) { + iter = &ctx_shared->uuid_table[i]; + + /* we got the id */ + if (message_type_id == iter->message_type_id) + return i; + } + + return -ENOENT; +} + +int ams_register_producer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id) +{ + struct async_message_service *ams = *arch_ams_get(); + struct ams_producer __sparse_cache *producer_table; + struct ams_shared_context __sparse_cache *shared_c; + int idx; + int err = -EINVAL; + + if (!ams->ams_context) + return -EINVAL; + + shared_c = ams_acquire(ams->ams_context->shared); + + idx = ams_find_uuid_index_by_msg_type_id(shared_c, message_type_id); + if (idx < 0) { + ams_release(shared_c); + return -EINVAL; + } + + producer_table = shared_c->producer_table; + for (int iter = 0; iter < AMS_ROUTING_TABLE_SIZE; iter++) { + /* Search for first invalid entry */ + if (producer_table[iter].message_type_id == AMS_INVALID_MSG_TYPE) { + producer_table[iter].message_type_id = message_type_id; + producer_table[iter].producer_module_id = module_id; + producer_table[iter].producer_instance_id = instance_id; + + /* Exit loop since we added new entry */ + err = 0; + break; + } + } + + ams_release(shared_c); + return err; +} + +int ams_unregister_producer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id) +{ + struct async_message_service *ams = *arch_ams_get(); + struct ams_producer __sparse_cache *producer_table; + struct ams_shared_context __sparse_cache *shared_c; + int idx; + int err = -EINVAL; + + if (!ams->ams_context) + return -EINVAL; + + shared_c = ams_acquire(ams->ams_context->shared); + + idx = ams_find_uuid_index_by_msg_type_id(shared_c, message_type_id); + if (idx < 0) { + ams_release(shared_c); + return -EINVAL; + } + + producer_table = shared_c->producer_table; + for (int iter = 0; iter < AMS_ROUTING_TABLE_SIZE; iter++) { + if ((producer_table[iter].message_type_id == message_type_id) && + (producer_table[iter].producer_instance_id == instance_id) && + (producer_table[iter].producer_module_id == module_id)) { + producer_table[iter].message_type_id = AMS_INVALID_MSG_TYPE; + + /* Exit loop since we added new entry */ + err = 0; + break; + } + } + + ams_release(shared_c); + return err; +} + +int ams_register_consumer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id, + ams_msg_callback_fn function, + void *ctx) +{ + struct async_message_service *ams = *arch_ams_get(); + struct ams_consumer_entry __sparse_cache *routing_table; + struct ams_shared_context __sparse_cache *shared_c; + int err = -EINVAL; + + if (!ams->ams_context || !function) + return -EINVAL; + + shared_c = ams_acquire(ams->ams_context->shared); + + routing_table = shared_c->rt_table; + for (int iter = 0; iter < AMS_ROUTING_TABLE_SIZE; iter++) { + /* Search for first invalid entry */ + if (routing_table[iter].message_type_id == AMS_INVALID_MSG_TYPE) { + /* Add entry to routing table for local service */ + routing_table[iter].consumer_callback = function; + routing_table[iter].message_type_id = message_type_id; + routing_table[iter].consumer_instance_id = instance_id; + routing_table[iter].consumer_module_id = module_id; + routing_table[iter].consumer_core_id = cpu_get_id(); + routing_table[iter].ctx = ctx; + + /* Exit loop since we added new entry */ + err = 0; + break; + } + } + + ams_release(shared_c); + return err; +} + +int ams_unregister_consumer(uint32_t message_type_id, + uint16_t module_id, + uint16_t instance_id, + ams_msg_callback_fn function) +{ + struct async_message_service *ams = *arch_ams_get(); + struct ams_consumer_entry __sparse_cache *routing_table; + struct ams_shared_context __sparse_cache *shared_c; + int err = -EINVAL; + + if (!ams->ams_context) + return -EINVAL; + + shared_c = ams_acquire(ams->ams_context->shared); + routing_table = shared_c->rt_table; + for (int iter = 0; iter < AMS_ROUTING_TABLE_SIZE; iter++) { + /* Search for required entry */ + if ((routing_table[iter].message_type_id == message_type_id) && + (routing_table[iter].consumer_module_id == module_id) && + (routing_table[iter].consumer_instance_id == instance_id) && + (routing_table[iter].consumer_callback == function)) { + /* Remove this entry from routing table */ + routing_table[iter].message_type_id = AMS_INVALID_MSG_TYPE; + routing_table[iter].consumer_callback = NULL; + + /* Exit loop since we removed entry */ + err = 0; + break; + } + } + + ams_release(shared_c); + return err; +} + +static uint32_t ams_push_slot(struct ams_shared_context __sparse_cache *ctx_shared, + const struct ams_message_payload *msg, + uint16_t module_id, uint16_t instance_id) +{ + int err; + + for (uint32_t i = 0; i < ARRAY_SIZE(ctx_shared->slots); ++i) { + if (ctx_shared->slot_uses[i] == 0) { + 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)); + + if (err != 0) + return AMS_INVALID_SLOT; + + ctx_shared->slots[i].module_id = module_id; + ctx_shared->slots[i].instance_id = instance_id; + ctx_shared->slot_done[i] = 0; + + return i; + } + } + + return AMS_INVALID_SLOT; +} + +static int ams_get_ixc_route_to_target(int source_core, int target_core) +{ + if (source_core >= CONFIG_CORE_COUNT || target_core >= CONFIG_CORE_COUNT) + return -EINVAL; + /* core 0 can target any core */ + if (source_core == PLATFORM_PRIMARY_CORE_ID) + return target_core; + /* other cores must proxy through main core */ + return source_core == target_core ? target_core : PLATFORM_PRIMARY_CORE_ID; +} + +static int send_message_over_ixc(struct async_message_service *ams, uint32_t slot, + struct ams_consumer_entry *target) +{ + if (!target) + return -EINVAL; + + int ixc_route = ams_get_ixc_route_to_target(cpu_get_id(), + target->consumer_core_id); + + struct idc_msg ams_request = { + .header = IDC_MSG_AMS | slot, + .extension = IDC_MSG_AMS_EXT, + .core = ixc_route, + .size = 0, + .payload = NULL}; + + /* send IDC message */ + return idc_send_msg(&ams_request, IDC_NON_BLOCKING); +} + +static int ams_send_over_ixc(struct async_message_service *ams, uint32_t slot, + struct ams_consumer_entry *target) +{ +#if CONFIG_SMP + return send_message_over_ixc(ams, slot, target); +#else + return -EINVAL; +#endif +} + +static int ams_message_send_internal(struct async_message_service *ams, + const struct ams_message_payload *const ams_message_payload, + uint16_t module_id, uint16_t instance_id, + uint32_t incoming_slot) +{ + bool found_any = false; + bool incoming = (incoming_slot != AMS_INVALID_SLOT); + struct ams_consumer_entry __sparse_cache *routing_table; + struct ams_shared_context __sparse_cache *shared_c; + uint32_t forwarded = 0; + uint32_t slot; + struct ams_consumer_entry ams_target; + int ixc_route; + int cpu_id; + int err = 0; + + if (!ams->ams_context || !ams_message_payload) + return -EINVAL; + + shared_c = ams_acquire(ams->ams_context->shared); + cpu_id = cpu_get_id(); + + if (incoming) + shared_c->slot_done[incoming_slot] |= BIT(cpu_id); + + routing_table = shared_c->rt_table; + + for (int iter = 0; iter < AMS_ROUTING_TABLE_SIZE; iter++) { + slot = AMS_INVALID_SLOT; + + /* Search for required entry */ + if (routing_table[iter].message_type_id != ams_message_payload->message_type_id) + continue; + + /* check if we want to limit to specific module* */ + if (module_id != AMS_ANY_ID && instance_id != AMS_ANY_ID) { + if (routing_table[iter].consumer_module_id != module_id || + routing_table[iter].consumer_instance_id != instance_id) { + continue; + } + } + + found_any = true; + ams_target = routing_table[iter]; + ixc_route = ams_get_ixc_route_to_target(cpu_id, + ams_target.consumer_core_id); + + if (ixc_route == cpu_id) { + /* we are on target core already */ + /* release lock here, callback are NOT supposed to change routing_table */ + ams_release(shared_c); + + ams_target.consumer_callback(ams_message_payload, ams_target.ctx); + err = 0; + } else { + /* we have to go through idc */ + if (incoming) { + /* if bit is set we are forwarding it again */ + if (shared_c->slot_done[incoming_slot] & BIT(ams_target.consumer_core_id)) { + /* slot was already processed for that core, skip it */ + continue; + } + } else { + slot = ams_push_slot(shared_c, + ams_message_payload, module_id, + instance_id); + if (slot == AMS_INVALID_SLOT) { + ams_release(shared_c); + return -EINVAL; + } + } + if ((forwarded & BIT(ams_target.consumer_core_id)) == 0) { + /* bump uses count, mark current as processed already */ + if (slot != AMS_INVALID_SLOT) { + shared_c->slot_uses[slot]++; + shared_c->slot_done[slot] |= BIT(cpu_id); + } + + /* release lock here, so other core can acquire it again */ + ams_release(shared_c); + + if (slot != AMS_INVALID_SLOT) { + forwarded |= BIT(ams_target.consumer_core_id); + err = ams_send_over_ixc(ams, slot, &ams_target); + if (err != 0) { + /* idc not sent, update slot refs locally */ + shared_c = ams_acquire(ams->ams_context->shared); + shared_c->slot_uses[slot]--; + shared_c->slot_done[slot] |= BIT(ams_target.consumer_core_id); + ams_release(shared_c); + } + } + } else { + /* message already forwarded, nothing to do here */ + ams_release(shared_c); + } + } + + /* acquire shared context lock again */ + shared_c = ams_acquire(ams->ams_context->shared); + } + + if (incoming) + shared_c->slot_uses[incoming_slot]--; + + ams_release(shared_c); + + if (!found_any) + tr_err(&ams_tr, "No entries found!"); + + return err; +} + +int ams_send(const struct ams_message_payload *const ams_message_payload) +{ + struct async_message_service *ams = *arch_ams_get(); + + return ams_message_send_internal(ams, ams_message_payload, AMS_ANY_ID, AMS_ANY_ID, + AMS_INVALID_SLOT); +} + +int ams_message_send_mi(struct async_message_service *ams, + const struct ams_message_payload *const ams_message_payload, + uint16_t target_module, uint16_t target_instance) +{ + return ams_message_send_internal(ams, ams_message_payload, target_module, + target_instance, AMS_INVALID_SLOT); +} + +int ams_send_mi(const struct ams_message_payload *const ams_message_payload, + uint16_t module_id, uint16_t instance_id) +{ + struct async_message_service *ams = *arch_ams_get(); + + return ams_message_send_mi(ams, ams_message_payload, module_id, instance_id); +} + +static int ams_process_slot(struct async_message_service *ams, uint32_t slot) +{ + struct ams_shared_context __sparse_cache *shared_c; + struct ams_message_payload msg; + uint16_t module_id; + uint16_t instance_id; + + shared_c = ams_acquire(ams->ams_context->shared); + + msg = shared_c->slots[slot].u.msg; + module_id = shared_c->slots[slot].module_id; + instance_id = shared_c->slots[slot].instance_id; + + ams_release(shared_c); + tr_info(&ams_tr, "slot %d msg %d from 0x%08x", + slot, msg.message_type_id, + msg.producer_module_id << 16 | msg.producer_instance_id); + + return ams_message_send_internal(ams, &msg, module_id, instance_id, slot); +} + +#if CONFIG_SMP + +static void ams_task_add_slot_to_process(struct ams_task *ams_task, uint32_t slot) +{ + int flags; + + irq_local_disable(flags); + ams_task->pending_slots |= BIT(slot); + irq_local_enable(flags); +} + +int process_incoming_message(uint32_t slot) +{ + struct async_message_service *ams = *arch_ams_get(); + struct ams_task *task = &ams->ams_task; + + ams_task_add_slot_to_process(task, slot); + + return schedule_task(&task->ams_task, 0, 10000); +} + +#endif /* CONFIG_SMP */ + +/* ams task */ + +static enum task_state process_message(void *arg) +{ + struct ams_task *ams_task = arg; + uint32_t slot; + int flags; + + if (ams_task->pending_slots == 0) { + tr_err(&ams_tr, "Could not process message! Skipping."); + return SOF_TASK_STATE_COMPLETED; + } + + slot = 31 - clz(ams_task->pending_slots); + + ams_process_slot(ams_task->ams, slot); + + /* only done on main core, irq disabling is enough */ + irq_local_disable(flags); + ams_task->pending_slots &= ~BIT(slot); + irq_local_enable(flags); + schedule_task_cancel(&ams_task->ams_task); + + return SOF_TASK_STATE_COMPLETED; +} + +static int ams_task_init(void) +{ + int ret; + struct async_message_service *ams = *arch_ams_get(); + struct ams_task *task = &ams->ams_task; + + task->ams = ams; + + ret = schedule_task_init_ll(&task->ams_task, SOF_UUID(ams_uuid), SOF_SCHEDULE_LL_TIMER, + SOF_TASK_PRI_MED, process_message, &ams->ams_task, cpu_get_id(), 0); + if (ret) + tr_err(&ams_tr, "Could not init AMS task!"); + + return ret; +} + +static int ams_create_shared_context(struct ams_shared_context *ctx) +{ + struct ams_shared_context __sparse_cache *shared_c; + + shared_c = ams_acquire(ctx); + shared_c->last_used_msg_id = AMS_INVALID_MSG_TYPE; + ams_release(shared_c); + + return 0; +} + +int ams_init(void) +{ + struct ams_shared_context *ams_shared_ctx; + struct async_message_service **ams = arch_ams_get(); + struct sof *sof; + int ret = 0; + + *ams = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(**ams)); + if (!*ams) + return -ENOMEM; + + (*ams)->ams_context = &ctx[cpu_get_id()]; + memset((*ams)->ams_context, 0, sizeof(*(*ams)->ams_context)); + + if (cpu_get_id() == PLATFORM_PRIMARY_CORE_ID) { + sof = sof_get(); + sof->ams_shared_ctx = coherent_init(struct ams_shared_context, c); + if (!sof->ams_shared_ctx) + goto err; + coherent_shared(sof->ams_shared_ctx, c); + } + + ams_shared_ctx = ams_ctx_get(); + (*ams)->ams_context->shared = ams_shared_ctx; + + ams_create_shared_context((*ams)->ams_context->shared); + +#if CONFIG_SMP + ret = ams_task_init(); +#endif /* CONFIG_SMP */ + + return ret; + +err: + rfree(*ams); + + return -ENOMEM; +} diff --git a/src/lib/clk.c b/src/lib/clk.c index 2ed82c5a45ff..d93ab81c680b 100644 --- a/src/lib/clk.c +++ b/src/lib/clk.c @@ -7,25 +7,24 @@ // Rander Wang <rander.wang@intel.com> // Janusz Jankowski <janusz.jankowski@linux.intel.com> -#include <sof/drivers/timer.h> -#include <sof/lib/clk.h> +#include <rtos/timer.h> +#include <rtos/clk.h> #include <sof/lib/memory.h> #include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> #include <sof/platform.h> -#include <sof/spinlock.h> +#include <rtos/spinlock.h> #include <sof/trace/trace.h> #include <user/trace.h> #include <stdint.h> -/* clock tracing */ -#define trace_clk(__e, ...) \ - trace_event(TRACE_CLASS_CLK, __e, ##__VA_ARGS__) -#define tracev_clk(__e, ...) \ - tracev_event(TRACE_CLASS_CLK, __e, ##__VA_ARGS__) -#define trace_clk_error(__e, ...) \ - trace_error(TRACE_CLASS_CLK, __e, ##__VA_ARGS__) +LOG_MODULE_REGISTER(clock, CONFIG_SOF_LOG_LEVEL); -struct clock_notify_data clk_notify_data; +SOF_DEFINE_REG_UUID(clock); + +DECLARE_TR_CTX(clock_tr, SOF_UUID(clock_uuid), LOG_LEVEL_INFO); + +SHARED_DATA struct k_spinlock clk_lock; static inline uint32_t clock_get_nearest_freq_idx(const struct freq_table *tab, uint32_t size, uint32_t hz) @@ -47,8 +46,6 @@ uint32_t clock_get_freq(int clock) struct clock_info *clk_info = clocks_get() + clock; uint32_t freq = clk_info->freqs[clk_info->current_freq_idx].freq; - platform_shared_commit(clk_info, sizeof(*clk_info)); - return freq; } @@ -56,65 +53,45 @@ void clock_set_freq(int clock, uint32_t hz) { struct clock_info *clk_info = clocks_get() + clock; uint32_t idx; - uint32_t flags; - - clk_notify_data.old_freq = - clk_info->freqs[clk_info->current_freq_idx].freq; - clk_notify_data.old_ticks_per_msec = - clk_info->freqs[clk_info->current_freq_idx].ticks_per_msec; + k_spinlock_key_t key; /* atomic context for changing clocks */ - spin_lock_irq(&clk_info->lock, flags); + key = clock_lock(); /* get nearest frequency that is >= requested Hz */ idx = clock_get_nearest_freq_idx(clk_info->freqs, clk_info->freqs_num, hz); - clk_notify_data.freq = clk_info->freqs[idx].freq; - /* tell anyone interested we are about to change freq */ - clk_notify_data.message = CLOCK_NOTIFY_PRE; - notifier_event(clk_info, clk_info->notification_id, - clk_info->notification_mask, &clk_notify_data, - sizeof(clk_notify_data)); + if (clk_info->current_freq_idx != idx && + (!clk_info->set_freq || + clk_info->set_freq(clock, idx) == 0)) { + tr_info(&clock_tr, "clock %d set freq %dHz freq_idx %d old %d", + clock, hz, idx, clk_info->current_freq_idx); - if (!clk_info->set_freq || - clk_info->set_freq(clock, idx) == 0) /* update clock frequency */ clk_info->current_freq_idx = idx; + } - /* tell anyone interested we have now changed freq */ - clk_notify_data.message = CLOCK_NOTIFY_POST; - notifier_event(clk_info, clk_info->notification_id, - clk_info->notification_mask, &clk_notify_data, - sizeof(clk_notify_data)); - - platform_shared_commit(clk_info, sizeof(*clk_info)); - - spin_unlock_irq(&clk_info->lock, flags); + clock_unlock(key); } -uint64_t clock_ms_to_ticks(int clock, uint64_t ms) +void clock_low_power_mode(int clock, bool enable) { struct clock_info *clk_info = clocks_get() + clock; - uint64_t ticks; - - ticks = clk_info->freqs[clk_info->current_freq_idx].ticks_per_msec * ms; - platform_shared_commit(clk_info, sizeof(*clk_info)); - - return ticks; + if (clk_info->low_power_mode) + clk_info->low_power_mode(clock, enable); } -void platform_timer_set_delta(struct timer *timer, uint64_t ns) +uint64_t clock_ticks_per_sample(int clock, uint32_t sample_rate) { - struct clock_info *clk_info = clocks_get() + PLATFORM_DEFAULT_CLOCK; - uint32_t ticks_per_msec = - clk_info->freqs[clk_info->current_freq_idx].ticks_per_msec; - uint64_t ticks; + struct clock_info *clk_info = clocks_get() + clock; + uint32_t ticks_per_msec; + uint64_t ticks_per_sample; - ticks = ticks_per_msec * ns / 1000000; - timer->delta = ticks - platform_timer_get(timer); + platform_shared_get(clk_info, sizeof(*clk_info)); + ticks_per_msec = clk_info->freqs[clk_info->current_freq_idx].ticks_per_msec; + ticks_per_sample = sample_rate ? ticks_per_msec * 1000 / sample_rate : 0; - platform_shared_commit(clk_info, sizeof(*clk_info)); - platform_shared_commit(timer, sizeof(*timer)); + return ticks_per_sample; } diff --git a/src/lib/cpu-clk-manager.c b/src/lib/cpu-clk-manager.c new file mode 100644 index 000000000000..59744063e4b9 --- /dev/null +++ b/src/lib/cpu-clk-manager.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Krzysztof Frydryk <frydryk.krzysztof@intel.com> + +#include <rtos/spinlock.h> +#include <rtos/sof.h> +#include <stdint.h> +#include <sof/lib/cpu-clk-manager.h> +#include <rtos/clk.h> +#include <sof/math/numbers.h> +#include <errno.h> +#include <zephyr/sys/util.h> + +static struct kcps_budget_data kcps_data; + +static int request_freq_change(unsigned int core, int freq) +{ + int current_freq; + int selected_freq_id; + struct clock_info *clk; + + clk = clocks_get() + core; + + for (selected_freq_id = 0; selected_freq_id < clk->freqs_num; selected_freq_id++) { + if (freq < clk->freqs[selected_freq_id].freq) + break; + } + + /* don't change clock frequency if already using proper clock */ + current_freq = clock_get_freq(core); + if (clk->freqs[selected_freq_id].freq != current_freq) + clock_set_freq(core, freq); + + return 0; +} + +static int max_core_consumption(void) +{ + int result = 0; + unsigned int core; + + for (core = 0; core < CONFIG_CORE_COUNT; core++) + result = MAX(result, kcps_data.kcps_consumption[core]); + + return result; +} + +int core_kcps_adjust(int adjusted_core_id, int kcps_delta) +{ + k_spinlock_key_t key; + int freq; + unsigned int core_id; + int ret = 0; + + key = k_spin_lock(&kcps_data.lock); + kcps_data.kcps_consumption[adjusted_core_id] += kcps_delta; + + /* set clock according to maximum requested mcps budget */ + freq = max_core_consumption(); + + for (core_id = 0; core_id < CONFIG_CORE_COUNT; core_id++) { + /* Convert kcps to cps */ + ret = request_freq_change(core_id, MIN(freq * 1000, CLK_MAX_CPU_HZ)); + if (ret < 0) + goto out; + } + +out: + k_spin_unlock(&kcps_data.lock, key); + + return ret; +} + +int core_kcps_get(int core) +{ + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&kcps_data.lock); + ret = kcps_data.kcps_consumption[core]; + k_spin_unlock(&kcps_data.lock, key); + return ret; +} + +int kcps_budget_init(void) +{ + k_spinlock_init(&kcps_data.lock); + + return 0; +} diff --git a/src/lib/dai.c b/src/lib/dai.c index 75f40d93bb8e..bd7c02edcb2d 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -5,16 +5,354 @@ // Author: Marcin Maka <marcin.maka@linux.intel.com> #include <sof/lib/dai.h> +#include <rtos/alloc.h> +#include <sof/lib/cpu.h> #include <sof/lib/memory.h> -#include <sof/spinlock.h> +#include <sof/lib/uuid.h> +#include <rtos/spinlock.h> #include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <ipc/dai.h> #include <user/trace.h> #include <errno.h> #include <stddef.h> #include <stdint.h> -#define trace_dai(__e, ...) trace_event(TRACE_CLASS_DAI, __e, ##__VA_ARGS__) +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +#include <zephyr/device.h> +#include <zephyr/drivers/dai.h> +#endif +LOG_MODULE_REGISTER(dai, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(dai_lib); + +DECLARE_TR_CTX(dai_tr, SOF_UUID(dai_lib_uuid), LOG_LEVEL_INFO); + +struct dai_group_list { + struct list_item list; +} __aligned(PLATFORM_DCACHE_ALIGN); + +static struct dai_group_list *groups[CONFIG_CORE_COUNT]; + +__cold static struct dai_group_list *dai_group_list_get(int core_id) +{ + struct dai_group_list *group_list = groups[core_id]; + + assert_can_be_cold(); + + if (!group_list) { + group_list = rzalloc(SOF_MEM_FLAG_USER, + sizeof(*group_list)); + if (!group_list) { + tr_err(&dai_tr, "dai_group_list_get(): failed to allocate group_list for core %d", + core_id); + return NULL; + } + + groups[core_id] = group_list; + list_init(&group_list->list); + } + + return group_list; +} + +__cold static struct dai_group *dai_group_find(uint32_t group_id) +{ + struct list_item *dai_groups; + struct dai_group_list *group_list; + struct list_item *group_item; + struct dai_group *group = NULL; + + assert_can_be_cold(); + + group_list = dai_group_list_get(cpu_get_id()); + if (!group_list) { + tr_err(&dai_tr, "dai_group_find(): failed to get group_list for core %d", + cpu_get_id()); + return NULL; + } + dai_groups = &group_list->list; + + list_for_item(group_item, dai_groups) { + group = container_of(group_item, struct dai_group, list); + + if (group->group_id == group_id) + break; + + group = NULL; + } + + return group; +} + +__cold static struct dai_group *dai_group_alloc(void) +{ + struct dai_group_list *group_list = dai_group_list_get(cpu_get_id()); + struct list_item *dai_groups; + struct dai_group *group; + + assert_can_be_cold(); + if (!group_list) { + tr_err(&dai_tr, "dai_group_alloc(): failed to get group_list for core %d", + cpu_get_id()); + return NULL; + } + dai_groups = &group_list->list; + + group = rzalloc(SOF_MEM_FLAG_USER, + sizeof(*group)); + if (!group) { + tr_err(&dai_tr, "dai_group_alloc(): failed to allocate dai group"); + return NULL; + } + + list_item_prepend(&group->list, dai_groups); + + return group; +} + +__cold struct dai_group *dai_group_get(uint32_t group_id, uint32_t flags) +{ + struct dai_group *group; + + assert_can_be_cold(); + + if (!group_id) { + tr_err(&dai_tr, "dai_group_get(): invalid group_id %u", + group_id); + return NULL; + } + + /* Check if this group already exists */ + group = dai_group_find(group_id); + + /* Check if there's a released and now unused group */ + if (!group) + group = dai_group_find(0); + + /* Group doesn't exist, let's allocate and initialize it */ + if (!group && flags & DAI_CREAT) + group = dai_group_alloc(); + + if (group) { + /* Group might've been previously unused */ + if (!group->group_id) + group->group_id = group_id; + + group->num_dais++; + } else { + tr_err(&dai_tr, "dai_group_get(): failed to get group_id %u", + group_id); + } + + return group; +} + +__cold void dai_group_put(struct dai_group *group) +{ + assert_can_be_cold(); + + group->num_dais--; + + /* Mark as unused if there are no more DAIs in this group */ + if (!group->num_dais) + group->group_id = 0; +} + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + +#define GET_DEVICE_LIST(node) DEVICE_DT_GET(node), + +const struct device *zephyr_dev[] = { +#if CONFIG_DAI_INTEL_SSP + DT_FOREACH_STATUS_OKAY(intel_ssp_dai, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_INTEL_DMIC + DT_FOREACH_STATUS_OKAY(intel_dai_dmic, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_INTEL_ALH + DT_FOREACH_STATUS_OKAY(intel_alh_dai, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_INTEL_HDA + DT_FOREACH_STATUS_OKAY(intel_hda_dai, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_NXP_SAI + DT_FOREACH_STATUS_OKAY(nxp_dai_sai, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_NXP_ESAI + DT_FOREACH_STATUS_OKAY(nxp_dai_esai, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_NXP_MICFIL + DT_FOREACH_STATUS_OKAY(nxp_dai_micfil, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_AMD_SDW + DT_FOREACH_STATUS_OKAY(amd_acp_sdw_dai, GET_DEVICE_LIST) +#endif +#if CONFIG_DAI_INTEL_UAOL + DT_FOREACH_STATUS_OKAY(intel_uaol_dai, GET_DEVICE_LIST) +#endif +}; + +const struct device **dai_get_device_list(size_t *count) +{ + __ASSERT_NO_MSG(count); + *count = ARRAY_SIZE(zephyr_dev); + + return zephyr_dev; +} + +/* convert sof_ipc_dai_type to Zephyr dai_type */ +static int sof_dai_type_to_zephyr(uint32_t type) +{ + switch (type) { + case SOF_DAI_INTEL_SSP: + return DAI_INTEL_SSP; + case SOF_DAI_INTEL_DMIC: + return DAI_INTEL_DMIC; + case SOF_DAI_INTEL_HDA: + return DAI_INTEL_HDA; + case SOF_DAI_INTEL_ALH: + return DAI_INTEL_ALH; + case SOF_DAI_INTEL_UAOL: + return DAI_INTEL_UAOL; + case SOF_DAI_IMX_SAI: + return DAI_IMX_SAI; + case SOF_DAI_IMX_ESAI: + return DAI_IMX_ESAI; + case SOF_DAI_AMD_BT: + return DAI_AMD_BT; + case SOF_DAI_AMD_SP: + return DAI_AMD_SP; + case SOF_DAI_AMD_DMIC: + return DAI_AMD_DMIC; + case SOF_DAI_MEDIATEK_AFE: + return DAI_MEDIATEK_AFE; + case SOF_DAI_IMX_MICFIL: + return DAI_IMX_MICFIL; + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_SP_VIRTUAL: + case SOF_DAI_AMD_HS_VIRTUAL: + case SOF_DAI_AMD_SDW: + return DAI_AMD_SDW; + default: + return -EINVAL; + } +} + +const struct device *dai_get_device(enum sof_ipc_dai_type type, uint32_t index) +{ + struct dai_config cfg; + int z_type; + int dir; + int i; + + dir = (type == SOF_DAI_INTEL_DMIC) ? DAI_DIR_RX : DAI_DIR_BOTH; + + z_type = sof_dai_type_to_zephyr(type); + if (z_type < 0) { + tr_err(&dai_tr, "dai_get_device: no matching zephyr DAI type for %d ret = %d", + type, z_type); + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(zephyr_dev); i++) { + if (dai_config_get(zephyr_dev[i], &cfg, dir)) + continue; + if (cfg.type == z_type && cfg.dai_index == index) + return zephyr_dev[i]; + } + + return NULL; +} + +static void dai_set_device_params(struct dai *d) +{ + switch (d->type) { + case SOF_DAI_INTEL_SSP: + d->dma_dev = SOF_DMA_DEV_SSP; +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA + d->dma_caps = SOF_DMA_CAP_GP_LP | SOF_DMA_CAP_GP_HP; +#else + d->dma_caps = SOF_DMA_CAP_HDA; +#endif + break; + case SOF_DAI_INTEL_DMIC: + d->dma_dev = SOF_DMA_DEV_DMIC; +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA + d->dma_caps = SOF_DMA_CAP_GP_LP | SOF_DMA_CAP_GP_HP; +#else + d->dma_caps = SOF_DMA_CAP_HDA; +#endif + break; + case SOF_DAI_INTEL_ALH: + d->dma_dev = SOF_DMA_DEV_ALH; +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA + d->dma_caps = SOF_DMA_CAP_GP_LP | SOF_DMA_CAP_GP_HP; +#else + d->dma_caps = SOF_DMA_CAP_HDA; +#endif + break; + case SOF_DAI_INTEL_HDA: + case SOF_DAI_INTEL_UAOL: + d->dma_dev = SOF_DMA_DEV_HDA; + d->dma_caps = SOF_DMA_CAP_HDA; + break; + case SOF_DAI_AMD_SDW: + d->dma_dev = SOF_DMA_DEV_SW; + d->dma_caps = SOF_DMA_CAP_SW; + break; + default: + break; + } +} + +/* called from ipc/ipc3/handler.c and some platform.c files */ +struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) +{ + const struct device *dev; + struct dai *d; + + dev = dai_get_device(type, index); + if (!dev) { + tr_err(&dai_tr, "dai_get: failed to get dai with index %d type %d", + index, type); + return NULL; + } + + d = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(struct dai)); + if (!d) + return NULL; + + d->index = index; + d->type = type; + d->dev = dev; + + dai_set_device_params(d); + + if (dai_probe(d->dev)) { + tr_err(&dai_tr, "dai_get: failed to probe dai with index %d type %d", + index, type); + rfree(d); + return NULL; + } + + return d; +} + +/* called from src/ipc/ipc3/handler.c */ +void dai_put(struct dai *dai) +{ + int ret; + + ret = dai_remove(dai->dev); + if (ret < 0) { + tr_err(&dai_tr, "index %d failed ret = %d", + dai->index, ret); + } + + rfree(dai); +} +#else static inline const struct dai_type_info *dai_find_type(uint32_t type) { const struct dai_info *info = dai_info_get(); @@ -33,6 +371,7 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) int ret = 0; const struct dai_type_info *dti; struct dai *d; + k_spinlock_key_t key; dti = dai_find_type(type); if (!dti) @@ -40,11 +379,10 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) for (d = dti->dai_array; d < dti->dai_array + dti->num_dais; d++) { if (d->index != index) { - platform_shared_commit(d, sizeof(*d)); continue; } /* device created? */ - spin_lock(&d->lock); + key = k_spin_lock(&d->lock); if (d->sref == 0) { if (flags & DAI_CREAT) ret = dai_probe(d); @@ -54,34 +392,32 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) if (!ret) d->sref++; - trace_dai("dai_get %d.%d new sref %d", - type, index, d->sref); - - platform_shared_commit(d, sizeof(*d)); + tr_info(&dai_tr, "dai_get type %d index %d new sref %d", + type, index, d->sref); - spin_unlock(&d->lock); + k_spin_unlock(&d->lock, key); return !ret ? d : NULL; } - trace_error(TRACE_CLASS_DAI, "dai_get error: %d.%d not found", - type, index); + tr_err(&dai_tr, "dai_get: type %d index %d not found", type, index); return NULL; } void dai_put(struct dai *dai) { int ret; + k_spinlock_key_t key; - spin_lock(&dai->lock); + key = k_spin_lock(&dai->lock); if (--dai->sref == 0) { ret = dai_remove(dai); if (ret < 0) { - trace_error(TRACE_CLASS_DAI, "dai_put error: %d.%d dai_remove() failed ret = %d", - dai->drv->type, dai->index, ret); + tr_err(&dai_tr, "type %d index %d dai_remove() failed ret = %d", + dai->drv->type, dai->index, ret); } } - trace_event(TRACE_CLASS_DAI, "dai_put %d.%d new sref %d", - dai->drv->type, dai->index, dai->sref); - platform_shared_commit(dai, sizeof(*dai)); - spin_unlock(&dai->lock); + tr_info(&dai_tr, "type %d index %d new sref %d", + dai->drv->type, dai->index, dai->sref); + k_spin_unlock(&dai->lock, key); } +#endif diff --git a/src/lib/dma.c b/src/lib/dma.c index 577ca7a0f90f..70ac5c975058 100644 --- a/src/lib/dma.c +++ b/src/lib/dma.c @@ -4,30 +4,180 @@ // // Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> -#include <sof/atomic.h> +#include <rtos/atomic.h> #include <sof/audio/audio_stream.h> #include <sof/audio/buffer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <sof/audio/component.h> +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include <sof/audio/mic_privacy_manager.h> +#endif +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> -#include <sof/spinlock.h> +#include <sof/lib/uuid.h> +#include <rtos/spinlock.h> #include <sof/trace/trace.h> #include <ipc/topology.h> #include <user/trace.h> #include <errno.h> #include <stddef.h> #include <stdint.h> +#include <module/module/base.h> +#include "../audio/copier/copier.h" +LOG_MODULE_REGISTER(dma, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dma); + +DECLARE_TR_CTX(dma_tr, SOF_UUID(dma_uuid), LOG_LEVEL_INFO); + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +static int dma_init(struct sof_dma *dma); + +struct sof_dma *z_impl_sof_dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags) +{ + const struct dma_info *info = dma_info_get(); + int users, ret = 0; + int min_users = INT32_MAX; + struct sof_dma *d = NULL, *dmin = NULL; + k_spinlock_key_t key; + + if (!info->num_dmas) { + tr_err(&dma_tr, "dma_get(): No DMACs installed"); + return NULL; + } + + /* find DMAC with free channels that matches request */ + for (d = info->dma_array; d < info->dma_array + info->num_dmas; + d++) { + /* skip if this DMAC does not support the requested dir */ + if (dir && (d->plat_data.dir & dir) == 0) + continue; + + /* skip if this DMAC does not support the requested caps */ + if (cap && (d->plat_data.caps & cap) == 0) + continue; + + /* skip if this DMAC does not support the requested dev */ + if (dev && (d->plat_data.devs & dev) == 0) + continue; + + /* if exclusive access is requested */ + if (flags & SOF_DMA_ACCESS_EXCLUSIVE) { + /* ret DMA with no users */ + if (!d->sref) { + dmin = d; + break; + } + } else { + /* get number of users for this DMAC*/ + users = d->sref; + + /* pick DMAC with the least num of users */ + if (users < min_users) { + dmin = d; + min_users = users; + } + } + } + + if (!dmin) { + tr_err(&dma_tr, "No DMAC dir %d caps 0x%x dev 0x%x flags 0x%x", + dir, cap, dev, flags); + + for (d = info->dma_array; + d < info->dma_array + info->num_dmas; + d++) { + tr_err(&dma_tr, " DMAC ID %d users %d busy channels %ld", + d->plat_data.id, d->sref, + atomic_read(&d->num_channels_busy)); + tr_err(&dma_tr, " caps 0x%x dev 0x%x", + d->plat_data.caps, d->plat_data.devs); + } + + return NULL; + } + + /* return DMAC */ + tr_dbg(&dma_tr, "dma_get(), dma-probe id = %d", + dmin->plat_data.id); + + /* Shared DMA controllers with multiple channels + * may be requested many times, let the probe() + * do on-first-use initialization. + */ + key = k_spin_lock(&dmin->lock); + + if (!dmin->sref) { + ret = dma_init(dmin); + if (ret < 0) { + tr_err(&dma_tr, "dma_get(): dma-probe failed id = %d, ret = %d", + dmin->plat_data.id, ret); + goto out; + } + } + + dmin->sref++; + + tr_info(&dma_tr, "dma_get() ID %d sref = %d busy channels %ld", + dmin->plat_data.id, dmin->sref, + atomic_read(&dmin->num_channels_busy)); +out: + k_spin_unlock(&dmin->lock, key); + return !ret ? dmin : NULL; +} + +void z_impl_sof_dma_put(struct sof_dma *dma) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&dma->lock); + if (--dma->sref == 0) { + rfree(dma->chan); + dma->chan = NULL; + } + + tr_info(&dma_tr, "dma_put(), dma = %p, sref = %d", + dma, dma->sref); + k_spin_unlock(&dma->lock, key); +} + +static int dma_init(struct sof_dma *dma) +{ + struct dma_chan_data *chan; + int i; + + /* allocate dma channels */ + dma->chan = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(struct dma_chan_data) * dma->plat_data.channels); + + if (!dma->chan) { + tr_err(&dma_tr, "dma_probe_sof(): dma %d allocaction of channels failed", + dma->plat_data.id); + return -ENOMEM; + } + + /* init work */ + for (i = 0, chan = dma->chan; i < dma->plat_data.channels; + i++, chan++) { + chan->dma = dma; + chan->index = i; + } + + return 0; +} +#else struct dma *dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags) { const struct dma_info *info = dma_info_get(); int users, ret; int min_users = INT32_MAX; struct dma *d = NULL, *dmin = NULL; + k_spinlock_key_t key; if (!info->num_dmas) { - trace_error(TRACE_CLASS_DMA, "dma_get(): No DMACs installed"); + tr_err(&dma_tr, "dma_get(): No DMACs installed"); return NULL; } @@ -71,100 +221,92 @@ struct dma *dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags) } if (!dmin) { - trace_error(TRACE_CLASS_DMA, "No DMAC dir %d caps 0x%x " - "dev 0x%x flags 0x%x", dir, cap, dev, flags); + tr_err(&dma_tr, "No DMAC dir %d caps 0x%x dev 0x%x flags 0x%x", + dir, cap, dev, flags); for (d = info->dma_array; d < info->dma_array + info->num_dmas; d++) { - trace_error(TRACE_CLASS_DMA, " DMAC ID %d users %d " - "busy channels %d", d->plat_data.id, - d->sref, - atomic_read(&d->num_channels_busy)); - trace_error(TRACE_CLASS_DMA, " caps 0x%x dev 0x%x", - d->plat_data.caps, d->plat_data.devs); + tr_err(&dma_tr, " DMAC ID %d users %d busy channels %ld", + d->plat_data.id, d->sref, + atomic_read(&d->num_channels_busy)); + tr_err(&dma_tr, " caps 0x%x dev 0x%x", + d->plat_data.caps, d->plat_data.devs); } - platform_shared_commit(info->dma_array, - sizeof(struct dma) * info->num_dmas); - return NULL; } - platform_shared_commit(info->dma_array, - sizeof(struct dma) * info->num_dmas); - /* return DMAC */ - tracev_event(TRACE_CLASS_DMA, "dma_get(), dma-probe id = %d", - dmin->plat_data.id); + tr_dbg(&dma_tr, "dma_get(), dma-probe id = %d", + dmin->plat_data.id); /* Shared DMA controllers with multiple channels * may be requested many times, let the probe() * do on-first-use initialization. */ - spin_lock(&dmin->lock); + key = k_spin_lock(&dmin->lock); ret = 0; if (!dmin->sref) { - ret = dma_probe(dmin); + ret = dma_probe_legacy(dmin); if (ret < 0) { - trace_error(TRACE_CLASS_DMA, - "dma_get() error: dma-probe failed" - " id = %d, ret = %d", - dmin->plat_data.id, ret); + tr_err(&dma_tr, "dma_get(): dma-probe failed id = %d, ret = %d", + dmin->plat_data.id, ret); } } if (!ret) dmin->sref++; - trace_event(TRACE_CLASS_DMA, "dma_get() ID %d sref = %d " - "busy channels %d", dmin->plat_data.id, dmin->sref, - atomic_read(&dmin->num_channels_busy)); - - platform_shared_commit(dmin, sizeof(*dmin)); + tr_info(&dma_tr, "dma_get() ID %d sref = %d busy channels %ld", + dmin->plat_data.id, dmin->sref, + atomic_read(&dmin->num_channels_busy)); - spin_unlock(&dmin->lock); + k_spin_unlock(&dmin->lock, key); return !ret ? dmin : NULL; } void dma_put(struct dma *dma) { + k_spinlock_key_t key; int ret; - spin_lock(&dma->lock); + key = k_spin_lock(&dma->lock); if (--dma->sref == 0) { - ret = dma_remove(dma); + ret = dma_remove_legacy(dma); if (ret < 0) { - trace_error(TRACE_CLASS_DMA, - "dma_put() error: dma_remove() failed id" - " = %d, ret = %d", dma->plat_data.id, ret); + tr_err(&dma_tr, "dma_remove() failed id = %d, ret = %d", + dma->plat_data.id, ret); } } - trace_event(TRACE_CLASS_DMA, "dma_put(), dma = %p, sref = %d", - (uintptr_t)dma, dma->sref); - platform_shared_commit(dma, sizeof(*dma)); - spin_unlock(&dma->lock); + tr_info(&dma_tr, "dma = %p, sref = %d", + dma, dma->sref); + k_spin_unlock(&dma->lock, key); } +#endif -int dma_sg_alloc(struct dma_sg_elem_array *elem_array, - enum mem_zone zone, +int dma_sg_alloc(struct k_heap *heap, + struct dma_sg_elem_array *elem_array, + uint32_t flags, uint32_t direction, uint32_t buffer_count, uint32_t buffer_bytes, uintptr_t dma_buffer_addr, uintptr_t external_addr) { int i; - elem_array->elems = rzalloc(zone, 0, SOF_MEM_CAPS_RAM, - sizeof(struct dma_sg_elem) * buffer_count); + elem_array->elems = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, + sizeof(struct dma_sg_elem) * buffer_count, 0); if (!elem_array->elems) return -ENOMEM; + memset(elem_array->elems, 0, sizeof(struct dma_sg_elem) * buffer_count); + for (i = 0; i < buffer_count; i++) { elem_array->elems[i].size = buffer_bytes; // TODO: may count offsets once switch (direction) { - case DMA_DIR_MEM_TO_DEV: - case DMA_DIR_LMEM_TO_HMEM: + case SOF_DMA_DIR_MEM_TO_DEV: + case SOF_DMA_DIR_LMEM_TO_HMEM: elem_array->elems[i].src = dma_buffer_addr; elem_array->elems[i].dest = external_addr; break; @@ -180,48 +322,200 @@ int dma_sg_alloc(struct dma_sg_elem_array *elem_array, return 0; } -void dma_sg_free(struct dma_sg_elem_array *elem_array) +void dma_sg_free(struct k_heap *heap, struct dma_sg_elem_array *elem_array) { - rfree(elem_array->elems); + sof_heap_free(heap, elem_array->elems); dma_sg_init(elem_array); } -void dma_buffer_copy_from(struct comp_buffer *source, uint32_t source_bytes, - struct comp_buffer *sink, uint32_t sink_bytes, - dma_process_func process, uint32_t samples) +int dma_buffer_copy_from(struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t source_bytes, uint32_t chmap) { + int source_channels = audio_stream_get_channels(&source->stream); + int sink_channels = audio_stream_get_channels(&sink->stream); + int source_samples; + int sink_bytes; struct audio_stream *istream = &source->stream; + int ret; + + /* WORKAROUND: Given that remapping conversion can alter the number of channels, it's + * necessary to use frames, not samples, to calculate sink_bytes for writeback/produce. + * Unfortunately, the Host DMA imposes size alignment requirement for chunks of data + * being copied. For certain frame sizes, this alignment constraint results in splitting + * the first and/or last frame in the buffer. Consequently, frame-based calculations + * cannot be used with Host DMA. Fortunately, remapping conversion is specifically + * designed for use with IPC4 DAI gateway's device posture feature. IPC4 DAI gateway + * does not have the same size alignment limitations. Therefore, frame-based calculations + * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping + * conversion that modifies number of channels. + */ + if (source_channels == sink_channels) { + /* Sample-based calculations can be used here since the source and sink have + * the same number of samples. Frame-based calculations, however, cannot be used + * in this scenario, as it might involve a gateway that does not supply full frames + * (e.g., the Host gateway). + */ + source_samples = source_bytes / audio_stream_sample_bytes(istream); + sink_bytes = source_samples * audio_stream_sample_bytes(&sink->stream); + } else { + int frames; + + /* Sample-based calculations cannot be used here since source and sink have + * different number of samples. Fortunately, only IPC4 DAI gateway supports + * remapping conversion -- it's safe to use frame-based calculations in this + * context. + */ + assert(source_channels); + assert(sink_channels); + + frames = source_bytes / audio_stream_frame_bytes(istream); + sink_bytes = audio_stream_frame_bytes(&sink->stream) * frames; + source_samples = frames * source_channels; + } /* source buffer contains data copied by DMA */ audio_stream_invalidate(istream, source_bytes); /* process data */ - process(istream, 0, &sink->stream, 0, samples); + ret = process(istream, 0, &sink->stream, 0, source_samples, chmap); - buffer_writeback(sink, sink_bytes); - - istream->r_ptr = (char *)istream->r_ptr + source_bytes; - istream->r_ptr = audio_stream_wrap(istream, istream->r_ptr); + buffer_stream_writeback(sink, sink_bytes); + /* + * consume istream using audio_stream API because this buffer doesn't + * appear in topology so notifier event is not needed + */ + audio_stream_consume(istream, source_bytes); comp_update_buffer_produce(sink, sink_bytes); + + return ret; } -void dma_buffer_copy_to(struct comp_buffer *source, uint32_t source_bytes, - struct comp_buffer *sink, uint32_t sink_bytes, - dma_process_func process, uint32_t samples) +int dma_buffer_copy_to(struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t sink_bytes, uint32_t chmap) { + int source_channels = audio_stream_get_channels(&source->stream); + int sink_channels = audio_stream_get_channels(&sink->stream); + int source_samples; + int source_bytes; struct audio_stream *ostream = &sink->stream; + int ret; - buffer_invalidate(source, source_bytes); + /* WORKAROUND: Given that remapping conversion can alter the number of channels, it's + * necessary to use frames, not samples, to calculate source_bytes for invalidate/consume. + * Unfortunately, the Host DMA imposes size alignment requirement for chunks of data + * being copied. For certain frame sizes, this alignment constraint results in splitting + * the first and/or last frame in the buffer. Consequently, frame-based calculations + * cannot be used with Host DMA. Fortunately, remapping conversion is specifically + * designed for use with IPC4 DAI gateway's device posture feature. IPC4 DAI gateway + * does not have the same size alignment limitations. Therefore, frame-based calculations + * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping + * conversion that modifies number of channels. + */ + if (source_channels == sink_channels) { + /* Sample-based calculations can be used here since the source and sink have + * the same number of samples. Frame-based calculations, however, cannot be used + * in this scenario, as it might involve a gateway that does not supply full frames + * (e.g., the Host gateway). + */ + source_samples = sink_bytes / audio_stream_sample_bytes(ostream); + source_bytes = source_samples * audio_stream_sample_bytes(&source->stream); + } else { + int frames; + + /* Sample-based calculations cannot be used here since source and sink have + * different number of samples. Fortunately, only IPC4 DAI gateway supports + * remapping conversion -- it's safe to use frame-based calculations in this + * context. + */ + assert(source_channels); + assert(sink_channels); + + frames = sink_bytes / audio_stream_frame_bytes(ostream); + source_bytes = audio_stream_frame_bytes(&source->stream) * frames; + source_samples = frames * source_channels; + } + + buffer_stream_invalidate(source, source_bytes); /* process data */ - process(&source->stream, 0, ostream, 0, samples); + ret = process(&source->stream, 0, ostream, 0, source_samples, chmap); /* sink buffer contains data meant to copied to DMA */ audio_stream_writeback(ostream, sink_bytes); - ostream->w_ptr = (char *)ostream->w_ptr + sink_bytes; - ostream->w_ptr = audio_stream_wrap(ostream, ostream->w_ptr); - + /* + * produce ostream using audio_stream API because this buffer doesn't + * appear in topology so notifier event is not needed + */ + audio_stream_produce(ostream, sink_bytes); comp_update_buffer_consume(source, source_bytes); + + return ret; +} + +int stream_copy_from_no_consume(struct comp_dev *dev, struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t source_bytes, uint32_t chmap) +{ + int source_channels = audio_stream_get_channels(&source->stream); + int sink_channels = audio_stream_get_channels(&sink->stream); + int source_samples; + int sink_bytes; + struct audio_stream *istream = &source->stream; + int ret; + + /* WORKAROUND: Given that remapping conversion can alter the number of channels, it's + * necessary to use frames, not samples, to calculate sink_bytes for writeback/produce. + * Unfortunately, the Host DMA imposes size alignment requirement for chunks of data + * being copied. For certain frame sizes, this alignment constraint results in splitting + * the first and/or last frame in the buffer. Consequently, frame-based calculations + * cannot be used with Host DMA. Fortunately, remapping conversion is specifically + * designed for use with IPC4 DAI gateway's device posture feature. IPC4 DAI gateway + * does not have the same size alignment limitations. Therefore, frame-based calculations + * are employed only when necessary —- in the case of IPC4 DAI gateway with remapping + * conversion that modifies number of channels. + */ + if (source_channels == sink_channels) { + /* Sample-based calculations can be used here since the source and sink have + * the same number of samples. Frame-based calculations, however, cannot be used + * in this scenario, as it might involve a gateway that does not supply full frames + * (e.g., the Host gateway). + */ + source_samples = source_bytes / audio_stream_sample_bytes(istream); + sink_bytes = source_samples * audio_stream_sample_bytes(&sink->stream); + } else { + int frames; + + /* Sample-based calculations cannot be used here since source and sink have + * different number of samples. Fortunately, only IPC4 DAI gateway supports + * remapping conversion -- it's safe to use frame-based calculations in this + * context. + */ + assert(source_channels); + assert(sink_channels); + + frames = source_bytes / audio_stream_frame_bytes(istream); + sink_bytes = audio_stream_frame_bytes(&sink->stream) * frames; + source_samples = frames * source_channels; + } + + /* process data */ + ret = process(istream, 0, &sink->stream, 0, source_samples, chmap); + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + + if (cd->mic_priv) + mic_privacy_process(dev, cd->mic_priv, sink, source_samples); +#endif + + buffer_stream_writeback(sink, sink_bytes); + + comp_update_buffer_produce(sink, sink_bytes); + + return ret; } diff --git a/src/lib/lib.c b/src/lib/lib.c index b6ee1b1b43a2..62d92c214d8c 100644 --- a/src/lib/lib.c +++ b/src/lib/lib.c @@ -4,12 +4,16 @@ // // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -#include <sof/string.h> -#include <config.h> +#include <sof/common.h> +#include <rtos/string.h> +#include <sof/compiler_info.h> + #include <stddef.h> #include <stdint.h> -#if !CONFIG_LIBRARY +/* Not needed for host or Zephyr or CC uses LIBC */ +#if !CONFIG_LIBRARY && !__ZEPHYR__ && !defined(CC_USE_LIBC) + /* used by gcc - but uses arch_memcpy internally */ void *memcpy(void *dest, const void *src, size_t n) { @@ -22,19 +26,52 @@ void *memset(void *s, int c, size_t n) { uint8_t *d8 = s; uint8_t v = c; + uint32_t v32 = (uint32_t)v | ((uint32_t)v << 8) | + ((uint32_t)v << 16) | ((uint32_t)v << 24); + uint32_t *d32 = (void *)ALIGN_UP((uintptr_t)s, sizeof(uint32_t)); + /* Don't bother with 32-bit copies for up to 7 bytes */ + size_t prefix_sz = n > 2 * sizeof(v32) - 1 ? (uint8_t *)d32 - d8 : n; int i; - for (i = 0; i < n; i++) + for (i = 0; i < prefix_sz; i++) + d8[i] = v; + + /* This won't be executed if n <= 7 */ + for (i = 0; i < (n - prefix_sz) >> 2; i++) + d32[i] = v32; + + /* + * The starting point now is the prefix plus the number of 32-bit copies + * from the loop above, multiplied by 4. + * This won't be executed if n <= 7 + */ + for (i = prefix_sz + (i << 2); i < n; i++) d8[i] = v; return s; } + +int memcmp(const void *p, const void *q, size_t count) +{ + uint8_t *s1 = (uint8_t *)p; + uint8_t *s2 = (uint8_t *)q; + + while (count) { + if (*s1 != *s2) + return *s1 < *s2 ? -1 : 1; + s1++; + s2++; + count--; + } + return 0; +} + #endif int memcpy_s(void *dest, size_t dest_size, - const void *src, size_t src_size) + const void *src, size_t count) { - return arch_memcpy_s(dest, dest_size, src, src_size); + return arch_memcpy_s(dest, dest_size, src, count); } int memset_s(void *dest, size_t dest_size, int data, size_t count) @@ -42,6 +79,18 @@ int memset_s(void *dest, size_t dest_size, int data, size_t count) return arch_memset_s(dest, dest_size, data, count); } +#if !__XCC__ || !XCHAL_HAVE_HIFI3 || CONFIG_LIBRARY +void *__vec_memcpy(void *dst, const void *src, size_t len) +{ + return memcpy(dst, src, len); +} + +void *__vec_memset(void *dest, int data, size_t src_size) +{ + return memset(dest, data, src_size); +} +#endif + /* generic strlen - TODO: can be optimsed for ARCH ? */ int rstrlen(const char *s) { diff --git a/src/lib/notifier.c b/src/lib/notifier.c index c09fd6d2d9e2..e398417a6fd1 100644 --- a/src/lib/notifier.c +++ b/src/lib/notifier.c @@ -5,58 +5,81 @@ // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/idc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <rtos/panic.h> +#include <rtos/idc.h> +#include <rtos/interrupt.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/lib/cpu.h> #include <sof/lib/memory.h> #include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> #include <sof/list.h> -#include <sof/sof.h> +#include <rtos/sof.h> +#include <rtos/symbol.h> #include <ipc/topology.h> +#include <stdint.h> -#define trace_notifier(__e, ...) \ - trace_event(TRACE_CLASS_NOTIFIER, __e, ##__VA_ARGS__) -#define tracev_notifier(__e, ...) \ - tracev_event(TRACE_CLASS_NOTIFIER, __e, ##__VA_ARGS__) -#define trace_notifier_error(__e, ...) \ - trace_error(TRACE_CLASS_NOTIFIER, __e, ##__VA_ARGS__) +LOG_MODULE_REGISTER(notifier, CONFIG_SOF_LOG_LEVEL); -static SHARED_DATA struct notify_data notify_data[PLATFORM_CORE_COUNT]; +SOF_DEFINE_REG_UUID(notifier); + +DECLARE_TR_CTX(nt_tr, SOF_UUID(notifier_uuid), LOG_LEVEL_INFO); + +static SHARED_DATA struct notify_data notify_data_shared[CONFIG_CORE_COUNT]; struct callback_handle { void *receiver; void *caller; void (*cb)(void *arg, enum notify_id, void *data); struct list_item list; + uint32_t num_registrations; }; int notifier_register(void *receiver, void *caller, enum notify_id type, - void (*cb)(void *arg, enum notify_id type, void *data)) + void (*cb)(void *arg, enum notify_id type, void *data), + uint32_t flags) { struct notify *notify = *arch_notify_get(); struct callback_handle *handle; + k_spinlock_key_t key; + int ret = 0; assert(type >= NOTIFIER_ID_CPU_FREQ && type < NOTIFIER_ID_COUNT); - handle = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, + key = k_spin_lock(¬ify->lock); + + /* Find already registered event of this type */ + if (flags & NOTIFIER_FLAG_AGGREGATE && + !list_is_empty(¬ify->list[type])) { + handle = container_of((¬ify->list[type])->next, + struct callback_handle, list); + handle->num_registrations++; + + goto out; + } + + handle = rzalloc(SOF_MEM_FLAG_USER, sizeof(*handle)); if (!handle) { - trace_notifier_error("notifier_register() error: callback " - "handle allocation failed."); - return -ENOMEM; + tr_err(&nt_tr, "callback handle allocation failed."); + ret = -ENOMEM; + goto out; } handle->receiver = receiver; handle->caller = caller; handle->cb = cb; + handle->num_registrations = 1; list_item_prepend(&handle->list, ¬ify->list[type]); - return 0; +out: + k_spin_unlock(¬ify->lock, key); + return ret; } +EXPORT_SYMBOL(notifier_register); void notifier_unregister(void *receiver, void *caller, enum notify_id type) { @@ -64,9 +87,12 @@ void notifier_unregister(void *receiver, void *caller, enum notify_id type) struct list_item *wlist; struct list_item *tlist; struct callback_handle *handle; + k_spinlock_key_t key; assert(type >= NOTIFIER_ID_CPU_FREQ && type < NOTIFIER_ID_COUNT); + key = k_spin_lock(¬ify->lock); + /* * Unregister all matching callbacks * If receiver is NULL, unregister all callbacks with matching callers @@ -81,11 +107,16 @@ void notifier_unregister(void *receiver, void *caller, enum notify_id type) handle = container_of(wlist, struct callback_handle, list); if ((!receiver || handle->receiver == receiver) && (!caller || handle->caller == caller)) { - list_item_del(&handle->list); - rfree(handle); + if (!--handle->num_registrations) { + list_item_del(&handle->list); + rfree(handle); + } } } + + k_spin_unlock(¬ify->lock, key); } +EXPORT_SYMBOL(notifier_unregister); void notifier_unregister_all(void *receiver, void *caller) { @@ -118,13 +149,12 @@ void notifier_notify_remote(void) struct notify_data *notify_data = notify_data_get() + cpu_get_id(); if (!list_is_empty(¬ify->list[notify_data->type])) { - dcache_invalidate_region(notify_data->data, + dcache_invalidate_region((__sparse_force void __sparse_cache *)notify_data->data, notify_data->data_size); notifier_notify(notify_data->caller, notify_data->type, notify_data->data); } - platform_shared_commit(notify_data, sizeof(*notify_data)); } void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask, @@ -135,7 +165,7 @@ void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask, int i; /* notify selected targets */ - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { + for (i = 0; i < CONFIG_CORE_COUNT; i++) { if (core_mask & NOTIFIER_TARGET_CORE_MASK(i)) { if (i == cpu_get_id()) { notifier_notify(caller, type, data); @@ -151,11 +181,8 @@ void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask, notify_data->data = data; notify_data->data_size = data_size; - dcache_writeback_region(notify_data->data, - data_size); - - platform_shared_commit(notify_data, - sizeof(*notify_data)); + dcache_writeback_region((__sparse_force void __sparse_cache *) + notify_data->data, data_size); idc_send_msg(¬ify_msg, IDC_NON_BLOCKING); } @@ -167,15 +194,20 @@ void init_system_notify(struct sof *sof) { struct notify **notify = arch_notify_get(); int i; - *notify = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, + *notify = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(**notify)); + if (!*notify) { + tr_err(&nt_tr, "allocation failed"); + sof_panic(SOF_IPC_PANIC_IPC); + } + k_spinlock_init(&(*notify)->lock); for (i = NOTIFIER_ID_CPU_FREQ; i < NOTIFIER_ID_COUNT; i++) list_init(&(*notify)->list[i]); - if (cpu_get_id() == PLATFORM_MASTER_CORE_ID) - sof->notify_data = platform_shared_get(notify_data, - sizeof(notify_data)); + if (cpu_get_id() == PLATFORM_PRIMARY_CORE_ID) + sof->notify_data = platform_shared_get(notify_data_shared, + sizeof(notify_data_shared)); } void free_system_notify(void) diff --git a/src/lib/objpool.c b/src/lib/objpool.c new file mode 100644 index 000000000000..6925e6f7070a --- /dev/null +++ b/src/lib/objpool.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <rtos/alloc.h> +#include <rtos/bit.h> +#include <sof/objpool.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/lib/vregion.h> + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +struct objpool { + struct list_item list; + unsigned int n; + uint32_t mask; + size_t size; + uint8_t data[]; +}; + +#define OBJPOOL_BITS (sizeof(((struct objpool *)0)->mask) * 8) + +static int objpool_add(struct objpool_head *head, unsigned int n, size_t size, uint32_t flags) +{ + if (n > OBJPOOL_BITS) + return -ENOMEM; + + if (!is_power_of_2(n)) + return -EINVAL; + + size_t aligned_size = n * ALIGN_UP(size, sizeof(int)); + + if (!head->heap) + head->heap = sof_sys_heap_get(); + + struct objpool *pobjpool; + + if (!head->vreg) + pobjpool = sof_heap_alloc(head->heap, flags, + aligned_size + sizeof(*pobjpool), 0); + else if (flags & SOF_MEM_FLAG_COHERENT) + pobjpool = vregion_alloc_coherent(head->vreg, VREGION_MEM_TYPE_INTERIM, + aligned_size + sizeof(*pobjpool)); + else + pobjpool = vregion_alloc(head->vreg, VREGION_MEM_TYPE_INTERIM, + aligned_size + sizeof(*pobjpool)); + + if (!pobjpool) + return -ENOMEM; + + /* Initialize with 0 to give caller a chance to identify new allocations */ + memset(pobjpool->data, 0, aligned_size); + + pobjpool->n = n; + /* clear bit means free */ + pobjpool->mask = 0; + pobjpool->size = size; + + list_item_append(&pobjpool->list, &head->list); + + return 0; +} + +void *objpool_alloc(struct objpool_head *head, size_t size, uint32_t flags) +{ + size_t aligned_size = ALIGN_UP(size, sizeof(int)); + struct list_item *list; + struct objpool *pobjpool; + + /* Make sure size * 32 still fits in OBJPOOL_BITS bits */ + if (!size || aligned_size > (UINT_MAX >> 5) - sizeof(*pobjpool)) + return NULL; + + if (!list_is_empty(&head->list) && head->flags != flags) + /* List isn't empty, and flags don't match */ + return NULL; + + list_for_item(list, &head->list) { + pobjpool = container_of(list, struct objpool, list); + + uint32_t free_mask = MASK(pobjpool->n - 1, 0) & ~pobjpool->mask; + + /* sanity check */ + if (size != pobjpool->size) + return NULL; + + if (!free_mask) + continue; + + /* Find first free - guaranteed valid now */ + unsigned int bit = ffs(free_mask) - 1; + + pobjpool->mask |= BIT(bit); + + return pobjpool->data + aligned_size * bit; + } + + /* no free elements found */ + unsigned int new_n; + + if (list_is_empty(&head->list)) { + head->flags = flags; + new_n = 2; + } else { + /* Check the last one */ + pobjpool = container_of(head->list.prev, struct objpool, list); + + if (pobjpool->n == OBJPOOL_BITS) + new_n = OBJPOOL_BITS; + else + new_n = pobjpool->n << 1; + } + + if (objpool_add(head, new_n, size, flags) < 0) + return NULL; + + /* Return the first element of the new objpool, which is now the last one in the list */ + pobjpool = container_of(head->list.prev, struct objpool, list); + pobjpool->mask = 1; + + return pobjpool->data; +} + +int objpool_free(struct objpool_head *head, void *data) +{ + struct list_item *list; + struct objpool *pobjpool; + + if (!data) + return 0; + + list_for_item(list, &head->list) { + pobjpool = container_of(list, struct objpool, list); + + size_t aligned_size = ALIGN_UP(pobjpool->size, sizeof(int)); + + if ((uint8_t *)data >= pobjpool->data && + (uint8_t *)data < pobjpool->data + aligned_size * pobjpool->n) { + unsigned int n = ((uint8_t *)data - pobjpool->data) / aligned_size; + + if ((uint8_t *)data != pobjpool->data + n * aligned_size) + return -EINVAL; + + pobjpool->mask &= ~BIT(n); + + return 0; + } + } + + return -EINVAL; +} + +void objpool_prune(struct objpool_head *head) +{ + struct list_item *next, *tmp; + + list_for_item_safe(next, tmp, &head->list) { + struct objpool *pool = container_of(next, struct objpool, list); + + list_item_del(next); + if (head->vreg) + vregion_free(head->vreg, pool); + else + sof_heap_free(head->heap, pool); + } +} + +int objpool_iterate(struct objpool_head *head, objpool_iterate_cb cb, void *arg) +{ + struct list_item *list; + + list_for_item(list, &head->list) { + struct objpool *pobjpool = container_of(list, struct objpool, list); + size_t aligned_size = ALIGN_UP(pobjpool->size, sizeof(int)); + unsigned int bit; + + for (uint32_t mask = pobjpool->mask; mask; mask &= ~BIT(bit)) { + bit = ffs(mask) - 1; + + if (cb(pobjpool->data + bit * aligned_size, arg)) + return 0; + } + } + + return -ENOENT; +} diff --git a/src/lib/pm_runtime.c b/src/lib/pm_runtime.c deleted file mode 100644 index d7470a93eab2..000000000000 --- a/src/lib/pm_runtime.c +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -/** - * \file lib/pm_runtime.c - * \brief Runtime power management implementation - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_runtime.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <ipc/topology.h> -#include <stdint.h> - -void pm_runtime_init(struct sof *sof) -{ - sof->prd = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*sof->prd)); - spinlock_init(&sof->prd->lock); - - platform_pm_runtime_init(sof->prd); - - platform_shared_commit(sof->prd, sizeof(*sof->prd)); -} - -void pm_runtime_get(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_get()"); - - switch (context) { - default: - platform_pm_runtime_get(context, index, RPM_ASYNC); - break; - } -} - -void pm_runtime_get_sync(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_get_sync()"); - - switch (context) { - default: - platform_pm_runtime_get(context, index, 0); - break; - } -} - -void pm_runtime_put(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_put()"); - - switch (context) { - default: - platform_pm_runtime_put(context, index, RPM_ASYNC); - break; - } -} - -void pm_runtime_put_sync(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_put_sync()"); - - switch (context) { - default: - platform_pm_runtime_put(context, index, 0); - break; - } -} - -void pm_runtime_enable(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_enable()"); - - switch (context) { - default: - platform_pm_runtime_enable(context, index); - break; - } -} - -void pm_runtime_disable(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_disable()"); - - switch (context) { - default: - platform_pm_runtime_disable(context, index); - break; - } -} - -bool pm_runtime_is_active(enum pm_runtime_context context, uint32_t index) -{ - tracev_pm("pm_runtime_is_active()"); - - switch (context) { - default: - return platform_pm_runtime_is_active(context, index); - } -} diff --git a/src/lib/wait.c b/src/lib/wait.c deleted file mode 100644 index 9eb07be6b773..000000000000 --- a/src/lib/wait.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -/* - * Simple wait for event completion and signaling with timeouts. - */ - -#include <sof/lib/clk.h> -#include <sof/lib/io.h> -#include <sof/lib/wait.h> -#include <sof/platform.h> -#include <sof/schedule/schedule.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <errno.h> -#include <stdint.h> -#include <inttypes.h> - -#define DEFAULT_TRY_TIMES 8 - -int poll_for_register_delay(uint32_t reg, uint32_t mask, - uint32_t val, uint64_t us) -{ - uint64_t tick = clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * - us / 1000; - uint32_t tries = DEFAULT_TRY_TIMES; - uint64_t delta = tick / tries; - - if (!delta) { - delta = us; - tries = 1; - } - - while ((io_reg_read(reg) & mask) != val) { - if (!tries--) { - trace_error(TRACE_CLASS_WAIT, "ewt"); - return -EIO; - } - wait_delay(delta); - } - return 0; -} - -void wait_delay(uint64_t number_of_clks) -{ - struct timer *timer = timer_get(); - uint64_t current = platform_timer_get(timer); - - while ((platform_timer_get(timer) - current) < number_of_clks) - idelay(PLATFORM_DEFAULT_DELAY); -} diff --git a/src/library_manager/CMakeLists.txt b/src/library_manager/CMakeLists.txt new file mode 100644 index 000000000000..e69ca4cca30c --- /dev/null +++ b/src/library_manager/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_LIBRARY_MANAGER) + add_local_sources(sof lib_manager.c lib_notification.c) + + if (CONFIG_MM_DRV AND CONFIG_LLEXT) + add_local_sources(sof llext_manager.c) + if(CONFIG_LLEXT_EXPERIMENTAL AND NOT CONFIG_ADSP_IMR_CONTEXT_SAVE) + add_local_sources_ifdef(CONFIG_L3_HEAP sof llext_manager_dram.c) + endif() + endif() +endif() diff --git a/src/library_manager/Kconfig b/src/library_manager/Kconfig new file mode 100644 index 000000000000..8eac39e59970 --- /dev/null +++ b/src/library_manager/Kconfig @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Library manager configs + +menu "Library Manager" + +config LIBRARY_MANAGER + bool "Library Manager Support" + default n + depends on IPC_MAJOR_4 + help + This is support for dynamic modules loading. + Externally developed modules both for SOF and Zephyr + could be used if enabled. + If unsure say N. + +config LIBCODE_MODULE_SUPPORT + bool "Add support for libcode modules" + default n + depends on LIBRARY_MANAGER + help + A loadable library can contain a several modules marked + as lib_code. This modules contains code shared by + a multiple modules. This option adds support for modules + of this type. + +config LIBRARY_AUTH_SUPPORT + bool "Library Authentication Support" + default n + help + This is support for dynamic modules authentication. + Externally developed modules both for SOF and Zephyr + could be used if enabled. + If unsure say N. + +config LIBRARY_DEFAULT_MODULAR + bool "Build LLEXT modules by default" + depends on LLEXT + help + Build code, that can be built as LLEXT modules as such. Usually such + code has tristate Kconfig entries, they will default to "m" if this + option is selected. + +config LIBRARY_BUILD_LIB + bool "Pack LLEXT modules into a library" + depends on LLEXT + help + The first option to build LLEXT modules is to pack one module per + file. This option enables packing of all enabled modules into a single + module library. + +config LIBRARY_BASE_ADDRESS + hex "Base address for memory, dedicated to loadable modules" + default 0 + help + When initializing modules SOF will allocate memory for them and map + it to a predefined per-module address. Those addresses are calculated + automatically but the beginning of that area is platform-specific and + should be set by this option. + +config LIBRARY_REGION_SIZE + hex "Size of memory region dedicated to loadable modules" + default 0x100000 + help + Size of the virtual memory region dedicated for loadable modules + +endmenu diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c new file mode 100644 index 000000000000..b81ec6bbe738 --- /dev/null +++ b/src/library_manager/lib_manager.c @@ -0,0 +1,1178 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> +// Pawel Dobrowolski <pawelx.dobrowolski@intel.com> +// Adrian Warecki <adrian.warecki@intel.com> + +/* + * Dynamic module loading functions. + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/common.h> +#include <sof/compiler_attributes.h> +#include <sof/ipc/topology.h> + +#include <rtos/clk.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <rtos/userspace_helper.h> +#include <sof/lib/cpu-clk-manager.h> +#include <sof/lib_manager.h> +#include <sof/llext_manager.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/modules.h> +#include <sof/audio/module_adapter/library/userspace_proxy.h> +#include <utilities/array.h> +#include <system_agent.h> +#include <native_system_agent.h> +#include <api_version.h> +#include <module/module/api_ver.h> + +#include <zephyr/cache.h> +#include <zephyr/drivers/mm/system_mm.h> +#if CONFIG_LLEXT +#include <zephyr/llext/llext.h> +#endif + +#if CONFIG_LIBRARY_AUTH_SUPPORT +#include <auth/intel_auth_api.h> +#else +struct auth_api_ctx; +#endif + +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(lib_manager, CONFIG_SOF_LOG_LEVEL); +/* 54cf5598-8b29-11ec-a8a3-0242ac120002 */ + +SOF_DEFINE_REG_UUID(lib_manager); + +DECLARE_TR_CTX(lib_manager_tr, SOF_UUID(lib_manager_uuid), LOG_LEVEL_INFO); + +struct lib_manager_dma_ext { + struct sof_dma *dma; + struct dma_chan_data *chan; + uintptr_t dma_addr; /**< buffer start pointer */ + uint32_t addr_align; +}; + +static struct ext_library loader_ext_lib; + +#if CONFIG_LIBRARY_AUTH_SUPPORT +static int lib_manager_auth_init(struct auth_api_ctx *auth_ctx, void **auth_buffer) +{ + int ret; + + if (auth_api_version().major != AUTH_API_VERSION_MAJOR) + return -EINVAL; + + *auth_buffer = rballoc_align(SOF_MEM_FLAG_KERNEL, + AUTH_SCRATCH_BUFF_SZ, CONFIG_MM_DRV_PAGE_SIZE); + if (!*auth_buffer) + return -ENOMEM; + + ret = auth_api_init(auth_ctx, *auth_buffer, AUTH_SCRATCH_BUFF_SZ, IMG_TYPE_LIB); + if (ret != 0) { + tr_err(&lib_manager_tr, "auth_api_init() failed with error: %d", ret); + rfree(*auth_buffer); + return -EACCES; + } + + return 0; +} + +static void lib_manager_auth_deinit(struct auth_api_ctx *auth_ctx, void *auth_buffer) +{ + ARG_UNUSED(auth_ctx); + rfree(auth_buffer); +} + +static int lib_manager_auth_proc(const void *buffer_data, size_t buffer_size, + enum auth_phase phase, struct auth_api_ctx *auth_ctx) +{ + int ret; + + ret = auth_api_init_auth_proc(auth_ctx, buffer_data, buffer_size, phase); + + if (ret != 0) { + tr_err(&lib_manager_tr, "auth_api_init_auth_proc() failed with error: %d", ret); + return -ENOTSUP; + } + + /* The auth_api_busy() will timeouts internally in case of failure */ + while (auth_api_busy(auth_ctx)) + ; + + ret = auth_api_result(auth_ctx); + + if (ret != AUTH_IMAGE_TRUSTED) { + tr_err(&lib_manager_tr, "Untrusted library!"); + return -EACCES; + } + + if (phase == AUTH_PHASE_LAST) + auth_api_cleanup(auth_ctx); + + return 0; +} +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + +#if IS_ENABLED(CONFIG_MM_DRV) + +#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE + +static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_addr, uint32_t size, + uint32_t flags) +{ + /* Region must be first mapped as writable in order to initialize its contents. */ + int ret = sys_mm_drv_map_region((__sparse_force void *)vma, POINTER_TO_UINT(NULL), size, + SYS_MM_MEM_PERM_RW); + if (ret < 0) + return ret; + + ret = memcpy_s((__sparse_force void *)vma, size, s_addr, size); + if (ret < 0) + return ret; + + dcache_writeback_region(vma, size); + + return sys_mm_drv_update_region_flags((__sparse_force void *)vma, size, flags); +} + +static int lib_manager_load_module(const uint32_t module_id, const struct sof_man_module *const mod) +{ + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + const uintptr_t load_offset = POINTER_TO_UINT(ctx->base_addr); + void *src; + void __sparse_cache *va_base; + size_t size; + uint32_t flags; + int ret, idx; + + for (idx = 0; idx < ARRAY_SIZE(mod->segment); ++idx) { + if (!mod->segment[idx].flags.r.load) + continue; + + flags = 0; + + if (mod->segment[idx].flags.r.code) + flags = SYS_MM_MEM_PERM_EXEC; + else if (!mod->segment[idx].flags.r.readonly) + flags = SYS_MM_MEM_PERM_RW; + + src = UINT_TO_POINTER(mod->segment[idx].file_offset + load_offset); + va_base = (void __sparse_cache *)UINT_TO_POINTER(mod->segment[idx].v_base_addr); + size = mod->segment[idx].flags.r.length * PAGE_SZ; + ret = lib_manager_load_data_from_storage(va_base, src, size, flags); + if (ret < 0) + goto err; + } + + return 0; + +err: + for (--idx; idx >= 0; --idx) { + if (!mod->segment[idx].flags.r.load) + continue; + + va_base = (void __sparse_cache *)UINT_TO_POINTER(mod->segment[idx].v_base_addr); + size = mod->segment[idx].flags.r.length * PAGE_SZ; + sys_mm_drv_unmap_region((__sparse_force void *)va_base, size); + } + + return ret; +} + +static int lib_manager_unload_module(const struct sof_man_module *const mod) +{ + void __sparse_cache *va_base; + size_t size; + uint32_t idx; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(mod->segment); ++idx) { + if (!mod->segment[idx].flags.r.load) + continue; + + va_base = (void __sparse_cache *)UINT_TO_POINTER(mod->segment[idx].v_base_addr); + size = mod->segment[idx].flags.r.length * PAGE_SZ; + ret = sys_mm_drv_unmap_region((__sparse_force void *)va_base, size); + if (ret < 0) + return ret; + } + + return 0; +} + +#ifdef CONFIG_LIBCODE_MODULE_SUPPORT +/* There are modules marked as lib_code. This is code shared between several modules inside + * the library. Load all lib_code modules with first none lib_code module load. + */ +static int lib_manager_load_libcode_modules(const uint32_t module_id) +{ + const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(module_id); + struct ext_library *const ext_lib = ext_lib_get(); + const struct sof_man_module *module_entry = (struct sof_man_module *) + ((char *)desc + SOF_MAN_MODULE_OFFSET(0)); + const uint32_t lib_id = LIB_MANAGER_GET_LIB_ID(module_id); + int ret, idx; + + if (++ext_lib->mods_exec_load_cnt > 1) + return 0; + + for (idx = 0; idx < desc->header.num_module_entries; ++idx, ++module_entry) { + if (module_entry->type.lib_code) { + ret = lib_manager_load_module(lib_id << LIB_MANAGER_LIB_ID_SHIFT | idx, + module_entry); + if (ret < 0) + goto err; + } + } + + return 0; + +err: + for (--idx, --module_entry; idx >= 0; --idx, --module_entry) { + if (module_entry->type.lib_code) { + ret = lib_manager_unload_module(module_entry); + if (ret < 0) + goto err; + } + } + + return ret; +} + +/* There are modules marked as lib_code. This is code shared between several modules inside + * the library. Unload all lib_code modules with last none lib_code module unload. + */ +static int lib_manager_unload_libcode_modules(const uint32_t module_id) +{ + const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(module_id); + const struct sof_man_module *module_entry = (struct sof_man_module *) + ((char *)desc + SOF_MAN_MODULE_OFFSET(0)); + struct ext_library *const ext_lib = ext_lib_get(); + int ret, idx; + + if (--ext_lib->mods_exec_load_cnt > 0) + return 0; + + for (idx = 0; idx < desc->header.num_module_entries; ++idx, ++module_entry) { + if (module_entry->type.lib_code) { + ret = lib_manager_unload_module(module_entry); + if (ret < 0) + return ret; + } + } + + return 0; +} +#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */ + +void lib_manager_get_instance_bss_address(uint32_t instance_id, + const struct sof_man_module *mod, + void __sparse_cache **va_addr, size_t *size) +{ + *size = mod->segment[SOF_MAN_SEGMENT_BSS].flags.r.length / mod->instance_max_count * + PAGE_SZ; + size_t inst_offset = *size * instance_id; + *va_addr = (void __sparse_cache *)(mod->segment[SOF_MAN_SEGMENT_BSS].v_base_addr + + inst_offset); + + tr_dbg(&lib_manager_tr, "instance_bss_size: %#zx, pointer: %p", *size, + (__sparse_force void *)*va_addr); +} + +static int lib_manager_allocate_module_instance(uint32_t instance_id, uint32_t is_pages, + const struct sof_man_module *mod) +{ + size_t bss_size; + void __sparse_cache *va_base; + + lib_manager_get_instance_bss_address(instance_id, mod, &va_base, &bss_size); + + if ((is_pages * PAGE_SZ) > bss_size) { + tr_err(&lib_manager_tr, "invalid is_pages: %u, required: %u", + is_pages, bss_size / PAGE_SZ); + return -ENOMEM; + } + + /* + * Map bss memory and clear it. + */ + if (sys_mm_drv_map_region((__sparse_force void *)va_base, POINTER_TO_UINT(NULL), + bss_size, SYS_MM_MEM_PERM_RW) < 0) + return -ENOMEM; + + memset((__sparse_force void *)va_base, 0, bss_size); + + return 0; +} + +static int lib_manager_free_module_instance(uint32_t instance_id, const struct sof_man_module *mod) +{ + size_t bss_size; + void __sparse_cache *va_base; + + lib_manager_get_instance_bss_address(instance_id, mod, &va_base, &bss_size); + /* + * Unmap bss memory. + */ + return sys_mm_drv_unmap_region((__sparse_force void *)va_base, bss_size); +} + +/* + * \brief Allocate module + * + * param[in] mod - module manifest + * param[in] ipc_config - audio component base configuration from IPC at creation + * param[in] ipc_specific_config - ipc4 base configuration + * + * Function is responsible to allocate module in available free memory and assigning proper address. + */ +static uintptr_t lib_manager_allocate_module(const struct sof_man_module *mod, + const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config) +{ + const struct ipc4_base_module_cfg *base_cfg = ipc_specific_config; + const uint32_t module_id = IPC4_MOD_ID(ipc_config->id); + int ret; + + tr_dbg(&lib_manager_tr, "mod_id: %#x", ipc_config->id); + + if (module_is_llext(mod)) + return llext_manager_allocate_module(ipc_config, ipc_specific_config); + + ret = lib_manager_load_module(module_id, mod); + if (ret < 0) + return 0; + +#ifdef CONFIG_LIBCODE_MODULE_SUPPORT + ret = lib_manager_load_libcode_modules(module_id); + if (ret < 0) + goto err; +#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */ + + ret = lib_manager_allocate_module_instance(IPC4_INST_ID(ipc_config->id), base_cfg->is_pages, + mod); + if (ret < 0) { + tr_err(&lib_manager_tr, "module allocation failed: %d", ret); +#ifdef CONFIG_LIBCODE_MODULE_SUPPORT + lib_manager_unload_libcode_modules(module_id); +#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */ + goto err; + } + return mod->entry_point; + +err: + lib_manager_unload_module(mod); + return 0; +} + +/* + * \brief Free module + * + * param[in] component_id - component id coming from ipc config. This function reguires valid + * lib_id and module_id fields of component id. + * + * Function is responsible to free module resources in HP memory. + */ +static int lib_manager_free_module(const uint32_t component_id) +{ + const struct sof_man_module *mod; + const uint32_t module_id = IPC4_MOD_ID(component_id); + int ret; + + tr_dbg(&lib_manager_tr, "mod_id: %#x", component_id); + + mod = lib_manager_get_module_manifest(module_id); + if (!mod) { + tr_err(&lib_manager_tr, "failed to get module descriptor"); + return -EINVAL; + } + + if (module_is_llext(mod)) + return llext_manager_free_module(component_id); + + ret = lib_manager_unload_module(mod); + if (ret < 0) + return ret; + +#ifdef CONFIG_LIBCODE_MODULE_SUPPORT + ret = lib_manager_unload_libcode_modules(module_id); + if (ret < 0) + return ret; +#endif /* CONFIG_LIBCODE_MODULE_SUPPORT */ + + ret = lib_manager_free_module_instance(IPC4_INST_ID(component_id), mod); + if (ret < 0) { + tr_err(&lib_manager_tr, "free module instance failed: %d", ret); + return ret; + } + return 0; +} + +#else /* CONFIG_MM_DRV */ + +#define PAGE_SZ 4096 /* equals to MAN_PAGE_SIZE used by rimage */ + +static uintptr_t lib_manager_allocate_module(const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config, const void **buildinfo) +{ + tr_err(&lib_manager_tr, "Dynamic module allocation is not supported"); + return 0; +} + +static int lib_manager_free_module(const uint32_t component_id) +{ + /* Since we cannot allocate the freeing is not considered to be an error */ + tr_warn(&lib_manager_tr, "Dynamic module freeing is not supported"); + return 0; +} +#endif /* CONFIG_MM_DRV */ + +void lib_manager_init(void) +{ + struct sof *sof = sof_get(); + + if (!sof->ext_library) + sof->ext_library = &loader_ext_lib; +} + +const struct sof_man_fw_desc *lib_manager_get_library_manifest(int module_id) +{ + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + uint8_t *buffptr = ctx ? ctx->base_addr : NULL; + + if (!buffptr) + return NULL; + return (struct sof_man_fw_desc *)(buffptr + SOF_MAN_ELF_TEXT_OFFSET); +} + +static void lib_manager_update_sof_ctx(void *base_addr, uint32_t lib_id) +{ + struct ext_library *_ext_lib = ext_lib_get(); + /* Never freed, will panic if fails */ + struct lib_manager_mod_ctx *ctx = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(*ctx)); + if (!ctx) { + tr_err(&lib_manager_tr, "allocation failed"); + sof_panic(SOF_IPC_PANIC_IPC); + } + + ctx->base_addr = base_addr; + + _ext_lib->desc[lib_id] = ctx; + /* TODO: maybe need to call dcache_writeback here? */ +} + +const struct sof_man_module *lib_manager_get_module_manifest(const uint32_t module_id) +{ + const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); + const struct lib_manager_mod_ctx *const ctx = lib_manager_get_mod_ctx(module_id); + const struct sof_man_fw_desc *desc; + + if (!ctx || !ctx->base_addr) + return NULL; + + desc = (const struct sof_man_fw_desc *)((const char *)ctx->base_addr + + SOF_MAN_ELF_TEXT_OFFSET); + + if (entry_index >= desc->header.num_module_entries) { + tr_err(&lib_manager_tr, "Entry index %d out of bounds.", entry_index); + return NULL; + } + + return (const struct sof_man_module *)((const char *)desc + + SOF_MAN_MODULE_OFFSET(entry_index)); +} + +/** + * \brief Starts system agent and returns module interface into agent_interface variable. + * + * \param[in] drv - Pointer to the component driver structure. + * \param[in] config - Pointer to component ipc config structure + * \param[in] args - Pointer to components' ipc configuration arguments. + * \param[in] module_entry_point - Entry point address of the module. + * \param[in] agent - Function pointer to the system agent start function. + * \param[out] agent_interface - Pointer to store the module interface returned by the system agent. + * \param[out] userspace - Pointer to store the userspace module proxy context. + * \param[out] ops - Pointer to store pointer to the module interface structure. + * + * \return Error code returned by the system agent, 0 on success. + */ +static int lib_manager_start_agent(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const struct sof_man_module *mod_manifest, + const struct ipc_config_process *args, + const uintptr_t module_entry_point, + const system_agent_start_fn agent, + const void **agent_interface, + struct userspace_context **userspace, + const struct module_interface **ops) +{ + struct system_agent_params agent_params; + byte_array_t mod_cfg; + int ret; + + mod_cfg.data = (uint8_t *)args->data; + /* Intel modules expects DW size here */ + mod_cfg.size = args->size >> 2; + + agent_params.entry_point = module_entry_point; + agent_params.module_id = IPC4_MOD_ID(config->id); + agent_params.instance_id = IPC4_INST_ID(config->id); + agent_params.core_id = config->core; + agent_params.log_handle = (uint32_t)drv->tctx; + agent_params.mod_cfg = &mod_cfg; + +#if CONFIG_SOF_USERSPACE_PROXY + /* If drv->user_heap is allocated, it means the module is userspace. */ + if (drv->user_heap) { + ret = userspace_proxy_create(userspace, drv, mod_manifest, agent, &agent_params, + agent_interface, ops); + if (ret) + tr_err(&lib_manager_tr, "userspace_proxy_create failed! %d", ret); + return ret; + } +#endif /* CONFIG_SOF_USERSPACE_PROXY */ + + ret = agent(&agent_params, agent_interface); + if (ret) + tr_err(&lib_manager_tr, "System agent start failed %d!", ret); + + return ret; +} + +enum buildinfo_mod_type { MOD_TYPE_INVALID, MOD_TYPE_IADK, MOD_TYPE_LMDK, MOD_TYPE_LLEXT }; + +/** + * \brief Get module type based on its build information. + * + * \param[in] desc - Pointer to the firmware descriptor containing module information. + * \param[in] mod - Pointer to the module manifest structure. + * + * \return The type of the module as an enum value. + */ +static enum buildinfo_mod_type lib_manager_get_module_type(const struct sof_man_fw_desc *const desc, + const struct sof_man_module *mod) +{ + const struct sof_module_api_build_info *const build_info = + (const struct sof_module_api_build_info *)((const char *)desc - + SOF_MAN_ELF_TEXT_OFFSET + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + + /* + * llext modules store build info structure in separate section which is not accessible now. + */ + if (module_is_llext(mod)) + return MOD_TYPE_LLEXT; + + tr_info(&lib_manager_tr, "Module API version: %u.%u.%u, format: 0x%x", + build_info->api_version_number.fields.major, + build_info->api_version_number.fields.middle, + build_info->api_version_number.fields.minor, + build_info->format); + + /* Check if module is IADK */ + if (IS_ENABLED(CONFIG_INTEL_MODULES) && + build_info->format == IADK_MODULE_API_BUILD_INFO_FORMAT && + build_info->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { + return MOD_TYPE_IADK; + } else { + /* Check if module is NOT native */ + if (build_info->format != SOF_MODULE_API_BUILD_INFO_FORMAT || + build_info->api_version_number.full != SOF_MODULE_API_CURRENT_VERSION) { + tr_err(&lib_manager_tr, "Unsupported module API version"); + return MOD_TYPE_INVALID; + } + + return MOD_TYPE_LMDK; + } +} + +/* + * \brief Load module code, allocate its instance and create a module adapter component. + * \param[in] drv - component driver pointer. + * \param[in] config - component ipc descriptor pointer. + * \param[in] spec - passdowned data from driver. + * + * \return: a pointer to newly created module adapter component on success. NULL on error. + */ +static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + const struct sof_man_fw_desc *const desc = lib_manager_get_library_manifest(config->id); + const struct ipc_config_process *args = (const struct ipc_config_process *)spec; + const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(config->id); + struct userspace_context *userspace = NULL; + const struct module_interface *ops; + const struct sof_man_module *mod; + system_agent_start_fn agent; + void *adapter_priv = NULL; + const void **agent_iface; + struct comp_dev *dev; + int ret; + +#ifdef CONFIG_SOF_USERSPACE_PROXY + if (drv->user_heap && config->proc_domain != COMP_PROCESSING_DOMAIN_DP) { + tr_err(&lib_manager_tr, "Userspace supports only DP modules."); + return NULL; + } +#endif + + tr_dbg(&lib_manager_tr, "start"); + if (!desc) { + tr_err(&lib_manager_tr, "Error: Couldn't find loadable module with id %u.", + config->id); + return NULL; + } + + if (entry_index >= desc->header.num_module_entries) { + tr_err(&lib_manager_tr, "Entry index %u out of bounds.", entry_index); + return NULL; + } + + mod = (const struct sof_man_module *) + ((const uint8_t *)desc + SOF_MAN_MODULE_OFFSET(entry_index)); + + const uintptr_t module_entry_point = lib_manager_allocate_module(mod, config, args->data); + + if (!module_entry_point) { + tr_err(&lib_manager_tr, "lib_manager_allocate_module() failed!"); + return NULL; + } + + switch (lib_manager_get_module_type(desc, mod)) { + case MOD_TYPE_LLEXT: + agent = NULL; + ops = (const struct module_interface *)module_entry_point; + break; + case MOD_TYPE_LMDK: + agent = &native_system_agent_start; + agent_iface = (const void **)&ops; + break; +#if CONFIG_INTEL_MODULES + case MOD_TYPE_IADK: + agent = &system_agent_start; + ops = &processing_module_adapter_interface; + agent_iface = (const void **)&adapter_priv; + break; +#endif + case MOD_TYPE_INVALID: + goto err; + } + + /* At this point module resources are allocated and it is moved to L2 memory. */ + if (agent) { + ret = lib_manager_start_agent(drv, config, mod, args, module_entry_point, agent, + agent_iface, &userspace, &ops); + if (ret) + goto err; + } + + if (comp_set_adapter_ops(drv, ops) < 0) + goto err; + + dev = module_adapter_new_ext(drv, config, spec, adapter_priv, userspace); + if (!dev) + goto err; + + return dev; + +err: +#if CONFIG_SOF_USERSPACE_PROXY + if (userspace) + userspace_proxy_destroy(drv, userspace); +#endif /* CONFIG_SOF_USERSPACE_PROXY */ + lib_manager_free_module(config->id); + return NULL; +} + +static void lib_manager_module_free(struct comp_dev *dev) +{ + uint32_t component_id = dev->ipc_config.id; + int ret; + + /* This call invalidates dev, mod and config pointers! */ + module_adapter_free(dev); + + /* Free module resources allocated in L2 memory. */ + ret = lib_manager_free_module(component_id); + if (ret < 0) + tr_err(&lib_manager_tr, "lib_manager_free_module() failed!"); +} + +static void lib_manager_prepare_module_adapter(struct comp_driver *drv, const struct sof_uuid *uuid) +{ + drv->type = SOF_COMP_MODULE_ADAPTER; + drv->uid = uuid; + drv->tctx = &lib_manager_tr; + drv->ops.create = lib_manager_module_create; + drv->ops.prepare = module_adapter_prepare; + drv->ops.params = module_adapter_params; + drv->ops.copy = module_adapter_copy; +#if CONFIG_IPC_MAJOR_3 + drv->ops.cmd = module_adapter_cmd; +#endif + drv->ops.trigger = module_adapter_trigger; + drv->ops.reset = module_adapter_reset; + drv->ops.free = lib_manager_module_free; + drv->ops.set_large_config = module_set_large_config; + drv->ops.get_large_config = module_get_large_config; + drv->ops.get_attribute = module_adapter_get_attribute; + drv->ops.set_attribute = module_adapter_set_attribute; + drv->ops.bind = module_adapter_bind; + drv->ops.unbind = module_adapter_unbind; + drv->ops.get_total_data_processed = module_adapter_get_total_data_processed; + drv->ops.dai_get_hw_params = module_adapter_get_hw_params; + drv->ops.position = module_adapter_position; + drv->ops.dai_ts_config = module_adapter_ts_config_op; + drv->ops.dai_ts_start = module_adapter_ts_start_op; + drv->ops.dai_ts_stop = module_adapter_ts_stop_op; + drv->ops.dai_ts_get = module_adapter_ts_get_op; +} + +int lib_manager_register_module(const uint32_t component_id) +{ + const struct sof_man_module *mod = lib_manager_get_module_manifest(component_id); + const struct sof_uuid *uid = (struct sof_uuid *)&mod->uuid; + struct comp_driver_info *new_drv_info; + struct k_heap *drv_heap = NULL; + struct comp_driver *drv = NULL; + int ret = -ENOMEM; + + if (!mod) { + tr_err(&lib_manager_tr, "Error: Couldn't find loadable module with id %u.", + component_id); + return -ENOENT; + } + + /* allocate new comp_driver_info */ + new_drv_info = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct comp_driver_info)); + + if (!new_drv_info) { + tr_err(&lib_manager_tr, "failed to allocate comp_driver_info"); + return -ENOMEM; + } + +#if CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP + if (mod->type.user_mode) { + drv_heap = module_driver_heap_init(); + if (!drv_heap) { + tr_err(&lib_manager_tr, "failed to allocate driver heap!"); + goto cleanup; + } + } +#endif /* CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP */ + + drv = sof_heap_alloc(drv_heap, SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct comp_driver), 0); + if (!drv) { + tr_err(&lib_manager_tr, "failed to allocate comp_driver"); + goto cleanup; + } + + memset(drv, 0, sizeof(*drv)); + drv->user_heap = drv_heap; + + lib_manager_prepare_module_adapter(drv, uid); + + /* Fill the new_drv_info structure with already known parameters */ + new_drv_info->drv = drv; + new_drv_info->adapter_ops = &drv->adapter_ops; + + /* Register new driver in the list */ + ret = comp_register(new_drv_info); + +cleanup: + if (ret < 0) { + rfree(new_drv_info); + sof_heap_free(drv_heap, drv); + module_driver_heap_remove(drv_heap); + } + + return ret; +} + +static int lib_manager_dma_buffer_alloc(struct lib_manager_dma_ext *dma_ext, + uint32_t size) +{ + /* + * allocate new buffer: this is the actual DMA buffer but we + * traditionally allocate a cached address for it + */ + dma_ext->dma_addr = (uintptr_t)rballoc_align(SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, size, + dma_ext->addr_align); + if (!dma_ext->dma_addr) { + tr_err(&lib_manager_tr, "alloc failed"); + return -ENOMEM; + } + + tr_dbg(&lib_manager_tr, "address: %#lx, size: %u", dma_ext->dma_addr, size); + + return 0; +} + +/** + * \brief Start, init and alloc DMA and buffer used by loader. + * + * \return 0 on success, error code otherwise. + */ +static int lib_manager_dma_init(struct lib_manager_dma_ext *dma_ext, uint32_t dma_id) +{ + int chan_index; + + /* Initialize dma_ext with zeros */ + memset(dma_ext, 0, sizeof(struct lib_manager_dma_ext)); + /* request DMA in the dir HMEM->LMEM */ + dma_ext->dma = sof_dma_get(SOF_DMA_DIR_HMEM_TO_LMEM, 0, SOF_DMA_DEV_HOST, + SOF_DMA_ACCESS_EXCLUSIVE); + if (!dma_ext->dma) { + tr_err(&lib_manager_tr, "dma_ext->dma = NULL"); + return -ENODEV; + } + + chan_index = dma_request_channel(dma_ext->dma->z_dev, &dma_id); + dma_ext->chan = &dma_ext->dma->chan[chan_index]; + if (!dma_ext->chan) + return -EINVAL; + + return 0; +} + +/** + * \brief Stop, deinit and free DMA and buffer used by loader. + * + * \return 0 on success, error code otherwise. + */ + +static int lib_manager_dma_deinit(struct lib_manager_dma_ext *dma_ext, uint32_t dma_id) +{ + if (dma_ext->dma) { + if (dma_ext->dma->z_dev) + dma_release_channel(dma_ext->dma->z_dev, dma_id); + + sof_dma_put(dma_ext->dma); + } + return 0; +} + +static int lib_manager_load_data_from_host(struct lib_manager_dma_ext *dma_ext, uint32_t size) +{ + uint64_t timeout = k_ms_to_cyc_ceil64(200); + struct dma_status stat; + int ret; + + /* Wait till whole data acquired with timeout of 200ms */ + timeout += sof_cycle_get_64(); + + for (;;) { + ret = dma_get_status(dma_ext->chan->dma->z_dev, + dma_ext->chan->index, &stat); + if (ret < 0 || stat.pending_length >= size) + return ret; + + if (sof_cycle_get_64() > timeout) + break; + + k_usleep(100); + } + + tr_err(&lib_manager_tr, "timeout during DMA transfer"); + return -ETIMEDOUT; +} + +static int lib_manager_store_data(struct lib_manager_dma_ext *dma_ext, + void __sparse_cache *dst_addr, uint32_t dst_size) +{ + uint32_t copied_bytes = 0; + + while (copied_bytes < dst_size) { + uint32_t bytes_to_copy; + int ret; + + if ((dst_size - copied_bytes) > MAN_MAX_SIZE_V1_8) + bytes_to_copy = MAN_MAX_SIZE_V1_8; + else + bytes_to_copy = dst_size - copied_bytes; + + ret = lib_manager_load_data_from_host(dma_ext, bytes_to_copy); + if (ret < 0) + return ret; + + memcpy_s((__sparse_force uint8_t *)dst_addr + copied_bytes, bytes_to_copy, + (void *)dma_ext->dma_addr, bytes_to_copy); + copied_bytes += bytes_to_copy; + dma_reload(dma_ext->chan->dma->z_dev, dma_ext->chan->index, 0, 0, bytes_to_copy); + } + + return 0; +} + +static void __sparse_cache *lib_manager_allocate_store_mem(uint32_t size, + uint32_t attribs) +{ + void __sparse_cache *local_add; +#if CONFIG_L3_HEAP + uint32_t flags = SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_L3 | SOF_MEM_FLAG_DMA; +#else + uint32_t flags = SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_DMA; +#endif + + uint32_t addr_align = PAGE_SZ; + /* allocate new buffer: cached alias */ + local_add = (__sparse_force void __sparse_cache *)rballoc_align(flags, size, addr_align); + + if (!local_add) { + tr_err(&lib_manager_tr, "alloc failed"); + return NULL; + } + + return local_add; +} + +static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, + const void __sparse_cache *man_buffer, + uint32_t lib_id, struct auth_api_ctx *auth_ctx) +{ + void __sparse_cache *library_base_address; + const struct sof_man_fw_desc *man_desc = (struct sof_man_fw_desc *) + ((__sparse_force uint8_t *)man_buffer + SOF_MAN_ELF_TEXT_OFFSET); + uint32_t preload_size = man_desc->header.preload_page_count * PAGE_SZ; + int ret; + + /* + * The module manifest structure always has its maximum size regardless of + * the actual size of the manifest. + */ + if (preload_size < MAN_MAX_SIZE_V1_8) { + tr_err(&lib_manager_tr, "Invalid preload_size value %x.", preload_size); + return -EINVAL; + } + + /* Prepare storage memory, note: it is never freed, library unloading is unsupported */ + /* + * Prepare storage memory, note: it is never freed, it is assumed, that this + * memory is abundant, so we store all loaded modules there permanently + */ + library_base_address = lib_manager_allocate_store_mem(preload_size, 0); + if (!library_base_address) + return -ENOMEM; + + tr_dbg(&lib_manager_tr, "pointer: %p", (__sparse_force void *)library_base_address); + +#if CONFIG_LIBRARY_AUTH_SUPPORT + /* AUTH_PHASE_FIRST - checks library manifest only. */ + ret = lib_manager_auth_proc((__sparse_force const void *)man_buffer, + MAN_MAX_SIZE_V1_8, AUTH_PHASE_FIRST, auth_ctx); + if (ret < 0) { + rfree((__sparse_force void *)library_base_address); + return ret; + } +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + + /* Copy data from temp_mft_buf to destination memory (pointed by library_base_address) */ + memcpy_s((__sparse_force void *)library_base_address, MAN_MAX_SIZE_V1_8, + (__sparse_force const void *)man_buffer, MAN_MAX_SIZE_V1_8); + + /* Copy remaining library part into storage buffer */ + ret = lib_manager_store_data(dma_ext, (uint8_t __sparse_cache *)library_base_address + + MAN_MAX_SIZE_V1_8, preload_size - MAN_MAX_SIZE_V1_8); + if (ret < 0) { + rfree((__sparse_force void *)library_base_address); + return ret; + } + + /* Writeback entire library to ensure it's visible to other cores */ + dcache_writeback_region((__sparse_force void *)library_base_address, preload_size); + +#if CONFIG_LIBRARY_AUTH_SUPPORT + /* AUTH_PHASE_LAST - do final library authentication checks */ + ret = lib_manager_auth_proc((__sparse_force void *)library_base_address, + preload_size - MAN_MAX_SIZE_V1_8, AUTH_PHASE_LAST, auth_ctx); + if (ret < 0) { + rfree((__sparse_force void *)library_base_address); + return ret; + } +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + + /* Now update sof context with new library */ + lib_manager_update_sof_ctx((__sparse_force void *)library_base_address, lib_id); + + return 0; +} + +static int lib_manager_setup(uint32_t dma_id) +{ + struct ext_library *_ext_lib = ext_lib_get(); + struct lib_manager_dma_ext *dma_ext; + struct dma_block_config dma_block_cfg = { + .block_size = MAN_MAX_SIZE_V1_8, + .flow_control_mode = 1, + }; + struct dma_config config = { + .channel_direction = HOST_TO_MEMORY, + .source_data_size = sizeof(uint32_t), + .dest_data_size = sizeof(uint32_t), + .block_count = 1, + .head_block = &dma_block_cfg, + }; + int ret; + + if (_ext_lib->runtime_data) + return 0; + + dma_ext = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(*dma_ext)); + if (!dma_ext) + return -ENOMEM; + + ret = lib_manager_dma_init(dma_ext, dma_id); + if (ret < 0) + goto err_dma_init; + + ret = dma_get_attribute(dma_ext->dma->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &dma_ext->addr_align); + if (ret < 0) + goto err_dma_init; + + ret = lib_manager_dma_buffer_alloc(dma_ext, MAN_MAX_SIZE_V1_8); + if (ret < 0) + goto err_dma_buffer; + + dma_block_cfg.dest_address = dma_ext->dma_addr; + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + /* + * make sure that the DSP is running full speed for the duration of + * library loading + */ + ret = core_kcps_adjust(cpu_get_id(), CLK_MAX_CPU_HZ / 1000); + if (ret < 0) + goto err_dma_buffer; +#endif + + ret = dma_config(dma_ext->chan->dma->z_dev, dma_ext->chan->index, &config); + if (ret < 0) + goto err_dma; + + ret = dma_start(dma_ext->chan->dma->z_dev, dma_ext->chan->index); + if (ret < 0) + goto err_dma; + + _ext_lib->runtime_data = dma_ext; + + return 0; + +err_dma: +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + core_kcps_adjust(cpu_get_id(), -(CLK_MAX_CPU_HZ / 1000)); +#endif + +err_dma_buffer: + lib_manager_dma_deinit(dma_ext, dma_id); + +err_dma_init: + rfree(dma_ext); + return ret; +} + +int lib_manager_load_library(uint32_t dma_id, uint32_t lib_id, uint32_t type) +{ + void __sparse_cache *man_tmp_buffer; + struct lib_manager_dma_ext *dma_ext; + struct ext_library *_ext_lib; + int ret, ret2; + + if (type == SOF_IPC4_GLB_LOAD_LIBRARY && + (lib_id == 0 || lib_id >= LIB_MANAGER_MAX_LIBS)) { + tr_err(&lib_manager_tr, "invalid lib_id: %u", lib_id); + return -EINVAL; + } + + lib_manager_init(); + + _ext_lib = ext_lib_get(); + + if (type == SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE || !_ext_lib->runtime_data) { + ret = lib_manager_setup(dma_id); + if (ret) + return ret; + + if (type == SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE) + return 0; + } + + dma_ext = _ext_lib->runtime_data; + + /* allocate temporary manifest buffer */ + man_tmp_buffer = (__sparse_force void __sparse_cache *) + rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + MAN_MAX_SIZE_V1_8, CONFIG_MM_DRV_PAGE_SIZE); + if (!man_tmp_buffer) { + ret = -ENOMEM; + goto cleanup; + } + + /* Load manifest to temporary buffer. */ + ret = lib_manager_store_data(dma_ext, man_tmp_buffer, MAN_MAX_SIZE_V1_8); + if (ret < 0) + goto stop_dma; + +#if CONFIG_LIBRARY_AUTH_SUPPORT + struct auth_api_ctx auth_ctx; + void *auth_buffer; + + /* Initialize authentication support */ + ret = lib_manager_auth_init(&auth_ctx, &auth_buffer); + if (ret < 0) + goto stop_dma; + + ret = lib_manager_store_library(dma_ext, man_tmp_buffer, lib_id, &auth_ctx); + + lib_manager_auth_deinit(&auth_ctx, auth_buffer); +#else + ret = lib_manager_store_library(dma_ext, man_tmp_buffer, lib_id, NULL); +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + +stop_dma: + ret2 = dma_stop(dma_ext->chan->dma->z_dev, dma_ext->chan->index); + if (ret2 < 0) { + tr_err(&lib_manager_tr, "error stopping DMA: %d", ret); + if (!ret) + ret = ret2; + } + + rfree((__sparse_force void *)man_tmp_buffer); + +cleanup: + rfree((void *)dma_ext->dma_addr); + lib_manager_dma_deinit(dma_ext, dma_id); + rfree(dma_ext); + _ext_lib->runtime_data = NULL; + + uint32_t module_id = lib_id << LIB_MANAGER_LIB_ID_SHIFT; + const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id); + + if (!ret && module_is_llext(mod)) + /* Auxiliary LLEXT libraries need to be linked upon loading */ + ret = llext_manager_add_library(module_id); + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + core_kcps_adjust(cpu_get_id(), -(CLK_MAX_CPU_HZ / 1000)); +#endif + + if (!ret) + tr_info(&lib_manager_tr, "loaded library id: %u", lib_id); + + return ret; +} diff --git a/src/library_manager/lib_notification.c b/src/library_manager/lib_notification.c new file mode 100644 index 000000000000..36aa85835e70 --- /dev/null +++ b/src/library_manager/lib_notification.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> +// Pawel Dobrowolski <pawelx.dobrowolski@intel.com> +// + +/* + * 3-rd party modules do not have access to component device runtime data. + * System service API used by these modules require notification handling + * based on base FW message management. Therefore this code expose notification + * calls aligned with cAVS/ACE System service API requirements. + */ +#include <rtos/sof.h> +#include <sof/list.h> +#include <sof/ipc/msg.h> +#include <sof/lib/memory.h> +#include <sof/lib_manager.h> + +LOG_MODULE_DECLARE(lib_manager, LOG_LEVEL_INFO); + +struct ipc_msg *lib_notif_msg_init(uint32_t header, uint32_t size) +{ + struct ipc_msg *msg = NULL; + struct ipc_lib_msg *msg_pool_elem; + struct ext_library *ext_lib = ext_lib_get(); + struct ipc_lib_msg *lib_notif = ext_lib->lib_notif_pool; + + /* If list not empty search for free notification handle */ + if (lib_notif && !list_is_empty(&lib_notif->list)) { + struct list_item *list_elem; + /* Search for not used message handle */ + list_for_item(list_elem, &lib_notif->list) { + msg_pool_elem = container_of(list_elem, struct ipc_lib_msg, list); + if (msg_pool_elem->msg && list_is_empty(&msg_pool_elem->msg->list)) { + msg = msg_pool_elem->msg; + break; + } + } + } + + if (!msg) { + k_spinlock_key_t key; + /* No free element or list empty, create new handle */ + if (ext_lib->lib_notif_count > LIB_MANAGER_LIB_NOTIX_MAX_COUNT) { + tr_dbg(&lib_manager_tr, "LIB_MANAGER_LIB_NOTIX_MAX_COUNT < %d", + ext_lib->lib_notif_count); + return NULL; + } + + msg_pool_elem = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*msg_pool_elem)); + if (!msg_pool_elem) + return NULL; + msg = ipc_msg_init(header, SRAM_OUTBOX_SIZE); + if (!msg) { + rfree(msg_pool_elem); + return NULL; + } + msg_pool_elem->msg = msg; + ext_lib->lib_notif_count++; + list_init(&msg_pool_elem->list); + /* Check if there is no rece between modules on separate cores */ + if (ext_lib->lib_notif_count > 1) { + key = k_spin_lock(&ext_lib->lock); + list_item_append(&msg_pool_elem->list, &lib_notif->list); + k_spin_unlock(&ext_lib->lock, key); + } else { + ext_lib->lib_notif_pool = msg_pool_elem; + } + } + /* Update header and size, since message handle can be reused */ + msg->header = header; + msg->tx_size = size; + return msg; +} + +void lib_notif_msg_send(struct ipc_msg *msg) +{ + ipc_msg_send(msg, msg->tx_data, false); + lib_notif_msg_clean(true); +} + +void lib_notif_msg_clean(bool leave_one_handle) +{ + struct list_item *list_elem, *list_tmp; + struct ipc_lib_msg *msg_pool_elem; + struct ext_library *ext_lib = ext_lib_get(); + struct ipc_lib_msg *lib_notif = ext_lib->lib_notif_pool; + + /* Free all unused elements except the last one */ + list_for_item_safe(list_elem, list_tmp, &lib_notif->list) { + msg_pool_elem = container_of(list_elem, struct ipc_lib_msg, list); + assert(msg_pool_elem->msg); + + if (list_is_empty(&msg_pool_elem->msg->list)) { + k_spinlock_key_t key; + + key = k_spin_lock(&ext_lib->lock); + list_item_del(&msg_pool_elem->list); + k_spin_unlock(&ext_lib->lock, key); + ipc_msg_free(msg_pool_elem->msg); + rfree(msg_pool_elem); + ext_lib->lib_notif_count--; + } + } + + /* Remove last handle - this should happen when there is no external libraries */ + if (!leave_one_handle && (list_is_empty(&lib_notif->list))) { + k_spinlock_key_t key; + + ipc_msg_free(lib_notif->msg); + key = k_spin_lock(&ext_lib->lock); + list_item_del(&lib_notif->list); + k_spin_unlock(&ext_lib->lock, key); + rfree(lib_notif); + ext_lib->lib_notif_pool = NULL; + ext_lib->lib_notif_count--; + } +} diff --git a/src/library_manager/llext_manager.c b/src/library_manager/llext_manager.c new file mode 100644 index 000000000000..a370a5f1c7f7 --- /dev/null +++ b/src/library_manager/llext_manager.c @@ -0,0 +1,1101 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> +// Pawel Dobrowolski<pawelx.dobrowolski@intel.com> + +/* + * Dynamic module loading functions using Zephyr Linkable Loadable Extensions (LLEXT) interface. + */ + +#include <sof/audio/buffer.h> +#include <sof/audio/component_ext.h> +#include <sof/common.h> +#include <sof/compiler_attributes.h> +#include <sof/ipc/topology.h> + +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/lib/cpu-clk-manager.h> +#include <sof/lib_manager.h> +#include <sof/lib/regions_mm.h> +#include <sof/llext_manager.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/module/modules.h> + +#include <zephyr/cache.h> +#include <zephyr/app_memory/mem_domain.h> +#include <zephyr/drivers/mm/system_mm.h> +#include <zephyr/llext/buf_loader.h> +#include <zephyr/llext/loader.h> +#include <zephyr/llext/llext.h> +#include <zephyr/logging/log_ctrl.h> +#include <zephyr/llext/inspect.h> +#include <kernel_arch_interface.h> + +#include <rimage/sof/user/manifest.h> +#include <module/module/api_ver.h> + +#include <adsp_memory_regions.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(lib_manager, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx lib_manager_tr; + +#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE + +static int llext_manager_update_flags(void __sparse_cache *vma, size_t size, uint32_t flags) +{ + size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); + void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; + + return sys_mm_drv_update_region_flags(aligned_vma, + ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); +} + +static int llext_manager_align_map(const struct sys_mm_drv_region *virtual_region, + void __sparse_cache *vma, size_t size, uint32_t flags) +{ + size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); + void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; + return sys_mm_drv_map_region_safe(virtual_region, aligned_vma, POINTER_TO_UINT(NULL), + ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); +} + +static int llext_manager_align_unmap(void __sparse_cache *vma, size_t size) +{ + size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); + void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; + + return sys_mm_drv_unmap_region(aligned_vma, ALIGN_UP(pre_pad_size + size, PAGE_SZ)); +} + +static void llext_manager_detached_update_flags(void __sparse_cache *vma, + size_t size, uint32_t flags) +{ +#ifdef CONFIG_MMU + size_t pre_pad_size = (uintptr_t)vma & (PAGE_SZ - 1); + void *aligned_vma = (__sparse_force uint8_t *)vma - pre_pad_size; + + /* Use cached virtual address */ + uintptr_t va = POINTER_TO_UINT(sys_cache_cached_ptr_get(aligned_vma)); + + arch_mem_map(aligned_vma, va, ALIGN_UP(pre_pad_size + size, PAGE_SZ), flags); +#endif +} + +/* + * Map the memory range covered by 'vma' and 'size' as writable, copy all + * sections that belong to the specified 'region' and are contained in the + * memory range, then remap the same area according to the 'flags' parameter. + */ +static int llext_manager_load_data_from_storage(const struct sys_mm_drv_region *virtual_region, + const struct llext_loader *ldr, + const struct llext *ext, + enum llext_mem region, + void __sparse_cache *vma, + size_t size, uint32_t flags) +{ + unsigned int i; + const void *region_addr; + + /* check if there region to be mapped exists */ + if (size == 0) + return 0; + + int ret = llext_manager_align_map(virtual_region, vma, size, SYS_MM_MEM_PERM_RW); + + if (ret < 0) { + tr_err(&lib_manager_tr, "cannot map %u of %p", size, (__sparse_force void *)vma); + return ret; + } + + llext_get_region_info(ldr, ext, region, NULL, ®ion_addr, NULL); + + /* Need to copy sections within regions individually, offsets may differ */ + for (i = 0; i < llext_section_count(ext); i++) { + const elf_shdr_t *shdr; + enum llext_mem s_region = LLEXT_MEM_COUNT; + size_t s_offset = 0; + int ret = llext_get_section_info(ldr, ext, i, &shdr, &s_region, &s_offset); + + if (ret < 0) { + tr_err(&lib_manager_tr, "no section info: %d", ret); + continue; + } + + /* skip sections not in the requested region */ + if (s_region != region) + continue; + + /* skip detached sections (will be outside requested VMA area) */ + if ((uintptr_t)shdr->sh_addr < (uintptr_t)vma || + (uintptr_t)shdr->sh_addr >= (uintptr_t)vma + size) { + llext_manager_detached_update_flags((__sparse_cache void *) + ((uint8_t *)region_addr + s_offset), + shdr->sh_size, flags); + if (flags & SYS_MM_MEM_PERM_EXEC) + icache_invalidate_region((__sparse_cache void *) + ((uint8_t *)region_addr + s_offset), + shdr->sh_size); + continue; + } + + ret = memcpy_s((__sparse_force void *)shdr->sh_addr, size - s_offset, + (const uint8_t *)region_addr + s_offset, shdr->sh_size); + if (ret < 0) + return ret; + } + + /* + * We don't know what flags we're changing to, maybe the buffer will be + * executable or read-only. Need to write back caches now + */ + dcache_writeback_region(vma, size); + + ret = llext_manager_update_flags(vma, size, flags); + if (!ret && (flags & SYS_MM_MEM_PERM_EXEC)) + icache_invalidate_region(vma, size); + + return ret; +} + +static void llext_manager_unmap_detached_sections(const struct llext_loader *ldr, + const struct llext *ext, + enum llext_mem region, + void __sparse_cache *vma, + size_t size) +{ +#ifdef CONFIG_MMU + unsigned int i; + const void *region_addr; + + llext_get_region_info(ldr, ext, region, NULL, ®ion_addr, NULL); + + for (i = 0; i < llext_section_count(ext); i++) { + const elf_shdr_t *shdr; + enum llext_mem s_region = LLEXT_MEM_COUNT; + size_t s_offset = 0; + + llext_get_section_info(ldr, ext, i, &shdr, &s_region, &s_offset); + + /* skip sections not in the requested region */ + if (s_region != region) + continue; + + /* unmap detached sections (will be outside requested VMA area) */ + if ((uintptr_t)shdr->sh_addr < (uintptr_t)vma || + (uintptr_t)shdr->sh_addr >= (uintptr_t)vma + size) + llext_manager_detached_update_flags((__sparse_force void *) + ((uint8_t *)region_addr + s_offset), + shdr->sh_size, 0); + } +#endif +} + +static int llext_manager_load_module(struct lib_manager_module *mctx) +{ + /* Executable code (.text) */ + void __sparse_cache *va_base_text = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_TEXT].addr; + size_t text_size = mctx->segment[LIB_MANAGER_TEXT].size; + + /* Read-only data (.rodata and others) */ + void __sparse_cache *va_base_rodata = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_RODATA].addr; + size_t rodata_size = mctx->segment[LIB_MANAGER_RODATA].size; + + /* Writable data (.data, .bss and others) */ + void __sparse_cache *va_base_data = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_DATA].addr; + size_t data_size = mctx->segment[LIB_MANAGER_DATA].size; + + /* .bss, should be within writable data above */ + void __sparse_cache *bss_addr = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_BSS].addr; + size_t bss_size = mctx->segment[LIB_MANAGER_BSS].size; + int ret; + + /* Check, that .bss is within .data */ + if (bss_size && + ((uintptr_t)bss_addr + bss_size <= (uintptr_t)va_base_data || + (uintptr_t)bss_addr >= (uintptr_t)va_base_data + data_size)) { + size_t bss_align = MIN(PAGE_SZ, BIT(__builtin_ctz((uintptr_t)bss_addr))); + + if ((!data_size || (uintptr_t)bss_addr + bss_size == (uintptr_t)va_base_data) && + bss_align >= PAGE_SZ) { + /* + * .bss is properly aligned and either there's no writable data, + * or .bss is directly in front of writable data, prepend .bss + */ + va_base_data = bss_addr; + data_size += bss_size; + } else if ((uintptr_t)bss_addr == (uintptr_t)va_base_data + + ALIGN_UP(data_size, bss_align)) { + /* .bss directly behind writable data, append */ + data_size += bss_size; + } else { + tr_err(&lib_manager_tr, ".bss %#x @%p isn't within writable data %#x @%p!", + bss_size, (__sparse_force void *)bss_addr, + data_size, (__sparse_force void *)va_base_data); + return -EPROTO; + } + } + + const struct llext_loader *ldr = &mctx->ebl->loader; + const struct llext *ext = mctx->llext; + + /* find dedicated virtual memory zone */ + const struct sys_mm_drv_region *virtual_memory_regions = sys_mm_drv_query_memory_regions(); + const struct sys_mm_drv_region *virtual_region; + + if (!virtual_memory_regions) + return -EFAULT; + + SYS_MM_DRV_MEMORY_REGION_FOREACH(virtual_memory_regions, virtual_region) { + if (virtual_region->attr == VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR) + break; + } + + if (!virtual_region->size) + return -EFAULT; + + /* Copy Code */ + ret = llext_manager_load_data_from_storage(virtual_region, ldr, ext, LLEXT_MEM_TEXT, + va_base_text, text_size, SYS_MM_MEM_PERM_EXEC); + if (ret < 0) + return ret; + + /* Copy read-only data */ + ret = llext_manager_load_data_from_storage(virtual_region, ldr, ext, LLEXT_MEM_RODATA, + va_base_rodata, rodata_size, 0); + if (ret < 0) + goto e_text; + + /* Copy writable data */ + /* + * NOTE: va_base_data and data_size refer to an address range that + * spans over the BSS area as well, so the mapping will cover + * both, but only LLEXT_MEM_DATA sections will be copied. + */ + ret = llext_manager_load_data_from_storage(virtual_region, ldr, ext, LLEXT_MEM_DATA, + va_base_data, data_size, SYS_MM_MEM_PERM_RW); + if (ret < 0) + goto e_rodata; + + memset((__sparse_force void *)bss_addr, 0, bss_size); + mctx->mapped = true; + + return 0; + +e_rodata: + if (rodata_size) + llext_manager_align_unmap(va_base_rodata, rodata_size); +e_text: + llext_manager_align_unmap(va_base_text, text_size); + + return ret; +} + +static int llext_manager_unload_module(struct lib_manager_module *mctx) +{ + const struct llext_loader *ldr = &mctx->ebl->loader; + const struct llext *ext = mctx->llext; + + /* Executable code (.text) */ + void __sparse_cache *va_base_text = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_TEXT].addr; + size_t text_size = mctx->segment[LIB_MANAGER_TEXT].size; + + /* Read-only data (.rodata, etc.) */ + void __sparse_cache *va_base_rodata = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_RODATA].addr; + size_t rodata_size = mctx->segment[LIB_MANAGER_RODATA].size; + + /* Writable data (.data, .bss, etc.) */ + void __sparse_cache *va_base_data = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_DATA].addr; + void __sparse_cache *va_base_bss = (void __sparse_cache *) + mctx->segment[LIB_MANAGER_BSS].addr; + size_t data_size = mctx->segment[LIB_MANAGER_DATA].size + + mctx->segment[LIB_MANAGER_BSS].size; + int err = 0, ret; + + llext_manager_unmap_detached_sections(ldr, ext, LLEXT_MEM_TEXT, + va_base_text, text_size); + ret = llext_manager_align_unmap(va_base_text, text_size); + if (ret < 0) + err = ret; + + /* Mimic the logic from load_module where the .bss address is used for mapping + * in case of e.g. lack of writable .data section + */ + if (!va_base_data) + va_base_data = va_base_bss; + + llext_manager_unmap_detached_sections(ldr, ext, LLEXT_MEM_DATA, + va_base_data, data_size); + ret = llext_manager_align_unmap(va_base_data, data_size); + if (ret < 0 && !err) + err = ret; + + llext_manager_unmap_detached_sections(ldr, ext, LLEXT_MEM_RODATA, + va_base_rodata, rodata_size); + ret = llext_manager_align_unmap(va_base_rodata, rodata_size); + if (ret < 0 && !err) + err = ret; + + mctx->mapped = false; + + return err; +} + +static bool llext_manager_section_detached(const elf_shdr_t *shdr) +{ + return shdr->sh_addr < SOF_MODULE_DRAM_LINK_END; +} + +static int llext_manager_link(const char *name, + struct lib_manager_module *mctx, const void **buildinfo, + const struct sof_man_module_manifest **mod_manifest) +{ + struct llext **llext = &mctx->llext; + struct llext_loader *ldr = &mctx->ebl->loader; + const elf_shdr_t *hdr; + int ret; + + if (*llext && !mctx->mapped) { + /* + * All module instances have been terminated, so we freed SRAM, + * but we kept the full Zephyr LLEXT context. Now a new instance + * is starting, so we just re-use all the configuration and only + * re-allocate SRAM and copy the module into it + */ + *mod_manifest = mctx->mod_manifest; + + return 0; + } + + if (!*llext || mctx->mapped) { + /* + * Either the very first time loading this module, or the module + * is already mapped, we just call llext_load() to refcount it + */ + struct llext_load_param ldr_parm = { + .relocate_local = !*llext, + .pre_located = true, + .section_detached = llext_manager_section_detached, + .keep_section_info = true, + }; + + ret = llext_load(ldr, name, llext, &ldr_parm); + if (ret) + return ret; + } + + /* All code sections */ + llext_get_region_info(ldr, *llext, LLEXT_MEM_TEXT, &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_TEXT].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_TEXT].size = hdr->sh_size; + + tr_dbg(&lib_manager_tr, ".text: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_TEXT].addr, + mctx->segment[LIB_MANAGER_TEXT].size); + + /* All read-only data sections */ + llext_get_region_info(ldr, *llext, LLEXT_MEM_RODATA, &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_RODATA].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_RODATA].size = hdr->sh_size; + + tr_dbg(&lib_manager_tr, ".rodata: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_RODATA].addr, + mctx->segment[LIB_MANAGER_RODATA].size); + + /* All writable data sections */ + llext_get_region_info(ldr, *llext, LLEXT_MEM_DATA, &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_DATA].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_DATA].size = hdr->sh_size; + + tr_dbg(&lib_manager_tr, ".data: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_DATA].addr, + mctx->segment[LIB_MANAGER_DATA].size); + + /* Writable uninitialized data section */ + llext_get_region_info(ldr, *llext, LLEXT_MEM_BSS, &hdr, NULL, NULL); + mctx->segment[LIB_MANAGER_BSS].addr = hdr->sh_addr; + mctx->segment[LIB_MANAGER_BSS].size = hdr->sh_size; + + tr_dbg(&lib_manager_tr, ".bss: start: %#lx size %#x", + mctx->segment[LIB_MANAGER_BSS].addr, + mctx->segment[LIB_MANAGER_BSS].size); + + *buildinfo = NULL; + ret = llext_section_shndx(ldr, *llext, ".mod_buildinfo"); + if (ret >= 0) { + llext_get_section_info(ldr, *llext, ret, &hdr, NULL, NULL); + *buildinfo = llext_peek(ldr, hdr->sh_offset); + } + + *mod_manifest = NULL; + ret = llext_section_shndx(ldr, *llext, ".module"); + if (ret >= 0) { + llext_get_section_info(ldr, *llext, ret, &hdr, NULL, NULL); + *mod_manifest = llext_peek(ldr, hdr->sh_offset); + } + + return *buildinfo && *mod_manifest ? 0 : -EPROTO; +} + +/* Count "module files" in the library, allocate and initialize memory for their descriptors */ +static int llext_manager_mod_init(struct lib_manager_mod_ctx *ctx, + const struct sof_man_fw_desc *desc) +{ + struct sof_man_module *mod_array = (struct sof_man_module *)((uint8_t *)desc + + SOF_MAN_MODULE_OFFSET(0)); + unsigned int i, n_mod; + size_t offs; + + /* count modules */ + for (i = 0, n_mod = 0, offs = ~0; i < desc->header.num_module_entries; i++) + if (mod_array[i].segment[LIB_MANAGER_TEXT].file_offset != offs) { + offs = mod_array[i].segment[LIB_MANAGER_TEXT].file_offset; + n_mod++; + } + + /* + * Loadable modules are loaded to DRAM once and never unloaded from it. + * Context, related to them, is never freed + */ + ctx->mod = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + n_mod * sizeof(ctx->mod[0])); + if (!ctx->mod) + return -ENOMEM; + + ctx->n_mod = n_mod; + + for (i = 0, n_mod = 0, offs = ~0; i < desc->header.num_module_entries; i++) + if (mod_array[i].segment[LIB_MANAGER_TEXT].file_offset != offs) { + offs = mod_array[i].segment[LIB_MANAGER_TEXT].file_offset; + ctx->mod[n_mod].mapped = false; + ctx->mod[n_mod].llext = NULL; + ctx->mod[n_mod].ebl = NULL; + ctx->mod[n_mod].n_dependent = 0; + ctx->mod[n_mod++].start_idx = i; + } + + return 0; +} + +/* Find a module context, containing the driver with the supplied index */ +static unsigned int llext_manager_mod_find(const struct lib_manager_mod_ctx *ctx, unsigned int idx) +{ + unsigned int i; + + for (i = 0; i < ctx->n_mod; i++) + if (ctx->mod[i].start_idx > idx) + break; + + return i - 1; +} + +static int llext_manager_link_single(uint32_t module_id, const struct sof_man_fw_desc *desc, + struct lib_manager_mod_ctx *ctx, const void **buildinfo, + const struct sof_man_module_manifest **mod_manifest) +{ + struct sof_man_module *mod_array = (struct sof_man_module *)((uint8_t *)desc + + SOF_MAN_MODULE_OFFSET(0)); + uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); + size_t mod_offset = mod_array[entry_index].segment[LIB_MANAGER_TEXT].file_offset; + int ret; + + tr_dbg(&lib_manager_tr, "mod_id: %u", module_id); + + if (entry_index >= desc->header.num_module_entries) { + tr_err(&lib_manager_tr, "Invalid driver index %u exceeds %d", + entry_index, desc->header.num_module_entries - 1); + return -EINVAL; + } + + unsigned int mod_ctx_idx = llext_manager_mod_find(ctx, entry_index); + struct lib_manager_module *mctx = ctx->mod + mod_ctx_idx; + size_t mod_size; + int i, inst_idx; + + /* + * We don't know the number of ELF files that this library is built of. + * We know the number of module drivers, but each of those ELF files can + * also contain multiple such drivers. Each driver brings two copies of + * its manifest with it: one in the ".module" ELF section and one in an + * array of manifests at the beginning of the library. This latter array + * is created from a TOML configuration file. The order is preserved - + * this is guaranteed by rimage. + * All module drivers within a single ELF file have equal .file_offset, + * this makes it possible to find borders between them. + * We know the global index of the requested driver in that array, but + * we need to find the matching manifest in ".module" because only it + * contains the entry point. For safety we calculate the ELF driver + * index and then also check the driver name. + * We also need a module size. For this we search the manifest array for + * the next ELF file, then the difference between offsets gives us the + * module size. + */ + for (i = entry_index - 1; i >= 0; i--) + if (mod_array[i].segment[LIB_MANAGER_TEXT].file_offset != mod_offset) + break; + + /* Driver index within a single module */ + inst_idx = entry_index - i - 1; + + /* Find the next module or stop at the end */ + for (i = entry_index + 1; i < desc->header.num_module_entries; i++) + if (mod_array[i].segment[LIB_MANAGER_TEXT].file_offset != mod_offset) + break; + + if (i == desc->header.num_module_entries) + mod_size = desc->header.preload_page_count * PAGE_SZ - mod_offset; + else + mod_size = ALIGN_UP(mod_array[i].segment[LIB_MANAGER_TEXT].file_offset - mod_offset, + PAGE_SZ); + + if (!mctx->ebl) { + /* allocate once, never freed */ + mctx->ebl = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(struct llext_buf_loader)); + if (!mctx->ebl) { + tr_err(&lib_manager_tr, "loader alloc failed"); + return -ENOMEM; + } + + uint8_t *dram_base = (uint8_t *)desc - SOF_MAN_ELF_TEXT_OFFSET; + + *mctx->ebl = (struct llext_buf_loader)LLEXT_BUF_LOADER(dram_base + mod_offset, + mod_size); + } + + /* + * LLEXT linking is only needed once for all the "drivers" in the + * module. This calls llext_load(), which also takes references to any + * dependencies, sets up sections and retrieves buildinfo and + * mod_manifest + */ + ret = llext_manager_link(mod_array[entry_index - inst_idx].name, mctx, + buildinfo, mod_manifest); + if (ret < 0) { + tr_err(&lib_manager_tr, "linking failed: %d", ret); + return ret; + } + + /* if ret > 0, then the "driver" is already loaded */ + if (!ret) + /* mctx->mod_manifest points to a const array of module manifests */ + mctx->mod_manifest = *mod_manifest; + + /* Return the manifest, related to the specific instance */ + *mod_manifest = mctx->mod_manifest + inst_idx; + + if (strncmp(mod_array[entry_index].name, (*mod_manifest)->module.name, + sizeof(mod_array[0].name))) { + tr_err(&lib_manager_tr, "Name mismatch %s vs. %s", + mod_array[entry_index].name, (*mod_manifest)->module.name); + return -ENOEXEC; + } + + return mod_ctx_idx; +} + +static int llext_lib_find(const struct llext *llext, struct lib_manager_module **dep_ctx) +{ + struct ext_library *_ext_lib = ext_lib_get(); + unsigned int i, j; + + if (!llext) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(_ext_lib->desc); i++) { + if (!_ext_lib->desc[i]) + continue; + + for (j = 0; j < _ext_lib->desc[i]->n_mod; j++) + if (_ext_lib->desc[i]->mod[j].llext == llext) { + *dep_ctx = _ext_lib->desc[i]->mod + j; + return i; + } + } + + return -ENOENT; +} + +/* n can be -1 */ +static void llext_manager_depend_unlink_rollback(struct lib_manager_module *dep_ctx[], int n) +{ + for (; n >= 0; n--) + if (!dep_ctx[n]) + tr_err(&lib_manager_tr, "dependency %d NULL", n); + else if (!--dep_ctx[n]->n_dependent) + llext_manager_unload_module(dep_ctx[n]); +} + +uintptr_t llext_manager_allocate_module(const struct comp_ipc_config *ipc_config, + const void *ipc_specific_config) +{ + uint32_t module_id = IPC4_MOD_ID(ipc_config->id); + /* Library manifest */ + const struct sof_man_fw_desc *desc = (struct sof_man_fw_desc *) + lib_manager_get_library_manifest(module_id); + /* Library context */ + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + + if (!ctx || !desc) { + tr_err(&lib_manager_tr, "failed to get module descriptor"); + return 0; + } + + /* Array of all "module drivers" (manifests) in the library */ + const struct sof_man_module_manifest *mod_manifest; + const struct sof_module_api_build_info *buildinfo = NULL; + + /* "module file" index in the ctx->mod array */ + int mod_ctx_idx = llext_manager_link_single(module_id, desc, ctx, + (const void **)&buildinfo, &mod_manifest); + + if (mod_ctx_idx < 0) + return 0; + + struct lib_manager_module *mctx = ctx->mod + mod_ctx_idx; + + if (buildinfo) { + /* First instance: check that the module is native */ + if (buildinfo->format != SOF_MODULE_API_BUILD_INFO_FORMAT || + buildinfo->api_version_number.full != SOF_MODULE_API_CURRENT_VERSION) { + tr_err(&lib_manager_tr, "Unsupported module API version"); + return 0; + } + } + + if (!mctx->mapped) { + int i, ret; + + /* + * Check if any dependencies need to be mapped - collect + * pointers to library contexts + */ + struct lib_manager_module *dep_ctx[LLEXT_MAX_DEPENDENCIES] = {}; + + for (i = 0; i < ARRAY_SIZE(mctx->llext->dependency); i++) { + struct lib_manager_module *dep; + + /* Dependencies are filled from the beginning of the array upwards */ + if (!mctx->llext->dependency[i]) + break; + + ret = llext_lib_find(mctx->llext->dependency[i], &dep); + if (ret < 0) { + tr_err(&lib_manager_tr, + "Unmet dependency: cannot find dependency %u", i); + continue; + } + + tr_dbg(&lib_manager_tr, "%s depending on %s index %u, %u users", + mctx->llext->name, mctx->llext->dependency[i]->name, + dep->start_idx, dep->n_dependent); + + /* + * Protected by the IPC serialization, but maybe we should protect the + * dependent-count explicitly too. It is incremented when a new dependent + * is identified. If it's non-zero, then some other modules also depend + * on it and have already mapped it. + */ + if (dep->n_dependent++) + continue; + + /* First user of this dependency, load it into SRAM */ + ret = llext_manager_load_module(dep); + if (ret < 0) { + dep->n_dependent--; + llext_manager_depend_unlink_rollback(dep_ctx, i - 1); + return 0; + } + + dep_ctx[i] = dep; + } + + /* Map executable code and data */ + ret = llext_manager_load_module(mctx); + if (ret < 0) + return 0; + } + + return mod_manifest->module.entry_point; +} + +#ifdef CONFIG_USERSPACE +static int llext_manager_add_partition(struct k_mem_domain *domain, + uintptr_t addr, size_t size, + k_mem_partition_attr_t attr) +{ + size_t pre_pad_size = addr & (PAGE_SZ - 1); + struct k_mem_partition part = { + .start = addr - pre_pad_size, + .size = ALIGN_UP(pre_pad_size + size, PAGE_SZ), + .attr = attr, + }; + + tr_dbg(&lib_manager_tr, "add %#zx @ %lx partition", part.size, part.start); + return k_mem_domain_add_partition(domain, &part); +} + +static int llext_manager_rm_partition(struct k_mem_domain *domain, + uintptr_t addr, size_t size, + k_mem_partition_attr_t attr) +{ + size_t pre_pad_size = addr & (PAGE_SZ - 1); + struct k_mem_partition part = { + .start = addr - pre_pad_size, + .size = ALIGN_UP(pre_pad_size + size, PAGE_SZ), + .attr = attr, + }; + + tr_dbg(&lib_manager_tr, "remove %#zx @ %lx partition", part.size, part.start); + return k_mem_domain_remove_partition(domain, &part); +} + +int llext_manager_add_domain(const uint32_t component_id, struct k_mem_domain *domain) +{ + const uint32_t module_id = IPC4_MOD_ID(component_id); + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); + const unsigned int mod_idx = llext_manager_mod_find(ctx, entry_index); + struct lib_manager_module *mctx = ctx->mod + mod_idx; + const struct llext *ext = mctx->llext; + const struct llext_loader *ldr = &mctx->ebl->loader; + + /* Executable code (.text) */ + uintptr_t va_base_text = mctx->segment[LIB_MANAGER_TEXT].addr; + size_t text_size = mctx->segment[LIB_MANAGER_TEXT].size; + + /* Read-only data (.rodata and others) */ + uintptr_t va_base_rodata = mctx->segment[LIB_MANAGER_RODATA].addr; + size_t rodata_size = mctx->segment[LIB_MANAGER_RODATA].size; + + /* Writable data (.data, .bss and others) */ + uintptr_t va_base_data = mctx->segment[LIB_MANAGER_DATA].addr; + size_t data_size = mctx->segment[LIB_MANAGER_DATA].size; + + int ret = llext_manager_add_partition(domain, va_base_text, text_size, + K_MEM_PARTITION_P_RX_U_RX | XTENSA_MMU_CACHED_WB); + + if (ret < 0) + return ret; + + if (rodata_size) { + ret = llext_manager_add_partition(domain, va_base_rodata, rodata_size, + K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB); + if (ret < 0) + goto e_text; + } + + if (data_size) { + ret = llext_manager_add_partition(domain, va_base_data, data_size, + K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB); + if (ret < 0) + goto e_rodata; + } + + elf_shdr_t shdr_cold, shdr_coldrodata; + bool rodata = false, text = false; + const void *rodata_addr = NULL, *text_addr = NULL; + size_t text_offset = 0, rodata_offset = 0; + + shdr_cold.sh_size = 0; + shdr_coldrodata.sh_size = 0; + + ret = llext_get_section_header(ldr, ext, ".cold", &shdr_cold); + if (ret < 0) + tr_warn(&lib_manager_tr, "couldn't get .cold header"); + else + llext_get_region_info(ldr, ext, LLEXT_MEM_TEXT, NULL, &text_addr, NULL); + + ret = llext_get_section_header(ldr, ext, ".coldrodata", &shdr_coldrodata); + if (ret < 0) + tr_warn(&lib_manager_tr, "couldn't get .coldrodata header"); + else + llext_get_region_info(ldr, ext, LLEXT_MEM_RODATA, NULL, &rodata_addr, NULL); + + for (unsigned int i = 0; i < llext_section_count(ext) && (!rodata || !text); i++) { + const elf_shdr_t *shdr; + enum llext_mem s_region = LLEXT_MEM_COUNT; + size_t s_offset = 0; + + ret = llext_get_section_info(ldr, ext, i, &shdr, &s_region, &s_offset); + if (ret < 0) + continue; + + switch (s_region) { + case LLEXT_MEM_TEXT: + if (shdr_cold.sh_size && + shdr->sh_name == shdr_cold.sh_name && + shdr->sh_offset == shdr_cold.sh_offset && !text) { + text = true; + text_offset = s_offset; + } + break; + case LLEXT_MEM_RODATA: + if (shdr_coldrodata.sh_size && + shdr->sh_name == shdr_coldrodata.sh_name && + shdr->sh_offset == shdr_coldrodata.sh_offset && !rodata) { + rodata = true; + rodata_offset = s_offset; + } + break; + default: + break; + } + } + + if (text) { + tr_dbg(&lib_manager_tr, ".cold %#x @ %#lx", + shdr_cold.sh_size, (uintptr_t)text_addr + text_offset); + ret = llext_manager_add_partition(domain, (uintptr_t)text_addr + text_offset, + shdr_cold.sh_size, + K_MEM_PARTITION_P_RX_U_RX | XTENSA_MMU_CACHED_WB); + if (ret < 0) + goto e_data; + mctx->segment[LIB_MANAGER_COLD].addr = (uintptr_t)text_addr + text_offset; + mctx->segment[LIB_MANAGER_COLD].size = shdr_cold.sh_size; + } + + if (rodata) { + tr_dbg(&lib_manager_tr, ".coldrodata %#x @ %#lx", + shdr_coldrodata.sh_size, (uintptr_t)rodata_addr + rodata_offset); + ret = llext_manager_add_partition(domain, (uintptr_t)rodata_addr + rodata_offset, + shdr_coldrodata.sh_size, + K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB); + if (ret < 0) + goto e_cold; + mctx->segment[LIB_MANAGER_COLDRODATA].addr = (uintptr_t)rodata_addr + rodata_offset; + mctx->segment[LIB_MANAGER_COLDRODATA].size = shdr_coldrodata.sh_size; + } + + return 0; + +e_cold: + llext_manager_rm_partition(domain, (uintptr_t)text_addr + text_offset, shdr_cold.sh_size, + K_MEM_PARTITION_P_RX_U_RX | XTENSA_MMU_CACHED_WB); + mctx->segment[LIB_MANAGER_COLD].addr = 0; + mctx->segment[LIB_MANAGER_COLD].size = 0; +e_data: + llext_manager_rm_partition(domain, va_base_data, data_size, + K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB); +e_rodata: + llext_manager_rm_partition(domain, va_base_rodata, rodata_size, + K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB); +e_text: + llext_manager_rm_partition(domain, va_base_text, text_size, + K_MEM_PARTITION_P_RX_U_RX | XTENSA_MMU_CACHED_WB); + return ret; +} + +int llext_manager_rm_domain(const uint32_t component_id, struct k_mem_domain *domain) +{ + const uint32_t module_id = IPC4_MOD_ID(component_id); + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); + const unsigned int mod_idx = llext_manager_mod_find(ctx, entry_index); + struct lib_manager_module *mctx = ctx->mod + mod_idx; + + /* Executable code (.text) */ + uintptr_t va_base_text = mctx->segment[LIB_MANAGER_TEXT].addr; + size_t text_size = mctx->segment[LIB_MANAGER_TEXT].size; + + /* Read-only data (.rodata and others) */ + uintptr_t va_base_rodata = mctx->segment[LIB_MANAGER_RODATA].addr; + size_t rodata_size = mctx->segment[LIB_MANAGER_RODATA].size; + + /* Writable data (.data, .bss and others) */ + uintptr_t va_base_data = mctx->segment[LIB_MANAGER_DATA].addr; + size_t data_size = mctx->segment[LIB_MANAGER_DATA].size; + + int err, ret = llext_manager_rm_partition(domain, va_base_text, text_size, + K_MEM_PARTITION_P_RX_U_RX | XTENSA_MMU_CACHED_WB); + + if (ret < 0) + tr_err(&lib_manager_tr, "failed to remove .text memory partition: %d", ret); + + if (rodata_size) { + err = llext_manager_rm_partition(domain, va_base_rodata, rodata_size, + K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB); + if (err < 0) { + tr_err(&lib_manager_tr, "failed to remove .rodata memory partition: %d", + err); + if (!ret) + ret = err; + } + } + + if (data_size) { + err = llext_manager_rm_partition(domain, va_base_data, data_size, + K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB); + if (err < 0) { + tr_err(&lib_manager_tr, "failed to remove .data memory partition: %d", err); + if (!ret) + ret = err; + } + } + + if (mctx->segment[LIB_MANAGER_COLD].addr) { + err = llext_manager_rm_partition(domain, + mctx->segment[LIB_MANAGER_COLD].addr, + mctx->segment[LIB_MANAGER_COLD].size, + K_MEM_PARTITION_P_RX_U_RX | XTENSA_MMU_CACHED_WB); + if (err < 0) { + tr_err(&lib_manager_tr, "failed to remove .cold memory partition: %d", err); + if (!ret) + ret = err; + } + } + + if (mctx->segment[LIB_MANAGER_COLDRODATA].addr) { + err = llext_manager_rm_partition(domain, + mctx->segment[LIB_MANAGER_COLDRODATA].addr, + mctx->segment[LIB_MANAGER_COLDRODATA].size, + K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB); + if (err < 0) { + tr_err(&lib_manager_tr, + "failed to remove .coldrodata memory partition: %d", err); + if (!ret) + ret = err; + } + } + + return ret; +} +#endif + +int llext_manager_free_module(const uint32_t component_id) +{ + const uint32_t module_id = IPC4_MOD_ID(component_id); + struct sof_man_fw_desc *desc = (struct sof_man_fw_desc *)lib_manager_get_library_manifest(module_id); + struct lib_manager_mod_ctx *ctx = lib_manager_get_mod_ctx(module_id); + uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(module_id); + + if (entry_index >= desc->header.num_module_entries) { + tr_err(&lib_manager_tr, "Invalid driver index %u exceeds %d", + entry_index, desc->header.num_module_entries - 1); + return -ENOENT; + } + + if (!ctx->mod) { + tr_err(&lib_manager_tr, "NULL module array: ID %#x ctx %p", component_id, ctx); + return -ENOENT; + } + + unsigned int mod_idx = llext_manager_mod_find(ctx, entry_index); + struct lib_manager_module *mctx = ctx->mod + mod_idx; + + /* Protected by IPC serialization */ + if (mctx->llext->use_count > 1) { + /* + * At least 2 users: llext_unload() will never actually free + * the extension but only reduce the refcount and return its + * new value (must be a positive number). + * NOTE: if this is modified to allow extension unload, the + * inspection data in the loader must be freed as well by + * calling the llext_free_inspection_data() function. + */ + int ret = llext_unload(&mctx->llext); + + if (ret <= 0) { + tr_err(&lib_manager_tr, + "mod_id: %#x: invalid return code from llext_unload(): %d", + component_id, ret); + return ret ? : -EPROTO; + } + + /* More users are active */ + return 0; + } + + struct lib_manager_module *dep_ctx[LLEXT_MAX_DEPENDENCIES] = {}; + int i; /* signed to match llext_manager_depend_unlink_rollback() */ + + for (i = 0; i < ARRAY_SIZE(mctx->llext->dependency); i++) + if (llext_lib_find(mctx->llext->dependency[i], &dep_ctx[i]) < 0) + break; + + /* Last user cleaning up, put dependencies */ + if (i) + llext_manager_depend_unlink_rollback(dep_ctx, i - 1); + + /* + * The last instance of the module has been destroyed and it can now be + * unloaded from SRAM + */ + tr_dbg(&lib_manager_tr, "mod_id: %#x", component_id); + + /* Since the LLEXT context now is preserved, we have to flush logs ourselves */ + log_flush(); + + return llext_manager_unload_module(mctx); +} + +/* An auxiliary library has been loaded, need to read in its exported symbols */ +int llext_manager_add_library(uint32_t module_id) +{ + struct lib_manager_mod_ctx *const ctx = lib_manager_get_mod_ctx(module_id); + + if (ctx->mod) { + tr_err(&lib_manager_tr, "module_id: %#x: repeated load!", module_id); + return -EBUSY; + } + + const struct sof_man_fw_desc *desc = lib_manager_get_library_manifest(module_id); + unsigned int i; + + if (!ctx->mod) + llext_manager_mod_init(ctx, desc); + + for (i = 0; i < ctx->n_mod; i++) { + const struct sof_man_module *mod = lib_manager_get_module_manifest(module_id + i); + + if (mod->type.load_type == SOF_MAN_MOD_TYPE_LLEXT_AUX) { + const struct sof_man_module_manifest *mod_manifest; + const struct sof_module_api_build_info *buildinfo; + int ret = llext_manager_link_single(module_id + i, desc, ctx, + (const void **)&buildinfo, &mod_manifest); + + if (ret < 0) + return ret; + } + } + + return 0; +} + +bool comp_is_llext(struct comp_dev *comp) +{ + const uint32_t module_id = IPC4_MOD_ID(comp->ipc_config.id); + const unsigned int base_module_id = LIB_MANAGER_GET_LIB_ID(module_id) << + LIB_MANAGER_LIB_ID_SHIFT; + const struct sof_man_module *mod = lib_manager_get_module_manifest(base_module_id); + + return mod && module_is_llext(mod); +} + +static int llext_memory_region_init(void) +{ + int ret; + + /* add a region for loadable libraries */ + ret = adsp_add_virtual_memory_region(CONFIG_LIBRARY_BASE_ADDRESS, + CONFIG_LIBRARY_REGION_SIZE, + VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR); + + return ret; +} + +SYS_INIT(llext_memory_region_init, POST_KERNEL, 1); diff --git a/src/library_manager/llext_manager_dram.c b/src/library_manager/llext_manager_dram.c new file mode 100644 index 000000000000..25c00f47b4e1 --- /dev/null +++ b/src/library_manager/llext_manager_dram.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <rtos/alloc.h> + +#include <sof/lib_manager.h> +#include <ipc/topology.h> + +#include <zephyr/llext/buf_loader.h> +#include <zephyr/llext/llext.h> +#include <zephyr/llext/llext_internal.h> +#include <zephyr/logging/log_ctrl.h> + +LOG_MODULE_DECLARE(lib_manager, CONFIG_SOF_LOG_LEVEL); + +struct lib_manager_dram_storage { + struct ext_library ext_lib; + struct lib_manager_mod_ctx *ctx; + struct lib_manager_module *mod; + struct llext *llext; + struct llext_buf_loader *bldr; + struct llext_elf_sect_map *sect; + struct llext_symbol *sym; + unsigned int n_llext; + unsigned int n_mod; +}; + +/* + * This holds the complete LLEXT manager context in DRAM over DSP shut down to + * be restored during the next boot + */ +__imrdata static struct lib_manager_dram_storage lib_manager_dram; + +/* Store LLEXT manager context in DRAM to be restored during the next boot. */ +int llext_manager_store_to_dram(void) +{ + struct ext_library *_ext_lib = ext_lib_get(); + unsigned int i, j, k, l, n_lib, n_mod, n_llext, n_sect, n_sym; + size_t buf_size; + + if (lib_manager_dram.n_llext) { + tr_err(&lib_manager_tr, "context already saved"); + return 0; + } + + /* + * Count libraries, modules, instantiated extensions, sections and exported + * symbols in them. Allocate a buffer of required size. + */ + lib_manager_dram.ext_lib = *_ext_lib; + for (i = 0, n_lib = 0, n_mod = 0, n_llext = 0, n_sect = 0, n_sym = 0; + i < ARRAY_SIZE(_ext_lib->desc); i++) + if (_ext_lib->desc[i]) { + n_lib++; + n_mod += _ext_lib->desc[i]->n_mod; + for (k = 0; k < _ext_lib->desc[i]->n_mod; k++) + if (_ext_lib->desc[i]->mod[k].ebl) { + n_llext++; + n_sect += _ext_lib->desc[i]->mod[k].llext->sect_cnt; + n_sym += _ext_lib->desc[i]->mod[k].llext->exp_tab.sym_cnt; + tr_dbg(&lib_manager_tr, "add %u exported syms", + _ext_lib->desc[i]->mod[k].llext->exp_tab.sym_cnt); + } + } + + buf_size = sizeof(lib_manager_dram.ctx[0]) * n_lib + + sizeof(lib_manager_dram.mod[0]) * n_mod + + sizeof(lib_manager_dram.sect[0]) * n_sect + + sizeof(lib_manager_dram.sym[0]) * n_sym + + (sizeof(lib_manager_dram.llext[0]) + sizeof(lib_manager_dram.bldr[0])) * n_llext; + + lib_manager_dram.ctx = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_L3, + buf_size); + if (!lib_manager_dram.ctx) + return -ENOMEM; + + /* Save pointers to buffer parts, holding parts of the context */ + lib_manager_dram.mod = (struct lib_manager_module *)(lib_manager_dram.ctx + n_lib); + lib_manager_dram.sect = (struct llext_elf_sect_map *)(lib_manager_dram.mod + n_mod); + lib_manager_dram.llext = (struct llext *)(lib_manager_dram.sect + n_sect); + lib_manager_dram.bldr = (struct llext_buf_loader *)(lib_manager_dram.llext + n_llext); + lib_manager_dram.sym = (struct llext_symbol *)(lib_manager_dram.bldr + n_llext); + + tr_dbg(&lib_manager_tr, "backup %u libs of %u modules with %u LLEXT with %u sections", + n_lib, n_mod, n_llext, n_sect); + + tr_dbg(&lib_manager_tr, "backup %p to %p, mod %p, loader %p", + lib_manager_dram.ctx, (void *)((uint8_t *)lib_manager_dram.ctx + buf_size), + lib_manager_dram.mod, lib_manager_dram.bldr); + + /* Walk all libraries */ + for (i = 0, j = 0, l = 0, n_mod = 0, n_sect = 0, n_sym = 0; + i < ARRAY_SIZE(_ext_lib->desc); i++) { + if (!_ext_lib->desc[i]) + continue; + + struct lib_manager_module *mod = _ext_lib->desc[i]->mod; + + /* Copy all modules in each library */ + lib_manager_dram.ctx[j++] = *_ext_lib->desc[i]; + memcpy(lib_manager_dram.mod + n_mod, mod, + sizeof(lib_manager_dram.mod[0]) * _ext_lib->desc[i]->n_mod); + tr_dbg(&lib_manager_tr, "lib %u base %p", j - 1, + lib_manager_dram.ctx[j - 1].base_addr); + n_mod += _ext_lib->desc[i]->n_mod; + + /* + * Copy instantiated extensions. Note that only modules, that + * were used, have their LLEXT context instantiated. + */ + for (k = 0; k < _ext_lib->desc[i]->n_mod; k++) { + if (!mod[k].llext) + continue; + + tr_dbg(&lib_manager_tr, "mod %u of %u sections", k, + mod[k].llext->sect_cnt); + + /* Copy the extension and the loader */ + lib_manager_dram.llext[l] = *mod[k].llext; + lib_manager_dram.bldr[l] = *mod[k].ebl; + + /* Copy the section map */ + memcpy(lib_manager_dram.sect + n_sect, mod[k].ebl->loader.sect_map, + mod[k].llext->sect_cnt * sizeof(lib_manager_dram.sect[0])); + n_sect += mod[k].llext->sect_cnt; + + /* Copy exported symbols */ + if (mod[k].llext->exp_tab.sym_cnt) { + memcpy(lib_manager_dram.sym + n_sym, mod[k].llext->exp_tab.syms, + mod[k].llext->exp_tab.sym_cnt * + sizeof(lib_manager_dram.sym[0])); + lib_manager_dram.llext[l].exp_tab.syms = lib_manager_dram.sym + + n_sym; + n_sym += mod[k].llext->exp_tab.sym_cnt; + } + + l++; + } + } + + /* Also flatten dependency lists */ + int ret = llext_relink_dependency(lib_manager_dram.llext, n_llext); + + if (ret < 0) { + tr_err(&lib_manager_tr, "Inconsistent dependencies!"); + return ret; + } + + lib_manager_dram.n_llext = n_llext; + lib_manager_dram.n_mod = n_mod; + + /* Make sure, that the data is actually in the DRAM, not just in data cache */ + dcache_writeback_region((__sparse_force void __sparse_cache *)&lib_manager_dram, + sizeof(lib_manager_dram)); + dcache_writeback_region((__sparse_force void __sparse_cache *)lib_manager_dram.ctx, + buf_size); + + return 0; +} + +int llext_manager_restore_from_dram(void) +{ + lib_manager_init(); + + struct ext_library *_ext_lib = ext_lib_get(); + unsigned int i, j, k, n_mod, n_llext, n_sect, n_sym; + struct llext_loader **ldr; + struct llext **llext; + + if (!lib_manager_dram.n_mod || !lib_manager_dram.ctx) { + tr_dbg(&lib_manager_tr, "No modules saved"); + dcache_writeback_region((__sparse_force void __sparse_cache *)&lib_manager_dram, + sizeof(lib_manager_dram)); + return 0; + } + + *_ext_lib = lib_manager_dram.ext_lib; + + if (lib_manager_dram.n_llext) { + /* arrays of pointers for llext_restore() */ + void **ptr_array = rmalloc(SOF_MEM_FLAG_KERNEL, + sizeof(*ptr_array) * lib_manager_dram.n_llext * 2); + + if (!ptr_array) + return -ENOMEM; + + ldr = (struct llext_loader **)ptr_array; + llext = (struct llext **)(ptr_array + lib_manager_dram.n_llext); + } else { + ldr = NULL; + llext = NULL; + } + + /* The external loop walks all the libraries */ + for (i = 0, j = 0, n_mod = 0, n_llext = 0, n_sect = 0, n_sym = 0; + i < ARRAY_SIZE(_ext_lib->desc); i++) { + if (!lib_manager_dram.ext_lib.desc[i]) { + _ext_lib->desc[i] = NULL; + continue; + } + + /* Panics on failure - use the same zone as during the first boot */ + struct lib_manager_mod_ctx *ctx = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(*ctx)); + + /* Restore the library context */ + *ctx = lib_manager_dram.ctx[j++]; + + /* Allocate and restore all the modules in the library */ + struct lib_manager_module *mod = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + ctx->n_mod * sizeof(ctx->mod[0])); + + if (!mod) { + tr_err(&lib_manager_tr, "module allocation failure"); + goto nomem; + } + tr_dbg(&lib_manager_tr, "%u modules alloc %p base %p copy %#zx", + ctx->n_mod, (void *)mod, ctx->base_addr, ctx->n_mod * sizeof(ctx->mod[0])); + + memcpy(mod, lib_manager_dram.mod + n_mod, sizeof(mod[0]) * ctx->n_mod); + n_mod += ctx->n_mod; + ctx->mod = mod; + + /* Second level: enumerate modules in each library */ + for (k = 0; k < ctx->n_mod; k++) { + if (!mod[k].llext) + /* Not instantiated - nothing to restore */ + continue; + + /* Loaders are supplied by the caller */ + struct llext_buf_loader *bldr = rmalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(*bldr)); + + if (!bldr) { + tr_err(&lib_manager_tr, "loader allocation failure"); + goto nomem; + } + + /* Extensions have to be restored by Zephyr, collect pointers first */ + llext[n_llext] = lib_manager_dram.llext + n_llext; + + *bldr = lib_manager_dram.bldr[n_llext]; + + bldr->loader.sect_map = lib_manager_dram.sect + n_sect; + + n_sect += llext[n_llext]->sect_cnt; + if (llext[n_llext]->exp_tab.sym_cnt) { + /* + * Just a check, that we're restoring exported + * symbols correctly + */ + tr_dbg(&lib_manager_tr, "got %u exported symbols", + llext[n_llext]->exp_tab.sym_cnt); + + if (llext[n_llext]->exp_tab.syms != lib_manager_dram.sym + n_sym) { + tr_err(&lib_manager_tr, + "bug detected! pointer mismatch %p vs. %p", + (void *)llext[n_llext]->exp_tab.syms, + (void *)(lib_manager_dram.sym + n_sym)); + goto nomem; + } + + n_sym += llext[n_llext]->exp_tab.sym_cnt; + } + + mod[k].ebl = bldr; + + ldr[n_llext++] = &bldr->loader; + } + + _ext_lib->desc[i] = ctx; + } + + if (lib_manager_dram.n_llext) { + /* Let Zephyr restore extensions and its own internal bookkeeping */ + int ret = llext_restore(llext, ldr, lib_manager_dram.n_llext); + + if (ret < 0) { + tr_err(&lib_manager_tr, "Zephyr failed to restore: %d", ret); + goto nomem; + } + + /* Rewrite to correct LLEXT pointers, created by Zephyr */ + for (i = 0, n_llext = 0; i < ARRAY_SIZE(_ext_lib->desc); i++) { + struct lib_manager_mod_ctx *ctx = _ext_lib->desc[i]; + + if (!ctx) + continue; + + struct lib_manager_module *mod = ctx->mod; + + for (k = 0; k < ctx->n_mod; k++) { + if (mod[k].llext) + mod[k].llext = llext[n_llext++]; + } + } + } + + tr_info(&lib_manager_tr, "restored %u modules with %u LLEXT", n_mod, n_llext); + + rfree(lib_manager_dram.ctx); + lib_manager_dram.ctx = NULL; + lib_manager_dram.sect = NULL; + lib_manager_dram.llext = NULL; + lib_manager_dram.bldr = NULL; + lib_manager_dram.sym = NULL; + rfree(ldr); + + lib_manager_dram.n_llext = 0; + + return 0; + +nomem: + tr_err(&lib_manager_tr, "Restore failed"); + for (i = 0; i < ARRAY_SIZE(_ext_lib->desc); i++) { + struct lib_manager_mod_ctx *ctx = _ext_lib->desc[i]; + + if (!ctx) + continue; + + struct lib_manager_module *mod = ctx->mod; + + if (!mod) + continue; + + for (k = 0; k < ctx->n_mod; k++) { + if (mod[k].llext) + llext_unload(&mod[k].llext); + + if (mod[k].ebl) + rfree(mod[k].ebl); + } + + rfree(mod); + rfree(ctx); + } + + /* at least create a sane empty lib-manager context */ + memset(_ext_lib->desc, 0, sizeof(_ext_lib->desc)); + + rfree(ldr); + + return -ENOMEM; +} diff --git a/src/logging/CMakeLists.txt b/src/logging/CMakeLists.txt new file mode 100644 index 000000000000..6114062e37c6 --- /dev/null +++ b/src/logging/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources_ifdef(CONFIG_LOG_BACKEND_SOF_PROBE sof log_backend_probe.c) diff --git a/src/logging/log_backend_probe.c b/src/logging/log_backend_probe.c new file mode 100644 index 000000000000..0b852d780455 --- /dev/null +++ b/src/logging/log_backend_probe.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +#include <zephyr/logging/log_backend.h> +#include <zephyr/logging/log_core.h> +#include <zephyr/logging/log_output.h> +#include <zephyr/logging/log_backend_std.h> +#include <zephyr/kernel.h> + +#include <sof/audio/buffer.h> +#include <sof/ipc/topology.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/probe/probe.h> + +#ifdef PROBE_LOG_DEBUG +#include <stdio.h> +#endif + +/* + * A lock is needed as log_process() and log_panic() have no internal locks + * to prevent concurrency. Meaning if log_process is called after + * log_panic was called previously, log_process may happen from another + * CPU and calling context than the log processing thread running in + * the background. On an SMP system this is a race. + * + * This caused a race on the output trace such that the logging output + * was garbled and useless. + */ +static struct k_spinlock probe_lock; + +static uint32_t probe_log_format_current = CONFIG_LOG_BACKEND_SOF_PROBE_OUTPUT; + +#define LOG_BUF_SIZE 80 +static uint8_t log_buf[LOG_BUF_SIZE]; + +static probe_logging_hook_t probe_hook; + +static void log_push(uint8_t *data, size_t length) +{ + size_t pos = 0; + + do { + int ret = probe_hook(data + pos, length - pos); + + if (ret < 0) + break; + pos += ret; + } while (pos < length); +} + +#define PRE_BUFFER_SIZE 4096 +static struct probe_pre_buffer { + uint8_t *buf; + size_t wpos; + size_t len; +} prebuf; + +static void pre_buffer_drain(void) +{ +#ifdef PROBE_LOG_DEBUG + /* NOTE: The debug code only works with ascii/text log output */ + uint64_t stamp = sof_cycle_get_64(); + char msg[80]; + int mlen; + + mlen = snprintf(msg, sizeof(msg), "[Drain %zu bytes of pre buffered logs]\n", prebuf.wpos); + if (prebuf.len > prebuf.wpos && mlen < sizeof(msg)) + mlen += snprintf(msg + mlen, sizeof(msg) - mlen, "[%zu bytes dropped]\n", + prebuf.len - prebuf.wpos); + log_push(msg, MIN(mlen, sizeof(msg))); +#endif + + log_push(prebuf.buf, prebuf.wpos); + rfree(prebuf.buf); + prebuf.buf = NULL; + prebuf.len = 0; + prebuf.wpos = 0; + +#ifdef PROBE_LOG_DEBUG + mlen = snprintf(msg, sizeof(msg), "[Buffer drained in %llu us]\n", + k_cyc_to_us_near64(sof_cycle_get_64() - stamp)); + + log_push(msg, MIN(mlen, sizeof(msg))); +#endif +} + +static void pre_buffer(uint8_t *data, size_t length) +{ + int ret; + + prebuf.len += length; + if (!prebuf.buf) { + prebuf.buf = rzalloc(SOF_MEM_FLAG_USER, PRE_BUFFER_SIZE); + if (!prebuf.buf) + return; + } + /* Protection against buffer over flow relies on memcpy_s() */ + ret = memcpy_s(&prebuf.buf[prebuf.wpos], PRE_BUFFER_SIZE - prebuf.wpos, data, length); + if (!ret) + prebuf.wpos += length; +} + +static int probe_char_out(uint8_t *data, size_t length, void *ctx) +{ + if (!probe_hook) { + pre_buffer(data, length); + } else { + if (prebuf.wpos) + pre_buffer_drain(); + + log_push(data, length); + } + + return length; +} + +LOG_OUTPUT_DEFINE(log_output_adsp_probe, probe_char_out, log_buf, sizeof(log_buf)); + +static uint32_t format_flags(void) +{ + uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_TIMESTAMP; + + if (IS_ENABLED(CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP)) + flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP; + + return flags; +} + +static void probe_log_panic(struct log_backend const *const backend) +{ + k_spinlock_key_t key = k_spin_lock(&probe_lock); + + log_backend_std_panic(&log_output_adsp_probe); + + k_spin_unlock(&probe_lock, key); +} + +static void probe_log_dropped(const struct log_backend *const backend, + uint32_t cnt) +{ + log_output_dropped_process(&log_output_adsp_probe, cnt); +} + +static void probe_log_process(const struct log_backend *const backend, + union log_msg_generic *msg) +{ + log_format_func_t log_output_func = log_format_func_t_get(probe_log_format_current); + + k_spinlock_key_t key = k_spin_lock(&probe_lock); + + log_output_func(&log_output_adsp_probe, &msg->log, format_flags()); + + k_spin_unlock(&probe_lock, key); +} + +static int probe_log_format_set(const struct log_backend *const backend, uint32_t log_type) +{ + probe_log_format_current = log_type; + return 0; +} + +/** + * Lazily initialized, while the DMA may not be setup we continue + * to buffer log messages untilt he buffer is full. + */ +static void probe_log_init(const struct log_backend *const backend) +{ + ARG_UNUSED(backend); +} + +const struct log_backend_api log_backend_adsp_probe_api = { + .process = probe_log_process, + .dropped = IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE) ? NULL : probe_log_dropped, + .panic = probe_log_panic, + .format_set = probe_log_format_set, + .init = probe_log_init, +}; + +LOG_BACKEND_DEFINE(log_backend_adsp_probe, log_backend_adsp_probe_api, true); + +void probe_logging_init(probe_logging_hook_t fn) +{ + probe_hook = fn; +} +EXPORT_SYMBOL(probe_logging_init); + +const struct log_backend *log_backend_probe_get(void) +{ + return &log_backend_adsp_probe; +} + +bool probe_is_backend_configured(void) +{ + return probe_hook != NULL; +} diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt index 0c0ad5189f52..a52263006295 100644 --- a/src/math/CMakeLists.txt +++ b/src/math/CMakeLists.txt @@ -1,3 +1,113 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof numbers.c trig.c decibels.c) +if(BUILD_LIBRARY) + add_local_sources(sof numbers.c) + return() +endif() + +set(base_files numbers.c gcc-builtins.c) + +if(CONFIG_CORDIC_FIXED) + list(APPEND base_files trig.c) +endif() + +if(CONFIG_MATH_ATAN2) + list(APPEND base_files atan2.c) +endif() + +if(CONFIG_MATH_LUT_SINE_FIXED) + list(APPEND base_files lut_trig.c) +endif() + +if(CONFIG_SQRT_FIXED) + list(APPEND base_files sqrt_int16.c sqrt_int32.c) +endif() + +if(CONFIG_MATH_EXP) + list(APPEND base_files exp_fcn.c exp_fcn_hifi.c) +endif() + +if(CONFIG_MATH_DECIBELS) + list(APPEND base_files decibels.c) +endif() + +if(CONFIG_NATURAL_LOGARITHM_FIXED) + list(APPEND base_files log_e.c) +endif() + +if(CONFIG_COMMON_LOGARITHM_FIXED) + list(APPEND base_files log_10.c) +endif() + +if(CONFIG_POWER_FIXED) + list(APPEND base_files power.c) +endif() + +if(CONFIG_BINARY_LOGARITHM_FIXED) + list(APPEND base_files base2log.c) +endif() + +if(CONFIG_MATH_FIR STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(fir_llext ${PROJECT_BINARY_DIR}/aux1_fir_llext) + add_dependencies(app aux1_fir) +elseif(CONFIG_MATH_FIR) + list(APPEND base_files fir_generic.c fir_hifi2ep.c fir_hifi3.c fir_hifi5.c) +endif() + +if(CONFIG_MATH_FFT) + add_subdirectory(fft) +endif() + +if(CONFIG_MATH_IIR STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(iir_llext ${PROJECT_BINARY_DIR}/aux1_iir_llext) + add_dependencies(app aux1_iir) +elseif(CONFIG_MATH_IIR) + if(CONFIG_MATH_IIR_DF2T) + list(APPEND base_files iir_df2t_generic.c iir_df2t_hifi3.c iir_df2t.c) + endif() + + if(CONFIG_MATH_IIR_DF1) + list(APPEND base_files iir_df1_generic.c iir_df1_hifi3.c iir_df1_hifi4.c iir_df1_hifi5.c iir_df1.c) + endif() +endif() + +if(CONFIG_MATH_WINDOW) + list(APPEND base_files window.c) +endif() + +if(CONFIG_MATH_MATRIX) + list(APPEND base_files matrix.c) +endif() + +if(CONFIG_MATH_AUDITORY) + add_subdirectory(auditory) +endif() + +if(CONFIG_MATH_DCT) + list(APPEND base_files dct.c) +endif() + +if(CONFIG_MATH_A_LAW_CODEC) + list(APPEND base_files a_law.c) +endif() + +if(CONFIG_MATH_MU_LAW_CODEC) + list(APPEND base_files mu_law.c) +endif() + +if(CONFIG_MATH_COMPLEX) + list(APPEND base_files complex.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + zephyr_library_sources( + ${base_files} + ) + +else() ### library, e.g. testbench or plugin ### + + add_local_sources(sof ${base_files}) + +endif() diff --git a/src/math/Kconfig b/src/math/Kconfig new file mode 100644 index 000000000000..1feaab8f03d1 --- /dev/null +++ b/src/math/Kconfig @@ -0,0 +1,322 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "Math functions" + +config CORDIC_FIXED + bool "Trigonometric functions" + default n + help + Select this to enable sin(), cos(), asin(), acos(), + and cexp() functions as 16 bit and 32 bit versions. + +config MATH_ATAN2 + bool "Four-quadrant arctangent function" + default n + help + Select this to enable sofm_atan2_32b(y, x) function. It computes + the four-quadrant arctangent using a polynomial approximation. + Input arguments y and x are Q1.31 format and the output angle + is Q3.29 format with range [-pi, pi]. The maximum approximation + error is ~0.001 degrees. + +config MATH_LUT_SINE_FIXED + bool "Lookup table based sine function" + default n + help + Select this to enable sofm_lut_sin_fixed_16b() function. The + calculation is using 1/4 wave lookup and interpolation. Use + this for fast sine calculation in hot code parts. Sine + calculation in component initialization should use the cordic + version. This option consumes 1026 bytes .bss RAM for the + lookup table. + +config POWER_FIXED + bool "Power function" + default n + help + This option builds the 32 bit power_int32(). A power represents repeated + multiplication of the same number. power_int32() calculates the power + raised to the base value. The power function works for even, odd and + fractional base and exponent argument.Operating range of power_int32() + with base having values from -32 to + 32 . Exponent values range from + -3 to +3. Power out MIN/MAX range is -/+32768. + +config BINARY_LOGARITHM_FIXED + bool "Binary Logarithm function" + default n + help + This option builds Binary Logarithm function (log2n) is the logarithm to + the base 2. The binary logarithm of x is the power to which the number 2 + must be raised to obtain the value x. Base 2 logarithm function is implemented + with a short lookup table. (log2n) operates for a range of 32 bit width size + i.e. 1 to 4294967295. + +config SQRT_FIXED + bool "Square Root functions" + default n + help + Select this to enable sqrt_int() functions as 16 bit version + to calculate square root.square function having positive number + y as input and return the positive number x multiplied by itself (squared) + +config MATH_EXP + bool "Exponential functions" + default n + help + By selecting this, the 32-bit sofm_exp_int32() function can be used to calculate + exponential values. With a maximum ulp of 5, an exponential function with + an input range of -5 to +5 gives positive numbers between 0.00673794699908547 and + 148.413159102577. The precision of this function is 1e-4. + +config NATURAL_LOGARITHM_FIXED + bool "Natural Logarithm function" + default n + select BINARY_LOGARITHM_FIXED + help + This option builds Natural Logarithm function (loge(N)) which is the logarithm to + the base e. + +config COMMON_LOGARITHM_FIXED + bool "Common Logarithm function" + default n + select BINARY_LOGARITHM_FIXED + help + This option builds common Logarithm function (log10(N)) which is the logarithm to + the base 10. + +config NUMBERS_NORM + bool "Norm function" + default n + help + Norm function counts the left shifts needed to + normalize integer value. + +config NUMBERS_VECTOR_FIND + bool "Find operations for numbers vecter" + default n + help + This option provides functions func_equal_int16(), + find_min_int16(), and find_max_abs32(). + +config MATH_DECIBELS + bool "Convert decibels to linear" + default n + help + Select this to enable db2lin_fixed() and exp_fixed() + functions. + +config MATH_COMPLEX + bool "Operations for complex numbers" + default n + select CORDIC_FIXED + select MATH_ATAN2 + select SQRT_FIXED + help + Select this to enable functions for complex numbers + arithmetic such as conversions to/from polar format. + +config MATH_FFT + bool "FFT library" + default n + select MATH_COMPLEX + help + Enable Fast Fourier Transform library, this should not be selected + directly, please select it from other audio components where need it. + +config MATH_FFT_MULTI + bool "FFT library for some non-power-of-two sizes" + depends on MATH_FFT + default n + help + Enable Fast Fourier Transform library for e.g. sizes 1536 and 3072, + this should not be selected directly, please select it from other + audio components where need it. + +menu "Supported FFT word lengths" + visible if MATH_FFT + +config MATH_16BIT_FFT + bool "S16_LE data support" + default y + help + This option enables support + for 16 bit PCM data. The twiddle + factors data consumes + 4096 bytes. + +config MATH_32BIT_FFT + bool "S32_LE data support" + default n + help + This option enables support + for 32 bit PCM data. The twiddle + factors data consumes + 8192 bytes. + +endmenu + +# this choice covers math iir, math fir, tdfb, and eqfir, eqiir. +choice "FILTER_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for IIR/FIR/TDFB module" + depends on COMP_FIR || COMP_IIR || COMP_TDFB + default FILTER_HIFI_MAX + + config FILTER_HIFI_MAX + prompt "SIMD will selected by toolchain pre-defined header" + bool + help + When this was selected, optimization level will be determined + by toolchain pre-defined macros in core isa header file. + + config FILTER_HIFI_5 + prompt "choose HIFI5 intrinsic optimized FILTER module" + bool + help + This option used to build HIFI5 optimized FILTER code + + config FILTER_HIFI_4 + prompt "choose HIFI4 intrinsic optimized FILTER module" + bool + help + This option used to build HIFI4 optimized FILTER code + + config FILTER_HIFI_3 + prompt "choose HIFI3 intrinsic optimized FILTER module" + bool + help + This option used to build HIFI3 intrinsic optimized FILTER code + + config FILTER_HIFI_2 + prompt "choose HIFI2ep intrinsic optimized FILTER module" + bool + help + This option used to build HIFI2ep intrinsic optimized FILTER code + + config FILTER_HIFI_NONE + prompt "choose generic C FILTER module, no HIFI SIMD involved" + bool + help + This option used to build FILTER generic code. +endchoice + +config MATH_FIR + tristate "FIR filter library" + default n + help + This option builds FIR (Finite Impulse Response) filter library. It + is selected by components for their digital signal processing. A FIR + filter calculates a convolution of input PCM sample and a configurable + impulse response. + +config MATH_IIR + tristate "Select IIR filter library build method" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + A helper option for MATH_IIR_DF2T and MATH_IIR_DF1 + +config MATH_IIR_DF2T + bool "IIR DF2T filter library" + depends on MATH_IIR != "n" + default n + help + Select this to build IIR (Infinite Impulse Response) filter + or type 2-transposed library. + +config MATH_IIR_DF1 + bool "IIR DF1 filter library" + depends on MATH_IIR != "n" + default n + help + Select this to build IIR (Infinite Impulse Response) filter + or type Direct-1 library. + +config MATH_WINDOW + bool "Window functions library" + default n + select CORDIC_FIXED + select NATURAL_LOGARITHM_FIXED + help + Select this to build a library for window functions. The window functions + are used to mitigate artefacts (from nature of FFT) to spectra when + computing FFT for a finite long chunk of audio. The sample values within + the window length need to be multiplied by the weight of coefficient value. + The currently provided window functions are Blackman, Hamming, Povey, and + rectangular. + +config MATH_MATRIX + bool "Matrix functions library" + default n + help + Select this to build a matrix arithmetic library. Currently it supports + matrix initialization, clear, set values, get values, and a multiply + function for 16 bit fractional format. Multiplication functions exist + for normal matrix multiply and elementwise multiplication. + +config MATH_AUDITORY + bool "Auditory functions library" + default n + select NATURAL_LOGARITHM_FIXED + help + Select this to build a psychoacoustics and auditory system related + functions library. Currently the library provides functions for Mel + frequency scale. Functions are provided to convert between Mel and + Hz, initialize a Mel filterbank and apply Mel filterbank to convert + a linear power spectrum into an auditory power spectrum. + +menu "Supported Mel filterbank word lengths" + visible if MATH_AUDITORY + +config MATH_16BIT_MEL_FILTERBANK + bool "icomplex16 data support" + default n + help + This option enables function psy_apply_mel_filterbank_16(). + It takes as input an array of icomplex16 + struct data from FFT. Output is 16 bit + logarithmic Mel spectrum. + +config MATH_32BIT_MEL_FILTERBANK + bool "icomplex32 data support" + default n + help + This option enables function psy_apply_mel_filterbank_32(). + It takes as input an array of icomplex32 + struct data from FFT. Output is 16 bit + logarithmic Mel spectrum. + +endmenu + +config MATH_DCT + bool "DCT transform library" + default n + select MATH_MATRIX + select CORDIC_FIXED + help + Select this to build library for discrete cosine transform + (DCT). The library currently supports initialization of a + matrix for ortho normalized DCT type II. The actual DCT + transform for data is done as matrix multiply with the + returned DCT matrix. + +config MATH_A_LAW_CODEC + bool "A-law encoder and decoder" + help + This option enables functions sofm_a_law_encode() and + sofm_a_law_decode(). The A-law codec is defined in + ITU-T G.711 standard and has been used in telecommunications + in e.g. Europe. The A-law coding compresses 13 bit samples + to 8 bit coded data. A-law codec can be used in VoIP and + 8-bit wav formats. + +config MATH_MU_LAW_CODEC + bool "mu-law encoder and decoder" + help + This option enables functions sofm_mu_law_encode() and + sofm_mu_law_decode(). The mu-law codec is defined in + ITU-T G.711 standard and has been used in telecommunications + in USA and Japan. The mu-law coding compresses 14 bit samples + to 8 bit coded data. Mu-law codec can be used in VoIP and + 8-bit wav formats. + +endmenu diff --git a/src/math/Kconfig.simd b/src/math/Kconfig.simd new file mode 100644 index 000000000000..6521259be116 --- /dev/null +++ b/src/math/Kconfig.simd @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: BSD-3-Clause + +comment "filter optimization level select" + +# this choice covers math iir, math fir, tdfb, and eqfir, eqiir. +choice "FILTER_SIMD_LEVEL_SELECT" + prompt "choose which SIMD level used for filter module" + depends on COMP_FIR + depends on COMP_IIR + default FILTER_HIFI_MAX + + config FILTER_HIFI_MAX + prompt "SIMD will selected by toolchain pre-defined header" + bool + help + When this was selected, optimization level will be determined + by toolchain pre-defined macros in core isa header file. + + config FILTER_HIFI_5 + prompt "choose HIFI5 intrinsic optimized FILTER module" + bool + help + This option used to build HIFI5 optimized FILTER code + + config FILTER_HIFI_4 + prompt "choose HIFI4 intrinsic optimized FILTER module" + bool + help + This option used to build HIFI4 optimized FILTER code + + config FILTER_HIFI_3 + prompt "choose HIFI3 intrinsic optimized FILTER module" + bool + help + This option used to build HIFI3 intrinsic optimized FILTER code + + config FILTER_HIFI_2 + prompt "choose HIFI2ep intrinsic optimized FILTER module" + bool + help + This option used to build HIFI2ep intrinsic optimized FILTER code + + config FILTER_HIFI_NONE + prompt "choose generic C FILTER module, no HIFI SIMD involved" + bool + help + This option used to build FILTER generic code. +endchoice diff --git a/src/math/a_law.c b/src/math/a_law.c new file mode 100644 index 000000000000..7a0b906ec255 --- /dev/null +++ b/src/math/a_law.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/a_law.h> +#include <stdint.h> + +#define SOFM_ALAW_SIGN_BIT 0x80 +#define SOFM_ALAW_MAX 4095 +#define SOFM_ALAW_TOGGLE_EVEN_BITS 0x55 +#define SOFM_ALAW_MANTISSA_MASK 0x0f +#define SOFM_ALAW_MANTISSA_BITS 4 +#define SOFM_ALAW_SHIFT_MASK 0x07 +#define SOFM_ALAW_DEC_ONES_MASK 0x21 /* 0b100001 for "1abcd1", see below */ + +/* + * A-law encode table (sign bit is b12) + * + * Input values 11:0 Output values 6:0 + * + * 0 0 0 0 0 0 0 a b c d x 0 0 0 a b c d + * 0 0 0 0 0 0 1 a b c d x 0 0 1 a b c d + * 0 0 0 0 0 1 a b c d x x 0 1 0 a b c d + * 0 0 0 0 1 a b c d x x x 0 1 1 a b c d + * 0 0 0 1 a b c d x x x x 1 0 0 a b c d + * 0 0 1 a b c d x x x x x 1 0 1 a b c d + * 0 1 a b c d x x x x x x 1 1 0 a b c d + * 1 a b c d x x x x x x x 1 1 1 a b c d + * + * + * A-law decode table (sign bit is b7) + * + * Input values 6:0 Output values 11:0 + * + * 0 0 0 a b c d 0 0 0 0 0 0 0 a b c d 1 + * 0 0 1 a b c d 0 0 0 0 0 0 1 a b c d 1 + * 0 1 0 a b c d 0 0 0 0 0 1 a b c d 1 0 + * 0 1 1 a b c d 0 0 0 0 1 a b c d 1 0 0 + * 1 0 0 a b c d 0 0 0 1 a b c d 1 0 0 0 + * 1 0 1 a b c d 0 0 1 a b c d 1 0 0 0 0 + * 1 1 0 a b c d 0 1 a b c d 1 0 0 0 0 0 + * 1 1 1 a b c d 1 a b c d 1 0 0 0 0 0 0 + * + */ + +/* Shift values lookup table for above table for 7 + * highest sample value bits. + */ +static uint8_t alaw_encode_shifts[128] = { + 1, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, +}; + +/** + * sofm_a_law_encode() - Encode sample with A-law coding + * @param sample: A s16 sample value + * + * The A-law codec is defined in ITU-T G.711 standard and has been used + * in telecommunications in e.g. Europe. The A-law coding compresses 13 bit + * samples to 8 bit data stream. In SOF the high 13 bits of s16 format are + * used for compatibility with normal audios. + * + * @return: Compressed 8 bit code value + */ + +uint8_t sofm_a_law_encode(int16_t sample) +{ + int sign = SOFM_ALAW_SIGN_BIT; + int shift = 0; + int low_bits; + uint8_t byte; + + /* Convert to 13 bits with shift */ + sample >>= 3; + + /* Negative samples are 1's complement with zero sign bit */ + if (sample < 0) { + sign = 0; + sample = -sample - 1; + } + + if (sample > SOFM_ALAW_MAX) + sample = SOFM_ALAW_MAX; + + if (sample > 31) { + shift = alaw_encode_shifts[sample >> 5]; + low_bits = (sample >> shift) & SOFM_ALAW_MANTISSA_MASK; + } else { + low_bits = (sample >> 1) & SOFM_ALAW_MANTISSA_MASK; + } + + byte = (shift << SOFM_ALAW_MANTISSA_BITS) | low_bits; + byte = (byte | sign) ^ SOFM_ALAW_TOGGLE_EVEN_BITS; + return byte; +} + +/** + * sofm_a_law_decode() - Decode A-law encoded code word + * @param byte: Encoded code word + * + * The A-law decoder expands a 8 bit code word into a 13 bit sample value. + * In the SOF the high 13 bits are aligned to the most significant bits + * to be compatible with normal s16 Q1.15 samples. + * + * @return: Sample value in s16 format + */ +int16_t sofm_a_law_decode(int8_t byte) +{ + int low_bits; + int shift; + int sign; + int16_t value; + + byte ^= SOFM_ALAW_TOGGLE_EVEN_BITS; + low_bits = byte & SOFM_ALAW_MANTISSA_MASK; + shift = (byte >> SOFM_ALAW_MANTISSA_BITS) & SOFM_ALAW_SHIFT_MASK; + sign = byte & SOFM_ALAW_SIGN_BIT; + + if (shift > 0) + value = (low_bits << shift) | (SOFM_ALAW_DEC_ONES_MASK << (shift - 1)); + else + value = (low_bits << 1) | 1; + + if (!sign) + value = -value; + + /* Shift 13 bit Q1.12 to 16 bit Q1.15 */ + return value << 3; +} diff --git a/src/math/atan2.c b/src/math/atan2.c new file mode 100644 index 000000000000..652f1d5c9cc7 --- /dev/null +++ b/src/math/atan2.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +/** + * \file math/atan2.c + * \brief Four-quadrant arctangent function using polynomial approximation + */ + +#include <rtos/symbol.h> +#include <sof/audio/format.h> +#include <sof/math/trig.h> +#include <stdint.h> + +/* + * Degree-9 Remez minimax polynomial for atan(z) in first octant, z in [0, 1]: + * + * atan(z) = z * (C0 + z^2 * (C1 + z^2 * (C2 + z^2 * (C3 + z^2 * C4)))) + * + * Coefficients are in Q3.29 format, computed via Remez exchange algorithm + * to minimize the maximum approximation error over [0, 1]. + * Maximum approximation error is ~0.0011 degrees (1.94e-5 radians). + */ +#define SOFM_ATAN2_C0 536890772 /* Q3.29, +1.000036992319 */ +#define SOFM_ATAN2_C1 -178298711 /* Q3.29, -0.332107229582 */ +#define SOFM_ATAN2_C2 99794340 /* Q3.29, +0.185881443393 */ +#define SOFM_ATAN2_C3 -49499604 /* Q3.29, -0.092200197922 */ +#define SOFM_ATAN2_C4 12781063 /* Q3.29, +0.023806584771 */ + +/** + * sofm_atan2_32b() - Compute four-quadrant arctangent of y/x + * @param y Imaginary component in Q1.31 format + * @param x Real component in Q1.31 format + * @return Angle in Q3.29 radians, range [-pi, +pi] + * + * Uses degree-9 Remez minimax polynomial for the core atan(z) computation + * where z = min(|y|,|x|) / max(|y|,|x|) is reduced to [0, 1] range. + * Octant and quadrant corrections extend the result to full [-pi, +pi]. + */ +int32_t sofm_atan2_32b(int32_t y, int32_t x) +{ + int32_t abs_x; + int32_t abs_y; + int32_t num; + int32_t den; + int32_t z; + int32_t z2; + int32_t acc; + int32_t angle; + int swap; + + /* Return zero for origin */ + if (x == 0 && y == 0) + return 0; + + /* Take absolute values, handle INT32_MIN overflow */ + abs_x = (x > 0) ? x : ((x == INT32_MIN) ? INT32_MAX : -x); + abs_y = (y > 0) ? y : ((y == INT32_MIN) ? INT32_MAX : -y); + + /* Reduce to first octant: z = min/max ensures z in [0, 1] */ + if (abs_y <= abs_x) { + num = abs_y; + den = abs_x; + swap = 0; + } else { + num = abs_x; + den = abs_y; + swap = 1; + } + + /* z = num / den in Q1.31, den is always > 0 here */ + z = sat_int32(((int64_t)num << 31) / den); + + /* + * Horner evaluation of degree-9 Remez minimax polynomial: + * atan(z) = z * (C0 + z^2 * (C1 + z^2 * (C2 + z^2 * (C3 + z^2 * C4)))) + * + * z is Q1.31, coefficients are Q3.29. + * Multiplications: Q1.31 * Q3.29 = Q4.60, >> 31 -> Q3.29. + */ + + /* z^2: Q1.31 * Q1.31 = Q2.62, >> 31 -> Q1.31 */ + z2 = (int32_t)(((int64_t)z * z) >> 31); + + /* Innermost: C3 + z^2 * C4 */ + acc = (int32_t)(((int64_t)z2 * SOFM_ATAN2_C4) >> 31) + SOFM_ATAN2_C3; + + /* C2 + z^2 * (C3 + z^2 * C4) */ + acc = (int32_t)(((int64_t)z2 * acc) >> 31) + SOFM_ATAN2_C2; + + /* C1 + z^2 * (C2 + z^2 * (C3 + z^2 * C4)) */ + acc = (int32_t)(((int64_t)z2 * acc) >> 31) + SOFM_ATAN2_C1; + + /* C0 + z^2 * (C1 + z^2 * (C2 + z^2 * (C3 + z^2 * C4))) */ + acc = (int32_t)(((int64_t)z2 * acc) >> 31) + SOFM_ATAN2_C0; + + /* angle = z * acc: Q1.31 * Q3.29 = Q4.60, >> 31 -> Q3.29 */ + angle = (int32_t)(((int64_t)z * acc) >> 31); + + /* If |y| > |x|, use identity: atan(y/x) = pi/2 - atan(x/y) */ + if (swap) + angle = PI_DIV2_Q3_29 - angle; + + /* Map to correct quadrant based on signs of x and y */ + if (x < 0) + angle = (y >= 0) ? PI_Q3_29 - angle : -(PI_Q3_29 - angle); + else if (y < 0) + angle = -angle; + + return angle; +} +EXPORT_SYMBOL(sofm_atan2_32b); diff --git a/src/math/auditory/CMakeLists.txt b/src/math/auditory/CMakeLists.txt new file mode 100644 index 000000000000..b24cf968f237 --- /dev/null +++ b/src/math/auditory/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: BSD-3-Clause + +set(base_files auditory.c) + +if(CONFIG_MATH_16BIT_MEL_FILTERBANK) + list(APPEND base_files mel_filterbank_16.c) +endif() + +if(CONFIG_MATH_32BIT_MEL_FILTERBANK) + list(APPEND base_files mel_filterbank_32.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + zephyr_library_sources( + ${base_files} + ) + +else() ### library, e.g. testbench or plugin ### + + add_local_sources(sof ${base_files}) + +endif() diff --git a/src/math/auditory/auditory.c b/src/math/auditory/auditory.c new file mode 100644 index 000000000000..57641c46aa5a --- /dev/null +++ b/src/math/auditory/auditory.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/format.h> +#include <rtos/alloc.h> +#include <sof/math/auditory.h> +#include <sof/math/decibels.h> +#include <sof/math/fft.h> +#include <sof/math/log.h> +#include <sof/math/numbers.h> +#include <ipc/topology.h> +#include <errno.h> +#include <stdint.h> + +#define ONE_Q16 Q_CONVERT_FLOAT(1, 16) +#define ONE_Q20 Q_CONVERT_FLOAT(1, 20) +#define ONE_Q30 Q_CONVERT_FLOAT(1, 30) +#define TWO_Q29 Q_CONVERT_FLOAT(2, 29) + +#define LOG_SCALE_HZMEL_Q26 Q_CONVERT_FLOAT(18.02182669, 26) +#define LOG_MULT_HZMEL_Q20 Q_CONVERT_FLOAT(1126.9941805389, 20) +#define ONE_OVER_HZDIV_Q31 Q_CONVERT_FLOAT(1.0 / 700, 31) +#define ONE_OVER_MELDIV_Q31 Q_CONVERT_FLOAT(1.0 / 1126.9941805389, 31) + +#define MEL_MAX_Q2 Q_CONVERT_FLOAT(4358.351140, 2) /* 32767 Hz */ + +#define LOG2_2P16 Q_CONVERT_FLOAT(16.0, 16) /* log2(2^16) as Q16.16 */ + +/* For scaling log2 power to log, log10, or dB*/ +#define ONE_OVER_LOG2E_Q29 Q_CONVERT_FLOAT(0.6931471806, 29) /* 1/log2(exp(1))) */ +#define ONE_OVER_LOG2TEN_Q29 Q_CONVERT_FLOAT(0.3010299957, 29) /* 1/log2(10) */ +#define TEN_OVER_LOG2TEN_Q29 Q_CONVERT_FLOAT(3.0102999566, 29) /* 10/log2(10) */ + +/** + * Convert Hz to Mel + * Wikipedia https://en.wikipedia.org/wiki/Mel_scale + * mel = 1126.9941805389 * log(1 + hz / 700) + * + * @param hz Frequency as Q16.0 Hz, max 32767 Hz + * @return Value as Q14.2 Mel, max 4358.4 Mel + */ +int16_t psy_hz_to_mel(int16_t hz) +{ + uint32_t log_arg; + int32_t log; + int16_t mel; + + if (hz < 0) + return 0; + + /* Log function input is unsigned UQ32.0, output is UQ5.27 */ + log_arg = (1 << 26) + Q_MULTSR_32X32((int64_t)hz, ONE_OVER_HZDIV_Q31, 0, 31, 26); + + log = (int32_t)(ln_int32(log_arg) >> 1) - LOG_SCALE_HZMEL_Q26; + mel = Q_MULTSR_32X32((int64_t)log, LOG_MULT_HZMEL_Q20, 26, 20, 2); + return mel; +} + +/** + * Convert Mel to Hz + * Wikipedia https://en.wikipedia.org/wiki/Mel_scale + * hz = 700 * (exp(mel / 1126.9941805389) - 1) + * + * @param mel Value as Q14.2 Mel, max 4358.4 Mel + * @return hz Frequency as Q16.0 Hz, max 32767 Hz + */ +int16_t psy_mel_to_hz(int16_t mel) +{ + int32_t exp_arg; + int32_t exp; + int16_t hz; + + if (mel > MEL_MAX_Q2) + return INT16_MAX; + + if (mel < 0) + return 0; + + exp_arg = Q_MULTSR_32X32((int64_t)mel, ONE_OVER_MELDIV_Q31, 2, 31, 27); + exp = exp_fixed(exp_arg) - ONE_Q20; + hz = Q_MULTSR_32X32((int64_t)exp, 700, 20, 0, 0); + return hz; +} + +int mod_psy_get_mel_filterbank(struct processing_module *mod, struct psy_mel_filterbank *fb) +{ + int32_t up_slope; + int32_t down_slope; + int32_t slope; + int32_t scale = ONE_Q16; + int32_t scale_inv = ONE_Q16; + int16_t *mel; + int16_t mel_start; + int16_t mel_end; + int16_t mel_step; + int16_t left_mel; + int16_t center_mel; + int16_t right_mel; + int16_t delta_cl; + int16_t delta_rc; + int16_t left_hz; + int16_t right_hz; + int16_t f; + int segment; + int i, j, idx; + int base_idx = 0; + int start_bin = 0; + int end_bin = 0; + + if (!fb) + return -ENOMEM; + + if (!fb->scratch_data1 || !fb->scratch_data2) + return -ENOMEM; + + /* Log power can be log, or log10 or dB, get multiply coef to convert + * log to desired format. + */ + switch (fb->mel_log_scale) { + case MEL_LOG: + fb->log_mult = ONE_OVER_LOG2E_Q29; + break; + case MEL_LOG10: + fb->log_mult = ONE_OVER_LOG2TEN_Q29; + break; + case MEL_DB: + fb->log_mult = TEN_OVER_LOG2TEN_Q29; + break; + default: + return -EINVAL; + } + + /* Use scratch area to hold vector of Mel values for each FFT frequency */ + if (fb->scratch_length1 < fb->half_fft_bins) + return -ENOMEM; + + fb->scale_log2 = 0; + + mel = fb->scratch_data1; + for (i = 0; i < fb->half_fft_bins; i++) { + f = fb->samplerate * i / fb->fft_bins; + mel[i] = psy_hz_to_mel(f); + } + + mel_start = psy_hz_to_mel(fb->start_freq); + mel_end = psy_hz_to_mel(fb->end_freq); + mel_step = (mel_end - mel_start) / (fb->mel_bins + 1); + for (i = 0; i < fb->mel_bins; i++) { + left_mel = mel_start + i * mel_step; + center_mel = mel_start + (i + 1) * mel_step; + right_mel = mel_start + (i + 2) * mel_step; + delta_cl = center_mel - left_mel; + delta_rc = right_mel - center_mel; + segment = 0; + idx = base_idx + 3; /* start of filter weight values */ + if (fb->slaney_normalize) { + left_hz = psy_mel_to_hz(left_mel); + right_hz = psy_mel_to_hz(right_mel); + scale = Q_SHIFT_RND(TWO_Q29 / (right_hz - left_hz), 29, 16); /* Q16.16*/ + if (i == 0) { + scale_inv = Q_SHIFT_LEFT(ONE_Q30 / scale, 14, 16); + fb->scale_log2 = base2_logarithm((uint32_t)scale) - LOG2_2P16; + } + + scale = Q_MULTSR_32X32((int64_t)scale, scale_inv, 16, 16, 16); + } + for (j = 0; j < fb->half_fft_bins; j++) { + up_slope = (((int32_t)mel[j] - left_mel) << 15) / delta_cl; /* Q17.15 */ + down_slope = (((int32_t)right_mel - mel[j]) << 15) / delta_rc; /* Q17.15 */ + slope = MIN(up_slope, down_slope); + slope = Q_MULTSR_32X32((int64_t)slope, scale, 15, 16, 15); + if (segment == 1 && slope <= 0) { + end_bin = j - 1; + break; + } + + if (segment == 0 && slope > 0) { + start_bin = j; + segment = 1; + } + + if (segment == 1) { + if (idx >= fb->scratch_length2) + return -EINVAL; + + fb->scratch_data2[idx++] = sat_int16(slope); + } + } + + if (idx + 2 >= fb->scratch_length2) + return -EINVAL; + + fb->scratch_data2[base_idx] = idx; /* index to next */ + fb->scratch_data2[base_idx + 1] = start_bin; + fb->scratch_data2[base_idx + 2] = end_bin - start_bin + 1; /* length */ + base_idx = idx; + } + + fb->data_length = &fb->scratch_data2[base_idx] - &fb->scratch_data2[0]; + fb->data = mod_zalloc(mod, sizeof(int16_t) * fb->data_length); + if (!fb->data) + return -ENOMEM; + + /* Copy the exact triangles data size to allocated buffer */ + memcpy_s(fb->data, sizeof(int16_t) * fb->data_length, + fb->scratch_data2, sizeof(int16_t) * fb->data_length); + return 0; +} + +int mod_psy_free_mel_filterbank(struct processing_module *mod, struct psy_mel_filterbank *mel_fb) +{ + return mod_free(mod, mel_fb->data); +} diff --git a/src/math/auditory/mel_filterbank_16.c b/src/math/auditory/mel_filterbank_16.c new file mode 100644 index 000000000000..f5a18f052b77 --- /dev/null +++ b/src/math/auditory/mel_filterbank_16.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex16.h> +#include <sof/math/log.h> +#include <sof/math/numbers.h> +#include <stdint.h> + +void psy_apply_mel_filterbank_16(struct psy_mel_filterbank *fb, struct icomplex16 *fft_out, + int32_t *power_spectra, int16_t *mel_log, int bitshift) +{ + int64_t pp; + int32_t pmax; + int32_t log_arg; + int32_t log; + int32_t p; + int next_idx; + int start_bin; + int num_bins; + int coef_idx; + int i, j; + int base_idx = 0; + int lshift; + + /* A FFT out bin is used several times in Mel bands conversion, so first + * convert FFT to real power spectra, p = (a + bi)(a - bi) = a^2 + b^2 + */ + pmax = 0; + for (i = 0; i < fb->half_fft_bins; i++) { + p = (int32_t)fft_out[i].real * fft_out[i].real + + (int32_t)fft_out[i].imag * fft_out[i].imag; + pmax = MAX(pmax, p); + } + + /* Power spectra is Q2.30 */ + lshift = norm_int32(pmax); + for (i = 0; i < fb->half_fft_bins; i++) { + p = (int32_t)fft_out[i].real * fft_out[i].real + + (int32_t)fft_out[i].imag * fft_out[i].imag; + power_spectra[i] = p << lshift; + } + + for (i = 0; i < fb->mel_bins; i++) { + /* Integrate power spectrum with Mel filter bank triangle weights */ + pp = 0; + next_idx = fb->data[base_idx]; + start_bin = fb->data[base_idx + 1]; + num_bins = fb->data[base_idx + 2]; + coef_idx = base_idx + 3; + base_idx = next_idx; /* For next round */ + + /* Accumulate power as Q3.45 (Q2.30 x Q1.15). Note that filter bank need + * to be later scaled with fb->scale. + */ + for (j = 0; j < num_bins; j++) + pp += (int64_t)power_spectra[start_bin + j] * fb->data[coef_idx + j]; + + /* Convert Mel band energy from Q19.45 to Q7.25 that has sufficient headroom + * for worst-case all ones FFT output. Log2() function input is unsigned Q32.0, + * output is signed Q16.16. The Q7.25 scale log2(2^25) need to be subtracted + * from log output. + */ + log_arg = sat_int32(Q_SHIFT_RND(pp, 45, 25)); + log_arg = MAX(log_arg, AUDITORY_EPS_Q31); + log = base2_logarithm((uint32_t)log_arg); + log -= AUDITORY_LOG2_2P25_Q16; + + /* Compensate Mel triangles scale */ + log += fb->scale_log2; + + /* Subtract the applied lshift for power spectra + * log2(x * 2^(-n)) = log2(x) - n. Note that the bitshift need to be subtracted + * as doubled because it was applied in linear domain, from log(x * 2^(-2 * n)) + */ + log -= ((int32_t)lshift + 2 * bitshift) << 16; + + /* Scale for desired log */ + log = Q_MULTSR_32X32((int64_t)log, fb->log_mult, 16, 29, 7); + mel_log[i] = sat_int16(log); /* Q8.7 */ + } +} diff --git a/src/math/auditory/mel_filterbank_32.c b/src/math/auditory/mel_filterbank_32.c new file mode 100644 index 000000000000..414ddf482f93 --- /dev/null +++ b/src/math/auditory/mel_filterbank_32.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex32.h> +#include <sof/math/log.h> +#include <sof/math/numbers.h> +#include <stdint.h> + +void psy_apply_mel_filterbank_32(struct psy_mel_filterbank *fb, struct icomplex32 *fft_out, + int32_t *power_spectra, int32_t *mel_log, int bitshift) +{ + int64_t pmax; + int64_t p; + int32_t log_arg; + int32_t log; + int next_idx; + int start_bin; + int num_bins; + int coef_idx; + int i, j; + int base_idx = 0; + int lshift; + + /* A FFT out bin is used several times in Mel bands conversion, so first + * convert FFT to real power spectra, p = (a + bi)(a - bi) = a^2 + b^2 + */ + pmax = 0; + for (i = 0; i < fb->half_fft_bins; i++) { + p = (int64_t)fft_out[i].real * fft_out[i].real + + (int64_t)fft_out[i].imag * fft_out[i].imag; + pmax = MAX(pmax, p); + } + + /* Product Q2.62, convert to 2.30 */ + pmax = sat_int32(pmax >> 32); + lshift = norm_int32(pmax); + for (i = 0; i < fb->half_fft_bins; i++) { + p = (int64_t)fft_out[i].real * fft_out[i].real + + (int64_t)fft_out[i].imag * fft_out[i].imag; + power_spectra[i] = Q_SHIFT_RND(p << lshift, 62, 30); + } + + for (i = 0; i < fb->mel_bins; i++) { + /* Integrate power spectrum with Mel filter bank triangle weights */ + p = 0; + next_idx = fb->data[base_idx]; + start_bin = fb->data[base_idx + 1]; + num_bins = fb->data[base_idx + 2]; + coef_idx = base_idx + 3; + base_idx = next_idx; /* For next round */ + + /* Accumulate power as Q3.45 (Q2.30 x Q1.15). Note that filter bank need + * to be later scaled with fb->scale. + */ + for (j = 0; j < num_bins; j++) + p += (int64_t)power_spectra[start_bin + j] * fb->data[coef_idx + j]; + + /* Convert Mel band energy from Q19.45 to Q7.25 that has sufficient headroom + * for worst-case all ones FFT output. Log2() function input is unsigned Q32.0, + * output is signed Q16.16. The Q7.25 scale log2(2^25) need to be subtracted + * from log output. + */ + log_arg = sat_int32(Q_SHIFT_RND(p, 45, 25)); + log_arg = MAX(log_arg, AUDITORY_EPS_Q31); + log = base2_logarithm((uint32_t)log_arg); + log -= AUDITORY_LOG2_2P25_Q16; + + /* Compensate Mel triangles scale */ + log += fb->scale_log2; + + /* Subtract the applied lshift for power spectra + * log2(x * 2^(-n)) = log2(x) - n. Note that the bitshift need to be subtracted + * as doubled because it was applied in linear domain, from log(x * 2^(-2 * n)) + */ + log -= ((int32_t)lshift + 2 * bitshift) << 16; + + /* Scale for desired log, output as Q9.23 */ + log = Q_MULTSR_32X32((int64_t)log, fb->log_mult, 16, 29, 23); + mel_log[i] = log; /* Q9.23 */ + } +} diff --git a/src/math/base2log.c b/src/math/base2log.c new file mode 100644 index 000000000000..5ca3967d9a85 --- /dev/null +++ b/src/math/base2log.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> +// +// + +#include <sof/math/log.h> + +/* Defines Constant*/ +#define BASE2LOG_WRAP_SCHAR_BITS 0xFF +#define BASE2LOG_UPPERBYTES 0xFFFFFF +#define BASE2LOG_WORDLENGTH 0x1F +/** + * Base-2 logarithm log2(n) + * + * Y = (u) computes the base-2 logarithm of + * u using lookup table. + * input u must be scalar/real number and positive + * + * +------------------+-----------------+--------+--------+ + * | u | y (returntype) | u | y | + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 0 | 0 | 32 | 16 | 0 | 32.0 | 16.16 | + * +------------------+-----------------+--------+--------+ + * + * Arguments : uint32_t u + * u input range [1 to 4294967295] + * + * Return Type : int32_t y + * y output range [0 to 32] + * + */ +int32_t base2_logarithm(uint32_t u) +{ + static const int32_t iv1[129] = { + 0, 736, 1466, 2190, 2909, 3623, 4331, 5034, 5732, 6425, 7112, 7795, + 8473, 9146, 9814, 10477, 11136, 11791, 12440, 13086, 13727, 14363, 14996, 15624, + 16248, 16868, 17484, 18096, 18704, 19308, 19909, 20505, 21098, 21687, 22272, 22854, + 23433, 24007, 24579, 25146, 25711, 26272, 26830, 27384, 27936, 28484, 29029, 29571, + 30109, 30645, 31178, 31707, 32234, 32758, 33279, 33797, 34312, 34825, 35334, 35841, + 36346, 36847, 37346, 37842, 38336, 38827, 39316, 39802, 40286, 40767, 41246, 41722, + 42196, 42667, 43137, 43603, 44068, 44530, 44990, 45448, 45904, 46357, 46809, 47258, + 47705, 48150, 48593, 49034, 49472, 49909, 50344, 50776, 51207, 51636, 52063, 52488, + 52911, 53332, 53751, 54169, 54584, 54998, 55410, 55820, 56229, 56635, 57040, 57443, + 57845, 58245, 58643, 59039, 59434, 59827, 60219, 60609, 60997, 61384, 61769, 62152, + 62534, 62915, 63294, 63671, 64047, 64421, 64794, 65166, 65536}; + static const int8_t iv[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint64_t v; + uint32_t x; + int32_t a_i; + int32_t l1_i; + int32_t s_v; + int32_t l2_i; + int32_t l3_i; + int num_left_shifts; + int shift_factor; + unsigned int slice_temp; + /* Skipping for-loop */ + /* Unroll the loop so there will be no branching. */ + /* Loop unroll execute 20% faster (CPU cycle count )than for loop */ + /* Every iteration, look for leading zeros are in the high */ + /* byte of V, and shift them out to the left. Continue with the */ + /* shifted V for as many bytes as it has. */ + /* The index is the high byte of the input plus 1 to make it a */ + /* one-based index. */ + /* Index into the number-of-leading-zeros lookup table. This lookup */ + /* table takes in a byte and returns the number of leading zeros in the */ + /* binary representation. */ + shift_factor = iv[u >> 24]; + /* Left-shift out all the leading zeros in the high byte. */ + v = (uint64_t)u << shift_factor; + /* Update the total number of left-shifts */ + num_left_shifts = shift_factor; + shift_factor = iv[v >> 24]; + /* Left-shift out all the leading zeros in the high byte. */ + v <<= shift_factor; + /* Update the total number of left-shifts */ + num_left_shifts += shift_factor; + shift_factor = iv[v >> 24]; + /* Left-shift out all the leading zeros in the high byte. */ + v <<= shift_factor; + /* Update the total number of left-shifts */ + num_left_shifts += shift_factor; + shift_factor = iv[v >> 24]; + /* Left-shift out all the leading zeros in the high byte. */ + /* Update the total number of left-shifts */ + num_left_shifts += shift_factor; + /* The input has been left-shifted so the most-significant-bit is a 1. */ + /* Reinterpret the output as unsigned with one integer bit, so */ + /* that 1 <= x < 2. */ + x = (uint32_t)v << shift_factor; + /* Let Q = int(u). Then u = Q*2^(-u_fraction_length), */ + /* and x = Q*2^num_left_shifts * 2^(1-word_length). Therefore, */ + /* u = x*2^n, where n is defined as: */ + /* Extract the high byte of x */ + /* Convert the high byte into an index for lookup table */ + slice_temp = (v << shift_factor) >> 24; + /* Interpolate between points. */ + /* The upper byte was used for the index into lookup table */ + /* The remaining bits make up the fraction between points. */ + a_i = BASE2LOG_WORDLENGTH - num_left_shifts; + a_i <<= 16; + l1_i = iv1[(BASE2LOG_WRAP_SCHAR_BITS & ((x >> 24) + 129)) - 1]; + s_v = a_i + l1_i; + l2_i = iv1[(BASE2LOG_WRAP_SCHAR_BITS & (slice_temp + 130)) - 1]; + l3_i = iv1[(slice_temp - 127) - 1]; + return s_v + (((x & BASE2LOG_UPPERBYTES) * (int64_t)(l2_i - l3_i)) >> 24); +} + diff --git a/src/math/complex.c b/src/math/complex.c new file mode 100644 index 000000000000..ac2a59e91498 --- /dev/null +++ b/src/math/complex.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// + +#include <rtos/symbol.h> +#include <sof/audio/format.h> +#include <sof/math/icomplex32.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <stdint.h> + +/* sofm_icomplex32_to_polar() - Convert (re, im) complex number to polar. */ +void sofm_icomplex32_to_polar(struct icomplex32 *complex, struct ipolar32 *polar) +{ + struct icomplex32 c = *complex; + int64_t squares_sum; + int32_t sqrt_arg; + + /* Calculate square of magnitudes Q1.31, result is Q2.62 */ + squares_sum = (int64_t)c.real * c.real + (int64_t)c.imag * c.imag; + + /* Square root */ + sqrt_arg = Q_SHIFT_RND(squares_sum, 62, 30); + polar->magnitude = sofm_sqrt_int32(sqrt_arg); /* Q2.30 */ + + /* Angle */ + polar->angle = sofm_atan2_32b(c.imag, c.real); /* Q3.29 */ +} +EXPORT_SYMBOL(sofm_icomplex32_to_polar); + +/* sofm_ipolar32_to_complex() - Convert complex number from polar to normal (re, im) format. */ +void sofm_ipolar32_to_complex(struct ipolar32 *polar, struct icomplex32 *complex) +{ + struct cordic_cmpx cexp; + int32_t phase; + int32_t magnitude; + + /* The conversion can happen in-place, so load copies of the values first */ + magnitude = polar->magnitude; + phase = Q_SHIFT_RND(polar->angle, 29, 28); /* Q3.29 to Q2.28 */ + cmpx_exp_32b(phase, &cexp); /* Q2.30 */ + complex->real = sat_int32(Q_MULTSR_32X32((int64_t)magnitude, cexp.re, 30, 30, 31)); + complex->imag = sat_int32(Q_MULTSR_32X32((int64_t)magnitude, cexp.im, 30, 30, 31)); +} +EXPORT_SYMBOL(sofm_ipolar32_to_complex); diff --git a/src/math/dct.c b/src/math/dct.c new file mode 100644 index 000000000000..e4bbe5623dd8 --- /dev/null +++ b/src/math/dct.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/format.h> +#include <sof/math/matrix.h> +#include <sof/math/dct.h> +#include <sof/math/sqrt.h> +#include <sof/math/trig.h> +#include <errno.h> +#include <stdint.h> + +#define PI_Q29 Q_CONVERT_FLOAT(3.1415926536, 29) +#define TWO_PI_Q24 Q_CONVERT_FLOAT(6.2831853072, 24) +#define ONE_OVER_SQRT_TWO Q_CONVERT_FLOAT(0.7071067812, 31) +#define HALF_Q1 Q_CONVERT_FLOAT(0.5, 1) +#define TWO_Q29 Q_CONVERT_FLOAT(2, 29) + +/* Return a matrix for discrete cosine transform (DCT). The DCT type is hard + * coded to DCT-II with orthogonal matrix. See + * https://en.wikipedia.org/wiki/Discrete_cosine_transform#DCT-II + * + * The size is (num_in, num_out). Currently there are not other input parameters. + * TODO: Add option for no ortho norm. + */ + +/** + * \brief Initialize a 16 bit DCT matrix. The actual DCT transform is a matrix + * multiply with the returned matrix. + * \param[in,out] dct In input provide DCT type and size, in output the DCT matrix + */ +int mod_dct_initialize_16(struct processing_module *mod, struct dct_plan_16 *dct) +{ + int16_t dct_val; + int32_t arg; + int32_t cos; + int32_t c1; + int16_t c2; + int16_t nk; + int n; + int k; + + if (dct->type != DCT_II || dct->ortho != true) + return -EINVAL; + + if (dct->num_in < 1 || dct->num_out < 1) + return -EINVAL; + + if (dct->num_in > DCT_MATRIX_SIZE_MAX || dct->num_out > DCT_MATRIX_SIZE_MAX) + return -EINVAL; + + dct->matrix = mod_mat_matrix_alloc_16b(mod, dct->num_in, dct->num_out, 15); + if (!dct->matrix) + return -ENOMEM; + + c1 = PI_Q29 / dct->num_in; + arg = Q_SHIFT_RND(TWO_Q29 / dct->num_in, 29, 12); + c2 = sofm_sqrt_int16(arg); /* Q4.12 */ + for (n = 0; n < dct->num_in; n++) { + for (k = 0; k < dct->num_out; k++) { + /* Note: Current int16_t nk works up to DCT_MATRIX_SIZE_MAX = 91 */ + nk = (Q_SHIFT_LEFT(n, 0, 1) + HALF_Q1) * Q_SHIFT_LEFT(k, 0, 1); /*Q14.2 */ + arg = Q_MULTSR_32X32((int64_t)c1, nk, 29, 2, 24); /* Q8.24 */ + /* Note: Q8.24 works up to DCT_MATRIX_SIZE_MAX = 42 */ + arg %= TWO_PI_Q24; + cos = cos_fixed_32b(Q_SHIFT_LEFT(arg, 24, 28)); /* Q1.31 */ + dct_val = Q_MULTSR_32X32((int64_t)cos, c2, 31, 12, 15); /* Q1.15 */ + if (k == 0) + dct_val = Q_MULTSR_32X32((int64_t)dct_val, + ONE_OVER_SQRT_TWO, 15, 31, 15); + + mat_set_scalar_16b(dct->matrix, n, k, dct_val); + } + } + + return 0; +} + +int mod_dct_free_16(struct processing_module *mod, struct dct_plan_16 *dct) +{ + return mod_free(mod, dct->matrix); +} diff --git a/src/math/exp_fcn.c b/src/math/exp_fcn.c new file mode 100644 index 000000000000..5ada3f708c7f --- /dev/null +++ b/src/math/exp_fcn.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022-2025 Intel Corporation. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Pasca, Bogdan <bogdan.pasca@intel.com> + */ + +#include <sof/audio/format.h> +#include <sof/math/exp_fcn.h> +#include <sof/math/numbers.h> +#include <rtos/symbol.h> +#include <sof/common.h> +#include <stdint.h> + +#if defined(EXPONENTIAL_GENERIC) + +#define SOFM_EXP_ONE_OVER_LOG2_Q30 1549082005 /* Q2.30 int32(round(1/log(2) * 2^30)) */ +#define SOFM_EXP_LOG2_Q31 1488522236 /* Q1.31 int32(round(log(2) * 2^31)) */ +#define SOFM_EXP_FIXED_INPUT_MINUS8 -1073741824 /* Q5.27 int32(-8 * 2^27) */ +#define SOFM_EXP_FIXED_INPUT_PLUS8 1073741823 /* Q5.27 int32(8 * 2^27) */ +#define SOFM_EXP_LOG10_DIV20_Q27 15452387 /* Q5.27 int32(round(log(10)/20*2^27)) */ + +/* The table contains exponents of value v, where values of v + * are the 3 bit 2's complement signed values presented by bits + * of index 0..7. + * + * v = [(0:3)/8 (-4:-1)/8]; + * uint32(round(exp(v) * 2^31)) + */ +static const uint32_t sofm_exp_3bit_lookup[8] = { + 2147483648, 2433417774, 2757423586, 3124570271, + 1302514674, 1475942488, 1672461947, 1895147668 +}; + +/* Taylor polynomial coefficients for x^3..x^6, calculated + * uint32(round(1 ./ factorial(3:6) * 2^32)) + */ +static const uint32_t sofm_exp_taylor_coeffs[4] = { + 715827883, 178956971, 35791394, 5965232 +}; + +/* function f(x) = e^x + * + * Arguments : int32_t x (Q4.28) + * input range -8 to 8 + * + * Return Type : int32_t (Q13.19) + * output range 3.3546e-04 to 2981.0 + */ +int32_t sofm_exp_approx(int32_t x) +{ + uint32_t taylor_first_2; + uint32_t exp_a_b_32bit; + uint32_t taylor_extra; + uint32_t rnd_one; + uint32_t b_f32; + uint32_t b_pow; + uint32_t exp_a; + uint32_t exp_b; + uint32_t term; + uint32_t b; + int32_t x_times_one_over_log2; + int32_t e_times_log2; + int32_t x_32bit; + int32_t y_32bit; + int32_t e; + int32_t r; + int shift_value; + int a; + + /* ------------------------------------------------------------------------- + * FIRST RANGE REDUCTION --------------------------------------------------- + * ------------------------------------------------------------------------- + */ + x_times_one_over_log2 = Q_MULTSR_32X32((int64_t)x, SOFM_EXP_ONE_OVER_LOG2_Q30, 28, 30, 26); + e = Q_SHIFT_RND(x_times_one_over_log2, 26, 0); + + /* Q6.31, but we only keep the bottom 31 bits */ + e_times_log2 = (uint32_t)e * SOFM_EXP_LOG2_Q31; + + /* ------------------------------------------------------------------------- + * SECOND RANGE REDUCTION -------------------------------------------------- + * y = a + b + * ------------------------------------------------------------------------- + */ + x_32bit = (int32_t)((uint32_t)x << 3); /* S4.31 */ + y_32bit = x_32bit - e_times_log2; /* S0.31, in ~[-0.34, +0.34] */ + a = (y_32bit >> 28) & 7; /* just the 3 top bits of "y" */ + b = y_32bit & 0x0FFFFFFF; /* bottom 31-3 = 28 bits. format U-3.31 */ + exp_a = sofm_exp_3bit_lookup[a]; + b_f32 = (b << 1) | 0x4; /* U0.32, align b on 32-bits of fraction */ + + /* Taylor approximation : base part + iterations + * Base part : 1 + b + b^2/2! + * Iterative part : b^3/3! + b^4/4! + b^5/5! + b^6/6! + * : Term count determined dynamically using e. + * + * Base part: NOTE: delay adding the "1" in "1 + b + b^2/2" until after we + * add the iterative part in. This gives us one more guard bit. + * NOTE: u_int32 x u_int32 => {hi, lo}. We only need {hi} for b_pow. + */ + b_pow = (uint64_t)b_f32 * b_f32 >> 32; + taylor_first_2 = b_f32 + (b_pow >> 1); /* 0.32 */ + taylor_extra = 0; + term = 1; + if (e < -10) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[0] >> 32; + taylor_extra += term; + if (e < -5) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[1] >> 32; + taylor_extra += term; + if (e < 0) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[2] >> 32; + taylor_extra += term; + if (e < 6) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[3] >> 32; + taylor_extra += term; + +ITER_END: + + /* Implement rounding to 31 fractional bits.. */ + taylor_first_2 = taylor_first_2 + taylor_extra + 1; + + /* Add the missing "1" for the Taylor series "1+b+b^2/2+...." */ + exp_b = ((uint32_t)1 << 31) + (taylor_first_2 >> 1); /* U1.31 */ + + /* ------------------------------------------------------------------------- + * FIRST RECONSTRUCTION ---------------------------------------------------- + * ------------------------------------------------------------------------- + */ + + /* U1.31 * U1.31 = U2.62 */ + exp_a_b_32bit = (uint64_t)exp_a * exp_b >> 31; + + /* ------------------------------------------------------------------------- + * SECOND RECONSTRUCTION --------------------------------------------------- + * ------------------------------------------------------------------------- + */ + + /* Rounding to nearest */ + shift_value = 12 - e; + rnd_one = (shift_value > 0 ? (1 << (shift_value - 1)) : 0); + exp_a_b_32bit += rnd_one; + r = (int32_t)(exp_a_b_32bit >> shift_value); + return r; +} +EXPORT_SYMBOL(sofm_exp_approx); + +/* Fixed point exponent function for approximate range -16 .. 7.6 + * that corresponds to decibels range -120 .. +66 dB. + * + * The functions uses rule exp(x) = exp(x/2) * exp(x/2) to reduce + * the input argument for the exponent function. + * + * Input is Q5.27, -16.0 .. +16.0, but note the input range limitation + * Output is Q12.20, 0.0 .. +2048.0 + */ + +int32_t sofm_exp_fixed(int32_t x) +{ + int32_t x0, y0, y1; + + if (x > SOFM_EXP_FIXED_INPUT_MAX) + return INT32_MAX; + + if (x < SOFM_EXP_FIXED_INPUT_MINUS8 || x > SOFM_EXP_FIXED_INPUT_PLUS8) { + /* Divide by 2, convert Q27 to Q28 is x as such */ + y0 = sofm_exp_approx(x); + y1 = Q_MULTSR_32X32((int64_t)y0, y0, 19, 19, 20); + return y1; + } + + x0 = sat_int32((int64_t)x << 1); + y0 = sofm_exp_approx(x0); + return sat_int32((int64_t)y0 << 1); +} +EXPORT_SYMBOL(sofm_exp_fixed); + +/* Decibels to linear conversion: The function uses exp() to calculate + * the linear value. The argument is multiplied by log(10)/20 to + * calculate equivalent of 10^(db/20). + * + * The error in conversion is less than 0.1 dB for -89..+66 dB range. Do not + * use the code for argument less than -100 dB. The code simply returns zero + * as linear value for such very small value. + * + * Input is Q8.24 (max 128.0) + * output is Q12.20 (max 2048.0) + */ + +int32_t sofm_db2lin_fixed(int32_t db) +{ + int32_t arg; + + if (db > SOFM_DB2LIN_INPUT_MAX) + return INT32_MAX; + + /* Q8.24 x Q5.27, result needs to be Q5.27 */ + arg = (int32_t)Q_MULTSR_32X32((int64_t)db, SOFM_EXP_LOG10_DIV20_Q27, 24, 27, 27); + return sofm_exp_fixed(arg); +} +EXPORT_SYMBOL(sofm_db2lin_fixed); + +#endif /* EXPONENTIAL_GENERIC */ diff --git a/src/math/exp_fcn_hifi.c b/src/math/exp_fcn_hifi.c new file mode 100644 index 000000000000..7180ef2ae0e6 --- /dev/null +++ b/src/math/exp_fcn_hifi.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + *Copyright(c) 2023-2025 Intel Corporation. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + * Pasca, Bogdan <bogdan.pasca@intel.com> + */ + +#include <sof/audio/format.h> +#include <sof/math/exp_fcn.h> +#include <sof/common.h> +#include <rtos/symbol.h> +#include <stdint.h> + +#if defined(SOFM_EXPONENTIAL_HIFI3) || defined(SOFM_EXPONENTIAL_HIFI4) || \ + defined(SOFM_EXPONENTIAL_HIFI5) + +#if XCHAL_HAVE_HIFI5 +#include <xtensa/tie/xt_hifi5.h> +#elif XCHAL_HAVE_HIFI4 +#include <xtensa/tie/xt_hifi4.h> +#else +#include <xtensa/tie/xt_hifi3.h> +#endif + +#define SOFM_EXP_ONE_OVER_LOG2_Q30 1549082005 /* Q2.30 int32(round(1/log(2) * 2^30)) */ +#define SOFM_EXP_LOG2_Q31 1488522236 /* Q1.31 int32(round(log(2) * 2^31)) */ +#define SOFM_EXP_FIXED_INPUT_MINUS8 -1073741824 /* Q5.27 int32(-8 * 2^27) */ +#define SOFM_EXP_FIXED_INPUT_PLUS8 1073741823 /* Q5.27 int32(8 * 2^27) */ +#define SOFM_EXP_LOG10_DIV20_Q27 15452387 /* Q5.27 int32(round(log(10)/20*2^27)) */ + +/* The table contains exponents of value v, where values of v + * are the 3 bit 2's complement signed values presented by bits + * of index 0..7. + * + * v = [(0:3)/8 (-4:-1)/8]; + * uint32(round(exp(v) * 2^31)) + */ +static const uint32_t sofm_exp_3bit_lookup[8] = { + 2147483648, 2433417774, 2757423586, 3124570271, + 1302514674, 1475942488, 1672461947, 1895147668 +}; + +/* Taylor polynomial coefficients for x^3..x^6, calculated + * uint32(round(1 ./ factorial(3:6) * 2^32)) + */ +static const uint32_t sofm_exp_taylor_coeffs[4] = { + 715827883, 178956971, 35791394, 5965232 +}; + +/* function f(x) = e^x + * + * Arguments : int32_t x (Q4.28) + * input range -8 to 8 + * + * Return Type : int32_t (Q13.19) + * output range 3.3546e-04 to 2981.0 + */ +int32_t sofm_exp_approx(int32_t x) +{ + ae_int64 p; + uint32_t taylor_first_2; + uint32_t taylor_extra; + uint32_t b_f32; + uint32_t b_pow; + uint32_t exp_a; + uint32_t exp_b; + uint32_t term; + uint32_t b; + int32_t x_times_one_over_log2; + int32_t e_times_log2; + int32_t x_32bit; + int32_t y_32bit; + int32_t e; + int32_t r; + int a; + + //x = 843314857; + + /* ------------------------------------------------------------------------- + * FIRST RANGE REDUCTION --------------------------------------------------- + * ------------------------------------------------------------------------- + * Multiply gives q28 * q30 -> q58, without shift the rounded value + * would be q42 (58 - 16). For q26 result, shift right by 16 (42 - 26). + */ + p = AE_MUL32_LL(x, SOFM_EXP_ONE_OVER_LOG2_Q30); + x_times_one_over_log2 = (ae_int32)AE_ROUND32F48SASYM(AE_SRAI64(p, 16)); + + /* Shift, round to q0 */ + e = AE_SRAI32R(x_times_one_over_log2, 26); + + + /* Q6.31, but we only keep the bottom 31 bits */ + e_times_log2 = (uint32_t)e * SOFM_EXP_LOG2_Q31; + + /* ------------------------------------------------------------------------- + * SECOND RANGE REDUCTION -------------------------------------------------- + * y = a + b + * ------------------------------------------------------------------------- + */ + x_32bit = AE_SLAI32(x, 3); /* S4.31, overflow to S1.31 */ + y_32bit = x_32bit - e_times_log2; /* S0.31, in ~[-0.34, +0.34] */ + a = (y_32bit >> 28) & 7; /* just the 3 top bits of "y" */ + b = y_32bit & 0x0FFFFFFF; /* bottom 31-3 = 28 bits. format U-3.31 */ + exp_a = sofm_exp_3bit_lookup[a]; + b_f32 = (b << 1) | 0x4; /* U0.32, align b on 32-bits of fraction */ + + /* Taylor approximation : base part + iterations + * Base part : 1 + b + b^2/2! + * Iterative part : b^3/3! + b^4/4! + b^5/5! + b^6/6! + * : Term count determined dynamically using e. + * + * Base part: NOTE: delay adding the "1" in "1 + b + b^2/2" until after we + * add the iterative part in. This gives us one more guard bit. + * NOTE: u_int32 x u_int32 => {hi, lo}. We only need {hi} for b_pow. + */ + b_pow = (uint64_t)b_f32 * b_f32 >> 32; + taylor_first_2 = b_f32 + (b_pow >> 1); /* 0.32 */ + taylor_extra = 0; + term = 1; + if (e < -10) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[0] >> 32; + taylor_extra += term; + if (e < -5) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[1] >> 32; + taylor_extra += term; + if (e < 0) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[2] >> 32; + taylor_extra += term; + if (e < 6) + goto ITER_END; + + b_pow = (uint64_t)b_f32 * b_pow >> 32; + term = (uint64_t)b_pow * sofm_exp_taylor_coeffs[3] >> 32; + taylor_extra += term; + +ITER_END: + + /* Implement rounding to 31 fractional bits.. */ + taylor_first_2 = taylor_first_2 + taylor_extra + 1; + + /* Add the missing "1" for the Taylor series "1+b+b^2/2+...." */ + exp_b = ((uint32_t)1 << 31) + (taylor_first_2 >> 1); /* U1.31 */ + + /* ------------------------------------------------------------------------- + * FIRST RECONSTRUCTION ---------------------------------------------------- + * ------------------------------------------------------------------------- + */ + + /* U1.31 * U1.31 = U2.62 */ + p = (ae_int64)((uint64_t)exp_a * exp_b); + + /* ------------------------------------------------------------------------- + * SECOND RECONSTRUCTION --------------------------------------------------- + * ------------------------------------------------------------------------- + */ + + /* Rounding to nearest, + * using f48 round with shift value for right shift is negative + * q62 to q31 shift right is -31, for round instruction shift left is +16, + * compensate shift e by right shift is -12: 16 - 31 - 12 = -27 + */ + p = AE_SLAA64(p, e - 27); + r = (ae_int32)AE_ROUND32F48SASYM(p); + return r; +} + +/* Fixed point exponent function for approximate range -16 .. 7.6246. + * + * The functions uses rule exp(x) = exp(x/2) * exp(x/2) to reduce + * the input argument for function sofm_exp_approx() with input + * range from -8 to +8. + * + * Input is Q5.27, -16.0 .. +16.0, but note the input range limitation + * Output is Q12.20, 0.0 .. +2048.0 + */ +int32_t sofm_exp_fixed(int32_t x) +{ + ae_int32 x0, y0, y1; + + if (x > SOFM_EXP_FIXED_INPUT_MAX) + return INT32_MAX; + + /* No need to check for > 8, the input max is lower, about 7.6 */ + if (x < SOFM_EXP_FIXED_INPUT_MINUS8) { + /* Divide by 2, convert Q27 to Q28 is x as such */ + y0 = sofm_exp_approx(x); + /* Multiply gives q19 * q19 -> q38, without shift the rounded value + * would be q22 (38 - 16). For q20 shift right by 2. + */ + y1 = (ae_int32)AE_ROUND32F48SASYM(AE_SRAI64(AE_MUL32_LL(y0, y0), 2)); + return y1; + } + + x0 = AE_SLAI32S(x, 1); + y0 = sofm_exp_approx((int32_t)x0); + return (ae_int32)AE_SLAI32S(y0, 1); +} +EXPORT_SYMBOL(sofm_exp_fixed); + +/* Decibels to linear conversion: The function uses exp() to calculate + * the linear value. The argument is multiplied by log(10)/20 to + * calculate equivalent of 10^(db/20). + * + * The error in conversion is less than 0.1 dB for -89..+66 dB range. Do not + * use the code for argument less than -100 dB. The code simply returns zero + * as linear value for such very small value. + * + * Input is Q8.24 (max 128.0) + * output is Q12.20 (max 2048.0) + */ + +int32_t sofm_db2lin_fixed(int32_t db) +{ + ae_int64 p; + ae_int32 arg; + + if (db > SOFM_DB2LIN_INPUT_MAX) + return INT32_MAX; + + /* Multiply gives Q8.24 * Q5.27 -> Q13.51 */ + p = AE_MUL32_LL(db, SOFM_EXP_LOG10_DIV20_Q27); + + /* Without shift the f48 rounded value would be Q35 (51 - 16). + * For Q5.27 result, shift right by 8 (35 - 27). + */ + arg = AE_ROUND32F48SASYM(AE_SRAI64(p, 8)); + return sofm_exp_fixed((int32_t)arg); +} +EXPORT_SYMBOL(sofm_db2lin_fixed); + +#endif diff --git a/src/math/fft/CMakeLists.txt b/src/math/fft/CMakeLists.txt new file mode 100644 index 000000000000..c605886c335e --- /dev/null +++ b/src/math/fft/CMakeLists.txt @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-3-Clause + +set(base_files fft_common.c) + +if(CONFIG_MATH_16BIT_FFT) + list(APPEND base_files fft_16.c fft_16_hifi3.c) +endif() + +if(CONFIG_MATH_32BIT_FFT) + list(APPEND base_files fft_32.c fft_32_hifi3.c) +endif() + +if(CONFIG_MATH_FFT_MULTI) + list(APPEND base_files fft_multi.c fft_multi_generic.c fft_multi_hifi3.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + + zephyr_library_sources( + ${base_files} + ) + +else() ### library, e.g. testbench or plugin ### + + add_local_sources(sof ${base_files}) + +endif() diff --git a/src/math/fft/fft_16.c b/src/math/fft/fft_16.c new file mode 100644 index 000000000000..7a8ffad26054 --- /dev/null +++ b/src/math/fft/fft_16.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020-2026 Intel Corporation. +// +// Author: Amery Song <chao.song@intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/fft.h> +#include <sof/math/icomplex16.h> +#include <sof/common.h> +#include <stdint.h> + +#ifdef FFT_GENERIC +#include <sof/audio/coefficients/fft/twiddle_16.h> + +/** + * \brief Execute the 16-bits Fast Fourier Transform (FFT) or Inverse FFT (IFFT) + * For the configured fft_pan. + * \param[in] plan - pointer to fft_plan which will be executed. + * \param[in] ifft - set to 1 for IFFT and 0 for FFT. + */ +void fft_execute_16(struct fft_plan *plan, bool ifft) +{ + struct icomplex16 tmp1; + struct icomplex16 tmp2; + struct icomplex16 *inb; + struct icomplex16 *outb; + int depth; + int top; + int bottom; + int index; + int i; + int j; + int k; + int m; + int n; + + if (!plan || !plan->bit_reverse_idx) + return; + + inb = plan->inb16; + outb = plan->outb16; + if (!inb || !outb) + return; + + /* convert to complex conjugate for ifft */ + if (ifft) { + for (i = 0; i < plan->size; i++) + icomplex16_conj(&inb[i]); + } + + /* step 1: re-arrange input in bit reverse order, and shrink the level to avoid overflow */ + for (i = 1; i < plan->size; ++i) + icomplex16_shift(&inb[i], -(plan->len), &outb[plan->bit_reverse_idx[i]]); + + /* step 2: loop to do FFT transform in smaller size */ + for (depth = 1; depth <= plan->len; ++depth) { + m = 1 << depth; + n = m >> 1; + i = FFT_SIZE_MAX >> depth; + + /* doing FFT transforms in size m */ + for (k = 0; k < plan->size; k += m) { + /* doing one FFT transform for size m */ + for (j = 0; j < n; ++j) { + index = i * j; + top = k + j; + bottom = top + n; + tmp1.real = twiddle_real_16[index]; + tmp1.imag = twiddle_imag_16[index]; + /* calculate the accumulator: twiddle * bottom */ + icomplex16_mul(&tmp1, &outb[bottom], &tmp2); + tmp1 = outb[top]; + /* calculate the top output: top = top + accumulate */ + icomplex16_add(&tmp1, &tmp2, &outb[top]); + /* calculate the bottom output: bottom = top - accumulate */ + icomplex16_sub(&tmp1, &tmp2, &outb[bottom]); + } + } + } + + /* shift back for ifft */ + if (ifft) { + /* + * no need to divide N as it is already done in the input side + * for Q1.31 format. Instead, we need to multiply N to compensate + * the shrink we did in the FFT transform. + */ + for (i = 0; i < plan->size; i++) + icomplex16_shift(&outb[i], plan->len, &outb[i]); + } +} +#endif diff --git a/src/math/fft/fft_16_hifi3.c b/src/math/fft/fft_16_hifi3.c new file mode 100644 index 000000000000..56d5bc177789 --- /dev/null +++ b/src/math/fft/fft_16_hifi3.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <sof/audio/format.h> +#include <sof/common.h> +#include <sof/math/fft.h> +#include <sof/math/icomplex16.h> + + +#ifdef FFT_HIFI3 +#include <sof/audio/coefficients/fft/twiddle_16.h> +#include <xtensa/tie/xt_hifi3.h> + +/** + * \brief Execute the 16-bits Fast Fourier Transform (FFT) or Inverse FFT (IFFT) + * For the configured fft_pan. + * \param[in] plan - pointer to fft_plan which will be executed. + * \param[in] ifft - set to 1 for IFFT and 0 for FFT. + */ +void fft_execute_16(struct fft_plan *plan, bool ifft) +{ + struct icomplex16 *outb; + ae_int16 *in; + ae_int16x4 sample; + ae_int32x2 res1, res2, res; + ae_p16x2s *outs16; + ae_int24x2 temp1, temp2; + ae_int16 *out; + ae_int16x4 *in16x4; + ae_int16x4 *out16x4; + ae_valign inu = AE_ZALIGN64(); + ae_valign outu = AE_ZALIGN64(); + int depth, top, bottom, index; + int i, j, k, m, n; + int size, len; + + if (!plan || !plan->bit_reverse_idx) + return; + + size = plan->size; + len = plan->len; + + outb = plan->outb16; + if (!plan->inb16 || !outb) + return; + + /* convert to complex conjugate for ifft */ + if (ifft) { + in = (ae_int16 *)&plan->inb16->imag; + for (i = 0; i < size; i++) { + AE_L16_IP(sample, in, 0); + sample = AE_NEG16S(sample); + AE_S16_0_IP(sample, in, sizeof(struct icomplex16)); + } + } + + /* step 1: re-arrange input in bit reverse order, and shrink the level to avoid overflow */ + in = (ae_int16 *)&plan->inb16[1]; + for (i = 1; i < size ; ++i) { + out = (ae_int16 *)&outb[plan->bit_reverse_idx[i]]; + AE_L16_IP(sample, in, 2); + sample = AE_SRAA16RS(sample, len); + AE_S16_0_IP(sample, out, 2); + + AE_L16_IP(sample, in, 2); + sample = AE_SRAA16RS(sample, len); + AE_S16_0_IP(sample, out, 2); + } + + /* step 2: loop to do FFT transform in smaller size */ + for (depth = 1; depth <= plan->len; ++depth) { + m = 1 << depth; + n = m >> 1; + i = FFT_SIZE_MAX >> depth; + + /* doing FFT transforms in size m */ + for (k = 0; k < plan->size; k += m) { + /* doing one FFT transform for size m */ + for (j = 0; j < n; ++j) { + index = i * j; + top = k + j; + bottom = top + n; + /* store twiddle and bottom as Q9.23*/ + temp1 = AE_CVTP24A16X2_LL(outb[bottom].real, outb[bottom].imag); + temp2 = AE_CVTP24A16X2_LL(twiddle_real_16[index], + twiddle_imag_16[index]); + /* calculate the accumulator: twiddle * bottom */ + res = AE_MULFC24RA(temp1, temp2); + /* saturate and round the result to 16bit and put it in + * the middle element of res. + */ + res2 = AE_SRAI32R(res, 8); + res2 = AE_SLAI32S(res2, 8); + /* store top format Q9.23*/ + res1 = AE_CVTP24A16X2_LL(outb[top].real, outb[top].imag); + /* calculate the top output: top = top + accumulate */ + res = AE_ADD24S(res1, res2); + outs16 = (ae_p16x2s *)&outb[top]; + /* store the middle 16bit into outb[top]*/ + AE_S16X2M_I(res, outs16, 0); + /* calculate the bottom output: bottom = top - accumulate */ + outs16 = (ae_p16x2s *)&outb[bottom]; + res = AE_SUB24S(res1, res2); + AE_S16X2M_I(res, outs16, 0); + } + } + } + + /* shift back for ifft */ + if (ifft) { + /* + * no need to divide N as it is already done in the input side + * for Q1.31 format. Instead, we need to multiply N to compensate + * the shrink we did in the FFT transform. + */ + in16x4 = (ae_int16x4 *)plan->outb16; + out16x4 = (ae_int16x4 *)plan->outb16; + n = size >> 1; + inu = AE_LA64_PP(in16x4); + /* shift 2 samples per loop */ + for (i = 0; i < n; i++) { + AE_LA16X4_IP(sample, inu, in16x4); + sample = AE_SLAA16S(sample, len); + AE_SA16X4_IP(sample, outu, out16x4); + } + AE_SA64POS_FP(outu, out16x4); + /* if size is odd, shift the real & imag part respectively */ + if (size & 1) { + in = (ae_int16 *)in16x4; + out = (ae_int16 *)out16x4; + AE_L16_IP(sample, in, 2); + sample = AE_SLAA16S(sample, len); + AE_S16_0_IP(sample, out, 2); + AE_L16_IP(sample, in, 2); + sample = AE_SLAA16S(sample, len); + AE_S16_0_IP(sample, out, 2); + } + } +} +#endif diff --git a/src/math/fft/fft_32.c b/src/math/fft/fft_32.c new file mode 100644 index 000000000000..a6f8b2aa1ab3 --- /dev/null +++ b/src/math/fft/fft_32.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Amery Song <chao.song@intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/fft.h> +#include <sof/math/icomplex32.h> +#include <sof/common.h> +#include <stdint.h> + +#ifdef FFT_GENERIC +#include <sof/audio/coefficients/fft/twiddle_32.h> + +/** + * \brief Execute the 32-bits Fast Fourier Transform (FFT) or Inverse FFT (IFFT) + * For the configured fft_pan. + * \param[in] plan - pointer to fft_plan which will be executed. + * \param[in] ifft - set to 1 for IFFT and 0 for FFT. + */ +void fft_execute_32(struct fft_plan *plan, bool ifft) +{ + struct icomplex32 tmp1; + struct icomplex32 tmp2; + struct icomplex32 *inb; + struct icomplex32 *outb; + int depth; + int top; + int bottom; + int index; + int i; + int j; + int k; + int m; + int n; + + if (!plan || !plan->bit_reverse_idx) + return; + + inb = plan->inb32; + outb = plan->outb32; + if (!inb || !outb) + return; + + /* convert to complex conjugate for ifft */ + if (ifft) { + for (i = 0; i < plan->size; i++) + icomplex32_conj(&inb[i]); + } + + /* step 1: re-arrange input in bit reverse order, and shrink the level to avoid overflow */ + for (i = 0; i < plan->size; ++i) + icomplex32_shift(&inb[i], -(plan->len), &outb[plan->bit_reverse_idx[i]]); + + /* step 2: loop to do FFT transform in smaller size */ + for (depth = 1; depth <= plan->len; ++depth) { + m = 1 << depth; + n = m >> 1; + i = FFT_SIZE_MAX >> depth; + + /* doing FFT transforms in size m */ + for (k = 0; k < plan->size; k += m) { + /* doing one FFT transform for size m */ + for (j = 0; j < n; ++j) { + index = i * j; + top = k + j; + bottom = top + n; + tmp1.real = twiddle_real_32[index]; + tmp1.imag = twiddle_imag_32[index]; + /* calculate the accumulator: twiddle * bottom */ + icomplex32_mul(&tmp1, &outb[bottom], &tmp2); + tmp1 = outb[top]; + /* calculate the top output: top = top + accumulate */ + icomplex32_add(&tmp1, &tmp2, &outb[top]); + /* calculate the bottom output: bottom = top - accumulate */ + icomplex32_sub(&tmp1, &tmp2, &outb[bottom]); + } + } + } + + /* shift back for ifft */ + if (ifft) { + /* + * no need to divide N as it is already done in the input side + * for Q1.31 format. Instead, we need to multiply N to compensate + * the shrink we did in the FFT transform. + */ + for (i = 0; i < plan->size; i++) { + icomplex32_conj(&outb[i]); + icomplex32_shift(&outb[i], plan->len, &outb[i]); + } + } +} + +#endif /* FFT_GENERIC */ diff --git a/src/math/fft/fft_32_hifi3.c b/src/math/fft/fft_32_hifi3.c new file mode 100644 index 000000000000..1d00dacd1b7f --- /dev/null +++ b/src/math/fft/fft_32_hifi3.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <sof/audio/format.h> +#include <sof/common.h> +#include <rtos/alloc.h> +#include <sof/math/fft.h> + +#ifdef FFT_HIFI3 +#include <sof/audio/coefficients/fft/twiddle_32.h> +#include <xtensa/tie/xt_hifi3.h> + +void fft_execute_32(struct fft_plan *plan, bool ifft) +{ + ae_int64 res, res1; + ae_int32x2 sample; + ae_int32x2 sample1; + ae_int32x2 sample2; + ae_int32x2 tw; + ae_int32x2 *inx; + ae_int32x2 *outx; + ae_int32x2 *top_ptr; + ae_int32x2 *bot_ptr; + uint16_t *idx; + const int32_t *tw_r; + const int32_t *tw_i; + int depth, i; + int j, k, m, n; + int size, len; + + if (!plan || !plan->bit_reverse_idx) + return; + + if (!plan->inb32 || !plan->outb32) + return; + + inx = (ae_int32x2 *)plan->inb32; + outx = (ae_int32x2 *)plan->outb32; + idx = &plan->bit_reverse_idx[0]; + size = plan->size; + len = plan->len; + + /* step 1: re-arrange input in bit reverse order, and shrink the level to avoid overflow */ + if (ifft) { + /* convert to complex conjugate for ifft */ + for (i = 0; i < size; ++i) { + AE_L32X2_IP(sample, inx, sizeof(ae_int32x2)); + sample = AE_SRAA32S(sample, len); + sample1 = AE_NEG32S(sample); + sample = AE_SEL32_HL(sample, sample1); + AE_S32X2_X(sample, outx, idx[i] * sizeof(ae_int32x2)); + } + } else { + for (i = 0; i < size; ++i) { + AE_L32X2_IP(sample, inx, sizeof(ae_int32x2)); + sample = AE_SRAA32S(sample, len); + AE_S32X2_X(sample, outx, idx[i] * sizeof(ae_int32x2)); + } + } + + /* + * Step 2a: First FFT stage (depth=1, m=2, n=1). + * All butterflies use twiddle factor W^0 = 1+0j, + * so the complex multiply is skipped entirely. + */ + top_ptr = outx; + bot_ptr = outx + 1; + for (k = 0; k < size; k += 2) { + sample1 = AE_L32X2_I(top_ptr, 0); + sample2 = AE_L32X2_I(bot_ptr, 0); + sample = AE_ADD32S(sample1, sample2); + AE_S32X2_I(sample, top_ptr, 0); + sample = AE_SUB32S(sample1, sample2); + AE_S32X2_I(sample, bot_ptr, 0); + top_ptr += 2; + bot_ptr += 2; + } + + /* Step 2b: Remaining FFT stages (depth >= 2) */ + for (depth = 2; depth <= len; ++depth) { + m = 1 << depth; + n = m >> 1; + i = FFT_SIZE_MAX >> depth; + + top_ptr = outx; + bot_ptr = outx + n; + + /* doing FFT transforms in size m */ + for (k = 0; k < size; k += m) { + /* + * j=0: twiddle factor W^0 = 1+0j, + * butterfly without complex multiply. + */ + sample1 = AE_L32X2_I(top_ptr, 0); + sample = AE_L32X2_I(bot_ptr, 0); + sample2 = AE_ADD32S(sample1, sample); + AE_S32X2_I(sample2, top_ptr, 0); + sample2 = AE_SUB32S(sample1, sample); + AE_S32X2_I(sample2, bot_ptr, 0); + top_ptr++; + bot_ptr++; + + /* j=1..n-1: full butterfly with twiddle multiply */ + tw_r = &twiddle_real_32[i]; + tw_i = &twiddle_imag_32[i]; + for (j = 1; j < n; ++j) { + /* load and combine twiddle factor {real, imag} into tw */ + tw = AE_MOVDA32X2(tw_r[0], tw_i[0]); + + /* calculate the accumulator: twiddle * bottom */ + sample2 = AE_L32X2_I(bot_ptr, 0); + res = AE_MULF32S_HH(tw, sample2); + AE_MULSF32S_LL(res, tw, sample2); + res1 = AE_MULF32S_HL(tw, sample2); + AE_MULAF32S_LH(res1, tw, sample2); + sample = AE_ROUND32X2F64SSYM(res, res1); + sample1 = AE_L32X2_I(top_ptr, 0); + + /* calculate the top output: top = top + accumulate */ + sample2 = AE_ADD32S(sample1, sample); + AE_S32X2_I(sample2, top_ptr, 0); + + /* calculate the bottom output: bottom = top - accumulate */ + sample2 = AE_SUB32S(sample1, sample); + AE_S32X2_I(sample2, bot_ptr, 0); + + top_ptr++; + bot_ptr++; + tw_r += i; + tw_i += i; + } + /* advance pointers past current group's bottom half */ + top_ptr += n; + bot_ptr += n; + } + } + + /* shift back for ifft */ + if (ifft) { + /* + * no need to divide N as it is already done in the input side + * for Q1.31 format. Instead, we need to multiply N to compensate + * the shrink we did in the FFT transform. Also make complex + * conjugate by negating the imaginary part. + */ + inx = outx; + for (i = 0; i < size; ++i) { + AE_L32X2_IP(sample, inx, sizeof(ae_int32x2)); + sample = AE_SLAA32S(sample, len); + sample1 = AE_NEG32S(sample); + sample = AE_SEL32_HL(sample, sample1); + AE_S32X2_IP(sample, outx, sizeof(ae_int32x2)); + } + } +} +#endif diff --git a/src/math/fft/fft_common.c b/src/math/fft/fft_common.c new file mode 100644 index 000000000000..5ce47acd025a --- /dev/null +++ b/src/math/fft/fft_common.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020-2025 Intel Corporation. +// +// Author: Amery Song <chao.song@intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/trace/trace.h> +#include <sof/lib/uuid.h> +#include <sof/common.h> +#include <rtos/alloc.h> +#include <sof/math/fft.h> +#include "fft_common.h" + +LOG_MODULE_REGISTER(math_fft, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(math_fft); +DECLARE_TR_CTX(math_fft_tr, SOF_UUID(math_fft_uuid), LOG_LEVEL_INFO); + +struct fft_plan *fft_plan_common_new(struct processing_module *mod, void *inb, + void *outb, uint32_t size, int bits) +{ + struct fft_plan *plan; + int lim = 1; + int len = 0; + + if (!inb || !outb) { + comp_cl_err(mod->dev, "NULL input/output buffers."); + return NULL; + } + + if (!is_power_of_2(size)) { + comp_cl_err(mod->dev, "The FFT size must be a power of two."); + return NULL; + } + + plan = mod_zalloc(mod, sizeof(struct fft_plan)); + if (!plan) { + comp_cl_err(mod->dev, "Failed to allocate FFT plan."); + return NULL; + } + + switch (bits) { + case 16: + plan->inb16 = inb; + plan->outb16 = outb; + break; + case 32: + plan->inb32 = inb; + plan->outb32 = outb; + break; + default: + comp_cl_err(mod->dev, "Invalid word length."); + return NULL; + } + + /* calculate the exponent of 2 */ + while (lim < size) { + lim <<= 1; + len++; + } + + plan->size = lim; + plan->len = len; + return plan; +} + +void fft_plan_init_bit_reverse(uint16_t *bit_reverse_idx, int size, int len) +{ + int i; + + /* Set up the bit reverse index. The array will contain the value of + * the index with the bits order reversed. Index can be skipped. + */ + for (i = 1; i < size; ++i) + bit_reverse_idx[i] = (bit_reverse_idx[i >> 1] >> 1) | ((i & 1) << (len - 1)); +} + +struct fft_plan *mod_fft_plan_new(struct processing_module *mod, void *inb, + void *outb, uint32_t size, int bits) +{ + struct fft_plan *plan; + + if (size > FFT_SIZE_MAX || size < FFT_SIZE_MIN) { + comp_cl_err(mod->dev, "Invalid FFT size %d", size); + return NULL; + } + + plan = fft_plan_common_new(mod, inb, outb, size, bits); + if (!plan) + return NULL; + + plan->bit_reverse_idx = mod_zalloc(mod, plan->size * sizeof(uint16_t)); + if (!plan->bit_reverse_idx) { + comp_cl_err(mod->dev, "Failed to allocate bit reverse table."); + mod_free(mod, plan); + return NULL; + } + + fft_plan_init_bit_reverse(plan->bit_reverse_idx, plan->size, plan->len); + return plan; +} + +void mod_fft_plan_free(struct processing_module *mod, struct fft_plan *plan) +{ + if (!plan) + return; + + mod_free(mod, plan->bit_reverse_idx); + mod_free(mod, plan); +} diff --git a/src/math/fft/fft_common.h b/src/math/fft/fft_common.h new file mode 100644 index 000000000000..9ea9998073ca --- /dev/null +++ b/src/math/fft/fft_common.h @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +/** + * fft_plan_common_new() - Common FFT prepare function + * @param mod: Pointer to module + * @param inb: Buffer to use for complex input data + * @param outb: Buffer to use for complex output data + * @param size: Size of FFT as number of bins + * @param bits: World length of FFT. Currently only 32 is supported. + * @return Pointer to FFT plan + */ +struct fft_plan *fft_plan_common_new(struct processing_module *mod, void *inb, + void *outb, uint32_t size, int bits); + +/** + * fft_plan_init_bit_reverse - Configures a bit reversal lookup vector + * @param bit_reverse_idx: Pointer to array to store bit reverse lookup + * @param size: Size of FFT + * @param len: Power of two value equals FFT size + */ +void fft_plan_init_bit_reverse(uint16_t *bit_reverse_idx, int size, int len); diff --git a/src/math/fft/fft_multi.c b/src/math/fft/fft_multi.c new file mode 100644 index 000000000000..b16decca012d --- /dev/null +++ b/src/math/fft/fft_multi.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/coefficients/fft/twiddle_3072_32.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/format.h> +#include <sof/math/icomplex32.h> +#include <sof/trace/trace.h> +#include <sof/lib/uuid.h> +#include <sof/common.h> +#include <rtos/alloc.h> +#include <sof/math/fft.h> +#include "fft_common.h" + +LOG_MODULE_REGISTER(math_fft_multi, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(math_fft_multi); +DECLARE_TR_CTX(math_fft_multi_tr, SOF_UUID(math_fft_multi_uuid), LOG_LEVEL_INFO); + +struct fft_multi_plan *mod_fft_multi_plan_new(struct processing_module *mod, void *inb, + void *outb, uint32_t size, int bits) +{ + struct fft_multi_plan *plan; + size_t tmp_size; + const int size_div3 = size / 3; + int i; + + if (!inb || !outb) { + comp_cl_err(mod->dev, "Null buffers"); + return NULL; + } + + if (size < FFT_SIZE_MIN) { + comp_cl_err(mod->dev, "Invalid FFT size %d", size); + return NULL; + } + + plan = mod_zalloc(mod, sizeof(struct fft_multi_plan)); + if (!plan) + return NULL; + + if (is_power_of_2(size)) { + plan->num_ffts = 1; + } else if (size_div3 * 3 == size) { + plan->num_ffts = 3; + } else { + comp_cl_err(mod->dev, "Not supported FFT size %d", size); + goto err; + } + + /* Allocate common bit reverse table for all FFT plans */ + plan->total_size = size; + plan->fft_size = size / plan->num_ffts; + if (plan->fft_size > FFT_SIZE_MAX) { + comp_cl_err(mod->dev, "Requested size %d FFT is too large", size); + goto err; + } + + plan->bit_reverse_idx = mod_zalloc(mod, plan->fft_size * sizeof(uint16_t)); + if (!plan->bit_reverse_idx) { + comp_cl_err(mod->dev, "Failed to allocate FFT plan"); + goto err; + } + + switch (bits) { + case 32: + plan->inb32 = inb; + plan->outb32 = outb; + + if (plan->num_ffts > 1) { + /* Allocate input/output buffers for FFTs */ + tmp_size = 2 * plan->num_ffts * plan->fft_size * sizeof(struct icomplex32); + plan->tmp_i32[0] = mod_balloc(mod, tmp_size); + if (!plan->tmp_i32[0]) { + comp_cl_err(mod->dev, "Failed to allocate FFT buffers"); + goto err_free_bit_reverse; + } + + /* Set up buffers */ + plan->tmp_o32[0] = plan->tmp_i32[0] + plan->fft_size; + for (i = 1; i < plan->num_ffts; i++) { + plan->tmp_i32[i] = plan->tmp_o32[i - 1] + plan->fft_size; + plan->tmp_o32[i] = plan->tmp_i32[i] + plan->fft_size; + } + } else { + plan->tmp_i32[0] = inb; + plan->tmp_o32[0] = outb; + } + + for (i = 0; i < plan->num_ffts; i++) { + plan->fft_plan[i] = fft_plan_common_new(mod, + plan->tmp_i32[i], + plan->tmp_o32[i], + plan->fft_size, 32); + if (!plan->fft_plan[i]) + goto err_free_buffer; + + plan->fft_plan[i]->bit_reverse_idx = plan->bit_reverse_idx; + } + break; + default: + comp_cl_err(mod->dev, "Not supported word length %d", bits); + goto err; + } + + /* Set up common bit index reverse table */ + fft_plan_init_bit_reverse(plan->bit_reverse_idx, plan->fft_plan[0]->size, + plan->fft_plan[0]->len); + return plan; + +err_free_buffer: + mod_free(mod, plan->tmp_i32[0]); + +err_free_bit_reverse: + mod_free(mod, plan->bit_reverse_idx); + +err: + mod_free(mod, plan); + return NULL; +} + +void mod_fft_multi_plan_free(struct processing_module *mod, struct fft_multi_plan *plan) +{ + int i; + + if (!plan) + return; + + for (i = 0; i < plan->num_ffts; i++) + mod_free(mod, plan->fft_plan[i]); + + /* If single FFT, the internal buffers were not allocated. */ + if (plan->num_ffts > 1) + mod_free(mod, plan->tmp_i32[0]); + + mod_free(mod, plan->bit_reverse_idx); + mod_free(mod, plan); +} diff --git a/src/math/fft/fft_multi_generic.c b/src/math/fft/fft_multi_generic.c new file mode 100644 index 000000000000..52ec1e8172c0 --- /dev/null +++ b/src/math/fft/fft_multi_generic.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025-2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/icomplex32.h> +#include <sof/common.h> +#include <sof/math/fft.h> +#include <string.h> + +#ifdef DEBUG_DUMP_TO_FILE +#include <stdio.h> +#endif + +/* Twiddle factor tables defined in fft_multi.c via twiddle_3072_32.h */ +#define FFT_MULTI_TWIDDLE_SIZE 2048 +extern const int32_t multi_twiddle_real_32[]; +extern const int32_t multi_twiddle_imag_32[]; + +/* Constants for size 3 DFT */ +#define DFT3_COEFR -1073741824 /* int32(-0.5 * 2^31) */ +#define DFT3_COEFI 1859775393 /* int32(sqrt(3) / 2 * 2^31) */ +#define DFT3_SCALE 715827883 /* int32(1/3*2^31) */ + +#ifdef FFT_GENERIC + +void dft3_32(struct icomplex32 *x_in, struct icomplex32 *y) +{ + const struct icomplex32 c0 = {DFT3_COEFR, -DFT3_COEFI}; + const struct icomplex32 c1 = {DFT3_COEFR, DFT3_COEFI}; + struct icomplex32 x[3]; + struct icomplex32 p1, p2, sum; + int i; + + for (i = 0; i < 3; i++) { + x[i].real = Q_MULTSR_32X32((int64_t)x_in[i].real, DFT3_SCALE, 31, 31, 31); + x[i].imag = Q_MULTSR_32X32((int64_t)x_in[i].imag, DFT3_SCALE, 31, 31, 31); + } + + /* + * | 1 1 1 | + * c = | 1 c0 c1 | , x = [ x0 x1 x2 ] + * | 1 c1 c0 | + * + * y(0) = c(0,0) * x(0) + c(1,0) * x(1) + c(2,0) * x(2) + * y(1) = c(0,1) * x(0) + c(1,1) * x(1) + c(2,1) * x(2) + * y(2) = c(0,2) * x(0) + c(1,2) * x(1) + c(2,2) * x(2) + */ + + /* y(0) = 1 * x(0) + 1 * x(1) + 1 * x(2) */ + icomplex32_adds(&x[0], &x[1], &sum); + icomplex32_adds(&x[2], &sum, &y[0]); + + /* y(1) = 1 * x(0) + c0 * x(1) + c1 * x(2) */ + icomplex32_mul(&c0, &x[1], &p1); + icomplex32_mul(&c1, &x[2], &p2); + icomplex32_adds(&p1, &p2, &sum); + icomplex32_adds(&x[0], &sum, &y[1]); + + /* y(2) = 1 * x(0) + c1 * x(1) + c0 * x(2) */ + icomplex32_mul(&c1, &x[1], &p1); + icomplex32_mul(&c0, &x[2], &p2); + icomplex32_adds(&p1, &p2, &sum); + icomplex32_adds(&x[0], &sum, &y[2]); +} + +void fft_multi_execute_32(struct fft_multi_plan *plan, bool ifft) +{ + struct icomplex32 x[FFT_MULTI_COUNT_MAX]; + struct icomplex32 y[FFT_MULTI_COUNT_MAX]; + struct icomplex32 t, c; + int i, j, k, m; + + /* Handle 2^N FFT */ + if (plan->num_ffts == 1) { + memset(plan->outb32, 0, plan->fft_size * sizeof(struct icomplex32)); + fft_execute_32(plan->fft_plan[0], ifft); + return; + } + +#ifdef DEBUG_DUMP_TO_FILE + FILE *fh1 = fopen("debug_fft_multi_int1.txt", "w"); + FILE *fh2 = fopen("debug_fft_multi_int2.txt", "w"); + FILE *fh3 = fopen("debug_fft_multi_twiddle.txt", "w"); + FILE *fh4 = fopen("debug_fft_multi_dft_out.txt", "w"); +#endif + + /* convert to complex conjugate for IFFT */ + if (ifft) { + for (i = 0; i < plan->total_size; i++) + icomplex32_conj(&plan->inb32[i]); + } + + /* Copy input buffers */ + k = 0; + for (i = 0; i < plan->fft_size; i++) + for (j = 0; j < plan->num_ffts; j++) + plan->tmp_i32[j][i] = plan->inb32[k++]; + + /* Clear output buffers and call individual FFTs*/ + for (j = 0; j < plan->num_ffts; j++) { + memset(&plan->tmp_o32[j][0], 0, plan->fft_size * sizeof(struct icomplex32)); + fft_execute_32(plan->fft_plan[j], 0); + } + +#ifdef DEBUG_DUMP_TO_FILE + for (j = 0; j < plan->num_ffts; j++) + for (i = 0; i < plan->fft_size; i++) + fprintf(fh1, "%d %d\n", plan->tmp_o32[j][i].real, plan->tmp_o32[j][i].imag); +#endif + + /* Multiply with twiddle factors */ + m = FFT_MULTI_TWIDDLE_SIZE / 2 / plan->fft_size; + for (j = 1; j < plan->num_ffts; j++) { + for (i = 0; i < plan->fft_size; i++) { + c = plan->tmp_o32[j][i]; + k = j * i * m; + t.real = multi_twiddle_real_32[k]; + t.imag = multi_twiddle_imag_32[k]; + // fprintf(fh3, "%d %d\n", t.real, t.imag); + icomplex32_mul(&t, &c, &plan->tmp_o32[j][i]); + } + } + +#ifdef DEBUG_DUMP_TO_FILE + for (j = 0; j < plan->num_ffts; j++) + for (i = 0; i < plan->fft_size; i++) + fprintf(fh2, "%d %d\n", plan->tmp_o32[j][i].real, plan->tmp_o32[j][i].imag); +#endif + + /* DFT of size 3 */ + j = plan->fft_size; + k = 2 * plan->fft_size; + for (i = 0; i < plan->fft_size; i++) { + x[0] = plan->tmp_o32[0][i]; + x[1] = plan->tmp_o32[1][i]; + x[2] = plan->tmp_o32[2][i]; + dft3_32(x, y); + plan->outb32[i] = y[0]; + plan->outb32[i + j] = y[1]; + plan->outb32[i + k] = y[2]; + } + +#ifdef DEBUG_DUMP_TO_FILE + for (i = 0; i < plan->total_size; i++) + fprintf(fh4, "%d %d\n", plan->outb32[i].real, plan->outb32[i].imag); +#endif + + /* shift back for IFFT */ + + /* TODO: Check if time shift method for IFFT is more efficient or more accurate + * tmp = 1 / N * fft(X); + * x = tmp([1 N:-1:2]) + */ + if (ifft) { + /* + * no need to divide N as it is already done in the input side + * for Q1.31 format. Instead, we need to multiply N to compensate + * the shrink we did in the FFT transform. + */ + for (i = 0; i < plan->total_size; i++) { + /* Need to negate imag part to match reference */ + plan->outb32[i].imag = -plan->outb32[i].imag; + icomplex32_shift(&plan->outb32[i], plan->fft_plan[0]->len, + &plan->outb32[i]); + plan->outb32[i].real = sat_int32((int64_t)plan->outb32[i].real * 3); + plan->outb32[i].imag = sat_int32((int64_t)plan->outb32[i].imag * 3); + } + } + +#ifdef DEBUG_DUMP_TO_FILE + fclose(fh1); + fclose(fh2); + fclose(fh3); + fclose(fh4); +#endif +} + +#endif /* FFT_GENERIC */ diff --git a/src/math/fft/fft_multi_hifi3.c b/src/math/fft/fft_multi_hifi3.c new file mode 100644 index 000000000000..8f0c25e65f8c --- /dev/null +++ b/src/math/fft/fft_multi_hifi3.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025-2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +/** + * @file fft_multi_hifi3.c + * @brief HiFi3 optimized multi-radix FFT functions. + * + * This file provides HiFi3 optimized implementations of dft3_32() and + * fft_multi_execute_32() using Xtensa HiFi3 intrinsics. These replace + * the generic versions when HiFi3 or HiFi4 hardware is available. + * + * Key optimizations over the generic versions: + * - Packed {real, imag} processing using ae_int32x2 registers + * - 64-bit MAC accumulation for fused complex multiply-add + * - Saturating 32-bit arithmetic via AE_ADD32S/AE_SLAA32S + * - Vectorized conjugate, shift, and scale in the IFFT path + */ + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/format.h> +#include <sof/math/icomplex32.h> +#include <sof/common.h> +#include <sof/math/fft.h> +#include <string.h> + +/* Twiddle factor tables defined in fft_multi.c via twiddle_3072_32.h */ +#define FFT_MULTI_TWIDDLE_SIZE 2048 +extern const int32_t multi_twiddle_real_32[]; +extern const int32_t multi_twiddle_imag_32[]; + +#ifdef FFT_HIFI3 + +#include <xtensa/tie/xt_hifi3.h> + +/** @brief Q1.31 constant -0.5 */ +#define DFT3_COEFR -1073741824 +/** @brief Q1.31 constant sqrt(3)/2 */ +#define DFT3_COEFI 1859775393 +/** @brief Q1.31 constant 1/3 */ +#define DFT3_SCALE 715827883 + +/** + * dft3_32() - Compute 3-point DFT of Q1.31 complex data (HiFi3). + * @param x_in Pointer to 3 input complex samples in Q1.31. + * @param y Pointer to 3 output complex samples in Q1.31. + * + * Computes the DFT matrix-vector product: + * + * | 1 1 1 | + * Y = | 1 c0 c1 | * X / 3 + * | 1 c1 c0 | + * + * where c0 = exp(-j*2*pi/3) and c1 = exp(+j*2*pi/3). + * Input is prescaled by 1/3 to prevent overflow. + * + * The two complex multiplies for each output bin are fused + * into a single 64-bit accumulator pair, avoiding intermediate + * rounding and saving instructions. + */ +void dft3_32(struct icomplex32 *x_in, struct icomplex32 *y) +{ + ae_int32x2 *p_in = (ae_int32x2 *)x_in; + ae_int32x2 *p_out = (ae_int32x2 *)y; + ae_int32x2 x0, x1, x2; + ae_int32x2 c0, c1; + ae_int32x2 scale; + ae_int32x2 sum, result; + ae_int64 re, im; + + /* + * Set up DFT3 twiddle factors as packed {H=real, L=imag}. + * c0 = {-0.5, -sqrt(3)/2} + * c1 = {-0.5, +sqrt(3)/2} + */ + scale = AE_MOVDA32(DFT3_COEFR); + c0 = AE_SEL32_LH(scale, AE_MOVDA32(-DFT3_COEFI)); + c1 = AE_SEL32_LH(scale, AE_MOVDA32(DFT3_COEFI)); + + /* Scale factor 1/3, broadcast to both H and L */ + scale = AE_MOVDA32(DFT3_SCALE); + + /* Load input samples as packed {real, imag} */ + x0 = AE_L32X2_I(p_in, 0); + x1 = AE_L32X2_I(p_in, 1 * sizeof(ae_int32x2)); + x2 = AE_L32X2_I(p_in, 2 * sizeof(ae_int32x2)); + + /* Scale all inputs by 1/3 to prevent overflow */ + x0 = AE_MULFP32X2RS(x0, scale); + x1 = AE_MULFP32X2RS(x1, scale); + x2 = AE_MULFP32X2RS(x2, scale); + + /* y[0] = x[0] + x[1] + x[2] */ + sum = AE_ADD32S(x0, x1); + AE_S32X2_I(AE_ADD32S(sum, x2), p_out, 0); + + /* + * y[1] = x[0] + c0 * x[1] + c1 * x[2] + * + * Fuse two complex multiplies and their sum into a single + * 64-bit accumulator pair to avoid intermediate rounding. + * + * Real part: c0.re*x1.re - c0.im*x1.im + c1.re*x2.re - c1.im*x2.im + * Imag part: c0.re*x1.im + c0.im*x1.re + c1.re*x2.im + c1.im*x2.re + */ + re = AE_MULF32S_HH(c0, x1); /* c0.re * x1.re */ + AE_MULSF32S_LL(re, c0, x1); /* -= c0.im * x1.im */ + AE_MULAF32S_HH(re, c1, x2); /* += c1.re * x2.re */ + AE_MULSF32S_LL(re, c1, x2); /* -= c1.im * x2.im */ + + im = AE_MULF32S_HL(c0, x1); /* c0.re * x1.im */ + AE_MULAF32S_LH(im, c0, x1); /* += c0.im * x1.re */ + AE_MULAF32S_HL(im, c1, x2); /* += c1.re * x2.im */ + AE_MULAF32S_LH(im, c1, x2); /* += c1.im * x2.re */ + + result = AE_ROUND32X2F64SSYM(re, im); + AE_S32X2_I(AE_ADD32S(x0, result), p_out, sizeof(ae_int32x2)); + + /* + * y[2] = x[0] + c1 * x[1] + c0 * x[2] + * + * Same structure as y[1] but with swapped coefficients. + */ + re = AE_MULF32S_HH(c1, x1); /* c1.re * x1.re */ + AE_MULSF32S_LL(re, c1, x1); /* -= c1.im * x1.im */ + AE_MULAF32S_HH(re, c0, x2); /* += c0.re * x2.re */ + AE_MULSF32S_LL(re, c0, x2); /* -= c0.im * x2.im */ + + im = AE_MULF32S_HL(c1, x1); /* c1.re * x1.im */ + AE_MULAF32S_LH(im, c1, x1); /* += c1.im * x1.re */ + AE_MULAF32S_HL(im, c0, x2); /* += c0.re * x2.im */ + AE_MULAF32S_LH(im, c0, x2); /* += c0.im * x2.re */ + + result = AE_ROUND32X2F64SSYM(re, im); + AE_S32X2_I(AE_ADD32S(x0, result), p_out, 2 * sizeof(ae_int32x2)); +} + +/** + * fft_multi_execute_32() - Execute multi-radix FFT/IFFT (HiFi3). + * @param plan Pointer to multi-FFT plan. + * @param ifft False for FFT, true for IFFT. + * + * Performs a composite FFT of size N = num_ffts * fft_size (e.g. 3 * 512 = 1536). + * For power-of-two sizes the call is forwarded to fft_execute_32(). + * + * HiFi3 optimizations vs. the generic path: + * - IFFT conjugate uses packed AE_SEL32_HL / AE_NEG32S + * - Twiddle multiply uses fused 64-bit MAC (no intermediate rounding) + * - IFFT shift-back combines negate, shift, and *3 scale in HiFi3 ops + */ +void fft_multi_execute_32(struct fft_multi_plan *plan, bool ifft) +{ + struct icomplex32 x[FFT_MULTI_COUNT_MAX]; + struct icomplex32 y[FFT_MULTI_COUNT_MAX]; + ae_int32x2 *p_src; + ae_int32x2 *p_dst; + ae_int32x2 sample, sample_neg, tw, data; + ae_int64 re, im; + int i, j, k, m; + + /* Handle 2^N FFT */ + if (plan->num_ffts == 1) { + memset(plan->outb32, 0, plan->fft_size * sizeof(struct icomplex32)); + fft_execute_32(plan->fft_plan[0], ifft); + return; + } + + /* Convert to complex conjugate for IFFT */ + if (ifft) { + p_src = (ae_int32x2 *)plan->inb32; + for (i = 0; i < plan->total_size; i++) { + AE_L32X2_IP(sample, p_src, 0); + sample_neg = AE_NEG32S(sample); + sample = AE_SEL32_HL(sample, sample_neg); + AE_S32X2_IP(sample, p_src, sizeof(ae_int32x2)); + } + } + + /* Copy input buffers (interleaved -> per-FFT) */ + k = 0; + for (i = 0; i < plan->fft_size; i++) + for (j = 0; j < plan->num_ffts; j++) + plan->tmp_i32[j][i] = plan->inb32[k++]; + + /* Clear output buffers and call individual FFTs */ + for (j = 0; j < plan->num_ffts; j++) { + memset(&plan->tmp_o32[j][0], 0, plan->fft_size * sizeof(struct icomplex32)); + fft_execute_32(plan->fft_plan[j], 0); + } + + /* Multiply with twiddle factors using HiFi3 complex multiply */ + m = FFT_MULTI_TWIDDLE_SIZE / 2 / plan->fft_size; + for (j = 1; j < plan->num_ffts; j++) { + p_dst = (ae_int32x2 *)plan->tmp_o32[j]; + for (i = 0; i < plan->fft_size; i++) { + k = j * i * m; + /* + * Build twiddle as packed {H=real, L=imag}. + * Use AE_SEL32_LH to pack two scalar loads. + */ + tw = AE_SEL32_LH(AE_MOVDA32(multi_twiddle_real_32[k]), + AE_MOVDA32(multi_twiddle_imag_32[k])); + + data = AE_L32X2_I(p_dst, 0); + + /* Complex multiply: tw * data */ + re = AE_MULF32S_HH(tw, data); + AE_MULSF32S_LL(re, tw, data); + im = AE_MULF32S_HL(tw, data); + AE_MULAF32S_LH(im, tw, data); + + AE_S32X2_IP(AE_ROUND32X2F64SSYM(re, im), + p_dst, sizeof(ae_int32x2)); + } + } + + /* DFT of size 3 */ + j = plan->fft_size; + k = 2 * plan->fft_size; + for (i = 0; i < plan->fft_size; i++) { + x[0] = plan->tmp_o32[0][i]; + x[1] = plan->tmp_o32[1][i]; + x[2] = plan->tmp_o32[2][i]; + dft3_32(x, y); + plan->outb32[i] = y[0]; + plan->outb32[i + j] = y[1]; + plan->outb32[i + k] = y[2]; + } + + /* Shift back for IFFT */ + if (ifft) { + int len = plan->fft_plan[0]->len; + + p_dst = (ae_int32x2 *)plan->outb32; + for (i = 0; i < plan->total_size; i++) { + AE_L32X2_IP(sample, p_dst, 0); + + /* Negate imag part to match reference */ + sample_neg = AE_NEG32S(sample); + sample = AE_SEL32_HL(sample, sample_neg); + + /* Shift left by FFT length to compensate shrink */ + sample = AE_SLAA32S(sample, len); + + /* Integer multiply by 3 (num_ffts) with saturation */ + data = AE_ADD32S(sample, sample); + sample = AE_ADD32S(data, sample); + + AE_S32X2_IP(sample, p_dst, sizeof(ae_int32x2)); + } + } +} + +#endif /* FFT_HIFI3 */ diff --git a/src/math/fft/tune/README.md b/src/math/fft/tune/README.md new file mode 100644 index 000000000000..e753716a8952 --- /dev/null +++ b/src/math/fft/tune/README.md @@ -0,0 +1,15 @@ +# Export FFT twiddle factors data + +To generate the twiddle factors headers for FFT max size of 1024 +(current assumption) run these shell commands: + +octave -q --eval "sof_export_twiddle(32, 'twiddle_32.h', 1024);" +octave -q --eval "sof_export_twiddle(16, 'twiddle_16.h', 1024);" +cp twiddle_32.h ../../../include/sof/audio/coefficients/fft/ +cp twiddle_16.h ../../../include/sof/audio/coefficients/fft/ + +To generate the twiddle factors for the non-power-of-two FFT implementation for max +size 3072 run these shell commands: + +octave -q --eval "sof_export_twiddle(32, 'twiddle_3072_32.h', 2048, 3072, 'FFT_MULTI_TWIDDLE_SIZE', 'multi_twiddle');" +cp twiddle_3072_32.h ../../../include/sof/audio/coefficients/fft/ diff --git a/src/math/fft/tune/sof_export_twiddle.m b/src/math/fft/tune/sof_export_twiddle.m new file mode 100644 index 000000000000..9e6b1489c8b5 --- /dev/null +++ b/src/math/fft/tune/sof_export_twiddle.m @@ -0,0 +1,106 @@ +% sof_export_twiddle(bits, fn, fft_size_max, denom, str_size_max, str_var) +% +% Input +% bits - Number of bits for data, 16 or 32 +% fn - File name, defaults to twiddle.h +% fft_size_max - Number of twiddle factors, defaults to 1024 if omitted +% denom - divide index * 2 * pi by denom instead of fft_size_max, same if omitted +% str_size_max - macro name for values array size, FFT_SIZE_MAX if omitted +% str_var - variable name prefix, twiddle if omitted + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function sof_export_twiddle(bits, fn, fft_size_max, denom, str_size_max, str_var) + +if nargin < 2 + fn = 'twiddle.h'; +end + +if nargin < 3 + fft_size_max = 1024; +end + +if nargin < 4 + denom = fft_size_max; +end + +if nargin < 5 + str_size_max = 'FFT_SIZE_MAX'; +end + +if nargin < 6 + str_var = 'twiddle'; +end + +switch bits + case 16, + qx = 1; + qy = 15; + case 32, + qx = 1; + qy = 31; + otherwise, + error('Illegal bits count'); +end + +[~, hname, ~] = fileparts(fn); +hcaps = upper(hname); + +i = 0:(fft_size_max - 1); +twiddle_real = cos(i * 2 * pi / denom); +twiddle_imag = -sin(i * 2 * pi / denom); + +year = datestr(now(), 'yyyy'); +fh = fopen(fn, 'w'); +fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); +fprintf(fh, ' *\n'); +fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', year); +fprintf(fh, ' *\n'); +fprintf(fh, ' */\n\n'); +fprintf(fh, '/* Twiddle factors in Q%d.%d format */\n\n', qx, qy); +fprintf(fh, '#ifndef __INCLUDE_%s_H__\n', hcaps); +fprintf(fh, '#define __INCLUDE_%s_H__\n\n', hcaps); +fprintf(fh, '#include <stdint.h>\n\n'); +fprintf(fh, '#define %s\t%d\n\n', str_size_max, fft_size_max); +fprintf(fh, '/* in Q1.%d, generated from cos(i * 2 * pi / FFT_SIZE_MAX) */\n', qy); +str_real = sprintf('%s_real', str_var); +c_export_int(fh, str_real, str_size_max, twiddle_real, qx, qy); + +fprintf(fh, '/* in Q1.%d, generated from sin(i * 2 * pi / FFT_SIZE_MAX) */\n', qy); +str_imag = sprintf('%s_imag', str_var); +c_export_int(fh, str_imag, str_size_max, twiddle_imag, qx, qy); + +fprintf(fh, '#endif\n'); +fclose(fh); + +fprintf(1, 'Exported successfully file %s\n', fn); + +end + +function c_export_int(fh, vname, vsize, data, qx, qy, vn) + +bits = qx + qy; +switch bits + case 16, + vtype = 'int16_t'; + case 32, + vtype = 'int32_t'; +end + +maxint = 2^(qx + qy - 1) - 1; +minint = -2^(qx + qy - 1) + 1; % Avoid "this decimal constant is unsigned only in ISO C90" +scale = 2^qy; +quant = round(data * scale); +quant = min(quant, maxint); +quant = max(quant, minint); + +fprintf(fh, 'const %s %s_%d[%s] = {\n', vtype, vname, bits, vsize); +for i = 1:length(data) + fprintf(fh, '\t%d,\n', quant(i)); +end + +fprintf(fh, '};\n\n'); + +end diff --git a/src/math/fir.toml b/src/math/fir.toml new file mode 100644 index 000000000000..86f2d4163b34 --- /dev/null +++ b/src/math/fir.toml @@ -0,0 +1,6 @@ + [[module.entry]] + name = "FIR" + uuid = UUIDREG_STR_FIR + load_type = "3" + + index = __COUNTER__ diff --git a/src/math/fir_generic.c b/src/math/fir_generic.c new file mode 100644 index 000000000000..802242d4dbec --- /dev/null +++ b/src/math/fir_generic.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(NONE, FILTER) + +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/math/fir_generic.h> +#include <user/fir.h> +#include <rtos/symbol.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* + * EQ FIR algorithm code + */ + +void fir_reset(struct fir_state_32x16 *fir) +{ + fir->rwi = 0; + fir->length = 0; + fir->out_shift = 0; + fir->coef = NULL; + /* There may need to know the beginning of dynamic allocation after + * reset so omitting setting also fir->delay to NULL. + */ +} +EXPORT_SYMBOL(fir_reset); + +int fir_delay_size(struct sof_fir_coef_data *config) +{ + /* Check FIR tap count for implementation specific constraints */ + if (config->length > SOF_FIR_MAX_LENGTH || config->length < 4) + return -EINVAL; + + /* The optimization requires the tap count to be multiple of four */ + if (config->length & 0x3) + return -EINVAL; + + /* The dual sample version needs one more delay entry. To preserve + * align for 64 bits need to add two. + */ + return (config->length + 4) * sizeof(int32_t); +} +EXPORT_SYMBOL(fir_delay_size); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config) +{ + fir->rwi = 0; + fir->taps = (int)config->length; + fir->length = (int)fir->taps + 2; + fir->out_shift = (int)config->out_shift; + fir->coef = ASSUME_ALIGNED(&config->coef[0], 4); + return 0; +} +EXPORT_SYMBOL(fir_init_coef); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) +{ + fir->delay = *data; + *data += fir->length; /* Point to next delay line start */ +} +EXPORT_SYMBOL(fir_init_delay); + +int32_t fir_32x16(struct fir_state_32x16 *fir, int32_t x) +{ + int64_t y = 0; + int32_t *data = &fir->delay[fir->rwi]; + int16_t *coef = &fir->coef[0]; + int n1; + int n2; + int n; + const int length = fir->length; + const int taps = fir->taps; + const int shift = 15 + fir->out_shift; + + /* Bypass is set with length set to zero. */ + if (!fir->length) + return x; + + /* Write sample to delay */ + *data = x; + + /* Advance write pointer and calculate into n1 max. number of taps + * to process before circular wrap. + */ + n1 = ++fir->rwi; + if (fir->rwi == length) + fir->rwi = 0; + + /* Part 1, loop n1 times */ + n1 = MIN(n1, taps); + for (n = 0; n < n1; n++) { + y += (int64_t)(*coef) * (*data); + coef++; + data--; + } + + /* Part 2, un-wrap data, continue n2 times */ + n2 = taps - n1; + data = &fir->delay[length - 1]; + for (n = 0; n < n2; n++) { + y += (int64_t)(*coef) * (*data); + coef++; + data--; + } + + /* Q2.46 -> Q2.31, saturate to Q1.31 */ + return sat_int32(y >> shift); +} +EXPORT_SYMBOL(fir_32x16); + +void fir_32x16_2x(struct fir_state_32x16 *fir, int32_t x0, int32_t x1, int32_t *y0, int32_t *y1) +{ + int64_t a0 = 0; + int64_t a1 = 0; + int32_t sample0; + int32_t sample1; + int16_t tap; + int32_t *data = &fir->delay[fir->rwi]; + int16_t *coef = &fir->coef[0]; + int n1; + int n2; + int i; + const int length = fir->length; + const int taps = fir->taps; + const int shift = 15 + fir->out_shift; + + /* Bypass is set with length set to zero. */ + if (!fir->taps) { + *y0 = x0; + *y1 = x1; + return; + } + + /* Write samples to delay */ + *data = x0; + *(data + 1) = x1; + + /* Advance write pointer and calculate into n1 max. number of taps + * to process before circular wrap. + */ + n1 = fir->rwi + 1; + fir->rwi += 2; + if (fir->rwi >= length) + fir->rwi -= length; + + /* Part 1, loop n1 times */ + sample1 = x1; + n1 = MIN(n1, taps); + for (i = 0; i < n1; i++) { + tap = *coef; + coef++; + sample0 = *data; + data--; + a1 += (int64_t)tap * sample1; + a0 += (int64_t)tap * sample0; + sample1 = sample0; + } + + /* Part 2, un-wrap data, continue n2 times */ + n2 = taps - n1; + data = &fir->delay[length - 1]; + for (i = 0; i < n2; i++) { + tap = *coef; + coef++; + sample0 = *data; + data--; + a1 += (int64_t)tap * sample1; + a0 += (int64_t)tap * sample0; + sample1 = sample0; + } + + /* Q2.46 -> Q2.31, saturate to Q1.31 */ + *y0 = sat_int32(a0 >> shift); + *y1 = sat_int32(a1 >> shift); +} +EXPORT_SYMBOL(fir_32x16_2x); + +#endif diff --git a/src/math/fir_hifi2ep.c b/src/math/fir_hifi2ep.c new file mode 100644 index 000000000000..1dd03d7c1485 --- /dev/null +++ b/src/math/fir_hifi2ep.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017-2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(2, FILTER) + +#include <sof/audio/format.h> +#include <sof/math/fir_hifi2ep.h> +#include <user/fir.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi2.h> +#include <rtos/symbol.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* + * EQ FIR algorithm code + */ + +void fir_reset(struct fir_state_32x16 *fir) +{ + fir->taps = 0; + fir->length = 0; + fir->out_shift = 0; + fir->coef = NULL; + /* There may need to know the beginning of dynamic allocation after + * reset so omitting setting also fir->delay to NULL. + */ +} +EXPORT_SYMBOL(fir_reset); + +int fir_delay_size(struct sof_fir_coef_data *config) +{ + /* Check FIR tap count for implementation specific constraints */ + if (config->length > SOF_FIR_MAX_LENGTH || config->length < 4) + return -EINVAL; + + if (config->length & 0x3) + return -EINVAL; + + /* The dual sample version needs one more delay entry. To preserve + * align for 64 bits need to add two. + */ + return (config->length + 2) * sizeof(int32_t); +} +EXPORT_SYMBOL(fir_delay_size); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config) +{ + /* The length is taps plus two since the filter computes two + * samples per call. Length plus one would be minimum but the add + * must be even. The even length is needed for 64 bit loads from delay + * lines with 32 bit samples. + */ + fir->taps = (int)config->length; + fir->length = fir->taps + 2; + fir->out_shift = (int)config->out_shift; + fir->coef = (ae_p16x2s *)&config->coef[0]; + return 0; +} +EXPORT_SYMBOL(fir_init_coef); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) +{ + fir->delay = (ae_p24f *)*data; + fir->delay_end = fir->delay + fir->length; + fir->rwp = (ae_p24x2f *)(fir->delay + fir->length - 1); + *data += fir->length; /* Point to next delay line start */ +} +EXPORT_SYMBOL(fir_init_delay); + +void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, + int *rshift) +{ + *lshift = (fir->out_shift < 0) ? -fir->out_shift : 0; + *rshift = (fir->out_shift > 0) ? fir->out_shift : 0; +} +EXPORT_SYMBOL(fir_get_lrshifts); + +/* HiFi EP has the follow number of reqisters that should not be exceeded + * 4x 56 bit registers in register file Q + * 8x 48 bit registers in register file P + */ + +void fir_32x16(struct fir_state_32x16 *fir, int32_t x, int32_t *y, int lshift, int rshift) +{ + /* This function uses + * 1x 56 bit registers Q, + * 4x 48 bit registers P + * 3x integers + * 2x address pointers, + */ + ae_q56s a; + ae_p24x2f data2; + ae_p24x2f coef2; + ae_p24x2f d0; + ae_p24x2f d1; + int i; + ae_p24x2f *dp = fir->rwp; + ae_p16x2s *coefp = fir->coef; + const int taps_div_4 = fir->taps >> 2; + const int inc = sizeof(int32_t); + + /* Bypass samples if taps count is zero. */ + if (!taps_div_4) { + *y = x; + return; + } + + /* Write sample to delay */ + a = AE_CVTQ48A32S(x); + AE_SQ32F_C(a, (ae_q32s *)fir->rwp, -sizeof(int32_t)); + + /* Note: If the next function is converted to handle two samples + * per call the data load can be done with single instruction + * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); + */ + a = AE_ZEROQ56(); + for (i = 0; i < taps_div_4; i++) { + /* Load two coefficients. Coef2_h contains tap coefp[n] + * and coef2_l contains coef[n+1]. + */ + coef2 = AE_LP16X2F_I(coefp, 0); + + /* Load two data samples and pack to d0 to data2_h and + * d1 to data2_l. + */ + AE_LP24F_C(d0, dp, inc); + AE_LP24F_C(d1, dp, inc); + data2 = AE_SELP24_LL(d0, d1); + + /* Accumulate + * data2_h * coef2_h + data2_l * coef2_l. The Q1.31 + * data and Q1.15 coefficients are used as 24 bits as + * Q1.23 values. + */ + AE_MULAAFP24S_HH_LL(a, data2, coef2); + + /* Repeat the same for next two taps and increase coefp. */ + coef2 = AE_LP16X2F_I(coefp, sizeof(ae_p16x2s)); + AE_LP24F_C(d0, dp, inc); + AE_LP24F_C(d1, dp, inc); + data2 = AE_SELP24_LL(d0, d1); + AE_MULAAFP24S_HH_LL(a, data2, coef2); + coefp += 2; + } + + /* Do scaling shifts and store sample. */ + a = AE_SRAAQ56(AE_SLLASQ56S(a, lshift), rshift); + AE_SQ32F_I(AE_ROUNDSQ32SYM(a), (ae_q32s *)y, 0); +} +EXPORT_SYMBOL(fir_32x16_hifiep); + +/* HiFi EP has the follow number of reqisters that should not be exceeded + * 4x 56 bit registers in register file Q + * 8x 48 bit registers in register file P + */ + +void fir_32x16_2x(struct fir_state_32x16 *fir, int32_t x0, int32_t x1, + int32_t *y0, int32_t *y1, int lshift, int rshift) +{ + /* This function uses + * 2x 56 bit registers Q, + * 4x 48 bit registers P + * 3x integers + * 2x address pointers, + */ + ae_q56s a; + ae_q56s b; + ae_p24x2f d0; + ae_p24x2f d1; + ae_p24x2f d3; + ae_p24x2f coefs; + int i; + ae_p24x2f *dp; + ae_p16x2s *coefp = fir->coef; + const int taps_div_4 = fir->taps >> 2; + const int inc = 2 * sizeof(int32_t); + + /* Bypass samples if taps count is zero. */ + if (!taps_div_4) { + *y0 = x0; + *y1 = x1; + return; + } + + /* Write samples to delay */ + a = AE_CVTQ48A32S(x0); + AE_SQ32F_C(a, (ae_q32s *)fir->rwp, -sizeof(int32_t)); + a = AE_CVTQ48A32S(x1); + dp = fir->rwp; + AE_SQ32F_C(a, (ae_q32s *)fir->rwp, -sizeof(int32_t)); + + /* Note: If the next function is converted to handle two samples + * per call the data load can be done with single instruction + * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); + */ + a = AE_ZEROQ56(); + b = AE_ZEROQ56(); + /* Load two data samples and pack to d0 to data2_h and + * d1 to data2_l. + */ + AE_LP24X2F_C(d0, dp, inc); + for (i = 0; i < taps_div_4; i++) { + /* Load two coefficients. Coef2_h contains tap coefp[n] + * and coef2_l contains coef[n+1]. + */ + coefs = AE_LP16X2F_I(coefp, 0); + + /* Load two data samples. Upper part d1_h is x[n+1] and + * lower part d1_l is x[n]. + */ + AE_LP24X2F_C(d1, dp, inc); + + /* Accumulate + * b += d0_h * coefs_h + d0_l * coefs_l. The Q1.31 data + * and Q1.15 coefficients are converted to 24 bits as + * Q1.23 values. + */ + AE_MULAAFP24S_HH_LL(b, d0, coefs); + + /* Pack d0_l and d1_h to d3. Then accumulate + * a += d3_h * coefs_h + d3_l * coefs_l. Pass d1 to d1 for + * next unrolled iteration. + */ + d3 = AE_SELP24_LH(d0, d1); + AE_MULAAFP24S_HH_LL(a, d3, coefs); + d0 = d1; + + /* Repeat the same for next two taps and increase coefp. */ + coefs = AE_LP16X2F_I(coefp, sizeof(ae_p16x2s)); + AE_LP24X2F_C(d1, dp, inc); + AE_MULAAFP24S_HH_LL(b, d0, coefs); + d3 = AE_SELP24_LH(d0, d1); + AE_MULAAFP24S_HH_LL(a, d3, coefs); + d0 = d1; + coefp += 2; + } + + /* Do scaling shifts and store sample. */ + b = AE_SRAAQ56(AE_SLLASQ56S(b, lshift), rshift); + a = AE_SRAAQ56(AE_SLLASQ56S(a, lshift), rshift); + AE_SQ32F_I(AE_ROUNDSQ32SYM(b), (ae_q32s *)y1, 0); + AE_SQ32F_I(AE_ROUNDSQ32SYM(a), (ae_q32s *)y0, 0); +} +EXPORT_SYMBOL(fir_32x16_2x_hifiep); + +#endif diff --git a/src/math/fir_hifi3.c b/src/math/fir_hifi3.c new file mode 100644 index 000000000000..dd3e0edf8bde --- /dev/null +++ b/src/math/fir_hifi3.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017-2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_HIFI(3, FILTER) || SOF_USE_HIFI(4, FILTER) + +#include <sof/audio/buffer.h> +#include <sof/math/fir_hifi3.h> +#include <user/fir.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi3.h> +#include <rtos/symbol.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* + * EQ FIR algorithm code + */ + +void fir_reset(struct fir_state_32x16 *fir) +{ + fir->taps = 0; + fir->length = 0; + fir->out_shift = 0; + fir->coef = NULL; + /* There may need to know the beginning of dynamic allocation after + * reset so omitting setting also fir->delay to NULL. + */ +} +EXPORT_SYMBOL(fir_reset); + +int fir_delay_size(struct sof_fir_coef_data *config) +{ + /* Check FIR tap count for implementation specific constraints */ + if (config->length > SOF_FIR_MAX_LENGTH || config->length < 4) + return -EINVAL; + + /* The optimization requires the tap count to be multiple of four */ + if (config->length & 0x3) + return -EINVAL; + + /* The dual sample version needs one more delay entry. To preserve + * align for 64 bits need to add two. + */ + return (config->length + 2) * sizeof(int32_t); +} +EXPORT_SYMBOL(fir_delay_size); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config) +{ + /* The length is taps plus two since the filter computes two + * samples per call. Length plus one would be minimum but the add + * must be even. The even length is needed for 64 bit loads from delay + * lines with 32 bit samples. + */ + fir->taps = (int)config->length; + fir->length = fir->taps + 2; + fir->out_shift = (int)config->out_shift; + fir->coef = (ae_f16x4 *)&config->coef[0]; + return 0; +} +EXPORT_SYMBOL(fir_init_coef); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) +{ + fir->delay = (ae_int32 *)*data; + fir->delay_end = fir->delay + fir->length; + fir->rwp = (ae_int32 *)(fir->delay + fir->length - 1); + *data += fir->length; /* Point to next delay line start */ +} +EXPORT_SYMBOL(fir_init_delay); + +void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, + int *rshift) +{ + *lshift = (fir->out_shift < 0) ? -fir->out_shift : 0; + *rshift = (fir->out_shift > 0) ? fir->out_shift : 0; +} +EXPORT_SYMBOL(fir_get_lrshifts); + +/* HiFi EP has the follow number of reqisters that should not be exceeded + * 4x 56 bit registers in register file Q + * 8x 48 bit registers in register file P + */ + +void fir_32x16(struct fir_state_32x16 *fir, ae_int32 x, ae_int32 *y, int shift) +{ + /* This function uses + * 1x 56 bit registers Q, + * 4x 48 bit registers P + * 3x integers + * 2x address pointers, + */ + ae_f64 a; + ae_valign u; + ae_f32x2 data2; + ae_f16x4 coefs; + ae_f32x2 d0; + ae_f32x2 d1; + int i; + ae_int32 *dp = fir->rwp; + ae_int16x4 *coefp = (ae_int16x4 *)fir->coef; + const int taps_div_4 = fir->taps >> 2; + const int inc = sizeof(int32_t); + + /* Bypass samples if taps count is zero. */ + if (!taps_div_4) { + *y = x; + return; + } + + /* Write sample to delay */ + AE_S32_L_XC(x, fir->rwp, -sizeof(int32_t)); + + /* Prime the coefficients stream */ + u = AE_LA64_PP(coefp); + + /* Note: If the next function is converted to handle two samples + * per call the data load can be done with single instruction + * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); + */ + a = AE_ZEROQ56(); + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients. Coef_3 contains tap h[n], + * coef_2 contains h[n+1], coef_1 contains h[n+2], and + * coef_0 contains h[n+3]; + */ + AE_LA16X4_IP(coefs, u, coefp); + + /* Load two data samples and pack to d0 to data2_h and + * d1 to data2_l. + */ + AE_L32_XC(d0, dp, inc); + AE_L32_XC(d1, dp, inc); + data2 = AE_SEL32_LL(d0, d1); + + /* Accumulate + * a += data2_h * coefs_3 + data2_l * coefs_2. The Q1.31 + * data and Q1.15 coefficients are used as 24 bits as + * Q1.23 values. + */ + AE_MULAAFD32X16_H3_L2(a, data2, coefs); + + /* Repeat the same for next two taps and increase coefp. + * a += data2_h * coefs_1 + data2_l * coefs_0. + */ + AE_L32_XC(d0, dp, inc); + AE_L32_XC(d1, dp, inc); + data2 = AE_SEL32_LL(d0, d1); + AE_MULAAFD32X16_H1_L0(a, data2, coefs); + } + + /* Do scaling shifts and store sample. */ + a = AE_SLAA64S(a, shift); + AE_S32_L_I(AE_ROUND32F48SSYM(a), (ae_int32 *)y, 0); +} +EXPORT_SYMBOL(fir_32x16); + +/* HiFi EP has the follow number of reqisters that should not be exceeded + * 4x 56 bit registers in register file Q + * 8x 48 bit registers in register file P + */ + +void fir_32x16_2x(struct fir_state_32x16 *fir, ae_int32 x0, ae_int32 x1, + ae_int32 *y0, ae_int32 *y1, int shift) +{ + /* This function uses + * 2x 56 bit registers Q, + * 4x 48 bit registers P + * 3x integers + * 2x address pointers, + */ + ae_f64 a; + ae_f64 b; + ae_valign u; + ae_f32x2 d0; + ae_f32x2 d1; + ae_f16x4 coefs; + int i; + ae_f32x2 *dp; + ae_f16x4 *coefp = fir->coef; + const int taps_div_4 = fir->taps >> 2; + const int inc = 2 * sizeof(int32_t); + + /* Bypass samples if taps count is zero. */ + if (!taps_div_4) { + *y0 = x0; + *y1 = x1; + return; + } + + /* Write samples to delay */ + AE_S32_L_XC(x0, fir->rwp, -sizeof(int32_t)); + dp = (ae_f32x2 *)fir->rwp; + AE_S32_L_XC(x1, fir->rwp, -sizeof(int32_t)); + + /* Note: If the next function is converted to handle two samples + * per call the data load can be done with single instruction + * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); + */ + a = AE_ZERO64(); + b = AE_ZERO64(); + + /* Prime the coefficients stream */ + u = AE_LA64_PP(coefp); + + /* Load two data samples and pack to d0 to data2_h and + * d1 to data2_l. + */ + AE_L32X2_XC(d0, dp, inc); + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients. Coef_3 contains tap h[n], + * coef_2 contains h[n+1], coef_1 contains h[n+2], and + * coef_0 contains h[n+3]; + */ + AE_LA16X4_IP(coefs, u, coefp); + + /* Load two data samples. Upper part d1_h is x[n+1] and + * lower part d1_l is x[n]. + */ + AE_L32X2_XC(d1, dp, inc); + + /* Quad MAC (HH) + * b += d0_h * coefs_3 + d0_l * coefs_2 + * a += d0_l * coefs_3 + d1_h * coefs_2 + */ + AE_MULAFD32X16X2_FIR_HH(b, a, d0, d1, coefs); + d0 = d1; + + /* Repeat the same for next two taps and increase coefp. */ + AE_L32X2_XC(d1, dp, inc); + + /* Quad MAC (HL) + * b += d0_h * coefs_1 + d0_l * coefs_0 + * a += d0_l * coefs_1 + d1_h * coefs_0 + */ + AE_MULAFD32X16X2_FIR_HL(b, a, d0, d1, coefs); + d0 = d1; + } + + /* Do scaling shifts and store sample. */ + b = AE_SLAA64S(b, shift); + a = AE_SLAA64S(a, shift); + AE_S32_L_I(AE_ROUND32F48SSYM(b), (ae_int32 *)y1, 0); + AE_S32_L_I(AE_ROUND32F48SSYM(a), (ae_int32 *)y0, 0); +} +EXPORT_SYMBOL(fir_32x16_2x); + +#endif diff --git a/src/math/fir_hifi5.c b/src/math/fir_hifi5.c new file mode 100644 index 000000000000..d4b699ceabb2 --- /dev/null +++ b/src/math/fir_hifi5.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017-2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/math/fir_config.h> +#include <sof/common.h> + +#if SOF_USE_MIN_HIFI(5, FILTER) + +#include <sof/audio/buffer.h> +#include <sof/math/fir_hifi3.h> +#include <user/fir.h> +#include <xtensa/config/defs.h> +#include <xtensa/tie/xt_hifi5.h> +#include <rtos/symbol.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +/* + * EQ FIR algorithm code + */ + +void fir_reset(struct fir_state_32x16 *fir) +{ + fir->taps = 0; + fir->length = 0; + fir->out_shift = 0; + fir->coef = NULL; + /* There may need to know the beginning of dynamic allocation after + * reset so omitting setting also fir->delay to NULL. + */ +} +EXPORT_SYMBOL(fir_reset); + +int fir_delay_size(struct sof_fir_coef_data *config) +{ + /* Check FIR tap count for implementation specific constraints */ + if (config->length > SOF_FIR_MAX_LENGTH || config->length < 4) + return -EINVAL; + + /* The optimization requires the tap count to be multiple of four */ + if (config->length & 0x3) + return -EINVAL; + + /* The dual sample version needs one more delay entry. To preserve + * align for 64 bits need to add two. + */ + return (config->length + 2) * sizeof(int32_t); +} +EXPORT_SYMBOL(fir_delay_size); + +int fir_init_coef(struct fir_state_32x16 *fir, + struct sof_fir_coef_data *config) +{ + /* The length is taps plus two since the filter computes two + * samples per call. Length plus one would be minimum but the add + * must be even. The even length is needed for 64 bit loads from delay + * lines with 32 bit samples. + */ + fir->taps = (int)config->length; + fir->length = fir->taps + 2; + fir->out_shift = (int)config->out_shift; + fir->coef = (ae_f16x4 *)&config->coef[0]; + return 0; +} +EXPORT_SYMBOL(fir_init_coef); + +void fir_init_delay(struct fir_state_32x16 *fir, int32_t **data) +{ + fir->delay = (ae_int32 *)*data; + fir->delay_end = fir->delay + fir->length; + fir->rwp = (ae_int32 *)(fir->delay + fir->length - 1); + *data += fir->length; /* Point to next delay line start */ +} +EXPORT_SYMBOL(fir_init_delay); + +void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, + int *rshift) +{ + *lshift = (fir->out_shift < 0) ? -fir->out_shift : 0; + *rshift = (fir->out_shift > 0) ? fir->out_shift : 0; +} +EXPORT_SYMBOL(fir_get_lrshifts); + +void fir_32x16(struct fir_state_32x16 *fir, ae_int32 x, ae_int32 *y, int shift) +{ + /* This function uses + * 1x 56 bit registers Q, + * 4x 48 bit registers P + * 3x integers + * 2x address pointers, + */ + ae_f64 a; + ae_valign u; + ae_f32x2 data2; + ae_f16x4 coefs; + ae_f32x2 d0; + ae_f32x2 d1; + int i; + ae_int32 *dp = fir->rwp; + ae_int16x4 *coefp = (ae_int16x4 *)fir->coef; + const int taps_div_4 = fir->taps >> 2; + const int inc = sizeof(int32_t); + + /* Bypass samples if taps count is zero. */ + if (!taps_div_4) { + *y = x; + return; + } + + /* Write sample to delay */ + AE_S32_L_XC(x, fir->rwp, -sizeof(int32_t)); + + /* Prime the coefficients stream */ + u = AE_LA64_PP(coefp); + + /* Note: If the next function is converted to handle two samples + * per call the data load can be done with single instruction + * AE_LP24X2F_C(data2, dp, sizeof(ae_p24x2f)); + */ + a = AE_ZEROQ56(); + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients. Coef_3 contains tap h[n], + * coef_2 contains h[n+1], coef_1 contains h[n+2], and + * coef_0 contains h[n+3]; + */ + AE_LA16X4_IP(coefs, u, coefp); + + /* Load two data samples and pack to d0 to data2_h and + * d1 to data2_l. + */ + AE_L32_XC(d0, dp, inc); + AE_L32_XC(d1, dp, inc); + data2 = AE_SEL32_LL(d0, d1); + + /* Accumulate + * a += data2_h * coefs_3 + data2_l * coefs_2. The Q1.31 + * data and Q1.15 coefficients are used as 24 bits as + * Q1.23 values. + */ + AE_MULAAFD32X16_H3_L2(a, data2, coefs); + + /* Repeat the same for next two taps and increase coefp. + * a += data2_h * coefs_1 + data2_l * coefs_0. + */ + AE_L32_XC(d0, dp, inc); + AE_L32_XC(d1, dp, inc); + data2 = AE_SEL32_LL(d0, d1); + AE_MULAAFD32X16_H1_L0(a, data2, coefs); + } + + /* Do scaling shifts and store sample. */ + a = AE_SLAA64S(a, shift); + AE_S32_L_I(AE_ROUND32F48SSYM(a), (ae_int32 *)y, 0); +} +EXPORT_SYMBOL(fir_32x16); + +void fir_32x16_2x(struct fir_state_32x16 *fir, ae_int32 x0, ae_int32 x1, + ae_int32 *y0, ae_int32 *y1, int shift) +{ + /* This function uses + * 7x 64 bit AE registers + * 3x integers + * 2x address pointers, + */ + ae_valign u; + ae_f64 a = AE_ZERO64(); + ae_f64 b = AE_ZERO64(); + ae_f32x2 d0; + ae_f32x2 d1; + ae_f32x2 d2; + ae_f16x4 coefs; + ae_f32x2 *dp; + ae_f16x4 *coefp = fir->coef; + const int taps_div_4 = fir->taps >> 2; + const int inc = 2 * sizeof(int32_t); + int i; + + /* Bypass samples if taps count is zero. */ + if (!taps_div_4) { + *y0 = x0; + *y1 = x1; + return; + } + + /* Write samples to delay */ + AE_S32_L_XC(x0, fir->rwp, -sizeof(int32_t)); + dp = (ae_f32x2 *)fir->rwp; + AE_S32_L_XC(x1, fir->rwp, -sizeof(int32_t)); + + /* Prime the coefficients stream */ + u = AE_LA64_PP(coefp); + + /* Load two samples, two newest samples and proceed + * to elder input samples in delay line. + */ + AE_L32X2_XC(d0, dp, inc); + for (i = 0; i < taps_div_4; i++) { + /* Load four coefficients. Coef_3 contains tap h[n], + * coef_2 contains h[n+1], coef_1 contains h[n+2], and + * coef_0 contains h[n+3]; + */ + AE_LA16X4_IP(coefs, u, coefp); + + /* Load two data samples more. + * d0.H is x[n] the newest sample + * d0.L is x[n-1] + * d1.H is x[n-2] + * d1.L is x[n-3] + * d2.H is x[n-4] + */ + AE_L32X2_XC(d1, dp, inc); + AE_L32X2_XC(d2, dp, inc); + + /* Calculate four FIR taps for current (x1 -> a) and previous input (x0 -> b) + * b = b + d0.H * c.3 + d0.L * c.2 + d1.H * c.1 + d1.L * c.0 + * a = a + d0.L * c.3 + d1.H * c.2 + d1.L * c.1 + d2.H * c.0 + */ + AE_MULA2Q32X16_FIR_H(b, a, d0, d1, d2, coefs); + + /* Prepare for next four taps, d2 overlaps to next loop iteration as d0 */ + d0 = d2; + } + + /* Shift left by one Q1.31 x Q1.15 -> Q2.46 format for Q2.47 round and + * store output samples. + */ + b = AE_SLAA64S(b, shift + 1); + a = AE_SLAA64S(a, shift + 1); + d0 = AE_ROUND32X2F48SASYM(b, a); + AE_S32_H_I(d0, (ae_int32 *)y1, 0); + AE_S32_L_I(d0, (ae_int32 *)y0, 0); +} +EXPORT_SYMBOL(fir_32x16_2x); + +#endif diff --git a/src/math/fir_llext/CMakeLists.txt b/src/math/fir_llext/CMakeLists.txt new file mode 100644 index 000000000000..688a07fa1ffb --- /dev/null +++ b/src/math/fir_llext/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("aux1_fir" + SOURCES fir_common.c + ../fir_generic.c + ../fir_hifi2ep.c + ../fir_hifi3.c + ../fir_hifi5.c + LIB openmodules +) diff --git a/src/math/fir_llext/fir_common.c b/src/math/fir_llext/fir_common.c new file mode 100644 index 000000000000..897ac857e07d --- /dev/null +++ b/src/math/fir_llext/fir_common.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. + +/* modular: llext dynamic link */ + +#include <sof/compiler_attributes.h> +#include <sof/lib/uuid.h> +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +#include <stddef.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_AUX_MANIFEST("FIR", NULL, SOF_REG_UUID(fir)); + +SOF_LLEXT_BUILDINFO; diff --git a/src/math/fir_llext/llext.toml.h b/src/math/fir_llext/llext.toml.h new file mode 100644 index 000000000000..fa2eab98627b --- /dev/null +++ b/src/math/fir_llext/llext.toml.h @@ -0,0 +1,5 @@ +#include <tools/rimage/config/platform.toml> +#include "../fir.toml" + +[module] +count = __COUNTER__ diff --git a/src/math/gcc-builtins.c b/src/math/gcc-builtins.c new file mode 100644 index 000000000000..56eef2087b43 --- /dev/null +++ b/src/math/gcc-builtins.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c); 2025 Intel Corporation. All rights reserved. + +#include <stdint.h> +#include <rtos/symbol.h> + +/* + * Below we export compiler builtin functions to be used by LLEXT modules. + * + * These builtins are defined in the following places: + * + * https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html + * https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html + * https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---signbitf.html + * + * Note: the list below are found in xtensa libgcc, other architecture may + * export more or less and we should then partition with some ifdefs. + */ +#if !CONFIG_64BIT + +long __ashldi3(long a, int b); +EXPORT_SYMBOL(__ashldi3); + +long __ashrdi3(long a, int b); +EXPORT_SYMBOL(__ashrdi3); + +int __divsi3(int a, int b); +EXPORT_SYMBOL(__divsi3); + +long __divdi3(long a, long b); +EXPORT_SYMBOL(__divdi3); + +long __lshrdi3(long a, int b); +EXPORT_SYMBOL(__lshrdi3); + +int __modsi3(int a, int b); +EXPORT_SYMBOL(__modsi3); + +long __moddi3(long a, long b); +EXPORT_SYMBOL(__moddi3); + +int __mulsi3(int a, int b); +EXPORT_SYMBOL(__mulsi3); + +long __muldi3(long a, long b); +EXPORT_SYMBOL(__muldi3); + +long __negdi2(long a); +EXPORT_SYMBOL(__negdi2); + +unsigned int __udivsi3(unsigned int a, unsigned int b); +EXPORT_SYMBOL(__udivsi3); + +unsigned long __udivdi3(unsigned long a, unsigned long b); +EXPORT_SYMBOL(__udivdi3); + +unsigned long __udivmoddi4(unsigned long a, unsigned long b, unsigned long *c); +EXPORT_SYMBOL(__udivmoddi4); + +unsigned int __umodsi3(unsigned int a, unsigned int b); +EXPORT_SYMBOL(__umodsi3); + +unsigned long __umoddi3(unsigned long a, unsigned long b); +EXPORT_SYMBOL(__umoddi3); + +int __cmpdi2(long a, long b); +EXPORT_SYMBOL(__cmpdi2); + +int __ucmpdi2(unsigned long a, unsigned long b); +EXPORT_SYMBOL(__ucmpdi2); + +int __absvsi2(int a); +EXPORT_SYMBOL(__absvsi2); + +long __absvdi2(long a); +EXPORT_SYMBOL(__absvdi2); + +int __addvsi3(int a, int b); +EXPORT_SYMBOL(__addvsi3); + +long __addvdi3(long a, long b); +EXPORT_SYMBOL(__addvdi3); + +int __mulvsi3(int a, int b); +EXPORT_SYMBOL(__mulvsi3); + +long __mulvdi3(long a, long b); +EXPORT_SYMBOL(__mulvdi3); + +int __negvsi2(int a); +EXPORT_SYMBOL(__negvsi2); + +long __negvdi2(long a); +EXPORT_SYMBOL(__negvdi2); + +int __subvsi3(int a, int b); +EXPORT_SYMBOL(__subvsi3); + +long __subvdi3(long a, long b); +EXPORT_SYMBOL(__subvdi3); + +int __clzsi2(unsigned int a); +EXPORT_SYMBOL(__clzsi2); + +int __clzdi2(unsigned long a); +EXPORT_SYMBOL(__clzdi2); + +int __ctzsi2(unsigned int a); +EXPORT_SYMBOL(__ctzsi2); + +int __ctzdi2(unsigned long a); +EXPORT_SYMBOL(__ctzdi2); + +int __ffsdi2(unsigned long a); +EXPORT_SYMBOL(__ffsdi2); + +int __paritysi2(unsigned int a); +EXPORT_SYMBOL(__paritysi2); + +int __paritydi2(unsigned long a); +EXPORT_SYMBOL(__paritydi2); + +int __popcountsi2(unsigned int a); +EXPORT_SYMBOL(__popcountsi2); + +int __popcountdi2(unsigned long a); +EXPORT_SYMBOL(__popcountdi2); + +float __addsf3(float a, float b); +EXPORT_SYMBOL(__addsf3); + +double __adddf3(double a, double b); +EXPORT_SYMBOL(__adddf3); + +float __subsf3(float a, float b); +EXPORT_SYMBOL(__subsf3); + +double __subdf3(double a, double b); +EXPORT_SYMBOL(__subdf3); + +float __mulsf3(float a, float b); +EXPORT_SYMBOL(__mulsf3); + +double __muldf3(double a, double b); +EXPORT_SYMBOL(__muldf3); + +float __divsf3(float a, float b); +EXPORT_SYMBOL(__divsf3); + +double __divdf3(double a, double b); +EXPORT_SYMBOL(__divdf3); + +float __negsf2(float a); +EXPORT_SYMBOL(__negsf2); + +double __negdf2(double a); +EXPORT_SYMBOL(__negdf2); + +double __extendsfdf2(float a); +EXPORT_SYMBOL(__extendsfdf2); + +float __truncdfsf2(double a); +EXPORT_SYMBOL(__truncdfsf2); + +int __fixsfsi(float a); +EXPORT_SYMBOL(__fixsfsi); + +int __fixdfsi(double a); +EXPORT_SYMBOL(__fixdfsi); + +long __fixsfdi(float a); +EXPORT_SYMBOL(__fixsfdi); + +long __fixdfdi(double a); +EXPORT_SYMBOL(__fixdfdi); + +unsigned int __fixunssfsi(float a); +EXPORT_SYMBOL(__fixunssfsi); + +unsigned int __fixunsdfsi(double a); +EXPORT_SYMBOL(__fixunsdfsi); + +unsigned long __fixunssfdi(float a); +EXPORT_SYMBOL(__fixunssfdi); + +unsigned long __fixunsdfdi(double a); +EXPORT_SYMBOL(__fixunsdfdi); + +float __floatsisf(int i); +EXPORT_SYMBOL(__floatsisf); + +double __floatsidf(int i); +EXPORT_SYMBOL(__floatsidf); + +float __floatdisf(long i); +EXPORT_SYMBOL(__floatdisf); + +double __floatdidf(long i); +EXPORT_SYMBOL(__floatdidf); + +float __floatunsisf(unsigned int i); +EXPORT_SYMBOL(__floatunsisf); + +double __floatunsidf(unsigned int i); +EXPORT_SYMBOL(__floatunsidf); + +float __floatundisf(unsigned long i); +EXPORT_SYMBOL(__floatundisf); + +double __floatundidf(unsigned long i); +EXPORT_SYMBOL(__floatundidf); + +int __unordsf2(float a, float b); +EXPORT_SYMBOL(__unordsf2); + +int __unorddf2(double a, double b); +EXPORT_SYMBOL(__unorddf2); + +int __eqsf2(float a, float b); +EXPORT_SYMBOL(__eqsf2); + +int __eqdf2(double a, double b); +EXPORT_SYMBOL(__eqdf2); + +int __nesf2(float a, float b); +EXPORT_SYMBOL(__nesf2); + +int __nedf2(double a, double b); +EXPORT_SYMBOL(__nedf2); + +int __gesf2(float a, float b); +EXPORT_SYMBOL(__gesf2); + +int __gedf2(double a, double b); +EXPORT_SYMBOL(__gedf2); + +int __ltsf2(float a, float b); +EXPORT_SYMBOL(__ltsf2); + +int __ltdf2(double a, double b); +EXPORT_SYMBOL(__ltdf2); + +int __lesf2(float a, float b); +EXPORT_SYMBOL(__lesf2); + +int __ledf2(double a, double b); +EXPORT_SYMBOL(__ledf2); + +int __gtsf2(float a, float b); +EXPORT_SYMBOL(__gtsf2); + +int __gtdf2(double a, double b); +EXPORT_SYMBOL(__gtdf2); + +float __powisf2(float a, int b); +EXPORT_SYMBOL(__powisf2); + +double __powidf2(double a, int b); +EXPORT_SYMBOL(__powidf2); + +#endif diff --git a/src/math/iir.toml b/src/math/iir.toml new file mode 100644 index 000000000000..145488fcccc9 --- /dev/null +++ b/src/math/iir.toml @@ -0,0 +1,6 @@ + [[module.entry]] + name = "IIR" + uuid = "B0CDCD9E-EF8B-404F-8480-0F287FC9D44D" + load_type = "3" + + index = __COUNTER__ diff --git a/src/math/iir_df1.c b/src/math/iir_df1.c new file mode 100644 index 000000000000..861c5cd2cf19 --- /dev/null +++ b/src/math/iir_df1.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <sof/common.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include <rtos/symbol.h> + +int iir_delay_size_df1(struct sof_eq_iir_header *config) +{ + int n = config->num_sections; /* One section uses two unit delays */ + + if (n > SOF_EQ_IIR_BIQUADS_MAX || n < 1) + return -EINVAL; + + return 4 * n * sizeof(int32_t); +} +EXPORT_SYMBOL(iir_delay_size_df1); + +int iir_init_coef_df1(struct iir_state_df1 *iir, + struct sof_eq_iir_header *config) +{ + iir->biquads = config->num_sections; + iir->biquads_in_series = config->num_sections_in_series; + iir->coef = ASSUME_ALIGNED(&config->biquads[0], 4); + + return 0; +} +EXPORT_SYMBOL(iir_init_coef_df1); + +void iir_init_delay_df1(struct iir_state_df1 *iir, int32_t **delay) +{ + /* Set state line of this IIR */ + iir->delay = *delay; + + /* Point to next IIR delay line start. */ + *delay += 4 * iir->biquads; +} +EXPORT_SYMBOL(iir_init_delay_df1); + +void iir_reset_df1(struct iir_state_df1 *iir) +{ + iir->biquads = 0; + iir->biquads_in_series = 0; + iir->coef = NULL; + /* Note: May need to know the beginning of dynamic allocation after so + * omitting setting iir->delay to NULL. + */ +} +EXPORT_SYMBOL(iir_reset_df1); diff --git a/src/math/iir_df1_generic.c b/src/math/iir_df1_generic.c new file mode 100644 index 000000000000..4b069eafb3d7 --- /dev/null +++ b/src/math/iir_df1_generic.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> + +#include <rtos/symbol.h> + +#if SOF_USE_HIFI(NONE, FILTER) + +/* + * Direct form I second order filter block (biquad) + * + * +----+ +---+ +-------+ + * X(z) ---o--->| b0 |---> + --+-------------o--->| g |--->| shift |---> Y(z) + * | +----+ ^ ^ | +---+ +-------+ + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | +----+ | | +----+ | + * o--->| b1 |---> + + <---| a1 |---o + * | +----+ ^ ^ +----+ | + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | ^ ^ | + * | +----+ | | +----+ | + * o--->| b2 |---> + +<--- | a2 |---o + * +----+ +----+ + * + * y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] + * the a1 a2 has been negated during calculation + */ + +/* Series DF1 IIR */ + +/* 32 bit data, 32 bit coefficients and 32 bit state variables */ + +int32_t iir_df1(struct iir_state_df1 *iir, int32_t x) +{ + int32_t in; + int32_t tmp; + int64_t out = 0; + int64_t acc; + int i; + int j; + int d = 0; /* Index to state */ + int c = 0; /* Index to coefficient a2 */ + int32_t *coefp = iir->coef; + int32_t *delay = iir->delay; + int nseries = iir->biquads_in_series; + + /* Bypass is set with number of biquads set to zero. */ + if (!iir->biquads) + return x; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + /* Delay order in state[] is {y(n - 2), y(n - 1), x(n - 2), x(n - 1)} */ + for (j = 0; j < iir->biquads; j += nseries) { + in = x; + for (i = 0; i < nseries; i++) { + /* Compute output: Delay is Q3.61 + * Q2.30 x Q1.31 -> Q3.61 + * Shift Q3.61 to Q3.31 with rounding, saturate to Q1.31 + */ + acc = ((int64_t)coefp[c]) * delay[d]; /* a2 * y(n - 2) */ + acc += ((int64_t)coefp[c + 1]) * delay[d + 1]; /* a1 * y(n - 1) */ + acc += ((int64_t)coefp[c + 2]) * delay[d + 2]; /* b2 * x(n - 2) */ + acc += ((int64_t)coefp[c + 3]) * delay[d + 3]; /* b1 * x(n - 1) */ + acc += ((int64_t)coefp[c + 4]) * in; /* b0 * x */ + tmp = (int32_t)sat_int32(Q_SHIFT_RND(acc, 61, 31)); + + /* update the delay value */ + delay[d] = delay[d + 1]; + delay[d + 1] = tmp; + delay[d + 2] = delay[d + 3]; + delay[d + 3] = in; + + /* Apply gain Q2.14 x Q1.31 -> Q3.45 */ + acc = ((int64_t)coefp[c + 6]) * tmp; /* Gain */ + + /* Apply biquad output shift right parameter + * simultaneously with Q3.45 to Q3.31 conversion. Then + * saturate to 32 bits Q1.31 and prepare for next + * biquad. + */ + acc = Q_SHIFT_RND(acc, 45 + coefp[c + 5], 31); + in = sat_int32(acc); + + /* Proceed to next biquad coefficients and delay + * lines. + */ + c += SOF_EQ_IIR_NBIQUAD; + d += IIR_DF1_NUM_STATE; + } + /* Output of previous section is in variable in */ + out += (int64_t)in; + } + return sat_int32(out); +} +EXPORT_SYMBOL(iir_df1); + +int32_t iir_df1_4th(struct iir_state_df1 *iir, int32_t x) +{ + int32_t in; + int32_t tmp; + int64_t acc; + int i; + int d = 0; /* Index to state */ + int c = 0; /* Index to coefficient a2 */ + int32_t *coefp = iir->coef; + int32_t *delay = iir->delay; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + /* Delay order in state[] is {y(n - 2), y(n - 1), x(n - 2), x(n - 1)} */ + in = x; + for (i = 0; i < SOF_IIR_DF1_4TH_NUM_BIQUADS; i++) { + /* Compute output: Delay is Q3.61 + * Q2.30 x Q1.31 -> Q3.61 + * Shift Q3.61 to Q3.31 with rounding, saturate to Q1.31 + */ + acc = ((int64_t)coefp[c]) * delay[d]; /* a2 * y(n - 2) */ + acc += ((int64_t)coefp[c + 1]) * delay[d + 1]; /* a1 * y(n - 1) */ + acc += ((int64_t)coefp[c + 2]) * delay[d + 2]; /* b2 * x(n - 2) */ + acc += ((int64_t)coefp[c + 3]) * delay[d + 3]; /* b1 * x(n - 1) */ + acc += ((int64_t)coefp[c + 4]) * in; /* b0 * x */ + tmp = (int32_t)sat_int32(Q_SHIFT_RND(acc, 61, 31)); + + /* update the delay value */ + delay[d] = delay[d + 1]; + delay[d + 1] = tmp; + delay[d + 2] = delay[d + 3]; + delay[d + 3] = in; + + /* Apply gain Q2.14 x Q1.31 -> Q3.45 */ + acc = ((int64_t)coefp[c + 6]) * tmp; /* Gain */ + + /* Apply biquad output shift right parameter + * simultaneously with Q3.45 to Q3.31 conversion. Then + * saturate to 32 bits Q1.31 and prepare for next + * biquad. + */ + acc = Q_SHIFT_RND(acc, 45 + coefp[c + 5], 31); + in = sat_int32(acc); + + /* Proceed to next biquad coefficients and delay + * lines. + */ + c += SOF_EQ_IIR_NBIQUAD; + d += IIR_DF1_NUM_STATE; + } + /* Output of previous section is in variable in */ + return in; +} +EXPORT_SYMBOL(iir_df1_4th); + +#endif diff --git a/src/math/iir_df1_hifi3.c b/src/math/iir_df1_hifi3.c new file mode 100644 index 000000000000..eddcc3f980ea --- /dev/null +++ b/src/math/iir_df1_hifi3.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Andrula Song <andrula.song@intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> +#include <sof/common.h> + +#include <rtos/symbol.h> + +#if SOF_USE_HIFI(3, FILTER) + +/* + * Direct form I second order filter block (biquad) + * + * +----+ +---+ +-------+ + * X(z) ---o--->| b0 |---> + --+-------------o--->| g |--->| shift |---> Y(z) + * | +----+ ^ ^ | +---+ +-------+ + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | +----+ | | +----+ | + * o--->| b1 |---> + + <---| a1 |---o + * | +----+ ^ ^ +----+ | + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | ^ ^ | + * | +----+ | | +----+ | + * o--->| b2 |---> + +<--- | a2 |---o + * +----+ +----+ + * + * y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] + * the a1 a2 has been negated during calculation + */ + +/* Series DF1 IIR */ + +/* 32 bit data, 32 bit coefficients and 32 bit state variables */ + +int32_t iir_df1(struct iir_state_df1 *iir, int32_t x) +{ + ae_int64 acc; + ae_valign coef_align; + ae_int32x2 coef_a2a1; + ae_int32x2 coef_b2b1; + ae_int32x2 coef_b0; + ae_int32x2 gain; + ae_int32x2 shift; + ae_int32x2 delay_y2y1; + ae_int32x2 delay_x2x1; + ae_int32 in; + ae_int32 tmp; + ae_int32x2 *coefp; + ae_int32x2 *delayp; + ae_int32 out = 0; + int32_t *delay_update; + int i; + int j; + int nseries = iir->biquads_in_series; + + /* Bypass is set with number of biquads set to zero. */ + if (!iir->biquads) + return x; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + coefp = (ae_int32x2 *)&iir->coef[0]; + delayp = (ae_int32x2 *)&iir->delay[0]; + for (j = 0; j < iir->biquads; j += nseries) { + /* the first for loop is for parallel EQs, and they have the same input */ + in = x; + for (i = 0; i < nseries; i++) { + /* Compute output: Delay is kept Q17.47 while multiply + * instruction gives Q2.30 x Q1.31 -> Q18.46. Need to + * shift delay line values right by one for same align + * as MAC. Store to delay line need to be shifted left + * by one similarly. + */ + coef_align = AE_LA64_PP(coefp); + AE_LA32X2_IP(coef_a2a1, coef_align, coefp); + AE_LA32X2_IP(coef_b2b1, coef_align, coefp); + AE_L32_IP(coef_b0, (ae_int32 *)coefp, 4); + AE_L32_IP(shift, (ae_int32 *)coefp, 4); + AE_L32_IP(gain, (ae_int32 *)coefp, 4); + + AE_L32X2_IP(delay_y2y1, delayp, 8); + AE_L32X2_IP(delay_x2x1, delayp, 8); + + acc = AE_MULF32R_HH(coef_a2a1, delay_y2y1); /* a2 * y(n - 2) */ + AE_MULAF32R_LL(acc, coef_a2a1, delay_y2y1); /* a1 * y(n - 1) */ + AE_MULAF32R_HH(acc, coef_b2b1, delay_x2x1); /* b2 * x(n - 2) */ + AE_MULAF32R_LL(acc, coef_b2b1, delay_x2x1); /* b1 * x(n - 1) */ + AE_MULAF32R_HH(acc, coef_b0, in); /* b0 * x */ + acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ + tmp = AE_ROUND32F48SSYM(acc); /* Round to Q1.31 */ + + /* update the state value */ + delay_update = (int32_t *)delayp - 4; + delay_update[0] = delay_update[1]; + delay_update[1] = tmp; + delay_update[2] = delay_update[3]; + delay_update[3] = in; + + /* Apply gain Q18.14 x Q1.31 -> Q34.30 */ + acc = AE_MULF32R_HH(gain, tmp); /* Gain */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + } + /* Output of previous section is in variable in */ + out = AE_F32_ADDS_F32(out, in); + } + return out; +} +EXPORT_SYMBOL(iir_df1); + +int32_t iir_df1_4th(struct iir_state_df1 *iir, int32_t x) +{ + ae_int64 acc; + ae_valign coef_align; + ae_int32x2 coef_a2a1; + ae_int32x2 coef_b2b1; + ae_int32x2 coef_b0; + ae_int32x2 gain; + ae_int32x2 shift; + ae_int32x2 delay_y2y1; + ae_int32x2 delay_x2x1; + ae_int32 in; + ae_int32 tmp; + ae_int32x2 *coefp; + ae_int32x2 *delayp; + int32_t *delay_update; + int i; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + coefp = (ae_int32x2 *)&iir->coef[0]; + delayp = (ae_int32x2 *)&iir->delay[0]; + in = x; + for (i = 0; i < SOF_IIR_DF1_4TH_NUM_BIQUADS; i++) { + /* Compute output: Delay is kept Q17.47 while multiply + * instruction gives Q2.30 x Q1.31 -> Q18.46. Need to + * shift delay line values right by one for same align + * as MAC. Store to delay line need to be shifted left + * by one similarly. + */ + coef_align = AE_LA64_PP(coefp); + AE_LA32X2_IP(coef_a2a1, coef_align, coefp); + AE_LA32X2_IP(coef_b2b1, coef_align, coefp); + AE_L32_IP(coef_b0, (ae_int32 *)coefp, 4); + AE_L32_IP(shift, (ae_int32 *)coefp, 4); + AE_L32_IP(gain, (ae_int32 *)coefp, 4); + + AE_L32X2_IP(delay_y2y1, delayp, 8); + AE_L32X2_IP(delay_x2x1, delayp, 8); + + acc = AE_MULF32R_HH(coef_a2a1, delay_y2y1); /* a2 * y(n - 2) */ + AE_MULAF32R_LL(acc, coef_a2a1, delay_y2y1); /* a1 * y(n - 1) */ + AE_MULAF32R_HH(acc, coef_b2b1, delay_x2x1); /* b2 * x(n - 2) */ + AE_MULAF32R_LL(acc, coef_b2b1, delay_x2x1); /* b1 * x(n - 1) */ + AE_MULAF32R_HH(acc, coef_b0, in); /* b0 * x */ + acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ + tmp = AE_ROUND32F48SSYM(acc); /* Round to Q1.31 */ + + /* update the state value */ + delay_update = (int32_t *)delayp - 4; + delay_update[0] = delay_update[1]; + delay_update[1] = tmp; + delay_update[2] = delay_update[3]; + delay_update[3] = in; + + /* Apply gain Q18.14 x Q1.31 -> Q34.30 */ + acc = AE_MULF32R_HH(gain, tmp); /* Gain */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + } + return in; +} +EXPORT_SYMBOL(iir_df1_4th); + +#endif diff --git a/src/math/iir_df1_hifi4.c b/src/math/iir_df1_hifi4.c new file mode 100644 index 000000000000..945fd67af5bc --- /dev/null +++ b/src/math/iir_df1_hifi4.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2024 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> +#include <sof/common.h> + +#include <rtos/symbol.h> + +#if SOF_USE_HIFI(4, FILTER) + +/* + * Direct form I second order filter block (biquad) + * + * +----+ +---+ +-------+ + * X(z) ---o--->| b0 |---> + --+-------------o--->| g |--->| shift |---> Y(z) + * | +----+ ^ ^ | +---+ +-------+ + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | +----+ | | +----+ | + * o--->| b1 |---> + + <---| a1 |---o + * | +----+ ^ ^ +----+ | + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | ^ ^ | + * | +----+ | | +----+ | + * o--->| b2 |---> + +<--- | a2 |---o + * +----+ +----+ + * + * y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] + * the a1 a2 has been negated during calculation + */ + +/* Series DF1 IIR */ + +/* 32 bit data, 32 bit coefficients and 32 bit state variables */ + +int32_t iir_df1(struct iir_state_df1 *iir, int32_t x) +{ + ae_valign coef_align; + ae_valign data_r_align; + ae_valign data_w_align = AE_ZALIGN64(); + ae_f64 acc; + ae_int32x2 delay_y2y1; + ae_int32x2 delay_x2x1; + ae_int32x2 coef_a2a1; + ae_int32x2 coef_b2b1; + ae_int32x2 coef_b0; + ae_int32x2 gain; + ae_int32x2 shift; + ae_int32 in; + ae_int32 out = 0; + ae_int32x2 *coefp = (ae_int32x2 *)iir->coef; + ae_int32x2 *delay_r = (ae_int32x2 *)iir->delay; + ae_int32x2 *delay_w = delay_r; + int i; + int j; + int nseries = iir->biquads_in_series; + + /* Bypass is set with number of biquads set to zero. */ + if (!iir->biquads) + return x; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + /* Delay order in state[] is {y(n - 2), y(n - 1), x(n - 2), x(n - 1)} */ + data_r_align = AE_LA64_PP(delay_r); + for (j = 0; j < iir->biquads; j += nseries) { + in = x; + for (i = 0; i < nseries; i++) { + /* Load data */ + AE_LA32X2_IP(delay_y2y1, data_r_align, delay_r); + AE_LA32X2_IP(delay_x2x1, data_r_align, delay_r); + + /* Load coefficients */ + coef_align = AE_LA64_PP(coefp); + AE_LA32X2_IP(coef_a2a1, coef_align, coefp); + AE_LA32X2_IP(coef_b2b1, coef_align, coefp); + AE_L32_IP(coef_b0, (ae_int32 *)coefp, 4); + AE_L32_IP(shift, (ae_int32 *)coefp, 4); + AE_L32_IP(gain, (ae_int32 *)coefp, 4); + + acc = AE_MULF32RA_HH(coef_b0, in); /* acc = b0 * in */ + AE_MULAAFD32RA_HH_LL(acc, coef_a2a1, delay_y2y1); /* + a2 * y2 + a1 * y1 */ + AE_MULAAFD32RA_HH_LL(acc, coef_b2b1, delay_x2x1); /* + b2 * x2 + b1 * x1 */ + AE_PKSR32(delay_y2y1, acc, 1); /* y2 = y1, y1 = acc(q1.31) */ + delay_x2x1 = AE_SEL32_LL(delay_x2x1, in); /* x2 = x1, x1 = in */ + + /* Store data */ + AE_SA32X2_IP(delay_y2y1, data_w_align, delay_w); + AE_SA32X2_IP(delay_x2x1, data_w_align, delay_w); + + /* Apply gain */ + acc = AE_MULF32R_LL(gain, delay_y2y1); /* acc = gain * y1 */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + } + /* Output of previous section is in variable in */ + out = AE_F32_ADDS_F32(out, in); + } + + AE_SA64POS_FP(data_w_align, delay_w); + return out; +} +EXPORT_SYMBOL(iir_df1); + +int32_t iir_df1_4th(struct iir_state_df1 *iir, int32_t x) +{ + ae_valign coef_align; + ae_valign data_r_align; + ae_valign data_w_align = AE_ZALIGN64(); + ae_f64 acc; + ae_int32x2 delay_y2y1; + ae_int32x2 delay_x2x1; + ae_int32x2 coef_a2a1; + ae_int32x2 coef_b2b1; + ae_int32x2 coef_b0; + ae_int32x2 gain; + ae_int32x2 shift; + ae_int32 in; + ae_int32x2 *coefp = (ae_int32x2 *)iir->coef; + ae_int32x2 *delay_r = (ae_int32x2 *)iir->delay; + ae_int32x2 *delay_w = delay_r; + int i; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + /* Delay order in state[] is {y(n - 2), y(n - 1), x(n - 2), x(n - 1)} */ + data_r_align = AE_LA64_PP(delay_r); + in = x; + for (i = 0; i < SOF_IIR_DF1_4TH_NUM_BIQUADS; i++) { + /* Load data */ + AE_LA32X2_IP(delay_y2y1, data_r_align, delay_r); + AE_LA32X2_IP(delay_x2x1, data_r_align, delay_r); + + /* Load coefficients */ + coef_align = AE_LA64_PP(coefp); + AE_LA32X2_IP(coef_a2a1, coef_align, coefp); + AE_LA32X2_IP(coef_b2b1, coef_align, coefp); + AE_L32_IP(coef_b0, (ae_int32 *)coefp, 4); + AE_L32_IP(shift, (ae_int32 *)coefp, 4); + AE_L32_IP(gain, (ae_int32 *)coefp, 4); + + acc = AE_MULF32RA_HH(coef_b0, in); /* acc = b0 * in */ + AE_MULAAFD32RA_HH_LL(acc, coef_a2a1, delay_y2y1); /* + a2 * y2 + a1 * y1 */ + AE_MULAAFD32RA_HH_LL(acc, coef_b2b1, delay_x2x1); /* + b2 * x2 + b1 * x1 */ + AE_PKSR32(delay_y2y1, acc, 1); /* y2 = y1, y1 = acc(q1.31) */ + delay_x2x1 = AE_SEL32_LL(delay_x2x1, in); /* x2 = x1, x1 = in */ + + /* Store data */ + AE_SA32X2_IP(delay_y2y1, data_w_align, delay_w); + AE_SA32X2_IP(delay_x2x1, data_w_align, delay_w); + + /* Apply gain */ + acc = AE_MULF32R_LL(gain, delay_y2y1); /* acc = gain * y1 */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + } + AE_SA64POS_FP(data_w_align, delay_w); + return in; +} +EXPORT_SYMBOL(iir_df1_4th); + +#endif diff --git a/src/math/iir_df1_hifi5.c b/src/math/iir_df1_hifi5.c new file mode 100644 index 000000000000..ca331d28c7fa --- /dev/null +++ b/src/math/iir_df1_hifi5.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2024 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df1.h> +#include <user/eq.h> +#include <sof/common.h> + +#include <rtos/symbol.h> + +#if SOF_USE_MIN_HIFI(5, FILTER) + +/* + * Direct form I second order filter block (biquad) + * + * +----+ +---+ +-------+ + * X(z) ---o--->| b0 |---> + --+-------------o--->| g |--->| shift |---> Y(z) + * | +----+ ^ ^ | +---+ +-------+ + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | +----+ | | +----+ | + * o--->| b1 |---> + + <---| a1 |---o + * | +----+ ^ ^ +----+ | + * | | | | + * +------+ | | +------+ + * | z^-1 | | | | z^-1 | + * +------+ | | +------+ + * | ^ ^ | + * | +----+ | | +----+ | + * o--->| b2 |---> + +<--- | a2 |---o + * +----+ +----+ + * + * y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] + * the a1 a2 has been negated during calculation + */ + +/* Series DF1 IIR */ + +/* 32 bit data, 32 bit coefficients and 32 bit state variables */ + +int32_t iir_df1(struct iir_state_df1 *iir, int32_t x) +{ + ae_valignx2 coef_align; + ae_valignx2 data_r_align; + ae_valignx2 data_w_align = AE_ZALIGN128(); + ae_f64 acc; + ae_int32x2 delay_y2y1; + ae_int32x2 delay_x2x1; + ae_int32x2 coef_a2a1; + ae_int32x2 coef_b2b1; + ae_int32x2 coef_b0; + ae_int32x2 gain; + ae_int32x2 shift; + ae_int32 in; + ae_int32 out = 0; + ae_int32x4 *coefp = (ae_int32x4 *)iir->coef; + ae_int32x4 *delay_r = (ae_int32x4 *)iir->delay; + ae_int32x4 *delay_w = delay_r; + int i; + int j; + int nseries = iir->biquads_in_series; + + /* Bypass is set with number of biquads set to zero. */ + if (!iir->biquads) + return x; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + /* Delay order in state[] is {y(n - 2), y(n - 1), x(n - 2), x(n - 1)} */ + data_r_align = AE_LA128_PP(delay_r); + for (j = 0; j < iir->biquads; j += nseries) { + in = x; + for (i = 0; i < nseries; i++) { + /* Load data */ + AE_LA32X2X2_IP(delay_y2y1, delay_x2x1, data_r_align, delay_r); + + /* Load coefficients */ + coef_align = AE_LA128_PP(coefp); + AE_LA32X2X2_IP(coef_a2a1, coef_b2b1, coef_align, coefp); + AE_L32_IP(coef_b0, (ae_int32 *)coefp, 4); + AE_L32_IP(shift, (ae_int32 *)coefp, 4); + AE_L32_IP(gain, (ae_int32 *)coefp, 4); + + acc = AE_MULF32RA_HH(coef_b0, in); /* acc = b0 * in */ + AE_MULAAFD32RA_HH_LL(acc, coef_a2a1, delay_y2y1); /* + a2 * y2 + a1 * y1 */ + AE_MULAAFD32RA_HH_LL(acc, coef_b2b1, delay_x2x1); /* + b2 * x2 + b1 * x1 */ + AE_PKSR32(delay_y2y1, acc, 1); /* y2 = y1, y1 = acc(q1.31) */ + delay_x2x1 = AE_SEL32_LL(delay_x2x1, in); /* x2 = x1, x1 = in */ + + /* Store data */ + AE_SA32X2X2_IP(delay_y2y1, delay_x2x1, data_w_align, delay_w); + + /* Apply gain */ + acc = AE_MULF32R_LL(gain, delay_y2y1); /* acc = gain * y1 */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + } + /* Output of previous section is in variable in */ + out = AE_F32_ADDS_F32(out, in); + } + + AE_SA128POS_FP(data_w_align, delay_w); + return out; +} +EXPORT_SYMBOL(iir_df1); + +int32_t iir_df1_4th(struct iir_state_df1 *iir, int32_t x) +{ + ae_valignx2 coef_align; + ae_valignx2 data_r_align; + ae_valignx2 data_w_align = AE_ZALIGN128(); + ae_f64 acc; + ae_int32x2 delay_y2y1; + ae_int32x2 delay_x2x1; + ae_int32x2 coef_a2a1; + ae_int32x2 coef_b2b1; + ae_int32x2 coef_b0; + ae_int32x2 gain; + ae_int32x2 shift; + ae_int32 in; + ae_int32x4 *coefp = (ae_int32x4 *)iir->coef; + ae_int32x4 *delay_r = (ae_int32x4 *)iir->delay; + ae_int32x4 *delay_w = delay_r; + int i; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + /* Delay order in state[] is {y(n - 2), y(n - 1), x(n - 2), x(n - 1)} */ + data_r_align = AE_LA128_PP(delay_r); + in = x; + for (i = 0; i < SOF_IIR_DF1_4TH_NUM_BIQUADS; i++) { + /* Load data */ + AE_LA32X2X2_IP(delay_y2y1, delay_x2x1, data_r_align, delay_r); + + /* Load coefficients */ + coef_align = AE_LA128_PP(coefp); + AE_LA32X2X2_IP(coef_a2a1, coef_b2b1, coef_align, coefp); + AE_L32_IP(coef_b0, (ae_int32 *)coefp, 4); + AE_L32_IP(shift, (ae_int32 *)coefp, 4); + AE_L32_IP(gain, (ae_int32 *)coefp, 4); + + acc = AE_MULF32RA_HH(coef_b0, in); /* acc = b0 * in */ + AE_MULAAFD32RA_HH_LL(acc, coef_a2a1, delay_y2y1); /* + a2 * y2 + a1 * y1 */ + AE_MULAAFD32RA_HH_LL(acc, coef_b2b1, delay_x2x1); /* + b2 * x2 + b1 * x1 */ + AE_PKSR32(delay_y2y1, acc, 1); /* y2 = y1, y1 = acc(q1.31) */ + delay_x2x1 = AE_SEL32_LL(delay_x2x1, in); /* x2 = x1, x1 = in */ + + /* Store data */ + AE_SA32X2X2_IP(delay_y2y1, delay_x2x1, data_w_align, delay_w); + + /* Apply gain */ + acc = AE_MULF32R_LL(gain, delay_y2y1); /* acc = gain * y1 */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + } + + AE_SA128POS_FP(data_w_align, delay_w); + return in; +} +EXPORT_SYMBOL(iir_df1_4th); + +#endif diff --git a/src/math/iir_df2t.c b/src/math/iir_df2t.c new file mode 100644 index 000000000000..b2adb69be03f --- /dev/null +++ b/src/math/iir_df2t.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/common.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df2t.h> +#include <user/eq.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +int iir_delay_size_df2t(struct sof_eq_iir_header *config) +{ + int n = config->num_sections; /* One section uses two unit delays */ + + if (n > SOF_EQ_IIR_BIQUADS_MAX || n < 1) + return -EINVAL; + + return 2 * n * sizeof(int64_t); +} + +int iir_init_coef_df2t(struct iir_state_df2t *iir, + struct sof_eq_iir_header *config) +{ + iir->biquads = config->num_sections; + iir->biquads_in_series = config->num_sections_in_series; + iir->coef = ASSUME_ALIGNED(&config->biquads[0], 4); + + return 0; +} + +void iir_init_delay_df2t(struct iir_state_df2t *iir, int64_t **delay) +{ + /* Set delay line of this IIR */ + iir->delay = *delay; + + /* Point to next IIR delay line start. The DF2T biquad uses two + * memory elements. + */ + *delay += 2 * iir->biquads; +} + +void iir_reset_df2t(struct iir_state_df2t *iir) +{ + iir->biquads = 0; + iir->biquads_in_series = 0; + iir->coef = NULL; + /* Note: May need to know the beginning of dynamic allocation after so + * omitting setting iir->delay to NULL. + */ +} + diff --git a/src/math/iir_df2t_generic.c b/src/math/iir_df2t_generic.c new file mode 100644 index 000000000000..1e1f9385a3aa --- /dev/null +++ b/src/math/iir_df2t_generic.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/iir_df2t.h> +#include <sof/common.h> +#include <user/eq.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#if SOF_USE_HIFI(NONE, FILTER) + +/* + * Direct form II transposed second order filter block (biquad) + * + * +----+ +---+ +-------+ + * X(z) ---o--->| b0 |---> + -------------o--->| g |--->| shift |---> Y(z) + * | +----+ ^ | +---+ +-------+ + * | | | + * | +------+ | + * | | z^-1 | | + * | +------+ | + * | ^ | + * | +----+ | +----+ | + * o--->| b1 |---> + <---| a1 |---o + * | +----+ ^ +----+ | + * | | | + * | +------+ | + * | | z^-1 | | + * | +------+ | + * | ^ | + * | +----+ | +----+ | + * o--->| b2 |---> + <---| a2 |---+ + * +----+ +----+ + * + */ + +/* Series DF2T IIR */ + +/* 32 bit data, 32 bit coefficients and 64 bit state variables */ + +int32_t iir_df2t(struct iir_state_df2t *iir, int32_t x) +{ + int32_t in; + int32_t tmp; + int64_t acc; + int32_t out = 0; + int i; + int j; + int d = 0; /* Index to delays */ + int c = 0; /* Index to coefficient a2 */ + + /* Bypass is set with number of biquads set to zero. */ + if (!iir->biquads) + return x; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + for (j = 0; j < iir->biquads; j += iir->biquads_in_series) { + /* the first for loop is for parallel EQs, and they have the same input */ + in = x; + for (i = 0; i < iir->biquads_in_series; i++) { + /* Compute output: Delay is Q3.61 + * Q2.30 x Q1.31 -> Q3.61 + * Shift Q3.61 to Q3.31 with rounding, saturate to Q1.31 + */ + acc = ((int64_t)iir->coef[c + 4]) * in + iir->delay[d]; /* Coef b0 */ + tmp = (int32_t)sat_int32(Q_SHIFT_RND(acc, 61, 31)); + + /* Compute first delay */ + acc = iir->delay[d + 1]; + acc += ((int64_t)iir->coef[c + 3]) * in; /* Coef b1 */ + acc += ((int64_t)iir->coef[c + 1]) * tmp; /* Coef a1 */ + iir->delay[d] = acc; + + /* Compute second delay */ + acc = ((int64_t)iir->coef[c + 2]) * in; /* Coef b2 */ + acc += ((int64_t)iir->coef[c]) * tmp; /* Coef a2 */ + iir->delay[d + 1] = acc; + + /* Apply gain Q2.14 x Q1.31 -> Q3.45 */ + acc = ((int64_t)iir->coef[c + 6]) * tmp; /* Gain */ + + /* Apply biquad output shift right parameter + * simultaneously with Q3.45 to Q3.31 conversion. Then + * saturate to 32 bits Q1.31 and prepare for next + * biquad. + */ + acc = Q_SHIFT_RND(acc, 45 + iir->coef[c + 5], 31); + in = sat_int32(acc); + + /* Proceed to next biquad coefficients and delay + * lines. + */ + c += SOF_EQ_IIR_NBIQUAD; + d += IIR_DF2T_NUM_DELAYS; + } + /* Output of previous section is in variable in */ + out = sat_int32((int64_t)out + in); + } + return out; +} + +#endif diff --git a/src/math/iir_df2t_hifi3.c b/src/math/iir_df2t_hifi3.c new file mode 100644 index 000000000000..13bddb32a9e6 --- /dev/null +++ b/src/math/iir_df2t_hifi3.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <sof/audio/format.h> +#include <sof/math/iir_df2t.h> +#include <user/eq.h> + +#if SOF_USE_MIN_HIFI(3, FILTER) + +#include <xtensa/tie/xt_hifi3.h> + +/* + * Direct form II transposed second order filter block (biquad) + * + * +----+ +---+ +-------+ + * X(z) ---o--->| b0 |---> + -------------o--->| g |--->| shift |---> Y(z) + * | +----+ ^ | +---+ +-------+ + * | | | + * | +------+ | + * | | z^-1 | | + * | +------+ | + * | ^ | + * | +----+ | +----+ | + * o--->| b1 |---> + <---| a1 |---o + * | +----+ ^ +----+ | + * | | | + * | +------+ | + * | | z^-1 | | + * | +------+ | + * | ^ | + * | +----+ | +----+ | + * o--->| b2 |---> + <---| a2 |---+ + * +----+ +----+ + * + */ + +/* Series DF2T IIR */ + +/* 32 bit data, 32 bit coefficients and 64 bit state variables */ + +int32_t iir_df2t(struct iir_state_df2t *iir, int32_t x) +{ + ae_f64 acc; + ae_valign align; + ae_f32x2 coef_a2a1; + ae_f32x2 coef_b2b1; + ae_f32x2 coef_b0shift; + ae_f32x2 gain; + ae_f32 in; + ae_f32 tmp; + ae_f32x2 *coefp; + ae_f64 *delayp; + ae_f32 out = 0; + int i; + int j; + int shift; + int nseries = iir->biquads_in_series; + + /* Bypass is set with number of biquads set to zero. */ + if (!iir->biquads) + return x; + + /* Coefficients order in coef[] is {a2, a1, b2, b1, b0, shift, gain} */ + coefp = (ae_f32x2 *)&iir->coef[0]; + delayp = (ae_f64 *)&iir->delay[0]; + for (j = 0; j < iir->biquads; j += nseries) { + /* the first for loop is for parallel EQs, and they have the same input */ + in = x; + for (i = 0; i < nseries; i++) { + /* Compute output: Delay is kept Q17.47 while multiply + * instruction gives Q2.30 x Q1.31 -> Q18.46. Need to + * shift delay line values right by one for same align + * as MAC. Store to delay line need to be shifted left + * by one similarly. + */ + align = AE_LA64_PP(coefp); + AE_LA32X2_IP(coef_a2a1, align, coefp); + AE_LA32X2_IP(coef_b2b1, align, coefp); + AE_LA32X2_IP(coef_b0shift, align, coefp); + AE_LA32X2_IP(gain, align, coefp); + + acc = AE_SRAI64(*delayp, 1); /* Convert d0 to Q18.46 */ + delayp++; /* Point to d1 */ + AE_MULAF32R_HH(acc, coef_b0shift, in); /* Coef b0 */ + acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ + tmp = AE_ROUND32F48SSYM(acc); /* Round to Q1.31 */ + + /* Compute 1st delay d0 */ + acc = AE_SRAI64(*delayp, 1); /* Convert d1 to Q18.46 */ + delayp--; /* Point to d0 */ + AE_MULAF32R_LL(acc, coef_b2b1, in); /* Coef b1 */ + AE_MULAF32R_LL(acc, coef_a2a1, tmp); /* Coef a1 */ + acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ + *delayp = acc; /* Store d0 */ + delayp++; /* Point to d1 */ + + /* Compute delay d1 */ + acc = AE_MULF32R_HH(coef_b2b1, in); /* Coef b2 */ + AE_MULAF32R_HH(acc, coef_a2a1, tmp); /* Coef a2 */ + acc = AE_SLAI64S(acc, 1); /* Convert to Q17.47 */ + *delayp = acc; /* Store d1 */ + + /* Apply gain Q18.14 x Q1.31 -> Q34.30 */ + acc = AE_MULF32R_HH(gain, tmp); /* Gain */ + acc = AE_SLAI64S(acc, 17); /* Convert to Q17.47 */ + + /* Apply biquad output shift right parameter and then + * round and saturate to 32 bits Q1.31. + */ + shift = AE_SEL32_LL(coef_b0shift, coef_b0shift); + acc = AE_SRAA64(acc, shift); + in = AE_ROUND32F48SSYM(acc); + + /* Proceed to next biquad coefficients and delay + * lines. The coefp needs rewind by one int32_t + * due to odd number of words in coefficient block. + */ + delayp++; + coefp = (ae_f32x2 *)((int32_t *)coefp - 1); + } + /* Output of previous section is in variable in */ + out = AE_F32_ADDS_F32(out, in); + } + return out; +} + +#endif diff --git a/src/math/iir_llext/CMakeLists.txt b/src/math/iir_llext/CMakeLists.txt new file mode 100644 index 000000000000..f6f2a7c328fa --- /dev/null +++ b/src/math/iir_llext/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_MATH_IIR_DF1) + set(df1 ../iir_df1.c ../iir_df1_generic.c ../iir_df1_hifi3.c + ../iir_df1_hifi4.c ../iir_df1_hifi5.c) +else() + set(df1 "") +endif() + +if(CONFIG_MATH_IIR_DF2T) + set(df2t ../iir_df2t.c ../iir_df2t_generic.c ../iir_df2t_hifi3.c) +else() + set(df2t "") +endif() + +if(CONFIG_MATH_IIR_DF1 OR CONFIG_MATH_IIR_DF2T) + sof_llext_build("aux1_iir" + SOURCES iir.c ${df1} ${df2t} + LIB openmodules + ) +endif() diff --git a/src/math/iir_llext/iir.c b/src/math/iir_llext/iir.c new file mode 100644 index 000000000000..7891bd8fc5b1 --- /dev/null +++ b/src/math/iir_llext/iir.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +/* modular: llext dynamic link */ + +#include <sof/compiler_attributes.h> +#include <sof/lib/uuid.h> +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { + SOF_LLEXT_AUX_MANIFEST("IIR", NULL, SOF_REG_UUID(iir)), +}; + +SOF_LLEXT_BUILDINFO; diff --git a/src/math/iir_llext/llext.toml.h b/src/math/iir_llext/llext.toml.h new file mode 100644 index 000000000000..89669daea077 --- /dev/null +++ b/src/math/iir_llext/llext.toml.h @@ -0,0 +1,5 @@ +#include <tools/rimage/config/platform.toml> +#include "../iir.toml" + +[module] +count = __COUNTER__ diff --git a/src/math/log_10.c b/src/math/log_10.c new file mode 100644 index 000000000000..61a885551883 --- /dev/null +++ b/src/math/log_10.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-3-Clause/ +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> +// +// + +#include <sof/math/log.h> +#include <sof/audio/format.h> +/** + * Base-10 logarithm log10(x) + * + * loge = (u) computes the base-10 logarithm of + * u using lookup table. + * input u must be scalar/real number and positive + * + * +------------------+-----------------+--------+--------+ + * | inpfxp |log10(returntype)| inpfxp | loge | + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 0 | 0 | 32 | 28 | 0 | 32.0 | 4.28 | + * +------------------+-----------------+--------+--------+ + * Arguments : uint32_t numerator [1 to 4294967295, Q32.0] + * Return Type : uint32_t UQ4.28 [0 to 9.6329499409] + */ +uint32_t log10_int32(uint32_t numerator) +{ + return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) * + ONE_OVER_LOG2_10, 63, 32)); +} diff --git a/src/math/log_e.c b/src/math/log_e.c new file mode 100644 index 000000000000..14d899265bb6 --- /dev/null +++ b/src/math/log_e.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> +// +// + +#include <sof/math/log.h> +#include <sof/audio/format.h> +/** + * Base-e logarithm loge(x) + * + * loge = (u) computes the base-e logarithm of + * u using lookup table. + * input u must be scalar/real number and positive + * + * +------------------+-----------------+--------+--------+ + * | inpfxp |loge (returntype)| inpfxp | loge | + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 0 | 0 | 32 | 27 | 0 | 32.0 | 5.27 | + * +------------------+-----------------+--------+--------+ + * + * Arguments : uint32_t numerator [1 to 4294967295- Q32.0] + * Return Type : uint32_t UQ5.27 [ 0 to 22.1808076352] + */ +uint32_t ln_int32(uint32_t numerator) +{ + return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) * + ONE_OVER_LOG2_E, 64, 32)); +} diff --git a/src/math/lut_trig.c b/src/math/lut_trig.c new file mode 100644 index 000000000000..a40729327932 --- /dev/null +++ b/src/math/lut_trig.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016-2024 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/lut_trig.h> +#include <rtos/symbol.h> +#include <stdint.h> + +#define SOFM_LUT_SINE_C_Q20 341782638 /* 2 * SINE_NQUART / pi in Q12.20 */ +#define SOFM_LUT_SINE_NQUART 512 /* Must be 2^N */ +#define SOFM_LUT_SINE_SIZE (SOFM_LUT_SINE_NQUART + 1) + +/* Sine values 0 to pi/2, calculated with Octave + * w = linspace(0, pi/2, 513); + * s = 2^16; + * x = min(round(s * sin(w)), s - 1); + */ + +static const uint16_t sofm_lut_sine_table_s16[SOFM_LUT_SINE_SIZE] = { + 0, 201, 402, 603, 804, 1005, 1206, 1407, 1608, 1809, 2010, + 2211, 2412, 2613, 2814, 3015, 3216, 3417, 3617, 3818, 4019, 4219, + 4420, 4621, 4821, 5022, 5222, 5422, 5623, 5823, 6023, 6224, 6424, + 6624, 6824, 7024, 7224, 7423, 7623, 7823, 8022, 8222, 8421, 8621, + 8820, 9019, 9218, 9417, 9616, 9815, 10014, 10212, 10411, 10609, 10808, + 11006, 11204, 11402, 11600, 11798, 11996, 12193, 12391, 12588, 12785, 12983, + 13180, 13376, 13573, 13770, 13966, 14163, 14359, 14555, 14751, 14947, 15143, + 15338, 15534, 15729, 15924, 16119, 16314, 16508, 16703, 16897, 17091, 17285, + 17479, 17673, 17867, 18060, 18253, 18446, 18639, 18832, 19024, 19216, 19409, + 19600, 19792, 19984, 20175, 20366, 20557, 20748, 20939, 21129, 21320, 21510, + 21699, 21889, 22078, 22268, 22457, 22645, 22834, 23022, 23210, 23398, 23586, + 23774, 23961, 24148, 24335, 24521, 24708, 24894, 25080, 25265, 25451, 25636, + 25821, 26005, 26190, 26374, 26558, 26742, 26925, 27108, 27291, 27474, 27656, + 27838, 28020, 28202, 28383, 28564, 28745, 28926, 29106, 29286, 29466, 29645, + 29824, 30003, 30182, 30360, 30538, 30716, 30893, 31071, 31248, 31424, 31600, + 31776, 31952, 32127, 32303, 32477, 32652, 32826, 33000, 33173, 33347, 33520, + 33692, 33865, 34037, 34208, 34380, 34551, 34721, 34892, 35062, 35231, 35401, + 35570, 35738, 35907, 36075, 36243, 36410, 36577, 36744, 36910, 37076, 37241, + 37407, 37572, 37736, 37900, 38064, 38228, 38391, 38554, 38716, 38878, 39040, + 39201, 39362, 39523, 39683, 39843, 40002, 40161, 40320, 40478, 40636, 40794, + 40951, 41108, 41264, 41420, 41576, 41731, 41886, 42040, 42194, 42348, 42501, + 42654, 42806, 42958, 43110, 43261, 43412, 43562, 43713, 43862, 44011, 44160, + 44308, 44456, 44604, 44751, 44898, 45044, 45190, 45335, 45480, 45625, 45769, + 45912, 46056, 46199, 46341, 46483, 46624, 46765, 46906, 47046, 47186, 47325, + 47464, 47603, 47741, 47878, 48015, 48152, 48288, 48424, 48559, 48694, 48828, + 48962, 49095, 49228, 49361, 49493, 49624, 49756, 49886, 50016, 50146, 50275, + 50404, 50532, 50660, 50787, 50914, 51041, 51166, 51292, 51417, 51541, 51665, + 51789, 51911, 52034, 52156, 52277, 52398, 52519, 52639, 52759, 52878, 52996, + 53114, 53232, 53349, 53465, 53581, 53697, 53812, 53926, 54040, 54154, 54267, + 54379, 54491, 54603, 54714, 54824, 54934, 55043, 55152, 55260, 55368, 55476, + 55582, 55689, 55794, 55900, 56004, 56108, 56212, 56315, 56418, 56520, 56621, + 56722, 56823, 56923, 57022, 57121, 57219, 57317, 57414, 57511, 57607, 57703, + 57798, 57892, 57986, 58079, 58172, 58265, 58356, 58448, 58538, 58628, 58718, + 58807, 58896, 58983, 59071, 59158, 59244, 59330, 59415, 59499, 59583, 59667, + 59750, 59832, 59914, 59995, 60075, 60156, 60235, 60314, 60392, 60470, 60547, + 60624, 60700, 60776, 60851, 60925, 60999, 61072, 61145, 61217, 61288, 61359, + 61429, 61499, 61568, 61637, 61705, 61772, 61839, 61906, 61971, 62036, 62101, + 62165, 62228, 62291, 62353, 62415, 62476, 62536, 62596, 62655, 62714, 62772, + 62830, 62886, 62943, 62998, 63054, 63108, 63162, 63215, 63268, 63320, 63372, + 63423, 63473, 63523, 63572, 63621, 63668, 63716, 63763, 63809, 63854, 63899, + 63944, 63987, 64031, 64073, 64115, 64156, 64197, 64237, 64277, 64316, 64354, + 64392, 64429, 64465, 64501, 64536, 64571, 64605, 64639, 64672, 64704, 64735, + 64766, 64797, 64827, 64856, 64884, 64912, 64940, 64967, 64993, 65018, 65043, + 65067, 65091, 65114, 65137, 65159, 65180, 65200, 65220, 65240, 65259, 65277, + 65294, 65311, 65328, 65343, 65358, 65373, 65387, 65400, 65413, 65425, 65436, + 65447, 65457, 65467, 65476, 65484, 65492, 65499, 65505, 65511, 65516, 65521, + 65525, 65528, 65531, 65533, 65535, 65535, 65535 +}; + +/* Sine lookup table read */ +static inline int32_t sofm_sine_lookup_16b(int idx) +{ + uint16_t s; + int i1; + + i1 = idx & (2 * SOFM_LUT_SINE_NQUART - 1); + if (i1 > SOFM_LUT_SINE_NQUART) + i1 = 2 * SOFM_LUT_SINE_NQUART - i1; + + s = sofm_lut_sine_table_s16[i1]; + if (idx > 2 * SOFM_LUT_SINE_NQUART) + return -((int32_t)s); + + return (int32_t)s; +} + +/* Compute fixed point sine with table lookup and interpolation */ +int16_t sofm_lut_sin_fixed_16b(int32_t w) +{ + int64_t idx; + int32_t sine; + int32_t frac; + int32_t delta; + int32_t s0; + int32_t s1; + int64_t idx_tmp; + + /* Q4.28 x Q12.20 -> Q16.48 --> Q16.31*/ + idx_tmp = ((int64_t)w * SOFM_LUT_SINE_C_Q20) >> 17; + idx = (idx_tmp >> 31); /* Shift to Q0 */ + frac = (int32_t)(idx_tmp - (idx << 31)); /* Get fraction Q1.31*/ + s0 = sofm_sine_lookup_16b(idx); /* Q1.16 */ + s1 = sofm_sine_lookup_16b(idx + 1); /* Q1.16 */ + delta = s1 - s0; /* Q1.16 */ + sine = s0 + q_mults_32x32(frac, delta, Q_SHIFT_BITS_64(31, 16, 16)); /* Q1.16 */ + return sat_int16((sine + 1) >> 1); /* Round to Q1.15 */ +} +EXPORT_SYMBOL(sofm_lut_sin_fixed_16b); diff --git a/src/math/matrix.c b/src/math/matrix.c new file mode 100644 index 000000000000..e4c4c1ecbfff --- /dev/null +++ b/src/math/matrix.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/math/matrix.h> +#include <errno.h> +#include <stdint.h> + +int mat_multiply(struct mat_matrix_16b *a, struct mat_matrix_16b *b, struct mat_matrix_16b *c) +{ + int64_t s; + int16_t *x; + int16_t *y; + int16_t *z = c->data; + int i, j, k; + int y_inc = b->columns; + const int shift_minus_one = a->fractions + b->fractions - c->fractions - 1; + + if (a->columns != b->rows || a->rows != c->rows || b->columns != c->columns) + return -EINVAL; + + /* If all data is Q0 */ + if (shift_minus_one == -1) { + for (i = 0; i < a->rows; i++) { + for (j = 0; j < b->columns; j++) { + s = 0; + x = a->data + a->columns * i; + y = b->data + j; + for (k = 0; k < b->rows; k++) { + s += (int32_t)(*x) * (*y); + x++; + y += y_inc; + } + *z = (int16_t)s; /* For Q16.0 */ + z++; + } + } + + return 0; + } + + for (i = 0; i < a->rows; i++) { + for (j = 0; j < b->columns; j++) { + s = 0; + x = a->data + a->columns * i; + y = b->data + j; + for (k = 0; k < b->rows; k++) { + s += (int32_t)(*x) * (*y); + x++; + y += y_inc; + } + *z = (int16_t)(((s >> shift_minus_one) + 1) >> 1); /*Shift to Qx.y */ + z++; + } + } + return 0; +} + +int mat_multiply_elementwise(struct mat_matrix_16b *a, struct mat_matrix_16b *b, + struct mat_matrix_16b *c) +{ int64_t p; + int16_t *x = a->data; + int16_t *y = b->data; + int16_t *z = c->data; + int i; + const int shift_minus_one = a->fractions + b->fractions - c->fractions - 1; + + if (a->columns != b->columns || b->columns != c->columns || + a->rows != b->rows || b->rows != c->rows) { + return -EINVAL; + } + + /* If all data is Q0 */ + if (shift_minus_one == -1) { + for (i = 0; i < a->rows * a->columns; i++) { + *z = *x * *y; + x++; + y++; + z++; + } + + return 0; + } + + for (i = 0; i < a->rows * a->columns; i++) { + p = (int32_t)(*x) * *y; + *z = (int16_t)(((p >> shift_minus_one) + 1) >> 1); /*Shift to Qx.y */ + x++; + y++; + z++; + } + + return 0; +} diff --git a/src/math/mu_law.c b/src/math/mu_law.c new file mode 100644 index 000000000000..32d50dad9b75 --- /dev/null +++ b/src/math/mu_law.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/mu_law.h> +#include <stdint.h> + +#define SOFM_MULAW_BIAS 33 +#define SOFM_MULAW_MAX 8191 +#define SOFM_MULAW_TOGGLE_BITS 0x7f +#define SOFM_MULAW_SIGN_BIT 0x80 +#define SOFM_MULAW_MANTISSA_MASK 0x0f +#define SOFM_MULAW_MANTISSA_BITS 4 +#define SOFM_MULAW_SHIFT_MASK 0x07 +#define SOFM_MULAW_DEC_ONES_MASK 0x21 /* 0b100001 for "1abcd1", see below */ + +/* + * mu-law encode table (sign bit is b12) + * + * Input values 12:0 Output values 6:0 + * + * 0 0 0 0 0 0 0 1 a b c d x 0 0 0 a b c d + * 0 0 0 0 0 0 1 a b c d x x 0 0 1 a b c d + * 0 0 0 0 0 1 a b c d x x x 0 1 0 a b c d + * 0 0 0 0 1 a b c d x x x x 0 1 1 a b c d + * 0 0 0 1 a b c d x x x x x 1 0 0 a b c d + * 0 0 1 a b c d x x x x x x 1 0 1 a b c d + * 0 1 a b c d x x x x x x x 1 1 0 a b c d + * 1 a b c d x x x x x x x x 1 1 1 a b c d + * + * mu-law decode table (sign bit is b7) + * + * Input values 6:0 Output values 12:0 + * + * 0 0 0 a b c d 0 0 0 0 0 0 0 1 a b c d 1 + * 0 0 1 a b c d 0 0 0 0 0 0 1 a b c d 1 0 + * 0 1 0 a b c d 0 0 0 0 0 1 a b c d 1 0 0 + * 0 1 1 a b c d 0 0 0 0 1 a b c d 1 0 0 0 + * 1 0 0 a b c d 0 0 0 1 a b c d 1 0 0 0 0 + * 1 0 1 a b c d 0 0 1 a b c d 1 0 0 0 0 0 + * 1 1 0 a b c d 0 1 a b c d 1 0 0 0 0 0 0 + * 1 1 1 a b c d 1 a b c d 1 0 0 0 0 0 0 0 + */ + +/* Shift values lookup table for above table for 7 + * highest sample value bits. + */ +static uint8_t mulaw_encode_shifts[128] = { + 0, 1, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, +}; + +/** + * sofm_mu_law_encode() - Encode sample with mu-law coding + * @param sample: A s16 sample value + * + * The mu-law codec is defined in ITU-T G.711 standard and has been used + * in telecommunications in USA and Japan. The mu-law coding compresses + * 14 bit samples to 8 bit data stream. In SOF the high 14 bits of s16 + * format are used for compatibility with normal audios. + * + * @return: Compressed 8 bit code value + */ + +uint8_t sofm_mu_law_encode(int16_t sample) +{ + int sign = SOFM_MULAW_SIGN_BIT; + int shift = 0; + int low_bits; + uint8_t byte; + + /* Convert to 14 bits with shift */ + sample >>= 2; + + /* Negative samples are 1's complement with zero sign bit */ + if (sample < 0) { + sign = 0; + sample = -sample - 1; + } + + sample += SOFM_MULAW_BIAS; + if (sample > SOFM_MULAW_MAX) + sample = SOFM_MULAW_MAX; + + shift = mulaw_encode_shifts[sample >> 6]; + low_bits = (sample >> (shift + 1)) & SOFM_MULAW_MANTISSA_MASK; + + byte = (shift << SOFM_MULAW_MANTISSA_BITS) | low_bits | sign; + byte ^= SOFM_MULAW_TOGGLE_BITS; + return byte; +} + +/** + * sofm_mu_law_decode() - Decode mu-law encoded code word + * @param byte: Encoded code word + * + * The mu-law decoder expands a 8 bit code word into a 14 bit sample value. + * In the SOF the high 14 bits are aligned to the most significant bits + * to be compatible with normal s16 Q1.15 samples. + * + * @return: Sampple value in s16 format + */ +int16_t sofm_mu_law_decode(int8_t byte) +{ + int low_bits; + int shift; + int sign; + int16_t value; + + sign = byte & SOFM_MULAW_SIGN_BIT; + byte ^= SOFM_MULAW_TOGGLE_BITS; + low_bits = byte & SOFM_MULAW_MANTISSA_MASK; + shift = (byte >> SOFM_MULAW_MANTISSA_BITS) & SOFM_MULAW_SHIFT_MASK; + value = (low_bits << (shift + 1)) | (SOFM_MULAW_DEC_ONES_MASK << shift); + value -= SOFM_MULAW_BIAS; + if (!sign) + value = -value; + + /* Shift 14 bit Q1.13 to 16 bit Q1.15 */ + return value << 2; +} diff --git a/src/math/numbers.c b/src/math/numbers.c index ae9bbebe06f5..df4f822c749a 100644 --- a/src/math/numbers.c +++ b/src/math/numbers.c @@ -6,26 +6,80 @@ // Liam Girdwood <liam.r.girdwood@linux.intel.com> // Keyon Jie <yang.jie@linux.intel.com> -/* Euclidean algorithm for greatest common denominator from - * pseudocode in - * https://en.wikipedia.org/wiki/Euclidean_algorithm#Implementations +/* Binary GCD algorithm + * https://en.wikipedia.org/wiki/Binary_GCD_algorithm */ #include <sof/audio/format.h> #include <sof/math/numbers.h> +#include <rtos/symbol.h> #include <stdint.h> +/* see numbers.h */ +#ifdef USE_SOF_GCD + +/* This function returns the greatest common divisor of two numbers + * If both parameters are 0, gcd(0, 0) returns 0 + * If first parameters is 0 or second parameter is 0, gcd(0, b) returns b + * and gcd(a, 0) returns a, because everything divides 0. + */ + int gcd(int a, int b) { - int t; + if (a == 0) + return b; + + if (b == 0) + return a; + + /* If the numbers are negative, convert them to positive numbers + * gcd(a, b) = gcd(-a, -b) = gcd(-a, b) = gcd(a, -b) + */ + + if (a < 0) + a = -a; - while (b != 0) { - t = b; - b = a % b; - a = t; + if (b < 0) + b = -b; + + int aux; + int k; + + /* Find the greatest power of 2 that devides both a and b */ + for (k = 0; ((a | b) & 1) == 0; k++) { + a >>= 1; + b >>= 1; } - return a; + + /* divide by 2 until a becomes odd */ + while ((a & 1) == 0) + a >>= 1; + + do { + /*if b is even, remove all factors of 2*/ + while ((b & 1) == 0) + b >>= 1; + + /* both a and b are odd now. Swap so a <= b + * then set b = b - a, which is also even + */ + if (a > b) { + aux = a; + a = b; + b = aux; + } + + b = b - a; + + } while (b != 0); + + /* restore common factors of 2 */ + return a << k; } +EXPORT_SYMBOL(gcd); +#endif /* USE_SOF_GCD */ + +#if CONFIG_NUMBERS_VECTOR_FIND /* This function searches from vec[] (of length vec_length) integer values * of n. The indexes to equal values is returned in idx[]. The function @@ -79,34 +133,29 @@ int32_t find_max_abs_int32(int32_t vec[], int vec_length) return SATP_INT32(amax); /* Amax is always a positive value */ } +#endif /* CONFIG_VECTOR_FIND */ + +#if CONFIG_NUMBERS_NORM + /* Count the left shift amount to normalize a 32 bit signed integer value * without causing overflow. Input value 0 will result to 31. */ int norm_int32(int32_t val) { - int s; - int32_t n; - - if (!val) - return 31; - - if (val > 0) { - n = val << 1; - s = 0; - while (n > 0) { - n = n << 1; - s++; - } - } else { - n = val << 1; - s = 0; - while (n < 0) { - n = n << 1; - s++; - } - } - return s; + int c = 0; + + /* count number of bits c that val can be right-shifted arithmetically + * until there is -1 (if val is negative) or 0 (if val is positive) + * norm of val will be 31-c + */ + for (; val != -1 && val != 0; c++) + val >>= 1; + + return 31 - c; } +EXPORT_SYMBOL(norm_int32); + +#endif /* CONFIG_NORM */ /** * Basic CRC-32 implementation, based on pseudo-code from @@ -124,7 +173,7 @@ uint32_t crc32(uint32_t base, const void *data, uint32_t bytes) cur = (crc ^ ((const uint8_t *)data)[i]) & 0xFF; for (j = 0; j < 8; ++j) - cur = cur & 1 ? (cur >> 1) ^ 0xEDB88320 : cur >> 1; + cur = (cur & 1) ? (cur >> 1) ^ 0xEDB88320 : cur >> 1; crc = cur ^ (crc >> 8); } diff --git a/src/math/power.c b/src/math/power.c new file mode 100644 index 000000000000..ff9e5f911d5f --- /dev/null +++ b/src/math/power.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> +// Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// + + /* Include Files */ +#include <sof/audio/format.h> +#include <sof/trace/trace.h> +#include <sof/math/power.h> + +#include <sof/lib/uuid.h> +#include <ipc/trace.h> +#include <user/trace.h> +#include <stdint.h> + +SOF_DEFINE_REG_UUID(math_power); + +DECLARE_TR_CTX(math_power_tr, SOF_UUID(math_power_uuid), LOG_LEVEL_INFO); +/* define constant */ +#define POWER_MAX_LIMIT 0x8000 + +/* Function Definitions */ + +/** + * Arguments : int32_t b + * base input range [-32 to +32] + * + * : int32_t e + * exponent input range [ -3 to +3 ] + * + * Return Type : int32_t + * power output range [-32768 to + 32768] + * ATTENTION - FRACTIONAL EXPONENTIAL IS NOT SUPPORTED + * +------------------+------------------+------------------+--------+--------+--------+ + * | base | exponent | power(returntype)| b | e | p | + * +----+-----+-------+----+-----+-------+----+----+--------+--------+--------+--------+ + * |WLen| FLen|Signbit|WLen| FLen|Signbit|WLen|FLen|Signbit | Qformat| Qformat| Qformat| + * +----+-----+-------+----+-----+-------+----+----+--------+--------+--------+--------+ + * | 32 | 25 | 1 | 32 | 29 | 1 | 32 | 15 | 1 | 6.26 | 2.30 | 16.16 | + * +------------------+------------------+------------------+--------+--------+--------+ + */ +int32_t power_int32(int32_t b, int32_t e) +{ + int32_t i; + int32_t k; + int32_t multiplier; + int32_t p; + + p = POWER_MAX_LIMIT; + + if (e < 0) { + e = -e; + if (b) { + multiplier = (int32_t)((1LL << 50) / (int64_t)b); + } else { + multiplier = INT32_MAX; + tr_err(&math_power_tr, "Divide by zero error."); + } + } else { + multiplier = b; + } + i = e >> 29; + for (k = 0; k < i; k++) + p = sat_int32((((p * (int64_t)multiplier) >> 24) + 1) >> 1); + + return p; +} diff --git a/src/math/sqrt_int16.c b/src/math/sqrt_int16.c new file mode 100644 index 000000000000..81772fc90c3c --- /dev/null +++ b/src/math/sqrt_int16.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> +// +// + +#include <rtos/symbol.h> +#include <sof/math/sqrt.h> + +#define SQRT_WRAP_SCHAR_BITS 0xFF + +/* + * Square root + * + * Y = SQRTLOOKUP_INT16(U) computes the square root of + * U using lookup tables. + * Range of u is [0 to 65535] + * Range of y is [0 to 4] + * +------------------+-----------------+--------+--------+ + * | u | y (returntype) | u | y | + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 16 | 12 | 0 | 16 | 12 | 1 | 4.12 | 4.12 | + * +------------------+-----------------+--------+--------+ + + * Arguments : uint16_t u + * Return Type : int32_t + */ +uint16_t sofm_sqrt_int16(uint16_t u) +{ + static const int32_t iv1[193] = { + 46341, 46702, 47059, 47415, 47767, 48117, 48465, 48809, 49152, 49492, 49830, 50166, + 50499, 50830, 51159, 51486, 51811, 52134, 52454, 52773, 53090, 53405, 53719, 54030, + 54340, 54647, 54954, 55258, 55561, 55862, 56162, 56459, 56756, 57051, 57344, 57636, + 57926, 58215, 58503, 58789, 59073, 59357, 59639, 59919, 60199, 60477, 60753, 61029, + 61303, 61576, 61848, 62119, 62388, 62657, 62924, 63190, 63455, 63719, 63982, 64243, + 64504, 64763, 65022, 65279, 65536, 65792, 66046, 66300, 66552, 66804, 67054, 67304, + 67553, 67801, 68048, 68294, 68539, 68784, 69027, 69270, 69511, 69752, 69992, 70232, + 70470, 70708, 70945, 71181, 71416, 71651, 71885, 72118, 72350, 72581, 72812, 73042, + 73271, 73500, 73728, 73955, 74182, 74408, 74633, 74857, 75081, 75304, 75527, 75748, + 75969, 76190, 76410, 76629, 76848, 77066, 77283, 77500, 77716, 77932, 78147, 78361, + 78575, 78788, 79001, 79213, 79424, 79635, 79846, 80056, 80265, 80474, 80682, 80890, + 81097, 81303, 81509, 81715, 81920, 82125, 82329, 82532, 82735, 82938, 83140, 83341, + 83542, 83743, 83943, 84143, 84342, 84540, 84739, 84936, 85134, 85331, 85527, 85723, + 85918, 86113, 86308, 86502, 86696, 86889, 87082, 87275, 87467, 87658, 87849, 88040, + 88231, 88420, 88610, 88799, 88988, 89176, 89364, 89552, 89739, 89926, 90112, 90298, + 90484, 90669, 90854, 91038, 91222, 91406, 91589, 91772, 91955, 92137, 92319, 92501, + 92682}; + static const int8_t iv[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t xfi_tmp; + int32_t y; + uint16_t v; + int32_t a_i; + int32_t l1_i; + int32_t l2_i; + int num_left_shifts; + int shift_factor; + int xfi; + unsigned int slice_temp; + int sign = 1; + + if (!u) + return 0; + /* Normalize the input such that u = x * 2^n and 0.5 <= x < 2 + * Normalize to the range [1, 2) + * normalizes the input U + * such that the output X is + * U = X*2^N + * 1 <= X < 2 + * The output X is unsigned with one integer bit. + * The input U must be scalar and positive. + * The number of bits in a byte is assumed to be B=8. + * Reinterpret the input as an unsigned integer. + * Unroll the loop in generated code so there will be no branching. + * For each iteration, see how many leading zeros are in the high + * byte of V, and shift them out to the left. Continue with the + * shifted V for as many bytes as it has. + * The index is the high byte of the input plus 1 to make it a + * one-based index. + * Index into the number-of-leading-zeros lookup table. This lookup + * table takes in a byte and returns the number of leading zeros in the + * binary representation. + */ + + shift_factor = iv[u >> 8]; + /* Left-shift out all the leading zeros in the high byte. */ + v = u << shift_factor; + /* Update the total number of left-shifts */ + num_left_shifts = shift_factor; + /* For each iteration, see how many leading zeros are in the high + * byte of V, and shift them out to the left. Continue with the + * shifted V for as many bytes as it has. + * The index is the high byte of the input plus 1 to make it a + * one-based index. + * Index into the number-of-leading-zeros lookup table. This lookup + * table takes in a byte and returns the number of leading zeros in the + * binary representation. + */ + shift_factor = iv[v >> 8]; + /* Left-shift out all the leading zeros in the high byte. + * Update the total number of left-shifts + */ + num_left_shifts += shift_factor; + /* The input has been left-shifted so the most-significant-bit is a 1. + * Reinterpret the output as unsigned with one integer bit, so + * that 1 <= x < 2. + * Let Q = int(u). Then u = Q*2^(-u_fraction_length), + * and x = Q*2^num_left_shifts * 2^(1-word_length). Therefore, + * u = x*2^n, where n is defined as: + */ + xfi_tmp = (3 - num_left_shifts) & 1; + v = (v << shift_factor) >> xfi_tmp; + /* Extract the high byte of x */ + /* Convert the high byte into an index for SQRTLUT */ + slice_temp = SQRT_WRAP_SCHAR_BITS & (v >> 8); + /* The upper byte was used for the index into SQRTLUT. + * The remainder, r, interpreted as a fraction, is used to + * linearly interpolate between points. + */ + a_i = iv1[((v >> 8) - 63) - 1]; + a_i <<= 8; + l1_i = iv1[SQRT_WRAP_SCHAR_BITS & ((slice_temp + 194) - 1)]; + l2_i = iv1[(slice_temp - 63) - 1]; + y = a_i + (v & SQRT_WRAP_SCHAR_BITS) * (l1_i - l2_i); + xfi = (((xfi_tmp - num_left_shifts) + 3) >> 1); + shift_factor = (((xfi_tmp - num_left_shifts) + 3) >> 1); + if (xfi != 0) { + if (xfi > 0) + y <<= (shift_factor >= 32) ? 0 : shift_factor; + else + y >>= -sign * xfi; + } + y = ((y >> 11) + 1) >> 1; + + return y; +} +EXPORT_SYMBOL(sofm_sqrt_int16); diff --git a/src/math/sqrt_int32.c b/src/math/sqrt_int32.c new file mode 100644 index 000000000000..6d412b33f33a --- /dev/null +++ b/src/math/sqrt_int32.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// + +#include <sof/math/sqrt.h> +#include <rtos/symbol.h> +#include <stdint.h> + +/* Lookup table for square root for initial value in iteration, + * created with Octave commands: + * + * arg=((1:64) * 2^25) / 2^30; lut = int32(sqrt(arg) * 2^30); + * fmt=['static const int32_t sqrt_int32_lut[] = {' repmat(' %d,',1, numel(lut)-1) ' %d};\n']; + * fprintf(fmt, lut) + */ +static const int32_t sqrt_int32_lut[] = { + 189812531, 268435456, 328764948, 379625062, 424433723, 464943848, 502196753, + 536870912, 569437594, 600239927, 629536947, 657529896, 684378814, 710213460, + 735140772, 759250125, 782617115, 805306368, 827373642, 848867446, 869830292, + 890299688, 910308921, 929887697, 949062656, 967857801, 986294844, 1004393507, + 1022171763, 1039646051, 1056831447, 1073741824, 1090389977, 1106787739, 1122946079, + 1138875187, 1154584553, 1170083026, 1185378878, 1200479854, 1215393219, 1230125796, + 1244684005, 1259073893, 1273301169, 1287371222, 1301289153, 1315059792, 1328687719, + 1342177280, 1355532607, 1368757628, 1381856086, 1394831545, 1407687407, 1420426919, + 1433053185, 1445569171, 1457977717, 1470281545, 1482483261, 1494585366, 1506590260, + 1518500250 +}; + +/* sofm_sqrt_int32() - Calculate 32-bit fractional square root function. */ +int32_t sofm_sqrt_int32(int32_t n) +{ + uint64_t n_shifted; + uint32_t x; + int shift; + + if (n < 1) + return 0; + + /* Scale input argument with 2^n, where n is even. + * Scale calculated sqrt() with 2^(-n/2). + */ + shift = (__builtin_clz(n) - 1) & ~1; /* Make even by clearing LSB */ + n = n << shift; + shift >>= 1; /* Divide by 2 for sqrt shift compensation */ + + /* For Q2.30 divide */ + n_shifted = (uint64_t)n << 30; + + /* Get initial guess from LUT, idx = 0 .. 63 */ + x = sqrt_int32_lut[n >> 25]; + + /* Iterate x(n+1) = 1/2 * (x(n) + N / x(n)) + * N is argument for square root + * x(n) is initial guess. Do two iterations. + */ + x = (uint32_t)(((n_shifted / x + x) + 1) >> 1); + x = (uint32_t)(((n_shifted / x + x) + 1) >> 1); + + return (int32_t)(x >> shift); +} +EXPORT_SYMBOL(sofm_sqrt_int32); diff --git a/src/math/trig.c b/src/math/trig.c index fe325e13b21e..1c1e221a5887 100644 --- a/src/math/trig.c +++ b/src/math/trig.c @@ -5,572 +5,244 @@ // Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> // Liam Girdwood <liam.r.girdwood@linux.intel.com> // Keyon Jie <yang.jie@linux.intel.com> +// Shriram Shastry <malladi.sastry@linux.intel.com> +#include <rtos/symbol.h> #include <sof/audio/format.h> #include <sof/math/trig.h> +#include <sof/math/cordic.h> #include <stdint.h> -#define SINE_C_Q20 341782638 /* 2*SINE_NQUART/pi in Q12.20 */ -#define SINE_NQUART 512 /* Must be 2^N */ -#define SINE_TABLE_SIZE (SINE_NQUART + 1) +#define CORDIC_SINE_COS_LUT_Q29 652032874 /* deg = 69.586061, int32(1.214505869895220 * 2^29) */ -/* An 1/4 period of sine wave as Q1.31 */ -const int32_t sine_table[SINE_TABLE_SIZE] = { - 0, - 6588387, - 13176712, - 19764913, - 26352928, - 32940695, - 39528151, - 46115236, - 52701887, - 59288042, - 65873638, - 72458615, - 79042909, - 85626460, - 92209205, - 98791081, - 105372028, - 111951983, - 118530885, - 125108670, - 131685278, - 138260647, - 144834714, - 151407418, - 157978697, - 164548489, - 171116732, - 177683365, - 184248325, - 190811551, - 197372981, - 203932553, - 210490206, - 217045877, - 223599506, - 230151030, - 236700388, - 243247517, - 249792358, - 256334847, - 262874923, - 269412525, - 275947592, - 282480061, - 289009871, - 295536961, - 302061269, - 308582734, - 315101294, - 321616889, - 328129457, - 334638936, - 341145265, - 347648383, - 354148229, - 360644742, - 367137860, - 373627523, - 380113669, - 386596237, - 393075166, - 399550396, - 406021864, - 412489512, - 418953276, - 425413098, - 431868915, - 438320667, - 444768293, - 451211734, - 457650927, - 464085813, - 470516330, - 476942419, - 483364019, - 489781069, - 496193509, - 502601279, - 509004318, - 515402566, - 521795963, - 528184448, - 534567963, - 540946445, - 547319836, - 553688076, - 560051103, - 566408860, - 572761285, - 579108319, - 585449903, - 591785976, - 598116478, - 604441351, - 610760535, - 617073970, - 623381597, - 629683357, - 635979190, - 642269036, - 648552837, - 654830534, - 661102068, - 667367379, - 673626408, - 679879097, - 686125386, - 692365218, - 698598533, - 704825272, - 711045377, - 717258790, - 723465451, - 729665303, - 735858287, - 742044345, - 748223418, - 754395449, - 760560379, - 766718151, - 772868706, - 779011986, - 785147934, - 791276492, - 797397602, - 803511207, - 809617248, - 815715670, - 821806413, - 827889421, - 833964637, - 840032003, - 846091463, - 852142959, - 858186434, - 864221832, - 870249095, - 876268167, - 882278991, - 888281511, - 894275670, - 900261412, - 906238681, - 912207419, - 918167571, - 924119082, - 930061894, - 935995952, - 941921200, - 947837582, - 953745043, - 959643527, - 965532978, - 971413341, - 977284561, - 983146583, - 988999351, - 994842809, - 1000676905, - 1006501581, - 1012316784, - 1018122458, - 1023918549, - 1029705003, - 1035481765, - 1041248781, - 1047005996, - 1052753356, - 1058490807, - 1064218296, - 1069935767, - 1075643168, - 1081340445, - 1087027543, - 1092704410, - 1098370992, - 1104027236, - 1109673088, - 1115308496, - 1120933406, - 1126547765, - 1132151521, - 1137744620, - 1143327011, - 1148898640, - 1154459455, - 1160009404, - 1165548435, - 1171076495, - 1176593532, - 1182099495, - 1187594332, - 1193077990, - 1198550419, - 1204011566, - 1209461381, - 1214899812, - 1220326808, - 1225742318, - 1231146290, - 1236538675, - 1241919421, - 1247288477, - 1252645793, - 1257991319, - 1263325005, - 1268646799, - 1273956652, - 1279254515, - 1284540337, - 1289814068, - 1295075658, - 1300325059, - 1305562221, - 1310787095, - 1315999631, - 1321199780, - 1326387493, - 1331562722, - 1336725418, - 1341875532, - 1347013016, - 1352137822, - 1357249900, - 1362349204, - 1367435684, - 1372509294, - 1377569985, - 1382617710, - 1387652421, - 1392674071, - 1397682613, - 1402677999, - 1407660183, - 1412629117, - 1417584755, - 1422527050, - 1427455956, - 1432371426, - 1437273414, - 1442161874, - 1447036759, - 1451898025, - 1456745625, - 1461579513, - 1466399644, - 1471205973, - 1475998455, - 1480777044, - 1485541695, - 1490292364, - 1495029005, - 1499751575, - 1504460029, - 1509154322, - 1513834410, - 1518500249, - 1523151796, - 1527789006, - 1532411836, - 1537020243, - 1541614182, - 1546193612, - 1550758488, - 1555308767, - 1559844407, - 1564365366, - 1568871600, - 1573363067, - 1577839726, - 1582301533, - 1586748446, - 1591180425, - 1595597427, - 1599999410, - 1604386334, - 1608758157, - 1613114837, - 1617456334, - 1621782607, - 1626093615, - 1630389318, - 1634669675, - 1638934646, - 1643184190, - 1647418268, - 1651636840, - 1655839867, - 1660027308, - 1664199124, - 1668355276, - 1672495724, - 1676620431, - 1680729357, - 1684822463, - 1688899710, - 1692961061, - 1697006478, - 1701035921, - 1705049354, - 1709046738, - 1713028036, - 1716993211, - 1720942224, - 1724875039, - 1728791619, - 1732691927, - 1736575926, - 1740443580, - 1744294852, - 1748129706, - 1751948106, - 1755750016, - 1759535401, - 1763304223, - 1767056449, - 1770792043, - 1774510970, - 1778213194, - 1781898680, - 1785567395, - 1789219304, - 1792854372, - 1796472564, - 1800073848, - 1803658188, - 1807225552, - 1810775906, - 1814309215, - 1817825448, - 1821324571, - 1824806551, - 1828271355, - 1831718951, - 1835149305, - 1838562387, - 1841958164, - 1845336603, - 1848697673, - 1852041343, - 1855367580, - 1858676354, - 1861967633, - 1865241387, - 1868497585, - 1871736195, - 1874957188, - 1878160534, - 1881346201, - 1884514160, - 1887664382, - 1890796836, - 1893911493, - 1897008324, - 1900087300, - 1903148391, - 1906191569, - 1909216806, - 1912224072, - 1915213339, - 1918184580, - 1921137766, - 1924072870, - 1926989863, - 1929888719, - 1932769410, - 1935631909, - 1938476189, - 1941302224, - 1944109986, - 1946899450, - 1949670588, - 1952423376, - 1955157787, - 1957873795, - 1960571374, - 1963250500, - 1965911147, - 1968553291, - 1971176905, - 1973781966, - 1976368449, - 1978936330, - 1981485584, - 1984016188, - 1986528117, - 1989021349, - 1991495859, - 1993951624, - 1996388621, - 1998806828, - 2001206221, - 2003586778, - 2005948477, - 2008291295, - 2010615209, - 2012920200, - 2015206244, - 2017473320, - 2019721407, - 2021950483, - 2024160528, - 2026351521, - 2028523441, - 2030676268, - 2032809981, - 2034924561, - 2037019987, - 2039096240, - 2041153301, - 2043191149, - 2045209766, - 2047209132, - 2049189230, - 2051150040, - 2053091543, - 2055013722, - 2056916559, - 2058800035, - 2060664132, - 2062508835, - 2064334123, - 2066139982, - 2067926393, - 2069693341, - 2071440807, - 2073168776, - 2074877232, - 2076566159, - 2078235539, - 2079885359, - 2081515602, - 2083126253, - 2084717297, - 2086288719, - 2087840504, - 2089372637, - 2090885104, - 2092377891, - 2093850984, - 2095304369, - 2096738031, - 2098151959, - 2099546138, - 2100920555, - 2102275198, - 2103610053, - 2104925108, - 2106220351, - 2107495769, - 2108751351, - 2109987084, - 2111202958, - 2112398959, - 2113575079, - 2114731304, - 2115867625, - 2116984030, - 2118080510, - 2119157053, - 2120213650, - 2121250291, - 2122266966, - 2123263665, - 2124240379, - 2125197099, - 2126133816, - 2127050521, - 2127947205, - 2128823861, - 2129680479, - 2130517051, - 2131333571, - 2132130029, - 2132906419, - 2133662733, - 2134398965, - 2135115106, - 2135811152, - 2136487094, - 2137142926, - 2137778643, - 2138394239, - 2138989707, - 2139565042, - 2140120239, - 2140655292, - 2141170196, - 2141664947, - 2142139540, - 2142593970, - 2143028233, - 2143442325, - 2143836243, - 2144209981, - 2144563538, - 2144896909, - 2145210091, - 2145503082, - 2145775879, - 2146028479, - 2146260880, - 2146473079, - 2146665075, - 2146836865, - 2146988449, - 2147119824, - 2147230990, - 2147321945, - 2147392689, - 2147443221, - 2147473541, - 2147483647 -}; +#define CORDIC_SINCOS_PIOVERTWO_Q28 421657428 /* int32(pi / 2 * 2^28) */ +#define CORDIC_SINCOS_PI_Q28 843314857 /* int32(pi * 2^28) */ +#define CORDIC_SINCOS_TWOPI_Q28 1686629713 /* int32(2 * pi * 2^28) */ +#define CORDIC_SINCOS_ONEANDHALFPI_Q28 1264972285 /* int32(1.5 * pi * 2^28) */ -/* Sine lookup table read */ -static inline int32_t sine_lookup(int idx) +/** + * CORDIC-based approximation of sine and cosine + * \+----------+----------------------------------------+--------------------+-------------------+ + * \|values | Q_CONVERT_FLOAT |(180/pi)*angleInRad |(pi/180)*angleInDeg| + * \+----------+----------------------------------------+--------------------+-------------------+ + * \|379625062 | Q_CONVERT_FLOAT(1.4142135605216026, 28)| 81.0284683480568| 1.41421356052160 | + * \|1073741824| Q_CONVERT_FLOAT(1.0000000000000000, 30)| 57.2957795130823| 1.00000000000000 | + * \|843314856 | Q_CONVERT_FLOAT(1.5707963258028030, 29)| 89.9999999431572| 1.57079632580280 | + * \|1686629713| Q_CONVERT_FLOAT(1.5707963267341256, 30)| 89.9999999965181| 1.57079632673413 | + * \+----------+----------------------------------------+--------------------+-------------------+ + */ + +#define CORDIC_ARCSINCOS_SQRT2_DIV4_Q30 379625062 /* int32(sqrt(2) / 4 * 2^30) */ +#define CORDIC_ARCSINCOS_ONE_Q30 1073741824 /* int32(1 * 2^30) */ + +/** + * CORDIC-based approximation of sine, cosine and complex exponential + */ +void cordic_approx(int32_t th_rad_fxp, int32_t a_idx, int32_t *sign, int32_t *b_yn, int32_t *xn, + int32_t *th_cdc_fxp) { - int32_t s; - int i1; + int32_t direction; + int32_t abs_th; + int32_t b_idx; + int32_t xn_local = CORDIC_SINE_COS_LUT_Q29; + int32_t yn_local = 0; + int32_t xtmp = CORDIC_SINE_COS_LUT_Q29; + int32_t ytmp = 0; + int shift; - i1 = idx & (2 * SINE_NQUART - 1); - if (i1 > SINE_NQUART) - i1 = 2 * SINE_NQUART - i1; + /* Addition or subtraction by a multiple of pi/2 is done in the data type + * of the input. When the fraction length is 29, then the quantization error + * introduced by the addition or subtraction of pi/2 is done with 29 bits of + * precision.Input range of cordicsin must be in the range [-2*pi, 2*pi), + * a signed type with fractionLength = wordLength-4 will fit this range + * without overflow.Increase of fractionLength makes the addition or + * subtraction of a multiple of pi/2 more precise + */ + abs_th = (th_rad_fxp >= 0) ? th_rad_fxp : -th_rad_fxp; + direction = (th_rad_fxp >= 0) ? 1 : -1; + *sign = 1; + if (abs_th > CORDIC_SINCOS_PIOVERTWO_Q28) { + if (abs_th <= CORDIC_SINCOS_ONEANDHALFPI_Q28) { + th_rad_fxp -= direction * CORDIC_SINCOS_PI_Q28; + *sign = -1; + } else { + th_rad_fxp -= direction * CORDIC_SINCOS_TWOPI_Q28; + } + } - if (idx > 2 * SINE_NQUART) - s = -sine_table[i1]; - else - s = sine_table[i1]; + th_rad_fxp <<= 2; - return s; + /* Calculate the correct coefficient values from rotation angle. + * Find difference between the coefficients from the lookup table + * and those from the calculation + */ + for (b_idx = 0; b_idx < a_idx; b_idx++) { + direction = (th_rad_fxp >= 0) ? 1 : -1; + shift = b_idx + 1; + th_rad_fxp -= direction * cordic_lookup[b_idx]; + xn_local -= direction * ytmp; + yn_local += direction * xtmp; + xtmp = xn_local >> shift; + ytmp = yn_local >> shift; + } + + /* Write back results once */ + *xn = xn_local; + *b_yn = yn_local; + *th_cdc_fxp = th_rad_fxp; } +EXPORT_SYMBOL(cordic_approx); -/* Compute fixed point sine with table lookup and interpolation */ -int32_t sin_fixed(int32_t w) +/** + * CORDIC-based approximation for inverse cosine + * cosvalue is Q2.30, return value is angle in Q3.29 format + */ +int32_t is_scalar_cordic_acos(int32_t cosvalue, int numiters) { - int idx; - int32_t frac; - int32_t s0; - int32_t s1; - int32_t delta; - int64_t sine; - int64_t idx_tmp; + int32_t xdshift; + int32_t ydshift; + int32_t yshift; + int32_t xshift; + int32_t x = 0; + int32_t y = 0; + int32_t z = 0; + int32_t sign; + int b_i; + int j; + + /* Initialize the variables for the cordic iteration + * angles less than pi/4, we initialize (x,y) along the x-axis. + * angles greater than or equal to pi/4, we initialize (x,y) + * along the y-axis. This improves the accuracy of the algorithm + * near the edge of the domain of convergence + * + * Note: not pi/4 but sqrt(2)/4 is used as the threshold + */ + if (cosvalue < CORDIC_ARCSINCOS_SQRT2_DIV4_Q30) { + y = CORDIC_ARCSINCOS_ONE_Q30; + z = PI_DIV2_Q3_29; + } else { + x = CORDIC_ARCSINCOS_ONE_Q30; + } - /* Q4.28 x Q12.20 -> Q16.48 */ - idx_tmp = (int64_t)w * SINE_C_Q20; - idx = (int)(idx_tmp >> 48); /* Shift to Q0 */ - idx_tmp = idx_tmp >> 17; /* Shift to Q16.31 */ - idx_tmp = idx_tmp - (idx << 31); /* Get fraction */ - frac = (int32_t)idx_tmp; /* Q1.31 */ - s0 = sine_lookup(idx); /* Q1.31 */ - s1 = sine_lookup(idx + 1); /* Q1.31 */ - delta = s1 - s0; /* Q1.31 */ - /* All Q1.31 */ - sine = s0 + q_mults_32x32(frac, delta, Q_SHIFT_BITS_64(31, 31, 31)); + /* DCORDIC(Double CORDIC) algorithm */ + /* Double iterations method consists in the fact that unlike the classical */ + /* CORDIC method,where the iteration step value changes EVERY time, i.e. on */ + /* each iteration, in the double iteration method, the iteration step value */ + /* is repeated twice and changes only through one iteration */ + for (b_i = 0; b_i < numiters; b_i++) { + j = (b_i + 1) << 1; + if (j >= 31) + j = 31; - return (int32_t)sine; + xshift = x >> b_i; + yshift = y >> b_i; + xdshift = x >> j; + ydshift = y >> j; + /* Do nothing if x currently equals the target value. Allowed for + * double rotations algorithms, as it is equivalent to rotating by + * the same angle in opposite directions sequentially. Accounts for + * the scaling effect of CORDIC Pseudo-rotations as well. + */ + if (x == cosvalue) { + x += xdshift; + y += ydshift; + } else { + sign = (((x > cosvalue) && (y >= 0)) || + ((x < cosvalue) && (y < 0))) ? 1 : -1; + x = x - xdshift - sign * yshift; + y = y - ydshift + sign * xshift; + z += sign * cordic_ilookup[b_i]; + } + cosvalue += cosvalue >> j; + } + if (z < 0) + z = -z; + + return z; +} + +/** + * CORDIC-based approximation for inverse sine + * sinvalue is Q2.30, return value is angle in Q2.30 format + */ +int32_t is_scalar_cordic_asin(int32_t sinvalue, int numiters) +{ + int32_t xdshift; + int32_t ydshift; + int32_t xshift; + int32_t yshift; + int32_t x = 0; + int32_t y = 0; + int32_t z = 0; + int32_t sign; + int b_i; + int j; + + /* Initialize the variables for the cordic iteration + * angles less than pi/4, we initialize (x,y) along the x-axis. + * angles greater than or equal to pi/4, we initialize (x,y) + * along the y-axis. This improves the accuracy of the algorithm + * near the edge of the domain of convergence + * + * Note: Instead of pi/4, sqrt(2)/4 is used as the threshold + */ + if (sinvalue > CORDIC_ARCSINCOS_SQRT2_DIV4_Q30) { + y = CORDIC_ARCSINCOS_ONE_Q30; + z = PI_DIV2_Q3_29; + } else { + x = CORDIC_ARCSINCOS_ONE_Q30; + } + + /* DCORDIC(Double CORDIC) algorithm */ + /* Double iterations method consists in the fact that unlike the classical */ + /* CORDIC method,where the iteration step value changes EVERY time, i.e. on */ + /* each iteration, in the double iteration method, the iteration step value */ + /* is repeated twice and changes only through one iteration */ + for (b_i = 0; b_i < numiters; b_i++) { + j = (b_i + 1) << 1; + if (j >= 31) + j = 31; + + xshift = x >> b_i; + yshift = y >> b_i; + ydshift = y >> j; + xdshift = x >> j; + /* Do nothing if x currently equals the target value. Allowed for + * double rotations algorithms, as it is equivalent to rotating by + * the same angle in opposite directions sequentially. Accounts for + * the scaling effect of CORDIC Pseudo-rotations as well. + */ + if (y == sinvalue) { + x += xdshift; + y += ydshift; + } else { + sign = (((y >= sinvalue) && (x >= 0)) || + ((y < sinvalue) && (x < 0))) ? 1 : -1; + x = x - xdshift + sign * yshift; + y = y - ydshift - sign * xshift; + z -= sign * cordic_ilookup[b_i]; + } + sinvalue += sinvalue >> j; + } + if (z < 0) + z = -z; + + return z; +} + +/** + * cmpx_cexp() - CORDIC-based approximation of complex exponential e^(j*THETA) + * + * The sine and cosine values are in Q2.30 format from cordic_approx()function. + */ +void cmpx_cexp(int32_t sign, int32_t b_yn, int32_t xn, cordic_cfg type, struct cordic_cmpx *cexp) +{ + cexp->re = sign * xn; + cexp->im = sign * b_yn; + /*convert Q2.30 to Q1.15*/ + if (type == EN_16B_CORDIC_CEXP) { + cexp->re = sat_int16(Q_SHIFT_RND((cexp->re), 30, 15)); + cexp->im = sat_int16(Q_SHIFT_RND((cexp->im), 30, 15)); + } } diff --git a/src/math/window.c b/src/math/window.c new file mode 100644 index 000000000000..39739ef24be3 --- /dev/null +++ b/src/math/window.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2025 Intel Corporation. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/decibels.h> +#include <sof/math/log.h> +#include <sof/math/trig.h> +#include <sof/math/window.h> +#include <errno.h> +#include <stdint.h> + +#define WIN_ONE_Q15 INT16_MAX +#define WIN_ONE_Q31 INT32_MAX +#define WIN_05_Q31 Q_CONVERT_FLOAT(0.5, 31) + +#define WIN_PI_Q28 Q_CONVERT_FLOAT(3.1415926536, 28) +#define WIN_TWO_PI_Q28 Q_CONVERT_FLOAT(6.2831853072, 28) + +#define WIN_085_Q31 Q_CONVERT_FLOAT(0.85, 31) +#define WIN_LOG_2POW31_Q26 Q_CONVERT_FLOAT(21.4875625974, 26) + +/* Exact + * #define WIN_HAMMING_A0_Q30 Q_CONVERT_FLOAT(25.0 / 46.0, 30) + * #define WIN_HAMMING_A1_Q30 Q_CONVERT_FLOAT(1 - 25.0 / 46.0, 30) + */ + +/* Common approximations to match e.g. Octave */ +#define WIN_HAMMING_A0_Q30 Q_CONVERT_FLOAT(0.54, 30) +#define WIN_HAMMING_A1_Q30 Q_CONVERT_FLOAT(0.46, 30) +#define WIN_HAMMING_A0_Q31 Q_CONVERT_FLOAT(0.54, 31) +#define WIN_HAMMING_A1_Q31 Q_CONVERT_FLOAT(0.46, 31) + +/* Rectangular window */ +void win_rectangular_16b(int16_t *win, int length) +{ + int i; + + for (i = 0; i < length; i++) + win[i] = WIN_ONE_Q15; +} + +void win_rectangular_32b(int32_t *win, int length) +{ + int i; + + for (i = 0; i < length; i++) + win[i] = WIN_ONE_Q31; +} + +/* Blackman window */ +void win_blackman_16b(int16_t win[], int length, int16_t a0) +{ + const int32_t a1 = Q_CONVERT_FLOAT(0.5, 31); + int32_t inv_length; + int32_t val; + int32_t a; + int16_t alpha; + int32_t a2; + int32_t c1; + int32_t c2; + int n; + + alpha = WIN_ONE_Q15 - 2 * a0; /* Q1.15 */ + a2 = alpha << 15; /* Divided by 2 in Q1.31 */ + a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */ + inv_length = WIN_ONE_Q31 / length; + + for (n = 0; n < length; n++) { + c1 = cos_fixed_32b(a * n); + c2 = cos_fixed_32b(2 * n * Q_MULTSR_32X32((int64_t)a, inv_length, 28, 31, 28)); + val = a0 - Q_MULTSR_32X32((int64_t)a1, c1, 31, 31, 15) + + Q_MULTSR_32X32((int64_t)a2, c2, 31, 31, 15); + win[n] = sat_int16(val); + } +} + +void win_blackman_32b(int32_t win[], int length, int32_t a0) +{ + const int32_t a1 = Q_CONVERT_FLOAT(0.5, 31); + int64_t val; + int32_t inv_length; + int32_t a; + int16_t alpha; + int32_t a2; + int32_t c1; + int32_t c2; + int n; + + alpha = WIN_ONE_Q31 - 2 * a0; /* Q1.31 */ + a2 = alpha << 15; /* Divided by 2 in Q1.31 */ + a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */ + inv_length = WIN_ONE_Q31 / length; + + for (n = 0; n < length; n++) { + c1 = cos_fixed_32b(a * n); + c2 = cos_fixed_32b(2 * n * Q_MULTSR_32X32((int64_t)a, inv_length, 28, 31, 28)); + val = a0 - Q_MULTSR_32X32((int64_t)a1, c1, 31, 31, 31) + + Q_MULTSR_32X32((int64_t)a2, c2, 31, 31, 31); + win[n] = sat_int32(val); + } +} + +/* Hann window */ +void win_hann_16b(int16_t win[], int length) +{ + int32_t val; + int32_t a; + int n; + + a = WIN_PI_Q28 / (length - 1); /* Q4.28 */ + for (n = 0; n < length; n++) { + /* Calculate sin(a * n)^2 */ + val = sin_fixed_32b(a * n); /* Q4.28 -> Q1.31 */ + val = Q_MULTSR_32X32((int64_t)val, val, 31, 31, 15); /* Q1.15 */ + win[n] = sat_int16(val); + } +} + +void win_hann_32b(int32_t win[], int length) +{ + int64_t val; + int32_t a; + int n; + + a = WIN_PI_Q28 / (length - 1); /* Q4.28 */ + for (n = 0; n < length; n++) { + /* Calculate sin(a * n)^2 */ + val = sin_fixed_32b(a * n); /* Q4.28 -> Q1.31 */ + val = Q_MULTSR_32X32((int64_t)val, val, 31, 31, 31); /* Q1.31 */ + win[n] = sat_int32(val); + } +} + +/* Hamming window */ +void win_hamming_16b(int16_t win[], int length) +{ + int32_t val; + int32_t a; + int n; + + a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */ + for (n = 0; n < length; n++) { + /* Calculate 0.54 - 0.46 * cos(a * n) */ + val = cos_fixed_32b(a * n); /* Q4.28 -> Q1.31 */ + val = Q_MULTSR_32X32((int64_t)val, WIN_HAMMING_A1_Q30, 31, 30, 30); /* Q1.30 */ + val = WIN_HAMMING_A0_Q30 - val; + + /* Convert to Q1.15 */ + win[n] = sat_int16(Q_SHIFT_RND(val, 30, 15)); + } +} + +void win_hamming_32b(int32_t win[], int length) +{ + int64_t val; + int32_t a; + int n; + + a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */ + for (n = 0; n < length; n++) { + /* Calculate 0.54 - 0.46 * cos(a * n) */ + val = cos_fixed_32b(a * n); /* Q4.28 -> Q1.31 */ + val = Q_MULTSR_32X32((int64_t)val, WIN_HAMMING_A1_Q31, 31, 31, 31); /* Q1.31 */ + val = WIN_HAMMING_A0_Q31 - val; + win[n] = sat_int32(val); + } +} + +/* Povey window */ +void win_povey_16b(int16_t win[], int length) +{ + int32_t cos_an; + int32_t x1; + int32_t x2; + int32_t x3; + int32_t x4; + int32_t a; + int n; + + a = WIN_TWO_PI_Q28 / (length - 1); /* Q4.28 */ + for (n = 0; n < length; n++) { + /* Calculate 0.5 - 0.5 * cos(a * n) */ + cos_an = cos_fixed_32b(a * n); /* Q4.28 -> Q1.31 */ + x1 = WIN_05_Q31 - (cos_an >> 1); /* Q1.31 */ + + /* Calculate x^0.85 as exp(0.85 * log(x)) */ + x2 = (int32_t)(ln_int32((uint32_t)x1) >> 1) - WIN_LOG_2POW31_Q26; + x3 = sat_int32(Q_MULTSR_32X32((int64_t)x2, WIN_085_Q31, 26, 31, 27)); /* Q5.27 */ + x4 = exp_fixed(x3); /* Q5.27 -> Q12.20 */ + + /* Convert to Q1.15 */ + win[n] = sat_int16(Q_SHIFT_RND(x4, 20, 15)); + } +} diff --git a/src/module/CMakeLists.txt b/src/module/CMakeLists.txt new file mode 100644 index 000000000000..1cdd0d2137a9 --- /dev/null +++ b/src/module/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(audio) diff --git a/src/module/README.md b/src/module/README.md new file mode 100644 index 000000000000..3d79c948bdd8 --- /dev/null +++ b/src/module/README.md @@ -0,0 +1,111 @@ +# Audio Processing Modules (`src/module`) + +The `src/module` directory and the `src/include/module` headers define the Sound Open Firmware (SOF) modern Audio Processing Module API. This architecture abstracts the underlying OS and pipeline scheduler implementations from the actual audio signal processing logic, allowing modules to be written once and deployed either as statically linked core components or as dynamically loadable Zephyr EXT (LLEXT) modules. + +## Architecture Overview + +The SOF module architecture is built around three core concepts: + +1. **`struct module_interface`**: A standardized set of operations (`init`, `prepare`, `process`, `reset`, `free`, `set_configuration`) that every audio processing module implements. +2. **`struct processing_module`**: The runtime instantiated state of a module. It holds metadata, configuration objects, memory allocations (`module_resources`), and references to interconnected streams. +3. **Module Adapter (`src/audio/module_adapter`)**: The system glue layer. It masquerades as a legacy pipeline `comp_dev` to the SOF schedulers, but acts as a sandbox container for the `processing_module`. It intercepts IPC commands, manages the module's state machine, manages inputs/outputs, and safely calls the `module_interface` operations. + +```mermaid +graph TD + subgraph SOF Core Pipeline Scheduler + P[Pipeline Scheduler <br> LL/DP Domains] + end + + subgraph Module Adapter System Layer + MA[Module Adapter `comp_dev`] + IPC[IPC Command Dispatch] + MEM[Memory Resource Manager] + end + + subgraph Standardized Module Framework API + INF[`module_interface` Ops] + SRC[Source API <br> `source_get_data`] + SNK[Sink API <br> `sink_get_buffer`] + end + + subgraph Custom Audio Modules + VOL[Volume] + EQ[EQ FIR/IIR] + CUSTOM[Loadable 3rd Party <br> Zephyr LLEXT] + end + + P <-->|Execute| MA + IPC -->|Config/Triggers| MA + + MA -->|Invoke| INF + MA -->|Manage| MEM + + INF --> VOL + INF --> EQ + INF --> CUSTOM + + VOL -->|Read| SRC + VOL -->|Write| SNK + EQ -->|Read| SRC + EQ -->|Write| SNK +``` + +## Module State Machine + +Every processing module is strictly governed by a uniform runtime state machine managed by the `module_adapter`. Modules must adhere to the transitions defined by `enum module_state`: + +1. `MODULE_DISABLED`: The module is loaded but uninitialized, or has been freed. No memory is allocated. +2. `MODULE_INITIALIZED`: After a successful `.init()` call. The module parses its IPC configuration and allocates necessary local resources (delay lines, coefficient tables). +3. `MODULE_IDLE`: After a successful `.prepare()` call. Audio stream formats are fully negotiated and agreed upon (Stream params, channels, rate). +4. `MODULE_PROCESSING`: When the pipeline triggers a `START` command. The `.process()` callback is actively handling buffers. + +```mermaid +stateDiagram-v2 + [*] --> MODULE_DISABLED: Module Created + + MODULE_DISABLED --> MODULE_INITIALIZED: .init() / IPC NEW + MODULE_INITIALIZED --> MODULE_DISABLED: .free() / IPC FREE + + MODULE_INITIALIZED --> MODULE_IDLE: .prepare() / Pipeline Setup + MODULE_IDLE --> MODULE_INITIALIZED: .reset() / Pipeline Reset + + MODULE_IDLE --> MODULE_PROCESSING: .trigger(START) / IPC START + MODULE_PROCESSING --> MODULE_IDLE: .trigger(STOP/PAUSE) / IPC STOP +``` + +## Data Flows and Buffer Management + +Modules do not directly manipulate underlying DMA, ALSA, or Zephyr `comp_buffer` pointers. Instead, they interact via the decoupled **Source and Sink APIs**. This allows the adapter to seamlessly feed data from varying topological sources without changing module code. + +The flow operates primarily in a "get -> manipulate -> commit/release" pattern: + +```mermaid +sequenceDiagram + participant Adapter as Module Adapter + participant Mod as Processing Module (.process) + participant Src as Source API (Input) + participant Snk as Sink API (Output) + + Adapter->>Mod: Process Trigger (sources[], sinks[]) + + Mod->>Src: source_get_data(req_size) + Src-->>Mod: Provides read_ptr, available_bytes + + Mod->>Snk: sink_get_buffer(req_size) + Snk-->>Mod: Provides write_ptr, free_bytes + + note over Mod: Execute DSP Algorithm <br> (Read from read_ptr -> Write to write_ptr) + + Mod->>Src: source_release_data(consumed_bytes) + Mod->>Snk: sink_commit_buffer(produced_bytes) + + Mod-->>Adapter: Return Status +``` + +### Source API (`src/module/audio/source_api.c`) +- modules request data by calling `source_get_data_s16` or `s32`. This establishes an active read lock. +- Once done, the module must call `source_release_data()` releasing only the frames actually consumed. + +### Sink API (`src/module/audio/sink_api.c`) +- modules request destination buffers by calling `sink_get_buffer_s16` or `s32`. +- After processing into the provided memory array, the module marks the memory as valid by calling `sink_commit_buffer()` for the exact number of frames successfully written. diff --git a/src/module/audio/CMakeLists.txt b/src/module/audio/CMakeLists.txt new file mode 100644 index 000000000000..06407bab7520 --- /dev/null +++ b/src/module/audio/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + source_api.c + sink_api.c +) diff --git a/src/module/audio/sink_api.c b/src/module/audio/sink_api.c new file mode 100644 index 000000000000..c0a94031f105 --- /dev/null +++ b/src/module/audio/sink_api.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include <module/audio/sink_api.h> +#include <module/audio/audio_stream.h> +/* + * When building native system-service modules only exported module headers can + * be included, autoconf.h isn't included either. To identify such a build we + * need any symbol that is guaranteed to be defined with any SOF build. + * CONFIG_CORE_COUNT is such a symbol, it is always defined to an integer number + */ +#ifndef CONFIG_CORE_COUNT +#define EXPORT_SYMBOL(...) +#else +#include <rtos/symbol.h> +#endif + +/* This file contains public sink API functions that were too large to mark is as inline. */ + +int sink_get_buffer(struct sof_sink *sink, size_t req_size, + void **data_ptr, void **buffer_start, size_t *buffer_size) +{ + int ret; + + if (sink->requested_write_frag_size) + return -EBUSY; + + ret = sink->ops->get_buffer(sink, req_size, data_ptr, + buffer_start, buffer_size); + + if (!ret) + sink->requested_write_frag_size = req_size; + return ret; +} +EXPORT_SYMBOL(sink_get_buffer); + +int sink_get_buffer_s16(struct sof_sink *sink, size_t req_size, + int16_t **data_ptr, int16_t **buffer_start, int *buffer_samples) +{ + size_t buffer_size; + int ret; + + ret = sink_get_buffer(sink, req_size, (void **)data_ptr, (void **)buffer_start, + &buffer_size); + if (ret) + return ret; + + *buffer_samples = buffer_size >> 1; + return 0; +} +EXPORT_SYMBOL(sink_get_buffer_s16); + +int sink_get_buffer_s32(struct sof_sink *sink, size_t req_size, + int32_t **data_ptr, int32_t **buffer_start, int *buffer_samples) +{ + size_t buffer_size; + int ret; + + ret = sink_get_buffer(sink, req_size, (void **)data_ptr, (void **)buffer_start, + &buffer_size); + if (ret) + return ret; + + *buffer_samples = buffer_size >> 2; + return 0; +} +EXPORT_SYMBOL(sink_get_buffer_s32); + +int sink_commit_buffer(struct sof_sink *sink, size_t commit_size) +{ + int ret; + + /* check if there was a buffer obtained for writing by sink_get_buffer */ + if (!sink->requested_write_frag_size) + return -ENODATA; + + /* limit size of data to be committed to previously obtained size */ + if (commit_size > sink->requested_write_frag_size) + commit_size = sink->requested_write_frag_size; + + ret = sink->ops->commit_buffer(sink, commit_size); + + if (!ret) + sink->requested_write_frag_size = 0; + + sink->num_of_bytes_processed += commit_size; + return ret; +} +EXPORT_SYMBOL(sink_commit_buffer); + +int sink_set_frm_fmt(struct sof_sink *sink, enum sof_ipc_frame frame_fmt) +{ + sink->audio_stream_params->frame_fmt = frame_fmt; + + /* notify the implementation */ + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} +EXPORT_SYMBOL(sink_set_frm_fmt); + +size_t sink_get_frame_bytes(struct sof_sink *sink) +{ + return get_frame_bytes(sink_get_frm_fmt(sink), sink_get_channels(sink)); +} +EXPORT_SYMBOL(sink_get_frame_bytes); + +size_t sink_get_free_frames(struct sof_sink *sink) +{ + return sink_get_free_size(sink) / sink_get_frame_bytes(sink); +} +EXPORT_SYMBOL(sink_get_free_frames); + +int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt) +{ + sink->audio_stream_params->valid_sample_fmt = valid_sample_fmt; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} +EXPORT_SYMBOL(sink_set_valid_fmt); + +int sink_set_rate(struct sof_sink *sink, unsigned int rate) +{ + sink->audio_stream_params->rate = rate; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} +EXPORT_SYMBOL(sink_set_rate); + +int sink_set_channels(struct sof_sink *sink, unsigned int channels) +{ + sink->audio_stream_params->channels = channels; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} +EXPORT_SYMBOL(sink_set_channels); + +int sink_set_buffer_fmt(struct sof_sink *sink, uint32_t buffer_fmt) +{ + sink->audio_stream_params->buffer_fmt = buffer_fmt; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} +EXPORT_SYMBOL(sink_set_buffer_fmt); + +int sink_set_overrun(struct sof_sink *sink, bool overrun_permitted) +{ + sink->audio_stream_params->overrun_permitted = overrun_permitted; + if (sink->ops->on_audio_format_set) + return sink->ops->on_audio_format_set(sink); + return 0; +} + +int sink_set_params(struct sof_sink *sink, struct sof_ipc_stream_params *params, bool force_update) +{ + if (sink->ops->audio_set_ipc_params) + return sink->ops->audio_set_ipc_params(sink, params, force_update); + return 0; +} +EXPORT_SYMBOL(sink_set_params); + +int sink_set_alignment_constants(struct sof_sink *sink, const uint32_t byte_align, + const uint32_t frame_align_req) +{ + if (sink->ops->set_alignment_constants) + return sink->ops->set_alignment_constants(sink, byte_align, frame_align_req); + return 0; +} +EXPORT_SYMBOL(sink_set_alignment_constants); diff --git a/src/module/audio/source_api.c b/src/module/audio/source_api.c new file mode 100644 index 000000000000..6ee2c54ed8d3 --- /dev/null +++ b/src/module/audio/source_api.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include <module/audio/source_api.h> +#include <module/audio/audio_stream.h> +/* + * When building native system-service modules only exported module headers can + * be included, autoconf.h isn't included either. To identify such a build we + * need any symbol that is guaranteed to be defined with any SOF build. + * CONFIG_CORE_COUNT is such a symbol, it is always defined to an integer number + */ +#ifndef CONFIG_CORE_COUNT +#define EXPORT_SYMBOL(...) +#else +#include <rtos/symbol.h> +#endif + +/* This file contains public source API functions that were too large to mark is as inline. */ + +int source_get_data(struct sof_source *source, size_t req_size, + void const **data_ptr, void const **buffer_start, size_t *buffer_size) +{ + int ret; + + if (source->requested_read_frag_size) + return -EBUSY; + + ret = source->ops->get_data(source, req_size, data_ptr, buffer_start, buffer_size); + + if (!ret) + source->requested_read_frag_size = req_size; + return ret; +} +EXPORT_SYMBOL(source_get_data); + +int source_get_data_s16(struct sof_source *source, size_t req_size, int16_t const **data_ptr, + int16_t const **buffer_start, int *buffer_samples) +{ + size_t buffer_size; + int ret; + + ret = source_get_data(source, req_size, (void const **)data_ptr, + (void const **)buffer_start, &buffer_size); + if (ret) + return ret; + + *buffer_samples = buffer_size >> 1; + return 0; +} +EXPORT_SYMBOL(source_get_data_s16); + +int source_get_data_s32(struct sof_source *source, size_t req_size, int32_t const **data_ptr, + int32_t const **buffer_start, int *buffer_samples) +{ + size_t buffer_size; + int ret; + + ret = source_get_data(source, req_size, (void const **)data_ptr, + (void const **)buffer_start, &buffer_size); + if (ret) + return ret; + + *buffer_samples = buffer_size >> 2; + return 0; +} +EXPORT_SYMBOL(source_get_data_s32); + +int source_release_data(struct sof_source *source, size_t free_size) +{ + int ret; + + /* Check if anything was obtained before for reading by source_get_data */ + if (!source->requested_read_frag_size) + return -ENODATA; + + /* limit size of data to be freed to previously obtained size */ + if (free_size > source->requested_read_frag_size) + free_size = source->requested_read_frag_size; + + ret = source->ops->release_data(source, free_size); + + if (!ret) + source->requested_read_frag_size = 0; + + source->num_of_bytes_processed += free_size; + return ret; +} +EXPORT_SYMBOL(source_release_data); + +size_t source_get_frame_bytes(struct sof_source *source) +{ + return get_frame_bytes(source_get_frm_fmt(source), + source_get_channels(source)); +} +EXPORT_SYMBOL(source_get_frame_bytes); + +size_t source_get_data_frames_available(struct sof_source *source) +{ + uint32_t frame_bytes = source_get_frame_bytes(source); + + if (frame_bytes > 0) + return source_get_data_available(source) / frame_bytes; + else + return 0; +} +EXPORT_SYMBOL(source_get_data_frames_available); diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt index cff60136a4f0..e43c21e1ac0d 100644 --- a/src/platform/CMakeLists.txt +++ b/src/platform/CMakeLists.txt @@ -1,25 +1,32 @@ # SPDX-License-Identifier: BSD-3-Clause -if(CONFIG_BAYTRAIL OR CONFIG_CHERRYTRAIL) - add_subdirectory(baytrail) -elseif(CONFIG_HASWELL OR CONFIG_BROADWELL) - add_subdirectory(haswell) -elseif(CONFIG_APOLLOLAKE) - add_subdirectory(apollolake) -elseif(CONFIG_CANNONLAKE) - add_subdirectory(cannonlake) -elseif(CONFIG_SUECREEK) - add_subdirectory(suecreek) -elseif(CONFIG_ICELAKE) - add_subdirectory(icelake) -elseif(CONFIG_TIGERLAKE) +if(CONFIG_LIBRARY) + add_subdirectory(library) + return() +endif() + +if(CONFIG_TIGERLAKE) add_subdirectory(tigerlake) elseif(CONFIG_IMX8 OR CONFIG_IMX8X) add_subdirectory(imx8) elseif(CONFIG_IMX8M) add_subdirectory(imx8m) -endif() - -if(CONFIG_CAVS) - add_subdirectory(intel) +elseif(CONFIG_IMX8M_CM7) + add_subdirectory(imx8m_cm7) +elseif(CONFIG_IMX8ULP) + add_subdirectory(imx8ulp) +elseif(CONFIG_AMD) + add_subdirectory(amd) +elseif(CONFIG_MT8186) + add_subdirectory(mt8186) +elseif(CONFIG_MT8188) + add_subdirectory(mt8188) +elseif(CONFIG_MT8195) + add_subdirectory(mt8195) +elseif(CONFIG_MT8196) + add_subdirectory(mt8196) +elseif(CONFIG_MT8365) + add_subdirectory(mt8365) +elseif(PLATFORM STREQUAL "qemu_xtensa") + add_subdirectory(qemu_xtensa) endif() diff --git a/src/platform/Kconfig b/src/platform/Kconfig index bcec159431a7..2de2c5ed00da 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -4,154 +4,52 @@ menu "Platform" choice prompt "Platform" - default APOLLOLAKE + default ZEPHYR_POSIX if ARCH_POSIX + # It's not really 'optional' but no value is much less confusing + # than falling back on a totally random value. + optional -config BAYTRAIL - bool "Build for Baytrail" - select HOST_PTABLE - select DW_DMA_AGGREGATED_IRQ - select DMA_SUSPEND_DRAIN - select DMA_FIFO_PARTITION - select DW - select DW_DMA - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_4 - select INTERRUPT_LEVEL_5 - select INTEL +config TIGERLAKE + bool "Build for Tigerlake" + select CAVS + select CAVS_VERSION_2_5 help - Select if your target platform is Baytrail-compatible + Select if your target platform is Tigerlake-compatible -config CHERRYTRAIL - bool "Build for Cherrytrail" - select HOST_PTABLE - select DW_DMA_AGGREGATED_IRQ - select DMA_SUSPEND_DRAIN - select DMA_FIFO_PARTITION - select DW - select DW_DMA - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_4 - select INTERRUPT_LEVEL_5 - select INTEL +config METEORLAKE + bool "Build for Meteorlake" + select ACE + select ACE_VERSION_1_5 help - Select if your target platform is Cherrytrail-compatible + Select if your target platform is Meteorlake-compatible -config HASWELL - bool "Build for Haswell" - select HOST_PTABLE - select DW_DMA_AGGREGATED_IRQ - select DW - select DW_DMA - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_2 - select INTERRUPT_LEVEL_3 - select INTEL +config LUNARLAKE + bool "Build for Lunarlake" + select ACE + select ACE_VERSION_2_0 help - Select if your target platform is Haswell-compatible + Select if your target platform is Lunarlake-compatible -config BROADWELL - bool "Build for Broadwell" - select HOST_PTABLE - select DW_DMA_AGGREGATED_IRQ - select DW - select DW_DMA - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_2 - select INTERRUPT_LEVEL_3 - select INTEL +config PANTHERLAKE + bool "Build for Pantherlake" + select ACE + select ACE_VERSION_3_0 help - Select if your target platform is Broadwell-compatible - -config APOLLOLAKE - bool "Build for Apollolake" - select BOOT_LOADER - select IRQ_MAP - select DMA_GW - select DW - select DW_DMA - select MEM_WND - select HW_LLI - select DMA_FIFO_PARTITION - select CAVS - select CAVS_VERSION_1_5 - help - Select if your target platform is Apollolake-compatible - -config CANNONLAKE - bool "Build for Cannonlake" - select BOOT_LOADER - select IRQ_MAP - select DMA_GW - select DW - select DW_DMA - select MEM_WND - select HW_LLI - select DW_DMA_AGGREGATED_IRQ - select DMA_FIFO_PARTITION - select CAVS - select CAVS_VERSION_1_8 - select WAITI_DELAY - select CAVS_USE_LPRO_IN_WAITI - help - Select if your target platform is Cannonlake-compatible - -config SUECREEK - bool "Build for Suecreek" - select BOOT_LOADER - select IRQ_MAP - select DW - select DW_DMA - select DW_SPI - select INTEL_IOMUX - select DW_GPIO - select HW_LLI - select DW_DMA_AGGREGATED_IRQ - select DMA_FIFO_PARTITION - select CAVS - select CAVS_VERSION_2_0 - select WAITI_DELAY - select CAVS_USE_LPRO_IN_WAITI - help - Select if your target platform is Suecreek-compatible - -config ICELAKE - bool "Build for Icelake" - select BOOT_LOADER - select IRQ_MAP - select DMA_GW - select DW - select DW_DMA - select MEM_WND - select HW_LLI - select DW_DMA_AGGREGATED_IRQ - select DMA_FIFO_PARTITION - select CAVS - select CAVS_VERSION_2_0 - select WAITI_DELAY - select CAVS_USE_LPRO_IN_WAITI + Select if your target platform is Pantherlake-compatible + +config WILDCATLAKE + bool "Build for Wildcatlake" + select ACE + select ACE_VERSION_3_0 help - Select if your target platform is Icelake-compatible + Select if your target platform is Wildcatlake-compatible -config TIGERLAKE - bool "Build for Tigerlake" - select BOOT_LOADER - select IRQ_MAP - select DMA_GW - select DW - select DW_DMA - select MEM_WND - select HW_LLI - select DW_DMA_AGGREGATED_IRQ - select DMA_FIFO_PARTITION - select CAVS - select CAVS_VERSION_2_5 - select WAITI_DELAY +config NOVALAKE + bool "Build for Novalake" + select ACE + select ACE_VERSION_4_0 help - Select if your target platform is Tigerlake-compatible + Select if your target platform is Novalake-compatible config LIBRARY bool "Build Library" @@ -161,146 +59,505 @@ config LIBRARY Library builds are not intended to be run on DSP, but to be used by user-space applications. +config LIBRARY_STATIC + bool "Build Library as static archive" + depends on LIBRARY + help + Select if you want to build a static library otherwise a dynamic + shared library will be built. + +config ZEPHYR_POSIX + bool "Build for Zephyr native_posix board" + help + Select if you are building a host unit test using + native_posix. This is similar to LIBRARY in that it builds + host binaries, but is tied to the Zephyr posix architecture + and thus able to instrument and test the whole OS + environment. + +if ZEPHYR_POSIX && ARCH_POSIX_LIBFUZZER + +config ZEPHYR_POSIX_FUZZ_IRQ + int "OS interrupt via which to deliver fuzz cases" + default 31 + help + New fuzz cases are delivered to Zephyr via interrupts. The + IRQ should be otherwise unused, but can be any value desired + by the app. + +config ZEPHYR_POSIX_FUZZ_TICKS + int "Ticks to allow for fuzz case processing" + default 2 + help + Fuzz interrupts are delivered, from the perspective of the + OS, at a steady cadence in simulated time. In general most + apps won't require much time to reach an idle state + following a unit-test style case, so the default is short to + prevent interaction with regular timer workloads. + +endif # ZEPHYR_POSIX && ARCH_POSIX_LIBFUZZER + config IMX8 bool "Build for NXP i.MX8" - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_2 - select INTERRUPT_LEVEL_3 + select XT_HAVE_RESET_VECTOR_ROM + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 select HOST_PTABLE select DUMMY_DMA - select WAITI_DELAY + select XT_WAITI_DELAY select IMX select IMX_EDMA + select IMX_ESAI + select IMX_INTERRUPT_IRQSTEER help Select if your target platform is imx8-compatible config IMX8X bool "Build for NXP i.MX8X" - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_2 - select INTERRUPT_LEVEL_3 + select XT_HAVE_RESET_VECTOR_ROM + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 select HOST_PTABLE select DUMMY_DMA - select WAITI_DELAY + select XT_WAITI_DELAY select IMX select IMX_EDMA + select IMX_ESAI + select IMX_INTERRUPT_IRQSTEER help Select if your target platform is imx8x-compatible config IMX8M bool "Build for NXP i.MX8M" - select HAVE_RESET_VECTOR_ROM - select INTERRUPT_LEVEL_1 - select INTERRUPT_LEVEL_2 - select INTERRUPT_LEVEL_3 + select XT_HAVE_RESET_VECTOR_ROM + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 select HOST_PTABLE select DUMMY_DMA - select WAITI_DELAY + select XT_WAITI_DELAY select IMX + select IMX_SDMA + select IMX_MICFIL + select IMX_INTERRUPT_IRQSTEER help Select if your target platform is imx8m-compatible +config IMX8M_CM7 + bool "Build for NXP i.MX8MP CM7 core" + select BUILD_OUTPUT_BIN + select HOST_PTABLE + select IMX + help + Select if your target platform is imx8mp-compatible with cm7 core. + +config IMX8ULP + bool "Build for NXP i.MX8ULP" + select XT_HAVE_RESET_VECTOR_ROM + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 + select HOST_PTABLE + select DUMMY_DMA + select XT_WAITI_DELAY + select IMX + select IMX_EDMA + select IMX_INTERRUPT_GENERIC + help + 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 IMX + help + Select if your target platform is imx93-compatible. + +config IMX95 + bool "Build for NXP i.MX95" + select ZEPHYR_LOG + select BUILD_OUTPUT_BIN + select HOST_PTABLE + select IMX + help + Select if your target platform is imx95-compatible. + +config RENOIR + bool "Build for Renoir" + select XT_INTERRUPT_LEVEL_5 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_4 + select XT_WAITI_DELAY + select AMD + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is renoir-compatible + +config REMBRANDT + bool "Build for Rembrandt" + select XT_INTERRUPT_LEVEL_5 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_4 + select XT_WAITI_DELAY + select XTENSA_EXCLUSIVE + select AMD + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is rembrandt-compatible + +config VANGOGH + bool "Build for Vangogh" + select XT_INTERRUPT_LEVEL_5 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_4 + select XT_WAITI_DELAY + select XTENSA_EXCLUSIVE + select AMD + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is vangogh-compatible + +config ACP_6_3 + bool "Build for ACP_6_3" + select XT_INTERRUPT_LEVEL_5 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_4 + select XT_WAITI_DELAY + select XTENSA_EXCLUSIVE + select AMD + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is acp_6_3-compatible + +config ACP_7_0 + bool "Build for ACP_7_0" + select XT_INTERRUPT_LEVEL_5 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_4 + select XT_WAITI_DELAY + select XTENSA_EXCLUSIVE + select AMD + select AMD_BINARY_BUILD + help + Select if your target platform is acp_7_0-compatible + +config MT8186 + bool "Build for MTK MT8186 (XTOS)" + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_4 + select DUMMY_DMA + select HOST_PTABLE + select XT_WAITI_DELAY + select MEDIATEK + select XTENSA_EXCLUSIVE + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is mt8186-compatible + Builds legacy/xtos firmware + +config MT8188 + bool "Build for MTK MT8188 (XTOS)" + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_4 + select DUMMY_DMA + select HOST_PTABLE + select XT_WAITI_DELAY + select MEDIATEK + select XTENSA_EXCLUSIVE + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is mt8188-compatible. + Builds legacy/xtos firmware + +config MT8195 + bool "Build for MTK MT8195 (XTOS)" + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 + select DUMMY_DMA + select HOST_PTABLE + select MEDIATEK + select XTENSA_EXCLUSIVE + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is mt8195-compatible + Builds legacy/xtos firmware + +config MT8365 + bool "Build for MTK MT8365" + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 + select DUMMY_DMA + select HOST_PTABLE + select MEDIATEK + select XTENSA_EXCLUSIVE + select SCHEDULE_DMA_MULTI_CHANNEL + help + Select if your target platform is mt8365-compatible + +config MTK + bool "Build for Mediatek (Zephyr)" + select SCHEDULE_DMA_MULTI_CHANNEL + select HOST_PTABLE + help + Select if your target is a Mediatek DSP. Builds Zephyr firmware. + +config MT8196 + bool "Build for MTK MT8196" + select XT_INTERRUPT_LEVEL_1 + select XT_INTERRUPT_LEVEL_2 + select XT_INTERRUPT_LEVEL_3 + select XT_INTERRUPT_LEVEL_4 + select DUMMY_DMA + select HOST_PTABLE + select XT_WAITI_DELAY + select MEDIATEK + select XTENSA_EXCLUSIVE + select SCHEDULE_DMA_MULTI_CHANNEL + help + This configuration enables support for the MediaTek MT8196 platform. + It includes necessary interrupt levels, DMA support, and other + platform-specific features required for the proper functioning of + the MT8196 SoC. Enabling this option will ensure that the build + system includes all relevant drivers and configurations for MT8196. + + Select this option if your target platform is MT8196-compatible. + endchoice +# +# For non-Zephyr builds like testbench, cmocka and SOF ALSA plugin, +# set core count separately. +# +if !ZEPHYR_SOF_MODULE + +config MP_MAX_NUM_CPUS + int + default 1 + help + Maximum number of cores per configuration + +endif # !ZEPHYR_SOF_MODULE + +config MAX_CORE_COUNT + int + default MP_MAX_NUM_CPUS + help + Maximum number of cores per configuration + +config CORE_COUNT + int "Number of cores" + default MP_MAX_NUM_CPUS + range 1 MP_MAX_NUM_CPUS + help + Number of used cores + Lowering available core count could result in lower power consumption + +config MULTICORE + bool + default CORE_COUNT > 1 + help + Indicates that architecture uses multiple cores + config INTEL bool - default n help This has to be selected for every Intel platform. It enables Intel platforms-specific features. +config HOST + bool + help + This has to be selected for building linux test targets. + config IMX bool - default n + select COMPILER_WORKAROUND_CACHE_ATTR if XTENSA help This has to be selected for every i.MX NXP platform. It enables NXP platforms-specific features. +config MEDIATEK + bool + help + This has to be selected for every MediaTek platform. + It enables MediaTek platforms-specific features. + +config AMD + bool + help + This has to be selected for every AMD platform. + It enables AMD platforms-specific features. + config CAVS bool - default n select INTEL - select INTERRUPT_LEVEL_2 - select INTERRUPT_LEVEL_5 + select SOF_ZEPHYR_NO_SOF_CLOCK -config CAVS_VERSION_1_5 +config CAVS_VERSION_2_5 depends on CAVS bool help - Select for CAVS version 1.5 + Select for CAVS version 2.5 -config CAVS_VERSION_1_8 - depends on CAVS && !CAVS_VERSION_1_5 +config ACE + bool + select INTEL + +config ACE_VERSION_1_5 + depends on ACE bool help - Select for CAVS version 1.8 + Select for ACE version 1.5 -config CAVS_VERSION_2_0 - depends on CAVS && !CAVS_VERSION_1_5 && !CAVS_VERSION_1_8 +config ACE_VERSION_2_0 + depends on ACE bool help - Select for CAVS version 2.0 + Select for ACE version 2.0 -config CAVS_VERSION_2_5 - depends on CAVS && !CAVS_VERSION_1_5 && !CAVS_VERSION_1_8 \ - && !CAVS_VERSION_2_0 +config ACE_VERSION_3_0 + depends on ACE bool help - Select for CAVS version 2.5 + Select for ACE version 3.0 -config CONFIG_CHERRYTRAIL_EXTRA_DW_DMA - bool "Support Cherrytrail 3rd DMAC" - default n if !CHERRYTRAIL - depends on CHERRYTRAIL +config ACE_VERSION_4_0 + depends on ACE + bool help - Select if you need support for all 3 DMACs versus the default 2 used - in baytrail. + Select for ACE version 4.0 -config CAVS_LPRO - bool "Enable low power ring oscillator as the default clock" - depends on CAVS && !CAVS_VERSION_1_5 +config HP_MEMORY_BANKS + int "HP memory banks count" + depends on CAVS + default 8 help - Select if you want to use 120MHz LPRO as the DSP clock source. - This option is required to support S0ix/D0ix mode. + Available memory banks count for High Performance memory + Lowering available banks could result in lower power consumption + Too low count should result in unresponsive/crashing image due to not + enough space for FW base image + Banks are 64kb in size. -config CAVS_USE_LPRO_IN_WAITI +config LP_MEMORY_BANKS + int "LP memory banks count" + depends on CAVS + default 0 + help + Available memory banks count for Low Power memory. + It can be used to turn ON/OFF LPSRAM bank/s. + Firmware will turn on only as many banks as are defined here. + +config LP_SRAM bool - default n + default LP_MEMORY_BANKS > 0 + help + Indicates that platform uses LPSRAM. + +config L1_DRAM + bool "L1 DRAM memory support" + help + Indicates that platform does support L1 DATA RAM. + +config L1_DRAM_MEMORY_BANKS + int "L1 DRAM memory banks count" + depends on L1_DRAM + default 0 + help + Available memory banks count for L1 DATA RAM. + It can be used to turn ON/OFF L1 DRAM bank/s. + Firmware will turn on only as many banks as specified. + +config L1_DRAM_MEMORY_BANK_SIZE + int "L1 DRAM memory bank size" + depends on L1_DRAM + default 0 + help + Specifies DRAM block size. + It can be used to calculate DRAM size. + +config CAVS_USE_LPRO_IN_WAITI + bool "Use low power ring oscillator in WFI" depends on CAVS - select WAKEUP_HOOK help - Select if platform requires DSP clock source to be switched to LPRO - while in waiti. - After waiti clock source is restored. + Select if we want to use LPRO clock in waiti. + After waiti exit clock source will be restored. + Choose n if unclear. + +config KCPS_DYNAMIC_CLOCK_CONTROL + bool "Use KCPS budget to determine DSP clock" + depends on IPC_MAJOR_4 + help + Select if we want to use compute budget + expressed in Kilo Cycles Per Second (KCPS) to determine DSP clock. + +config L3_HEAP + bool "Use L3 memory heap" + depends on ACE + help + Select this if L3 memory is supported on the platform and + it is intended to be used for dynamic allocations. + For Intel ACE platform the L3 memory is called + IMR (Isolated Memory Region). Feature has been + only tested on ACE platform. + Choose n if unclear. + +config CAVS_IMR_D3_PERSISTENT + bool "Intel IMR content persistent on DSP in D3" + depends on CAVS + default y + help + Select this if the Intel cAVS platform can keep the + IMR (Isolated Memory Region) content persistent when + the DSP is in power off (D3) mode, which means we + don't need to re-downloading firmware binary to DSP + SRAM so fast D3->D0 transition can be supported. + Choose n if unclear. # TODO: it should just take manifest version and offsets -config FIRMWARE_SHORT_NAME - string "Rimage firmware name" - default "byt" if BAYTRAIL - default "cht" if CHERRYTRAIL - default "hsw" if HASWELL - default "bdw" if BROADWELL - default "apl" if APOLLOLAKE - default "cnl" if CANNONLAKE - default "sue" if SUECREEK - default "icl" if ICELAKE +config RIMAGE_SIGNING_SCHEMA + string "Rimage firmware signing schema name" default "tgl" if TIGERLAKE default "imx8" if IMX8 default "imx8x" if IMX8X default "imx8m" if IMX8M + default "imx8m_cm7" if IMX8M_CM7 + default "imx8ulp" if IMX8ULP + default "imx95" if IMX95 + default "rn" if RENOIR + default "rmb" if REMBRANDT + default "vangogh" if VANGOGH + default "acp_6_3" if ACP_6_3 + default "acp_7_0" if ACP_7_0 + default "mt8186" if MT8186 + default "mt8188" if MT8188 + default "mt8195" if MT8195 + default "mt8196" if MT8196 + default "mt8365" if MT8365 default "" help - 3-characters long firmware identifer - used by rimage to decide how to build final binary + Signing schema name used by rimage to decide how to build final binary config SYSTICK_PERIOD int "System tick period in microseconds" default 1000 help - Defines platform system tick period. It is used to - drive timer based low latency scheduler and also + Defines platform system tick period. It is used as a timeout check value for system agent. Value should be provided in microseconds. @@ -310,6 +567,77 @@ config HAVE_AGENT help Enables system agent. It can be disabled on systems which are still unstable and cannot assure that - system agent will always execute on time. + system agent will always execute on time or systems + with DMA based scheduling, where asynchronous interrupts + can potentially starve the agent. + +config AMS + bool "Enable Async Messaging Service" + depends on IPC_MAJOR_4 + help + Enables Async Messaging Service. + Async messages are used to send messages between modules. + +config AGENT_PANIC_ON_DELAY + bool "Enable system agent time verification panic" + depends on HAVE_AGENT + help + Enables system agent time verification panic. + If scheduler timing verification fails, SA will + call a DSP panic. + +config XTENSA_EXCLUSIVE + bool + help + This has to be selected for xtensa exclusive instructions. + There is a definition for EXCLUSIVE option in xtensa-config.h + +config FORCE_DMA_COPY_WHOLE_BLOCK + bool + default y if MT8195 + default y if MT8365 + depends on HOST_PTABLE + help + The host component forces DMA to copy the block size to avoid + copying byte jitter between the components of the same pipeline. + +config SOF_STACK_SIZE + int "Primary core SOF stack size" + default 4096 + help + Size of the primary core stack. This is the stack used by all + IPC calls. Increasing it allows deeper call stack on those IPC + and might be useful when creating more complex audio processing + components. + +config SECONDARY_CORE_DISABLING_TIMEOUT + int + default 400 + depends on MULTICORE + help + Timeout value (in ms) for secondary core to enter D3 state. + +if XTENSA + +config INCOHERENT + bool "Enable cached data access via the Coherent API" + default y if CAVS || ACE + help + The architecture is cache incoherent. i.e FW has to manually manage + cache coherency amongst objects that are used on multiple cores. + This setting should only be disabled for cache incoherent + architectures for testing without cached access to shared data. + +endif + +config LL_WATCHDOG + bool "Enable watchdog support in ll scheduler" + depends on ACE + help + Select if you want to protect ll scheduler with a watchdog timer. + The watchdog is enabled after creating a ll thread for specified + core. When all tasks are finished, the watchdog will be disabled + before stopping the thread. Periodically, after each tick has been + handled, the watchdog counter is reseted. endmenu diff --git a/src/platform/ace30/include/platform/lib/clk.h b/src/platform/ace30/include/platform/lib/clk.h new file mode 100644 index 000000000000..efba9f8129a0 --- /dev/null +++ b/src/platform/ace30/include/platform/lib/clk.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <ace/lib/clk.h> + +#define CLK_MAX_CPU_HZ CONFIG_XTENSA_CCOUNT_HZ + +#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 NUM_CPU_FREQ 3 + +#define PRIMARY_CORE_BASE_CPS_USAGE 20000 +#define SECONDARY_CORE_BASE_CPS_USAGE 10000 + +#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/ace30/include/platform/lib/mailbox.h b/src/platform/ace30/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..7d253fd9327e --- /dev/null +++ b/src/platform/ace30/include/platform/lib/mailbox.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <ace/lib/mailbox.h> + +#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/ace30/include/platform/lib/memory.h b/src/platform/ace30/include/platform/lib/memory.h new file mode 100644 index 000000000000..70888798e22a --- /dev/null +++ b/src/platform/ace30/include/platform/lib/memory.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + * + * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +/* prioritize definitions in Zephyr SoC layer */ +#include <adsp_memory.h> + +#include <ace/lib/memory.h> +#include <mem_window.h> +#include <sof/lib/cpu.h> + +/* 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 CONFIG_SOF_ZEPHYR_HEAP_SIZE + +#if CONFIG_COLD_STORE_EXECUTE_DRAM && \ + (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD)) +#define __cold __section(".cold") +#define __cold_rodata __section(".coldrodata") +#endif + +#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/ace30/include/platform/platform.h b/src/platform/ace30/include/platform/platform.h new file mode 100644 index 000000000000..62ba6a24fe97 --- /dev/null +++ b/src/platform/ace30/include/platform/platform.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + * Xiuli Pan <xiuli.pan@linux.intel.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#include <rtos/clk.h> + +/*! \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) + +#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/ace30/include/platform/trace/trace.h b/src/platform/ace30/include/platform/trace/trace.h new file mode 100644 index 000000000000..2e1e6022854f --- /dev/null +++ b/src/platform/ace30/include/platform/trace/trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <stdint.h> + +/* 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/ace30/lib/clk.c b/src/platform/ace30/lib/clk.c new file mode 100644 index 000000000000..34fd9e7f653f --- /dev/null +++ b/src/platform/ace30/lib/clk.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2024 Intel Corporation. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/common.h> +#include <rtos/clk.h> + +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/amd/CMakeLists.txt b/src/platform/amd/CMakeLists.txt new file mode 100644 index 000000000000..5b971f6e4b9e --- /dev/null +++ b/src/platform/amd/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause +add_subdirectory(common) +if(CONFIG_RENOIR) + add_subdirectory(renoir) +elseif(CONFIG_REMBRANDT) + add_subdirectory(rembrandt) +elseif(CONFIG_VANGOGH) + add_subdirectory(vangogh) +elseif(CONFIG_ACP_6_3) + add_subdirectory(acp_6_3) +elseif(CONFIG_ACP_7_0) + add_subdirectory(acp_7_0) +endif() diff --git a/src/platform/baytrail/CMakeLists.txt b/src/platform/amd/acp_6_3/CMakeLists.txt similarity index 100% rename from src/platform/baytrail/CMakeLists.txt rename to src/platform/amd/acp_6_3/CMakeLists.txt diff --git a/src/platform/amd/acp_6_3/acp_6_3.x.in b/src/platform/amd/acp_6_3/acp_6_3.x.in new file mode 100644 index 000000000000..44de135f96f3 --- /dev/null +++ b/src/platform/amd/acp_6_3/acp_6_3.x.in @@ -0,0 +1,581 @@ +/* + * Linker Script for AMD ACP_6_3 + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_WINDOW_VECTORS_VADDR, //XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int6_lit : + org = XCHAL_INTLEVEL6_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int6_text : + org = XCHAL_INTLEVEL6_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + + vector_int7_lit : + org = XCHAL_INTLEVEL7_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int7_text : + org = XCHAL_INTLEVEL7_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE, + len = IRAM_BASE + (XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE) + sof_sdram0 : + org = DRAM0_BASE, + len = DRAM0_SIZE + DRAM1_SIZE - SOF_STACK_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END, +sof_sdram1 : + org = DRAM1_BASE, + len = DRAM1_SIZE +sof_sram1 : + org = SRAM1_BASE, + len = SRAM1_SIZE + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_iram_text_start_phdr PT_LOAD; + sof_sdram0_phdr PT_LOAD; + sof_sram1_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_sdram1_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_WINDOW_VECTORS_VADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x20004400; +_memmap_cacheattr_wt_base = 0x20001100; +_memmap_cacheattr_bp_base = 0x20002200; +_memmap_cacheattr_unused_mask = 0x0FFF00FF; +_memmap_cacheattr_wb_trapnull = 0x2222442F; +_memmap_cacheattr_wba_trapnull = 0x2222442F; +_memmap_cacheattr_wbna_trapnull = 0x2222552F; +_memmap_cacheattr_wt_trapnull = 0x2222112F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0x2FFF44FF; +_memmap_cacheattr_wt_strict = 0x2FFF11FF; +_memmap_cacheattr_bp_strict = 0x2FFF22FF; +_memmap_cacheattr_wb_allvalid = 0x22224422; +_memmap_cacheattr_wt_allvalid = 0x22221122; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .Level5InterruptVector.literal : ALIGN(4) + { + _Level5InterruptVector_literal_start = ABSOLUTE(.); + *(.Level5InterruptVector.literal) + _Level5InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .Level5InterruptVector.text : ALIGN(4) + { + _Level5InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level5InterruptVector.text)) + _Level5InterruptVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int6_lit :vector_int6_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int6_text :vector_int6_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int7_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int7_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >sof_iram_text_start :sof_iram_text_start_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_iram_text_start :sof_iram_text_start_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sram1 :sof_sram1_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sram1 :sof_sram1_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sram1 :sof_sram1_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sram1 :sof_sram1_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + } >sof_sram1 :sof_sram1_phdr + + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sram1 :sof_sram1_phdr + + +.sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sram1 :sof_sram1_phdr + + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + +} diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/core-isa.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..e006725edc39 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,714 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=7490; Build=0xa28f5; Copyright (c) 1999-2022 Tensilica 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. */ + +#ifndef XTENSA_CORE_CONFIGURATION_H_ +#define XTENSA_CORE_CONFIGURATION_H_ + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 16 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 0 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 1 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 1 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 1 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 1 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_DP_VFPU 0 /* Double-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_LDPC 0 /* LDPC option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6, Q7 or Q8 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_DP_VFPU 0 /* dp_vfpu option on Vision Q7/Q8 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 16 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1406000 /* sw version of this header */ +#define XCHAL_SW_VERSION_MAJOR 14000 /* major ver# of sw */ +#define XCHAL_SW_VERSION_MINOR 6 /* minor ver# of sw */ +#define XCHAL_SW_VERSION_MICRO 0 /* micro ver# of sw */ +#define XCHAL_SW_MINOR_VERSION 1406000 /* with zeroed micro */ +#define XCHAL_SW_MICRO_VERSION 1406000 + +#define XCHAL_CORE_ID "ACP_6_3_HiFi5_PROD_Linux" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000A28F5 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC3038286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x29892812 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.6" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 6 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO 0 /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281060 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_6 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 6 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281060 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 6 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO 0 /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281060 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +/* Config is enabled for secure operation: */ +#define XCHAL_HAVE_SECURE 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 131072 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 17 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 8 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 1 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_L1VCACHE_SIZE 0 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ +#define XCHAL_HAVE_L2_CACHE 0 +#define XCHAL_NUM_CORES_IN_CLUSTER 0 + +/* PRID_ID macros are for internal use only ... subject to removal */ +#define PRID_ID_SHIFT 0 +#define PRID_ID_BITS 4 +#define PRID_ID_MASK 0x0000000F + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 8 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x7F000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x7F000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0xE0000000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0xE0000000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + IDMA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_IDMA 0 + + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 9 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 5 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00000143 +#define XCHAL_INTLEVEL2_MASK 0x00000004 +#define XCHAL_INTLEVEL3_MASK 0x00000008 +#define XCHAL_INTLEVEL4_MASK 0x00000010 +#define XCHAL_INTLEVEL5_MASK 0x00000020 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000080 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00000143 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00000147 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0000014F +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0000015F +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0000017F +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0000017F +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x000001FF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 2 +#define XCHAL_INT3_LEVEL 3 +#define XCHAL_INT4_LEVEL 4 +#define XCHAL_INT5_LEVEL 5 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 7 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFFFE00 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00000138 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_NMI 0x00000080 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000002 +#define XCHAL_INTTYPE_MASK_TIMER 0x00000041 +#define XCHAL_INTTYPE_MASK_ETIE 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000004 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_WWDT 0x00000000 +#define XCHAL_INTTYPE_MASK_FXLK 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 0 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 6 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 7 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 2 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL2_NUM 2 +#define XCHAL_INTLEVEL3_NUM 3 +#define XCHAL_INTLEVEL4_NUM 4 +#define XCHAL_INTLEVEL5_NUM 5 +#define XCHAL_INTLEVEL7_NUM 7 +/* (There are many interrupts each at level(s) 1.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 3 /* (intlevel 3) */ +#define XCHAL_EXTINT1_NUM 4 /* (intlevel 4) */ +#define XCHAL_EXTINT2_NUM 5 /* (intlevel 5) */ +#define XCHAL_EXTINT3_NUM 7 /* (intlevel 7) */ +#define XCHAL_EXTINT4_NUM 8 /* (intlevel 1) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT3_EXTNUM 0 /* (intlevel 3) */ +#define XCHAL_INT4_EXTNUM 1 /* (intlevel 4) */ +#define XCHAL_INT5_EXTNUM 2 /* (intlevel 5) */ +#define XCHAL_INT7_EXTNUM 3 /* (intlevel 7) */ +#define XCHAL_INT8_EXTNUM 4 /* (intlevel 1) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ + +#define XCHAL_RESET_VECOFS 0x00000000 +#define XCHAL_RESET_VECTOR_VADDR 0x7F000000 +#define XCHAL_RESET_VECTOR_PADDR 0x7F000000 +#define XCHAL_USER_VECOFS 0x00000000 +#define XCHAL_USER_VECTOR_VADDR 0x7F000740 +#define XCHAL_USER_VECTOR_PADDR 0x7F000740 +#define XCHAL_KERNEL_VECOFS 0x00000000 +#define XCHAL_KERNEL_VECTOR_VADDR 0x7F000700 +#define XCHAL_KERNEL_VECTOR_PADDR 0x7F000700 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x7F0007C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x7F0007C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x7F000400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x7F000400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000000 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x7F000580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x7F000580 +#define XCHAL_INTLEVEL3_VECOFS 0x00000000 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x7F0005C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x7F0005C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000000 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x7F000600 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x7F000600 +#define XCHAL_INTLEVEL5_VECOFS 0x00000000 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x7F000640 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x7F000640 +#define XCHAL_INTLEVEL6_VECOFS 0x00000000 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x7F000680 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x7F000680 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000000 +#define XCHAL_NMI_VECTOR_VADDR 0x7F0006C0 +#define XCHAL_NMI_VECTOR_PADDR 0x7F0006C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 1 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 0 +#define XCHAL_MPU_ENTRIES 0 +#define XCHAL_MPU_LOCK 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 0 +#define XCHAL_MPU_ALIGN 0 + +/*----------------------------------------------------------------------- + CSR Parity +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_CSR_PARITY 0 + + +/*---------------------------------------------------------------------- + FLEX-LOCK +------------------------------------------------------------------------*/ + +#define XCHAL_HAVE_FXLK 0 + +/*---------------------------------------------------------------------- + WWDT (Windowed Watchdog Timer) +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_WWDT 0 +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* XTENSA_CORE_CONFIGURATION_H_ */ + diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/core-matmap.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..5195b5230905 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,317 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=7490; Build=0xa28f5; Copyright (c) 1999-2022 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + +#define XCHAL_CA_R (0xC0 | 0x40000000) +#define XCHAL_CA_RX (0xD0 | 0x40000000) +#define XCHAL_CA_RW (0xE0 | 0x40000000) +#define XCHAL_CA_RWX (0xF0 | 0x40000000) + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ +#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefine hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Reset PPN values for each entry of ITLB way set 0 (because SET0_PPN_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_RESET 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_RESET 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_RESET 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_RESET 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_RESET 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_RESET 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_RESET 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_RESET 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Reset PPN values for each entry of DTLB way set 0 (because SET0_PPN_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_RESET 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_RESET 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_RESET 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_RESET 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_RESET 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_RESET 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_RESET 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_RESET 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/defs.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..0da4586ce0d3 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=12153; Build=0x878bf; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/specreg.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..0c54c7290dd6 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/specreg.h @@ -0,0 +1,108 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Homewood/ib.6/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=7490; Build=0xa28f5; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define SCOMPARE1 12 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define ATOMCTL 99 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define MISC_REG_0 244 +#define MISC_REG_1 245 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/system.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..31459310d3d7 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/system.h @@ -0,0 +1,262 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=7490; Build=0xa28f5; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +#define XSHAL_ROM_VADDR 0x50000000 +#define XSHAL_ROM_PADDR 0x50000000 +#define XSHAL_ROM_SIZE 0x00020000 +/* Largest available area (free of vectors): */ +#define XSHAL_ROM_AVAIL_VADDR 0x50000000 +#define XSHAL_ROM_AVAIL_VSIZE 0x00020000 + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x60000000 +#define XSHAL_RAM_PADDR 0x60000000 +#define XSHAL_RAM_VSIZE 0x1F000000 +#define XSHAL_RAM_PSIZE 0x1F000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x60000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x1F000000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x1F000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xc0000000 +#define XSHAL_STL_INFO_LOCATION 0x9ffffffc + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x42224422 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x12221122 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x12221122 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0x4FFF44FF /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0x1FFF11FF /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0x1FFF11FF /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0x2FFF22FF /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x4222442F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x1222112F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x1222112F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x4FF2442F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x1FF2112F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x1FF2112F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0x2FF2222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000044 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 0 +#define XSHAL_RESET_VECTOR_VADDR 0x7F000000 +#define XSHAL_RESET_VECTOR_PADDR 0x7F000000 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x00000300 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x00000038 +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x00000038 +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/tie-asm.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..ce8f0103809b --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,366 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=7490; Build=0xa28f5; Copyright (c) 1999-2022 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + rsr.br \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.scompare1 \at1 // conditional store option + s32i \at1, \ptr, .Lxchal_ofs_+4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 // boolean option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.scompare1 \at1 // conditional store option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed16, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed24, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed31, \ptr, .Lxchal_ofs_+48 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+56 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+57 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+58 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+59 + addi.a \ptr, \ptr, 64 + ae_salign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_salign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_salign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_salign128.i u3, \ptr, .Lxchal_ofs_+48 + addi.a \ptr, \ptr, -320 + ae_movdrzbvc aed0 // ureg AE_ZBIASV8C + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 + rur.ae_ovf_sar \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_bithead \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_ts_fts_bu_bp \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cw_sd_no \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.ae_cbegin0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.ae_cend0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+36 + rur.ae_cbegin1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+40 + rur.ae_cend1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+44 + rur.ae_cbegin2 \at1 // ureg 250 + s32i \at1, \ptr, .Lxchal_ofs_+48 + rur.ae_cend2 \at1 // ureg 251 + s32i \at1, \ptr, .Lxchal_ofs_+52 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg AE_ZBIASV8C + ae_movzbvcdr aed0 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ovf_sar \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_bithead \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_ts_fts_bu_bp \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cw_sd_no \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.ae_cbegin0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.ae_cend0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+40 + wur.ae_cbegin1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+44 + wur.ae_cend1 \at1 // ureg 249 + l32i \at1, \ptr, .Lxchal_ofs_+48 + wur.ae_cbegin2 \at1 // ureg 250 + l32i \at1, \ptr, .Lxchal_ofs_+52 + wur.ae_cend2 \at1 // ureg 251 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed16, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed24, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed31, \ptr, .Lxchal_ofs_+48 + addi.a \ptr, \ptr, 56 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi.a \ptr, \ptr, 8 + ae_lalign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_lalign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_lalign128.i u3, \ptr, .Lxchal_ofs_+48 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 320 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 64 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/config/tie.h b/src/platform/amd/acp_6_3/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..22fe621c7127 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/config/tie.h @@ -0,0 +1,211 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=7490; Build=0xa28f5; Copyright (c) 1999-2022 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 384 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 16 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 12 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 400 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 16 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 3 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 52 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ae_zbiasv8c,16, 8, 8,0x1029, ur,-1 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x102A, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin2, 4, 4, 4,0x03FA, ur,250, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend2, 4, 4, 4,0x03FB, ur,251, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed16, 8, 8, 8,0x1010, aed,16 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed17, 8, 8, 8,0x1011, aed,17 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed18, 8, 8, 8,0x1012, aed,18 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed19, 8, 8, 8,0x1013, aed,19 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed20, 8, 8, 8,0x1014, aed,20 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed21, 8, 8, 8,0x1015, aed,21 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed22, 8, 8, 8,0x1016, aed,22 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed23, 8, 8, 8,0x1017, aed,23 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed24, 8, 8, 8,0x1018, aed,24 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed25, 8, 8, 8,0x1019, aed,25 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed26, 8, 8, 8,0x101A, aed,26 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed27, 8, 8, 8,0x101B, aed,27 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed28, 8, 8, 8,0x101C, aed,28 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed29, 8, 8, 8,0x101D, aed,29 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed30, 8, 8, 8,0x101E, aed,30 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed31, 8, 8, 8,0x101F, aed,31 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1024, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1025, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1026, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1027, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0,16,16,16,0x1020, u,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1,16,16,16,0x1021, u,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2,16,16,16,0x1022, u,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3,16,16,16,0x1023, u,3 ,128,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/amd/acp_6_3/include/arch/xtensa/tie/xt_datacache.h b/src/platform/amd/acp_6_3/include/arch/xtensa/tie/xt_datacache.h new file mode 100644 index 000000000000..8e83064e2923 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/arch/xtensa/tie/xt_datacache.h @@ -0,0 +1,132 @@ +// Customer ID=12153; Build=0x878bf; Copyright (c) 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. + +/* Definitions for the xt_datacache TIE package */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_datacache_HEADER +#define _XTENSA_xt_datacache_HEADER + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#ifndef _ASMLANGUAGE +#ifndef _NOCLANGUAGE +#ifndef __ASSEMBLER__ + +#include <xtensa/tie/xt_core.h> + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_datacache_DHI(const int * s, immediate i); +extern void _TIE_xt_datacache_DHI_B(const int * s, int i); +extern void _TIE_xt_datacache_DHU(const int * s, immediate i); +extern void _TIE_xt_datacache_DHWB(const int * s, immediate i); +extern void _TIE_xt_datacache_DHWBI(const int * s, immediate i); +extern void _TIE_xt_datacache_DHWBI_B(const int * s, int i); +extern void _TIE_xt_datacache_DHWB_B(const int * s, int i); +extern void _TIE_xt_datacache_DII(const int * s, immediate i); +extern void _TIE_xt_datacache_DIU(const int * s, immediate i); +extern void _TIE_xt_datacache_DIWB(const int * s, immediate i); +extern void _TIE_xt_datacache_DIWBI(const int * s, immediate i); +extern void _TIE_xt_datacache_DIWBUI_P(const int * s /*inout*/); +extern void _TIE_xt_datacache_DPFL(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFM_B(const int * s, int i); +extern void _TIE_xt_datacache_DPFM_BF(const int * s, int i); +extern void _TIE_xt_datacache_DPFR(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFRO(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFR_B(const int * s, int i); +extern void _TIE_xt_datacache_DPFR_BF(const int * s, int i); +extern void _TIE_xt_datacache_DPFW(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFWO(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFW_B(const int * s, int i); +extern void _TIE_xt_datacache_DPFW_BF(const int * s, int i); +extern int _TIE_xt_datacache_LDCT(const int * s); +extern int _TIE_xt_datacache_LDCW(const int * s); +extern void _TIE_xt_datacache_PFEND_A(void); +extern void _TIE_xt_datacache_PFEND_O(void); +extern void _TIE_xt_datacache_PFNXT_F(void); +extern void _TIE_xt_datacache_PFWAIT_A(void); +extern void _TIE_xt_datacache_PFWAIT_R(void); +extern void _TIE_xt_datacache_SDCT(int t, int * s); +extern void _TIE_xt_datacache_SDCW(int t, int * s); + +#endif /*__ASSEMBLER__*/ +#endif /*_NOCLANGUAGE*/ +#endif /*_ASMLANGUAGE*/ + +#define XT_DHI _TIE_xt_datacache_DHI +#define XT_DHI_B _TIE_xt_datacache_DHI_B +#define XT_DHU _TIE_xt_datacache_DHU +#define XT_DHWB _TIE_xt_datacache_DHWB +#define XT_DHWBI _TIE_xt_datacache_DHWBI +#define XT_DHWBI_B _TIE_xt_datacache_DHWBI_B +#define XT_DHWB_B _TIE_xt_datacache_DHWB_B +#define XT_DII _TIE_xt_datacache_DII +#define XT_DIU _TIE_xt_datacache_DIU +#define XT_DIWB _TIE_xt_datacache_DIWB +#define XT_DIWBI _TIE_xt_datacache_DIWBI +#define XT_DIWBUI_P _TIE_xt_datacache_DIWBUI_P +#define XT_DPFL _TIE_xt_datacache_DPFL +#define XT_DPFM_B _TIE_xt_datacache_DPFM_B +#define XT_DPFM_BF _TIE_xt_datacache_DPFM_BF +#define XT_DPFR _TIE_xt_datacache_DPFR +#define XT_DPFRO _TIE_xt_datacache_DPFRO +#define XT_DPFR_B _TIE_xt_datacache_DPFR_B +#define XT_DPFR_BF _TIE_xt_datacache_DPFR_BF +#define XT_DPFW _TIE_xt_datacache_DPFW +#define XT_DPFWO _TIE_xt_datacache_DPFWO +#define XT_DPFW_B _TIE_xt_datacache_DPFW_B +#define XT_DPFW_BF _TIE_xt_datacache_DPFW_BF +#define XT_LDCT _TIE_xt_datacache_LDCT +#define XT_LDCW _TIE_xt_datacache_LDCW +#define XT_PFEND_A _TIE_xt_datacache_PFEND_A +#define XT_PFEND_O _TIE_xt_datacache_PFEND_O +#define XT_PFNXT_F _TIE_xt_datacache_PFNXT_F +#define XT_PFWAIT_A _TIE_xt_datacache_PFWAIT_A +#define XT_PFWAIT_R _TIE_xt_datacache_PFWAIT_R +#define XT_SDCT _TIE_xt_datacache_SDCT +#define XT_SDCW _TIE_xt_datacache_SDCW + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* !_XTENSA_xt_datacache_HEADER */ diff --git a/src/platform/amd/acp_6_3/include/platform/chip_offset_byte.h b/src/platform/amd/acp_6_3/include/platform/chip_offset_byte.h new file mode 100644 index 000000000000..ac60c3d6cc1c --- /dev/null +++ b/src/platform/amd/acp_6_3/include/platform/chip_offset_byte.h @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ + +#ifndef _ACP_6_3_OFFSET_HEADER +#define _ACP_6_3_OFFSET_HEADER + +#define PU_REGISTER_BASE (0x9FD00000 - 0x01240000) +#define PU_SCRATCH_REG_BASE (0x9FF00000 - 0x01250000) + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 + +/* Registers from ACP_MISC block */ +#define ACP_CLKMUX_SEL 0x124102C +#define ACP_I2S_196MHZ_CLK_SEL 0x124105C +#define ACP_DSP0_INTR_CNTL 0x1241800 +#define ACP_DSP0_INTR_STAT 0x1241804 +#define ACP_DSP_SW_INTR_CNTL 0x1241808 +#define ACP_DSP_SW_INTR_STAT 0x124180C +#define ACP_SW_INTR_TRIG 0x1241810 +#define DSP_INTERRUPT_ROUTING_CTRL_0 0x1241814 +#define DSP_INTERRUPT_ROUTING_CTRL_1 0x1241818 +#define ACP_FUTURE_REG_ACLK_0 0x1241854 +#define ACP_AXI2DAGB_SEM_0 0x1241874 +#define ACP_DSP0_INTR_CNTL1 0x1241920 +#define ACP_DSP0_INTR_STAT1 0x1241924 +#define ACP_SRBM_CLIENT_BASE_ADDR 0x12419EC +#define ACP_SRBM_CLIENT_RDDATA 0x12419F0 +#define ACP_SRBM_CYCLE_STS 0x12419F4 +#define ACP_SRBM_CLIENT_CONFIG 0x12419F8 + +/* Registers from ACP_P1_MISC block */ +#define ACP_EXTERNAL_INTR_ENB 0x1241A00 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_AUDIO_RX_RINGBUFADDR 0x1242000 +#define ACP_AUDIO_RX_RINGBUFSIZE 0x1242004 +#define ACP_AUDIO_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_AUDIO_RX_FIFOADDR 0x124200C +#define ACP_AUDIO_RX_FIFOSIZE 0x1242010 +#define ACP_AUDIO_RX_DMA_SIZE 0x1242014 +#define ACP_AUDIO_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define ACP_AUDIO_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define ACP_AUDIO_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_AUDIO_TX_RINGBUFADDR 0x1242024 +#define ACP_AUDIO_TX_RINGBUFSIZE 0x1242028 +#define ACP_AUDIO_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_AUDIO_TX_FIFOADDR 0x1242030 +#define ACP_AUDIO_TX_FIFOSIZE 0x1242034 +#define ACP_AUDIO_TX_DMA_SIZE 0x1242038 +#define ACP_AUDIO_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define ACP_AUDIO_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define ACP_AUDIO_TX_INTR_WATERMARK_SIZE 0x1242044 + +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C + +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 +#define ACP_I2STDM0_MSTRCLKGEN 0x1242414 +#define ACP_I2STDM2_MSTRCLKGEN 0x124241C + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_HSTDM_IER 0x1242814 +#define ACP_HSTDM_IRER 0x1242818 +#define ACP_HSTDM_RXFRMT 0x124281C +#define ACP_HSTDM_ITER 0x1242820 +#define ACP_HSTDM_TXFRMT 0x1242824 + +/* Registers from ACP_WOV block */ +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 + +#define ACP_SW_EN 0x1243000 +#define ACP_SW_EN_STATUS 0x1243004 +#define ACP_SW_AUDIO_TX_EN 0x1243010 +#define ACP_SW_AUDIO_TX_EN_STATUS 0x1243014 +#define ACP_SW_BT_TX_EN 0x1243050 +#define ACP_SW_BT_TX_EN_STATUS 0x1243054 +#define ACP_SW_HS_TX_EN 0x124306C +#define ACP_SW_HS_TX_EN_STATUS 0x1243070 +#define ACP_SW_AUDIO_RX_EN 0x1243088 +#define ACP_SW_AUDIO_RX_EN_STATUS 0x124308C +#define ACP_SW_BT_RX_EN 0x1243128 +#define ACP_SW_BT_RX_EN_STATUS 0x124312C +#define ACP_SW_HS_RX_EN 0x1243144 +#define ACP_SW_HS_RX_EN_STATUS 0x1243148 +/* Registers from ACP_P1_AUDIO_BUFFERS block */ +#define ACP_P1_I2S_RX_RINGBUFADDR 0x1243A00 +#define ACP_P1_I2S_RX_RINGBUFSIZE 0x1243A04 +#define ACP_P1_I2S_RX_FIFOADDR 0x1243A0C +#define ACP_P1_I2S_RX_FIFOSIZE 0x1243A10 +#define ACP_P1_I2S_RX_DMA_SIZE 0x1243A14 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1243A18 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW 0x1243A1C +#define ACP_P1_I2S_RX_INTR_WATERMARK_SIZE 0x1243A20 +#define ACP_P1_I2S_TX_RINGBUFADDR 0x1243A24 +#define ACP_P1_I2S_TX_RINGBUFSIZE 0x1243A28 +#define ACP_P1_I2S_TX_FIFOADDR 0x1243A30 +#define ACP_P1_I2S_TX_FIFOSIZE 0x1243A34 +#define ACP_P1_I2S_TX_DMA_SIZE 0x1243A38 +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x1243A3C +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1243A40 +#define ACP_P1_I2S_TX_INTR_WATERMARK_SIZE 0x1243A44 +#define ACP_P1_BT_RX_RINGBUFADDR 0x1243A48 +#define ACP_P1_BT_RX_RINGBUFSIZE 0x1243A4C +#define ACP_P1_BT_RX_FIFOADDR 0x1243A54 +#define ACP_P1_BT_RX_FIFOSIZE 0x1243A58 +#define ACP_P1_BT_RX_DMA_SIZE 0x1243A5C +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1243A60 +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW 0x1243A64 +#define ACP_P1_BT_RX_INTR_WATERMARK_SIZE 0x1243A68 +#define ACP_P1_BT_TX_RINGBUFADDR 0x1243A6C +#define ACP_P1_BT_TX_RINGBUFSIZE 0x1243A70 +#define ACP_P1_BT_TX_FIFOADDR 0x1243A78 +#define ACP_P1_BT_TX_FIFOSIZE 0x1243A7C +#define ACP_P1_BT_TX_DMA_SIZE 0x1243A80 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1243A84 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW 0x1243A88 +#define ACP_P1_BT_TX_INTR_WATERMARK_SIZE 0x1243A8C +#define ACP_P1_HS_RX_RINGBUFADDR 0x1243A90 +#define ACP_P1_HS_RX_RINGBUFSIZE 0x1243A94 +#define ACP_P1_HS_RX_FIFOADDR 0x1243A9C +#define ACP_P1_HS_RX_FIFOSIZE 0x1243AA0 +#define ACP_P1_HS_RX_DMA_SIZE 0x1243AA4 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH 0x1243AA8 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW 0x1243AAC +#define ACP_P1_HS_RX_INTR_WATERMARK_SIZE 0x1243AB0 +#define ACP_P1_HS_TX_RINGBUFADDR 0x1243AB4 +#define ACP_P1_HS_TX_RINGBUFSIZE 0x1243AB8 +#define ACP_P1_HS_TX_FIFOADDR 0x1243AC0 +#define ACP_P1_HS_TX_FIFOSIZE 0x1243AC4 +#define ACP_P1_HS_TX_DMA_SIZE 0x1243AC8 +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH 0x1243ACC +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW 0x1243AD0 +#define ACP_P1_HS_TX_INTR_WATERMARK_SIZE 0x1243AD4 + +#define ACP_P1_SW_EN 0x1243C00 +#define ACP_P1_SW_BT_TX_EN 0x1243C50 +#define ACP_P1_SW_BT_TX_EN_STATUS 0x1243C54 +#define ACP_P1_SW_BT_RX_EN 0x1243D28 +#define ACP_P1_SW_BT_RX_EN_STATUS 0x1243D2C +#define MP1_SMN_C2PMSG_69 0x58A14 +#define MP1_SMN_C2PMSG_85 0x58A54 +#define MP1_SMN_C2PMSG_93 0x58A74 + +#define CLK5_ROOTREFCLKMUX_1 0x6c0c8 +#define CLK5_CLK_PLL_REFCLK_RATE_STARTUP 0x6C0D0 +#define CLK5_CLK_PLL_REQ 0x6C0DC +#define CLK5_CLK1_DFS_CNTL 0x6C1B0 +#define CLK5_CLK1_CURRENT_CNT 0x6C348 +#define CLK5_CLK0_DFS_CNTL 0x6C1A4 +#define CLK5_CLK0_CURRENT_CNT 0x6C344 +#define CLK5_CLK0_BYPASS_CNTL 0x6C200 +#define CLK5_CLK1_BYPASS_CNTL 0x6C224 +#define CLK5_CLK0_DFS_STATUS 0x6C1AC +#define CLK5_CLK1_DFS_STATUS 0x6C1B8 +#define CLK5_SPLL_FIELD_2 0x6C114 +#define CLK5_CLK_PLL_PWR_REQ 0x6C2C0 +#define CLK5_CLK_DFSBYPASS_CONTROL 0x6C2C8 +#define CLK5_CLK_FSM_STATUS 0x6C2D4 +#define CLK5_SPLL_FUSE_1 0x6C0F8 +#define CLK5_SPLL_FUSE_2 0x6C0FC +#define CLK5_SPLL_FIELD_7 0x6C128 +#define CLK5_SPLL_FIELD_9 0x6C130 +#define CLK5_SPLL_FIELD_6nm 0x6C138 +#define CLK5_SPLL_FIELD_4 0x6C11C +#define CLK5_SPLL_FIELD_5nm_BUS_CTRL 0x6c140 +#define CLK5_SPLL_FIELD_5nm_BUS_WDATA 0x6c144 +#define CLK5_SPLL_FIELD_5nm_BUS_STATUS 0x6c148 +#define CLK5_CLK_PLL_RESET_STOP_TIMER 0x6C180 + +#endif diff --git a/src/platform/amd/acp_6_3/include/platform/chip_registers.h b/src/platform/amd/acp_6_3/include/platform/chip_registers.h new file mode 100644 index 000000000000..5ea907e2ff5b --- /dev/null +++ b/src/platform/amd/acp_6_3/include/platform/chip_registers.h @@ -0,0 +1,1062 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#if !defined(_ACP_6_3_REG_HEADER) +#define _ACP_6_3_REG_HEADER + +typedef union acp_dma_cntl_0 { + struct { + unsigned int dmachrst:1; + unsigned int dmachrun:1; + unsigned int dmachiocen:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_dma_cntl_0_t; + +typedef union acp_dma_ch_sts { + struct { + unsigned int dmachrunsts:8; + unsigned int :24; + } bits; + unsigned int u32all; +} acp_dma_ch_sts_t; + +typedef union acp_external_intr_enb { + struct { + unsigned int acpextintrenb:1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_external_intr_enb_t; + +typedef union acp_dsp0_intr_cntl { + struct { + unsigned int dmaiocmask:8; + unsigned int :8; + unsigned int wov_dma_intr_mask:1; + unsigned int :6; + unsigned int audio_buffer_int_mask:6; + unsigned int :3; + } bits; + unsigned int u32all; +} acp_dsp0_intr_cntl_t; + +typedef union acp_dsp0_intr_stat { + struct { + unsigned int dmaiocstat:8; + unsigned int :8; + unsigned int wov_dma_stat:1; + unsigned int :6; + unsigned int audio_buffer_int_stat:6; + unsigned int :3; + } bits; + unsigned int u32all; +} acp_dsp0_intr_stat_t; + +typedef union acp_dsp0_intr_cntl1 { + struct { + unsigned int acp_fusion_dsp_ext_timer1_timeoutmask :1; + unsigned int fusion_dsp_watchdog_timeoutmask :1; + unsigned int soundwire_mask :1; + unsigned int audio_buffer_int_mask :6; + unsigned int :23; + } bits; + unsigned int u32all; +} acp_dsp0_intr_cntl1_t; + +typedef union acp_dsp0_intr_stat1 { + struct { + unsigned int acp_fusion_dsp_timer1_timeoutstat :1; + unsigned int fusion_dsp_watchdog_timeoutstat :1; + unsigned int soundwire_stat :1; + unsigned int audio_buffer_int_stat :6; + unsigned int :23; + } bits; + unsigned int u32all; +} acp_dsp0_intr_stat1_t; + +typedef union acp_dsp_sw_intr_cntl { + struct { + unsigned int :2; + unsigned int dsp0_to_host_intr_mask:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_dsp_sw_intr_cntl_t; + +typedef union acp_dsp_sw_intr_stat { + struct { + unsigned int host_to_dsp0_intr1_stat:1; + unsigned int host_to_dsp0_intr2_stat:1; + unsigned int dsp0_to_host_intr_stat:1; + unsigned int host_to_dsp0_intr3_stat:1; + unsigned int :28; + } bits; + unsigned int u32all; +} acp_dsp_sw_intr_stat_t; + +typedef union acp_sw_intr_trig { + struct { + unsigned int trig_host_to_dsp0_intr1:1; + unsigned int :1; + unsigned int trig_dsp0_to_host_intr:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_sw_intr_trig_t; + +typedef union dsp_interrupt_routing_ctrl_0 { + struct { + unsigned int dma_intr_level:3; + unsigned int :18; + unsigned int watchdog_intr_level:3; + unsigned int az_sw_i2s_intr_level:3; + unsigned int sha_intr_level:3; + unsigned int :2; + } bits; + unsigned int u32all; +} dsp_interrupt_routing_ctrl_0_t; + +typedef union dsp_interrupt_routing_ctrl_1 { + struct { + unsigned int host_to_dsp_intr1_level:3; + unsigned int host_to_dsp_intr2_level:3; + unsigned int src_intr_level:3; + unsigned int mailbox_intr_level:3; + unsigned int error_intr_level:3; + unsigned int wov_intr_level:3; + unsigned int fusion_timer1_intr_level:3; + unsigned int fusion_watchdog_intr_level:3; + unsigned int p1_sw_i2s_intr_level:3; + unsigned int :5; + } bits; + unsigned int u32all; +} dsp_interrupt_routing_ctrl_1_t; + +typedef union acp_i2s_rx_ringbufaddr { + struct { + unsigned int i2s_rx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_rx_ringbufaddr_t; + +typedef union acp_i2s_rx_ringbufsize { + struct { + unsigned int i2s_rx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_rx_ringbufsize_t; + +typedef union acp_i2s_rx_linkpositioncntr { + struct { + unsigned int i2s_rx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_rx_linkpositioncntr_t; + +typedef union acp_i2s_rx_fifoaddr { + struct { + unsigned int i2s_rx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_rx_fifoaddr_t; + +typedef union acp_i2s_rx_fifosize { + struct { + unsigned int i2s_rx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_rx_fifosize_t; + +typedef union acp_i2s_rx_dma_size { + struct { + unsigned int i2s_rx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_rx_dma_size_t; + +typedef union acp_i2s_rx_linearpositioncntr_high { + struct { + unsigned int i2s_rx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_high_t; + +typedef union acp_i2s_rx_linearpositioncntr_low { + struct { + unsigned int i2s_rx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_low_t; + +typedef union acp_i2s_rx_watermark_size { + struct { + unsigned int i2s_rx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_rx_intr_watermark_size_t; + +typedef union acp_i2s_tx_ringbufaddr { + struct { + unsigned int i2s_tx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_tx_ringbufaddr_t; + +typedef union acp_i2s_tx_ringbufsize { + struct { + unsigned int i2s_tx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_tx_ringbufsize_t; + +typedef union acp_i2s_tx_linkpositioncntr { + struct { + unsigned int i2s_tx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_tx_linkpositioncntr_t; + +typedef union acp_i2s_tx_fifoaddr { + struct { + unsigned int i2s_tx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_tx_fifoaddr_t; + +typedef union acp_i2s_tx_fifosize { + struct { + unsigned int i2s_tx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_tx_fifosize_t; + +typedef union acp_i2s_tx_dma_size { + struct { + unsigned int i2s_tx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_tx_dma_size_t; + +typedef union acp_i2s_tx_linearpositioncntr_high { + struct { + unsigned int i2s_tx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_hight_t; + +typedef union acp_i2s_tx_linearpositioncntr_low { + struct { + unsigned int i2s_tx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_low_t; + +typedef union acp_i2s_tx_intr_watermark_size { + struct { + unsigned int i2s_tx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_tx_intr_watermark_size_t; + +typedef union acp_bt_rx_ringbufaddr { + struct { + unsigned int bt_rx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_rx_ringbufaddr_t; + +typedef union acp_bt_rx_ringbufsize { + struct { + unsigned int bt_rx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_rx_ringbufsize_t; + +typedef union acp_bt_rx_linkpositioncntr { + struct { + unsigned int bt_rx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_rx_linkpositioncntr_t; + +typedef union acp_bt_rx_fifoaddr { + struct { + unsigned int bt_rx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_rx_fifoaddr_t; + +typedef union acp_bt_rx_fifosize { + struct { + unsigned int bt_rx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_rx_fifosize_t; + +typedef union acp_bt_rx_dma_size { + struct { + unsigned int bt_rx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_rx_dma_size_t; + +typedef union acp_bt_rx_linearpositioncntr_high { + struct { + unsigned int bt_rx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_bt_rx_linearpositioncntr_high_t; + +typedef union acp_bt_rx_linearpositioncntr_low { + struct { + unsigned int bt_rx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_bt_rx_linearpositioncntr_low_t; + +typedef union acp_bt_rx_intr_watermark_size { + struct { + unsigned int bt_rx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_rx_intr_watermark_size_t; + +typedef union acp_bt_tx_ringbufaddr { + struct { + unsigned int bt_tx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_tx_ringbufaddr_t; + +typedef union acp_bt_tx_ringbufsize { + struct { + unsigned int bt_tx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_tx_ringbufsize_t; + +typedef union acp_bt_tx_linkpositiontcntr { + struct { + unsigned int bt_tx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_tx_linkpositiontcntr_t; + +typedef union acp_bt_tx_fifoaddr { + struct { + unsigned int bt_tx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_tx_fifoaddr_t; + +typedef union acp_bt_tx_fifosize { + struct { + unsigned int bt_tx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_tx_fifosize_t; + +typedef union acp_bt_tx_dmasize { + struct { + unsigned int bt_tx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_tx_dmasize_t; + +typedef union acp_bt_tx_linearpositioncntr_high { + struct { + unsigned int bt_tx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_bt_tx_linearpositioncntr_high_t; + +typedef union acp_bt_tx_linearpositioncntr_low { + struct { + unsigned int bt_tx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_bt_tx_linearpositioncntr_low_t; + +typedef union acp_bt_tx_intr_watermark_size { + struct { + unsigned int bt_tx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_tx_intr_watermark_size_t; + +typedef union acp_i2stdm_ier { + struct { + unsigned int i2stdm_ien:1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_i2stdm_ier_t; + +typedef union acp_i2stdm_irer { + struct { + unsigned int i2stdm_rx_en:1; + unsigned int i2stdm_rx_protocol_mode:1; + unsigned int i2stdm_rx_data_path_mode:1; + unsigned int i2stdm_rx_samplen:3; + unsigned int i2stdm_rx_status:1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_i2stdm_irer_t; + +typedef union acp_i2stdm_iter { + struct { + unsigned int i2stdm_txen:1; + unsigned int i2stdm_tx_protocol_mode:1; + unsigned int i2stdm_tx_data_path_mode:1; + unsigned int i2stdm_tx_samp_len:3; + unsigned int i2stdm_tx_status:1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_i2stdm_iter_t; + +typedef union acp_bttdm_ier { + struct { + unsigned int bttdm_ien:1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_bttdm_ier_t; + +typedef union acp_bttdm_irer { + struct { + unsigned int bttdm_rx_en:1; + unsigned int bttdm_rx_protocol_mode:1; + unsigned int bttdm_rx_data_path_mode:1; + unsigned int bttdm_rx_samplen:3; + unsigned int bttdm_rx_status:1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_bttdm_irer_t; + +typedef union acp_bttdm_iter { + struct { + unsigned int bttdm_txen :1; + unsigned int bttdm_tx_protocol_mode :1; + unsigned int bttdm_tx_data_path_mode :1; + unsigned int bttdm_tx_samp_len :3; + unsigned int bttdm_tx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_bttdm_iter_t; + +typedef union acp_wov_pdm_dma_enable { + struct { + unsigned int pdm_dma_en :1; + unsigned int pdm_dma_en_status :1; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_dma_enable_t; + +typedef union acp_wov_rx_ringbufaddr { + struct { + unsigned int rx_ringbufaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_wov_rx_ringbufaddr_t; + +typedef union acp_wov_rx_ringbufsize { + struct { + unsigned int rx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_wov_rx_ringbufsize_t; + +typedef union acp_wov_rx_intr_watermark_size { + struct { + unsigned int rx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_wov_rx_intr_watermark_size_t; + +typedef union acp_wov_pdm_no_of_channels { + struct { + unsigned int pdm_no_of_channels :2; + unsigned int :30; + } bits; + unsigned int u32all; +} acp_wov_pdm_no_of_channels_t; + +typedef union acp_wov_pdm_decimation_factor { + struct { + unsigned int pdm_decimation_factor :2; + unsigned int :30; + } bits; + unsigned int u32all; +} acp_wov_pdm_decimation_factor_t; + +typedef union acp_wov_misc_ctrl { + struct { + unsigned int :3; + unsigned int pcm_data_shift_ctrl :2; + unsigned int :27; + } bits; + unsigned int u32all; +} acp_wov_misc_ctrl_t; + +typedef union acp_wov_clk_ctrl { + struct { + unsigned int brm_clk_ctrl :4; + unsigned int pdm_vad_clkdiv :2; + unsigned int :26; + } bits; + unsigned int u32all; +} acp_wov_clk_ctrl_t; + +typedef union acp_srbm_cycle_sts { + struct { + unsigned int srbm_clients_sts :1; + unsigned int :7; + } bits; + unsigned int u32all; +} acp_srbm_cycle_sts_t; + +typedef union acp_hs_rx_ringbufaddr { + struct { + unsigned int hs_rx_ringbufaddr :32; + } bits; + unsigned int u32all; +} acp_hs_rx_ringbufaddr_t; + +typedef union acp_hs_rx_ringbufsize { + struct { + unsigned int hs_rx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_ringbufsize_t; + +typedef union acp_hs_rx_linkpositioncntr { + struct { + unsigned int hs_rx_linkpositioncntr :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_linkpositioncntr_t; + +typedef union acp_hs_rx_fifoaddr { + struct { + unsigned int hs_rx_fifoaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_hs_rx_fifoaddr_t; + +typedef union acp_hs_rx_fifosize { + struct { + unsigned int hs_rx_fifosize :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_rx_fifosize_t; + +typedef union acp_hs_rx_dma_size { + struct { + unsigned int hs_rx_dma_size :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_rx_dma_size_t; + +typedef union acp_hs_rx_linearpositioncntr_high { + struct { + unsigned int hs_rx_linearpositioncntr_high :32; + } bits; + unsigned int u32all; +} acp_hs_rx_linearpositioncntr_high_t; + +typedef union acp_hs_rx_linearpositioncntr_low { + struct { + unsigned int hs_rx_linearpositioncntr_low :32; + } bits; + unsigned int u32all; +} acp_hs_rx_linearpositioncntr_low_t; + +typedef union acp_hs_rx_intr_watermark_size { + struct { + unsigned int hs_rx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_intr_watermark_size_t; + +typedef union acp_hs_tx_ringbufaddr { + struct { + unsigned int hs_tx_ringbufaddr :32; + } bits; + unsigned int u32all; +} acp_hs_tx_ringbufaddr_t; + +typedef union acp_hs_tx_ringbufsize { + struct { + unsigned int hs_tx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_ringbufsize_t; + +typedef union acp_hs_tx_linkpositioncntr { + struct { + unsigned int hs_tx_linkpositioncntr :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_linkpositioncntr_t; + +typedef union acp_hs_tx_fifoaddr { + struct { + unsigned int hs_tx_fifoaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_hs_tx_fifoaddr_t; + +typedef union acp_hs_tx_fifosize { + struct { + unsigned int hs_tx_fifosize :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_tx_fifosize_t; + +typedef union acp_hs_tx_dma_size { + struct { + unsigned int hs_tx_dma_size :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_tx_dma_size_t; + +typedef union acp_hs_tx_linearpositioncntr_high { + struct { + unsigned int hs_tx_linearpositioncntr_high :32; + } bits; + unsigned int u32all; +} acp_hs_tx_linearpositioncntr_high_t; + +typedef union acp_hs_tx_linearpositioncntr_low { + struct { + unsigned int hs_tx_linearpositioncntr_low :32; + } bits; + unsigned int u32all; +} acp_hs_tx_linearpositioncntr_low_t; + +typedef union acp_hs_tx_intr_watermark_size { + struct { + unsigned int hs_tx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_intr_watermark_size_t; + +typedef union acp_i2stdm_rxfrmt { + struct { + unsigned int i2stdm_frame_len :9; + unsigned int :6; + unsigned int i2stdm_num_slots :3; + unsigned int i2stdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_i2stdm_rxfrmt_t; + +typedef union acp_i2stdm_txfrmt { + struct { + unsigned int i2stdm_frame_len :9; + unsigned int :6; + unsigned int i2stdm_num_slots :3; + unsigned int i2stdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_i2stdm_txfrmt_t; + +typedef union acp_hstdm_ier { + struct { + unsigned int hstdm_ien :1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_hstdm_ier_t; + +typedef union acp_hstdm_irer { + struct { + unsigned int hstdm_rx_en :1; + unsigned int hstdm_rx_protocol_mode :1; + unsigned int hstdm_rx_data_path_mode :1; + unsigned int hstdm_rx_samplen :3; + unsigned int hstdm_rx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_hstdm_irer_t; + +typedef union acp_hstdm_rxfrmt { + struct { + unsigned int hstdm_frame_len :9; + unsigned int :6; + unsigned int hstdm_num_slots :3; + unsigned int hstdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_hstdm_rxfrmt_t; + +typedef union acp_hstdm_iter { + struct { + unsigned int hstdm_txen :1; + unsigned int hstdm_tx_protocol_mode :1; + unsigned int hstdm_tx_data_path_mode :1; + unsigned int hstdm_tx_samp_len :3; + unsigned int hstdm_tx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_hstdm_iter_t; + +typedef union acp_hstdm_txfrmt { + struct { + unsigned int hstdm_frame_len :9; + unsigned int :6; + unsigned int hstdm_num_slots :3; + unsigned int hstdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_hstdm_txfrmt_t; + +typedef union acp_clkmux_sel { + struct { + unsigned int acp_clkmux_sel : 3; + unsigned int : 13; + unsigned int acp_clkmux_div_value : 16; + } bits; + unsigned int u32all; +} acp_clkmux_sel_t; + +typedef union acp_i2stdm_mstrclkgen { + struct { + unsigned int i2stdm_master_mode : 1; + unsigned int i2stdm_format_mode : 1; + unsigned int i2stdm_lrclk_div_val : 11; + unsigned int i2stdm_bclk_div_val : 11; + unsigned int : 8; + } bits; + unsigned int u32all; +} acp_i2stdm_mstrclkgen_t; + +typedef union clk5_clk1_dfs_cntl_u { + struct { + unsigned int CLK1_DIVIDER : 7; + unsigned int : 25; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk1_dfs_cntl_u_t; + +typedef union clk5_clk1_dfs_status_u { + struct { + unsigned int : 16; + unsigned int CLK1_DFS_DIV_REQ_IDLE : 1; + unsigned int : 2; + unsigned int RO_CLK1_DFS_STATE_IDLE : 1; + unsigned int CLK1_CURRENT_DFS_DID : 7; + unsigned int : 5; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk1_dfs_status_u_t; + +typedef union clk5_clk1_bypass_cntl_u { + struct { + unsigned int CLK1_BYPASS_SEL : 3; + unsigned int : 13; + unsigned int CLK1_BYPASS_DIV : 4; + unsigned int : 12; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk1_bypass_cntl_u_t; + +typedef union clk5_clk_fsm_status_u { + struct { + unsigned int AUTOLAUCH_FSM_FULL_SPEED_IDLE : 1; + unsigned int : 3; + unsigned int AUTOLAUCH_FSM_BYPASS_IDLE : 1; + unsigned int : 3; + unsigned int RO_FSM_PLL_STATUS_STARTED : 1; + unsigned int : 3; + unsigned int RO_FSM_PLL_STATUS_STOPPED : 1; + unsigned int : 3; + unsigned int RO_EARLY_FSM_DONE : 1; + unsigned int : 3; + unsigned int RO_DFS_GAP_ACTIVE : 1; + unsigned int : 3; + unsigned int RO_DID_FSM_IDLE : 1; + unsigned int : 7; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk_fsm_status_t; + +typedef union clk5_clk_pll_req_u { + struct { + unsigned int fbmult_int : 9; + unsigned int : 3; + unsigned int pllspinediv : 4; + unsigned int fbmult_frac : 16; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk_pll_req_u_t; + +typedef union clk5_clk_pll_refclk_startup { + struct { + unsigned int main_pll_ref_clk_rate_startup : 8; + unsigned int main_pll_cfg_4_startup : 8; + unsigned int main_pll_ref_clk_div_startup : 2; + unsigned int main_pll_cfg_3_startup : 10; + unsigned int : 1; + unsigned int main_pll_refclk_src_mux0_startup : 1; + unsigned int main_pll_refclk_src_mux1_startup : 1; + unsigned int : 1; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk_pll_refclk_startup_t; + +typedef union clk5_spll_field_2 { + struct{ + unsigned int : 3; + unsigned int spll_fbdiv_mask_en : 1; + unsigned int spll_fracn_en : 1; + unsigned int spll_freq_jump_en : 1; + unsigned int : 25; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_2_t; + +typedef union clk5_clk_dfsbypass_cntl { + struct { + unsigned int enter_dfs_bypass_0 : 1; + unsigned int enter_dfs_bypass_1 : 1; + unsigned int : 14; + unsigned int exit_dfs_bypass_0 : 1; + unsigned int exit_dfs_bypass_1 : 1; + unsigned int : 14; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk_dfsbypass_cntl_t; + +typedef union clk5_clk_pll_pwr_req { + struct { + unsigned int PLL_AUTO_START_REQ : 1; + unsigned int : 3; + unsigned int PLL_AUTO_STOP_REQ : 1; + unsigned int : 3; + unsigned int PLL_AUTO_STOP_NOCLK_REQ : 1; + unsigned int : 3; + unsigned int PLL_AUTO_STOP_REFBYPCLK_REQ : 1; + unsigned int : 3; + unsigned int PLL_FORCE_RESET_HIGH : 1; + unsigned int : 15; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_clk_pll_pwr_req_t; + +typedef union clk5_spll_fuse_1 { + struct { + unsigned int : 8; + unsigned int spll_gp_coarse_exp : 4; + unsigned int spll_gp_coarse_mant : 4; + unsigned int : 4; + unsigned int spll_gi_coarse_exp : 4; + unsigned int : 1; + unsigned int spll_gi_coarse_mant : 2; + unsigned int : 5; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_fuse_1_t; + +typedef union clk5_spll_fuse_2 { + struct { + unsigned int spll_tdc_resolution : 8; + unsigned int spll_freq_offset_exp : 4; + unsigned int spll_freq_offset_mant : 5; + unsigned int : 15; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_fuse_2_t; + +typedef union clk5_spll_field_9 { + struct { + unsigned int : 16; + unsigned int spll_dpll_cfg_3 : 10; + unsigned int spll_fll_mode : 1; + unsigned int : 5; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_9_t; + +typedef union clk5_spll_field_6nm { + struct { + unsigned int spll_dpll_cfg_4 : 8; + unsigned int spll_reg_tim_exp : 3; + unsigned int spll_reg_tim_mant : 1; + unsigned int spll_ref_tim_exp : 3; + unsigned int spll_ref_tim_mant : 1; + unsigned int spll_vco_pre_div : 2; + unsigned int : 14; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_6nm_t; + +typedef union clk5_spll_field_7 { + struct { + unsigned int : 7; + unsigned int spll_pllout_sel : 1; + unsigned int spll_pllout_req : 1; + unsigned int spll_pllout_state : 2; + unsigned int spll_postdiv_ovrd : 4; + unsigned int spll_postdiv_pllout_ovrd : 4; + unsigned int spll_postdiv_sync_enable : 1; + unsigned int : 1; + unsigned int spll_pwr_state : 2; + unsigned int : 1; + unsigned int spll_refclk_rate : 8; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_7_t; + +typedef union clk5_spll_field_4 { + struct { + unsigned int spll_fcw0_frac_ovrd : 16; + unsigned int pll_out_sel : 1; + unsigned int : 3; + unsigned int pll_pwr_dn_state : 2; + unsigned int : 2; + unsigned int spll_refclk_div : 2; + unsigned int : 6; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_4_t; + +typedef union clk5_spll_field_5nm_bus_ctrl { + struct { + unsigned int bus_spll_async_mode :1; + unsigned int bus_spll_apb_mode :1; + unsigned int bus_spll_addr :8; + unsigned int bus_spll_byte_en :4; + unsigned int bus_spll_rdtr :1; + unsigned int bus_spll_resetb :1; + unsigned int bus_spll_sel :1; + unsigned int bus_spll_wrtr :1; + unsigned int :14; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_5nm_bus_ctrl_t; + +typedef union clk5_spll_field_5nm_bus_wdata { + struct { + unsigned int bus_spll_wr_data; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_5nm_bus_wdata_t; + +typedef union clk5_rootrefclk_mux_1 { + struct { + unsigned int ROOTREFCLK_MUX_1 : 1; + unsigned int reserved : 31; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_rootrefclk_mux_1_t; + +typedef union clk5_spll_field_5nm_bus_status { + struct { + unsigned int spll_bus_error :1; + unsigned int spll_bus_rd_valid :1; + unsigned int spll_bus_wr_ack :1; + unsigned int :29; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk5_spll_field_5nm_bus_status_t; + +#endif diff --git a/src/platform/amd/acp_6_3/include/platform/drivers/interrupt.h b/src/platform/amd/acp_6_3/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..6197427cdf92 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/platform/drivers/interrupt.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <rtos/bit.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> + +#define PLATFORM_IRQ_HW_NUM 9 + +#define PLATFORM_IRQ_FIRST_CHILD 5 + +#define PLATFORM_IRQ_CHILDREN 32 + +/* IRQ numbers - wrt Tensilica DSP */ +#define IRQ_NUM_SOFTWARE0 1 /* level 1 */ + +#define IRQ_NUM_TIMER0 0 /* level 1 */ + +#define IRQ_NUM_EXT_LEVEL3 3 /* level 1 */ + +#define IRQ_NUM_TIMER1 6 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL4 4 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL5 5 /* level 3 */ + +/* IRQ Masks */ +#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) + +#define IRQ_MASK_TIMER0 BIT(IRQ_NUM_TIMER0) + +#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) + +#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) + +#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) + +#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) + +#define HOST_TO_DSP_INTR 0x1 + +#define _XTSTR(x) # x + +#define XTSTR(x) _XTSTR(x) + +/* Enabling flag */ +#define INTERRUPT_ENABLE 1 + +/* Clearing flag */ +#define INTERRUPT_CLEAR 0 + +/* Disable flag */ +#define INTERRUPT_DISABLE 0 + +/* brief Tensilica Interrupt Levels. */ +typedef enum { + acp_interrupt_level_3 = 0, + + acp_interrupt_level_4, + + acp_interrupt_level_5, + + acp_interrupt_level_nmi, + + acp_interrupt_level_max +} artos_interrupt_levels_t; + +/* brief Tensilica timer control */ +typedef enum { + acp_timer_cntl_disable = 0, + + acp_timer_cntl_oneshot, + + acp_timer_cntl_periodic, + + acp_timer_cntl_max +} artos_timer_control_t; + +/* Disable Host to DSP interrupt */ +void acp_dsp_sw_intr_disable(void); + +void acp_intr_route(void); + +void acp_dsp_to_host_intr_trig(void); + +void acp_ack_intr_from_host(void); + +void acp_dsp_sw_intr_enable(void); + +void acp_intr_enable(void); + +void acp_intr_disable(void); + +#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/amd/acp_6_3/include/platform/fw_scratch_mem.h b/src/platform/amd/acp_6_3/include/platform/fw_scratch_mem.h new file mode 100644 index 000000000000..9f77a7d33383 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/platform/fw_scratch_mem.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifndef __EXT_SCRATCH_MEM_H__ +#define __EXT_SCRATCH_MEM_H__ + +#include <sof/lib/mailbox.h> + +/* MAX number of DMA descriptors */ +#define MAX_NUM_DMA_DESC_DSCR 64 +#define SCRATCH_REG_OFFSET 0x1250000 +#define ACP_SRAM 0x03800000 +typedef struct acp_atu_grp_pte { + uint32_t low_part; + uint32_t high_part; +} __attribute__((packed, aligned(4))) acp_atu_grp_pte_t; + +typedef union acp_cfg_dma_trns_cnt { + struct{ + uint32_t trns_cnt : 19; + uint32_t reserved : 12; + uint32_t ioc : 1; + } bits; + unsigned int u32all; +} __attribute__((packed, aligned(4))) acp_cfg_dma_trns_cnt_t; + +typedef struct acp_config_dma_descriptor { + uint32_t src_addr; + uint32_t dest_addr; + acp_cfg_dma_trns_cnt_t trns_cnt; + uint32_t reserved; +} __attribute__((packed, aligned(4))) acp_cfg_dma_descriptor_t; + +typedef struct acp_config_dma_misc { + uint32_t channelstatus; + uint32_t channel; + uint32_t flag; +} __attribute__((packed, aligned(4))) acp_cfg_dma_misc_t; + +typedef struct acp_scratch_memory_config { + /* ACP out box buffer */ + uint8_t acp_outbox_buffer[MAILBOX_DSPBOX_SIZE]; + + /* ACP in box buffer */ + uint8_t acp_inbox_buffer[MAILBOX_HOSTBOX_SIZE]; + + /* ACP debug box buffer */ + uint8_t acp_debug_buffer[MAILBOX_DEBUG_SIZE]; + + /* ACP exception box buffer */ + uint8_t acp_except_buffer[MAILBOX_EXCEPTION_SIZE]; + + /* ACP stream buffer */ + uint8_t acp_stream_buffer[MAILBOX_STREAM_SIZE]; + + /* ACP trace buffer */ + uint8_t acp_trace_buffer[MAILBOX_TRACE_SIZE]; + + /* Host msg write flag */ + uint32_t acp_host_msg_write; + + /* Host ack flag */ + uint32_t acp_host_ack_write; + + /* Dsp msg write flag */ + uint32_t acp_dsp_msg_write; + + /* Dsp ack flag */ + uint32_t acp_dsp_ack_write; + + /* ACP pte1 table */ + acp_atu_grp_pte_t acp_atugrp1_pte[16]; + + /* ACP pte2 table */ + acp_atu_grp_pte_t acp_atugrp2_pte[16]; + + /* ACP pte3 table */ + acp_atu_grp_pte_t acp_atugrp3_pte[16]; + + /* ACP pte4 table */ + acp_atu_grp_pte_t acp_atugrp4_pte[16]; + + /* ACP pte5 table */ + acp_atu_grp_pte_t acp_atugrp5_pte[16]; + + /* ACP pte6 table */ + acp_atu_grp_pte_t acp_atugrp6_pte[16]; + + /* ACP pte7 table */ + acp_atu_grp_pte_t acp_atugrp7_pte[16]; + + /* ACP pte8 table */ + acp_atu_grp_pte_t acp_atugrp8_pte[16]; + + /* ACP DMA Descriptor */ + acp_cfg_dma_descriptor_t acp_cfg_dma_descriptor[MAX_NUM_DMA_DESC_DSCR]; + + /* Stream physical offset */ + uint32_t phy_offset[8]; + + /* Stream system memory size */ + uint32_t syst_buff_size[8]; + + /* Fifo buffers are not part of scratch memory on ACP_6_3 */ + /* Added fifo members to align with Driver structure */ + /* ACP transmit fifo buffer */ + uint8_t acp_transmit_fifo_buffer[256] __attribute__((aligned(128))); + + /* ACP receive fifo buffer */ + uint8_t acp_receive_fifo_buffer[256] __attribute__((aligned(128))); + + uint32_t reserve[]; +} __attribute__((packed, aligned(4))) acp_scratch_mem_config_t; + +#endif /* __EXT_SCRATCH_MEM_H__ */ + diff --git a/src/platform/amd/acp_6_3/include/platform/lib/memory.h b/src/platform/amd/acp_6_3/include/platform/lib/memory.h new file mode 100644 index 000000000000..2597b0858715 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/platform/lib/memory.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> +#include <platform/chip_offset_byte.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN 128 + +/* physical DSP addresses */ +#define IRAM_BASE 0x7F000000 +#define IRAM_SIZE 0x60000 + +#define DRAM0_BASE 0xE0000000 +#define DRAM0_SIZE 0x10000 +#define SRAM0_BASE 0x9FF00000 + +#define DRAM1_BASE 0xE0010000 +#define DRAM1_SIZE 0x10000 +#define SRAM1_BASE 0x60006000 +#define SRAM1_SIZE 0x27A000 + +#define DMA0_BASE PU_REGISTER_BASE +#define DMA0_SIZE 0x4 + +/* DAI DMA register base address */ +#define DAI_BASE (PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR) +#define DAI_BASE_REM (PU_REGISTER_BASE + ACP_P1_I2S_RX_RINGBUFADDR) +#define DAI_SIZE 0x4 +#define BT_TX_FIFO_OFFST (ACP_P1_BT_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define BT_RX_FIFO_OFFST (ACP_P1_BT_RX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) + +#define HS_TX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define HS_RX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define SW0_AUDIO_TX_FIFO_OFFST (ACP_AUDIO_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) +#define SW0_AUDIO_RX_FIFO_OFFST (ACP_AUDIO_RX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) + +#define BT0_TX_FIFO_OFFST (ACP_BT_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) +#define BT0_RX_FIFO_OFFST (ACP_BT_RX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) + +#define HS0_TX_FIFO_OFFST (ACP_HS_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) +#define HS0_RX_FIFO_OFFST (ACP_HS_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +/* Log buffer base need to be updated properly, these are used in linker scripts */ +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* Stack configuration */ +#define SOF_STACK_SIZE 0x1000 +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE +#define SOF_STACK_END (DRAM1_BASE + DRAM1_SIZE - SOF_STACK_SIZE) +#define SOF_STACK_BASE (SOF_STACK_END + SOF_STACK_SIZE) + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE SRAM0_BASE +#define SRAM_OUTBOX_SIZE 0x400 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x400 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x400 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x400 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x400 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x400 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 192 +#define HEAP_RT_COUNT32 192 +#define HEAP_RT_COUNT64 128 +#define HEAP_RT_COUNT128 240 +#define HEAP_RT_COUNT256 128 +#define HEAP_RT_COUNT512 16 +#define HEAP_RT_COUNT1024 73 +#define HEAP_RT_COUNT2048 48 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 720 +#define HEAP_SYS_RT_COUNT512 240 +#define HEAP_SYS_RT_COUNT1024 91 + +#define SIZE_OF_MEMORY_FOR_DATA_SECTION 0x60000 + +/* Heap configuration */ +#define HEAP_SYSTEM_BASE (SRAM1_BASE + SIZE_OF_MEMORY_FOR_DATA_SECTION) +#define HEAP_SYSTEM_SIZE 0x40000 +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +#define HEAP_SYS_RUNTIME_SIZE (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE (0x60000) +#define HEAP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x7 +#define SOF_MEM_VECT_TEXT_SIZE 0x37 +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x400 +#define SOF_MEM_RESET_LIT_SIZE 0x8 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 +#define SOF_MEM_WIN_TEXT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define is_uncached(address) 0 + +#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN + +/* brief EDF task's default stack size in bytes */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +struct sof; + +#define SHARED_DATA +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} +#endif + +#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/amd/acp_6_3/include/platform/platform.h b/src/platform/amd/acp_6_3/include/platform/platform.h new file mode 100644 index 000000000000..21d77802fda7 --- /dev/null +++ b/src/platform/amd/acp_6_3/include/platform/platform.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <rtos/interrupt.h> +#include <rtos/clk.h> +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LEVEL_3 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 65536 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE (16384 + 8192) //8192 + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500 //1000 //50000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +/* default dma trace channel */ +#define DMA_TRACE_CHANNEL 7 + +/* debug offset */ +#define ACP_SOF_FW_STATUS 0 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + acp_sw_intr_trig_t sw_intr_trig; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + + pscratch_mem_cfg->acp_dsp_msg_write = p; + mailbox_sw_reg_write(ACP_SOF_FW_STATUS, p); + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt trigger register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* + * brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/baytrail/lib/CMakeLists.txt b/src/platform/amd/acp_6_3/lib/CMakeLists.txt similarity index 100% rename from src/platform/baytrail/lib/CMakeLists.txt rename to src/platform/amd/acp_6_3/lib/CMakeLists.txt diff --git a/src/platform/amd/acp_6_3/lib/clk.c b/src/platform/amd/acp_6_3/lib/clk.c new file mode 100644 index 000000000000..f060aafc22c6 --- /dev/null +++ b/src/platform/amd/acp_6_3/lib/clk.c @@ -0,0 +1,493 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 AMD.All rights reserved. +// +// Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Maruthi Machani <maruthi.machani@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <rtos/sof.h> +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +SOF_DEFINE_REG_UUID(acp_clk); + +DECLARE_TR_CTX(acp_clk_tr, SOF_UUID(acp_clk_uuid), LOG_LEVEL_INFO); + +const struct freq_table platform_cpu_freq[] = { + {600000000, 600000 }, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +void audio_pll_power_off(void); +void audio_pll_power_on(void); +void clk_dfs_bypassexit(void); +void audio_pll_mode_switch(uint32_t mode, uint32_t fcw_int, uint32_t fcw_frac, uint32_t fcw_denom, + uint32_t pllspinediv); +void clk5_init_vco(void); +void acp_6_3_reg_wait(void); +void acp_6_3_get_boot_ref_clock(float *boot_ref_clk); + +typedef enum { + PLL_MODE_100MHZ_NORMAL, + PLL_MODE_48MHZ_NORMAL, + PLL_MODE_32KHZ_LPPM, + PLL_MODE_48MHZ_LPPM, + PLL_MODE_100MHZ_LPPM +} PLL_MODE; + +/* Enumeration for the Clock Types */ +typedef enum _acp_clock_type_ { + acp_aclk_clock, + acp_sclk_clock, + acp_clock_type_max, + acp_clock_type_force = 0xFF +} acp_clock_type_t; + +static int acp_reg_read_via_smn(uint32_t reg_offset, + uint32_t size) +{ + uint32_t reg_value; + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + reg_value = (uint32_t)io_reg_read(PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + ACP_FIRST_REG_OFFSET)); + if (reg_value) + reg_value = 0; + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + while (delay_cnt > 0) { + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CLIENT_RDDATA); + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + delay_cnt--; + } + return -1; +} + +static void acp_reg_write_via_smn(uint32_t reg_offset, + uint32_t value, uint32_t size) +{ + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + io_reg_write((PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + + ACP_FIRST_REG_OFFSET)), + value); + acp_srbm_cycle_sts = + (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CYCLE_STS); + while (delay_cnt > 0) { + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return; + delay_cnt--; + } +} + +void acp_6_3_reg_wait(void) +{ + int test_count = 0; + int val = 0; + + for (test_count = 0; test_count < 255; test_count++) { + val = acp_reg_read_via_smn(CLK5_CLK_FSM_STATUS, sizeof(int)); + val = val * 0; + } +} + +void acp_6_3_get_boot_ref_clock(float *boot_ref_clk) +{ + clk5_clk_pll_refclk_startup_t boot_ref_clk_startup; + clk5_clk_pll_req_u_t clk5_clk_pll_req; + clk5_spll_field_2_t clk5_spll_field; + uint32_t spinediv = 1; + float fract_part = 0.0f; + float final_refclk = 0.0f; + + boot_ref_clk_startup.u32all = + acp_reg_read_via_smn(CLK5_CLK_PLL_REFCLK_RATE_STARTUP, sizeof(int)); + + clk5_spll_field_9_t clk_spll_field_9; + + clk_spll_field_9.u32all = 0x0; + clk_spll_field_9.u32all = acp_reg_read_via_smn(CLK5_SPLL_FIELD_9, sizeof(int)); + + if (clk_spll_field_9.bitfields.spll_dpll_cfg_3 == 0x2) + final_refclk = ((32768.0f * 128.0f) / 1000000.0f); + else + final_refclk = (float)boot_ref_clk_startup.bitfields.main_pll_ref_clk_rate_startup; + + clk5_clk_pll_req.u32all = acp_reg_read_via_smn(CLK5_CLK_PLL_REQ, sizeof(int)); + clk5_spll_field.u32all = acp_reg_read_via_smn(CLK5_SPLL_FIELD_2, sizeof(int)); + + spinediv = (1 << clk5_clk_pll_req.bitfields.pllspinediv); + + if (clk5_spll_field.bitfields.spll_fracn_en == 1) + fract_part = (float)(clk5_clk_pll_req.bitfields.fbmult_frac / (float)65536.0f); + + *boot_ref_clk = (float)(((final_refclk) * (clk5_clk_pll_req.bitfields.fbmult_int + + fract_part)) / (float)spinediv); +} + +void acp_change_clock_notify(uint32_t clock_freq) +{ + volatile clk5_clk1_dfs_cntl_u_t dfs_cntl; + volatile clk5_clk1_bypass_cntl_u_t bypass_cntl; + volatile clk5_clk1_dfs_status_u_t dfs_status; + volatile uint32_t updated_clk; + float did = 0.0f; + float fraction_val = 0.0f; + uint32_t int_did_val = 0; + float boot_ref_clk; + acp_clock_type_t clock_type = acp_aclk_clock; + + acp_6_3_get_boot_ref_clock(&boot_ref_clk); + + tr_info(&acp_clk_tr, "clock_freq : %d clock_type : %d", + clock_freq, clock_type); + + fraction_val = (float)(clock_freq / (float)1000000.0f); + clock_freq = (clock_freq / 1000000); + if (acp_aclk_clock == clock_type) { + bypass_cntl.u32all = acp_reg_read_via_smn(CLK5_CLK1_BYPASS_CNTL, sizeof(int)); + dfs_cntl.u32all = acp_reg_read_via_smn(CLK5_CLK1_DFS_CNTL, sizeof(int)); + } else if (acp_sclk_clock == clock_type) { + bypass_cntl.u32all = acp_reg_read_via_smn(CLK5_CLK0_BYPASS_CNTL, sizeof(int)); + dfs_cntl.u32all = acp_reg_read_via_smn(CLK5_CLK0_DFS_CNTL, sizeof(int)); + } + + bypass_cntl.bitfields.CLK1_BYPASS_DIV = 0; + + if (clock_freq == 6 || clock_freq == 0) { + did = 128; + dfs_cntl.bitfields.CLK1_DIVIDER = 0x7F; + bypass_cntl.bitfields.CLK1_BYPASS_DIV = 0xF; + } else { + did = (float)(boot_ref_clk / (float)fraction_val); + tr_info(&acp_clk_tr, "CLK Divider : %d boot_ref_clk : %d\n", + (uint32_t)(did * 100), (uint32_t)boot_ref_clk); + + if (did > 62.0f) { + dfs_cntl.bitfields.CLK1_DIVIDER = 0x7F; + } else { + fraction_val = did - (uint8_t)(did); + did = did - fraction_val; + if (did <= 16.00f) + did = (did * 4.0f); + else if ((did > 16.0f) && (did <= 32.0f)) + did = ((did - 16.0f) * 2.0f + 64.0f); + else if ((did > 32.0f) && (did <= 62.0f)) + did = ((did - 32.0f) + 96.0f); + + int_did_val = (uint32_t)(fraction_val * 100.0f); + fraction_val = (float)(int_did_val / 100.0f); + + if (fraction_val == 0.0f) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did); + else if (fraction_val <= 0.25f) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 1; + else if ((fraction_val > 0.25f) && (fraction_val <= 0.5f)) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 2; + else if ((fraction_val > 0.5f) && (fraction_val <= 0.75f)) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 3; + else if ((fraction_val > 0.75f)) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 4; + } + } + + if (acp_aclk_clock == clock_type) { + acp_reg_write_via_smn(CLK5_CLK1_BYPASS_CNTL, bypass_cntl.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_CLK1_DFS_CNTL, dfs_cntl.u32all, sizeof(int)); + dfs_status.u32all = acp_reg_read_via_smn(CLK5_CLK1_DFS_STATUS, sizeof(int)); + acp_6_3_reg_wait(); + + do { + dfs_status.u32all = acp_reg_read_via_smn(CLK5_CLK1_DFS_STATUS, sizeof(int)); + tr_info(&acp_clk_tr, "ACLK1 CLK1_DIVIDER : %d dfsstatus %d ", + dfs_cntl.u32all, dfs_status.u32all); + } while (dfs_status.bitfields.CLK1_DFS_DIV_REQ_IDLE == 0); + updated_clk = acp_reg_read_via_smn(CLK5_CLK1_CURRENT_CNT, sizeof(int)); + acp_6_3_reg_wait(); + + if (updated_clk < (clock_freq * 10)) { + dfs_cntl.bitfields.CLK1_DIVIDER -= 1; + dfs_status.u32all = 0; + acp_reg_write_via_smn(CLK5_CLK1_DFS_CNTL, dfs_cntl.u32all, sizeof(int)); + do { + dfs_status.u32all = + acp_reg_read_via_smn(CLK5_CLK1_DFS_STATUS, + sizeof(int)); + dfs_cntl.u32all = + acp_reg_read_via_smn(CLK5_CLK1_DFS_CNTL, + sizeof(int)); + tr_info(&acp_clk_tr, "ACLK2 CLK1_DIVIDER:%d dfsstatus %d ", + dfs_cntl.u32all, dfs_status.u32all); + } while (dfs_status.bitfields.CLK1_DFS_DIV_REQ_IDLE == 0); + } + updated_clk = acp_reg_read_via_smn(CLK5_CLK1_CURRENT_CNT, sizeof(int)); + } else if (acp_sclk_clock == clock_type) { + acp_reg_write_via_smn(CLK5_CLK0_BYPASS_CNTL, bypass_cntl.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_CLK0_DFS_CNTL, dfs_cntl.u32all, sizeof(int)); + dfs_status.u32all = acp_reg_read_via_smn(CLK5_CLK0_DFS_STATUS, sizeof(int)); + acp_6_3_reg_wait(); + + do { + dfs_status.u32all = acp_reg_read_via_smn(CLK5_CLK0_DFS_STATUS, sizeof(int)); + tr_info(&acp_clk_tr, "SCLK CLK1_DIVIDER: %d", + dfs_cntl.u32all); + } while (dfs_status.bitfields.CLK1_DFS_DIV_REQ_IDLE == 0); + + updated_clk = acp_reg_read_via_smn(CLK5_CLK0_CURRENT_CNT, sizeof(int)); + } + tr_info(&acp_clk_tr, + "clock_notify:CLK1_DIVIDER :%x boot_ref_clk : %d ClkReq : %d FinalClockValue: %d", + dfs_cntl.u32all, (uint32_t)boot_ref_clk, + clock_freq, updated_clk); +} + +void audio_pll_power_off(void) +{ + volatile clk5_clk_pll_pwr_req_t clk5_clk_pll_pwr_req; + volatile clk5_clk_fsm_status_t clk5_clk_fsm_status; + int count = 0; + + for (count = 0; count < 10; count++) { + clk5_clk_pll_pwr_req.u32all = + acp_reg_read_via_smn(CLK5_CLK_PLL_PWR_REQ, sizeof(int)); + clk5_clk_pll_pwr_req.bitfields.PLL_AUTO_STOP_REQ = 1; + + acp_reg_write_via_smn(CLK5_CLK_PLL_PWR_REQ, + clk5_clk_pll_pwr_req.u32all, sizeof(int)); + acp_6_3_reg_wait(); + + clk5_clk_fsm_status.u32all = acp_reg_read_via_smn(CLK5_CLK_FSM_STATUS, sizeof(int)); + + if (clk5_clk_fsm_status.bitfields.RO_FSM_PLL_STATUS_STOPPED == 1) + break; + } +} + +void audio_pll_power_on(void) +{ + volatile clk5_clk_pll_pwr_req_t clk5_clk_pll_pwr_req; + volatile clk5_clk_fsm_status_t clk5_clk_fsm_status; + int count = 0; + + for (count = 0; count < 10; count++) { + clk5_clk_pll_pwr_req.u32all = + acp_reg_read_via_smn(CLK5_CLK_PLL_PWR_REQ, sizeof(int)); + clk5_clk_pll_pwr_req.bitfields.PLL_AUTO_START_REQ = 1; + + acp_reg_write_via_smn(CLK5_CLK_PLL_PWR_REQ, + clk5_clk_pll_pwr_req.u32all, + sizeof(int)); + acp_6_3_reg_wait(); + + clk5_clk_fsm_status.u32all = acp_reg_read_via_smn(CLK5_CLK_FSM_STATUS, sizeof(int)); + if (clk5_clk_fsm_status.bitfields.RO_FSM_PLL_STATUS_STARTED == 1) + break; + acp_6_3_reg_wait(); + } +} + +void clk_dfs_bypassexit(void) +{ + volatile clk5_clk_dfsbypass_cntl_t clk5_clk_dfsbypass_cntl; + + clk5_clk_dfsbypass_cntl = (clk5_clk_dfsbypass_cntl_t)acp_reg_read_via_smn + (CLK5_CLK_DFSBYPASS_CONTROL, sizeof(int)); + + clk5_clk_dfsbypass_cntl.bitfields.exit_dfs_bypass_0 = 1; + clk5_clk_dfsbypass_cntl.bitfields.exit_dfs_bypass_1 = 1; + + acp_reg_write_via_smn(CLK5_CLK_DFSBYPASS_CONTROL, + clk5_clk_dfsbypass_cntl.u32all, + sizeof(int)); +} + +void audio_pll_mode_switch(uint32_t mode, uint32_t fcw_int, uint32_t fcw_frac, uint32_t fcw_denom, + uint32_t pllspinediv) +{ + volatile clk5_spll_fuse_1_t clk_spll_fuse1; + volatile clk5_spll_fuse_2_t clk_spll_fuse2; + volatile clk5_spll_field_9_t clk_spll_field_9; + volatile clk5_spll_field_6nm_t clk_spll_field_6nm; + volatile clk5_spll_field_7_t clk_spll_field_7; + volatile clk5_spll_field_4_t clk_spll_field_4; + volatile clk5_spll_field_5nm_bus_ctrl_t clk_spll_field_5nm_bus_ctrl; + volatile clk5_spll_field_5nm_bus_wdata_t clk_spll_field_5nm_bus_wdata; + volatile clk5_spll_field_5nm_bus_status_t clk_spll_field_5nm_bus_status; + volatile clk5_rootrefclk_mux_1_t clk_rootrefclkmux; + volatile clk5_spll_field_2_t clk5_spll_field_2; + + clk_spll_fuse1.u32all = 0x0; + clk_spll_fuse2.u32all = 0x0; + clk_spll_field_9.u32all = 0x0; + clk_spll_field_6nm.u32all = 0x0; + clk_spll_field_7.u32all = 0x0; + clk_spll_field_4.u32all = 0x0; + clk_spll_field_5nm_bus_ctrl.u32all = 0x0; + clk_spll_field_5nm_bus_wdata.u32all = 0x0; + clk_spll_field_5nm_bus_status.u32all = 0x0; + clk5_spll_field_2 = + (clk5_spll_field_2_t)acp_reg_read_via_smn(CLK5_SPLL_FIELD_2, sizeof(int)); + + if (clk5_spll_field_2.bitfields.spll_fracn_en == 0) + clk5_spll_field_2.bitfields.spll_fracn_en = 1; + acp_reg_write_via_smn(CLK5_SPLL_FIELD_2, clk5_spll_field_2.u32all, sizeof(int)); + + switch (mode) { + case PLL_MODE_32KHZ_LPPM: + clk_rootrefclkmux.bitfields.ROOTREFCLK_MUX_1 = 0x0; + clk_rootrefclkmux.u32all = acp_reg_read_via_smn(CLK5_ROOTREFCLKMUX_1, sizeof(int)); + + clk_rootrefclkmux.bitfields.ROOTREFCLK_MUX_1 = 1; + acp_reg_write_via_smn(CLK5_ROOTREFCLKMUX_1, clk_rootrefclkmux.u32all, sizeof(int)); + + clk_spll_fuse1.bitfields.spll_gp_coarse_exp = 0x5; + clk_spll_fuse1.bitfields.spll_gp_coarse_mant = 0x0; + clk_spll_fuse1.bitfields.spll_gi_coarse_exp = 0x7; + clk_spll_fuse1.bitfields.spll_gi_coarse_mant = 0x0; + + clk_spll_fuse2.bitfields.spll_tdc_resolution = 0xe8; + clk_spll_fuse2.bitfields.spll_freq_offset_exp = 0xa; + clk_spll_fuse2.bitfields.spll_freq_offset_mant = 0xe; + + clk_spll_field_9.bitfields.spll_dpll_cfg_3 = 2; + clk_spll_field_6nm.bitfields.spll_dpll_cfg_4 = 0x60; + clk_spll_field_6nm.bitfields.spll_vco_pre_div = 3; + clk_spll_field_7.bitfields.spll_refclk_rate = 4; + clk_spll_field_7.bitfields.spll_pwr_state = 1; + clk_spll_field_4.bitfields.spll_refclk_div = 0; + + acp_reg_write_via_smn(CLK5_SPLL_FUSE_1, clk_spll_fuse1.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_SPLL_FUSE_2, clk_spll_fuse2.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_SPLL_FIELD_9, clk_spll_field_9.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_SPLL_FIELD_6nm, clk_spll_field_6nm.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_SPLL_FIELD_7, clk_spll_field_7.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK5_SPLL_FIELD_4, clk_spll_field_4.u32all, sizeof(int)); + + clk_spll_field_5nm_bus_wdata.bitfields.bus_spll_wr_data = 0x00400000; + acp_reg_write_via_smn(CLK5_SPLL_FIELD_5nm_BUS_WDATA, + clk_spll_field_5nm_bus_wdata.u32all, + sizeof(int)); + + clk_spll_field_5nm_bus_ctrl.u32all = + acp_reg_read_via_smn(CLK5_SPLL_FIELD_5nm_BUS_CTRL, + sizeof(int)); + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_async_mode = 1; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_apb_mode = 0; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_addr = 0xa; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_byte_en = 0xf; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_rdtr = + !clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_rdtr; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_resetb = 1; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_sel = 1; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_wrtr = 1; + acp_reg_write_via_smn(CLK5_SPLL_FIELD_5nm_BUS_CTRL, + clk_spll_field_5nm_bus_ctrl.u32all, + sizeof(int)); + do { + clk_spll_field_5nm_bus_status.u32all = + acp_reg_read_via_smn(CLK5_SPLL_FIELD_5nm_BUS_STATUS, + sizeof(int)); + } while (clk_spll_field_5nm_bus_status.bitfields.spll_bus_rd_valid != + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_rdtr); + + acp_reg_write_via_smn(CLK5_CLK_PLL_RESET_STOP_TIMER, 0xbbb11aa, sizeof(int)); + break; + default: + tr_err(&acp_clk_tr, "ERROR: Invalid PLL Mode"); + return; + } + + clk5_clk_pll_req_u_t clk5_clk_pll_req; + + clk5_clk_pll_req.u32all = 0; + clk5_clk_pll_req = + (clk5_clk_pll_req_u_t)acp_reg_read_via_smn(CLK5_CLK_PLL_REQ, sizeof(int)); + clk5_clk_pll_req.bitfields.fbmult_int = fcw_int; + + if (clk5_spll_field_2.bitfields.spll_fracn_en) + clk5_clk_pll_req.bitfields.fbmult_frac = fcw_frac; + clk5_clk_pll_req.bitfields.pllspinediv = pllspinediv; + acp_reg_write_via_smn(CLK5_CLK_PLL_REQ, clk5_clk_pll_req.u32all, sizeof(int)); +} + +void clk5_init_vco(void) +{ + audio_pll_power_off(); + audio_pll_mode_switch(PLL_MODE_32KHZ_LPPM, 0x125, 0, 0, 0); + + audio_pll_power_on(); + + clk_dfs_bypassexit(); + acp_reg_write_via_smn(CLK5_CLK1_BYPASS_CNTL, 0, sizeof(int)); +} + +void platform_clock_init(struct sof *sof) +{ + int i = 0; + + sof->clocks = platform_clocks_info; + 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, + }; + } + clk5_init_vco(); +} diff --git a/src/platform/amd/acp_6_3/lib/dai.c b/src/platform/amd/acp_6_3/lib/dai.c new file mode 100644 index 000000000000..c280d8a28c85 --- /dev/null +++ b/src/platform/amd/acp_6_3/lib/dai.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +static struct dai acp_dmic_dai[] = { + { + .index = 0, + .plat_data = { + .base = DMA0_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 0, + }, + .base = DMA0_BASE, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 1, + }, + }, + .drv = &acp_dmic_dai_driver, + }, +}; + +static struct dai hsdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS_RX_FIFO_OFFST, + .depth = 8, + .handshake = 0, + }, + }, + .drv = &acp_hsdai_driver, + }, + { + .index = 1, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS_RX_FIFO_OFFST, + .depth = 8, + .handshake = 0, + }, + }, + .drv = &acp_hsdai_driver, + } +}; + +static struct dai swaudiodai[] = { + { + .index = DI_SDW0_ACP_SW_AUDIO_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + SW0_AUDIO_TX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_AUDIO_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_AUDIO_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + SW0_AUDIO_RX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_AUDIO_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_BT_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + BT0_TX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_BT_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_BT_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + BT0_RX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_BT_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_HS_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS0_TX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_HS_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_HS_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS0_RX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_HS_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_BT_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + BT_TX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_BT_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_BT_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + BT_RX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_BT_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, +}; + +#ifdef ACP_SP_ENABLE +static struct dai spdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_spdai_driver, + } +}; + +static struct dai sp_virtual_dai[] = { + { + .index = 1, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_sp_virtual_dai_driver, + } +}; +#endif +#ifdef ACP_BT_ENABLE +static struct dai btdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 2, + }, + }, + .drv = &acp_btdai_driver, + }, +}; +#endif + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_AMD_DMIC, + .dai_array = acp_dmic_dai, + .num_dais = ARRAY_SIZE(acp_dmic_dai) + }, + { + .type = SOF_DAI_AMD_HS, + .dai_array = hsdai, + .num_dais = ARRAY_SIZE(hsdai) + }, +#ifdef ACP_SP_ENABLE + { + .type = SOF_DAI_AMD_SP, + .dai_array = spdai, + .num_dais = ARRAY_SIZE(spdai) + }, + { + .type = SOF_DAI_AMD_SP_VIRTUAL, + .dai_array = sp_virtual_dai, + .num_dais = ARRAY_SIZE(sp_virtual_dai) + }, +#endif +#ifdef ACP_BT_ENABLE + { + .type = SOF_DAI_AMD_BT, + .dai_array = btdai, + .num_dais = ARRAY_SIZE(btdai) + }, +#endif + { + .type = SOF_DAI_AMD_SW_AUDIO, + .dai_array = swaudiodai, + .num_dais = ARRAY_SIZE(swaudiodai) + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(acp_dmic_dai); i++) + k_spinlock_init(&acp_dmic_dai[i].lock); + for (i = 0; i < ARRAY_SIZE(hsdai); i++) + k_spinlock_init(&hsdai[i].lock); + for (i = 0; i < ARRAY_SIZE(swaudiodai); i++) + k_spinlock_init(&swaudiodai[i].lock); +#ifdef ACP_SP_ENABLE + for (i = 0; i < ARRAY_SIZE(spdai); i++) + k_spinlock_init(&spdai[i].lock); + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(sp_virtual_dai); i++) + k_spinlock_init(&sp_virtual_dai[i].lock); +#endif +#ifdef ACP_BT_ENABLE + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(btdai); i++) + k_spinlock_init(&btdai[i].lock); +#endif + sof->dai_info = &lib_dai; + return 0; +} diff --git a/src/platform/amd/acp_6_3/lib/dma.c b/src/platform/amd/acp_6_3/lib/dma.c new file mode 100644 index 000000000000..01da5ce0b528 --- /dev/null +++ b/src/platform/amd/acp_6_3/lib/dma.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <platform/fw_scratch_mem.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +extern struct dma_ops acp_dma_ops; +extern struct dma_ops acp_dmic_dma_ops; +#ifdef ACP_BT_ENABLE +extern struct dma_ops acp_dai_bt_dma_ops; +#endif +#ifdef ACP_SP_ENABLE +extern struct dma_ops acp_dai_sp_dma_ops; +#endif +extern struct dma_ops acp_dai_hs_dma_ops; +extern struct dma_ops acp_dai_sw_audio_dma_ops; + +SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .plat_data = { + .id = DMA_ID_DMA0, + .dir = DMA_DIR_LMEM_TO_HMEM | DMA_DIR_HMEM_TO_LMEM, + .devs = DMA_DEV_HOST, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_HS, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dai_hs_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SW_AUDIO, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SW, + .caps = DMA_CAP_SW, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dai_sw_audio_dma_ops, +}, + +{ + .plat_data = { + .id = DMA_ID_DAI_DMIC, + .dir = DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_DMIC, + .caps = DMA_CAP_DMIC, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL4, + }, + .ops = &acp_dmic_dma_ops, +}, +#ifdef ACP_SP_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI_SP, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SP_VIRTUAL, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP_VIRTUAL, + .caps = DMA_CAP_SP_VIRTUAL, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_virtual_dma_ops, +}, +#endif + +#ifdef ACP_BT_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_BT, + .caps = DMA_CAP_BT, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_bt_dma_ops, +}, +#endif +}; + +const struct dma_info lib_dma = { + .dma_array = dma, + .num_dmas = ARRAY_SIZE(dma) +}; + +int acp_dma_init(struct sof *sof) +{ + int i; + uint32_t descr_base; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + descr_base = (uint32_t)(&pscratch_mem_cfg->acp_cfg_dma_descriptor); + descr_base = (descr_base - 0x9C700000); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_BASE_ADDR), descr_base); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_MAX_NUM_DSCR), 0x1); + /* 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/amd/acp_6_3/lib/memory.c b/src/platform/amd/acp_6_3/lib/memory.c new file mode 100644 index 000000000000..94047b7c488a --- /dev/null +++ b/src/platform/amd/acp_6_3/lib/memory.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 AMD +// +// Author:Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA | SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_HP, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = &memmap; +} diff --git a/src/platform/amd/acp_6_3/platform.c b/src/platform/amd/acp_6_3/platform.c new file mode 100644 index 000000000000..e0b1f2b8fe9f --- /dev/null +++ b/src/platform/amd/acp_6_3/platform.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <rtos/interrupt.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <platform/chip_offset_byte.h> + +struct sof; +static const struct sof_ipc_fw_ready ready + __attribute__((section(".fw_ready"))) = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#ifdef DEBUG_BUILD + /* only added in debug for reproducibility in releases */ + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_ACP_WINDOWS 6 + +const struct ext_man_windows xsram_window +#ifdef CONFIG_AMD_BINARY_BUILD + __aligned(EXT_MAN_ALIGN) __unused = { +#else + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { +#endif + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_ACP_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + }, +}; + +static SHARED_DATA struct timer timer = { + .id = TIMER0, + .irq = IRQ_NUM_TIMER0, +}; + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = &timer; + sof->cpu_timers = &timer; + /* to view system memory */ + interrupt_init(sof); + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + /* init low latency domains and schedulers */ + /* CONFIG_SYSTICK_PERIOD set as PLATFORM_DEFAULT_CLOCK */ + sof->platform_timer_domain = + timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + platform_timer_start(sof->platform_timer); + /*CONFIG_SYSTICK_PERIOD hardcoded as 200000*/ + sa_init(sof, 200000); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + /* init DMA */ + ret = acp_dma_init(sof); + if (ret < 0) + return -ENODEV; + /* Init DMA platform domain */ + sof->platform_dma_domain = + dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], + sizeof(sof->dma_info->dma_array), + PLATFORM_DEFAULT_CLOCK, true); + sof->platform_dma_domain->full_sync = true; + scheduler_init_ll(sof->platform_dma_domain); + /* initialize the host IPC mechanisms */ + ipc_init(sof); + /* initialize the DAI mechanisms */ + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + sof->dmat->config.elem_array.elems = + rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct dma_sg_elem) * 1); + sof->dmat->config.elem_array.count = 1; + sof->dmat->config.elem_array.elems->dest = 0x03800000; + sof->dmat->config.elem_array.elems->size = 65536; + sof->dmat->config.scatter = 0; + dma_trace_init_complete(sof->dmat); +#endif + /* show heap status */ + heap_trace_all(1); + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + acp_sw_intr_trig_t swintrtrig; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + mailbox_dspbox_write(0, &ready, sizeof(ready)); +#ifdef CONFIG_AMD_BINARY_BUILD + mailbox_dspbox_write(sizeof(ready), &xsram_window.window, sizeof(xsram_window.window)); +#endif + pscratch_mem_cfg->acp_dsp_msg_write = 1; + acp_dsp_to_host_intr_trig(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), swintrtrig.u32all); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} diff --git a/src/platform/haswell/CMakeLists.txt b/src/platform/amd/acp_7_0/CMakeLists.txt similarity index 100% rename from src/platform/haswell/CMakeLists.txt rename to src/platform/amd/acp_7_0/CMakeLists.txt diff --git a/src/platform/amd/acp_7_0/acp_7_0.x.in b/src/platform/amd/acp_7_0/acp_7_0.x.in new file mode 100644 index 000000000000..1f263e126802 --- /dev/null +++ b/src/platform/amd/acp_7_0/acp_7_0.x.in @@ -0,0 +1,586 @@ +/* + * Linker Script for AMD ACP_7_0 + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_WINDOW_VECTORS_VADDR, //XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int6_lit : + org = XCHAL_INTLEVEL6_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int6_text : + org = XCHAL_INTLEVEL6_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + + vector_int7_lit : + org = XCHAL_INTLEVEL7_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int7_text : + org = XCHAL_INTLEVEL7_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE, + len = IRAM_BASE + (XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE) + sof_sdram0 : + org = DRAM0_BASE, + len = DRAM0_SIZE + DRAM1_SIZE - SOF_STACK_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END, +sof_sdram1 : + org = DRAM1_BASE, + len = DRAM1_SIZE +sof_sram1 : + org = SRAM1_BASE, + len = SRAM1_SIZE + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_iram_text_start_phdr PT_LOAD; + sof_sdram0_phdr PT_LOAD; + sof_sram1_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_sdram1_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_WINDOW_VECTORS_VADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x40001140; +_memmap_cacheattr_wt_base = 0x40003340; +_memmap_cacheattr_bp_base = 0x40004440; +_memmap_cacheattr_unused_mask = 0x0FFF000F; +_memmap_cacheattr_wb_trapnull = 0x44441140; +_memmap_cacheattr_wba_trapnull = 0x44441140; +_memmap_cacheattr_wbna_trapnull = 0x44442240; +_memmap_cacheattr_wt_trapnull = 0x44443340; +_memmap_cacheattr_bp_trapnull = 0x44444440; +_memmap_cacheattr_wb_strict = 0x40001140; +_memmap_cacheattr_wt_strict = 0x40003340; +_memmap_cacheattr_bp_strict = 0x40004440; +_memmap_cacheattr_wb_allvalid = 0x44441144; +_memmap_cacheattr_wt_allvalid = 0x44443344; +_memmap_cacheattr_bp_allvalid = 0x44444444; +_memmap_region_map = 0x0000008E; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .Level5InterruptVector.literal : ALIGN(4) + { + _Level5InterruptVector_literal_start = ABSOLUTE(.); + *(.Level5InterruptVector.literal) + _Level5InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .Level5InterruptVector.text : ALIGN(4) + { + _Level5InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level5InterruptVector.text)) + _Level5InterruptVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int6_lit :vector_int6_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int6_text :vector_int6_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int7_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int7_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >sof_iram_text_start :sof_iram_text_start_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_iram_text_start :sof_iram_text_start_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + } >sof_sdram0 :sof_sdram0_phdr + + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + +.sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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) } + .xtensa.info 0 : { *(.xtensa.info) } + .comment 0 : { *(.comment) } + .note.GNU-stack 0 : { *(.note.GNU-stack) } + .debug_ranges 0 : { *(.debug_ranges) } + + .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.*)) + } + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + +} diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/core-isa.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..55176da88da5 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,760 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=18056; Build=0xa6a6b; Copyright (c) 1999-2023 Tensilica 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. */ + +#ifndef XTENSA_CORE_CONFIGURATION_H_ +#define XTENSA_CORE_CONFIGURATION_H_ + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 16 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ +#define XCHAL_HAVE_RNX 0 /* RNX core (starting RJ) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion */ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 1 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 1 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 1 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 1 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI1 0 /* HiFi1 */ +#define XCHAL_HAVE_HIFI1_VFPU 0 /* HiFi1 VFPU option */ +#define XCHAL_HAVE_HIFI1_LOW_LATENCY_MAC_FMA 0 /* HiFi1 Low-latency MAC/FMA option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_DP_VFPU 0 /* Double-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_DPX_VFPU 0 /* Double-precision Vector Floating-point option on FP Machine*/ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HP_VFPU 0 /* Half-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_LDPC 0 /* LDPC option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6, Q7 or Q8 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_DP_VFPU 0 /* dp_vfpu option on Vision Q7/Q8 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 1 /* XNNE */ +#define XCHAL_XNNE_VERSION 2 /* XNNE version */ +#define XCHAL_XNNE_PADDR 0x20000000 /* Base address */ +#define XCHAL_XNNE_NUM_SBLKS 1 /* SBLK count */ +#define XCHAL_XNNE_MBLKS_PER_SBLK 4 /* MBLKs per SBLK */ +#define XCHAL_XNNE_IBUF_SIZE 0 /* IBuf size */ +#define XCHAL_XNNE_OBUF_SIZE 0 /* OBuf size */ +#define XCHAL_XNNE_CBUF_SIZE 0 /* CBuf size */ +#define XCHAL_XNNE_UBUF_SIZE 131072 /* UBuf size */ +#define XCHAL_XNNE_AXIM_DATA_WIDTH 128 /* Data Width */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 16 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1411000 /* sw version of this header */ +#define XCHAL_SW_VERSION_MAJOR 14000 /* major ver# of sw */ +#define XCHAL_SW_VERSION_MINOR 11 /* minor ver# of sw */ +#define XCHAL_SW_VERSION_MICRO 0 /* micro ver# of sw */ +#define XCHAL_SW_MINOR_VERSION 1411000 /* with zeroed micro */ +#define XCHAL_SW_MICRO_VERSION 1411000 + +#define XCHAL_CORE_ID "ACP_7_0_HiFi5_NNE_PROD" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000A6A6B /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC0039286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x2A09DA98 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.8" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 8 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO 0 /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281080 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_8 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 8 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281080 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 8 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO 0 /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281080 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +/* Config is enabled for secure operation: */ +#define XCHAL_HAVE_SECURE 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 131072 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 17 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 8 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 1 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_L1VCACHE_SIZE 0 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ +#define XCHAL_HAVE_L2_CACHE 0 +#define XCHAL_NUM_CORES_IN_CLUSTER 0 + +/* PRID_ID macros are for internal use only ... subject to removal */ +#define PRID_ID_SHIFT 0 +#define PRID_ID_BITS 4 +#define PRID_ID_MASK 0x0000000F + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 8 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ + +/* Extended memory attributes supported. */ +#define XCHAL_HAVE_EXT_CA 0 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x7F000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x7F000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0xE0000000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0xE0000000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 1 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + IDMA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_IDMA 1 +#define XCHAL_IDMA_NUM_CHANNELS 1 /* number of channels */ +#define XCHAL_IDMA_ADDR_WIDTH 32 /* address width in bits */ +#define XCHAL_IDMA_DATA_WIDTH 128 /* data width in bits */ +#define XCHAL_IDMA_DESC_SIZE 32 /* max descriptor size */ +#define XCHAL_IDMA_MAX_OUTSTANDING_REQ 32 /* max outstanding requests */ +#define XCHAL_IDMA_HAVE_REORDERBUF 0 /* has reorder buffer */ +#define XCHAL_IDMA_HAVE_TRANSPOSE 0 /* has transpose function */ +#define XCHAL_IDMA_HAVE_FBC 0 /* has FBC function */ +#define XCHAL_IDMA_HAVE_ZVC 0 /* has ZVC function */ +#define XCHAL_IDMA_HAVE_2DPRED 0 /* supports 2D predicated transfers */ +#define XCHAL_IDMA_NUM_AXI2AXI_CHAN 0 /* how many channels support AXI-to-AXI transfers */ +#define XCHAL_IDMA_ID_PER_CHANNEL 0 + +#define XCHAL_IDMA_CH0_DONE_INTERRUPT 9 +#define XCHAL_IDMA_CH0_ERR_INTERRUPT 10 + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 13 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 7 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_INTERRUPT_RANGE 13 /* range of interrupt numbers */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00001F43 +#define XCHAL_INTLEVEL2_MASK 0x00000004 +#define XCHAL_INTLEVEL3_MASK 0x00000008 +#define XCHAL_INTLEVEL4_MASK 0x00000010 +#define XCHAL_INTLEVEL5_MASK 0x00000020 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000080 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00001F43 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00001F47 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00001F4F +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00001F5F +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x00001F7F +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x00001F7F +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x00001FFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 2 +#define XCHAL_INT3_LEVEL 3 +#define XCHAL_INT4_LEVEL 4 +#define XCHAL_INT5_LEVEL 5 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 7 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 1 +#define XCHAL_INT11_LEVEL 1 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_IDMA_DONE +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_IDMA_ERR +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFFE000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00001938 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_NMI 0x00000080 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000002 +#define XCHAL_INTTYPE_MASK_TIMER 0x00000041 +#define XCHAL_INTTYPE_MASK_ETIE 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000004 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000200 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000400 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_WWDT 0x00000000 +#define XCHAL_INTTYPE_MASK_FXLK 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 0 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 6 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 7 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 2 +#define XCHAL_IDMA_DONE_INTERRUPT 9 +#define XCHAL_IDMA_ERR_INTERRUPT 10 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL2_NUM 2 +#define XCHAL_INTLEVEL3_NUM 3 +#define XCHAL_INTLEVEL4_NUM 4 +#define XCHAL_INTLEVEL5_NUM 5 +#define XCHAL_INTLEVEL7_NUM 7 +/* (There are many interrupts each at level(s) 1.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 3 /* (intlevel 3) */ +#define XCHAL_EXTINT1_NUM 4 /* (intlevel 4) */ +#define XCHAL_EXTINT2_NUM 5 /* (intlevel 5) */ +#define XCHAL_EXTINT3_NUM 7 /* (intlevel 7) */ +#define XCHAL_EXTINT4_NUM 8 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 11 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 12 /* (intlevel 1) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT3_EXTNUM 0 /* (intlevel 3) */ +#define XCHAL_INT4_EXTNUM 1 /* (intlevel 4) */ +#define XCHAL_INT5_EXTNUM 2 /* (intlevel 5) */ +#define XCHAL_INT7_EXTNUM 3 /* (intlevel 7) */ +#define XCHAL_INT8_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT11_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT12_EXTNUM 6 /* (intlevel 1) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (LX) + 3 == XEA3 (NX) + 0 == XEA5 (RNX) */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEA5 0 /* Exception Architecture 5 */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ + +#define XCHAL_RESET_VECOFS 0x00000000 +#define XCHAL_RESET_VECTOR_VADDR 0x7F000000 +#define XCHAL_RESET_VECTOR_PADDR 0x7F000000 +#define XCHAL_USER_VECOFS 0x00000000 +#define XCHAL_USER_VECTOR_VADDR 0x7F000740 +#define XCHAL_USER_VECTOR_PADDR 0x7F000740 +#define XCHAL_KERNEL_VECOFS 0x00000000 +#define XCHAL_KERNEL_VECTOR_VADDR 0x7F000700 +#define XCHAL_KERNEL_VECTOR_PADDR 0x7F000700 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x7F0007C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x7F0007C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x7F000400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x7F000400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000000 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x7F000580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x7F000580 +#define XCHAL_INTLEVEL3_VECOFS 0x00000000 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x7F0005C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x7F0005C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000000 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x7F000600 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x7F000600 +#define XCHAL_INTLEVEL5_VECOFS 0x00000000 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x7F000640 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x7F000640 +#define XCHAL_INTLEVEL6_VECOFS 0x00000000 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x7F000680 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x7F000680 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000000 +#define XCHAL_NMI_VECTOR_VADDR 0x7F0006C0 +#define XCHAL_NMI_VECTOR_PADDR 0x7F0006C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 4096 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 0 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 1 +#define XCHAL_MPU_ENTRIES 32 +#define XCHAL_MPU_LOCK 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 2 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0xFF /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 12 +#define XCHAL_MPU_ALIGN 4096 + +/*----------------------------------------------------------------------- + CSR Parity +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_CSR_PARITY 0 + + +/*---------------------------------------------------------------------- + FLEX-LOCK +------------------------------------------------------------------------*/ + +#define XCHAL_HAVE_FXLK 0 + +/*---------------------------------------------------------------------- + WWDT (Windowed Watchdog Timer) +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_WWDT 0 +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* XTENSA_CORE_CONFIGURATION_H_ */ + diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/core-matmap.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..adc5b3e41bf1 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,101 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=18056; Build=0xa6a6b; Copyright (c) 1999-2023 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ + +/* Mappings for legacy constants where appropriate */ + +#define XCHAL_CA_WRITEBACK (XTHAL_MEM_WRITEBACK | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITEBACK_NOALLOC (XTHAL_MEM_WRITEBACK_NOALLOC| XTHAL_AR_RWXrwx ) + +#define XCHAL_CA_WRITETHRU (XTHAL_MEM_WRITETHRU | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_ILLEGAL (XTHAL_AR_NONE | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASSBUF (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE |\ + XTHAL_MEM_BUFFERABLE) +#define XCHAL_CA_BYPASS_RX (XTHAL_AR_RX | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_RW (XTHAL_AR_RW | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_R (XTHAL_AR_R | XTHAL_MEM_DEVICE) +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 + + +/* + * Contents of MPU background map. + * NOTE: caller must define the XCHAL_MPU_BGMAP() macro (not defined here + * but specified below) before expanding the XCHAL_MPU_BACKGROUND_MAP(s) macro. + * + * XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) + * + * s = passed from XCHAL_MPU_BACKGROUND_MAP(s), eg. to select how to expand + * vaddr_start = first byte of region (always 0 for first entry) + * vaddr_end = last byte of region (always 0xFFFFFFFF for last entry) + * rights = access rights + * memtype = memory type + * x = reserved for future use (0 until then) + */ +/* parasoft-begin-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ +#define XCHAL_MPU_BACKGROUND_MAP(s) \ + XCHAL_MPU_BGMAP(s, 0x00000000, 0x7fffffff, 7, 6, 0) \ + XCHAL_MPU_BGMAP(s, 0x80000000, 0xffffffff, 7, 6, 0) \ +/* parasoft-end-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ + + /* end */ + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/defs.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..bc058b9b906d --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=18056; Build=0xa6a6b; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/specreg.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..ecba5a759e81 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/specreg.h @@ -0,0 +1,109 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Homewood/ib.11/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=18056; Build=0xa6a6b; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define MPUENB 90 +#define ERACCESS 95 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEADRDIS 98 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTCLEAR 227 +#define INTENABLE 228 +#define PS 230 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define MISC_REG_0 244 +#define MISC_REG_1 245 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/system.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..032e706ea5b3 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/system.h @@ -0,0 +1,262 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=18056; Build=0xa6a6b; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +#define XSHAL_ROM_VADDR 0x50000000 +#define XSHAL_ROM_PADDR 0x50000000 +#define XSHAL_ROM_SIZE 0x00020000 +/* Largest available area (free of vectors): */ +#define XSHAL_ROM_AVAIL_VADDR 0x50000000 +#define XSHAL_ROM_AVAIL_VSIZE 0x00020000 + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x60000000 +#define XSHAL_RAM_PADDR 0x60000000 +#define XSHAL_RAM_VSIZE 0x1F000000 +#define XSHAL_RAM_PSIZE 0x1F000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x60000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x1F000000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x1F000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xc61b3000 +#define XSHAL_STL_INFO_LOCATION 0xbffffffc + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x42224422 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x12221122 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x12221122 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0x4FFF44FF /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0x1FFF11FF /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0x1FFF11FF /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0x2FFF22FF /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x4222442F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x1222112F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x1222112F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x4FF2442F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x1FF2112F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x1FF2112F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0x2FF2222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000044 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 0 +#define XSHAL_RESET_VECTOR_VADDR 0x7F000000 +#define XSHAL_RESET_VECTOR_PADDR 0x7F000000 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x00000300 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x00000038 +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x00000038 +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/tie-asm.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..5e31df65fca0 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,382 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=18056; Build=0xa6a6b; Copyright (c) 1999-2023 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rsr.br \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.xnne_rerr \at1 // ureg 0 + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 // boolean option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.xnne_rerr \at1 // ureg 0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed16, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed24, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed31, \ptr, .Lxchal_ofs_+48 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+56 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+57 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+58 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+59 + addi \ptr, \ptr, 64 + ae_salign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_salign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_salign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_salign128.i u3, \ptr, .Lxchal_ofs_+48 + addi \ptr, \ptr, -320 + ae_movdrzbvc aed0 // ureg AE_ZBIASV8C + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 + rur.ae_ovf_sar \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_bithead \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_ts_fts_bu_bp \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cw_sd_no \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.ae_cbegin0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.ae_cend0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+36 + rur.ae_cbegin1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+40 + rur.ae_cend1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+44 + rur.ae_cbegin2 \at1 // ureg 250 + s32i \at1, \ptr, .Lxchal_ofs_+48 + rur.ae_cend2 \at1 // ureg 251 + s32i \at1, \ptr, .Lxchal_ofs_+52 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg AE_ZBIASV8C + ae_movzbvcdr aed0 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ovf_sar \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_bithead \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_ts_fts_bu_bp \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cw_sd_no \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.ae_cbegin0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.ae_cend0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+40 + wur.ae_cbegin1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+44 + wur.ae_cend1 \at1 // ureg 249 + l32i \at1, \ptr, .Lxchal_ofs_+48 + wur.ae_cbegin2 \at1 // ureg 250 + l32i \at1, \ptr, .Lxchal_ofs_+52 + wur.ae_cend2 \at1 // ureg 251 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed16, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed24, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed31, \ptr, .Lxchal_ofs_+48 + addi \ptr, \ptr, 56 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi \ptr, \ptr, 8 + ae_lalign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_lalign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_lalign128.i u3, \ptr, .Lxchal_ofs_+48 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 320 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 64 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/config/tie.h b/src/platform/amd/acp_7_0/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..cd55d1d3028c --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/config/tie.h @@ -0,0 +1,215 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=18056; Build=0xa6a6b; Copyright (c) 1999-2023 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +#ifndef UINT32_C +#define UINT32_C(x) x +#endif + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM UINT32_C(1) /* number of coprocessors */ +#define XCHAL_CP_MAX UINT32_C(2) /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK UINT32_C(0x02) /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK UINT32_C(0x00) /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE UINT32_C(384) /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN UINT32_C(16) /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE UINT32_C(0) +#define XCHAL_CP0_SA_ALIGN UINT32_C(1) +#define XCHAL_CP2_SA_SIZE UINT32_C(0) +#define XCHAL_CP2_SA_ALIGN UINT32_C(1) +#define XCHAL_CP3_SA_SIZE UINT32_C(0) +#define XCHAL_CP3_SA_ALIGN UINT32_C(1) +#define XCHAL_CP4_SA_SIZE UINT32_C(0) +#define XCHAL_CP4_SA_ALIGN UINT32_C(1) +#define XCHAL_CP5_SA_SIZE UINT32_C(0) +#define XCHAL_CP5_SA_ALIGN UINT32_C(1) +#define XCHAL_CP6_SA_SIZE UINT32_C(0) +#define XCHAL_CP6_SA_ALIGN UINT32_C(1) +#define XCHAL_CP7_SA_SIZE UINT32_C(0) +#define XCHAL_CP7_SA_ALIGN UINT32_C(1) + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE UINT32_C(12) +#define XCHAL_NCP_SA_ALIGN UINT32_C(4) + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE UINT32_C(400) /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN UINT32_C(16) /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 3 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, xnne_rerr, 4, 4, 4,0x0300, ur,0 , 1,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 52 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ae_zbiasv8c,16, 8, 8,0x1029, ur,-1 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x102A, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin2, 4, 4, 4,0x03FA, ur,250, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend2, 4, 4, 4,0x03FB, ur,251, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed16, 8, 8, 8,0x1010, aed,16 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed17, 8, 8, 8,0x1011, aed,17 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed18, 8, 8, 8,0x1012, aed,18 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed19, 8, 8, 8,0x1013, aed,19 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed20, 8, 8, 8,0x1014, aed,20 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed21, 8, 8, 8,0x1015, aed,21 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed22, 8, 8, 8,0x1016, aed,22 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed23, 8, 8, 8,0x1017, aed,23 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed24, 8, 8, 8,0x1018, aed,24 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed25, 8, 8, 8,0x1019, aed,25 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed26, 8, 8, 8,0x101A, aed,26 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed27, 8, 8, 8,0x101B, aed,27 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed28, 8, 8, 8,0x101C, aed,28 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed29, 8, 8, 8,0x101D, aed,29 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed30, 8, 8, 8,0x101E, aed,30 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed31, 8, 8, 8,0x101F, aed,31 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1024, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1025, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1026, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1027, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0,16,16,16,0x1020, u,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1,16,16,16,0x1021, u,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2,16,16,16,0x1022, u,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3,16,16,16,0x1023, u,3 ,128,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/idma.h b/src/platform/amd/acp_7_0/include/arch/xtensa/idma.h new file mode 100644 index 000000000000..5ba0e82d3c10 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/idma.h @@ -0,0 +1,3775 @@ +/* + * Copyright (c) 2018-2023 Cadence Design Systems. ALL RIGHTS RESERVED. + * + * 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. + */ + +#ifndef IDMA_H__ +#define IDMA_H__ + +#include <xtensa/hal.h> +#include <xtensa/xtensa-types.h> +#include <xtensa/config/core-isa.h> +#if XCHAL_HAVE_EXTERN_REGS +#include <xtensa/tie/xt_externalregisters.h> +#endif + + +#ifndef XCHAL_IDMA_ADDR_WIDTH +# define XCHAL_IDMA_ADDR_WIDTH 32 +#endif + +/* If HAL doesn't define # of channels macro, need to set to 1 */ +#ifndef XCHAL_IDMA_NUM_CHANNELS +# define XCHAL_IDMA_NUM_CHANNELS 1 +#endif + +/* User enabled multichannel mode - use LIBIDMA_USE_MULTICHANNEL */ +#if (defined IDMA_USE_MULTICHANNEL) +# define LIBIDMA_USE_MULTICHANNEL 1 +#else +# define LIBIDMA_USE_MULTICHANNEL 0 +#endif + +/* Use multichannels only if user-enabled */ +#if (LIBIDMA_USE_MULTICHANNEL > 0) +# define LIBIDMA_USE_MULTICHANNEL_API 1 +#else +# define LIBIDMA_USE_MULTICHANNEL_API 0 +#endif + +/* Enable large (64-byte) descriptor API if the hardware supports it. */ +#if (XCHAL_IDMA_DESC_SIZE == 64) +# define IDMA_USE_64B_DESC 1 +# define IDMA_HAVE_LARGE_DESC 1 +# define IDMA_HAVE_3D 1 +#else +# define IDMA_USE_64B_DESC 0 +# define IDMA_HAVE_LARGE_DESC 0 +# define IDMA_HAVE_3D 0 +#endif + +/* Enable wide address API if the hardware supports it. */ +#if (XCHAL_IDMA_ADDR_WIDTH > 32) && (XCHAL_IDMA_ADDR_WIDTH <= 64) +# define IDMA_USE_WIDE_API 1 +# define IDMA_HAVE_WIDE_API 1 +#else +# define IDMA_USE_WIDE_API 0 +# define IDMA_HAVE_WIDE_API 0 +#endif + +#if (IDMA_USE_64B_DESC == 0) && (IDMA_USE_WIDE_API > 0) +/* #error "IDMA_USE_WIDE_API requires a config that supports 64-byte descriptors" */ +#endif + +/* This is INTERNAL. Need to be here as headers use it */ +#define PSO_SAVE_SIZE_PER_CHANNEL 6 +#define IDMA_PSO_SAVE_SIZE PSO_SAVE_SIZE_PER_CHANNEL*XCHAL_IDMA_NUM_CHANNELS + + +// For the old 2-channel implementation, ch0 and ch1 are at different +// base addresses. For the newer implementation, all the channels can +// be accessed at either of the two base addresses. We choose to use +// the first (device1) base address. +#if (XCHAL_IDMA_NUM_CHANNELS == 2) && (IDMA_USE_64B_DESC == 0) +#if XCHAL_HAVE_XEA2 || XCHAL_HAVE_XEA3 +#if defined(IDMA_USERMODE) +# define IDMAREG_BASE_CH0 UINT32_C(0x00910000) +# define IDMAREG_BASE_CH1 UINT32_C(0x00930400) +#else +# define IDMAREG_BASE_CH0 UINT32_C(0x00110000) +# define IDMAREG_BASE_CH1 UINT32_C(0x00130400) +#endif +# define IDMAREG_BASE(n) (((n) == 0U) ? (IDMAREG_BASE_CH0) : (IDMAREG_BASE_CH1)) +#else +# define IDMAREG_BASE_CH0 IDMA_CHAN_ADDR(0) +# define IDMAREG_BASE_CH1 IDMA_CHAN_ADDR(1) +# define IDMAREG_BASE(n) IDMA_CHAN_ADDR(n) +#endif +#else +#if defined(IDMA_USERMODE) +# define IDMAREG_BASE_SDEV1 UINT32_C(0x00910000) +#else +# define IDMAREG_BASE_SDEV1 UINT32_C(0x00110000) +#endif +# define IDMAREG_BASE(n) (IDMAREG_BASE_SDEV1 + ((UINT32_C(0x400)) * (n))) +#endif + +/* iDMA registers offsets */ +#define IDMA_REG_SETTINGS 0x00 +#define IDMA_REG_TIMEOUT 0x04 +#define IDMA_REG_DESC_START 0x08 +#define IDMA_REG_NUM_DESC 0x0C +#define IDMA_REG_DESC_INC 0x10 +#define IDMA_REG_CONTROL 0x14 +#define IDMA_REG_USERPRIV 0x18 +#define IDMA_REG_STATUS 0x40 +#define IDMA_REG_CURR_DESC 0x44 +#define IDMA_REG_DESC_TYPE 0x48 +#define IDMA_REG_SRC_ADDR 0x4C +#define IDMA_REG_DST_ADDR 0x50 + +// PSO status, after core save/restore +// Value at IDMA_PSO_STATUS_OFFSET from at XtosSaveState.idmaregs +// will indicate if idma HW was idle prior to save, so save was +// skipped, or there was forced iDMA HW disable, or save was done. +#define IDMA_PSO_STATUS_OFFSET 5 +#define IDMA_PSO_STATUS_SAVED 0x1 +#define IDMA_PSO_STATUS_DISABLED 0x2 +#define IDMA_PSO_STATUS_IDLE 0x3 + +#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) + +#include <stdint.h> +#include <stddef.h> +#include <time.h> + +/* Typedef for internal use (required by idma_os.h) */ +typedef struct idma_buf_struct idma_buf_t; + +/* libidma internal buffer ptr, used in Fixed-Buffer mode */ +extern idma_buf_t * g_idma_buf_ptr[XCHAL_IDMA_NUM_CHANNELS]; + +#if defined(IDMA_USERMODE) +#undef IDMA_USE_INTR /* parasoft-suppress MISRA2012-RULE-20_5-4 "Not defined by library" */ +#define IDMA_USE_INTR 0 +#define IDMA_USE_XTOS 1 +#define IDMA_APP_USE_XTOS 1 +#endif + +/** + * Use inline XTOS interface if application defines IDMA_APP_USE_XTOS or + * library build defines IDMA_USE_XTOS. Else use libidma OS interface. + * Both are defined in idma_os.h. + */ +#include "idma_os.h" /* parasoft-suppress MISRA2012-RULE-20_1-4 "This has to follow idma_buf_t" */ + + +/** + * Use interrupts in APIs defined in the header. Default is to use interrupts. + * Overhead of enabling/disabling interrupts to guard shared structs + */ +#if !defined(IDMA_USE_INTR) +#define IDMA_USE_INTR 1 +#endif + +/******************************************************/ +/**** Initialization flags, types, defines ****/ +/******************************************************/ + +/** + * iDMAlib and iDMA HW operation flags, for idma_init() 1st arg. + */ +#define IDMA_OCD_HALT_ON 0x001 /* Enable iDMA halt on OCD interrupt. */ + +/** +* Type of descriptor to add. NOTE: value reflects multiple of 16B. +*/ +typedef enum { + IDMA_1D_DESC = 1, + IDMA_2D_DESC = 2, + IDMA_64B_DESC = 4 +} idma_type_t; + +/** + * Maximum allowed PIF request block size. + */ +typedef enum { + MAX_BLOCK_2 = 0, + MAX_BLOCK_4 = 1, + MAX_BLOCK_8 = 2, + MAX_BLOCK_16 = 3 +} idma_max_block_t; + +/** + * TICK_CYCLES_N: iDMA HW internal timer ticks every N cycles. + */ +typedef enum { +TICK_CYCLES_1 = 0, /* internal timer ticks every 1 cycle */ +TICK_CYCLES_2 = 1, /* internal timer ticks every 2 cycles */ +TICK_CYCLES_4 = 2, +TICK_CYCLES_8 = 3, +TICK_CYCLES_16 = 4, +TICK_CYCLES_32 = 5, +TICK_CYCLES_64 = 6, +TICK_CYCLES_128 = 7 +} idma_ticks_cyc_t; + +/** + * "Descriptor Control Flags" for any type of descriptor + * This sets the idma descriptor control field - see HW description. + */ +#define DESC_IDMA_NOPRIV_SRC 0x00200 /* Non-privileged source memory access */ +#define DESC_IDMA_NOPRIV_DST 0x00800 /* Non-privileged dest. memory access */ +#define DESC_IDMA_PRIOR_H 0x08000 /* QoS high */ +#define DESC_IDMA_PRIOR_L 0x00000 /* QoS low */ +#define DESC_IDMA_TRIG_WAIT 0x20000000 /* wait for external trigger to start */ +#define DESC_IDMA_TRIG_OUT 0x40000000 /* send trigger out on desc. completion */ +#define DESC_NOTIFY_W_INT 0x80000000 /* trigger interrupt on completion */ +//* "Descriptor Control Flags" for new 64-Byte descriptors only. +#define DESC64_IDMA_OVERLAP 0x00000008 /* Overlap Bit (bit 3) */ +#define DESC64_IDMA_LONG_ADDR 0x00000400 /* LA – Long Address (bit 10) */ + +// "Descriptor Control Flags" AXI attribute bits for 64-byte descriptors. +// These go into bits 27:24 of the descriptor control word. +#define DESC64_IDMA_AXI_ATTRIBUTE(val) (((val) & 0xF) << 24) + +/** + * iDMA API return values + * For most of the iDMAlib API calls + */ +typedef enum { + IDMA_ERR_NO_BUF = -40, /* No valid ring buffer */ + IDMA_ERR_BAD_DESC = -20, /* Descriptor not correct */ + IDMA_ERR_BAD_CHAN, /* Invalid channel number */ + IDMA_ERR_NOT_INIT, /* iDMAlib and HW not initialized */ + IDMA_ERR_TASK_NOT_INIT, /* Cannot scheduled uninitialized task */ + IDMA_ERR_BAD_TASK, /* Task not correct */ + IDMA_ERR_BUSY, /* iDMA busy when not expected */ + IDMA_ERR_IN_SPEC_MODE, /* iDMAlib in unexpected mode */ + IDMA_ERR_NOT_SPEC_MODE, /* iDMAlib in unexpected mode */ + IDMA_ERR_TASK_EMPTY, /* No descs in the task/buffer */ + IDMA_ERR_TASK_OUTSTAND_NEG, /* Number of outstanding descs is a negative value */ + IDMA_ERR_TASK_IN_ERROR, /* Task in error */ + IDMA_ERR_BUFFER_IN_ERROR, /* Buffer in error */ + IDMA_ERR_NO_NEXT_TASK, /* Next task to process is missing */ + IDMA_ERR_BUF_OVFL, /* Attempt to schedule too many descriptors */ + IDMA_ERR_HW_ERROR, /* HW error detected */ + IDMA_ERR_BAD_INIT, /* Bad idma_init args */ + IDMA_ERR_UNSUP, /* Not supported in current configuration/mode */ + IDMA_OK = 0, /* No error */ + IDMA_CANT_SLEEP = 1, /* Cannot sleep (no pending descriptors) */ +} idma_status_t; + +/** + * iDMA task status API return values + * NOTE: Valid only after task is scheduled + * + * N (>=0) - Number of outstanding scheduled descriptors. + * 0 (IDMA_TASK_DONE) - Whole task has completed the execution. + * IDMA_TASK_ERROR - iDMA HW error happened due to a descriptor executed + * from this task. Error details are available (idma_hw_error_t). + * IDMA_TASK_ABORTED - Task forcefully aborted. + */ +typedef enum { + IDMA_TASK_ABORTED = -3, + IDMA_TASK_ERROR = -2, + IDMA_TASK_NOINIT = -1, + IDMA_TASK_DONE = 0, + IDMA_TASK_EMPTY = 0 +} task_status_t; + +/** + * iDMA HW error details API return values + * This corresponds to the Error Codes field + * of the HW Status register. + */ +#if XCHAL_HAVE_XEA2 +#define IDMA_ERR_FETCH_ADDR UINT32_C(0x2000) +#define IDMA_ERR_FETCH_DATA UINT32_C(0x1000) +#define IDMA_ERR_READ_ADDR UINT32_C(0x0800) +#define IDMA_ERR_READ_DATA UINT32_C(0x0400) +#define IDMA_ERR_WRITE_ADDR UINT32_C(0x0200) +#define IDMA_ERR_WRITE_DATA UINT32_C(0x0100) +#define IDMA_ERR_REG_TIMEOUT UINT32_C(0x0080) +#define IDMA_ERR_TRIG_OVFL UINT32_C(0x0040) +#define IDMA_ERR_DESC_OVFL UINT32_C(0x0020) +#define IDMA_ERR_DESC_UNKNW UINT32_C(0x0010) +#define IDMA_ERR_DESC_UNSUP_DIR UINT32_C(0x0008) +#define IDMA_ERR_DESC_BAD_PARAMS UINT32_C(0x0004) +#define IDMA_ERR_DESC_NULL_ADDR UINT32_C(0x0002) +#define IDMA_ERR_DESC_PRIVILEGE UINT32_C(0x0001) +#define IDMA_NO_ERR UINT32_C(0x0000) +#else +#define IDMA_ERR_FETCH_ADDR UINT32_C(0x80000) +#define IDMA_ERR_FETCH_DATA UINT32_C(0x40000) +#define IDMA_ERR_READ_ADDR UINT32_C(0x20000) +#define IDMA_ERR_READ_DATA UINT32_C(0x10000) +#define IDMA_ERR_WRITE_ADDR UINT32_C(0x08000) +#define IDMA_ERR_WRITE_DATA UINT32_C(0x04000) +#define IDMA_ERR_REG_TIMEOUT UINT32_C(0x02000) +#define IDMA_ERR_TRIG_OVFL UINT32_C(0x01000) +#define IDMA_ERR_DESC_OVFL UINT32_C(0x00800) +#define IDMA_ERR_DESC_UNKNW UINT32_C(0x00400) +#define IDMA_ERR_DESC_UNSUP_DIR UINT32_C(0x00200) +#define IDMA_ERR_DESC_BAD_PARAMS UINT32_C(0x00100) +#define IDMA_ERR_DESC_NULL_ADDR UINT32_C(0x00080) +#define IDMA_ERR_DESC_PRIVILEGE UINT32_C(0x00040) +#define IDMA_ERR_DESC_MMUMPU UINT32_C(0x00020) +#define IDMA_ERR_BIT_VECT UINT32_C(0x00010) +#define IDMA_ERR_VECT_OTHER UINT32_C(0x00008) +#define IDMA_ERR_VECT_DATA UINT32_C(0x00004) +#define IDMA_ERR_SRC_MMUMPU UINT32_C(0x00002) +#define IDMA_ERR_DST_MMUMPU UINT32_C(0x00001) +#define IDMA_NO_ERR UINT32_C(0x00000) +#endif + +typedef uint32_t idma_hw_error_t; + +/* Status reg fields */ +#define IDMA_STATE_IDLE UINT32_C(0x0) //idma done with all descriptors and disabled +#define IDMA_STATE_STANDBY UINT32_C(0x1) //transient stat +#define IDMA_STATE_BUSY UINT32_C(0x2) //idma busy copying +#define IDMA_STATE_DONE UINT32_C(0x3) //idma done with all descriptors but enabled +#define IDMA_STATE_HALT UINT32_C(0x4) //idma disabled during copy operation +#define IDMA_STATE_ERROR UINT32_C(0x5) //idma in error +#define IDMA_STATE_MASK UINT32_C(0x7) + +typedef uint32_t idma_state_t; + +# ifdef IDMA_DEBUG +# define INTERNAL_FUNC static +# else +# define INTERNAL_FUNC static inline +# endif + +/* No inlining for debug libs */ +#ifdef IDMA_LIB_BUILD +# define IDMA_API static inline +#else +# define IDMA_API INTERNAL_FUNC +#endif + +#define ALWAYS_INLINE __attribute__((always_inline)) static inline + +#ifndef IDMA_EXTERN +# define IDMA_EXTERN +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * iDMA error details structure - available from different API calls + */ +typedef struct idma_error_details_struct { + idma_hw_error_t err_type; /* ErrorCodes field of the Status reg */ + uint32_t currDesc; /* Descriptor causing error */ + uint32_t srcAddr; /* PIF source address causing error */ + uint32_t dstAddr; /* PIF dest. address causing error */ +} idma_error_details_t; + +/* callback typedef */ +typedef void (*idma_callback_fn)( void* arg); +/* error callback typedef */ +typedef void (*idma_err_callback_fn)( const idma_error_details_t* error); +/* log handler typedef */ +typedef void (*idma_log_h)( const char* xlog); + +/* Typedef for external API use */ +typedef struct idma_buffer_struct { + char buffer[4]; +} idma_buffer_t; + +/* allocate space for n descriptors of type idma_type_t. */ +#define IDMA_BUFFER_SIZE(n,type) \ + ( ((n)* (((type) == IDMA_1D_DESC) ? IDMA_1D_DESC_SIZE : (((type) == IDMA_2D_DESC) ? IDMA_2D_DESC_SIZE : IDMA_64_DESC_SIZE))) + \ + sizeof(struct idma_buf_struct)) + +/* Define a buffer of containing n descriptors of type n */ +#define IDMA_BUFFER_DEFINE(name, n, type) \ + IDMA_DRAM idma_buffer_t name[IDMA_BUFFER_SIZE((n), (type))/sizeof(idma_buffer_t)] + +/* Use these macros when allocating copy buffers to avoid sharing cache lines */ +#define IDMA_DCACHE_ALIGN (XCHAL_DCACHE_LINESIZE << XCHAL_DCACHE_LINES_PER_TAG_LOG2) + +/* Align to dcache line */ +#define ALIGNDCACHE __attribute__ ((aligned(IDMA_DCACHE_ALIGN))) + +/* Buffer size will be rounded to the cache alignment so it occupies the whole cache line */ +#define IDMA_SIZE(N) (((N) + IDMA_DCACHE_ALIGN-1) & -IDMA_DCACHE_ALIGN) + +/* These macros are empty if no interrupts. Otherwise, they map to OS provided + * functions that are defined in idma-xtos.h or idma-os.h. The XTOS versions + * will get inlined for performance. + */ +#if defined XCHAL_HAVE_INTERRUPTS && (IDMA_USE_INTR > 0) +# define DECLARE_PS() uint32_t ps +# define IDMA_ENABLE_INTS() idma_enable_interrupts(ps) +# define IDMA_DISABLE_INTS() ps = idma_disable_interrupts() +#else //no interrupts +# define DECLARE_PS() do {} while (0) +# define IDMA_ENABLE_INTS() do {} while (0) +# define IDMA_DISABLE_INTS() do {} while (0) +#endif + +/*************************************************/ +/** Forward declarations for internal stuff **/ +/*************************************************/ +typedef struct idma_desc_struct idma_desc_t; +typedef struct idma_2d_desc_struct idma_2d_desc_t; +typedef struct idma_desc64_struct idma_desc64_t; + +/************************************************/ +/**** MISC HELPER FUNCTIONS ****/ +/************************************************/ + +ALWAYS_INLINE void * +cvt_uint32_to_voidp(uint32_t val) +{ + return (void *) val; // parasoft-suppress MISRA2012-RULE-11_6-2 "Type conversion necessary." +} + +ALWAYS_INLINE uint32_t +cvt_voidp_to_uint32(void * val) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const because of type conversion." +{ + return (uint32_t) val; // parasoft-suppress MISRA2012-RULE-11_6-2 "Type conversion necessary." +} + +ALWAYS_INLINE void * +cvt_uint32p_to_voidp(uint32_t * val) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const because of type conversion." +{ + return (void *) val; +} + +ALWAYS_INLINE uint32_t * +cvt_voidp_to_uint32p(void * val) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const because of type conversion." +{ + return (uint32_t *) val; // parasoft-suppress MISRA2012-RULE-11_5-4 "Type conversion necessary." +} + +ALWAYS_INLINE void * +cvt_int32_to_voidp(int32_t val) +{ + return (void *) val; // parasoft-suppress MISRA2012-RULE-11_6-2 "Type conversion necessary." +} + +ALWAYS_INLINE int32_t +cvt_voidp_to_int32(void * val) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const because of type conversion." +{ + return (int32_t) val; // parasoft-suppress MISRA2012-RULE-11_6-2 "Type conversion necessary." +} + +ALWAYS_INLINE idma_desc64_t * +cvt_desc_to_desc64(idma_desc_t * val) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const because of type conversion." +{ + return (idma_desc64_t *) val; // parasoft-suppress MISRA2012-RULE-11_3-2 MISRA2012-RULE-11_2-2 "Type conversion necessary." +} + +/************************************************/ +/**** API ****/ +/************************************************/ + +/* NOTE NOTE NOTE: + * Have to define LIBIDMA_USE_MULTICHANNEL if want to use the multichannel API. + * The new API basically adds the channel argument to the most of the old functions. + * See below, #else part, for the old API. Also, each function descriptions mentions + * if an argument is not present in the old API. + */ +#if (LIBIDMA_USE_MULTICHANNEL_API > 0) + +/** + * @name Wait for all descriptors to finish, by polling only the HW + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval None + */ +IDMA_API void +idma_hw_wait_all(int32_t ch); + +/** + * @name Schedule a number of descriptors, by accessing HW only. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param count Number of descriptors to schedule. + * @retval None + */ +IDMA_API void +idma_hw_schedule(int32_t ch, uint32_t count); + +/** + * @name Return number of outstanding descriptor, as indicated by HW + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval number of outstanding descriptor + */ +IDMA_API uint32_t +idma_hw_num_outstanding(int32_t ch); + +/** + * @name iDMAlib and iDMA HW initialization + * @brief Does iDMA HW soft reset, sets iDMAlib parameters and sets + * iDMA HW registers (Settings/Timeout) with given parameters. + * @param ch Selected. iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param flags iDMAlib initialization flags, above. + * @param block_sz idma_max_block_t above. + * @param pif_req Maximum outstanding PIF requests (1-64). + * @param ticks_per_cyc Ticks per cycle. See iDMA hardware details. + * @param timeout_ticks Timeout ticks. See iDMA hardware details. + * @param err_cb_func Register global error handler. Called on idma HW + * error detection for which intr is always enabled. + * @retval IDMA_OK Successful + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_init( int32_t ch, + uint32_t flags, + idma_max_block_t block_sz, + uint32_t pif_req, + idma_ticks_cyc_t ticks_per_cyc, + uint32_t timeout_ticks, + idma_err_callback_fn err_cb_func); + +/** + * @name Enable fast-wake mode for all channels. + * @brief Enables fast wakeup from WAITI for all channels. All channels + * must be not busy and not in error state. + * @retval IDMA_OK Successful + * @retval IDMA_ERR_BUSY At least one channel was busy or in error + * @retval IDMA_ERR_UNSUP Not supported in this configuration + */ +idma_status_t +idma_fast_wake_enable(void); + +/** + * @name Disable fast-wake mode for all channels. + * @brief Disables fast wakeup from WAITI for all channels. All channels + * must be not busy and not in error state. + * @retval IDMA_OK Successful + * @retval IDMA_ERR_BUSY At least one channel was busy or in error + * @retval IDMA_ERR_UNSUP Not supported in this configuration + */ +idma_status_t +idma_fast_wake_disable(void); + +/** + * @name Check the state of idma HW. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + */ +IDMA_API idma_state_t +idma_get_state(int32_t ch); + +/** + * @name Add log messages handler. + * @brief Log messages from iDMAlib are sent to this handler. + * NOTE: In debug library only ! + * @param xlog Function to call on iDMAlib log call + */ +void +idma_log_handler(idma_log_h xlog); + +/** + * @name Sleep/block until current iDMA activity completes. + * @brief Wait in low-power mode until iDMA activity completes. Return immediately + * if iDMA is in error or there are no outstanding descriptors. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval IDMA_OK Normal return. + * @retval IDMA_CANT_SLEEP Cannot sleep (no pending descriptors). + * @retval (all other values) Error code. + */ +IDMA_API idma_status_t +idma_sleep(int32_t ch); + +/** + * @name Get the error details. + * @brief When task or fixed buffer status indicate error, use this + * function to obtain the error details. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param task Pointer to iDMA task + * @retval Pointer to the structure containing error details. + * NOTE: Pointer is valid only if idma task/buffer is in error. + */ +IDMA_API idma_error_details_t* idma_error_details(int32_t ch); +IDMA_API idma_error_details_t* idma_buffer_error_details(int32_t ch); + +/** + * @name Disable iDMA HW when not in use. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @brief Needs idma_init to resume. + */ +IDMA_API idma_status_t +idma_stop(int32_t ch); + +/** + * @name Pause iDMA HW. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @brief Can simply resume after + */ +IDMA_API void +idma_pause(int32_t ch); + +/** + * @name Resume iDMA HW. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @brief Can simply pause before + */ +IDMA_API void +idma_resume(int32_t ch); + +/** + * @name Add 1D desc to the next location in the buffer/task + * @brief Descriptors are added in order. Used in both Task and + * and the fixed-buffer mode. + * NOTE: Number of added descriptors needs to match the + * size of the task (an argument to idma_init_task()). + * @param dst... iDMA 1D transfer parameters + * @param flags Descriptor options (Control field). + * See "Descriptor Control Flags". + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type. + */ +IDMA_API idma_status_t +idma_add_desc( idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + uint32_t flags); + +/** + * @name Add 2D desc to the next location in the buffer/task + * @brief Descriptors are added in order. Used in both Task and + * and the fixed-buffer mode. + * NOTE: Number of added descriptors needs to match the + * size of the task (an argument to idma_init_task()). + * @param dst... iDMA 1D transfer parameters + * @param flags Descriptor options (Control field). + * See "Descriptor Control Flags". + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type. + */ +IDMA_API idma_status_t +idma_add_2d_desc( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); + +/************************************************/ +/**** Task-mode API ****/ +/************************************************/ + +/** + * @name Initialize a task (a separate buffer/array of descriptors). + * @brief Needs to be called before adding descriptors to a task. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param task Pointer to the memory used for iDMA task. + * @param type 1D or 2D. + * @param num Number of descriptors to be added. NOTE: must match + * the actual number of added descs using _add_ calls. + * Also, IDMA_BUFFER_DEFINE must allocate sufficent memory. + * @param cb_func Function to call on each descriptor completion. + * (if enabled by descriptor). + * @param cb_data Callback data. + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_init_task (int32_t ch, + idma_buffer_t *taskh, + idma_type_t type, + int32_t ndescs, + idma_callback_fn cb_func, + void *cb_data); + +/** + * @name Get the task execution status. + * @brief Reads the number of outstanding descriptors from the + * scheduled task. When no iDMA interrupts, must be used + * together with idma_process_tasks() as something must + * trigger iDMAlib internal task completion processing. + * @param task Pointer to iDMA task + * @retval < 0 Error (task_status_t) + * @retval >= 0 Number of outstanding descriptors in the task. + */ +IDMA_API int32_t +idma_task_status(idma_buffer_t *taskh); + +/** + * @name Create and schedule 1D copy request. + * @brief Convenience functions that combine buffer initialization, + * adding one descriptor to it and scheduling the task. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param task Pointer to iDMA buffer + * @param cb_func Function to call on each descriptor completion + * (if enabled by descriptor) + * @param cb_data Callback data. + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_copy_task(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func); + +/** + * @name Create and schedule 2D copy request. + * @brief Convenience functions that combine buffer initialization, + * adding one descriptor to it and scheduling the task. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param task Pointer to iDMA buffer + * @param cb_func Function to call on each descriptor completion + * (if enabled by descriptor) + * @param cb_data Callback data. + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_copy_2d_task(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func); + +/** + * @name Schedule a task for execution. + * @brief Schedule a task(separate buffer/array ofdescriptor) + * for execution in the task mode. If IDMA is busy, + * last desc from the last scheduled buffer is linked + * with the 1st desc from this task using a JUMP command. + * If IDMA is not busy iDMA HW starts execution from this task. + * NOTE: TASK MODE ONLY. + * @param buf Pointer to iDMA task to be scheduled. + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type. + */ +idma_status_t +idma_schedule_task(idma_buffer_t *taskh); + +/** + * @name Trigger iDMAlib internal processing of completed tasks. + * @brief Needed when no interrupts are available/setup. + * NOTE: Function will also invoke completion callback, + * if set with idma_init_task() function. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type (when iDMA is in error). + */ +IDMA_API idma_status_t +idma_process_tasks(int32_t ch); + +/** + * @name Abort all tasks. + * @brief Reset iDMA HW and set status of all "outstanding" tasks to + * aborted state. Note: "Outstanding" tasks can also include + * tasks that actually completed (their descriptors are all executed). + * To ensure all the completed tasks are not seen as "outstanding", + * enable iDMA Done interrupt for at least the last descriptor in + * a task, or call idma_process_tasks() before calling this function. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_abort_tasks(int32_t ch); + +/************************************************/ +/**** Fixed-Buffer Mode API ****/ +/************************************************/ + +/** + * @name Initialize buffer (array of descs). Also enables the fixed-buffer + * mode which prevents using the buffer as a separate task. + * @brief Needs to be called after a buffer is created (e.g. using the + * IDMA_DEFINE_BUFFER) and before adding descriptors to it. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param buffer Pointer to the memory used for iDMA buffer + * @param type 1D or 2D + * @param ndescs Number of descriptors. In the TASK mode, the number + * of descs added to the task need to much this number. + * @param cb_func Function to call on each descriptor completion. + * (if enabled by each descriptor settings) + * @param cb_data Callback data + * @retval IDMA_OK Successful. + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_init_loop (int32_t ch, + idma_buffer_t *bufh, + idma_type_t type, + int32_t ndescs, + void *cb_data, + idma_callback_fn cb_func); + +/** + * @name Schedule consecutive descriptors for execution. + * @brief Schedule a number of next in line descriptors, with wrap-around + * NOTE: INCOMPATIBLE with idma_copy_desc/idma_copy_2d_desc + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param count Number of descriptors to schedule. + * NOTE: Cannot be larger than the number of descriptors + * in the buffer initialized using idma_init_loop(). + * @retval < 0 Error code, from idma_status_t. + * @retval >= 0 Unique index of the scheduled descriptor in the range from 0 + * to 0x7fffffff. Starts with value of 1 at iDMAlib initialization + * time. It's expected the number of outstanding descriptors in + * the system is always less then 0x7fffffff. + * E.g. if the circular buffer contains 8 descs and retval=17, + * the 2nd descriptor in the buffer is the last scheduled one and + * by, the iDMAlib has scheduled 17 descriptors. + * NOTE: This unique index is to be used in idma_desc_done() only. + */ +IDMA_API int32_t +idma_schedule_desc(int32_t ch, + uint32_t count); + +/** + * @name Schedule consecutive descriptors for execution w/o ability to change descs. + * @brief Schedule a number of next in line descriptors, with wrap-around. + * The function is to be used when all the descriptors are already added + * so they are just scheduled or possibly updated. This is because the + * the function doesn't keep the track of the place where the next descriptor + * is to be added. + * NOTE: INCOMPATIBLE with idma_copy_desc/idma_copy_2d_desc and idma_update_desc_* + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param count Number of descriptors to schedule. + * @retval < 0 Error code, from idma_status_t. + * @retval >= 0 See idma_schedule_desc() + */ +IDMA_API int32_t +idma_schedule_desc_fast(int32_t ch, + uint32_t count); + +/** + * @name Add and schedule a 1D descriptor. + * @brief Descriptor added in order and scheduled in order. + * NOTE: INCOMPATIBLE with idma_add_desc/idma_add_2d_desc/idma_schedule_desc + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param dst iDMA transfer destination + * @param src iDMA transfer source + * @param size iDMA transfer size + * @param flags Descriptor options (Control field). See "Descriptor Control Flags". + * @retval < 0 Error code, from idma_status_t. + * @retval >= 0 See idma_schedule_desc() + */ +IDMA_API int32_t +idma_copy_desc(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags); + +/** + * @name Add and schedule a 2D descriptor. + * @brief Descriptor added in order and scheduled in order. + * NOTE: INCOMPATIBLE with idma_add_desc/idma_add_2d_desc/idma_schedule_desc + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param dst iDMA transfer destination + * @param src iDMA transfer source + * @param size iDMA transfer size + * @param flags Descriptor options (Control field). + * See "Descriptor Control Flags". + * @param nrows Number of rows to transfer + * @param src_pitch iDMA transfer source pitch + * @param dst_pitch iDMA transfer destination pitch + * @retval < 0 Error code, from idma_status_t. + * @retval >= 0 See idma_schedule_desc() + */ +IDMA_API int32_t +idma_copy_2d_desc(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); + +/** + * @name Check if a descriptor is done, using unique desc ID. + * @brief Unique ID is made available when descriptor was scheduled. + * The function does the internal processing so it can be + * called in an empty loop if want to wait for desc to complete. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param index Unique ID of the descriptor. + * @retval 1 Desc is done. + * @retval 0 Desc is NOT done. + * @retval -1 Error. + */ +IDMA_API int32_t +idma_desc_done(int32_t ch, + int32_t index); + + +/** + * @name Update destination field of the "next" descriptor + * @brief Update next to be schedule descriptor (means the next + * call to idma_desc_schedule() will schedule the desc. + * updated in this call. + * ONLY IN FIXED-BUFFER MODE. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param dst New destination address + * @retval IDMA_OK Successful + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_update_desc_dst(int32_t ch, + void *dst); + +/** + * @name Update source field of the "next" descriptor. + * @brief Update next to be schedule descriptor (means the next + * call to idma_desc_schedule() will schedule the desc. + * updated in this call. + * ONLY IN FIXED-BUFFER MODE. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param src New source address + * @retval IDMA_OK Successful + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_update_desc_src(int32_t ch, + void *src); + +/** + * @name Update size field of the "next" descriptor. + * @brief Update next to be schedule descriptor (means the next + * call to idma_desc_schedule() will schedule the desc. + * updated in this call. + * ONLY IN FIXED-BUFFER MODE. + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @param size New copy request size + * @retval IDMA_OK Successful + * @retval !IDMA_OK Error type + */ +IDMA_API idma_status_t +idma_update_desc_size(int32_t ch, + uint32_t size); + +/** + * @name Get buffer status w/ internal processing of completed descs. + * @brief Check the number of outstanding descriptors. Will also + * trigger internal processing making this call needed when no + * interrupts are available/setup. + * ONLY IN FIXED-BUFFER MODE. + * @brief Returns error or the number of outstanding descs + * @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval >=0 num. of outstanding descriptors + * @retval <0 Error type + */ +IDMA_API int32_t +idma_buffer_status(int32_t ch); + +/** + * @name Check if the IDMA HW is in error. If yes the function also + * sets the error details, sets the buffer status to indicate + * error and returns the error code. +* @param ch Selected iDMA HW channel. + * NOTE: Argument present only if LIBIDMA_USE_MULTICHANNEL_API defined. + * @retval IDMA_NO_ERR No Error. + * @retval !IDMA_NO_ERR Error type + */ +IDMA_API idma_hw_error_t +idma_buffer_check_errors(int32_t ch); + +/** + * These two functions operate exactly like idma_schedule_desc() and + * idma_schedule_desc_fast(), and in addition they also return the + * current clock value (which normally is the CCOUNT register value) + * in the location pointed to by the "ptime" argument. + */ +IDMA_API int32_t +idma_schedule_desc_clock(int32_t ch, + uint32_t count, + uint32_t *ptime); + +IDMA_API int32_t +idma_schedule_desc_fast_clock(int32_t ch, + uint32_t count, + uint32_t *ptime); + +#else // OLD API - no channels + +IDMA_API void idma_hw_wait_all(void); +IDMA_API void idma_hw_schedule(uint32_t count); +IDMA_API uint32_t idma_hw_num_outstanding(void); + +void idma_log_handler(idma_log_h xlog); + +idma_status_t idma_fast_wake_enable(void); +idma_status_t idma_fast_wake_disable(void); +IDMA_API idma_status_t idma_init(uint32_t flags, idma_max_block_t block_sz, uint32_t pif_req, idma_ticks_cyc_t ticks_per_cyc, uint32_t timeout_ticks, idma_err_callback_fn err_cb_func); +IDMA_API idma_status_t idma_add_desc(idma_buffer_t *bufh, void *dst, void *src, size_t size, uint32_t flags); +IDMA_API idma_status_t idma_add_2d_desc(idma_buffer_t *bufh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch); +IDMA_API idma_status_t idma_init_loop (idma_buffer_t *bufh, idma_type_t type, int32_t ndescs, void *cb_data, idma_callback_fn cb_func); +IDMA_API idma_status_t idma_init_task(idma_buffer_t *taskh, idma_type_t type, int32_t ndescs, idma_callback_fn cb_func, void *cb_data); +IDMA_API idma_status_t idma_copy_task(idma_buffer_t *taskh, void *dst, void *src, size_t size, uint32_t flags, void *cb_data, idma_callback_fn cb_func); +IDMA_API idma_status_t idma_copy_2d_task(idma_buffer_t *taskh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch, void *cb_data, idma_callback_fn cb_func); +IDMA_API idma_status_t idma_process_tasks(void); +IDMA_API idma_status_t idma_abort_tasks(void); +IDMA_API idma_status_t idma_stop(void); +IDMA_API idma_status_t idma_update_desc_dst(void *dst); +IDMA_API idma_status_t idma_update_desc_src(void *src); +IDMA_API idma_status_t idma_update_desc_size(uint32_t size); +idma_status_t idma_schedule_task( idma_buffer_t *taskh); + +IDMA_API idma_state_t idma_get_state(void); + +IDMA_API void idma_pause(void); +IDMA_API void idma_resume(void); + +IDMA_API int32_t idma_schedule_desc(uint32_t count); +IDMA_API int32_t idma_schedule_desc_fast(uint32_t count); +IDMA_API int32_t idma_copy_desc(void *dst, void *src, size_t size, uint32_t flags); +IDMA_API int32_t idma_copy_2d_desc(void *dst, void *src, size_t size, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch); +IDMA_API int32_t idma_desc_done(int32_t index); +IDMA_API int32_t idma_buffer_status(void); +IDMA_API int32_t idma_task_status(idma_buffer_t *taskh); +IDMA_API idma_status_t idma_sleep(void); + +IDMA_API idma_hw_error_t idma_buffer_check_errors(void); + +IDMA_API idma_error_details_t* idma_error_details(void); +IDMA_API idma_error_details_t* idma_buffer_error_details(void); + +IDMA_API int32_t idma_schedule_desc_clock(uint32_t count, uint32_t *ptime); +IDMA_API int32_t idma_schedule_desc_fast_clock(uint32_t count, uint32_t *ptime); + +#endif // not LIBIDMA_USE_MULTICHANNEL_API + +/* For compatibility with macros that were used before */ +#define IDMA_HW_NUM_OUTSTANDING idma_hw_num_outstanding +#define IDMA_HW_SCHEDULE idma_hw_schedule +#define IDMA_HW_WAIT_ALL idma_hw_wait_all + +#if (IDMA_USE_64B_DESC > 0) + +/** + * @name Add 1D descriptor in 64B format to the next location in the buffer/task + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + uint32_t flags); + +/** + * @name Add 2D descriptor in 64B format to the next location in the buffer/task + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_2d_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +/** + * @name Add predicated 2D descriptor in 64B format to the next location in the buffer/task + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_2d_pred_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); +#endif + +/** + * @name Add 3D descriptor in 64B format to the next location in the buffer/task + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_3d_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch); + +/** + * @name Create & schedule 1D copy request in 64B format + * @brief See idma_copy_task for details + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_copy_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func); + +/** + * @name Create & schedule 2D copy request in 64B format + * @brief See idma_copy_2d_task for details. + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_copy_2d_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func); + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +/** + * @name Create & schedule predicated 2D copy request in 64B format + * @brief See idma_copy_2d_task for details. + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_copy_2d_pred_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func); +#endif + +/** + * @name Add and schedule a 1D descriptor in 64B format. + * @brief See idma_copy_desc for details. + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_desc64(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags); + +/** + * @name Add and schedule a 2D descriptor in 64B format. + * @brief See idma_copy_2d_desc for details. + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_2d_desc64(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +/** + * @name Add and schedule a predicated 2D descriptor in 64B format. + * @brief See idma_copy_2d_desc for details. + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_2d_pred_desc64(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); +#endif + +/** + * @name Add and schedule a 3D descriptor in 64B format. + * @brief See idma_copy_2d_desc for details. + * NOTE: This functions uses 32-bit src/dst addresses; it'll fetch + * one word behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_3d_desc64(int32_t ch, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch); + +#if (IDMA_USE_WIDE_API > 0) + +/** + * @name Add 1D descriptor in 64B format to the next location in the buffer/task. + * @brief See idma_add_2d_desc for details on arguments. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_desc64_wide( idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + uint32_t flags); + +/** + * @name Add 2D descriptor in 64B format to the next location in the buffer/task + * @brief See idma_add_2d_desc for details on arguments. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_2d_desc64_wide( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +/** + * @name Add predicated 2D descriptor in 64B format to the next location in the buffer/task. + * @brief See idma_add_2d_desc for details on arguments. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_2d_pred_desc64_wide( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); +#endif + +/** + * @name Add 3D descriptor in 64B format to the next location in the buffer/task. + * @brief See idma_add_3d_desc64 for details on arguments. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_add_3d_desc64_wide( idma_buffer_t *bufh, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch); + +/** + * @name Create & schedule 1D copy request in 64B format. + * @brief See idma_copy_task for details + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_copy_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func); + +/** + * @name Create & schedule 2D copy request in 64B format. + * @brief See idma_copy_task for details + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_copy_2d_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func); + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +/** + * @name Create & schedule predicated 2D copy request in 64B format. + * @brief See idma_copy_task for details + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API idma_status_t +idma_copy_2d_pred_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func); +#endif + +/** + * @name Add and schedule a 1D descriptor in 64B format. + * @brief See idma_copy_desc for details. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_desc64_wide(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags); + +/** + * @name Add and schedule a 2D descriptor in 64B format. + * @brief See idma_copy_2d_desc for details. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two word behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_2d_desc64_wide(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +/** + * @name Add and schedule a predicated 2D descriptor in 64B format. + * @brief See idma_copy_desc for details. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_2d_pred_desc64_wide(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch); +#endif + +/** + * @name Add and schedule a 3D descriptor in 64B format. + * @brief See idma_copy_desc for details. + * NOTE: This functions uses 64-bit src/dst addresses; it'll fetch + * two words behind the src/dst pointers. + */ +IDMA_API int32_t +idma_copy_3d_desc64_wide(int32_t ch, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch); + +#endif +#endif + + + + + +/*************************************************/ +/**** Internal Stuff ****/ +/**** DO NOT ACCESS OR RELY ON THE CODE BELOW ****/ +/*************************************************/ + +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + +# define SRC_WIDE_ADDR_SHIFT UINT32_C(16) +# define DST_WIDE_ADDR_SHIFT UINT32_C(20) +# define IDMA_WIDE_ADDR_MASK UINT32_C(0x0000000F) + +idma_status_t +idma_copy_task_wide_i(int32_t ch, + idma_buffer_t * taskh, + void * dst, + void * src, + size_t size, + uint32_t flags, + void * cb_data, + idma_callback_fn cb_func); + +idma_status_t +idma_copy_2d_task_wide_i(int32_t ch, + idma_buffer_t * taskh, + void * dst, + void * src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void * cb_data, + idma_callback_fn cb_func); + +#endif // IDMA_USE_WIDE_ADDRESS_COMPILE + +#define IDMA_CHANNEL_0 0 +#define IDMA_CHANNEL_1 1 +#define IDMA_CHANNEL_2 2 +#define IDMA_CHANNEL_3 3 +#define IDMA_CHANNEL_4 4 +#define IDMA_CHANNEL_5 5 +#define IDMA_CHANNEL_6 6 +#define IDMA_CHANNEL_7 7 + + +#if (LIBIDMA_USE_MULTICHANNEL_API > 0) +# define IDMA_CH_PTR ch +# define IDMA_CHAN_FUNC_ARG int32_t ch, +# define IDMA_CHAN_FUNC_ARG_SINGLE int32_t ch +#else +# define IDMA_CH_PTR IDMA_CHANNEL_0 +# define IDMA_CHAN_FUNC_ARG +# define IDMA_CHAN_FUNC_ARG_SINGLE void +#endif + +#if XCHAL_HAVE_XEA2 || XCHAL_HAVE_XEA3 +# define IDMA_REG_ADDR(c,r) (IDMAREG_BASE((uint32_t)(c)) + (uint32_t)(r)) +# define IDMA_RER XT_RER +# define IDMA_WER XT_WER +#else +# define IDMA_RER(r) xthal_mmio_ld32((r)) +# define IDMA_WER(v,r) xthal_mmio_st32((r),(v)) +#endif + +#if XCHAL_HAVE_XEA5 +# define IDMA_DONE_INT(ch) ((uint32_t)XCHAL_IDMA_CH0_DONE_INTERRUPT + ((ch) * UINT32_C(2))) +# define IDMA_ERR_INT(ch) ((uint32_t)XCHAL_IDMA_CH0_ERR_INTERRUPT + ((ch) * UINT32_C(2))) +#else +# define IDMA_DONE_INT(ch) ((uint32_t)XCHAL_IDMA_CH0_DONE_INTERRUPT + (ch)) +# define IDMA_ERR_INT(ch) ((uint32_t)XCHAL_IDMA_CH0_ERR_INTERRUPT + (ch)) +#endif + + +#if defined (IDMA_USERMODE) +#define IDMA_1D_DESC_CODE UINT32_C(0xA03) +#define IDMA_2D_DESC_CODE UINT32_C(0xA07) +#define IDMA_JMP_DESC_CODE UINT32_C(0xA00) +#define IDMA_64B_DESC_CODE UINT32_C(0xA01) +#define IDMA_ZVC_DESC_CODE UINT32_C(0xA05) +#else +#define IDMA_1D_DESC_CODE UINT32_C(3) +#define IDMA_2D_DESC_CODE UINT32_C(7) +#define IDMA_JMP_DESC_CODE UINT32_C(0) +#define IDMA_64B_DESC_CODE UINT32_C(1) +#define IDMA_ZVC_DESC_CODE UINT32_C(5) +#endif + +// Applicable to 64-byte and zvc descriptors only +#define IDMA_64B_SUBTYPE_MASK UINT32_C(0x00000007) +#define IDMA_64B_SUBTYPE_SHIFT 4 +#define IDMA_64B_1D_TYPE UINT32_C(0) +#define IDMA_64B_2D_TYPE UINT32_C(1) +#define IDMA_64B_2D_COMPRESS_TYPE UINT32_C(2) +#define IDMA_64B_3D_TYPE UINT32_C(4) +#define IDMA_64B_2D_FBC_TYPE UINT32_C(6) +#define IDMA_ZVC_1D_TYPE UINT32_C(5) +#define IDMA_ZVC_2D_TYPE UINT32_C(7) +#define IDMA_64B_LONG_ADDR_CTRL_BIT_MASK UINT32_C(0x00000400) +#define SET_CONTROL_SUBTYPE(a) (((a) & IDMA_64B_SUBTYPE_MASK) << IDMA_64B_SUBTYPE_SHIFT) + +// Inline selection for "wrapper" functions +#define WRAPPER_FUNC static __attribute__((always_inline)) + +#define IDMA_1D_DESC_SIZE 16 +#define IDMA_2D_DESC_SIZE 32 +#define IDMA_64_DESC_SIZE 64 + +// Data placement in local memory. First, let the user select which dataram to +// use. If the user has defined neither IDMA_USE_DRAM0 or IDMA_USE_DRAM1, then +// - if both datarams are present, choose the one at the lower address +// - if only one is present, it must be dataram0 + +#if defined (IDMA_USE_DRAM_BSS) +# define IDMA_SECTION "bss" +#else +# define IDMA_SECTION "data" +#endif + +#if defined (IDMA_USE_DRAM1) +# define IDMA_DRAM __attribute__ ((section(".dram1."IDMA_SECTION))) +#elif defined (IDMA_USE_DRAM0) +# define IDMA_DRAM __attribute__ ((section(".dram0."IDMA_SECTION))) +#else +# if (XCHAL_NUM_DATARAM > 1) +# if XCHAL_DATARAM1_VADDR > XCHAL_DATARAM0_VADDR +# define IDMA_DRAM __attribute__ ((section(".dram0."IDMA_SECTION))) +# else +# define IDMA_DRAM __attribute__ ((section(".dram1."IDMA_SECTION))) +# endif +# else +# define IDMA_DRAM __attribute__ ((section(".dram0."IDMA_SECTION))) +# endif +#endif + +#ifdef IDMA_DEBUG +# define IDMA_CONTROL_STRUCT_SIZE_ 52 +#else +# define IDMA_CONTROL_STRUCT_SIZE_ 48 +#endif + +# ifdef IDMA_DEBUG +# define IDMA_ASSERT(expr) +void idma_print(int32_t ch, const char* fmt, ...); +# define XLOG(ch, ...) do { idma_print((ch), __VA_ARGS__);} while (0) // parasoft-suppress MISRA2012-RULE-20_7 "used only in non-FuSa code" +# else +# define IDMA_ASSERT(expr) +# define XLOG(ch, ...) (void)(ch); do {} while (0) +# endif + + +/* 1D descriptor structure */ +struct idma_desc_struct { + uint32_t control; + uint32_t src; + uint32_t dst; + uint32_t size; +}; + +/* 2D descriptor structure */ +struct idma_2d_desc_struct { + uint32_t control; + uint32_t src; + uint32_t dst; + uint32_t size; + uint32_t src_pitch; + uint32_t dst_pitch; + uint32_t nrows; + uint32_t word8; +}; + +/* 64B descriptor structure */ +struct idma_desc64_struct { + uint32_t control; + uint32_t src; + uint32_t dst; + uint32_t size; + uint32_t src_pitch; + uint32_t dst_pitch; + uint32_t nrows; + uint32_t word8; + int32_t src_tile_pitch; + int32_t dst_tile_pitch; + uint32_t ntiles; + uint32_t pred_mask; + uint32_t word13; + uint32_t word14; + uint32_t ext_src; + uint32_t ext_dst; +}; + +/* Real buffer struct - NOT TO BE USED BY APPLICATION */ + +struct idma_buf_struct { + idma_desc_t * next_desc; // points past the last scheduled desc. Used by functions + // needing to update the desc that is just to be scheduled. + idma_desc_t * next_add_desc; // points past the last added desc. Used by functions that + // populate a new task, or populate a buffer where later + // schedule call will schedule them all at once. + + int32_t num_descs; // total num of descs, assigned on init. In fixed buffer mode + // it sets the size of the circular buffer by setting JUMP + // command between the last desc and the 1st one. In TASK mode + // it is used to tell the lib how many descs to schedule. + idma_desc_t * last_desc; // points past the last desc. Assigned to sped-up wrap-arround + // calculation, not to use num_descs and multiplication. + + int32_t type; // descs type, assigned on init. + + idma_buf_t * next_task; // TASK: points to next task, assigned on schedule + int32_t cur_desc_i; // FIXED-BUFFER: tracks next desc to execute. + int32_t status; // TASK: # of remaining descs after schedule. + // BOTH modes: error type, if in error. + idma_callback_fn cb_func; // Callback on completion + void * cb_data; // Completion callback argument + int32_t ch; + void * thread_id; // (OS-specific) ID of owning thread + int16_t sleeping; // Nonzero when thread is sleeping (blocked) + int16_t pending; // Nonzero when buffer is queued + int32_t pending_desc_cnt; + + idma_desc_t desc __attribute__ ((aligned(16))); +}; + + +/* Inline functions for iDMA register read/write */ +ALWAYS_INLINE uint32_t +READ_IDMA_REG(int32_t ch, int32_t reg) +{ + return IDMA_RER(IDMA_REG_ADDR(ch,reg)); +} + +ALWAYS_INLINE void +WRITE_IDMA_REG(int32_t ch, int32_t reg, uint32_t val) +{ + IDMA_WER(val, IDMA_REG_ADDR(ch,reg)); +} + +ALWAYS_INLINE void +set_desc_addr_fields(idma_desc_t * desc, + void * dst, + void * src) +{ +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + uint32_t * src36 = cvt_voidp_to_uint32p(src); + uint32_t * dst36 = cvt_voidp_to_uint32p(dst); + uint32_t wide_addr_mask = IDMA_WIDE_ADDR_MASK; + + desc->src = src36[0]; + desc->dst = dst36[0]; + desc->control = + (desc->control & ~(wide_addr_mask << SRC_WIDE_ADDR_SHIFT)) | ((src36[1] & wide_addr_mask) << SRC_WIDE_ADDR_SHIFT); + desc->control = + (desc->control & ~(wide_addr_mask << DST_WIDE_ADDR_SHIFT)) | ((dst36[1] & wide_addr_mask) << DST_WIDE_ADDR_SHIFT); +#else + desc->src = cvt_voidp_to_uint32(src); + desc->dst = cvt_voidp_to_uint32(dst); +#endif +} + +ALWAYS_INLINE void +set_1d_fields( int32_t ch, + idma_desc_t* desc, + void *dst, + void *src, + size_t size) +{ + set_desc_addr_fields(desc, dst, src); + desc->size = size; +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE +# ifdef IDMA_DEBUG + { + uint32_t src64 = (desc->control >> SRC_WIDE_ADDR_SHIFT) & IDMA_WIDE_ADDR_MASK; + uint32_t dst64 = (desc->control >> DST_WIDE_ADDR_SHIFT) & IDMA_WIDE_ADDR_MASK; + XLOG(ch, "Add 1D desc wide @ %p, %d-bytes(%x-%p -> %x-%p), control:0x%x\n", + desc, desc->size, src64, desc->src, dst64, desc->dst, desc->control); + } +# endif +#else + XLOG(ch, "Add 1D desc @ %p, %d-bytes(%p -> %p), control:0x%x\n", desc, desc->size, desc->src, desc->dst, desc->control); +#endif + (void)(ch); +} + +ALWAYS_INLINE void +set_2d_fields(int32_t ch, + idma_desc_t* desc, + void *dst, + void *src, + size_t size, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch) +{ + idma_2d_desc_t* desc2d = (idma_2d_desc_t*) desc; // parasoft-suppress MISRA2012-RULE-11_3 "conversion checked" + set_desc_addr_fields(desc, dst, src); + desc2d->size = size; + desc2d->nrows = nrows; + desc2d->src_pitch = src_pitch; + desc2d->dst_pitch = dst_pitch; +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE +# ifdef IDMA_DEBUG + { + uint32_t src64 = (desc->control >> SRC_WIDE_ADDR_SHIFT) & IDMA_WIDE_ADDR_MASK; + uint32_t dst64 = (desc->control >> DST_WIDE_ADDR_SHIFT) & IDMA_WIDE_ADDR_MASK; + XLOG(ch, "Add 2D desc wide @ %p, %d-bytes (%x-%p -> %x-%p)\n", + desc2d, desc2d->size, src64, desc->src, dst64, desc->dst); + XLOG(ch, " (#rows:%d, src_pitch:%d, dst_pitch:%d, control:0x%x)\n", + desc2d->nrows, desc2d->src_pitch, desc2d->dst_pitch, desc2d->control); + + } +# endif +#else + XLOG(ch, "Add 2D desc @ %p, %d-bytes (%p -> %p)\n", desc2d, desc2d->size, desc2d->src, desc2d->dst); + XLOG(ch, " (#rows:%d, src_pitch:%d, dst_pitch:%d, control:0x%x)\n", + desc2d->nrows, desc2d->src_pitch, desc2d->dst_pitch, desc2d->control); +#endif + (void)(ch); +} + +#if (IDMA_USE_64B_DESC > 0) + +INTERNAL_FUNC void +set_desc64_short_addr(idma_desc64_t* desc, void *dst, void *src) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const, backward compatibility and dst is modified" +{ + desc->src = (cvt_voidp_to_uint32p(src))[0]; + desc->dst = (cvt_voidp_to_uint32p(dst))[0]; +} + + +INTERNAL_FUNC void +set_desc64_2d_pitch(idma_desc64_t* desc, uint32_t src_pitch, uint32_t dst_pitch) +{ + desc->src_pitch = src_pitch; + desc->dst_pitch = dst_pitch; +} + +INTERNAL_FUNC void +set_desc64_3d_pitch(idma_desc64_t* desc, uint32_t src_pitch, uint32_t dst_pitch, uint32_t src_tile_pitch, uint32_t dst_tile_pitch) +{ + set_desc64_2d_pitch(desc, src_pitch, dst_pitch); + desc->src_tile_pitch = (int32_t) src_tile_pitch; + desc->dst_tile_pitch = (int32_t) dst_tile_pitch; +} + +INTERNAL_FUNC void +set_1d_desc64_fields(int32_t ch, + idma_desc_t* desch, + void *dst, + void *src, + size_t size) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + + set_desc64_short_addr(desc, dst, src); + desc->size = size; + XLOG(ch, "Add 1D desc64 @ %p, %d-bytes(%lx -> %lx), control:0x%x\n", desc, desc->size, desc->src, desc->dst, desc->control); +} + +INTERNAL_FUNC void +set_2d_desc64_fields(int32_t ch, + idma_desc_t* desch, + void *dst, + void *src, + size_t size, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + + set_desc64_short_addr(desc, dst, src); + set_desc64_2d_pitch(desc, src_pitch, dst_pitch); + desc->size = size; + desc->nrows = nrows; + + XLOG(ch, "Add 2D desc @ %p, %d-bytes (%x -> %x)\n", desc, desc->size, desc->src, desc->dst); + XLOG(ch, " (#rows:%d, src_pitch:%d, dst_pitch:%d, control:0x%x)\n", desc->nrows, desc->src_pitch, desc->dst_pitch, desc->control); +} + +INTERNAL_FUNC void +set_3d_desc64_fields(int32_t ch, + idma_desc_t* desch, + void *dst, + void *src, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_pitch, + uint32_t dst_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + + set_desc64_short_addr(desc, dst, src); + set_desc64_3d_pitch(desc, src_pitch, dst_pitch, src_tile_pitch, dst_tile_pitch); + + desc->size = row_sz; + desc->nrows = nrows; + desc->ntiles = ntiles; + + XLOG(ch, "Add 3D desc @ %p, %d-bytes (%x -> %x)\n", desc, desc->size, desc->src, desc->dst); + XLOG(ch, " (#row_sz/rows/tiles:%d/%d/%d, row_pitch:%d/%d, tile_pitch:%d/%d, control:0x%x)\n", + desc->size,desc->nrows, desc->ntiles, desc->src_pitch, desc->dst_pitch, src_tile_pitch, dst_tile_pitch, desc->control); +} + +INTERNAL_FUNC void +set_desc64_ctrl(idma_desc_t* desch, uint32_t flags, uint32_t code) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + desc->control = (flags | code); +} + +#if (IDMA_USE_WIDE_API > 0) + +INTERNAL_FUNC void +set_desc64_long_addr(idma_desc64_t* desc, void *dst, void *src) +{ + set_desc64_short_addr(desc, dst, src); + desc->ext_src = (cvt_voidp_to_uint32p(src))[1]; + desc->ext_dst = (cvt_voidp_to_uint32p(dst))[1]; +} + +INTERNAL_FUNC void +set_1d_desc64_fields_wide(int32_t ch, + idma_desc_t* desch, + void *dst, + void *src, + size_t size) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + + set_desc64_long_addr(desc, dst, src); + desc->size = size; + XLOG(ch, "Add 1D desc64 wide @ %p, %d-bytes(%x-%x -> %x-%x), control:0x%x\n", desc, desc->size, desc->ext_src, desc->src, desc->ext_dst, desc->dst, desc->control); +} + +INTERNAL_FUNC void +set_2d_desc64_fields_wide(int32_t ch, + idma_desc_t* desch, + void *dst, + void *src, + size_t size, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + + set_desc64_long_addr(desc, dst, src); + set_desc64_2d_pitch(desc, src_pitch, dst_pitch); + desc->size = size; + desc->nrows = nrows; + + XLOG(ch, "Add 2D desc wide @ %p, %d-bytes (%x-%x -> %x-%x)\n", desc, desc->size, desc->ext_src, desc->src, desc->ext_dst, desc->dst); + XLOG(ch, " (#rows:%d, src_pitch:%d, dst_pitch:%d, control:0x%x)\n", desc->nrows, desc->src_pitch, desc->dst_pitch, desc->control); +} + +INTERNAL_FUNC void +set_3d_desc64_fields_wide(int32_t ch, + idma_desc_t* desch, + void *dst, + void *src, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_pitch, + uint32_t dst_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch) +{ + idma_desc64_t* desc = cvt_desc_to_desc64(desch); + + set_desc64_long_addr(desc, dst, src); + set_desc64_3d_pitch(desc, src_pitch, dst_pitch, src_tile_pitch, dst_tile_pitch); + desc->size = row_sz; + desc->nrows = nrows; + desc->ntiles = ntiles; + + XLOG(ch, "Add 3D desc wide @ %p, %d-bytes (%x-%x -> %x-%x)\n", desc, desc->size, desc->ext_src, desc->src, desc->ext_dst, desc->dst); + XLOG(ch, " (#row_sz/rows/tiles:%d/%d/%d, row_pitch:%d/%d, tile_pitch:%d/%d, control:0x%x)\n", + desc->size,desc->nrows, desc->ntiles, desc->src_pitch, desc->dst_pitch, src_tile_pitch, dst_tile_pitch, desc->control); +} + +#endif +#endif + +INTERNAL_FUNC void +set_desc_ctrl(idma_desc_t* desc, uint32_t flags, uint32_t code) +{ + desc->control = (flags | code); +} + +INTERNAL_FUNC void +update_next_add_ptr(idma_buf_t* buf) +{ + idma_desc_t* next = &buf->next_add_desc[buf->type]; + + if (next >= buf->last_desc) { + next = &buf->desc; + } + buf->next_add_desc = next; +} + +#if defined(IDMA_USE_XTOS) || defined(IDMA_APP_USE_XTOS) +INTERNAL_FUNC void +update_next_desc(int32_t ch, uint32_t count) +{ + idma_buf_t* buf; + idma_desc_t* next; + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + next = &buf->next_desc[count*(uint32_t)buf->type]; // parasoft-suppress MISRA2012-DIR-4_1_b "Skip check for performance" + + if (next >= buf->last_desc) { + next = &buf->desc + (next - buf->last_desc); // parasoft-suppress MISRA2012-RULE-18_4-4 "Pointer arithmetic cleaner than casting" + } + buf->next_desc = next; + } +} +#endif + +INTERNAL_FUNC void +hw_schedule(int32_t ch, uint32_t count) +{ + extern uint32_t g_idma_ctrl; + +#if XCHAL_HAVE_XEA2 || XCHAL_HAVE_XEA3 + XT_MEMW(); +#endif + WRITE_IDMA_REG(ch, IDMA_REG_CONTROL, 0x1U | g_idma_ctrl); + WRITE_IDMA_REG(ch, IDMA_REG_DESC_INC, count); +} + +INTERNAL_FUNC uint32_t +hw_num_outstanding(int32_t ch) +{ + return READ_IDMA_REG(ch, IDMA_REG_NUM_DESC); +} + +INTERNAL_FUNC int32_t +schedule_desc_fast(int32_t ch, uint32_t count) +{ + idma_buf_t* buf = idma_chan_buf_get(ch); + if (buf != NULL) { + buf->cur_desc_i += (int32_t)count; + buf->cur_desc_i &= INT32_C(0x7fffffff); + + XLOG(ch, "Schedule %d desc from index:%d\n", count, buf->cur_desc_i); + hw_schedule(ch, count); + return buf->cur_desc_i; + } + + return (int32_t) IDMA_ERR_BAD_CHAN; +} + +#if defined(IDMA_USE_XTOS) || defined(IDMA_APP_USE_XTOS) +INTERNAL_FUNC int32_t +schedule_desc(int32_t ch, uint32_t count) +{ + update_next_desc(ch, count); + return schedule_desc_fast(ch, count); +} +#else +int32_t schedule_thread_buffer(int32_t ch, uint32_t count); + +INTERNAL_FUNC int32_t +schedule_desc(int32_t ch, uint32_t count) +{ + return schedule_thread_buffer(ch, count); +} +#endif + +WRAPPER_FUNC idma_buf_t * +convert_buffer_to_buf(idma_buffer_t * buffer) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Pointer is converted, cannot use const here" +{ + return (idma_buf_t *) buffer; // parasoft-suppress MISRA2012-RULE-11_3-2 "Conversion to internal data type OK" +} + + +idma_status_t idma_sleep_i(int32_t ch); +int32_t idma_buffer_status_i(int32_t ch); +idma_state_t idma_get_state_i(int32_t ch); +idma_status_t idma_init_i(int32_t ch, uint32_t flags, idma_max_block_t block_sz, uint32_t pif_req, idma_ticks_cyc_t ticks_per_cyc, uint32_t timeout_ticks, idma_err_callback_fn err_cb_func); +void idma_stop_i(int32_t ch); +void idma_pause_i(int32_t ch); +void idma_enable_i(int32_t ch); +void idma_resume_i(int32_t ch); +idma_status_t idma_process_tasks_i(int32_t ch); +idma_status_t idma_abort_tasks_i(int32_t ch); +idma_status_t idma_init_task_i (int32_t ch, idma_buffer_t *taskh, idma_type_t type, int32_t ndescs, idma_callback_fn cb_func, void *cb_data); +idma_status_t idma_copy_task_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t size, uint32_t flags, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_task64_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t size, uint32_t flags, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_task64_wide_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t size, uint32_t flags, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_2d_task64_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_2d_task64_wide_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_2d_pred_task64_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t row_sz, uint32_t flags, void* pred_mask, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_2d_pred_task64_wide_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t row_sz, uint32_t flags, void* pred_mask, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_3d_task64_i( int32_t ch, idma_buffer_t *taskh, void *dst, void *src, uint32_t flags, size_t row_sz, uint32_t nrows, uint32_t ntiles, uint32_t src_pitch, uint32_t dst_pitch, uint32_t src_tile_pitch, uint32_t dst_tile_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_3d_task64_wide_i( int32_t ch, idma_buffer_t *taskh, void *dst, void *src, uint32_t flags, size_t row_sz, uint32_t nrows, uint32_t ntiles, uint32_t src_pitch, uint32_t dst_pitch, uint32_t src_tile_pitch, uint32_t dst_tile_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_copy_2d_task_i(int32_t ch, idma_buffer_t *taskh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch, void *cb_data, idma_callback_fn cb_func); +idma_status_t idma_init_loop_i (int32_t ch, idma_buffer_t* bufh, idma_type_t type, int32_t ndescs, void* cb_data, idma_callback_fn cb_func); +idma_hw_error_t idma_buffer_check_errors_i(int32_t ch); +idma_error_details_t* idma_error_details_i(int32_t ch); + + +/************************************************/ +/**** API Implementation ****/ +/************************************************/ + +IDMA_API void +idma_hw_wait_all(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + uint32_t state; + do { + state = READ_IDMA_REG(IDMA_CH_PTR, IDMA_REG_STATUS) & IDMA_STATE_MASK; + if ((state == (uint32_t)IDMA_STATE_DONE) || (state == (uint32_t)IDMA_STATE_IDLE) || (state == (uint32_t)IDMA_STATE_ERROR)) { + break; + } + } while (1); +} + +IDMA_API void +idma_hw_schedule(IDMA_CHAN_FUNC_ARG + uint32_t count) +{ +#if defined(IDMA_USE_XTOS) || defined(IDMA_APP_USE_XTOS) + hw_schedule(IDMA_CH_PTR, count); +#else +# if (LIBIDMA_USE_MULTICHANNEL_API > 0) + (void) idma_schedule_desc(ch, count); +# else + (void) idma_schedule_desc(count); +# endif +#endif +} + +IDMA_API uint32_t +idma_hw_num_outstanding(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return hw_num_outstanding(IDMA_CH_PTR); +} + +IDMA_API idma_state_t +idma_get_state(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return idma_get_state_i(IDMA_CH_PTR); +} + +IDMA_API idma_status_t +idma_init( IDMA_CHAN_FUNC_ARG + uint32_t flags, + idma_max_block_t block_sz, + uint32_t pif_req, + idma_ticks_cyc_t ticks_per_cyc, + uint32_t timeout_ticks, + idma_err_callback_fn err_cb_func) +{ + return idma_init_i(IDMA_CH_PTR, flags, block_sz, pif_req, ticks_per_cyc, timeout_ticks, err_cb_func); +} + +IDMA_API idma_status_t +idma_stop(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + idma_stop_i(IDMA_CH_PTR); + return IDMA_OK; +} + +IDMA_API void +idma_pause(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + idma_pause_i(IDMA_CH_PTR); +} + +IDMA_API void +idma_resume(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + idma_resume_i(IDMA_CH_PTR); +} + +IDMA_API idma_status_t +idma_sleep(IDMA_CHAN_FUNC_ARG_SINGLE) +{ +#if defined(IDMA_USERMODE) + return IDMA_CANT_SLEEP; +#else + return idma_sleep_i(IDMA_CH_PTR); +#endif +} + +IDMA_API idma_status_t +idma_init_loop (IDMA_CHAN_FUNC_ARG + idma_buffer_t *bufh, + idma_type_t type, + int32_t ndescs, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_init_loop_i(IDMA_CH_PTR, bufh, type, ndescs, cb_data, cb_func); +} + +IDMA_API int32_t +idma_buffer_status(IDMA_CHAN_FUNC_ARG_SINGLE) { + return idma_buffer_status_i(IDMA_CH_PTR); +} + +IDMA_API idma_status_t +idma_add_desc( idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + uint32_t flags) +{ + idma_buf_t *buf; + DECLARE_PS(); + IDMA_DISABLE_INTS(); + buf = convert_buffer_to_buf(bufh); + + set_desc_ctrl(buf->next_add_desc, flags, IDMA_1D_DESC_CODE); + set_1d_fields(buf->ch, buf->next_add_desc, dst, src, size); + + update_next_add_ptr(buf); + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + + +static inline idma_status_t +idma_add_2d_desc( idma_buffer_t *bufh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + + set_desc_ctrl(buf->next_add_desc, flags, IDMA_2D_DESC_CODE); + set_2d_fields(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, src_pitch, dst_pitch); + + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_desc(IDMA_CHAN_FUNC_ARG + void *dst, + void *src, + size_t size, + uint32_t flags) +{ + int32_t ret; + idma_buf_t* buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(IDMA_CH_PTR); + + set_desc_ctrl(buf->next_desc, flags, IDMA_1D_DESC_CODE); + set_1d_fields(IDMA_CH_PTR, buf->next_desc, dst, src, size); + + ret = schedule_desc(IDMA_CH_PTR, 1U); + IDMA_ENABLE_INTS(); + + return ret; +} + +IDMA_API int32_t +idma_copy_2d_desc(IDMA_CHAN_FUNC_ARG void *dst, void *src, size_t size, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret = 0; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(IDMA_CH_PTR); + + set_desc_ctrl(buf->next_desc, flags, IDMA_2D_DESC_CODE); + set_2d_fields (IDMA_CH_PTR, buf->next_desc, dst, src, size, nrows, src_pitch, dst_pitch); + + ret = schedule_desc(IDMA_CH_PTR, 1U); + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API int32_t +idma_schedule_desc(IDMA_CHAN_FUNC_ARG + uint32_t count) +{ + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + ret = schedule_desc(IDMA_CH_PTR, count); + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API int32_t +idma_schedule_desc_fast(IDMA_CHAN_FUNC_ARG + uint32_t count) +{ + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); +#if defined(IDMA_USE_XTOS) || defined(IDMA_APP_USE_XTOS) + ret = schedule_desc_fast(IDMA_CH_PTR, count); +#else + ret = schedule_desc(IDMA_CH_PTR, count); +#endif + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API int32_t +idma_desc_done(IDMA_CHAN_FUNC_ARG + int32_t index) +{ + idma_buf_t* buf; + int32_t diff ; + DECLARE_PS(); + int32_t ret = 0; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(IDMA_CH_PTR); + + if (buf == NULL) { + ret = -1; + } + else if (buf != g_idma_buf_ptr[IDMA_CH_PTR]) { // parasoft-suppress MISRA2012-RULE-14_3_zc--1 "Not a constant expression in all configs" +#if defined(IDMA_USE_XTOS) || defined(IDMA_APP_USE_XTOS) + ret = -1; +#else + /* There are 3 cases to handle when the buffer is not the active buffer: + * - buffer is queued but not yet started, + * - buffer has completed successfully, or + * - buffer has encountered an error. + */ + ret = (buf->pending > 0) ? 0 : (buf->status == 0) ? 1 : -1; +#endif + } + else { + /* Descriptor is done if it's index is less then or equal the difference between + the last scheduled descriptor, and the number of outstanding descriptors. + We take the diff between the last scheduled descriptor and the index. + This diff is (cur_desc_i - index) or 0x7fffffff - (index - cur_desc_i) + depending on which value is larger. + */ + diff = (buf->cur_desc_i - index) & INT32_C(0x7fffffff); + if ((int32_t)hw_num_outstanding(IDMA_CH_PTR) <= diff) { + ret = 1; + } + + XLOG(IDMA_CH_PTR, "Descriptor @%u: %s (remaining: %d, current:%d) \n", + index, ((ret != 0) ? "DONE" : "PENDING"), hw_num_outstanding(IDMA_CH_PTR), buf->cur_desc_i); + } + + IDMA_ENABLE_INTS(); + return ret; +} + +ALWAYS_INLINE idma_status_t +idma_update_desc_dst(IDMA_CHAN_FUNC_ARG + void *dst) +{ + idma_desc_t *desc; + idma_buf_t *buf; +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + uint32_t * dstw = cvt_voidp_to_uint32p(dst); +#endif + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(IDMA_CH_PTR); + desc = buf->next_desc; +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + desc->dst = dstw[0]; + { + uint32_t wide_addr_mask = IDMA_WIDE_ADDR_MASK; + desc->control = + (desc->control & ~(wide_addr_mask << DST_WIDE_ADDR_SHIFT)) | ((dstw[1] & wide_addr_mask) << DST_WIDE_ADDR_SHIFT); + } + XLOG(IDMA_CH_PTR, "Change dst field for descriptor @ %p to: %p-%p\n", + desc, cvt_uint32_to_voidp(dstw[1]), cvt_uint32_to_voidp(dstw[0])); +#else + desc->dst = cvt_voidp_to_uint32(dst); + XLOG(IDMA_CH_PTR, "Change dst field for descriptor @ %p to: %p\n", + desc, desc->dst); +#endif + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +ALWAYS_INLINE idma_status_t +idma_update_desc_src(IDMA_CHAN_FUNC_ARG + void *src) +{ + idma_desc_t *desc; + idma_buf_t *buf; +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + uint32_t * srcw = cvt_voidp_to_uint32p(src); +#endif + + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(IDMA_CH_PTR); + desc = buf->next_desc; +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + desc->src = srcw[0]; + { + uint32_t wide_addr_mask = IDMA_WIDE_ADDR_MASK; + desc->control = + (desc->control & ~(wide_addr_mask << SRC_WIDE_ADDR_SHIFT)) | ((srcw[1] & wide_addr_mask) << SRC_WIDE_ADDR_SHIFT); + } + XLOG(IDMA_CH_PTR, "Change src field for descriptor @ %p to: %p-%p\n", + desc, cvt_uint32_to_voidp(srcw[1]), cvt_uint32_to_voidp(srcw[0])); +#else + desc->src = cvt_voidp_to_uint32(src); + XLOG(IDMA_CH_PTR, "Change src field for descriptor @ %p to: %p\n", + desc, desc->src); +#endif + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +IDMA_API idma_status_t +idma_update_desc_size(IDMA_CHAN_FUNC_ARG + uint32_t size) +{ + idma_desc_t *desc; + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(IDMA_CH_PTR); + desc = buf->next_desc; + desc->size = size; + + XLOG(IDMA_CH_PTR, "Change size field for descriptor @ %p to: %d\n", desc, desc->size); + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +#if (IDMA_USE_64B_DESC > 0) + +IDMA_API idma_status_t +idma_update_desc64_dst(int32_t ch, void *dst) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const, dst modified" +{ + idma_desc64_t *desc; + idma_buf_t *buf; + idma_status_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + desc = cvt_desc_to_desc64(buf->next_desc); + desc->dst = (cvt_voidp_to_uint32p(dst))[0]; + XLOG(ch, "Change dst field for descriptor @ %p to: %p\n", desc, desc->dst); + ret = IDMA_OK; + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API idma_status_t +idma_update_desc64_src(int32_t ch, void *src) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const (backward compatibility)" +{ + idma_desc64_t *desc; + idma_buf_t *buf; + idma_status_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + desc = cvt_desc_to_desc64(buf->next_desc); + desc->src = (cvt_voidp_to_uint32p(src))[0]; + + XLOG(ch, "Change src field for descriptor @ %p to: %p\n", desc, desc->src); + ret = IDMA_OK; + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API idma_status_t +idma_update_desc64_size(int32_t ch, uint32_t size) +{ + idma_desc64_t *desc; + idma_buf_t *buf; + idma_status_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + desc = cvt_desc_to_desc64(buf->next_desc); + desc->size = size; + + XLOG(ch, "Change size field for descriptor @ %p to: %d\n", desc, desc->size); + ret = IDMA_OK; + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +#if (IDMA_USE_WIDE_API > 0) + +IDMA_API idma_status_t +idma_update_desc64_dst_wide(int32_t ch, void *dst) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const (backward compatibility)" +{ + idma_desc64_t *desc; + idma_buf_t *buf; + idma_status_t ret; + + DECLARE_PS(); + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + desc = cvt_desc_to_desc64(buf->next_desc); + desc->dst = (cvt_voidp_to_uint32p(dst))[0]; + desc->ext_dst = (cvt_voidp_to_uint32p(dst))[1]; + XLOG(ch, "Change dst field for descriptor @ %p to: %p\n", desc, desc->dst); + ret = IDMA_OK; + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API idma_status_t +idma_update_desc64_src_wide(int32_t ch, void *src) // parasoft-suppress MISRA2012-RULE-8_13_a-4 "Cannot use const (backward compatibility)" +{ + idma_desc64_t *desc; + idma_buf_t *buf; + idma_status_t ret; + + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + desc = cvt_desc_to_desc64(buf->next_desc); + desc->src = (cvt_voidp_to_uint32p(src))[0]; + desc->ext_src = (cvt_voidp_to_uint32p(src))[1]; + XLOG(ch, "Change src field for descriptor @ %p to: %p\n", desc, desc->src); + ret = IDMA_OK; + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +#endif +#endif + +IDMA_API idma_status_t +idma_init_task (IDMA_CHAN_FUNC_ARG + idma_buffer_t *taskh, + idma_type_t type, + int32_t ndescs, + idma_callback_fn cb_func, + void *cb_data) +{ + return idma_init_task_i(IDMA_CH_PTR, taskh, type, ndescs, cb_func, cb_data); +} + +ALWAYS_INLINE idma_status_t +idma_copy_task(IDMA_CHAN_FUNC_ARG + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func) +{ +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + return idma_copy_task_wide_i(IDMA_CH_PTR, taskh, dst, src, size, flags, cb_data, cb_func); +#else + return idma_copy_task_i(IDMA_CH_PTR, taskh, dst, src, size, flags, cb_data, cb_func); +#endif +} + +ALWAYS_INLINE idma_status_t +idma_copy_2d_task(IDMA_CHAN_FUNC_ARG + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ +#ifdef IDMA_USE_WIDE_ADDRESS_COMPILE + return idma_copy_2d_task_wide_i(IDMA_CH_PTR, taskh, dst, src, row_sz, flags, nrows, src_pitch, dst_pitch, cb_data, cb_func); +#else + return idma_copy_2d_task_i(IDMA_CH_PTR, taskh, dst, src, row_sz, flags, nrows, src_pitch, dst_pitch, cb_data, cb_func); +#endif +} + +#if (IDMA_USE_64B_DESC > 0) + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +IDMA_API idma_status_t +idma_copy_2d_pred_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_2d_pred_task64_i(ch, taskh, dst, src, row_sz, flags, pred_mask, nrows, src_pitch, dst_pitch, cb_data, cb_func); +} +#endif + +IDMA_API idma_status_t +idma_copy_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_task64_i(ch, taskh, dst, src, size, flags, cb_data, cb_func); +} + +IDMA_API idma_status_t +idma_copy_2d_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_2d_task64_i(ch, taskh, dst, src, row_sz, flags, nrows, src_pitch, dst_pitch, cb_data, cb_func); +} + +IDMA_API idma_status_t +idma_copy_3d_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_pitch, + uint32_t dst_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_3d_task64_i(ch, taskh, dst, src, flags, row_sz, nrows, ntiles, src_pitch, dst_pitch, src_tile_pitch, dst_tile_pitch, cb_data, cb_func); +} + +IDMA_API idma_status_t +idma_add_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + uint32_t flags) +{ + idma_buf_t *buf; + DECLARE_PS(); + IDMA_DISABLE_INTS(); + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_1D_TYPE)); + set_1d_desc64_fields(buf->ch, buf->next_add_desc, dst, src, size); + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +static inline idma_status_t +idma_add_2d_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_2D_TYPE)); + set_2d_desc64_fields(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, src_pitch, dst_pitch); + + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +static inline idma_status_t +idma_add_2d_pred_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_2D_COMPRESS_TYPE)); + set_2d_desc64_fields(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, src_pitch, dst_pitch); + (cvt_desc_to_desc64(buf->next_add_desc))->pred_mask = cvt_voidp_to_uint32(pred_mask); + + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} +#endif + +IDMA_API idma_status_t +idma_add_3d_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_3D_TYPE)); + set_3d_desc64_fields(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, ntiles, src_row_pitch, dst_row_pitch, src_tile_pitch, dst_tile_pitch); + + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_desc64(int32_t ch, void *dst, void *src, size_t size, uint32_t flags) +{ + int32_t ret; + idma_buf_t* buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_1D_TYPE)); + set_1d_desc64_fields(ch, buf->next_desc, dst, src, size); + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API int32_t +idma_copy_2d_desc64(int32_t ch, + void *dst, + void *src, + size_t size, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_2D_TYPE)); + set_2d_desc64_fields(ch, buf->next_desc, dst, src, size, nrows, src_pitch, dst_pitch); + + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +IDMA_API int32_t +idma_copy_2d_pred_desc64(int32_t ch, void *dst, void *src, size_t size, uint32_t flags, void* pred_mask, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_2D_COMPRESS_TYPE)); + set_2d_desc64_fields(ch, buf->next_desc, dst, src, size, nrows, src_pitch, dst_pitch); + (cvt_desc_to_desc64(buf->next_desc))->pred_mask = cvt_voidp_to_uint32(pred_mask); + + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} +#endif + + +IDMA_API int32_t +idma_copy_3d_desc64(int32_t ch, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_3D_TYPE)); + set_3d_desc64_fields(ch, buf->next_desc, dst, src, row_sz, nrows, ntiles, src_row_pitch, dst_row_pitch, src_tile_pitch, dst_tile_pitch); + + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +#if (IDMA_USE_WIDE_API > 0) + +IDMA_API idma_status_t +idma_copy_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_task64_wide_i(ch, taskh, dst, src, size, flags, cb_data, cb_func); +} + +IDMA_API idma_status_t +idma_copy_2d_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_2d_task64_wide_i(ch, taskh, dst, src, row_sz, flags, nrows, src_pitch, dst_pitch, cb_data, cb_func); +} + +IDMA_API idma_status_t +idma_copy_3d_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_pitch, + uint32_t dst_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_3d_task64_wide_i(ch, taskh, dst, src, flags, row_sz, nrows, ntiles, src_pitch, dst_pitch, src_tile_pitch, dst_tile_pitch, cb_data, cb_func); +} + +IDMA_API idma_status_t +idma_add_desc64_wide( idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + uint32_t flags) +{ + idma_buf_t *buf; + DECLARE_PS(); + IDMA_DISABLE_INTS(); + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_1D_TYPE)); + set_1d_desc64_fields_wide(buf->ch, buf->next_add_desc, dst, src, size); + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_desc64_wide(int32_t ch, void *dst, void *src, size_t size, uint32_t flags) +{ + int32_t ret; + idma_buf_t* buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_1D_TYPE)); + set_1d_desc64_fields_wide(ch, buf->next_desc, dst, src, size); + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +IDMA_API idma_status_t +idma_copy_2d_pred_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t row_sz, + uint32_t flags, + void* pred_mask, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_2d_pred_task64_wide_i(ch, taskh, dst, src, row_sz, flags, pred_mask, nrows, src_pitch, dst_pitch, cb_data, cb_func); +} + + +static inline idma_status_t +idma_add_2d_pred_desc64_wide( idma_buffer_t *bufh, void *dst, void *src, size_t row_sz, uint32_t flags, void* pred_mask, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_2D_COMPRESS_TYPE)); + set_2d_desc64_fields_wide(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, src_pitch, dst_pitch); + (cvt_desc_to_desc64(buf->next_add_desc))->pred_mask = cvt_voidp_to_uint32(pred_mask); + + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} +#endif + +static inline idma_status_t +idma_add_2d_desc64_wide( idma_buffer_t *bufh, void *dst, void *src, size_t row_sz, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_2D_TYPE)); + set_2d_desc64_fields_wide(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, src_pitch, dst_pitch); + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +IDMA_API idma_status_t +idma_add_3d_desc64_wide( idma_buffer_t *bufh, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + set_desc64_ctrl(buf->next_add_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_3D_TYPE)); + set_3d_desc64_fields_wide(buf->ch, buf->next_add_desc, dst, src, row_sz, nrows, ntiles, src_row_pitch, dst_row_pitch, src_tile_pitch, dst_tile_pitch); + update_next_add_ptr(buf); + + IDMA_ENABLE_INTS(); + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_2d_desc64_wide(int32_t ch, void *dst, void *src, size_t size, uint32_t flags, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret = 0; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_2D_TYPE)); + set_2d_desc64_fields_wide(ch, buf->next_desc, dst, src, size, nrows, src_pitch, dst_pitch); + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +#if (XCHAL_IDMA_HAVE_2DPRED > 0) +IDMA_API int32_t +idma_copy_2d_pred_desc64_wide(int32_t ch, void *dst, void *src, size_t size, uint32_t flags, void* pred_mask, uint32_t nrows, uint32_t src_pitch, uint32_t dst_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret = 0; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_2D_COMPRESS_TYPE)); + set_2d_desc64_fields_wide(ch, buf->next_desc, dst, src, size, nrows, src_pitch, dst_pitch); + (cvt_desc_to_desc64(buf->next_desc))->pred_mask = cvt_voidp_to_uint32(pred_mask); + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} +#endif + +IDMA_API int32_t +idma_copy_3d_desc64_wide(int32_t ch, + void *dst, + void *src, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t ntiles, + uint32_t src_row_pitch, + uint32_t dst_row_pitch, + uint32_t src_tile_pitch, + uint32_t dst_tile_pitch) +{ + idma_buf_t* buf; + DECLARE_PS(); + int32_t ret = 0; + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, flags, IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | SET_CONTROL_SUBTYPE(IDMA_64B_3D_TYPE)); + set_3d_desc64_fields_wide(ch, buf->next_desc, dst, src, row_sz, nrows, ntiles, src_row_pitch, dst_row_pitch, src_tile_pitch, dst_tile_pitch); + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} +#endif +#endif //64B + + +IDMA_API idma_status_t +idma_process_tasks(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return idma_process_tasks_i(IDMA_CH_PTR); +} + +IDMA_API idma_error_details_t* +idma_error_details(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return idma_error_details_i(IDMA_CH_PTR); +} + +IDMA_API idma_error_details_t* +idma_buffer_error_details(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return idma_error_details_i(IDMA_CH_PTR); +} + +IDMA_API idma_hw_error_t +idma_buffer_check_errors(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return idma_buffer_check_errors_i(IDMA_CH_PTR); +} + +IDMA_API idma_status_t +idma_abort_tasks(IDMA_CHAN_FUNC_ARG_SINGLE) +{ + return idma_abort_tasks_i(IDMA_CH_PTR); +} + + +IDMA_API int32_t +idma_task_status(idma_buffer_t *taskh) +{ + idma_buf_t* task; + task = convert_buffer_to_buf(taskh); + + XLOG(task->ch, "Task %p status '%s' (%d)\n", task, + (task->status == (int32_t)IDMA_TASK_ERROR) ? "Error" : + (task->status == (int32_t)IDMA_TASK_DONE) ? "Done" : + (task->status > (int32_t)IDMA_TASK_DONE) ? "Pending" : "UNKNOWN" , task->status); + + return (task->status); +} + + +IDMA_API int32_t +idma_schedule_desc_clock(IDMA_CHAN_FUNC_ARG + uint32_t count, + uint32_t *ptime) +{ + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + ret = schedule_desc(IDMA_CH_PTR, count); + *ptime = (uint32_t) clock(); // parasoft-suppress MISRA2012-RULE-21_10-2 "This function is used for profiling only." + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API int32_t +idma_schedule_desc_fast_clock(IDMA_CHAN_FUNC_ARG + uint32_t count, + uint32_t *ptime) +{ + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + ret = schedule_desc_fast(IDMA_CH_PTR, count); + *ptime = (uint32_t) clock(); // parasoft-suppress MISRA2012-RULE-21_10-2 "This function is used for profiling only." + IDMA_ENABLE_INTS(); + return ret; +} + + +#if (XCHAL_IDMA_HAVE_FBC > 0) + +typedef enum { + IDMA_FBC_SF_1_1 = 0, + IDMA_FBC_SF_1_2 = 1, + IDMA_FBC_SF_3_8 = 2, +} idma_fbc_sf_t; + +typedef enum { + IDMA_FBC_CTW_32B = 0, + IDMA_FBC_CTW_64B = 1, + IDMA_FBC_CTW_128B = 2, + IDMA_FBC_CTW_256B = 3, + IDMA_FBC_CTW_512B = 4, +} idma_fbc_ctw_t; + +typedef enum { + IDMA_FBC_CTH_2 = 0, + IDMA_FBC_CTH_4 = 1, + IDMA_FBC_CTH_8 = 2, + IDMA_FBC_CTH_16 = 3, + IDMA_FBC_CTH_32 = 4, +} idma_fbc_cth_t; + + +idma_status_t +idma_copy_fbc_task64_i(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom, + void *cb_data, + idma_callback_fn cb_func); + +idma_status_t +idma_copy_fbc_task64_wide_i(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom, + void *cb_data, + idma_callback_fn cb_func); + + +INTERNAL_FUNC void +set_fbc_desc64_fields(idma_desc_t *desch, + uint32_t baseaddr_lo, + uint32_t baseaddr_hi, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom) +{ + idma_desc64_t *desc = cvt_desc_to_desc64(desch); + + desc->word13 = baseaddr_lo; + desc->word14 = ((uint32_t)(custom >> 4) << 20) | + ((uint32_t)sf << 18) | + ((uint32_t)ctw << 15) | + ((uint32_t)cth << 12) | + ((custom & 0xF) << 8) | + (baseaddr_hi & 0xFF); +} + + +IDMA_API idma_status_t +idma_add_fbc_desc64( idma_buffer_t *bufh, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, + flags, + IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_2D_FBC_TYPE)); + + set_2d_desc64_fields(buf->ch, + buf->next_add_desc, + dst, + src, + row_sz, + nrows, + src_pitch, + dst_pitch); + + set_fbc_desc64_fields(buf->next_add_desc, + cvt_voidp_to_uint32(baseaddr), + 0U, + sf, + ctw, + cth, + custom); + + update_next_add_ptr(buf); + IDMA_ENABLE_INTS(); + + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_fbc_desc64(int32_t ch, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom) +{ + idma_buf_t *buf; + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, + flags, + IDMA_64B_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_64B_2D_FBC_TYPE)); + + set_2d_desc64_fields(ch, + buf->next_desc, + dst, + src, + row_sz, + nrows, + src_pitch, + dst_pitch); + + set_fbc_desc64_fields(buf->next_desc, + cvt_voidp_to_uint32(baseaddr), + 0U, + sf, + ctw, + cth, + custom); + + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API idma_status_t +idma_copy_fbc_task64(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_fbc_task64_i(ch, taskh, dst, src, baseaddr, flags, + row_sz, nrows, src_pitch, dst_pitch, sf, ctw, cth, + custom, cb_data, cb_func); +} + +#if (IDMA_USE_WIDE_API > 0) + +IDMA_API idma_status_t +idma_add_fbc_desc64_wide(idma_buffer_t *bufh, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, + flags, + IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | + SET_CONTROL_SUBTYPE(IDMA_64B_2D_FBC_TYPE)); + + set_2d_desc64_fields_wide(buf->ch, + buf->next_add_desc, + dst, + src, + row_sz, + nrows, + src_pitch, + dst_pitch); + + set_fbc_desc64_fields(buf->next_add_desc, + (cvt_voidp_to_uint32p(baseaddr))[0], + (cvt_voidp_to_uint32p(baseaddr))[1], + sf, + ctw, + cth, + custom); + + update_next_add_ptr(buf); + IDMA_ENABLE_INTS(); + + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_fbc_desc64_wide(int32_t ch, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom) +{ + idma_buf_t* buf; + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc64_ctrl(buf->next_desc, + flags, + IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | + SET_CONTROL_SUBTYPE(IDMA_64B_2D_FBC_TYPE)); + + set_2d_desc64_fields_wide(ch, + buf->next_desc, + dst, + src, + row_sz, + nrows, + src_pitch, + dst_pitch); + + set_fbc_desc64_fields(buf->next_desc, + (cvt_voidp_to_uint32p(baseaddr))[0], + (cvt_voidp_to_uint32p(baseaddr))[1], + sf, + ctw, + cth, + custom); + + ret = schedule_desc(ch, 1U); + } + else { + ret = (int32_t) IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +IDMA_API idma_status_t +idma_copy_fbc_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + void *baseaddr, + uint32_t flags, + size_t row_sz, + uint32_t nrows, + uint32_t src_pitch, + uint32_t dst_pitch, + idma_fbc_sf_t sf, + idma_fbc_ctw_t ctw, + idma_fbc_cth_t cth, + uint16_t custom, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_fbc_task64_wide_i(ch, taskh, dst, src, baseaddr, flags, + row_sz, nrows, src_pitch, dst_pitch, + sf, ctw, cth, custom, cb_data, cb_func); +} + +#endif // IDMA_USE_WIDE_API + +#endif // XCHAL_IDMA_HAVE_FBC + + +#if (XCHAL_IDMA_HAVE_ZVC > 0) + +idma_status_t +idma_copy_zvc_task_i(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func); + +idma_status_t +idma_copy_zvc_task64_wide_i(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func); + +INTERNAL_FUNC void +set_zvc_desc_fields(idma_desc_t *desch, + void *table_addr) +{ + idma_2d_desc_t *desc2d = (idma_2d_desc_t *) desch; + + desc2d->word8 = cvt_voidp_to_uint32(table_addr); +} + +IDMA_API idma_status_t +idma_add_zvc_desc(idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + buf = convert_buffer_to_buf(bufh); + + set_desc_ctrl(buf->next_add_desc, + flags, + IDMA_ZVC_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_ZVC_1D_TYPE)); + set_2d_fields(buf->ch, buf->next_add_desc, dst, src, size, 0, 0, 0); + set_zvc_desc_fields(buf->next_add_desc, table_addr); + + update_next_add_ptr(buf); + IDMA_ENABLE_INTS(); + + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_zvc_desc(int32_t ch, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags) +{ + idma_buf_t* buf; + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc_ctrl(buf->next_desc, + flags, + IDMA_ZVC_DESC_CODE | SET_CONTROL_SUBTYPE(IDMA_ZVC_1D_TYPE)); + set_2d_fields(ch, buf->next_desc, dst, src, size, 0, 0, 0); + set_zvc_desc_fields(buf->next_desc, table_addr); + + ret = schedule_desc(ch, 1U); + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +ALWAYS_INLINE idma_status_t +idma_copy_zvc_task(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_zvc_task_i(ch, taskh, dst, src, size, table_addr, + flags, cb_data, cb_func); +} + + +#if (IDMA_USE_WIDE_API > 0) + +IDMA_API idma_status_t +idma_add_zvc_desc64_wide(idma_buffer_t *bufh, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags) +{ + idma_buf_t *buf; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + buf = convert_buffer_to_buf(bufh); + + set_desc64_ctrl(buf->next_add_desc, + flags, + IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | + SET_CONTROL_SUBTYPE(IDMA_ZVC_1D_TYPE)); + set_2d_desc64_fields_wide(buf->ch, buf->next_add_desc, dst, src, size, 0, 0, 0); + set_zvc_desc_fields(buf->next_add_desc, table_addr); + + update_next_add_ptr(buf); + IDMA_ENABLE_INTS(); + + return IDMA_OK; +} + +IDMA_API int32_t +idma_copy_zvc_desc64_wide(int32_t ch, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags) +{ + idma_buf_t* buf; + int32_t ret; + DECLARE_PS(); + + IDMA_DISABLE_INTS(); + + buf = idma_chan_buf_get(ch); + if (buf != NULL) { + set_desc_ctrl(buf->next_desc, + flags, + IDMA_64B_DESC_CODE | IDMA_64B_LONG_ADDR_CTRL_BIT_MASK | + SET_CONTROL_SUBTYPE(IDMA_ZVC_1D_TYPE)); + set_2d_desc64_fields_wide(ch, buf->next_desc, dst, src, size, 0, 0, 0); + set_zvc_desc_fields(buf->next_desc, table_addr); + + ret = schedule_desc(ch, 1U); + } + else { + ret = IDMA_ERR_NO_BUF; + } + + IDMA_ENABLE_INTS(); + return ret; +} + +ALWAYS_INLINE idma_status_t +idma_copy_zvc_task64_wide(int32_t ch, + idma_buffer_t *taskh, + void *dst, + void *src, + size_t size, + void *table_addr, + uint32_t flags, + void *cb_data, + idma_callback_fn cb_func) +{ + return idma_copy_zvc_task64_wide_i(ch, taskh, dst, src, size, table_addr, + flags, cb_data, cb_func); +} + +#endif // IDMA_USE_WIDE_API + +#endif // XCHAL_IDMA_HAVE_ZVC + + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* __IDMA_H__ */ diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/tie/xt_datacache.h b/src/platform/amd/acp_7_0/include/arch/xtensa/tie/xt_datacache.h new file mode 100755 index 000000000000..0ae25bbda726 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/tie/xt_datacache.h @@ -0,0 +1,131 @@ +// Customer ID=18056; Build=0xa6a6b; Copyright (c) 2017-2019 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. + +/* Definitions for the xt_datacache TIE package */ + +/* Do not modify. This is automatically generated.*/ + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#ifndef _XTENSA_xt_datacache_HEADER +#define _XTENSA_xt_datacache_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#ifndef _ASMLANGUAGE +#ifndef _NOCLANGUAGE +#ifndef __ASSEMBLER__ + +#include <xtensa/tie/xt_core.h> + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_datacache_DHI(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DHI_B(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DHU(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DHWB(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DHWBI(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DHWBI_B(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DHWB_B(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DII(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DIU(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DIWB(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DIWBI(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DIWBUI_P(const int * s /*inout*/); +extern void _TIE_xt_datacache_DPFL(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DPFM_B(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DPFM_BF(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DPFR(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DPFRO(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DPFR_B(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DPFR_BF(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DPFW(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DPFWO(const int * s /*in*/, immediate i /*in*/); +extern void _TIE_xt_datacache_DPFW_B(const int * s /*in*/, int i /*in*/); +extern void _TIE_xt_datacache_DPFW_BF(const int * s /*in*/, int i /*in*/); +extern int _TIE_xt_datacache_LDCT(const int * s /*in*/); +extern int _TIE_xt_datacache_LDCW(const int * s /*in*/); +extern void _TIE_xt_datacache_PFEND_A(void); +extern void _TIE_xt_datacache_PFEND_O(void); +extern void _TIE_xt_datacache_PFNXT_F(void); +extern void _TIE_xt_datacache_PFWAIT_A(void); +extern void _TIE_xt_datacache_PFWAIT_R(void); +extern void _TIE_xt_datacache_SDCT(int t /*in*/, int * s /*in*/); +extern void _TIE_xt_datacache_SDCW(int t /*in*/, int * s /*in*/); + +#endif /*__ASSEMBLER__*/ +#endif /*_NOCLANGUAGE*/ +#endif /*_ASMLANGUAGE*/ + +#define XT_DHI _TIE_xt_datacache_DHI +#define XT_DHI_B _TIE_xt_datacache_DHI_B +#define XT_DHU _TIE_xt_datacache_DHU +#define XT_DHWB _TIE_xt_datacache_DHWB +#define XT_DHWBI _TIE_xt_datacache_DHWBI +#define XT_DHWBI_B _TIE_xt_datacache_DHWBI_B +#define XT_DHWB_B _TIE_xt_datacache_DHWB_B +#define XT_DII _TIE_xt_datacache_DII +#define XT_DIU _TIE_xt_datacache_DIU +#define XT_DIWB _TIE_xt_datacache_DIWB +#define XT_DIWBI _TIE_xt_datacache_DIWBI +#define XT_DIWBUI_P _TIE_xt_datacache_DIWBUI_P +#define XT_DPFL _TIE_xt_datacache_DPFL +#define XT_DPFM_B _TIE_xt_datacache_DPFM_B +#define XT_DPFM_BF _TIE_xt_datacache_DPFM_BF +#define XT_DPFR _TIE_xt_datacache_DPFR +#define XT_DPFRO _TIE_xt_datacache_DPFRO +#define XT_DPFR_B _TIE_xt_datacache_DPFR_B +#define XT_DPFR_BF _TIE_xt_datacache_DPFR_BF +#define XT_DPFW _TIE_xt_datacache_DPFW +#define XT_DPFWO _TIE_xt_datacache_DPFWO +#define XT_DPFW_B _TIE_xt_datacache_DPFW_B +#define XT_DPFW_BF _TIE_xt_datacache_DPFW_BF +#define XT_LDCT _TIE_xt_datacache_LDCT +#define XT_LDCW _TIE_xt_datacache_LDCW +#define XT_PFEND_A _TIE_xt_datacache_PFEND_A +#define XT_PFEND_O _TIE_xt_datacache_PFEND_O +#define XT_PFNXT_F _TIE_xt_datacache_PFNXT_F +#define XT_PFWAIT_A _TIE_xt_datacache_PFWAIT_A +#define XT_PFWAIT_R _TIE_xt_datacache_PFWAIT_R +#define XT_SDCT _TIE_xt_datacache_SDCT +#define XT_SDCW _TIE_xt_datacache_SDCW + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_datacache_HEADER */ + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/tie/xt_externalregisters.h b/src/platform/amd/acp_7_0/include/arch/xtensa/tie/xt_externalregisters.h new file mode 100644 index 000000000000..0fbb7e17e800 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/tie/xt_externalregisters.h @@ -0,0 +1,77 @@ +// Customer ID=18056; Build=0xa6a6b; Copyright (c) 2017-2019 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. + +/* Definitions for the xt_externalregisters TIE package */ + +/* Do not modify. This is automatically generated.*/ + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#ifndef _XTENSA_xt_externalregisters_HEADER +#define _XTENSA_xt_externalregisters_HEADER + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#ifndef _ASMLANGUAGE +#ifndef _NOCLANGUAGE +#ifndef __ASSEMBLER__ + +#include <xtensa/tie/xt_core.h> + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern unsigned _TIE_xt_externalregisters_RER(unsigned ars /*in*/); +extern unsigned _TIE_xt_externalregisters_RSR_ERACCESS(void); +extern void _TIE_xt_externalregisters_WER(unsigned art /*in*/, unsigned ars /*in*/); +extern void _TIE_xt_externalregisters_WSR_ERACCESS(unsigned art /*in*/); +extern void _TIE_xt_externalregisters_XSR_ERACCESS(unsigned art /*inout*/); + +#endif /*__ASSEMBLER__*/ +#endif /*_NOCLANGUAGE*/ +#endif /*_ASMLANGUAGE*/ + +#define XT_RER _TIE_xt_externalregisters_RER +#define XT_RSR_ERACCESS _TIE_xt_externalregisters_RSR_ERACCESS +#define XT_WER _TIE_xt_externalregisters_WER +#define XT_WSR_ERACCESS _TIE_xt_externalregisters_WSR_ERACCESS +#define XT_XSR_ERACCESS _TIE_xt_externalregisters_XSR_ERACCESS + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + +#endif /* !_XTENSA_xt_externalregisters_HEADER */ + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ diff --git a/src/platform/amd/acp_7_0/include/arch/xtensa/xtensa-types.h b/src/platform/amd/acp_7_0/include/arch/xtensa/xtensa-types.h new file mode 100644 index 000000000000..4a0d2cd90404 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/arch/xtensa/xtensa-types.h @@ -0,0 +1,65 @@ +/* + * xtensa-types.h -- General type definitions and macros. + */ + +/* + * Copyright (c) 2002-2018 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. + */ + +#ifndef XTENSA_TYPES_H +#define XTENSA_TYPES_H + +/* parasoft-begin-suppress MISRA2012-RULE-20_7 "Cannot parenthesize macro args here" */ +#if defined (_ASMLANGUAGE) || defined (__ASSEMBLER__) + +/* Redefine stdint.h macros for assembler. */ +/* parasoft-begin-suppress MISRA2012-RULE-21_1_c "It is necessary to redefine these to enable assembly code to compile." */ +#define INT8_C(x) x +#define UINT8_C(x) x +#define INT16_C(x) x +#define UINT16_C(x) x +#define INT32_C(x) x +#define UINT32_C(x) x +#define INT64_C(x) x +#define UINT64_C(x) x +/* parasoft-end-suppress MISRA2012-RULE-21_1_c "It is necessary to redefine these to enable assembly code to compile." */ + +#else + +#include <stdint.h> + +/* Adapt inline spec for older and newer versions of C standard. */ +#if (__STDC_VERSION__ >= 199901L) || defined (__cplusplus) +#define XT_INLINE __attribute__((always_inline)) static inline +#else +#define XT_INLINE __attribute__((always_inline)) static __inline__ +#endif + +/* This macro is used to mark unused function parameters and suppress warnings + from compiler / MISRA checker. + */ +#define UNUSED(x) ((void)(x)) + +#endif +/* parasoft-end-suppress MISRA2012-RULE-20_7 "Cannot parenthesize macro args here" */ + +#endif // XTENSA_TYPES_H diff --git a/src/platform/amd/acp_7_0/include/platform/drivers/interrupt.h b/src/platform/amd/acp_7_0/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..dfc5f7785f69 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/platform/drivers/interrupt.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 AMD.All rights reserved. + * + * Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <rtos/bit.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> + +#define PLATFORM_IRQ_HW_NUM 9 + +#define PLATFORM_IRQ_FIRST_CHILD 5 + +#define PLATFORM_IRQ_CHILDREN 32 + +/* IRQ numbers - wrt Tensilica DSP */ +#define IRQ_NUM_SOFTWARE0 1 /* level 1 */ + +#define IRQ_NUM_TIMER0 0 /* level 1 */ + +#define IRQ_NUM_EXT_LEVEL3 3 /* level 1 */ + +#define IRQ_NUM_TIMER1 6 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL4 4 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL5 5 /* level 3 */ + +/* IRQ Masks */ +#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) + +#define IRQ_MASK_TIMER0 BIT(IRQ_NUM_TIMER0) + +#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) + +#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) + +#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) + +#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) + +#define HOST_TO_DSP_INTR 0x1 + +#define _XTSTR(x) # x + +#define XTSTR(x) _XTSTR(x) + +/* Enabling flag */ +#define INTERRUPT_ENABLE 1 + +/* Clearing flag */ +#define INTERRUPT_CLEAR 0 + +/* Disable flag */ +#define INTERRUPT_DISABLE 0 + +/* brief Tensilica Interrupt Levels. */ +typedef enum { + acp_interrupt_level_3 = 0, + + acp_interrupt_level_4, + + acp_interrupt_level_5, + + acp_interrupt_level_nmi, + + acp_interrupt_level_max +} artos_interrupt_levels_t; + +/* brief Tensilica timer control */ +typedef enum { + acp_timer_cntl_disable = 0, + + acp_timer_cntl_oneshot, + + acp_timer_cntl_periodic, + + acp_timer_cntl_max +} artos_timer_control_t; + +/* Disable Host to DSP interrupt */ +void acp_dsp_sw_intr_disable(void); + +void acp_intr_route(void); + +void acp_dsp_to_host_intr_trig(void); + +void acp_ack_intr_from_host(void); + +void acp_dsp_sw_intr_enable(void); + +void acp_intr_enable(void); + +void acp_intr_disable(void); + +#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/amd/acp_7_0/include/platform/fw_scratch_mem.h b/src/platform/amd/acp_7_0/include/platform/fw_scratch_mem.h new file mode 100644 index 000000000000..1a9726fc413e --- /dev/null +++ b/src/platform/amd/acp_7_0/include/platform/fw_scratch_mem.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 AMD. All rights reserved. + * + * Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifndef __EXT_SCRATCH_MEM_H__ +#define __EXT_SCRATCH_MEM_H__ + +#include <sof/lib/mailbox.h> + +/* MAX number of DMA descriptors */ +#define MAX_NUM_DMA_DESC_DSCR 64 +#define SCRATCH_REG_OFFSET 0x1250000 +#define ACP_SRAM 0x03800000 +typedef struct acp_atu_grp_pte { + uint32_t low_part; + uint32_t high_part; +} __attribute__((packed, aligned(4))) acp_atu_grp_pte_t; + +typedef union acp_cfg_dma_trns_cnt { + struct{ + uint32_t trns_cnt : 19; + uint32_t reserved : 12; + uint32_t ioc : 1; + } bits; + unsigned int u32all; +} __attribute__((packed, aligned(4))) acp_cfg_dma_trns_cnt_t; + +typedef struct acp_config_dma_descriptor { + uint32_t src_addr; + uint32_t dest_addr; + acp_cfg_dma_trns_cnt_t trns_cnt; + uint32_t reserved; +} __attribute__((packed, aligned(4))) acp_cfg_dma_descriptor_t; + +typedef struct acp_config_dma_misc { + uint32_t channelstatus; + uint32_t channel; + uint32_t flag; +} __attribute__((packed, aligned(4))) acp_cfg_dma_misc_t; + +typedef struct acp_scratch_memory_config { + /* ACP out box buffer */ + uint8_t acp_outbox_buffer[MAILBOX_DSPBOX_SIZE]; + + /* ACP in box buffer */ + uint8_t acp_inbox_buffer[MAILBOX_HOSTBOX_SIZE]; + + /* ACP debug box buffer */ + uint8_t acp_debug_buffer[MAILBOX_DEBUG_SIZE]; + + /* ACP exception box buffer */ + uint8_t acp_except_buffer[MAILBOX_EXCEPTION_SIZE]; + + /* ACP stream buffer */ + uint8_t acp_stream_buffer[MAILBOX_STREAM_SIZE]; + + /* ACP trace buffer */ + uint8_t acp_trace_buffer[MAILBOX_TRACE_SIZE]; + + /* Host msg write flag */ + uint32_t acp_host_msg_write; + + /* Host ack flag */ + uint32_t acp_host_ack_write; + + /* Dsp msg write flag */ + uint32_t acp_dsp_msg_write; + + /* Dsp ack flag */ + uint32_t acp_dsp_ack_write; + + /* ACP pte1 table */ + acp_atu_grp_pte_t acp_atugrp1_pte[16]; + + /* ACP pte2 table */ + acp_atu_grp_pte_t acp_atugrp2_pte[16]; + + /* ACP pte3 table */ + acp_atu_grp_pte_t acp_atugrp3_pte[16]; + + /* ACP pte4 table */ + acp_atu_grp_pte_t acp_atugrp4_pte[16]; + + /* ACP pte5 table */ + acp_atu_grp_pte_t acp_atugrp5_pte[16]; + + /* ACP pte6 table */ + acp_atu_grp_pte_t acp_atugrp6_pte[16]; + + /* ACP pte7 table */ + acp_atu_grp_pte_t acp_atugrp7_pte[16]; + + /* ACP pte8 table */ + acp_atu_grp_pte_t acp_atugrp8_pte[16]; + + /* ACP DMA Descriptor */ + acp_cfg_dma_descriptor_t acp_cfg_dma_descriptor[MAX_NUM_DMA_DESC_DSCR]; + + /* Stream physical offset */ + uint32_t phy_offset[8]; + + /* Stream system memory size */ + uint32_t syst_buff_size[8]; + + /* Fifo buffers are not part of scratch memory on ACP_7_0 */ + /* Added fifo members to align with Driver structure */ + /* ACP transmit fifo buffer */ + uint8_t acp_transmit_fifo_buffer[256] __attribute__((aligned(128))); + + /* ACP receive fifo buffer */ + uint8_t acp_receive_fifo_buffer[256] __attribute__((aligned(128))); + + uint32_t reserve[]; +} __attribute__((packed, aligned(4))) acp_scratch_mem_config_t; + +#endif /* __EXT_SCRATCH_MEM_H__ */ + diff --git a/src/platform/amd/acp_7_0/include/platform/lib/memory.h b/src/platform/amd/acp_7_0/include/platform/lib/memory.h new file mode 100644 index 000000000000..de506811721d --- /dev/null +++ b/src/platform/amd/acp_7_0/include/platform/lib/memory.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024, 2026 AMD.All rights reserved. + * + * Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + * Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Sivasubramanian <sravisar@amd.com> + */ +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + +#define PU_REGISTER_BASE (0x9FD00000 - 0x01240000) +#define PU_SCRATCH_REG_BASE (0x9FF00000 - 0x01250000) + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN 128 + +/* physical DSP addresses */ +#define IRAM_BASE 0x7F000000 +#define IRAM_SIZE 0x60000 + +#define DRAM0_BASE 0xE0000000 +#define DRAM0_SIZE 0x10000 +#define SRAM0_BASE 0x9FF00000 + +#define DRAM1_BASE 0xE0010000 +#define DRAM1_SIZE 0x10000 +#define SRAM1_BASE 0x6000C000 +#define SRAM1_SIZE 0x274000 + +#define DMA0_BASE PU_REGISTER_BASE +#define DMA0_SIZE 0x4 + +/* DAI DMA register base address */ +#define DAI_BASE (PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR) +#define DAI_BASE_REM (PU_REGISTER_BASE + ACP_P1_I2S_RX_RINGBUFADDR) +#define DAI_SIZE 0x4 + +#define SW1_AUDIO_TX_FIFO_OFFST (ACP_P1_AUDIO_TX_FIFOADDR - ACP_P1_AUDIO_RX_RINGBUFADDR) +#define SW1_AUDIO_RX_FIFO_OFFST (ACP_P1_AUDIO_RX_FIFOADDR - ACP_P1_AUDIO_RX_RINGBUFADDR) + +#define BT_TX_FIFO_OFFST (ACP_P1_BT_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define BT_RX_FIFO_OFFST (ACP_P1_BT_RX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) + +#define SW1_HS_TX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_HS_RX_RINGBUFADDR) +#define SW1_HS_RX_FIFO_OFFST (ACP_P1_HS_RX_FIFOADDR - ACP_P1_HS_RX_RINGBUFADDR) + +#define HS_TX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define HS_RX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) + +#define SW0_AUDIO_TX_FIFO_OFFST (ACP_AUDIO_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) +#define SW0_AUDIO_RX_FIFO_OFFST (ACP_AUDIO_RX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) + +#define BT0_TX_FIFO_OFFST (ACP_BT_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) +#define BT0_RX_FIFO_OFFST (ACP_BT_RX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) + +#define HS0_TX_FIFO_OFFST (ACP_HS_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) +#define HS0_RX_FIFO_OFFST (ACP_HS_TX_FIFOADDR - ACP_AUDIO_RX_RINGBUFADDR) + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +/* Log buffer base need to be updated properly, these are used in linker scripts */ +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* Stack configuration */ +#define SOF_STACK_SIZE (0x1000) +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE +#define SOF_STACK_END (DRAM1_BASE + DRAM1_SIZE - SOF_STACK_SIZE) +#define SOF_STACK_BASE (SOF_STACK_END + SOF_STACK_SIZE) + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE SRAM0_BASE +#define SRAM_OUTBOX_SIZE 0x400 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x400 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x400 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x400 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x400 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x400 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 192 +#define HEAP_RT_COUNT32 192 +#define HEAP_RT_COUNT64 128 +#define HEAP_RT_COUNT128 240 +#define HEAP_RT_COUNT256 128 +#define HEAP_RT_COUNT512 16 +#define HEAP_RT_COUNT1024 73 +#define HEAP_RT_COUNT2048 48 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 720 +#define HEAP_SYS_RT_COUNT512 240 +#define HEAP_SYS_RT_COUNT1024 91 + +#define SIZE_OF_MEMORY_FOR_DATA_SECTION 0x60000 + +/* Heap configuration */ +#define HEAP_SYSTEM_BASE (SRAM1_BASE + SIZE_OF_MEMORY_FOR_DATA_SECTION) +#define HEAP_SYSTEM_SIZE 0x40000 +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +#define HEAP_SYS_RUNTIME_SIZE (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE (0x60000) +#define HEAP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x7 +#define SOF_MEM_VECT_TEXT_SIZE 0x37 +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x400 +#define SOF_MEM_RESET_LIT_SIZE 0x8 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 +#define SOF_MEM_WIN_TEXT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define is_uncached(address) 0 + +#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN + +/* brief EDF task's default stack size in bytes */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +struct sof; + +#define SHARED_DATA +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} +#endif +#define host_to_local(addr) addr +#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/amd/acp_7_0/include/platform/platform.h b/src/platform/amd/acp_7_0/include/platform/platform.h new file mode 100644 index 000000000000..5c2e7db0549e --- /dev/null +++ b/src/platform/amd/acp_7_0/include/platform/platform.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024, 2026 AMD.All rights reserved. + * + * Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + * Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Sivasubramanian <sravisar@amd.com> + */ +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <rtos/interrupt.h> +#include <rtos/clk.h> +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/platform_misc.h> + +#define INTERRUPT_ENABLE 1 +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LEVEL_3 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 65536 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE (16384 + 8192) //8192 + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500 //1000 //50000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +/* default dma trace channel */ +#define DMA_TRACE_CHANNEL 7 + +/* debug offset */ +#define ACP_SOF_FW_STATUS 0 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + acp_sw_intr_trig_t sw_intr_trig; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + + pscratch_mem_cfg->acp_dsp_msg_write = p; + mailbox_sw_reg_write(ACP_SOF_FW_STATUS, p); + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt trigger register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* + * brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/amd/acp_7_0/include/platform/platform_misc.h b/src/platform/amd/acp_7_0/include/platform/platform_misc.h new file mode 100644 index 000000000000..2338a91317e0 --- /dev/null +++ b/src/platform/amd/acp_7_0/include/platform/platform_misc.h @@ -0,0 +1,445 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 AMD. All rights reserved. + * + * + */ + +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#define ACP_SW_INTR_TRIG 0x1241810 +#define ACP_DSP0_INTR_CNTL 0x1241800 +#define ACP_DSP0_INTR_STAT 0x1241804 +#define ACP_DSP_SW_INTR_CNTL 0x1241808 +#define ACP_DSP_SW_INTR_STAT 0x124180C +#define ACP_AXI2DAGB_SEM_0 0x1241874 +#define ACP_SRBM_CLIENT_BASE_ADDR 0x12419EC +#define ACP_SRBM_CLIENT_RDDATA 0x12419F0 +#define ACP_SRBM_CYCLE_STS 0x12419F4 +#define ACP_SRBM_CLIENT_CONFIG 0x12419F8 +#define MP1_SMN_C2PMSG_69 0x58A14 +#define MP1_SMN_C2PMSG_85 0x58A54 +#define MP1_SMN_C2PMSG_93 0x58A74 +#define CLK7_ROOTREFCLK_MUX_1 0x6C0C8 +#define CLK7_CLK_PLL_REFCLK_RATE_STARTUP 0x6C0D0 +#define CLK7_CLK_PLL_REQ 0x6C0DC +#define CLK7_CLK1_DFS_CNTL 0x6C1B0 +#define CLK7_CLK1_CURRENT_CNT 0x6C378 +#define CLK7_CLK0_DFS_CNTL 0x6C1A4 +#define CLK7_CLK0_CURRENT_CNT 0x6C374 +#define CLK7_CLK0_BYPASS_CNTL 0x6C210 +#define CLK7_CLK1_BYPASS_CNTL 0x6C234 +#define CLK7_CLK0_DFS_STATUS 0x6C1AC +#define CLK7_CLK1_DFS_STATUS 0x6C1B8 +#define CLK7_SPLL_FIELD_2 0x6C114 +#define CLK7_CLK2_CURRENT_CNT 0x6C37C +#define CLK7_CLK2_BYPASS_CNTL 0x6C258 +#define CLK7_CLK2_DFS_STATUS 0x6C1C4 +#define CLK7_CLK_PLL_PWR_REQ 0x6C2F0 +#define CLK7_CLK_DFSBYPASS_CONTROL 0x6C2F8 +#define CLK7_CLK_FSM_STATUS 0x6C304 +#define CLK7_SPLL_FUSE_1 0x6C0F8 +#define CLK7_SPLL_FUSE_2 0x6C0FC +#define CLK7_SPLL_FIELD_7 0x6C128 +#define CLK7_SPLL_FIELD_9 0x6C130 +#define CLK7_SPLL_FIELD_6nm 0x6C138 +#define CLK7_SPLL_FIELD_4 0x6C11C +#define CLK7_SPLL_FIELD_5nm_BUS_CTRL 0x6C140 +#define CLK7_SPLL_FIELD_5nm_BUS_WDATA 0x6C144 +#define CLK7_SPLL_FIELD_5nm_BUS_STATUS 0x6C148 +#define CLK7_CLK_PLL_RESET_STOP_TIMER 0x6C180 + +typedef union acp_srbm_cycle_sts { + struct { + unsigned int srbm_clients_sts :1; + unsigned int :7; + } bits; + unsigned int u32all; +} acp_srbm_cycle_sts_t; + +typedef union acp_clkmux_sel { + struct { + unsigned int acp_clkmux_sel : 3; + unsigned int : 13; + unsigned int acp_clkmux_div_value : 16; + } bits; + unsigned int u32all; +} acp_clkmux_sel_t; + +typedef union clk7_clk1_dfs_cntl_u { + struct { + unsigned int CLK1_DIVIDER : 7; + unsigned int : 25; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk1_dfs_cntl_u_t; + +typedef union clk7_clk1_dfs_status_u { + struct { + unsigned int : 16; + unsigned int CLK1_DFS_DIV_REQ_IDLE : 1; + unsigned int : 2; + unsigned int RO_CLK1_DFS_STATE_IDLE : 1; + unsigned int CLK1_CURRENT_DFS_DID : 7; + unsigned int : 5; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk1_dfs_status_u_t; + +typedef union clk7_clk1_bypass_cntl_u { + struct { + unsigned int CLK1_BYPASS_SEL : 3; + unsigned int : 13; + unsigned int CLK1_BYPASS_DIV : 4; + unsigned int : 12; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk1_bypass_cntl_u_t; + +typedef union clk7_clk_fsm_status_u { + struct { + unsigned int AUTOLAUCH_FSM_FULL_SPEED_IDLE : 1; + unsigned int : 3; + unsigned int AUTOLAUCH_FSM_BYPASS_IDLE : 1; + unsigned int : 3; + unsigned int RO_FSM_PLL_STATUS_STARTED : 1; + unsigned int : 3; + unsigned int RO_FSM_PLL_STATUS_STOPPED : 1; + unsigned int : 3; + unsigned int RO_EARLY_FSM_DONE : 1; + unsigned int : 3; + unsigned int RO_DFS_GAP_ACTIVE : 1; + unsigned int : 3; + unsigned int RO_DID_FSM_IDLE : 1; + unsigned int : 7; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk_fsm_status_t; + +typedef union clk7_clk_pll_req_u { + struct { + unsigned int fbmult_int : 9; + unsigned int : 3; + unsigned int pllspinediv : 4; + unsigned int fbmult_frac : 16; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk_pll_req_u_t; + +typedef union clk7_clk_pll_refclk_startup { + struct { + unsigned int main_pll_ref_clk_rate_startup : 8; + unsigned int main_pll_cfg_4_startup : 8; + unsigned int main_pll_ref_clk_div_startup : 2; + unsigned int main_pll_cfg_3_startup : 10; + unsigned int : 1; + unsigned int main_pll_refclk_src_mux0_startup : 1; + unsigned int main_pll_refclk_src_mux1_startup : 1; + unsigned int : 1; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk_pll_refclk_startup_t; + +typedef union clk7_spll_field_2 { + struct{ + unsigned int : 3; + unsigned int spll_fbdiv_mask_en : 1; + unsigned int spll_fracn_en : 1; + unsigned int spll_freq_jump_en : 1; + unsigned int : 25; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_2_t; + +typedef union clk7_clk_dfsbypass_cntl { + struct { + unsigned int enter_dfs_bypass_0 : 1; + unsigned int enter_dfs_bypass_1 : 1; + unsigned int : 14; + unsigned int exit_dfs_bypass_0 : 1; + unsigned int exit_dfs_bypass_1 : 1; + unsigned int : 14; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk_dfsbypass_cntl_t; + +typedef union clk7_clk_pll_pwr_req { + struct { + unsigned int PLL_AUTO_START_REQ : 1; + unsigned int : 3; + unsigned int PLL_AUTO_STOP_REQ : 1; + unsigned int : 3; + unsigned int PLL_AUTO_STOP_NOCLK_REQ : 1; + unsigned int : 3; + unsigned int PLL_AUTO_STOP_REFBYPCLK_REQ : 1; + unsigned int : 3; + unsigned int PLL_FORCE_RESET_HIGH : 1; + unsigned int : 15; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_clk_pll_pwr_req_t; + +typedef union clk7_spll_fuse_1 { + struct { + unsigned int : 8; + unsigned int spll_gp_coarse_exp : 4; + unsigned int spll_gp_coarse_mant : 4; + unsigned int : 4; + unsigned int spll_gi_coarse_exp : 4; + unsigned int : 1; + unsigned int spll_gi_coarse_mant : 2; + unsigned int : 5; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_fuse_1_t; + +typedef union clk7_spll_fuse_2 { + struct { + unsigned int spll_tdc_resolution : 8; + unsigned int spll_freq_offset_exp : 4; + unsigned int spll_freq_offset_mant : 5; + unsigned int : 15; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_fuse_2_t; + +typedef union clk7_spll_field_9 { + struct { + unsigned int : 16; + unsigned int spll_dpll_cfg_3 : 10; + unsigned int spll_fll_mode : 1; + unsigned int : 5; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_9_t; + +typedef union clk7_spll_field_6nm { + struct { + unsigned int spll_dpll_cfg_4 : 8; + unsigned int spll_reg_tim_exp : 3; + unsigned int spll_reg_tim_mant : 1; + unsigned int spll_ref_tim_exp : 3; + unsigned int spll_ref_tim_mant : 1; + unsigned int spll_vco_pre_div : 2; + unsigned int : 14; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_6nm_t; + +typedef union clk7_spll_field_7 { + struct { + unsigned int : 7; + unsigned int spll_pllout_sel : 1; + unsigned int spll_pllout_req : 1; + unsigned int spll_pllout_state : 2; + unsigned int spll_postdiv_ovrd : 4; + unsigned int spll_postdiv_pllout_ovrd : 4; + unsigned int spll_postdiv_sync_enable : 1; + unsigned int : 1; + unsigned int spll_pwr_state : 2; + unsigned int : 1; + unsigned int spll_refclk_rate : 8; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_7_t; + +typedef union clk7_spll_field_4 { + struct { + unsigned int spll_fcw0_frac_ovrd : 16; + unsigned int pll_out_sel : 1; + unsigned int : 3; + unsigned int pll_pwr_dn_state : 2; + unsigned int : 2; + unsigned int spll_refclk_div : 2; + unsigned int : 6; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_4_t; + +typedef union clk7_spll_field_5nm_bus_ctrl { + struct { + unsigned int bus_spll_async_mode :1; + unsigned int bus_spll_apb_mode :1; + unsigned int bus_spll_addr :8; + unsigned int bus_spll_byte_en :4; + unsigned int bus_spll_rdtr :1; + unsigned int bus_spll_resetb :1; + unsigned int bus_spll_sel :1; + unsigned int bus_spll_wrtr :1; + unsigned int :14; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_5nm_bus_ctrl_t; + +typedef union clk7_spll_field_5nm_bus_wdata { + struct { + unsigned int bus_spll_wr_data; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_5nm_bus_wdata_t; + +typedef union clk7_rootrefclk_mux_1 { + struct { + unsigned int ROOTREFCLK_MUX_1 : 1; + unsigned int reserved : 31; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_rootrefclk_mux_1_t; + +typedef union clk7_spll_field_5nm_bus_status { + struct { + unsigned int spll_bus_error :1; + unsigned int spll_bus_rd_valid :1; + unsigned int spll_bus_wr_ack :1; + unsigned int :29; + } bitfields, bits; + uint32_t u32all; + int32_t i32all; + float f32all; +} clk7_spll_field_5nm_bus_status_t; + +typedef union acp_dsp0_sdw_intr_cntl { + struct { + unsigned int soundwire_mask :17; + unsigned int :15; + } bits; + unsigned int u32all; +} acp_dsp0_sdw_intr_cntl_t; + +typedef union acp_dsp_sw_intr_stat { + struct { + unsigned int host_to_dsp0_intr1_stat:1; + unsigned int host_to_dsp0_intr2_stat:1; + unsigned int dsp0_to_host_intr_stat:1; + unsigned int host_to_dsp0_intr3_stat:1; + unsigned int :28; + } bits; + unsigned int u32all; +} acp_dsp_sw_intr_stat_t; + +typedef union acp_sw_intr_trig { + struct { + unsigned int trig_host_to_dsp0_intr1:1; + unsigned int :1; + unsigned int trig_dsp0_to_host_intr:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_sw_intr_trig_t; + +typedef void (*dma_callback_t)(const struct device *dev, void *user_data, + uint32_t channel, int status); + +#define ACP_DMA_CHAN_COUNT 12 +struct acp_dma_ptr_data { + /* base address of dma buffer */ + uint32_t base; + /* size of dma buffer */ + uint32_t size; + /* write pointer of dma buffer */ + uint32_t wr_ptr; + /* read pointer of dma buffer */ + uint32_t rd_ptr; + /* read size of dma buffer */ + uint32_t rd_size; + /* write size of dma buffer */ + uint32_t wr_size; + /* system memory size defined for the stream */ + uint32_t sys_buff_size; + /* virtual system memory offset for system memory buffer */ + uint32_t phy_off; + /* probe_channel id */ + uint32_t probe_channel; +}; + +enum acp_dma_state { + ACP_DMA_READY, + ACP_DMA_PREPARED, + ACP_DMA_SUSPENDED, + ACP_DMA_ACTIVE, +}; + +struct acp_dma_chan_data { + uint32_t direction; + enum acp_dma_state state; + struct acp_dma_ptr_data ptr_data; /* pointer data */ + dma_callback_t dma_tfrcallback; + void *priv_data;//unused +}; + +struct dma_context1 { + /** magic code to identify the context */ + int32_t magic; + /** number of dma channels */ + int dma_channels; + /** atomic holding bit flags for each channel to mark as used/unused */ + atomic_t *atomic; +}; + +struct sdw_pin_data { + uint32_t pin_num; + uint32_t pin_dir; + uint32_t dma_channel; + uint32_t index; + uint32_t instance; +}; + +struct tdm_context { + uint32_t tdm_instance; + uint32_t pin_dir; + uint32_t dma_channel; + uint32_t index; +}; + +struct dmic_context { + uint32_t dmic_instance; + uint32_t pin_dir; + uint32_t dma_channel; + uint32_t index; +}; + +struct acp_dma_dev_data { + struct dma_context1 dma_ctx; + struct acp_dma_chan_data chan_data[ACP_DMA_CHAN_COUNT]; + + ATOMIC_DEFINE(atomic, ACP_DMA_CHAN_COUNT); + struct dma_config *dma_config; + void *dai_index_ptr; +}; diff --git a/src/platform/haswell/lib/CMakeLists.txt b/src/platform/amd/acp_7_0/lib/CMakeLists.txt similarity index 100% rename from src/platform/haswell/lib/CMakeLists.txt rename to src/platform/amd/acp_7_0/lib/CMakeLists.txt diff --git a/src/platform/amd/acp_7_0/lib/clk.c b/src/platform/amd/acp_7_0/lib/clk.c new file mode 100644 index 000000000000..da2b069682d0 --- /dev/null +++ b/src/platform/amd/acp_7_0/lib/clk.c @@ -0,0 +1,485 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024, 2026 AMD.All rights reserved. +// +// Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Sivasubramanian <sravisar@amd.com> +// + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <rtos/sof.h> +#include <rtos/atomic.h> +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/lib/io.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/notifier.h> +#include <sof/platform.h> +#include <sof/schedule/schedule.h> +#include <rtos/spinlock.h> +#include <sof/math/numbers.h> +#include <sof/trace/trace.h> +#include <ipc/topology.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> + +LOG_MODULE_REGISTER(acp_clk, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(acp_clk); +DECLARE_TR_CTX(acp_clk_tr, SOF_UUID(acp_clk_uuid), LOG_LEVEL_INFO); + +const struct freq_table platform_cpu_freq[] = { + {600000000, 600000 }, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +void audio_pll_power_off(void); +void audio_pll_power_on(void); +void clk_dfs_bypassexit(void); +void audio_pll_mode_switch(uint32_t mode, uint32_t fcw_int, uint32_t fcw_frac, uint32_t fcw_denom, + uint32_t pllspinediv); +void clk7_init_vco(void); +void acp_7_0_reg_wait(void); +void acp_7_0_get_boot_ref_clock(float *boot_ref_clk); + +typedef enum { + PLL_MODE_100MHZ_NORMAL, + PLL_MODE_48MHZ_NORMAL, + PLL_MODE_32KHZ_LPPM, + PLL_MODE_48MHZ_LPPM, + PLL_MODE_100MHZ_LPPM +} PLL_MODE; + +/* Enumeration for the Clock Types */ +typedef enum _acp_clock_type_ { + acp_aclk_clock, + acp_sclk_clock, + acp_clock_type_max, + acp_clock_type_force = 0xFF +} acp_clock_type_t; + +static int acp_reg_read_via_smn(uint32_t reg_offset, + uint32_t size) +{ + uint32_t reg_value; + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + reg_value = (uint32_t)io_reg_read(PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + ACP_FIRST_REG_OFFSET)); + if (reg_value) + reg_value = 0; + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + while (delay_cnt > 0) { + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CLIENT_RDDATA); + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + delay_cnt--; + } + return -1; +} + +static void acp_reg_write_via_smn(uint32_t reg_offset, + uint32_t value, uint32_t size) +{ + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + io_reg_write((PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + + ACP_FIRST_REG_OFFSET)), + value); + acp_srbm_cycle_sts = + (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CYCLE_STS); + while (delay_cnt > 0) { + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return; + delay_cnt--; + } +} + +void acp_7_0_reg_wait(void) +{ + int test_count; + + for (test_count = 0; test_count < 255; test_count++) { + (void)acp_reg_read_via_smn(CLK7_CLK_FSM_STATUS, sizeof(int)); + } +} + +void acp_7_0_get_boot_ref_clock(float *boot_ref_clk) +{ + clk7_clk_pll_refclk_startup_t boot_ref_clk_startup; + clk7_clk_pll_req_u_t clk7_clk_pll_req; + clk7_spll_field_2_t clk7_spll_field; + uint32_t spinediv = 1; + float fract_part = 0.0f; + float final_refclk; + + boot_ref_clk_startup.u32all = + acp_reg_read_via_smn(CLK7_CLK_PLL_REFCLK_RATE_STARTUP, sizeof(int)); + + clk7_spll_field_9_t clk_spll_field_9; + + clk_spll_field_9.u32all = 0x0; + clk_spll_field_9.u32all = acp_reg_read_via_smn(CLK7_SPLL_FIELD_9, sizeof(int)); + + if (clk_spll_field_9.bitfields.spll_dpll_cfg_3 == 0x2) + final_refclk = ((32768.0f * 128.0f) / 1000000.0f); + else + final_refclk = (float)boot_ref_clk_startup.bitfields.main_pll_ref_clk_rate_startup; + + clk7_clk_pll_req.u32all = acp_reg_read_via_smn(CLK7_CLK_PLL_REQ, sizeof(int)); + clk7_spll_field.u32all = acp_reg_read_via_smn(CLK7_SPLL_FIELD_2, sizeof(int)); + + spinediv = (1 << clk7_clk_pll_req.bitfields.pllspinediv); + + if (clk7_spll_field.bitfields.spll_fracn_en == 1) + fract_part = (float)(clk7_clk_pll_req.bitfields.fbmult_frac / (float)65536.0f); + + *boot_ref_clk = (float)(((final_refclk) * (clk7_clk_pll_req.bitfields.fbmult_int + + fract_part)) / (float)spinediv); +} + +void acp_change_clock_notify(uint32_t clock_freq) +{ + volatile clk7_clk1_dfs_cntl_u_t dfs_cntl; + volatile clk7_clk1_bypass_cntl_u_t bypass_cntl; + volatile clk7_clk1_dfs_status_u_t dfs_status; + volatile uint32_t updated_clk = 0; + float did, fraction_val, boot_ref_clk; + acp_clock_type_t clock_type = acp_aclk_clock; + + acp_7_0_get_boot_ref_clock(&boot_ref_clk); + + tr_info(&acp_clk_tr, "clock_freq : %d clock_type : %d", + clock_freq, clock_type); + + fraction_val = (float)(clock_freq / 1000000.0f); + clock_freq /= 1000000; + if (acp_aclk_clock == clock_type) { + bypass_cntl.u32all = acp_reg_read_via_smn(CLK7_CLK1_BYPASS_CNTL, sizeof(int)); + dfs_cntl.u32all = acp_reg_read_via_smn(CLK7_CLK1_DFS_CNTL, sizeof(int)); + } else if (acp_sclk_clock == clock_type) { + bypass_cntl.u32all = acp_reg_read_via_smn(CLK7_CLK0_BYPASS_CNTL, sizeof(int)); + dfs_cntl.u32all = acp_reg_read_via_smn(CLK7_CLK0_DFS_CNTL, sizeof(int)); + } + + bypass_cntl.bitfields.CLK1_BYPASS_DIV = 0; + + if (clock_freq == 6 || clock_freq == 0) { + did = 128; + dfs_cntl.bitfields.CLK1_DIVIDER = 0x7F; + bypass_cntl.bitfields.CLK1_BYPASS_DIV = 0xF; + } else { + did = boot_ref_clk / fraction_val; + tr_info(&acp_clk_tr, "CLK Divider : %d boot_ref_clk : %d\n", + (uint32_t)(did * 100), (uint32_t)boot_ref_clk); + + if (did > 62.0f) { + dfs_cntl.bitfields.CLK1_DIVIDER = 0x7F; + } else { + fraction_val = did - (uint8_t)(did); + did = did - fraction_val; + if (did <= 16.00f) + did = (did * 4.0f); + else if ((did > 16.0f) && (did <= 32.0f)) + did = ((did - 16.0f) * 2.0f + 64.0f); + else if ((did > 32.0f) && (did <= 62.0f)) + did = ((did - 32.0f) + 96.0f); + + if (fraction_val == 0.0f) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did); + else if (fraction_val <= 0.25f) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 1; + else if ((fraction_val > 0.25f) && (fraction_val <= 0.5f)) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 2; + else if ((fraction_val > 0.5f) && (fraction_val <= 0.75f)) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 3; + else if ((fraction_val > 0.75f)) + dfs_cntl.bitfields.CLK1_DIVIDER = (uint8_t)(did) + 4; + } + } + + if (acp_aclk_clock == clock_type) { + acp_reg_write_via_smn(CLK7_CLK1_BYPASS_CNTL, bypass_cntl.u32all, sizeof(int)); + tr_info(&acp_clk_tr, "check CLK7_CLK0_DFS_CNTL : not entered the condition"); + acp_reg_write_via_smn(CLK7_CLK1_DFS_CNTL, dfs_cntl.u32all, sizeof(int)); + dfs_status.u32all = acp_reg_read_via_smn(CLK7_CLK1_DFS_STATUS, sizeof(int)); + acp_7_0_reg_wait(); + + do { + dfs_status.u32all = acp_reg_read_via_smn(CLK7_CLK1_DFS_STATUS, sizeof(int)); + tr_info(&acp_clk_tr, "ACLK1 CLK1_DIVIDER : %d dfsstatus %d ", + dfs_cntl.u32all, dfs_status.u32all); + } while (dfs_status.bitfields.CLK1_DFS_DIV_REQ_IDLE == 0); + updated_clk = acp_reg_read_via_smn(CLK7_CLK1_CURRENT_CNT, sizeof(int)); + acp_7_0_reg_wait(); + + if (updated_clk < (clock_freq * 10)) { + dfs_cntl.bitfields.CLK1_DIVIDER -= 1; + dfs_status.u32all = 0; + acp_reg_write_via_smn(CLK7_CLK1_DFS_CNTL, dfs_cntl.u32all, sizeof(int)); + do { + dfs_status.u32all = + acp_reg_read_via_smn(CLK7_CLK1_DFS_STATUS, + sizeof(int)); + dfs_cntl.u32all = + acp_reg_read_via_smn(CLK7_CLK1_DFS_CNTL, + sizeof(int)); + tr_info(&acp_clk_tr, "ACLK2 CLK1_DIVIDER:%d dfsstatus %d ", + dfs_cntl.u32all, dfs_status.u32all); + } while (dfs_status.bitfields.CLK1_DFS_DIV_REQ_IDLE == 0); + } + updated_clk = acp_reg_read_via_smn(CLK7_CLK1_CURRENT_CNT, sizeof(int)); + } else if (acp_sclk_clock == clock_type) { + acp_reg_write_via_smn(CLK7_CLK0_BYPASS_CNTL, bypass_cntl.u32all, sizeof(int)); + tr_info(&acp_clk_tr, "check CLK7_CLK0_DFS_CNTL : %d",dfs_cntl.u32all); + acp_reg_write_via_smn(CLK7_CLK0_DFS_CNTL, dfs_cntl.u32all, sizeof(int)); + dfs_status.u32all = acp_reg_read_via_smn(CLK7_CLK0_DFS_STATUS, sizeof(int)); + acp_7_0_reg_wait(); + + do { + dfs_status.u32all = acp_reg_read_via_smn(CLK7_CLK0_DFS_STATUS, sizeof(int)); + tr_info(&acp_clk_tr, "SCLK CLK1_DIVIDER: %d", + dfs_cntl.u32all); + } while (dfs_status.bitfields.CLK1_DFS_DIV_REQ_IDLE == 0); + + updated_clk = acp_reg_read_via_smn(CLK7_CLK0_CURRENT_CNT, sizeof(int)); + } + tr_info(&acp_clk_tr, + "clock_notify:CLK1_DIVIDER :%x boot_ref_clk : %d ClkReq : %d FinalClockValue: %d", + dfs_cntl.u32all, (uint32_t)boot_ref_clk, + clock_freq, updated_clk); +} + +void audio_pll_power_off(void) +{ + volatile clk7_clk_pll_pwr_req_t clk7_clk_pll_pwr_req; + volatile clk7_clk_fsm_status_t clk7_clk_fsm_status; + int count; + + for (count = 0; count < 10; count++) { + clk7_clk_pll_pwr_req.u32all = + acp_reg_read_via_smn(CLK7_CLK_PLL_PWR_REQ, sizeof(int)); + clk7_clk_pll_pwr_req.bitfields.PLL_AUTO_STOP_REQ = 1; + + acp_reg_write_via_smn(CLK7_CLK_PLL_PWR_REQ, + clk7_clk_pll_pwr_req.u32all, sizeof(int)); + acp_7_0_reg_wait(); + + clk7_clk_fsm_status.u32all = acp_reg_read_via_smn(CLK7_CLK_FSM_STATUS, sizeof(int)); + + if (clk7_clk_fsm_status.bitfields.RO_FSM_PLL_STATUS_STOPPED == 1) + break; + } +} + +void audio_pll_power_on(void) +{ + volatile clk7_clk_pll_pwr_req_t clk7_clk_pll_pwr_req; + volatile clk7_clk_fsm_status_t clk7_clk_fsm_status; + int count; + + for (count = 0; count < 10; count++) { + clk7_clk_pll_pwr_req.u32all = + acp_reg_read_via_smn(CLK7_CLK_PLL_PWR_REQ, sizeof(int)); + clk7_clk_pll_pwr_req.bitfields.PLL_AUTO_START_REQ = 1; + + acp_reg_write_via_smn(CLK7_CLK_PLL_PWR_REQ, + clk7_clk_pll_pwr_req.u32all, + sizeof(int)); + acp_7_0_reg_wait(); + + clk7_clk_fsm_status.u32all = acp_reg_read_via_smn(CLK7_CLK_FSM_STATUS, sizeof(int)); + if (clk7_clk_fsm_status.bitfields.RO_FSM_PLL_STATUS_STARTED == 1) + break; + acp_7_0_reg_wait(); + } +} + +void clk_dfs_bypassexit(void) +{ + volatile clk7_clk_dfsbypass_cntl_t clk7_clk_dfsbypass_cntl; + + clk7_clk_dfsbypass_cntl = (clk7_clk_dfsbypass_cntl_t)acp_reg_read_via_smn + (CLK7_CLK_DFSBYPASS_CONTROL, sizeof(int)); + + clk7_clk_dfsbypass_cntl.bitfields.exit_dfs_bypass_0 = 1; + clk7_clk_dfsbypass_cntl.bitfields.exit_dfs_bypass_1 = 1; + + acp_reg_write_via_smn(CLK7_CLK_DFSBYPASS_CONTROL, + clk7_clk_dfsbypass_cntl.u32all, + sizeof(int)); +} + +void audio_pll_mode_switch(uint32_t mode, uint32_t fcw_int, uint32_t fcw_frac, uint32_t fcw_denom, + uint32_t pllspinediv) +{ + volatile clk7_spll_fuse_1_t clk_spll_fuse1; + volatile clk7_spll_fuse_2_t clk_spll_fuse2; + volatile clk7_spll_field_9_t clk_spll_field_9; + volatile clk7_spll_field_6nm_t clk_spll_field_6nm; + volatile clk7_spll_field_7_t clk_spll_field_7; + volatile clk7_spll_field_4_t clk_spll_field_4; + volatile clk7_spll_field_5nm_bus_ctrl_t clk_spll_field_5nm_bus_ctrl; + volatile clk7_spll_field_5nm_bus_wdata_t clk_spll_field_5nm_bus_wdata; + volatile clk7_spll_field_5nm_bus_status_t clk_spll_field_5nm_bus_status; + volatile clk7_rootrefclk_mux_1_t clk_rootrefclkmux; + volatile clk7_spll_field_2_t clk7_spll_field_2; + + clk_spll_fuse1.u32all = 0x0; + clk_spll_fuse2.u32all = 0x0; + clk_spll_field_9.u32all = 0x0; + clk_spll_field_6nm.u32all = 0x0; + clk_spll_field_7.u32all = 0x0; + clk_spll_field_4.u32all = 0x0; + clk_spll_field_5nm_bus_ctrl.u32all = 0x0; + clk_spll_field_5nm_bus_wdata.u32all = 0x0; + clk_spll_field_5nm_bus_status.u32all = 0x0; + clk7_spll_field_2 = + (clk7_spll_field_2_t)acp_reg_read_via_smn(CLK7_SPLL_FIELD_2, sizeof(int)); + + if (clk7_spll_field_2.bitfields.spll_fracn_en == 0) + clk7_spll_field_2.bitfields.spll_fracn_en = 1; + acp_reg_write_via_smn(CLK7_SPLL_FIELD_2, clk7_spll_field_2.u32all, sizeof(int)); + + switch (mode) { + case PLL_MODE_32KHZ_LPPM: + clk_rootrefclkmux.bitfields.ROOTREFCLK_MUX_1 = 0x0; + clk_rootrefclkmux.u32all = acp_reg_read_via_smn(CLK7_ROOTREFCLK_MUX_1, sizeof(int)); + + clk_rootrefclkmux.bitfields.ROOTREFCLK_MUX_1 = 1; + acp_reg_write_via_smn(CLK7_ROOTREFCLK_MUX_1, clk_rootrefclkmux.u32all, sizeof(int)); + + clk_spll_fuse1.bitfields.spll_gp_coarse_exp = 0x5; + clk_spll_fuse1.bitfields.spll_gp_coarse_mant = 0x0; + clk_spll_fuse1.bitfields.spll_gi_coarse_exp = 0x7; + clk_spll_fuse1.bitfields.spll_gi_coarse_mant = 0x0; + + clk_spll_fuse2.bitfields.spll_tdc_resolution = 0xe8; + clk_spll_fuse2.bitfields.spll_freq_offset_exp = 0xa; + clk_spll_fuse2.bitfields.spll_freq_offset_mant = 0xe; + + clk_spll_field_9.bitfields.spll_dpll_cfg_3 = 2; + clk_spll_field_6nm.bitfields.spll_dpll_cfg_4 = 0x60; + clk_spll_field_6nm.bitfields.spll_vco_pre_div = 3; + clk_spll_field_7.bitfields.spll_refclk_rate = 4; + clk_spll_field_7.bitfields.spll_pwr_state = 1; + clk_spll_field_4.bitfields.spll_refclk_div = 0; + + acp_reg_write_via_smn(CLK7_SPLL_FUSE_1, clk_spll_fuse1.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK7_SPLL_FUSE_2, clk_spll_fuse2.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK7_SPLL_FIELD_9, clk_spll_field_9.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK7_SPLL_FIELD_6nm, clk_spll_field_6nm.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK7_SPLL_FIELD_7, clk_spll_field_7.u32all, sizeof(int)); + acp_reg_write_via_smn(CLK7_SPLL_FIELD_4, clk_spll_field_4.u32all, sizeof(int)); + + clk_spll_field_5nm_bus_wdata.bitfields.bus_spll_wr_data = 0x00400000; + acp_reg_write_via_smn(CLK7_SPLL_FIELD_5nm_BUS_WDATA, + clk_spll_field_5nm_bus_wdata.u32all, + sizeof(int)); + + clk_spll_field_5nm_bus_ctrl.u32all = + acp_reg_read_via_smn(CLK7_SPLL_FIELD_5nm_BUS_CTRL, + sizeof(int)); + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_async_mode = 1; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_apb_mode = 0; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_addr = 0xa; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_byte_en = 0xf; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_rdtr = + !clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_rdtr; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_resetb = 1; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_sel = 1; + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_wrtr = 1; + acp_reg_write_via_smn(CLK7_SPLL_FIELD_5nm_BUS_CTRL, + clk_spll_field_5nm_bus_ctrl.u32all, + sizeof(int)); + do { + clk_spll_field_5nm_bus_status.u32all = + acp_reg_read_via_smn(CLK7_SPLL_FIELD_5nm_BUS_STATUS, + sizeof(int)); + } while (clk_spll_field_5nm_bus_status.bitfields.spll_bus_rd_valid != + clk_spll_field_5nm_bus_ctrl.bitfields.bus_spll_rdtr); + + acp_reg_write_via_smn(CLK7_CLK_PLL_RESET_STOP_TIMER, 0xbbb11aa, sizeof(int)); + break; + default: + tr_err(&acp_clk_tr, "ERROR: Invalid PLL Mode"); + return; + } + + clk7_clk_pll_req_u_t clk7_clk_pll_req; + + clk7_clk_pll_req = + (clk7_clk_pll_req_u_t)acp_reg_read_via_smn(CLK7_CLK_PLL_REQ, sizeof(int)); + clk7_clk_pll_req.bitfields.fbmult_int = fcw_int; + + if (clk7_spll_field_2.bitfields.spll_fracn_en) + clk7_clk_pll_req.bitfields.fbmult_frac = fcw_frac; + clk7_clk_pll_req.bitfields.pllspinediv = pllspinediv; + acp_reg_write_via_smn(CLK7_CLK_PLL_REQ, clk7_clk_pll_req.u32all, sizeof(int)); +} + +void clk7_init_vco(void) +{ + audio_pll_power_off(); + audio_pll_mode_switch(PLL_MODE_32KHZ_LPPM, 0x125, 0, 0, 0); + + audio_pll_power_on(); + + clk_dfs_bypassexit(); + acp_reg_write_via_smn(CLK7_CLK1_BYPASS_CNTL, 0, sizeof(int)); +} + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_clocks_info; + 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, + }; + } + acp_reg_write_via_smn(CLK7_CLK0_DFS_CNTL, 0x19, sizeof(int)); +} diff --git a/src/platform/amd/acp_7_0/lib/dai.c b/src/platform/amd/acp_7_0/lib/dai.c new file mode 100644 index 000000000000..87c3f8f62a53 --- /dev/null +++ b/src/platform/amd/acp_7_0/lib/dai.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2024, 2026 AMD. All rights reserved. +// +//Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/common.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +static struct dai acp_dmic_dai[] = { + { + .index = 0, + .plat_data = { + .base = DMA0_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 0, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 1, + }, + }, + .drv = &acp_dmic_dai_driver, + }, +}; + +static struct dai hsdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS_RX_FIFO_OFFST, + .depth = 8, + .handshake = 0, + }, + }, + .drv = &acp_hsdai_driver, + }, + { + .index = 1, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS_RX_FIFO_OFFST, + .depth = 8, + .handshake = 0, + }, + }, + .drv = &acp_hsdai_driver, + } +}; + +static struct dai swaudiodai[] = { + { + .index = DI_SDW0_ACP_SW_AUDIO_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + SW0_AUDIO_TX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_AUDIO_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_AUDIO_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + SW0_AUDIO_RX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_AUDIO_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_BT_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + BT0_TX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_BT_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_BT_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + BT0_RX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_BT_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_HS_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS0_TX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_HS_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW0_ACP_SW_HS_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS0_RX_FIFO_OFFST, + .handshake = SDW0_ACP_SW_HS_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_BT_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + BT_TX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_BT_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_BT_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + BT_RX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_BT_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_AUDIO_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + SW1_AUDIO_TX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_AUDIO_TX_EN_CH, + } + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_AUDIO_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + SW1_AUDIO_RX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_AUDIO_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_HS_TX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + SW1_HS_TX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_HS_TX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, + { + .index = DI_SDW1_ACP_P1_SW_HS_RX, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + SW1_HS_RX_FIFO_OFFST, + .handshake = SDW1_ACP_P1_SW_HS_RX_EN_CH, + }, + }, + .drv = &acp_swaudiodai_driver, + }, +}; + +#ifdef ACP_SP_ENABLE +static struct dai spdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_spdai_driver, + } +}; + +static struct dai sp_virtual_dai[] = { + { + .index = 1, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_sp_virtual_dai_driver, + } +}; +#endif +#ifdef ACP_BT_ENABLE +static struct dai btdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 2, + }, + }, + .drv = &acp_btdai_driver, + }, +}; +#endif + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_AMD_DMIC, + .dai_array = acp_dmic_dai, + .num_dais = ARRAY_SIZE(acp_dmic_dai) + }, + { + .type = SOF_DAI_AMD_HS, + .dai_array = hsdai, + .num_dais = ARRAY_SIZE(hsdai) + }, +#ifdef ACP_SP_ENABLE + { + .type = SOF_DAI_AMD_SP, + .dai_array = spdai, + .num_dais = ARRAY_SIZE(spdai) + }, + { + .type = SOF_DAI_AMD_SP_VIRTUAL, + .dai_array = sp_virtual_dai, + .num_dais = ARRAY_SIZE(sp_virtual_dai) + }, +#endif +#ifdef ACP_BT_ENABLE + { + .type = SOF_DAI_AMD_BT, + .dai_array = btdai, + .num_dais = ARRAY_SIZE(btdai) + }, +#endif + { + .type = SOF_DAI_AMD_SDW, + .dai_array = swaudiodai, + .num_dais = ARRAY_SIZE(swaudiodai) + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(acp_dmic_dai); i++) + k_spinlock_init(&acp_dmic_dai[i].lock); + for (i = 0; i < ARRAY_SIZE(hsdai); i++) + k_spinlock_init(&hsdai[i].lock); + for (i = 0; i < ARRAY_SIZE(swaudiodai); i++) + k_spinlock_init(&swaudiodai[i].lock); +#ifdef ACP_SP_ENABLE + for (i = 0; i < ARRAY_SIZE(spdai); i++) + k_spinlock_init(&spdai[i].lock); + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(sp_virtual_dai); i++) + k_spinlock_init(&sp_virtual_dai[i].lock); +#endif +#ifdef ACP_BT_ENABLE + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(btdai); i++) + k_spinlock_init(&btdai[i].lock); +#endif + sof->dai_info = &lib_dai; + return 0; +} diff --git a/src/platform/amd/acp_7_0/lib/dma.c b/src/platform/amd/acp_7_0/lib/dma.c new file mode 100644 index 000000000000..bbc6b4a6cd8a --- /dev/null +++ b/src/platform/amd/acp_7_0/lib/dma.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2024 AMD. All rights reserved. +// +//Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <platform/fw_scratch_mem.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +extern struct dma_ops acp_dma_ops; +extern struct dma_ops acp_dmic_dma_ops; +#ifdef ACP_BT_ENABLE +extern struct dma_ops acp_dai_bt_dma_ops; +#endif +#ifdef ACP_SP_ENABLE +extern struct dma_ops acp_dai_sp_dma_ops; +#endif +extern struct dma_ops acp_dai_hs_dma_ops; +extern struct dma_ops acp_dai_sw_audio_dma_ops; + +SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .plat_data = { + .id = DMA_ID_DMA0, + .dir = DMA_DIR_LMEM_TO_HMEM | DMA_DIR_HMEM_TO_LMEM, + .devs = DMA_DEV_HOST, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_HS, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dai_hs_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SW_AUDIO, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SW, + .caps = DMA_CAP_SW, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 12, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dai_sw_audio_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_DMIC, + .dir = DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_DMIC, + .caps = DMA_CAP_DMIC, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL4, + }, + .ops = &acp_dmic_dma_ops, +}, +#ifdef ACP_SP_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI_SP, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SP_VIRTUAL, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP_VIRTUAL, + .caps = DMA_CAP_SP_VIRTUAL, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_virtual_dma_ops, +}, +#endif + +#ifdef ACP_BT_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_BT, + .caps = DMA_CAP_BT, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_bt_dma_ops, +}, +#endif +}; + +const struct dma_info lib_dma = { + .dma_array = dma, + .num_dmas = ARRAY_SIZE(dma) +}; + +int acp_dma_init(struct sof *sof) +{ + int i; + uint32_t descr_base; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + descr_base = (uint32_t)(&pscratch_mem_cfg->acp_cfg_dma_descriptor); + descr_base = (descr_base - 0x9C700000); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_BASE_ADDR), descr_base); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_MAX_NUM_DSCR), 0x1); + /* 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/amd/acp_7_0/lib/memory.c b/src/platform/amd/acp_7_0/lib/memory.c new file mode 100644 index 000000000000..ce3925e95860 --- /dev/null +++ b/src/platform/amd/acp_7_0/lib/memory.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 AMD. All rights reserved. +// +// Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA | SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_HP, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = &memmap; +} diff --git a/src/platform/amd/acp_7_0/platform.c b/src/platform/amd/acp_7_0/platform.c new file mode 100644 index 000000000000..72162bfd68f4 --- /dev/null +++ b/src/platform/amd/acp_7_0/platform.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2024, 2026 AMD. All rights reserved. +// +//Author: SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> +// Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <rtos/interrupt.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <zephyr/logging/log.h> + +LOG_MODULE_REGISTER(platform_file, CONFIG_SOF_LOG_LEVEL); + +#define INTERRUPT_DISABLE 0 +extern void acp_dsp_to_host_intr_trig(void); + +struct sof; +static const struct sof_ipc_fw_ready ready + __attribute__((section(".fw_ready"))) = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#if BLD_COUNTERS + .build = SOF_BUILD, /* See version-build-counter.cmake */ + .date = __DATE__, + .time = __TIME__, +#else + .build = -1, + .date = "dtermin.\0", + .time = "fwready.\0", +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_ACP_WINDOWS 6 + +const struct ext_man_windows xsram_window +#ifdef CONFIG_AMD_BINARY_BUILD + __aligned(EXT_MAN_ALIGN) __unused = { +#else + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { +#endif + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_ACP_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + }, +}; + +int platform_init(struct sof *sof) +{ + int ret; + + /* to view system memory */ + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + /* init low latency domains and schedulers */ + /* CONFIG_SYSTICK_PERIOD set as PLATFORM_DEFAULT_CLOCK */ + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + zephyr_ll_scheduler_init(sof->platform_timer_domain); + + /*CONFIG_SYSTICK_PERIOD hardcoded as 200000*/ + sa_init(sof, 200000); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* initialize the host IPC mechanisms */ + ipc_init(sof); + /* initialize the DAI mechanisms */ + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; + + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + acp_sw_intr_trig_t swintrtrig; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + mailbox_dspbox_write(0, &ready, sizeof(ready)); +#ifdef CONFIG_AMD_BINARY_BUILD + mailbox_dspbox_write(sizeof(ready), &xsram_window.window, sizeof(xsram_window.window)); +#endif + pscratch_mem_cfg->acp_dsp_msg_write = 1; + acp_dsp_to_host_intr_trig(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), swintrtrig.u32all); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} diff --git a/src/platform/amd/common/CMakeLists.txt b/src/platform/amd/common/CMakeLists.txt new file mode 100644 index 000000000000..fe55f14509aa --- /dev/null +++ b/src/platform/amd/common/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof) diff --git a/src/platform/amd/common/include/platform/acp_dma.h b/src/platform/amd/common/include/platform/acp_dma.h new file mode 100644 index 000000000000..913efa0c47ed --- /dev/null +++ b/src/platform/amd/common/include/platform/acp_dma.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + *Copyright(c) 2023 AMD. All rights reserved. + * + *Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ + +#ifndef _COMMON_DMA_HEADER +#define _COMMON_DMA_HEADER + +#include <stdint.h> + +#define ACP_MAX_STREAMS 8 +#define ACP_DMA_BUFFER_PERIOD_COUNT 2 +#define ACP_SYST_MEM_WINDOW 0x4000000 + +struct acp_dma_config { + /* base address of dma buffer */ + uint32_t base; + /* size of dma buffer */ + uint32_t size; + /* write pointer of dma buffer */ + uint32_t wr_ptr; + /* read pointer of dma buffer */ + uint32_t rd_ptr; + /* read size of dma buffer */ + uint32_t rd_size; + /* write size of dma buffer */ + uint32_t wr_size; + /* system memory size defined for the stream */ + uint32_t sys_buff_size; + /* virtual system memory offset for system memory buffer */ + uint32_t phy_off; + /* probe_channel id */ + uint32_t probe_channel; +}; + +struct acp_dma_chan_data { + /* channel index */ + uint32_t idx; + /* stream direction */ + uint32_t dir; + /* configuration data of dma */ + struct acp_dma_config config[ACP_MAX_STREAMS]; +}; + +void amd_dma_reconfig(struct dma_chan_data *channel, uint32_t bytes); +int dma_setup(struct dma_chan_data *channel, + struct dma_sg_elem_array *sgelems, uint32_t dir); +void dma_config_descriptor(uint32_t dscr_start_idx, uint32_t dscr_count, + acp_cfg_dma_descriptor_t *psrc_dscr, + acp_cfg_dma_descriptor_t *pdest_dscr); +int acp_dma_get_attribute(struct dma *dma, uint32_t type, + uint32_t *value); +#endif diff --git a/src/platform/amd/common/include/platform/acp_dmic_dma.h b/src/platform/amd/common/include/platform/acp_dmic_dma.h new file mode 100644 index 000000000000..a8e72d8e57c6 --- /dev/null +++ b/src/platform/amd/common/include/platform/acp_dmic_dma.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ + +#ifndef _COMMON_DMIC_DMA_HEADER +#define _COMMON_DMIC_DMA_HEADER + +#include <stdint.h> +#include <platform/chip_registers.h> + +/* 109c7aba-a7ba-43c3-b9-42-59-e2-0a-66-11-be */ + +#define DMIC_SETTLING_TIME_MS 360 +#define DMIC_SMOOTH_TIME_MS 40 + +struct acp_dmic_silence { + uint32_t bytes_per_sample; + uint32_t num_chs; + uint32_t samplerate_khz; + uint32_t silence_cnt; + uint32_t silence_incr; + int coeff; + int numfilterbuffers; + char *dmic_rngbuff_addr1; + int *dmic_rngbuff_iaddr; +}; + +int acp_dmic_dma_start(struct dma_chan_data *channel); +int acp_dmic_dma_stop(struct dma_chan_data *channel); +int acp_dmic_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config); +int acp_dmic_dma_get_attribute(struct dma *dma, + uint32_t type, uint32_t *value); +#endif diff --git a/src/platform/amd/common/include/platform/acp_sp_dma.h b/src/platform/amd/common/include/platform/acp_sp_dma.h new file mode 100644 index 000000000000..dcb2ed5119ae --- /dev/null +++ b/src/platform/amd/common/include/platform/acp_sp_dma.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + *Copyright(c) 2023 AMD. All rights reserved. + * + *Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ + +#ifndef _COMMON_SP_DMA_HEADER +#define _COMMON_SP_DMA_HEADER + +#include <stdint.h> +#include <platform/chip_registers.h> + +#define SP_FIFO_SIZE 512 +#define SP_IER_DISABLE 0x0 + +int acp_dai_sp_dma_start(struct dma_chan_data *channel); +int acp_dai_sp_dma_stop(struct dma_chan_data *channel); +/* set the DMA channel configuration, source/target address, buffer sizes */ +int acp_dai_sp_dma_set_config(struct dma_chan_data *channel, + struct dma_sg_config *config); +int acp_dai_sp_dma_get_data_size(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free); +int acp_dai_sp_dma_get_attribute(struct dma *dma, uint32_t type, uint32_t *value); +int acp_dai_sp_dma_interrupt(struct dma_chan_data *channel, enum dma_irq_cmd cmd); +#endif diff --git a/src/platform/amd/common/include/platform/drivers/idc.h b/src/platform/amd/common/include/platform/drivers/idc.h new file mode 100644 index 000000000000..03b3aae68ba8 --- /dev/null +++ b/src/platform/amd/common/include/platform/drivers/idc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, + uint32_t mode) { return 0; } + +static inline int idc_init(void) { return 0; } + +#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/amd/common/include/platform/ipc.h b/src/platform/amd/common/include/platform/ipc.h new file mode 100644 index 000000000000..a715adde1254 --- /dev/null +++ b/src/platform/amd/common/include/platform/ipc.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023, 2026 AMD. All rights reserved. + * + *Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + * Sivasubramanian <sravisar@amd.com> + */ +#ifndef _COMMON_IPC_HEADER +#define _COMMON_IPC_HEADER + +#include <stdint.h> +#include <platform/platform.h> + +#define IRQ_NUM_EXT_LEVEL3 3 +uint32_t sof_ipc_host_status(void); +uint32_t sof_ipc_host_ack_flag(void); +void sof_ipc_host_ack_clear(void); +uint32_t sof_ipc_host_msg_flag(void); +void sof_ipc_host_msg_clear(void); +void sof_ipc_dsp_ack_set(void); +uint32_t sof_ipc_dsp_status(void); +void sof_ipc_dsp_msg_set(void); +void amd_irq_handler(void *arg); +#endif diff --git a/src/platform/amd/common/include/platform/lib/clk.h b/src/platform/amd/common/include/platform/lib/clk.h new file mode 100644 index 000000000000..54101527270f --- /dev/null +++ b/src/platform/amd/common/include/platform/lib/clk.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <sof/lib/io.h> +#include <stdint.h> + +struct sof; + +#define CLK_CPU(x) (x) + +#define CPU_DEFAULT_IDX 0 + +#define CLK_DEFAULT_CPU_HZ 600000000 +#define CLK_MAX_CPU_HZ 600000000 + +#define NUM_CLOCKS 1 + +#define NUM_CPU_FREQ 1 + +#define ACP_MASTER_REG_ACCESS_ADDRESS 0x3400 + +#define MP1_APERTURE_ID 0x0 + +#define ACP_FIRST_REG_OFFSET 0x01240000 + +#define ACP_SMU_MSG_SET_ACLK 0x3 + + +void acp_change_clock_notify(uint32_t clockFreq); + +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/amd/common/include/platform/lib/cpu.h b/src/platform/amd/common/include/platform/lib/cpu.h new file mode 100644 index 000000000000..5ac72135c0db --- /dev/null +++ b/src/platform/amd/common/include/platform/lib/cpu.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ + +/* + * file platform/lib/cpu.h + * brief DSP core parameters. + */ +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/* brief Number of available DSP cores (conf. by kconfig) */ +#define PLATFORM_CORE_COUNT CONFIG_CORE_COUNT + +/* brief Maximum allowed number of DSP cores */ +#define MAX_CORE_COUNT 1 + +/* brief Id of master DSP core */ +#define PLATFORM_MASTER_CORE_ID 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/amd/common/include/platform/lib/dai.h b/src/platform/amd/common/include/platform/lib/dai.h new file mode 100644 index 000000000000..250e8f945552 --- /dev/null +++ b/src/platform/amd/common/include/platform/lib/dai.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#define SDW0_ACP_SW_HS_RX_EN_CH 0 +#define SDW0_ACP_SW_HS_TX_EN_CH 1 +#define SDW1_ACP_P1_SW_BT_RX_EN_CH 2 +#define SDW1_ACP_P1_SW_BT_TX_EN_CH 3 +#define SDW0_ACP_SW_AUDIO_RX_EN_CH 4 +#define SDW0_ACP_SW_AUDIO_TX_EN_CH 5 +#define SDW0_ACP_SW_BT_RX_EN_CH 6 +#define SDW0_ACP_SW_BT_TX_EN_CH 7 +#define SDW1_ACP_P1_SW_AUDIO_RX_EN_CH 8 +#define SDW1_ACP_P1_SW_AUDIO_TX_EN_CH 9 +#define SDW1_ACP_P1_SW_HS_RX_EN_CH 10 +#define SDW1_ACP_P1_SW_HS_TX_EN_CH 11 + +#define DI_SDW0_ACP_SW_AUDIO_TX 0 +#define DI_SDW0_ACP_SW_BT_TX 1 +#define DI_SDW0_ACP_SW_HS_TX 2 +#define DI_SDW0_ACP_SW_AUDIO_RX 3 +#define DI_SDW0_ACP_SW_BT_RX 4 +#define DI_SDW0_ACP_SW_HS_RX 5 +#define DI_SDW1_ACP_P1_SW_AUDIO_TX 64 +#define DI_SDW1_ACP_P1_SW_BT_TX 65 +#define DI_SDW1_ACP_P1_SW_HS_TX 66 +#define DI_SDW1_ACP_P1_SW_AUDIO_RX 67 +#define DI_SDW1_ACP_P1_SW_BT_RX 68 +#define DI_SDW1_ACP_P1_SW_HS_RX 69 + +#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/amd/common/include/platform/lib/dma.h b/src/platform/amd/common/include/platform/lib/dma.h new file mode 100644 index 000000000000..f8d053876353 --- /dev/null +++ b/src/platform/amd/common/include/platform/lib/dma.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 4 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 12 + +#define DMA_ID_DMA0 0 +#define DMA_ID_HOST 1 +#define DMA_ID_DAI 2 +#define DMA_ID_DAI_SP 3 +#define DMA_ID_DAI_DMIC 4 +#define DMA_ID_DAI_HS 5 +#define DMA_ID_DAI_SP_VIRTUAL 6 +#define DMA_ID_DAI_HS_VIRTUAL 7 +#define DMA_ID_DAI_SW_AUDIO 8 + +#define dma_chan_irq(dma, chan) dma_irq(dma) + +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) +#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/amd/common/include/platform/lib/mailbox.h b/src/platform/amd/common/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..9ef95b01db01 --- /dev/null +++ b/src/platform/amd/common/include/platform/lib/mailbox.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/memory.h> + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE + +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + *ptr = src; +} + +#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/amd/common/include/platform/lib/pm_runtime.h b/src/platform/amd/common/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..542d73a2e179 --- /dev/null +++ b/src/platform/amd/common/include/platform/lib/pm_runtime.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> + +struct pm_runtime_data; + +/* + * brief Initializes platform specific runtime power management. + * param[in,out] prd Runtime power management data. + */ +static inline 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. + */ +static inline 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. + */ +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/amd/common/include/platform/trace/trace.h b/src/platform/amd/common/include/platform/trace/trace.h new file mode 100644 index 000000000000..08980eb539b0 --- /dev/null +++ b/src/platform/amd/common/include/platform/trace/trace.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +/* Platform defined trace code */ +#define platform_trace_point(__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/amd/rembrandt/CMakeLists.txt b/src/platform/amd/rembrandt/CMakeLists.txt new file mode 100644 index 000000000000..ec909d60035f --- /dev/null +++ b/src/platform/amd/rembrandt/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/amd/rembrandt/include/arch/xtensa/config/core-isa.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..36cfd4756638 --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,672 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=12153; Build=0x878bf; Copyright (c) 1999-2020 Tensilica 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. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + +//depot/dev/Homewood/Xtensa/SWConfig/hal/core-common.h.tph#24 - edit change 444323 (text+ko) + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 16 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 0 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 1 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 1 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 1 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 1 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6 or Q7 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 16 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1401000 /* sw version of this header */ +#define XCHAL_SW_MINOR_VERSION 1401000 /* same, with zeroed micro and patch */ +#define XCHAL_SW_MICRO_VERSION 1401000 /* same, with zeroed patch */ + +#define XCHAL_CORE_ID "LX7_HiFi5_PROD" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000878BF /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2038286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x284878BF /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.1" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281010 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_1 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281010 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281010 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 131072 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 17 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 8 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 1 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 8 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x7F000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x7F000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 1048576 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0xE0000000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0xE0000000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 1048576 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + + +#define XCHAL_HAVE_IDMA 0 + + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 9 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 5 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00000143 +#define XCHAL_INTLEVEL2_MASK 0x00000004 +#define XCHAL_INTLEVEL3_MASK 0x00000008 +#define XCHAL_INTLEVEL4_MASK 0x00000010 +#define XCHAL_INTLEVEL5_MASK 0x00000020 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000080 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00000143 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00000147 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0000014F +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0000015F +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0000017F +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0000017F +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x000001FF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 2 +#define XCHAL_INT3_LEVEL 3 +#define XCHAL_INT4_LEVEL 4 +#define XCHAL_INT5_LEVEL 5 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 7 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFFFE00 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00000138 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_NMI 0x00000080 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000002 +#define XCHAL_INTTYPE_MASK_TIMER 0x00000041 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000004 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 0 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 6 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 7 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 2 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL2_NUM 2 +#define XCHAL_INTLEVEL3_NUM 3 +#define XCHAL_INTLEVEL4_NUM 4 +#define XCHAL_INTLEVEL5_NUM 5 +#define XCHAL_INTLEVEL7_NUM 7 +/* (There are many interrupts each at level(s) 1.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 3 /* (intlevel 3) */ +#define XCHAL_EXTINT1_NUM 4 /* (intlevel 4) */ +#define XCHAL_EXTINT2_NUM 5 /* (intlevel 5) */ +#define XCHAL_EXTINT3_NUM 7 /* (intlevel 7) */ +#define XCHAL_EXTINT4_NUM 8 /* (intlevel 1) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT3_EXTNUM 0 /* (intlevel 3) */ +#define XCHAL_INT4_EXTNUM 1 /* (intlevel 4) */ +#define XCHAL_INT5_EXTNUM 2 /* (intlevel 5) */ +#define XCHAL_INT7_EXTNUM 3 /* (intlevel 7) */ +#define XCHAL_INT8_EXTNUM 4 /* (intlevel 1) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ + +#define XCHAL_RESET_VECOFS 0x00000000 +#define XCHAL_RESET_VECTOR_VADDR 0x7F000000 +#define XCHAL_RESET_VECTOR_PADDR 0x7F000000 +#define XCHAL_USER_VECOFS 0x00000000 +#define XCHAL_USER_VECTOR_VADDR 0x7F000740 +#define XCHAL_USER_VECTOR_PADDR 0x7F000740 +#define XCHAL_KERNEL_VECOFS 0x00000000 +#define XCHAL_KERNEL_VECTOR_VADDR 0x7F000700 +#define XCHAL_KERNEL_VECTOR_PADDR 0x7F000700 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x7F0007C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x7F0007C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x7F000400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x7F000400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000000 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x7F000580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x7F000580 +#define XCHAL_INTLEVEL3_VECOFS 0x00000000 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x7F0005C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x7F0005C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000000 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x7F000600 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x7F000600 +#define XCHAL_INTLEVEL5_VECOFS 0x00000000 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x7F000640 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x7F000640 +#define XCHAL_INTLEVEL6_VECOFS 0x00000000 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x7F000680 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x7F000680 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000000 +#define XCHAL_NMI_VECTOR_VADDR 0x7F0006C0 +#define XCHAL_NMI_VECTOR_PADDR 0x7F0006C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 0 +#define XCHAL_MPU_ENTRIES 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 0 +#define XCHAL_MPU_ALIGN 0 + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/config/core-matmap.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..dfac414b0092 --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,317 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=12153; Build=0x878bf; Copyright (c) 1999-2020 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + +#define XCHAL_CA_R (0xC0 | 0x40000000) +#define XCHAL_CA_RX (0xD0 | 0x40000000) +#define XCHAL_CA_RW (0xE0 | 0x40000000) +#define XCHAL_CA_RWX (0xF0 | 0x40000000) + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ +#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefine hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/config/defs.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..0da4586ce0d3 --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=12153; Build=0x878bf; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/config/specreg.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..bac44571c963 --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/specreg.h @@ -0,0 +1,108 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Homewood/ib.1/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=12153; Build=0x878bf; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define SCOMPARE1 12 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define ATOMCTL 99 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define MISC_REG_0 244 +#define MISC_REG_1 245 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/config/system.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..46ddf9d302a0 --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/system.h @@ -0,0 +1,262 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=12153; Build=0x878bf; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +#define XSHAL_ROM_VADDR 0x50000000 +#define XSHAL_ROM_PADDR 0x50000000 +#define XSHAL_ROM_SIZE 0x00020000 +/* Largest available area (free of vectors): */ +#define XSHAL_ROM_AVAIL_VADDR 0x50000000 +#define XSHAL_ROM_AVAIL_VSIZE 0x00020000 + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x60000000 +#define XSHAL_RAM_PADDR 0x60000000 +#define XSHAL_RAM_VSIZE 0x1F000000 +#define XSHAL_RAM_PSIZE 0x1F000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x60000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x1F000000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x1F000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xc0000000 +#define XSHAL_STL_INFO_LOCATION 0x54 + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x42224422 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x12221122 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x12221122 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0x4FFF44FF /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0x1FFF11FF /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0x1FFF11FF /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0x2FFF22FF /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x4222442F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x1222112F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x1222112F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x4FF2442F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x1FF2112F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x1FF2112F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0x2FF2222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000044 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 0 +#define XSHAL_RESET_VECTOR_VADDR 0x7F000000 +#define XSHAL_RESET_VECTOR_PADDR 0x7F000000 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x00000300 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x00000038 +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x00000038 +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/config/tie-asm.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..9ac7ec55993d --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,366 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=12153; Build=0x878bf; Copyright (c) 1999-2020 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + rsr.br \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.scompare1 \at1 // conditional store option + s32i \at1, \ptr, .Lxchal_ofs_+4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 // boolean option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.scompare1 \at1 // conditional store option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed16, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed24, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed31, \ptr, .Lxchal_ofs_+48 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+56 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+57 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+58 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+59 + addi \ptr, \ptr, 64 + ae_salign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_salign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_salign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_salign128.i u3, \ptr, .Lxchal_ofs_+48 + addi \ptr, \ptr, -320 + ae_movdrzbvc aed0 // ureg AE_ZBIASV8C + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 + rur.ae_ovf_sar \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_bithead \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_ts_fts_bu_bp \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cw_sd_no \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.ae_cbegin0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.ae_cend0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+36 + rur.ae_cbegin1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+40 + rur.ae_cend1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+44 + rur.ae_cbegin2 \at1 // ureg 250 + s32i \at1, \ptr, .Lxchal_ofs_+48 + rur.ae_cend2 \at1 // ureg 251 + s32i \at1, \ptr, .Lxchal_ofs_+52 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg AE_ZBIASV8C + ae_movzbvcdr aed0 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ovf_sar \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_bithead \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_ts_fts_bu_bp \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cw_sd_no \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.ae_cbegin0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.ae_cend0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+40 + wur.ae_cbegin1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+44 + wur.ae_cend1 \at1 // ureg 249 + l32i \at1, \ptr, .Lxchal_ofs_+48 + wur.ae_cbegin2 \at1 // ureg 250 + l32i \at1, \ptr, .Lxchal_ofs_+52 + wur.ae_cend2 \at1 // ureg 251 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed16, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed24, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed31, \ptr, .Lxchal_ofs_+48 + addi \ptr, \ptr, 56 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi \ptr, \ptr, 8 + ae_lalign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_lalign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_lalign128.i u3, \ptr, .Lxchal_ofs_+48 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 320 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 64 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/config/tie.h b/src/platform/amd/rembrandt/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..760c76a78b4f --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/config/tie.h @@ -0,0 +1,211 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=12153; Build=0x878bf; Copyright (c) 1999-2020 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 384 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 16 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 12 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 400 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 16 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 3 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 52 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ae_zbiasv8c,16, 8, 8,0x1029, ur,-1 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x102A, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin2, 4, 4, 4,0x03FA, ur,250, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend2, 4, 4, 4,0x03FB, ur,251, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed16, 8, 8, 8,0x1010, aed,16 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed17, 8, 8, 8,0x1011, aed,17 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed18, 8, 8, 8,0x1012, aed,18 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed19, 8, 8, 8,0x1013, aed,19 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed20, 8, 8, 8,0x1014, aed,20 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed21, 8, 8, 8,0x1015, aed,21 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed22, 8, 8, 8,0x1016, aed,22 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed23, 8, 8, 8,0x1017, aed,23 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed24, 8, 8, 8,0x1018, aed,24 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed25, 8, 8, 8,0x1019, aed,25 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed26, 8, 8, 8,0x101A, aed,26 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed27, 8, 8, 8,0x101B, aed,27 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed28, 8, 8, 8,0x101C, aed,28 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed29, 8, 8, 8,0x101D, aed,29 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed30, 8, 8, 8,0x101E, aed,30 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed31, 8, 8, 8,0x101F, aed,31 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1024, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1025, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1026, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1027, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0,16,16,16,0x1020, u,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1,16,16,16,0x1021, u,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2,16,16,16,0x1022, u,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3,16,16,16,0x1023, u,3 ,128,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/amd/rembrandt/include/arch/xtensa/tie/xt_datacache.h b/src/platform/amd/rembrandt/include/arch/xtensa/tie/xt_datacache.h new file mode 100644 index 000000000000..8e83064e2923 --- /dev/null +++ b/src/platform/amd/rembrandt/include/arch/xtensa/tie/xt_datacache.h @@ -0,0 +1,132 @@ +// Customer ID=12153; Build=0x878bf; Copyright (c) 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. + +/* Definitions for the xt_datacache TIE package */ + +/* Do not modify. This is automatically generated.*/ + +#ifndef _XTENSA_xt_datacache_HEADER +#define _XTENSA_xt_datacache_HEADER + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#ifdef __XTENSA__ +#ifdef __XCC__ + +#ifndef _ASMLANGUAGE +#ifndef _NOCLANGUAGE +#ifndef __ASSEMBLER__ + +#include <xtensa/tie/xt_core.h> + +/* + * The following prototypes describe intrinsic functions + * corresponding to TIE instructions. Some TIE instructions + * may produce multiple results (designated as "out" operands + * in the iclass section) or may have operands used as both + * inputs and outputs (designated as "inout"). However, the C + * and C++ languages do not provide syntax that can express + * the in/out/inout constraints of TIE intrinsics. + * Nevertheless, the compiler understands these constraints + * and will check that the intrinsic functions are used + * correctly. To improve the readability of these prototypes, + * the "out" and "inout" parameters are marked accordingly + * with comments. + */ + +extern void _TIE_xt_datacache_DHI(const int * s, immediate i); +extern void _TIE_xt_datacache_DHI_B(const int * s, int i); +extern void _TIE_xt_datacache_DHU(const int * s, immediate i); +extern void _TIE_xt_datacache_DHWB(const int * s, immediate i); +extern void _TIE_xt_datacache_DHWBI(const int * s, immediate i); +extern void _TIE_xt_datacache_DHWBI_B(const int * s, int i); +extern void _TIE_xt_datacache_DHWB_B(const int * s, int i); +extern void _TIE_xt_datacache_DII(const int * s, immediate i); +extern void _TIE_xt_datacache_DIU(const int * s, immediate i); +extern void _TIE_xt_datacache_DIWB(const int * s, immediate i); +extern void _TIE_xt_datacache_DIWBI(const int * s, immediate i); +extern void _TIE_xt_datacache_DIWBUI_P(const int * s /*inout*/); +extern void _TIE_xt_datacache_DPFL(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFM_B(const int * s, int i); +extern void _TIE_xt_datacache_DPFM_BF(const int * s, int i); +extern void _TIE_xt_datacache_DPFR(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFRO(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFR_B(const int * s, int i); +extern void _TIE_xt_datacache_DPFR_BF(const int * s, int i); +extern void _TIE_xt_datacache_DPFW(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFWO(const int * s, immediate i); +extern void _TIE_xt_datacache_DPFW_B(const int * s, int i); +extern void _TIE_xt_datacache_DPFW_BF(const int * s, int i); +extern int _TIE_xt_datacache_LDCT(const int * s); +extern int _TIE_xt_datacache_LDCW(const int * s); +extern void _TIE_xt_datacache_PFEND_A(void); +extern void _TIE_xt_datacache_PFEND_O(void); +extern void _TIE_xt_datacache_PFNXT_F(void); +extern void _TIE_xt_datacache_PFWAIT_A(void); +extern void _TIE_xt_datacache_PFWAIT_R(void); +extern void _TIE_xt_datacache_SDCT(int t, int * s); +extern void _TIE_xt_datacache_SDCW(int t, int * s); + +#endif /*__ASSEMBLER__*/ +#endif /*_NOCLANGUAGE*/ +#endif /*_ASMLANGUAGE*/ + +#define XT_DHI _TIE_xt_datacache_DHI +#define XT_DHI_B _TIE_xt_datacache_DHI_B +#define XT_DHU _TIE_xt_datacache_DHU +#define XT_DHWB _TIE_xt_datacache_DHWB +#define XT_DHWBI _TIE_xt_datacache_DHWBI +#define XT_DHWBI_B _TIE_xt_datacache_DHWBI_B +#define XT_DHWB_B _TIE_xt_datacache_DHWB_B +#define XT_DII _TIE_xt_datacache_DII +#define XT_DIU _TIE_xt_datacache_DIU +#define XT_DIWB _TIE_xt_datacache_DIWB +#define XT_DIWBI _TIE_xt_datacache_DIWBI +#define XT_DIWBUI_P _TIE_xt_datacache_DIWBUI_P +#define XT_DPFL _TIE_xt_datacache_DPFL +#define XT_DPFM_B _TIE_xt_datacache_DPFM_B +#define XT_DPFM_BF _TIE_xt_datacache_DPFM_BF +#define XT_DPFR _TIE_xt_datacache_DPFR +#define XT_DPFRO _TIE_xt_datacache_DPFRO +#define XT_DPFR_B _TIE_xt_datacache_DPFR_B +#define XT_DPFR_BF _TIE_xt_datacache_DPFR_BF +#define XT_DPFW _TIE_xt_datacache_DPFW +#define XT_DPFWO _TIE_xt_datacache_DPFWO +#define XT_DPFW_B _TIE_xt_datacache_DPFW_B +#define XT_DPFW_BF _TIE_xt_datacache_DPFW_BF +#define XT_LDCT _TIE_xt_datacache_LDCT +#define XT_LDCW _TIE_xt_datacache_LDCW +#define XT_PFEND_A _TIE_xt_datacache_PFEND_A +#define XT_PFEND_O _TIE_xt_datacache_PFEND_O +#define XT_PFNXT_F _TIE_xt_datacache_PFNXT_F +#define XT_PFWAIT_A _TIE_xt_datacache_PFWAIT_A +#define XT_PFWAIT_R _TIE_xt_datacache_PFWAIT_R +#define XT_SDCT _TIE_xt_datacache_SDCT +#define XT_SDCW _TIE_xt_datacache_SDCW + +#endif /* __XCC__ */ + +#endif /* __XTENSA__ */ + + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* !_XTENSA_xt_datacache_HEADER */ diff --git a/src/platform/amd/rembrandt/include/platform/chip_offset_byte.h b/src/platform/amd/rembrandt/include/platform/chip_offset_byte.h new file mode 100644 index 000000000000..27b465ce79a5 --- /dev/null +++ b/src/platform/amd/rembrandt/include/platform/chip_offset_byte.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ + +#ifndef _RMB_OFFSET_HEADER +#define _RMB_OFFSET_HEADER + +#define PU_REGISTER_BASE (0x9FD00000 - 0x01240000) +#define PU_SCRATCH_REG_BASE (0x9FF00000 - 0x01250000) + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_PRIO_0 0x1240060 +#define ACP_DMA_CUR_DSCR_0 0x1240080 +#define ACP_DMA_CUR_TRANS_CNT_0 0x12400A0 +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 +#define ACP_DMA_CH_GROUP 0x12400EC +#define ACP_DMA_CH_RST_STS 0x12400F0 + +/* Registers from ACP_MISC block */ +#define ACP_CLKMUX_SEL 0x124102C +#define ACP_DSP0_INTR_CNTL 0x1241800 +#define ACP_DSP0_INTR_STAT 0x1241804 +#define ACP_DSP_SW_INTR_CNTL 0x1241808 +#define ACP_DSP_SW_INTR_STAT 0x124180C +#define ACP_SW_INTR_TRIG 0x1241810 +#define DSP_INTERRUPT_ROUTING_CTRL_0 0x1241814 +#define DSP_INTERRUPT_ROUTING_CTRL_1 0x1241818 +#define ACP_FUTURE_REG_ACLK_0 0x1241854 +#define ACP_AXI2DAGB_SEM_0 0x1241874 +#define ACP_DSP0_INTR_CNTL1 0x1241920 +#define ACP_DSP0_INTR_STAT1 0x1241924 +#define ACP_SRBM_CLIENT_BASE_ADDR 0x12419EC +#define ACP_SRBM_CLIENT_RDDATA 0x12419F0 +#define ACP_SRBM_CYCLE_STS 0x12419F4 +#define ACP_SRBM_CLIENT_CONFIG 0x12419F8 + +/* Registers from ACP_P1_MISC block */ +#define ACP_EXTERNAL_INTR_ENB 0x1241A00 +#define ACP_EXTERNAL_INTR_CNTL 0x1241A04 +#define ACP_EXTERNAL_INTR_CNTL1 0x1241A08 +#define ACP_EXTERNAL_INTR_STAT 0x1241A0C +#define ACP_EXTERNAL_INTR_STAT1 0x1241A10 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 +#define ACP_I2STDM0_MSTRCLKGEN 0x1242414 +#define ACP_I2STDM1_MSTRCLKGEN 0x1242418 +#define ACP_I2STDM2_MSTRCLKGEN 0x124241C +#define ACP_I2STDM_REFCLKGEN 0x1242420 + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 +#define ACP_HSTDM_IER 0x1242814 +#define ACP_HSTDM_IRER 0x1242818 +#define ACP_HSTDM_RXFRMT 0x124281C +#define ACP_HSTDM_ITER 0x1242820 +#define ACP_HSTDM_TXFRMT 0x1242824 + +/* Registers from ACP_WOV block */ +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x1242C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x1242C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x1242C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_PDM_VAD_CTRL 0x1242C30 +#define ACP_WOV_WAKE 0x1242C54 +#define ACP_WOV_BUFFER_STATUS 0x1242C58 +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x1242C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x1242C68 +#define ACP_PDM_CLKDIV 0x1242C6C + +/* Registers from ACP_P1_AUDIO_BUFFERS block */ +#define ACP_P1_I2S_RX_RINGBUFADDR 0x1243A00 +#define ACP_P1_I2S_RX_RINGBUFSIZE 0x1243A04 +#define ACP_P1_I2S_RX_LINKPOSITIONCNTR 0x1243A08 +#define ACP_P1_I2S_RX_FIFOADDR 0x1243A0C +#define ACP_P1_I2S_RX_FIFOSIZE 0x1243A10 +#define ACP_P1_I2S_RX_DMA_SIZE 0x1243A14 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1243A18 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW 0x1243A1C +#define ACP_P1_I2S_RX_INTR_WATERMARK_SIZE 0x1243A20 +#define ACP_P1_I2S_TX_RINGBUFADDR 0x1243A24 +#define ACP_P1_I2S_TX_RINGBUFSIZE 0x1243A28 +#define ACP_P1_I2S_TX_LINKPOSITIONCNTR 0x1243A2C +#define ACP_P1_I2S_TX_FIFOADDR 0x1243A30 +#define ACP_P1_I2S_TX_FIFOSIZE 0x1243A34 +#define ACP_P1_I2S_TX_DMA_SIZE 0x1243A38 +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x1243A3C +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1243A40 +#define ACP_P1_I2S_TX_INTR_WATERMARK_SIZE 0x1243A44 +#define ACP_P1_BT_RX_RINGBUFADDR 0x1243A48 +#define ACP_P1_BT_RX_RINGBUFSIZE 0x1243A4C +#define ACP_P1_BT_RX_LINKPOSITIONCNTR 0x1243A50 +#define ACP_P1_BT_RX_FIFOADDR 0x1243A54 +#define ACP_P1_BT_RX_FIFOSIZE 0x1243A58 +#define ACP_P1_BT_RX_DMA_SIZE 0x1243A5C +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1243A60 +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW 0x1243A64 +#define ACP_P1_BT_RX_INTR_WATERMARK_SIZE 0x1243A68 +#define ACP_P1_BT_TX_RINGBUFADDR 0x1243A6C +#define ACP_P1_BT_TX_RINGBUFSIZE 0x1243A70 +#define ACP_P1_BT_TX_LINKPOSITIONCNTR 0x1243A74 +#define ACP_P1_BT_TX_FIFOADDR 0x1243A78 +#define ACP_P1_BT_TX_FIFOSIZE 0x1243A7C +#define ACP_P1_BT_TX_DMA_SIZE 0x1243A80 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1243A84 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW 0x1243A88 +#define ACP_P1_BT_TX_INTR_WATERMARK_SIZE 0x1243A8C +#define ACP_P1_HS_RX_RINGBUFADDR 0x1243A90 +#define ACP_P1_HS_RX_RINGBUFSIZE 0x1243A94 +#define ACP_P1_HS_RX_LINKPOSITIONCNTR 0x1243A98 +#define ACP_P1_HS_RX_FIFOADDR 0x1243A9C +#define ACP_P1_HS_RX_FIFOSIZE 0x1243AA0 +#define ACP_P1_HS_RX_DMA_SIZE 0x1243AA4 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH 0x1243AA8 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW 0x1243AAC +#define ACP_P1_HS_RX_INTR_WATERMARK_SIZE 0x1243AB0 +#define ACP_P1_HS_TX_RINGBUFADDR 0x1243AB4 +#define ACP_P1_HS_TX_RINGBUFSIZE 0x1243AB8 +#define ACP_P1_HS_TX_LINKPOSITIONCNTR 0x1243ABC +#define ACP_P1_HS_TX_FIFOADDR 0x1243AC0 +#define ACP_P1_HS_TX_FIFOSIZE 0x1243AC4 +#define ACP_P1_HS_TX_DMA_SIZE 0x1243AC8 +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH 0x1243ACC +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW 0x1243AD0 +#define ACP_P1_HS_TX_INTR_WATERMARK_SIZE 0x1243AD4 + +#define MP1_SMN_C2PMSG_69 0x58A14 +#define MP1_SMN_C2PMSG_85 0x58A54 +#define MP1_SMN_C2PMSG_93 0x58A74 + +#define MP0_C2PMSG_73 0x3810A24 +#define MP0_C2PMSG_114 0x3810AC8 +#endif diff --git a/src/platform/amd/rembrandt/include/platform/chip_registers.h b/src/platform/amd/rembrandt/include/platform/chip_registers.h new file mode 100644 index 000000000000..2c2ab79bc1b3 --- /dev/null +++ b/src/platform/amd/rembrandt/include/platform/chip_registers.h @@ -0,0 +1,793 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#if !defined(_RMB_REG_HEADER) +#define _RMB_REG_HEADER + +typedef union acp_dma_cntl_0 { + struct { + unsigned int dmachrst:1; + unsigned int dmachrun:1; + unsigned int dmachiocen:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_dma_cntl_0_t; + +typedef union acp_dma_ch_sts { + struct { + unsigned int dmachrunsts:8; + unsigned int :24; + } bits; + unsigned int u32all; +} acp_dma_ch_sts_t; + +typedef union acp_external_intr_enb { + struct { + unsigned int acpextintrenb:1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_external_intr_enb_t; + +typedef union acp_dsp0_intr_cntl { + struct { + unsigned int dmaiocmask:8; + unsigned int :8; + unsigned int wov_dma_intr_mask:1; + unsigned int :6; + unsigned int audio_buffer_int_mask:6; + unsigned int :3; + } bits; + unsigned int u32all; +} acp_dsp0_intr_cntl_t; + +typedef union acp_dsp0_intr_stat { + struct { + unsigned int dmaiocstat:8; + unsigned int :8; + unsigned int wov_dma_stat:1; + unsigned int :6; + unsigned int audio_buffer_int_stat:6; + unsigned int :3; + } bits; + unsigned int u32all; +} acp_dsp0_intr_stat_t; + +typedef union acp_dsp0_intr_cntl1 { + struct { + unsigned int acp_fusion_dsp_ext_timer1_timeoutmask :1; + unsigned int fusion_dsp_watchdog_timeoutmask :1; + unsigned int soundwire_mask :1; + unsigned int audio_buffer_int_mask :6; + unsigned int :23; + } bits; + unsigned int u32all; +} acp_dsp0_intr_cntl1_t; + +typedef union acp_dsp0_intr_stat1 { + struct { + unsigned int acp_fusion_dsp_timer1_timeoutstat :1; + unsigned int fusion_dsp_watchdog_timeoutstat :1; + unsigned int soundwire_stat :1; + unsigned int audio_buffer_int_stat :6; + unsigned int :23; + } bits; + unsigned int u32all; +} acp_dsp0_intr_stat1_t; + +typedef union acp_dsp_sw_intr_cntl { + struct { + unsigned int :2; + unsigned int dsp0_to_host_intr_mask:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_dsp_sw_intr_cntl_t; + +typedef union acp_dsp_sw_intr_stat { + struct { + unsigned int host_to_dsp0_intr1_stat:1; + unsigned int host_to_dsp0_intr2_stat:1; + unsigned int dsp0_to_host_intr_stat:1; + unsigned int host_to_dsp0_intr3_stat:1; + unsigned int :28; + } bits; + unsigned int u32all; +} acp_dsp_sw_intr_stat_t; + +typedef union acp_sw_intr_trig { + struct { + unsigned int trig_host_to_dsp0_intr1:1; + unsigned int :1; + unsigned int trig_dsp0_to_host_intr:1; + unsigned int :29; + } bits; + unsigned int u32all; +} acp_sw_intr_trig_t; + +typedef union dsp_interrupt_routing_ctrl_0 { + struct { + unsigned int dma_intr_level:3; + unsigned int :18; + unsigned int watchdog_intr_level:3; + unsigned int az_sw_i2s_intr_level:3; + unsigned int sha_intr_level:3; + unsigned int :2; + } bits; + unsigned int u32all; +} dsp_interrupt_routing_ctrl_0_t; + +typedef union dsp_interrupt_routing_ctrl_1 { + struct { + unsigned int host_to_dsp_intr1_level:3; + unsigned int host_to_dsp_intr2_level:3; + unsigned int src_intr_level:3; + unsigned int mailbox_intr_level:3; + unsigned int error_intr_level:3; + unsigned int wov_intr_level:3; + unsigned int fusion_timer1_intr_level:3; + unsigned int fusion_watchdog_intr_level:3; + unsigned int p1_sw_i2s_intr_level:3; + unsigned int :5; + } bits; + unsigned int u32all; +} dsp_interrupt_routing_ctrl_1_t; + +typedef union acp_i2s_rx_ringbufaddr { + struct { + unsigned int i2s_rx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_rx_ringbufaddr_t; + +typedef union acp_i2s_rx_ringbufsize { + struct { + unsigned int i2s_rx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_rx_ringbufsize_t; + +typedef union acp_i2s_rx_linkpositioncntr { + struct { + unsigned int i2s_rx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_rx_linkpositioncntr_t; + +typedef union acp_i2s_rx_fifoaddr { + struct { + unsigned int i2s_rx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_rx_fifoaddr_t; + +typedef union acp_i2s_rx_fifosize { + struct { + unsigned int i2s_rx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_rx_fifosize_t; + +typedef union acp_i2s_rx_dma_size { + struct { + unsigned int i2s_rx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_rx_dma_size_t; + +typedef union acp_i2s_rx_linearpositioncntr_high { + struct { + unsigned int i2s_rx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_high_t; + +typedef union acp_i2s_rx_linearpositioncntr_low { + struct { + unsigned int i2s_rx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_low_t; + +typedef union acp_i2s_rx_watermark_size { + struct { + unsigned int i2s_rx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_rx_intr_watermark_size_t; + +typedef union acp_i2s_tx_ringbufaddr { + struct { + unsigned int i2s_tx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_tx_ringbufaddr_t; + +typedef union acp_i2s_tx_ringbufsize { + struct { + unsigned int i2s_tx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_tx_ringbufsize_t; + +typedef union acp_i2s_tx_linkpositioncntr { + struct { + unsigned int i2s_tx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_tx_linkpositioncntr_t; + +typedef union acp_i2s_tx_fifoaddr { + struct { + unsigned int i2s_tx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_i2s_tx_fifoaddr_t; + +typedef union acp_i2s_tx_fifosize { + struct { + unsigned int i2s_tx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_tx_fifosize_t; + +typedef union acp_i2s_tx_dma_size { + struct { + unsigned int i2s_tx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_i2s_tx_dma_size_t; + +typedef union acp_i2s_tx_linearpositioncntr_high { + struct { + unsigned int i2s_tx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_hight_t; + +typedef union acp_i2s_tx_linearpositioncntr_low { + struct { + unsigned int i2s_tx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_low_t; + +typedef union acp_i2s_tx_intr_watermark_size { + struct { + unsigned int i2s_tx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_i2s_tx_intr_watermark_size_t; + +typedef union acp_bt_rx_ringbufaddr { + struct { + unsigned int bt_rx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_rx_ringbufaddr_t; + +typedef union acp_bt_rx_ringbufsize { + struct { + unsigned int bt_rx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_rx_ringbufsize_t; + +typedef union acp_bt_rx_linkpositioncntr { + struct { + unsigned int bt_rx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_rx_linkpositioncntr_t; + +typedef union acp_bt_rx_fifoaddr { + struct { + unsigned int bt_rx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_rx_fifoaddr_t; + +typedef union acp_bt_rx_fifosize { + struct { + unsigned int bt_rx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_rx_fifosize_t; + +typedef union acp_bt_rx_dma_size { + struct { + unsigned int bt_rx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_rx_dma_size_t; + +typedef union acp_bt_rx_linearpositioncntr_high { + struct { + unsigned int bt_rx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_bt_rx_linearpositioncntr_high_t; + +typedef union acp_bt_rx_linearpositioncntr_low { + struct { + unsigned int bt_rx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_bt_rx_linearpositioncntr_low_t; + +typedef union acp_bt_rx_intr_watermark_size { + struct { + unsigned int bt_rx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_rx_intr_watermark_size_t; + +typedef union acp_bt_tx_ringbufaddr { + struct { + unsigned int bt_tx_ringbufaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_tx_ringbufaddr_t; + +typedef union acp_bt_tx_ringbufsize { + struct { + unsigned int bt_tx_ringbufsize:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_tx_ringbufsize_t; + +typedef union acp_bt_tx_linkpositiontcntr { + struct { + unsigned int bt_tx_linkpositioncntr:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_tx_linkpositiontcntr_t; + +typedef union acp_bt_tx_fifoaddr { + struct { + unsigned int bt_tx_fifoaddr:27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_bt_tx_fifoaddr_t; + +typedef union acp_bt_tx_fifosize { + struct { + unsigned int bt_tx_fifosize:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_tx_fifosize_t; + +typedef union acp_bt_tx_dmasize { + struct { + unsigned int bt_tx_dma_size:13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_bt_tx_dmasize_t; + +typedef union acp_bt_tx_linearpositioncntr_high { + struct { + unsigned int bt_tx_linearpositioncntr_high:32; + } bits; + unsigned int u32all; +} acp_bt_tx_linearpositioncntr_high_t; + +typedef union acp_bt_tx_linearpositioncntr_low { + struct { + unsigned int bt_tx_linearpositioncntr_low:32; + } bits; + unsigned int u32all; +} acp_bt_tx_linearpositioncntr_low_t; + +typedef union acp_bt_tx_intr_watermark_size { + struct { + unsigned int bt_tx_intr_watermark_size:26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_bt_tx_intr_watermark_size_t; + +typedef union acp_i2stdm_ier { + struct { + unsigned int i2stdm_ien:1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_i2stdm_ier_t; + +typedef union acp_i2stdm_irer { + struct { + unsigned int i2stdm_rx_en:1; + unsigned int i2stdm_rx_protocol_mode:1; + unsigned int i2stdm_rx_data_path_mode:1; + unsigned int i2stdm_rx_samplen:3; + unsigned int i2stdm_rx_status:1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_i2stdm_irer_t; + +typedef union acp_i2stdm_iter { + struct { + unsigned int i2stdm_txen:1; + unsigned int i2stdm_tx_protocol_mode:1; + unsigned int i2stdm_tx_data_path_mode:1; + unsigned int i2stdm_tx_samp_len:3; + unsigned int i2stdm_tx_status:1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_i2stdm_iter_t; + +typedef union acp_bttdm_ier { + struct { + unsigned int bttdm_ien:1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_bttdm_ier_t; + +typedef union acp_bttdm_irer { + struct { + unsigned int bttdm_rx_en:1; + unsigned int bttdm_rx_protocol_mode:1; + unsigned int bttdm_rx_data_path_mode:1; + unsigned int bttdm_rx_samplen:3; + unsigned int bttdm_rx_status:1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_bttdm_irer_t; + +typedef union acp_bttdm_iter { + struct { + unsigned int bttdm_txen :1; + unsigned int bttdm_tx_protocol_mode :1; + unsigned int bttdm_tx_data_path_mode :1; + unsigned int bttdm_tx_samp_len :3; + unsigned int bttdm_tx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_bttdm_iter_t; + +typedef union acp_wov_pdm_dma_enable { + struct { + unsigned int pdm_dma_en :1; + unsigned int pdm_dma_en_status :1; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_dma_enable_t; + +typedef union acp_wov_rx_ringbufaddr { + struct { + unsigned int rx_ringbufaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_wov_rx_ringbufaddr_t; + +typedef union acp_wov_rx_ringbufsize { + struct { + unsigned int rx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_wov_rx_ringbufsize_t; + +typedef union acp_wov_rx_intr_watermark_size { + struct { + unsigned int rx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_wov_rx_intr_watermark_size_t; + +typedef union acp_wov_pdm_no_of_channels { + struct { + unsigned int pdm_no_of_channels :2; + unsigned int :30; + } bits; + unsigned int u32all; +} acp_wov_pdm_no_of_channels_t; + +typedef union acp_wov_pdm_decimation_factor { + struct { + unsigned int pdm_decimation_factor :2; + unsigned int :30; + } bits; + unsigned int u32all; +} acp_wov_pdm_decimation_factor_t; + +typedef union acp_wov_misc_ctrl { + struct { + unsigned int :3; + unsigned int pcm_data_shift_ctrl :2; + unsigned int :27; + } bits; + unsigned int u32all; +} acp_wov_misc_ctrl_t; + +typedef union acp_wov_clk_ctrl { + struct { + unsigned int brm_clk_ctrl :4; + unsigned int pdm_vad_clkdiv :2; + unsigned int :26; + } bits; + unsigned int u32all; +} acp_wov_clk_ctrl_t; + +typedef union acp_srbm_cycle_sts { + struct { + unsigned int srbm_clients_sts :1; + unsigned int :7; + } bits; + unsigned int u32all; +} acp_srbm_cycle_sts_t; + +typedef union acp_hs_rx_ringbufaddr { + struct { + unsigned int hs_rx_ringbufaddr :32; + } bits; + unsigned int u32all; +} acp_hs_rx_ringbufaddr_t; + +typedef union acp_hs_rx_ringbufsize { + struct { + unsigned int hs_rx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_ringbufsize_t; + +typedef union acp_hs_rx_linkpositioncntr { + struct { + unsigned int hs_rx_linkpositioncntr :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_linkpositioncntr_t; + +typedef union acp_hs_rx_fifoaddr { + struct { + unsigned int hs_rx_fifoaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_hs_rx_fifoaddr_t; + +typedef union acp_hs_rx_fifosize { + struct { + unsigned int hs_rx_fifosize :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_rx_fifosize_t; + +typedef union acp_hs_rx_dma_size { + struct { + unsigned int hs_rx_dma_size :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_rx_dma_size_t; + +typedef union acp_hs_rx_linearpositioncntr_high { + struct { + unsigned int hs_rx_linearpositioncntr_high :32; + } bits; + unsigned int u32all; +} acp_hs_rx_linearpositioncntr_high_t; + +typedef union acp_hs_rx_linearpositioncntr_low { + struct { + unsigned int hs_rx_linearpositioncntr_low :32; + } bits; + unsigned int u32all; +} acp_hs_rx_linearpositioncntr_low_t; + +typedef union acp_hs_rx_intr_watermark_size { + struct { + unsigned int hs_rx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_intr_watermark_size_t; + +typedef union acp_hs_tx_ringbufaddr { + struct { + unsigned int hs_tx_ringbufaddr :32; + } bits; + unsigned int u32all; +} acp_hs_tx_ringbufaddr_t; + +typedef union acp_hs_tx_ringbufsize { + struct { + unsigned int hs_tx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_ringbufsize_t; + +typedef union acp_hs_tx_linkpositioncntr { + struct { + unsigned int hs_tx_linkpositioncntr :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_linkpositioncntr_t; + +typedef union acp_hs_tx_fifoaddr { + struct { + unsigned int hs_tx_fifoaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_hs_tx_fifoaddr_t; + +typedef union acp_hs_tx_fifosize { + struct { + unsigned int hs_tx_fifosize :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_tx_fifosize_t; + +typedef union acp_hs_tx_dma_size { + struct { + unsigned int hs_tx_dma_size :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_tx_dma_size_t; + +typedef union acp_hs_tx_linearpositioncntr_high { + struct { + unsigned int hs_tx_linearpositioncntr_high :32; + } bits; + unsigned int u32all; +} acp_hs_tx_linearpositioncntr_high_t; + +typedef union acp_hs_tx_linearpositioncntr_low { + struct { + unsigned int hs_tx_linearpositioncntr_low :32; + } bits; + unsigned int u32all; +} acp_hs_tx_linearpositioncntr_low_t; + +typedef union acp_hs_tx_intr_watermark_size { + struct { + unsigned int hs_tx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_intr_watermark_size_t; + +typedef union acp_i2stdm_rxfrmt { + struct { + unsigned int i2stdm_frame_len :9; + unsigned int :6; + unsigned int i2stdm_num_slots :3; + unsigned int i2stdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_i2stdm_rxfrmt_t; + +typedef union acp_i2stdm_txfrmt { + struct { + unsigned int i2stdm_frame_len :9; + unsigned int :6; + unsigned int i2stdm_num_slots :3; + unsigned int i2stdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_i2stdm_txfrmt_t; + +typedef union acp_hstdm_ier { + struct { + unsigned int hstdm_ien :1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_hstdm_ier_t; + +typedef union acp_hstdm_irer { + struct { + unsigned int hstdm_rx_en :1; + unsigned int hstdm_rx_protocol_mode :1; + unsigned int hstdm_rx_data_path_mode :1; + unsigned int hstdm_rx_samplen :3; + unsigned int hstdm_rx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_hstdm_irer_t; + +typedef union acp_hstdm_rxfrmt { + struct { + unsigned int hstdm_frame_len :9; + unsigned int :6; + unsigned int hstdm_num_slots :3; + unsigned int hstdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_hstdm_rxfrmt_t; + +typedef union acp_hstdm_iter { + struct { + unsigned int hstdm_txen :1; + unsigned int hstdm_tx_protocol_mode :1; + unsigned int hstdm_tx_data_path_mode :1; + unsigned int hstdm_tx_samp_len :3; + unsigned int hstdm_tx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_hstdm_iter_t; + +typedef union acp_hstdm_txfrmt { + struct { + unsigned int hstdm_frame_len :9; + unsigned int :6; + unsigned int hstdm_num_slots :3; + unsigned int hstdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_hstdm_txfrmt_t; + +typedef union acp_clkmux_sel { + struct { + unsigned int acp_clkmux_sel : 3; + unsigned int : 13; + unsigned int acp_clkmux_div_value : 16; + } bits; + unsigned int u32all; +} acp_clkmux_sel_t; + +typedef union acp_i2stdm_mstrclkgen { + struct { + unsigned int i2stdm_master_mode : 1; + unsigned int i2stdm_format_mode : 1; + unsigned int i2stdm_lrclk_div_val : 9; + unsigned int i2stdm_bclk_div_val : 11; + unsigned int : 10; + } bits; + unsigned int u32all; +} acp_i2stdm_mstrclkgen_t; +#endif diff --git a/src/platform/amd/rembrandt/include/platform/drivers/interrupt.h b/src/platform/amd/rembrandt/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..dfbb58df5ea6 --- /dev/null +++ b/src/platform/amd/rembrandt/include/platform/drivers/interrupt.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <rtos/bit.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> + +#define PLATFORM_IRQ_HW_NUM 9 + +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM + +#define PLATFORM_IRQ_CHILDREN 0 + +/* IRQ numbers - wrt Tensilica DSP */ +#define IRQ_NUM_SOFTWARE0 1 /* level 1 */ + +#define IRQ_NUM_TIMER0 0 /* level 1 */ + +#define IRQ_NUM_EXT_LEVEL3 3 /* level 1 */ + +#define IRQ_NUM_TIMER1 6 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL4 4 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL5 5 /* level 3 */ + +/* IRQ Masks */ +#define IRQ_MASK_SOFTWARE0 (1 << IRQ_NUM_SOFTWARE0) + +#define IRQ_MASK_TIMER0 (1 << IRQ_NUM_TIMER0) + +#define IRQ_MASK_TIMER1 (1 << IRQ_NUM_TIMER1) + +#define IRQ_MASK_EXT_LEVEL3 (1 << IRQ_NUM_EXT_LEVEL3) + +#define IRQ_MASK_EXT_LEVEL4 (1 << IRQ_NUM_EXT_LEVEL4) + +#define IRQ_MASK_EXT_LEVEL5 (1 << IRQ_NUM_EXT_LEVEL5) + + +#define HOST_TO_DSP_INTR 0x1 + +#define _XTSTR(x) # x + +#define XTSTR(x) _XTSTR(x) + + +/* Enabling flag */ +#define INTERRUPT_ENABLE 1 + +/* Clearing flag */ +#define INTERRUPT_CLEAR 0 + +/* Disable flag */ +#define INTERRUPT_DISABLE 0 + +/* brief Tensilica Interrupt Levels. */ +typedef enum { + acp_interrupt_level_3 = 0, + + acp_interrupt_level_4, + + acp_interrupt_level_5, + + acp_interrupt_level_nmi, + + acp_interrupt_level_max +} artos_interrupt_levels_t; + +/* brief Tensilica timer control */ +typedef enum { + acp_timer_cntl_disable = 0, + + acp_timer_cntl_oneshot, + + acp_timer_cntl_periodic, + + acp_timer_cntl_max +} artos_timer_control_t; + +/* Disable Host to DSP interrupt */ +void acp_dsp_sw_intr_disable(void); + +void acp_intr_route(void); + +void acp_dsp_to_host_intr_trig(void); + +void acp_ack_intr_from_host(void); + +void acp_dsp_sw_intr_enable(void); + +void acp_intr_enable(void); + +void acp_intr_disable(void); + +#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/amd/rembrandt/include/platform/fw_scratch_mem.h b/src/platform/amd/rembrandt/include/platform/fw_scratch_mem.h new file mode 100644 index 000000000000..1b0a0dea44d3 --- /dev/null +++ b/src/platform/amd/rembrandt/include/platform/fw_scratch_mem.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifndef __EXT_SCRATCH_MEM_H__ +#define __EXT_SCRATCH_MEM_H__ + +#include <sof/lib/mailbox.h> + +/* MAX number of DMA descriptors */ +#define MAX_NUM_DMA_DESC_DSCR 64 +#define SCRATCH_REG_OFFSET 0x1250000 +#define ACP_SRAM 0x03800000 +typedef struct acp_atu_grp_pte { + uint32_t low_part; + uint32_t high_part; +} __attribute__((packed, aligned(4))) acp_atu_grp_pte_t; + +typedef union acp_cfg_dma_trns_cnt { + struct{ + uint32_t trns_cnt : 19; + uint32_t reserved : 12; + uint32_t ioc : 1; + } bits; + unsigned int u32all; +} __attribute__((packed, aligned(4))) acp_cfg_dma_trns_cnt_t; + +typedef struct acp_config_dma_descriptor { + uint32_t src_addr; + uint32_t dest_addr; + acp_cfg_dma_trns_cnt_t trns_cnt; + uint32_t reserved; +} __attribute__((packed, aligned(4))) acp_cfg_dma_descriptor_t; + +typedef struct acp_config_dma_misc { + uint32_t channelstatus; + uint32_t channel; + uint32_t flag; +} __attribute__((packed, aligned(4))) acp_cfg_dma_misc_t; + +typedef struct acp_scratch_memory_config { + /* ACP out box buffer */ + uint8_t acp_outbox_buffer[MAILBOX_DSPBOX_SIZE]; + + /* ACP in box buffer */ + uint8_t acp_inbox_buffer[MAILBOX_HOSTBOX_SIZE]; + + /* ACP debug box buffer */ + uint8_t acp_debug_buffer[MAILBOX_DEBUG_SIZE]; + + /* ACP exception box buffer */ + uint8_t acp_except_buffer[MAILBOX_EXCEPTION_SIZE]; + + /* ACP stream buffer */ + uint8_t acp_stream_buffer[MAILBOX_STREAM_SIZE]; + + /* ACP trace buffer */ + uint8_t acp_trace_buffer[MAILBOX_TRACE_SIZE]; + + /* Host msg write flag */ + uint32_t acp_host_msg_write; + + /* Host ack flag */ + uint32_t acp_host_ack_write; + + /* Dsp msg write flag */ + uint32_t acp_dsp_msg_write; + + /* Dsp ack flag */ + uint32_t acp_dsp_ack_write; + + /* ACP pte1 table */ + acp_atu_grp_pte_t acp_atugrp1_pte[16]; + + /* ACP pte2 table */ + acp_atu_grp_pte_t acp_atugrp2_pte[16]; + + /* ACP pte3 table */ + acp_atu_grp_pte_t acp_atugrp3_pte[16]; + + /* ACP pte4 table */ + acp_atu_grp_pte_t acp_atugrp4_pte[16]; + + /* ACP pte5 table */ + acp_atu_grp_pte_t acp_atugrp5_pte[16]; + + /* ACP pte6 table */ + acp_atu_grp_pte_t acp_atugrp6_pte[16]; + + /* ACP pte7 table */ + acp_atu_grp_pte_t acp_atugrp7_pte[16]; + + /* ACP pte8 table */ + acp_atu_grp_pte_t acp_atugrp8_pte[16]; + + /* ACP DMA Descriptor */ + acp_cfg_dma_descriptor_t acp_cfg_dma_descriptor[MAX_NUM_DMA_DESC_DSCR]; + + /* Stream physical offset */ + uint32_t phy_offset[8]; + + /* Stream system memeory size */ + uint32_t syst_buff_size[8]; + + /* Fifo buffers are not part of scratch memory on Rembrandt */ + /* Added fifo members to align with Driver structure */ + /* ACP transmit fifo buffer */ + uint8_t acp_transmit_fifo_buffer[768] __attribute__((aligned(128))); + + /* ACP receive fifo buffer */ + uint8_t acp_receive_fifo_buffer[768] __attribute__((aligned(128))); + + uint32_t reserve[]; +} __attribute__((packed, aligned(4))) acp_scratch_mem_config_t; + +#endif /* __EXT_SCRATCH_MEM_H__ */ + diff --git a/src/platform/amd/rembrandt/include/platform/lib/memory.h b/src/platform/amd/rembrandt/include/platform/lib/memory.h new file mode 100644 index 000000000000..92ac53b4c2ed --- /dev/null +++ b/src/platform/amd/rembrandt/include/platform/lib/memory.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> +#include <platform/chip_offset_byte.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN 128 + +/* physical DSP addresses */ +#define IRAM_BASE 0x7F000000 +#define IRAM_SIZE 0x60000 + +#define DRAM0_BASE 0xE0000000 +#define DRAM0_SIZE 0x10000 +#define SRAM0_BASE 0x9FF00000 + +#define DRAM1_BASE 0xE0010000 +#define DRAM1_SIZE 0x10000 +#define SRAM1_BASE 0x60006000 +#define SRAM1_SIZE 0x13A000 + +#define DMA0_BASE PU_REGISTER_BASE +#define DMA0_SIZE 0x4 + +/* DAI DMA register base address */ +#define DAI_BASE (PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR) +#define DAI_BASE_REM (PU_REGISTER_BASE + ACP_P1_I2S_RX_RINGBUFADDR) +#define DAI_SIZE 0x4 +#define BT_TX_FIFO_OFFST (ACP_P1_BT_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define BT_RX_FIFO_OFFST (ACP_P1_BT_RX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) + +#define HS_TX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) +#define HS_RX_FIFO_OFFST (ACP_P1_HS_TX_FIFOADDR - ACP_P1_I2S_RX_RINGBUFADDR) + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +/* Log buffer base need to be updated properly, these are used in linker scripts */ +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* Stack configuration */ +#define SOF_STACK_SIZE 0x1000 +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE +#define SOF_STACK_END (DRAM0_BASE + DRAM0_SIZE) +#define SOF_STACK_BASE (SOF_STACK_END + SOF_STACK_SIZE) + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE SRAM0_BASE +#define SRAM_OUTBOX_SIZE 0x400 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x400 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x400 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x400 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x400 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x400 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 60 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 4 +#define HEAP_RT_COUNT1024 12 +#define HEAP_RT_COUNT2048 12 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 72 +#define HEAP_SYS_RT_COUNT512 24 /*rembrandt-arch*/ +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ +#define HEAP_SYSTEM_BASE SRAM1_BASE +#define HEAP_SYSTEM_SIZE 0xE000 +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +#define HEAP_SYS_RUNTIME_SIZE (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE (0xF000) +#define HEAP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x7 +#define SOF_MEM_VECT_TEXT_SIZE 0x37 +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x400 +#define SOF_MEM_RESET_LIT_SIZE 0x8 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 +#define SOF_MEM_WIN_TEXT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define is_uncached(address) 0 + +#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN + +/* brief EDF task's default stack size in bytes */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +struct sof; + + +#define SHARED_DATA +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} +#endif + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#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/amd/rembrandt/include/platform/platform.h b/src/platform/amd/rembrandt/include/platform/platform.h new file mode 100644 index 000000000000..5cfd40d83f32 --- /dev/null +++ b/src/platform/amd/rembrandt/include/platform/platform.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <rtos/interrupt.h> +#include <rtos/clk.h> +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LEVEL_3 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 65536 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE 8192 + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +/* default dma trace channel */ +#define DMA_TRACE_CHANNEL 7 + +/* debug offset */ +#define ACP_SOF_FW_STATUS 0 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + acp_sw_intr_trig_t sw_intr_trig; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + + pscratch_mem_cfg->acp_dsp_msg_write = p; + mailbox_sw_reg_write(ACP_SOF_FW_STATUS, p); + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t) io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt trigger register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* + * brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/amd/rembrandt/lib/CMakeLists.txt b/src/platform/amd/rembrandt/lib/CMakeLists.txt new file mode 100644 index 000000000000..163fe4463158 --- /dev/null +++ b/src/platform/amd/rembrandt/lib/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dai.c + dma.c +) diff --git a/src/platform/amd/rembrandt/lib/clk.c b/src/platform/amd/rembrandt/lib/clk.c new file mode 100644 index 000000000000..071e8c74168f --- /dev/null +++ b/src/platform/amd/rembrandt/lib/clk.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 AMD. All rights reserved. +// +// Author: Basavaraj Hiregoudar<basavaraj.hiregoudar@amd.com> + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <rtos/sof.h> +#include <platform/chip_registers.h> + +const struct freq_table platform_cpu_freq[] = { + {600000000, 600000 }, +}; + +STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static int acp_reg_read_via_smn(uint32_t reg_offset, + uint32_t size) +{ + uint32_t reg_value; + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + /* Configuring the MP1 Aperture Id in SRB_client_config register */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + /* Configuring the base address of MP1 */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + /* dummy read to the to the address offset 0x3400 */ + /* Master config offset to access register outside of ACP */ + reg_value = (uint32_t)io_reg_read(PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + ACP_FIRST_REG_OFFSET)); + if (reg_value) + reg_value = 0; + /* reading status register to check above read request is completed or not */ + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + /* Waiting for status to be set to '0' */ + while (delay_cnt > 0) { + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) { + /* when status is '0' from above read the data from data register */ + return (uint32_t) io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CLIENT_RDDATA); + } + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + delay_cnt--; + } + return -1; +} + +static void acp_reg_write_via_smn(uint32_t reg_offset, + uint32_t value, uint32_t size) +{ + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + /* Configuring the MP1 Aperture Id in SRB_client_config register */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + /* Configuring the base address of MP1 */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + /* write to the address offset 0x3400 + * Master config offset to access register outside of ACP + */ + io_reg_write((PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + ACP_FIRST_REG_OFFSET)), + value); + /* reading status register to check above read request is completed or not */ + acp_srbm_cycle_sts = + (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CYCLE_STS); + /* Waiting for status to be set to '0' */ + while (delay_cnt > 0) { + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return; + delay_cnt--; + } +} + +static void get_response_from_smu(void) +{ + uint32_t ret_value; + uint32_t count = 0; + + do { + ret_value = acp_reg_read_via_smn(MP1_SMN_C2PMSG_93, sizeof(int)); + if (count > 0x007fffff) + count = 0; + count++; + } while (ret_value == 0); +} + + +void acp_change_clock_notify(uint32_t clock_freq) +{ + /* converting Hz to Mhz */ + clock_freq = (clock_freq / 1000000); + /* Writing response zero to the response register + * so that it cab reset to '0' for further response + */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_93, + 0, sizeof(int)); + /* Writing clock frequency value in Mhz in the Argument register */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_85, + clock_freq, sizeof(int)); + /* Writing Message to message register */ + /* Writing Aclk change message to message register */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_69, + ACP_SMU_MSG_SET_ACLK, sizeof(int)); + /* Waiting for SMU response */ + get_response_from_smu(); +} + +void platform_clock_init(struct sof *sof) +{ + int i = 0; + + sof->clocks = platform_clocks_info; + 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/amd/rembrandt/lib/dai.c b/src/platform/amd/rembrandt/lib/dai.c new file mode 100644 index 000000000000..c72e5e6ee139 --- /dev/null +++ b/src/platform/amd/rembrandt/lib/dai.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/common.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +static struct dai acp_dmic_dai[] = { + { + .index = 0, + .plat_data = { + .base = DMA0_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 0, + }, + .base = DMA0_BASE, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 1, + }, + }, + .drv = &acp_dmic_dai_driver, + }, +}; + +static struct dai hsdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS_RX_FIFO_OFFST, + .depth = 8, + .handshake = 0, + }, + }, + .drv = &acp_hsdai_driver, + }, + { + .index = 1, + .plat_data = { + .base = DAI_BASE_REM, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE_REM + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE_REM + HS_RX_FIFO_OFFST, + .depth = 8, + .handshake = 0, + }, + }, + .drv = &acp_hsdai_driver, + } +}; + +#ifdef ACP_SP_ENABLE +static struct dai spdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_spdai_driver, + } +}; + +static struct dai sp_virtual_dai[] = { + { + .index = 1, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_sp_virtual_dai_driver, + } +}; +#endif +#ifdef ACP_BT_ENABLE +static struct dai btdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 2, + }, + }, + .drv = &acp_btdai_driver, + }, +}; +#endif + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_AMD_DMIC, + .dai_array = acp_dmic_dai, + .num_dais = ARRAY_SIZE(acp_dmic_dai) + }, + { + .type = SOF_DAI_AMD_HS, + .dai_array = hsdai, + .num_dais = ARRAY_SIZE(hsdai) + }, +#ifdef ACP_SP_ENABLE + { + .type = SOF_DAI_AMD_SP, + .dai_array = spdai, + .num_dais = ARRAY_SIZE(spdai) + }, + { + .type = SOF_DAI_AMD_SP_VIRTUAL, + .dai_array = sp_virtual_dai, + .num_dais = ARRAY_SIZE(sp_virtual_dai) + }, +#endif +#ifdef ACP_BT_ENABLE + { + .type = SOF_DAI_AMD_BT, + .dai_array = btdai, + .num_dais = ARRAY_SIZE(btdai) + }, +#endif +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(acp_dmic_dai); i++) + k_spinlock_init(&acp_dmic_dai[i].lock); + for (i = 0; i < ARRAY_SIZE(hsdai); i++) + k_spinlock_init(&hsdai[i].lock); +#ifdef ACP_SP_ENABLE + for (i = 0; i < ARRAY_SIZE(spdai); i++) + k_spinlock_init(&spdai[i].lock); + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(sp_virtual_dai); i++) + k_spinlock_init(&sp_virtual_dai[i].lock); +#endif +#ifdef ACP_BT_ENABLE + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(btdai); i++) + k_spinlock_init(&btdai[i].lock); +#endif + sof->dai_info = &lib_dai; + return 0; +} diff --git a/src/platform/amd/rembrandt/lib/dma.c b/src/platform/amd/rembrandt/lib/dma.c new file mode 100644 index 000000000000..66ddea8effe8 --- /dev/null +++ b/src/platform/amd/rembrandt/lib/dma.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022, 2026 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> +// Sivasubramanian <sravisar@amd.com> + +#include <sof/common.h> +#include <platform/fw_scratch_mem.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +extern struct dma_ops acp_dma_ops; +extern struct dma_ops acp_dmic_dma_ops; +#ifdef ACP_BT_ENABLE +extern struct dma_ops acp_dai_bt_dma_ops; +#endif +#ifdef ACP_SP_ENABLE +extern struct dma_ops acp_dai_sp_dma_ops; +#endif +extern struct dma_ops acp_dai_hs_dma_ops; + +SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .plat_data = { + .id = DMA_ID_DMA0, + .dir = DMA_DIR_LMEM_TO_HMEM | DMA_DIR_HMEM_TO_LMEM, + .devs = DMA_DEV_HOST, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_DMIC, + .dir = DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_DMIC, + .caps = SOF_DMA_CAP_DMIC, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL4, + }, + .ops = &acp_dmic_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_HS, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = SOF_DMA_DEV_SP, + .caps = SOF_DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_hs_dma_ops, +}, +#ifdef ACP_SP_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI_SP, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SP_VIRTUAL, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP_VIRTUAL, + .caps = DMA_CAP_SP_VIRTUAL, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_virtual_dma_ops, +}, +#endif + +#ifdef ACP_BT_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_BT, + .caps = DMA_CAP_BT, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_bt_dma_ops, +}, +#endif +}; + +const struct dma_info lib_dma = { + .dma_array = dma, + .num_dmas = ARRAY_SIZE(dma) +}; + +int acp_dma_init(struct sof *sof) +{ + int i; + uint32_t descr_base; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + descr_base = (uint32_t)(&pscratch_mem_cfg->acp_cfg_dma_descriptor); + descr_base = (descr_base - 0x9C700000); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_BASE_ADDR), descr_base); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_MAX_NUM_DSCR), 0x1); + /* 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/amd/rembrandt/platform.c b/src/platform/amd/rembrandt/platform.c new file mode 100644 index 000000000000..1c26e8e8fcfa --- /dev/null +++ b/src/platform/amd/rembrandt/platform.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2022 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <rtos/interrupt.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <platform/chip_offset_byte.h> + +struct sof; +static const struct sof_ipc_fw_ready ready + __attribute__((section(".fw_ready"))) = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#ifdef DEBUG_BUILD + /* only added in debug for reproducability in releases */ + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_ACP_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_ACP_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + }, +}; + +int platform_init(struct sof *sof) +{ + int ret; + + /* initialize cascade interrupts before any usage */ + interrupt_init(sof); + + /* to view system memory */ + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + /* init low latency domains and schedulers */ + /* CONFIG_SYSTICK_PERIOD set as PLATFORM_DEFAULT_CLOCK */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, + PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + + /*CONFIG_SYSTICK_PERIOD hardcoded as 200000*/ + sa_init(sof, 200000); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + /* init DMA */ + ret = acp_dma_init(sof); + if (ret < 0) + return -ENODEV; + /* Init DMA platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], + sizeof(sof->dma_info->dma_array), PLATFORM_DEFAULT_CLOCK, true); + sof->platform_dma_domain->full_sync = true; + scheduler_init_ll(sof->platform_dma_domain); + /* initialize the host IPC mechanisms */ + ipc_init(sof); + /* initialize the DAI mechanisms */ + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + sof->dmat->config.elem_array.elems = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct dma_sg_elem) * 1); + sof->dmat->config.elem_array.count = 1; + sof->dmat->config.elem_array.elems->dest = 0x03800000; + sof->dmat->config.elem_array.elems->size = 65536; + sof->dmat->config.scatter = 0; + dma_trace_init_complete(sof->dmat); +#endif + /* show heap status */ + heap_trace_all(1); + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + acp_sw_intr_trig_t swintrtrig; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + mailbox_dspbox_write(0, &ready, sizeof(ready)); + pscratch_mem_cfg->acp_dsp_msg_write = 1; + acp_dsp_to_host_intr_trig(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), swintrtrig.u32all); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} diff --git a/src/platform/amd/rembrandt/rembrandt.x.in b/src/platform/amd/rembrandt/rembrandt.x.in new file mode 100644 index 000000000000..1a1434aa3005 --- /dev/null +++ b/src/platform/amd/rembrandt/rembrandt.x.in @@ -0,0 +1,580 @@ +/* + * Linker Script for AMD Rembrandt + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_WINDOW_VECTORS_VADDR, //XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int6_lit : + org = XCHAL_INTLEVEL6_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int6_text : + org = XCHAL_INTLEVEL6_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + + vector_int7_lit : + org = XCHAL_INTLEVEL7_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int7_text : + org = XCHAL_INTLEVEL7_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE, + len = IRAM_BASE + (XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE) + sof_sdram0 : + org = DRAM0_BASE, + len = DRAM0_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END, +sof_sdram1 : + org = DRAM1_BASE, + len = DRAM1_SIZE +sof_sram1 : + org = SRAM1_BASE, + len = SRAM1_SIZE + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_iram_text_start_phdr PT_LOAD; + sof_sdram0_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_sdram1_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_WINDOW_VECTORS_VADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x44024000; +_memmap_cacheattr_wt_base = 0x11021000; +_memmap_cacheattr_bp_base = 0x22022000; +_memmap_cacheattr_unused_mask = 0x00F00FFF; +_memmap_cacheattr_wb_trapnull = 0x4422422F; +_memmap_cacheattr_wba_trapnull = 0x4422422F; +_memmap_cacheattr_wbna_trapnull = 0x25222222; +_memmap_cacheattr_wt_trapnull = 0x1122122F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0x44F24FFF; +_memmap_cacheattr_wt_strict = 0x11F21FFF; +_memmap_cacheattr_bp_strict = 0x22F22FFF; +_memmap_cacheattr_wb_allvalid = 0x44224222; +_memmap_cacheattr_wt_allvalid = 0x11221222; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .Level5InterruptVector.literal : ALIGN(4) + { + _Level5InterruptVector_literal_start = ABSOLUTE(.); + *(.Level5InterruptVector.literal) + _Level5InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .Level5InterruptVector.text : ALIGN(4) + { + _Level5InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level5InterruptVector.text)) + _Level5InterruptVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int6_lit :vector_int6_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int6_text :vector_int6_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int7_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int7_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >sof_iram_text_start :sof_iram_text_start_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_iram_text_start :sof_iram_text_start_phdr + + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + } >sof_sdram0 :sof_sdram0_phdr + + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + +.sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + +} diff --git a/src/platform/amd/renoir/CMakeLists.txt b/src/platform/amd/renoir/CMakeLists.txt new file mode 100644 index 000000000000..ec909d60035f --- /dev/null +++ b/src/platform/amd/renoir/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/amd/renoir/include/arch/xtensa/config/core-isa.h b/src/platform/amd/renoir/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..d620328c2b4b --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,534 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=12153; Build=0x72343; Copyright (c) 1999-2018 Tensilica 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. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 0 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector or user floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 1 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 1 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 1 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 1 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 1 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 1 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ +#define XCHAL_HAVE_PDX4 0 /* PDX4 */ +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* GRIVPEP is General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 16 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 1100004 /* sw version of this header */ + +#define XCHAL_CORE_ID "ACP_3_1_001_PROD" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x00072343 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2F0CFFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x1D072343 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX6.0.4" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 4 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 260004 /* major*100+minor */ +#define XCHAL_HW_REL_LX6 1 +#define XCHAL_HW_REL_LX6_0 1 +#define XCHAL_HW_REL_LX6_0_4 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 4 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 260004 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 4 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 260004 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 8 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 8 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 3 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 3 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 0 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 0 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_ICACHE_TEST 0 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 0 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ +#define XCHAL_HAVE_AXI 1 /* AXI bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 0 +#define XCHAL_DCACHE_SETWIDTH 0 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 1 +#define XCHAL_DCACHE_WAYS 1 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 0 +#define XCHAL_DCACHE_LINE_LOCKABLE 0 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 1 +#define XCHAL_DCACHE_ACCESS_SIZE 1 + +#define XCHAL_DCACHE_BANKS 0 /* number of banks */ + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x20000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x20000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 1048576 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x21000000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x21000000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 1048576 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 8 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 3 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 4 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00000003 +#define XCHAL_INTLEVEL2_MASK 0x00000004 +#define XCHAL_INTLEVEL3_MASK 0x00000008 +#define XCHAL_INTLEVEL4_MASK 0x00000010 +#define XCHAL_INTLEVEL5_MASK 0x00000060 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000080 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00000003 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00000007 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0000000F +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0000001F +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0000007F +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0000007F +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x000000FF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 2 +#define XCHAL_INT3_LEVEL 3 +#define XCHAL_INT4_LEVEL 4 +#define XCHAL_INT5_LEVEL 5 +#define XCHAL_INT6_LEVEL 5 +#define XCHAL_INT7_LEVEL 7 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_NMI + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFFFF00 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000002 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00000038 +#define XCHAL_INTTYPE_MASK_TIMER 0x00000041 +#define XCHAL_INTTYPE_MASK_NMI 0x00000080 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000004 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 0 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 6 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 7 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 2 /* write-error interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL2_NUM 2 +#define XCHAL_INTLEVEL3_NUM 3 +#define XCHAL_INTLEVEL4_NUM 4 +#define XCHAL_INTLEVEL7_NUM 7 +/* (There are many interrupts each at level(s) 1, 5.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 3 /* (intlevel 3) */ +#define XCHAL_EXTINT1_NUM 4 /* (intlevel 4) */ +#define XCHAL_EXTINT2_NUM 5 /* (intlevel 5) */ +#define XCHAL_EXTINT3_NUM 7 /* (intlevel 7) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT3_EXTNUM 0 /* (intlevel 3) */ +#define XCHAL_INT4_EXTNUM 1 /* (intlevel 4) */ +#define XCHAL_INT5_EXTNUM 2 /* (intlevel 5) */ +#define XCHAL_INT7_EXTNUM 3 /* (intlevel 7) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x20000400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x20000400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x20000000 +#define XCHAL_RESET_VECTOR0_PADDR 0x20000000 +#define XCHAL_RESET_VECTOR1_VADDR 0x20000800 +#define XCHAL_RESET_VECTOR1_PADDR 0x20000800 +#define XCHAL_RESET_VECTOR_VADDR 0x20000000 +#define XCHAL_RESET_VECTOR_PADDR 0x20000000 +#define XCHAL_USER_VECOFS 0x00000340 +#define XCHAL_USER_VECTOR_VADDR 0x20000740 +#define XCHAL_USER_VECTOR_PADDR 0x20000740 +#define XCHAL_KERNEL_VECOFS 0x00000300 +#define XCHAL_KERNEL_VECTOR_VADDR 0x20000700 +#define XCHAL_KERNEL_VECTOR_PADDR 0x20000700 +#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x200007C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x200007C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x20000400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x20000400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x20000580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x20000580 +#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x200005C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x200005C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000200 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x20000600 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x20000600 +#define XCHAL_INTLEVEL5_VECOFS 0x00000240 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x20000640 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x20000640 +#define XCHAL_INTLEVEL6_VECOFS 0x00000280 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x20000680 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x20000680 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000002C0 +#define XCHAL_NMI_VECTOR_VADDR 0x200006C0 +#define XCHAL_NMI_VECTOR_PADDR 0x200006C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ +/* If none of the above last 4 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/src/platform/amd/renoir/include/arch/xtensa/config/core-matmap.h b/src/platform/amd/renoir/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..c455815cd9d1 --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,318 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=12153; Build=0x72343; Copyright (c) 1999-2018 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ +#define XCHAL_CA_WRITETHRU 2 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 2 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 0 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 2 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_BYPASS_RW 0 /* cache disabled (bypassed) mode (no exec) */ +#define XCHAL_CA_WRITETHRU_RW 0 /* cache enabled (write-through) mode (no exec) */ +#define XCHAL_CA_WRITEBACK_RW 0 /* cache enabled (write-back) mode (no exec) */ +#define XCHAL_CA_WRITEBACK_NOALLOC_RW 0 /* cache enabled (write-back no-allocate) mode (no exec) */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ +#define XCHAL_CA_ISOLATE 0 /* cache isolate (accesses go to cache not memory) mode */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefined hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/amd/renoir/include/arch/xtensa/config/defs.h b/src/platform/amd/renoir/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..0e3500014cd1 --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=12153; Build=0x72343; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/amd/renoir/include/arch/xtensa/config/specreg.h b/src/platform/amd/renoir/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..ae2eaaf0b6ea --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/specreg.h @@ -0,0 +1,113 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Eaglenest/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=12153; Build=0x72343; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define SCOMPARE1 12 +#define ACCLO 16 +#define ACCHI 17 +#define MR_0 32 +#define MR_1 33 +#define MR_2 34 +#define MR_3 35 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define IBREAKENABLE 96 +#define ATOMCTL 99 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define MISC_REG_0 244 +#define MISC_REG_1 245 + +/* Special cases (bases of special register series): */ +#define MR 32 +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/amd/renoir/include/arch/xtensa/config/system.h b/src/platform/amd/renoir/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..fb070b1918a1 --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/system.h @@ -0,0 +1,271 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=12153; Build=0x72343; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + +/*#include <xtensa/hal.h>*/ + + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 +/* Alternatives: */ +/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ +/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ + +#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 +/* Alternatives: */ +/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ +/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ +/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 0 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +/*#define XSHAL_ROM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ROM_SIZE ...not configured...*/ +/*#define XSHAL_ROM_AVAIL_V{ADDR,SIZE} ...not configured...*/ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x40000000 +#define XSHAL_RAM_PADDR 0x40000000 +#define XSHAL_RAM_VSIZE 0x40000000 +#define XSHAL_RAM_PSIZE 0x40000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x40000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x40000000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x80000000 +#define XSHAL_RAM_BYPASS_PADDR 0x80000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ +/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0x0 + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22221112 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22221112 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22221112 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFFFF111F /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFFFF111F /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFFFF111F /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFFFF222F /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2222111F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2222111F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2222111F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFFF2121F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFFF2121F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFFF2121F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFFF2222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000110 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 +#define XSHAL_STATIC_VECTOR_SELECT 0 +#define XSHAL_RESET_VECTOR_VADDR 0x20000000 +#define XSHAL_RESET_VECTOR_PADDR 0x20000000 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x00000300 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x00000038 +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x00000038 +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/amd/renoir/include/arch/xtensa/config/tie-asm.h b/src/platform/amd/renoir/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..68a172f0de2d --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,409 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=12153; Build=0x72343; Copyright (c) 1999-2018 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.THREADPTR \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + rsr.ACCLO \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.ACCHI \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 996, 4, 4 + rsr.BR \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.SCOMPARE1 \at1 // conditional store option + s32i \at1, \ptr, .Lxchal_ofs_+4 + rsr.M0 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+8 + rsr.M1 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+12 + rsr.M2 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+16 + rsr.M3 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+20 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 996, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.THREADPTR \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.ACCLO \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.ACCHI \at1 // MAC16 option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 996, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.BR \at1 // boolean option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.SCOMPARE1 \at1 // conditional store option + l32i \at1, \ptr, .Lxchal_ofs_+8 + wsr.M0 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+12 + wsr.M1 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+16 + wsr.M2 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+20 + wsr.M3 \at1 // MAC16 option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 996, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor FPU. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_FPU_store xchal_cp0_store + .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1008, 8, 8 + rur.FCR \at1 // ureg 232 + s32i \at1, \ptr, .Lxchal_ofs_+0 + rur.FSR \at1 // ureg 233 + s32i \at1, \ptr, .Lxchal_ofs_+4 + sdi f0, \ptr, .Lxchal_ofs_+8 + sdi f1, \ptr, .Lxchal_ofs_+16 + sdi f2, \ptr, .Lxchal_ofs_+24 + sdi f3, \ptr, .Lxchal_ofs_+32 + sdi f4, \ptr, .Lxchal_ofs_+40 + sdi f5, \ptr, .Lxchal_ofs_+48 + sdi f6, \ptr, .Lxchal_ofs_+56 + sdi f7, \ptr, .Lxchal_ofs_+64 + sdi f8, \ptr, .Lxchal_ofs_+72 + sdi f9, \ptr, .Lxchal_ofs_+80 + sdi f10, \ptr, .Lxchal_ofs_+88 + sdi f11, \ptr, .Lxchal_ofs_+96 + sdi f12, \ptr, .Lxchal_ofs_+104 + sdi f13, \ptr, .Lxchal_ofs_+112 + sdi f14, \ptr, .Lxchal_ofs_+120 + sdi f15, \ptr, .Lxchal_ofs_+128 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 136 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1008, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 136 + .endif + .endm // xchal_cp0_store + + /* + * Macro to load the state of TIE coprocessor FPU. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_FPU_load xchal_cp0_load + .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1008, 8, 8 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.FCR \at1 // ureg 232 + l32i \at1, \ptr, .Lxchal_ofs_+4 + wur.FSR \at1 // ureg 233 + ldi f0, \ptr, .Lxchal_ofs_+8 + ldi f1, \ptr, .Lxchal_ofs_+16 + ldi f2, \ptr, .Lxchal_ofs_+24 + ldi f3, \ptr, .Lxchal_ofs_+32 + ldi f4, \ptr, .Lxchal_ofs_+40 + ldi f5, \ptr, .Lxchal_ofs_+48 + ldi f6, \ptr, .Lxchal_ofs_+56 + ldi f7, \ptr, .Lxchal_ofs_+64 + ldi f8, \ptr, .Lxchal_ofs_+72 + ldi f9, \ptr, .Lxchal_ofs_+80 + ldi f10, \ptr, .Lxchal_ofs_+88 + ldi f11, \ptr, .Lxchal_ofs_+96 + ldi f12, \ptr, .Lxchal_ofs_+104 + ldi f13, \ptr, .Lxchal_ofs_+112 + ldi f14, \ptr, .Lxchal_ofs_+120 + ldi f15, \ptr, .Lxchal_ofs_+128 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 136 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1008, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 136 + .endif + .endm // xchal_cp0_load + +#define XCHAL_CP0_NUM_ATMPS 1 + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + rur.AE_OVF_SAR \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+0 + rur.AE_BITHEAD \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+4 + rur.AE_TS_FTS_BU_BP \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+8 + rur.AE_CW_SD_NO \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+12 + rur.AE_CBEGIN0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.AE_CEND0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+20 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+16 + ae_salign64.i u0, \ptr, .Lxchal_ofs_+24 + ae_salign64.i u1, \ptr, .Lxchal_ofs_+32 + ae_salign64.i u2, \ptr, .Lxchal_ofs_+40 + ae_salign64.i u3, \ptr, .Lxchal_ofs_+48 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 128 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.AE_OVF_SAR \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+4 + wur.AE_BITHEAD \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.AE_TS_FTS_BU_BP \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+12 + wur.AE_CW_SD_NO \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.AE_CBEGIN0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.AE_CEND0 \at1 // ureg 247 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+16 + addi \ptr, \ptr, 24 + ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 + ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 + ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 152 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/amd/renoir/include/arch/xtensa/config/tie.h b/src/platform/amd/renoir/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..697f28a6b840 --- /dev/null +++ b/src/platform/amd/renoir/include/arch/xtensa/config/tie.h @@ -0,0 +1,208 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=12153; Build=0x72343; Copyright (c) 1999-2018 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. */ + +#ifndef _XTENSA_CORE_TIE_H +#define _XTENSA_CORE_TIE_H + +#define XCHAL_CP_NUM 2 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x03 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP0_NAME "FPU" +#define XCHAL_CP0_IDENT FPU +#define XCHAL_CP0_SA_SIZE 136 /* size of state save area */ +#define XCHAL_CP0_SA_ALIGN 8 /* min alignment of save area */ +#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 184 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 36 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 368 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 9 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,1,0,0,1, acclo, 4, 4, 4,0x0210, sr,16 , 32,0,0,0) \ + XCHAL_SA_REG(s,1,0,0,1, acchi, 4, 4, 4,0x0211, sr,17 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m0, 4, 4, 4,0x0220, sr,32 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m1, 4, 4, 4,0x0221, sr,33 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m2, 4, 4, 4,0x0222, sr,34 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m3, 4, 4, 4,0x0223, sr,35 , 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 18 +#define XCHAL_CP0_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, fcr, 8, 4, 4,0x03E8, ur,232, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f0, 8, 8, 8,0x0030, f,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f1, 8, 8, 8,0x0031, f,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f2, 8, 8, 8,0x0032, f,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f3, 8, 8, 8,0x0033, f,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f4, 8, 8, 8,0x0034, f,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f5, 8, 8, 8,0x0035, f,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f6, 8, 8, 8,0x0036, f,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f7, 8, 8, 8,0x0037, f,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f8, 8, 8, 8,0x0038, f,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f9, 8, 8, 8,0x0039, f,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f10, 8, 8, 8,0x003A, f,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f11, 8, 8, 8,0x003B, f,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f12, 8, 8, 8,0x003C, f,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f13, 8, 8, 8,0x003D, f,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f14, 8, 8, 8,0x003E, f,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f15, 8, 8, 8,0x003F, f,15 , 64,0,0,0) + +#define XCHAL_CP1_SA_NUM 26 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1010, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1011, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1012, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1013, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1014, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1015, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1016, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1017, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1018, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1019, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x101A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x101B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x101C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x101D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x101E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x101F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1020, u,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1021, u,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1022, u,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1023, u,3 , 64,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 + +#endif /*_XTENSA_CORE_TIE_H*/ + diff --git a/src/platform/amd/renoir/include/platform/chip_offset_byte.h b/src/platform/amd/renoir/include/platform/chip_offset_byte.h new file mode 100644 index 000000000000..b8f670f9b570 --- /dev/null +++ b/src/platform/amd/renoir/include/platform/chip_offset_byte.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni <anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifndef _rn_OFFSET_HEADER +#define _rn_OFFSET_HEADER + +#define PU_REGISTER_BASE (0x22040000 - 0x01240000) + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 + +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_PRIO_0 0x1240060 + +/* Registers from ACP_MISC block */ +#define ACP_CLKMUX_SEL 0x1241424 +#define ACP_EXTERNAL_INTR_ENB 0x1241800 +#define ACP_EXTERNAL_INTR_STAT 0x1241808 +#define ACP_DSP0_INTR_CNTL 0x124180C +#define ACP_DSP0_INTR_STAT 0x1241810 +#define ACP_DSP_SW_INTR_CNTL 0x1241814 +#define ACP_DSP_SW_INTR_STAT 0x1241818 +#define ACP_SW_INTR_TRIG 0x124181C +#define ACP_SMU_MAILBOX 0x1241820 +#define DSP_INTERRUPT_ROUTING_CTRL 0x1241824 +#define ACP_FUTURE_REG_ACLK_0 0x1241860 +#define ACP_TIMER 0x1241874 +#define ACP_TIMER_CNTL 0x1241878 +#define ACP_AXI2DAGB_SEM_0 0x1241880 + +#define ACP_SRBM_CLIENT_BASE_ADDR 0x1241BBC +#define ACP_SRBM_Client_RDDATA 0x1241BC0 +#define ACP_SRBM_CYCLE_STS 0x1241BC4 +#define ACP_SRBM_CLIENT_CONFIG 0x1241BC8 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 + + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 + + +/* Registers from ACP_WOV block */ +#define ACP_WOV_VAD_ENABLE 0x1242C00 +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x1242C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x1242C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x1242C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_PDM_VAD_CTRL 0x1242C30 + +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x1242C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x1242C68 + +#define MP1_SMN_C2PMSG_69 0x58A14 +#define MP1_SMN_C2PMSG_85 0x58A54 +#define MP1_SMN_C2PMSG_93 0x58A74 +#endif diff --git a/src/platform/amd/renoir/include/platform/chip_registers.h b/src/platform/amd/renoir/include/platform/chip_registers.h new file mode 100644 index 000000000000..643050afb9f9 --- /dev/null +++ b/src/platform/amd/renoir/include/platform/chip_registers.h @@ -0,0 +1,546 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni <anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#if !defined(_RN_REG_HEADER) +#define _RN_REG_HEADER + +typedef union acp_dma_cntl_0 { + struct { + unsigned int dmachrst:1; + unsigned int dmachrun:1; + unsigned int dmachiocen:1; + unsigned int :29; + } bits; +unsigned int u32all; +} acp_dma_cntl_0_t; + +typedef union acp_dma_ch_sts { + struct { + unsigned int dmachrunsts:8; + unsigned int :24; + } bits; +unsigned int u32all; +} acp_dma_ch_sts_t; + +typedef union acp_external_intr_enb { + struct { + unsigned int acpextintrenb:1; + unsigned int :31; + } bits; +unsigned int u32all; +} acp_external_intr_enb_t; + +typedef union acp_dsp0_intr_cntl { + struct { + unsigned int dmaiocmask:8; + unsigned int :8; + unsigned int wov_dma_intr_mask:1; + unsigned int :6; + unsigned int audio_buffer_int_mask:6; + unsigned int :3; + } bits; +unsigned int u32all; +} acp_dsp0_intr_cntl_t; + +typedef union acp_dsp0_intr_stat { + struct { + unsigned int dmaiocstat:8; + unsigned int :8; + unsigned int wov_dma_stat:1; + unsigned int :6; + unsigned int audio_buffer_int_stat:6; + unsigned int :3; + } bits; +unsigned int u32all; +} acp_dsp0_intr_stat_t; + +typedef union acp_dsp_sw_intr_cntl { + struct { + unsigned int :2; + unsigned int dsp0_to_host_intr_mask:1; + unsigned int :29; + } bits; +unsigned int u32all; +} acp_dsp_sw_intr_cntl_t; + +typedef union acp_dsp_sw_intr_stat { + struct { + unsigned int host_to_dsp0_intr1_stat:1; + unsigned int host_to_dsp0_intr2_stat:1; + unsigned int dsp0_to_host_intr_stat:1; + unsigned int host_to_dsp0_intr3_stat:1; + unsigned int :28; + } bits; +unsigned int u32all; +} acp_dsp_sw_intr_stat_t; + +typedef union acp_sw_intr_trig { + struct { + unsigned int trig_host_to_dsp0_intr1:1; + unsigned int :1; + unsigned int trig_dsp0_to_host_intr:1; + unsigned int :29; + } bits; +unsigned int u32all; +} acp_sw_intr_trig_t; + +typedef union dsp_interrupt_routing_ctrl { + struct { + unsigned int dma_intr_level:2; + unsigned int :14; + unsigned int az_sw_i2s_intr_level:2; + unsigned int :2; + unsigned int host_to_dsp_intr1_level:2; + unsigned int :8; + unsigned int wov_intr_level:2; + } bits; +unsigned int u32all; +} dsp_interrupt_routing_ctrl_t; + +typedef union acp_i2s_rx_ringbufaddr { + struct { + unsigned int i2s_rx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_rx_ringbufaddr_t; + +typedef union acp_i2s_rx_ringbufsize { + struct { + unsigned int i2s_rx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_rx_ringbufsize_t; + +typedef union acp_i2s_rx_linkpositioncntr { + struct { + unsigned int i2s_rx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_rx_linkpositioncntr_t; + +typedef union acp_i2s_rx_fifoaddr { + struct { + unsigned int i2s_rx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_rx_fifoaddr_t; + +typedef union acp_i2s_rx_fifosize { + struct { + unsigned int i2s_rx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_rx_fifosize_t; + +typedef union acp_i2s_rx_dma_size { + struct { + unsigned int i2s_rx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_rx_dma_size_t; + +typedef union acp_i2s_rx_linearpositioncntr_high { + struct { + unsigned int i2s_rx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_high_t; + +typedef union acp_i2s_rx_linearpositioncntr_low { + struct { + unsigned int i2s_rx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_low_t; + +typedef union acp_i2s_rx_watermark_size { + struct { + unsigned int i2s_rx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_rx_intr_watermark_size_t; + +typedef union acp_i2s_tx_ringbufaddr { + struct { + unsigned int i2s_tx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_tx_ringbufaddr_t; + +typedef union acp_i2s_tx_ringbufsize { + struct { + unsigned int i2s_tx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_tx_ringbufsize_t; + +typedef union acp_i2s_tx_linkpositioncntr { + struct { + unsigned int i2s_tx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_tx_linkpositioncntr_t; + +typedef union acp_i2s_tx_fifoaddr { + struct { + unsigned int i2s_tx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_tx_fifoaddr_t; + +typedef union acp_i2s_tx_fifosize { + struct { + unsigned int i2s_tx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_tx_fifosize_t; + +typedef union acp_i2s_tx_dma_size { + struct { + unsigned int i2s_tx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_tx_dma_size_t; + +typedef union acp_i2s_tx_linearpositioncntr_high { + struct { + unsigned int i2s_tx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_hight_t; + +typedef union acp_i2s_tx_linearpositioncntr_low { + struct { + unsigned int i2s_tx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_low_t; + +typedef union acp_i2s_tx_intr_watermark_size { + struct { + unsigned int i2s_tx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_tx_intr_watermark_size_t; + +typedef union acp_bt_rx_ringbufaddr { + struct { + unsigned int bt_rx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_rx_ringbufaddr_t; + +typedef union acp_bt_rx_ringbufsize { + struct { + unsigned int bt_rx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_rx_ringbufsize_t; + +typedef union acp_bt_rx_linkpositioncntr { + struct { + unsigned int bt_rx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_rx_linkpositioncntr_t; + +typedef union acp_bt_rx_fifoaddr { + struct { + unsigned int bt_rx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_rx_fifoaddr_t; + +typedef union acp_bt_rx_fifosize { + struct { + unsigned int bt_rx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_rx_fifosize_t; + +typedef union acp_bt_rx_dma_size { + struct { + unsigned int bt_rx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_rx_dma_size_t; + +typedef union acp_bt_rx_linearpositioncntr_high { + struct { + unsigned int bt_rx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_bt_rx_linearpositioncntr_high_t; + +typedef union acp_bt_rx_linearpositioncntr_low { + struct { + unsigned int bt_rx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_bt_rx_linearpositioncntr_low_t; + +typedef union acp_bt_rx_intr_watermark_size { + struct { + unsigned int bt_rx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_rx_intr_watermark_size_t; + +typedef union acp_bt_tx_ringbufaddr { + struct { + unsigned int bt_tx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_tx_ringbufaddr_t; + +typedef union acp_bt_tx_ringbufsize { + struct { + unsigned int bt_tx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_tx_ringbufsize_t; + +typedef union acp_bt_tx_linkpositiontcntr { + struct { + unsigned int bt_tx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_tx_linkpositiontcntr_t; + +typedef union acp_bt_tx_fifoaddr { + struct { + unsigned int bt_tx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_tx_fifoaddr_t; + +typedef union acp_bt_tx_fifosize { + struct { + unsigned int bt_tx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_tx_fifosize_t; +typedef union acp_bt_tx_dmasize { + struct { + unsigned int bt_tx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_tx_dmasize_t; + +typedef union acp_bt_tx_linearpositioncntr_high { + struct { + unsigned int bt_tx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_bt_tx_linearpositioncntr_high_t; + +typedef union acp_bt_tx_linearpositioncntr_low { + struct { + unsigned int bt_tx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_bt_tx_linearpositioncntr_low_t; + +typedef union acp_bt_tx_intr_watermark_size { + struct { + unsigned int bt_tx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_tx_intr_watermark_size_t; + +typedef union acp_i2stdm_ier { + struct { + unsigned int i2stdm_ien:1; + unsigned int :31; + } bits; +unsigned int u32all; +} acp_i2stdm_ier_t; +typedef union acp_i2stdm_irer { + struct { + unsigned int i2stdm_rx_en:1; + unsigned int i2stdm_rx_protocol_mode:1; + unsigned int i2stdm_rx_data_path_mode:1; + unsigned int i2stdm_rx_samplen:3; + unsigned int i2stdm_rx_status:1; + unsigned int :25; + + } bits; +unsigned int u32all; +} acp_i2stdm_irer_t; + +typedef union acp_i2stdm_iter { + struct { + unsigned int i2stdm_txen:1; + unsigned int i2stdm_tx_protocol_mode:1; + unsigned int i2stdm_tx_data_path_mode:1; + unsigned int i2stdm_tx_samp_len:3; + unsigned int i2stdm_tx_status:1; + unsigned int :25; + } bits; +unsigned int u32all; +} acp_i2stdm_iter_t; + +typedef union acp_bttdm_ier { + struct { + unsigned int bttdm_ien:1; + unsigned int :31; + } bits; +unsigned int u32all; +} acp_bttdm_ier_t; + +typedef union acp_bttdm_irer { + struct { + unsigned int bttdm_rx_en:1; + unsigned int bttdm_rx_protocol_mode:1; + unsigned int bttdm_rx_data_path_mode:1; + unsigned int bttdm_rx_samplen:3; + unsigned int bttdm_rx_status:1; + unsigned int :25; + } bits; +unsigned int u32all; +} acp_bttdm_irer_t; + +typedef union acp_bttdm_iter { + struct { + unsigned int bttdm_txen:1; + unsigned int bttdm_tx_protocol_mode:1; + unsigned int bttdm_tx_data_path_mode:1; + unsigned int bttdm_tx_samp_len:3; + unsigned int bttdm_tx_status:1; + unsigned int :25; + } bits; +unsigned int u32all; +} acp_bttdm_iter_t; + +typedef union acp_wov_pdm_dma_enable { + struct { + unsigned int pdm_dma_en:1; + unsigned int pdm_dma_en_status:1; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_dma_enable_t; + +typedef union acp_wov_rx_ringbufaddr { + struct { + unsigned int rx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_wov_rx_ringbufaddr_t; + +typedef union acp_wov_rx_ringbufsize { + struct { + unsigned int rx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_wov_rx_ringbufsize_t; + +typedef union acp_wov_rx_intr_watermark_size { + struct { + unsigned int rx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_wov_rx_intr_watermark_size_t; + +typedef union acp_wov_pdm_no_of_channels { + struct { + unsigned int pdm_no_of_channels:2; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_no_of_channels_t; + +typedef union acp_wov_pdm_decimation_factor { + struct { + unsigned int pdm_decimation_factor:2; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_decimation_factor_t; + +typedef union acp_wov_misc_ctrl { + struct { + unsigned int :3; + unsigned int pcm_data_shift_ctrl:2; + unsigned int :27; + } bits; +unsigned int u32all; +} acp_wov_misc_ctrl_t; + +typedef union acp_wov_clk_ctrl { + struct { + unsigned int brm_clk_ctrl:4; + unsigned int pdm_vad_clkdiv:2; + unsigned int :26; + } bits; +unsigned int u32all; +} acp_wov_clk_ctrl_t; + +typedef union acp_srbm_cycle_sts { + struct { + unsigned int srbm_clients_sts:1; + unsigned int :7; + + } bits; +unsigned int u32all; +} acp_srbm_cycle_sts_t; + +typedef union acp_i2stdm_rxfrmt { + struct { + unsigned int i2stdm_frame_len :9; + unsigned int :6; + unsigned int i2stdm_num_slots :3; + unsigned int i2stdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_i2stdm_rxfrmt_t; +typedef union acp_i2stdm_txfrmt { + struct { + unsigned int i2stdm_frame_len :9; + unsigned int :6; + unsigned int i2stdm_num_slots :3; + unsigned int i2stdm_slot_len :5; + unsigned int :9; + } bits; + unsigned int u32all; +} acp_i2stdm_txfrmt_t; + +#endif + diff --git a/src/platform/amd/renoir/include/platform/drivers/interrupt.h b/src/platform/amd/renoir/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..328ffb832ca6 --- /dev/null +++ b/src/platform/amd/renoir/include/platform/drivers/interrupt.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni <anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <rtos/bit.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> + +#define PLATFORM_IRQ_HW_NUM 8 + +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM + +#define PLATFORM_IRQ_CHILDREN 0 + +/* IRQ numbers - wrt Tensilica DSP */ +#define IRQ_NUM_SOFTWARE0 1 /* level 1 */ + +#define IRQ_NUM_TIMER0 0 /* level 1 */ + +#define IRQ_NUM_EXT_LEVEL3 3 /* level 1 */ + +#define IRQ_NUM_TIMER1 6 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL4 4 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL5 5 /* level 3 */ + +/* IRQ Masks */ +#define IRQ_MASK_SOFTWARE0 (1 << IRQ_NUM_SOFTWARE0) + +#define IRQ_MASK_TIMER0 (1 << IRQ_NUM_TIMER0) + +#define IRQ_MASK_TIMER1 (1 << IRQ_NUM_TIMER1) + +#define IRQ_MASK_EXT_LEVEL3 (1 << IRQ_NUM_EXT_LEVEL3) + +#define IRQ_MASK_EXT_LEVEL4 (1 << IRQ_NUM_EXT_LEVEL4) + +#define IRQ_MASK_EXT_LEVEL5 (1 << IRQ_NUM_EXT_LEVEL5) + + +#define HOST_TO_DSP_INTR 0x1 + +#define _XTSTR(x) # x + +#define XTSTR(x) _XTSTR(x) + + +/* Enabling flag */ +#define INTERRUPT_ENABLE 1 + +/* Clearing flag */ +#define INTERRUPT_CLEAR 0 + +/* Disable flag */ +#define INTERRUPT_DISABLE 0 + +/* brief Tensilica Interrupt Levels. */ +typedef enum { + acp_interrupt_level_3 = 0, + + acp_interrupt_level_4, + + acp_interrupt_level_5, + + acp_interrupt_level_nmi, + + acp_interrupt_level_max +} artos_interrupt_levels_t; + +/* brief Tensilica timer control */ +typedef enum { + acp_timer_cntl_disable = 0, + + acp_timer_cntl_oneshot, + + acp_timer_cntl_periodic, + + acp_timer_cntl_max +} artos_timer_control_t; + +/* Disable Host to DSP interrupt */ +void acp_dsp_sw_intr_disable(void); + +void acp_intr_route(void); + +void acp_dsp_to_host_intr_trig(void); + +void acp_ack_intr_from_host(void); + +void acp_dsp_sw_intr_enable(void); + +void acp_intr_enable(void); + +void acp_intr_disable(void); + +#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/amd/renoir/include/platform/fw_scratch_mem.h b/src/platform/amd/renoir/include/platform/fw_scratch_mem.h new file mode 100644 index 000000000000..db779b8cfb03 --- /dev/null +++ b/src/platform/amd/renoir/include/platform/fw_scratch_mem.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni <anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifndef __EXT_SCRATCH_MEM_H__ +#define __EXT_SCRATCH_MEM_H__ + +#include <sof/lib/mailbox.h> + +/* MAX number of DMA descriptors */ +#define MAX_NUM_DMA_DESC_DSCR 64 +#define SCRATCH_REG_OFFSET 0x1250000 + +typedef struct acp_atu_grp_pte { + uint32_t low_part; + uint32_t high_part; +} __attribute__((packed, aligned(4))) acp_atu_grp_pte_t; + +typedef union acp_cfg_dma_trns_cnt { + struct{ + uint32_t trns_cnt : 19; + uint32_t reserved : 12; + uint32_t ioc : 1; + } bits; + unsigned int u32all; +} __attribute__((packed, aligned(4))) acp_cfg_dma_trns_cnt_t; + +typedef struct acp_config_dma_descriptor { + uint32_t src_addr; + uint32_t dest_addr; + acp_cfg_dma_trns_cnt_t trns_cnt; + uint32_t reserved; +} __attribute__((packed, aligned(4))) acp_cfg_dma_descriptor_t; + +typedef struct acp_config_dma_misc { + uint32_t channelstatus; + uint32_t channel; + uint32_t flag; +} __attribute__((packed, aligned(4))) acp_cfg_dma_misc_t; + +typedef struct acp_scratch_memory_config { + /* ACP out box buffer */ + uint8_t acp_outbox_buffer[MAILBOX_DSPBOX_SIZE]; + + /* ACP in box buffer */ + uint8_t acp_inbox_buffer[MAILBOX_HOSTBOX_SIZE]; + + /* ACP debug box buffer */ + uint8_t acp_debug_buffer[MAILBOX_DEBUG_SIZE]; + + /* ACP exception box buffer */ + uint8_t acp_except_buffer[MAILBOX_EXCEPTION_SIZE]; + + /* ACP stream buffer */ + uint8_t acp_stream_buffer[MAILBOX_STREAM_SIZE]; + + /* ACP trace buffer */ + uint8_t acp_trace_buffer[MAILBOX_TRACE_SIZE]; + + /* Host msg write flag */ + uint32_t acp_host_msg_write; + + /* Host ack flag */ + uint32_t acp_host_ack_write; + + /* Dsp msg write flag */ + uint32_t acp_dsp_msg_write; + + /* Dsp ack flag */ + uint32_t acp_dsp_ack_write; + + /* ACP pte1 table */ + acp_atu_grp_pte_t acp_atugrp1_pte[16]; + + /* ACP pte2 table */ + acp_atu_grp_pte_t acp_atugrp2_pte[16]; + + /* ACP pte3 table */ + acp_atu_grp_pte_t acp_atugrp3_pte[16]; + + /* ACP pte4 table */ + acp_atu_grp_pte_t acp_atugrp4_pte[16]; + + /* ACP pte5 table */ + acp_atu_grp_pte_t acp_atugrp5_pte[16]; + + /* ACP pte6 table */ + acp_atu_grp_pte_t acp_atugrp6_pte[16]; + + /* ACP pte7 table */ + acp_atu_grp_pte_t acp_atugrp7_pte[16]; + + /* ACP pte8 table */ + acp_atu_grp_pte_t acp_atugrp8_pte[16]; + + /* ACP DMA Descriptor */ + acp_cfg_dma_descriptor_t acp_cfg_dma_descriptor[MAX_NUM_DMA_DESC_DSCR]; + + /* Stream physical offset */ + uint32_t phy_offset[8]; + + /* Stream system memeory size */ + uint32_t syst_buff_size[8]; + + /* ACP transmit fifo buffer */ + uint8_t acp_transmit_fifo_buffer[768]; + + /* ACP receive fifo buffer */ + uint8_t acp_receive_fifo_buffer[768]; + + uint32_t reserve[]; +} __attribute__((packed, aligned(4))) acp_scratch_mem_config_t; + +#endif /* __EXT_SCRATCH_MEM_H__ */ + diff --git a/src/platform/amd/renoir/include/platform/lib/memory.h b/src/platform/amd/renoir/include/platform/lib/memory.h new file mode 100644 index 000000000000..4caeb0e30d06 --- /dev/null +++ b/src/platform/amd/renoir/include/platform/lib/memory.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni <anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> +#include <platform/chip_offset_byte.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN 64 + +/* physical DSP addresses */ + +#define IRAM_BASE 0x20000000 +#define IRAM_SIZE 0x40000 + +#define DRAM0_BASE 0x21000000 +#define DRAM0_SIZE 0x36000 +#define DRAM1_SIZE 0xA8000 + + +#define DMA0_BASE PU_REGISTER_BASE +#define DMA0_SIZE 0x4 + +/* DAI DMA register base address */ +#define DAI_BASE (PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR) +#define DAI_SIZE 0x4 +#define BT_TX_FIFO_OFFST (ACP_BT_TX_FIFOADDR - ACP_I2S_RX_RINGBUFADDR) +#define BT_RX_FIFO_OFFST (ACP_BT_RX_FIFOADDR - ACP_I2S_RX_RINGBUFADDR) + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +/* Log buffer base need to be updated properly, these are used in linker scripts */ +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* Stack configuration */ +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE +#define SOF_STACK_END (DRAM0_BASE + DRAM0_SIZE) +#define SOF_STACK_BASE (SOF_STACK_END + SOF_STACK_SIZE) + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE 0x22050000 +#define SRAM_OUTBOX_SIZE 0x400 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x400 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x400 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x400 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x400 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x400 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 48 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 4 +#define HEAP_RT_COUNT1024 12 +#define HEAP_RT_COUNT2048 12 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 64 +#define HEAP_SYS_RT_COUNT512 8 +#define HEAP_SYS_RT_COUNT1024 4 + +/* Heap configuration */ +#define HEAP_SYSTEM_BASE SOF_STACK_BASE +#define HEAP_SYSTEM_SIZE 0xe000 +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +#define HEAP_SYS_RUNTIME_SIZE (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE (0xF000) +#define HEAP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x7 +#define SOF_MEM_VECT_TEXT_SIZE 0x37 +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x400 +#define SOF_MEM_RESET_LIT_SIZE 0x8 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 +#define SOF_MEM_WIN_TEXT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN + +/* brief EDF task's default stack size in bytes */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +struct sof; + + +#define SHARED_DATA +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} +#endif + +#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/amd/renoir/include/platform/platform.h b/src/platform/amd/renoir/include/platform/platform.h new file mode 100644 index 000000000000..e3b7cd58ea03 --- /dev/null +++ b/src/platform/amd/renoir/include/platform/platform.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * Anup Kulkarni <anup.kulkarni@amd.com> + * Bala Kishore <balakishore.pati@amd.com> + */ +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <rtos/interrupt.h> +#include <rtos/clk.h> +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LEVEL_3 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 65536 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE 8192 + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +/* default dma trace channel */ +#define DMA_TRACE_CHANNEL 7 + +/* debug offset */ +#define ACP_SOF_FW_STATUS 0 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + acp_sw_intr_trig_t sw_intr_trig; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + + pscratch_mem_cfg->acp_dsp_msg_write = p; + mailbox_sw_reg_write(ACP_SOF_FW_STATUS, p); + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t) io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt trigger register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* + * brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/amd/renoir/lib/CMakeLists.txt b/src/platform/amd/renoir/lib/CMakeLists.txt new file mode 100644 index 000000000000..271a099cc6a9 --- /dev/null +++ b/src/platform/amd/renoir/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dai.c + dma.c + memory.c +) diff --git a/src/platform/amd/renoir/lib/clk.c b/src/platform/amd/renoir/lib/clk.c new file mode 100644 index 000000000000..dddc974f631a --- /dev/null +++ b/src/platform/amd/renoir/lib/clk.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 AMD. All rights reserved. +// +// Author: Basavaraj Hiregoudar<basavaraj.hiregoudar@amd.com> + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <rtos/sof.h> +#include <platform/chip_registers.h> + +static struct freq_table platform_cpu_freq[] = { + {200000000, 200000 }, +}; + +STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static int acp_reg_read_via_smn(uint32_t reg_offset, + uint32_t size) +{ + uint32_t reg_value; + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + /* Configuring the MP1 Aperture Id in SRB_client_config register */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), MP1_APERTURE_ID); + /* Configuring the base address of MP1 */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + /* dummy read to the to the address offset 0x3400 */ + /* Master config offset to access register outside of ACP */ + reg_value = (uint32_t)io_reg_read(PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + ACP_FIRST_REG_OFFSET)); + if (reg_value) + reg_value = 0; + /* reading status register to check above read request is completed or not */ + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + /* Waiting for status to be set to '0' */ + while (delay_cnt > 0) { + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) { + /* when status is '0' from above read the data from data register */ + return (uint32_t) io_reg_read(PU_REGISTER_BASE + ACP_SRBM_Client_RDDATA); + } + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + delay_cnt--; + } + return -1; +} + +static void acp_reg_write_via_smn(uint32_t reg_offset, + uint32_t value, uint32_t size) +{ + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + /* Configuring the MP1 Aperture Id in SRB_client_config register */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), MP1_APERTURE_ID); + /* Configuring the base address of MP1 */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + /* write to the address offset 0x3400 + * Master config offset to access register outside of ACP + */ + io_reg_write((PU_REGISTER_BASE + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + ACP_FIRST_REG_OFFSET)), value); + /* reading status register to check above read request is completed or not */ + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CYCLE_STS); + /* Waiting for status to be set to '0' */ + while (delay_cnt > 0) { + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return; + delay_cnt--; + } +} + +static void get_response_from_smu(void) +{ + uint32_t ret_value; + uint32_t count = 0; + + do { + ret_value = acp_reg_read_via_smn(MP1_SMN_C2PMSG_93, sizeof(int)); + if (count > 0x007fffff) + count = 0; + count++; + } while (ret_value == 0); +} + + +void acp_change_clock_notify(uint32_t clock_freq) +{ + /* converting Hz to Mhz */ + clock_freq = (clock_freq / 1000000); + /* Writing response zero to the response register + * so that it cab reset to '0' for further response + */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_93, + 0, sizeof(int)); + /* Writing clock frequency value in Mhz in the Argument register */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_85, + clock_freq, sizeof(int)); + /* Writing Message to message register */ + /* Writing Aclk change message to message register */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_69, + ACP_SMU_MSG_SET_ACLK, sizeof(int)); + /* Waiting for SMU response */ + get_response_from_smu(); +} + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + for (i = 0; i < PLATFORM_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/amd/renoir/lib/dai.c b/src/platform/amd/renoir/lib/dai.c new file mode 100644 index 000000000000..b104790716fc --- /dev/null +++ b/src/platform/amd/renoir/lib/dai.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/common.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +static struct dai acp_dmic_dai[] = { + { + .index = 0, + .plat_data = { + .base = DMA0_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 0, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DMA0_BASE, + .depth = 8, + .handshake = 1, + }, + }, + .drv = &acp_dmic_dai_driver, + }, +}; + +static struct dai spdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_spdai_driver, + }, + { + .index = 1, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_spdai_driver, + } +}; + +#ifdef ACP_BT_ENABLE +static struct dai btdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 2, + }, + }, + .drv = &acp_btdai_driver, + }, +}; +#endif + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_AMD_DMIC, + .dai_array = acp_dmic_dai, + .num_dais = ARRAY_SIZE(acp_dmic_dai) + }, + { + .type = SOF_DAI_AMD_SP, + .dai_array = spdai, + .num_dais = ARRAY_SIZE(spdai) + }, +#ifdef ACP_BT_ENABLE + { + .type = SOF_DAI_AMD_BT, + .dai_array = btdai, + .num_dais = ARRAY_SIZE(btdai) + }, +#endif +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(acp_dmic_dai); i++) + k_spinlock_init(&acp_dmic_dai[i].lock); + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(spdai); i++) + k_spinlock_init(&spdai[i].lock); +#ifdef ACP_BT_ENABLE + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(btdai); i++) + k_spinlock_init(&btdai[i].lock); +#endif + sof->dai_info = &lib_dai; + return 0; +} diff --git a/src/platform/amd/renoir/lib/dma.c b/src/platform/amd/renoir/lib/dma.c new file mode 100644 index 000000000000..e6c75bee3905 --- /dev/null +++ b/src/platform/amd/renoir/lib/dma.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/common.h> +#include <platform/fw_scratch_mem.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +#define ACP_ADDR_MASK 0x20000000 + +extern struct dma_ops acp_dma_ops; +extern struct dma_ops acp_dmic_dma_ops; +#ifdef ACP_BT_ENABLE +extern struct dma_ops acp_dai_bt_dma_ops; +#endif +extern struct dma_ops acp_dai_sp_dma_ops; + +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .plat_data = { + .id = DMA_ID_DMA0, + .dir = DMA_DIR_LMEM_TO_HMEM | DMA_DIR_HMEM_TO_LMEM, + .devs = DMA_DEV_HOST, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_DMIC, + .dir = DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_DMIC, + .caps = DMA_CAP_DMIC, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL4, + }, + .ops = &acp_dmic_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SP, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_sp_dma_ops, +}, +#ifdef ACP_BT_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_BT, + .caps = DMA_CAP_BT, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_bt_dma_ops, +}, +#endif +}; + +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)dma), + .num_dmas = ARRAY_SIZE(dma) +}; + +int acp_dma_init(struct sof *sof) +{ + int i; + uint32_t descr_base; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + + descr_base = (uint32_t)(&pscratch_mem_cfg->acp_cfg_dma_descriptor); + descr_base = (descr_base - ACP_ADDR_MASK); + /* configure dma descriptor base addr */ + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_BASE_ADDR), descr_base); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_MAX_NUM_DSCR), 0x1); + /* 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/amd/renoir/lib/memory.c b/src/platform/amd/renoir/lib/memory.c new file mode 100644 index 000000000000..9f16b1977f05 --- /dev/null +++ b/src/platform/amd/renoir/lib/memory.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 AMD +// +// Author:Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA | SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_HP, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/amd/renoir/platform.c b/src/platform/amd/renoir/platform.c new file mode 100644 index 000000000000..ad2fa16cf0a0 --- /dev/null +++ b/src/platform/amd/renoir/platform.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2021 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// Anup Kulkarni <anup.kulkarni@amd.com> +// Bala Kishore <balakishore.pati@amd.com> + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <rtos/interrupt.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <platform/chip_offset_byte.h> + +struct sof; +static const struct sof_ipc_fw_ready ready + __attribute__((section(".fw_ready"))) = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#ifdef DEBUG_BUILD + /* only added in debug for reproducability in releases */ + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_ACP_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_ACP_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + }, +}; + +static SHARED_DATA struct timer timer_shared = { + .id = TIMER0, + .irq = IRQ_NUM_TIMER0, +}; + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = platform_shared_get(&timer_shared, sizeof(timer_shared)); + sof->cpu_timers = sof->platform_timer; + + /* to view system memory */ + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + /* init low latency domains and schedulers */ + /* CONFIG_SYSTICK_PERIOD set as PLATFORM_DEFAULT_CLOCK */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, + PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + platform_timer_start(sof->platform_timer); + /*CONFIG_SYSTICK_PERIOD hardcoded as 200000*/ + sa_init(sof, 200000); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + /* init DMA */ + ret = acp_dma_init(sof); + if (ret < 0) + return -ENODEV; + /* Init DMA platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], + sizeof(sof->dma_info->dma_array), PLATFORM_DEFAULT_CLOCK, true); + sof->platform_dma_domain->full_sync = true; + scheduler_init_ll(sof->platform_dma_domain); + /* initialize the host IPC mechanisms */ + ipc_init(sof); + /* initialize the DAI mechanisms */ + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + sof->dmat->config.elem_array.elems = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct dma_sg_elem) * 1); + sof->dmat->config.elem_array.count = 1; + sof->dmat->config.elem_array.elems->dest = 0x03800000; + sof->dmat->config.elem_array.elems->size = 65536; + sof->dmat->config.scatter = 0; + dma_trace_init_complete(sof->dmat); +#endif + /* show heap status */ + heap_trace_all(1); + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + acp_sw_intr_trig_t swintrtrig; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_REGISTER_BASE + SCRATCH_REG_OFFSET); + mailbox_dspbox_write(0, &ready, sizeof(ready)); + pscratch_mem_cfg->acp_dsp_msg_write = 1; + acp_dsp_to_host_intr_trig(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), swintrtrig.u32all); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} +int platform_context_save(struct sof *sof) +{ + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} diff --git a/src/platform/amd/renoir/renoir.x.in b/src/platform/amd/renoir/renoir.x.in new file mode 100644 index 000000000000..34792f24dee9 --- /dev/null +++ b/src/platform/amd/renoir/renoir.x.in @@ -0,0 +1,560 @@ +/* + * Linker Script for AMD Renoir + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE, + len = IRAM_BASE + (XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE) + sof_sdram0 : + org = DRAM0_BASE, + len = DRAM0_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END, +sof_sdram1 : + org = HEAP_BUFFER_BASE + HEAP_BUFFER_SIZE, + len = DRAM1_SIZE- (HEAP_SYSTEM_SIZE +HEAP_SYS_RUNTIME_SIZE + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE + SOF_STACK_SIZE ) + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_iram_text_start_phdr PT_LOAD; + sof_sdram0_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_sdram1_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x44024000; +_memmap_cacheattr_wt_base = 0x11021000; +_memmap_cacheattr_bp_base = 0x22022000; +_memmap_cacheattr_unused_mask = 0x00F00FFF; +_memmap_cacheattr_wb_trapnull = 0x4422422F; +_memmap_cacheattr_wba_trapnull = 0x4422422F; +_memmap_cacheattr_wbna_trapnull = 0x25222222; +_memmap_cacheattr_wt_trapnull = 0x1122122F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0x44F24FFF; +_memmap_cacheattr_wt_strict = 0x11F21FFF; +_memmap_cacheattr_bp_strict = 0x22F22FFF; +_memmap_cacheattr_wb_allvalid = 0x44224222; +_memmap_cacheattr_wt_allvalid = 0x11221222; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .Level5InterruptVector.literal : ALIGN(4) + { + _Level5InterruptVector_literal_start = ABSOLUTE(.); + *(.Level5InterruptVector.literal) + _Level5InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .Level5InterruptVector.text : ALIGN(4) + { + _Level5InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level5InterruptVector.text)) + _Level5InterruptVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >sof_iram_text_start :sof_iram_text_start_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_iram_text_start :sof_iram_text_start_phdr + + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + } >sof_sdram0 :sof_sdram0_phdr + + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + +.sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + +} diff --git a/src/platform/amd/vangogh/CMakeLists.txt b/src/platform/amd/vangogh/CMakeLists.txt new file mode 100644 index 000000000000..ec909d60035f --- /dev/null +++ b/src/platform/amd/vangogh/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/amd/vangogh/include/arch/xtensa/config/core-isa.h b/src/platform/amd/vangogh/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..d6d5af62f9ea --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,672 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=7490; Build=0x8176c; Copyright (c) 1999-2019 Tensilica 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. +*/ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + +//depot/dev/Homewood/Xtensa/SWConfig/hal/core-common.h.tph#24 - edit change 444323 (text+ko) + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + +/*---------------------------------------------------------------------- + ISA + ---------------------------------------------------------------------- +*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 0 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 0 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 0 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 0 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 1 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 1 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6 or Q7 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1401000 /* sw version of this header */ +#define XCHAL_SW_MINOR_VERSION 1401000 /* same, with zeroed micro and patch */ +#define XCHAL_SW_MICRO_VERSION 1401000 /* same, with zeroed patch */ + +#define XCHAL_CORE_ID "ACP_5_0_001_PROD" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x0008176C /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2F3CBFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x22481571 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.0.9" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2700 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 9 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 270009 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_0 1 +#define XCHAL_HW_REL_LX7_0_9 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2700 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 9 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 270009 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2700 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 9 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 270009 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 6 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 6 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 131072 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 17 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 8 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 9 +#define XCHAL_DCACHE_SETWIDTH 9 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 8 +#define XCHAL_DCACHE_ACCESS_SIZE 8 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x20000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x20000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 1048576 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0xE0000000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0xE0000000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 1048576 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + + +#define XCHAL_HAVE_IDMA 0 + + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 9 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 5 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00000103 +#define XCHAL_INTLEVEL2_MASK 0x00000004 +#define XCHAL_INTLEVEL3_MASK 0x00000008 +#define XCHAL_INTLEVEL4_MASK 0x00000010 +#define XCHAL_INTLEVEL5_MASK 0x00000060 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000080 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00000103 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00000107 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0000010F +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0000011F +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0000017F +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0000017F +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x000001FF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 2 +#define XCHAL_INT3_LEVEL 3 +#define XCHAL_INT4_LEVEL 4 +#define XCHAL_INT5_LEVEL 5 +#define XCHAL_INT6_LEVEL 5 +#define XCHAL_INT7_LEVEL 7 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFFFE00 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00000138 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_NMI 0x00000080 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000002 +#define XCHAL_INTTYPE_MASK_TIMER 0x00000041 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000004 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 0 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 6 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 7 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 2 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL2_NUM 2 +#define XCHAL_INTLEVEL3_NUM 3 +#define XCHAL_INTLEVEL4_NUM 4 +#define XCHAL_INTLEVEL7_NUM 7 +/* (There are many interrupts each at level(s) 1, 5.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 3 /* (intlevel 3) */ +#define XCHAL_EXTINT1_NUM 4 /* (intlevel 4) */ +#define XCHAL_EXTINT2_NUM 5 /* (intlevel 5) */ +#define XCHAL_EXTINT3_NUM 7 /* (intlevel 7) */ +#define XCHAL_EXTINT4_NUM 8 /* (intlevel 1) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT3_EXTNUM 0 /* (intlevel 3) */ +#define XCHAL_INT4_EXTNUM 1 /* (intlevel 4) */ +#define XCHAL_INT5_EXTNUM 2 /* (intlevel 5) */ +#define XCHAL_INT7_EXTNUM 3 /* (intlevel 7) */ +#define XCHAL_INT8_EXTNUM 4 /* (intlevel 1) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ + +#define XCHAL_RESET_VECOFS 0x00000000 +#define XCHAL_RESET_VECTOR_VADDR 0x20000000 +#define XCHAL_RESET_VECTOR_PADDR 0x20000000 +#define XCHAL_USER_VECOFS 0x00000000 +#define XCHAL_USER_VECTOR_VADDR 0x20000740 +#define XCHAL_USER_VECTOR_PADDR 0x20000740 +#define XCHAL_KERNEL_VECOFS 0x00000000 +#define XCHAL_KERNEL_VECTOR_VADDR 0x20000700 +#define XCHAL_KERNEL_VECTOR_PADDR 0x20000700 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x200007C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x200007C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x20000400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x20000400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000000 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x20000580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x20000580 +#define XCHAL_INTLEVEL3_VECOFS 0x00000000 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x200005C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x200005C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000000 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x20000600 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x20000600 +#define XCHAL_INTLEVEL5_VECOFS 0x00000000 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x20000640 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x20000640 +#define XCHAL_INTLEVEL6_VECOFS 0x00000000 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x20000680 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x20000680 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000000 +#define XCHAL_NMI_VECTOR_VADDR 0x200006C0 +#define XCHAL_NMI_VECTOR_PADDR 0x200006C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 0 +#define XCHAL_MPU_ENTRIES 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 0 +#define XCHAL_MPU_ALIGN 0 + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/src/platform/amd/vangogh/include/arch/xtensa/config/core-matmap.h b/src/platform/amd/vangogh/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..711f34d9af39 --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,317 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=7490; Build=0x8176c; Copyright (c) 1999-2019 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + +#define XCHAL_CA_R (0xC0 | 0x40000000) +#define XCHAL_CA_RX (0xD0 | 0x40000000) +#define XCHAL_CA_RW (0xE0 | 0x40000000) +#define XCHAL_CA_RWX (0xF0 | 0x40000000) + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ +#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefine hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/amd/vangogh/include/arch/xtensa/config/specreg.h b/src/platform/amd/vangogh/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..ce2b5dc4d541 --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/config/specreg.h @@ -0,0 +1,108 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Homewood/ib.1/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=7490; Build=0x8176c; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define SCOMPARE1 12 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define ATOMCTL 99 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define EPC_7 183 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EPS_7 199 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define EXCSAVE_7 215 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define MISC_REG_0 244 +#define MISC_REG_1 245 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/amd/vangogh/include/arch/xtensa/config/system.h b/src/platform/amd/vangogh/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..cdc6537bfdc1 --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/config/system.h @@ -0,0 +1,256 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=7490; Build=0x8176c; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x60000000 +#define XSHAL_RAM_PADDR 0x60000000 +#define XSHAL_RAM_VSIZE 0x1FE00000 +#define XSHAL_RAM_PSIZE 0x1FE00000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x60000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x1FE00000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x40000000 +#define XSHAL_RAM_BYPASS_PADDR 0x40000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x1FE00000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xc0000000 +#define XSHAL_STL_INFO_LOCATION 0x4c + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x42224242 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x12221212 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x12221212 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0x4FFF4F4F /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0x1FFF1F1F /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0x1FFF1F1F /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0x2FFF2F2F /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x4222424F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x1222121F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x1222121F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x4FF2424F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x1FF2121F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x1FF2121F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0x2FF2222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000050 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 0 +#define XSHAL_RESET_VECTOR_VADDR 0x20000000 +#define XSHAL_RESET_VECTOR_PADDR 0x20000000 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x00000300 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x00000038 +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 +#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x00000038 +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/amd/vangogh/include/arch/xtensa/config/tie-asm.h b/src/platform/amd/vangogh/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..e03bace79955 --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,292 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=7490; Build=0x8176c; Copyright (c) 1999-2019 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + rsr.br \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.scompare1 \at1 // conditional store option + s32i \at1, \ptr, .Lxchal_ofs_+4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 // boolean option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.scompare1 \at1 // conditional store option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+24 + ae_salign64.i u0, \ptr, .Lxchal_ofs_+32 + ae_salign64.i u1, \ptr, .Lxchal_ofs_+40 + ae_salign64.i u2, \ptr, .Lxchal_ofs_+48 + ae_salign64.i u3, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, -128 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + rur.ae_ovf_sar \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+8 + rur.ae_bithead \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+12 + rur.ae_ts_fts_bu_bp \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_cw_sd_no \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_cbegin0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cend0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+28 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 192 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 192 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.ae_ovf_sar \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+12 + wur.ae_bithead \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ts_fts_bu_bp \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_cw_sd_no \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_cbegin0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cend0 \at1 // ureg 247 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+24 + addi.a \ptr, \ptr, 32 + ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 + ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 + ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 160 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 192 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/amd/vangogh/include/arch/xtensa/config/tie.h b/src/platform/amd/vangogh/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..3a5f1106d316 --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/config/tie.h @@ -0,0 +1,186 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=7490; Build=0x8176c; Copyright (c) 1999-2019 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 192 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 12 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 208 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 3 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 27 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x1015, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +/* (not available, must use XCHAL_BYTE0_FORMAT_LENGTHS for this processor) */ +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,5,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,5,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,5,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/amd/vangogh/include/arch/xtensa/tie/xt_datacache.h b/src/platform/amd/vangogh/include/arch/xtensa/tie/xt_datacache.h new file mode 100755 index 000000000000..7fcaa456ca16 --- /dev/null +++ b/src/platform/amd/vangogh/include/arch/xtensa/tie/xt_datacache.h @@ -0,0 +1,4 @@ +#ifndef __cstub_xt_datacache_h__ +#define __cstub_xt_datacache_h__ + +#endif diff --git a/src/platform/amd/vangogh/include/platform/chip_offset_byte.h b/src/platform/amd/vangogh/include/platform/chip_offset_byte.h new file mode 100644 index 000000000000..e6fda5f19b60 --- /dev/null +++ b/src/platform/amd/vangogh/include/platform/chip_offset_byte.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifndef _VANGOGH_OFFSET_HEADER +#define _VANGOGH_OFFSET_HEADER + +#define PU_REGISTER_BASE (0x9FD00000 - 0x01240000) +#define PU_SCRATCH_REG_BASE (0x9FF00000 - 0x01250000) + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x1240000 +#define ACP_DMA_DESC_BASE_ADDR 0x12400E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4 +#define ACP_DMA_CH_STS 0x12400E8 + +#define ACP_DMA_DSCR_STRT_IDX_0 0x1240020 +#define ACP_DMA_DSCR_CNT_0 0x1240040 +#define ACP_DMA_PRIO_0 0x1240060 + +/* Registers from ACP_MISC block */ +#define ACP_CLKMUX_SEL 0x124142C +#define ACP_EXTERNAL_INTR_ENB 0x1241800 +#define ACP_EXTERNAL_INTR_STAT 0x1241808 +#define ACP_DSP0_INTR_CNTL 0x124180C +#define ACP_DSP0_INTR_STAT 0x1241810 +#define ACP_DSP_SW_INTR_CNTL 0x1241814 +#define ACP_DSP_SW_INTR_STAT 0x1241818 +#define ACP_SW_INTR_TRIG 0x124181C +#define ACP_SMU_MAILBOX 0x1241820 +#define DSP_INTERRUPT_ROUTING_CTRL_0 0x1241824 +#define DSP_INTERRUPT_ROUTING_CTRL_1 0x1241828 +#define ACP_FUTURE_REG_ACLK_0 0x1241864 + +#define ACP_TIMER 0x1241878 +#define ACP_TIMER_CNTL 0x124187C +#define ACP_AXI2DAGB_SEM_0 0x1241884 + +#define ACP_SRBM_CLIENT_BASE_ADDR 0x1241BBC +#define ACP_SRBM_CLIENT_RDDATA 0x1241BC0 +#define ACP_SRBM_CYCLE_STS 0x1241BC4 +#define ACP_SRBM_CLIENT_CONFIG 0x1241BC8 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_I2S_RX_RINGBUFADDR 0x1242000 +#define ACP_I2S_RX_RINGBUFSIZE 0x1242004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x1242008 +#define ACP_I2S_RX_FIFOADDR 0x124200C +#define ACP_I2S_RX_FIFOSIZE 0x1242010 +#define ACP_I2S_RX_DMA_SIZE 0x1242014 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020 +#define ACP_I2S_TX_RINGBUFADDR 0x1242024 +#define ACP_I2S_TX_RINGBUFSIZE 0x1242028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x124202C +#define ACP_I2S_TX_FIFOADDR 0x1242030 +#define ACP_I2S_TX_FIFOSIZE 0x1242034 +#define ACP_I2S_TX_DMA_SIZE 0x1242038 +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044 +#define ACP_BT_RX_RINGBUFADDR 0x1242048 +#define ACP_BT_RX_RINGBUFSIZE 0x124204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x1242050 +#define ACP_BT_RX_FIFOADDR 0x1242054 +#define ACP_BT_RX_FIFOSIZE 0x1242058 +#define ACP_BT_RX_DMA_SIZE 0x124205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068 +#define ACP_BT_TX_RINGBUFADDR 0x124206C +#define ACP_BT_TX_RINGBUFSIZE 0x1242070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x1242074 +#define ACP_BT_TX_FIFOADDR 0x1242078 +#define ACP_BT_TX_FIFOSIZE 0x124207C +#define ACP_BT_TX_DMA_SIZE 0x1242080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C +#define ACP_HS_RX_RINGBUFADDR 0x1242090 +#define ACP_HS_RX_RINGBUFSIZE 0x1242094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x1242098 +#define ACP_HS_RX_FIFOADDR 0x124209C +#define ACP_HS_RX_FIFOSIZE 0x12420A0 +#define ACP_HS_RX_DMA_SIZE 0x12420A4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0 +#define ACP_HS_TX_RINGBUFADDR 0x12420B4 +#define ACP_HS_TX_RINGBUFSIZE 0x12420B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x12420BC +#define ACP_HS_TX_FIFOADDR 0x12420C0 +#define ACP_HS_TX_FIFOSIZE 0x12420C4 +#define ACP_HS_TX_DMA_SIZE 0x12420C8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x1242400 +#define ACP_I2STDM_IRER 0x1242404 +#define ACP_I2STDM_RXFRMT 0x1242408 +#define ACP_I2STDM_ITER 0x124240C +#define ACP_I2STDM_TXFRMT 0x1242410 +#define ACP_I2STDM0_MSTRCLKGEN 0x1242414 +#define ACP_I2STDM1_MSTRCLKGEN 0x1242418 +#define ACP_I2STDM2_MSTRCLKGEN 0x124241C +#define ACP_I2STDM_REFCLKGEN 0x1242420 + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x1242800 +#define ACP_BTTDM_IRER 0x1242804 +#define ACP_BTTDM_RXFRMT 0x1242808 +#define ACP_BTTDM_ITER 0x124280C +#define ACP_BTTDM_TXFRMT 0x1242810 + +/* Registers from ACP_HS_TDM block */ +#define ACP_HSTDM_IER 0x1242814 +#define ACP_HSTDM_IRER 0x1242818 +#define ACP_HSTDM_RXFRMT 0x124281C +#define ACP_HSTDM_ITER 0x1242820 +#define ACP_HSTDM_TXFRMT 0x1242824 + +/* Registers from ACP_WOV block */ +#define ACP_WOV_VAD_ENABLE 0x1242C00 +#define ACP_WOV_PDM_ENABLE 0x1242C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x1242C08 +#define ACP_WOV_RX_RINGBUFADDR 0x1242C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x1242C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x1242C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x1242C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x1242C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x1242C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x1242C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x1242C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x1242C2C +#define ACP_WOV_PDM_VAD_CTRL 0x1242C30 + +#define ACP_WOV_MISC_CTRL 0x1242C5C +#define ACP_WOV_CLK_CTRL 0x1242C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x1242C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x1242C68 + +#define MP1_SMN_C2PMSG_69 0x58A14 +#define MP1_SMN_C2PMSG_85 0x58A54 +#define MP1_SMN_C2PMSG_93 0x58A74 +#endif diff --git a/src/platform/amd/vangogh/include/platform/chip_registers.h b/src/platform/amd/vangogh/include/platform/chip_registers.h new file mode 100644 index 000000000000..f7e89d18dedb --- /dev/null +++ b/src/platform/amd/vangogh/include/platform/chip_registers.h @@ -0,0 +1,707 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#if !defined(_VANGOGH_REG_HEADER) +#define _VANGOGH_REG_HEADER + +typedef union acp_dma_cntl_0 { + struct { + unsigned int dmachrst:1; + unsigned int dmachrun:1; + unsigned int dmachiocen:1; + unsigned int :29; + } bits; +unsigned int u32all; +} acp_dma_cntl_0_t; + +typedef union acp_dma_ch_sts { + struct { + unsigned int dmachrunsts:8; + unsigned int :24; + } bits; +unsigned int u32all; +} acp_dma_ch_sts_t; + +typedef union acp_external_intr_enb { + struct { + unsigned int acpextintrenb:1; + unsigned int :31; + } bits; +unsigned int u32all; +} acp_external_intr_enb_t; + +typedef union acp_dsp0_intr_cntl { + struct { + unsigned int dmaiocmask:8; + unsigned int :8; + unsigned int wov_dma_intr_mask:1; + unsigned int :6; + unsigned int audio_buffer_int_mask:6; + unsigned int :3; + } bits; +unsigned int u32all; +} acp_dsp0_intr_cntl_t; + +typedef union acp_dsp0_intr_stat { + struct { + unsigned int dmaiocstat:8; + unsigned int :8; + unsigned int wov_dma_stat:1; + unsigned int :6; + unsigned int audio_buffer_int_stat:6; + unsigned int :3; + } bits; +unsigned int u32all; +} acp_dsp0_intr_stat_t; + +typedef union acp_dsp_sw_intr_cntl { + struct { + unsigned int :2; + unsigned int dsp0_to_host_intr_mask:1; + unsigned int :29; + } bits; +unsigned int u32all; +} acp_dsp_sw_intr_cntl_t; + +typedef union acp_dsp_sw_intr_stat { + struct { + unsigned int host_to_dsp0_intr1_stat:1; + unsigned int host_to_dsp0_intr2_stat:1; + unsigned int dsp0_to_host_intr_stat:1; + unsigned int host_to_dsp0_intr3_stat:1; + unsigned int :28; + } bits; +unsigned int u32all; +} acp_dsp_sw_intr_stat_t; + +typedef union acp_sw_intr_trig { + struct { + unsigned int trig_host_to_dsp0_intr1:1; + unsigned int :1; + unsigned int trig_dsp0_to_host_intr:1; + unsigned int :29; + } bits; +unsigned int u32all; +} acp_sw_intr_trig_t; + +typedef union dsp_interrupt_routing_ctrl_0 { + struct { + unsigned int dma_intr_level:3; + unsigned int :18; + unsigned int watchdog_intr_level:3; + unsigned int az_sw_i2s_intr_level:3; + unsigned int sha_intr_level:3; + unsigned int :2; + } bits; +unsigned int u32all; +} dsp_interrupt_routing_ctrl_0_t; + +typedef union dsp_interrupt_routing_ctrl_1 { + struct { + unsigned int host_to_dsp_intr1_level:3; + unsigned int host_to_dsp_intr2_level:3; + unsigned int src_intr_level:3; + unsigned int mailbox_intr_level:3; + unsigned int error_intr_level:3; + unsigned int wov_intr_level:3; + unsigned int :14; + } bits; + unsigned int u32all; +} dsp_interrupt_routing_ctrl_1_t; + +typedef union acp_i2s_rx_ringbufaddr { + struct { + unsigned int i2s_rx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_rx_ringbufaddr_t; + +typedef union acp_i2s_rx_ringbufsize { + struct { + unsigned int i2s_rx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_rx_ringbufsize_t; + +typedef union acp_i2s_rx_linkpositioncntr { + struct { + unsigned int i2s_rx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_rx_linkpositioncntr_t; + +typedef union acp_i2s_rx_fifoaddr { + struct { + unsigned int i2s_rx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_rx_fifoaddr_t; + +typedef union acp_i2s_rx_fifosize { + struct { + unsigned int i2s_rx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_rx_fifosize_t; + +typedef union acp_i2s_rx_dma_size { + struct { + unsigned int i2s_rx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_rx_dma_size_t; + +typedef union acp_i2s_rx_linearpositioncntr_high { + struct { + unsigned int i2s_rx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_high_t; + +typedef union acp_i2s_rx_linearpositioncntr_low { + struct { + unsigned int i2s_rx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_i2s_rx_linearpositioncntr_low_t; + +typedef union acp_i2s_rx_watermark_size { + struct { + unsigned int i2s_rx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_rx_intr_watermark_size_t; + +typedef union acp_i2s_tx_ringbufaddr { + struct { + unsigned int i2s_tx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_tx_ringbufaddr_t; + +typedef union acp_i2s_tx_ringbufsize { + struct { + unsigned int i2s_tx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_tx_ringbufsize_t; + +typedef union acp_i2s_tx_linkpositioncntr { + struct { + unsigned int i2s_tx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_tx_linkpositioncntr_t; + +typedef union acp_i2s_tx_fifoaddr { + struct { + unsigned int i2s_tx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_i2s_tx_fifoaddr_t; + +typedef union acp_i2s_tx_fifosize { + struct { + unsigned int i2s_tx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_tx_fifosize_t; + +typedef union acp_i2s_tx_dma_size { + struct { + unsigned int i2s_tx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_i2s_tx_dma_size_t; + +typedef union acp_i2s_tx_linearpositioncntr_high { + struct { + unsigned int i2s_tx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_hight_t; + +typedef union acp_i2s_tx_linearpositioncntr_low { + struct { + unsigned int i2s_tx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_i2s_tx_linearpositioncntr_low_t; + +typedef union acp_i2s_tx_intr_watermark_size { + struct { + unsigned int i2s_tx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_i2s_tx_intr_watermark_size_t; + +typedef union acp_bt_rx_ringbufaddr { + struct { + unsigned int bt_rx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_rx_ringbufaddr_t; + +typedef union acp_bt_rx_ringbufsize { + struct { + unsigned int bt_rx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_rx_ringbufsize_t; + +typedef union acp_bt_rx_linkpositioncntr { + struct { + unsigned int bt_rx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_rx_linkpositioncntr_t; + +typedef union acp_bt_rx_fifoaddr { + struct { + unsigned int bt_rx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_rx_fifoaddr_t; + +typedef union acp_bt_rx_fifosize { + struct { + unsigned int bt_rx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_rx_fifosize_t; + +typedef union acp_bt_rx_dma_size { + struct { + unsigned int bt_rx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_rx_dma_size_t; + +typedef union acp_bt_rx_linearpositioncntr_high { + struct { + unsigned int bt_rx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_bt_rx_linearpositioncntr_high_t; + +typedef union acp_bt_rx_linearpositioncntr_low { + struct { + unsigned int bt_rx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_bt_rx_linearpositioncntr_low_t; + +typedef union acp_bt_rx_intr_watermark_size { + struct { + unsigned int bt_rx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_rx_intr_watermark_size_t; + +typedef union acp_bt_tx_ringbufaddr { + struct { + unsigned int bt_tx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_tx_ringbufaddr_t; + +typedef union acp_bt_tx_ringbufsize { + struct { + unsigned int bt_tx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_tx_ringbufsize_t; + +typedef union acp_bt_tx_linkpositiontcntr { + struct { + unsigned int bt_tx_linkpositioncntr:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_tx_linkpositiontcntr_t; + +typedef union acp_bt_tx_fifoaddr { + struct { + unsigned int bt_tx_fifoaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_bt_tx_fifoaddr_t; + +typedef union acp_bt_tx_fifosize { + struct { + unsigned int bt_tx_fifosize:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_tx_fifosize_t; + +typedef union acp_bt_tx_dmasize { + struct { + unsigned int bt_tx_dma_size:13; + unsigned int :19; + } bits; +unsigned int u32all; +} acp_bt_tx_dmasize_t; + +typedef union acp_bt_tx_linearpositioncntr_high { + struct { + unsigned int bt_tx_linearpositioncntr_high:32; + } bits; +unsigned int u32all; +} acp_bt_tx_linearpositioncntr_high_t; + +typedef union acp_bt_tx_linearpositioncntr_low { + struct { + unsigned int bt_tx_linearpositioncntr_low:32; + } bits; +unsigned int u32all; +} acp_bt_tx_linearpositioncntr_low_t; + +typedef union acp_bt_tx_intr_watermark_size { + struct { + unsigned int bt_tx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_bt_tx_intr_watermark_size_t; + +typedef union acp_hs_rx_ringbufaddr { + struct { + unsigned int hs_rx_ringbufaddr :32; + } bits; + unsigned int u32all; +} acp_hs_rx_ringbufaddr_t; + +typedef union acp_hs_rx_ringbufsize { + struct { + unsigned int hs_rx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_ringbufsize_t; + +typedef union acp_hs_rx_linkpositioncntr { + struct { + unsigned int hs_rx_linkpositioncntr :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_linkpositioncntr_t; + +typedef union acp_hs_rx_fifoaddr { + struct { + unsigned int hs_rx_fifoaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_hs_rx_fifoaddr_t; + +typedef union acp_hs_rx_fifosize { + struct { + unsigned int hs_rx_fifosize :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_rx_fifosize_t; + +typedef union acp_hs_rx_dma_size { + struct { + unsigned int hs_rx_dma_size :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_rx_dma_size_t; + +typedef union acp_hs_rx_linearpositioncntr_high { + struct { + unsigned int hs_rx_linearpositioncntr_high :32; + } bits; + unsigned int u32all; +} acp_hs_rx_linearpositioncntr_high_t; + +typedef union acp_hs_rx_linearpositioncntr_low { + struct { + unsigned int hs_rx_linearpositioncntr_low :32; + } bits; + unsigned int u32all; +} acp_hs_rx_linearpositioncntr_low_t; + +typedef union acp_hs_rx_intr_watermark_size { + struct { + unsigned int hs_rx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_rx_intr_watermark_size_t; + +typedef union acp_hs_tx_ringbufaddr { + struct { + unsigned int hs_tx_ringbufaddr :32; + } bits; + unsigned int u32all; +} acp_hs_tx_ringbufaddr_t; + +typedef union acp_hs_tx_ringbufsize { + struct { + unsigned int hs_tx_ringbufsize :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_ringbufsize_t; + +typedef union acp_hs_tx_linkpositioncntr { + struct { + unsigned int hs_tx_linkpositioncntr :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_linkpositioncntr_t; + +typedef union acp_hs_tx_fifoaddr { + struct { + unsigned int hs_tx_fifoaddr :27; + unsigned int :5; + } bits; + unsigned int u32all; +} acp_hs_tx_fifoaddr_t; + +typedef union acp_hs_tx_fifosize { + struct { + unsigned int hs_tx_fifosize :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_tx_fifosize_t; + +typedef union acp_hs_tx_dma_size { + struct { + unsigned int hs_tx_dma_size :13; + unsigned int :19; + } bits; + unsigned int u32all; +} acp_hs_tx_dma_size_t; + +typedef union acp_hs_tx_linearpositioncntr_high { + struct { + unsigned int hs_tx_linearpositioncntr_high :32; + } bits; + unsigned int u32all; +} acp_hs_tx_linearpositioncntr_high_t; + +typedef union acp_hs_tx_linearpositioncntr_low { + struct { + unsigned int hs_tx_linearpositioncntr_low :32; + } bits; + unsigned int u32all; +} acp_hs_tx_linearpositioncntr_low_t; + +typedef union acp_hs_tx_intr_watermark_size { + struct { + unsigned int hs_tx_intr_watermark_size :26; + unsigned int :6; + } bits; + unsigned int u32all; +} acp_hs_tx_intr_watermark_size_t; + +typedef union acp_i2stdm_ier { + struct { + unsigned int i2stdm_ien:1; + unsigned int :31; + } bits; +unsigned int u32all; +} acp_i2stdm_ier_t; + +typedef union acp_i2stdm_irer { + struct { + unsigned int i2stdm_rx_en:1; + unsigned int i2stdm_rx_protocol_mode:1; + unsigned int i2stdm_rx_data_path_mode:1; + unsigned int i2stdm_rx_samplen:3; + unsigned int i2stdm_rx_status:1; + unsigned int :25; + + } bits; +unsigned int u32all; +} acp_i2stdm_irer_t; + +typedef union acp_i2stdm_iter { + struct { + unsigned int i2stdm_txen:1; + unsigned int i2stdm_tx_protocol_mode:1; + unsigned int i2stdm_tx_data_path_mode:1; + unsigned int i2stdm_tx_samp_len:3; + unsigned int i2stdm_tx_status:1; + unsigned int :25; + } bits; +unsigned int u32all; +} acp_i2stdm_iter_t; + +typedef union acp_bttdm_ier { + struct { + unsigned int bttdm_ien:1; + unsigned int :31; + } bits; +unsigned int u32all; +} acp_bttdm_ier_t; + +typedef union acp_bttdm_irer { + struct { + unsigned int bttdm_rx_en:1; + unsigned int bttdm_rx_protocol_mode:1; + unsigned int bttdm_rx_data_path_mode:1; + unsigned int bttdm_rx_samplen:3; + unsigned int bttdm_rx_status:1; + unsigned int :25; + } bits; +unsigned int u32all; +} acp_bttdm_irer_t; + +typedef union acp_bttdm_iter { + struct { + unsigned int bttdm_txen:1; + unsigned int bttdm_tx_protocol_mode:1; + unsigned int bttdm_tx_data_path_mode:1; + unsigned int bttdm_tx_samp_len:3; + unsigned int bttdm_tx_status:1; + unsigned int :25; + } bits; +unsigned int u32all; +} acp_bttdm_iter_t; + +typedef union acp_hstdm_ier { + struct { + unsigned int hstdm_ien :1; + unsigned int :31; + } bits; + unsigned int u32all; +} acp_hstdm_ier_t; + +typedef union acp_hstdm_irer { + struct { + unsigned int hstdm_rx_en :1; + unsigned int hstdm_rx_protocol_mode :1; + unsigned int hstdm_rx_data_path_mode :1; + unsigned int hstdm_rx_samplen :3; + unsigned int hstdm_rx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_hstdm_irer_t; + +typedef union acp_hstdm_iter { + struct { + unsigned int hstdm_txen :1; + unsigned int hstdm_tx_protocol_mode :1; + unsigned int hstdm_tx_data_path_mode :1; + unsigned int hstdm_tx_samp_len :3; + unsigned int hstdm_tx_status :1; + unsigned int :25; + } bits; + unsigned int u32all; +} acp_hstdm_iter_t; + +typedef union acp_wov_pdm_dma_enable { + struct { + unsigned int pdm_dma_en:1; + unsigned int pdm_dma_en_status:1; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_dma_enable_t; + +typedef union acp_wov_rx_ringbufaddr { + struct { + unsigned int rx_ringbufaddr:27; + unsigned int :5; + } bits; +unsigned int u32all; +} acp_wov_rx_ringbufaddr_t; + +typedef union acp_wov_rx_ringbufsize { + struct { + unsigned int rx_ringbufsize:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_wov_rx_ringbufsize_t; + +typedef union acp_wov_rx_intr_watermark_size { + struct { + unsigned int rx_intr_watermark_size:26; + unsigned int :6; + } bits; +unsigned int u32all; +} acp_wov_rx_intr_watermark_size_t; + +typedef union acp_wov_pdm_no_of_channels { + struct { + unsigned int pdm_no_of_channels:2; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_no_of_channels_t; + +typedef union acp_wov_pdm_decimation_factor { + struct { + unsigned int pdm_decimation_factor:2; + unsigned int :30; + } bits; +unsigned int u32all; +} acp_wov_pdm_decimation_factor_t; +typedef union acp_wov_misc_ctrl { + struct { + unsigned int :3; + unsigned int pcm_data_shift_ctrl:2; + unsigned int :27; + } bits; +unsigned int u32all; +} acp_wov_misc_ctrl_t; + +typedef union acp_wov_clk_ctrl { + struct { + unsigned int brm_clk_ctrl:4; + unsigned int pdm_vad_clkdiv:2; + unsigned int :26; + } bits; +unsigned int u32all; +} acp_wov_clk_ctrl_t; + +typedef union acp_srbm_cycle_sts { + struct { + unsigned int srbm_clients_sts:1; + unsigned int :7; + + } bits; +unsigned int u32all; +} acp_srbm_cycle_sts_t; + +#endif + diff --git a/src/platform/amd/vangogh/include/platform/drivers/interrupt.h b/src/platform/amd/vangogh/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..6197427cdf92 --- /dev/null +++ b/src/platform/amd/vangogh/include/platform/drivers/interrupt.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <rtos/bit.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> + +#define PLATFORM_IRQ_HW_NUM 9 + +#define PLATFORM_IRQ_FIRST_CHILD 5 + +#define PLATFORM_IRQ_CHILDREN 32 + +/* IRQ numbers - wrt Tensilica DSP */ +#define IRQ_NUM_SOFTWARE0 1 /* level 1 */ + +#define IRQ_NUM_TIMER0 0 /* level 1 */ + +#define IRQ_NUM_EXT_LEVEL3 3 /* level 1 */ + +#define IRQ_NUM_TIMER1 6 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL4 4 /* level 2 */ + +#define IRQ_NUM_EXT_LEVEL5 5 /* level 3 */ + +/* IRQ Masks */ +#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) + +#define IRQ_MASK_TIMER0 BIT(IRQ_NUM_TIMER0) + +#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) + +#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) + +#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) + +#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) + +#define HOST_TO_DSP_INTR 0x1 + +#define _XTSTR(x) # x + +#define XTSTR(x) _XTSTR(x) + +/* Enabling flag */ +#define INTERRUPT_ENABLE 1 + +/* Clearing flag */ +#define INTERRUPT_CLEAR 0 + +/* Disable flag */ +#define INTERRUPT_DISABLE 0 + +/* brief Tensilica Interrupt Levels. */ +typedef enum { + acp_interrupt_level_3 = 0, + + acp_interrupt_level_4, + + acp_interrupt_level_5, + + acp_interrupt_level_nmi, + + acp_interrupt_level_max +} artos_interrupt_levels_t; + +/* brief Tensilica timer control */ +typedef enum { + acp_timer_cntl_disable = 0, + + acp_timer_cntl_oneshot, + + acp_timer_cntl_periodic, + + acp_timer_cntl_max +} artos_timer_control_t; + +/* Disable Host to DSP interrupt */ +void acp_dsp_sw_intr_disable(void); + +void acp_intr_route(void); + +void acp_dsp_to_host_intr_trig(void); + +void acp_ack_intr_from_host(void); + +void acp_dsp_sw_intr_enable(void); + +void acp_intr_enable(void); + +void acp_intr_disable(void); + +#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/amd/vangogh/include/platform/fw_scratch_mem.h b/src/platform/amd/vangogh/include/platform/fw_scratch_mem.h new file mode 100644 index 000000000000..9890110540ef --- /dev/null +++ b/src/platform/amd/vangogh/include/platform/fw_scratch_mem.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD. All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifndef __EXT_SCRATCH_MEM_H__ +#define __EXT_SCRATCH_MEM_H__ + +#include <sof/lib/mailbox.h> + +/* MAX number of DMA descriptors */ +#define MAX_NUM_DMA_DESC_DSCR 64 +#define SCRATCH_REG_OFFSET 0x1250000 + +typedef struct acp_atu_grp_pte { + uint32_t low_part; + uint32_t high_part; +} __attribute__((packed, aligned(4))) acp_atu_grp_pte_t; + +typedef union acp_cfg_dma_trns_cnt { + struct{ + uint32_t trns_cnt : 19; + uint32_t reserved : 12; + uint32_t ioc : 1; + } bits; + unsigned int u32all; +} __attribute__((packed, aligned(4))) acp_cfg_dma_trns_cnt_t; + +typedef struct acp_config_dma_descriptor { + uint32_t src_addr; + uint32_t dest_addr; + acp_cfg_dma_trns_cnt_t trns_cnt; + uint32_t reserved; +} __attribute__((packed, aligned(4))) acp_cfg_dma_descriptor_t; + +typedef struct acp_config_dma_misc { + uint32_t channelstatus; + uint32_t channel; + uint32_t flag; +} __attribute__((packed, aligned(4))) acp_cfg_dma_misc_t; + +typedef struct acp_scratch_memory_config { + /* ACP out box buffer */ + uint8_t acp_outbox_buffer[MAILBOX_DSPBOX_SIZE]; + + /* ACP in box buffer */ + uint8_t acp_inbox_buffer[MAILBOX_HOSTBOX_SIZE]; + + /* ACP debug box buffer */ + uint8_t acp_debug_buffer[MAILBOX_DEBUG_SIZE]; + + /* ACP exception box buffer */ + uint8_t acp_except_buffer[MAILBOX_EXCEPTION_SIZE]; + + /* ACP stream buffer */ + uint8_t acp_stream_buffer[MAILBOX_STREAM_SIZE]; + + /* ACP trace buffer */ + uint8_t acp_trace_buffer[MAILBOX_TRACE_SIZE]; + + /* Host msg write flag */ + uint32_t acp_host_msg_write; + + /* Host ack flag */ + uint32_t acp_host_ack_write; + + /* Dsp msg write flag */ + uint32_t acp_dsp_msg_write; + + /* Dsp ack flag */ + uint32_t acp_dsp_ack_write; + + /* ACP pte1 table */ + acp_atu_grp_pte_t acp_atugrp1_pte[16]; + + /* ACP pte2 table */ + acp_atu_grp_pte_t acp_atugrp2_pte[16]; + + /* ACP pte3 table */ + acp_atu_grp_pte_t acp_atugrp3_pte[16]; + + /* ACP pte4 table */ + acp_atu_grp_pte_t acp_atugrp4_pte[16]; + + /* ACP pte5 table */ + acp_atu_grp_pte_t acp_atugrp5_pte[16]; + + /* ACP pte6 table */ + acp_atu_grp_pte_t acp_atugrp6_pte[16]; + + /* ACP pte7 table */ + acp_atu_grp_pte_t acp_atugrp7_pte[16]; + + /* ACP pte8 table */ + acp_atu_grp_pte_t acp_atugrp8_pte[16]; + + /* ACP DMA Descriptor */ + acp_cfg_dma_descriptor_t acp_cfg_dma_descriptor[MAX_NUM_DMA_DESC_DSCR]; + + /* Stream physical offset */ + uint32_t phy_offset[8]; + + /* Stream system memeory size */ + uint32_t syst_buff_size[8]; + + /* Fifo buffers are not part of scratch memory on Vangogh */ + /* Added fifo members to align with Driver structure */ + /* ACP transmit fifo buffers */ + uint8_t acp_transmit_fifo_buffer[768] __attribute__((aligned(64))); + uint8_t acp_transmit_hs_fifo_buffer[768] __attribute__((aligned(64))); + + /* ACP receive fifo buffer */ + uint8_t acp_receive_fifo_buffer[768] __attribute__((aligned(64))); + + uint32_t reserve[]; +} __attribute__((packed, aligned(4))) acp_scratch_mem_config_t; + +#endif /* __EXT_SCRATCH_MEM_H__ */ + diff --git a/src/platform/amd/vangogh/include/platform/lib/memory.h b/src/platform/amd/vangogh/include/platform/lib/memory.h new file mode 100644 index 000000000000..6e0b768cc57a --- /dev/null +++ b/src/platform/amd/vangogh/include/platform/lib/memory.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> +#include <platform/chip_offset_byte.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN 64 + +/* physical DSP addresses */ +#define IRAM_BASE 0x20000000 +#define IRAM_SIZE 0x40000 + +#define DRAM0_BASE 0xE0000000 +#define DRAM0_SIZE 0x80000 +#define DRAM1_SIZE 0x80000 + +#define DMA0_BASE PU_REGISTER_BASE +#define DMA0_SIZE 0x4 + +/* DAI DMA register base address */ +#define DAI_BASE (PU_REGISTER_BASE + ACP_I2S_RX_RINGBUFADDR) +#define DAI_SIZE 0x4 +#define BT_TX_FIFO_OFFST (ACP_BT_TX_FIFOADDR - ACP_I2S_RX_RINGBUFADDR) +#define BT_RX_FIFO_OFFST (ACP_BT_RX_FIFOADDR - ACP_I2S_RX_RINGBUFADDR) + +#define HS_TX_FIFO_OFFST (ACP_HS_TX_FIFOADDR - ACP_I2S_RX_RINGBUFADDR) +#define HS_RX_FIFO_OFFST (ACP_HS_RX_FIFOADDR - ACP_I2S_RX_RINGBUFADDR) + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +/* Log buffer base need to be updated properly, these are used in linker scripts */ +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* Stack configuration */ +#define SOF_STACK_SIZE 0x1000 +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE +#define SOF_STACK_END (DRAM0_BASE + DRAM0_SIZE) +#define SOF_STACK_BASE (SOF_STACK_END + SOF_STACK_SIZE) + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE 0x9FF00000 +#define SRAM_OUTBOX_SIZE 0x400 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x400 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x400 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x400 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x400 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x400 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 48 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 4 +#define HEAP_RT_COUNT1024 13 +#define HEAP_RT_COUNT2048 24 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 64 +#define HEAP_SYS_RT_COUNT512 22 /*vangogh-arch*/ +#define HEAP_SYS_RT_COUNT1024 30 + +/* Heap configuration */ +#define HEAP_SYSTEM_BASE (SOF_STACK_BASE + SOF_STACK_SIZE) +#define HEAP_SYSTEM_SIZE 0x14400 +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +#define HEAP_SYS_RUNTIME_SIZE (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE (0x15400) +#define HEAP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x7 +#define SOF_MEM_VECT_TEXT_SIZE 0x37 +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x400 +#define SOF_MEM_RESET_LIT_SIZE 0x8 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 +#define SOF_MEM_WIN_TEXT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define is_uncached(address) 0 + +#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN + +/* brief EDF task's default stack size in bytes */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +struct sof; + + +#define SHARED_DATA +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} +#endif + +#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/amd/vangogh/include/platform/platform.h b/src/platform/amd/vangogh/include/platform/platform.h new file mode 100644 index 000000000000..efdda9d6b446 --- /dev/null +++ b/src/platform/amd/vangogh/include/platform/platform.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 AMD.All rights reserved. + * + * Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> + * SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + */ +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <rtos/interrupt.h> +#include <rtos/clk.h> +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> +#include <platform/fw_scratch_mem.h> +#include <platform/chip_registers.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LEVEL_3 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 65536 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE 8192 + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +/* default dma trace channel */ +#define DMA_TRACE_CHANNEL 7 + +/* debug offset */ +#define ACP_SOF_FW_STATUS 0 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + acp_sw_intr_trig_t sw_intr_trig; + + mailbox_sw_reg_write(ACP_SOF_FW_STATUS, p); + /* Read the Software Interrupt controller register and update */ + sw_intr_trig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + sw_intr_trig.bits.trig_dsp0_to_host_intr = INTERRUPT_ENABLE; + /* Write the Software Interrupt trigger register */ + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), sw_intr_trig.u32all); +} + +/* + * brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/amd/vangogh/lib/CMakeLists.txt b/src/platform/amd/vangogh/lib/CMakeLists.txt new file mode 100644 index 000000000000..271a099cc6a9 --- /dev/null +++ b/src/platform/amd/vangogh/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dai.c + dma.c + memory.c +) diff --git a/src/platform/amd/vangogh/lib/clk.c b/src/platform/amd/vangogh/lib/clk.c new file mode 100644 index 000000000000..25f7befed373 --- /dev/null +++ b/src/platform/amd/vangogh/lib/clk.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 AMD. All rights reserved. +// +// Author: Basavaraj Hiregoudar<basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <platform/chip_registers.h> + +const struct freq_table platform_cpu_freq[] = { + {600000000, 600000 }, +}; + +STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static int acp_reg_read_via_smn(uint32_t reg_offset, + uint32_t size) +{ + uint32_t reg_value; + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + /* Configuring the MP1 Aperture Id in SRB_client_config register */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + /* Configuring the base address of MP1 */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + /* dummy read to the to the address offset 0x3400 */ + /* Master config offset to access register outside of ACP */ + reg_value = (uint32_t)io_reg_read(PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - + region_start_addr + ACP_FIRST_REG_OFFSET)); + if (reg_value) + reg_value = 0; + /* reading status register to check above read request is completed or not */ + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + /* Waiting for status to be set to '0' */ + while (delay_cnt > 0) { + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) { + /* when status is '0' from above read the data from data register */ + return (uint32_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CLIENT_RDDATA); + } + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + delay_cnt--; + } + return -1; +} + +static void acp_reg_write_via_smn(uint32_t reg_offset, + uint32_t value, uint32_t size) +{ + uint32_t delay_cnt = 10000; + uint32_t smn_client_base_addr = (reg_offset >> 10); + uint32_t region_start_addr = (smn_client_base_addr << 10); + uint32_t apertureid = ((reg_offset >> 20) & 0xFFF); + acp_srbm_cycle_sts_t acp_srbm_cycle_sts; + + /* Configuring the MP1 Aperture Id in SRB_client_config register */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_CONFIG), apertureid); + /* Configuring the base address of MP1 */ + io_reg_write((PU_REGISTER_BASE + ACP_SRBM_CLIENT_BASE_ADDR), smn_client_base_addr); + /* write to the address offset 0x3400 + * Master config offset to access register outside of ACP + */ + io_reg_write((PU_REGISTER_BASE + + (ACP_MASTER_REG_ACCESS_ADDRESS + reg_offset - region_start_addr + + ACP_FIRST_REG_OFFSET)), value); + /* reading status register to check above read request is completed or not */ + acp_srbm_cycle_sts = + (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + ACP_SRBM_CYCLE_STS); + /* Waiting for status to be set to '0' */ + while (delay_cnt > 0) { + acp_srbm_cycle_sts = (acp_srbm_cycle_sts_t)io_reg_read(PU_REGISTER_BASE + + ACP_SRBM_CYCLE_STS); + if (!acp_srbm_cycle_sts.bits.srbm_clients_sts) + return; + delay_cnt--; + } +} + +static void get_response_from_smu(void) +{ + uint32_t ret_value; + uint32_t count = 0; + + do { + ret_value = acp_reg_read_via_smn(MP1_SMN_C2PMSG_93, sizeof(int)); + if (count > 0x007fffff) + count = 0; + count++; + } while (ret_value == 0); +} + +void acp_change_clock_notify(uint32_t clock_freq) +{ + /* converting Hz to Mhz */ + clock_freq = (clock_freq / 1000000); + /* Writing response zero to the response register + * so that it cab reset to '0' for further response + */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_93, + 0, sizeof(int)); + /* Writing clock frequency value in Mhz in the Argument register */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_85, + clock_freq, sizeof(int)); + /* Writing Message to message register */ + /* Writing Aclk change message to message register */ + acp_reg_write_via_smn(MP1_SMN_C2PMSG_69, + ACP_SMU_MSG_SET_ACLK, sizeof(int)); + /* Waiting for SMU response */ + get_response_from_smu(); +} + +void platform_clock_init(struct sof *sof) +{ + int i = 0; + + sof->clocks = platform_clocks_info; + 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, + }; + } + acp_change_clock_notify(600000000); +} diff --git a/src/platform/amd/vangogh/lib/dai.c b/src/platform/amd/vangogh/lib/dai.c new file mode 100644 index 000000000000..d47eee304ab4 --- /dev/null +++ b/src/platform/amd/vangogh/lib/dai.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +static struct dai hsdai[] = { + { + .index = 1, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + HS_TX_FIFO_OFFST, + .depth = 8, + .handshake = 1, + }, + }, + .drv = &acp_hsdai_driver, + }, +}; + +static struct dai spdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 5, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 4, + }, + }, + .drv = &acp_spdai_driver, + } +}; + +#ifdef ACP_BT_ENABLE +static struct dai btdai[] = { + { + .index = 0, + .plat_data = { + .base = DAI_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = DAI_BASE + BT_TX_FIFO_OFFST, + .depth = 8, + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = DAI_BASE + BT_RX_FIFO_OFFST, + .depth = 8, + .handshake = 2, + }, + }, + .drv = &acp_btdai_driver, + }, +}; +#endif + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_AMD_HS, + .dai_array = hsdai, + .num_dais = ARRAY_SIZE(hsdai) + }, + { + .type = SOF_DAI_AMD_SP, + .dai_array = spdai, + .num_dais = ARRAY_SIZE(spdai) + }, +#ifdef ACP_BT_ENABLE + { + .type = SOF_DAI_AMD_BT, + .dai_array = btdai, + .num_dais = ARRAY_SIZE(btdai) + }, +#endif +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(hsdai); i++) + k_spinlock_init(&hsdai[i].lock); + for (i = 0; i < ARRAY_SIZE(spdai); i++) + k_spinlock_init(&spdai[i].lock); +#ifdef ACP_BT_ENABLE + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(btdai); i++) + k_spinlock_init(&btdai[i].lock); +#endif + sof->dai_info = &lib_dai; + return 0; +} diff --git a/src/platform/amd/vangogh/lib/dma.c b/src/platform/amd/vangogh/lib/dma.c new file mode 100644 index 000000000000..cd764542dcfa --- /dev/null +++ b/src/platform/amd/vangogh/lib/dma.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <platform/fw_scratch_mem.h> +#include <sof/drivers/acp_dai_dma.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +#define ACP_ADDR_MASK 0x9DEB0000 + +extern struct dma_ops acp_dma_ops; +#ifdef ACP_BT_ENABLE +extern struct dma_ops acp_dai_bt_dma_ops; +#endif +extern struct dma_ops acp_dai_sp_dma_ops; +extern struct dma_ops acp_dai_hs_dma_ops; + +SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .plat_data = { + .id = DMA_ID_DMA0, + .dir = DMA_DIR_LMEM_TO_HMEM | DMA_DIR_HMEM_TO_LMEM, + .devs = DMA_DEV_HOST, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_HS, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_HS, + .caps = DMA_CAP_HS, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dai_hs_dma_ops, +}, +{ + .plat_data = { + .id = DMA_ID_DAI_SP, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_SP, + .caps = DMA_CAP_SP, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + .irq_name = "irqsteer1", + }, + .ops = &acp_dai_sp_dma_ops, +}, + +#ifdef ACP_BT_ENABLE +{ + .plat_data = { + .id = DMA_ID_DAI, + .dir = DMA_DIR_DEV_TO_MEM | DMA_DIR_MEM_TO_DEV, + .devs = DMA_DEV_BT, + .caps = DMA_CAP_BT, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .irq = IRQ_NUM_EXT_LEVEL5, + }, + .ops = &acp_dai_bt_dma_ops, +}, +#endif +}; + +const struct dma_info lib_dma = { + .dma_array = dma, + .num_dmas = ARRAY_SIZE(dma) +}; + +int acp_dma_init(struct sof *sof) +{ + int i; + uint32_t descr_base; + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + descr_base = (uint32_t)(&pscratch_mem_cfg->acp_cfg_dma_descriptor); + descr_base = (descr_base - ACP_ADDR_MASK); + /* configure dma descriptor base addr */ + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_BASE_ADDR), descr_base); + io_reg_write((PU_REGISTER_BASE + ACP_DMA_DESC_MAX_NUM_DSCR), 0x1); + + /* 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/amd/vangogh/lib/memory.c b/src/platform/amd/vangogh/lib/memory.c new file mode 100644 index 000000000000..d4a0ab144706 --- /dev/null +++ b/src/platform/amd/vangogh/lib/memory.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 AMD. All rights reserved. +// +// Author:Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA | SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_HP, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = &memmap; +} diff --git a/src/platform/amd/vangogh/platform.c b/src/platform/amd/vangogh/platform.c new file mode 100644 index 000000000000..300239a023be --- /dev/null +++ b/src/platform/amd/vangogh/platform.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +//Copyright(c) 2023 AMD. All rights reserved. +// +//Author: Basavaraj Hiregoudar <basavaraj.hiregoudar@amd.com> +// SaiSurya, Ch <saisurya.chakkaveeravenkatanaga@amd.com> + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <rtos/interrupt.h> +#include <sof/drivers/acp_dai_dma.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <platform/chip_offset_byte.h> + +struct sof; +static const struct sof_ipc_fw_ready ready + __attribute__((section(".fw_ready"))) = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#ifdef DEBUG_BUILD + /* only added in debug for reproducability in releases */ + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_ACP_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_ACP_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + }, +}; + +static SHARED_DATA struct timer timer = { + .id = TIMER0, + .irq = IRQ_NUM_TIMER0, +}; + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = &timer; + sof->cpu_timers = &timer; + /* to view system memory */ + interrupt_init(sof); + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + /* init low latency domains and schedulers */ + /* CONFIG_SYSTICK_PERIOD set as PLATFORM_DEFAULT_CLOCK */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, + PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + platform_timer_start(sof->platform_timer); + /*CONFIG_SYSTICK_PERIOD hardcoded as 200000*/ + sa_init(sof, 200000); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + /* init DMA */ + ret = acp_dma_init(sof); + if (ret < 0) + return -ENODEV; + /* Init DMA platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], + sizeof(sof->dma_info->dma_array), + PLATFORM_DEFAULT_CLOCK, true); + scheduler_init_ll(sof->platform_dma_domain); + /* initialize the host IPC mechanisms */ + ipc_init(sof); + /* initialize the DAI mechanisms */ + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + sof->dmat->config.elem_array.elems = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct dma_sg_elem) * 1); + sof->dmat->config.elem_array.count = 1; + sof->dmat->config.elem_array.elems->dest = 0x03800000; + sof->dmat->config.elem_array.elems->size = 65536; + sof->dmat->config.scatter = 0; + dma_trace_init_complete(sof->dmat); +#endif + /* show heap status */ + heap_trace_all(1); + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + acp_sw_intr_trig_t swintrtrig; + + volatile acp_scratch_mem_config_t *pscratch_mem_cfg = + (volatile acp_scratch_mem_config_t *)(PU_SCRATCH_REG_BASE + SCRATCH_REG_OFFSET); + mailbox_dspbox_write(0, &ready, sizeof(ready)); + mailbox_dspbox_write(sizeof(ready), &xsram_window.window, sizeof(xsram_window.window)); + pscratch_mem_cfg->acp_dsp_msg_write = 1; + acp_dsp_to_host_intr_trig(); + /* Configures the trigger bit in ACP_DSP_SW_INTR_TRIG register */ + swintrtrig = (acp_sw_intr_trig_t)io_reg_read(PU_REGISTER_BASE + ACP_SW_INTR_TRIG); + swintrtrig.bits.trig_dsp0_to_host_intr = INTERRUPT_DISABLE; + io_reg_write((PU_REGISTER_BASE + ACP_SW_INTR_TRIG), swintrtrig.u32all); + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} diff --git a/src/platform/amd/vangogh/vangogh.x.in b/src/platform/amd/vangogh/vangogh.x.in new file mode 100644 index 000000000000..860bf21987fb --- /dev/null +++ b/src/platform/amd/vangogh/vangogh.x.in @@ -0,0 +1,577 @@ +/* + * Linker Script for AMD Vangogh + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_WINDOW_VECTORS_VADDR, //XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int6_lit : + org = XCHAL_INTLEVEL6_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int6_text : + org = XCHAL_INTLEVEL6_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + + vector_int7_lit : + org = XCHAL_INTLEVEL7_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int7_text : + org = XCHAL_INTLEVEL7_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE, + len = IRAM_BASE + (XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE) + sof_sdram0 : + org = DRAM0_BASE, + len = DRAM0_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_BASE, + len = SOF_STACK_BASE - SOF_STACK_END, +sof_sdram1 : + org = HEAP_BUFFER_BASE + HEAP_BUFFER_SIZE, + len = DRAM1_SIZE- (HEAP_SYSTEM_SIZE +HEAP_SYS_RUNTIME_SIZE + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE + SOF_STACK_SIZE ) + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_int6_text_phdr PT_LOAD; + vector_int6_lit_phdr PT_LOAD; + vector_int7_text_phdr PT_LOAD; + vector_int7_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_iram_text_start_phdr PT_LOAD; + sof_sdram0_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_sdram1_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_WINDOW_VECTORS_VADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x44024000; +_memmap_cacheattr_wt_base = 0x11021000; +_memmap_cacheattr_bp_base = 0x22022000; +_memmap_cacheattr_unused_mask = 0x00F00FFF; +_memmap_cacheattr_wb_trapnull = 0x4422422F; +_memmap_cacheattr_wba_trapnull = 0x4422422F; +_memmap_cacheattr_wbna_trapnull = 0x25222222; +_memmap_cacheattr_wt_trapnull = 0x1122122F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0x44F24FFF; +_memmap_cacheattr_wt_strict = 0x11F21FFF; +_memmap_cacheattr_bp_strict = 0x22F22FFF; +_memmap_cacheattr_wb_allvalid = 0x44224222; +_memmap_cacheattr_wt_allvalid = 0x11221222; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .Level5InterruptVector.literal : ALIGN(4) + { + _Level5InterruptVector_literal_start = ABSOLUTE(.); + *(.Level5InterruptVector.literal) + _Level5InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .Level5InterruptVector.text : ALIGN(4) + { + _Level5InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level5InterruptVector.text)) + _Level5InterruptVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int6_lit :vector_int6_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int6_text :vector_int6_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int7_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int7_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >sof_iram_text_start :sof_iram_text_start_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_iram_text_start :sof_iram_text_start_phdr + + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + } >sof_sdram0 :sof_sdram0_phdr + + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + +.sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr + +} diff --git a/src/platform/apollolake/CMakeLists.txt b/src/platform/apollolake/CMakeLists.txt deleted file mode 100644 index 3fad0567edcb..000000000000 --- a/src/platform/apollolake/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(lib) - -add_executable(boot_module boot_module.c) -add_executable(base_module base_module.c) - -target_link_libraries(boot_module sof_options) -target_link_libraries(base_module sof_options) diff --git a/src/platform/apollolake/apollolake.x.in b/src/platform/apollolake/apollolake.x.in deleted file mode 100644 index e7ebbd14b613..000000000000 --- a/src/platform/apollolake/apollolake.x.in +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Linker Script for Apololake. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ -#if defined(CONFIG_SKYLAKE) || defined(CONFIG_KABYLAKE) - vector_reset_text : - org = HP_SRAM_VECBASE_RESET, - len = HP_SRAM_RESET_TEXT_SIZE - vector_reset_lit : - org = HP_SRAM_VECBASE_RESET + HP_SRAM_RESET_TEXT_SIZE, - len = HP_SRAM_RESET_LIT_SIZE -#endif - vector_memory_lit : - org = XCHAL_MEMERROR_VECTOR_PADDR + SOF_MEM_ERROR_LIT_SIZE, - len = SOF_MEM_ERROR_LIT_SIZE - vector_memory_text : - org = XCHAL_MEMERROR_VECTOR_PADDR, - len = SOF_MEM_ERROR_TEXT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_fw : - org = SOF_FW_BASE, - len = SOF_FW_MAX_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE - wnd1 : - org = HP_SRAM_WIN1_BASE, - len = HP_SRAM_WIN1_SIZE - wnd2 : - org = HP_SRAM_WIN2_BASE, - len = HP_SRAM_WIN2_SIZE - wnd3 : - org = HP_SRAM_WIN3_BASE, - len = HP_SRAM_WIN3_SIZE - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_memory_lit_phdr PT_LOAD; - vector_memory_text_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_fw_phdr PT_LOAD; - wnd0_phdr PT_LOAD; - wnd1_phdr PT_LOAD; - wnd2_phdr PT_LOAD; - wnd3_phdr PT_LOAD; - - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; -} - -/* Default entry point: */ -#if !defined(CONFIG_SKYLAKE) && !defined(CONFIG_KABYLAKE) -ENTRY(_MainEntry) -#endif -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = SOF_MEM_VECBASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .MemoryExceptionVector.literal : ALIGN(4) - { - _MemoryExceptionVector_literal_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.literal)) - _MemoryExceptionVector_literal_end = ABSOLUTE(.); - } >vector_memory_lit :vector_memory_lit_phdr - - .MemoryExceptionVector.text : ALIGN(4) - { - _MemoryExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.text)) - _MemoryExceptionVector_text_end = ABSOLUTE(.); - } >vector_memory_text :vector_memory_text_phdr - - .wnd0 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd0_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN0_SIZE; - _wnd0_end = ABSOLUTE(.); - } >wnd0 :wnd0_phdr - - .wnd1 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd1_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN1_SIZE; - _wnd1_end = ABSOLUTE(.); - } >wnd1 :wnd1_phdr - - .wnd2 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd2_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN2_SIZE; - _wnd2_end = ABSOLUTE(.); - } >wnd2 :wnd2_phdr - - .wnd3 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd3_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN3_SIZE; - _wnd3_end = ABSOLUTE(.); - } >wnd3 :wnd3_phdr - -#if defined(CONFIG_SKYLAKE) || defined(CONFIG_KABYLAKE) - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - -#endif - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_fw :sof_fw_phdr - - .rodata : ALIGN(4096) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .shared_data : ALIGN(PLATFORM_DCACHE_ALIGN) - { - _shared_data_start = ABSOLUTE(.); - *(*.shared_data) - _shared_data_end = ABSOLUTE(.); - . = ALIGN(PLATFORM_DCACHE_ALIGN); - } >sof_fw :sof_fw_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_fw :sof_fw_phdr - - .bss (NOLOAD) : ALIGN(4096) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_M_SIZE; - _system_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_M_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_SIZE; - _sof_stack_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _sof_core_s_start = ABSOLUTE(.); - . = . + SOF_CORE_S_T_SIZE; - _sof_core_s_end = ABSOLUTE(.); - - _bss_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - /* stack */ - _end = _sof_stack_start; - PROVIDE(end = _sof_stack_start); - _stack_sentry = _sof_stack_start; - __stack = _sof_stack_end; - - /* Slave core size */ - _core_s_size = SOF_CORE_S_SIZE; - - /* System Heap */ - _system_heap = _system_heap_start; - - /* system runtime heap */ - _system_runtime_heap = _system_runtime_heap_start; - - /* module heap */ - _module_heap = _runtime_heap_start; - - /* buffer heap */ - _buffer_heap = _buffer_heap_start; - _buffer_heap_end = _buffer_heap_end; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr -} diff --git a/src/platform/apollolake/base_module.c b/src/platform/apollolake/base_module.c deleted file mode 100644 index 69243c7d30f6..000000000000 --- a/src/platform/apollolake/base_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest apl_manifest = { - .module = { - .name = "BASEFW", - .uuid = {0x2e, 0x9e, 0x86, 0xfc, 0xf8, 0x45, 0x45, 0x40, - 0xa4, 0x16, 0x89, 0x88, 0x0a, 0xe3, 0x20, 0xa9}, - .entry_point = SOF_TEXT_START, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/apollolake/boot_ldr.x.in b/src/platform/apollolake/boot_ldr.x.in deleted file mode 100644 index 4cf03efec605..000000000000 --- a/src/platform/apollolake/boot_ldr.x.in +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Linker Script for Apollolake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - boot_entry_text : - org = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - len = IMR_BOOT_LDR_TEXT_ENTRY_SIZE - boot_entry_lit : - org = IMR_BOOT_LDR_LIT_BASE, - len = IMR_BOOT_LDR_LIT_SIZE - sof_text : - org = IMR_BOOT_LDR_TEXT_BASE, - len = IMR_BOOT_LDR_TEXT_SIZE, - sof_data : - org = IMR_BOOT_LDR_DATA_BASE, - len = IMR_BOOT_LDR_DATA_SIZE - sof_bss_data : - org = IMR_BOOT_LDR_BSS_BASE, - len = IMR_BOOT_LDR_BSS_SIZE - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE -} - -PHDRS -{ - boot_entry_text_phdr PT_LOAD; - boot_entry_lit_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_bss_data_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; - wnd0_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(boot_entry) -EXTERN(reset_vector) - -SECTIONS -{ - .boot_entry.text : ALIGN(4) - { - _boot_entry_text_start = ABSOLUTE(.); - KEEP (*(.boot_entry.text)) - _boot_entry_text_end = ABSOLUTE(.); - } >boot_entry_text :boot_entry_text_phdr - - .boot_entry.literal : ALIGN(4) - { - _boot_entry_literal_start = ABSOLUTE(.); - *(.boot_entry.literal) - *(.literal .literal.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _boot_entry_literal_end = ABSOLUTE(.); - } >boot_entry_lit :boot_entry_lit_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - *(.entry.text) - *(.init.literal) - KEEP(*(.init)) - *( .text .text.*) - *(.fini.literal) - KEEP(*(.fini)) - *(.gnu.version) - KEEP (*(.ResetVector.text)) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_bss_data :sof_bss_data_phdr - - _man = 0x1234567; - - PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - - _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; - PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - __wnd0 = HP_SRAM_WIN0_BASE; - __wnd0_size = HP_SRAM_WIN0_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/apollolake/boot_module.c b/src/platform/apollolake/boot_module.c deleted file mode 100644 index 6e6e5a318e55..000000000000 --- a/src/platform/apollolake/boot_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Marcin Maka <marcin.maka@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to generate the manifest). - */ -struct sof_man_module_manifest apl_bootldr_manifest = { - .module = { - .name = "BRNGUP", - .uuid = {0xcc, 0x48, 0x7b, 0x0d, 0xa9, 0x1e, 0x0a, 0x47, - 0xa8, 0xc1, 0x53, 0x34, 0x24, 0x52, 0x8a, 0x17}, - .entry_point = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/apollolake/include/arch/xtensa/config/core-isa.h b/src/platform/apollolake/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index 714a6b237417..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,613 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 0 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 0 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 0 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 0 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 0 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 0 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "X4H3I16w2D48w3a_2017_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x00072B8F /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC3F3FBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x1544813C /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX4.0.5" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2400 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 5 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 240005 /* major*100+minor */ -#define XCHAL_HW_REL_LX4 1 -#define XCHAL_HW_REL_LX4_0 1 -#define XCHAL_HW_REL_LX4_0_5 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2400 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 5 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 240005 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2400 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 5 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 240005 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 6 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 6 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 49152 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 8 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 7 -#define XCHAL_DCACHE_SETWIDTH 8 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 2 -#define XCHAL_DCACHE_WAYS 3 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY XTHAL_MEMEP_ECC -#define XCHAL_DCACHE_ECC_PARITY XTHAL_MEMEP_ECC - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 8 -#define XCHAL_DCACHE_ACCESS_SIZE 8 - -#define XCHAL_DCACHE_BANKS 1 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 21 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 8 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x0000000F -#define XCHAL_INTLEVEL2_MASK 0x000000F0 -#define XCHAL_INTLEVEL3_MASK 0x00000F00 -#define XCHAL_INTLEVEL4_MASK 0x00007000 -#define XCHAL_INTLEVEL5_MASK 0x000F8000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00100000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000000F -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00007FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x001FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 2 -#define XCHAL_INT5_LEVEL 2 -#define XCHAL_INT6_LEVEL 2 -#define XCHAL_INT7_LEVEL 2 -#define XCHAL_INT8_LEVEL 3 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 4 -#define XCHAL_INT14_LEVEL 4 -#define XCHAL_INT15_LEVEL 5 -#define XCHAL_INT16_LEVEL 5 -#define XCHAL_INT17_LEVEL 5 -#define XCHAL_INT18_LEVEL 5 -#define XCHAL_INT19_LEVEL 5 -#define XCHAL_INT20_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFE00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0008D999 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00072444 -#define XCHAL_INTTYPE_MASK_TIMER 0x00000222 -#define XCHAL_INTTYPE_MASK_NMI 0x00100000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 1 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 5 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 9 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 20 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL7_NUM 20 -/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 6 /* (intlevel 2) */ -#define XCHAL_EXTINT2_NUM 10 /* (intlevel 3) */ -#define XCHAL_EXTINT3_NUM 13 /* (intlevel 4) */ -#define XCHAL_EXTINT4_NUM 16 /* (intlevel 5) */ -#define XCHAL_EXTINT5_NUM 17 /* (intlevel 5) */ -#define XCHAL_EXTINT6_NUM 18 /* (intlevel 5) */ -#define XCHAL_EXTINT7_NUM 20 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT2_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT6_EXTNUM 1 /* (intlevel 2) */ -#define XCHAL_INT10_EXTNUM 2 /* (intlevel 3) */ -#define XCHAL_INT13_EXTNUM 3 /* (intlevel 4) */ -#define XCHAL_INT16_EXTNUM 4 /* (intlevel 5) */ -#define XCHAL_INT17_EXTNUM 5 /* (intlevel 5) */ -#define XCHAL_INT18_EXTNUM 6 /* (intlevel 5) */ -#define XCHAL_INT20_EXTNUM 7 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 1 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0xBEFE0800 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0xBEFE0800 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR0_PADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR1_VADDR 0xBE800000 -#define XCHAL_RESET_VECTOR1_PADDR 0xBE800000 -#define XCHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XCHAL_MEMERROR_VECTOR0_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR0_PADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR1_VADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR1_PADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 -#define XCHAL_USER_VECOFS 0x00000340 -#define XCHAL_USER_VECTOR_VADDR 0xBEFE0B40 -#define XCHAL_USER_VECTOR_PADDR 0xBEFE0B40 -#define XCHAL_KERNEL_VECOFS 0x00000300 -#define XCHAL_KERNEL_VECTOR_VADDR 0xBEFE0B00 -#define XCHAL_KERNEL_VECTOR_PADDR 0xBEFE0B00 -#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xBEFE0BC0 -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0xBEFE0BC0 -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0xBEFE0800 -#define XCHAL_WINDOW_VECTORS_PADDR 0xBEFE0800 -#define XCHAL_INTLEVEL2_VECOFS 0x00000180 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xBEFE0980 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0xBEFE0980 -#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL4_VECOFS 0x00000200 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL5_VECOFS 0x00000240 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL6_VECOFS 0x00000280 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0xBEFE0A80 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0xBEFE0A80 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x000002C0 -#define XCHAL_NMI_VECTOR_VADDR 0xBEFE0AC0 -#define XCHAL_NMI_VECTOR_PADDR 0xBEFE0AC0 -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 0 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 0 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 1 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/arch/xtensa/config/core-matmap.h b/src/platform/apollolake/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index 9cea939f7534..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - -#define XCHAL_CA_R (0xC0 | 0x40000000) -#define XCHAL_CA_RX (0xD0 | 0x40000000) -#define XCHAL_CA_RW (0xE0 | 0x40000000) -#define XCHAL_CA_RWX (0xF0 | 0x40000000) - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefine hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Reset PPN values for each entry of ITLB way set 0 (because SET0_PPN_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_RESET 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_RESET 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_RESET 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_RESET 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_RESET 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_RESET 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_RESET 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_RESET 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Reset PPN values for each entry of DTLB way set 0 (because SET0_PPN_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_RESET 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_RESET 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_RESET 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_RESET 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_RESET 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_RESET 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_RESET 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_RESET 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/arch/xtensa/config/defs.h b/src/platform/apollolake/include/arch/xtensa/config/defs.h deleted file mode 100644 index d93272ae05a3..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/arch/xtensa/config/specreg.h b/src/platform/apollolake/include/arch/xtensa/config/specreg.h deleted file mode 100644 index 36fafab35555..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ - -/* Copyright (c) 1998-2002 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define ATOMCTL 99 -#define DDR 104 -#define MEPC 106 -#define MEPS 107 -#define MESAVE 108 -#define MESR 109 -#define MECR 110 -#define MEVADDR 111 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 - -/* Special cases (bases of special register series): */ -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -#endif /* XTENSA_SPECREG_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/arch/xtensa/config/system.h b/src/platform/apollolake/include/arch/xtensa/config/system.h deleted file mode 100644 index 0e434954c920..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Copyright (c) 2000-2010 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -#define XSHAL_FLOATING_POINT_ABI 0 - -/* SW workarounds enabled for HW errata: */ - -/* SW options for functional safety: */ -#define XSHAL_FUNC_SAFETY_ENABLED 0 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -#define XSHAL_ROM_VADDR 0xBEFE0000 -#define XSHAL_ROM_PADDR 0xBEFE0000 -#define XSHAL_ROM_SIZE 0x00020000 -/* Largest available area (free of vectors): */ -#define XSHAL_ROM_AVAIL_VADDR 0xBEFE0BC0 -#define XSHAL_ROM_AVAIL_VSIZE 0x0001F440 - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x80000000 -#define XSHAL_RAM_PADDR 0x80000000 -#define XSHAL_RAM_VSIZE 0x3EFE0000 -#define XSHAL_RAM_PSIZE 0x3EFE0000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x80000000 -#define XSHAL_RAM_AVAIL_VSIZE 0x3EFE0000 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit and diagnostic routines. - */ -#define XSHAL_MAGIC_EXIT 0xe0000000 - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22442222 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22112222 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22112222 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44FFFF /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11FFFF /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11FFFF /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22FFFF /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244222F /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211222F /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211222F /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF44422F /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF11122F /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF11122F /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000104 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XSHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XSHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XSHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x00000300 -#define XSHAL_RESET_VECTOR_ISROM 1 -#define XSHAL_USER_VECTOR_SIZE 0x00000038 -#define XSHAL_USER_VECTOR_ISROM 1 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 -#define XSHAL_KERNEL_VECTOR_ISROM 1 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 1 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 1 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL2_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL3_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL4_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL5_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL6_VECTOR_ISROM 1 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x00000038 -#define XSHAL_NMI_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/arch/xtensa/config/tie-asm.h b/src/platform/apollolake/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index 0d1279a805c3..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - /* - * Macro to store all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rur.THREADPTR \at1 // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_+0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_store - - /* - * Macro to load all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.THREADPTR \at1 // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - /* - * Macro to store the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_CW_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - rur.AE_CBEGIN0 \at1 // ureg 246 - s32i \at1, \ptr, .Lxchal_ofs_+16 - rur.AE_CEND0 \at1 // ureg 247 - s32i \at1, \ptr, .Lxchal_ofs_+20 - ae_s64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_s64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed15, \ptr, .Lxchal_ofs_+16 - ae_salign64.i u0, \ptr, .Lxchal_ofs_+24 - ae_salign64.i u1, \ptr, .Lxchal_ofs_+32 - ae_salign64.i u2, \ptr, .Lxchal_ofs_+40 - ae_salign64.i u3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 128 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_store - - /* - * Macro to load the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_CW_SD_NO \at1 // ureg 243 - l32i \at1, \ptr, .Lxchal_ofs_+16 - wur.AE_CBEGIN0 \at1 // ureg 246 - l32i \at1, \ptr, .Lxchal_ofs_+20 - wur.AE_CEND0 \at1 // ureg 247 - ae_l64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_l64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed15, \ptr, .Lxchal_ofs_+16 - addi \ptr, \ptr, 24 - ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 - ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 - ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 - ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 152 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/arch/xtensa/config/tie.h b/src/platform/apollolake/include/arch/xtensa/config/tie.h deleted file mode 100644 index c0ca1a44a71a..000000000000 --- a/src/platform/apollolake/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 1 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 184 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP0_SA_SIZE 0 -#define XCHAL_CP0_SA_ALIGN 1 -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 12 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 208 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 3 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 0 -#define XCHAL_CP0_SA_LIST(s) /* empty */ - -#define XCHAL_CP1_SA_NUM 26 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 -/* Byte length of instruction from its first byte, per FLIX. */ -#define XCHAL_BYTE0_FORMAT_LENGTHS \ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 - -#endif /*_XTENSA_CORE_TIE_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/apollolake/include/platform/drivers/dw-dma.h b/src/platform/apollolake/include/platform/drivers/dw-dma.h deleted file mode 100644 index 26d781ac8844..000000000000 --- a/src/platform/apollolake/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <cavs/drivers/dw-dma.h> - -#endif /* __PLATFORM_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/apollolake/include/platform/drivers/idc.h b/src/platform/apollolake/include/platform/drivers/idc.h deleted file mode 100644 index b8565347f42e..000000000000 --- a/src/platform/apollolake/include/platform/drivers/idc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <cavs/drivers/idc.h> - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/apollolake/include/platform/drivers/interrupt.h b/src/platform/apollolake/include/platform/drivers/interrupt.h deleted file mode 100644 index b7f65bb0a7c4..000000000000 --- a/src/platform/apollolake/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,153 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <cavs/drivers/interrupt.h> -#include <sof/bit.h> -#include <config.h> - -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 32 - -/* IRQ numbers - wrt Tensilica DSP */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_SOFTWARE0 0 /* level 1 */ -#define IRQ_NUM_TIMER1 1 /* level 1 */ -#define IRQ_NUM_EXT_LEVEL1 2 /* level 1 */ -#define IRQ_NUM_SOFTWARE1 3 /* level 1 */ - -#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_EXT_LEVEL1 BIT(IRQ_NUM_EXT_LEVEL1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_SOFTWARE2 4 /* level 2 */ -#define IRQ_NUM_TIMER2 5 /* level 2 */ -#define IRQ_NUM_EXT_LEVEL2 6 /* level 2 */ -#define IRQ_NUM_SOFTWARE3 7 /* level 2 */ - -/* IRQ Level 2 bits */ -#define IRQ_BIT_LVL2_HP_GP_DMA0(x) (x + 24) -#define IRQ_BIT_LVL2_WALL_CLK1 23 -#define IRQ_BIT_LVL2_WALL_CLK0 22 -#define IRQ_BIT_LVL2_L2_MEMERR 21 -#define IRQ_BIT_LVL2_SHA256 16 -#define IRQ_BIT_LVL2_L2_CACHE 15 -#define IRQ_BIT_LVL2_IDC 8 -#define IRQ_BIT_LVL2_HOST_IPC 7 -#define IRQ_BIT_LVL2_CSME_IPC 6 -#define IRQ_BIT_LVL2_PMC_IPC 5 - -/* Level 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) -#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC -#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC -#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 -#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 -#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR -#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE -#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 - -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_EXT_LEVEL2 BIT(IRQ_NUM_EXT_LEVEL2) -#define IRQ_MASK_SOFTWARE3 BIT(IRQ_NUM_SOFTWARE3) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_SOFTWARE4 8 /* level 3 */ -#define IRQ_NUM_TIMER3 9 /* level 3 */ -#define IRQ_NUM_EXT_LEVEL3 10 /* level 3 */ -#define IRQ_NUM_SOFTWARE5 11 /* level 3 */ - -/* IRQ Level 3 bits */ -#define IRQ_BIT_LVL3_CODE_LOADER 31 -#define IRQ_BIT_LVL3_HOST_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL3_HOST_STREAM_IN(x) (0 + x) - -/* Level 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER -#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE4 BIT(IRQ_NUM_SOFTWARE4) -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) -#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) -#define IRQ_MASK_SOFTWARE5 BIT(IRQ_NUM_SOFTWARE5) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_SOFTWARE6 12 /* level 4 */ -#define IRQ_NUM_EXT_LEVEL4 13 /* level 4 */ -#define IRQ_NUM_SOFTWARE7 14 /* level 4 */ - -/* IRQ Level 4 bits */ -#define IRQ_BIT_LVL4_LINK_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL4_LINK_STREAM_IN(x) (0 + x) - -/* Level 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE6 BIT(IRQ_NUM_SOFTWARE6) -#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) -#define IRQ_MASK_SOFTWARE7 BIT(IRQ_NUM_SOFTWARE7) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_SOFTWARE8 15 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL5 16 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL6 17 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL7 18 /* level 5 */ -#define IRQ_NUM_SOFTWARE9 19 /* level 5 */ - -/* IRQ Level 5 bits */ -#define IRQ_BIT_LVL5_LP_GP_DMA1(x) (24 + x) -#define IRQ_BIT_LVL5_LP_GP_DMA0(x) (16 + x) -#define IRQ_BIT_LVL5_DMIC(x) 6 -#define IRQ_BIT_LVL5_SSP(x) (0 + x) - -/* Level 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0(channel) -#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA1(channel) -#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) - -#define IRQ_MASK_SOFTWARE8 BIT(IRQ_NUM_SOFTWARE8) -#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) -#define IRQ_MASK_EXT_LEVEL6 BIT(IRQ_NUM_EXT_LEVEL6) -#define IRQ_MASK_EXT_LEVEL7 BIT(IRQ_NUM_EXT_LEVEL7) -#define IRQ_MASK_SOFTWARE9 BIT(IRQ_NUM_SOFTWARE9) - -#endif - -#define IRQ_NUM_NMI 20 /* level 7 */ - -#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/apollolake/include/platform/lib/asm_ldo_management.h b/src/platform/apollolake/include/platform/lib/asm_ldo_management.h deleted file mode 100644 index a9e17de45906..000000000000 --- a/src/platform/apollolake/include/platform/lib/asm_ldo_management.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Lech Betlej <lech.betlej@linux.intel.com> - */ - -/** - * \file platform/apollolake/lib/asm_ldo_management.h - * \brief Macros for controlling LDO state specific for cAVS 1.5. The header is - * intended to be used in Apollolake specific implementation of power_down - * routine - */ - -#ifndef __PLATFORM_LIB_ASM_LDO_MANAGEMENT_H__ -#define __PLATFORM_LIB_ASM_LDO_MANAGEMENT_H__ - -#include <cavs/lib/asm_ldo_management.h> - -#endif /* __PLATFORM_LIB_ASM_LDO_MANAGEMENT_H__ */ diff --git a/src/platform/apollolake/include/platform/lib/asm_memory_management.h b/src/platform/apollolake/include/platform/lib/asm_memory_management.h deleted file mode 100644 index 68b3abcf29ba..000000000000 --- a/src/platform/apollolake/include/platform/lib/asm_memory_management.h +++ /dev/null @@ -1,70 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Lech Betlej <lech.betlej@linux.intel.com> - */ - -/** - * \file platform/apollolake/include/platform/lib/asm_memory_management.h - * \brief Macros for power gating memory banks specific for Apollolake - * \author Lech Betlej <lech.betlej@linux.intel.com> - */ - -#ifndef __PLATFORM_LIB_ASM_MEMORY_MANAGEMENT_H__ -#define __PLATFORM_LIB_ASM_MEMORY_MANAGEMENT_H__ - -#ifndef ASSEMBLY -#warning "ASSEMBLY macro not defined." -#endif - -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> - - /* Macro powers down entire hpsram. on entry literals and code for - * section from where this code is executed needs to be placed in - * memory which is not HPSRAM (in case when this code is located in - * HPSRAM lock memory in L1$ or L1 SRAM) - */ - .macro m_cavs_hpsram_power_off ax, ay, az - // SEGMENT #0 - movi \az, (SHIM_BASE + SHIM_HSPGISTS) - movi \ax, (SHIM_BASE + SHIM_HSPGCTL) - movi \ay, HPSRAM_MASK(0) - s32i \ay, \ax, 0 - memw - /* since HPSRAM EBB bank #0 might be used as buffer for legacy - * streaming, should not be checked in status - */ - movi \ax, 0xfffffffe - and \ay, \ay, \ax - 1 : - l32i \ax, \az, 0 - and \ax, \ax, \ay - bne \ax, \ay, 1b - /* there is no possibility to check from DSP whether EBB #0 is actually - * in use therefore wait additional 4K DSP cycles as chicken check - - * after that time EBB #0 should be already power gated unless is used - * by other HW components (like HD-A) - */ - l32i \ax, \az, 0 - beq \ax, \ay, m_cavs_hpsram_power_off_end - movi \ax, 4096 - 1 : - addi \ax, \ax, -1 - bnez \ax, 1b - m_cavs_hpsram_power_off_end : - .endm - - .macro m_cavs_lpsram_power_off ax, ay, az - movi \az, (SHIM_BASE + SHIM_LSPGISTS) - movi \ax, (SHIM_BASE + SHIM_LSPGCTL) - movi \ay, LPSRAM_MASK() - s32i \ay, \ax, 0 - memw - 1 : - l32i \ax, \az, 0 - bne \ax, \ay, 1b - .endm - -#endif /* __PLATFORM_LIB_ASM_MEMORY_MANAGEMENT_H__ */ diff --git a/src/platform/apollolake/include/platform/lib/clk.h b/src/platform/apollolake/include/platform/lib/clk.h deleted file mode 100644 index b07098d2722a..000000000000 --- a/src/platform/apollolake/include/platform/lib/clk.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <cavs/lib/clk.h> - -#define CLK_MAX_CPU_HZ 400000000 - -#define CPU_DEFAULT_IDX 2 - -#define SSP_DEFAULT_IDX 0 - -#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/apollolake/include/platform/lib/cpu.h b/src/platform/apollolake/include/platform/lib/cpu.h deleted file mode 100644 index 8e7eb190e0d3..000000000000 --- a/src/platform/apollolake/include/platform/lib/cpu.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <cavs/lib/cpu.h> - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 2 - -#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/apollolake/include/platform/lib/dai.h b/src/platform/apollolake/include/platform/lib/dai.h deleted file mode 100644 index 60d6ddce9b92..000000000000 --- a/src/platform/apollolake/include/platform/lib/dai.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -/* APOLLOLAKE */ - -/* 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 4 - -/** \brief Number of 'extended' SSP ports available */ -#define DAI_NUM_SSP_EXT 2 - -/** \brief Number of SSP MCLKs available */ -#define DAI_NUM_SSP_MCLK 2 - -/* HD/A */ - -/** \brief Number of HD/A Link Outputs */ -#define DAI_NUM_HDA_OUT 6 - -/** \brief Number of HD/A Link Inputs */ -#define DAI_NUM_HDA_IN 7 - -#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/apollolake/include/platform/lib/dma.h b/src/platform/apollolake/include/platform/lib/dma.h deleted file mode 100644 index d8793eab9baa..000000000000 --- a/src/platform/apollolake/include/platform/lib/dma.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -/* number of supported DMACs */ -#define PLATFORM_NUM_DMACS 6 - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 8 - -/* available DMACs */ -#define DMA_GP_LP_DMAC0 0 -#define DMA_GP_LP_DMAC1 1 -#define DMA_GP_HP_DMAC0 2 -#define DMA_GP_HP_DMAC1 3 -#define DMA_HOST_IN_DMAC 4 -#define DMA_HOST_OUT_DMAC 5 -#define DMA_LINK_IN_DMAC 6 -#define DMA_LINK_OUT_DMAC 7 - -/* mappings - TODO improve API to get type */ -#define DMA_ID_DMAC0 DMA_HOST_IN_DMAC -#define DMA_ID_DMAC1 DMA_GP_LP_DMAC0 -#define DMA_ID_DMAC2 DMA_HOST_OUT_DMAC -#define DMA_ID_DMAC3 DMA_GP_HP_DMAC0 -#define DMA_ID_DMAC4 DMA_GP_LP_DMAC1 -#define DMA_ID_DMAC5 DMA_GP_HP_DMAC1 -#define DMA_ID_DMAC6 DMA_LINK_IN_DMAC -#define DMA_ID_DMAC7 DMA_LINK_OUT_DMAC - -/* handshakes */ -#define DMA_HANDSHAKE_DMIC_CH0 0 -#define DMA_HANDSHAKE_DMIC_CH1 1 -#define DMA_HANDSHAKE_SSP0_TX 2 -#define DMA_HANDSHAKE_SSP0_RX 3 -#define DMA_HANDSHAKE_SSP1_TX 4 -#define DMA_HANDSHAKE_SSP1_RX 5 -#define DMA_HANDSHAKE_SSP2_TX 6 -#define DMA_HANDSHAKE_SSP2_RX 7 -#define DMA_HANDSHAKE_SSP3_TX 8 -#define DMA_HANDSHAKE_SSP3_RX 9 -#define DMA_HANDSHAKE_SSP4_TX 10 -#define DMA_HANDSHAKE_SSP4_RX 11 -#define DMA_HANDSHAKE_SSP5_TX 12 -#define DMA_HANDSHAKE_SSP5_RX 13 - -#define dma_chan_irq(dma, chan) (dma_irq(dma) + chan) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/apollolake/include/platform/lib/mailbox.h b/src/platform/apollolake/include/platform/lib/mailbox.h deleted file mode 100644 index baf6539a9fc3..000000000000 --- a/src/platform/apollolake/include/platform/lib/mailbox.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_LIB_MAILBOX_H__ - -#ifndef __PLATFORM_LIB_MAILBOX_H__ -#define __PLATFORM_LIB_MAILBOX_H__ - -#include <cavs/lib/mailbox.h> - -#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/apollolake/include/platform/lib/memory.h b/src/platform/apollolake/include/platform/lib/memory.h deleted file mode 100644 index 5c764d81f0ee..000000000000 --- a/src/platform/apollolake/include/platform/lib/memory.h +++ /dev/null @@ -1,442 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_LIB_MEMORY_H__ - -#ifndef __PLATFORM_LIB_MEMORY_H__ -#define __PLATFORM_LIB_MEMORY_H__ - -#include <cavs/lib/memory.h> -#include <sof/lib/cpu.h> -#include <config.h> - -/* physical DSP addresses */ - -/* shim */ -#define SHIM_BASE 0x00001000 -#define SHIM_SIZE 0x00000100 - -/* cmd IO to audio codecs */ -#define CMD_BASE 0x00001100 -#define CMD_SIZE 0x00000010 - -/* resource allocation */ -#define RES_BASE 0x00001110 -#define RES_SIZE 0x00000010 - -/* IPC to the host */ -#define IPC_HOST_BASE 0x00001180 -#define IPC_HOST_SIZE 0x00000020 - -/* intra DSP IPC */ -#define IPC_DSP_SIZE 0x00000080 -#define IPC_DSP_BASE(x) (0x00001200 + x * IPC_DSP_SIZE) - -/* SRAM window for HOST */ -#define HOST_WIN_SIZE 0x00000008 -#define HOST_WIN_BASE(x) (0x00001580 + x * HOST_WIN_SIZE) - -/* IRQ controller */ -#define IRQ_BASE 0x00001600 -#define IRQ_SIZE 0x00000200 - -/* time stamping */ -#define TIME_BASE 0x00001800 -#define TIME_SIZE 0x00000200 - -/* M/N dividers */ -#define MN_BASE 0x00008E00 -#define MN_SIZE 0x00000200 - -/* low power DMA position */ -#define LP_GP_DMA_LINK_SIZE 0x00000010 -#define LP_GP_DMA_LINK_BASE(x) (0x00001C00 + x * LP_GP_DMA_LINK_SIZE) - -/* high performance DMA position */ -#define HP_GP_DMA_LINK_SIZE 0x00000010 -#define HP_GP_DMA_LINK_BASE(x) (0x00001D00 + x * HP_GP_DMA_LINK_SIZE) - -/* link DMAC stream */ -#define GTW_LINK_OUT_STREAM_SIZE 0x00000020 -#define GTW_LINK_OUT_STREAM_BASE(x) \ - (0x00002400 + x * GTW_LINK_OUT_STREAM_SIZE) - -#define GTW_LINK_IN_STREAM_SIZE 0x00000020 -#define GTW_LINK_IN_STREAM_BASE(x) \ - (0x00002600 + x * GTW_LINK_IN_STREAM_SIZE) - -/* host DMAC stream */ -#define GTW_HOST_OUT_STREAM_SIZE 0x00000040 -#define GTW_HOST_OUT_STREAM_BASE(x) \ - (0x00002800 + x * GTW_HOST_OUT_STREAM_SIZE) - -#define GTW_HOST_IN_STREAM_SIZE 0x00000040 -#define GTW_HOST_IN_STREAM_BASE(x) \ - (0x00002C00 + x * GTW_HOST_IN_STREAM_SIZE) - -/* code loader */ -#define GTW_CODE_LDR_SIZE 0x00000040 -#define GTW_CODE_LDR_BASE 0x00002BC0 - -/* L2 TLBs */ -#define L2_HP_SRAM_TLB_SIZE 0x00001000 -#define L2_HP_SRAM_TLB_BASE 0x00003000 - -/* DMICs */ -#define DMIC_BASE 0x00004000 -#define DMIC_SIZE 0x00004000 - -/* SSP */ -#define SSP_SIZE 0x0000200 -#define SSP_BASE(x) (0x00008000 + x * SSP_SIZE) - -/* Timestamp */ -#define TIMESTAMP_BASE 0x00001800 - -/* low power DMACs */ -#define LP_GP_DMA_SIZE 0x00001000 -#define LP_GP_DMA_BASE(x) (0x0000C000 + x * LP_GP_DMA_SIZE) - -/* high performance DMACs */ -#define HP_GP_DMA_SIZE 0x00001000 -#define HP_GP_DMA_BASE(x) (0x0000E000 + x * HP_GP_DMA_SIZE) - -/* ROM */ -#define ROM_BASE 0xBEFE0000 -#define ROM_SIZE 0x00002000 - -/* IMR accessible via L2$ */ -#define L2_SRAM_BASE 0xA000A000 -#define L2_SRAM_SIZE 0x00056000 - -#define L2_VECTOR_SIZE 0x1000 - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -/* - * The HP SRAM Region Apollolake is organised like this :- - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_SW_REG_BASE | SW Registers W0 | SRAM_SW_REG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_MAILBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_EXCEPT_BASE | Debug data W2 | SRAM_EXCEPT_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_STREAM_BASE | Stream data W2 | SRAM_STREAM_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_TRACE_BASE | Trace Buffer W3 | SRAM_TRACE_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SOF_FW_START | text | | - * | | data | | - * | | ----------------------- | | - * | ||BSS: || | - * | ||-----------------------++-----------------------------+ - * | ||Runtime Heap || HEAP_RUNTIME_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Module Buffers || HEAP_BUFFER_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master core Sys Heap || HEAP_SYSTEM_M_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master Sys Runtime Heap|| HEAP_SYS_RUNTIME_M_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master core Stack || SOF_STACK_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Slave core Sys Heap || SOF_CORE_S_T_SIZE | - * | ||Slave Sys Runtime Heap || | - * | ||Slave core Stack || | - * | | ----------------------- | | - * +------------------+-------------------------+-----------------------------+ - */ - -/* HP SRAM */ - -#define HP_SRAM_BASE 0xBE000000 - -/* HP SRAM windows */ - -/* window 3 */ -#define SRAM_TRACE_BASE SRAM_WND_BASE -#if CONFIG_TRACE -#define SRAM_TRACE_SIZE 0x2000 -#else -#define SRAM_TRACE_SIZE 0 -#endif - -/* window 2 */ -#define SRAM_DEBUG_BASE (SRAM_TRACE_BASE + SRAM_TRACE_SIZE) -#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 - -/* window 1 */ -#define SRAM_INBOX_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) -#define SRAM_INBOX_SIZE 0x2000 - -/* window 0 */ -#define SRAM_SW_REG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) -#define SRAM_SW_REG_SIZE 0x1000 - -/* SRAM window 0 FW "registers" */ -#define SRAM_REG_ROM_STATUS 0x0 -#define SRAM_REG_FW_STATUS 0x4 -#define SRAM_REG_FW_TRACEP 0x8 -#define SRAM_REG_FW_IPC_RECEIVED_COUNT 0xc -#define SRAM_REG_FW_IPC_PROCESSED_COUNT 0x10 -#define SRAM_REG_FW_END 0x14 - -#define SRAM_OUTBOX_BASE (SRAM_SW_REG_BASE + SRAM_SW_REG_SIZE) -#define SRAM_OUTBOX_SIZE 0x1000 - -#define HP_SRAM_WIN0_BASE SRAM_SW_REG_BASE -#define HP_SRAM_WIN0_SIZE (SRAM_SW_REG_SIZE + SRAM_OUTBOX_SIZE) -#define HP_SRAM_WIN1_BASE SRAM_INBOX_BASE -#define HP_SRAM_WIN1_SIZE SRAM_INBOX_SIZE -#define HP_SRAM_WIN2_BASE SRAM_DEBUG_BASE -#define HP_SRAM_WIN2_SIZE (SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE + \ - SRAM_STREAM_SIZE) -#define HP_SRAM_WIN3_BASE SRAM_TRACE_BASE -#define HP_SRAM_WIN3_SIZE SRAM_TRACE_SIZE - -/* Apollolake HP-SRAM config */ -#if CONFIG_APOLLOLAKE && !(CONFIG_KABYLAKE || CONFIG_SKYLAKE) - -#define SRAM_WND_BASE (HP_SRAM_BASE) - -#define HP_SRAM_VECBASE_RESET (HP_SRAM_WIN0_BASE + HP_SRAM_WIN0_SIZE) -#define HP_SRAM_VECBASE_OFFSET 0x0 - -#define SOF_FW_START (HP_SRAM_VECBASE_RESET + 0x400) -#define SOF_FW_BASE (SOF_FW_START) - -/* Skylake or kabylake HP-SRAM config */ -#elif CONFIG_KABYLAKE || CONFIG_SKYLAKE - -#define SRAM_WND_BASE 0xBE058000 - -#define HP_SRAM_VECBASE_RESET 0xBE0A0000 -#define HP_SRAM_VECBASE_OFFSET 0x800 -#define HP_SRAM_RESET_TEXT_SIZE 0x400 -#define HP_SRAM_RESET_LIT_SIZE 0x100 - -#define SOF_FW_START HP_SRAM_VECBASE_RESET -#define SOF_FW_BASE (SOF_FW_START + 0x1000) - -#else -#error Platform not specified -#endif - -/* max size for all var-size sections (text/rodata/bss) */ -#define SOF_FW_MAX_SIZE (HP_SRAM_BASE + HP_SRAM_SIZE - SOF_FW_BASE) - -#define SOF_TEXT_START (SOF_FW_START) -#define SOF_TEXT_BASE (SOF_FW_START) - -/* Heap section sizes for system runtime heap for master core */ -#define HEAP_SYS_RT_0_COUNT64 128 -#define HEAP_SYS_RT_0_COUNT512 16 -#define HEAP_SYS_RT_0_COUNT1024 4 - -/* Heap section sizes for system runtime heap for slave core */ -#define HEAP_SYS_RT_X_COUNT64 64 -#define HEAP_SYS_RT_X_COUNT512 8 -#define HEAP_SYS_RT_X_COUNT1024 4 - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT64 128 -#define HEAP_RT_COUNT128 64 -#define HEAP_RT_COUNT256 96 -#define HEAP_RT_COUNT512 8 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 0 -#define HEAP_RT_COUNT4096 1 - -/* Heap configuration */ -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT64 * 64 + HEAP_RT_COUNT128 * 128 + \ - HEAP_RT_COUNT256 * 256 + HEAP_RT_COUNT512 * 512 + \ - HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + \ - HEAP_RT_COUNT4096 * 4096) - -#define HEAP_BUFFER_SIZE 0x10000 - -#define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) - -#define HEAP_SYSTEM_M_SIZE 0x8000 /* heap master core size */ -#define HEAP_SYSTEM_S_SIZE 0x6000 /* heap slave core size */ -#define HEAP_SYSTEM_T_SIZE \ - (HEAP_SYSTEM_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) - -#define HEAP_SYS_RUNTIME_M_SIZE \ - (HEAP_SYS_RT_0_COUNT64 * 64 + HEAP_SYS_RT_0_COUNT512 * 512 + \ - HEAP_SYS_RT_0_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_S_SIZE \ - (HEAP_SYS_RT_X_COUNT64 * 64 + HEAP_SYS_RT_X_COUNT512 * 512 + \ - HEAP_SYS_RT_X_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_T_SIZE \ - (HEAP_SYS_RUNTIME_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * \ - HEAP_SYS_RUNTIME_S_SIZE)) - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * SOF_STACK_SIZE) - -/* SOF Core S configuration */ -#define SOF_CORE_S_SIZE \ - ALIGN((HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE + SOF_STACK_SIZE),\ - SRAM_BANK_SIZE) -#define SOF_CORE_S_T_SIZE ((PLATFORM_CORE_COUNT - 1) * SOF_CORE_S_SIZE) - -/* - * The LP SRAM Heap and Stack on Apollolake are organised like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | LP_SRAM_BASE | RO Data | SOF_LP_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_SYSTEM_BASE | System Heap | HEAP_LP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_RUNTIME_BASE| Runtime Heap | HEAP_LP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_BUFFER_BASE | Module Buffers | HEAP_LP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_LP_STACK_END | Stack | SOF_LP_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - -/* LP SRAM */ -#define LP_SRAM_BASE 0xBE800000 - -/* Heap section sizes for module pool */ -#define HEAP_RT_LP_COUNT8 0 -#define HEAP_RT_LP_COUNT16 256 -#define HEAP_RT_LP_COUNT32 128 -#define HEAP_RT_LP_COUNT64 64 -#define HEAP_RT_LP_COUNT128 64 -#define HEAP_RT_LP_COUNT256 96 -#define HEAP_RT_LP_COUNT512 8 -#define HEAP_RT_LP_COUNT1024 4 - -/* Heap configuration */ -#define SOF_LP_DATA_SIZE 0x4000 - -#define HEAP_LP_SYSTEM_BASE (LP_SRAM_BASE + SOF_LP_DATA_SIZE) -#define HEAP_LP_SYSTEM_SIZE 0x1000 - -#define HEAP_LP_RUNTIME_BASE \ - (HEAP_LP_SYSTEM_BASE + HEAP_LP_SYSTEM_SIZE) -#define HEAP_LP_RUNTIME_SIZE \ - (HEAP_RT_LP_COUNT8 * 8 + HEAP_RT_LP_COUNT16 * 16 + \ - HEAP_RT_LP_COUNT32 * 32 + HEAP_RT_LP_COUNT64 * 64 + \ - HEAP_RT_LP_COUNT128 * 128 + HEAP_RT_LP_COUNT256 * 256 + \ - HEAP_RT_LP_COUNT512 * 512 + HEAP_RT_LP_COUNT1024 * 1024) - -#define HEAP_LP_BUFFER_BASE LP_SRAM_BASE -#define HEAP_LP_BUFFER_SIZE LP_SRAM_SIZE - -#define HEAP_LP_BUFFER_BLOCK_SIZE 0x180 - -#if CONFIG_LP_MEMORY_BANKS -#define HEAP_LP_BUFFER_COUNT \ - (HEAP_LP_BUFFER_SIZE / HEAP_LP_BUFFER_BLOCK_SIZE) -#else -#define HEAP_LP_BUFFER_COUNT 0 -#endif - -#define PLATFORM_HEAP_SYSTEM PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 2 - -/* Stack configuration */ -#define SOF_LP_STACK_SIZE 0x1000 -#define SOF_LP_STACK_BASE (LP_SRAM_BASE + LP_SRAM_SIZE) -#define SOF_LP_STACK_END (SOF_LP_STACK_BASE - SOF_LP_STACK_SIZE) - -/* Vector and literal sizes - not in core-isa.h */ -#define SOF_MEM_VECT_LIT_SIZE 0x8 -#define SOF_MEM_VECT_TEXT_SIZE 0x38 -#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ - SOF_MEM_VECT_LIT_SIZE) - -#define SOF_MEM_ERROR_TEXT_SIZE 0x180 -#define SOF_MEM_ERROR_LIT_SIZE 0x8 - -#define SOF_MEM_VECBASE \ - (HP_SRAM_VECBASE_RESET + HP_SRAM_VECBASE_OFFSET) -#define SOF_MEM_VECBASE_LIT_SIZE 0x178 - -#define SOF_MEM_RO_SIZE 0x8 - -/* VM ROM sizes */ -#define ROM_RESET_TEXT_SIZE 0x400 -#define ROM_RESET_LIT_SIZE 0x200 - -/* boot loader in IMR - APL uses manifest v1.8 and SKL/KBL use v1.5 */ -#if CONFIG_APOLLOLAKE && !(CONFIG_KABYLAKE || CONFIG_SKYLAKE) -#define IMR_BOOT_LDR_TEXT_ENTRY_BASE 0xB000A000 -#elif CONFIG_KABYLAKE || CONFIG_SKYLAKE -#define IMR_BOOT_LDR_TEXT_ENTRY_BASE 0xBE0A0000 -#else -#error Platform not specified -#endif - -#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x86 -#define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ - IMR_BOOT_LDR_TEXT_ENTRY_SIZE) -#define IMR_BOOT_LDR_LIT_SIZE 0x70 -#define IMR_BOOT_LDR_TEXT_BASE (IMR_BOOT_LDR_LIT_BASE + \ - IMR_BOOT_LDR_LIT_SIZE) -#define IMR_BOOT_LDR_TEXT_SIZE 0x1C00 -#define IMR_BOOT_LDR_TEXT1_BASE (IMR_BOOT_LDR_TEXT_BASE + \ - IMR_BOOT_LDR_TEXT_SIZE) -#define IMR_BOOT_LDR_TEXT1_SIZE 0x2000 -#define IMR_BOOT_LDR_DATA_BASE 0xB0002000 -#define IMR_BOOT_LDR_DATA_SIZE 0x1000 -#define IMR_BOOT_LDR_BSS_BASE 0xB0100000 -#define IMR_BOOT_LDR_BSS_SIZE 0x10000 - -/* Temporary stack place for boot_ldr */ -#define BOOT_LDR_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE - \ - SOF_STACK_TOTAL_SIZE) -#define BOOT_LDR_STACK_SIZE SOF_STACK_TOTAL_SIZE - -/** \brief Manifest base address in IMR - used by boot loader copy procedure. */ -#define IMR_BOOT_LDR_MANIFEST_BASE 0xB0004000 - -/** \brief Manifest size (seems unused). */ -#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 - -#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/apollolake/include/platform/lib/pm_runtime.h b/src/platform/apollolake/include/platform/lib/pm_runtime.h deleted file mode 100644 index 74670e099b18..000000000000 --- a/src/platform/apollolake/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/apollolake/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Apollolake - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <cavs/lib/pm_runtime.h> -#include <stdint.h> - -/** - * \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_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); - -/** - * \brief Power gates platform specific hardware resources. - * \param[in] context Type of power management context. - */ -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/apollolake/include/platform/lib/shim.h b/src/platform/apollolake/include/platform/lib/shim.h deleted file mode 100644 index 977820decdb9..000000000000 --- a/src/platform/apollolake/include/platform/lib/shim.h +++ /dev/null @@ -1,342 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <sof/bit.h> -#include <sof/lib/memory.h> - -#ifndef ASSEMBLY -#include <stdint.h> -#endif - -/* DSP IPC for Host Registers */ -#define IPC_DIPCT 0x00 -#define IPC_DIPCTE 0x04 -#define IPC_DIPCI 0x08 -#define IPC_DIPCIE 0x0c -#define IPC_DIPCCTL 0x10 - -/* DIPCT */ -#define IPC_DIPCT_BUSY BIT(31) -#define IPC_DIPCT_MSG_MASK 0x7FFFFFFF - -/* DIPCTE */ -#define IPC_DIPCTE_MSG_MASK 0x3FFFFFFF - -/* DIPCI */ -#define IPC_DIPCI_BUSY BIT(31) -#define IPC_DIPCI_MSG_MASK 0x7FFFFFFF - -/* DIPCIE */ -#define IPC_DIPCIE_DONE BIT(30) -#define IPC_DIPCIE_MSG_MASK 0x3FFFFFFF - -/* DIPCCTL */ -#define IPC_DIPCCTL_IPCIDIE BIT(1) -#define IPC_DIPCCTL_IPCTBIE BIT(0) - -#define IPC_DSP_OFFSET 0x10 - -/* DSP IPC for intra DSP communication */ -#define IPC_IDCTFC(x) (0x0 + x * IPC_DSP_OFFSET) -#define IPC_IDCTEFC(x) (0x4 + x * IPC_DSP_OFFSET) -#define IPC_IDCITC(x) (0x8 + x * IPC_DSP_OFFSET) -#define IPC_IDCIETC(x) (0xc + x * IPC_DSP_OFFSET) -#define IPC_IDCCTL 0x50 - -/* IDCTFC */ -#define IPC_IDCTFC_BUSY BIT(31) -#define IPC_IDCTFC_MSG_MASK 0x7FFFFFFF - -/* IDCTEFC */ -#define IPC_IDCTEFC_MSG_MASK 0x3FFFFFFF - -/* IDCITC */ -#define IPC_IDCITC_BUSY BIT(31) -#define IPC_IDCITC_MSG_MASK 0x7FFFFFFF - -/* IDCIETC */ -#define IPC_IDCIETC_DONE BIT(30) -#define IPC_IDCIETC_MSG_MASK 0x3FFFFFFF - -/* IDCCTL */ -#define IPC_IDCCTL_IDCIDIE(x) (0x100 << (x)) -#define IPC_IDCCTL_IDCTBIE(x) BIT(x) - -#define IRQ_CPU_OFFSET 0x40 - -#define REG_IRQ_IL2MSD(xcpu) (0x0 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MCD(xcpu) (0x4 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MD(xcpu) (0x8 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2SD(xcpu) (0xc + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL2MD_ALL 0x03F181F0 - -#define REG_IRQ_IL3MSD(xcpu) (0x10 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MCD(xcpu) (0x14 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MD(xcpu) (0x18 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3SD(xcpu) (0x1c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL3MD_ALL 0x807F81FF - -#define REG_IRQ_IL4MSD(xcpu) (0x20 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MCD(xcpu) (0x24 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MD(xcpu) (0x28 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4SD(xcpu) (0x2c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL4MD_ALL 0x807F81FF - -#define REG_IRQ_IL5MSD(xcpu) (0x30 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MCD(xcpu) (0x34 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MD(xcpu) (0x38 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5SD(xcpu) (0x3c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL5MD_ALL 0xFFFFC0CF - -#define REG_IRQ_IL2RSD 0x100 -#define REG_IRQ_IL3RSD 0x104 -#define REG_IRQ_IL4RSD 0x108 -#define REG_IRQ_IL5RSD 0x10c - -#define REG_IRQ_LVL5_LP_GPDMA0_MASK (0xff << 16) -#define REG_IRQ_LVL5_LP_GPDMA1_MASK (0xff << 24) - -/* DSP Shim Registers */ -#define SHIM_DSPWC 0x20 /* DSP Wall Clock */ -#define SHIM_DSPWCTCS 0x28 /* DSP Wall Clock Timer Control & Status */ -#define SHIM_DSPWCT0C 0x30 /* DSP Wall Clock Timer 0 Compare */ -#define SHIM_DSPWCT1C 0x38 /* DSP Wall Clock Timer 1 Compare */ - -#define SHIM_DSPWCTCS_T1T BIT(5) /* Timer 1 triggered */ -#define SHIM_DSPWCTCS_T0T BIT(4) /* Timer 0 triggered */ -#define SHIM_DSPWCTCS_T1A BIT(1) /* Timer 1 armed */ -#define SHIM_DSPWCTCS_T0A BIT(0) /* Timer 0 armed */ - -/** \brief Clock control */ -#define SHIM_CLKCTL 0x78 - -/** \brief Clock status */ -#define SHIM_CLKSTS 0x7C - -/** \brief Request Audio PLL Clock */ -#define SHIM_CLKCTL_RAPLLC BIT(31) - -/** \brief Request XTAL Oscillator Clock */ -#define SHIM_CLKCTL_RXOSCC BIT(30) - -/** \brief Request Fast RING Oscillator Clock */ -#define SHIM_CLKCTL_RFROSCC BIT(29) - -/** \brief LP GPDMA Force Dynamic Clock Gating bits, 0: enable */ -#define SHIM_CLKCTL_LPGPDMAFDCGB(x) BIT(26 + x) - -/** \brief DMIC Force Dynamic Clock Gating */ -#define SHIM_CLKCTL_DMICFDCGB BIT(24) - -/** \brief I2S Force Dynamic Clock Gating */ -#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) - -/** \brief I2S Extension Force Dynamic Clock Gating */ -#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) - -/** \brief Tensilica Core Prevent Local Clock Gating */ -#define SHIM_CLKCTL_TCPLCG_EN(x) BIT(16 + (x)) -#define SHIM_CLKCTL_TCPLCG_DIS(x) 0 - -/** \brief Core clock PLL divisor */ -#define SHIM_CLKCTL_DPCS_MASK(x) (0x3 << (8 + x * 2)) -#define SHIM_CLKCTL_DPCS_DIV1(x) (0x0 << (8 + x * 2)) -#define SHIM_CLKCTL_DPCS_DIV2(x) (0x1 << (8 + x * 2)) -#define SHIM_CLKCTL_DPCS_DIV4(x) (0x3 << (8 + x * 2)) - -/** \brief Tensilica Core Prevent Audio PLL Shutdown */ -#define SHIM_CLKCTL_TCPAPLLS_EN BIT(7) -#define SHIM_CLKCTL_TCPAPLLS_DIS 0 - -/** \brief LP domain clock select, 0: PLL, 1: oscillator */ -#define SHIM_CLKCTL_LDCS_XTAL BIT(5) -#define SHIM_CLKCTL_LDCS_PLL 0 - -/** \brief HP domain clock select */ -#define SHIM_CLKCTL_HDCS BIT(4) -#define SHIM_CLKCTL_HDCS_XTAL BIT(4) -#define SHIM_CLKCTL_HDCS_PLL 0 - -/** \brief LP domain oscillator clock select select, 0: XTAL, 1: Fast RING */ -#define SHIM_CLKCTL_LDOCS BIT(3) - -/** \brief HP domain oscillator clock select select, 0: XTAL, 1: Fast RING */ -#define SHIM_CLKCTL_HDOCS BIT(2) - -/** \brief LP memory clock PLL divisor, 0: div by 2, 1: div by 4 */ -#define SHIM_CLKCTL_LPMPCS_DIV4 BIT(1) -#define SHIM_CLKCTL_LPMPCS_DIV2 0 - -/** \brief HP memory clock PLL divisor, 0: div by 2, 1: div by 4 */ -#define SHIM_CLKCTL_HPMPCS_DIV4 BIT(0) -#define SHIM_CLKCTL_HPMPCS_DIV2 0 - -#define SHIM_PWRCTL 0x90 -#define SHIM_PWRSTS 0x92 -#define SHIM_LPSCTL 0x94 - -/* HP & LP SRAM Power Gating */ -#define SHIM_HSPGCTL 0x80 -#define SHIM_LSPGCTL 0x84 -#define SHIM_SPSREQ 0xa0 -#define LSPGCTL (SHIM_BASE + SHIM_LSPGCTL) - -#define SHIM_SPSREQ_RVNNP BIT(0) - -/** \brief GPDMA shim registers Control */ -#define SHIM_GPDMA_BASE_OFFSET 0xC00 -#define SHIM_GPDMA_BASE(x) (SHIM_GPDMA_BASE_OFFSET + (x) * 0x80) - -/** \brief GPDMA Channel Linear Link Position Control */ -#define SHIM_GPDMA_CHLLPC(x, y) (SHIM_GPDMA_BASE(x) + (y) * 0x10) -#define SHIM_GPDMA_CHLLPC_EN BIT(5) -#define SHIM_GPDMA_CHLLPC_DHRS(x) SET_BITS(4, 0, x) - -/** \brief LDO Control */ -#define SHIM_LDOCTL 0xA4 -#define SHIM_LDOCTL_HPSRAM_MASK (3 << 0) -#define SHIM_LDOCTL_LPSRAM_MASK (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) -#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS BIT(2) -#define SHIM_LDOCTL_HPSRAM_LDO_OFF (0 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_OFF (0 << 2) - -#define SHIM_HSPGISTS 0xb0 -#define SHIM_LSPGISTS 0xb4 -#define LSPGISTS (SHIM_BASE + SHIM_LSPGISTS) - - -#define SHIM_LPSCTL_FDSPRUN BIT(9) -#define SHIM_LPSCTL_FDMARUN BIT(8) - -#define SHIM_L2_MECS (SHIM_BASE + 0xd0) - -#define SHIM_LPGPDMAC(x) (0x1110 + (2 * x)) -#define SHIM_LPGPDMAC_CTLOSEL BIT(15) -#define SHIM_LPGPDMAC_CHOSEL 0xFF - -#define SHIM_DSPIOPO 0x1118 -#define SHIM_DSPIOPO_DMICOSEL BIT(0) -#define SHIM_DSPIOPO_I2SOSEL (0x3F << 8) - -#define SHIM_GENO 0x111C -#define SHIM_GENO_SHIMOSEL BIT(0) -#define SHIM_GENO_MDIVOSEL BIT(1) -#define SHIM_GENO_DIOPTOSEL BIT(2) - -#define SHIM_L2_CACHE_CTRL (SHIM_BASE + 0x500) -#define SHIM_L2_PREF_CFG (SHIM_BASE + 0x508) -#define SHIM_L2_CACHE_PREF (SHIM_BASE + 0x510) - -#define SHIM_SVCFG 0xF4 -#define SHIM_SVCFG_FORCE_L1_EXIT BIT(1) - -/* host windows */ -#define DMWBA(x) (HOST_WIN_BASE(x) + 0x0) -#define DMWLO(x) (HOST_WIN_BASE(x) + 0x4) - -#define DMWBA_ENABLE BIT(0) -#define DMWBA_READONLY BIT(1) - -#ifndef ASSEMBLY - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint64_t shim_read64(uint32_t reg) -{ - return *((volatile uint64_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write64(uint32_t reg, uint64_t val) -{ - *((volatile uint64_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t sw_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)); -} - -static inline void sw_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)) = val; -} - -static inline uint32_t mn_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)(MN_BASE + reg)); -} - -static inline void mn_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(MN_BASE + reg)) = val; -} - -static inline uint32_t irq_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IRQ_BASE + reg)); -} - -static inline void irq_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IRQ_BASE + reg)) = val; -} - -static inline uint32_t ipc_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IPC_HOST_BASE + reg)); -} - -static inline void ipc_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IPC_HOST_BASE + reg)) = val; -} - -static inline uint32_t idc_read(uint32_t reg, uint32_t core_id) -{ - return *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)); -} - -static inline void idc_write(uint32_t reg, uint32_t core_id, uint32_t val) -{ - *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)) = val; -} -#endif - -#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/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h deleted file mode 100644 index 8355b62125e2..000000000000 --- a/src/platform/apollolake/include/platform/platform.h +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Xiuli Pan <xiuli.pan@linux.intel.com> - */ - -#ifdef __SOF_PLATFORM_H__ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_RESET_MHE_AT_BOOT 1 - -#define PLATFORM_DISABLE_L2CACHE_AT_BOOT 1 - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> -#include <stddef.h> -#include <stdint.h> - -struct ll_schedule_domain; -struct timer; - -/*! \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 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 -#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_BIT_LVL2_HOST_IPC -#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL - -/* 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) - -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 500 - -/* platform has DMA memory type */ -#define PLATFORM_MEM_HAS_DMA - -/* platform has low power memory type */ -#define PLATFORM_MEM_HAS_LP_RAM - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* minimal L1 exit time in cycles */ -#define PLATFORM_FORCE_L1_EXIT_TIME 585 - -/* the SSP port fifo depth */ -#define SSP_FIFO_DEPTH 16 - -/* the watermark for the SSP fifo depth setting */ -#define SSP_FIFO_WATERMARK 8 - -/* minimal SSP port delay in cycles */ -#define PLATFORM_SSP_DELAY 800 - -/* Platform defined panic code */ -static inline void platform_panic(uint32_t p) -{ - mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p & 0x3fffffff); - ipc_write(IPC_DIPCIE, MAILBOX_EXCEPTION_OFFSET + 2 * 0x20000); - ipc_write(IPC_DIPCI, 0x80000000 | (p & 0x3fffffff)); -} - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -void platform_wait_for_interrupt(int level); - -extern intptr_t _module_init_start; -extern intptr_t _module_init_end; - -#endif -#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/apollolake/include/platform/trace/trace.h b/src/platform/apollolake/include/platform/trace/trace.h deleted file mode 100644 index 22a480092132..000000000000 --- a/src/platform/apollolake/include/platform/trace/trace.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_TRACE_TRACE_H__ - -#ifndef __PLATFORM_TRACE_TRACE_H__ -#define __PLATFORM_TRACE_TRACE_H__ - -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - mailbox_sw_reg_write(SRAM_REG_FW_TRACEP, (__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/apollolake/lib/CMakeLists.txt b/src/platform/apollolake/lib/CMakeLists.txt deleted file mode 100644 index c60199960955..000000000000 --- a/src/platform/apollolake/lib/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof - clk.c - power_down.S -) diff --git a/src/platform/apollolake/lib/clk.c b/src/platform/apollolake/lib/clk.c deleted file mode 100644 index 4823b633abd5..000000000000 --- a/src/platform/apollolake/lib/clk.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> - -const struct freq_table platform_cpu_freq[] = { - { 100000000, 100000 }, - { 200000000, 200000 }, - { CLK_MAX_CPU_HZ, 400000 }, -}; - -const uint32_t cpu_freq_enc[] = { - 0x3, - 0x1, - 0x0, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table *cpu_freq = platform_cpu_freq; - -/* IMPORTANT: array should be filled in increasing order - * (regarding to .freq field) - */ -const struct freq_table platform_ssp_freq[] = { - { 19200000, 19200 }, - { 24576000, 24576 }, - { 96000000, 96000 }, -}; - -const uint32_t platform_ssp_freq_sources[] = { - SSP_CLOCK_XTAL_OSCILLATOR, - SSP_CLOCK_AUDIO_CARDINAL, - SSP_CLOCK_PLL_FIXED, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; diff --git a/src/platform/apollolake/lib/power_down.S b/src/platform/apollolake/lib/power_down.S deleted file mode 100644 index 8c607e743c79..000000000000 --- a/src/platform/apollolake/lib/power_down.S +++ /dev/null @@ -1,150 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Lech Betlej <lech.betlej@linux.intel.com> - */ - -/** - * \file platform/apollolake/lib/power_down.S - * \brief Power gating memory banks - implementation specific for Apollolake - * \author Lech Betlej <lech.betlej@linux.intel.com> - */ -#include <platform/lib/asm_ldo_management.h> -#include <platform/lib/asm_memory_management.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> - - .section .text, "ax" - .align 64 -literals: - .literal_position - .global power_down - .type power_down, @function -/** - * Perform power down. - * - * Depending on arguments, memories are switched off. - * A2 - argument for LPSRAM - * A3 - pointer to array containing power gating mask. - * - * Finally, core enters waiti. - */ - -#define b_enable_lpsram a2 -#define pu32_hpsram_mask a3 -#define temp_reg0 a6 -#define temp_reg1 a7 -#define temp_reg2 a8 -#define temp_reg3 a9 -#define pfl_reg a15 - - .align 64 -power_down: - entry sp, 32 - // effectively executes: - // xthal_dcache_region_lock(&literals, 128); - // xthal_dcache_region_lock(&power_down, 384); - // xthal_dcache_region_lock(&pu32_hpsram_mask, 64); - movi pfl_reg, literals - dpfl pfl_reg, 0 - dpfl pfl_reg, 64 - - movi pfl_reg, power_down - ipfl pfl_reg, 0 - ipfl pfl_reg, 64 - ipfl pfl_reg, 128 - ipfl pfl_reg, 192 - addi pfl_reg, pfl_reg, 256 - ipfl pfl_reg, 0 - ipfl pfl_reg, 64 - - mov pfl_reg, pu32_hpsram_mask - dpfl pfl_reg, 0 - - // if b_enable_lpsram = 0 (bool disable_lpsram) - do not disable lpsram. - beqz b_enable_lpsram, _PD_DISABLE_HPSRAM - -_PD_DISABLE_LPSRAM: - movi temp_reg0, SHIM_LDOCTL_LPSRAM_LDO_ON - m_cavs_set_lpldo_state temp_reg0, temp_reg1, temp_reg2 - - m_cavs_lpsram_power_off temp_reg0, temp_reg1, temp_reg2 - - movi temp_reg0, SHIM_LDOCTL_LPSRAM_LDO_OFF - m_cavs_set_lpldo_state temp_reg0, temp_reg1, temp_reg2 - - // DISABLE_HPSRAM is aligned so there can be zeros between - //it and last instr. - j _PD_DISABLE_HPSRAM - - // workaround for incidental gnu assembler bug - no alignment here - // (see comment before IPFL) ... - // .align 64 -_PD_DISABLE_HPSRAM: - // if value in memory pointed by pu32_hpsram_mask = 0 - // (hpsram_pwrgating_mask) - do not disable hpsram. - l32i temp_reg0, pu32_hpsram_mask, 0 - beqz temp_reg0, _PD_SLEEP - - movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_ON - m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2 - // Disable L2 cache in case it would be enabled - - m_cavs_hpsram_power_off temp_reg0, temp_reg1, temp_reg2 - - movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_OFF - m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2 - - // For BXT-P we need to deassert VNN request and select slow XTAL - // as clock source - // APL specific code _PD_SWITCH_TO_XTAL_CLOCK: and _PD_RELEASE_VNN -_PD_SWITCH_TO_XTAL_CLOCK: - // TODO: move to CLOCK hal macros - movi temp_reg0, (SHIM_BASE + SHIM_CLKCTL) - movi temp_reg1, ~(SHIM_CLKCTL_HDOCS | SHIM_CLKCTL_LDOCS) - movi temp_reg2, (SHIM_CLKCTL_LDCS_XTAL | SHIM_CLKCTL_HDCS_XTAL) - l32i temp_reg3, temp_reg0, 0 - // Reset LDOCS & HDOCS bits to select XTAL - and temp_reg3, temp_reg3, temp_reg1 - // Set LDCS & HDCS so clock selection depends on LDOCS & HDOCS - or temp_reg3, temp_reg3, temp_reg2 - s32i temp_reg3, temp_reg0, 0 - -_PD_RELEASE_VNN: - // TODO: move to VNN/SHIM hal macros - movi temp_reg0, (SHIM_BASE + SHIM_SPSREQ) - movi temp_reg1, ~SHIM_SPSREQ_RVNNP - l32i temp_reg2, temp_reg0, 0 - and temp_reg2, temp_reg2, temp_reg1 - s32i temp_reg2, temp_reg0, 0 - l32i temp_reg2, temp_reg0, 0 - // We cannot wait for VNN to drop since it can be held by something else - // and never drop - -_PD_SEND_IPC: - // Send IPC to host informing of PD completion - Clear BUSY bit by - // writting IPC_DIPCT_BUSY to IPC_DIPCT - movi temp_reg0, IPC_HOST_BASE - l32i temp_reg1, temp_reg0, IPC_DIPCT - movi temp_reg2, IPC_DIPCT_BUSY - or temp_reg1, temp_reg1, temp_reg2 - s32i temp_reg1, temp_reg0, IPC_DIPCT - -_PD_SLEEP: - // effecfively executes: - // xmp_spin() - // waiti 5 - movi temp_reg0, 128 -loop: - addi temp_reg0, temp_reg0, -1 - bnez temp_reg0, loop - - extw - extw - waiti 5 - j _PD_SLEEP - - .size power_down , . - power_down - - diff --git a/src/platform/apollolake/rom.x.in b/src/platform/apollolake/rom.x.in deleted file mode 100644 index d811b63c2c75..000000000000 --- a/src/platform/apollolake/rom.x.in +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Linker Script for Apollolake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = ROM_BASE, - len = ROM_RESET_TEXT_SIZE - vector_reset_lit : - org = ROM_BASE + ROM_RESET_TEXT_SIZE, - len = ROM_RESET_LIT_SIZE - vector_base_text : - org = ROM_BASE + ROM_RESET_TEXT_SIZE + ROM_RESET_LIT_SIZE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = ROM_BASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = ROM_BASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = ROM_BASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = ROM_BASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text : - org = ROM_BASE + 0x800, - len = ROM_SIZE, - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; -} - -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = ROM_BASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - /* stack */ - _end = BOOT_LDR_STACK_BASE; - PROVIDE(end = BOOT_LDR_STACK_BASE); - _stack_sentry = BOOT_LDR_STACK_BASE; - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/baytrail/baytrail.x.in b/src/platform/baytrail/baytrail.x.in deleted file mode 100644 index 996b739114bd..000000000000 --- a/src/platform/baytrail/baytrail.x.in +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Linker Script for Baytrail. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = SOF_MEM_RESET_VECT, - len = SOF_MEM_RESET_TEXT_SIZE - vector_reset_lit : - org = SOF_MEM_RESET_VECT + SOF_MEM_RESET_TEXT_SIZE, - len = SOF_MEM_RESET_LIT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = SOF_MEM_INTLEVEL2_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = SOF_MEM_INTLEVEL2_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = SOF_MEM_INTLEVEL3_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = SOF_MEM_INTLEVEL3_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = SOF_MEM_INTLEVEL4_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = SOF_MEM_INTLEVEL4_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = SOF_MEM_INTLEVEL5_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = SOF_MEM_INTLEVEL5_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = SOF_MEM_INTLEVEL6_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = SOF_MEM_INTLEVEL6_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = SOF_MEM_INTLEVEL7_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = SOF_MEM_INTLEVEL7_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = SOF_MEM_KERNEL_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = SOF_MEM_KERNEL_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = SOF_MEM_USER_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = SOF_MEM_USER_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = SOF_MEM_DOUBLEEXC_VECT - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = SOF_MEM_DOUBLEEXC_VECT, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text_start : - org = SOF_MEM_DOUBLEEXC_VECT + SOF_MEM_VECT_SIZE, - len = (IRAM_BASE + IRAM_SIZE) - (SOF_MEM_DOUBLEEXC_VECT + SOF_MEM_VECT_SIZE) - sof_data_ro : - org = DRAM0_BASE, - len = SOF_MEM_RO_SIZE - sof_data : - org = DRAM0_BASE + SOF_MEM_RO_SIZE, - len = HEAP_SYSTEM_BASE - (DRAM0_BASE + SOF_MEM_RO_SIZE) - system_heap : - org = HEAP_SYSTEM_BASE, - len = HEAP_SYSTEM_SIZE - system_runtime_heap : - org = HEAP_SYS_RUNTIME_BASE, - len = HEAP_SYS_RUNTIME_SIZE - runtime_heap : - org = HEAP_RUNTIME_BASE, - len = HEAP_RUNTIME_SIZE - buffer_heap : - org = HEAP_BUFFER_BASE, - len = HEAP_BUFFER_SIZE - sof_stack : - org = SOF_STACK_END, - len = SOF_STACK_BASE - SOF_STACK_END - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_base_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - sof_text_start_phdr PT_LOAD; - sof_data_ro_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_data_bss_phdr PT_LOAD; - system_heap_phdr PT_LOAD; - system_runtime_heap_phdr PT_LOAD; - runtime_heap_phdr PT_LOAD; - buffer_heap_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; -} - -/* Default entry point: */ -ENTRY(_ResetVector) -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = SOF_MEM_VECBASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wb_base = 0x44024000; -_memmap_cacheattr_wt_base = 0x11021000; -_memmap_cacheattr_bp_base = 0x22022000; -_memmap_cacheattr_unused_mask = 0x00F00FFF; -_memmap_cacheattr_wb_trapnull = 0x4422422F; -_memmap_cacheattr_wba_trapnull = 0x4422422F; -_memmap_cacheattr_wbna_trapnull = 0x25222222; -_memmap_cacheattr_wt_trapnull = 0x1122122F; -_memmap_cacheattr_bp_trapnull = 0x2222222F; -_memmap_cacheattr_wb_strict = 0x44F24FFF; -_memmap_cacheattr_wt_strict = 0x11F21FFF; -_memmap_cacheattr_bp_strict = 0x22F22FFF; -_memmap_cacheattr_wb_allvalid = 0x44224222; -_memmap_cacheattr_wt_allvalid = 0x11221222; -_memmap_cacheattr_bp_allvalid = 0x22222222; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text_start :sof_text_start_phdr - - .reset.rodata : ALIGN(4) - { - _reset_rodata_start = ABSOLUTE(.); - *(.reset.rodata) - _reset_rodata_end = ABSOLUTE(.); - } >sof_data_ro :sof_data_ro_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_data :sof_data_bss_phdr - - /* stack */ - _end = SOF_STACK_END; - PROVIDE(end = SOF_STACK_END); - _stack_sentry = SOF_STACK_END; - __stack = SOF_STACK_BASE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .system_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_SIZE; - _system_heap_end = ABSOLUTE(.); - } >system_heap :system_heap_phdr - - .system_runtime_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - } >system_runtime_heap :system_runtime_heap_phdr - - .runtime_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - } >runtime_heap :runtime_heap_phdr - - .buffer_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - } >buffer_heap :buffer_heap_phdr - - .sof_stack (NOLOAD) : ALIGN(8) - { - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_TOTAL_SIZE; - _sof_stack_end = ABSOLUTE(.); - } >sof_stack :sof_stack_phdr - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_data :sof_data_phdr -} diff --git a/src/platform/baytrail/include/arch/xtensa/config/core-isa.h b/src/platform/baytrail/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index 0c6558ba9691..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Customer ID=11430; Build=0x668e9; Copyright (c) 1999-2017 Tensilica 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. */ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 0 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_FP 0 /* floating point pkg */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_accel 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2 1 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2_MUL32X24 1 /* HiFi2 and 32x24 MACs */ -#define XCHAL_HAVE_HIFI2EP 1 /* HiFi2EP */ -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ - - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 16 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 900005 /* sw version of this header */ - -#define XCHAL_CORE_ID "Intel_HiFiEP" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x000668E9 /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC3B3CFFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x15455C8A /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX4.0.5" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2400 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 5 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 240005 /* major*100+minor */ -#define XCHAL_HW_REL_LX4 1 -#define XCHAL_HW_REL_LX4_0 1 -#define XCHAL_HW_REL_LX4_0_5 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2400 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 5 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 240005 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2400 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 5 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 240005 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 49152 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 98304 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 7 -#define XCHAL_DCACHE_SETWIDTH 8 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 3 -#define XCHAL_DCACHE_WAYS 3 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY 0 -#define XCHAL_DCACHE_ECC_PARITY 0 - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 8 -#define XCHAL_DCACHE_ACCESS_SIZE 8 - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -/* Instruction RAM 0: */ -#define XCHAL_INSTRAM0_VADDR 0xFF2C0000 -#define XCHAL_INSTRAM0_PADDR 0xFF2C0000 -#define XCHAL_INSTRAM0_SIZE 65536 -#define XCHAL_INSTRAM0_ECC_PARITY 0 - -/* Instruction RAM 1: */ -#define XCHAL_INSTRAM1_VADDR 0xFF2D0000 -#define XCHAL_INSTRAM1_PADDR 0xFF2D0000 -#define XCHAL_INSTRAM1_SIZE 16384 -#define XCHAL_INSTRAM1_ECC_PARITY 0 - -/* Data RAM 0: */ -#define XCHAL_DATARAM0_VADDR 0xFF300000 -#define XCHAL_DATARAM0_PADDR 0xFF300000 -#define XCHAL_DATARAM0_SIZE 131072 -#define XCHAL_DATARAM0_ECC_PARITY 0 - -/* Data RAM 1: */ -#define XCHAL_DATARAM1_VADDR 0xFF320000 -#define XCHAL_DATARAM1_PADDR 0xFF320000 -#define XCHAL_DATARAM1_SIZE 32768 -#define XCHAL_DATARAM1_ECC_PARITY 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 22 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 12 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x0000000F -#define XCHAL_INTLEVEL2_MASK 0x00000070 -#define XCHAL_INTLEVEL3_MASK 0x00000380 -#define XCHAL_INTLEVEL4_MASK 0x00200C00 -#define XCHAL_INTLEVEL5_MASK 0x000FF000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00100000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000000F -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x0000007F -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x000003FF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00200FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x002FFFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x002FFFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x003FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 2 -#define XCHAL_INT5_LEVEL 2 -#define XCHAL_INT6_LEVEL 2 -#define XCHAL_INT7_LEVEL 3 -#define XCHAL_INT8_LEVEL 3 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 4 -#define XCHAL_INT11_LEVEL 4 -#define XCHAL_INT12_LEVEL 5 -#define XCHAL_INT13_LEVEL 5 -#define XCHAL_INT14_LEVEL 5 -#define XCHAL_INT15_LEVEL 5 -#define XCHAL_INT16_LEVEL 5 -#define XCHAL_INT17_LEVEL 5 -#define XCHAL_INT18_LEVEL 5 -#define XCHAL_INT19_LEVEL 5 -#define XCHAL_INT20_LEVEL 7 -#define XCHAL_INT21_LEVEL 4 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_NMI -#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFC00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0000134D -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x002FEC10 -#define XCHAL_INTTYPE_MASK_TIMER 0x000000A2 -#define XCHAL_INTTYPE_MASK_NMI 0x00100000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 1 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 5 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 7 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 20 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL7_NUM 20 -/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ - - -/* - * External interrupt vectors/levels. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */ -#define XCHAL_EXTINT0_NUM 4 /* (intlevel 2) */ -#define XCHAL_EXTINT1_NUM 10 /* (intlevel 4) */ -#define XCHAL_EXTINT2_NUM 11 /* (intlevel 4) */ -#define XCHAL_EXTINT3_NUM 13 /* (intlevel 5) */ -#define XCHAL_EXTINT4_NUM 14 /* (intlevel 5) */ -#define XCHAL_EXTINT5_NUM 15 /* (intlevel 5) */ -#define XCHAL_EXTINT6_NUM 16 /* (intlevel 5) */ -#define XCHAL_EXTINT7_NUM 17 /* (intlevel 5) */ -#define XCHAL_EXTINT8_NUM 18 /* (intlevel 5) */ -#define XCHAL_EXTINT9_NUM 19 /* (intlevel 5) */ -#define XCHAL_EXTINT10_NUM 20 /* (intlevel 7) */ -#define XCHAL_EXTINT11_NUM 21 /* (intlevel 4) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0x00100400 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0x00100400 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0x00100000 -#define XCHAL_RESET_VECTOR0_PADDR 0x00100000 -#define XCHAL_RESET_VECTOR1_VADDR 0xFF2C0000 -#define XCHAL_RESET_VECTOR1_PADDR 0xFF2C0000 -#define XCHAL_RESET_VECTOR_VADDR 0x00100000 -#define XCHAL_RESET_VECTOR_PADDR 0x00100000 -#define XCHAL_USER_VECOFS 0x0000025C -#define XCHAL_USER_VECTOR_VADDR 0x0010065C -#define XCHAL_USER_VECTOR_PADDR 0x0010065C -#define XCHAL_KERNEL_VECOFS 0x0000023C -#define XCHAL_KERNEL_VECTOR_VADDR 0x0010063C -#define XCHAL_KERNEL_VECTOR_PADDR 0x0010063C -#define XCHAL_DOUBLEEXC_VECOFS 0x0000027C -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x0010067C -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x0010067C -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0x00100400 -#define XCHAL_WINDOW_VECTORS_PADDR 0x00100400 -#define XCHAL_INTLEVEL2_VECOFS 0x0000017C -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x0010057C -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x0010057C -#define XCHAL_INTLEVEL3_VECOFS 0x0000019C -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x0010059C -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x0010059C -#define XCHAL_INTLEVEL4_VECOFS 0x000001BC -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x001005BC -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x001005BC -#define XCHAL_INTLEVEL5_VECOFS 0x000001DC -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x001005DC -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x001005DC -#define XCHAL_INTLEVEL6_VECOFS 0x000001FC -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x001005FC -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x001005FC -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x0000021C -#define XCHAL_NMI_VECTOR_VADDR 0x0010061C -#define XCHAL_NMI_VECTOR_PADDR 0x0010061C -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 0 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 1 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ -/* If none of the above last 4 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ diff --git a/src/platform/baytrail/include/arch/xtensa/config/core-matmap.h b/src/platform/baytrail/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index 62329df8cba5..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,312 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Customer ID=11430; Build=0x668e9; Copyright (c) 1999-2017 Tensilica 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. */ - - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefined hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Reset PPN values for each entry of ITLB way set 0 (because SET0_PPN_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_RESET 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_RESET 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_RESET 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_RESET 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_RESET 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_RESET 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_RESET 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_RESET 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 1 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Reset PPN values for each entry of DTLB way set 0 (because SET0_PPN_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_RESET 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_RESET 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_RESET 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_RESET 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_RESET 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_RESET 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_RESET 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_RESET 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ diff --git a/src/platform/baytrail/include/arch/xtensa/config/defs.h b/src/platform/baytrail/include/arch/xtensa/config/defs.h deleted file mode 100644 index b994c4114a94..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Customer ID=11430; Build=0x668e9; Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/baytrail/include/arch/xtensa/config/specreg.h b/src/platform/baytrail/include/arch/xtensa/config/specreg.h deleted file mode 100644 index f6e402727a97..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Cottonwood/Xtensa/SWConfig/hal/specreg.h.tpp#2 $ */ - -/* Customer ID=11430; Build=0x668e9; Copyright (c) 1998-2002 Tensilica 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. */ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define ACCLO 16 -#define ACCHI 17 -#define MR_0 32 -#define MR_1 33 -#define MR_2 34 -#define MR_3 35 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define ATOMCTL 99 -#define DDR 104 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 - -/* Special cases (bases of special register series): */ -#define MR 32 -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -/* Special names for read-only and write-only interrupt registers: */ -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 - -#endif /* XTENSA_SPECREG_H */ diff --git a/src/platform/baytrail/include/arch/xtensa/config/system.h b/src/platform/baytrail/include/arch/xtensa/config/system.h deleted file mode 100644 index 8db075bbcf96..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Customer ID=11430; Build=0x668e9; Copyright (c) 2000-2010 Tensilica 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. */ - - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -/*#define XSHAL_ROM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ROM_SIZE ...not configured...*/ -/*#define XSHAL_ROM_AVAIL_V{ADDR,SIZE} ...not configured...*/ - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x00100000 -#define XSHAL_RAM_PADDR 0x00100000 -#define XSHAL_RAM_VSIZE 0x80000000 -#define XSHAL_RAM_PSIZE 0x80000000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x00100698 -#define XSHAL_RAM_AVAIL_VSIZE 0x7FFFF968 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0xA0000000 -#define XSHAL_RAM_BYPASS_PADDR 0xA0000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit routines. - */ - -#define XSHAL_MAGIC_LOCAL_EXIT 0xc0000000 -#define XSHAL_MAGIC_EXIT XSHAL_SIMIO_BYPASS_VADDR /* (have PIF) */ - - - - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x42244444 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x12211111 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x12211111 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0x4FF44444 /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0x1FF11111 /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0x1FF11111 /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0x2FF22222 /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x42244444 /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x12211111 /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x12211111 /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x4F244244 /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x1F211211 /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x1F211211 /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0x2F222222 /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000401 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0x00100000 -#define XSHAL_RESET_VECTOR_PADDR 0x00100000 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 -#define XSHAL_RESET_VECTOR_ISROM 0 -#define XSHAL_USER_VECTOR_SIZE 0x0000001C -#define XSHAL_USER_VECTOR_ISROM 0 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C -#define XSHAL_KERNEL_VECTOR_ISROM 0 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 0 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C -#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C -#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C -#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x0000001C -#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x0000001C -#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x0000001C -#define XSHAL_NMI_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ diff --git a/src/platform/baytrail/include/arch/xtensa/config/tie-asm.h b/src/platform/baytrail/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index 6b4c77dbba1d..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Customer ID=11430; Build=0x668e9; Copyright (c) 1999-2017 Tensilica 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. */ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - - /* - * Macro to save all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global register used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1020, 4, 4 - rur.THREADPTR \at1 // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_+0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1020, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rsr.ACCLO \at1 // MAC16 option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.ACCHI \at1 // MAC16 option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1000, 4, 4 - rsr.M0 \at1 // MAC16 option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.M1 \at1 // MAC16 option - s32i \at1, \ptr, .Lxchal_ofs_+4 - rsr.M2 \at1 // MAC16 option - s32i \at1, \ptr, .Lxchal_ofs_+8 - rsr.M3 \at1 // MAC16 option - s32i \at1, \ptr, .Lxchal_ofs_+12 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+16 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+20 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1000, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 - .endif - .endm // xchal_ncp_store - - /* - * Macro to restore all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global register used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1020, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.THREADPTR \at1 // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1020, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.ACCLO \at1 // MAC16 option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.ACCHI \at1 // MAC16 option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1000, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.M0 \at1 // MAC16 option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.M1 \at1 // MAC16 option - l32i \at1, \ptr, .Lxchal_ofs_+8 - wsr.M2 \at1 // MAC16 option - l32i \at1, \ptr, .Lxchal_ofs_+12 - wsr.M3 \at1 // MAC16 option - l32i \at1, \ptr, .Lxchal_ofs_+16 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+20 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1000, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - - - - /* - * Macro to save the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - rur.AE_CBEGIN0 \at1 // ureg 246 - s32i \at1, \ptr, .Lxchal_ofs_+16 - rur.AE_CEND0 \at1 // ureg 247 - s32i \at1, \ptr, .Lxchal_ofs_+20 - AE_SP24X2S.I aep0, \ptr, .Lxchal_ofs_+24 - AE_SP24X2S.I aep1, \ptr, .Lxchal_ofs_+32 - AE_SP24X2S.I aep2, \ptr, .Lxchal_ofs_+40 - AE_SP24X2S.I aep3, \ptr, .Lxchal_ofs_+48 - AE_SP24X2S.I aep4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - AE_SP24X2S.I aep5, \ptr, .Lxchal_ofs_+0 - AE_SP24X2S.I aep6, \ptr, .Lxchal_ofs_+8 - AE_SP24X2S.I aep7, \ptr, .Lxchal_ofs_+16 - AE_SQ56S.I aeq0, \ptr, .Lxchal_ofs_+24 - AE_SQ56S.I aeq1, \ptr, .Lxchal_ofs_+32 - AE_SQ56S.I aeq2, \ptr, .Lxchal_ofs_+40 - AE_SQ56S.I aeq3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 64 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 120 - .endif - .endm // xchal_cp1_store - - /* - * Macro to restore the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_SD_NO \at1 // ureg 243 - l32i \at1, \ptr, .Lxchal_ofs_+16 - wur.AE_CBEGIN0 \at1 // ureg 246 - l32i \at1, \ptr, .Lxchal_ofs_+20 - wur.AE_CEND0 \at1 // ureg 247 - AE_LP24X2.I aep0, \ptr, .Lxchal_ofs_+24 - AE_LP24X2.I aep1, \ptr, .Lxchal_ofs_+32 - AE_LP24X2.I aep2, \ptr, .Lxchal_ofs_+40 - AE_LP24X2.I aep3, \ptr, .Lxchal_ofs_+48 - AE_LP24X2.I aep4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - AE_LP24X2.I aep5, \ptr, .Lxchal_ofs_+0 - AE_LP24X2.I aep6, \ptr, .Lxchal_ofs_+8 - AE_LP24X2.I aep7, \ptr, .Lxchal_ofs_+16 - AE_LQ56.I aeq0, \ptr, .Lxchal_ofs_+24 - AE_LQ56.I aeq1, \ptr, .Lxchal_ofs_+32 - AE_LQ56.I aeq2, \ptr, .Lxchal_ofs_+40 - AE_LQ56.I aeq3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 64 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 120 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ diff --git a/src/platform/baytrail/include/arch/xtensa/config/tie.h b/src/platform/baytrail/include/arch/xtensa/config/tie.h deleted file mode 100644 index db0f1fec44fb..000000000000 --- a/src/platform/baytrail/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Customer ID=11430; Build=0x668e9; Copyright (c) 1999-2017 Tensilica 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. */ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 1 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 120 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP0_SA_SIZE 0 -#define XCHAL_CP0_SA_ALIGN 1 -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 36 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 176 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 9 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ - XCHAL_SA_REG(s,1,0,0,1, acclo, 4, 4, 4,0x0210, sr,16 , 32,0,0,0) \ - XCHAL_SA_REG(s,1,0,0,1, acchi, 4, 4, 4,0x0211, sr,17 , 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m0, 4, 4, 4,0x0220, sr,32 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m1, 4, 4, 4,0x0221, sr,33 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m2, 4, 4, 4,0x0222, sr,34 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, m3, 4, 4, 4,0x0223, sr,35 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 0 -#define XCHAL_CP0_SA_LIST(s) /* empty */ - -#define XCHAL_CP1_SA_NUM 18 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 7,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_sd_no, 4, 4, 4,0x03F3, ur,243, 28,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep0, 8, 8, 8,0x0060, aep,0 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep1, 8, 8, 8,0x0061, aep,1 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep2, 8, 8, 8,0x0062, aep,2 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep3, 8, 8, 8,0x0063, aep,3 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep4, 8, 8, 8,0x0064, aep,4 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep5, 8, 8, 8,0x0065, aep,5 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep6, 8, 8, 8,0x0066, aep,6 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep7, 8, 8, 8,0x0067, aep,7 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq0, 8, 8, 8,0x0068, aeq,0 , 56,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq1, 8, 8, 8,0x0069, aeq,1 , 56,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq2, 8, 8, 8,0x006A, aeq,2 , 56,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq3, 8, 8, 8,0x006B, aeq,3 , 56,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8 - -#endif /*_XTENSA_CORE_TIE_H*/ diff --git a/src/platform/baytrail/include/platform/drivers/dw-dma.h b/src/platform/baytrail/include/platform/drivers/dw-dma.h deleted file mode 100644 index 84f7284b73c2..000000000000 --- a/src/platform/baytrail/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <sof/bit.h> -#include <config.h> -#include <stdint.h> - -struct dma; -struct dma_chan_data; - - -/* number of supported DW-DMACs */ -#if CONFIG_CHERRYTRAIL_EXTRA_DW_DMA -#define PLATFORM_NUM_DW_DMACS 3 -#else -#define PLATFORM_NUM_DW_DMACS 2 -#endif - -/* index of the first DW-DMAC in the array */ -#define PLATFORM_DW_DMA_INDEX 0 - -/* DMA treats PHY addresses as host address unless within DSP region */ -#define PLATFORM_DW_DMA_HOST_MASK 0xFF000000 - -/* CTL_HI */ -#define DW_CTLH_CLASS(x) SET_BITS(31, 29, x) -#define DW_CTLH_WEIGHT(x) SET_BITS(28, 18, x) -#define DW_CTLH_DONE(x) SET_BIT(17, x) -#define DW_CTLH_BLOCK_TS_MASK MASK(16, 0) - -/* CFG_HI */ -#define DW_CFGH_DST_PER(x) SET_BITS(7, 4, x) -#define DW_CFGH_SRC_PER(x) SET_BITS(3, 0, x) -#define DW_CFGH_DST(x) DW_CFGH_DST_PER(x) -#define DW_CFGH_SRC(x) DW_CFGH_SRC_PER(x) - -/* default initial setup register values */ -#define DW_CFG_LOW_DEF 0x3 -#define DW_CFG_HIGH_DEF 0x0 - -#define platform_dw_dma_set_class(chan, lli, class) \ - (lli->ctrl_hi |= DW_CTLH_CLASS(class)) - -#define platform_dw_dma_set_transfer_size(chan, lli, size) \ - (lli->ctrl_hi |= (size & DW_CTLH_BLOCK_TS_MASK)) - -static inline void platform_dw_dma_llp_config(struct dma *dma, - struct dma_chan_data *chan, - uint32_t config) { } - -static inline void platform_dw_dma_llp_enable(struct dma *dma, - struct dma_chan_data *chan) { } - -static inline void platform_dw_dma_llp_disable(struct dma *dma, - struct dma_chan_data *chan) { } - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __SOF_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/baytrail/include/platform/drivers/idc.h b/src/platform/baytrail/include/platform/drivers/idc.h deleted file mode 100644 index 70a264d2dbc5..000000000000 --- a/src/platform/baytrail/include/platform/drivers/idc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <stdint.h> - -struct idc_msg; - -static inline int idc_send_msg(struct idc_msg *msg, - uint32_t mode) { return 0; } - -static inline int idc_init(void) { return 0; } - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/baytrail/include/platform/drivers/interrupt.h b/src/platform/baytrail/include/platform/drivers/interrupt.h deleted file mode 100644 index 4ef013fe9691..000000000000 --- a/src/platform/baytrail/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <sof/bit.h> -#include <config.h> - -/* IRQ numbers */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_SOFTWARE0 0 /* Level 1 */ -#define IRQ_NUM_TIMER1 1 /* Level 1 */ -#define IRQ_NUM_SOFTWARE1 2 /* Level 1 */ -#define IRQ_NUM_SOFTWARE2 3 /* Level 1 */ - -#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_TIMER2 5 /* Level 2 */ -#define IRQ_NUM_SOFTWARE3 6 /* Level 2 */ - -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_SOFTWARE3 BIT(IRQ_NUM_SOFTWARE3) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_TIMER3 7 /* Level 3 */ -#define IRQ_NUM_SOFTWARE4 8 /* Level 3 */ -#define IRQ_NUM_SOFTWARE5 9 /* Level 3 */ - -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) -#define IRQ_MASK_SOFTWARE4 BIT(IRQ_NUM_SOFTWARE4) -#define IRQ_MASK_SOFTWARE5 BIT(IRQ_NUM_SOFTWARE5) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_EXT_IA 10 /* Level 4 */ -#define IRQ_NUM_EXT_PMC 11 /* Level 4 */ - -#define IRQ_MASK_EXT_IA BIT(IRQ_NUM_EXT_IA) -#define IRQ_MASK_EXT_PMC BIT(IRQ_NUM_EXT_PMC) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_SOFTWARE6 12 /* Level 5 */ -#define IRQ_NUM_EXT_DMAC0 13 /* Level 5 */ -#define IRQ_NUM_EXT_DMAC1 14 /* Level 5 */ -#define IRQ_NUM_EXT_TIMER 15 /* Level 5 */ -#define IRQ_NUM_EXT_SSP0 16 /* Level 5 */ -#define IRQ_NUM_EXT_SSP1 17 /* Level 5 */ -#define IRQ_NUM_EXT_SSP2 18 /* Level 5 */ -#define IRQ_NUM_EXT_DMAC2 19 /* Level 5 */ - -/* SSP 3,4,5 share PHY IRQs with SSP 0,1,2 respectively but we give them a - * virtual number in order to differentiate from SSP0, 1 and 2 IRQs - */ -#define IRQ_CHT_SSP_OFFSET 16 - -/* Level 5 */ -#define IRQ_NUM_EXT_SSP3 (IRQ_CHT_SSP_OFFSET + IRQ_NUM_EXT_SSP0) -#define IRQ_NUM_EXT_SSP4 (IRQ_CHT_SSP_OFFSET + IRQ_NUM_EXT_SSP1) -#define IRQ_NUM_EXT_SSP5 (IRQ_CHT_SSP_OFFSET + IRQ_NUM_EXT_SSP2) - -#define IRQ_MASK_SOFTWARE6 BIT(IRQ_NUM_SOFTWARE6) -#define IRQ_MASK_EXT_DMAC0 BIT(IRQ_NUM_EXT_DMAC0) -#define IRQ_MASK_EXT_DMAC1 BIT(IRQ_NUM_EXT_DMAC1) -#define IRQ_MASK_EXT_TIMER BIT(IRQ_NUM_EXT_TIMER) -#define IRQ_MASK_EXT_SSP0 BIT(IRQ_NUM_EXT_SSP0) -#define IRQ_MASK_EXT_SSP1 BIT(IRQ_NUM_EXT_SSP1) -#define IRQ_MASK_EXT_SSP2 BIT(IRQ_NUM_EXT_SSP2) -#define IRQ_MASK_EXT_DMAC2 BIT(IRQ_NUM_EXT_DMAC2) - -#endif - -#define IRQ_NUM_NMI 20 /* Level 7 */ - -/* no nested interrupts */ -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 0 - -#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/baytrail/include/platform/drivers/pmc.h b/src/platform/baytrail/include/platform/drivers/pmc.h deleted file mode 100644 index eb2890630465..000000000000 --- a/src/platform/baytrail/include/platform/drivers/pmc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_PMC_H__ - -#ifndef __PLATFORM_DRIVERS_PMC_H__ -#define __PLATFORM_DRIVERS_PMC_H__ - -#include <config.h> -#include <stdint.h> - -/* messages */ -#define PMC_DDR_LINK_UP 0xc0 /* LPE req path to DRAM is up */ -#define PMC_DDR_LINK_DOWN 0xc1 /* LPE req path to DRAM is down */ -#define PMC_SET_LPECLK 0xc2 /* LPE req clock change to FR_LAT_REQ */ - -#if CONFIG_BAYTRAIL - -/* LPE req SSP clock to 19.2MHz w/ PLL*/ -#define PMC_SET_SSP_19M2 0xc5 - -/* LPE req SSP clock to 25MHz w/ XTAL */ -#define PMC_SET_SSP_25M 0xc6 - -#elif CONFIG_CHERRYTRAIL - -/* LPE req SSP clock to 25MHz w/ PLL */ -#define PMC_SET_SSP_25M 0xc5 - -/* LPE req SSP clock to 19.2MHz w/ XTAL */ -#define PMC_SET_SSP_19M2 0xc6 -#endif - -int platform_ipc_pmc_init(void); -int ipc_pmc_send_msg(uint32_t message); -int pmc_process_msg_queue(void); - -#endif /* __PLATFORM_DRIVERS_PMC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/pmc.h" - -#endif /* __SOF_DRIVERS_PMC_H__ */ diff --git a/src/platform/baytrail/include/platform/lib/clk.h b/src/platform/baytrail/include/platform/lib/clk.h deleted file mode 100644 index c9a60be78162..000000000000 --- a/src/platform/baytrail/include/platform/lib/clk.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <sof/drivers/pmc.h> -#include <sof/lib/io.h> -#include <sof/lib/shim.h> -#include <stdint.h> - -struct sof; - -#define CLK_CPU(x) (x) -#define CLK_SSP 1 - -#define CPU_DEFAULT_IDX 3 - -#if defined CONFIG_BAYTRAIL -#define SSP_DEFAULT_IDX 1 -#elif defined CONFIG_CHERRYTRAIL -#define SSP_DEFAULT_IDX 0 -#endif - -#define CLK_DEFAULT_CPU_HZ 50000000 -#define CLK_MAX_CPU_HZ 343000000 - -#define NUM_CLOCKS 2 - -#define NUM_CPU_FREQ 8 -#define NUM_SSP_FREQ 2 - -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/baytrail/include/platform/lib/cpu.h b/src/platform/baytrail/include/platform/lib/cpu.h deleted file mode 100644 index a03e856ed8cc..000000000000 --- a/src/platform/baytrail/include/platform/lib/cpu.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <config.h> - -/** \brief Number of available DSP cores (conf. by kconfig) */ -#define PLATFORM_CORE_COUNT CONFIG_CORE_COUNT - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 1 - -/** \brief Id of master DSP core */ -#define PLATFORM_MASTER_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/baytrail/include/platform/lib/dai.h b/src/platform/baytrail/include/platform/lib/dai.h deleted file mode 100644 index 0cfdf919d1bb..000000000000 --- a/src/platform/baytrail/include/platform/lib/dai.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -#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/baytrail/include/platform/lib/dma.h b/src/platform/baytrail/include/platform/lib/dma.h deleted file mode 100644 index 360619340feb..000000000000 --- a/src/platform/baytrail/include/platform/lib/dma.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -#include <config.h> - -#if defined CONFIG_CHERRYTRAIL_EXTRA_DW_DMA -#define PLATFORM_NUM_DMACS 3 -#else -#define PLATFORM_NUM_DMACS 2 -#endif - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 8 - -#define DMA_ID_DMAC0 0 -#define DMA_ID_DMAC1 1 -#define DMA_ID_DMAC2 2 - -#define DMA_HANDSHAKE_SSP0_RX 0 -#define DMA_HANDSHAKE_SSP0_TX 1 -#define DMA_HANDSHAKE_SSP1_RX 2 -#define DMA_HANDSHAKE_SSP1_TX 3 -#define DMA_HANDSHAKE_SSP2_RX 4 -#define DMA_HANDSHAKE_SSP2_TX 5 -#define DMA_HANDSHAKE_SSP3_RX 6 -#define DMA_HANDSHAKE_SSP3_TX 7 -#define DMA_HANDSHAKE_SSP4_RX 8 -#define DMA_HANDSHAKE_SSP4_TX 9 -#define DMA_HANDSHAKE_SSP5_RX 10 -#define DMA_HANDSHAKE_SSP5_TX 11 -#define DMA_HANDSHAKE_SSP6_RX 12 -#define DMA_HANDSHAKE_SSP6_TX 13 - -#define dma_chan_irq(dma, chan) dma_irq(dma) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/baytrail/include/platform/lib/mailbox.h b/src/platform/baytrail/include/platform/lib/mailbox.h deleted file mode 100644 index 4fe72b3f791e..000000000000 --- a/src/platform/baytrail/include/platform/lib/mailbox.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_MAILBOX_H__ - -#ifndef __PLATFORM_LIB_MAILBOX_H__ -#define __PLATFORM_LIB_MAILBOX_H__ - -#include <sof/lib/memory.h> -#include <config.h> -#include <stddef.h> -#include <stdint.h> - -#define MAILBOX_HOST_OFFSET 0x144000 - -#define MAILBOX_DSPBOX_OFFSET 0x0 -#define MAILBOX_DSPBOX_SIZE 0x400 -#define MAILBOX_DSPBOX_BASE \ - (MAILBOX_BASE + MAILBOX_DSPBOX_OFFSET) - -#define MAILBOX_HOSTBOX_OFFSET MAILBOX_DSPBOX_SIZE -#define MAILBOX_HOSTBOX_SIZE 0x400 -#define MAILBOX_HOSTBOX_BASE \ - (MAILBOX_BASE + MAILBOX_HOSTBOX_OFFSET) - -#define MAILBOX_EXCEPTION_OFFSET \ - (MAILBOX_HOSTBOX_SIZE + MAILBOX_DSPBOX_SIZE) -#define MAILBOX_EXCEPTION_SIZE 0x100 -#define MAILBOX_EXCEPTION_BASE \ - (MAILBOX_BASE + MAILBOX_EXCEPTION_OFFSET) - -#define MAILBOX_DEBUG_OFFSET \ - (MAILBOX_EXCEPTION_SIZE + MAILBOX_EXCEPTION_OFFSET) -#define MAILBOX_DEBUG_SIZE 0x100 -#define MAILBOX_DEBUG_BASE \ - (MAILBOX_BASE + MAILBOX_DEBUG_OFFSET) - -#define MAILBOX_STREAM_OFFSET \ - (MAILBOX_DEBUG_SIZE + MAILBOX_DEBUG_OFFSET) -#define MAILBOX_STREAM_SIZE 0x200 -#define MAILBOX_STREAM_BASE \ - (MAILBOX_BASE + MAILBOX_STREAM_OFFSET) - -#define MAILBOX_TRACE_OFFSET \ - (MAILBOX_STREAM_SIZE + MAILBOX_STREAM_OFFSET) - -#if CONFIG_TRACE -#define MAILBOX_TRACE_SIZE 0x380 -#else -#define MAILBOX_TRACE_SIZE 0x0 -#endif - -#define MAILBOX_TRACE_BASE \ - (MAILBOX_BASE + MAILBOX_TRACE_OFFSET) - -static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) -{ - volatile uint32_t *ptr; - - ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); - *ptr = src; -} - -#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/baytrail/include/platform/lib/memory.h b/src/platform/baytrail/include/platform/lib/memory.h deleted file mode 100644 index 1905b2edf553..000000000000 --- a/src/platform/baytrail/include/platform/lib/memory.h +++ /dev/null @@ -1,208 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_MEMORY_H__ - -#ifndef __PLATFORM_LIB_MEMORY_H__ -#define __PLATFORM_LIB_MEMORY_H__ - -#include <config.h> - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -struct sof; - -/** - * \brief Data shared between different cores. - * Does nothing, since BYT doesn't support SMP. - */ -#define SHARED_DATA - -void platform_init_memmap(struct sof *sof); - -static inline void *platform_shared_get(void *ptr, int bytes) -{ - return ptr; -} - -/** - * \brief Function for keeping shared data synchronized. - * It's used after usage of data shared by different cores. - * Such data is either statically marked with SHARED_DATA - * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. - * Does nothing, since BYT doesn't support SMP. - */ -static inline void platform_shared_commit(void *ptr, int bytes) { } - -static inline void *platform_rfree_prepare(void *ptr) -{ - return ptr; -} - -#endif - -#define PLATFORM_DCACHE_ALIGN sizeof(void *) - -/** \brief EDF task's default stack size in bytes. */ -#define PLATFORM_TASK_DEFAULT_STACK_SIZE 2048 - -/* physical DSP addresses */ - -#define SHIM_BASE 0xFF340000 -#define SHIM_SIZE 0x00004000 - -#define IRAM_BASE 0xFF2C0000 -#define IRAM_SIZE 0x00014000 - -#define DRAM0_BASE 0xFF300000 -#define DRAM0_SIZE 0x00028000 -#define DRAM0_VBASE 0xC0000000 - -#define MAILBOX_BASE 0xFF344000 -#define MAILBOX_SIZE 0x00001000 - -#define DMA0_BASE 0xFF298000 -#define DMA0_SIZE 0x00004000 - -#define DMA1_BASE 0xFF29C000 -#define DMA1_SIZE 0x00004000 - -#define DMA2_BASE 0xFF294000 -#define DMA2_SIZE 0x00004000 - -#define SSP0_BASE 0xFF2A0000 -#define SSP0_SIZE 0x00001000 - -#define SSP1_BASE 0xFF2A1000 -#define SSP1_SIZE 0x00001000 - -#define SSP2_BASE 0xFF2A2000 -#define SSP2_SIZE 0x00001000 - -#define SSP3_BASE 0xFF2A4000 -#define SSP3_SIZE 0x00001000 - -#define SSP4_BASE 0xFF2A5000 -#define SSP4_SIZE 0x00001000 - -#define SSP5_BASE 0xFF2A6000 -#define SSP5_SIZE 0x00001000 - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -/* - * The Heap and Stack on Baytrail are organised like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | DRAM0_BASE | RO Data | SOF_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_END | Stack | SOF_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT8 0 -#define HEAP_RT_COUNT16 32 -#define HEAP_RT_COUNT32 32 -#define HEAP_RT_COUNT64 32 -#define HEAP_RT_COUNT128 32 -#define HEAP_RT_COUNT256 32 -#define HEAP_RT_COUNT512 2 -#define HEAP_RT_COUNT1024 1 - -/* Heap section sizes for system runtime heap */ -#define HEAP_SYS_RT_COUNT64 64 -#define HEAP_SYS_RT_COUNT512 8 -#define HEAP_SYS_RT_COUNT1024 4 - -/* Heap configuration */ -#define SOF_DATA_SIZE 0x9800 - -#define HEAP_SYSTEM_BASE (DRAM0_BASE + SOF_DATA_SIZE) -#define HEAP_SYSTEM_SIZE 0xA800 - -#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE - -#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) -#define HEAP_SYS_RUNTIME_SIZE \ - (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ - HEAP_SYS_RT_COUNT1024 * 1024) - -#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ - HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ - HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ - HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024) - -#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) -#define HEAP_BUFFER_SIZE \ - (DRAM0_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE -\ - HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE - SOF_DATA_SIZE) - -#define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) - -#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ -#define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 1 - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE -#define SOF_STACK_BASE (DRAM0_BASE + DRAM0_SIZE) -#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) - -/* Vector and literal addresses and sizes - do not use core-isa.h */ -#define SOF_MEM_RESET_VECT 0xff2c0000 -#define SOF_MEM_VECBASE 0xff2c0400 -#define SOF_MEM_INTLEVEL2_VECT 0xff2c057c -#define SOF_MEM_INTLEVEL3_VECT 0xff2c059c -#define SOF_MEM_INTLEVEL4_VECT 0xff2c05bc -#define SOF_MEM_INTLEVEL5_VECT 0xff2c05dc -#define SOF_MEM_INTLEVEL6_VECT 0xff2c05fc -#define SOF_MEM_INTLEVEL7_VECT 0xff2c061c -#define SOF_MEM_KERNEL_VECT 0xff2c063c -#define SOF_MEM_USER_VECT 0xff2c065c -#define SOF_MEM_DOUBLEEXC_VECT 0xff2c067c - -#define SOF_MEM_VECT_LIT_SIZE 0x4 -#define SOF_MEM_VECT_TEXT_SIZE 0x1c -#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ - SOF_MEM_VECT_LIT_SIZE) - -#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 -#define SOF_MEM_RESET_LIT_SIZE 0x120 -#define SOF_MEM_VECBASE_LIT_SIZE 0x178 - -#define SOF_MEM_RO_SIZE 0x8 - -#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/baytrail/include/platform/lib/pm_runtime.h b/src/platform/baytrail/include/platform/lib/pm_runtime.h deleted file mode 100644 index 16deb3e91cef..000000000000 --- a/src/platform/baytrail/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/baytrail/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Baytrail - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <stdint.h> - -struct pm_runtime_data; - -/** - * \brief Initializes platform specific runtime power management. - * \param[in,out] prd Runtime power management data. - */ -static inline 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_... - */ -static inline 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_... - */ -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/baytrail/include/platform/lib/shim.h b/src/platform/baytrail/include/platform/lib/shim.h deleted file mode 100644 index 346642d9157a..000000000000 --- a/src/platform/baytrail/include/platform/lib/shim.h +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <sof/lib/memory.h> -#include <stdint.h> - -#define SHIM_CSR 0x00 -#define SHIM_PISR 0x08 -#define SHIM_PISRH 0x0c -#define SHIM_PIMR 0x10 -#define SHIM_PIMRH 0x14 -#define SHIM_ISRX 0x18 -#define SHIM_ISRD 0x20 -#define SHIM_IMRX 0x28 -#define SHIM_IMRD 0x30 -#define SHIM_IPCXL 0x38 /* IPC IA -> SST */ -#define SHIM_IPCXH 0x3c /* IPC IA -> SST */ -#define SHIM_IPCDL 0x40 /* IPC SST -> IA */ -#define SHIM_IPCDH 0x44 /* IPC SST -> IA */ -#define SHIM_ISRSC 0x48 -#define SHIM_ISRLPESC 0x50 -#define SHIM_IMRSCL 0x58 -#define SHIM_IMRSCH 0x5c -#define SHIM_IMRLPESC 0x60 -#define SHIM_IPCSCL 0x68 -#define SHIM_IPCSCH 0x6c -#define SHIM_IPCLPESCL 0x70 -#define SHIM_IPCLPESCH 0x74 -#define SHIM_CLKCTL 0x78 -#define SHIM_FR_LAT_REQ 0x80 -#define SHIM_MISC 0x88 -#define SHIM_EXT_TIMER_CNTLL 0xC0 -#define SHIM_EXT_TIMER_CNTLH 0xC4 -#define SHIM_EXT_TIMER_STAT 0xC8 -#define SHIM_SSP0_DIVL 0xE8 -#define SHIM_SSP0_DIVH 0xEC -#define SHIM_SSP1_DIVL 0xF0 -#define SHIM_SSP1_DIVH 0xF4 -#define SHIM_SSP2_DIVL 0xF8 -#define SHIM_SSP2_DIVH 0xFC -#define SHIM_SSP3_DIVL 0x100 -#define SHIM_SSP3_DIVH 0x104 -#define SHIM_SSP4_DIVL 0x108 -#define SHIM_SSP4_DIVH 0x10c -#define SHIM_SSP5_DIVL 0x110 -#define SHIM_SSP5_DIVH 0x114 - -#define SHIM_SHIM_BEGIN SHIM_CSR - -#if defined CONFIG_BAYTRAIL - -#define SHIM_SHIM_END SHIM_SSP2_DIVH - -#elif defined CONFIG_CHERRYTRAIL - -#define SHIM_SHIM_END SHIM_SSP5_DIVH - -#endif - -/* CSR 0x0 */ -#define SHIM_CSR_RST (0x1 << 0) -#define SHIM_CSR_VECTOR_SEL (0x1 << 1) -#define SHIM_CSR_STALL (0x1 << 2) -#define SHIM_CSR_PWAITMODE (0x1 << 3) - -/* PISR */ -#define SHIM_PISR_EXT_TIMER (1 << 10) - -/* ISRX 0x18 */ -#define SHIM_ISRX_BUSY (0x1 << 1) -#define SHIM_ISRX_DONE (0x1 << 0) - -/* ISRD / ISD */ -#define SHIM_ISRD_BUSY (0x1 << 1) -#define SHIM_ISRD_DONE (0x1 << 0) - -/* IMRX / IMC */ -#define SHIM_IMRX_BUSY (0x1 << 1) -#define SHIM_IMRX_DONE (0x1 << 0) - -/* IMRD / IMD */ -#define SHIM_IMRD_DONE (0x1 << 0) -#define SHIM_IMRD_BUSY (0x1 << 1) -#define SHIM_IMRD_SSP0 (0x1 << 16) -#define SHIM_IMRD_DMAC0 (0x1 << 21) -#define SHIM_IMRD_DMAC1 (0x1 << 22) -#define SHIM_IMRD_DMAC (SHIM_IMRD_DMAC0 | SHIM_IMRD_DMAC1) - -/* IPCX / IPCCH */ -#define SHIM_IPCXH_DONE (0x1 << 30) -#define SHIM_IPCXH_BUSY (0x1 << 31) - -/* IPCDH */ -#define SHIM_IPCDH_DONE (0x1 << 30) -#define SHIM_IPCDH_BUSY (0x1 << 31) - -/* ISRLPESC */ -#define SHIM_ISRLPESC_DONE (0x1 << 0) -#define SHIM_ISRLPESC_BUSY (0x1 << 1) - -/* IMRLPESC */ -#define SHIM_IMRLPESC_BUSY (0x1 << 1) -#define SHIM_IMRLPESC_DONE (0x1 << 0) - -/* IPCSCH */ -#define SHIM_IPCSCH_DONE (0x1 << 30) -#define SHIM_IPCSCH_BUSY (0x1 << 31) - -/* IPCLPESCH */ -#define SHIM_IPCLPESCH_DONE (0x1 << 30) -#define SHIM_IPCLPESCH_BUSY (0x1 << 31) - -/* CLKCTL */ -#define SHIM_CLKCTL_SSP2_EN (1 << 18) -#define SHIM_CLKCTL_SSP1_EN (1 << 17) -#define SHIM_CLKCTL_SSP0_EN (1 << 16) -#define SHIM_CLKCTL_FRCHNGGO (1 << 5) -#define SHIM_CLKCTL_FRCHNGACK (1 << 4) - -/* SHIM_FR_LAT_REQ */ -#define SHIM_FR_LAT_CLK_MASK 0x7 - -/* ext timer */ -#define SHIM_EXT_TIMER_RUN (1 << 31) -#define SHIM_EXT_TIMER_CLEAR (1 << 30) - -/* SSP M/N */ -#define SHIM_SSP_DIV_BYP (1 << 31) -#define SHIM_SSP_DIV_ENA (1 << 30) -#define SHIM_SSP_DIV_UPD (1 << 29) - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -#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/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h deleted file mode 100644 index 99b724a1b0e6..000000000000 --- a/src/platform/baytrail/include/platform/platform.h +++ /dev/null @@ -1,114 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Xiuli Pan <xiuli.pan@linux.intel.com> - */ - -#ifdef __SOF_PLATFORM_H__ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_LPSRAM_EBB_COUNT 1 - -#define LPSRAM_BANK_SIZE (64 * 1024) - -#define LPSRAM_SIZE (PLATFORM_LPSRAM_EBB_COUNT * LPSRAM_BANK_SIZE) - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <arch/lib/wait.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/shim.h> -#include <stddef.h> -#include <stdint.h> - -struct ll_schedule_domain; -struct timer; - -/*! \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 - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_EXT_IA -#define PLATFORM_IPC_INTERRUPT_NAME NULL - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL - -/* Platform stream capabilities */ -#define PLATFORM_MAX_CHANNELS 4 -#define PLATFORM_MAX_STREAMS 5 - -/* local buffer size of DMA tracing */ -#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE - -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 100 - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* DSP LPE delay in cycles */ -#define PLATFORM_LPE_DELAY 2000 - -/* Platform defined panic code */ -static inline void platform_panic(uint32_t p) -{ - shim_write(SHIM_IPCDL, p); - shim_write(SHIM_IPCDH, (SHIM_IPCDH_BUSY | MAILBOX_EXCEPTION_OFFSET)); -} - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -static inline void platform_wait_for_interrupt(int level) -{ - if (arch_interrupt_get_level()) - panic(SOF_IPC_PANIC_WFI); - - arch_wait_for_interrupt(level); -} - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - shim_write(SHIM_IPCXL, (__x & 0x3fffffff)) - -extern intptr_t _module_init_start; -extern intptr_t _module_init_end; - -#endif -#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/baytrail/include/platform/trace/trace.h b/src/platform/baytrail/include/platform/trace/trace.h deleted file mode 100644 index 5931b3690a91..000000000000 --- a/src/platform/baytrail/include/platform/trace/trace.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_TRACE_TRACE_H__ - -#ifndef __PLATFORM_TRACE_TRACE_H__ -#define __PLATFORM_TRACE_TRACE_H__ - -#include <sof/lib/shim.h> - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - shim_write(SHIM_IPCXL, (__x & 0x3fffffff)) - -#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/baytrail/lib/clk.c b/src/platform/baytrail/lib/clk.c deleted file mode 100644 index befbf1612f75..000000000000 --- a/src/platform/baytrail/lib/clk.c +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <config.h> - -#if CONFIG_BAYTRAIL -const struct freq_table platform_cpu_freq[] = { - { 25000000, 25000 }, - { 25000000, 25000 }, - { 50000000, 50000 }, - { 50000000, 50000 }, /* default */ - { 100000000, 100000 }, - { 200000000, 200000 }, - { 267000000, 267000 }, - { 343000000, 343000 }, -}; -#elif CONFIG_CHERRYTRAIL -const struct freq_table platform_cpu_freq[] = { - { 19200000, 19200 }, - { 19200000, 19200 }, - { 38400000, 38400 }, - { 50000000, 50000 }, /* default */ - { 100000000, 100000 }, - { 200000000, 200000 }, - { 267000000, 267000 }, - { 343000000, 343000 }, -}; -#endif - -const uint32_t cpu_freq_enc[] = { - 0x0, - 0x1, - 0x2, - 0x3, - 0x4, - 0x5, - 0x6, - 0x7, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table *cpu_freq = platform_cpu_freq; - -const struct freq_table platform_ssp_freq[] = { - { 19200000, 19200 }, /* default */ - { 25000000, 25000 }, -}; - -const uint32_t platform_ssp_freq_sources[] = { - PMC_SET_SSP_19M2, - PMC_SET_SSP_25M, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; - -static inline int clock_platform_set_cpu_freq(int clock, int freq_idx) -{ - uint32_t enc = cpu_freq_enc[freq_idx]; - - /* set CPU frequency request for CCU */ - io_reg_update_bits(SHIM_BASE + SHIM_FR_LAT_REQ, SHIM_FR_LAT_CLK_MASK, - enc); - - /* send freq request to SC */ - return ipc_pmc_send_msg(PMC_SET_LPECLK); -} - -static int clock_platform_set_ssp_freq(int clock, int freq_idx) -{ - /* send SSP freq request to SC */ - return ipc_pmc_send_msg(platform_ssp_freq_sources[freq_idx]); -} - -static SHARED_DATA struct clock_info platform_clocks_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(0), - .set_freq = clock_platform_set_cpu_freq, - }, - { - .freqs_num = NUM_SSP_FREQ, - .freqs = platform_ssp_freq, - .default_freq_idx = SSP_DEFAULT_IDX, - .current_freq_idx = SSP_DEFAULT_IDX, - .notification_id = NOTIFIER_ID_SSP_FREQ, - .notification_mask = NOTIFIER_TARGET_CORE_ALL_MASK, - .set_freq = clock_platform_set_ssp_freq, - } -}; - -STATIC_ASSERT(ARRAY_SIZE(platform_clocks_info) == NUM_CLOCKS, - invalid_number_of_clocks); - -void platform_clock_init(struct sof *sof) -{ - int i; - - sof->clocks = platform_clocks_info; - - for (i = 0; i < NUM_CLOCKS; i++) - spinlock_init(&sof->clocks[i].lock); - - platform_shared_commit(sof->clocks, sizeof(*sof->clocks) * NUM_CLOCKS); -} diff --git a/src/platform/baytrail/lib/dai.c b/src/platform/baytrail/lib/dai.c deleted file mode 100644 index 04a1eaa4ab8a..000000000000 --- a/src/platform/baytrail/lib/dai.c +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <ipc/dai.h> -#include <ipc/stream.h> -#include <config.h> - -static SHARED_DATA struct dai ssp[] = { -{ - .index = 0, - .plat_data = { - .base = SSP0_BASE, - .irq = IRQ_NUM_EXT_SSP0, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP0_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP0_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP0_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP0_RX, - } - }, - .drv = &ssp_driver, -}, -{ - .index = 1, - .plat_data = { - .base = SSP1_BASE, - .irq = IRQ_NUM_EXT_SSP1, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP1_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP1_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP1_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP1_RX, - } - }, - .drv = &ssp_driver, -}, -{ - .index = 2, - .plat_data = { - .base = SSP2_BASE, - .irq = IRQ_NUM_EXT_SSP2, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP2_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP2_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP2_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP2_RX, - } - }, - .drv = &ssp_driver, -}, -#if defined CONFIG_CHERRYTRAIL -{ - .index = 3, - .plat_data = { - .base = SSP3_BASE, - .irq = IRQ_NUM_EXT_SSP0, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP3_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP3_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP0_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP3_RX, - } - }, - .drv = &ssp_driver, -}, -{ - .index = 4, - .plat_data = { - .base = SSP4_BASE, - .irq = IRQ_NUM_EXT_SSP1, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP4_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP4_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP4_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP4_RX, - } - }, - .drv = &ssp_driver, -}, -{ - .index = 5, - .plat_data = { - .base = SSP5_BASE, - .irq = IRQ_NUM_EXT_SSP2, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP5_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP5_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP5_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP5_RX, - } - }, - .drv = &ssp_driver, -}, -#endif -}; - -const struct dai_type_info dti[] = { - { - .type = SOF_DAI_INTEL_SSP, - .dai_array = ssp, - .num_dais = ARRAY_SIZE(ssp) - } -}; - -const struct dai_info lib_dai = { - .dai_type_array = dti, - .num_dai_types = ARRAY_SIZE(dti) -}; - -int dai_init(struct sof *sof) -{ - int i; - - /* initialize spin locks early to enable ref counting */ - for (i = 0; i < ARRAY_SIZE(ssp); i++) - spinlock_init(&ssp[i].lock); - - platform_shared_commit(ssp, sizeof(*ssp)); - - sof->dai_info = &lib_dai; - - return 0; -} diff --git a/src/platform/baytrail/lib/dma.c b/src/platform/baytrail/lib/dma.c deleted file mode 100644 index b645601feb6e..000000000000 --- a/src/platform/baytrail/lib/dma.c +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/dw-dma.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <config.h> - -const struct dw_drv_plat_data dmac0 = { - .chan[0] = { - .class = 6, - .weight = 0, - }, - .chan[1] = { - .class = 6, - .weight = 0, - }, - .chan[2] = { - .class = 6, - .weight = 0, - }, - .chan[3] = { - .class = 6, - .weight = 0, - }, - .chan[4] = { - .class = 6, - .weight = 0, - }, - .chan[5] = { - .class = 6, - .weight = 0, - }, - .chan[6] = { - .class = 6, - .weight = 0, - }, - .chan[7] = { - .class = 6, - .weight = 0, - }, -}; - -const struct dw_drv_plat_data dmac1 = { - .chan[0] = { - .class = 7, - .weight = 0, - }, - .chan[1] = { - .class = 7, - .weight = 0, - }, - .chan[2] = { - .class = 7, - .weight = 0, - }, - .chan[3] = { - .class = 7, - .weight = 0, - }, - .chan[4] = { - .class = 7, - .weight = 0, - }, - .chan[5] = { - .class = 7, - .weight = 0, - }, - .chan[6] = { - .class = 7, - .weight = 0, - }, - .chan[7] = { - .class = 7, - .weight = 0, - }, -}; - -#if defined CONFIG_CHERRYTRAIL_EXTRA_DW_DMA -const struct dw_drv_plat_data dmac2 = { - .chan[0] = { - .class = 7, - .weight = 0, - }, - .chan[1] = { - .class = 7, - .weight = 0, - }, - .chan[2] = { - .class = 7, - .weight = 0, - }, - .chan[3] = { - .class = 7, - .weight = 0, - }, - .chan[4] = { - .class = 7, - .weight = 0, - }, - .chan[5] = { - .class = 7, - .weight = 0, - }, - .chan[6] = { - .class = 7, - .weight = 0, - }, - .chan[7] = { - .class = 7, - .weight = 0, - }, -}; -#endif - -SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { -{ - .plat_data = { - .id = DMA_ID_DMAC0, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | - DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, - .caps = DMA_CAP_GP_HP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HOST, - .base = DMA0_BASE, - .channels = 8, - .irq = IRQ_NUM_EXT_DMAC0, - .drv_plat_data = &dmac0, - }, - .ops = &dw_dma_ops, -}, -{ - .plat_data = { - .id = DMA_ID_DMAC1, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | - DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, - .caps = DMA_CAP_GP_HP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HOST, - .base = DMA1_BASE, - .channels = 8, - .irq = IRQ_NUM_EXT_DMAC1, - .drv_plat_data = &dmac1, - }, - .ops = &dw_dma_ops, -}, -#if defined CONFIG_CHERRYTRAIL_EXTRA_DW_DMA -{ - .plat_data = { - .id = DMA_ID_DMAC2, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | - DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, - .caps = DMA_CAP_GP_HP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HOST, - .base = DMA2_BASE, - .channels = 8, - .irq = IRQ_NUM_EXT_DMAC2, - .drv_plat_data = &dmac2, - }, - .ops = &dw_dma_ops, -}, -#endif -}; - -const struct dma_info lib_dma = { - .dma_array = dma, - .num_dmas = ARRAY_SIZE(dma) -}; - -/* Initialize all platform DMAC's */ -int dmac_init(struct sof *sof) -{ - int i; - /* no probing before first use */ - - /* TODO: dynamic init based on platform settings */ - - /* early lock initialization for ref counting */ - for (i = 0; i < ARRAY_SIZE(dma); i++) - spinlock_init(&dma[i].lock); - - platform_shared_commit(dma, sizeof(*dma)); - - sof->dma_info = &lib_dma; - - return 0; -} diff --git a/src/platform/baytrail/lib/memory.c b/src/platform/baytrail/lib/memory.c deleted file mode 100644 index 7e82e1ac4f87..000000000000 --- a/src/platform/baytrail/lib/memory.c +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/common.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <ipc/topology.h> - -/* Heap blocks for system runtime */ -static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; -static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; -static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; - -/* Heap memory for system runtime */ -static SHARED_DATA struct block_map sys_rt_heap_map[] = { - BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), - BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), - BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), -}; - -/* Heap blocks for modules */ -static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; -static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; -static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; -static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; -static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; -static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; -static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; - -/* Heap memory map for modules */ -static SHARED_DATA struct block_map rt_heap_map[] = { - BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), - BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), - BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), - BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), - BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), - BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), - BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), -}; - -/* Heap blocks for buffers */ -static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; - -/* Heap memory map for buffers */ -static SHARED_DATA struct block_map buf_heap_map[] = { - BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), -}; - -static SHARED_DATA struct mm memmap = { - .system[0] = { - .heap = HEAP_SYSTEM_BASE, - .size = HEAP_SYSTEM_SIZE, - .info = {.free = HEAP_SYSTEM_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .system_runtime[0] = { - .blocks = ARRAY_SIZE(sys_rt_heap_map), - .map = sys_rt_heap_map, - .heap = HEAP_SYS_RUNTIME_BASE, - .size = HEAP_SYS_RUNTIME_SIZE, - .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .runtime[0] = { - .blocks = ARRAY_SIZE(rt_heap_map), - .map = rt_heap_map, - .heap = HEAP_RUNTIME_BASE, - .size = HEAP_RUNTIME_SIZE, - .info = {.free = HEAP_RUNTIME_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .buffer[0] = { - .blocks = ARRAY_SIZE(buf_heap_map), - .map = buf_heap_map, - .heap = HEAP_BUFFER_BASE, - .size = HEAP_BUFFER_SIZE, - .info = {.free = HEAP_BUFFER_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + - HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, -}; - -void platform_init_memmap(struct sof *sof) -{ - /* memmap has been initialized statically as a part of .data */ - sof->memory_map = &memmap; -} diff --git a/src/platform/baytrail/platform.c b/src/platform/baytrail/platform.c deleted file mode 100644 index 0ae12a2cc146..000000000000 --- a/src/platform/baytrail/platform.c +++ /dev/null @@ -1,315 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> - -#include <sof/compiler_info.h> -#include <sof/debug/debug.h> -#include <sof/drivers/dw-dma.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/pmc.h> -#include <sof/drivers/timer.h> -#include <sof/fw-ready-metadata.h> -#include <sof/lib/agent.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/shim.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/ll_schedule_domain.h> -#include <sof/sof.h> -#include <sof/trace/dma-trace.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/header.h> -#include <ipc/info.h> -#include <kernel/abi.h> -#include <config.h> -#include <version.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -static const struct sof_ipc_fw_ready ready - __section(".fw_ready") = { - .hdr = { - .cmd = SOF_IPC_FW_READY, - .size = sizeof(struct sof_ipc_fw_ready), - }, - /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ - .version = { - .hdr.size = sizeof(struct sof_ipc_fw_version), - .micro = SOF_MICRO, - .minor = SOF_MINOR, - .major = SOF_MAJOR, -#if CONFIG_DEBUG - /* only added in debug for reproducability in releases */ - .build = SOF_BUILD, - .date = __DATE__, - .time = __TIME__, -#endif - .tag = SOF_TAG, - .abi_version = SOF_ABI_VERSION, - }, - .flags = DEBUG_SET_FW_READY_FLAGS -}; - -#define NUM_BYT_WINDOWS 6 -static const struct sof_ipc_window sram_window - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_window) + - sizeof(struct sof_ipc_window_elem) * NUM_BYT_WINDOWS, - .type = SOF_IPC_EXT_WINDOW, - }, - .num_windows = NUM_BYT_WINDOWS, - .window = { - { - .type = SOF_IPC_REGION_UPBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DSPBOX_SIZE, - .offset = MAILBOX_DSPBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DOWNBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_HOSTBOX_SIZE, - .offset = MAILBOX_HOSTBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DEBUG, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DEBUG_SIZE, - .offset = MAILBOX_DEBUG_OFFSET, - }, - { - .type = SOF_IPC_REGION_TRACE, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_TRACE_SIZE, - .offset = MAILBOX_TRACE_OFFSET, - }, - { - .type = SOF_IPC_REGION_STREAM, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_STREAM_SIZE, - .offset = MAILBOX_STREAM_OFFSET, - }, - { - .type = SOF_IPC_REGION_EXCEPTION, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_EXCEPTION_SIZE, - .offset = MAILBOX_EXCEPTION_OFFSET, - }, - }, -}; - -SHARED_DATA struct timer timer = { - .id = TIMER3, /* external timer */ - .irq = IRQ_NUM_EXT_TIMER, -}; - -int platform_boot_complete(uint32_t boot_message) -{ - uint32_t mb_offset = 0; - uint64_t outbox = MAILBOX_HOST_OFFSET >> 3; - - mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); - mb_offset = mb_offset + sizeof(ready); - - mailbox_dspbox_write(mb_offset, &sram_window, - sram_window.ext_hdr.hdr.size); - mb_offset = mb_offset + sram_window.ext_hdr.hdr.size; - - /* variable length compiler description is a last field of cc_version */ - mailbox_dspbox_write(mb_offset, &cc_version, - cc_version.ext_hdr.hdr.size); - mb_offset = mb_offset + cc_version.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &probe_support, - probe_support.ext_hdr.hdr.size); - mb_offset = mb_offset + probe_support.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &user_abi_version, - user_abi_version.ext_hdr.hdr.size); - - /* now interrupt host to tell it we are done booting */ - shim_write(SHIM_IPCDL, SOF_IPC_FW_READY | outbox); - shim_write(SHIM_IPCDH, SHIM_IPCDH_BUSY); - - /* boot now complete so we can relax the CPU */ - /* For now skip this to gain more processing performance - * for SRC component. - */ - /* clock_set_freq(CLK_CPU, CLK_DEFAULT_CPU_HZ); */ - - return 0; -} - -int platform_init(struct sof *sof) -{ -#if defined CONFIG_BAYTRAIL - struct dai *ssp0; - struct dai *ssp1; - struct dai *ssp2; -#elif defined CONFIG_CHERRYTRAIL - struct dai *ssp0; - struct dai *ssp1; - struct dai *ssp2; - struct dai *ssp3; - struct dai *ssp4; - struct dai *ssp5; -#else -#error Undefined platform -#endif - int ret; - - sof->platform_timer = &timer; - sof->cpu_timer = &timer; - - /* clear mailbox for early trace and debug */ - trace_point(TRACE_BOOT_PLATFORM_MBOX); - bzero((void *)MAILBOX_BASE, MAILBOX_SIZE); - - /* configure the shim */ - trace_point(TRACE_BOOT_PLATFORM_SHIM); -#if defined CONFIG_BAYTRAIL - shim_write(SHIM_MISC, shim_read(SHIM_MISC) | 0x0000000e); -#elif defined CONFIG_CHERRYTRAIL - shim_write(SHIM_MISC, shim_read(SHIM_MISC) | 0x00000e0e); -#endif - - /* init PMC IPC */ - trace_point(TRACE_BOOT_PLATFORM_PMC); - platform_ipc_pmc_init(); - - /* init timers, clocks and schedulers */ - trace_point(TRACE_BOOT_PLATFORM_TIMER); - platform_timer_start(sof->platform_timer); - - trace_point(TRACE_BOOT_PLATFORM_CLOCK); - platform_clock_init(sof); - - trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(); - - /* init low latency timer domain and scheduler */ - sof->platform_timer_domain = - timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK, - CONFIG_SYSTICK_PERIOD); - scheduler_init_ll(sof->platform_timer_domain); - - /* init the system agent */ - trace_point(TRACE_BOOT_PLATFORM_AGENT); - sa_init(sof, CONFIG_SYSTICK_PERIOD); - - /* Set CPU to default frequency for booting */ - trace_point(TRACE_BOOT_PLATFORM_CPU_FREQ); - clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); - - /* set SSP clock to 19.2M */ - trace_point(TRACE_BOOT_PLATFORM_SSP_FREQ); - clock_set_freq(CLK_SSP, 19200000); - - /* init DMACs */ - trace_point(TRACE_BOOT_PLATFORM_DMA); - ret = dmac_init(sof); - if (ret < 0) - return -ENODEV; - - /* init low latency multi channel DW-DMA domain and scheduler */ - sof->platform_dma_domain = dma_multi_chan_domain_init - (&sof->dma_info->dma_array[PLATFORM_DW_DMA_INDEX], - PLATFORM_NUM_DW_DMACS, - PLATFORM_DEFAULT_CLOCK, true); - scheduler_init_ll(sof->platform_dma_domain); - - /* initialise the host IPC mechanisms */ - trace_point(TRACE_BOOT_PLATFORM_IPC); - ipc_init(sof); - - trace_point(TRACE_BOOT_PLATFORM_DAI); - ret = dai_init(sof); - if (ret < 0) - return -ENODEV; - - /* mask SSP 0 - 2 interrupts */ - shim_write(SHIM_PIMR, shim_read(SHIM_PIMR) | 0x00000038); - -#if defined CONFIG_CHERRYTRAIL - /* mask SSP 3 - 5 interrupts */ - shim_write(SHIM_PIMRH, shim_read(SHIM_PIMRH) | 0x00000700); -#endif - - /* Reset M/N SSP clock dividers */ - shim_write(SHIM_SSP0_DIVL, 1); - shim_write(SHIM_SSP0_DIVH, 0x80000001); - shim_write(SHIM_SSP1_DIVL, 1); - shim_write(SHIM_SSP1_DIVH, 0x80000001); - shim_write(SHIM_SSP2_DIVL, 1); - shim_write(SHIM_SSP2_DIVH, 0x80000001); -#if defined CONFIG_CHERRYTRAIL - shim_write(SHIM_SSP3_DIVL, 1); - shim_write(SHIM_SSP3_DIVH, 0x80000001); - shim_write(SHIM_SSP4_DIVL, 1); - shim_write(SHIM_SSP4_DIVH, 0x80000001); - shim_write(SHIM_SSP5_DIVL, 1); - shim_write(SHIM_SSP5_DIVH, 0x80000001); -#endif - - /* init SSP ports */ - trace_point(TRACE_BOOT_PLATFORM_SSP); - ssp0 = dai_get(SOF_DAI_INTEL_SSP, 0, DAI_CREAT); - if (ssp0 == NULL) - return -ENODEV; - - ssp1 = dai_get(SOF_DAI_INTEL_SSP, 1, DAI_CREAT); - if (ssp1 == NULL) - return -ENODEV; - - ssp2 = dai_get(SOF_DAI_INTEL_SSP, 2, DAI_CREAT); - if (ssp2 == NULL) - return -ENODEV; - -#if defined CONFIG_CHERRYTRAIL - ssp3 = dai_get(SOF_DAI_INTEL_SSP, 3, DAI_CREAT); - if (ssp3 == NULL) - return -ENODEV; - - ssp4 = dai_get(SOF_DAI_INTEL_SSP, 4, DAI_CREAT); - if (ssp4 == NULL) - return -ENODEV; - - ssp5 = dai_get(SOF_DAI_INTEL_SSP, 5, DAI_CREAT); - if (ssp5 == NULL) - return -ENODEV; -#endif - -#if CONFIG_TRACE - /* Initialize DMA for Trace*/ - trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); - dma_trace_init_complete(sof->dmat); -#endif - - /* show heap status */ - heap_trace_all(1); - - return 0; -} diff --git a/src/platform/cannonlake/CMakeLists.txt b/src/platform/cannonlake/CMakeLists.txt deleted file mode 100644 index 3fad0567edcb..000000000000 --- a/src/platform/cannonlake/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(lib) - -add_executable(boot_module boot_module.c) -add_executable(base_module base_module.c) - -target_link_libraries(boot_module sof_options) -target_link_libraries(base_module sof_options) diff --git a/src/platform/cannonlake/base_module.c b/src/platform/cannonlake/base_module.c deleted file mode 100644 index 70335c60ed93..000000000000 --- a/src/platform/cannonlake/base_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest cnl_manifest = { - .module = { - .name = "BASEFW", - .uuid = {0x32, 0x8c, 0x39, 0x0e, 0xde, 0x5a, 0x4b, 0xba, - 0x93, 0xb1, 0xc5, 0x04, 0x32, 0x28, 0x0e, 0xe4}, - .entry_point = SOF_TEXT_START, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/cannonlake/boot_ldr.x.in b/src/platform/cannonlake/boot_ldr.x.in deleted file mode 100644 index 8fc4547799ec..000000000000 --- a/src/platform/cannonlake/boot_ldr.x.in +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Linker Script for Cannonlake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - boot_entry_text : - org = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - len = IMR_BOOT_LDR_TEXT_ENTRY_SIZE - boot_entry_lit : - org = IMR_BOOT_LDR_LIT_BASE, - len = IMR_BOOT_LDR_LIT_SIZE - sof_text : - org = IMR_BOOT_LDR_TEXT_BASE, - len = IMR_BOOT_LDR_TEXT_SIZE, - sof_data : - org = IMR_BOOT_LDR_DATA_BASE, - len = IMR_BOOT_LDR_DATA_SIZE - sof_bss_data : - org = IMR_BOOT_LDR_BSS_BASE, - len = IMR_BOOT_LDR_BSS_SIZE - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE -} - -PHDRS -{ - boot_entry_text_phdr PT_LOAD; - boot_entry_lit_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_bss_data_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; - wnd0_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(boot_entry) -EXTERN(reset_vector) - -SECTIONS -{ - .boot_entry.text : ALIGN(4) - { - _boot_entry_text_start = ABSOLUTE(.); - KEEP (*(.boot_entry.text)) - _boot_entry_text_end = ABSOLUTE(.); - } >boot_entry_text :boot_entry_text_phdr - - .boot_entry.literal : ALIGN(4) - { - _boot_entry_literal_start = ABSOLUTE(.); - *(.boot_entry.literal) - *(.literal .literal.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _boot_entry_literal_end = ABSOLUTE(.); - } >boot_entry_lit :boot_entry_lit_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - *(.entry.text) - *(.init.literal) - KEEP(*(.init)) - *( .text .text.*) - *(.fini.literal) - KEEP(*(.fini)) - *(.gnu.version) - KEEP (*(.ResetVector.text)) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_bss_data :sof_bss_data_phdr - - _man = 0x1234567; - - PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - - _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; - PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - __wnd0 = HP_SRAM_WIN0_BASE; - __wnd0_size = HP_SRAM_WIN0_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/cannonlake/boot_module.c b/src/platform/cannonlake/boot_module.c deleted file mode 100644 index e0d2e1888582..000000000000 --- a/src/platform/cannonlake/boot_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest cnl_bootldr_manifest = { - .module = { - .name = "BRNGUP", - .uuid = {0xf3, 0xe4, 0x79, 0x2b, 0x75, 0x46, 0x49, 0xf6, - 0x89, 0xdf, 0x3b, 0xc1, 0x94, 0xa9, 0x1a, 0xeb}, - .entry_point = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/cannonlake/cannonlake.x.in b/src/platform/cannonlake/cannonlake.x.in deleted file mode 100644 index 54a9e3bc81b7..000000000000 --- a/src/platform/cannonlake/cannonlake.x.in +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Linker Script for Cannonlake. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_memory_lit : - org = XCHAL_MEMERROR_VECTOR_PADDR + SOF_MEM_ERROR_LIT_SIZE, - len = SOF_MEM_ERROR_LIT_SIZE - vector_memory_text : - org = XCHAL_MEMERROR_VECTOR_PADDR, - len = SOF_MEM_ERROR_TEXT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_fw : - org = SOF_FW_BASE, - len = SOF_FW_MAX_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE - wnd1 : - org = HP_SRAM_WIN1_BASE, - len = HP_SRAM_WIN1_SIZE - wnd2 : - org = HP_SRAM_WIN2_BASE, - len = HP_SRAM_WIN2_SIZE - wnd3 : - org = HP_SRAM_WIN3_BASE, - len = HP_SRAM_WIN3_SIZE - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE -} - -PHDRS -{ - vector_memory_lit_phdr PT_LOAD; - vector_memory_text_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_fw_phdr PT_LOAD; - wnd0_phdr PT_LOAD; - wnd1_phdr PT_LOAD; - wnd2_phdr PT_LOAD; - wnd3_phdr PT_LOAD; - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; -} - -/* Default entry point: */ -ENTRY(_MainEntry) -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .MemoryExceptionVector.text : ALIGN(4) - { - _MemoryExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.text)) - _MemoryExceptionVector_text_end = ABSOLUTE(.); - } >vector_memory_text :vector_memory_text_phdr - - .wnd0 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd0_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN0_SIZE; - _wnd0_end = ABSOLUTE(.); - } >wnd0 :wnd0_phdr - - .wnd1 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd1_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN1_SIZE; - _wnd1_end = ABSOLUTE(.); - } >wnd1 :wnd1_phdr - - .wnd2 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd2_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN2_SIZE; - _wnd2_end = ABSOLUTE(.); - } >wnd2 :wnd2_phdr - - .wnd3 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd3_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN3_SIZE; - _wnd3_end = ABSOLUTE(.); - } >wnd3 :wnd3_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.entry.text) - *(.init.literal) - KEEP(*(.init)) - KEEP(*(.lps_vector)) - *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - *(.fini.literal) - KEEP(*(.fini)) - *(.gnu.version) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_fw :sof_fw_phdr - - .rodata : ALIGN(4096) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .shared_data : ALIGN(PLATFORM_DCACHE_ALIGN) - { - _shared_data_start = ABSOLUTE(.); - *(*.shared_data) - _shared_data_end = ABSOLUTE(.); - . = ALIGN(PLATFORM_DCACHE_ALIGN); - } >sof_fw :sof_fw_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_fw :sof_fw_phdr - - .bss (NOLOAD) : ALIGN(4096) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - - . = ALIGN (SRAM_BANK_SIZE); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_M_SIZE; - _system_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_M_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_SIZE; - _sof_stack_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _sof_core_s_start = ABSOLUTE(.); - . = . + SOF_CORE_S_T_SIZE; - _sof_core_s_end = ABSOLUTE(.); - - _bss_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - /* stack */ - _end = _sof_stack_start; - PROVIDE(end = _sof_stack_start); - _stack_sentry = _sof_stack_start; - __stack = _sof_stack_end; - - /* Slave core size */ - _core_s_size = SOF_CORE_S_SIZE; - - /* System Heap */ - _system_heap = _system_heap_start; - - /* system runtime heap */ - _system_runtime_heap = _system_runtime_heap_start; - - /* module heap */ - _module_heap = _runtime_heap_start; - - /* buffer heap */ - _buffer_heap = _buffer_heap_start; - _buffer_heap_end = _buffer_heap_end; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr -} diff --git a/src/platform/cannonlake/include/arch/xtensa/config/core-isa.h b/src/platform/cannonlake/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index a776e0c1009c..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,613 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 64 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 1 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "X6H3CNL_2017_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x00075E9B /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC2F3FBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x1C45212F /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX6.0.1" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 260001 /* major*100+minor */ -#define XCHAL_HW_REL_LX6 1 -#define XCHAL_HW_REL_LX6_0 1 -#define XCHAL_HW_REL_LX6_0_1 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 260001 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 260001 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 6 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 6 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 49152 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 8 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 6 -#define XCHAL_DCACHE_SETWIDTH 8 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 4 -#define XCHAL_DCACHE_WAYS 3 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY XTHAL_MEMEP_ECC -#define XCHAL_DCACHE_ECC_PARITY XTHAL_MEMEP_ECC - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 8 -#define XCHAL_DCACHE_ACCESS_SIZE 8 - -#define XCHAL_DCACHE_BANKS 1 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 21 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 8 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x0000000F -#define XCHAL_INTLEVEL2_MASK 0x000000F0 -#define XCHAL_INTLEVEL3_MASK 0x00000F00 -#define XCHAL_INTLEVEL4_MASK 0x00007000 -#define XCHAL_INTLEVEL5_MASK 0x000F8000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00100000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000000F -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00007FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x001FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 2 -#define XCHAL_INT5_LEVEL 2 -#define XCHAL_INT6_LEVEL 2 -#define XCHAL_INT7_LEVEL 2 -#define XCHAL_INT8_LEVEL 3 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 4 -#define XCHAL_INT14_LEVEL 4 -#define XCHAL_INT15_LEVEL 5 -#define XCHAL_INT16_LEVEL 5 -#define XCHAL_INT17_LEVEL 5 -#define XCHAL_INT18_LEVEL 5 -#define XCHAL_INT19_LEVEL 5 -#define XCHAL_INT20_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFE00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0008D999 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00072444 -#define XCHAL_INTTYPE_MASK_TIMER 0x00000222 -#define XCHAL_INTTYPE_MASK_NMI 0x00100000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 1 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 5 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 9 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 20 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL7_NUM 20 -/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 6 /* (intlevel 2) */ -#define XCHAL_EXTINT2_NUM 10 /* (intlevel 3) */ -#define XCHAL_EXTINT3_NUM 13 /* (intlevel 4) */ -#define XCHAL_EXTINT4_NUM 16 /* (intlevel 5) */ -#define XCHAL_EXTINT5_NUM 17 /* (intlevel 5) */ -#define XCHAL_EXTINT6_NUM 18 /* (intlevel 5) */ -#define XCHAL_EXTINT7_NUM 20 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT2_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT6_EXTNUM 1 /* (intlevel 2) */ -#define XCHAL_INT10_EXTNUM 2 /* (intlevel 3) */ -#define XCHAL_INT13_EXTNUM 3 /* (intlevel 4) */ -#define XCHAL_INT16_EXTNUM 4 /* (intlevel 5) */ -#define XCHAL_INT17_EXTNUM 5 /* (intlevel 5) */ -#define XCHAL_INT18_EXTNUM 6 /* (intlevel 5) */ -#define XCHAL_INT20_EXTNUM 7 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 1 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0xBEFE0800 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0xBEFE0800 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR0_PADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR1_VADDR 0xBE800000 -#define XCHAL_RESET_VECTOR1_PADDR 0xBE800000 -#define XCHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XCHAL_MEMERROR_VECTOR0_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR0_PADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR1_VADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR1_PADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 -#define XCHAL_USER_VECOFS 0x00000340 -#define XCHAL_USER_VECTOR_VADDR 0xBEFE0B40 -#define XCHAL_USER_VECTOR_PADDR 0xBEFE0B40 -#define XCHAL_KERNEL_VECOFS 0x00000300 -#define XCHAL_KERNEL_VECTOR_VADDR 0xBEFE0B00 -#define XCHAL_KERNEL_VECTOR_PADDR 0xBEFE0B00 -#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xBEFE0BC0 -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0xBEFE0BC0 -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0xBEFE0800 -#define XCHAL_WINDOW_VECTORS_PADDR 0xBEFE0800 -#define XCHAL_INTLEVEL2_VECOFS 0x00000180 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xBEFE0980 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0xBEFE0980 -#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL4_VECOFS 0x00000200 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL5_VECOFS 0x00000240 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL6_VECOFS 0x00000280 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0xBEFE0A80 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0xBEFE0A80 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x000002C0 -#define XCHAL_NMI_VECTOR_VADDR 0xBEFE0AC0 -#define XCHAL_NMI_VECTOR_PADDR 0xBEFE0AC0 -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/arch/xtensa/config/core-matmap.h b/src/platform/cannonlake/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index d7fd7795e3f1..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - -#define XCHAL_CA_R (0xC0 | 0x40000000) -#define XCHAL_CA_RX (0xD0 | 0x40000000) -#define XCHAL_CA_RW (0xE0 | 0x40000000) -#define XCHAL_CA_RWX (0xF0 | 0x40000000) - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefine hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/arch/xtensa/config/defs.h b/src/platform/cannonlake/include/arch/xtensa/config/defs.h deleted file mode 100644 index d93272ae05a3..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/arch/xtensa/config/specreg.h b/src/platform/cannonlake/include/arch/xtensa/config/specreg.h deleted file mode 100644 index 9d1d2ea95dad..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ - -/* Copyright (c) 1998-2002 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define MEMCTL 97 -#define ATOMCTL 99 -#define DDR 104 -#define MEPC 106 -#define MEPS 107 -#define MESAVE 108 -#define MESR 109 -#define MECR 110 -#define MEVADDR 111 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 - -/* Special cases (bases of special register series): */ -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -/* Special names for read-only and write-only interrupt registers: */ -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 - -#endif /* XTENSA_SPECREG_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/arch/xtensa/config/system.h b/src/platform/cannonlake/include/arch/xtensa/config/system.h deleted file mode 100644 index 0e434954c920..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Copyright (c) 2000-2010 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -#define XSHAL_FLOATING_POINT_ABI 0 - -/* SW workarounds enabled for HW errata: */ - -/* SW options for functional safety: */ -#define XSHAL_FUNC_SAFETY_ENABLED 0 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -#define XSHAL_ROM_VADDR 0xBEFE0000 -#define XSHAL_ROM_PADDR 0xBEFE0000 -#define XSHAL_ROM_SIZE 0x00020000 -/* Largest available area (free of vectors): */ -#define XSHAL_ROM_AVAIL_VADDR 0xBEFE0BC0 -#define XSHAL_ROM_AVAIL_VSIZE 0x0001F440 - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x80000000 -#define XSHAL_RAM_PADDR 0x80000000 -#define XSHAL_RAM_VSIZE 0x3EFE0000 -#define XSHAL_RAM_PSIZE 0x3EFE0000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x80000000 -#define XSHAL_RAM_AVAIL_VSIZE 0x3EFE0000 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit and diagnostic routines. - */ -#define XSHAL_MAGIC_EXIT 0xe0000000 - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22442222 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22112222 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22112222 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44FFFF /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11FFFF /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11FFFF /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22FFFF /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244222F /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211222F /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211222F /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF44422F /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF11122F /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF11122F /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000104 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XSHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XSHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XSHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x00000300 -#define XSHAL_RESET_VECTOR_ISROM 1 -#define XSHAL_USER_VECTOR_SIZE 0x00000038 -#define XSHAL_USER_VECTOR_ISROM 1 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 -#define XSHAL_KERNEL_VECTOR_ISROM 1 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 1 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 1 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL2_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL3_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL4_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL5_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL6_VECTOR_ISROM 1 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x00000038 -#define XSHAL_NMI_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/arch/xtensa/config/tie-asm.h b/src/platform/cannonlake/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index f6210e126331..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - /* - * Macro to store all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rur.THREADPTR \at1 // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_+0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_store - - /* - * Macro to load all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.THREADPTR \at1 // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - /* - * Macro to store the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_FPU_store xchal_cp0_store - .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - rur.FCR \at1 // ureg 232 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.FSR \at1 // ureg 233 - s32i \at1, \ptr, .Lxchal_ofs_+4 - ssi f0, \ptr, .Lxchal_ofs_+8 - ssi f1, \ptr, .Lxchal_ofs_+12 - ssi f2, \ptr, .Lxchal_ofs_+16 - ssi f3, \ptr, .Lxchal_ofs_+20 - ssi f4, \ptr, .Lxchal_ofs_+24 - ssi f5, \ptr, .Lxchal_ofs_+28 - ssi f6, \ptr, .Lxchal_ofs_+32 - ssi f7, \ptr, .Lxchal_ofs_+36 - ssi f8, \ptr, .Lxchal_ofs_+40 - ssi f9, \ptr, .Lxchal_ofs_+44 - ssi f10, \ptr, .Lxchal_ofs_+48 - ssi f11, \ptr, .Lxchal_ofs_+52 - ssi f12, \ptr, .Lxchal_ofs_+56 - ssi f13, \ptr, .Lxchal_ofs_+60 - ssi f14, \ptr, .Lxchal_ofs_+64 - ssi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_store - - /* - * Macro to load the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_FPU_load xchal_cp0_load - .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.FCR \at1 // ureg 232 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.FSR \at1 // ureg 233 - lsi f0, \ptr, .Lxchal_ofs_+8 - lsi f1, \ptr, .Lxchal_ofs_+12 - lsi f2, \ptr, .Lxchal_ofs_+16 - lsi f3, \ptr, .Lxchal_ofs_+20 - lsi f4, \ptr, .Lxchal_ofs_+24 - lsi f5, \ptr, .Lxchal_ofs_+28 - lsi f6, \ptr, .Lxchal_ofs_+32 - lsi f7, \ptr, .Lxchal_ofs_+36 - lsi f8, \ptr, .Lxchal_ofs_+40 - lsi f9, \ptr, .Lxchal_ofs_+44 - lsi f10, \ptr, .Lxchal_ofs_+48 - lsi f11, \ptr, .Lxchal_ofs_+52 - lsi f12, \ptr, .Lxchal_ofs_+56 - lsi f13, \ptr, .Lxchal_ofs_+60 - lsi f14, \ptr, .Lxchal_ofs_+64 - lsi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_load - -#define XCHAL_CP0_NUM_ATMPS 1 - /* - * Macro to store the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_CW_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - rur.AE_CBEGIN0 \at1 // ureg 246 - s32i \at1, \ptr, .Lxchal_ofs_+16 - rur.AE_CEND0 \at1 // ureg 247 - s32i \at1, \ptr, .Lxchal_ofs_+20 - ae_s64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_s64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed15, \ptr, .Lxchal_ofs_+16 - ae_salign64.i u0, \ptr, .Lxchal_ofs_+24 - ae_salign64.i u1, \ptr, .Lxchal_ofs_+32 - ae_salign64.i u2, \ptr, .Lxchal_ofs_+40 - ae_salign64.i u3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 128 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_store - - /* - * Macro to load the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_CW_SD_NO \at1 // ureg 243 - l32i \at1, \ptr, .Lxchal_ofs_+16 - wur.AE_CBEGIN0 \at1 // ureg 246 - l32i \at1, \ptr, .Lxchal_ofs_+20 - wur.AE_CEND0 \at1 // ureg 247 - ae_l64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_l64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed15, \ptr, .Lxchal_ofs_+16 - addi \ptr, \ptr, 24 - ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 - ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 - ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 - ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 152 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/arch/xtensa/config/tie.h b/src/platform/cannonlake/include/arch/xtensa/config/tie.h deleted file mode 100644 index 6865fad953af..000000000000 --- a/src/platform/cannonlake/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 2 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x03 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP0_NAME "FPU" -#define XCHAL_CP0_IDENT FPU -#define XCHAL_CP0_SA_SIZE 72 /* size of state save area */ -#define XCHAL_CP0_SA_ALIGN 4 /* min alignment of save area */ -#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 184 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 12 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 272 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 3 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 18 -#define XCHAL_CP0_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, fcr, 4, 4, 4,0x03E8, ur,232, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f0, 4, 4, 4,0x0030, f,0 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f1, 4, 4, 4,0x0031, f,1 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f2, 4, 4, 4,0x0032, f,2 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f3, 4, 4, 4,0x0033, f,3 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f4, 4, 4, 4,0x0034, f,4 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f5, 4, 4, 4,0x0035, f,5 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f6, 4, 4, 4,0x0036, f,6 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f7, 4, 4, 4,0x0037, f,7 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f8, 4, 4, 4,0x0038, f,8 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f9, 4, 4, 4,0x0039, f,9 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f10, 4, 4, 4,0x003A, f,10 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f11, 4, 4, 4,0x003B, f,11 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f12, 4, 4, 4,0x003C, f,12 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f13, 4, 4, 4,0x003D, f,13 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f14, 4, 4, 4,0x003E, f,14 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f15, 4, 4, 4,0x003F, f,15 , 32,0,0,0) - -#define XCHAL_CP1_SA_NUM 26 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 -/* Byte length of instruction from its first byte, per FLIX. */ -#define XCHAL_BYTE0_FORMAT_LENGTHS \ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 - -#endif /*_XTENSA_CORE_TIE_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/cannonlake/include/platform/drivers/alh.h b/src/platform/cannonlake/include/platform/drivers/alh.h deleted file mode 100644 index 64a17690fd8d..000000000000 --- a/src/platform/cannonlake/include/platform/drivers/alh.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_ALH__ - -#ifndef __PLATFORM_DRIVERS_ALH__ -#define __PLATFORM_DRIVERS_ALH__ - -#include <stdint.h> - -/** - * \brief ALH Handshakes for audio I/O - * Stream ID -> DMA Handshake map - * -1 identifies invalid handshakes/streams - */ -static const uint8_t alh_handshake_map[64] = { - -1, /* 0 - INVALID */ - -1, /* 1 - INVALID */ - -1, /* 2 - INVALID */ - -1, /* 3 - INVALID */ - -1, /* 4 - INVALID */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - 22, /* 7 - BIDIRECTIONAL */ - 23, /* 8 - BIDIRECTIONAL */ - 24, /* 9 - BIDIRECTIONAL */ - 25, /* 10 - BIDIRECTIONAL */ - 26, /* 11 - BIDIRECTIONAL */ - 27, /* 12 - BIDIRECTIONAL */ - -1, /* 13 - INVALID */ - -1, /* 14 - INVALID */ - -1, /* 15 - INVALID */ - -1, /* 16 - INVALID */ - -1, /* 17 - INVALID */ - -1, /* 18 - INVALID */ - -1, /* 19 - INVALID */ - -1, /* 20 - INVALID */ - -1, /* 21 - INVALID */ - -1, /* 22 - INVALID */ - 32, /* 23 - BIDIRECTIONAL */ - 33, /* 24 - BIDIRECTIONAL */ - 34, /* 25 - BIDIRECTIONAL */ - 35, /* 26 - BIDIRECTIONAL */ - 36, /* 27 - BIDIRECTIONAL */ - 37, /* 28 - BIDIRECTIONAL */ - -1, /* 29 - INVALID */ - -1, /* 30 - INVALID */ - -1, /* 31 - INVALID */ - -1, /* 32 - INVALID */ - -1, /* 33 - INVALID */ - -1, /* 34 - INVALID */ - -1, /* 35 - INVALID */ - -1, /* 36 - INVALID */ - -1, /* 37 - INVALID */ - -1, /* 38 - INVALID */ - 42, /* 39 - BIDIRECTIONAL */ - 43, /* 40 - BIDIRECTIONAL */ - 44, /* 41 - BIDIRECTIONAL */ - 45, /* 42 - BIDIRECTIONAL */ - 46, /* 43 - BIDIRECTIONAL */ - 47, /* 44 - BIDIRECTIONAL */ - -1, /* 45 - INVALID */ - -1, /* 46 - INVALID */ - -1, /* 47 - INVALID */ - -1, /* 48 - INVALID */ - -1, /* 49 - INVALID */ - -1, /* 50 - INVALID */ - -1, /* 51 - INVALID */ - -1, /* 52 - INVALID */ - -1, /* 53 - INVALID */ - -1, /* 54 - INVALID */ - 52, /* 55 - BIDIRECTIONAL */ - 53, /* 56 - BIDIRECTIONAL */ - 54, /* 57 - BIDIRECTIONAL */ - 55, /* 58 - BIDIRECTIONAL */ - 56, /* 59 - BIDIRECTIONAL */ - 57, /* 60 - BIDIRECTIONAL */ - -1, /* 61 - INVALID */ - -1, /* 62 - INVALID */ - -1, /* 63 - INVALID */ -}; - -#define ALH_GPDMA_BURST_LENGTH 4 - -#endif /* __PLATFORM_DRIVERS_ALH__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/alh.h" - -#endif diff --git a/src/platform/cannonlake/include/platform/drivers/dw-dma.h b/src/platform/cannonlake/include/platform/drivers/dw-dma.h deleted file mode 100644 index 2fe0b26450d5..000000000000 --- a/src/platform/cannonlake/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <cavs/drivers/dw-dma.h> - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __SOF_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/cannonlake/include/platform/drivers/idc.h b/src/platform/cannonlake/include/platform/drivers/idc.h deleted file mode 100644 index b8565347f42e..000000000000 --- a/src/platform/cannonlake/include/platform/drivers/idc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <cavs/drivers/idc.h> - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/cannonlake/include/platform/drivers/interrupt.h b/src/platform/cannonlake/include/platform/drivers/interrupt.h deleted file mode 100644 index 057b13be1679..000000000000 --- a/src/platform/cannonlake/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,154 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <cavs/drivers/interrupt.h> -#include <sof/bit.h> -#include <config.h> - -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 32 - -/* IRQ numbers - wrt Tensilica DSP */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_SOFTWARE0 0 /* level 1 */ -#define IRQ_NUM_TIMER1 1 /* level 1 */ -#define IRQ_NUM_EXT_LEVEL1 2 /* level 1 */ -#define IRQ_NUM_SOFTWARE1 3 /* level 1 */ - -#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_EXT_LEVEL1 BIT(IRQ_NUM_EXT_LEVEL1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_SOFTWARE2 4 /* level 2 */ -#define IRQ_NUM_TIMER2 5 /* level 2 */ -#define IRQ_NUM_EXT_LEVEL2 6 /* level 2 */ -#define IRQ_NUM_SOFTWARE3 7 /* level 2 */ - -/* IRQ Level 2 bits */ -#define IRQ_BIT_LVL2_HP_GP_DMA0(x) (x + 24) -#define IRQ_BIT_LVL2_WALL_CLK1 23 -#define IRQ_BIT_LVL2_WALL_CLK0 22 -#define IRQ_BIT_LVL2_L2_MEMERR 21 -#define IRQ_BIT_LVL2_SHA256 16 -#define IRQ_BIT_LVL2_L2_CACHE 15 -#define IRQ_BIT_LVL2_IDC 8 -#define IRQ_BIT_LVL2_HOST_IPC 7 -#define IRQ_BIT_LVL2_CSME_IPC 6 -#define IRQ_BIT_LVL2_PMC_IPC 5 - -/* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) -#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC -#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC -#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 -#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 -#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR -#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE -#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 - -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_EXT_LEVEL2 BIT(IRQ_NUM_EXT_LEVEL2) -#define IRQ_MASK_SOFTWARE3 BIT(IRQ_NUM_SOFTWARE3) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_SOFTWARE4 8 /* level 3 */ -#define IRQ_NUM_TIMER3 9 /* level 3 */ -#define IRQ_NUM_EXT_LEVEL3 10 /* level 3 */ -#define IRQ_NUM_SOFTWARE5 11 /* level 3 */ - -/* IRQ Level 3 bits */ -#define IRQ_BIT_LVL3_CODE_LOADER 31 -#define IRQ_BIT_LVL3_HOST_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL3_HOST_STREAM_IN(x) (0 + x) - -/* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER -#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE4 BIT(IRQ_NUM_SOFTWARE4) -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) -#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) -#define IRQ_MASK_SOFTWARE5 BIT(IRQ_NUM_SOFTWARE5) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_SOFTWARE6 12 /* level 4 */ -#define IRQ_NUM_EXT_LEVEL4 13 /* level 4 */ -#define IRQ_NUM_SOFTWARE7 14 /* level 4 */ - -/* IRQ Level 4 bits */ -#define IRQ_BIT_LVL4_LINK_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL4_LINK_STREAM_IN(x) (0 + x) - -/* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE6 BIT(IRQ_NUM_SOFTWARE6) -#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) -#define IRQ_MASK_SOFTWARE7 BIT(IRQ_NUM_SOFTWARE7) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_SOFTWARE8 15 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL5 16 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL6 17 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL7 18 /* level 5 */ -#define IRQ_NUM_SOFTWARE9 19 /* level 5 */ - -/* IRQ Level 5 bits */ -#define IRQ_BIT_LVL5_LP_GP_DMA1 15 -#define IRQ_BIT_LVL5_LP_GP_DMA0 16 -#define IRQ_BIT_LVL5_DMIC(x) 8 -#define IRQ_BIT_LVL5_SSP(x) (0 + x) - -/* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) - -#define IRQ_MASK_SOFTWARE8 BIT(IRQ_NUM_SOFTWARE8) -#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) -#define IRQ_MASK_EXT_LEVEL6 BIT(IRQ_NUM_EXT_LEVEL6) -#define IRQ_MASK_EXT_LEVEL7 BIT(IRQ_NUM_EXT_LEVEL7) -#define IRQ_MASK_SOFTWARE9 BIT(IRQ_NUM_SOFTWARE9) - -#endif - -#define IRQ_NUM_NMI 20 /* level 7 */ - -#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/cannonlake/include/platform/lib/clk.h b/src/platform/cannonlake/include/platform/lib/clk.h deleted file mode 100644 index 61fbbd53fa55..000000000000 --- a/src/platform/cannonlake/include/platform/lib/clk.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <cavs/lib/clk.h> - -#define CLK_MAX_CPU_HZ 400000000 - -#define CPU_LPRO_FREQ_IDX 0 - -#define CPU_HPRO_FREQ_IDX 1 - -#if CONFIG_CAVS_LPRO -#define CPU_DEFAULT_IDX CPU_LPRO_FREQ_IDX -#else -#define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX -#endif - -#define SSP_DEFAULT_IDX 0 - -#define NUM_CPU_FREQ 2 - -#define NUM_SSP_FREQ 2 - -#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/cannonlake/include/platform/lib/cpu.h b/src/platform/cannonlake/include/platform/lib/cpu.h deleted file mode 100644 index 78a6e78bc889..000000000000 --- a/src/platform/cannonlake/include/platform/lib/cpu.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <cavs/lib/cpu.h> - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 4 - -#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/cannonlake/include/platform/lib/dai.h b/src/platform/cannonlake/include/platform/lib/dai.h deleted file mode 100644 index 489e0c1d0567..000000000000 --- a/src/platform/cannonlake/include/platform/lib/dai.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -/* CANNONLAKE */ - -/* 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 - -/** \brief Number of 'extended' SSP ports available */ -#define DAI_NUM_SSP_EXT 0 - -/** \brief Number of SSP MCLKs available */ -#define DAI_NUM_SSP_MCLK 2 - -/* 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 7 - -/* ALH */ - -/** \brief Number of ALH bi-directional links */ -#define DAI_NUM_ALH_BI_DIR_LINKS 24 - -/** \brief Number of contiguous ALH bi-dir links */ -#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 6 - -#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/cannonlake/include/platform/lib/dma.h b/src/platform/cannonlake/include/platform/lib/dma.h deleted file mode 100644 index 4dfae664ae11..000000000000 --- a/src/platform/cannonlake/include/platform/lib/dma.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -/* number of supported DMACs */ -#define PLATFORM_NUM_DMACS 6 - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 9 - -/* available DMACs */ -#define DMA_GP_LP_DMAC0 0 -#define DMA_GP_LP_DMAC1 1 -#define DMA_GP_HP_DMAC0 2 -#define DMA_GP_HP_DMAC1 3 -#define DMA_HOST_IN_DMAC 4 -#define DMA_HOST_OUT_DMAC 5 -#define DMA_LINK_IN_DMAC 6 -#define DMA_LINK_OUT_DMAC 7 - -/* mappings - TODO improve API to get type */ -#define DMA_ID_DMAC0 DMA_HOST_IN_DMAC -#define DMA_ID_DMAC1 DMA_GP_LP_DMAC0 -#define DMA_ID_DMAC2 DMA_HOST_OUT_DMAC -#define DMA_ID_DMAC3 DMA_GP_HP_DMAC0 -#define DMA_ID_DMAC4 DMA_GP_LP_DMAC1 -#define DMA_ID_DMAC5 DMA_GP_HP_DMAC1 -#define DMA_ID_DMAC6 DMA_LINK_IN_DMAC -#define DMA_ID_DMAC7 DMA_LINK_OUT_DMAC - -/* handshakes */ -#define DMA_HANDSHAKE_DMIC_CH0 0 -#define DMA_HANDSHAKE_DMIC_CH1 1 -#define DMA_HANDSHAKE_SSP0_TX 2 -#define DMA_HANDSHAKE_SSP0_RX 3 -#define DMA_HANDSHAKE_SSP1_TX 4 -#define DMA_HANDSHAKE_SSP1_RX 5 -#define DMA_HANDSHAKE_SSP2_TX 6 -#define DMA_HANDSHAKE_SSP2_RX 7 -#define DMA_HANDSHAKE_SSP3_TX 8 -#define DMA_HANDSHAKE_SSP3_RX 9 -#define DMA_HANDSHAKE_SSP4_TX 10 -#define DMA_HANDSHAKE_SSP4_RX 11 -#define DMA_HANDSHAKE_SSP5_TX 12 -#define DMA_HANDSHAKE_SSP5_RX 13 - -#define dma_chan_irq(dma, chan) dma_irq(dma) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/cannonlake/include/platform/lib/mailbox.h b/src/platform/cannonlake/include/platform/lib/mailbox.h deleted file mode 100644 index a781e3aecb31..000000000000 --- a/src/platform/cannonlake/include/platform/lib/mailbox.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_MAILBOX_H__ - -#ifndef __PLATFORM_LIB_MAILBOX_H__ -#define __PLATFORM_LIB_MAILBOX_H__ - -#include <cavs/lib/mailbox.h> - -#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/cannonlake/include/platform/lib/memory.h b/src/platform/cannonlake/include/platform/lib/memory.h deleted file mode 100644 index 800c27840e67..000000000000 --- a/src/platform/cannonlake/include/platform/lib/memory.h +++ /dev/null @@ -1,425 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_MEMORY_H__ - -#ifndef __PLATFORM_LIB_MEMORY_H__ -#define __PLATFORM_LIB_MEMORY_H__ - -#include <cavs/lib/memory.h> -#include <sof/lib/cpu.h> -#include <config.h> - -/* physical DSP addresses */ - -/* shim */ -#define SHIM_BASE 0x00071F00 -#define SHIM_SIZE 0x00000100 - -/* Digital Mic Shim Registers */ -#define DMIC_SHIM_BASE 0x00071E80 -#define DMICLCTL_OFFSET 0x04 -#define DMICLCTL (DMIC_SHIM_BASE + DMICLCTL_OFFSET) - -/* cmd IO to audio codecs */ -#define CMD_BASE 0x00001100 -#define CMD_SIZE 0x00000010 - -/* resource allocation */ -#define RES_BASE 0x00001110 -#define RES_SIZE 0x00000010 - -/* IPC to the host */ -#define IPC_HOST_BASE 0x00071E00 -#define IPC_HOST_SIZE 0x00000020 - -/* intra DSP IPC */ -#define IPC_DSP_SIZE 0x00000080 -#define IPC_DSP_BASE(x) (0x00001200 + x * IPC_DSP_SIZE) - -/* SRAM window for HOST */ -#define HOST_WIN_SIZE 0x00000008 -#define HOST_WIN_BASE(x) (0x00071A00 + x * HOST_WIN_SIZE) - -/* IRQ controller */ -#define IRQ_BASE 0x00078800 -#define IRQ_SIZE 0x00000200 - -/* time stamping */ -#define TIME_BASE 0x00071800 -#define TIME_SIZE 0x00000200 - -/* M/N dividers */ -#define MN_BASE 0x00078C00 -#define MN_SIZE 0x00000200 - -/* low power DMA position */ -#define LP_GP_DMA_LINK_SIZE 0x00000010 -#define LP_GP_DMA_LINK_BASE(x) (0x00001C00 + x * LP_GP_DMA_LINK_SIZE) - -/* high performance DMA position */ -#define HP_GP_DMA_LINK_SIZE 0x00000010 -#define HP_GP_DMA_LINK_BASE(x) (0x00001D00 + x * HP_GP_DMA_LINK_SIZE) - -/* link DMAC stream */ -#define GTW_LINK_OUT_STREAM_SIZE 0x00000020 -#define GTW_LINK_OUT_STREAM_BASE(x) \ - (0x00072400 + x * GTW_LINK_OUT_STREAM_SIZE) - -#define GTW_LINK_IN_STREAM_SIZE 0x00000020 -#define GTW_LINK_IN_STREAM_BASE(x) \ - (0x00072600 + x * GTW_LINK_IN_STREAM_SIZE) - -/* host DMAC stream */ -#define GTW_HOST_OUT_STREAM_SIZE 0x00000040 -#define GTW_HOST_OUT_STREAM_BASE(x) \ - (0x00072800 + x * GTW_HOST_OUT_STREAM_SIZE) - -#define GTW_HOST_IN_STREAM_SIZE 0x00000040 -#define GTW_HOST_IN_STREAM_BASE(x) \ - (0x00072C00 + x * GTW_HOST_IN_STREAM_SIZE) - -/* code loader */ -#define GTW_CODE_LDR_SIZE 0x00000040 -#define GTW_CODE_LDR_BASE 0x00002BC0 - -/* L2 TLBs */ -#define L2_HP_SRAM_TLB_SIZE 0x00001000 -#define L2_HP_SRAM_TLB_BASE 0x00003000 - -/* DMICs */ -#define DMIC_BASE 0x00010000 -#define DMIC_SIZE 0x00008000 - -/* SSP */ -#define SSP_BASE(x) (0x00077000 + x * SSP_SIZE) -#define SSP_SIZE 0x0000200 - -/* ALH */ -#define ALH_BASE 0x000071000 -#define ALH_TXDA_OFFSET 0x000000400 -#define ALH_RXDA_OFFSET 0x000000500 -#define ALH_STREAM_OFFSET 0x000000004 - -/* Timestamping */ -#define TIMESTAMP_BASE 0x00071800 - -/* low power DMACs */ -#define LP_GP_DMA_SIZE 0x00001000 -#define LP_GP_DMA_BASE(x) (0x0007C000 + x * LP_GP_DMA_SIZE) - -/* high performance DMACs */ -#define HP_GP_DMA_SIZE 0x00001000 -#define HP_GP_DMA_BASE(x) (0x0000E000 + x * HP_GP_DMA_SIZE) - -/* ROM */ -#define ROM_BASE 0xBEFE0000 -#define ROM_SIZE 0x00002000 - -#define L2_VECTOR_SIZE 0x1000 - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -/* - * The HP SRAM Region on Cannonlake is organised like this :- - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_SW_REG_BASE | SW Registers W0 | SRAM_SW_REG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_MAILBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_EXCEPT_BASE | Debug data W2 | SRAM_EXCEPT_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_STREAM_BASE | Stream data W2 | SRAM_STREAM_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_TRACE_BASE | Trace Buffer W3 | SRAM_TRACE_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SOF_FW_START | text | | - * | | data | | - * | | ----------------------- | | - * | ||BSS: || | - * | ||-----------------------++-----------------------------+ - * | ||Runtime Heap || HEAP_RUNTIME_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Module Buffers || HEAP_BUFFER_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master core Sys Heap || HEAP_SYSTEM_M_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master Sys Runtime Heap|| HEAP_SYS_RUNTIME_M_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master core Stack || SOF_STACK_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Slave core Sys Heap || SOF_CORE_S_T_SIZE | - * | ||Slave Sys Runtime Heap || | - * | ||Slave core Stack || | - * | | ----------------------- | | - * +------------------+-------------------------+-----------------------------+ - */ - -/* HP SRAM */ -#define HP_SRAM_BASE 0xBE000000 - -/* HP SRAM windows */ -/* window 0 */ -#define SRAM_SW_REG_BASE (HP_SRAM_BASE + 0x4000) -#define SRAM_SW_REG_SIZE 0x1000 - -/* SRAM window 0 FW "registers" */ -#define SRAM_REG_ROM_STATUS 0x0 -#define SRAM_REG_FW_STATUS 0x4 -#define SRAM_REG_FW_TRACEP 0x8 -#define SRAM_REG_FW_IPC_RECEIVED_COUNT 0xc -#define SRAM_REG_FW_IPC_PROCESSED_COUNT 0x10 -#define SRAM_REG_FW_END 0x14 - -#define SRAM_OUTBOX_BASE (SRAM_SW_REG_BASE + SRAM_SW_REG_SIZE) -#define SRAM_OUTBOX_SIZE 0x1000 - -/* window 1 */ -#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) -#define SRAM_INBOX_SIZE 0x2000 - -/* window 2 */ -#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) -#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 - -/* window 3 */ -#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) -#if CONFIG_TRACE -#define SRAM_TRACE_SIZE 0x2000 -#else -#define SRAM_TRACE_SIZE 0x0 -#endif - -#define HP_SRAM_WIN0_BASE SRAM_SW_REG_BASE -#define HP_SRAM_WIN0_SIZE (SRAM_SW_REG_SIZE + SRAM_OUTBOX_SIZE) -#define HP_SRAM_WIN1_BASE SRAM_INBOX_BASE -#define HP_SRAM_WIN1_SIZE SRAM_INBOX_SIZE -#define HP_SRAM_WIN2_BASE SRAM_DEBUG_BASE -#define HP_SRAM_WIN2_SIZE (SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE + \ - SRAM_STREAM_SIZE) -#define HP_SRAM_WIN3_BASE SRAM_TRACE_BASE -#define HP_SRAM_WIN3_SIZE SRAM_TRACE_SIZE - -/* HP SRAM Base */ -#define HP_SRAM_VECBASE_RESET (SRAM_TRACE_BASE + SRAM_TRACE_SIZE) - -/* text and data share the same HP L2 SRAM on Cannonlake */ -#define SOF_FW_START (HP_SRAM_VECBASE_RESET + 0x400) -#define SOF_FW_BASE (SOF_FW_START) - -/* max size for all var-size sections (text/rodata/bss) */ -#define SOF_FW_MAX_SIZE (HP_SRAM_BASE + HP_SRAM_SIZE - SOF_FW_BASE) - -#define SOF_TEXT_START (SOF_FW_START) -#define SOF_TEXT_BASE (SOF_FW_START) - -/* Heap section sizes for system runtime heap for master core */ -#define HEAP_SYS_RT_0_COUNT64 128 -#define HEAP_SYS_RT_0_COUNT512 16 -#define HEAP_SYS_RT_0_COUNT1024 4 - -/* Heap section sizes for system runtime heap for slave core */ -#define HEAP_SYS_RT_X_COUNT64 64 -#define HEAP_SYS_RT_X_COUNT512 8 -#define HEAP_SYS_RT_X_COUNT1024 4 - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT64 128 -#define HEAP_RT_COUNT128 64 -#define HEAP_RT_COUNT256 128 -#define HEAP_RT_COUNT512 8 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 0 -#define HEAP_RT_COUNT4096 1 - -/* Heap configuration */ -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT64 * 64 + HEAP_RT_COUNT128 * 128 + \ - HEAP_RT_COUNT256 * 256 + HEAP_RT_COUNT512 * 512 + \ - HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + \ - HEAP_RT_COUNT4096 * 4096) - -#define HEAP_BUFFER_SIZE 0x50000 -#define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) - -#define HEAP_SYSTEM_M_SIZE 0x8000 /* heap master core size */ -#define HEAP_SYSTEM_S_SIZE 0x6000 /* heap slave core size */ - -#define HEAP_SYSTEM_T_SIZE \ - (HEAP_SYSTEM_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) - -#define HEAP_SYS_RUNTIME_M_SIZE \ - (HEAP_SYS_RT_0_COUNT64 * 64 + HEAP_SYS_RT_0_COUNT512 * 512 + \ - HEAP_SYS_RT_0_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_S_SIZE \ - (HEAP_SYS_RT_X_COUNT64 * 64 + HEAP_SYS_RT_X_COUNT512 * 512 + \ - HEAP_SYS_RT_X_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_T_SIZE \ - (HEAP_SYS_RUNTIME_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * \ - HEAP_SYS_RUNTIME_S_SIZE)) - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * SOF_STACK_SIZE) - -/* SOF Core S configuration */ -#define SOF_CORE_S_SIZE \ - ALIGN((HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE + SOF_STACK_SIZE),\ - SRAM_BANK_SIZE) -#define SOF_CORE_S_T_SIZE ((PLATFORM_CORE_COUNT - 1) * SOF_CORE_S_SIZE) - -/* - * The LP SRAM Heap and Stack on Cannonlake are organised like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | LP_SRAM_BASE | RO Data | SOF_LP_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_SYSTEM_BASE | System Heap | HEAP_LP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_RUNTIME_BASE| Runtime Heap | HEAP_LP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_BUFFER_BASE | Module Buffers | HEAP_LP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_LP_STACK_END | Stack | SOF_LP_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - -/* LP SRAM */ -#define LP_SRAM_BASE 0xBE800000 - -/* Heap section sizes for module pool */ -#define HEAP_RT_LP_COUNT8 0 -#define HEAP_RT_LP_COUNT16 256 -#define HEAP_RT_LP_COUNT32 128 -#define HEAP_RT_LP_COUNT64 64 -#define HEAP_RT_LP_COUNT128 64 -#define HEAP_RT_LP_COUNT256 96 -#define HEAP_RT_LP_COUNT512 8 -#define HEAP_RT_LP_COUNT1024 4 - -/* Heap configuration */ -#define SOF_LP_DATA_SIZE 0x4000 - -#define HEAP_LP_SYSTEM_BASE (LP_SRAM_BASE + SOF_LP_DATA_SIZE) -#define HEAP_LP_SYSTEM_SIZE 0x1000 - -#define HEAP_LP_RUNTIME_BASE \ - (HEAP_LP_SYSTEM_BASE + HEAP_LP_SYSTEM_SIZE) -#define HEAP_LP_RUNTIME_SIZE \ - (HEAP_RT_LP_COUNT8 * 8 + HEAP_RT_LP_COUNT16 * 16 + \ - HEAP_RT_LP_COUNT32 * 32 + HEAP_RT_LP_COUNT64 * 64 + \ - HEAP_RT_LP_COUNT128 * 128 + HEAP_RT_LP_COUNT256 * 256 + \ - HEAP_RT_LP_COUNT512 * 512 + HEAP_RT_LP_COUNT1024 * 1024) - -#if (CONFIG_CAVS_LPS) -#define LPS_RESTORE_VECTOR_OFFSET 0x1000 -#define LPS_RESTORE_VECTOR_SIZE 0x800 -#define LPS_RESTORE_VECTOR_ADDR (LP_SRAM_BASE + LPS_RESTORE_VECTOR_OFFSET) -#define HEAP_LP_BUFFER_BASE (LPS_RESTORE_VECTOR_ADDR + LPS_RESTORE_VECTOR_SIZE) -#define HEAP_LP_BUFFER_SIZE (LP_SRAM_SIZE - LPS_RESTORE_VECTOR_SIZE -\ - LPS_RESTORE_VECTOR_OFFSET) -#else -#define HEAP_LP_BUFFER_BASE LP_SRAM_BASE -#define HEAP_LP_BUFFER_SIZE LP_SRAM_SIZE -#endif - -#define HEAP_LP_BUFFER_BLOCK_SIZE 0x180 - -#if CONFIG_LP_MEMORY_BANKS -#define HEAP_LP_BUFFER_COUNT \ - (HEAP_LP_BUFFER_SIZE / HEAP_LP_BUFFER_BLOCK_SIZE) -#else -#define HEAP_LP_BUFFER_COUNT 0 -#endif - -#define PLATFORM_HEAP_SYSTEM PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 2 - -/* Stack configuration */ -#define SOF_LP_STACK_SIZE 0x1000 -#define SOF_LP_STACK_BASE (LP_SRAM_BASE + LP_SRAM_SIZE) -#define SOF_LP_STACK_END (SOF_LP_STACK_BASE - SOF_LP_STACK_SIZE) - - -/* Vector and literal sizes - do not use core-isa.h */ -#define SOF_MEM_VECBASE HP_SRAM_VECBASE_RESET -#define SOF_MEM_VECT_LIT_SIZE 0x8 -#define SOF_MEM_VECT_TEXT_SIZE 0x38 -#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ - SOF_MEM_VECT_LIT_SIZE) - -#define SOF_MEM_ERROR_TEXT_SIZE 0x180 -#define SOF_MEM_ERROR_LIT_SIZE 0x8 - -#define SOF_MEM_RESET_TEXT_SIZE 0x268 -#define SOF_MEM_RESET_LIT_SIZE 0x8 -#define SOF_MEM_VECBASE_LIT_SIZE 0x178 - -#define SOF_MEM_RO_SIZE 0x8 - -/* VM ROM sizes */ -#define ROM_RESET_TEXT_SIZE 0x400 -#define ROM_RESET_LIT_SIZE 0x200 - -/* boot loader in IMR */ -#define IMR_BOOT_LDR_MANIFEST_BASE 0xB0032000 -#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 - -#define IMR_BOOT_LDR_TEXT_ENTRY_BASE 0xB0038000 -#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x120 -#define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ - IMR_BOOT_LDR_TEXT_ENTRY_SIZE) -#define IMR_BOOT_LDR_LIT_SIZE 0x22 -#define IMR_BOOT_LDR_TEXT_BASE (IMR_BOOT_LDR_LIT_BASE + \ - IMR_BOOT_LDR_LIT_SIZE) -#define IMR_BOOT_LDR_TEXT_SIZE 0x1C00 -#define IMR_BOOT_LDR_DATA_BASE 0xB0039000 -#define IMR_BOOT_LDR_DATA_SIZE 0x1000 -#define IMR_BOOT_LDR_BSS_BASE 0xB0100000 -#define IMR_BOOT_LDR_BSS_SIZE 0x10000 - -/* Temporary stack place for boot_ldr */ -#define BOOT_LDR_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE - \ - SOF_STACK_TOTAL_SIZE) -#define BOOT_LDR_STACK_SIZE SOF_STACK_TOTAL_SIZE - -#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/cannonlake/include/platform/lib/pm_runtime.h b/src/platform/cannonlake/include/platform/lib/pm_runtime.h deleted file mode 100644 index edda6e691ff1..000000000000 --- a/src/platform/cannonlake/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/cannonlake/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Cannonlake - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <cavs/lib/pm_runtime.h> -#include <stdint.h> - -/** - * \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_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); - -/** - * \brief Power gates platform specific hardware resources. - */ -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/cannonlake/include/platform/lib/shim.h b/src/platform/cannonlake/include/platform/lib/shim.h deleted file mode 100644 index cc497fa85b17..000000000000 --- a/src/platform/cannonlake/include/platform/lib/shim.h +++ /dev/null @@ -1,370 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <cavs/drivers/sideband-ipc.h> -#include <sof/bit.h> -#include <sof/lib/memory.h> - -#ifndef ASSEMBLY -#include <stdint.h> -#endif - -/* DSP IPC for Host Registers */ -#define IPC_DIPCTDR 0x00 -#define IPC_DIPCTDA 0x04 -#define IPC_DIPCTDD 0x08 -#define IPC_DIPCIDR 0x10 -#define IPC_DIPCIDA 0x14 -#define IPC_DIPCIDD 0x18 -#define IPC_DIPCCTL 0x28 - -#define IPC_DSP_OFFSET 0x10 - -/* DSP IPC for intra DSP communication */ -#define IPC_IDCTFC(x) (0x0 + x * IPC_DSP_OFFSET) -#define IPC_IDCTEFC(x) (0x4 + x * IPC_DSP_OFFSET) -#define IPC_IDCITC(x) (0x8 + x * IPC_DSP_OFFSET) -#define IPC_IDCIETC(x) (0xc + x * IPC_DSP_OFFSET) -#define IPC_IDCCTL 0x50 - -/* IDCTFC */ -#define IPC_IDCTFC_BUSY BIT(31) -#define IPC_IDCTFC_MSG_MASK 0x7FFFFFFF - -/* IDCTEFC */ -#define IPC_IDCTEFC_MSG_MASK 0x3FFFFFFF - -/* IDCITC */ -#define IPC_IDCITC_BUSY BIT(31) -#define IPC_IDCITC_MSG_MASK 0x7FFFFFFF - -/* IDCIETC */ -#define IPC_IDCIETC_DONE BIT(30) -#define IPC_IDCIETC_MSG_MASK 0x3FFFFFFF - -/* IDCCTL */ -#define IPC_IDCCTL_IDCIDIE(x) (0x100 << (x)) -#define IPC_IDCCTL_IDCTBIE(x) BIT(x) - -#define IRQ_CPU_OFFSET 0x40 - -#define REG_IRQ_IL2MSD(xcpu) (0x0 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MCD(xcpu) (0x4 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MD(xcpu) (0x8 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2SD(xcpu) (0xc + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL2MD_ALL 0x03F181F0 - -#define REG_IRQ_IL3MSD(xcpu) (0x10 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MCD(xcpu) (0x14 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MD(xcpu) (0x18 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3SD(xcpu) (0x1c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL3MD_ALL 0x807F81FF - -#define REG_IRQ_IL4MSD(xcpu) (0x20 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MCD(xcpu) (0x24 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MD(xcpu) (0x28 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4SD(xcpu) (0x2c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL4MD_ALL 0x807F81FF - -#define REG_IRQ_IL5MSD(xcpu) (0x30 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MCD(xcpu) (0x34 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MD(xcpu) (0x38 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5SD(xcpu) (0x3c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL5MD_ALL 0xFFFFC0CF - -#define REG_IRQ_IL2RSD 0x100 -#define REG_IRQ_IL3RSD 0x104 -#define REG_IRQ_IL4RSD 0x108 -#define REG_IRQ_IL5RSD 0x10c - -#define REG_IRQ_LVL5_LP_GPDMA0_MASK (0xff << 16) -#define REG_IRQ_LVL5_LP_GPDMA1_MASK (0xff << 24) - -/* DSP Shim Registers */ -#define SHIM_DSPWC 0x20 /* DSP Wall Clock */ -#define SHIM_DSPWCTCS 0x28 /* DSP Wall Clock Timer Control & Status */ -#define SHIM_DSPWCT0C 0x30 /* DSP Wall Clock Timer 0 Compare */ -#define SHIM_DSPWCT1C 0x38 /* DSP Wall Clock Timer 1 Compare */ - -#define SHIM_DSPWCTCS_T1T BIT(5) /* Timer 1 triggered */ -#define SHIM_DSPWCTCS_T0T BIT(4) /* Timer 0 triggered */ -#define SHIM_DSPWCTCS_T1A BIT(1) /* Timer 1 armed */ -#define SHIM_DSPWCTCS_T0A BIT(0) /* Timer 0 armed */ - -/** \brief Clock control */ -#define SHIM_CLKCTL 0x78 - -/** \brief Request HP RING Oscillator Clock */ -#define SHIM_CLKCTL_RHROSCC BIT(31) - -/** \brief Request XTAL Oscillator Clock */ -#define SHIM_CLKCTL_RXOSCC BIT(30) - -/** \brief Request LP RING Oscillator Clock */ -#define SHIM_CLKCTL_RLROSCC BIT(29) - -/** \brief Tensilica Core Prevent Local Clock Gating */ -#define SHIM_CLKCTL_TCPLCG_EN(x) BIT(16 + (x)) -#define SHIM_CLKCTL_TCPLCG_DIS(x) 0 -#define SHIM_CLKCTL_TCPLCG_DIS_ALL (SHIM_CLKCTL_TCPLCG_DIS(0) | \ - SHIM_CLKCTL_TCPLCG_DIS(1) | \ - SHIM_CLKCTL_TCPLCG_DIS(2) | \ - SHIM_CLKCTL_TCPLCG_DIS(3)) - -/** \brief Core clock PLL divisor */ -#define SHIM_CLKCTL_DPCS_MASK(x) BIT(2) - -/** \brief DMIC Force Dynamic Clock Gating */ -#define SHIM_CLKCTL_DMICFDCGB BIT(30) - -/** \brief Oscillator Clock Select*/ -#define SHIM_CLKCTL_OCS_HP_RING BIT(2) -#define SHIM_CLKCTL_OCS_LP_RING 0 - -/** \brief LP Memory Clock Select */ -#define SHIM_CLKCTL_LMCS_DIV2 0 -#define SHIM_CLKCTL_LMCS_DIV4 BIT(1) - -/** \brief HP Memory Clock Select */ -#define SHIM_CLKCTL_HMCS_DIV2 0 -#define SHIM_CLKCTL_HMCS_DIV4 BIT(0) - -/* Core clock PLL divisor */ -#define SHIM_CLKCTL_DPCS_MASK(x) BIT(2) - -/* Prevent Audio PLL Shutdown */ -#define SHIM_CLKCTL_TCPAPLLS BIT(7) - -/* 0--from PLL, 1--from oscillator */ -#define SHIM_CLKCTL_HDCS BIT(4) - -/* Oscillator select */ -#define SHIM_CLKCTL_HDOCS BIT(2) - -/* HP memory clock PLL divisor */ -#define SHIM_CLKCTL_HPMPCS BIT(0) - -/** \brief Mask for requesting clock - */ -#define SHIM_CLKCTL_OSC_REQUEST_MASK \ - (SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_RXOSCC | \ - SHIM_CLKCTL_RLROSCC) - -/** \brief Mask for setting previously requested clock - */ -#define SHIM_CLKCTL_OSC_SOURCE_MASK \ - (SHIM_CLKCTL_OCS_HP_RING | SHIM_CLKCTL_LMCS_DIV4 | \ - SHIM_CLKCTL_HMCS_DIV4) - -/** \brief Clock status */ -#define SHIM_CLKSTS 0x7C - -/** \brief HP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_HROSCCS BIT(31) - -/** \brief XTAL Oscillator Clock Status */ -#define SHIM_CLKSTS_XOSCCS BIT(30) - -/** \brief LP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_LROSCCS BIT(29) - -#define SHIM_PWRCTL 0x90 -#define SHIM_PWRCTL_TCPDSPPG(x) BIT(x) -#define SHIM_PWRCTL_TCPCTLPG BIT(4) - -#define SHIM_PWRSTS 0x92 - -#define SHIM_LPSCTL 0x94 -#define SHIM_LPSCTL_BID BIT(7) -#define SHIM_LPSCTL_FDSPRUN BIT(9) -#define SHIM_LPSCTL_BATTR_0 BIT(12) - -/** \brief GPDMA shim registers Control */ -#define SHIM_GPDMA_BASE_OFFSET 0x6500 -#define SHIM_GPDMA_BASE(x) (SHIM_GPDMA_BASE_OFFSET + (x) * 0x100) - -/** \brief GPDMA Clock Control */ -#define SHIM_GPDMA_CLKCTL(x) (SHIM_GPDMA_BASE(x) + 0x4) -/* LP GPDMA Force Dynamic Clock Gating bits, 0--enable */ -#define SHIM_CLKCTL_LPGPDMAFDCGB BIT(0) - -/** \brief GPDMA Channel Linear Link Position Control */ -#define SHIM_GPDMA_CHLLPC(x, y) (SHIM_GPDMA_BASE(x) + 0x10 + (y) * 0x10) -#define SHIM_GPDMA_CHLLPC_EN BIT(7) -#define SHIM_GPDMA_CHLLPC_DHRS(x) SET_BITS(6, 0, x) - -#define L2LMCAP 0x71D00 -#define L2MPAT 0x71D04 - -#define HSPGCTL0 0x71D10 -#define HSRMCTL0 0x71D14 -#define HSPGISTS0 0x71D18 - -#define SHIM_HSPGCTL(x) (HSPGCTL0 + 0x10 * (x)) -#define SHIM_HSPGISTS(x) (HSPGISTS0 + 0x10 * (x)) - -#define HSPGCTL1 0x71D20 -#define HSRMCTL1 0x71D24 -#define HSPGISTS1 0x71D28 - -#define LSPGCTL 0x71D50 -#define LSRMCTL 0x71D54 -#define LSPGISTS 0x71D58 - -#define SHIM_L2_MECS (SHIM_BASE + 0xd0) - -/** \brief LDO Control */ -#define SHIM_LDOCTL 0xA4 -#define SHIM_LDOCTL_HPSRAM_MASK (3 << 0) -#define SHIM_LDOCTL_LPSRAM_MASK (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) -#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS BIT(2) -#define SHIM_LDOCTL_HPSRAM_LDO_OFF (0 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_OFF (0 << 2) - -#define DSP_INIT_LPGPDMA(x) (0x71A60 + (2*x)) -#define LPGPDMA_CTLOSEL_FLAG BIT(15) -#define LPGPDMA_CHOSEL_FLAG 0xFF - -#define DSP_INIT_IOPO 0x71A68 -#define IOPO_DMIC_FLAG BIT(0) -#define IOPO_I2S_FLAG (7 << 8) - -#define DSP_INIT_GENO 0x71A6C -#define GENO_MDIVOSEL BIT(1) -#define GENO_DIOPTOSEL BIT(2) - -#define DSP_INIT_ALHO 0x71A70 -#define ALHO_ASO_FLAG BIT(0) -#define ALHO_CSO_FLAG BIT(1) -#define ALHO_CFO_FLAG BIT(2) - -#define SHIM_SVCFG 0xF4 -#define SHIM_SVCFG_FORCE_L1_EXIT BIT(1) - -/* host windows */ -#define DMWBA(x) (HOST_WIN_BASE(x) + 0x0) -#define DMWLO(x) (HOST_WIN_BASE(x) + 0x4) - -#define DMWBA_ENABLE BIT(0) -#define DMWBA_READONLY BIT(1) - -/* DMIC power ON bit */ -#define DMICLCTL_SPA ((uint32_t) BIT(0)) - -/* DMIC disable clock gating */ -#define DMIC_DCGD ((uint32_t) BIT(30)) - -#ifndef ASSEMBLY - -static inline uint16_t shim_read16(uint16_t reg) -{ - return *((volatile uint16_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write16(uint16_t reg, uint16_t val) -{ - *((volatile uint16_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint64_t shim_read64(uint32_t reg) -{ - return *((volatile uint64_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write64(uint32_t reg, uint64_t val) -{ - *((volatile uint64_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t sw_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)); -} - -static inline void sw_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)) = val; -} - -static inline uint32_t mn_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)(MN_BASE + reg)); -} - -static inline void mn_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(MN_BASE + reg)) = val; -} - -static inline uint32_t irq_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IRQ_BASE + reg)); -} - -static inline void irq_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IRQ_BASE + reg)) = val; -} - -static inline uint32_t ipc_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IPC_HOST_BASE + reg)); -} - -static inline void ipc_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IPC_HOST_BASE + reg)) = val; -} - -static inline uint32_t idc_read(uint32_t reg, uint32_t core_id) -{ - return *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)); -} - -static inline void idc_write(uint32_t reg, uint32_t core_id, uint32_t val) -{ - *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)) = val; -} -#endif - -#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/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h deleted file mode 100644 index f28c8a5062aa..000000000000 --- a/src/platform/cannonlake/include/platform/platform.h +++ /dev/null @@ -1,117 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - * Xiuli Pan <xiuli.pan@linux.intel.com> - */ - -#ifdef __SOF_PLATFORM_H__ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_RESET_MHE_AT_BOOT 1 - -#define PLATFORM_MEM_INIT_AT_BOOT 1 - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> -#include <stddef.h> -#include <stdint.h> - -struct ll_schedule_domain; -struct timer; - -/*! \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 - -#define MAX_GPDMA_COUNT 2 - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 -#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2 -#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL - -/* 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) - -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 500 - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* minimal L1 exit time in cycles */ -#define PLATFORM_FORCE_L1_EXIT_TIME 985 - -/* the SSP port fifo depth */ -#define SSP_FIFO_DEPTH 16 - -/* the watermark for the SSP fifo depth setting */ -#define SSP_FIFO_WATERMARK 8 - -/* minimal SSP port delay in cycles */ -#define PLATFORM_SSP_DELAY 1000 - -/* Platform defined trace code */ -static inline void platform_panic(uint32_t p) -{ - mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p & 0x3fffffff); - ipc_write(IPC_DIPCIDD, MAILBOX_EXCEPTION_OFFSET + 2 * 0x20000); - ipc_write(IPC_DIPCIDR, 0x80000000 | (p & 0x3fffffff)); -} - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -void platform_wait_for_interrupt(int level); - -extern intptr_t _module_init_start; -extern intptr_t _module_init_end; - -#endif -#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/cannonlake/include/platform/trace/trace.h b/src/platform/cannonlake/include/platform/trace/trace.h deleted file mode 100644 index 22a480092132..000000000000 --- a/src/platform/cannonlake/include/platform/trace/trace.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_TRACE_TRACE_H__ - -#ifndef __PLATFORM_TRACE_TRACE_H__ -#define __PLATFORM_TRACE_TRACE_H__ - -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - mailbox_sw_reg_write(SRAM_REG_FW_TRACEP, (__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/cannonlake/lib/CMakeLists.txt b/src/platform/cannonlake/lib/CMakeLists.txt deleted file mode 100644 index 47a1b5962abf..000000000000 --- a/src/platform/cannonlake/lib/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof clk.c) diff --git a/src/platform/cannonlake/lib/clk.c b/src/platform/cannonlake/lib/clk.c deleted file mode 100644 index 44c4bce6c52f..000000000000 --- a/src/platform/cannonlake/lib/clk.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> - -const struct freq_table platform_cpu_freq[] = { - { 120000000, 120000 }, - { CLK_MAX_CPU_HZ, 400000 }, -}; - -const uint32_t cpu_freq_enc[] = { - SHIM_CLKCTL_RLROSCC | SHIM_CLKCTL_OCS_LP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, - SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_OCS_HP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, -}; - -const uint32_t cpu_freq_status_mask[] = { - SHIM_CLKSTS_LROSCCS, - SHIM_CLKSTS_HROSCCS, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table *cpu_freq = platform_cpu_freq; - -/* IMPORTANT: array should be filled in increasing order - * (regarding to .freq field) - */ -const static struct freq_table platform_ssp_freq[] = { - { 24000000, 24000 }, - { 96000000, 96000 }, -}; - -const static uint32_t platform_ssp_freq_sources[] = { - SSP_CLOCK_XTAL_OSCILLATOR, - SSP_CLOCK_PLL_FIXED, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; diff --git a/src/platform/cannonlake/rom.x.in b/src/platform/cannonlake/rom.x.in deleted file mode 100644 index d811b63c2c75..000000000000 --- a/src/platform/cannonlake/rom.x.in +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Linker Script for Apollolake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = ROM_BASE, - len = ROM_RESET_TEXT_SIZE - vector_reset_lit : - org = ROM_BASE + ROM_RESET_TEXT_SIZE, - len = ROM_RESET_LIT_SIZE - vector_base_text : - org = ROM_BASE + ROM_RESET_TEXT_SIZE + ROM_RESET_LIT_SIZE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = ROM_BASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = ROM_BASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = ROM_BASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = ROM_BASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text : - org = ROM_BASE + 0x800, - len = ROM_SIZE, - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; -} - -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = ROM_BASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - /* stack */ - _end = BOOT_LDR_STACK_BASE; - PROVIDE(end = BOOT_LDR_STACK_BASE); - _stack_sentry = BOOT_LDR_STACK_BASE; - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/haswell/haswell.x.in b/src/platform/haswell/haswell.x.in deleted file mode 100644 index 3f9adaea9c95..000000000000 --- a/src/platform/haswell/haswell.x.in +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Linker Script for Baytrail. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = XCHAL_RESET_VECTOR_PADDR, - len = SOF_MEM_RESET_TEXT_SIZE - vector_reset_lit : - org = XCHAL_RESET_VECTOR_PADDR + SOF_MEM_RESET_TEXT_SIZE, - len = SOF_MEM_RESET_LIT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE_TEXT_BASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = XCHAL_INTLEVEL2_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = XCHAL_INTLEVEL3_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = XCHAL_INTLEVEL4_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = XCHAL_INTLEVEL5_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = XCHAL_INTLEVEL6_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = XCHAL_INTLEVEL6_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = XCHAL_INTLEVEL7_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = XCHAL_INTLEVEL7_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = XCHAL_KERNEL_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = XCHAL_USER_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = XCHAL_DOUBLEEXC_VECTOR_PADDR, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text_start : - org = XCHAL_NMI_VECTOR_VADDR + SOF_MEM_VECT_SIZE, - len = (IRAM_BASE + IRAM_SIZE) - (XCHAL_NMI_VECTOR_VADDR + SOF_MEM_VECT_SIZE) - sof_data_ro : - org = DRAM0_BASE, - len = SOF_MEM_RO_SIZE - sof_data : - org = DRAM0_BASE + SOF_MEM_RO_SIZE, - len = HEAP_SYSTEM_BASE - (DRAM0_BASE + SOF_MEM_RO_SIZE) - system_heap : - org = HEAP_SYSTEM_BASE, - len = HEAP_SYSTEM_SIZE - system_runtime_heap : - org = HEAP_SYS_RUNTIME_BASE, - len = HEAP_SYS_RUNTIME_SIZE - runtime_heap : - org = HEAP_RUNTIME_BASE, - len = HEAP_RUNTIME_SIZE - buffer_heap : - org = HEAP_BUFFER_BASE, - len = HEAP_BUFFER_SIZE - sof_stack : - org = SOF_STACK_END, - len = SOF_STACK_BASE - SOF_STACK_END - mailbox : - org = MAILBOX_BASE, - len = MAILBOX_SIZE - virtual_thread : - org = SOF_VIRTUAL_THREAD_BASE, - len = SOF_VIRTUAL_THREAD_SIZE - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_base_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - sof_text_start_phdr PT_LOAD; - sof_data_ro_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_data_bss_phdr PT_LOAD; - system_heap_phdr PT_LOAD; - system_runtime_heap_phdr PT_LOAD; - runtime_heap_phdr PT_LOAD; - buffer_heap_phdr PT_LOAD; - mailbox_phdr PT_LOAD; - virtual_thread_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; -} - -/* Default entry point: */ -ENTRY(_ResetVector) -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = SOF_MEM_VECBASE_TEXT_BASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wb_base = 0x44024000; -_memmap_cacheattr_wt_base = 0x11021000; -_memmap_cacheattr_bp_base = 0x22022000; -_memmap_cacheattr_unused_mask = 0x00F00FFF; -_memmap_cacheattr_wb_trapnull = 0x4422422F; -_memmap_cacheattr_wba_trapnull = 0x4422422F; -_memmap_cacheattr_wbna_trapnull = 0x25222222; -_memmap_cacheattr_wt_trapnull = 0x1122122F; -_memmap_cacheattr_bp_trapnull = 0x2222222F; -_memmap_cacheattr_wb_strict = 0x44F24FFF; -_memmap_cacheattr_wt_strict = 0x11F21FFF; -_memmap_cacheattr_bp_strict = 0x22F22FFF; -_memmap_cacheattr_wb_allvalid = 0x44224222; -_memmap_cacheattr_wt_allvalid = 0x11221222; -_memmap_cacheattr_bp_allvalid = 0x22222222; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text_start :sof_text_start_phdr - - .reset.rodata : ALIGN(4) - { - _reset_rodata_start = ABSOLUTE(.); - *(.reset.rodata) - _reset_rodata_end = ABSOLUTE(.); - } >sof_data_ro :sof_data_ro_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_data :sof_data_bss_phdr - - /* stack */ - _end = SOF_STACK_END; - PROVIDE(end = SOF_STACK_END); - _stack_sentry = SOF_STACK_END; - __stack = SOF_STACK_BASE; - - _virtual_thread_ptr = _virtual_thread_start; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .system_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_SIZE; - _system_heap_end = ABSOLUTE(.); - } >system_heap :system_heap_phdr - - .system_runtime_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - } >system_runtime_heap :system_runtime_heap_phdr - - .runtime_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - } >runtime_heap :runtime_heap_phdr - - .buffer_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - } >buffer_heap :buffer_heap_phdr - - .mailbox (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _mailbox_start = ABSOLUTE(.); - . = . + MAILBOX_SIZE; - _mailbox_end = ABSOLUTE(.); - } >mailbox :mailbox_phdr - - .virtual_thread (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _virtual_thread_start = ABSOLUTE(.); - . = . + SOF_VIRTUAL_THREAD_SIZE; - _virtual_thread_end = ABSOLUTE(.); - } >virtual_thread :virtual_thread_phdr - - .sof_stack (NOLOAD) : ALIGN(8) - { - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_TOTAL_SIZE; - _sof_stack_end = ABSOLUTE(.); - } >sof_stack :sof_stack_phdr - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_data :sof_data_phdr -} diff --git a/src/platform/haswell/include/arch/xtensa/config/core-isa-bdw.h b/src/platform/haswell/include/arch/xtensa/config/core-isa-bdw.h deleted file mode 100644 index b7b2fbb6c671..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/core-isa-bdw.h +++ /dev/null @@ -1,616 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Customer ID=8198; Build=0x7550e; Copyright (c) 1999-2018 Tensilica 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. */ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 0 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 0 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 0 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 0 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 1 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2_MUL32X24 1 /* HiFi2 and 32x24 MACs */ -#define XCHAL_HAVE_HIFI2EP 1 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 0 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 0 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 0 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 0 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 0 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "LX4_langwell_audio_17_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x0007550E /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC2B0DBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x15044668 /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX4.0.4" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2400 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 4 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 240004 /* major*100+minor */ -#define XCHAL_HW_REL_LX4 1 -#define XCHAL_HW_REL_LX4_0 1 -#define XCHAL_HW_REL_LX4_0_4 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2400 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 4 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 240004 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2400 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 4 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 240004 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 8 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 8 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 3 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 3 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 0 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 0 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 0 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 0 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 0 -#define XCHAL_DCACHE_SETWIDTH 0 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 1 -#define XCHAL_DCACHE_WAYS 1 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 0 -#define XCHAL_DCACHE_LINE_LOCKABLE 0 -#define XCHAL_ICACHE_ECC_PARITY 0 -#define XCHAL_DCACHE_ECC_PARITY 0 - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 1 -#define XCHAL_DCACHE_ACCESS_SIZE 1 - -#define XCHAL_DCACHE_BANKS 0 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -/* Instruction RAM 0: */ -#define XCHAL_INSTRAM0_VADDR 0x00000000 /* virtual address */ -#define XCHAL_INSTRAM0_PADDR 0x00000000 /* physical address */ -#define XCHAL_INSTRAM0_SIZE 0x50000 /* size in bytes */ -#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ -#define XCHAL_HAVE_INSTRAM0 1 -#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ - -/* Data RAM 0: */ -#define XCHAL_DATARAM0_VADDR 0x00400000 /* virtual address */ -#define XCHAL_DATARAM0_PADDR 0x00400000 /* physical address */ -#define XCHAL_DATARAM0_SIZE 0x50000 /* size in bytes */ -#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ -#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ -#define XCHAL_HAVE_DATARAM0 1 -#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ - -/* Data RAM 1: */ -#define XCHAL_DATARAM1_VADDR 0x00480000 /* virtual address */ -#define XCHAL_DATARAM1_PADDR 0x00480000 /* physical address */ -#define XCHAL_DATARAM1_SIZE 0x50000 /* size in bytes */ -#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ -#define XCHAL_DATARAM1_BANKS 1 /* number of banks */ -#define XCHAL_HAVE_DATARAM1 1 -#define XCHAL_DATARAM1_HAVE_IDMA 0 /* idma supported by this local memory */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 15 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 10 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x000000FF -#define XCHAL_INTLEVEL2_MASK 0x00000100 -#define XCHAL_INTLEVEL3_MASK 0x00000E00 -#define XCHAL_INTLEVEL4_MASK 0x00001000 -#define XCHAL_INTLEVEL5_MASK 0x00002000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00004000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000001FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00001FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x00003FFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x00003FFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x00007FFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 1 -#define XCHAL_INT5_LEVEL 1 -#define XCHAL_INT6_LEVEL 1 -#define XCHAL_INT7_LEVEL 1 -#define XCHAL_INT8_LEVEL 2 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 5 -#define XCHAL_INT14_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFF8000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000880 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F -#define XCHAL_INTTYPE_MASK_TIMER 0x00002440 -#define XCHAL_INTTYPE_MASK_NMI 0x00004000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 10 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 13 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL2_NUM 8 -#define XCHAL_INTLEVEL4_NUM 12 -#define XCHAL_INTLEVEL5_NUM 13 -#define XCHAL_INTLEVEL7_NUM 14 -/* (There are many interrupts each at level(s) 1, 3.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ -#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ -#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ -#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ -#define XCHAL_EXTINT6_NUM 8 /* (intlevel 2) */ -#define XCHAL_EXTINT7_NUM 9 /* (intlevel 3) */ -#define XCHAL_EXTINT8_NUM 12 /* (intlevel 4) */ -#define XCHAL_EXTINT9_NUM 14 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ -#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ -#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ -#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ -#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ -#define XCHAL_INT8_EXTNUM 6 /* (intlevel 2) */ -#define XCHAL_INT9_EXTNUM 7 /* (intlevel 3) */ -#define XCHAL_INT12_EXTNUM 8 /* (intlevel 4) */ -#define XCHAL_INT14_EXTNUM 9 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ - -#define XCHAL_RESET_VECOFS 0x00000000 -#define XCHAL_RESET_VECTOR_VADDR 0x00000000 -#define XCHAL_RESET_VECTOR_PADDR 0x00000000 -#define XCHAL_USER_VECOFS 0x00000000 -#define XCHAL_USER_VECTOR_VADDR 0x000005C0 -#define XCHAL_USER_VECTOR_PADDR 0x000005C0 -#define XCHAL_KERNEL_VECOFS 0x00000000 -#define XCHAL_KERNEL_VECTOR_VADDR 0x00000584 -#define XCHAL_KERNEL_VECTOR_PADDR 0x00000584 -#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x000005FC -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x000005FC -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0x00000400 -#define XCHAL_WINDOW_VECTORS_PADDR 0x00000400 -#define XCHAL_INTLEVEL2_VECOFS 0x00000000 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x00000640 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000640 -#define XCHAL_INTLEVEL3_VECOFS 0x00000000 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x0000067C -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x0000067C -#define XCHAL_INTLEVEL4_VECOFS 0x00000000 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x000006B8 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x000006B8 -#define XCHAL_INTLEVEL5_VECOFS 0x00000000 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x000006F4 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x000006F4 -#define XCHAL_INTLEVEL6_VECOFS 0x00000000 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x00000730 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x00000730 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x00000000 -#define XCHAL_NMI_VECTOR_VADDR 0x0000076C -#define XCHAL_NMI_VECTOR_PADDR 0x0000076C -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 0 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 0 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - diff --git a/src/platform/haswell/include/arch/xtensa/config/core-isa-hsw.h b/src/platform/haswell/include/arch/xtensa/config/core-isa-hsw.h deleted file mode 100644 index e8469b8d64f4..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/core-isa-hsw.h +++ /dev/null @@ -1,616 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Customer ID=4313; Build=0x5483b; Copyright (c) 1999-2015 Tensilica 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. */ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 0 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 0 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 0 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 0 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 1 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2_MUL32X24 1 /* HiFi2 and 32x24 MACs */ -#define XCHAL_HAVE_HIFI2EP 1 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 0 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 0 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 0 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 0 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 0 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "LX4_langwell_audio_17_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x0005483B /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC2B0DBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x15044668 /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX4.0.4" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2400 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 4 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 240004 /* major*100+minor */ -#define XCHAL_HW_REL_LX4 1 -#define XCHAL_HW_REL_LX4_0 1 -#define XCHAL_HW_REL_LX4_0_4 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2400 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 4 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 240004 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2400 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 4 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 240004 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 8 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 8 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 3 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 3 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 0 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 0 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 0 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 0 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 0 -#define XCHAL_DCACHE_SETWIDTH 0 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 1 -#define XCHAL_DCACHE_WAYS 1 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 0 -#define XCHAL_DCACHE_LINE_LOCKABLE 0 -#define XCHAL_ICACHE_ECC_PARITY 0 -#define XCHAL_DCACHE_ECC_PARITY 0 - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 1 -#define XCHAL_DCACHE_ACCESS_SIZE 1 - -#define XCHAL_DCACHE_BANKS 0 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -/* Instruction RAM 0: */ -#define XCHAL_INSTRAM0_VADDR 0x00000000 /* virtual address */ -#define XCHAL_INSTRAM0_PADDR 0x00000000 /* physical address */ -#define XCHAL_INSTRAM0_SIZE 0x50000 /* size in bytes */ -#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ -#define XCHAL_HAVE_INSTRAM0 1 -#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ - -/* Data RAM 0: */ -#define XCHAL_DATARAM0_VADDR 0x00400000 /* virtual address */ -#define XCHAL_DATARAM0_PADDR 0x00400000 /* physical address */ -#define XCHAL_DATARAM0_SIZE 0x50000 /* size in bytes */ -#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ -#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ -#define XCHAL_HAVE_DATARAM0 1 -#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ - -/* Data RAM 1: */ -#define XCHAL_DATARAM1_VADDR 0x00480000 /* virtual address */ -#define XCHAL_DATARAM1_PADDR 0x00480000 /* physical address */ -#define XCHAL_DATARAM1_SIZE 0x30000 /* size in bytes */ -#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ -#define XCHAL_DATARAM1_BANKS 1 /* number of banks */ -#define XCHAL_HAVE_DATARAM1 1 -#define XCHAL_DATARAM1_HAVE_IDMA 0 /* idma supported by this local memory */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 15 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 4 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 10 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x000000FF -#define XCHAL_INTLEVEL2_MASK 0x00000100 -#define XCHAL_INTLEVEL3_MASK 0x00000E00 -#define XCHAL_INTLEVEL4_MASK 0x00001000 -#define XCHAL_INTLEVEL5_MASK 0x00002000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00004000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000001FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00001FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x00003FFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x00003FFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x00007FFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 1 -#define XCHAL_INT5_LEVEL 1 -#define XCHAL_INT6_LEVEL 1 -#define XCHAL_INT7_LEVEL 1 -#define XCHAL_INT8_LEVEL 2 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 5 -#define XCHAL_INT14_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFF8000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000880 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000133F -#define XCHAL_INTTYPE_MASK_TIMER 0x00002440 -#define XCHAL_INTTYPE_MASK_NMI 0x00004000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 10 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 13 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL2_NUM 8 -#define XCHAL_INTLEVEL4_NUM 12 -#define XCHAL_INTLEVEL5_NUM 13 -#define XCHAL_INTLEVEL7_NUM 14 -/* (There are many interrupts each at level(s) 1, 3.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ -#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ -#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ -#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ -#define XCHAL_EXTINT6_NUM 8 /* (intlevel 2) */ -#define XCHAL_EXTINT7_NUM 9 /* (intlevel 3) */ -#define XCHAL_EXTINT8_NUM 12 /* (intlevel 4) */ -#define XCHAL_EXTINT9_NUM 14 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ -#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ -#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ -#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ -#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ -#define XCHAL_INT8_EXTNUM 6 /* (intlevel 2) */ -#define XCHAL_INT9_EXTNUM 7 /* (intlevel 3) */ -#define XCHAL_INT12_EXTNUM 8 /* (intlevel 4) */ -#define XCHAL_INT14_EXTNUM 9 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ - -#define XCHAL_RESET_VECOFS 0x00000000 -#define XCHAL_RESET_VECTOR_VADDR 0x00000000 -#define XCHAL_RESET_VECTOR_PADDR 0x00000000 -#define XCHAL_USER_VECOFS 0x00000000 -#define XCHAL_USER_VECTOR_VADDR 0x000005C0 -#define XCHAL_USER_VECTOR_PADDR 0x000005C0 -#define XCHAL_KERNEL_VECOFS 0x00000000 -#define XCHAL_KERNEL_VECTOR_VADDR 0x00000584 -#define XCHAL_KERNEL_VECTOR_PADDR 0x00000584 -#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x000005FC -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x000005FC -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0x00000400 -#define XCHAL_WINDOW_VECTORS_PADDR 0x00000400 -#define XCHAL_INTLEVEL2_VECOFS 0x00000000 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x00000640 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000640 -#define XCHAL_INTLEVEL3_VECOFS 0x00000000 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x0000067C -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x0000067C -#define XCHAL_INTLEVEL4_VECOFS 0x00000000 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x000006B8 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x000006B8 -#define XCHAL_INTLEVEL5_VECOFS 0x00000000 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x000006F4 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x000006F4 -#define XCHAL_INTLEVEL6_VECOFS 0x00000000 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x00000730 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x00000730 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x00000000 -#define XCHAL_NMI_VECTOR_VADDR 0x0000076C -#define XCHAL_NMI_VECTOR_PADDR 0x0000076C -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 0 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 0 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - diff --git a/src/platform/haswell/include/arch/xtensa/config/core-isa.h b/src/platform/haswell/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index 9490f1a404c9..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,9 +0,0 @@ -#include <config.h> - -#if CONFIG_HASWELL -#include <xtensa/config/core-isa-hsw.h> -#elif CONFIG_BROADWELL -#include <xtensa/config/core-isa-bdw.h> -#else -#error "No ISA configuration selected" -#endif diff --git a/src/platform/haswell/include/arch/xtensa/config/core-matmap.h b/src/platform/haswell/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index 5c6fffeb7ddf..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Customer ID=4313; Build=0x5483b; Copyright (c) 1999-2015 Tensilica 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. */ - - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefined hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ - diff --git a/src/platform/haswell/include/arch/xtensa/config/defs.h b/src/platform/haswell/include/arch/xtensa/config/defs.h deleted file mode 100644 index b695e595135c..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Customer ID=4313; Build=0x5483b; Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/haswell/include/arch/xtensa/config/specreg.h b/src/platform/haswell/include/arch/xtensa/config/specreg.h deleted file mode 100644 index 89bfe163eeb0..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Eaglenest/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ - -/* Customer ID=4313; Build=0x5483b; Copyright (c) 1998-2002 Tensilica 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. */ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define ATOMCTL 99 -#define DDR 104 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 -#define MISC_REG_0 244 -#define MISC_REG_1 245 - -/* Special cases (bases of special register series): */ -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -/* Special names for read-only and write-only interrupt registers: */ -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 - -#endif /* XTENSA_SPECREG_H */ - diff --git a/src/platform/haswell/include/arch/xtensa/config/system.h b/src/platform/haswell/include/arch/xtensa/config/system.h deleted file mode 100644 index 147346a0c691..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Customer ID=4313; Build=0x5483b; Copyright (c) 2000-2010 Tensilica 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. */ - - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_CALL0 /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -#define XSHAL_FLOATING_POINT_ABI 0 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -#define XSHAL_ROM_VADDR 0x50000000 -#define XSHAL_ROM_PADDR 0x50000000 -#define XSHAL_ROM_SIZE 0x01000000 -/* Largest available area (free of vectors): */ -#define XSHAL_ROM_AVAIL_VADDR 0x50000300 -#define XSHAL_ROM_AVAIL_VSIZE 0x00FFFD00 - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x60000000 -#define XSHAL_RAM_PADDR 0x60000000 -#define XSHAL_RAM_VSIZE 0x04000000 -#define XSHAL_RAM_PSIZE 0x04000000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x60000400 -#define XSHAL_RAM_AVAIL_VSIZE 0x03FFFC00 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0xA0000000 -#define XSHAL_RAM_BYPASS_PADDR 0xA0000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x04000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit and diagnostic routines. - */ -#define XSHAL_MAGIC_EXIT 0x0 - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22224442 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22221112 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22221112 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFFFF444F /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFFFF111F /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFFFF111F /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFFFF222F /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2222444F /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2222111F /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2222111F /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF22444F /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF22111F /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF22111F /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000440 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0x50000000 -#define XSHAL_RESET_VECTOR_PADDR 0x50000000 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x00000300 -#define XSHAL_RESET_VECTOR_ISROM 1 -#define XSHAL_USER_VECTOR_SIZE 0x00000038 -#define XSHAL_USER_VECTOR_ISROM 0 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 -#define XSHAL_KERNEL_VECTOR_ISROM 0 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 0 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL6_VECTOR_ISROM 0 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x00000038 -#define XSHAL_NMI_VECTOR_ISROM 0 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ - diff --git a/src/platform/haswell/include/arch/xtensa/config/tie-asm.h b/src/platform/haswell/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index d7140f87b71b..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Copyright (c) 1999-2015 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. */ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - /* - * Macro to store all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_store - - /* - * Macro to load all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - /* - * Macro to store the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - ae_sp24x2s.i aep0, \ptr, .Lxchal_ofs_+16 - ae_sp24x2s.i aep1, \ptr, .Lxchal_ofs_+24 - ae_sp24x2s.i aep2, \ptr, .Lxchal_ofs_+32 - ae_sp24x2s.i aep3, \ptr, .Lxchal_ofs_+40 - ae_sp24x2s.i aep4, \ptr, .Lxchal_ofs_+48 - ae_sp24x2s.i aep5, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_sp24x2s.i aep6, \ptr, .Lxchal_ofs_+0 - ae_sp24x2s.i aep7, \ptr, .Lxchal_ofs_+8 - ae_sq56s.i aeq0, \ptr, .Lxchal_ofs_+16 - ae_sq56s.i aeq1, \ptr, .Lxchal_ofs_+24 - ae_sq56s.i aeq2, \ptr, .Lxchal_ofs_+32 - ae_sq56s.i aeq3, \ptr, .Lxchal_ofs_+40 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 64 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 48 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 112 - .endif - .endm // xchal_cp1_store - - /* - * Macro to load the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_SD_NO \at1 // ureg 243 - ae_lp24x2.i aep0, \ptr, .Lxchal_ofs_+16 - ae_lp24x2.i aep1, \ptr, .Lxchal_ofs_+24 - ae_lp24x2.i aep2, \ptr, .Lxchal_ofs_+32 - ae_lp24x2.i aep3, \ptr, .Lxchal_ofs_+40 - ae_lp24x2.i aep4, \ptr, .Lxchal_ofs_+48 - ae_lp24x2.i aep5, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_lp24x2.i aep6, \ptr, .Lxchal_ofs_+0 - ae_lp24x2.i aep7, \ptr, .Lxchal_ofs_+8 - addi \ptr, \ptr, 16 - ae_lq56.i aeq0, \ptr, .Lxchal_ofs_+0 - ae_lq56.i aeq1, \ptr, .Lxchal_ofs_+8 - ae_lq56.i aeq2, \ptr, .Lxchal_ofs_+16 - ae_lq56.i aeq3, \ptr, .Lxchal_ofs_+24 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 80 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 112 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - diff --git a/src/platform/haswell/include/arch/xtensa/config/tie.h b/src/platform/haswell/include/arch/xtensa/config/tie.h deleted file mode 100644 index 3c638122930a..000000000000 --- a/src/platform/haswell/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Copyright (c) 1999-2015 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. */ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 1 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 112 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP0_SA_SIZE 0 -#define XCHAL_CP0_SA_ALIGN 1 -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 8 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 128 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 2 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 0 -#define XCHAL_CP0_SA_LIST(s) /* empty */ - -#define XCHAL_CP1_SA_NUM 16 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 7,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_sd_no, 4, 4, 4,0x03F3, ur,243, 28,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep0, 8, 8, 8,0x0060, aep,0 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep1, 8, 8, 8,0x0061, aep,1 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep2, 8, 8, 8,0x0062, aep,2 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep3, 8, 8, 8,0x0063, aep,3 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep4, 8, 8, 8,0x0064, aep,4 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep5, 8, 8, 8,0x0065, aep,5 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep6, 8, 8, 8,0x0066, aep,6 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aep7, 8, 8, 8,0x0067, aep,7 , 48,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq0, 8, 8, 8,0x0068, aeq,0 , 56,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq1, 8, 8, 8,0x0069, aeq,1 , 56,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq2, 8, 8, 8,0x006A, aeq,2 , 56,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aeq3, 8, 8, 8,0x006B, aeq,3 , 56,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8 -/* Byte length of instruction from its first byte, per FLIX. */ -#define XCHAL_BYTE0_FORMAT_LENGTHS \ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8 - -#endif /*_XTENSA_CORE_TIE_H*/ - diff --git a/src/platform/haswell/include/platform/drivers/dw-dma.h b/src/platform/haswell/include/platform/drivers/dw-dma.h deleted file mode 100644 index c42ce8ecc645..000000000000 --- a/src/platform/haswell/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <sof/bit.h> -#include <stdint.h> - -struct dma; -struct dma_chan_data; - -/* number of supported DW-DMACs (DMAC0 is not related with SSP)*/ -#define PLATFORM_NUM_DW_DMACS 1 - -/* index of the first DW-DMAC in the array (DMAC0 is not related with SSP)*/ -#define PLATFORM_DW_DMA_INDEX 1 - -/* DMA treats PHY addresses as host address unless within DSP region */ -#define PLATFORM_DW_DMA_HOST_MASK 0xFFF00000 - -/* CTL_HI */ -#define DW_CTLH_DONE(x) SET_BIT(12, x) -#define DW_CTLH_BLOCK_TS_MASK MASK(11, 0) - -/* CFG_LO */ -#define DW_CFGL_CLASS(x) SET_BITS(7, 5, x) - -/* CFG_HI */ -#define DW_CFGH_DST_PER(x) SET_BITS(14, 11, x) -#define DW_CFGH_SRC_PER(x) SET_BITS(10, 7, x) -#define DW_CFGH_DST(x) DW_CFGH_DST_PER(x) -#define DW_CFGH_SRC(x) DW_CFGH_SRC_PER(x) - -/* default initial setup register values */ -#define DW_CFG_LOW_DEF 0x0 -#define DW_CFG_HIGH_DEF 0x4 - -#define platform_dw_dma_set_class(chan, lli, class) \ - (chan->cfg_lo |= DW_CFGL_CLASS(class)) - -#define platform_dw_dma_set_transfer_size(chan, lli, size) \ - (lli->ctrl_hi |= ((size / (1 << ((lli->ctrl_lo & \ - DW_CTLL_SRC_WIDTH_MASK) >> DW_CTLL_SRC_WIDTH_SHIFT))) & \ - DW_CTLH_BLOCK_TS_MASK)) - -static inline void platform_dw_dma_llp_config(struct dma *dma, - struct dma_chan_data *chan, - uint32_t config) { } - -static inline void platform_dw_dma_llp_enable(struct dma *dma, - struct dma_chan_data *chan) { } - -static inline void platform_dw_dma_llp_disable(struct dma *dma, - struct dma_chan_data *chan) { } - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __SOF_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/haswell/include/platform/drivers/idc.h b/src/platform/haswell/include/platform/drivers/idc.h deleted file mode 100644 index 70a264d2dbc5..000000000000 --- a/src/platform/haswell/include/platform/drivers/idc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <stdint.h> - -struct idc_msg; - -static inline int idc_send_msg(struct idc_msg *msg, - uint32_t mode) { return 0; } - -static inline int idc_init(void) { return 0; } - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/haswell/include/platform/drivers/interrupt.h b/src/platform/haswell/include/platform/drivers/interrupt.h deleted file mode 100644 index 46f9a20d4837..000000000000 --- a/src/platform/haswell/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <sof/bit.h> -#include <config.h> - -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 0 - -/* IRQ numbers */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_EXT_SSP0 0 /* Level 1 */ -#define IRQ_NUM_EXT_SSP1 1 /* Level 1 */ -#define IRQ_NUM_EXT_OBFF 2 /* Level 1 */ -#define IRQ_NUM_EXT_IA 4 /* Level 1 */ -#define IRQ_NUM_TIMER1 6 /* Level 1 */ -#define IRQ_NUM_SOFTWARE1 7 /* Level 1 */ - -#define IRQ_MASK_EXT_SSP0 BIT(IRQ_NUM_EXT_SSP0) -#define IRQ_MASK_EXT_SSP1 BIT(IRQ_NUM_EXT_SSP1) -#define IRQ_MASK_EXT_OBFF BIT(IRQ_NUM_EXT_OBFF) -#define IRQ_MASK_EXT_IA BIT(IRQ_NUM_EXT_IA) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_EXT_DMAC0 8 /* Level 2 */ - -#define IRQ_MASK_EXT_DMAC0 BIT(IRQ_NUM_EXT_DMAC0) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_EXT_DMAC1 9 /* Level 3 */ -#define IRQ_NUM_TIMER2 10 /* Level 3 */ -#define IRQ_NUM_SOFTWARE2 11 /* Level 3 */ - -#define IRQ_MASK_EXT_DMAC1 BIT(IRQ_NUM_EXT_DMAC1) -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_EXT_PARITY 12 /* Level 4 */ - -#define IRQ_MASK_EXT_PARITY BIT(IRQ_NUM_EXT_PARITY) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_TIMER3 13 /* Level 5 */ - -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) - -#endif - -#define IRQ_NUM_NMI 14 /* Level 7 */ - -#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/haswell/include/platform/lib/clk.h b/src/platform/haswell/include/platform/lib/clk.h deleted file mode 100644 index beb12c7d0415..000000000000 --- a/src/platform/haswell/include/platform/lib/clk.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <sof/lib/io.h> -#include <sof/lib/shim.h> -#include <stdint.h> - -struct sof; - -#define CLK_CPU(x) (x) -#define CLK_SSP 1 - -#define CPU_DEFAULT_IDX 3 -#define SSP_DEFAULT_IDX 0 - -#define CLK_DEFAULT_CPU_HZ 320000000 -#define CLK_MAX_CPU_HZ 320000000 - -#define NUM_CLOCKS 2 - -#define NUM_CPU_FREQ 6 -#define NUM_SSP_FREQ 1 - -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/haswell/include/platform/lib/cpu.h b/src/platform/haswell/include/platform/lib/cpu.h deleted file mode 100644 index a03e856ed8cc..000000000000 --- a/src/platform/haswell/include/platform/lib/cpu.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <config.h> - -/** \brief Number of available DSP cores (conf. by kconfig) */ -#define PLATFORM_CORE_COUNT CONFIG_CORE_COUNT - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 1 - -/** \brief Id of master DSP core */ -#define PLATFORM_MASTER_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/haswell/include/platform/lib/dai.h b/src/platform/haswell/include/platform/lib/dai.h deleted file mode 100644 index 0cfdf919d1bb..000000000000 --- a/src/platform/haswell/include/platform/lib/dai.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -#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/haswell/include/platform/lib/dma.h b/src/platform/haswell/include/platform/lib/dma.h deleted file mode 100644 index 434c397d573e..000000000000 --- a/src/platform/haswell/include/platform/lib/dma.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -#define PLATFORM_NUM_DMACS 2 - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 8 - -#define DMA_ID_DMAC0 0 -#define DMA_ID_DMAC1 1 - -#define DMA_HANDSHAKE_SSP1_RX 0 -#define DMA_HANDSHAKE_SSP1_TX 1 -#define DMA_HANDSHAKE_SSP0_RX 2 -#define DMA_HANDSHAKE_SSP0_TX 3 -#define DMA_HANDSHAKE_OBFF_0 4 -#define DMA_HANDSHAKE_OBFF_1 5 -#define DMA_HANDSHAKE_OBFF_2 6 -#define DMA_HANDSHAKE_OBFF_3 7 -#define DMA_HANDSHAKE_OBFF_4 8 -#define DMA_HANDSHAKE_OBFF_5 9 -#define DMA_HANDSHAKE_OBFF_6 10 -#define DMA_HANDSHAKE_OBFF_7 11 -#define DMA_HANDSHAKE_OBFF_8 12 -#define DMA_HANDSHAKE_OBFF_9 13 -#define DMA_HANDSHAKE_OBFF_10 14 -#define DMA_HANDSHAKE_OBFF_11 15 - -#define dma_chan_irq(dma, chan) dma_irq(dma) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/haswell/include/platform/lib/mailbox.h b/src/platform/haswell/include/platform/lib/mailbox.h deleted file mode 100644 index 848019926193..000000000000 --- a/src/platform/haswell/include/platform/lib/mailbox.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_MAILBOX_H__ - -#ifndef __PLATFORM_LIB_MAILBOX_H__ -#define __PLATFORM_LIB_MAILBOX_H__ - -#include <sof/lib/memory.h> -#include <config.h> -#include <stddef.h> -#include <stdint.h> - -#if CONFIG_BROADWELL -#define MAILBOX_HOST_OFFSET 0x0009E000 -#else -#define MAILBOX_HOST_OFFSET 0x0007E000 -#endif - -#define MAILBOX_DSPBOX_OFFSET 0x0 -#define MAILBOX_DSPBOX_SIZE 0x400 -#define MAILBOX_DSPBOX_BASE \ - (MAILBOX_BASE + MAILBOX_DSPBOX_OFFSET) - -#define MAILBOX_HOSTBOX_OFFSET MAILBOX_DSPBOX_SIZE -#define MAILBOX_HOSTBOX_SIZE 0x400 -#define MAILBOX_HOSTBOX_BASE \ - (MAILBOX_BASE + MAILBOX_HOSTBOX_OFFSET) - -#define MAILBOX_EXCEPTION_OFFSET \ - (MAILBOX_HOSTBOX_SIZE + MAILBOX_DSPBOX_SIZE) -#define MAILBOX_EXCEPTION_SIZE 0x100 -#define MAILBOX_EXCEPTION_BASE \ - (MAILBOX_BASE + MAILBOX_EXCEPTION_OFFSET) - -#define MAILBOX_DEBUG_OFFSET \ - (MAILBOX_EXCEPTION_SIZE + MAILBOX_EXCEPTION_OFFSET) -#define MAILBOX_DEBUG_SIZE 0x100 -#define MAILBOX_DEBUG_BASE \ - (MAILBOX_BASE + MAILBOX_DEBUG_OFFSET) - -#define MAILBOX_STREAM_OFFSET \ - (MAILBOX_DEBUG_SIZE + MAILBOX_DEBUG_OFFSET) -#define MAILBOX_STREAM_SIZE 0x200 -#define MAILBOX_STREAM_BASE \ - (MAILBOX_BASE + MAILBOX_STREAM_OFFSET) - -#define MAILBOX_TRACE_OFFSET \ - (MAILBOX_STREAM_SIZE + MAILBOX_STREAM_OFFSET) - -#if CONFIG_TRACE -#define MAILBOX_TRACE_SIZE 0x380 -#else -#define MAILBOX_TRACE_SIZE 0x0 -#endif - -#define MAILBOX_TRACE_BASE \ - (MAILBOX_BASE + MAILBOX_TRACE_OFFSET) - -static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) -{ - volatile uint32_t *ptr; - - ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); - *ptr = src; -} - -#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/haswell/include/platform/lib/memory.h b/src/platform/haswell/include/platform/lib/memory.h deleted file mode 100644 index ec8a02d708e2..000000000000 --- a/src/platform/haswell/include/platform/lib/memory.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_MEMORY_H__ - -#ifndef __PLATFORM_LIB_MEMORY_H__ -#define __PLATFORM_LIB_MEMORY_H__ - -#include <config.h> - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -struct sof; - -/** - * \brief Data shared between different cores. - * Does nothing, since HSW doesn't support SMP. - */ -#define SHARED_DATA - -void platform_init_memmap(struct sof *sof); - -static inline void *platform_shared_get(void *ptr, int bytes) -{ - return ptr; -} - -/** - * \brief Function for keeping shared data synchronized. - * It's used after usage of data shared by different cores. - * Such data is either statically marked with SHARED_DATA - * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. - * Does nothing, since HSW doesn't support SMP. - */ -static inline void platform_shared_commit(void *ptr, int bytes) { } - -static inline void *platform_rfree_prepare(void *ptr) -{ - return ptr; -} - -#endif - -/* data cache line alignment */ -#define PLATFORM_DCACHE_ALIGN sizeof(void *) - -/** \brief EDF task's default stack size in bytes. */ -#define PLATFORM_TASK_DEFAULT_STACK_SIZE 2048 - -/* physical DSP addresses */ - -#define SHIM_SIZE 0x00001000 - -#define IRAM_BASE 0x00000000 -#define IRAM_SIZE 0x00050000 - -#define DRAM0_BASE 0x00400000 -#define DRAM0_VBASE 0x00400000 - -#define MAILBOX_SIZE (0x00001000 - SOF_VIRTUAL_THREAD_SIZE) -#define DMA0_SIZE 0x00001000 -#define DMA1_SIZE 0x00001000 -#define SSP0_SIZE 0x00001000 -#define SSP1_SIZE 0x00001000 - -#if CONFIG_BROADWELL -#define DRAM0_SIZE 0x000A0000 -#define SHIM_BASE 0xFFFFB000 -#define DMA0_BASE 0xFFFFE000 -#define DMA1_BASE 0xFFFFF000 -#define SSP0_BASE 0xFFFFC000 -#define SSP1_BASE 0xFFFFD000 - -#else /* HASWELL */ -#define DRAM0_SIZE 0x00080000 -#define SHIM_BASE 0xFFFE7000 -#define DMA0_BASE 0xFFFF0000 -#define DMA1_BASE 0xFFFF8000 -#define SSP0_BASE 0xFFFE8000 -#define SSP1_BASE 0xFFFE9000 - -#endif - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -/* - * The Heap and Stack on Haswell/Broadwell are organised like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | DRAM0_BASE | RO Data | SOF_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | MAILBOX_BASE | Mailbox | MAILBOX_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | VIRTUAL_THREAD_BASE | Vthread Ptr | SOF_VIRTUAL_THREAD_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_END | Stack | SOF_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT8 0 -#define HEAP_RT_COUNT16 192 -#define HEAP_RT_COUNT32 128 -#define HEAP_RT_COUNT64 64 -#define HEAP_RT_COUNT128 64 -#define HEAP_RT_COUNT256 64 -#define HEAP_RT_COUNT512 8 -#define HEAP_RT_COUNT1024 4 - -/* Heap section sizes for system runtime heap */ -#define HEAP_SYS_RT_COUNT64 64 -#define HEAP_SYS_RT_COUNT512 8 -#define HEAP_SYS_RT_COUNT1024 4 - -/* Heap configuration */ -#define SOF_DATA_SIZE 0xD000 - -#define HEAP_SYSTEM_BASE (DRAM0_BASE + SOF_DATA_SIZE) -#define HEAP_SYSTEM_SIZE 0x4000 - -#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE - -#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) -#define HEAP_SYS_RUNTIME_SIZE \ - (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ - HEAP_SYS_RT_COUNT1024 * 1024) - -#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ - HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ - HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ - HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024) - -#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) -#define HEAP_BUFFER_SIZE \ - (DRAM0_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE -\ - HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE - SOF_DATA_SIZE -\ - SOF_VIRTUAL_THREAD_SIZE - MAILBOX_SIZE) - -#define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT \ - (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) - -#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ -#define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 1 - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE -#define SOF_STACK_BASE (DRAM0_BASE + DRAM0_SIZE) -#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) - -/* Virtual threadptr */ -#define SOF_VIRTUAL_THREAD_SIZE 0x20 -#define SOF_VIRTUAL_THREAD_BASE (SOF_STACK_END - SOF_VIRTUAL_THREAD_SIZE) - -#define MAILBOX_BASE (SOF_VIRTUAL_THREAD_BASE - MAILBOX_SIZE) - -/* Vector and literal sizes - not in core-isa.h */ -#define SOF_MEM_VECT_LIT_SIZE 0x4 -#define SOF_MEM_VECT_TEXT_SIZE 0x1c -#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ - SOF_MEM_VECT_LIT_SIZE) - -#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 -#define SOF_MEM_RESET_LIT_SIZE 0x120 -#define SOF_MEM_VECBASE_TEXT_BASE 0x400 -#define SOF_MEM_VECBASE_LIT_SIZE 0x178 - -#define SOF_MEM_RO_SIZE 0x8 - -#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/haswell/include/platform/lib/pm_runtime.h b/src/platform/haswell/include/platform/lib/pm_runtime.h deleted file mode 100644 index 7ab3b8458613..000000000000 --- a/src/platform/haswell/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/haswell/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Haswell - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <stdint.h> - -struct pm_runtime_data; - -/** - * \brief Initializes platform specific runtime power management. - * \param[in,out] prd Runtime power management data. - */ -static inline 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_... - */ -static inline 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_... - */ -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/haswell/include/platform/lib/shim.h b/src/platform/haswell/include/platform/lib/shim.h deleted file mode 100644 index 954b86ed5f5c..000000000000 --- a/src/platform/haswell/include/platform/lib/shim.h +++ /dev/null @@ -1,123 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <stdint.h> - -#define SHIM_CSR 0x00 -#define SHIM_ISRX 0x18 -#define SHIM_ISRD 0x20 -#define SHIM_IMRX 0x28 -#define SHIM_IMRD 0x30 -#define SHIM_IPCX 0x38 /* IPC IA -> SST */ -#define SHIM_IPCD 0x40 /* IPC SST -> IA */ - -#define SHIM_CLKCTL 0x78 - -#define SHIM_CSR2 0x80 -#define SHIM_LTRC 0xE0 -#define SHIM_HMDC 0xE8 - -#define SHIM_SHIM_BEGIN SHIM_CSR -#define SHIM_SHIM_END SHIM_HMDC - -/* CSR 0x0 */ -#define SHIM_CSR_RST (0x1 << 1) -#define SHIM_CSR_STALL (0x1 << 10) -#define SHIM_CSR_SDPM0 (0x1 << 11) -#define SHIM_CSR_SDPM1 (0x1 << 12) -#define SHIM_CSR_PCE (0x1 << 15) -#define SHIM_CSR_SFCR0 (0x1 << 27) -#define SHIM_CSR_SFCR1 (0x1 << 28) -#define SHIM_CSR_DCS(x) (x << 4) -#define SHIM_CSR_DCS_MASK (0x7 << 4) -#define SHIM_CSR_SFCR_SSP(x) (1 << (27 + x)) - -/* ISRX 0x18 */ -#define SHIM_ISRX_BUSY (0x1 << 1) -#define SHIM_ISRX_DONE (0x1 << 0) - -/* ISRD / ISD */ -#define SHIM_ISRD_BUSY (0x1 << 1) -#define SHIM_ISRD_DONE (0x1 << 0) - -/* IMRX / IMC */ -#define SHIM_IMRX_BUSY (0x1 << 1) -#define SHIM_IMRX_DONE (0x1 << 0) - -/* IMRD / IMD */ -#define SHIM_IMRD_DONE (0x1 << 0) -#define SHIM_IMRD_BUSY (0x1 << 1) -#define SHIM_IMRD_SSP0 (0x1 << 16) -#define SHIM_IMRD_SSP1 (0x1 << 17) -#define SHIM_IMRD_DMAC0 (0x1 << 21) -#define SHIM_IMRD_DMAC1 (0x1 << 22) -#define SHIM_IMRD_DMAC (SHIM_IMRD_DMAC0 | SHIM_IMRD_DMAC1) - -/* IPCX / IPCCH */ -#define SHIM_IPCX_DONE (0x1 << 30) -#define SHIM_IPCX_BUSY (0x1 << 31) - -/* IPCDH */ -#define SHIM_IPCD_DONE (0x1 << 30) -#define SHIM_IPCD_BUSY (0x1 << 31) - -/* CLKCTL */ -#define SHIM_CLKCTL_SMOS(x) (x << 24) -#define SHIM_CLKCTL_MASK (3 << 24) -#define SHIM_CLKCTL_DCPLCG (1 << 18) -#define SHIM_CLKCTL_EN_SSP(x) (1 << (16 + x)) - -/* CSR2 / CS2 */ -#define SHIM_CSR2_SDFD_SSP0 (1 << 1) -#define SHIM_CSR2_SDFD_SSP1 (1 << 2) - -/* LTRC */ -#define SHIM_LTRC_VAL(x) (x << 0) - -/* HMDC */ -#define SHIM_HMDC_HDDA0(x) (x << 0) -#define SHIM_HMDC_HDDA1(x) (x << 8) -#define SHIM_HMDC_HDDA_CH_MASK 0xFF -#define SHIM_HMDC_HDDA_E0_ALLCH SHIM_HMDC_HDDA0(SHIM_HMDC_HDDA_CH_MASK) -#define SHIM_HMDC_HDDA_E1_ALLCH SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_CH_MASK) -#define SHIM_HMDC_HDDA_ALLCH (SHIM_HMDC_HDDA_E0_ALLCH | \ - SHIM_HMDC_HDDA_E1_ALLCH) - -/* PMCS */ -#define PCI_PMCS 0x84 -#define PCI_PMCS_PS_MASK 0x3 - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -static inline void shim_update_bits(uint32_t reg, uint32_t mask, - uint32_t value) -{ - io_reg_update_bits(SHIM_BASE + reg, mask, value); -} - -#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/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h deleted file mode 100644 index dd10aa93e6c2..000000000000 --- a/src/platform/haswell/include/platform/platform.h +++ /dev/null @@ -1,103 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - */ - -#ifdef __SOF_PLATFORM_H__ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_LPSRAM_EBB_COUNT 1 - -#define LPSRAM_BANK_SIZE (64 * 1024) - -#define LPSRAM_SIZE (PLATFORM_LPSRAM_EBB_COUNT * LPSRAM_BANK_SIZE) - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <arch/lib/wait.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/shim.h> -#include <stddef.h> -#include <stdint.h> - -struct ll_schedule_domain; -struct timer; - -/*! \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_CPU(0) - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_EXT_IA -#define PLATFORM_IPC_INTERRUPT_NAME NULL - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL - -/* Platform stream capabilities */ -#define PLATFORM_MAX_CHANNELS 4 -#define PLATFORM_MAX_STREAMS 5 - -/* local buffer size of DMA tracing */ -#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE - -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 100 - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* Platform defined panic code */ -static inline void platform_panic(uint32_t p) -{ - shim_write(SHIM_IPCX, MAILBOX_EXCEPTION_OFFSET & 0x3fffffff); - shim_write(SHIM_IPCD, (SHIM_IPCD_BUSY | p)); -} - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -static inline void platform_wait_for_interrupt(int level) -{ - if (arch_interrupt_get_level()) - panic(SOF_IPC_PANIC_WFI); - - arch_wait_for_interrupt(level); -} - -extern intptr_t _module_init_start; -extern intptr_t _module_init_end; - -#endif -#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/haswell/include/platform/trace/trace.h b/src/platform/haswell/include/platform/trace/trace.h deleted file mode 100644 index 306e4fd5f40f..000000000000 --- a/src/platform/haswell/include/platform/trace/trace.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_TRACE_TRACE_H__ - -#ifndef __PLATFORM_TRACE_TRACE_H__ -#define __PLATFORM_TRACE_TRACE_H__ - -#include <sof/lib/shim.h> - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - shim_write(SHIM_IPCX, ((__x) & 0x3fffffff)) - -#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/haswell/lib/clk.c b/src/platform/haswell/lib/clk.c deleted file mode 100644 index bd2867fcd97e..000000000000 --- a/src/platform/haswell/lib/clk.c +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/sof.h> -#include <sof/spinlock.h> - -const struct freq_table platform_cpu_freq[] = { - { 32000000, 32000 }, - { 80000000, 80000 }, - { 160000000, 160000 }, - { 320000000, 320000 }, - { 320000000, 320000 }, - { 160000000, 160000 }, -}; - -const uint32_t cpu_freq_enc[] = { - 0x6, - 0x2, - 0x1, - 0x4, - 0x0, - 0x5, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table platform_ssp_freq[] = { - { 24000000, 24000 }, -}; - -const uint32_t platform_ssp_freq_sources[] = { - 0, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; - -static int clock_platform_set_cpu_freq(int clock, int freq_idx) -{ - uint32_t enc = cpu_freq_enc[freq_idx]; - - /* set CPU frequency request for CCU */ - io_reg_update_bits(SHIM_BASE + SHIM_CSR, SHIM_CSR_DCS_MASK, - enc); - - return 0; -} - -static SHARED_DATA struct clock_info platform_clocks_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(0), - .set_freq = clock_platform_set_cpu_freq, - }, - { - .freqs_num = NUM_SSP_FREQ, - .freqs = platform_ssp_freq, - .default_freq_idx = SSP_DEFAULT_IDX, - .current_freq_idx = SSP_DEFAULT_IDX, - .notification_id = NOTIFIER_ID_SSP_FREQ, - .notification_mask = NOTIFIER_TARGET_CORE_ALL_MASK, - .set_freq = NULL, - } -}; - -STATIC_ASSERT(ARRAY_SIZE(platform_clocks_info) == NUM_CLOCKS, - invalid_number_of_clocks); - -void platform_clock_init(struct sof *sof) -{ - int i; - - sof->clocks = platform_clocks_info; - - for (i = 0; i < NUM_CLOCKS; i++) - spinlock_init(&sof->clocks[i].lock); - - platform_shared_commit(sof->clocks, sizeof(*sof->clocks) * NUM_CLOCKS); -} diff --git a/src/platform/haswell/lib/dai.c b/src/platform/haswell/lib/dai.c deleted file mode 100644 index d13c21ce36c8..000000000000 --- a/src/platform/haswell/lib/dai.c +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <ipc/dai.h> -#include <ipc/stream.h> - -static SHARED_DATA struct dai ssp[2] = { -{ - .index = 0, - .plat_data = { - .base = SSP0_BASE, - .irq = IRQ_NUM_EXT_SSP0, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP0_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP0_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP0_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP0_RX, - } - }, - .drv = &ssp_driver, -}, -{ - .index = 1, - .plat_data = { - .base = SSP1_BASE, - .irq = IRQ_NUM_EXT_SSP1, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = SSP1_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP1_TX, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = SSP1_BASE + SSDR, - .handshake = DMA_HANDSHAKE_SSP1_RX, - } - }, - .drv = &ssp_driver, -}, -}; - -const struct dai_type_info dti[] = { - { - .type = SOF_DAI_INTEL_SSP, - .dai_array = ssp, - .num_dais = ARRAY_SIZE(ssp) - } -}; - -const struct dai_info lib_dai = { - .dai_type_array = dti, - .num_dai_types = ARRAY_SIZE(dti) -}; - -int dai_init(struct sof *sof) -{ - int i; - - /* initialize spin locks early to enable ref counting */ - for (i = 0; i < ARRAY_SIZE(ssp); i++) - spinlock_init(&ssp[i].lock); - - platform_shared_commit(ssp, sizeof(*ssp)); - - sof->dai_info = &lib_dai; - - return 0; -} diff --git a/src/platform/haswell/lib/dma.c b/src/platform/haswell/lib/dma.c deleted file mode 100644 index 30d26ea25096..000000000000 --- a/src/platform/haswell/lib/dma.c +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/dw-dma.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/dma.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <sof/sof.h> -#include <sof/spinlock.h> - -const struct dw_drv_plat_data dmac0 = { - .chan[0] = { - .class = 6, - .weight = 0, - }, - .chan[1] = { - .class = 6, - .weight = 0, - }, - .chan[2] = { - .class = 6, - .weight = 0, - }, - .chan[3] = { - .class = 6, - .weight = 0, - }, - .chan[4] = { - .class = 6, - .weight = 0, - }, - .chan[5] = { - .class = 6, - .weight = 0, - }, - .chan[6] = { - .class = 6, - .weight = 0, - }, - .chan[7] = { - .class = 6, - .weight = 0, - }, -}; - -const struct dw_drv_plat_data dmac1 = { - .chan[0] = { - .class = 7, - .weight = 0, - }, - .chan[1] = { - .class = 7, - .weight = 0, - }, - .chan[2] = { - .class = 7, - .weight = 0, - }, - .chan[3] = { - .class = 7, - .weight = 0, - }, - .chan[4] = { - .class = 7, - .weight = 0, - }, - .chan[5] = { - .class = 7, - .weight = 0, - }, - .chan[6] = { - .class = 7, - .weight = 0, - }, - .chan[7] = { - .class = 7, - .weight = 0, - }, -}; - -SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { -{ - .plat_data = { - .id = DMA_ID_DMAC0, - .base = DMA0_BASE, - .dir = DMA_DIR_MEM_TO_MEM, - .caps = DMA_CAP_GP_HP | DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HOST, - .irq = IRQ_NUM_EXT_DMAC0, - .drv_plat_data = &dmac0, - .channels = 8, - }, - .ops = &dw_dma_ops, -}, -{ - .plat_data = { - .id = DMA_ID_DMAC1, - .base = DMA1_BASE, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV | - DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, - .caps = DMA_CAP_GP_HP | DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | DMA_DEV_HOST, - .irq = IRQ_NUM_EXT_DMAC1, - .drv_plat_data = &dmac1, - .channels = 8, - }, - .ops = &dw_dma_ops, -},}; - -const struct dma_info lib_dma = { - .dma_array = dma, - .num_dmas = ARRAY_SIZE(dma) -}; - -/* Initialize all platform DMAC's */ -int dmac_init(struct sof *sof) -{ - int i; - /* no probing before first use */ - - /* TODO: dynamic init based on platform settings */ - - /* early lock initialization for ref counting */ - for (i = 0; i < ARRAY_SIZE(dma); i++) - spinlock_init(&dma[i].lock); - - platform_shared_commit(dma, sizeof(*dma)); - - /* clear the masks for dsp of the dmacs */ - io_reg_update_bits(SHIM_BASE + SHIM_IMRD, - SHIM_IMRD_DMAC0, 0); - - io_reg_update_bits(SHIM_BASE + SHIM_IMRD, - SHIM_IMRD_DMAC1, 0); - - sof->dma_info = &lib_dma; - - return 0; -} diff --git a/src/platform/haswell/lib/memory.c b/src/platform/haswell/lib/memory.c deleted file mode 100644 index 7e82e1ac4f87..000000000000 --- a/src/platform/haswell/lib/memory.c +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/common.h> -#include <sof/lib/alloc.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <ipc/topology.h> - -/* Heap blocks for system runtime */ -static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; -static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; -static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; - -/* Heap memory for system runtime */ -static SHARED_DATA struct block_map sys_rt_heap_map[] = { - BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), - BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), - BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), -}; - -/* Heap blocks for modules */ -static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; -static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; -static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; -static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; -static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; -static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; -static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; - -/* Heap memory map for modules */ -static SHARED_DATA struct block_map rt_heap_map[] = { - BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), - BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), - BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), - BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), - BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), - BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), - BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), -}; - -/* Heap blocks for buffers */ -static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; - -/* Heap memory map for buffers */ -static SHARED_DATA struct block_map buf_heap_map[] = { - BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), -}; - -static SHARED_DATA struct mm memmap = { - .system[0] = { - .heap = HEAP_SYSTEM_BASE, - .size = HEAP_SYSTEM_SIZE, - .info = {.free = HEAP_SYSTEM_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .system_runtime[0] = { - .blocks = ARRAY_SIZE(sys_rt_heap_map), - .map = sys_rt_heap_map, - .heap = HEAP_SYS_RUNTIME_BASE, - .size = HEAP_SYS_RUNTIME_SIZE, - .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .runtime[0] = { - .blocks = ARRAY_SIZE(rt_heap_map), - .map = rt_heap_map, - .heap = HEAP_RUNTIME_BASE, - .size = HEAP_RUNTIME_SIZE, - .info = {.free = HEAP_RUNTIME_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .buffer[0] = { - .blocks = ARRAY_SIZE(buf_heap_map), - .map = buf_heap_map, - .heap = HEAP_BUFFER_BASE, - .size = HEAP_BUFFER_SIZE, - .info = {.free = HEAP_BUFFER_SIZE,}, - .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA, - }, - .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + - HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, -}; - -void platform_init_memmap(struct sof *sof) -{ - /* memmap has been initialized statically as a part of .data */ - sof->memory_map = &memmap; -} diff --git a/src/platform/haswell/platform.c b/src/platform/haswell/platform.c deleted file mode 100644 index d9fba46d0cb8..000000000000 --- a/src/platform/haswell/platform.c +++ /dev/null @@ -1,261 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/compiler_info.h> -#include <sof/debug/debug.h> -#include <sof/drivers/dw-dma.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> -#include <sof/fw-ready-metadata.h> -#include <sof/lib/agent.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/io.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/shim.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/ll_schedule_domain.h> -#include <sof/sof.h> -#include <sof/trace/dma-trace.h> -#include <sof/trace/trace.h> -#include <ipc/dai.h> -#include <ipc/header.h> -#include <ipc/info.h> -#include <kernel/abi.h> -#include <version.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -static const struct sof_ipc_fw_ready ready - __section(".fw_ready") = { - .hdr = { - .cmd = SOF_IPC_FW_READY, - .size = sizeof(struct sof_ipc_fw_ready), - }, - /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ - .version = { - .hdr.size = sizeof(struct sof_ipc_fw_version), - .micro = SOF_MICRO, - .minor = SOF_MINOR, - .major = SOF_MAJOR, -#if CONFIG_DEBUG - /* only added in debug for reproducability in releases */ - .build = SOF_BUILD, - .date = __DATE__, - .time = __TIME__, -#endif - .tag = SOF_TAG, - .abi_version = SOF_ABI_VERSION, - }, - .flags = DEBUG_SET_FW_READY_FLAGS, -}; - -#define NUM_HSW_WINDOWS 6 -static const struct sof_ipc_window sram_window - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_window) + - sizeof(struct sof_ipc_window_elem) * NUM_HSW_WINDOWS, - .type = SOF_IPC_EXT_WINDOW, - }, - .num_windows = NUM_HSW_WINDOWS, - .window = { - { - .type = SOF_IPC_REGION_UPBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DSPBOX_SIZE, - .offset = MAILBOX_DSPBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DOWNBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_HOSTBOX_SIZE, - .offset = MAILBOX_HOSTBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DEBUG, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DEBUG_SIZE, - .offset = MAILBOX_DEBUG_OFFSET, - }, - { - .type = SOF_IPC_REGION_TRACE, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_TRACE_SIZE, - .offset = MAILBOX_TRACE_OFFSET, - }, - { - .type = SOF_IPC_REGION_STREAM, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_STREAM_SIZE, - .offset = MAILBOX_STREAM_OFFSET, - }, - { - .type = SOF_IPC_REGION_EXCEPTION, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_EXCEPTION_SIZE, - .offset = MAILBOX_EXCEPTION_OFFSET, - }, - }, -}; - -SHARED_DATA struct timer timer = { - .id = TIMER1, /* internal timer */ - .irq = IRQ_NUM_TIMER2, -}; - -int platform_boot_complete(uint32_t boot_message) -{ - uint32_t mb_offset = 0; - uint32_t outbox = MAILBOX_HOST_OFFSET >> 3; - - mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); - mb_offset = mb_offset + sizeof(ready); - - mailbox_dspbox_write(mb_offset, &sram_window, - sram_window.ext_hdr.hdr.size); - mb_offset = mb_offset + sram_window.ext_hdr.hdr.size; - - /* variable length compiler description is a last field of cc_version */ - mailbox_dspbox_write(mb_offset, &cc_version, - cc_version.ext_hdr.hdr.size); - mb_offset = mb_offset + cc_version.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &probe_support, - probe_support.ext_hdr.hdr.size); - mb_offset = mb_offset + probe_support.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &user_abi_version, - user_abi_version.ext_hdr.hdr.size); - - /* now interrupt host to tell it we are done booting */ - shim_write(SHIM_IPCD, outbox | SHIM_IPCD_BUSY); - - /* boot now complete so we can relax the CPU */ - clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); - - return 0; -} - -/* init shim registers */ -static void platform_init_shim(void) -{ - /* disable power gate */ - io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL, - SHIM_CLKCTL_DCPLCG, - SHIM_CLKCTL_DCPLCG); - - /* disable parity check */ - io_reg_update_bits(SHIM_BASE + SHIM_CSR, SHIM_CSR_PCE, 0); - - /* enable DMA finsh on ssp ports */ - io_reg_update_bits(SHIM_BASE + SHIM_CSR2, - SHIM_CSR2_SDFD_SSP0 | SHIM_CSR2_SDFD_SSP1, - SHIM_CSR2_SDFD_SSP0 | SHIM_CSR2_SDFD_SSP1); -} - -int platform_init(struct sof *sof) -{ - struct dai *ssp0; - struct dai *ssp1; - int ret; - - sof->platform_timer = &timer; - sof->cpu_timer = &timer; - - /* clear mailbox for early trace and debug */ - trace_point(TRACE_BOOT_PLATFORM_MBOX); - bzero((void *)MAILBOX_BASE, MAILBOX_SIZE); - - trace_point(TRACE_BOOT_PLATFORM_SHIM); - platform_init_shim(); - - /* init timers, clocks and schedulers */ - trace_point(TRACE_BOOT_PLATFORM_TIMER); - platform_timer_start(sof->platform_timer); - - trace_point(TRACE_BOOT_PLATFORM_CLOCK); - platform_clock_init(sof); - - trace_point(TRACE_BOOT_PLATFORM_SCHED); - scheduler_init_edf(); - - /* init low latency timer domain and scheduler */ - sof->platform_timer_domain = - timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK, - CONFIG_SYSTICK_PERIOD); - scheduler_init_ll(sof->platform_timer_domain); - - /* init the system agent */ - trace_point(TRACE_BOOT_PLATFORM_AGENT); - sa_init(sof, CONFIG_SYSTICK_PERIOD); - - /* Set CPU to default frequency for booting */ - trace_point(TRACE_BOOT_PLATFORM_CPU_FREQ); - clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); - - /* set SSP clock to 24M */ - trace_point(TRACE_BOOT_PLATFORM_SSP_FREQ); - clock_set_freq(CLK_SSP, 24000000); - - /* init DMACs */ - trace_point(TRACE_BOOT_PLATFORM_DMA); - ret = dmac_init(sof); - if (ret < 0) - return -ENODEV; - - /* init low latency multi channel DW-DMA domain and scheduler */ - sof->platform_dma_domain = dma_multi_chan_domain_init - (&sof->dma_info->dma_array[PLATFORM_DW_DMA_INDEX], - PLATFORM_NUM_DW_DMACS, - PLATFORM_DEFAULT_CLOCK, true); - scheduler_init_ll(sof->platform_dma_domain); - - /* initialise the host IPC mechanisms */ - trace_point(TRACE_BOOT_PLATFORM_IPC); - ipc_init(sof); - - trace_point(TRACE_BOOT_PLATFORM_DAI); - ret = dai_init(sof); - if (ret < 0) - return -ENODEV; - - /* init SSP ports */ - trace_point(TRACE_BOOT_PLATFORM_SSP); - ssp0 = dai_get(SOF_DAI_INTEL_SSP, 0, DAI_CREAT); - if (ssp0 == NULL) - return -ENODEV; - - ssp1 = dai_get(SOF_DAI_INTEL_SSP, 1, DAI_CREAT); - if (ssp1 == NULL) - return -ENODEV; - -#if CONFIG_TRACE - /* Initialize DMA for Trace*/ - trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); - dma_trace_init_complete(sof->dmat); -#endif - - /* show heap status */ - heap_trace_all(1); - - return 0; -} diff --git a/src/platform/icelake/CMakeLists.txt b/src/platform/icelake/CMakeLists.txt deleted file mode 100644 index 3fad0567edcb..000000000000 --- a/src/platform/icelake/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(lib) - -add_executable(boot_module boot_module.c) -add_executable(base_module base_module.c) - -target_link_libraries(boot_module sof_options) -target_link_libraries(base_module sof_options) diff --git a/src/platform/icelake/base_module.c b/src/platform/icelake/base_module.c deleted file mode 100644 index eb3779cf950e..000000000000 --- a/src/platform/icelake/base_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest icl_manifest = { - .module = { - .name = "BASEFW", - .uuid = {0x32, 0x8c, 0x39, 0x0e, 0xde, 0x5a, 0x4b, 0xba, - 0x93, 0xb1, 0xc5, 0x04, 0x32, 0x28, 0x0e, 0xe4}, - .entry_point = SOF_TEXT_START, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/icelake/boot_ldr.x.in b/src/platform/icelake/boot_ldr.x.in deleted file mode 100644 index 0820331625a9..000000000000 --- a/src/platform/icelake/boot_ldr.x.in +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Linker Script for Icelake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - boot_entry_text : - org = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - len = IMR_BOOT_LDR_TEXT_ENTRY_SIZE - boot_entry_lit : - org = IMR_BOOT_LDR_LIT_BASE, - len = IMR_BOOT_LDR_LIT_SIZE - sof_text : - org = IMR_BOOT_LDR_TEXT_BASE, - len = IMR_BOOT_LDR_TEXT_SIZE, - sof_data : - org = IMR_BOOT_LDR_DATA_BASE, - len = IMR_BOOT_LDR_DATA_SIZE - sof_bss_data : - org = IMR_BOOT_LDR_BSS_BASE, - len = IMR_BOOT_LDR_BSS_SIZE - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE - lpsram_mem : - org = LP_SRAM_BASE, - len = LP_SRAM_SIZE -} - -PHDRS -{ - boot_entry_text_phdr PT_LOAD; - boot_entry_lit_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_bss_data_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; - wnd0_phdr PT_LOAD; - lpsram_mem_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(boot_entry) -EXTERN(reset_vector) - -SECTIONS -{ - .boot_entry.text : ALIGN(4) - { - _boot_entry_text_start = ABSOLUTE(.); - KEEP (*(.boot_entry.text)) - _boot_entry_text_end = ABSOLUTE(.); - } >boot_entry_text :boot_entry_text_phdr - - .boot_entry.literal : ALIGN(4) - { - _boot_entry_literal_start = ABSOLUTE(.); - *(.boot_entry.literal) - *(.literal .literal.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _boot_entry_literal_end = ABSOLUTE(.); - } >boot_entry_lit :boot_entry_lit_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - *(.entry.text) - *(.init.literal) - KEEP(*(.init)) - *( .text .text.*) - *(.fini.literal) - KEEP(*(.fini)) - *(.gnu.version) - KEEP (*(.ResetVector.text)) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_bss_data :sof_bss_data_phdr - - _man = 0x1234567; - - PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - - _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; - PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - __wnd0 = HP_SRAM_WIN0_BASE; - __wnd0_size = HP_SRAM_WIN0_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - .lpsram(NOLOAD) : ALIGN(8) - { - _lpsram_start = ABSOLUTE(.); - KEEP (*(*.lpsram)) - _lpsram_end = ABSOLUTE(.); - } >lpsram_mem :lpsram_mem_phdr -} diff --git a/src/platform/icelake/boot_module.c b/src/platform/icelake/boot_module.c deleted file mode 100644 index caeb48934104..000000000000 --- a/src/platform/icelake/boot_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest icl_bootldr_manifest = { - .module = { - .name = "BRNGUP", - .uuid = {0xf3, 0xe4, 0x79, 0x2b, 0x75, 0x46, 0x49, 0xf6, - 0x89, 0xdf, 0x3b, 0xc1, 0x94, 0xa9, 0x1a, 0xeb}, - .entry_point = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/icelake/icelake.x.in b/src/platform/icelake/icelake.x.in deleted file mode 100644 index bcf2243ae255..000000000000 --- a/src/platform/icelake/icelake.x.in +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Linker Script for Icelake. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_memory_lit : - org = XCHAL_MEMERROR_VECTOR_PADDR + SOF_MEM_ERROR_LIT_SIZE, - len = SOF_MEM_ERROR_LIT_SIZE - vector_memory_text : - org = XCHAL_MEMERROR_VECTOR_PADDR, - len = SOF_MEM_ERROR_TEXT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_fw : - org = SOF_FW_BASE, - len = SOF_FW_MAX_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE - wnd1 : - org = HP_SRAM_WIN1_BASE, - len = HP_SRAM_WIN1_SIZE - wnd2 : - org = HP_SRAM_WIN2_BASE, - len = HP_SRAM_WIN2_SIZE - wnd3 : - org = HP_SRAM_WIN3_BASE, - len = HP_SRAM_WIN3_SIZE - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE - lpsram_mem : - org = LP_SRAM_BASE, - len = LP_SRAM_SIZE -} - -PHDRS -{ - vector_memory_lit_phdr PT_LOAD; - vector_memory_text_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_fw_phdr PT_LOAD; - wnd0_phdr PT_LOAD; - wnd1_phdr PT_LOAD; - wnd2_phdr PT_LOAD; - wnd3_phdr PT_LOAD; - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; - lpsram_mem_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(_MainEntry) -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .MemoryExceptionVector.text : ALIGN(4) - { - _MemoryExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.text)) - _MemoryExceptionVector_text_end = ABSOLUTE(.); - } >vector_memory_text :vector_memory_text_phdr - - .wnd0 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd0_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN0_SIZE; - _wnd0_end = ABSOLUTE(.); - } >wnd0 :wnd0_phdr - - .wnd1 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd1_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN1_SIZE; - _wnd1_end = ABSOLUTE(.); - } >wnd1 :wnd1_phdr - - .wnd2 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd2_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN2_SIZE; - _wnd2_end = ABSOLUTE(.); - } >wnd2 :wnd2_phdr - - .wnd3 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd3_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN3_SIZE; - _wnd3_end = ABSOLUTE(.); - } >wnd3 :wnd3_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_fw :sof_fw_phdr - - .rodata : ALIGN(4096) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .shared_data : ALIGN(PLATFORM_DCACHE_ALIGN) - { - _shared_data_start = ABSOLUTE(.); - *(*.shared_data) - _shared_data_end = ABSOLUTE(.); - . = ALIGN(PLATFORM_DCACHE_ALIGN); - } >sof_fw :sof_fw_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_fw :sof_fw_phdr - - .bss (NOLOAD) : ALIGN(4096) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - - . = ALIGN (SRAM_BANK_SIZE); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_M_SIZE; - _system_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_M_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_SIZE; - _sof_stack_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _sof_core_s_start = ABSOLUTE(.); - . = . + SOF_CORE_S_T_SIZE; - _sof_core_s_end = ABSOLUTE(.); - - _bss_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - /* stack */ - _end = _sof_stack_start; - PROVIDE(end = _sof_stack_start); - _stack_sentry = _sof_stack_start; - __stack = _sof_stack_end; - - /* Slave core size */ - _core_s_size = SOF_CORE_S_SIZE; - - /* System Heap */ - _system_heap = _system_heap_start; - - /* system runtime heap */ - _system_runtime_heap = _system_runtime_heap_start; - - /* module heap */ - _module_heap = _runtime_heap_start; - - /* buffer heap */ - _buffer_heap = _buffer_heap_start; - _buffer_heap_end = _buffer_heap_end; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr - - .lpsram(NOLOAD) : ALIGN(8) - { - _lpsram_start = ABSOLUTE(.); - KEEP (*(*.lpsram)) - _lpsram_end = ABSOLUTE(.); - } >lpsram_mem :lpsram_mem_phdr - -} diff --git a/src/platform/icelake/include/arch/xtensa/config/core-isa.h b/src/platform/icelake/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index a776e0c1009c..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,613 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 64 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 1 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "X6H3CNL_2017_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x00075E9B /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC2F3FBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x1C45212F /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX6.0.1" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 260001 /* major*100+minor */ -#define XCHAL_HW_REL_LX6 1 -#define XCHAL_HW_REL_LX6_0 1 -#define XCHAL_HW_REL_LX6_0_1 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 260001 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 260001 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 6 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 6 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 49152 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 8 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 6 -#define XCHAL_DCACHE_SETWIDTH 8 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 4 -#define XCHAL_DCACHE_WAYS 3 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY XTHAL_MEMEP_ECC -#define XCHAL_DCACHE_ECC_PARITY XTHAL_MEMEP_ECC - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 8 -#define XCHAL_DCACHE_ACCESS_SIZE 8 - -#define XCHAL_DCACHE_BANKS 1 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 21 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 8 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x0000000F -#define XCHAL_INTLEVEL2_MASK 0x000000F0 -#define XCHAL_INTLEVEL3_MASK 0x00000F00 -#define XCHAL_INTLEVEL4_MASK 0x00007000 -#define XCHAL_INTLEVEL5_MASK 0x000F8000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00100000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000000F -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00007FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x001FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 2 -#define XCHAL_INT5_LEVEL 2 -#define XCHAL_INT6_LEVEL 2 -#define XCHAL_INT7_LEVEL 2 -#define XCHAL_INT8_LEVEL 3 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 4 -#define XCHAL_INT14_LEVEL 4 -#define XCHAL_INT15_LEVEL 5 -#define XCHAL_INT16_LEVEL 5 -#define XCHAL_INT17_LEVEL 5 -#define XCHAL_INT18_LEVEL 5 -#define XCHAL_INT19_LEVEL 5 -#define XCHAL_INT20_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFE00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0008D999 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00072444 -#define XCHAL_INTTYPE_MASK_TIMER 0x00000222 -#define XCHAL_INTTYPE_MASK_NMI 0x00100000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 1 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 5 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 9 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 20 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL7_NUM 20 -/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 6 /* (intlevel 2) */ -#define XCHAL_EXTINT2_NUM 10 /* (intlevel 3) */ -#define XCHAL_EXTINT3_NUM 13 /* (intlevel 4) */ -#define XCHAL_EXTINT4_NUM 16 /* (intlevel 5) */ -#define XCHAL_EXTINT5_NUM 17 /* (intlevel 5) */ -#define XCHAL_EXTINT6_NUM 18 /* (intlevel 5) */ -#define XCHAL_EXTINT7_NUM 20 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT2_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT6_EXTNUM 1 /* (intlevel 2) */ -#define XCHAL_INT10_EXTNUM 2 /* (intlevel 3) */ -#define XCHAL_INT13_EXTNUM 3 /* (intlevel 4) */ -#define XCHAL_INT16_EXTNUM 4 /* (intlevel 5) */ -#define XCHAL_INT17_EXTNUM 5 /* (intlevel 5) */ -#define XCHAL_INT18_EXTNUM 6 /* (intlevel 5) */ -#define XCHAL_INT20_EXTNUM 7 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 1 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0xBEFE0800 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0xBEFE0800 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR0_PADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR1_VADDR 0xBE800000 -#define XCHAL_RESET_VECTOR1_PADDR 0xBE800000 -#define XCHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XCHAL_MEMERROR_VECTOR0_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR0_PADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR1_VADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR1_PADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 -#define XCHAL_USER_VECOFS 0x00000340 -#define XCHAL_USER_VECTOR_VADDR 0xBEFE0B40 -#define XCHAL_USER_VECTOR_PADDR 0xBEFE0B40 -#define XCHAL_KERNEL_VECOFS 0x00000300 -#define XCHAL_KERNEL_VECTOR_VADDR 0xBEFE0B00 -#define XCHAL_KERNEL_VECTOR_PADDR 0xBEFE0B00 -#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xBEFE0BC0 -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0xBEFE0BC0 -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0xBEFE0800 -#define XCHAL_WINDOW_VECTORS_PADDR 0xBEFE0800 -#define XCHAL_INTLEVEL2_VECOFS 0x00000180 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xBEFE0980 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0xBEFE0980 -#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL4_VECOFS 0x00000200 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL5_VECOFS 0x00000240 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL6_VECOFS 0x00000280 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0xBEFE0A80 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0xBEFE0A80 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x000002C0 -#define XCHAL_NMI_VECTOR_VADDR 0xBEFE0AC0 -#define XCHAL_NMI_VECTOR_PADDR 0xBEFE0AC0 -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/arch/xtensa/config/core-matmap.h b/src/platform/icelake/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index d7fd7795e3f1..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - -#define XCHAL_CA_R (0xC0 | 0x40000000) -#define XCHAL_CA_RX (0xD0 | 0x40000000) -#define XCHAL_CA_RW (0xE0 | 0x40000000) -#define XCHAL_CA_RWX (0xF0 | 0x40000000) - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefine hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/arch/xtensa/config/defs.h b/src/platform/icelake/include/arch/xtensa/config/defs.h deleted file mode 100644 index d93272ae05a3..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/arch/xtensa/config/specreg.h b/src/platform/icelake/include/arch/xtensa/config/specreg.h deleted file mode 100644 index 9d1d2ea95dad..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ - -/* Copyright (c) 1998-2002 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define MEMCTL 97 -#define ATOMCTL 99 -#define DDR 104 -#define MEPC 106 -#define MEPS 107 -#define MESAVE 108 -#define MESR 109 -#define MECR 110 -#define MEVADDR 111 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 - -/* Special cases (bases of special register series): */ -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -/* Special names for read-only and write-only interrupt registers: */ -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 - -#endif /* XTENSA_SPECREG_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/arch/xtensa/config/system.h b/src/platform/icelake/include/arch/xtensa/config/system.h deleted file mode 100644 index 0e434954c920..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Copyright (c) 2000-2010 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -#define XSHAL_FLOATING_POINT_ABI 0 - -/* SW workarounds enabled for HW errata: */ - -/* SW options for functional safety: */ -#define XSHAL_FUNC_SAFETY_ENABLED 0 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -#define XSHAL_ROM_VADDR 0xBEFE0000 -#define XSHAL_ROM_PADDR 0xBEFE0000 -#define XSHAL_ROM_SIZE 0x00020000 -/* Largest available area (free of vectors): */ -#define XSHAL_ROM_AVAIL_VADDR 0xBEFE0BC0 -#define XSHAL_ROM_AVAIL_VSIZE 0x0001F440 - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x80000000 -#define XSHAL_RAM_PADDR 0x80000000 -#define XSHAL_RAM_VSIZE 0x3EFE0000 -#define XSHAL_RAM_PSIZE 0x3EFE0000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x80000000 -#define XSHAL_RAM_AVAIL_VSIZE 0x3EFE0000 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit and diagnostic routines. - */ -#define XSHAL_MAGIC_EXIT 0xe0000000 - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22442222 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22112222 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22112222 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44FFFF /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11FFFF /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11FFFF /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22FFFF /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244222F /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211222F /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211222F /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF44422F /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF11122F /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF11122F /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000104 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XSHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XSHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XSHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x00000300 -#define XSHAL_RESET_VECTOR_ISROM 1 -#define XSHAL_USER_VECTOR_SIZE 0x00000038 -#define XSHAL_USER_VECTOR_ISROM 1 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 -#define XSHAL_KERNEL_VECTOR_ISROM 1 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 1 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 1 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL2_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL3_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL4_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL5_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL6_VECTOR_ISROM 1 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x00000038 -#define XSHAL_NMI_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/arch/xtensa/config/tie-asm.h b/src/platform/icelake/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index f6210e126331..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - /* - * Macro to store all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rur.THREADPTR \at1 // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_+0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_store - - /* - * Macro to load all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.THREADPTR \at1 // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - /* - * Macro to store the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_FPU_store xchal_cp0_store - .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - rur.FCR \at1 // ureg 232 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.FSR \at1 // ureg 233 - s32i \at1, \ptr, .Lxchal_ofs_+4 - ssi f0, \ptr, .Lxchal_ofs_+8 - ssi f1, \ptr, .Lxchal_ofs_+12 - ssi f2, \ptr, .Lxchal_ofs_+16 - ssi f3, \ptr, .Lxchal_ofs_+20 - ssi f4, \ptr, .Lxchal_ofs_+24 - ssi f5, \ptr, .Lxchal_ofs_+28 - ssi f6, \ptr, .Lxchal_ofs_+32 - ssi f7, \ptr, .Lxchal_ofs_+36 - ssi f8, \ptr, .Lxchal_ofs_+40 - ssi f9, \ptr, .Lxchal_ofs_+44 - ssi f10, \ptr, .Lxchal_ofs_+48 - ssi f11, \ptr, .Lxchal_ofs_+52 - ssi f12, \ptr, .Lxchal_ofs_+56 - ssi f13, \ptr, .Lxchal_ofs_+60 - ssi f14, \ptr, .Lxchal_ofs_+64 - ssi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_store - - /* - * Macro to load the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_FPU_load xchal_cp0_load - .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.FCR \at1 // ureg 232 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.FSR \at1 // ureg 233 - lsi f0, \ptr, .Lxchal_ofs_+8 - lsi f1, \ptr, .Lxchal_ofs_+12 - lsi f2, \ptr, .Lxchal_ofs_+16 - lsi f3, \ptr, .Lxchal_ofs_+20 - lsi f4, \ptr, .Lxchal_ofs_+24 - lsi f5, \ptr, .Lxchal_ofs_+28 - lsi f6, \ptr, .Lxchal_ofs_+32 - lsi f7, \ptr, .Lxchal_ofs_+36 - lsi f8, \ptr, .Lxchal_ofs_+40 - lsi f9, \ptr, .Lxchal_ofs_+44 - lsi f10, \ptr, .Lxchal_ofs_+48 - lsi f11, \ptr, .Lxchal_ofs_+52 - lsi f12, \ptr, .Lxchal_ofs_+56 - lsi f13, \ptr, .Lxchal_ofs_+60 - lsi f14, \ptr, .Lxchal_ofs_+64 - lsi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_load - -#define XCHAL_CP0_NUM_ATMPS 1 - /* - * Macro to store the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_CW_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - rur.AE_CBEGIN0 \at1 // ureg 246 - s32i \at1, \ptr, .Lxchal_ofs_+16 - rur.AE_CEND0 \at1 // ureg 247 - s32i \at1, \ptr, .Lxchal_ofs_+20 - ae_s64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_s64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed15, \ptr, .Lxchal_ofs_+16 - ae_salign64.i u0, \ptr, .Lxchal_ofs_+24 - ae_salign64.i u1, \ptr, .Lxchal_ofs_+32 - ae_salign64.i u2, \ptr, .Lxchal_ofs_+40 - ae_salign64.i u3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 128 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_store - - /* - * Macro to load the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_CW_SD_NO \at1 // ureg 243 - l32i \at1, \ptr, .Lxchal_ofs_+16 - wur.AE_CBEGIN0 \at1 // ureg 246 - l32i \at1, \ptr, .Lxchal_ofs_+20 - wur.AE_CEND0 \at1 // ureg 247 - ae_l64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_l64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed15, \ptr, .Lxchal_ofs_+16 - addi \ptr, \ptr, 24 - ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 - ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 - ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 - ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 152 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/arch/xtensa/config/tie.h b/src/platform/icelake/include/arch/xtensa/config/tie.h deleted file mode 100644 index 6865fad953af..000000000000 --- a/src/platform/icelake/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 2 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x03 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP0_NAME "FPU" -#define XCHAL_CP0_IDENT FPU -#define XCHAL_CP0_SA_SIZE 72 /* size of state save area */ -#define XCHAL_CP0_SA_ALIGN 4 /* min alignment of save area */ -#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 184 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 12 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 272 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 3 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 18 -#define XCHAL_CP0_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, fcr, 4, 4, 4,0x03E8, ur,232, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f0, 4, 4, 4,0x0030, f,0 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f1, 4, 4, 4,0x0031, f,1 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f2, 4, 4, 4,0x0032, f,2 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f3, 4, 4, 4,0x0033, f,3 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f4, 4, 4, 4,0x0034, f,4 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f5, 4, 4, 4,0x0035, f,5 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f6, 4, 4, 4,0x0036, f,6 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f7, 4, 4, 4,0x0037, f,7 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f8, 4, 4, 4,0x0038, f,8 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f9, 4, 4, 4,0x0039, f,9 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f10, 4, 4, 4,0x003A, f,10 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f11, 4, 4, 4,0x003B, f,11 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f12, 4, 4, 4,0x003C, f,12 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f13, 4, 4, 4,0x003D, f,13 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f14, 4, 4, 4,0x003E, f,14 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f15, 4, 4, 4,0x003F, f,15 , 32,0,0,0) - -#define XCHAL_CP1_SA_NUM 26 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 -/* Byte length of instruction from its first byte, per FLIX. */ -#define XCHAL_BYTE0_FORMAT_LENGTHS \ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 - -#endif /*_XTENSA_CORE_TIE_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/icelake/include/platform/drivers/alh.h b/src/platform/icelake/include/platform/drivers/alh.h deleted file mode 100644 index 64a17690fd8d..000000000000 --- a/src/platform/icelake/include/platform/drivers/alh.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_ALH__ - -#ifndef __PLATFORM_DRIVERS_ALH__ -#define __PLATFORM_DRIVERS_ALH__ - -#include <stdint.h> - -/** - * \brief ALH Handshakes for audio I/O - * Stream ID -> DMA Handshake map - * -1 identifies invalid handshakes/streams - */ -static const uint8_t alh_handshake_map[64] = { - -1, /* 0 - INVALID */ - -1, /* 1 - INVALID */ - -1, /* 2 - INVALID */ - -1, /* 3 - INVALID */ - -1, /* 4 - INVALID */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - 22, /* 7 - BIDIRECTIONAL */ - 23, /* 8 - BIDIRECTIONAL */ - 24, /* 9 - BIDIRECTIONAL */ - 25, /* 10 - BIDIRECTIONAL */ - 26, /* 11 - BIDIRECTIONAL */ - 27, /* 12 - BIDIRECTIONAL */ - -1, /* 13 - INVALID */ - -1, /* 14 - INVALID */ - -1, /* 15 - INVALID */ - -1, /* 16 - INVALID */ - -1, /* 17 - INVALID */ - -1, /* 18 - INVALID */ - -1, /* 19 - INVALID */ - -1, /* 20 - INVALID */ - -1, /* 21 - INVALID */ - -1, /* 22 - INVALID */ - 32, /* 23 - BIDIRECTIONAL */ - 33, /* 24 - BIDIRECTIONAL */ - 34, /* 25 - BIDIRECTIONAL */ - 35, /* 26 - BIDIRECTIONAL */ - 36, /* 27 - BIDIRECTIONAL */ - 37, /* 28 - BIDIRECTIONAL */ - -1, /* 29 - INVALID */ - -1, /* 30 - INVALID */ - -1, /* 31 - INVALID */ - -1, /* 32 - INVALID */ - -1, /* 33 - INVALID */ - -1, /* 34 - INVALID */ - -1, /* 35 - INVALID */ - -1, /* 36 - INVALID */ - -1, /* 37 - INVALID */ - -1, /* 38 - INVALID */ - 42, /* 39 - BIDIRECTIONAL */ - 43, /* 40 - BIDIRECTIONAL */ - 44, /* 41 - BIDIRECTIONAL */ - 45, /* 42 - BIDIRECTIONAL */ - 46, /* 43 - BIDIRECTIONAL */ - 47, /* 44 - BIDIRECTIONAL */ - -1, /* 45 - INVALID */ - -1, /* 46 - INVALID */ - -1, /* 47 - INVALID */ - -1, /* 48 - INVALID */ - -1, /* 49 - INVALID */ - -1, /* 50 - INVALID */ - -1, /* 51 - INVALID */ - -1, /* 52 - INVALID */ - -1, /* 53 - INVALID */ - -1, /* 54 - INVALID */ - 52, /* 55 - BIDIRECTIONAL */ - 53, /* 56 - BIDIRECTIONAL */ - 54, /* 57 - BIDIRECTIONAL */ - 55, /* 58 - BIDIRECTIONAL */ - 56, /* 59 - BIDIRECTIONAL */ - 57, /* 60 - BIDIRECTIONAL */ - -1, /* 61 - INVALID */ - -1, /* 62 - INVALID */ - -1, /* 63 - INVALID */ -}; - -#define ALH_GPDMA_BURST_LENGTH 4 - -#endif /* __PLATFORM_DRIVERS_ALH__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/alh.h" - -#endif diff --git a/src/platform/icelake/include/platform/drivers/dw-dma.h b/src/platform/icelake/include/platform/drivers/dw-dma.h deleted file mode 100644 index 2fe0b26450d5..000000000000 --- a/src/platform/icelake/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <cavs/drivers/dw-dma.h> - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __SOF_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/icelake/include/platform/drivers/idc.h b/src/platform/icelake/include/platform/drivers/idc.h deleted file mode 100644 index b8565347f42e..000000000000 --- a/src/platform/icelake/include/platform/drivers/idc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <cavs/drivers/idc.h> - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/icelake/include/platform/drivers/interrupt.h b/src/platform/icelake/include/platform/drivers/interrupt.h deleted file mode 100644 index 057b13be1679..000000000000 --- a/src/platform/icelake/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,154 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <cavs/drivers/interrupt.h> -#include <sof/bit.h> -#include <config.h> - -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 32 - -/* IRQ numbers - wrt Tensilica DSP */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_SOFTWARE0 0 /* level 1 */ -#define IRQ_NUM_TIMER1 1 /* level 1 */ -#define IRQ_NUM_EXT_LEVEL1 2 /* level 1 */ -#define IRQ_NUM_SOFTWARE1 3 /* level 1 */ - -#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_EXT_LEVEL1 BIT(IRQ_NUM_EXT_LEVEL1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_SOFTWARE2 4 /* level 2 */ -#define IRQ_NUM_TIMER2 5 /* level 2 */ -#define IRQ_NUM_EXT_LEVEL2 6 /* level 2 */ -#define IRQ_NUM_SOFTWARE3 7 /* level 2 */ - -/* IRQ Level 2 bits */ -#define IRQ_BIT_LVL2_HP_GP_DMA0(x) (x + 24) -#define IRQ_BIT_LVL2_WALL_CLK1 23 -#define IRQ_BIT_LVL2_WALL_CLK0 22 -#define IRQ_BIT_LVL2_L2_MEMERR 21 -#define IRQ_BIT_LVL2_SHA256 16 -#define IRQ_BIT_LVL2_L2_CACHE 15 -#define IRQ_BIT_LVL2_IDC 8 -#define IRQ_BIT_LVL2_HOST_IPC 7 -#define IRQ_BIT_LVL2_CSME_IPC 6 -#define IRQ_BIT_LVL2_PMC_IPC 5 - -/* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) -#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC -#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC -#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 -#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 -#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR -#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE -#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 - -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_EXT_LEVEL2 BIT(IRQ_NUM_EXT_LEVEL2) -#define IRQ_MASK_SOFTWARE3 BIT(IRQ_NUM_SOFTWARE3) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_SOFTWARE4 8 /* level 3 */ -#define IRQ_NUM_TIMER3 9 /* level 3 */ -#define IRQ_NUM_EXT_LEVEL3 10 /* level 3 */ -#define IRQ_NUM_SOFTWARE5 11 /* level 3 */ - -/* IRQ Level 3 bits */ -#define IRQ_BIT_LVL3_CODE_LOADER 31 -#define IRQ_BIT_LVL3_HOST_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL3_HOST_STREAM_IN(x) (0 + x) - -/* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER -#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE4 BIT(IRQ_NUM_SOFTWARE4) -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) -#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) -#define IRQ_MASK_SOFTWARE5 BIT(IRQ_NUM_SOFTWARE5) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_SOFTWARE6 12 /* level 4 */ -#define IRQ_NUM_EXT_LEVEL4 13 /* level 4 */ -#define IRQ_NUM_SOFTWARE7 14 /* level 4 */ - -/* IRQ Level 4 bits */ -#define IRQ_BIT_LVL4_LINK_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL4_LINK_STREAM_IN(x) (0 + x) - -/* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE6 BIT(IRQ_NUM_SOFTWARE6) -#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) -#define IRQ_MASK_SOFTWARE7 BIT(IRQ_NUM_SOFTWARE7) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_SOFTWARE8 15 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL5 16 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL6 17 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL7 18 /* level 5 */ -#define IRQ_NUM_SOFTWARE9 19 /* level 5 */ - -/* IRQ Level 5 bits */ -#define IRQ_BIT_LVL5_LP_GP_DMA1 15 -#define IRQ_BIT_LVL5_LP_GP_DMA0 16 -#define IRQ_BIT_LVL5_DMIC(x) 8 -#define IRQ_BIT_LVL5_SSP(x) (0 + x) - -/* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) - -#define IRQ_MASK_SOFTWARE8 BIT(IRQ_NUM_SOFTWARE8) -#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) -#define IRQ_MASK_EXT_LEVEL6 BIT(IRQ_NUM_EXT_LEVEL6) -#define IRQ_MASK_EXT_LEVEL7 BIT(IRQ_NUM_EXT_LEVEL7) -#define IRQ_MASK_SOFTWARE9 BIT(IRQ_NUM_SOFTWARE9) - -#endif - -#define IRQ_NUM_NMI 20 /* level 7 */ - -#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/icelake/include/platform/lib/clk.h b/src/platform/icelake/include/platform/lib/clk.h deleted file mode 100644 index dc13be94b6c1..000000000000 --- a/src/platform/icelake/include/platform/lib/clk.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <cavs/lib/clk.h> - -#define CLK_MAX_CPU_HZ 400000000 - -#define CPU_LPRO_FREQ_IDX 0 - -#define CPU_HPRO_FREQ_IDX 1 - -#define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX - -#define SSP_DEFAULT_IDX 1 - -#define NUM_CPU_FREQ 2 - -#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/icelake/include/platform/lib/cpu.h b/src/platform/icelake/include/platform/lib/cpu.h deleted file mode 100644 index 78a6e78bc889..000000000000 --- a/src/platform/icelake/include/platform/lib/cpu.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <cavs/lib/cpu.h> - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 4 - -#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/icelake/include/platform/lib/dai.h b/src/platform/icelake/include/platform/lib/dai.h deleted file mode 100644 index dce7601cdef6..000000000000 --- a/src/platform/icelake/include/platform/lib/dai.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -/* ICELAKE */ - -/* 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 6 - -/** \brief Number of 'extended' SSP ports available */ -#define DAI_NUM_SSP_EXT 0 - -/** \brief Number of SSP MCLKs available */ -#define DAI_NUM_SSP_MCLK 2 - -/* 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 7 - -/* ALH */ - -/** \brief Number of ALH bi-directional links */ -#define DAI_NUM_ALH_BI_DIR_LINKS 24 - -/** \brief Number of contiguous ALH bi-dir links */ -#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 6 - -#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/icelake/include/platform/lib/dma.h b/src/platform/icelake/include/platform/lib/dma.h deleted file mode 100644 index 4dfae664ae11..000000000000 --- a/src/platform/icelake/include/platform/lib/dma.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -/* number of supported DMACs */ -#define PLATFORM_NUM_DMACS 6 - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 9 - -/* available DMACs */ -#define DMA_GP_LP_DMAC0 0 -#define DMA_GP_LP_DMAC1 1 -#define DMA_GP_HP_DMAC0 2 -#define DMA_GP_HP_DMAC1 3 -#define DMA_HOST_IN_DMAC 4 -#define DMA_HOST_OUT_DMAC 5 -#define DMA_LINK_IN_DMAC 6 -#define DMA_LINK_OUT_DMAC 7 - -/* mappings - TODO improve API to get type */ -#define DMA_ID_DMAC0 DMA_HOST_IN_DMAC -#define DMA_ID_DMAC1 DMA_GP_LP_DMAC0 -#define DMA_ID_DMAC2 DMA_HOST_OUT_DMAC -#define DMA_ID_DMAC3 DMA_GP_HP_DMAC0 -#define DMA_ID_DMAC4 DMA_GP_LP_DMAC1 -#define DMA_ID_DMAC5 DMA_GP_HP_DMAC1 -#define DMA_ID_DMAC6 DMA_LINK_IN_DMAC -#define DMA_ID_DMAC7 DMA_LINK_OUT_DMAC - -/* handshakes */ -#define DMA_HANDSHAKE_DMIC_CH0 0 -#define DMA_HANDSHAKE_DMIC_CH1 1 -#define DMA_HANDSHAKE_SSP0_TX 2 -#define DMA_HANDSHAKE_SSP0_RX 3 -#define DMA_HANDSHAKE_SSP1_TX 4 -#define DMA_HANDSHAKE_SSP1_RX 5 -#define DMA_HANDSHAKE_SSP2_TX 6 -#define DMA_HANDSHAKE_SSP2_RX 7 -#define DMA_HANDSHAKE_SSP3_TX 8 -#define DMA_HANDSHAKE_SSP3_RX 9 -#define DMA_HANDSHAKE_SSP4_TX 10 -#define DMA_HANDSHAKE_SSP4_RX 11 -#define DMA_HANDSHAKE_SSP5_TX 12 -#define DMA_HANDSHAKE_SSP5_RX 13 - -#define dma_chan_irq(dma, chan) dma_irq(dma) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/icelake/include/platform/lib/mailbox.h b/src/platform/icelake/include/platform/lib/mailbox.h deleted file mode 100644 index a781e3aecb31..000000000000 --- a/src/platform/icelake/include/platform/lib/mailbox.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_MAILBOX_H__ - -#ifndef __PLATFORM_LIB_MAILBOX_H__ -#define __PLATFORM_LIB_MAILBOX_H__ - -#include <cavs/lib/mailbox.h> - -#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/icelake/include/platform/lib/memory.h b/src/platform/icelake/include/platform/lib/memory.h deleted file mode 100644 index f6c38d5e4e34..000000000000 --- a/src/platform/icelake/include/platform/lib/memory.h +++ /dev/null @@ -1,412 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_MEMORY_H__ - -#ifndef __PLATFORM_LIB_MEMORY_H__ -#define __PLATFORM_LIB_MEMORY_H__ - -#include <cavs/lib/memory.h> -#include <sof/lib/cpu.h> -#include <config.h> - -/* physical DSP addresses */ - -/* shim */ -#define SHIM_BASE 0x00071F00 -#define SHIM_SIZE 0x00000100 - -/* Digital Mic Shim Registers */ -#define DMIC_SHIM_BASE 0x00071E80 -#define DMICLCTL_OFFSET 0x04 -#define DMICLCTL (DMIC_SHIM_BASE + DMICLCTL_OFFSET) - -/* cmd IO to audio codecs */ -#define CMD_BASE 0x00001100 -#define CMD_SIZE 0x00000010 - -/* resource allocation */ -#define RES_BASE 0x00001110 -#define RES_SIZE 0x00000010 - -/* IPC to the host */ -#define IPC_HOST_BASE 0x00071E00 -#define IPC_HOST_SIZE 0x00000020 - -/* intra DSP IPC */ -#define IPC_DSP_SIZE 0x00000080 -#define IPC_DSP_BASE(x) (0x00001200 + x * IPC_DSP_SIZE) - -/* SRAM window for HOST */ -#define HOST_WIN_SIZE 0x00000008 -#define HOST_WIN_BASE(x) (0x00071A00 + x * HOST_WIN_SIZE) - -/* IRQ controller */ -#define IRQ_BASE 0x00078800 -#define IRQ_SIZE 0x00000200 - -/* time stamping */ -#define TIME_BASE 0x00071800 -#define TIME_SIZE 0x00000200 - -/* M/N dividers */ -#define MN_BASE 0x00078C00 -#define MN_SIZE 0x00000200 - -/* low power DMA position */ -#define LP_GP_DMA_LINK_SIZE 0x00000010 -#define LP_GP_DMA_LINK_BASE(x) (0x00001C00 + x * LP_GP_DMA_LINK_SIZE) - -/* high performance DMA position */ -#define HP_GP_DMA_LINK_SIZE 0x00000010 -#define HP_GP_DMA_LINK_BASE(x) (0x00001D00 + x * HP_GP_DMA_LINK_SIZE) - -/* link DMAC stream */ -#define GTW_LINK_OUT_STREAM_SIZE 0x00000020 -#define GTW_LINK_OUT_STREAM_BASE(x) \ - (0x00072400 + x * GTW_LINK_OUT_STREAM_SIZE) - -#define GTW_LINK_IN_STREAM_SIZE 0x00000020 -#define GTW_LINK_IN_STREAM_BASE(x) \ - (0x00072600 + x * GTW_LINK_IN_STREAM_SIZE) - -/* host DMAC stream */ -#define GTW_HOST_OUT_STREAM_SIZE 0x00000040 -#define GTW_HOST_OUT_STREAM_BASE(x) \ - (0x00072800 + x * GTW_HOST_OUT_STREAM_SIZE) - -#define GTW_HOST_IN_STREAM_SIZE 0x00000040 -#define GTW_HOST_IN_STREAM_BASE(x) \ - (0x00072C00 + x * GTW_HOST_IN_STREAM_SIZE) - -/* code loader */ -#define GTW_CODE_LDR_SIZE 0x00000040 -#define GTW_CODE_LDR_BASE 0x00002BC0 - -/* L2 TLBs */ -#define L2_HP_SRAM_TLB_SIZE 0x00001000 -#define L2_HP_SRAM_TLB_BASE 0x00003000 - -/* DMICs */ -#define DMIC_BASE 0x00010000 -#define DMIC_SIZE 0x00008000 - -/* SSP */ -#define SSP_BASE(x) (0x00077000 + x * SSP_SIZE) -#define SSP_SIZE 0x0000200 - -/* ALH */ -#define ALH_BASE 0x000071000 -#define ALH_TXDA_OFFSET 0x000000400 -#define ALH_RXDA_OFFSET 0x000000500 -#define ALH_STREAM_OFFSET 0x000000004 - -/* Timestamping */ -#define TIMESTAMP_BASE 0x00071800 - -/* low power DMACs */ -#define LP_GP_DMA_SIZE 0x00001000 -#define LP_GP_DMA_BASE(x) (0x0007C000 + x * LP_GP_DMA_SIZE) - -/* high performance DMACs */ -#define HP_GP_DMA_SIZE 0x00001000 -#define HP_GP_DMA_BASE(x) (0x0000E000 + x * HP_GP_DMA_SIZE) - -/* ROM */ -#define ROM_BASE 0xBEFE0000 -#define ROM_SIZE 0x00002000 - -#define L2_VECTOR_SIZE 0x1000 - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -/* - * The HP SRAM Region on Icelake is organised like this :- - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_SW_REG_BASE | SW Registers W0 | SRAM_SW_REG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_MAILBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_EXCEPT_BASE | Debug data W2 | SRAM_EXCEPT_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_STREAM_BASE | Stream data W2 | SRAM_STREAM_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_TRACE_BASE | Trace Buffer W3 | SRAM_TRACE_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SOF_FW_START | text | | - * | | data | | - * | | BSS | | - * +------------------+-------------------------+-----------------------------+ - * | | Runtime Heap | HEAP_RUNTIME_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Module Buffers | HEAP_BUFFER_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Master core Sys Heap | HEAP_SYSTEM_M_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Master Sys Runtime Heap | HEAP_SYS_RUNTIME_M_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Master core Stack | SOF_STACK_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Slave core Sys Heap | SOF_CORE_S_T_SIZE | - * | | Slave Sys Runtime Heap | | - * | | Slave core Stack | | - * +------------------+-------------------------+-----------------------------+ - */ - -/* HP SRAM */ -#define HP_SRAM_BASE 0xBE000000 - -/* HP SRAM windows */ -/* window 0 */ -#define SRAM_SW_REG_BASE (HP_SRAM_BASE + 0x4000) -#define SRAM_SW_REG_SIZE 0x1000 - -/* SRAM window 0 FW "registers" */ -#define SRAM_REG_ROM_STATUS 0x0 -#define SRAM_REG_FW_STATUS 0x4 -#define SRAM_REG_FW_TRACEP 0x8 -#define SRAM_REG_FW_IPC_RECEIVED_COUNT 0xc -#define SRAM_REG_FW_IPC_PROCESSED_COUNT 0x10 -#define SRAM_REG_FW_END 0x14 - -#define SRAM_OUTBOX_BASE (SRAM_SW_REG_BASE + SRAM_SW_REG_SIZE) -#define SRAM_OUTBOX_SIZE 0x1000 - -/* window 1 */ -#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) -#define SRAM_INBOX_SIZE 0x2000 -/* window 2 */ -#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) -#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 - -/* window 3 */ -#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) -#if CONFIG_TRACE -#define SRAM_TRACE_SIZE 0x2000 -#else -#define SRAM_TRACE_SIZE 0x0 -#endif - -#define HP_SRAM_WIN0_BASE SRAM_SW_REG_BASE -#define HP_SRAM_WIN0_SIZE (SRAM_SW_REG_SIZE + SRAM_OUTBOX_SIZE) -#define HP_SRAM_WIN1_BASE SRAM_INBOX_BASE -#define HP_SRAM_WIN1_SIZE SRAM_INBOX_SIZE -#define HP_SRAM_WIN2_BASE SRAM_DEBUG_BASE -#define HP_SRAM_WIN2_SIZE (SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE + \ - SRAM_STREAM_SIZE) -#define HP_SRAM_WIN3_BASE SRAM_TRACE_BASE -#define HP_SRAM_WIN3_SIZE SRAM_TRACE_SIZE - -/* HP SRAM Base */ -#define HP_SRAM_VECBASE_RESET (SRAM_TRACE_BASE + SRAM_TRACE_SIZE) - -/* text and data share the same HP L2 SRAM on Icelake */ -#define SOF_FW_START (HP_SRAM_VECBASE_RESET + 0x400) -#define SOF_FW_BASE (SOF_FW_START) - -/* max size for all var-size sections (text/rodata/bss) */ -#define SOF_FW_MAX_SIZE (HP_SRAM_BASE + HP_SRAM_SIZE - SOF_FW_BASE) - -#define SOF_TEXT_START (SOF_FW_START) -#define SOF_TEXT_BASE (SOF_FW_START) - -/* Heap section sizes for system runtime heap for master core */ -#define HEAP_SYS_RT_0_COUNT64 128 -#define HEAP_SYS_RT_0_COUNT512 16 -#define HEAP_SYS_RT_0_COUNT1024 4 - -/* Heap section sizes for system runtime heap for slave core */ -#define HEAP_SYS_RT_X_COUNT64 64 -#define HEAP_SYS_RT_X_COUNT512 8 -#define HEAP_SYS_RT_X_COUNT1024 4 - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT64 128 -#define HEAP_RT_COUNT128 64 -#define HEAP_RT_COUNT256 128 -#define HEAP_RT_COUNT512 8 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 0 -#define HEAP_RT_COUNT4096 1 - -/* Heap configuration */ -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT64 * 64 + HEAP_RT_COUNT128 * 128 + \ - HEAP_RT_COUNT256 * 256 + HEAP_RT_COUNT512 * 512 + \ - HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + \ - HEAP_RT_COUNT4096 * 4096) - -#define HEAP_BUFFER_SIZE 0x50000 -#define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) - -#define HEAP_SYSTEM_M_SIZE 0x8000 /* heap master core size */ -#define HEAP_SYSTEM_S_SIZE 0x6000 /* heap slave core size */ -#define HEAP_SYSTEM_T_SIZE \ - (HEAP_SYSTEM_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) - -#define HEAP_SYS_RUNTIME_M_SIZE \ - (HEAP_SYS_RT_0_COUNT64 * 64 + HEAP_SYS_RT_0_COUNT512 * 512 + \ - HEAP_SYS_RT_0_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_S_SIZE \ - (HEAP_SYS_RT_X_COUNT64 * 64 + HEAP_SYS_RT_X_COUNT512 * 512 + \ - HEAP_SYS_RT_X_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_T_SIZE \ - (HEAP_SYS_RUNTIME_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * \ - HEAP_SYS_RUNTIME_S_SIZE)) - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * SOF_STACK_SIZE) - -/* SOF Core S configuration */ -#define SOF_CORE_S_SIZE \ - ALIGN((HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE + SOF_STACK_SIZE),\ - SRAM_BANK_SIZE) -#define SOF_CORE_S_T_SIZE ((PLATFORM_CORE_COUNT - 1) * SOF_CORE_S_SIZE) - -/* - * The LP SRAM Heap and Stack on Icelake are organised like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | LP_SRAM_BASE | RO Data | SOF_LP_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_SYSTEM_BASE | System Heap | HEAP_LP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_RUNTIME_BASE| Runtime Heap | HEAP_LP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_BUFFER_BASE | Module Buffers | HEAP_LP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_LP_STACK_END | Stack | SOF_LP_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - -/* LP SRAM */ -#define LP_SRAM_BASE 0xBE800000 - -/* Heap section sizes for module pool */ -#define HEAP_RT_LP_COUNT8 0 -#define HEAP_RT_LP_COUNT16 256 -#define HEAP_RT_LP_COUNT32 128 -#define HEAP_RT_LP_COUNT64 64 -#define HEAP_RT_LP_COUNT128 64 -#define HEAP_RT_LP_COUNT256 96 -#define HEAP_RT_LP_COUNT512 8 -#define HEAP_RT_LP_COUNT1024 4 - -/* Heap configuration */ -#define SOF_LP_DATA_SIZE 0x4000 - -#define HEAP_LP_SYSTEM_BASE (LP_SRAM_BASE + SOF_LP_DATA_SIZE) -#define HEAP_LP_SYSTEM_SIZE 0x1000 - -#define HEAP_LP_RUNTIME_BASE \ - (HEAP_LP_SYSTEM_BASE + HEAP_LP_SYSTEM_SIZE) -#define HEAP_LP_RUNTIME_SIZE \ - (HEAP_RT_LP_COUNT8 * 8 + HEAP_RT_LP_COUNT16 * 16 + \ - HEAP_RT_LP_COUNT32 * 32 + HEAP_RT_LP_COUNT64 * 64 + \ - HEAP_RT_LP_COUNT128 * 128 + HEAP_RT_LP_COUNT256 * 256 + \ - HEAP_RT_LP_COUNT512 * 512 + HEAP_RT_LP_COUNT1024 * 1024) - -#define HEAP_LP_BUFFER_BASE LP_SRAM_BASE -#define HEAP_LP_BUFFER_SIZE LP_SRAM_SIZE - -#define HEAP_LP_BUFFER_BLOCK_SIZE 0x180 - -#if CONFIG_LP_MEMORY_BANKS -#define HEAP_LP_BUFFER_COUNT \ - (HEAP_LP_BUFFER_SIZE / HEAP_LP_BUFFER_BLOCK_SIZE) -#else -#define HEAP_LP_BUFFER_COUNT 0 -#endif - -#define PLATFORM_HEAP_SYSTEM PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 2 - -/* Stack configuration */ -#define SOF_LP_STACK_SIZE 0x1000 -#define SOF_LP_STACK_BASE (LP_SRAM_BASE + LP_SRAM_SIZE) -#define SOF_LP_STACK_END (SOF_LP_STACK_BASE - SOF_LP_STACK_SIZE) - - -/* Vector and literal sizes - do not use core-isa.h */ -#define SOF_MEM_VECBASE HP_SRAM_VECBASE_RESET -#define SOF_MEM_VECT_LIT_SIZE 0x8 -#define SOF_MEM_VECT_TEXT_SIZE 0x38 -#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ - SOF_MEM_VECT_LIT_SIZE) - -#define SOF_MEM_ERROR_TEXT_SIZE 0x180 -#define SOF_MEM_ERROR_LIT_SIZE 0x8 - -#define SOF_MEM_RESET_TEXT_SIZE 0x268 -#define SOF_MEM_RESET_LIT_SIZE 0x8 -#define SOF_MEM_VECBASE_LIT_SIZE 0x178 - -#define SOF_MEM_RO_SIZE 0x8 - -/* VM ROM sizes */ -#define ROM_RESET_TEXT_SIZE 0x400 -#define ROM_RESET_LIT_SIZE 0x200 - -/* boot loader in IMR */ -#define IMR_BOOT_LDR_MANIFEST_BASE 0xB0032000 -#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 - -#define IMR_BOOT_LDR_TEXT_ENTRY_BASE 0xB0038000 -#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x120 -#define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ - IMR_BOOT_LDR_TEXT_ENTRY_SIZE) -#define IMR_BOOT_LDR_LIT_SIZE 0x22 -#define IMR_BOOT_LDR_TEXT_BASE (IMR_BOOT_LDR_LIT_BASE + \ - IMR_BOOT_LDR_LIT_SIZE) -#define IMR_BOOT_LDR_TEXT_SIZE 0x1C00 -#define IMR_BOOT_LDR_DATA_BASE 0xB0039000 -#define IMR_BOOT_LDR_DATA_SIZE 0x1000 -#define IMR_BOOT_LDR_BSS_BASE 0xB0100000 -#define IMR_BOOT_LDR_BSS_SIZE 0x10000 - -/* Temporary stack place for boot_ldr */ -#define BOOT_LDR_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE - \ - SOF_STACK_TOTAL_SIZE) -#define BOOT_LDR_STACK_SIZE SOF_STACK_TOTAL_SIZE - -#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/icelake/include/platform/lib/pm_runtime.h b/src/platform/icelake/include/platform/lib/pm_runtime.h deleted file mode 100644 index 00ea63026438..000000000000 --- a/src/platform/icelake/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/icelake/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Icelake - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <cavs/lib/pm_runtime.h> -#include <stdint.h> - -/** - * \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_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); - -/** - * \brief Power gates platform specific hardware resources. - */ -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/icelake/include/platform/lib/shim.h b/src/platform/icelake/include/platform/lib/shim.h deleted file mode 100644 index 43b9df28b893..000000000000 --- a/src/platform/icelake/include/platform/lib/shim.h +++ /dev/null @@ -1,364 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <cavs/drivers/sideband-ipc.h> -#include <sof/bit.h> -#include <sof/lib/memory.h> - -#ifndef ASSEMBLY -#include <stdint.h> -#endif - -/* DSP IPC for Host Registers */ -#define IPC_DIPCTDR 0x00 -#define IPC_DIPCTDA 0x04 -#define IPC_DIPCTDD 0x08 -#define IPC_DIPCIDR 0x10 -#define IPC_DIPCIDA 0x14 -#define IPC_DIPCIDD 0x18 -#define IPC_DIPCCTL 0x28 - -#define IPC_DSP_OFFSET 0x10 - -/* DSP IPC for intra DSP communication */ -#define IPC_IDCTFC(x) (0x0 + x * IPC_DSP_OFFSET) -#define IPC_IDCTEFC(x) (0x4 + x * IPC_DSP_OFFSET) -#define IPC_IDCITC(x) (0x8 + x * IPC_DSP_OFFSET) -#define IPC_IDCIETC(x) (0xc + x * IPC_DSP_OFFSET) -#define IPC_IDCCTL 0x50 - -/* IDCTFC */ -#define IPC_IDCTFC_BUSY BIT(31) -#define IPC_IDCTFC_MSG_MASK 0x7FFFFFFF - -/* IDCTEFC */ -#define IPC_IDCTEFC_MSG_MASK 0x3FFFFFFF - -/* IDCITC */ -#define IPC_IDCITC_BUSY BIT(31) -#define IPC_IDCITC_MSG_MASK 0x7FFFFFFF - -/* IDCIETC */ -#define IPC_IDCIETC_DONE BIT(30) -#define IPC_IDCIETC_MSG_MASK 0x3FFFFFFF - -/* IDCCTL */ -#define IPC_IDCCTL_IDCIDIE(x) (0x100 << (x)) -#define IPC_IDCCTL_IDCTBIE(x) BIT(x) - -#define IRQ_CPU_OFFSET 0x40 - -#define REG_IRQ_IL2MSD(xcpu) (0x0 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MCD(xcpu) (0x4 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MD(xcpu) (0x8 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2SD(xcpu) (0xc + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL2MD_ALL 0x03F181F0 - -#define REG_IRQ_IL3MSD(xcpu) (0x10 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MCD(xcpu) (0x14 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MD(xcpu) (0x18 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3SD(xcpu) (0x1c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL3MD_ALL 0x807F81FF - -#define REG_IRQ_IL4MSD(xcpu) (0x20 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MCD(xcpu) (0x24 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MD(xcpu) (0x28 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4SD(xcpu) (0x2c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL4MD_ALL 0x807F81FF - -#define REG_IRQ_IL5MSD(xcpu) (0x30 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MCD(xcpu) (0x34 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MD(xcpu) (0x38 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5SD(xcpu) (0x3c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL5MD_ALL 0xFFFFC0CF - -#define REG_IRQ_IL2RSD 0x100 -#define REG_IRQ_IL3RSD 0x104 -#define REG_IRQ_IL4RSD 0x108 -#define REG_IRQ_IL5RSD 0x10c - -#define REG_IRQ_LVL5_LP_GPDMA0_MASK (0xff << 16) -#define REG_IRQ_LVL5_LP_GPDMA1_MASK (0xff << 24) - -/* DSP Shim Registers */ -#define SHIM_DSPWC 0x20 /* DSP Wall Clock */ -#define SHIM_DSPWCTCS 0x28 /* DSP Wall Clock Timer Control & Status */ -#define SHIM_DSPWCT0C 0x30 /* DSP Wall Clock Timer 0 Compare */ -#define SHIM_DSPWCT1C 0x38 /* DSP Wall Clock Timer 1 Compare */ - -#define SHIM_DSPWCTCS_T1T BIT(5) /* Timer 1 triggered */ -#define SHIM_DSPWCTCS_T0T BIT(4) /* Timer 0 triggered */ -#define SHIM_DSPWCTCS_T1A BIT(1) /* Timer 1 armed */ -#define SHIM_DSPWCTCS_T0A BIT(0) /* Timer 0 armed */ - -/** \brief Clock control */ -#define SHIM_CLKCTL 0x78 - -/** \brief Request HP RING Oscillator Clock */ -#define SHIM_CLKCTL_RHROSCC BIT(31) - -/** \brief Request XTAL Oscillator Clock */ -#define SHIM_CLKCTL_RXOSCC BIT(30) - -/** \brief Request LP RING Oscillator Clock */ -#define SHIM_CLKCTL_RLROSCC BIT(29) - -/** \brief Tensilica Core Prevent Local Clock Gating */ -#define SHIM_CLKCTL_TCPLCG_EN(x) BIT(16 + (x)) -#define SHIM_CLKCTL_TCPLCG_DIS(x) 0 -#define SHIM_CLKCTL_TCPLCG_DIS_ALL (SHIM_CLKCTL_TCPLCG_DIS(0) | \ - SHIM_CLKCTL_TCPLCG_DIS(1) | \ - SHIM_CLKCTL_TCPLCG_DIS(2) | \ - SHIM_CLKCTL_TCPLCG_DIS(3)) - -/** \brief Oscillator Clock Select*/ -#define SHIM_CLKCTL_OCS_HP_RING BIT(2) -#define SHIM_CLKCTL_OCS_LP_RING 0 - -/** \brief LP Memory Clock Select */ -#define SHIM_CLKCTL_LMCS_DIV2 0 -#define SHIM_CLKCTL_LMCS_DIV4 BIT(1) - -/** \brief HP Memory Clock Select */ -#define SHIM_CLKCTL_HMCS_DIV2 0 -#define SHIM_CLKCTL_HMCS_DIV4 BIT(0) - -/* Core clock PLL divisor */ -#define SHIM_CLKCTL_DPCS_MASK(x) BIT(2) - -/* Prevent Audio PLL Shutdown */ -#define SHIM_CLKCTL_TCPAPLLS BIT(7) - -/* 0--from PLL, 1--from oscillator */ -#define SHIM_CLKCTL_HDCS BIT(4) - -/* Oscillator select */ -#define SHIM_CLKCTL_HDOCS BIT(2) - -/* HP memory clock PLL divisor */ -#define SHIM_CLKCTL_HPMPCS BIT(0) - -/** \brief Mask for requesting clock - */ -#define SHIM_CLKCTL_OSC_REQUEST_MASK \ - (SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_RXOSCC | \ - SHIM_CLKCTL_RLROSCC) - -/** \brief Mask for setting previously requested clock - */ -#define SHIM_CLKCTL_OSC_SOURCE_MASK \ - (SHIM_CLKCTL_OCS_HP_RING | SHIM_CLKCTL_LMCS_DIV4 | \ - SHIM_CLKCTL_HMCS_DIV4) - -/** \brief Clock status */ -#define SHIM_CLKSTS 0x7C - -/** \brief HP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_HROSCCS BIT(31) - -/** \brief XTAL Oscillator Clock Status */ -#define SHIM_CLKSTS_XOSCCS BIT(30) - -/** \brief LP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_LROSCCS BIT(29) - -#define SHIM_PWRCTL 0x90 -#define SHIM_PWRCTL_TCPDSPPG(x) BIT(x) -#define SHIM_PWRCTL_TCPCTLPG BIT(4) - -#define SHIM_PWRSTS 0x92 - -#define SHIM_LPSCTL 0x94 -#define SHIM_LPSCTL_BID BIT(7) -#define SHIM_LPSCTL_FDSPRUN BIT(9) -#define SHIM_LPSCTL_BATTR_0 BIT(12) - -/** \brief GPDMA shim registers Control */ -#define SHIM_GPDMA_BASE_OFFSET 0x6500 -#define SHIM_GPDMA_BASE(x) (SHIM_GPDMA_BASE_OFFSET + (x) * 0x100) - -/** \brief GPDMA Clock Control */ -#define SHIM_GPDMA_CLKCTL(x) (SHIM_GPDMA_BASE(x) + 0x4) -/* LP GPDMA Force Dynamic Clock Gating bits, 0--enable */ -#define SHIM_CLKCTL_LPGPDMAFDCGB BIT(0) - -/** \brief GPDMA Channel Linear Link Position Control */ -#define SHIM_GPDMA_CHLLPC(x, y) (SHIM_GPDMA_BASE(x) + 0x10 + (y) * 0x10) -#define SHIM_GPDMA_CHLLPC_EN BIT(7) -#define SHIM_GPDMA_CHLLPC_DHRS(x) SET_BITS(6, 0, x) - -#define L2LMCAP 0x71D00 -#define L2MPAT 0x71D04 - -#define HSPGCTL0 0x71D10 -#define HSRMCTL0 0x71D14 -#define HSPGISTS0 0x71D18 - -#define SHIM_HSPGCTL(x) (HSPGCTL0 + 0x10 * (x)) -#define SHIM_HSPGISTS(x) (HSPGISTS0 + 0x10 * (x)) - -#define HSPGCTL1 0x71D20 -#define HSRMCTL1 0x71D24 -#define HSPGISTS1 0x71D28 - -#define LSPGCTL 0x71D50 -#define LSRMCTL 0x71D54 -#define LSPGISTS 0x71D58 - -#define SHIM_L2_MECS (SHIM_BASE + 0xd0) - -/** \brief LDO Control */ -#define SHIM_LDOCTL 0xA4 -#define SHIM_LDOCTL_HPSRAM_MASK (3 << 0) -#define SHIM_LDOCTL_LPSRAM_MASK (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) -#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS BIT(2) -#define SHIM_LDOCTL_HPSRAM_LDO_OFF (0 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_OFF (0 << 2) - -#define DSP_INIT_LPGPDMA(x) (0x71A60 + (2*x)) -#define LPGPDMA_CTLOSEL_FLAG BIT(15) -#define LPGPDMA_CHOSEL_FLAG 0xFF - -#define DSP_INIT_IOPO 0x71A68 -#define IOPO_DMIC_FLAG BIT(0) -#define IOPO_I2S_FLAG MASK(DAI_NUM_SSP_BASE + DAI_NUM_SSP_EXT + 7, 8) - -#define DSP_INIT_GENO 0x71A6C -#define GENO_MDIVOSEL BIT(1) -#define GENO_DIOPTOSEL BIT(2) - -#define DSP_INIT_ALHO 0x71A70 -#define ALHO_ASO_FLAG BIT(0) -#define ALHO_CSO_FLAG BIT(1) -#define ALHO_CFO_FLAG BIT(2) - -#define SHIM_SVCFG 0xF4 -#define SHIM_SVCFG_FORCE_L1_EXIT BIT(1) - -/* host windows */ -#define DMWBA(x) (HOST_WIN_BASE(x) + 0x0) -#define DMWLO(x) (HOST_WIN_BASE(x) + 0x4) - -#define DMWBA_ENABLE BIT(0) -#define DMWBA_READONLY BIT(1) - -/* DMIC power ON bit */ -#define DMICLCTL_SPA ((uint32_t) BIT(0)) - -/* DMIC disable clock gating */ -#define DMIC_DCGD ((uint32_t) BIT(30)) - -#ifndef ASSEMBLY - -static inline uint16_t shim_read16(uint16_t reg) -{ - return *((volatile uint16_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write16(uint16_t reg, uint16_t val) -{ - *((volatile uint16_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint64_t shim_read64(uint32_t reg) -{ - return *((volatile uint64_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write64(uint32_t reg, uint64_t val) -{ - *((volatile uint64_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t sw_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)); -} - -static inline void sw_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)) = val; -} - -static inline uint32_t mn_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)(MN_BASE + reg)); -} - -static inline void mn_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(MN_BASE + reg)) = val; -} - -static inline uint32_t irq_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IRQ_BASE + reg)); -} - -static inline void irq_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IRQ_BASE + reg)) = val; -} - -static inline uint32_t ipc_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IPC_HOST_BASE + reg)); -} - -static inline void ipc_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IPC_HOST_BASE + reg)) = val; -} - -static inline uint32_t idc_read(uint32_t reg, uint32_t core_id) -{ - return *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)); -} - -static inline void idc_write(uint32_t reg, uint32_t core_id, uint32_t val) -{ - *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)) = val; -} -#endif - -#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/icelake/include/platform/platform.h b/src/platform/icelake/include/platform/platform.h deleted file mode 100644 index 992e0828ed28..000000000000 --- a/src/platform/icelake/include/platform/platform.h +++ /dev/null @@ -1,117 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - * Xiuli Pan <xiuli.pan@linux.intel.com> - */ - -#ifdef __SOF_PLATFORM_H__ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_RESET_MHE_AT_BOOT 1 - -#define PLATFORM_MEM_INIT_AT_BOOT 1 - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> -#include <stddef.h> -#include <stdint.h> - -struct ll_schedule_domain; -struct timer; - -/*! \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 - -#define MAX_GPDMA_COUNT 2 - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 -#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2 -#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL - -/* 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) - -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 500 - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* minimal L1 exit time in cycles */ -#define PLATFORM_FORCE_L1_EXIT_TIME 985 - -/* the SSP port fifo depth */ -#define SSP_FIFO_DEPTH 16 - -/* the watermark for the SSP fifo depth setting */ -#define SSP_FIFO_WATERMARK 8 - -/* minimal SSP port delay in cycles */ -#define PLATFORM_SSP_DELAY 1600 - -/* Platform defined trace code */ -static inline void platform_panic(uint32_t p) -{ - mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p & 0x3fffffff); - ipc_write(IPC_DIPCIDD, MAILBOX_EXCEPTION_OFFSET + 2 * 0x20000); - ipc_write(IPC_DIPCIDR, 0x80000000 | (p & 0x3fffffff)); -} - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -void platform_wait_for_interrupt(int level); - -extern intptr_t _module_init_start; -extern intptr_t _module_init_end; - -#endif -#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/icelake/include/platform/trace/trace.h b/src/platform/icelake/include/platform/trace/trace.h deleted file mode 100644 index 22a480092132..000000000000 --- a/src/platform/icelake/include/platform/trace/trace.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_TRACE_TRACE_H__ - -#ifndef __PLATFORM_TRACE_TRACE_H__ -#define __PLATFORM_TRACE_TRACE_H__ - -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - mailbox_sw_reg_write(SRAM_REG_FW_TRACEP, (__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/icelake/lib/CMakeLists.txt b/src/platform/icelake/lib/CMakeLists.txt deleted file mode 100644 index 47a1b5962abf..000000000000 --- a/src/platform/icelake/lib/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof clk.c) diff --git a/src/platform/icelake/lib/clk.c b/src/platform/icelake/lib/clk.c deleted file mode 100644 index 276fded135bc..000000000000 --- a/src/platform/icelake/lib/clk.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> - -const struct freq_table platform_cpu_freq[] = { - { 120000000, 120000 }, - { CLK_MAX_CPU_HZ, 400000 }, -}; - -const uint32_t cpu_freq_enc[] = { - SHIM_CLKCTL_RLROSCC | SHIM_CLKCTL_OCS_LP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, - SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_OCS_HP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, -}; - -const uint32_t cpu_freq_status_mask[] = { - SHIM_CLKSTS_LROSCCS, - SHIM_CLKSTS_HROSCCS, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table *cpu_freq = platform_cpu_freq; - -/* IMPORTANT: array should be filled in increasing order - * (regarding to .freq field) - */ -const struct freq_table platform_ssp_freq[] = { - { 24576000, 24576 }, - { 38400000, 38400 }, - { 96000000, 96000 }, -}; - -const uint32_t platform_ssp_freq_sources[] = { - SSP_CLOCK_AUDIO_CARDINAL, - SSP_CLOCK_XTAL_OSCILLATOR, - SSP_CLOCK_PLL_FIXED, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; diff --git a/src/platform/icelake/rom.x.in b/src/platform/icelake/rom.x.in deleted file mode 100644 index d811b63c2c75..000000000000 --- a/src/platform/icelake/rom.x.in +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Linker Script for Apollolake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = ROM_BASE, - len = ROM_RESET_TEXT_SIZE - vector_reset_lit : - org = ROM_BASE + ROM_RESET_TEXT_SIZE, - len = ROM_RESET_LIT_SIZE - vector_base_text : - org = ROM_BASE + ROM_RESET_TEXT_SIZE + ROM_RESET_LIT_SIZE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = ROM_BASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = ROM_BASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = ROM_BASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = ROM_BASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text : - org = ROM_BASE + 0x800, - len = ROM_SIZE, - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; -} - -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = ROM_BASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - /* stack */ - _end = BOOT_LDR_STACK_BASE; - PROVIDE(end = BOOT_LDR_STACK_BASE); - _stack_sentry = BOOT_LDR_STACK_BASE; - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/imx8/imx8.x.in b/src/platform/imx8/imx8.x.in index b8ae0bd21ec0..a178793b84f1 100644 --- a/src/platform/imx8/imx8.x.in +++ b/src/platform/imx8/imx8.x.in @@ -7,7 +7,7 @@ * Use spaces for formatting as cpp ignore tab sizes. */ -#include <config.h> + #include <sof/lib/memory.h> #include <xtensa/config/core-isa.h> @@ -96,6 +96,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -127,6 +130,7 @@ PHDRS sof_stack_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -152,9 +156,19 @@ _memmap_cacheattr_bp_strict = 0x22F22FFF; _memmap_cacheattr_wb_allvalid = 0x44224222; _memmap_cacheattr_wt_allvalid = 0x11221222; _memmap_cacheattr_bp_allvalid = 0x22222222; +/* + * Every 512M in 4GB space has dedicate cache attribute. + * 1: write through + * 2: cache bypass + * 4: write back + * F: invalid access + */ _memmap_cacheattr_imx8_wt_allvalid = 0x22212222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_imx8_wt_allvalid); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -325,7 +339,7 @@ SECTIONS .module_init : ALIGN(4) { _module_init_start = ABSOLUTE(.); - *(*.module_init) + *(*.initcall) _module_init_end = ABSOLUTE(.); } >sof_sdram0 :sof_sdram0_phdr @@ -367,6 +381,9 @@ SECTIONS *(.sdata2.*) *(.gnu.linkonce.s2.*) KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); _data_end = ABSOLUTE(.); } >sof_sdram0 :sof_sdram0_phdr @@ -512,4 +529,10 @@ SECTIONS KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_sdram0 :sof_sdram0_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/imx8/include/platform/drivers/idc.h b/src/platform/imx8/include/platform/drivers/idc.h index 6d1a4186a2f6..f85abef65924 100644 --- a/src/platform/imx8/include/platform/drivers/idc.h +++ b/src/platform/imx8/include/platform/drivers/idc.h @@ -5,7 +5,7 @@ * Author: Daniel Baluta <daniel.baluta@nxp.com> */ -#ifdef __SOF_DRIVERS_IDC_H__ +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) #ifndef __PLATFORM_DRIVERS_IDC_H__ #define __PLATFORM_DRIVERS_IDC_H__ @@ -23,6 +23,6 @@ static inline int idc_init(void) { return 0; } #else -#error "This file shouldn't be included from outside of sof/drivers/idc.h" +#error "This file shouldn't be included from outside of Zepyhr/XTOS's rtos/idc.h" -#endif /* __SOF_DRIVERS_IDC_H__ */ +#endif diff --git a/src/platform/imx8/include/platform/drivers/interrupt.h b/src/platform/imx8/include/platform/drivers/interrupt.h index 28d4ba97ff95..d18af631df26 100644 --- a/src/platform/imx8/include/platform/drivers/interrupt.h +++ b/src/platform/imx8/include/platform/drivers/interrupt.h @@ -10,11 +10,10 @@ #ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ #define __PLATFORM_DRIVERS_INTERRUPT_H__ -#include <sof/bit.h> -#include <config.h> +#include <rtos/bit.h> /* IRQ numbers */ -#if CONFIG_INTERRUPT_LEVEL_1 +#if CONFIG_XT_INTERRUPT_LEVEL_1 #define IRQ_NUM_SOFTWARE0 8 /* Level 1 */ @@ -22,7 +21,7 @@ #endif -#if CONFIG_INTERRUPT_LEVEL_2 +#if CONFIG_XT_INTERRUPT_LEVEL_2 #define IRQ_NUM_TIMER0 2 /* Level 2 */ #define IRQ_NUM_MU 7 /* Level 2 */ @@ -50,7 +49,7 @@ #endif -#if CONFIG_INTERRUPT_LEVEL_3 +#if CONFIG_XT_INTERRUPT_LEVEL_3 #define IRQ_NUM_TIMER1 3 /* Level 3 */ diff --git a/src/platform/imx8/include/platform/lib/clk.h b/src/platform/imx8/include/platform/lib/clk.h index d581aa1c504e..6d52972da9e5 100644 --- a/src/platform/imx8/include/platform/lib/clk.h +++ b/src/platform/imx8/include/platform/lib/clk.h @@ -18,8 +18,13 @@ struct sof; #define CPU_DEFAULT_IDX 0 +#ifdef CONFIG_IMX8 #define CLK_DEFAULT_CPU_HZ 666000000 #define CLK_MAX_CPU_HZ 666000000 +#else /* CONFIG_IMX8X */ +#define CLK_DEFAULT_CPU_HZ 640000000 +#define CLK_MAX_CPU_HZ 640000000 +#endif #define NUM_CLOCKS 1 diff --git a/src/platform/imx8/include/platform/lib/cpu.h b/src/platform/imx8/include/platform/lib/cpu.h index a03e856ed8cc..2c7124c5b0dd 100644 --- a/src/platform/imx8/include/platform/lib/cpu.h +++ b/src/platform/imx8/include/platform/lib/cpu.h @@ -6,7 +6,7 @@ */ /** - * \file platform/lib/cpu.h + * \file * \brief DSP core parameters. */ @@ -15,16 +15,8 @@ #ifndef __PLATFORM_LIB_CPU_H__ #define __PLATFORM_LIB_CPU_H__ -#include <config.h> - -/** \brief Number of available DSP cores (conf. by kconfig) */ -#define PLATFORM_CORE_COUNT CONFIG_CORE_COUNT - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 1 - -/** \brief Id of master DSP core */ -#define PLATFORM_MASTER_CORE_ID 0 +/** \brief Id of primary DSP core */ +#define PLATFORM_PRIMARY_CORE_ID 0 #endif /* __PLATFORM_LIB_CPU_H__ */ diff --git a/src/platform/imx8/include/platform/lib/memory.h b/src/platform/imx8/include/platform/lib/memory.h index 2169130766e9..1c3d88fe4d4d 100644 --- a/src/platform/imx8/include/platform/lib/memory.h +++ b/src/platform/imx8/include/platform/lib/memory.h @@ -10,11 +10,10 @@ #ifndef __PLATFORM_LIB_MEMORY_H__ #define __PLATFORM_LIB_MEMORY_H__ -#include <sof/lib/cache.h> -#include <config.h> +#include <rtos/cache.h> /* data cache line alignment */ -#define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE +#define PLATFORM_DCACHE_ALIGN 32 /* physical DSP addresses */ @@ -51,6 +50,9 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The Heap and Stack on i.MX8 are organised like this :- * @@ -109,7 +111,7 @@ #define HEAP_RT_COUNT64 32 #define HEAP_RT_COUNT128 32 #define HEAP_RT_COUNT256 32 -#define HEAP_RT_COUNT512 4 +#define HEAP_RT_COUNT512 32 #define HEAP_RT_COUNT1024 4 #define HEAP_RT_COUNT2048 4 @@ -152,7 +154,7 @@ #define PLATFORM_HEAP_BUFFER 1 /* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) #define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE #define SOF_STACK_BASE (SDRAM1_BASE + SDRAM1_SIZE) #define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) @@ -168,7 +170,7 @@ #define SOF_MEM_RO_SIZE 0x8 -#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE /** \brief EDF task's default stack size in bytes. */ #define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 @@ -190,6 +192,11 @@ static inline void *platform_shared_get(void *ptr, int bytes) return ptr; } +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + /** * \brief Function for keeping shared data synchronized. * It's used after usage of data shared by different cores. @@ -197,7 +204,6 @@ static inline void *platform_shared_get(void *ptr, int bytes) * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. * Does nothing, since IMX doesn't support SMP. */ -static inline void platform_shared_commit(void *ptr, int bytes) { } static inline void *platform_rfree_prepare(void *ptr) { @@ -206,6 +212,9 @@ static inline void *platform_rfree_prepare(void *ptr) #endif +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + #endif /* __PLATFORM_LIB_MEMORY_H__ */ #else diff --git a/src/platform/imx8/include/platform/lib/pm_runtime.h b/src/platform/imx8/include/platform/lib/pm_runtime.h deleted file mode 100644 index f2b85b2e9d4e..000000000000 --- a/src/platform/imx8/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2019 NXP - * - * Author: Daniel Baluta <daniel.baluta@nxp.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <stdint.h> - -struct pm_runtime_data; - -/** - * \brief Initializes platform specific runtime power management. - * \param[in,out] prd Runtime power management data. - */ -static inline 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_... - */ -static inline 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_... - */ -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/imx8/include/platform/platform.h b/src/platform/imx8/include/platform/platform.h index 4314a1cd0b72..a0a498d667d1 100644 --- a/src/platform/imx8/include/platform/platform.h +++ b/src/platform/imx8/include/platform/platform.h @@ -12,9 +12,7 @@ #if !defined(__ASSEMBLER__) && !defined(LINKER) -#include <arch/lib/wait.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> +#include <sof/drivers/mu.h> #include <sof/lib/mailbox.h> #include <stddef.h> #include <stdint.h> @@ -26,7 +24,7 @@ struct timer; #define LPSRAM_SIZE 16384 /* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU +#define PLATFORM_IPC_INTERRUPT 7 #define PLATFORM_IPC_INTERRUPT_NAME NULL /* Host page size */ @@ -59,9 +57,19 @@ struct timer; /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 +#define SRAM_REG_FW_STATUS 0x4 + /* Platform defined panic code */ static inline void platform_panic(uint32_t p) { + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); } /** @@ -69,10 +77,7 @@ static inline void platform_panic(uint32_t p) * May be power-optimized using platform specific capabilities. * @param level Interrupt level. */ -static inline void platform_wait_for_interrupt(int level) -{ - arch_wait_for_interrupt(level); -} +void platform_wait_for_interrupt(int level); extern intptr_t _module_init_start; extern intptr_t _module_init_end; diff --git a/src/platform/imx8/lib/clk.c b/src/platform/imx8/lib/clk.c index 31903e25e8f6..45edfe98461d 100644 --- a/src/platform/imx8/lib/clk.c +++ b/src/platform/imx8/lib/clk.c @@ -6,15 +6,19 @@ // Janusz Jankowski <janusz.jankowski@linux.intel.com> #include <sof/common.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> +#include <rtos/clk.h> #include <sof/lib/memory.h> #include <sof/lib/notifier.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> + +#include <zephyr/sys/util.h> const struct freq_table platform_cpu_freq[] = { +#ifdef CONFIG_IMX8 { 666000000, 666000 }, +#else /* CONFIG_IMX8X */ + { 640000000, 640000 }, +#endif }; STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), @@ -26,9 +30,9 @@ void platform_clock_init(struct sof *sof) { int i; - sof->clocks = platform_clocks_info; + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { + for (i = 0; i < CONFIG_CORE_COUNT; i++) { sof->clocks[i] = (struct clock_info) { .freqs_num = NUM_CPU_FREQ, .freqs = platform_cpu_freq, @@ -38,9 +42,5 @@ void platform_clock_init(struct sof *sof) .notification_mask = NOTIFIER_TARGET_CORE_MASK(i), .set_freq = NULL, }; - - spinlock_init(&sof->clocks[i].lock); } - - platform_shared_commit(sof->clocks, sizeof(*sof->clocks) * NUM_CLOCKS); } diff --git a/src/platform/imx8/lib/dai.c b/src/platform/imx8/lib/dai.c index e4766fba1f7c..69366cf18d3f 100644 --- a/src/platform/imx8/lib/dai.c +++ b/src/platform/imx8/lib/dai.c @@ -10,8 +10,8 @@ #include <sof/drivers/sai.h> #include <sof/lib/dai.h> #include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> #include <ipc/dai.h> #include <ipc/stream.h> @@ -24,13 +24,15 @@ static SHARED_DATA struct dai esai[] = { .offset = ESAI_BASE + REG_ESAI_ETDR, .depth = 96, /* in 4 bytes words */ .handshake = EDMA_HANDSHAKE(EDMA_ESAI_IRQ, - EDMA_ESAI_TX_CHAN), + EDMA_ESAI_TX_CHAN, + 0), }, .fifo[SOF_IPC_STREAM_CAPTURE] = { .offset = ESAI_BASE + REG_ESAI_ERDR, .depth = 96, /* in 4 bytes words */ .handshake = EDMA_HANDSHAKE(EDMA_ESAI_IRQ, - EDMA_ESAI_RX_CHAN), + EDMA_ESAI_RX_CHAN, + 0), }, }, .drv = &esai_driver, @@ -50,14 +52,18 @@ static SHARED_DATA struct dai sai[] = { * Receive Data Registers */ .depth = 64, /* in 4 bytes words */ + .watermark = 32, /* half the depth */ .handshake = EDMA_HANDSHAKE(EDMA0_SAI_CHAN_TX_IRQ, - EDMA0_SAI_CHAN_TX), + EDMA0_SAI_CHAN_TX, + 0), }, .fifo[SOF_IPC_STREAM_CAPTURE] = { .offset = SAI_1_BASE + REG_SAI_RDR0, .depth = 64, /* in 4 bytes words */ + .watermark = 32, /* half the depth */ .handshake = EDMA_HANDSHAKE(EDMA0_SAI_CHAN_RX_IRQ, - EDMA0_SAI_CHAN_RX), + EDMA0_SAI_CHAN_RX, + 0), }, }, .drv = &sai_driver, @@ -67,12 +73,12 @@ static SHARED_DATA struct dai sai[] = { const struct dai_type_info dti[] = { { .type = SOF_DAI_IMX_SAI, - .dai_array = sai, + .dai_array = cache_to_uncache_init((struct dai *)sai), .num_dais = ARRAY_SIZE(sai) }, { .type = SOF_DAI_IMX_ESAI, - .dai_array = esai, + .dai_array = cache_to_uncache_init((struct dai *)esai), .num_dais = ARRAY_SIZE(esai) }, }; @@ -88,14 +94,10 @@ int dai_init(struct sof *sof) /* initialize spin locks early to enable ref counting */ for (i = 0; i < ARRAY_SIZE(esai); i++) - spinlock_init(&esai[i].lock); - - platform_shared_commit(esai, sizeof(*esai)); + k_spinlock_init(&dti[1].dai_array[i].lock); for (i = 0; i < ARRAY_SIZE(sai); i++) - spinlock_init(&sai[i].lock); - - platform_shared_commit(sai, sizeof(*sai)); + k_spinlock_init(&dti[0].dai_array[i].lock); sof->dai_info = &lib_dai; diff --git a/src/platform/imx8/lib/dma.c b/src/platform/imx8/lib/dma.c index 77e745653b40..e5a40d251557 100644 --- a/src/platform/imx8/lib/dma.c +++ b/src/platform/imx8/lib/dma.c @@ -6,28 +6,28 @@ #include <sof/common.h> #include <sof/drivers/edma.h> -#include <sof/drivers/interrupt.h> +#include <rtos/interrupt.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> extern struct dma_ops dummy_dma_ops; extern struct dma_ops edma_ops; -const int edma0_ints[EDMA0_CHAN_MAX] = { +static const int edma0_ints[EDMA0_CHAN_MAX] = { [EDMA0_ESAI_CHAN_RX] = EDMA0_ESAI_CHAN_RX_IRQ, [EDMA0_ESAI_CHAN_TX] = EDMA0_ESAI_CHAN_TX_IRQ, [EDMA0_SAI_CHAN_RX] = EDMA0_SAI_CHAN_RX_IRQ, [EDMA0_SAI_CHAN_TX] = EDMA0_SAI_CHAN_TX_IRQ, }; -SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { { .plat_data = { .id = DMA_ID_EDMA0, - .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, - .devs = DMA_DEV_ESAI | DMA_DEV_SAI, + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_ESAI | SOF_DMA_DEV_SAI, .base = EDMA0_BASE, .chan_size = EDMA0_SIZE, .channels = 32, @@ -38,16 +38,16 @@ SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { { .plat_data = { .id = DMA_ID_HOST, - .dir = DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, - .devs = DMA_DEV_HOST, + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, .channels = 16, }, .ops = &dummy_dma_ops, }, }; -const struct dma_info lib_dma = { - .dma_array = dma, +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)dma), .num_dmas = ARRAY_SIZE(dma) }; @@ -57,9 +57,7 @@ int dmac_init(struct sof *sof) /* early lock initialization for ref counting */ for (i = 0; i < ARRAY_SIZE(dma); i++) - spinlock_init(&dma[i].lock); - - platform_shared_commit(dma, sizeof(*dma)); + k_spinlock_init(&dma[i].lock); sof->dma_info = &lib_dma; diff --git a/src/platform/imx8/lib/memory.c b/src/platform/imx8/lib/memory.c index 98b2af98eff8..78cb05c86cbb 100644 --- a/src/platform/imx8/lib/memory.c +++ b/src/platform/imx8/lib/memory.c @@ -5,10 +5,10 @@ // Author: Daniel Baluta <daniel.baluta@nxp.com> #include <sof/common.h> -#include <sof/lib/alloc.h> +#include <sof/lib/mm_heap.h> #include <sof/lib/memory.h> #include <sof/platform.h> -#include <sof/sof.h> +#include <rtos/sof.h> #include <ipc/topology.h> /* Heap blocks for system runtime */ @@ -95,5 +95,5 @@ static SHARED_DATA struct mm memmap = { void platform_init_memmap(struct sof *sof) { /* memmap has been initialized statically as a part of .data */ - sof->memory_map = &memmap; + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); } diff --git a/src/platform/imx8/platform.c b/src/platform/imx8/platform.c index bf4728377d34..50d6bb4f4ac6 100644 --- a/src/platform/imx8/platform.c +++ b/src/platform/imx8/platform.c @@ -4,34 +4,15 @@ // // Author: Daniel Baluta <daniel.baluta@nxp.com> -#include <sof/compiler_info.h> #include <sof/debug/debug.h> -#include <sof/drivers/edma.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/mu.h> -#include <sof/drivers/timer.h> -#include <sof/fw-ready-metadata.h> -#include <sof/lib/agent.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> #include <sof/lib/dai.h> #include <sof/lib/dma.h> -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> -#include <sof/platform.h> #include <sof/schedule/edf_schedule.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/ll_schedule_domain.h> -#include <sof/sof.h> -#include <sof/trace/dma-trace.h> -#include <ipc/dai.h> -#include <ipc/header.h> -#include <ipc/info.h> #include <kernel/abi.h> -#include <version.h> -#include <errno.h> -#include <stdint.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> struct sof; @@ -47,105 +28,91 @@ static const struct sof_ipc_fw_ready ready .micro = SOF_MICRO, .minor = SOF_MINOR, .major = SOF_MAJOR, -#ifdef DEBUG_BUILD - /* only added in debug for reproducability in releases */ - .build = SOF_BUILD, +/* opt-in; reproducible build by default */ +#if BLD_COUNTERS + .build = SOF_BUILD, /* See version-build-counter.cmake */ .date = __DATE__, .time = __TIME__, +#else + .build = -1, + .date = "dtermin.\0", + .time = "fwready.\0", #endif .tag = SOF_TAG, .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, }, .flags = DEBUG_SET_FW_READY_FLAGS, }; #define NUM_IMX_WINDOWS 6 -static const struct sof_ipc_window sram_window - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_window) + - sizeof(struct sof_ipc_window_elem) * NUM_IMX_WINDOWS, - .type = SOF_IPC_EXT_WINDOW, +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), }, - .num_windows = NUM_IMX_WINDOWS, - .window = { - { - .type = SOF_IPC_REGION_UPBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DSPBOX_SIZE, - .offset = MAILBOX_DSPBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DOWNBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_HOSTBOX_SIZE, - .offset = MAILBOX_HOSTBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DEBUG, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DEBUG_SIZE, - .offset = MAILBOX_DEBUG_OFFSET, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, }, - { - .type = SOF_IPC_REGION_TRACE, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_TRACE_SIZE, - .offset = MAILBOX_TRACE_OFFSET, + .num_windows = NUM_IMX_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, }, - { - .type = SOF_IPC_REGION_STREAM, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_STREAM_SIZE, - .offset = MAILBOX_STREAM_OFFSET, - }, - { - .type = SOF_IPC_REGION_EXCEPTION, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_EXCEPTION_SIZE, - .offset = MAILBOX_EXCEPTION_OFFSET, - }, - }, -}; - -SHARED_DATA struct timer timer = { - .id = TIMER0, /* internal timer */ - .irq = IRQ_NUM_TIMER0, + } }; int platform_boot_complete(uint32_t boot_message) { - uint32_t mb_offset = 0; - - mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); - mb_offset = mb_offset + sizeof(ready); - - mailbox_dspbox_write(mb_offset, &sram_window, - sram_window.ext_hdr.hdr.size); - mb_offset = mb_offset + sram_window.ext_hdr.hdr.size; - - /* variable length compiler description is a last field of cc_version */ - mailbox_dspbox_write(mb_offset, &cc_version, - cc_version.ext_hdr.hdr.size); - mb_offset = mb_offset + cc_version.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &probe_support, - probe_support.ext_hdr.hdr.size); - mb_offset = mb_offset + probe_support.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &user_abi_version, - user_abi_version.ext_hdr.hdr.size); + mailbox_dspbox_write(0, &ready, sizeof(ready)); /* now interrupt host to tell it we are done booting */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); /* boot now complete so we can relax the CPU */ /* For now skip this to gain more processing performance @@ -160,22 +127,14 @@ int platform_init(struct sof *sof) { int ret; - sof->platform_timer = &timer; - sof->cpu_timer = &timer; - - platform_interrupt_init(); platform_clock_init(sof); scheduler_init_edf(); /* init low latency domains and schedulers */ sof->platform_timer_domain = - timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK, - CONFIG_SYSTICK_PERIOD); + timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); scheduler_init_ll(sof->platform_timer_domain); - platform_timer_start(sof->platform_timer); - sa_init(sof, CONFIG_SYSTICK_PERIOD); - clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); /* init DMA */ @@ -183,12 +142,6 @@ int platform_init(struct sof *sof) if (ret < 0) return -ENODEV; - /* Init EDMA platform domain */ - sof->platform_dma_domain = dma_multi_chan_domain_init - (&sof->dma_info->dma_array[0], 1, - PLATFORM_DEFAULT_CLOCK, false); - scheduler_init_ll(sof->platform_dma_domain); - /* initialize the host IPC mechanims */ ipc_init(sof); @@ -196,14 +149,10 @@ int platform_init(struct sof *sof) if (ret < 0) return -ENODEV; -#if CONFIG_TRACE - /* Initialize DMA for Trace*/ - trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); - dma_trace_init_complete(sof->dmat); -#endif - - /* show heap status */ - heap_trace_all(1); + return 0; +} +int platform_context_save(struct sof *sof) +{ return 0; } diff --git a/src/platform/imx8m/imx8m.x.in b/src/platform/imx8m/imx8m.x.in index 5652d28bb637..8c90dd919b02 100644 --- a/src/platform/imx8m/imx8m.x.in +++ b/src/platform/imx8m/imx8m.x.in @@ -7,7 +7,7 @@ * Use spaces for formatting as cpp ignore tab sizes. */ -#include <config.h> + #include <sof/lib/memory.h> #include <xtensa/config/core-isa.h> @@ -96,6 +96,9 @@ MEMORY static_log_entries_seg (!ari) : org = LOG_ENTRY_ELF_BASE, len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE } PHDRS @@ -127,6 +130,7 @@ PHDRS sof_stack_phdr PT_LOAD; static_uuid_entries_phdr PT_NOTE; static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; } /* Default entry point: */ @@ -152,9 +156,19 @@ _memmap_cacheattr_bp_strict = 0x22F22FFF; _memmap_cacheattr_wb_allvalid = 0x44224222; _memmap_cacheattr_wt_allvalid = 0x11221222; _memmap_cacheattr_bp_allvalid = 0x22222222; +/* + * Every 512M in 4GB space has dedicate cache attribute. + * 1: write through + * 2: cache bypass + * 4: write back + * F: invalid access + */ _memmap_cacheattr_imx8_wt_allvalid = 0x22212222; PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_imx8_wt_allvalid); +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + SECTIONS { .ResetVector.text : ALIGN(4) @@ -325,7 +339,7 @@ SECTIONS .module_init : ALIGN(4) { _module_init_start = ABSOLUTE(.); - *(*.module_init) + *(*.initcall) _module_init_end = ABSOLUTE(.); } >sof_sdram0 :sof_sdram0_phdr @@ -367,6 +381,9 @@ SECTIONS *(.sdata2.*) *(.gnu.linkonce.s2.*) KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); _data_end = ABSOLUTE(.); } >sof_sdram0 :sof_sdram0_phdr @@ -512,4 +529,10 @@ SECTIONS KEEP (*(.fw_ready)) KEEP (*(.fw_ready_metadata)) } >sof_sdram0 :sof_sdram0_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr } diff --git a/src/platform/imx8m/include/platform/drivers/idc.h b/src/platform/imx8m/include/platform/drivers/idc.h index 0af0df542fa3..0352e459a715 100644 --- a/src/platform/imx8m/include/platform/drivers/idc.h +++ b/src/platform/imx8m/include/platform/drivers/idc.h @@ -5,7 +5,7 @@ * Author: Daniel Baluta <daniel.baluta@nxp.com> */ -#ifdef __SOF_DRIVERS_IDC_H__ +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) #ifndef __PLATFORM_DRIVERS_IDC_H__ #define __PLATFORM_DRIVERS_IDC_H__ @@ -23,6 +23,6 @@ static inline int idc_init(void) { return 0; } #else -#error "This file shouldn't be included from outside of sof/drivers/idc.h" +#error "This file shouldn't be included from outside of Zephyr/XTOS's rtos/idc.h" -#endif /* __SOF_DRIVERS_IDC_H__ */ +#endif diff --git a/src/platform/imx8m/include/platform/drivers/interrupt.h b/src/platform/imx8m/include/platform/drivers/interrupt.h index 227494aa7fa7..88fbe20eacc7 100644 --- a/src/platform/imx8m/include/platform/drivers/interrupt.h +++ b/src/platform/imx8m/include/platform/drivers/interrupt.h @@ -10,11 +10,11 @@ #ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ #define __PLATFORM_DRIVERS_INTERRUPT_H__ -#include <sof/bit.h> -#include <config.h> +#include <rtos/bit.h> + /* IRQ numbers */ -#if CONFIG_INTERRUPT_LEVEL_1 +#if CONFIG_XT_INTERRUPT_LEVEL_1 #define IRQ_NUM_SOFTWARE0 8 /* Level 1 */ @@ -22,7 +22,7 @@ #endif -#if CONFIG_INTERRUPT_LEVEL_2 +#if CONFIG_XT_INTERRUPT_LEVEL_2 #define IRQ_NUM_TIMER0 2 /* Level 2 */ #define IRQ_NUM_MU 7 /* Level 2 */ @@ -50,7 +50,7 @@ #endif -#if CONFIG_INTERRUPT_LEVEL_3 +#if CONFIG_XT_INTERRUPT_LEVEL_3 #define IRQ_NUM_TIMER1 3 /* Level 3 */ @@ -72,7 +72,7 @@ * SOF internal interrupt numbers exactly; rather IRQ_STEER interrupt 0 will be * known as interrupt number 32 within SOF. */ -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM +#define PLATFORM_IRQ_FIRST_CHILD 0 /* irqstr_get_sof_int() - Convert IRQ_STEER interrupt to SOF logical * interrupt @@ -105,15 +105,16 @@ int irqstr_get_sof_int(int irqstr_int); */ #define IRQSTR_CHANCTL 0x00 -#define IRQSTR_CH_MASK(n) (0x04 + 0x04 * (5 - (n))) -#define IRQSTR_CH_SET(n) (0x18 + 0x04 * (5 - (n))) -#define IRQSTR_CH_STATUS(n) (0x2C + 0x04 * (5 - (n))) +#define IRQSTR_CH_MASK(n) (0x04 + 0x04 * (4 - (n))) +#define IRQSTR_CH_SET(n) (0x18 + 0x04 * (4 - (n))) +#define IRQSTR_CH_STATUS(n) (0x2C + 0x04 * (4 - (n))) + #define IRQSTR_MASTER_DISABLE 0x40 #define IRQSTR_MASTER_STATUS 0x44 #define IRQSTR_RESERVED_IRQS_NUM 32 #define IRQSTR_IRQS_NUM 192 -#define IRQSTR_IRQS_REGISTERS_NUM 6 +#define IRQSTR_IRQS_REGISTERS_NUM 5 #define IRQSTR_IRQS_PER_LINE 64 #endif /* __PLATFORM_DRIVERS_INTERRUPT_H__ */ diff --git a/src/platform/imx8m/include/platform/lib/cpu.h b/src/platform/imx8m/include/platform/lib/cpu.h index 4bcfec2f3717..7e83ff1ee7a1 100644 --- a/src/platform/imx8m/include/platform/lib/cpu.h +++ b/src/platform/imx8m/include/platform/lib/cpu.h @@ -6,7 +6,7 @@ */ /** - * \file platform/lib/cpu.h + * \file * \brief DSP core parameters. */ @@ -15,16 +15,8 @@ #ifndef __PLATFORM_LIB_CPU_H__ #define __PLATFORM_LIB_CPU_H__ -#include <config.h> - -/** \brief Number of available DSP cores (conf. by kconfig) */ -#define PLATFORM_CORE_COUNT CONFIG_CORE_COUNT - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 1 - -/** \brief Id of master DSP core */ -#define PLATFORM_MASTER_CORE_ID 0 +/** \brief Id of primary DSP core */ +#define PLATFORM_PRIMARY_CORE_ID 0 #endif /* __PLATFORM_LIB_CPU_H__ */ diff --git a/src/platform/imx8m/include/platform/lib/dma.h b/src/platform/imx8m/include/platform/lib/dma.h index cc2dffa6bbfd..e5cc5a137f6e 100644 --- a/src/platform/imx8m/include/platform/lib/dma.h +++ b/src/platform/imx8m/include/platform/lib/dma.h @@ -17,6 +17,7 @@ #define DMA_ID_SDMA2 0 #define DMA_ID_HOST 1 +#define DMA_ID_SDMA3 2 #define dma_chan_irq(dma, chan) dma_irq(dma) #define dma_chan_irq_name(dma, chan) dma_irq_name(dma) @@ -31,7 +32,18 @@ * IRQ_STEER driver interacts with SOF. */ #define SDMA2_IRQ 7 -#define SDMA2_IRQ_NAME "irqstr2" +#define SDMA2_IRQ_NAME "irqsteer2" + +/* SDMA3 specific data */ + +/* Hardware interrupt at the input of irqsteer for SDMA3_IRQ is 34. In + * order to map it inside the IRQSTEER we must add 32. So inside + * irqsteer SDMA2 interrupt will be 32 + 34 = 66. Next is to map it + * to an irqsteer child 66 % 64 = 1 and reminder 2. This means the + * interrupt is mapped to irqsteer1 and has the index 2. + */ +#define SDMA3_IRQ 2 +#define SDMA3_IRQ_NAME "irqsteer1" #define SDMA_CORE_RATIO 1/* Enable ACR bit as it's needed for this platform */ diff --git a/src/platform/imx8m/include/platform/lib/memory.h b/src/platform/imx8m/include/platform/lib/memory.h index 8de989da9ac7..6b2c00f89bad 100644 --- a/src/platform/imx8m/include/platform/lib/memory.h +++ b/src/platform/imx8m/include/platform/lib/memory.h @@ -10,11 +10,10 @@ #ifndef __PLATFORM_LIB_MEMORY_H__ #define __PLATFORM_LIB_MEMORY_H__ -#include <sof/lib/cache.h> -#include <config.h> +#include <rtos/cache.h> /* data cache line alignment */ -#define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE +#define PLATFORM_DCACHE_ALIGN 32 /* physical DSP addresses */ @@ -39,15 +38,39 @@ #define SDMA2_BASE 0x30e10000 #define SDMA2_SIZE 0x10000 +#define SDMA3_BASE 0x30e00000 +#define SDMA3_SIZE 0x10000 + +#define SAI_1_BASE 0x30c10000 +#define SAI_1_SIZE 0x00010000 + +#define SAI_2_BASE 0x30c20000 +#define SAI_2_SIZE 0x00010000 + #define SAI_3_BASE 0x30c30000 #define SAI_3_SIZE 0x00010000 +#define SAI_5_BASE 0x30c50000 +#define SAI_5_SIZE 0x00010000 + +#define SAI_6_BASE 0x30c60000 +#define SAI_6_SIZE 0x00010000 + +#define SAI_7_BASE 0x30c80000 +#define SAI_7_SIZE 0x00010000 + +#define MICFIL_BASE 0x30ca0000 +#define MICFIL_SIZE 0x00010000 + #define UUID_ENTRY_ELF_BASE 0x1FFFA000 #define UUID_ENTRY_ELF_SIZE 0x6000 #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The Heap and Stack on i.MX8M are organised like this :- * @@ -106,7 +129,7 @@ #define HEAP_RT_COUNT64 32 #define HEAP_RT_COUNT128 32 #define HEAP_RT_COUNT256 32 -#define HEAP_RT_COUNT512 4 +#define HEAP_RT_COUNT512 32 #define HEAP_RT_COUNT1024 4 #define HEAP_RT_COUNT2048 4 #define HEAP_RT_COUNT4096 4 @@ -150,7 +173,7 @@ #define PLATFORM_HEAP_BUFFER 1 /* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) #define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE #define SOF_STACK_BASE (SDRAM1_BASE + SDRAM1_SIZE) #define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) @@ -166,7 +189,7 @@ #define SOF_MEM_RO_SIZE 0x8 -#define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE /** \brief EDF task's default stack size in bytes. */ #define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 @@ -183,6 +206,11 @@ struct sof; void platform_init_memmap(struct sof *sof); +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + static inline void *platform_shared_get(void *ptr, int bytes) { return ptr; @@ -196,8 +224,6 @@ static inline void *platform_shared_get(void *ptr, int bytes) * Does nothing, since IMX doesn't support SMP. */ -static inline void platform_shared_commit(void *ptr, int bytes) { } - static inline void *platform_rfree_prepare(void *ptr) { return ptr; @@ -205,6 +231,9 @@ static inline void *platform_rfree_prepare(void *ptr) #endif +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + #endif /* __PLATFORM_LIB_MEMORY_H__ */ #else diff --git a/src/platform/imx8m/include/platform/platform.h b/src/platform/imx8m/include/platform/platform.h index 7451d89f8897..0b4bf87e8eb5 100644 --- a/src/platform/imx8m/include/platform/platform.h +++ b/src/platform/imx8m/include/platform/platform.h @@ -12,9 +12,7 @@ #if !defined(__ASSEMBLER__) && !defined(LINKER) -#include <arch/lib/wait.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> +#include <rtos/clk.h> #include <sof/lib/mailbox.h> #include <stddef.h> #include <stdint.h> @@ -26,7 +24,7 @@ struct timer; #define LPSRAM_SIZE 16384 /* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_NUM_MU +#define PLATFORM_IPC_INTERRUPT 7 #define PLATFORM_IPC_INTERRUPT_NAME NULL /* Host page size */ @@ -37,9 +35,13 @@ struct timer; #define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 #define PLATFORM_SCHEDULE_IRQ_NAME NULL -/* Platform stream capabilities */ -#define PLATFORM_MAX_CHANNELS 4 -#define PLATFORM_MAX_STREAMS 5 +/* + * Platform stream capabilities + * MAX_CHANNELS only affects 'components' so it is, for example, + * still possible to have multiple SAI peripherals output 8 channels each. + */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 8 /* local buffer size of DMA tracing */ #define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE @@ -69,10 +71,7 @@ static inline void platform_panic(uint32_t p) * May be power-optimized using platform specific capabilities. * @param level Interrupt level. */ -static inline void platform_wait_for_interrupt(int level) -{ - arch_wait_for_interrupt(level); -} +void platform_wait_for_interrupt(int level); extern intptr_t _module_init_start; extern intptr_t _module_init_end; diff --git a/src/platform/imx8m/lib/clk.c b/src/platform/imx8m/lib/clk.c index 95a647bcba9c..37b115e507a2 100644 --- a/src/platform/imx8m/lib/clk.c +++ b/src/platform/imx8m/lib/clk.c @@ -5,12 +5,12 @@ // Author: Daniel Baluta <daniel.baluta@nxp.com> #include <sof/common.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> +#include <rtos/clk.h> #include <sof/lib/memory.h> #include <sof/lib/notifier.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> + +#include <zephyr/sys/util.h> const struct freq_table platform_cpu_freq[] = { { 800000000, 800000 }, @@ -25,9 +25,9 @@ void platform_clock_init(struct sof *sof) { int i; - sof->clocks = platform_clocks_info; + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { + for (i = 0; i < CONFIG_CORE_COUNT; i++) { sof->clocks[i] = (struct clock_info) { .freqs_num = NUM_CPU_FREQ, .freqs = platform_cpu_freq, @@ -37,9 +37,5 @@ void platform_clock_init(struct sof *sof) .notification_mask = NOTIFIER_TARGET_CORE_MASK(i), .set_freq = NULL, }; - - spinlock_init(&sof->clocks[i].lock); } - - platform_shared_commit(sof->clocks, sizeof(*sof->clocks) * NUM_CLOCKS); } diff --git a/src/platform/imx8m/lib/dai.c b/src/platform/imx8m/lib/dai.c index fb39b1dafc9c..1293cdc6fd7f 100644 --- a/src/platform/imx8m/lib/dai.c +++ b/src/platform/imx8m/lib/dai.c @@ -6,40 +6,176 @@ #include <sof/common.h> #include <sof/drivers/sai.h> +#include <sof/drivers/micfil.h> + #include <sof/lib/dai.h> #include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> #include <ipc/dai.h> #include <ipc/stream.h> static SHARED_DATA struct dai sai[] = { +{ + .index = 1, + .plat_data = { + .base = SAI_1_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_1_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 1, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_1_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 0, + }, + }, + .drv = &sai_driver, +}, + +{ + .index = 2, + .plat_data = { + .base = SAI_2_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_2_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 3, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_2_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 2, + }, + }, + .drv = &sai_driver, +}, + { .index = 3, .plat_data = { .base = SAI_3_BASE, .fifo[SOF_IPC_STREAM_PLAYBACK] = { .offset = SAI_3_BASE + REG_SAI_TDR0, - .depth = 16, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ /* Handshake is SDMA hardware event */ .handshake = 5, }, .fifo[SOF_IPC_STREAM_CAPTURE] = { .offset = SAI_3_BASE + REG_SAI_RDR0, - .depth = 16, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ .handshake = 4, }, }, .drv = &sai_driver, }, + +{ + .index = 5, + .plat_data = { + .base = SAI_5_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_5_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 9, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_5_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 8, + }, + }, + .drv = &sai_driver, +}, + +{ + .index = 6, + .plat_data = { + .base = SAI_6_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_6_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 11, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_6_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 10, + }, + }, + .drv = &sai_driver, +}, + +{ + .index = 7, + .plat_data = { + .base = SAI_7_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_7_BASE + REG_SAI_TDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + /* Handshake is SDMA hardware event */ + .handshake = 13, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_7_BASE + REG_SAI_RDR0, + .depth = 128, /* in 4 bytes words */ + .watermark = 64, /* half the depth */ + .handshake = 12, + }, + }, + .drv = &sai_driver, +}, + +}; + +static SHARED_DATA struct dai micfil[] = { +{ + .index = 2, + .plat_data = { + .base = MICFIL_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = 0, /* No playback */ + .handshake = 0, + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = MICFIL_BASE + REG_MICFIL_DATACH0, + .handshake = 24, + .depth = 32, /* in 4 bytes words */ + }, + }, + + .drv = &micfil_driver, +}, }; const struct dai_type_info dti[] = { { .type = SOF_DAI_IMX_SAI, - .dai_array = sai, + .dai_array = cache_to_uncache_init((struct dai *)sai), .num_dais = ARRAY_SIZE(sai) }, + { + .type = SOF_DAI_IMX_MICFIL, + .dai_array = cache_to_uncache_init((struct dai *)micfil), + .num_dais = ARRAY_SIZE(micfil) + }, + }; const struct dai_info lib_dai = { @@ -53,9 +189,7 @@ int dai_init(struct sof *sof) /* initialize spin locks early to enable ref counting */ for (i = 0; i < ARRAY_SIZE(sai); i++) - spinlock_init(&sai[i].lock); - - platform_shared_commit(sai, sizeof(*sai)); + k_spinlock_init(&dti[0].dai_array[i].lock); sof->dai_info = &lib_dai; diff --git a/src/platform/imx8m/lib/dma.c b/src/platform/imx8m/lib/dma.c index af0736a882c1..f9cb5a74682a 100644 --- a/src/platform/imx8m/lib/dma.c +++ b/src/platform/imx8m/lib/dma.c @@ -5,44 +5,44 @@ // Author: Daniel Baluta <daniel.baluta@nxp.com> #include <sof/common.h> -#include <sof/drivers/interrupt.h> +#include <rtos/interrupt.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> extern struct dma_ops dummy_dma_ops; extern struct dma_ops sdma_ops; -SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { { .plat_data = { .id = DMA_ID_HOST, - .dir = DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, - .devs = DMA_DEV_HOST, + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, .channels = 16, }, .ops = &dummy_dma_ops, }, { .plat_data = { - .id = DMA_ID_SDMA2, + .id = DMA_ID_SDMA3, /* Note: support is available for MEM_TO_MEM but not * enabled as it is unneeded */ - .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, - .devs = DMA_DEV_SAI, - .base = SDMA2_BASE, + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SAI | SOF_DMA_DEV_MICFIL, + .base = SDMA3_BASE, .channels = 32, - .irq = SDMA2_IRQ, - .irq_name = SDMA2_IRQ_NAME, + .irq = SDMA3_IRQ, + .irq_name = SDMA3_IRQ_NAME, }, .ops = &sdma_ops, }, }; -const struct dma_info lib_dma = { - .dma_array = dma, +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((void *)dma), .num_dmas = ARRAY_SIZE(dma) }; @@ -52,9 +52,7 @@ int dmac_init(struct sof *sof) /* early lock initialization for ref counting */ for (i = 0; i < ARRAY_SIZE(dma); i++) - spinlock_init(&dma[i].lock); - - platform_shared_commit(dma, sizeof(*dma)); + k_spinlock_init(&dma[i].lock); sof->dma_info = &lib_dma; diff --git a/src/platform/imx8m/lib/memory.c b/src/platform/imx8m/lib/memory.c index 773b20f2f5d2..85596ca2b525 100644 --- a/src/platform/imx8m/lib/memory.c +++ b/src/platform/imx8m/lib/memory.c @@ -5,10 +5,10 @@ // Author: Daniel Baluta <daniel.baluta@nxp.com> #include <sof/common.h> -#include <sof/lib/alloc.h> +#include <sof/lib/mm_heap.h> #include <sof/lib/memory.h> #include <sof/platform.h> -#include <sof/sof.h> +#include <rtos/sof.h> #include <ipc/topology.h> /* Heap blocks for system runtime */ @@ -97,5 +97,5 @@ static SHARED_DATA struct mm memmap = { void platform_init_memmap(struct sof *sof) { /* memmap has been initialized statically as a part of .data */ - sof->memory_map = &memmap; + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); } diff --git a/src/platform/imx8m/platform.c b/src/platform/imx8m/platform.c index bf8939212382..46e60a7e8608 100644 --- a/src/platform/imx8m/platform.c +++ b/src/platform/imx8m/platform.c @@ -6,29 +6,31 @@ #include <sof/compiler_info.h> #include <sof/debug/debug.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> #include <sof/drivers/mu.h> -#include <sof/drivers/timer.h> +#include <rtos/timer.h> #include <sof/fw-ready-metadata.h> #include <sof/lib/agent.h> -#include <sof/lib/clk.h> +#include <rtos/clk.h> #include <sof/lib/cpu.h> #include <sof/lib/dai.h> #include <sof/lib/dma.h> #include <sof/lib/mailbox.h> #include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> #include <sof/platform.h> #include <sof/schedule/edf_schedule.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/ll_schedule_domain.h> -#include <sof/sof.h> +#include <rtos/sof.h> #include <sof/trace/dma-trace.h> #include <ipc/dai.h> #include <ipc/header.h> #include <ipc/info.h> #include <kernel/abi.h> -#include <version.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> #include <errno.h> #include <stdint.h> @@ -46,105 +48,91 @@ static const struct sof_ipc_fw_ready ready .micro = SOF_MICRO, .minor = SOF_MINOR, .major = SOF_MAJOR, -#ifdef DEBUG_BUILD - /* only added in debug for reproducability in releases */ - .build = SOF_BUILD, +/* opt-in; reproducible build by default */ +#if BLD_COUNTERS + .build = SOF_BUILD, /* See version-build-counter.cmake */ .date = __DATE__, .time = __TIME__, +#else + .build = -1, + .date = "dtermin.\0", + .time = "fwready.\0", #endif .tag = SOF_TAG, .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, }, .flags = DEBUG_SET_FW_READY_FLAGS, }; #define NUM_IMX_WINDOWS 6 -static const struct sof_ipc_window sram_window - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_window) + - sizeof(struct sof_ipc_window_elem) * NUM_IMX_WINDOWS, - .type = SOF_IPC_EXT_WINDOW, +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), }, - .num_windows = NUM_IMX_WINDOWS, - .window = { - { - .type = SOF_IPC_REGION_UPBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DSPBOX_SIZE, - .offset = MAILBOX_DSPBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DOWNBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_HOSTBOX_SIZE, - .offset = MAILBOX_HOSTBOX_OFFSET, - }, - { - .type = SOF_IPC_REGION_DEBUG, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DEBUG_SIZE, - .offset = MAILBOX_DEBUG_OFFSET, - }, - { - .type = SOF_IPC_REGION_TRACE, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_TRACE_SIZE, - .offset = MAILBOX_TRACE_OFFSET, - }, - { - .type = SOF_IPC_REGION_STREAM, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_STREAM_SIZE, - .offset = MAILBOX_STREAM_OFFSET, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, }, - { - .type = SOF_IPC_REGION_EXCEPTION, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_EXCEPTION_SIZE, - .offset = MAILBOX_EXCEPTION_OFFSET, + .num_windows = NUM_IMX_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, }, }, }; -SHARED_DATA struct timer timer = { - .id = TIMER0, /* internal timer */ - .irq = IRQ_NUM_TIMER0, -}; - int platform_boot_complete(uint32_t boot_message) { - uint32_t mb_offset = 0; - - mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); - mb_offset = mb_offset + sizeof(ready); - - mailbox_dspbox_write(mb_offset, &sram_window, - sram_window.ext_hdr.hdr.size); - mb_offset = mb_offset + sram_window.ext_hdr.hdr.size; - - /* variable length compiler description is a last field of cc_version */ - mailbox_dspbox_write(mb_offset, &cc_version, - cc_version.ext_hdr.hdr.size); - mb_offset = mb_offset + cc_version.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &probe_support, - probe_support.ext_hdr.hdr.size); - mb_offset = mb_offset + probe_support.ext_hdr.hdr.size; - - mailbox_dspbox_write(mb_offset, &user_abi_version, - user_abi_version.ext_hdr.hdr.size); + mailbox_dspbox_write(0, &ready, sizeof(ready)); /* now interrupt host to tell it we are done booting */ - imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0); + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); /* boot now complete so we can relax the CPU */ /* For now skip this to gain more processing performance @@ -159,20 +147,15 @@ int platform_init(struct sof *sof) { int ret; - sof->platform_timer = &timer; - sof->cpu_timer = &timer; - platform_interrupt_init(); platform_clock_init(sof); scheduler_init_edf(); /* init low latency domains and schedulers */ sof->platform_timer_domain = - timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK, - CONFIG_SYSTICK_PERIOD); + timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); scheduler_init_ll(sof->platform_timer_domain); - platform_timer_start(sof->platform_timer); sa_init(sof, CONFIG_SYSTICK_PERIOD); clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); @@ -182,12 +165,6 @@ int platform_init(struct sof *sof) if (ret < 0) return -ENODEV; - /* Init SDMA platform domain */ - sof->platform_dma_domain = - dma_multi_chan_domain_init(&sof->dma_info->dma_array[1], - 1, PLATFORM_DEFAULT_CLOCK, true); - scheduler_init_ll(sof->platform_dma_domain); - /* initialize the host IPC mechanims */ ipc_init(sof); @@ -206,3 +183,8 @@ int platform_init(struct sof *sof) return 0; } + +int platform_context_save(struct sof *sof) +{ + return 0; +} diff --git a/src/platform/imx8m_cm7/include/platform/lib/clk.h b/src/platform/imx8m_cm7/include/platform/lib/clk.h new file mode 100644 index 000000000000..379aade87252 --- /dev/null +++ b/src/platform/imx8m_cm7/include/platform/lib/clk.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2026 NXP + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#define CLK_MAX_CPU_HZ 800000000 +#define CPU_DEFAULT_IDX 0 +#define NUM_CPU_FREQ 1 +#define NUM_CLOCKS 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/imx8m_cm7/include/platform/lib/dma.h b/src/platform/imx8m_cm7/include/platform/lib/dma.h new file mode 100644 index 000000000000..ad55e7f7fb89 --- /dev/null +++ b/src/platform/imx8m_cm7/include/platform/lib/dma.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2026 NXP + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +/* TODO: remove me whenever possible */ + +#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/imx8m_cm7/include/platform/lib/mailbox.h b/src/platform/imx8m_cm7/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..6099d36806f9 --- /dev/null +++ b/src/platform/imx8m_cm7/include/platform/lib/mailbox.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2026 NXP + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +/* The i.MX8MP CM7 mailbox region is organized like this: + * + * +---------------+-------------------------+ + * | Region name | Base address | Size | + * +---------------+---------------+---------+ + * | Outbox region | 0x82000000 | 0x1000 | + * +---------------+---------------+---------+ + * | Inbox region | 0x82001000 | 0x1000 | + * +---------------+---------------+---------+ + * | Stream region | 0x82002000 | 0x1000 | + * +---------------+---------------+---------+ + * + * IMPORTANT: all regions should be 32-byte aligned. + * This is required because cache maintenance might + * be performed on them. + */ + +/* outbox */ +#define MAILBOX_DSPBOX_SIZE 0x1000 +#define MAILBOX_DSPBOX_BASE 0x82000000 +#define MAILBOX_DSPBOX_OFFSET 0 + +/* inbox */ +#define MAILBOX_HOSTBOX_SIZE 0x1000 +#define MAILBOX_HOSTBOX_BASE 0x82001000 +#define MAILBOX_HOSTBOX_OFFSET (MAILBOX_DSPBOX_OFFSET + MAILBOX_DSPBOX_SIZE) + +/* stream */ +#define MAILBOX_STREAM_SIZE 0x1000 +#define MAILBOX_STREAM_BASE 0x82002000 +#define MAILBOX_STREAM_OFFSET (MAILBOX_HOSTBOX_OFFSET + MAILBOX_HOSTBOX_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/imx8m_cm7/include/platform/lib/memory.h b/src/platform/imx8m_cm7/include/platform/lib/memory.h new file mode 100644 index 000000000000..413e77f142e1 --- /dev/null +++ b/src/platform/imx8m_cm7/include/platform/lib/memory.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2026 NXP + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + +#define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE + +#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 + +/* no address translation required */ +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#define HEAPMEM_SIZE 0x00010000 + +/* WAKEUP domain MU1 side B */ +#define MU_BASE 0x30AB0000UL + +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/imx8m_cm7/include/platform/platform.h b/src/platform/imx8m_cm7/include/platform/platform.h new file mode 100644 index 000000000000..7d65624accda --- /dev/null +++ b/src/platform/imx8m_cm7/include/platform/platform.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2026 NXP + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +/* refers to M7 core clock - one core, one clock */ +#define PLATFORM_DEFAULT_CLOCK 0 + +#define HOST_PAGE_SIZE 4096 + +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* TODO: generous (SOF is usually used with 2 channels at most on i.MX + * platforms) and (potentially) not true. Can be adjusted later on if + * need be. + */ +#define PLATFORM_MAX_CHANNELS 4 +/* TODO: same as PLATFORM_MAX_CHANNELS */ +#define PLATFORM_MAX_STREAMS 5 + +/* WAKEUP domain MU7 side B */ +#define PLATFORM_IPC_INTERRUPT 97 + +#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/imx8m_cm7/include/platform/trace/trace.h b/src/platform/imx8m_cm7/include/platform/trace/trace.h new file mode 100644 index 000000000000..3209ad9dc0ae --- /dev/null +++ b/src/platform/imx8m_cm7/include/platform/trace/trace.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2026 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/imx8m_cm7/lib/clk.c b/src/platform/imx8m_cm7/lib/clk.c new file mode 100644 index 000000000000..9c2bcd70f63f --- /dev/null +++ b/src/platform/imx8m_cm7/lib/clk.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2026 NXP + */ + +#include <rtos/clk.h> +#include <sof/lib/notifier.h> + +static const struct freq_table platform_cpu_freq[] = { + { + .freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + .ticks_per_msec = 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; + + 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/imx8m_cm7/linker/data-sections.ld b/src/platform/imx8m_cm7/linker/data-sections.ld new file mode 100644 index 000000000000..3df5d5526577 --- /dev/null +++ b/src/platform/imx8m_cm7/linker/data-sections.ld @@ -0,0 +1,5 @@ +SECTION_PROLOGUE(.fw_metadata,,) +{ + KEEP (*(*.fw_metadata)) + . = ALIGN(16); +} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) diff --git a/src/platform/imx8m_cm7/platform.c b/src/platform/imx8m_cm7/platform.c new file mode 100644 index 000000000000..2da512f3063d --- /dev/null +++ b/src/platform/imx8m_cm7/platform.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2026 NXP + */ + +#include <rtos/sof.h> +#include <rtos/clk.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/lib/dma.h> +#include <sof/lib/dai.h> +#include <sof/debug/debug.h> +#include <sof_versions.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof/drivers/mu.h> + +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, +#ifdef DEBUG_BUILD + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +const struct ext_man_windows windows + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .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, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_UPBOX, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + }, + }, +}; + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, + IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + /* nothing to be done here */ + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + platform_clock_init(sof); + + scheduler_init_edf(); + + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + zephyr_ll_scheduler_init(sof->platform_timer_domain); + + ret = dmac_init(sof); + if (ret < 0) + return ret; + + ipc_init(sof); + + dai_init(sof); + + return 0; +} diff --git a/src/platform/imx8ulp/CMakeLists.txt b/src/platform/imx8ulp/CMakeLists.txt new file mode 100644 index 000000000000..ec909d60035f --- /dev/null +++ b/src/platform/imx8ulp/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/imx8ulp/imx8ulp.x.in b/src/platform/imx8ulp/imx8ulp.x.in new file mode 100644 index 000000000000..ea3257a83707 --- /dev/null +++ b/src/platform/imx8ulp/imx8ulp.x.in @@ -0,0 +1,531 @@ +/* + * Linker Script for i.MX8ULP + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_iram_text_start : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE, + len = (IRAM_BASE + IRAM_SIZE) - (XCHAL_DOUBLEEXC_VECTOR_PADDR + SOF_MEM_VECT_TEXT_SIZE) + sof_sdram0 : + org = SDRAM0_BASE, + len = SDRAM0_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END + sof_sdram1 : + org = SDRAM1_BASE, + len = SDRAM1_SIZE + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_iram_text_start_phdr PT_LOAD; + sof_sdram0_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x44024000; +_memmap_cacheattr_wt_base = 0x11021000; +_memmap_cacheattr_bp_base = 0x22022000; +_memmap_cacheattr_unused_mask = 0x00F00FFF; +_memmap_cacheattr_wb_trapnull = 0x4422422F; +_memmap_cacheattr_wba_trapnull = 0x4422422F; +_memmap_cacheattr_wbna_trapnull = 0x25222222; +_memmap_cacheattr_wt_trapnull = 0x1122122F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0x44F24FFF; +_memmap_cacheattr_wt_strict = 0x11F21FFF; +_memmap_cacheattr_bp_strict = 0x22F22FFF; +_memmap_cacheattr_wb_allvalid = 0x44224222; +_memmap_cacheattr_wt_allvalid = 0x11221222; +_memmap_cacheattr_bp_allvalid = 0x22222222; +_memmap_cacheattr_imx8_wt_allvalid = 0x22222221; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_imx8_wt_allvalid); + +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .iram.text : ALIGN(4) + { + _stext = .; + _iram_text_start = ABSOLUTE(.); + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + _iram_text_end = ABSOLUTE(.); + } >sof_iram_text_start :sof_iram_text_start_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_sdram0 :sof_sdram0_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sdram0 :sof_sdram0_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + KEEP (*(.fw_ready_metadata)) + } >sof_sdram0 :sof_sdram0_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr +} diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/core-isa.h b/src/platform/imx8ulp/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..899f7c606b21 --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,673 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=13270; Build=0x92cb6; Copyright (c) 1999-2021 Tensilica 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. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 32 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 5 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 11 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 2 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4 1 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 1 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_PDX 0 /* PDX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4 */ +#define XCHAL_HAVE_PDX8 0 /* PDX8 */ +#define XCHAL_HAVE_PDX16 0 /* PDX16 */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ + +#define XCHAL_CORE_ID "hifi4_nxp2_ulp_prod" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x00092CB6 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC203B286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x2908A8C2 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.0.8" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2700 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 8 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 270008 /* major*100+minor */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_0 1 +#define XCHAL_HW_REL_LX7_0_8 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2700 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 8 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 270008 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2700 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 8 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 270008 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 32768 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 65536 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 dcache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 8 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 1 /* block prefetch for caches */ +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 6 +#define XCHAL_DCACHE_SETWIDTH 7 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS 4 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 4 /* number of banks */ + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x21170000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x21170000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 65536 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x21180000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x21180000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 65536 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 4 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IDMA 0 +#define XCHAL_HAVE_IDMA_TRANSPOSE 0 + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 2 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 27 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 2 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x0000FFC0 +#define XCHAL_INTLEVEL2_MASK 0x00FF0006 +#define XCHAL_INTLEVEL3_MASK 0xFF000038 +#define XCHAL_INTLEVEL4_MASK 0x00000000 +#define XCHAL_INTLEVEL5_MASK 0x00000001 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000FFC0 +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x00FFFFC6 +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0xFFFFFFFE +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0xFFFFFFFE +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFFFFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 5 +#define XCHAL_INT1_LEVEL 2 +#define XCHAL_INT2_LEVEL 2 +#define XCHAL_INT3_LEVEL 3 +#define XCHAL_INT4_LEVEL 3 +#define XCHAL_INT5_LEVEL 3 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 1 +#define XCHAL_INT11_LEVEL 1 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_INT13_LEVEL 1 +#define XCHAL_INT14_LEVEL 1 +#define XCHAL_INT15_LEVEL 1 +#define XCHAL_INT16_LEVEL 2 +#define XCHAL_INT17_LEVEL 2 +#define XCHAL_INT18_LEVEL 2 +#define XCHAL_INT19_LEVEL 2 +#define XCHAL_INT20_LEVEL 2 +#define XCHAL_INT21_LEVEL 2 +#define XCHAL_INT22_LEVEL 2 +#define XCHAL_INT23_LEVEL 2 +#define XCHAL_INT24_LEVEL 3 +#define XCHAL_INT25_LEVEL 3 +#define XCHAL_INT26_LEVEL 3 +#define XCHAL_INT27_LEVEL 3 +#define XCHAL_INT28_LEVEL 3 +#define XCHAL_INT29_LEVEL 3 +#define XCHAL_INT30_LEVEL 3 +#define XCHAL_INT31_LEVEL 3 +#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 5 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00000002 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0xFFFFFFC0 +#define XCHAL_INTTYPE_MASK_TIMER 0x0000000C +#define XCHAL_INTTYPE_MASK_NMI 0x00000001 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000020 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000010 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 2 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 3 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 0 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 5 +#define XCHAL_PROFILING_INTERRUPT 4 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL5_NUM 0 +/* (There are many interrupts each at level(s) 1, 2, 3.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 5) */ +#define XCHAL_EXTINT1_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 8 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 9 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 10 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 11 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 12 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 13 /* (intlevel 1) */ +#define XCHAL_EXTINT9_NUM 14 /* (intlevel 1) */ +#define XCHAL_EXTINT10_NUM 15 /* (intlevel 1) */ +#define XCHAL_EXTINT11_NUM 16 /* (intlevel 2) */ +#define XCHAL_EXTINT12_NUM 17 /* (intlevel 2) */ +#define XCHAL_EXTINT13_NUM 18 /* (intlevel 2) */ +#define XCHAL_EXTINT14_NUM 19 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 20 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 21 /* (intlevel 2) */ +#define XCHAL_EXTINT17_NUM 22 /* (intlevel 2) */ +#define XCHAL_EXTINT18_NUM 23 /* (intlevel 2) */ +#define XCHAL_EXTINT19_NUM 24 /* (intlevel 3) */ +#define XCHAL_EXTINT20_NUM 25 /* (intlevel 3) */ +#define XCHAL_EXTINT21_NUM 26 /* (intlevel 3) */ +#define XCHAL_EXTINT22_NUM 27 /* (intlevel 3) */ +#define XCHAL_EXTINT23_NUM 28 /* (intlevel 3) */ +#define XCHAL_EXTINT24_NUM 29 /* (intlevel 3) */ +#define XCHAL_EXTINT25_NUM 30 /* (intlevel 3) */ +#define XCHAL_EXTINT26_NUM 31 /* (intlevel 3) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 5) */ +#define XCHAL_INT6_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT7_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT9_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT10_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT11_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT12_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT13_EXTNUM 8 /* (intlevel 1) */ +#define XCHAL_INT14_EXTNUM 9 /* (intlevel 1) */ +#define XCHAL_INT15_EXTNUM 10 /* (intlevel 1) */ +#define XCHAL_INT16_EXTNUM 11 /* (intlevel 2) */ +#define XCHAL_INT17_EXTNUM 12 /* (intlevel 2) */ +#define XCHAL_INT18_EXTNUM 13 /* (intlevel 2) */ +#define XCHAL_INT19_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT20_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT21_EXTNUM 16 /* (intlevel 2) */ +#define XCHAL_INT22_EXTNUM 17 /* (intlevel 2) */ +#define XCHAL_INT23_EXTNUM 18 /* (intlevel 2) */ +#define XCHAL_INT24_EXTNUM 19 /* (intlevel 3) */ +#define XCHAL_INT25_EXTNUM 20 /* (intlevel 3) */ +#define XCHAL_INT26_EXTNUM 21 /* (intlevel 3) */ +#define XCHAL_INT27_EXTNUM 22 /* (intlevel 3) */ +#define XCHAL_INT28_EXTNUM 23 /* (intlevel 3) */ +#define XCHAL_INT29_EXTNUM 24 /* (intlevel 3) */ +#define XCHAL_INT30_EXTNUM 25 /* (intlevel 3) */ +#define XCHAL_INT31_EXTNUM 26 /* (intlevel 3) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x21170400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x21170400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x21170000 +#define XCHAL_RESET_VECTOR0_PADDR 0x21170000 +#define XCHAL_RESET_VECTOR1_VADDR 0x20100000 +#define XCHAL_RESET_VECTOR1_PADDR 0x20100000 +#define XCHAL_RESET_VECTOR_VADDR 0x21170000 +#define XCHAL_RESET_VECTOR_PADDR 0x21170000 +#define XCHAL_USER_VECOFS 0x0000021C +#define XCHAL_USER_VECTOR_VADDR 0x2117061C +#define XCHAL_USER_VECTOR_PADDR 0x2117061C +#define XCHAL_KERNEL_VECOFS 0x000001FC +#define XCHAL_KERNEL_VECTOR_VADDR 0x211705FC +#define XCHAL_KERNEL_VECTOR_PADDR 0x211705FC +#define XCHAL_DOUBLEEXC_VECOFS 0x0000023C +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x2117063C +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x2117063C +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x21170400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x21170400 +#define XCHAL_INTLEVEL2_VECOFS 0x0000017C +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x2117057C +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x2117057C +#define XCHAL_INTLEVEL3_VECOFS 0x0000019C +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x2117059C +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x2117059C +#define XCHAL_INTLEVEL4_VECOFS 0x000001BC +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x211705BC +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x211705BC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL4_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000001DC +#define XCHAL_NMI_VECTOR_VADDR 0x211705DC +#define XCHAL_NMI_VECTOR_PADDR 0x211705DC +#define XCHAL_INTLEVEL5_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL5_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL5_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 2 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 0 +#define XCHAL_MPU_ENTRIES 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 0 +#define XCHAL_MPU_ALIGN 0 + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/core-matmap.h b/src/platform/imx8ulp/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..f25903591617 --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,317 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=13270; Build=0x92cb6; Copyright (c) 1999-2021 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ + + + +/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ +#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_CACHED XCHAL_SEP \ + XTHAL_FAM_BYPASS XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION XCHAL_SEP \ + XTHAL_FAM_EXCEPTION +#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_CACHED XCHAL_SEP \ + XTHAL_LAM_BYPASSG XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION XCHAL_SEP \ + XTHAL_LAM_EXCEPTION +#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_WRITETHRU XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_WRITEBACK XCHAL_SEP \ + XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ + XTHAL_SAM_BYPASS XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION XCHAL_SEP \ + XTHAL_SAM_EXCEPTION + +#define XCHAL_CA_R (0xC0 | 0x40000000) +#define XCHAL_CA_RX (0xD0 | 0x40000000) +#define XCHAL_CA_RW (0xE0 | 0x40000000) +#define XCHAL_CA_RWX (0xF0 | 0x40000000) + +/* + * Specific encoded cache attribute values of general interest. + * If a specific cache mode is not available, the closest available + * one is returned instead (eg. writethru instead of writeback, + * bypass instead of writethru). + */ +#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ +#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ +#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ +#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ +#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ +#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* + * General notes on MMU parameters. + * + * Terminology: + * ASID = address-space ID (acts as an "extension" of virtual addresses) + * VPN = virtual page number + * PPN = physical page number + * CA = encoded cache attribute (access modes) + * TLB = translation look-aside buffer (term is stretched somewhat here) + * I = instruction (fetch accesses) + * D = data (load and store accesses) + * way = each TLB (ITLB and DTLB) consists of a number of "ways" + * that simultaneously match the virtual address of an access; + * a TLB successfully translates a virtual address if exactly + * one way matches the vaddr; if none match, it is a miss; + * if multiple match, one gets a "multihit" exception; + * each way can be independently configured in terms of number of + * entries, page sizes, which fields are writable or constant, etc. + * set = group of contiguous ways with exactly identical parameters + * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE + * from the page table and storing it in one of the auto-refill ways; + * if this PTE load also misses, a miss exception is posted for s/w. + * min-wired = a "min-wired" way can be used to map a single (minimum-sized) + * page arbitrarily under program control; it has a single entry, + * is non-auto-refill (some other way(s) must be auto-refill), + * all its fields (VPN, PPN, ASID, CA) are all writable, and it + * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current + * restriction is that this be the only page size it supports). + * + * TLB way entries are virtually indexed. + * TLB ways that support multiple page sizes: + * - must have all writable VPN and PPN fields; + * - can only use one page size at any given time (eg. setup at startup), + * selected by the respective ITLBCFG or DTLBCFG special register, + * whose bits n*4+3 .. n*4 index the list of page sizes for way n + * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); + * this list may be sparse for auto-refill ways because auto-refill + * ways have independent lists of supported page sizes sharing a + * common encoding with PTE entries; the encoding is the index into + * this list; unsupported sizes for a given way are zero in the list; + * selecting unsupported sizes results in undefine hardware behaviour; + * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). + */ + +#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ +#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ +#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ +#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ +#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ + + +/*** Instruction TLB: ***/ + +#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_ITLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* ITLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 + + +/*** Data TLB: ***/ + +#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ +#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ +#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ +#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ + +/* Way set to which each way belongs: */ +#define XCHAL_DTLB_WAY0_SET 0 + +/* Ways sets that are used by hardware auto-refill (ARF): */ +#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ + +/* Way sets that are "min-wired" (see terminology comment above): */ +#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ + + +/* DTLB way set 0 (group of ways 0 thru 0): */ +#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ +#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ +#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ +#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ +#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ +#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ +#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ +#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; + 2^PAGESZ_BITS entries in list, unsupported entries are zero */ +#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ +#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ +#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ +/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 +/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ +#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 +#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 +#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 +#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 +#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 +#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 +#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 +#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 +/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ +#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 +#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 + + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/defs.h b/src/platform/imx8ulp/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..6d4851ca7c41 --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=13270; Build=0x92cb6; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/specreg.h b/src/platform/imx8ulp/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..c48a496320a2 --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/specreg.h @@ -0,0 +1,109 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=13270; Build=0x92cb6; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define SCOMPARE1 12 +#define ACCLO 16 +#define ACCHI 17 +#define MR_0 32 +#define MR_1 33 +#define MR_2 34 +#define MR_3 35 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define ATOMCTL 99 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define MISC_REG_0 244 +#define MISC_REG_1 245 + +/* Special cases (bases of special register series): */ +#define MR 32 +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/system.h b/src/platform/imx8ulp/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..5d3394622d2c --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/system.h @@ -0,0 +1,270 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=13270; Build=0x92cb6; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + +/*#include <xtensa/hal.h>*/ + + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 +/* Alternatives: */ +/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ +/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ + +#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 +/* Alternatives: */ +/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ +/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ +/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/* SW options for functional safety: */ +#define XSHAL_FUNC_SAFETY_ENABLED 0 + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +/*#define XSHAL_ROM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ROM_SIZE ...not configured...*/ +/*#define XSHAL_ROM_AVAIL_V{ADDR,SIZE} ...not configured...*/ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x00000000 +#define XSHAL_RAM_PADDR 0x00000000 +#define XSHAL_RAM_VSIZE 0x21100000 +#define XSHAL_RAM_PSIZE 0x21100000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x00000004 +#define XSHAL_RAM_AVAIL_VSIZE 0x210FFFFC + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x80000000 +#define XSHAL_RAM_BYPASS_PADDR 0x80000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ +/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0x60000000 + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22222244 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22222211 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22222211 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFFFFFF44 /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFFFFFF11 /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFFFFFF11 /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFFFFFF22 /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x22222244 /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x22222211 /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x22222211 /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFFF24244 /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFFF21211 /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFFF21211 /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFFF22222 /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000101 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 +#define XSHAL_STATIC_VECTOR_SELECT 0 +#define XSHAL_RESET_VECTOR_VADDR 0x21170000 +#define XSHAL_RESET_VECTOR_PADDR 0x21170000 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x0000001C +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL4_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL4_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x0000001C +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/tie-asm.h b/src/platform/imx8ulp/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..ecc74e894724 --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,384 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=13270; Build=0x92cb6; Copyright (c) 1999-2021 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.THREADPTR \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + rsr.ACCLO \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.ACCHI \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 996, 4, 4 + rsr.BR \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + rsr.SCOMPARE1 \at1 // conditional store option + s32i \at1, \ptr, .Lxchal_ofs_+4 + rsr.M0 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+8 + rsr.M1 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+12 + rsr.M2 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+16 + rsr.M3 \at1 // MAC16 option + s32i \at1, \ptr, .Lxchal_ofs_+20 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 996, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1008, 4, 4 + rur.F64R_LO \at1 // ureg 234 + s32i \at1, \ptr, .Lxchal_ofs_+0 + rur.F64R_HI \at1 // ureg 235 + s32i \at1, \ptr, .Lxchal_ofs_+4 + rur.F64S \at1 // ureg 236 + s32i \at1, \ptr, .Lxchal_ofs_+8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 12 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1008, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 12 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.THREADPTR \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.ACCLO \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.ACCHI \at1 // MAC16 option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 996, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.BR \at1 // boolean option + l32i \at1, \ptr, .Lxchal_ofs_+4 + wsr.SCOMPARE1 \at1 // conditional store option + l32i \at1, \ptr, .Lxchal_ofs_+8 + wsr.M0 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+12 + wsr.M1 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+16 + wsr.M2 \at1 // MAC16 option + l32i \at1, \ptr, .Lxchal_ofs_+20 + wsr.M3 \at1 // MAC16 option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 996, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 24 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1008, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.F64R_LO \at1 // ureg 234 + l32i \at1, \ptr, .Lxchal_ofs_+4 + wur.F64R_HI \at1 // ureg 235 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.F64S \at1 // ureg 236 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 12 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1008, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 12 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+32 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+40 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+41 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+42 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+43 + ae_salign64.i u0, \ptr, .Lxchal_ofs_+48 + ae_salign64.i u1, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_salign64.i u2, \ptr, .Lxchal_ofs_+0 + ae_salign64.i u3, \ptr, .Lxchal_ofs_+8 + addi \ptr, \ptr, -192 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + rur.AE_OVF_SAR \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+8 + rur.AE_BITHEAD \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+12 + rur.AE_TS_FTS_BU_BP \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.AE_CW_SD_NO \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.AE_CBEGIN0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.AE_CEND0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.AE_CBEGIN1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.AE_CEND1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+36 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.AE_OVF_SAR \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+12 + wur.AE_BITHEAD \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.AE_TS_FTS_BU_BP \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.AE_CW_SD_NO \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.AE_CBEGIN0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.AE_CEND0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.AE_CBEGIN1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.AE_CEND1 \at1 // ureg 249 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+32 + addi \ptr, \ptr, 40 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi \ptr, \ptr, 8 + ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 + ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 + ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 176 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/imx8ulp/include/arch/xtensa/config/tie.h b/src/platform/imx8ulp/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..d40fcd566f75 --- /dev/null +++ b/src/platform/imx8ulp/include/arch/xtensa/config/tie.h @@ -0,0 +1,197 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=13270; Build=0x92cb6; Copyright (c) 1999-2021 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. */ + +#ifndef _XTENSA_CORE_TIE_H +#define _XTENSA_CORE_TIE_H + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 208 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 48 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 256 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 12 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,1,0,0,1, acclo, 4, 4, 4,0x0210, sr,16 , 32,0,0,0) \ + XCHAL_SA_REG(s,1,0,0,1, acchi, 4, 4, 4,0x0211, sr,17 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m0, 4, 4, 4,0x0220, sr,32 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m1, 4, 4, 4,0x0221, sr,33 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m2, 4, 4, 4,0x0222, sr,34 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, m3, 4, 4, 4,0x0223, sr,35 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, f64r_lo, 4, 4, 4,0x03EA, ur,234, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, f64r_hi, 4, 4, 4,0x03EB, ur,235, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, f64s, 4, 4, 4,0x03EC, ur,236, 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 33 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x1029, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1010, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1011, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1012, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1013, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1014, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1015, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1016, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1017, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1018, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1019, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x101A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x101B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x101C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x101D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x101E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x101F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1024, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1025, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1026, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1027, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1020, u,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1021, u,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1022, u,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1023, u,3 , 64,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +/* (not available, must use XCHAL_BYTE0_FORMAT_LENGTHS for this processor) */ +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,3, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11 + +#endif /*_XTENSA_CORE_TIE_H*/ + diff --git a/src/platform/imx8ulp/include/platform/drivers/idc.h b/src/platform/imx8ulp/include/platform/drivers/idc.h new file mode 100644 index 000000000000..44829152c2a1 --- /dev/null +++ b/src/platform/imx8ulp/include/platform/drivers/idc.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Daniel Baluta <daniel.baluta@nxp.com> + * Author: Zhang Peng <peng.zhang_8@nxp.com> + */ + +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, + uint32_t mode) { return 0; } + +static inline int idc_init(void) { return 0; } + +#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/imx8ulp/include/platform/drivers/interrupt.h b/src/platform/imx8ulp/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..f2dfc054453f --- /dev/null +++ b/src/platform/imx8ulp/include/platform/drivers/interrupt.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Zhang Peng <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <rtos/bit.h> + +/* IRQ numbers */ +#define IRQ_DSP_SYS_NMI 0 +#define IRQ_NUM_SOFTWARE0 1 +#define IRQ_NUM_TIMER0 2 +#define IRQ_NUM_TIMER1 3 +#define IRQ_NUM_MU2 14 +#define IRQ_NUM_MU3 15 +#define IRQ_SAI5_NUM 23 +#define IRQ_SAI6_NUM 24 +#define IRQ_SAI7_NUM 25 + +#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS +#define PLATFORM_IRQ_CHILDREN 0 /* Each cascaded struct covers 64 IRQs */ +/* IMX: Covered steer IRQs are modulo-64 aligned. */ +#define PLATFORM_IRQ_FIRST_CHILD 0 + +/* no irqstr in 8ulp */ +int irqstr_get_sof_int(int irqstr_int); +#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/imx8ulp/include/platform/lib/clk.h b/src/platform/imx8ulp/include/platform/lib/clk.h new file mode 100644 index 000000000000..fbbc34bf812b --- /dev/null +++ b/src/platform/imx8ulp/include/platform/lib/clk.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Peng Zhang <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <stdint.h> + +struct sof; + +#define CLK_CPU(x) (x) + +#define CPU_DEFAULT_IDX 0 + +#define CLK_DEFAULT_CPU_HZ 528000000 +#define CLK_MAX_CPU_HZ 600000000 + +#define NUM_CLOCKS 1 + +#define NUM_CPU_FREQ 1 + +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/imx8ulp/include/platform/lib/cpu.h b/src/platform/imx8ulp/include/platform/lib/cpu.h new file mode 100644 index 000000000000..09018734f5b9 --- /dev/null +++ b/src/platform/imx8ulp/include/platform/lib/cpu.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Peng Zhang <peng.zhang_8@nxp.com> + */ + +/* + * \file platform/lib/cpu.h + * \brief DSP core parameters. + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/** \brief Id of primary DSP core */ +#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/imx8ulp/include/platform/lib/dai.h b/src/platform/imx8ulp/include/platform/lib/dai.h new file mode 100644 index 000000000000..3b77f60b88d9 --- /dev/null +++ b/src/platform/imx8ulp/include/platform/lib/dai.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Zhang Peng <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#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/imx8ulp/include/platform/lib/dma.h b/src/platform/imx8ulp/include/platform/lib/dma.h new file mode 100644 index 000000000000..000508d0e46e --- /dev/null +++ b/src/platform/imx8ulp/include/platform/lib/dma.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Peng Zhang <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 2 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 32 + +#define DMA_ID_EDMA2 0 +#define DMA_ID_HOST 1 + +#define dma_chan_irq(dma, chan) \ + (((int *)dma->plat_data.drv_plat_data)[chan]) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#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/imx8ulp/include/platform/lib/mailbox.h b/src/platform/imx8ulp/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..f06560ba41c1 --- /dev/null +++ b/src/platform/imx8ulp/include/platform/lib/mailbox.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Peng Zhang <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/memory.h> +#include <stddef.h> +#include <stdint.h> + +/* + * The Window Region on i.MX8 SRAM is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer | SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + *ptr = src; +} + +#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/imx8ulp/include/platform/lib/memory.h b/src/platform/imx8ulp/include/platform/lib/memory.h new file mode 100644 index 000000000000..00aa9b8b2a41 --- /dev/null +++ b/src/platform/imx8ulp/include/platform/lib/memory.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Zhang Peng <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN 32 + +/* physical DSP addresses */ + +#define IRAM_BASE 0x21170000 +#define IRAM_SIZE 0x10000 + +#define DRAM0_BASE 0x21180000 +#define DRAM0_SIZE 0x10000 + +#define SDRAM0_BASE 0x1a000000 +#define SDRAM0_SIZE 0x800000 + +#define SDRAM1_BASE 0x1a800000 +#define SDRAM1_SIZE 0x800000 + +/* physical address in Arm side */ +#define MEM_RESERVED 0x8e000000 + +/* MU3: ASide (A35) BSide (HIFI4) */ +#define XSHAL_MU3_SIDEB_BYPASS_PADDR 0x2DA20000 +#define MU_BASE XSHAL_MU3_SIDEB_BYPASS_PADDR + +#define EDMA2_BASE 0x2D810000 +#define EDMA2_SIZE 0x10000 + +#define SAI_5_BASE 0x29890000 +#define SAI_5_SIZE 0x00010000 +#define SAI_6_BASE 0x2DA90000 +#define SAI_6_SIZE 0x00010000 +#define SAI_7_BASE 0x2DAA0000 +#define SAI_7_SIZE 0x00010000 + +#define UUID_ENTRY_ELF_BASE 0x1FFFA000 +#define UUID_ENTRY_ELF_SIZE 0x6000 + +#define LOG_ENTRY_ELF_BASE 0x20000000 +#define LOG_ENTRY_ELF_SIZE 0x2000000 + +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + +/* + * The Heap and Stack on i.MX8 are organised like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SDRAM_BASE | RO Data | SOF_DATA_SIZE | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + */ + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE SDRAM1_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x2800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ + + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ + + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 32 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 32 +#define HEAP_RT_COUNT1024 4 +#define HEAP_RT_COUNT2048 4 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 128 +#define HEAP_SYS_RT_COUNT512 16 +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ + +#define HEAP_SYSTEM_BASE (SDRAM1_BASE + SOF_MAILBOX_SIZE) +#define HEAP_SYSTEM_SIZE 0xe000 + +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE + +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +#define HEAP_SYS_RUNTIME_SIZE \ + (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE \ + (SDRAM1_SIZE - SOF_MAILBOX_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE -\ + HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Stack configuration */ +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE +#define SOF_STACK_BASE (SDRAM1_BASE + SDRAM1_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x4 +#define SOF_MEM_VECT_TEXT_SIZE 0x1c +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 +#define SOF_MEM_RESET_LIT_SIZE 0x120 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE + +/** \brief EDF task's default stack size in bytes. */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +struct sof; + +/** + * \brief Data shared between different cores. + * Does nothing, since IMX doesn't support SMP. + */ +#define SHARED_DATA + +void platform_init_memmap(struct sof *sof); + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +/** + * \brief Function for keeping shared data synchronized. + * It's used after usage of data shared by different cores. + * Such data is either statically marked with SHARED_DATA + * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. + * Does nothing, since IMX doesn't support SMP. + */ +static inline void platform_shared_commit(void *ptr, int bytes) { } + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#endif + +#define host_to_local(addr) (SDRAM0_BASE + ((addr) - MEM_RESERVED)) +#define local_to_host(addr) (MEM_RESERVED + ((addr) - SDRAM0_BASE)) + +#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/imx8ulp/include/platform/platform.h b/src/platform/imx8ulp/include/platform/platform.h new file mode 100644 index 000000000000..82899b5eaa58 --- /dev/null +++ b/src/platform/imx8ulp/include/platform/platform.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2021 NXP + * + * Author: Zhang Peng <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <sof/drivers/mu.h> +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) +#define LPSRAM_SIZE 16384 + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT 15 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#define SRAM_REG_FW_STATUS 0x4 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); +} + +/** + * \brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/imx8ulp/include/platform/trace/trace.h b/src/platform/imx8ulp/include/platform/trace/trace.h new file mode 100644 index 000000000000..3a3a60b3f1df --- /dev/null +++ b/src/platform/imx8ulp/include/platform/trace/trace.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright 2021 NXP + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + * Author: Zhang Peng <peng.zhang_8@nxp.com> + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +/* Platform defined trace code */ +#define platform_trace_point(__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/imx8ulp/lib/CMakeLists.txt b/src/platform/imx8ulp/lib/CMakeLists.txt new file mode 100644 index 000000000000..271a099cc6a9 --- /dev/null +++ b/src/platform/imx8ulp/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dai.c + dma.c + memory.c +) diff --git a/src/platform/imx8ulp/lib/clk.c b/src/platform/imx8ulp/lib/clk.c new file mode 100644 index 000000000000..21d1f4166188 --- /dev/null +++ b/src/platform/imx8ulp/lib/clk.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Peng Zhang <peng.zhang_8@nxp.com> + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <rtos/sof.h> + +#include <zephyr/sys/util.h> + +const struct freq_table platform_cpu_freq[] = { + { 528000000, 528000 }, +}; + +STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + 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, + }; + } + + platform_shared_commit(sof->clocks, sizeof(*sof->clocks) * NUM_CLOCKS); +} diff --git a/src/platform/imx8ulp/lib/dai.c b/src/platform/imx8ulp/lib/dai.c new file mode 100644 index 000000000000..879da871ffcb --- /dev/null +++ b/src/platform/imx8ulp/lib/dai.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Zhang Peng <peng.zhang_8@nxp.com> + +#include <sof/common.h> +#include <sof/drivers/edma.h> +#include <sof/drivers/sai.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +static SHARED_DATA struct dai sai[] = { +{ + .index = 5, + .plat_data = { + .base = SAI_5_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_5_BASE + REG_SAI_TDR0, + /* use depth to model the HW FIFO size: + * each channel includes a 16 x 32 bit FIFO + * that can be accessed using Transmit or + * Receive Data Registers + */ + .depth = 16, /* in 4 bytes words */ + .watermark = 8, + .handshake = EDMA_HANDSHAKE(IMX8ULP_EDMA2_CHAN0_IRQ, + IMX8ULP_EDMA2_CHAN0, + IMX8ULP_DMAMUX2_SAI5_TX), + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_5_BASE + REG_SAI_RDR3, + .depth = 16, /* in 4 bytes words */ + .watermark = 8, + .handshake = EDMA_HANDSHAKE(IMX8ULP_EDMA2_CHAN1_IRQ, + IMX8ULP_EDMA2_CHAN1, + IMX8ULP_DMAMUX2_SAI5_RX), + }, + }, + .drv = &sai_driver, +}, +{ + .index = 6, + .plat_data = { + .base = SAI_6_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI_6_BASE + REG_SAI_TDR2, + .depth = 16, /* in 4 bytes words */ + .watermark = 8, + .handshake = EDMA_HANDSHAKE(IMX8ULP_EDMA2_CHAN0_IRQ, + IMX8ULP_EDMA2_CHAN0, + IMX8ULP_DMAMUX2_SAI6_TX), + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI_6_BASE + REG_SAI_RDR0, + .depth = 16, /* in 4 bytes words */ + .watermark = 8, + .handshake = EDMA_HANDSHAKE(IMX8ULP_EDMA2_CHAN1_IRQ, + IMX8ULP_EDMA2_CHAN1, + IMX8ULP_DMAMUX2_SAI6_RX), + }, + }, + .drv = &sai_driver, +}, +}; + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_IMX_SAI, + .dai_array = cache_to_uncache_init((struct dai *)sai), + .num_dais = ARRAY_SIZE(sai) + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(sai); i++) + k_spinlock_init(&dti[0].dai_array[i].lock); + + platform_shared_commit(sai, sizeof(*sai)); + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/imx8ulp/lib/dma.c b/src/platform/imx8ulp/lib/dma.c new file mode 100644 index 000000000000..0cfc47f68039 --- /dev/null +++ b/src/platform/imx8ulp/lib/dma.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Peng Zhang <peng.zhang_8@nxp.com> + +#include <sof/common.h> +#include <sof/drivers/edma.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +extern struct dma_ops dummy_dma_ops; +extern struct dma_ops edma_ops; + +static const int edma2_ints[IMX8ULP_EDMA2_CHAN_MAX] = { + [IMX8ULP_EDMA2_CHAN0] = IMX8ULP_EDMA2_CHAN0_IRQ, + [IMX8ULP_EDMA2_CHAN1] = IMX8ULP_EDMA2_CHAN1_IRQ, +}; + +static SHARED_DATA 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_SIZE, + .channels = 8, + .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 = cache_to_uncache_init((struct dma *)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); + + platform_shared_commit(dma, sizeof(*dma)); + + sof->dma_info = &lib_dma; + + return 0; +} diff --git a/src/platform/imx8ulp/lib/memory.c b/src/platform/imx8ulp/lib/memory.c new file mode 100644 index 000000000000..ac80bf55aae6 --- /dev/null +++ b/src/platform/imx8ulp/lib/memory.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Daniel Baluta <daniel.baluta@nxp.com> +// Author: Zhang Peng <peng.zhang_8@nxp.com> + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/imx8ulp/platform.c b/src/platform/imx8ulp/platform.c new file mode 100644 index 000000000000..88e6dfb8d56d --- /dev/null +++ b/src/platform/imx8ulp/platform.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Zhang Peng <peng.zhang_8@nxp.com> + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <sof/drivers/edma.h> +#include <rtos/interrupt.h> +#include <sof/ipc/driver.h> +#include <sof/drivers/mu.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#if CONFIG_TRACE +#include <sof/trace/dma-trace.h> +#endif +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> + +struct sof; + +static const struct sof_ipc_fw_ready ready + __section(".fw_ready") = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, +#ifdef DEBUG_BUILD + /* only added in debug for reproducability in releases */ + .build = SOF_BUILD, + .date = __DATE__, + .time = __TIME__, +#endif + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_IMX_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_IMX_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, // TODO: set later + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + } +}; + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + /* now interrupt host to tell it we are done booting */ + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); + + /* boot now complete so we can relax the CPU */ + /* For now skip this to gain more processing performance + * for SRC component. + */ + /* clock_set_freq(CLK_CPU, CLK_DEFAULT_CPU_HZ); */ + + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + + /* init low latency domains and schedulers */ + sof->platform_timer_domain = + timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* initialize the host IPC mechanims */ + ipc_init(sof); + + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; + +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + dma_trace_init_complete(sof->dmat); +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} 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 <stdint.h> + +/* 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/lib/clk.h b/src/platform/imx93_a55/include/platform/lib/clk.h new file mode 100644 index 000000000000..cb834906b485 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/clk.h @@ -0,0 +1,27 @@ +/* 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 +#define CLK_MAX_CPU_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC + +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/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..77ca3ec6103b --- /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 <rtos/cache.h> + +#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 0x42430000ULL + +/* 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/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 <rtos/clk.h> +#include <sof/lib/notifier.h> + +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 <rtos/sof.h> +#include <sof/drivers/sai.h> +#include <sof/drivers/edma.h> +#include <sof/lib/memory.h> + +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 <rtos/sof.h> +#include <sof/lib/dma.h> +#include <sof/drivers/edma.h> + +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..ed5a7f6956fc --- /dev/null +++ b/src/platform/imx93_a55/platform.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2023 NXP + */ + +#include <rtos/sof.h> +#include <rtos/clk.h> +#include <sof/lib/dma.h> +#include <sof/lib/dai.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/lib/mailbox.h> +#include <sof/drivers/mu.h> +#include <sof/fw-ready-metadata.h> +#include <sof_versions.h> +#include <kernel/abi.h> +#include <sof/debug/debug.h> + +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 IPC */ + ipc_init(sof); + + /* Initialize DAI */ + dai_init(sof); + + /* We're all set */ + return 0; +} diff --git a/src/platform/imx95/include/platform/lib/clk.h b/src/platform/imx95/include/platform/lib/clk.h new file mode 100644 index 000000000000..ad8b193fab1d --- /dev/null +++ b/src/platform/imx95/include/platform/lib/clk.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2024 NXP + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#define CLK_MAX_CPU_HZ 800000000 +#define CPU_DEFAULT_IDX 0 +#define NUM_CPU_FREQ 1 +#define NUM_CLOCKS 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/imx95/include/platform/lib/dma.h b/src/platform/imx95/include/platform/lib/dma.h new file mode 100644 index 000000000000..5f1c725f693d --- /dev/null +++ b/src/platform/imx95/include/platform/lib/dma.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2024 NXP + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +/* TODO: remove me whenever possible */ + +#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/imx95/include/platform/lib/mailbox.h b/src/platform/imx95/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..ffdb39b34398 --- /dev/null +++ b/src/platform/imx95/include/platform/lib/mailbox.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2024 NXP + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +/* i.MX95's mailbox is organized as follows: + * + * +---------------+-------------------------+ + * | Region name | Base address | Size | + * +---------------+---------------+---------+ + * | Inbox region | 0x8fffd000 | 0x1000 | + * +---------------+---------------+---------+ + * | Outbox region | 0x8fffe000 | 0x1000 | + * +---------------+---------------+---------+ + * | Stream region | 0x8ffff000 | 0x1000 | + * +---------------+---------------+---------+ + * + * IMPORTANT: all regions should be 32-byte aligned. + * This is required because cache maintenance might + * be performed on them. + */ + +/* inbox */ +#define MAILBOX_HOSTBOX_SIZE 0x1000 +#define MAILBOX_HOSTBOX_BASE 0x86000000 +#define MAILBOX_HOSTBOX_OFFSET 0 + +/* outbox */ +#define MAILBOX_DSPBOX_SIZE 0x1000 +#define MAILBOX_DSPBOX_BASE 0x86001000 +#define MAILBOX_DSPBOX_OFFSET (MAILBOX_HOSTBOX_OFFSET + MAILBOX_HOSTBOX_SIZE) + +/* stream */ +#define MAILBOX_STREAM_SIZE 0x1000 +#define MAILBOX_STREAM_BASE 0x86002000 +#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/imx95/include/platform/lib/memory.h b/src/platform/imx95/include/platform/lib/memory.h new file mode 100644 index 000000000000..bf3ff05a5c69 --- /dev/null +++ b/src/platform/imx95/include/platform/lib/memory.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2024 NXP + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + +#define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE + +#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 + +/* no address translation required */ +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#define HEAPMEM_SIZE 0x00010000 + +/* WAKEUP domain MU7 side B */ +#define MU_BASE 0x42440000UL + +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/imx95/include/platform/platform.h b/src/platform/imx95/include/platform/platform.h new file mode 100644 index 000000000000..c676dfc742cb --- /dev/null +++ b/src/platform/imx95/include/platform/platform.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2024 NXP + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +/* refers to M7 core clock - one core, one clock */ +#define PLATFORM_DEFAULT_CLOCK 0 + +#define HOST_PAGE_SIZE 4096 + +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* TODO: generous (SOF is usually used with 2 channels at most on i.MX + * platforms) and (potentially) not true. Can be adjusted later on if + * need be. + */ +#define PLATFORM_MAX_CHANNELS 4 +/* TODO: same as PLATFORM_MAX_CHANNELS */ +#define PLATFORM_MAX_STREAMS 5 + +/* WAKEUP domain MU7 side B */ +#define PLATFORM_IPC_INTERRUPT 207 + +#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/imx95/include/platform/trace/trace.h b/src/platform/imx95/include/platform/trace/trace.h new file mode 100644 index 000000000000..a1702e324436 --- /dev/null +++ b/src/platform/imx95/include/platform/trace/trace.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2024 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/imx95/lib/clk.c b/src/platform/imx95/lib/clk.c new file mode 100644 index 000000000000..8f9e2763057d --- /dev/null +++ b/src/platform/imx95/lib/clk.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2024 NXP + */ + +#include <rtos/clk.h> +#include <sof/lib/notifier.h> + +static const struct freq_table platform_cpu_freq[] = { + { + .freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + .ticks_per_msec = 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; + + 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/imx95/linker/data-sections.ld b/src/platform/imx95/linker/data-sections.ld new file mode 100644 index 000000000000..cc4c0872545b --- /dev/null +++ b/src/platform/imx95/linker/data-sections.ld @@ -0,0 +1,5 @@ +SECTION_PROLOGUE(.fw_metadata,,) +{ + KEEP (*(*.fw_metadata)) + . = ALIGN(16); +} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) diff --git a/src/platform/imx95/platform.c b/src/platform/imx95/platform.c new file mode 100644 index 000000000000..f46500907c91 --- /dev/null +++ b/src/platform/imx95/platform.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2024 NXP + */ + +#include <rtos/sof.h> +#include <rtos/clk.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/lib/dma.h> +#include <sof/lib/dai.h> +#include <sof/debug/debug.h> +#include <sof_versions.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof/drivers/mu.h> + +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, +}; + +const struct ext_man_windows windows + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .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, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_UPBOX, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + }, + }, +}; + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GCR, + IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1), 0); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + /* nothing to be done here */ + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + platform_clock_init(sof); + + scheduler_init_edf(); + + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + zephyr_ll_scheduler_init(sof->platform_timer_domain); + + ret = dmac_init(sof); + if (ret < 0) + return ret; + + ipc_init(sof); + + dai_init(sof); + + return 0; +} diff --git a/src/platform/intel/CMakeLists.txt b/src/platform/intel/CMakeLists.txt deleted file mode 100644 index 2a0859167c11..000000000000 --- a/src/platform/intel/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(cavs) diff --git a/src/platform/intel/ace/include/ace/lib/clk.h b/src/platform/intel/ace/include/ace/lib/clk.h new file mode 100644 index 000000000000..b9c7fd0aec8f --- /dev/null +++ b/src/platform/intel/ace/include/ace/lib/clk.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +/** + * \file ace/lib/clk.h + * \brief Clk parameters for run-time clock data, common for cAVS platforms. + */ + +#ifdef __PLATFORM_LIB_CLK_H__ + +#ifndef __ACE_LIB_CLK_H__ +#define __ACE_LIB_CLK_H__ + +#include <ace/version.h> +#include <sof/lib/cpu.h> + +struct sof; + +/** \brief Total number of clocks */ +#define NUM_CLOCKS CONFIG_CORE_COUNT + +extern const struct freq_table *cpu_freq; + +void platform_clock_init(struct sof *sof); + +#endif /* __ACE_LIB_CLK_H__ */ + +#else + +#error "This file shouldn't be included from outside of platform/lib/clk.h" + +#endif /* __PLATFORM_LIB_CLK_H__ */ diff --git a/src/platform/intel/ace/include/ace/lib/mailbox.h b/src/platform/intel/ace/include/ace/lib/mailbox.h new file mode 100644 index 000000000000..b3cccad8c85a --- /dev/null +++ b/src/platform/intel/ace/include/ace/lib/mailbox.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + */ + +#ifdef __PLATFORM_LIB_MAILBOX_H__ + +#ifndef __ACE_LIB_MAILBOX_H__ +#define __ACE_LIB_MAILBOX_H__ + +#include <rtos/panic.h> +#include <sof/lib/memory.h> +#include <rtos/string.h> +#include <stddef.h> +#include <stdint.h> + +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE + + /* window 3 - trace */ +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE + + /* window 1 inbox/downlink and FW registers */ +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE + + /* window 0 */ +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE + +#define MAILBOX_SW_REG_SIZE SRAM_SW_REG_SIZE +#define MAILBOX_SW_REG_BASE SRAM_SW_REG_BASE + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + uint32_t __sparse_cache *ptr_c; + + ptr_c = (uint32_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache(ptr_c); + *ptr = src; +} + +static inline void mailbox_sw_reg_write64(size_t offset, uint64_t src) +{ + volatile uint64_t *ptr; + uint64_t __sparse_cache *ptr_c; + + ptr_c = (uint64_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache(ptr_c); + *ptr = src; +} + +static inline uint32_t mailbox_sw_reg_read(size_t offset) +{ + volatile uint32_t *ptr; + uint32_t __sparse_cache *ptr_c; + + ptr_c = (uint32_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache(ptr_c); + + return *ptr; +} + +static inline uint64_t mailbox_sw_reg_read64(size_t offset) +{ + volatile uint64_t *ptr; + uint64_t __sparse_cache *ptr_c; + + ptr_c = (uint64_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache(ptr_c); + + return *ptr; +} + +static inline void mailbox_sw_regs_write(size_t offset, const void *src, size_t bytes) +{ + uint32_t __sparse_cache *ptr_c; + uint32_t *ptr; + + ptr_c = (uint32_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache(ptr_c); + memcpy_s(ptr, MAILBOX_SW_REG_SIZE - offset, src, bytes); +} + +#endif /* __ACE_LIB_MAILBOX_H__ */ + +#else + +#error "This file shouldn't be included from outside of platform/lib/mailbox.h" + +#endif /* __PLATFORM_LIB_MAILBOX_H__ */ diff --git a/src/platform/intel/ace/include/ace/lib/memory.h b/src/platform/intel/ace/include/ace/lib/memory.h new file mode 100644 index 000000000000..357397b2affa --- /dev/null +++ b/src/platform/intel/ace/include/ace/lib/memory.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> + */ + +#ifdef __PLATFORM_LIB_MEMORY_H__ + +#ifndef __ACE_LIB_MEMORY_H__ +#define __ACE_LIB_MEMORY_H__ + +#include <sof/common.h> +#include <rtos/cache.h> +#if !defined(__ASSEMBLER__) && !defined(LINKER) +#include <sof/lib/cpu.h> +#endif + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE + +/** + * \brief Data shared between different cores. + * Placed into dedicated section, which should be accessed through + * uncached memory region. SMP platforms without uncache can simply + * align to cache line size instead. + */ +#define SHARED_DATA + +#include <zephyr/cache.h> + +#define uncache_to_cache(address) sys_cache_cached_ptr_get(address) +#define cache_to_uncache(address) sys_cache_uncached_ptr_get(address) +#define is_uncached(address) (!sys_cache_is_ptr_cached(address)) + +/** + * \brief Returns pointer to the memory shared by multiple cores. + * \param[in,out] ptr Initial pointer to the allocated memory. + * \param[in] bytes Size of the allocated memory + * \return Appropriate pointer to the shared memory. + * + * This function is called only once right after allocation of shared memory. + * Platforms with uncached memory region should return aliased address. + * On platforms without such region simple invalidate is enough. + */ +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#endif /* __ACE_LIB_MEMORY_H__ */ + +#else + +#error "This file shouldn't be included from outside of platform/lib/memory.h" + +#endif /* __PLATFORM_LIB_MEMORY_H__ */ diff --git a/src/platform/intel/ace/include/ace/version.h b/src/platform/intel/ace/include/ace/version.h new file mode 100644 index 000000000000..c2df425307e6 --- /dev/null +++ b/src/platform/intel/ace/include/ace/version.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __ACE_VERSION_H__ +#define __ACE_VERSION_H__ + +#define ACE_VERSION_1_5 0x10500 /* MTL */ +#define ACE_VERSION_2_0 0x20000 /* LNL */ +#define ACE_VERSION_3_0 0x30000 /* PTL */ +#define ACE_VERSION_4_0 0x40000 /* NVL */ + +/* ACE version defined by CONFIG_ACE_VER_*/ +#if defined(CONFIG_ACE_VERSION_1_5) +#define ACE_VERSION ACE_VERSION_1_5 +#elif defined(CONFIG_ACE_VERSION_2_0) +#define ACE_VERSION ACE_VERSION_2_0 +#elif defined(CONFIG_ACE_VERSION_3_0) +#define ACE_VERSION ACE_VERSION_3_0 +#elif defined(CONFIG_ACE_VERSION_4_0) +#define ACE_VERSION ACE_VERSION_4_0 +#endif + +#define HW_CFG_VERSION ACE_VERSION + +#endif /* __ACE_VERSION_H__ */ diff --git a/src/platform/intel/ace/include/auth/intel_auth_api.h b/src/platform/intel/ace/include/auth/intel_auth_api.h new file mode 100644 index 000000000000..69a9e0cd8ca2 --- /dev/null +++ b/src/platform/intel/ace/include/auth/intel_auth_api.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ +#ifndef INTEL_AUTH_API_H +#define INTEL_AUTH_API_H + +#include <sof/auth_api_iface.h> + +#define AUTH_API_CALLBACKS_ADDR (0x162000 + 0x140) + +/* The same as auth_api->init. */ +inline int auth_api_init(struct auth_api_ctx *ctx, + void *scratch_buff, + size_t scratch_buff_size, + enum auth_image_type image_type) +{ + struct auth_api_ctx **auth_api_callbacks = + (struct auth_api_ctx **)AUTH_API_CALLBACKS_ADDR; + + ctx->version_api = (*auth_api_callbacks)->version_api; + ctx->auth_api = (*auth_api_callbacks)->auth_api; + return ctx->auth_api->init(ctx, scratch_buff, scratch_buff_size, image_type); +} + +/* The same as auth_api->cleanup. */ +inline void auth_api_cleanup(struct auth_api_ctx *ctx) +{ + ctx->auth_api->cleanup(ctx); +} + +/* The same as auth_api->init_auth_proc. */ +inline int auth_api_init_auth_proc(struct auth_api_ctx *ctx, + const void *chunk, + size_t chunk_size, + enum auth_phase phase) +{ + return ctx->auth_api->init_auth_proc(ctx, chunk, chunk_size, phase); +} + +/* The same as auth_api->busy. */ +inline bool auth_api_busy(struct auth_api_ctx *ctx) +{ + return ctx->auth_api->busy(ctx); +} + +/* The same as auth_api->result. */ +inline enum auth_result auth_api_result(struct auth_api_ctx *ctx) +{ + return ctx->auth_api->result(ctx); +} + +/* The same as auth_api->register_status_logger. */ +inline int auth_api_register_status_logger(struct auth_api_ctx *ctx, + struct status_logger_ctx *status_logger) +{ + return ctx->auth_api->register_status_logger(ctx, status_logger); +} + +/* The same as AuthApi::UnregisterStatusLogger. */ +inline void auth_api_unregister_status_logger(struct auth_api_ctx *ctx) +{ + ctx->auth_api->unregister_status_logger(ctx); +} + +/* The same as auth_api->version. */ +inline struct auth_api_version_num auth_api_version(void) +{ + struct auth_api_ctx **auth_api_callbacks = + (struct auth_api_ctx **)AUTH_API_CALLBACKS_ADDR; + return (*auth_api_callbacks)->version_api->version(); +} + +#endif /* INTEL_AUTH_API_H */ + diff --git a/src/platform/intel/ace/include/auth/intel_status_logger_api.h b/src/platform/intel/ace/include/auth/intel_status_logger_api.h new file mode 100644 index 000000000000..eca4162219da --- /dev/null +++ b/src/platform/intel/ace/include/auth/intel_status_logger_api.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ +#ifndef INTEL_STATUS_LOGGER_API +#define INTEL_STATUS_LOGGER_API + +#include "stdint.h" +#include "intel_status_logger_iface.h" + +inline void sts_log_init(struct status_logger_ctx *ctx) +{ + ctx->cb.init(ctx); +} + +inline void sts_log_cleanup(struct status_logger_ctx *ctx) +{ + ctx->cb.cleanup(ctx); +} + +inline void sts_log_report_error(struct status_logger_ctx *ctx, int error_code) +{ + ctx->cb.report_error(ctx, error_code); +} + +inline void sts_log_set_boot_state(struct status_logger_ctx *ctx, uint32_t state) +{ + ctx->cb.set_boot_state(ctx, state); +} + +inline void sts_log_set_wait_state(struct status_logger_ctx *ctx, uint32_t state) +{ + ctx->cb.set_wait_state(ctx, state); +} + +inline void sts_log_set_module(struct status_logger_ctx *ctx, uint32_t mod) +{ + ctx->cb.set_module(ctx, mod); +} + +#endif /*INTEL_STATUS_LOGGER_API*/ diff --git a/src/platform/intel/ace/include/auth/intel_status_logger_iface.h b/src/platform/intel/ace/include/auth/intel_status_logger_iface.h new file mode 100644 index 000000000000..4a22a072bebc --- /dev/null +++ b/src/platform/intel/ace/include/auth/intel_status_logger_iface.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Pawel Dobrowolski <pawelx.dobrowolski@intel.com> + */ +#ifndef INTEL_STATUS_LOGGER_IFACE +#define INTEL_STATUS_LOGGER_IFACE + +#include "stdint.h" + +struct status_logger_ctx; + +/* Status Logger Interface callbacks. */ +struct status_logger_iface { + /* Interface to initialize Status Logger context. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * Return value: + * 0 - SUCCESS - successful initialization. + */ + int (*init)(struct status_logger_ctx *ctx); + + /* Interface to cleanup Status Logger context. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + */ + void (*cleanup)(struct status_logger_ctx *ctx); + + /** + * Reports critical rom error. Halts execution. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param error_code - error code to report + */ + void (*report_error)(struct status_logger_ctx *ctx, int error_code); + + /** + * Reports boot status. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param uint32_t state - boot state code to report. + */ + void (*set_boot_state)(struct status_logger_ctx *ctx, uint32_t state); + + /** + * Reports that caller is waiting on some external event or action. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param uint32_t state - reason of waiting. + */ + void (*set_wait_state)(struct status_logger_ctx *ctx, uint32_t state); + + /** + * Set module type in FSR. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param mod module id + */ + + void (*set_module)(struct status_logger_ctx *ctx, uint32_t mod); +} __packed __aligned(4); + +/* Design note: Compiler was not able to generate proper call assembly code using standard C++ + * inheritance in Auth API implementation. That's why we do explicit callbacks assignment, + * following C-like OOP. + */ +struct status_logger_ctx { + struct status_logger_iface cb; +}; + +#endif /*INTEL_STATUS_LOGGER_IFACE*/ diff --git a/src/platform/intel/ace/lib/watchdog.c b/src/platform/intel/ace/lib/watchdog.c new file mode 100644 index 000000000000..dcae80da801d --- /dev/null +++ b/src/platform/intel/ace/lib/watchdog.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2023 Intel Corporation + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <sof/lib/uuid.h> +#include <rtos/idc.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/ipc/msg.h> +#include <ipc4/notification.h> + +#include <zephyr/kernel.h> +#include <zephyr/drivers/watchdog.h> + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(adsp_watchdog), okay) +#include <adsp_watchdog.h> +#include <intel_adsp_ipc.h> +#include <intel_adsp_ipc_devtree.h> + +LOG_MODULE_REGISTER(wdt, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(wdt); + +DECLARE_TR_CTX(wdt_tr, SOF_UUID(wdt_uuid), LOG_LEVEL_INFO); + +static const struct device *const watchdog = DEVICE_DT_GET(DT_NODELABEL(adsp_watchdog)); +static struct ipc_msg secondary_timeout_ipc; + +static void watchdog_primary_core_action_on_timeout(void) +{ + struct ipc4_watchdog_timeout_notification notif; + + /* Send Watchdog Timeout IPC notification */ + ipc4_notification_watchdog_init(¬if, cpu_get_id(), true); + intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, + notif.primary.dat, notif.extension.dat); +} + +static void watchdog_secondary_core_action_on_timeout(void) +{ + struct idc_msg msg; + + /* Send Watchdog Timeout IDC notification */ + msg.header = IDC_MSG_SECONDARY_CORE_CRASHED | IDC_SCC_CORE(cpu_get_id()) | + IDC_SCC_REASON(IDC_SCC_REASON_WATCHDOG); + msg.extension = 0; + msg.core = 0; + msg.size = 0; + msg.payload = NULL; + idc_send_msg(&msg, IDC_NON_BLOCKING); +} + +/* This function is called by idc handler on primary core */ +void watchdog_secondary_core_timeout(int core) +{ + struct ipc4_watchdog_timeout_notification notif; + + /* Send Watchdog Timeout IPC notification */ + ipc4_notification_watchdog_init(¬if, core, true); + secondary_timeout_ipc.header = notif.primary.dat; + secondary_timeout_ipc.extension = notif.extension.dat; + ipc_msg_send(&secondary_timeout_ipc, NULL, true); +} + +static void watchdog_timeout(const struct device *dev, int core) +{ + if (core == PLATFORM_PRIMARY_CORE_ID) + watchdog_primary_core_action_on_timeout(); + else + watchdog_secondary_core_action_on_timeout(); +} + +void watchdog_init(void) +{ + int i, ret; + const struct wdt_timeout_cfg watchdog_config = { + .window.max = LL_WATCHDOG_TIMEOUT_US / 1000, + .callback = watchdog_timeout, + }; + + secondary_timeout_ipc.tx_data = NULL; + secondary_timeout_ipc.tx_size = 0; + list_init(&secondary_timeout_ipc.list); + + ret = wdt_install_timeout(watchdog, &watchdog_config); + if (ret) { + tr_warn(&wdt_tr, "Watchdog install timeout error %d", ret); + return; + } + + for (i = 0; i < arch_num_cpus(); i++) + intel_adsp_watchdog_pause(watchdog, i); + + ret = wdt_setup(watchdog, 0); + if (ret) + tr_warn(&wdt_tr, "Watchdog setup error %d", ret); +} + +void watchdog_enable(int core) +{ + intel_adsp_watchdog_resume(watchdog, core); +} + +void watchdog_disable(int core) +{ + intel_adsp_watchdog_pause(watchdog, core); +} + +void watchdog_feed(int core) +{ + wdt_feed(watchdog, core); +} +#else +void watchdog_enable(int core) {} +void watchdog_disable(int core) {} +void watchdog_feed(int core) {} +void watchdog_init(void) {} +void watchdog_secondary_core_timeout(int core) {} +#endif diff --git a/src/platform/intel/ace/platform.c b/src/platform/intel/ace/platform.c new file mode 100644 index 000000000000..1fde2713049d --- /dev/null +++ b/src/platform/intel/ace/platform.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Rander Wang <rander.wang@intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/debug/debug.h> +#include <sof/ipc/common.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/lib/agent.h> +#include <sof/lib/cpu-clk-manager.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/watchdog.h> +#include <sof/lib/cpu-clk-manager.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/twb_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/trace/trace.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include "sof/audio/mic_privacy_manager.h" +#endif +#include <sof_versions.h> +#include <stdint.h> + +static const struct sof_ipc_fw_ready ready + __section(".fw_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, +/* opt-in; reproducible build by default */ +#if BLD_COUNTERS + .build = SOF_BUILD, /* See version-build-counter.cmake */ + .date = __DATE__, + .time = __TIME__, +#else /* BLD_COUNTERS */ + .build = -1, + .date = "dtermin.\0", + .time = "fwready.\0", +#endif /* BLD_COUNTERS */ + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +__cold int platform_boot_complete(uint32_t boot_message) +{ + struct ipc_cmd_hdr header; + + /* get any IPC specific boot message and optional data */ + ipc_boot_complete_msg(&header, 0); + header.pri |= boot_message; + + struct ipc_msg msg = { + .header = header.pri, + .extension = header.ext, + .tx_size = sizeof(ready), + .tx_data = (void *)&ready, + }; + + /* send fimrware ready message. */ + return ipc_platform_send_msg(&msg); +} + +#ifdef CONFIG_PM +static struct pm_notifier pm_state_notifier = { + .state_entry = cpu_notify_state_entry, + .state_exit = cpu_notify_state_exit, +}; +#endif + +/* Runs on the primary core only */ +__cold int platform_init(struct sof *sof) +{ + int ret; + + trace_point(TRACE_BOOT_PLATFORM_CLOCK); + platform_clock_init(sof); + +#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL + kcps_budget_init(); + + ret = core_kcps_adjust(cpu_get_id(), PRIMARY_CORE_BASE_CPS_USAGE); + if (ret < 0) + return ret; +#endif + + trace_point(TRACE_BOOT_PLATFORM_SCHED); + scheduler_init_edf(); + + /* init low latency timer domain and scheduler. Any failure is fatal */ + /* clk is ignored on Zephyr so pass 0 */ + sof->platform_timer_domain = zephyr_domain_init(0); + ret = scheduler_init_ll(sof->platform_timer_domain); + if (ret < 0) + return ret; + +#if CONFIG_ZEPHYR_DP_SCHEDULER + ret = scheduler_dp_init(); + if (ret < 0) + return ret; +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ + +#if CONFIG_ZEPHYR_TWB_SCHEDULER + ret = scheduler_twb_init(); + if (ret < 0) + return ret; +#endif + + /* init the system agent */ + trace_point(TRACE_BOOT_PLATFORM_AGENT); + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + /* init DMACs */ + trace_point(TRACE_BOOT_PLATFORM_DMA); + ret = dmac_init(sof); + if (ret < 0) + return ret; + +#ifdef CONFIG_PM + /* register power states entry / exit notifiers */ + pm_notifier_register(&pm_state_notifier); +#endif + + /* initialize the host IPC mechanisms */ + trace_point(TRACE_BOOT_PLATFORM_IPC); + ipc_init(sof); + idc_init(); + + watchdog_init(); + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + /* Init mic privacy manager */ + ret = mic_privacy_manager_init(); + if (ret < 0) + return ret; +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} diff --git a/src/platform/intel/cavs/CMakeLists.txt b/src/platform/intel/cavs/CMakeLists.txt deleted file mode 100644 index 09b76c325913..000000000000 --- a/src/platform/intel/cavs/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(lib) - - -if(CONFIG_CAVS_LPS) -add_library(lps_vector STATIC "") -target_link_libraries(lps_vector sof_options) -target_compile_options(lps_vector PRIVATE -mtext-section-literals) - -add_local_sources(lps_vector lps_pic_restore_vector.S) - -target_link_libraries(sof_static_libraries INTERFACE lps_vector) - -add_local_sources(sof lps_wait.c) -endif() - -add_local_sources(sof platform.c) - -target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/intel/cavs/include) diff --git a/src/platform/intel/cavs/include/cavs/drivers/dw-dma.h b/src/platform/intel/cavs/include/cavs/drivers/dw-dma.h deleted file mode 100644 index 3e664f8eebcc..000000000000 --- a/src/platform/intel/cavs/include/cavs/drivers/dw-dma.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __PLATFORM_DRIVERS_DW_DMA_H__ - -#ifndef __CAVS_LIB_DW_DMA_H__ -#define __CAVS_LIB_DW_DMA_H__ - -#include <sof/bit.h> -#include <sof/lib/dma.h> -#include <sof/lib/shim.h> -#include <config.h> -#include <stdint.h> - -/* number of supported DW-DMACs */ -#if CONFIG_SUECREEK -#define PLATFORM_NUM_DW_DMACS 3 -#else -#define PLATFORM_NUM_DW_DMACS 2 -#endif - -/* index of the first DW-DMAC in the array */ -#define PLATFORM_DW_DMA_INDEX 0 - -/* DMA treats PHY addresses as host address unless within DSP region */ -#define PLATFORM_DW_DMA_HOST_MASK 0x00000000 - -/* CTL_HI */ -#define DW_CTLH_CLASS(x) SET_BITS(31, 29, x) -#define DW_CTLH_WEIGHT(x) SET_BITS(28, 18, x) -#define DW_CTLH_DONE(x) SET_BIT(17, x) -#define DW_CTLH_BLOCK_TS_MASK MASK(16, 0) - -/* CFG_LO */ -#define DW_CFG_RELOAD_DST BIT(31) -#define DW_CFG_RELOAD_SRC BIT(30) -#define DW_CFG_CTL_HI_UPD_EN BIT(5) - -/* CFG_HI */ -#define DW_CFGH_DST_PER_EXT(x) SET_BITS(31, 30, x) -#define DW_CFGH_SRC_PER_EXT(x) SET_BITS(29, 28, x) -#define DW_CFGH_DST_PER(x) SET_BITS(7, 4, x) -#define DW_CFGH_SRC_PER(x) SET_BITS(3, 0, x) -#define DW_CFGH_DST(x) \ - (DW_CFGH_DST_PER_EXT((x) >> 4) | DW_CFGH_DST_PER(x)) -#define DW_CFGH_SRC(x) \ - (DW_CFGH_SRC_PER_EXT((x) >> 4) | DW_CFGH_SRC_PER(x)) - -/* default initial setup register values */ -#define DW_CFG_LOW_DEF 0x3 -#define DW_CFG_HIGH_DEF 0x0 - -/* LLPC address */ -#define DW_CHLLPC(dma, chan) \ - SHIM_GPDMA_CHLLPC((dma)->plat_data.id, (chan)->index) - -#define platform_dw_dma_set_class(chan, lli, class) \ - (lli->ctrl_hi |= DW_CTLH_CLASS(class)) - -#define platform_dw_dma_set_transfer_size(chan, lli, size) \ - (lli->ctrl_hi |= (size & DW_CTLH_BLOCK_TS_MASK)) - -static inline void platform_dw_dma_llp_config(struct dma *dma, - struct dma_chan_data *chan, - uint32_t config) -{ - shim_write(DW_CHLLPC(dma, chan), SHIM_GPDMA_CHLLPC_DHRS(config)); -} - -static inline void platform_dw_dma_llp_enable(struct dma *dma, - struct dma_chan_data *chan) -{ - shim_write(DW_CHLLPC(dma, chan), - shim_read(DW_CHLLPC(dma, chan)) | SHIM_GPDMA_CHLLPC_EN); -} - -static inline void platform_dw_dma_llp_disable(struct dma *dma, - struct dma_chan_data *chan) -{ - shim_write(DW_CHLLPC(dma, chan), - shim_read(DW_CHLLPC(dma, chan)) & ~SHIM_GPDMA_CHLLPC_EN); -} - -static inline struct dw_lli *platform_dw_dma_lli_get(struct dw_lli *lli) -{ - return cache_to_uncache(lli); -} - -#endif /* __CAVS_LIB_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of platform/drivers/dw-dma.h" - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/drivers/idc.h b/src/platform/intel/cavs/include/cavs/drivers/idc.h deleted file mode 100644 index 6eb04ad6fbe7..000000000000 --- a/src/platform/intel/cavs/include/cavs/drivers/idc.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __PLATFORM_DRIVERS_IDC_H__ - -#ifndef __CAVS_DRIVERS_IDC_H__ -#define __CAVS_DRIVERS_IDC_H__ - -#include <config.h> -#include <stdint.h> - -struct idc_msg; - -#if CONFIG_SMP - -int idc_send_msg(struct idc_msg *msg, uint32_t mode); - -int idc_init(void); - -#else - -static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) { return 0; } - -static inline int idc_init(void) { return 0; } - -#endif - -#endif /* __CAVS_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of platform/drivers/idc.h" - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/drivers/interrupt.h b/src/platform/intel/cavs/include/cavs/drivers/interrupt.h deleted file mode 100644 index 82ce1ec4f6f0..000000000000 --- a/src/platform/intel/cavs/include/cavs/drivers/interrupt.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __PLATFORM_DRIVERS_INTERRUPT_H__ - -#ifndef __CAVS_DRIVERS_INTERRUPT_H__ -#define __CAVS_DRIVERS_INTERRUPT_H__ - -#include <sof/lib/clk.h> - -extern const char irq_name_level2[]; -extern const char irq_name_level3[]; -extern const char irq_name_level4[]; -extern const char irq_name_level5[]; - -#if CONFIG_CAVS_USE_LPRO_IN_WAITI -static inline void platform_interrupt_on_wakeup(void) -{ - platform_clock_on_wakeup(); -} -#endif - -#endif /* __CAVS_DRIVERS_INTERRUPT_H__ */ - -#else - -#error "This file shouldn't be included from outside of platform/drivers/interrupt.h" - -#endif /* __PLATFORM_DRIVERS_INTERRUPT_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/drivers/mn.h b/src/platform/intel/cavs/include/cavs/drivers/mn.h new file mode 100644 index 000000000000..4a1407dba68c --- /dev/null +++ b/src/platform/intel/cavs/include/cavs/drivers/mn.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> + */ + +#ifdef __PLATFORM_DRIVERS_MN_H__ + +#ifndef __CAVS_DRIVERS_MN_H__ +#define __CAVS_DRIVERS_MN_H__ + +#include <rtos/bit.h> + +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x0 + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x80 + (x) * 0x4) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __CAVS_DRIVERS_MN_H__ */ + +#else + +#error "This file shouldn't be included from outside of platform/drivers/mn.h" + +#endif /* __PLATFORM_DRIVERS_MN_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/drivers/sideband-ipc.h b/src/platform/intel/cavs/include/cavs/drivers/sideband-ipc.h index 4a2ab57a64b7..6476d19ddd3f 100644 --- a/src/platform/intel/cavs/include/cavs/drivers/sideband-ipc.h +++ b/src/platform/intel/cavs/include/cavs/drivers/sideband-ipc.h @@ -15,7 +15,7 @@ #ifndef __CAVS_DRIVERS_SIDEBAND_IPC_H__ #define __CAVS_DRIVERS_SIDEBAND_IPC_H__ -#include <sof/bit.h> +#include <rtos/bit.h> /* DIPCTDR */ #define IPC_DIPCTDR_BUSY BIT(31) diff --git a/src/platform/intel/cavs/include/cavs/drivers/timestamp.h b/src/platform/intel/cavs/include/cavs/drivers/timestamp.h new file mode 100644 index 000000000000..f6b76d1fdd27 --- /dev/null +++ b/src/platform/intel/cavs/include/cavs/drivers/timestamp.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +#ifdef __PLATFORM_DRIVERS_TIMESTAMP_H__ + +#ifndef __CAVS_DRIVERS_TIMESTAMP_H__ +#define __CAVS_DRIVERS_TIMESTAMP_H__ + +#include <rtos/bit.h> + +#define TS_LOCAL_TSCTRL_NTK_BIT BIT(31) +#define TS_LOCAL_TSCTRL_IONTE_BIT BIT(30) +#define TS_LOCAL_TSCTRL_SIP_BIT BIT(8) +#define TS_LOCAL_TSCTRL_HHTSE_BIT BIT(7) +#define TS_LOCAL_TSCTRL_ODTS_BIT BIT(5) +#define TS_LOCAL_TSCTRL_CDMAS(x) SET_BITS(4, 0, x) +#define TS_LOCAL_OFFS_FRM GET_BITS(15, 12) +#define TS_LOCAL_OFFS_CLK GET_BITS(11, 0) + +#endif /* __CAVS_DRIVERS_TIMESTAMP_H__ */ + +#else + +#error "This file shouldn't be included from outside of platform/drivers/timestamp.h" + +#endif /* __PLATFORM_DRIVERS_TIMESTAMP_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/ext_manifest.h b/src/platform/intel/cavs/include/cavs/ext_manifest.h new file mode 100644 index 000000000000..3eaf2d3d6c49 --- /dev/null +++ b/src/platform/intel/cavs/include/cavs/ext_manifest.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Adrian Bonislawski <adrian.bonislawski@linux.intel.com> + */ + +#ifndef __CAVS_EXT_MANIFEST_H__ +#define __CAVS_EXT_MANIFEST_H__ + +#include <kernel/ext_manifest.h> + +/* EXT_MAN_ELEM_PLATFORM_CONFIG_DATA elements identificators */ +enum cavs_config_elem_type { + EXT_MAN_CAVS_CONFIG_LPRO = 1, + EXT_MAN_CAVS_CONFIG_OUTBOX_SIZE, + EXT_MAN_CAVS_CONFIG_INBOX_SIZE, + EXT_MAN_CAVS_CONFIG_LAST_ELEM, /**< keep it at the end of enum list */ +}; + +/* EXT_MAN_ELEM_PLATFORM_CONFIG_DATA elements */ +struct ext_man_cavs_config_data { + struct ext_man_elem_header hdr; + + struct config_elem elems[]; +} __packed; + +#endif /* __KERNEL_EXT_MANIFEST_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lib/asm_ldo_management.h b/src/platform/intel/cavs/include/cavs/lib/asm_ldo_management.h deleted file mode 100644 index 17a2e98403a4..000000000000 --- a/src/platform/intel/cavs/include/cavs/lib/asm_ldo_management.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Lech Betlej <lech.betlej@linux.intel.com> - */ - -/** - * \file platform/apollolake/include/platform/asm_ldo_management.h - * \brief Macros for controlling LDO state specific for cAVS - * \author Lech Betlej <lech.betlej@linux.intel.com> - */ - -#ifndef __CAVS_LIB_ASM_LDO_MANAGEMENT_H__ -#define __CAVS_LIB_ASM_LDO_MANAGEMENT_H__ - -#ifndef ASSEMBLY -#warning "Header can only be used by assembly sources." -#endif - -#include <sof/lib/shim.h> - -.macro m_cavs_set_ldo_state state, ax -movi \ax, (SHIM_BASE + SHIM_LDOCTL) -s32i \state, \ax, 0 -memw -// wait loop > 300ns (min 100ns required) -movi \ax, 128 -1 : -addi \ax, \ax, -1 -nop -bnez \ax, 1b -.endm - -.macro m_cavs_set_hpldo_state state, ax, ay -movi \ax, (SHIM_BASE + SHIM_LDOCTL) -l32i \ay, \ax, 0 - -movi \ax, ~(SHIM_LDOCTL_HPSRAM_MASK) -and \ay, \ax, \ay -or \state, \ay, \state - -m_cavs_set_ldo_state \state, \ax -.endm - -.macro m_cavs_set_lpldo_state state, ax, ay -movi \ax, (SHIM_BASE + SHIM_LDOCTL) -l32i \ay, \ax, 0 -// LP SRAM mask -movi \ax, ~(SHIM_LDOCTL_LPSRAM_MASK) -and \ay, \ax, \ay -or \state, \ay, \state - -m_cavs_set_ldo_state \state, \ax -.endm - -.macro m_cavs_set_ldo_on_state ax, ay, az -movi \ay, (SHIM_BASE + SHIM_LDOCTL) -l32i \az, \ay, 0 - -movi \ax, ~(SHIM_LDOCTL_HPSRAM_MASK | SHIM_LDOCTL_LPSRAM_MASK) -and \az, \ax, \az -movi \ax, (SHIM_LDOCTL_HPSRAM_LDO_ON | SHIM_LDOCTL_LPSRAM_LDO_ON) -or \ax, \az, \ax - -m_cavs_set_ldo_state \ax, \ay -.endm - -.macro m_cavs_set_ldo_off_state ax, ay, az -// wait loop > 300ns (min 100ns required) -movi \ax, 128 -1 : - addi \ax, \ax, -1 - nop - bnez \ax, 1b -movi \ay, (SHIM_BASE + SHIM_LDOCTL) -l32i \az, \ay, 0 - -movi \ax, ~(SHIM_LDOCTL_HPSRAM_MASK | SHIM_LDOCTL_LPSRAM_MASK) -and \az, \az, \ax - -movi \ax, (SHIM_LDOCTL_HPSRAM_LDO_OFF | SHIM_LDOCTL_LPSRAM_LDO_OFF) -or \ax, \ax, \az - -s32i \ax, \ay, 0 -l32i \ax, \ay, 0 -.endm - -.macro m_cavs_set_ldo_bypass_state ax, ay, az -// wait loop > 300ns (min 100ns required) -movi \ax, 128 -1 : - addi \ax, \ax, -1 - nop - bnez \ax, 1b -movi \ay, (SHIM_BASE + SHIM_LDOCTL) -l32i \az, \ay, 0 - -movi \ax, ~(SHIM_LDOCTL_HPSRAM_MASK | SHIM_LDOCTL_LPSRAM_MASK) -and \az, \az, \ax - -movi \ax, (SHIM_LDOCTL_HPSRAM_LDO_BYPASS | SHIM_LDOCTL_LPSRAM_LDO_BYPASS) -or \ax, \ax, \az - -s32i \ax, \ay, 0 -l32i \ax, \ay, 0 -.endm - -#endif /* __CAVS_LIB_ASM_LDO_MANAGEMENT_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lib/asm_memory_management.h b/src/platform/intel/cavs/include/cavs/lib/asm_memory_management.h deleted file mode 100644 index 05a32a88fa06..000000000000 --- a/src/platform/intel/cavs/include/cavs/lib/asm_memory_management.h +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Lech Betlej <lech.betlej@linux.intel.com> - */ - -/** - * \file platform/cannonlake/include/platform/asm_memory_management.h - * \brief Macros for power gating memory banks specific for cAVS 1.8 - * \(CannonLake) and cAVS 2.0 (IceLake) - * \author Lech Betlej <lech.betlej@linux.intel.com> - */ - -#ifndef __CAVS_LIB_ASM_MEMORY_MANAGEMENT_H__ -#define __CAVS_LIB_ASM_MEMORY_MANAGEMENT_H__ - -#ifndef ASSEMBLY -#warning "ASSEMBLY macro not defined. Header can't be included in C files" -#warning "The file is intended to be included in assembly files only." -#endif - -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> - -#if CAVS_VERSION >= CAVS_VERSION_1_8 -/** - * Macro powers down entire HPSRAM. On entry literals and code for section from - * where this code is executed need to be placed in memory which is not - * HPSRAM (in case when this code is located in HPSRAM, lock memory in L1$ or - * L1 SRAM) - */ -.macro m_cavs_hpsram_power_down_entire ax, ay, az - // SEGMENT #0 - movi \az, SHIM_HSPGCTL(0) - movi \ax, SHIM_HSPGISTS(0) - movi \ay, HPSRAM_MASK(0) - s32i \ay, \ax, 0 - memw -1 : - l32i \ax, \az, 0 - bne \ax, \ay, 1b - - // SEGMENT #1 - movi \az, SHIM_HSPGCTL(1) - movi \ax, SHIM_HSPGISTS(1) - movi \ay, HPSRAM_MASK(1) - s32i \ay, \ax, 0 - memw -1 : - l32i \ax, \az, 0 - bne \ax, \ay, 1b -.endm - -.macro m_cavs_hpsram_power_change segment_index, mask, ax, ay, az - movi \ax, SHIM_HSPGCTL(\segment_index) - movi \ay, SHIM_HSPGISTS(\segment_index) - s32i \mask, \ax, 0 - memw - // assumed that HDA shared dma buffer will be in LPSRAM -1 : - l32i \ax, \ay, 0 - bne \ax, \mask, 1b -.endm - -.macro m_cavs_lpsram_power_down_entire ax, ay, az, loop_cnt_addr - movi \az, LSPGISTS - movi \ax, LSPGCTL - movi \ay, LPSRAM_MASK() - s32i \ay, \ax, 0 - memw - // assumed that HDA shared dma buffer will be in LPSRAM - movi \ax, \loop_cnt_addr - l32i \ax, \ax, 0 -1 : - addi \ax, \ax, -1 - bnez \ax, 1b -.endm - -#endif /* CAVS_VERSION == CAVS_VERSION_1_8 */ -#endif /* __CAVS_LIB_ASM_MEMORY_MANAGEMENT_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lib/clk.h b/src/platform/intel/cavs/include/cavs/lib/clk.h deleted file mode 100644 index 459d84847b11..000000000000 --- a/src/platform/intel/cavs/include/cavs/lib/clk.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -/** - * \file cavs/lib/clk.h - * \brief Clk parameters for run-time clock data, common for cAVS platforms. - */ - -#ifdef __PLATFORM_LIB_CLK_H__ - -#ifndef __CAVS_LIB_CLK_H__ -#define __CAVS_LIB_CLK_H__ - -#include <cavs/version.h> -#include <sof/lib/cpu.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> -#include <stdint.h> - -struct sof; - -/** \brief Core(s) settings, up to PLATFORM_CORE_COUNT */ -#define CLK_CPU(x) (x) - -/** \brief SSP clock r-t settings are after the core(s) settings */ -#define CLK_SSP PLATFORM_CORE_COUNT - -/* SSP clock run-time data is the last one, so total number is ssp idx +1 */ - -/** \brief Total number of clocks */ -#define NUM_CLOCKS (CLK_SSP + 1) - -extern const struct freq_table *cpu_freq; -extern const uint32_t cpu_freq_enc[]; -extern const uint32_t cpu_freq_status_mask[]; - -void platform_clock_init(struct sof *sof); - -#if CONFIG_CAVS_USE_LPRO_IN_WAITI -void platform_clock_on_waiti(void); -void platform_clock_on_wakeup(void); -#endif - -#endif /* __CAVS_LIB_CLK_H__ */ - -#else - -#error "This file shouldn't be included from outside of platform/lib/clk.h" - -#endif /* __PLATFORM_LIB_CLK_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lib/cpu.h b/src/platform/intel/cavs/include/cavs/lib/cpu.h deleted file mode 100644 index d638bfdad66c..000000000000 --- a/src/platform/intel/cavs/include/cavs/lib/cpu.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> - */ - -/** - * \file cavs/lib/cpu.h - * \brief DSP parameters, common for cAVS platforms. - */ - -#ifdef __PLATFORM_LIB_CPU_H__ - -#ifndef __CAVS_LIB_CPU_H__ -#define __CAVS_LIB_CPU_H__ - -#include <config.h> - -/** \brief Number of available DSP cores (conf. by kconfig) */ -#define PLATFORM_CORE_COUNT CONFIG_CORE_COUNT - -/** \brief Id of master DSP core */ -#define PLATFORM_MASTER_CORE_ID 0 - -#endif /* __CAVS_LIB_CPU_H__ */ - -#else - -#error "This file shouldn't be included from outside of platform/lib/cpu.h" - -#endif /* __PLATFORM_LIB_CPU_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lib/mailbox.h b/src/platform/intel/cavs/include/cavs/lib/mailbox.h index 60ef4360e10f..063ccfcf6f3e 100644 --- a/src/platform/intel/cavs/include/cavs/lib/mailbox.h +++ b/src/platform/intel/cavs/include/cavs/lib/mailbox.h @@ -11,12 +11,17 @@ #ifndef __CAVS_LIB_MAILBOX_H__ #define __CAVS_LIB_MAILBOX_H__ +#include <rtos/panic.h> #include <sof/lib/memory.h> +#include <rtos/string.h> #include <stddef.h> #include <stdint.h> /* - * The Window Region on HPSRAM for cAVS platforms is organised like this :- + * The Window Region on HPSRAM for cAVS platforms is organised like + * this. The actual region order is platform-specific, see memory.h + * files. + * * +--------------------------------------------------------------------------+ * | Offset | Region | Size | * +---------------------+----------------+-----------------------------------+ @@ -30,9 +35,6 @@ * +---------------------+----------------+-----------------------------------+ * | SRAM_SW_REG_BASE | SW Registers W0| SRAM_SW_REG_SIZE | * +---------------------+----------------+-----------------------------------+ - * - * Note: For suecreek SRAM_SW_REG window does not exist - MAILBOX_SW_REG_BASE - * and MAILBOX_SW_REG_BASE are equal to 0 */ /* window 3 - trace */ @@ -65,12 +67,55 @@ static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) { volatile uint32_t *ptr; + volatile uint32_t __sparse_cache *ptr_c; - ptr = (volatile uint32_t *)(MAILBOX_SW_REG_BASE + offset); - ptr = cache_to_uncache(ptr); + ptr_c = (volatile uint32_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache((uint32_t __sparse_cache *)ptr_c); *ptr = src; } +static inline void mailbox_sw_reg_write64(size_t offset, uint64_t src) +{ + volatile uint64_t *ptr; + volatile uint64_t __sparse_cache *ptr_c; + + ptr_c = (volatile uint64_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache((uint64_t __sparse_cache *)ptr_c); + *ptr = src; +} + +static inline uint32_t mailbox_sw_reg_read(size_t offset) +{ + volatile uint32_t *ptr; + volatile uint32_t __sparse_cache *ptr_c; + + ptr_c = (volatile uint32_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache((uint32_t __sparse_cache *)ptr_c); + + return *ptr; +} + +static inline uint64_t mailbox_sw_reg_read64(size_t offset) +{ + volatile uint64_t *ptr; + volatile uint64_t __sparse_cache *ptr_c; + + ptr_c = (volatile uint64_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache((uint64_t __sparse_cache *)ptr_c); + + return *ptr; +} + +static inline void mailbox_sw_regs_write(size_t offset, const void *src, size_t bytes) +{ + uint32_t __sparse_cache *ptr_c; + uint32_t *ptr; + + ptr_c = (uint32_t __sparse_cache *)(MAILBOX_SW_REG_BASE + offset); + ptr = cache_to_uncache(ptr_c); + memcpy_s(ptr, MAILBOX_SW_REG_SIZE - offset, src, bytes); +} + #endif /* __CAVS_LIB_MAILBOX_H__ */ #else diff --git a/src/platform/intel/cavs/include/cavs/lib/memory.h b/src/platform/intel/cavs/include/cavs/lib/memory.h index a74d4aed8686..b53c76d64b6d 100644 --- a/src/platform/intel/cavs/include/cavs/lib/memory.h +++ b/src/platform/intel/cavs/include/cavs/lib/memory.h @@ -10,62 +10,24 @@ #ifndef __CAVS_LIB_MEMORY_H__ #define __CAVS_LIB_MEMORY_H__ -#include <sof/lib/cache.h> +#include <sof/common.h> +#include <rtos/cache.h> #if !defined(__ASSEMBLER__) && !defined(LINKER) #include <sof/lib/cpu.h> #endif -#include <config.h> /* data cache line alignment */ #define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE -#define SRAM_BANK_SIZE (64 * 1024) - -#define EBB_BANKS_IN_SEGMENT 32 - -#define EBB_SEGMENT_SIZE EBB_BANKS_IN_SEGMENT - -#if CONFIG_LP_MEMORY_BANKS -#define PLATFORM_LPSRAM_EBB_COUNT CONFIG_LP_MEMORY_BANKS -#else -#define PLATFORM_LPSRAM_EBB_COUNT 0 -#endif - -#define PLATFORM_HPSRAM_EBB_COUNT CONFIG_HP_MEMORY_BANKS - -#define MAX_MEMORY_SEGMENTS PLATFORM_HPSRAM_SEGMENTS - -#if CONFIG_LP_MEMORY_BANKS -#define LP_SRAM_SIZE \ - (CONFIG_LP_MEMORY_BANKS * SRAM_BANK_SIZE) -#else -#define LP_SRAM_SIZE 0 -#endif - -#define HP_SRAM_SIZE \ - (CONFIG_HP_MEMORY_BANKS * SRAM_BANK_SIZE) - -#define PLATFORM_HPSRAM_SEGMENTS ((PLATFORM_HPSRAM_EBB_COUNT \ - + EBB_BANKS_IN_SEGMENT - 1) / EBB_BANKS_IN_SEGMENT) - -#if defined(__ASSEMBLER__) -#define LPSRAM_MASK(ignored) ((1 << PLATFORM_LPSRAM_EBB_COUNT) - 1) - -#define HPSRAM_MASK(seg_idx) ((1 << (PLATFORM_HPSRAM_EBB_COUNT \ - - EBB_BANKS_IN_SEGMENT * seg_idx)) - 1) -#else -#define LPSRAM_MASK(ignored) ((1ULL << PLATFORM_LPSRAM_EBB_COUNT) - 1) - -#define HPSRAM_MASK(seg_idx) ((1ULL << (PLATFORM_HPSRAM_EBB_COUNT \ - - EBB_BANKS_IN_SEGMENT * seg_idx)) - 1) -#endif - -#define LPSRAM_SIZE (PLATFORM_LPSRAM_EBB_COUNT * SRAM_BANK_SIZE) - #define HEAP_BUF_ALIGNMENT PLATFORM_DCACHE_ALIGN /** \brief EDF task's default stack size in bytes. */ -#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 +/* increase stack size for RTNR and GOOGLE_RTC_AUDIO_PROCESSING */ +#if defined(CONFIG_COMP_RTNR) || defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 0x2000 +#else +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 0x1000 +#endif #if !defined(__ASSEMBLER__) && !defined(LINKER) @@ -77,21 +39,27 @@ struct sof; * uncached memory region. SMP platforms without uncache can simply * align to cache line size instead. */ -#if PLATFORM_CORE_COUNT > 1 && !defined(UNIT_TEST) -#define SHARED_DATA __section(".shared_data") +#if !defined(UNIT_TEST) && !defined __ZEPHYR__ +#define SHARED_DATA __section(".shared_data") __attribute__((aligned(PLATFORM_DCACHE_ALIGN))) #else #define SHARED_DATA #endif #define SRAM_ALIAS_BASE 0x9E000000 #define SRAM_ALIAS_MASK 0xFF000000 -#define SRAM_ALIAS_OFFSET 0x20000000 +#define SRAM_ALIAS_OFFSET SRAM_UNCACHED_ALIAS + +#if !defined UNIT_TEST +static inline void __sparse_cache *uncache_to_cache(void *address) +{ + return (void __sparse_cache *)((uintptr_t)(address) | SRAM_ALIAS_OFFSET); +} + +static inline void *cache_to_uncache(void __sparse_cache *address) +{ + return (void *)((uintptr_t)(address) & ~SRAM_ALIAS_OFFSET); +} -#ifndef UNIT_TEST -#define uncache_to_cache(address) \ - ((__typeof__((address)))((uint32_t)((address)) + SRAM_ALIAS_OFFSET)) -#define cache_to_uncache(address) \ - ((__typeof__((address)))((uint32_t)((address)) - SRAM_ALIAS_OFFSET)) #define is_uncached(address) \ (((uint32_t)(address) & SRAM_ALIAS_MASK) == SRAM_ALIAS_BASE) #else @@ -100,6 +68,13 @@ struct sof; #define is_uncached(address) 0 #endif +#if !defined UNIT_TEST && !defined __ZEPHYR__ +#define cache_to_uncache_init(address) \ + ((__typeof__((address)))((uint32_t)((address)) - SRAM_ALIAS_OFFSET)) +#else +#define cache_to_uncache_init(address) address +#endif + /** * \brief Returns pointer to the memory shared by multiple cores. * \param[in,out] ptr Initial pointer to the allocated memory. @@ -112,25 +87,14 @@ struct sof; */ static inline void *platform_shared_get(void *ptr, int bytes) { -#if PLATFORM_CORE_COUNT > 1 - dcache_invalidate_region(ptr, bytes); +#if CONFIG_CORE_COUNT > 1 && !defined __ZEPHYR__ + dcache_invalidate_region((__sparse_force void __sparse_cache *)ptr, bytes); return cache_to_uncache(ptr); #else return ptr; #endif } -/** - * \brief Function for keeping shared data synchronized. - * It's used after usage of data shared by different cores. - * Such data is either statically marked with SHARED_DATA - * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. - * cAVS platforms use uncached memory region, so no additional - * synchronization is needed, but for SMP platforms without uncache - * this macro should writeback and invalidate data. - */ -static inline void platform_shared_commit(void *ptr, int bytes) { } - /** * \brief Transforms pointer if necessary before freeing the memory. * \param[in,out] ptr Pointer to the allocated memory. @@ -138,14 +102,16 @@ static inline void platform_shared_commit(void *ptr, int bytes) { } */ static inline void *platform_rfree_prepare(void *ptr) { - /* free should operate only on cached addresses */ - return is_uncached(ptr) ? uncache_to_cache(ptr) : ptr; + return ptr; } void platform_init_memmap(struct sof *sof); #endif +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + #endif /* __CAVS_LIB_MEMORY_H__ */ #else diff --git a/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h b/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h deleted file mode 100644 index 0234b9eb1ffd..000000000000 --- a/src/platform/intel/cavs/include/cavs/lib/pm_runtime.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file cavs/lib/pm_runtime.h - * \brief Runtime power management header file for cAVS platforms - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __PLATFORM_LIB_PM_RUNTIME_H__ - -#ifndef __CAVS_LIB_PM_RUNTIME_H__ -#define __CAVS_LIB_PM_RUNTIME_H__ - -struct pm_runtime_data; - -/** \brief cAVS specific runtime power management data. */ -struct cavs_pm_runtime_data { - int dsp_d0_sref; /**< simple ref counter, accessed by core 0 only */ -}; - -#endif - -#else - -#error "Do not include outside of platform/lib/pm_runtime.h" - -#endif diff --git a/src/platform/intel/cavs/include/cavs/lib/power_down.h b/src/platform/intel/cavs/include/cavs/lib/power_down.h index d8cd322859df..203deacd5f80 100644 --- a/src/platform/intel/cavs/include/cavs/lib/power_down.h +++ b/src/platform/intel/cavs/include/cavs/lib/power_down.h @@ -11,6 +11,8 @@ #include <stdbool.h> #include <stdint.h> +#include <sof/compiler_attributes.h> + /** * Power down procedure. * Locks its code in L1 cache and shuts down memories. @@ -19,6 +21,6 @@ * (each bit corresponds to one ebb) * @return nothing returned - this function never quits */ -void power_down(bool disable_lpsram, uint32_t *hpsram_pwrgating_mask); +void power_down(bool disable_lpsram, uint32_t __sparse_cache *hpsram_pwrgating_mask); #endif /* __CAVS_LIB_POWER_DOWN_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lps_ctx.h b/src/platform/intel/cavs/include/cavs/lps_ctx.h deleted file mode 100644 index 4e75d4cd4c4c..000000000000 --- a/src/platform/intel/cavs/include/cavs/lps_ctx.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifndef __CAVS_LPS_CTX_H__ -#define __CAVS_LPS_CTX_H__ - -#include <xtensa/xtruntime-frames.h> - -STRUCT_BEGIN -STRUCT_FIELD(void*, 4, lps_ctx_, vector_level_2) -STRUCT_FIELD(void*, 4, lps_ctx_, vector_level_3) -STRUCT_FIELD(void*, 4, lps_ctx_, vector_level_4) -STRUCT_FIELD(void*, 4, lps_ctx_, vector_level_5) -STRUCT_FIELD(long, 4, lps_ctx_, intenable) -STRUCT_FIELD(long, 4, lps_ctx_, memmap_vecbase_reset) -STRUCT_FIELD(long, 4, lps_ctx_, threadptr) -STRUCT_FIELD(void*, 4, lps_ctx_, task_ctx) -STRUCT_END(lps_ctx) - -#endif /*__CAVS_LPS_CTX_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/lps_wait.h b/src/platform/intel/cavs/include/cavs/lps_wait.h deleted file mode 100644 index 64952f850764..000000000000 --- a/src/platform/intel/cavs/include/cavs/lps_wait.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifndef __CAVS_LPS_WAIT_H__ -#define __CAVS_LPS_WAIT_H__ - -extern void *lps_pic_restore_vector; -extern void *lps_pic_restore_vector_end; -extern void *lps_pic_restore_vector_literals; - -void lps_wait_for_interrupt(int level); - -#endif /*__CAVS_LPS_WAIT_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/mem_window.h b/src/platform/intel/cavs/include/cavs/mem_window.h index 614103507ef5..0792d4e8f925 100644 --- a/src/platform/intel/cavs/include/cavs/mem_window.h +++ b/src/platform/intel/cavs/include/cavs/mem_window.h @@ -8,7 +8,7 @@ #ifndef __CAVS_MEM_WINDOW_H__ #define __CAVS_MEM_WINDOW_H__ -#include <sof/bit.h> +#include <rtos/bit.h> #include <stdint.h> /** \brief Zero memory window during initialization */ diff --git a/src/platform/intel/cavs/include/cavs/trace/trace.h b/src/platform/intel/cavs/include/cavs/trace/trace.h new file mode 100644 index 000000000000..738a28530094 --- /dev/null +++ b/src/platform/intel/cavs/include/cavs/trace/trace.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +#ifdef __PLATFORM_TRACE_TRACE_H__ + +#ifndef __CAVS_TRACE_TRACE_H__ +#define __CAVS_TRACE_TRACE_H__ + +#include <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <stdint.h> + +#if CONFIG_IPC_MAJOR_4 +/* Platform defined trace code */ +static inline void platform_trace_point(uint32_t x) +{ } +#else +#define PLATFORM_TRACEP_SECONDARY_CORE(x) \ + (SRAM_REG_FW_TRACEP_SECONDARY_CORE_BASE + ((x) - 1) * 0x4) + +/* Platform defined trace code */ +static inline void platform_trace_point(uint32_t x) +{ + int cpu = cpu_get_id(); + uint32_t offset; + + if (cpu == PLATFORM_PRIMARY_CORE_ID) + offset = SRAM_REG_FW_TRACEP; + else + offset = PLATFORM_TRACEP_SECONDARY_CORE(cpu); + + mailbox_sw_reg_write(offset, x); +} +#endif +#endif /* __CAVS_TRACE_TRACE_H__ */ + +#else + +#error "This file shouldn't be included from outside of platform/trace/trace.h" + +#endif /* __PLATFORM_TRACE_H__ */ diff --git a/src/platform/intel/cavs/include/cavs/version.h b/src/platform/intel/cavs/include/cavs/version.h index be73cffc536b..a56a88105c7d 100644 --- a/src/platform/intel/cavs/include/cavs/version.h +++ b/src/platform/intel/cavs/include/cavs/version.h @@ -8,22 +8,13 @@ #ifndef __CAVS_VERSION_H__ #define __CAVS_VERSION_H__ -#include <config.h> - -#define CAVS_VERSION_1_5 0x10500 -#define CAVS_VERSION_1_8 0x10800 -#define CAVS_VERSION_2_0 0x20000 #define CAVS_VERSION_2_5 0x20500 /* CAVS version defined by CONFIG_CAVS_VER_*/ -#if CONFIG_CAVS_VERSION_1_5 -#define CAVS_VERSION CAVS_VERSION_1_5 -#elif CONFIG_CAVS_VERSION_1_8 -#define CAVS_VERSION CAVS_VERSION_1_8 -#elif CONFIG_CAVS_VERSION_2_0 -#define CAVS_VERSION CAVS_VERSION_2_0 -#elif CONFIG_CAVS_VERSION_2_5 +#if CONFIG_CAVS_VERSION_2_5 #define CAVS_VERSION CAVS_VERSION_2_5 #endif +#define HW_CFG_VERSION CAVS_VERSION + #endif /* __CAVS_VERSION_H__ */ diff --git a/src/platform/intel/cavs/lib/CMakeLists.txt b/src/platform/intel/cavs/lib/CMakeLists.txt deleted file mode 100644 index 1ed93d8bf39a..000000000000 --- a/src/platform/intel/cavs/lib/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_library(pdown STATIC "") -target_link_libraries(pdown sof_options) -target_compile_options(pdown PRIVATE -mtext-section-literals) - -add_local_sources(pdown power_down.S) -target_link_libraries(sof_static_libraries INTERFACE pdown) - -add_local_sources(sof - clk.c - dai.c - dma.c - memory.c - pm_runtime.c - pm_memory.c -) - -if(CONFIG_MEM_WND) - add_local_sources(sof mem_window.c) -endif() diff --git a/src/platform/intel/cavs/lib/clk.c b/src/platform/intel/cavs/lib/clk.c deleted file mode 100644 index 834a85b491f4..000000000000 --- a/src/platform/intel/cavs/lib/clk.c +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/sof.h> -#include <sof/spinlock.h> - -static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; - -#if CAVS_VERSION == CAVS_VERSION_1_5 -static inline void select_cpu_clock(int freq_idx, bool release_unused) -{ - uint32_t enc = cpu_freq_enc[freq_idx]; - - io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL, SHIM_CLKCTL_HDCS, 0); - io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL, - SHIM_CLKCTL_DPCS_MASK(cpu_get_id()), - enc); -} -#else -static inline void select_cpu_clock(int freq_idx, bool release_unused) -{ - uint32_t enc = cpu_freq_enc[freq_idx]; - uint32_t status_mask = cpu_freq_status_mask[freq_idx]; - - /* request clock */ - io_reg_write(SHIM_BASE + SHIM_CLKCTL, - io_reg_read(SHIM_BASE + SHIM_CLKCTL) | enc); - - /* wait for requested clock to be on */ - while ((io_reg_read(SHIM_BASE + SHIM_CLKSTS) & - status_mask) != status_mask) - idelay(PLATFORM_DEFAULT_DELAY); - - /* switch to requested clock */ - io_reg_update_bits(SHIM_BASE + SHIM_CLKCTL, - SHIM_CLKCTL_OSC_SOURCE_MASK, enc); - - if (release_unused) { - /* release other clocks */ - io_reg_write(SHIM_BASE + SHIM_CLKCTL, - (io_reg_read(SHIM_BASE + SHIM_CLKCTL) & - ~SHIM_CLKCTL_OSC_REQUEST_MASK) | enc); - } -} -#endif - -static int clock_platform_set_cpu_freq(int clock, int freq_idx) -{ - select_cpu_clock(freq_idx, true); - return 0; -} - -#if CONFIG_CAVS_USE_LPRO_IN_WAITI -/* Store clock source that was active before going to waiti, - * so it can be restored on wake up. - */ -static SHARED_DATA int active_freq_idx = CPU_DEFAULT_IDX; - -static inline int get_cpu_current_freq_idx(void) -{ - struct clock_info *clk_info = clocks_get() + CLK_CPU(cpu_get_id()); - - return clk_info->current_freq_idx; -} - -static inline void set_cpu_current_freq_idx(int freq_idx) -{ - int i; - struct clock_info *clk_info = clocks_get(); - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) - clk_info[i].current_freq_idx = freq_idx; - - platform_shared_commit(clk_info, - sizeof(*clk_info) * PLATFORM_CORE_COUNT); -} - -void platform_clock_on_wakeup(void) -{ - int freq_idx = *cache_to_uncache(&active_freq_idx); - - if (freq_idx != get_cpu_current_freq_idx()) { - select_cpu_clock(freq_idx, true); - set_cpu_current_freq_idx(freq_idx); - } -} - -void platform_clock_on_waiti(void) -{ - int freq_idx = get_cpu_current_freq_idx(); - - *cache_to_uncache(&active_freq_idx) = freq_idx; - - if (freq_idx != CPU_LPRO_FREQ_IDX) { - /* LPRO requests are fast, but requests for other ROs - * can take a lot of time. That's why it's better to - * not release active clock just for waiti, - * so they can be switched without delay on wake up. - */ - select_cpu_clock(CPU_LPRO_FREQ_IDX, false); - set_cpu_current_freq_idx(CPU_LPRO_FREQ_IDX); - } -} -#endif - -void platform_clock_init(struct sof *sof) -{ - int i; - - sof->clocks = - cache_to_uncache((struct clock_info *)platform_clocks_info); - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - sof->clocks[i] = (struct clock_info) { - .freqs_num = NUM_CPU_FREQ, - .freqs = 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 = clock_platform_set_cpu_freq, - }; - - spinlock_init(&sof->clocks[i].lock); - } - - sof->clocks[CLK_SSP] = (struct clock_info) { - .freqs_num = NUM_SSP_FREQ, - .freqs = ssp_freq, - .default_freq_idx = SSP_DEFAULT_IDX, - .current_freq_idx = SSP_DEFAULT_IDX, - .notification_id = NOTIFIER_ID_SSP_FREQ, - .notification_mask = NOTIFIER_TARGET_CORE_ALL_MASK, - .set_freq = NULL, - }; - - spinlock_init(&sof->clocks[CLK_SSP].lock); - - platform_shared_commit(sof->clocks, sizeof(*sof->clocks) * NUM_CLOCKS); -} diff --git a/src/platform/intel/cavs/lib/dai.c b/src/platform/intel/cavs/lib/dai.c deleted file mode 100644 index eb405ccf8ec2..000000000000 --- a/src/platform/intel/cavs/lib/dai.c +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/hda.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/mn.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <ipc/dai.h> -#include <ipc/stream.h> -#include <config.h> - -#if CONFIG_CAVS_SSP - -#include <sof/drivers/ssp.h> - -static SHARED_DATA struct dai ssp[(DAI_NUM_SSP_BASE + DAI_NUM_SSP_EXT)]; - -#endif - -#if CONFIG_CAVS_DMIC - -#include <sof/drivers/dmic.h> - -static SHARED_DATA struct dai dmic[2] = { - /* Testing idea if DMIC FIFOs A and B to access the same microphones - * with two different sample rate and PCM format could be presented - * similarly as SSP0..N. The difference however is that the DMIC - * programming is global and not per FIFO. - */ - - /* Primary FIFO A */ - { - .index = 0, - .plat_data = { - .base = DMIC_BASE, - .irq = IRQ_EXT_DMIC_LVL5(0), - .irq_name = irq_name_level5, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = 0, /* No playback */ - .handshake = 0, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = DMIC_BASE + OUTDATA0, - .handshake = DMA_HANDSHAKE_DMIC_CH0, - } - }, - .drv = &dmic_driver, - }, - /* Secondary FIFO B */ - { - .index = 1, - .plat_data = { - .base = DMIC_BASE, - .irq = IRQ_EXT_DMIC_LVL5(1), - .irq_name = irq_name_level5, - .fifo[SOF_IPC_STREAM_PLAYBACK] = { - .offset = 0, /* No playback */ - .handshake = 0, - }, - .fifo[SOF_IPC_STREAM_CAPTURE] = { - .offset = DMIC_BASE + OUTDATA1, - .handshake = DMA_HANDSHAKE_DMIC_CH1, - } - }, - .drv = &dmic_driver, - } -}; - -#endif - -#if CONFIG_CAVS_ALH - -#include <sof/drivers/alh.h> - -static SHARED_DATA struct dai alh[DAI_NUM_ALH_BI_DIR_LINKS]; -#endif - -static SHARED_DATA struct dai hda[(DAI_NUM_HDA_OUT + DAI_NUM_HDA_IN)]; - -const struct dai_type_info dti[] = { -#if CONFIG_CAVS_SSP - { - .type = SOF_DAI_INTEL_SSP, - .dai_array = cache_to_uncache((struct dai *)ssp), - .num_dais = ARRAY_SIZE(ssp) - }, -#endif -#if CONFIG_CAVS_DMIC - { - .type = SOF_DAI_INTEL_DMIC, - .dai_array = cache_to_uncache((struct dai *)dmic), - .num_dais = ARRAY_SIZE(dmic) - }, -#endif - { - .type = SOF_DAI_INTEL_HDA, - .dai_array = cache_to_uncache((struct dai *)hda), - .num_dais = ARRAY_SIZE(hda) - }, -#if CONFIG_CAVS_ALH - { - .type = SOF_DAI_INTEL_ALH, - .dai_array = cache_to_uncache((struct dai *)alh), - .num_dais = ARRAY_SIZE(alh) - } -#endif -}; - -const struct dai_info lib_dai = { - .dai_type_array = dti, - .num_dai_types = ARRAY_SIZE(dti) -}; - -int dai_init(struct sof *sof) -{ - struct dai *dai; - int i; - - sof->dai_info = &lib_dai; - -#if CONFIG_CAVS_SSP - dai = cache_to_uncache((struct dai *)ssp); - - /* init ssp */ - for (i = 0; i < ARRAY_SIZE(ssp); i++) { - dai[i].index = i; - dai[i].drv = &ssp_driver; - dai[i].plat_data.base = SSP_BASE(i); - dai[i].plat_data.irq = IRQ_EXT_SSPx_LVL5(i); - dai[i].plat_data.irq_name = irq_name_level5; - dai[i].plat_data.fifo[SOF_IPC_STREAM_PLAYBACK].offset = - SSP_BASE(i) + SSDR; - dai[i].plat_data.fifo[SOF_IPC_STREAM_PLAYBACK].handshake = - DMA_HANDSHAKE_SSP0_TX + 2 * i; - dai[i].plat_data.fifo[SOF_IPC_STREAM_CAPTURE].offset = - SSP_BASE(i) + SSDR; - dai[i].plat_data.fifo[SOF_IPC_STREAM_CAPTURE].handshake = - DMA_HANDSHAKE_SSP0_RX + 2 * i; - /* initialize spin locks early to enable ref counting */ - spinlock_init(&dai[i].lock); - } - - platform_shared_commit(dai, sizeof(*dai) * ARRAY_SIZE(ssp)); -#endif - -#if CONFIG_CAVS_MN - mn_init(sof); -#endif - - dai = cache_to_uncache((struct dai *)hda); - - /* init hd/a, note that size depends on the platform caps */ - for (i = 0; i < ARRAY_SIZE(hda); i++) { - dai[i].index = i; - dai[i].drv = &hda_driver; - spinlock_init(&dai[i].lock); - } - - platform_shared_commit(dai, sizeof(*dai) * ARRAY_SIZE(hda)); - -#if (CONFIG_CAVS_DMIC) - dai = cache_to_uncache((struct dai *)dmic); - - /* init dmic */ - for (i = 0; i < ARRAY_SIZE(dmic); i++) - spinlock_init(&dai[i].lock); - - platform_shared_commit(dai, sizeof(*dai) * ARRAY_SIZE(dmic)); -#endif - -#if CONFIG_CAVS_ALH - dai = cache_to_uncache((struct dai *)alh); - - for (i = 0; i < ARRAY_SIZE(alh); i++) { - dai[i].index = (i / DAI_NUM_ALH_BI_DIR_LINKS_GROUP) << 8 | - (i % DAI_NUM_ALH_BI_DIR_LINKS_GROUP); - dai[i].drv = &alh_driver; - - /* set burst length to align with DMAT value in the - * Audio Link Hub. - */ - dai[i].plat_data.fifo[SOF_IPC_STREAM_PLAYBACK].depth = - ALH_GPDMA_BURST_LENGTH; - dai[i].plat_data.fifo[SOF_IPC_STREAM_CAPTURE].depth = - ALH_GPDMA_BURST_LENGTH; - spinlock_init(&dai[i].lock); - } - - platform_shared_commit(dai, sizeof(*dai) * ARRAY_SIZE(alh)); -#endif - - return 0; -} diff --git a/src/platform/intel/cavs/lib/dma.c b/src/platform/intel/cavs/lib/dma.c deleted file mode 100644 index aa826de3dc1f..000000000000 --- a/src/platform/intel/cavs/lib/dma.c +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/dw-dma.h> -#include <sof/drivers/hda-dma.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/dma.h> -#include <sof/lib/memory.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <config.h> - -#if CONFIG_APOLLOLAKE -#define DMAC0_CLASS 1 -#define DMAC1_CLASS 2 -#define DMAC_HOST_OUT_CHANNELS_COUNT 6 -#define DMAC_LINK_IN_CHANNELS_COUNT 8 -#define DMAC_LINK_OUT_CHANNELS_COUNT 8 -#elif CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_TIGERLAKE -#define DMAC0_CLASS 6 -#define DMAC1_CLASS 7 -#define DMAC_HOST_OUT_CHANNELS_COUNT 9 -#define DMAC_LINK_IN_CHANNELS_COUNT 9 -#define DMAC_LINK_OUT_CHANNELS_COUNT 7 -#elif CONFIG_SUECREEK -#define DMAC0_CLASS 6 -#define DMAC1_CLASS 7 -#endif - -const struct dw_drv_plat_data dmac0 = { - .chan[0] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[1] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[2] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[3] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[4] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[5] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[6] = { - .class = DMAC0_CLASS, - .weight = 0, - }, - .chan[7] = { - .class = DMAC0_CLASS, - .weight = 0, - }, -}; - -const struct dw_drv_plat_data dmac1 = { - .chan[0] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[1] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[2] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[3] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[4] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[5] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[6] = { - .class = DMAC1_CLASS, - .weight = 0, - }, - .chan[7] = { - .class = DMAC1_CLASS, - .weight = 0, - }, -}; - -#if CONFIG_SUECREEK -struct SHARED_DATA dma dma[PLATFORM_NUM_DMACS] = { -{ /* LP GP DMAC 0 */ - .plat_data = { - .id = DMA_GP_LP_DMAC0, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, - .caps = DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_SSI | DMA_DEV_DMIC, - .base = LP_GP_DMA_BASE(0), - .channels = 8, - .irq = IRQ_EXT_LP_GPDMA0_LVL5(0), - .irq_name = irq_name_level5, - .drv_plat_data = &dmac0, - }, - .ops = &dw_dma_ops, -}, -{ /* LP GP DMAC 1 */ - .plat_data = { - .id = DMA_GP_LP_DMAC1, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, - .caps = DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC, - .base = LP_GP_DMA_BASE(1), - .channels = 8, - .irq = IRQ_EXT_LP_GPDMA1_LVL5(0), - .irq_name = irq_name_level5, - .drv_plat_data = &dmac1, - }, - .ops = &dw_dma_ops, -}, -{ /* LP GP DMAC 2 */ - .plat_data = { - .id = DMA_GP_LP_DMAC2, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, - .caps = DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC, - .base = LP_GP_DMA_BASE(1), - .channels = 8, - .irq = IRQ_EXT_LP_GPDMA1_LVL5(0), - .irq_name = irq_name_level5, - .drv_plat_data = &dmac1, - }, - .ops = &dw_dma_ops, -}, -}; - -#else -SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { -{ /* Low Power GP DMAC 0 */ - .plat_data = { - .id = DMA_GP_LP_DMAC0, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, - .caps = DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | - DMA_DEV_ALH, - .base = LP_GP_DMA_BASE(0), - .channels = 8, - .irq = IRQ_EXT_LP_GPDMA0_LVL5(0), - .irq_name = irq_name_level5, - .drv_plat_data = &dmac0, - }, - .ops = &dw_dma_ops, -}, -{ /* Low Power GP DMAC 1 */ - .plat_data = { - .id = DMA_GP_LP_DMAC1, - .dir = DMA_DIR_MEM_TO_MEM | DMA_DIR_MEM_TO_DEV | - DMA_DIR_DEV_TO_MEM | DMA_DIR_DEV_TO_DEV, - .caps = DMA_CAP_GP_LP, - .devs = DMA_DEV_SSP | DMA_DEV_DMIC | - DMA_DEV_ALH, - .base = LP_GP_DMA_BASE(1), - .channels = 8, - .irq = IRQ_EXT_LP_GPDMA1_LVL5(0), - .irq_name = irq_name_level5, - .drv_plat_data = &dmac1, - }, - .ops = &dw_dma_ops, -}, -{ /* Host In DMAC */ - .plat_data = { - .id = DMA_HOST_IN_DMAC, - .dir = DMA_DIR_LMEM_TO_HMEM, - .caps = DMA_CAP_HDA, - .devs = DMA_DEV_HOST, - .base = GTW_HOST_IN_STREAM_BASE(0), - .channels = 7, - .chan_size = GTW_HOST_IN_STREAM_SIZE, - }, - .ops = &hda_host_dma_ops, -}, -{ /* Host out DMAC */ - .plat_data = { - .id = DMA_HOST_OUT_DMAC, - .dir = DMA_DIR_HMEM_TO_LMEM, - .caps = DMA_CAP_HDA, - .devs = DMA_DEV_HOST, - .base = GTW_HOST_OUT_STREAM_BASE(0), - .channels = DMAC_HOST_OUT_CHANNELS_COUNT, - .chan_size = GTW_HOST_OUT_STREAM_SIZE, - }, - .ops = &hda_host_dma_ops, -}, -{ /* Link In DMAC */ - .plat_data = { - .id = DMA_LINK_IN_DMAC, - .dir = DMA_DIR_DEV_TO_MEM, - .caps = DMA_CAP_HDA, - .devs = DMA_DEV_HDA, - .base = GTW_LINK_IN_STREAM_BASE(0), - .channels = DMAC_LINK_IN_CHANNELS_COUNT, - .chan_size = GTW_LINK_IN_STREAM_SIZE, - }, - .ops = &hda_link_dma_ops, -}, -{ /* Link out DMAC */ - .plat_data = { - .id = DMA_LINK_OUT_DMAC, - .dir = DMA_DIR_MEM_TO_DEV, - .caps = DMA_CAP_HDA, - .devs = DMA_DEV_HDA, - .base = GTW_LINK_OUT_STREAM_BASE(0), - .channels = DMAC_LINK_OUT_CHANNELS_COUNT, - .chan_size = GTW_LINK_OUT_STREAM_SIZE, - }, - .ops = &hda_link_dma_ops, -},}; -#endif - -const struct dma_info lib_dma = { - .dma_array = cache_to_uncache((struct dma *)dma), - .num_dmas = ARRAY_SIZE(dma) -}; - -/* Initialize all platform DMAC's */ -int dmac_init(struct sof *sof) -{ - int i; - /* no probing before first use */ - - /* TODO: dynamic init based on platform settings */ - - sof->dma_info = &lib_dma; - - /* early lock initialization for ref counting */ - for (i = 0; i < sof->dma_info->num_dmas; i++) - spinlock_init(&sof->dma_info->dma_array[i].lock); - - platform_shared_commit(sof->dma_info->dma_array, - sizeof(struct dma) * sof->dma_info->num_dmas); - - return 0; -} diff --git a/src/platform/intel/cavs/lib/mem_window.c b/src/platform/intel/cavs/lib/mem_window.c deleted file mode 100644 index b813109de04d..000000000000 --- a/src/platform/intel/cavs/lib/mem_window.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Marcin Maka <marcin.maka@linux.intel.com> - -/** - * \file platform/intel/cavs/mem_window.c - * \brief Memory windows programming and initialization - * \author Marcin Maka <marcin.maka@linux.intel.com> - */ - -#include <cavs/mem_window.h> -#include <sof/lib/alloc.h> -#include <sof/lib/io.h> -#include <sof/lib/shim.h> - -static inline void memory_window_init(uint32_t index, - uint32_t base, uint32_t size, - uint32_t zero_base, uint32_t zero_size, - uint32_t wnd_flags, uint32_t init_flags) -{ - io_reg_write(DMWLO(index), size | 0x7); - io_reg_write(DMWBA(index), base | wnd_flags); - if (init_flags & MEM_WND_INIT_CLEAR) { - bzero((void *)zero_base, zero_size); - dcache_writeback_region((void *)zero_base, zero_size); - } -} - -void platform_memory_windows_init(uint32_t flags) -{ - /* window0, for fw status & outbox/uplink mbox */ - memory_window_init(0, HP_SRAM_WIN0_BASE, HP_SRAM_WIN0_SIZE, - HP_SRAM_WIN0_BASE + SRAM_REG_FW_END, - HP_SRAM_WIN0_SIZE - SRAM_REG_FW_END, - DMWBA_READONLY | DMWBA_ENABLE, flags); - - /* window1, for inbox/downlink mbox */ - memory_window_init(1, HP_SRAM_WIN1_BASE, HP_SRAM_WIN1_SIZE, - HP_SRAM_WIN1_BASE, HP_SRAM_WIN1_SIZE, - DMWBA_ENABLE, flags); - - /* window2, for debug */ - memory_window_init(2, HP_SRAM_WIN2_BASE, HP_SRAM_WIN2_SIZE, - HP_SRAM_WIN2_BASE, HP_SRAM_WIN2_SIZE, - DMWBA_ENABLE, flags); - - /* window3, for trace - * zeroed by trace initialization - */ - memory_window_init(3, HP_SRAM_WIN3_BASE, HP_SRAM_WIN3_SIZE, - HP_SRAM_WIN3_BASE, HP_SRAM_WIN3_SIZE, - DMWBA_READONLY | DMWBA_ENABLE, 0); -} diff --git a/src/platform/intel/cavs/lib/memory.c b/src/platform/intel/cavs/lib/memory.c deleted file mode 100644 index 55275bc3052e..000000000000 --- a/src/platform/intel/cavs/lib/memory.c +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/platform.h> -#include <sof/sof.h> -#include <ipc/topology.h> -#include <stdint.h> - -#define uncached_block_hdr(hdr) cache_to_uncache((struct block_hdr *)(hdr)) -#define uncached_block_map(map) cache_to_uncache((struct block_map *)(map)) - -extern uintptr_t _system_heap, _system_runtime_heap, _module_heap; -extern uintptr_t _buffer_heap, _sof_core_s_start; - -/* Heap blocks for system runtime for master core */ -static SHARED_DATA struct block_hdr sys_rt_0_block64[HEAP_SYS_RT_0_COUNT64]; -static SHARED_DATA struct block_hdr sys_rt_0_block512[HEAP_SYS_RT_0_COUNT512]; -static SHARED_DATA struct block_hdr sys_rt_0_block1024[HEAP_SYS_RT_0_COUNT1024]; - -/* Heap blocks for system runtime for slave core */ -#if PLATFORM_CORE_COUNT > 1 -static SHARED_DATA struct block_hdr - sys_rt_x_block64[PLATFORM_CORE_COUNT - 1][HEAP_SYS_RT_X_COUNT64]; -static SHARED_DATA struct block_hdr - sys_rt_x_block512[PLATFORM_CORE_COUNT - 1][HEAP_SYS_RT_X_COUNT512]; -static SHARED_DATA struct block_hdr - sys_rt_x_block1024[PLATFORM_CORE_COUNT - 1][HEAP_SYS_RT_X_COUNT1024]; -#endif - -/* Heap memory for system runtime */ -static SHARED_DATA struct block_map sys_rt_heap_map[PLATFORM_CORE_COUNT][3] = { - { BLOCK_DEF(64, HEAP_SYS_RT_0_COUNT64, - uncached_block_hdr(sys_rt_0_block64)), - BLOCK_DEF(512, HEAP_SYS_RT_0_COUNT512, - uncached_block_hdr(sys_rt_0_block512)), - BLOCK_DEF(1024, HEAP_SYS_RT_0_COUNT1024, - uncached_block_hdr(sys_rt_0_block1024)), }, -#if PLATFORM_CORE_COUNT > 1 - { BLOCK_DEF(64, HEAP_SYS_RT_X_COUNT64, - uncached_block_hdr(sys_rt_x_block64[0])), - BLOCK_DEF(512, HEAP_SYS_RT_X_COUNT512, - uncached_block_hdr(sys_rt_x_block512[0])), - BLOCK_DEF(1024, HEAP_SYS_RT_X_COUNT1024, - uncached_block_hdr(sys_rt_x_block1024[0])), }, -#endif -#if PLATFORM_CORE_COUNT > 2 - { BLOCK_DEF(64, HEAP_SYS_RT_X_COUNT64, - uncached_block_hdr(sys_rt_x_block64[1])), - BLOCK_DEF(512, HEAP_SYS_RT_X_COUNT512, - uncached_block_hdr(sys_rt_x_block512[1])), - BLOCK_DEF(1024, HEAP_SYS_RT_X_COUNT1024, - uncached_block_hdr(sys_rt_x_block1024[1])), }, -#endif -#if PLATFORM_CORE_COUNT > 3 - { BLOCK_DEF(64, HEAP_SYS_RT_X_COUNT64, - uncached_block_hdr(sys_rt_x_block64[2])), - BLOCK_DEF(512, HEAP_SYS_RT_X_COUNT512, - uncached_block_hdr(sys_rt_x_block512[2])), - BLOCK_DEF(1024, HEAP_SYS_RT_X_COUNT1024, - uncached_block_hdr(sys_rt_x_block1024[2])), }, -#endif -}; - -/* Heap blocks for modules */ -static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; -static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; -static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; -static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; -static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; -static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; -static SHARED_DATA struct block_hdr mod_block4096[HEAP_RT_COUNT4096]; - -/* Heap memory map for modules */ -static SHARED_DATA struct block_map rt_heap_map[] = { - BLOCK_DEF(64, HEAP_RT_COUNT64, uncached_block_hdr(mod_block64)), - BLOCK_DEF(128, HEAP_RT_COUNT128, uncached_block_hdr(mod_block128)), - BLOCK_DEF(256, HEAP_RT_COUNT256, uncached_block_hdr(mod_block256)), - BLOCK_DEF(512, HEAP_RT_COUNT512, uncached_block_hdr(mod_block512)), - BLOCK_DEF(1024, HEAP_RT_COUNT1024, uncached_block_hdr(mod_block1024)), - BLOCK_DEF(2048, HEAP_RT_COUNT2048, uncached_block_hdr(mod_block2048)), - BLOCK_DEF(4096, HEAP_RT_COUNT4096, uncached_block_hdr(mod_block4096)), -}; - -/* Heap blocks for buffers */ -static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; -static SHARED_DATA struct block_hdr lp_buf_block[HEAP_LP_BUFFER_COUNT]; - -/* Heap memory map for buffers */ -static SHARED_DATA struct block_map buf_heap_map[] = { - BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, - uncached_block_hdr(buf_block)), -}; - -static SHARED_DATA struct block_map lp_buf_heap_map[] = { - BLOCK_DEF(HEAP_LP_BUFFER_BLOCK_SIZE, HEAP_LP_BUFFER_COUNT, - uncached_block_hdr(lp_buf_block)), -}; - -static SHARED_DATA struct mm memmap; - -void platform_init_memmap(struct sof *sof) -{ - int i; - - /* access memory map through uncached region */ - sof->memory_map = cache_to_uncache(&memmap); - - /* .system master core initialization */ - sof->memory_map->system[0].heap = (uintptr_t)&_system_heap; - sof->memory_map->system[0].size = HEAP_SYSTEM_M_SIZE; - sof->memory_map->system[0].info.free = HEAP_SYSTEM_M_SIZE; - sof->memory_map->system[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_EXT | - SOF_MEM_CAPS_CACHE; - - /* .system_runtime master core initialization */ - sof->memory_map->system_runtime[0].blocks = - ARRAY_SIZE(sys_rt_heap_map[0]); - sof->memory_map->system_runtime[0].map = - uncached_block_map(sys_rt_heap_map[0]); - sof->memory_map->system_runtime[0].heap = - (uintptr_t)&_system_runtime_heap; - sof->memory_map->system_runtime[0].size = HEAP_SYS_RUNTIME_M_SIZE; - sof->memory_map->system_runtime[0].info.free = HEAP_SYS_RUNTIME_M_SIZE; - sof->memory_map->system_runtime[0].caps = SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_EXT | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA; - - /* .system and .system_runtime slave core initialization */ - for (i = 1; i < PLATFORM_CORE_COUNT; i++) { - /* .system init */ - sof->memory_map->system[i].heap = - (uintptr_t)&_sof_core_s_start + - ((i - 1) * SOF_CORE_S_SIZE); - sof->memory_map->system[i].size = HEAP_SYSTEM_S_SIZE; - sof->memory_map->system[i].info.free = HEAP_SYSTEM_S_SIZE; - sof->memory_map->system[i].caps = SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_EXT | SOF_MEM_CAPS_CACHE; - - /* .system_runtime init */ - sof->memory_map->system_runtime[i].blocks = - ARRAY_SIZE(sys_rt_heap_map[i]); - sof->memory_map->system_runtime[i].map = - uncached_block_map(sys_rt_heap_map[i]); - sof->memory_map->system_runtime[i].heap = - (uintptr_t)&_sof_core_s_start + - ((i - 1) * SOF_CORE_S_SIZE) + HEAP_SYSTEM_S_SIZE; - sof->memory_map->system_runtime[i].size = - HEAP_SYS_RUNTIME_S_SIZE; - sof->memory_map->system_runtime[i].info.free = - HEAP_SYS_RUNTIME_S_SIZE; - sof->memory_map->system_runtime[i].caps = SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_EXT | SOF_MEM_CAPS_CACHE | - SOF_MEM_CAPS_DMA; - } - - platform_shared_commit(sof->memory_map->system, - sizeof(*sof->memory_map->system) * - PLATFORM_CORE_COUNT); - - /* .runtime init*/ - sof->memory_map->runtime[0].blocks = ARRAY_SIZE(rt_heap_map); - sof->memory_map->runtime[0].map = uncached_block_map(rt_heap_map); - sof->memory_map->runtime[0].heap = (uintptr_t)&_module_heap; - sof->memory_map->runtime[0].size = HEAP_RUNTIME_SIZE; - sof->memory_map->runtime[0].info.free = HEAP_RUNTIME_SIZE; - sof->memory_map->runtime[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_EXT | - SOF_MEM_CAPS_CACHE; - - platform_shared_commit(sof->memory_map->runtime, - sizeof(*sof->memory_map->runtime)); - - /* heap buffer init */ - sof->memory_map->buffer[0].blocks = ARRAY_SIZE(buf_heap_map); - sof->memory_map->buffer[0].map = uncached_block_map(buf_heap_map); - sof->memory_map->buffer[0].heap = (uintptr_t)&_buffer_heap; - sof->memory_map->buffer[0].size = HEAP_BUFFER_SIZE; - sof->memory_map->buffer[0].info.free = HEAP_BUFFER_SIZE; - sof->memory_map->buffer[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_HP | - SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_DMA; - - /* heap lp buffer init */ - sof->memory_map->buffer[1].blocks = ARRAY_SIZE(lp_buf_heap_map); - sof->memory_map->buffer[1].map = uncached_block_map(lp_buf_heap_map); - sof->memory_map->buffer[1].heap = HEAP_LP_BUFFER_BASE; - sof->memory_map->buffer[1].size = HEAP_LP_BUFFER_SIZE; - sof->memory_map->buffer[1].info.free = HEAP_LP_BUFFER_SIZE; - sof->memory_map->buffer[1].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_LP | - SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_DMA; - - platform_shared_commit(sof->memory_map->buffer, - sizeof(*sof->memory_map->buffer) * - PLATFORM_HEAP_BUFFER); - - /* .total init */ - sof->memory_map->total.free = HEAP_SYSTEM_T_SIZE + - HEAP_SYS_RUNTIME_T_SIZE + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE + - HEAP_LP_BUFFER_SIZE; - - platform_shared_commit(sof->memory_map, sizeof(*sof->memory_map)); -} diff --git a/src/platform/intel/cavs/lib/pm_memory.c b/src/platform/intel/cavs/lib/pm_memory.c deleted file mode 100644 index 8045976ed76c..000000000000 --- a/src/platform/intel/cavs/lib/pm_memory.c +++ /dev/null @@ -1,207 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Jakub Dabek <jakub.dabek@intel.com> - */ - -#include <cavs/version.h> -#include <sof/bit.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_memory.h> -#include <sof/lib/shim.h> -#include <sof/lib/wait.h> -#include <sof/trace/trace.h> -#include <user/trace.h> -#include <stdint.h> - -#define trace_mem_pm(__e, ...) \ - trace_event(TRACE_CLASS_MEM, __e, ##__VA_ARGS__) -#if CAVS_VERSION >= CAVS_VERSION_1_8 - -#define EBB_SEGMENT_SIZE_ZERO_BASE (EBB_SEGMENT_SIZE - 1) -#define MEMORY_POWER_DOWN_DELAY 256 -/** - * \brief Read masks from hw registers and prepare new masks from data - * \param[in] ebb_data All masks data required for calculations. - */ -static void set_bank_masks(struct ebb_data *ebb) -{ - /* Bit is set for gated banks in the HSPGISTS register so - * we negate it to have consistent 1 = powered 0 = gated - * convention since HSPGISTS registers have it other way - */ - ebb->current_mask0 = ~io_reg_read(HSPGISTS0); - ebb->current_mask1 = ~io_reg_read(HSPGISTS1); - - /* Calculate mask of bits (banks) to set to powered */ - ebb->change_mask0 = SET_BITS(ebb->ending_bank_id, - ebb->start_bank_id, MASK(ebb->ending_bank_id, 0)); - ebb->change_mask1 = SET_BITS(ebb->ending_bank_id_high, - ebb->start_bank_id_high, - MASK(ebb->ending_bank_id_high, 0)); -} - -/** - * \brief Calculates new mask to write to hw register - * \param[in] ebb_data All masks data required for calculations. - * \param[in] enabled Boolean deciding banks desired state (1 powered 0 gated). - */ -static void calculate_new_masks(struct ebb_data *ebb, uint32_t enabled) -{ - /* check if either start or end bank is in different segment - * and treat it on case by case basis first only banks - * the segments above EBB_SEGMENT_SIZE are managed - * (separate hw register has to be used for ebb - * numbered over 32 different ebb segment) - */ - if (ebb->start_bank_id > EBB_SEGMENT_SIZE_ZERO_BASE && - ebb->ending_bank_id > EBB_SEGMENT_SIZE_ZERO_BASE) { - /* Set the bits for all powered banks operations - * depend whether we turn on or off the memory - */ - ebb->new_mask0 = - ebb->current_mask0; - ebb->new_mask1 = enabled ? - ebb->current_mask1 - | ebb->change_mask1 : - ebb->current_mask1 - & ~ebb->change_mask1; - - /* second check if managing spans above and below EBB_SEGMENT_SIZE - * meaning we have to handle both ebb for both segments - */ - } else if (ebb->start_bank_id > EBB_SEGMENT_SIZE_ZERO_BASE - && ebb->ending_bank_id - < EBB_SEGMENT_SIZE_ZERO_BASE) { - ebb->new_mask0 = enabled ? - ebb->current_mask0 - | ebb->change_mask0 : - ebb->current_mask0 - & ~ebb->change_mask0; - ebb->new_mask1 = enabled ? - ebb->current_mask1 - | ebb->change_mask1 : - ebb->current_mask1 - & ~ebb->change_mask1; - - /* if only first segment needs changes */ - } else { - ebb->new_mask0 = enabled ? - ebb->current_mask0 - | ebb->change_mask0 : - ebb->current_mask0 - & ~ebb->change_mask0; - ebb->new_mask1 = - ebb->current_mask1; - } -} - -/** - * \brief Write calculated masks to HW registers - * \param[in] ebb_data All masks data with masks to write. - */ -static void write_new_masks_and_check_status(struct ebb_data *ebb) -{ - uint32_t status; - - /* HSPGCTL, HSRMCTL use reverse logic - 0 means EBB is enabled gated */ - io_reg_write(HSPGCTL0, ~ebb->new_mask0); - io_reg_write(HSRMCTL0, ~ebb->new_mask0); - io_reg_write(HSPGCTL1, ~ebb->new_mask1); - io_reg_write(HSRMCTL1, ~ebb->new_mask1); - - /* Query the enabled status of first part of HP memory - * to check whether it has been powered up. A few - * cycles are needed for it to be powered up - */ - status = io_reg_read(HSPGISTS0); - while (status != ~ebb->new_mask0) { - idelay(MEMORY_POWER_DOWN_DELAY); - status = io_reg_read(HSPGISTS0); - } - - /* Query the enabled status of second part of HP memory */ - status = io_reg_read(HSPGISTS1); - while (status != ~ebb->new_mask1) { - idelay(MEMORY_POWER_DOWN_DELAY); - status = io_reg_read(HSPGISTS1); - } - /* add some delay before touch enabled register */ - idelay(MEMORY_POWER_DOWN_DELAY); -} - -/** - * \brief Set memory enabled gating hw bit mask for memory banks - * \param[in] start_bank_id Id of first bank to be managed (inclusive) 0 based. - * \param[in] ending_bank_id Id of last bank to be managed (inclusive) 0 based. - * \param[in] enabled Boolean deciding banks desired state (1 powered 0 gated). - */ -static void set_banks_gating(uint32_t start_bank_id, uint32_t ending_bank_id, - uint32_t enabled) -{ - struct ebb_data ebb = {0}; - - ebb.start_bank_id = start_bank_id; - ebb.ending_bank_id = ending_bank_id; - ebb.start_bank_id_high = start_bank_id - EBB_SEGMENT_SIZE; - ebb.ending_bank_id_high = ending_bank_id - EBB_SEGMENT_SIZE; - - /* Take note that if there are more banks than EBB_SEGMENT_SIZE - * then those over have to be controlled by second mask - * hence start_bank_id and start_bank_id_high - * for calculating the banks in second segment (currently two - * segments is all HW supports) - */ - shim_write(SHIM_LDOCTL, SHIM_LDOCTL_HPSRAM_LDO_ON); - - set_bank_masks(&ebb); - - calculate_new_masks(&ebb, enabled); - - write_new_masks_and_check_status(&ebb); - - shim_write(SHIM_LDOCTL, SHIM_LDOCTL_HPSRAM_LDO_BYPASS); -} - -void set_power_gate_for_memory_address_range(void *ptr, - uint32_t size, uint32_t enabled) -{ - uint32_t start_bank_id; - uint32_t ending_bank_id; - void *end_ptr = (char *)ptr + size; - - /* if ptr is not aligned to bank size change it to - * closest possible memory address at the start of bank - * or end for end address - */ - if ((uintptr_t)ptr % SRAM_BANK_SIZE) - ptr = (void *)ALIGN((uintptr_t)ptr, SRAM_BANK_SIZE); - - if ((uintptr_t)end_ptr % SRAM_BANK_SIZE) - end_ptr = (void *)ALIGN_DOWN((uintptr_t)ptr, SRAM_BANK_SIZE); - - /* return if no full bank could be found for enabled gate control */ - if ((char *)end_ptr - (char *)ptr < SRAM_BANK_SIZE) { - trace_mem_pm("Could not find full bank " - "to perform gating operation"); - return; - } - - start_bank_id = ((uintptr_t)ptr - HP_SRAM_BASE) / SRAM_BANK_SIZE; - /* Ending bank id has to be lowered by one because it is - * calculated from memory end ptr - */ - ending_bank_id = (((uintptr_t)end_ptr - HP_SRAM_BASE) - / SRAM_BANK_SIZE - 1); - - set_banks_gating(start_bank_id, ending_bank_id, enabled); -} - -#else -void set_power_gate_for_memory_address_range(void *ptr, - uint32_t size, uint32_t enabled) -{ -} -#endif diff --git a/src/platform/intel/cavs/lib/pm_runtime.c b/src/platform/intel/cavs/lib/pm_runtime.c deleted file mode 100644 index 7fd04fdc39c6..000000000000 --- a/src/platform/intel/cavs/lib/pm_runtime.c +++ /dev/null @@ -1,477 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -/** - * \file platform/intel/cavs/pm_runtime.c - * \brief Runtime power management implementation for Apollolake, Cannonlake - * and Icelake - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/alloc.h> -#include <sof/lib/dai.h> -#include <sof/lib/io.h> -#include <sof/lib/memory.h> -#include <sof/lib/pm_memory.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/shim.h> -#include <sof/lib/wait.h> -#include <sof/platform.h> -#include <sof/spinlock.h> -#include <sof/trace/trace.h> -#include <ipc/topology.h> -#include <user/trace.h> -#include <config.h> -#include <version.h> -#include <stdint.h> - -#define trace_power(format, ...) \ - trace_event(TRACE_CLASS_POWER, format, ##__VA_ARGS__) - -#if !CONFIG_SUECREEK -#include <cavs/lib/power_down.h> -#endif - -/** - * \brief Forces Host DMAs to exit L1. - */ -static inline void cavs_pm_runtime_force_host_dma_l1_exit(void) -{ - struct pm_runtime_data *prd = pm_runtime_data_get(); - uint32_t flags; - - spin_lock_irq(&prd->lock, flags); - - if (!(shim_read(SHIM_SVCFG) & SHIM_SVCFG_FORCE_L1_EXIT)) { - shim_write(SHIM_SVCFG, - shim_read(SHIM_SVCFG) | SHIM_SVCFG_FORCE_L1_EXIT); - - wait_delay(PLATFORM_FORCE_L1_EXIT_TIME); - - shim_write(SHIM_SVCFG, - shim_read(SHIM_SVCFG) & ~(SHIM_SVCFG_FORCE_L1_EXIT)); - } - - spin_unlock_irq(&prd->lock, flags); -} - -static inline void cavs_pm_runtime_enable_dsp(bool enable) -{ - struct pm_runtime_data *prd = pm_runtime_data_get(); - struct cavs_pm_runtime_data *pprd = prd->platform_data; - uint32_t flags; - - /* request is always run on dsp0 and applies to dsp0, - * so no global lock is required. - */ - irq_local_disable(flags); - - enable ? --pprd->dsp_d0_sref : ++pprd->dsp_d0_sref; - - platform_shared_commit(prd, sizeof(*prd)); - - irq_local_enable(flags); - - trace_power("pm_runtime_enable_dsp dsp_d0_sref %d", pprd->dsp_d0_sref); -} - -static inline bool cavs_pm_runtime_is_active_dsp(void) -{ - struct pm_runtime_data *prd = pm_runtime_data_get(); - struct cavs_pm_runtime_data *pprd = prd->platform_data; - - platform_shared_commit(prd, sizeof(*prd)); - - return pprd->dsp_d0_sref > 0; -} - -#if CONFIG_CAVS_SSP -static inline void cavs_pm_runtime_dis_ssp_clk_gating(uint32_t index) -{ -#if CONFIG_APOLLOLAKE - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_CLKCTL) | - (index < DAI_NUM_SSP_BASE ? - SHIM_CLKCTL_I2SFDCGB(index) : - SHIM_CLKCTL_I2SEFDCGB(index - DAI_NUM_SSP_BASE)); - - shim_write(SHIM_CLKCTL, shim_reg); - - trace_power("dis-ssp-clk-gating index %d CLKCTL %08x", index, shim_reg); -#endif -} - -static inline void cavs_pm_runtime_en_ssp_clk_gating(uint32_t index) -{ -#if CONFIG_APOLLOLAKE - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_CLKCTL) & - ~(index < DAI_NUM_SSP_BASE ? - SHIM_CLKCTL_I2SFDCGB(index) : - SHIM_CLKCTL_I2SEFDCGB(index - DAI_NUM_SSP_BASE)); - - shim_write(SHIM_CLKCTL, shim_reg); - - trace_power("en-ssp-clk-gating index %d CLKCTL %08x", index, shim_reg); -#endif -} - -static inline void cavs_pm_runtime_en_ssp_power(uint32_t index) -{ -#if CONFIG_TIGERLAKE - uint32_t reg; - - trace_power("en_ssp_power index %d", index); - - io_reg_write(I2SLCTL, io_reg_read(I2SLCTL) | I2SLCTL_SPA(index)); - - /* Check if powered on. */ - do { - reg = io_reg_read(I2SLCTL); - } while (!(reg & I2SLCTL_CPA(index))); - - trace_power("en_ssp_power I2SLCTL %08x", reg); -#endif -} - -static inline void cavs_pm_runtime_dis_ssp_power(uint32_t index) -{ -#if CONFIG_TIGERLAKE - uint32_t reg; - - trace_power("dis_ssp_power index %d", index); - - io_reg_write(I2SLCTL, io_reg_read(I2SLCTL) & (~I2SLCTL_SPA(index))); - - /* Check if powered off. */ - do { - reg = io_reg_read(I2SLCTL); - } while (reg & I2SLCTL_CPA(index)); - - trace_power("dis_ssp_power I2SLCTL %08x", reg); -#endif -} -#endif - -#if CONFIG_CAVS_DMIC -static inline void cavs_pm_runtime_dis_dmic_clk_gating(uint32_t index) -{ -#if CONFIG_APOLLOLAKE || CONFIG_CANNONLAKE - (void)index; - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_CLKCTL) | SHIM_CLKCTL_DMICFDCGB; - - shim_write(SHIM_CLKCTL, shim_reg); - - trace_power("dis-dmic-clk-gating index %d CLKCTL %08x", index, - shim_reg); -#endif -#if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_SUECREEK || CONFIG_TIGERLAKE - /* Disable DMIC clock gating */ - io_reg_write(DMICLCTL, - (io_reg_read(DMICLCTL) | DMIC_DCGD)); -#endif -} - -static inline void cavs_pm_runtime_en_dmic_clk_gating(uint32_t index) -{ -#if CONFIG_APOLLOLAKE || CONFIG_CANNONLAKE - (void)index; - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_CLKCTL) & ~SHIM_CLKCTL_DMICFDCGB; - - shim_write(SHIM_CLKCTL, shim_reg); - - trace_power("en-dmic-clk-gating index %d CLKCTL %08x", index, shim_reg); -#endif -#if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_SUECREEK || CONFIG_TIGERLAKE - /* Enable DMIC clock gating */ - io_reg_write(DMICLCTL, - (io_reg_read(DMICLCTL) & ~DMIC_DCGD)); -#endif -} -static inline void cavs_pm_runtime_en_dmic_power(uint32_t index) -{ - (void) index; -#if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_SUECREEK || CONFIG_TIGERLAKE - /* Enable DMIC power */ - io_reg_write(DMICLCTL, - (io_reg_read(DMICLCTL) | DMICLCTL_SPA)); -#endif -} -static inline void cavs_pm_runtime_dis_dmic_power(uint32_t index) -{ - (void) index; -#if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_SUECREEK || CONFIG_TIGERLAKE - /* Disable DMIC power */ - io_reg_write(DMICLCTL, - (io_reg_read(DMICLCTL) & (~DMICLCTL_SPA))); -#endif -} -#endif /* #if defined(CONFIG_CAVS_DMIC) */ - -static inline void cavs_pm_runtime_dis_dwdma_clk_gating(uint32_t index) -{ -#if CONFIG_APOLLOLAKE - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_CLKCTL) | SHIM_CLKCTL_LPGPDMAFDCGB(index); - - shim_write(SHIM_CLKCTL, shim_reg); - - trace_power("dis-dwdma-clk-gating index %d CLKCTL %08x", index, - shim_reg); -#elif CONFIG_CANNONLAKE - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_GPDMA_CLKCTL(index)) | - SHIM_CLKCTL_LPGPDMAFDCGB; - - shim_write(SHIM_GPDMA_CLKCTL(index), shim_reg); - - trace_power("dis-dwdma-clk-gating index %d GPDMA_CLKCTL %08x", index, - shim_reg); -#endif -} - -static inline void cavs_pm_runtime_en_dwdma_clk_gating(uint32_t index) -{ -#if CONFIG_APOLLOLAKE - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_CLKCTL) & ~SHIM_CLKCTL_LPGPDMAFDCGB(index); - - shim_write(SHIM_CLKCTL, shim_reg); - - trace_power("en-dwdma-clk-gating index %d CLKCTL %08x", index, - shim_reg); -#elif CONFIG_CANNONLAKE - uint32_t shim_reg; - - shim_reg = shim_read(SHIM_GPDMA_CLKCTL(index)) & - ~SHIM_CLKCTL_LPGPDMAFDCGB; - - shim_write(SHIM_GPDMA_CLKCTL(index), shim_reg); - - trace_power("en-dwdma-clk-gating index %d GPDMA_CLKCTL %08x", index, - shim_reg); -#endif -} - -static inline void cavs_pm_runtime_core_dis_memory(uint32_t index) -{ -#if CAVS_VERSION >= CAVS_VERSION_1_8 - void *core_memory_ptr; - extern uintptr_t _sof_core_s_start; - - /* Address is calculated for index (0 for the master core) minus one - * since _sof_core_s_start is first slave core stack address - */ - core_memory_ptr = (char *)&_sof_core_s_start - + (index - 1) * SOF_CORE_S_SIZE; - - set_power_gate_for_memory_address_range(core_memory_ptr, - SOF_CORE_S_SIZE, 0); - -#endif -} - -static inline void cavs_pm_runtime_core_en_memory(uint32_t index) -{ -#if CAVS_VERSION >= CAVS_VERSION_1_8 - void *core_memory_ptr; - extern uintptr_t _sof_core_s_start; - - /* Address is calculated for index (0 for the master core) minus one - * since _sof_core_s_start is first slave core stack address - */ - core_memory_ptr = (char *)&_sof_core_s_start - + (index - 1) * SOF_CORE_S_SIZE; - - set_power_gate_for_memory_address_range(core_memory_ptr, - SOF_CORE_S_SIZE, 1); - -#endif -} - -static inline void cavs_pm_runtime_dis_dsp_pg(uint32_t index) -{ -#if CAVS_VERSION >= CAVS_VERSION_1_8 - uint32_t lps_ctl; - - if (index == PLATFORM_MASTER_CORE_ID) { - lps_ctl = shim_read(SHIM_LPSCTL); - - shim_write16(SHIM_PWRCTL, shim_read16(SHIM_PWRCTL) | - SHIM_PWRCTL_TCPDSPPG(index) | - SHIM_PWRCTL_TCPCTLPG); - - lps_ctl &= ~SHIM_LPSCTL_BID; - lps_ctl &= ~SHIM_LPSCTL_BATTR_0; - lps_ctl |= SHIM_LPSCTL_FDSPRUN; - shim_write(SHIM_LPSCTL, lps_ctl); - } else { - shim_write16(SHIM_PWRCTL, shim_read16(SHIM_PWRCTL) | - SHIM_PWRCTL_TCPDSPPG(index)); - } -#endif -} - -static inline void cavs_pm_runtime_en_dsp_pg(uint32_t index) -{ -#if CAVS_VERSION >= CAVS_VERSION_1_8 - uint32_t lps_ctl; - - if (index == PLATFORM_MASTER_CORE_ID) { - lps_ctl = shim_read(SHIM_LPSCTL); - -#if CONFIG_ICELAKE - shim_write16(SHIM_PWRCTL, SHIM_PWRCTL_TCPCTLPG); -#else - shim_write16(SHIM_PWRCTL, 0); -#endif - lps_ctl |= SHIM_LPSCTL_BID | SHIM_LPSCTL_BATTR_0; - lps_ctl &= ~SHIM_LPSCTL_FDSPRUN; - shim_write(SHIM_LPSCTL, lps_ctl); - } else { - shim_write16(SHIM_PWRCTL, shim_read16(SHIM_PWRCTL) & - ~SHIM_PWRCTL_TCPDSPPG(index)); - } -#endif -} - -void platform_pm_runtime_init(struct pm_runtime_data *prd) -{ - struct cavs_pm_runtime_data *pprd; - - pprd = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(*pprd)); - prd->platform_data = pprd; -} - -void platform_pm_runtime_get(enum pm_runtime_context context, uint32_t index, - uint32_t flags) -{ - /* Action based on context */ - switch (context) { -#if CONFIG_CAVS_SSP - case SSP_CLK: - cavs_pm_runtime_dis_ssp_clk_gating(index); - break; - case SSP_POW: - cavs_pm_runtime_en_ssp_power(index); - break; -#endif -#if CONFIG_CAVS_DMIC - case DMIC_CLK: - cavs_pm_runtime_dis_dmic_clk_gating(index); - break; - case DMIC_POW: - cavs_pm_runtime_en_dmic_power(index); - break; -#endif - case DW_DMAC_CLK: - cavs_pm_runtime_dis_dwdma_clk_gating(index); - break; - case CORE_MEMORY_POW: - cavs_pm_runtime_core_en_memory(index); - break; - case PM_RUNTIME_DSP: - cavs_pm_runtime_dis_dsp_pg(index); - break; - default: - break; - } -} - -void platform_pm_runtime_put(enum pm_runtime_context context, uint32_t index, - uint32_t flags) -{ - switch (context) { - case PM_RUNTIME_HOST_DMA_L1: - cavs_pm_runtime_force_host_dma_l1_exit(); - break; -#if CONFIG_CAVS_SSP - case SSP_CLK: - cavs_pm_runtime_en_ssp_clk_gating(index); - break; - case SSP_POW: - cavs_pm_runtime_dis_ssp_power(index); - break; -#endif -#if CONFIG_CAVS_DMIC - case DMIC_CLK: - cavs_pm_runtime_en_dmic_clk_gating(index); - break; - case DMIC_POW: - cavs_pm_runtime_dis_dmic_power(index); - break; -#endif - case DW_DMAC_CLK: - cavs_pm_runtime_en_dwdma_clk_gating(index); - break; - case CORE_MEMORY_POW: - cavs_pm_runtime_core_dis_memory(index); - break; - case PM_RUNTIME_DSP: - cavs_pm_runtime_en_dsp_pg(index); - break; - default: - break; - } -} - -void platform_pm_runtime_enable(uint32_t context, uint32_t index) -{ - switch (context) { - case PM_RUNTIME_DSP: - cavs_pm_runtime_enable_dsp(true); - break; - default: - break; - } -} - -void platform_pm_runtime_disable(uint32_t context, uint32_t index) -{ - switch (context) { - case PM_RUNTIME_DSP: - cavs_pm_runtime_enable_dsp(false); - break; - default: - break; - } -} - -bool platform_pm_runtime_is_active(uint32_t context, uint32_t index) -{ - switch (context) { - case PM_RUNTIME_DSP: - return cavs_pm_runtime_is_active_dsp(); - default: - assert(false); /* unsupported query */ - return false; - } - -} - -#if !CONFIG_SUECREEK -void platform_pm_runtime_power_off(void) -{ - uint32_t hpsram_mask[PLATFORM_HPSRAM_SEGMENTS], i; - /* power down entire HPSRAM */ - for (i = 0; i < PLATFORM_HPSRAM_SEGMENTS; i++) - hpsram_mask[i] = HPSRAM_MASK(i); - - power_down(true, hpsram_mask); -} -#endif diff --git a/src/platform/intel/cavs/lib/power_down.S b/src/platform/intel/cavs/lib/power_down.S deleted file mode 100644 index 35c03da4d1a2..000000000000 --- a/src/platform/intel/cavs/lib/power_down.S +++ /dev/null @@ -1,170 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Lech Betlej <lech.betlej@linux.intel.com> - */ - -/** - * \file platform/intel/cavs/lib/power_down.S - * \brief Power gating memory banks - implementation specific for platforms - * with cAVS 1.8 (i.e. CannonLake) and cAVS 2.0 (i.e. IceLake) - * \author Lech Betlej <lech.betlej@linux.intel.com> - */ - - -#include <cavs/version.h> -#include <cavs/lib/asm_ldo_management.h> -#include <cavs/lib/asm_memory_management.h> -#include <sof/lib/memory.h> -#include <sof/lib/shim.h> - -#if CAVS_VERSION >= CAVS_VERSION_1_8 - - .section .text, "ax" - .align 64 -power_down_literals: - .literal_position -ipc_flag: - .word IPC_DIPCTDR_BUSY -sram_dis_loop_cnt: - .word 4096 - - .global power_down - .type power_down, @function - -/** - * Perform power down. - * - * Depending on arguments, memories are switched off. - * A2 - argument for LPSRAM - * A3 - pointer to array containing power gating mask. - *Size of array is determined by MEMORY_SEGMENTS define. - * A4 - platform type - * A5 - response_to_ipc - */ - -#define b_enable_lpsram a2 -#define pu32_hpsram_mask a3 -#define temp_reg0 a6 -#define temp_reg1 a7 -#define temp_reg2 a8 -#define temp_reg3 a9 -#define pfl_reg a15 - -power_down: - entry sp, 32 - // effectively executes: - // xthal_dcache_region_lock(&literals, 128); - // xthal_dcache_region_lock(&powerdown, 256); - // xthal_dcache_region_lock(&pu32_hpsram_mask, 64); - movi pfl_reg, power_down_literals - dpfl pfl_reg, 0 - dpfl pfl_reg, 64 - - movi pfl_reg, power_down - ipfl pfl_reg, 0 - ipfl pfl_reg, 64 - ipfl pfl_reg, 128 - ipfl pfl_reg, 192 - - mov pfl_reg, pu32_hpsram_mask - dpfl pfl_reg, 0 - -_PD_DISABLE_LPSRAM: -/* effectively executes: - * if (b_enable_lpsram){ - * cavs_lpsram_power_down_entire(); - * } - */ - beqz b_enable_lpsram, _PD_DISABLE_HPSRAM - m_cavs_lpsram_power_down_entire temp_reg0, temp_reg1, temp_reg2,\ - sram_dis_loop_cnt - j _PD_DISABLE_HPSRAM - -_PD_DISABLE_HPSRAM: - /* if value in memory pointed by pu32_hpsram_mask = 0 - (hpsram_pwrgating_mask) - do not disable hpsram. */ - beqz pu32_hpsram_mask, _PD_SEND_IPC - -/* mandatory sequence for LDO ON - effectively executes: - * m_cavs_s_set_ldo_hpsram_on_state(); - * WAIT_300NS(); - */ - movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_ON - m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2 - movi temp_reg0, 128 -1 : - addi temp_reg0, temp_reg0, -1 - bnez temp_reg0, 1b - - -/* effectively executes: - * for (size_t seg_index = (MAX_MEMORY_SEGMENTS - 1); seg_index >= 0; - * --seg_index) { - * cavs_hpsram_power_change(seg_index, mask[seg_index]); - * } - * where mask is given in pu32_hpsram_mask register - */ - - .set seg_index, MAX_MEMORY_SEGMENTS - 1 - .rept MAX_MEMORY_SEGMENTS - l32i temp_reg0, pu32_hpsram_mask, 4 * seg_index - m_cavs_hpsram_power_change\ - /*segment_index=*/ seg_index,\ - /*mask=*/ temp_reg0,\ - temp_reg1,\ - temp_reg2,\ - temp_reg3 - .set seg_index, seg_index - 1 - .endr - - -/* mandatory sequence for LDO OFF - effectively executes: - * WAIT_300NS(); - * m_cavs_set_ldo_hpsram_on_state() - */ - movi temp_reg0, 128 -1 : - addi temp_reg0, temp_reg0, -1 - bnez temp_reg0, 1b - - movi temp_reg0, SHIM_LDOCTL_HPSRAM_LDO_OFF - m_cavs_set_hpldo_state temp_reg0, temp_reg1, temp_reg2 - -_PD_SEND_IPC: -/* Send IPC to host informing of PD completion - Clear BUSY - * bit by writing IPC_DIPCTDR_BUSY to IPC_DIPCTDR - * and writing IPC_DIPCTDA_DONE to IPC_DIPCTDA - */ - movi temp_reg0, IPC_HOST_BASE - l32i temp_reg1, temp_reg0, IPC_DIPCTDR - movi temp_reg2, ipc_flag - l32i temp_reg2, temp_reg2, 0 - or temp_reg1, temp_reg1, temp_reg2 - s32i temp_reg1, temp_reg0, IPC_DIPCTDR - - l32i temp_reg1, temp_reg0, IPC_DIPCTDA - or temp_reg1, temp_reg1, temp_reg2 - s32i temp_reg1, temp_reg0, IPC_DIPCTDA - -_PD_SLEEP: -/* effecfively executes: - * xmp_spin() - * waiti 5 - */ - movi temp_reg0, 128 -loop: - addi temp_reg0, temp_reg0, -1 - bnez temp_reg0, loop - - extw - extw - waiti 5 - 1: - j 1b - -.size power_down , . - power_down - -#endif /* CAVS_VERSION >= CAVS_VERSION_1_8 */ - 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 b0ac476625db..000000000000 --- a/src/platform/intel/cavs/lps_pic_restore_vector.S +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#include <xtensa/coreasm.h> -#include <xtensa/cacheattrasm.h> -#include <cavs/lps_ctx.h> - -#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<<SW_INT_NUM) - -#define L1_CACHE_PREFCTL 0x0000 - - .section .lps_vector, "ax" -lps_pic_restore_vector_literals: - .literal_position - .align 4 - - .macro restore_vector level - l32i a4, a3, lps_ctx_vector_level_&level - wsr a4, EXCSAVE+\level - .endm - - .global lps_pic_restore_vector_literals - .global lps_pic_restore_vector - .global lps_pic_restore_vector_end - -lps_pic_restore_vector: - movi a0, 0 - movi a1, 1 - wsr a1, WINDOWSTART - wsr a0, WINDOWBASE - rsync - - movi a3, MEMCTL_INIT_VAL - wsr a3, MEMCTL - rsync - - movi a3, 0x15 /* RCW for non-coherent dcache */ - wsr a3, ATOMCTL - - movi a2, L1_CACHE_PREFCTL - wsr a2, PREFCTL - - movi a3, PS_UM|PS_WOE - wsr a3, PS - rsync - - movi a2, _memmap_cacheattr_reset - cacheattr_set - - movi a3, (~MEMCTL_SNOOP_EN) - wsr a3, MEMCTL - rsync - - movi a3, (MEMCTL_SNOOP_EN | MEMCTL_L0IBUF_EN) - rsr a2, MEMCTL - or a2, a2, a3 - wsr a2, MEMCTL - rsync - - /* setup the stack */ - movi sp, lps_boot_stack - movi a2, 0x1000 - add sp, sp, a2 - - /* Restore things saved by the platform code before sleep */ - - movi a3, lps_restore - - l32i a2, a3, lps_ctx_threadptr - wur a2, THREADPTR - - l32i a4, a3, lps_ctx_memmap_vecbase_reset - wsr a4, vecbase - rsync - - restore_vector 2 - restore_vector 3 - restore_vector 4 - restore_vector 5 - - /* generate sw interrupt (# 7)*/ - movi a3, SW_INT_MASK - rsr a4, intenable - or a4, a4, a3 - wsr a4, intenable - rsync - wsr a3, interrupt - rsync - -loop: - j loop - /* should never go here */ -_HaltLoop: - j _HaltLoop - - /* alignment is needed to ensure that vector - * will be copied with proper alignment - */ - .align 64 -lps_pic_restore_vector_end: - - .size lps_pic_restore_vector, . - lps_pic_restore_vector diff --git a/src/platform/intel/cavs/lps_wait.c b/src/platform/intel/cavs/lps_wait.c deleted file mode 100644 index 37da7446407e..000000000000 --- a/src/platform/intel/cavs/lps_wait.c +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Marcin Maka <marcin.maka@linux.intel.com> - -#include <arch/lib/wait.h> -#include <cavs/lps_ctx.h> -#include <cavs/lps_wait.h> -#include <cavs/mem_window.h> -#include <sof/common.h> -#include <sof/platform.h> -#include <sof/drivers/interrupt.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/shim.h> -#include <sof/schedule/task.h> -#include <config.h> -#include <stdint.h> - -#define LPSRAM_MAGIC_VALUE 0x13579BDF - -#define LPSRAM_HEADER_SIZE 0xc00 - -struct lpsram_header { - uint32_t alt_reset_vector; - uint32_t adsp_lpsram_magic; - void *lp_restore_vector; - uint32_t reserved; - - /* align total size of the structure to the full header size - * with bypass vector area - */ - uint8_t rom_bypass_vectors_reserved[LPSRAM_HEADER_SIZE - 16]; -}; - -#define LPSRAM_HEADER_BYPASS_ADDR (LP_SRAM_BASE - SRAM_ALIAS_OFFSET) - -#define LPS_POWER_FLOW_D0_D0I3 1 -#define LPS_POWER_FLOW_D0I3_D0 0 - -#define LPS_BOOT_STACK_SIZE 4096 -#define PG_TASK_STACK_SIZE 4096 - -__aligned(PLATFORM_DCACHE_ALIGN) uint8_t lps_boot_stack[LPS_BOOT_STACK_SIZE]; -__aligned(PLATFORM_DCACHE_ALIGN) lps_ctx lps_restore; -static void *pg_task_ctx; -static uint8_t pg_task_stack[PG_TASK_STACK_SIZE]; - -static void platform_pg_int_handler(void *arg); - -static void platform_pg_task(void) -{ - struct lpsram_header *lpsram_hdr = (struct lpsram_header *) - LPSRAM_HEADER_BYPASS_ADDR; - size_t vector_size; - size_t offset_to_entry; - int schedule_irq; - - _xtos_set_intlevel(5); - xthal_window_spill(); - - offset_to_entry = (uint32_t)&lps_pic_restore_vector - - (uint32_t)&lps_pic_restore_vector_literals; - vector_size = ALIGN_UP((size_t)&lps_pic_restore_vector_end - - (size_t)&lps_pic_restore_vector_literals, 4); - - /* Half of area is available, - * another half is reserved for custom vectors in future (like WHM) - */ - memcpy_s((void *)LPS_RESTORE_VECTOR_ADDR, LPS_RESTORE_VECTOR_SIZE, - &lps_pic_restore_vector_literals, vector_size); - dcache_writeback_invalidate_region((void *)LPS_RESTORE_VECTOR_ADDR, - vector_size); - - /* set magic and vector in LPSRAM */ - lpsram_hdr->adsp_lpsram_magic = LPSRAM_MAGIC_VALUE; - lpsram_hdr->lp_restore_vector = (void *)(LPS_RESTORE_VECTOR_ADDR - + offset_to_entry); - - /* re-register to change the direction (arg) */ - schedule_irq = interrupt_get_irq(IRQ_NUM_SOFTWARE3, NULL); - interrupt_register(schedule_irq, - platform_pg_int_handler, - (void *)LPS_POWER_FLOW_D0I3_D0); - - /* enable all INTs that should turn the dsp on */ - arch_interrupt_enable_mask(BIT(PLATFORM_SCHEDULE_IRQ) | - BIT(IRQ_NUM_EXT_LEVEL2) | - BIT(IRQ_NUM_EXT_LEVEL5)); - - while (1) { - /* flush caches and handle int or pwr off */ - xthal_dcache_all_writeback_inv(); - arch_wait_for_interrupt(0); - } -} - -static void platform_pg_int_handler(void *arg) -{ - uint32_t dir = (uint32_t)arg; - - if (dir == LPS_POWER_FLOW_D0_D0I3) { - pm_runtime_put(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); - - /* init power flow task */ - if (!pg_task_ctx) - task_context_alloc(&pg_task_ctx); - task_context_init(pg_task_ctx, platform_pg_task, NULL, NULL, - PLATFORM_MASTER_CORE_ID, - pg_task_stack, sizeof(pg_task_stack)); - - /* set TCB to power flow task */ - task_context_set(pg_task_ctx); - - arch_interrupt_disable_mask(0xffffffff); - } else { - pm_runtime_get(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); - - /* set TCB to the one stored in platform_power_gate() */ - task_context_set(lps_restore.task_ctx); - arch_interrupt_disable_mask(0xffffffff); -#if CONFIG_MEM_WND - platform_memory_windows_init(0); -#endif - arch_interrupt_enable_mask(lps_restore.intenable); - } -} - -void lps_wait_for_interrupt(int level) -{ - int schedule_irq; - - /* store the current state */ - - lps_restore.intenable = arch_interrupt_get_enabled(); - - lps_restore.threadptr = cpu_read_threadptr(); - lps_restore.task_ctx = (void *)task_context_get(); - lps_restore.memmap_vecbase_reset = cpu_read_vecbase(); - lps_restore.vector_level_2 = (void *)cpu_read_excsave2(); - lps_restore.vector_level_3 = (void *)cpu_read_excsave3(); - lps_restore.vector_level_4 = (void *)cpu_read_excsave4(); - lps_restore.vector_level_5 = (void *)cpu_read_excsave5(); - - /* use SW INT handler to do the context switch directly there */ - schedule_irq = interrupt_get_irq(IRQ_NUM_SOFTWARE3, NULL); - interrupt_register(schedule_irq, - platform_pg_int_handler, - (void *)LPS_POWER_FLOW_D0_D0I3); - arch_interrupt_disable_mask(0xffffffff); - _xtos_set_intlevel(0); - interrupt_enable(schedule_irq, NULL); - interrupt_set(schedule_irq); -} - diff --git a/src/platform/intel/cavs/platform.c b/src/platform/intel/cavs/platform.c index 0e71175e4999..8a1a7c59c3b5 100644 --- a/src/platform/intel/cavs/platform.c +++ b/src/platform/intel/cavs/platform.c @@ -8,43 +8,36 @@ // Janusz Jankowski <janusz.jankowski@linux.intel.com> #include <cavs/version.h> -#if (CONFIG_CAVS_LPS) -#include <cavs/lps_wait.h> -#endif -#include <cavs/mem_window.h> #include <sof/common.h> #include <sof/compiler_info.h> #include <sof/debug/debug.h> -#include <sof/drivers/dw-dma.h> -#include <sof/drivers/idc.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> +#include <rtos/idc.h> +#include <sof/ipc/common.h> +#include <rtos/timer.h> #include <sof/fw-ready-metadata.h> #include <sof/lib/agent.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> -#include <sof/lib/clk.h> +#include <rtos/cache.h> +#include <rtos/clk.h> #include <sof/lib/cpu.h> #include <sof/lib/dai.h> #include <sof/lib/dma.h> #include <sof/lib/io.h> #include <sof/lib/mailbox.h> #include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> #include <sof/lib/notifier.h> -#include <sof/lib/pm_runtime.h> -#include <sof/lib/wait.h> +#include <rtos/wait.h> #include <sof/platform.h> #include <sof/schedule/edf_schedule.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/ll_schedule_domain.h> -#include <sof/trace/dma-trace.h> #include <sof/trace/trace.h> #include <ipc/header.h> #include <ipc/info.h> #include <kernel/abi.h> -#include <config.h> -#include <version.h> +#include <kernel/ext_manifest.h> + +#include <sof_versions.h> #include <errno.h> #include <stdint.h> @@ -59,339 +52,74 @@ static const struct sof_ipc_fw_ready ready .micro = SOF_MICRO, .minor = SOF_MINOR, .major = SOF_MAJOR, -#if CONFIG_DEBUG - /* only added in debug for reproducability in releases */ - .build = SOF_BUILD, +/* opt-in; reproducible build by default */ +#if BLD_COUNTERS + .build = SOF_BUILD, /* See version-build-counter.cmake */ .date = __DATE__, .time = __TIME__, +#else + .build = -1, + .date = "dtermin.\0", + .time = "fwready.\0", #endif .tag = SOF_TAG, .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, }, +#if CONFIG_CAVS_IMR_D3_PERSISTENT + .flags = DEBUG_SET_FW_READY_FLAGS | SOF_IPC_INFO_D3_PERSISTENT, +#else .flags = DEBUG_SET_FW_READY_FLAGS, +#endif }; -#if CONFIG_MEM_WND #define SRAM_WINDOW_HOST_OFFSET(x) (0x80000 + x * 0x20000) -#define NUM_WINDOWS 7 - -static const struct sof_ipc_window sram_window - __section(".fw_ready_metadata") = { - .ext_hdr = { - .hdr.cmd = SOF_IPC_FW_READY, - .hdr.size = sizeof(struct sof_ipc_window) + - sizeof(struct sof_ipc_window_elem) * NUM_WINDOWS, - .type = SOF_IPC_EXT_WINDOW, - }, - .num_windows = NUM_WINDOWS, - .window = { - { - .type = SOF_IPC_REGION_REGS, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_SW_REG_SIZE, - .offset = 0, - }, - { - .type = SOF_IPC_REGION_UPBOX, - .id = 0, /* map to host window 0 */ - .flags = 0, // TODO: set later - .size = MAILBOX_DSPBOX_SIZE, - .offset = MAILBOX_SW_REG_SIZE, - }, - { - .type = SOF_IPC_REGION_DOWNBOX, - .id = 1, /* map to host window 1 */ - .flags = 0, // TODO: set later - .size = MAILBOX_HOSTBOX_SIZE, - .offset = 0, - }, - { - .type = SOF_IPC_REGION_DEBUG, - .id = 2, /* map to host window 2 */ - .flags = 0, // TODO: set later - .size = MAILBOX_EXCEPTION_SIZE + MAILBOX_DEBUG_SIZE, - .offset = 0, - }, - { - .type = SOF_IPC_REGION_EXCEPTION, - .id = 2, /* map to host window 2 */ - .flags = 0, // TODO: set later - .size = MAILBOX_EXCEPTION_SIZE, - .offset = MAILBOX_EXCEPTION_OFFSET, - }, - { - .type = SOF_IPC_REGION_STREAM, - .id = 2, /* map to host window 2 */ - .flags = 0, // TODO: set later - .size = MAILBOX_STREAM_SIZE, - .offset = MAILBOX_STREAM_OFFSET, - }, - { - .type = SOF_IPC_REGION_TRACE, - .id = 3, /* map to host window 3 */ - .flags = 0, // TODO: set later - .size = MAILBOX_TRACE_SIZE, - .offset = 0, - }, - }, -}; -#endif - -#if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_TIGERLAKE -#if CONFIG_CAVS_LPRO -#define CAVS_DEFAULT_RO SHIM_CLKCTL_RLROSCC -#define CAVS_DEFAULT_RO_FOR_MEM SHIM_CLKCTL_OCS_LP_RING -#else +#if CONFIG_TIGERLAKE #define CAVS_DEFAULT_RO SHIM_CLKCTL_RHROSCC #define CAVS_DEFAULT_RO_FOR_MEM SHIM_CLKCTL_OCS_HP_RING -#endif -#endif - -#if CONFIG_DW_GPIO - -#include <sof/drivers/gpio.h> - -const struct gpio_pin_config gpio_data[] = { - { /* GPIO0 */ - .mux_id = 1, - .mux_config = {.bit = 0, .mask = 3, .fn = 1}, - }, { /* GPIO1 */ - .mux_id = 1, - .mux_config = {.bit = 2, .mask = 3, .fn = 1}, - }, { /* GPIO2 */ - .mux_id = 1, - .mux_config = {.bit = 4, .mask = 3, .fn = 1}, - }, { /* GPIO3 */ - .mux_id = 1, - .mux_config = {.bit = 6, .mask = 3, .fn = 1}, - }, { /* GPIO4 */ - .mux_id = 1, - .mux_config = {.bit = 8, .mask = 3, .fn = 1}, - }, { /* GPIO5 */ - .mux_id = 1, - .mux_config = {.bit = 10, .mask = 3, .fn = 1}, - }, { /* GPIO6 */ - .mux_id = 1, - .mux_config = {.bit = 12, .mask = 3, .fn = 1}, - }, { /* GPIO7 */ - .mux_id = 1, - .mux_config = {.bit = 14, .mask = 3, .fn = 1}, - }, { /* GPIO8 */ - .mux_id = 1, - .mux_config = {.bit = 16, .mask = 1, .fn = 1}, - }, { /* GPIO9 */ - .mux_id = 0, - .mux_config = {.bit = 11, .mask = 1, .fn = 1}, - }, { /* GPIO10 */ - .mux_id = 0, - .mux_config = {.bit = 11, .mask = 1, .fn = 1}, - }, { /* GPIO11 */ - .mux_id = 0, - .mux_config = {.bit = 11, .mask = 1, .fn = 1}, - }, { /* GPIO12 */ - .mux_id = 0, - .mux_config = {.bit = 11, .mask = 1, .fn = 1}, - }, { /* GPIO13 */ - .mux_id = 0, - .mux_config = {.bit = 0, .mask = 1, .fn = 1}, - }, { /* GPIO14 */ - .mux_id = 0, - .mux_config = {.bit = 1, .mask = 1, .fn = 1}, - }, { /* GPIO15 */ - .mux_id = 0, - .mux_config = {.bit = 9, .mask = 1, .fn = 1}, - }, { /* GPIO16 */ - .mux_id = 0, - .mux_config = {.bit = 9, .mask = 1, .fn = 1}, - }, { /* GPIO17 */ - .mux_id = 0, - .mux_config = {.bit = 9, .mask = 1, .fn = 1}, - }, { /* GPIO18 */ - .mux_id = 0, - .mux_config = {.bit = 9, .mask = 1, .fn = 1}, - }, { /* GPIO19 */ - .mux_id = 0, - .mux_config = {.bit = 10, .mask = 1, .fn = 1}, - }, { /* GPIO20 */ - .mux_id = 0, - .mux_config = {.bit = 10, .mask = 1, .fn = 1}, - }, { /* GPIO21 */ - .mux_id = 0, - .mux_config = {.bit = 10, .mask = 1, .fn = 1}, - }, { /* GPIO22 */ - .mux_id = 0, - .mux_config = {.bit = 10, .mask = 1, .fn = 1}, - }, { /* GPIO23 */ - .mux_id = 0, - .mux_config = {.bit = 16, .mask = 1, .fn = 1}, - }, { /* GPIO24 */ - .mux_id = 0, - .mux_config = {.bit = 16, .mask = 1, .fn = 1}, - }, { /* GPIO25 */ - .mux_id = 0, - .mux_config = {.bit = 26, .mask = 1, .fn = 1}, - }, -}; - -const int n_gpios = ARRAY_SIZE(gpio_data); - -#if CONFIG_INTEL_IOMUX - -#include <sof/drivers/iomux.h> - -struct iomux iomux_data[] = { - {.base = EXT_CTRL_BASE + 0x30,}, - {.base = EXT_CTRL_BASE + 0x34,}, - {.base = EXT_CTRL_BASE + 0x38,}, -}; - -const int n_iomux = ARRAY_SIZE(iomux_data); - -#endif - #endif -SHARED_DATA struct timer timer = { - .id = TIMER3, /* external timer */ - .irq = IRQ_EXT_TSTAMP0_LVL2, - .irq_name = irq_name_level2, -}; +#include <cavs/drivers/sideband-ipc.h> -SHARED_DATA struct timer arch_timer = { - .id = TIMER1, /* internal timer */ - .irq = IRQ_NUM_TIMER2, -}; - -#if CONFIG_DW_SPI - -#include <sof/drivers/spi.h> - -static struct spi_platform_data spi = { - .base = DW_SPI_SLAVE_BASE, - .type = SOF_SPI_INTEL_SLAVE, - .fifo[SPI_DIR_RX] = { - .handshake = DMA_HANDSHAKE_SSI_RX, - }, - .fifo[SPI_DIR_TX] = { - .handshake = DMA_HANDSHAKE_SSI_TX, - } -}; +/* DSP IPC for Host Registers */ +#define IPC_DIPCIDR 0x10 +#define IPC_DIPCIDD 0x18 -int platform_boot_complete(uint32_t boot_message) +static inline void ipc_write(uint32_t reg, uint32_t val) { - return spi_push(spi_get(SOF_SPI_INTEL_SLAVE), &ready, sizeof(ready)); + *((volatile uint32_t*)(IPC_HOST_BASE + reg)) = val; } -#else - int platform_boot_complete(uint32_t boot_message) { - uint32_t mb_offset = 0; - - mailbox_dspbox_write(mb_offset, &ready, sizeof(ready)); - mb_offset = mb_offset + sizeof(ready); - -#if CONFIG_MEM_WND - mailbox_dspbox_write(mb_offset, &sram_window, - sram_window.ext_hdr.hdr.size); - mb_offset = mb_offset + sram_window.ext_hdr.hdr.size; -#endif + struct ipc_cmd_hdr header; - /* variable length compiler description is a last field of cc_version */ - mailbox_dspbox_write(mb_offset, &cc_version, - cc_version.ext_hdr.hdr.size); - mb_offset = mb_offset + cc_version.ext_hdr.hdr.size; + mailbox_dspbox_write(0, &ready, sizeof(ready)); - mailbox_dspbox_write(mb_offset, &probe_support, - probe_support.ext_hdr.hdr.size); - mb_offset = mb_offset + probe_support.ext_hdr.hdr.size; + /* get any IPC specific boot message and optional data */ + ipc_boot_complete_msg(&header, SRAM_WINDOW_HOST_OFFSET(0) >> 12); - mailbox_dspbox_write(mb_offset, &user_abi_version, - user_abi_version.ext_hdr.hdr.size); + /* tell host we are ready (IPC4) */ + ipc_write(IPC_DIPCIDD, header.ext); + ipc_write(IPC_DIPCIDR, IPC_DIPCIDR_BUSY | header.pri); - /* tell host we are ready */ -#if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_write(IPC_DIPCIE, SRAM_WINDOW_HOST_OFFSET(0) >> 12); - ipc_write(IPC_DIPCI, 0x80000000 | SOF_IPC_FW_READY); -#else - ipc_write(IPC_DIPCIDD, SRAM_WINDOW_HOST_OFFSET(0) >> 12); - ipc_write(IPC_DIPCIDR, 0x80000000 | SOF_IPC_FW_READY); -#endif return 0; } -#endif - -#if CAVS_VERSION >= CAVS_VERSION_1_8 -/* init HW */ -static void platform_init_hw(void) -{ - io_reg_write(DSP_INIT_GENO, - GENO_MDIVOSEL | GENO_DIOPTOSEL); - - io_reg_write(DSP_INIT_IOPO, - IOPO_DMIC_FLAG | IOPO_I2S_FLAG); - - io_reg_write(DSP_INIT_ALHO, - ALHO_ASO_FLAG | ALHO_CSO_FLAG); - - io_reg_write(DSP_INIT_LPGPDMA(0), - LPGPDMA_CHOSEL_FLAG | LPGPDMA_CTLOSEL_FLAG); - io_reg_write(DSP_INIT_LPGPDMA(1), - LPGPDMA_CHOSEL_FLAG | LPGPDMA_CTLOSEL_FLAG); -} -#endif +static struct pm_notifier pm_state_notifier; +/* Runs on the primary core only */ int platform_init(struct sof *sof) { -#if CONFIG_DW_SPI - struct spi *spi_dev; -#endif int ret; - int i; - - sof->platform_timer = cache_to_uncache(&timer); - sof->cpu_timer = cache_to_uncache(&arch_timer); - - /* Turn off memory for all unused cores */ - for (i = 0; i < PLATFORM_CORE_COUNT; i++) - if (i != PLATFORM_MASTER_CORE_ID) - pm_runtime_put(CORE_MEMORY_POW, i); - - /* pm runtime already initialized, request the DSP to stay in D0 - * until we are allowed to do full power gating (by the IPC req). - */ - pm_runtime_disable(PM_RUNTIME_DSP, 0); - -#if CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_SUECREEK || CONFIG_TIGERLAKE - trace_point(TRACE_BOOT_PLATFORM_ENTRY); - platform_init_hw(); -#endif - - trace_point(TRACE_BOOT_PLATFORM_IRQ); - platform_interrupt_init(); - -#if CONFIG_MEM_WND - trace_point(TRACE_BOOT_PLATFORM_MBOX); - platform_memory_windows_init(MEM_WND_INIT_CLEAR); -#endif - - /* init timers, clocks and schedulers */ - trace_point(TRACE_BOOT_PLATFORM_TIMER); - platform_timer_start(sof->platform_timer); - - trace_point(TRACE_BOOT_PLATFORM_CLOCK); - platform_clock_init(sof); trace_point(TRACE_BOOT_PLATFORM_SCHED); scheduler_init_edf(); /* init low latency timer domain and scheduler */ - sof->platform_timer_domain = - timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK, - CONFIG_SYSTICK_PERIOD); + /* clk is ignored on Zephyr so pass 0 */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, 0); scheduler_init_ll(sof->platform_timer_domain); /* init the system agent */ @@ -400,65 +128,6 @@ int platform_init(struct sof *sof) /* Set CPU to max frequency for booting (single shim_write below) */ trace_point(TRACE_BOOT_PLATFORM_CPU_FREQ); -#if CONFIG_APOLLOLAKE - /* initialize PM for boot */ - - /* TODO: there are two clk freqs CRO & CRO/4 - * Running on CRO all the time atm - */ - - shim_write(SHIM_CLKCTL, - SHIM_CLKCTL_HDCS_PLL | /* HP domain clocked by PLL */ - SHIM_CLKCTL_LDCS_PLL | /* LP domain clocked by PLL */ - SHIM_CLKCTL_DPCS_DIV1(0) | /* Core 0 clk not divided */ - SHIM_CLKCTL_DPCS_DIV1(1) | /* Core 1 clk not divided */ - SHIM_CLKCTL_HPMPCS_DIV2 | /* HP mem clock div by 2 */ - SHIM_CLKCTL_LPMPCS_DIV4 | /* LP mem clock div by 4 */ - SHIM_CLKCTL_TCPAPLLS_DIS | - SHIM_CLKCTL_TCPLCG_DIS(0) | SHIM_CLKCTL_TCPLCG_DIS(1)); - - shim_write(SHIM_LPSCTL, shim_read(SHIM_LPSCTL)); - -#elif CONFIG_CANNONLAKE || CONFIG_ICELAKE || CONFIG_TIGERLAKE - - /* initialize PM for boot */ - - /* request configured ring oscillator and wait for status ready */ - shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | CAVS_DEFAULT_RO); - while (!(shim_read(SHIM_CLKSTS) & CAVS_DEFAULT_RO)) - idelay(16); - - shim_write(SHIM_CLKCTL, - CAVS_DEFAULT_RO | /* Request configured RING Osc */ - CAVS_DEFAULT_RO_FOR_MEM | /* Select configured - * RING Oscillator Clk for memory - */ - SHIM_CLKCTL_HMCS_DIV2 | /* HP mem clock div by 2 */ - SHIM_CLKCTL_LMCS_DIV4 | /* LP mem clock div by 4 */ - SHIM_CLKCTL_TCPLCG_DIS_ALL); /* Allow Local Clk Gating */ - - /* prevent LP GPDMA 0&1 clock gating */ - shim_write(SHIM_GPDMA_CLKCTL(0), SHIM_CLKCTL_LPGPDMAFDCGB); - shim_write(SHIM_GPDMA_CLKCTL(1), SHIM_CLKCTL_LPGPDMAFDCGB); - - /* prevent DSP Common power gating */ - pm_runtime_get(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); - -#elif CONFIG_SUECREEK - /* TODO: need to merge as for APL */ - clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); - - /* prevent Core0 clock gating. */ - shim_write(SHIM_CLKCTL, shim_read(SHIM_CLKCTL) | - SHIM_CLKCTL_TCPLCG(0)); - - /* prevent LP GPDMA 0&1 clock gating */ - shim_write(SHIM_GPDMA_CLKCTL(0), SHIM_CLKCTL_LPGPDMAFDCGB); - shim_write(SHIM_GPDMA_CLKCTL(1), SHIM_CLKCTL_LPGPDMAFDCGB); - - /* prevent DSP Common power gating */ - pm_runtime_get(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID); -#endif /* init DMACs */ trace_point(TRACE_BOOT_PLATFORM_DMA); @@ -466,13 +135,9 @@ int platform_init(struct sof *sof) if (ret < 0) return ret; - /* init low latency single channel DW-DMA domain and scheduler */ - sof->platform_dma_domain = - dma_single_chan_domain_init - (&sof->dma_info->dma_array[PLATFORM_DW_DMA_INDEX], - PLATFORM_NUM_DW_DMACS, - PLATFORM_DEFAULT_CLOCK); - scheduler_init_ll(sof->platform_dma_domain); + /* register power states exit notifiers */ + pm_state_notifier.state_exit = cpu_notify_state_exit; + pm_notifier_register(&pm_state_notifier); /* initialize the host IPC mechanisms */ trace_point(TRACE_BOOT_PLATFORM_IPC); @@ -490,45 +155,69 @@ int platform_init(struct sof *sof) if (ret < 0) return ret; -#if CONFIG_DW_SPI - /* initialize the SPI slave */ - trace_point(TRACE_BOOT_PLATFORM_SPI); - spi_init(); - ret = spi_install(&spi, 1); - if (ret < 0) - return ret; - - spi_dev = spi_get(SOF_SPI_INTEL_SLAVE); - if (!spi_dev) - return -ENODEV; - - /* initialize the SPI-SLave module */ - ret = spi_probe(spi_dev); - if (ret < 0) - return ret; -#elif CONFIG_TRACE - /* Initialize DMA for Trace*/ - trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); - dma_trace_init_complete(sof->dmat); -#endif - /* show heap status */ heap_trace_all(1); return 0; } -void platform_wait_for_interrupt(int level) +#if CONFIG_CAVS_IMR_D3_PERSISTENT +/* These structs and macros are from from the ROM code header + * on cAVS platforms, please keep them immutable + */ + +#define ADSP_IMR_MAGIC_VALUE 0x02468ACE +#define IMR_L1_CACHE_ADDRESS 0xB0000000 + +struct imr_header { + uint32_t adsp_imr_magic; + uint32_t structure_version; + uint32_t structure_size; + uint32_t imr_state; + uint32_t imr_size; + void *imr_restore_vector; +}; + +struct imr_state { + struct imr_header header; + uint8_t reserved[0x1000 - sizeof(struct imr_header)]; +}; + +struct imr_layout { + uint8_t css_reserved[0x1000]; + struct imr_state imr_state; +}; + +/* cAVS ROM structs and macros end */ + +static void imr_layout_update(void *vector) { -#if CONFIG_CAVS_USE_LPRO_IN_WAITI - platform_clock_on_waiti(); + struct imr_layout *imr_layout = (struct imr_layout *)(IMR_L1_CACHE_ADDRESS); + + /* update the IMR layout and write it back to uncache memory + * for ROM code usage. The ROM code will read this from IMR + * at the subsequent run and decide (e.g. combine with checking + * if FW_PURGE IPC from host got) if it can use the previous + * IMR FW directly. So this here is only a host->FW->ROM one way + * configuration, no symmetric task need to done in any + * platform_resume() to clear the configuration. + */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)imr_layout, + sizeof(*imr_layout)); + imr_layout->imr_state.header.adsp_imr_magic = ADSP_IMR_MAGIC_VALUE; + imr_layout->imr_state.header.imr_restore_vector = vector; + dcache_writeback_region((__sparse_force void __sparse_cache *)imr_layout, + sizeof(*imr_layout)); +} #endif -#if (CONFIG_CAVS_LPS) - if (pm_runtime_is_active(PM_RUNTIME_DSP, PLATFORM_MASTER_CORE_ID)) - arch_wait_for_interrupt(level); - else - lps_wait_for_interrupt(level); -#else - arch_wait_for_interrupt(level); + +int platform_context_save(struct sof *sof) +{ + ipc_get()->task_mask |= IPC_TASK_POWERDOWN; + +#if CONFIG_CAVS_IMR_D3_PERSISTENT + /* Only support IMR restoring on cAVS 1.8 and onward at the moment. */ + imr_layout_update((void *)IMR_BOOT_LDR_TEXT_ENTRY_BASE); #endif + return 0; } diff --git a/src/platform/library/CMakeLists.txt b/src/platform/library/CMakeLists.txt new file mode 100644 index 000000000000..ffc7649998c6 --- /dev/null +++ b/src/platform/library/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) +add_subdirectory(schedule) + +add_local_sources(sof + panic.c + platform.c + init.c +) diff --git a/src/platform/library/include/platform/drivers/idc.h b/src/platform/library/include/platform/drivers/idc.h index 9732796cbdcb..e538884bbb5f 100644 --- a/src/platform/library/include/platform/drivers/idc.h +++ b/src/platform/library/include/platform/drivers/idc.h @@ -5,7 +5,7 @@ * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> */ -#ifdef __SOF_DRIVERS_IDC_H__ +#ifdef __POSIX_RTOS_IDC_H__ #ifndef __PLATFORM_DRIVERS_IDC_H__ #define __PLATFORM_DRIVERS_IDC_H__ @@ -28,10 +28,15 @@ static inline int idc_init(void) return 0; } +static inline int idc_restore(void) +{ + return 0; +} + #endif /* __PLATFORM_DRIVERS_IDC_H__ */ #else -#error "This file shouldn't be included from outside of sof/drivers/idc.h" +#error "This file shouldn't be included from outside of Zephyr/XTOS's rtos/idc.h" -#endif /* __SOF_DRIVERS_IDC_H__ */ +#endif diff --git a/src/platform/library/include/platform/lib/clk.h b/src/platform/library/include/platform/lib/clk.h index 7c089ebac4f9..6d389a6152af 100644 --- a/src/platform/library/include/platform/lib/clk.h +++ b/src/platform/library/include/platform/lib/clk.h @@ -18,6 +18,22 @@ #define NUM_CLOCKS 2 +#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 diff --git a/src/platform/library/include/platform/lib/cpu.h b/src/platform/library/include/platform/lib/cpu.h index a9b4c38be571..564f383f0880 100644 --- a/src/platform/library/include/platform/lib/cpu.h +++ b/src/platform/library/include/platform/lib/cpu.h @@ -10,11 +10,7 @@ #ifndef __PLATFORM_LIB_CPU_H__ #define __PLATFORM_LIB_CPU_H__ -#define PLATFORM_CORE_COUNT 1 - -#define MAX_CORE_COUNT 1 - -#define PLATFORM_MASTER_CORE_ID 0 +#define PLATFORM_PRIMARY_CORE_ID 0 #endif /* __PLATFORM_LIB_CPU_H__ */ diff --git a/src/platform/library/include/platform/lib/dai.h b/src/platform/library/include/platform/lib/dai.h index 45065e86c3b9..5fb740e32270 100644 --- a/src/platform/library/include/platform/lib/dai.h +++ b/src/platform/library/include/platform/lib/dai.h @@ -10,6 +10,22 @@ #ifndef __PLATFORM_LIB_DAI_H__ #define __PLATFORM_LIB_DAI_H__ +#define DAI_NUM_SSP_BASE 6 + +/** \brief Number of HD/A Link Outputs */ +#define DAI_NUM_HDA_OUT 6 + +/** \brief Number of HD/A Link Inputs */ +#define DAI_NUM_HDA_IN 7 + +/* ALH */ + +/** \brief Number of ALH bi-directional links */ +#define DAI_NUM_ALH_BI_DIR_LINKS 16 + +/** \brief Number of contiguous ALH bi-dir links */ +#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 4 + #endif /* __PLATFORM_LIB_DAI_H__ */ #else diff --git a/src/platform/library/include/platform/lib/dma.h b/src/platform/library/include/platform/lib/dma.h index 69ad93b914b0..510df4301d31 100644 --- a/src/platform/library/include/platform/lib/dma.h +++ b/src/platform/library/include/platform/lib/dma.h @@ -2,7 +2,7 @@ * * Copyright(c) 2016 Intel Corporation. All rights reserved. * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Author: Curtis Malainey <cujomalainey@chromium.org> */ #ifdef __SOF_LIB_DMA_H__ @@ -16,6 +16,12 @@ #define DMA_DEV_PCM 0 #define DMA_DEV_WAV 1 +#define PLATFORM_NUM_DMACS 1 +#define PLATFORM_MAX_DMA_CHAN 1 + +#define dma_chan_irq(dma, chan) 0 +#define dma_chan_irq_name(dma, chan) "chan0-irq" + #endif /* __PLATFORM_LIB_DMA_H__ */ #else diff --git a/src/platform/library/include/platform/lib/ll_schedule.h b/src/platform/library/include/platform/lib/ll_schedule.h new file mode 100644 index 000000000000..06c918b84fdc --- /dev/null +++ b/src/platform/library/include/platform/lib/ll_schedule.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + */ + +#ifndef __LIBRARY_INCLUDE_LIB_SCHEDULE_H__ +#define __LIBRARY_INCLUDE_LIB_SCHEDULE_H__ + +#include <rtos/task.h> +#include <stdint.h> + +struct task; +struct sof_uuid_entry; +struct ll_schedule_domain; + +void schedule_ll_run_tasks(void); + +int scheduler_init_ll(struct ll_schedule_domain *domain); + +int schedule_task_init_ll(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags); + +#endif /* __LIBRARY_INCLUDE_LIB_SCHEDULE_H__ */ diff --git a/src/platform/library/include/platform/lib/mailbox.h b/src/platform/library/include/platform/lib/mailbox.h index 0c9367a3d1bb..daa858481149 100644 --- a/src/platform/library/include/platform/lib/mailbox.h +++ b/src/platform/library/include/platform/lib/mailbox.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2016 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Google Inc. All rights reserved. * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Author: Curtis Malainey <cujomalainey@chromium.org> */ #ifdef __SOF_LIB_MAILBOX_H__ @@ -14,20 +14,19 @@ #include <stddef.h> #include <stdint.h> -#define MAILBOX_HOST_OFFSET 0x144000 +#define MAILBOX_DSPBOX_OFFSET 0x0 +#define MAILBOX_DSPBOX_SIZE 0x400 +#define MAILBOX_DSPBOX_BASE \ + (MAILBOX_BASE + MAILBOX_DSPBOX_OFFSET) -#define MAILBOX_OUTBOX_OFFSET 0x0 -#define MAILBOX_OUTBOX_SIZE 0x400 -#define MAILBOX_OUTBOX_BASE \ - (MAILBOX_BASE + MAILBOX_OUTBOX_OFFSET) - -#define MAILBOX_INBOX_OFFSET MAILBOX_OUTBOX_SIZE -#define MAILBOX_INBOX_SIZE 0x400 -#define MAILBOX_INBOX_BASE \ - (MAILBOX_BASE + MAILBOX_INBOX_OFFSET) +#define MAILBOX_HOSTBOX_OFFSET \ + (MAILBOX_DSPBOX_SIZE + MAILBOX_DSPBOX_OFFSET) +#define MAILBOX_HOSTBOX_SIZE 0x400 +#define MAILBOX_HOSTBOX_BASE \ + (MAILBOX_BASE + MAILBOX_HOSTBOX_OFFSET) #define MAILBOX_EXCEPTION_OFFSET \ - (MAILBOX_INBOX_SIZE + MAILBOX_OUTBOX_SIZE) + (MAILBOX_HOSTBOX_SIZE + MAILBOX_HOSTBOX_OFFSET) #define MAILBOX_EXCEPTION_SIZE 0x100 #define MAILBOX_EXCEPTION_BASE \ (MAILBOX_BASE + MAILBOX_EXCEPTION_OFFSET) @@ -40,7 +39,8 @@ #define MAILBOX_STREAM_OFFSET \ (MAILBOX_DEBUG_SIZE + MAILBOX_DEBUG_OFFSET) -#define MAILBOX_STREAM_SIZE 0x200 +/* host mailbox can be bigger to support larger and more complex use cases */ +#define MAILBOX_STREAM_SIZE 0x2000 #define MAILBOX_STREAM_BASE \ (MAILBOX_BASE + MAILBOX_STREAM_OFFSET) @@ -52,6 +52,18 @@ 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) {} + +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; +} + #endif /* __PLATFORM_LIB_MAILBOX_H__ */ #else diff --git a/src/platform/library/include/platform/lib/memory.h b/src/platform/library/include/platform/lib/memory.h index fb8fd6a59500..fafb3df303f7 100644 --- a/src/platform/library/include/platform/lib/memory.h +++ b/src/platform/library/include/platform/lib/memory.h @@ -10,22 +10,30 @@ #ifndef __PLATFORM_LIB_MEMORY_H__ #define __PLATFORM_LIB_MEMORY_H__ +#include <inttypes.h> +#include <stddef.h> + +/* prioritize definitions in Zephyr SoC layer */ +#ifdef __ZEPHYR__ +#include <adsp_memory.h> +#endif + +struct sof; + #define PLATFORM_DCACHE_ALIGN sizeof(void *) -#define HEAP_BUFFER_SIZE (1024 * 128) -#define SOF_STACK_SIZE 0x1000 +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) -#define MAILBOX_DSPBOX_BASE 0 -#define MAILBOX_DSPBOX_SIZE 0x400 -#define MAILBOX_HOSTBOX_BASE 0 -#define MAILBOX_HOSTBOX_SIZE 0x400 -#define MAILBOX_BASE 0 -#define MAILBOX_BASE_SIZE 0x400 +uint8_t *get_library_mailbox(void); -#define PLATFORM_HEAP_SYSTEM 1 -#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define MAILBOX_BASE get_library_mailbox() + +#define PLATFORM_HEAP_SYSTEM 2 +#define PLATFORM_HEAP_SYSTEM_RUNTIME CONFIG_CORE_COUNT #define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 3 +#define PLATFORM_HEAP_BUFFER 2 +#define PLATFORM_HEAP_SYSTEM_SHARED 1 +#define PLATFORM_HEAP_RUNTIME_SHARED 1 #define SHARED_DATA @@ -34,7 +42,147 @@ static inline void *platform_shared_get(void *ptr, int bytes) return ptr; } -static inline void platform_shared_commit(void *ptr, int bytes) { } +void platform_init_memmap(struct sof *sof); + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define is_uncached(address) 1 +#define cache_to_uncache_init(address) address + +#define ARCH_OOPS_SIZE 0 + +static inline void *arch_get_stack_entry(void) +{ + return NULL; +} + +static inline uint32_t arch_get_stack_size(void) +{ + return 0; +} + +/* NOTE - FAKE Memory configurations are used by UT's to test allocator */ + +#define SRAM_BANK_SIZE 0x10000 +#define LP_SRAM_SIZE SRAM_BANK_SIZE +/* use big enough HP_SRAM_SIZE to build all components for the test bench at once */ +#define HP_SRAM_SIZE (SRAM_BANK_SIZE * 47) + +#define HP_SRAM_BASE 0xBE000000 +#ifndef LP_SRAM_BASE +#define LP_SRAM_BASE 0xBE800000 +#endif + +#define SOF_FW_END (HP_SRAM_BASE + HP_SRAM_SIZE) + +/* Heap section sizes for system runtime heap for primary core */ +#define HEAP_SYS_RT_0_COUNT64 128 +#define HEAP_SYS_RT_0_COUNT512 16 +#define HEAP_SYS_RT_0_COUNT1024 4 + +/* Heap section sizes for system runtime heap for secondary core */ +#define HEAP_SYS_RT_X_COUNT64 64 +#define HEAP_SYS_RT_X_COUNT512 8 +#define HEAP_SYS_RT_X_COUNT1024 4 + +/* Heap section sizes for module pool */ +#define HEAP_COUNT64 128 +#define HEAP_COUNT128 64 +#define HEAP_COUNT256 128 +#define HEAP_COUNT512 8 +#define HEAP_COUNT1024 4 +#define HEAP_COUNT2048 1 +#define HEAP_COUNT4096 1 + +/* Heap configuration */ +#define HEAP_RUNTIME_SIZE \ + (HEAP_COUNT64 * 64 + HEAP_COUNT128 * 128 + \ + HEAP_COUNT256 * 256 + HEAP_COUNT512 * 512 + \ + HEAP_COUNT1024 * 1024 + HEAP_COUNT2048 * 2048 + \ + HEAP_COUNT4096 * 4096) + +/* Heap section sizes for runtime shared heap */ +#define HEAP_RUNTIME_SHARED_COUNT64 (64 + 32 * CONFIG_CORE_COUNT) +#define HEAP_RUNTIME_SHARED_COUNT128 64 +#define HEAP_RUNTIME_SHARED_COUNT256 4 +#define HEAP_RUNTIME_SHARED_COUNT512 16 +#define HEAP_RUNTIME_SHARED_COUNT1024 4 + +#define HEAP_RUNTIME_SHARED_SIZE \ + (HEAP_RUNTIME_SHARED_COUNT64 * 64 + HEAP_RUNTIME_SHARED_COUNT128 * 128 + \ + HEAP_RUNTIME_SHARED_COUNT256 * 256 + HEAP_RUNTIME_SHARED_COUNT512 * 512 + \ + HEAP_RUNTIME_SHARED_COUNT1024 * 1024) + +/* Heap section sizes for system shared heap */ +#define HEAP_SYSTEM_SHARED_SIZE 0x1500 + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT_MAX (HP_SRAM_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define HEAP_SYSTEM_M_SIZE 0x4000 /* heap primary core size */ +#define HEAP_SYSTEM_S_SIZE 0x3000 /* heap secondary core size */ + +#define HEAP_SYSTEM_T_SIZE \ + (HEAP_SYSTEM_M_SIZE + ((CONFIG_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) + +#define HEAP_SYS_RUNTIME_M_SIZE \ + (HEAP_SYS_RT_0_COUNT64 * 64 + HEAP_SYS_RT_0_COUNT512 * 512 + \ + HEAP_SYS_RT_0_COUNT1024 * 1024) + +#define HEAP_SYS_RUNTIME_S_SIZE \ + (HEAP_SYS_RT_X_COUNT64 * 64 + HEAP_SYS_RT_X_COUNT512 * 512 + \ + HEAP_SYS_RT_X_COUNT1024 * 1024) + +#define HEAP_SYS_RUNTIME_T_SIZE \ + (HEAP_SYS_RUNTIME_M_SIZE + ((CONFIG_CORE_COUNT - 1) * \ + HEAP_SYS_RUNTIME_S_SIZE)) + +/* Heap section sizes for module pool */ +#define HEAP_RT_LP_COUNT8 0 +#define HEAP_RT_LP_COUNT16 256 +#define HEAP_RT_LP_COUNT32 128 +#define HEAP_RT_LP_COUNT64 64 +#define HEAP_RT_LP_COUNT128 64 +#define HEAP_RT_LP_COUNT256 96 +#define HEAP_RT_LP_COUNT512 8 +#define HEAP_RT_LP_COUNT1024 4 + +/* Heap configuration */ +#define SOF_LP_DATA_SIZE 0x4000 + +#define HEAP_LP_SYSTEM_BASE (LP_SRAM_BASE + SOF_LP_DATA_SIZE) +#define HEAP_LP_SYSTEM_SIZE 0x1000 + +#define HEAP_LP_RUNTIME_BASE \ + (HEAP_LP_SYSTEM_BASE + HEAP_LP_SYSTEM_SIZE) +#define HEAP_LP_RUNTIME_SIZE \ + (HEAP_RT_LP_COUNT8 * 8 + HEAP_RT_LP_COUNT16 * 16 + \ + HEAP_RT_LP_COUNT32 * 32 + HEAP_RT_LP_COUNT64 * 64 + \ + HEAP_RT_LP_COUNT128 * 128 + HEAP_RT_LP_COUNT256 * 256 + \ + HEAP_RT_LP_COUNT512 * 512 + HEAP_RT_LP_COUNT1024 * 1024) + +#define HEAP_LP_BUFFER_BLOCK_SIZE 0x180 +#define HEAP_LP_BUFFER_COUNT \ + (HEAP_LP_BUFFER_SIZE / HEAP_LP_BUFFER_BLOCK_SIZE) + +#define HEAP_LP_BUFFER_BASE LP_SRAM_BASE +#define HEAP_LP_BUFFER_SIZE LP_SRAM_SIZE + +/* SOF Core S configuration */ +#define SOF_CORE_S_SIZE \ + ALIGN((HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE + SOF_STACK_SIZE),\ + SRAM_BANK_SIZE) +#define SOF_CORE_S_T_SIZE ((CONFIG_CORE_COUNT - 1) * SOF_CORE_S_SIZE) + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#define IMR_BOOT_LDR_MANIFEST_BASE NULL #endif /* __PLATFORM_LIB_MEMORY_H__ */ diff --git a/src/platform/library/include/platform/lib/pm_runtime.h b/src/platform/library/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..9c4fb663fbf2 --- /dev/null +++ b/src/platform/library/include/platform/lib/pm_runtime.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +/** + * \file platform/library/include/platform/lib/pm_runtime.h + * \brief Runtime power management header file for host-side testing + * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> +#include <stdbool.h> + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +static inline 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_... + */ +static inline 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_... + */ +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/library/include/platform/lib/shim.h b/src/platform/library/include/platform/lib/shim.h deleted file mode 100644 index 10a4f517bf53..000000000000 --- a/src/platform/library/include/platform/lib/shim.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <stdint.h> - -static inline uint32_t shim_read(uint32_t reg) {return 0; } -static inline void shim_write(uint32_t reg, uint32_t val) {} - -#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/library/include/platform/platform.h b/src/platform/library/include/platform/platform.h index 03b985d0cc63..2b1b4f31fa0c 100644 --- a/src/platform/library/include/platform/platform.h +++ b/src/platform/library/include/platform/platform.h @@ -11,8 +11,9 @@ #ifndef __PLATFORM_PLATFORM_H__ #define __PLATFORM_PLATFORM_H__ -#include <arch/lib/wait.h> -#include <sof/lib/clk.h> +#include <rtos/wait.h> +#include <rtos/clk.h> +#include <sof/lib/mailbox.h> #include <stdint.h> struct ipc_msg; @@ -40,6 +41,23 @@ struct timer; /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +#define HW_CFG_VERSION 0 + static inline void platform_panic(uint32_t p) {} /** @@ -47,12 +65,12 @@ static inline void platform_panic(uint32_t p) {} * May be power-optimized using platform specific capabilities. * @param level Interrupt level. */ -static inline void platform_wait_for_interrupt(int level) -{ - arch_wait_for_interrupt(level); -} +static inline void platform_wait_for_interrupt(int level) {} + + +static inline int ipc_platform_send_msg(const struct ipc_msg *msg) { return 0; } -static inline int ipc_platform_send_msg(struct ipc_msg *msg) { return 0; } +static inline void ipc_platform_send_msg_direct(const struct ipc_msg *msg) {} #endif /* __PLATFORM_PLATFORM_H__ */ diff --git a/src/platform/library/init.c b/src/platform/library/init.c new file mode 100644 index 000000000000..7da29f2d8668 --- /dev/null +++ b/src/platform/library/init.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include <rtos/sof.h> +#include <stdlib.h> + +/* main firmware context */ +static struct sof sof; + +struct sof *sof_get() +{ + return &sof; +} diff --git a/src/platform/library/lib/CMakeLists.txt b/src/platform/library/lib/CMakeLists.txt new file mode 100644 index 000000000000..05965cd482ee --- /dev/null +++ b/src/platform/library/lib/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + alloc.c + clk.c + dai.c + pm_runtime.c + memory.c +) + +if (CONFIG_TRACE) + add_local_sources(sof trace.c) +endif() diff --git a/src/platform/library/lib/alloc.c b/src/platform/library/lib/alloc.c new file mode 100644 index 000000000000..953267ab5265 --- /dev/null +++ b/src/platform/library/lib/alloc.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <malloc.h> +#include <rtos/alloc.h> +#include <sof/lib/mm_heap.h> + +/* testbench mem alloc definition */ + +void *rmalloc_align(uint32_t flags, size_t bytes, uint32_t alignment) +{ + return malloc(bytes); +} + +void *rmalloc(uint32_t flags, size_t bytes) +{ + return malloc(bytes); +} + +void *rzalloc(uint32_t flags, size_t bytes) +{ + return calloc(bytes, 1); +} + +void rfree(void *ptr) +{ + free(ptr); +} + +void *rballoc_align(uint32_t flags, size_t bytes, + uint32_t alignment) +{ + return malloc(bytes); +} + +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + return malloc(bytes); +} + +void sof_heap_free(struct k_heap *heap, void *addr) +{ + free(addr); +} + +void heap_trace(struct mm_heap *heap, int size) +{ +#if MALLOC_DEBUG + malloc_info(0, stdout); +#endif +} + +void heap_trace_all(int force) +{ + heap_trace(NULL, 0); +} + +struct k_heap *sof_sys_heap_get(void) +{ + return NULL; +} + +struct k_heap *sof_sys_user_heap_get(void) +{ + return NULL; +} diff --git a/src/platform/library/lib/clk.c b/src/platform/library/lib/clk.c new file mode 100644 index 000000000000..aa7c86cd2f91 --- /dev/null +++ b/src/platform/library/lib/clk.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include <rtos/clk.h> + +uint64_t clock_ms_to_ticks(int clock, uint64_t ms) +{ + return 0; +} + +uint64_t clock_us_to_ticks(int clock, uint64_t us) +{ + return 0; +} + +uint64_t clock_ns_to_ticks(int clock, uint64_t ns) +{ + return 0; +} diff --git a/src/platform/library/lib/dai.c b/src/platform/library/lib/dai.c new file mode 100644 index 000000000000..2d0de317bb22 --- /dev/null +++ b/src/platform/library/lib/dai.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google Inc. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org> + +#include <rtos/sof.h> +#include <sof/lib/dai.h> + +const struct dai_type_info dti[] = { +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/library/lib/memory.c b/src/platform/library/lib/memory.c new file mode 100644 index 000000000000..1a03d1ecf503 --- /dev/null +++ b/src/platform/library/lib/memory.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <rtos/cache.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/platform.h> +#include <rtos/sof.h> +#include <ipc/topology.h> +#include <stdint.h> +#include <stdlib.h> + +#define uncached_block_hdr(hdr) cache_to_uncache_init((struct block_hdr *)(hdr)) +#define uncached_block_map(map) cache_to_uncache((struct block_map *)(map)) + +/* Memory mock for memmap */ +#define HEAP_SYSTEM_0_BASE 0xBE100000 +#define HEAP_SYS_RUNTIME_0_BASE 0xBE120000 +#define SOF_CORE_S_START 0xBE140000 +#define HEAP_RUNTIME_BASE 0xBE180000 +#define HEAP_BUFFER_BASE 0xBE1C0000 + +/* Heap blocks for system runtime for primary core */ +static SHARED_DATA struct block_hdr sys_rt_0_block64[HEAP_SYS_RT_0_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_0_block512[HEAP_SYS_RT_0_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_0_block1024[HEAP_SYS_RT_0_COUNT1024]; + +/* Heap blocks for system runtime for secondary core */ +#if CONFIG_CORE_COUNT > 1 +static SHARED_DATA struct block_hdr + sys_rt_x_block64[CONFIG_CORE_COUNT - 1][HEAP_SYS_RT_X_COUNT64]; +static SHARED_DATA struct block_hdr + sys_rt_x_block512[CONFIG_CORE_COUNT - 1][HEAP_SYS_RT_X_COUNT512]; +static SHARED_DATA struct block_hdr + sys_rt_x_block1024[CONFIG_CORE_COUNT - 1][HEAP_SYS_RT_X_COUNT1024]; +#endif + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[CONFIG_CORE_COUNT][3] = { + { BLOCK_DEF(64, HEAP_SYS_RT_0_COUNT64, + uncached_block_hdr(sys_rt_0_block64)), + BLOCK_DEF(512, HEAP_SYS_RT_0_COUNT512, + uncached_block_hdr(sys_rt_0_block512)), + BLOCK_DEF(1024, HEAP_SYS_RT_0_COUNT1024, + uncached_block_hdr(sys_rt_0_block1024)), }, +#if CONFIG_CORE_COUNT > 1 + { BLOCK_DEF(64, HEAP_SYS_RT_X_COUNT64, + uncached_block_hdr(sys_rt_x_block64[0])), + BLOCK_DEF(512, HEAP_SYS_RT_X_COUNT512, + uncached_block_hdr(sys_rt_x_block512[0])), + BLOCK_DEF(1024, HEAP_SYS_RT_X_COUNT1024, + uncached_block_hdr(sys_rt_x_block1024[0])), }, +#endif +#if CONFIG_CORE_COUNT > 2 + { BLOCK_DEF(64, HEAP_SYS_RT_X_COUNT64, + uncached_block_hdr(sys_rt_x_block64[1])), + BLOCK_DEF(512, HEAP_SYS_RT_X_COUNT512, + uncached_block_hdr(sys_rt_x_block512[1])), + BLOCK_DEF(1024, HEAP_SYS_RT_X_COUNT1024, + uncached_block_hdr(sys_rt_x_block1024[1])), }, +#endif +#if CONFIG_CORE_COUNT > 3 + { BLOCK_DEF(64, HEAP_SYS_RT_X_COUNT64, + uncached_block_hdr(sys_rt_x_block64[2])), + BLOCK_DEF(512, HEAP_SYS_RT_X_COUNT512, + uncached_block_hdr(sys_rt_x_block512[2])), + BLOCK_DEF(1024, HEAP_SYS_RT_X_COUNT1024, + uncached_block_hdr(sys_rt_x_block1024[2])), }, +#endif +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block64[HEAP_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_COUNT2048]; +static SHARED_DATA struct block_hdr mod_block4096[HEAP_COUNT4096]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(64, HEAP_COUNT64, uncached_block_hdr(mod_block64)), + BLOCK_DEF(128, HEAP_COUNT128, uncached_block_hdr(mod_block128)), + BLOCK_DEF(256, HEAP_COUNT256, uncached_block_hdr(mod_block256)), + BLOCK_DEF(512, HEAP_COUNT512, uncached_block_hdr(mod_block512)), + BLOCK_DEF(1024, HEAP_COUNT1024, uncached_block_hdr(mod_block1024)), + BLOCK_DEF(2048, HEAP_COUNT2048, uncached_block_hdr(mod_block2048)), + BLOCK_DEF(4096, HEAP_COUNT4096, uncached_block_hdr(mod_block4096)), +}; + +#if CONFIG_CORE_COUNT > 1 +/* Heap blocks for runtime shared */ +static SHARED_DATA struct block_hdr rt_shared_block64[HEAP_RUNTIME_SHARED_COUNT64]; +static SHARED_DATA struct block_hdr rt_shared_block128[HEAP_RUNTIME_SHARED_COUNT128]; +static SHARED_DATA struct block_hdr rt_shared_block256[HEAP_RUNTIME_SHARED_COUNT256]; +static SHARED_DATA struct block_hdr rt_shared_block512[HEAP_RUNTIME_SHARED_COUNT512]; +static SHARED_DATA struct block_hdr rt_shared_block1024[HEAP_RUNTIME_SHARED_COUNT1024]; + +/* Heap memory map for runtime shared */ +static SHARED_DATA struct block_map rt_shared_heap_map[] = { + BLOCK_DEF(64, HEAP_RUNTIME_SHARED_COUNT64, uncached_block_hdr(rt_shared_block64)), + BLOCK_DEF(128, HEAP_RUNTIME_SHARED_COUNT128, uncached_block_hdr(rt_shared_block128)), + BLOCK_DEF(256, HEAP_RUNTIME_SHARED_COUNT256, uncached_block_hdr(rt_shared_block256)), + BLOCK_DEF(512, HEAP_RUNTIME_SHARED_COUNT512, uncached_block_hdr(rt_shared_block512)), + BLOCK_DEF(1024, HEAP_RUNTIME_SHARED_COUNT1024, uncached_block_hdr(rt_shared_block1024)), +}; +#endif + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT_MAX]; +static SHARED_DATA struct block_hdr lp_buf_block[HEAP_LP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT_MAX, + uncached_block_hdr(buf_block)), +}; + +static SHARED_DATA struct block_map lp_buf_heap_map[] = { + BLOCK_DEF(HEAP_LP_BUFFER_BLOCK_SIZE, HEAP_LP_BUFFER_COUNT, + uncached_block_hdr(lp_buf_block)), +}; + +static SHARED_DATA struct mm memmap; + +void platform_init_memmap(struct sof *sof) +{ + uint32_t heap_buffer_size = SOF_FW_END - HEAP_BUFFER_BASE; + uint32_t buffer_count; + int i; + + /* calculate the buffer heap size */ + buffer_count = heap_buffer_size / HEAP_BUFFER_BLOCK_SIZE; + heap_buffer_size = buffer_count * HEAP_BUFFER_BLOCK_SIZE; + + for (i = 0; i < ARRAY_SIZE(buf_heap_map); i++) { + buf_heap_map[i].count = buffer_count; + buf_heap_map[i].free_count = buffer_count; + } + dcache_writeback_region(buf_heap_map, + sizeof(struct block_map) * ARRAY_SIZE(buf_heap_map)); + + /* access memory map through uncached region */ + sof->memory_map = cache_to_uncache(&memmap); + + /* .system primary core initialization */ + sof->memory_map->system[0].heap = (unsigned long)malloc(HEAP_SYSTEM_M_SIZE); + sof->memory_map->system[0].size = HEAP_SYSTEM_M_SIZE; + sof->memory_map->system[0].info.free = HEAP_SYSTEM_M_SIZE; + sof->memory_map->system[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_EXT | + SOF_MEM_CAPS_CACHE; + + /* .system_runtime primary core initialization */ + sof->memory_map->system_runtime[0].blocks = + ARRAY_SIZE(sys_rt_heap_map[0]); + sof->memory_map->system_runtime[0].map = + uncached_block_map(sys_rt_heap_map[0]); + sof->memory_map->system_runtime[0].heap = + (unsigned long)malloc(HEAP_SYS_RUNTIME_M_SIZE); + sof->memory_map->system_runtime[0].size = HEAP_SYS_RUNTIME_M_SIZE; + sof->memory_map->system_runtime[0].info.free = HEAP_SYS_RUNTIME_M_SIZE; + sof->memory_map->system_runtime[0].caps = SOF_MEM_CAPS_RAM | + SOF_MEM_CAPS_EXT | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA; + + /* .system and .system_runtime secondary core initialization */ + for (i = 1; i < CONFIG_CORE_COUNT; i++) { + /* .system init */ + sof->memory_map->system[i].heap = + (unsigned long)malloc(HEAP_SYSTEM_S_SIZE) + + ((i - 1) * SOF_CORE_S_SIZE); + sof->memory_map->system[i].size = HEAP_SYSTEM_S_SIZE; + sof->memory_map->system[i].info.free = HEAP_SYSTEM_S_SIZE; + sof->memory_map->system[i].caps = SOF_MEM_CAPS_RAM | + SOF_MEM_CAPS_EXT | SOF_MEM_CAPS_CACHE; + + /* .system_runtime init */ + sof->memory_map->system_runtime[i].blocks = + ARRAY_SIZE(sys_rt_heap_map[i]); + sof->memory_map->system_runtime[i].map = + uncached_block_map(sys_rt_heap_map[i]); + sof->memory_map->system_runtime[i].heap = + (unsigned long)malloc(HEAP_SYS_RUNTIME_S_SIZE) + + ((i - 1) * SOF_CORE_S_SIZE) + HEAP_SYSTEM_S_SIZE; + sof->memory_map->system_runtime[i].size = + HEAP_SYS_RUNTIME_S_SIZE; + sof->memory_map->system_runtime[i].info.free = + HEAP_SYS_RUNTIME_S_SIZE; + sof->memory_map->system_runtime[i].caps = SOF_MEM_CAPS_RAM | + SOF_MEM_CAPS_EXT | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA; + } + +#if CONFIG_CORE_COUNT > 1 + /* .runtime_shared init */ + sof->memory_map->runtime_shared[0].blocks = ARRAY_SIZE(rt_shared_heap_map); + sof->memory_map->runtime_shared[0].map = uncached_block_map(rt_shared_heap_map); + sof->memory_map->runtime_shared[0].heap = + (unsigned long)cache_to_uncache(malloc(HEAP_RUNTIME_SHARED_SIZE)); + sof->memory_map->runtime_shared[0].size = HEAP_RUNTIME_SHARED_SIZE; + sof->memory_map->runtime_shared[0].info.free = HEAP_RUNTIME_SHARED_SIZE; + sof->memory_map->runtime_shared[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_EXT | + SOF_MEM_CAPS_CACHE; + + /* .system_shared init */ + sof->memory_map->system_shared[0].heap = + (unsigned long)cache_to_uncache(malloc(HEAP_SYSTEM_SHARED_SIZE)); + sof->memory_map->system_shared[0].size = HEAP_SYSTEM_SHARED_SIZE; + sof->memory_map->system_shared[0].info.free = HEAP_SYSTEM_SHARED_SIZE; + sof->memory_map->system_shared[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_EXT | + SOF_MEM_CAPS_CACHE; + +#endif + + /* .runtime init*/ + sof->memory_map->runtime[0].blocks = ARRAY_SIZE(rt_heap_map); + sof->memory_map->runtime[0].map = uncached_block_map(rt_heap_map); + sof->memory_map->runtime[0].heap = (unsigned long)malloc(HEAP_RUNTIME_SIZE); + sof->memory_map->runtime[0].size = HEAP_RUNTIME_SIZE; + sof->memory_map->runtime[0].info.free = HEAP_RUNTIME_SIZE; + sof->memory_map->runtime[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_EXT | + SOF_MEM_CAPS_CACHE; + + /* heap buffer init */ + sof->memory_map->buffer[0].blocks = ARRAY_SIZE(buf_heap_map); + sof->memory_map->buffer[0].map = uncached_block_map(buf_heap_map); + sof->memory_map->buffer[0].heap = (unsigned long)malloc(heap_buffer_size); + sof->memory_map->buffer[0].size = heap_buffer_size; + sof->memory_map->buffer[0].info.free = heap_buffer_size; + sof->memory_map->buffer[0].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_HP | + SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_DMA; + + /* heap lp buffer init */ + sof->memory_map->buffer[1].blocks = ARRAY_SIZE(lp_buf_heap_map); + sof->memory_map->buffer[1].map = uncached_block_map(lp_buf_heap_map); + sof->memory_map->buffer[1].heap = (unsigned long)malloc(HEAP_LP_BUFFER_SIZE); + sof->memory_map->buffer[1].size = HEAP_LP_BUFFER_SIZE; + sof->memory_map->buffer[1].info.free = HEAP_LP_BUFFER_SIZE; + sof->memory_map->buffer[1].caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_LP | + SOF_MEM_CAPS_CACHE | SOF_MEM_CAPS_DMA; + + /* .total init */ + sof->memory_map->total.free = HEAP_SYSTEM_T_SIZE + + HEAP_SYS_RUNTIME_T_SIZE + HEAP_RUNTIME_SIZE + heap_buffer_size + + HEAP_LP_BUFFER_SIZE; + +} diff --git a/src/platform/library/lib/pm_runtime.c b/src/platform/library/lib/pm_runtime.c new file mode 100644 index 000000000000..f0066854f88f --- /dev/null +++ b/src/platform/library/lib/pm_runtime.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include <sof/lib/pm_runtime.h> + +#include <inttypes.h> + +void pm_runtime_enable(enum pm_runtime_context context, uint32_t index) +{} + +void pm_runtime_disable(enum pm_runtime_context context, uint32_t index) +{} diff --git a/src/platform/library/lib/trace.c b/src/platform/library/lib/trace.c new file mode 100644 index 000000000000..7ca847afabec --- /dev/null +++ b/src/platform/library/lib/trace.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +#include <stdint.h> +#include <sof/trace/trace.h> +#include <sof/trace/dma-trace.h> + +/* enable trace by default in testbench */ +int host_trace_level = LOG_LEVEL_ERROR; + +/* look up subsystem class name from table */ +char *get_trace_class(uint32_t trace_class) +{ + (void)trace_class; + /* todo: trace class is deprecated, + * uuid should be used only + */ + return "unknown"; +} diff --git a/src/platform/library/panic.c b/src/platform/library/panic.c new file mode 100644 index 000000000000..bb481d69a36a --- /dev/null +++ b/src/platform/library/panic.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + +#include <rtos/panic.h> +#include <stdlib.h> + +void __panic(uint32_t p, const char *filename, uint32_t linenum) +{ + abort(); +} diff --git a/src/platform/library/platform.c b/src/platform/library/platform.c new file mode 100644 index 000000000000..756c34c996f4 --- /dev/null +++ b/src/platform/library/platform.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Google Inc. All rights reserved. +// +// Author: Curtis Malainey <cujomalainey@chromium.org> + +#include <rtos/sof.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> +#include <sof/lib/agent.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/dai.h> + +static SHARED_DATA struct timer timer = {}; + +static uint8_t mailbox[MAILBOX_DSPBOX_SIZE + + MAILBOX_HOSTBOX_SIZE + + MAILBOX_EXCEPTION_SIZE + + MAILBOX_DEBUG_SIZE + + MAILBOX_STREAM_SIZE + + MAILBOX_TRACE_SIZE]; + +uint8_t *get_library_mailbox() +{ + return mailbox; +} + +static void platform_clock_init(struct sof *sof) {} + +int dmac_init(struct sof *sof) +{ + return 0; +} + +int platform_init(struct sof *sof) +{ + sof->platform_timer = &timer; + sof->cpu_timers = &timer; + + platform_clock_init(sof); + + scheduler_init_edf(); + + /* init low latency timer domain and scheduler */ + /* sof->platform_timer_domain = */ + /* timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK, */ + /* CONFIG_SYSTICK_PERIOD); */ + + /* init the system agent */ + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + /* init DMACs */ + dmac_init(sof); + + /* initialise the host IPC mechanisms */ + ipc_init(sof); + + dai_init(sof); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} diff --git a/src/platform/library/schedule/CMakeLists.txt b/src/platform/library/schedule/CMakeLists.txt new file mode 100644 index 000000000000..31d325038217 --- /dev/null +++ b/src/platform/library/schedule/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + schedule.c + ll_schedule.c + edf_schedule.c +) diff --git a/src/platform/library/schedule/edf_schedule.c b/src/platform/library/schedule/edf_schedule.c new file mode 100644 index 000000000000..0c127c934e21 --- /dev/null +++ b/src/platform/library/schedule/edf_schedule.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> + +#include <sof/audio/component.h> +#include <rtos/task.h> +#include <stdint.h> +#include <sof/schedule/edf_schedule.h> +#include <rtos/wait.h> +#include <stdlib.h> + + /* scheduler testbench definition */ + +SOF_DEFINE_REG_UUID(edf_sched_lib); + +DECLARE_TR_CTX(edf_tr, SOF_UUID(edf_sched_lib_uuid), LOG_LEVEL_INFO); + +struct edf_schedule_data { + struct list_item list; /* list of tasks in priority queue */ + uint32_t clock; +}; + +static struct edf_schedule_data *sch; + +static int schedule_edf_task_complete(struct task *task) +{ + list_item_del(&task->list); + task->state = SOF_TASK_STATE_COMPLETED; + + return 0; +} + +/* schedule task */ +static int schedule_edf_task(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + struct edf_schedule_data *sched = data; + (void)period; + list_item_prepend(&task->list, &sched->list); + task->state = SOF_TASK_STATE_QUEUED; + + if (task->ops.run) + task->ops.run(task->data); + + schedule_edf_task_complete(task); + + return 0; +} + +static void edf_scheduler_free(void *data, uint32_t flags) +{ + free(data); +} + +static int schedule_edf_task_cancel(void *data, struct task *task) +{ + if (task->state == SOF_TASK_STATE_QUEUED) { + /* delete task */ + task->state = SOF_TASK_STATE_CANCEL; + list_item_del(&task->list); + } + + return 0; +} + +static int schedule_edf_task_free(void *data, struct task *task) +{ + task->state = SOF_TASK_STATE_FREE; + task->ops.run = NULL; + task->data = NULL; + + free(edf_sch_get_pdata(task)); + edf_sch_set_pdata(task, NULL); + + return 0; +} + +static struct scheduler_ops schedule_edf_ops = { + .schedule_task = schedule_edf_task, + .schedule_task_running = NULL, + .reschedule_task = NULL, + .schedule_task_cancel = schedule_edf_task_cancel, + .schedule_task_free = schedule_edf_task_free, + .scheduler_free = edf_scheduler_free, +}; + +int schedule_task_init_edf(struct task *task, const struct sof_uuid_entry *uid, + const struct task_ops *ops, void *data, + uint16_t core, uint32_t flags) +{ + struct edf_task_pdata *edf_pdata; + int ret = 0; + + ret = schedule_task_init(task, uid, SOF_SCHEDULE_EDF, 0, ops->run, + data, core, flags); + if (ret < 0) + return ret; + + edf_pdata = malloc(sizeof(*edf_pdata)); + edf_sch_set_pdata(task, edf_pdata); + + task->ops.complete = ops->complete; + + return 0; +} + +/* initialize scheduler */ +int scheduler_init_edf(void) +{ + tr_info(&edf_tr, "edf_scheduler_init()"); + sch = malloc(sizeof(*sch)); + list_init(&sch->list); + + scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, sch); + + return 0; +} diff --git a/src/platform/library/schedule/ll_schedule.c b/src/platform/library/schedule/ll_schedule.c new file mode 100644 index 000000000000..4cfd0a9d196c --- /dev/null +++ b/src/platform/library/schedule/ll_schedule.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + +#define _GNU_SOURCE + +#include <sof/audio/component.h> +#include <rtos/task.h> +#include <sof/schedule/schedule.h> +#include <platform/lib/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/wait.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <stdint.h> + + /* scheduler testbench definition */ + +SOF_DEFINE_REG_UUID(ll_sched_lib); + +DECLARE_TR_CTX(ll_tr, SOF_UUID(ll_sched_lib_uuid), LOG_LEVEL_INFO); + +/* list of all tasks */ +static struct list_item sched_list; + +void schedule_ll_run_tasks(void) +{ + struct list_item *tlist, *tlist_; + struct task *task; + + /* list empty then return */ + if (list_is_empty(&sched_list)) + fprintf(stdout, "LL scheduler thread exit - list empty\n"); + + /* iterate through the task list */ + list_for_item_safe(tlist, tlist_, &sched_list) { + task = container_of(tlist, struct task, list); + + /* only run queued tasks */ + if (task->state == SOF_TASK_STATE_QUEUED) { + task->state = SOF_TASK_STATE_RUNNING; + + task->ops.run(task->data); + + /* only re-queue if not cancelled */ + if (task->state == SOF_TASK_STATE_RUNNING) + task->state = SOF_TASK_STATE_QUEUED; + + } + } +} + +/* schedule new LL task */ +static int schedule_ll_task(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + /* add task to list */ + list_item_prepend(&task->list, &sched_list); + task->state = SOF_TASK_STATE_QUEUED; + task->start = 0; + + return 0; +} + +static void ll_scheduler_free(void *data, uint32_t flags) +{ + free(data); +} + +/* TODO: scheduler free and cancel APIs can merge as part of Zephyr */ +static int schedule_ll_task_cancel(void *data, struct task *task) +{ + /* delete task */ + task->state = SOF_TASK_STATE_CANCEL; + list_item_del(&task->list); + + return 0; +} + +/* TODO: scheduler free and cancel APIs can merge as part of Zephyr */ +static int schedule_ll_task_free(void *data, struct task *task) +{ + task->state = SOF_TASK_STATE_FREE; + list_item_del(&task->list); + + return 0; +} + +static struct scheduler_ops schedule_ll_ops = { + .schedule_task = schedule_ll_task, + .schedule_task_running = NULL, + .reschedule_task = NULL, + .schedule_task_cancel = schedule_ll_task_cancel, + .schedule_task_free = schedule_ll_task_free, + .scheduler_free = ll_scheduler_free, +}; + +int schedule_task_init_ll(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) +{ + return schedule_task_init(task, uid, SOF_SCHEDULE_LL_TIMER, 0, run, + data, core, flags); +} + +/* initialize scheduler */ +int scheduler_init_ll(struct ll_schedule_domain *domain) +{ + tr_info(&ll_tr, "ll_scheduler_init()"); + + list_init(&sched_list); + scheduler_init(SOF_SCHEDULE_LL_TIMER, &schedule_ll_ops, NULL); + + return 0; +} diff --git a/src/platform/library/schedule/schedule.c b/src/platform/library/schedule/schedule.c new file mode 100644 index 000000000000..b1dfcbb19445 --- /dev/null +++ b/src/platform/library/schedule/schedule.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +#include <sof/audio/component.h> +#include <rtos/task.h> +#include <stdint.h> +#include <rtos/wait.h> +#include <stdlib.h> + +static struct schedulers *testbench_schedulers_ptr; /* Initialized as NULL */ + +struct schedulers **arch_schedulers_get(void) +{ + return &testbench_schedulers_ptr; +} + +int schedule_task_init(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) +{ + if (type >= SOF_SCHEDULE_COUNT) + return -EINVAL; + + task->uid = uid; + task->type = type; + task->priority = priority; + task->core = core; + task->flags = flags; + task->state = SOF_TASK_STATE_INIT; + task->ops.run = run; + task->data = data; + + return 0; +} + +static void scheduler_register(struct schedule_data *scheduler) +{ + struct schedulers **sch = arch_schedulers_get(); + + if (!*sch) { + /* init schedulers list */ + *sch = calloc(1, sizeof(**sch)); + list_init(&(*sch)->list); + } + + list_item_append(&scheduler->list, &(*sch)->list); +} + +void scheduler_init(int type, const struct scheduler_ops *ops, void *data) +{ + struct schedule_data *sch; + + sch = calloc(1, sizeof(*sch)); + list_init(&sch->list); + sch->type = type; + sch->ops = ops; + sch->data = data; + + scheduler_register(sch); +} 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..29b0a6c81686 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/clk.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <ace/lib/clk.h> + +#define CLK_MAX_CPU_HZ CONFIG_XTENSA_CCOUNT_HZ + +#define CPU_WOVCRO_FREQ_IDX 0 + +#define CPU_IPLL_FREQ_IDX 1 + +#define CPU_LOWEST_FREQ_IDX CPU_WOVCRO_FREQ_IDX + +#define CPU_DEFAULT_IDX CPU_IPLL_FREQ_IDX + +#define NUM_CPU_FREQ 2 + +#define PRIMARY_CORE_BASE_CPS_USAGE 20000 +#define SECONDARY_CORE_BASE_CPS_USAGE 10000 + +#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/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 <ace/lib/mailbox.h> + +#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..276c61d17d58 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/memory.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +/* prioritize definitions in Zephyr SoC layer */ +#ifdef __ZEPHYR__ +#include <adsp_memory.h> +#endif + +#include <ace/lib/memory.h> +#include <mem_window.h> +#include <sof/lib/cpu.h> + +/* 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 CONFIG_SOF_ZEPHYR_HEAP_SIZE + +#if CONFIG_COLD_STORE_EXECUTE_DRAM && \ + (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD)) +#define __cold __section(".cold") +#define __cold_rodata __section(".coldrodata") +#endif + +#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/platform.h b/src/platform/lunarlake/include/platform/platform.h new file mode 100644 index 000000000000..7238b5abf70c --- /dev/null +++ b/src/platform/lunarlake/include/platform/platform.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + * Xiuli Pan <xiuli.pan@linux.intel.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#include <rtos/clk.h> + +/*! \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) + +#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 <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <stdint.h> + +/* 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..7ad664c94118 --- /dev/null +++ b/src/platform/lunarlake/lib/clk.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/common.h> +#include <rtos/clk.h> + +static const struct freq_table platform_cpu_freq[] = { + { CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000 }, + { CLK_MAX_CPU_HZ, CLK_MAX_CPU_HZ / 1000 }, +}; + +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/meteorlake/include/platform/lib/clk.h b/src/platform/meteorlake/include/platform/lib/clk.h new file mode 100644 index 000000000000..744ad4b82e79 --- /dev/null +++ b/src/platform/meteorlake/include/platform/lib/clk.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <ace/lib/clk.h> + +#define CLK_MAX_CPU_HZ CONFIG_XTENSA_CCOUNT_HZ + +#define CPU_WOVCRO_FREQ_IDX 0 + +#define CPU_IPLL_FREQ_IDX 1 + +#define CPU_LOWEST_FREQ_IDX CPU_WOVCRO_FREQ_IDX + +#define CPU_DEFAULT_IDX CPU_IPLL_FREQ_IDX + +#define NUM_CPU_FREQ 2 + +#define PRIMARY_CORE_BASE_CPS_USAGE 20000 +#define SECONDARY_CORE_BASE_CPS_USAGE 10000 + +#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/meteorlake/include/platform/lib/mailbox.h b/src/platform/meteorlake/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..3b7f218ad563 --- /dev/null +++ b/src/platform/meteorlake/include/platform/lib/mailbox.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <ace/lib/mailbox.h> + +#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/meteorlake/include/platform/lib/memory.h b/src/platform/meteorlake/include/platform/lib/memory.h new file mode 100644 index 000000000000..cd279b603c64 --- /dev/null +++ b/src/platform/meteorlake/include/platform/lib/memory.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +/* prioritize definitions in Zephyr SoC layer */ +#ifdef __ZEPHYR__ +#include <adsp_memory.h> +#endif + +#include <ace/lib/memory.h> +#include <mem_window.h> +#include <sof/lib/cpu.h> + +/* 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 CONFIG_SOF_ZEPHYR_HEAP_SIZE + +#if CONFIG_COLD_STORE_EXECUTE_DRAM && \ + (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD)) +#define __cold __section(".cold") +#define __cold_rodata __section(".coldrodata") +#endif + +#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/meteorlake/include/platform/platform.h b/src/platform/meteorlake/include/platform/platform.h new file mode 100644 index 000000000000..8cf0cc79a13a --- /dev/null +++ b/src/platform/meteorlake/include/platform/platform.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + * Xiuli Pan <xiuli.pan@linux.intel.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#include <rtos/clk.h> + +/*! \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) + +#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/meteorlake/include/platform/trace/trace.h b/src/platform/meteorlake/include/platform/trace/trace.h new file mode 100644 index 000000000000..b69592196cdb --- /dev/null +++ b/src/platform/meteorlake/include/platform/trace/trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <stdint.h> + +/* 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/meteorlake/lib/clk.c b/src/platform/meteorlake/lib/clk.c new file mode 100644 index 000000000000..20221b89d790 --- /dev/null +++ b/src/platform/meteorlake/lib/clk.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/common.h> +#include <rtos/clk.h> + +static const struct freq_table platform_cpu_freq[] = { + { CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000 }, + { CLK_MAX_CPU_HZ, CLK_MAX_CPU_HZ / 1000 }, +}; + +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/mt8186/CMakeLists.txt b/src/platform/mt8186/CMakeLists.txt new file mode 100644 index 000000000000..1b9e043186fe --- /dev/null +++ b/src/platform/mt8186/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) + +add_local_sources(sof platform.c afe-platform.c) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8186/include/arch) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8186/include/platform) diff --git a/src/platform/mt8186/afe-platform.c b/src/platform/mt8186/afe-platform.c new file mode 100644 index 000000000000..e91a6a01367f --- /dev/null +++ b/src/platform/mt8186/afe-platform.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Chunxu Li <chunxu.li@mediatek.com> + */ + +#include <sof/common.h> +#include <errno.h> +#include <sof/drivers/afe-drv.h> +#include <mt8186-afe-regs.h> +#include <mt8186-afe-common.h> + +/* + * AFE: Audio Front-End + * + * frontend (memif): + * memory interface + * UL (uplink for capture) + * DL (downlink for playback) + * backend: + * TDM In + * TMD Out + * DMIC + * GASRC + * I2S Out + * I2S In + * etc. + * interconn: + * inter-connection, + * connect frontends and backends as DSP path + */ + +static const struct mtk_base_memif_data memif_data[MT8186_MEMIF_NUM] = { + [MT8186_MEMIF_DL1] = { + .name = "DL1", + .id = MT8186_MEMIF_DL1, + .reg_ofs_base = AFE_DL1_BASE, + .reg_ofs_cur = AFE_DL1_CUR, + .reg_ofs_end = AFE_DL1_END, + .reg_ofs_base_msb = AFE_DL1_BASE_MSB, + .reg_ofs_cur_msb = AFE_DL1_CUR_MSB, + .reg_ofs_end_msb = AFE_DL1_END_MSB, + .fs_reg = AFE_DL1_CON0, + .fs_shift = DL1_MODE_SFT, + .fs_maskbit = DL1_MODE_MASK, + .mono_reg = AFE_DL1_CON0, + .mono_shift = DL1_MONO_SFT, + .enable_reg = AFE_DAC_CON0, + .enable_shift = DL1_ON_SFT, + .hd_reg = AFE_DL1_CON0, + .hd_shift = DL1_HD_MODE_SFT, + .hd_align_reg = AFE_DL1_CON0, + .hd_align_mshift = DL1_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .ch_num_reg = -1, + .ch_num_shift = -1, + .ch_num_maskbit = -1, + .msb_reg = -1, + .msb_shift = -1, + .msb2_reg = -1, + .msb2_shift = -1, + .pbuf_reg = AFE_DL1_CON0, + .pbuf_mask = DL1_PBUF_SIZE_MASK, + .pbuf_shift = DL1_PBUF_SIZE_SFT, + .minlen_reg = AFE_DL1_CON0, + .minlen_mask = DL1_MINLEN_MASK, + .minlen_shift = DL1_MINLEN_SFT, + }, + [MT8186_MEMIF_DL2] = { + .name = "DL2", + .id = MT8186_MEMIF_DL2, + .reg_ofs_base = AFE_DL2_BASE, + .reg_ofs_cur = AFE_DL2_CUR, + .reg_ofs_end = AFE_DL2_END, + .reg_ofs_base_msb = AFE_DL2_BASE_MSB, + .reg_ofs_cur_msb = AFE_DL2_CUR_MSB, + .reg_ofs_end_msb = AFE_DL2_END_MSB, + .fs_reg = AFE_DL2_CON0, + .fs_shift = DL2_MODE_SFT, + .fs_maskbit = DL2_MODE_MASK, + .mono_reg = AFE_DL2_CON0, + .mono_shift = DL2_MONO_SFT, + .enable_reg = AFE_DAC_CON0, + .enable_shift = DL2_ON_SFT, + .hd_reg = AFE_DL2_CON0, + .hd_shift = DL2_HD_MODE_SFT, + .hd_align_reg = AFE_DL2_CON0, + .hd_align_mshift = DL2_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .ch_num_reg = -1, + .ch_num_shift = -1, + .ch_num_maskbit = -1, + .msb_reg = -1, + .msb_shift = -1, + .msb2_reg = -1, + .msb2_shift = -1, + .pbuf_reg = AFE_DL2_CON0, + .pbuf_mask = DL2_PBUF_SIZE_MASK, + .pbuf_shift = DL2_PBUF_SIZE_SFT, + .minlen_reg = AFE_DL2_CON0, + .minlen_mask = DL2_MINLEN_MASK, + .minlen_shift = DL2_MINLEN_SFT, + }, + [MT8186_MEMIF_UL1] = { + .name = "UL1", + .id = MT8186_MEMIF_UL1, + .reg_ofs_base = AFE_VUL12_BASE, + .reg_ofs_cur = AFE_VUL12_CUR, + .reg_ofs_end = AFE_VUL12_END, + .reg_ofs_base_msb = AFE_VUL12_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL12_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL12_END_MSB, + .fs_reg = AFE_VUL12_CON0, + .fs_shift = VUL12_MODE_SFT, + .fs_maskbit = VUL12_MODE_MASK, + .mono_reg = AFE_VUL12_CON0, + .mono_shift = VUL12_MONO_SFT, + .quad_ch_reg = AFE_VUL12_CON0, + .quad_ch_mask = VUL12_4CH_EN_MASK, + .quad_ch_shift = VUL12_4CH_EN_SFT, + .enable_reg = AFE_DAC_CON0, + .enable_shift = VUL12_ON_SFT, + .hd_reg = AFE_VUL12_CON0, + .hd_shift = VUL12_HD_MODE_SFT, + .hd_align_reg = AFE_VUL12_CON0, + .hd_align_mshift = VUL12_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .ch_num_reg = -1, + .ch_num_shift = -1, + .ch_num_maskbit = -1, + .msb_reg = -1, + .msb_shift = -1, + .msb2_reg = -1, + .msb2_shift = -1, + }, + [MT8186_MEMIF_UL2] = { + .name = "UL2", + .id = MT8186_MEMIF_UL2, + .reg_ofs_base = AFE_AWB_BASE, + .reg_ofs_cur = AFE_AWB_CUR, + .reg_ofs_end = AFE_AWB_END, + .reg_ofs_base_msb = AFE_AWB_BASE_MSB, + .reg_ofs_cur_msb = AFE_AWB_CUR_MSB, + .reg_ofs_end_msb = AFE_AWB_END_MSB, + .fs_reg = AFE_AWB_CON0, + .fs_shift = AWB_MODE_SFT, + .fs_maskbit = AWB_MODE_MASK, + .mono_reg = AFE_AWB_CON0, + .mono_shift = AWB_MONO_SFT, + .enable_reg = AFE_DAC_CON0, + .enable_shift = AWB_ON_SFT, + .hd_reg = AFE_AWB_CON0, + .hd_shift = AWB_HD_MODE_SFT, + .hd_align_reg = AFE_AWB_CON0, + .hd_align_mshift = AWB_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .ch_num_reg = -1, + .ch_num_shift = -1, + .ch_num_maskbit = -1, + .msb_reg = -1, + .msb_shift = -1, + .msb2_reg = -1, + .msb2_shift = -1, + } +}; + +struct mt8186_afe_rate { + unsigned int rate; + unsigned int reg_value; +}; + +enum { + MTK_AFE_RATE_8K = 0, + MTK_AFE_RATE_11K = 1, + MTK_AFE_RATE_12K = 2, + MTK_AFE_RATE_384K = 3, + MTK_AFE_RATE_16K = 4, + MTK_AFE_RATE_22K = 5, + MTK_AFE_RATE_24K = 6, + MTK_AFE_RATE_352K = 7, + MTK_AFE_RATE_32K = 8, + MTK_AFE_RATE_44K = 9, + MTK_AFE_RATE_48K = 10, + MTK_AFE_RATE_88K = 11, + MTK_AFE_RATE_96K = 12, + MTK_AFE_RATE_176K = 13, + MTK_AFE_RATE_192K = 14, + MTK_AFE_RATE_260K = 15, +}; + +static const struct mt8186_afe_rate mt8186_afe_rates[] = { + { + .rate = 8000, + .reg_value = MTK_AFE_RATE_8K, + }, + { + .rate = 12000, + .reg_value = MTK_AFE_RATE_12K, + }, + { + .rate = 16000, + .reg_value = MTK_AFE_RATE_16K, + }, + { + .rate = 24000, + .reg_value = MTK_AFE_RATE_24K, + }, + { + .rate = 32000, + .reg_value = MTK_AFE_RATE_32K, + }, + { + .rate = 48000, + .reg_value = MTK_AFE_RATE_48K, + }, + { + .rate = 96000, + .reg_value = MTK_AFE_RATE_96K, + }, + { + .rate = 192000, + .reg_value = MTK_AFE_RATE_192K, + }, + { + .rate = 384000, + .reg_value = MTK_AFE_RATE_384K, + }, + { + .rate = 11025, + .reg_value = MTK_AFE_RATE_11K, + }, + { + .rate = 22050, + .reg_value = MTK_AFE_RATE_22K, + }, + { + .rate = 44100, + .reg_value = MTK_AFE_RATE_44K, + }, + { + .rate = 88200, + .reg_value = MTK_AFE_RATE_88K, + }, + { + .rate = 176400, + .reg_value = MTK_AFE_RATE_176K, + }, + { + .rate = 352800, + .reg_value = MTK_AFE_RATE_352K, + }, +}; + +static unsigned int mt8186_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8186_afe_rates); i++) + if (mt8186_afe_rates[i].rate == rate) + return mt8186_afe_rates[i].reg_value; + + return -EINVAL; +} + +static unsigned int mt8186_afe_fs(unsigned int rate, int aud_blk) +{ + return mt8186_afe_fs_timing(rate); +} + +static unsigned int mt8186_afe2adsp_addr(unsigned int addr) +{ + /*TODO : Need apply the address remap */ + return addr; +} + +static unsigned int mt8186_adsp2afe_addr(unsigned int addr) +{ + /* TODO : Need apply the address remap */ + return addr; +} + +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = AFE_BASE_ADDR, + .memif_datas = memif_data, + .memif_size = MT8186_MEMIF_NUM, + .memif_dl_num = MT8186_MEMIF_DL_NUM, + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = MT8186_DAI_NUM, + .afe2adsp_addr = mt8186_afe2adsp_addr, + .adsp2afe_addr = mt8186_adsp2afe_addr, + .afe_fs = mt8186_afe_fs, + .irq_fs = mt8186_afe_fs_timing, +}; diff --git a/src/platform/mt8186/include/arch/xtensa/config/core-isa.h b/src/platform/mt8186/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..79bee81a1ff1 --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,805 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 Tensilica 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. */ + +#ifndef XTENSA_CORE_CONFIGURATION_H_ +#define XTENSA_CORE_CONFIGURATION_H_ + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 16 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 1 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 1 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 1 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 1 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 1 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_DP_VFPU 0 /* Double-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_LDPC 0 /* LDPC option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6, Q7 or Q8 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_DP_VFPU 0 /* dp_vfpu option on Vision Q7/Q8 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1405000 /* sw version of this header */ +#define XCHAL_SW_VERSION_MAJOR 14000 /* major ver# of sw */ +#define XCHAL_SW_VERSION_MINOR 5 /* minor ver# of sw */ +#define XCHAL_SW_VERSION_MICRO 0 /* micro ver# of sw */ +#define XCHAL_SW_MINOR_VERSION 1405000 /* with zeroed micro */ +#define XCHAL_SW_MICRO_VERSION 1405000 + +#define XCHAL_CORE_ID "hifi5_7stg_I64D128" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000904D8 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC003B286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x294904D8 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.5" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 5 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO 0 /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281050 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_5 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 5 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281050 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 5 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO 0 /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281050 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +/* Config is enabled for secure operation: */ +#define XCHAL_HAVE_SECURE 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 65536 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 16 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 8 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 1 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ +#define XCHAL_HAVE_L2_CACHE 0 +#define XCHAL_NUM_CORES_IN_CLUSTER 0 + +/* PRID_ID macros are for internal use only ... subject to removal */ +#define PRID_ID_SHIFT 0 +#define PRID_ID_BITS 4 +#define PRID_ID_MASK 0x0000000F + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 7 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x3FFF0000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x3FFF0000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 32768 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x3FFF8000 /* virtual address */ +#define XCHAL_INSTRAM1_PADDR 0x3FFF8000 /* physical address */ +#define XCHAL_INSTRAM1_SIZE 4096 /* size in bytes */ +#define XCHAL_INSTRAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM1 1 +#define XCHAL_INSTRAM1_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FFE8000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x3FFE8000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 32768 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + IDMA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_IDMA 0 + + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 26 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 5 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x040000FF +#define XCHAL_INTLEVEL2_MASK 0xA800FF00 +#define XCHAL_INTLEVEL3_MASK 0x518F0000 +#define XCHAL_INTLEVEL4_MASK 0x00700000 +#define XCHAL_INTLEVEL5_MASK 0x00000000 +#define XCHAL_INTLEVEL6_MASK 0x02000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x040000FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0xAC00FFFF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0xFD8FFFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0xFDFFFFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFDFFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 2 +#define XCHAL_INT10_LEVEL 2 +#define XCHAL_INT11_LEVEL 2 +#define XCHAL_INT12_LEVEL 2 +#define XCHAL_INT13_LEVEL 2 +#define XCHAL_INT14_LEVEL 2 +#define XCHAL_INT15_LEVEL 2 +#define XCHAL_INT16_LEVEL 3 +#define XCHAL_INT17_LEVEL 3 +#define XCHAL_INT18_LEVEL 3 +#define XCHAL_INT19_LEVEL 3 +#define XCHAL_INT20_LEVEL 4 +#define XCHAL_INT21_LEVEL 4 +#define XCHAL_INT22_LEVEL 4 +#define XCHAL_INT23_LEVEL 3 +#define XCHAL_INT24_LEVEL 3 +#define XCHAL_INT25_LEVEL 6 +#define XCHAL_INT26_LEVEL 1 +#define XCHAL_INT27_LEVEL 2 +#define XCHAL_INT28_LEVEL 3 +#define XCHAL_INT29_LEVEL 2 +#define XCHAL_INT30_LEVEL 3 +#define XCHAL_INT31_LEVEL 2 +#define XCHAL_DEBUGLEVEL 5 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 6 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_SOFTWARE + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x007FFFFF +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x01800000 +#define XCHAL_INTTYPE_MASK_NMI 0x02000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x80000000 +#define XCHAL_INTTYPE_MASK_TIMER 0x1C000000 +#define XCHAL_INTTYPE_MASK_ETIE 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x40000000 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x20000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_WWDT 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 26 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 27 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 28 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 25 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 30 +#define XCHAL_PROFILING_INTERRUPT 29 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL6_NUM 25 +/* (There are many interrupts each at level(s) 1, 2, 3, 4.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT9_NUM 9 /* (intlevel 2) */ +#define XCHAL_EXTINT10_NUM 10 /* (intlevel 2) */ +#define XCHAL_EXTINT11_NUM 11 /* (intlevel 2) */ +#define XCHAL_EXTINT12_NUM 12 /* (intlevel 2) */ +#define XCHAL_EXTINT13_NUM 13 /* (intlevel 2) */ +#define XCHAL_EXTINT14_NUM 14 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 15 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 16 /* (intlevel 3) */ +#define XCHAL_EXTINT17_NUM 17 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 18 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 19 /* (intlevel 3) */ +#define XCHAL_EXTINT20_NUM 20 /* (intlevel 4) */ +#define XCHAL_EXTINT21_NUM 21 /* (intlevel 4) */ +#define XCHAL_EXTINT22_NUM 22 /* (intlevel 4) */ +#define XCHAL_EXTINT23_NUM 23 /* (intlevel 3) */ +#define XCHAL_EXTINT24_NUM 24 /* (intlevel 3) */ +#define XCHAL_EXTINT25_NUM 25 /* (intlevel 6) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT6_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT7_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 8 /* (intlevel 2) */ +#define XCHAL_INT9_EXTNUM 9 /* (intlevel 2) */ +#define XCHAL_INT10_EXTNUM 10 /* (intlevel 2) */ +#define XCHAL_INT11_EXTNUM 11 /* (intlevel 2) */ +#define XCHAL_INT12_EXTNUM 12 /* (intlevel 2) */ +#define XCHAL_INT13_EXTNUM 13 /* (intlevel 2) */ +#define XCHAL_INT14_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT15_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT16_EXTNUM 16 /* (intlevel 3) */ +#define XCHAL_INT17_EXTNUM 17 /* (intlevel 3) */ +#define XCHAL_INT18_EXTNUM 18 /* (intlevel 3) */ +#define XCHAL_INT19_EXTNUM 19 /* (intlevel 3) */ +#define XCHAL_INT20_EXTNUM 20 /* (intlevel 4) */ +#define XCHAL_INT21_EXTNUM 21 /* (intlevel 4) */ +#define XCHAL_INT22_EXTNUM 22 /* (intlevel 4) */ +#define XCHAL_INT23_EXTNUM 23 /* (intlevel 3) */ +#define XCHAL_INT24_EXTNUM 24 /* (intlevel 3) */ +#define XCHAL_INT25_EXTNUM 25 /* (intlevel 6) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x4e100400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x4e100400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 /* UNUSED */ + +#define XCHAL_RESET_VECTOR0_VADDR 0x4e100000 +#define XCHAL_RESET_VECTOR0_PADDR 0x4e100000 +#define XCHAL_RESET_VECTOR1_VADDR 0x4e100800 +#define XCHAL_RESET_VECTOR1_PADDR 0x4e100800 +#define XCHAL_RESET_VECTOR_VADDR XCHAL_RESET_VECTOR1_VADDR +#define XCHAL_RESET_VECTOR_PADDR XCHAL_RESET_VECTOR1_PADDR +#define XCHAL_USER_VECOFS 0x00000250 +#define XCHAL_USER_VECTOR_VADDR 0x4e100650 +#define XCHAL_USER_VECTOR_PADDR 0x4e100650 +#define XCHAL_KERNEL_VECOFS 0x00000230 +#define XCHAL_KERNEL_VECTOR_VADDR 0x4e100630 +#define XCHAL_KERNEL_VECTOR_PADDR 0x4e100630 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000270 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x4e100670 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x4e100670 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x4e100400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x4e100400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x4e100580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x4e100580 +#define XCHAL_INTLEVEL3_VECOFS 0x000001A4 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x4e1005A4 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x4e1005A4 +#define XCHAL_INTLEVEL4_VECOFS 0x000001C8 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x4e1005C8 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x4e1005C8 +#define XCHAL_INTLEVEL5_VECOFS 0x000001EC +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x4e1005EC +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x4e1005EC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL5_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL5_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL5_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000210 +#define XCHAL_NMI_VECTOR_VADDR 0x4e100610 +#define XCHAL_NMI_VECTOR_PADDR 0x4e100610 +#define XCHAL_INTLEVEL6_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL6_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL6_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 4096 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 64 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 8 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 0 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 1 +#define XCHAL_MPU_ENTRIES 32 +#define XCHAL_MPU_LOCK 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 2 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0xFF /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 12 +#define XCHAL_MPU_ALIGN 4096 + +/*----------------------------------------------------------------------- + CSR Parity +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_CSR_PARITY 0 + + +/*---------------------------------------------------------------------- + FLEX-LOCK +------------------------------------------------------------------------*/ + +#define XCHAL_HAVE_FXLK 0 + +/*---------------------------------------------------------------------- + WWDT (Windowed Watchdog Timer) +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_WWDT 0 +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* XTENSA_CORE_CONFIGURATION_H_ */ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/core-matmap.h b/src/platform/mt8186/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..8a0056ca9c21 --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,106 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ + +/* Mappings for legacy constants where appropriate */ + +#define XCHAL_CA_WRITEBACK (XTHAL_MEM_WRITEBACK | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITEBACK_NOALLOC (XTHAL_MEM_WRITEBACK_NOALLOC| XTHAL_AR_RWXrwx ) + +#define XCHAL_CA_WRITETHRU (XTHAL_MEM_WRITETHRU | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_ILLEGAL (XTHAL_AR_NONE | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASSBUF (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE |\ + XTHAL_MEM_BUFFERABLE) +#define XCHAL_CA_BYPASS_RX (XTHAL_AR_RX | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_RW (XTHAL_AR_RW | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_R (XTHAL_AR_R | XTHAL_MEM_DEVICE) +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 + +#define XCHAL_CA_R (XTHAL_AR_R) +#define XCHAL_CA_RX (XTHAL_AR_RX) +#define XCHAL_CA_RW (XTHAL_AR_RW) +#define XCHAL_CA_RWX (XTHAL_AR_RWX) + + +/* + * Contents of MPU background map. + * NOTE: caller must define the XCHAL_MPU_BGMAP() macro (not defined here + * but specified below) before expanding the XCHAL_MPU_BACKGROUND_MAP(s) macro. + * + * XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) + * + * s = passed from XCHAL_MPU_BACKGROUND_MAP(s), eg. to select how to expand + * vaddr_start = first byte of region (always 0 for first entry) + * vaddr_end = last byte of region (always 0xFFFFFFFF for last entry) + * rights = access rights + * memtype = memory type + * x = reserved for future use (0 until then) + */ +/* parasoft-begin-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ +#define XCHAL_MPU_BACKGROUND_MAP(s) \ + XCHAL_MPU_BGMAP(s, 0x00000000, 0x7fffffff, 7, 6, 0) \ + XCHAL_MPU_BGMAP(s, 0x80000000, 0xffffffff, 7, 6, 0) \ +/* parasoft-end-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ + + /* end */ + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/defs.h b/src/platform/mt8186/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..be3cf59f6756 --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/mt8186/include/arch/xtensa/config/key.h b/src/platform/mt8186/include/arch/xtensa/config/key.h new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/key.h @@ -0,0 +1 @@ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/secure.h b/src/platform/mt8186/include/arch/xtensa/config/secure.h new file mode 100644 index 000000000000..561b2133c98e --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/secure.h @@ -0,0 +1,48 @@ + +/* Secure Mode defines. */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 2020 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. + */ + +#ifndef XTENSA_SECURE_H +#define XTENSA_SECURE_H + + +/* SRAM */ +#define XCHAL_HAVE_SECURE_SRAM 0 + +/* INSTRAM0 */ +#define XCHAL_HAVE_SECURE_INSTRAM0 0 + +/* INSTRAM1 */ +#define XCHAL_HAVE_SECURE_INSTRAM1 0 + +/* DATARAM0 */ +#define XCHAL_HAVE_SECURE_DATARAM0 0 + +/* Array of all secure regions' start/size */ +#define XCHAL_SECURE_MEM_LIST \ +{ \ +} + +#endif /* XTENSA_SECURE_H */ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/specreg.h b/src/platform/mt8186/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..7e4ed373ecc1 --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/specreg.h @@ -0,0 +1,110 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Homewood/ib.5/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define MPUENB 90 +#define ERACCESS 95 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEADRDIS 98 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/system.h b/src/platform/mt8186/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..e92cc4ad0433 --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/system.h @@ -0,0 +1,254 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x40000000 +#define XSHAL_RAM_PADDR 0x40000000 +#define XSHAL_RAM_VSIZE 0x80000000 +#define XSHAL_RAM_PSIZE 0x80000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x40000AE0 +#define XSHAL_RAM_AVAIL_VSIZE 0x7FFFF520 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0xC0000000 +#define XSHAL_RAM_BYPASS_PADDR 0xC0000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xdeed2000 +#define XSHAL_STL_INFO_LOCATION 0xfffffffc + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22444442 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22111112 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22111112 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44444F /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11111F /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11111F /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244444F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211111F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211111F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xF242444F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xF212111F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xF212111F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xF222222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00001010 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 1 +#define XSHAL_RESET_VECTOR_VADDR 0x40000800 +#define XSHAL_RESET_VECTOR_PADDR 0x40000800 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x0000001C +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL5_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL5_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x0000001C +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/tie-asm.h b/src/platform/mt8186/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..1dd05a4d23b9 --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,362 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rsr.br \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 // boolean option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed16, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed24, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed31, \ptr, .Lxchal_ofs_+48 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+56 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+57 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+58 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+59 + addi.a \ptr, \ptr, 64 + ae_salign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_salign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_salign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_salign128.i u3, \ptr, .Lxchal_ofs_+48 + addi.a \ptr, \ptr, -320 + ae_movdrzbvc aed0 // ureg AE_ZBIASV8C + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 + rur.ae_ovf_sar \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_bithead \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_ts_fts_bu_bp \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cw_sd_no \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.ae_cbegin0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.ae_cend0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+36 + rur.ae_cbegin1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+40 + rur.ae_cend1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+44 + rur.ae_cbegin2 \at1 // ureg 250 + s32i \at1, \ptr, .Lxchal_ofs_+48 + rur.ae_cend2 \at1 // ureg 251 + s32i \at1, \ptr, .Lxchal_ofs_+52 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg AE_ZBIASV8C + ae_movzbvcdr aed0 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ovf_sar \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_bithead \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_ts_fts_bu_bp \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cw_sd_no \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.ae_cbegin0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.ae_cend0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+40 + wur.ae_cbegin1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+44 + wur.ae_cend1 \at1 // ureg 249 + l32i \at1, \ptr, .Lxchal_ofs_+48 + wur.ae_cbegin2 \at1 // ureg 250 + l32i \at1, \ptr, .Lxchal_ofs_+52 + wur.ae_cend2 \at1 // ureg 251 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed16, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed24, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed31, \ptr, .Lxchal_ofs_+48 + addi.a \ptr, \ptr, 56 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi.a \ptr, \ptr, 8 + ae_lalign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_lalign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_lalign128.i u3, \ptr, .Lxchal_ofs_+48 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 320 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 64 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/mt8186/include/arch/xtensa/config/tie.h b/src/platform/mt8186/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..8ff7910d17ab --- /dev/null +++ b/src/platform/mt8186/include/arch/xtensa/config/tie.h @@ -0,0 +1,210 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 384 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 16 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 8 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 400 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 16 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 2 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 52 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ae_zbiasv8c,16, 8, 8,0x1029, ur,-1 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x102A, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin2, 4, 4, 4,0x03FA, ur,250, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend2, 4, 4, 4,0x03FB, ur,251, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed16, 8, 8, 8,0x1010, aed,16 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed17, 8, 8, 8,0x1011, aed,17 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed18, 8, 8, 8,0x1012, aed,18 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed19, 8, 8, 8,0x1013, aed,19 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed20, 8, 8, 8,0x1014, aed,20 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed21, 8, 8, 8,0x1015, aed,21 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed22, 8, 8, 8,0x1016, aed,22 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed23, 8, 8, 8,0x1017, aed,23 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed24, 8, 8, 8,0x1018, aed,24 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed25, 8, 8, 8,0x1019, aed,25 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed26, 8, 8, 8,0x101A, aed,26 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed27, 8, 8, 8,0x101B, aed,27 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed28, 8, 8, 8,0x101C, aed,28 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed29, 8, 8, 8,0x101D, aed,29 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed30, 8, 8, 8,0x101E, aed,30 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed31, 8, 8, 8,0x101F, aed,31 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1024, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1025, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1026, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1027, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0,16,16,16,0x1020, u,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1,16,16,16,0x1021, u,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2,16,16,16,0x1022, u,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3,16,16,16,0x1023, u,3 ,128,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/mt8186/include/platform/drivers/idc.h b/src/platform/mt8186/include/platform/drivers/idc.h new file mode 100644 index 000000000000..e77600345b55 --- /dev/null +++ b/src/platform/mt8186/include/platform/drivers/idc.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +static inline int idc_init(void) +{ + return 0; +} + +#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/mt8186/include/platform/drivers/interrupt.h b/src/platform/mt8186/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..7be0f42c1f16 --- /dev/null +++ b/src/platform/mt8186/include/platform/drivers/interrupt.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Zhengnan Chen <zhengnan.chen@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <stdint.h> +#include <platform/drivers/mt_reg_base.h> + +#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM +#define PLATFORM_IRQ_CHILDREN 32 + +/* MTK_ADSP_IRQ_MASK */ +#define MTK_DSP_OUT_IRQ_MASK 0x3FF + +/* interrupt table */ +#define MTK_DSP_IRQ_UART 0 +#define MTK_DSP_IRQ_SPM 1 +#define MTK_DSP_IRQ_MAILBOX 2 +#define MTK_DSP_IRQ_DSP_TIMER0 3 +#define MTK_DSP_IRQ_DSP_TIMER1 4 +#define MTK_DSP_IRQ_CORE0 5 +#define MTK_DSP_IRQ_RSV0 6 +#define MTK_DSP_IRQ_RSV1 7 +#define MTK_DSP_IRQ_CONNSYS1 8 +#define MTK_DSP_IRQ_CONNSYS2 9 +#define MTK_DSP_IRQ_CONNSYS3 10 +#define MTK_DSP_IRQ_NNA0 11 +#define MTK_DSP_IRQ_NNA1 12 +#define MTK_DSP_IRQ_OSTIMER64 13 +#define MTK_DSP_IRQ_DMA 14 +#define MTK_DSP_IRQ_WDT 16 +#define MTK_DSP_IRQ_MDLA 17 +#define MTK_DSP_IRQ_OSTIMER32 18 +#define MTK_DSP_IRQ_NNA2 19 +#define MTK_DSP_IRQ_SCP 20 +#define MTK_DSP_IRQ_LATENCT_MON 21 +#define MTK_DSP_IRQ_BUS_TRACKER 22 +#define MTK_DSP_IRQ_WAKEUP_SRC 23 +#define MTK_DSP_IRQ_INFRA_HANG 24 +#define MTK_DSP_IRQ_NMI 25 +#define MTK_DSP_IRQ_TIMER0 26 +#define MTK_DSP_IRQ_TIMER1 27 +#define MTK_DSP_IRQ_TIMER2 28 +#define MTK_DSP_IRQ_PMU 29 +#define MTK_DSP_IRQ_WERR 30 +#define MTK_DSP_IRQ_SW 31 + +#define MTK_MAX_IRQ_NUM 32 + +/* grouped mailbox IRQ */ +#define MTK_DSP_IRQ_MBOX0 32 +#define MTK_DSP_IRQ_MBOX1 33 +#define MTK_DSP_IRQ_MBOX2 34 +#define MTK_DSP_IRQ_MBOX3 35 +#define MTK_DSP_IRQ_MBOX4 36 + +#define MTK_DSP_MBOX_MASK 0xF + +int mtk_irq_group_id(uint32_t irq); + +#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/mt8186/include/platform/drivers/mt_reg_base.h b/src/platform/mt8186/include/platform/drivers/mt_reg_base.h new file mode 100644 index 000000000000..1de4e6ad2ca1 --- /dev/null +++ b/src/platform/mt8186/include/platform/drivers/mt_reg_base.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifndef MT_REG_BASE_H +#define MT_REG_BASE_H + +#define MTK_REG_TOPCKGEN_BASE 0x10000000 +#define MTK_REG_TOPCKGEN_SIZE 0x1000 +#define MTK_REG_APMIXDSYS_BASE 0x1000C000 +#define MTK_REG_APMIXDSYS_SIZE 0x1000 + +#define MTK_DSP_REG_BASE 0x10680000 /* DSP Register base */ +#define MTK_DSP_CFGREG_BASE 0x10680000 +#define MTK_DSP_CFGREG_SIZE 0x1000 +#define MTK_DSP_CKCTRL_BASE 0x10681000 +#define MTK_DSP_CKCTRL_SIZE 0x1000 +#define MTK_DSP_OS_TIMER_BASE 0x10683000 +#define MTK_DSP_OS_TIMER_SIZE 0x1000 +#define MTK_DSP_UART0_BASE 0x10684000 +#define MTK_DSP_UART0_SIZE 0x1000 +#define MTK_DSP_TIMER_BASE 0x1068E000 +#define MTK_DSP_TIMER_SIZE 0x1000 +#define MTK_DSP_BUS_BASE 0x1068F000 +#define MTK_DSP_BUS_SIZE 0x1000 +#define MTK_DSP_AFE_BASE 0x11210000 +#define MTK_DSP_AFE_SIZE 0xF000 /* register 8k, compacted sram 52k */ + +#define MTK_ADSP_CFGREG_SW_RSTN (MTK_DSP_REG_BASE + 0x0000) +#define MTK_ADSP_HIFI_IO_CONFIG (MTK_DSP_REG_BASE + 0x000c) +#define MTK_ADSP_IRQ_STATUS (MTK_DSP_REG_BASE + 0x0010) +#define MTK_ADSP_SW_INT_SET (MTK_DSP_REG_BASE + 0x0018) +#define MTK_ADSP_SW_INT_CLR (MTK_DSP_REG_BASE + 0x001c) +#define MTK_ADSP_SW_INT_32A (MTK_DSP_REG_BASE + 0x0020) +#define MTK_ADSP_IRQ_MASK (MTK_DSP_REG_BASE + 0x0030) +#define MTK_ADSP_GENERAL_IRQ_SET (MTK_DSP_REG_BASE + 0x0034) +#define MTK_ADSP_GENERAL_IRQ_CLR (MTK_DSP_REG_BASE + 0x0038) +#define MTK_ADSP_DVFSRC_STATE (MTK_DSP_REG_BASE + 0x003c) +#define MTK_ADSP_DVFSRC_REQ (MTK_DSP_REG_BASE + 0x0040) +#define MTK_ADSP_DDREN_REQ_0 (MTK_DSP_REG_BASE + 0x0044) +#define MTK_ADSP_SPM_ACK (MTK_DSP_REG_BASE + 0x004c) +#define MTK_ADSP_IRQ_EN (MTK_DSP_REG_BASE + 0x0050) +#define MTK_ADSP_IRQ_POL_FIX (MTK_DSP_REG_BASE + 0x0054) +#define MTK_ADSP_SPM_WAKEUPSRC_CORE0 (MTK_DSP_REG_BASE + 0x005c) +#define MTK_ADSP_SEMAPHORE (MTK_DSP_REG_BASE + 0x0064) +#define MTK_ADSP_DBG_SEL (MTK_DSP_REG_BASE + 0x0074) +#define MTK_ADSP_DBG_INFO (MTK_DSP_REG_BASE + 0x0078) +#define MTK_ADSP_WDT_CON_C0 (MTK_DSP_REG_BASE + 0x007c) +#define MTK_ADSP_WDT_INIT_VALUE_C0 (MTK_DSP_REG_BASE + 0x0080) +#define MTK_ADSP_WDT_CNT_C0 (MTK_DSP_REG_BASE + 0x0084) +#define MTK_ADSP_WAKEUPSRC_MASK_C0 (MTK_DSP_REG_BASE + 0x00a0) +#define MTK_ADSP_WAKEUPSRC_IRQ_C0 (MTK_DSP_REG_BASE + 0x00a4) +#define MTK_ADSP2SPM_MBOX (MTK_DSP_REG_BASE + 0x00bc) +#define MTK_SPM2ADSP_MBOX (MTK_DSP_REG_BASE + 0x00c0) +#define MTK_GPR_RW_REG0 (MTK_DSP_REG_BASE + 0x0440) +#define MTK_GPR_RW_REG1 (MTK_DSP_REG_BASE + 0x0444) +#define MTK_GPR_RW_REG2 (MTK_DSP_REG_BASE + 0x0448) +#define MTK_GPR_RW_REG3 (MTK_DSP_REG_BASE + 0x044c) +#define MTK_GPR_RW_REG4 (MTK_DSP_REG_BASE + 0x0450) +#define MTK_GPR_RW_REG5 (MTK_DSP_REG_BASE + 0x0454) +#define MTK_GPR_RW_REG6 (MTK_DSP_REG_BASE + 0x0458) +#define MTK_GPR_RW_REG7 (MTK_DSP_REG_BASE + 0x045c) +#define MTK_GPR_RW_REG8 (MTK_DSP_REG_BASE + 0x0460) +#define MTK_GPR_RW_REG9 (MTK_DSP_REG_BASE + 0x0464) +#define MTK_GPR_RW_REG10 (MTK_DSP_REG_BASE + 0x0468) +#define MTK_GPR_RW_REG11 (MTK_DSP_REG_BASE + 0x046c) +#define MTK_GPR_RW_REG12 (MTK_DSP_REG_BASE + 0x0470) +#define MTK_GPR_RW_REG13 (MTK_DSP_REG_BASE + 0x0474) +#define MTK_GPR_RW_REG14 (MTK_DSP_REG_BASE + 0x0478) +#define MTK_GPR_RW_REG15 (MTK_DSP_REG_BASE + 0x047c) +#define MTK_GPR_RW_REG16 (MTK_DSP_REG_BASE + 0x0480) +#define MTK_GPR_RW_REG17 (MTK_DSP_REG_BASE + 0x0484) +#define MTK_GPR_RW_REG18 (MTK_DSP_REG_BASE + 0x0488) +#define MTK_GPR_RW_REG19 (MTK_DSP_REG_BASE + 0x048c) +#define MTK_GPR_RW_REG20 (MTK_DSP_REG_BASE + 0x0490) +#define MTK_GPR_RW_REG21 (MTK_DSP_REG_BASE + 0x0494) +#define MTK_GPR_RW_REG22 (MTK_DSP_REG_BASE + 0x0498) +#define MTK_GPR_RW_REG23 (MTK_DSP_REG_BASE + 0x049c) +#define MTK_GPR_RW_REG24 (MTK_DSP_REG_BASE + 0x04a0) +#define MTK_GPR_RW_REG25 (MTK_DSP_REG_BASE + 0x04a4) +#define MTK_GPR_RW_REG26 (MTK_DSP_REG_BASE + 0x04a8) +#define MTK_GPR_RW_REG27 (MTK_DSP_REG_BASE + 0x04ac) +#define MTK_GPR_RW_REG28 (MTK_DSP_REG_BASE + 0x04b0) /* use for tickless status */ +#define MTK_GPR_RW_REG29 (MTK_DSP_REG_BASE + 0x04b4) +#define MTK_ADSP_CLK_BUS_UPDATE (MTK_DSP_REG_BASE + 0x04c0) +#define MTK_ADSP_IRQ_OUT_MASK (MTK_DSP_REG_BASE + 0x0500) +#define MTK_MBOX_IRQ_IN (MTK_DSP_REG_BASE + 0xB070) + +#define MTK_ADSP_BUS_SRC (MTK_DSP_BUS_BASE + 0x140) + +#define MTK_ADSPPLL_CON0 (MTK_REG_APMIXDSYS_BASE + 0x304) +#define MTK_ADSPPLL_CON1 (MTK_REG_APMIXDSYS_BASE + 0x308) +#define MTK_ADSPPLL_CON2 (MTK_REG_APMIXDSYS_BASE + 0x30C) +#define MTK_ADSPPLL_CON3 (MTK_REG_APMIXDSYS_BASE + 0x310) + +#define MTK_CLK_MODE (MTK_REG_TOPCKGEN_BASE + 0x0) +#define MTK_CLK_CFG_UPDATE (MTK_REG_TOPCKGEN_BASE + 0x8) +#define MTK_CLK_CFG_11 (MTK_REG_TOPCKGEN_BASE + 0x0EC) +#define MTK_CLK_CFG_11_SET (MTK_REG_TOPCKGEN_BASE + 0x0F0) +#define MTK_CLK_CFG_11_CLR (MTK_REG_TOPCKGEN_BASE + 0x0F4) +#define MTK_CLK_CFG_15 (MTK_REG_TOPCKGEN_BASE + 0x180) +#define MTK_CLK_CFG_15_SET (MTK_REG_TOPCKGEN_BASE + 0x184) +#define MTK_CLK_CFG_15_CLR (MTK_REG_TOPCKGEN_BASE + 0x188) + +/* MBOX registers */ +#define MTK_ADSP_MBOX_REG_BASE(x) (0x10686000 + (0x1000 * (x))) +#define MTK_ADSP_MBOX_REG_SIZE (0x5000) +#define MTK_ADSP_MBOX_IN_CMD(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x100) +#define MTK_ADSP_MBOX_IN_CMD_CLR(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x108) +#define MTK_ADSP_MBOX_OUT_CMD(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x104) +#define MTK_ADSP_MBOX_OUT_CMD_CLR(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x10c) + +#endif /* MT_REG_BASE_H */ diff --git a/src/platform/mt8186/include/platform/drivers/timer.h b/src/platform/mt8186/include/platform/drivers/timer.h new file mode 100644 index 000000000000..f32777bd5cfa --- /dev/null +++ b/src/platform/mt8186/include/platform/drivers/timer.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifndef __PLATFORM_DRIVERS_TIMER_H__ +#define __PLATFORM_DRIVERS_TIMER_H__ + +#include <rtos/bit.h> +#include <platform/drivers/mt_reg_base.h> + +/*-------timer:ostimer0-------*/ +enum ostimer { + OSTIMER0 = 0, + OSTIMER1, + OSTIMER2, + OSTIMER3, + NR_TMRS +}; + +#define MTK_TIMER_CON(n) (MTK_DSP_OS_TIMER_BASE + 0x0 + 0x10 * (n)) +#define MTK_TIMER_RST_VAL(n) (MTK_DSP_OS_TIMER_BASE + 0x4 + 0x10 * (n)) +#define MTK_TIMER_CUR_VAL(n) (MTK_DSP_OS_TIMER_BASE + 0x8 + 0x10 * (n)) +#define MTK_TIMER_IRQ_ACK(n) (MTK_DSP_OS_TIMER_BASE + 0xC + 0x10 * (n)) + +#define MTK_TIMER_ENABLE_BIT BIT(0) +#define MTK_TIMER_IRQ_ENABLE BIT(0) +#define MTK_TIMER_IRQ_STA BIT(4) +#define MTK_TIMER_IRQ_CLEAR BIT(5) +#define MTK_TIMER_CLKSRC_BIT (BIT(4) | BIT(5)) + +#define MTK_TIMER_CLK_SRC_OFFSET 4 +#define MTK_TIMER_CLK_SRC_CLK_26M 0 +#define MTK_TIMER_CLK_SRC_BCLK BIT(4) +#define MTK_TIMER_CLK_SRC_PCLK BIT(5) + +/*-------platform_timer: 64 bit systimer-------*/ +#define MTK_OSTIMER_CON (MTK_DSP_OS_TIMER_BASE + 0x80) +#define MTK_OSTIMER_INIT_L (MTK_DSP_OS_TIMER_BASE + 0x84) +#define MTK_OSTIMER_INIT_H (MTK_DSP_OS_TIMER_BASE + 0x88) +#define MTK_OSTIMER_CUR_L (MTK_DSP_OS_TIMER_BASE + 0x8C) +#define MTK_OSTIMER_CUR_H (MTK_DSP_OS_TIMER_BASE + 0x90) +#define MTK_OSTIMER_TVAL (MTK_DSP_OS_TIMER_BASE + 0x94) +#define MTK_OSTIMER_IRQ_ACK (MTK_DSP_OS_TIMER_BASE + 0x98) + +#define MTK_OSTIMER_EN_BIT BIT(0) + +#endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/mt8186/include/platform/lib/clk.h b/src/platform/mt8186/include/platform/lib/clk.h new file mode 100644 index 000000000000..d48e83bd75b9 --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/clk.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <stdint.h> + +struct sof; + +#define CPU_DEFAULT_IDX 0 + +#define CLK_CPU(x) (x) +#define CLK_DEFAULT_CPU_HZ 26000000 +/* check vcore voltage before select higher frequency than 300M */ +#define CLK_MAX_CPU_HZ 300000000 +#define NUM_CLOCKS 1 +#define NUM_CPU_FREQ 3 + +/* MTK_ADSP_CLK_BUS_UPDATE */ +#define MTK_ADSP_CLK_BUS_UPDATE_BIT BIT(31) + +/* MTK_ADSP_BUS_SRC */ +#define MTK_ADSP_CLK_BUS_SRC_EMI 0 +#define MTK_ADSP_CLK_BUS_SRC_LOCAL 1 + +/* MTK_CLK_CFG_11 */ +#define MTK_CLK_CFG_ADSP_UPDATE BIT(16) +#define MTK_CLK_ADSP_OFFSET 24 +#define MTK_CLK_ADSP_MASK 0x7 +#define MTK_CLK_ADSP_26M 0 +#define MTK_CLK_ADSP_ULPOSC_D_10 1 /* 25M, Not used */ +#define MTK_CLK_ADSP_DSPPLL 2 +#define MTK_CLK_ADSP_DSPPLL_2 3 +#define MTK_CLK_ADSP_DSPPLL_4 4 +#define MTK_CLK_ADSP_DSPPLL_8 5 + +/* MTK_CLK_CFG_15 */ +#define MTK_CLK_CFG_ADSP_BUS_UPDATE BIT(31) +#define MTK_CLK_ADSP_BUS_OFFSET 17 +#define MTK_CLK_ADSP_BUS_MASK 0x7 +#define MTK_CLK_ADSP_BUS_26M 0 +#define MTK_CLK_ADSP_BUS_ULPOSC_D_2 1 +#define MTK_CLK_ADSP_BUS_MAINPPLL_D_5 2 +#define MTK_CLK_ADSP_BUS_MAINPPLL_D_2_D_2 3 +#define MTK_CLK_ADSP_BUS_MAINPPLL_D_3 4 +#define MTK_CLK_ADSP_BUS_RESERVED 5 +#define MTK_CLK_ADSP_BUS_UNIVPLL_D_3 6 + +#define MTK_PLL_BASE_EN BIT(0) +#define MTK_PLL_PWR_ON BIT(0) +#define MTK_PLL_ISO_EN BIT(1) + +#define MTK_PLL_DIV_RATIO_300M 0x831713B2 +#define MTK_PLL_DIV_RATIO_400M 0x831EC4ED + +/* List resource from low to high request */ +/* 0 is the lowest request */ +enum ADSP_HW_DSP_CLK { + ADSP_CLK_26M = 0, + ADSP_CLK_PLL_300M, + ADSP_CLK_PLL_400M, +}; + +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/mt8186/include/platform/lib/cpu.h b/src/platform/mt8186/include/platform/lib/cpu.h new file mode 100644 index 000000000000..ecbb220d5f02 --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/cpu.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/** \brief Id of primary DSP core */ +#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/mt8186/include/platform/lib/dai.h b/src/platform/mt8186/include/platform/lib/dai.h new file mode 100644 index 000000000000..8d367ed32cdd --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/dai.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#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/mt8186/include/platform/lib/dma.h b/src/platform/mt8186/include/platform/lib/dma.h new file mode 100644 index 000000000000..a7080012ffd9 --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/dma.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 2 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 32 + +#define DMA_ID_AFE_MEMIF 0 +#define DMA_ID_HOST 1 + +#define dma_chan_irq(dma, chan) dma_irq(dma) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#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/mt8186/include/platform/lib/mailbox.h b/src/platform/mt8186/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..37714ca7811d --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/mailbox.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/memory.h> +#include <stddef.h> +#include <stdint.h> + +/* + * The Window Region on MT8186 SRAM is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_EXCEPT_BASE | Except | SRAM_EXCEPT_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_STREAM_BASE | Stream | SRAM_STREAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer | SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + *ptr = src; +} + +#define ADSP_IPI_OP_REQ 0x1 +#define ADSP_IPI_OP_RSP 0x2 +void trigger_irq_to_host_req(void); +void trigger_irq_to_host_rsp(void); + +#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/mt8186/include/platform/lib/memory.h b/src/platform/mt8186/include/platform/lib/memory.h new file mode 100644 index 000000000000..65148c9c348d --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/memory.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN sizeof(void *) + +/* physical DSP addresses */ +#define SRAM_BASE 0x4e100000 +#define SRAM_SIZE 0x80000 + +/* reset vector + rodata + module_init + text + data + bss */ +#define SOF_DATA_SIZE 0x80000 +#define VECTOR_SIZE 0x700 +#define SRAM_START (SRAM_BASE + VECTOR_SIZE) + +#define DRAM_BASE 0x60000000 +#define DRAM0_SIZE 0x500000 +#define MAILBOX_BASE (DRAM_BASE + DRAM0_SIZE) +#define DSP_SYS_SIZE 0xA00000 + +#define UUID_ENTRY_ELF_BASE (SRAM_BASE + SOF_DATA_SIZE) +#define UUID_ENTRY_ELF_SIZE 0x6000 + +#define LOG_ENTRY_ELF_BASE (UUID_ENTRY_ELF_BASE + UUID_ENTRY_ELF_SIZE) +#define LOG_ENTRY_ELF_SIZE 0x20000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE (SRAM_BASE + SRAM_SIZE - EXT_MANIFEST_ELF_BASE) + +/* + * The Memory Layout on MT8186 are organised like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_START | RO Data | SOF_DATA_SIZE | + * | | text | | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | fw_ready | + * +---------------------+----------------+-----------------------------------+ + * | static_uuid | + * +---------------------+----------------+-----------------------------------+ + * | static_log | + * +---------------------+----------------+-----------------------------------+ + * | fw_metadata | + * +---------------------+----------------+-----------------------------------+ + * + * +---------------------+----------------+-----------------------------------+ + * | SOF_DRAM_BASE | | SOF_DRAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + * | MAILBOX_BASE | | SOF_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define SRAM_OUTBOX_BASE MAILBOX_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +/*4K + 4K +2K + 2K + 4K + 4K = 20KB*/ +#define SOF_MAILBOX_SIZE \ + (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE + SRAM_DEBUG_SIZE + \ + SRAM_EXCEPT_SIZE + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* SOF image on DRAM */ +#define SOF_DRAM_BASE DRAM_BASE +#define SOF_DRAM_SIZE 0x100000 + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 32 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 32 +#define HEAP_RT_COUNT1024 4 +#define HEAP_RT_COUNT2048 2 +#define HEAP_RT_COUNT4096 2 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 128 +#define HEAP_SYS_RT_COUNT512 16 +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ + +#define HEAP_SYSTEM_BASE (SOF_DRAM_BASE + SOF_DRAM_SIZE) +#define HEAP_SYSTEM_SIZE 0x6000 + +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +/*24KB*/ +#define HEAP_SYS_RUNTIME_SIZE \ + (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +/*48*(16 +32) + 32*(64 128+256) + 4*(512+1024) + 1*2048 = 24832 = 24.25KB*/ +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048 + HEAP_RT_COUNT4096 * 4096) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE \ + (DRAM0_SIZE - SOF_DRAM_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE - \ + HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Stack configuration */ +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE /*4KB*/ +#define SOF_STACK_BASE (DRAM_BASE + DRAM0_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x4 +#define SOF_MEM_VECT_TEXT_SIZE 0x1c +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 +#define SOF_MEM_RESET_LIT_SIZE 0x120 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE + +/** \brief EDF task's default stack size in bytes. */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +struct sof; + +/** + * \brief Data shared between different cores. + * Does nothing, since mt8186 doesn't support SMP. + */ +#define SHARED_DATA + +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +/** + * \brief Function for keeping shared data synchronized. + * It's used after usage of data shared by different cores. + * Such data is either statically marked with SHARED_DATA + * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. + * Does nothing, since mt8186 doesn't support SMP. + */ + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#endif + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#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/mt8186/include/platform/lib/pm_runtime.h b/src/platform/mt8186/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..581f9d77f698 --- /dev/null +++ b/src/platform/mt8186/include/platform/lib/pm_runtime.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +static inline 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_... + */ +static inline 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_... + */ +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/mt8186/include/platform/mt8186-afe-common.h b/src/platform/mt8186/include/platform/mt8186-afe-common.h new file mode 100644 index 000000000000..8667369820c1 --- /dev/null +++ b/src/platform/mt8186/include/platform/mt8186-afe-common.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Chunxu Li <chunxu.li@mediatek.com> + */ + +#ifndef _MT_8186_AFE_COMMON_H_ +#define _MT_8186_AFE_COMMON_H_ + +/* AFE: the abbreviation for Audio Front End */ + +enum { + MT8186_MEMIF_START, + MT8186_MEMIF_DL_START = MT8186_MEMIF_START, + MT8186_MEMIF_DL1 = MT8186_MEMIF_DL_START, + MT8186_MEMIF_DL2, + MT8186_MEMIF_DL_END, + MT8186_MEMIF_UL_START = MT8186_MEMIF_DL_END, + MT8186_MEMIF_UL1 = MT8186_MEMIF_UL_START, + MT8186_MEMIF_UL2, + MT8186_MEMIF_UL_END, + MT8186_MEMIF_END = MT8186_MEMIF_UL_END, + MT8186_MEMIF_DL_NUM = (MT8186_MEMIF_DL_END - MT8186_MEMIF_DL_START), + MT8186_MEMIF_UL_NUM = (MT8186_MEMIF_UL_END - MT8186_MEMIF_UL_START), + MT8186_MEMIF_NUM = (MT8186_MEMIF_END - MT8186_MEMIF_START), +}; + +enum { + MT8186_IRQ_0, + MT8186_IRQ_1, + MT8186_IRQ_2, + MT8186_IRQ_3, + MT8186_IRQ_4, + MT8186_IRQ_5, + MT8186_IRQ_6, + MT8186_IRQ_7, + MT8186_IRQ_8, + MT8186_IRQ_9, + MT8186_IRQ_10, + MT8186_IRQ_11, + MT8186_IRQ_12, + MT8186_IRQ_13, + MT8186_IRQ_14, + MT8186_IRQ_15, + MT8186_IRQ_16, + MT8186_IRQ_17, + MT8186_IRQ_18, + MT8186_IRQ_19, + MT8186_IRQ_20, + MT8186_IRQ_21, + MT8186_IRQ_22, + MT8186_IRQ_23, + MT8186_IRQ_24, + MT8186_IRQ_25, + MT8186_IRQ_26, + MT8186_IRQ_NUM, +}; + +enum { + MT8186_AFE_IO_I2S1, + MT8186_AFE_IO_I2S3, + MT8186_AFE_IO_UL_SRC1, + MT8186_AFE_IO_I2S0, + MT8186_DAI_NUM, +}; + +#endif diff --git a/src/platform/mt8186/include/platform/mt8186-afe-regs.h b/src/platform/mt8186/include/platform/mt8186-afe-regs.h new file mode 100644 index 000000000000..d7cbede7aa1c --- /dev/null +++ b/src/platform/mt8186/include/platform/mt8186-afe-regs.h @@ -0,0 +1,1737 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Chunxu Li <chunxu.li@mediatek.com> + */ + +#ifndef _MT8186_REG_H_ +#define _MT8186_REG_H_ + +#define AFE_SRAM_BASE (0x11210000 + 0x2000) +#define AFE_SRAM_SIZE (0x9C00) +#define AFE_BASE_ADDR (0x11210000) + +#define AUDIO_TOP_CON0 (0x0000) +#define AUDIO_TOP_CON1 (0x0004) +#define AUDIO_TOP_CON2 (0x0008) +#define AUDIO_TOP_CON3 (0x000c) +#define AFE_DAC_CON0 (0x0010) +#define AFE_I2S_CON (0x0018) +#define AFE_CONN0_0 (0x0020) +#define AFE_CONN1_0 (0x0024) +#define AFE_CONN2_0 (0x0028) +#define AFE_CONN3_0 (0x002c) +#define AFE_CONN4_0 (0x0030) +#define AFE_I2S_CON1 (0x0034) +#define AFE_I2S_CON2 (0x0038) +#define AFE_I2S_CON3 (0x0040) +#define AFE_CONN5_0 (0x0044) +#define AFE_CONN_24BIT_0 (0x0048) +#define AFE_DL1_CON0 (0x004c) +#define AFE_DL1_BASE_MSB (0x0050) +#define AFE_DL1_BASE (0x0054) +#define AFE_DL1_CUR_MSB (0x0058) +#define AFE_DL1_CUR (0x005c) +#define AFE_DL1_END_MSB (0x0060) +#define AFE_DL1_END (0x0064) +#define AFE_DL2_CON0 (0x0068) +#define AFE_DL2_BASE_MSB (0x006c) +#define AFE_DL2_BASE (0x0070) +#define AFE_DL2_CUR_MSB (0x0074) +#define AFE_DL2_CUR (0x0078) +#define AFE_DL2_END_MSB (0x007c) +#define AFE_DL2_END (0x0080) +#define AFE_DL3_CON0 (0x0084) +#define AFE_DL3_BASE_MSB (0x0088) +#define AFE_DL3_BASE (0x008c) +#define AFE_DL3_CUR_MSB (0x0090) +#define AFE_DL3_CUR (0x0094) +#define AFE_DL3_END_MSB (0x0098) +#define AFE_DL3_END (0x009c) +#define AFE_CONN6_0 (0x00bc) +#define AFE_DL4_CON0 (0x00cc) +#define AFE_DL4_BASE_MSB (0x00d0) +#define AFE_DL4_BASE (0x00d4) +#define AFE_DL4_CUR_MSB (0x00d8) +#define AFE_DL4_CUR (0x00dc) +#define AFE_DL4_END_MSB (0x00e0) +#define AFE_DL4_END (0x00e4) +#define AFE_DL12_CON0 (0x00e8) +#define AFE_DL12_BASE_MSB (0x00ec) +#define AFE_DL12_BASE (0x00f0) +#define AFE_DL12_CUR_MSB (0x00f4) +#define AFE_DL12_CUR (0x00f8) +#define AFE_DL12_END_MSB (0x00fc) +#define AFE_DL12_END (0x0100) +#define AFE_ADDA_DL_SRC2_CON0 (0x0108) +#define AFE_ADDA_DL_SRC2_CON1 (0x010c) +#define AFE_ADDA_UL_SRC_CON0 (0x0114) +#define AFE_ADDA_UL_SRC_CON1 (0x0118) +#define AFE_ADDA_TOP_CON0 (0x0120) +#define AFE_ADDA_UL_DL_CON0 (0x0124) +#define AFE_ADDA_SRC_DEBUG (0x012c) +#define AFE_ADDA_SRC_DEBUG_MON0 (0x0130) +#define AFE_ADDA_SRC_DEBUG_MON1 (0x0134) +#define AFE_ADDA_UL_SRC_MON0 (0x0148) +#define AFE_ADDA_UL_SRC_MON1 (0x014c) +#define AFE_SECURE_CON0 (0x0150) +#define AFE_SRAM_BOUND (0x0154) +#define AFE_SECURE_CON1 (0x0158) +#define AFE_SECURE_CONN0 (0x015c) +#define AFE_VUL_CON0 (0x0170) +#define AFE_VUL_BASE_MSB (0x0174) +#define AFE_VUL_BASE (0x0178) +#define AFE_VUL_CUR_MSB (0x017c) +#define AFE_VUL_CUR (0x0180) +#define AFE_VUL_END_MSB (0x0184) +#define AFE_VUL_END (0x0188) +#define AFE_SIDETONE_DEBUG (0x01d0) +#define AFE_SIDETONE_MON (0x01d4) +#define AFE_SINEGEN_CON2 (0x01dc) +#define AFE_SIDETONE_CON0 (0x01e0) +#define AFE_SIDETONE_COEFF (0x01e4) +#define AFE_SIDETONE_CON1 (0x01e8) +#define AFE_SIDETONE_GAIN (0x01ec) +#define AFE_SINEGEN_CON0 (0x01f0) +#define AFE_TOP_CON0 (0x0200) +#define AFE_VUL2_CON0 (0x020c) +#define AFE_VUL2_BASE_MSB (0x0210) +#define AFE_VUL2_BASE (0x0214) +#define AFE_VUL2_CUR_MSB (0x0218) +#define AFE_VUL2_CUR (0x021c) +#define AFE_VUL2_END_MSB (0x0220) +#define AFE_VUL2_END (0x0224) +#define AFE_VUL3_CON0 (0x0228) +#define AFE_VUL3_BASE_MSB (0x022c) +#define AFE_VUL3_BASE (0x0230) +#define AFE_VUL3_CUR_MSB (0x0234) +#define AFE_VUL3_CUR (0x0238) +#define AFE_VUL3_END_MSB (0x023c) +#define AFE_VUL3_END (0x0240) +#define AFE_BUSY (0x0244) +#define AFE_BUS_CFG (0x0250) +#define AFE_ADDA_PREDIS_CON0 (0x0260) +#define AFE_ADDA_PREDIS_CON1 (0x0264) +#define AFE_I2S_MON (0x027c) +#define AFE_ADDA_IIR_COEF_02_01 (0x0290) +#define AFE_ADDA_IIR_COEF_04_03 (0x0294) +#define AFE_ADDA_IIR_COEF_06_05 (0x0298) +#define AFE_ADDA_IIR_COEF_08_07 (0x029c) +#define AFE_ADDA_IIR_COEF_10_09 (0x02a0) +#define AFE_IRQ_MCU_CON1 (0x02e4) +#define AFE_IRQ_MCU_CON2 (0x02e8) +#define AFE_DAC_MON (0x02ec) +#define AFE_IRQ_MCU_CON3 (0x02f0) +#define AFE_IRQ_MCU_CON4 (0x02f4) +#define AFE_IRQ_MCU_CNT0 (0x0300) +#define AFE_IRQ_MCU_CNT6 (0x0304) +#define AFE_IRQ_MCU_CNT8 (0x0308) +#define AFE_IRQ0_MCU_CNT_MON (0x0310) +#define AFE_IRQ6_MCU_CNT_MON (0x0314) +#define AFE_VUL4_CON0 (0x0358) +#define AFE_VUL4_BASE_MSB (0x035c) +#define AFE_VUL4_BASE (0x0360) +#define AFE_VUL4_CUR_MSB (0x0364) +#define AFE_VUL4_CUR (0x0368) +#define AFE_VUL4_END_MSB (0x036c) +#define AFE_VUL4_END (0x0370) +#define AFE_VUL12_CON0 (0x0374) +#define AFE_VUL12_BASE_MSB (0x0378) +#define AFE_VUL12_BASE (0x037c) +#define AFE_VUL12_CUR_MSB (0x0380) +#define AFE_VUL12_CUR (0x0384) +#define AFE_VUL12_END_MSB (0x0388) +#define AFE_VUL12_END (0x038c) +#define AFE_IRQ3_MCU_CNT_MON (0x0398) +#define AFE_IRQ4_MCU_CNT_MON (0x039c) +#define AFE_IRQ_MCU_CON0 (0x03a0) +#define AFE_IRQ_MCU_STATUS (0x03a4) +#define AFE_IRQ_MCU_CLR (0x03a8) +#define AFE_IRQ_MCU_CNT1 (0x03ac) +#define AFE_IRQ_MCU_CNT2 (0x03b0) +#define AFE_IRQ_MCU_EN (0x03b4) +#define AFE_IRQ_MCU_MON2 (0x03b8) +#define AFE_IRQ_MCU_CNT5 (0x03bc) +#define AFE_IRQ1_MCU_CNT_MON (0x03c0) +#define AFE_IRQ2_MCU_CNT_MON (0x03c4) +#define AFE_IRQ5_MCU_CNT_MON (0x03cc) +#define AFE_IRQ_MCU_DSP_EN (0x03d0) +#define AFE_IRQ_MCU_SCP_EN (0x03d4) +#define AFE_IRQ_MCU_CNT7 (0x03dc) +#define AFE_IRQ7_MCU_CNT_MON (0x03e0) +#define AFE_IRQ_MCU_CNT3 (0x03e4) +#define AFE_IRQ_MCU_CNT4 (0x03e8) +#define AFE_IRQ_MCU_CNT11 (0x03ec) +#define AFE_APLL1_TUNER_CFG (0x03f0) +#define AFE_APLL2_TUNER_CFG (0x03f4) +#define AFE_IRQ_MCU_MISS_CLR (0x03f8) +#define AFE_CONN33_0 (0x0408) +#define AFE_IRQ_MCU_CNT12 (0x040c) +#define AFE_GAIN1_CON0 (0x0410) +#define AFE_GAIN1_CON1 (0x0414) +#define AFE_GAIN1_CON2 (0x0418) +#define AFE_GAIN1_CON3 (0x041c) +#define AFE_CONN7_0 (0x0420) +#define AFE_GAIN1_CUR (0x0424) +#define AFE_GAIN2_CON0 (0x0428) +#define AFE_GAIN2_CON1 (0x042c) +#define AFE_GAIN2_CON2 (0x0430) +#define AFE_GAIN2_CON3 (0x0434) +#define AFE_CONN8_0 (0x0438) +#define AFE_GAIN2_CUR (0x043c) +#define AFE_CONN9_0 (0x0440) +#define AFE_CONN10_0 (0x0444) +#define AFE_CONN11_0 (0x0448) +#define AFE_CONN12_0 (0x044c) +#define AFE_CONN13_0 (0x0450) +#define AFE_CONN14_0 (0x0454) +#define AFE_CONN15_0 (0x0458) +#define AFE_CONN16_0 (0x045c) +#define AFE_CONN17_0 (0x0460) +#define AFE_CONN18_0 (0x0464) +#define AFE_CONN19_0 (0x0468) +#define AFE_CONN20_0 (0x046c) +#define AFE_CONN21_0 (0x0470) +#define AFE_CONN22_0 (0x0474) +#define AFE_CONN23_0 (0x0478) +#define AFE_CONN24_0 (0x047c) +#define AFE_CONN_RS_0 (0x0494) +#define AFE_CONN_DI_0 (0x0498) +#define AFE_CONN25_0 (0x04b0) +#define AFE_CONN26_0 (0x04b4) +#define AFE_CONN27_0 (0x04b8) +#define AFE_CONN28_0 (0x04bc) +#define AFE_CONN29_0 (0x04c0) +#define AFE_CONN30_0 (0x04c4) +#define AFE_CONN31_0 (0x04c8) +#define AFE_CONN32_0 (0x04cc) +#define AFE_SRAM_DELSEL_CON1 (0x04f4) +#define AFE_CONN56_0 (0x0500) +#define AFE_CONN57_0 (0x0504) +#define AFE_CONN58_0 (0x0508) +#define AFE_CONN59_0 (0x050c) +#define AFE_CONN56_1 (0x0510) +#define AFE_CONN57_1 (0x0514) +#define AFE_CONN58_1 (0x0518) +#define AFE_CONN59_1 (0x051c) +#define PCM_INTF_CON1 (0x0530) +#define PCM_INTF_CON2 (0x0538) +#define PCM2_INTF_CON (0x053c) +#define AFE_CM1_CON (0x0550) +#define AFE_CM1_MON (0x0554) +#define AFE_CONN34_0 (0x0580) +#define FPGA_CFG0 (0x05b0) +#define FPGA_CFG1 (0x05b4) +#define FPGA_CFG2 (0x05c0) +#define FPGA_CFG3 (0x05c4) +#define AUDIO_TOP_DBG_CON (0x05c8) +#define AUDIO_TOP_DBG_MON0 (0x05cc) +#define AUDIO_TOP_DBG_MON1 (0x05d0) +#define AFE_IRQ8_MCU_CNT_MON (0x05e4) +#define AFE_IRQ11_MCU_CNT_MON (0x05e8) +#define AFE_IRQ12_MCU_CNT_MON (0x05ec) +#define AFE_IRQ_MCU_CNT9 (0x0600) +#define AFE_IRQ_MCU_CNT10 (0x0604) +#define AFE_IRQ_MCU_CNT13 (0x0608) +#define AFE_IRQ_MCU_CNT14 (0x060c) +#define AFE_IRQ_MCU_CNT15 (0x0610) +#define AFE_IRQ_MCU_CNT16 (0x0614) +#define AFE_IRQ_MCU_CNT17 (0x0618) +#define AFE_IRQ_MCU_CNT18 (0x061c) +#define AFE_IRQ_MCU_CNT19 (0x0620) +#define AFE_IRQ_MCU_CNT20 (0x0624) +#define AFE_IRQ_MCU_CNT21 (0x0628) +#define AFE_IRQ_MCU_CNT22 (0x062c) +#define AFE_IRQ_MCU_CNT23 (0x0630) +#define AFE_IRQ_MCU_CNT24 (0x0634) +#define AFE_IRQ_MCU_CNT25 (0x0638) +#define AFE_IRQ_MCU_CNT26 (0x063c) +#define AFE_IRQ9_MCU_CNT_MON (0x0660) +#define AFE_IRQ10_MCU_CNT_MON (0x0664) +#define AFE_IRQ13_MCU_CNT_MON (0x0668) +#define AFE_IRQ14_MCU_CNT_MON (0x066c) +#define AFE_IRQ15_MCU_CNT_MON (0x0670) +#define AFE_IRQ16_MCU_CNT_MON (0x0674) +#define AFE_IRQ17_MCU_CNT_MON (0x0678) +#define AFE_IRQ18_MCU_CNT_MON (0x067c) +#define AFE_IRQ19_MCU_CNT_MON (0x0680) +#define AFE_IRQ20_MCU_CNT_MON (0x0684) +#define AFE_IRQ21_MCU_CNT_MON (0x0688) +#define AFE_IRQ22_MCU_CNT_MON (0x068c) +#define AFE_IRQ23_MCU_CNT_MON (0x0690) +#define AFE_IRQ24_MCU_CNT_MON (0x0694) +#define AFE_IRQ25_MCU_CNT_MON (0x0698) +#define AFE_IRQ26_MCU_CNT_MON (0x069c) +#define AFE_IRQ31_MCU_CNT_MON (0x06a0) +#define AFE_GENERAL_REG0 (0x0800) +#define AFE_GENERAL_REG1 (0x0804) +#define AFE_GENERAL_REG2 (0x0808) +#define AFE_GENERAL_REG3 (0x080c) +#define AFE_GENERAL_REG4 (0x0810) +#define AFE_GENERAL_REG5 (0x0814) +#define AFE_GENERAL_REG6 (0x0818) +#define AFE_GENERAL_REG7 (0x081c) +#define AFE_GENERAL_REG8 (0x0820) +#define AFE_GENERAL_REG9 (0x0824) +#define AFE_GENERAL_REG10 (0x0828) +#define AFE_GENERAL_REG11 (0x082c) +#define AFE_GENERAL_REG12 (0x0830) +#define AFE_GENERAL_REG13 (0x0834) +#define AFE_GENERAL_REG14 (0x0838) +#define AFE_GENERAL_REG15 (0x083c) +#define AFE_CBIP_CFG0 (0x0840) +#define AFE_CBIP_MON0 (0x0844) +#define AFE_CBIP_SLV_MUX_MON0 (0x0848) +#define AFE_CBIP_SLV_DECODER_MON0 (0x084c) +#define AFE_ADDA6_MTKAIF_MON0 (0x0854) +#define AFE_ADDA6_MTKAIF_MON1 (0x0858) +#define AFE_AWB_CON0 (0x085c) +#define AFE_AWB_BASE_MSB (0x0860) +#define AFE_AWB_BASE (0x0864) +#define AFE_AWB_CUR_MSB (0x0868) +#define AFE_AWB_CUR (0x086c) +#define AFE_AWB_END_MSB (0x0870) +#define AFE_AWB_END (0x0874) +#define AFE_AWB2_CON0 (0x0878) +#define AFE_AWB2_BASE_MSB (0x087c) +#define AFE_AWB2_BASE (0x0880) +#define AFE_AWB2_CUR_MSB (0x0884) +#define AFE_AWB2_CUR (0x0888) +#define AFE_AWB2_END_MSB (0x088c) +#define AFE_AWB2_END (0x0890) +#define AFE_DAI_CON0 (0x0894) +#define AFE_DAI_BASE_MSB (0x0898) +#define AFE_DAI_BASE (0x089c) +#define AFE_DAI_CUR_MSB (0x08a0) +#define AFE_DAI_CUR (0x08a4) +#define AFE_DAI_END_MSB (0x08a8) +#define AFE_DAI_END (0x08ac) +#define AFE_DAI2_CON0 (0x08b0) +#define AFE_DAI2_BASE_MSB (0x08b4) +#define AFE_DAI2_BASE (0x08b8) +#define AFE_DAI2_CUR_MSB (0x08bc) +#define AFE_DAI2_CUR (0x08c0) +#define AFE_DAI2_END_MSB (0x08c4) +#define AFE_DAI2_END (0x08c8) +#define AFE_MEMIF_CON0 (0x08cc) +#define AFE_CONN0_1 (0x0900) +#define AFE_CONN1_1 (0x0904) +#define AFE_CONN2_1 (0x0908) +#define AFE_CONN3_1 (0x090c) +#define AFE_CONN4_1 (0x0910) +#define AFE_CONN5_1 (0x0914) +#define AFE_CONN6_1 (0x0918) +#define AFE_CONN7_1 (0x091c) +#define AFE_CONN8_1 (0x0920) +#define AFE_CONN9_1 (0x0924) +#define AFE_CONN10_1 (0x0928) +#define AFE_CONN11_1 (0x092c) +#define AFE_CONN12_1 (0x0930) +#define AFE_CONN13_1 (0x0934) +#define AFE_CONN14_1 (0x0938) +#define AFE_CONN15_1 (0x093c) +#define AFE_CONN16_1 (0x0940) +#define AFE_CONN17_1 (0x0944) +#define AFE_CONN18_1 (0x0948) +#define AFE_CONN19_1 (0x094c) +#define AFE_CONN20_1 (0x0950) +#define AFE_CONN21_1 (0x0954) +#define AFE_CONN22_1 (0x0958) +#define AFE_CONN23_1 (0x095c) +#define AFE_CONN24_1 (0x0960) +#define AFE_CONN25_1 (0x0964) +#define AFE_CONN26_1 (0x0968) +#define AFE_CONN27_1 (0x096c) +#define AFE_CONN28_1 (0x0970) +#define AFE_CONN29_1 (0x0974) +#define AFE_CONN30_1 (0x0978) +#define AFE_CONN31_1 (0x097c) +#define AFE_CONN32_1 (0x0980) +#define AFE_CONN33_1 (0x0984) +#define AFE_CONN34_1 (0x0988) +#define AFE_CONN_RS_1 (0x098c) +#define AFE_CONN_DI_1 (0x0990) +#define AFE_CONN_24BIT_1 (0x0994) +#define AFE_CONN_REG (0x0998) +#define AFE_CONN35_0 (0x09a0) +#define AFE_CONN36_0 (0x09a4) +#define AFE_CONN37_0 (0x09a8) +#define AFE_CONN38_0 (0x09ac) +#define AFE_CONN35_1 (0x09b0) +#define AFE_CONN36_1 (0x09b4) +#define AFE_CONN37_1 (0x09b8) +#define AFE_CONN38_1 (0x09bc) +#define AFE_CONN39_0 (0x09c0) +#define AFE_CONN40_0 (0x09c4) +#define AFE_CONN41_0 (0x09c8) +#define AFE_CONN42_0 (0x09cc) +#define AFE_CONN39_1 (0x09e0) +#define AFE_CONN40_1 (0x09e4) +#define AFE_CONN41_1 (0x09e8) +#define AFE_CONN42_1 (0x09ec) +#define AFE_CONN60_0 (0x0a64) +#define AFE_CONN61_0 (0x0a68) +#define AFE_CONN62_0 (0x0a6c) +#define AFE_CONN63_0 (0x0a70) +#define AFE_CONN64_0 (0x0a74) +#define AFE_CONN65_0 (0x0a78) +#define AFE_CONN66_0 (0x0a7c) +#define AFE_ADDA6_TOP_CON0 (0x0a80) +#define AFE_ADDA6_UL_SRC_CON0 (0x0a84) +#define AFE_ADDA6_UL_SRC_CON1 (0x0a88) +#define AFE_ADDA6_SRC_DEBUG (0x0a8c) +#define AFE_ADDA6_SRC_DEBUG_MON0 (0x0a90) +#define AFE_ADDA6_ULCF_CFG_02_01 (0x0aa0) +#define AFE_ADDA6_ULCF_CFG_04_03 (0x0aa4) +#define AFE_ADDA6_ULCF_CFG_06_05 (0x0aa8) +#define AFE_ADDA6_ULCF_CFG_08_07 (0x0aac) +#define AFE_ADDA6_ULCF_CFG_10_09 (0x0ab0) +#define AFE_ADDA6_ULCF_CFG_12_11 (0x0ab4) +#define AFE_ADDA6_ULCF_CFG_14_13 (0x0ab8) +#define AFE_ADDA6_ULCF_CFG_16_15 (0x0abc) +#define AFE_ADDA6_ULCF_CFG_18_17 (0x0ac0) +#define AFE_ADDA6_ULCF_CFG_20_19 (0x0ac4) +#define AFE_ADDA6_ULCF_CFG_22_21 (0x0ac8) +#define AFE_ADDA6_ULCF_CFG_24_23 (0x0acc) +#define AFE_ADDA6_ULCF_CFG_26_25 (0x0ad0) +#define AFE_ADDA6_ULCF_CFG_28_27 (0x0ad4) +#define AFE_ADDA6_ULCF_CFG_30_29 (0x0ad8) +#define AFE_ADD6A_UL_SRC_MON0 (0x0ae4) +#define AFE_ADDA6_UL_SRC_MON1 (0x0ae8) +#define AFE_CONN43_0 (0x0af8) +#define AFE_CONN43_1 (0x0afc) +#define AFE_MOD_DAI_CON0 (0x0b00) +#define AFE_MOD_DAI_BASE_MSB (0x0b04) +#define AFE_MOD_DAI_BASE (0x0b08) +#define AFE_MOD_DAI_CUR_MSB (0x0b0c) +#define AFE_MOD_DAI_CUR (0x0b10) +#define AFE_MOD_DAI_END_MSB (0x0b14) +#define AFE_MOD_DAI_END (0x0b18) +#define AFE_AWB_RCH_MON (0x0b70) +#define AFE_AWB_LCH_MON (0x0b74) +#define AFE_VUL_RCH_MON (0x0b78) +#define AFE_VUL_LCH_MON (0x0b7c) +#define AFE_VUL12_RCH_MON (0x0b80) +#define AFE_VUL12_LCH_MON (0x0b84) +#define AFE_VUL2_RCH_MON (0x0b88) +#define AFE_VUL2_LCH_MON (0x0b8c) +#define AFE_DAI_DATA_MON (0x0b90) +#define AFE_MOD_DAI_DATA_MON (0x0b94) +#define AFE_DAI2_DATA_MON (0x0b98) +#define AFE_AWB2_RCH_MON (0x0b9c) +#define AFE_AWB2_LCH_MON (0x0ba0) +#define AFE_VUL3_RCH_MON (0x0ba4) +#define AFE_VUL3_LCH_MON (0x0ba8) +#define AFE_VUL4_RCH_MON (0x0bac) +#define AFE_VUL4_LCH_MON (0x0bb0) +#define AFE_VUL5_RCH_MON (0x0bb4) +#define AFE_VUL5_LCH_MON (0x0bb8) +#define AFE_VUL6_RCH_MON (0x0bbc) +#define AFE_VUL6_LCH_MON (0x0bc0) +#define AFE_DL1_RCH_MON (0x0bc4) +#define AFE_DL1_LCH_MON (0x0bc8) +#define AFE_DL2_RCH_MON (0x0bcc) +#define AFE_DL2_LCH_MON (0x0bd0) +#define AFE_DL12_RCH1_MON (0x0bd4) +#define AFE_DL12_LCH1_MON (0x0bd8) +#define AFE_DL12_RCH2_MON (0x0bdc) +#define AFE_DL12_LCH2_MON (0x0be0) +#define AFE_DL3_RCH_MON (0x0be4) +#define AFE_DL3_LCH_MON (0x0be8) +#define AFE_DL4_RCH_MON (0x0bec) +#define AFE_DL4_LCH_MON (0x0bf0) +#define AFE_DL5_RCH_MON (0x0bf4) +#define AFE_DL5_LCH_MON (0x0bf8) +#define AFE_DL6_RCH_MON (0x0bfc) +#define AFE_DL6_LCH_MON (0x0c00) +#define AFE_DL7_RCH_MON (0x0c04) +#define AFE_DL7_LCH_MON (0x0c08) +#define AFE_DL8_RCH_MON (0x0c0c) +#define AFE_DL8_LCH_MON (0x0c10) +#define AFE_VUL5_CON0 (0x0c14) +#define AFE_VUL5_BASE_MSB (0x0c18) +#define AFE_VUL5_BASE (0x0c1c) +#define AFE_VUL5_CUR_MSB (0x0c20) +#define AFE_VUL5_CUR (0x0c24) +#define AFE_VUL5_END_MSB (0x0c28) +#define AFE_VUL5_END (0x0c2c) +#define AFE_VUL6_CON0 (0x0c30) +#define AFE_VUL6_BASE_MSB (0x0c34) +#define AFE_VUL6_BASE (0x0c38) +#define AFE_VUL6_CUR_MSB (0x0c3c) +#define AFE_VUL6_CUR (0x0c40) +#define AFE_VUL6_END_MSB (0x0c44) +#define AFE_VUL6_END (0x0c48) +#define AFE_ADDA_DL_SDM_DCCOMP_CON (0x0c50) +#define AFE_ADDA_DL_SDM_TEST (0x0c54) +#define AFE_ADDA_DL_DC_COMP_CFG0 (0x0c58) +#define AFE_ADDA_DL_DC_COMP_CFG1 (0x0c5c) +#define AFE_ADDA_DL_SDM_FIFO_MON (0x0c60) +#define AFE_ADDA_DL_SRC_LCH_MON (0x0c64) +#define AFE_ADDA_DL_SRC_RCH_MON (0x0c68) +#define AFE_ADDA_DL_SDM_OUT_MON (0x0c6c) +#define AFE_ADDA_DL_SDM_DITHER_CON (0x0c70) +#define AFE_ADDA_DL_SDM_AUTO_RESET_CON (0x0c74) +#define AFE_CONNSYS_I2S_CON (0x0c78) +#define AFE_CONNSYS_I2S_MON (0x0c7c) +#define AFE_ASRC_2CH_CON0 (0x0c80) +#define AFE_ASRC_2CH_CON1 (0x0c84) +#define AFE_ASRC_2CH_CON2 (0x0c88) +#define AFE_ASRC_2CH_CON3 (0x0c8c) +#define AFE_ASRC_2CH_CON4 (0x0c90) +#define AFE_ASRC_2CH_CON5 (0x0c94) +#define AFE_ASRC_2CH_CON6 (0x0c98) +#define AFE_ASRC_2CH_CON7 (0x0c9c) +#define AFE_ASRC_2CH_CON8 (0x0ca0) +#define AFE_ASRC_2CH_CON9 (0x0ca4) +#define AFE_ASRC_2CH_CON10 (0x0ca8) +#define AFE_ASRC_2CH_CON12 (0x0cb0) +#define AFE_ASRC_2CH_CON13 (0x0cb4) +#define AFE_ADDA6_IIR_COEF_02_01 (0x0ce0) +#define AFE_ADDA6_IIR_COEF_04_03 (0x0ce4) +#define AFE_ADDA6_IIR_COEF_06_05 (0x0ce8) +#define AFE_ADDA6_IIR_COEF_08_07 (0x0cec) +#define AFE_ADDA6_IIR_COEF_10_09 (0x0cf0) +#define AFE_CONN67_0 (0x0cf4) +#define AFE_CONN68_0 (0x0cf8) +#define AFE_CONN69_0 (0x0cfc) +#define AFE_ADDA_PREDIS_CON2 (0x0d40) +#define AFE_ADDA_PREDIS_CON3 (0x0d44) +#define AFE_CONN44_0 (0x0d70) +#define AFE_CONN45_0 (0x0d74) +#define AFE_CONN46_0 (0x0d78) +#define AFE_CONN47_0 (0x0d7c) +#define AFE_CONN44_1 (0x0d80) +#define AFE_CONN45_1 (0x0d84) +#define AFE_CONN46_1 (0x0d88) +#define AFE_CONN47_1 (0x0d8c) +#define AFE_DL1_MON0 (0x0d90) +#define AFE_DL2_MON0 (0x0d94) +#define AFE_DL3_MON0 (0x0d98) +#define AFE_DL4_MON0 (0x0d9c) +#define AFE_DL5_MON0 (0x0da0) +#define AFE_DL6_MON0 (0x0da4) +#define AFE_DL7_MON0 (0x0da8) +#define AFE_DL8_MON0 (0x0dac) +#define AFE_DL12_MON0 (0x0db0) +#define AFE_HD_ENGEN_ENABLE (0x0dd0) +#define AFE_ADDA_DL_NLE_FIFO_MON (0x0dfc) +#define AFE_ADDA_MTKAIF_CFG0 (0x0e00) +#define AFE_CONN67_1 (0x0e04) +#define AFE_CONN68_1 (0x0e08) +#define AFE_CONN69_1 (0x0e0c) +#define AFE_ADDA_MTKAIF_SYNCWORD_CFG (0x0e14) +#define AFE_ADDA_MTKAIF_RX_CFG0 (0x0e20) +#define AFE_ADDA_MTKAIF_RX_CFG1 (0x0e24) +#define AFE_ADDA_MTKAIF_RX_CFG2 (0x0e28) +#define AFE_ADDA_MTKAIF_MON0 (0x0e34) +#define AFE_ADDA_MTKAIF_MON1 (0x0e38) +#define AFE_AUD_PAD_TOP (0x0e40) +#define AFE_DL_NLE_R_CFG0 (0x0e44) +#define AFE_DL_NLE_R_CFG1 (0x0e48) +#define AFE_DL_NLE_L_CFG0 (0x0e4c) +#define AFE_DL_NLE_L_CFG1 (0x0e50) +#define AFE_DL_NLE_R_MON0 (0x0e54) +#define AFE_DL_NLE_R_MON1 (0x0e58) +#define AFE_DL_NLE_R_MON2 (0x0e5c) +#define AFE_DL_NLE_L_MON0 (0x0e60) +#define AFE_DL_NLE_L_MON1 (0x0e64) +#define AFE_DL_NLE_L_MON2 (0x0e68) +#define AFE_DL_NLE_GAIN_CFG0 (0x0e6c) +#define AFE_ADDA6_MTKAIF_CFG0 (0x0e70) +#define AFE_ADDA6_MTKAIF_RX_CFG0 (0x0e74) +#define AFE_ADDA6_MTKAIF_RX_CFG1 (0x0e78) +#define AFE_ADDA6_MTKAIF_RX_CFG2 (0x0e7c) +#define AFE_GENERAL1_ASRC_2CH_CON0 (0x0e80) +#define AFE_GENERAL1_ASRC_2CH_CON1 (0x0e84) +#define AFE_GENERAL1_ASRC_2CH_CON2 (0x0e88) +#define AFE_GENERAL1_ASRC_2CH_CON3 (0x0e8c) +#define AFE_GENERAL1_ASRC_2CH_CON4 (0x0e90) +#define AFE_GENERAL1_ASRC_2CH_CON5 (0x0e94) +#define AFE_GENERAL1_ASRC_2CH_CON6 (0x0e98) +#define AFE_GENERAL1_ASRC_2CH_CON7 (0x0e9c) +#define AFE_GENERAL1_ASRC_2CH_CON8 (0x0ea0) +#define AFE_GENERAL1_ASRC_2CH_CON9 (0x0ea4) +#define AFE_GENERAL1_ASRC_2CH_CON10 (0x0ea8) +#define AFE_GENERAL1_ASRC_2CH_CON12 (0x0eb0) +#define AFE_GENERAL1_ASRC_2CH_CON13 (0x0eb4) +#define GENERAL_ASRC_MODE (0x0eb8) +#define GENERAL_ASRC_EN_ON (0x0ebc) +#define AFE_CONN48_0 (0x0ec0) +#define AFE_CONN49_0 (0x0ec4) +#define AFE_CONN50_0 (0x0ec8) +#define AFE_CONN51_0 (0x0ecc) +#define AFE_CONN52_0 (0x0ed0) +#define AFE_CONN53_0 (0x0ed4) +#define AFE_CONN54_0 (0x0ed8) +#define AFE_CONN55_0 (0x0edc) +#define AFE_CONN48_1 (0x0ee0) +#define AFE_CONN49_1 (0x0ee4) +#define AFE_CONN50_1 (0x0ee8) +#define AFE_CONN51_1 (0x0eec) +#define AFE_CONN52_1 (0x0ef0) +#define AFE_CONN53_1 (0x0ef4) +#define AFE_CONN54_1 (0x0ef8) +#define AFE_CONN55_1 (0x0efc) +#define AFE_GENERAL2_ASRC_2CH_CON0 (0x0f00) +#define AFE_GENERAL2_ASRC_2CH_CON1 (0x0f04) +#define AFE_GENERAL2_ASRC_2CH_CON2 (0x0f08) +#define AFE_GENERAL2_ASRC_2CH_CON3 (0x0f0c) +#define AFE_GENERAL2_ASRC_2CH_CON4 (0x0f10) +#define AFE_GENERAL2_ASRC_2CH_CON5 (0x0f14) +#define AFE_GENERAL2_ASRC_2CH_CON6 (0x0f18) +#define AFE_GENERAL2_ASRC_2CH_CON7 (0x0f1c) +#define AFE_GENERAL2_ASRC_2CH_CON8 (0x0f20) +#define AFE_GENERAL2_ASRC_2CH_CON9 (0x0f24) +#define AFE_GENERAL2_ASRC_2CH_CON10 (0x0f28) +#define AFE_GENERAL2_ASRC_2CH_CON12 (0x0f30) +#define AFE_GENERAL2_ASRC_2CH_CON13 (0x0f34) +#define AFE_DL5_CON0 (0x0f4c) +#define AFE_DL5_BASE_MSB (0x0f50) +#define AFE_DL5_BASE (0x0f54) +#define AFE_DL5_CUR_MSB (0x0f58) +#define AFE_DL5_CUR (0x0f5c) +#define AFE_DL5_END_MSB (0x0f60) +#define AFE_DL5_END (0x0f64) +#define AFE_DL6_CON0 (0x0f68) +#define AFE_DL6_BASE_MSB (0x0f6c) +#define AFE_DL6_BASE (0x0f70) +#define AFE_DL6_CUR_MSB (0x0f74) +#define AFE_DL6_CUR (0x0f78) +#define AFE_DL6_END_MSB (0x0f7c) +#define AFE_DL6_END (0x0f80) +#define AFE_DL7_CON0 (0x0f84) +#define AFE_DL7_BASE_MSB (0x0f88) +#define AFE_DL7_BASE (0x0f8c) +#define AFE_DL7_CUR_MSB (0x0f90) +#define AFE_DL7_CUR (0x0f94) +#define AFE_DL7_END_MSB (0x0f98) +#define AFE_DL7_END (0x0f9c) +#define AFE_DL8_CON0 (0x0fa0) +#define AFE_DL8_BASE_MSB (0x0fa4) +#define AFE_DL8_BASE (0x0fa8) +#define AFE_DL8_CUR_MSB (0x0fac) +#define AFE_DL8_CUR (0x0fb0) +#define AFE_DL8_END_MSB (0x0fb4) +#define AFE_DL8_END (0x0fb8) +#define AFE_VUL_MON0 (0x0fc8) +#define AFE_VUL2_MON0 (0x0fcc) +#define AFE_VUL3_MON0 (0x0fd0) +#define AFE_VUL4_MON0 (0x0fd4) +#define AFE_VUL5_MON0 (0x0fd8) +#define AFE_VUL6_MON0 (0x0fdc) +#define AFE_VUL12_MON0 (0x0fe0) +#define AFE_AWB_MON0 (0x0fe4) +#define AFE_AWB2_MON0 (0x0fe8) +#define AFE_MOD_DAI_MON0 (0x0fec) +#define AFE_DAI_MON0 (0x0ff0) +#define AFE_DAI2_MON0 (0x0ff4) +#define AFE_CONN_RS_2 (0x0ff8) +#define AFE_CONN_DI_2 (0x0ffc) +#define AFE_CONN_24BIT_2 (0x1000) +#define AFE_CONN60_1 (0x11f0) +#define AFE_CONN61_1 (0x11f4) +#define AFE_CONN62_1 (0x11f8) +#define AFE_CONN63_1 (0x11fc) +#define AFE_CONN64_1 (0x1220) +#define AFE_CONN65_1 (0x1224) +#define AFE_CONN66_1 (0x1228) +#define FPGA_CFG4 (0x1230) +#define FPGA_CFG5 (0x1234) +#define FPGA_CFG6 (0x1238) +#define FPGA_CFG7 (0x123c) +#define FPGA_CFG8 (0x1240) +#define FPGA_CFG9 (0x1244) +#define FPGA_CFG10 (0x1248) +#define FPGA_CFG11 (0x124c) +#define FPGA_CFG12 (0x1250) +#define FPGA_CFG13 (0x1254) +#define ETDM_IN1_CON0 (0x1430) +#define ETDM_IN1_CON1 (0x1434) +#define ETDM_IN1_CON2 (0x1438) +#define ETDM_IN1_CON3 (0x143c) +#define ETDM_IN1_CON4 (0x1440) +#define ETDM_IN1_CON5 (0x1444) +#define ETDM_IN1_CON6 (0x1448) +#define ETDM_IN1_CON7 (0x144c) +#define ETDM_IN1_CON8 (0x1450) +#define ETDM_OUT1_CON0 (0x1454) +#define ETDM_OUT1_CON1 (0x1458) +#define ETDM_OUT1_CON2 (0x145c) +#define ETDM_OUT1_CON3 (0x1460) +#define ETDM_OUT1_CON4 (0x1464) +#define ETDM_OUT1_CON5 (0x1468) +#define ETDM_OUT1_CON6 (0x146c) +#define ETDM_OUT1_CON7 (0x1470) +#define ETDM_OUT1_CON8 (0x1474) +#define ETDM_IN1_MON (0x1478) +#define ETDM_OUT1_MON (0x147c) +#define ETDM_0_3_COWORK_CON0 (0x18b0) +#define ETDM_0_3_COWORK_CON1 (0x18b4) +#define ETDM_0_3_COWORK_CON3 (0x18bc) + +/* AFE_DAC_CON0 */ +#define VUL12_ON_SFT 31 +#define VUL12_ON_MASK 0x1 +#define VUL12_ON_MASK_SFT (0x1 << 31) +#define MOD_DAI_ON_SFT 30 +#define MOD_DAI_ON_MASK 0x1 +#define MOD_DAI_ON_MASK_SFT (0x1 << 30) +#define DAI_ON_SFT 29 +#define DAI_ON_MASK 0x1 +#define DAI_ON_MASK_SFT (0x1 << 29) +#define DAI2_ON_SFT 28 +#define DAI2_ON_MASK 0x1 +#define DAI2_ON_MASK_SFT (0x1 << 28) +#define VUL6_ON_SFT 23 +#define VUL6_ON_MASK 0x1 +#define VUL6_ON_MASK_SFT (0x1 << 23) +#define VUL5_ON_SFT 22 +#define VUL5_ON_MASK 0x1 +#define VUL5_ON_MASK_SFT (0x1 << 22) +#define VUL4_ON_SFT 21 +#define VUL4_ON_MASK 0x1 +#define VUL4_ON_MASK_SFT (0x1 << 21) +#define VUL3_ON_SFT 20 +#define VUL3_ON_MASK 0x1 +#define VUL3_ON_MASK_SFT (0x1 << 20) +#define VUL2_ON_SFT 19 +#define VUL2_ON_MASK 0x1 +#define VUL2_ON_MASK_SFT (0x1 << 19) +#define VUL_ON_SFT 18 +#define VUL_ON_MASK 0x1 +#define VUL_ON_MASK_SFT (0x1 << 18) +#define AWB2_ON_SFT 17 +#define AWB2_ON_MASK 0x1 +#define AWB2_ON_MASK_SFT (0x1 << 17) +#define AWB_ON_SFT 16 +#define AWB_ON_MASK 0x1 +#define AWB_ON_MASK_SFT (0x1 << 16) +#define DL12_ON_SFT 15 +#define DL12_ON_MASK 0x1 +#define DL12_ON_MASK_SFT (0x1 << 15) +#define DL8_ON_SFT 11 +#define DL8_ON_MASK 0x1 +#define DL8_ON_MASK_SFT (0x1 << 11) +#define DL7_ON_SFT 10 +#define DL7_ON_MASK 0x1 +#define DL7_ON_MASK_SFT (0x1 << 10) +#define DL6_ON_SFT 9 +#define DL6_ON_MASK 0x1 +#define DL6_ON_MASK_SFT (0x1 << 9) +#define DL5_ON_SFT 8 +#define DL5_ON_MASK 0x1 +#define DL5_ON_MASK_SFT (0x1 << 8) +#define DL4_ON_SFT 7 +#define DL4_ON_MASK 0x1 +#define DL4_ON_MASK_SFT (0x1 << 7) +#define DL3_ON_SFT 6 +#define DL3_ON_MASK 0x1 +#define DL3_ON_MASK_SFT (0x1 << 6) +#define DL2_ON_SFT 5 +#define DL2_ON_MASK 0x1 +#define DL2_ON_MASK_SFT (0x1 << 5) +#define DL1_ON_SFT 4 +#define DL1_ON_MASK 0x1 +#define DL1_ON_MASK_SFT (0x1 << 4) +#define AFE_ON_SFT 0 +#define AFE_ON_MASK 0x1 +#define AFE_ON_MASK_SFT (0x1 << 0) + +// AFE_CM1_CON +#define CHANNEL_MERGE0_DEBUG_MODE_SFT (31) +#define CHANNEL_MERGE0_DEBUG_MODE_MASK (0x1) +#define CHANNEL_MERGE0_DEBUG_MODE_MASK_SFT (0x1 << 31) +#define VUL3_BYPASS_CM_SFT (30) +#define VUL3_BYPASS_CM_MASK (0x1) +#define VUL3_BYPASS_CM_MASK_SFT (0x1 << 30) +#define CM1_DEBUG_MODE_SEL_SFT (29) +#define CM1_DEBUG_MODE_SEL_MASK (0x1) +#define CM1_DEBUG_MODE_SEL_MASK_SFT (0x1 << 29) +#define CHANNEL_MERGE0_UPDATE_CNT_SFT (16) +#define CHANNEL_MERGE0_UPDATE_CNT_MASK (0x1fff) +#define CHANNEL_MERGE0_UPDATE_CNT_MASK_SFT (0x1fff << 16) +#define CM1_FS_SELECT_SFT (8) +#define CM1_FS_SELECT_MASK (0x1f) +#define CM1_FS_SELECT_MASK_SFT (0x1f << 8) +#define CHANNEL_MERGE0_CHNUM_SFT (3) +#define CHANNEL_MERGE0_CHNUM_MASK (0x1f) +#define CHANNEL_MERGE0_CHNUM_MASK_SFT (0x1f << 3) +#define CHANNEL_MERGE0_BYTE_SWAP_SFT (1) +#define CHANNEL_MERGE0_BYTE_SWAP_MASK (0x1) +#define CHANNEL_MERGE0_BYTE_SWAP_MASK_SFT (0x1 << 1) +#define CHANNEL_MERGE0_EN_SFT (0) +#define CHANNEL_MERGE0_EN_MASK (0x1) +#define CHANNEL_MERGE0_EN_MASK_SFT (0x1 << 0) + +// AFE_CM1_MON +#define AFE_CM0_OUTPUT_CNT_POS (16) +#define AFE_CM0_OUTPUT_CNT_LEN (13) +#define AFE_CM0_CUR_CHSET_POS (5) +#define AFE_CM0_CUR_CHSET_LEN (4) +#define AFE_CM0_ODD_FLAG_POS (4) +#define AFE_CM0_ODD_FLAG_LEN (1) +#define AFE_CM0_BYTE_SWAP_MON_POS (1) +#define AFE_CM0_BYTE_SWAP_MON_LEN (1) +#define AFE_CM0_ON_MON_POS (0) +#define AFE_CM0_ON_MON_LEN (1) + +/* AFE_DL1_CON0 */ +#define DL1_MODE_SFT 24 +#define DL1_MODE_MASK 0xf +#define DL1_MODE_MASK_SFT (0xf << 24) +#define DL1_MINLEN_SFT 20 +#define DL1_MINLEN_MASK 0xf +#define DL1_MINLEN_MASK_SFT (0xf << 20) +#define DL1_MAXLEN_SFT 16 +#define DL1_MAXLEN_MASK 0xf +#define DL1_MAXLEN_MASK_SFT (0xf << 16) +#define DL1_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL1_PBUF_SIZE_SFT 12 +#define DL1_PBUF_SIZE_MASK 0x3 +#define DL1_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL1_MONO_SFT 8 +#define DL1_MONO_MASK 0x1 +#define DL1_MONO_MASK_SFT (0x1 << 8) +#define DL1_NORMAL_MODE_SFT 5 +#define DL1_NORMAL_MODE_MASK 0x1 +#define DL1_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL1_HALIGN_SFT 4 +#define DL1_HALIGN_MASK 0x1 +#define DL1_HALIGN_MASK_SFT (0x1 << 4) +#define DL1_HD_MODE_SFT 0 +#define DL1_HD_MODE_MASK 0x3 +#define DL1_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL2_CON0 */ +#define DL2_MODE_SFT 24 +#define DL2_MODE_MASK 0xf +#define DL2_MODE_MASK_SFT (0xf << 24) +#define DL2_MINLEN_SFT 20 +#define DL2_MINLEN_MASK 0xf +#define DL2_MINLEN_MASK_SFT (0xf << 20) +#define DL2_MAXLEN_SFT 16 +#define DL2_MAXLEN_MASK 0xf +#define DL2_MAXLEN_MASK_SFT (0xf << 16) +#define DL2_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL2_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL2_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL2_PBUF_SIZE_SFT 12 +#define DL2_PBUF_SIZE_MASK 0x3 +#define DL2_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL2_MONO_SFT 8 +#define DL2_MONO_MASK 0x1 +#define DL2_MONO_MASK_SFT (0x1 << 8) +#define DL2_NORMAL_MODE_SFT 5 +#define DL2_NORMAL_MODE_MASK 0x1 +#define DL2_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL2_HALIGN_SFT 4 +#define DL2_HALIGN_MASK 0x1 +#define DL2_HALIGN_MASK_SFT (0x1 << 4) +#define DL2_HD_MODE_SFT 0 +#define DL2_HD_MODE_MASK 0x3 +#define DL2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL3_CON0 */ +#define DL3_MODE_SFT 24 +#define DL3_MODE_MASK 0xf +#define DL3_MODE_MASK_SFT (0xf << 24) +#define DL3_MINLEN_SFT 20 +#define DL3_MINLEN_MASK 0xf +#define DL3_MINLEN_MASK_SFT (0xf << 20) +#define DL3_MAXLEN_SFT 16 +#define DL3_MAXLEN_MASK 0xf +#define DL3_MAXLEN_MASK_SFT (0xf << 16) +#define DL3_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL3_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL3_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL3_PBUF_SIZE_SFT 12 +#define DL3_PBUF_SIZE_MASK 0x3 +#define DL3_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL3_MONO_SFT 8 +#define DL3_MONO_MASK 0x1 +#define DL3_MONO_MASK_SFT (0x1 << 8) +#define DL3_NORMAL_MODE_SFT 5 +#define DL3_NORMAL_MODE_MASK 0x1 +#define DL3_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL3_HALIGN_SFT 4 +#define DL3_HALIGN_MASK 0x1 +#define DL3_HALIGN_MASK_SFT (0x1 << 4) +#define DL3_HD_MODE_SFT 0 +#define DL3_HD_MODE_MASK 0x3 +#define DL3_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL4_CON0 */ +#define DL4_MODE_SFT 24 +#define DL4_MODE_MASK 0xf +#define DL4_MODE_MASK_SFT (0xf << 24) +#define DL4_MINLEN_SFT 20 +#define DL4_MINLEN_MASK 0xf +#define DL4_MINLEN_MASK_SFT (0xf << 20) +#define DL4_MAXLEN_SFT 16 +#define DL4_MAXLEN_MASK 0xf +#define DL4_MAXLEN_MASK_SFT (0xf << 16) +#define DL4_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL4_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL4_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL4_PBUF_SIZE_SFT 12 +#define DL4_PBUF_SIZE_MASK 0x3 +#define DL4_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL4_MONO_SFT 8 +#define DL4_MONO_MASK 0x1 +#define DL4_MONO_MASK_SFT (0x1 << 8) +#define DL4_NORMAL_MODE_SFT 5 +#define DL4_NORMAL_MODE_MASK 0x1 +#define DL4_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL4_HALIGN_SFT 4 +#define DL4_HALIGN_MASK 0x1 +#define DL4_HALIGN_MASK_SFT (0x1 << 4) +#define DL4_HD_MODE_SFT 0 +#define DL4_HD_MODE_MASK 0x3 +#define DL4_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL5_CON0 */ +#define DL5_MODE_SFT 24 +#define DL5_MODE_MASK 0xf +#define DL5_MODE_MASK_SFT (0xf << 24) +#define DL5_MINLEN_SFT 20 +#define DL5_MINLEN_MASK 0xf +#define DL5_MINLEN_MASK_SFT (0xf << 20) +#define DL5_MAXLEN_SFT 16 +#define DL5_MAXLEN_MASK 0xf +#define DL5_MAXLEN_MASK_SFT (0xf << 16) +#define DL5_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL5_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL5_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL5_PBUF_SIZE_SFT 12 +#define DL5_PBUF_SIZE_MASK 0x3 +#define DL5_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL5_MONO_SFT 8 +#define DL5_MONO_MASK 0x1 +#define DL5_MONO_MASK_SFT (0x1 << 8) +#define DL5_NORMAL_MODE_SFT 5 +#define DL5_NORMAL_MODE_MASK 0x1 +#define DL5_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL5_HALIGN_SFT 4 +#define DL5_HALIGN_MASK 0x1 +#define DL5_HALIGN_MASK_SFT (0x1 << 4) +#define DL5_HD_MODE_SFT 0 +#define DL5_HD_MODE_MASK 0x3 +#define DL5_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL6_CON0 */ +#define DL6_MODE_SFT 24 +#define DL6_MODE_MASK 0xf +#define DL6_MODE_MASK_SFT (0xf << 24) +#define DL6_MINLEN_SFT 20 +#define DL6_MINLEN_MASK 0xf +#define DL6_MINLEN_MASK_SFT (0xf << 20) +#define DL6_MAXLEN_SFT 16 +#define DL6_MAXLEN_MASK 0xf +#define DL6_MAXLEN_MASK_SFT (0xf << 16) +#define DL6_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL6_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL6_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL6_PBUF_SIZE_SFT 12 +#define DL6_PBUF_SIZE_MASK 0x3 +#define DL6_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL6_MONO_SFT 8 +#define DL6_MONO_MASK 0x1 +#define DL6_MONO_MASK_SFT (0x1 << 8) +#define DL6_NORMAL_MODE_SFT 5 +#define DL6_NORMAL_MODE_MASK 0x1 +#define DL6_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL6_HALIGN_SFT 4 +#define DL6_HALIGN_MASK 0x1 +#define DL6_HALIGN_MASK_SFT (0x1 << 4) +#define DL6_HD_MODE_SFT 0 +#define DL6_HD_MODE_MASK 0x3 +#define DL6_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL7_CON0 */ +#define DL7_MODE_SFT 24 +#define DL7_MODE_MASK 0xf +#define DL7_MODE_MASK_SFT (0xf << 24) +#define DL7_MINLEN_SFT 20 +#define DL7_MINLEN_MASK 0xf +#define DL7_MINLEN_MASK_SFT (0xf << 20) +#define DL7_MAXLEN_SFT 16 +#define DL7_MAXLEN_MASK 0xf +#define DL7_MAXLEN_MASK_SFT (0xf << 16) +#define DL7_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL7_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL7_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL7_PBUF_SIZE_SFT 12 +#define DL7_PBUF_SIZE_MASK 0x3 +#define DL7_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL7_MONO_SFT 8 +#define DL7_MONO_MASK 0x1 +#define DL7_MONO_MASK_SFT (0x1 << 8) +#define DL7_NORMAL_MODE_SFT 5 +#define DL7_NORMAL_MODE_MASK 0x1 +#define DL7_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL7_HALIGN_SFT 4 +#define DL7_HALIGN_MASK 0x1 +#define DL7_HALIGN_MASK_SFT (0x1 << 4) +#define DL7_HD_MODE_SFT 0 +#define DL7_HD_MODE_MASK 0x3 +#define DL7_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL8_CON0 */ +#define DL8_MODE_SFT 24 +#define DL8_MODE_MASK 0xf +#define DL8_MODE_MASK_SFT (0xf << 24) +#define DL8_MINLEN_SFT 20 +#define DL8_MINLEN_MASK 0xf +#define DL8_MINLEN_MASK_SFT (0xf << 20) +#define DL8_MAXLEN_SFT 16 +#define DL8_MAXLEN_MASK 0xf +#define DL8_MAXLEN_MASK_SFT (0xf << 16) +#define DL8_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL8_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL8_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL8_PBUF_SIZE_SFT 12 +#define DL8_PBUF_SIZE_MASK 0x3 +#define DL8_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL8_MONO_SFT 8 +#define DL8_MONO_MASK 0x1 +#define DL8_MONO_MASK_SFT (0x1 << 8) +#define DL8_NORMAL_MODE_SFT 5 +#define DL8_NORMAL_MODE_MASK 0x1 +#define DL8_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL8_HALIGN_SFT 4 +#define DL8_HALIGN_MASK 0x1 +#define DL8_HALIGN_MASK_SFT (0x1 << 4) +#define DL8_HD_MODE_SFT 0 +#define DL8_HD_MODE_MASK 0x3 +#define DL8_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL12_CON0 */ +#define DL12_MODE_SFT 24 +#define DL12_MODE_MASK 0xf +#define DL12_MODE_MASK_SFT (0xf << 24) +#define DL12_MINLEN_SFT 20 +#define DL12_MINLEN_MASK 0xf +#define DL12_MINLEN_MASK_SFT (0xf << 20) +#define DL12_MAXLEN_SFT 16 +#define DL12_MAXLEN_MASK 0xf +#define DL12_MAXLEN_MASK_SFT (0xf << 16) +#define DL12_SW_CLEAR_BUF_EMPTY_SFT 15 +#define DL12_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL12_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define DL12_PBUF_SIZE_SFT 12 +#define DL12_PBUF_SIZE_MASK 0x3 +#define DL12_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define DL12_4CH_EN_SFT 11 +#define DL12_4CH_EN_MASK 0x1 +#define DL12_4CH_EN_MASK_SFT (0x1 << 11) +#define DL12_MONO_SFT 8 +#define DL12_MONO_MASK 0x1 +#define DL12_MONO_MASK_SFT (0x1 << 8) +#define DL12_NORMAL_MODE_SFT 5 +#define DL12_NORMAL_MODE_MASK 0x1 +#define DL12_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DL12_HALIGN_SFT 4 +#define DL12_HALIGN_MASK 0x1 +#define DL12_HALIGN_MASK_SFT (0x1 << 4) +#define DL12_HD_MODE_SFT 0 +#define DL12_HD_MODE_MASK 0x3 +#define DL12_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_AWB_CON0 */ +#define AWB_MODE_SFT 24 +#define AWB_MODE_MASK 0xf +#define AWB_MODE_MASK_SFT (0xf << 24) +#define AWB_SW_CLEAR_BUF_FULL_SFT 15 +#define AWB_SW_CLEAR_BUF_FULL_MASK 0x1 +#define AWB_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define AWB_R_MONO_SFT 9 +#define AWB_R_MONO_MASK 0x1 +#define AWB_R_MONO_MASK_SFT (0x1 << 9) +#define AWB_MONO_SFT 8 +#define AWB_MONO_MASK 0x1 +#define AWB_MONO_MASK_SFT (0x1 << 8) +#define AWB_WR_SIGN_SFT 6 +#define AWB_WR_SIGN_MASK 0x1 +#define AWB_WR_SIGN_MASK_SFT (0x1 << 6) +#define AWB_NORMAL_MODE_SFT 5 +#define AWB_NORMAL_MODE_MASK 0x1 +#define AWB_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define AWB_HALIGN_SFT 4 +#define AWB_HALIGN_MASK 0x1 +#define AWB_HALIGN_MASK_SFT (0x1 << 4) +#define AWB_HD_MODE_SFT 0 +#define AWB_HD_MODE_MASK 0x3 +#define AWB_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_AWB2_CON0 */ +#define AWB2_MODE_SFT 24 +#define AWB2_MODE_MASK 0xf +#define AWB2_MODE_MASK_SFT (0xf << 24) +#define AWB2_SW_CLEAR_BUF_FULL_SFT 15 +#define AWB2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define AWB2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define AWB2_R_MONO_SFT 9 +#define AWB2_R_MONO_MASK 0x1 +#define AWB2_R_MONO_MASK_SFT (0x1 << 9) +#define AWB2_MONO_SFT 8 +#define AWB2_MONO_MASK 0x1 +#define AWB2_MONO_MASK_SFT (0x1 << 8) +#define AWB2_WR_SIGN_SFT 6 +#define AWB2_WR_SIGN_MASK 0x1 +#define AWB2_WR_SIGN_MASK_SFT (0x1 << 6) +#define AWB2_NORMAL_MODE_SFT 5 +#define AWB2_NORMAL_MODE_MASK 0x1 +#define AWB2_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define AWB2_HALIGN_SFT 4 +#define AWB2_HALIGN_MASK 0x1 +#define AWB2_HALIGN_MASK_SFT (0x1 << 4) +#define AWB2_HD_MODE_SFT 0 +#define AWB2_HD_MODE_MASK 0x3 +#define AWB2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL_CON0 */ +#define VUL_MODE_SFT 24 +#define VUL_MODE_MASK 0xf +#define VUL_MODE_MASK_SFT (0xf << 24) +#define VUL_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL_R_MONO_SFT 9 +#define VUL_R_MONO_MASK 0x1 +#define VUL_R_MONO_MASK_SFT (0x1 << 9) +#define VUL_MONO_SFT 8 +#define VUL_MONO_MASK 0x1 +#define VUL_MONO_MASK_SFT (0x1 << 8) +#define VUL_WR_SIGN_SFT 6 +#define VUL_WR_SIGN_MASK 0x1 +#define VUL_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL_NORMAL_MODE_SFT 5 +#define VUL_NORMAL_MODE_MASK 0x1 +#define VUL_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL_HALIGN_SFT 4 +#define VUL_HALIGN_MASK 0x1 +#define VUL_HALIGN_MASK_SFT (0x1 << 4) +#define VUL_HD_MODE_SFT 0 +#define VUL_HD_MODE_MASK 0x3 +#define VUL_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL12_CON0 */ +#define VUL12_MODE_SFT 24 +#define VUL12_MODE_MASK 0xf +#define VUL12_MODE_MASK_SFT (0xf << 24) +#define VUL12_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL12_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL12_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL12_4CH_EN_SFT 11 +#define VUL12_4CH_EN_MASK 0x1 +#define VUL12_4CH_EN_MASK_SFT (0x1 << 11) +#define VUL12_R_MONO_SFT 9 +#define VUL12_R_MONO_MASK 0x1 +#define VUL12_R_MONO_MASK_SFT (0x1 << 9) +#define VUL12_MONO_SFT 8 +#define VUL12_MONO_MASK 0x1 +#define VUL12_MONO_MASK_SFT (0x1 << 8) +#define VUL12_WR_SIGN_SFT 6 +#define VUL12_WR_SIGN_MASK 0x1 +#define VUL12_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL12_NORMAL_MODE_SFT 5 +#define VUL12_NORMAL_MODE_MASK 0x1 +#define VUL12_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL12_HALIGN_SFT 4 +#define VUL12_HALIGN_MASK 0x1 +#define VUL12_HALIGN_MASK_SFT (0x1 << 4) +#define VUL12_HD_MODE_SFT 0 +#define VUL12_HD_MODE_MASK 0x3 +#define VUL12_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL2_CON0 */ +#define VUL2_MODE_SFT 24 +#define VUL2_MODE_MASK 0xf +#define VUL2_MODE_MASK_SFT (0xf << 24) +#define VUL2_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL2_R_MONO_SFT 9 +#define VUL2_R_MONO_MASK 0x1 +#define VUL2_R_MONO_MASK_SFT (0x1 << 9) +#define VUL2_MONO_SFT 8 +#define VUL2_MONO_MASK 0x1 +#define VUL2_MONO_MASK_SFT (0x1 << 8) +#define VUL2_WR_SIGN_SFT 6 +#define VUL2_WR_SIGN_MASK 0x1 +#define VUL2_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL2_NORMAL_MODE_SFT 5 +#define VUL2_NORMAL_MODE_MASK 0x1 +#define VUL2_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL2_HALIGN_SFT 4 +#define VUL2_HALIGN_MASK 0x1 +#define VUL2_HALIGN_MASK_SFT (0x1 << 4) +#define VUL2_HD_MODE_SFT 0 +#define VUL2_HD_MODE_MASK 0x3 +#define VUL2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL3_CON0 */ +#define VUL3_MODE_SFT 24 +#define VUL3_MODE_MASK 0xf +#define VUL3_MODE_MASK_SFT (0xf << 24) +#define VUL3_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL3_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL3_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL3_R_MONO_SFT 9 +#define VUL3_R_MONO_MASK 0x1 +#define VUL3_R_MONO_MASK_SFT (0x1 << 9) +#define VUL3_MONO_SFT 8 +#define VUL3_MONO_MASK 0x1 +#define VUL3_MONO_MASK_SFT (0x1 << 8) +#define VUL3_WR_SIGN_SFT 6 +#define VUL3_WR_SIGN_MASK 0x1 +#define VUL3_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL3_NORMAL_MODE_SFT 5 +#define VUL3_NORMAL_MODE_MASK 0x1 +#define VUL3_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL3_HALIGN_SFT 4 +#define VUL3_HALIGN_MASK 0x1 +#define VUL3_HALIGN_MASK_SFT (0x1 << 4) +#define VUL3_HD_MODE_SFT 0 +#define VUL3_HD_MODE_MASK 0x3 +#define VUL3_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL4_CON0 */ +#define VUL4_MODE_SFT 24 +#define VUL4_MODE_MASK 0xf +#define VUL4_MODE_MASK_SFT (0xf << 24) +#define VUL4_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL4_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL4_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL4_R_MONO_SFT 9 +#define VUL4_R_MONO_MASK 0x1 +#define VUL4_R_MONO_MASK_SFT (0x1 << 9) +#define VUL4_MONO_SFT 8 +#define VUL4_MONO_MASK 0x1 +#define VUL4_MONO_MASK_SFT (0x1 << 8) +#define VUL4_WR_SIGN_SFT 6 +#define VUL4_WR_SIGN_MASK 0x1 +#define VUL4_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL4_NORMAL_MODE_SFT 5 +#define VUL4_NORMAL_MODE_MASK 0x1 +#define VUL4_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL4_HALIGN_SFT 4 +#define VUL4_HALIGN_MASK 0x1 +#define VUL4_HALIGN_MASK_SFT (0x1 << 4) +#define VUL4_HD_MODE_SFT 0 +#define VUL4_HD_MODE_MASK 0x3 +#define VUL4_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL5_CON0 */ +#define VUL5_MODE_SFT 24 +#define VUL5_MODE_MASK 0xf +#define VUL5_MODE_MASK_SFT (0xf << 24) +#define VUL5_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL5_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL5_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL5_R_MONO_SFT 9 +#define VUL5_R_MONO_MASK 0x1 +#define VUL5_R_MONO_MASK_SFT (0x1 << 9) +#define VUL5_MONO_SFT 8 +#define VUL5_MONO_MASK 0x1 +#define VUL5_MONO_MASK_SFT (0x1 << 8) +#define VUL5_WR_SIGN_SFT 6 +#define VUL5_WR_SIGN_MASK 0x1 +#define VUL5_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL5_NORMAL_MODE_SFT 5 +#define VUL5_NORMAL_MODE_MASK 0x1 +#define VUL5_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL5_HALIGN_SFT 4 +#define VUL5_HALIGN_MASK 0x1 +#define VUL5_HALIGN_MASK_SFT (0x1 << 4) +#define VUL5_HD_MODE_SFT 0 +#define VUL5_HD_MODE_MASK 0x3 +#define VUL5_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL6_CON0 */ +#define VUL6_MODE_SFT 24 +#define VUL6_MODE_MASK 0xf +#define VUL6_MODE_MASK_SFT (0xf << 24) +#define VUL6_SW_CLEAR_BUF_FULL_SFT 15 +#define VUL6_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL6_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define VUL6_R_MONO_SFT 9 +#define VUL6_R_MONO_MASK 0x1 +#define VUL6_R_MONO_MASK_SFT (0x1 << 9) +#define VUL6_MONO_SFT 8 +#define VUL6_MONO_MASK 0x1 +#define VUL6_MONO_MASK_SFT (0x1 << 8) +#define VUL6_WR_SIGN_SFT 6 +#define VUL6_WR_SIGN_MASK 0x1 +#define VUL6_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL6_NORMAL_MODE_SFT 5 +#define VUL6_NORMAL_MODE_MASK 0x1 +#define VUL6_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define VUL6_HALIGN_SFT 4 +#define VUL6_HALIGN_MASK 0x1 +#define VUL6_HALIGN_MASK_SFT (0x1 << 4) +#define VUL6_HD_MODE_SFT 0 +#define VUL6_HD_MODE_MASK 0x3 +#define VUL6_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DAI_CON0 */ +#define DAI_MODE_SFT 24 +#define DAI_MODE_MASK 0x3 +#define DAI_MODE_MASK_SFT (0x3 << 24) +#define DAI_SW_CLEAR_BUF_FULL_SFT 15 +#define DAI_SW_CLEAR_BUF_FULL_MASK 0x1 +#define DAI_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define DAI_DUPLICATE_WR_SFT 10 +#define DAI_DUPLICATE_WR_MASK 0x1 +#define DAI_DUPLICATE_WR_MASK_SFT (0x1 << 10) +#define DAI_MONO_SFT 8 +#define DAI_MONO_MASK 0x1 +#define DAI_MONO_MASK_SFT (0x1 << 8) +#define DAI_WR_SIGN_SFT 6 +#define DAI_WR_SIGN_MASK 0x1 +#define DAI_WR_SIGN_MASK_SFT (0x1 << 6) +#define DAI_NORMAL_MODE_SFT 5 +#define DAI_NORMAL_MODE_MASK 0x1 +#define DAI_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DAI_HALIGN_SFT 4 +#define DAI_HALIGN_MASK 0x1 +#define DAI_HALIGN_MASK_SFT (0x1 << 4) +#define DAI_HD_MODE_SFT 0 +#define DAI_HD_MODE_MASK 0x3 +#define DAI_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_MOD_DAI_CON0 */ +#define MOD_DAI_MODE_SFT 24 +#define MOD_DAI_MODE_MASK 0x3 +#define MOD_DAI_MODE_MASK_SFT (0x3 << 24) +#define MOD_DAI_SW_CLEAR_BUF_FULL_SFT 15 +#define MOD_DAI_SW_CLEAR_BUF_FULL_MASK 0x1 +#define MOD_DAI_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define MOD_DAI_DUPLICATE_WR_SFT 10 +#define MOD_DAI_DUPLICATE_WR_MASK 0x1 +#define MOD_DAI_DUPLICATE_WR_MASK_SFT (0x1 << 10) +#define MOD_DAI_MONO_SFT 8 +#define MOD_DAI_MONO_MASK 0x1 +#define MOD_DAI_MONO_MASK_SFT (0x1 << 8) +#define MOD_DAI_WR_SIGN_SFT 6 +#define MOD_DAI_WR_SIGN_MASK 0x1 +#define MOD_DAI_WR_SIGN_MASK_SFT (0x1 << 6) +#define MOD_DAI_NORMAL_MODE_SFT 5 +#define MOD_DAI_NORMAL_MODE_MASK 0x1 +#define MOD_DAI_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define MOD_DAI_HALIGN_SFT 4 +#define MOD_DAI_HALIGN_MASK 0x1 +#define MOD_DAI_HALIGN_MASK_SFT (0x1 << 4) +#define MOD_DAI_HD_MODE_SFT 0 +#define MOD_DAI_HD_MODE_MASK 0x3 +#define MOD_DAI_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DAI2_CON0 */ +#define DAI2_MODE_SFT 24 +#define DAI2_MODE_MASK 0xf +#define DAI2_MODE_MASK_SFT (0xf << 24) +#define DAI2_SW_CLEAR_BUF_FULL_SFT 15 +#define DAI2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define DAI2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 15) +#define DAI2_DUPLICATE_WR_SFT 10 +#define DAI2_DUPLICATE_WR_MASK 0x1 +#define DAI2_DUPLICATE_WR_MASK_SFT (0x1 << 10) +#define DAI2_MONO_SFT 8 +#define DAI2_MONO_MASK 0x1 +#define DAI2_MONO_MASK_SFT (0x1 << 8) +#define DAI2_WR_SIGN_SFT 6 +#define DAI2_WR_SIGN_MASK 0x1 +#define DAI2_WR_SIGN_MASK_SFT (0x1 << 6) +#define DAI2_NORMAL_MODE_SFT 5 +#define DAI2_NORMAL_MODE_MASK 0x1 +#define DAI2_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define DAI2_HALIGN_SFT 4 +#define DAI2_HALIGN_MASK 0x1 +#define DAI2_HALIGN_MASK_SFT (0x1 << 4) +#define DAI2_HD_MODE_SFT 0 +#define DAI2_HD_MODE_MASK 0x3 +#define DAI2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_MEMIF_CON0 */ +#define CPU_COMPACT_MODE_SFT 2 +#define CPU_COMPACT_MODE_MASK 0x1 +#define CPU_COMPACT_MODE_MASK_SFT (0x1 << 2) +#define CPU_HD_ALIGN_SFT 1 +#define CPU_HD_ALIGN_MASK 0x1 +#define CPU_HD_ALIGN_MASK_SFT (0x1 << 1) +#define SYSRAM_SIGN_SFT 0 +#define SYSRAM_SIGN_MASK 0x1 +#define SYSRAM_SIGN_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_CON0 */ +#define IRQ31_MCU_ON_SFT 31 +#define IRQ31_MCU_ON_MASK 0x1 +#define IRQ31_MCU_ON_MASK_SFT (0x1 << 31) +#define IRQ26_MCU_ON_SFT 26 +#define IRQ26_MCU_ON_MASK 0x1 +#define IRQ26_MCU_ON_MASK_SFT (0x1 << 26) +#define IRQ25_MCU_ON_SFT 25 +#define IRQ25_MCU_ON_MASK 0x1 +#define IRQ25_MCU_ON_MASK_SFT (0x1 << 25) +#define IRQ24_MCU_ON_SFT 24 +#define IRQ24_MCU_ON_MASK 0x1 +#define IRQ24_MCU_ON_MASK_SFT (0x1 << 24) +#define IRQ23_MCU_ON_SFT 23 +#define IRQ23_MCU_ON_MASK 0x1 +#define IRQ23_MCU_ON_MASK_SFT (0x1 << 23) +#define IRQ22_MCU_ON_SFT 22 +#define IRQ22_MCU_ON_MASK 0x1 +#define IRQ22_MCU_ON_MASK_SFT (0x1 << 22) +#define IRQ21_MCU_ON_SFT 21 +#define IRQ21_MCU_ON_MASK 0x1 +#define IRQ21_MCU_ON_MASK_SFT (0x1 << 21) +#define IRQ20_MCU_ON_SFT 20 +#define IRQ20_MCU_ON_MASK 0x1 +#define IRQ20_MCU_ON_MASK_SFT (0x1 << 20) +#define IRQ19_MCU_ON_SFT 19 +#define IRQ19_MCU_ON_MASK 0x1 +#define IRQ19_MCU_ON_MASK_SFT (0x1 << 19) +#define IRQ18_MCU_ON_SFT 18 +#define IRQ18_MCU_ON_MASK 0x1 +#define IRQ18_MCU_ON_MASK_SFT (0x1 << 18) +#define IRQ17_MCU_ON_SFT 17 +#define IRQ17_MCU_ON_MASK 0x1 +#define IRQ17_MCU_ON_MASK_SFT (0x1 << 17) +#define IRQ16_MCU_ON_SFT 16 +#define IRQ16_MCU_ON_MASK 0x1 +#define IRQ16_MCU_ON_MASK_SFT (0x1 << 16) +#define IRQ15_MCU_ON_SFT 15 +#define IRQ15_MCU_ON_MASK 0x1 +#define IRQ15_MCU_ON_MASK_SFT (0x1 << 15) +#define IRQ14_MCU_ON_SFT 14 +#define IRQ14_MCU_ON_MASK 0x1 +#define IRQ14_MCU_ON_MASK_SFT (0x1 << 14) +#define IRQ13_MCU_ON_SFT 13 +#define IRQ13_MCU_ON_MASK 0x1 +#define IRQ13_MCU_ON_MASK_SFT (0x1 << 13) +#define IRQ12_MCU_ON_SFT 12 +#define IRQ12_MCU_ON_MASK 0x1 +#define IRQ12_MCU_ON_MASK_SFT (0x1 << 12) +#define IRQ11_MCU_ON_SFT 11 +#define IRQ11_MCU_ON_MASK 0x1 +#define IRQ11_MCU_ON_MASK_SFT (0x1 << 11) +#define IRQ10_MCU_ON_SFT 10 +#define IRQ10_MCU_ON_MASK 0x1 +#define IRQ10_MCU_ON_MASK_SFT (0x1 << 10) +#define IRQ9_MCU_ON_SFT 9 +#define IRQ9_MCU_ON_MASK 0x1 +#define IRQ9_MCU_ON_MASK_SFT (0x1 << 9) +#define IRQ8_MCU_ON_SFT 8 +#define IRQ8_MCU_ON_MASK 0x1 +#define IRQ8_MCU_ON_MASK_SFT (0x1 << 8) +#define IRQ7_MCU_ON_SFT 7 +#define IRQ7_MCU_ON_MASK 0x1 +#define IRQ7_MCU_ON_MASK_SFT (0x1 << 7) +#define IRQ6_MCU_ON_SFT 6 +#define IRQ6_MCU_ON_MASK 0x1 +#define IRQ6_MCU_ON_MASK_SFT (0x1 << 6) +#define IRQ5_MCU_ON_SFT 5 +#define IRQ5_MCU_ON_MASK 0x1 +#define IRQ5_MCU_ON_MASK_SFT (0x1 << 5) +#define IRQ4_MCU_ON_SFT 4 +#define IRQ4_MCU_ON_MASK 0x1 +#define IRQ4_MCU_ON_MASK_SFT (0x1 << 4) +#define IRQ3_MCU_ON_SFT 3 +#define IRQ3_MCU_ON_MASK 0x1 +#define IRQ3_MCU_ON_MASK_SFT (0x1 << 3) +#define IRQ2_MCU_ON_SFT 2 +#define IRQ2_MCU_ON_MASK 0x1 +#define IRQ2_MCU_ON_MASK_SFT (0x1 << 2) +#define IRQ1_MCU_ON_SFT 1 +#define IRQ1_MCU_ON_MASK 0x1 +#define IRQ1_MCU_ON_MASK_SFT (0x1 << 1) +#define IRQ0_MCU_ON_SFT 0 +#define IRQ0_MCU_ON_MASK 0x1 +#define IRQ0_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_CON1 */ +#define IRQ7_MCU_MODE_SFT 28 +#define IRQ7_MCU_MODE_MASK 0xf +#define IRQ7_MCU_MODE_MASK_SFT (0xf << 28) +#define IRQ6_MCU_MODE_SFT 24 +#define IRQ6_MCU_MODE_MASK 0xf +#define IRQ6_MCU_MODE_MASK_SFT (0xf << 24) +#define IRQ5_MCU_MODE_SFT 20 +#define IRQ5_MCU_MODE_MASK 0xf +#define IRQ5_MCU_MODE_MASK_SFT (0xf << 20) +#define IRQ4_MCU_MODE_SFT 16 +#define IRQ4_MCU_MODE_MASK 0xf +#define IRQ4_MCU_MODE_MASK_SFT (0xf << 16) +#define IRQ3_MCU_MODE_SFT 12 +#define IRQ3_MCU_MODE_MASK 0xf +#define IRQ3_MCU_MODE_MASK_SFT (0xf << 12) +#define IRQ2_MCU_MODE_SFT 8 +#define IRQ2_MCU_MODE_MASK 0xf +#define IRQ2_MCU_MODE_MASK_SFT (0xf << 8) +#define IRQ1_MCU_MODE_SFT 4 +#define IRQ1_MCU_MODE_MASK 0xf +#define IRQ1_MCU_MODE_MASK_SFT (0xf << 4) +#define IRQ0_MCU_MODE_SFT 0 +#define IRQ0_MCU_MODE_MASK 0xf +#define IRQ0_MCU_MODE_MASK_SFT (0xf << 0) + +/* AFE_IRQ_MCU_CON2 */ +#define IRQ15_MCU_MODE_SFT 28 +#define IRQ15_MCU_MODE_MASK 0xf +#define IRQ15_MCU_MODE_MASK_SFT (0xf << 28) +#define IRQ14_MCU_MODE_SFT 24 +#define IRQ14_MCU_MODE_MASK 0xf +#define IRQ14_MCU_MODE_MASK_SFT (0xf << 24) +#define IRQ13_MCU_MODE_SFT 20 +#define IRQ13_MCU_MODE_MASK 0xf +#define IRQ13_MCU_MODE_MASK_SFT (0xf << 20) +#define IRQ12_MCU_MODE_SFT 16 +#define IRQ12_MCU_MODE_MASK 0xf +#define IRQ12_MCU_MODE_MASK_SFT (0xf << 16) +#define IRQ11_MCU_MODE_SFT 12 +#define IRQ11_MCU_MODE_MASK 0xf +#define IRQ11_MCU_MODE_MASK_SFT (0xf << 12) +#define IRQ10_MCU_MODE_SFT 8 +#define IRQ10_MCU_MODE_MASK 0xf +#define IRQ10_MCU_MODE_MASK_SFT (0xf << 8) +#define IRQ9_MCU_MODE_SFT 4 +#define IRQ9_MCU_MODE_MASK 0xf +#define IRQ9_MCU_MODE_MASK_SFT (0xf << 4) +#define IRQ8_MCU_MODE_SFT 0 +#define IRQ8_MCU_MODE_MASK 0xf +#define IRQ8_MCU_MODE_MASK_SFT (0xf << 0) + +/* AFE_IRQ_MCU_CON3 */ +#define IRQ23_MCU_MODE_SFT 28 +#define IRQ23_MCU_MODE_MASK 0xf +#define IRQ23_MCU_MODE_MASK_SFT (0xf << 28) +#define IRQ22_MCU_MODE_SFT 24 +#define IRQ22_MCU_MODE_MASK 0xf +#define IRQ22_MCU_MODE_MASK_SFT (0xf << 24) +#define IRQ21_MCU_MODE_SFT 20 +#define IRQ21_MCU_MODE_MASK 0xf +#define IRQ21_MCU_MODE_MASK_SFT (0xf << 20) +#define IRQ20_MCU_MODE_SFT 16 +#define IRQ20_MCU_MODE_MASK 0xf +#define IRQ20_MCU_MODE_MASK_SFT (0xf << 16) +#define IRQ19_MCU_MODE_SFT 12 +#define IRQ19_MCU_MODE_MASK 0xf +#define IRQ19_MCU_MODE_MASK_SFT (0xf << 12) +#define IRQ18_MCU_MODE_SFT 8 +#define IRQ18_MCU_MODE_MASK 0xf +#define IRQ18_MCU_MODE_MASK_SFT (0xf << 8) +#define IRQ17_MCU_MODE_SFT 4 +#define IRQ17_MCU_MODE_MASK 0xf +#define IRQ17_MCU_MODE_MASK_SFT (0xf << 4) +#define IRQ16_MCU_MODE_SFT 0 +#define IRQ16_MCU_MODE_MASK 0xf +#define IRQ16_MCU_MODE_MASK_SFT (0xf << 0) + +/* AFE_IRQ_MCU_CON4 */ +#define IRQ26_MCU_MODE_SFT 8 +#define IRQ26_MCU_MODE_MASK 0xf +#define IRQ26_MCU_MODE_MASK_SFT (0xf << 8) +#define IRQ25_MCU_MODE_SFT 4 +#define IRQ25_MCU_MODE_MASK 0xf +#define IRQ25_MCU_MODE_MASK_SFT (0xf << 4) +#define IRQ24_MCU_MODE_SFT 0 +#define IRQ24_MCU_MODE_MASK 0xf +#define IRQ24_MCU_MODE_MASK_SFT (0xf << 0) + +/* AFE_IRQ_MCU_CLR */ +#define IRQ31_MCU_CLR_SFT 31 +#define IRQ31_MCU_CLR_MASK 0x1 +#define IRQ31_MCU_CLR_MASK_SFT (0x1 << 31) +#define IRQ26_MCU_CLR_SFT 26 +#define IRQ26_MCU_CLR_MASK 0x1 +#define IRQ26_MCU_CLR_MASK_SFT (0x1 << 26) +#define IRQ25_MCU_CLR_SFT 25 +#define IRQ25_MCU_CLR_MASK 0x1 +#define IRQ25_MCU_CLR_MASK_SFT (0x1 << 25) +#define IRQ24_MCU_CLR_SFT 24 +#define IRQ24_MCU_CLR_MASK 0x1 +#define IRQ24_MCU_CLR_MASK_SFT (0x1 << 24) +#define IRQ23_MCU_CLR_SFT 23 +#define IRQ23_MCU_CLR_MASK 0x1 +#define IRQ23_MCU_CLR_MASK_SFT (0x1 << 23) +#define IRQ22_MCU_CLR_SFT 22 +#define IRQ22_MCU_CLR_MASK 0x1 +#define IRQ22_MCU_CLR_MASK_SFT (0x1 << 22) +#define IRQ21_MCU_CLR_SFT 21 +#define IRQ21_MCU_CLR_MASK 0x1 +#define IRQ21_MCU_CLR_MASK_SFT (0x1 << 21) +#define IRQ20_MCU_CLR_SFT 20 +#define IRQ20_MCU_CLR_MASK 0x1 +#define IRQ20_MCU_CLR_MASK_SFT (0x1 << 20) +#define IRQ19_MCU_CLR_SFT 19 +#define IRQ19_MCU_CLR_MASK 0x1 +#define IRQ19_MCU_CLR_MASK_SFT (0x1 << 19) +#define IRQ18_MCU_CLR_SFT 18 +#define IRQ18_MCU_CLR_MASK 0x1 +#define IRQ18_MCU_CLR_MASK_SFT (0x1 << 18) +#define IRQ17_MCU_CLR_SFT 17 +#define IRQ17_MCU_CLR_MASK 0x1 +#define IRQ17_MCU_CLR_MASK_SFT (0x1 << 17) +#define IRQ16_MCU_CLR_SFT 16 +#define IRQ16_MCU_CLR_MASK 0x1 +#define IRQ16_MCU_CLR_MASK_SFT (0x1 << 16) +#define IRQ15_MCU_CLR_SFT 15 +#define IRQ15_MCU_CLR_MASK 0x1 +#define IRQ15_MCU_CLR_MASK_SFT (0x1 << 15) +#define IRQ14_MCU_CLR_SFT 14 +#define IRQ14_MCU_CLR_MASK 0x1 +#define IRQ14_MCU_CLR_MASK_SFT (0x1 << 14) +#define IRQ13_MCU_CLR_SFT 13 +#define IRQ13_MCU_CLR_MASK 0x1 +#define IRQ13_MCU_CLR_MASK_SFT (0x1 << 13) +#define IRQ12_MCU_CLR_SFT 12 +#define IRQ12_MCU_CLR_MASK 0x1 +#define IRQ12_MCU_CLR_MASK_SFT (0x1 << 12) +#define IRQ11_MCU_CLR_SFT 11 +#define IRQ11_MCU_CLR_MASK 0x1 +#define IRQ11_MCU_CLR_MASK_SFT (0x1 << 11) +#define IRQ10_MCU_CLR_SFT 10 +#define IRQ10_MCU_CLR_MASK 0x1 +#define IRQ10_MCU_CLR_MASK_SFT (0x1 << 10) +#define IRQ9_MCU_CLR_SFT 9 +#define IRQ9_MCU_CLR_MASK 0x1 +#define IRQ9_MCU_CLR_MASK_SFT (0x1 << 9) +#define IRQ8_MCU_CLR_SFT 8 +#define IRQ8_MCU_CLR_MASK 0x1 +#define IRQ8_MCU_CLR_MASK_SFT (0x1 << 8) +#define IRQ7_MCU_CLR_SFT 7 +#define IRQ7_MCU_CLR_MASK 0x1 +#define IRQ7_MCU_CLR_MASK_SFT (0x1 << 7) +#define IRQ6_MCU_CLR_SFT 6 +#define IRQ6_MCU_CLR_MASK 0x1 +#define IRQ6_MCU_CLR_MASK_SFT (0x1 << 6) +#define IRQ5_MCU_CLR_SFT 5 +#define IRQ5_MCU_CLR_MASK 0x1 +#define IRQ5_MCU_CLR_MASK_SFT (0x1 << 5) +#define IRQ4_MCU_CLR_SFT 4 +#define IRQ4_MCU_CLR_MASK 0x1 +#define IRQ4_MCU_CLR_MASK_SFT (0x1 << 4) +#define IRQ3_MCU_CLR_SFT 3 +#define IRQ3_MCU_CLR_MASK 0x1 +#define IRQ3_MCU_CLR_MASK_SFT (0x1 << 3) +#define IRQ2_MCU_CLR_SFT 2 +#define IRQ2_MCU_CLR_MASK 0x1 +#define IRQ2_MCU_CLR_MASK_SFT (0x1 << 2) +#define IRQ1_MCU_CLR_SFT 1 +#define IRQ1_MCU_CLR_MASK 0x1 +#define IRQ1_MCU_CLR_MASK_SFT (0x1 << 1) +#define IRQ0_MCU_CLR_SFT 0 +#define IRQ0_MCU_CLR_MASK 0x1 +#define IRQ0_MCU_CLR_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_EN */ +#define IRQ31_MCU_EN_SFT 31 +#define IRQ30_MCU_EN_SFT 30 +#define IRQ29_MCU_EN_SFT 29 +#define IRQ28_MCU_EN_SFT 28 +#define IRQ27_MCU_EN_SFT 27 +#define IRQ26_MCU_EN_SFT 26 +#define IRQ25_MCU_EN_SFT 25 +#define IRQ24_MCU_EN_SFT 24 +#define IRQ23_MCU_EN_SFT 23 +#define IRQ22_MCU_EN_SFT 22 +#define IRQ21_MCU_EN_SFT 21 +#define IRQ20_MCU_EN_SFT 20 +#define IRQ19_MCU_EN_SFT 19 +#define IRQ18_MCU_EN_SFT 18 +#define IRQ17_MCU_EN_SFT 17 +#define IRQ16_MCU_EN_SFT 16 +#define IRQ15_MCU_EN_SFT 15 +#define IRQ14_MCU_EN_SFT 14 +#define IRQ13_MCU_EN_SFT 13 +#define IRQ12_MCU_EN_SFT 12 +#define IRQ11_MCU_EN_SFT 11 +#define IRQ10_MCU_EN_SFT 10 +#define IRQ9_MCU_EN_SFT 9 +#define IRQ8_MCU_EN_SFT 8 +#define IRQ7_MCU_EN_SFT 7 +#define IRQ6_MCU_EN_SFT 6 +#define IRQ5_MCU_EN_SFT 5 +#define IRQ4_MCU_EN_SFT 4 +#define IRQ3_MCU_EN_SFT 3 +#define IRQ2_MCU_EN_SFT 2 +#define IRQ1_MCU_EN_SFT 1 +#define IRQ0_MCU_EN_SFT 0 + +/* AFE_IRQ_MCU_SCP_EN */ +#define IRQ31_MCU_SCP_EN_SFT 31 +#define IRQ30_MCU_SCP_EN_SFT 30 +#define IRQ29_MCU_SCP_EN_SFT 29 +#define IRQ28_MCU_SCP_EN_SFT 28 +#define IRQ27_MCU_SCP_EN_SFT 27 +#define IRQ26_MCU_SCP_EN_SFT 26 +#define IRQ25_MCU_SCP_EN_SFT 25 +#define IRQ24_MCU_SCP_EN_SFT 24 +#define IRQ23_MCU_SCP_EN_SFT 23 +#define IRQ22_MCU_SCP_EN_SFT 22 +#define IRQ21_MCU_SCP_EN_SFT 21 +#define IRQ20_MCU_SCP_EN_SFT 20 +#define IRQ19_MCU_SCP_EN_SFT 19 +#define IRQ18_MCU_SCP_EN_SFT 18 +#define IRQ17_MCU_SCP_EN_SFT 17 +#define IRQ16_MCU_SCP_EN_SFT 16 +#define IRQ15_MCU_SCP_EN_SFT 15 +#define IRQ14_MCU_SCP_EN_SFT 14 +#define IRQ13_MCU_SCP_EN_SFT 13 +#define IRQ12_MCU_SCP_EN_SFT 12 +#define IRQ11_MCU_SCP_EN_SFT 11 +#define IRQ10_MCU_SCP_EN_SFT 10 +#define IRQ9_MCU_SCP_EN_SFT 9 +#define IRQ8_MCU_SCP_EN_SFT 8 +#define IRQ7_MCU_SCP_EN_SFT 7 +#define IRQ6_MCU_SCP_EN_SFT 6 +#define IRQ5_MCU_SCP_EN_SFT 5 +#define IRQ4_MCU_SCP_EN_SFT 4 +#define IRQ3_MCU_SCP_EN_SFT 3 +#define IRQ2_MCU_SCP_EN_SFT 2 +#define IRQ1_MCU_SCP_EN_SFT 1 +#define IRQ0_MCU_SCP_EN_SFT 0 + +/* AFE_IRQ_MCU_DSP_EN */ +#define IRQ31_MCU_DSP_EN_SFT 31 +#define IRQ30_MCU_DSP_EN_SFT 30 +#define IRQ29_MCU_DSP_EN_SFT 29 +#define IRQ28_MCU_DSP_EN_SFT 28 +#define IRQ27_MCU_DSP_EN_SFT 27 +#define IRQ26_MCU_DSP_EN_SFT 26 +#define IRQ25_MCU_DSP_EN_SFT 25 +#define IRQ24_MCU_DSP_EN_SFT 24 +#define IRQ23_MCU_DSP_EN_SFT 23 +#define IRQ22_MCU_DSP_EN_SFT 22 +#define IRQ21_MCU_DSP_EN_SFT 21 +#define IRQ20_MCU_DSP_EN_SFT 20 +#define IRQ19_MCU_DSP_EN_SFT 19 +#define IRQ18_MCU_DSP_EN_SFT 18 +#define IRQ17_MCU_DSP_EN_SFT 17 +#define IRQ16_MCU_DSP_EN_SFT 16 +#define IRQ15_MCU_DSP_EN_SFT 15 +#define IRQ14_MCU_DSP_EN_SFT 14 +#define IRQ13_MCU_DSP_EN_SFT 13 +#define IRQ12_MCU_DSP_EN_SFT 12 +#define IRQ11_MCU_DSP_EN_SFT 11 +#define IRQ10_MCU_DSP_EN_SFT 10 +#define IRQ9_MCU_DSP_EN_SFT 9 +#define IRQ8_MCU_DSP_EN_SFT 8 +#define IRQ7_MCU_DSP_EN_SFT 7 +#define IRQ6_MCU_DSP_EN_SFT 6 +#define IRQ5_MCU_DSP_EN_SFT 5 +#define IRQ4_MCU_DSP_EN_SFT 4 +#define IRQ3_MCU_DSP_EN_SFT 3 +#define IRQ2_MCU_DSP_EN_SFT 2 +#define IRQ1_MCU_DSP_EN_SFT 1 +#define IRQ0_MCU_DSP_EN_SFT 0 + +#define AFE_IRQ_STATUS_BITS 0x87FFFFFF +#define AFE_IRQ_CNT_SHIFT 0 +#define AFE_IRQ_CNT_MASK 0x3ffff + +#endif diff --git a/src/platform/mt8186/include/platform/platform.h b/src/platform/mt8186/include/platform/platform.h new file mode 100644 index 000000000000..187f0fa5e6a2 --- /dev/null +++ b/src/platform/mt8186/include/platform/platform.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) +#define LPSRAM_SIZE 16384 + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT MTK_DSP_IRQ_MAILBOX +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ MTK_DSP_IRQ_SW +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#define SRAM_REG_FW_STATUS 0x4 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + trigger_irq_to_host_req(); +} + +/** + * \brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/mt8186/include/platform/trace/trace.h b/src/platform/mt8186/include/platform/trace/trace.h new file mode 100644 index 000000000000..393530083efb --- /dev/null +++ b/src/platform/mt8186/include/platform/trace/trace.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/io.h> +#include <platform/drivers/mt_reg_base.h> + +#define platform_trace_point(__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/mt8186/lib/CMakeLists.txt b/src/platform/mt8186/lib/CMakeLists.txt new file mode 100644 index 000000000000..ef71f8eea6cd --- /dev/null +++ b/src/platform/mt8186/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dma.c + memory.c + dai.c +) diff --git a/src/platform/mt8186/lib/clk.c b/src/platform/mt8186/lib/clk.c new file mode 100644 index 000000000000..033580a280bf --- /dev/null +++ b/src/platform/mt8186/lib/clk.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <platform/drivers/mt_reg_base.h> +#include <rtos/clk.h> +#include <rtos/wait.h> +#include <sof/common.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <rtos/sof.h> +#include <sof/trace/trace.h> + +SOF_DEFINE_REG_UUID(clkdrv_mt8186); + +DECLARE_TR_CTX(clkdrv_tr, SOF_UUID(clkdrv_mt8186_uuid), LOG_LEVEL_INFO); + +/* default voltage is 0.8V */ +const struct freq_table platform_cpu_freq[] = { + { 26000000, 26000}, + { 300000000, 26000}, + { 400000000, 26000}, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static void clk_dsppll_enable(uint32_t value) +{ + tr_dbg(&clkdrv_tr, "%d\n", value); + + switch (value) { + case ADSP_CLK_PLL_300M: + io_reg_write(MTK_ADSPPLL_CON1, MTK_PLL_DIV_RATIO_300M); + break; + case ADSP_CLK_PLL_400M: + io_reg_write(MTK_ADSPPLL_CON1, MTK_PLL_DIV_RATIO_400M); + break; + default: + tr_err(&clkdrv_tr, "invalid dsppll: %d\n", value); + return; + } + + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_PWR_ON, MTK_PLL_PWR_ON); + wait_delay_us(20); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_ISO_EN, 0); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON0, MTK_PLL_BASE_EN, MTK_PLL_BASE_EN); + wait_delay_us(20); +} + +static void clk_dsppll_disable(void) +{ + tr_dbg(&clkdrv_tr, "entry"); + + io_reg_update_bits(MTK_ADSPPLL_CON0, MTK_PLL_BASE_EN, 0); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_ISO_EN, MTK_PLL_ISO_EN); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_PWR_ON, 0); +} + +static void set_mux_adsp_sel(uint32_t value) +{ + io_reg_write(MTK_CLK_CFG_11_CLR, MTK_CLK_ADSP_MASK << MTK_CLK_ADSP_OFFSET); + io_reg_write(MTK_CLK_CFG_11_SET, value << MTK_CLK_ADSP_OFFSET); + io_reg_write(MTK_CLK_CFG_UPDATE, MTK_CLK_CFG_ADSP_UPDATE); + + tr_dbg(&clkdrv_tr, "adsp_clk_mux=%x, CLK_CFG_11=0x%08x\n", + value, io_reg_read(MTK_CLK_CFG_11)); +} + +static void set_mux_adsp_bus_src_sel(uint32_t value) +{ + io_reg_write(MTK_ADSP_BUS_SRC, value); + io_reg_write(MTK_ADSP_CLK_BUS_UPDATE, MTK_ADSP_CLK_BUS_UPDATE_BIT); + wait_delay_us(1); + + tr_dbg(&clkdrv_tr, "adsp_bus_mux=%x, MTK_ADSP_BUS_SRC=0x%08x\n", + value, io_reg_read(MTK_ADSP_BUS_SRC)); +} + +static void set_mux_adsp_bus_sel(uint32_t value) +{ + io_reg_write(MTK_CLK_CFG_15_CLR, MTK_CLK_ADSP_BUS_MASK << MTK_CLK_ADSP_BUS_OFFSET); + io_reg_write(MTK_CLK_CFG_15_SET, value << MTK_CLK_ADSP_BUS_OFFSET); + io_reg_write(MTK_CLK_CFG_UPDATE, MTK_CLK_CFG_ADSP_BUS_UPDATE); + + tr_dbg(&clkdrv_tr, "adsp_bus_clk_mux=%x, CLK_CFG_15=0x%08x\n", + value, io_reg_read(MTK_CLK_CFG_15)); +} + +static int clock_platform_set_dsp_freq(int clock, int freq_idx) +{ + switch (freq_idx) { + case ADSP_CLK_26M: + set_mux_adsp_bus_sel(MTK_CLK_ADSP_BUS_26M); + set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_LOCAL); + set_mux_adsp_sel(MTK_CLK_ADSP_26M); + clk_dsppll_disable(); + break; + case ADSP_CLK_PLL_300M: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + clk_dsppll_enable(ADSP_CLK_PLL_300M); + set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL); + set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_EMI); + set_mux_adsp_bus_sel(MTK_CLK_ADSP_BUS_26M); + break; + case ADSP_CLK_PLL_400M: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + clk_dsppll_enable(ADSP_CLK_PLL_400M); + set_mux_adsp_sel(MTK_CLK_ADSP_DSPPLL); + set_mux_adsp_bus_src_sel(MTK_ADSP_CLK_BUS_SRC_EMI); + set_mux_adsp_bus_sel(MTK_CLK_ADSP_BUS_26M); + break; + default: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + tr_err(&clkdrv_tr, "unknown freq index %x\n", freq_idx); + break; + } + + return 0; +} + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + 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 = clock_platform_set_dsp_freq, + }; + } + + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); +} diff --git a/src/platform/mt8186/lib/dai.c b/src/platform/mt8186/lib/dai.c new file mode 100644 index 000000000000..4d302d48fbdc --- /dev/null +++ b/src/platform/mt8186/lib/dai.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Chunxu Li <chunxu.li@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +#include <sof/drivers/afe-dai.h> +#include <mt8186-afe-common.h> + +static int afe_dai_handshake[MT8186_DAI_NUM] = { + AFE_HANDSHAKE(MT8186_AFE_IO_I2S1, MT8186_IRQ_0, MT8186_MEMIF_DL1), + AFE_HANDSHAKE(MT8186_AFE_IO_I2S3, MT8186_IRQ_1, MT8186_MEMIF_DL2), + AFE_HANDSHAKE(MT8186_AFE_IO_UL_SRC1, MT8186_IRQ_10, MT8186_MEMIF_UL1), + AFE_HANDSHAKE(MT8186_AFE_IO_I2S0, MT8186_IRQ_12, MT8186_MEMIF_UL2), +}; + +static SHARED_DATA struct dai afe_dai[MT8186_DAI_NUM]; + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_MEDIATEK_AFE, + .dai_array = afe_dai, + .num_dais = ARRAY_SIZE(afe_dai), + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti), +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(afe_dai); i++) { + k_spinlock_init(&afe_dai[i].lock); + afe_dai[i].index = AFE_HS_GET_DAI(afe_dai_handshake[i]); + afe_dai[i].drv = &afe_dai_driver; + /* TODO, fifo[0] change to target playback or capture */ + afe_dai[i].plat_data.fifo[0].handshake = afe_dai_handshake[i]; + } + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/mt8186/lib/dma.c b/src/platform/mt8186/lib/dma.c new file mode 100644 index 000000000000..db00628ae547 --- /dev/null +++ b/src/platform/mt8186/lib/dma.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/drivers/afe-memif.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +#include <mt8186-afe-regs.h> +#include <mt8186-afe-common.h> + +extern const struct dma_ops dummy_dma_ops; + +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .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, +}, +{ + .plat_data = { + .id = DMA_ID_AFE_MEMIF, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_AFE_MEMIF, + .base = AFE_BASE_ADDR, + .channels = MT8186_MEMIF_NUM, + }, + .ops = &memif_ops, +}, +}; + +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)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/mt8186/lib/memory.c b/src/platform/mt8186/lib/memory.c new file mode 100644 index 000000000000..2a01e0333bab --- /dev/null +++ b/src/platform/mt8186/lib/memory.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; +static SHARED_DATA struct block_hdr mod_block4096[HEAP_RT_COUNT4096]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), + BLOCK_DEF(4096, HEAP_RT_COUNT4096, mod_block4096), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/mt8186/mt8186.x.in b/src/platform/mt8186/mt8186.x.in new file mode 100644 index 000000000000..2aa7c480c06e --- /dev/null +++ b/src/platform/mt8186/mt8186.x.in @@ -0,0 +1,538 @@ +/* + * Linker Script for mt8186 MediaTek + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +#if CONFIG_MEDIATEK_DRAM_IMAGE +#define IMAGE_LOC sof_dram +#else +#define IMAGE_LOC sof_sram +#endif + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_sram : + org = SRAM_START, + len = SRAM_SIZE + sof_dram : + org = SOF_DRAM_BASE, + len = SOF_DRAM_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_sram_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000100; +_memmap_cacheattr_wt_base = 0x00000300; +_memmap_cacheattr_bp_base = 0x00000400; +_memmap_cacheattr_unused_mask = 0xFFFFF0FF; +_memmap_cacheattr_wb_trapnull = 0x44444140; +_memmap_cacheattr_wba_trapnull = 0x44444140; +_memmap_cacheattr_wbna_trapnull = 0x44444240; +_memmap_cacheattr_wt_trapnull = 0x44444340; +_memmap_cacheattr_bp_trapnull = 0x44444440; +_memmap_cacheattr_wb_strict = 0x00000100; +_memmap_cacheattr_wt_strict = 0x00000300; +_memmap_cacheattr_bp_strict = 0x00000400; +_memmap_cacheattr_wb_allvalid = 0x44444144; +_memmap_cacheattr_wt_allvalid = 0x44444344; +_memmap_cacheattr_bp_allvalid = 0x44444444; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + KEEP (*(.fw_ready_metadata)) + } >IMAGE_LOC :sof_sram_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >IMAGE_LOC :sof_sram_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr +} diff --git a/src/platform/mt8186/platform.c b/src/platform/mt8186/platform.c new file mode 100644 index 000000000000..f171e6cb7d0b --- /dev/null +++ b/src/platform/mt8186/platform.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <sof/drivers/edma.h> +#include <rtos/interrupt.h> +#include <sof/ipc/msg.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <xtensa/hal.h> +#include <platform/drivers/timer.h> + +struct sof; + +static const struct sof_ipc_fw_ready ready + __section(".fw_ready") = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_MTK_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_MTK_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + } +}; + +static SHARED_DATA struct timer timer_shared = { + .id = OSTIMER0, + .irq = MTK_DSP_IRQ_OSTIMER32, +}; + +/* Override the default MPU setup. This table matches the memory map + * of the 'sample_controller' core and will need to be modified for + * other cores. + * NOTE: This table sets up all of external memory as shared uncached. + * For best results, edit the LSP memory map to create a separate + * section in shared memory, place all sections that need to be uncached + * into that section, and only map that section uncached. See README + * for more details. + */ +const struct xthal_MPU_entry __xt_mpu_init_table[] __section(".ResetVector.text") = { + XTHAL_MPU_ENTRY(0x00000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // unused + XTHAL_MPU_ENTRY(0x4e100000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // sram + XTHAL_MPU_ENTRY(0x4e180000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused + XTHAL_MPU_ENTRY(0x60000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // dram + XTHAL_MPU_ENTRY(0x60500000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_NON_CACHEABLE), // dram + XTHAL_MPU_ENTRY(0x61100000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused +}; + +const unsigned int __xt_mpu_init_table_size __section(".ResetVector.text") = + ARRAY_SIZE(__xt_mpu_init_table); + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + /* now interrupt host to tell it we are done booting */ + trigger_irq_to_host_req(); + + return 0; +} + +extern void dump_adsppll(int line); + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = platform_shared_get(&timer_shared, sizeof(timer_shared)); + sof->cpu_timers = sof->platform_timer; + + platform_interrupt_init(); + platform_clock_init(sof); + + scheduler_init_edf(); + + /* init low latency domains and schedulers */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + platform_timer_start(sof->platform_timer); + + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* Init platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], 1, + PLATFORM_DEFAULT_CLOCK, false); + scheduler_init_ll(sof->platform_dma_domain); + + /* initialize the host IPC mechanims */ + ipc_init(sof); + + ret = dai_init(sof); + if (ret < 0) + return ret; + +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + dma_trace_init_complete(sof->dmat); +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} + diff --git a/src/platform/mt8188/CMakeLists.txt b/src/platform/mt8188/CMakeLists.txt new file mode 100644 index 000000000000..0965341701b5 --- /dev/null +++ b/src/platform/mt8188/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) + +add_local_sources(sof platform.c afe-platform.c) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8188/include/arch) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8188/include/platform) diff --git a/src/platform/mt8188/afe-platform.c b/src/platform/mt8188/afe-platform.c new file mode 100644 index 000000000000..4e0e2db4db35 --- /dev/null +++ b/src/platform/mt8188/afe-platform.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <sof/common.h> +#include <errno.h> +#include <sof/drivers/afe-drv.h> +#include <mt8188-afe-reg.h> +#include <mt8188-afe-common.h> + +/* + * AFE: Audio Front-End + * + * frontend (memif): + * memory interface + * UL (uplink for capture) + * DL (downlink for playback) + * backend: + * TDM In + * TDM Out + * DMIC + * GASRC + * I2S Out + * I2S In + * etc. + * interconn: + * inter-connection, + * connect frontends and backends as DSP path + */ + +static const struct mtk_base_memif_data memif_data[MT8188_MEMIF_NUM] = { + [MT8188_MEMIF_DL2] = { + .name = "DL2", + .id = MT8188_MEMIF_DL2, + .reg_ofs_base = AFE_DL2_BASE, + .reg_ofs_cur = AFE_DL2_CUR, + .reg_ofs_end = AFE_DL2_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON0, + .fs_shift = 10, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 18, + .hd_reg = AFE_DL2_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 18, + .ch_num_reg = AFE_DL2_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 18, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 18, + }, + [MT8188_MEMIF_DL3] = { + .name = "DL3", + .id = MT8188_MEMIF_DL3, + .reg_ofs_base = AFE_DL3_BASE, + .reg_ofs_cur = AFE_DL3_CUR, + .reg_ofs_end = AFE_DL3_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON0, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = 0, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 19, + .hd_reg = AFE_DL3_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 19, + .ch_num_reg = AFE_DL3_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 19, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 19, + }, + [MT8188_MEMIF_UL4] = { + .name = "UL4", + .id = MT8188_MEMIF_UL4, + .reg_ofs_base = AFE_UL4_BASE, + .reg_ofs_cur = AFE_UL4_CUR, + .reg_ofs_end = AFE_UL4_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL4_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL4_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 4, + .hd_reg = AFE_UL4_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 3, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 3, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 3, + }, + [MT8188_MEMIF_UL5] = { + .name = "UL5", + .id = MT8188_MEMIF_UL5, + .reg_ofs_base = AFE_UL5_BASE, + .reg_ofs_cur = AFE_UL5_CUR, + .reg_ofs_end = AFE_UL5_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 20, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL5_CON0, + .mono_shift = 1, + .int_odd_flag_reg = AFE_UL5_CON0, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 5, + .hd_reg = AFE_UL5_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 4, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 4, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 4, + }, +}; + +struct mt8188_afe_rate { + unsigned int rate; + unsigned int reg_value; +}; + +static const struct mt8188_afe_rate mt8188_afe_rates[] = { + { + .rate = 8000, + .reg_value = 0, + }, + { + .rate = 12000, + .reg_value = 1, + }, + { + .rate = 16000, + .reg_value = 2, + }, + { + .rate = 24000, + .reg_value = 3, + }, + { + .rate = 32000, + .reg_value = 4, + }, + { + .rate = 48000, + .reg_value = 5, + }, + { + .rate = 96000, + .reg_value = 6, + }, + { + .rate = 192000, + .reg_value = 7, + }, + { + .rate = 384000, + .reg_value = 8, + }, + { + .rate = 7350, + .reg_value = 16, + }, + { + .rate = 11025, + .reg_value = 17, + }, + { + .rate = 14700, + .reg_value = 18, + }, + { + .rate = 22050, + .reg_value = 19, + }, + { + .rate = 29400, + .reg_value = 20, + }, + { + .rate = 44100, + .reg_value = 21, + }, + { + .rate = 88200, + .reg_value = 22, + }, + { + .rate = 176400, + .reg_value = 23, + }, + { + .rate = 352800, + .reg_value = 24, + }, +}; + +static unsigned int mt8188_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8188_afe_rates); i++) + if (mt8188_afe_rates[i].rate == rate) + return mt8188_afe_rates[i].reg_value; + + return -EINVAL; +} + +static unsigned int mt8188_afe_fs(unsigned int rate, int aud_blk) +{ + return mt8188_afe_fs_timing(rate); +} + +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = AFE_BASE_ADDR, + .memif_datas = memif_data, + .memif_size = MT8188_MEMIF_NUM, + .memif_dl_num = MT8188_MEMIF_DL_NUM, + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = MT8188_DAI_NUM, + .afe_fs = mt8188_afe_fs, + .irq_fs = mt8188_afe_fs_timing, +}; diff --git a/src/platform/mt8188/include/arch/xtensa/config/core-isa.h b/src/platform/mt8188/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..79bee81a1ff1 --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,805 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 Tensilica 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. */ + +#ifndef XTENSA_CORE_CONFIGURATION_H_ +#define XTENSA_CORE_CONFIGURATION_H_ + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 16 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 1 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 1 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 1 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 1 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 1 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_DP_VFPU 0 /* Double-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_LDPC 0 /* LDPC option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6, Q7 or Q8 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_DP_VFPU 0 /* dp_vfpu option on Vision Q7/Q8 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1405000 /* sw version of this header */ +#define XCHAL_SW_VERSION_MAJOR 14000 /* major ver# of sw */ +#define XCHAL_SW_VERSION_MINOR 5 /* minor ver# of sw */ +#define XCHAL_SW_VERSION_MICRO 0 /* micro ver# of sw */ +#define XCHAL_SW_MINOR_VERSION 1405000 /* with zeroed micro */ +#define XCHAL_SW_MICRO_VERSION 1405000 + +#define XCHAL_CORE_ID "hifi5_7stg_I64D128" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000904D8 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC003B286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x294904D8 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.5" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 5 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO 0 /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281050 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_5 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 5 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281050 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 5 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO 0 /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281050 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +/* Config is enabled for secure operation: */ +#define XCHAL_HAVE_SECURE 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 65536 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 16 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 8 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 1 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ +#define XCHAL_HAVE_L2_CACHE 0 +#define XCHAL_NUM_CORES_IN_CLUSTER 0 + +/* PRID_ID macros are for internal use only ... subject to removal */ +#define PRID_ID_SHIFT 0 +#define PRID_ID_BITS 4 +#define PRID_ID_MASK 0x0000000F + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 7 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x3FFF0000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x3FFF0000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 32768 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x3FFF8000 /* virtual address */ +#define XCHAL_INSTRAM1_PADDR 0x3FFF8000 /* physical address */ +#define XCHAL_INSTRAM1_SIZE 4096 /* size in bytes */ +#define XCHAL_INSTRAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM1 1 +#define XCHAL_INSTRAM1_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FFE8000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x3FFE8000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 32768 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + IDMA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_IDMA 0 + + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 26 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 5 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x040000FF +#define XCHAL_INTLEVEL2_MASK 0xA800FF00 +#define XCHAL_INTLEVEL3_MASK 0x518F0000 +#define XCHAL_INTLEVEL4_MASK 0x00700000 +#define XCHAL_INTLEVEL5_MASK 0x00000000 +#define XCHAL_INTLEVEL6_MASK 0x02000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x040000FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0xAC00FFFF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0xFD8FFFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0xFDFFFFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFDFFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 2 +#define XCHAL_INT10_LEVEL 2 +#define XCHAL_INT11_LEVEL 2 +#define XCHAL_INT12_LEVEL 2 +#define XCHAL_INT13_LEVEL 2 +#define XCHAL_INT14_LEVEL 2 +#define XCHAL_INT15_LEVEL 2 +#define XCHAL_INT16_LEVEL 3 +#define XCHAL_INT17_LEVEL 3 +#define XCHAL_INT18_LEVEL 3 +#define XCHAL_INT19_LEVEL 3 +#define XCHAL_INT20_LEVEL 4 +#define XCHAL_INT21_LEVEL 4 +#define XCHAL_INT22_LEVEL 4 +#define XCHAL_INT23_LEVEL 3 +#define XCHAL_INT24_LEVEL 3 +#define XCHAL_INT25_LEVEL 6 +#define XCHAL_INT26_LEVEL 1 +#define XCHAL_INT27_LEVEL 2 +#define XCHAL_INT28_LEVEL 3 +#define XCHAL_INT29_LEVEL 2 +#define XCHAL_INT30_LEVEL 3 +#define XCHAL_INT31_LEVEL 2 +#define XCHAL_DEBUGLEVEL 5 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 6 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_SOFTWARE + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x007FFFFF +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x01800000 +#define XCHAL_INTTYPE_MASK_NMI 0x02000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x80000000 +#define XCHAL_INTTYPE_MASK_TIMER 0x1C000000 +#define XCHAL_INTTYPE_MASK_ETIE 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x40000000 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x20000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_WWDT 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 26 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 27 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 28 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 25 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 30 +#define XCHAL_PROFILING_INTERRUPT 29 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL6_NUM 25 +/* (There are many interrupts each at level(s) 1, 2, 3, 4.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT9_NUM 9 /* (intlevel 2) */ +#define XCHAL_EXTINT10_NUM 10 /* (intlevel 2) */ +#define XCHAL_EXTINT11_NUM 11 /* (intlevel 2) */ +#define XCHAL_EXTINT12_NUM 12 /* (intlevel 2) */ +#define XCHAL_EXTINT13_NUM 13 /* (intlevel 2) */ +#define XCHAL_EXTINT14_NUM 14 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 15 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 16 /* (intlevel 3) */ +#define XCHAL_EXTINT17_NUM 17 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 18 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 19 /* (intlevel 3) */ +#define XCHAL_EXTINT20_NUM 20 /* (intlevel 4) */ +#define XCHAL_EXTINT21_NUM 21 /* (intlevel 4) */ +#define XCHAL_EXTINT22_NUM 22 /* (intlevel 4) */ +#define XCHAL_EXTINT23_NUM 23 /* (intlevel 3) */ +#define XCHAL_EXTINT24_NUM 24 /* (intlevel 3) */ +#define XCHAL_EXTINT25_NUM 25 /* (intlevel 6) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT6_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT7_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 8 /* (intlevel 2) */ +#define XCHAL_INT9_EXTNUM 9 /* (intlevel 2) */ +#define XCHAL_INT10_EXTNUM 10 /* (intlevel 2) */ +#define XCHAL_INT11_EXTNUM 11 /* (intlevel 2) */ +#define XCHAL_INT12_EXTNUM 12 /* (intlevel 2) */ +#define XCHAL_INT13_EXTNUM 13 /* (intlevel 2) */ +#define XCHAL_INT14_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT15_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT16_EXTNUM 16 /* (intlevel 3) */ +#define XCHAL_INT17_EXTNUM 17 /* (intlevel 3) */ +#define XCHAL_INT18_EXTNUM 18 /* (intlevel 3) */ +#define XCHAL_INT19_EXTNUM 19 /* (intlevel 3) */ +#define XCHAL_INT20_EXTNUM 20 /* (intlevel 4) */ +#define XCHAL_INT21_EXTNUM 21 /* (intlevel 4) */ +#define XCHAL_INT22_EXTNUM 22 /* (intlevel 4) */ +#define XCHAL_INT23_EXTNUM 23 /* (intlevel 3) */ +#define XCHAL_INT24_EXTNUM 24 /* (intlevel 3) */ +#define XCHAL_INT25_EXTNUM 25 /* (intlevel 6) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x4e100400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x4e100400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 /* UNUSED */ + +#define XCHAL_RESET_VECTOR0_VADDR 0x4e100000 +#define XCHAL_RESET_VECTOR0_PADDR 0x4e100000 +#define XCHAL_RESET_VECTOR1_VADDR 0x4e100800 +#define XCHAL_RESET_VECTOR1_PADDR 0x4e100800 +#define XCHAL_RESET_VECTOR_VADDR XCHAL_RESET_VECTOR1_VADDR +#define XCHAL_RESET_VECTOR_PADDR XCHAL_RESET_VECTOR1_PADDR +#define XCHAL_USER_VECOFS 0x00000250 +#define XCHAL_USER_VECTOR_VADDR 0x4e100650 +#define XCHAL_USER_VECTOR_PADDR 0x4e100650 +#define XCHAL_KERNEL_VECOFS 0x00000230 +#define XCHAL_KERNEL_VECTOR_VADDR 0x4e100630 +#define XCHAL_KERNEL_VECTOR_PADDR 0x4e100630 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000270 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x4e100670 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x4e100670 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x4e100400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x4e100400 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x4e100580 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x4e100580 +#define XCHAL_INTLEVEL3_VECOFS 0x000001A4 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x4e1005A4 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x4e1005A4 +#define XCHAL_INTLEVEL4_VECOFS 0x000001C8 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x4e1005C8 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x4e1005C8 +#define XCHAL_INTLEVEL5_VECOFS 0x000001EC +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x4e1005EC +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x4e1005EC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL5_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL5_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL5_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000210 +#define XCHAL_NMI_VECTOR_VADDR 0x4e100610 +#define XCHAL_NMI_VECTOR_PADDR 0x4e100610 +#define XCHAL_INTLEVEL6_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL6_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL6_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 4096 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 64 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 8 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 0 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 1 +#define XCHAL_MPU_ENTRIES 32 +#define XCHAL_MPU_LOCK 0 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 2 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0xFF /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 12 +#define XCHAL_MPU_ALIGN 4096 + +/*----------------------------------------------------------------------- + CSR Parity +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_CSR_PARITY 0 + + +/*---------------------------------------------------------------------- + FLEX-LOCK +------------------------------------------------------------------------*/ + +#define XCHAL_HAVE_FXLK 0 + +/*---------------------------------------------------------------------- + WWDT (Windowed Watchdog Timer) +------------------------------------------------------------------------*/ +#define XCHAL_HAVE_WWDT 0 +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* XTENSA_CORE_CONFIGURATION_H_ */ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/core-matmap.h b/src/platform/mt8188/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..8a0056ca9c21 --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,106 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ + +/* Mappings for legacy constants where appropriate */ + +#define XCHAL_CA_WRITEBACK (XTHAL_MEM_WRITEBACK | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITEBACK_NOALLOC (XTHAL_MEM_WRITEBACK_NOALLOC| XTHAL_AR_RWXrwx ) + +#define XCHAL_CA_WRITETHRU (XTHAL_MEM_WRITETHRU | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_ILLEGAL (XTHAL_AR_NONE | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASSBUF (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE |\ + XTHAL_MEM_BUFFERABLE) +#define XCHAL_CA_BYPASS_RX (XTHAL_AR_RX | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_RW (XTHAL_AR_RW | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_R (XTHAL_AR_R | XTHAL_MEM_DEVICE) +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 + +#define XCHAL_CA_R (XTHAL_AR_R) +#define XCHAL_CA_RX (XTHAL_AR_RX) +#define XCHAL_CA_RW (XTHAL_AR_RW) +#define XCHAL_CA_RWX (XTHAL_AR_RWX) + + +/* + * Contents of MPU background map. + * NOTE: caller must define the XCHAL_MPU_BGMAP() macro (not defined here + * but specified below) before expanding the XCHAL_MPU_BACKGROUND_MAP(s) macro. + * + * XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) + * + * s = passed from XCHAL_MPU_BACKGROUND_MAP(s), eg. to select how to expand + * vaddr_start = first byte of region (always 0 for first entry) + * vaddr_end = last byte of region (always 0xFFFFFFFF for last entry) + * rights = access rights + * memtype = memory type + * x = reserved for future use (0 until then) + */ +/* parasoft-begin-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ +#define XCHAL_MPU_BACKGROUND_MAP(s) \ + XCHAL_MPU_BGMAP(s, 0x00000000, 0x7fffffff, 7, 6, 0) \ + XCHAL_MPU_BGMAP(s, 0x80000000, 0xffffffff, 7, 6, 0) \ +/* parasoft-end-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ + + /* end */ + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/defs.h b/src/platform/mt8188/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..be3cf59f6756 --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/mt8188/include/arch/xtensa/config/key.h b/src/platform/mt8188/include/arch/xtensa/config/key.h new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/key.h @@ -0,0 +1 @@ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/secure.h b/src/platform/mt8188/include/arch/xtensa/config/secure.h new file mode 100644 index 000000000000..561b2133c98e --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/secure.h @@ -0,0 +1,48 @@ + +/* Secure Mode defines. */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 2020 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. + */ + +#ifndef XTENSA_SECURE_H +#define XTENSA_SECURE_H + + +/* SRAM */ +#define XCHAL_HAVE_SECURE_SRAM 0 + +/* INSTRAM0 */ +#define XCHAL_HAVE_SECURE_INSTRAM0 0 + +/* INSTRAM1 */ +#define XCHAL_HAVE_SECURE_INSTRAM1 0 + +/* DATARAM0 */ +#define XCHAL_HAVE_SECURE_DATARAM0 0 + +/* Array of all secure regions' start/size */ +#define XCHAL_SECURE_MEM_LIST \ +{ \ +} + +#endif /* XTENSA_SECURE_H */ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/specreg.h b/src/platform/mt8188/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..7e4ed373ecc1 --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/specreg.h @@ -0,0 +1,110 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Homewood/ib.5/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define MPUENB 90 +#define ERACCESS 95 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEADRDIS 98 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/system.h b/src/platform/mt8188/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..e92cc4ad0433 --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/system.h @@ -0,0 +1,254 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=16990; Build=0x904d8; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x40000000 +#define XSHAL_RAM_PADDR 0x40000000 +#define XSHAL_RAM_VSIZE 0x80000000 +#define XSHAL_RAM_PSIZE 0x80000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x40000AE0 +#define XSHAL_RAM_AVAIL_VSIZE 0x7FFFF520 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0xC0000000 +#define XSHAL_RAM_BYPASS_PADDR 0xC0000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xdeed2000 +#define XSHAL_STL_INFO_LOCATION 0xfffffffc + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22444442 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22111112 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22111112 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44444F /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11111F /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11111F /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244444F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211111F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211111F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xF242444F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xF212111F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xF212111F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xF222222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00001010 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 1 +#define XSHAL_RESET_VECTOR_VADDR 0x40000800 +#define XSHAL_RESET_VECTOR_PADDR 0x40000800 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x0000001C +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL5_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL5_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x0000001C +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/tie-asm.h b/src/platform/mt8188/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..1dd05a4d23b9 --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,362 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rsr.br \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 // boolean option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed16, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed24, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed31, \ptr, .Lxchal_ofs_+48 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+56 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+57 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+58 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+59 + addi.a \ptr, \ptr, 64 + ae_salign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_salign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_salign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_salign128.i u3, \ptr, .Lxchal_ofs_+48 + addi.a \ptr, \ptr, -320 + ae_movdrzbvc aed0 // ureg AE_ZBIASV8C + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 + rur.ae_ovf_sar \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_bithead \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_ts_fts_bu_bp \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cw_sd_no \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.ae_cbegin0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.ae_cend0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+36 + rur.ae_cbegin1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+40 + rur.ae_cend1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+44 + rur.ae_cbegin2 \at1 // ureg 250 + s32i \at1, \ptr, .Lxchal_ofs_+48 + rur.ae_cend2 \at1 // ureg 251 + s32i \at1, \ptr, .Lxchal_ofs_+52 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 16, 16 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg AE_ZBIASV8C + ae_movzbvcdr aed0 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+8 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ovf_sar \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_bithead \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_ts_fts_bu_bp \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cw_sd_no \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.ae_cbegin0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.ae_cend0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+40 + wur.ae_cbegin1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+44 + wur.ae_cend1 \at1 // ureg 249 + l32i \at1, \ptr, .Lxchal_ofs_+48 + wur.ae_cbegin2 \at1 // ureg 250 + l32i \at1, \ptr, .Lxchal_ofs_+52 + wur.ae_cend2 \at1 // ureg 251 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed16, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed17, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed18, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed19, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed20, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed21, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed22, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed23, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed24, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed25, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed26, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed27, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed28, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed29, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed30, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed31, \ptr, .Lxchal_ofs_+48 + addi.a \ptr, \ptr, 56 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi.a \ptr, \ptr, 8 + ae_lalign128.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign128.i u1, \ptr, .Lxchal_ofs_+16 + ae_lalign128.i u2, \ptr, .Lxchal_ofs_+32 + ae_lalign128.i u3, \ptr, .Lxchal_ofs_+48 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 320 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 64 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 16, 16 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 384 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/mt8188/include/arch/xtensa/config/tie.h b/src/platform/mt8188/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..8ff7910d17ab --- /dev/null +++ b/src/platform/mt8188/include/arch/xtensa/config/tie.h @@ -0,0 +1,210 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=16990; Build=0x904d8; Copyright (c) 1999-2020 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 384 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 16 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 8 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 400 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 16 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 2 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 52 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ae_zbiasv8c,16, 8, 8,0x1029, ur,-1 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x102A, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin2, 4, 4, 4,0x03FA, ur,250, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend2, 4, 4, 4,0x03FB, ur,251, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed16, 8, 8, 8,0x1010, aed,16 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed17, 8, 8, 8,0x1011, aed,17 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed18, 8, 8, 8,0x1012, aed,18 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed19, 8, 8, 8,0x1013, aed,19 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed20, 8, 8, 8,0x1014, aed,20 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed21, 8, 8, 8,0x1015, aed,21 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed22, 8, 8, 8,0x1016, aed,22 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed23, 8, 8, 8,0x1017, aed,23 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed24, 8, 8, 8,0x1018, aed,24 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed25, 8, 8, 8,0x1019, aed,25 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed26, 8, 8, 8,0x101A, aed,26 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed27, 8, 8, 8,0x101B, aed,27 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed28, 8, 8, 8,0x101C, aed,28 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed29, 8, 8, 8,0x101D, aed,29 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed30, 8, 8, 8,0x101E, aed,30 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed31, 8, 8, 8,0x101F, aed,31 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1024, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1025, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1026, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1027, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0,16,16,16,0x1020, u,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1,16,16,16,0x1021, u,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2,16,16,16,0x1022, u,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3,16,16,16,0x1023, u,3 ,128,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,16 + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/mt8188/include/platform/drivers/idc.h b/src/platform/mt8188/include/platform/drivers/idc.h new file mode 100644 index 000000000000..e77600345b55 --- /dev/null +++ b/src/platform/mt8188/include/platform/drivers/idc.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +static inline int idc_init(void) +{ + return 0; +} + +#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/mt8188/include/platform/drivers/interrupt.h b/src/platform/mt8188/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..d9a5b367d1fb --- /dev/null +++ b/src/platform/mt8188/include/platform/drivers/interrupt.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Zhengnan Chen <zhengnan.chen@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <stdint.h> +#include <platform/drivers/mt_reg_base.h> + +#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM +#define PLATFORM_IRQ_CHILDREN 32 + +/* MTK_ADSP_IRQ_MASK */ +#define MTK_DSP_OUT_IRQ_MASK 0x3FF + +/* interrupt table */ +#define MTK_DSP_IRQ_UART 0 +#define MTK_DSP_IRQ_SPM 1 +#define MTK_DSP_IRQ_MAILBOX 2 +#define MTK_DSP_IRQ_DSP_TIMER0 3 +#define MTK_DSP_IRQ_DSP_TIMER1 4 +#define MTK_DSP_IRQ_CORE0 5 +#define MTK_DSP_IRQ_RSV0 6 +#define MTK_DSP_IRQ_CORE0_32A 7 +#define MTK_DSP_IRQ_I2C4 8 +#define MTK_DSP_IRQ_ASRC0 9 +#define MTK_DSP_IRQ_ASRC1 10 +#define MTK_DSP_IRQ_ASRC2 11 +#define MTK_DSP_IRQ_ASRC3 12 +#define MTK_DSP_IRQ_OSTIMER64 13 +#define MTK_DSP_IRQ_DMA 14 +#define MTK_DSP_IRQ_AUDIOSYS 15 +#define MTK_DSP_IRQ_WDT 16 +#define MTK_DSP_IRQ_RSV1 17 +#define MTK_DSP_IRQ_OSTIMER32 18 +#define MTK_DSP_IRQ_SCP 19 +#define MTK_DSP_IRQ_RSV2 20 +#define MTK_DSP_IRQ_LATENCT_MON 21 +#define MTK_DSP_IRQ_BUS_TRACKER 22 +#define MTK_DSP_IRQ_WAKEUP_SRC 23 +#define MTK_DSP_IRQ_INFRA_HANG 24 +/* following interrupts are HiFi internal interrupts */ +#define MTK_DSP_IRQ_NMI 25 +#define MTK_DSP_IRQ_TIMER0 26 +#define MTK_DSP_IRQ_TIMER1 27 +#define MTK_DSP_IRQ_TIMER2 28 +#define MTK_DSP_IRQ_PROFILING 29 +#define MTK_DSP_IRQ_WERR 30 +#define MTK_DSP_IRQ_SW 31 + +#define MTK_MAX_IRQ_NUM 32 + +/* grouped mailbox IRQ */ +#define MTK_DSP_IRQ_MBOX0 32 +#define MTK_DSP_IRQ_MBOX1 33 +#define MTK_DSP_IRQ_MBOX2 34 +#define MTK_DSP_IRQ_MBOX3 35 +#define MTK_DSP_IRQ_MBOX4 36 + +#define MTK_DSP_MBOX_MASK 0xF + +int mtk_irq_group_id(uint32_t irq); + +#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/mt8188/include/platform/drivers/mt_reg_base.h b/src/platform/mt8188/include/platform/drivers/mt_reg_base.h new file mode 100644 index 000000000000..5fae02c0cec9 --- /dev/null +++ b/src/platform/mt8188/include/platform/drivers/mt_reg_base.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifndef MT_REG_BASE_H +#define MT_REG_BASE_H + +#define MTK_REG_TOPCKGEN_BASE 0x10000000 +#define MTK_REG_TOPCKGEN_SIZE 0x1000 +#define MTK_REG_APMIXDSYS_BASE 0x1000C000 +#define MTK_REG_APMIXDSYS_SIZE 0x1000 + +#define MTK_DSP_REG_BASE 0x10b80000 /* DSP Register base */ +#define MTK_DSP_CFGREG_BASE 0x10b80000 +#define MTK_DSP_CFGREG_SIZE 0x1000 +#define MTK_DSP_CKCTRL_BASE 0x10b81000 +#define MTK_DSP_CKCTRL_SIZE 0x1000 +#define MTK_DSP_OS_TIMER_BASE 0x10b83000 +#define MTK_DSP_OS_TIMER_SIZE 0x1000 +#define MTK_DSP_UART0_BASE 0x10b84000 +#define MTK_DSP_UART0_SIZE 0x1000 +#define MTK_DSP_TIMER_BASE 0x10b92000 +#define MTK_DSP_TIMER_SIZE 0x1000 +#define MTK_DSP_BUS_BASE 0x10b8F000 +#define MTK_DSP_BUS_SIZE 0x1000 + +#define MTK_ADSP_CFGREG_SW_RSTN (MTK_DSP_REG_BASE + 0x0000) +#define MTK_ADSP_HIFI_IO_CONFIG (MTK_DSP_REG_BASE + 0x000c) +#define MTK_ADSP_IRQ_STATUS (MTK_DSP_REG_BASE + 0x0010) +#define MTK_ADSP_SW_INT_SET (MTK_DSP_REG_BASE + 0x0018) +#define MTK_ADSP_SW_INT_CLR (MTK_DSP_REG_BASE + 0x001c) +#define MTK_ADSP_SW_INT_32A (MTK_DSP_REG_BASE + 0x0020) +#define MTK_ADSP_IRQ_MASK (MTK_DSP_REG_BASE + 0x0030) +#define MTK_ADSP_GENERAL_IRQ_SET (MTK_DSP_REG_BASE + 0x0034) +#define MTK_ADSP_GENERAL_IRQ_CLR (MTK_DSP_REG_BASE + 0x0038) +#define MTK_ADSP_DVFSRC_STATE (MTK_DSP_REG_BASE + 0x003c) +#define MTK_ADSP_DVFSRC_REQ (MTK_DSP_REG_BASE + 0x0040) +#define MTK_ADSP_DDREN_REQ_0 (MTK_DSP_REG_BASE + 0x0044) +#define MTK_ADSP_SPM_ACK (MTK_DSP_REG_BASE + 0x004c) +#define MTK_ADSP_IRQ_EN (MTK_DSP_REG_BASE + 0x0050) +#define MTK_ADSP_IRQ_POL_FIX (MTK_DSP_REG_BASE + 0x0054) +#define MTK_ADSP_SPM_WAKEUPSRC_CORE0 (MTK_DSP_REG_BASE + 0x005c) +#define MTK_ADSP_SEMAPHORE (MTK_DSP_REG_BASE + 0x0064) +#define MTK_ADSP_DBG_SEL (MTK_DSP_REG_BASE + 0x0074) +#define MTK_ADSP_DBG_INFO (MTK_DSP_REG_BASE + 0x0078) +#define MTK_ADSP_WDT_CON_C0 (MTK_DSP_REG_BASE + 0x007c) +#define MTK_ADSP_WDT_INIT_VALUE_C0 (MTK_DSP_REG_BASE + 0x0080) +#define MTK_ADSP_WDT_CNT_C0 (MTK_DSP_REG_BASE + 0x0084) +#define MTK_ADSP_WAKEUPSRC_MASK_C0 (MTK_DSP_REG_BASE + 0x00a0) +#define MTK_ADSP_WAKEUPSRC_IRQ_C0 (MTK_DSP_REG_BASE + 0x00a4) +#define MTK_ADSP2SPM_MBOX (MTK_DSP_REG_BASE + 0x00bc) +#define MTK_SPM2ADSP_MBOX (MTK_DSP_REG_BASE + 0x00c0) +#define MTK_GPR_RW_REG0 (MTK_DSP_REG_BASE + 0x0440) +#define MTK_GPR_RW_REG1 (MTK_DSP_REG_BASE + 0x0444) +#define MTK_GPR_RW_REG2 (MTK_DSP_REG_BASE + 0x0448) +#define MTK_GPR_RW_REG3 (MTK_DSP_REG_BASE + 0x044c) +#define MTK_GPR_RW_REG4 (MTK_DSP_REG_BASE + 0x0450) +#define MTK_GPR_RW_REG5 (MTK_DSP_REG_BASE + 0x0454) +#define MTK_GPR_RW_REG6 (MTK_DSP_REG_BASE + 0x0458) +#define MTK_GPR_RW_REG7 (MTK_DSP_REG_BASE + 0x045c) +#define MTK_GPR_RW_REG8 (MTK_DSP_REG_BASE + 0x0460) +#define MTK_GPR_RW_REG9 (MTK_DSP_REG_BASE + 0x0464) +#define MTK_GPR_RW_REG10 (MTK_DSP_REG_BASE + 0x0468) +#define MTK_GPR_RW_REG11 (MTK_DSP_REG_BASE + 0x046c) +#define MTK_GPR_RW_REG12 (MTK_DSP_REG_BASE + 0x0470) +#define MTK_GPR_RW_REG13 (MTK_DSP_REG_BASE + 0x0474) +#define MTK_GPR_RW_REG14 (MTK_DSP_REG_BASE + 0x0478) +#define MTK_GPR_RW_REG15 (MTK_DSP_REG_BASE + 0x047c) +#define MTK_GPR_RW_REG16 (MTK_DSP_REG_BASE + 0x0480) +#define MTK_GPR_RW_REG17 (MTK_DSP_REG_BASE + 0x0484) +#define MTK_GPR_RW_REG18 (MTK_DSP_REG_BASE + 0x0488) +#define MTK_GPR_RW_REG19 (MTK_DSP_REG_BASE + 0x048c) +#define MTK_GPR_RW_REG20 (MTK_DSP_REG_BASE + 0x0490) +#define MTK_GPR_RW_REG21 (MTK_DSP_REG_BASE + 0x0494) +#define MTK_GPR_RW_REG22 (MTK_DSP_REG_BASE + 0x0498) +#define MTK_GPR_RW_REG23 (MTK_DSP_REG_BASE + 0x049c) +#define MTK_GPR_RW_REG24 (MTK_DSP_REG_BASE + 0x04a0) +#define MTK_GPR_RW_REG25 (MTK_DSP_REG_BASE + 0x04a4) +#define MTK_GPR_RW_REG26 (MTK_DSP_REG_BASE + 0x04a8) +#define MTK_GPR_RW_REG27 (MTK_DSP_REG_BASE + 0x04ac) +#define MTK_GPR_RW_REG28 (MTK_DSP_REG_BASE + 0x04b0) /* use for tickless status */ +#define MTK_GPR_RW_REG29 (MTK_DSP_REG_BASE + 0x04b4) +#define MTK_ADSP_IRQ_OUT_MASK (MTK_DSP_REG_BASE + 0x0500) +#define MTK_MBOX_IRQ_IN (MTK_DSP_REG_BASE + 0xB070) + +#define MTK_ADSPPLL_CON0 (MTK_REG_APMIXDSYS_BASE + 0x42C) +#define MTK_ADSPPLL_CON1 (MTK_REG_APMIXDSYS_BASE + 0x430) +#define MTK_ADSPPLL_CON2 (MTK_REG_APMIXDSYS_BASE + 0x434) +#define MTK_ADSPPLL_CON3 (MTK_REG_APMIXDSYS_BASE + 0x438) + +#define MTK_CLK_CFG_UPDATE2 (MTK_REG_TOPCKGEN_BASE + 0xC) +#define MTK_CLK_CFG_17 (MTK_REG_TOPCKGEN_BASE + 0x0EC) +#define MTK_CLK_CFG_17_SET (MTK_REG_TOPCKGEN_BASE + 0x0F0) +#define MTK_CLK_CFG_17_CLR (MTK_REG_TOPCKGEN_BASE + 0x0F4) + +/* MBOX registers */ +#define MTK_ADSP_MBOX_REG_BASE(x) (0x10b86000 + (0x1000 * (x))) +#define MTK_ADSP_MBOX_REG_SIZE (0x5000) +#define MTK_ADSP_MBOX_IN_CMD(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x100) +#define MTK_ADSP_MBOX_IN_CMD_CLR(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x108) +#define MTK_ADSP_MBOX_OUT_CMD(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x104) +#define MTK_ADSP_MBOX_OUT_CMD_CLR(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x10c) + +#endif /* MT_REG_BASE_H */ diff --git a/src/platform/mt8188/include/platform/drivers/timer.h b/src/platform/mt8188/include/platform/drivers/timer.h new file mode 100644 index 000000000000..4f0e68f1928d --- /dev/null +++ b/src/platform/mt8188/include/platform/drivers/timer.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifndef __PLATFORM_DRIVERS_TIMER_H__ +#define __PLATFORM_DRIVERS_TIMER_H__ + +#include <rtos/bit.h> +#include <platform/drivers/mt_reg_base.h> + +/*-------timer:ostimer0-------*/ +enum ostimer { + OSTIMER0 = 0, + OSTIMER1, + OSTIMER2, + OSTIMER3, + NR_TMRS +}; + +#define MTK_TIMER_CON(n) (MTK_DSP_OS_TIMER_BASE + 0x0 + 0x10 * (n)) +#define MTK_TIMER_RST_VAL(n) (MTK_DSP_OS_TIMER_BASE + 0x4 + 0x10 * (n)) +#define MTK_TIMER_CUR_VAL(n) (MTK_DSP_OS_TIMER_BASE + 0x8 + 0x10 * (n)) +#define MTK_TIMER_IRQ_ACK(n) (MTK_DSP_OS_TIMER_BASE + 0xC + 0x10 * (n)) + +#define MTK_TIMER_ENABLE_BIT BIT(0) +#define MTK_TIMER_IRQ_ENABLE BIT(0) +#define MTK_TIMER_IRQ_STA BIT(4) +#define MTK_TIMER_IRQ_CLEAR BIT(5) +#define MTK_TIMER_CLKSRC_BIT (BIT(4) | BIT(5)) + +#define MTK_TIMER_CLK_SRC_OFFSET 4 +#define MTK_TIMER_CLK_SRC_CLK_26M 0 +#define MTK_TIMER_CLK_SRC_BCLK BIT(4) +#define MTK_TIMER_CLK_SRC_PCLK BIT(5) + +/*-------platform_timer: 64 bit systimer-------*/ +#define MTK_OSTIMER_CON (MTK_DSP_OS_TIMER_BASE + 0x80) +#define MTK_OSTIMER_CUR_L (MTK_DSP_OS_TIMER_BASE + 0x8C) +#define MTK_OSTIMER_CUR_H (MTK_DSP_OS_TIMER_BASE + 0x90) +#define MTK_OSTIMER_TVAL (MTK_DSP_OS_TIMER_BASE + 0x94) +#define MTK_OSTIMER_IRQ_ACK (MTK_DSP_OS_TIMER_BASE + 0x98) + +#define MTK_OSTIMER_EN_BIT BIT(0) + +#endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/mt8188/include/platform/lib/clk.h b/src/platform/mt8188/include/platform/lib/clk.h new file mode 100644 index 000000000000..d9f76609384a --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/clk.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <stdint.h> + +struct sof; + +#define CPU_DEFAULT_IDX 0 + +#define CLK_CPU(x) (x) +#define CLK_DEFAULT_CPU_HZ 26000000 +#define CLK_MAX_CPU_HZ 800000000 +#define NUM_CLOCKS 1 +#define NUM_CPU_FREQ 3 + +/* MTK_ADSPPLL_CON1 */ +#define MTK_PLL_DIV_RATIO_800M 0x810F6276 +#define MTK_PLL_DIV_RATIO_400M 0x831EC4ED + +/* MTK_ADSPPLL_CON3 */ +#define MTK_PLL_EN BIT(9) +#define MTK_PLL_PWR_ON BIT(0) +#define MTK_PLL_ISO_EN BIT(1) + +/* MTK_CLK_CFG_UPDATE2 */ +#define MTK_CLK_UPDATE_ADSK_CLK BIT(4) +#define MTK_CLK_UPDATE_AUDIO_LOCAL_BUS_CLK BIT(5) + +/* MTK_CLK_CFG_17[3:0] */ +#define MTK_CLK_ADSP_OFFSET 0 +#define MTK_CLK_ADSP_MASK 0xF +#define MTK_CLK_ADSP_26M 0 +#define MTK_CLK_ADSP_ADSPPLL 8 /* 800M */ +#define MTK_CLK_ADSP_ADSPPLL_D_2 9 /* 400M */ + +/* MTK_CLK_CFG_17[11:8] */ +#define MTK_CLK_AUDIO_LOCAL_BUS_OFFSET 8 +#define MTK_CLK_AUDIO_LOCAL_BUS_MASK 0xF +#define MTK_CLK_AUDIO_LOCAL_BUS_26M 0 +#define MTK_CLK_AUDIO_LOCAL_BUS_MAINPLL_D_7 6 /* 312M */ +#define MTK_CLK_AUDIO_LOCAL_BUS_MAINPLL_D_4 7 /* 546M */ + +/* List resource from low to high request */ +/* 0 is the lowest request */ +enum ADSP_HW_DSP_CLK { + ADSP_CLK_26M = 0, + ADSP_CLK_PLL_400M, + ADSP_CLK_PLL_800M, +}; + +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/mt8188/include/platform/lib/cpu.h b/src/platform/mt8188/include/platform/lib/cpu.h new file mode 100644 index 000000000000..ecbb220d5f02 --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/cpu.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/** \brief Id of primary DSP core */ +#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/mt8188/include/platform/lib/dai.h b/src/platform/mt8188/include/platform/lib/dai.h new file mode 100644 index 000000000000..8d367ed32cdd --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/dai.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#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/mt8188/include/platform/lib/dma.h b/src/platform/mt8188/include/platform/lib/dma.h new file mode 100644 index 000000000000..a7080012ffd9 --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/dma.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 2 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 32 + +#define DMA_ID_AFE_MEMIF 0 +#define DMA_ID_HOST 1 + +#define dma_chan_irq(dma, chan) dma_irq(dma) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#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/mt8188/include/platform/lib/mailbox.h b/src/platform/mt8188/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..2473f542ceee --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/mailbox.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/memory.h> +#include <stddef.h> +#include <stdint.h> + +/* + * The Window Region on MT8186 SRAM is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_EXCEPT_BASE | Except | SRAM_EXCEPT_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_STREAM_BASE | Stream | SRAM_STREAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer | SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +#define ADSP_IPI_OP_REQ 0x1 +#define ADSP_IPI_OP_RSP 0x2 +void trigger_irq_to_host_req(void); +void trigger_irq_to_host_rsp(void); + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + *ptr = src; +} + +#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/mt8188/include/platform/lib/memory.h b/src/platform/mt8188/include/platform/lib/memory.h new file mode 100644 index 000000000000..65148c9c348d --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/memory.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN sizeof(void *) + +/* physical DSP addresses */ +#define SRAM_BASE 0x4e100000 +#define SRAM_SIZE 0x80000 + +/* reset vector + rodata + module_init + text + data + bss */ +#define SOF_DATA_SIZE 0x80000 +#define VECTOR_SIZE 0x700 +#define SRAM_START (SRAM_BASE + VECTOR_SIZE) + +#define DRAM_BASE 0x60000000 +#define DRAM0_SIZE 0x500000 +#define MAILBOX_BASE (DRAM_BASE + DRAM0_SIZE) +#define DSP_SYS_SIZE 0xA00000 + +#define UUID_ENTRY_ELF_BASE (SRAM_BASE + SOF_DATA_SIZE) +#define UUID_ENTRY_ELF_SIZE 0x6000 + +#define LOG_ENTRY_ELF_BASE (UUID_ENTRY_ELF_BASE + UUID_ENTRY_ELF_SIZE) +#define LOG_ENTRY_ELF_SIZE 0x20000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE (SRAM_BASE + SRAM_SIZE - EXT_MANIFEST_ELF_BASE) + +/* + * The Memory Layout on MT8186 are organised like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_START | RO Data | SOF_DATA_SIZE | + * | | text | | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | fw_ready | + * +---------------------+----------------+-----------------------------------+ + * | static_uuid | + * +---------------------+----------------+-----------------------------------+ + * | static_log | + * +---------------------+----------------+-----------------------------------+ + * | fw_metadata | + * +---------------------+----------------+-----------------------------------+ + * + * +---------------------+----------------+-----------------------------------+ + * | SOF_DRAM_BASE | | SOF_DRAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + * | MAILBOX_BASE | | SOF_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define SRAM_OUTBOX_BASE MAILBOX_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +/*4K + 4K +2K + 2K + 4K + 4K = 20KB*/ +#define SOF_MAILBOX_SIZE \ + (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE + SRAM_DEBUG_SIZE + \ + SRAM_EXCEPT_SIZE + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* SOF image on DRAM */ +#define SOF_DRAM_BASE DRAM_BASE +#define SOF_DRAM_SIZE 0x100000 + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 32 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 32 +#define HEAP_RT_COUNT1024 4 +#define HEAP_RT_COUNT2048 2 +#define HEAP_RT_COUNT4096 2 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 128 +#define HEAP_SYS_RT_COUNT512 16 +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ + +#define HEAP_SYSTEM_BASE (SOF_DRAM_BASE + SOF_DRAM_SIZE) +#define HEAP_SYSTEM_SIZE 0x6000 + +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +/*24KB*/ +#define HEAP_SYS_RUNTIME_SIZE \ + (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +/*48*(16 +32) + 32*(64 128+256) + 4*(512+1024) + 1*2048 = 24832 = 24.25KB*/ +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048 + HEAP_RT_COUNT4096 * 4096) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE \ + (DRAM0_SIZE - SOF_DRAM_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE - \ + HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Stack configuration */ +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE /*4KB*/ +#define SOF_STACK_BASE (DRAM_BASE + DRAM0_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x4 +#define SOF_MEM_VECT_TEXT_SIZE 0x1c +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 +#define SOF_MEM_RESET_LIT_SIZE 0x120 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE + +/** \brief EDF task's default stack size in bytes. */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +struct sof; + +/** + * \brief Data shared between different cores. + * Does nothing, since mt8186 doesn't support SMP. + */ +#define SHARED_DATA + +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +/** + * \brief Function for keeping shared data synchronized. + * It's used after usage of data shared by different cores. + * Such data is either statically marked with SHARED_DATA + * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. + * Does nothing, since mt8186 doesn't support SMP. + */ + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#endif + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#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/mt8188/include/platform/lib/pm_runtime.h b/src/platform/mt8188/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..9831aadb4447 --- /dev/null +++ b/src/platform/mt8188/include/platform/lib/pm_runtime.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +static inline 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 The index of the device. + * \param[in] flags The flags, set of RPM_... + */ +static inline 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 The index of the device. + * \param[in] flags The flags, set of RPM_... + */ +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/mt8188/include/platform/mt8188-afe-common.h b/src/platform/mt8188/include/platform/mt8188-afe-common.h new file mode 100644 index 000000000000..2336c1491363 --- /dev/null +++ b/src/platform/mt8188/include/platform/mt8188-afe-common.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT_8188_AFE_COMMON_H_ +#define _MT_8188_AFE_COMMON_H_ + +enum { + MT8188_MEMIF_START, + MT8188_MEMIF_DL_START = MT8188_MEMIF_START, + MT8188_MEMIF_DL2 = MT8188_MEMIF_DL_START, + MT8188_MEMIF_DL3, + MT8188_MEMIF_DL_END, + MT8188_MEMIF_UL_START = MT8188_MEMIF_DL_END, + MT8188_MEMIF_UL4 = MT8188_MEMIF_UL_START, + MT8188_MEMIF_UL5, + MT8188_MEMIF_UL_END, + MT8188_MEMIF_END = MT8188_MEMIF_UL_END, + MT8188_MEMIF_DL_NUM = (MT8188_MEMIF_DL_END - MT8188_MEMIF_DL_START), + MT8188_MEMIF_UL_NUM = (MT8188_MEMIF_UL_END - MT8188_MEMIF_UL_START), + MT8188_MEMIF_NUM = (MT8188_MEMIF_END - MT8188_MEMIF_START), +}; + +enum { + MT8188_IRQ_1, + MT8188_IRQ_2, + MT8188_IRQ_3, + MT8188_IRQ_8, + MT8188_IRQ_9, + MT8188_IRQ_10, + MT8188_IRQ_13, + MT8188_IRQ_14, + MT8188_IRQ_15, + MT8188_IRQ_16, + MT8188_IRQ_17, + MT8188_IRQ_18, + MT8188_IRQ_19, + MT8188_IRQ_20, + MT8188_IRQ_21, + MT8188_IRQ_22, + MT8188_IRQ_23, + MT8188_IRQ_24, + MT8188_IRQ_25, + MT8188_IRQ_26, + MT8188_IRQ_27, + MT8188_IRQ_28, + MT8188_IRQ_NUM, +}; + +enum { + MT8188_AFE_IO_ETDM2_OUT, /* speaker */ + MT8188_AFE_IO_ETDM1_OUT, /* headset out */ + MT8188_AFE_IO_ADDA, /* DMIC */ + MT8188_AFE_IO_ETDM2_IN, /* headset mic */ + MT8188_DAI_NUM, +}; + +#endif diff --git a/src/platform/mt8188/include/platform/mt8188-afe-reg.h b/src/platform/mt8188/include/platform/mt8188-afe-reg.h new file mode 100644 index 000000000000..277f43f7e8a7 --- /dev/null +++ b/src/platform/mt8188/include/platform/mt8188-afe-reg.h @@ -0,0 +1,2725 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#ifndef _MT8188_AFE_REG_H_ +#define _MT8188_AFE_REG_H_ + +#define AFE_BASE_ADDR 0x10B10000 + +#define AUDIO_TOP_CON0 0x0000 +#define AUDIO_TOP_CON1 0x0004 +#define AUDIO_TOP_CON2 0x0008 +#define AUDIO_TOP_CON3 0x000c +#define AUDIO_TOP_CON4 0x0010 +#define AUDIO_TOP_CON5 0x0014 +#define AUDIO_TOP_CON6 0x0018 +#define AFE_MAS_HADDR_MSB 0x0020 +#define AFE_MEMIF_ONE_HEART 0x0024 +#define AFE_MUX_SEL_CFG 0x0044 +#define PWR1_ASM_CON1 0x0108 +#define ASYS_IRQ_CONFIG 0x0110 +#define ASYS_IRQ1_CON 0x0114 +#define ASYS_IRQ2_CON 0x0118 +#define ASYS_IRQ3_CON 0x011c +#define ASYS_IRQ4_CON 0x0120 +#define ASYS_IRQ5_CON 0x0124 +#define ASYS_IRQ6_CON 0x0128 +#define ASYS_IRQ7_CON 0x012c +#define ASYS_IRQ8_CON 0x0130 +#define ASYS_IRQ9_CON 0x0134 +#define ASYS_IRQ10_CON 0x0138 +#define ASYS_IRQ11_CON 0x013c +#define ASYS_IRQ12_CON 0x0140 +#define ASYS_IRQ13_CON 0x0144 +#define ASYS_IRQ14_CON 0x0148 +#define ASYS_IRQ15_CON 0x014c +#define ASYS_IRQ16_CON 0x0150 +#define ASYS_IRQ_CLR 0x0154 +#define ASYS_IRQ_STATUS 0x0158 +#define ASYS_IRQ_MON1 0x015c +#define ASYS_IRQ_MON2 0x0160 +#define AFE_IRQ1_CON 0x0164 +#define AFE_IRQ2_CON 0x0168 +#define AFE_IRQ3_CON 0x016c +#define AFE_IRQ_MCU_CLR 0x0170 +#define AFE_IRQ_STATUS 0x0174 +#define AFE_IRQ_MASK 0x0178 +#define ASYS_IRQ_MASK 0x017c +#define AFE_IRQ3_CON_MON 0x01b0 +#define AFE_IRQ_MCU_MON2 0x01b4 +#define AFE_IRQ8_CON 0x01b8 +#define AFE_IRQ9_CON 0x01bc +#define AFE_IRQ10_CON 0x01c0 +#define AFE_IRQ9_CON_MON 0x01c4 +#define ADSP_IRQ_MASK 0x01c8 +#define ADSP_IRQ_STATUS 0x01cc +#define AFE_SINEGEN_CON0 0x01f0 +#define AFE_SINEGEN_CON1 0x01f4 +#define AFE_SINEGEN_CON2 0x01f8 +#define AFE_SINEGEN_CON3 0x01fc +#define AFE_SPDIF_OUT_CON0 0x0380 +#define AFE_TDMOUT_CONN0 0x0390 +#define PWR1_ASM_CON2 0x03b0 +#define PWR1_ASM_CON3 0x03b4 +#define AFE_APLL_TUNER_CFG 0x03f8 +#define AFE_APLL_TUNER_CFG1 0x03fc +#define AUDIO_TOP_STA0 0x0400 +#define AUDIO_TOP_STA1 0x0404 +#define AFE_GAIN1_CON0 0x0410 +#define AFE_GAIN1_CON1 0x0414 +#define AFE_GAIN1_CON2 0x0418 +#define AFE_GAIN1_CON3 0x041c +#define AFE_GAIN1_CUR 0x0424 +#define AFE_GAIN2_CON0 0x0428 +#define AFE_GAIN2_CON1 0x042c +#define AFE_GAIN2_CON2 0x0430 +#define AFE_GAIN2_CON3 0x0434 +#define AFE_GAIN2_CUR 0x043c +#define AFE_IEC_CFG 0x0480 +#define AFE_IEC_NSNUM 0x0484 +#define AFE_IEC_BURST_INFO 0x0488 +#define AFE_IEC_BURST_LEN 0x048c +#define AFE_IEC_NSADR 0x0490 +#define AFE_IEC_CHL_STAT0 0x04a0 +#define AFE_IEC_CHL_STAT1 0x04a4 +#define AFE_IEC_CHR_STAT0 0x04a8 +#define AFE_IEC_CHR_STAT1 0x04ac +#define AFE_SPDIFIN_CFG0 0x0500 +#define AFE_SPDIFIN_CFG1 0x0504 +#define AFE_SPDIFIN_CHSTS1 0x0508 +#define AFE_SPDIFIN_CHSTS2 0x050c +#define AFE_SPDIFIN_CHSTS3 0x0510 +#define AFE_SPDIFIN_CHSTS4 0x0514 +#define AFE_SPDIFIN_CHSTS5 0x0518 +#define AFE_SPDIFIN_CHSTS6 0x051c +#define AFE_SPDIFIN_DEBUG1 0x0520 +#define AFE_SPDIFIN_DEBUG2 0x0524 +#define AFE_SPDIFIN_DEBUG3 0x0528 +#define AFE_SPDIFIN_DEBUG4 0x052c +#define AFE_SPDIFIN_EC 0x0530 +#define AFE_SPDIFIN_CKLOCK_CFG 0x0534 +#define AFE_SPDIFIN_BR 0x053c +#define AFE_SPDIFIN_BR_DBG1 0x0540 +#define AFE_SPDIFIN_CKFBDIV 0x0544 +#define AFE_SPDIFIN_INT_EXT 0x0548 +#define AFE_SPDIFIN_INT_EXT2 0x054c +#define SPDIFIN_FREQ_INFO 0x0550 +#define SPDIFIN_FREQ_INFO_2 0x0554 +#define SPDIFIN_FREQ_INFO_3 0x0558 +#define SPDIFIN_FREQ_STATUS 0x055c +#define SPDIFIN_USERCODE1 0x0560 +#define SPDIFIN_USERCODE2 0x0564 +#define SPDIFIN_USERCODE3 0x0568 +#define SPDIFIN_USERCODE4 0x056c +#define SPDIFIN_USERCODE5 0x0570 +#define SPDIFIN_USERCODE6 0x0574 +#define SPDIFIN_USERCODE7 0x0578 +#define SPDIFIN_USERCODE8 0x057c +#define SPDIFIN_USERCODE9 0x0580 +#define SPDIFIN_USERCODE10 0x0584 +#define SPDIFIN_USERCODE11 0x0588 +#define SPDIFIN_USERCODE12 0x058c +#define AFE_SPDIFIN_APLL_TUNER_CFG 0x0594 +#define AFE_SPDIFIN_APLL_TUNER_CFG1 0x0598 +#define ASYS_TOP_CON 0x0600 +#define AFE_LINEIN_APLL_TUNER_CFG 0x0610 +#define AFE_LINEIN_APLL_TUNER_MON 0x0614 +#define AFE_EARC_APLL_TUNER_CFG 0x0618 +#define AFE_EARC_APLL_TUNER_MON 0x061c +#define PWR2_TOP_CON0 0x0634 +#define PWR2_TOP_CON1 0x0638 +#define PCM_INTF_CON1 0x063c +#define PCM_INTF_CON2 0x0640 +#define AFE_CM0_CON 0x0660 +#define AFE_CM1_CON 0x0664 +#define AFE_CM2_CON 0x0668 +#define AFE_CM0_MON 0x0670 +#define AFE_CM1_MON 0x0674 +#define AFE_CM2_MON 0x0678 +#define AFE_MPHONE_MULTI_CON0 0x06a4 +#define AFE_MPHONE_MULTI_CON1 0x06a8 +#define AFE_MPHONE_MULTI_CON2 0x06ac +#define AFE_MPHONE_MULTI_MON 0x06b0 +#define AFE_MPHONE_MULTI_DET_REG_CON0 0x06b4 +#define AFE_MPHONE_MULTI_DET_REG_CON1 0x06b8 +#define AFE_MPHONE_MULTI_DET_REG_CON2 0x06bc +#define AFE_MPHONE_MULTI_DET_REG_CON3 0x06c0 +#define AFE_MPHONE_MULTI_DET_MON0 0x06c4 +#define AFE_MPHONE_MULTI_DET_MON1 0x06c8 +#define AFE_MPHONE_MULTI_DET_MON2 0x06d0 +#define AFE_MPHONE_MULTI2_CON0 0x06d4 +#define AFE_MPHONE_MULTI2_CON1 0x06d8 +#define AFE_MPHONE_MULTI2_CON2 0x06dc +#define AFE_MPHONE_MULTI2_MON 0x06e0 +#define AFE_MPHONE_MULTI2_DET_REG_CON0 0x06e4 +#define AFE_MPHONE_MULTI2_DET_REG_CON1 0x06e8 +#define AFE_MPHONE_MULTI2_DET_REG_CON2 0x06ec +#define AFE_MPHONE_MULTI2_DET_REG_CON3 0x06f0 +#define AFE_MPHONE_MULTI2_DET_MON0 0x06f4 +#define AFE_MPHONE_MULTI2_DET_MON1 0x06f8 +#define AFE_MPHONE_MULTI2_DET_MON2 0x06fc +#define AFE_ADDA_IIR_COEF_02_01 0x0700 +#define AFE_ADDA_IIR_COEF_04_03 0x0704 +#define AFE_ADDA_IIR_COEF_06_05 0x0708 +#define AFE_ADDA_IIR_COEF_08_07 0x070c +#define AFE_ADDA_IIR_COEF_10_09 0x0710 +#define AFE_ADDA_ULCF_CFG_02_01 0x0714 +#define AFE_ADDA_ULCF_CFG_04_03 0x0718 +#define AFE_ADDA_ULCF_CFG_06_05 0x071c +#define AFE_ADDA_ULCF_CFG_08_07 0x0720 +#define AFE_ADDA_ULCF_CFG_10_09 0x0724 +#define AFE_ADDA_ULCF_CFG_12_11 0x0728 +#define AFE_ADDA_ULCF_CFG_14_13 0x072c +#define AFE_ADDA_ULCF_CFG_16_15 0x0730 +#define AFE_ADDA_ULCF_CFG_18_17 0x0734 +#define AFE_ADDA_ULCF_CFG_20_19 0x0738 +#define AFE_ADDA_ULCF_CFG_22_21 0x073c +#define AFE_ADDA_ULCF_CFG_24_23 0x0740 +#define AFE_ADDA_ULCF_CFG_26_25 0x0744 +#define AFE_ADDA_ULCF_CFG_28_27 0x0748 +#define AFE_ADDA_ULCF_CFG_30_29 0x074c +#define AFE_ADDA6_IIR_COEF_02_01 0x0750 +#define AFE_ADDA6_IIR_COEF_04_03 0x0754 +#define AFE_ADDA6_IIR_COEF_06_05 0x0758 +#define AFE_ADDA6_IIR_COEF_08_07 0x075c +#define AFE_ADDA6_IIR_COEF_10_09 0x0760 +#define AFE_ADDA6_ULCF_CFG_02_01 0x0764 +#define AFE_ADDA6_ULCF_CFG_04_03 0x0768 +#define AFE_ADDA6_ULCF_CFG_06_05 0x076c +#define AFE_ADDA6_ULCF_CFG_08_07 0x0770 +#define AFE_ADDA6_ULCF_CFG_10_09 0x0774 +#define AFE_ADDA6_ULCF_CFG_12_11 0x0778 +#define AFE_ADDA6_ULCF_CFG_14_13 0x077c +#define AFE_ADDA6_ULCF_CFG_16_15 0x0780 +#define AFE_ADDA6_ULCF_CFG_18_17 0x0784 +#define AFE_ADDA6_ULCF_CFG_20_19 0x0788 +#define AFE_ADDA6_ULCF_CFG_22_21 0x078c +#define AFE_ADDA6_ULCF_CFG_24_23 0x0790 +#define AFE_ADDA6_ULCF_CFG_26_25 0x0794 +#define AFE_ADDA6_ULCF_CFG_28_27 0x0798 +#define AFE_ADDA6_ULCF_CFG_30_29 0x079c +#define AFE_ADDA_MTKAIF_CFG0 0x07a0 +#define AFE_ADDA_MTKAIF_SYNCWORD_CFG 0x07a8 +#define AFE_ADDA_MTKAIF_RX_CFG0 0x07b4 +#define AFE_ADDA_MTKAIF_RX_CFG1 0x07b8 +#define AFE_ADDA_MTKAIF_RX_CFG2 0x07bc +#define AFE_ADDA_MTKAIF_MON0 0x07c8 +#define AFE_ADDA_MTKAIF_MON1 0x07cc +#define AFE_AUD_PAD_TOP 0x07d4 +#define AFE_ADDA6_MTKAIF_MON0 0x07d8 +#define AFE_ADDA6_MTKAIF_MON1 0x07dc +#define AFE_ADDA6_MTKAIF_CFG0 0x07e0 +#define AFE_ADDA6_MTKAIF_RX_CFG0 0x07e4 +#define AFE_ADDA6_MTKAIF_RX_CFG1 0x07e8 +#define AFE_ADDA6_MTKAIF_RX_CFG2 0x07ec +#define AFE_ADDA6_TOP_CON0 0x07f0 +#define AFE_ADDA6_UL_SRC_CON0 0x07f4 +#define AFE_ADDA6_UL_SRC_CON1 0x07f8 +#define AFE_ADDA6_SRC_DEBUG 0x0800 +#define AFE_ADDA6_SRC_DEBUG_MON0 0x0804 +#define AFE_ADDA6_UL_SRC_MON0 0x0818 +#define AFE_ADDA6_UL_SRC_MON1 0x081c +#define AFE_CONN0_5 0x0830 +#define AFE_CONN1_5 0x0834 +#define AFE_CONN2_5 0x0838 +#define AFE_CONN3_5 0x083c +#define AFE_CONN4_5 0x0840 +#define AFE_CONN5_5 0x0844 +#define AFE_CONN6_5 0x0848 +#define AFE_CONN7_5 0x084c +#define AFE_CONN8_5 0x0850 +#define AFE_CONN9_5 0x0854 +#define AFE_CONN10_5 0x0858 +#define AFE_CONN11_5 0x085c +#define AFE_CONN12_5 0x0860 +#define AFE_CONN13_5 0x0864 +#define AFE_CONN14_5 0x0868 +#define AFE_CONN15_5 0x086c +#define AFE_CONN16_5 0x0870 +#define AFE_CONN17_5 0x0874 +#define AFE_CONN18_5 0x0878 +#define AFE_CONN19_5 0x087c +#define AFE_CONN20_5 0x0880 +#define AFE_CONN21_5 0x0884 +#define AFE_CONN22_5 0x0888 +#define AFE_CONN23_5 0x088c +#define AFE_CONN24_5 0x0890 +#define AFE_CONN25_5 0x0894 +#define AFE_CONN26_5 0x0898 +#define AFE_CONN27_5 0x089c +#define AFE_CONN28_5 0x08a0 +#define AFE_CONN29_5 0x08a4 +#define AFE_CONN30_5 0x08a8 +#define AFE_CONN31_5 0x08ac +#define AFE_CONN32_5 0x08b0 +#define AFE_CONN33_5 0x08b4 +#define AFE_CONN34_5 0x08b8 +#define AFE_CONN35_5 0x08bc +#define AFE_CONN36_5 0x08c0 +#define AFE_CONN37_5 0x08c4 +#define AFE_CONN38_5 0x08c8 +#define AFE_CONN39_5 0x08cc +#define AFE_CONN40_5 0x08d0 +#define AFE_CONN41_5 0x08d4 +#define AFE_CONN42_5 0x08d8 +#define AFE_CONN43_5 0x08dc +#define AFE_CONN44_5 0x08e0 +#define AFE_CONN45_5 0x08e4 +#define AFE_CONN46_5 0x08e8 +#define AFE_CONN47_5 0x08ec +#define AFE_CONN48_5 0x08f0 +#define AFE_CONN49_5 0x08f4 +#define AFE_CONN50_5 0x08f8 +#define AFE_CONN51_5 0x08fc +#define AFE_CONN52_5 0x0900 +#define AFE_CONN53_5 0x0904 +#define AFE_CONN54_5 0x0908 +#define AFE_CONN55_5 0x090c +#define AFE_CONN56_5 0x0910 +#define AFE_CONN57_5 0x0914 +#define AFE_CONN58_5 0x0918 +#define AFE_CONN59_5 0x091c +#define AFE_CONN60_5 0x0920 +#define AFE_CONN61_5 0x0924 +#define AFE_CONN62_5 0x0928 +#define AFE_CONN63_5 0x092c +#define AFE_CONN64_5 0x0930 +#define AFE_CONN65_5 0x0934 +#define AFE_CONN66_5 0x0938 +#define AFE_CONN67_5 0x093c +#define AFE_CONN68_5 0x0940 +#define AFE_CONN69_5 0x0944 +#define AFE_CONN70_5 0x0948 +#define AFE_CONN71_5 0x094c +#define AFE_CONN72_5 0x0950 +#define AFE_CONN73_5 0x0954 +#define AFE_CONN74_5 0x0958 +#define AFE_CONN75_5 0x095c +#define AFE_CONN76_5 0x0960 +#define AFE_CONN77_5 0x0964 +#define AFE_CONN78_5 0x0968 +#define AFE_CONN79_5 0x096c +#define AFE_CONN80_5 0x0970 +#define AFE_CONN81_5 0x0974 +#define AFE_CONN82_5 0x0978 +#define AFE_CONN83_5 0x097c +#define AFE_CONN84_5 0x0980 +#define AFE_CONN85_5 0x0984 +#define AFE_CONN86_5 0x0988 +#define AFE_CONN87_5 0x098c +#define AFE_CONN88_5 0x0990 +#define AFE_CONN89_5 0x0994 +#define AFE_CONN90_5 0x0998 +#define AFE_CONN91_5 0x099c +#define AFE_CONN92_5 0x09a0 +#define AFE_CONN93_5 0x09a4 +#define AFE_CONN94_5 0x09a8 +#define AFE_CONN95_5 0x09ac +#define AFE_CONN96_5 0x09b0 +#define AFE_CONN97_5 0x09b4 +#define AFE_CONN98_5 0x09b8 +#define AFE_CONN99_5 0x09bc +#define AFE_CONN100_5 0x09c0 +#define AFE_CONN101_5 0x09c4 +#define AFE_CONN102_5 0x09c8 +#define AFE_CONN103_5 0x09cc +#define AFE_CONN104_5 0x09d0 +#define AFE_CONN105_5 0x09d4 +#define AFE_CONN106_5 0x09d8 +#define AFE_CONN107_5 0x09dc +#define AFE_CONN108_5 0x09e0 +#define AFE_CONN109_5 0x09e4 +#define AFE_CONN110_5 0x09e8 +#define AFE_CONN111_5 0x09ec +#define AFE_CONN112_5 0x09f0 +#define AFE_CONN113_5 0x09f4 +#define AFE_CONN114_5 0x09f8 +#define AFE_CONN115_5 0x09fc +#define AFE_CONN116_5 0x0a00 +#define AFE_CONN117_5 0x0a04 +#define AFE_CONN118_5 0x0a08 +#define AFE_CONN119_5 0x0a0c +#define AFE_CONN120_5 0x0a10 +#define AFE_CONN121_5 0x0a14 +#define AFE_CONN122_5 0x0a18 +#define AFE_CONN123_5 0x0a1c +#define AFE_CONN124_5 0x0a20 +#define AFE_CONN125_5 0x0a24 +#define AFE_CONN126_5 0x0a28 +#define AFE_CONN127_5 0x0a2c +#define AFE_CONN128_5 0x0a30 +#define AFE_CONN129_5 0x0a34 +#define AFE_CONN130_5 0x0a38 +#define AFE_CONN131_5 0x0a3c +#define AFE_CONN132_5 0x0a40 +#define AFE_CONN133_5 0x0a44 +#define AFE_CONN134_5 0x0a48 +#define AFE_CONN135_5 0x0a4c +#define AFE_CONN136_5 0x0a50 +#define AFE_CONN137_5 0x0a54 +#define AFE_CONN138_5 0x0a58 +#define AFE_CONN139_5 0x0a5c +#define AFE_CONN_RS_5 0x0a60 +#define AFE_CONN_DI_5 0x0a64 +#define AFE_CONN_16BIT_5 0x0a68 +#define AFE_CONN_24BIT_5 0x0a6c +#define AFE_SECURE_MASK_CONN53_5 0x0a70 +#define AFE_SECURE_MASK_CONN54_5 0x0a74 +#define AFE_SECURE_MASK_CONN55_5 0x0a78 +#define AFE_SECURE_MASK_CONN56_5 0x0a7c +#define AFE_SECURE_MASK_CONN57_5 0x0a80 +#define AFE_SECURE_MASK_CONN58_5 0x0a84 +#define AFE_SECURE_MASK_CONN59_5 0x0a88 +#define AFE_SECURE_MASK_CONN60_5 0x0a8c +#define AFE_SECURE_MASK_CONN61_5 0x0a90 +#define AFE_SECURE_MASK_CONN62_5 0x0a94 +#define AFE_SECURE_MASK_CONN63_5 0x0a98 +#define AFE_SECURE_MASK_CONN64_5 0x0a9c +#define AFE_SECURE_MASK_CONN65_5 0x0aa0 +#define AFE_SECURE_MASK_CONN66_5 0x0aa4 +#define AFE_SECURE_MASK_CONN67_5 0x0aa8 +#define AFE_SECURE_MASK_CONN68_5 0x0aac +#define AFE_SECURE_MASK_CONN69_5 0x0ab0 +#define AFE_SECURE_MASK_CONN70_5 0x0ab4 +#define AFE_SECURE_MASK_CONN71_5 0x0ab8 +#define AFE_SECURE_MASK_CONN72_5 0x0abc +#define AFE_SECURE_MASK_CONN73_5 0x0ac0 +#define AFE_SECURE_MASK_CONN74_5 0x0ac4 +#define AFE_SECURE_MASK_CONN75_5 0x0ac8 +#define AFE_SECURE_MASK_CONN76_5 0x0acc +#define AFE_SECURE_MASK_CONN77_5 0x0ad0 +#define AFE_SECURE_MASK_CONN78_5 0x0ad4 +#define AFE_SECURE_MASK_CONN79_5 0x0ad8 +#define AFE_SECURE_MASK_CONN80_5 0x0adc +#define AFE_SECURE_MASK_CONN81_5 0x0ae0 +#define AFE_SECURE_MASK_CONN82_5 0x0ae4 +#define AFE_SECURE_MASK_CONN83_5 0x0ae8 +#define AFE_SECURE_MASK_CONN84_5 0x0aec +#define AFE_SECURE_MASK_CONN85_5 0x0af0 +#define AFE_SECURE_MASK_CONN86_5 0x0af4 +#define AFE_SECURE_MASK_CONN87_5 0x0af8 +#define AFE_SECURE_MASK_CONN88_5 0x0afc +#define AFE_SECURE_MASK_CONN89_5 0x0b00 +#define AFE_SECURE_MASK_CONN90_5 0x0b04 +#define AFE_SECURE_MASK_CONN91_5 0x0b08 +#define AFE_SECURE_MASK_CONN92_5 0x0b0c +#define AFE_SECURE_MASK_CONN93_5 0x0b10 +#define AFE_SECURE_MASK_CONN94_5 0x0b14 +#define AFE_SECURE_MASK_CONN95_5 0x0b18 +#define AFE_SECURE_MASK_CONN96_5 0x0b1c +#define AFE_SECURE_MASK_CONN97_5 0x0b20 +#define AFE_SECURE_MASK_CONN98_5 0x0b24 +#define AFE_SECURE_MASK_CONN99_5 0x0b28 +#define AFE_SECURE_MASK_CONN100_5 0x0b2c +#define AFE_SECURE_MASK_CONN101_5 0x0b30 +#define AFE_SECURE_MASK_CONN102_5 0x0b34 +#define AFE_SECURE_MASK_CONN103_5 0x0b38 +#define AFE_SECURE_MASK_CONN104_5 0x0b3c +#define AFE_SECURE_MASK_CONN105_5 0x0b40 +#define AFE_SECURE_MASK_CONN106_5 0x0b44 +#define AFE_SECURE_MASK_CONN107_5 0x0b48 +#define AFE_SECURE_MASK_CONN108_5 0x0b4c +#define AFE_SECURE_MASK_CONN109_5 0x0b50 +#define AFE_SECURE_MASK_CONN110_5 0x0b54 +#define AFE_SECURE_MASK_CONN111_5 0x0b58 +#define AFE_SECURE_MASK_CONN112_5 0x0b5c +#define AFE_SECURE_MASK_CONN113_5 0x0b60 +#define AFE_SECURE_MASK_CONN114_5 0x0b64 +#define AFE_SECURE_MASK_CONN115_5 0x0b68 +#define AFE_SECURE_MASK_CONN116_5 0x0b6c +#define AFE_SECURE_MASK_CONN117_5 0x0b70 +#define AFE_SECURE_MASK_CONN118_5 0x0b74 +#define AFE_SECURE_MASK_CONN119_5 0x0b78 +#define AFE_SECURE_MASK_CONN120_5 0x0b7c +#define AFE_SECURE_MASK_CONN121_5 0x0b80 +#define AFE_SECURE_MASK_CONN122_5 0x0b84 +#define AFE_SECURE_MASK_CONN123_5 0x0b88 +#define AFE_SECURE_MASK_CONN124_5 0x0b8c +#define AFE_SECURE_MASK_CONN125_5 0x0b90 +#define AFE_SECURE_MASK_CONN126_5 0x0b94 +#define AFE_SECURE_MASK_CONN127_5 0x0b98 +#define AFE_SECURE_MASK_CONN128_5 0x0b9c +#define AFE_SECURE_MASK_CONN129_5 0x0ba0 +#define AFE_SECURE_MASK_CONN130_5 0x0ba4 +#define AFE_SECURE_MASK_CONN131_5 0x0ba8 +#define AFE_SECURE_MASK_CONN132_5 0x0bac +#define AFE_SECURE_MASK_CONN133_5 0x0bb0 +#define AFE_SECURE_MASK_CONN134_5 0x0bb4 +#define AFE_SECURE_MASK_CONN135_5 0x0bb8 +#define AFE_SECURE_MASK_CONN136_5 0x0bbc +#define AFE_SECURE_MASK_CONN137_5 0x0bc0 +#define AFE_SECURE_MASK_CONN138_5 0x0bc4 +#define AFE_SECURE_MASK_CONN139_5 0x0bc8 +#define AFE_SECURE_MASK_CONN_RS_5 0x0bcc +#define AFE_SECURE_MASK_CONN_16BIT_5 0x0bd0 +#define AFE_SECURE_MASK_CONN_24BIT_5 0x0bd4 +#define AFE_ASRC11_NEW_CON0 0x0d80 +#define AFE_ASRC11_NEW_CON1 0x0d84 +#define AFE_ASRC11_NEW_CON2 0x0d88 +#define AFE_ASRC11_NEW_CON3 0x0d8c +#define AFE_ASRC11_NEW_CON4 0x0d90 +#define AFE_ASRC11_NEW_CON5 0x0d94 +#define AFE_ASRC11_NEW_CON6 0x0d98 +#define AFE_ASRC11_NEW_CON7 0x0d9c +#define AFE_ASRC11_NEW_CON8 0x0da0 +#define AFE_ASRC11_NEW_CON9 0x0da4 +#define AFE_ASRC11_NEW_CON10 0x0da8 +#define AFE_ASRC11_NEW_CON11 0x0dac +#define AFE_ASRC11_NEW_CON13 0x0db4 +#define AFE_ASRC11_NEW_CON14 0x0db8 +#define AFE_ASRC12_NEW_CON0 0x0dc0 +#define AFE_ASRC12_NEW_CON1 0x0dc4 +#define AFE_ASRC12_NEW_CON2 0x0dc8 +#define AFE_ASRC12_NEW_CON3 0x0dcc +#define AFE_ASRC12_NEW_CON4 0x0dd0 +#define AFE_ASRC12_NEW_CON5 0x0dd4 +#define AFE_ASRC12_NEW_CON6 0x0dd8 +#define AFE_ASRC12_NEW_CON7 0x0ddc +#define AFE_ASRC12_NEW_CON8 0x0de0 +#define AFE_ASRC12_NEW_CON9 0x0de4 +#define AFE_ASRC12_NEW_CON10 0x0de8 +#define AFE_ASRC12_NEW_CON11 0x0dec +#define AFE_ASRC12_NEW_CON13 0x0df4 +#define AFE_ASRC12_NEW_CON14 0x0df8 +#define AFE_SECURE_MASK_CONN176 0x0fe0 +#define AFE_SECURE_MASK_CONN176_1 0x0fe4 +#define AFE_SECURE_MASK_CONN176_2 0x0fe8 +#define AFE_SECURE_MASK_CONN176_3 0x0fec +#define AFE_SECURE_MASK_CONN176_4 0x0ff0 +#define AFE_SECURE_MASK_CONN176_5 0x0ff4 +#define AFE_SECURE_MASK_CONN177 0x0ff8 +#define AFE_SECURE_MASK_CONN177_1 0x0ffc +#define AFE_LRCK_CNT 0x1018 +#define AFE_SECURE_MASK_CONN177_2 0x1020 +#define AFE_SECURE_MASK_CONN177_3 0x1024 +#define AFE_SECURE_MASK_CONN177_4 0x1028 +#define AFE_SECURE_MASK_CONN177_5 0x102c +#define AFE_SECURE_MASK_CONN182 0x1090 +#define AFE_SECURE_MASK_CONN182_1 0x1094 +#define AFE_SECURE_MASK_CONN182_2 0x1098 +#define AFE_SECURE_MASK_CONN182_3 0x109c +#define AFE_SECURE_MASK_CONN182_4 0x10a0 +#define AFE_SECURE_MASK_CONN182_5 0x10a4 +#define AFE_SECURE_MASK_CONN183 0x10a8 +#define AFE_SECURE_MASK_CONN183_1 0x10ac +#define AFE_SECURE_MASK_CONN183_2 0x10b0 +#define AFE_SECURE_MASK_CONN183_3 0x10b4 +#define AFE_SECURE_MASK_CONN183_4 0x10b8 +#define AFE_SECURE_MASK_CONN183_5 0x10bc +#define AFE_DAC_CON0 0x1200 +#define AFE_DAC_CON1 0x1204 +#define AFE_DAC_CON2 0x1208 +#define AFE_DAC_MON0 0x1218 +#define AFE_DL1_BASE 0x1240 +#define AFE_DL1_CUR 0x1244 +#define AFE_DL1_END 0x1248 +#define AFE_DL1_CON0 0x124c +#define AFE_DL2_BASE 0x1250 +#define AFE_DL2_CUR 0x1254 +#define AFE_DL2_END 0x1258 +#define AFE_DL2_CON0 0x125c +#define AFE_DL3_BASE 0x1260 +#define AFE_DL3_CUR 0x1264 +#define AFE_DL3_END 0x1268 +#define AFE_DL3_CON0 0x126c +#define AFE_DL6_BASE 0x1290 +#define AFE_DL6_CUR 0x1294 +#define AFE_DL6_END 0x1298 +#define AFE_DL6_CON0 0x129c +#define AFE_DL7_BASE 0x12a0 +#define AFE_DL7_CUR 0x12a4 +#define AFE_DL7_END 0x12a8 +#define AFE_DL7_CON0 0x12ac +#define AFE_DL8_BASE 0x12b0 +#define AFE_DL8_CUR 0x12b4 +#define AFE_DL8_END 0x12b8 +#define AFE_DL8_CON0 0x12bc +#define AFE_DL10_BASE 0x12d0 +#define AFE_DL10_CUR 0x12d4 +#define AFE_DL10_END 0x12d8 +#define AFE_DL10_CON0 0x12dc +#define AFE_DL11_BASE 0x12e0 +#define AFE_DL11_CUR 0x12e4 +#define AFE_DL11_END 0x12e8 +#define AFE_DL11_CON0 0x12ec +#define AFE_UL1_BASE 0x1300 +#define AFE_UL1_CUR 0x1304 +#define AFE_UL1_END 0x1308 +#define AFE_UL1_CON0 0x130c +#define AFE_UL2_BASE 0x1310 +#define AFE_UL2_CUR 0x1314 +#define AFE_UL2_END 0x1318 +#define AFE_UL2_CON0 0x131c +#define AFE_UL3_BASE 0x1320 +#define AFE_UL3_CUR 0x1324 +#define AFE_UL3_END 0x1328 +#define AFE_UL3_CON0 0x132c +#define AFE_UL4_BASE 0x1330 +#define AFE_UL4_CUR 0x1334 +#define AFE_UL4_END 0x1338 +#define AFE_UL4_CON0 0x133c +#define AFE_UL5_BASE 0x1340 +#define AFE_UL5_CUR 0x1344 +#define AFE_UL5_END 0x1348 +#define AFE_UL5_CON0 0x134c +#define AFE_UL6_BASE 0x1350 +#define AFE_UL6_CUR 0x1354 +#define AFE_UL6_END 0x1358 +#define AFE_UL6_CON0 0x135c +#define AFE_UL8_BASE 0x1370 +#define AFE_UL8_CUR 0x1374 +#define AFE_UL8_END 0x1378 +#define AFE_UL8_CON0 0x137c +#define AFE_UL9_BASE 0x1380 +#define AFE_UL9_CUR 0x1384 +#define AFE_UL9_END 0x1388 +#define AFE_UL9_CON0 0x138c +#define AFE_UL10_BASE 0x13d0 +#define AFE_UL10_CUR 0x13d4 +#define AFE_UL10_END 0x13d8 +#define AFE_UL10_CON0 0x13dc +#define AFE_DL8_CHK_SUM1 0x1400 +#define AFE_DL8_CHK_SUM2 0x1404 +#define AFE_DL8_CHK_SUM3 0x1408 +#define AFE_DL8_CHK_SUM4 0x140c +#define AFE_DL8_CHK_SUM5 0x1410 +#define AFE_DL8_CHK_SUM6 0x1414 +#define AFE_DL10_CHK_SUM1 0x1418 +#define AFE_DL10_CHK_SUM2 0x141c +#define AFE_DL10_CHK_SUM3 0x1420 +#define AFE_DL10_CHK_SUM4 0x1424 +#define AFE_DL10_CHK_SUM5 0x1428 +#define AFE_DL10_CHK_SUM6 0x142c +#define AFE_DL11_CHK_SUM1 0x1430 +#define AFE_DL11_CHK_SUM2 0x1434 +#define AFE_DL11_CHK_SUM3 0x1438 +#define AFE_DL11_CHK_SUM4 0x143c +#define AFE_DL11_CHK_SUM5 0x1440 +#define AFE_DL11_CHK_SUM6 0x1444 +#define AFE_UL1_CHK_SUM1 0x1450 +#define AFE_UL1_CHK_SUM2 0x1454 +#define AFE_UL2_CHK_SUM1 0x1458 +#define AFE_UL2_CHK_SUM2 0x145c +#define AFE_UL3_CHK_SUM1 0x1460 +#define AFE_UL3_CHK_SUM2 0x1464 +#define AFE_UL4_CHK_SUM1 0x1468 +#define AFE_UL4_CHK_SUM2 0x146c +#define AFE_UL5_CHK_SUM1 0x1470 +#define AFE_UL5_CHK_SUM2 0x1474 +#define AFE_UL6_CHK_SUM1 0x1478 +#define AFE_UL6_CHK_SUM2 0x147c +#define AFE_UL8_CHK_SUM1 0x1488 +#define AFE_UL8_CHK_SUM2 0x148c +#define AFE_DL1_CHK_SUM1 0x1490 +#define AFE_DL1_CHK_SUM2 0x1494 +#define AFE_DL2_CHK_SUM1 0x14a0 +#define AFE_DL2_CHK_SUM2 0x14a4 +#define AFE_DL3_CHK_SUM1 0x14b0 +#define AFE_DL3_CHK_SUM2 0x14b4 +#define AFE_DL6_CHK_SUM1 0x14e0 +#define AFE_DL6_CHK_SUM2 0x14e4 +#define AFE_DL7_CHK_SUM1 0x14f0 +#define AFE_DL7_CHK_SUM2 0x14f4 +#define AFE_UL9_CHK_SUM1 0x1528 +#define AFE_UL9_CHK_SUM2 0x152c +#define AFE_BUS_MON1 0x1540 +#define AFE_UL10_CHK_SUM1 0x1550 +#define AFE_UL10_CHK_SUM2 0x1554 +#define UL1_MOD2AGT_CNT_LAT 0x1568 +#define UL2_MOD2AGT_CNT_LAT 0x156c +#define UL3_MOD2AGT_CNT_LAT 0x1570 +#define UL4_MOD2AGT_CNT_LAT 0x1574 +#define UL5_MOD2AGT_CNT_LAT 0x1578 +#define UL6_MOD2AGT_CNT_LAT 0x157c +#define UL8_MOD2AGT_CNT_LAT 0x1588 +#define UL9_MOD2AGT_CNT_LAT 0x158c +#define UL10_MOD2AGT_CNT_LAT 0x1590 +#define AFE_MEMIF_AGENT_FS_CON0 0x15a0 +#define AFE_MEMIF_AGENT_FS_CON1 0x15a4 +#define AFE_MEMIF_AGENT_FS_CON2 0x15a8 +#define AFE_MEMIF_AGENT_FS_CON3 0x15ac +#define AFE_MEMIF_BURST_CFG 0x1600 +#define AFE_MEMIF_BUF_FULL_MON 0x1610 +#define AFE_MEMIF_BUF_MON0 0x1618 +#define AFE_MEMIF_BUF_MON1 0x161c +#define AFE_MEMIF_BUF_MON3 0x1624 +#define AFE_MEMIF_BUF_MON4 0x1628 +#define AFE_MEMIF_BUF_MON5 0x162c +#define AFE_MEMIF_BUF_MON6 0x1630 +#define AFE_MEMIF_BUF_MON7 0x1634 +#define AFE_MEMIF_BUF_MON8 0x1638 +#define AFE_MEMIF_BUF_MON9 0x163c +#define AFE_MEMIF_BUF_MON10 0x1640 +#define DL1_AGENT2MODULE_CNT 0x1674 +#define DL2_AGENT2MODULE_CNT 0x1678 +#define DL3_AGENT2MODULE_CNT 0x167c +#define DL6_AGENT2MODULE_CNT 0x1688 +#define DL7_AGENT2MODULE_CNT 0x168c +#define DL8_AGENT2MODULE_CNT 0x1690 +#define DL10_AGENT2MODULE_CNT 0x1698 +#define DL11_AGENT2MODULE_CNT 0x169c +#define UL1_MODULE2AGENT_CNT 0x16a0 +#define UL2_MODULE2AGENT_CNT 0x16a4 +#define UL3_MODULE2AGENT_CNT 0x16a8 +#define UL4_MODULE2AGENT_CNT 0x16ac +#define UL5_MODULE2AGENT_CNT 0x16b0 +#define UL6_MODULE2AGENT_CNT 0x16b4 +#define UL8_MODULE2AGENT_CNT 0x16bc +#define UL9_MODULE2AGENT_CNT 0x16c0 +#define UL10_MODULE2AGENT_CNT 0x16c4 +#define AFE_SECURE_CON2 0x1798 +#define AFE_SECURE_CON1 0x179c +#define AFE_SECURE_CON 0x17a0 +#define AFE_SRAM_BOUND 0x17a4 +#define AFE_SE_SECURE_CON 0x17a8 +#define AFE_SECURE_MASK_LOOPBACK 0x17bc +#define AFE_SRAM_SECURE_CON 0x1800 +#define AFE_SRAM_SECURE_CON1 0x1804 +#define AFE_SRAM_SECURE_CON2 0x1808 +#define AFE_SECURE_SIDEBAND0 0x1908 +#define AFE_SECURE_SIDEBAND1 0x190c +#define AFE_SECURE_SIDEBAND2 0x1910 +#define AFE_SECURE_SIDEBAND3 0x1914 +#define AFE_SECURE_MASK_BASE_ADR_MSB 0x1920 +#define AFE_SECURE_MASK_END_ADR_MSB 0x1924 +#define AFE_NORMAL_BASE_ADR_MSB 0x192c +#define AFE_NORMAL_END_ADR_MSB 0x1930 +#define AFE_SECURE_MASK_LOOPBACK0 0x1940 +#define AFE_SECURE_MASK_LOOPBACK1 0x1944 +#define AFE_SECURE_MASK_LOOPBACK2 0x1948 +#define AFE_LOOPBACK_CFG0 0x1950 +#define AFE_LOOPBACK_CFG1 0x1954 +#define AFE_LOOPBACK_CFG2 0x1958 +#define AFE_DMIC0_UL_SRC_CON0 0x1a00 +#define AFE_DMIC0_UL_SRC_CON1 0x1a04 +#define AFE_DMIC0_SRC_DEBUG 0x1a08 +#define AFE_DMIC0_SRC_DEBUG_MON0 0x1a0c +#define AFE_DMIC0_UL_SRC_MON0 0x1a10 +#define AFE_DMIC0_UL_SRC_MON1 0x1a14 +#define AFE_DMIC0_IIR_COEF_02_01 0x1a18 +#define AFE_DMIC0_IIR_COEF_04_03 0x1a1c +#define AFE_DMIC0_IIR_COEF_06_05 0x1a20 +#define AFE_DMIC0_IIR_COEF_08_07 0x1a24 +#define AFE_DMIC0_IIR_COEF_10_09 0x1a28 +#define AFE_DMIC1_UL_SRC_CON0 0x1a68 +#define AFE_DMIC1_UL_SRC_CON1 0x1a6c +#define AFE_DMIC1_SRC_DEBUG 0x1a70 +#define AFE_DMIC1_SRC_DEBUG_MON0 0x1a74 +#define AFE_DMIC1_UL_SRC_MON0 0x1a78 +#define AFE_DMIC1_UL_SRC_MON1 0x1a7c +#define AFE_DMIC1_IIR_COEF_02_01 0x1a80 +#define AFE_DMIC1_IIR_COEF_04_03 0x1a84 +#define AFE_DMIC1_IIR_COEF_06_05 0x1a88 +#define AFE_DMIC1_IIR_COEF_08_07 0x1a8c +#define AFE_DMIC1_IIR_COEF_10_09 0x1a90 +#define AFE_DMIC2_UL_SRC_CON0 0x1ad0 +#define AFE_DMIC2_UL_SRC_CON1 0x1ad4 +#define AFE_DMIC2_SRC_DEBUG 0x1ad8 +#define AFE_DMIC2_SRC_DEBUG_MON0 0x1adc +#define AFE_DMIC2_UL_SRC_MON0 0x1ae0 +#define AFE_DMIC2_UL_SRC_MON1 0x1ae4 +#define AFE_DMIC2_IIR_COEF_02_01 0x1ae8 +#define AFE_DMIC2_IIR_COEF_04_03 0x1aec +#define AFE_DMIC2_IIR_COEF_06_05 0x1af0 +#define AFE_DMIC2_IIR_COEF_08_07 0x1af4 +#define AFE_DMIC2_IIR_COEF_10_09 0x1af8 +#define AFE_DMIC3_UL_SRC_CON0 0x1b38 +#define AFE_DMIC3_UL_SRC_CON1 0x1b3c +#define AFE_DMIC3_SRC_DEBUG 0x1b40 +#define AFE_DMIC3_SRC_DEBUG_MON0 0x1b44 +#define AFE_DMIC3_UL_SRC_MON0 0x1b48 +#define AFE_DMIC3_UL_SRC_MON1 0x1b4c +#define AFE_DMIC3_IIR_COEF_02_01 0x1b50 +#define AFE_DMIC3_IIR_COEF_04_03 0x1b54 +#define AFE_DMIC3_IIR_COEF_06_05 0x1b58 +#define AFE_DMIC3_IIR_COEF_08_07 0x1b5c +#define AFE_DMIC3_IIR_COEF_10_09 0x1b60 +#define DMIC_BYPASS_HW_GAIN 0x1bf0 +#define DMIC_GAIN1_CON0 0x1c00 +#define DMIC_GAIN1_CON1 0x1c04 +#define DMIC_GAIN1_CON2 0x1c08 +#define DMIC_GAIN1_CON3 0x1c0c +#define DMIC_GAIN1_CUR 0x1c10 +#define DMIC_GAIN2_CON0 0x1c20 +#define DMIC_GAIN2_CON1 0x1c24 +#define DMIC_GAIN2_CON2 0x1c28 +#define DMIC_GAIN2_CON3 0x1c2c +#define DMIC_GAIN2_CUR 0x1c30 +#define DMIC_GAIN3_CON0 0x1c40 +#define DMIC_GAIN3_CON1 0x1c44 +#define DMIC_GAIN3_CON2 0x1c48 +#define DMIC_GAIN3_CON3 0x1c4c +#define DMIC_GAIN3_CUR 0x1c50 +#define DMIC_GAIN4_CON0 0x1c60 +#define DMIC_GAIN4_CON1 0x1c64 +#define DMIC_GAIN4_CON2 0x1c68 +#define DMIC_GAIN4_CON3 0x1c6c +#define DMIC_GAIN4_CUR 0x1c70 +#define ETDM_OUT1_DSD_FADE_CON 0x2260 +#define ETDM_OUT1_DSD_FADE_CON1 0x2264 +#define ETDM_OUT3_DSD_FADE_CON 0x2280 +#define ETDM_OUT3_DSD_FADE_CON1 0x2284 +#define ETDM_IN1_AFIFO_CON 0x2294 +#define ETDM_IN2_AFIFO_CON 0x2298 +#define ETDM_IN1_MONITOR 0x22c0 +#define ETDM_IN2_MONITOR 0x22c4 +#define ETDM_OUT1_MONITOR 0x22d0 +#define ETDM_OUT2_MONITOR 0x22d4 +#define ETDM_OUT3_MONITOR 0x22d8 +#define ETDM_COWORK_SEC_CON0 0x22e0 +#define ETDM_COWORK_SEC_CON1 0x22e4 +#define ETDM_COWORK_SEC_CON2 0x22e8 +#define ETDM_COWORK_SEC_CON3 0x22ec +#define ETDM_COWORK_CON0 0x22f0 +#define ETDM_COWORK_CON1 0x22f4 +#define ETDM_COWORK_CON2 0x22f8 +#define ETDM_COWORK_CON3 0x22fc +#define ETDM_IN1_CON0 0x2300 +#define ETDM_IN1_CON1 0x2304 +#define ETDM_IN1_CON2 0x2308 +#define ETDM_IN1_CON3 0x230c +#define ETDM_IN1_CON4 0x2310 +#define ETDM_IN1_CON5 0x2314 +#define ETDM_IN1_CON6 0x2318 +#define ETDM_IN1_CON7 0x231c +#define ETDM_IN2_CON0 0x2320 +#define ETDM_IN2_CON1 0x2324 +#define ETDM_IN2_CON2 0x2328 +#define ETDM_IN2_CON3 0x232c +#define ETDM_IN2_CON4 0x2330 +#define ETDM_IN2_CON5 0x2334 +#define ETDM_IN2_CON6 0x2338 +#define ETDM_IN2_CON7 0x233c +#define ETDM_OUT1_CON0 0x2380 +#define ETDM_OUT1_CON1 0x2384 +#define ETDM_OUT1_CON2 0x2388 +#define ETDM_OUT1_CON3 0x238c +#define ETDM_OUT1_CON4 0x2390 +#define ETDM_OUT1_CON5 0x2394 +#define ETDM_OUT1_CON6 0x2398 +#define ETDM_OUT1_CON7 0x239c +#define ETDM_OUT2_CON0 0x23a0 +#define ETDM_OUT2_CON1 0x23a4 +#define ETDM_OUT2_CON2 0x23a8 +#define ETDM_OUT2_CON3 0x23ac +#define ETDM_OUT2_CON4 0x23b0 +#define ETDM_OUT2_CON5 0x23b4 +#define ETDM_OUT2_CON6 0x23b8 +#define ETDM_OUT2_CON7 0x23bc +#define ETDM_OUT3_CON0 0x23c0 +#define ETDM_OUT3_CON1 0x23c4 +#define ETDM_OUT3_CON2 0x23c8 +#define ETDM_OUT3_CON3 0x23cc +#define ETDM_OUT3_CON4 0x23d0 +#define ETDM_OUT3_CON5 0x23d4 +#define ETDM_OUT3_CON6 0x23d8 +#define ETDM_OUT3_CON7 0x23dc +#define ETDM_OUT3_CON8 0x23e0 +#define ETDM_OUT1_CON8 0x23e4 +#define ETDM_OUT2_CON8 0x23e8 +#define GASRC_TIMING_CON0 0x2414 +#define GASRC_TIMING_CON1 0x2418 +#define GASRC_TIMING_CON2 0x241c +#define GASRC_TIMING_CON3 0x2420 +#define GASRC_TIMING_CON4 0x2424 +#define GASRC_TIMING_CON5 0x2428 +#define A3_A4_TIMING_SEL0 0x2440 +#define A3_A4_TIMING_SEL1 0x2444 +#define A3_A4_TIMING_SEL2 0x2448 +#define A3_A4_TIMING_SEL3 0x244c +#define A3_A4_TIMING_SEL4 0x2450 +#define A3_A4_TIMING_SEL5 0x2454 +#define A3_A4_TIMING_SEL6 0x2458 +#define ASYS_TOP_DEBUG 0x2500 +#define AFE_DPTX_CON 0x2558 +#define AFE_DPTX_MON 0x255c +#define AFE_ADDA_DL_SRC2_CON0 0x2d00 +#define AFE_ADDA_DL_SRC2_CON1 0x2d04 +#define AFE_ADDA_TOP_CON0 0x2d0c +#define AFE_ADDA_UL_DL_CON0 0x2d10 +#define AFE_ADDA_SRC_DEBUG 0x2d14 +#define AFE_ADDA_SRC_DEBUG_MON0 0x2d18 +#define AFE_ADDA_SRC_DEBUG_MON1 0x2d20 +#define AFE_ADDA_PREDIS_CON0 0x2d24 +#define AFE_ADDA_PREDIS_CON1 0x2d28 +#define AFE_ADDA_PREDIS_CON2 0x2d2c +#define AFE_ADDA_PREDIS_CON3 0x2d30 +#define AFE_ADDA_DL_SDM_DCCOMP_CON 0x2d34 +#define AFE_ADDA_DL_SDM_TEST 0x2d38 +#define AFE_ADDA_DL_DC_COMP_CFG0 0x2d3c +#define AFE_ADDA_DL_DC_COMP_CFG1 0x2d40 +#define AFE_ADDA_DL_SDM_FIFO_MON 0x2d44 +#define AFE_ADDA_DL_SRC_LCH_MON 0x2d50 +#define AFE_ADDA_DL_SRC_RCH_MON 0x2d54 +#define AFE_ADDA_DL_SDM_OUT_MON 0x2d58 +#define AFE_ADDA_DL_SDM_DITHER_CON 0x2d5c +#define AFE_ADDA_DL_SDM_AUTO_RESET_CON 0x2d60 +#define AFE_ADDA_UL_SRC_CON0 0x2e3c +#define AFE_ADDA_UL_SRC_CON1 0x2e40 +#define AFE_CONN0 0x3000 +#define AFE_CONN0_1 0x3004 +#define AFE_CONN0_2 0x3008 +#define AFE_CONN0_3 0x300c +#define AFE_CONN0_4 0x3010 +#define AFE_CONN1 0x3014 +#define AFE_CONN1_1 0x3018 +#define AFE_CONN1_2 0x301c +#define AFE_CONN1_3 0x3020 +#define AFE_CONN1_4 0x3024 +#define AFE_CONN2 0x3028 +#define AFE_CONN2_1 0x302c +#define AFE_CONN2_2 0x3030 +#define AFE_CONN2_3 0x3034 +#define AFE_CONN2_4 0x3038 +#define AFE_CONN3 0x303c +#define AFE_CONN3_1 0x3040 +#define AFE_CONN3_2 0x3044 +#define AFE_CONN3_3 0x3048 +#define AFE_CONN3_4 0x304c +#define AFE_CONN4 0x3050 +#define AFE_CONN4_1 0x3054 +#define AFE_CONN4_2 0x3058 +#define AFE_CONN4_3 0x305c +#define AFE_CONN4_4 0x3060 +#define AFE_CONN5 0x3064 +#define AFE_CONN5_1 0x3068 +#define AFE_CONN5_2 0x306c +#define AFE_CONN5_3 0x3070 +#define AFE_CONN5_4 0x3074 +#define AFE_CONN6 0x3078 +#define AFE_CONN6_1 0x307c +#define AFE_CONN6_2 0x3080 +#define AFE_CONN6_3 0x3084 +#define AFE_CONN6_4 0x3088 +#define AFE_CONN7 0x308c +#define AFE_CONN7_1 0x3090 +#define AFE_CONN7_2 0x3094 +#define AFE_CONN7_3 0x3098 +#define AFE_CONN7_4 0x309c +#define AFE_CONN8 0x30a0 +#define AFE_CONN8_1 0x30a4 +#define AFE_CONN8_2 0x30a8 +#define AFE_CONN8_3 0x30ac +#define AFE_CONN8_4 0x30b0 +#define AFE_CONN9 0x30b4 +#define AFE_CONN9_1 0x30b8 +#define AFE_CONN9_2 0x30bc +#define AFE_CONN9_3 0x30c0 +#define AFE_CONN9_4 0x30c4 +#define AFE_CONN10 0x30c8 +#define AFE_CONN10_1 0x30cc +#define AFE_CONN10_2 0x30d0 +#define AFE_CONN10_3 0x30d4 +#define AFE_CONN10_4 0x30d8 +#define AFE_CONN11 0x30dc +#define AFE_CONN11_1 0x30e0 +#define AFE_CONN11_2 0x30e4 +#define AFE_CONN11_3 0x30e8 +#define AFE_CONN11_4 0x30ec +#define AFE_CONN12 0x30f0 +#define AFE_CONN12_1 0x30f4 +#define AFE_CONN12_2 0x30f8 +#define AFE_CONN12_3 0x30fc +#define AFE_CONN12_4 0x3100 +#define AFE_CONN13 0x3104 +#define AFE_CONN13_1 0x3108 +#define AFE_CONN13_2 0x310c +#define AFE_CONN13_3 0x3110 +#define AFE_CONN13_4 0x3114 +#define AFE_CONN14 0x3118 +#define AFE_CONN14_1 0x311c +#define AFE_CONN14_2 0x3120 +#define AFE_CONN14_3 0x3124 +#define AFE_CONN14_4 0x3128 +#define AFE_CONN15 0x312c +#define AFE_CONN15_1 0x3130 +#define AFE_CONN15_2 0x3134 +#define AFE_CONN15_3 0x3138 +#define AFE_CONN15_4 0x313c +#define AFE_CONN16 0x3140 +#define AFE_CONN16_1 0x3144 +#define AFE_CONN16_2 0x3148 +#define AFE_CONN16_3 0x314c +#define AFE_CONN16_4 0x3150 +#define AFE_CONN17 0x3154 +#define AFE_CONN17_1 0x3158 +#define AFE_CONN17_2 0x315c +#define AFE_CONN17_3 0x3160 +#define AFE_CONN17_4 0x3164 +#define AFE_CONN18 0x3168 +#define AFE_CONN18_1 0x316c +#define AFE_CONN18_2 0x3170 +#define AFE_CONN18_3 0x3174 +#define AFE_CONN18_4 0x3178 +#define AFE_CONN19 0x317c +#define AFE_CONN19_1 0x3180 +#define AFE_CONN19_2 0x3184 +#define AFE_CONN19_3 0x3188 +#define AFE_CONN19_4 0x318c +#define AFE_CONN20 0x3190 +#define AFE_CONN20_1 0x3194 +#define AFE_CONN20_2 0x3198 +#define AFE_CONN20_3 0x319c +#define AFE_CONN20_4 0x31a0 +#define AFE_CONN21 0x31a4 +#define AFE_CONN21_1 0x31a8 +#define AFE_CONN21_2 0x31ac +#define AFE_CONN21_3 0x31b0 +#define AFE_CONN21_4 0x31b4 +#define AFE_CONN22 0x31b8 +#define AFE_CONN22_1 0x31bc +#define AFE_CONN22_2 0x31c0 +#define AFE_CONN22_3 0x31c4 +#define AFE_CONN22_4 0x31c8 +#define AFE_CONN23 0x31cc +#define AFE_CONN23_1 0x31d0 +#define AFE_CONN23_2 0x31d4 +#define AFE_CONN23_3 0x31d8 +#define AFE_CONN23_4 0x31dc +#define AFE_CONN24 0x31e0 +#define AFE_CONN24_1 0x31e4 +#define AFE_CONN24_2 0x31e8 +#define AFE_CONN24_3 0x31ec +#define AFE_CONN24_4 0x31f0 +#define AFE_CONN25 0x31f4 +#define AFE_CONN25_1 0x31f8 +#define AFE_CONN25_2 0x31fc +#define AFE_CONN25_3 0x3200 +#define AFE_CONN25_4 0x3204 +#define AFE_CONN26 0x3208 +#define AFE_CONN26_1 0x320c +#define AFE_CONN26_2 0x3210 +#define AFE_CONN26_3 0x3214 +#define AFE_CONN26_4 0x3218 +#define AFE_CONN27 0x321c +#define AFE_CONN27_1 0x3220 +#define AFE_CONN27_2 0x3224 +#define AFE_CONN27_3 0x3228 +#define AFE_CONN27_4 0x322c +#define AFE_CONN28 0x3230 +#define AFE_CONN28_1 0x3234 +#define AFE_CONN28_2 0x3238 +#define AFE_CONN28_3 0x323c +#define AFE_CONN28_4 0x3240 +#define AFE_CONN29 0x3244 +#define AFE_CONN29_1 0x3248 +#define AFE_CONN29_2 0x324c +#define AFE_CONN29_3 0x3250 +#define AFE_CONN29_4 0x3254 +#define AFE_CONN30 0x3258 +#define AFE_CONN30_1 0x325c +#define AFE_CONN30_2 0x3260 +#define AFE_CONN30_3 0x3264 +#define AFE_CONN30_4 0x3268 +#define AFE_CONN31 0x326c +#define AFE_CONN31_1 0x3270 +#define AFE_CONN31_2 0x3274 +#define AFE_CONN31_3 0x3278 +#define AFE_CONN31_4 0x327c +#define AFE_CONN32 0x3280 +#define AFE_CONN32_1 0x3284 +#define AFE_CONN32_2 0x3288 +#define AFE_CONN32_3 0x328c +#define AFE_CONN32_4 0x3290 +#define AFE_CONN33 0x3294 +#define AFE_CONN33_1 0x3298 +#define AFE_CONN33_2 0x329c +#define AFE_CONN33_3 0x32a0 +#define AFE_CONN33_4 0x32a4 +#define AFE_CONN34 0x32a8 +#define AFE_CONN34_1 0x32ac +#define AFE_CONN34_2 0x32b0 +#define AFE_CONN34_3 0x32b4 +#define AFE_CONN34_4 0x32b8 +#define AFE_CONN35 0x32bc +#define AFE_CONN35_1 0x32c0 +#define AFE_CONN35_2 0x32c4 +#define AFE_CONN35_3 0x32c8 +#define AFE_CONN35_4 0x32cc +#define AFE_CONN36 0x32d0 +#define AFE_CONN36_1 0x32d4 +#define AFE_CONN36_2 0x32d8 +#define AFE_CONN36_3 0x32dc +#define AFE_CONN36_4 0x32e0 +#define AFE_CONN37 0x32e4 +#define AFE_CONN37_1 0x32e8 +#define AFE_CONN37_2 0x32ec +#define AFE_CONN37_3 0x32f0 +#define AFE_CONN37_4 0x32f4 +#define AFE_CONN38 0x32f8 +#define AFE_CONN38_1 0x32fc +#define AFE_CONN38_2 0x3300 +#define AFE_CONN38_3 0x3304 +#define AFE_CONN38_4 0x3308 +#define AFE_CONN39 0x330c +#define AFE_CONN39_1 0x3310 +#define AFE_CONN39_2 0x3314 +#define AFE_CONN39_3 0x3318 +#define AFE_CONN39_4 0x331c +#define AFE_CONN40 0x3320 +#define AFE_CONN40_1 0x3324 +#define AFE_CONN40_2 0x3328 +#define AFE_CONN40_3 0x332c +#define AFE_CONN40_4 0x3330 +#define AFE_CONN41 0x3334 +#define AFE_CONN41_1 0x3338 +#define AFE_CONN41_2 0x333c +#define AFE_CONN41_3 0x3340 +#define AFE_CONN41_4 0x3344 +#define AFE_CONN42 0x3348 +#define AFE_CONN42_1 0x334c +#define AFE_CONN42_2 0x3350 +#define AFE_CONN42_3 0x3354 +#define AFE_CONN42_4 0x3358 +#define AFE_CONN43 0x335c +#define AFE_CONN43_1 0x3360 +#define AFE_CONN43_2 0x3364 +#define AFE_CONN43_3 0x3368 +#define AFE_CONN43_4 0x336c +#define AFE_CONN44 0x3370 +#define AFE_CONN44_1 0x3374 +#define AFE_CONN44_2 0x3378 +#define AFE_CONN44_3 0x337c +#define AFE_CONN44_4 0x3380 +#define AFE_CONN45 0x3384 +#define AFE_CONN45_1 0x3388 +#define AFE_CONN45_2 0x338c +#define AFE_CONN45_3 0x3390 +#define AFE_CONN45_4 0x3394 +#define AFE_CONN46 0x3398 +#define AFE_CONN46_1 0x339c +#define AFE_CONN46_2 0x33a0 +#define AFE_CONN46_3 0x33a4 +#define AFE_CONN46_4 0x33a8 +#define AFE_CONN47 0x33ac +#define AFE_CONN47_1 0x33b0 +#define AFE_CONN47_2 0x33b4 +#define AFE_CONN47_3 0x33b8 +#define AFE_CONN47_4 0x33bc +#define AFE_CONN48 0x33c0 +#define AFE_CONN48_1 0x33c4 +#define AFE_CONN48_2 0x33c8 +#define AFE_CONN48_3 0x33cc +#define AFE_CONN48_4 0x33d0 +#define AFE_CONN49 0x33d4 +#define AFE_CONN49_1 0x33d8 +#define AFE_CONN49_2 0x33dc +#define AFE_CONN49_3 0x33e0 +#define AFE_CONN49_4 0x33e4 +#define AFE_CONN50 0x33e8 +#define AFE_CONN50_1 0x33ec +#define AFE_CONN50_2 0x33f0 +#define AFE_CONN50_3 0x33f4 +#define AFE_CONN50_4 0x33f8 +#define AFE_CONN51 0x33fc +#define AFE_CONN51_1 0x3400 +#define AFE_CONN51_2 0x3404 +#define AFE_CONN51_3 0x3408 +#define AFE_CONN51_4 0x340c +#define AFE_CONN52 0x3410 +#define AFE_CONN52_1 0x3414 +#define AFE_CONN52_2 0x3418 +#define AFE_CONN52_3 0x341c +#define AFE_CONN52_4 0x3420 +#define AFE_CONN53 0x3424 +#define AFE_CONN53_1 0x3428 +#define AFE_CONN53_2 0x342c +#define AFE_CONN53_3 0x3430 +#define AFE_CONN53_4 0x3434 +#define AFE_CONN54 0x3438 +#define AFE_CONN54_1 0x343c +#define AFE_CONN54_2 0x3440 +#define AFE_CONN54_3 0x3444 +#define AFE_CONN54_4 0x3448 +#define AFE_CONN55 0x344c +#define AFE_CONN55_1 0x3450 +#define AFE_CONN55_2 0x3454 +#define AFE_CONN55_3 0x3458 +#define AFE_CONN55_4 0x345c +#define AFE_CONN56 0x3460 +#define AFE_CONN56_1 0x3464 +#define AFE_CONN56_2 0x3468 +#define AFE_CONN56_3 0x346c +#define AFE_CONN56_4 0x3470 +#define AFE_CONN57 0x3474 +#define AFE_CONN57_1 0x3478 +#define AFE_CONN57_2 0x347c +#define AFE_CONN57_3 0x3480 +#define AFE_CONN57_4 0x3484 +#define AFE_CONN58 0x3488 +#define AFE_CONN58_1 0x348c +#define AFE_CONN58_2 0x3490 +#define AFE_CONN58_3 0x3494 +#define AFE_CONN58_4 0x3498 +#define AFE_CONN59 0x349c +#define AFE_CONN59_1 0x34a0 +#define AFE_CONN59_2 0x34a4 +#define AFE_CONN59_3 0x34a8 +#define AFE_CONN59_4 0x34ac +#define AFE_CONN60 0x34b0 +#define AFE_CONN60_1 0x34b4 +#define AFE_CONN60_2 0x34b8 +#define AFE_CONN60_3 0x34bc +#define AFE_CONN60_4 0x34c0 +#define AFE_CONN61 0x34c4 +#define AFE_CONN61_1 0x34c8 +#define AFE_CONN61_2 0x34cc +#define AFE_CONN61_3 0x34d0 +#define AFE_CONN61_4 0x34d4 +#define AFE_CONN62 0x34d8 +#define AFE_CONN62_1 0x34dc +#define AFE_CONN62_2 0x34e0 +#define AFE_CONN62_3 0x34e4 +#define AFE_CONN62_4 0x34e8 +#define AFE_CONN63 0x34ec +#define AFE_CONN63_1 0x34f0 +#define AFE_CONN63_2 0x34f4 +#define AFE_CONN63_3 0x34f8 +#define AFE_CONN63_4 0x34fc +#define AFE_CONN64 0x3500 +#define AFE_CONN64_1 0x3504 +#define AFE_CONN64_2 0x3508 +#define AFE_CONN64_3 0x350c +#define AFE_CONN64_4 0x3510 +#define AFE_CONN65 0x3514 +#define AFE_CONN65_1 0x3518 +#define AFE_CONN65_2 0x351c +#define AFE_CONN65_3 0x3520 +#define AFE_CONN65_4 0x3524 +#define AFE_CONN66 0x3528 +#define AFE_CONN66_1 0x352c +#define AFE_CONN66_2 0x3530 +#define AFE_CONN66_3 0x3534 +#define AFE_CONN66_4 0x3538 +#define AFE_CONN67 0x353c +#define AFE_CONN67_1 0x3540 +#define AFE_CONN67_2 0x3544 +#define AFE_CONN67_3 0x3548 +#define AFE_CONN67_4 0x354c +#define AFE_CONN68 0x3550 +#define AFE_CONN68_1 0x3554 +#define AFE_CONN68_2 0x3558 +#define AFE_CONN68_3 0x355c +#define AFE_CONN68_4 0x3560 +#define AFE_CONN69 0x3564 +#define AFE_CONN69_1 0x3568 +#define AFE_CONN69_2 0x356c +#define AFE_CONN69_3 0x3570 +#define AFE_CONN69_4 0x3574 +#define AFE_CONN70 0x3578 +#define AFE_CONN70_1 0x357c +#define AFE_CONN70_2 0x3580 +#define AFE_CONN70_3 0x3584 +#define AFE_CONN70_4 0x3588 +#define AFE_CONN71 0x358c +#define AFE_CONN71_1 0x3590 +#define AFE_CONN71_2 0x3594 +#define AFE_CONN71_3 0x3598 +#define AFE_CONN71_4 0x359c +#define AFE_CONN72 0x35a0 +#define AFE_CONN72_1 0x35a4 +#define AFE_CONN72_2 0x35a8 +#define AFE_CONN72_3 0x35ac +#define AFE_CONN72_4 0x35b0 +#define AFE_CONN73 0x35b4 +#define AFE_CONN73_1 0x35b8 +#define AFE_CONN73_2 0x35bc +#define AFE_CONN73_3 0x35c0 +#define AFE_CONN73_4 0x35c4 +#define AFE_CONN74 0x35c8 +#define AFE_CONN74_1 0x35cc +#define AFE_CONN74_2 0x35d0 +#define AFE_CONN74_3 0x35d4 +#define AFE_CONN74_4 0x35d8 +#define AFE_CONN75 0x35dc +#define AFE_CONN75_1 0x35e0 +#define AFE_CONN75_2 0x35e4 +#define AFE_CONN75_3 0x35e8 +#define AFE_CONN75_4 0x35ec +#define AFE_CONN76 0x35f0 +#define AFE_CONN76_1 0x35f4 +#define AFE_CONN76_2 0x35f8 +#define AFE_CONN76_3 0x35fc +#define AFE_CONN76_4 0x3600 +#define AFE_CONN77 0x3604 +#define AFE_CONN77_1 0x3608 +#define AFE_CONN77_2 0x360c +#define AFE_CONN77_3 0x3610 +#define AFE_CONN77_4 0x3614 +#define AFE_CONN78 0x3618 +#define AFE_CONN78_1 0x361c +#define AFE_CONN78_2 0x3620 +#define AFE_CONN78_3 0x3624 +#define AFE_CONN78_4 0x3628 +#define AFE_CONN79 0x362c +#define AFE_CONN79_1 0x3630 +#define AFE_CONN79_2 0x3634 +#define AFE_CONN79_3 0x3638 +#define AFE_CONN79_4 0x363c +#define AFE_CONN80 0x3640 +#define AFE_CONN80_1 0x3644 +#define AFE_CONN80_2 0x3648 +#define AFE_CONN80_3 0x364c +#define AFE_CONN80_4 0x3650 +#define AFE_CONN81 0x3654 +#define AFE_CONN81_1 0x3658 +#define AFE_CONN81_2 0x365c +#define AFE_CONN81_3 0x3660 +#define AFE_CONN81_4 0x3664 +#define AFE_CONN82 0x3668 +#define AFE_CONN82_1 0x366c +#define AFE_CONN82_2 0x3670 +#define AFE_CONN82_3 0x3674 +#define AFE_CONN82_4 0x3678 +#define AFE_CONN83 0x367c +#define AFE_CONN83_1 0x3680 +#define AFE_CONN83_2 0x3684 +#define AFE_CONN83_3 0x3688 +#define AFE_CONN83_4 0x368c +#define AFE_CONN84 0x3690 +#define AFE_CONN84_1 0x3694 +#define AFE_CONN84_2 0x3698 +#define AFE_CONN84_3 0x369c +#define AFE_CONN84_4 0x36a0 +#define AFE_CONN85 0x36a4 +#define AFE_CONN85_1 0x36a8 +#define AFE_CONN85_2 0x36ac +#define AFE_CONN85_3 0x36b0 +#define AFE_CONN85_4 0x36b4 +#define AFE_CONN86 0x36b8 +#define AFE_CONN86_1 0x36bc +#define AFE_CONN86_2 0x36c0 +#define AFE_CONN86_3 0x36c4 +#define AFE_CONN86_4 0x36c8 +#define AFE_CONN87 0x36cc +#define AFE_CONN87_1 0x36d0 +#define AFE_CONN87_2 0x36d4 +#define AFE_CONN87_3 0x36d8 +#define AFE_CONN87_4 0x36dc +#define AFE_CONN88 0x36e0 +#define AFE_CONN88_1 0x36e4 +#define AFE_CONN88_2 0x36e8 +#define AFE_CONN88_3 0x36ec +#define AFE_CONN88_4 0x36f0 +#define AFE_CONN89 0x36f4 +#define AFE_CONN89_1 0x36f8 +#define AFE_CONN89_2 0x36fc +#define AFE_CONN89_3 0x3700 +#define AFE_CONN89_4 0x3704 +#define AFE_CONN90 0x3708 +#define AFE_CONN90_1 0x370c +#define AFE_CONN90_2 0x3710 +#define AFE_CONN90_3 0x3714 +#define AFE_CONN90_4 0x3718 +#define AFE_CONN91 0x371c +#define AFE_CONN91_1 0x3720 +#define AFE_CONN91_2 0x3724 +#define AFE_CONN91_3 0x3728 +#define AFE_CONN91_4 0x372c +#define AFE_CONN92 0x3730 +#define AFE_CONN92_1 0x3734 +#define AFE_CONN92_2 0x3738 +#define AFE_CONN92_3 0x373c +#define AFE_CONN92_4 0x3740 +#define AFE_CONN93 0x3744 +#define AFE_CONN93_1 0x3748 +#define AFE_CONN93_2 0x374c +#define AFE_CONN93_3 0x3750 +#define AFE_CONN93_4 0x3754 +#define AFE_CONN94 0x3758 +#define AFE_CONN94_1 0x375c +#define AFE_CONN94_2 0x3760 +#define AFE_CONN94_3 0x3764 +#define AFE_CONN94_4 0x3768 +#define AFE_CONN95 0x376c +#define AFE_CONN95_1 0x3770 +#define AFE_CONN95_2 0x3774 +#define AFE_CONN95_3 0x3778 +#define AFE_CONN95_4 0x377c +#define AFE_CONN96 0x3780 +#define AFE_CONN96_1 0x3784 +#define AFE_CONN96_2 0x3788 +#define AFE_CONN96_3 0x378c +#define AFE_CONN96_4 0x3790 +#define AFE_CONN97 0x3794 +#define AFE_CONN97_1 0x3798 +#define AFE_CONN97_2 0x379c +#define AFE_CONN97_3 0x37a0 +#define AFE_CONN97_4 0x37a4 +#define AFE_CONN98 0x37a8 +#define AFE_CONN98_1 0x37ac +#define AFE_CONN98_2 0x37b0 +#define AFE_CONN98_3 0x37b4 +#define AFE_CONN98_4 0x37b8 +#define AFE_CONN99 0x37bc +#define AFE_CONN99_1 0x37c0 +#define AFE_CONN99_2 0x37c4 +#define AFE_CONN99_3 0x37c8 +#define AFE_CONN99_4 0x37cc +#define AFE_CONN100 0x37d0 +#define AFE_CONN100_1 0x37d4 +#define AFE_CONN100_2 0x37d8 +#define AFE_CONN100_3 0x37dc +#define AFE_CONN100_4 0x37e0 +#define AFE_CONN101 0x37e4 +#define AFE_CONN101_1 0x37e8 +#define AFE_CONN101_2 0x37ec +#define AFE_CONN101_3 0x37f0 +#define AFE_CONN101_4 0x37f4 +#define AFE_CONN102 0x37f8 +#define AFE_CONN102_1 0x37fc +#define AFE_CONN102_2 0x3800 +#define AFE_CONN102_3 0x3804 +#define AFE_CONN102_4 0x3808 +#define AFE_CONN103 0x380c +#define AFE_CONN103_1 0x3810 +#define AFE_CONN103_2 0x3814 +#define AFE_CONN103_3 0x3818 +#define AFE_CONN103_4 0x381c +#define AFE_CONN104 0x3820 +#define AFE_CONN104_1 0x3824 +#define AFE_CONN104_2 0x3828 +#define AFE_CONN104_3 0x382c +#define AFE_CONN104_4 0x3830 +#define AFE_CONN105 0x3834 +#define AFE_CONN105_1 0x3838 +#define AFE_CONN105_2 0x383c +#define AFE_CONN105_3 0x3840 +#define AFE_CONN105_4 0x3844 +#define AFE_CONN106 0x3848 +#define AFE_CONN106_1 0x384c +#define AFE_CONN106_2 0x3850 +#define AFE_CONN106_3 0x3854 +#define AFE_CONN106_4 0x3858 +#define AFE_CONN107 0x385c +#define AFE_CONN107_1 0x3860 +#define AFE_CONN107_2 0x3864 +#define AFE_CONN107_3 0x3868 +#define AFE_CONN107_4 0x386c +#define AFE_CONN108 0x3870 +#define AFE_CONN108_1 0x3874 +#define AFE_CONN108_2 0x3878 +#define AFE_CONN108_3 0x387c +#define AFE_CONN108_4 0x3880 +#define AFE_CONN109 0x3884 +#define AFE_CONN109_1 0x3888 +#define AFE_CONN109_2 0x388c +#define AFE_CONN109_3 0x3890 +#define AFE_CONN109_4 0x3894 +#define AFE_CONN110 0x3898 +#define AFE_CONN110_1 0x389c +#define AFE_CONN110_2 0x38a0 +#define AFE_CONN110_3 0x38a4 +#define AFE_CONN110_4 0x38a8 +#define AFE_CONN111 0x38ac +#define AFE_CONN111_1 0x38b0 +#define AFE_CONN111_2 0x38b4 +#define AFE_CONN111_3 0x38b8 +#define AFE_CONN111_4 0x38bc +#define AFE_CONN112 0x38c0 +#define AFE_CONN112_1 0x38c4 +#define AFE_CONN112_2 0x38c8 +#define AFE_CONN112_3 0x38cc +#define AFE_CONN112_4 0x38d0 +#define AFE_CONN113 0x38d4 +#define AFE_CONN113_1 0x38d8 +#define AFE_CONN113_2 0x38dc +#define AFE_CONN113_3 0x38e0 +#define AFE_CONN113_4 0x38e4 +#define AFE_CONN114 0x38e8 +#define AFE_CONN114_1 0x38ec +#define AFE_CONN114_2 0x38f0 +#define AFE_CONN114_3 0x38f4 +#define AFE_CONN114_4 0x38f8 +#define AFE_CONN115 0x38fc +#define AFE_CONN115_1 0x3900 +#define AFE_CONN115_2 0x3904 +#define AFE_CONN115_3 0x3908 +#define AFE_CONN115_4 0x390c +#define AFE_CONN116 0x3910 +#define AFE_CONN116_1 0x3914 +#define AFE_CONN116_2 0x3918 +#define AFE_CONN116_3 0x391c +#define AFE_CONN116_4 0x3920 +#define AFE_CONN117 0x3924 +#define AFE_CONN117_1 0x3928 +#define AFE_CONN117_2 0x392c +#define AFE_CONN117_3 0x3930 +#define AFE_CONN117_4 0x3934 +#define AFE_CONN118 0x3938 +#define AFE_CONN118_1 0x393c +#define AFE_CONN118_2 0x3940 +#define AFE_CONN118_3 0x3944 +#define AFE_CONN118_4 0x3948 +#define AFE_CONN119 0x394c +#define AFE_CONN119_1 0x3950 +#define AFE_CONN119_2 0x3954 +#define AFE_CONN119_3 0x3958 +#define AFE_CONN119_4 0x395c +#define AFE_CONN120 0x3960 +#define AFE_CONN120_1 0x3964 +#define AFE_CONN120_2 0x3968 +#define AFE_CONN120_3 0x396c +#define AFE_CONN120_4 0x3970 +#define AFE_CONN121 0x3974 +#define AFE_CONN121_1 0x3978 +#define AFE_CONN121_2 0x397c +#define AFE_CONN121_3 0x3980 +#define AFE_CONN121_4 0x3984 +#define AFE_CONN122 0x3988 +#define AFE_CONN122_1 0x398c +#define AFE_CONN122_2 0x3990 +#define AFE_CONN122_3 0x3994 +#define AFE_CONN122_4 0x3998 +#define AFE_CONN123 0x399c +#define AFE_CONN123_1 0x39a0 +#define AFE_CONN123_2 0x39a4 +#define AFE_CONN123_3 0x39a8 +#define AFE_CONN123_4 0x39ac +#define AFE_CONN124 0x39b0 +#define AFE_CONN124_1 0x39b4 +#define AFE_CONN124_2 0x39b8 +#define AFE_CONN124_3 0x39bc +#define AFE_CONN124_4 0x39c0 +#define AFE_CONN125 0x39c4 +#define AFE_CONN125_1 0x39c8 +#define AFE_CONN125_2 0x39cc +#define AFE_CONN125_3 0x39d0 +#define AFE_CONN125_4 0x39d4 +#define AFE_CONN126 0x39d8 +#define AFE_CONN126_1 0x39dc +#define AFE_CONN126_2 0x39e0 +#define AFE_CONN126_3 0x39e4 +#define AFE_CONN126_4 0x39e8 +#define AFE_CONN127 0x39ec +#define AFE_CONN127_1 0x39f0 +#define AFE_CONN127_2 0x39f4 +#define AFE_CONN127_3 0x39f8 +#define AFE_CONN127_4 0x39fc +#define AFE_CONN128 0x3a00 +#define AFE_CONN128_1 0x3a04 +#define AFE_CONN128_2 0x3a08 +#define AFE_CONN128_3 0x3a0c +#define AFE_CONN128_4 0x3a10 +#define AFE_CONN129 0x3a14 +#define AFE_CONN129_1 0x3a18 +#define AFE_CONN129_2 0x3a1c +#define AFE_CONN129_3 0x3a20 +#define AFE_CONN129_4 0x3a24 +#define AFE_CONN130 0x3a28 +#define AFE_CONN130_1 0x3a2c +#define AFE_CONN130_2 0x3a30 +#define AFE_CONN130_3 0x3a34 +#define AFE_CONN130_4 0x3a38 +#define AFE_CONN131 0x3a3c +#define AFE_CONN131_1 0x3a40 +#define AFE_CONN131_2 0x3a44 +#define AFE_CONN131_3 0x3a48 +#define AFE_CONN131_4 0x3a4c +#define AFE_CONN132 0x3a50 +#define AFE_CONN132_1 0x3a54 +#define AFE_CONN132_2 0x3a58 +#define AFE_CONN132_3 0x3a5c +#define AFE_CONN132_4 0x3a60 +#define AFE_CONN133 0x3a64 +#define AFE_CONN133_1 0x3a68 +#define AFE_CONN133_2 0x3a6c +#define AFE_CONN133_3 0x3a70 +#define AFE_CONN133_4 0x3a74 +#define AFE_CONN134 0x3a78 +#define AFE_CONN134_1 0x3a7c +#define AFE_CONN134_2 0x3a80 +#define AFE_CONN134_3 0x3a84 +#define AFE_CONN134_4 0x3a88 +#define AFE_CONN135 0x3a8c +#define AFE_CONN135_1 0x3a90 +#define AFE_CONN135_2 0x3a94 +#define AFE_CONN135_3 0x3a98 +#define AFE_CONN135_4 0x3a9c +#define AFE_CONN136 0x3aa0 +#define AFE_CONN136_1 0x3aa4 +#define AFE_CONN136_2 0x3aa8 +#define AFE_CONN136_3 0x3aac +#define AFE_CONN136_4 0x3ab0 +#define AFE_CONN137 0x3ab4 +#define AFE_CONN137_1 0x3ab8 +#define AFE_CONN137_2 0x3abc +#define AFE_CONN137_3 0x3ac0 +#define AFE_CONN137_4 0x3ac4 +#define AFE_CONN138 0x3ac8 +#define AFE_CONN138_1 0x3acc +#define AFE_CONN138_2 0x3ad0 +#define AFE_CONN138_3 0x3ad4 +#define AFE_CONN138_4 0x3ad8 +#define AFE_CONN139 0x3adc +#define AFE_CONN139_1 0x3ae0 +#define AFE_CONN139_2 0x3ae4 +#define AFE_CONN139_3 0x3ae8 +#define AFE_CONN139_4 0x3aec +#define AFE_CONN_RS 0x3af0 +#define AFE_CONN_RS_1 0x3af4 +#define AFE_CONN_RS_2 0x3af8 +#define AFE_CONN_RS_3 0x3afc +#define AFE_CONN_RS_4 0x3b00 +#define AFE_CONN_16BIT 0x3b04 +#define AFE_CONN_16BIT_1 0x3b08 +#define AFE_CONN_16BIT_2 0x3b0c +#define AFE_CONN_16BIT_3 0x3b10 +#define AFE_CONN_16BIT_4 0x3b14 +#define AFE_CONN_24BIT 0x3b18 +#define AFE_CONN_24BIT_1 0x3b1c +#define AFE_CONN_24BIT_2 0x3b20 +#define AFE_CONN_24BIT_3 0x3b24 +#define AFE_CONN_24BIT_4 0x3b28 +#define AFE_CONN_DI 0x3b2c +#define AFE_CONN_DI_1 0x3b30 +#define AFE_CONN_DI_2 0x3b34 +#define AFE_CONN_DI_3 0x3b38 +#define AFE_CONN_DI_4 0x3b3c +#define AFE_CONN176 0x3ea0 +#define AFE_CONN176_1 0x3ea4 +#define AFE_CONN176_2 0x3ea8 +#define AFE_CONN176_3 0x3eac +#define AFE_CONN176_4 0x3eb0 +#define AFE_CONN176_5 0x3eb4 +#define AFE_CONN177 0x3eb8 +#define AFE_CONN177_1 0x3ebc +#define AFE_CONN177_2 0x3ec0 +#define AFE_CONN177_3 0x3ec4 +#define AFE_CONN177_4 0x3ec8 +#define AFE_CONN177_5 0x3ecc +#define AFE_CONN182 0x3f30 +#define AFE_CONN182_1 0x3f34 +#define AFE_CONN182_2 0x3f38 +#define AFE_CONN182_3 0x3f3c +#define AFE_CONN182_4 0x3f40 +#define AFE_CONN182_5 0x3f44 +#define AFE_CONN183 0x3f48 +#define AFE_CONN183_1 0x3f4c +#define AFE_CONN183_2 0x3f50 +#define AFE_CONN183_3 0x3f54 +#define AFE_CONN183_4 0x3f58 +#define AFE_CONN183_5 0x3f5c +#define AFE_SECURE_MASK_CONN0 0x4000 +#define AFE_SECURE_MASK_CONN0_1 0x4004 +#define AFE_SECURE_MASK_CONN0_2 0x4008 +#define AFE_SECURE_MASK_CONN0_3 0x400c +#define AFE_SECURE_MASK_CONN0_4 0x4010 +#define AFE_SECURE_MASK_CONN1 0x4014 +#define AFE_SECURE_MASK_CONN1_1 0x4018 +#define AFE_SECURE_MASK_CONN1_2 0x401c +#define AFE_SECURE_MASK_CONN1_3 0x4020 +#define AFE_SECURE_MASK_CONN1_4 0x4024 +#define AFE_SECURE_MASK_CONN2 0x4028 +#define AFE_SECURE_MASK_CONN2_1 0x402c +#define AFE_SECURE_MASK_CONN2_2 0x4030 +#define AFE_SECURE_MASK_CONN2_3 0x4034 +#define AFE_SECURE_MASK_CONN2_4 0x4038 +#define AFE_SECURE_MASK_CONN3 0x403c +#define AFE_SECURE_MASK_CONN3_1 0x4040 +#define AFE_SECURE_MASK_CONN3_2 0x4044 +#define AFE_SECURE_MASK_CONN3_3 0x4048 +#define AFE_SECURE_MASK_CONN3_4 0x404c +#define AFE_SECURE_MASK_CONN4 0x4050 +#define AFE_SECURE_MASK_CONN4_1 0x4054 +#define AFE_SECURE_MASK_CONN4_2 0x4058 +#define AFE_SECURE_MASK_CONN4_3 0x405c +#define AFE_SECURE_MASK_CONN4_4 0x4060 +#define AFE_SECURE_MASK_CONN5 0x4064 +#define AFE_SECURE_MASK_CONN5_1 0x4068 +#define AFE_SECURE_MASK_CONN5_2 0x406c +#define AFE_SECURE_MASK_CONN5_3 0x4070 +#define AFE_SECURE_MASK_CONN5_4 0x4074 +#define AFE_SECURE_MASK_CONN6 0x4078 +#define AFE_SECURE_MASK_CONN6_1 0x407c +#define AFE_SECURE_MASK_CONN6_2 0x4080 +#define AFE_SECURE_MASK_CONN6_3 0x4084 +#define AFE_SECURE_MASK_CONN6_4 0x4088 +#define AFE_SECURE_MASK_CONN7 0x408c +#define AFE_SECURE_MASK_CONN7_1 0x4090 +#define AFE_SECURE_MASK_CONN7_2 0x4094 +#define AFE_SECURE_MASK_CONN7_3 0x4098 +#define AFE_SECURE_MASK_CONN7_4 0x409c +#define AFE_SECURE_MASK_CONN8 0x40a0 +#define AFE_SECURE_MASK_CONN8_1 0x40a4 +#define AFE_SECURE_MASK_CONN8_2 0x40a8 +#define AFE_SECURE_MASK_CONN8_3 0x40ac +#define AFE_SECURE_MASK_CONN8_4 0x40b0 +#define AFE_SECURE_MASK_CONN9 0x40b4 +#define AFE_SECURE_MASK_CONN9_1 0x40b8 +#define AFE_SECURE_MASK_CONN9_2 0x40bc +#define AFE_SECURE_MASK_CONN9_3 0x40c0 +#define AFE_SECURE_MASK_CONN9_4 0x40c4 +#define AFE_SECURE_MASK_CONN10 0x40c8 +#define AFE_SECURE_MASK_CONN10_1 0x40cc +#define AFE_SECURE_MASK_CONN10_2 0x40d0 +#define AFE_SECURE_MASK_CONN10_3 0x40d4 +#define AFE_SECURE_MASK_CONN10_4 0x40d8 +#define AFE_SECURE_MASK_CONN11 0x40dc +#define AFE_SECURE_MASK_CONN11_1 0x40e0 +#define AFE_SECURE_MASK_CONN11_2 0x40e4 +#define AFE_SECURE_MASK_CONN11_3 0x40e8 +#define AFE_SECURE_MASK_CONN11_4 0x40ec +#define AFE_SECURE_MASK_CONN12 0x40f0 +#define AFE_SECURE_MASK_CONN12_1 0x40f4 +#define AFE_SECURE_MASK_CONN12_2 0x40f8 +#define AFE_SECURE_MASK_CONN12_3 0x40fc +#define AFE_SECURE_MASK_CONN12_4 0x4100 +#define AFE_SECURE_MASK_CONN13 0x4104 +#define AFE_SECURE_MASK_CONN13_1 0x4108 +#define AFE_SECURE_MASK_CONN13_2 0x410c +#define AFE_SECURE_MASK_CONN13_3 0x4110 +#define AFE_SECURE_MASK_CONN13_4 0x4114 +#define AFE_SECURE_MASK_CONN14 0x4118 +#define AFE_SECURE_MASK_CONN14_1 0x411c +#define AFE_SECURE_MASK_CONN14_2 0x4120 +#define AFE_SECURE_MASK_CONN14_3 0x4124 +#define AFE_SECURE_MASK_CONN14_4 0x4128 +#define AFE_SECURE_MASK_CONN15 0x412c +#define AFE_SECURE_MASK_CONN15_1 0x4130 +#define AFE_SECURE_MASK_CONN15_2 0x4134 +#define AFE_SECURE_MASK_CONN15_3 0x4138 +#define AFE_SECURE_MASK_CONN15_4 0x413c +#define AFE_SECURE_MASK_CONN16 0x4140 +#define AFE_SECURE_MASK_CONN16_1 0x4144 +#define AFE_SECURE_MASK_CONN16_2 0x4148 +#define AFE_SECURE_MASK_CONN16_3 0x414c +#define AFE_SECURE_MASK_CONN16_4 0x4150 +#define AFE_SECURE_MASK_CONN17 0x4154 +#define AFE_SECURE_MASK_CONN17_1 0x4158 +#define AFE_SECURE_MASK_CONN17_2 0x415c +#define AFE_SECURE_MASK_CONN17_3 0x4160 +#define AFE_SECURE_MASK_CONN17_4 0x4164 +#define AFE_SECURE_MASK_CONN18 0x4168 +#define AFE_SECURE_MASK_CONN18_1 0x416c +#define AFE_SECURE_MASK_CONN18_2 0x4170 +#define AFE_SECURE_MASK_CONN18_3 0x4174 +#define AFE_SECURE_MASK_CONN18_4 0x4178 +#define AFE_SECURE_MASK_CONN19 0x417c +#define AFE_SECURE_MASK_CONN19_1 0x4180 +#define AFE_SECURE_MASK_CONN19_2 0x4184 +#define AFE_SECURE_MASK_CONN19_3 0x4188 +#define AFE_SECURE_MASK_CONN19_4 0x418c +#define AFE_SECURE_MASK_CONN20 0x4190 +#define AFE_SECURE_MASK_CONN20_1 0x4194 +#define AFE_SECURE_MASK_CONN20_2 0x4198 +#define AFE_SECURE_MASK_CONN20_3 0x419c +#define AFE_SECURE_MASK_CONN20_4 0x41a0 +#define AFE_SECURE_MASK_CONN21 0x41a4 +#define AFE_SECURE_MASK_CONN21_1 0x41a8 +#define AFE_SECURE_MASK_CONN21_2 0x41ac +#define AFE_SECURE_MASK_CONN21_3 0x41b0 +#define AFE_SECURE_MASK_CONN21_4 0x41b4 +#define AFE_SECURE_MASK_CONN22 0x41b8 +#define AFE_SECURE_MASK_CONN22_1 0x41bc +#define AFE_SECURE_MASK_CONN22_2 0x41c0 +#define AFE_SECURE_MASK_CONN22_3 0x41c4 +#define AFE_SECURE_MASK_CONN22_4 0x41c8 +#define AFE_SECURE_MASK_CONN23 0x41cc +#define AFE_SECURE_MASK_CONN23_1 0x41d0 +#define AFE_SECURE_MASK_CONN23_2 0x41d4 +#define AFE_SECURE_MASK_CONN23_3 0x41d8 +#define AFE_SECURE_MASK_CONN23_4 0x41dc +#define AFE_SECURE_MASK_CONN24 0x41e0 +#define AFE_SECURE_MASK_CONN24_1 0x41e4 +#define AFE_SECURE_MASK_CONN24_2 0x41e8 +#define AFE_SECURE_MASK_CONN24_3 0x41ec +#define AFE_SECURE_MASK_CONN24_4 0x41f0 +#define AFE_SECURE_MASK_CONN25 0x41f4 +#define AFE_SECURE_MASK_CONN25_1 0x41f8 +#define AFE_SECURE_MASK_CONN25_2 0x41fc +#define AFE_SECURE_MASK_CONN25_3 0x4200 +#define AFE_SECURE_MASK_CONN25_4 0x4204 +#define AFE_SECURE_MASK_CONN26 0x4208 +#define AFE_SECURE_MASK_CONN26_1 0x420c +#define AFE_SECURE_MASK_CONN26_2 0x4210 +#define AFE_SECURE_MASK_CONN26_3 0x4214 +#define AFE_SECURE_MASK_CONN26_4 0x4218 +#define AFE_SECURE_MASK_CONN27 0x421c +#define AFE_SECURE_MASK_CONN27_1 0x4220 +#define AFE_SECURE_MASK_CONN27_2 0x4224 +#define AFE_SECURE_MASK_CONN27_3 0x4228 +#define AFE_SECURE_MASK_CONN27_4 0x422c +#define AFE_SECURE_MASK_CONN28 0x4230 +#define AFE_SECURE_MASK_CONN28_1 0x4234 +#define AFE_SECURE_MASK_CONN28_2 0x4238 +#define AFE_SECURE_MASK_CONN28_3 0x423c +#define AFE_SECURE_MASK_CONN28_4 0x4240 +#define AFE_SECURE_MASK_CONN29 0x4244 +#define AFE_SECURE_MASK_CONN29_1 0x4248 +#define AFE_SECURE_MASK_CONN29_2 0x424c +#define AFE_SECURE_MASK_CONN29_3 0x4250 +#define AFE_SECURE_MASK_CONN29_4 0x4254 +#define AFE_SECURE_MASK_CONN30 0x4258 +#define AFE_SECURE_MASK_CONN30_1 0x425c +#define AFE_SECURE_MASK_CONN30_2 0x4260 +#define AFE_SECURE_MASK_CONN30_3 0x4264 +#define AFE_SECURE_MASK_CONN30_4 0x4268 +#define AFE_SECURE_MASK_CONN31 0x426c +#define AFE_SECURE_MASK_CONN31_1 0x4270 +#define AFE_SECURE_MASK_CONN31_2 0x4274 +#define AFE_SECURE_MASK_CONN31_3 0x4278 +#define AFE_SECURE_MASK_CONN31_4 0x427c +#define AFE_SECURE_MASK_CONN32 0x4280 +#define AFE_SECURE_MASK_CONN32_1 0x4284 +#define AFE_SECURE_MASK_CONN32_2 0x4288 +#define AFE_SECURE_MASK_CONN32_3 0x428c +#define AFE_SECURE_MASK_CONN32_4 0x4290 +#define AFE_SECURE_MASK_CONN33 0x4294 +#define AFE_SECURE_MASK_CONN33_1 0x4298 +#define AFE_SECURE_MASK_CONN33_2 0x429c +#define AFE_SECURE_MASK_CONN33_3 0x42a0 +#define AFE_SECURE_MASK_CONN33_4 0x42a4 +#define AFE_SECURE_MASK_CONN34 0x42a8 +#define AFE_SECURE_MASK_CONN34_1 0x42ac +#define AFE_SECURE_MASK_CONN34_2 0x42b0 +#define AFE_SECURE_MASK_CONN34_3 0x42b4 +#define AFE_SECURE_MASK_CONN34_4 0x42b8 +#define AFE_SECURE_MASK_CONN35 0x42bc +#define AFE_SECURE_MASK_CONN35_1 0x42c0 +#define AFE_SECURE_MASK_CONN35_2 0x42c4 +#define AFE_SECURE_MASK_CONN35_3 0x42c8 +#define AFE_SECURE_MASK_CONN35_4 0x42cc +#define AFE_SECURE_MASK_CONN36 0x42d0 +#define AFE_SECURE_MASK_CONN36_1 0x42d4 +#define AFE_SECURE_MASK_CONN36_2 0x42d8 +#define AFE_SECURE_MASK_CONN36_3 0x42dc +#define AFE_SECURE_MASK_CONN36_4 0x42e0 +#define AFE_SECURE_MASK_CONN37 0x42e4 +#define AFE_SECURE_MASK_CONN37_1 0x42e8 +#define AFE_SECURE_MASK_CONN37_2 0x42ec +#define AFE_SECURE_MASK_CONN37_3 0x42f0 +#define AFE_SECURE_MASK_CONN37_4 0x42f4 +#define AFE_SECURE_MASK_CONN38 0x42f8 +#define AFE_SECURE_MASK_CONN38_1 0x42fc +#define AFE_SECURE_MASK_CONN38_2 0x4300 +#define AFE_SECURE_MASK_CONN38_3 0x4304 +#define AFE_SECURE_MASK_CONN38_4 0x4308 +#define AFE_SECURE_MASK_CONN39 0x430c +#define AFE_SECURE_MASK_CONN39_1 0x4310 +#define AFE_SECURE_MASK_CONN39_2 0x4314 +#define AFE_SECURE_MASK_CONN39_3 0x4318 +#define AFE_SECURE_MASK_CONN39_4 0x431c +#define AFE_SECURE_MASK_CONN40 0x4320 +#define AFE_SECURE_MASK_CONN40_1 0x4324 +#define AFE_SECURE_MASK_CONN40_2 0x4328 +#define AFE_SECURE_MASK_CONN40_3 0x432c +#define AFE_SECURE_MASK_CONN40_4 0x4330 +#define AFE_SECURE_MASK_CONN41 0x4334 +#define AFE_SECURE_MASK_CONN41_1 0x4338 +#define AFE_SECURE_MASK_CONN41_2 0x433c +#define AFE_SECURE_MASK_CONN41_3 0x4340 +#define AFE_SECURE_MASK_CONN41_4 0x4344 +#define AFE_SECURE_MASK_CONN42 0x4348 +#define AFE_SECURE_MASK_CONN42_1 0x434c +#define AFE_SECURE_MASK_CONN42_2 0x4350 +#define AFE_SECURE_MASK_CONN42_3 0x4354 +#define AFE_SECURE_MASK_CONN42_4 0x4358 +#define AFE_SECURE_MASK_CONN43 0x435c +#define AFE_SECURE_MASK_CONN43_1 0x4360 +#define AFE_SECURE_MASK_CONN43_2 0x4364 +#define AFE_SECURE_MASK_CONN43_3 0x4368 +#define AFE_SECURE_MASK_CONN43_4 0x436c +#define AFE_SECURE_MASK_CONN44 0x4370 +#define AFE_SECURE_MASK_CONN44_1 0x4374 +#define AFE_SECURE_MASK_CONN44_2 0x4378 +#define AFE_SECURE_MASK_CONN44_3 0x437c +#define AFE_SECURE_MASK_CONN44_4 0x4380 +#define AFE_SECURE_MASK_CONN45 0x4384 +#define AFE_SECURE_MASK_CONN45_1 0x4388 +#define AFE_SECURE_MASK_CONN45_2 0x438c +#define AFE_SECURE_MASK_CONN45_3 0x4390 +#define AFE_SECURE_MASK_CONN45_4 0x4394 +#define AFE_SECURE_MASK_CONN46 0x4398 +#define AFE_SECURE_MASK_CONN46_1 0x439c +#define AFE_SECURE_MASK_CONN46_2 0x43a0 +#define AFE_SECURE_MASK_CONN46_3 0x43a4 +#define AFE_SECURE_MASK_CONN46_4 0x43a8 +#define AFE_SECURE_MASK_CONN47 0x43ac +#define AFE_SECURE_MASK_CONN47_1 0x43b0 +#define AFE_SECURE_MASK_CONN47_2 0x43b4 +#define AFE_SECURE_MASK_CONN47_3 0x43b8 +#define AFE_SECURE_MASK_CONN47_4 0x43bc +#define AFE_SECURE_MASK_CONN48 0x43c0 +#define AFE_SECURE_MASK_CONN48_1 0x43c4 +#define AFE_SECURE_MASK_CONN48_2 0x43c8 +#define AFE_SECURE_MASK_CONN48_3 0x43cc +#define AFE_SECURE_MASK_CONN48_4 0x43d0 +#define AFE_SECURE_MASK_CONN49 0x43d4 +#define AFE_SECURE_MASK_CONN49_1 0x43d8 +#define AFE_SECURE_MASK_CONN49_2 0x43dc +#define AFE_SECURE_MASK_CONN49_3 0x43e0 +#define AFE_SECURE_MASK_CONN49_4 0x43e4 +#define AFE_SECURE_MASK_CONN50 0x43e8 +#define AFE_SECURE_MASK_CONN50_1 0x43ec +#define AFE_SECURE_MASK_CONN50_2 0x43f0 +#define AFE_SECURE_MASK_CONN50_3 0x43f4 +#define AFE_SECURE_MASK_CONN50_4 0x43f8 +#define AFE_SECURE_MASK_CONN51 0x43fc +#define AFE_SECURE_MASK_CONN51_1 0x4400 +#define AFE_SECURE_MASK_CONN51_2 0x4404 +#define AFE_SECURE_MASK_CONN51_3 0x4408 +#define AFE_SECURE_MASK_CONN51_4 0x440c +#define AFE_SECURE_MASK_CONN52 0x4410 +#define AFE_SECURE_MASK_CONN52_1 0x4414 +#define AFE_SECURE_MASK_CONN52_2 0x4418 +#define AFE_SECURE_MASK_CONN52_3 0x441c +#define AFE_SECURE_MASK_CONN52_4 0x4420 +#define AFE_SECURE_MASK_CONN53 0x4424 +#define AFE_SECURE_MASK_CONN53_1 0x4428 +#define AFE_SECURE_MASK_CONN53_2 0x442c +#define AFE_SECURE_MASK_CONN53_3 0x4430 +#define AFE_SECURE_MASK_CONN53_4 0x4434 +#define AFE_SECURE_MASK_CONN54 0x4438 +#define AFE_SECURE_MASK_CONN54_1 0x443c +#define AFE_SECURE_MASK_CONN54_2 0x4440 +#define AFE_SECURE_MASK_CONN54_3 0x4444 +#define AFE_SECURE_MASK_CONN54_4 0x4448 +#define AFE_SECURE_MASK_CONN55 0x444c +#define AFE_SECURE_MASK_CONN55_1 0x4450 +#define AFE_SECURE_MASK_CONN55_2 0x4454 +#define AFE_SECURE_MASK_CONN55_3 0x4458 +#define AFE_SECURE_MASK_CONN55_4 0x445c +#define AFE_SECURE_MASK_CONN56 0x4460 +#define AFE_SECURE_MASK_CONN56_1 0x4464 +#define AFE_SECURE_MASK_CONN56_2 0x4468 +#define AFE_SECURE_MASK_CONN56_3 0x446c +#define AFE_SECURE_MASK_CONN56_4 0x4470 +#define AFE_SECURE_MASK_CONN57 0x4474 +#define AFE_SECURE_MASK_CONN57_1 0x4478 +#define AFE_SECURE_MASK_CONN57_2 0x447c +#define AFE_SECURE_MASK_CONN57_3 0x4480 +#define AFE_SECURE_MASK_CONN57_4 0x4484 +#define AFE_SECURE_MASK_CONN58 0x4488 +#define AFE_SECURE_MASK_CONN58_1 0x448c +#define AFE_SECURE_MASK_CONN58_2 0x4490 +#define AFE_SECURE_MASK_CONN58_3 0x4494 +#define AFE_SECURE_MASK_CONN58_4 0x4498 +#define AFE_SECURE_MASK_CONN59 0x449c +#define AFE_SECURE_MASK_CONN59_1 0x44a0 +#define AFE_SECURE_MASK_CONN59_2 0x44a4 +#define AFE_SECURE_MASK_CONN59_3 0x44a8 +#define AFE_SECURE_MASK_CONN59_4 0x44ac +#define AFE_SECURE_MASK_CONN60 0x44b0 +#define AFE_SECURE_MASK_CONN60_1 0x44b4 +#define AFE_SECURE_MASK_CONN60_2 0x44b8 +#define AFE_SECURE_MASK_CONN60_3 0x44bc +#define AFE_SECURE_MASK_CONN60_4 0x44c0 +#define AFE_SECURE_MASK_CONN61 0x44c4 +#define AFE_SECURE_MASK_CONN61_1 0x44c8 +#define AFE_SECURE_MASK_CONN61_2 0x44cc +#define AFE_SECURE_MASK_CONN61_3 0x44d0 +#define AFE_SECURE_MASK_CONN61_4 0x44d4 +#define AFE_SECURE_MASK_CONN62 0x44d8 +#define AFE_SECURE_MASK_CONN62_1 0x44dc +#define AFE_SECURE_MASK_CONN62_2 0x44e0 +#define AFE_SECURE_MASK_CONN62_3 0x44e4 +#define AFE_SECURE_MASK_CONN62_4 0x44e8 +#define AFE_SECURE_MASK_CONN63 0x44ec +#define AFE_SECURE_MASK_CONN63_1 0x44f0 +#define AFE_SECURE_MASK_CONN63_2 0x44f4 +#define AFE_SECURE_MASK_CONN63_3 0x44f8 +#define AFE_SECURE_MASK_CONN63_4 0x44fc +#define AFE_SECURE_MASK_CONN64 0x4500 +#define AFE_SECURE_MASK_CONN64_1 0x4504 +#define AFE_SECURE_MASK_CONN64_2 0x4508 +#define AFE_SECURE_MASK_CONN64_3 0x450c +#define AFE_SECURE_MASK_CONN64_4 0x4510 +#define AFE_SECURE_MASK_CONN65 0x4514 +#define AFE_SECURE_MASK_CONN65_1 0x4518 +#define AFE_SECURE_MASK_CONN65_2 0x451c +#define AFE_SECURE_MASK_CONN65_3 0x4520 +#define AFE_SECURE_MASK_CONN65_4 0x4524 +#define AFE_SECURE_MASK_CONN66 0x4528 +#define AFE_SECURE_MASK_CONN66_1 0x452c +#define AFE_SECURE_MASK_CONN66_2 0x4530 +#define AFE_SECURE_MASK_CONN66_3 0x4534 +#define AFE_SECURE_MASK_CONN66_4 0x4538 +#define AFE_SECURE_MASK_CONN67 0x453c +#define AFE_SECURE_MASK_CONN67_1 0x4540 +#define AFE_SECURE_MASK_CONN67_2 0x4544 +#define AFE_SECURE_MASK_CONN67_3 0x4548 +#define AFE_SECURE_MASK_CONN67_4 0x454c +#define AFE_SECURE_MASK_CONN68 0x4550 +#define AFE_SECURE_MASK_CONN68_1 0x4554 +#define AFE_SECURE_MASK_CONN68_2 0x4558 +#define AFE_SECURE_MASK_CONN68_3 0x455c +#define AFE_SECURE_MASK_CONN68_4 0x4560 +#define AFE_SECURE_MASK_CONN69 0x4564 +#define AFE_SECURE_MASK_CONN69_1 0x4568 +#define AFE_SECURE_MASK_CONN69_2 0x456c +#define AFE_SECURE_MASK_CONN69_3 0x4570 +#define AFE_SECURE_MASK_CONN69_4 0x4574 +#define AFE_SECURE_MASK_CONN70 0x4578 +#define AFE_SECURE_MASK_CONN70_1 0x457c +#define AFE_SECURE_MASK_CONN70_2 0x4580 +#define AFE_SECURE_MASK_CONN70_3 0x4584 +#define AFE_SECURE_MASK_CONN70_4 0x4588 +#define AFE_SECURE_MASK_CONN71 0x458c +#define AFE_SECURE_MASK_CONN71_1 0x4590 +#define AFE_SECURE_MASK_CONN71_2 0x4594 +#define AFE_SECURE_MASK_CONN71_3 0x4598 +#define AFE_SECURE_MASK_CONN71_4 0x459c +#define AFE_SECURE_MASK_CONN72 0x45a0 +#define AFE_SECURE_MASK_CONN72_1 0x45a4 +#define AFE_SECURE_MASK_CONN72_2 0x45a8 +#define AFE_SECURE_MASK_CONN72_3 0x45ac +#define AFE_SECURE_MASK_CONN72_4 0x45b0 +#define AFE_SECURE_MASK_CONN73 0x45b4 +#define AFE_SECURE_MASK_CONN73_1 0x45b8 +#define AFE_SECURE_MASK_CONN73_2 0x45bc +#define AFE_SECURE_MASK_CONN73_3 0x45c0 +#define AFE_SECURE_MASK_CONN73_4 0x45c4 +#define AFE_SECURE_MASK_CONN74 0x45c8 +#define AFE_SECURE_MASK_CONN74_1 0x45cc +#define AFE_SECURE_MASK_CONN74_2 0x45d0 +#define AFE_SECURE_MASK_CONN74_3 0x45d4 +#define AFE_SECURE_MASK_CONN74_4 0x45d8 +#define AFE_SECURE_MASK_CONN75 0x45dc +#define AFE_SECURE_MASK_CONN75_1 0x45e0 +#define AFE_SECURE_MASK_CONN75_2 0x45e4 +#define AFE_SECURE_MASK_CONN75_3 0x45e8 +#define AFE_SECURE_MASK_CONN75_4 0x45ec +#define AFE_SECURE_MASK_CONN76 0x45f0 +#define AFE_SECURE_MASK_CONN76_1 0x45f4 +#define AFE_SECURE_MASK_CONN76_2 0x45f8 +#define AFE_SECURE_MASK_CONN76_3 0x45fc +#define AFE_SECURE_MASK_CONN76_4 0x4600 +#define AFE_SECURE_MASK_CONN77 0x4604 +#define AFE_SECURE_MASK_CONN77_1 0x4608 +#define AFE_SECURE_MASK_CONN77_2 0x460c +#define AFE_SECURE_MASK_CONN77_3 0x4610 +#define AFE_SECURE_MASK_CONN77_4 0x4614 +#define AFE_SECURE_MASK_CONN78 0x4618 +#define AFE_SECURE_MASK_CONN78_1 0x461c +#define AFE_SECURE_MASK_CONN78_2 0x4620 +#define AFE_SECURE_MASK_CONN78_3 0x4624 +#define AFE_SECURE_MASK_CONN78_4 0x4628 +#define AFE_SECURE_MASK_CONN79 0x462c +#define AFE_SECURE_MASK_CONN79_1 0x4630 +#define AFE_SECURE_MASK_CONN79_2 0x4634 +#define AFE_SECURE_MASK_CONN79_3 0x4638 +#define AFE_SECURE_MASK_CONN79_4 0x463c +#define AFE_SECURE_MASK_CONN80 0x4640 +#define AFE_SECURE_MASK_CONN80_1 0x4644 +#define AFE_SECURE_MASK_CONN80_2 0x4648 +#define AFE_SECURE_MASK_CONN80_3 0x464c +#define AFE_SECURE_MASK_CONN80_4 0x4650 +#define AFE_SECURE_MASK_CONN81 0x4654 +#define AFE_SECURE_MASK_CONN81_1 0x4658 +#define AFE_SECURE_MASK_CONN81_2 0x465c +#define AFE_SECURE_MASK_CONN81_3 0x4660 +#define AFE_SECURE_MASK_CONN81_4 0x4664 +#define AFE_SECURE_MASK_CONN82 0x4668 +#define AFE_SECURE_MASK_CONN82_1 0x466c +#define AFE_SECURE_MASK_CONN82_2 0x4670 +#define AFE_SECURE_MASK_CONN82_3 0x4674 +#define AFE_SECURE_MASK_CONN82_4 0x4678 +#define AFE_SECURE_MASK_CONN83 0x467c +#define AFE_SECURE_MASK_CONN83_1 0x4680 +#define AFE_SECURE_MASK_CONN83_2 0x4684 +#define AFE_SECURE_MASK_CONN83_3 0x4688 +#define AFE_SECURE_MASK_CONN83_4 0x468c +#define AFE_SECURE_MASK_CONN84 0x4690 +#define AFE_SECURE_MASK_CONN84_1 0x4694 +#define AFE_SECURE_MASK_CONN84_2 0x4698 +#define AFE_SECURE_MASK_CONN84_3 0x469c +#define AFE_SECURE_MASK_CONN84_4 0x46a0 +#define AFE_SECURE_MASK_CONN85 0x46a4 +#define AFE_SECURE_MASK_CONN85_1 0x46a8 +#define AFE_SECURE_MASK_CONN85_2 0x46ac +#define AFE_SECURE_MASK_CONN85_3 0x46b0 +#define AFE_SECURE_MASK_CONN85_4 0x46b4 +#define AFE_SECURE_MASK_CONN86 0x46b8 +#define AFE_SECURE_MASK_CONN86_1 0x46bc +#define AFE_SECURE_MASK_CONN86_2 0x46c0 +#define AFE_SECURE_MASK_CONN86_3 0x46c4 +#define AFE_SECURE_MASK_CONN86_4 0x46c8 +#define AFE_SECURE_MASK_CONN87 0x46cc +#define AFE_SECURE_MASK_CONN87_1 0x46d0 +#define AFE_SECURE_MASK_CONN87_2 0x46d4 +#define AFE_SECURE_MASK_CONN87_3 0x46d8 +#define AFE_SECURE_MASK_CONN87_4 0x46dc +#define AFE_SECURE_MASK_CONN88 0x46e0 +#define AFE_SECURE_MASK_CONN88_1 0x46e4 +#define AFE_SECURE_MASK_CONN88_2 0x46e8 +#define AFE_SECURE_MASK_CONN88_3 0x46ec +#define AFE_SECURE_MASK_CONN88_4 0x46f0 +#define AFE_SECURE_MASK_CONN89 0x46f4 +#define AFE_SECURE_MASK_CONN89_1 0x46f8 +#define AFE_SECURE_MASK_CONN89_2 0x46fc +#define AFE_SECURE_MASK_CONN89_3 0x4700 +#define AFE_SECURE_MASK_CONN89_4 0x4704 +#define AFE_SECURE_MASK_CONN90 0x4708 +#define AFE_SECURE_MASK_CONN90_1 0x470c +#define AFE_SECURE_MASK_CONN90_2 0x4710 +#define AFE_SECURE_MASK_CONN90_3 0x4714 +#define AFE_SECURE_MASK_CONN90_4 0x4718 +#define AFE_SECURE_MASK_CONN91 0x471c +#define AFE_SECURE_MASK_CONN91_1 0x4720 +#define AFE_SECURE_MASK_CONN91_2 0x4724 +#define AFE_SECURE_MASK_CONN91_3 0x4728 +#define AFE_SECURE_MASK_CONN91_4 0x472c +#define AFE_SECURE_MASK_CONN92 0x4730 +#define AFE_SECURE_MASK_CONN92_1 0x4734 +#define AFE_SECURE_MASK_CONN92_2 0x4738 +#define AFE_SECURE_MASK_CONN92_3 0x473c +#define AFE_SECURE_MASK_CONN92_4 0x4740 +#define AFE_SECURE_MASK_CONN93 0x4744 +#define AFE_SECURE_MASK_CONN93_1 0x4748 +#define AFE_SECURE_MASK_CONN93_2 0x474c +#define AFE_SECURE_MASK_CONN93_3 0x4750 +#define AFE_SECURE_MASK_CONN93_4 0x4754 +#define AFE_SECURE_MASK_CONN94 0x4758 +#define AFE_SECURE_MASK_CONN94_1 0x475c +#define AFE_SECURE_MASK_CONN94_2 0x4760 +#define AFE_SECURE_MASK_CONN94_3 0x4764 +#define AFE_SECURE_MASK_CONN94_4 0x4768 +#define AFE_SECURE_MASK_CONN95 0x476c +#define AFE_SECURE_MASK_CONN95_1 0x4770 +#define AFE_SECURE_MASK_CONN95_2 0x4774 +#define AFE_SECURE_MASK_CONN95_3 0x4778 +#define AFE_SECURE_MASK_CONN95_4 0x477c +#define AFE_SECURE_MASK_CONN96 0x4780 +#define AFE_SECURE_MASK_CONN96_1 0x4784 +#define AFE_SECURE_MASK_CONN96_2 0x4788 +#define AFE_SECURE_MASK_CONN96_3 0x478c +#define AFE_SECURE_MASK_CONN96_4 0x4790 +#define AFE_SECURE_MASK_CONN97 0x4794 +#define AFE_SECURE_MASK_CONN97_1 0x4798 +#define AFE_SECURE_MASK_CONN97_2 0x479c +#define AFE_SECURE_MASK_CONN97_3 0x47a0 +#define AFE_SECURE_MASK_CONN97_4 0x47a4 +#define AFE_SECURE_MASK_CONN98 0x47a8 +#define AFE_SECURE_MASK_CONN98_1 0x47ac +#define AFE_SECURE_MASK_CONN98_2 0x47b0 +#define AFE_SECURE_MASK_CONN98_3 0x47b4 +#define AFE_SECURE_MASK_CONN98_4 0x47b8 +#define AFE_SECURE_MASK_CONN99 0x47bc +#define AFE_SECURE_MASK_CONN99_1 0x47c0 +#define AFE_SECURE_MASK_CONN99_2 0x47c4 +#define AFE_SECURE_MASK_CONN99_3 0x47c8 +#define AFE_SECURE_MASK_CONN99_4 0x47cc +#define AFE_SECURE_MASK_CONN100 0x47d0 +#define AFE_SECURE_MASK_CONN100_1 0x47d4 +#define AFE_SECURE_MASK_CONN100_2 0x47d8 +#define AFE_SECURE_MASK_CONN100_3 0x47dc +#define AFE_SECURE_MASK_CONN100_4 0x47e0 +#define AFE_SECURE_MASK_CONN101 0x47e4 +#define AFE_SECURE_MASK_CONN101_1 0x47e8 +#define AFE_SECURE_MASK_CONN101_2 0x47ec +#define AFE_SECURE_MASK_CONN101_3 0x47f0 +#define AFE_SECURE_MASK_CONN101_4 0x47f4 +#define AFE_SECURE_MASK_CONN102 0x47f8 +#define AFE_SECURE_MASK_CONN102_1 0x47fc +#define AFE_SECURE_MASK_CONN102_2 0x4800 +#define AFE_SECURE_MASK_CONN102_3 0x4804 +#define AFE_SECURE_MASK_CONN102_4 0x4808 +#define AFE_SECURE_MASK_CONN103 0x480c +#define AFE_SECURE_MASK_CONN103_1 0x4810 +#define AFE_SECURE_MASK_CONN103_2 0x4814 +#define AFE_SECURE_MASK_CONN103_3 0x4818 +#define AFE_SECURE_MASK_CONN103_4 0x481c +#define AFE_SECURE_MASK_CONN104 0x4820 +#define AFE_SECURE_MASK_CONN104_1 0x4824 +#define AFE_SECURE_MASK_CONN104_2 0x4828 +#define AFE_SECURE_MASK_CONN104_3 0x482c +#define AFE_SECURE_MASK_CONN104_4 0x4830 +#define AFE_SECURE_MASK_CONN105 0x4834 +#define AFE_SECURE_MASK_CONN105_1 0x4838 +#define AFE_SECURE_MASK_CONN105_2 0x483c +#define AFE_SECURE_MASK_CONN105_3 0x4840 +#define AFE_SECURE_MASK_CONN105_4 0x4844 +#define AFE_SECURE_MASK_CONN106 0x4848 +#define AFE_SECURE_MASK_CONN106_1 0x484c +#define AFE_SECURE_MASK_CONN106_2 0x4850 +#define AFE_SECURE_MASK_CONN106_3 0x4854 +#define AFE_SECURE_MASK_CONN106_4 0x4858 +#define AFE_SECURE_MASK_CONN107 0x485c +#define AFE_SECURE_MASK_CONN107_1 0x4860 +#define AFE_SECURE_MASK_CONN107_2 0x4864 +#define AFE_SECURE_MASK_CONN107_3 0x4868 +#define AFE_SECURE_MASK_CONN107_4 0x486c +#define AFE_SECURE_MASK_CONN108 0x4870 +#define AFE_SECURE_MASK_CONN108_1 0x4874 +#define AFE_SECURE_MASK_CONN108_2 0x4878 +#define AFE_SECURE_MASK_CONN108_3 0x487c +#define AFE_SECURE_MASK_CONN108_4 0x4880 +#define AFE_SECURE_MASK_CONN109 0x4884 +#define AFE_SECURE_MASK_CONN109_1 0x4888 +#define AFE_SECURE_MASK_CONN109_2 0x488c +#define AFE_SECURE_MASK_CONN109_3 0x4890 +#define AFE_SECURE_MASK_CONN109_4 0x4894 +#define AFE_SECURE_MASK_CONN110 0x4898 +#define AFE_SECURE_MASK_CONN110_1 0x489c +#define AFE_SECURE_MASK_CONN110_2 0x48a0 +#define AFE_SECURE_MASK_CONN110_3 0x48a4 +#define AFE_SECURE_MASK_CONN110_4 0x48a8 +#define AFE_SECURE_MASK_CONN111 0x48ac +#define AFE_SECURE_MASK_CONN111_1 0x48b0 +#define AFE_SECURE_MASK_CONN111_2 0x48b4 +#define AFE_SECURE_MASK_CONN111_3 0x48b8 +#define AFE_SECURE_MASK_CONN111_4 0x48bc +#define AFE_SECURE_MASK_CONN112 0x48c0 +#define AFE_SECURE_MASK_CONN112_1 0x48c4 +#define AFE_SECURE_MASK_CONN112_2 0x48c8 +#define AFE_SECURE_MASK_CONN112_3 0x48cc +#define AFE_SECURE_MASK_CONN112_4 0x48d0 +#define AFE_SECURE_MASK_CONN113 0x48d4 +#define AFE_SECURE_MASK_CONN113_1 0x48d8 +#define AFE_SECURE_MASK_CONN113_2 0x48dc +#define AFE_SECURE_MASK_CONN113_3 0x48e0 +#define AFE_SECURE_MASK_CONN113_4 0x48e4 +#define AFE_SECURE_MASK_CONN114 0x48e8 +#define AFE_SECURE_MASK_CONN114_1 0x48ec +#define AFE_SECURE_MASK_CONN114_2 0x48f0 +#define AFE_SECURE_MASK_CONN114_3 0x48f4 +#define AFE_SECURE_MASK_CONN114_4 0x48f8 +#define AFE_SECURE_MASK_CONN115 0x48fc +#define AFE_SECURE_MASK_CONN115_1 0x4900 +#define AFE_SECURE_MASK_CONN115_2 0x4904 +#define AFE_SECURE_MASK_CONN115_3 0x4908 +#define AFE_SECURE_MASK_CONN115_4 0x490c +#define AFE_SECURE_MASK_CONN116 0x4910 +#define AFE_SECURE_MASK_CONN116_1 0x4914 +#define AFE_SECURE_MASK_CONN116_2 0x4918 +#define AFE_SECURE_MASK_CONN116_3 0x491c +#define AFE_SECURE_MASK_CONN116_4 0x4920 +#define AFE_SECURE_MASK_CONN117 0x4924 +#define AFE_SECURE_MASK_CONN117_1 0x4928 +#define AFE_SECURE_MASK_CONN117_2 0x492c +#define AFE_SECURE_MASK_CONN117_3 0x4930 +#define AFE_SECURE_MASK_CONN117_4 0x4934 +#define AFE_SECURE_MASK_CONN118 0x4938 +#define AFE_SECURE_MASK_CONN118_1 0x493c +#define AFE_SECURE_MASK_CONN118_2 0x4940 +#define AFE_SECURE_MASK_CONN118_3 0x4944 +#define AFE_SECURE_MASK_CONN118_4 0x4948 +#define AFE_SECURE_MASK_CONN119 0x494c +#define AFE_SECURE_MASK_CONN119_1 0x4950 +#define AFE_SECURE_MASK_CONN119_2 0x4954 +#define AFE_SECURE_MASK_CONN119_3 0x4958 +#define AFE_SECURE_MASK_CONN119_4 0x495c +#define AFE_SECURE_MASK_CONN120 0x4960 +#define AFE_SECURE_MASK_CONN120_1 0x4964 +#define AFE_SECURE_MASK_CONN120_2 0x4968 +#define AFE_SECURE_MASK_CONN120_3 0x496c +#define AFE_SECURE_MASK_CONN120_4 0x4970 +#define AFE_SECURE_MASK_CONN121 0x4974 +#define AFE_SECURE_MASK_CONN121_1 0x4978 +#define AFE_SECURE_MASK_CONN121_2 0x497c +#define AFE_SECURE_MASK_CONN121_3 0x4980 +#define AFE_SECURE_MASK_CONN121_4 0x4984 +#define AFE_SECURE_MASK_CONN122 0x4988 +#define AFE_SECURE_MASK_CONN122_1 0x498c +#define AFE_SECURE_MASK_CONN122_2 0x4990 +#define AFE_SECURE_MASK_CONN122_3 0x4994 +#define AFE_SECURE_MASK_CONN122_4 0x4998 +#define AFE_SECURE_MASK_CONN123 0x499c +#define AFE_SECURE_MASK_CONN123_1 0x49a0 +#define AFE_SECURE_MASK_CONN123_2 0x49a4 +#define AFE_SECURE_MASK_CONN123_3 0x49a8 +#define AFE_SECURE_MASK_CONN123_4 0x49ac +#define AFE_SECURE_MASK_CONN124 0x49b0 +#define AFE_SECURE_MASK_CONN124_1 0x49b4 +#define AFE_SECURE_MASK_CONN124_2 0x49b8 +#define AFE_SECURE_MASK_CONN124_3 0x49bc +#define AFE_SECURE_MASK_CONN124_4 0x49c0 +#define AFE_SECURE_MASK_CONN125 0x49c4 +#define AFE_SECURE_MASK_CONN125_1 0x49c8 +#define AFE_SECURE_MASK_CONN125_2 0x49cc +#define AFE_SECURE_MASK_CONN125_3 0x49d0 +#define AFE_SECURE_MASK_CONN125_4 0x49d4 +#define AFE_SECURE_MASK_CONN126 0x49d8 +#define AFE_SECURE_MASK_CONN126_1 0x49dc +#define AFE_SECURE_MASK_CONN126_2 0x49e0 +#define AFE_SECURE_MASK_CONN126_3 0x49e4 +#define AFE_SECURE_MASK_CONN126_4 0x49e8 +#define AFE_SECURE_MASK_CONN127 0x49ec +#define AFE_SECURE_MASK_CONN127_1 0x49f0 +#define AFE_SECURE_MASK_CONN127_2 0x49f4 +#define AFE_SECURE_MASK_CONN127_3 0x49f8 +#define AFE_SECURE_MASK_CONN127_4 0x49fc +#define AFE_SECURE_MASK_CONN128 0x4a00 +#define AFE_SECURE_MASK_CONN128_1 0x4a04 +#define AFE_SECURE_MASK_CONN128_2 0x4a08 +#define AFE_SECURE_MASK_CONN128_3 0x4a0c +#define AFE_SECURE_MASK_CONN128_4 0x4a10 +#define AFE_SECURE_MASK_CONN129 0x4a14 +#define AFE_SECURE_MASK_CONN129_1 0x4a18 +#define AFE_SECURE_MASK_CONN129_2 0x4a1c +#define AFE_SECURE_MASK_CONN129_3 0x4a20 +#define AFE_SECURE_MASK_CONN129_4 0x4a24 +#define AFE_SECURE_MASK_CONN130 0x4a28 +#define AFE_SECURE_MASK_CONN130_1 0x4a2c +#define AFE_SECURE_MASK_CONN130_2 0x4a30 +#define AFE_SECURE_MASK_CONN130_3 0x4a34 +#define AFE_SECURE_MASK_CONN130_4 0x4a38 +#define AFE_SECURE_MASK_CONN131 0x4a3c +#define AFE_SECURE_MASK_CONN131_1 0x4a40 +#define AFE_SECURE_MASK_CONN131_2 0x4a44 +#define AFE_SECURE_MASK_CONN131_3 0x4a48 +#define AFE_SECURE_MASK_CONN131_4 0x4a4c +#define AFE_SECURE_MASK_CONN132 0x4a50 +#define AFE_SECURE_MASK_CONN132_1 0x4a54 +#define AFE_SECURE_MASK_CONN132_2 0x4a58 +#define AFE_SECURE_MASK_CONN132_3 0x4a5c +#define AFE_SECURE_MASK_CONN132_4 0x4a60 +#define AFE_SECURE_MASK_CONN133 0x4a64 +#define AFE_SECURE_MASK_CONN133_1 0x4a68 +#define AFE_SECURE_MASK_CONN133_2 0x4a6c +#define AFE_SECURE_MASK_CONN133_3 0x4a70 +#define AFE_SECURE_MASK_CONN133_4 0x4a74 +#define AFE_SECURE_MASK_CONN134 0x4a78 +#define AFE_SECURE_MASK_CONN134_1 0x4a7c +#define AFE_SECURE_MASK_CONN134_2 0x4a80 +#define AFE_SECURE_MASK_CONN134_3 0x4a84 +#define AFE_SECURE_MASK_CONN134_4 0x4a88 +#define AFE_SECURE_MASK_CONN135 0x4a8c +#define AFE_SECURE_MASK_CONN135_1 0x4a90 +#define AFE_SECURE_MASK_CONN135_2 0x4a94 +#define AFE_SECURE_MASK_CONN135_3 0x4a98 +#define AFE_SECURE_MASK_CONN135_4 0x4a9c +#define AFE_SECURE_MASK_CONN136 0x4aa0 +#define AFE_SECURE_MASK_CONN136_1 0x4aa4 +#define AFE_SECURE_MASK_CONN136_2 0x4aa8 +#define AFE_SECURE_MASK_CONN136_3 0x4aac +#define AFE_SECURE_MASK_CONN136_4 0x4ab0 +#define AFE_SECURE_MASK_CONN137 0x4ab4 +#define AFE_SECURE_MASK_CONN137_1 0x4ab8 +#define AFE_SECURE_MASK_CONN137_2 0x4abc +#define AFE_SECURE_MASK_CONN137_3 0x4ac0 +#define AFE_SECURE_MASK_CONN137_4 0x4ac4 +#define AFE_SECURE_MASK_CONN138 0x4ac8 +#define AFE_SECURE_MASK_CONN138_1 0x4acc +#define AFE_SECURE_MASK_CONN138_2 0x4ad0 +#define AFE_SECURE_MASK_CONN138_3 0x4ad4 +#define AFE_SECURE_MASK_CONN138_4 0x4ad8 +#define AFE_SECURE_MASK_CONN139 0x4adc +#define AFE_SECURE_MASK_CONN139_1 0x4ae0 +#define AFE_SECURE_MASK_CONN139_2 0x4ae4 +#define AFE_SECURE_MASK_CONN139_3 0x4ae8 +#define AFE_SECURE_MASK_CONN139_4 0x4aec +#define AFE_SECURE_MASK_CONN_RS 0x4af0 +#define AFE_SECURE_MASK_CONN_RS_1 0x4af4 +#define AFE_SECURE_MASK_CONN_RS_2 0x4af8 +#define AFE_SECURE_MASK_CONN_RS_3 0x4afc +#define AFE_SECURE_MASK_CONN_RS_4 0x4b00 +#define AFE_SECURE_MASK_CONN_16BIT 0x4b04 +#define AFE_SECURE_MASK_CONN_16BIT_1 0x4b08 +#define AFE_SECURE_MASK_CONN_16BIT_2 0x4b0c +#define AFE_SECURE_MASK_CONN_16BIT_3 0x4b10 +#define AFE_SECURE_MASK_CONN_16BIT_4 0x4b14 +#define AFE_SECURE_MASK_CONN_24BIT 0x4b18 +#define AFE_SECURE_MASK_CONN_24BIT_1 0x4b1c +#define AFE_SECURE_MASK_CONN_24BIT_2 0x4b20 +#define AFE_SECURE_MASK_CONN_24BIT_3 0x4b24 +#define AFE_SECURE_MASK_CONN_24BIT_4 0x4b28 +#define AFE_SECURE_MASK_CONN0_5 0x4b2c +#define AFE_SECURE_MASK_CONN1_5 0x4b30 +#define AFE_SECURE_MASK_CONN2_5 0x4b34 +#define AFE_SECURE_MASK_CONN3_5 0x4b38 +#define AFE_SECURE_MASK_CONN4_5 0x4b3c +#define AFE_SECURE_MASK_CONN5_5 0x4b40 +#define AFE_SECURE_MASK_CONN6_5 0x4b44 +#define AFE_SECURE_MASK_CONN7_5 0x4b48 +#define AFE_SECURE_MASK_CONN8_5 0x4b4c +#define AFE_SECURE_MASK_CONN9_5 0x4b50 +#define AFE_SECURE_MASK_CONN10_5 0x4b54 +#define AFE_SECURE_MASK_CONN11_5 0x4b58 +#define AFE_SECURE_MASK_CONN12_5 0x4b5c +#define AFE_SECURE_MASK_CONN13_5 0x4b60 +#define AFE_SECURE_MASK_CONN14_5 0x4b64 +#define AFE_SECURE_MASK_CONN15_5 0x4b68 +#define AFE_SECURE_MASK_CONN16_5 0x4b6c +#define AFE_SECURE_MASK_CONN17_5 0x4b70 +#define AFE_SECURE_MASK_CONN18_5 0x4b74 +#define AFE_SECURE_MASK_CONN19_5 0x4b78 +#define AFE_SECURE_MASK_CONN20_5 0x4b7c +#define AFE_SECURE_MASK_CONN21_5 0x4b80 +#define AFE_SECURE_MASK_CONN22_5 0x4b84 +#define AFE_SECURE_MASK_CONN23_5 0x4b88 +#define AFE_SECURE_MASK_CONN24_5 0x4b8c +#define AFE_SECURE_MASK_CONN25_5 0x4b90 +#define AFE_SECURE_MASK_CONN26_5 0x4b94 +#define AFE_SECURE_MASK_CONN27_5 0x4b98 +#define AFE_SECURE_MASK_CONN28_5 0x4b9c +#define AFE_SECURE_MASK_CONN29_5 0x4ba0 +#define AFE_SECURE_MASK_CONN30_5 0x4ba4 +#define AFE_SECURE_MASK_CONN31_5 0x4ba8 +#define AFE_SECURE_MASK_CONN32_5 0x4bac +#define AFE_SECURE_MASK_CONN33_5 0x4bb0 +#define AFE_SECURE_MASK_CONN34_5 0x4bb4 +#define AFE_SECURE_MASK_CONN35_5 0x4bb8 +#define AFE_SECURE_MASK_CONN36_5 0x4bbc +#define AFE_SECURE_MASK_CONN37_5 0x4bc0 +#define AFE_SECURE_MASK_CONN38_5 0x4bc4 +#define AFE_SECURE_MASK_CONN39_5 0x4bc8 +#define AFE_SECURE_MASK_CONN40_5 0x4bcc +#define AFE_SECURE_MASK_CONN41_5 0x4bd0 +#define AFE_SECURE_MASK_CONN42_5 0x4bd4 +#define AFE_SECURE_MASK_CONN43_5 0x4bd8 +#define AFE_SECURE_MASK_CONN44_5 0x4bdc +#define AFE_SECURE_MASK_CONN45_5 0x4be0 +#define AFE_SECURE_MASK_CONN46_5 0x4be4 +#define AFE_SECURE_MASK_CONN47_5 0x4be8 +#define AFE_SECURE_MASK_CONN48_5 0x4bec +#define AFE_SECURE_MASK_CONN49_5 0x4bf0 +#define AFE_SECURE_MASK_CONN50_5 0x4bf4 +#define AFE_SECURE_MASK_CONN51_5 0x4bf8 +#define AFE_SECURE_MASK_CONN52_5 0x4bfc +#define AFE_GASRC0_NEW_CON0 0x4c40 +#define AFE_GASRC0_NEW_CON1 0x4c44 +#define AFE_GASRC0_NEW_CON2 0x4c48 +#define AFE_GASRC0_NEW_CON3 0x4c4c +#define AFE_GASRC0_NEW_CON4 0x4c50 +#define AFE_GASRC0_NEW_CON5 0x4c54 +#define AFE_GASRC0_NEW_CON6 0x4c58 +#define AFE_GASRC0_NEW_CON7 0x4c5c +#define AFE_GASRC0_NEW_CON8 0x4c60 +#define AFE_GASRC0_NEW_CON9 0x4c64 +#define AFE_GASRC0_NEW_CON10 0x4c68 +#define AFE_GASRC0_NEW_CON11 0x4c6c +#define AFE_GASRC0_NEW_CON12 0x4c70 +#define AFE_GASRC0_NEW_CON13 0x4c74 +#define AFE_GASRC0_NEW_CON14 0x4c78 +#define AFE_GASRC1_NEW_CON0 0x4c80 +#define AFE_GASRC1_NEW_CON1 0x4c84 +#define AFE_GASRC1_NEW_CON2 0x4c88 +#define AFE_GASRC1_NEW_CON3 0x4c8c +#define AFE_GASRC1_NEW_CON4 0x4c90 +#define AFE_GASRC1_NEW_CON5 0x4c94 +#define AFE_GASRC1_NEW_CON6 0x4c98 +#define AFE_GASRC1_NEW_CON7 0x4c9c +#define AFE_GASRC1_NEW_CON8 0x4ca0 +#define AFE_GASRC1_NEW_CON9 0x4ca4 +#define AFE_GASRC1_NEW_CON10 0x4ca8 +#define AFE_GASRC1_NEW_CON11 0x4cac +#define AFE_GASRC1_NEW_CON12 0x4cb0 +#define AFE_GASRC1_NEW_CON13 0x4cb4 +#define AFE_GASRC1_NEW_CON14 0x4cb8 +#define AFE_GASRC2_NEW_CON0 0x4cc0 +#define AFE_GASRC2_NEW_CON1 0x4cc4 +#define AFE_GASRC2_NEW_CON2 0x4cc8 +#define AFE_GASRC2_NEW_CON3 0x4ccc +#define AFE_GASRC2_NEW_CON4 0x4cd0 +#define AFE_GASRC2_NEW_CON5 0x4cd4 +#define AFE_GASRC2_NEW_CON6 0x4cd8 +#define AFE_GASRC2_NEW_CON7 0x4cdc +#define AFE_GASRC2_NEW_CON8 0x4ce0 +#define AFE_GASRC2_NEW_CON9 0x4ce4 +#define AFE_GASRC2_NEW_CON10 0x4ce8 +#define AFE_GASRC2_NEW_CON11 0x4cec +#define AFE_GASRC2_NEW_CON12 0x4cf0 +#define AFE_GASRC2_NEW_CON13 0x4cf4 +#define AFE_GASRC2_NEW_CON14 0x4cf8 +#define AFE_GASRC3_NEW_CON0 0x4d00 +#define AFE_GASRC3_NEW_CON1 0x4d04 +#define AFE_GASRC3_NEW_CON2 0x4d08 +#define AFE_GASRC3_NEW_CON3 0x4d0c +#define AFE_GASRC3_NEW_CON4 0x4d10 +#define AFE_GASRC3_NEW_CON5 0x4d14 +#define AFE_GASRC3_NEW_CON6 0x4d18 +#define AFE_GASRC3_NEW_CON7 0x4d1c +#define AFE_GASRC3_NEW_CON8 0x4d20 +#define AFE_GASRC3_NEW_CON9 0x4d24 +#define AFE_GASRC3_NEW_CON10 0x4d28 +#define AFE_GASRC3_NEW_CON11 0x4d2c +#define AFE_GASRC3_NEW_CON12 0x4d30 +#define AFE_GASRC3_NEW_CON13 0x4d34 +#define AFE_GASRC3_NEW_CON14 0x4d38 +#define AFE_GASRC4_NEW_CON0 0x4d40 +#define AFE_GASRC4_NEW_CON1 0x4d44 +#define AFE_GASRC4_NEW_CON2 0x4d48 +#define AFE_GASRC4_NEW_CON3 0x4d4c +#define AFE_GASRC4_NEW_CON4 0x4d50 +#define AFE_GASRC4_NEW_CON5 0x4d54 +#define AFE_GASRC4_NEW_CON6 0x4d58 +#define AFE_GASRC4_NEW_CON7 0x4d5c +#define AFE_GASRC4_NEW_CON8 0x4d60 +#define AFE_GASRC4_NEW_CON9 0x4d64 +#define AFE_GASRC4_NEW_CON10 0x4d68 +#define AFE_GASRC4_NEW_CON11 0x4d6c +#define AFE_GASRC4_NEW_CON12 0x4d70 +#define AFE_GASRC4_NEW_CON13 0x4d74 +#define AFE_GASRC4_NEW_CON14 0x4d78 +#define AFE_GASRC5_NEW_CON0 0x4d80 +#define AFE_GASRC5_NEW_CON1 0x4d84 +#define AFE_GASRC5_NEW_CON2 0x4d88 +#define AFE_GASRC5_NEW_CON3 0x4d8c +#define AFE_GASRC5_NEW_CON4 0x4d90 +#define AFE_GASRC5_NEW_CON5 0x4d94 +#define AFE_GASRC5_NEW_CON6 0x4d98 +#define AFE_GASRC5_NEW_CON7 0x4d9c +#define AFE_GASRC5_NEW_CON8 0x4da0 +#define AFE_GASRC5_NEW_CON9 0x4da4 +#define AFE_GASRC5_NEW_CON10 0x4da8 +#define AFE_GASRC5_NEW_CON11 0x4dac +#define AFE_GASRC5_NEW_CON12 0x4db0 +#define AFE_GASRC5_NEW_CON13 0x4db4 +#define AFE_GASRC5_NEW_CON14 0x4db8 +#define AFE_GASRC6_NEW_CON0 0x4dc0 +#define AFE_GASRC6_NEW_CON1 0x4dc4 +#define AFE_GASRC6_NEW_CON2 0x4dc8 +#define AFE_GASRC6_NEW_CON3 0x4dcc +#define AFE_GASRC6_NEW_CON4 0x4dd0 +#define AFE_GASRC6_NEW_CON5 0x4dd4 +#define AFE_GASRC6_NEW_CON6 0x4dd8 +#define AFE_GASRC6_NEW_CON7 0x4ddc +#define AFE_GASRC6_NEW_CON8 0x4de0 +#define AFE_GASRC6_NEW_CON9 0x4de4 +#define AFE_GASRC6_NEW_CON10 0x4de8 +#define AFE_GASRC6_NEW_CON11 0x4dec +#define AFE_GASRC6_NEW_CON12 0x4df0 +#define AFE_GASRC6_NEW_CON13 0x4df4 +#define AFE_GASRC6_NEW_CON14 0x4df8 +#define AFE_GASRC7_NEW_CON0 0x4e00 +#define AFE_GASRC7_NEW_CON1 0x4e04 +#define AFE_GASRC7_NEW_CON2 0x4e08 +#define AFE_GASRC7_NEW_CON3 0x4e0c +#define AFE_GASRC7_NEW_CON4 0x4e10 +#define AFE_GASRC7_NEW_CON5 0x4e14 +#define AFE_GASRC7_NEW_CON6 0x4e18 +#define AFE_GASRC7_NEW_CON7 0x4e1c +#define AFE_GASRC7_NEW_CON8 0x4e20 +#define AFE_GASRC7_NEW_CON9 0x4e24 +#define AFE_GASRC7_NEW_CON10 0x4e28 +#define AFE_GASRC7_NEW_CON11 0x4e2c +#define AFE_GASRC7_NEW_CON12 0x4e30 +#define AFE_GASRC7_NEW_CON13 0x4e34 +#define AFE_GASRC7_NEW_CON14 0x4e38 +#define AFE_GASRC8_NEW_CON0 0x4e40 +#define AFE_GASRC8_NEW_CON1 0x4e44 +#define AFE_GASRC8_NEW_CON2 0x4e48 +#define AFE_GASRC8_NEW_CON3 0x4e4c +#define AFE_GASRC8_NEW_CON4 0x4e50 +#define AFE_GASRC8_NEW_CON5 0x4e54 +#define AFE_GASRC8_NEW_CON6 0x4e58 +#define AFE_GASRC8_NEW_CON7 0x4e5c +#define AFE_GASRC8_NEW_CON8 0x4e60 +#define AFE_GASRC8_NEW_CON9 0x4e64 +#define AFE_GASRC8_NEW_CON10 0x4e68 +#define AFE_GASRC8_NEW_CON11 0x4e6c +#define AFE_GASRC8_NEW_CON12 0x4e70 +#define AFE_GASRC8_NEW_CON13 0x4e74 +#define AFE_GASRC8_NEW_CON14 0x4e78 +#define AFE_GASRC9_NEW_CON0 0x4e80 +#define AFE_GASRC9_NEW_CON1 0x4e84 +#define AFE_GASRC9_NEW_CON2 0x4e88 +#define AFE_GASRC9_NEW_CON3 0x4e8c +#define AFE_GASRC9_NEW_CON4 0x4e90 +#define AFE_GASRC9_NEW_CON5 0x4e94 +#define AFE_GASRC9_NEW_CON6 0x4e98 +#define AFE_GASRC9_NEW_CON7 0x4e9c +#define AFE_GASRC9_NEW_CON8 0x4ea0 +#define AFE_GASRC9_NEW_CON9 0x4ea4 +#define AFE_GASRC9_NEW_CON10 0x4ea8 +#define AFE_GASRC9_NEW_CON11 0x4eac +#define AFE_GASRC9_NEW_CON12 0x4eb0 +#define AFE_GASRC9_NEW_CON13 0x4eb4 +#define AFE_GASRC9_NEW_CON14 0x4eb8 +#define AFE_GASRC10_NEW_CON0 0x4ec0 +#define AFE_GASRC10_NEW_CON1 0x4ec4 +#define AFE_GASRC10_NEW_CON2 0x4ec8 +#define AFE_GASRC10_NEW_CON3 0x4ecc +#define AFE_GASRC10_NEW_CON4 0x4ed0 +#define AFE_GASRC10_NEW_CON5 0x4ed4 +#define AFE_GASRC10_NEW_CON6 0x4ed8 +#define AFE_GASRC10_NEW_CON7 0x4edc +#define AFE_GASRC10_NEW_CON8 0x4ee0 +#define AFE_GASRC10_NEW_CON9 0x4ee4 +#define AFE_GASRC10_NEW_CON10 0x4ee8 +#define AFE_GASRC10_NEW_CON11 0x4eec +#define AFE_GASRC10_NEW_CON12 0x4ef0 +#define AFE_GASRC10_NEW_CON13 0x4ef4 +#define AFE_GASRC10_NEW_CON14 0x4ef8 +#define AFE_GASRC11_NEW_CON0 0x4f00 +#define AFE_GASRC11_NEW_CON1 0x4f04 +#define AFE_GASRC11_NEW_CON2 0x4f08 +#define AFE_GASRC11_NEW_CON3 0x4f0c +#define AFE_GASRC11_NEW_CON4 0x4f10 +#define AFE_GASRC11_NEW_CON5 0x4f14 +#define AFE_GASRC11_NEW_CON6 0x4f18 +#define AFE_GASRC11_NEW_CON7 0x4f1c +#define AFE_GASRC11_NEW_CON8 0x4f20 +#define AFE_GASRC11_NEW_CON9 0x4f24 +#define AFE_GASRC11_NEW_CON10 0x4f28 +#define AFE_GASRC11_NEW_CON11 0x4f2c +#define AFE_GASRC11_NEW_CON12 0x4f30 +#define AFE_GASRC11_NEW_CON13 0x4f34 +#define AFE_GASRC11_NEW_CON14 0x4f38 + +#define AFE_IEC_BURST_INFO_MON 0x64b0 +#define AFE_SPDIFOUT_IP_VERSION 0x64b4 +#define AFE_SPDIF_OUT_CFG0 0x64b8 +#define AFE_SPDIF_OUT_CFG1 0x64bc +#define AFE_SPDIF_OUT_CHSTS1 0x64c0 +#define AFE_SPDIF_OUT_CHSTS2 0x64c4 +#define AFE_SPDIF_OUT_CHSTS3 0x64c8 +#define AFE_SPDIF_OUT_CHSTS4 0x64cc +#define AFE_SPDIF_OUT_CHSTS5 0x64d0 +#define AFE_SPDIF_OUT_CHSTS6 0x64d4 +#define AFE_SPDIF_OUT_USERCODE1 0x64d8 +#define AFE_SPDIF_OUT_USERCODE2 0x64dc +#define AFE_SPDIF_OUT_USERCODE3 0x64e0 +#define AFE_SPDIF_OUT_USERCODE4 0x64e4 +#define AFE_SPDIF_OUT_USERCODE5 0x64e8 +#define AFE_SPDIF_OUT_USERCODE6 0x64ec +#define AFE_SPDIF_OUT_BURST_PRE0 0x64f0 +#define AFE_SPDIF_OUT_BURST_PRE1 0x64f4 +#define AFE_SPDIF_OUT_MON0 0x64f8 +#define AFE_SPDIF_OUT_MON1 0x64fc +#define AFE_SPDIF_OUT_MON2 0x6500 +#define AFE_SPDIF_OUT_MON3 0x6504 +#define AFE_SPDIF_OUT_MON4 0x6508 +#define AFE_SPDIF_OUT_MON5 0x650c +#define AFE_CONN0_6 0x7000 +#define AFE_CONN1_6 0x7004 +#define AFE_CONN2_6 0x7008 +#define AFE_CONN3_6 0x700c +#define AFE_CONN4_6 0x7010 +#define AFE_CONN5_6 0x7014 +#define AFE_CONN6_6 0x7018 +#define AFE_CONN7_6 0x701c +#define AFE_CONN8_6 0x7020 +#define AFE_CONN9_6 0x7024 +#define AFE_CONN10_6 0x7028 +#define AFE_CONN11_6 0x702c +#define AFE_CONN12_6 0x7030 +#define AFE_CONN13_6 0x7034 +#define AFE_CONN14_6 0x7038 +#define AFE_CONN15_6 0x703c +#define AFE_CONN16_6 0x7040 +#define AFE_CONN17_6 0x7044 +#define AFE_CONN18_6 0x7048 +#define AFE_CONN19_6 0x704c +#define AFE_CONN20_6 0x7050 +#define AFE_CONN21_6 0x7054 +#define AFE_CONN22_6 0x7058 +#define AFE_CONN23_6 0x705c +#define AFE_CONN24_6 0x7060 +#define AFE_CONN25_6 0x7064 +#define AFE_CONN26_6 0x7068 +#define AFE_CONN27_6 0x706c +#define AFE_CONN28_6 0x7070 +#define AFE_CONN29_6 0x7074 +#define AFE_CONN30_6 0x7078 +#define AFE_CONN31_6 0x707c +#define AFE_CONN32_6 0x7080 +#define AFE_CONN33_6 0x7084 +#define AFE_CONN34_6 0x7088 +#define AFE_CONN35_6 0x708c +#define AFE_CONN36_6 0x7090 +#define AFE_CONN37_6 0x7094 +#define AFE_CONN38_6 0x7098 +#define AFE_CONN39_6 0x709c +#define AFE_CONN40_6 0x70a0 +#define AFE_CONN41_6 0x70a4 +#define AFE_CONN42_6 0x70a8 +#define AFE_CONN43_6 0x70ac +#define AFE_CONN44_6 0x70b0 +#define AFE_CONN45_6 0x70b4 +#define AFE_CONN46_6 0x70b8 +#define AFE_CONN47_6 0x70bc +#define AFE_CONN48_6 0x70c0 +#define AFE_CONN49_6 0x70c4 +#define AFE_CONN50_6 0x70c8 +#define AFE_CONN51_6 0x70cc +#define AFE_CONN52_6 0x70d0 +#define AFE_CONN53_6 0x70d4 +#define AFE_CONN54_6 0x70d8 +#define AFE_CONN55_6 0x70dc +#define AFE_CONN56_6 0x70e0 +#define AFE_CONN57_6 0x70e4 +#define AFE_CONN58_6 0x70e8 +#define AFE_CONN59_6 0x70ec +#define AFE_CONN60_6 0x70f0 +#define AFE_CONN61_6 0x70f4 +#define AFE_CONN62_6 0x70f8 +#define AFE_CONN63_6 0x70fc +#define AFE_CONN64_6 0x7100 +#define AFE_CONN65_6 0x7104 +#define AFE_CONN66_6 0x7108 +#define AFE_CONN67_6 0x710c +#define AFE_CONN68_6 0x7110 +#define AFE_CONN69_6 0x7114 +#define AFE_CONN70_6 0x7118 +#define AFE_CONN71_6 0x711c +#define AFE_CONN72_6 0x7120 +#define AFE_CONN73_6 0x7124 +#define AFE_CONN74_6 0x7128 +#define AFE_CONN75_6 0x712c +#define AFE_CONN76_6 0x7130 +#define AFE_CONN77_6 0x7134 +#define AFE_CONN78_6 0x7138 +#define AFE_CONN79_6 0x713c +#define AFE_CONN80_6 0x7140 +#define AFE_CONN81_6 0x7144 +#define AFE_CONN82_6 0x7148 +#define AFE_CONN83_6 0x714c +#define AFE_CONN84_6 0x7150 +#define AFE_CONN85_6 0x7154 +#define AFE_CONN86_6 0x7158 +#define AFE_CONN87_6 0x715c +#define AFE_CONN88_6 0x7160 +#define AFE_CONN89_6 0x7164 +#define AFE_CONN90_6 0x7168 +#define AFE_CONN91_6 0x716c +#define AFE_CONN92_6 0x7170 +#define AFE_CONN93_6 0x7174 +#define AFE_CONN94_6 0x7178 +#define AFE_CONN95_6 0x717c +#define AFE_CONN96_6 0x7180 +#define AFE_CONN97_6 0x7184 +#define AFE_CONN98_6 0x7188 +#define AFE_CONN99_6 0x718c +#define AFE_CONN100_6 0x7190 +#define AFE_CONN101_6 0x7194 +#define AFE_CONN102_6 0x7198 +#define AFE_CONN103_6 0x719c +#define AFE_CONN104_6 0x71a0 +#define AFE_CONN105_6 0x71a4 +#define AFE_CONN106_6 0x71a8 +#define AFE_CONN107_6 0x71ac +#define AFE_CONN108_6 0x71b0 +#define AFE_CONN109_6 0x71b4 +#define AFE_CONN110_6 0x71b8 +#define AFE_CONN111_6 0x71bc +#define AFE_CONN112_6 0x71c0 +#define AFE_CONN113_6 0x71c4 +#define AFE_CONN114_6 0x71c8 +#define AFE_CONN115_6 0x71cc +#define AFE_CONN116_6 0x71d0 +#define AFE_CONN117_6 0x71d4 +#define AFE_CONN118_6 0x71d8 +#define AFE_CONN119_6 0x71dc +#define AFE_CONN120_6 0x71e0 +#define AFE_CONN121_6 0x71e4 +#define AFE_CONN122_6 0x71e8 +#define AFE_CONN123_6 0x71ec +#define AFE_CONN124_6 0x71f0 +#define AFE_CONN125_6 0x71f4 +#define AFE_CONN126_6 0x71f8 +#define AFE_CONN127_6 0x71fc +#define AFE_CONN128_6 0x7200 +#define AFE_CONN129_6 0x7204 +#define AFE_CONN130_6 0x7208 +#define AFE_CONN131_6 0x720c +#define AFE_CONN132_6 0x7210 +#define AFE_CONN133_6 0x7214 +#define AFE_CONN134_6 0x7218 +#define AFE_CONN135_6 0x721c +#define AFE_CONN136_6 0x7220 +#define AFE_CONN137_6 0x7224 +#define AFE_CONN138_6 0x7228 +#define AFE_CONN139_6 0x722c +#define AFE_CONN176_6 0x72c0 +#define AFE_CONN177_6 0x72c4 +#define AFE_CONN182_6 0x72d8 +#define AFE_CONN183_6 0x72dc + +#endif diff --git a/src/platform/mt8188/include/platform/platform.h b/src/platform/mt8188/include/platform/platform.h new file mode 100644 index 000000000000..187f0fa5e6a2 --- /dev/null +++ b/src/platform/mt8188/include/platform/platform.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) +#define LPSRAM_SIZE 16384 + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT MTK_DSP_IRQ_MAILBOX +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ MTK_DSP_IRQ_SW +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#define SRAM_REG_FW_STATUS 0x4 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + trigger_irq_to_host_req(); +} + +/** + * \brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/mt8188/include/platform/trace/trace.h b/src/platform/mt8188/include/platform/trace/trace.h new file mode 100644 index 000000000000..393530083efb --- /dev/null +++ b/src/platform/mt8188/include/platform/trace/trace.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/io.h> +#include <platform/drivers/mt_reg_base.h> + +#define platform_trace_point(__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/mt8188/lib/CMakeLists.txt b/src/platform/mt8188/lib/CMakeLists.txt new file mode 100644 index 000000000000..ef71f8eea6cd --- /dev/null +++ b/src/platform/mt8188/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dma.c + memory.c + dai.c +) diff --git a/src/platform/mt8188/lib/clk.c b/src/platform/mt8188/lib/clk.c new file mode 100644 index 000000000000..f39872fca845 --- /dev/null +++ b/src/platform/mt8188/lib/clk.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <platform/drivers/mt_reg_base.h> +#include <rtos/clk.h> +#include <rtos/wait.h> +#include <sof/common.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <rtos/sof.h> +#include <sof/trace/trace.h> + +SOF_DEFINE_REG_UUID(clkdrv_mt8188); + +DECLARE_TR_CTX(clkdrv_tr, SOF_UUID(clkdrv_mt8188_uuid), LOG_LEVEL_INFO); + +/* default voltage is 0.75V */ +const struct freq_table platform_cpu_freq[] = { + { 26000000, 26000}, + { 400000000, 26000}, + { 800000000, 26000}, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static void clk_dsppll_enable(uint32_t value) +{ + tr_dbg(&clkdrv_tr, "%d\n", value); + + switch (value) { + case ADSP_CLK_PLL_400M: + io_reg_write(MTK_ADSPPLL_CON1, MTK_PLL_DIV_RATIO_400M); + break; + case ADSP_CLK_PLL_800M: + io_reg_write(MTK_ADSPPLL_CON1, MTK_PLL_DIV_RATIO_800M); + break; + default: + tr_err(&clkdrv_tr, "invalid dsppll: %d\n", value); + return; + } + + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_PWR_ON, MTK_PLL_PWR_ON); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_ISO_EN, 0); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON0, MTK_PLL_EN, MTK_PLL_EN); + wait_delay_us(20); +} + +static void clk_dsppll_disable(void) +{ + tr_dbg(&clkdrv_tr, "entry"); + + io_reg_update_bits(MTK_ADSPPLL_CON0, MTK_PLL_EN, 0); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_ISO_EN, MTK_PLL_ISO_EN); + wait_delay_us(1); + io_reg_update_bits(MTK_ADSPPLL_CON3, MTK_PLL_PWR_ON, 0); +} + +static void set_mux_adsp_sel(uint32_t value) +{ + io_reg_write(MTK_CLK_CFG_17_CLR, MTK_CLK_ADSP_MASK << MTK_CLK_ADSP_OFFSET); + io_reg_write(MTK_CLK_CFG_17_SET, value << MTK_CLK_ADSP_OFFSET); + io_reg_write(MTK_CLK_CFG_UPDATE2, MTK_CLK_UPDATE_ADSK_CLK); + + tr_dbg(&clkdrv_tr, "adsp_clk_mux=%x, CLK_CFG_17=0x%08x\n", + value, io_reg_read(MTK_CLK_CFG_17)); +} + +static void set_mux_adsp_bus_sel(uint32_t value) +{ + io_reg_write(MTK_CLK_CFG_17_CLR, + MTK_CLK_AUDIO_LOCAL_BUS_MASK << MTK_CLK_AUDIO_LOCAL_BUS_OFFSET); + io_reg_write(MTK_CLK_CFG_17_SET, value << MTK_CLK_AUDIO_LOCAL_BUS_OFFSET); + io_reg_write(MTK_CLK_CFG_UPDATE2, MTK_CLK_UPDATE_AUDIO_LOCAL_BUS_CLK); + + tr_dbg(&clkdrv_tr, "audio_local_bus_mux=%x, CLK_CFG_17=0x%08x\n", + value, io_reg_read(MTK_CLK_CFG_17)); +} + +static int clock_platform_set_dsp_freq(int clock, int freq_idx) +{ + int freq = platform_cpu_freq[freq_idx].freq; + + tr_info(&clkdrv_tr, "clock_platform_set_cpu_freq %d\n", freq); + + switch (freq_idx) { + case ADSP_CLK_26M: + set_mux_adsp_sel(MTK_CLK_ADSP_26M); + set_mux_adsp_bus_sel(MTK_CLK_AUDIO_LOCAL_BUS_26M); + clk_dsppll_disable(); + break; + case ADSP_CLK_PLL_400M: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + clk_dsppll_enable(ADSP_CLK_PLL_400M); + set_mux_adsp_sel(MTK_CLK_ADSP_ADSPPLL); + set_mux_adsp_bus_sel(MTK_CLK_AUDIO_LOCAL_BUS_MAINPLL_D_7); + break; + case ADSP_CLK_PLL_800M: + clock_platform_set_dsp_freq(clock, ADSP_CLK_26M); + clk_dsppll_enable(ADSP_CLK_PLL_800M); + set_mux_adsp_sel(MTK_CLK_ADSP_ADSPPLL); + set_mux_adsp_bus_sel(MTK_CLK_AUDIO_LOCAL_BUS_MAINPLL_D_4); + break; + } + + return 0; +} + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + 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 = clock_platform_set_dsp_freq, + }; + } + + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); +} diff --git a/src/platform/mt8188/lib/dai.c b/src/platform/mt8188/lib/dai.c new file mode 100644 index 000000000000..d721bd4c1d39 --- /dev/null +++ b/src/platform/mt8188/lib/dai.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 MediaTek. All rights reserved. + * + * Author: Trevor Wu <trevor.wu@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +#include <sof/drivers/afe-dai.h> +#include <mt8188-afe-common.h> + +static int afe_dai_handshake[MT8188_DAI_NUM] = { + AFE_HANDSHAKE(MT8188_AFE_IO_ETDM2_OUT, MT8188_IRQ_13, MT8188_MEMIF_DL2), + AFE_HANDSHAKE(MT8188_AFE_IO_ETDM1_OUT, MT8188_IRQ_14, MT8188_MEMIF_DL3), + AFE_HANDSHAKE(MT8188_AFE_IO_ADDA, MT8188_IRQ_21, MT8188_MEMIF_UL4), + AFE_HANDSHAKE(MT8188_AFE_IO_ETDM2_IN, MT8188_IRQ_22, MT8188_MEMIF_UL5), +}; + +static SHARED_DATA struct dai afe_dai[MT8188_DAI_NUM]; + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_MEDIATEK_AFE, + .dai_array = afe_dai, + .num_dais = ARRAY_SIZE(afe_dai), + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti), +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(afe_dai); i++) { + k_spinlock_init(&afe_dai[i].lock); + afe_dai[i].index = AFE_HS_GET_DAI(afe_dai_handshake[i]); + afe_dai[i].drv = &afe_dai_driver; + /* TODO, fifo[0] change to target playback or capture */ + afe_dai[i].plat_data.fifo[0].handshake = afe_dai_handshake[i]; + } + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/mt8188/lib/dma.c b/src/platform/mt8188/lib/dma.c new file mode 100644 index 000000000000..aa377133b730 --- /dev/null +++ b/src/platform/mt8188/lib/dma.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <rtos/interrupt.h> +#include <rtos/spinlock.h> +#include <sof/common.h> +#include <sof/drivers/afe-memif.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> + +#include <mt8188-afe-reg.h> +#include <mt8188-afe-common.h> + +extern const struct dma_ops dummy_dma_ops; + +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .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, +}, +{ + .plat_data = { + .id = DMA_ID_AFE_MEMIF, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_AFE_MEMIF, + .base = AFE_BASE_ADDR, + .channels = MT8188_MEMIF_NUM, + }, + .ops = &memif_ops, +}, + +}; + +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)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/mt8188/lib/memory.c b/src/platform/mt8188/lib/memory.c new file mode 100644 index 000000000000..73d3af0f4d43 --- /dev/null +++ b/src/platform/mt8188/lib/memory.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <ipc/topology.h> +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; +static SHARED_DATA struct block_hdr mod_block4096[HEAP_RT_COUNT4096]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), + BLOCK_DEF(4096, HEAP_RT_COUNT4096, mod_block4096), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/mt8188/mt8188.x.in b/src/platform/mt8188/mt8188.x.in new file mode 100644 index 000000000000..99120a0b225c --- /dev/null +++ b/src/platform/mt8188/mt8188.x.in @@ -0,0 +1,538 @@ +/* + * Linker Script for mt8188 MediaTek + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +#if CONFIG_MEDIATEK_DRAM_IMAGE +#define IMAGE_LOC sof_dram +#else +#define IMAGE_LOC sof_sram +#endif + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_sram : + org = SRAM_START, + len = SRAM_SIZE + sof_dram : + org = SOF_DRAM_BASE, + len = SOF_DRAM_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_sram_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000100; +_memmap_cacheattr_wt_base = 0x00000300; +_memmap_cacheattr_bp_base = 0x00000400; +_memmap_cacheattr_unused_mask = 0xFFFFF0FF; +_memmap_cacheattr_wb_trapnull = 0x44444140; +_memmap_cacheattr_wba_trapnull = 0x44444140; +_memmap_cacheattr_wbna_trapnull = 0x44444240; +_memmap_cacheattr_wt_trapnull = 0x44444340; +_memmap_cacheattr_bp_trapnull = 0x44444440; +_memmap_cacheattr_wb_strict = 0x00000100; +_memmap_cacheattr_wt_strict = 0x00000300; +_memmap_cacheattr_bp_strict = 0x00000400; +_memmap_cacheattr_wb_allvalid = 0x44444144; +_memmap_cacheattr_wt_allvalid = 0x44444344; +_memmap_cacheattr_bp_allvalid = 0x44444444; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + KEEP (*(.fw_ready_metadata)) + } >IMAGE_LOC :sof_sram_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >IMAGE_LOC :sof_sram_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr +} diff --git a/src/platform/mt8188/platform.c b/src/platform/mt8188/platform.c new file mode 100644 index 000000000000..fc2e83dbed25 --- /dev/null +++ b/src/platform/mt8188/platform.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + * Tinghan Shen <tinghan.shen@mediatek.com> + */ + +#include <errno.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <platform/drivers/timer.h> +#include <rtos/clk.h> +#include <rtos/timer.h> +#include <rtos/interrupt.h> +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <sof/drivers/edma.h> +#include <sof/ipc/msg.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <sof_versions.h> +#include <stdint.h> +#include <xtensa/hal.h> + +struct sof; + +static const struct sof_ipc_fw_ready ready + __section(".fw_ready") = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_MTK_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_MTK_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + } +}; + +static SHARED_DATA struct timer timer_shared = { + .id = OSTIMER0, + .irq = MTK_DSP_IRQ_OSTIMER32, +}; + +/* Override the default MPU setup. This table matches the memory map + * of the 'sample_controller' core and will need to be modified for + * other cores. + * NOTE: This table sets up all of external memory as shared uncached. + * For best results, edit the LSP memory map to create a separate + * section in shared memory, place all sections that need to be uncached + * into that section, and only map that section uncached. See README + * for more details. + */ +const struct xthal_MPU_entry __xt_mpu_init_table[] __section(".ResetVector.text") = { + XTHAL_MPU_ENTRY(0x00000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // infra + XTHAL_MPU_ENTRY(0x4e100000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // sram + XTHAL_MPU_ENTRY(0x4e180000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused + XTHAL_MPU_ENTRY(0x60000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // dram + XTHAL_MPU_ENTRY(0x60500000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_NON_CACHEABLE), // dram + XTHAL_MPU_ENTRY(0x61100000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused +}; + +const unsigned int __xt_mpu_init_table_size __section(".ResetVector.text") = + ARRAY_SIZE(__xt_mpu_init_table); + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + /* now interrupt host to tell it we are done booting */ + trigger_irq_to_host_req(); + + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = platform_shared_get(&timer_shared, sizeof(timer_shared)); + sof->cpu_timers = sof->platform_timer; + + platform_interrupt_init(); + platform_clock_init(sof); + + scheduler_init_edf(); + + /* init low latency domains and schedulers */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + platform_timer_start(sof->platform_timer); + + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* Init platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], 1, + PLATFORM_DEFAULT_CLOCK, false); + scheduler_init_ll(sof->platform_dma_domain); + + /* initialize the host IPC mechanims */ + ipc_init(sof); + + ret = dai_init(sof); + if (ret < 0) + return ret; + +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + dma_trace_init_complete(sof->dmat); +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} + diff --git a/src/platform/mt8195/CMakeLists.txt b/src/platform/mt8195/CMakeLists.txt new file mode 100644 index 000000000000..b5b1e06e9e10 --- /dev/null +++ b/src/platform/mt8195/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) + +add_local_sources(sof platform.c afe-platform.c) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8195/include/platform) diff --git a/src/platform/mt8195/afe-platform.c b/src/platform/mt8195/afe-platform.c new file mode 100644 index 000000000000..f879b2dcfeaf --- /dev/null +++ b/src/platform/mt8195/afe-platform.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#include <sof/common.h> +#include <errno.h> +#include <sof/drivers/afe-drv.h> +#include <mt8195-afe-regs.h> +#include <mt8195-afe-common.h> + +/* + * AFE: Audio Front-End + * + * frontend (memif): + * memory interface + * UL (uplink for capture) + * DL (downlink for playback) + * backend: + * TDM In + * TMD out + * DMIC + * GASRC + * etc. + * interconn: + * inter-connection, + * connect frontends and backends as DSP path + */ + +static const struct mtk_base_memif_data memif_data[MT8195_MEMIF_NUM] = { + [MT8195_MEMIF_DL2] = { + .name = "DL2", + .id = MT8195_MEMIF_DL2, + .reg_ofs_base = AFE_DL2_BASE, + .reg_ofs_cur = AFE_DL2_CUR, + .reg_ofs_end = AFE_DL2_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON0, + .fs_shift = 10, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = -1, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 18, + .hd_reg = AFE_DL2_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 18, + .ch_num_reg = AFE_DL2_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 18, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 18, + }, + [MT8195_MEMIF_DL3] = { + .name = "DL3", + .id = MT8195_MEMIF_DL3, + .reg_ofs_base = AFE_DL3_BASE, + .reg_ofs_cur = AFE_DL3_CUR, + .reg_ofs_end = AFE_DL3_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON0, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = -1, + .mono_shift = -1, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 19, + .hd_reg = AFE_DL3_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 19, + .ch_num_reg = AFE_DL3_CON0, + .ch_num_shift = 0, + .ch_num_maskbit = 0x1f, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 19, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 19, + }, + [MT8195_MEMIF_UL4] = { + .name = "UL4", + .id = MT8195_MEMIF_UL4, + .reg_ofs_base = AFE_UL4_BASE, + .reg_ofs_cur = AFE_UL4_CUR, + .reg_ofs_end = AFE_UL4_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 15, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL4_CON0, + .mono_shift = 1, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 4, + .hd_reg = AFE_UL4_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 3, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 3, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 3, + }, + [MT8195_MEMIF_UL5] = { + .name = "UL5", + .id = MT8195_MEMIF_UL5, + .reg_ofs_base = AFE_UL5_BASE, + .reg_ofs_cur = AFE_UL5_CUR, + .reg_ofs_end = AFE_UL5_END, + .fs_reg = AFE_MEMIF_AGENT_FS_CON2, + .fs_shift = 20, + .fs_maskbit = 0x1f, + .mono_reg = AFE_UL5_CON0, + .mono_shift = 1, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 5, + .hd_reg = AFE_UL5_CON0, + .hd_shift = 5, + .agent_disable_reg = AUDIO_TOP_CON5, + .agent_disable_shift = 4, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_NORMAL_BASE_ADR_MSB, + .msb_shift = 4, + .msb2_reg = AFE_NORMAL_END_ADR_MSB, + .msb2_shift = 4, + } +}; + +struct mt8195_afe_rate { + unsigned int rate; + unsigned int reg_value; +}; + +static const struct mt8195_afe_rate mt8195_afe_rates[] = { + { + .rate = 8000, + .reg_value = 0, + }, + { + .rate = 12000, + .reg_value = 1, + }, + { + .rate = 16000, + .reg_value = 2, + }, + { + .rate = 24000, + .reg_value = 3, + }, + { + .rate = 32000, + .reg_value = 4, + }, + { + .rate = 48000, + .reg_value = 5, + }, + { + .rate = 96000, + .reg_value = 6, + }, + { + .rate = 192000, + .reg_value = 7, + }, + { + .rate = 384000, + .reg_value = 8, + }, + { + .rate = 7350, + .reg_value = 16, + }, + { + .rate = 11025, + .reg_value = 17, + }, + { + .rate = 14700, + .reg_value = 18, + }, + { + .rate = 22050, + .reg_value = 19, + }, + { + .rate = 29400, + .reg_value = 20, + }, + { + .rate = 44100, + .reg_value = 21, + }, + { + .rate = 88200, + .reg_value = 22, + }, + { + .rate = 176400, + .reg_value = 23, + }, + { + .rate = 352800, + .reg_value = 24, + }, +}; + +static unsigned int mt8195_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8195_afe_rates); i++) + if (mt8195_afe_rates[i].rate == rate) + return mt8195_afe_rates[i].reg_value; + + return -EINVAL; +} + +static unsigned int mt8195_afe_fs(unsigned int rate, int aud_blk) +{ + return mt8195_afe_fs_timing(rate); +} + +static unsigned int mt8195_afe2adsp_addr(unsigned int addr) +{ + /*TODO : Need apply the address remap */ + return addr; +} + +static unsigned int mt8195_adsp2afe_addr(unsigned int addr) +{ + /* TODO : Need apply the address remap */ + return addr; +} + +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = AFE_BASE_ADDR, + .memif_datas = memif_data, + .memif_size = MT8195_MEMIF_NUM, + .memif_dl_num = MT8195_MEMIF_DL_NUM, + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = MT8195_DAI_NUM, + .afe2adsp_addr = mt8195_afe2adsp_addr, + .adsp2afe_addr = mt8195_adsp2afe_addr, + .afe_fs = mt8195_afe_fs, + .irq_fs = mt8195_afe_fs_timing, +}; diff --git a/src/platform/mt8195/include/arch/xtensa/config/core-isa.h b/src/platform/mt8195/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..0c5a5fd59fe5 --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,697 @@ +/* +* xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa +* processor CORE configuration +* +* See <xtensa/config/core.h>, which includes this file, for more details. +*/ +/* Xtensa processor core configuration information. + + Customer ID=16233; Build=0x89932; Copyright (c) 1999-2020 Tensilica 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. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + +/* depot/dev/Homewood/Xtensa/SWConfig/hal/core-common.h.tph#24 - edit change 444323 (text+ko) */ + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 11 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 1 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 0 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 0 /* HiFi5 Audio Engine NN-MAC option */ +#define XCHAL_HAVE_HIFI5_VFPU 0 /* HiFi5 Audio Engine Single-Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_HP_VFPU 0 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 1 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 /* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 /* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 /* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 /* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6 or Q7 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1401000 /* sw version of this header */ +#define XCHAL_SW_MINOR_VERSION 1401000 /* same, with zeroed micro and patch */ +#define XCHAL_SW_MICRO_VERSION 1401000 /* same, with zeroed patch */ + +#define XCHAL_CORE_ID "hifi4_8195_PROD" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x00089932 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC003B286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x28489932 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.1" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO /* subdot ver# of targeted hw */ +#define XCHAL_HW_VERSION 281010 /* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_1 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281010 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281010 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 32768 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 15 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 6 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 8 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + + +#define XCHAL_HAVE_IDMA 0 + + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 0 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 25 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 18 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels + (not including level zero) */ + + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 2 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00B900FF +#define XCHAL_INTLEVEL2_MASK 0x0142FF00 +#define XCHAL_INTLEVEL3_MASK 0x00040000 +#define XCHAL_INTLEVEL4_MASK 0x00000000 +#define XCHAL_INTLEVEL5_MASK 0x00000000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00B900FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x01FBFFFF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x01FFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 2 +#define XCHAL_INT10_LEVEL 2 +#define XCHAL_INT11_LEVEL 2 +#define XCHAL_INT12_LEVEL 2 +#define XCHAL_INT13_LEVEL 2 +#define XCHAL_INT14_LEVEL 2 +#define XCHAL_INT15_LEVEL 2 +#define XCHAL_INT16_LEVEL 1 +#define XCHAL_INT17_LEVEL 2 +#define XCHAL_INT18_LEVEL 3 +#define XCHAL_INT19_LEVEL 1 +#define XCHAL_INT20_LEVEL 1 +#define XCHAL_INT21_LEVEL 1 +#define XCHAL_INT22_LEVEL 2 +#define XCHAL_INT23_LEVEL 1 +#define XCHAL_INT24_LEVEL 2 +#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFE000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x01803F3F +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x0000C0C0 +#define XCHAL_INTTYPE_MASK_NMI 0x00000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00600000 +#define XCHAL_INTTYPE_MASK_TIMER 0x00070000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00080000 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00100000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 16 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 17 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 18 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_WRITE_ERROR_INTERRUPT 19 +#define XCHAL_PROFILING_INTERRUPT 20 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL3_NUM 18 +/* (There are many interrupts each at level(s) 1, 2.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT9_NUM 9 /* (intlevel 2) */ +#define XCHAL_EXTINT10_NUM 10 /* (intlevel 2) */ +#define XCHAL_EXTINT11_NUM 11 /* (intlevel 2) */ +#define XCHAL_EXTINT12_NUM 12 /* (intlevel 2) */ +#define XCHAL_EXTINT13_NUM 13 /* (intlevel 2) */ +#define XCHAL_EXTINT14_NUM 14 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 15 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 23 /* (intlevel 1) */ +#define XCHAL_EXTINT17_NUM 24 /* (intlevel 2) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT6_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT7_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 8 /* (intlevel 2) */ +#define XCHAL_INT9_EXTNUM 9 /* (intlevel 2) */ +#define XCHAL_INT10_EXTNUM 10 /* (intlevel 2) */ +#define XCHAL_INT11_EXTNUM 11 /* (intlevel 2) */ +#define XCHAL_INT12_EXTNUM 12 /* (intlevel 2) */ +#define XCHAL_INT13_EXTNUM 13 /* (intlevel 2) */ +#define XCHAL_INT14_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT15_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT23_EXTNUM 16 /* (intlevel 1) */ +#define XCHAL_INT24_EXTNUM 17 /* (intlevel 2) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (until T1050) + 2 == XEA2 (T1040 onwards) + 3 == XEA3 (LX8/NX/SX onwards) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x40000400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x40000400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 /* UNUSED */ + +#define XCHAL_RESET_VECTOR0_VADDR 0x40000000 +#define XCHAL_RESET_VECTOR0_PADDR 0x40000000 +#define XCHAL_RESET_VECTOR1_VADDR 0x40000640 +#define XCHAL_RESET_VECTOR1_PADDR 0x40000640 +#define XCHAL_RESET_VECTOR_VADDR XCHAL_RESET_VECTOR1_VADDR +#define XCHAL_RESET_VECTOR_PADDR XCHAL_RESET_VECTOR1_PADDR +#define XCHAL_USER_VECOFS 0x000001FC +#define XCHAL_USER_VECTOR_VADDR 0x400005FC +#define XCHAL_USER_VECTOR_PADDR 0x400005FC +#define XCHAL_KERNEL_VECOFS 0x000001DC +#define XCHAL_KERNEL_VECTOR_VADDR 0x400005DC +#define XCHAL_KERNEL_VECTOR_PADDR 0x400005DC +#define XCHAL_DOUBLEEXC_VECOFS 0x0000021C +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x4000061C +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x4000061C +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x40000400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x40000400 +#define XCHAL_INTLEVEL2_VECOFS 0x0000017C +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x4000057C +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x4000057C +#define XCHAL_INTLEVEL3_VECOFS 0x0000019C +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x4000059C +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x4000059C +#define XCHAL_INTLEVEL4_VECOFS 0x000001BC +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x400005BC +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x400005BC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL4_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 4096 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 8 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 0 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 1 +#define XCHAL_MPU_ENTRIES 32 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 2 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0xFF /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 12 +#define XCHAL_MPU_ALIGN 4096 + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/src/platform/mt8195/include/arch/xtensa/config/core-matmap.h b/src/platform/mt8195/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..d6e9558c0eb4 --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,105 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=16233; Build=0x89932; Copyright (c) 1999-2020 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ + +/* Mappings for legacy constants where appropriate */ + +#define XCHAL_CA_WRITEBACK (XTHAL_MEM_WRITEBACK | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITEBACK_NOALLOC (XTHAL_MEM_WRITEBACK_NOALLOC | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITETHRU (XTHAL_MEM_WRITETHRU | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_ILLEGAL (XTHAL_AR_NONE | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASSBUF (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE | XTHAL_MEM_BUFFERABLE) +#define XCHAL_CA_BYPASS_RX (XTHAL_AR_RX | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_RW (XTHAL_AR_RW | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_R (XTHAL_AR_R | XTHAL_MEM_DEVICE) +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 + +#define XCHAL_CA_R (XTHAL_AR_R) +#define XCHAL_CA_RX (XTHAL_AR_RX) +#define XCHAL_CA_RW (XTHAL_AR_RW) +#define XCHAL_CA_RWX (XTHAL_AR_RWX) + + +/* + * Contents of MPU background map. + * NOTE: caller must define the XCHAL_MPU_BGMAP() macro (not defined here + * but specified below) before expanding the XCHAL_MPU_BACKGROUND_MAP(s) macro. + * + * XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) + * + * s = passed from XCHAL_MPU_BACKGROUND_MAP(s), eg. to select how to expand + * vaddr_start = first byte of region (always 0 for first entry) + * vaddr_end = last byte of region (always 0xFFFFFFFF for last entry) + * rights = access rights + * memtype = memory type + * x = reserved for future use (0 until then) + */ +/* parasoft-begin-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ +#define XCHAL_MPU_BACKGROUND_MAP(s) \ + (XCHAL_MPU_BGMAP(s, 0x00000000, 0x7fffffff, 7, 6, 0) \ + XCHAL_MPU_BGMAP(s, 0x80000000, 0xffffffff, 7, 6, 0)) +/* parasoft-end-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ + + /* end */ + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/mt8195/include/arch/xtensa/config/defs.h b/src/platform/mt8195/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..23229428bb0b --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=16233; Build=0x89932; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/mt8195/include/arch/xtensa/config/specreg.h b/src/platform/mt8195/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..4961e38f895f --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/specreg.h @@ -0,0 +1,104 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: /depot/rel/Homewood/ib.1/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=16233; Build=0x89932; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define MPUENB 90 +#define ERACCESS 95 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEADRDIS 98 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/mt8195/include/arch/xtensa/config/system.h b/src/platform/mt8195/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..aa462dbdd47b --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/system.h @@ -0,0 +1,249 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=16233; Build=0x89932; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x40000000 +#define XSHAL_RAM_PADDR 0x40000000 +#define XSHAL_RAM_VSIZE 0x80000000 +#define XSHAL_RAM_PSIZE 0x80000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x40000640 +#define XSHAL_RAM_AVAIL_VSIZE 0x7FFFF9C0 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 +#define XSHAL_SIMIO_PADDR 0xC0000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xdeece000 +#define XSHAL_STL_INFO_LOCATION 0x6c + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22444422 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22111122 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22111122 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF4444FF /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF1111FF /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF1111FF /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF2222FF /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244442F /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211112F /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211112F /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF42442F /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF12112F /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF12112F /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000014 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 1 +#define XSHAL_RESET_VECTOR_VADDR 0x40000640 +#define XSHAL_RESET_VECTOR_PADDR 0x40000640 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x0000001C +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL4_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL4_VECTOR_ISROM + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/mt8195/include/arch/xtensa/config/tie-asm.h b/src/platform/mt8195/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..5d3937e9e977 --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,314 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=16233; Build=0x89932; Copyright (c) 1999-2020 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie, ccuse, abi) (((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI)) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 + xchal_sa_start \continue, \ofs + /* Optional global registers used by default by the compiler: */ + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.threadptr \at1 /* threadptr option */ + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + /* Optional caller-saved registers not used by default by the compiler: */ + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rsr.br \at1 /* boolean option */ + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm /* xchal_ncp_store */ + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 + xchal_sa_start \continue, \ofs + /* Optional global registers used by default by the compiler: */ + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.threadptr \at1 /* threadptr option */ + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + /* Optional caller-saved registers not used by default by the compiler: */ + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.br \at1 /* boolean option */ + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm /* xchal_ncp_load */ + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 + xchal_sa_start \continue, \ofs + /* Custom caller-saved registers not used by default by the compiler: */ + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+32 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+40 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+41 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+42 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+43 + ae_salign64.i u0, \ptr, .Lxchal_ofs_+48 + ae_salign64.i u1, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_salign64.i u2, \ptr, .Lxchal_ofs_+0 + ae_salign64.i u3, \ptr, .Lxchal_ofs_+8 + addi.a \ptr, \ptr, -192 + ae_movvfcrfsr aed0 /* ureg FCR_FSR */ + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + rur.ae_ovf_sar \at1 /* ureg 240 */ + s32i \at1, \ptr, .Lxchal_ofs_+8 + rur.ae_bithead \at1 /* ureg 241 */ + s32i \at1, \ptr, .Lxchal_ofs_+12 + rur.ae_ts_fts_bu_bp \at1 /* ureg 242 */ + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.ae_cw_sd_no \at1 /* ureg 243 */ + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.ae_cbegin0 \at1 /* ureg 246 */ + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.ae_cend0 \at1 /* ureg 247 */ + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.ae_cbegin1 \at1 /* ureg 248 */ + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.ae_cend1 \at1 /* ureg 249 */ + s32i \at1, \ptr, .Lxchal_ofs_+36 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .endif + .endm /* xchal_cp1_store */ + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 + xchal_sa_start \continue, \ofs + /* Custom caller-saved registers not used by default by the compiler: */ + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 /* ureg FCR_FSR */ + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.ae_ovf_sar \at1 /* ureg 240 */ + l32i \at1, \ptr, .Lxchal_ofs_+12 + wur.ae_bithead \at1 /* ureg 241 */ + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.ae_ts_fts_bu_bp \at1 /* ureg 242 */ + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.ae_cw_sd_no \at1 /* ureg 243 */ + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.ae_cbegin0 \at1 /* ureg 246 */ + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.ae_cend0 \at1 /* ureg 247 */ + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.ae_cbegin1 \at1 /* ureg 248 */ + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.ae_cend1 \at1 /* ureg 249 */ + ae_l64.i aed0, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+56 + addi.a \ptr, \ptr, 64 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+32 + addi.a \ptr, \ptr, 40 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi.a \ptr, \ptr, 8 + ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 + ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 + ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 176 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .endif + .endm /* xchal_cp1_load */ + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp0_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp2_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp2_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp3_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp3_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp4_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp4_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp5_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp5_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp6_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp6_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp7_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm + .macro xchal_cp7_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/mt8195/include/arch/xtensa/config/tie.h b/src/platform/mt8195/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..e7e8a6847e43 --- /dev/null +++ b/src/platform/mt8195/include/arch/xtensa/config/tie.h @@ -0,0 +1,191 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=16233; Build=0x89932; Copyright (c) 1999-2020 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. */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 208 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 8 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 224 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 2 +#define XCHAL_NCP_SA_LIST(s) \ + (XCHAL_SA_REG(s, 1, 2, 1, 1, threadptr, 4, 4, 4, 0x03E7, ur, 231, 32, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 0, 1, br, 4, 4, 4, 0x0204, sr, 4, 16, 0, 0, 0)) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 33 +#define XCHAL_CP1_SA_LIST(s) \ + (XCHAL_SA_REG(s, 0, 0, 1, 0, fcr_fsr, 8, 8, 8, 0x1019, ur, -1, 7, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_ovf_sar, 4, 4, 4, 0x03F0, ur, 240, 15, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_bithead, 4, 4, 4, 0x03F1, ur, 241, 32, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_ts_fts_bu_bp, 4, 4, 4, 0x03F2, ur, 242, 16, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cw_sd_no, 4, 4, 4, 0x03F3, ur, 243, 29, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cbegin0, 4, 4, 4, 0x03F6, ur, 246, 32, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cend0, 4, 4, 4, 0x03F7, ur, 247, 32, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cbegin1, 4, 4, 4, 0x03F8, ur, 248, 32, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cend1, 4, 4, 4, 0x03F9, ur, 249, 32, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed0, 8, 8, 8, 0x1000, aed, 0, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed1, 8, 8, 8, 0x1001, aed, 1, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed2, 8, 8, 8, 0x1002, aed, 2, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed3, 8, 8, 8, 0x1003, aed, 3, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed4, 8, 8, 8, 0x1004, aed, 4, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed5, 8, 8, 8, 0x1005, aed, 5, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed6, 8, 8, 8, 0x1006, aed, 6, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed7, 8, 8, 8, 0x1007, aed, 7, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed8, 8, 8, 8, 0x1008, aed, 8, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed9, 8, 8, 8, 0x1009, aed, 9, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed10, 8, 8, 8, 0x100A, aed, 10, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed11, 8, 8, 8, 0x100B, aed, 11, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed12, 8, 8, 8, 0x100C, aed, 12, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed13, 8, 8, 8, 0x100D, aed, 13, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed14, 8, 8, 8, 0x100E, aed, 14, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aed15, 8, 8, 8, 0x100F, aed, 15, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aep0, 1, 1, 1, 0x1014, aep, 0, 8, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aep1, 1, 1, 1, 0x1015, aep, 1, 8, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aep2, 1, 1, 1, 0x1016, aep, 2, 8, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, aep3, 1, 1, 1, 0x1017, aep, 3, 8, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, u0, 8, 8, 8, 0x1010, u, 0, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, u1, 8, 8, 8, 0x1011, u, 1, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, u2, 8, 8, 8, 0x1012, u, 2, 64, 0, 0, 0) \ + XCHAL_SA_REG(s, 0, 0, 2, 0, u3, 8, 8, 8, 0x1013, u, 3, 64, 0, 0, 0)) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +/* (not available, must use XCHAL_BYTE0_FORMAT_LENGTHS for this processor) */ +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + (3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11,\ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 6, 11) + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/mt8195/include/platform/drivers/idc.h b/src/platform/mt8195/include/platform/drivers/idc.h new file mode 100644 index 000000000000..7f3d5213aade --- /dev/null +++ b/src/platform/mt8195/include/platform/drivers/idc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +static inline int idc_init(void) +{ + return 0; +} + +#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/mt8195/include/platform/drivers/interrupt.h b/src/platform/mt8195/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..50a9ce207661 --- /dev/null +++ b/src/platform/mt8195/include/platform/drivers/interrupt.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <stdint.h> +#include <platform/drivers/mt_reg_base.h> + +#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM +#define PLATFORM_IRQ_CHILDREN 32 + +/* IRQ numbers - wrt Tensilica DSP */ +#if CONFIG_XT_INTERRUPT_LEVEL_1 +#define IRQ_NUM_TIMER0 0 +#define IRQ_NUM_SOFTWARE0 21 +#define IRQ_NUM_EXT_LEVEL01 1 +#define IRQ_NUM_EXT_LEVEL23 23 +#define IRQ_EXT_DOMAIN0 IRQ_NUM_EXT_LEVEL01 +#define IRQ_EXT_DOMAIN1 IRQ_NUM_EXT_LEVEL23 +#define IRQ_EXT_DOMAIN0_OFFSET 4 +#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) +#define IRQ_MASK_TIMER0 BIT(IRQ_NUM_TIMER0) +#define IRQ_MASK_GROUP16 BIT(IRQ_NUM_GROUP16) +#endif + +#if CONFIG_XT_INTERRUPT_LEVEL_2 +#define IRQ_NUM_SOFTWARE1 22 /* level 2 */ +#define IRQ_NUM_EXT_LEVEL09 9 /* Level 2 */ +#define IRQ_NUM_EXT_LEVEL24 24 /* Level 2 */ +#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) +#define IRQ_MASK_GROUP17 BIT(IRQ_NUM_GROUP17) +#endif + +/* platform irq information */ +#define IRQ_TYPE_EDGE_RISING 0x00000001 +#define IRQ_TYPE_EDGE_FALLING 0x00000002 +#define IRQ_TYPE_LEVEL_HIGH 0x00000004 +#define IRQ_TYPE_LEVEL_LOW 0x00000008 + +/* int level */ +#define IRQ_INVALID 0xff +#define IRQ_MASK 0xff +#define IRQ_EXT_DOMAIN1_MASK 0x3FFFFFF0 +#define IRQ_EXT_DOMAIN2_MASK 0xFFFF +#define GET_INTERRUPT_ID(n) ((n) & IRQ_MASK) +#define LEVEL_SHFIT 8 +#define LEVEL_MASK 0xff +#define INT_LEVEL(n) ((n) << LEVEL_SHFIT) +#define GET_INTLEVEL(irq) (((irq) >> LEVEL_SHFIT) & LEVEL_MASK) +#define IRQ_LEVEL0 0 +#define IRQ_LEVEL1 1 + +/* + * IRQ = 0xcc-dd + * cc = int level + * dd = irq + * LX_MODULEX_IRQX_B = ( (0xcc << 8 ) | 0xdd ) + * All irq dispatch to level0 default + */ +#define INTERRUPT_ID(ID) (ID) + +#define L1_INT_IRQ_B (INT_LEVEL(1) | IRQ_INVALID) +#define L23_INT_IRQ_B (INT_LEVEL(23) | IRQ_INVALID) +#define L1_DSP_TIMER_IRQ0_B (INT_LEVEL(2) | INTERRUPT_ID(0)) +#define L1_DSP_TIMER_IRQ1_B (INT_LEVEL(3) | INTERRUPT_ID(1)) +#define L1_DSP_TIMER_IRQ2_B (INT_LEVEL(4) | INTERRUPT_ID(2)) +#define L1_DSP_TIMER_IRQ3_B (INT_LEVEL(5) | INTERRUPT_ID(3)) + +#define LX_CQDMA_IRQ0_B (INT_LEVEL(1) | INTERRUPT_ID(4)) +#define LX_CQDMA_IRQ1_B (INT_LEVEL(1) | INTERRUPT_ID(5)) +#define LX_CQDMA_IRQ2_B (INT_LEVEL(1) | INTERRUPT_ID(6)) +#define LX_CQDMA_IRQ3_B (INT_LEVEL(1) | INTERRUPT_ID(7)) +#define LX_UART_IRQ_B (INT_LEVEL(1) | INTERRUPT_ID(8)) +#define LX_AFE_IRQ_B (INT_LEVEL(1) | INTERRUPT_ID(9)) +#define LX_MCU_IRQ_B (INT_LEVEL(1) | INTERRUPT_ID(10)) +#define LX_I2C_IRQ4_B (INT_LEVEL(1) | INTERRUPT_ID(11)) +#define LX_I2C_IRQ5_B (INT_LEVEL(1) | INTERRUPT_ID(12)) +#define LX_RSVD_IRQ1_B (INT_LEVEL(1) | INTERRUPT_ID(13)) +#define LX_RSVD_IRQ2_B (INT_LEVEL(1) | INTERRUPT_ID(14)) +#define LX_ASRC_IRQ0_B (INT_LEVEL(1) | INTERRUPT_ID(15)) +#define LX_ASRC_IRQ1_B (INT_LEVEL(1) | INTERRUPT_ID(16)) +#define LX_ASRC_IRQ2_B (INT_LEVEL(1) | INTERRUPT_ID(17)) +#define LX_ASRC_IRQ3_B (INT_LEVEL(1) | INTERRUPT_ID(18)) +#define LX_ASRC_IRQ4_B (INT_LEVEL(1) | INTERRUPT_ID(19)) +#define LX_ASRC_IRQ5_B (INT_LEVEL(1) | INTERRUPT_ID(20)) +#define LX_ASRC_IRQ6_B (INT_LEVEL(1) | INTERRUPT_ID(21)) +#define LX_ASRC_IRQ7_B (INT_LEVEL(1) | INTERRUPT_ID(22)) +#define LX_ASRC_IRQ8_B (INT_LEVEL(1) | INTERRUPT_ID(23)) +#define LX_ASRC_IRQ9_B (INT_LEVEL(1) | INTERRUPT_ID(24)) +#define LX_ASRC_IRQ10_B (INT_LEVEL(1) | INTERRUPT_ID(25)) +#define LX_ASRC_IRQ11_B (INT_LEVEL(1) | INTERRUPT_ID(26)) +#define LX_ASRC_IRQ15_IRQ12_B (INT_LEVEL(1) | INTERRUPT_ID(27)) +#define LX_SPM_IRQ_B (INT_LEVEL(1) | INTERRUPT_ID(28)) +#define LX_SCP_IRQ_B (INT_LEVEL(1) | INTERRUPT_ID(29)) +#define LX_MBOX_IRQ0_B (INT_LEVEL(23) | INTERRUPT_ID(32)) +#define LX_MBOX_IRQ1_B (INT_LEVEL(23) | INTERRUPT_ID(33)) +#define LX_MBOX_IRQ2_B (INT_LEVEL(23) | INTERRUPT_ID(34)) +#define LX_MBOX_IRQ3_B (INT_LEVEL(23) | INTERRUPT_ID(35)) +#define LX_MBOX_IRQ4_B (INT_LEVEL(23) | INTERRUPT_ID(36)) +#define LX_MISC_NNA0_IRQ0_B (INT_LEVEL(23) | INTERRUPT_ID(37)) +#define LX_MISC_NNA0_IRQ1_B (INT_LEVEL(23) | INTERRUPT_ID(38)) +#define LX_MISC_NNA0_IRQ2_B (INT_LEVEL(23) | INTERRUPT_ID(39)) +#define LX_MISC_NNA1_IRQ0_B (INT_LEVEL(23) | INTERRUPT_ID(40)) +#define LX_MISC_NNA1_IRQ1_B (INT_LEVEL(23) | INTERRUPT_ID(41)) +#define LX_MISC_NNA1_IRQ2_B (INT_LEVEL(23) | INTERRUPT_ID(42)) +#define LX_ADSP_TIMTER_IRQ0_B (INT_LEVEL(23) | INTERRUPT_ID(43)) +#define LX_ADSP_TIMTER_IRQ1_B (INT_LEVEL(23) | INTERRUPT_ID(44)) +#define LX_ADSP_TIMTER_IRQ2_B (INT_LEVEL(23) | INTERRUPT_ID(45)) +#define LX_ADSP_TIMTER_IRQ3_B (INT_LEVEL(23) | INTERRUPT_ID(46)) +#define LX_OS_TIMTER_IRQ_B (INT_LEVEL(23) | INTERRUPT_ID(47)) + +#define MAX_IRQ_NUM 64 +#define DOMAIN1_MAX_IRQ_NUM 32 +#define MAX_INT_LEVEL 24 +#define AUDIO_IRQn LX_AFE_IRQ_B +/* + * irq register information + * INT 23/24 + * + */ +#define DSP_IRQ_POL MTK_DSP_RG_DSP_IRQ_POL +#define DSP_IRQ_EN MTK_DSP_DSP_IRQ_EN +#define DSP_IRQ_LEVEL MTK_DSP_DSP_IRQ_LEVEL +#define DSP_IRQ_STATUS MTK_DSP_DSP_IRQ_STATUS + +/* + * irq register information + * INT 0~15 + * + */ +#define RG_DSP_IRQ_POL MTK_DSP_RG_INT_POL_CTL0 +#define RG_DSP_IRQ_EN MTK_DSP_RG_INT_EN_CTL0 +#define RG_DSP_IRQ_LEVEL MTK_DSP_RG_INT_LV_CTL0 +#define RG_DSP_IRQ_STATUS MTK_DSP_RG_INT_STATUS0 + +uint32_t mtk_get_irq_domain_id(int32_t irq); + +#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/mt8195/include/platform/drivers/mt_reg_base.h b/src/platform/mt8195/include/platform/drivers/mt_reg_base.h new file mode 100644 index 000000000000..0c94c06bc6e8 --- /dev/null +++ b/src/platform/mt8195/include/platform/drivers/mt_reg_base.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#ifndef MT_REG_BASE_H +#define MT_REG_BASE_H + +#define MTK_DSP_IRQ_BASE 0x10009000 +#define MTK_DSP_IRQ_SIZE 0x1000 + +#define MTK_TOPCKGEN_REG_BASE 0x1001B000 +#define MTK_TOPCKGEN_REG_SIZE 0x00001000 + +#define MTK_DSP_REG_REMAP_BASE 0x10800000 +#define MTK_DSP_REG_REMAP_SIZE 0xE000 +#define MTK_DSP_TIMER_BASE 0x10800000 +#define MTK_DSP_UART0_BASE 0x10801000 +#define MTK_DSP_REG_BASE 0x10803000 /* DSPCFG base */ +#define MTK_DSP_WDT_BASE 0x10803400 +#define MTK_DSP_OSTIMER_BASE 0x1080D000 + +#define MTK_DSP_JTAGMUX (MTK_DSP_REG_BASE + 0x0000) +#define MTK_DSP_ALTRESETVEC (MTK_DSP_REG_BASE + 0x0004) +#define MTK_DSP_PDEBUGDATA (MTK_DSP_REG_BASE + 0x0008) +#define MTK_DSP_PDEBUGBUS0 (MTK_DSP_REG_BASE + 0x000c) +#define MTK_DSP_PDEBUGBUS1 (MTK_DSP_REG_BASE + 0x0010) +#define MTK_DSP_PDEBUGINST (MTK_DSP_REG_BASE + 0x0014) +#define MTK_DSP_PDEBUGLS0STAT (MTK_DSP_REG_BASE + 0x0018) +#define MTK_DSP_PDEBUGLS1STAT (MTK_DSP_REG_BASE + 0x001c) +#define MTK_DSP_PDEBUGPC (MTK_DSP_REG_BASE + 0x0020) +#define MTK_DSP_RESET_SW (MTK_DSP_REG_BASE + 0x0024) +#define MTK_DSP_PFAULTBUS (MTK_DSP_REG_BASE + 0x0028) +#define MTK_DSP_PFAULTINFO (MTK_DSP_REG_BASE + 0x002c) +#define MTK_DSP_GPR00 (MTK_DSP_REG_BASE + 0x0030) +#define MTK_DSP_GPR01 (MTK_DSP_REG_BASE + 0x0034) +#define MTK_DSP_GPR02 (MTK_DSP_REG_BASE + 0x0038) +#define MTK_DSP_GPR03 (MTK_DSP_REG_BASE + 0x003c) +#define MTK_DSP_GPR04 (MTK_DSP_REG_BASE + 0x0040) +#define MTK_DSP_GPR05 (MTK_DSP_REG_BASE + 0x0044) +#define MTK_DSP_GPR06 (MTK_DSP_REG_BASE + 0x0048) +#define MTK_DSP_GPR07 (MTK_DSP_REG_BASE + 0x004c) +#define MTK_DSP_GPR08 (MTK_DSP_REG_BASE + 0x0050) +#define MTK_DSP_GPR09 (MTK_DSP_REG_BASE + 0x0054) +#define MTK_DSP_GPR0A (MTK_DSP_REG_BASE + 0x0058) +#define MTK_DSP_GPR0B (MTK_DSP_REG_BASE + 0x005c) +#define MTK_DSP_GPR0C (MTK_DSP_REG_BASE + 0x0060) +#define MTK_DSP_GPR0D (MTK_DSP_REG_BASE + 0x0064) +#define MTK_DSP_GPR0E (MTK_DSP_REG_BASE + 0x0068) +#define MTK_DSP_GPR0F (MTK_DSP_REG_BASE + 0x006c) +#define MTK_DSP_GPR10 (MTK_DSP_REG_BASE + 0x0070) +#define MTK_DSP_GPR11 (MTK_DSP_REG_BASE + 0x0074) +#define MTK_DSP_GPR12 (MTK_DSP_REG_BASE + 0x0078) +#define MTK_DSP_GPR13 (MTK_DSP_REG_BASE + 0x007c) +#define MTK_DSP_GPR14 (MTK_DSP_REG_BASE + 0x0080) +#define MTK_DSP_GPR15 (MTK_DSP_REG_BASE + 0x0084) +#define MTK_DSP_GPR16 (MTK_DSP_REG_BASE + 0x0088) +#define MTK_DSP_GPR17 (MTK_DSP_REG_BASE + 0x008c) +#define MTK_DSP_GPR18 (MTK_DSP_REG_BASE + 0x0090) +#define MTK_DSP_GPR19 (MTK_DSP_REG_BASE + 0x0094) +#define MTK_DSP_GPR1A (MTK_DSP_REG_BASE + 0x0098) +#define MTK_DSP_GPR1B (MTK_DSP_REG_BASE + 0x009c) +#define MTK_DSP_GPR1C (MTK_DSP_REG_BASE + 0x00a0) +#define MTK_DSP_GPR1D (MTK_DSP_REG_BASE + 0x00a4) +#define MTK_DSP_GPR1E (MTK_DSP_REG_BASE + 0x00a8) +#define MTK_DSP_GPR1F (MTK_DSP_REG_BASE + 0x00ac) +#define MTK_DSP_TCM_OFFSET (MTK_DSP_REG_BASE + 0x00b0) /* not used */ +#define MTK_DSP_DDR_OFFSET (MTK_DSP_REG_BASE + 0x00b4) /* not used */ +#define MTK_DSP_INTFDSP (MTK_DSP_REG_BASE + 0x00d0) +#define MTK_DSP_INTFDSP_CLR (MTK_DSP_REG_BASE + 0x00d4) +#define MTK_DSP_SRAM_PD_SW1 (MTK_DSP_REG_BASE + 0x00d8) +#define MTK_DSP_SRAM_PD_SW2 (MTK_DSP_REG_BASE + 0x00dc) +#define MTK_DSP_OCD (MTK_DSP_REG_BASE + 0x00e0) +#define MTK_DSP_RG_DSP_IRQ_POL (MTK_DSP_REG_BASE + 0x00f0) +#define MTK_DSP_DSP_IRQ_EN (MTK_DSP_REG_BASE + 0x00f4) +#define MTK_DSP_DSP_IRQ_LEVEL (MTK_DSP_REG_BASE + 0x00f8) +#define MTK_DSP_DSP_IRQ_STATUS (MTK_DSP_REG_BASE + 0x00fc) +#define MTK_DSP_RG_INT2CIRQ (MTK_DSP_REG_BASE + 0x0114) +#define MTK_DSP_RG_INT_POL_CTL0 (MTK_DSP_REG_BASE + 0x0120) +#define MTK_DSP_RG_INT_EN_CTL0 (MTK_DSP_REG_BASE + 0x0130) +#define MTK_DSP_RG_INT_LV_CTL0 (MTK_DSP_REG_BASE + 0x0140) +#define MTK_DSP_RG_INT_STATUS0 (MTK_DSP_REG_BASE + 0x0150) +#define MTK_DSP_PDEBUGSTATUS0 (MTK_DSP_REG_BASE + 0x0200) +#define MTK_DSP_PDEBUGSTATUS1 (MTK_DSP_REG_BASE + 0x0204) +#define MTK_DSP_PDEBUGSTATUS2 (MTK_DSP_REG_BASE + 0x0208) +#define MTK_DSP_PDEBUGSTATUS3 (MTK_DSP_REG_BASE + 0x020c) +#define MTK_DSP_PDEBUGSTATUS4 (MTK_DSP_REG_BASE + 0x0210) +#define MTK_DSP_PDEBUGSTATUS5 (MTK_DSP_REG_BASE + 0x0214) +#define MTK_DSP_PDEBUGSTATUS6 (MTK_DSP_REG_BASE + 0x0218) +#define MTK_DSP_PDEBUGSTATUS7 (MTK_DSP_REG_BASE + 0x021c) +#define MTK_DSP_DSP2PSRAM_PRIORITY (MTK_DSP_REG_BASE + 0x0220) /* not used */ +#define MTK_DSP_AUDIO_DSP2SPM_INT (MTK_DSP_REG_BASE + 0x0224) +#define MTK_DSP_AUDIO_DSP2SPM_INT_ACK (MTK_DSP_REG_BASE + 0x0228) +#define MTK_DSP_AUDIO_DSP_DEBUG_SEL (MTK_DSP_REG_BASE + 0x022C) +#define MTK_DSP_AUDIO_DSP_EMI_BASE_ADDR (MTK_DSP_REG_BASE + 0x02E0) /* not used */ +#define MTK_DSP_AUDIO_DSP_SHARED_IRAM (MTK_DSP_REG_BASE + 0x02E4) +#define MTK_DSP_AUDIO_DSP_CKCTRL_P2P_CK_CON (MTK_DSP_REG_BASE + 0x02F0) +#define MTK_DSP_RG_SEMAPHORE00 (MTK_DSP_REG_BASE + 0x0300) +#define MTK_DSP_RG_SEMAPHORE01 (MTK_DSP_REG_BASE + 0x0304) +#define MTK_DSP_RG_SEMAPHORE02 (MTK_DSP_REG_BASE + 0x0308) +#define MTK_DSP_RG_SEMAPHORE03 (MTK_DSP_REG_BASE + 0x030C) +#define MTK_DSP_RG_SEMAPHORE04 (MTK_DSP_REG_BASE + 0x0310) +#define MTK_DSP_RG_SEMAPHORE05 (MTK_DSP_REG_BASE + 0x0314) +#define MTK_DSP_RG_SEMAPHORE06 (MTK_DSP_REG_BASE + 0x0318) +#define MTK_DSP_RG_SEMAPHORE07 (MTK_DSP_REG_BASE + 0x031C) +#define MTK_DSP_RESERVED_0 (MTK_DSP_REG_BASE + 0x03F0) +#define MTK_DSP_RESERVED_1 (MTK_DSP_REG_BASE + 0x03F4) + +/*MBOX registers*/ +#define MTK_DSP_MBOX_REG_BASE(x) (0x10816000 + (0x1000 * (x))) +#define MTK_DSP_MBOX_REG_SIZE (0x5000) +#define MTK_DSP_MBOX_IN_CMD(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x0) +#define MTK_DSP_MBOX_IN_CMD_CLR(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x04) +#define MTK_DSP_MBOX_OUT_CMD(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x1c) +#define MTK_DSP_MBOX_OUT_CMD_CLR(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x20) +#define MTK_DSP_MBOX_OUT_CMD_MSG0(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x24) +#define MTK_DSP_MBOX_OUT_CMD_MSG1(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x28) +#define MTK_DSP_MBOX_OUT_CMD_MSG2(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x2c) +#define MTK_DSP_MBOX_OUT_CMD_MSG3(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x30) +#define MTK_DSP_MBOX_OUT_CMD_MSG4(x) (MTK_DSP_MBOX_REG_BASE(x) + 0x34) + +/* Redefinition for using Special registers */ +#define MTK_TICKLESS_STATUS_REG (DSP_RESERVED_1) + +/* WDT CONFIGS */ +#define MTK_ADSP_WDT_MODE (MTK_DSP_WDT_BASE + 0x00) +#define MTK_ADSP_WDT_LENGTH (MTK_DSP_WDT_BASE + 0x04) +#define MTK_ADSP_WDT_RESTART (MTK_DSP_WDT_BASE + 0x08) +#define MTK_ADSP_WDT_STA (MTK_DSP_WDT_BASE + 0x0C) +#define MTK_ADSP_WDT_SWRST (MTK_DSP_WDT_BASE + 0x14) + +#define MTK_ADSP_WDT_SWRST_KEY 0x1209 +#define MTK_ADSP_WDT_RESTART_RELOAD 0x1971 +#define MTK_ADSP_WDT_LENGTH_KEY 0x8 + +#define MTK_WDT_LENGTH_TIMEOUT(n) ((n) << 5) + +#endif /* MT_REG_BASE_H */ diff --git a/src/platform/mt8195/include/platform/drivers/timer.h b/src/platform/mt8195/include/platform/drivers/timer.h new file mode 100644 index 000000000000..025d9f138bef --- /dev/null +++ b/src/platform/mt8195/include/platform/drivers/timer.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Author: Fengquan Chen <fengquan.chen@mediatek.com> + */ + +#ifndef __PLATFORM_DRIVERS_TIMER_H__ +#define __PLATFORM_DRIVERS_TIMER_H__ + +#include <rtos/bit.h> +#include <platform/drivers/mt_reg_base.h> + +/*-------timer:ostimer0-------*/ +enum ostimer { + OSTIMER0 = 0, + OSTIMER1, + OSTIMER2, + OSTIMER3, + NR_TMRS +}; + +#define TIMER_CON(n) (MTK_DSP_OSTIMER_BASE + 0x0 + 0x10 * (n)) +#define TIMER_RST_VAL(n) (MTK_DSP_OSTIMER_BASE + 0x4 + 0x10 * (n)) +#define TIMER_CUR_VAL(n) (MTK_DSP_OSTIMER_BASE + 0x8 + 0x10 * (n)) +#define TIMER_IRQ_ACK(n) (MTK_DSP_OSTIMER_BASE + 0xC + 0x10 * (n)) + +#define TIMER_ENABLE_BIT (0x1 << 0) +#define TIMER_IRQ_ENABLE (0x1 << 0) +#define TIMER_IRQ_STA (0x1 << 4) +#define TIMER_IRQ_CLEAR (0x1 << 5) +#define TIMER_CLKSRC_BIT (0x3 << 4) + +#define TIMER_CLK_SRC_CLK_32K 0x00 +#define TIMER_CLK_SRC_CLK_26M 0x01 +#define TIMER_CLK_SRC_BCLK 0x02 +#define TIMER_CLK_SRC_PCLK 0x03 + +#define TIMER_CLK_SRC_SHIFT 4 + +#define OSTIMER_CON (MTK_DSP_OSTIMER_BASE + 0x80) +#define OSTIMER_INIT_L (MTK_DSP_OSTIMER_BASE + 0x84) +#define OSTIMER_INIT_H (MTK_DSP_OSTIMER_BASE + 0x88) +#define OSTIMER_CUR_L (MTK_DSP_OSTIMER_BASE + 0x8C) +#define OSTIMER_CUR_H (MTK_DSP_OSTIMER_BASE + 0x90) +#define OSTIMER_TVAL (MTK_DSP_OSTIMER_BASE + 0x94) +#define OSTIMER_IRQ_ACK (MTK_DSP_OSTIMER_BASE + 0x98) + +/*-------platform_timer: 64 bit systimer-------*/ +#define CNTCR (MTK_DSP_TIMER_BASE + 0x00) +#define CNTSR (MTK_DSP_TIMER_BASE + 0x04) +#define CNTCV_L (MTK_DSP_TIMER_BASE + 0x08) +#define CNTCV_H (MTK_DSP_TIMER_BASE + 0x0c) +#define CNTWACR (MTK_DSP_TIMER_BASE + 0x10) +#define CNTRACR (MTK_DSP_TIMER_BASE + 0x14) + +#define CNT_EN_BIT BIT(0) +#define CLKSRC_BIT (BIT(8) | BIT(9)) +#define CLKSRC_13M_BIT BIT(8) +#define COMP_BIT (BIT(10) | BIT(11) | BIT(12)) +#define COMP_20_25_EN_BIT (BIT(11) | BIT(12)) + +#endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/mt8195/include/platform/lib/clk.h b/src/platform/mt8195/include/platform/lib/clk.h new file mode 100644 index 000000000000..769363f4e228 --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/clk.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <stdint.h> + +struct sof; + +#define CLK_CPU(x) (x) + +#define CPU_DEFAULT_IDX 4 + +#define CLK_DEFAULT_CPU_HZ 720000000 +#define CLK_MAX_CPU_HZ 720000000 +#define CLK_SUSPEND_CPU_HZ 26000000 + +#define NUM_CLOCKS 1 + +#define NUM_CPU_FREQ 5 + +void platform_clock_init(struct sof *sof); + +#define REG_TOPCKGEN_BASE 0x10000000 +#define REG_APMIXDSYS_BASE 0x1000C000 +#define REG_SCP_BASE 0x10700000 + +/* dsp clock */ +#define DSPPLL_CON0 (REG_APMIXDSYS_BASE + 0x7E0) +#define DSPPLL_CON1 (REG_APMIXDSYS_BASE + 0x7E4) +#define DSPPLL_CON2 (REG_APMIXDSYS_BASE + 0x7E8) +#define DSPPLL_CON3 (REG_APMIXDSYS_BASE + 0x7EC) +#define DSPPLL_CON4 (REG_APMIXDSYS_BASE + 0x7F0) + +#define PLL_BASE_EN BIT(0) +#define PLL_PWR_ON BIT(0) +#define PLL_ISO_EN BIT(1) +#define PLL_EN BIT(9) + +#define CLK_MODE (REG_TOPCKGEN_BASE + 0x0) +#define CLK_CFG_UPDATE0 (REG_TOPCKGEN_BASE + 0x4) +#define CLK_CFG_UPDATE1 (REG_TOPCKGEN_BASE + 0x8) +#define CLK_CFG_UPDATE2 (REG_TOPCKGEN_BASE + 0xC) +#define CLK_CFG_UPDATE3 (REG_TOPCKGEN_BASE + 0x10) + +#define CLK_CFG_22 (REG_TOPCKGEN_BASE + 0x128) +#define CLK_CFG_22_SET (REG_TOPCKGEN_BASE + 0x12C) +#define CLK_CFG_22_CLR (REG_TOPCKGEN_BASE + 0x130) + +#define CLK_CFG_28 (REG_TOPCKGEN_BASE + 0x170) +#define CLK_CFG_28_SET (REG_TOPCKGEN_BASE + 0x174) +#define CLK_CFG_28_CLR (REG_TOPCKGEN_BASE + 0x178) + +/* CLK_CFG_UPDATE2 */ +#define CLK_UPDATE_ADSP_CK 24 + +/* CLK_CFG_UPDATE3 */ +#define CLK_UPDATE_AUDIO_LOCAL_BUS_CK 18 + +/* CLK_CFG_22[3:0] hf_fadsp_ck_sel clksrc. */ +#define CLK_ADSP_SEL_26M 0 +#define CLK_ADSP_SEL_26M_D_2 1 +#define CLK_ADSP_SEL_MAINPLL_D_6 2 +#define CLK_ADSP_SEL_MAINPLL_D_5_D_2 3 +#define CLK_ADSP_SEL_MAINPLL_D_4_D_4 4 +#define CLK_ADSP_SEL_UNIVPLL_D_4 5 +#define CLK_ADSP_SEL_UNIVPLL_D_6 6 +#define CLK_ADSP_SEL_ULPOSC 7 +#define CLK_ADSP_SEL_ADSPPLL 8 +#define CLK_ADSP_SEL_ADSPPLL_D_2 9 +#define CLK_ADSP_SEL_ADSPPLL_D_4 10 +#define CLK_ADSP_SEL_ADSPPLL_D_8 11 + +/* CLK_CFG_28[19:16] hf_faudio_local_bus_ck_sel clksrc. */ +#define CLK_AUDIO_LOCAL_BUS_SEL_26M 0 +#define CLK_AUDIO_LOCAL_BUS_SEL_26M_D_2 1 +#define CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_4_D_4 2 +#define CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_7_D_2 3 +#define CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_4_D_2 4 +#define CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_5_D_2 5 +#define CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_6_D_2 6 +#define CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_7 7 +#define CLK_AUDIO_LOCAL_BUS_SEL_UNIVPLL_D_6 8 +#define CLK_AUDIO_LOCAL_BUS_SEL_ULPOSC 9 +#define CLK_AUDIO_LOCAL_BUS_SEL_ULPOSC_D_4 10 +#define CLK_AUDIO_LOCAL_BUS_SEL_ULPOSC_D_2 11 + +#define AUDIODSP_CK_CG (REG_SCP_BASE + 0x20180) +#define RG_AUDIODSP_SW_CG 0 + +enum mux_id_t { + MUX_CLK_ADSP_SEL = 0, + MUX_CLK_AUDIO_LOCAL_BUS_SEL, + HIFI4DSP_MUX_NUM, +}; + +enum DSP_HW_DSP_CLK { + DSP_CLK_13M = 0, + DSP_CLK_26M, + DSP_CLK_PLL_370M, + DSP_CLK_PLL_540M, + DSP_CLK_PLL_720M, +}; +#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/mt8195/include/platform/lib/cpu.h b/src/platform/mt8195/include/platform/lib/cpu.h new file mode 100644 index 000000000000..e391c32a07b0 --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/cpu.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/** \brief Id of primary DSP core */ +#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/mt8195/include/platform/lib/dai.h b/src/platform/mt8195/include/platform/lib/dai.h new file mode 100644 index 000000000000..81dc98863314 --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/dai.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#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/mt8195/include/platform/lib/dma.h b/src/platform/mt8195/include/platform/lib/dma.h new file mode 100644 index 000000000000..06c8ea9ef3bd --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/dma.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 2 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 32 + +#define DMA_ID_AFE_MEMIF 0 +#define DMA_ID_HOST 1 + +#define dma_chan_irq(dma, chan) dma_irq(dma) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#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/mt8195/include/platform/lib/mailbox.h b/src/platform/mt8195/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..8de30a1cb422 --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/mailbox.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/memory.h> +#include <stddef.h> +#include <stdint.h> + +/* + * The Window Region on MT8195 SRAM is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer | SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + *ptr = src; +} + +#define ADSP_IPI_OP_REQ 0x1 +#define ADSP_IPI_OP_RSP 0x2 +void trigger_irq_to_host_req(void); +void trigger_irq_to_host_rsp(void); + +#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/mt8195/include/platform/lib/memory.h b/src/platform/mt8195/include/platform/lib/memory.h new file mode 100644 index 000000000000..42ee7f7990ab --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/memory.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> +#include <xtensa/config/core-isa.h> + +#define BOOT_WITH_DRAM /*Use DRAM as SRAM1 for heap related*/ +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN sizeof(void *) + +/* BOOT_WITH_DRAM ONLY */ +/* physical DSP addresses */ +#define DRAM_BASE 0x60000000 +#define DRAM_AUDIO_SHARED_SIZE 0x280000 +#define DRAM_SIZE 0x1000000 /*DRAM Size : 16M , need to sync with Host side*/ + +#define SRAM_TOTAL_SIZE 0x40000 /*256KB DSP SRAM*/ +#define VECTOR_SIZE 0x628 + +#define SRAM0_BASE DRAM_BASE +#define SRAM0_SIZE (DRAM_SIZE >> 1) +#define SRAM1_BASE (DRAM_BASE + SRAM0_SIZE) +#define SRAM1_SIZE \ + (DRAM_SIZE - SRAM0_SIZE - DRAM_AUDIO_SHARED_SIZE - UUID_ENTRY_ELF_SIZE - \ + LOG_ENTRY_ELF_SIZE - EXT_MANIFEST_ELF_SIZE) + +#define DMA_SIZE 0x100000 + +#define UUID_ENTRY_ELF_SIZE 0x6000 +#define LOG_ENTRY_ELF_SIZE 0x200000 +#define EXT_MANIFEST_ELF_SIZE 0x100000 + +#define UUID_ENTRY_ELF_BASE (SRAM1_BASE + SRAM1_SIZE) +#define LOG_ENTRY_ELF_BASE (UUID_ENTRY_ELF_BASE + UUID_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) + +/* + * The Heap and Stack on MT8195 are organised like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM1_BASE | RO Data | SOF_DATA_SIZE | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + */ + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE SRAM1_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +/*4K + 4K +2K + 2K + 4K + 4K = 20KB*/ +#define SOF_MAILBOX_SIZE \ + (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE + \ + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 32 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 32 +#define HEAP_RT_COUNT1024 4 +#define HEAP_RT_COUNT2048 2 +#define HEAP_RT_COUNT4096 2 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 128 +#define HEAP_SYS_RT_COUNT512 16 +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ + +#define HEAP_SYSTEM_BASE (SRAM1_BASE + SOF_MAILBOX_SIZE) +#define HEAP_SYSTEM_SIZE 0x6000 + +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE + +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +/*24KB*/ +#define HEAP_SYS_RUNTIME_SIZE \ + (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +/*48*(16 +32) + 32*(64 128+256) + 4*(512+1024) + 1*2048 = 24832 = 24.25KB*/ +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + HEAP_RT_COUNT512 * 512 + \ + HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + HEAP_RT_COUNT4096 * 4096) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE \ + (SRAM1_SIZE - SOF_MAILBOX_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE - \ + HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Stack configuration */ +#define SOF_STACK_SIZE 0x8000 +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE /*4KB*/ +#define SOF_STACK_BASE (SRAM1_BASE + SRAM1_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x4 +#define SOF_MEM_VECT_TEXT_SIZE 0x1c +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 +#define SOF_MEM_RESET_LIT_SIZE 0x120 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE + +/** \brief EDF task's default stack size in bytes. */ +#ifdef CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING +#define PLATFORM_TASK_DEFAULT_STACK_SIZE (12 * 1024) +#else +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 +#endif + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +struct sof; + +/** + * \brief Data shared between different cores. + * Does nothing, since mt8195 doesn't support SMP. + */ +#define SHARED_DATA + +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +/** + * \brief Function for keeping shared data synchronized. + * It's used after usage of data shared by different cores. + * Such data is either statically marked with SHARED_DATA + * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. + * Does nothing, since mt8195 doesn't support SMP. + */ + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#endif + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#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/mt8195/include/platform/lib/pm_runtime.h b/src/platform/mt8195/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..ee7f32e7a442 --- /dev/null +++ b/src/platform/mt8195/include/platform/lib/pm_runtime.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +static inline 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_... + */ +static inline 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_... + */ +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/mt8195/include/platform/mt8195-afe-common.h b/src/platform/mt8195/include/platform/mt8195-afe-common.h new file mode 100644 index 000000000000..ffd699dce523 --- /dev/null +++ b/src/platform/mt8195/include/platform/mt8195-afe-common.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifndef _MT_8195_AFE_COMMON_H_ +#define _MT_8195_AFE_COMMON_H_ + +/* AFE: the abbreviation for Audio Front End */ + +enum { + MT8195_MEMIF_START, + MT8195_MEMIF_DL_START = MT8195_MEMIF_START, + MT8195_MEMIF_DL2 = MT8195_MEMIF_DL_START, + MT8195_MEMIF_DL3, + MT8195_MEMIF_DL_END, + MT8195_MEMIF_UL_START = MT8195_MEMIF_DL_END, + MT8195_MEMIF_UL4 = MT8195_MEMIF_UL_START, + MT8195_MEMIF_UL5, + MT8195_MEMIF_UL_END, + MT8195_MEMIF_END = MT8195_MEMIF_UL_END, + MT8195_MEMIF_DL_NUM = (MT8195_MEMIF_DL_END - MT8195_MEMIF_DL_START), + MT8195_MEMIF_UL_NUM = (MT8195_MEMIF_UL_END - MT8195_MEMIF_UL_START), + MT8195_MEMIF_NUM = (MT8195_MEMIF_END - MT8195_MEMIF_START), +}; + +enum { + MT8195_IRQ_0, + MT8195_IRQ_1, + MT8195_IRQ_2, + MT8195_IRQ_3, + MT8195_IRQ_4, + MT8195_IRQ_5, + MT8195_IRQ_6, + MT8195_IRQ_7, + MT8195_IRQ_8, + MT8195_IRQ_9, + MT8195_IRQ_10, + MT8195_IRQ_11, + MT8195_IRQ_12, + MT8195_IRQ_13, + MT8195_IRQ_14, + MT8195_IRQ_15, + MT8195_IRQ_16, + MT8195_IRQ_17, + MT8195_IRQ_18, + MT8195_IRQ_19, + MT8195_IRQ_20, + MT8195_IRQ_21, + MT8195_IRQ_22, + MT8195_IRQ_23, + MT8195_IRQ_24, + MT8195_IRQ_25, + MT8195_IRQ_26, + MT8195_IRQ_31, /* used only for TDM */ + MT8195_IRQ_NUM, +}; + +enum { + MT8195_AFE_IO_ETDM2_OUT, + MT8195_AFE_IO_ETDM1_OUT, + MT8195_AFE_IO_UL_SRC1, + MT8195_AFE_IO_ETDM2_IN, + MT8195_DAI_NUM, +}; + +#endif diff --git a/src/platform/mt8195/include/platform/mt8195-afe-regs.h b/src/platform/mt8195/include/platform/mt8195-afe-regs.h new file mode 100644 index 000000000000..57d0d4637558 --- /dev/null +++ b/src/platform/mt8195/include/platform/mt8195-afe-regs.h @@ -0,0 +1,2790 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifndef _MT8195_REG_H_ +#define _MT8195_REG_H_ + +#define AFE_SRAM_BASE 0x10880000 +#define AFE_SRAM_SIZE 0x10000 +#define AFE_BASE_ADDR 0x10890000 + +#define AUDIO_TOP_CON0 0x0000 +#define AUDIO_TOP_CON1 0x0004 +#define AUDIO_TOP_CON2 0x0008 +#define AUDIO_TOP_CON3 0x000c +#define AUDIO_TOP_CON4 0x0010 +#define AUDIO_TOP_CON5 0x0014 +#define AUDIO_TOP_CON6 0x0018 +#define AFE_MAS_HADDR_MSB 0x0020 +#define PWR1_ASM_CON1 0x0108 +#define ASYS_IRQ_CONFIG 0x0110 +#define ASYS_IRQ1_CON 0x0114 +#define ASYS_IRQ2_CON 0x0118 +#define ASYS_IRQ3_CON 0x011c +#define ASYS_IRQ4_CON 0x0120 +#define ASYS_IRQ5_CON 0x0124 +#define ASYS_IRQ6_CON 0x0128 +#define ASYS_IRQ7_CON 0x012c +#define ASYS_IRQ8_CON 0x0130 +#define ASYS_IRQ9_CON 0x0134 +#define ASYS_IRQ10_CON 0x0138 +#define ASYS_IRQ11_CON 0x013c +#define ASYS_IRQ12_CON 0x0140 +#define ASYS_IRQ13_CON 0x0144 +#define ASYS_IRQ14_CON 0x0148 +#define ASYS_IRQ15_CON 0x014c +#define ASYS_IRQ16_CON 0x0150 +#define ASYS_IRQ_CLR 0x0154 +#define ASYS_IRQ_STATUS 0x0158 +#define ASYS_IRQ_MON1 0x015c +#define ASYS_IRQ_MON2 0x0160 +#define AFE_IRQ1_CON 0x0164 +#define AFE_IRQ2_CON 0x0168 +#define AFE_IRQ3_CON 0x016c +#define AFE_IRQ_MCU_CLR 0x0170 +#define AFE_IRQ_STATUS 0x0174 +#define AFE_IRQ_MASK 0x0178 +#define ASYS_IRQ_MASK 0x017c +#define AFE_IRQ3_CON_MON 0x01b0 +#define AFE_IRQ_MCU_MON2 0x01b4 +#define AFE_IRQ8_CON 0x01b8 +#define AFE_IRQ9_CON 0x01bc +#define AFE_IRQ10_CON 0x01c0 +#define AFE_IRQ9_CON_MON 0x01c4 +#define ADSP_IRQ_MASK 0x01c8 +#define ADSP_IRQ_STATUS 0x01cc +#define AFE_SINEGEN_CON0 0x01f0 +#define AFE_SINEGEN_CON1 0x01f4 +#define AFE_SINEGEN_CON2 0x01f8 +#define AFE_SINEGEN_CON3 0x01fc +#define AFE_SPDIF_OUT_CON0 0x0380 +#define AFE_TDMOUT_CONN0 0x0390 +#define PWR1_ASM_CON2 0x03b0 +#define PWR1_ASM_CON3 0x03b4 +#define PWR1_ASM_CON4 0x03b8 +#define AFE_APLL_TUNER_CFG 0x03f8 +#define AFE_APLL_TUNER_CFG1 0x03fc +#define AUDIO_TOP_STA0 0x0400 +#define AUDIO_TOP_STA1 0x0404 +#define AFE_GAIN1_CON0 0x0410 +#define AFE_GAIN1_CON1 0x0414 +#define AFE_GAIN1_CON2 0x0418 +#define AFE_GAIN1_CON3 0x041c +#define AFE_GAIN1_CUR 0x0424 +#define AFE_GAIN2_CON0 0x0428 +#define AFE_GAIN2_CON1 0x042c +#define AFE_GAIN2_CON2 0x0430 +#define AFE_GAIN2_CON3 0x0434 +#define AFE_GAIN2_CUR 0x043c +#define AFE_IEC_CFG 0x0480 +#define AFE_IEC_NSNUM 0x0484 +#define AFE_IEC_BURST_INFO 0x0488 +#define AFE_IEC_BURST_LEN 0x048c +#define AFE_IEC_NSADR 0x0490 +#define AFE_IEC_CHL_STAT0 0x04a0 +#define AFE_IEC_CHL_STAT1 0x04a4 +#define AFE_IEC_CHR_STAT0 0x04a8 +#define AFE_IEC_CHR_STAT1 0x04ac +#define AFE_SPDIFIN_CFG0 0x0500 +#define AFE_SPDIFIN_CFG1 0x0504 +#define AFE_SPDIFIN_CHSTS1 0x0508 +#define AFE_SPDIFIN_CHSTS2 0x050c +#define AFE_SPDIFIN_CHSTS3 0x0510 +#define AFE_SPDIFIN_CHSTS4 0x0514 +#define AFE_SPDIFIN_CHSTS5 0x0518 +#define AFE_SPDIFIN_CHSTS6 0x051c +#define AFE_SPDIFIN_DEBUG1 0x0520 +#define AFE_SPDIFIN_DEBUG2 0x0524 +#define AFE_SPDIFIN_DEBUG3 0x0528 +#define AFE_SPDIFIN_DEBUG4 0x052c +#define AFE_SPDIFIN_EC 0x0530 +#define AFE_SPDIFIN_CKLOCK_CFG 0x0534 +#define AFE_SPDIFIN_BR 0x053c +#define AFE_SPDIFIN_BR_DBG1 0x0540 +#define AFE_SPDIFIN_CKFBDIV 0x0544 +#define AFE_SPDIFIN_INT_EXT 0x0548 +#define AFE_SPDIFIN_INT_EXT2 0x054c +#define SPDIFIN_FREQ_INFO 0x0550 +#define SPDIFIN_FREQ_INFO_2 0x0554 +#define SPDIFIN_FREQ_INFO_3 0x0558 +#define SPDIFIN_FREQ_STATUS 0x055c +#define SPDIFIN_USERCODE1 0x0560 +#define SPDIFIN_USERCODE2 0x0564 +#define SPDIFIN_USERCODE3 0x0568 +#define SPDIFIN_USERCODE4 0x056c +#define SPDIFIN_USERCODE5 0x0570 +#define SPDIFIN_USERCODE6 0x0574 +#define SPDIFIN_USERCODE7 0x0578 +#define SPDIFIN_USERCODE8 0x057c +#define SPDIFIN_USERCODE9 0x0580 +#define SPDIFIN_USERCODE10 0x0584 +#define SPDIFIN_USERCODE11 0x0588 +#define SPDIFIN_USERCODE12 0x058c +#define AFE_SPDIFIN_APLL_TUNER_CFG 0x0594 +#define AFE_SPDIFIN_APLL_TUNER_CFG1 0x0598 +#define ASYS_TOP_CON 0x0600 +#define AFE_LINEIN_APLL_TUNER_CFG 0x0610 +#define AFE_LINEIN_APLL_TUNER_MON 0x0614 +#define AFE_EARC_APLL_TUNER_CFG 0x0618 +#define AFE_EARC_APLL_TUNER_MON 0x061c +#define PWR2_TOP_CON0 0x0634 +#define PWR2_TOP_CON1 0x0638 +#define PCM_INTF_CON1 0x063c +#define PCM_INTF_CON2 0x0640 +#define AFE_CM0_CON 0x0660 +#define AFE_CM1_CON 0x0664 +#define AFE_CM2_CON 0x0668 +#define AFE_CM0_MON 0x0670 +#define AFE_CM1_MON 0x0674 +#define AFE_CM2_MON 0x0678 +#define AFE_MPHONE_MULTI_CON0 0x06a4 +#define AFE_MPHONE_MULTI_CON1 0x06a8 +#define AFE_MPHONE_MULTI_CON2 0x06ac +#define AFE_MPHONE_MULTI_MON 0x06b0 +#define AFE_MPHONE_MULTI_DET_REG_CON0 0x06b4 +#define AFE_MPHONE_MULTI_DET_REG_CON1 0x06b8 +#define AFE_MPHONE_MULTI_DET_REG_CON2 0x06bc +#define AFE_MPHONE_MULTI_DET_REG_CON3 0x06c0 +#define AFE_MPHONE_MULTI_DET_MON0 0x06c4 +#define AFE_MPHONE_MULTI_DET_MON1 0x06c8 +#define AFE_MPHONE_MULTI_DET_MON2 0x06d0 +#define AFE_MPHONE_MULTI2_CON0 0x06d4 +#define AFE_MPHONE_MULTI2_CON1 0x06d8 +#define AFE_MPHONE_MULTI2_CON2 0x06dc +#define AFE_MPHONE_MULTI2_MON 0x06e0 +#define AFE_MPHONE_MULTI2_DET_REG_CON0 0x06e4 +#define AFE_MPHONE_MULTI2_DET_REG_CON1 0x06e8 +#define AFE_MPHONE_MULTI2_DET_REG_CON2 0x06ec +#define AFE_MPHONE_MULTI2_DET_REG_CON3 0x06f0 +#define AFE_MPHONE_MULTI2_DET_MON0 0x06f4 +#define AFE_MPHONE_MULTI2_DET_MON1 0x06f8 +#define AFE_MPHONE_MULTI2_DET_MON2 0x06fc +#define AFE_ADDA_IIR_COEF_02_01 0x0700 +#define AFE_ADDA_IIR_COEF_04_03 0x0704 +#define AFE_ADDA_IIR_COEF_06_05 0x0708 +#define AFE_ADDA_IIR_COEF_08_07 0x070c +#define AFE_ADDA_IIR_COEF_10_09 0x0710 +#define AFE_ADDA_ULCF_CFG_02_01 0x0714 +#define AFE_ADDA_ULCF_CFG_04_03 0x0718 +#define AFE_ADDA_ULCF_CFG_06_05 0x071c +#define AFE_ADDA_ULCF_CFG_08_07 0x0720 +#define AFE_ADDA_ULCF_CFG_10_09 0x0724 +#define AFE_ADDA_ULCF_CFG_12_11 0x0728 +#define AFE_ADDA_ULCF_CFG_14_13 0x072c +#define AFE_ADDA_ULCF_CFG_16_15 0x0730 +#define AFE_ADDA_ULCF_CFG_18_17 0x0734 +#define AFE_ADDA_ULCF_CFG_20_19 0x0738 +#define AFE_ADDA_ULCF_CFG_22_21 0x073c +#define AFE_ADDA_ULCF_CFG_24_23 0x0740 +#define AFE_ADDA_ULCF_CFG_26_25 0x0744 +#define AFE_ADDA_ULCF_CFG_28_27 0x0748 +#define AFE_ADDA_ULCF_CFG_30_29 0x074c +#define AFE_ADDA6_IIR_COEF_02_01 0x0750 +#define AFE_ADDA6_IIR_COEF_04_03 0x0754 +#define AFE_ADDA6_IIR_COEF_06_05 0x0758 +#define AFE_ADDA6_IIR_COEF_08_07 0x075c +#define AFE_ADDA6_IIR_COEF_10_09 0x0760 +#define AFE_ADDA6_ULCF_CFG_02_01 0x0764 +#define AFE_ADDA6_ULCF_CFG_04_03 0x0768 +#define AFE_ADDA6_ULCF_CFG_06_05 0x076c +#define AFE_ADDA6_ULCF_CFG_08_07 0x0770 +#define AFE_ADDA6_ULCF_CFG_10_09 0x0774 +#define AFE_ADDA6_ULCF_CFG_12_11 0x0778 +#define AFE_ADDA6_ULCF_CFG_14_13 0x077c +#define AFE_ADDA6_ULCF_CFG_16_15 0x0780 +#define AFE_ADDA6_ULCF_CFG_18_17 0x0784 +#define AFE_ADDA6_ULCF_CFG_20_19 0x0788 +#define AFE_ADDA6_ULCF_CFG_22_21 0x078c +#define AFE_ADDA6_ULCF_CFG_24_23 0x0790 +#define AFE_ADDA6_ULCF_CFG_26_25 0x0794 +#define AFE_ADDA6_ULCF_CFG_28_27 0x0798 +#define AFE_ADDA6_ULCF_CFG_30_29 0x079c +#define AFE_ADDA_MTKAIF_CFG0 0x07a0 +#define AFE_ADDA_MTKAIF_SYNCWORD_CFG 0x07a8 +#define AFE_ADDA_MTKAIF_RX_CFG0 0x07b4 +#define AFE_ADDA_MTKAIF_RX_CFG1 0x07b8 +#define AFE_ADDA_MTKAIF_RX_CFG2 0x07bc +#define AFE_ADDA_MTKAIF_MON0 0x07c8 +#define AFE_ADDA_MTKAIF_MON1 0x07cc +#define AFE_AUD_PAD_TOP 0x07d4 +#define AFE_ADDA6_MTKAIF_MON0 0x07d8 +#define AFE_ADDA6_MTKAIF_MON1 0x07dc +#define AFE_ADDA6_MTKAIF_CFG0 0x07e0 +#define AFE_ADDA6_MTKAIF_RX_CFG0 0x07e4 +#define AFE_ADDA6_MTKAIF_RX_CFG1 0x07e8 +#define AFE_ADDA6_MTKAIF_RX_CFG2 0x07ec +#define AFE_ADDA6_TOP_CON0 0x07f0 +#define AFE_ADDA6_UL_SRC_CON0 0x07f4 +#define AFE_ADDA6_UL_SRC_CON1 0x07f8 +#define AFE_ADDA6_SRC_DEBUG 0x0800 +#define AFE_ADDA6_SRC_DEBUG_MON0 0x0804 +#define AFE_ADDA6_UL_SRC_MON0 0x0818 +#define AFE_ADDA6_UL_SRC_MON1 0x081c +#define AFE_CONN0_5 0x0830 +#define AFE_CONN1_5 0x0834 +#define AFE_CONN2_5 0x0838 +#define AFE_CONN3_5 0x083c +#define AFE_CONN4_5 0x0840 +#define AFE_CONN5_5 0x0844 +#define AFE_CONN6_5 0x0848 +#define AFE_CONN7_5 0x084c +#define AFE_CONN8_5 0x0850 +#define AFE_CONN9_5 0x0854 +#define AFE_CONN10_5 0x0858 +#define AFE_CONN11_5 0x085c +#define AFE_CONN12_5 0x0860 +#define AFE_CONN13_5 0x0864 +#define AFE_CONN14_5 0x0868 +#define AFE_CONN15_5 0x086c +#define AFE_CONN16_5 0x0870 +#define AFE_CONN17_5 0x0874 +#define AFE_CONN18_5 0x0878 +#define AFE_CONN19_5 0x087c +#define AFE_CONN20_5 0x0880 +#define AFE_CONN21_5 0x0884 +#define AFE_CONN22_5 0x0888 +#define AFE_CONN23_5 0x088c +#define AFE_CONN24_5 0x0890 +#define AFE_CONN25_5 0x0894 +#define AFE_CONN26_5 0x0898 +#define AFE_CONN27_5 0x089c +#define AFE_CONN28_5 0x08a0 +#define AFE_CONN29_5 0x08a4 +#define AFE_CONN30_5 0x08a8 +#define AFE_CONN31_5 0x08ac +#define AFE_CONN32_5 0x08b0 +#define AFE_CONN33_5 0x08b4 +#define AFE_CONN34_5 0x08b8 +#define AFE_CONN35_5 0x08bc +#define AFE_CONN36_5 0x08c0 +#define AFE_CONN37_5 0x08c4 +#define AFE_CONN38_5 0x08c8 +#define AFE_CONN39_5 0x08cc +#define AFE_CONN40_5 0x08d0 +#define AFE_CONN41_5 0x08d4 +#define AFE_CONN42_5 0x08d8 +#define AFE_CONN43_5 0x08dc +#define AFE_CONN44_5 0x08e0 +#define AFE_CONN45_5 0x08e4 +#define AFE_CONN46_5 0x08e8 +#define AFE_CONN47_5 0x08ec +#define AFE_CONN48_5 0x08f0 +#define AFE_CONN49_5 0x08f4 +#define AFE_CONN50_5 0x08f8 +#define AFE_CONN51_5 0x08fc +#define AFE_CONN52_5 0x0900 +#define AFE_CONN53_5 0x0904 +#define AFE_CONN54_5 0x0908 +#define AFE_CONN55_5 0x090c +#define AFE_CONN56_5 0x0910 +#define AFE_CONN57_5 0x0914 +#define AFE_CONN58_5 0x0918 +#define AFE_CONN59_5 0x091c +#define AFE_CONN60_5 0x0920 +#define AFE_CONN61_5 0x0924 +#define AFE_CONN62_5 0x0928 +#define AFE_CONN63_5 0x092c +#define AFE_CONN64_5 0x0930 +#define AFE_CONN65_5 0x0934 +#define AFE_CONN66_5 0x0938 +#define AFE_CONN67_5 0x093c +#define AFE_CONN68_5 0x0940 +#define AFE_CONN69_5 0x0944 +#define AFE_CONN70_5 0x0948 +#define AFE_CONN71_5 0x094c +#define AFE_CONN72_5 0x0950 +#define AFE_CONN73_5 0x0954 +#define AFE_CONN74_5 0x0958 +#define AFE_CONN75_5 0x095c +#define AFE_CONN76_5 0x0960 +#define AFE_CONN77_5 0x0964 +#define AFE_CONN78_5 0x0968 +#define AFE_CONN79_5 0x096c +#define AFE_CONN80_5 0x0970 +#define AFE_CONN81_5 0x0974 +#define AFE_CONN82_5 0x0978 +#define AFE_CONN83_5 0x097c +#define AFE_CONN84_5 0x0980 +#define AFE_CONN85_5 0x0984 +#define AFE_CONN86_5 0x0988 +#define AFE_CONN87_5 0x098c +#define AFE_CONN88_5 0x0990 +#define AFE_CONN89_5 0x0994 +#define AFE_CONN90_5 0x0998 +#define AFE_CONN91_5 0x099c +#define AFE_CONN92_5 0x09a0 +#define AFE_CONN93_5 0x09a4 +#define AFE_CONN94_5 0x09a8 +#define AFE_CONN95_5 0x09ac +#define AFE_CONN96_5 0x09b0 +#define AFE_CONN97_5 0x09b4 +#define AFE_CONN98_5 0x09b8 +#define AFE_CONN99_5 0x09bc +#define AFE_CONN100_5 0x09c0 +#define AFE_CONN101_5 0x09c4 +#define AFE_CONN102_5 0x09c8 +#define AFE_CONN103_5 0x09cc +#define AFE_CONN104_5 0x09d0 +#define AFE_CONN105_5 0x09d4 +#define AFE_CONN106_5 0x09d8 +#define AFE_CONN107_5 0x09dc +#define AFE_CONN108_5 0x09e0 +#define AFE_CONN109_5 0x09e4 +#define AFE_CONN110_5 0x09e8 +#define AFE_CONN111_5 0x09ec +#define AFE_CONN112_5 0x09f0 +#define AFE_CONN113_5 0x09f4 +#define AFE_CONN114_5 0x09f8 +#define AFE_CONN115_5 0x09fc +#define AFE_CONN116_5 0x0a00 +#define AFE_CONN117_5 0x0a04 +#define AFE_CONN118_5 0x0a08 +#define AFE_CONN119_5 0x0a0c +#define AFE_CONN120_5 0x0a10 +#define AFE_CONN121_5 0x0a14 +#define AFE_CONN122_5 0x0a18 +#define AFE_CONN123_5 0x0a1c +#define AFE_CONN124_5 0x0a20 +#define AFE_CONN125_5 0x0a24 +#define AFE_CONN126_5 0x0a28 +#define AFE_CONN127_5 0x0a2c +#define AFE_CONN128_5 0x0a30 +#define AFE_CONN129_5 0x0a34 +#define AFE_CONN130_5 0x0a38 +#define AFE_CONN131_5 0x0a3c +#define AFE_CONN132_5 0x0a40 +#define AFE_CONN133_5 0x0a44 +#define AFE_CONN134_5 0x0a48 +#define AFE_CONN135_5 0x0a4c +#define AFE_CONN136_5 0x0a50 +#define AFE_CONN137_5 0x0a54 +#define AFE_CONN138_5 0x0a58 +#define AFE_CONN139_5 0x0a5c +#define AFE_CONN_RS_5 0x0a60 +#define AFE_CONN_DI_5 0x0a64 +#define AFE_CONN_16BIT_5 0x0a68 +#define AFE_CONN_24BIT_5 0x0a6c +#define AFE_ASRC11_NEW_CON0 0x0d80 +#define AFE_ASRC11_NEW_CON1 0x0d84 +#define AFE_ASRC11_NEW_CON2 0x0d88 +#define AFE_ASRC11_NEW_CON3 0x0d8c +#define AFE_ASRC11_NEW_CON4 0x0d90 +#define AFE_ASRC11_NEW_CON5 0x0d94 +#define AFE_ASRC11_NEW_CON6 0x0d98 +#define AFE_ASRC11_NEW_CON7 0x0d9c +#define AFE_ASRC11_NEW_CON8 0x0da0 +#define AFE_ASRC11_NEW_CON9 0x0da4 +#define AFE_ASRC11_NEW_CON10 0x0da8 +#define AFE_ASRC11_NEW_CON11 0x0dac +#define AFE_ASRC11_NEW_CON13 0x0db4 +#define AFE_ASRC11_NEW_CON14 0x0db8 +#define AFE_ASRC12_NEW_CON0 0x0dc0 +#define AFE_ASRC12_NEW_CON1 0x0dc4 +#define AFE_ASRC12_NEW_CON2 0x0dc8 +#define AFE_ASRC12_NEW_CON3 0x0dcc +#define AFE_ASRC12_NEW_CON4 0x0dd0 +#define AFE_ASRC12_NEW_CON5 0x0dd4 +#define AFE_ASRC12_NEW_CON6 0x0dd8 +#define AFE_ASRC12_NEW_CON7 0x0ddc +#define AFE_ASRC12_NEW_CON8 0x0de0 +#define AFE_ASRC12_NEW_CON9 0x0de4 +#define AFE_ASRC12_NEW_CON10 0x0de8 +#define AFE_ASRC12_NEW_CON11 0x0dec +#define AFE_ASRC12_NEW_CON13 0x0df4 +#define AFE_ASRC12_NEW_CON14 0x0df8 +#define AFE_LRCK_CNT 0x1018 +#define AFE_DAC_CON0 0x1200 +#define AFE_DAC_CON1 0x1204 +#define AFE_DAC_CON2 0x1208 +#define AFE_DAC_MON0 0x1218 +#define AFE_DL2_BASE 0x1250 +#define AFE_DL2_CUR 0x1254 +#define AFE_DL2_END 0x1258 +#define AFE_DL2_CON0 0x125c +#define AFE_DL3_BASE 0x1260 +#define AFE_DL3_CUR 0x1264 +#define AFE_DL3_END 0x1268 +#define AFE_DL3_CON0 0x126c +#define AFE_DL6_BASE 0x1290 +#define AFE_DL6_CUR 0x1294 +#define AFE_DL6_END 0x1298 +#define AFE_DL6_CON0 0x129c +#define AFE_DL7_BASE 0x12a0 +#define AFE_DL7_CUR 0x12a4 +#define AFE_DL7_END 0x12a8 +#define AFE_DL7_CON0 0x12ac +#define AFE_DL8_BASE 0x12b0 +#define AFE_DL8_CUR 0x12b4 +#define AFE_DL8_END 0x12b8 +#define AFE_DL8_CON0 0x12bc +#define AFE_DL10_BASE 0x12d0 +#define AFE_DL10_CUR 0x12d4 +#define AFE_DL10_END 0x12d8 +#define AFE_DL10_CON0 0x12dc +#define AFE_DL11_BASE 0x12e0 +#define AFE_DL11_CUR 0x12e4 +#define AFE_DL11_END 0x12e8 +#define AFE_DL11_CON0 0x12ec +#define AFE_UL1_BASE 0x1300 +#define AFE_UL1_CUR 0x1304 +#define AFE_UL1_END 0x1308 +#define AFE_UL1_CON0 0x130c +#define AFE_UL2_BASE 0x1310 +#define AFE_UL2_CUR 0x1314 +#define AFE_UL2_END 0x1318 +#define AFE_UL2_CON0 0x131c +#define AFE_UL3_BASE 0x1320 +#define AFE_UL3_CUR 0x1324 +#define AFE_UL3_END 0x1328 +#define AFE_UL3_CON0 0x132c +#define AFE_UL4_BASE 0x1330 +#define AFE_UL4_CUR 0x1334 +#define AFE_UL4_END 0x1338 +#define AFE_UL4_CON0 0x133c +#define AFE_UL5_BASE 0x1340 +#define AFE_UL5_CUR 0x1344 +#define AFE_UL5_END 0x1348 +#define AFE_UL5_CON0 0x134c +#define AFE_UL6_BASE 0x1350 +#define AFE_UL6_CUR 0x1354 +#define AFE_UL6_END 0x1358 +#define AFE_UL6_CON0 0x135c +#define AFE_UL8_BASE 0x1370 +#define AFE_UL8_CUR 0x1374 +#define AFE_UL8_END 0x1378 +#define AFE_UL8_CON0 0x137c +#define AFE_UL9_BASE 0x1380 +#define AFE_UL9_CUR 0x1384 +#define AFE_UL9_END 0x1388 +#define AFE_UL9_CON0 0x138c +#define AFE_UL10_BASE 0x13d0 +#define AFE_UL10_CUR 0x13d4 +#define AFE_UL10_END 0x13d8 +#define AFE_UL10_CON0 0x13dc +#define AFE_DL8_CHK_SUM1 0x1400 +#define AFE_DL8_CHK_SUM2 0x1404 +#define AFE_DL8_CHK_SUM3 0x1408 +#define AFE_DL8_CHK_SUM4 0x140c +#define AFE_DL8_CHK_SUM5 0x1410 +#define AFE_DL8_CHK_SUM6 0x1414 +#define AFE_DL10_CHK_SUM1 0x1418 +#define AFE_DL10_CHK_SUM2 0x141c +#define AFE_DL10_CHK_SUM3 0x1420 +#define AFE_DL10_CHK_SUM4 0x1424 +#define AFE_DL10_CHK_SUM5 0x1428 +#define AFE_DL10_CHK_SUM6 0x142c +#define AFE_DL11_CHK_SUM1 0x1430 +#define AFE_DL11_CHK_SUM2 0x1434 +#define AFE_DL11_CHK_SUM3 0x1438 +#define AFE_DL11_CHK_SUM4 0x143c +#define AFE_DL11_CHK_SUM5 0x1440 +#define AFE_DL11_CHK_SUM6 0x1444 +#define AFE_UL1_CHK_SUM1 0x1450 +#define AFE_UL1_CHK_SUM2 0x1454 +#define AFE_UL2_CHK_SUM1 0x1458 +#define AFE_UL2_CHK_SUM2 0x145c +#define AFE_UL3_CHK_SUM1 0x1460 +#define AFE_UL3_CHK_SUM2 0x1464 +#define AFE_UL4_CHK_SUM1 0x1468 +#define AFE_UL4_CHK_SUM2 0x146c +#define AFE_UL5_CHK_SUM1 0x1470 +#define AFE_UL5_CHK_SUM2 0x1474 +#define AFE_UL6_CHK_SUM1 0x1478 +#define AFE_UL6_CHK_SUM2 0x147c +#define AFE_UL8_CHK_SUM1 0x1488 +#define AFE_UL8_CHK_SUM2 0x148c +#define AFE_DL2_CHK_SUM1 0x14a0 +#define AFE_DL2_CHK_SUM2 0x14a4 +#define AFE_DL3_CHK_SUM1 0x14b0 +#define AFE_DL3_CHK_SUM2 0x14b4 +#define AFE_DL6_CHK_SUM1 0x14e0 +#define AFE_DL6_CHK_SUM2 0x14e4 +#define AFE_DL7_CHK_SUM1 0x14f0 +#define AFE_DL7_CHK_SUM2 0x14f4 +#define AFE_UL9_CHK_SUM1 0x1528 +#define AFE_UL9_CHK_SUM2 0x152c +#define AFE_BUS_MON1 0x1540 +#define UL1_MOD2AGT_CNT_LAT 0x1568 +#define UL2_MOD2AGT_CNT_LAT 0x156c +#define UL3_MOD2AGT_CNT_LAT 0x1570 +#define UL4_MOD2AGT_CNT_LAT 0x1574 +#define UL5_MOD2AGT_CNT_LAT 0x1578 +#define UL6_MOD2AGT_CNT_LAT 0x157c +#define UL8_MOD2AGT_CNT_LAT 0x1588 +#define UL9_MOD2AGT_CNT_LAT 0x158c +#define UL10_MOD2AGT_CNT_LAT 0x1590 +#define AFE_MEMIF_AGENT_FS_CON0 0x15a0 +#define AFE_MEMIF_AGENT_FS_CON1 0x15a4 +#define AFE_MEMIF_AGENT_FS_CON2 0x15a8 +#define AFE_MEMIF_AGENT_FS_CON3 0x15ac +#define AFE_MEMIF_BURST_CFG 0x1600 +#define AFE_MEMIF_BUF_FULL_MON 0x1610 +#define AFE_MEMIF_BUF_MON1 0x161c +#define AFE_MEMIF_BUF_MON3 0x1624 +#define AFE_MEMIF_BUF_MON4 0x1628 +#define AFE_MEMIF_BUF_MON5 0x162c +#define AFE_MEMIF_BUF_MON6 0x1630 +#define AFE_MEMIF_BUF_MON7 0x1634 +#define AFE_MEMIF_BUF_MON8 0x1638 +#define AFE_MEMIF_BUF_MON9 0x163c +#define AFE_MEMIF_BUF_MON10 0x1640 +#define DL2_AGENT2MODULE_CNT 0x1678 +#define DL3_AGENT2MODULE_CNT 0x167c +#define DL6_AGENT2MODULE_CNT 0x1688 +#define DL7_AGENT2MODULE_CNT 0x168c +#define DL8_AGENT2MODULE_CNT 0x1690 +#define DL10_AGENT2MODULE_CNT 0x1698 +#define DL11_AGENT2MODULE_CNT 0x169c +#define UL1_MODULE2AGENT_CNT 0x16a0 +#define UL2_MODULE2AGENT_CNT 0x16a4 +#define UL3_MODULE2AGENT_CNT 0x16a8 +#define UL4_MODULE2AGENT_CNT 0x16ac +#define UL5_MODULE2AGENT_CNT 0x16b0 +#define UL6_MODULE2AGENT_CNT 0x16b4 +#define UL8_MODULE2AGENT_CNT 0x16bc +#define UL9_MODULE2AGENT_CNT 0x16c0 +#define UL10_MODULE2AGENT_CNT 0x16c4 +#define AFE_SECURE_CON2 0x1798 +#define AFE_SECURE_CON1 0x179c +#define AFE_SECURE_CON 0x17a0 +#define AFE_SRAM_BOUND 0x17a4 +#define AFE_SE_SECURE_CON 0x17a8 +#define AFE_SECURE_MASK_LOOPBACK 0x17bc +#define AFE_SECURE_SIDEBAND0 0x1908 +#define AFE_SECURE_SIDEBAND1 0x190c +#define AFE_SECURE_SIDEBAND2 0x1910 +#define AFE_SECURE_SIDEBAND3 0x1914 +#define AFE_SECURE_MASK_BASE_ADR_MSB 0x1920 +#define AFE_SECURE_MASK_END_ADR_MSB 0x1924 +#define AFE_NORMAL_BASE_ADR_MSB 0x192c +#define AFE_NORMAL_END_ADR_MSB 0x1930 +#define AFE_SECURE_MASK_LOOPBACK0 0x1940 +#define AFE_SECURE_MASK_LOOPBACK1 0x1944 +#define AFE_SECURE_MASK_LOOPBACK2 0x1948 +#define AFE_LOOPBACK_CFG0 0x1950 +#define AFE_LOOPBACK_CFG1 0x1954 +#define AFE_LOOPBACK_CFG2 0x1958 +#define AFE_DMIC0_UL_SRC_CON0 0x1a00 +#define AFE_DMIC0_UL_SRC_CON1 0x1a04 +#define AFE_DMIC0_SRC_DEBUG 0x1a08 +#define AFE_DMIC0_SRC_DEBUG_MON0 0x1a0c +#define AFE_DMIC0_UL_SRC_MON0 0x1a10 +#define AFE_DMIC0_UL_SRC_MON1 0x1a14 +#define AFE_DMIC0_IIR_COEF_02_01 0x1a18 +#define AFE_DMIC0_IIR_COEF_04_03 0x1a1c +#define AFE_DMIC0_IIR_COEF_06_05 0x1a20 +#define AFE_DMIC0_IIR_COEF_08_07 0x1a24 +#define AFE_DMIC0_IIR_COEF_10_09 0x1a28 +#define AFE_DMIC1_UL_SRC_CON0 0x1a68 +#define AFE_DMIC1_UL_SRC_CON1 0x1a6c +#define AFE_DMIC1_SRC_DEBUG 0x1a70 +#define AFE_DMIC1_SRC_DEBUG_MON0 0x1a74 +#define AFE_DMIC1_UL_SRC_MON0 0x1a78 +#define AFE_DMIC1_UL_SRC_MON1 0x1a7c +#define AFE_DMIC1_IIR_COEF_02_01 0x1a80 +#define AFE_DMIC1_IIR_COEF_04_03 0x1a84 +#define AFE_DMIC1_IIR_COEF_06_05 0x1a88 +#define AFE_DMIC1_IIR_COEF_08_07 0x1a8c +#define AFE_DMIC1_IIR_COEF_10_09 0x1a90 +#define AFE_DMIC2_UL_SRC_CON0 0x1ad0 +#define AFE_DMIC2_UL_SRC_CON1 0x1ad4 +#define AFE_DMIC2_SRC_DEBUG 0x1ad8 +#define AFE_DMIC2_SRC_DEBUG_MON0 0x1adc +#define AFE_DMIC2_UL_SRC_MON0 0x1ae0 +#define AFE_DMIC2_UL_SRC_MON1 0x1ae4 +#define AFE_DMIC2_IIR_COEF_02_01 0x1ae8 +#define AFE_DMIC2_IIR_COEF_04_03 0x1aec +#define AFE_DMIC2_IIR_COEF_06_05 0x1af0 +#define AFE_DMIC2_IIR_COEF_08_07 0x1af4 +#define AFE_DMIC2_IIR_COEF_10_09 0x1af8 +#define AFE_DMIC3_UL_SRC_CON0 0x1b38 +#define AFE_DMIC3_UL_SRC_CON1 0x1b3c +#define AFE_DMIC3_SRC_DEBUG 0x1b40 +#define AFE_DMIC3_SRC_DEBUG_MON0 0x1b44 +#define AFE_DMIC3_UL_SRC_MON0 0x1b48 +#define AFE_DMIC3_UL_SRC_MON1 0x1b4c +#define AFE_DMIC3_IIR_COEF_02_01 0x1b50 +#define AFE_DMIC3_IIR_COEF_04_03 0x1b54 +#define AFE_DMIC3_IIR_COEF_06_05 0x1b58 +#define AFE_DMIC3_IIR_COEF_08_07 0x1b5c +#define AFE_DMIC3_IIR_COEF_10_09 0x1b60 +#define DMIC_BYPASS_HW_GAIN 0x1bf0 +#define DMIC_GAIN1_CON0 0x1c00 +#define DMIC_GAIN1_CON1 0x1c04 +#define DMIC_GAIN1_CON2 0x1c08 +#define DMIC_GAIN1_CON3 0x1c0c +#define DMIC_GAIN1_CUR 0x1c10 +#define DMIC_GAIN2_CON0 0x1c20 +#define DMIC_GAIN2_CON1 0x1c24 +#define DMIC_GAIN2_CON2 0x1c28 +#define DMIC_GAIN2_CON3 0x1c2c +#define DMIC_GAIN2_CUR 0x1c30 +#define DMIC_GAIN3_CON0 0x1c40 +#define DMIC_GAIN3_CON1 0x1c44 +#define DMIC_GAIN3_CON2 0x1c48 +#define DMIC_GAIN3_CON3 0x1c4c +#define DMIC_GAIN3_CUR 0x1c50 +#define DMIC_GAIN4_CON0 0x1c60 +#define DMIC_GAIN4_CON1 0x1c64 +#define DMIC_GAIN4_CON2 0x1c68 +#define DMIC_GAIN4_CON3 0x1c6c +#define DMIC_GAIN4_CUR 0x1c70 +#define ETDM_OUT1_DSD_FADE_CON 0x2260 +#define ETDM_OUT1_DSD_FADE_CON1 0x2264 +#define ETDM_OUT3_DSD_FADE_CON 0x2280 +#define ETDM_OUT3_DSD_FADE_CON1 0x2284 +#define ETDM_IN1_AFIFO_CON 0x2294 +#define ETDM_IN2_AFIFO_CON 0x2298 +#define ETDM_IN1_MONITOR 0x22c0 +#define ETDM_IN2_MONITOR 0x22c4 +#define ETDM_OUT1_MONITOR 0x22d0 +#define ETDM_OUT2_MONITOR 0x22d4 +#define ETDM_OUT3_MONITOR 0x22d8 +#define ETDM_COWORK_SEC_CON0 0x22e0 +#define ETDM_COWORK_SEC_CON1 0x22e4 +#define ETDM_COWORK_SEC_CON2 0x22e8 +#define ETDM_COWORK_SEC_CON3 0x22ec +#define ETDM_COWORK_CON0 0x22f0 +#define ETDM_COWORK_CON1 0x22f4 +#define ETDM_COWORK_CON2 0x22f8 +#define ETDM_COWORK_CON3 0x22fc +#define ETDM_IN1_CON0 0x2300 +#define ETDM_IN1_CON1 0x2304 +#define ETDM_IN1_CON2 0x2308 +#define ETDM_IN1_CON3 0x230c +#define ETDM_IN1_CON4 0x2310 +#define ETDM_IN1_CON5 0x2314 +#define ETDM_IN1_CON6 0x2318 +#define ETDM_IN1_CON7 0x231c +#define ETDM_IN2_CON0 0x2320 +#define ETDM_IN2_CON1 0x2324 +#define ETDM_IN2_CON2 0x2328 +#define ETDM_IN2_CON3 0x232c +#define ETDM_IN2_CON4 0x2330 +#define ETDM_IN2_CON5 0x2334 +#define ETDM_IN2_CON6 0x2338 +#define ETDM_IN2_CON7 0x233c +#define ETDM_OUT1_CON0 0x2380 +#define ETDM_OUT1_CON1 0x2384 +#define ETDM_OUT1_CON2 0x2388 +#define ETDM_OUT1_CON3 0x238c +#define ETDM_OUT1_CON4 0x2390 +#define ETDM_OUT1_CON5 0x2394 +#define ETDM_OUT1_CON6 0x2398 +#define ETDM_OUT1_CON7 0x239c +#define ETDM_OUT2_CON0 0x23a0 +#define ETDM_OUT2_CON1 0x23a4 +#define ETDM_OUT2_CON2 0x23a8 +#define ETDM_OUT2_CON3 0x23ac +#define ETDM_OUT2_CON4 0x23b0 +#define ETDM_OUT2_CON5 0x23b4 +#define ETDM_OUT2_CON6 0x23b8 +#define ETDM_OUT2_CON7 0x23bc +#define ETDM_OUT3_CON0 0x23c0 +#define ETDM_OUT3_CON1 0x23c4 +#define ETDM_OUT3_CON2 0x23c8 +#define ETDM_OUT3_CON3 0x23cc +#define ETDM_OUT3_CON4 0x23d0 +#define ETDM_OUT3_CON5 0x23d4 +#define ETDM_OUT3_CON6 0x23d8 +#define ETDM_OUT3_CON7 0x23dc +#define ETDM_OUT3_CON8 0x23e0 +#define ETDM_OUT1_CON8 0x23e4 +#define ETDM_OUT2_CON8 0x23e8 +#define GASRC_TIMING_CON0 0x2414 +#define GASRC_TIMING_CON1 0x2418 +#define GASRC_TIMING_CON2 0x241c +#define GASRC_TIMING_CON3 0x2420 +#define GASRC_TIMING_CON4 0x2424 +#define GASRC_TIMING_CON5 0x2428 +#define GASRC_TIMING_CON6 0x242c +#define GASRC_TIMING_CON7 0x2430 +#define A3_A4_TIMING_SEL0 0x2440 +#define A3_A4_TIMING_SEL1 0x2444 +#define A3_A4_TIMING_SEL2 0x2448 +#define A3_A4_TIMING_SEL3 0x244c +#define A3_A4_TIMING_SEL4 0x2450 +#define A3_A4_TIMING_SEL5 0x2454 +#define A3_A4_TIMING_SEL6 0x2458 +#define ASYS_TOP_DEBUG 0x2500 +#define AFE_DPTX_CON 0x2558 +#define AFE_DPTX_MON 0x255c +#define AFE_ADDA_DL_SRC2_CON0 0x2d00 +#define AFE_ADDA_DL_SRC2_CON1 0x2d04 +#define AFE_ADDA_TOP_CON0 0x2d0c +#define AFE_ADDA_UL_DL_CON0 0x2d10 +#define AFE_ADDA_SRC_DEBUG 0x2d14 +#define AFE_ADDA_SRC_DEBUG_MON0 0x2d18 +#define AFE_ADDA_SRC_DEBUG_MON1 0x2d20 +#define AFE_ADDA_PREDIS_CON0 0x2d24 +#define AFE_ADDA_PREDIS_CON1 0x2d28 +#define AFE_ADDA_PREDIS_CON2 0x2d2c +#define AFE_ADDA_PREDIS_CON3 0x2d30 +#define AFE_ADDA_DL_SDM_DCCOMP_CON 0x2d34 +#define AFE_ADDA_DL_SDM_TEST 0x2d38 +#define AFE_ADDA_DL_DC_COMP_CFG0 0x2d3c +#define AFE_ADDA_DL_DC_COMP_CFG1 0x2d40 +#define AFE_ADDA_DL_SDM_FIFO_MON 0x2d44 +#define AFE_ADDA_DL_SRC_LCH_MON 0x2d50 +#define AFE_ADDA_DL_SRC_RCH_MON 0x2d54 +#define AFE_ADDA_DL_SDM_OUT_MON 0x2d58 +#define AFE_ADDA_DL_SDM_DITHER_CON 0x2d5c +#define AFE_ADDA_DL_SDM_AUTO_RESET_CON 0x2d60 +#define AFE_ADDA_UL_SRC_CON0 0x2e3c +#define AFE_ADDA_UL_SRC_CON1 0x2e40 +#define AFE_CONN0 0x3000 +#define AFE_CONN0_1 0x3004 +#define AFE_CONN0_2 0x3008 +#define AFE_CONN0_3 0x300c +#define AFE_CONN0_4 0x3010 +#define AFE_CONN1 0x3014 +#define AFE_CONN1_1 0x3018 +#define AFE_CONN1_2 0x301c +#define AFE_CONN1_3 0x3020 +#define AFE_CONN1_4 0x3024 +#define AFE_CONN2 0x3028 +#define AFE_CONN2_1 0x302c +#define AFE_CONN2_2 0x3030 +#define AFE_CONN2_3 0x3034 +#define AFE_CONN2_4 0x3038 +#define AFE_CONN3 0x303c +#define AFE_CONN3_1 0x3040 +#define AFE_CONN3_2 0x3044 +#define AFE_CONN3_3 0x3048 +#define AFE_CONN3_4 0x304c +#define AFE_CONN4 0x3050 +#define AFE_CONN4_1 0x3054 +#define AFE_CONN4_2 0x3058 +#define AFE_CONN4_3 0x305c +#define AFE_CONN4_4 0x3060 +#define AFE_CONN5 0x3064 +#define AFE_CONN5_1 0x3068 +#define AFE_CONN5_2 0x306c +#define AFE_CONN5_3 0x3070 +#define AFE_CONN5_4 0x3074 +#define AFE_CONN6 0x3078 +#define AFE_CONN6_1 0x307c +#define AFE_CONN6_2 0x3080 +#define AFE_CONN6_3 0x3084 +#define AFE_CONN6_4 0x3088 +#define AFE_CONN7 0x308c +#define AFE_CONN7_1 0x3090 +#define AFE_CONN7_2 0x3094 +#define AFE_CONN7_3 0x3098 +#define AFE_CONN7_4 0x309c +#define AFE_CONN8 0x30a0 +#define AFE_CONN8_1 0x30a4 +#define AFE_CONN8_2 0x30a8 +#define AFE_CONN8_3 0x30ac +#define AFE_CONN8_4 0x30b0 +#define AFE_CONN9 0x30b4 +#define AFE_CONN9_1 0x30b8 +#define AFE_CONN9_2 0x30bc +#define AFE_CONN9_3 0x30c0 +#define AFE_CONN9_4 0x30c4 +#define AFE_CONN10 0x30c8 +#define AFE_CONN10_1 0x30cc +#define AFE_CONN10_2 0x30d0 +#define AFE_CONN10_3 0x30d4 +#define AFE_CONN10_4 0x30d8 +#define AFE_CONN11 0x30dc +#define AFE_CONN11_1 0x30e0 +#define AFE_CONN11_2 0x30e4 +#define AFE_CONN11_3 0x30e8 +#define AFE_CONN11_4 0x30ec +#define AFE_CONN12 0x30f0 +#define AFE_CONN12_1 0x30f4 +#define AFE_CONN12_2 0x30f8 +#define AFE_CONN12_3 0x30fc +#define AFE_CONN12_4 0x3100 +#define AFE_CONN13 0x3104 +#define AFE_CONN13_1 0x3108 +#define AFE_CONN13_2 0x310c +#define AFE_CONN13_3 0x3110 +#define AFE_CONN13_4 0x3114 +#define AFE_CONN14 0x3118 +#define AFE_CONN14_1 0x311c +#define AFE_CONN14_2 0x3120 +#define AFE_CONN14_3 0x3124 +#define AFE_CONN14_4 0x3128 +#define AFE_CONN15 0x312c +#define AFE_CONN15_1 0x3130 +#define AFE_CONN15_2 0x3134 +#define AFE_CONN15_3 0x3138 +#define AFE_CONN15_4 0x313c +#define AFE_CONN16 0x3140 +#define AFE_CONN16_1 0x3144 +#define AFE_CONN16_2 0x3148 +#define AFE_CONN16_3 0x314c +#define AFE_CONN16_4 0x3150 +#define AFE_CONN17 0x3154 +#define AFE_CONN17_1 0x3158 +#define AFE_CONN17_2 0x315c +#define AFE_CONN17_3 0x3160 +#define AFE_CONN17_4 0x3164 +#define AFE_CONN18 0x3168 +#define AFE_CONN18_1 0x316c +#define AFE_CONN18_2 0x3170 +#define AFE_CONN18_3 0x3174 +#define AFE_CONN18_4 0x3178 +#define AFE_CONN19 0x317c +#define AFE_CONN19_1 0x3180 +#define AFE_CONN19_2 0x3184 +#define AFE_CONN19_3 0x3188 +#define AFE_CONN19_4 0x318c +#define AFE_CONN20 0x3190 +#define AFE_CONN20_1 0x3194 +#define AFE_CONN20_2 0x3198 +#define AFE_CONN20_3 0x319c +#define AFE_CONN20_4 0x31a0 +#define AFE_CONN21 0x31a4 +#define AFE_CONN21_1 0x31a8 +#define AFE_CONN21_2 0x31ac +#define AFE_CONN21_3 0x31b0 +#define AFE_CONN21_4 0x31b4 +#define AFE_CONN22 0x31b8 +#define AFE_CONN22_1 0x31bc +#define AFE_CONN22_2 0x31c0 +#define AFE_CONN22_3 0x31c4 +#define AFE_CONN22_4 0x31c8 +#define AFE_CONN23 0x31cc +#define AFE_CONN23_1 0x31d0 +#define AFE_CONN23_2 0x31d4 +#define AFE_CONN23_3 0x31d8 +#define AFE_CONN23_4 0x31dc +#define AFE_CONN24 0x31e0 +#define AFE_CONN24_1 0x31e4 +#define AFE_CONN24_2 0x31e8 +#define AFE_CONN24_3 0x31ec +#define AFE_CONN24_4 0x31f0 +#define AFE_CONN25 0x31f4 +#define AFE_CONN25_1 0x31f8 +#define AFE_CONN25_2 0x31fc +#define AFE_CONN25_3 0x3200 +#define AFE_CONN25_4 0x3204 +#define AFE_CONN26 0x3208 +#define AFE_CONN26_1 0x320c +#define AFE_CONN26_2 0x3210 +#define AFE_CONN26_3 0x3214 +#define AFE_CONN26_4 0x3218 +#define AFE_CONN27 0x321c +#define AFE_CONN27_1 0x3220 +#define AFE_CONN27_2 0x3224 +#define AFE_CONN27_3 0x3228 +#define AFE_CONN27_4 0x322c +#define AFE_CONN28 0x3230 +#define AFE_CONN28_1 0x3234 +#define AFE_CONN28_2 0x3238 +#define AFE_CONN28_3 0x323c +#define AFE_CONN28_4 0x3240 +#define AFE_CONN29 0x3244 +#define AFE_CONN29_1 0x3248 +#define AFE_CONN29_2 0x324c +#define AFE_CONN29_3 0x3250 +#define AFE_CONN29_4 0x3254 +#define AFE_CONN30 0x3258 +#define AFE_CONN30_1 0x325c +#define AFE_CONN30_2 0x3260 +#define AFE_CONN30_3 0x3264 +#define AFE_CONN30_4 0x3268 +#define AFE_CONN31 0x326c +#define AFE_CONN31_1 0x3270 +#define AFE_CONN31_2 0x3274 +#define AFE_CONN31_3 0x3278 +#define AFE_CONN31_4 0x327c +#define AFE_CONN32 0x3280 +#define AFE_CONN32_1 0x3284 +#define AFE_CONN32_2 0x3288 +#define AFE_CONN32_3 0x328c +#define AFE_CONN32_4 0x3290 +#define AFE_CONN33 0x3294 +#define AFE_CONN33_1 0x3298 +#define AFE_CONN33_2 0x329c +#define AFE_CONN33_3 0x32a0 +#define AFE_CONN33_4 0x32a4 +#define AFE_CONN34 0x32a8 +#define AFE_CONN34_1 0x32ac +#define AFE_CONN34_2 0x32b0 +#define AFE_CONN34_3 0x32b4 +#define AFE_CONN34_4 0x32b8 +#define AFE_CONN35 0x32bc +#define AFE_CONN35_1 0x32c0 +#define AFE_CONN35_2 0x32c4 +#define AFE_CONN35_3 0x32c8 +#define AFE_CONN35_4 0x32cc +#define AFE_CONN36 0x32d0 +#define AFE_CONN36_1 0x32d4 +#define AFE_CONN36_2 0x32d8 +#define AFE_CONN36_3 0x32dc +#define AFE_CONN36_4 0x32e0 +#define AFE_CONN37 0x32e4 +#define AFE_CONN37_1 0x32e8 +#define AFE_CONN37_2 0x32ec +#define AFE_CONN37_3 0x32f0 +#define AFE_CONN37_4 0x32f4 +#define AFE_CONN38 0x32f8 +#define AFE_CONN38_1 0x32fc +#define AFE_CONN38_2 0x3300 +#define AFE_CONN38_3 0x3304 +#define AFE_CONN38_4 0x3308 +#define AFE_CONN39 0x330c +#define AFE_CONN39_1 0x3310 +#define AFE_CONN39_2 0x3314 +#define AFE_CONN39_3 0x3318 +#define AFE_CONN39_4 0x331c +#define AFE_CONN40 0x3320 +#define AFE_CONN40_1 0x3324 +#define AFE_CONN40_2 0x3328 +#define AFE_CONN40_3 0x332c +#define AFE_CONN40_4 0x3330 +#define AFE_CONN41 0x3334 +#define AFE_CONN41_1 0x3338 +#define AFE_CONN41_2 0x333c +#define AFE_CONN41_3 0x3340 +#define AFE_CONN41_4 0x3344 +#define AFE_CONN42 0x3348 +#define AFE_CONN42_1 0x334c +#define AFE_CONN42_2 0x3350 +#define AFE_CONN42_3 0x3354 +#define AFE_CONN42_4 0x3358 +#define AFE_CONN43 0x335c +#define AFE_CONN43_1 0x3360 +#define AFE_CONN43_2 0x3364 +#define AFE_CONN43_3 0x3368 +#define AFE_CONN43_4 0x336c +#define AFE_CONN44 0x3370 +#define AFE_CONN44_1 0x3374 +#define AFE_CONN44_2 0x3378 +#define AFE_CONN44_3 0x337c +#define AFE_CONN44_4 0x3380 +#define AFE_CONN45 0x3384 +#define AFE_CONN45_1 0x3388 +#define AFE_CONN45_2 0x338c +#define AFE_CONN45_3 0x3390 +#define AFE_CONN45_4 0x3394 +#define AFE_CONN46 0x3398 +#define AFE_CONN46_1 0x339c +#define AFE_CONN46_2 0x33a0 +#define AFE_CONN46_3 0x33a4 +#define AFE_CONN46_4 0x33a8 +#define AFE_CONN47 0x33ac +#define AFE_CONN47_1 0x33b0 +#define AFE_CONN47_2 0x33b4 +#define AFE_CONN47_3 0x33b8 +#define AFE_CONN47_4 0x33bc +#define AFE_CONN48 0x33c0 +#define AFE_CONN48_1 0x33c4 +#define AFE_CONN48_2 0x33c8 +#define AFE_CONN48_3 0x33cc +#define AFE_CONN48_4 0x33d0 +#define AFE_CONN49 0x33d4 +#define AFE_CONN49_1 0x33d8 +#define AFE_CONN49_2 0x33dc +#define AFE_CONN49_3 0x33e0 +#define AFE_CONN49_4 0x33e4 +#define AFE_CONN50 0x33e8 +#define AFE_CONN50_1 0x33ec +#define AFE_CONN50_2 0x33f0 +#define AFE_CONN50_3 0x33f4 +#define AFE_CONN50_4 0x33f8 +#define AFE_CONN51 0x33fc +#define AFE_CONN51_1 0x3400 +#define AFE_CONN51_2 0x3404 +#define AFE_CONN51_3 0x3408 +#define AFE_CONN51_4 0x340c +#define AFE_CONN52 0x3410 +#define AFE_CONN52_1 0x3414 +#define AFE_CONN52_2 0x3418 +#define AFE_CONN52_3 0x341c +#define AFE_CONN52_4 0x3420 +#define AFE_CONN53 0x3424 +#define AFE_CONN53_1 0x3428 +#define AFE_CONN53_2 0x342c +#define AFE_CONN53_3 0x3430 +#define AFE_CONN53_4 0x3434 +#define AFE_CONN54 0x3438 +#define AFE_CONN54_1 0x343c +#define AFE_CONN54_2 0x3440 +#define AFE_CONN54_3 0x3444 +#define AFE_CONN54_4 0x3448 +#define AFE_CONN55 0x344c +#define AFE_CONN55_1 0x3450 +#define AFE_CONN55_2 0x3454 +#define AFE_CONN55_3 0x3458 +#define AFE_CONN55_4 0x345c +#define AFE_CONN56 0x3460 +#define AFE_CONN56_1 0x3464 +#define AFE_CONN56_2 0x3468 +#define AFE_CONN56_3 0x346c +#define AFE_CONN56_4 0x3470 +#define AFE_CONN57 0x3474 +#define AFE_CONN57_1 0x3478 +#define AFE_CONN57_2 0x347c +#define AFE_CONN57_3 0x3480 +#define AFE_CONN57_4 0x3484 +#define AFE_CONN58 0x3488 +#define AFE_CONN58_1 0x348c +#define AFE_CONN58_2 0x3490 +#define AFE_CONN58_3 0x3494 +#define AFE_CONN58_4 0x3498 +#define AFE_CONN59 0x349c +#define AFE_CONN59_1 0x34a0 +#define AFE_CONN59_2 0x34a4 +#define AFE_CONN59_3 0x34a8 +#define AFE_CONN59_4 0x34ac +#define AFE_CONN60 0x34b0 +#define AFE_CONN60_1 0x34b4 +#define AFE_CONN60_2 0x34b8 +#define AFE_CONN60_3 0x34bc +#define AFE_CONN60_4 0x34c0 +#define AFE_CONN61 0x34c4 +#define AFE_CONN61_1 0x34c8 +#define AFE_CONN61_2 0x34cc +#define AFE_CONN61_3 0x34d0 +#define AFE_CONN61_4 0x34d4 +#define AFE_CONN62 0x34d8 +#define AFE_CONN62_1 0x34dc +#define AFE_CONN62_2 0x34e0 +#define AFE_CONN62_3 0x34e4 +#define AFE_CONN62_4 0x34e8 +#define AFE_CONN63 0x34ec +#define AFE_CONN63_1 0x34f0 +#define AFE_CONN63_2 0x34f4 +#define AFE_CONN63_3 0x34f8 +#define AFE_CONN63_4 0x34fc +#define AFE_CONN64 0x3500 +#define AFE_CONN64_1 0x3504 +#define AFE_CONN64_2 0x3508 +#define AFE_CONN64_3 0x350c +#define AFE_CONN64_4 0x3510 +#define AFE_CONN65 0x3514 +#define AFE_CONN65_1 0x3518 +#define AFE_CONN65_2 0x351c +#define AFE_CONN65_3 0x3520 +#define AFE_CONN65_4 0x3524 +#define AFE_CONN66 0x3528 +#define AFE_CONN66_1 0x352c +#define AFE_CONN66_2 0x3530 +#define AFE_CONN66_3 0x3534 +#define AFE_CONN66_4 0x3538 +#define AFE_CONN67 0x353c +#define AFE_CONN67_1 0x3540 +#define AFE_CONN67_2 0x3544 +#define AFE_CONN67_3 0x3548 +#define AFE_CONN67_4 0x354c +#define AFE_CONN68 0x3550 +#define AFE_CONN68_1 0x3554 +#define AFE_CONN68_2 0x3558 +#define AFE_CONN68_3 0x355c +#define AFE_CONN68_4 0x3560 +#define AFE_CONN69 0x3564 +#define AFE_CONN69_1 0x3568 +#define AFE_CONN69_2 0x356c +#define AFE_CONN69_3 0x3570 +#define AFE_CONN69_4 0x3574 +#define AFE_CONN70 0x3578 +#define AFE_CONN70_1 0x357c +#define AFE_CONN70_2 0x3580 +#define AFE_CONN70_3 0x3584 +#define AFE_CONN70_4 0x3588 +#define AFE_CONN71 0x358c +#define AFE_CONN71_1 0x3590 +#define AFE_CONN71_2 0x3594 +#define AFE_CONN71_3 0x3598 +#define AFE_CONN71_4 0x359c +#define AFE_CONN72 0x35a0 +#define AFE_CONN72_1 0x35a4 +#define AFE_CONN72_2 0x35a8 +#define AFE_CONN72_3 0x35ac +#define AFE_CONN72_4 0x35b0 +#define AFE_CONN73 0x35b4 +#define AFE_CONN73_1 0x35b8 +#define AFE_CONN73_2 0x35bc +#define AFE_CONN73_3 0x35c0 +#define AFE_CONN73_4 0x35c4 +#define AFE_CONN74 0x35c8 +#define AFE_CONN74_1 0x35cc +#define AFE_CONN74_2 0x35d0 +#define AFE_CONN74_3 0x35d4 +#define AFE_CONN74_4 0x35d8 +#define AFE_CONN75 0x35dc +#define AFE_CONN75_1 0x35e0 +#define AFE_CONN75_2 0x35e4 +#define AFE_CONN75_3 0x35e8 +#define AFE_CONN75_4 0x35ec +#define AFE_CONN76 0x35f0 +#define AFE_CONN76_1 0x35f4 +#define AFE_CONN76_2 0x35f8 +#define AFE_CONN76_3 0x35fc +#define AFE_CONN76_4 0x3600 +#define AFE_CONN77 0x3604 +#define AFE_CONN77_1 0x3608 +#define AFE_CONN77_2 0x360c +#define AFE_CONN77_3 0x3610 +#define AFE_CONN77_4 0x3614 +#define AFE_CONN78 0x3618 +#define AFE_CONN78_1 0x361c +#define AFE_CONN78_2 0x3620 +#define AFE_CONN78_3 0x3624 +#define AFE_CONN78_4 0x3628 +#define AFE_CONN79 0x362c +#define AFE_CONN79_1 0x3630 +#define AFE_CONN79_2 0x3634 +#define AFE_CONN79_3 0x3638 +#define AFE_CONN79_4 0x363c +#define AFE_CONN80 0x3640 +#define AFE_CONN80_1 0x3644 +#define AFE_CONN80_2 0x3648 +#define AFE_CONN80_3 0x364c +#define AFE_CONN80_4 0x3650 +#define AFE_CONN81 0x3654 +#define AFE_CONN81_1 0x3658 +#define AFE_CONN81_2 0x365c +#define AFE_CONN81_3 0x3660 +#define AFE_CONN81_4 0x3664 +#define AFE_CONN82 0x3668 +#define AFE_CONN82_1 0x366c +#define AFE_CONN82_2 0x3670 +#define AFE_CONN82_3 0x3674 +#define AFE_CONN82_4 0x3678 +#define AFE_CONN83 0x367c +#define AFE_CONN83_1 0x3680 +#define AFE_CONN83_2 0x3684 +#define AFE_CONN83_3 0x3688 +#define AFE_CONN83_4 0x368c +#define AFE_CONN84 0x3690 +#define AFE_CONN84_1 0x3694 +#define AFE_CONN84_2 0x3698 +#define AFE_CONN84_3 0x369c +#define AFE_CONN84_4 0x36a0 +#define AFE_CONN85 0x36a4 +#define AFE_CONN85_1 0x36a8 +#define AFE_CONN85_2 0x36ac +#define AFE_CONN85_3 0x36b0 +#define AFE_CONN85_4 0x36b4 +#define AFE_CONN86 0x36b8 +#define AFE_CONN86_1 0x36bc +#define AFE_CONN86_2 0x36c0 +#define AFE_CONN86_3 0x36c4 +#define AFE_CONN86_4 0x36c8 +#define AFE_CONN87 0x36cc +#define AFE_CONN87_1 0x36d0 +#define AFE_CONN87_2 0x36d4 +#define AFE_CONN87_3 0x36d8 +#define AFE_CONN87_4 0x36dc +#define AFE_CONN88 0x36e0 +#define AFE_CONN88_1 0x36e4 +#define AFE_CONN88_2 0x36e8 +#define AFE_CONN88_3 0x36ec +#define AFE_CONN88_4 0x36f0 +#define AFE_CONN89 0x36f4 +#define AFE_CONN89_1 0x36f8 +#define AFE_CONN89_2 0x36fc +#define AFE_CONN89_3 0x3700 +#define AFE_CONN89_4 0x3704 +#define AFE_CONN90 0x3708 +#define AFE_CONN90_1 0x370c +#define AFE_CONN90_2 0x3710 +#define AFE_CONN90_3 0x3714 +#define AFE_CONN90_4 0x3718 +#define AFE_CONN91 0x371c +#define AFE_CONN91_1 0x3720 +#define AFE_CONN91_2 0x3724 +#define AFE_CONN91_3 0x3728 +#define AFE_CONN91_4 0x372c +#define AFE_CONN92 0x3730 +#define AFE_CONN92_1 0x3734 +#define AFE_CONN92_2 0x3738 +#define AFE_CONN92_3 0x373c +#define AFE_CONN92_4 0x3740 +#define AFE_CONN93 0x3744 +#define AFE_CONN93_1 0x3748 +#define AFE_CONN93_2 0x374c +#define AFE_CONN93_3 0x3750 +#define AFE_CONN93_4 0x3754 +#define AFE_CONN94 0x3758 +#define AFE_CONN94_1 0x375c +#define AFE_CONN94_2 0x3760 +#define AFE_CONN94_3 0x3764 +#define AFE_CONN94_4 0x3768 +#define AFE_CONN95 0x376c +#define AFE_CONN95_1 0x3770 +#define AFE_CONN95_2 0x3774 +#define AFE_CONN95_3 0x3778 +#define AFE_CONN95_4 0x377c +#define AFE_CONN96 0x3780 +#define AFE_CONN96_1 0x3784 +#define AFE_CONN96_2 0x3788 +#define AFE_CONN96_3 0x378c +#define AFE_CONN96_4 0x3790 +#define AFE_CONN97 0x3794 +#define AFE_CONN97_1 0x3798 +#define AFE_CONN97_2 0x379c +#define AFE_CONN97_3 0x37a0 +#define AFE_CONN97_4 0x37a4 +#define AFE_CONN98 0x37a8 +#define AFE_CONN98_1 0x37ac +#define AFE_CONN98_2 0x37b0 +#define AFE_CONN98_3 0x37b4 +#define AFE_CONN98_4 0x37b8 +#define AFE_CONN99 0x37bc +#define AFE_CONN99_1 0x37c0 +#define AFE_CONN99_2 0x37c4 +#define AFE_CONN99_3 0x37c8 +#define AFE_CONN99_4 0x37cc +#define AFE_CONN100 0x37d0 +#define AFE_CONN100_1 0x37d4 +#define AFE_CONN100_2 0x37d8 +#define AFE_CONN100_3 0x37dc +#define AFE_CONN100_4 0x37e0 +#define AFE_CONN101 0x37e4 +#define AFE_CONN101_1 0x37e8 +#define AFE_CONN101_2 0x37ec +#define AFE_CONN101_3 0x37f0 +#define AFE_CONN101_4 0x37f4 +#define AFE_CONN102 0x37f8 +#define AFE_CONN102_1 0x37fc +#define AFE_CONN102_2 0x3800 +#define AFE_CONN102_3 0x3804 +#define AFE_CONN102_4 0x3808 +#define AFE_CONN103 0x380c +#define AFE_CONN103_1 0x3810 +#define AFE_CONN103_2 0x3814 +#define AFE_CONN103_3 0x3818 +#define AFE_CONN103_4 0x381c +#define AFE_CONN104 0x3820 +#define AFE_CONN104_1 0x3824 +#define AFE_CONN104_2 0x3828 +#define AFE_CONN104_3 0x382c +#define AFE_CONN104_4 0x3830 +#define AFE_CONN105 0x3834 +#define AFE_CONN105_1 0x3838 +#define AFE_CONN105_2 0x383c +#define AFE_CONN105_3 0x3840 +#define AFE_CONN105_4 0x3844 +#define AFE_CONN106 0x3848 +#define AFE_CONN106_1 0x384c +#define AFE_CONN106_2 0x3850 +#define AFE_CONN106_3 0x3854 +#define AFE_CONN106_4 0x3858 +#define AFE_CONN107 0x385c +#define AFE_CONN107_1 0x3860 +#define AFE_CONN107_2 0x3864 +#define AFE_CONN107_3 0x3868 +#define AFE_CONN107_4 0x386c +#define AFE_CONN108 0x3870 +#define AFE_CONN108_1 0x3874 +#define AFE_CONN108_2 0x3878 +#define AFE_CONN108_3 0x387c +#define AFE_CONN108_4 0x3880 +#define AFE_CONN109 0x3884 +#define AFE_CONN109_1 0x3888 +#define AFE_CONN109_2 0x388c +#define AFE_CONN109_3 0x3890 +#define AFE_CONN109_4 0x3894 +#define AFE_CONN110 0x3898 +#define AFE_CONN110_1 0x389c +#define AFE_CONN110_2 0x38a0 +#define AFE_CONN110_3 0x38a4 +#define AFE_CONN110_4 0x38a8 +#define AFE_CONN111 0x38ac +#define AFE_CONN111_1 0x38b0 +#define AFE_CONN111_2 0x38b4 +#define AFE_CONN111_3 0x38b8 +#define AFE_CONN111_4 0x38bc +#define AFE_CONN112 0x38c0 +#define AFE_CONN112_1 0x38c4 +#define AFE_CONN112_2 0x38c8 +#define AFE_CONN112_3 0x38cc +#define AFE_CONN112_4 0x38d0 +#define AFE_CONN113 0x38d4 +#define AFE_CONN113_1 0x38d8 +#define AFE_CONN113_2 0x38dc +#define AFE_CONN113_3 0x38e0 +#define AFE_CONN113_4 0x38e4 +#define AFE_CONN114 0x38e8 +#define AFE_CONN114_1 0x38ec +#define AFE_CONN114_2 0x38f0 +#define AFE_CONN114_3 0x38f4 +#define AFE_CONN114_4 0x38f8 +#define AFE_CONN115 0x38fc +#define AFE_CONN115_1 0x3900 +#define AFE_CONN115_2 0x3904 +#define AFE_CONN115_3 0x3908 +#define AFE_CONN115_4 0x390c +#define AFE_CONN116 0x3910 +#define AFE_CONN116_1 0x3914 +#define AFE_CONN116_2 0x3918 +#define AFE_CONN116_3 0x391c +#define AFE_CONN116_4 0x3920 +#define AFE_CONN117 0x3924 +#define AFE_CONN117_1 0x3928 +#define AFE_CONN117_2 0x392c +#define AFE_CONN117_3 0x3930 +#define AFE_CONN117_4 0x3934 +#define AFE_CONN118 0x3938 +#define AFE_CONN118_1 0x393c +#define AFE_CONN118_2 0x3940 +#define AFE_CONN118_3 0x3944 +#define AFE_CONN118_4 0x3948 +#define AFE_CONN119 0x394c +#define AFE_CONN119_1 0x3950 +#define AFE_CONN119_2 0x3954 +#define AFE_CONN119_3 0x3958 +#define AFE_CONN119_4 0x395c +#define AFE_CONN120 0x3960 +#define AFE_CONN120_1 0x3964 +#define AFE_CONN120_2 0x3968 +#define AFE_CONN120_3 0x396c +#define AFE_CONN120_4 0x3970 +#define AFE_CONN121 0x3974 +#define AFE_CONN121_1 0x3978 +#define AFE_CONN121_2 0x397c +#define AFE_CONN121_3 0x3980 +#define AFE_CONN121_4 0x3984 +#define AFE_CONN122 0x3988 +#define AFE_CONN122_1 0x398c +#define AFE_CONN122_2 0x3990 +#define AFE_CONN122_3 0x3994 +#define AFE_CONN122_4 0x3998 +#define AFE_CONN123 0x399c +#define AFE_CONN123_1 0x39a0 +#define AFE_CONN123_2 0x39a4 +#define AFE_CONN123_3 0x39a8 +#define AFE_CONN123_4 0x39ac +#define AFE_CONN124 0x39b0 +#define AFE_CONN124_1 0x39b4 +#define AFE_CONN124_2 0x39b8 +#define AFE_CONN124_3 0x39bc +#define AFE_CONN124_4 0x39c0 +#define AFE_CONN125 0x39c4 +#define AFE_CONN125_1 0x39c8 +#define AFE_CONN125_2 0x39cc +#define AFE_CONN125_3 0x39d0 +#define AFE_CONN125_4 0x39d4 +#define AFE_CONN126 0x39d8 +#define AFE_CONN126_1 0x39dc +#define AFE_CONN126_2 0x39e0 +#define AFE_CONN126_3 0x39e4 +#define AFE_CONN126_4 0x39e8 +#define AFE_CONN127 0x39ec +#define AFE_CONN127_1 0x39f0 +#define AFE_CONN127_2 0x39f4 +#define AFE_CONN127_3 0x39f8 +#define AFE_CONN127_4 0x39fc +#define AFE_CONN128 0x3a00 +#define AFE_CONN128_1 0x3a04 +#define AFE_CONN128_2 0x3a08 +#define AFE_CONN128_3 0x3a0c +#define AFE_CONN128_4 0x3a10 +#define AFE_CONN129 0x3a14 +#define AFE_CONN129_1 0x3a18 +#define AFE_CONN129_2 0x3a1c +#define AFE_CONN129_3 0x3a20 +#define AFE_CONN129_4 0x3a24 +#define AFE_CONN130 0x3a28 +#define AFE_CONN130_1 0x3a2c +#define AFE_CONN130_2 0x3a30 +#define AFE_CONN130_3 0x3a34 +#define AFE_CONN130_4 0x3a38 +#define AFE_CONN131 0x3a3c +#define AFE_CONN131_1 0x3a40 +#define AFE_CONN131_2 0x3a44 +#define AFE_CONN131_3 0x3a48 +#define AFE_CONN131_4 0x3a4c +#define AFE_CONN132 0x3a50 +#define AFE_CONN132_1 0x3a54 +#define AFE_CONN132_2 0x3a58 +#define AFE_CONN132_3 0x3a5c +#define AFE_CONN132_4 0x3a60 +#define AFE_CONN133 0x3a64 +#define AFE_CONN133_1 0x3a68 +#define AFE_CONN133_2 0x3a6c +#define AFE_CONN133_3 0x3a70 +#define AFE_CONN133_4 0x3a74 +#define AFE_CONN134 0x3a78 +#define AFE_CONN134_1 0x3a7c +#define AFE_CONN134_2 0x3a80 +#define AFE_CONN134_3 0x3a84 +#define AFE_CONN134_4 0x3a88 +#define AFE_CONN135 0x3a8c +#define AFE_CONN135_1 0x3a90 +#define AFE_CONN135_2 0x3a94 +#define AFE_CONN135_3 0x3a98 +#define AFE_CONN135_4 0x3a9c +#define AFE_CONN136 0x3aa0 +#define AFE_CONN136_1 0x3aa4 +#define AFE_CONN136_2 0x3aa8 +#define AFE_CONN136_3 0x3aac +#define AFE_CONN136_4 0x3ab0 +#define AFE_CONN137 0x3ab4 +#define AFE_CONN137_1 0x3ab8 +#define AFE_CONN137_2 0x3abc +#define AFE_CONN137_3 0x3ac0 +#define AFE_CONN137_4 0x3ac4 +#define AFE_CONN138 0x3ac8 +#define AFE_CONN138_1 0x3acc +#define AFE_CONN138_2 0x3ad0 +#define AFE_CONN138_3 0x3ad4 +#define AFE_CONN138_4 0x3ad8 +#define AFE_CONN139 0x3adc +#define AFE_CONN139_1 0x3ae0 +#define AFE_CONN139_2 0x3ae4 +#define AFE_CONN139_3 0x3ae8 +#define AFE_CONN139_4 0x3aec +#define AFE_CONN_RS 0x3af0 +#define AFE_CONN_RS_1 0x3af4 +#define AFE_CONN_RS_2 0x3af8 +#define AFE_CONN_RS_3 0x3afc +#define AFE_CONN_RS_4 0x3b00 +#define AFE_CONN_16BIT 0x3b04 +#define AFE_CONN_16BIT_1 0x3b08 +#define AFE_CONN_16BIT_2 0x3b0c +#define AFE_CONN_16BIT_3 0x3b10 +#define AFE_CONN_16BIT_4 0x3b14 +#define AFE_CONN_24BIT 0x3b18 +#define AFE_CONN_24BIT_1 0x3b1c +#define AFE_CONN_24BIT_2 0x3b20 +#define AFE_CONN_24BIT_3 0x3b24 +#define AFE_CONN_24BIT_4 0x3b28 +#define AFE_CONN_DI 0x3b2c +#define AFE_CONN_DI_1 0x3b30 +#define AFE_CONN_DI_2 0x3b34 +#define AFE_CONN_DI_3 0x3b38 +#define AFE_CONN_DI_4 0x3b3c +#define AFE_CONN176 0x3ea0 +#define AFE_CONN176_1 0x3ea4 +#define AFE_CONN176_2 0x3ea8 +#define AFE_CONN176_3 0x3eac +#define AFE_CONN176_4 0x3eb0 +#define AFE_CONN176_5 0x3eb4 +#define AFE_CONN177 0x3eb8 +#define AFE_CONN177_1 0x3ebc +#define AFE_CONN177_2 0x3ec0 +#define AFE_CONN177_3 0x3ec4 +#define AFE_CONN177_4 0x3ec8 +#define AFE_CONN177_5 0x3ecc +#define AFE_CONN182 0x3f30 +#define AFE_CONN182_1 0x3f34 +#define AFE_CONN182_2 0x3f38 +#define AFE_CONN182_3 0x3f3c +#define AFE_CONN182_4 0x3f40 +#define AFE_CONN182_5 0x3f44 +#define AFE_CONN183 0x3f48 +#define AFE_CONN183_1 0x3f4c +#define AFE_CONN183_2 0x3f50 +#define AFE_CONN183_3 0x3f54 +#define AFE_CONN183_4 0x3f58 +#define AFE_CONN183_5 0x3f5c +#define AFE_SECURE_MASK_CONN0 0x4000 +#define AFE_SECURE_MASK_CONN0_1 0x4004 +#define AFE_SECURE_MASK_CONN0_2 0x4008 +#define AFE_SECURE_MASK_CONN0_3 0x400c +#define AFE_SECURE_MASK_CONN0_4 0x4010 +#define AFE_SECURE_MASK_CONN1 0x4014 +#define AFE_SECURE_MASK_CONN1_1 0x4018 +#define AFE_SECURE_MASK_CONN1_2 0x401c +#define AFE_SECURE_MASK_CONN1_3 0x4020 +#define AFE_SECURE_MASK_CONN1_4 0x4024 +#define AFE_SECURE_MASK_CONN2 0x4028 +#define AFE_SECURE_MASK_CONN2_1 0x402c +#define AFE_SECURE_MASK_CONN2_2 0x4030 +#define AFE_SECURE_MASK_CONN2_3 0x4034 +#define AFE_SECURE_MASK_CONN2_4 0x4038 +#define AFE_SECURE_MASK_CONN3 0x403c +#define AFE_SECURE_MASK_CONN3_1 0x4040 +#define AFE_SECURE_MASK_CONN3_2 0x4044 +#define AFE_SECURE_MASK_CONN3_3 0x4048 +#define AFE_SECURE_MASK_CONN3_4 0x404c +#define AFE_SECURE_MASK_CONN4 0x4050 +#define AFE_SECURE_MASK_CONN4_1 0x4054 +#define AFE_SECURE_MASK_CONN4_2 0x4058 +#define AFE_SECURE_MASK_CONN4_3 0x405c +#define AFE_SECURE_MASK_CONN4_4 0x4060 +#define AFE_SECURE_MASK_CONN5 0x4064 +#define AFE_SECURE_MASK_CONN5_1 0x4068 +#define AFE_SECURE_MASK_CONN5_2 0x406c +#define AFE_SECURE_MASK_CONN5_3 0x4070 +#define AFE_SECURE_MASK_CONN5_4 0x4074 +#define AFE_SECURE_MASK_CONN6 0x4078 +#define AFE_SECURE_MASK_CONN6_1 0x407c +#define AFE_SECURE_MASK_CONN6_2 0x4080 +#define AFE_SECURE_MASK_CONN6_3 0x4084 +#define AFE_SECURE_MASK_CONN6_4 0x4088 +#define AFE_SECURE_MASK_CONN7 0x408c +#define AFE_SECURE_MASK_CONN7_1 0x4090 +#define AFE_SECURE_MASK_CONN7_2 0x4094 +#define AFE_SECURE_MASK_CONN7_3 0x4098 +#define AFE_SECURE_MASK_CONN7_4 0x409c +#define AFE_SECURE_MASK_CONN8 0x40a0 +#define AFE_SECURE_MASK_CONN8_1 0x40a4 +#define AFE_SECURE_MASK_CONN8_2 0x40a8 +#define AFE_SECURE_MASK_CONN8_3 0x40ac +#define AFE_SECURE_MASK_CONN8_4 0x40b0 +#define AFE_SECURE_MASK_CONN9 0x40b4 +#define AFE_SECURE_MASK_CONN9_1 0x40b8 +#define AFE_SECURE_MASK_CONN9_2 0x40bc +#define AFE_SECURE_MASK_CONN9_3 0x40c0 +#define AFE_SECURE_MASK_CONN9_4 0x40c4 +#define AFE_SECURE_MASK_CONN10 0x40c8 +#define AFE_SECURE_MASK_CONN10_1 0x40cc +#define AFE_SECURE_MASK_CONN10_2 0x40d0 +#define AFE_SECURE_MASK_CONN10_3 0x40d4 +#define AFE_SECURE_MASK_CONN10_4 0x40d8 +#define AFE_SECURE_MASK_CONN11 0x40dc +#define AFE_SECURE_MASK_CONN11_1 0x40e0 +#define AFE_SECURE_MASK_CONN11_2 0x40e4 +#define AFE_SECURE_MASK_CONN11_3 0x40e8 +#define AFE_SECURE_MASK_CONN11_4 0x40ec +#define AFE_SECURE_MASK_CONN12 0x40f0 +#define AFE_SECURE_MASK_CONN12_1 0x40f4 +#define AFE_SECURE_MASK_CONN12_2 0x40f8 +#define AFE_SECURE_MASK_CONN12_3 0x40fc +#define AFE_SECURE_MASK_CONN12_4 0x4100 +#define AFE_SECURE_MASK_CONN13 0x4104 +#define AFE_SECURE_MASK_CONN13_1 0x4108 +#define AFE_SECURE_MASK_CONN13_2 0x410c +#define AFE_SECURE_MASK_CONN13_3 0x4110 +#define AFE_SECURE_MASK_CONN13_4 0x4114 +#define AFE_SECURE_MASK_CONN14 0x4118 +#define AFE_SECURE_MASK_CONN14_1 0x411c +#define AFE_SECURE_MASK_CONN14_2 0x4120 +#define AFE_SECURE_MASK_CONN14_3 0x4124 +#define AFE_SECURE_MASK_CONN14_4 0x4128 +#define AFE_SECURE_MASK_CONN15 0x412c +#define AFE_SECURE_MASK_CONN15_1 0x4130 +#define AFE_SECURE_MASK_CONN15_2 0x4134 +#define AFE_SECURE_MASK_CONN15_3 0x4138 +#define AFE_SECURE_MASK_CONN15_4 0x413c +#define AFE_SECURE_MASK_CONN16 0x4140 +#define AFE_SECURE_MASK_CONN16_1 0x4144 +#define AFE_SECURE_MASK_CONN16_2 0x4148 +#define AFE_SECURE_MASK_CONN16_3 0x414c +#define AFE_SECURE_MASK_CONN16_4 0x4150 +#define AFE_SECURE_MASK_CONN17 0x4154 +#define AFE_SECURE_MASK_CONN17_1 0x4158 +#define AFE_SECURE_MASK_CONN17_2 0x415c +#define AFE_SECURE_MASK_CONN17_3 0x4160 +#define AFE_SECURE_MASK_CONN17_4 0x4164 +#define AFE_SECURE_MASK_CONN18 0x4168 +#define AFE_SECURE_MASK_CONN18_1 0x416c +#define AFE_SECURE_MASK_CONN18_2 0x4170 +#define AFE_SECURE_MASK_CONN18_3 0x4174 +#define AFE_SECURE_MASK_CONN18_4 0x4178 +#define AFE_SECURE_MASK_CONN19 0x417c +#define AFE_SECURE_MASK_CONN19_1 0x4180 +#define AFE_SECURE_MASK_CONN19_2 0x4184 +#define AFE_SECURE_MASK_CONN19_3 0x4188 +#define AFE_SECURE_MASK_CONN19_4 0x418c +#define AFE_SECURE_MASK_CONN20 0x4190 +#define AFE_SECURE_MASK_CONN20_1 0x4194 +#define AFE_SECURE_MASK_CONN20_2 0x4198 +#define AFE_SECURE_MASK_CONN20_3 0x419c +#define AFE_SECURE_MASK_CONN20_4 0x41a0 +#define AFE_SECURE_MASK_CONN21 0x41a4 +#define AFE_SECURE_MASK_CONN21_1 0x41a8 +#define AFE_SECURE_MASK_CONN21_2 0x41ac +#define AFE_SECURE_MASK_CONN21_3 0x41b0 +#define AFE_SECURE_MASK_CONN21_4 0x41b4 +#define AFE_SECURE_MASK_CONN22 0x41b8 +#define AFE_SECURE_MASK_CONN22_1 0x41bc +#define AFE_SECURE_MASK_CONN22_2 0x41c0 +#define AFE_SECURE_MASK_CONN22_3 0x41c4 +#define AFE_SECURE_MASK_CONN22_4 0x41c8 +#define AFE_SECURE_MASK_CONN23 0x41cc +#define AFE_SECURE_MASK_CONN23_1 0x41d0 +#define AFE_SECURE_MASK_CONN23_2 0x41d4 +#define AFE_SECURE_MASK_CONN23_3 0x41d8 +#define AFE_SECURE_MASK_CONN23_4 0x41dc +#define AFE_SECURE_MASK_CONN24 0x41e0 +#define AFE_SECURE_MASK_CONN24_1 0x41e4 +#define AFE_SECURE_MASK_CONN24_2 0x41e8 +#define AFE_SECURE_MASK_CONN24_3 0x41ec +#define AFE_SECURE_MASK_CONN24_4 0x41f0 +#define AFE_SECURE_MASK_CONN25 0x41f4 +#define AFE_SECURE_MASK_CONN25_1 0x41f8 +#define AFE_SECURE_MASK_CONN25_2 0x41fc +#define AFE_SECURE_MASK_CONN25_3 0x4200 +#define AFE_SECURE_MASK_CONN25_4 0x4204 +#define AFE_SECURE_MASK_CONN26 0x4208 +#define AFE_SECURE_MASK_CONN26_1 0x420c +#define AFE_SECURE_MASK_CONN26_2 0x4210 +#define AFE_SECURE_MASK_CONN26_3 0x4214 +#define AFE_SECURE_MASK_CONN26_4 0x4218 +#define AFE_SECURE_MASK_CONN27 0x421c +#define AFE_SECURE_MASK_CONN27_1 0x4220 +#define AFE_SECURE_MASK_CONN27_2 0x4224 +#define AFE_SECURE_MASK_CONN27_3 0x4228 +#define AFE_SECURE_MASK_CONN27_4 0x422c +#define AFE_SECURE_MASK_CONN28 0x4230 +#define AFE_SECURE_MASK_CONN28_1 0x4234 +#define AFE_SECURE_MASK_CONN28_2 0x4238 +#define AFE_SECURE_MASK_CONN28_3 0x423c +#define AFE_SECURE_MASK_CONN28_4 0x4240 +#define AFE_SECURE_MASK_CONN29 0x4244 +#define AFE_SECURE_MASK_CONN29_1 0x4248 +#define AFE_SECURE_MASK_CONN29_2 0x424c +#define AFE_SECURE_MASK_CONN29_3 0x4250 +#define AFE_SECURE_MASK_CONN29_4 0x4254 +#define AFE_SECURE_MASK_CONN30 0x4258 +#define AFE_SECURE_MASK_CONN30_1 0x425c +#define AFE_SECURE_MASK_CONN30_2 0x4260 +#define AFE_SECURE_MASK_CONN30_3 0x4264 +#define AFE_SECURE_MASK_CONN30_4 0x4268 +#define AFE_SECURE_MASK_CONN31 0x426c +#define AFE_SECURE_MASK_CONN31_1 0x4270 +#define AFE_SECURE_MASK_CONN31_2 0x4274 +#define AFE_SECURE_MASK_CONN31_3 0x4278 +#define AFE_SECURE_MASK_CONN31_4 0x427c +#define AFE_SECURE_MASK_CONN32 0x4280 +#define AFE_SECURE_MASK_CONN32_1 0x4284 +#define AFE_SECURE_MASK_CONN32_2 0x4288 +#define AFE_SECURE_MASK_CONN32_3 0x428c +#define AFE_SECURE_MASK_CONN32_4 0x4290 +#define AFE_SECURE_MASK_CONN33 0x4294 +#define AFE_SECURE_MASK_CONN33_1 0x4298 +#define AFE_SECURE_MASK_CONN33_2 0x429c +#define AFE_SECURE_MASK_CONN33_3 0x42a0 +#define AFE_SECURE_MASK_CONN33_4 0x42a4 +#define AFE_SECURE_MASK_CONN34 0x42a8 +#define AFE_SECURE_MASK_CONN34_1 0x42ac +#define AFE_SECURE_MASK_CONN34_2 0x42b0 +#define AFE_SECURE_MASK_CONN34_3 0x42b4 +#define AFE_SECURE_MASK_CONN34_4 0x42b8 +#define AFE_SECURE_MASK_CONN35 0x42bc +#define AFE_SECURE_MASK_CONN35_1 0x42c0 +#define AFE_SECURE_MASK_CONN35_2 0x42c4 +#define AFE_SECURE_MASK_CONN35_3 0x42c8 +#define AFE_SECURE_MASK_CONN35_4 0x42cc +#define AFE_SECURE_MASK_CONN36 0x42d0 +#define AFE_SECURE_MASK_CONN36_1 0x42d4 +#define AFE_SECURE_MASK_CONN36_2 0x42d8 +#define AFE_SECURE_MASK_CONN36_3 0x42dc +#define AFE_SECURE_MASK_CONN36_4 0x42e0 +#define AFE_SECURE_MASK_CONN37 0x42e4 +#define AFE_SECURE_MASK_CONN37_1 0x42e8 +#define AFE_SECURE_MASK_CONN37_2 0x42ec +#define AFE_SECURE_MASK_CONN37_3 0x42f0 +#define AFE_SECURE_MASK_CONN37_4 0x42f4 +#define AFE_SECURE_MASK_CONN38 0x42f8 +#define AFE_SECURE_MASK_CONN38_1 0x42fc +#define AFE_SECURE_MASK_CONN38_2 0x4300 +#define AFE_SECURE_MASK_CONN38_3 0x4304 +#define AFE_SECURE_MASK_CONN38_4 0x4308 +#define AFE_SECURE_MASK_CONN39 0x430c +#define AFE_SECURE_MASK_CONN39_1 0x4310 +#define AFE_SECURE_MASK_CONN39_2 0x4314 +#define AFE_SECURE_MASK_CONN39_3 0x4318 +#define AFE_SECURE_MASK_CONN39_4 0x431c +#define AFE_SECURE_MASK_CONN40 0x4320 +#define AFE_SECURE_MASK_CONN40_1 0x4324 +#define AFE_SECURE_MASK_CONN40_2 0x4328 +#define AFE_SECURE_MASK_CONN40_3 0x432c +#define AFE_SECURE_MASK_CONN40_4 0x4330 +#define AFE_SECURE_MASK_CONN41 0x4334 +#define AFE_SECURE_MASK_CONN41_1 0x4338 +#define AFE_SECURE_MASK_CONN41_2 0x433c +#define AFE_SECURE_MASK_CONN41_3 0x4340 +#define AFE_SECURE_MASK_CONN41_4 0x4344 +#define AFE_SECURE_MASK_CONN42 0x4348 +#define AFE_SECURE_MASK_CONN42_1 0x434c +#define AFE_SECURE_MASK_CONN42_2 0x4350 +#define AFE_SECURE_MASK_CONN42_3 0x4354 +#define AFE_SECURE_MASK_CONN42_4 0x4358 +#define AFE_SECURE_MASK_CONN43 0x435c +#define AFE_SECURE_MASK_CONN43_1 0x4360 +#define AFE_SECURE_MASK_CONN43_2 0x4364 +#define AFE_SECURE_MASK_CONN43_3 0x4368 +#define AFE_SECURE_MASK_CONN43_4 0x436c +#define AFE_SECURE_MASK_CONN44 0x4370 +#define AFE_SECURE_MASK_CONN44_1 0x4374 +#define AFE_SECURE_MASK_CONN44_2 0x4378 +#define AFE_SECURE_MASK_CONN44_3 0x437c +#define AFE_SECURE_MASK_CONN44_4 0x4380 +#define AFE_SECURE_MASK_CONN45 0x4384 +#define AFE_SECURE_MASK_CONN45_1 0x4388 +#define AFE_SECURE_MASK_CONN45_2 0x438c +#define AFE_SECURE_MASK_CONN45_3 0x4390 +#define AFE_SECURE_MASK_CONN45_4 0x4394 +#define AFE_SECURE_MASK_CONN46 0x4398 +#define AFE_SECURE_MASK_CONN46_1 0x439c +#define AFE_SECURE_MASK_CONN46_2 0x43a0 +#define AFE_SECURE_MASK_CONN46_3 0x43a4 +#define AFE_SECURE_MASK_CONN46_4 0x43a8 +#define AFE_SECURE_MASK_CONN47 0x43ac +#define AFE_SECURE_MASK_CONN47_1 0x43b0 +#define AFE_SECURE_MASK_CONN47_2 0x43b4 +#define AFE_SECURE_MASK_CONN47_3 0x43b8 +#define AFE_SECURE_MASK_CONN47_4 0x43bc +#define AFE_SECURE_MASK_CONN48 0x43c0 +#define AFE_SECURE_MASK_CONN48_1 0x43c4 +#define AFE_SECURE_MASK_CONN48_2 0x43c8 +#define AFE_SECURE_MASK_CONN48_3 0x43cc +#define AFE_SECURE_MASK_CONN48_4 0x43d0 +#define AFE_SECURE_MASK_CONN49 0x43d4 +#define AFE_SECURE_MASK_CONN49_1 0x43d8 +#define AFE_SECURE_MASK_CONN49_2 0x43dc +#define AFE_SECURE_MASK_CONN49_3 0x43e0 +#define AFE_SECURE_MASK_CONN49_4 0x43e4 +#define AFE_SECURE_MASK_CONN50 0x43e8 +#define AFE_SECURE_MASK_CONN50_1 0x43ec +#define AFE_SECURE_MASK_CONN50_2 0x43f0 +#define AFE_SECURE_MASK_CONN50_3 0x43f4 +#define AFE_SECURE_MASK_CONN50_4 0x43f8 +#define AFE_SECURE_MASK_CONN51 0x43fc +#define AFE_SECURE_MASK_CONN51_1 0x4400 +#define AFE_SECURE_MASK_CONN51_2 0x4404 +#define AFE_SECURE_MASK_CONN51_3 0x4408 +#define AFE_SECURE_MASK_CONN51_4 0x440c +#define AFE_SECURE_MASK_CONN52 0x4410 +#define AFE_SECURE_MASK_CONN52_1 0x4414 +#define AFE_SECURE_MASK_CONN52_2 0x4418 +#define AFE_SECURE_MASK_CONN52_3 0x441c +#define AFE_SECURE_MASK_CONN52_4 0x4420 +#define AFE_SECURE_MASK_CONN53 0x4424 +#define AFE_SECURE_MASK_CONN53_1 0x4428 +#define AFE_SECURE_MASK_CONN53_2 0x442c +#define AFE_SECURE_MASK_CONN53_3 0x4430 +#define AFE_SECURE_MASK_CONN53_4 0x4434 +#define AFE_SECURE_MASK_CONN54 0x4438 +#define AFE_SECURE_MASK_CONN54_1 0x443c +#define AFE_SECURE_MASK_CONN54_2 0x4440 +#define AFE_SECURE_MASK_CONN54_3 0x4444 +#define AFE_SECURE_MASK_CONN54_4 0x4448 +#define AFE_SECURE_MASK_CONN55 0x444c +#define AFE_SECURE_MASK_CONN55_1 0x4450 +#define AFE_SECURE_MASK_CONN55_2 0x4454 +#define AFE_SECURE_MASK_CONN55_3 0x4458 +#define AFE_SECURE_MASK_CONN55_4 0x445c +#define AFE_SECURE_MASK_CONN56 0x4460 +#define AFE_SECURE_MASK_CONN56_1 0x4464 +#define AFE_SECURE_MASK_CONN56_2 0x4468 +#define AFE_SECURE_MASK_CONN56_3 0x446c +#define AFE_SECURE_MASK_CONN56_4 0x4470 +#define AFE_SECURE_MASK_CONN57 0x4474 +#define AFE_SECURE_MASK_CONN57_1 0x4478 +#define AFE_SECURE_MASK_CONN57_2 0x447c +#define AFE_SECURE_MASK_CONN57_3 0x4480 +#define AFE_SECURE_MASK_CONN57_4 0x4484 +#define AFE_SECURE_MASK_CONN58 0x4488 +#define AFE_SECURE_MASK_CONN58_1 0x448c +#define AFE_SECURE_MASK_CONN58_2 0x4490 +#define AFE_SECURE_MASK_CONN58_3 0x4494 +#define AFE_SECURE_MASK_CONN58_4 0x4498 +#define AFE_SECURE_MASK_CONN59 0x449c +#define AFE_SECURE_MASK_CONN59_1 0x44a0 +#define AFE_SECURE_MASK_CONN59_2 0x44a4 +#define AFE_SECURE_MASK_CONN59_3 0x44a8 +#define AFE_SECURE_MASK_CONN59_4 0x44ac +#define AFE_SECURE_MASK_CONN60 0x44b0 +#define AFE_SECURE_MASK_CONN60_1 0x44b4 +#define AFE_SECURE_MASK_CONN60_2 0x44b8 +#define AFE_SECURE_MASK_CONN60_3 0x44bc +#define AFE_SECURE_MASK_CONN60_4 0x44c0 +#define AFE_SECURE_MASK_CONN61 0x44c4 +#define AFE_SECURE_MASK_CONN61_1 0x44c8 +#define AFE_SECURE_MASK_CONN61_2 0x44cc +#define AFE_SECURE_MASK_CONN61_3 0x44d0 +#define AFE_SECURE_MASK_CONN61_4 0x44d4 +#define AFE_SECURE_MASK_CONN62 0x44d8 +#define AFE_SECURE_MASK_CONN62_1 0x44dc +#define AFE_SECURE_MASK_CONN62_2 0x44e0 +#define AFE_SECURE_MASK_CONN62_3 0x44e4 +#define AFE_SECURE_MASK_CONN62_4 0x44e8 +#define AFE_SECURE_MASK_CONN63 0x44ec +#define AFE_SECURE_MASK_CONN63_1 0x44f0 +#define AFE_SECURE_MASK_CONN63_2 0x44f4 +#define AFE_SECURE_MASK_CONN63_3 0x44f8 +#define AFE_SECURE_MASK_CONN63_4 0x44fc +#define AFE_SECURE_MASK_CONN64 0x4500 +#define AFE_SECURE_MASK_CONN64_1 0x4504 +#define AFE_SECURE_MASK_CONN64_2 0x4508 +#define AFE_SECURE_MASK_CONN64_3 0x450c +#define AFE_SECURE_MASK_CONN64_4 0x4510 +#define AFE_SECURE_MASK_CONN65 0x4514 +#define AFE_SECURE_MASK_CONN65_1 0x4518 +#define AFE_SECURE_MASK_CONN65_2 0x451c +#define AFE_SECURE_MASK_CONN65_3 0x4520 +#define AFE_SECURE_MASK_CONN65_4 0x4524 +#define AFE_SECURE_MASK_CONN66 0x4528 +#define AFE_SECURE_MASK_CONN66_1 0x452c +#define AFE_SECURE_MASK_CONN66_2 0x4530 +#define AFE_SECURE_MASK_CONN66_3 0x4534 +#define AFE_SECURE_MASK_CONN66_4 0x4538 +#define AFE_SECURE_MASK_CONN67 0x453c +#define AFE_SECURE_MASK_CONN67_1 0x4540 +#define AFE_SECURE_MASK_CONN67_2 0x4544 +#define AFE_SECURE_MASK_CONN67_3 0x4548 +#define AFE_SECURE_MASK_CONN67_4 0x454c +#define AFE_SECURE_MASK_CONN68 0x4550 +#define AFE_SECURE_MASK_CONN68_1 0x4554 +#define AFE_SECURE_MASK_CONN68_2 0x4558 +#define AFE_SECURE_MASK_CONN68_3 0x455c +#define AFE_SECURE_MASK_CONN68_4 0x4560 +#define AFE_SECURE_MASK_CONN69 0x4564 +#define AFE_SECURE_MASK_CONN69_1 0x4568 +#define AFE_SECURE_MASK_CONN69_2 0x456c +#define AFE_SECURE_MASK_CONN69_3 0x4570 +#define AFE_SECURE_MASK_CONN69_4 0x4574 +#define AFE_SECURE_MASK_CONN70 0x4578 +#define AFE_SECURE_MASK_CONN70_1 0x457c +#define AFE_SECURE_MASK_CONN70_2 0x4580 +#define AFE_SECURE_MASK_CONN70_3 0x4584 +#define AFE_SECURE_MASK_CONN70_4 0x4588 +#define AFE_SECURE_MASK_CONN71 0x458c +#define AFE_SECURE_MASK_CONN71_1 0x4590 +#define AFE_SECURE_MASK_CONN71_2 0x4594 +#define AFE_SECURE_MASK_CONN71_3 0x4598 +#define AFE_SECURE_MASK_CONN71_4 0x459c +#define AFE_SECURE_MASK_CONN72 0x45a0 +#define AFE_SECURE_MASK_CONN72_1 0x45a4 +#define AFE_SECURE_MASK_CONN72_2 0x45a8 +#define AFE_SECURE_MASK_CONN72_3 0x45ac +#define AFE_SECURE_MASK_CONN72_4 0x45b0 +#define AFE_SECURE_MASK_CONN73 0x45b4 +#define AFE_SECURE_MASK_CONN73_1 0x45b8 +#define AFE_SECURE_MASK_CONN73_2 0x45bc +#define AFE_SECURE_MASK_CONN73_3 0x45c0 +#define AFE_SECURE_MASK_CONN73_4 0x45c4 +#define AFE_SECURE_MASK_CONN74 0x45c8 +#define AFE_SECURE_MASK_CONN74_1 0x45cc +#define AFE_SECURE_MASK_CONN74_2 0x45d0 +#define AFE_SECURE_MASK_CONN74_3 0x45d4 +#define AFE_SECURE_MASK_CONN74_4 0x45d8 +#define AFE_SECURE_MASK_CONN75 0x45dc +#define AFE_SECURE_MASK_CONN75_1 0x45e0 +#define AFE_SECURE_MASK_CONN75_2 0x45e4 +#define AFE_SECURE_MASK_CONN75_3 0x45e8 +#define AFE_SECURE_MASK_CONN75_4 0x45ec +#define AFE_SECURE_MASK_CONN76 0x45f0 +#define AFE_SECURE_MASK_CONN76_1 0x45f4 +#define AFE_SECURE_MASK_CONN76_2 0x45f8 +#define AFE_SECURE_MASK_CONN76_3 0x45fc +#define AFE_SECURE_MASK_CONN76_4 0x4600 +#define AFE_SECURE_MASK_CONN77 0x4604 +#define AFE_SECURE_MASK_CONN77_1 0x4608 +#define AFE_SECURE_MASK_CONN77_2 0x460c +#define AFE_SECURE_MASK_CONN77_3 0x4610 +#define AFE_SECURE_MASK_CONN77_4 0x4614 +#define AFE_SECURE_MASK_CONN78 0x4618 +#define AFE_SECURE_MASK_CONN78_1 0x461c +#define AFE_SECURE_MASK_CONN78_2 0x4620 +#define AFE_SECURE_MASK_CONN78_3 0x4624 +#define AFE_SECURE_MASK_CONN78_4 0x4628 +#define AFE_SECURE_MASK_CONN79 0x462c +#define AFE_SECURE_MASK_CONN79_1 0x4630 +#define AFE_SECURE_MASK_CONN79_2 0x4634 +#define AFE_SECURE_MASK_CONN79_3 0x4638 +#define AFE_SECURE_MASK_CONN79_4 0x463c +#define AFE_SECURE_MASK_CONN80 0x4640 +#define AFE_SECURE_MASK_CONN80_1 0x4644 +#define AFE_SECURE_MASK_CONN80_2 0x4648 +#define AFE_SECURE_MASK_CONN80_3 0x464c +#define AFE_SECURE_MASK_CONN80_4 0x4650 +#define AFE_SECURE_MASK_CONN81 0x4654 +#define AFE_SECURE_MASK_CONN81_1 0x4658 +#define AFE_SECURE_MASK_CONN81_2 0x465c +#define AFE_SECURE_MASK_CONN81_3 0x4660 +#define AFE_SECURE_MASK_CONN81_4 0x4664 +#define AFE_SECURE_MASK_CONN82 0x4668 +#define AFE_SECURE_MASK_CONN82_1 0x466c +#define AFE_SECURE_MASK_CONN82_2 0x4670 +#define AFE_SECURE_MASK_CONN82_3 0x4674 +#define AFE_SECURE_MASK_CONN82_4 0x4678 +#define AFE_SECURE_MASK_CONN83 0x467c +#define AFE_SECURE_MASK_CONN83_1 0x4680 +#define AFE_SECURE_MASK_CONN83_2 0x4684 +#define AFE_SECURE_MASK_CONN83_3 0x4688 +#define AFE_SECURE_MASK_CONN83_4 0x468c +#define AFE_SECURE_MASK_CONN84 0x4690 +#define AFE_SECURE_MASK_CONN84_1 0x4694 +#define AFE_SECURE_MASK_CONN84_2 0x4698 +#define AFE_SECURE_MASK_CONN84_3 0x469c +#define AFE_SECURE_MASK_CONN84_4 0x46a0 +#define AFE_SECURE_MASK_CONN85 0x46a4 +#define AFE_SECURE_MASK_CONN85_1 0x46a8 +#define AFE_SECURE_MASK_CONN85_2 0x46ac +#define AFE_SECURE_MASK_CONN85_3 0x46b0 +#define AFE_SECURE_MASK_CONN85_4 0x46b4 +#define AFE_SECURE_MASK_CONN86 0x46b8 +#define AFE_SECURE_MASK_CONN86_1 0x46bc +#define AFE_SECURE_MASK_CONN86_2 0x46c0 +#define AFE_SECURE_MASK_CONN86_3 0x46c4 +#define AFE_SECURE_MASK_CONN86_4 0x46c8 +#define AFE_SECURE_MASK_CONN87 0x46cc +#define AFE_SECURE_MASK_CONN87_1 0x46d0 +#define AFE_SECURE_MASK_CONN87_2 0x46d4 +#define AFE_SECURE_MASK_CONN87_3 0x46d8 +#define AFE_SECURE_MASK_CONN87_4 0x46dc +#define AFE_SECURE_MASK_CONN88 0x46e0 +#define AFE_SECURE_MASK_CONN88_1 0x46e4 +#define AFE_SECURE_MASK_CONN88_2 0x46e8 +#define AFE_SECURE_MASK_CONN88_3 0x46ec +#define AFE_SECURE_MASK_CONN88_4 0x46f0 +#define AFE_SECURE_MASK_CONN89 0x46f4 +#define AFE_SECURE_MASK_CONN89_1 0x46f8 +#define AFE_SECURE_MASK_CONN89_2 0x46fc +#define AFE_SECURE_MASK_CONN89_3 0x4700 +#define AFE_SECURE_MASK_CONN89_4 0x4704 +#define AFE_SECURE_MASK_CONN90 0x4708 +#define AFE_SECURE_MASK_CONN90_1 0x470c +#define AFE_SECURE_MASK_CONN90_2 0x4710 +#define AFE_SECURE_MASK_CONN90_3 0x4714 +#define AFE_SECURE_MASK_CONN90_4 0x4718 +#define AFE_SECURE_MASK_CONN91 0x471c +#define AFE_SECURE_MASK_CONN91_1 0x4720 +#define AFE_SECURE_MASK_CONN91_2 0x4724 +#define AFE_SECURE_MASK_CONN91_3 0x4728 +#define AFE_SECURE_MASK_CONN91_4 0x472c +#define AFE_SECURE_MASK_CONN92 0x4730 +#define AFE_SECURE_MASK_CONN92_1 0x4734 +#define AFE_SECURE_MASK_CONN92_2 0x4738 +#define AFE_SECURE_MASK_CONN92_3 0x473c +#define AFE_SECURE_MASK_CONN92_4 0x4740 +#define AFE_SECURE_MASK_CONN93 0x4744 +#define AFE_SECURE_MASK_CONN93_1 0x4748 +#define AFE_SECURE_MASK_CONN93_2 0x474c +#define AFE_SECURE_MASK_CONN93_3 0x4750 +#define AFE_SECURE_MASK_CONN93_4 0x4754 +#define AFE_SECURE_MASK_CONN94 0x4758 +#define AFE_SECURE_MASK_CONN94_1 0x475c +#define AFE_SECURE_MASK_CONN94_2 0x4760 +#define AFE_SECURE_MASK_CONN94_3 0x4764 +#define AFE_SECURE_MASK_CONN94_4 0x4768 +#define AFE_SECURE_MASK_CONN95 0x476c +#define AFE_SECURE_MASK_CONN95_1 0x4770 +#define AFE_SECURE_MASK_CONN95_2 0x4774 +#define AFE_SECURE_MASK_CONN95_3 0x4778 +#define AFE_SECURE_MASK_CONN95_4 0x477c +#define AFE_SECURE_MASK_CONN96 0x4780 +#define AFE_SECURE_MASK_CONN96_1 0x4784 +#define AFE_SECURE_MASK_CONN96_2 0x4788 +#define AFE_SECURE_MASK_CONN96_3 0x478c +#define AFE_SECURE_MASK_CONN96_4 0x4790 +#define AFE_SECURE_MASK_CONN97 0x4794 +#define AFE_SECURE_MASK_CONN97_1 0x4798 +#define AFE_SECURE_MASK_CONN97_2 0x479c +#define AFE_SECURE_MASK_CONN97_3 0x47a0 +#define AFE_SECURE_MASK_CONN97_4 0x47a4 +#define AFE_SECURE_MASK_CONN98 0x47a8 +#define AFE_SECURE_MASK_CONN98_1 0x47ac +#define AFE_SECURE_MASK_CONN98_2 0x47b0 +#define AFE_SECURE_MASK_CONN98_3 0x47b4 +#define AFE_SECURE_MASK_CONN98_4 0x47b8 +#define AFE_SECURE_MASK_CONN99 0x47bc +#define AFE_SECURE_MASK_CONN99_1 0x47c0 +#define AFE_SECURE_MASK_CONN99_2 0x47c4 +#define AFE_SECURE_MASK_CONN99_3 0x47c8 +#define AFE_SECURE_MASK_CONN99_4 0x47cc +#define AFE_SECURE_MASK_CONN100 0x47d0 +#define AFE_SECURE_MASK_CONN100_1 0x47d4 +#define AFE_SECURE_MASK_CONN100_2 0x47d8 +#define AFE_SECURE_MASK_CONN100_3 0x47dc +#define AFE_SECURE_MASK_CONN100_4 0x47e0 +#define AFE_SECURE_MASK_CONN101 0x47e4 +#define AFE_SECURE_MASK_CONN101_1 0x47e8 +#define AFE_SECURE_MASK_CONN101_2 0x47ec +#define AFE_SECURE_MASK_CONN101_3 0x47f0 +#define AFE_SECURE_MASK_CONN101_4 0x47f4 +#define AFE_SECURE_MASK_CONN102 0x47f8 +#define AFE_SECURE_MASK_CONN102_1 0x47fc +#define AFE_SECURE_MASK_CONN102_2 0x4800 +#define AFE_SECURE_MASK_CONN102_3 0x4804 +#define AFE_SECURE_MASK_CONN102_4 0x4808 +#define AFE_SECURE_MASK_CONN103 0x480c +#define AFE_SECURE_MASK_CONN103_1 0x4810 +#define AFE_SECURE_MASK_CONN103_2 0x4814 +#define AFE_SECURE_MASK_CONN103_3 0x4818 +#define AFE_SECURE_MASK_CONN103_4 0x481c +#define AFE_SECURE_MASK_CONN104 0x4820 +#define AFE_SECURE_MASK_CONN104_1 0x4824 +#define AFE_SECURE_MASK_CONN104_2 0x4828 +#define AFE_SECURE_MASK_CONN104_3 0x482c +#define AFE_SECURE_MASK_CONN104_4 0x4830 +#define AFE_SECURE_MASK_CONN105 0x4834 +#define AFE_SECURE_MASK_CONN105_1 0x4838 +#define AFE_SECURE_MASK_CONN105_2 0x483c +#define AFE_SECURE_MASK_CONN105_3 0x4840 +#define AFE_SECURE_MASK_CONN105_4 0x4844 +#define AFE_SECURE_MASK_CONN106 0x4848 +#define AFE_SECURE_MASK_CONN106_1 0x484c +#define AFE_SECURE_MASK_CONN106_2 0x4850 +#define AFE_SECURE_MASK_CONN106_3 0x4854 +#define AFE_SECURE_MASK_CONN106_4 0x4858 +#define AFE_SECURE_MASK_CONN107 0x485c +#define AFE_SECURE_MASK_CONN107_1 0x4860 +#define AFE_SECURE_MASK_CONN107_2 0x4864 +#define AFE_SECURE_MASK_CONN107_3 0x4868 +#define AFE_SECURE_MASK_CONN107_4 0x486c +#define AFE_SECURE_MASK_CONN108 0x4870 +#define AFE_SECURE_MASK_CONN108_1 0x4874 +#define AFE_SECURE_MASK_CONN108_2 0x4878 +#define AFE_SECURE_MASK_CONN108_3 0x487c +#define AFE_SECURE_MASK_CONN108_4 0x4880 +#define AFE_SECURE_MASK_CONN109 0x4884 +#define AFE_SECURE_MASK_CONN109_1 0x4888 +#define AFE_SECURE_MASK_CONN109_2 0x488c +#define AFE_SECURE_MASK_CONN109_3 0x4890 +#define AFE_SECURE_MASK_CONN109_4 0x4894 +#define AFE_SECURE_MASK_CONN110 0x4898 +#define AFE_SECURE_MASK_CONN110_1 0x489c +#define AFE_SECURE_MASK_CONN110_2 0x48a0 +#define AFE_SECURE_MASK_CONN110_3 0x48a4 +#define AFE_SECURE_MASK_CONN110_4 0x48a8 +#define AFE_SECURE_MASK_CONN111 0x48ac +#define AFE_SECURE_MASK_CONN111_1 0x48b0 +#define AFE_SECURE_MASK_CONN111_2 0x48b4 +#define AFE_SECURE_MASK_CONN111_3 0x48b8 +#define AFE_SECURE_MASK_CONN111_4 0x48bc +#define AFE_SECURE_MASK_CONN112 0x48c0 +#define AFE_SECURE_MASK_CONN112_1 0x48c4 +#define AFE_SECURE_MASK_CONN112_2 0x48c8 +#define AFE_SECURE_MASK_CONN112_3 0x48cc +#define AFE_SECURE_MASK_CONN112_4 0x48d0 +#define AFE_SECURE_MASK_CONN113 0x48d4 +#define AFE_SECURE_MASK_CONN113_1 0x48d8 +#define AFE_SECURE_MASK_CONN113_2 0x48dc +#define AFE_SECURE_MASK_CONN113_3 0x48e0 +#define AFE_SECURE_MASK_CONN113_4 0x48e4 +#define AFE_SECURE_MASK_CONN114 0x48e8 +#define AFE_SECURE_MASK_CONN114_1 0x48ec +#define AFE_SECURE_MASK_CONN114_2 0x48f0 +#define AFE_SECURE_MASK_CONN114_3 0x48f4 +#define AFE_SECURE_MASK_CONN114_4 0x48f8 +#define AFE_SECURE_MASK_CONN115 0x48fc +#define AFE_SECURE_MASK_CONN115_1 0x4900 +#define AFE_SECURE_MASK_CONN115_2 0x4904 +#define AFE_SECURE_MASK_CONN115_3 0x4908 +#define AFE_SECURE_MASK_CONN115_4 0x490c +#define AFE_SECURE_MASK_CONN116 0x4910 +#define AFE_SECURE_MASK_CONN116_1 0x4914 +#define AFE_SECURE_MASK_CONN116_2 0x4918 +#define AFE_SECURE_MASK_CONN116_3 0x491c +#define AFE_SECURE_MASK_CONN116_4 0x4920 +#define AFE_SECURE_MASK_CONN117 0x4924 +#define AFE_SECURE_MASK_CONN117_1 0x4928 +#define AFE_SECURE_MASK_CONN117_2 0x492c +#define AFE_SECURE_MASK_CONN117_3 0x4930 +#define AFE_SECURE_MASK_CONN117_4 0x4934 +#define AFE_SECURE_MASK_CONN118 0x4938 +#define AFE_SECURE_MASK_CONN118_1 0x493c +#define AFE_SECURE_MASK_CONN118_2 0x4940 +#define AFE_SECURE_MASK_CONN118_3 0x4944 +#define AFE_SECURE_MASK_CONN118_4 0x4948 +#define AFE_SECURE_MASK_CONN119 0x494c +#define AFE_SECURE_MASK_CONN119_1 0x4950 +#define AFE_SECURE_MASK_CONN119_2 0x4954 +#define AFE_SECURE_MASK_CONN119_3 0x4958 +#define AFE_SECURE_MASK_CONN119_4 0x495c +#define AFE_SECURE_MASK_CONN120 0x4960 +#define AFE_SECURE_MASK_CONN120_1 0x4964 +#define AFE_SECURE_MASK_CONN120_2 0x4968 +#define AFE_SECURE_MASK_CONN120_3 0x496c +#define AFE_SECURE_MASK_CONN120_4 0x4970 +#define AFE_SECURE_MASK_CONN121 0x4974 +#define AFE_SECURE_MASK_CONN121_1 0x4978 +#define AFE_SECURE_MASK_CONN121_2 0x497c +#define AFE_SECURE_MASK_CONN121_3 0x4980 +#define AFE_SECURE_MASK_CONN121_4 0x4984 +#define AFE_SECURE_MASK_CONN122 0x4988 +#define AFE_SECURE_MASK_CONN122_1 0x498c +#define AFE_SECURE_MASK_CONN122_2 0x4990 +#define AFE_SECURE_MASK_CONN122_3 0x4994 +#define AFE_SECURE_MASK_CONN122_4 0x4998 +#define AFE_SECURE_MASK_CONN123 0x499c +#define AFE_SECURE_MASK_CONN123_1 0x49a0 +#define AFE_SECURE_MASK_CONN123_2 0x49a4 +#define AFE_SECURE_MASK_CONN123_3 0x49a8 +#define AFE_SECURE_MASK_CONN123_4 0x49ac +#define AFE_SECURE_MASK_CONN124 0x49b0 +#define AFE_SECURE_MASK_CONN124_1 0x49b4 +#define AFE_SECURE_MASK_CONN124_2 0x49b8 +#define AFE_SECURE_MASK_CONN124_3 0x49bc +#define AFE_SECURE_MASK_CONN124_4 0x49c0 +#define AFE_SECURE_MASK_CONN125 0x49c4 +#define AFE_SECURE_MASK_CONN125_1 0x49c8 +#define AFE_SECURE_MASK_CONN125_2 0x49cc +#define AFE_SECURE_MASK_CONN125_3 0x49d0 +#define AFE_SECURE_MASK_CONN125_4 0x49d4 +#define AFE_SECURE_MASK_CONN126 0x49d8 +#define AFE_SECURE_MASK_CONN126_1 0x49dc +#define AFE_SECURE_MASK_CONN126_2 0x49e0 +#define AFE_SECURE_MASK_CONN126_3 0x49e4 +#define AFE_SECURE_MASK_CONN126_4 0x49e8 +#define AFE_SECURE_MASK_CONN127 0x49ec +#define AFE_SECURE_MASK_CONN127_1 0x49f0 +#define AFE_SECURE_MASK_CONN127_2 0x49f4 +#define AFE_SECURE_MASK_CONN127_3 0x49f8 +#define AFE_SECURE_MASK_CONN127_4 0x49fc +#define AFE_SECURE_MASK_CONN128 0x4a00 +#define AFE_SECURE_MASK_CONN128_1 0x4a04 +#define AFE_SECURE_MASK_CONN128_2 0x4a08 +#define AFE_SECURE_MASK_CONN128_3 0x4a0c +#define AFE_SECURE_MASK_CONN128_4 0x4a10 +#define AFE_SECURE_MASK_CONN129 0x4a14 +#define AFE_SECURE_MASK_CONN129_1 0x4a18 +#define AFE_SECURE_MASK_CONN129_2 0x4a1c +#define AFE_SECURE_MASK_CONN129_3 0x4a20 +#define AFE_SECURE_MASK_CONN129_4 0x4a24 +#define AFE_SECURE_MASK_CONN130 0x4a28 +#define AFE_SECURE_MASK_CONN130_1 0x4a2c +#define AFE_SECURE_MASK_CONN130_2 0x4a30 +#define AFE_SECURE_MASK_CONN130_3 0x4a34 +#define AFE_SECURE_MASK_CONN130_4 0x4a38 +#define AFE_SECURE_MASK_CONN131 0x4a3c +#define AFE_SECURE_MASK_CONN131_1 0x4a40 +#define AFE_SECURE_MASK_CONN131_2 0x4a44 +#define AFE_SECURE_MASK_CONN131_3 0x4a48 +#define AFE_SECURE_MASK_CONN131_4 0x4a4c +#define AFE_SECURE_MASK_CONN132 0x4a50 +#define AFE_SECURE_MASK_CONN132_1 0x4a54 +#define AFE_SECURE_MASK_CONN132_2 0x4a58 +#define AFE_SECURE_MASK_CONN132_3 0x4a5c +#define AFE_SECURE_MASK_CONN132_4 0x4a60 +#define AFE_SECURE_MASK_CONN133 0x4a64 +#define AFE_SECURE_MASK_CONN133_1 0x4a68 +#define AFE_SECURE_MASK_CONN133_2 0x4a6c +#define AFE_SECURE_MASK_CONN133_3 0x4a70 +#define AFE_SECURE_MASK_CONN133_4 0x4a74 +#define AFE_SECURE_MASK_CONN134 0x4a78 +#define AFE_SECURE_MASK_CONN134_1 0x4a7c +#define AFE_SECURE_MASK_CONN134_2 0x4a80 +#define AFE_SECURE_MASK_CONN134_3 0x4a84 +#define AFE_SECURE_MASK_CONN134_4 0x4a88 +#define AFE_SECURE_MASK_CONN135 0x4a8c +#define AFE_SECURE_MASK_CONN135_1 0x4a90 +#define AFE_SECURE_MASK_CONN135_2 0x4a94 +#define AFE_SECURE_MASK_CONN135_3 0x4a98 +#define AFE_SECURE_MASK_CONN135_4 0x4a9c +#define AFE_SECURE_MASK_CONN136 0x4aa0 +#define AFE_SECURE_MASK_CONN136_1 0x4aa4 +#define AFE_SECURE_MASK_CONN136_2 0x4aa8 +#define AFE_SECURE_MASK_CONN136_3 0x4aac +#define AFE_SECURE_MASK_CONN136_4 0x4ab0 +#define AFE_SECURE_MASK_CONN137 0x4ab4 +#define AFE_SECURE_MASK_CONN137_1 0x4ab8 +#define AFE_SECURE_MASK_CONN137_2 0x4abc +#define AFE_SECURE_MASK_CONN137_3 0x4ac0 +#define AFE_SECURE_MASK_CONN137_4 0x4ac4 +#define AFE_SECURE_MASK_CONN138 0x4ac8 +#define AFE_SECURE_MASK_CONN138_1 0x4acc +#define AFE_SECURE_MASK_CONN138_2 0x4ad0 +#define AFE_SECURE_MASK_CONN138_3 0x4ad4 +#define AFE_SECURE_MASK_CONN138_4 0x4ad8 +#define AFE_SECURE_MASK_CONN139 0x4adc +#define AFE_SECURE_MASK_CONN139_1 0x4ae0 +#define AFE_SECURE_MASK_CONN139_2 0x4ae4 +#define AFE_SECURE_MASK_CONN139_3 0x4ae8 +#define AFE_SECURE_MASK_CONN139_4 0x4aec +#define AFE_SECURE_MASK_CONN_RS 0x4af0 +#define AFE_SECURE_MASK_CONN_RS_1 0x4af4 +#define AFE_SECURE_MASK_CONN_RS_2 0x4af8 +#define AFE_SECURE_MASK_CONN_RS_3 0x4afc +#define AFE_SECURE_MASK_CONN_RS_4 0x4b00 +#define AFE_SECURE_MASK_CONN_16BIT 0x4b04 +#define AFE_SECURE_MASK_CONN_16BIT_1 0x4b08 +#define AFE_SECURE_MASK_CONN_16BIT_2 0x4b0c +#define AFE_SECURE_MASK_CONN_16BIT_3 0x4b10 +#define AFE_SECURE_MASK_CONN_16BIT_4 0x4b14 +#define AFE_SECURE_MASK_CONN_24BIT 0x4b18 +#define AFE_SECURE_MASK_CONN_24BIT_1 0x4b1c +#define AFE_SECURE_MASK_CONN_24BIT_2 0x4b20 +#define AFE_SECURE_MASK_CONN_24BIT_3 0x4b24 +#define AFE_SECURE_MASK_CONN_24BIT_4 0x4b28 +#define AFE_GASRC0_NEW_CON0 0x4c40 +#define AFE_GASRC0_NEW_CON1 0x4c44 +#define AFE_GASRC0_NEW_CON2 0x4c48 +#define AFE_GASRC0_NEW_CON3 0x4c4c +#define AFE_GASRC0_NEW_CON4 0x4c50 +#define AFE_GASRC0_NEW_CON5 0x4c54 +#define AFE_GASRC0_NEW_CON6 0x4c58 +#define AFE_GASRC0_NEW_CON7 0x4c5c +#define AFE_GASRC0_NEW_CON8 0x4c60 +#define AFE_GASRC0_NEW_CON9 0x4c64 +#define AFE_GASRC0_NEW_CON10 0x4c68 +#define AFE_GASRC0_NEW_CON11 0x4c6c +#define AFE_GASRC0_NEW_CON12 0x4c70 +#define AFE_GASRC0_NEW_CON13 0x4c74 +#define AFE_GASRC0_NEW_CON14 0x4c78 +#define AFE_GASRC1_NEW_CON0 0x4c80 +#define AFE_GASRC1_NEW_CON1 0x4c84 +#define AFE_GASRC1_NEW_CON2 0x4c88 +#define AFE_GASRC1_NEW_CON3 0x4c8c +#define AFE_GASRC1_NEW_CON4 0x4c90 +#define AFE_GASRC1_NEW_CON5 0x4c94 +#define AFE_GASRC1_NEW_CON6 0x4c98 +#define AFE_GASRC1_NEW_CON7 0x4c9c +#define AFE_GASRC1_NEW_CON8 0x4ca0 +#define AFE_GASRC1_NEW_CON9 0x4ca4 +#define AFE_GASRC1_NEW_CON10 0x4ca8 +#define AFE_GASRC1_NEW_CON11 0x4cac +#define AFE_GASRC1_NEW_CON12 0x4cb0 +#define AFE_GASRC1_NEW_CON13 0x4cb4 +#define AFE_GASRC1_NEW_CON14 0x4cb8 +#define AFE_GASRC2_NEW_CON0 0x4cc0 +#define AFE_GASRC2_NEW_CON1 0x4cc4 +#define AFE_GASRC2_NEW_CON2 0x4cc8 +#define AFE_GASRC2_NEW_CON3 0x4ccc +#define AFE_GASRC2_NEW_CON4 0x4cd0 +#define AFE_GASRC2_NEW_CON5 0x4cd4 +#define AFE_GASRC2_NEW_CON6 0x4cd8 +#define AFE_GASRC2_NEW_CON7 0x4cdc +#define AFE_GASRC2_NEW_CON8 0x4ce0 +#define AFE_GASRC2_NEW_CON9 0x4ce4 +#define AFE_GASRC2_NEW_CON10 0x4ce8 +#define AFE_GASRC2_NEW_CON11 0x4cec +#define AFE_GASRC2_NEW_CON12 0x4cf0 +#define AFE_GASRC2_NEW_CON13 0x4cf4 +#define AFE_GASRC2_NEW_CON14 0x4cf8 +#define AFE_GASRC3_NEW_CON0 0x4d00 +#define AFE_GASRC3_NEW_CON1 0x4d04 +#define AFE_GASRC3_NEW_CON2 0x4d08 +#define AFE_GASRC3_NEW_CON3 0x4d0c +#define AFE_GASRC3_NEW_CON4 0x4d10 +#define AFE_GASRC3_NEW_CON5 0x4d14 +#define AFE_GASRC3_NEW_CON6 0x4d18 +#define AFE_GASRC3_NEW_CON7 0x4d1c +#define AFE_GASRC3_NEW_CON8 0x4d20 +#define AFE_GASRC3_NEW_CON9 0x4d24 +#define AFE_GASRC3_NEW_CON10 0x4d28 +#define AFE_GASRC3_NEW_CON11 0x4d2c +#define AFE_GASRC3_NEW_CON12 0x4d30 +#define AFE_GASRC3_NEW_CON13 0x4d34 +#define AFE_GASRC3_NEW_CON14 0x4d38 +#define AFE_GASRC4_NEW_CON0 0x4d40 +#define AFE_GASRC4_NEW_CON1 0x4d44 +#define AFE_GASRC4_NEW_CON2 0x4d48 +#define AFE_GASRC4_NEW_CON3 0x4d4c +#define AFE_GASRC4_NEW_CON4 0x4d50 +#define AFE_GASRC4_NEW_CON5 0x4d54 +#define AFE_GASRC4_NEW_CON6 0x4d58 +#define AFE_GASRC4_NEW_CON7 0x4d5c +#define AFE_GASRC4_NEW_CON8 0x4d60 +#define AFE_GASRC4_NEW_CON9 0x4d64 +#define AFE_GASRC4_NEW_CON10 0x4d68 +#define AFE_GASRC4_NEW_CON11 0x4d6c +#define AFE_GASRC4_NEW_CON12 0x4d70 +#define AFE_GASRC4_NEW_CON13 0x4d74 +#define AFE_GASRC4_NEW_CON14 0x4d78 +#define AFE_GASRC5_NEW_CON0 0x4d80 +#define AFE_GASRC5_NEW_CON1 0x4d84 +#define AFE_GASRC5_NEW_CON2 0x4d88 +#define AFE_GASRC5_NEW_CON3 0x4d8c +#define AFE_GASRC5_NEW_CON4 0x4d90 +#define AFE_GASRC5_NEW_CON5 0x4d94 +#define AFE_GASRC5_NEW_CON6 0x4d98 +#define AFE_GASRC5_NEW_CON7 0x4d9c +#define AFE_GASRC5_NEW_CON8 0x4da0 +#define AFE_GASRC5_NEW_CON9 0x4da4 +#define AFE_GASRC5_NEW_CON10 0x4da8 +#define AFE_GASRC5_NEW_CON11 0x4dac +#define AFE_GASRC5_NEW_CON12 0x4db0 +#define AFE_GASRC5_NEW_CON13 0x4db4 +#define AFE_GASRC5_NEW_CON14 0x4db8 +#define AFE_GASRC6_NEW_CON0 0x4dc0 +#define AFE_GASRC6_NEW_CON1 0x4dc4 +#define AFE_GASRC6_NEW_CON2 0x4dc8 +#define AFE_GASRC6_NEW_CON3 0x4dcc +#define AFE_GASRC6_NEW_CON4 0x4dd0 +#define AFE_GASRC6_NEW_CON5 0x4dd4 +#define AFE_GASRC6_NEW_CON6 0x4dd8 +#define AFE_GASRC6_NEW_CON7 0x4ddc +#define AFE_GASRC6_NEW_CON8 0x4de0 +#define AFE_GASRC6_NEW_CON9 0x4de4 +#define AFE_GASRC6_NEW_CON10 0x4de8 +#define AFE_GASRC6_NEW_CON11 0x4dec +#define AFE_GASRC6_NEW_CON12 0x4df0 +#define AFE_GASRC6_NEW_CON13 0x4df4 +#define AFE_GASRC6_NEW_CON14 0x4df8 +#define AFE_GASRC7_NEW_CON0 0x4e00 +#define AFE_GASRC7_NEW_CON1 0x4e04 +#define AFE_GASRC7_NEW_CON2 0x4e08 +#define AFE_GASRC7_NEW_CON3 0x4e0c +#define AFE_GASRC7_NEW_CON4 0x4e10 +#define AFE_GASRC7_NEW_CON5 0x4e14 +#define AFE_GASRC7_NEW_CON6 0x4e18 +#define AFE_GASRC7_NEW_CON7 0x4e1c +#define AFE_GASRC7_NEW_CON8 0x4e20 +#define AFE_GASRC7_NEW_CON9 0x4e24 +#define AFE_GASRC7_NEW_CON10 0x4e28 +#define AFE_GASRC7_NEW_CON11 0x4e2c +#define AFE_GASRC7_NEW_CON12 0x4e30 +#define AFE_GASRC7_NEW_CON13 0x4e34 +#define AFE_GASRC7_NEW_CON14 0x4e38 +#define AFE_GASRC8_NEW_CON0 0x4e40 +#define AFE_GASRC8_NEW_CON1 0x4e44 +#define AFE_GASRC8_NEW_CON2 0x4e48 +#define AFE_GASRC8_NEW_CON3 0x4e4c +#define AFE_GASRC8_NEW_CON4 0x4e50 +#define AFE_GASRC8_NEW_CON5 0x4e54 +#define AFE_GASRC8_NEW_CON6 0x4e58 +#define AFE_GASRC8_NEW_CON7 0x4e5c +#define AFE_GASRC8_NEW_CON8 0x4e60 +#define AFE_GASRC8_NEW_CON9 0x4e64 +#define AFE_GASRC8_NEW_CON10 0x4e68 +#define AFE_GASRC8_NEW_CON11 0x4e6c +#define AFE_GASRC8_NEW_CON12 0x4e70 +#define AFE_GASRC8_NEW_CON13 0x4e74 +#define AFE_GASRC8_NEW_CON14 0x4e78 +#define AFE_GASRC9_NEW_CON0 0x4e80 +#define AFE_GASRC9_NEW_CON1 0x4e84 +#define AFE_GASRC9_NEW_CON2 0x4e88 +#define AFE_GASRC9_NEW_CON3 0x4e8c +#define AFE_GASRC9_NEW_CON4 0x4e90 +#define AFE_GASRC9_NEW_CON5 0x4e94 +#define AFE_GASRC9_NEW_CON6 0x4e98 +#define AFE_GASRC9_NEW_CON7 0x4e9c +#define AFE_GASRC9_NEW_CON8 0x4ea0 +#define AFE_GASRC9_NEW_CON9 0x4ea4 +#define AFE_GASRC9_NEW_CON10 0x4ea8 +#define AFE_GASRC9_NEW_CON11 0x4eac +#define AFE_GASRC9_NEW_CON12 0x4eb0 +#define AFE_GASRC9_NEW_CON13 0x4eb4 +#define AFE_GASRC9_NEW_CON14 0x4eb8 +#define AFE_GASRC10_NEW_CON0 0x4ec0 +#define AFE_GASRC10_NEW_CON1 0x4ec4 +#define AFE_GASRC10_NEW_CON2 0x4ec8 +#define AFE_GASRC10_NEW_CON3 0x4ecc +#define AFE_GASRC10_NEW_CON4 0x4ed0 +#define AFE_GASRC10_NEW_CON5 0x4ed4 +#define AFE_GASRC10_NEW_CON6 0x4ed8 +#define AFE_GASRC10_NEW_CON7 0x4edc +#define AFE_GASRC10_NEW_CON8 0x4ee0 +#define AFE_GASRC10_NEW_CON9 0x4ee4 +#define AFE_GASRC10_NEW_CON10 0x4ee8 +#define AFE_GASRC10_NEW_CON11 0x4eec +#define AFE_GASRC10_NEW_CON12 0x4ef0 +#define AFE_GASRC10_NEW_CON13 0x4ef4 +#define AFE_GASRC10_NEW_CON14 0x4ef8 +#define AFE_GASRC11_NEW_CON0 0x4f00 +#define AFE_GASRC11_NEW_CON1 0x4f04 +#define AFE_GASRC11_NEW_CON2 0x4f08 +#define AFE_GASRC11_NEW_CON3 0x4f0c +#define AFE_GASRC11_NEW_CON4 0x4f10 +#define AFE_GASRC11_NEW_CON5 0x4f14 +#define AFE_GASRC11_NEW_CON6 0x4f18 +#define AFE_GASRC11_NEW_CON7 0x4f1c +#define AFE_GASRC11_NEW_CON8 0x4f20 +#define AFE_GASRC11_NEW_CON9 0x4f24 +#define AFE_GASRC11_NEW_CON10 0x4f28 +#define AFE_GASRC11_NEW_CON11 0x4f2c +#define AFE_GASRC11_NEW_CON12 0x4f30 +#define AFE_GASRC11_NEW_CON13 0x4f34 +#define AFE_GASRC11_NEW_CON14 0x4f38 +#define AFE_GASRC12_NEW_CON0 0x4f40 +#define AFE_GASRC12_NEW_CON1 0x4f44 +#define AFE_GASRC12_NEW_CON2 0x4f48 +#define AFE_GASRC12_NEW_CON3 0x4f4c +#define AFE_GASRC12_NEW_CON4 0x4f50 +#define AFE_GASRC12_NEW_CON5 0x4f54 +#define AFE_GASRC12_NEW_CON6 0x4f58 +#define AFE_GASRC12_NEW_CON7 0x4f5c +#define AFE_GASRC12_NEW_CON8 0x4f60 +#define AFE_GASRC12_NEW_CON9 0x4f64 +#define AFE_GASRC12_NEW_CON10 0x4f68 +#define AFE_GASRC12_NEW_CON11 0x4f6c +#define AFE_GASRC12_NEW_CON12 0x4f70 +#define AFE_GASRC12_NEW_CON13 0x4f74 +#define AFE_GASRC12_NEW_CON14 0x4f78 +#define AFE_GASRC13_NEW_CON0 0x4f80 +#define AFE_GASRC13_NEW_CON1 0x4f84 +#define AFE_GASRC13_NEW_CON2 0x4f88 +#define AFE_GASRC13_NEW_CON3 0x4f8c +#define AFE_GASRC13_NEW_CON4 0x4f90 +#define AFE_GASRC13_NEW_CON5 0x4f94 +#define AFE_GASRC13_NEW_CON6 0x4f98 +#define AFE_GASRC13_NEW_CON7 0x4f9c +#define AFE_GASRC13_NEW_CON8 0x4fa0 +#define AFE_GASRC13_NEW_CON9 0x4fa4 +#define AFE_GASRC13_NEW_CON10 0x4fa8 +#define AFE_GASRC13_NEW_CON11 0x4fac +#define AFE_GASRC13_NEW_CON12 0x4fb0 +#define AFE_GASRC13_NEW_CON13 0x4fb4 +#define AFE_GASRC13_NEW_CON14 0x4fb8 +#define AFE_GASRC14_NEW_CON0 0x4fc0 +#define AFE_GASRC14_NEW_CON1 0x4fc4 +#define AFE_GASRC14_NEW_CON2 0x4fc8 +#define AFE_GASRC14_NEW_CON3 0x4fcc +#define AFE_GASRC14_NEW_CON4 0x4fd0 +#define AFE_GASRC14_NEW_CON5 0x4fd4 +#define AFE_GASRC14_NEW_CON6 0x4fd8 +#define AFE_GASRC14_NEW_CON7 0x4fdc +#define AFE_GASRC14_NEW_CON8 0x4fe0 +#define AFE_GASRC14_NEW_CON9 0x4fe4 +#define AFE_GASRC14_NEW_CON10 0x4fe8 +#define AFE_GASRC14_NEW_CON11 0x4fec +#define AFE_GASRC14_NEW_CON12 0x4ff0 +#define AFE_GASRC14_NEW_CON13 0x4ff4 +#define AFE_GASRC14_NEW_CON14 0x4ff8 +#define AFE_GASRC15_NEW_CON0 0x5000 +#define AFE_GASRC15_NEW_CON1 0x5004 +#define AFE_GASRC15_NEW_CON2 0x5008 +#define AFE_GASRC15_NEW_CON3 0x500c +#define AFE_GASRC15_NEW_CON4 0x5010 +#define AFE_GASRC15_NEW_CON5 0x5014 +#define AFE_GASRC15_NEW_CON6 0x5018 +#define AFE_GASRC15_NEW_CON7 0x501c +#define AFE_GASRC15_NEW_CON8 0x5020 +#define AFE_GASRC15_NEW_CON9 0x5024 +#define AFE_GASRC15_NEW_CON10 0x5028 +#define AFE_GASRC15_NEW_CON11 0x502c +#define AFE_GASRC15_NEW_CON12 0x5030 +#define AFE_GASRC15_NEW_CON13 0x5034 +#define AFE_GASRC15_NEW_CON14 0x5038 +#define AFE_GASRC16_NEW_CON0 0x5040 +#define AFE_GASRC16_NEW_CON1 0x5044 +#define AFE_GASRC16_NEW_CON2 0x5048 +#define AFE_GASRC16_NEW_CON3 0x504c +#define AFE_GASRC16_NEW_CON4 0x5050 +#define AFE_GASRC16_NEW_CON5 0x5054 +#define AFE_GASRC16_NEW_CON6 0x5058 +#define AFE_GASRC16_NEW_CON7 0x505c +#define AFE_GASRC16_NEW_CON8 0x5060 +#define AFE_GASRC16_NEW_CON9 0x5064 +#define AFE_GASRC16_NEW_CON10 0x5068 +#define AFE_GASRC16_NEW_CON11 0x506c +#define AFE_GASRC16_NEW_CON12 0x5070 +#define AFE_GASRC16_NEW_CON13 0x5074 +#define AFE_GASRC16_NEW_CON14 0x5078 +#define AFE_GASRC17_NEW_CON0 0x5080 +#define AFE_GASRC17_NEW_CON1 0x5084 +#define AFE_GASRC17_NEW_CON2 0x5088 +#define AFE_GASRC17_NEW_CON3 0x508c +#define AFE_GASRC17_NEW_CON4 0x5090 +#define AFE_GASRC17_NEW_CON5 0x5094 +#define AFE_GASRC17_NEW_CON6 0x5098 +#define AFE_GASRC17_NEW_CON7 0x509c +#define AFE_GASRC17_NEW_CON8 0x50a0 +#define AFE_GASRC17_NEW_CON9 0x50a4 +#define AFE_GASRC17_NEW_CON10 0x50a8 +#define AFE_GASRC17_NEW_CON11 0x50ac +#define AFE_GASRC17_NEW_CON12 0x50b0 +#define AFE_GASRC17_NEW_CON13 0x50b4 +#define AFE_GASRC17_NEW_CON14 0x50b8 +#define AFE_GASRC18_NEW_CON0 0x50c0 +#define AFE_GASRC18_NEW_CON1 0x50c4 +#define AFE_GASRC18_NEW_CON2 0x50c8 +#define AFE_GASRC18_NEW_CON3 0x50cc +#define AFE_GASRC18_NEW_CON4 0x50d0 +#define AFE_GASRC18_NEW_CON5 0x50d4 +#define AFE_GASRC18_NEW_CON6 0x50d8 +#define AFE_GASRC18_NEW_CON7 0x50dc +#define AFE_GASRC18_NEW_CON8 0x50e0 +#define AFE_GASRC18_NEW_CON9 0x50e4 +#define AFE_GASRC18_NEW_CON10 0x50e8 +#define AFE_GASRC18_NEW_CON11 0x50ec +#define AFE_GASRC18_NEW_CON12 0x50f0 +#define AFE_GASRC18_NEW_CON13 0x50f4 +#define AFE_GASRC18_NEW_CON14 0x50f8 +#define AFE_GASRC19_NEW_CON0 0x5100 +#define AFE_GASRC19_NEW_CON1 0x5104 +#define AFE_GASRC19_NEW_CON2 0x5108 +#define AFE_GASRC19_NEW_CON3 0x510c +#define AFE_GASRC19_NEW_CON4 0x5110 +#define AFE_GASRC19_NEW_CON5 0x5114 +#define AFE_GASRC19_NEW_CON6 0x5118 +#define AFE_GASRC19_NEW_CON7 0x511c +#define AFE_GASRC19_NEW_CON8 0x5120 +#define AFE_GASRC19_NEW_CON9 0x5124 +#define AFE_GASRC19_NEW_CON10 0x5128 +#define AFE_GASRC19_NEW_CON11 0x512c +#define AFE_GASRC19_NEW_CON12 0x5130 +#define AFE_GASRC19_NEW_CON13 0x5134 +#define AFE_GASRC19_NEW_CON14 0x5138 + +/* ASYS_TOP_CON */ +#define ASYS_TOP_CON_A1SYS_TIMING_ON BIT(0) +#define ASYS_TOP_CON_A2SYS_TIMING_ON BIT(1) +#define ASYS_TOP_CON_A3SYS_TIMING_ON BIT(4) +#define ASYS_TOP_CON_A4SYS_TIMING_ON BIT(5) +#define ASYS_TOP_CON_26M_TIMING_ON BIT(2) + +/* PWR2_TOP_CON0 */ +#define PWR2_TOP_CON_DMIC8_SRC_SEL_MASK GENMASK(31, 29) +#define PWR2_TOP_CON_DMIC7_SRC_SEL_MASK GENMASK(28, 26) +#define PWR2_TOP_CON_DMIC6_SRC_SEL_MASK GENMASK(25, 23) +#define PWR2_TOP_CON_DMIC5_SRC_SEL_MASK GENMASK(22, 20) +#define PWR2_TOP_CON_DMIC4_SRC_SEL_MASK GENMASK(19, 17) +#define PWR2_TOP_CON_DMIC3_SRC_SEL_MASK GENMASK(16, 14) +#define PWR2_TOP_CON_DMIC2_SRC_SEL_MASK GENMASK(13, 11) +#define PWR2_TOP_CON_DMIC1_SRC_SEL_MASK GENMASK(10, 8) +#define PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(x) ((x) << 29) +#define PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(x) ((x) << 26) +#define PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(x) ((x) << 23) +#define PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(x) ((x) << 20) +#define PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(x) ((x) << 17) +#define PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(x) ((x) << 14) +#define PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(x) ((x) << 11) +#define PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(x) ((x) << 8) + +/* PWR2_TOP_CON1 */ +#define PWR2_TOP_CON1_DMIC_CKDIV_ON BIT(1) + +/* PCM_INTF_CON1 */ +#define PCM_INTF_CON1_SYNC_OUT_INV BIT(23) +#define PCM_INTF_CON1_BCLK_OUT_INV BIT(22) +#define PCM_INTF_CON1_CLK_OUT_INV_MASK GENMASK(23, 22) +#define PCM_INTF_CON1_SYNC_IN_INV BIT(21) +#define PCM_INTF_CON1_BCLK_IN_INV BIT(20) +#define PCM_INTF_CON1_CLK_IN_INV_MASK GENMASK(21, 20) +#define PCM_INTF_CON1_PCM_24BIT BIT(16) +#define PCM_INTF_CON1_PCM_16BIT (0 << 16) +#define PCM_INTF_CON1_PCM_BIT_MASK BIT(16) +#define PCM_INTF_CON1_PCM_WLEN_32BCK (0 << 14) +#define PCM_INTF_CON1_PCM_WLEN_64BCK BIT(14) +#define PCM_INTF_CON1_PCM_WLEN_MASK BIT(14) +#define PCM_INTF_CON1_SYNC_LENGTH(x) (((x) & 0x1f) << 9) +#define PCM_INTF_CON1_SYNC_LENGTH_MASK (0x1f << 9) +#define PCM_INTF_CON1_PCM_SLAVE BIT(5) +#define PCM_INTF_CON1_PCM_MASTER (0 << 5) +#define PCM_INTF_CON1_PCM_M_S_MASK BIT(5) +#define PCM_INTF_CON1_PCM_MODE(x) (((x) & 0x3) << 3) +#define PCM_INTF_CON1_PCM_MODE_MASK (0x3 << 3) +#define PCM_INTF_CON1_PCM_FMT(x) (((x) & 0x3) << 1) +#define PCM_INTF_CON1_PCM_FMT_MASK (0x3 << 1) +#define PCM_INTF_CON1_PCM_EN BIT(0) + +/* PCM_INTF_CON2 */ +#define PCM_INTF_CON2_CLK_DOMAIN_SEL(x) (((x) & 0x3) << 23) +#define PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK (0x3 << 23) +#define PCM_INTF_CON2_SYNC_FREQ_MODE(x) (((x) & 0x1f) << 12) +#define PCM_INTF_CON2_SYNC_FREQ_MODE_MASK (0x1f << 12) +#define PCM_INTF_CON2_PCM_TX2RX_LPBK BIT(8) + +/* AFE_MPHONE_MULTIx_CON0 */ +#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP BIT(3) +#define AFE_MPHONE_MULTI_CON0_16BIT_SWAP_MASK BIT(3) +#define AFE_MPHONE_MULTI_CON0_24BIT_DATA (0x1 << 1) +#define AFE_MPHONE_MULTI_CON0_16BIT_DATA (0x0 << 1) +#define AFE_MPHONE_MULIT_CON0_24BIT_DATA_MASK BIT(1) +#define AFE_MPHONE_MULTI_CON0_EN BIT(0) +#define AFE_MPHONE_MULTI_CON0_EN_MASK BIT(0) + +/* AFE_MPHONE_MULTIx_CON1 */ +#define AFE_MPHONE_MULTI_CON1_SYNC_ON BIT(24) +#define AFE_MPHONE_MULTI_CON1_SYNC_ON_MASK BIT(24) +#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS BIT(22) +#define AFE_MPHONE_MULTI_CON1_24BIT_SWAP_BYPASS_MASK BIT(22) +#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE (0x1 << 19) +#define AFE_MPHONE_MULTI_CON1_COMPACT_MODE (0x0 << 19) +#define AFE_MPHONE_MULTI_CON1_NON_COMPACT_MODE_MASK BIT(19) +#define AFE_MPHONE_MULTI_CON1_HBR_MODE BIT(18) +#define AFE_MPHONE_MULTI_CON1_HBR_MODE_MASK BIT(18) +#define AFE_MPHONE_MULTI_CON1_LRCK_32_CYCLE (0x2 << 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_24_CYCLE (0x1 << 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_16_CYCLE (0x0 << 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_CYCLE_SEL_MASK GENMASK(17, 16) +#define AFE_MPHONE_MULTI_CON1_LRCK_INV BIT(15) +#define AFE_MPHONE_MULTI_CON1_LRCK_INV_MASK BIT(15) +#define AFE_MPHONE_MULTI_CON1_DELAY_DATA BIT(14) +#define AFE_MPHONE_MULTI_CON1_DELAY_DATA_MASK BIT(14) +#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN BIT(13) +#define AFE_MPHONE_MULTI_CON1_LEFT_ALIGN_MASK BIT(13) +#define AFE_MPHONE_MULTI_CON1_BIT_NUM(x) ((((x) - 1) & 0x1f) << 8) +#define AFE_MPHONE_MULTI_CON1_BIT_NUM_MASK GENMASK(12, 8) +#define AFE_MPHONE_MULTI_CON1_BCK_INV BIT(6) +#define AFE_MPHONE_MULTI_CON1_BCK_INV_MASK BIT(6) +#define AFE_MPHONE_MULTI_CON1_CH_NUM(x) ((((x) >> 1) - 1) & 0x3) +#define AFE_MPHONE_MULTI_CON1_CH_NUM_MASK GENMASK(1, 0) + +/* AFE_MPHONE_MULTIx_CON2 */ +#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN BIT(19) +#define AFE_MPHONE_MULTI_CON2_SEL_SPDIFIN_MASK BIT(19) + +/* AFE_AUD_PAD_TOP */ +#define RG_RX_PROTOCOL2 BIT(3) +#define RG_RX_FIFO_ON BIT(0) + +/* AFE_ADDA_MTKAIF_CFG0 */ +#define MTKAIF_RXIF_CLKINV_ADC BIT(31) +#define MTKAIF_RXIF_PROTOCOL2 BIT(16) +#define MTKAIF_TXIF_PROTOCOL2 BIT(4) +#define MTKAIF_TXIF_8TO5 BIT(2) +#define MTKAIF_RXIF_8TO5 BIT(1) +#define MTKAIF_IF_LOOPBACK1 BIT(0) + +/* AFE_ADDA_MTKAIF_RX_CFG2 */ +#define MTKAIF_RXIF_DELAY_CYCLE(x) ((x) << 12) +#define MTKAIF_RXIF_DELAY_CYCLE_MASK GENMASK(15, 12) +#define MTKAIF_RXIF_DELAY_DATA BIT(8) +#define MTKAIF_RXIF_DELAY_DATA_SHIFT 8 + +/* AFE_ADDA_MTKAIF_SYNCWORD_CFG */ +#define ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE BIT(23) + +/* AFE_DMICx_UL_SRC_CON0 */ +#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH1(x) (((x) & 0x7) << 27) +#define AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH2(x) (((x) & 0x7) << 24) +#define AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL BIT(23) +#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL BIT(22) +#define AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL BIT(21) +#define AFE_DMIC_UL_VOICE_MODE(x) (((x) & 0x7) << 17) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_8K AFE_DMIC_UL_VOICE_MODE(0) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_16K AFE_DMIC_UL_VOICE_MODE(1) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_32K AFE_DMIC_UL_VOICE_MODE(2) +#define AFE_DMIC_UL_CON0_VOCIE_MODE_48K AFE_DMIC_UL_VOICE_MODE(3) +#define AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(x) (((x) & 0x7) << 7) +#define AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL BIT(10) +#define AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL BIT(1) +#define AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL BIT(0) + +/* ETDM_INx_AFIFO_CON */ +#define ETDM_IN_USE_AFIFO BIT(8) +#define ETDM_IN_AFIFO_CLOCK(x) ((x) << 5) +#define ETDM_IN_AFIFO_CLOCK_MASK GENMASK(7, 5) +#define ETDM_IN_AFIFO_MODE(x) ((x) << 0) +#define ETDM_IN_AFIFO_MODE_MASK GENMASK(4, 0) + +/* ETDM_COWORK_CON0 */ +#define ETDM_OUT1_SLAVE_SEL(x) ((x) << 20) +#define ETDM_OUT1_SLAVE_SEL_MASK GENMASK(23, 20) +#define ETDM_OUT1_SLAVE_SEL_SHIFT 20 + +/* ETDM_COWORK_CON1 */ +#define ETDM_IN1_SDATA_SEL(x) ((x) << 20) +#define ETDM_IN1_SDATA_SEL_MASK GENMASK(23, 20) +#define ETDM_IN1_SDATA_SEL_SHIFT 20 +#define ETDM_IN1_SDATA0_SEL(x) ((x) << 16) +#define ETDM_IN1_SDATA0_SEL_MASK GENMASK(19, 16) +#define ETDM_IN1_SDATA0_SEL_SHIFT 16 +#define ETDM_IN1_SLAVE_SEL(x) ((x) << 8) +#define ETDM_IN1_SLAVE_SEL_MASK GENMASK(11, 8) +#define ETDM_IN1_SLAVE_SEL_SHIFT 8 + +/* ETDM_COWORK_CON2 */ +#define ETDM_IN2_SLAVE_SEL(x) ((x) << 24) +#define ETDM_IN2_SLAVE_SEL_MASK GENMASK(27, 24) +#define ETDM_IN2_SLAVE_SEL_SHIFT 24 +#define ETDM_OUT3_SLAVE_SEL(x) ((x) << 20) +#define ETDM_OUT3_SLAVE_SEL_MASK GENMASK(23, 20) +#define ETDM_OUT3_SLAVE_SEL_SHIFT 20 +#define ETDM_OUT2_SLAVE_SEL(x) ((x) << 8) +#define ETDM_OUT2_SLAVE_SEL_MASK GENMASK(11, 8) +#define ETDM_OUT2_SLAVE_SEL_SHIFT 8 + +/* ETDM_COWORK_CON3 */ +#define ETDM_IN2_SDATA_SEL(x) ((x) << 4) +#define ETDM_IN2_SDATA_SEL_MASK GENMASK(7, 4) +#define ETDM_IN2_SDATA_SEL_SHIFT 4 +#define ETDM_IN2_SDATA0_SEL(x) ((x) << 0) +#define ETDM_IN2_SDATA0_SEL_MASK GENMASK(3, 0) +#define ETDM_IN2_SDATA0_SEL_SHIFT 0 + +/* ETDM_x_CONx */ +#define ETDM_CON0_CH_NUM(x) (((x) - 1) << 23) +#define ETDM_CON0_CH_NUM_MASK GENMASK(27, 23) +#define ETDM_CON0_WORD_LEN(x) (((x) - 1) << 16) +#define ETDM_CON0_WORD_LEN_MASK GENMASK(20, 16) +#define ETDM_CON0_BIT_LEN(x) (((x) - 1) << 11) +#define ETDM_CON0_BIT_LEN_MASK GENMASK(15, 11) +#define ETDM_CON0_FORMAT(x) ((x) << 6) +#define ETDM_CON0_FORMAT_MASK GENMASK(8, 6) +#define ETDM_CON0_SLAVE_MODE BIT(5) +#define ETDM_CON0_EN BIT(0) + +#define ETDM_OUT_CON0_RELATCH_DOMAIN(x) ((x) << 28) +#define ETDM_OUT_CON0_RELATCH_DOMAIN_MASK GENMASK(29, 28) + +#define ETDM_CON1_LRCK_AUTO_MODE BIT(29) +#define ETDM_CON1_LRCK_WIDTH(x) (((x) - 1) << 20) +#define ETDM_CON1_LRCK_WIDTH_MASK GENMASK(29, 20) +#define ETDM_CON1_MCLK_OUTPUT BIT(16) + +#define ETDM_IN_CON2_MULTI_IP_2CH_MODE BIT(31) +#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH(x) (((x) - 1) << 15) +#define ETDM_IN_CON2_MULTI_IP_TOTAL_CH_MASK GENMASK(19, 15) +#define ETDM_IN_CON2_CLOCK(x) ((x) << 10) +#define ETDM_IN_CON2_CLOCK_MASK GENMASK(12, 10) +#define ETDM_IN_CON2_CLOCK_SHIFT 10 +#define ETDM_IN_CON2_UPDATE_GAP(x) ((x) << 5) +#define ETDM_IN_CON2_UPDATE_GAP_MASK GENMASK(9, 5) + +#define ETDM_OUT_CON2_LRCK_DELAY_BCK_INV BIT(30) +#define ETDM_OUT_CON2_LRCK_DELAY_0P5T_EN BIT(29) + +#define ETDM_IN_CON3_FS(x) ((x) << 26) +#define ETDM_IN_CON3_FS_MASK GENMASK(30, 26) +#define ETDM_IN_CON3_DISABLE_OUT(x) BIT(((x) & 0xffff)) +#define ETDM_IN_CON3_DISABLE_OUT_MASK GENMASK(15, 0) + +#define ETDM_IN_CON4_MASTER_LRCK_INV BIT(19) +#define ETDM_IN_CON4_MASTER_BCK_INV BIT(18) +#define ETDM_IN_CON4_SLAVE_LRCK_INV BIT(17) +#define ETDM_IN_CON4_SLAVE_BCK_INV BIT(16) + +#define ETDM_OUT_CON4_RELATCH_EN(x) ((x) << 24) +#define ETDM_OUT_CON4_RELATCH_EN_MASK GENMASK(28, 24) +#define ETDM_OUT_CON4_CLOCK(x) ((x) << 6) +#define ETDM_OUT_CON4_CLOCK_MASK GENMASK(8, 6) +#define ETDM_OUT_CON4_CLOCK_SHIFT 6 +#define ETDM_OUT_CON4_FS(x) ((x) << 0) +#define ETDM_OUT_CON4_FS_MASK GENMASK(4, 0) + +#define ETDM_IN_CON5_LR_SWAP(x) BIT(((x) & 0xffff) + 16) +#define ETDM_IN_CON5_LR_SWAP_MASK GENMASK(31, 16) +#define ETDM_IN_CON5_ENABLE_ODD(x) BIT(((x) & 0xffff)) +#define ETDM_IN_CON5_ENABLE_ODD_MASK GENMASK(15, 0) + +#define ETDM_OUT_CON5_MASTER_LRCK_INV BIT(10) +#define ETDM_OUT_CON5_MASTER_BCK_INV BIT(9) +#define ETDM_OUT_CON5_SLAVE_LRCK_INV BIT(8) +#define ETDM_OUT_CON5_SLAVE_BCK_INV BIT(7) + +/* AFE_DPTX_CON */ +#define AFE_DPTX_CON_CH_EN(x) (((x) & 0xf) << 8) +#define AFE_DPTX_CON_CH_EN_2CH (AFE_DPTX_CON_CH_EN(GENMASK(1, 0))) +#define AFE_DPTX_CON_CH_EN_4CH (AFE_DPTX_CON_CH_EN(GENMASK(3, 0))) +#define AFE_DPTX_CON_CH_EN_6CH (AFE_DPTX_CON_CH_EN(GENMASK(5, 0))) +#define AFE_DPTX_CON_CH_EN_8CH (AFE_DPTX_CON_CH_EN(GENMASK(7, 0))) +#define AFE_DPTX_CON_CH_EN_MASK GENMASK(15, 8) +#define AFE_DPTX_CON_16BIT BIT(2) +#define AFE_DPTX_CON_24BIT (0 << 2) +#define AFE_DPTX_CON_16BIT_MASK BIT(2) +#define AFE_DPTX_CON_CH_NUM(x) (((x) & 0x1) << 1) +#define AFE_DPTX_CON_CH_NUM_2CH (AFE_DPTX_CON_CH_NUM(0)) +#define AFE_DPTX_CON_CH_NUM_8CH (AFE_DPTX_CON_CH_NUM(1)) +#define AFE_DPTX_CON_CH_NUM_MASK (0x1 << 1) +#define AFE_DPTX_CON_ON BIT(0) +#define AFE_DPTX_CON_ON_MASK BIT(0) + +/* AFE_ADDA_UL_DL_CON0 */ +#define ADDA_AFE_ON_SHIFT 0 + +/* AFE_ADDA_DL_SRC2_CON0 */ +#define DL_2_INPUT_MODE_CTL(x) ((x) << 28) +#define DL_2_INPUT_MODE_CTL_MASK GENMASK(31, 28) +#define DL_2_CH1_SATURATION_EN_CTL BIT(27) +#define DL_2_CH2_SATURATION_EN_CTL BIT(26) +#define DL_2_MUTE_CH1_OFF_CTL_PRE BIT(12) +#define DL_2_MUTE_CH2_OFF_CTL_PRE BIT(11) +#define DL_2_VOICE_MODE_CTL_PRE BIT(5) +#define DL_2_GAIN_ON_CTL_PRE_SHIFT 1 +#define DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT 0 + +/* AFE_ADDA_DL_SRC2_CON1 */ +#define DL_2_GAIN_CTL_PRE(x) ((x) << 16) +#define DL_2_GAIN_CTL_PRE_MASK GENMASK(31, 16) +#define DL_2_GAIN_CTL_PRE_SHIFT 16 + +/* AFE_ADDA_TOP_CON0 */ +#define C_LOOPBACK_MODE_CTL_MASK GENMASK(15, 12) +#define DL_INPUT_FROM_SINEGEN (4 << 12) + +/* AFE_ADDA_DL_SDM_DCCOMP_CON */ +#define DL_USE_NEW_2ND_SDM BIT(30) +#define ATTGAIN_CTL_MASK GENMASK(5, 0) + +/* AFE_ADDA_UL_SRC_CON0 */ +#define UL_MODE_3P25M_CH2_CTL BIT(22) +#define UL_MODE_3P25M_CH1_CTL BIT(21) +#define UL_VOICE_MODE_CTL(x) ((x) << 17) +#define UL_VOICE_MODE_CTL_MASK GENMASK(19, 17) +#define UL_LOOPBACK_MODE_CTL BIT(2) +#define UL_SDM3_LEVEL_CTL BIT(1) +#define UL_SRC_ON_TMP_CTL_SHIFT 0 + +#endif diff --git a/src/platform/mt8195/include/platform/platform.h b/src/platform/mt8195/include/platform/platform.h new file mode 100644 index 000000000000..dba4a22805a4 --- /dev/null +++ b/src/platform/mt8195/include/platform/platform.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) +#define LPSRAM_SIZE 16384 + +/*MTK_TODO : use correct ipc interrupt , mailbox int group 16 bit 0*/ +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT IRQ_MASK_GROUP16 +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#define SRAM_REG_FW_STATUS 0x4 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + trigger_irq_to_host_req(); +} + +/** + * \brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/mt8195/include/platform/trace/trace.h b/src/platform/mt8195/include/platform/trace/trace.h new file mode 100644 index 000000000000..a1bd3c149846 --- /dev/null +++ b/src/platform/mt8195/include/platform/trace/trace.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/io.h> +#include <platform/drivers/mt_reg_base.h> + +#define ADSP_TRACE_POINT (0x2) + +/* Platform defined trace code */ +#define platform_trace_point(__x) \ + do { \ + io_reg_write(MTK_DSP_MBOX_OUT_CMD_MSG0(2), __x); \ + io_reg_write(MTK_DSP_MBOX_OUT_CMD(2), ADSP_TRACE_POINT);\ + } while (0) + +#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/mt8195/lib/CMakeLists.txt b/src/platform/mt8195/lib/CMakeLists.txt new file mode 100644 index 000000000000..ef71f8eea6cd --- /dev/null +++ b/src/platform/mt8195/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dma.c + memory.c + dai.c +) diff --git a/src/platform/mt8195/lib/clk.c b/src/platform/mt8195/lib/clk.c new file mode 100644 index 000000000000..1514b9d9307d --- /dev/null +++ b/src/platform/mt8195/lib/clk.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <rtos/sof.h> + +SOF_DEFINE_REG_UUID(clkdrv_mt8195); + +DECLARE_TR_CTX(clkdrv_tr, SOF_UUID(clkdrv_mt8195_uuid), LOG_LEVEL_INFO); + +static int dsppll_enable; /* default no adsp clock*/ +static int adsp_clock; + +/*Use external Ostimer*/ +const struct freq_table platform_cpu_freq[] = { + { 13000000, 26000}, + { 26000000, 26000}, + { 370000000, 26000}, + { 540000000, 26000}, + { 720000000, 26000}, +}; + +const uint32_t cpu_freq_enc[] = { + 13000000, + 26000000, + 0x831C7628, + 0x8214C4ED, + 0x821BB13C, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static inline void clk_setl(uint32_t addr, uint32_t val) +{ + io_reg_write(addr, io_reg_read(addr) | (val)); +} + +static inline void clk_clrl(uint32_t addr, uint32_t val) +{ + io_reg_write(addr, io_reg_read(addr) & ~(val)); +} + +static inline int dsp_clk_value_convert(int value) +{ + int ret; + + switch (value) { + case DSP_CLK_13M: + case DSP_CLK_26M: + ret = CLK_ADSP_SEL_26M; + break; + case DSP_CLK_PLL_370M: + case DSP_CLK_PLL_540M: + case DSP_CLK_PLL_720M: + ret = CLK_ADSP_SEL_ADSPPLL; + break; + default: + ret = CLK_ADSP_SEL_26M; + break; + } + + return ret; +} + +static void clk_dsppll_enable(void) +{ + tr_dbg(&clkdrv_tr, "entry"); + + io_reg_update_bits(AUDIODSP_CK_CG, 0x1 << RG_AUDIODSP_SW_CG, 0x0); + clk_setl(DSPPLL_CON4, PLL_PWR_ON); + wait_delay_us(1); + clk_clrl(DSPPLL_CON4, PLL_ISO_EN); + wait_delay_us(1); + clk_setl(DSPPLL_CON0, PLL_EN); + wait_delay_us(20); + dsppll_enable = 1; +} + +static void clk_dsppll_disable(void) +{ + tr_dbg(&clkdrv_tr, "entry"); + + clk_clrl(DSPPLL_CON0, PLL_EN); + wait_delay_us(1); + clk_setl(DSPPLL_CON4, PLL_ISO_EN); + wait_delay_us(1); + clk_clrl(DSPPLL_CON4, PLL_PWR_ON); + dsppll_enable = 0; +} + +static int dsppll_get_enable(void) +{ + tr_dbg(&clkdrv_tr, "dsppll_enable=%d.\n", dsppll_enable); + + return dsppll_enable; +} + +static int set_mux_sel(enum mux_id_t mux_id, uint32_t value) +{ + switch (mux_id) { + case MUX_CLK_ADSP_SEL: + io_reg_update_bits(CLK_CFG_22_CLR, (0xF << 0), (0xF << 0)); + io_reg_update_bits(CLK_CFG_22_SET, (0xF << 0), (value << 0)); + io_reg_write(CLK_CFG_UPDATE2, 1 << CLK_UPDATE_ADSP_CK); + + tr_dbg(&clkdrv_tr, "adspclk_mux=%x, CLK_CFG_22=0x%08x\n", + value, io_reg_read(CLK_CFG_22)); + break; + case MUX_CLK_AUDIO_LOCAL_BUS_SEL: + io_reg_update_bits(CLK_CFG_28_CLR, (0xF << 16), (0xF << 16)); + io_reg_update_bits(CLK_CFG_28_SET, (0xF << 16), (value << 16)); + io_reg_write(CLK_CFG_UPDATE3, 1 << CLK_UPDATE_AUDIO_LOCAL_BUS_CK); + + tr_dbg(&clkdrv_tr, "audio_local_bus_clk_mux=%x, CLK_CFG_28=0x%08x\n", + value, io_reg_read(CLK_CFG_28)); + break; + default: + tr_dbg(&clkdrv_tr, "error: unknown mux_id (%d)\n", mux_id); + break; + } + + return 0; +} + +static int clock_platform_set_cpu_freq(int clock, int freq_idx) +{ + uint32_t enc = cpu_freq_enc[freq_idx]; + int clk_mux; + int adsp_clk_req = platform_cpu_freq[freq_idx].freq; + + if (adsp_clock == adsp_clk_req) + return 0; + + tr_info(&clkdrv_tr, "%d\n", adsp_clk_req); + + /* convert res manager value to driver map */ + clk_mux = dsp_clk_value_convert(freq_idx); + + if (enc > 26000000) { + /* adsp pll */ + if (!dsppll_get_enable()) { + clk_dsppll_enable(); + set_mux_sel(MUX_CLK_ADSP_SEL, clk_mux); + set_mux_sel(MUX_CLK_AUDIO_LOCAL_BUS_SEL, + CLK_AUDIO_LOCAL_BUS_SEL_MAINPLL_D_7); + } + /* set adsp pll clock */ + io_reg_update_bits(DSPPLL_CON2, 0xffffffff, enc); + } else { + /* clk26m */ + if (dsppll_get_enable()) { + set_mux_sel(MUX_CLK_AUDIO_LOCAL_BUS_SEL, CLK_AUDIO_LOCAL_BUS_SEL_26M); + set_mux_sel(MUX_CLK_ADSP_SEL, clk_mux); + clk_dsppll_disable(); + } + } + + adsp_clock = adsp_clk_req; + + return 0; +} + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + 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 = clock_platform_set_cpu_freq, + }; + } + + adsp_clock = 0; + dsppll_enable = 0; +} diff --git a/src/platform/mt8195/lib/dai.c b/src/platform/mt8195/lib/dai.c new file mode 100644 index 000000000000..c385331489a6 --- /dev/null +++ b/src/platform/mt8195/lib/dai.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +#include <sof/drivers/afe-dai.h> +#include <mt8195-afe-common.h> + +static int afe_dai_handshake[MT8195_DAI_NUM] = { + AFE_HANDSHAKE(MT8195_AFE_IO_ETDM2_OUT, MT8195_IRQ_13, MT8195_MEMIF_DL2), + AFE_HANDSHAKE(MT8195_AFE_IO_ETDM1_OUT, MT8195_IRQ_14, MT8195_MEMIF_DL3), + AFE_HANDSHAKE(MT8195_AFE_IO_UL_SRC1, MT8195_IRQ_21, MT8195_MEMIF_UL4), + AFE_HANDSHAKE(MT8195_AFE_IO_ETDM2_IN, MT8195_IRQ_22, MT8195_MEMIF_UL5), +}; + +static SHARED_DATA struct dai afe_dai[MT8195_DAI_NUM]; + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_MEDIATEK_AFE, + .dai_array = afe_dai, + .num_dais = ARRAY_SIZE(afe_dai), + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti), +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(afe_dai); i++) { + k_spinlock_init(&afe_dai[i].lock); + afe_dai[i].index = AFE_HS_GET_DAI(afe_dai_handshake[i]); + afe_dai[i].drv = &afe_dai_driver; + /* TODO, fifo[0] change to target playback or capture */ + afe_dai[i].plat_data.fifo[0].handshake = afe_dai_handshake[i]; + } + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/mt8195/lib/dma.c b/src/platform/mt8195/lib/dma.c new file mode 100644 index 000000000000..7a9719e8a30c --- /dev/null +++ b/src/platform/mt8195/lib/dma.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/drivers/afe-memif.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +#include <mt8195-afe-regs.h> +#include <mt8195-afe-common.h> + +extern struct dma_ops dummy_dma_ops; + +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .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, +}, +{ + .plat_data = { + .id = DMA_ID_AFE_MEMIF, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_AFE_MEMIF, + .base = AFE_BASE_ADDR, + .channels = MT8195_MEMIF_NUM, + }, + .ops = &memif_ops, +}, +}; + +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)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/mt8195/lib/memory.c b/src/platform/mt8195/lib/memory.c new file mode 100644 index 000000000000..b2d545ff6f1d --- /dev/null +++ b/src/platform/mt8195/lib/memory.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; +static SHARED_DATA struct block_hdr mod_block4096[HEAP_RT_COUNT4096]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), + BLOCK_DEF(4096, HEAP_RT_COUNT4096, mod_block4096), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/mt8195/mt8195.x.in b/src/platform/mt8195/mt8195.x.in new file mode 100644 index 000000000000..e34db20246cd --- /dev/null +++ b/src/platform/mt8195/mt8195.x.in @@ -0,0 +1,515 @@ +/* + * Linker Script for mt8195 MediaTek + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_sram0 : + org = SRAM0_BASE, + len = SRAM0_SIZE + sof_sram1 : + org = SRAM1_BASE, + len = SRAM1_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_sram0_phdr PT_LOAD; + sof_sram1_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000100; +_memmap_cacheattr_wt_base = 0x00000300; +_memmap_cacheattr_bp_base = 0x00000400; +_memmap_cacheattr_unused_mask = 0xFFFFF0FF; +_memmap_cacheattr_wb_trapnull = 0x44444140; +_memmap_cacheattr_wba_trapnull = 0x44444140; +_memmap_cacheattr_wbna_trapnull = 0x44444240; +_memmap_cacheattr_wt_trapnull = 0x44444340; +_memmap_cacheattr_bp_trapnull = 0x44444440; +_memmap_cacheattr_wb_strict = 0x00000100; +_memmap_cacheattr_wt_strict = 0x00000300; +_memmap_cacheattr_bp_strict = 0x00000400; +_memmap_cacheattr_wb_allvalid = 0x44444144; +_memmap_cacheattr_wt_allvalid = 0x44444344; +_memmap_cacheattr_bp_allvalid = 0x44444444; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + *(.clib.rodata) + __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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_sram0 :sof_sram0_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.clib.data) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + .clib.data : ALIGN(4) + { + _clib_data_start = ABSOLUTE(.); + *(.clib.data) + . = ALIGN (4); + _clib_data_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + .clib.rodata : ALIGN(4) + { + _clib_rodata_start = ABSOLUTE(.); + *(.clib.rodata) + . = ALIGN (4); + _clib_rodata_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sram0 :sof_sram0_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + KEEP (*(.fw_ready_metadata)) + } >sof_sram0 :sof_sram0_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr +} diff --git a/src/platform/mt8195/platform.c b/src/platform/mt8195/platform.c new file mode 100644 index 000000000000..7e713290437d --- /dev/null +++ b/src/platform/mt8195/platform.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2021 MediaTek. All rights reserved. + * + * Author: YC Hung <yc.hung@mediatek.com> + * Allen-KH Cheng <allen-kh.cheng@mediatek.com> + */ + +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <sof/drivers/edma.h> +#include <rtos/interrupt.h> +#include <sof/ipc/msg.h> +#include <rtos/timer.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <platform/drivers/timer.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <sof_versions.h> +#include <errno.h> +#include <stdint.h> +#include <xtensa/hal.h> + +struct sof; + +static const struct sof_ipc_fw_ready ready + __section(".fw_ready") = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_MTK_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_MTK_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, /* TODO: set later */ + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, /* TODO: set later */ + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, /* TODO: set later */ + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, /* TODO: set later */ + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, /* TODO: set later */ + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, /* TODO: set later */ + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + } +}; + +static SHARED_DATA struct timer timer_shared = { + .id = OSTIMER0, + .irq = LX_ADSP_TIMTER_IRQ0_B, +}; + +/* Override the default MPU setup. This table matches the memory map + * of the 'sample_controller' core and will need to be modified for + * other cores. + * NOTE: This table sets up all of external memory as shared uncached. + * For best results, edit the LSP memory map to create a separate + * section in shared memory, place all sections that need to be uncached + * into that section, and only map that section uncached. See README + * for more details. + */ +const unsigned int __xt_mpu_init_table_size __attribute__((section(".ResetVector.text"))) = 11; + +const struct xthal_MPU_entry __xt_mpu_init_table[] __attribute__((section(".ResetVector.text"))) = { + XTHAL_MPU_ENTRY(0x00000000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x0C000000, 1, XTHAL_AR_RWrw, + XTHAL_MEM_DEVICE), /* MCU & DBG Registers read/write */ + XTHAL_MPU_ENTRY(0x0F000000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x10000000, 1, XTHAL_AR_RWrw, + XTHAL_MEM_DEVICE), /* DSP register: read/write */ + XTHAL_MPU_ENTRY(0x12000000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x40000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_WRITEBACK), /* DSP SRAM: read/write/execute writeback */ + XTHAL_MPU_ENTRY(0x40040000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ + XTHAL_MPU_ENTRY(0x60000000, 1, XTHAL_AR_RWXrwx, + XTHAL_MEM_WRITEBACK), /* DRAM: read/write/execute writeback */ + XTHAL_MPU_ENTRY(0x60800000, 1, XTHAL_AR_RWrw, + XTHAL_MEM_WRITEBACK), /* DRAM: read/write writeback */ + XTHAL_MPU_ENTRY(0x61000000, 1, XTHAL_AR_RWrw, + XTHAL_MEM_DEVICE), /* DMA: read/write writeback */ + XTHAL_MPU_ENTRY(0x61100000, 1, XTHAL_AR_NONE, + XTHAL_MEM_DEVICE), /* illegal: no access */ +}; + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + /* now interrupt host to tell it we are done booting */ + trigger_irq_to_host_req(); + + /* boot now complete so we can relax the CPU */ + /* For now skip this to gain more processing performance + * for SRC component. + */ + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = platform_shared_get(&timer_shared, sizeof(timer_shared)); + sof->cpu_timers = sof->platform_timer; + + platform_interrupt_init(); + platform_clock_init(sof); + scheduler_init_edf(); + + /* init low latency domains and schedulers */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + + platform_timer_start(sof->platform_timer); + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); + + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* Init platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], 1, + PLATFORM_DEFAULT_CLOCK, false); + scheduler_init_ll(sof->platform_dma_domain); + + /* initialize the host IPC mechanims */ + ipc_init(sof); + + ret = dai_init(sof); + if (ret < 0) + return -ENODEV; + +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + dma_trace_init_complete(sof->dmat); +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} + +#ifdef __XCC__ +/* This is a stub for the Xtensa libc (not their newlib version), + * which inexplicably wants to pull in an unlink() implementation when + * linked against the C++ standard library. Obviously nothing in SOF + * uses the C library filesystem layer, this is just spurious. + */ +int __attribute__((weak)) _unlink_r(struct _reent *ptr, const char *file); +int __attribute__((weak)) _unlink_r(struct _reent *ptr, const char *file) +{ + return -1; +} +#endif diff --git a/src/platform/mt8196/CMakeLists.txt b/src/platform/mt8196/CMakeLists.txt new file mode 100644 index 000000000000..f7a68fd4ea31 --- /dev/null +++ b/src/platform/mt8196/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) + +add_local_sources(sof platform.c afe-platform.c) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8196/include/arch) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8196/include/platform) diff --git a/src/platform/mt8196/afe-platform.c b/src/platform/mt8196/afe-platform.c new file mode 100755 index 000000000000..3d9452772ba7 --- /dev/null +++ b/src/platform/mt8196/afe-platform.c @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Darren Ye <darren.ye@mediatek.com> + */ + +#include <sof/common.h> +#include <errno.h> +#include <sof/drivers/afe-drv.h> +#include <mt8196-afe-reg.h> +#include <mt8196-afe-common.h> + +/* + * AFE: Audio Front-End + * + * frontend (memif): + * memory interface + * UL (uplink for capture) + * DL (downlink for playback) + * backend: + * TDM In + * TDM Out + * DMIC + * GASRC + * I2S Out + * I2S In + * etc. + * interconn: + * inter-connection, + * connect frontends and backends as DSP path + */ + +static const struct mtk_base_memif_data memif_data[MT8196_MEMIF_NUM] = { + [MT8196_MEMIF_DL1] = { + .name = "DL1", + .id = MT8196_MEMIF_DL1, + .reg_ofs_base = AFE_DL1_BASE, + .reg_ofs_cur = AFE_DL1_CUR, + .reg_ofs_end = AFE_DL1_END, + .reg_ofs_base_msb = AFE_DL1_BASE_MSB, + .reg_ofs_cur_msb = AFE_DL1_CUR_MSB, + .reg_ofs_end_msb = AFE_DL1_END_MSB, + .fs_reg = AFE_DL1_CON0, + .fs_shift = DL1_SEL_FS_SFT, + .fs_maskbit = DL1_SEL_FS_MASK, + .mono_reg = AFE_DL1_CON0, + .mono_shift = DL1_MONO_SFT, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DL1_CON0, + .enable_shift = DL1_ON_SFT, + .hd_reg = AFE_DL1_CON0, + .hd_shift = DL1_HD_MODE_SFT, + .hd_align_reg = AFE_DL1_CON0, + .hd_align_mshift = DL1_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .ch_num_reg = -1, + .msb_reg = -1, + .msb_shift = -1, + .pbuf_reg = AFE_DL1_CON0, + .pbuf_mask = DL1_PBUF_SIZE_MASK, + .pbuf_shift = DL1_PBUF_SIZE_SFT, + .minlen_reg = AFE_DL1_CON0, + .minlen_mask = DL1_MINLEN_MASK, + .minlen_shift = DL1_MINLEN_SFT, + }, + [MT8196_MEMIF_DL_24CH] = { + .name = "DL_24CH", + .id = MT8196_MEMIF_DL_24CH, + .reg_ofs_base = AFE_DL_24CH_BASE, + .reg_ofs_cur = AFE_DL_24CH_CUR, + .reg_ofs_end = AFE_DL_24CH_END, + .reg_ofs_base_msb = AFE_DL_24CH_BASE_MSB, + .reg_ofs_cur_msb = AFE_DL_24CH_CUR_MSB, + .reg_ofs_end_msb = AFE_DL_24CH_END_MSB, + .fs_reg = AFE_DL_24CH_CON0, + .fs_shift = DL_24CH_SEL_FS_SFT, + .fs_maskbit = DL_24CH_SEL_FS_MASK, + .mono_reg = -1, + .mono_shift = -1, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_DL_24CH_CON0, + .enable_shift = DL_24CH_ON_SFT, + .hd_reg = AFE_DL_24CH_CON0, + .hd_shift = DL_24CH_HD_MODE_SFT, + .hd_align_reg = AFE_DL_24CH_CON0, + .hd_align_mshift = DL_24CH_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + .pbuf_reg = AFE_DL_24CH_CON0, + .pbuf_mask = DL_24CH_PBUF_SIZE_MASK, + .pbuf_shift = DL_24CH_PBUF_SIZE_SFT, + .minlen_reg = AFE_DL_24CH_CON0, + .minlen_mask = DL_24CH_MINLEN_MASK, + .minlen_shift = DL_24CH_MINLEN_SFT, + .ch_num_reg = AFE_DL_24CH_CON0, + .ch_num_maskbit = DL_24CH_NUM_MASK, + .ch_num_shift = DL_24CH_NUM_SFT, + }, + [MT8196_MEMIF_UL0] = { + .name = "UL0", + .id = MT8196_MEMIF_UL0, + .reg_ofs_base = AFE_VUL0_BASE, + .reg_ofs_cur = AFE_VUL0_CUR, + .reg_ofs_end = AFE_VUL0_END, + .reg_ofs_base_msb = AFE_VUL0_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL0_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL0_END_MSB, + .fs_reg = AFE_VUL0_CON0, + .fs_shift = VUL0_SEL_FS_SFT, + .fs_maskbit = VUL0_SEL_FS_MASK, + .mono_reg = AFE_VUL0_CON0, + .mono_shift = VUL0_MONO_SFT, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_VUL0_CON0, + .enable_shift = VUL0_ON_SFT, + .hd_reg = AFE_VUL0_CON0, + .hd_shift = VUL0_HD_MODE_SFT, + .hd_align_reg = AFE_VUL0_CON0, + .hd_align_mshift = VUL0_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + }, + [MT8196_MEMIF_UL1] = { + .name = "UL1", + .id = MT8196_MEMIF_UL1, + .reg_ofs_base = AFE_VUL1_BASE, + .reg_ofs_cur = AFE_VUL1_CUR, + .reg_ofs_end = AFE_VUL1_END, + .reg_ofs_base_msb = AFE_VUL1_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL1_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL1_END_MSB, + .fs_reg = AFE_VUL1_CON0, + .fs_shift = VUL1_SEL_FS_SFT, + .fs_maskbit = VUL1_SEL_FS_MASK, + .mono_reg = AFE_VUL1_CON0, + .mono_shift = VUL1_MONO_SFT, + .enable_reg = AFE_VUL1_CON0, + .enable_shift = VUL1_ON_SFT, + .hd_reg = AFE_VUL1_CON0, + .hd_shift = VUL1_HD_MODE_SFT, + .hd_align_reg = AFE_VUL1_CON0, + .hd_align_mshift = VUL1_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + }, + [MT8196_MEMIF_UL2] = { + .name = "UL2", + .id = MT8196_MEMIF_UL2, + .reg_ofs_base = AFE_VUL2_BASE, + .reg_ofs_cur = AFE_VUL2_CUR, + .reg_ofs_end = AFE_VUL2_END, + .reg_ofs_base_msb = AFE_VUL2_BASE_MSB, + .reg_ofs_cur_msb = AFE_VUL2_CUR_MSB, + .reg_ofs_end_msb = AFE_VUL2_END_MSB, + .fs_reg = AFE_VUL2_CON0, + .fs_shift = VUL2_SEL_FS_SFT, + .fs_maskbit = VUL2_SEL_FS_MASK, + .mono_reg = AFE_VUL2_CON0, + .mono_shift = VUL2_MONO_SFT, + .int_odd_flag_reg = -1, + .int_odd_flag_shift = 0, + .enable_reg = AFE_VUL2_CON0, + .enable_shift = VUL2_ON_SFT, + .hd_reg = AFE_VUL2_CON0, + .hd_shift = VUL2_HD_MODE_SFT, + .hd_align_reg = AFE_VUL2_CON0, + .hd_align_mshift = VUL2_HALIGN_SFT, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + .msb_reg = -1, + .msb_shift = -1, + }, +}; + +struct mt8196_afe_rate { + unsigned int rate; + unsigned int reg_value; +}; + +static const struct mt8196_afe_rate mt8196_afe_rates[] = { + { + .rate = 8000, + .reg_value = 0, + }, + { + .rate = 12000, + .reg_value = 2, + }, + { + .rate = 16000, + .reg_value = 4, + }, + { + .rate = 24000, + .reg_value = 6, + }, + { + .rate = 32000, + .reg_value = 8, + }, + { + .rate = 48000, + .reg_value = 0x0a, + }, + { + .rate = 96000, + .reg_value = 14, + }, + { + .rate = 192000, + .reg_value = 18, + }, + { + .rate = 384000, + .reg_value = 22, + }, + { + .rate = 11025, + .reg_value = 1, + }, + { + .rate = 22050, + .reg_value = 5, + }, + { + .rate = 44100, + .reg_value = 9, + }, + { + .rate = 88200, + .reg_value = 13, + }, + { + .rate = 176400, + .reg_value = 17, + }, + { + .rate = 352800, + .reg_value = 21, + }, +}; + +static unsigned int mt8196_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8196_afe_rates); i++) + if (mt8196_afe_rates[i].rate == rate) + return mt8196_afe_rates[i].reg_value; + + return -EINVAL; +} + +static unsigned int mt8196_afe_fs(unsigned int rate, int aud_blk) +{ + return mt8196_afe_fs_timing(rate); +} + +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = AFE_BASE_ADDR, + .memif_datas = memif_data, + .memif_size = MT8196_MEMIF_NUM, + .memif_dl_num = MT8196_MEMIF_DL_NUM, + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = MT8196_DAI_NUM, + .afe_fs = mt8196_afe_fs, + .irq_fs = mt8196_afe_fs_timing, +}; diff --git a/src/platform/mt8196/include/arch/xtensa/config/core-isa.h b/src/platform/mt8196/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..b0d7ed6a7c67 --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,831 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + * + * Customer ID=7578; Build=0xa69ab; Copyright (c) 1999-2023 Tensilica 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. + */ + +#ifndef XTENSA_CORE_CONFIGURATION_H_ +#define XTENSA_CORE_CONFIGURATION_H_ + +/**************************************************************************** + * Parameters Useful for Any Code, USER or PRIVILEGED + **************************************************************************** + */ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + +/*---------------------------------------------------------------------- + * ISA + *---------------------------------------------------------------------- + */ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 16 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 1 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_LX 1 /* LX core */ +#define XCHAL_HAVE_NX 0 /* NX core (starting RH) */ +#define XCHAL_HAVE_RNX 0 /* RNX core (starting RJ) */ + +#define XCHAL_HAVE_SUPERGATHER 0 /* SuperGather */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion */ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 1 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_NN_MAC 1 /* HiFi5 Audio Engine NN-MAC option */ + +/* HiFi5 Audio Engine Single--Precision VFPU option */ +#define XCHAL_HAVE_HIFI5_VFPU 1 +#define XCHAL_HAVE_HIFI5_HP_VFPU 1 /* HiFi5 Audio Engine Half-Precision VFPU option */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 1 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI1 0 /* HiFi1 */ +#define XCHAL_HAVE_HIFI1_VFPU 0 /* HiFi1 VFPU option */ +/* HiFi1 Low-latency MAC/FMA option */ +#define XCHAL_HAVE_HIFI1_LOW_LATENCY_MAC_FMA 0 +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_FUSIONJ 0 /* FusionJ */ +#define XCHAL_HAVE_FUSIONJ6 0 /* FusionJ6 */ +#define XCHAL_HAVE_FUSIONJ_SP_VFPU 0 /* sp_vfpu option on FusionJ */ +#define XCHAL_HAVE_FUSIONJ_DP_VFPU 0 /* dp_vfpu option on FusionJ */ +#define XCHAL_FUSIONJ_SIMD32 0 /* simd32 for FusionJ */ + +#define XCHAL_HAVE_PDX 0 /* PDX-LX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4-LX */ +#define XCHAL_HAVE_PDX8 0 /* PDX8-LX */ +#define XCHAL_HAVE_PDX16 0 /* PDX16-LX */ +#define XCHAL_HAVE_PDXNX 0 /* PDX-NX */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BALL 0 +#define XCHAL_HAVE_BALLAP 0 +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_CONNX_B10 0 /* ConnX B10 pkg*/ +#define XCHAL_HAVE_CONNX_B20 0 /* ConnX B20 pkg*/ + +/* Double-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_DP_VFPU 0 +/* Double-precision Vector Floating-point option on FP Machine*/ +#define XCHAL_HAVE_CONNX_B_DPX_VFPU 0 +/* Single-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SP_VFPU 0 +/* Single-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_SPX_VFPU 0 +/* Half-precision Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HP_VFPU 0 +/* Half-precision Extended Vector Floating-point option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_HPX_VFPU 0 +/* 32-bit vector MAC (real and complex), FIR & FFT option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_32B_MAC 0 +#define XCHAL_HAVE_CONNX_B_VITERBI 0 /* Viterbi option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_TURBO 0 /* Turbo option on ConnX B10 & B20 */ +#define XCHAL_HAVE_CONNX_B_LDPC 0 /* LDPC option on ConnX B10 & B20 */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, Q6, Q7 or Q8 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_DP_VFPU 0 /* dp_vfpu option on Vision Q7/Q8 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6/Q6/Q7 */ +#define XCHAL_HAVE_VISION_SP_VFPU_2XFMAC 0 /* sp_vfpu_2xfma option on Vision Q7 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6/Q6 */ +#define XCHAL_HAVE_VISION_HP_VFPU_2XFMAC 0 /* hp_vfpu_2xfma option on Vision Q7 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +#define XCHAL_HAVE_XNNE 0 /* XNNE */ + +/*---------------------------------------------------------------------- + * MISC + *---------------------------------------------------------------------- + */ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ + +/* d-side pipeline delay (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_DATA_PIPE_DELAY 2 +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_UNIFIED_LOADSTORE 0 + +#define XCHAL_SW_VERSION 1411000 /* sw version of this header */ +#define XCHAL_SW_VERSION_MAJOR 14000 /* major ver# of sw */ +#define XCHAL_SW_VERSION_MINOR 11 /* minor ver# of sw */ +#define XCHAL_SW_VERSION_MICRO 0 /* micro ver# of sw */ +#define XCHAL_SW_MINOR_VERSION 1411000 /* with zeroed micro */ +#define XCHAL_SW_MICRO_VERSION 1411000 + +/* alphanum core name (CoreID) set in the Xtensa Processor Generator */ +#define XCHAL_CORE_ID "HiFi5_MPU_lock_2023_11" + +#define XCHAL_BUILD_UNIQUE_ID 0x000A69AB /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC003B286 /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x2A09D04B /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.1.8" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2810 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 8 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION_MICRO 0 /* subdot ver# of targeted hw */ +/* major*100+(major<2810 ? minor : minor*10+micro) */ +#define XCHAL_HW_VERSION 281080 +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_1 1 +#define XCHAL_HW_REL_LX7_1_8 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2810 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 8 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MICRO 0 /* micro v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 281080 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2810 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 8 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MICRO 0 /* micro v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 281080 /* latest targeted hw */ + +/* Config is enabled for functional safety: */ +#define XCHAL_HAVE_FUNC_SAFETY 0 + +/* Config is enabled for secure operation: */ +#define XCHAL_HAVE_SECURE 0 + +#define XCHAL_HAVE_APB 0 + +/*---------------------------------------------------------------------- + * CACHE + *---------------------------------------------------------------------- + */ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 65536 /* I-cache size in bytes or 0 */ +#define XCHAL_ICACHE_SIZE_LOG2 16 +#define XCHAL_DCACHE_SIZE 131072 /* D-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE_LOG2 17 + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 cache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_CME_DOWNGRADES 0 +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ +#define XCHAL_HAVE_ICACHE_DYN_ENABLE 1 /* Icache enabled via MEMCTL */ +#define XCHAL_HAVE_DCACHE_DYN_ENABLE 1 /* Dcache enabled via MEMCTL */ + +#define XCHAL_L1SCACHE_SIZE 0 +#define XCHAL_L1SCACHE_SIZE_LOG2 0 +#define XCHAL_L1SCACHE_WAYS 1 +#define XCHAL_L1SCACHE_WAYS_LOG2 0 +#define XCHAL_L1SCACHE_ACCESS_SIZE 0 +#define XCHAL_L1SCACHE_BANKS 1 + +#define XCHAL_L1VCACHE_SIZE 0 + +#define XCHAL_HAVE_L2 0 /* NX L2 cache controller */ +#define XCHAL_HAVE_L2_CACHE 0 +#define XCHAL_NUM_CORES_IN_CLUSTER 0 + +/* PRID_ID macros are for internal use only ... subject to removal */ +#define PRID_ID_SHIFT 0 +#define PRID_ID_BITS 4 +#define PRID_ID_MASK 0x0000000F + +/* This one is a form of caching, though not architecturally visible: */ +#define XCHAL_HAVE_BRANCH_PREDICTION 0 /* branch [target] prediction */ + +/**************************************************************************** + * Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + * CACHE + *---------------------------------------------------------------------- + */ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 7 +#define XCHAL_DCACHE_SETWIDTH 8 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_ICACHE_WAYS_LOG2 2 +#define XCHAL_DCACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS_LOG2 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 +#define XCHAL_ICACHE_ECC_WIDTH 4 +#define XCHAL_DCACHE_ECC_WIDTH 1 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 16 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* The number of Cache lines associated with a single cache tag */ +#define XCHAL_DCACHE_LINES_PER_TAG_LOG2 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ + +/* Extended memory attributes supported. */ +#define XCHAL_HAVE_EXT_CA 0 + +/*---------------------------------------------------------------------- + * INTERNAL I/D RAM/ROMs and XLMI + *---------------------------------------------------------------------- + */ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ +#define XCHAL_HAVE_IRAMCFG 0 /* IRAMxCFG register present */ +#define XCHAL_HAVE_DRAMCFG 0 /* DRAMxCFG register present */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x3FFF0000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x3FFF0000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 262144 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FFE8000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x3FFE8000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 65536 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 1: */ +#define XCHAL_DATARAM1_VADDR 0x3FFE9000 /* virtual address */ +#define XCHAL_DATARAM1_PADDR 0x3FFE9000 /* physical address */ +#define XCHAL_DATARAM1_SIZE 131072 /* size in bytes */ +#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM1_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM1 1 +#define XCHAL_DATARAM1_HAVE_IDMA 0 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + +/*---------------------------------------------------------------------- + * IDMA + *---------------------------------------------------------------------- + */ + +#define XCHAL_HAVE_IDMA 0 + +/*---------------------------------------------------------------------- + * INTERRUPTS and TIMERS + *---------------------------------------------------------------------- + */ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 26 /* num of external interrupts */ +/* number of interrupt levels (not including level zero) */ +#define XCHAL_NUM_INTLEVELS 5 +#define XCHAL_INTERRUPT_RANGE 32 /* range of interrupt numbers */ + +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x040000FF +#define XCHAL_INTLEVEL2_MASK 0xA800FF00 +#define XCHAL_INTLEVEL3_MASK 0x518F0000 +#define XCHAL_INTLEVEL4_MASK 0x00700000 +#define XCHAL_INTLEVEL5_MASK 0x00000000 +#define XCHAL_INTLEVEL6_MASK 0x02000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x040000FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0xAC00FFFF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0xFD8FFFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0xFDFFFFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFDFFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 2 +#define XCHAL_INT10_LEVEL 2 +#define XCHAL_INT11_LEVEL 2 +#define XCHAL_INT12_LEVEL 2 +#define XCHAL_INT13_LEVEL 2 +#define XCHAL_INT14_LEVEL 2 +#define XCHAL_INT15_LEVEL 2 +#define XCHAL_INT16_LEVEL 3 +#define XCHAL_INT17_LEVEL 3 +#define XCHAL_INT18_LEVEL 3 +#define XCHAL_INT19_LEVEL 3 +#define XCHAL_INT20_LEVEL 4 +#define XCHAL_INT21_LEVEL 4 +#define XCHAL_INT22_LEVEL 4 +#define XCHAL_INT23_LEVEL 3 +#define XCHAL_INT24_LEVEL 3 +#define XCHAL_INT25_LEVEL 6 +#define XCHAL_INT26_LEVEL 1 +#define XCHAL_INT27_LEVEL 2 +#define XCHAL_INT28_LEVEL 3 +#define XCHAL_INT29_LEVEL 2 +#define XCHAL_INT30_LEVEL 3 +#define XCHAL_INT31_LEVEL 2 +#define XCHAL_DEBUGLEVEL 5 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +/* NMI "level" (for use with EXCSAVE/EPS/EPC_n, RFI n) */ +#define XCHAL_NMILEVEL 6 + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_SOFTWARE + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x007FFFFF +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x01800000 +#define XCHAL_INTTYPE_MASK_NMI 0x02000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x80000000 +#define XCHAL_INTTYPE_MASK_TIMER 0x1C000000 +#define XCHAL_INTTYPE_MASK_ETIE 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x40000000 +#define XCHAL_INTTYPE_MASK_DBG_REQUEST 0x00000000 +#define XCHAL_INTTYPE_MASK_BREAKIN 0x00000000 +#define XCHAL_INTTYPE_MASK_TRAX 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x20000000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_L2_STATUS 0x00000000 +#define XCHAL_INTTYPE_MASK_COR_ECC_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_WWDT 0x00000000 +#define XCHAL_INTTYPE_MASK_FXLK 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 26 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 27 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 28 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 25 /* non-maskable interrupt */ +#define XCHAL_WRITE_ERROR_INTERRUPT 30 +#define XCHAL_PROFILING_INTERRUPT 29 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL6_NUM 25 +/* (There are many interrupts each at level(s) 1, 2, 3, 4.) */ + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT9_NUM 9 /* (intlevel 2) */ +#define XCHAL_EXTINT10_NUM 10 /* (intlevel 2) */ +#define XCHAL_EXTINT11_NUM 11 /* (intlevel 2) */ +#define XCHAL_EXTINT12_NUM 12 /* (intlevel 2) */ +#define XCHAL_EXTINT13_NUM 13 /* (intlevel 2) */ +#define XCHAL_EXTINT14_NUM 14 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 15 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 16 /* (intlevel 3) */ +#define XCHAL_EXTINT17_NUM 17 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 18 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 19 /* (intlevel 3) */ +#define XCHAL_EXTINT20_NUM 20 /* (intlevel 4) */ +#define XCHAL_EXTINT21_NUM 21 /* (intlevel 4) */ +#define XCHAL_EXTINT22_NUM 22 /* (intlevel 4) */ +#define XCHAL_EXTINT23_NUM 23 /* (intlevel 3) */ +#define XCHAL_EXTINT24_NUM 24 /* (intlevel 3) */ +#define XCHAL_EXTINT25_NUM 25 /* (intlevel 6) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT6_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT7_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 8 /* (intlevel 2) */ +#define XCHAL_INT9_EXTNUM 9 /* (intlevel 2) */ +#define XCHAL_INT10_EXTNUM 10 /* (intlevel 2) */ +#define XCHAL_INT11_EXTNUM 11 /* (intlevel 2) */ +#define XCHAL_INT12_EXTNUM 12 /* (intlevel 2) */ +#define XCHAL_INT13_EXTNUM 13 /* (intlevel 2) */ +#define XCHAL_INT14_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT15_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT16_EXTNUM 16 /* (intlevel 3) */ +#define XCHAL_INT17_EXTNUM 17 /* (intlevel 3) */ +#define XCHAL_INT18_EXTNUM 18 /* (intlevel 3) */ +#define XCHAL_INT19_EXTNUM 19 /* (intlevel 3) */ +#define XCHAL_INT20_EXTNUM 20 /* (intlevel 4) */ +#define XCHAL_INT21_EXTNUM 21 /* (intlevel 4) */ +#define XCHAL_INT22_EXTNUM 22 /* (intlevel 4) */ +#define XCHAL_INT23_EXTNUM 23 /* (intlevel 3) */ +#define XCHAL_INT24_EXTNUM 24 /* (intlevel 3) */ +#define XCHAL_INT25_EXTNUM 25 /* (intlevel 6) */ + +#define XCHAL_HAVE_ISB 0 /* No ISB */ +#define XCHAL_ISB_VADDR 0 /* N/A */ +#define XCHAL_HAVE_ITB 0 /* No ITB */ +#define XCHAL_ITB_VADDR 0 /* N/A */ + +#define XCHAL_HAVE_KSL 0 /* Kernel Stack Limit */ +#define XCHAL_HAVE_ISL 0 /* Interrupt Stack Limit */ +#define XCHAL_HAVE_PSL 0 /* Pageable Stack Limit */ + +/*---------------------------------------------------------------------- + * EXCEPTIONS and VECTORS + *---------------------------------------------------------------------- + */ + +/* Xtensa Exception Architecture + * number: 1 == XEA1 (until T1050) + * 2 == XEA2 (LX) + * 3 == XEA3 (NX) + * 0 == XEA5 (RNX) + */ +#define XCHAL_XEA_VERSION 2 +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEA3 0 /* Exception Architecture 3 */ +#define XCHAL_HAVE_XEA5 0 /* Exception Architecture 5 */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_IMPRECISE_EXCEPTIONS 0 /* imprecise exception option */ +#define XCHAL_EXCCAUSE_NUM 64 /* Number of exceptions */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x4e100400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x4e100400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 /* UNUSED */ + +#define XCHAL_RESET_VECTOR0_VADDR 0x4e100000 +#define XCHAL_RESET_VECTOR0_PADDR 0x4e100000 +#define XCHAL_RESET_VECTOR1_VADDR 0x4e100680 +#define XCHAL_RESET_VECTOR1_PADDR 0x4e100680 +#define XCHAL_RESET_VECTOR_VADDR XCHAL_RESET_VECTOR1_VADDR +#define XCHAL_RESET_VECTOR_PADDR XCHAL_RESET_VECTOR1_PADDR +#define XCHAL_USER_VECOFS 0x0000023C +#define XCHAL_USER_VECTOR_VADDR 0x4e10063C +#define XCHAL_USER_VECTOR_PADDR 0x4e10063C +#define XCHAL_KERNEL_VECOFS 0x0000021C +#define XCHAL_KERNEL_VECTOR_VADDR 0x4e10061C +#define XCHAL_KERNEL_VECTOR_PADDR 0x4e10061C +#define XCHAL_DOUBLEEXC_VECOFS 0x0000025C +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x4e10065C +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x4e10065C +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x4e100400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x4e100400 +#define XCHAL_INTLEVEL2_VECOFS 0x0000017C +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x4e10057C +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x4e10057C +#define XCHAL_INTLEVEL3_VECOFS 0x0000019C +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x4e10059C +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x4e10059C +#define XCHAL_INTLEVEL4_VECOFS 0x000001BC +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x4e1005BC +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x4e1005BC +#define XCHAL_INTLEVEL5_VECOFS 0x000001DC +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x4e1005DC +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x4e1005DC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL5_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL5_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL5_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000001FC +#define XCHAL_NMI_VECTOR_VADDR 0x4e1005FC +#define XCHAL_NMI_VECTOR_PADDR 0x4e1005FC +#define XCHAL_INTLEVEL6_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL6_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL6_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + +/*---------------------------------------------------------------------- + * DEBUG MODULE + *---------------------------------------------------------------------- + */ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 4096 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 64 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 8 /* performance counters */ + +/*---------------------------------------------------------------------- + * MMU + *---------------------------------------------------------------------- + */ + +/* See core-matmap.h header file for more details. */ +#define XCHAL_HAVE_TLBS 0 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +/* full MMU (with page table [autorefill] and protection) usable for an MMU-based OS */ +#define XCHAL_HAVE_PTP_MMU 0 + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + * MPU + *---------------------------------------------------------------------- + */ +#define XCHAL_HAVE_MPU 1 +#define XCHAL_MPU_ENTRIES 32 +#define XCHAL_MPU_LOCK 1 + +/* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_ALIGN_REQ 1 +#define XCHAL_MPU_BACKGROUND_ENTRIES 2 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0xFF /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 7 +#define XCHAL_MPU_ALIGN 128 + +/*----------------------------------------------------------------------- + * CSR Parity + *------------------------------------------------------------------------ + */ +#define XCHAL_HAVE_CSR_PARITY 0 + + +/*---------------------------------------------------------------------- + * FLEX-LOCK + *------------------------------------------------------------------------ + */ + +#define XCHAL_HAVE_FXLK 0 + +/*---------------------------------------------------------------------- + * WWDT (Windowed Watchdog Timer) + *------------------------------------------------------------------------ + */ +#define XCHAL_HAVE_WWDT 0 +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + +#endif /* XTENSA_CORE_CONFIGURATION_H_ */ + diff --git a/src/platform/mt8196/include/arch/xtensa/config/core-matmap.h b/src/platform/mt8196/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..a35a16752f8b --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=7578; Build=0xa69ab; Copyright (c) 1999-2023 Tensilica 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. + */ + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + +/*---------------------------------------------------------------------- + * CACHE (MEMORY ACCESS) ATTRIBUTES + *---------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------- + * MPU + *---------------------------------------------------------------------- + */ + +/* Mappings for legacy constants where appropriate */ + +#define XCHAL_CA_WRITEBACK (XTHAL_MEM_WRITEBACK | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITEBACK_NOALLOC (XTHAL_MEM_WRITEBACK_NOALLOC | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITETHRU (XTHAL_MEM_WRITETHRU | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_ILLEGAL (XTHAL_AR_NONE | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASSBUF (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE |\ +XTHAL_MEM_BUFFERABLE) +#define XCHAL_CA_BYPASS_RX (XTHAL_AR_RX | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_RW (XTHAL_AR_RW | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_R (XTHAL_AR_R | XTHAL_MEM_DEVICE) +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 + +/* + * Contents of MPU background map. + * NOTE: caller must define the XCHAL_MPU_BGMAP() macro (not defined here + * but specified below) before expanding the XCHAL_MPU_BACKGROUND_MAP(s) macro. + * + * XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) + * + * s = passed from XCHAL_MPU_BACKGROUND_MAP(s), eg. to select how to expand + * vaddr_start = first byte of region (always 0 for first entry) + * vaddr_end = last byte of region (always 0xFFFFFFFF for last entry) + * rights = access rights + * memtype = memory type + * x = reserved for future use (0 until then) + */ +/* parasoft-begin-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ +#define XCHAL_MPU_BACKGROUND_MAP(s) (\ +XCHAL_MPU_BGMAP(s, 0x00000000, 0x7fffffff, 7, 6, 0) \ +XCHAL_MPU_BGMAP(s, 0x80000000, 0xffffffff, 7, 6, 0) \) +/* parasoft-end-suppress MISRA2012-RULE-20_7 "Macro use model requires s to not be in ()" */ + +/* end */ + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/mt8196/include/arch/xtensa/config/defs.h b/src/platform/mt8196/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..18ee59f671b3 --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/defs.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID = 7578; Build = 0xa69ab; Copyright (c) 2003-2004 Tensilica 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. + */ + +/* NOTE: This file exists only for backward compatibility with T1050 + * and earlier Xtensa releases. It includes only a subset of the + * available header files. + */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/mt8196/include/arch/xtensa/config/key.h b/src/platform/mt8196/include/arch/xtensa/config/key.h new file mode 100644 index 000000000000..61a1fa79ed1c --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/key.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Customer ID = 7578; Build = 0xa69ab; Copyright (c) 2020-2021 by Cadence Design Systems. Inc. + * ALL RIGHTS RESERVED. + * These coded instructions, statements, and computer programs are the + * copyrighted works and confidential proprietary information of Tensilica Inc. + * They may not be modified, copied, reproduced, distributed, or disclosed to + * third parties in any manner, medium, or form, in whole or in part, without + * the prior written consent of Cadence Design Systems Inc. + */ + +#ifndef TENSILICA_CONFIG_KEY +#define TENSILICA_CONFIG_KEY 1 + +#include <xtensa/xtensa-types.h> + +#endif + diff --git a/src/platform/mt8196/include/arch/xtensa/config/secure.h b/src/platform/mt8196/include/arch/xtensa/config/secure.h new file mode 100644 index 000000000000..8d46c3eb0257 --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/secure.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Secure Mode defines. */ + +/* Customer ID = 7578; Build = 0xa69ab; Copyright (c) 2020 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. + */ + +#ifndef XTENSA_SECURE_H +#define XTENSA_SECURE_H + +/* SRAM */ +#define XCHAL_HAVE_SECURE_SRAM 0 + +/* INSTRAM0 */ +#define XCHAL_HAVE_SECURE_INSTRAM0 0 + +/* DATARAM1 */ +#define XCHAL_HAVE_SECURE_DATARAM1 0 + +/* DATARAM0 */ +#define XCHAL_HAVE_SECURE_DATARAM0 0 + +/* Array of all secure regions' start/size */ +#define XCHAL_SECURE_MEM_LIST \ +{ \ +} + +#endif /* XTENSA_SECURE_H */ + diff --git a/src/platform/mt8196/include/arch/xtensa/config/specreg.h b/src/platform/mt8196/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..e2ef5d4dd469 --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/specreg.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Xtensa Special Register symbolic names + */ + +/* Id: + * //depot/rel/Homewood/ib.11/Xtensa/SWConfig/hal/specreg.h.tpp#1 + */ + +/* Customer ID = 7578; Build = 0xa69ab; Copyright (c) 1998-2002 Tensilica 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. + */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define MPUENB 90 +#define ERACCESS 95 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEADRDIS 98 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define EPC_5 181 +#define EPC_6 182 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EPS_5 197 +#define EPS_6 198 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define EXCSAVE_5 213 +#define EXCSAVE_6 214 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTCLEAR 227 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/mt8196/include/arch/xtensa/config/system.h b/src/platform/mt8196/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..77b6a105f71f --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/system.h @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID = 7578; Build = 0xa69ab; Copyright (c) 2000-2010 Tensilica 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. + */ + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + +/*---------------------------------------------------------------------- + * CONFIGURED SOFTWARE OPTIONS + *---------------------------------------------------------------------- + */ + +/* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_USE_ABSOLUTE_LITERALS 0 +/* Set if there is some memory that allows both code and literals. */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 + +/* (sw-only option, selected ABI) */ +#define XSHAL_ABI XTHAL_ABI_WINDOWED +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 + +/* (sw-only option, selected C library) */ +#define XSHAL_CLIB XTHAL_CLIB_XCLIB +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/*---------------------------------------------------------------------- + * DEVICE ADDRESSES + *---------------------------------------------------------------------- + */ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x90000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x40000000 +#define XSHAL_RAM_PADDR 0x40000000 +#define XSHAL_RAM_VSIZE 0x80000000 +#define XSHAL_RAM_PSIZE 0x80000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x50000000 +#define XSHAL_RAM_AVAIL_VSIZE 0x80000000 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0x20000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0x20000000 +#define XSHAL_SIMIO_PADDR 0x20000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + *---------------------------------------------------------------------- + */ +#define XSHAL_MAGIC_EXIT 0xdeeeb400 +#define XSHAL_STL_INFO_LOCATION 0xfffffffc + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *---------------------------------------------------------------------- + */ + +/*---------------------------------------------------------------------- + * BACKWARD COMPATIBILITY ... + *---------------------------------------------------------------------- + */ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +/* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS +/* default setting to enable caches (no writeback!) */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT + +/*---------------------------------------------------------------------- + * GENERIC + *---------------------------------------------------------------------- + */ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. + */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +/* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x24444422 +/* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x21111122 +/* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x21111122 +/* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 +/* default setting to enable caches */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK + +/* These set any unused 512MB region to ILLEGAL attribute: */ +/* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xF44444FF +/* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xF11111FF +/* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xF11111FF +/* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xF22222FF +/* default setting to enable caches */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: + */ +/* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2444442F +/* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2111112F +/* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2111112F +/* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F +/* default setting to enable caches */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +/*---------------------------------------------------------------------- + *ISS (Instruction Set Simulator) SPECIFIC ... + *---------------------------------------------------------------------- + */ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + +/*---------------------------------------------------------------------- + * XT2000 BOARD SPECIFIC ... + *---------------------------------------------------------------------- + */ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. + */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +/* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xF442442F +/* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xF112112F +/* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xF112112F +/* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xF222222F +/* default setting to enable caches */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000024 /* BusInt SDRAM regions */ + +/*---------------------------------------------------------------------- + * VECTOR INFO AND SIZES + *---------------------------------------------------------------------- + */ + +#define XSHAL_VECTORS_PACKED 0 /* UNUSED */ +#define XSHAL_STATIC_VECTOR_SELECT 1 +#define XSHAL_RESET_VECTOR_VADDR 0x4e100680 +#define XSHAL_RESET_VECTOR_PADDR 0x4e100680 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x0000001C +#define XSHAL_USER_VECTOR_ISROM 0 +/* for backward compatibility */ +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE +/* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE +#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C +#define XSHAL_KERNEL_VECTOR_ISROM 0 +/* for backward compatibility */ +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE +/* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL5_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL5_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL5_VECTOR_ISROM +#define XSHAL_NMI_VECTOR_SIZE 0x0000001C +#define XSHAL_NMI_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL6_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/mt8196/include/arch/xtensa/config/tie-asm.h b/src/platform/mt8196/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..ebef0818d327 --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,362 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + * macros, etc.) for this specific Xtensa processor's TIE extensions + * and options. It is customized to this Xtensa processor configuration. + * + * Customer ID = 7578; Build = 0xa69ab; Copyright (c) 1999-2023 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. + */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +#include <xtensa/coreasm.h> + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie, ccuse, abi) (((optie) & XTHAL_SAS_ANYOT) \ +| ((ccuse) & XTHAL_SAS_ANYCC) \ +| ((abi) & XTHAL_SAS_ANYABI)) + +/* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ +.macro xchal_ncp_store ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 +xchal_sa_start \continue, \ofs +// Optional global registers used by default by the compiler: +.ifeq(XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) +xchal_sa_align \ptr, 0, 1016, 4, 4 +rur.threadptr \at1 // threadptr option +s32i \at1, \ptr, .Lxchal_ofs_ + 0 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.elseif((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 +xchal_sa_align \ptr, 0, 1016, 4, 4 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.endif +// Optional caller-saved registers not used by default by the compiler: +.ifeq(XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) +xchal_sa_align \ptr, 0, 1016, 4, 4 +rsr.br \at1 // boolean option +s32i \at1, \ptr, .Lxchal_ofs_ + 0 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.elseif((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 +xchal_sa_align \ptr, 0, 1016, 4, 4 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.endif +.endm // xchal_ncp_store + +/* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ +.macro xchal_ncp_load ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 +xchal_sa_start \continue, \ofs +// Optional global registers used by default by the compiler: +.ifeq(XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) +xchal_sa_align \ptr, 0, 1016, 4, 4 +l32i \at1, \ptr, .Lxchal_ofs_ + 0 +wur.threadptr \at1 // threadptr option +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.elseif((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 +xchal_sa_align \ptr, 0, 1016, 4, 4 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.endif +// Optional caller-saved registers not used by default by the compiler: +.ifeq(XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) +xchal_sa_align \ptr, 0, 1016, 4, 4 +l32i \at1, \ptr, .Lxchal_ofs_ + 0 +wsr.br \at1 // boolean option +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.elseif((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 +xchal_sa_align \ptr, 0, 1016, 4, 4 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 4 +.endif +.endm // xchal_ncp_load + +#define XCHAL_NCP_NUM_ATMPS 1 + +/* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store +.macro xchal_cp1_store ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 +xchal_sa_start \continue, \ofs +// Custom caller-saved registers not used by default by the compiler: +.ifeq(XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) +xchal_sa_align \ptr, 0, 0, 16, 16 +ae_s64.i aed0, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_s64.i aed1, \ptr, .Lxchal_ofs_ + 0 +ae_s64.i aed2, \ptr, .Lxchal_ofs_ + 8 +ae_s64.i aed3, \ptr, .Lxchal_ofs_ + 16 +ae_s64.i aed4, \ptr, .Lxchal_ofs_ + 24 +ae_s64.i aed5, \ptr, .Lxchal_ofs_ + 32 +ae_s64.i aed6, \ptr, .Lxchal_ofs_ + 40 +ae_s64.i aed7, \ptr, .Lxchal_ofs_ + 48 +ae_s64.i aed8, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_s64.i aed9, \ptr, .Lxchal_ofs_ + 0 +ae_s64.i aed10, \ptr, .Lxchal_ofs_ + 8 +ae_s64.i aed11, \ptr, .Lxchal_ofs_ + 16 +ae_s64.i aed12, \ptr, .Lxchal_ofs_ + 24 +ae_s64.i aed13, \ptr, .Lxchal_ofs_ + 32 +ae_s64.i aed14, \ptr, .Lxchal_ofs_ + 40 +ae_s64.i aed15, \ptr, .Lxchal_ofs_ + 48 +ae_s64.i aed16, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_s64.i aed17, \ptr, .Lxchal_ofs_ + 0 +ae_s64.i aed18, \ptr, .Lxchal_ofs_ + 8 +ae_s64.i aed19, \ptr, .Lxchal_ofs_ + 16 +ae_s64.i aed20, \ptr, .Lxchal_ofs_ + 24 +ae_s64.i aed21, \ptr, .Lxchal_ofs_ + 32 +ae_s64.i aed22, \ptr, .Lxchal_ofs_ + 40 +ae_s64.i aed23, \ptr, .Lxchal_ofs_ + 48 +ae_s64.i aed24, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_s64.i aed25, \ptr, .Lxchal_ofs_ + 0 +ae_s64.i aed26, \ptr, .Lxchal_ofs_ + 8 +ae_s64.i aed27, \ptr, .Lxchal_ofs_ + 16 +ae_s64.i aed28, \ptr, .Lxchal_ofs_ + 24 +ae_s64.i aed29, \ptr, .Lxchal_ofs_ + 32 +ae_s64.i aed30, \ptr, .Lxchal_ofs_ + 40 +ae_s64.i aed31, \ptr, .Lxchal_ofs_ + 48 +ae_movae \at1, aep0 +s8i \at1, \ptr, .Lxchal_ofs_ + 56 +ae_movae \at1, aep1 +s8i \at1, \ptr, .Lxchal_ofs_ + 57 +ae_movae \at1, aep2 +s8i \at1, \ptr, .Lxchal_ofs_ + 58 +ae_movae \at1, aep3 +s8i \at1, \ptr, .Lxchal_ofs_ + 59 +addi.a \ptr, \ptr, 64 +ae_salign128.i u0, \ptr, .Lxchal_ofs_ + 0 +ae_salign128.i u1, \ptr, .Lxchal_ofs_ + 16 +ae_salign128.i u2, \ptr, .Lxchal_ofs_ + 32 +ae_salign128.i u3, \ptr, .Lxchal_ofs_ + 48 +addi.a \ptr, \ptr, -320 +ae_movdrzbvc aed0 // ureg AE_ZBIASV8C +ae_s64.i aed0, \ptr, .Lxchal_ofs_ + 0 + 0 +ae_movvfcrfsr aed0 // ureg FCR_FSR +ae_s64.i aed0, \ptr, .Lxchal_ofs_ + 8 + 0 +rur.ae_ovf_sar \at1 // ureg 240 +s32i \at1, \ptr, .Lxchal_ofs_ + 16 +rur.ae_bithead \at1 // ureg 241 +s32i \at1, \ptr, .Lxchal_ofs_ + 20 +rur.ae_ts_fts_bu_bp \at1 // ureg 242 +s32i \at1, \ptr, .Lxchal_ofs_ + 24 +rur.ae_cw_sd_no \at1 // ureg 243 +s32i \at1, \ptr, .Lxchal_ofs_ + 28 +rur.ae_cbegin0 \at1 // ureg 246 +s32i \at1, \ptr, .Lxchal_ofs_ + 32 +rur.ae_cend0 \at1 // ureg 247 +s32i \at1, \ptr, .Lxchal_ofs_ + 36 +rur.ae_cbegin1 \at1 // ureg 248 +s32i \at1, \ptr, .Lxchal_ofs_ + 40 +rur.ae_cend1 \at1 // ureg 249 +s32i \at1, \ptr, .Lxchal_ofs_ + 44 +rur.ae_cbegin2 \at1 // ureg 250 +s32i \at1, \ptr, .Lxchal_ofs_ + 48 +rur.ae_cend2 \at1 // ureg 251 +s32i \at1, \ptr, .Lxchal_ofs_ + 52 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 384 +.elseif((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 +xchal_sa_align \ptr, 0, 0, 16, 16 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 384 +.endif +.endm // xchal_cp1_store + +/* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 16 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load +.macro xchal_cp1_load ptr at1 at2 at3 at4 continue = 0 ofs = -1 select = XTHAL_SAS_ALL alloc = 0 +xchal_sa_start \continue, \ofs +// Custom caller-saved registers not used by default by the compiler: +.ifeq(XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) +xchal_sa_align \ptr, 0, 0, 16, 16 +ae_l64.i aed0, \ptr, .Lxchal_ofs_ + 0 + 0 // ureg AE_ZBIASV8C +ae_movzbvcdr aed0 +ae_l64.i aed0, \ptr, .Lxchal_ofs_ + 8 + 0 // ureg FCR_FSR +ae_movfcrfsrv aed0 +l32i \at1, \ptr, .Lxchal_ofs_ + 16 +wur.ae_ovf_sar \at1 // ureg 240 +l32i \at1, \ptr, .Lxchal_ofs_ + 20 +wur.ae_bithead \at1 // ureg 241 +l32i \at1, \ptr, .Lxchal_ofs_ + 24 +wur.ae_ts_fts_bu_bp \at1 // ureg 242 +l32i \at1, \ptr, .Lxchal_ofs_ + 28 +wur.ae_cw_sd_no \at1 // ureg 243 +l32i \at1, \ptr, .Lxchal_ofs_ + 32 +wur.ae_cbegin0 \at1 // ureg 246 +l32i \at1, \ptr, .Lxchal_ofs_ + 36 +wur.ae_cend0 \at1 // ureg 247 +l32i \at1, \ptr, .Lxchal_ofs_ + 40 +wur.ae_cbegin1 \at1 // ureg 248 +l32i \at1, \ptr, .Lxchal_ofs_ + 44 +wur.ae_cend1 \at1 // ureg 249 +l32i \at1, \ptr, .Lxchal_ofs_ + 48 +wur.ae_cbegin2 \at1 // ureg 250 +l32i \at1, \ptr, .Lxchal_ofs_ + 52 +wur.ae_cend2 \at1 // ureg 251 +ae_l64.i aed0, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_l64.i aed1, \ptr, .Lxchal_ofs_ + 0 +ae_l64.i aed2, \ptr, .Lxchal_ofs_ + 8 +ae_l64.i aed3, \ptr, .Lxchal_ofs_ + 16 +ae_l64.i aed4, \ptr, .Lxchal_ofs_ + 24 +ae_l64.i aed5, \ptr, .Lxchal_ofs_ + 32 +ae_l64.i aed6, \ptr, .Lxchal_ofs_ + 40 +ae_l64.i aed7, \ptr, .Lxchal_ofs_ + 48 +ae_l64.i aed8, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_l64.i aed9, \ptr, .Lxchal_ofs_ + 0 +ae_l64.i aed10, \ptr, .Lxchal_ofs_ + 8 +ae_l64.i aed11, \ptr, .Lxchal_ofs_ + 16 +ae_l64.i aed12, \ptr, .Lxchal_ofs_ + 24 +ae_l64.i aed13, \ptr, .Lxchal_ofs_ + 32 +ae_l64.i aed14, \ptr, .Lxchal_ofs_ + 40 +ae_l64.i aed15, \ptr, .Lxchal_ofs_ + 48 +ae_l64.i aed16, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_l64.i aed17, \ptr, .Lxchal_ofs_ + 0 +ae_l64.i aed18, \ptr, .Lxchal_ofs_ + 8 +ae_l64.i aed19, \ptr, .Lxchal_ofs_ + 16 +ae_l64.i aed20, \ptr, .Lxchal_ofs_ + 24 +ae_l64.i aed21, \ptr, .Lxchal_ofs_ + 32 +ae_l64.i aed22, \ptr, .Lxchal_ofs_ + 40 +ae_l64.i aed23, \ptr, .Lxchal_ofs_ + 48 +ae_l64.i aed24, \ptr, .Lxchal_ofs_ + 56 +addi.a \ptr, \ptr, 64 +ae_l64.i aed25, \ptr, .Lxchal_ofs_ + 0 +ae_l64.i aed26, \ptr, .Lxchal_ofs_ + 8 +ae_l64.i aed27, \ptr, .Lxchal_ofs_ + 16 +ae_l64.i aed28, \ptr, .Lxchal_ofs_ + 24 +ae_l64.i aed29, \ptr, .Lxchal_ofs_ + 32 +ae_l64.i aed30, \ptr, .Lxchal_ofs_ + 40 +ae_l64.i aed31, \ptr, .Lxchal_ofs_ + 48 +addi.a \ptr, \ptr, 56 +l8ui \at1, \ptr, .Lxchal_ofs_ + 0 +ae_movea aep0, \at1 +l8ui \at1, \ptr, .Lxchal_ofs_ + 1 +ae_movea aep1, \at1 +l8ui \at1, \ptr, .Lxchal_ofs_ + 2 +ae_movea aep2, \at1 +l8ui \at1, \ptr, .Lxchal_ofs_ + 3 +ae_movea aep3, \at1 +addi.a \ptr, \ptr, 8 +ae_lalign128.i u0, \ptr, .Lxchal_ofs_ + 0 +ae_lalign128.i u1, \ptr, .Lxchal_ofs_ + 16 +ae_lalign128.i u2, \ptr, .Lxchal_ofs_ + 32 +ae_lalign128.i u3, \ptr, .Lxchal_ofs_ + 48 +.set .Lxchal_pofs_, .Lxchal_pofs_ + 320 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 64 +.elseif((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 +xchal_sa_align \ptr, 0, 0, 16, 16 +.set .Lxchal_ofs_, .Lxchal_ofs_ + 384 +.endif +.endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + +/* Empty macros for unconfigured coprocessors: */ +.macro xchal_cp0_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp0_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp2_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp2_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp3_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp3_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp4_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp4_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp5_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp5_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp6_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp6_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp7_store p a b c d continue = 0 ofs = -1 select = -1 ; .endm +.macro xchal_cp7_load p a b c d continue = 0 ofs = -1 select = -1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/mt8196/include/arch/xtensa/config/tie.h b/src/platform/mt8196/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..517d79faab47 --- /dev/null +++ b/src/platform/mt8196/include/arch/xtensa/config/tie.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + * that extend basic Xtensa core functionality. It is customized to this + * Xtensa processor configuration. + * + * Customer ID = 7578; Build = 0xa69ab; Copyright (c) 1999-2023 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. + */ + +#ifndef XTENSA_CORE_TIE_H +#define XTENSA_CORE_TIE_H + +/* parasoft-begin-suppress ALL "This file not MISRA checked." */ + +#define XCHAL_CP_NUM UINT32_C(1) /* number of coprocessors */ +#define XCHAL_CP_MAX UINT32_C(2) /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK UINT32_C(0x02) /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK UINT32_C(0x00) /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "audio_engine_lx" +#define XCHAL_CP1_IDENT audio_engine_lx +#define XCHAL_CP1_SA_SIZE UINT32_C(384) /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN UINT32_C(16) /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE UINT32_C(0) +#define XCHAL_CP0_SA_ALIGN UINT32_C(1) +#define XCHAL_CP2_SA_SIZE UINT32_C(0) +#define XCHAL_CP2_SA_ALIGN UINT32_C(1) +#define XCHAL_CP3_SA_SIZE UINT32_C(0) +#define XCHAL_CP3_SA_ALIGN UINT32_C(1) +#define XCHAL_CP4_SA_SIZE UINT32_C(0) +#define XCHAL_CP4_SA_ALIGN UINT32_C(1) +#define XCHAL_CP5_SA_SIZE UINT32_C(0) +#define XCHAL_CP5_SA_ALIGN UINT32_C(1) +#define XCHAL_CP6_SA_SIZE UINT32_C(0) +#define XCHAL_CP6_SA_ALIGN UINT32_C(1) +#define XCHAL_CP7_SA_SIZE UINT32_C(0) +#define XCHAL_CP7_SA_ALIGN UINT32_C(1) + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE UINT32_C(8) +#define XCHAL_NCP_SA_ALIGN UINT32_C(4) + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE UINT32_C(400) /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN UINT32_C(16) /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s, ccused, abikind, kind, opt, name, galign, align, asize, + * dbnum, base, regnum, bitsz, gapsz, reset, x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr = special, ur = TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur, sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s, ccused, p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind, p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind, tie, name, galn, aln, asz, csz, dbnum, base, rnum, bsz, rst, x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 2 +#define XCHAL_NCP_SA_LIST(s) (\ +XCHAL_SA_REG(s, 1, 2, 1, 1, threadptr, 4, 4, 4, 0x03E7, ur, 231, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 0, 1, br, 4, 4, 4, 0x0204, sr, 4, 16, 0, 0, 0)) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 52 +#define XCHAL_CP1_SA_LIST(s) (\ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_zbiasv8c, 16, 8, 8, 0x1029, ur, -1, 16, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, fcr_fsr, 8, 8, 8, 0x102A, ur, -1, 7, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_ovf_sar, 4, 4, 4, 0x03F0, ur, 240, 15, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_bithead, 4, 4, 4, 0x03F1, ur, 241, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_ts_fts_bu_bp, 4, 4, 4, 0x03F2, ur, 242, 16, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cw_sd_no, 4, 4, 4, 0x03F3, ur, 243, 29, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cbegin0, 4, 4, 4, 0x03F6, ur, 246, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cend0, 4, 4, 4, 0x03F7, ur, 247, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cbegin1, 4, 4, 4, 0x03F8, ur, 248, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cend1, 4, 4, 4, 0x03F9, ur, 249, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cbegin2, 4, 4, 4, 0x03FA, ur, 250, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 1, 0, ae_cend2, 4, 4, 4, 0x03FB, ur, 251, 32, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed0, 8, 8, 8, 0x1000, aed, 0, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed1, 8, 8, 8, 0x1001, aed, 1, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed2, 8, 8, 8, 0x1002, aed, 2, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed3, 8, 8, 8, 0x1003, aed, 3, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed4, 8, 8, 8, 0x1004, aed, 4, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed5, 8, 8, 8, 0x1005, aed, 5, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed6, 8, 8, 8, 0x1006, aed, 6, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed7, 8, 8, 8, 0x1007, aed, 7, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed8, 8, 8, 8, 0x1008, aed, 8, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed9, 8, 8, 8, 0x1009, aed, 9, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed10, 8, 8, 8, 0x100A, aed, 10, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed11, 8, 8, 8, 0x100B, aed, 11, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed12, 8, 8, 8, 0x100C, aed, 12, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed13, 8, 8, 8, 0x100D, aed, 13, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed14, 8, 8, 8, 0x100E, aed, 14, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed15, 8, 8, 8, 0x100F, aed, 15, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed16, 8, 8, 8, 0x1010, aed, 16, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed17, 8, 8, 8, 0x1011, aed, 17, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed18, 8, 8, 8, 0x1012, aed, 18, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed19, 8, 8, 8, 0x1013, aed, 19, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed20, 8, 8, 8, 0x1014, aed, 20, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed21, 8, 8, 8, 0x1015, aed, 21, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed22, 8, 8, 8, 0x1016, aed, 22, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed23, 8, 8, 8, 0x1017, aed, 23, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed24, 8, 8, 8, 0x1018, aed, 24, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed25, 8, 8, 8, 0x1019, aed, 25, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed26, 8, 8, 8, 0x101A, aed, 26, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed27, 8, 8, 8, 0x101B, aed, 27, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed28, 8, 8, 8, 0x101C, aed, 28, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed29, 8, 8, 8, 0x101D, aed, 29, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed30, 8, 8, 8, 0x101E, aed, 30, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aed31, 8, 8, 8, 0x101F, aed, 31, 64, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aep0, 1, 1, 1, 0x1024, aep, 0, 8, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aep1, 1, 1, 1, 0x1025, aep, 1, 8, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aep2, 1, 1, 1, 0x1026, aep, 2, 8, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, aep3, 1, 1, 1, 0x1027, aep, 3, 8, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, u0, 16, 16, 16, 0x1020, u, 0, 128, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, u1, 16, 16, 16, 0x1021, u, 1, 128, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, u2, 16, 16, 16, 0x1022, u, 2, 128, 0, 0, 0) \ +XCHAL_SA_REG(s, 0, 0, 2, 0, u3, 16, 16, 16, 0x1023, u, 3, 128, 0, 0, 0)) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS (3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16) +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS (\ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \ +3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 16, \) + +/* parasoft-end-suppress ALL "This file not MISRA checked." */ + +#endif /* XTENSA_CORE_TIE_H */ + diff --git a/src/platform/mt8196/include/platform/drivers/idc.h b/src/platform/mt8196/include/platform/drivers/idc.h new file mode 100644 index 000000000000..8ad311b1471b --- /dev/null +++ b/src/platform/mt8196/include/platform/drivers/idc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +static inline int idc_init(void) +{ + return 0; +} + +#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/mt8196/include/platform/drivers/intc.h b/src/platform/mt8196/include/platform/drivers/intc.h new file mode 100644 index 000000000000..be741ae6e484 --- /dev/null +++ b/src/platform/mt8196/include/platform/drivers/intc.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ +#ifndef MTK_INTC_H +#define MTK_INTC_H + +#include <rtos/bit.h> +#include <stdint.h> +#include <platform/drivers/mt_reg_base.h> + +enum IRQn_Type { + CCU_IRQn = 0, + SCP_IRQn = 1, + SPM_IRQn = 2, + PCIE_IRQn = 3, + INFRA_HANG_IRQn = 4, + PERI_TIMEOUT_IRQn = 5, + MBOX_C0_IRQn = 6, + MBOX_C1_IRQn = 7, + TIMER0_IRQn = 8, + TIMER1_IRQn = 9, + IPC_C0_IRQn = 10, + IPC_C1_IRQn = 11, + IPC1_RSV_IRQn = 12, + C2C_SW_C0_IRQn = 13, + C2C_SW_C1_IRQn = 14, + UART_IRQn = 15, + UART_BT_IRQn = 16, + LATENCY_MON_IRQn = 17, + BUS_TRACKER_IRQn = 18, + USB0_IRQn = 19, + USB1_IRQn = 20, + SCPVOW_IRQn = 21, + CCIF3_C0_IRQn = 22, + CCIF3_C1_IRQn = 23, + PWR_CTRL_IRQn = 24, + DMA_C0_IRQn = 25, + DMA_C1_IRQn = 26, // no use as gdma only has one set + AXI_DMA0_IRQn = 27, + AXI_DMA1_IRQn = 28, + AUDIO_C0_IRQn = 29, + AUDIO_C1_IRQn = 30, + HIFI5_WDT_C0_IRQn = 31, + HIFI5_WDT_C1_IRQn = 32, + APU_MBOX_C0_IRQn = 33, + APU_MBOX_C1_IRQn = 34, + TIMER2_IRQn = 35, + PWR_ON_C0_IRQ = 36, + PWR_ON_C1_IRQ = 37, + WAKEUP_SRC_C0_IRQn = 38, + WAKEUP_SRC_C1_IRQn = 39, + WDT_IRQn = 40, + CONNSYS1_IRQn = 41, // BTCVSD + CONNSYS3_IRQn = 42, // BLEISO + CONNSYS4_IRQn = 43, // ISOCH, bt2dsp_isoch_irq_mask + CONNSYS2_IRQn = 44, // A2DP + IPIC_IRQn = 45, + AXI_DMA2_IRQn = 46, + AXI_DMA3_IRQn = 47, + APSRC_DDREN_IRQn = 48, + LAT_MON_EMI_IRQn = 49, + LAT_MON_INFRA_IRQn = 50, + DEVAPC_VIO_IRQn = 51, + AO_INFRA_HANG_IRQn = 52, + BUS_TRA_EMI_IRQn = 53, + BUS_TRA_INFRA_IRQn = 54, + L2SRAM_VIO_IRQn = 55, + L2SRAM_SETERR_IRQn = 56, + PCIERC_GRP2_IRQn = 57, + PCIERC_GRP3_IRQn = 58, + IRQ_MAX_CHANNEL = 59, + NO_IRQ = 0xFFFFFFFFU, // -1 +}; + +#define INTC_GRP_LEN 2 +#define INTC_GRP_GAP 3 // size of group = 2 words = 8 bytes +#define WORD_LEN 32 +#define INTC_WORD(irq) ((irq) >> 5) +#define INTC_BIT(irq) (1 << ((irq) & 0x1F)) +#define INTC_WORD_OFS(word) ((word) << 2) +#ifndef INTC_GROUP_OFS +#define INTC_GROUP_OFS(grp) ((grp) << INTC_GRP_GAP) +#endif + +// #define INTC_IRQ_RAW_STA(word) (INTC_IRQ_RAW_STA0 + INTC_WORD_OFS(word)) +#define INTC_IRQ_STA(word) (INTC_IRQ_STA0 + INTC_WORD_OFS(word)) +#define INTC_IRQ_EN(word) (INTC_IRQ_EN0 + INTC_WORD_OFS(word)) +#define INTC_IRQ_WAKE_EN(word) (INTC_IRQ_WAKE_EN0 + INTC_WORD_OFS(word)) +#define INTC_IRQ_STAGE1_EN(word) (INTC_IRQ_STAGE1_EN0 + INTC_WORD_OFS(word)) +#define INTC_IRQ_POL(word) (INTC_IRQ_POL0 + INTC_WORD_OFS(word)) +#define INTC_IRQ_GRP(grp, word) (INTC_IRQ_GRP0_0 + INTC_GROUP_OFS(grp)\ + + INTC_WORD_OFS(word)) +#define INTC_IRQ_GRP_STA(grp, word) (INTC_IRQ_GRP0_STA0 + INTC_GROUP_OFS(grp)\ + + INTC_WORD_OFS(word)) + +/* intc group level */ +#define INTC_GRP0_LEVEL XCHAL_INT0_LEVEL +#define INTC_GRP1_LEVEL XCHAL_INT1_LEVEL +#define INTC_GRP2_LEVEL XCHAL_INT2_LEVEL +#define INTC_GRP3_LEVEL XCHAL_INT3_LEVEL +#define INTC_GRP4_LEVEL XCHAL_INT4_LEVEL +#define INTC_GRP5_LEVEL XCHAL_INT5_LEVEL +#define INTC_GRP6_LEVEL XCHAL_INT7_LEVEL +#define INTC_GRP7_LEVEL XCHAL_INT8_LEVEL +#define INTC_GRP8_LEVEL XCHAL_INT9_LEVEL +#define INTC_GRP9_LEVEL XCHAL_INT10_LEVEL +#define INTC_GRP10_LEVEL XCHAL_INT11_LEVEL +#define INTC_GRP11_LEVEL XCHAL_INT16_LEVEL +#define INTC_GRP12_LEVEL XCHAL_INT17_LEVEL +#define INTC_GRP13_LEVEL XCHAL_INT18_LEVEL +#define INTC_GRP14_LEVEL XCHAL_INT20_LEVEL +#define INTC_GRP15_LEVEL XCHAL_INT21_LEVEL + + +enum INTC_GROUP { + INTC_GRP0 = 0, + INTC_GRP1, + INTC_GRP2, + INTC_GRP3, + INTC_GRP4, + INTC_GRP5, + INTC_GRP6, + INTC_GRP7, + INTC_GRP8, + INTC_GRP9, + INTC_GRP10, + INTC_GRP11, + INTC_GRP12, + INTC_GRP13, + INTC_GRP14, + INTC_GRP15, + INTC_GRP_NUM, + NO_GRP, +}; + +enum INTC_POL { + INTC_POL_HIGH = 0x0, + INTC_POL_LOW = 0x1, + INTC_POL_NUM, +}; + +struct intc_irq_desc_t { + uint8_t id; + uint8_t group; + uint8_t pol; +}; + +struct intc_desc_t { + uint32_t int_en[INTC_GRP_LEN]; + uint32_t grp_irqs[INTC_GRP_NUM][INTC_GRP_LEN]; + struct intc_irq_desc_t irqs[IRQ_MAX_CHANNEL]; +}; + +struct intc_irq_config { + uint32_t int_en[INTC_GRP_LEN]; +}; + +struct intc_grp_config { + uint32_t grp_irq[INTC_GRP_NUM][INTC_GRP_LEN]; +}; + +struct intc_coreoff_wake_en_config { + uint32_t wake_en[INTC_GRP_LEN]; +}; + +struct intc_sleep_wake_en_config { + uint32_t wake_en[INTC_GRP_LEN]; +}; + +extern const unsigned char grp_pri[INTC_GRP_NUM]; +extern const uint8_t irq2grp_map[IRQ_MAX_CHANNEL]; +extern const uint8_t grp2hifi_irq_map[INTC_GRP_NUM]; +void intc_init(void); + +#ifdef CFG_TICKLESS_SUPPORT +extern struct intc_sleep_wake_en_config sleep_wakeup_src_en; +#endif +#ifdef CFG_CORE_OFF_SUPPORT +extern struct intc_coreoff_wake_en_config coreoff_wakeup_src_en; +#endif + +#endif /* INTC_H */ + diff --git a/src/platform/mt8196/include/platform/drivers/interrupt.h b/src/platform/mt8196/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..71048100df8c --- /dev/null +++ b/src/platform/mt8196/include/platform/drivers/interrupt.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <stdint.h> +#include <platform/drivers/mt_reg_base.h> +#include <platform/drivers/intc.h> + +#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM +#define PLATFORM_IRQ_CHILDREN 32 + +/* MTK_ADSP_IRQ_MASK */ +#define MTK_DSP_OUT_IRQ_MASK 0x3FF + +#define HIFI_IRQ_MAX_CHANNEL 26 + +#define DEFALUT_WAKEUP_SRC_MASK_BIT 0x001A5E13 +#define DEFAULT_WAKEUP_SRC_EN0_BIT 0xA046B550 +#define DEFAULT_WAKEUP_SRC_EN1_BIT 0x00002148 + +#define MTK_DSP_IRQ_MBOX_C0 2 +#define MTK_DSP_IRQ_OSTIMER32_C0 1 +#define IPC0_IRQn IPC_C0_IRQn +#define C2C_SW_IRQn C2C_SW_C0_IRQn +#define CCIF3_IRQn CCIF3_C0_IRQn +#define DMA_IRQn DMA_C0_IRQn +#define AUDIO_IRQn AUDIO_C0_IRQn +#define HIFI5_WDT_IRQn HIFI5_WDT_C0_IRQn +#define APU_MBOX_IRQn APU_MBOX_C0_IRQn +#define PWR_ON_CORE_IRQn PWR_ON_C0_IRQ +#define WAKEUP_SRC_IRQn WAKEUP_SRC_C0_IRQn +#define AXI_DMA_CH0_IRQn AXI_DMA0_IRQn +#define AXI_DMA_CH1_IRQn AXI_DMA2_IRQn + +/* following interrupts are HiFi internal interrupts */ +#define MTK_DSP_IRQ_NMI 25 +#define MTK_DSP_IRQ_PROFILING 29 +#define MTK_DSP_IRQ_WERR 30 +#define MTK_DSP_IRQ_SW 31 +#define MTK_MAX_IRQ_NUM 59 + +/* grouped mailbox IRQ */ +#define MTK_DSP_IRQ_MBOX0 59 +#define MTK_DSP_IRQ_MBOX1 60 +#define MTK_DSP_IRQ_MBOX2 61 +#define MTK_DSP_IRQ_MBOX3 62 +#define MTK_DSP_IRQ_MBOX4 63 + +#define MTK_DSP_MBOX_MASK 0xF + +int mtk_irq_group_id(uint32_t irq); +void intc_irq_unmask(enum IRQn_Type irq); +void intc_irq_mask(enum IRQn_Type irq); +int intc_irq_enable(enum IRQn_Type irq); +int intc_irq_disable(enum IRQn_Type irq); + +#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/mt8196/include/platform/drivers/mt_reg_base.h b/src/platform/mt8196/include/platform/drivers/mt_reg_base.h new file mode 100644 index 000000000000..bb990270512e --- /dev/null +++ b/src/platform/mt8196/include/platform/drivers/mt_reg_base.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + * + */ + +#ifndef MT_REG_BASE_H +#define MT_REG_BASE_H + +#define MTK_DSP_CFGREG_BASE 0x1A000000 /* DSP Register base */ +#define MTK_DSP_CFGREG_SIZE 0x1000 +#define MTK_ADSP_CFGREG_SW_RSTN (MTK_DSP_CFGREG_BASE + 0x0000) +#define MTK_ADSP_HIFI_IO_CONFIG (MTK_DSP_CFGREG_BASE + 0x000c) +#define MTK_ADSP_IRQ_STATUS (MTK_DSP_CFGREG_BASE + 0x0010) +#define MTK_ADSP_SW_INT_SET (MTK_DSP_CFGREG_BASE + 0x0018) +#define MTK_ADSP_SW_INT_CLR (MTK_DSP_CFGREG_BASE + 0x001c) +#define MTK_ADSP_SW_INT_32A (MTK_DSP_CFGREG_BASE + 0x0020) +#define MTK_ADSP_IRQ_MASK (MTK_DSP_CFGREG_BASE + 0x0030) +#define MTK_ADSP_GENERAL_IRQ_SET (MTK_DSP_CFGREG_BASE + 0x0034) +#define MTK_ADSP_GENERAL_IRQ_CLR (MTK_DSP_CFGREG_BASE + 0x0038) +#define MTK_ADSP_DVFSRC_STATE (MTK_DSP_CFGREG_BASE + 0x003c) +#define MTK_ADSP_DVFSRC_REQ (MTK_DSP_CFGREG_BASE + 0x0040) +#define MTK_ADSP_DDREN_REQ_0 (MTK_DSP_CFGREG_BASE + 0x0044) +#define MTK_ADSP_SPM_ACK (MTK_DSP_CFGREG_BASE + 0x004c) +#define MTK_ADSP_IRQ_EN (MTK_DSP_CFGREG_BASE + 0x0050) +#define MTK_ADSP_IRQ_POL_FIX (MTK_DSP_CFGREG_BASE + 0x0054) +#define MTK_ADSP_SPM_WAKEUPSRC_CORE0 (MTK_DSP_CFGREG_BASE + 0x005c) +#define MTK_ADSP_SEMAPHORE (MTK_DSP_CFGREG_BASE + 0x0064) +#define MTK_ADSP_DBG_SEL (MTK_DSP_CFGREG_BASE + 0x0074) +#define MTK_ADSP_DBG_INFO (MTK_DSP_CFGREG_BASE + 0x0078) +#define MTK_ADSP_WDT_CON_C0 (MTK_DSP_CFGREG_BASE + 0x007c) +#define MTK_ADSP_WDT_INIT_VALUE_C0 (MTK_DSP_CFGREG_BASE + 0x0080) +#define MTK_ADSP_WDT_CNT_C0 (MTK_DSP_CFGREG_BASE + 0x0084) +#define MTK_ADSP_WAKEUPSRC_MASK_C0 (MTK_DSP_CFGREG_BASE + 0x00a0) +#define MTK_ADSP_WAKEUPSRC_IRQ_C0 (MTK_DSP_CFGREG_BASE + 0x00a4) +#define MTK_ADSP2SPM_MBOX (MTK_DSP_CFGREG_BASE + 0x00bc) +#define MTK_SPM2ADSP_MBOX (MTK_DSP_CFGREG_BASE + 0x00c0) + +/* intc */ +#define MTK_ADSP_INTC_BASE (MTK_DSP_CFGREG_BASE + 0x14000) + +#define INTC_IRQ_RAW_STA0 (MTK_ADSP_INTC_BASE + 0x000) +#define INTC_IRQ_STA0 (MTK_ADSP_INTC_BASE + 0x008) +#define INTC_IRQ_STA1 (MTK_ADSP_INTC_BASE + 0x00c) +#define INTC_IRQ_EN0 (MTK_ADSP_INTC_BASE + 0x010) +#define INTC_IRQ_POL0 (MTK_ADSP_INTC_BASE + 0x018) +#define INTC_IRQ_WAKE_EN0 (MTK_ADSP_INTC_BASE + 0x020) +#define INTC_IRQ_STAGE1_EN0 (MTK_ADSP_INTC_BASE + 0x030) +#define INTC_IRQ_GRP0_0 (MTK_ADSP_INTC_BASE + 0x040) +#define INTC_IRQ_GRP0_STA0 (MTK_ADSP_INTC_BASE + 0x0C0) +#define INTC_GRP_IRQ_OUT_STA (MTK_ADSP_INTC_BASE + 0x140) + +#define MTK_GPR_RW_REG0 (MTK_DSP_CFGREG_BASE + 0x0440) +#define MTK_GPR_RW_REG1 (MTK_DSP_CFGREG_BASE + 0x0444) +#define MTK_GPR_RW_REG2 (MTK_DSP_CFGREG_BASE + 0x0448) +#define MTK_GPR_RW_REG3 (MTK_DSP_CFGREG_BASE + 0x044c) +#define MTK_GPR_RW_REG4 (MTK_DSP_CFGREG_BASE + 0x0450) +#define MTK_GPR_RW_REG5 (MTK_DSP_CFGREG_BASE + 0x0454) +#define MTK_GPR_RW_REG6 (MTK_DSP_CFGREG_BASE + 0x0458) +#define MTK_GPR_RW_REG7 (MTK_DSP_CFGREG_BASE + 0x045c) +#define MTK_GPR_RW_REG8 (MTK_DSP_CFGREG_BASE + 0x0460) +#define MTK_GPR_RW_REG9 (MTK_DSP_CFGREG_BASE + 0x0464) +#define MTK_GPR_RW_REG10 (MTK_DSP_CFGREG_BASE + 0x0468) +#define MTK_GPR_RW_REG11 (MTK_DSP_CFGREG_BASE + 0x046c) +#define MTK_GPR_RW_REG12 (MTK_DSP_CFGREG_BASE + 0x0470) +#define MTK_GPR_RW_REG13 (MTK_DSP_CFGREG_BASE + 0x0474) +#define MTK_GPR_RW_REG14 (MTK_DSP_CFGREG_BASE + 0x0478) +#define MTK_GPR_RW_REG15 (MTK_DSP_CFGREG_BASE + 0x047c) +#define MTK_GPR_RW_REG16 (MTK_DSP_CFGREG_BASE + 0x0480) +#define MTK_GPR_RW_REG17 (MTK_DSP_CFGREG_BASE + 0x0484) +#define MTK_GPR_RW_REG18 (MTK_DSP_CFGREG_BASE + 0x0488) +#define MTK_GPR_RW_REG19 (MTK_DSP_CFGREG_BASE + 0x048c) +#define MTK_GPR_RW_REG20 (MTK_DSP_CFGREG_BASE + 0x0490) +#define MTK_GPR_RW_REG21 (MTK_DSP_CFGREG_BASE + 0x0494) +#define MTK_GPR_RW_REG22 (MTK_DSP_CFGREG_BASE + 0x0498) +#define MTK_GPR_RW_REG23 (MTK_DSP_CFGREG_BASE + 0x049c) +#define MTK_GPR_RW_REG24 (MTK_DSP_CFGREG_BASE + 0x04a0) +#define MTK_GPR_RW_REG25 (MTK_DSP_CFGREG_BASE + 0x04a4) +#define MTK_GPR_RW_REG26 (MTK_DSP_CFGREG_BASE + 0x04a8) +#define MTK_GPR_RW_REG27 (MTK_DSP_CFGREG_BASE + 0x04ac) +/* use for tickless status */ +#define MTK_GPR_RW_REG28 (MTK_DSP_CFGREG_BASE + 0x04b0) +#define MTK_GPR_RW_REG29 (MTK_DSP_CFGREG_BASE + 0x04b4) + +#define MTK_ADSP_IRQ_OUT_MASK (MTK_DSP_CFGREG_BASE + 0x0500) + +#define MTK_DSP_CKCTRL_BASE (MTK_DSP_CFGREG_BASE + 0x1000) +#define MTK_DSP_CKCTRL_SIZE 0x1000 + +#define MTK_DSP_OS_TIMER_BASE (MTK_DSP_CFGREG_BASE + 0xB000) +#define MTK_DSP_OS_TIMER_SIZE 0x1000 + +#define MTK_DSP_UART0_BASE (MTK_DSP_CFGREG_BASE + 0xD000) +#define MTK_DSP_UART0_SIZE 0x1000 +#define MTK_DSP_BT_UART_BASE (MTK_DSP_CFGREG_BASE + 0xE000) +#define MTK_DSP_BT_UART_SIZE 0x1000 + +#define MTK_DSP_BUS_BASE (MTK_DSP_CFGREG_BASE + 0xF000) +#define MTK_DSP_BUS_SIZE 0x1000 + +#define MTK_DSP_SECURE_BASE (MTK_DSP_CFGREG_BASE + 0x345000) +#define MTK_MBOX_IRQ_IN (MTK_DSP_SECURE_BASE + 0x70) + +/* MBOX registers */ +#define MTK_ADSP_MBOX_BASE (MTK_DSP_CFGREG_BASE + 0x350000) +#define MTK_ADSP_MBOX_REG_BASE(x) (MTK_ADSP_MBOX_BASE + (0x10000 * (x))) +#define MTK_ADSP_MBOX_REG_SIZE (0x50000) +#define MTK_ADSP_MBOX_IN_CMD(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x100) +#define MTK_ADSP_MBOX_IN_CMD_CLR(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x108) +#define MTK_ADSP_MBOX_OUT_CMD(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x104) +#define MTK_ADSP_MBOX_OUT_CMD_CLR(x) (MTK_ADSP_MBOX_REG_BASE(x) + 0x10c) + +#endif /* MT_REG_BASE_H */ diff --git a/src/platform/mt8196/include/platform/drivers/timer.h b/src/platform/mt8196/include/platform/drivers/timer.h new file mode 100644 index 000000000000..8aeacca52981 --- /dev/null +++ b/src/platform/mt8196/include/platform/drivers/timer.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifndef __PLATFORM_DRIVERS_TIMER_H__ +#define __PLATFORM_DRIVERS_TIMER_H__ + +#include <rtos/bit.h> +#include <platform/drivers/mt_reg_base.h> + +/*-------timer:ostimer0-------*/ +enum ostimer { + OSTIMER0 = 0, + OSTIMER1, + OSTIMER2, + OSTIMER3, + NR_TMRS +}; + +#define MTK_TIMER_CON(n) (MTK_DSP_OS_TIMER_BASE + 0x0 + 0x10 * (n)) +#define MTK_TIMER_RST_VAL(n) (MTK_DSP_OS_TIMER_BASE + 0x4 + 0x10 * (n)) +#define MTK_TIMER_CUR_VAL(n) (MTK_DSP_OS_TIMER_BASE + 0x8 + 0x10 * (n)) +#define MTK_TIMER_IRQ_ACK(n) (MTK_DSP_OS_TIMER_BASE + 0xC + 0x10 * (n)) + +#define MTK_TIMER_ENABLE_BIT BIT(0) +#define MTK_TIMER_IRQ_ENABLE BIT(0) +#define MTK_TIMER_IRQ_STA BIT(4) +#define MTK_TIMER_IRQ_CLEAR BIT(5) + +#define MTK_TIMER_CLKSRC_BIT (BIT(4) | BIT(5)) +#define MTK_TIMER_CLK_SRC_CLK_26M 0 +#define MTK_TIMER_CLK_SRC_BCLK BIT(5) +#define MTK_TIMER_CLK_SRC_PCLK (BIT(4) | BIT(5)) + +/*-------platform_timer: 64 bit systimer-------*/ +#define MTK_OSTIMER_CON (MTK_DSP_OS_TIMER_BASE + 0x80) +#define MTK_OSTIMER_CUR_L (MTK_DSP_OS_TIMER_BASE + 0x8C) +#define MTK_OSTIMER_CUR_H (MTK_DSP_OS_TIMER_BASE + 0x90) +#define MTK_OSTIMER_TVAL (MTK_DSP_OS_TIMER_BASE + 0x94) +#define MTK_OSTIMER_IRQ_ACK (MTK_DSP_OS_TIMER_BASE + 0x98) + +#define MTK_OSTIMER_EN_BIT BIT(0) + +#endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/mt8196/include/platform/lib/clk.h b/src/platform/mt8196/include/platform/lib/clk.h new file mode 100644 index 000000000000..f4f311948fb4 --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/clk.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <stdint.h> + +struct sof; + +#define CPU_DEFAULT_IDX 0 + +#define CLK_CPU(x) (x) +#define CLK_DEFAULT_CPU_HZ 26000000 +#define CLK_MAX_CPU_HZ 800000000 +#define NUM_CLOCKS 1 +#define NUM_CPU_FREQ 2 + +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/mt8196/include/platform/lib/cpu.h b/src/platform/mt8196/include/platform/lib/cpu.h new file mode 100644 index 000000000000..f99974213c2f --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/cpu.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/** \brief Id of primary DSP core */ +#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/mt8196/include/platform/lib/dai.h b/src/platform/mt8196/include/platform/lib/dai.h new file mode 100644 index 000000000000..e56a35d5ccc1 --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/dai.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#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/mt8196/include/platform/lib/dma.h b/src/platform/mt8196/include/platform/lib/dma.h new file mode 100644 index 000000000000..419f160cbfd9 --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/dma.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 2 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 32 + +#define DMA_ID_AFE_MEMIF 0 +#define DMA_ID_HOST 1 + +#define dma_chan_irq(dma, chan) dma_irq(dma) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#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/mt8196/include/platform/lib/mailbox.h b/src/platform/mt8196/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..04896aaa3ee5 --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/mailbox.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <stddef.h> +#include <stdint.h> + +/* + * The Window Region on MT8186 SRAM is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_EXCEPT_BASE | Except | SRAM_EXCEPT_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_STREAM_BASE | Stream | SRAM_STREAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer | SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +#define ADSP_IPI_OP_REQ 0x1 +#define ADSP_IPI_OP_RSP 0x2 +void trigger_irq_to_host_req(void); +void trigger_irq_to_host_rsp(void); + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + io_reg_write(MAILBOX_DEBUG_BASE + offset, src); +} + +#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/mt8196/include/platform/lib/memory.h b/src/platform/mt8196/include/platform/lib/memory.h new file mode 100644 index 000000000000..f6d8bd521208 --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/memory.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> + +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN sizeof(void *) + +/* physical DSP addresses */ +#define SRAM_BASE 0x4e100000 +#define SRAM_SIZE 0x80000 + +/* reset vector + rodata + module_init + text + data + bss */ +#define SOF_DATA_SIZE 0x80000 +#define VECTOR_SIZE 0x700 +#define SRAM_START (SRAM_BASE + VECTOR_SIZE) + +#define DRAM_BASE 0x90000000 +#define DRAM0_SIZE 0x500000 +#define MAILBOX_BASE (DRAM_BASE + DRAM0_SIZE) +#define DSP_SYS_SIZE 0xA00000 + +#define UUID_ENTRY_ELF_BASE (SRAM_BASE + SOF_DATA_SIZE) +#define UUID_ENTRY_ELF_SIZE 0x6000 + +#define LOG_ENTRY_ELF_BASE (UUID_ENTRY_ELF_BASE + UUID_ENTRY_ELF_SIZE) +#define LOG_ENTRY_ELF_SIZE 0x20000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE (SRAM_BASE + SRAM_SIZE - EXT_MANIFEST_ELF_BASE) + +/* + * The Memory Layout on MT8189 are organised like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_START | RO Data | SOF_DATA_SIZE | + * | | text | | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | fw_ready | + * +---------------------+----------------+-----------------------------------+ + * | static_uuid | + * +---------------------+----------------+-----------------------------------+ + * | static_log | + * +---------------------+----------------+-----------------------------------+ + * | fw_metadata | + * +---------------------+----------------+-----------------------------------+ + * + * +---------------------+----------------+-----------------------------------+ + * | SOF_DRAM_BASE | | SOF_DRAM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + * | MAILBOX_BASE | | SOF_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define SRAM_OUTBOX_BASE MAILBOX_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +/*4K + 4K +2K + 2K + 4K + 4K = 20KB*/ +#define SOF_MAILBOX_SIZE \ + (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE + SRAM_DEBUG_SIZE + \ + SRAM_EXCEPT_SIZE + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* SOF image on DRAM */ +#define SOF_DRAM_BASE DRAM_BASE +#define SOF_DRAM_SIZE 0x100000 + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 32 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 32 +#define HEAP_RT_COUNT1024 4 +#define HEAP_RT_COUNT2048 2 +#define HEAP_RT_COUNT4096 2 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 128 +#define HEAP_SYS_RT_COUNT512 16 +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ + +#define HEAP_SYSTEM_BASE (SOF_DRAM_BASE + SOF_DRAM_SIZE) +#define HEAP_SYSTEM_SIZE 0x6000 + +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +/*24KB*/ +#define HEAP_SYS_RUNTIME_SIZE \ + (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + \ + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +/*48*(16 +32) + 32*(64 128+256) + 4*(512+1024) + 1*2048 = 24832 = 24.25KB*/ +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + \ + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + \ + HEAP_RT_COUNT512 * 512 + HEAP_RT_COUNT1024 * 1024 + \ + HEAP_RT_COUNT2048 * 2048 + HEAP_RT_COUNT4096 * 4096) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE \ + (DRAM0_SIZE - SOF_DRAM_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE - \ + HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Stack configuration */ +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE /*4KB*/ +#define SOF_STACK_BASE (DRAM_BASE + DRAM0_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x4 +#define SOF_MEM_VECT_TEXT_SIZE 0x1c +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 +#define SOF_MEM_RESET_LIT_SIZE 0x120 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE + +/** \brief EDF task's default stack size in bytes. */ +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +struct sof; + +/** + * \brief Data shared between different cores. + * Does nothing, since mt8186 doesn't support SMP. + */ +#define SHARED_DATA + +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +/** + * \brief Function for keeping shared data synchronized. + * It's used after usage of data shared by different cores. + * Such data is either statically marked with SHARED_DATA + * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. + * Does nothing, since mt8186 doesn't support SMP. + */ + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#endif + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#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/mt8196/include/platform/lib/pm_runtime.h b/src/platform/mt8196/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..7d6213823fd6 --- /dev/null +++ b/src/platform/mt8196/include/platform/lib/pm_runtime.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +static inline 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 The index of the device. + * \param[in] flags The flags, set of RPM_... + */ +static inline 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 The index of the device. + * \param[in] flags The flags, set of RPM_... + */ +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/mt8196/include/platform/mt8196-afe-common.h b/src/platform/mt8196/include/platform/mt8196-afe-common.h new file mode 100755 index 000000000000..e75195b50bd4 --- /dev/null +++ b/src/platform/mt8196/include/platform/mt8196-afe-common.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Darren Ye <darren.ye@mediatek.com> + */ + +#ifndef _MT_8196_AFE_COMMON_H_ +#define _MT_8196_AFE_COMMON_H_ + +enum { + MT8196_MEMIF_START, + MT8196_MEMIF_DL_START = MT8196_MEMIF_START, + MT8196_MEMIF_DL1 = MT8196_MEMIF_DL_START, + MT8196_MEMIF_DL_24CH, + MT8196_MEMIF_DL_END, + MT8196_MEMIF_UL_START = MT8196_MEMIF_DL_END, + MT8196_MEMIF_UL0 = MT8196_MEMIF_UL_START, + MT8196_MEMIF_UL1, + MT8196_MEMIF_UL2, + MT8196_MEMIF_UL_END, + MT8196_MEMIF_END = MT8196_MEMIF_UL_END, + MT8196_MEMIF_DL_NUM = (MT8196_MEMIF_DL_END - MT8196_MEMIF_DL_START), + MT8196_MEMIF_UL_NUM = (MT8196_MEMIF_UL_END - MT8196_MEMIF_UL_START), + MT8196_MEMIF_NUM = (MT8196_MEMIF_END - MT8196_MEMIF_START), +}; + +/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */ +enum { + MT8196_IRQ_0, + MT8196_IRQ_1, + MT8196_IRQ_2, + MT8196_IRQ_3, + MT8196_IRQ_4, + MT8196_IRQ_5, + MT8196_IRQ_6, + MT8196_IRQ_7, + MT8196_IRQ_8, + MT8196_IRQ_9, + MT8196_IRQ_10, + MT8196_IRQ_11, + MT8196_IRQ_12, + MT8196_IRQ_13, + MT8196_IRQ_14, + MT8196_IRQ_15, + MT8196_IRQ_16, + MT8196_IRQ_17, + MT8196_IRQ_18, + MT8196_IRQ_19, + MT8196_IRQ_20, + MT8196_IRQ_21, + MT8196_IRQ_22, + MT8196_IRQ_23, + MT8196_IRQ_24, + MT8196_IRQ_25, + MT8196_IRQ_26, + MT8196_IRQ_31, /* used only for TDM */ + MT8196_IRQ_NUM, +}; + +enum { + MT8196_DAI_I2S_OUT4, /* speaker */ + MT8196_DAI_I2S_OUT6, /* headset out */ + MT8196_DAI_AP_DMIC, /* DMIC */ + MT8196_DAI_I2S_IN6, /* headset mic */ + MT8196_DAI_AP_DMIC_CH34, + MT8196_DAI_NUM, +}; + +#endif diff --git a/src/platform/mt8196/include/platform/mt8196-afe-reg.h b/src/platform/mt8196/include/platform/mt8196-afe-reg.h new file mode 100755 index 000000000000..10c4237dd6b5 --- /dev/null +++ b/src/platform/mt8196/include/platform/mt8196-afe-reg.h @@ -0,0 +1,2979 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Darren Ye <darren.ye@mediatek.com> + */ + +#ifndef _MT8196_AFE_REG_H_ +#define _MT8196_AFE_REG_H_ + +#define AFE_BASE_ADDR 0x1A110000 + +/***************************************************************************** + * R E G I S T E R D E F I N I T I O N + *****************************************************************************/ +/* AFE_DL1_BASE_MSB */ +#define DL1_BASE_ADDR_MSB_SFT 0 +#define DL1_BASE_ADDR_MSB_MASK 0x1ff +#define DL1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL1_BASE */ +#define DL1_BASE_ADDR_SFT 4 +#define DL1_BASE_ADDR_MASK 0xfffffff +#define DL1_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL1_CUR_MSB */ +#define DL1_CUR_PTR_MSB_SFT 0 +#define DL1_CUR_PTR_MSB_MASK 0x1ff +#define DL1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL1_CUR */ +#define DL1_CUR_PTR_SFT 0 +#define DL1_CUR_PTR_MASK 0xffffffff +#define DL1_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL1_END_MSB */ +#define DL1_END_ADDR_MSB_SFT 0 +#define DL1_END_ADDR_MSB_MASK 0x1ff +#define DL1_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL1_END */ +#define DL1_END_ADDR_SFT 4 +#define DL1_END_ADDR_MASK 0xfffffff +#define DL1_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL1_RCH_MON */ +#define DL1_RCH_DATA_SFT 0 +#define DL1_RCH_DATA_MASK 0xffffffff +#define DL1_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL1_LCH_MON */ +#define DL1_LCH_DATA_SFT 0 +#define DL1_LCH_DATA_MASK 0xffffffff +#define DL1_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL1_CON0 */ +#define DL1_ON_SFT 28 +#define DL1_ON_MASK 0x1 +#define DL1_ON_MASK_SFT (0x1 << 28) +#define DL1_ONE_HEART_SEL_SFT 22 +#define DL1_ONE_HEART_SEL_MASK 0x3 +#define DL1_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL1_MINLEN_SFT 20 +#define DL1_MINLEN_MASK 0x3 +#define DL1_MINLEN_MASK_SFT (0x3 << 20) +#define DL1_MAXLEN_SFT 16 +#define DL1_MAXLEN_MASK 0x3 +#define DL1_MAXLEN_MASK_SFT (0x3 << 16) +#define DL1_SEL_DOMAIN_SFT 13 +#define DL1_SEL_DOMAIN_MASK 0x7 +#define DL1_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL1_SEL_FS_SFT 8 +#define DL1_SEL_FS_MASK 0x1f +#define DL1_SEL_FS_MASK_SFT (0x1f << 8) +#define DL1_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL1_PBUF_SIZE_SFT 5 +#define DL1_PBUF_SIZE_MASK 0x3 +#define DL1_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL1_MONO_SFT 4 +#define DL1_MONO_MASK 0x1 +#define DL1_MONO_MASK_SFT (0x1 << 4) +#define DL1_NORMAL_MODE_SFT 3 +#define DL1_NORMAL_MODE_MASK 0x1 +#define DL1_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL1_HALIGN_SFT 2 +#define DL1_HALIGN_MASK 0x1 +#define DL1_HALIGN_MASK_SFT (0x1 << 2) +#define DL1_HD_MODE_SFT 0 +#define DL1_HD_MODE_MASK 0x3 +#define DL1_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL_24CH_BASE_MSB */ +#define DL_24CH_BASE__ADDR_MSB_SFT 0 +#define DL_24CH_BASE__ADDR_MSB_MASK 0x1ff +#define DL_24CH_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_24CH_BASE */ +#define DL_24CH_BASE_ADDR_SFT 4 +#define DL_24CH_BASE_ADDR_MASK 0xfffffff +#define DL_24CH_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL_24CH_CUR_MSB */ +#define DL_24CH_CUR_PTR_MSB_SFT 0 +#define DL_24CH_CUR_PTR_MSB_MASK 0x1ff +#define DL_24CH_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_24CH_CUR */ +#define DL_24CH_CUR_PTR_SFT 0 +#define DL_24CH_CUR_PTR_MASK 0xffffffff +#define DL_24CH_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_END_MSB */ +#define DL_24CH_END_ADDR_MSB_SFT 0 +#define DL_24CH_END_ADDR_MSB_MASK 0x1ff +#define DL_24CH_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_24CH_END */ +#define DL_24CH_END_ADDR_SFT 4 +#define DL_24CH_END_ADDR_MASK 0xfffffff +#define DL_24CH_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL_24CH_CON0 */ +#define DL_24CH_ON_SFT 31 +#define DL_24CH_ON_MASK 0x1 +#define DL_24CH_ON_MASK_SFT (0x1 << 31) +#define DL_24CH_NUM_SFT 24 +#define DL_24CH_NUM_MASK 0x3f +#define DL_24CH_NUM_MASK_SFT (0x3f << 24) +#define DL_24CH_ONE_HEART_SEL_SFT 22 +#define DL_24CH_ONE_HEART_SEL_MASK 0x3 +#define DL_24CH_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL_24CH_MINLEN_SFT 20 +#define DL_24CH_MINLEN_MASK 0x3 +#define DL_24CH_MINLEN_MASK_SFT (0x3 << 20) +#define DL_24CH_MAXLEN_SFT 16 +#define DL_24CH_MAXLEN_MASK 0x3 +#define DL_24CH_MAXLEN_MASK_SFT (0x3 << 16) +#define DL_24CH_SEL_DOMAIN_SFT 13 +#define DL_24CH_SEL_DOMAIN_MASK 0x7 +#define DL_24CH_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL_24CH_SEL_FS_SFT 8 +#define DL_24CH_SEL_FS_MASK 0x1f +#define DL_24CH_SEL_FS_MASK_SFT (0x1f << 8) +#define DL_24CH_BUF_EMPTY_CLR_SFT 7 +#define DL_24CH_BUF_EMPTY_CLR_MASK 0x1 +#define DL_24CH_BUF_EMPTY_CLR_MASK_SFT (0x1 << 7) +#define DL_24CH_PBUF_SIZE_SFT 5 +#define DL_24CH_PBUF_SIZE_MASK 0x3 +#define DL_24CH_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL_24CH_HANG_CLR_SFT 4 +#define DL_24CH_HANG_CLR_MASK 0x1 +#define DL_24CH_HANG_CLR_MASK_SFT (0x1 << 4) +#define DL_24CH_NORMAL_MODE_SFT 3 +#define DL_24CH_NORMAL_MODE_MASK 0x1 +#define DL_24CH_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL_24CH_HALIGN_SFT 2 +#define DL_24CH_HALIGN_MASK 0x1 +#define DL_24CH_HALIGN_MASK_SFT (0x1 << 2) +#define DL_24CH_HD_MODE_SFT 0 +#define DL_24CH_HD_MODE_MASK 0x3 +#define DL_24CH_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL24_BASE_MSB */ +#define DL24_BASE__ADDR_MSB_SFT 0 +#define DL24_BASE__ADDR_MSB_MASK 0x1ff +#define DL24_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL24_BASE */ +#define DL24_BASE_ADDR_SFT 4 +#define DL24_BASE_ADDR_MASK 0xfffffff +#define DL24_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL24_CUR_MSB */ +#define DL24_CUR_PTR_MSB_SFT 0 +#define DL24_CUR_PTR_MSB_MASK 0x1ff +#define DL24_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL24_CUR */ +#define DL24_CUR_PTR_SFT 0 +#define DL24_CUR_PTR_MASK 0xffffffff +#define DL24_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL24_END_MSB */ +#define DL24_END_ADDR_MSB_SFT 0 +#define DL24_END_ADDR_MSB_MASK 0x1ff +#define DL24_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL24_END */ +#define DL24_END_ADDR_SFT 4 +#define DL24_END_ADDR_MASK 0xfffffff +#define DL24_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL24_RCH_MON */ +#define DL24_RCH_DATA_SFT 0 +#define DL24_RCH_DATA_MASK 0xffffffff +#define DL24_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL24_LCH_MON */ +#define DL24_LCH_DATA_SFT 0 +#define DL24_LCH_DATA_MASK 0xffffffff +#define DL24_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL24_CON0 */ +#define DL24_ON_SFT 28 +#define DL24_ON_MASK 0x1 +#define DL24_ON_MASK_SFT (0x1 << 28) +#define DL24_ONE_HEART_SEL_SFT 22 +#define DL24_ONE_HEART_SEL_MASK 0x3 +#define DL24_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL24_MINLEN_SFT 20 +#define DL24_MINLEN_MASK 0x3 +#define DL24_MINLEN_MASK_SFT (0x3 << 20) +#define DL24_MAXLEN_SFT 16 +#define DL24_MAXLEN_MASK 0x3 +#define DL24_MAXLEN_MASK_SFT (0x3 << 16) +#define DL24_SEL_DOMAIN_SFT 13 +#define DL24_SEL_DOMAIN_MASK 0x7 +#define DL24_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL24_SEL_FS_SFT 8 +#define DL24_SEL_FS_MASK 0x1f +#define DL24_SEL_FS_MASK_SFT (0x1f << 8) +#define DL24_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL24_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL24_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL24_PBUF_SIZE_SFT 5 +#define DL24_PBUF_SIZE_MASK 0x3 +#define DL24_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL24_MONO_SFT 4 +#define DL24_MONO_MASK 0x1 +#define DL24_MONO_MASK_SFT (0x1 << 4) +#define DL24_NORMAL_MODE_SFT 3 +#define DL24_NORMAL_MODE_MASK 0x1 +#define DL24_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL24_HALIGN_SFT 2 +#define DL24_HALIGN_MASK 0x1 +#define DL24_HALIGN_MASK_SFT (0x1 << 2) +#define DL24_HD_MODE_SFT 0 +#define DL24_HD_MODE_MASK 0x3 +#define DL24_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL0_BASE_MSB */ +#define VUL0_BASE_ADDR_MSB_SFT 0 +#define VUL0_BASE_ADDR_MSB_MASK 0x1ff +#define VUL0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL0_BASE */ +#define VUL0_BASE_ADDR_SFT 4 +#define VUL0_BASE_ADDR_MASK 0xfffffff +#define VUL0_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL0_CUR_MSB */ +#define VUL0_CUR_PTR_MSB_SFT 0 +#define VUL0_CUR_PTR_MSB_MASK 0x1ff +#define VUL0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL0_CUR */ +#define VUL0_CUR_PTR_SFT 0 +#define VUL0_CUR_PTR_MASK 0xffffffff +#define VUL0_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL0_END_MSB */ +#define VUL0_END_ADDR_MSB_SFT 0 +#define VUL0_END_ADDR_MSB_MASK 0x1ff +#define VUL0_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL0_END */ +#define VUL0_END_ADDR_SFT 4 +#define VUL0_END_ADDR_MASK 0xfffffff +#define VUL0_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL0_RCH_MON */ +#define VUL0_RCH_DATA_SFT 0 +#define VUL0_RCH_DATA_MASK 0xffffffff +#define VUL0_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL0_LCH_MON */ +#define VUL0_LCH_DATA_SFT 0 +#define VUL0_LCH_DATA_MASK 0xffffffff +#define VUL0_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL0_CON0 */ +#define VUL0_ON_SFT 28 +#define VUL0_ON_MASK 0x1 +#define VUL0_ON_MASK_SFT (0x1 << 28) +#define VUL0_MINLEN_SFT 20 +#define VUL0_MINLEN_MASK 0x3 +#define VUL0_MINLEN_MASK_SFT (0x3 << 20) +#define VUL0_MAXLEN_SFT 16 +#define VUL0_MAXLEN_MASK 0x3 +#define VUL0_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL0_SEL_DOMAIN_SFT 13 +#define VUL0_SEL_DOMAIN_MASK 0x7 +#define VUL0_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL0_SEL_FS_SFT 8 +#define VUL0_SEL_FS_MASK 0x1f +#define VUL0_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL0_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL0_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL0_WR_SIGN_SFT 6 +#define VUL0_WR_SIGN_MASK 0x1 +#define VUL0_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL0_R_MONO_SFT 5 +#define VUL0_R_MONO_MASK 0x1 +#define VUL0_R_MONO_MASK_SFT (0x1 << 5) +#define VUL0_MONO_SFT 4 +#define VUL0_MONO_MASK 0x1 +#define VUL0_MONO_MASK_SFT (0x1 << 4) +#define VUL0_NORMAL_MODE_SFT 3 +#define VUL0_NORMAL_MODE_MASK 0x1 +#define VUL0_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL0_HALIGN_SFT 2 +#define VUL0_HALIGN_MASK 0x1 +#define VUL0_HALIGN_MASK_SFT (0x1 << 2) +#define VUL0_HD_MODE_SFT 0 +#define VUL0_HD_MODE_MASK 0x3 +#define VUL0_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL1_BASE_MSB */ +#define VUL1_BASE_ADDR_MSB_SFT 0 +#define VUL1_BASE_ADDR_MSB_MASK 0x1ff +#define VUL1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL1_BASE */ +#define VUL1_BASE_ADDR_SFT 4 +#define VUL1_BASE_ADDR_MASK 0xfffffff +#define VUL1_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL1_CUR_MSB */ +#define VUL1_CUR_PTR_MSB_SFT 0 +#define VUL1_CUR_PTR_MSB_MASK 0x1ff +#define VUL1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL1_CUR */ +#define VUL1_CUR_PTR_SFT 0 +#define VUL1_CUR_PTR_MASK 0xffffffff +#define VUL1_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL1_END_MSB */ +#define VUL1_END_ADDR_MSB_SFT 0 +#define VUL1_END_ADDR_MSB_MASK 0x1ff +#define VUL1_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL1_END */ +#define VUL1_END_ADDR_SFT 4 +#define VUL1_END_ADDR_MASK 0xfffffff +#define VUL1_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL1_RCH_MON */ +#define VUL1_RCH_DATA_SFT 0 +#define VUL1_RCH_DATA_MASK 0xffffffff +#define VUL1_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL1_LCH_MON */ +#define VUL1_LCH_DATA_SFT 0 +#define VUL1_LCH_DATA_MASK 0xffffffff +#define VUL1_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL1_CON0 */ +#define VUL1_ON_SFT 28 +#define VUL1_ON_MASK 0x1 +#define VUL1_ON_MASK_SFT (0x1 << 28) +#define VUL1_MINLEN_SFT 20 +#define VUL1_MINLEN_MASK 0x3 +#define VUL1_MINLEN_MASK_SFT (0x3 << 20) +#define VUL1_MAXLEN_SFT 16 +#define VUL1_MAXLEN_MASK 0x3 +#define VUL1_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL1_SEL_DOMAIN_SFT 13 +#define VUL1_SEL_DOMAIN_MASK 0x7 +#define VUL1_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL1_SEL_FS_SFT 8 +#define VUL1_SEL_FS_MASK 0x1f +#define VUL1_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL1_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL1_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL1_WR_SIGN_SFT 6 +#define VUL1_WR_SIGN_MASK 0x1 +#define VUL1_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL1_R_MONO_SFT 5 +#define VUL1_R_MONO_MASK 0x1 +#define VUL1_R_MONO_MASK_SFT (0x1 << 5) +#define VUL1_MONO_SFT 4 +#define VUL1_MONO_MASK 0x1 +#define VUL1_MONO_MASK_SFT (0x1 << 4) +#define VUL1_NORMAL_MODE_SFT 3 +#define VUL1_NORMAL_MODE_MASK 0x1 +#define VUL1_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL1_HALIGN_SFT 2 +#define VUL1_HALIGN_MASK 0x1 +#define VUL1_HALIGN_MASK_SFT (0x1 << 2) +#define VUL1_HD_MODE_SFT 0 +#define VUL1_HD_MODE_MASK 0x3 +#define VUL1_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL2_BASE_MSB */ +#define VUL2_BASE_ADDR_MSB_SFT 0 +#define VUL2_BASE_ADDR_MSB_MASK 0x1ff +#define VUL2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL2_BASE */ +#define VUL2_BASE_ADDR_SFT 4 +#define VUL2_BASE_ADDR_MASK 0xfffffff +#define VUL2_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL2_CUR_MSB */ +#define VUL2_CUR_PTR_MSB_SFT 0 +#define VUL2_CUR_PTR_MSB_MASK 0x1ff +#define VUL2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL2_CUR */ +#define VUL2_CUR_PTR_SFT 0 +#define VUL2_CUR_PTR_MASK 0xffffffff +#define VUL2_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL2_END_MSB */ +#define VUL2_END_ADDR_MSB_SFT 0 +#define VUL2_END_ADDR_MSB_MASK 0x1ff +#define VUL2_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL2_END */ +#define VUL2_END_ADDR_SFT 4 +#define VUL2_END_ADDR_MASK 0xfffffff +#define VUL2_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL2_RCH_MON */ +#define VUL2_RCH_DATA_SFT 0 +#define VUL2_RCH_DATA_MASK 0xffffffff +#define VUL2_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL2_LCH_MON */ +#define VUL2_LCH_DATA_SFT 0 +#define VUL2_LCH_DATA_MASK 0xffffffff +#define VUL2_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL2_CON0 */ +#define VUL2_ON_SFT 28 +#define VUL2_ON_MASK 0x1 +#define VUL2_ON_MASK_SFT (0x1 << 28) +#define VUL2_MINLEN_SFT 20 +#define VUL2_MINLEN_MASK 0x3 +#define VUL2_MINLEN_MASK_SFT (0x3 << 20) +#define VUL2_MAXLEN_SFT 16 +#define VUL2_MAXLEN_MASK 0x3 +#define VUL2_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL2_SEL_DOMAIN_SFT 13 +#define VUL2_SEL_DOMAIN_MASK 0x7 +#define VUL2_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL2_SEL_FS_SFT 8 +#define VUL2_SEL_FS_MASK 0x1f +#define VUL2_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL2_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL2_WR_SIGN_SFT 6 +#define VUL2_WR_SIGN_MASK 0x1 +#define VUL2_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL2_R_MONO_SFT 5 +#define VUL2_R_MONO_MASK 0x1 +#define VUL2_R_MONO_MASK_SFT (0x1 << 5) +#define VUL2_MONO_SFT 4 +#define VUL2_MONO_MASK 0x1 +#define VUL2_MONO_MASK_SFT (0x1 << 4) +#define VUL2_NORMAL_MODE_SFT 3 +#define VUL2_NORMAL_MODE_MASK 0x1 +#define VUL2_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL2_HALIGN_SFT 2 +#define VUL2_HALIGN_MASK 0x1 +#define VUL2_HALIGN_MASK_SFT (0x1 << 2) +#define VUL2_HD_MODE_SFT 0 +#define VUL2_HD_MODE_MASK 0x3 +#define VUL2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL_24CH_CH0_MON */ +#define DL_24CH_CH0_DATA_SFT 0 +#define DL_24CH_CH0_DATA_MASK 0xffffffff +#define DL_24CH_CH0_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH1_MON */ +#define DL_24CH_CH1_DATA_SFT 0 +#define DL_24CH_CH1_DATA_MASK 0xffffffff +#define DL_24CH_CH1_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH2_MON */ +#define DL_24CH_CH2_DATA_SFT 0 +#define DL_24CH_CH2_DATA_MASK 0xffffffff +#define DL_24CH_CH2_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH3_MON */ +#define DL_24CH_CH3_DATA_SFT 0 +#define DL_24CH_CH3_DATA_MASK 0xffffffff +#define DL_24CH_CH3_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH4_MON */ +#define DL_24CH_CH4_DATA_SFT 0 +#define DL_24CH_CH4_DATA_MASK 0xffffffff +#define DL_24CH_CH4_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH5_MON */ +#define DL_24CH_CH5_DATA_SFT 0 +#define DL_24CH_CH5_DATA_MASK 0xffffffff +#define DL_24CH_CH5_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH6_MON */ +#define DL_24CH_CH6_DATA_SFT 0 +#define DL_24CH_CH6_DATA_MASK 0xffffffff +#define DL_24CH_CH6_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH7_MON */ +#define DL_24CH_CH7_DATA_SFT 0 +#define DL_24CH_CH7_DATA_MASK 0xffffffff +#define DL_24CH_CH7_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH8_MON */ +#define DL_24CH_CH8_DATA_SFT 0 +#define DL_24CH_CH8_DATA_MASK 0xffffffff +#define DL_24CH_CH8_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH9_MON */ +#define DL_24CH_CH9_DATA_SFT 0 +#define DL_24CH_CH9_DATA_MASK 0xffffffff +#define DL_24CH_CH9_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH10_MON */ +#define DL_24CH_CH10_DATA_SFT 0 +#define DL_24CH_CH10_DATA_MASK 0xffffffff +#define DL_24CH_CH10_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH11_MON */ +#define DL_24CH_CH11_DATA_SFT 0 +#define DL_24CH_CH11_DATA_MASK 0xffffffff +#define DL_24CH_CH11_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH12_MON */ +#define DL_24CH_CH12_DATA_SFT 0 +#define DL_24CH_CH12_DATA_MASK 0xffffffff +#define DL_24CH_CH12_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH13_MON */ +#define DL_24CH_CH13_DATA_SFT 0 +#define DL_24CH_CH13_DATA_MASK 0xffffffff +#define DL_24CH_CH13_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH14_MON */ +#define DL_24CH_CH14_DATA_SFT 0 +#define DL_24CH_CH14_DATA_MASK 0xffffffff +#define DL_24CH_CH14_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH15_MON */ +#define DL_24CH_CH15_DATA_SFT 0 +#define DL_24CH_CH15_DATA_MASK 0xffffffff +#define DL_24CH_CH15_DATA_MASK_SFT (0xffffffff << 0) + +#define AUDIO_TOP_CON0 0x0 +#define AUDIO_TOP_CON1 0x4 +#define AUDIO_TOP_CON2 0x8 +#define AUDIO_TOP_CON3 0xc +#define AUDIO_TOP_CON4 0x10 +#define AUDIO_ENGEN_CON0 0x14 +#define AUDIO_ENGEN_CON0_USER1 0x18 +#define AUDIO_ENGEN_CON0_USER2 0x1c +#define AFE_SINEGEN_CON0 0x20 +#define AFE_SINEGEN_CON1 0x24 +#define AFE_SINEGEN_CON2 0x28 +#define AFE_SINEGEN_CON3 0x2c +#define AFE_APLL1_TUNER_CFG 0x30 +#define AFE_APLL1_TUNER_MON0 0x34 +#define AFE_APLL2_TUNER_CFG 0x38 +#define AFE_APLL2_TUNER_MON0 0x3c +#define AUDIO_TOP_RG0 0x4c +#define AUDIO_TOP_RG1 0x50 +#define AUDIO_TOP_RG2 0x54 +#define AUDIO_TOP_RG3 0x58 +#define AUDIO_TOP_RG4 0x5c +#define AFE_SPM_CONTROL_REQ 0x60 +#define AFE_SPM_CONTROL_ACK 0x64 +#define AUD_TOP_CFG_VCORE_RG 0x68 +#define AUDIO_TOP_IP_VERSION 0x6c +#define AUDIO_ENGEN_CON0_MON 0x7c +#define AUD_TOP_CFG_VLP_RG 0x98 +#define AUD_TOP_MON_RG 0x9c +#define AUDIO_USE_DEFAULT_DELSEL0 0xa0 +#define AUDIO_USE_DEFAULT_DELSEL1 0xa4 +#define AUDIO_USE_DEFAULT_DELSEL2 0xa8 +#define AFE_CONNSYS_I2S_IPM_VER_MON 0xb0 +#define AFE_CONNSYS_I2S_MON_SEL 0xb4 +#define AFE_CONNSYS_I2S_MON 0xb8 +#define AFE_CONNSYS_I2S_CON 0xbc +#define AFE_PCM0_INTF_CON0 0xc0 +#define AFE_PCM0_INTF_CON1 0xc4 +#define AFE_PCM_INTF_MON 0xc8 +#define AFE_PCM1_INTF_CON0 0xd0 +#define AFE_PCM1_INTF_CON1 0xd4 +#define AFE_PCM_TOP_IP_VERSION 0xe8 +#define AFE_IRQ_MCU_EN 0x100 +#define AFE_IRQ_MCU_DSP_EN 0x104 +#define AFE_IRQ_MCU_DSP2_EN 0x108 +#define AFE_IRQ_MCU_SCP_EN 0x10c +#define AFE_CUSTOM_IRQ_MCU_EN 0x110 +#define AFE_CUSTOM_IRQ_MCU_DSP_EN 0x114 +#define AFE_CUSTOM_IRQ_MCU_DSP2_EN 0x118 +#define AFE_CUSTOM_IRQ_MCU_SCP_EN 0x11c +#define AFE_IRQ_MCU_STATUS 0x120 +#define AFE_CUSTOM_IRQ_MCU_STATUS 0x124 +#define AFE_IRQ0_MCU_CFG0 0x140 +#define AFE_IRQ0_MCU_CFG1 0x144 +#define AFE_IRQ1_MCU_CFG0 0x148 +#define AFE_IRQ1_MCU_CFG1 0x14c +#define AFE_IRQ2_MCU_CFG0 0x150 +#define AFE_IRQ2_MCU_CFG1 0x154 +#define AFE_IRQ3_MCU_CFG0 0x158 +#define AFE_IRQ3_MCU_CFG1 0x15c +#define AFE_IRQ4_MCU_CFG0 0x160 +#define AFE_IRQ4_MCU_CFG1 0x164 +#define AFE_IRQ5_MCU_CFG0 0x168 +#define AFE_IRQ5_MCU_CFG1 0x16c +#define AFE_IRQ6_MCU_CFG0 0x170 +#define AFE_IRQ6_MCU_CFG1 0x174 +#define AFE_IRQ7_MCU_CFG0 0x178 +#define AFE_IRQ7_MCU_CFG1 0x17c +#define AFE_IRQ8_MCU_CFG0 0x180 +#define AFE_IRQ8_MCU_CFG1 0x184 +#define AFE_IRQ9_MCU_CFG0 0x188 +#define AFE_IRQ9_MCU_CFG1 0x18c +#define AFE_IRQ10_MCU_CFG0 0x190 +#define AFE_IRQ10_MCU_CFG1 0x194 +#define AFE_IRQ11_MCU_CFG0 0x198 +#define AFE_IRQ11_MCU_CFG1 0x19c +#define AFE_IRQ12_MCU_CFG0 0x1a0 +#define AFE_IRQ12_MCU_CFG1 0x1a4 +#define AFE_IRQ13_MCU_CFG0 0x1a8 +#define AFE_IRQ13_MCU_CFG1 0x1ac +#define AFE_IRQ14_MCU_CFG0 0x1b0 +#define AFE_IRQ14_MCU_CFG1 0x1b4 +#define AFE_IRQ15_MCU_CFG0 0x1b8 +#define AFE_IRQ15_MCU_CFG1 0x1bc +#define AFE_IRQ16_MCU_CFG0 0x1c0 +#define AFE_IRQ16_MCU_CFG1 0x1c4 +#define AFE_IRQ17_MCU_CFG0 0x1c8 +#define AFE_IRQ17_MCU_CFG1 0x1cc +#define AFE_IRQ18_MCU_CFG0 0x1d0 +#define AFE_IRQ18_MCU_CFG1 0x1d4 +#define AFE_IRQ19_MCU_CFG0 0x1d8 +#define AFE_IRQ19_MCU_CFG1 0x1dc +#define AFE_IRQ20_MCU_CFG0 0x1e0 +#define AFE_IRQ20_MCU_CFG1 0x1e4 +#define AFE_IRQ21_MCU_CFG0 0x1e8 +#define AFE_IRQ21_MCU_CFG1 0x1ec +#define AFE_IRQ22_MCU_CFG0 0x1f0 +#define AFE_IRQ22_MCU_CFG1 0x1f4 +#define AFE_IRQ23_MCU_CFG0 0x1f8 +#define AFE_IRQ23_MCU_CFG1 0x1fc +#define AFE_IRQ24_MCU_CFG0 0x200 +#define AFE_IRQ24_MCU_CFG1 0x204 +#define AFE_IRQ25_MCU_CFG0 0x208 +#define AFE_IRQ25_MCU_CFG1 0x20c +#define AFE_IRQ26_MCU_CFG0 0x210 +#define AFE_IRQ26_MCU_CFG1 0x214 +#define AFE_CUSTOM_IRQ0_MCU_CFG0 0x268 +#define AFE_IRQ_MCU_MON0 0x300 +#define AFE_IRQ_MCU_MON1 0x304 +#define AFE_IRQ_MCU_MON2 0x308 +#define AFE_IRQ0_CNT_MON 0x310 +#define AFE_IRQ1_CNT_MON 0x314 +#define AFE_IRQ2_CNT_MON 0x318 +#define AFE_IRQ3_CNT_MON 0x31c +#define AFE_IRQ4_CNT_MON 0x320 +#define AFE_IRQ5_CNT_MON 0x324 +#define AFE_IRQ6_CNT_MON 0x328 +#define AFE_IRQ7_CNT_MON 0x32c +#define AFE_IRQ8_CNT_MON 0x330 +#define AFE_IRQ9_CNT_MON 0x334 +#define AFE_IRQ10_CNT_MON 0x338 +#define AFE_IRQ11_CNT_MON 0x33c +#define AFE_IRQ12_CNT_MON 0x340 +#define AFE_IRQ13_CNT_MON 0x344 +#define AFE_IRQ14_CNT_MON 0x348 +#define AFE_IRQ15_CNT_MON 0x34c +#define AFE_IRQ16_CNT_MON 0x350 +#define AFE_IRQ17_CNT_MON 0x354 +#define AFE_IRQ18_CNT_MON 0x358 +#define AFE_IRQ19_CNT_MON 0x35c +#define AFE_IRQ20_CNT_MON 0x360 +#define AFE_IRQ21_CNT_MON 0x364 +#define AFE_IRQ22_CNT_MON 0x368 +#define AFE_IRQ23_CNT_MON 0x36c +#define AFE_IRQ24_CNT_MON 0x370 +#define AFE_IRQ25_CNT_MON 0x374 +#define AFE_IRQ26_CNT_MON 0x378 +#define AFE_CUSTOM_IRQ0_CNT_MON 0x390 +#define AFE_CUSTOM_IRQ0_MCU_CFG1 0x3dc +#define AFE_GAIN0_CON0 0x400 +#define AFE_GAIN0_CON1_R 0x404 +#define AFE_GAIN0_CON1_L 0x408 +#define AFE_GAIN0_CON2 0x40c +#define AFE_GAIN0_CON3 0x410 +#define AFE_GAIN0_CUR_R 0x414 +#define AFE_GAIN0_CUR_L 0x418 +#define AFE_GAIN1_CON0 0x41c +#define AFE_GAIN1_CON1_R 0x420 +#define AFE_GAIN1_CON1_L 0x424 +#define AFE_GAIN1_CON2 0x428 +#define AFE_GAIN1_CON3 0x42c +#define AFE_GAIN1_CUR_R 0x430 +#define AFE_GAIN1_CUR_L 0x434 +#define AFE_GAIN2_CON0 0x438 +#define AFE_GAIN2_CON1_R 0x43c +#define AFE_GAIN2_CON1_L 0x440 +#define AFE_GAIN2_CON2 0x444 +#define AFE_GAIN2_CON3 0x448 +#define AFE_GAIN2_CUR_R 0x44c +#define AFE_GAIN2_CUR_L 0x450 +#define AFE_GAIN3_CON0 0x454 +#define AFE_GAIN3_CON1_R 0x458 +#define AFE_GAIN3_CON1_L 0x45c +#define AFE_GAIN3_CON2 0x460 +#define AFE_GAIN3_CON3 0x464 +#define AFE_GAIN3_CUR_R 0x468 +#define AFE_GAIN3_CUR_L 0x46c +#define AFE_STF_CON0 0xb80 +#define AFE_STF_CON1 0xb84 +#define AFE_STF_COEFF 0xb88 +#define AFE_STF_GAIN 0xb8c +#define AFE_STF_MON 0xb90 +#define AFE_STF_IP_VERSION 0xb94 +#define AFE_CM0_CON0 0xba0 +#define AFE_CM0_MON 0xba4 +#define AFE_CM0_IP_VERSION 0xba8 +#define AFE_CM1_CON0 0xbb0 +#define AFE_CM1_MON 0xbb4 +#define AFE_CM1_IP_VERSION 0xbb8 +#define AFE_CM2_CON0 0xbc0 +#define AFE_CM2_MON 0xbc4 +#define AFE_CM2_IP_VERSION 0xbc8 +#define AFE_ADDA_UL0_SRC_CON0 0xbd0 +#define AFE_ADDA_UL0_SRC_CON1 0xbd4 +#define AFE_ADDA_UL0_SRC_CON2 0xbd8 +#define AFE_ADDA_UL0_SRC_DEBUG 0xbdc +#define AFE_ADDA_UL0_SRC_DEBUG_MON0 0xbe0 +#define AFE_ADDA_UL0_SRC_MON0 0xbe4 +#define AFE_ADDA_UL0_SRC_MON1 0xbe8 +#define AFE_ADDA_UL0_IIR_COEF_02_01 0xbec +#define AFE_ADDA_UL0_IIR_COEF_04_03 0xbf0 +#define AFE_ADDA_UL0_IIR_COEF_06_05 0xbf4 +#define AFE_ADDA_UL0_IIR_COEF_08_07 0xbf8 +#define AFE_ADDA_UL0_IIR_COEF_10_09 0xbfc +#define AFE_ADDA_UL0_ULCF_CFG_02_01 0xc00 +#define AFE_ADDA_UL0_ULCF_CFG_04_03 0xc04 +#define AFE_ADDA_UL0_ULCF_CFG_06_05 0xc08 +#define AFE_ADDA_UL0_ULCF_CFG_08_07 0xc0c +#define AFE_ADDA_UL0_ULCF_CFG_10_09 0xc10 +#define AFE_ADDA_UL0_ULCF_CFG_12_11 0xc14 +#define AFE_ADDA_UL0_ULCF_CFG_14_13 0xc18 +#define AFE_ADDA_UL0_ULCF_CFG_16_15 0xc1c +#define AFE_ADDA_UL0_ULCF_CFG_18_17 0xc20 +#define AFE_ADDA_UL0_ULCF_CFG_20_19 0xc24 +#define AFE_ADDA_UL0_ULCF_CFG_22_21 0xc28 +#define AFE_ADDA_UL0_ULCF_CFG_24_23 0xc2c +#define AFE_ADDA_UL0_ULCF_CFG_26_25 0xc30 +#define AFE_ADDA_UL0_ULCF_CFG_28_27 0xc34 +#define AFE_ADDA_UL0_ULCF_CFG_30_29 0xc38 +#define AFE_ADDA_UL0_ULCF_CFG_32_31 0xc3c +#define AFE_ADDA_UL0_IP_VERSION 0xc4c +#define AFE_ADDA_UL1_SRC_CON0 0xc50 +#define AFE_ADDA_UL1_SRC_CON1 0xc54 +#define AFE_ADDA_UL1_SRC_CON2 0xc58 +#define AFE_ADDA_UL1_SRC_DEBUG 0xc5c +#define AFE_ADDA_UL1_SRC_DEBUG_MON0 0xc60 +#define AFE_ADDA_UL1_SRC_MON0 0xc64 +#define AFE_ADDA_UL1_SRC_MON1 0xc68 +#define AFE_ADDA_UL1_IIR_COEF_02_01 0xc6c +#define AFE_ADDA_UL1_IIR_COEF_04_03 0xc70 +#define AFE_ADDA_UL1_IIR_COEF_06_05 0xc74 +#define AFE_ADDA_UL1_IIR_COEF_08_07 0xc78 +#define AFE_ADDA_UL1_IIR_COEF_10_09 0xc7c +#define AFE_ADDA_UL1_ULCF_CFG_02_01 0xc80 +#define AFE_ADDA_UL1_ULCF_CFG_04_03 0xc84 +#define AFE_ADDA_UL1_ULCF_CFG_06_05 0xc88 +#define AFE_ADDA_UL1_ULCF_CFG_08_07 0xc8c +#define AFE_ADDA_UL1_ULCF_CFG_10_09 0xc90 +#define AFE_ADDA_UL1_ULCF_CFG_12_11 0xc94 +#define AFE_ADDA_UL1_ULCF_CFG_14_13 0xc98 +#define AFE_ADDA_UL1_ULCF_CFG_16_15 0xc9c +#define AFE_ADDA_UL1_ULCF_CFG_18_17 0xca0 +#define AFE_ADDA_UL1_ULCF_CFG_20_19 0xca4 +#define AFE_ADDA_UL1_ULCF_CFG_22_21 0xca8 +#define AFE_ADDA_UL1_ULCF_CFG_24_23 0xcac +#define AFE_ADDA_UL1_ULCF_CFG_26_25 0xcb0 +#define AFE_ADDA_UL1_ULCF_CFG_28_27 0xcb4 +#define AFE_ADDA_UL1_ULCF_CFG_30_29 0xcb8 +#define AFE_ADDA_UL1_ULCF_CFG_32_31 0xcbc +#define AFE_ADDA_UL1_IP_VERSION 0xccc +#define AFE_ADDA_UL2_SRC_CON0 0xcd0 +#define AFE_ADDA_UL2_SRC_CON1 0xcd4 +#define AFE_ADDA_UL2_SRC_CON2 0xcd8 +#define AFE_ADDA_UL2_SRC_DEBUG 0xcdc +#define AFE_ADDA_UL2_SRC_DEBUG_MON0 0xce0 +#define AFE_ADDA_UL2_SRC_MON0 0xce4 +#define AFE_ADDA_UL2_SRC_MON1 0xce8 +#define AFE_ADDA_UL2_IIR_COEF_02_01 0xcec +#define AFE_ADDA_UL2_IIR_COEF_04_03 0xcf0 +#define AFE_ADDA_UL2_IIR_COEF_06_05 0xcf4 +#define AFE_ADDA_UL2_IIR_COEF_08_07 0xcf8 +#define AFE_ADDA_UL2_IIR_COEF_10_09 0xcfc +#define AFE_ADDA_UL2_ULCF_CFG_02_01 0xd00 +#define AFE_ADDA_UL2_ULCF_CFG_04_03 0xd04 +#define AFE_ADDA_UL2_ULCF_CFG_06_05 0xd08 +#define AFE_ADDA_UL2_ULCF_CFG_08_07 0xd0c +#define AFE_ADDA_UL2_ULCF_CFG_10_09 0xd10 +#define AFE_ADDA_UL2_ULCF_CFG_12_11 0xd14 +#define AFE_ADDA_UL2_ULCF_CFG_14_13 0xd18 +#define AFE_ADDA_UL2_ULCF_CFG_16_15 0xd1c +#define AFE_ADDA_UL2_ULCF_CFG_18_17 0xd20 +#define AFE_ADDA_UL2_ULCF_CFG_20_19 0xd24 +#define AFE_ADDA_UL2_ULCF_CFG_22_21 0xd28 +#define AFE_ADDA_UL2_ULCF_CFG_24_23 0xd2c +#define AFE_ADDA_UL2_ULCF_CFG_26_25 0xd30 +#define AFE_ADDA_UL2_ULCF_CFG_28_27 0xd34 +#define AFE_ADDA_UL2_ULCF_CFG_30_29 0xd38 +#define AFE_ADDA_UL2_ULCF_CFG_32_31 0xd3c +#define AFE_ADDA_UL2_IP_VERSION 0xd4c +#define AFE_ADDA_PROXIMITY_CON0 0xed0 +#define AFE_ADDA_ULSRC_PHASE_CON0 0xf00 +#define AFE_ADDA_ULSRC_PHASE_CON1 0xf04 +#define AFE_ADDA_ULSRC_PHASE_CON2 0xf08 +#define AFE_ADDA_ULSRC_PHASE_CON3 0xf0c +#define AFE_MTKAIF_IPM_VER_MON 0x1180 +#define AFE_MTKAIF_MON_SEL 0x1184 +#define AFE_MTKAIF_MON 0x1188 +#define AFE_MTKAIF0_CFG0 0x1190 +#define AFE_MTKAIF0_TX_CFG0 0x1194 +#define AFE_MTKAIF0_RX_CFG0 0x1198 +#define AFE_MTKAIF0_RX_CFG1 0x119c +#define AFE_MTKAIF0_RX_CFG2 0x11a0 +#define AFE_MTKAIF1_CFG0 0x11f0 +#define AFE_MTKAIF1_TX_CFG0 0x11f4 +#define AFE_MTKAIF1_RX_CFG0 0x11f8 +#define AFE_MTKAIF1_RX_CFG1 0x11fc +#define AFE_MTKAIF1_RX_CFG2 0x1200 +#define AFE_AUD_PAD_TOP_CFG0 0x1204 +#define AFE_AUD_PAD_TOP_MON 0x1208 +#define AFE_ADDA_MTKAIFV4_TX_CFG0 0x1280 +#define AFE_ADDA6_MTKAIFV4_TX_CFG0 0x1284 +#define AFE_ADDA_MTKAIFV4_RX_CFG0 0x1288 +#define AFE_ADDA_MTKAIFV4_RX_CFG1 0x128c +#define AFE_ADDA6_MTKAIFV4_RX_CFG0 0x1290 +#define AFE_ADDA6_MTKAIFV4_RX_CFG1 0x1294 +#define AFE_ADDA_MTKAIFV4_TX_SYNCWORD_CFG 0x1298 +#define AFE_ADDA_MTKAIFV4_RX_SYNCWORD_CFG 0x129c +#define AFE_ADDA_MTKAIFV4_MON0 0x12a0 +#define AFE_ADDA_MTKAIFV4_MON1 0x12a4 +#define AFE_ADDA6_MTKAIFV4_MON0 0x12a8 +#define ETDM_IN0_CON0 0x1300 +#define ETDM_IN0_CON1 0x1304 +#define ETDM_IN0_CON2 0x1308 +#define ETDM_IN0_CON3 0x130c +#define ETDM_IN0_CON4 0x1310 +#define ETDM_IN0_CON5 0x1314 +#define ETDM_IN0_CON6 0x1318 +#define ETDM_IN0_CON7 0x131c +#define ETDM_IN0_CON8 0x1320 +#define ETDM_IN0_CON9 0x1324 +#define ETDM_IN0_MON 0x1328 +#define ETDM_IN1_CON0 0x1330 +#define ETDM_IN1_CON1 0x1334 +#define ETDM_IN1_CON2 0x1338 +#define ETDM_IN1_CON3 0x133c +#define ETDM_IN1_CON4 0x1340 +#define ETDM_IN1_CON5 0x1344 +#define ETDM_IN1_CON6 0x1348 +#define ETDM_IN1_CON7 0x134c +#define ETDM_IN1_CON8 0x1350 +#define ETDM_IN1_CON9 0x1354 +#define ETDM_IN1_MON 0x1358 +#define ETDM_IN2_CON0 0x1360 +#define ETDM_IN2_CON1 0x1364 +#define ETDM_IN2_CON2 0x1368 +#define ETDM_IN2_CON3 0x136c +#define ETDM_IN2_CON4 0x1370 +#define ETDM_IN2_CON5 0x1374 +#define ETDM_IN2_CON6 0x1378 +#define ETDM_IN2_CON7 0x137c +#define ETDM_IN2_CON8 0x1380 +#define ETDM_IN2_CON9 0x1384 +#define ETDM_IN2_MON 0x1388 +#define ETDM_IN3_CON0 0x1390 +#define ETDM_IN3_CON1 0x1394 +#define ETDM_IN3_CON2 0x1398 +#define ETDM_IN3_CON3 0x139c +#define ETDM_IN3_CON4 0x13a0 +#define ETDM_IN3_CON5 0x13a4 +#define ETDM_IN3_CON6 0x13a8 +#define ETDM_IN3_CON7 0x13ac +#define ETDM_IN3_CON8 0x13b0 +#define ETDM_IN3_CON9 0x13b4 +#define ETDM_IN3_MON 0x13b8 +#define ETDM_IN4_CON0 0x13c0 +#define ETDM_IN4_CON1 0x13c4 +#define ETDM_IN4_CON2 0x13c8 +#define ETDM_IN4_CON3 0x13cc +#define ETDM_IN4_CON4 0x13d0 +#define ETDM_IN4_CON5 0x13d4 +#define ETDM_IN4_CON6 0x13d8 +#define ETDM_IN4_CON7 0x13dc +#define ETDM_IN4_CON8 0x13e0 +#define ETDM_IN4_CON9 0x13e4 +#define ETDM_IN4_MON 0x13e8 +#define ETDM_IN5_CON0 0x13f0 +#define ETDM_IN5_CON1 0x13f4 +#define ETDM_IN5_CON2 0x13f8 +#define ETDM_IN5_CON3 0x13fc +#define ETDM_IN5_CON4 0x1400 +#define ETDM_IN5_CON5 0x1404 +#define ETDM_IN5_CON6 0x1408 +#define ETDM_IN5_CON7 0x140c +#define ETDM_IN5_CON8 0x1410 +#define ETDM_IN5_CON9 0x1414 +#define ETDM_IN5_MON 0x1418 +#define ETDM_IN6_CON0 0x1420 +#define ETDM_IN6_CON1 0x1424 +#define ETDM_IN6_CON2 0x1428 +#define ETDM_IN6_CON3 0x142c +#define ETDM_IN6_CON4 0x1430 +#define ETDM_IN6_CON5 0x1434 +#define ETDM_IN6_CON6 0x1438 +#define ETDM_IN6_CON7 0x143c +#define ETDM_IN6_CON8 0x1440 +#define ETDM_IN6_CON9 0x1444 +#define ETDM_IN6_MON 0x1448 +#define ETDM_OUT0_CON0 0x1480 +#define ETDM_OUT0_CON1 0x1484 +#define ETDM_OUT0_CON2 0x1488 +#define ETDM_OUT0_CON3 0x148c +#define ETDM_OUT0_CON4 0x1490 +#define ETDM_OUT0_CON5 0x1494 +#define ETDM_OUT0_CON6 0x1498 +#define ETDM_OUT0_CON7 0x149c +#define ETDM_OUT0_CON8 0x14a0 +#define ETDM_OUT0_CON9 0x14a4 +#define ETDM_OUT0_MON 0x14a8 +#define ETDM_OUT1_CON0 0x14c0 +#define ETDM_OUT1_CON1 0x14c4 +#define ETDM_OUT1_CON2 0x14c8 +#define ETDM_OUT1_CON3 0x14cc +#define ETDM_OUT1_CON4 0x14d0 +#define ETDM_OUT1_CON5 0x14d4 +#define ETDM_OUT1_CON6 0x14d8 +#define ETDM_OUT1_CON7 0x14dc +#define ETDM_OUT1_CON8 0x14e0 +#define ETDM_OUT1_CON9 0x14e4 +#define ETDM_OUT1_MON 0x14e8 +#define ETDM_OUT2_CON0 0x1500 +#define ETDM_OUT2_CON1 0x1504 +#define ETDM_OUT2_CON2 0x1508 +#define ETDM_OUT2_CON3 0x150c +#define ETDM_OUT2_CON4 0x1510 +#define ETDM_OUT2_CON5 0x1514 +#define ETDM_OUT2_CON6 0x1518 +#define ETDM_OUT2_CON7 0x151c +#define ETDM_OUT2_CON8 0x1520 +#define ETDM_OUT2_CON9 0x1524 +#define ETDM_OUT2_MON 0x1528 +#define ETDM_OUT3_CON0 0x1540 +#define ETDM_OUT3_CON1 0x1544 +#define ETDM_OUT3_CON2 0x1548 +#define ETDM_OUT3_CON3 0x154c +#define ETDM_OUT3_CON4 0x1550 +#define ETDM_OUT3_CON5 0x1554 +#define ETDM_OUT3_CON6 0x1558 +#define ETDM_OUT3_CON7 0x155c +#define ETDM_OUT3_CON8 0x1560 +#define ETDM_OUT3_CON9 0x1564 +#define ETDM_OUT3_MON 0x1568 +#define ETDM_OUT4_CON0 0x1580 +#define ETDM_OUT4_CON1 0x1584 +#define ETDM_OUT4_CON2 0x1588 +#define ETDM_OUT4_CON3 0x158c +#define ETDM_OUT4_CON4 0x1590 +#define ETDM_OUT4_CON5 0x1594 +#define ETDM_OUT4_CON6 0x1598 +#define ETDM_OUT4_CON7 0x159c +#define ETDM_OUT4_CON8 0x15a0 +#define ETDM_OUT4_CON9 0x15a4 +#define ETDM_OUT4_MON 0x15a8 +#define ETDM_OUT5_CON0 0x15c0 +#define ETDM_OUT5_CON1 0x15c4 +#define ETDM_OUT5_CON2 0x15c8 +#define ETDM_OUT5_CON3 0x15cc +#define ETDM_OUT5_CON4 0x15d0 +#define ETDM_OUT5_CON5 0x15d4 +#define ETDM_OUT5_CON6 0x15d8 +#define ETDM_OUT5_CON7 0x15dc +#define ETDM_OUT5_CON8 0x15e0 +#define ETDM_OUT5_CON9 0x15e4 +#define ETDM_OUT5_MON 0x15e8 +#define ETDM_OUT6_CON0 0x1600 +#define ETDM_OUT6_CON1 0x1604 +#define ETDM_OUT6_CON2 0x1608 +#define ETDM_OUT6_CON3 0x160c +#define ETDM_OUT6_CON4 0x1610 +#define ETDM_OUT6_CON5 0x1614 +#define ETDM_OUT6_CON6 0x1618 +#define ETDM_OUT6_CON7 0x161c +#define ETDM_OUT6_CON8 0x1620 +#define ETDM_OUT6_CON9 0x1624 +#define ETDM_OUT6_MON 0x1628 +#define ETDM_0_3_COWORK_CON0 0x1680 +#define ETDM_0_3_COWORK_CON1 0x1684 +#define ETDM_0_3_COWORK_CON2 0x1688 +#define ETDM_0_3_COWORK_CON3 0x168c +#define ETDM_4_7_COWORK_CON0 0x1690 +#define ETDM_4_7_COWORK_CON1 0x1694 +#define ETDM_4_7_COWORK_CON2 0x1698 +#define ETDM_4_7_COWORK_CON3 0x169c +#define AFE_DPTX_CON 0x2040 +#define AFE_DPTX_MON 0x2044 +#define AFE_TDM_CON1 0x2048 +#define AFE_TDM_CON2 0x204c +#define AFE_TDM_CON3 0x2050 +#define AFE_TDM_OUT_MON 0x2054 +#define AFE_HDMI_CONN0 0x2078 +#define AFE_TDM_TOP_IP_VERSION 0x207c +#define AFE_CONN004_0 0x2100 +#define AFE_CONN004_1 0x2104 +#define AFE_CONN004_2 0x2108 +#define AFE_CONN004_4 0x2110 +#define AFE_CONN004_5 0x2114 +#define AFE_CONN004_6 0x2118 +#define AFE_CONN004_7 0x211c +#define AFE_CONN005_0 0x2120 +#define AFE_CONN005_1 0x2124 +#define AFE_CONN005_2 0x2128 +#define AFE_CONN005_4 0x2130 +#define AFE_CONN005_5 0x2134 +#define AFE_CONN005_6 0x2138 +#define AFE_CONN005_7 0x213c +#define AFE_CONN006_0 0x2140 +#define AFE_CONN006_1 0x2144 +#define AFE_CONN006_2 0x2148 +#define AFE_CONN006_4 0x2150 +#define AFE_CONN006_5 0x2154 +#define AFE_CONN006_6 0x2158 +#define AFE_CONN006_7 0x215c +#define AFE_CONN007_0 0x2160 +#define AFE_CONN007_1 0x2164 +#define AFE_CONN007_2 0x2168 +#define AFE_CONN007_4 0x2170 +#define AFE_CONN007_5 0x2174 +#define AFE_CONN007_6 0x2178 +#define AFE_CONN007_7 0x217c +#define AFE_CONN008_0 0x2180 +#define AFE_CONN008_1 0x2184 +#define AFE_CONN008_2 0x2188 +#define AFE_CONN008_4 0x2190 +#define AFE_CONN008_5 0x2194 +#define AFE_CONN008_6 0x2198 +#define AFE_CONN008_7 0x219c +#define AFE_CONN009_0 0x21a0 +#define AFE_CONN009_1 0x21a4 +#define AFE_CONN009_2 0x21a8 +#define AFE_CONN009_4 0x21b0 +#define AFE_CONN009_5 0x21b4 +#define AFE_CONN009_6 0x21b8 +#define AFE_CONN009_7 0x21bc +#define AFE_CONN010_0 0x21c0 +#define AFE_CONN010_1 0x21c4 +#define AFE_CONN010_2 0x21c8 +#define AFE_CONN010_4 0x21d0 +#define AFE_CONN010_5 0x21d4 +#define AFE_CONN010_6 0x21d8 +#define AFE_CONN010_7 0x21dc +#define AFE_CONN011_0 0x21e0 +#define AFE_CONN011_1 0x21e4 +#define AFE_CONN011_2 0x21e8 +#define AFE_CONN011_4 0x21f0 +#define AFE_CONN011_5 0x21f4 +#define AFE_CONN011_6 0x21f8 +#define AFE_CONN011_7 0x21fc +#define AFE_CONN012_0 0x2200 +#define AFE_CONN012_1 0x2204 +#define AFE_CONN012_2 0x2208 +#define AFE_CONN012_4 0x2210 +#define AFE_CONN012_5 0x2214 +#define AFE_CONN012_6 0x2218 +#define AFE_CONN012_7 0x221c +#define AFE_CONN014_0 0x2240 +#define AFE_CONN014_1 0x2244 +#define AFE_CONN014_2 0x2248 +#define AFE_CONN014_4 0x2250 +#define AFE_CONN014_5 0x2254 +#define AFE_CONN014_6 0x2258 +#define AFE_CONN014_7 0x225c +#define AFE_CONN015_0 0x2260 +#define AFE_CONN015_1 0x2264 +#define AFE_CONN015_2 0x2268 +#define AFE_CONN015_4 0x2270 +#define AFE_CONN015_5 0x2274 +#define AFE_CONN015_6 0x2278 +#define AFE_CONN015_7 0x227c +#define AFE_CONN016_0 0x2280 +#define AFE_CONN016_1 0x2284 +#define AFE_CONN016_2 0x2288 +#define AFE_CONN016_4 0x2290 +#define AFE_CONN016_5 0x2294 +#define AFE_CONN016_6 0x2298 +#define AFE_CONN016_7 0x229c +#define AFE_CONN017_0 0x22a0 +#define AFE_CONN017_1 0x22a4 +#define AFE_CONN017_2 0x22a8 +#define AFE_CONN017_4 0x22b0 +#define AFE_CONN017_5 0x22b4 +#define AFE_CONN017_6 0x22b8 +#define AFE_CONN017_7 0x22bc +#define AFE_CONN018_0 0x22c0 +#define AFE_CONN018_1 0x22c4 +#define AFE_CONN018_2 0x22c8 +#define AFE_CONN018_4 0x22d0 +#define AFE_CONN018_5 0x22d4 +#define AFE_CONN018_6 0x22d8 +#define AFE_CONN018_7 0x22dc +#define AFE_CONN019_0 0x22e0 +#define AFE_CONN019_1 0x22e4 +#define AFE_CONN019_2 0x22e8 +#define AFE_CONN019_4 0x22f0 +#define AFE_CONN019_5 0x22f4 +#define AFE_CONN019_6 0x22f8 +#define AFE_CONN019_7 0x22fc +#define AFE_CONN020_0 0x2300 +#define AFE_CONN020_1 0x2304 +#define AFE_CONN020_2 0x2308 +#define AFE_CONN020_4 0x2310 +#define AFE_CONN020_5 0x2314 +#define AFE_CONN020_6 0x2318 +#define AFE_CONN020_7 0x231c +#define AFE_CONN021_0 0x2320 +#define AFE_CONN021_1 0x2324 +#define AFE_CONN021_2 0x2328 +#define AFE_CONN021_4 0x2330 +#define AFE_CONN021_5 0x2334 +#define AFE_CONN021_6 0x2338 +#define AFE_CONN021_7 0x233c +#define AFE_CONN022_0 0x2340 +#define AFE_CONN022_1 0x2344 +#define AFE_CONN022_2 0x2348 +#define AFE_CONN022_4 0x2350 +#define AFE_CONN022_5 0x2354 +#define AFE_CONN022_6 0x2358 +#define AFE_CONN022_7 0x235c +#define AFE_CONN023_0 0x2360 +#define AFE_CONN023_1 0x2364 +#define AFE_CONN023_2 0x2368 +#define AFE_CONN023_4 0x2370 +#define AFE_CONN023_5 0x2374 +#define AFE_CONN023_6 0x2378 +#define AFE_CONN023_7 0x237c +#define AFE_CONN024_0 0x2380 +#define AFE_CONN024_1 0x2384 +#define AFE_CONN024_2 0x2388 +#define AFE_CONN024_4 0x2390 +#define AFE_CONN024_5 0x2394 +#define AFE_CONN024_6 0x2398 +#define AFE_CONN024_7 0x239c +#define AFE_CONN025_0 0x23a0 +#define AFE_CONN025_1 0x23a4 +#define AFE_CONN025_2 0x23a8 +#define AFE_CONN025_4 0x23b0 +#define AFE_CONN025_5 0x23b4 +#define AFE_CONN025_6 0x23b8 +#define AFE_CONN025_7 0x23bc +#define AFE_CONN026_0 0x23c0 +#define AFE_CONN026_1 0x23c4 +#define AFE_CONN026_2 0x23c8 +#define AFE_CONN026_4 0x23d0 +#define AFE_CONN026_5 0x23d4 +#define AFE_CONN026_6 0x23d8 +#define AFE_CONN026_7 0x23dc +#define AFE_CONN027_0 0x23e0 +#define AFE_CONN027_1 0x23e4 +#define AFE_CONN027_2 0x23e8 +#define AFE_CONN027_4 0x23f0 +#define AFE_CONN027_5 0x23f4 +#define AFE_CONN027_6 0x23f8 +#define AFE_CONN027_7 0x23fc +#define AFE_CONN028_0 0x2400 +#define AFE_CONN028_1 0x2404 +#define AFE_CONN028_2 0x2408 +#define AFE_CONN028_4 0x2410 +#define AFE_CONN028_5 0x2414 +#define AFE_CONN028_6 0x2418 +#define AFE_CONN028_7 0x241c +#define AFE_CONN029_0 0x2420 +#define AFE_CONN029_1 0x2424 +#define AFE_CONN029_2 0x2428 +#define AFE_CONN029_4 0x2430 +#define AFE_CONN029_5 0x2434 +#define AFE_CONN029_6 0x2438 +#define AFE_CONN029_7 0x243c +#define AFE_CONN030_0 0x2440 +#define AFE_CONN030_1 0x2444 +#define AFE_CONN030_2 0x2448 +#define AFE_CONN030_4 0x2450 +#define AFE_CONN030_5 0x2454 +#define AFE_CONN030_6 0x2458 +#define AFE_CONN030_7 0x245c +#define AFE_CONN031_0 0x2460 +#define AFE_CONN031_1 0x2464 +#define AFE_CONN031_2 0x2468 +#define AFE_CONN031_4 0x2470 +#define AFE_CONN031_5 0x2474 +#define AFE_CONN031_6 0x2478 +#define AFE_CONN031_7 0x247c +#define AFE_CONN032_0 0x2480 +#define AFE_CONN032_1 0x2484 +#define AFE_CONN032_2 0x2488 +#define AFE_CONN032_4 0x2490 +#define AFE_CONN032_5 0x2494 +#define AFE_CONN032_6 0x2498 +#define AFE_CONN032_7 0x249c +#define AFE_CONN033_0 0x24a0 +#define AFE_CONN033_1 0x24a4 +#define AFE_CONN033_2 0x24a8 +#define AFE_CONN033_4 0x24b0 +#define AFE_CONN033_5 0x24b4 +#define AFE_CONN033_6 0x24b8 +#define AFE_CONN033_7 0x24bc +#define AFE_CONN034_0 0x24c0 +#define AFE_CONN034_1 0x24c4 +#define AFE_CONN034_2 0x24c8 +#define AFE_CONN034_4 0x24d0 +#define AFE_CONN034_5 0x24d4 +#define AFE_CONN034_6 0x24d8 +#define AFE_CONN034_7 0x24dc +#define AFE_CONN035_0 0x24e0 +#define AFE_CONN035_1 0x24e4 +#define AFE_CONN035_2 0x24e8 +#define AFE_CONN035_4 0x24f0 +#define AFE_CONN035_5 0x24f4 +#define AFE_CONN035_6 0x24f8 +#define AFE_CONN035_7 0x24fc +#define AFE_CONN036_0 0x2500 +#define AFE_CONN036_1 0x2504 +#define AFE_CONN036_2 0x2508 +#define AFE_CONN036_4 0x2510 +#define AFE_CONN036_5 0x2514 +#define AFE_CONN036_6 0x2518 +#define AFE_CONN036_7 0x251c +#define AFE_CONN037_0 0x2520 +#define AFE_CONN037_1 0x2524 +#define AFE_CONN037_2 0x2528 +#define AFE_CONN037_4 0x2530 +#define AFE_CONN037_5 0x2534 +#define AFE_CONN037_6 0x2538 +#define AFE_CONN037_7 0x253c +#define AFE_CONN038_0 0x2540 +#define AFE_CONN038_1 0x2544 +#define AFE_CONN038_2 0x2548 +#define AFE_CONN038_4 0x2550 +#define AFE_CONN038_5 0x2554 +#define AFE_CONN038_6 0x2558 +#define AFE_CONN038_7 0x255c +#define AFE_CONN039_0 0x2560 +#define AFE_CONN039_1 0x2564 +#define AFE_CONN039_2 0x2568 +#define AFE_CONN039_4 0x2570 +#define AFE_CONN039_5 0x2574 +#define AFE_CONN039_6 0x2578 +#define AFE_CONN039_7 0x257c +#define AFE_CONN040_0 0x2580 +#define AFE_CONN040_1 0x2584 +#define AFE_CONN040_2 0x2588 +#define AFE_CONN040_4 0x2590 +#define AFE_CONN040_5 0x2594 +#define AFE_CONN040_6 0x2598 +#define AFE_CONN040_7 0x259c +#define AFE_CONN041_0 0x25a0 +#define AFE_CONN041_1 0x25a4 +#define AFE_CONN041_2 0x25a8 +#define AFE_CONN041_4 0x25b0 +#define AFE_CONN041_5 0x25b4 +#define AFE_CONN041_6 0x25b8 +#define AFE_CONN041_7 0x25bc +#define AFE_CONN042_0 0x25c0 +#define AFE_CONN042_1 0x25c4 +#define AFE_CONN042_2 0x25c8 +#define AFE_CONN042_4 0x25d0 +#define AFE_CONN042_5 0x25d4 +#define AFE_CONN042_6 0x25d8 +#define AFE_CONN042_7 0x25dc +#define AFE_CONN043_0 0x25e0 +#define AFE_CONN043_1 0x25e4 +#define AFE_CONN043_2 0x25e8 +#define AFE_CONN043_4 0x25f0 +#define AFE_CONN043_5 0x25f4 +#define AFE_CONN043_6 0x25f8 +#define AFE_CONN043_7 0x25fc +#define AFE_CONN044_0 0x2600 +#define AFE_CONN044_1 0x2604 +#define AFE_CONN044_2 0x2608 +#define AFE_CONN044_4 0x2610 +#define AFE_CONN044_5 0x2614 +#define AFE_CONN044_6 0x2618 +#define AFE_CONN044_7 0x261c +#define AFE_CONN045_0 0x2620 +#define AFE_CONN045_1 0x2624 +#define AFE_CONN045_2 0x2628 +#define AFE_CONN045_4 0x2630 +#define AFE_CONN045_5 0x2634 +#define AFE_CONN045_6 0x2638 +#define AFE_CONN045_7 0x263c +#define AFE_CONN046_0 0x2640 +#define AFE_CONN046_1 0x2644 +#define AFE_CONN046_2 0x2648 +#define AFE_CONN046_4 0x2650 +#define AFE_CONN046_5 0x2654 +#define AFE_CONN046_6 0x2658 +#define AFE_CONN046_7 0x265c +#define AFE_CONN047_0 0x2660 +#define AFE_CONN047_1 0x2664 +#define AFE_CONN047_2 0x2668 +#define AFE_CONN047_4 0x2670 +#define AFE_CONN047_5 0x2674 +#define AFE_CONN047_6 0x2678 +#define AFE_CONN047_7 0x267c +#define AFE_CONN048_0 0x2680 +#define AFE_CONN048_1 0x2684 +#define AFE_CONN048_2 0x2688 +#define AFE_CONN048_4 0x2690 +#define AFE_CONN048_5 0x2694 +#define AFE_CONN048_6 0x2698 +#define AFE_CONN048_7 0x269c +#define AFE_CONN049_0 0x26a0 +#define AFE_CONN049_1 0x26a4 +#define AFE_CONN049_2 0x26a8 +#define AFE_CONN049_4 0x26b0 +#define AFE_CONN049_5 0x26b4 +#define AFE_CONN049_6 0x26b8 +#define AFE_CONN049_7 0x26bc +#define AFE_CONN050_0 0x26c0 +#define AFE_CONN050_1 0x26c4 +#define AFE_CONN050_2 0x26c8 +#define AFE_CONN050_4 0x26d0 +#define AFE_CONN050_5 0x26d4 +#define AFE_CONN050_6 0x26d8 +#define AFE_CONN050_7 0x26dc +#define AFE_CONN051_0 0x26e0 +#define AFE_CONN051_1 0x26e4 +#define AFE_CONN051_2 0x26e8 +#define AFE_CONN051_4 0x26f0 +#define AFE_CONN051_5 0x26f4 +#define AFE_CONN051_6 0x26f8 +#define AFE_CONN051_7 0x26fc +#define AFE_CONN052_0 0x2700 +#define AFE_CONN052_1 0x2704 +#define AFE_CONN052_2 0x2708 +#define AFE_CONN052_4 0x2710 +#define AFE_CONN052_5 0x2714 +#define AFE_CONN052_6 0x2718 +#define AFE_CONN052_7 0x271c +#define AFE_CONN053_0 0x2720 +#define AFE_CONN053_1 0x2724 +#define AFE_CONN053_2 0x2728 +#define AFE_CONN053_4 0x2730 +#define AFE_CONN053_5 0x2734 +#define AFE_CONN053_6 0x2738 +#define AFE_CONN053_7 0x273c +#define AFE_CONN054_0 0x2740 +#define AFE_CONN054_1 0x2744 +#define AFE_CONN054_2 0x2748 +#define AFE_CONN054_4 0x2750 +#define AFE_CONN054_5 0x2754 +#define AFE_CONN054_6 0x2758 +#define AFE_CONN054_7 0x275c +#define AFE_CONN055_0 0x2760 +#define AFE_CONN055_1 0x2764 +#define AFE_CONN055_2 0x2768 +#define AFE_CONN055_4 0x2770 +#define AFE_CONN055_5 0x2774 +#define AFE_CONN055_6 0x2778 +#define AFE_CONN055_7 0x277c +#define AFE_CONN056_0 0x2780 +#define AFE_CONN056_1 0x2784 +#define AFE_CONN056_2 0x2788 +#define AFE_CONN056_4 0x2790 +#define AFE_CONN056_5 0x2794 +#define AFE_CONN056_6 0x2798 +#define AFE_CONN056_7 0x279c +#define AFE_CONN057_0 0x27a0 +#define AFE_CONN057_1 0x27a4 +#define AFE_CONN057_2 0x27a8 +#define AFE_CONN057_4 0x27b0 +#define AFE_CONN057_5 0x27b4 +#define AFE_CONN057_6 0x27b8 +#define AFE_CONN057_7 0x27bc +#define AFE_CONN058_0 0x27c0 +#define AFE_CONN058_1 0x27c4 +#define AFE_CONN058_2 0x27c8 +#define AFE_CONN058_4 0x27d0 +#define AFE_CONN058_5 0x27d4 +#define AFE_CONN058_6 0x27d8 +#define AFE_CONN058_7 0x27dc +#define AFE_CONN059_0 0x27e0 +#define AFE_CONN059_1 0x27e4 +#define AFE_CONN059_2 0x27e8 +#define AFE_CONN059_4 0x27f0 +#define AFE_CONN059_5 0x27f4 +#define AFE_CONN059_6 0x27f8 +#define AFE_CONN059_7 0x27fc +#define AFE_CONN060_0 0x2800 +#define AFE_CONN060_1 0x2804 +#define AFE_CONN060_2 0x2808 +#define AFE_CONN060_4 0x2810 +#define AFE_CONN060_5 0x2814 +#define AFE_CONN060_6 0x2818 +#define AFE_CONN060_7 0x281c +#define AFE_CONN061_0 0x2820 +#define AFE_CONN061_1 0x2824 +#define AFE_CONN061_2 0x2828 +#define AFE_CONN061_4 0x2830 +#define AFE_CONN061_5 0x2834 +#define AFE_CONN061_6 0x2838 +#define AFE_CONN061_7 0x283c +#define AFE_CONN062_0 0x2840 +#define AFE_CONN062_1 0x2844 +#define AFE_CONN062_2 0x2848 +#define AFE_CONN062_4 0x2850 +#define AFE_CONN062_5 0x2854 +#define AFE_CONN062_6 0x2858 +#define AFE_CONN062_7 0x285c +#define AFE_CONN063_0 0x2860 +#define AFE_CONN063_1 0x2864 +#define AFE_CONN063_2 0x2868 +#define AFE_CONN063_4 0x2870 +#define AFE_CONN063_5 0x2874 +#define AFE_CONN063_6 0x2878 +#define AFE_CONN063_7 0x287c +#define AFE_CONN064_0 0x2880 +#define AFE_CONN064_1 0x2884 +#define AFE_CONN064_2 0x2888 +#define AFE_CONN064_4 0x2890 +#define AFE_CONN064_5 0x2894 +#define AFE_CONN064_6 0x2898 +#define AFE_CONN064_7 0x289c +#define AFE_CONN065_0 0x28a0 +#define AFE_CONN065_1 0x28a4 +#define AFE_CONN065_2 0x28a8 +#define AFE_CONN065_4 0x28b0 +#define AFE_CONN065_5 0x28b4 +#define AFE_CONN065_6 0x28b8 +#define AFE_CONN065_7 0x28bc +#define AFE_CONN066_0 0x28c0 +#define AFE_CONN066_1 0x28c4 +#define AFE_CONN066_2 0x28c8 +#define AFE_CONN066_4 0x28d0 +#define AFE_CONN066_5 0x28d4 +#define AFE_CONN066_6 0x28d8 +#define AFE_CONN066_7 0x28dc +#define AFE_CONN067_0 0x28e0 +#define AFE_CONN067_1 0x28e4 +#define AFE_CONN067_2 0x28e8 +#define AFE_CONN067_4 0x28f0 +#define AFE_CONN067_5 0x28f4 +#define AFE_CONN067_6 0x28f8 +#define AFE_CONN067_7 0x28fc +#define AFE_CONN068_0 0x2900 +#define AFE_CONN068_1 0x2904 +#define AFE_CONN068_2 0x2908 +#define AFE_CONN068_4 0x2910 +#define AFE_CONN068_5 0x2914 +#define AFE_CONN068_6 0x2918 +#define AFE_CONN068_7 0x291c +#define AFE_CONN069_0 0x2920 +#define AFE_CONN069_1 0x2924 +#define AFE_CONN069_2 0x2928 +#define AFE_CONN069_4 0x2930 +#define AFE_CONN069_5 0x2934 +#define AFE_CONN069_6 0x2938 +#define AFE_CONN069_7 0x293c +#define AFE_CONN070_0 0x2940 +#define AFE_CONN070_1 0x2944 +#define AFE_CONN070_2 0x2948 +#define AFE_CONN070_4 0x2950 +#define AFE_CONN070_5 0x2954 +#define AFE_CONN070_6 0x2958 +#define AFE_CONN070_7 0x295c +#define AFE_CONN071_0 0x2960 +#define AFE_CONN071_1 0x2964 +#define AFE_CONN071_2 0x2968 +#define AFE_CONN071_4 0x2970 +#define AFE_CONN071_5 0x2974 +#define AFE_CONN071_6 0x2978 +#define AFE_CONN071_7 0x297c +#define AFE_CONN072_0 0x2980 +#define AFE_CONN072_1 0x2984 +#define AFE_CONN072_2 0x2988 +#define AFE_CONN072_4 0x2990 +#define AFE_CONN072_5 0x2994 +#define AFE_CONN072_6 0x2998 +#define AFE_CONN072_7 0x299c +#define AFE_CONN073_0 0x29a0 +#define AFE_CONN073_1 0x29a4 +#define AFE_CONN073_2 0x29a8 +#define AFE_CONN073_4 0x29b0 +#define AFE_CONN073_5 0x29b4 +#define AFE_CONN073_6 0x29b8 +#define AFE_CONN073_7 0x29bc +#define AFE_CONN074_0 0x29c0 +#define AFE_CONN074_1 0x29c4 +#define AFE_CONN074_2 0x29c8 +#define AFE_CONN074_4 0x29d0 +#define AFE_CONN074_5 0x29d4 +#define AFE_CONN074_6 0x29d8 +#define AFE_CONN074_7 0x29dc +#define AFE_CONN075_0 0x29e0 +#define AFE_CONN075_1 0x29e4 +#define AFE_CONN075_2 0x29e8 +#define AFE_CONN075_4 0x29f0 +#define AFE_CONN075_5 0x29f4 +#define AFE_CONN075_6 0x29f8 +#define AFE_CONN075_7 0x29fc +#define AFE_CONN076_0 0x2a00 +#define AFE_CONN076_1 0x2a04 +#define AFE_CONN076_2 0x2a08 +#define AFE_CONN076_4 0x2a10 +#define AFE_CONN076_5 0x2a14 +#define AFE_CONN076_6 0x2a18 +#define AFE_CONN076_7 0x2a1c +#define AFE_CONN077_0 0x2a20 +#define AFE_CONN077_1 0x2a24 +#define AFE_CONN077_2 0x2a28 +#define AFE_CONN077_4 0x2a30 +#define AFE_CONN077_5 0x2a34 +#define AFE_CONN077_6 0x2a38 +#define AFE_CONN077_7 0x2a3c +#define AFE_CONN078_0 0x2a40 +#define AFE_CONN078_1 0x2a44 +#define AFE_CONN078_2 0x2a48 +#define AFE_CONN078_4 0x2a50 +#define AFE_CONN078_5 0x2a54 +#define AFE_CONN078_6 0x2a58 +#define AFE_CONN078_7 0x2a5c +#define AFE_CONN079_0 0x2a60 +#define AFE_CONN079_1 0x2a64 +#define AFE_CONN079_2 0x2a68 +#define AFE_CONN079_4 0x2a70 +#define AFE_CONN079_5 0x2a74 +#define AFE_CONN079_6 0x2a78 +#define AFE_CONN079_7 0x2a7c +#define AFE_CONN080_0 0x2a80 +#define AFE_CONN080_1 0x2a84 +#define AFE_CONN080_2 0x2a88 +#define AFE_CONN080_4 0x2a90 +#define AFE_CONN080_5 0x2a94 +#define AFE_CONN080_6 0x2a98 +#define AFE_CONN080_7 0x2a9c +#define AFE_CONN081_0 0x2aa0 +#define AFE_CONN081_1 0x2aa4 +#define AFE_CONN081_2 0x2aa8 +#define AFE_CONN081_4 0x2ab0 +#define AFE_CONN081_5 0x2ab4 +#define AFE_CONN081_6 0x2ab8 +#define AFE_CONN081_7 0x2abc +#define AFE_CONN082_0 0x2ac0 +#define AFE_CONN082_1 0x2ac4 +#define AFE_CONN082_2 0x2ac8 +#define AFE_CONN082_4 0x2ad0 +#define AFE_CONN082_5 0x2ad4 +#define AFE_CONN082_6 0x2ad8 +#define AFE_CONN082_7 0x2adc +#define AFE_CONN083_0 0x2ae0 +#define AFE_CONN083_1 0x2ae4 +#define AFE_CONN083_2 0x2ae8 +#define AFE_CONN083_4 0x2af0 +#define AFE_CONN083_5 0x2af4 +#define AFE_CONN083_6 0x2af8 +#define AFE_CONN083_7 0x2afc +#define AFE_CONN084_0 0x2b00 +#define AFE_CONN084_1 0x2b04 +#define AFE_CONN084_2 0x2b08 +#define AFE_CONN084_4 0x2b10 +#define AFE_CONN084_5 0x2b14 +#define AFE_CONN084_6 0x2b18 +#define AFE_CONN084_7 0x2b1c +#define AFE_CONN085_0 0x2b20 +#define AFE_CONN085_1 0x2b24 +#define AFE_CONN085_2 0x2b28 +#define AFE_CONN085_4 0x2b30 +#define AFE_CONN085_5 0x2b34 +#define AFE_CONN085_6 0x2b38 +#define AFE_CONN085_7 0x2b3c +#define AFE_CONN086_0 0x2b40 +#define AFE_CONN086_1 0x2b44 +#define AFE_CONN086_2 0x2b48 +#define AFE_CONN086_4 0x2b50 +#define AFE_CONN086_5 0x2b54 +#define AFE_CONN086_6 0x2b58 +#define AFE_CONN086_7 0x2b5c +#define AFE_CONN087_0 0x2b60 +#define AFE_CONN087_1 0x2b64 +#define AFE_CONN087_2 0x2b68 +#define AFE_CONN087_4 0x2b70 +#define AFE_CONN087_5 0x2b74 +#define AFE_CONN087_6 0x2b78 +#define AFE_CONN087_7 0x2b7c +#define AFE_CONN088_0 0x2b80 +#define AFE_CONN088_1 0x2b84 +#define AFE_CONN088_2 0x2b88 +#define AFE_CONN088_4 0x2b90 +#define AFE_CONN088_5 0x2b94 +#define AFE_CONN088_6 0x2b98 +#define AFE_CONN088_7 0x2b9c +#define AFE_CONN089_0 0x2ba0 +#define AFE_CONN089_1 0x2ba4 +#define AFE_CONN089_2 0x2ba8 +#define AFE_CONN089_4 0x2bb0 +#define AFE_CONN089_5 0x2bb4 +#define AFE_CONN089_6 0x2bb8 +#define AFE_CONN089_7 0x2bbc +#define AFE_CONN090_0 0x2bc0 +#define AFE_CONN090_1 0x2bc4 +#define AFE_CONN090_2 0x2bc8 +#define AFE_CONN090_4 0x2bd0 +#define AFE_CONN090_5 0x2bd4 +#define AFE_CONN090_6 0x2bd8 +#define AFE_CONN090_7 0x2bdc +#define AFE_CONN091_0 0x2be0 +#define AFE_CONN091_1 0x2be4 +#define AFE_CONN091_2 0x2be8 +#define AFE_CONN091_4 0x2bf0 +#define AFE_CONN091_5 0x2bf4 +#define AFE_CONN091_6 0x2bf8 +#define AFE_CONN091_7 0x2bfc +#define AFE_CONN092_0 0x2c00 +#define AFE_CONN092_1 0x2c04 +#define AFE_CONN092_2 0x2c08 +#define AFE_CONN092_4 0x2c10 +#define AFE_CONN092_5 0x2c14 +#define AFE_CONN092_6 0x2c18 +#define AFE_CONN092_7 0x2c1c +#define AFE_CONN093_0 0x2c20 +#define AFE_CONN093_1 0x2c24 +#define AFE_CONN093_2 0x2c28 +#define AFE_CONN093_4 0x2c30 +#define AFE_CONN093_5 0x2c34 +#define AFE_CONN093_6 0x2c38 +#define AFE_CONN093_7 0x2c3c +#define AFE_CONN094_0 0x2c40 +#define AFE_CONN094_1 0x2c44 +#define AFE_CONN094_2 0x2c48 +#define AFE_CONN094_4 0x2c50 +#define AFE_CONN094_5 0x2c54 +#define AFE_CONN094_6 0x2c58 +#define AFE_CONN094_7 0x2c5c +#define AFE_CONN095_0 0x2c60 +#define AFE_CONN095_1 0x2c64 +#define AFE_CONN095_2 0x2c68 +#define AFE_CONN095_4 0x2c70 +#define AFE_CONN095_5 0x2c74 +#define AFE_CONN095_6 0x2c78 +#define AFE_CONN095_7 0x2c7c +#define AFE_CONN096_0 0x2c80 +#define AFE_CONN096_1 0x2c84 +#define AFE_CONN096_2 0x2c88 +#define AFE_CONN096_4 0x2c90 +#define AFE_CONN096_5 0x2c94 +#define AFE_CONN096_6 0x2c98 +#define AFE_CONN096_7 0x2c9c +#define AFE_CONN097_0 0x2ca0 +#define AFE_CONN097_1 0x2ca4 +#define AFE_CONN097_2 0x2ca8 +#define AFE_CONN097_4 0x2cb0 +#define AFE_CONN097_5 0x2cb4 +#define AFE_CONN097_6 0x2cb8 +#define AFE_CONN097_7 0x2cbc +#define AFE_CONN098_0 0x2cc0 +#define AFE_CONN098_1 0x2cc4 +#define AFE_CONN098_2 0x2cc8 +#define AFE_CONN098_4 0x2cd0 +#define AFE_CONN098_5 0x2cd4 +#define AFE_CONN098_6 0x2cd8 +#define AFE_CONN098_7 0x2cdc +#define AFE_CONN099_0 0x2ce0 +#define AFE_CONN099_1 0x2ce4 +#define AFE_CONN099_2 0x2ce8 +#define AFE_CONN099_4 0x2cf0 +#define AFE_CONN099_5 0x2cf4 +#define AFE_CONN099_6 0x2cf8 +#define AFE_CONN099_7 0x2cfc +#define AFE_CONN100_0 0x2d00 +#define AFE_CONN100_1 0x2d04 +#define AFE_CONN100_2 0x2d08 +#define AFE_CONN100_4 0x2d10 +#define AFE_CONN100_5 0x2d14 +#define AFE_CONN100_6 0x2d18 +#define AFE_CONN100_7 0x2d1c +#define AFE_CONN102_0 0x2d40 +#define AFE_CONN102_1 0x2d44 +#define AFE_CONN102_2 0x2d48 +#define AFE_CONN102_4 0x2d50 +#define AFE_CONN102_5 0x2d54 +#define AFE_CONN102_6 0x2d58 +#define AFE_CONN102_7 0x2d5c +#define AFE_CONN103_0 0x2d60 +#define AFE_CONN103_1 0x2d64 +#define AFE_CONN103_2 0x2d68 +#define AFE_CONN103_4 0x2d70 +#define AFE_CONN103_5 0x2d74 +#define AFE_CONN103_6 0x2d78 +#define AFE_CONN103_7 0x2d7c +#define AFE_CONN104_0 0x2d80 +#define AFE_CONN104_1 0x2d84 +#define AFE_CONN104_2 0x2d88 +#define AFE_CONN104_4 0x2d90 +#define AFE_CONN104_5 0x2d94 +#define AFE_CONN104_6 0x2d98 +#define AFE_CONN104_7 0x2d9c +#define AFE_CONN105_0 0x2da0 +#define AFE_CONN105_1 0x2da4 +#define AFE_CONN105_2 0x2da8 +#define AFE_CONN105_4 0x2db0 +#define AFE_CONN105_5 0x2db4 +#define AFE_CONN105_6 0x2db8 +#define AFE_CONN105_7 0x2dbc +#define AFE_CONN106_0 0x2dc0 +#define AFE_CONN106_1 0x2dc4 +#define AFE_CONN106_2 0x2dc8 +#define AFE_CONN106_4 0x2dd0 +#define AFE_CONN106_5 0x2dd4 +#define AFE_CONN106_6 0x2dd8 +#define AFE_CONN106_7 0x2ddc +#define AFE_CONN108_0 0x2e00 +#define AFE_CONN108_1 0x2e04 +#define AFE_CONN108_2 0x2e08 +#define AFE_CONN108_4 0x2e10 +#define AFE_CONN108_5 0x2e14 +#define AFE_CONN108_6 0x2e18 +#define AFE_CONN108_7 0x2e1c +#define AFE_CONN109_0 0x2e20 +#define AFE_CONN109_1 0x2e24 +#define AFE_CONN109_2 0x2e28 +#define AFE_CONN109_4 0x2e30 +#define AFE_CONN109_5 0x2e34 +#define AFE_CONN109_6 0x2e38 +#define AFE_CONN109_7 0x2e3c +#define AFE_CONN110_0 0x2e40 +#define AFE_CONN110_1 0x2e44 +#define AFE_CONN110_2 0x2e48 +#define AFE_CONN110_4 0x2e50 +#define AFE_CONN110_5 0x2e54 +#define AFE_CONN110_6 0x2e58 +#define AFE_CONN110_7 0x2e5c +#define AFE_CONN111_0 0x2e60 +#define AFE_CONN111_1 0x2e64 +#define AFE_CONN111_2 0x2e68 +#define AFE_CONN111_4 0x2e70 +#define AFE_CONN111_5 0x2e74 +#define AFE_CONN111_6 0x2e78 +#define AFE_CONN111_7 0x2e7c +#define AFE_CONN112_0 0x2e80 +#define AFE_CONN112_1 0x2e84 +#define AFE_CONN112_2 0x2e88 +#define AFE_CONN112_4 0x2e90 +#define AFE_CONN112_5 0x2e94 +#define AFE_CONN112_6 0x2e98 +#define AFE_CONN112_7 0x2e9c +#define AFE_CONN113_0 0x2ea0 +#define AFE_CONN113_1 0x2ea4 +#define AFE_CONN113_2 0x2ea8 +#define AFE_CONN113_4 0x2eb0 +#define AFE_CONN113_5 0x2eb4 +#define AFE_CONN113_6 0x2eb8 +#define AFE_CONN113_7 0x2ebc +#define AFE_CONN114_0 0x2ec0 +#define AFE_CONN114_1 0x2ec4 +#define AFE_CONN114_2 0x2ec8 +#define AFE_CONN114_4 0x2ed0 +#define AFE_CONN114_5 0x2ed4 +#define AFE_CONN114_6 0x2ed8 +#define AFE_CONN114_7 0x2edc +#define AFE_CONN115_0 0x2ee0 +#define AFE_CONN115_1 0x2ee4 +#define AFE_CONN115_2 0x2ee8 +#define AFE_CONN115_4 0x2ef0 +#define AFE_CONN115_5 0x2ef4 +#define AFE_CONN115_6 0x2ef8 +#define AFE_CONN115_7 0x2efc +#define AFE_CONN116_0 0x2f00 +#define AFE_CONN116_1 0x2f04 +#define AFE_CONN116_2 0x2f08 +#define AFE_CONN116_4 0x2f10 +#define AFE_CONN116_5 0x2f14 +#define AFE_CONN116_6 0x2f18 +#define AFE_CONN116_7 0x2f1c +#define AFE_CONN117_0 0x2f20 +#define AFE_CONN117_1 0x2f24 +#define AFE_CONN117_2 0x2f28 +#define AFE_CONN117_4 0x2f30 +#define AFE_CONN117_5 0x2f34 +#define AFE_CONN117_6 0x2f38 +#define AFE_CONN117_7 0x2f3c +#define AFE_CONN118_0 0x2f40 +#define AFE_CONN118_1 0x2f44 +#define AFE_CONN118_2 0x2f48 +#define AFE_CONN118_4 0x2f50 +#define AFE_CONN118_5 0x2f54 +#define AFE_CONN118_6 0x2f58 +#define AFE_CONN118_7 0x2f5c +#define AFE_CONN119_0 0x2f60 +#define AFE_CONN119_1 0x2f64 +#define AFE_CONN119_2 0x2f68 +#define AFE_CONN119_4 0x2f70 +#define AFE_CONN119_5 0x2f74 +#define AFE_CONN119_6 0x2f78 +#define AFE_CONN119_7 0x2f7c +#define AFE_CONN120_0 0x2f80 +#define AFE_CONN120_1 0x2f84 +#define AFE_CONN120_2 0x2f88 +#define AFE_CONN120_4 0x2f90 +#define AFE_CONN120_5 0x2f94 +#define AFE_CONN120_6 0x2f98 +#define AFE_CONN120_7 0x2f9c +#define AFE_CONN121_0 0x2fa0 +#define AFE_CONN121_1 0x2fa4 +#define AFE_CONN121_2 0x2fa8 +#define AFE_CONN121_4 0x2fb0 +#define AFE_CONN121_5 0x2fb4 +#define AFE_CONN121_6 0x2fb8 +#define AFE_CONN121_7 0x2fbc +#define AFE_CONN122_0 0x2fc0 +#define AFE_CONN122_1 0x2fc4 +#define AFE_CONN122_2 0x2fc8 +#define AFE_CONN122_4 0x2fd0 +#define AFE_CONN122_5 0x2fd4 +#define AFE_CONN122_6 0x2fd8 +#define AFE_CONN122_7 0x2fdc +#define AFE_CONN123_0 0x2fe0 +#define AFE_CONN123_1 0x2fe4 +#define AFE_CONN123_2 0x2fe8 +#define AFE_CONN123_4 0x2ff0 +#define AFE_CONN123_5 0x2ff4 +#define AFE_CONN123_6 0x2ff8 +#define AFE_CONN123_7 0x2ffc +#define AFE_CONN124_0 0x3000 +#define AFE_CONN124_1 0x3004 +#define AFE_CONN124_2 0x3008 +#define AFE_CONN124_4 0x3010 +#define AFE_CONN124_5 0x3014 +#define AFE_CONN124_6 0x3018 +#define AFE_CONN124_7 0x301c +#define AFE_CONN125_0 0x3020 +#define AFE_CONN125_1 0x3024 +#define AFE_CONN125_2 0x3028 +#define AFE_CONN125_4 0x3030 +#define AFE_CONN125_5 0x3034 +#define AFE_CONN125_6 0x3038 +#define AFE_CONN125_7 0x303c +#define AFE_CONN126_0 0x3040 +#define AFE_CONN126_1 0x3044 +#define AFE_CONN126_2 0x3048 +#define AFE_CONN126_4 0x3050 +#define AFE_CONN126_5 0x3054 +#define AFE_CONN126_6 0x3058 +#define AFE_CONN126_7 0x305c +#define AFE_CONN127_0 0x3060 +#define AFE_CONN127_1 0x3064 +#define AFE_CONN127_2 0x3068 +#define AFE_CONN127_4 0x3070 +#define AFE_CONN127_5 0x3074 +#define AFE_CONN127_6 0x3078 +#define AFE_CONN127_7 0x307c +#define AFE_CONN128_0 0x3080 +#define AFE_CONN128_1 0x3084 +#define AFE_CONN128_2 0x3088 +#define AFE_CONN128_4 0x3090 +#define AFE_CONN128_5 0x3094 +#define AFE_CONN128_6 0x3098 +#define AFE_CONN128_7 0x309c +#define AFE_CONN129_0 0x30a0 +#define AFE_CONN129_1 0x30a4 +#define AFE_CONN129_2 0x30a8 +#define AFE_CONN129_4 0x30b0 +#define AFE_CONN129_5 0x30b4 +#define AFE_CONN129_6 0x30b8 +#define AFE_CONN129_7 0x30bc +#define AFE_CONN130_0 0x30c0 +#define AFE_CONN130_1 0x30c4 +#define AFE_CONN130_2 0x30c8 +#define AFE_CONN130_4 0x30d0 +#define AFE_CONN130_5 0x30d4 +#define AFE_CONN130_6 0x30d8 +#define AFE_CONN130_7 0x30dc +#define AFE_CONN131_0 0x30e0 +#define AFE_CONN131_1 0x30e4 +#define AFE_CONN131_2 0x30e8 +#define AFE_CONN131_4 0x30f0 +#define AFE_CONN131_5 0x30f4 +#define AFE_CONN131_6 0x30f8 +#define AFE_CONN131_7 0x30fc +#define AFE_CONN132_0 0x3100 +#define AFE_CONN132_1 0x3104 +#define AFE_CONN132_2 0x3108 +#define AFE_CONN132_4 0x3110 +#define AFE_CONN132_5 0x3114 +#define AFE_CONN132_6 0x3118 +#define AFE_CONN132_7 0x311c +#define AFE_CONN133_0 0x3120 +#define AFE_CONN133_1 0x3124 +#define AFE_CONN133_2 0x3128 +#define AFE_CONN133_4 0x3130 +#define AFE_CONN133_5 0x3134 +#define AFE_CONN133_6 0x3138 +#define AFE_CONN133_7 0x313c +#define AFE_CONN134_0 0x3140 +#define AFE_CONN134_1 0x3144 +#define AFE_CONN134_2 0x3148 +#define AFE_CONN134_4 0x3150 +#define AFE_CONN134_5 0x3154 +#define AFE_CONN134_6 0x3158 +#define AFE_CONN134_7 0x315c +#define AFE_CONN135_0 0x3160 +#define AFE_CONN135_1 0x3164 +#define AFE_CONN135_2 0x3168 +#define AFE_CONN135_4 0x3170 +#define AFE_CONN135_5 0x3174 +#define AFE_CONN135_6 0x3178 +#define AFE_CONN135_7 0x317c +#define AFE_CONN136_0 0x3180 +#define AFE_CONN136_1 0x3184 +#define AFE_CONN136_2 0x3188 +#define AFE_CONN136_4 0x3190 +#define AFE_CONN136_5 0x3194 +#define AFE_CONN136_6 0x3198 +#define AFE_CONN136_7 0x319c +#define AFE_CONN137_0 0x31a0 +#define AFE_CONN137_1 0x31a4 +#define AFE_CONN137_2 0x31a8 +#define AFE_CONN137_4 0x31b0 +#define AFE_CONN137_5 0x31b4 +#define AFE_CONN137_6 0x31b8 +#define AFE_CONN137_7 0x31bc +#define AFE_CONN138_0 0x31c0 +#define AFE_CONN138_1 0x31c4 +#define AFE_CONN138_2 0x31c8 +#define AFE_CONN138_4 0x31d0 +#define AFE_CONN138_5 0x31d4 +#define AFE_CONN138_6 0x31d8 +#define AFE_CONN138_7 0x31dc +#define AFE_CONN139_0 0x31e0 +#define AFE_CONN139_1 0x31e4 +#define AFE_CONN139_2 0x31e8 +#define AFE_CONN139_4 0x31f0 +#define AFE_CONN139_5 0x31f4 +#define AFE_CONN139_6 0x31f8 +#define AFE_CONN139_7 0x31fc +#define AFE_CONN148_0 0x3300 +#define AFE_CONN148_1 0x3304 +#define AFE_CONN148_2 0x3308 +#define AFE_CONN148_4 0x3310 +#define AFE_CONN148_5 0x3314 +#define AFE_CONN148_6 0x3318 +#define AFE_CONN148_7 0x331c +#define AFE_CONN149_0 0x3320 +#define AFE_CONN149_1 0x3324 +#define AFE_CONN149_2 0x3328 +#define AFE_CONN149_4 0x3330 +#define AFE_CONN149_5 0x3334 +#define AFE_CONN149_6 0x3338 +#define AFE_CONN149_7 0x333c +#define AFE_CONN180_0 0x3700 +#define AFE_CONN180_1 0x3704 +#define AFE_CONN180_2 0x3708 +#define AFE_CONN180_4 0x3710 +#define AFE_CONN180_5 0x3714 +#define AFE_CONN180_6 0x3718 +#define AFE_CONN180_7 0x371c +#define AFE_CONN181_0 0x3720 +#define AFE_CONN181_1 0x3724 +#define AFE_CONN181_2 0x3728 +#define AFE_CONN181_4 0x3730 +#define AFE_CONN181_5 0x3734 +#define AFE_CONN181_6 0x3738 +#define AFE_CONN181_7 0x373c +#define AFE_CONN182_0 0x3740 +#define AFE_CONN182_1 0x3744 +#define AFE_CONN182_2 0x3748 +#define AFE_CONN182_4 0x3750 +#define AFE_CONN182_5 0x3754 +#define AFE_CONN182_6 0x3758 +#define AFE_CONN182_7 0x375c +#define AFE_CONN183_0 0x3760 +#define AFE_CONN183_1 0x3764 +#define AFE_CONN183_2 0x3768 +#define AFE_CONN183_4 0x3770 +#define AFE_CONN183_5 0x3774 +#define AFE_CONN183_6 0x3778 +#define AFE_CONN183_7 0x377c +#define AFE_CONN184_0 0x3780 +#define AFE_CONN184_1 0x3784 +#define AFE_CONN184_2 0x3788 +#define AFE_CONN184_4 0x3790 +#define AFE_CONN184_5 0x3794 +#define AFE_CONN184_6 0x3798 +#define AFE_CONN184_7 0x379c +#define AFE_CONN185_0 0x37a0 +#define AFE_CONN185_1 0x37a4 +#define AFE_CONN185_2 0x37a8 +#define AFE_CONN185_4 0x37b0 +#define AFE_CONN185_5 0x37b4 +#define AFE_CONN185_6 0x37b8 +#define AFE_CONN185_7 0x37bc +#define AFE_CONN186_0 0x37c0 +#define AFE_CONN186_1 0x37c4 +#define AFE_CONN186_2 0x37c8 +#define AFE_CONN186_4 0x37d0 +#define AFE_CONN186_5 0x37d4 +#define AFE_CONN186_6 0x37d8 +#define AFE_CONN186_7 0x37dc +#define AFE_CONN187_0 0x37e0 +#define AFE_CONN187_1 0x37e4 +#define AFE_CONN187_2 0x37e8 +#define AFE_CONN187_4 0x37f0 +#define AFE_CONN187_5 0x37f4 +#define AFE_CONN187_6 0x37f8 +#define AFE_CONN187_7 0x37fc +#define AFE_CONN188_0 0x3800 +#define AFE_CONN188_1 0x3804 +#define AFE_CONN188_2 0x3808 +#define AFE_CONN188_4 0x3810 +#define AFE_CONN188_5 0x3814 +#define AFE_CONN188_6 0x3818 +#define AFE_CONN188_7 0x381c +#define AFE_CONN189_0 0x3820 +#define AFE_CONN189_1 0x3824 +#define AFE_CONN189_2 0x3828 +#define AFE_CONN189_4 0x3830 +#define AFE_CONN189_5 0x3834 +#define AFE_CONN189_6 0x3838 +#define AFE_CONN189_7 0x383c +#define AFE_CONN190_0 0x3840 +#define AFE_CONN190_1 0x3844 +#define AFE_CONN190_2 0x3848 +#define AFE_CONN190_4 0x3850 +#define AFE_CONN190_5 0x3854 +#define AFE_CONN190_6 0x3858 +#define AFE_CONN190_7 0x385c +#define AFE_CONN191_0 0x3860 +#define AFE_CONN191_1 0x3864 +#define AFE_CONN191_2 0x3868 +#define AFE_CONN191_4 0x3870 +#define AFE_CONN191_5 0x3874 +#define AFE_CONN191_6 0x3878 +#define AFE_CONN191_7 0x387c +#define AFE_CONN192_0 0x3880 +#define AFE_CONN192_1 0x3884 +#define AFE_CONN192_2 0x3888 +#define AFE_CONN192_4 0x3890 +#define AFE_CONN192_5 0x3894 +#define AFE_CONN192_6 0x3898 +#define AFE_CONN192_7 0x389c +#define AFE_CONN193_0 0x38a0 +#define AFE_CONN193_1 0x38a4 +#define AFE_CONN193_2 0x38a8 +#define AFE_CONN193_4 0x38b0 +#define AFE_CONN193_5 0x38b4 +#define AFE_CONN193_6 0x38b8 +#define AFE_CONN193_7 0x38bc +#define AFE_CONN194_0 0x38c0 +#define AFE_CONN194_1 0x38c4 +#define AFE_CONN194_2 0x38c8 +#define AFE_CONN194_4 0x38d0 +#define AFE_CONN194_5 0x38d4 +#define AFE_CONN194_6 0x38d8 +#define AFE_CONN194_7 0x38dc +#define AFE_CONN195_0 0x38e0 +#define AFE_CONN195_1 0x38e4 +#define AFE_CONN195_2 0x38e8 +#define AFE_CONN195_4 0x38f0 +#define AFE_CONN195_5 0x38f4 +#define AFE_CONN195_6 0x38f8 +#define AFE_CONN195_7 0x38fc +#define AFE_CONN196_0 0x3900 +#define AFE_CONN196_1 0x3904 +#define AFE_CONN196_2 0x3908 +#define AFE_CONN196_4 0x3910 +#define AFE_CONN196_5 0x3914 +#define AFE_CONN196_6 0x3918 +#define AFE_CONN196_7 0x391c +#define AFE_CONN197_0 0x3920 +#define AFE_CONN197_1 0x3924 +#define AFE_CONN197_2 0x3928 +#define AFE_CONN197_4 0x3930 +#define AFE_CONN197_5 0x3934 +#define AFE_CONN197_6 0x3938 +#define AFE_CONN197_7 0x393c +#define AFE_CONN198_0 0x3940 +#define AFE_CONN198_1 0x3944 +#define AFE_CONN198_2 0x3948 +#define AFE_CONN198_4 0x3950 +#define AFE_CONN198_5 0x3954 +#define AFE_CONN198_6 0x3958 +#define AFE_CONN198_7 0x395c +#define AFE_CONN199_0 0x3960 +#define AFE_CONN199_1 0x3964 +#define AFE_CONN199_2 0x3968 +#define AFE_CONN199_4 0x3970 +#define AFE_CONN199_5 0x3974 +#define AFE_CONN199_6 0x3978 +#define AFE_CONN199_7 0x397c +#define AFE_CONN200_0 0x3980 +#define AFE_CONN200_1 0x3984 +#define AFE_CONN200_2 0x3988 +#define AFE_CONN200_4 0x3990 +#define AFE_CONN200_5 0x3994 +#define AFE_CONN200_6 0x3998 +#define AFE_CONN200_7 0x399c +#define AFE_CONN201_0 0x39a0 +#define AFE_CONN201_1 0x39a4 +#define AFE_CONN201_2 0x39a8 +#define AFE_CONN201_4 0x39b0 +#define AFE_CONN201_5 0x39b4 +#define AFE_CONN201_6 0x39b8 +#define AFE_CONN201_7 0x39bc +#define AFE_CONN202_0 0x39c0 +#define AFE_CONN202_1 0x39c4 +#define AFE_CONN202_2 0x39c8 +#define AFE_CONN202_4 0x39d0 +#define AFE_CONN202_5 0x39d4 +#define AFE_CONN202_6 0x39d8 +#define AFE_CONN202_7 0x39dc +#define AFE_CONN203_0 0x39e0 +#define AFE_CONN203_1 0x39e4 +#define AFE_CONN203_2 0x39e8 +#define AFE_CONN203_4 0x39f0 +#define AFE_CONN203_5 0x39f4 +#define AFE_CONN203_6 0x39f8 +#define AFE_CONN203_7 0x39fc +#define AFE_CONN204_0 0x3a00 +#define AFE_CONN204_1 0x3a04 +#define AFE_CONN204_2 0x3a08 +#define AFE_CONN204_4 0x3a10 +#define AFE_CONN204_5 0x3a14 +#define AFE_CONN204_6 0x3a18 +#define AFE_CONN204_7 0x3a1c +#define AFE_CONN205_0 0x3a20 +#define AFE_CONN205_1 0x3a24 +#define AFE_CONN205_2 0x3a28 +#define AFE_CONN205_4 0x3a30 +#define AFE_CONN205_5 0x3a34 +#define AFE_CONN205_6 0x3a38 +#define AFE_CONN205_7 0x3a3c +#define AFE_CONN206_0 0x3a40 +#define AFE_CONN206_1 0x3a44 +#define AFE_CONN206_2 0x3a48 +#define AFE_CONN206_4 0x3a50 +#define AFE_CONN206_5 0x3a54 +#define AFE_CONN206_6 0x3a58 +#define AFE_CONN206_7 0x3a5c +#define AFE_CONN207_0 0x3a60 +#define AFE_CONN207_1 0x3a64 +#define AFE_CONN207_2 0x3a68 +#define AFE_CONN207_4 0x3a70 +#define AFE_CONN207_5 0x3a74 +#define AFE_CONN207_6 0x3a78 +#define AFE_CONN207_7 0x3a7c +#define AFE_CONN208_0 0x3a80 +#define AFE_CONN208_1 0x3a84 +#define AFE_CONN208_2 0x3a88 +#define AFE_CONN208_4 0x3a90 +#define AFE_CONN208_5 0x3a94 +#define AFE_CONN208_6 0x3a98 +#define AFE_CONN208_7 0x3a9c +#define AFE_CONN209_0 0x3aa0 +#define AFE_CONN209_1 0x3aa4 +#define AFE_CONN209_2 0x3aa8 +#define AFE_CONN209_4 0x3ab0 +#define AFE_CONN209_5 0x3ab4 +#define AFE_CONN209_6 0x3ab8 +#define AFE_CONN209_7 0x3abc +#define AFE_CONN210_0 0x3ac0 +#define AFE_CONN210_1 0x3ac4 +#define AFE_CONN210_2 0x3ac8 +#define AFE_CONN210_4 0x3ad0 +#define AFE_CONN210_5 0x3ad4 +#define AFE_CONN210_6 0x3ad8 +#define AFE_CONN210_7 0x3adc +#define AFE_CONN211_0 0x3ae0 +#define AFE_CONN211_1 0x3ae4 +#define AFE_CONN211_2 0x3ae8 +#define AFE_CONN211_4 0x3af0 +#define AFE_CONN211_5 0x3af4 +#define AFE_CONN211_6 0x3af8 +#define AFE_CONN211_7 0x3afc +#define AFE_CONN_MON_CFG 0x4080 +#define AFE_CONN_MON0 0x4084 +#define AFE_CONN_MON1 0x4088 +#define AFE_CONN_MON2 0x408c +#define AFE_CONN_MON3 0x4090 +#define AFE_CONN_MON4 0x4094 +#define AFE_CONN_MON5 0x4098 +#define AFE_CONN_RS_0 0x40a0 +#define AFE_CONN_RS_1 0x40a4 +#define AFE_CONN_RS_2 0x40a8 +#define AFE_CONN_RS_3 0x40ac +#define AFE_CONN_RS_4 0x40b0 +#define AFE_CONN_RS_5 0x40b4 +#define AFE_CONN_RS_6 0x40b8 +#define AFE_CONN_DI_0 0x40c0 +#define AFE_CONN_DI_1 0x40c4 +#define AFE_CONN_DI_2 0x40c8 +#define AFE_CONN_DI_3 0x40cc +#define AFE_CONN_DI_4 0x40d0 +#define AFE_CONN_DI_5 0x40d4 +#define AFE_CONN_DI_6 0x40d8 +#define AFE_CONN_16BIT_0 0x40e0 +#define AFE_CONN_16BIT_1 0x40e4 +#define AFE_CONN_16BIT_2 0x40e8 +#define AFE_CONN_16BIT_3 0x40ec +#define AFE_CONN_16BIT_4 0x40f0 +#define AFE_CONN_16BIT_5 0x40f4 +#define AFE_CONN_16BIT_6 0x40f8 +#define AFE_CONN_24BIT_0 0x4100 +#define AFE_CONN_24BIT_1 0x4104 +#define AFE_CONN_24BIT_2 0x4108 +#define AFE_CONN_24BIT_3 0x410c +#define AFE_CONN_24BIT_4 0x4110 +#define AFE_CONN_24BIT_5 0x4114 +#define AFE_CONN_24BIT_6 0x4118 +#define AFE_CBIP_CFG0 0x4380 +#define AFE_CBIP_SLV_DECODER_MON0 0x4384 +#define AFE_CBIP_SLV_DECODER_MON1 0x4388 +#define AFE_CBIP_SLV_MUX_MON_CFG 0x438c +#define AFE_CBIP_SLV_MUX_MON0 0x4390 +#define AFE_CBIP_SLV_MUX_MON1 0x4394 +#define AFE_MEMIF_CON0 0x4400 +#define AFE_MEMIF_ONE_HEART 0x4420 +#define AFE_DL0_BASE_MSB 0x4440 +#define AFE_DL0_BASE 0x4444 +#define AFE_DL0_CUR_MSB 0x4448 +#define AFE_DL0_CUR 0x444c +#define AFE_DL0_END_MSB 0x4450 +#define AFE_DL0_END 0x4454 +#define AFE_DL0_RCH_MON 0x4458 +#define AFE_DL0_LCH_MON 0x445c +#define AFE_DL0_CON0 0x4460 +#define AFE_DL0_MON0 0x4464 +#define AFE_DL1_BASE_MSB 0x4470 +#define AFE_DL1_BASE 0x4474 +#define AFE_DL1_CUR_MSB 0x4478 +#define AFE_DL1_CUR 0x447c +#define AFE_DL1_END_MSB 0x4480 +#define AFE_DL1_END 0x4484 +#define AFE_DL1_RCH_MON 0x4488 +#define AFE_DL1_LCH_MON 0x448c +#define AFE_DL1_CON0 0x4490 +#define AFE_DL1_MON0 0x4494 +#define AFE_DL2_BASE_MSB 0x44a0 +#define AFE_DL2_BASE 0x44a4 +#define AFE_DL2_CUR_MSB 0x44a8 +#define AFE_DL2_CUR 0x44ac +#define AFE_DL2_END_MSB 0x44b0 +#define AFE_DL2_END 0x44b4 +#define AFE_DL2_RCH_MON 0x44b8 +#define AFE_DL2_LCH_MON 0x44bc +#define AFE_DL2_CON0 0x44c0 +#define AFE_DL2_MON0 0x44c4 +#define AFE_DL3_BASE_MSB 0x44d0 +#define AFE_DL3_BASE 0x44d4 +#define AFE_DL3_CUR_MSB 0x44d8 +#define AFE_DL3_CUR 0x44dc +#define AFE_DL3_END_MSB 0x44e0 +#define AFE_DL3_END 0x44e4 +#define AFE_DL3_RCH_MON 0x44e8 +#define AFE_DL3_LCH_MON 0x44ec +#define AFE_DL3_CON0 0x44f0 +#define AFE_DL3_MON0 0x44f4 +#define AFE_DL4_BASE_MSB 0x4500 +#define AFE_DL4_BASE 0x4504 +#define AFE_DL4_CUR_MSB 0x4508 +#define AFE_DL4_CUR 0x450c +#define AFE_DL4_END_MSB 0x4510 +#define AFE_DL4_END 0x4514 +#define AFE_DL4_RCH_MON 0x4518 +#define AFE_DL4_LCH_MON 0x451c +#define AFE_DL4_CON0 0x4520 +#define AFE_DL4_MON0 0x4524 +#define AFE_DL5_BASE_MSB 0x4530 +#define AFE_DL5_BASE 0x4534 +#define AFE_DL5_CUR_MSB 0x4538 +#define AFE_DL5_CUR 0x453c +#define AFE_DL5_END_MSB 0x4540 +#define AFE_DL5_END 0x4544 +#define AFE_DL5_RCH_MON 0x4548 +#define AFE_DL5_LCH_MON 0x454c +#define AFE_DL5_CON0 0x4550 +#define AFE_DL5_MON0 0x4554 +#define AFE_DL6_BASE_MSB 0x4560 +#define AFE_DL6_BASE 0x4564 +#define AFE_DL6_CUR_MSB 0x4568 +#define AFE_DL6_CUR 0x456c +#define AFE_DL6_END_MSB 0x4570 +#define AFE_DL6_END 0x4574 +#define AFE_DL6_RCH_MON 0x4578 +#define AFE_DL6_LCH_MON 0x457c +#define AFE_DL6_CON0 0x4580 +#define AFE_DL6_MON0 0x4584 +#define AFE_DL7_BASE_MSB 0x4590 +#define AFE_DL7_BASE 0x4594 +#define AFE_DL7_CUR_MSB 0x4598 +#define AFE_DL7_CUR 0x459c +#define AFE_DL7_END_MSB 0x45a0 +#define AFE_DL7_END 0x45a4 +#define AFE_DL7_RCH_MON 0x45a8 +#define AFE_DL7_LCH_MON 0x45ac +#define AFE_DL7_CON0 0x45b0 +#define AFE_DL7_MON0 0x45b4 +#define AFE_DL8_BASE_MSB 0x45c0 +#define AFE_DL8_BASE 0x45c4 +#define AFE_DL8_CUR_MSB 0x45c8 +#define AFE_DL8_CUR 0x45cc +#define AFE_DL8_END_MSB 0x45d0 +#define AFE_DL8_END 0x45d4 +#define AFE_DL8_RCH_MON 0x45d8 +#define AFE_DL8_LCH_MON 0x45dc +#define AFE_DL8_CON0 0x45e0 +#define AFE_DL8_MON0 0x45e4 +#define AFE_DL_4CH_BASE_MSB 0x45f0 +#define AFE_DL_4CH_BASE 0x45f4 +#define AFE_DL_4CH_CUR_MSB 0x45f8 +#define AFE_DL_4CH_CUR 0x45fc +#define AFE_DL_4CH_END_MSB 0x4600 +#define AFE_DL_4CH_END 0x4604 +#define AFE_DL_4CH_CON0 0x4610 +#define AFE_DL_4CH_MON0 0x4618 +#define AFE_DL_24CH_BASE_MSB 0x4620 +#define AFE_DL_24CH_BASE 0x4624 +#define AFE_DL_24CH_CUR_MSB 0x4628 +#define AFE_DL_24CH_CUR 0x462c +#define AFE_DL_24CH_END_MSB 0x4630 +#define AFE_DL_24CH_END 0x4634 +#define AFE_DL_24CH_CON0 0x4640 +#define AFE_DL_24CH_MON0 0x4648 +#define AFE_DL23_BASE_MSB 0x4680 +#define AFE_DL23_BASE 0x4684 +#define AFE_DL23_CUR_MSB 0x4688 +#define AFE_DL23_CUR 0x468c +#define AFE_DL23_END_MSB 0x4690 +#define AFE_DL23_END 0x4694 +#define AFE_DL23_RCH_MON 0x4698 +#define AFE_DL23_LCH_MON 0x469c +#define AFE_DL23_CON0 0x46a0 +#define AFE_DL23_MON0 0x46a4 +#define AFE_DL24_BASE_MSB 0x46b0 +#define AFE_DL24_BASE 0x46b4 +#define AFE_DL24_CUR_MSB 0x46b8 +#define AFE_DL24_CUR 0x46bc +#define AFE_DL24_END_MSB 0x46c0 +#define AFE_DL24_END 0x46c4 +#define AFE_DL24_RCH_MON 0x46c8 +#define AFE_DL24_LCH_MON 0x46cc +#define AFE_DL24_CON0 0x46d0 +#define AFE_DL24_MON0 0x46d4 +#define AFE_DL25_BASE_MSB 0x46e0 +#define AFE_DL25_BASE 0x46e4 +#define AFE_DL25_CUR_MSB 0x46e8 +#define AFE_DL25_CUR 0x46ec +#define AFE_DL25_END_MSB 0x46f0 +#define AFE_DL25_END 0x46f4 +#define AFE_DL25_RCH_MON 0x46f8 +#define AFE_DL25_LCH_MON 0x46fc +#define AFE_DL25_CON0 0x4700 +#define AFE_DL25_MON0 0x4704 +#define AFE_DL26_BASE_MSB 0x4710 +#define AFE_DL26_BASE 0x4714 +#define AFE_DL26_CUR_MSB 0x4718 +#define AFE_DL26_CUR 0x471c +#define AFE_DL26_END_MSB 0x4720 +#define AFE_DL26_END 0x4724 +#define AFE_DL26_RCH_MON 0x4728 +#define AFE_DL26_LCH_MON 0x472c +#define AFE_DL26_CON0 0x4730 +#define AFE_DL26_MON0 0x4734 +#define AFE_VUL0_BASE_MSB 0x4d60 +#define AFE_VUL0_BASE 0x4d64 +#define AFE_VUL0_CUR_MSB 0x4d68 +#define AFE_VUL0_CUR 0x4d6c +#define AFE_VUL0_END_MSB 0x4d70 +#define AFE_VUL0_END 0x4d74 +#define AFE_VUL0_RCH_MON 0x4d78 +#define AFE_VUL0_LCH_MON 0x4d7c +#define AFE_VUL0_CON0 0x4d80 +#define AFE_VUL0_MON0 0x4d84 +#define AFE_VUL1_BASE_MSB 0x4d90 +#define AFE_VUL1_BASE 0x4d94 +#define AFE_VUL1_CUR_MSB 0x4d98 +#define AFE_VUL1_CUR 0x4d9c +#define AFE_VUL1_END_MSB 0x4da0 +#define AFE_VUL1_END 0x4da4 +#define AFE_VUL1_RCH_MON 0x4da8 +#define AFE_VUL1_LCH_MON 0x4dac +#define AFE_VUL1_CON0 0x4db0 +#define AFE_VUL1_MON0 0x4db4 +#define AFE_VUL2_BASE_MSB 0x4dc0 +#define AFE_VUL2_BASE 0x4dc4 +#define AFE_VUL2_CUR_MSB 0x4dc8 +#define AFE_VUL2_CUR 0x4dcc +#define AFE_VUL2_END_MSB 0x4dd0 +#define AFE_VUL2_END 0x4dd4 +#define AFE_VUL2_RCH_MON 0x4dd8 +#define AFE_VUL2_LCH_MON 0x4ddc +#define AFE_VUL2_CON0 0x4de0 +#define AFE_VUL2_MON0 0x4de4 +#define AFE_VUL3_BASE_MSB 0x4df0 +#define AFE_VUL3_BASE 0x4df4 +#define AFE_VUL3_CUR_MSB 0x4df8 +#define AFE_VUL3_CUR 0x4dfc +#define AFE_VUL3_END_MSB 0x4e00 +#define AFE_VUL3_END 0x4e04 +#define AFE_VUL3_RCH_MON 0x4e08 +#define AFE_VUL3_LCH_MON 0x4e0c +#define AFE_VUL3_CON0 0x4e10 +#define AFE_VUL3_MON0 0x4e14 +#define AFE_VUL4_BASE_MSB 0x4e20 +#define AFE_VUL4_BASE 0x4e24 +#define AFE_VUL4_CUR_MSB 0x4e28 +#define AFE_VUL4_CUR 0x4e2c +#define AFE_VUL4_END_MSB 0x4e30 +#define AFE_VUL4_END 0x4e34 +#define AFE_VUL4_RCH_MON 0x4e38 +#define AFE_VUL4_LCH_MON 0x4e3c +#define AFE_VUL4_CON0 0x4e40 +#define AFE_VUL4_MON0 0x4e44 +#define AFE_VUL5_BASE_MSB 0x4e50 +#define AFE_VUL5_BASE 0x4e54 +#define AFE_VUL5_CUR_MSB 0x4e58 +#define AFE_VUL5_CUR 0x4e5c +#define AFE_VUL5_END_MSB 0x4e60 +#define AFE_VUL5_END 0x4e64 +#define AFE_VUL5_RCH_MON 0x4e68 +#define AFE_VUL5_LCH_MON 0x4e6c +#define AFE_VUL5_CON0 0x4e70 +#define AFE_VUL5_MON0 0x4e74 +#define AFE_VUL6_BASE_MSB 0x4e80 +#define AFE_VUL6_BASE 0x4e84 +#define AFE_VUL6_CUR_MSB 0x4e88 +#define AFE_VUL6_CUR 0x4e8c +#define AFE_VUL6_END_MSB 0x4e90 +#define AFE_VUL6_END 0x4e94 +#define AFE_VUL6_RCH_MON 0x4e98 +#define AFE_VUL6_LCH_MON 0x4e9c +#define AFE_VUL6_CON0 0x4ea0 +#define AFE_VUL6_MON0 0x4ea4 +#define AFE_VUL7_BASE_MSB 0x4eb0 +#define AFE_VUL7_BASE 0x4eb4 +#define AFE_VUL7_CUR_MSB 0x4eb8 +#define AFE_VUL7_CUR 0x4ebc +#define AFE_VUL7_END_MSB 0x4ec0 +#define AFE_VUL7_END 0x4ec4 +#define AFE_VUL7_RCH_MON 0x4ec8 +#define AFE_VUL7_LCH_MON 0x4ecc +#define AFE_VUL7_CON0 0x4ed0 +#define AFE_VUL7_MON0 0x4ed4 +#define AFE_VUL8_BASE_MSB 0x4ee0 +#define AFE_VUL8_BASE 0x4ee4 +#define AFE_VUL8_CUR_MSB 0x4ee8 +#define AFE_VUL8_CUR 0x4eec +#define AFE_VUL8_END_MSB 0x4ef0 +#define AFE_VUL8_END 0x4ef4 +#define AFE_VUL8_RCH_MON 0x4ef8 +#define AFE_VUL8_LCH_MON 0x4efc +#define AFE_VUL8_CON0 0x4f00 +#define AFE_VUL8_MON0 0x4f04 +#define AFE_VUL9_BASE_MSB 0x4f10 +#define AFE_VUL9_BASE 0x4f14 +#define AFE_VUL9_CUR_MSB 0x4f18 +#define AFE_VUL9_CUR 0x4f1c +#define AFE_VUL9_END_MSB 0x4f20 +#define AFE_VUL9_END 0x4f24 +#define AFE_VUL9_RCH_MON 0x4f28 +#define AFE_VUL9_LCH_MON 0x4f2c +#define AFE_VUL9_CON0 0x4f30 +#define AFE_VUL9_MON0 0x4f34 +#define AFE_VUL10_BASE_MSB 0x4f40 +#define AFE_VUL10_BASE 0x4f44 +#define AFE_VUL10_CUR_MSB 0x4f48 +#define AFE_VUL10_CUR 0x4f4c +#define AFE_VUL10_END_MSB 0x4f50 +#define AFE_VUL10_END 0x4f54 +#define AFE_VUL10_RCH_MON 0x4f58 +#define AFE_VUL10_LCH_MON 0x4f5c +#define AFE_VUL10_CON0 0x4f60 +#define AFE_VUL10_MON0 0x4f64 +#define AFE_VUL24_BASE_MSB 0x4fa0 +#define AFE_VUL24_BASE 0x4fa4 +#define AFE_VUL24_CUR_MSB 0x4fa8 +#define AFE_VUL24_CUR 0x4fac +#define AFE_VUL24_END_MSB 0x4fb0 +#define AFE_VUL24_END 0x4fb4 +#define AFE_VUL24_CON0 0x4fb8 +#define AFE_VUL24_MON0 0x4fbc +#define AFE_VUL25_BASE_MSB 0x4fc0 +#define AFE_VUL25_BASE 0x4fc4 +#define AFE_VUL25_CUR_MSB 0x4fc8 +#define AFE_VUL25_CUR 0x4fcc +#define AFE_VUL25_END_MSB 0x4fd0 +#define AFE_VUL25_END 0x4fd4 +#define AFE_VUL25_CON0 0x4fd8 +#define AFE_VUL25_MON0 0x4fdc +#define AFE_VUL26_BASE_MSB 0x4fe0 +#define AFE_VUL26_BASE 0x4fe4 +#define AFE_VUL26_CUR_MSB 0x4fe8 +#define AFE_VUL26_CUR 0x4fec +#define AFE_VUL26_END_MSB 0x4ff0 +#define AFE_VUL26_END 0x4ff4 +#define AFE_VUL26_CON0 0x4ff8 +#define AFE_VUL26_MON0 0x4ffc +#define AFE_VUL_CM0_BASE_MSB 0x51c0 +#define AFE_VUL_CM0_BASE 0x51c4 +#define AFE_VUL_CM0_CUR_MSB 0x51c8 +#define AFE_VUL_CM0_CUR 0x51cc +#define AFE_VUL_CM0_END_MSB 0x51d0 +#define AFE_VUL_CM0_END 0x51d4 +#define AFE_VUL_CM0_CON0 0x51d8 +#define AFE_VUL_CM1_BASE_MSB 0x51e0 +#define AFE_VUL_CM1_BASE 0x51e4 +#define AFE_VUL_CM1_CUR_MSB 0x51e8 +#define AFE_VUL_CM1_CUR 0x51ec +#define AFE_VUL_CM1_END_MSB 0x51f0 +#define AFE_VUL_CM1_END 0x51f4 +#define AFE_VUL_CM1_CON0 0x51f8 +#define AFE_VUL_CM2_BASE_MSB 0x5200 +#define AFE_VUL_CM2_BASE 0x5204 +#define AFE_VUL_CM2_CUR_MSB 0x5208 +#define AFE_VUL_CM2_CUR 0x520c +#define AFE_VUL_CM2_END_MSB 0x5210 +#define AFE_VUL_CM2_END 0x5214 +#define AFE_VUL_CM2_CON0 0x5218 +#define AFE_ETDM_IN0_BASE_MSB 0x5220 +#define AFE_ETDM_IN0_BASE 0x5224 +#define AFE_ETDM_IN0_CUR_MSB 0x5228 +#define AFE_ETDM_IN0_CUR 0x522c +#define AFE_ETDM_IN0_END_MSB 0x5230 +#define AFE_ETDM_IN0_END 0x5234 +#define AFE_ETDM_IN0_CON0 0x5238 +#define AFE_ETDM_IN1_BASE_MSB 0x5240 +#define AFE_ETDM_IN1_BASE 0x5244 +#define AFE_ETDM_IN1_CUR_MSB 0x5248 +#define AFE_ETDM_IN1_CUR 0x524c +#define AFE_ETDM_IN1_END_MSB 0x5250 +#define AFE_ETDM_IN1_END 0x5254 +#define AFE_ETDM_IN1_CON0 0x5258 +#define AFE_ETDM_IN2_BASE_MSB 0x5260 +#define AFE_ETDM_IN2_BASE 0x5264 +#define AFE_ETDM_IN2_CUR_MSB 0x5268 +#define AFE_ETDM_IN2_CUR 0x526c +#define AFE_ETDM_IN2_END_MSB 0x5270 +#define AFE_ETDM_IN2_END 0x5274 +#define AFE_ETDM_IN2_CON0 0x5278 +#define AFE_ETDM_IN3_BASE_MSB 0x5280 +#define AFE_ETDM_IN3_BASE 0x5284 +#define AFE_ETDM_IN3_CUR_MSB 0x5288 +#define AFE_ETDM_IN3_CUR 0x528c +#define AFE_ETDM_IN3_END_MSB 0x5290 +#define AFE_ETDM_IN3_END 0x5294 +#define AFE_ETDM_IN3_CON0 0x5298 +#define AFE_ETDM_IN4_BASE_MSB 0x52a0 +#define AFE_ETDM_IN4_BASE 0x52a4 +#define AFE_ETDM_IN4_CUR_MSB 0x52a8 +#define AFE_ETDM_IN4_CUR 0x52ac +#define AFE_ETDM_IN4_END_MSB 0x52b0 +#define AFE_ETDM_IN4_END 0x52b4 +#define AFE_ETDM_IN4_CON0 0x52b8 +#define AFE_ETDM_IN5_BASE_MSB 0x52c0 +#define AFE_ETDM_IN5_BASE 0x52c4 +#define AFE_ETDM_IN5_CUR_MSB 0x52c8 +#define AFE_ETDM_IN5_CUR 0x52cc +#define AFE_ETDM_IN5_END_MSB 0x52d0 +#define AFE_ETDM_IN5_END 0x52d4 +#define AFE_ETDM_IN5_CON0 0x52d8 +#define AFE_ETDM_IN6_BASE_MSB 0x52e0 +#define AFE_ETDM_IN6_BASE 0x52e4 +#define AFE_ETDM_IN6_CUR_MSB 0x52e8 +#define AFE_ETDM_IN6_CUR 0x52ec +#define AFE_ETDM_IN6_END_MSB 0x52f0 +#define AFE_ETDM_IN6_END 0x52f4 +#define AFE_ETDM_IN6_CON0 0x52f8 +#define AFE_HDMI_OUT_BASE_MSB 0x5360 +#define AFE_HDMI_OUT_BASE 0x5364 +#define AFE_HDMI_OUT_CUR_MSB 0x5368 +#define AFE_HDMI_OUT_CUR 0x536c +#define AFE_HDMI_OUT_END_MSB 0x5370 +#define AFE_HDMI_OUT_END 0x5374 +#define AFE_HDMI_OUT_CON0 0x5378 +#define AFE_VUL24_RCH_MON 0x53e0 +#define AFE_VUL24_LCH_MON 0x53e4 +#define AFE_VUL25_RCH_MON 0x53e8 +#define AFE_VUL25_LCH_MON 0x53ec +#define AFE_VUL26_RCH_MON 0x53f0 +#define AFE_VUL26_LCH_MON 0x53f4 +#define AFE_VUL_CM0_RCH_MON 0x5458 +#define AFE_VUL_CM0_LCH_MON 0x545c +#define AFE_VUL_CM1_RCH_MON 0x5460 +#define AFE_VUL_CM1_LCH_MON 0x5464 +#define AFE_VUL_CM2_RCH_MON 0x5468 +#define AFE_VUL_CM2_LCH_MON 0x546c +#define AFE_DL_4CH_CH0_MON 0x54f4 +#define AFE_DL_4CH_CH1_MON 0x54f8 +#define AFE_DL_4CH_CH2_MON 0x54fc +#define AFE_DL_4CH_CH3_MON 0x5500 +#define AFE_DL_24CH_CH0_MON 0x5504 +#define AFE_DL_24CH_CH1_MON 0x5508 +#define AFE_DL_24CH_CH2_MON 0x550c +#define AFE_DL_24CH_CH3_MON 0x5510 +#define AFE_DL_24CH_CH4_MON 0x5514 +#define AFE_DL_24CH_CH5_MON 0x5518 +#define AFE_DL_24CH_CH6_MON 0x551c +#define AFE_DL_24CH_CH7_MON 0x5520 +#define AFE_DL_24CH_CH8_MON 0x5524 +#define AFE_DL_24CH_CH9_MON 0x5528 +#define AFE_DL_24CH_CH10_MON 0x552c +#define AFE_DL_24CH_CH11_MON 0x5530 +#define AFE_DL_24CH_CH12_MON 0x5534 +#define AFE_DL_24CH_CH13_MON 0x5538 +#define AFE_DL_24CH_CH14_MON 0x553c +#define AFE_DL_24CH_CH15_MON 0x5540 +#define AFE_SRAM_BOUND 0x5620 +#define AFE_SECURE_CON0 0x5624 +#define AFE_SECURE_CON1 0x5628 +#define AFE_SE_SECURE_CON0 0x5630 +#define AFE_SE_SECURE_CON1 0x5634 +#define AFE_SE_SECURE_CON2 0x5638 +#define AFE_SE_SECURE_CON3 0x563c +#define AFE_SE_PROT_SIDEBAND0 0x5640 +#define AFE_SE_PROT_SIDEBAND1 0x5644 +#define AFE_SE_PROT_SIDEBAND2 0x5648 +#define AFE_SE_PROT_SIDEBAND3 0x564c +#define AFE_SE_DOMAIN_SIDEBAND0 0x5650 +#define AFE_SE_DOMAIN_SIDEBAND1 0x5654 +#define AFE_SE_DOMAIN_SIDEBAND2 0x5658 +#define AFE_SE_DOMAIN_SIDEBAND3 0x565c +#define AFE_SE_DOMAIN_SIDEBAND4 0x5660 +#define AFE_SE_DOMAIN_SIDEBAND5 0x5664 +#define AFE_SE_DOMAIN_SIDEBAND6 0x5668 +#define AFE_SE_DOMAIN_SIDEBAND7 0x566c +#define AFE_SE_DOMAIN_SIDEBAND8 0x5670 +#define AFE_SE_DOMAIN_SIDEBAND9 0x5674 +#define AFE_PROT_SIDEBAND0_MON 0x5678 +#define AFE_PROT_SIDEBAND1_MON 0x567c +#define AFE_PROT_SIDEBAND2_MON 0x5680 +#define AFE_PROT_SIDEBAND3_MON 0x5684 +#define AFE_DOMAIN_SIDEBAND0_MON 0x5688 +#define AFE_DOMAIN_SIDEBAND1_MON 0x568c +#define AFE_DOMAIN_SIDEBAND2_MON 0x5690 +#define AFE_DOMAIN_SIDEBAND3_MON 0x5694 +#define AFE_DOMAIN_SIDEBAND4_MON 0x5698 +#define AFE_DOMAIN_SIDEBAND5_MON 0x569c +#define AFE_DOMAIN_SIDEBAND6_MON 0x56a0 +#define AFE_DOMAIN_SIDEBAND7_MON 0x56a4 +#define AFE_DOMAIN_SIDEBAND8_MON 0x56a8 +#define AFE_DOMAIN_SIDEBAND9_MON 0x56ac +#define AFE_SECURE_CONN0 0x56b0 +#define AFE_SECURE_CONN_ETDM0 0x56b4 +#define AFE_SECURE_CONN_ETDM1 0x56b8 +#define AFE_SECURE_CONN_ETDM2 0x56bc +#define AFE_SECURE_SRAM_CON0 0x56c0 +#define AFE_SECURE_SRAM_CON1 0x56c4 +#define AFE_SE_CONN_INPUT_MASK0 0x56d0 +#define AFE_SE_CONN_INPUT_MASK1 0x56d4 +#define AFE_SE_CONN_INPUT_MASK2 0x56d8 +#define AFE_SE_CONN_INPUT_MASK3 0x56dc +#define AFE_SE_CONN_INPUT_MASK4 0x56e0 +#define AFE_SE_CONN_INPUT_MASK5 0x56e4 +#define AFE_SE_CONN_INPUT_MASK6 0x56e8 +#define AFE_SE_CONN_INPUT_MASK7 0x56ec +#define AFE_NON_SE_CONN_INPUT_MASK0 0x56f0 +#define AFE_NON_SE_CONN_INPUT_MASK1 0x56f4 +#define AFE_NON_SE_CONN_INPUT_MASK2 0x56f8 +#define AFE_NON_SE_CONN_INPUT_MASK3 0x56fc +#define AFE_NON_SE_CONN_INPUT_MASK4 0x5700 +#define AFE_NON_SE_CONN_INPUT_MASK5 0x5704 +#define AFE_NON_SE_CONN_INPUT_MASK6 0x5708 +#define AFE_NON_SE_CONN_INPUT_MASK7 0x570c +#define AFE_SE_CONN_OUTPUT_SEL0 0x5710 +#define AFE_SE_CONN_OUTPUT_SEL1 0x5714 +#define AFE_SE_CONN_OUTPUT_SEL2 0x5718 +#define AFE_SE_CONN_OUTPUT_SEL3 0x571c +#define AFE_SE_CONN_OUTPUT_SEL4 0x5720 +#define AFE_SE_CONN_OUTPUT_SEL5 0x5724 +#define AFE_SE_CONN_OUTPUT_SEL6 0x5728 +#define AFE_SE_CONN_OUTPUT_SEL7 0x572c +#define AFE_PCM0_INTF_CON1_MASK_MON 0x5730 +#define AFE_PCM0_INTF_CON0_MASK_MON 0x5734 +#define AFE_CONNSYS_I2S_CON_MASK_MON 0x5738 +#define AFE_TDM_CON2_MASK_MON 0x5744 +#define AFE_MTKAIF0_CFG0_MASK_MON 0x574c +#define AFE_MTKAIF1_CFG0_MASK_MON 0x5750 +#define AFE_ADDA_UL0_SRC_CON0_MASK_MON 0x5754 +#define AFE_ADDA_UL1_SRC_CON0_MASK_MON 0x5758 +#define AFE_ADDA_UL2_SRC_CON0_MASK_MON 0x575c +#define AFE_ASRC_NEW_CON0 0x7800 +#define AFE_ASRC_NEW_CON1 0x7804 +#define AFE_ASRC_NEW_CON2 0x7808 +#define AFE_ASRC_NEW_CON3 0x780c +#define AFE_ASRC_NEW_CON4 0x7810 +#define AFE_ASRC_NEW_CON5 0x7814 +#define AFE_ASRC_NEW_CON6 0x7818 +#define AFE_ASRC_NEW_CON7 0x781c +#define AFE_ASRC_NEW_CON8 0x7820 +#define AFE_ASRC_NEW_CON9 0x7824 +#define AFE_ASRC_NEW_CON10 0x7828 +#define AFE_ASRC_NEW_CON11 0x782c +#define AFE_ASRC_NEW_CON12 0x7830 +#define AFE_ASRC_NEW_CON13 0x7834 +#define AFE_ASRC_NEW_CON14 0x7838 +#define AFE_ASRC_NEW_IP_VERSION 0x783c +#define AFE_GASRC0_NEW_CON0 0x7840 +#define AFE_GASRC0_NEW_CON1 0x7844 +#define AFE_GASRC0_NEW_CON2 0x7848 +#define AFE_GASRC0_NEW_CON3 0x784c +#define AFE_GASRC0_NEW_CON4 0x7850 +#define AFE_GASRC0_NEW_CON5 0x7854 +#define AFE_GASRC0_NEW_CON6 0x7858 +#define AFE_GASRC0_NEW_CON7 0x785c +#define AFE_GASRC0_NEW_CON8 0x7860 +#define AFE_GASRC0_NEW_CON9 0x7864 +#define AFE_GASRC0_NEW_CON10 0x7868 +#define AFE_GASRC0_NEW_CON11 0x786c +#define AFE_GASRC0_NEW_CON12 0x7870 +#define AFE_GASRC0_NEW_CON13 0x7874 +#define AFE_GASRC0_NEW_CON14 0x7878 +#define AFE_GASRC0_NEW_IP_VERSION 0x787c +#define AFE_GASRC1_NEW_CON0 0x7880 +#define AFE_GASRC1_NEW_CON1 0x7884 +#define AFE_GASRC1_NEW_CON2 0x7888 +#define AFE_GASRC1_NEW_CON3 0x788c +#define AFE_GASRC1_NEW_CON4 0x7890 +#define AFE_GASRC1_NEW_CON5 0x7894 +#define AFE_GASRC1_NEW_CON6 0x7898 +#define AFE_GASRC1_NEW_CON7 0x789c +#define AFE_GASRC1_NEW_CON8 0x78a0 +#define AFE_GASRC1_NEW_CON9 0x78a4 +#define AFE_GASRC1_NEW_CON10 0x78a8 +#define AFE_GASRC1_NEW_CON11 0x78ac +#define AFE_GASRC1_NEW_CON12 0x78b0 +#define AFE_GASRC1_NEW_CON13 0x78b4 +#define AFE_GASRC1_NEW_CON14 0x78b8 +#define AFE_GASRC1_NEW_IP_VERSION 0x78bc +#define AFE_GASRC2_NEW_CON0 0x78c0 +#define AFE_GASRC2_NEW_CON1 0x78c4 +#define AFE_GASRC2_NEW_CON2 0x78c8 +#define AFE_GASRC2_NEW_CON3 0x78cc +#define AFE_GASRC2_NEW_CON4 0x78d0 +#define AFE_GASRC2_NEW_CON5 0x78d4 +#define AFE_GASRC2_NEW_CON6 0x78d8 +#define AFE_GASRC2_NEW_CON7 0x78dc +#define AFE_GASRC2_NEW_CON8 0x78e0 +#define AFE_GASRC2_NEW_CON9 0x78e4 +#define AFE_GASRC2_NEW_CON10 0x78e8 +#define AFE_GASRC2_NEW_CON11 0x78ec +#define AFE_GASRC2_NEW_CON12 0x78f0 +#define AFE_GASRC2_NEW_CON13 0x78f4 +#define AFE_GASRC2_NEW_CON14 0x78f8 +#define AFE_GASRC2_NEW_IP_VERSION 0x78fc +#define AFE_GASRC3_NEW_CON0 0x7900 +#define AFE_GASRC3_NEW_CON1 0x7904 +#define AFE_GASRC3_NEW_CON2 0x7908 +#define AFE_GASRC3_NEW_CON3 0x790c +#define AFE_GASRC3_NEW_CON4 0x7910 +#define AFE_GASRC3_NEW_CON5 0x7914 +#define AFE_GASRC3_NEW_CON6 0x7918 +#define AFE_GASRC3_NEW_CON7 0x791c +#define AFE_GASRC3_NEW_CON8 0x7920 +#define AFE_GASRC3_NEW_CON9 0x7924 +#define AFE_GASRC3_NEW_CON10 0x7928 +#define AFE_GASRC3_NEW_CON11 0x792c +#define AFE_GASRC3_NEW_CON12 0x7930 +#define AFE_GASRC3_NEW_CON13 0x7934 +#define AFE_GASRC3_NEW_CON14 0x7938 +#define AFE_GASRC3_NEW_IP_VERSION 0x793c +#define AFE_GASRC4_NEW_CON0 0x7940 +#define AFE_GASRC4_NEW_CON1 0x7944 +#define AFE_GASRC4_NEW_CON2 0x7948 +#define AFE_GASRC4_NEW_CON3 0x794c +#define AFE_GASRC4_NEW_CON4 0x7950 +#define AFE_GASRC4_NEW_CON5 0x7954 +#define AFE_GASRC4_NEW_CON6 0x7958 +#define AFE_GASRC4_NEW_CON7 0x795c +#define AFE_GASRC4_NEW_CON8 0x7960 +#define AFE_GASRC4_NEW_CON9 0x7964 +#define AFE_GASRC4_NEW_CON10 0x7968 +#define AFE_GASRC4_NEW_CON11 0x796c +#define AFE_GASRC4_NEW_CON12 0x7970 +#define AFE_GASRC4_NEW_CON13 0x7974 +#define AFE_GASRC4_NEW_CON14 0x7978 +#define AFE_GASRC4_NEW_IP_VERSION 0x797c +#define AFE_GASRC5_NEW_CON0 0x7980 +#define AFE_GASRC5_NEW_CON1 0x7984 +#define AFE_GASRC5_NEW_CON2 0x7988 +#define AFE_GASRC5_NEW_CON3 0x798c +#define AFE_GASRC5_NEW_CON4 0x7990 +#define AFE_GASRC5_NEW_CON5 0x7994 +#define AFE_GASRC5_NEW_CON6 0x7998 +#define AFE_GASRC5_NEW_CON7 0x799c +#define AFE_GASRC5_NEW_CON8 0x79a0 +#define AFE_GASRC5_NEW_CON9 0x79a4 +#define AFE_GASRC5_NEW_CON10 0x79a8 +#define AFE_GASRC5_NEW_CON11 0x79ac +#define AFE_GASRC5_NEW_CON12 0x79b0 +#define AFE_GASRC5_NEW_CON13 0x79b4 +#define AFE_GASRC5_NEW_CON14 0x79b8 +#define AFE_GASRC5_NEW_IP_VERSION 0x79bc +#define AFE_GASRC6_NEW_CON0 0x79c0 +#define AFE_GASRC6_NEW_CON1 0x79c4 +#define AFE_GASRC6_NEW_CON2 0x79c8 +#define AFE_GASRC6_NEW_CON3 0x79cc +#define AFE_GASRC6_NEW_CON4 0x79d0 +#define AFE_GASRC6_NEW_CON5 0x79d4 +#define AFE_GASRC6_NEW_CON6 0x79d8 +#define AFE_GASRC6_NEW_CON7 0x79dc +#define AFE_GASRC6_NEW_CON8 0x79e0 +#define AFE_GASRC6_NEW_CON9 0x79e4 +#define AFE_GASRC6_NEW_CON10 0x79e8 +#define AFE_GASRC6_NEW_CON11 0x79ec +#define AFE_GASRC6_NEW_CON12 0x79f0 +#define AFE_GASRC6_NEW_CON13 0x79f4 +#define AFE_GASRC6_NEW_CON14 0x79f8 +#define AFE_GASRC6_NEW_IP_VERSION 0x79fc +#define AFE_GASRC7_NEW_CON0 0x7a00 +#define AFE_GASRC7_NEW_CON1 0x7a04 +#define AFE_GASRC7_NEW_CON2 0x7a08 +#define AFE_GASRC7_NEW_CON3 0x7a0c +#define AFE_GASRC7_NEW_CON4 0x7a10 +#define AFE_GASRC7_NEW_CON5 0x7a14 +#define AFE_GASRC7_NEW_CON6 0x7a18 +#define AFE_GASRC7_NEW_CON7 0x7a1c +#define AFE_GASRC7_NEW_CON8 0x7a20 +#define AFE_GASRC7_NEW_CON9 0x7a24 +#define AFE_GASRC7_NEW_CON10 0x7a28 +#define AFE_GASRC7_NEW_CON11 0x7a2c +#define AFE_GASRC7_NEW_CON12 0x7a30 +#define AFE_GASRC7_NEW_CON13 0x7a34 +#define AFE_GASRC7_NEW_CON14 0x7a38 +#define AFE_GASRC7_NEW_IP_VERSION 0x7a3c +#define AFE_GASRC8_NEW_CON0 0x7a40 +#define AFE_GASRC8_NEW_CON1 0x7a44 +#define AFE_GASRC8_NEW_CON2 0x7a48 +#define AFE_GASRC8_NEW_CON3 0x7a4c +#define AFE_GASRC8_NEW_CON4 0x7a50 +#define AFE_GASRC8_NEW_CON5 0x7a54 +#define AFE_GASRC8_NEW_CON6 0x7a58 +#define AFE_GASRC8_NEW_CON7 0x7a5c +#define AFE_GASRC8_NEW_CON8 0x7a60 +#define AFE_GASRC8_NEW_CON9 0x7a64 +#define AFE_GASRC8_NEW_CON10 0x7a68 +#define AFE_GASRC8_NEW_CON11 0x7a6c +#define AFE_GASRC8_NEW_CON12 0x7a70 +#define AFE_GASRC8_NEW_CON13 0x7a74 +#define AFE_GASRC8_NEW_CON14 0x7a78 +#define AFE_GASRC8_NEW_IP_VERSION 0x7a7c +#define AFE_GASRC9_NEW_CON0 0x7a80 +#define AFE_GASRC9_NEW_CON1 0x7a84 +#define AFE_GASRC9_NEW_CON2 0x7a88 +#define AFE_GASRC9_NEW_CON3 0x7a8c +#define AFE_GASRC9_NEW_CON4 0x7a90 +#define AFE_GASRC9_NEW_CON5 0x7a94 +#define AFE_GASRC9_NEW_CON6 0x7a98 +#define AFE_GASRC9_NEW_CON7 0x7a9c +#define AFE_GASRC9_NEW_CON8 0x7aa0 +#define AFE_GASRC9_NEW_CON9 0x7aa4 +#define AFE_GASRC9_NEW_CON10 0x7aa8 +#define AFE_GASRC9_NEW_CON11 0x7aac +#define AFE_GASRC9_NEW_CON12 0x7ab0 +#define AFE_GASRC9_NEW_CON13 0x7ab4 +#define AFE_GASRC9_NEW_CON14 0x7ab8 +#define AFE_GASRC9_NEW_IP_VERSION 0x7abc +#define AFE_GASRC10_NEW_CON0 0x7ac0 +#define AFE_GASRC10_NEW_CON1 0x7ac4 +#define AFE_GASRC10_NEW_CON2 0x7ac8 +#define AFE_GASRC10_NEW_CON3 0x7acc +#define AFE_GASRC10_NEW_CON4 0x7ad0 +#define AFE_GASRC10_NEW_CON5 0x7ad4 +#define AFE_GASRC10_NEW_CON6 0x7ad8 +#define AFE_GASRC10_NEW_CON7 0x7adc +#define AFE_GASRC10_NEW_CON8 0x7ae0 +#define AFE_GASRC10_NEW_CON9 0x7ae4 +#define AFE_GASRC10_NEW_CON10 0x7ae8 +#define AFE_GASRC10_NEW_CON11 0x7aec +#define AFE_GASRC10_NEW_CON12 0x7af0 +#define AFE_GASRC10_NEW_CON13 0x7af4 +#define AFE_GASRC10_NEW_CON14 0x7af8 +#define AFE_GASRC10_NEW_IP_VERSION 0x7afc +#define AFE_GASRC11_NEW_CON0 0x7b00 +#define AFE_GASRC11_NEW_CON1 0x7b04 +#define AFE_GASRC11_NEW_CON2 0x7b08 +#define AFE_GASRC11_NEW_CON3 0x7b0c +#define AFE_GASRC11_NEW_CON4 0x7b10 +#define AFE_GASRC11_NEW_CON5 0x7b14 +#define AFE_GASRC11_NEW_CON6 0x7b18 +#define AFE_GASRC11_NEW_CON7 0x7b1c +#define AFE_GASRC11_NEW_CON8 0x7b20 +#define AFE_GASRC11_NEW_CON9 0x7b24 +#define AFE_GASRC11_NEW_CON10 0x7b28 +#define AFE_GASRC11_NEW_CON11 0x7b2c +#define AFE_GASRC11_NEW_CON12 0x7b30 +#define AFE_GASRC11_NEW_CON13 0x7b34 +#define AFE_GASRC11_NEW_CON14 0x7b38 +#define AFE_GASRC11_NEW_IP_VERSION 0x7b3c +#define AFE_GASRC12_NEW_CON0 0x7b40 +#define AFE_GASRC12_NEW_CON1 0x7b44 +#define AFE_GASRC12_NEW_CON2 0x7b48 +#define AFE_GASRC12_NEW_CON3 0x7b4c +#define AFE_GASRC12_NEW_CON4 0x7b50 +#define AFE_GASRC12_NEW_CON5 0x7b54 +#define AFE_GASRC12_NEW_CON6 0x7b58 +#define AFE_GASRC12_NEW_CON7 0x7b5c +#define AFE_GASRC12_NEW_CON8 0x7b60 +#define AFE_GASRC12_NEW_CON9 0x7b64 +#define AFE_GASRC12_NEW_CON10 0x7b68 +#define AFE_GASRC12_NEW_CON11 0x7b6c +#define AFE_GASRC12_NEW_CON12 0x7b70 +#define AFE_GASRC12_NEW_CON13 0x7b74 +#define AFE_GASRC12_NEW_CON14 0x7b78 +#define AFE_GASRC12_NEW_IP_VERSION 0x7b7c +#define AFE_GASRC13_NEW_CON0 0x7b80 +#define AFE_GASRC13_NEW_CON1 0x7b84 +#define AFE_GASRC13_NEW_CON2 0x7b88 +#define AFE_GASRC13_NEW_CON3 0x7b8c +#define AFE_GASRC13_NEW_CON4 0x7b90 +#define AFE_GASRC13_NEW_CON5 0x7b94 +#define AFE_GASRC13_NEW_CON6 0x7b98 +#define AFE_GASRC13_NEW_CON7 0x7b9c +#define AFE_GASRC13_NEW_CON8 0x7ba0 +#define AFE_GASRC13_NEW_CON9 0x7ba4 +#define AFE_GASRC13_NEW_CON10 0x7ba8 +#define AFE_GASRC13_NEW_CON11 0x7bac +#define AFE_GASRC13_NEW_CON12 0x7bb0 +#define AFE_GASRC13_NEW_CON13 0x7bb4 +#define AFE_GASRC13_NEW_CON14 0x7bb8 +#define AFE_GASRC13_NEW_IP_VERSION 0x7bbc +#define AFE_GASRC14_NEW_CON0 0x7bc0 +#define AFE_GASRC14_NEW_CON1 0x7bc4 +#define AFE_GASRC14_NEW_CON2 0x7bc8 +#define AFE_GASRC14_NEW_CON3 0x7bcc +#define AFE_GASRC14_NEW_CON4 0x7bd0 +#define AFE_GASRC14_NEW_CON5 0x7bd4 +#define AFE_GASRC14_NEW_CON6 0x7bd8 +#define AFE_GASRC14_NEW_CON7 0x7bdc +#define AFE_GASRC14_NEW_CON8 0x7be0 +#define AFE_GASRC14_NEW_CON9 0x7be4 +#define AFE_GASRC14_NEW_CON10 0x7be8 +#define AFE_GASRC14_NEW_CON11 0x7bec +#define AFE_GASRC14_NEW_CON12 0x7bf0 +#define AFE_GASRC14_NEW_CON13 0x7bf4 +#define AFE_GASRC14_NEW_CON14 0x7bf8 +#define AFE_GASRC14_NEW_IP_VERSION 0x7bfc +#define AFE_GASRC15_NEW_CON0 0x7c00 +#define AFE_GASRC15_NEW_CON1 0x7c04 +#define AFE_GASRC15_NEW_CON2 0x7c08 +#define AFE_GASRC15_NEW_CON3 0x7c0c +#define AFE_GASRC15_NEW_CON4 0x7c10 +#define AFE_GASRC15_NEW_CON5 0x7c14 +#define AFE_GASRC15_NEW_CON6 0x7c18 +#define AFE_GASRC15_NEW_CON7 0x7c1c +#define AFE_GASRC15_NEW_CON8 0x7c20 +#define AFE_GASRC15_NEW_CON9 0x7c24 +#define AFE_GASRC15_NEW_CON10 0x7c28 +#define AFE_GASRC15_NEW_CON11 0x7c2c +#define AFE_GASRC15_NEW_CON12 0x7c30 +#define AFE_GASRC15_NEW_CON13 0x7c34 +#define AFE_GASRC15_NEW_CON14 0x7c38 +#define AFE_GASRC15_NEW_IP_VERSION 0x7c3c + +#define AFE_MAX_REGISTER AFE_GASRC15_NEW_IP_VERSION + +#define AFE_IRQ_STATUS_BITS 0x87FFFFFF +#define AFE_IRQ_CNT_SHIFT 0 +#define AFE_IRQ_CNT_MASK 0xffffff +#endif diff --git a/src/platform/mt8196/include/platform/platform.h b/src/platform/mt8196/include/platform/platform.h new file mode 100644 index 000000000000..60becc79ded7 --- /dev/null +++ b/src/platform/mt8196/include/platform/platform.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) +#define LPSRAM_SIZE 16384 + +/* IPC Interrupt */ +#define PLATFORM_IPC_INTERRUPT MTK_DSP_IRQ_MAILBOX +#define PLATFORM_IPC_INTERRUPT_NAME NULL + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ MTK_DSP_IRQ_SW +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#define SRAM_REG_FW_STATUS 0x4 + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + trigger_irq_to_host_req(); +} + +/** + * \brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/mt8196/include/platform/trace/trace.h b/src/platform/mt8196/include/platform/trace/trace.h new file mode 100644 index 000000000000..ede2259cf192 --- /dev/null +++ b/src/platform/mt8196/include/platform/trace/trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/io.h> +#include <platform/drivers/mt_reg_base.h> + +#define platform_trace_point(__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/mt8196/lib/CMakeLists.txt b/src/platform/mt8196/lib/CMakeLists.txt new file mode 100644 index 000000000000..ef71f8eea6cd --- /dev/null +++ b/src/platform/mt8196/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dma.c + memory.c + dai.c +) diff --git a/src/platform/mt8196/lib/clk.c b/src/platform/mt8196/lib/clk.c new file mode 100644 index 000000000000..69af725dec73 --- /dev/null +++ b/src/platform/mt8196/lib/clk.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <platform/drivers/mt_reg_base.h> +#include <rtos/clk.h> +#include <rtos/wait.h> +#include <sof/common.h> +#include <sof/lib/cpu.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <rtos/sof.h> +#include <sof/trace/trace.h> + +SOF_DEFINE_REG_UUID(clkdrv_mt8196); + +DECLARE_TR_CTX(clkdrv_tr, SOF_UUID(clkdrv_mt8196_uuid), LOG_LEVEL_INFO); + +/* default voltage is 0.75V */ +const struct freq_table platform_cpu_freq[] = { + { 26000000, 26000}, + { 800000000, 26000}, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +void platform_clock_init(struct sof *sof) +{ + int i; + + tr_dbg(&clkdrv_tr, "clock init\n"); + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + /* When the system is in an active state, the DSP clock operates at 800MHz (0.75V). + * In a low power scenario, the DSP enters WFI state, and the clock reduces to 26MHz. + * The clock selection is controlled by the host, and we do not allow SOF to change + * the ADSP frequency. + */ + 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/mt8196/lib/dai.c b/src/platform/mt8196/lib/dai.c new file mode 100755 index 000000000000..6f5300e6aa48 --- /dev/null +++ b/src/platform/mt8196/lib/dai.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Darren Ye <darren.ye@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <sof/lib/uuid.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> +#include <sof/drivers/afe-dai.h> +#include <mt8196-afe-common.h> + +static int afe_dai_handshake[MT8196_DAI_NUM] = { + AFE_HANDSHAKE(MT8196_DAI_I2S_OUT4, MT8196_IRQ_12, MT8196_MEMIF_DL_24CH), + AFE_HANDSHAKE(MT8196_DAI_I2S_OUT6, MT8196_IRQ_1, MT8196_MEMIF_DL1), + AFE_HANDSHAKE(MT8196_DAI_AP_DMIC, MT8196_IRQ_13, MT8196_MEMIF_UL0), + AFE_HANDSHAKE(MT8196_DAI_I2S_IN6, MT8196_IRQ_0, MT8196_MEMIF_UL1), + AFE_HANDSHAKE(MT8196_DAI_AP_DMIC_CH34, MT8196_IRQ_15, MT8196_MEMIF_UL2), +}; + +static SHARED_DATA struct dai afe_dai[MT8196_DAI_NUM]; + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_MEDIATEK_AFE, + .dai_array = afe_dai, + .num_dais = ARRAY_SIZE(afe_dai), + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti), +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(afe_dai); i++) { + k_spinlock_init(&afe_dai[i].lock); + afe_dai[i].index = AFE_HS_GET_DAI(afe_dai_handshake[i]); + afe_dai[i].drv = &afe_dai_driver; + /* TODO, fifo[0] change to target playback or capture */ + afe_dai[i].plat_data.fifo[0].handshake = afe_dai_handshake[i]; + } + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/mt8196/lib/dma.c b/src/platform/mt8196/lib/dma.c new file mode 100644 index 000000000000..0cc4e1043a26 --- /dev/null +++ b/src/platform/mt8196/lib/dma.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + * Darren Ye <darren.ye@mediatek.com> + */ + +#include <rtos/interrupt.h> +#include <rtos/spinlock.h> +#include <sof/common.h> +#include <sof/drivers/afe-memif.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <mt8196-afe-reg.h> +#include <mt8196-afe-common.h> + +extern const struct dma_ops dummy_dma_ops; + +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .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, +}, +{ + .plat_data = { + .id = DMA_ID_AFE_MEMIF, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_AFE_MEMIF, + .base = AFE_BASE_ADDR, + .channels = MT8196_MEMIF_NUM, + }, + .ops = &memif_ops, +}, + +}; + +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)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/mt8196/lib/memory.c b/src/platform/mt8196/lib/memory.c new file mode 100644 index 000000000000..dca28790d741 --- /dev/null +++ b/src/platform/mt8196/lib/memory.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + */ + +#include <ipc/topology.h> +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; +static SHARED_DATA struct block_hdr mod_block4096[HEAP_RT_COUNT4096]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), + BLOCK_DEF(4096, HEAP_RT_COUNT4096, mod_block4096), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/mt8196/mt8196.x.in b/src/platform/mt8196/mt8196.x.in new file mode 100644 index 000000000000..939779d8f120 --- /dev/null +++ b/src/platform/mt8196/mt8196.x.in @@ -0,0 +1,554 @@ +/* + * Linker Script for mt8196 MediaTek + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +#if CONFIG_MEDIATEK_DRAM_IMAGE +#define IMAGE_LOC sof_dram +#else +#define IMAGE_LOC sof_sram +#endif + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int5_lit : + org = XCHAL_INTLEVEL5_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int5_text : + org = XCHAL_INTLEVEL5_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_sram : + org = SRAM_START, + len = SRAM_SIZE + sof_dram : + org = SOF_DRAM_BASE, + len = SOF_DRAM_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_int5_text_phdr PT_LOAD; + vector_int5_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_sram_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000404; +_memmap_cacheattr_wt_base = 0x00000404; +_memmap_cacheattr_bp_base = 0x00000404; +_memmap_cacheattr_unused_mask = 0xFFFFF0FF; +_memmap_cacheattr_wb_trapnull = 0x44444444; +_memmap_cacheattr_wba_trapnull = 0x44444444; +_memmap_cacheattr_wbna_trapnull = 0x44444444; +_memmap_cacheattr_wt_trapnull = 0x44444444; +_memmap_cacheattr_bp_trapnull = 0x44444444; +_memmap_cacheattr_wb_strict = 0x00000404; +_memmap_cacheattr_wt_strict = 0x00000404; +_memmap_cacheattr_bp_strict = 0x00000404; +_memmap_cacheattr_wb_allvalid = 0x44444444; +_memmap_cacheattr_wt_allvalid = 0x44444444; +_memmap_cacheattr_bp_allvalid = 0x44444444; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .Level4InterruptVector.literal : ALIGN(4) + { + _Level4InterruptVector_literal_start = ABSOLUTE(.); + *(.Level4InterruptVector.literal) + _Level4InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .Level4InterruptVector.text : ALIGN(4) + { + _Level4InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level4InterruptVector.text)) + _Level4InterruptVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .NMIExceptionVector.literal : ALIGN(4) + { + _NMIExceptionVector_literal_start = ABSOLUTE(.); + *(.NMIExceptionVector.literal) + _NMIExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int5_lit :vector_int5_lit_phdr + + .NMIExceptionVector.text : ALIGN(4) + { + _NMIExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.NMIExceptionVector.text)) + _NMIExceptionVector_text_end = ABSOLUTE(.); + } >vector_int5_text :vector_int5_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + KEEP (*(.fw_ready_metadata)) + } >IMAGE_LOC :sof_sram_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >IMAGE_LOC :sof_sram_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >IMAGE_LOC :sof_sram_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_ranges 0 : { *(.debug_ranges) } + .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.*)) + } + + .xtensa.info 0 : + { + *(.xtensa.info) + } + + .comment 0 : + { + KEEP(*(.comment)) + } + + .note.GNU-stack 0 : + { + *(.note.GNU-stack) + } + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr +} diff --git a/src/platform/mt8196/platform.c b/src/platform/mt8196/platform.c new file mode 100644 index 000000000000..fc7cd9a7eb34 --- /dev/null +++ b/src/platform/mt8196/platform.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Hailong Fan <hailong.fan@mediatek.com> + * Darren Ye <darren.ye@mediatek.com> + */ + +#include <errno.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <platform/drivers/timer.h> +#include <rtos/clk.h> +#include <rtos/timer.h> +#include <rtos/interrupt.h> +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <sof/drivers/edma.h> +#include <sof/ipc/msg.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <sof_versions.h> +#include <stdint.h> +#include <xtensa/hal.h> + +struct sof; + +static const struct sof_ipc_fw_ready ready + __section(".fw_ready") = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_MTK_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_MTK_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + } +}; + +static SHARED_DATA struct timer timer_shared = { + .id = OSTIMER0, + .irq = MTK_DSP_IRQ_OSTIMER32_C0, +}; + +/* Override the default MPU setup. This table matches the memory map + * of the 'sample_controller' core and will need to be modified for + * other cores. + * NOTE: This table sets up all of external memory as shared uncached. + * For best results, edit the LSP memory map to create a separate + * section in shared memory, place all sections that need to be uncached + * into that section, and only map that section uncached. See README + * for more details. + */ +const struct xthal_MPU_entry __xt_mpu_init_table[] __section(".ResetVector.text") = { + XTHAL_MPU_ENTRY(0x00000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // infra + XTHAL_MPU_ENTRY(0x10000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // infra + XTHAL_MPU_ENTRY(0x1a000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // cfg + XTHAL_MPU_ENTRY(0x1a110000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // audio + XTHAL_MPU_ENTRY(0x4e100000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // sram + XTHAL_MPU_ENTRY(0x4e180000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused + XTHAL_MPU_ENTRY(0x90000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // dram + XTHAL_MPU_ENTRY(0x90500000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_NON_CACHEABLE), // dram + XTHAL_MPU_ENTRY(0x90900000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused +}; + +const unsigned int __xt_mpu_init_table_size __section(".ResetVector.text") = + ARRAY_SIZE(__xt_mpu_init_table); + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + /* now interrupt host to tell it we are done booting */ + trigger_irq_to_host_req(); + + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + sof->platform_timer = platform_shared_get(&timer_shared, sizeof(timer_shared)); + sof->cpu_timers = sof->platform_timer; + platform_interrupt_init(); + platform_clock_init(sof); + + scheduler_init_edf(); + + /* init low latency domains and schedulers */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + platform_timer_start(sof->platform_timer); + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* Init platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], 1, + PLATFORM_DEFAULT_CLOCK, false); + + scheduler_init_ll(sof->platform_dma_domain); + + /* initialize the host IPC mechanisms */ + ipc_init(sof); + + ret = dai_init(sof); + if (ret < 0) + return ret; + +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + dma_trace_init_complete(sof->dmat); +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} + diff --git a/src/platform/mt8365/CMakeLists.txt b/src/platform/mt8365/CMakeLists.txt new file mode 100644 index 000000000000..4091be2eeaff --- /dev/null +++ b/src/platform/mt8365/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) + +add_local_sources(sof platform.c afe-platform.c) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8365/include/arch) +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/mt8365/include/platform) diff --git a/src/platform/mt8365/afe-platform.c b/src/platform/mt8365/afe-platform.c new file mode 100644 index 000000000000..1255972479ce --- /dev/null +++ b/src/platform/mt8365/afe-platform.c @@ -0,0 +1,336 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <sof/common.h> +#include <errno.h> +#include <sof/drivers/afe-drv.h> +#include <mt8365-afe-regs.h> +#include <mt8365-afe-common.h> + +/* + * AFE: Audio Front-End + * + * frontend (memif): + * memory interface + * AWB, VULx, TDM_IN (uplink for capture) + * DLx, TDM_OUT (downlink for playback) + * backend: + * TDM In + * TMD out + * DMIC + * GASRC + * etc. + * interconn: + * inter-connection, + * connect frontends and backends as DSP path + */ + +static const struct mtk_base_memif_data memif_data[MT8365_MEMIF_NUM] = { + [MT8365_MEMIF_DL1] = { + .name = "DL1", + .id = MT8365_MEMIF_DL1, + .reg_ofs_base = AFE_DL1_BASE, + .reg_ofs_cur = AFE_DL1_CUR, + .reg_ofs_end = AFE_DL1_END, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 0, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 21, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 1, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 16, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = -1, + .msb_shift = 0, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_DL2] = { + .name = "DL2", + .id = MT8365_MEMIF_DL2, + .reg_ofs_base = AFE_DL2_BASE, + .reg_ofs_cur = AFE_DL2_CUR, + .reg_ofs_end = AFE_DL2_END, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 4, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 22, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 2, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 18, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = -1, + .msb_shift = 0, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_TDM_OUT] = { + .name = "TDM_OUT", + .id = MT8365_MEMIF_DL2, + .reg_ofs_base = AFE_HDMI_OUT_BASE, + .reg_ofs_cur = AFE_HDMI_OUT_CUR, + .reg_ofs_end = AFE_HDMI_OUT_END, + .fs_reg = -1, + .fs_shift = 0, + .fs_maskbit = 0, + .mono_reg = -1, + .mono_shift = 0, + .enable_reg = AFE_HDMI_OUT_CON0, + .enable_shift = 0, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 28, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = -1, + .msb_shift = 0, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_AWB] = { + .name = "AWB", + .id = MT8365_MEMIF_AWB, + .reg_ofs_base = AFE_AWB_BASE, + .reg_ofs_cur = AFE_AWB_CUR, + .reg_ofs_end = AFE_AWB_END, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 12, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 24, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 6, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 20, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 17, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_VUL] = { + .name = "VUL", + .id = MT8365_MEMIF_VUL, + .reg_ofs_base = AFE_VUL_BASE, + .reg_ofs_cur = AFE_VUL_CUR, + .reg_ofs_end = AFE_VUL_END, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 16, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 27, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 3, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 22, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 20, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_VUL2] = { + .name = "VUL2", + .id = MT8365_MEMIF_VUL2, + .reg_ofs_base = AFE_VUL_D2_BASE, + .reg_ofs_cur = AFE_VUL_D2_CUR, + .reg_ofs_end = AFE_VUL_D2_END, + .fs_reg = AFE_DAC_CON0, + .fs_shift = 20, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON0, + .mono_shift = 10, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 9, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 14, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 21, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_VUL3] = { + .name = "VUL3", + .id = MT8365_MEMIF_VUL3, + .reg_ofs_base = AFE_VUL3_BASE, + .reg_ofs_cur = AFE_VUL3_CUR, + .reg_ofs_end = AFE_VUL3_END, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 8, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON0, + .mono_shift = 13, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 12, + .hd_reg = AFE_MEMIF_PBUF2_SIZE, + .hd_shift = 10, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 27, + .msb2_reg = -1, + .msb2_shift = 0, + }, + [MT8365_MEMIF_TDM_IN] = { + .name = "TDM_IN", + .id = MT8365_MEMIF_TDM_IN, + .reg_ofs_base = AFE_HDMI_IN_2CH_BASE, + .reg_ofs_cur = AFE_HDMI_IN_2CH_CUR, + .reg_ofs_end = AFE_HDMI_IN_2CH_END, + .fs_reg = -1, + .fs_shift = 0, + .fs_maskbit = 0, + .mono_reg = AFE_HDMI_IN_2CH_CON0, + .mono_shift = 1, + .enable_reg = AFE_HDMI_IN_2CH_CON0, + .enable_shift = 0, + .hd_reg = AFE_MEMIF_PBUF2_SIZE, + .hd_shift = 8, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .ch_num_reg = -1, + .ch_num_shift = 0, + .ch_num_maskbit = 0, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 28, + .msb2_reg = -1, + .msb2_shift = 0, + }, +}; + +struct mt8365_afe_rate { + unsigned int rate; + unsigned int reg_value; +}; + +static const struct mt8365_afe_rate mt8365_afe_rates[] = { + { + .rate = 8000, + .reg_value = 0, + }, + { + .rate = 11025, + .reg_value = 1, + }, + { + .rate = 12000, + .reg_value = 2, + }, + { + .rate = 16000, + .reg_value = 4, + }, + { + .rate = 22050, + .reg_value = 5, + }, + { + .rate = 24000, + .reg_value = 6, + }, + { + .rate = 32000, + .reg_value = 8, + }, + { + .rate = 44100, + .reg_value = 9, + }, + { + .rate = 48000, + .reg_value = 10, + }, + { + .rate = 88200, + .reg_value = 11, + }, + { + .rate = 96000, + .reg_value = 12, + }, + { + .rate = 176400, + .reg_value = 13, + }, + { + .rate = 192000, + .reg_value = 14, + }, +}; + +static unsigned int mt8365_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8365_afe_rates); i++) + if (mt8365_afe_rates[i].rate == rate) + return mt8365_afe_rates[i].reg_value; + + return -EINVAL; +} + +static unsigned int mt8365_afe_fs(unsigned int rate, int aud_blk) +{ + return mt8365_afe_fs_timing(rate); +} + +static unsigned int mt8365_afe2adsp_addr(unsigned int addr) +{ + /*TODO : Need apply the address remap */ + return addr; +} + +static unsigned int mt8365_adsp2afe_addr(unsigned int addr) +{ + /* TODO : Need apply the address remap */ + return addr; +} + +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = AFE_REG_BASE, + .memif_datas = memif_data, + .memif_size = MT8365_MEMIF_NUM, + .memif_dl_num = MT8365_MEMIF_DL_NUM, + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = MT8365_DAI_NUM, + .afe2adsp_addr = mt8365_afe2adsp_addr, + .adsp2afe_addr = mt8365_adsp2afe_addr, + .afe_fs = mt8365_afe_fs, + .irq_fs = mt8365_afe_fs_timing, +}; diff --git a/src/platform/mt8365/include/arch/xtensa/config/core-isa.h b/src/platform/mt8365/include/arch/xtensa/config/core-isa.h new file mode 100644 index 000000000000..b8efd6318c50 --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/core-isa.h @@ -0,0 +1,649 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See <xtensa/config/core.h>, which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Customer ID=13943; Build=0x75f5e; Copyright (c) 1999-2018 Tensilica 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. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 11 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 0 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_EXCLUSIVE 1 /* L32EX/S32EX instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5 0 /* HiFi5 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI5_VFPU 0 /* HiFi5 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI4 1 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 1 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 1 /* user SP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 0 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ + +#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ +#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ +#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ +#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ +#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ +#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ + +#define XCHAL_HAVE_PDX 0 /* PDX */ +#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ +#define XCHAL_HAVE_PDX4 0 /* PDX4 */ +#define XCHAL_HAVE_PDX8 0 /* PDX8 */ +#define XCHAL_HAVE_PDX16 0 /* PDX16 */ + +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + +#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ +#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ +#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ +#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ +#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ +#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ + +#define XCHAL_HAVE_VISIONC 0 /* Vision C */ + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 2 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 32 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 16 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 1200009 /* sw version of this header */ + +#define XCHAL_CORE_ID "hifi4_Aquila_E2_PROD" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x00075F5E /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC0F3FBFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x22475F5E /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX7.0.9" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2700 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 9 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 270009 /* major*100+minor */ +#define XCHAL_HW_REL_LX7 1 +#define XCHAL_HW_REL_LX7_0 1 +#define XCHAL_HW_REL_LX7_0_9 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2700 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 9 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 270009 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2700 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 9 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 270009 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 128 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 128 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 7 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 7 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 32768 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 32768 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 1 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 16 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ + +#define XCHAL_HAVE_AXI 1 /* AXI bus */ +#define XCHAL_HAVE_AXI_ECC 1 /* ECC on AXI bus */ +#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 1 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 6 +#define XCHAL_DCACHE_SETWIDTH 6 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS 4 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 1 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 16 +#define XCHAL_DCACHE_ACCESS_SIZE 8 + +#define XCHAL_DCACHE_BANKS 2 /* number of banks */ + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x40000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x40000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 65536 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM0 1 +#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x40010000 /* virtual address */ +#define XCHAL_INSTRAM1_PADDR 0x40010000 /* physical address */ +#define XCHAL_INSTRAM1_SIZE 65536 /* size in bytes */ +#define XCHAL_INSTRAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_HAVE_INSTRAM1 1 +#define XCHAL_INSTRAM1_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x1E000000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x1E000000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 262144 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM0 1 +#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ + +/* Data RAM 1: */ +#define XCHAL_DATARAM1_VADDR 0x1E040000 /* virtual address */ +#define XCHAL_DATARAM1_PADDR 0x1E040000 /* physical address */ +#define XCHAL_DATARAM1_SIZE 262144 /* size in bytes */ +#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM1_BANKS 2 /* number of banks */ +#define XCHAL_HAVE_DATARAM1 1 +#define XCHAL_DATARAM1_HAVE_IDMA 0 /* idma supported by this local memory */ + +#define XCHAL_HAVE_IDMA 0 +#define XCHAL_HAVE_IDMA_TRANSPOSE 0 + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 0 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 25 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 18 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 2 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x00B900FF +#define XCHAL_INTLEVEL2_MASK 0x0142FF00 +#define XCHAL_INTLEVEL3_MASK 0x00040000 +#define XCHAL_INTLEVEL4_MASK 0x00000000 +#define XCHAL_INTLEVEL5_MASK 0x00000000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x00B900FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x01FBFFFF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x01FFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x01FFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 2 +#define XCHAL_INT9_LEVEL 2 +#define XCHAL_INT10_LEVEL 2 +#define XCHAL_INT11_LEVEL 2 +#define XCHAL_INT12_LEVEL 2 +#define XCHAL_INT13_LEVEL 2 +#define XCHAL_INT14_LEVEL 2 +#define XCHAL_INT15_LEVEL 2 +#define XCHAL_INT16_LEVEL 1 +#define XCHAL_INT17_LEVEL 2 +#define XCHAL_INT18_LEVEL 3 +#define XCHAL_INT19_LEVEL 1 +#define XCHAL_INT20_LEVEL 1 +#define XCHAL_INT21_LEVEL 1 +#define XCHAL_INT22_LEVEL 2 +#define XCHAL_INT23_LEVEL 1 +#define XCHAL_INT24_LEVEL 2 +#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_WRITE_ERROR +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFE000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00600000 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x0000C0C0 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x01803F3F +#define XCHAL_INTTYPE_MASK_TIMER 0x00070000 +#define XCHAL_INTTYPE_MASK_NMI 0x00000000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00080000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00100000 +#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 +#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 +#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 16 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 17 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 18 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_WRITE_ERROR_INTERRUPT 19 +#define XCHAL_PROFILING_INTERRUPT 20 + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL3_NUM 18 +/* (There are many interrupts each at level(s) 1, 2.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */ +#define XCHAL_EXTINT9_NUM 9 /* (intlevel 2) */ +#define XCHAL_EXTINT10_NUM 10 /* (intlevel 2) */ +#define XCHAL_EXTINT11_NUM 11 /* (intlevel 2) */ +#define XCHAL_EXTINT12_NUM 12 /* (intlevel 2) */ +#define XCHAL_EXTINT13_NUM 13 /* (intlevel 2) */ +#define XCHAL_EXTINT14_NUM 14 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 15 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 23 /* (intlevel 1) */ +#define XCHAL_EXTINT17_NUM 24 /* (intlevel 2) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT6_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT7_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 8 /* (intlevel 2) */ +#define XCHAL_INT9_EXTNUM 9 /* (intlevel 2) */ +#define XCHAL_INT10_EXTNUM 10 /* (intlevel 2) */ +#define XCHAL_INT11_EXTNUM 11 /* (intlevel 2) */ +#define XCHAL_INT12_EXTNUM 12 /* (intlevel 2) */ +#define XCHAL_INT13_EXTNUM 13 /* (intlevel 2) */ +#define XCHAL_INT14_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT15_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT23_EXTNUM 16 /* (intlevel 1) */ +#define XCHAL_INT24_EXTNUM 17 /* (intlevel 2) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x40020400 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x40020400 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x40020000 +#define XCHAL_RESET_VECTOR0_PADDR 0x40020000 +#define XCHAL_RESET_VECTOR1_VADDR 0x40000640 +#define XCHAL_RESET_VECTOR1_PADDR 0x40000640 +#define XCHAL_RESET_VECTOR_VADDR 0x40000640 +#define XCHAL_RESET_VECTOR_PADDR 0x40000640 +#define XCHAL_USER_VECOFS 0x000001FC +#define XCHAL_USER_VECTOR_VADDR 0x400205FC +#define XCHAL_USER_VECTOR_PADDR 0x400205FC +#define XCHAL_KERNEL_VECOFS 0x000001DC +#define XCHAL_KERNEL_VECTOR_VADDR 0x400205DC +#define XCHAL_KERNEL_VECTOR_PADDR 0x400205DC +#define XCHAL_DOUBLEEXC_VECOFS 0x0000021C +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x4002061C +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x4002061C +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x40020400 +#define XCHAL_WINDOW_VECTORS_PADDR 0x40020400 +#define XCHAL_INTLEVEL2_VECOFS 0x0000017C +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x4002057C +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x4002057C +#define XCHAL_INTLEVEL3_VECOFS 0x0000019C +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x4002059C +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x4002059C +#define XCHAL_INTLEVEL4_VECOFS 0x000001BC +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x400205BC +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x400205BC +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL4_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 262144 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 8 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 0 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 0 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ + +/* If none of the above last 5 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ +#define XCHAL_HAVE_MPU 1 +#define XCHAL_MPU_ENTRIES 32 + +#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ +#define XCHAL_MPU_BACKGROUND_ENTRIES 2 /* number of entries in bg map*/ +#define XCHAL_MPU_BG_CACHEADRDIS 0xFF /* default CACHEADRDIS for bg */ + +#define XCHAL_MPU_ALIGN_BITS 12 +#define XCHAL_MPU_ALIGN 4096 + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/src/platform/mt8365/include/arch/xtensa/config/core-matmap.h b/src/platform/mt8365/include/arch/xtensa/config/core-matmap.h new file mode 100644 index 000000000000..1235cf0f758b --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/core-matmap.h @@ -0,0 +1,103 @@ +/* + * xtensa/config/core-matmap.h -- Memory access and translation mapping + * parameters (CHAL) of the Xtensa processor core configuration. + * + * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes + * this file) for more details. + * + * In the Xtensa processor products released to date, all parameters + * defined in this file are derivable (at least in theory) from + * information contained in the core-isa.h header file. + * In particular, the following core configuration parameters are relevant: + * XCHAL_HAVE_CACHEATTR + * XCHAL_HAVE_MIMIC_CACHEATTR + * XCHAL_HAVE_XLT_CACHEATTR + * XCHAL_HAVE_PTP_MMU + * XCHAL_ITLB_ARF_ENTRIES_LOG2 + * XCHAL_DTLB_ARF_ENTRIES_LOG2 + * XCHAL_DCACHE_IS_WRITEBACK + * XCHAL_ICACHE_SIZE (presence of I-cache) + * XCHAL_DCACHE_SIZE (presence of D-cache) + * XCHAL_HW_VERSION_MAJOR + * XCHAL_HW_VERSION_MINOR + */ + +/* Customer ID=13943; Build=0x75f5e; Copyright (c) 1999-2018 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_CORE_MATMAP_H +#define XTENSA_CONFIG_CORE_MATMAP_H + + +/*---------------------------------------------------------------------- + CACHE (MEMORY ACCESS) ATTRIBUTES + ----------------------------------------------------------------------*/ +/*---------------------------------------------------------------------- + MPU + ----------------------------------------------------------------------*/ + +/* Mappings for legacy constants where appropriate */ + +#define XCHAL_CA_WRITEBACK (XTHAL_MEM_WRITEBACK | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_WRITEBACK_NOALLOC (XTHAL_MEM_WRITEBACK_NOALLOC| XTHAL_AR_RWXrwx ) + +#define XCHAL_CA_WRITETHRU (XTHAL_MEM_WRITETHRU | XTHAL_AR_RWXrwx) + +#define XCHAL_CA_ILLEGAL (XTHAL_AR_NONE | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASSBUF (XTHAL_AR_RWXrwx | XTHAL_MEM_DEVICE |\ + XTHAL_MEM_BUFFERABLE) +#define XCHAL_CA_BYPASS_RX (XTHAL_AR_RX | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_RW (XTHAL_AR_RW | XTHAL_MEM_DEVICE) +#define XCHAL_CA_BYPASS_R (XTHAL_AR_R | XTHAL_MEM_DEVICE) +#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 + +#define XCHAL_CA_R (XTHAL_AR_R) +#define XCHAL_CA_RX (XTHAL_AR_RX) +#define XCHAL_CA_RW (XTHAL_AR_RW) +#define XCHAL_CA_RWX (XTHAL_AR_RWX) + + +/* + * Contents of MPU background map. + * NOTE: caller must define the XCHAL_MPU_BGMAP() macro (not defined here + * but specified below) before expanding the XCHAL_MPU_BACKGROUND_MAP(s) macro. + * + * XCHAL_MPU_BGMAP(s, vaddr_start, vaddr_last, rights, memtype, x...) + * + * s = passed from XCHAL_MPU_BACKGROUND_MAP(s), eg. to select how to expand + * vaddr_start = first byte of region (always 0 for first entry) + * vaddr_end = last byte of region (always 0xFFFFFFFF for last entry) + * rights = access rights + * memtype = memory type + * x = reserved for future use (0 until then) + */ +#define XCHAL_MPU_BACKGROUND_MAP(s) \ + XCHAL_MPU_BGMAP(s, 0x00000000, 0x7fffffff, 7, 6, 0) \ + XCHAL_MPU_BGMAP(s, 0x80000000, 0xffffffff, 7, 6, 0) \ + /* end */ + + + +#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ + diff --git a/src/platform/mt8365/include/arch/xtensa/config/defs.h b/src/platform/mt8365/include/arch/xtensa/config/defs.h new file mode 100644 index 000000000000..2a05ec08e4bb --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/defs.h @@ -0,0 +1,38 @@ +/* Definitions for Xtensa instructions, types, and protos. */ + +/* Customer ID=13943; Build=0x75f5e; Copyright (c) 2003-2004 Tensilica 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. */ + +/* NOTE: This file exists only for backward compatibility with T1050 + and earlier Xtensa releases. It includes only a subset of the + available header files. */ + +#ifndef _XTENSA_BASE_HEADER +#define _XTENSA_BASE_HEADER + +#ifdef __XTENSA__ + +#include <xtensa/tie/xt_core.h> +#include <xtensa/tie/xt_misc.h> +#include <xtensa/tie/xt_booleans.h> + +#endif /* __XTENSA__ */ +#endif /* !_XTENSA_BASE_HEADER */ diff --git a/src/platform/mt8365/include/arch/xtensa/config/specreg.h b/src/platform/mt8365/include/arch/xtensa/config/specreg.h new file mode 100644 index 000000000000..9345cc424d5a --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/specreg.h @@ -0,0 +1,103 @@ +/* + * Xtensa Special Register symbolic names + */ + +/* $Id: //depot/rel/Foxhill/dot.9/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ + +/* Customer ID=13943; Build=0x75f5e; Copyright (c) 1998-2002 Tensilica 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. */ + +#ifndef XTENSA_SPECREG_H +#define XTENSA_SPECREG_H + +/* Include these special register bitfield definitions, for historical reasons: */ +#include <xtensa/corebits.h> + + +/* Special registers: */ +#define LBEG 0 +#define LEND 1 +#define LCOUNT 2 +#define SAR 3 +#define BR 4 +#define PREFCTL 40 +#define WINDOWBASE 72 +#define WINDOWSTART 73 +#define MPUENB 90 +#define ERACCESS 95 +#define IBREAKENABLE 96 +#define MEMCTL 97 +#define CACHEADRDIS 98 +#define DDR 104 +#define IBREAKA_0 128 +#define IBREAKA_1 129 +#define DBREAKA_0 144 +#define DBREAKA_1 145 +#define DBREAKC_0 160 +#define DBREAKC_1 161 +#define EPC_1 177 +#define EPC_2 178 +#define EPC_3 179 +#define EPC_4 180 +#define DEPC 192 +#define EPS_2 194 +#define EPS_3 195 +#define EPS_4 196 +#define EXCSAVE_1 209 +#define EXCSAVE_2 210 +#define EXCSAVE_3 211 +#define EXCSAVE_4 212 +#define CPENABLE 224 +#define INTERRUPT 226 +#define INTENABLE 228 +#define PS 230 +#define VECBASE 231 +#define EXCCAUSE 232 +#define DEBUGCAUSE 233 +#define CCOUNT 234 +#define PRID 235 +#define ICOUNT 236 +#define ICOUNTLEVEL 237 +#define EXCVADDR 238 +#define CCOMPARE_0 240 +#define CCOMPARE_1 241 +#define CCOMPARE_2 242 +#define MISC_REG_0 244 +#define MISC_REG_1 245 +#define MISC_REG_2 246 +#define MISC_REG_3 247 + +/* Special cases (bases of special register series): */ +#define IBREAKA 128 +#define DBREAKA 144 +#define DBREAKC 160 +#define EPC 176 +#define EPS 192 +#define EXCSAVE 208 +#define CCOMPARE 240 + +/* Special names for read-only and write-only interrupt registers: */ +#define INTREAD 226 +#define INTSET 226 +#define INTCLEAR 227 + +#endif /* XTENSA_SPECREG_H */ + diff --git a/src/platform/mt8365/include/arch/xtensa/config/system.h b/src/platform/mt8365/include/arch/xtensa/config/system.h new file mode 100644 index 000000000000..2368853e0097 --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/system.h @@ -0,0 +1,267 @@ +/* + * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration + * + * NOTE: The location and contents of this file are highly subject to change. + * + * Source for configuration-independent binaries (which link in a + * configuration-specific HAL library) must NEVER include this file. + * The HAL itself has historically included this file in some instances, + * but this is not appropriate either, because the HAL is meant to be + * core-specific but system independent. + */ + +/* Customer ID=13943; Build=0x75f5e; Copyright (c) 2000-2010 Tensilica 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. */ + + +#ifndef XTENSA_CONFIG_SYSTEM_H +#define XTENSA_CONFIG_SYSTEM_H + +/*#include <xtensa/hal.h>*/ + + + +/*---------------------------------------------------------------------- + CONFIGURED SOFTWARE OPTIONS + ----------------------------------------------------------------------*/ + +#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ +#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ + +#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ +/* The above maps to one of the following constants: */ +#define XTHAL_ABI_WINDOWED 0 +#define XTHAL_ABI_CALL0 1 +/* Alternatives: */ +/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ +/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ + +#define XSHAL_CLIB XTHAL_CLIB_XCLIB /* (sw-only option, selected C library) */ +/* The above maps to one of the following constants: */ +#define XTHAL_CLIB_NEWLIB 0 +#define XTHAL_CLIB_UCLIBC 1 +#define XTHAL_CLIB_XCLIB 2 +/* Alternatives: */ +/*#define XSHAL_NEWLIB 0*/ /* set if newlib C library selected */ +/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ +/*#define XSHAL_XCLIB 1*/ /* set if Xtensa C library selected */ + +#define XSHAL_USE_FLOATING_POINT 1 + +#define XSHAL_FLOATING_POINT_ABI 1 + +/* SW workarounds enabled for HW errata: */ + +/* SW options for functional safety: */ +#define XSHAL_FUNC_SAFETY_ENABLED 0 + +/*---------------------------------------------------------------------- + DEVICE ADDRESSES + ----------------------------------------------------------------------*/ + +/* + * Strange place to find these, but the configuration GUI + * allows moving these around to account for various core + * configurations. Specific boards (and their BSP software) + * will have specific meanings for these components. + */ + +/* I/O Block areas: */ +#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 +#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 + +#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 +#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 +#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 + +/* System ROM: */ +/*#define XSHAL_ROM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ROM_SIZE ...not configured...*/ +/*#define XSHAL_ROM_AVAIL_V{ADDR,SIZE} ...not configured...*/ + +/* System RAM: */ +#define XSHAL_RAM_VADDR 0x40020000 +#define XSHAL_RAM_PADDR 0x40020000 +#define XSHAL_RAM_VSIZE 0x80000000 +#define XSHAL_RAM_PSIZE 0x80000000 +#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE +/* Largest available area (free of vectors): */ +#define XSHAL_RAM_AVAIL_VADDR 0x4002061C +#define XSHAL_RAM_AVAIL_VSIZE 0x7FFFF9E4 + +/* + * Shadow system RAM (same device as system RAM, at different address). + * (Emulation boards need this for the SONIC Ethernet driver + * when data caches are configured for writeback mode.) + * NOTE: on full MMU configs, this points to the BYPASS virtual address + * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual + * addresses are viewed through the BYPASS static map rather than + * the CACHED static map. + */ +#define XSHAL_RAM_BYPASS_VADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PADDR 0x20000000 +#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 + +/* Alternate system RAM (different device than system RAM): */ +/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ +/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ + +/* Some available location in which to place devices in a simulation (eg. XTMP): */ +#define XSHAL_SIMIO_CACHED_VADDR 0x20000000 +#define XSHAL_SIMIO_BYPASS_VADDR 0x20000000 +#define XSHAL_SIMIO_PADDR 0x20000000 +#define XSHAL_SIMIO_SIZE 0x20000000 + + +/*---------------------------------------------------------------------- + * For use by reference testbench exit and diagnostic routines. + */ +#define XSHAL_MAGIC_EXIT 0xcce5000 + +/*---------------------------------------------------------------------- + * DEVICE-ADDRESS DEPENDENT... + * + * Values written to CACHEATTR special register (or its equivalent) + * to enable and disable caches in various modes. + *----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------- + BACKWARD COMPATIBILITY ... + ----------------------------------------------------------------------*/ + +/* + * NOTE: the following two macros are DEPRECATED. Use the latter + * board-specific macros instead, which are specially tuned for the + * particular target environments' memory maps. + */ +#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ +#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ + +/*---------------------------------------------------------------------- + GENERIC + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains a system (PIF) RAM, + * system (PIF) ROM, local memory, or XLMI. */ + +/* These set any unused 512MB region to cache-BYPASS attribute: */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x24444424 /* enable caches in write-back mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x21111121 /* enable caches in write-allocate mode */ +#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x21111121 /* enable caches in write-through mode */ +#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set any unused 512MB region to ILLEGAL attribute: */ +#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xF44444F4 /* enable caches in write-back mode */ +#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xF11111F1 /* enable caches in write-allocate mode */ +#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xF11111F1 /* enable caches in write-through mode */ +#define XSHAL_STRICT_CACHEATTR_BYPASS 0xF22222F2 /* disable caches in bypass mode */ +#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch + * NULL-pointer dereference bugs; all other unused 512MB regions are set + * to cache-BYPASS attribute: */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x24444424 /* enable caches in write-back mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x21111121 /* enable caches in write-allocate mode */ +#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x21111121 /* enable caches in write-through mode */ +#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ +#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +/*---------------------------------------------------------------------- + ISS (Instruction Set Simulator) SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For now, ISS defaults to the TRAPNULL settings: */ +#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK +#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC +#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU +#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS +#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK + +#define XSHAL_ISS_PIPE_REGIONS 0 +#define XSHAL_ISS_SDRAM_REGIONS 0 + + +/*---------------------------------------------------------------------- + XT2000 BOARD SPECIFIC ... + ----------------------------------------------------------------------*/ + +/* For the following, a 512MB region is used if it contains any system RAM, + * system ROM, local memory, XLMI, or other XT2000 board device or memory. + * Regions containing devices are forced to cache-BYPASS mode regardless + * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ + +/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ +#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xF4444224 /* enable caches in write-back mode */ +#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xF1111221 /* enable caches in write-allocate mode */ +#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xF1111221 /* enable caches in write-through mode */ +#define XSHAL_XT2000_CACHEATTR_BYPASS 0xF2222222 /* disable caches in bypass mode */ +#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ + +#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ +#define XSHAL_XT2000_SDRAM_REGIONS 0x00000014 /* BusInt SDRAM regions */ + + +/*---------------------------------------------------------------------- + VECTOR INFO AND SIZES + ----------------------------------------------------------------------*/ + +#define XSHAL_VECTORS_PACKED 0 +#define XSHAL_STATIC_VECTOR_SELECT 1 +#define XSHAL_RESET_VECTOR_VADDR 0x40000640 +#define XSHAL_RESET_VECTOR_PADDR 0x40000640 + +/* + * Sizes allocated to vectors by the system (memory map) configuration. + * These sizes are constrained by core configuration (eg. one vector's + * code cannot overflow into another vector) but are dependent on the + * system or board (or LSP) memory map configuration. + * + * Whether or not each vector happens to be in a system ROM is also + * a system configuration matter, sometimes useful, included here also: + */ +#define XSHAL_RESET_VECTOR_SIZE 0x000002E0 +#define XSHAL_RESET_VECTOR_ISROM 0 +#define XSHAL_USER_VECTOR_SIZE 0x0000001C +#define XSHAL_USER_VECTOR_ISROM 0 +#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C +#define XSHAL_KERNEL_VECTOR_ISROM 0 +#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ +#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x0000001C +#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0 +#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 +#define XSHAL_WINDOW_VECTORS_ISROM 0 +#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL2_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL3_VECTOR_ISROM 0 +#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000001C +#define XSHAL_INTLEVEL4_VECTOR_ISROM 0 +#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL4_VECTOR_SIZE +#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL4_VECTOR_ISROM + + +#endif /*XTENSA_CONFIG_SYSTEM_H*/ + diff --git a/src/platform/mt8365/include/arch/xtensa/config/tie-asm.h b/src/platform/mt8365/include/arch/xtensa/config/tie-asm.h new file mode 100644 index 000000000000..2d9c889ecc5b --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/tie-asm.h @@ -0,0 +1,336 @@ +/* + * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file contains assembly-language definitions (assembly + macros, etc.) for this specific Xtensa processor's TIE extensions + and options. It is customized to this Xtensa processor configuration. + + Customer ID=13943; Build=0x75f5e; Copyright (c) 1999-2018 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. */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ +#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ + | ((ccuse) & XTHAL_SAS_ANYCC) \ + | ((abi) & XTHAL_SAS_ANYABI) ) + + + /* + * Macro to store all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger store sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to store. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to store, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any store. + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rur.THREADPTR \at1 // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + rsr.BR \at1 // boolean option + s32i \at1, \ptr, .Lxchal_ofs_+0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + rur.accreg_0 \at1 // ureg 3 + s32i \at1, \ptr, .Lxchal_ofs_+0 + rur.accreg_1 \at1 // ureg 4 + s32i \at1, \ptr, .Lxchal_ofs_+4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_store + + /* + * Macro to load all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 4 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters: + * continue If macro invoked as part of a larger load sequence, set to 1 + * if this is not the first in the sequence. Defaults to 0. + * ofs Offset from start of larger sequence (from value of first ptr + * in sequence) at which to load. Defaults to next available space + * (or 0 if <continue> is 0). + * select Select what category(ies) of registers to load, as a bitmask + * (see XTHAL_SAS_xxx constants). Defaults to all registers. + * alloc Select what category(ies) of registers to allocate; if any + * category is selected here that is not in <select>, space for + * the corresponding registers is skipped without doing any load. + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Optional global registers used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.THREADPTR \at1 // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Optional caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1016, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wsr.BR \at1 // boolean option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1016, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 1012, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_+0 + wur.accreg_0 \at1 // ureg 3 + l32i \at1, \ptr, .Lxchal_ofs_+4 + wur.accreg_1 \at1 // ureg 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 1012, 4, 4 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 + .endif + .endm // xchal_ncp_load + + +#define XCHAL_NCP_NUM_ATMPS 1 + + /* + * Macro to store the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_store. + */ +#define xchal_cp_AudioEngineLX_store xchal_cp1_store + .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_s64.i aed0, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed1, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed2, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed3, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed4, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed5, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed6, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed7, \ptr, .Lxchal_ofs_+32 + ae_s64.i aed8, \ptr, .Lxchal_ofs_+40 + ae_s64.i aed9, \ptr, .Lxchal_ofs_+48 + ae_s64.i aed10, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_s64.i aed11, \ptr, .Lxchal_ofs_+0 + ae_s64.i aed12, \ptr, .Lxchal_ofs_+8 + ae_s64.i aed13, \ptr, .Lxchal_ofs_+16 + ae_s64.i aed14, \ptr, .Lxchal_ofs_+24 + ae_s64.i aed15, \ptr, .Lxchal_ofs_+32 + ae_movae \at1, aep0 + s8i \at1, \ptr, .Lxchal_ofs_+40 + ae_movae \at1, aep1 + s8i \at1, \ptr, .Lxchal_ofs_+41 + ae_movae \at1, aep2 + s8i \at1, \ptr, .Lxchal_ofs_+42 + ae_movae \at1, aep3 + s8i \at1, \ptr, .Lxchal_ofs_+43 + ae_salign64.i u0, \ptr, .Lxchal_ofs_+48 + ae_salign64.i u1, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_salign64.i u2, \ptr, .Lxchal_ofs_+0 + ae_salign64.i u3, \ptr, .Lxchal_ofs_+8 + addi \ptr, \ptr, -192 + ae_movvfcrfsr aed0 // ureg FCR_FSR + ae_s64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 + rur.AE_OVF_SAR \at1 // ureg 240 + s32i \at1, \ptr, .Lxchal_ofs_+8 + rur.AE_BITHEAD \at1 // ureg 241 + s32i \at1, \ptr, .Lxchal_ofs_+12 + rur.AE_TS_FTS_BU_BP \at1 // ureg 242 + s32i \at1, \ptr, .Lxchal_ofs_+16 + rur.AE_CW_SD_NO \at1 // ureg 243 + s32i \at1, \ptr, .Lxchal_ofs_+20 + rur.AE_CBEGIN0 \at1 // ureg 246 + s32i \at1, \ptr, .Lxchal_ofs_+24 + rur.AE_CEND0 \at1 // ureg 247 + s32i \at1, \ptr, .Lxchal_ofs_+28 + rur.AE_CBEGIN1 \at1 // ureg 248 + s32i \at1, \ptr, .Lxchal_ofs_+32 + rur.AE_CEND1 \at1 // ureg 249 + s32i \at1, \ptr, .Lxchal_ofs_+36 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .endif + .endm // xchal_cp1_store + + /* + * Macro to load the state of TIE coprocessor AudioEngineLX. + * Required parameters: + * ptr Save area pointer address register (clobbered) + * (register must contain a 8 byte aligned address). + * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS + * registers are clobbered, the remaining are unused). + * Optional parameters are the same as for xchal_ncp_load. + */ +#define xchal_cp_AudioEngineLX_load xchal_cp1_load + .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 + xchal_sa_start \continue, \ofs + // Custom caller-saved registers not used by default by the compiler: + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) + xchal_sa_align \ptr, 0, 0, 8, 8 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+0 + 0 // ureg FCR_FSR + ae_movfcrfsrv aed0 + l32i \at1, \ptr, .Lxchal_ofs_+8 + wur.AE_OVF_SAR \at1 // ureg 240 + l32i \at1, \ptr, .Lxchal_ofs_+12 + wur.AE_BITHEAD \at1 // ureg 241 + l32i \at1, \ptr, .Lxchal_ofs_+16 + wur.AE_TS_FTS_BU_BP \at1 // ureg 242 + l32i \at1, \ptr, .Lxchal_ofs_+20 + wur.AE_CW_SD_NO \at1 // ureg 243 + l32i \at1, \ptr, .Lxchal_ofs_+24 + wur.AE_CBEGIN0 \at1 // ureg 246 + l32i \at1, \ptr, .Lxchal_ofs_+28 + wur.AE_CEND0 \at1 // ureg 247 + l32i \at1, \ptr, .Lxchal_ofs_+32 + wur.AE_CBEGIN1 \at1 // ureg 248 + l32i \at1, \ptr, .Lxchal_ofs_+36 + wur.AE_CEND1 \at1 // ureg 249 + ae_l64.i aed0, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed1, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed2, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed3, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed4, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed5, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed6, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed7, \ptr, .Lxchal_ofs_+32 + ae_l64.i aed8, \ptr, .Lxchal_ofs_+40 + ae_l64.i aed9, \ptr, .Lxchal_ofs_+48 + ae_l64.i aed10, \ptr, .Lxchal_ofs_+56 + addi \ptr, \ptr, 64 + ae_l64.i aed11, \ptr, .Lxchal_ofs_+0 + ae_l64.i aed12, \ptr, .Lxchal_ofs_+8 + ae_l64.i aed13, \ptr, .Lxchal_ofs_+16 + ae_l64.i aed14, \ptr, .Lxchal_ofs_+24 + ae_l64.i aed15, \ptr, .Lxchal_ofs_+32 + addi \ptr, \ptr, 40 + l8ui \at1, \ptr, .Lxchal_ofs_+0 + ae_movea aep0, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+1 + ae_movea aep1, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+2 + ae_movea aep2, \at1 + l8ui \at1, \ptr, .Lxchal_ofs_+3 + ae_movea aep3, \at1 + addi \ptr, \ptr, 8 + ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 + ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 + ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 + ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 + .set .Lxchal_pofs_, .Lxchal_pofs_ + 176 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 + .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 + xchal_sa_align \ptr, 0, 0, 8, 8 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 208 + .endif + .endm // xchal_cp1_load + +#define XCHAL_CP1_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp0_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp0_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/src/platform/mt8365/include/arch/xtensa/config/tie.h b/src/platform/mt8365/include/arch/xtensa/config/tie.h new file mode 100644 index 000000000000..196c1fd575b8 --- /dev/null +++ b/src/platform/mt8365/include/arch/xtensa/config/tie.h @@ -0,0 +1,189 @@ +/* + * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration + * + * NOTE: This header file is not meant to be included directly. + */ + +/* This header file describes this specific Xtensa processor's TIE extensions + that extend basic Xtensa core functionality. It is customized to this + Xtensa processor configuration. + + Customer ID=13943; Build=0x75f5e; Copyright (c) 1999-2018 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. */ + +#ifndef _XTENSA_CORE_TIE_H +#define _XTENSA_CORE_TIE_H + +#define XCHAL_CP_NUM 1 /* number of coprocessors */ +#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x02 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP1_NAME "AudioEngineLX" +#define XCHAL_CP1_IDENT AudioEngineLX +#define XCHAL_CP1_SA_SIZE 208 /* size of state save area */ +#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ +#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 16 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 224 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 4 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, accreg_0, 4, 4, 4,0x0303, ur,3 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, accreg_1, 4, 4, 4,0x0304, ur,4 , 32,0,0,0) + +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) /* empty */ + +#define XCHAL_CP1_SA_NUM 33 +#define XCHAL_CP1_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, fcr_fsr, 8, 8, 8,0x1019, ur,-1 , 7,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 4, 4, 4,0x03F0, ur,240, 15,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cbegin1, 4, 4, 4,0x03F8, ur,248, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ae_cend1, 4, 4, 4,0x03F9, ur,249, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep0, 1, 1, 1,0x1014, aep,0 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep1, 1, 1, 1,0x1015, aep,1 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep2, 1, 1, 1,0x1016, aep,2 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, aep3, 1, 1, 1,0x1017, aep,3 , 8,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) /* empty */ + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +/* (not available, must use XCHAL_BYTE0_FORMAT_LENGTHS for this processor) */ +/* Byte length of instruction from its first byte, per FLIX. */ +#define XCHAL_BYTE0_FORMAT_LENGTHS \ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11,\ + 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,6,11 + +#endif /*_XTENSA_CORE_TIE_H*/ + diff --git a/src/platform/mt8365/include/platform/drivers/idc.h b/src/platform/mt8365/include/platform/drivers/idc.h new file mode 100644 index 000000000000..b638b9ec987e --- /dev/null +++ b/src/platform/mt8365/include/platform/drivers/idc.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#if defined(__XTOS_RTOS_IDC_H__) || defined(__ZEPHYR_RTOS_IDC_H__) + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include <stdint.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +static inline int idc_init(void) +{ + return 0; +} + +#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/mt8365/include/platform/drivers/interrupt.h b/src/platform/mt8365/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..c40b68ab1f42 --- /dev/null +++ b/src/platform/mt8365/include/platform/drivers/interrupt.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#include <stdint.h> +#include <platform/drivers/mt_reg_base.h> + +#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS +#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM +#define PLATFORM_IRQ_CHILDREN (LX_MCU_IRQ_B - LX_CQDMA_IRQ0_B + 1) + +#define IRQ_EXT_MASK 0x3F0 + +/* interrupt table */ +#define MTK_DSP_EXT_IRQ0 0 +#define L1_INT_IRQ_B 1 // (INT_LEVEL(1) | IRQ_INVALID) +#define L1_DSP_TIMER_IRQ0_B 2 // (INT_LEVEL(2) | INTERRUPT_ID(0)) +#define L1_DSP_TIMER_IRQ1_B 3 // (INT_LEVEL(3) | INTERRUPT_ID(1)) +#define L1_DSP_TIMER_IRQ2_B 4 // (INT_LEVEL(4) | INTERRUPT_ID(2)) +#define L1_DSP_TIMER_IRQ3_B 5 // (INT_LEVEL(5) | INTERRUPT_ID(3)) +#define MTK_DSP_EXT_IRQ6 6 +#define MTK_DSP_EXT_IRQ7 7 +#define MTK_DSP_EXT_IRQ8 8 +#define MTK_DSP_EXT_IRQ9 9 +#define MTK_DSP_EXT_IRQ10 10 +#define MTK_DSP_EXT_IRQ11 11 +#define MTK_DSP_EXT_IRQ12 12 +#define MTK_DSP_EXT_IRQ13 13 +#define MTK_DSP_EXT_IRQ14 14 +#define MTK_DSP_EXT_IRQ15 15 +/* HiFi internal interrupts */ +#define MTK_DSP_IRQ_TIMER0 16 +#define MTK_DSP_IRQ_TIMER1 17 +#define MTK_DSP_IRQ_TIMER2 18 +#define MTK_DSP_IRQ_WRITE_ERROR 19 +#define MTK_DSP_IRQ_PROFILING 20 +#define MTK_DSP_IRQ_SOFTWARE0 21 +#define MTK_DSP_IRQ_SOFTWARE1 22 +/* HiFi external interrupts */ +#define MTK_DSP_EXT_INT23 23 +#define MTK_DSP_EXT_INT24 24 + +/* group 1 cascaded IRQ trigger L1_INT_IRQ_B */ +#define IRQ_EXT_GROUP1_BASE L1_INT_IRQ_B +#define LX_CQDMA_IRQ0_B 25 // (INT_LEVEL(1) | INTERRUPT_ID(4)) +#define LX_CQDMA_IRQ1_B 26 // (INT_LEVEL(1) | INTERRUPT_ID(5)) +#define LX_CQDMA_IRQ2_B 27 // (INT_LEVEL(1) | INTERRUPT_ID(6)) +#define LX_UART_IRQ_B 28 // (INT_LEVEL(1) | INTERRUPT_ID(7)) +#define LX_AFE_IRQ_B 29 // (INT_LEVEL(1) | INTERRUPT_ID(8)) +#define LX_MCU_IRQ_B 30 // (INT_LEVEL(1) | INTERRUPT_ID(9)) + +int mtk_irq_group_id(uint32_t irq); + +/* L1_DSP_TIMER_IRQ0_B corresponds to bit# 0 of RG_DSP_IRQ_EN */ +#define IRQ_EXT_BIT_OFFSET (-2) + +/* base_irq = 25; (LX_CQDMA_IRQ0_B - base_irq) corresponds to bit# 4 of RG_DSP_IRQ_EN */ +#define IRQ_EXT_GROUP1_BIT_OFFSET (4) + +#define RG_DSP_IRQ_EN DSP_RG_INT_EN_CTL0 +#define RG_DSP_IRQ_STATUS DSP_RG_INT_STATUS0 + +#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/mt8365/include/platform/drivers/mt_reg_base.h b/src/platform/mt8365/include/platform/drivers/mt_reg_base.h new file mode 100644 index 000000000000..289ab7d256d6 --- /dev/null +++ b/src/platform/mt8365/include/platform/drivers/mt_reg_base.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifndef MT_REG_BASE_H +#define MT_REG_BASE_H + +#define DSP_REG_BASE (0x1D062000) /* DSPCFG base */ +#define DSP_TIMER_BASE (0x1D060000) +#define DSP_UART0_BASE (0x1D061000) +#define DSP_WDT_BASE (0x1D062400) +#define DSP_IRQ_BASE (0x1D063000) +#define DSP_D_TCM (CFG_HIFI4_DTCM_ADDRESS) +#define DSP_I_TCM (CFG_HIFI4_ITCM_ADDRESS) +#define DSP_DRAM_BASE (CFG_HIFI4_DRAM_ADDRESS) + +#define DSP_AUDIO_SRAM_BASE (0x11221000) +#define DSP_AUDIO_SRAM_SIZE (0xA000) +#define DSP_REG_REMAP_BASE (0x1D060000) +#define DSP_REG_REMAP_SIZE (0x8000) +#define DSP_SYS_REG_BASE (0x10000000) +#define DSP_SYS_REG_SIZE (0x1221000) +#define DSP_VER_REG_BASE (0x08000000) +#define DSP_VER_REG_SIZE (0x1000) + + +#define DSP_JTAGMUX (DSP_REG_BASE + 0x0000) +#define DSP_ALTRESETVEC (DSP_REG_BASE + 0x0004) +#define DSP_PDEBUGDATA (DSP_REG_BASE + 0x0008) +#define DSP_PDEBUGBUS0 (DSP_REG_BASE + 0x000c) +#define DSP_PDEBUGBUS1 (DSP_REG_BASE + 0x0010) +#define DSP_PDEBUGINST (DSP_REG_BASE + 0x0014) +#define DSP_PDEBUGLS0STAT (DSP_REG_BASE + 0x0018) +#define DSP_PDEBUGLS1STAT (DSP_REG_BASE + 0x001c) +#define DSP_PDEBUGPC (DSP_REG_BASE + 0x0020) +#define DSP_RESET_SW (DSP_REG_BASE + 0x0024) +#define DSP_PFAULTBUS (DSP_REG_BASE + 0x0028) +#define DSP_PFAULTINFO (DSP_REG_BASE + 0x002c) +#define DSP_GPR00 (DSP_REG_BASE + 0x0030) +#define DSP_GPR01 (DSP_REG_BASE + 0x0034) +#define DSP_GPR02 (DSP_REG_BASE + 0x0038) +#define DSP_GPR03 (DSP_REG_BASE + 0x003c) +#define DSP_GPR04 (DSP_REG_BASE + 0x0040) +#define DSP_GPR05 (DSP_REG_BASE + 0x0044) +#define DSP_GPR06 (DSP_REG_BASE + 0x0048) +#define DSP_GPR07 (DSP_REG_BASE + 0x004c) +#define DSP_GPR08 (DSP_REG_BASE + 0x0050) +#define DSP_GPR09 (DSP_REG_BASE + 0x0054) +#define DSP_GPR0A (DSP_REG_BASE + 0x0058) +#define DSP_GPR0B (DSP_REG_BASE + 0x005c) +#define DSP_GPR0C (DSP_REG_BASE + 0x0060) +#define DSP_GPR0D (DSP_REG_BASE + 0x0064) +#define DSP_GPR0E (DSP_REG_BASE + 0x0068) +#define DSP_GPR0F (DSP_REG_BASE + 0x006c) +#define DSP_GPR10 (DSP_REG_BASE + 0x0070) +#define DSP_GPR11 (DSP_REG_BASE + 0x0074) +#define DSP_GPR12 (DSP_REG_BASE + 0x0078) +#define DSP_GPR13 (DSP_REG_BASE + 0x007c) +#define DSP_GPR14 (DSP_REG_BASE + 0x0080) +#define DSP_GPR15 (DSP_REG_BASE + 0x0084) +#define DSP_GPR16 (DSP_REG_BASE + 0x0088) +#define DSP_GPR17 (DSP_REG_BASE + 0x008c) +#define DSP_GPR18 (DSP_REG_BASE + 0x0090) +#define DSP_GPR19 (DSP_REG_BASE + 0x0094) +#define DSP_GPR1A (DSP_REG_BASE + 0x0098) +#define DSP_GPR1B (DSP_REG_BASE + 0x009c) +#define DSP_GPR1C (DSP_REG_BASE + 0x00a0) +#define DSP_GPR1D (DSP_REG_BASE + 0x00a4) +#define DSP_GPR1E (DSP_REG_BASE + 0x00a8) +#define DSP_GPR1F (DSP_REG_BASE + 0x00ac) +#define DSP_TCM_OFFSET (DSP_REG_BASE + 0x00b0) /* not used */ +#define DSP_DDR_OFFSET (DSP_REG_BASE + 0x00b4) /* not used */ +#define DSP_INTFDSP (DSP_REG_BASE + 0x00d0) +#define DSP_INTFDSP_CLR (DSP_REG_BASE + 0x00d4) +#define DSP_SRAM_PD_SW1 (DSP_REG_BASE + 0x00d8) +#define DSP_SRAM_PD_SW2 (DSP_REG_BASE + 0x00dc) +#define DSP_OCD (DSP_REG_BASE + 0x00e0) +#define DSP_RG_DSP_IRQ_POL (DSP_REG_BASE + 0x00f0) /* not used */ +#define DSP_DSP_IRQ_EN (DSP_REG_BASE + 0x00f4) /* not used */ +#define DSP_DSP_IRQ_LEVEL (DSP_REG_BASE + 0x00f8) /* not used */ +#define DSP_DSP_IRQ_STATUS (DSP_REG_BASE + 0x00fc) /* not used */ +#define DSP_RG_INT2CIRQ (DSP_REG_BASE + 0x0114) +#define DSP_RG_INT_POL_CTL0 (DSP_REG_BASE + 0x0120) +#define DSP_RG_INT_EN_CTL0 (DSP_REG_BASE + 0x0130) +#define DSP_RG_INT_LV_CTL0 (DSP_REG_BASE + 0x0140) +#define DSP_RG_INT_STATUS0 (DSP_REG_BASE + 0x0150) +#define DSP_PDEBUGSTATUS0 (DSP_REG_BASE + 0x0200) +#define DSP_PDEBUGSTATUS1 (DSP_REG_BASE + 0x0204) +#define DSP_PDEBUGSTATUS2 (DSP_REG_BASE + 0x0208) +#define DSP_PDEBUGSTATUS3 (DSP_REG_BASE + 0x020c) +#define DSP_PDEBUGSTATUS4 (DSP_REG_BASE + 0x0210) +#define DSP_PDEBUGSTATUS5 (DSP_REG_BASE + 0x0214) +#define DSP_PDEBUGSTATUS6 (DSP_REG_BASE + 0x0218) +#define DSP_PDEBUGSTATUS7 (DSP_REG_BASE + 0x021c) +#define DSP_DSP2PSRAM_PRIORITY (DSP_REG_BASE + 0x0220) /* not used */ +#define DSP_AUDIO_DSP2SPM_INT (DSP_REG_BASE + 0x0224) +#define DSP_AUDIO_DSP2SPM_INT_ACK (DSP_REG_BASE + 0x0228) +#define DSP_AUDIO_DSP_DEBUG_SEL (DSP_REG_BASE + 0x022C) +#define DSP_AUDIO_DSP_EMI_BASE_ADDR (DSP_REG_BASE + 0x02E0) /* not used */ +#define DSP_AUDIO_DSP_SHARED_IRAM (DSP_REG_BASE + 0x02E4) +#define DSP_AUDIO_DSP_CKCTRL_P2P_CK_CON (DSP_REG_BASE + 0x02F0) +#define DSP_RG_SEMAPHORE00 (DSP_REG_BASE + 0x0300) +#define DSP_RG_SEMAPHORE01 (DSP_REG_BASE + 0x0304) +#define DSP_RG_SEMAPHORE02 (DSP_REG_BASE + 0x0308) +#define DSP_RG_SEMAPHORE03 (DSP_REG_BASE + 0x030C) +#define DSP_RG_SEMAPHORE04 (DSP_REG_BASE + 0x0310) +#define DSP_RG_SEMAPHORE05 (DSP_REG_BASE + 0x0314) +#define DSP_RG_SEMAPHORE06 (DSP_REG_BASE + 0x0318) +#define DSP_RG_SEMAPHORE07 (DSP_REG_BASE + 0x031C) +#define DSP_RESERVED_0 (DSP_REG_BASE + 0x03F0) +#define DSP_RESERVED_1 (DSP_REG_BASE + 0x03F4) /* use for tickless status */ + +/* Redefinition for using Special registers */ +#define TICKLESS_STATUS_REG (DSP_RESERVED_1) + +/* WDT CONFIGS */ +#define ADSP_WDT_MODE (DSP_REG_BASE + 0x400 + 0x00) +#define ADSP_WDT_LENGTH (DSP_REG_BASE + 0x400 + 0x04) +#define ADSP_WDT_RESTART (DSP_REG_BASE + 0x400 + 0x08) +#define ADSP_WDT_STA (DSP_REG_BASE + 0x400 + 0x0C) +#define ADSP_WDT_SWRST (DSP_REG_BASE + 0x400 + 0x14) + +#define ADSP_WDT_SWRST_KEY 0x1209 +#define ADSP_WDT_RESTART_RELOAD 0x1971 +#define ADSP_WDT_LENGTH_KEY 0x8 + +#define WDT_LENGTH_TIMEOUT(n) ((n) << 5) + +/* DSP IPI IRQ */ +#define CPU2DSP_IRQ BIT(0) +#define DSP2CPU_IRQ BIT(1) +#define DSP2SPM_IRQ_B BIT(2) + +#endif /* MT_REG_BASE_H */ + diff --git a/src/platform/mt8365/include/platform/drivers/timer.h b/src/platform/mt8365/include/platform/drivers/timer.h new file mode 100644 index 000000000000..8d389d5da4e0 --- /dev/null +++ b/src/platform/mt8365/include/platform/drivers/timer.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifndef __PLATFORM_DRIVERS_TIMER_H__ +#define __PLATFORM_DRIVERS_TIMER_H__ + +#include <rtos/bit.h> +#include <platform/drivers/mt_reg_base.h> + + +/*-------timer:ostimer0-------*/ +enum ostimer { + OSTIMER0 = 0, + OSTIMER1, + OSTIMER2, + OSTIMER3, + NR_TMRS +}; + +#define TIMER_CON(n) (DSP_TIMER_BASE + 0x40 + 0x8 * (n)) +#define TIMER_CNT_VAL(n) (DSP_TIMER_BASE + 0x44 + 0x8 * (n)) + +#define TIMER_ENABLE_BIT (0x1 << 0) +#define TIMER_IRQ_ENABLE (0x1 << 1) +#define TIMER_IRQ_STA (0x1 << 4) +#define TIMER_IRQ_CLEAR (0x1 << 4) + +/** + * system timer register map + */ +#define CNTCR (DSP_TIMER_BASE + 0x00) +#define CNTSR (DSP_TIMER_BASE + 0x04) +#define CNTCV_L (DSP_TIMER_BASE + 0x08) +#define CNTCV_H (DSP_TIMER_BASE + 0x0c) +#define CNTWACR (DSP_TIMER_BASE + 0x10) +#define CNTRACR (DSP_TIMER_BASE + 0x14) +#define CNTACR_LOCK (DSP_TIMER_BASE + 0x18) +#define CNTFID0 (DSP_TIMER_BASE + 0x20) +#define CNTFID1 (DSP_TIMER_BASE + 0x24) +#define CNTFID2 (DSP_TIMER_BASE + 0x28) +#define CNTFIDE (DSP_TIMER_BASE + 0x2c) + +#define CNT_EN_BIT BIT(0) +#define CLKSRC_BIT (BIT(8) | BIT(9)) +#define CLKSRC_13M_BIT BIT(8) +#define COMP_BIT (BIT(10) | BIT(11) | BIT(12)) +#define COMP_20_25_EN_BIT (BIT(11) | BIT(12)) + +#define CNT_EN (0x1 << 0) +#define CNTTVAL_EN (0x1 << 0) +#define CNTIRQ_EN (0x1 << 1) +#define CNTIRQ_STACLR (0x1 << 4) +#define CNTMODE_REPEAT (0x1 << 8) + + +#define DELAY_TIMER_1US_TICK (13U) // (13MHz) +#define DELAY_TIMER_1MS_TICK (13000U) // (13MHz) +#define TIME_TO_TICK_US(us) ((us)*DELAY_TIMER_1US_TICK) +#define TIME_TO_TICK_MS(ms) ((ms)*DELAY_TIMER_1MS_TICK) + +#define SYSTICK_TIMER_IRQ L1_DSP_TIMER_IRQ0_B + + +#endif /* __PLATFORM_DRIVERS_TIMER_H__ */ diff --git a/src/platform/mt8365/include/platform/lib/clk.h b/src/platform/mt8365/include/platform/lib/clk.h new file mode 100644 index 000000000000..beaa2f762bbe --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/clk.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <stdint.h> + +struct sof; + +#define CPU_DEFAULT_IDX 4 + +#define CLK_CPU(x) (x) +#define CLK_DEFAULT_CPU_HZ 600000000 +#define CLK_MAX_CPU_HZ 600000000 +#define CLK_SUSPEND_CPU_HZ 26000000 +#define NUM_CLOCKS 1 +#define NUM_CPU_FREQ 5 + +void platform_clock_init(struct sof *sof); + +#define REG_APMIXDSYS_BASE 0x1000C000 +#define REG_TOPCKGEN_BASE 0x10000000 + +#define DSPPLL_CON0 (REG_APMIXDSYS_BASE + 0x390) +#define DSPPLL_CON1 (REG_APMIXDSYS_BASE + 0x394) +#define DSPPLL_CON2 (REG_APMIXDSYS_BASE + 0x398) +#define DSPPLL_CON3 (REG_APMIXDSYS_BASE + 0x39C) + +#define ULPLL_CON0 (REG_APMIXDSYS_BASE + 0x3B0) +#define ULPLL_CON1 (REG_APMIXDSYS_BASE + 0x3B4) + +#define PLL_BASE_EN BIT(0) +#define PLL_PWR_ON BIT(0) +#define PLL_ISO_EN BIT(1) + +#define DSPPLL_312MHZ 0 +#define DSPPLL_400MHZ 1 +#define DSPPLL_600MHZ 2 + +#define CLK_MODE (REG_TOPCKGEN_BASE + 0x0) +#define CLK_CFG_UPDATE1 (REG_TOPCKGEN_BASE + 0x8) +#define CLK_CFG_8 (REG_TOPCKGEN_BASE + 0xC0) +#define CLK_CFG_8_SET (REG_TOPCKGEN_BASE + 0xC4) +#define CLK_CFG_8_CLR (REG_TOPCKGEN_BASE + 0xC8) + +#define CLK_SCP_CFG_1 (REG_TOPCKGEN_BASE + 0x204) + +#define CLK_DSP_SEL_26M 0 +#define CLK_DSP_SEL_26M_D_2 1 +#define CLK_DSP_SEL_DSPPLL 2 +#define CLK_DSP_SEL_DSPPLL_D_2 3 +#define CLK_DSP_SEL_DSPPLL_D_4 4 +#define CLK_DSP_SEL_DSPPLL_D_8 5 + +#define CLK_TOPCKGEN_SEL_PLLGP_26M 1 +#define CLK_TOPCKGEN_SEL_ULPLL_26M 2 +#define CLK_TOPCKGEN_SEL_GPIO_26M 4 + +enum mux_id_t { + MUX_CLK_DSP_SEL = 0, + MUX_CLK_TOPCKGEN_26M_SEL, + HIFI4DSP_MUX_NUM, +}; + +enum mux_26m_t { + DCXO_26 = 0, + ULPLL_26M, +}; + +enum DSP_HW_DSP_CLK { + DSP_CLK_13M = 0, + DSP_CLK_26M, + DSP_CLK_PLL_312M, + DSP_CLK_PLL_400M, + DSP_CLK_PLL_600M, +}; +#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/mt8365/include/platform/lib/cpu.h b/src/platform/mt8365/include/platform/lib/cpu.h new file mode 100644 index 000000000000..1c72bd51b176 --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/cpu.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/** \brief Id of primary DSP core */ +#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/mt8365/include/platform/lib/dai.h b/src/platform/mt8365/include/platform/lib/dai.h new file mode 100644 index 000000000000..98fe70955f2f --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/dai.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +#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/mt8365/include/platform/lib/dma.h b/src/platform/mt8365/include/platform/lib/dma.h new file mode 100644 index 000000000000..479591ab5daa --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/dma.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +#define PLATFORM_NUM_DMACS 2 + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 32 + +#define DMA_ID_AFE_MEMIF 0 +#define DMA_ID_HOST 1 + +#define dma_chan_irq(dma, chan) dma_irq(dma) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#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/mt8365/include/platform/lib/mailbox.h b/src/platform/mt8365/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..27f48a72238c --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/mailbox.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <sof/lib/memory.h> +#include <stddef.h> +#include <stdint.h> + +/* + * The Window Region on MT8365 SRAM is organised like this :- + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer | SRAM_TRACE_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_DEBUG_BASE | Debug data | SRAM_DEBUG_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_INBOX_BASE | Inbox | SRAM_INBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM_OUTBOX_BASE | Outbox | SRAM_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + */ + +#define MAILBOX_DSPBOX_SIZE SRAM_OUTBOX_SIZE +#define MAILBOX_DSPBOX_BASE SRAM_OUTBOX_BASE +#define MAILBOX_DSPBOX_OFFSET SRAM_OUTBOX_OFFSET + +#define MAILBOX_HOSTBOX_SIZE SRAM_INBOX_SIZE +#define MAILBOX_HOSTBOX_BASE SRAM_INBOX_BASE +#define MAILBOX_HOSTBOX_OFFSET SRAM_INBOX_OFFSET + +#define MAILBOX_DEBUG_SIZE SRAM_DEBUG_SIZE +#define MAILBOX_DEBUG_BASE SRAM_DEBUG_BASE +#define MAILBOX_DEBUG_OFFSET SRAM_DEBUG_OFFSET + +#define MAILBOX_TRACE_SIZE SRAM_TRACE_SIZE +#define MAILBOX_TRACE_BASE SRAM_TRACE_BASE +#define MAILBOX_TRACE_OFFSET SRAM_TRACE_OFFSET + +#define MAILBOX_EXCEPTION_SIZE SRAM_EXCEPT_SIZE +#define MAILBOX_EXCEPTION_BASE SRAM_EXCEPT_BASE +#define MAILBOX_EXCEPTION_OFFSET SRAM_EXCEPT_OFFSET + +#define MAILBOX_STREAM_SIZE SRAM_STREAM_SIZE +#define MAILBOX_STREAM_BASE SRAM_STREAM_BASE +#define MAILBOX_STREAM_OFFSET SRAM_STREAM_OFFSET + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + *ptr = src; +} + +static inline uint32_t mailbox_sw_reg_read(size_t offset) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *)(MAILBOX_DEBUG_BASE + offset); + + return *ptr; +} + + #define ADSP_IPI_OP_REQ 0x1 + #define ADSP_IPI_OP_RSP 0x2 +void trigger_irq_to_host_req(void); +void trigger_irq_to_host_rsp(void); + +#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/mt8365/include/platform/lib/memory.h b/src/platform/mt8365/include/platform/lib/memory.h new file mode 100644 index 000000000000..3f0532d4d417 --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/memory.h @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include <rtos/cache.h> +#include <xtensa/config/core-isa.h> + +#define BOOT_WITH_DRAM /*Use DRAM as SRAM1 for heap related*/ +/* data cache line alignment */ +#define PLATFORM_DCACHE_ALIGN sizeof(void *) + +/* + * +-----------------------------------+-----------------------------+ + * | | AUDIO_DSP_SHARED_DRAM | + * +------------+----------------------+---------+---------+---------+ + * | DSP | Sys | Size | 00b | 01b *** | 11b | + * +------------+------------+---------+---------+---------+---------+ + * | 0x40000000 | 0x1e100000 | 0x8000 | iram0_0 | iram0_0 | iram0_0 | + * | 0x40008000 | 0x1e108000 | 0x8000 | iram0_1 | iram0_1 | --- | + * | 0x40010000 | 0x1e110000 | 0x8000 | iram1 | --- | --- | + * +------------+------------+---------+---------+---------+---------+ + * | 0x1e000000 | 0x1e000000 | 0x40000 | dram0 | dram0 | dram0 | + * | 0x1e040000 | 0x1e040000 | 0x20000 | dram1 | dram1 | dram1 | + * | 0x1e060000 | 0x1e060000 | 0x8000 | --- | iram1 | iram1 | + * | 0x1e068000 | 0x1e068000 | 0x8000 | --- | --- | iram0_1 | + * +------------+------------+---------+---------+---------+---------+ + */ + +/* BOOT_WITH_DRAM ONLY */ +/* physical DSP addresses */ +#define DRAM_BASE 0x60000000 +#define DRAM_AUDIO_SHARED_SIZE 0x280000 +#define DRAM_SIZE 0x1000000 /*DRAM Size : 16M , need to sync with Host side*/ + +#define SRAM_TOTAL_SIZE 0x40000 /*256KB DSP SRAM*/ +#define VECTOR_SIZE 0x628 + +#define SRAM0_BASE DRAM_BASE +#define SRAM0_SIZE (DRAM_SIZE >> 1) +#define SRAM1_BASE (DRAM_BASE + SRAM0_SIZE) +#define SRAM1_SIZE \ + (DRAM_SIZE - SRAM0_SIZE - DRAM_AUDIO_SHARED_SIZE - UUID_ENTRY_ELF_SIZE - \ + LOG_ENTRY_ELF_SIZE - EXT_MANIFEST_ELF_SIZE) + +#define DMA_SIZE 0x100000 + +#define UUID_ENTRY_ELF_SIZE 0x6000 +#define LOG_ENTRY_ELF_SIZE 0x200000 +#define EXT_MANIFEST_ELF_SIZE 0x100000 + +#define UUID_ENTRY_ELF_BASE (SRAM1_BASE + SRAM1_SIZE) +#define LOG_ENTRY_ELF_BASE (UUID_ENTRY_ELF_BASE + UUID_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) + +/* + * The Memory Layout on MT8365 are organised like this :- + * + * +--------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +---------------------+----------------+-----------------------------------+ + * | XCHAL_RESET_VECTOR0 | DSP Vectors | VECTOR_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SRAM0_BASE | fw_ready | SRAM0_SIZE | + * | | RO Data | | + * | | module_init | | + * | | Text | | + * | | Data | | + * | | BSS | | + * +---------------------+----------------+-----------------------------------+ + * | SRAM1_BASE | MAILBOX | SOF_MAILBOX_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_SYSTEM_BASE | System Heap | HEAP_SYSTEM_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_RUNTIME_BASE | Runtime Heap | HEAP_RUNTIME_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | HEAP_BUFFER_BASE | Module Buffers | HEAP_BUFFER_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_END | Stack | SOF_STACK_SIZE | + * +---------------------+----------------+-----------------------------------+ + * | SOF_STACK_BASE | | | + * +---------------------+----------------+-----------------------------------+ + */ + +/* Mailbox configuration */ +#define SRAM_OUTBOX_BASE SRAM1_BASE +#define SRAM_OUTBOX_SIZE 0x1000 +#define SRAM_OUTBOX_OFFSET 0 + +#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) +#define SRAM_INBOX_SIZE 0x1000 +#define SRAM_INBOX_OFFSET SRAM_OUTBOX_SIZE + +#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) +#define SRAM_DEBUG_SIZE 0x800 +#define SRAM_DEBUG_OFFSET (SRAM_INBOX_OFFSET + SRAM_INBOX_SIZE) + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 +#define SRAM_EXCEPT_OFFSET (SRAM_DEBUG_OFFSET + SRAM_DEBUG_SIZE) + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 +#define SRAM_STREAM_OFFSET (SRAM_EXCEPT_OFFSET + SRAM_EXCEPT_SIZE) + +#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) +#define SRAM_TRACE_SIZE 0x1000 +#define SRAM_TRACE_OFFSET (SRAM_STREAM_OFFSET + SRAM_STREAM_SIZE) + +/*4K + 4K +2K + 2K + 4K + 4K = 20KB*/ +#define SOF_MAILBOX_SIZE \ + (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE + \ + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) + +/* Heap section sizes for module pool */ +#define HEAP_RT_COUNT8 0 +#define HEAP_RT_COUNT16 48 +#define HEAP_RT_COUNT32 48 +#define HEAP_RT_COUNT64 32 +#define HEAP_RT_COUNT128 32 +#define HEAP_RT_COUNT256 32 +#define HEAP_RT_COUNT512 32 +#define HEAP_RT_COUNT1024 4 +#define HEAP_RT_COUNT2048 2 +#define HEAP_RT_COUNT4096 2 + +/* Heap section sizes for system runtime heap */ +#define HEAP_SYS_RT_COUNT64 128 +#define HEAP_SYS_RT_COUNT512 16 +#define HEAP_SYS_RT_COUNT1024 8 + +/* Heap configuration */ + +#define HEAP_SYSTEM_BASE (SRAM1_BASE + SOF_MAILBOX_SIZE) +#define HEAP_SYSTEM_SIZE 0x6000 + +#define HEAP_SYSTEM_0_BASE HEAP_SYSTEM_BASE + +#define HEAP_SYS_RUNTIME_BASE (HEAP_SYSTEM_BASE + HEAP_SYSTEM_SIZE) +/*24KB*/ +#define HEAP_SYS_RUNTIME_SIZE \ + (HEAP_SYS_RT_COUNT64 * 64 + HEAP_SYS_RT_COUNT512 * 512 + HEAP_SYS_RT_COUNT1024 * 1024) + +#define HEAP_RUNTIME_BASE (HEAP_SYS_RUNTIME_BASE + HEAP_SYS_RUNTIME_SIZE) +/*48*(16 +32) + 32*(64 128+256) + 4*(512+1024) + 1*2048 = 24832 = 24.25KB*/ +#define HEAP_RUNTIME_SIZE \ + (HEAP_RT_COUNT8 * 8 + HEAP_RT_COUNT16 * 16 + HEAP_RT_COUNT32 * 32 + HEAP_RT_COUNT64 * 64 + \ + HEAP_RT_COUNT128 * 128 + HEAP_RT_COUNT256 * 256 + HEAP_RT_COUNT512 * 512 + \ + HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + HEAP_RT_COUNT4096 * 4096) + +#define HEAP_BUFFER_BASE (HEAP_RUNTIME_BASE + HEAP_RUNTIME_SIZE) +#define HEAP_BUFFER_SIZE \ + (SRAM1_SIZE - SOF_MAILBOX_SIZE - HEAP_RUNTIME_SIZE - SOF_STACK_TOTAL_SIZE - \ + HEAP_SYS_RUNTIME_SIZE - HEAP_SYSTEM_SIZE) + +#define HEAP_BUFFER_BLOCK_SIZE 0x100 +#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) + +#define PLATFORM_HEAP_SYSTEM 1 /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* Stack configuration */ +#define SOF_STACK_SIZE 0x8000 +#define SOF_STACK_TOTAL_SIZE SOF_STACK_SIZE /*4KB*/ +#define SOF_STACK_BASE (SRAM1_BASE + SRAM1_SIZE) +#define SOF_STACK_END (SOF_STACK_BASE - SOF_STACK_TOTAL_SIZE) + +/* Vector and literal sizes - not in core-isa.h */ +#define SOF_MEM_VECT_LIT_SIZE 0x4 +#define SOF_MEM_VECT_TEXT_SIZE 0x1c +#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + SOF_MEM_VECT_LIT_SIZE) + +#define SOF_MEM_RESET_TEXT_SIZE 0x2e0 +#define SOF_MEM_RESET_LIT_SIZE 0x120 +#define SOF_MEM_VECBASE_LIT_SIZE 0x178 + +#define SOF_MEM_RO_SIZE 0x8 + +#define HEAP_BUF_ALIGNMENT DCACHE_LINE_SIZE + +/** \brief EDF task's default stack size in bytes. */ +#ifdef CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING +#define PLATFORM_TASK_DEFAULT_STACK_SIZE (12 * 1024) +#else +#define PLATFORM_TASK_DEFAULT_STACK_SIZE 3072 +#endif + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +struct sof; + +/** + * \brief Data shared between different cores. + * Does nothing, since mt8195 doesn't support SMP. + */ +#define SHARED_DATA + +void platform_init_memmap(struct sof *sof); + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +/** + * \brief Function for keeping shared data synchronized. + * It's used after usage of data shared by different cores. + * Such data is either statically marked with SHARED_DATA + * or dynamically allocated with SOF_MEM_FLAG_SHARED flag. + * Does nothing, since mt8195 doesn't support SMP. + */ + +static inline void *platform_rfree_prepare(void *ptr) +{ + return ptr; +} + +#endif + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +#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/mt8365/include/platform/lib/pm_runtime.h b/src/platform/mt8365/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..e93410938f30 --- /dev/null +++ b/src/platform/mt8365/include/platform/lib/pm_runtime.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include <stdint.h> + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +static inline 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_... + */ +static inline 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_... + */ +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/mt8365/include/platform/mt8365-afe-common.h b/src/platform/mt8365/include/platform/mt8365-afe-common.h new file mode 100644 index 000000000000..f597f6980da2 --- /dev/null +++ b/src/platform/mt8365/include/platform/mt8365-afe-common.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifndef _MT_8365_AFE_COMMON_H_ +#define _MT_8365_AFE_COMMON_H_ + +/* AFE: the abbreviation for Audio Front End */ + +enum { + MT8365_MEMIF_START, + MT8365_MEMIF_DL_START = MT8365_MEMIF_START, + MT8365_MEMIF_DL1 = MT8365_MEMIF_DL_START, + MT8365_MEMIF_DL2, + MT8365_MEMIF_TDM_OUT, + MT8365_MEMIF_DL_END, + MT8365_MEMIF_UL_START = MT8365_MEMIF_DL_END, + MT8365_MEMIF_AWB = MT8365_MEMIF_UL_START, + MT8365_MEMIF_VUL, + MT8365_MEMIF_VUL2, + MT8365_MEMIF_VUL3, + MT8365_MEMIF_TDM_IN, + MT8365_MEMIF_UL_END, + MT8365_MEMIF_END = MT8365_MEMIF_UL_END, + MT8365_MEMIF_DL_NUM = (MT8365_MEMIF_DL_END - MT8365_MEMIF_DL_START), + MT8365_MEMIF_UL_NUM = (MT8365_MEMIF_UL_END - MT8365_MEMIF_UL_START), + MT8365_MEMIF_NUM = (MT8365_MEMIF_END - MT8365_MEMIF_START), +}; + +enum { + MT8365_AFE_IRQ_1, + MT8365_AFE_IRQ_2, + MT8365_AFE_IRQ_3, + MT8365_AFE_IRQ_4, + MT8365_AFE_IRQ_5, + MT8365_AFE_IRQ_6, + MT8365_AFE_IRQ_7, + MT8365_AFE_IRQ_8, + MT8365_AFE_IRQ_9, + MT8365_AFE_IRQ_10, + MT8365_AFE_IRQ_NUM, +}; + +enum { + MT8365_AFE_IO_INT_ADDA_OUT, + MT8365_AFE_IO_2ND_I2S, + MT8365_AFE_IO_INT_ADDA_IN, + MT8365_AFE_IO_DMIC, + MT8365_DAI_NUM, +}; + +#endif /* _MT_8365_AFE_COMMON_H_ */ diff --git a/src/platform/mt8365/include/platform/mt8365-afe-regs.h b/src/platform/mt8365/include/platform/mt8365-afe-regs.h new file mode 100644 index 000000000000..8bd7163434dc --- /dev/null +++ b/src/platform/mt8365/include/platform/mt8365-afe-regs.h @@ -0,0 +1,1207 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifndef _MT8365_AFE_REGS_H_ +#define _MT8365_AFE_REGS_H_ + +#define AFE_REG_BASE 0x11220000 +#define AFE_REG_SIZE 0x1000 +#define AFE_SRAM_BASE 0x11221000 +#define AFE_SRAM_SIZE 0xA000 + +/***************************************************************************** + * R E G I S T E R D E F I N I T I O N + *****************************************************************************/ +#define AUDIO_TOP_CON0 (0x0000) +#define AUDIO_TOP_CON1 (0x0004) +#define AUDIO_TOP_CON2 (0x0008) +#define AUDIO_TOP_CON3 (0x000c) + +#define AFE_DAC_CON0 (0x0010) +#define AFE_DAC_CON1 (0x0014) +#define AFE_I2S_CON (0x0018) +#define AFE_CONN0 (0x0020) +#define AFE_CONN1 (0x0024) +#define AFE_CONN2 (0x0028) +#define AFE_CONN3 (0x002c) +#define AFE_CONN4 (0x0030) +#define AFE_I2S_CON1 (0x0034) +#define AFE_I2S_CON2 (0x0038) +#define AFE_MRGIF_CON (0x003c) +#define AFE_DL1_BASE (0x0040) +#define AFE_DL1_CUR (0x0044) +#define AFE_DL1_END (0x0048) +#define AFE_I2S_CON3 (0x004c) +#define AFE_DL2_BASE (0x0050) +#define AFE_DL2_CUR (0x0054) +#define AFE_DL2_END (0x0058) +#define AFE_CONN5 (0x005c) +#define AFE_AWB_BASE (0x0070) +#define AFE_AWB_END (0x0078) +#define AFE_AWB_CUR (0x007c) +#define AFE_VUL_BASE (0x0080) +#define AFE_VUL_END (0x0088) +#define AFE_VUL_CUR (0x008c) +#define AFE_CONN6 (0x00bc) +#define AFE_MEMIF_MSB (0x00cc) +#define AFE_MEMIF_MON0 (0x00d0) +#define AFE_MEMIF_MON1 (0x00d4) +#define AFE_MEMIF_MON2 (0x00d8) +#define AFE_MEMIF_MON3 (0x00dc) +#define AFE_MEMIF_MON4 (0x00e0) +#define AFE_MEMIF_MON5 (0x00e4) +#define AFE_MEMIF_MON6 (0x00e8) +#define AFE_MEMIF_MON7 (0x00ec) +#define AFE_MEMIF_MON8 (0x00f0) +#define AFE_MEMIF_MON9 (0x00f4) +#define AFE_MEMIF_MON10 (0x00f8) +#define AFE_MEMIF_MON11 (0x00fc) +#define AFE_ADDA_DL_SRC2_CON0 (0x0108) +#define AFE_ADDA_DL_SRC2_CON1 (0x010c) +#define AFE_ADDA_UL_SRC_CON0 (0x0114) +#define AFE_ADDA_UL_SRC_CON1 (0x0118) +#define AFE_ADDA_TOP_CON0 (0x0120) +#define AFE_ADDA_UL_DL_CON0 (0x0124) +#define AFE_ADDA_SRC_DEBUG (0x012c) +#define AFE_ADDA_SRC_DEBUG_MON0 (0x0130) +#define AFE_ADDA_SRC_DEBUG_MON1 (0x0134) +#define AFE_ADDA_UL_SRC_MON0 (0x0148) +#define AFE_ADDA_UL_SRC_MON1 (0x014c) +#define AFE_SRAM_BOUND (0x0170) +#define AFE_SECURE_CON (0x0174) +#define AFE_SECURE_CONN0 (0x0178) +#define AFE_SIDETONE_DEBUG (0x01d0) +#define AFE_SIDETONE_MON (0x01d4) +#define AFE_SIDETONE_CON0 (0x01e0) +#define AFE_SIDETONE_COEFF (0x01e4) +#define AFE_SIDETONE_CON1 (0x01e8) +#define AFE_SIDETONE_GAIN (0x01ec) +#define AFE_SGEN_CON0 (0x01f0) +#define AFE_SINEGEN_CON_TDM (0x01f8) +#define AFE_SINEGEN_CON_TDM_IN (0x01fc) +#define AFE_TOP_CON0 (0x0200) +#define AFE_BUS_CFG (0x0240) +#define AFE_BUS_MON0 (0x0244) +#define AFE_ADDA_PREDIS_CON0 (0x0260) +#define AFE_ADDA_PREDIS_CON1 (0x0264) +#define AFE_CONN_MON0 (0x0280) +#define AFE_CONN_MON1 (0x0284) +#define AFE_CONN_MON2 (0x0288) +#define AFE_CONN_MON3 (0x028c) +#define AFE_ADDA_IIR_COEF_02_01 (0x0290) +#define AFE_ADDA_IIR_COEF_04_03 (0x0294) +#define AFE_ADDA_IIR_COEF_06_05 (0x0298) +#define AFE_ADDA_IIR_COEF_08_07 (0x029c) +#define AFE_ADDA_IIR_COEF_10_09 (0x02a0) +#define AFE_VUL_D2_BASE (0x0350) +#define AFE_VUL_D2_END (0x0358) +#define AFE_VUL_D2_CUR (0x035c) +#define AFE_HDMI_OUT_CON0 (0x0370) +#define AFE_HDMI_OUT_BASE (0x0374) +#define AFE_HDMI_OUT_CUR (0x0378) +#define AFE_HDMI_OUT_END (0x037c) +#define AFE_SPDIF_OUT_CON0 (0x0380) +#define AFE_SPDIF_OUT_BASE (0x0384) +#define AFE_SPDIF_OUT_CUR (0x0388) +#define AFE_SPDIF_OUT_END (0x038c) +#define AFE_HDMI_CONN0 (0x0390) +#define AFE_HDMI_CONN1 (0x0398) +#define AFE_CONN_TDMIN_CON (0x039c) +#define AFE_IRQ_MCU_CON (0x03a0) +#define AFE_IRQ_MCU_STATUS (0x03a4) +#define AFE_IRQ_MCU_CLR (0x03a8) +#define AFE_IRQ_MCU_CNT1 (0x03ac) +#define AFE_IRQ_MCU_CNT2 (0x03b0) +#define AFE_IRQ_MCU_EN (0x03b4) +#define AFE_IRQ_MCU_MON2 (0x03b8) +#define AFE_IRQ_MCU_CNT5 (0x03bc) +#define AFE_IRQ1_MCU_CNT_MON (0x03c0) +#define AFE_IRQ2_MCU_CNT_MON (0x03c4) +#define AFE_IRQ1_MCU_EN_CNT_MON (0x03c8) +#define AFE_IRQ5_MCU_CNT_MON (0x03cc) +#define AFE_MEMIF_MINLEN (0x03d0) +#define AFE_MEMIF_MAXLEN (0x03d4) +#define AFE_MEMIF_PBUF_SIZE (0x03d8) +#define AFE_IRQ_MCU_CNT7 (0x03dc) +#define AFE_IRQ7_MCU_CNT_MON (0x03e0) +#define AFE_MEMIF_PBUF2_SIZE (0x03ec) +#define AFE_APLL_TUNER_CFG (0x03f0) +#define AFE_APLL_TUNER_CFG1 (0x03f4) +#define AFE_IRQ_MCU_CON2 (0x03f8) +#define IRQ13_MCU_CNT (0x0408) +#define IRQ13_MCU_CNT_MON (0x040c) +#define AFE_GAIN1_CON0 (0x0410) +#define AFE_GAIN1_CON1 (0x0414) +#define AFE_GAIN1_CON2 (0x0418) +#define AFE_GAIN1_CON3 (0x041c) +#define AFE_GAIN2_CON0 (0x0428) +#define AFE_GAIN2_CON1 (0x042c) +#define AFE_GAIN2_CON2 (0x0430) +#define AFE_GAIN2_CON3 (0x0434) +#define AFE_GAIN2_CUR (0x043c) +#define AFE_CONN11 (0x0448) +#define AFE_CONN12 (0x044c) +#define AFE_CONN13 (0x0450) +#define AFE_CONN14 (0x0454) +#define AFE_CONN15 (0x0458) +#define AFE_CONN16 (0x045c) +#define AFE_CONN7 (0x0460) +#define AFE_CONN8 (0x0464) +#define AFE_CONN9 (0x0468) +#define AFE_CONN10 (0x046c) +#define AFE_CONN21 (0x0470) +#define AFE_CONN22 (0x0474) +#define AFE_CONN23 (0x0478) +#define AFE_CONN24 (0x047c) +#define AFE_IEC_CFG (0x0480) +#define AFE_IEC_NSNUM (0x0484) +#define AFE_IEC_BURST_INFO (0x0488) +#define AFE_IEC_BURST_LEN (0x048c) +#define AFE_IEC_NSADR (0x0490) +#define AFE_CONN_RS (0x0494) +#define AFE_CONN_DI (0x0498) +#define AFE_IEC_CHL_STAT0 (0x04a0) +#define AFE_IEC_CHL_STAT1 (0x04a4) +#define AFE_IEC_CHR_STAT0 (0x04a8) +#define AFE_IEC_CHR_STAT1 (0x04ac) +#define AFE_CONN25 (0x04b0) +#define AFE_CONN26 (0x04b4) +#define FPGA_CFG2 (0x04b8) +#define FPGA_CFG3 (0x04bc) +#define FPGA_CFG0 (0x04c0) +#define FPGA_CFG1 (0x04c4) +#define AFE_SRAM_DELSEL_CON0 (0x04f0) +#define AFE_SRAM_DELSEL_CON1 (0x04f4) +#define AFE_SRAM_DELSEL_CON2 (0x04f8) +#define FPGA_CFG4 (0x04fc) +#define AFE_TDM_GASRC4_ASRC_2CH_CON0 (0x0500) +#define AFE_TDM_GASRC4_ASRC_2CH_CON1 (0x0504) +#define AFE_TDM_GASRC4_ASRC_2CH_CON2 (0x0508) +#define AFE_TDM_GASRC4_ASRC_2CH_CON3 (0x050c) +#define AFE_TDM_GASRC4_ASRC_2CH_CON4 (0x0510) +#define AFE_TDM_GASRC4_ASRC_2CH_CON5 (0x0514) +#define AFE_TDM_GASRC4_ASRC_2CH_CON6 (0x0518) +#define AFE_TDM_GASRC4_ASRC_2CH_CON7 (0x051c) +#define AFE_TDM_GASRC4_ASRC_2CH_CON8 (0x0520) +#define AFE_TDM_GASRC4_ASRC_2CH_CON9 (0x0524) +#define AFE_TDM_GASRC4_ASRC_2CH_CON10 (0x0528) +#define AFE_TDM_GASRC4_ASRC_2CH_CON12 (0x0530) +#define AFE_TDM_GASRC4_ASRC_2CH_CON13 (0x0534) +#define PCM_INTF_CON2 (0x0538) +#define PCM2_INTF_CON (0x053c) +#define AFE_APB_MON (0x0540) +#define AFE_CONN34 (0x0544) +#define AFE_TDM_CON1 (0x0548) +#define AFE_TDM_CON2 (0x054c) +#define PCM_INTF_CON1 (0x0550) +#define AFE_SECURE_MASK_CONN47_1 (0x0554) +#define AFE_SECURE_MASK_CONN48_1 (0x0558) +#define AFE_SECURE_MASK_CONN49_1 (0x055c) +#define AFE_SECURE_MASK_CONN50_1 (0x0560) +#define AFE_SECURE_MASK_CONN51_1 (0x0564) +#define AFE_SECURE_MASK_CONN52_1 (0x0568) +#define AFE_SECURE_MASK_CONN53_1 (0x056c) +#define AFE_SE_SECURE_CON (0x0570) +#define AFE_TDM_IN_CON1 (0x0588) +#define AFE_TDM_IN_CON2 (0x058c) +#define AFE_TDM_IN_MON1 (0x0590) +#define AFE_TDM_IN_MON2 (0x0594) +#define AFE_TDM_IN_MON3 (0x0598) +#define AFE_DMIC0_UL_SRC_CON0 (0x05b4) +#define AFE_DMIC0_UL_SRC_CON1 (0x05b8) +#define AFE_DMIC0_SRC_DEBUG (0x05bc) +#define AFE_DMIC0_SRC_DEBUG_MON0 (0x05c0) +#define AFE_DMIC0_UL_SRC_MON0 (0x05c8) +#define AFE_DMIC0_UL_SRC_MON1 (0x05cc) +#define AFE_DMIC0_IIR_COEF_02_01 (0x05d0) +#define AFE_DMIC0_IIR_COEF_04_03 (0x05d4) +#define AFE_DMIC0_IIR_COEF_06_05 (0x05d8) +#define AFE_DMIC0_IIR_COEF_08_07 (0x05dc) +#define AFE_DMIC0_IIR_COEF_10_09 (0x05e0) +#define AFE_DMIC1_UL_SRC_CON0 (0x0620) +#define AFE_DMIC1_UL_SRC_CON1 (0x0624) +#define AFE_DMIC1_SRC_DEBUG (0x0628) +#define AFE_DMIC1_SRC_DEBUG_MON0 (0x062c) +#define AFE_DMIC1_UL_SRC_MON0 (0x0634) +#define AFE_DMIC1_UL_SRC_MON1 (0x0638) +#define AFE_DMIC1_IIR_COEF_02_01 (0x063c) +#define AFE_DMIC1_IIR_COEF_04_03 (0x0640) +#define AFE_DMIC1_IIR_COEF_06_05 (0x0644) +#define AFE_DMIC1_IIR_COEF_08_07 (0x0648) +#define AFE_DMIC1_IIR_COEF_10_09 (0x064c) +#define AFE_SECURE_MASK_CONN39_1 (0x068c) +#define AFE_SECURE_MASK_CONN40_1 (0x0690) +#define AFE_SECURE_MASK_CONN41_1 (0x0694) +#define AFE_SECURE_MASK_CONN42_1 (0x0698) +#define AFE_SECURE_MASK_CONN43_1 (0x069c) +#define AFE_SECURE_MASK_CONN44_1 (0x06a0) +#define AFE_SECURE_MASK_CONN45_1 (0x06a4) +#define AFE_SECURE_MASK_CONN46_1 (0x06a8) +#define AFE_TDM_GASRC1_ASRC_2CH_CON0 (0x06c0) +#define AFE_TDM_GASRC1_ASRC_2CH_CON1 (0x06c4) +#define AFE_TDM_GASRC1_ASRC_2CH_CON2 (0x06c8) +#define AFE_TDM_GASRC1_ASRC_2CH_CON3 (0x06cc) +#define AFE_TDM_GASRC1_ASRC_2CH_CON4 (0x06d0) +#define AFE_TDM_GASRC1_ASRC_2CH_CON5 (0x06d4) +#define AFE_TDM_GASRC1_ASRC_2CH_CON6 (0x06d8) +#define AFE_TDM_GASRC1_ASRC_2CH_CON7 (0x06dc) +#define AFE_TDM_GASRC1_ASRC_2CH_CON8 (0x06e0) +#define AFE_TDM_GASRC1_ASRC_2CH_CON9 (0x06e4) +#define AFE_TDM_GASRC1_ASRC_2CH_CON10 (0x06e8) +#define AFE_TDM_GASRC1_ASRC_2CH_CON12 (0x06f0) +#define AFE_TDM_GASRC1_ASRC_2CH_CON13 (0x06f4) +#define AFE_TDM_ASRC_CON0 (0x06f8) +#define AFE_TDM_GASRC2_ASRC_2CH_CON0 (0x0700) +#define AFE_TDM_GASRC2_ASRC_2CH_CON1 (0x0704) +#define AFE_TDM_GASRC2_ASRC_2CH_CON2 (0x0708) +#define AFE_TDM_GASRC2_ASRC_2CH_CON3 (0x070c) +#define AFE_TDM_GASRC2_ASRC_2CH_CON4 (0x0710) +#define AFE_TDM_GASRC2_ASRC_2CH_CON5 (0x0714) +#define AFE_TDM_GASRC2_ASRC_2CH_CON6 (0x0718) +#define AFE_TDM_GASRC2_ASRC_2CH_CON7 (0x071c) +#define AFE_TDM_GASRC2_ASRC_2CH_CON8 (0x0720) +#define AFE_TDM_GASRC2_ASRC_2CH_CON9 (0x0724) +#define AFE_TDM_GASRC2_ASRC_2CH_CON10 (0x0728) +#define AFE_TDM_GASRC2_ASRC_2CH_CON12 (0x0730) +#define AFE_TDM_GASRC2_ASRC_2CH_CON13 (0x0734) +#define AFE_TDM_GASRC3_ASRC_2CH_CON0 (0x0740) +#define AFE_TDM_GASRC3_ASRC_2CH_CON1 (0x0744) +#define AFE_TDM_GASRC3_ASRC_2CH_CON2 (0x0748) +#define AFE_TDM_GASRC3_ASRC_2CH_CON3 (0x074c) +#define AFE_TDM_GASRC3_ASRC_2CH_CON4 (0x0750) +#define AFE_TDM_GASRC3_ASRC_2CH_CON5 (0x0754) +#define AFE_TDM_GASRC3_ASRC_2CH_CON6 (0x0758) +#define AFE_TDM_GASRC3_ASRC_2CH_CON7 (0x075c) +#define AFE_TDM_GASRC3_ASRC_2CH_CON8 (0x0760) +#define AFE_TDM_GASRC3_ASRC_2CH_CON9 (0x0764) +#define AFE_TDM_GASRC3_ASRC_2CH_CON10 (0x0768) +#define AFE_TDM_GASRC3_ASRC_2CH_CON12 (0x0770) +#define AFE_TDM_GASRC3_ASRC_2CH_CON13 (0x0774) +#define AFE_DMIC2_UL_SRC_CON0 (0x0780) +#define AFE_DMIC2_UL_SRC_CON1 (0x0784) +#define AFE_DMIC2_SRC_DEBUG (0x0788) +#define AFE_DMIC2_SRC_DEBUG_MON0 (0x078c) +#define AFE_DMIC2_UL_SRC_MON0 (0x0794) +#define AFE_DMIC2_UL_SRC_MON1 (0x0798) +#define AFE_DMIC2_IIR_COEF_02_01 (0x079c) +#define AFE_DMIC2_IIR_COEF_04_03 (0x07a0) +#define AFE_DMIC2_IIR_COEF_06_05 (0x07a4) +#define AFE_DMIC2_IIR_COEF_08_07 (0x07a8) +#define AFE_DMIC2_IIR_COEF_10_09 (0x07ac) +#define AFE_DMIC3_UL_SRC_CON0 (0x07ec) +#define AFE_DMIC3_UL_SRC_CON1 (0x07f0) +#define AFE_DMIC3_SRC_DEBUG (0x07f4) +#define AFE_DMIC3_SRC_DEBUG_MON0 (0x07f8) +#define AFE_DMIC3_UL_SRC_MON0 (0x0800) +#define AFE_DMIC3_UL_SRC_MON1 (0x0804) +#define AFE_DMIC3_IIR_COEF_02_01 (0x0808) +#define AFE_DMIC3_IIR_COEF_04_03 (0x080c) +#define AFE_DMIC3_IIR_COEF_06_05 (0x0810) +#define AFE_DMIC3_IIR_COEF_08_07 (0x0814) +#define AFE_DMIC3_IIR_COEF_10_09 (0x0818) +#define AFE_SECURE_MASK_CONN25_1 (0x0858) +#define AFE_SECURE_MASK_CONN26_1 (0x085c) +#define AFE_SECURE_MASK_CONN27_1 (0x0860) +#define AFE_SECURE_MASK_CONN28_1 (0x0864) +#define AFE_SECURE_MASK_CONN29_1 (0x0868) +#define AFE_SECURE_MASK_CONN30_1 (0x086c) +#define AFE_SECURE_MASK_CONN31_1 (0x0870) +#define AFE_SECURE_MASK_CONN32_1 (0x0874) +#define AFE_SECURE_MASK_CONN33_1 (0x0878) +#define AFE_SECURE_MASK_CONN34_1 (0x087c) +#define AFE_SECURE_MASK_CONN35_1 (0x0880) +#define AFE_SECURE_MASK_CONN36_1 (0x0884) +#define AFE_SECURE_MASK_CONN37_1 (0x0888) +#define AFE_SECURE_MASK_CONN38_1 (0x088c) +#define AFE_IRQ_MCU_SCP_EN (0x0890) +#define AFE_IRQ_MCU_DSP_EN (0x0894) +#define AFE_IRQ3_MCU_CNT_MON (0x0898) +#define AFE_IRQ4_MCU_CNT_MON (0x089c) +#define AFE_IRQ8_MCU_CNT_MON (0x08a0) +#define AFE_IRQ_MCU_CNT3 (0x08a4) +#define AFE_IRQ_MCU_CNT4 (0x08a8) +#define AFE_IRQ_MCU_CNT8 (0x08ac) +#define AFE_IRQ_MCU_CNT11 (0x08b0) +#define AFE_IRQ_MCU_CNT12 (0x08b4) +#define AFE_IRQ11_MCU_CNT_MON (0x08b8) +#define AFE_IRQ12_MCU_CNT_MON (0x08bc) +#define AFE_VUL3_BASE (0x08c0) +#define AFE_VUL3_CUR (0x08c4) +#define AFE_VUL3_END (0x08c8) +#define AFE_VUL3_BASE_MSB (0x08d0) +#define AFE_VUL3_END_MSB (0x08d4) +#define AFE_IRQ10_MCU_CNT_MON (0x08d8) +#define AFE_IRQ_MCU_CNT10 (0x08dc) +#define AFE_IRQ_ACC1_CNT (0x08e0) +#define AFE_IRQ_ACC2_CNT (0x08e4) +#define AFE_IRQ_ACC1_CNT_MON1 (0x08e8) +#define AFE_IRQ_ACC2_CNT_MON (0x08ec) +#define AFE_TSF_CON (0x08f0) +#define AFE_TSF_MON (0x08f4) +#define AFE_IRQ_ACC1_CNT_MON2 (0x08f8) +#define AFE_SPDIFIN_CFG0 (0x0900) +#define AFE_SPDIFIN_CFG1 (0x0904) +#define AFE_SPDIFIN_CHSTS1 (0x0908) +#define AFE_SPDIFIN_CHSTS2 (0x090c) +#define AFE_SPDIFIN_CHSTS3 (0x0910) +#define AFE_SPDIFIN_CHSTS4 (0x0914) +#define AFE_SPDIFIN_CHSTS5 (0x0918) +#define AFE_SPDIFIN_CHSTS6 (0x091c) +#define AFE_SPDIFIN_DEBUG1 (0x0920) +#define AFE_SPDIFIN_DEBUG2 (0x0924) +#define AFE_SPDIFIN_DEBUG3 (0x0928) +#define AFE_SPDIFIN_DEBUG4 (0x092c) +#define AFE_SPDIFIN_EC (0x0930) +#define AFE_SPDIFIN_CKLOCK_CFG (0x0934) +#define AFE_SPDIFIN_BR (0x093c) +#define AFE_SPDIFIN_BR_DBG1 (0x0940) +#define AFE_SPDIFIN_INT_EXT (0x0948) +#define AFE_SPDIFIN_INT_EXT2 (0x094c) +#define SPDIFIN_FREQ_INFO (0x0950) +#define SPDIFIN_FREQ_INFO_2 (0x0954) +#define SPDIFIN_FREQ_INFO_3 (0x0958) +#define SPDIFIN_FREQ_STATUS (0x095c) +#define SPDIFIN_USERCODE1 (0x0960) +#define SPDIFIN_USERCODE2 (0x0964) +#define SPDIFIN_USERCODE3 (0x0968) +#define SPDIFIN_USERCODE4 (0x096c) +#define SPDIFIN_USERCODE5 (0x0970) +#define SPDIFIN_USERCODE6 (0x0974) +#define SPDIFIN_USERCODE7 (0x0978) +#define SPDIFIN_USERCODE8 (0x097c) +#define SPDIFIN_USERCODE9 (0x0980) +#define SPDIFIN_USERCODE10 (0x0984) +#define SPDIFIN_USERCODE11 (0x0988) +#define SPDIFIN_USERCODE12 (0x098c) +#define SPDIFIN_MEMIF_CON0 (0x0990) +#define SPDIFIN_BASE_ADR (0x0994) +#define SPDIFIN_END_ADR (0x0998) +#define SPDIFIN_APLL_TUNER_CFG (0x09a0) +#define SPDIFIN_APLL_TUNER_CFG1 (0x09a4) +#define SPDIFIN_APLL2_TUNER_CFG (0x09a8) +#define SPDIFIN_APLL2_TUNER_CFG1 (0x09ac) +#define SPDIFIN_TYPE_DET (0x09b0) +#define MPHONE_MULTI_CON0 (0x09b4) +#define SPDIFIN_CUR_ADR (0x09b8) +#define AFE_SINEGEN_CON_SPDIFIN (0x09bc) +#define AFE_HDMI_IN_2CH_CON0 (0x09c0) +#define AFE_HDMI_IN_2CH_BASE (0x09c4) +#define AFE_HDMI_IN_2CH_END (0x09c8) +#define AFE_HDMI_IN_2CH_CUR (0x09cc) +#define AFE_MEMIF_BUF_MON0 (0x09d0) +#define AFE_MEMIF_BUF_MON1 (0x09d4) +#define AFE_MEMIF_BUF_MON2 (0x09d8) +#define AFE_MEMIF_BUF_MON3 (0x09dc) +#define AFE_MEMIF_BUF_MON6 (0x09e8) +#define AFE_MEMIF_BUF_MON7 (0x09ec) +#define AFE_MEMIF_BUF_MON8 (0x09f0) +#define AFE_MEMIF_BUF_MON10 (0x09f8) +#define AFE_MEMIF_BUF_MON11 (0x09fc) +#define SYSTOP_STC_CONFIG (0x0a00) +#define AUDIO_STC_STATUS (0x0a04) +#define SYSTOP_W_STC_H (0x0a08) +#define SYSTOP_W_STC_L (0x0a0c) +#define SYSTOP_R_STC_H (0x0a10) +#define SYSTOP_R_STC_L (0x0a14) +#define AUDIO_W_STC_H (0x0a18) +#define AUDIO_W_STC_L (0x0a1c) +#define AUDIO_R_STC_H (0x0a20) +#define AUDIO_R_STC_L (0x0a24) +#define SYSTOP_W_STC2_H (0x0a28) +#define SYSTOP_W_STC2_L (0x0a2c) +#define SYSTOP_R_STC2_H (0x0a30) +#define SYSTOP_R_STC2_L (0x0a34) +#define AUDIO_W_STC2_H (0x0a38) +#define AUDIO_W_STC2_L (0x0a3c) +#define AUDIO_R_STC2_H (0x0a40) +#define AUDIO_R_STC2_L (0x0a44) + +#define AFE_CONN17 (0x0a48) +#define AFE_CONN18 (0x0a4c) +#define AFE_CONN19 (0x0a50) +#define AFE_CONN20 (0x0a54) +#define AFE_CONN27 (0x0a58) +#define AFE_CONN28 (0x0a5c) +#define AFE_CONN29 (0x0a60) +#define AFE_CONN30 (0x0a64) +#define AFE_CONN31 (0x0a68) +#define AFE_CONN32 (0x0a6c) +#define AFE_CONN33 (0x0a70) +#define AFE_CONN35 (0x0a74) +#define AFE_CONN36 (0x0a78) +#define AFE_CONN37 (0x0a7c) +#define AFE_CONN38 (0x0a80) +#define AFE_CONN39 (0x0a84) +#define AFE_CONN40 (0x0a88) +#define AFE_CONN41 (0x0a8c) +#define AFE_CONN42 (0x0a90) +#define AFE_CONN44 (0x0a94) +#define AFE_CONN45 (0x0a98) +#define AFE_CONN46 (0x0a9c) +#define AFE_CONN47 (0x0aa0) +#define AFE_CONN_24BIT (0x0aa4) +#define AFE_CONN0_1 (0x0aa8) +#define AFE_CONN1_1 (0x0aac) +#define AFE_CONN2_1 (0x0ab0) +#define AFE_CONN3_1 (0x0ab4) +#define AFE_CONN4_1 (0x0ab8) +#define AFE_CONN5_1 (0x0abc) +#define AFE_CONN6_1 (0x0ac0) +#define AFE_CONN7_1 (0x0ac4) +#define AFE_CONN8_1 (0x0ac8) +#define AFE_CONN9_1 (0x0acc) +#define AFE_CONN10_1 (0x0ad0) +#define AFE_CONN11_1 (0x0ad4) +#define AFE_CONN12_1 (0x0ad8) +#define AFE_CONN13_1 (0x0adc) +#define AFE_CONN14_1 (0x0ae0) +#define AFE_CONN15_1 (0x0ae4) +#define AFE_CONN16_1 (0x0ae8) +#define AFE_CONN17_1 (0x0aec) +#define AFE_CONN18_1 (0x0af0) +#define AFE_CONN19_1 (0x0af4) +#define AFE_CONN43 (0x0af8) +#define AFE_CONN43_1 (0x0afc) +#define AFE_CONN21_1 (0x0b00) +#define AFE_CONN22_1 (0x0b04) +#define AFE_CONN23_1 (0x0b08) +#define AFE_CONN24_1 (0x0b0c) +#define AFE_CONN25_1 (0x0b10) +#define AFE_CONN26_1 (0x0b14) +#define AFE_CONN27_1 (0x0b18) +#define AFE_CONN28_1 (0x0b1c) +#define AFE_CONN29_1 (0x0b20) +#define AFE_CONN30_1 (0x0b24) +#define AFE_CONN31_1 (0x0b28) +#define AFE_CONN32_1 (0x0b2c) +#define AFE_CONN33_1 (0x0b30) +#define AFE_CONN34_1 (0x0b34) +#define AFE_CONN35_1 (0x0b38) +#define AFE_CONN36_1 (0x0b3c) +#define AFE_CONN37_1 (0x0b40) +#define AFE_CONN38_1 (0x0b44) +#define AFE_CONN39_1 (0x0b48) +#define AFE_CONN40_1 (0x0b4c) +#define AFE_CONN41_1 (0x0b50) +#define AFE_CONN42_1 (0x0b54) +#define AFE_CONN44_1 (0x0b58) +#define AFE_CONN45_1 (0x0b5c) +#define AFE_CONN46_1 (0x0b60) +#define AFE_CONN47_1 (0x0b64) +#define AFE_CONN_RS_1 (0x0b68) +#define AFE_CONN_DI_1 (0x0b6c) +#define AFE_CONN_24BIT_1 (0x0b70) +#define AFE_GAIN1_CUR (0x0b78) +#define AFE_CONN20_1 (0x0b7c) +#define AFE_DL1_BASE_MSB (0x0b80) +#define AFE_DL1_END_MSB (0x0b84) +#define AFE_DL2_BASE_MSB (0x0b88) +#define AFE_DL2_END_MSB (0x0b8c) +#define AFE_AWB_BASE_MSB (0x0b90) +#define AFE_AWB_END_MSB (0x0b94) +#define AFE_VUL_BASE_MSB (0x0ba0) +#define AFE_VUL_END_MSB (0x0ba4) +#define AFE_VUL_D2_BASE_MSB (0x0ba8) +#define AFE_VUL_D2_END_MSB (0x0bac) +#define AFE_HDMI_OUT_BASE_MSB (0x0bb8) +#define AFE_HDMI_OUT_END_MSB (0x0bbc) +#define AFE_HDMI_IN_2CH_BASE_MSB (0x0bc0) +#define AFE_HDMI_IN_2CH_END_MSB (0x0bc4) +#define AFE_SPDIF_OUT_BASE_MSB (0x0bc8) +#define AFE_SPDIF_OUT_END_MSB (0x0bcc) +#define SPDIFIN_BASE_MSB (0x0bd0) +#define SPDIFIN_END_MSB (0x0bd4) +#define AFE_DL1_CUR_MSB (0x0bd8) +#define AFE_DL2_CUR_MSB (0x0bdc) +#define AFE_AWB_CUR_MSB (0x0be8) +#define AFE_VUL_CUR_MSB (0x0bf8) +#define AFE_VUL_D2_CUR_MSB (0x0c04) +#define AFE_HDMI_OUT_CUR_MSB (0x0c0c) +#define AFE_HDMI_IN_2CH_CUR_MSB (0x0c10) +#define AFE_SPDIF_OUT_CUR_MSB (0x0c14) +#define SPDIFIN_CUR_MSB (0x0c18) +#define AFE_CONN_REG (0x0c20) +#define AFE_SECURE_MASK_CONN14_1 (0x0c24) +#define AFE_SECURE_MASK_CONN15_1 (0x0c28) +#define AFE_SECURE_MASK_CONN16_1 (0x0c2c) +#define AFE_SECURE_MASK_CONN17_1 (0x0c30) +#define AFE_SECURE_MASK_CONN18_1 (0x0c34) +#define AFE_SECURE_MASK_CONN19_1 (0x0c38) +#define AFE_SECURE_MASK_CONN20_1 (0x0c3c) +#define AFE_SECURE_MASK_CONN21_1 (0x0c40) +#define AFE_SECURE_MASK_CONN22_1 (0x0c44) +#define AFE_SECURE_MASK_CONN23_1 (0x0c48) +#define AFE_SECURE_MASK_CONN24_1 (0x0c4c) +#define AFE_ADDA_DL_SDM_DCCOMP_CON (0x0c50) +#define AFE_ADDA_DL_SDM_TEST (0x0c54) +#define AFE_ADDA_DL_DC_COMP_CFG0 (0x0c58) +#define AFE_ADDA_DL_DC_COMP_CFG1 (0x0c5c) +#define AFE_ADDA_DL_SDM_FIFO_MON (0x0c60) +#define AFE_ADDA_DL_SRC_LCH_MON (0x0c64) +#define AFE_ADDA_DL_SRC_RCH_MON (0x0c68) +#define AFE_ADDA_DL_SDM_OUT_MON (0x0c6c) +#define AFE_ADDA_DL_SDM_DITHER_CON (0x0c70) + +#define AFE_VUL3_CUR_MSB (0x0c78) +#define AFE_ASRC_2CH_CON0 (0x0c80) +#define AFE_ASRC_2CH_CON1 (0x0c84) +#define AFE_ASRC_2CH_CON2 (0x0c88) +#define AFE_ASRC_2CH_CON3 (0x0c8c) +#define AFE_ASRC_2CH_CON4 (0x0c90) +#define AFE_ASRC_2CH_CON5 (0x0c94) +#define AFE_ASRC_2CH_CON6 (0x0c98) +#define AFE_ASRC_2CH_CON7 (0x0c9c) +#define AFE_ASRC_2CH_CON8 (0x0ca0) +#define AFE_ASRC_2CH_CON9 (0x0ca4) +#define AFE_ASRC_2CH_CON10 (0x0ca8) +#define AFE_ASRC_2CH_CON12 (0x0cb0) +#define AFE_ASRC_2CH_CON13 (0x0cb4) + +#define AFE_PCM_TX_ASRC_2CH_CON0 (0x0cc0) +#define AFE_PCM_TX_ASRC_2CH_CON1 (0x0cc4) +#define AFE_PCM_TX_ASRC_2CH_CON2 (0x0cc8) +#define AFE_PCM_TX_ASRC_2CH_CON3 (0x0ccc) +#define AFE_PCM_TX_ASRC_2CH_CON4 (0x0cd0) +#define AFE_PCM_TX_ASRC_2CH_CON5 (0x0cd4) +#define AFE_PCM_TX_ASRC_2CH_CON6 (0x0cd8) +#define AFE_PCM_TX_ASRC_2CH_CON7 (0x0cdc) +#define AFE_PCM_TX_ASRC_2CH_CON8 (0x0ce0) +#define AFE_PCM_TX_ASRC_2CH_CON9 (0x0ce4) +#define AFE_PCM_TX_ASRC_2CH_CON10 (0x0ce8) +#define AFE_PCM_TX_ASRC_2CH_CON12 (0x0cf0) +#define AFE_PCM_TX_ASRC_2CH_CON13 (0x0cf4) +#define AFE_PCM_RX_ASRC_2CH_CON0 (0x0d00) +#define AFE_PCM_RX_ASRC_2CH_CON1 (0x0d04) +#define AFE_PCM_RX_ASRC_2CH_CON2 (0x0d08) +#define AFE_PCM_RX_ASRC_2CH_CON3 (0x0d0c) +#define AFE_PCM_RX_ASRC_2CH_CON4 (0x0d10) +#define AFE_PCM_RX_ASRC_2CH_CON5 (0x0d14) +#define AFE_PCM_RX_ASRC_2CH_CON6 (0x0d18) +#define AFE_PCM_RX_ASRC_2CH_CON7 (0x0d1c) +#define AFE_PCM_RX_ASRC_2CH_CON8 (0x0d20) +#define AFE_PCM_RX_ASRC_2CH_CON9 (0x0d24) +#define AFE_PCM_RX_ASRC_2CH_CON10 (0x0d28) +#define AFE_PCM_RX_ASRC_2CH_CON12 (0x0d30) +#define AFE_PCM_RX_ASRC_2CH_CON13 (0x0d34) + +#define AFE_ADDA_PREDIS_CON2 (0x0d40) +#define AFE_ADDA_PREDIS_CON3 (0x0d44) +#define AFE_SECURE_MASK_CONN4_1 (0x0d48) +#define AFE_SECURE_MASK_CONN5_1 (0x0d4c) +#define AFE_SECURE_MASK_CONN6_1 (0x0d50) +#define AFE_SECURE_MASK_CONN7_1 (0x0d54) +#define AFE_SECURE_MASK_CONN8_1 (0x0d58) +#define AFE_SECURE_MASK_CONN9_1 (0x0d5c) +#define AFE_SECURE_MASK_CONN10_1 (0x0d60) +#define AFE_SECURE_MASK_CONN11_1 (0x0d64) +#define AFE_SECURE_MASK_CONN12_1 (0x0d68) +#define AFE_SECURE_MASK_CONN13_1 (0x0d6c) +#define AFE_MEMIF_MON12 (0x0d70) +#define AFE_MEMIF_MON13 (0x0d74) +#define AFE_MEMIF_MON14 (0x0d78) +#define AFE_MEMIF_MON15 (0x0d7c) +#define AFE_SECURE_MASK_CONN42 (0x0dbc) +#define AFE_SECURE_MASK_CONN43 (0x0dc0) +#define AFE_SECURE_MASK_CONN44 (0x0dc4) +#define AFE_SECURE_MASK_CONN45 (0x0dc8) +#define AFE_SECURE_MASK_CONN46 (0x0dcc) +#define AFE_HD_ENGEN_ENABLE (0x0dd0) +#define AFE_SECURE_MASK_CONN47 (0x0dd4) +#define AFE_SECURE_MASK_CONN48 (0x0dd8) +#define AFE_SECURE_MASK_CONN49 (0x0ddc) +#define AFE_SECURE_MASK_CONN50 (0x0de0) +#define AFE_SECURE_MASK_CONN51 (0x0de4) +#define AFE_SECURE_MASK_CONN52 (0x0de8) +#define AFE_SECURE_MASK_CONN53 (0x0dec) +#define AFE_SECURE_MASK_CONN0_1 (0x0df0) +#define AFE_SECURE_MASK_CONN1_1 (0x0df4) +#define AFE_SECURE_MASK_CONN2_1 (0x0df8) +#define AFE_SECURE_MASK_CONN3_1 (0x0dfc) + +#define AFE_ADDA_MTKAIF_CFG0 (0x0e00) +#define AFE_ADDA_MTKAIF_SYNCWORD_CFG (0x0e14) +#define AFE_ADDA_MTKAIF_RX_CFG0 (0x0e20) +#define AFE_ADDA_MTKAIF_RX_CFG1 (0x0e24) +#define AFE_ADDA_MTKAIF_RX_CFG2 (0x0e28) +#define AFE_ADDA_MTKAIF_MON0 (0x0e34) +#define AFE_ADDA_MTKAIF_MON1 (0x0e38) +#define AFE_AUD_PAD_TOP (0x0e40) + +#define AFE_CM1_CON4 (0x0e48) +#define AFE_CM2_CON4 (0x0e4c) +#define AFE_CM1_CON0 (0x0e50) +#define AFE_CM1_CON1 (0x0e54) +#define AFE_CM1_CON2 (0x0e58) +#define AFE_CM1_CON3 (0x0e5c) +#define AFE_CM2_CON0 (0x0e60) +#define AFE_CM2_CON1 (0x0e64) +#define AFE_CM2_CON2 (0x0e68) +#define AFE_CM2_CON3 (0x0e6c) +#define AFE_CM2_CONN0 (0x0e70) +#define AFE_CM2_CONN1 (0x0e74) +#define AFE_CM2_CONN2 (0x0e78) + +#define AFE_GENERAL1_ASRC_2CH_CON0 (0x0e80) +#define AFE_GENERAL1_ASRC_2CH_CON1 (0x0e84) +#define AFE_GENERAL1_ASRC_2CH_CON2 (0x0e88) +#define AFE_GENERAL1_ASRC_2CH_CON3 (0x0e8c) +#define AFE_GENERAL1_ASRC_2CH_CON4 (0x0e90) +#define AFE_GENERAL1_ASRC_2CH_CON5 (0x0e94) +#define AFE_GENERAL1_ASRC_2CH_CON6 (0x0e98) +#define AFE_GENERAL1_ASRC_2CH_CON7 (0x0e9c) +#define AFE_GENERAL1_ASRC_2CH_CON8 (0x0ea0) +#define AFE_GENERAL1_ASRC_2CH_CON9 (0x0ea4) +#define AFE_GENERAL1_ASRC_2CH_CON10 (0x0ea8) +#define AFE_GENERAL1_ASRC_2CH_CON12 (0x0eb0) +#define AFE_GENERAL1_ASRC_2CH_CON13 (0x0eb4) +#define GENERAL_ASRC_MODE (0x0eb8) +#define GENERAL_ASRC_EN_ON (0x0ebc) + +#define AFE_CONN48 (0x0ec0) +#define AFE_CONN49 (0x0ec4) +#define AFE_CONN50 (0x0ec8) +#define AFE_CONN51 (0x0ecc) +#define AFE_CONN52 (0x0ed0) +#define AFE_CONN53 (0x0ed4) +#define AFE_CONN48_1 (0x0ee0) +#define AFE_CONN49_1 (0x0ee4) +#define AFE_CONN50_1 (0x0ee8) +#define AFE_CONN51_1 (0x0eec) +#define AFE_CONN52_1 (0x0ef0) +#define AFE_CONN53_1 (0x0ef4) + +#define AFE_GENERAL2_ASRC_2CH_CON0 (0x0f00) +#define AFE_GENERAL2_ASRC_2CH_CON1 (0x0f04) +#define AFE_GENERAL2_ASRC_2CH_CON2 (0x0f08) +#define AFE_GENERAL2_ASRC_2CH_CON3 (0x0f0c) +#define AFE_GENERAL2_ASRC_2CH_CON4 (0x0f10) +#define AFE_GENERAL2_ASRC_2CH_CON5 (0x0f14) +#define AFE_GENERAL2_ASRC_2CH_CON6 (0x0f18) +#define AFE_GENERAL2_ASRC_2CH_CON7 (0x0f1c) +#define AFE_GENERAL2_ASRC_2CH_CON8 (0x0f20) +#define AFE_GENERAL2_ASRC_2CH_CON9 (0x0f24) +#define AFE_GENERAL2_ASRC_2CH_CON10 (0x0f28) +#define AFE_GENERAL2_ASRC_2CH_CON12 (0x0f30) +#define AFE_GENERAL2_ASRC_2CH_CON13 (0x0f34) + +#define AFE_SECURE_MASK_CONN28 (0x0f48) +#define AFE_SECURE_MASK_CONN29 (0x0f4c) +#define AFE_SECURE_MASK_CONN30 (0x0f50) +#define AFE_SECURE_MASK_CONN31 (0x0f54) +#define AFE_SECURE_MASK_CONN32 (0x0f58) +#define AFE_SECURE_MASK_CONN33 (0x0f5c) +#define AFE_SECURE_MASK_CONN34 (0x0f60) +#define AFE_SECURE_MASK_CONN35 (0x0f64) +#define AFE_SECURE_MASK_CONN36 (0x0f68) +#define AFE_SECURE_MASK_CONN37 (0x0f6c) +#define AFE_SECURE_MASK_CONN38 (0x0f70) +#define AFE_SECURE_MASK_CONN39 (0x0f74) +#define AFE_SECURE_MASK_CONN40 (0x0f78) +#define AFE_SECURE_MASK_CONN41 (0x0f7c) +#define AFE_SIDEBAND0 (0x0f80) +#define AFE_SIDEBAND1 (0x0f84) +#define AFE_SECURE_SIDEBAND0 (0x0f88) +#define AFE_SECURE_SIDEBAND1 (0x0f8c) +#define AFE_SECURE_MASK_CONN0 (0x0f90) +#define AFE_SECURE_MASK_CONN1 (0x0f94) +#define AFE_SECURE_MASK_CONN2 (0x0f98) +#define AFE_SECURE_MASK_CONN3 (0x0f9c) +#define AFE_SECURE_MASK_CONN4 (0x0fa0) +#define AFE_SECURE_MASK_CONN5 (0x0fa4) +#define AFE_SECURE_MASK_CONN6 (0x0fa8) +#define AFE_SECURE_MASK_CONN7 (0x0fac) +#define AFE_SECURE_MASK_CONN8 (0x0fb0) +#define AFE_SECURE_MASK_CONN9 (0x0fb4) +#define AFE_SECURE_MASK_CONN10 (0x0fb8) +#define AFE_SECURE_MASK_CONN11 (0x0fbc) +#define AFE_SECURE_MASK_CONN12 (0x0fc0) +#define AFE_SECURE_MASK_CONN13 (0x0fc4) +#define AFE_SECURE_MASK_CONN14 (0x0fc8) +#define AFE_SECURE_MASK_CONN15 (0x0fcc) +#define AFE_SECURE_MASK_CONN16 (0x0fd0) +#define AFE_SECURE_MASK_CONN17 (0x0fd4) +#define AFE_SECURE_MASK_CONN18 (0x0fd8) +#define AFE_SECURE_MASK_CONN19 (0x0fdc) +#define AFE_SECURE_MASK_CONN20 (0x0fe0) +#define AFE_SECURE_MASK_CONN21 (0x0fe4) +#define AFE_SECURE_MASK_CONN22 (0x0fe8) +#define AFE_SECURE_MASK_CONN23 (0x0fec) +#define AFE_SECURE_MASK_CONN24 (0x0ff0) +#define AFE_SECURE_MASK_CONN25 (0x0ff4) +#define AFE_SECURE_MASK_CONN26 (0x0ff8) +#define AFE_SECURE_MASK_CONN27 (0x0ffc) + +#define MAX_REGISTER AFE_SECURE_MASK_CONN27 + +#define AFE_IRQ_STATUS_BITS 0x3ff + +/* AUDIO_TOP_CON0 (0x0000) */ +#define AUD_TCON0_PDN_TML BIT(27) +#define AUD_TCON0_PDN_DAC_PREDIS BIT(26) +#define AUD_TCON0_PDN_DAC BIT(25) +#define AUD_TCON0_PDN_ADC BIT(24) +#define AUD_TCON0_PDN_TDM_IN BIT(23) +#define AUD_TCON0_PDN_TDM_OUT BIT(22) +#define AUD_TCON0_PDN_SPDIF BIT(21) +#define AUD_TCON0_PDN_APLL_TUNER BIT(19) +#define AUD_TCON0_PDN_APLL2_TUNER BIT(18) +#define AUD_TCON0_PDN_INTDIR BIT(15) +#define AUD_TCON0_PDN_24M BIT(9) +#define AUD_TCON0_PDN_22M BIT(8) +#define AUD_TCON0_PDN_I2S_IN BIT(6) +#define AUD_TCON0_PDN_AFE BIT(2) + +/* AUDIO_TOP_CON1 (0x0004) */ +#define AUD_TCON1_PDN_TDM_ASRC BIT(15) +#define AUD_TCON1_PDN_GENERAL2_ASRC BIT(14) +#define AUD_TCON1_PDN_GENERAL1_ASRC BIT(13) +#define AUD_TCON1_PDN_CONNSYS_I2S_ASRC BIT(12) +#define AUD_TCON1_PDN_DMIC3_ADC BIT(11) +#define AUD_TCON1_PDN_DMIC2_ADC BIT(10) +#define AUD_TCON1_PDN_DMIC1_ADC BIT(9) +#define AUD_TCON1_PDN_DMIC0_ADC BIT(8) +#define AUD_TCON1_PDN_I2S4_BCLK BIT(7) +#define AUD_TCON1_PDN_I2S3_BCLK BIT(6) +#define AUD_TCON1_PDN_I2S2_BCLK BIT(5) +#define AUD_TCON1_PDN_I2S1_BCLK BIT(4) + +/* AUDIO_TOP_CON3 (0x000C) */ +#define AUD_TCON3_HDMI_BCK_INV BIT(3) + +/* AFE_I2S_CON (0x0018) */ +#define AFE_I2S_CON_PHASE_SHIFT_FIX BIT(31) +#define AFE_I2S_CON_FROM_IO_MUX BIT(28) +#define AFE_I2S_CON_LOW_JITTER_CLK BIT(12) +#define AFE_I2S_CON_RATE(x) (((x) & 0xf) << 8) +#define AFE_I2S_CON_FORMAT_I2S BIT(3) +#define AFE_I2S_CON_SRC_SLAVE BIT(2) + +/* AFE_ASRC_2CH_CON0 */ +#define ONE_HEART_MASK (0x1 << 31) +#define CHSET_STR_CLR (0x1<<4) +#define ASM_ON_MASK (0x1<<0) +#define ASM_ON (0x1<<0) + +/* CON2 */ +#define O16BIT_MASK (0x1<<19) +#define CLR_IIR_HISTORY_MASK (0x1<<17) +#define CLR_IIR_HISTORY (0x1<<17) +#define IS_MONO_MASK (0x1<<16) +#define IIR_EN_MASK (0x1<<11) +#define IIR_EN (0x1<<11) +#define IIR_DIS (0x0<<11) +#define IIR_STAGE_MASK (0x7<<8) +#define IIR_STAGE_8 (0x7<<8) + +/* CON5 */ +#define CALI_CYCLE_MASK (0xFFFF << 16) +#define CALI_64_CYCLE (0x3F << 16) +#define CALI_96_CYCLE (0x5F << 16) +#define CALI_441_CYCLE (0x1B8 << 16) + +#define CALI_AUTORST_MASK (0x1 << 15) +#define CALI_AUTORST_ENABLE (0x1 << 15) +#define CALI_AUTORST_DISABLE (0x0 << 15) + +#define AUTO_TUNE_FREQ5_MASK (0x1 << 12) +#define AUTO_TUNE_FREQ5_ENABLE (0x1 << 12) +#define AUTO_TUNE_FREQ5_DISABLE (0x0 << 12) + +#define COMP_FREQ_RES_MASK (0x1 << 11) +#define COMP_FREQ_RES_ENABLE (0x1 << 11) + +#define CALI_SEL_MASK (0x3 << 8) +#define CALI_SEL_00 (0x0 << 8) +#define CALI_SEL_01 (0x1 << 8) + +#define CALI_BP_DGL_MASK (0x1 << 7) +#define CALI_BP_DGL_BYPASS (0x1 << 7) + +#define AUTO_TUNE_FREQ4_MASK (0x1 << 3) +#define AUTO_TUNE_FREQ4_ENABLE (0x1 << 3) +#define AUTO_TUNE_FREQ4_DISABLE (0x0 << 3) + +#define CALI_AUTO_RESTART_MASK (0x1 << 2) +#define CALI_AUTO_RESTART_ENABLE (0x1 << 2) + +#define CALI_USE_FREQ_OUT_MASK (0x1 << 1) +#define CALI_USE_FREQ (0x1 << 1) +#define CALI_USE_PERIOD (0x0 << 1) + +#define CALI_ON_MASK (0x1 << 0) +#define CALI_ON (0x1 << 0) +#define CALI_OFF (0x0 << 0) + + +#define AFE_I2S_CON_WLEN_32BIT BIT(1) +#define AFE_I2S_CON_EN BIT(0) + +#define AFE_CONN3_I03_O03_S BIT(3) +#define AFE_CONN4_I04_O04_S BIT(4) +#define AFE_CONN4_I03_O04_S BIT(3) + +/* AFE_I2S_CON1 (0x0034) */ +#define AFE_I2S_CON1_I2S2_TO_PAD (1 << 18) +#define AFE_I2S_CON1_TDMOUT_TO_PAD (0 << 18) +#define AFE_I2S_CON1_TDMOUT_MUX_MASK GENMASK(18, 18) +#define AFE_I2S_CON1_LOW_JITTER_CLK BIT(12) +#define AFE_I2S_CON1_RATE(x) (((x) & 0xf) << 8) +#define AFE_I2S_CON1_FORMAT_I2S BIT(3) +#define AFE_I2S_CON1_WLEN_32BIT BIT(1) +#define AFE_I2S_CON1_EN BIT(0) + +/* AFE_I2S_CON2 (0x0038) */ +#define AFE_I2S_CON2_LOW_JITTER_CLK BIT(12) +#define AFE_I2S_CON2_RATE(x) (((x) & 0xf) << 8) +#define AFE_I2S_CON2_FORMAT_I2S BIT(3) +#define AFE_I2S_CON2_WLEN_32BIT BIT(1) +#define AFE_I2S_CON2_EN BIT(0) + +/* AFE_I2S_CON3 (0x004C) */ +#define AFE_I2S_CON3_LOW_JITTER_CLK BIT(12) +#define AFE_I2S_CON3_RATE(x) (((x) & 0xf) << 8) +#define AFE_I2S_CON3_FORMAT_I2S BIT(3) +#define AFE_I2S_CON3_WLEN_32BIT BIT(1) +#define AFE_I2S_CON3_EN BIT(0) + +/* AFE_ADDA_DL_SRC2_CON0 (0x0108) */ +#define AFE_ADDA_DL_8X_UPSAMPLE (BIT(25) | BIT(24)) +#define AFE_ADDA_DL_MUTE_OFF (BIT(12) | BIT(11)) +#define AFE_ADDA_DL_VOICE_DATA BIT(5) +#define AFE_ADDA_DL_DEGRADE_GAIN BIT(1) + +/* AFE_ADDA_UL_DL_CON0 */ +#define AFE_ADDA_UL_DL_ADDA_AFE_ON_MASK BIT(0) +#define AFE_ADDA_UL_DL_ADDA_AFE_ON (1 << 0) +#define AFE_ADDA_UL_DL_ADDA_AFE_OFF (0 << 0) +#define AFE_ADDA_UL_DL_DMIC_CLKDIV_ON_MASK BIT(1) +#define AFE_ADDA_UL_DL_DMIC_CLKDIV_ON (1 << 1) +#define AFE_ADDA_UL_DL_DMIC_CLKDIV_OFF (0 << 1) + +/* AFE_SINEGEN_CON0 (0x01f0) */ +#define AFE_SINEGEN_CON0_EN BIT(26) +#define AFE_SINEGEN_CON0_IN_OUT_SEL BIT(27) +#define AFE_SINEGEN_CON0_MODE_MASK GENMASK(31, 28) +#define AFE_SINEGEN_CON0_AMP_DIV_CH2_MASK GENMASK(19, 17) +#define AFE_SINEGEN_CON0_AMP_DIV_CH1_MASK GENMASK(7, 5) +#define AFE_SINEGEN_CON0_AMP_DIV_CH2(x) (((x) & 0x7) << 17) +#define AFE_SINEGEN_CON0_AMP_DIV_CH1(x) (((x) & 0x7) << 5) +#define AFE_SINEGEN_CON0_FREQ_DIV_CH2_MASK GENMASK(16, 12) +#define AFE_SINEGEN_CON0_FREQ_DIV_CH1_MASK GENMASK(4, 0) +#define AFE_SINEGEN_CON0_FREQ_DIV_CH2(x) (((x) & 0x1f) << 12) +#define AFE_SINEGEN_CON0_FREQ_DIV_CH1(x) (((x) & 0x1f) << 0) +#define AFE_SINEGEN_CON0_TIMING_CH2_MASK GENMASK(23, 20) +#define AFE_SINEGEN_CON0_TIMING_CH1_MASK GENMASK(11, 8) +#define AFE_SINEGEN_CON0_TIMING_CH2(x) (((x) & 0xf) << 20) +#define AFE_SINEGEN_CON0_TIMING_CH1(x) (((x) & 0xf) << 8) +#define AFE_SINEGEN_CON0_TIMING_8K (0) +#define AFE_SINEGEN_CON0_TIMING_11D025K (1) +#define AFE_SINEGEN_CON0_TIMING_12K (2) +#define AFE_SINEGEN_CON0_TIMING_16K (4) +#define AFE_SINEGEN_CON0_TIMING_22D05K (5) +#define AFE_SINEGEN_CON0_TIMING_24K (6) +#define AFE_SINEGEN_CON0_TIMING_32K (8) +#define AFE_SINEGEN_CON0_TIMING_44D1K (9) +#define AFE_SINEGEN_CON0_TIMING_48K (10) +#define AFE_SINEGEN_CON0_TIMING_88D2K (11) +#define AFE_SINEGEN_CON0_TIMING_96K (12) +#define AFE_SINEGEN_CON0_TIMING_176D4K (13) +#define AFE_SINEGEN_CON0_TIMING_192K (14) + +/* AFE_HDMI_OUT_CON0 (0x0370) */ +#define AFE_HDMI_OUT_CON0_CH_MASK GENMASK(7, 4) + +/* AFE_HDMI_CONN0 (0x0390) */ +#define AFE_HDMI_CONN0_O35_I35 (0x7 << 21) +#define AFE_HDMI_CONN0_O34_I34 (0x6 << 18) +#define AFE_HDMI_CONN0_O33_I33 (0x5 << 15) +#define AFE_HDMI_CONN0_O32_I32 (0x4 << 12) +#define AFE_HDMI_CONN0_O31_I30 (0x2 << 9) +#define AFE_HDMI_CONN0_O31_I31 (0x3 << 9) +#define AFE_HDMI_CONN0_O30_I31 (0x3 << 6) +#define AFE_HDMI_CONN0_O30_I30 (0x2 << 6) +#define AFE_HDMI_CONN0_O29_I29 (0x1 << 3) +#define AFE_HDMI_CONN0_O28_I28 (0x0 << 0) + +/* AFE_CONN_TDMIN_CON (0x039c) */ +#define AFE_CONN_TDMIN_O41_I41 (0x1 << 3) +#define AFE_CONN_TDMIN_O41_I40 (0x0 << 3) +#define AFE_CONN_TDMIN_O40_I41 (0x1 << 0) +#define AFE_CONN_TDMIN_O40_I40 (0x0 << 0) +#define AFE_CONN_TDMIN_CON0_MASK GENMASK(5, 0) + +/* AFE_APLL_TUNER_CFG (0x03f0) */ +#define AFE_APLL_TUNER_CFG_MASK GENMASK(15, 1) +#define AFE_APLL_TUNER_CFG_EN_MASK GENMASK(0, 0) + +/* AFE_APLL_TUNER_CFG1 (0x03f4) */ +#define AFE_APLL_TUNER_CFG1_MASK GENMASK(15, 1) +#define AFE_APLL_TUNER_CFG1_EN_MASK GENMASK(0, 0) + +/* AFE_TDM_CON1 (0x0548) */ +#define AFE_TDM_CON1_LRCK_WIDTH(x) (((x) - 1) << 24) +#define AFE_TDM_CON1_32_BCK_CYCLES (0x2 << 12) +#define AFE_TDM_CON1_16_BCK_CYCLES (0x0 << 12) +#define AFE_TDM_CON1_8CH_PER_SDATA (0x2 << 10) +#define AFE_TDM_CON1_4CH_PER_SDATA (0x1 << 10) +#define AFE_TDM_CON1_2CH_PER_SDATA (0x0 << 10) +#define AFE_TDM_CON1_WLEN_32BIT BIT(9) +#define AFE_TDM_CON1_WLEN_16BIT BIT(8) +#define AFE_TDM_CON1_MSB_ALIGNED BIT(4) +#define AFE_TDM_CON1_1_BCK_DELAY BIT(3) +#define AFE_TDM_CON1_LRCK_INV BIT(2) +#define AFE_TDM_CON1_EN BIT(0) + +/* AFE_TDM_CON2 (0x054c) */ +#define AFE_TDM_CON2_SOUT_MASK GENMASK(14, 0) + +/* PCM_INTF_CON1 (0x0550) */ +#define PCM_INTF_CON1_EXT_MODEM (1 << 17) +#define PCM_INTF_CON1_16BIT (0 << 16) +#define PCM_INTF_CON1_24BIT (1 << 16) +#define PCM_INTF_CON1_32BCK (0 << 14) +#define PCM_INTF_CON1_64BCK (1 << 14) +#define PCM_INTF_CON1_MASTER_MODE (0 << 5) +#define PCM_INTF_CON1_SLAVE_MODE (1 << 5) +#define PCM_INTF_CON1_FS_8K (0 << 3) +#define PCM_INTF_CON1_FS_16K (1 << 3) +#define PCM_INTF_CON1_FS_32K (2 << 3) +#define PCM_INTF_CON1_FS_48K (3 << 3) +#define PCM_INTF_CON1_SYNC_LEN(x) (((x) - 1) << 9) +#define PCM_INTF_CON1_FORMAT(x) ((x) << 1) +#define PCM_INTF_CON1_SYNC_OUT_INV BIT(23) +#define PCM_INTF_CON1_BCLK_OUT_INV BIT(22) +#define PCM_INTF_CON1_SYNC_IN_INV BIT(21) +#define PCM_INTF_CON1_BCLK_IN_INV BIT(20) +#define PCM_INTF_CON1_BYPASS_ASRC BIT(6) +#define PCM_INTF_CON1_EN BIT(0) +#define PCM_INTF_CON1_CONFIG_MASK (0xf3fffe) + +/* AFE_TDM_IN_CON1 (0x0588) */ +#define AFE_TDM_IN_CON1_LRCK_WIDTH(x) (((x) - 1) << 24) +#define AFE_TDM_IN_CON1_FAST_LRCK_CYCLE_32BCK (0x2 << 16) +#define AFE_TDM_IN_CON1_FAST_LRCK_CYCLE_16BCK (0x0 << 16) +#define AFE_TDM_IN_CON1_8CH_PER_SDATA (0x2 << 12) +#define AFE_TDM_IN_CON1_4CH_PER_SDATA (0x1 << 12) +#define AFE_TDM_IN_CON1_2CH_PER_SDATA (0x0 << 12) +#define AFE_TDM_IN_CON1_WLEN_32BIT (0x3 << 8) +#define AFE_TDM_IN_CON1_WLEN_24BIT (0x2 << 8) +#define AFE_TDM_IN_CON1_WLEN_16BIT (0x1 << 8) +#define AFE_TDM_IN_CON1_I2S BIT(3) +#define AFE_TDM_IN_CON1_LRCK_INV BIT(2) +#define AFE_TDM_IN_CON1_BCK_INV BIT(1) +#define AFE_TDM_IN_CON1_EN BIT(0) + +/* AFE_TDM_IN_CON2 (0x058c) */ +#define AFE_TDM_IN_CON2_DISABLE_CH01 BIT(0) +#define AFE_TDM_IN_CON2_DISABLE_CH23 BIT(1) +#define AFE_TDM_IN_CON2_DISABLE_CH45 BIT(2) +#define AFE_TDM_IN_CON2_DISABLE_CH67 BIT(3) + +/* AFE_DMIC0_UL_SRC_CON0 (0x05b4) + * AFE_DMIC0_UL_SRC_CON0 (0x0620) + * AFE_DMIC0_UL_SRC_CON0 (0x0780) + * AFE_DMIC0_UL_SRC_CON0 (0x07ec) + */ +#define DMIC_TOP_CON_DMIC_TWO_WIRE_MODE BIT(23) +#define DMIC_TOP_CON_DMIC_CK_PHASE_SEL_CH2(x) ((x) << 24) +#define DMIC_TOP_CON_DMIC_CK_PHASE_SEL_CH1(x) ((x) << 27) +#define DMIC_TOP_CON_DMIC_CH2_ON_MASK BIT(22) +#define DMIC_TOP_CON_DMIC_CH2_ON (1 << 22) +#define DMIC_TOP_CON_DMIC_CH2_OFF (0 << 22) +#define DMIC_TOP_CON_DMIC_CH1_ON_MASK BIT(21) +#define DMIC_TOP_CON_DMIC_CH1_ON (1 << 21) +#define DMIC_TOP_CON_DMIC_CH1_OFF (0 << 21) +#define DMIC_TOP_CON_DMIC_VOICE_MODE_8K (0 << 17) +#define DMIC_TOP_CON_DMIC_VOICE_MODE_16K (1 << 17) +#define DMIC_TOP_CON_DMIC_VOICE_MODE_32K (2 << 17) +#define DMIC_TOP_CON_DMIC_VOICE_MODE_48K (3 << 17) +#define DMIC_TOP_CON_DMIC_NO_LOW_POWER_MODE (0 << 14) +#define DMIC_TOP_CON_DMIC_LOW_POWER_MODE(x) ((x) << 14) +#define DMIC_TOP_CON_DMIC_IIR_ON BIT(10) +#define DMIC_TOP_CON_DMIC_INPUT_MODE(x) ((x) << 5) +#define DMIC_TOP_CON_DMIC_IIR_MODE(x) ((x) << 7) +#define DMIC_TOP_CON_DMIC_SDM3_LEVEL_MODE BIT(1) +#define DMIC_TOP_CON_DMIC_SRC_ON_MASK BIT(0) +#define DMIC_TOP_CON_DMIC_SRC_ON (1 << 0) +#define DMIC_TOP_CON_DMIC_SRC_OFF (0 << 0) +#define DMIC_TOP_CON_DMIC_SDM3_DE_SELECT (0 << 1) +#define DMIC_TOP_CON_CONFIG_MASK (0x3f8ed7a6) + +/* AFE_TDM_ASRC_CON0 (0x06f8)*/ +#define TDM_ASRC_OUT_MODE(x) ((x) << 4) +#define TDM_ASRC_OUT_MODE_MASK GENMASK(7, 4) +#define TDM_ASRC_OUT_SEL BIT(2) +#define TDM_ASRC_OUT_SEL_TO_CM1 (0 << 2) +#define TDM_ASRC_OUT_SEL_TO_CM2 (1 << 2) +#define TDM_ASRC_IN_SEL_FROM_TDMIN (0 << 1) +#define TDM_ASRC_IN_SEL_FROM_TDMOUT (1 << 1) +#define TDM_ASRC_IN_SEL_MASK BIT(1) +#define TDM_ASRC_EN_ON BIT(0) + +/* AFE_CONN_24BIT (0x0AA4) */ +#define AFE_CONN_24BIT_O10 BIT(10) +#define AFE_CONN_24BIT_O09 BIT(9) +#define AFE_CONN_24BIT_O06 BIT(6) +#define AFE_CONN_24BIT_O05 BIT(5) +#define AFE_CONN_24BIT_O04 BIT(4) +#define AFE_CONN_24BIT_O03 BIT(3) +#define AFE_CONN_24BIT_O02 BIT(2) +#define AFE_CONN_24BIT_O01 BIT(1) +#define AFE_CONN_24BIT_O00 BIT(0) + +/* AFE_HD_ENGEN_ENABLE */ +#define AFE_22M_PLL_EN BIT(0) +#define AFE_22M_PLL_ON (1 << 0) +#define AFE_22M_PLL_OFF (0 << 0) +#define AFE_24M_PLL_EN BIT(1) +#define AFE_24M_PLL_ON (1 << 1) +#define AFE_24M_PLL_OFF (0 << 1) + +/* AFE_GAIN1_CON0 (0x0410) */ +#define AFE_GAIN1_CON0_EN_MASK GENMASK(0, 0) +#define AFE_GAIN1_CON0_MODE_MASK GENMASK(7, 4) +#define AFE_GAIN1_CON0_SAMPLE_PER_STEP_MASK GENMASK(15, 8) + +/* AFE_GAIN1_CON1 (0x0414) */ +#define AFE_GAIN1_CON1_MASK GENMASK(19, 0) + +/* AFE_GAIN1_CUR (0x0B78) */ +#define AFE_GAIN1_CUR_MASK GENMASK(19, 0) + +/* AFE_CM1_CON0 (0x0e50) */ +/* AFE_CM2_CON0 (0x0e60) */ +#define CM_AFE_CM_CH_NUM(x) (((x) - 1) << 0) +#define CM_AFE_CM_CH_NUM_MASK GENMASK(3, 0) +#define CM_AFE_CM_ON BIT(4) +#define CM_AFE_CM_OFF (0 << 4) +#define CM_AFE_CM_START_DATA(x) ((x) << 8) +#define CM_AFE_CM_START_DATA_MASK GENMASK(11, 8) + +#define CM_AFE_CM1_VUL_SEL_CM1_OUTPUT (0 << 12) +#define CM_AFE_CM1_VUL_SEL_O17_O18 (1 << 12) +#define CM_AFE_CM1_VUL_SEL BIT(12) +#define CM_AFE_CM1_IN_MODE(x) ((x) << 16) +#define CM_AFE_CM1_IN_MODE_MASK GENMASK(19, 16) +#define CM_AFE_CM2_TDM_SEL_CM2_OUTPUT (1 << 12) +#define CM_AFE_CM2_TDM_SEL_TDM (0 << 12) +#define CM_AFE_CM2_TDM_SEL BIT(12) +#define CM_AFE_CM2_CLK_SEL_24M (0 << 13) +#define CM_AFE_CM2_CLK_SEL_22M (1 << 13) +#define CM_AFE_CM2_CLK_SEL BIT(13) +#define CM_AFE_CM2_GASRC1_OUT_SEL BIT(17) +#define CM_AFE_CM2_GASRC2_OUT_SEL BIT(16) +#define GASRC1_OUT_TO_TDM_OUT_EN (0 << 17) +#define GASRC1_OUT_TO_ENGEN_OUT_EN (1 << 17) +#define GASRC2_OUT_TO_TDM_OUT_EN (0 << 16) +#define GASRC2_OUT_TO_ENGEN_OUT_EN (1 << 16) + +/* AFE_CM2_CONN* */ +#define CM2_AFE_CM2_CONN_CFG1(x) ((x) << 0) +#define CM2_AFE_CM2_CONN_CFG1_MASK GENMASK(4, 0) +#define CM2_AFE_CM2_CONN_CFG2(x) ((x) << 5) +#define CM2_AFE_CM2_CONN_CFG2_MASK GENMASK(9, 5) +#define CM2_AFE_CM2_CONN_CFG3(x) ((x) << 10) +#define CM2_AFE_CM2_CONN_CFG3_MASK GENMASK(14, 10) +#define CM2_AFE_CM2_CONN_CFG4(x) ((x) << 15) +#define CM2_AFE_CM2_CONN_CFG4_MASK GENMASK(19, 15) +#define CM2_AFE_CM2_CONN_CFG5(x) ((x) << 20) +#define CM2_AFE_CM2_CONN_CFG5_MASK GENMASK(24, 20) +#define CM2_AFE_CM2_CONN_CFG6(x) ((x) << 25) +#define CM2_AFE_CM2_CONN_CFG6_MASK GENMASK(29, 25) +#define CM2_AFE_CM2_CONN_CFG7(x) ((x) << 0) +#define CM2_AFE_CM2_CONN_CFG7_MASK GENMASK(4, 0) +#define CM2_AFE_CM2_CONN_CFG8(x) ((x) << 5) +#define CM2_AFE_CM2_CONN_CFG8_MASK GENMASK(9, 5) +#define CM2_AFE_CM2_CONN_CFG9(x) ((x) << 10) +#define CM2_AFE_CM2_CONN_CFG9_MASK GENMASK(14, 10) +#define CM2_AFE_CM2_CONN_CFG10(x) ((x) << 15) +#define CM2_AFE_CM2_CONN_CFG10_MASK GENMASK(19, 15) +#define CM2_AFE_CM2_CONN_CFG11(x) ((x) << 20) +#define CM2_AFE_CM2_CONN_CFG11_MASK GENMASK(24, 20) +#define CM2_AFE_CM2_CONN_CFG12(x) ((x) << 25) +#define CM2_AFE_CM2_CONN_CFG12_MASK GENMASK(29, 25) +#define CM2_AFE_CM2_CONN_CFG13(x) ((x) << 0) +#define CM2_AFE_CM2_CONN_CFG13_MASK GENMASK(4, 0) +#define CM2_AFE_CM2_CONN_CFG14(x) ((x) << 5) +#define CM2_AFE_CM2_CONN_CFG14_MASK GENMASK(9, 5) +#define CM2_AFE_CM2_CONN_CFG15(x) ((x) << 10) +#define CM2_AFE_CM2_CONN_CFG15_MASK GENMASK(14, 10) +#define CM2_AFE_CM2_CONN_CFG16(x) ((x) << 15) +#define CM2_AFE_CM2_CONN_CFG16_MASK GENMASK(19, 15) + +/* AFE_CM1_CON* */ +#define CM_AFE_CM_UPDATE_CNT1(x) (((x) & (0xffff)) << 0) +#define CM_AFE_CM_UPDATE_CNT2(x) (((x) & (0xffff)) << 16) +#define CM_AFE_CM_UPDATE_CNT1_MASK GENMASK(15, 0) +#define CM_AFE_CM_UPDATE_CNT2_MASK GENMASK(31, 16) +#define CM_AFE_CM_UPDATE_CNT_MASK GENMASK(31, 0) + +/* AFE_CM2_CON0 (0x0e60)*/ +#define GASRC_ASRC1_OUT_EN_SEL BIT(17) +#define GASRC_ASRC2_OUT_EN_SEL BIT(16) + + +/* AFE_GENERAL1_ASRC_2CH_CON0 (0x0e80) + * AFE_GENERAL2_ASRC_2CH_CON0 (0x0f00) + */ +#define GASRC_CON0_CHSET0_CLR_IIR_HISTORY BIT(17) +#define GASRC_NEW_CON0_CHSET0_OFS_SEL_MASK GENMASK(15, 14) +#define GASRC_NEW_CON0_CHSET0_OFS_SEL_TX (0 << 14) +#define GASRC_NEW_CON0_CHSET0_OFS_SEL_RX (1 << 14) +#define GASRC_NEW_CON0_CHSET0_IFS_SEL_MASK GENMASK(13, 12) +#define GASRC_NEW_CON0_CHSET0_IFS_SEL_TX (3 << 12) +#define GASRC_NEW_CON0_CHSET0_IFS_SEL_RX (2 << 12) +#define GASRC_CON0_CHSET_IIR_EN BIT(11) +#define GASRC_CON0_CHSET_IIR_STAGE(x) ((x) << 8) +#define GASRC_CON0_CHSET_IIR_STAGE_MASK GENMASK(10, 8) +#define GASRC_CON0_CHSET_STR_CLR BIT(4) +#define GASRC_CON0_COEFF_SRAM_CTRL BIT(1) +#define GASRC_CON0_ASM_ON BIT(0) + +/* GENERAL_ASRC_MODE (0x0eb8) */ +#define GASRC_MODE_GASRC1_IN_MODE(x) (((x) & 0xf) << 0) +#define GASRC_MODE_GASRC2_IN_MODE(x) (((x) & 0xf) << 8) +#define GASRC_MODE_GASRC1_IN_MODE_MASK GENMASK(3, 0) +#define GASRC_MODE_GASRC2_IN_MODE_MASK GENMASK(11, 8) +#define GASRC_MODE_GASRC1_OUT_MODE(x) (((x) & 0xf) << 4) +#define GASRC_MODE_GASRC2_OUT_MODE(x) (((x) & 0xf) << 12) +#define GASRC_MODE_GASRC1_OUT_MODE_MASK GENMASK(7, 4) +#define GASRC_MODE_GASRC2_OUT_MODE_MASK GENMASK(15, 12) + +/* GENERAL_ASRC_EN_ON (0x0ebc) */ +#define GASRC_EN_ON_MASK(x) (0x1 << (x)) +#define GASRC_EN_ON(x) (0x1 << (x)) +#define GASRC_EN_OFF(x) (0x0 << (x)) + +/* AFE_GENERAL1_ASRC_2CH_CON5 (0x0e94) + * AFE_GENERAL2_ASRC_2CH_CON5 (0x0f14) + */ +#define GASRC_CON5_CALI_CYCLE_MASK GENMASK(31, 16) +#define GASRC_CON5_CALI_64_CYCLE (0x3F << 16) +#define GASRC_CON5_CALI_96_CYCLE (0x5F << 16) +#define GASRC_CON5_CALI_441_CYCLE (0x1B8 << 16) +#define GASRC_CON5_CALI_AUTORST_ENABLE BIT(15) +#define GASRC_CON5_AUTO_TUNE_FREQ5_ENABLE BIT(12) +#define GASRC_CON5_AUTO_TUNE_FREQ5_DISABLE (0x0 << 12) +#define GASRC_CON5_COMP_FREQ_RES_ENABLE BIT(11) +#define GASRC_CON5_CALI_BP_DGL_BYPASS BIT(7) +#define GASRC_CON5_AUTO_TUNE_FREQ4_ENABLE BIT(3) +#define GASRC_CON5_AUTO_TUNE_FREQ4_DISABLE (0x0 << 3) +#define GASRC_CON5_CALI_AUTO_RESTART_ENABLE BIT(2) +#define GASRC_CON5_CALI_USE_FREQ BIT(1) +#define GASRC_CON5_CALI_USE_PERIOD (0x0 << 1) +#define GASRC_CON5_CALI_ON BIT(0) +#define GASRC_CON5_CALI_OFF (0x0 << 0) +#define GASRC_CON5_CALI_SEL_MASK GENMASK(9, 8) +#define GASRC_CON5_CALI_SEL_00 (0x0 << 8) +#define GASRC_CON5_CALI_SEL_01 (0x1 << 8) + +/* AFE_TDM_GASRC*_ASRC_2CH_CON0 */ +#define TDM_ASRC_CON0_ONE_HEART BIT(31) + +#endif /* _MT8365_AFE_REGS_H_ */ diff --git a/src/platform/mt8365/include/platform/platform.h b/src/platform/mt8365/include/platform/platform.h new file mode 100644 index 000000000000..c447312c16a5 --- /dev/null +++ b/src/platform/mt8365/include/platform/platform.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <sof/lib/mailbox.h> +#include <stddef.h> +#include <stdint.h> + +struct ll_schedule_domain; +struct timer; + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) +#define LPSRAM_SIZE 16384 + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* pipeline IRQ */ +#define PLATFORM_SCHEDULE_IRQ MTK_DSP_IRQ_SOFTWARE0 +#define PLATFORM_SCHEDULE_IRQ_NAME NULL + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +/* trace bytes flushed during panic */ +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +/* the interval of DMA trace copying */ +#define DMA_TRACE_PERIOD 500000 + +/* + * the interval of reschedule DMA trace copying in special case like half + * fullness of local DMA trace buffer + */ +#define DMA_TRACE_RESCHEDULE_TIME 100 + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#define SRAM_REG_FW_STATUS 0x4 +#define SRAM_REG_OP_CPU2DSP 0x8 +#define SRAM_REG_OP_DSP2CPU 0xC + +/* Platform defined panic code */ +static inline void platform_panic(uint32_t p) +{ + /* Store the error code in the debug box so the + * application processor can pick it up. Takes up 4 bytes + * from the debug box. + */ + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p); + + /* Notify application processor */ + trigger_irq_to_host_req(); +} + +/** + * \brief Platform specific CPU entering idle. + * May be power-optimized using platform specific capabilities. + * @param level Interrupt level. + */ +void platform_wait_for_interrupt(int level); + +extern intptr_t _module_init_start; +extern intptr_t _module_init_end; +#endif + +#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/mt8365/include/platform/trace/trace.h b/src/platform/mt8365/include/platform/trace/trace.h new file mode 100644 index 000000000000..63122335e650 --- /dev/null +++ b/src/platform/mt8365/include/platform/trace/trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/io.h> +#include <platform/drivers/mt_reg_base.h> + +#define platform_trace_point(__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/mt8365/lib/CMakeLists.txt b/src/platform/mt8365/lib/CMakeLists.txt new file mode 100644 index 000000000000..ef71f8eea6cd --- /dev/null +++ b/src/platform/mt8365/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof + clk.c + dma.c + memory.c + dai.c +) diff --git a/src/platform/mt8365/lib/clk.c b/src/platform/mt8365/lib/clk.c new file mode 100644 index 000000000000..8101d4fd0f2c --- /dev/null +++ b/src/platform/mt8365/lib/clk.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <sof/common.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <rtos/wait.h> +#include <rtos/sof.h> +#include <sof/trace/trace.h> + +SOF_DEFINE_REG_UUID(clkdrv_mt8365); + +DECLARE_TR_CTX(clkdrv_tr, SOF_UUID(clkdrv_mt8365_uuid), LOG_LEVEL_INFO); + +static int dsppll_enable; /* default no adsp clock*/ +static int adsp_clock; + +const struct freq_table platform_cpu_freq[] = { + { 13000000, 13000}, + { 26000000, 13000}, + { 312000000, 13000}, + { 400000000, 13000}, + { 600000000, 13000}, +}; + +const uint32_t cpu_freq_enc[] = { + 13000000, + 26000000, + 0x83180000, + 0x820F6276, + 0x821713B1, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, + invalid_number_of_cpu_frequencies); + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static inline void clk_setl(uint32_t addr, uint32_t val) +{ + io_reg_write(addr, io_reg_read(addr) | (val)); +} + +static inline void clk_clrl(uint32_t addr, uint32_t val) +{ + io_reg_write(addr, io_reg_read(addr) & ~(val)); +} + +static inline int dsp_clk_value_convert(int value) +{ + int ret; + + switch (value) { + case DSP_CLK_13M: + ret = CLK_DSP_SEL_26M_D_2; + break; + case DSP_CLK_26M: + ret = CLK_DSP_SEL_26M; + break; + case DSP_CLK_PLL_312M: + case DSP_CLK_PLL_400M: + case DSP_CLK_PLL_600M: + ret = CLK_DSP_SEL_DSPPLL; + break; + default: + ret = CLK_DSP_SEL_26M; + break; + } + + return ret; +} + +static void clk_dsppll_enable(void) +{ + tr_dbg(&clkdrv_tr, "entry"); + + clk_setl(DSPPLL_CON3, PLL_PWR_ON); + wait_delay_us(1); + clk_clrl(DSPPLL_CON3, PLL_ISO_EN); + wait_delay_us(1); + clk_setl(DSPPLL_CON0, PLL_BASE_EN); + wait_delay_us(20); + dsppll_enable = 1; + +} + +static void clk_dsppll_disable(void) +{ + tr_dbg(&clkdrv_tr, "entry"); + + clk_clrl(DSPPLL_CON0, PLL_BASE_EN); + wait_delay_us(1); + clk_setl(DSPPLL_CON3, PLL_ISO_EN); + wait_delay_us(1); + clk_clrl(DSPPLL_CON3, PLL_PWR_ON); + dsppll_enable = 0; +} + +static int dsppll_get_enable(void) +{ + tr_dbg(&clkdrv_tr, "dsppll_enable=%d.\n", dsppll_enable); + + return dsppll_enable; +} + +static int set_mux_sel(enum mux_id_t mux_id, uint32_t value) +{ + switch (mux_id) { + case MUX_CLK_DSP_SEL: + io_reg_update_bits(CLK_CFG_8_CLR, (0x7 << 24), (0x7 << 24)); + io_reg_update_bits(CLK_CFG_8_SET, (0x7 << 24), (value << 24)); + io_reg_write(CLK_CFG_UPDATE1, 0x8); + + tr_dbg(&clkdrv_tr, "adspclk_mux=%x, CLK_CFG_8=0x%08x\n", + value, io_reg_read(CLK_CFG_8)); + break; + default: + tr_dbg(&clkdrv_tr, "error: unknown mux_id (%d)\n", mux_id); + break; + } + + return 0; +} + +static int clock_platform_set_dsp_freq(int clock, int freq_idx) +{ + uint32_t enc = cpu_freq_enc[freq_idx]; + int clk_mux; + int adsp_clk_req = platform_cpu_freq[freq_idx].freq; + + if (adsp_clock == adsp_clk_req) + return 0; + + tr_info(&clkdrv_tr, "clock_platform_set_cpu_freq %d\n", adsp_clk_req); + + /* convert res manager value to driver map */ + clk_mux = dsp_clk_value_convert(freq_idx); + + if (enc > 26000000) { + /* adsp pll */ + if (!dsppll_get_enable()) { + clk_dsppll_enable(); + set_mux_sel(MUX_CLK_DSP_SEL, clk_mux); + } + /* set adsp pll clock */ + io_reg_update_bits(DSPPLL_CON1, 0xffffffff, enc); + } else { + /* clk26m */ + if (dsppll_get_enable()) { + set_mux_sel(MUX_CLK_DSP_SEL, clk_mux); + clk_dsppll_disable(); + } + } + + adsp_clock = adsp_clk_req; + + return 0; +} + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_shared_get(platform_clocks_info, sizeof(platform_clocks_info)); + + 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 = clock_platform_set_dsp_freq, + }; + } + + adsp_clock = 0; + dsppll_enable = 0; + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_MAX_CPU_HZ); +} diff --git a/src/platform/mt8365/lib/dai.c b/src/platform/mt8365/lib/dai.c new file mode 100644 index 000000000000..6700e3257ac2 --- /dev/null +++ b/src/platform/mt8365/lib/dai.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/dai.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <ipc/dai.h> +#include <ipc/stream.h> + +#include <sof/drivers/afe-dai.h> +#include <mt8365-afe-common.h> + +/* MEMIF specified IRQs set in the Linux driver: + * + * [MT8365_AFE_MEMIF_DL1] = MT8365_AFE_IRQ1, + * [MT8365_AFE_MEMIF_DL2] = MT8365_AFE_IRQ2, + * [MT8365_AFE_MEMIF_TDM_OUT] = MT8365_AFE_IRQ5, + * // [MT8365_AFE_MEMIF_SPDIF_OUT] = MT8365_AFE_IRQ6, + * [MT8365_AFE_MEMIF_AWB] = MT8365_AFE_IRQ3, + * [MT8365_AFE_MEMIF_VUL] = MT8365_AFE_IRQ4, + * [MT8365_AFE_MEMIF_VUL2] = MT8365_AFE_IRQ7, + * [MT8365_AFE_MEMIF_VUL3] = MT8365_AFE_IRQ8, + * // [MT8365_AFE_MEMIF_SPDIF_IN] = MT8365_AFE_IRQ9, + * [MT8365_AFE_MEMIF_TDM_IN] = MT8365_AFE_IRQ10, + */ + +static int afe_dai_handshake[MT8365_DAI_NUM] = { + AFE_HANDSHAKE(MT8365_AFE_IO_INT_ADDA_OUT, MT8365_AFE_IRQ_1, MT8365_MEMIF_DL1), + AFE_HANDSHAKE(MT8365_AFE_IO_2ND_I2S, MT8365_AFE_IRQ_2, MT8365_MEMIF_DL2), + AFE_HANDSHAKE(MT8365_AFE_IO_INT_ADDA_IN, MT8365_AFE_IRQ_3, MT8365_MEMIF_AWB), + AFE_HANDSHAKE(MT8365_AFE_IO_DMIC, MT8365_AFE_IRQ_4, MT8365_MEMIF_VUL), +}; + +static SHARED_DATA struct dai afe_dai[MT8365_DAI_NUM]; + +const struct dai_type_info dti[] = { + { + .type = SOF_DAI_MEDIATEK_AFE, + .dai_array = afe_dai, + .num_dais = ARRAY_SIZE(afe_dai), + }, +}; + +const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti), +}; + +int dai_init(struct sof *sof) +{ + int i; + + /* initialize spin locks early to enable ref counting */ + for (i = 0; i < ARRAY_SIZE(afe_dai); i++) { + k_spinlock_init(&afe_dai[i].lock); + afe_dai[i].index = AFE_HS_GET_DAI(afe_dai_handshake[i]); + afe_dai[i].drv = &afe_dai_driver; + /* TODO, fifo[0] change to target playback or capture */ + afe_dai[i].plat_data.fifo[0].handshake = afe_dai_handshake[i]; + } + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/mt8365/lib/dma.c b/src/platform/mt8365/lib/dma.c new file mode 100644 index 000000000000..9e6209790731 --- /dev/null +++ b/src/platform/mt8365/lib/dma.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/drivers/afe-memif.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> + +#include <mt8365-afe-regs.h> +#include <mt8365-afe-common.h> + +extern const struct dma_ops dummy_dma_ops; + +static SHARED_DATA struct dma dma[PLATFORM_NUM_DMACS] = { +{ + .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, +}, +{ + .plat_data = { + .id = DMA_ID_AFE_MEMIF, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_AFE_MEMIF, + .base = AFE_REG_BASE, + .channels = MT8365_MEMIF_NUM, + }, + .ops = &memif_ops, +}, +}; + +static const struct dma_info lib_dma = { + .dma_array = cache_to_uncache_init((struct dma *)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/mt8365/lib/memory.c b/src/platform/mt8365/lib/memory.c new file mode 100644 index 000000000000..13c7a9b2bdd4 --- /dev/null +++ b/src/platform/mt8365/lib/memory.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <sof/common.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <ipc/topology.h> + +/* Heap blocks for system runtime */ +static SHARED_DATA struct block_hdr sys_rt_block64[HEAP_SYS_RT_COUNT64]; +static SHARED_DATA struct block_hdr sys_rt_block512[HEAP_SYS_RT_COUNT512]; +static SHARED_DATA struct block_hdr sys_rt_block1024[HEAP_SYS_RT_COUNT1024]; + +/* Heap memory for system runtime */ +static SHARED_DATA struct block_map sys_rt_heap_map[] = { + BLOCK_DEF(64, HEAP_SYS_RT_COUNT64, sys_rt_block64), + BLOCK_DEF(512, HEAP_SYS_RT_COUNT512, sys_rt_block512), + BLOCK_DEF(1024, HEAP_SYS_RT_COUNT1024, sys_rt_block1024), +}; + +/* Heap blocks for modules */ +static SHARED_DATA struct block_hdr mod_block16[HEAP_RT_COUNT16]; +static SHARED_DATA struct block_hdr mod_block32[HEAP_RT_COUNT32]; +static SHARED_DATA struct block_hdr mod_block64[HEAP_RT_COUNT64]; +static SHARED_DATA struct block_hdr mod_block128[HEAP_RT_COUNT128]; +static SHARED_DATA struct block_hdr mod_block256[HEAP_RT_COUNT256]; +static SHARED_DATA struct block_hdr mod_block512[HEAP_RT_COUNT512]; +static SHARED_DATA struct block_hdr mod_block1024[HEAP_RT_COUNT1024]; +static SHARED_DATA struct block_hdr mod_block2048[HEAP_RT_COUNT2048]; +static SHARED_DATA struct block_hdr mod_block4096[HEAP_RT_COUNT4096]; + +/* Heap memory map for modules */ +static SHARED_DATA struct block_map rt_heap_map[] = { + BLOCK_DEF(16, HEAP_RT_COUNT16, mod_block16), + BLOCK_DEF(32, HEAP_RT_COUNT32, mod_block32), + BLOCK_DEF(64, HEAP_RT_COUNT64, mod_block64), + BLOCK_DEF(128, HEAP_RT_COUNT128, mod_block128), + BLOCK_DEF(256, HEAP_RT_COUNT256, mod_block256), + BLOCK_DEF(512, HEAP_RT_COUNT512, mod_block512), + BLOCK_DEF(1024, HEAP_RT_COUNT1024, mod_block1024), + BLOCK_DEF(2048, HEAP_RT_COUNT2048, mod_block2048), + BLOCK_DEF(4096, HEAP_RT_COUNT4096, mod_block4096), +}; + +/* Heap blocks for buffers */ +static SHARED_DATA struct block_hdr buf_block[HEAP_BUFFER_COUNT]; + +/* Heap memory map for buffers */ +static SHARED_DATA struct block_map buf_heap_map[] = { + BLOCK_DEF(HEAP_BUFFER_BLOCK_SIZE, HEAP_BUFFER_COUNT, buf_block), +}; + +static SHARED_DATA struct mm memmap = { + .system[0] = { + .heap = HEAP_SYSTEM_BASE, + .size = HEAP_SYSTEM_SIZE, + .info = {.free = HEAP_SYSTEM_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .system_runtime[0] = { + .blocks = ARRAY_SIZE(sys_rt_heap_map), + .map = sys_rt_heap_map, + .heap = HEAP_SYS_RUNTIME_BASE, + .size = HEAP_SYS_RUNTIME_SIZE, + .info = {.free = HEAP_SYS_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .runtime[0] = { + .blocks = ARRAY_SIZE(rt_heap_map), + .map = rt_heap_map, + .heap = HEAP_RUNTIME_BASE, + .size = HEAP_RUNTIME_SIZE, + .info = {.free = HEAP_RUNTIME_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .buffer[0] = { + .blocks = ARRAY_SIZE(buf_heap_map), + .map = buf_heap_map, + .heap = HEAP_BUFFER_BASE, + .size = HEAP_BUFFER_SIZE, + .info = {.free = HEAP_BUFFER_SIZE,}, + .caps = SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_CACHE | + SOF_MEM_CAPS_DMA, + }, + .total = {.free = HEAP_SYSTEM_SIZE + HEAP_SYS_RUNTIME_SIZE + + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE,}, +}; + +void platform_init_memmap(struct sof *sof) +{ + /* memmap has been initialized statically as a part of .data */ + sof->memory_map = platform_shared_get(&memmap, sizeof(memmap)); +} diff --git a/src/platform/mt8365/mt8365.x.in b/src/platform/mt8365/mt8365.x.in new file mode 100644 index 000000000000..fdf588d33e4f --- /dev/null +++ b/src/platform/mt8365/mt8365.x.in @@ -0,0 +1,492 @@ +/* + * Linker Script for mt8365 MediaTek + * + * This script is run through the GNU C preprocessor to align the memory + * offsets with headers. + * + * Use spaces for formatting as cpp ignore tab sizes. + */ + +#include <sof/lib/memory.h> +#include <xtensa/config/core-isa.h> + +OUTPUT_ARCH(xtensa) + +MEMORY +{ + vector_reset_text : + org = XCHAL_RESET_VECTOR0_PADDR, + len = SOF_MEM_RESET_TEXT_SIZE + vector_reset_lit : + org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, + len = SOF_MEM_RESET_LIT_SIZE + vector_base_text : + org = XCHAL_VECBASE_RESET_PADDR, + len = SOF_MEM_VECBASE_LIT_SIZE + vector_int2_lit : + org = XCHAL_INTLEVEL2_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int2_text : + org = XCHAL_INTLEVEL2_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int3_lit : + org = XCHAL_INTLEVEL3_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int3_text : + org = XCHAL_INTLEVEL3_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_int4_lit : + org = XCHAL_INTLEVEL4_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_int4_text : + org = XCHAL_INTLEVEL4_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_kernel_lit : + org = XCHAL_KERNEL_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_kernel_text : + org = XCHAL_KERNEL_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_user_lit : + org = XCHAL_USER_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_user_text : + org = XCHAL_USER_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + vector_double_lit : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR - SOF_MEM_VECT_LIT_SIZE, + len = SOF_MEM_VECT_LIT_SIZE + vector_double_text : + org = XCHAL_DOUBLEEXC_VECTOR_PADDR, + len = SOF_MEM_VECT_TEXT_SIZE + sof_sram : + org = SRAM0_BASE, + len = SRAM0_SIZE + system_heap : + org = HEAP_SYSTEM_BASE, + len = HEAP_SYSTEM_SIZE + system_runtime_heap : + org = HEAP_SYS_RUNTIME_BASE, + len = HEAP_SYS_RUNTIME_SIZE + runtime_heap : + org = HEAP_RUNTIME_BASE, + len = HEAP_RUNTIME_SIZE + buffer_heap : + org = HEAP_BUFFER_BASE, + len = HEAP_BUFFER_SIZE + sof_stack : + org = SOF_STACK_END, + len = SOF_STACK_BASE - SOF_STACK_END + static_uuid_entries_seg (!ari) : + org = UUID_ENTRY_ELF_BASE, + len = UUID_ENTRY_ELF_SIZE + static_log_entries_seg (!ari) : + org = LOG_ENTRY_ELF_BASE, + len = LOG_ENTRY_ELF_SIZE + fw_metadata_seg (!ari) : + org = EXT_MANIFEST_ELF_BASE, + len = EXT_MANIFEST_ELF_SIZE +} + +PHDRS +{ + vector_reset_text_phdr PT_LOAD; + vector_reset_lit_phdr PT_LOAD; + vector_base_text_phdr PT_LOAD; + vector_base_lit_phdr PT_LOAD; + vector_int2_text_phdr PT_LOAD; + vector_int2_lit_phdr PT_LOAD; + vector_int3_text_phdr PT_LOAD; + vector_int3_lit_phdr PT_LOAD; + vector_int4_text_phdr PT_LOAD; + vector_int4_lit_phdr PT_LOAD; + vector_kernel_text_phdr PT_LOAD; + vector_kernel_lit_phdr PT_LOAD; + vector_user_text_phdr PT_LOAD; + vector_user_lit_phdr PT_LOAD; + vector_double_text_phdr PT_LOAD; + vector_double_lit_phdr PT_LOAD; + sof_sram_phdr PT_LOAD; + system_heap_phdr PT_LOAD; + system_runtime_heap_phdr PT_LOAD; + runtime_heap_phdr PT_LOAD; + buffer_heap_phdr PT_LOAD; + sof_stack_phdr PT_LOAD; + static_uuid_entries_phdr PT_NOTE; + static_log_entries_phdr PT_NOTE; + metadata_entries_phdr PT_NOTE; +} + +/* Default entry point: */ +ENTRY(_ResetVector) +_rom_store_table = 0; + +/* ABI0 does not use Window base */ +PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); + +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000100; +_memmap_cacheattr_wt_base = 0x00000300; +_memmap_cacheattr_bp_base = 0x00000400; +_memmap_cacheattr_unused_mask = 0xFFFFF0FF; +_memmap_cacheattr_wb_trapnull = 0x44444140; +_memmap_cacheattr_wba_trapnull = 0x44444140; +_memmap_cacheattr_wbna_trapnull = 0x44444240; +_memmap_cacheattr_wt_trapnull = 0x44444340; +_memmap_cacheattr_bp_trapnull = 0x44444440; +_memmap_cacheattr_wb_strict = 0x00000100; +_memmap_cacheattr_wt_strict = 0x00000300; +_memmap_cacheattr_bp_strict = 0x00000400; +_memmap_cacheattr_wb_allvalid = 0x44444144; +_memmap_cacheattr_wt_allvalid = 0x44444344; +_memmap_cacheattr_bp_allvalid = 0x44444444; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +_EXT_MAN_ALIGN_ = 16; +EXTERN(ext_man_fw_ver) + +SECTIONS +{ + .ResetVector.text : ALIGN(4) + { + _ResetVector_text_start = ABSOLUTE(.); + KEEP (*(.ResetVector.text)) + _ResetVector_text_end = ABSOLUTE(.); + } >vector_reset_text :vector_reset_text_phdr + + .ResetVector.literal : ALIGN(4) + { + _ResetVector_literal_start = ABSOLUTE(.); + *(.ResetVector.literal) + _ResetVector_literal_end = ABSOLUTE(.); + } >vector_reset_lit :vector_reset_lit_phdr + + .WindowVectors.text : ALIGN(4) + { + _WindowVectors_text_start = ABSOLUTE(.); + KEEP (*(.WindowVectors.text)) + _WindowVectors_text_end = ABSOLUTE(.); + } >vector_base_text :vector_base_text_phdr + + .Level2InterruptVector.literal : ALIGN(4) + { + _Level2InterruptVector_literal_start = ABSOLUTE(.); + *(.Level2InterruptVector.literal) + _Level2InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int2_lit :vector_int2_lit_phdr + + .Level2InterruptVector.text : ALIGN(4) + { + _Level2InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level2InterruptVector.text)) + _Level2InterruptVector_text_end = ABSOLUTE(.); + } >vector_int2_text :vector_int2_text_phdr + + .Level3InterruptVector.literal : ALIGN(4) + { + _Level3InterruptVector_literal_start = ABSOLUTE(.); + *(.Level3InterruptVector.literal) + _Level3InterruptVector_literal_end = ABSOLUTE(.); + } >vector_int3_lit :vector_int3_lit_phdr + + .Level3InterruptVector.text : ALIGN(4) + { + _Level3InterruptVector_text_start = ABSOLUTE(.); + KEEP (*(.Level3InterruptVector.text)) + _Level3InterruptVector_text_end = ABSOLUTE(.); + } >vector_int3_text :vector_int3_text_phdr + + .DebugExceptionVector.literal : ALIGN(4) + { + _DebugExceptionVector_literal_start = ABSOLUTE(.); + *(.DebugExceptionVector.literal) + _DebugExceptionVector_literal_end = ABSOLUTE(.); + } >vector_int4_lit :vector_int4_lit_phdr + + .DebugExceptionVector.text : ALIGN(4) + { + _DebugExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DebugExceptionVector.text)) + _DebugExceptionVector_text_end = ABSOLUTE(.); + } >vector_int4_text :vector_int4_text_phdr + + .KernelExceptionVector.literal : ALIGN(4) + { + _KernelExceptionVector_literal_start = ABSOLUTE(.); + *(.KernelExceptionVector.literal) + _KernelExceptionVector_literal_end = ABSOLUTE(.); + } >vector_kernel_lit :vector_kernel_lit_phdr + + .KernelExceptionVector.text : ALIGN(4) + { + _KernelExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.KernelExceptionVector.text)) + _KernelExceptionVector_text_end = ABSOLUTE(.); + } >vector_kernel_text :vector_kernel_text_phdr + + .UserExceptionVector.literal : ALIGN(4) + { + _UserExceptionVector_literal_start = ABSOLUTE(.); + *(.UserExceptionVector.literal) + _UserExceptionVector_literal_end = ABSOLUTE(.); + } >vector_user_lit :vector_user_lit_phdr + + .UserExceptionVector.text : ALIGN(4) + { + _UserExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.UserExceptionVector.text)) + _UserExceptionVector_text_end = ABSOLUTE(.); + } >vector_user_text :vector_user_text_phdr + + .DoubleExceptionVector.literal : ALIGN(4) + { + _DoubleExceptionVector_literal_start = ABSOLUTE(.); + *(.DoubleExceptionVector.literal) + _DoubleExceptionVector_literal_end = ABSOLUTE(.); + } >vector_double_lit :vector_double_lit_phdr + + .DoubleExceptionVector.text : ALIGN(4) + { + _DoubleExceptionVector_text_start = ABSOLUTE(.); + KEEP (*(.DoubleExceptionVector.text)) + _DoubleExceptionVector_text_end = ABSOLUTE(.); + } >vector_double_text :vector_double_text_phdr + + .fw_ready : ALIGN(4) + { + KEEP (*(.fw_ready)) + KEEP (*(.fw_ready_metadata)) + } >sof_sram :sof_sram_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.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 */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >sof_sram :sof_sram_phdr + + .module_init : ALIGN(4) + { + _module_init_start = ABSOLUTE(.); + *(*.initcall) + _module_init_end = ABSOLUTE(.); + } >sof_sram :sof_sram_phdr + + .text : ALIGN(4) + { + _stext = .; + _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) + _text_end = ABSOLUTE(.); + _etext = .; + } >sof_sram :sof_sram_phdr + + .reset.rodata : ALIGN(4) + { + _reset_rodata_start = ABSOLUTE(.); + *(.reset.rodata) + _reset_rodata_end = ABSOLUTE(.); + } >sof_sram :sof_sram_phdr + + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + KEEP(*(.gnu.linkonce.d.*personality*)) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + KEEP(*(.jcr)) + _trace_ctx_start = ABSOLUTE(.); + *(.trace_ctx) + _trace_ctx_end = ABSOLUTE(.); + _data_end = ABSOLUTE(.); + } >sof_sram :sof_sram_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >sof_sram :sof_sram_phdr + + .bss (NOLOAD) : ALIGN(8) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + } >sof_sram :sof_sram_phdr + + /* stack */ + _end = SOF_STACK_END; + PROVIDE(end = SOF_STACK_END); + _stack_sentry = SOF_STACK_END; + __stack = SOF_STACK_BASE; + + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .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.*)) + } + + .system_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _system_heap_start = ABSOLUTE(.); + . = . + HEAP_SYSTEM_SIZE; + _system_heap_end = ABSOLUTE(.); + } >system_heap :system_heap_phdr + + .system_runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _system_runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_SYS_RUNTIME_SIZE; + _system_runtime_heap_end = ABSOLUTE(.); + } >system_runtime_heap :system_runtime_heap_phdr + + .runtime_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (32); + _runtime_heap_start = ABSOLUTE(.); + . = . + HEAP_RUNTIME_SIZE; + _runtime_heap_end = ABSOLUTE(.); + } >runtime_heap :runtime_heap_phdr + + .buffer_heap (NOLOAD) : ALIGN(8) + { + . = ALIGN (HEAP_BUF_ALIGNMENT); + _buffer_heap_start = ABSOLUTE(.); + . = . + HEAP_BUFFER_SIZE; + _buffer_heap_end = ABSOLUTE(.); + } >buffer_heap :buffer_heap_phdr + + .sof_stack (NOLOAD) : ALIGN(8) + { + . = ALIGN (4096); + _sof_stack_start = ABSOLUTE(.); + . = . + SOF_STACK_TOTAL_SIZE; + _sof_stack_end = ABSOLUTE(.); + } >sof_stack :sof_stack_phdr + + .static_uuid_entries (COPY) : ALIGN(1024) + { + *(*.static_uuids) + } > static_uuid_entries_seg :static_uuid_entries_phdr + + .static_log_entries (COPY) : ALIGN(1024) + { + *(*.static_log*) + } > static_log_entries_seg :static_log_entries_phdr + + .fw_metadata (COPY) : ALIGN(1024) + { + KEEP (*(.fw_metadata)) + . = ALIGN(_EXT_MAN_ALIGN_); + } >fw_metadata_seg :metadata_entries_phdr +} diff --git a/src/platform/mt8365/platform.c b/src/platform/mt8365/platform.c new file mode 100644 index 000000000000..d57edc2f8431 --- /dev/null +++ b/src/platform/mt8365/platform.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 MediaTek. All rights reserved. + * + * Author: Andrew Perepech <andrew.perepech@mediatek.com> + */ + +#include <errno.h> +#include <ipc/dai.h> +#include <ipc/header.h> +#include <ipc/info.h> +#include <kernel/abi.h> +#include <kernel/ext_manifest.h> +#include <platform/drivers/timer.h> +#include <rtos/clk.h> +#include <rtos/timer.h> +#include <rtos/interrupt.h> +#include <sof/compiler_info.h> +#include <sof/debug/debug.h> +#include <sof/drivers/edma.h> +#include <sof/ipc/msg.h> +#include <sof/fw-ready-metadata.h> +#include <sof/lib/agent.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <sof/lib/mm_heap.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <rtos/sof.h> +#include <sof/trace/dma-trace.h> +#include <sof_versions.h> +#include <stdint.h> +#include <xtensa/hal.h> + +struct sof; + +static const struct sof_ipc_fw_ready ready + __section(".fw_ready") = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + /* dspbox is for DSP initiated IPC, hostbox is for host initiated IPC */ + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +#define NUM_MTK_WINDOWS 6 + +const struct ext_man_windows xsram_window + __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") __unused = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_windows), EXT_MAN_ALIGN), + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = NUM_MTK_WINDOWS, + .window = { + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DOWNBOX, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_DEBUG, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_DEBUG_SIZE, + .offset = MAILBOX_DEBUG_OFFSET, + }, + { + .type = SOF_IPC_REGION_TRACE, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_TRACE_SIZE, + .offset = MAILBOX_TRACE_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + { + .type = SOF_IPC_REGION_EXCEPTION, + .id = 0, /* map to host window 0 */ + .flags = 0, + .size = MAILBOX_EXCEPTION_SIZE, + .offset = MAILBOX_EXCEPTION_OFFSET, + }, + }, + } +}; + +static SHARED_DATA struct timer timer_shared = { + .id = OSTIMER0, + .irq = SYSTICK_TIMER_IRQ, +}; + +/* Override the default MPU setup. This table matches the memory map + * of the 'sample_controller' core and will need to be modified for + * other cores. + * NOTE: This table sets up all of external memory as shared uncached. + * For best results, edit the LSP memory map to create a separate + * section in shared memory, place all sections that need to be uncached + * into that section, and only map that section uncached. See README + * for more details. + */ +const struct xthal_MPU_entry __xt_mpu_init_table[] __section(".ResetVector.text") = { + XTHAL_MPU_ENTRY(0x00000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_DEVICE), // infra + XTHAL_MPU_ENTRY(0x40020000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // vectors + XTHAL_MPU_ENTRY(0x40060000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused + XTHAL_MPU_ENTRY(0x60000000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_WRITEBACK), // DSP FW + XTHAL_MPU_ENTRY(0x60800000, 1, XTHAL_AR_RWXrwx, XTHAL_MEM_NON_CACHEABLE), // shared + XTHAL_MPU_ENTRY(0x61000000, 1, XTHAL_AR_NONE, XTHAL_MEM_DEVICE), // unused +}; + +const unsigned int __xt_mpu_init_table_size __section(".ResetVector.text") = + ARRAY_SIZE(__xt_mpu_init_table); + +int platform_boot_complete(uint32_t boot_message) +{ + mailbox_dspbox_write(0, &ready, sizeof(ready)); + + /* now interrupt host to tell it we are done booting */ + trigger_irq_to_host_req(); + + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + mailbox_sw_reg_write(SRAM_REG_FW_STATUS, 0); + mailbox_sw_reg_write(SRAM_REG_OP_CPU2DSP, 0); + mailbox_sw_reg_write(SRAM_REG_OP_DSP2CPU, 0); + + sof->platform_timer = platform_shared_get(&timer_shared, sizeof(timer_shared)); + sof->cpu_timers = sof->platform_timer; + + platform_interrupt_init(); + platform_clock_init(sof); + + scheduler_init_edf(); + + /* init low latency domains and schedulers */ + sof->platform_timer_domain = timer_domain_init(sof->platform_timer, PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + + platform_timer_start(sof->platform_timer); + sa_init(sof, CONFIG_SYSTICK_PERIOD); + + /* init DMA */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* Init platform domain */ + sof->platform_dma_domain = dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], 1, + PLATFORM_DEFAULT_CLOCK, false); + scheduler_init_ll(sof->platform_dma_domain); + + /* initialize the host IPC mechanims */ + ipc_init(sof); + + ret = dai_init(sof); + if (ret < 0) + return ret; + +#if CONFIG_TRACE + /* Initialize DMA for Trace*/ + trace_point(TRACE_BOOT_PLATFORM_DMA_TRACE); + dma_trace_init_complete(sof->dmat); +#endif + + /* show heap status */ + heap_trace_all(1); + + return 0; +} + +int platform_context_save(struct sof *sof) +{ + clock_set_freq(CLK_CPU(cpu_get_id()), CLK_DEFAULT_CPU_HZ); + return 0; +} + +void platform_wait_for_interrupt(int level) +{ + arch_wait_for_interrupt(level); +} + diff --git a/src/platform/mtk/dai.c b/src/platform/mtk/dai.c new file mode 100644 index 000000000000..17fbc665dfbe --- /dev/null +++ b/src/platform/mtk/dai.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2024 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <sof/lib/dai-legacy.h> +#include <ipc/dai.h> +#include <sof/drivers/afe-drv.h> + +/* The legacy driver stores register addresses as an offset from an + * arbitrary base address (which is not actually a unified block of + * AFE-related registers), where DTS naturally wants to provide full + * addresses. We store the base here, pending a Zephyrized driver. + */ +#if defined(CONFIG_SOC_MT8186) +#define MTK_AFE_BASE 0x11210000 +#define SRAM_CPU_START 0x10800000 +#elif defined(CONFIG_SOC_SERIES_MT818X) +#define MTK_AFE_BASE 0x10b10000 +#define SRAM_CPU_START 0x10d00000 +#elif defined(CONFIG_SOC_MT8195) +#define MTK_AFE_BASE 0x10890000 +#define SRAM_CPU_START 0x10840000 +#elif defined(CONFIG_SOC_MT8196) +#define MTK_AFE_BASE 0x1a110000 +#define SRAM_CPU_START 0x1a210000 +#elif defined(CONFIG_SOC_MT8365) +#define MTK_AFE_BASE 0x11220000 +#define SRAM_CPU_START 0x1e000000 +#else +#error Unrecognized device +#endif + +#define SRAM_ADSP_START DT_REG_ADDR(DT_NODELABEL(sram0)) +#define SRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sram0)) +#define SRAM_ADSP_END (SRAM_ADSP_START + SRAM_SIZE) +#define SRAM_CPU_END (SRAM_CPU_START + SRAM_SIZE) + +/* Bitfield register: address, left shift amount, and number of bits */ +struct afe_bitfld { + uint32_t reg; + uint8_t shift; + uint8_t bits; +}; + +/* Pair of registers to store a 64 bit host/bus address */ +struct afe_busreg { + uint32_t hi; + uint32_t lo; +}; + +/* Config struct for a DTS-defined AFE device */ +struct afe_cfg { + char afe_name[32]; + int dai_id; + bool downlink; + bool mono_invert; + struct afe_busreg base; + struct afe_busreg end; + struct afe_busreg cur; + struct afe_bitfld fs; + struct afe_bitfld hd; + struct afe_bitfld enable; + struct afe_bitfld mono; + struct afe_bitfld quad_ch; + struct afe_bitfld int_odd; + struct afe_bitfld msb; + struct afe_bitfld msb2; + struct afe_bitfld agent_disable; + struct afe_bitfld ch_num; +}; + +/* Converts the DTS_derived afe_cfg struct to a runtime memif_data for + * use by the legacy driver. This is temporary, pending a + * Zephyrization port that will get the driver using the config struct + * directly. + * + * Note the preprocessor trickery to help mapping the regularized DTS + * data to the "almost but not quite convention-conforming" original + * naming. Mostly just some naming quirks. The only semantic + * differences are that the register addresses in DTS become offsets + * from MTK_AFE_BASE, that default/unset register addresses are stored + * as -1 and not NULL. + */ +static void cfg_convert(const struct afe_cfg *src, struct mtk_base_memif_data *dst) +{ +#define REGCVT(R) (((R) > 0) ? ((R) - MTK_AFE_BASE) : 0) + +#define COPYBIT(S, Dr, Ds) do { \ + dst->Dr = REGCVT(src->S.reg); \ + dst->Ds = src->S.shift; \ + } while (0) + +#define COPYFLD(S, Dr, Ds, Dm) do { \ + COPYBIT(S, Dr, Ds); \ + dst->Dm = BIT(src->S.bits) - 1; \ + } while (0) + +#define COPY2(F) COPYBIT(F, F##_reg, F##_shift) +#define COPY3(F) COPYFLD(F, F##_reg, F##_shift, F##_mask) + + dst->name = src->afe_name; /* DTS values are string literals */ + dst->reg_ofs_base = REGCVT(src->base.lo); + dst->reg_ofs_cur = REGCVT(src->cur.lo); + dst->reg_ofs_end = REGCVT(src->end.lo); + dst->reg_ofs_base_msb = REGCVT(src->base.hi); + dst->reg_ofs_cur_msb = REGCVT(src->cur.hi); + dst->reg_ofs_end_msb = REGCVT(src->end.hi); + dst->mono_invert = src->mono_invert; + + COPYFLD(fs, fs_reg, fs_shift, fs_maskbit); + COPY2(mono); + COPY3(quad_ch); + COPYBIT(int_odd, int_odd_flag_reg, int_odd_flag_shift); + COPY2(enable); + COPY2(hd); + COPY2(msb); + COPY2(msb2); + COPY2(agent_disable); + COPYFLD(ch_num, ch_num_reg, ch_num_shift, ch_num_maskbit); + +#undef REGCVT +#undef COPYBIT +#undef COPYFLD +#undef COPY2 +#undef COPY3 +} + +/* Some properties may be skipped/defaulted in DTS, leave them zero-filled */ +#define COND_PROP(n, prop) \ + IF_ENABLED(DT_NODE_HAS_PROP(n, prop), (.prop = DT_PROP(n, prop),)) + +#define GENAFE(n) { \ + .afe_name = DT_PROP(n, afe_name), \ + .dai_id = DT_PROP(n, dai_id), \ + .downlink = DT_PROP(n, downlink), \ + .mono_invert = DT_PROP(n, mono_invert), \ + .base = DT_PROP(n, base), \ + .end = DT_PROP(n, end), \ + .cur = DT_PROP(n, cur), \ + COND_PROP(n, fs) \ + .hd = DT_PROP(n, hd), \ + .enable = DT_PROP(n, enable), \ + COND_PROP(n, mono) \ + COND_PROP(n, quad_ch) \ + COND_PROP(n, int_odd) \ + COND_PROP(n, msb) \ + COND_PROP(n, msb2) \ + COND_PROP(n, agent_disable) \ + COND_PROP(n, ch_num) \ + }, + +static const struct afe_cfg afes[] = { + DT_FOREACH_STATUS_OKAY(mediatek_afe, GENAFE) +}; + +#define EMPTY_STRUCT(n) {}, + +static struct mtk_base_memif_data afe_memifs[] = { + DT_FOREACH_STATUS_OKAY(mediatek_afe, EMPTY_STRUCT) +}; + +static struct dai mtk_dais[] = { + DT_FOREACH_STATUS_OKAY(mediatek_afe, EMPTY_STRUCT) +}; + +extern const struct dma_ops memif_ops; +extern const struct dma_ops dummy_dma_ops; + +// FIXME: remove this ID field? Nothing seems to use it +enum dma_id { + DMA_ID_AFE_MEMIF, + DMA_ID_HOST, +}; + +static struct dma mtk_dma[] = { + { + .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, + }, + { + .plat_data = { + .id = DMA_ID_AFE_MEMIF, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_AFE_MEMIF, + .base = MTK_AFE_BASE, + .channels = ARRAY_SIZE(mtk_dais), + }, + .ops = &memif_ops, + }, +}; + +static const struct dma_info mtk_dma_info = { + .dma_array = mtk_dma, + .num_dmas = ARRAY_SIZE(mtk_dma), +}; + +static const struct dai_type_info mtk_dai_types[] = { + { + .type = SOF_DAI_MEDIATEK_AFE, + .dai_array = mtk_dais, + .num_dais = ARRAY_SIZE(mtk_dais), + }, +}; + +static const struct dai_info mtk_dai_info = { + .dai_type_array = mtk_dai_types, + .num_dai_types = ARRAY_SIZE(mtk_dai_types), +}; + +#if defined(CONFIG_SOC_SERIES_MT818X) || defined(CONFIG_SOC_MT8195) +static unsigned int mtk_afe2adsp_addr(unsigned int addr) +{ + /* CPU -> ADSP address remap */ + if ((addr >= SRAM_CPU_START) && (addr < SRAM_CPU_END)) { + addr = SRAM_ADSP_START + (addr - SRAM_CPU_START); + } + + return addr; +} + +static unsigned int mtk_adsp2afe_addr(unsigned int addr) +{ + /* ADSP -> CPU address remap */ + if ((addr >= SRAM_ADSP_START) && (addr < SRAM_ADSP_END)) { + addr = SRAM_CPU_START + (addr - SRAM_ADSP_START); + } + + return addr; +} +#endif + +/* Static table of fs register values. TODO: binary search */ +static unsigned int mtk_afe_fs_timing(unsigned int rate) +{ + static const struct { int hz, reg; } rate2reg[] = { +#if defined(CONFIG_SOC_MT8188) || defined(CONFIG_SOC_MT8195) + { 7350, 16 }, + { 8000, 0 }, + { 11025, 17 }, + { 12000, 1 }, + { 14700, 18 }, + { 16000, 2 }, + { 22050, 19 }, + { 24000, 3 }, + { 29400, 20 }, + { 32000, 4 }, + { 44100, 21 }, + { 48000, 5 }, + { 88200, 22 }, + { 96000, 6 }, + { 176400, 23 }, + { 192000, 7 }, + { 352800, 24 }, + { 384000, 8 }, +#elif defined(CONFIG_SOC_MT8186) + { 8000, 0 }, + { 11025, 1 }, + { 12000, 2 }, + { 16000, 4 }, + { 22050, 5 }, + { 24000, 6 }, + { 32000, 8 }, + { 44100, 9 }, + { 48000, 10 }, + { 88200, 11 }, + { 96000, 12 }, + { 176400, 13 }, + { 192000, 14 }, + { 352800, 7 }, + { 384000, 3 }, +#elif defined(CONFIG_SOC_MT8365) + { 8000, 0 }, + { 11025, 1 }, + { 12000, 2 }, + { 16000, 4 }, + { 22050, 5 }, + { 24000, 6 }, + { 32000, 8 }, + { 44100, 9 }, + { 48000, 10 }, + { 88200, 11 }, + { 96000, 12 }, + { 176400, 13 }, + { 192000, 14 }, +#else + { 8000, 0 }, + { 11025, 1 }, + { 12000, 2 }, + { 16000, 4 }, + { 22050, 5 }, + { 24000, 6 }, + { 32000, 8 }, + { 44100, 9 }, + { 48000, 10 }, + { 88200, 13 }, + { 96000, 14 }, + { 176400, 17 }, + { 192000, 18 }, + { 352800, 21 }, + { 384000, 22 }, +#endif + }; + + for (int i = 0; i < ARRAY_SIZE(rate2reg); i++) + if (rate2reg[i].hz == rate) + return rate2reg[i].reg; + return -EINVAL; +} + +static unsigned int mtk_afe_fs(unsigned int rate, int aud_blk) +{ + return mtk_afe_fs_timing(rate); +} + +/* Global symbol referenced by AFE driver */ +struct mtk_base_afe_platform mtk_afe_platform = { + .base_addr = MTK_AFE_BASE, + .memif_datas = afe_memifs, + .memif_size = ARRAY_SIZE(afe_memifs), + .memif_32bit_supported = 0, + .irq_datas = NULL, + .irqs_size = 0, + .dais_size = ARRAY_SIZE(mtk_dais), + .afe_fs = mtk_afe_fs, + .irq_fs = mtk_afe_fs_timing, +#if defined(CONFIG_SOC_SERIES_MT818X) || defined(CONFIG_SOC_MT8195) + .afe2adsp_addr = mtk_afe2adsp_addr, + .adsp2afe_addr = mtk_adsp2afe_addr, +#endif +}; + +int mtk_dai_init(struct sof *sof) +{ + int i; + + /* Convert our DTS-defined AFE devices to legacy memif structs */ + for (i = 0; i < ARRAY_SIZE(afes); i++) { + afe_memifs[i].id = i; + cfg_convert(&afes[i], &afe_memifs[i]); + + /* Also initialize the dais array */ + extern const struct dai_driver afe_dai_driver; + + mtk_dais[i].index = i; + mtk_dais[i].drv = &afe_dai_driver; + + /* Also construct the mtk_dais[] array, which is the + * mapping from the host-visible DAI index to a driver + * defined in afe_memifs[]. The mapping is ad-hoc, + * and stored, bitpacked, in the "handshake" variable + * in plat data. The DAI index is the low byte, the + * AFE index is in the third byte. There is an IRQ + * traditionally defined in the middle byte but unused + * here because the driver doesn't support + * interrupts. + */ + int di = afes[i].dai_id; + int hs = (i << 16) | di; + + mtk_dais[di].plat_data.fifo[0].handshake = hs; + } + + /* DTS stores the direction as a boolean property, but the + * legacy driver wants all the DL devices at the start of the + * array. Compute memif_dl_num (and validate the order!). + */ + for (i = 0; i < ARRAY_SIZE(afes); i++) { + if (!afes[i].downlink) { + mtk_afe_platform.memif_dl_num = i; + break; + } + } + for (/**/; i < ARRAY_SIZE(afes); i++) + __ASSERT_NO_MSG(!afes[i].downlink); + + sof->dai_info = &mtk_dai_info; + sof->dma_info = &mtk_dma_info; + return 0; +} diff --git a/src/platform/mtk/include/platform/lib/clk.h b/src/platform/mtk/include/platform/lib/clk.h new file mode 100644 index 000000000000..de604ef4001d --- /dev/null +++ b/src/platform/mtk/include/platform/lib/clk.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_LIB_CLK_H +#define _SOF_PLATFORM_MTK_LIB_CLK_H + +#define CLK_CPU(x) (x) + +// FIXME: set correctly from mtk_adsp layer! +#define CLK_MAX_CPU_HZ CONFIG_XTENSA_CCOUNT_HZ + +#endif /* _SOF_PLATFORM_MTK_LIB_CLK_H */ diff --git a/src/platform/mtk/include/platform/lib/cpu.h b/src/platform/mtk/include/platform/lib/cpu.h new file mode 100644 index 000000000000..bd2b0c29640d --- /dev/null +++ b/src/platform/mtk/include/platform/lib/cpu.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_LIB_CPU_H +#define _SOF_PLATFORM_MTK_LIB_CPU_H + +#define PLATFORM_PRIMARY_CORE_ID 0 + +#endif /* _SOF_PLATFORM_MTK_LIB_CPU_H */ diff --git a/src/platform/mtk/include/platform/lib/dai.h b/src/platform/mtk/include/platform/lib/dai.h new file mode 100644 index 000000000000..82fca579236c --- /dev/null +++ b/src/platform/mtk/include/platform/lib/dai.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_LIB_DAI_H +#define _SOF_PLATFORM_MTK_LIB_DAI_H + +/* No symbols needed from this header, but included anyway */ + +#endif /* _SOF_PLATFORM_MTK_LIB_DAI_H */ diff --git a/src/platform/mtk/include/platform/lib/dma.h b/src/platform/mtk/include/platform/lib/dma.h new file mode 100644 index 000000000000..42f8adc4190b --- /dev/null +++ b/src/platform/mtk/include/platform/lib/dma.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_DMA_H +#define _SOF_PLATFORM_MTK_DMA_H + +/* Only needed in dma_multi_chan_domain.c */ +#define PLATFORM_NUM_DMACS 2 +#define PLATFORM_MAX_DMA_CHAN 32 + +#define dma_chan_irq(dma, chan) dma_irq(dma) +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) + +#endif /* _SOF_PLATFORM_MTK_DMA_H */ diff --git a/src/platform/mtk/include/platform/lib/mailbox.h b/src/platform/mtk/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..1157730ead57 --- /dev/null +++ b/src/platform/mtk/include/platform/lib/mailbox.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_LIB_MAILBOX_H +#define _SOF_PLATFORM_MTK_LIB_MAILBOX_H + +#include "memory.h" + +#define MAILBOX_DSPBOX_BASE MTK_IPC_WIN_BASE(UPBOX) +#define MAILBOX_DSPBOX_SIZE MTK_IPC_WIN_SIZE(UPBOX) + +#define MAILBOX_HOSTBOX_BASE MTK_IPC_WIN_BASE(DOWNBOX) +#define MAILBOX_HOSTBOX_SIZE MTK_IPC_WIN_SIZE(DOWNBOX) + +#define MAILBOX_STREAM_BASE MTK_IPC_WIN_BASE(STREAM) +#define MAILBOX_STREAM_SIZE MTK_IPC_WIN_SIZE(STREAM) + +#endif /* _SOF_PLATFORM_MTK_LIB_MAILBOX_H */ diff --git a/src/platform/mtk/include/platform/lib/memory.h b/src/platform/mtk/include/platform/lib/memory.h new file mode 100644 index 000000000000..26806ab394ba --- /dev/null +++ b/src/platform/mtk/include/platform/lib/memory.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_LIB_MEMORY_H +#define _SOF_PLATFORM_MTK_LIB_MEMORY_H + +#include <xtensa/config/core-isa.h> +#include <ipc/info.h> + +#define PLATFORM_DCACHE_ALIGN 128 + +/* Sigh, too many ways to get this wrong... */ +BUILD_ASSERT(PLATFORM_DCACHE_ALIGN == XCHAL_DCACHE_LINESIZE); + +#define uncache_to_cache(addr) (addr) +#define cache_to_uncache(addr) (addr) + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define host_to_local(addr) (addr) + +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +#define SHARED_DATA /* no special section attribute needed */ + +/* Mailbox window addresses for the rimage extended manifest. The + * struct is optimized out in generated code, it's just here to be a + * little clearer than the pages of #defines used traditionally. + * + * 8195 puts the window region at 8M into the DRAM memory space, + * everything else at 5M. Note that these are linkable addresses! + * There's nothing preventing a symbol from ending up here except the + * fact that SOF isn't (remotely) that big. Long term we should move + * this stuff into regular .bss/.noinit symbols, but that requires + * validation that the kernel driver interprets the manifest + * correctly. Right now we're using the historical addresses. + */ +#if defined(CONFIG_SOC_MT8195) || defined(CONFIG_SOC_MT8365) +#define MTK_IPC_BASE (DT_REG_ADDR(DT_NODELABEL(dram0)) + 0x800000) +#else +#define MTK_IPC_BASE (DT_REG_ADDR(DT_NODELABEL(dram0)) + 0x500000) +#endif + +/* Beware: the first two buffers are variously labelled UP/DOWN OUT/IN + * and DSP/HOST, and the correspondance isn't as clear as one would + * want. + */ +#define _MTK_WIN_SZ_K_UPBOX 4 +#define _MTK_WIN_SZ_K_DOWNBOX 4 +#define _MTK_WIN_SZ_K_DEBUG 2 +#define _MTK_WIN_SZ_K_EXCEPTION 2 +#define _MTK_WIN_SZ_K_STREAM 4 +#define _MTK_WIN_SZ_K_TRACE 4 + +#define _MTK_WIN_OFF_K_UPBOX 0 +#define _MTK_WIN_OFF_K_DOWNBOX (_MTK_WIN_SZ_K_UPBOX) +#define _MTK_WIN_OFF_K_DEBUG (_MTK_WIN_SZ_K_DOWNBOX + _MTK_WIN_OFF_K_DOWNBOX) +#define _MTK_WIN_OFF_K_EXCEPTION (_MTK_WIN_SZ_K_DEBUG + _MTK_WIN_OFF_K_DEBUG) +#define _MTK_WIN_OFF_K_STREAM (_MTK_WIN_SZ_K_EXCEPTION + _MTK_WIN_OFF_K_EXCEPTION) +#define _MTK_WIN_OFF_K_TRACE (_MTK_WIN_SZ_K_STREAM + _MTK_WIN_OFF_K_STREAM) + +#define MTK_IPC_WIN_OFF(reg) (1024 * _MTK_WIN_OFF_K_##reg) +#define MTK_IPC_WIN_SIZE(reg) (1024 * _MTK_WIN_SZ_K_##reg) +#define MTK_IPC_WIN_BASE(reg) (MTK_IPC_BASE + MTK_IPC_WIN_OFF(reg)) + +#endif /* _SOF_PLATFORM_MTK_LIB_MEMORY_H */ diff --git a/src/platform/mtk/include/platform/lib/pm_runtime.h b/src/platform/mtk/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..4d3bc1b3e1ef --- /dev/null +++ b/src/platform/mtk/include/platform/lib/pm_runtime.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_LIB_PM_RUNTIME_H +#define _SOF_PLATFORM_MTK_LIB_PM_RUNTIME_H + +#include <stdint.h> + +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 /* _SOF_PLATFORM_MTK_LIB_PM_RUNTIME_H */ diff --git a/src/platform/mtk/include/platform/platform.h b/src/platform/mtk/include/platform/platform.h new file mode 100644 index 000000000000..df4a4ca1ddfc --- /dev/null +++ b/src/platform/mtk/include/platform/platform.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_PLATFORM_H +#define _SOF_PLATFORM_MTK_PLATFORM_H + +#include <platform/lib/clk.h> + +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +#define HOST_PAGE_SIZE 4096 + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +#endif /* _SOF_PLATFORM_MTK_PLATFORM_H */ diff --git a/src/platform/mtk/include/platform/trace/trace.h b/src/platform/mtk/include/platform/trace/trace.h new file mode 100644 index 000000000000..bac2cd302ef3 --- /dev/null +++ b/src/platform/mtk/include/platform/trace/trace.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef _SOF_PLATFORM_MTK_TRACE_H +#define _SOF_PLATFORM_MTK_TRACE_H + +/* No legacy trace defined for this platform, but header required anyway */ + +#endif /* _SOF_PLATFORM_MTK_TRACE_H */ diff --git a/src/platform/mtk/platform.c b/src/platform/mtk/platform.c new file mode 100644 index 000000000000..c189af1f0a16 --- /dev/null +++ b/src/platform/mtk/platform.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2024 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <rtos/clk.h> +#include <platform/lib/memory.h> +#include <kernel/ext_manifest.h> +#include <sof/platform.h> +#include <sof/debug/debug.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/lib/agent.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/edf_schedule.h> +#include <sof_versions.h> +#include <sof/ipc/schedule.h> + +/* General platform glue code. In a Zephyr build, most of this is + * vestigial or degenerate, or at least evolving in that direction. + */ + +void mtk_dai_init(struct sof *sof); + +#ifndef CONFIG_SOC_MT8365 +#define MBOX0 DEVICE_DT_GET(DT_INST(0, mediatek_mbox)) +#define MBOX1 DEVICE_DT_GET(DT_INST(1, mediatek_mbox)) +#else +#define IPI DEVICE_DT_GET(DT_INST(0, mediatek_ipi)) + +#define MAILBOX_DEBUG_BASE MTK_IPC_WIN_BASE(DEBUG) + +#define SRAM_REG_OP_CPU2DSP 0x8 +#define SRAM_REG_OP_DSP2CPU 0xC + +#define ADSP_IPI_OP_REQ 0x1 +#define ADSP_IPI_OP_RSP 0x2 +#endif + +/* Use the same UUID as in "ipc-zephyr.c", which is actually an Intel driver */ +SOF_DEFINE_REG_UUID(zipc_task); + +#ifndef CONFIG_SOC_MT8365 +static void mbox_cmd_fn(const struct device *mbox, void *arg) +{ + /* We're in ISR context. This unblocks the IPC task thread, + * which calls ipc_do_cmd(), which calls back into + * ipc_platform_do_cmd() below, which then calls ipc_cmd(). + */ + ipc_schedule_process(ipc_get()); +} +#endif + +enum task_state ipc_platform_do_cmd(struct ipc *ipc) +{ + /* mailbox_validate() checks the command length (that's all it + * vaildates) and copies the incoming command from the host + * window to the comp_data buffer in the IPC object. + */ + struct ipc_cmd_hdr *hdr = mailbox_validate(); + + if (hdr) + ipc_cmd(hdr); + return SOF_TASK_STATE_COMPLETED; +} + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ +#ifndef CONFIG_SOC_MT8365 + mtk_adsp_mbox_signal(MBOX0, 1); +#else + *(uint32_t *)(MAILBOX_DEBUG_BASE + SRAM_REG_OP_DSP2CPU) = ADSP_IPI_OP_RSP; + mtk_adsp_ipi_signal(IPI, 1); +#endif +} + +static void mtk_ipc_send(const void *msg, size_t sz) +{ + mailbox_dspbox_write(0, msg, sz); +#ifndef CONFIG_SOC_MT8365 + mtk_adsp_mbox_signal(MBOX1, 0); +#else + *(uint32_t *)(MAILBOX_DEBUG_BASE + SRAM_REG_OP_DSP2CPU) = ADSP_IPI_OP_REQ; + mtk_adsp_ipi_signal(IPI, 1); +#endif +} + +int ipc_platform_send_msg(const struct ipc_msg *msg) +{ + struct ipc *ipc = ipc_get(); + + if (ipc->is_notification_pending) + return -EBUSY; + + ipc->is_notification_pending = true; + mtk_ipc_send(msg->tx_data, msg->tx_size); + return 0; +} + +#ifndef CONFIG_SOC_MT8365 +static void mbox_reply_fn(const struct device *mbox, void *arg) +{ + ipc_get()->is_notification_pending = false; +} + +#else + +static void ipi_handler_fn(const struct device *ipi, void *arg) +{ + uint32_t op; + + op = *(uint32_t *)(MAILBOX_DEBUG_BASE + SRAM_REG_OP_CPU2DSP); + + switch (op) { + case ADSP_IPI_OP_REQ: + /* new message from host */ + ipc_schedule_process(ipc_get()); + break; + case ADSP_IPI_OP_RSP: + /* reply message(done) from host */ + ipc_get()->is_notification_pending = false; + break; + default: + /* do nothing */ + break; + } +} +#endif + +/* "Host Page Table" support. The platform is responsible for + * providing a buffer into which the IPC layer reads a DMA "page + * table" from the host. This isn't really a page table, it's a + * packed array of PPN addresses (basically a scatter/gather list) + * used to configure the buffer used for dummy_dma, which is a "DMA" + * driver that works by directly copying data in shared memory. And + * somewhat confusingly, it's itself configured at runtime by "DMA" + * over the same mechanism (instead of e.g. by a IPC command, which + * would fit just fine!). All of this is degenerate with MTK anyway, + * because the actual addresses being passed are in a DRAM region + * dedicated for the purpose and are AFAICT guaranteed contiguous. + * + * Note: the 256 byte page table size is fixed by protocol in the + * linux driver, but here in SOF it's always been a platform symbol. + * But it's not tunable! Don't touch it. + */ +static uint8_t hostbuf_ptable[256]; +static struct ipc_data_host_buffer mtk_host_buffer; + +struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) +{ + return &mtk_host_buffer; +} + +/* Called out of ipc_init(), which is called out of platform_init() below */ +int platform_ipc_init(struct ipc *ipc) +{ + mtk_host_buffer.page_table = hostbuf_ptable; + mtk_host_buffer.dmac = dma_get(DMA_DIR_HMEM_TO_LMEM, 0, DMA_DEV_HOST, + DMA_ACCESS_SHARED); + + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(zipc_task_uuid), + &ipc_task_ops, ipc, 0, 0); + +#ifndef CONFIG_SOC_MT8365 + mtk_adsp_mbox_set_handler(MBOX0, 0, mbox_cmd_fn, NULL); + mtk_adsp_mbox_set_handler(MBOX1, 1, mbox_reply_fn, NULL); +#else + mtk_adsp_ipi_set_handler(IPI, 0, ipi_handler_fn, NULL); +#endif + return 0; +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} + +static int set_cpuclk(int clock, int hz) +{ + return clock == 0 && hz == CONFIG_XTENSA_CCOUNT_HZ ? 0 : -EINVAL; +} + +/* This is required out of dma_multi_chan_domain but nothing + * defines it in Zephyr builds. Stub with a noop here, + * knowing that MTK "DMA" "devices" don't have interrupts. + */ +void interrupt_clear_mask(uint32_t irq, uint32_t mask) +{ +} + +/* Dummy CPU clock driver that supports one known frequency. This + * hardware has clock scaling support, but it hasn't historically been + * exercised so we have nothing to test against. + */ +void clocks_init(struct sof *sof) +{ + static const struct freq_table freqs[] = { + { .freq = CONFIG_XTENSA_CCOUNT_HZ, + .ticks_per_msec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000, } + }; + static struct clock_info clks[] = { + { .freqs_num = ARRAY_SIZE(freqs), + .freqs = freqs, + .notification_id = NOTIFIER_ID_CPU_FREQ, + .notification_mask = NOTIFIER_TARGET_CORE_MASK(0), + .set_freq = set_cpuclk, }, + }; + sof->clocks = clks; +} + +int platform_init(struct sof *sof) +{ + clocks_init(sof); + scheduler_init_edf(); + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + mtk_dai_init(sof); + ipc_init(sof); + sof->platform_dma_domain = + dma_multi_chan_domain_init(&sof->dma_info->dma_array[0], + sof->dma_info->num_dmas, + PLATFORM_DEFAULT_CLOCK, false); + sa_init(sof, CONFIG_SYSTICK_PERIOD); + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + static const struct sof_ipc_fw_ready fw_ready_cmd = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.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, + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, + }; + + mtk_ipc_send(&fw_ready_cmd, sizeof(fw_ready_cmd)); + return 0; +} + +/* Extended manifest window record. Note the alignment attribute is + * critical as rimage demands allocation in units of 16 bytes, yet the + * C struct records emitted into the section are not in general padded + * and will pack tighter than that! (Really this is an rimage bug, it + * should separately validate each symbol in the section and re-pack + * the array instead of relying on the poor linker to do it). + */ +#define WINDOW(region) \ + { .type = SOF_IPC_REGION_##region, \ + .size = MTK_IPC_WIN_SIZE(region), \ + . offset = MTK_IPC_WIN_OFF(region), } +struct ext_man_windows mtk_man_win __section(".fw_metadata") __aligned(EXT_MAN_ALIGN) = { + .hdr = { + .type = EXT_MAN_ELEM_WINDOW, + .elem_size = ROUND_UP(sizeof(struct ext_man_windows), EXT_MAN_ALIGN) + }, + .window = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = 6, + .window = { + // Order doesn't match memory layout for historical + // reasons. Shouldn't matter, but don't rock the boat... + WINDOW(UPBOX), + WINDOW(DOWNBOX), + WINDOW(DEBUG), + WINDOW(TRACE), + WINDOW(STREAM), + WINDOW(EXCEPTION), + }, + }, +}; diff --git a/src/platform/mtk/tools/README.txt b/src/platform/mtk/tools/README.txt new file mode 100644 index 000000000000..a7b35f464e96 --- /dev/null +++ b/src/platform/mtk/tools/README.txt @@ -0,0 +1,17 @@ + +MTK AFE Generator tool +====================== + +Early versions of the AFE driver were published with large C struct +definitions tied to platform headers. Zephyr strongly prefers +Devicetree for configuration and not C code. + +So this is a somewhat klugey C program that builds and runs the AFE +platform code on a Linux host CPU, producing valid DTS output that can +be included in a board devicetree file in Zephyr. + +Just run ./build.sh from inside this directory. The only required +host software is a working gcc that supports the "-m32" flag. + +The resulting afe-<platform>.dts files can be included directly in +Zephyr board config. diff --git a/src/platform/mtk/tools/build.sh b/src/platform/mtk/tools/build.sh new file mode 100755 index 000000000000..1b17c8e38cf8 --- /dev/null +++ b/src/platform/mtk/tools/build.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Google LLC. All rights reserved. +# Author: Andy Ross <andyross@google.com> +set -ex + +PLATFORMS="$*" +if [ -z "$PLATFORMS" ]; then + PLATFORMS="mt8195 mt8188 mt8186" +fi + +SOF=`cd ../../../..; /bin/pwd` + +for p in $PLATFORMS; do + + SRCS="$SOF/src/platform/$p/lib/dai.c $SOF/src/platform/$p/afe-platform.c" + + INCS="-I$SOF/src/include -I$SOF/src/platform/posix/include -I$SOF/posix/include" + INCS="$INCS -I$SOF/src/arch/host/include -I$SOF/src/platform/$p/include/platform" + INCS="$INCS -I$SOF/src/platform/$p/include" + + DEFS="-DRELATIVE_FILE=\"mt-dai-gen.c\" -DCONFIG_CORE_COUNT=1 -DCONFIG_IPC_MAJOR_3=1" + + touch uuid-registry.h + INCS="$INCS -I." + + gcc -g -Wall -Werror -m32 -o mt-dai-gen mt-dai-gen.c $SRCS $INCS $DEFS + + ./mt-dai-gen > afe-${p}.dts +done diff --git a/src/platform/mtk/tools/mt-dai-gen.c b/src/platform/mtk/tools/mt-dai-gen.c new file mode 100644 index 000000000000..9c3ae67013a8 --- /dev/null +++ b/src/platform/mtk/tools/mt-dai-gen.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2024 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <sof/lib/dai-legacy.h> +#include <sof/drivers/afe-drv.h> +#include <stdio.h> + +/* DIY assertion, an "assert()" is already defined in platform headers */ +#define CHECK(expr) do { if (!(expr)) { \ + printf("FAILED: " #expr " at line %d\n", __LINE__); \ + *(int *)0 = 0; } \ + } while (false) + +/* These are the symbols we need to enumerate */ +extern struct mtk_base_afe_platform mtk_afe_platform; +extern const struct dai_info lib_dai; + +/* Call this to initialize the dai arrays */ +int dai_init(struct sof *sof); + +/* Debug hook in some versions of MTK firmware */ +void printf_(void) {} + +/* Just need a pointer to a symbol with this name */ +int afe_dai_driver; + +/* So dai_init() can write to something */ +struct sof sof; + +unsigned int afe_base_addr; + +void symify(char *s) +{ + for (; *s; s++) { + if (*s >= 'A' && *s <= 'Z') + *s += 'a' - 'A'; + CHECK((*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9') || *s == '_'); + } +} + +/* The AFE driver has some... idiosyncratic defaulting. The existing + * configurations have a varying set of conventions to encode "no + * value is set": + * + * ch_num is skipped if the stored reg value is negative + * quad_ch is skipped if the mask is zero + * int_odd: reg <=0 + * mono: reg <=0 OR shift <=0 + * msb: reg <=0 + * msb2: reg <=0 + * agent_disable: reg <=0 + * fs: never skipped + * hd: never skipped + * enable: never skipped + * + * We detect the union of those conditions and elide the setting (it + * will be defaulted to reg=-1/shift=0/mask=0 in the driver DTS macros) + */ +void print_fld(const char *name, int reg, int shift, int lomask) +{ + if (reg <= 0 || shift < 0 || lomask == 0) + return; + + int bits = __builtin_ffs(lomask + 1) - 1; + + CHECK(((lomask + 1) & lomask) == 0); /* must be proper mask in low bits */ + CHECK(lomask); /* and not zero */ + CHECK(shift >= 0 && (shift + bits) <= 32); /* and shift doesn't overrun */ + + printf("\t\t%s = <0x%8.8x %d %d>;\n", + name, reg + afe_base_addr, shift, bits); +} + +unsigned int msbaddr(int val) +{ + return val ? val + afe_base_addr : 0; +} + +int main(void) +{ + dai_init(&sof); + + afe_base_addr = mtk_afe_platform.base_addr; + + /* The DAI order here is immutable: the indexes are known to and + * used by the kernel driver. And these point to the memif array + * via an index stored in the low byte (?!) of the first fifo's + * "handshake" (it's not a DMA handshake value at all). So we + * invert the mapping and store the dai index along with the AFE + * record. + */ + int dai_memif[64]; + int num_dais = 0; + + for (int t = 0; t < lib_dai.num_dai_types; t++) { + for (int i = 0; i < lib_dai.dai_type_array[t].num_dais; i++) { + int idx = lib_dai.dai_type_array[t].dai_array[i].index; + int hs = lib_dai.dai_type_array[t].dai_array[i].plat_data.fifo[0].handshake; + + CHECK(idx == num_dais); + dai_memif[num_dais++] = hs >> 16; + } + } + + /* Quick check that the dai/memif mapping is unique */ + for (int i = 0; i < num_dais; i++) { + int n = 0; + + for (int j = 0; j < num_dais; j++) + if (dai_memif[j] == i) + n++; + CHECK(n == 1); + } + + for (int i = 0; i < mtk_afe_platform.memif_size; i++) { + const struct mtk_base_memif_data *m = &mtk_afe_platform.memif_datas[i]; + + int dai_id = -1; + + for (int j = 0; j < num_dais; j++) { + if (dai_memif[j] == i) { + dai_id = j; + break; + } + } + CHECK(dai_id >= 0); + + /* We use the UL/DL naming to detect direction, make + * sure it isn't broken + */ + bool uplink = !!strstr(m->name, "UL"); + bool downlink = !!strstr(m->name, "DL"); + + CHECK(uplink != downlink); + + /* Validate and lower-case the name to make a DTS symbol */ + char sym[64]; + + CHECK(strlen(m->name) < sizeof(sym)); + strcpy(sym, m->name); + symify(sym); + + printf("\tafe_%s: afe_%s {\n", sym, sym); + printf("\t\tcompatible = \"mediatek,afe\";\n"); + printf("\t\tafe_name = \"%s\";\n", m->name); + printf("\t\tdai_id = <%d>;\n", dai_id); + if (downlink) + printf("\t\tdownlink;\n"); + + /* Register pairs containing the high and low words of + * bus/host addresses. The first (high) register is allowed + * to be zero indicating all addresses will be 32 bit. + */ + printf("\t\tbase = <0x%8.8x 0x%8.8x>;\n", + msbaddr(m->reg_ofs_base_msb), m->reg_ofs_base + afe_base_addr); + printf("\t\tcur = <0x%8.8x 0x%8.8x>;\n", + msbaddr(m->reg_ofs_cur_msb), m->reg_ofs_cur + afe_base_addr); + printf("\t\tend = <0x%8.8x 0x%8.8x>;\n", + msbaddr(m->reg_ofs_end_msb), m->reg_ofs_end + afe_base_addr); + + print_fld("fs", m->fs_reg, m->fs_shift, m->fs_maskbit); + print_fld("mono", m->mono_reg, m->mono_shift, 1); + if (m->mono_invert) + printf("\t\tmono_invert;\n"); + print_fld("quad_ch", m->quad_ch_reg, m->quad_ch_shift, m->quad_ch_mask); + print_fld("int_odd", m->int_odd_flag_reg, m->int_odd_flag_shift, 1); + print_fld("enable", m->enable_reg, m->enable_shift, 1); + print_fld("hd", m->hd_reg, m->hd_shift, 1); + print_fld("msb", m->msb_reg, m->msb_shift, 1); + print_fld("msb2", m->msb2_reg, m->msb2_shift, 1); + print_fld("agent_disable", m->agent_disable_reg, m->agent_disable_shift, 1); + print_fld("ch_num", m->ch_num_reg, m->ch_num_shift, m->ch_num_maskbit); + + /* Note: there are also "pbuf" and "minlen" registers defined + * in the memif_data struct, but they are unused by the + * existing driver. + */ + + printf("\t};\n\n"); + } +} diff --git a/src/platform/novalake/include/platform/lib/clk.h b/src/platform/novalake/include/platform/lib/clk.h new file mode 100644 index 000000000000..e4017efcf329 --- /dev/null +++ b/src/platform/novalake/include/platform/lib/clk.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include <ace/lib/clk.h> + +#define CLK_MAX_CPU_HZ CONFIG_XTENSA_CCOUNT_HZ + +#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 NUM_CPU_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/novalake/include/platform/lib/mailbox.h b/src/platform/novalake/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..7d253fd9327e --- /dev/null +++ b/src/platform/novalake/include/platform/lib/mailbox.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include <ace/lib/mailbox.h> + +#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/novalake/include/platform/lib/memory.h b/src/platform/novalake/include/platform/lib/memory.h new file mode 100644 index 000000000000..666c4fc9eb89 --- /dev/null +++ b/src/platform/novalake/include/platform/lib/memory.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + * + * Author: Marcin Rajwa <marcin.rajwa@linux.intel.com> + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +/* prioritize definitions in Zephyr SoC layer */ +#include <adsp_memory.h> + +#include <ace/lib/memory.h> +#include <mem_window.h> +#include <sof/lib/cpu.h> + +/* 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 (CONFIG_SOF_STACK_SIZE) + +#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 CONFIG_SOF_ZEPHYR_HEAP_SIZE + +#if CONFIG_COLD_STORE_EXECUTE_DRAM && \ + (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD)) +#define __cold __section(".cold") +#define __cold_rodata __section(".coldrodata") +#endif + +#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/novalake/include/platform/platform.h b/src/platform/novalake/include/platform/platform.h new file mode 100644 index 000000000000..62ba6a24fe97 --- /dev/null +++ b/src/platform/novalake/include/platform/platform.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Rander Wang <rander.wang@intel.com> + * Xiuli Pan <xiuli.pan@linux.intel.com> + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#include <rtos/clk.h> + +/*! \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) + +#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/novalake/include/platform/trace/trace.h b/src/platform/novalake/include/platform/trace/trace.h new file mode 100644 index 000000000000..2e1e6022854f --- /dev/null +++ b/src/platform/novalake/include/platform/trace/trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2024 Intel Corporation. + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include <sof/lib/cpu.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/memory.h> +#include <stdint.h> + +/* 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/novalake/lib/clk.c b/src/platform/novalake/lib/clk.c new file mode 100644 index 000000000000..29a69aaab1d3 --- /dev/null +++ b/src/platform/novalake/lib/clk.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2024 Intel Corporation. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/common.h> +#include <rtos/clk.h> + +static const struct freq_table platform_cpu_freq[] = { + { 38400000, 38400 }, + { 120000000, 120000 }, + { CLK_MAX_CPU_HZ, CLK_MAX_CPU_HZ / 1000 } +}; + +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/base_fw_platform.c b/src/platform/posix/base_fw_platform.c new file mode 100644 index 000000000000..79bf0d9b33ca --- /dev/null +++ b/src/platform/posix/base_fw_platform.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. +// +// Author: Kai Vehmanen <kai.vehmanen@linux.intel.com> + +#include <stdint.h> +#include <stddef.h> +#include <ipc4/error_status.h> +#include <ipc4/base_fw_platform.h> + +int platform_basefw_fw_config(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + +int platform_basefw_hw_config(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + +struct sof_man_fw_desc *platform_base_fw_get_manifest(void) +{ + struct sof_man_fw_desc *desc = NULL; + + return desc; +} + +int platform_basefw_modules_info_get(uint32_t *data_offset, char *data) +{ + *data_offset = 0; + + return 0; +} + +int platform_basefw_get_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t *data_offset, + char *data) +{ + return -EINVAL; +} + +int platform_basefw_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + return IPC4_UNKNOWN_MESSAGE_TYPE; +} diff --git a/src/platform/posix/dai.c b/src/platform/posix/dai.c new file mode 100644 index 000000000000..3fdaa61ff44d --- /dev/null +++ b/src/platform/posix/dai.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2022 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <sof/lib/dai-legacy.h> + +#define NUM_DAI_TYPES 12 +#define DAIS_PER_TYPE 2 + +uint8_t useless_sum; + +static int pdai_set_config(struct dai *dai, struct ipc_config_dai *config, + const void *spec_config) +{ + for (int i = 0; config && i < sizeof(*config); i++) + useless_sum += ((uint8_t *)config)[i]; + return 0; +} + +static int pdai_trigger(struct dai *dai, int cmd, int direction) +{ + return 0; +} + +static int pdai_get_hw_params(struct dai *dai, + struct sof_ipc_stream_params *params, int dir) +{ + // FIXME: this is a polymorphic struct with extra + // type-specific data at the end, may need to do this more + // intelligently. + memset(params, 0, sizeof(*params)); + return 0; +} + +static int pdai_hw_params(struct dai *dai, struct sof_ipc_stream_params *params) +{ + for (int i = 0; params && i < sizeof(*params); i++) + useless_sum += ((uint8_t *)params)[i]; + return 0; +} + +static int pdai_get_handshake(struct dai *dai, int direction, int stream_id) +{ + return 0; +} + +static int pdai_get_fifo(struct dai *dai, int direction, int stream_id) +{ + return 0; +} + +static int pdai_probe(struct dai *dai) +{ + return 0; +} + +static int pdai_remove(struct dai *dai) +{ + return 0; +} + +static uint32_t pdai_get_init_delay_ms(struct dai *dai) +{ + return 0; +} + +static int pdai_get_fifo_depth(struct dai *dai, int direction) +{ + return 0; +} + +static void pdai_copy(struct dai *dai) +{ +} + +const struct dai_ops posix_dai_ops = { + .set_config = pdai_set_config, + .trigger = pdai_trigger, + .get_hw_params = pdai_get_hw_params, + .hw_params = pdai_hw_params, + .get_handshake = pdai_get_handshake, + .get_fifo = pdai_get_fifo, + .probe = pdai_probe, + .remove = pdai_remove, + .get_init_delay_ms = pdai_get_init_delay_ms, + .get_fifo_depth = pdai_get_fifo_depth, + .copy = pdai_copy, +}; + +static struct dai_type_info dai_types[NUM_DAI_TYPES]; +static struct dai_driver dai_drivers[NUM_DAI_TYPES]; +static struct dai dais[NUM_DAI_TYPES][DAIS_PER_TYPE]; + +static const struct dai_info posix_dai_info = { + .dai_type_array = dai_types, + .num_dai_types = ARRAY_SIZE(dai_types), +}; + +void posix_dai_init(struct sof *sof) +{ + for (int type = 0; type < ARRAY_SIZE(dai_types); type++) { + dai_types[type].type = type; + dai_types[type].dai_array = &dais[type][0]; + dai_types[type].num_dais = DAIS_PER_TYPE; + + dai_drivers[type].type = type; + //dai_drivers[type].uid = ???; + //dai_drivers[type].tctx = ???; + dai_drivers[type].dma_caps = BIT(0); + dai_drivers[type].dma_dev = BIT(0); + dai_drivers[type].ops = posix_dai_ops; + //dai_drivers[type].ts_ops = ???; + + for (int i = 0; i < DAIS_PER_TYPE; i++) { + dais[type][i].index = i; + dais[type][i].drv = &dai_drivers[type]; + } + } + + sof->dai_info = &posix_dai_info; +} diff --git a/src/platform/posix/dma.c b/src/platform/posix/dma.c new file mode 100644 index 000000000000..63ab0c31e069 --- /dev/null +++ b/src/platform/posix/dma.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2022 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <zephyr/drivers/dma.h> +#include <sof/lib/dma.h> + +/* Zephyr "DMA" stub device */ + +#define NUM_CHANS 2 + +/* Note that the spinlock in this struct isn't really needed for + * native_posix, which can't preempt app code. But it's here for + * correctness in case anyone wants to port this to a different test + * environment. + */ +struct pzdma_data { + struct dma_context ctx; /* MUST BE FIRST! See API docs */ + struct k_spinlock lock; + atomic_t chan_atom; /* weird API... */ + struct { + struct dma_config cfg; + uint32_t src, dst, sz; + bool started; + bool suspended; + } chans[NUM_CHANS]; +}; + +struct pzdma_cfg { + int id; +}; + +static int pzdma_config(const struct device *dev, uint32_t channel, + struct dma_config *config) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + __ASSERT_NO_MSG(!dev_data->chans[channel].started); + + dev_data->chans[channel].cfg = *config; + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static int pzdma_reload(const struct device *dev, uint32_t channel, + uint32_t src, uint32_t dst, size_t size) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + __ASSERT_NO_MSG(!dev_data->chans[channel].started); + + dev_data->chans[channel].src = src; + dev_data->chans[channel].dst = dst; + dev_data->chans[channel].sz = size; + + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static int pzdma_suspend(const struct device *dev, uint32_t channel) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + __ASSERT_NO_MSG(dev_data->chans[channel].started); + __ASSERT_NO_MSG(!dev_data->chans[channel].suspended); + dev_data->chans[channel].suspended = true; + + // FIXME: cancel callback + + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static int pzdma_resume(const struct device *dev, uint32_t channel) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + __ASSERT_NO_MSG(dev_data->chans[channel].started); + __ASSERT_NO_MSG(dev_data->chans[channel].suspended); + dev_data->chans[channel].suspended = false; + + // FIXME: resume callback + + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static int pzdma_start(const struct device *dev, uint32_t channel) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + __ASSERT_NO_MSG(!dev_data->chans[channel].started); + dev_data->chans[channel].started = true; + dev_data->chans[channel].suspended = true; + pzdma_resume(dev, channel); + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static int pzdma_stop(const struct device *dev, uint32_t channel) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + __ASSERT_NO_MSG(dev_data->chans[channel].started); + + if (!dev_data->chans[channel].suspended) + pzdma_suspend(dev, channel); + + dev_data->chans[channel].started = false; + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static int pzdma_get_status(const struct device *dev, uint32_t channel, + struct dma_status *status) +{ + struct pzdma_data *dev_data = dev->data; + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + // FIXME: synthesize offsets + + k_spin_unlock(&dev_data->lock, key); + return 0; +} + +static bool pzdma_chan_filter(const struct device *dev, + int channel, void *filter_param) +{ + return true; +} + +static int pzdma_init(const struct device *dev) +{ + struct pzdma_data *dev_data = dev->data; + + dev_data->ctx.magic = DMA_MAGIC; + dev_data->ctx.dma_channels = NUM_CHANS; + dev_data->ctx.atomic = &dev_data->chan_atom; /* ... why?! */ + return 0; +} + +/* Zephyr device definition */ + +static DEVICE_API(dma, pzdma_api) = { + .config = pzdma_config, + .reload = pzdma_reload, + .start = pzdma_start, + .stop = pzdma_stop, + .suspend = pzdma_suspend, + .resume = pzdma_resume, + .get_status = pzdma_get_status, + .chan_filter = pzdma_chan_filter, +}; + +struct pzdma_data pzdma0_data; +struct pzdma_data pzdma1_data; +struct pzdma_data pzdma2_data; +struct pzdma_data pzdma3_data; + +const struct pzdma_cfg pzdma0_cfg = { .id = 0 }; +const struct pzdma_cfg pzdma1_cfg = { .id = 1 }; +const struct pzdma_cfg pzdma2_cfg = { .id = 2 }; +const struct pzdma_cfg pzdma3_cfg = { .id = 3 }; + +DEVICE_DEFINE(pzdma0, "pzdma0", pzdma_init, NULL, &pzdma0_data, &pzdma0_cfg, + POST_KERNEL, 0, &pzdma_api); +DEVICE_DEFINE(pzdma1, "pzdma1", pzdma_init, NULL, &pzdma1_data, &pzdma1_cfg, + POST_KERNEL, 0, &pzdma_api); +DEVICE_DEFINE(pzdma2, "pzdma2", pzdma_init, NULL, &pzdma2_data, &pzdma2_cfg, + POST_KERNEL, 0, &pzdma_api); +DEVICE_DEFINE(pzdma3, "pzdma3", pzdma_init, NULL, &pzdma3_data, &pzdma3_cfg, + POST_KERNEL, 0, &pzdma_api); + +struct sof_dma posix_sof_dma[4]; + +const struct dma_info posix_sof_dma_info = { + .dma_array = posix_sof_dma, + .num_dmas = ARRAY_SIZE(posix_sof_dma), +}; + +void posix_dma_init(struct sof *sof) +{ + /* DEVICE_DEFINE() used to produce proper C identifiers, and + * is still documented that way, but now they have a + * "__device_" prefix... + */ + const struct device *devs[] = { + &__device_pzdma0, &__device_pzdma1, &__device_pzdma2, &__device_pzdma3 + }; + + for (int i = 0; i < ARRAY_SIZE(posix_sof_dma); i++) { + posix_sof_dma[i] = (struct sof_dma) {}; + posix_sof_dma[i].plat_data.dir = 0xffffffff; + posix_sof_dma[i].plat_data.caps = 0xffffffff; + posix_sof_dma[i].plat_data.devs = 0xffffffff; + posix_sof_dma[i].plat_data.channels = NUM_CHANS; + posix_sof_dma[i].z_dev = devs[i]; + }; + + sof->dma_info = &posix_sof_dma_info; +} diff --git a/src/platform/posix/fuzz.c b/src/platform/posix/fuzz.c new file mode 100644 index 000000000000..555a22d40578 --- /dev/null +++ b/src/platform/posix/fuzz.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2024 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> + +#include <stdint.h> +#include <stddef.h> +#include <stdbool.h> + +#include <irq_ctrl.h> +#include <zephyr/sys/time_units.h> +#include <nsi_cpu_if.h> +#include <nsi_main_semipublic.h> + +const uint8_t *posix_fuzz_buf; +size_t posix_fuzz_sz; + +/** + * Entry point for fuzzing. Works by placing the data + * into two known symbols, triggering an app-visible interrupt, and + * then letting the simulator run for a fixed amount of time (intended to be + * "long enough" to handle the event and reach a quiescent state + * again) + */ +NATIVE_SIMULATOR_IF +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) +{ + static bool runner_initialized; + + if (!runner_initialized) { + nsi_init(0, NULL); + runner_initialized = true; + } + + /* Provide the fuzz data to the embedded OS as an interrupt, with + * "DMA-like" data placed into native_fuzz_buf/sz + */ + posix_fuzz_buf = (void *)data; + posix_fuzz_sz = sz; + hw_irq_ctrl_set_irq(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); + + /* Give the OS time to process whatever happened in that + * interrupt and reach an idle state. + */ + nsi_exec_for(k_ticks_to_us_ceil64(CONFIG_ZEPHYR_POSIX_FUZZ_TICKS)); + return 0; +} diff --git a/src/platform/posix/include/platform/drivers/idc.h b/src/platform/posix/include/platform/drivers/idc.h new file mode 100644 index 000000000000..9d96891c141d --- /dev/null +++ b/src/platform/posix/include/platform/drivers/idc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_POSIX_DRIVERS_IDC_H +#define PLATFORM_POSIX_DRIVERS_IDC_H + +#include <stdint.h> +#include <rtos/idc.h> + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +#endif /* PLATFORM_POSIX_DRIVERS_IDC_H */ diff --git a/src/platform/posix/include/platform/drivers/interrupt.h b/src/platform/posix/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..d88916847428 --- /dev/null +++ b/src/platform/posix/include/platform/drivers/interrupt.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_POSIX_PLATFORM_DRIVERS_INTERRUPT_H +#define PLATFORM_POSIX_PLATFORM_DRIVERS_INTERRUPT_H + +#define PLATFORM_IRQ_FIRST_CHILD 0 + +#endif /* PLATFORM_POSIX_PLATFORM_DRIVERS_INTERRUPT_H */ diff --git a/src/platform/posix/include/platform/lib/clk.h b/src/platform/posix/include/platform/lib/clk.h new file mode 100644 index 000000000000..7d396330a0cb --- /dev/null +++ b/src/platform/posix/include/platform/lib/clk.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ + +#define CLK_MAX_CPU_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC +#define CPU_LPRO_FREQ_IDX 1 +#define CPU_LOWEST_FREQ_IDX CPU_LPRO_FREQ_IDX + +/* 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/cpu.h b/src/platform/posix/include/platform/lib/cpu.h new file mode 100644 index 000000000000..801018cd3087 --- /dev/null +++ b/src/platform/posix/include/platform/lib/cpu.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#define PLATFORM_PRIMARY_CORE_ID 0 + +void platform_wait_for_interrupt(int lvl); diff --git a/src/platform/posix/include/platform/lib/dai.h b/src/platform/posix/include/platform/lib/dai.h new file mode 100644 index 000000000000..02b58fb55681 --- /dev/null +++ b/src/platform/posix/include/platform/lib/dai.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ + +#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/dma.h b/src/platform/posix/include/platform/lib/dma.h new file mode 100644 index 000000000000..809ae9127af1 --- /dev/null +++ b/src/platform/posix/include/platform/lib/dma.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_POSIX_LIB_DMA_H +#define PLATFORM_POSIX_LIB_DMA_H + +#define FIXME_DMA_IRQ 999 +#define dma_chan_irq(dma, chan) FIXME_DMA_IRQ +#define dma_chan_irq_name(dma, chan) "FIXME_DMA_NAME" + +#define PLATFORM_NUM_DMACS 6 +#define PLATFORM_MAX_DMA_CHAN 9 + +#endif /* PLATFORM_POSIX_LIB_DMA_H */ diff --git a/src/platform/posix/include/platform/lib/mailbox.h b/src/platform/posix/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..3a42e93f6ea2 --- /dev/null +++ b/src/platform/posix/include/platform/lib/mailbox.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_POSIX_LIB_MAILBOX_H +#define PLATFORM_POSIX_LIB_MAILBOX_H + +#include <platform/lib/memory.h> + +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 new file mode 100644 index 000000000000..e15e5f370aec --- /dev/null +++ b/src/platform/posix/include/platform/lib/memory.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_HOST_PLATFORM_MEMORY_H +#define PLATFORM_HOST_PLATFORM_MEMORY_H + +#include <stdint.h> + +#define PLATFORM_DCACHE_ALIGN 64 +#define uncache_to_cache(addr) (addr) +#define cache_to_uncache(addr) (addr) + +extern uint32_t posix_hostbox[]; +#define MAILBOX_HOSTBOX_SIZE 1024 +#define MAILBOX_HOSTBOX_BASE (&posix_hostbox[0]) + +extern uint32_t posix_dspbox[]; +#define MAILBOX_DSPBOX_SIZE 4096 +#define MAILBOX_DSPBOX_BASE (&posix_dspbox[0]) + +extern uint32_t posix_stream[]; +#define MAILBOX_STREAM_SIZE 4096 +#define MAILBOX_STREAM_BASE (&posix_stream[0]) + +extern uint32_t posix_trace[]; +#define MAILBOX_TRACE_BASE (&posix_trace[0]) +#define MAILBOX_TRACE_SIZE 4096 + +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +#define host_to_local(addr) (addr) + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define SHARED_DATA /**/ + +#endif /* PLATFORM_HOST_PLATFORM_MEMORY_H */ diff --git a/src/platform/posix/include/platform/lib/pm_runtime.h b/src/platform/posix/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..db12e36c7d45 --- /dev/null +++ b/src/platform/posix/include/platform/lib/pm_runtime.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_LIB_PM_RUNTIME_H +#define PLATFORM_LIB_PM_RUNTIME_H + +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 */ diff --git a/src/platform/posix/include/platform/platform.h b/src/platform/posix/include/platform/platform.h new file mode 100644 index 000000000000..aae9ac4be4f9 --- /dev/null +++ b/src/platform/posix/include/platform/platform.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_POSIX_PLATFORM_PLATFORM_H +#define PLATFORM_POSIX_PLATFORM_PLATFORM_H + +#include <platform/lib/memory.h> + +#define DMA_TRACE_LOCAL_SIZE 8192 + +#define HOST_PAGE_SIZE 4096 + +#define PLATFORM_MAX_CHANNELS 8 + +#define PLATFORM_MAX_STREAMS 16 + +#define DMA_TRACE_PERIOD 500000 +#define DMA_TRACE_RESCHEDULE_TIME 500000 + +#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) + +#define PLATFORM_DEFAULT_CLOCK 0 + +#define PLATFORM_DEFAULT_DELAY 12 + +#define HW_CFG_VERSION 0x010000 + +struct sof; + +void posix_dma_init(struct sof *sof); +void posix_dai_init(struct sof *sof); + +#endif /* PLATFORM_POSIX_PLATFORM_PLATFORM_H */ diff --git a/src/platform/posix/include/platform/trace/trace.h b/src/platform/posix/include/platform/trace/trace.h new file mode 100644 index 000000000000..76ca72210b37 --- /dev/null +++ b/src/platform/posix/include/platform/trace/trace.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Google LLC. All rights reserved. + * Author: Andy Ross <andyross@google.com> + */ +#ifndef PLATFORM_POSIX_TRACE_TRACE_H +#define PLATFORM_POSIX_TRACE_TRACE_H + +#define platform_trace_point(x) /**/ + +#endif /* PLATFORM_POSIX_TRACE_TRACE_H */ + diff --git a/src/platform/posix/ipc.c b/src/platform/posix/ipc.c new file mode 100644 index 000000000000..701686e6ff97 --- /dev/null +++ b/src/platform/posix/ipc.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2022 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <sof/lib/uuid.h> +#include <sof/ipc/msg.h> +#include <sof/lib/mailbox.h> +#include <sof/ipc/common.h> +#include <sof/ipc/schedule.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/audio/component_ext.h> + +// 6c8f0d53-ff77-4ca1-b825-c0c4e1b0d322 +SOF_DEFINE_REG_UUID(ipc_task_posix); + +static struct ipc *global_ipc; + +// Not an ISR, called from the native_posix fuzz interrupt. Left +// alone for general hygiene. This is how a IPC interrupt would look +// if we had one. +static void posix_ipc_isr(void *arg) +{ + ipc_schedule_process(global_ipc); +} + +// External symbols set up by the fuzzing layer +extern uint8_t *posix_fuzz_buf, posix_fuzz_sz; + +// Lots of space. Should really synchronize with the -max_len +// parameter to libFuzzer (defaults to 4096), but that requires +// thinking/experimentation about how much fuzzing we want to do at a +// time... +static uint8_t fuzz_in[65536]; +static size_t fuzz_in_sz; + +// The protocol here is super simple: the first byte is a message size +// in units of 16 bits (the buffer maximum defaults to 384 bytes, and +// I didn't want to waste space early in the buffer lest I confuse the +// fuzzing heuristics). We then copy that much of the input buffer +// (subject to clamping obviously) into the incoming IPC message +// buffer and invoke the ISR. Any remainder will be delivered +// synchronously as another message after receipt of "complete_cmd()" +// from the SOF engine, etc... Eventually we'll receive another fuzz +// input after some amount of simulated time has passed (c.f. +// CONFIG_ZEPHYR_POSIX_FUZZ_TICKS) +static void fuzz_isr(const void *arg) +{ + size_t rem, i, n = MIN(posix_fuzz_sz, sizeof(fuzz_in) - fuzz_in_sz); + + for (i = 0; i < n; i++) + fuzz_in[fuzz_in_sz++] = posix_fuzz_buf[i]; + + if (fuzz_in_sz == 0) + return; + + if (!global_ipc->comp_data) + return; + + size_t maxsz = SOF_IPC_MSG_MAX_SIZE - 4, msgsz = fuzz_in[0] * 2; + + n = MIN(msgsz, MIN(fuzz_in_sz - 1, maxsz)); + rem = fuzz_in_sz - (n + 1); + + memset(global_ipc->comp_data, 0, maxsz); + memcpy(global_ipc->comp_data, &fuzz_in[1], n); + memmove(&fuzz_in[0], &fuzz_in[n + 1], rem); + fuzz_in_sz = rem; + +#ifdef CONFIG_IPC_MAJOR_3 + bool comp_new = false; + int comp_idx = 0; + + // 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" + // command, which we format specially, with a driver index + // specified by the second byte (modulo the number of + // registered drivers). This command involves matching + // against a UUID value, which even fuzzing isn't able to + // discover at runtime. So unless we whitebox this, no + // components will be created. + if (n > 2 && ((uint8_t *)global_ipc->comp_data)[0] == 0xff) { + comp_new = true; + comp_idx = ((uint8_t *)global_ipc->comp_data)[1]; + } + + // The first dword is a size value which fuzzing will stumble + // on only rarely, fill it in manually. + *(uint32_t *)global_ipc->comp_data = msgsz; + + // "Adjust" the command to represent a "comp new" command per + // above. Basically we want to copy in the UUID value for one + // of the runtime-enumerated drivers based on data already + // randomized in the fuzz command. + if (comp_new) { + struct { + struct sof_ipc_comp comp; + struct sof_ipc_comp_ext ext; + } *cmd = global_ipc->comp_data; + + // Set global/command type fields to TPLG_MSG/TPLG_COMP_NEW + cmd->comp.hdr.cmd &= 0x0000ffff; + cmd->comp.hdr.cmd |= SOF_IPC_GLB_TPLG_MSG; + cmd->comp.hdr.cmd |= SOF_IPC_TPLG_COMP_NEW; + + // We have only one core available in native_posix + cmd->comp.core = 0; + + // Fix up cmd size and ext_data_length to match + if (cmd->comp.hdr.size < sizeof(*cmd)) + cmd->comp.hdr.size = sizeof(*cmd); + cmd->comp.ext_data_length = cmd->comp.hdr.size - sizeof(cmd->comp); + + // Extract the list of available component drivers (do + // it every time; in practice I don't think this + // changes at runtime but in principle it might in the + // future) + int ndrvs = 0; + static struct comp_driver_info *drvs[256]; + struct list_item *iter; + struct comp_driver_list *dlist = comp_drivers_get(); + list_for_item(iter, &dlist->list) { + struct comp_driver_info *inf = + container_of(iter, struct comp_driver_info, list); + drvs[ndrvs++] = inf; + } + + 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... 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, 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) +{ + extern void posix_sw_set_pending_IRQ(unsigned int IRQn); + + if (fuzz_in_sz > 0) { + posix_fuzz_sz = 0; + posix_sw_set_pending_IRQ(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); + } +} + +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_ZEPHYR_POSIX_FUZZ_IRQ, 0, fuzz_isr, NULL, 0); + irq_enable(CONFIG_ZEPHYR_POSIX_FUZZ_IRQ); + + global_ipc = ipc; + schedule_task_init_edf(&ipc->ipc_task, SOF_UUID(ipc_task_posix_uuid), + &ipc_task_ops, ipc, 0, 0); + + return 0; +} diff --git a/src/platform/posix/posix.c b/src/platform/posix/posix.c new file mode 100644 index 000000000000..cea923d91ef1 --- /dev/null +++ b/src/platform/posix/posix.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2022 Google LLC. All rights reserved. +// Author: Andy Ross <andyross@google.com> +#include <sof/ipc/driver.h> +#include <rtos/task.h> +#include <sof/platform.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/lib/agent.h> + +uint32_t posix_hostbox[MAILBOX_HOSTBOX_SIZE / sizeof(uint32_t)]; +uint32_t posix_dspbox[MAILBOX_DSPBOX_SIZE / sizeof(uint32_t)]; +uint32_t posix_stream[MAILBOX_STREAM_SIZE / sizeof(uint32_t)]; +uint32_t posix_trace[MAILBOX_TRACE_SIZE / sizeof(uint32_t)]; + +/* This seems like a vestige. Existing Zephyr platforms are emitting + * these markers in their linker scripts, and wrapper.c code iterates + * over the list, but no data gets placed there anywhere? Note that + * Zephyr has a proper STRUCT_SECTION_ITERABLE API for this kind of + * trick... + * + * Just emit two identical symbols to make the existing code work + */ +__asm__(".globl _module_init_start\n" + "_module_init_start:\n" + ".globl _module_init_end\n" + "_module_init_end:\n"); + +/* Ditto for symbols in .trace_ctx */ +__asm__(".globl _trace_ctx_start\n" + "_trace_ctx_start:\n" + ".globl _trace_ctx_end\n" + "_trace_ctx_end:\n"); + +struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) +{ + return NULL; +} + +void mtrace_event(const char *data, uint32_t length) +{ +} + +int platform_context_save(struct sof *sof) +{ + return 0; +} + +static void posix_clk_init(struct sof *sof) +{ + static const struct freq_table cpu_freq[] = { + { + .freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + .ticks_per_msec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000, + }, + }; + static struct clock_info clocks_info[] = { + { + .freqs_num = ARRAY_SIZE(cpu_freq), + .freqs = cpu_freq, + .notification_id = 0, + .notification_mask = 1, + }, + }; + + sof->clocks = clocks_info; +} + +int platform_init(struct sof *sof) +{ + posix_clk_init(sof); + + /* Boilerplate. Copied from ACE platform.c. Only DMA has any + * posix-specific code + */ + scheduler_init_edf(); + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + scheduler_init_ll(sof->platform_timer_domain); + sa_init(sof, CONFIG_SYSTICK_PERIOD); + posix_dma_init(sof); + ipc_init(sof); + + return 0; +} + +int platform_boot_complete(uint32_t boot_message) +{ + return 0; +} diff --git a/src/platform/qemu_xtensa/CMakeLists.txt b/src/platform/qemu_xtensa/CMakeLists.txt new file mode 100644 index 000000000000..8688947cf0c6 --- /dev/null +++ b/src/platform/qemu_xtensa/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_local_sources(sof platform.c) diff --git a/src/platform/qemu_xtensa/include/platform/lib/clk.h b/src/platform/qemu_xtensa/include/platform/lib/clk.h new file mode 100644 index 000000000000..c9f05cdf405b --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/lib/clk.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +/* Dummy clk header for qemu_xtensa */ +#define CLK_MAX_CPU_HZ 10000000 +#define CPU_LOWEST_FREQ_IDX 0 + +#endif /* __PLATFORM_LIB_CLK_H__ */ diff --git a/src/platform/qemu_xtensa/include/platform/lib/dai.h b/src/platform/qemu_xtensa/include/platform/lib/dai.h new file mode 100644 index 000000000000..418c383789a8 --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/lib/dai.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +/* Dummy dai header for qemu_xtensa */ + +#endif /* __PLATFORM_LIB_DAI_H__ */ diff --git a/src/platform/qemu_xtensa/include/platform/lib/dma.h b/src/platform/qemu_xtensa/include/platform/lib/dma.h new file mode 100644 index 000000000000..4c4068b99392 --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/lib/dma.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +/* Dummy dma header for qemu_xtensa */ +struct dma; + +struct sof_dma { + const struct device *z_dev; +}; + +#endif /* __PLATFORM_LIB_DMA_H__ */ diff --git a/src/platform/qemu_xtensa/include/platform/lib/mailbox.h b/src/platform/qemu_xtensa/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..47c97744fe6d --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/lib/mailbox.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +/* Dummy mailbox header for qemu_xtensa */ +#define MAILBOX_HOSTBOX_BASE 0x10000000 +#define MAILBOX_HOSTBOX_SIZE 0x1000 +#define MAILBOX_DSPBOX_BASE 0x10005000 +#define MAILBOX_DSPBOX_SIZE 0x1000 +#define MAILBOX_STREAM_BASE 0x10001000 +#define MAILBOX_STREAM_SIZE 0x1000 +#define MAILBOX_TRACE_BASE 0x10002000 +#define MAILBOX_TRACE_SIZE 0x1000 +#define MAILBOX_EXCEPTION_BASE 0x10003000 +#define MAILBOX_EXCEPTION_SIZE 0x1000 +#define MAILBOX_DEBUG_BASE 0x10004000 +#define MAILBOX_DEBUG_SIZE 0x1000 +#define MAILBOX_SW_REG_BASE 0x10005000 +#define MAILBOX_SW_REG_SIZE 0x1000 + +#include <stddef.h> +#include <stdint.h> + +static inline void mailbox_sw_regs_write(size_t offset, const void *src, size_t bytes) {} +static inline void mailbox_sw_reg_write(size_t offset, uint32_t val) {} +static inline void mailbox_sw_reg_write64(size_t offset, uint64_t val) {} +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; } + +#endif /* __PLATFORM_LIB_MAILBOX_H__ */ diff --git a/src/platform/qemu_xtensa/include/platform/lib/memory.h b/src/platform/qemu_xtensa/include/platform/lib/memory.h new file mode 100644 index 000000000000..d0843904f563 --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/lib/memory.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +/* Dummy memory header for qemu_xtensa */ + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#define PLATFORM_DCACHE_ALIGN sizeof(void *) +#define HOST_PAGE_SIZE 4096 +#define SHARED_DATA + +#endif /* __PLATFORM_LIB_MEMORY_H__ */ diff --git a/src/platform/qemu_xtensa/include/platform/platform.h b/src/platform/qemu_xtensa/include/platform/platform.h new file mode 100644 index 000000000000..5f89152251b4 --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/platform.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +/* Dummy platform header for qemu_xtensa */ +#define PLATFORM_CORE_COUNT 1 +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 8 + +#define HW_CFG_VERSION 0x010000 +#define DMA_TRACE_LOCAL_SIZE HOST_PAGE_SIZE + +struct ipc_msg; +static inline void ipc_platform_send_msg_direct(const struct ipc_msg *msg) {} + +#endif /* __PLATFORM_PLATFORM_H__ */ diff --git a/src/platform/qemu_xtensa/include/platform/trace/trace.h b/src/platform/qemu_xtensa/include/platform/trace/trace.h new file mode 100644 index 000000000000..65499099cd52 --- /dev/null +++ b/src/platform/qemu_xtensa/include/platform/trace/trace.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +/* Dummy trace header for qemu_xtensa */ +#define PLATFORM_TRACE_DICT_FRONT 0 + +#endif /* __PLATFORM_TRACE_TRACE_H__ */ diff --git a/src/platform/qemu_xtensa/platform.c b/src/platform/qemu_xtensa/platform.c new file mode 100644 index 000000000000..f39ba5c1a639 --- /dev/null +++ b/src/platform/qemu_xtensa/platform.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. +// +#include <sof/lib/mailbox.h> +#include <sof/ipc/common.h> +#include <rtos/sof.h> + +void ipc_platform_complete_cmd(struct ipc *ipc) +{ +} + +int platform_boot_complete(uint32_t boot_message) +{ + return 0; +} + +int platform_init(struct sof *sof) +{ + return 0; +} diff --git a/src/platform/suecreek/CMakeLists.txt b/src/platform/suecreek/CMakeLists.txt deleted file mode 100644 index 3fad0567edcb..000000000000 --- a/src/platform/suecreek/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(lib) - -add_executable(boot_module boot_module.c) -add_executable(base_module base_module.c) - -target_link_libraries(boot_module sof_options) -target_link_libraries(base_module sof_options) diff --git a/src/platform/suecreek/base_module.c b/src/platform/suecreek/base_module.c deleted file mode 100644 index 1d6e0f8ebe82..000000000000 --- a/src/platform/suecreek/base_module.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> -#include <sof/common.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest cnl_manifest = { - .module = { - .name = "BASEFW", - .uuid = {0x32, 0x8c, 0x39, 0x0e, 0xde, 0x5a, 0x4b, 0xba, - 0x93, 0xb1, 0xc5, 0x04, 0x32, 0x28, 0x0e, 0xe4}, - .entry_point = SOF_TEXT_START, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/suecreek/boot_ldr.x.in b/src/platform/suecreek/boot_ldr.x.in deleted file mode 100644 index 966dc5025005..000000000000 --- a/src/platform/suecreek/boot_ldr.x.in +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Linker Script for Sue Creek - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - boot_entry_text : - org = BOOT_LDR_TEXT_ENTRY_BASE, - len = BOOT_LDR_TEXT_ENTRY_SIZE - boot_entry_lit : - org = BOOT_LDR_LIT_BASE, - len = BOOT_LDR_LIT_SIZE - sof_text : - org = BOOT_LDR_TEXT_BASE, - len = BOOT_LDR_TEXT_SIZE, - sof_data : - org = BOOT_LDR_DATA_BASE, - len = BOOT_LDR_DATA_SIZE - sof_bss_data : - org = BOOT_LDR_BSS_BASE, - len = BOOT_LDR_BSS_SIZE - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE -} - -PHDRS -{ - boot_entry_text_phdr PT_LOAD; - boot_entry_lit_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_bss_data_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(boot_entry) -EXTERN(reset_vector) - -SECTIONS -{ - .boot_entry.text : ALIGN(4) - { - _boot_entry_text_start = ABSOLUTE(.); - KEEP (*(.boot_entry.text)) - _boot_entry_text_end = ABSOLUTE(.); - } >boot_entry_text :boot_entry_text_phdr - - .boot_entry.literal : ALIGN(4) - { - _boot_entry_literal_start = ABSOLUTE(.); - *(.boot_entry.literal) - *(.literal .literal.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _boot_entry_literal_end = ABSOLUTE(.); - } >boot_entry_lit :boot_entry_lit_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - *(.entry.text) - *(.init.literal) - KEEP(*(.init)) - *( .text .text.*) - *(.fini.literal) - KEEP(*(.fini)) - *(.gnu.version) - KEEP (*(.ResetVector.text)) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_bss_data :sof_bss_data_phdr - - _man = 0x1234567; - - PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - - _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; - PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/suecreek/boot_module.c b/src/platform/suecreek/boot_module.c deleted file mode 100644 index 88ed52b75c1d..000000000000 --- a/src/platform/suecreek/boot_module.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest sue_bootldr_manifest = { - .module = { - .name = "BRNGUP", - .uuid = {0xf3, 0xe4, 0x79, 0x2b, 0x75, 0x46, 0x49, 0xf6, - 0x89, 0xdf, 0x3b, 0xc1, 0x94, 0xa9, 0x1a, 0xeb}, - .entry_point = BOOT_LDR_TEXT_ENTRY_BASE, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/suecreek/include/arch/xtensa/config/core-isa.h b/src/platform/suecreek/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index a776e0c1009c..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,613 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 64 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 1 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "X6H3CNL_2017_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x00075E9B /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC2F3FBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x1C45212F /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX6.0.1" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 1 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 260001 /* major*100+minor */ -#define XCHAL_HW_REL_LX6 1 -#define XCHAL_HW_REL_LX6_0 1 -#define XCHAL_HW_REL_LX6_0_1 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 1 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 260001 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 1 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 260001 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 6 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 6 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 49152 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 8 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 6 -#define XCHAL_DCACHE_SETWIDTH 8 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 4 -#define XCHAL_DCACHE_WAYS 3 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY XTHAL_MEMEP_ECC -#define XCHAL_DCACHE_ECC_PARITY XTHAL_MEMEP_ECC - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 8 -#define XCHAL_DCACHE_ACCESS_SIZE 8 - -#define XCHAL_DCACHE_BANKS 1 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 21 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 8 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x0000000F -#define XCHAL_INTLEVEL2_MASK 0x000000F0 -#define XCHAL_INTLEVEL3_MASK 0x00000F00 -#define XCHAL_INTLEVEL4_MASK 0x00007000 -#define XCHAL_INTLEVEL5_MASK 0x000F8000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00100000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000000F -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00007FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x001FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 2 -#define XCHAL_INT5_LEVEL 2 -#define XCHAL_INT6_LEVEL 2 -#define XCHAL_INT7_LEVEL 2 -#define XCHAL_INT8_LEVEL 3 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 4 -#define XCHAL_INT14_LEVEL 4 -#define XCHAL_INT15_LEVEL 5 -#define XCHAL_INT16_LEVEL 5 -#define XCHAL_INT17_LEVEL 5 -#define XCHAL_INT18_LEVEL 5 -#define XCHAL_INT19_LEVEL 5 -#define XCHAL_INT20_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFE00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0008D999 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00072444 -#define XCHAL_INTTYPE_MASK_TIMER 0x00000222 -#define XCHAL_INTTYPE_MASK_NMI 0x00100000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 1 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 5 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 9 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 20 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL7_NUM 20 -/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 6 /* (intlevel 2) */ -#define XCHAL_EXTINT2_NUM 10 /* (intlevel 3) */ -#define XCHAL_EXTINT3_NUM 13 /* (intlevel 4) */ -#define XCHAL_EXTINT4_NUM 16 /* (intlevel 5) */ -#define XCHAL_EXTINT5_NUM 17 /* (intlevel 5) */ -#define XCHAL_EXTINT6_NUM 18 /* (intlevel 5) */ -#define XCHAL_EXTINT7_NUM 20 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT2_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT6_EXTNUM 1 /* (intlevel 2) */ -#define XCHAL_INT10_EXTNUM 2 /* (intlevel 3) */ -#define XCHAL_INT13_EXTNUM 3 /* (intlevel 4) */ -#define XCHAL_INT16_EXTNUM 4 /* (intlevel 5) */ -#define XCHAL_INT17_EXTNUM 5 /* (intlevel 5) */ -#define XCHAL_INT18_EXTNUM 6 /* (intlevel 5) */ -#define XCHAL_INT20_EXTNUM 7 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 1 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0xBEFE0800 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0xBEFE0800 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR0_PADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR1_VADDR 0xBE800000 -#define XCHAL_RESET_VECTOR1_PADDR 0xBE800000 -#define XCHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XCHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XCHAL_MEMERROR_VECTOR0_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR0_PADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR1_VADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR1_PADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XCHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 -#define XCHAL_USER_VECOFS 0x00000340 -#define XCHAL_USER_VECTOR_VADDR 0xBEFE0B40 -#define XCHAL_USER_VECTOR_PADDR 0xBEFE0B40 -#define XCHAL_KERNEL_VECOFS 0x00000300 -#define XCHAL_KERNEL_VECTOR_VADDR 0xBEFE0B00 -#define XCHAL_KERNEL_VECTOR_PADDR 0xBEFE0B00 -#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xBEFE0BC0 -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0xBEFE0BC0 -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0xBEFE0800 -#define XCHAL_WINDOW_VECTORS_PADDR 0xBEFE0800 -#define XCHAL_INTLEVEL2_VECOFS 0x00000180 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xBEFE0980 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0xBEFE0980 -#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0xBEFE09C0 -#define XCHAL_INTLEVEL4_VECOFS 0x00000200 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xBEFE0A00 -#define XCHAL_INTLEVEL5_VECOFS 0x00000240 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0xBEFE0A40 -#define XCHAL_INTLEVEL6_VECOFS 0x00000280 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0xBEFE0A80 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0xBEFE0A80 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x000002C0 -#define XCHAL_NMI_VECTOR_VADDR 0xBEFE0AC0 -#define XCHAL_NMI_VECTOR_PADDR 0xBEFE0AC0 -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/arch/xtensa/config/core-matmap.h b/src/platform/suecreek/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index d7fd7795e3f1..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - -#define XCHAL_CA_R (0xC0 | 0x40000000) -#define XCHAL_CA_RX (0xD0 | 0x40000000) -#define XCHAL_CA_RW (0xE0 | 0x40000000) -#define XCHAL_CA_RWX (0xF0 | 0x40000000) - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefine hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/arch/xtensa/config/defs.h b/src/platform/suecreek/include/arch/xtensa/config/defs.h deleted file mode 100644 index d93272ae05a3..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/arch/xtensa/config/specreg.h b/src/platform/suecreek/include/arch/xtensa/config/specreg.h deleted file mode 100644 index 9d1d2ea95dad..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ - -/* Copyright (c) 1998-2002 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define MEMCTL 97 -#define ATOMCTL 99 -#define DDR 104 -#define MEPC 106 -#define MEPS 107 -#define MESAVE 108 -#define MESR 109 -#define MECR 110 -#define MEVADDR 111 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 - -/* Special cases (bases of special register series): */ -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -/* Special names for read-only and write-only interrupt registers: */ -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 - -#endif /* XTENSA_SPECREG_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/arch/xtensa/config/system.h b/src/platform/suecreek/include/arch/xtensa/config/system.h deleted file mode 100644 index 0e434954c920..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Copyright (c) 2000-2010 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -#define XSHAL_FLOATING_POINT_ABI 0 - -/* SW workarounds enabled for HW errata: */ - -/* SW options for functional safety: */ -#define XSHAL_FUNC_SAFETY_ENABLED 0 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -#define XSHAL_ROM_VADDR 0xBEFE0000 -#define XSHAL_ROM_PADDR 0xBEFE0000 -#define XSHAL_ROM_SIZE 0x00020000 -/* Largest available area (free of vectors): */ -#define XSHAL_ROM_AVAIL_VADDR 0xBEFE0BC0 -#define XSHAL_ROM_AVAIL_VSIZE 0x0001F440 - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x80000000 -#define XSHAL_RAM_PADDR 0x80000000 -#define XSHAL_RAM_VSIZE 0x3EFE0000 -#define XSHAL_RAM_PSIZE 0x3EFE0000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x80000000 -#define XSHAL_RAM_AVAIL_VSIZE 0x3EFE0000 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit and diagnostic routines. - */ -#define XSHAL_MAGIC_EXIT 0xe0000000 - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22442222 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22112222 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22112222 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44FFFF /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11FFFF /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11FFFF /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22FFFF /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244222F /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211222F /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211222F /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF44422F /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF11122F /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF11122F /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000104 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XSHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XSHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XSHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x00000300 -#define XSHAL_RESET_VECTOR_ISROM 1 -#define XSHAL_USER_VECTOR_SIZE 0x00000038 -#define XSHAL_USER_VECTOR_ISROM 1 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 -#define XSHAL_KERNEL_VECTOR_ISROM 1 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 1 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 1 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL2_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL3_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL4_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL5_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL6_VECTOR_ISROM 1 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x00000038 -#define XSHAL_NMI_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/arch/xtensa/config/tie-asm.h b/src/platform/suecreek/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index f6210e126331..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - /* - * Macro to store all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rur.THREADPTR \at1 // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_+0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_store - - /* - * Macro to load all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.THREADPTR \at1 // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - /* - * Macro to store the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_FPU_store xchal_cp0_store - .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - rur.FCR \at1 // ureg 232 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.FSR \at1 // ureg 233 - s32i \at1, \ptr, .Lxchal_ofs_+4 - ssi f0, \ptr, .Lxchal_ofs_+8 - ssi f1, \ptr, .Lxchal_ofs_+12 - ssi f2, \ptr, .Lxchal_ofs_+16 - ssi f3, \ptr, .Lxchal_ofs_+20 - ssi f4, \ptr, .Lxchal_ofs_+24 - ssi f5, \ptr, .Lxchal_ofs_+28 - ssi f6, \ptr, .Lxchal_ofs_+32 - ssi f7, \ptr, .Lxchal_ofs_+36 - ssi f8, \ptr, .Lxchal_ofs_+40 - ssi f9, \ptr, .Lxchal_ofs_+44 - ssi f10, \ptr, .Lxchal_ofs_+48 - ssi f11, \ptr, .Lxchal_ofs_+52 - ssi f12, \ptr, .Lxchal_ofs_+56 - ssi f13, \ptr, .Lxchal_ofs_+60 - ssi f14, \ptr, .Lxchal_ofs_+64 - ssi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_store - - /* - * Macro to load the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_FPU_load xchal_cp0_load - .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.FCR \at1 // ureg 232 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.FSR \at1 // ureg 233 - lsi f0, \ptr, .Lxchal_ofs_+8 - lsi f1, \ptr, .Lxchal_ofs_+12 - lsi f2, \ptr, .Lxchal_ofs_+16 - lsi f3, \ptr, .Lxchal_ofs_+20 - lsi f4, \ptr, .Lxchal_ofs_+24 - lsi f5, \ptr, .Lxchal_ofs_+28 - lsi f6, \ptr, .Lxchal_ofs_+32 - lsi f7, \ptr, .Lxchal_ofs_+36 - lsi f8, \ptr, .Lxchal_ofs_+40 - lsi f9, \ptr, .Lxchal_ofs_+44 - lsi f10, \ptr, .Lxchal_ofs_+48 - lsi f11, \ptr, .Lxchal_ofs_+52 - lsi f12, \ptr, .Lxchal_ofs_+56 - lsi f13, \ptr, .Lxchal_ofs_+60 - lsi f14, \ptr, .Lxchal_ofs_+64 - lsi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_load - -#define XCHAL_CP0_NUM_ATMPS 1 - /* - * Macro to store the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_CW_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - rur.AE_CBEGIN0 \at1 // ureg 246 - s32i \at1, \ptr, .Lxchal_ofs_+16 - rur.AE_CEND0 \at1 // ureg 247 - s32i \at1, \ptr, .Lxchal_ofs_+20 - ae_s64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_s64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed15, \ptr, .Lxchal_ofs_+16 - ae_salign64.i u0, \ptr, .Lxchal_ofs_+24 - ae_salign64.i u1, \ptr, .Lxchal_ofs_+32 - ae_salign64.i u2, \ptr, .Lxchal_ofs_+40 - ae_salign64.i u3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 128 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_store - - /* - * Macro to load the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_CW_SD_NO \at1 // ureg 243 - l32i \at1, \ptr, .Lxchal_ofs_+16 - wur.AE_CBEGIN0 \at1 // ureg 246 - l32i \at1, \ptr, .Lxchal_ofs_+20 - wur.AE_CEND0 \at1 // ureg 247 - ae_l64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_l64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed15, \ptr, .Lxchal_ofs_+16 - addi \ptr, \ptr, 24 - ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 - ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 - ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 - ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 152 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/arch/xtensa/config/tie.h b/src/platform/suecreek/include/arch/xtensa/config/tie.h deleted file mode 100644 index 6865fad953af..000000000000 --- a/src/platform/suecreek/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 2 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x03 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP0_NAME "FPU" -#define XCHAL_CP0_IDENT FPU -#define XCHAL_CP0_SA_SIZE 72 /* size of state save area */ -#define XCHAL_CP0_SA_ALIGN 4 /* min alignment of save area */ -#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 184 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 12 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 272 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 3 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 18 -#define XCHAL_CP0_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, fcr, 4, 4, 4,0x03E8, ur,232, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f0, 4, 4, 4,0x0030, f,0 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f1, 4, 4, 4,0x0031, f,1 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f2, 4, 4, 4,0x0032, f,2 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f3, 4, 4, 4,0x0033, f,3 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f4, 4, 4, 4,0x0034, f,4 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f5, 4, 4, 4,0x0035, f,5 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f6, 4, 4, 4,0x0036, f,6 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f7, 4, 4, 4,0x0037, f,7 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f8, 4, 4, 4,0x0038, f,8 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f9, 4, 4, 4,0x0039, f,9 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f10, 4, 4, 4,0x003A, f,10 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f11, 4, 4, 4,0x003B, f,11 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f12, 4, 4, 4,0x003C, f,12 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f13, 4, 4, 4,0x003D, f,13 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f14, 4, 4, 4,0x003E, f,14 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f15, 4, 4, 4,0x003F, f,15 , 32,0,0,0) - -#define XCHAL_CP1_SA_NUM 26 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 -/* Byte length of instruction from its first byte, per FLIX. */ -#define XCHAL_BYTE0_FORMAT_LENGTHS \ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 - -#endif /*_XTENSA_CORE_TIE_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/suecreek/include/platform/drivers/dw-dma.h b/src/platform/suecreek/include/platform/drivers/dw-dma.h deleted file mode 100644 index 2fe0b26450d5..000000000000 --- a/src/platform/suecreek/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <cavs/drivers/dw-dma.h> - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __SOF_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/suecreek/include/platform/drivers/idc.h b/src/platform/suecreek/include/platform/drivers/idc.h deleted file mode 100644 index b8565347f42e..000000000000 --- a/src/platform/suecreek/include/platform/drivers/idc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <cavs/drivers/idc.h> - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/suecreek/include/platform/drivers/interrupt.h b/src/platform/suecreek/include/platform/drivers/interrupt.h deleted file mode 100644 index 9acca789f2d8..000000000000 --- a/src/platform/suecreek/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,196 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <cavs/drivers/interrupt.h> -#include <sof/bit.h> -#include <sof/drivers/interrupt-map.h> -#include <config.h> - -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 32 - -/* IRQ numbers - wrt Tensilica DSP */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_SOFTWARE0 0 /* level 1 */ -#define IRQ_NUM_TIMER1 1 /* level 1 */ -#define IRQ_NUM_EXT_LEVEL1 2 /* level 1 */ -#define IRQ_NUM_SOFTWARE1 3 /* level 1 */ - -#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_EXT_LEVEL1 BIT(IRQ_NUM_EXT_LEVEL1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_SOFTWARE2 4 /* level 2 */ -#define IRQ_NUM_TIMER2 5 /* level 2 */ -#define IRQ_NUM_EXT_LEVEL2 6 /* level 2 */ -#define IRQ_NUM_SOFTWARE3 7 /* level 2 */ - -/* IRQ Level 2 bits */ -#define IRQ_BIT_LVL2_HP_GP_DMA0(x) (x + 24) -#define IRQ_BIT_LVL2_WALL_CLK1 23 -#define IRQ_BIT_LVL2_WALL_CLK0 22 -#define IRQ_BIT_LVL2_L2_MEMERR 21 -#define IRQ_BIT_LVL2_SHA256 16 -#define IRQ_BIT_LVL2_L2_CACHE 15 -#define IRQ_BIT_LVL2_IDC 8 -#define IRQ_BIT_LVL2_HOST_IPC 7 -#define IRQ_BIT_LVL2_CSME_IPC 6 -#define IRQ_BIT_LVL2_PMC_IPC 5 - -/* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) -#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC -#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC -#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 -#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 -#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR -#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE -#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 - -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_EXT_LEVEL2 BIT(IRQ_NUM_EXT_LEVEL2) -#define IRQ_MASK_SOFTWARE3 BIT(IRQ_NUM_SOFTWARE3) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_SOFTWARE4 8 /* level 3 */ -#define IRQ_NUM_TIMER3 9 /* level 3 */ -#define IRQ_NUM_EXT_LEVEL3 10 /* level 3 */ -#define IRQ_NUM_SOFTWARE5 11 /* level 3 */ - -/* IRQ Level 3 bits */ -#define IRQ_BIT_LVL3_CODE_LOADER 31 -#define IRQ_BIT_LVL3_HOST_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL3_HOST_STREAM_IN(x) (0 + x) - -/* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER -#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE4 BIT(IRQ_NUM_SOFTWARE4) -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) -#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) -#define IRQ_MASK_SOFTWARE5 BIT(IRQ_NUM_SOFTWARE5) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_SOFTWARE6 12 /* level 4 */ -#define IRQ_NUM_EXT_LEVEL4 13 /* level 4 */ -#define IRQ_NUM_SOFTWARE7 14 /* level 4 */ - -/* IRQ Level 4 bits */ -#define IRQ_BIT_LVL4_LINK_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL4_LINK_STREAM_IN(x) (0 + x) - -/* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE6 BIT(IRQ_NUM_SOFTWARE6) -#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) -#define IRQ_MASK_SOFTWARE7 BIT(IRQ_NUM_SOFTWARE7) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_SOFTWARE8 15 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL5 16 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL6 17 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL7 18 /* level 5 */ -#define IRQ_NUM_SOFTWARE9 19 /* level 5 */ - -/* IRQ Level 5 bits */ -#define IRQ_BIT_LVL5_LP_GP_DMA1 15 -#define IRQ_BIT_LVL5_LP_GP_DMA0 16 -#define IRQ_BIT_LVL5_DMIC(x) 8 -#define IRQ_BIT_LVL5_SSP(x) (0 + x) - -/* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) - -#define IRQ_MASK_SOFTWARE8 BIT(IRQ_NUM_SOFTWARE8) -#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) -#define IRQ_MASK_EXT_LEVEL6 BIT(IRQ_NUM_EXT_LEVEL6) -#define IRQ_MASK_EXT_LEVEL7 BIT(IRQ_NUM_EXT_LEVEL7) -#define IRQ_MASK_SOFTWARE9 BIT(IRQ_NUM_SOFTWARE9) - -#endif - -#define IRQ_NUM_NMI 20 /* level 7 */ - -/* platform interrupt control */ -#define SUE_DW_ICTL_BASE_ADDR 0x00081800 -#define SUE_DW_ICTL_IRQ_INTEN_L (0x00 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_INTEN_H (0x04 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_INTMASK_L (0x08 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_INTMASK_H (0x0C + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_INTFORCE_L (0x10 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_INTFORCE_H (0x14 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_RAWSTATUS_L (0x18 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_RAWSTATUS_H (0x1C + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_STATUS_L (0x20 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_STATUS_H (0x24 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_MASKSTATUS_L (0x28 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_MASKSTATUS_H (0x2C + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FINALSTATUS_L (0x30 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FINALSTATUS_H (0x34 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR (0x38 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_0 (0x40 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_1 (0x48 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_2 (0x50 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_3 (0x58 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_4 (0x60 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_5 (0x68 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_6 (0x70 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_7 (0x78 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_8 (0x80 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_9 (0x88 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_10 (0x90 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_11 (0x98 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_12 (0xA0 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_13 (0xA8 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_14 (0xB0 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_VECTOR_15 (0xB8 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_INTEN (0xC0 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_INTMASK (0xC4 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_INTFORCE (0xC8 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_RAWSTATUS (0xCC + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_STATUS (0xD0 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_FINALSTATUS (0xD4 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_IRQ_FIQ_PLEVEL (0xD8 + SUE_DW_ICTL_BASE_ADDR) -#define SUE_DW_ICTL_PR_N(x) (0xE8 + x * 4 + SUE_DW_ICTL_BASE_ADDR) -#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/suecreek/include/platform/lib/clk.h b/src/platform/suecreek/include/platform/lib/clk.h deleted file mode 100644 index eb39bb31f549..000000000000 --- a/src/platform/suecreek/include/platform/lib/clk.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <cavs/lib/clk.h> - -#define CLK_MAX_CPU_HZ 400000000 - -#define CPU_LPRO_FREQ_IDX 0 - -#define CPU_HPRO_FREQ_IDX 1 - -#define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX - -#define SSP_DEFAULT_IDX 0 - -#define NUM_CPU_FREQ 2 - -#define NUM_SSP_FREQ 2 - -#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/suecreek/include/platform/lib/cpu.h b/src/platform/suecreek/include/platform/lib/cpu.h deleted file mode 100644 index 78a6e78bc889..000000000000 --- a/src/platform/suecreek/include/platform/lib/cpu.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <cavs/lib/cpu.h> - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 4 - -#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/suecreek/include/platform/lib/dai.h b/src/platform/suecreek/include/platform/lib/dai.h deleted file mode 100644 index c15b364097fd..000000000000 --- a/src/platform/suecreek/include/platform/lib/dai.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -/* SUECREEK */ - -/* 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 - -/** \brief Number of 'extended' SSP ports available */ -#define DAI_NUM_SSP_EXT 0 - -/** \brief Number of SSP MCLKs available */ -#define DAI_NUM_SSP_MCLK 2 - -/** \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 7 - -#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/suecreek/include/platform/lib/dma.h b/src/platform/suecreek/include/platform/lib/dma.h deleted file mode 100644 index d1d92abd2682..000000000000 --- a/src/platform/suecreek/include/platform/lib/dma.h +++ /dev/null @@ -1,55 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -/* number of supported DMACs */ -#define PLATFORM_NUM_DMACS 3 - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 8 - -/* available DMACs */ -#define DMA_GP_LP_DMAC0 0 -#define DMA_GP_LP_DMAC1 1 -#define DMA_GP_LP_DMAC2 2 - - -/* mappings - TODO improve API to get type */ -#define DMA_ID_DMAC0 DMA_GP_LP_DMAC0 -#define DMA_ID_DMAC1 DMA_GP_LP_DMAC1 -#define DMA_ID_DMAC2 DMA_GP_LP_DMAC1 - -/* handshakes */ -#define DMA_HANDSHAKE_DMIC_CH0 0 -#define DMA_HANDSHAKE_DMIC_CH1 1 -#define DMA_HANDSHAKE_SSP0_RX 2 -#define DMA_HANDSHAKE_SSP0_TX 3 -#define DMA_HANDSHAKE_SSP1_RX 4 -#define DMA_HANDSHAKE_SSP1_TX 5 -#define DMA_HANDSHAKE_SSP2_RX 6 -#define DMA_HANDSHAKE_SSP2_TX 7 -#define DMA_HANDSHAKE_SSP3_RX 8 -#define DMA_HANDSHAKE_SSP3_TX 9 -#define DMA_HANDSHAKE_SSI_TX 26 -#define DMA_HANDSHAKE_SSI_RX 27 - -#define dma_chan_irq(dma, chan) dma_irq(dma) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/suecreek/include/platform/lib/mailbox.h b/src/platform/suecreek/include/platform/lib/mailbox.h deleted file mode 100644 index a781e3aecb31..000000000000 --- a/src/platform/suecreek/include/platform/lib/mailbox.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_MAILBOX_H__ - -#ifndef __PLATFORM_LIB_MAILBOX_H__ -#define __PLATFORM_LIB_MAILBOX_H__ - -#include <cavs/lib/mailbox.h> - -#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/suecreek/include/platform/lib/memory.h b/src/platform/suecreek/include/platform/lib/memory.h deleted file mode 100644 index eedd76166b44..000000000000 --- a/src/platform/suecreek/include/platform/lib/memory.h +++ /dev/null @@ -1,420 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_MEMORY_H__ - -#ifndef __PLATFORM_LIB_MEMORY_H__ -#define __PLATFORM_LIB_MEMORY_H__ - -#include <cavs/lib/memory.h> -#include <sof/lib/cpu.h> -#include <config.h> - -/* physical DSP addresses */ - -/* shim */ -#define SHIM_BASE 0x00071F00 -#define SHIM_SIZE 0x00000100 - -/* Digital Mic Shim Registers */ -#define DMIC_SHIM_BASE 0x00071E80 -#define DMICLCTL_OFFSET 0x04 -#define DMICLCTL (DMIC_SHIM_BASE + DMICLCTL_OFFSET) - -/* resource allocation */ -#define RES_BASE 0x00001110 -#define RES_SIZE 0x00000010 - -/* IPC to the host */ -#define IPC_HOST_BASE 0x00071E00 -#define IPC_HOST_SIZE 0x00000020 - -/* intra DSP IPC */ -#define IPC_DSP_SIZE 0x00000080 -#define IPC_DSP_BASE(x) (0x00001200 + x * IPC_DSP_SIZE) - -/* IRQ controller */ -#define IRQ_BASE 0x00078800 -#define IRQ_SIZE 0x00000200 - -/* time stamping */ -#define TIME_BASE 0x00071800 -#define TIME_SIZE 0x00000200 - -/* M/N dividers */ -#define MN_BASE 0x00078C00 -#define MN_SIZE 0x00000200 - -/* low power DMA position */ -#define LP_GP_DMA_LINK_SIZE 0x00000010 -#define LP_GP_DMA_LINK_BASE(x) (0x00001C00 + x * LP_GP_DMA_LINK_SIZE) - -/* high performance DMA position */ -#define HP_GP_DMA_LINK_SIZE 0x00000010 -#define HP_GP_DMA_LINK_BASE(x) (0x00001D00 + x * HP_GP_DMA_LINK_SIZE) - -/* code loader */ -#define GTW_CODE_LDR_SIZE 0x00000040 -#define GTW_CODE_LDR_BASE 0x00002BC0 - -/* L2 TLBs */ -#define L2_HP_SRAM_TLB_SIZE 0x00001000 -#define L2_HP_SRAM_TLB_BASE 0x00003000 - -/* DMICs */ -#define DMIC_BASE 0x00010000 -#define DMIC_SIZE 0x00008000 - -/* SSP */ -#define SSP_BASE(x) (0x00077000 + x * SSP_SIZE) -#define SSP_SIZE 0x0000200 - -/* Timestamping */ -#define TIMESTAMP_BASE 0x00071800 - -/* low power DMACs */ -#define LP_GP_DMA_SIZE 0x00001000 -#define LP_GP_DMA_BASE(x) (0x0007C000 + x * LP_GP_DMA_SIZE) - -/* high performance DMACs */ -#define HP_GP_DMA_SIZE 0x00001000 -#define HP_GP_DMA_BASE(x) (0x00004000 + x * HP_GP_DMA_SIZE) - -/* DW SPI slave/master */ -#define DW_SPI_SLAVE_BASE 0x80000 -#define DW_SPI_SLAVE_SIZE 0x400 -#define DW_SPI_MASTER_BASE 0xE000 -#define DW_SPI_MASTER_SIZE 0x400 - -/* DW I2C controller */ -#define DW_I2C_BASE 0x80400 -#define DW_I2C_SIZE 0x400 - -/* DW UART controller */ -#define DW_UART_BASE 0x88000 -#define DW_UART_SIZE 0x400 - -/* DW GPIO controller */ -#define DW_GPIO_BASE 0x80c00 -#define DW_GPIO_SIZE 0x400 - -/* DW timer */ -#define DW_TIMER_BASE 0x81000 -#define DW_TIMER_SIZE 0x400 - -/* DW watchdog */ -#define DW_WDT_BASE 0x81400 -#define DW_WDT_SIZE 0x400 - -/* DW 3rd level IRQ controller */ -#define DW_IRQ_BASE 0x81800 -#define DW_IRQ_SIZE 0x400 - -/* Misc external controller */ -#define EXT_CTRL_BASE 0x81c00 -#define EXT_CTRL_SIZE 0x400 - -/* DW USB 2.0 controller */ -#define DW_USB_BASE 0xA0000 -#define DW_USB_SIZE 0x6000 - -/* Parallel memory controller */ -#define DW_PMEMCTRL_BASE 0xE400 -#define DW_PMEMCTRL_SIZE 0x400 - -/* GNA controller */ -#define DW_GNA_BASE 0xE800 -#define DW_GNA_SIZE 0x400 - -/* XIP SPI memory */ -#define DW_SPIMEM_UNCACHE_BASE 0xC0000000 -#define DW_SPIMEM_CACHE_BASE 0xE0000000 -#define DW_SPIMEML_SIZE 0x8000000 - -/* Parallel memory */ -#define DW_PARMEM_UNCACHE_BASE 0xD0000000 -#define DW_PARMEM_CACHE_BASE 0xF0000000 -#define DW_PARMEML_SIZE 0x4000000 - -/* ROM */ -#define ROM_BASE 0xBEFE0000 -#define ROM_SIZE 0x00002000 - -#define L2_VECTOR_SIZE 0x2000 - -#define UUID_ENTRY_ELF_BASE 0x1FFFA000 -#define UUID_ENTRY_ELF_SIZE 0x6000 - -#define LOG_ENTRY_ELF_BASE 0x20000000 -#define LOG_ENTRY_ELF_SIZE 0x2000000 - -/* - * The HP SRAM Region on Sue Creek is organised like this :- - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +------------------+-------------------------+-----------------------------+ - * | SOF_FW_START | text | | - * | | data | | - * | | ----------------------- | | - * | ||BSS: || | - * | ||-----------------------++-----------------------------+ - * | ||Runtime Heap || HEAP_RUNTIME_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Module Buffers || HEAP_BUFFER_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master core Sys Heap || HEAP_SYSTEM_M_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master Sys Runtime Heap|| HEAP_SYS_RUNTIME_M_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Master core Stack || SOF_STACK_SIZE | - * | ||-----------------------++-----------------------------+ - * | ||Slave core Sys Heap || SOF_CORE_S_T_SIZE | - * | ||Slave Sys Runtime Heap || | - * | ||Slave core Stack || | - * | | ----------------------- | | - * +------------------+-------------------------+-----------------------------+ - */ - -/* HP SRAM */ -#define HP_SRAM_BASE 0xBE000000 - -/* Mailbox configuration */ -#define SRAM_OUTBOX_BASE HP_SRAM_BASE -#define SRAM_OUTBOX_SIZE 0x1000 - -#define SRAM_INBOX_BASE (SRAM_OUTBOX_BASE + SRAM_OUTBOX_SIZE) -#define SRAM_INBOX_SIZE 0x1000 - -#define SRAM_DEBUG_BASE (SRAM_INBOX_BASE + SRAM_INBOX_SIZE) -#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 - -#define SRAM_TRACE_BASE (SRAM_STREAM_BASE + SRAM_STREAM_SIZE) -#if CONFIG_TRACE -#define SRAM_TRACE_SIZE 0x1000 -#else -#define SRAM_TRACE_SIZE 0x0 -#endif - -/* Suecreek HPSRAM does not have SW_REG window*/ -#define SRAM_SW_REG_BASE 0 -#define SRAM_SW_REG_SIZE 0 - -#define SOF_MAILBOX_SIZE (SRAM_INBOX_SIZE + SRAM_OUTBOX_SIZE \ - + SRAM_DEBUG_SIZE + SRAM_EXCEPT_SIZE \ - + SRAM_STREAM_SIZE + SRAM_TRACE_SIZE) - -/* HP SRAM Base */ -#define HP_SRAM_VECBASE_RESET SRAM_VECBASE_RESET - -#define SOF_TEXT_START_SIZE 0x400 - -/* text and data share the same HP L2 SRAM on Suecreek */ -#define SOF_FW_START (HP_SRAM_VECBASE_RESET + SOF_TEXT_START_SIZE) -#define SOF_FW_BASE (SOF_FW_START) - -#define SOF_TEXT_START (SOF_FW_START) -#define SOF_TEXT_BASE (SOF_FW_START) - -/* max size for all var-size sections (text/rodata/bss) */ -#define SOF_FW_MAX_SIZE (HP_SRAM_BASE + HP_SRAM_SIZE - SOF_FW_BASE) - -/* Heap section sizes for system runtime heap for master core */ -#define HEAP_SYS_RT_0_COUNT64 64 -#define HEAP_SYS_RT_0_COUNT512 16 -#define HEAP_SYS_RT_0_COUNT1024 4 - -/* Heap section sizes for system runtime heap for slave core */ -#define HEAP_SYS_RT_X_COUNT64 32 -#define HEAP_SYS_RT_X_COUNT512 8 -#define HEAP_SYS_RT_X_COUNT1024 4 - -/* Heap section sizes for module pool */ -#define HEAP_RT_COUNT64 192 -#define HEAP_RT_COUNT128 32 -#define HEAP_RT_COUNT256 80 -#define HEAP_RT_COUNT512 8 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 0 -#define HEAP_RT_COUNT4096 1 - -/* Heap configuration */ -#define HEAP_RUNTIME_SIZE \ - (HEAP_RT_COUNT64 * 64 + HEAP_RT_COUNT128 * 128 + \ - HEAP_RT_COUNT256 * 256 + HEAP_RT_COUNT512 * 512 + \ - HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + \ - HEAP_RT_COUNT4096 * 4096) - -#define HEAP_BUFFER_SIZE 0x10000 -#define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) - -#define HEAP_SYSTEM_M_SIZE 0x8000 /* heap master core size */ -#define HEAP_SYSTEM_S_SIZE 0x6000 /* heap slave core size */ -#define HEAP_SYSTEM_T_SIZE \ - (HEAP_SYSTEM_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) - -#define HEAP_SYS_RUNTIME_M_SIZE \ - (HEAP_SYS_RT_0_COUNT64 * 64 + HEAP_SYS_RT_0_COUNT512 * 512 + \ - HEAP_SYS_RT_0_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_S_SIZE \ - (HEAP_SYS_RT_X_COUNT64 * 64 + HEAP_SYS_RT_X_COUNT512 * 512 + \ - HEAP_SYS_RT_X_COUNT1024 * 1024) - -#define HEAP_SYS_RUNTIME_T_SIZE \ - (HEAP_SYS_RUNTIME_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * \ - HEAP_SYS_RUNTIME_S_SIZE)) - -/* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * SOF_STACK_SIZE) - -/* SOF Core S configuration */ -#define SOF_CORE_S_SIZE \ - ALIGN((HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE + SOF_STACK_SIZE),\ - SRAM_BANK_SIZE) -#define SOF_CORE_S_T_SIZE ((PLATFORM_CORE_COUNT - 1) * SOF_CORE_S_SIZE) - -/* - * The LP SRAM Heap and Stack on Suecreek are organised like this :- - * - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +---------------------+----------------+-----------------------------------+ - * | LP_SRAM_BASE | RO Data | SOF_LP_DATA_SIZE | - * | | Data | | - * | | BSS | | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_SYSTEM_BASE | System Heap | HEAP_LP_SYSTEM_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_RUNTIME_BASE| Runtime Heap | HEAP_LP_RUNTIME_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | HEAP_LP_BUFFER_BASE | Module Buffers | HEAP_LP_BUFFER_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_LP_STACK_END | Stack | SOF_LP_STACK_SIZE | - * +---------------------+----------------+-----------------------------------+ - * | SOF_STACK_BASE | | | - * +---------------------+----------------+-----------------------------------+ - */ - -/* LP SRAM */ -#define LP_SRAM_BASE 0xBE800000 - -/* Heap section sizes for module pool */ -#define HEAP_RT_LP_COUNT8 0 -#define HEAP_RT_LP_COUNT16 256 -#define HEAP_RT_LP_COUNT32 128 -#define HEAP_RT_LP_COUNT64 64 -#define HEAP_RT_LP_COUNT128 32 -#define HEAP_RT_LP_COUNT256 16 -#define HEAP_RT_LP_COUNT512 8 -#define HEAP_RT_LP_COUNT1024 4 - -/* Heap configuration */ -#define SOF_LP_DATA_SIZE 0x4000 - -#define HEAP_LP_SYSTEM_BASE (LP_SRAM_BASE + SOF_LP_DATA_SIZE) -#define HEAP_LP_SYSTEM_SIZE 0x1000 - -#define HEAP_LP_RUNTIME_BASE \ - (HEAP_LP_SYSTEM_BASE + HEAP_LP_SYSTEM_SIZE) -#define HEAP_LP_RUNTIME_SIZE \ - (HEAP_RT_LP_COUNT8 * 8 + HEAP_RT_LP_COUNT16 * 16 + \ - HEAP_RT_LP_COUNT32 * 32 + HEAP_RT_LP_COUNT64 * 64 + \ - HEAP_RT_LP_COUNT128 * 128 + HEAP_RT_LP_COUNT256 * 256 + \ - HEAP_RT_LP_COUNT512 * 512 + HEAP_RT_LP_COUNT1024 * 1024) - -#define HEAP_LP_BUFFER_BASE (HEAP_LP_RUNTIME_BASE + HEAP_LP_RUNTIME_SIZE) -#define HEAP_LP_BUFFER_SIZE \ - (LP_SRAM_SIZE - HEAP_LP_RUNTIME_SIZE - SOF_LP_STACK_SIZE - \ - HEAP_LP_SYSTEM_SIZE) - -#define HEAP_LP_BUFFER_BLOCK_SIZE 0x180 - -#if CONFIG_LP_MEMORY_BANKS -#define HEAP_LP_BUFFER_COUNT \ - (HEAP_LP_BUFFER_SIZE / HEAP_LP_BUFFER_BLOCK_SIZE) -#else -#define HEAP_LP_BUFFER_COUNT 0 -#endif - - -#define PLATFORM_HEAP_SYSTEM PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_RUNTIME 1 -#define PLATFORM_HEAP_BUFFER 2 - -/* Stack configuration */ -#define SOF_LP_STACK_SIZE 0x1000 -#define SOF_LP_STACK_BASE (LP_SRAM_BASE + LP_SRAM_SIZE) -#define SOF_LP_STACK_END (SOF_LP_STACK_BASE - SOF_LP_STACK_SIZE) - - -/* Vector and literal sizes - do not use core-isa.h */ -#define SOF_MEM_VECBASE HP_SRAM_VECBASE_RESET -#define SOF_MEM_VECT_LIT_SIZE 0x8 -#define SOF_MEM_VECT_TEXT_SIZE 0x38 -#define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ - SOF_MEM_VECT_LIT_SIZE) - -#define SOF_MEM_ERROR_TEXT_SIZE 0x180 -#define SOF_MEM_ERROR_LIT_SIZE 0x8 - -#define SOF_MEM_RESET_TEXT_SIZE 0x268 -#define SOF_MEM_RESET_LIT_SIZE 0x8 -#define SOF_MEM_VECBASE_LIT_SIZE 0x178 - -#define SOF_MEM_RO_SIZE 0x8 - -/* VM ROM sizes */ -#define ROM_RESET_TEXT_SIZE 0x400 -#define ROM_RESET_LIT_SIZE 0x200 - -/* boot loader */ -#define BOOT_LDR_MANIFEST_BASE (SRAM_TRACE_BASE + SRAM_TRACE_SIZE) -#define BOOT_LDR_MANIFEST_SIZE 0x6000 - -/* code loader */ -#define BOOT_LDR_TEXT_ENTRY_BASE (BOOT_LDR_MANIFEST_BASE + \ - BOOT_LDR_MANIFEST_SIZE) -#define BOOT_LDR_TEXT_ENTRY_SIZE 0x200 -#define BOOT_LDR_LIT_BASE (BOOT_LDR_TEXT_ENTRY_BASE + \ - BOOT_LDR_TEXT_ENTRY_SIZE) -#define BOOT_LDR_LIT_SIZE 0x200 -#define BOOT_LDR_TEXT_BASE (BOOT_LDR_LIT_BASE + BOOT_LDR_LIT_SIZE) -#define BOOT_LDR_TEXT_SIZE 0xC00 -#define BOOT_LDR_DATA_BASE (BOOT_LDR_TEXT_BASE + \ - BOOT_LDR_TEXT_SIZE) -#define BOOT_LDR_DATA_SIZE 0x1000 -#define BOOT_LDR_BSS_BASE (BOOT_LDR_DATA_BASE + \ - BOOT_LDR_DATA_SIZE) -#define BOOT_LDR_BSS_SIZE 0x100 - -/* Temporary stack place for boot_ldr */ -#define BOOT_LDR_STACK_BASE (HP_SRAM_BASE + HP_SRAM_SIZE - \ - SOF_STACK_TOTAL_SIZE) -#define BOOT_LDR_STACK_SIZE SOF_STACK_TOTAL_SIZE - -/* code loader entry point for base fw */ -#define _SRAM_VECBASE_RESET (BOOT_LDR_BSS_BASE + BOOT_LDR_BSS_SIZE) -#define SRAM_VECBASE_RESET ALIGN(_SRAM_VECBASE_RESET,4096) - -#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/suecreek/include/platform/lib/pm_runtime.h b/src/platform/suecreek/include/platform/lib/pm_runtime.h deleted file mode 100644 index ba2c6f85c2cb..000000000000 --- a/src/platform/suecreek/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/cannonlake/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Cannonlake - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <cavs/lib/pm_runtime.h> -#include <stdint.h> - -/** - * \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_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); - -#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/suecreek/include/platform/lib/shim.h b/src/platform/suecreek/include/platform/lib/shim.h deleted file mode 100644 index 67a078e9f6bc..000000000000 --- a/src/platform/suecreek/include/platform/lib/shim.h +++ /dev/null @@ -1,362 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <cavs/drivers/sideband-ipc.h> -#include <sof/bit.h> -#include <sof/lib/memory.h> - -#ifndef ASSEMBLY -#include <stdint.h> -#endif - -/* DSP IPC for Host Registers */ -#define IPC_DIPCTDR 0x00 -#define IPC_DIPCTDA 0x04 -#define IPC_DIPCTDD 0x08 -#define IPC_DIPCIDR 0x10 -#define IPC_DIPCIDA 0x14 -#define IPC_DIPCIDD 0x18 -#define IPC_DIPCCTL 0x28 - -#define IPC_DSP_OFFSET 0x10 - -/* DSP IPC for intra DSP communication */ -#define IPC_IDCTFC(x) (0x0 + x * IPC_DSP_OFFSET) -#define IPC_IDCTEFC(x) (0x4 + x * IPC_DSP_OFFSET) -#define IPC_IDCITC(x) (0x8 + x * IPC_DSP_OFFSET) -#define IPC_IDCIETC(x) (0xc + x * IPC_DSP_OFFSET) -#define IPC_IDCCTL 0x50 - -/* IDCTFC */ -#define IPC_IDCTFC_BUSY (1 << 31) -#define IPC_IDCTFC_MSG_MASK 0x7FFFFFFF - -/* IDCTEFC */ -#define IPC_IDCTEFC_MSG_MASK 0x3FFFFFFF - -/* IDCITC */ -#define IPC_IDCITC_BUSY (1 << 31) -#define IPC_IDCITC_MSG_MASK 0x7FFFFFFF - -/* IDCIETC */ -#define IPC_IDCIETC_DONE (1 << 30) -#define IPC_IDCIETC_MSG_MASK 0x3FFFFFFF - -/* IDCCTL */ -#define IPC_IDCCTL_IDCIDIE(x) (0x100 << (x)) -#define IPC_IDCCTL_IDCTBIE(x) (0x1 << (x)) - -#define IRQ_CPU_OFFSET 0x40 - -#define REG_IRQ_IL2MSD(xcpu) (0x0 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MCD(xcpu) (0x4 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MD(xcpu) (0x8 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2SD(xcpu) (0xc + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL2MD_ALL 0x03F181F0 - -#define REG_IRQ_IL3MSD(xcpu) (0x10 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MCD(xcpu) (0x14 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MD(xcpu) (0x18 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3SD(xcpu) (0x1c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL3MD_ALL 0x807F81FF - -#define REG_IRQ_IL4MSD(xcpu) (0x20 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MCD(xcpu) (0x24 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MD(xcpu) (0x28 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4SD(xcpu) (0x2c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL4MD_ALL 0x807F81FF - -#define REG_IRQ_IL5MSD(xcpu) (0x30 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MCD(xcpu) (0x34 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MD(xcpu) (0x38 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5SD(xcpu) (0x3c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL5MD_ALL 0xFFFFC0CF - -#define REG_IRQ_IL2RSD 0x100 -#define REG_IRQ_IL3RSD 0x104 -#define REG_IRQ_IL4RSD 0x108 -#define REG_IRQ_IL5RSD 0x10c - -#define REG_IRQ_LVL5_LP_GPDMA0_MASK (0xff << 16) -#define REG_IRQ_LVL5_LP_GPDMA1_MASK (0xff << 24) - -/* DSP Shim Registers */ -#define SHIM_DSPWC 0x20 /* DSP Wall Clock */ -#define SHIM_DSPWCTCS 0x28 /* DSP Wall Clock Timer Control & Status */ -#define SHIM_DSPWCT0C 0x30 /* DSP Wall Clock Timer 0 Compare */ -#define SHIM_DSPWCT1C 0x38 /* DSP Wall Clock Timer 1 Compare */ - -#define SHIM_DSPWCTCS_T1T (0x1 << 5) /* Timer 1 triggered */ -#define SHIM_DSPWCTCS_T0T (0x1 << 4) /* Timer 0 triggered */ -#define SHIM_DSPWCTCS_T1A (0x1 << 1) /* Timer 1 armed */ -#define SHIM_DSPWCTCS_T0A (0x1 << 0) /* Timer 0 armed */ - -/** \brief Clock control */ -#define SHIM_CLKCTL 0x78 - -/** \brief Request HP RING Oscillator Clock */ -#define SHIM_CLKCTL_RHROSCC BIT(31) - -/** \brief Request XTAL Oscillator Clock */ -#define SHIM_CLKCTL_RXOSCC BIT(30) - -/** \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 - -/** \brief LP Memory Clock Select */ -#define SHIM_CLKCTL_LMCS_DIV2 0 -#define SHIM_CLKCTL_LMCS_DIV4 BIT(1) - -/** \brief HP Memory Clock Select */ -#define SHIM_CLKCTL_HMCS_DIV2 0 -#define SHIM_CLKCTL_HMCS_DIV4 BIT(0) - -/* LP GPDMA Force Dynamic Clock Gating bits, 0--enable */ -#define SHIM_CLKCTL_TCPLCG(x) (0x1 << (16 + x)) - -/* Core clock PLL divisor */ -#define SHIM_CLKCTL_DPCS_MASK(x) (0x1 << 2) - -/* Prevent Audio PLL Shutdown */ -#define SHIM_CLKCTL_TCPAPLLS (0x1 << 7) - -/* 0--from PLL, 1--from oscillator */ -#define SHIM_CLKCTL_HDCS (0x1 << 4) - -/* Oscillator select */ -#define SHIM_CLKCTL_HDOCS (0x1 << 2) - -/* HP memory clock PLL divisor */ -#define SHIM_CLKCTL_HPMPCS (0x1 << 0) - -/** \brief Mask for requesting clock - */ -#define SHIM_CLKCTL_OSC_REQUEST_MASK \ - (SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_RXOSCC | \ - SHIM_CLKCTL_RLROSCC) - -/** \brief Mask for setting previously requested clock - */ -#define SHIM_CLKCTL_OSC_SOURCE_MASK \ - (SHIM_CLKCTL_OCS_HP_RING | SHIM_CLKCTL_LMCS_DIV4 | \ - SHIM_CLKCTL_HMCS_DIV4) - -/** \brief Clock status */ -#define SHIM_CLKSTS 0x7C - -/** \brief HP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_HROSCCS BIT(31) - -/** \brief XTAL Oscillator Clock Status */ -#define SHIM_CLKSTS_XOSCCS BIT(30) - -/** \brief LP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_LROSCCS BIT(29) - -#define SHIM_PWRCTL 0x90 -#define SHIM_PWRCTL_TCPDSPPG(x) BIT(x) -#define SHIM_PWRCTL_TCPCTLPG BIT(4) - -#define SHIM_PWRSTS 0x92 - -#define SHIM_LPSCTL 0x94 -#define SHIM_LPSCTL_BID BIT(7) -#define SHIM_LPSCTL_FDSPRUN BIT(9) -#define SHIM_LPSCTL_BATTR_0 BIT(12) - -/** \brief GPDMA shim registers Control */ -#define SHIM_GPDMA_BASE_OFFSET 0x6500 -#define SHIM_GPDMA_BASE(x) (SHIM_GPDMA_BASE_OFFSET + (x) * 0x100) - -/** \brief GPDMA Clock Control */ -#define SHIM_GPDMA_CLKCTL(x) (SHIM_GPDMA_BASE(x) + 0x4) -/* LP GPDMA Force Dynamic Clock Gating bits, 0--enable */ -#define SHIM_CLKCTL_LPGPDMAFDCGB BIT(0) - -/** \brief GPDMA Channel Linear Link Position Control */ -#define SHIM_GPDMA_CHLLPC(x, y) (SHIM_GPDMA_BASE(x) + 0x10 + (y) * 0x10) -#define SHIM_GPDMA_CHLLPC_EN BIT(7) -#define SHIM_GPDMA_CHLLPC_DHRS(x) SET_BITS(6, 0, x) - -#define L2LMCAP 0x71D00 -#define L2MPAT 0x71D04 - -#define HSPGCTL0 0x71D10 -#define HSRMCTL0 0x71D14 -#define HSPGISTS0 0x71D18 - -#define HSPGCTL1 0x71D20 -#define HSRMCTL1 0x71D24 -#define HSPGISTS1 0x71D28 - -#define SHIM_HSPGCTL(x) (HSPGCTL0 + 0x10 * (x)) -#define SHIM_HSPGISTS(x) (HSPGISTS0 + 0x10 * (x)) - -#define LSPGCTL 0x71D50 -#define LSRMCTL 0x71D54 -#define LSPGISTS 0x71D58 - -#define SHIM_L2_MECS (SHIM_BASE + 0xd0) - -/** \brief LDO Control */ -#define SHIM_LDOCTL 0xA4 -#define SHIM_LDOCTL_HPSRAM_MASK (3 << 0) -#define SHIM_LDOCTL_LPSRAM_MASK (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS (1 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS (1 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_OFF (0 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_OFF (0 << 2) - -#define DSP_INIT_LPGPDMA(x) (0x71A60 + (2*x)) -#define LPGPDMA_CTLOSEL_FLAG (1 << 15) -#define LPGPDMA_CHOSEL_FLAG (0xFF) - -#define DSP_INIT_IOPO 0x71A68 -#define IOPO_DMIC_FLAG (1 << 0) -#define IOPO_I2S_FLAG (7 << 8) - -#define DSP_INIT_GENO 0x71A6C -#define GENO_MDIVOSEL (1 << 1) -#define GENO_DIOPTOSEL (1 << 2) - -#define DSP_INIT_ALHO 0x71A70 -#define ALHO_ASO_FLAG (1 << 0) -#define ALHO_CSO_FLAG (1 << 1) -#define ALHO_CFO_FLAG (1 << 2) - -#define SHIM_SVCFG 0xF4 -#define SHIM_SVCFG_FORCE_L1_EXIT (0x1 << 1) - -/* host windows */ -#define DMWBA(x) (HOST_WIN_BASE(x) + 0x0) -#define DMWLO(x) (HOST_WIN_BASE(x) + 0x4) - -#define DMWBA_ENABLE (1 << 0) -#define DMWBA_READONLY (1 << 1) - -/* DMIC power ON bit */ -#define DMICLCTL_SPA ((uint32_t) BIT(0)) - -/* DMIC disable clock gating */ -#define DMIC_DCGD ((uint32_t) BIT(30)) - -#ifndef ASSEMBLY - -static inline uint16_t shim_read16(uint16_t reg) -{ - return *((volatile uint16_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write16(uint16_t reg, uint16_t val) -{ - *((volatile uint16_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint64_t shim_read64(uint32_t reg) -{ - return *((volatile uint64_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write64(uint32_t reg, uint64_t val) -{ - *((volatile uint64_t*)(SHIM_BASE + reg)) = val; -} - -// TODO: this should be BUILD_MAILBOX -#if !defined CONFIG_SUECREEK -static inline uint32_t sw_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)); -} - -static inline void sw_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)) = val; -} -#endif - -static inline uint32_t mn_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)(MN_BASE + reg)); -} - -static inline void mn_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(MN_BASE + reg)) = val; -} - -static inline uint32_t irq_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IRQ_BASE + reg)); -} - -static inline void irq_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IRQ_BASE + reg)) = val; -} - -static inline uint32_t ipc_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IPC_HOST_BASE + reg)); -} - -static inline void ipc_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IPC_HOST_BASE + reg)) = val; -} - -static inline uint32_t idc_read(uint32_t reg, uint32_t core_id) -{ - return *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)); -} - -static inline void idc_write(uint32_t reg, uint32_t core_id, uint32_t val) -{ - *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)) = val; -} -#endif - -#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/suecreek/include/platform/platform.h b/src/platform/suecreek/include/platform/platform.h deleted file mode 100644 index 58b1fd9bdc83..000000000000 --- a/src/platform/suecreek/include/platform/platform.h +++ /dev/null @@ -1,127 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - * Xiuli Pan <xiuli.pan@linux.intel.com> - */ - -#ifdef __SOF_PLATFORM_H__ - -#ifndef __PLATFORM_PLATFORM_H__ -#define __PLATFORM_PLATFORM_H__ - -#define PLATFORM_RESET_MHE_AT_BOOT 1 - -#define PLATFORM_MEM_INIT_AT_BOOT 1 - -#if !defined(__ASSEMBLER__) && !defined(LINKER) - -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> -#include <stddef.h> -#include <stdint.h> - -struct ll_schedule_domain; -struct timer; - -/*! \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 - -#define MAX_GPDMA_COUNT 2 - -/* Host page size */ -#define HOST_PAGE_SIZE 4096 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 -#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL - -/* Platform stream capabilities */ -#define PLATFORM_MAX_CHANNELS 4 -#define PLATFORM_MAX_STREAMS 5 - -/* local buffer size of DMA tracing */ -#define DMA_TRACE_LOCAL_SIZE (HOST_PAGE_SIZE * 2) - -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 500 - -/* baud-rate used for uart port trace log */ -#define PATFORM_TRACE_UART_BAUDRATE 115200 - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* minimal L1 exit time in cycles */ -#define PLATFORM_FORCE_L1_EXIT_TIME 985 - -/* the SSP port fifo depth */ -#define SSP_FIFO_DEPTH 16 - -/* the watermark for the SSP fifo depth setting */ -#define SSP_FIFO_WATERMARK 8 - -/* minimal SSP port delay in cycles */ -#define PLATFORM_SSP_DELAY 1000 - -/* SSI / SPI GPIO bindings */ -#define PLATFORM_SPI_GPIO_ID 0 -#define PLATFORM_SPI_GPIO_IRQ 14 - -// TODO: need UART versions -#if 0 -/* Platform defined trace code */ -static inline void platform_panic(uint32_t p) -{ - mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p & 0x3fffffff); - ipc_write(IPC_DIPCIDD, MAILBOX_EXCEPTION_OFFSET + 2 * 0x20000); - ipc_write(IPC_DIPCIDR, 0x80000000 | (p & 0x3fffffff)); -} -#else -static inline void platform_panic(uint32_t p) -{ -} -#endif - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -void platform_wait_for_interrupt(int level); - -extern intptr_t _module_init_start; -extern intptr_t _module_init_end; - -#endif -#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/suecreek/include/platform/trace/trace.h b/src/platform/suecreek/include/platform/trace/trace.h deleted file mode 100644 index fe02bb4656ee..000000000000 --- a/src/platform/suecreek/include/platform/trace/trace.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_TRACE_TRACE_H__ - -#ifndef __PLATFORM_TRACE_TRACE_H__ -#define __PLATFORM_TRACE_TRACE_H__ - -/* Platform defined trace code */ -#define platform_trace_point(__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/suecreek/lib/CMakeLists.txt b/src/platform/suecreek/lib/CMakeLists.txt deleted file mode 100644 index 47a1b5962abf..000000000000 --- a/src/platform/suecreek/lib/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof clk.c) diff --git a/src/platform/suecreek/lib/clk.c b/src/platform/suecreek/lib/clk.c deleted file mode 100644 index e08358c87ddf..000000000000 --- a/src/platform/suecreek/lib/clk.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> - -const struct freq_table platform_cpu_freq[] = { - { 120000000, 120000 }, - { CLK_MAX_CPU_HZ, 400000 }, -}; - -const uint32_t cpu_freq_enc[] = { - SHIM_CLKCTL_RLROSCC | SHIM_CLKCTL_OCS_LP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, - SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_OCS_HP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, -}; - -const uint32_t cpu_freq_status_mask[] = { - SHIM_CLKSTS_LROSCCS, - SHIM_CLKSTS_HROSCCS, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table *cpu_freq = platform_cpu_freq; - -/* IMPORTANT: array should be filled in increasing order - * (regarding to .freq field) - */ -const struct freq_table platform_ssp_freq[] = { - { 19200000, 19200 }, - { 24000000, 24000 }, -}; - -const uint32_t platform_ssp_freq_sources[] = { - SSP_CLOCK_XTAL_OSCILLATOR, - SSP_CLOCK_PLL_FIXED, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; diff --git a/src/platform/suecreek/rom.x.in b/src/platform/suecreek/rom.x.in deleted file mode 100644 index c0845ee55b10..000000000000 --- a/src/platform/suecreek/rom.x.in +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Linker Script for Suecreek ROM. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = ROM_BASE, - len = ROM_RESET_TEXT_SIZE - vector_reset_lit : - org = ROM_BASE + ROM_RESET_TEXT_SIZE, - len = ROM_RESET_LIT_SIZE - vector_base_text : - org = ROM_BASE + ROM_RESET_TEXT_SIZE + ROM_RESET_LIT_SIZE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = ROM_BASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = ROM_BASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = ROM_BASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = ROM_BASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text : - org = ROM_BASE + 0x800, - len = ROM_SIZE, - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; -} - -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = ROM_BASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - /* stack */ - _end = BOOT_LDR_STACK_BASE; - PROVIDE(end = BOOT_LDR_STACK_BASE); - _stack_sentry = BOOT_LDR_STACK_BASE; - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/suecreek/suecreek.x.in b/src/platform/suecreek/suecreek.x.in deleted file mode 100644 index 4dc70396f48d..000000000000 --- a/src/platform/suecreek/suecreek.x.in +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Linker Script for Suecreek. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = XCHAL_RESET_VECTOR0_PADDR, - len = SOF_MEM_RESET_TEXT_SIZE - vector_reset_lit : - org = XCHAL_RESET_VECTOR0_PADDR + SOF_MEM_RESET_TEXT_SIZE, - len = SOF_MEM_RESET_LIT_SIZE - vector_memory_lit : - org = XCHAL_MEMERROR_VECTOR_PADDR + SOF_MEM_ERROR_LIT_SIZE, - len = SOF_MEM_ERROR_LIT_SIZE - vector_memory_text : - org = XCHAL_MEMERROR_VECTOR_PADDR, - len = SOF_MEM_ERROR_TEXT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_fw : - org = SOF_FW_BASE, - len = SOF_FW_MAX_SIZE, - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_memory_lit_phdr PT_LOAD; - vector_memory_text_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_fw_phdr PT_LOAD; - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; -} - -/* Default entry point: */ -ENTRY(_ResetVector) -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = XCHAL_VECBASE_RESET_PADDR); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wb_base = 0x44024000; -_memmap_cacheattr_wt_base = 0x11021000; -_memmap_cacheattr_bp_base = 0x22022000; -_memmap_cacheattr_unused_mask = 0x00F00FFF; -_memmap_cacheattr_wb_trapnull = 0x4422422F; -_memmap_cacheattr_wba_trapnull = 0x4422422F; -_memmap_cacheattr_wbna_trapnull = 0x25222222; -_memmap_cacheattr_wt_trapnull = 0x1122122F; -_memmap_cacheattr_bp_trapnull = 0x2222222F; -_memmap_cacheattr_wb_strict = 0x44F24FFF; -_memmap_cacheattr_wt_strict = 0x11F21FFF; -_memmap_cacheattr_bp_strict = 0x22F22FFF; -_memmap_cacheattr_wb_allvalid = 0x44224222; -_memmap_cacheattr_wt_allvalid = 0x11221222; -_memmap_cacheattr_bp_allvalid = 0x22222222; -_memmap_cacheattr_sue_creek = 0xf2ff4242; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_sue_creek); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .MemoryExceptionVector.literal : ALIGN(4) - { - _MemoryExceptionVector_literal_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.literal)) - _MemoryExceptionVector_literal_end = ABSOLUTE(.); - } >vector_memory_lit :vector_memory_lit_phdr - - .MemoryExceptionVector.text : ALIGN(4) - { - _MemoryExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.text)) - _MemoryExceptionVector_text_end = ABSOLUTE(.); - } >vector_memory_text :vector_memory_text_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .ResetHandler.text : ALIGN(4) - { - _ResetHandler_text_start = ABSOLUTE(.); - KEEP (*(.ResetHandler.text)) - _ResetHandler_text_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_fw :sof_fw_phdr - - .rodata : ALIGN(SRAM_BANK_SIZE) /* TODO: it should be 4096 */ - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .shared_data : ALIGN(PLATFORM_DCACHE_ALIGN) - { - _shared_data_start = ABSOLUTE(.); - *(*.shared_data) - _shared_data_end = ABSOLUTE(.); - . = ALIGN(PLATFORM_DCACHE_ALIGN); - } >sof_fw :sof_fw_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_fw :sof_fw_phdr - - .bss (NOLOAD) : ALIGN(4096) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - - . = ALIGN (SRAM_BANK_SIZE); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_M_SIZE; - _system_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_M_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_SIZE; - _sof_stack_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _sof_core_s_start = ABSOLUTE(.); - . = . + SOF_CORE_S_T_SIZE; - _sof_core_s_end = ABSOLUTE(.); - - _bss_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - /* stack */ - _end = _sof_stack_start; - PROVIDE(end = _sof_stack_start); - _stack_sentry = _sof_stack_start; - __stack = _sof_stack_end; - - /* Slave core size */ - _core_s_size = SOF_CORE_S_SIZE; - - /* System Heap */ - _system_heap = _system_heap_start; - - /* system runtime heap */ - _system_runtime_heap = _system_runtime_heap_start; - - /* module heap */ - _module_heap = _runtime_heap_start; - - /* buffer heap */ - _buffer_heap = _buffer_heap_start; - _buffer_heap_end = _buffer_heap_end; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr -} diff --git a/src/platform/tigerlake/CMakeLists.txt b/src/platform/tigerlake/CMakeLists.txt deleted file mode 100644 index 3fad0567edcb..000000000000 --- a/src/platform/tigerlake/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_subdirectory(lib) - -add_executable(boot_module boot_module.c) -add_executable(base_module base_module.c) - -target_link_libraries(boot_module sof_options) -target_link_libraries(base_module sof_options) diff --git a/src/platform/tigerlake/base_module.c b/src/platform/tigerlake/base_module.c deleted file mode 100644 index 9c9f87b6b91c..000000000000 --- a/src/platform/tigerlake/base_module.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest tgl_manifest = { - .module = { - .name = "BASEFW", - .uuid = {0x32, 0x8c, 0x39, 0x0e, 0xde, 0x5a, 0x4b, 0xba, - 0x93, 0xb1, 0xc5, 0x04, 0x32, 0x28, 0x0e, 0xe4}, - .entry_point = SOF_TEXT_START, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/tigerlake/boot_ldr.x.in b/src/platform/tigerlake/boot_ldr.x.in deleted file mode 100644 index 0aa16d69e919..000000000000 --- a/src/platform/tigerlake/boot_ldr.x.in +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Linker Script for Tigerlake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - boot_entry_text : - org = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - len = IMR_BOOT_LDR_TEXT_ENTRY_SIZE - boot_entry_lit : - org = IMR_BOOT_LDR_LIT_BASE, - len = IMR_BOOT_LDR_LIT_SIZE - sof_text : - org = IMR_BOOT_LDR_TEXT_BASE, - len = IMR_BOOT_LDR_TEXT_SIZE, - sof_data : - org = IMR_BOOT_LDR_DATA_BASE, - len = IMR_BOOT_LDR_DATA_SIZE - sof_bss_data : - org = IMR_BOOT_LDR_BSS_BASE, - len = IMR_BOOT_LDR_BSS_SIZE - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE - lpsram_mem : - org = LP_SRAM_BASE, - len = LP_SRAM_SIZE -} - -PHDRS -{ - boot_entry_text_phdr PT_LOAD; - boot_entry_lit_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_data_phdr PT_LOAD; - sof_bss_data_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; - wnd0_phdr PT_LOAD; - lpsram_mem_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(boot_entry) -EXTERN(reset_vector) - -SECTIONS -{ - .boot_entry.text : ALIGN(4) - { - _boot_entry_text_start = ABSOLUTE(.); - KEEP (*(.boot_entry.text)) - _boot_entry_text_end = ABSOLUTE(.); - } >boot_entry_text :boot_entry_text_phdr - - .boot_entry.literal : ALIGN(4) - { - _boot_entry_literal_start = ABSOLUTE(.); - *(.boot_entry.literal) - *(.literal .literal.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - _boot_entry_literal_end = ABSOLUTE(.); - } >boot_entry_lit :boot_entry_lit_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - *(.entry.text) - *(.init.literal) - KEEP(*(.init)) - *( .text .text.*) - *(.fini.literal) - KEEP(*(.fini)) - *(.gnu.version) - KEEP (*(.ResetVector.text)) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - .rodata : ALIGN(4) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_data :sof_data_phdr - - .bss (NOLOAD) : ALIGN(8) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >sof_bss_data :sof_bss_data_phdr - - _man = 0x1234567; - - PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - - _memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; - PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - __wnd0 = HP_SRAM_WIN0_BASE; - __wnd0_size = HP_SRAM_WIN0_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - .lpsram(NOLOAD) : ALIGN(8) - { - _lpsram_start = ABSOLUTE(.); - KEEP (*(*.lpsram)) - _lpsram_end = ABSOLUTE(.); - } >lpsram_mem :lpsram_mem_phdr -} diff --git a/src/platform/tigerlake/boot_module.c b/src/platform/tigerlake/boot_module.c deleted file mode 100644 index dd1c30015a22..000000000000 --- a/src/platform/tigerlake/boot_module.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/lib/memory.h> -#include <user/manifest.h> - -/* - * Each module has an entry in the FW manifest header. This is NOT part of - * the SOF executable image but is inserted by object copy as a ELF section - * for parsing by rimage (to genrate the manifest). - */ -struct sof_man_module_manifest tgl_bootldr_manifest = { - .module = { - .name = "BRNGUP", - .uuid = {0xf3, 0xe4, 0x79, 0x2b, 0x75, 0x46, 0x49, 0xf6, - 0x89, 0xdf, 0x3b, 0xc1, 0x94, 0xa9, 0x1a, 0xeb}, - .entry_point = IMR_BOOT_LDR_TEXT_ENTRY_BASE, - .type = { - .load_type = SOF_MAN_MOD_TYPE_MODULE, - .domain_ll = 1, - }, - .affinity_mask = 3, - }, -}; - -/* not used, but stops linker complaining */ -int _start; diff --git a/src/platform/tigerlake/include/arch/xtensa/config/core-isa.h b/src/platform/tigerlake/include/arch/xtensa/config/core-isa.h deleted file mode 100644 index 95afb9588332..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/core-isa.h +++ /dev/null @@ -1,636 +0,0 @@ -/* - * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa - * processor CORE configuration - * - * See <xtensa/config/core.h>, which includes this file, for more details. - */ - -/* Xtensa processor core configuration information. - - Copyright (c) 1999-2019 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_CONFIGURATION_H -#define _XTENSA_CORE_CONFIGURATION_H - - -/**************************************************************************** - Parameters Useful for Any Code, USER or PRIVILEGED - ****************************************************************************/ - -/* - * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is - * configured, and a value of 0 otherwise. These macros are always defined. - */ - - -/*---------------------------------------------------------------------- - ISA - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ -#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ -#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ -#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ -#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ -#define XCHAL_HAVE_DEBUG 1 /* debug option */ -#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ -#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ -#define XCHAL_LOOP_BUFFER_SIZE 64 /* zero-ov. loop instr buffer size */ -#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ -#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ -#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ -#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ -#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ -#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ -#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ -#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ -#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ -#define XCHAL_HAVE_L32R 1 /* L32R instruction */ -#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ -#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ -#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ -#define XCHAL_HAVE_EXCLUSIVE 0 /* L32EX/S32EX instructions */ -#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ -#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ -#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ -#define XCHAL_HAVE_ABS 1 /* ABS instruction */ -/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ -/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ -#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ -#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ -#define XCHAL_HAVE_SPECULATION 0 /* speculation */ -#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ -#define XCHAL_NUM_CONTEXTS 1 /* */ -#define XCHAL_NUM_MISC_REGS 0 /* num of scratch regs (0..4) */ -#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ -#define XCHAL_HAVE_PRID 1 /* processor ID register */ -#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ -#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ -#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ -#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ -#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ -#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ -#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ -#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ -#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ -#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ -#define XCHAL_CP_MAXCFG 2 /* max allowed cp id plus one */ -#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ - -#define XCHAL_HAVE_FUSION 0 /* Fusion*/ -#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ -#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ -#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ -#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ -#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ -#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ -#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ -#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ -#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ -#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ -#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3 1 /* HiFi3 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI3Z 0 /* HiFi3Z Audio Engine pkg */ -#define XCHAL_HAVE_HIFI3Z_VFPU 0 /* HiFi3Z Audio Engine VFPU option */ -#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ -#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ -#define XCHAL_HAVE_HIFI_MINI 0 - - - -#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ -#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ -#define XCHAL_HAVE_USER_SPFPU 0 /* user SP floating-point pkg */ -#define XCHAL_HAVE_FP 1 /* single prec floating point */ -#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ -#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ -#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ -#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ -#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ -#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ -#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ -#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ -#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ -#define XCHAL_HAVE_DFP_ACCEL 0 /* double precision FP acceleration pkg */ -#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ - -#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ -#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ -#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ -#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ - -#define XCHAL_HAVE_FUSIONG 0 /* FusionG */ -#define XCHAL_HAVE_FUSIONG3 0 /* FusionG3 */ -#define XCHAL_HAVE_FUSIONG6 0 /* FusionG6 */ -#define XCHAL_HAVE_FUSIONG_SP_VFPU 0 /* sp_vfpu option on FusionG */ -#define XCHAL_HAVE_FUSIONG_DP_VFPU 0 /* dp_vfpu option on FusionG */ -#define XCHAL_FUSIONG_SIMD32 0 /* simd32 for FusionG */ - -#define XCHAL_HAVE_PDX 0 /* PDX */ -#define XCHAL_PDX_SIMD32 0 /* simd32 for PDX */ -#define XCHAL_HAVE_PDX4 0 /* PDX4 */ -#define XCHAL_HAVE_PDX8 0 /* PDX8 */ -#define XCHAL_HAVE_PDX16 0 /* PDX16 */ - -#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ -#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ -#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ -#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ -#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ -#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ -#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ -#define XCHAL_HAVE_BBENEP_SP_VFPU 0 /* sp_vfpu option on BBE-EP */ -#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ -#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ -#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ -#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ -#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ -#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ -#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ -#define XCHAL_HAVE_GRIVPEP 0 /* General Release of IVPEP */ -#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ - -#define XCHAL_HAVE_VISION 0 /* Vision P5/P6 */ -#define XCHAL_VISION_SIMD16 0 /* simd16 for Vision P5/P6 */ -#define XCHAL_VISION_TYPE 0 /* Vision P5, P6, or P3 */ -#define XCHAL_VISION_QUAD_MAC_TYPE 0 /* quad_mac option on Vision P6 */ -#define XCHAL_HAVE_VISION_HISTOGRAM 0 /* histogram option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_SP_VFPU 0 /* sp_vfpu option on Vision P5/P6 */ -#define XCHAL_HAVE_VISION_HP_VFPU 0 /* hp_vfpu option on Vision P6 */ - -#define XCHAL_HAVE_VISIONC 0 /* Vision C */ - -/*---------------------------------------------------------------------- - MISC - ----------------------------------------------------------------------*/ - -#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ -#define XCHAL_NUM_WRITEBUFFER_ENTRIES 16 /* size of write buffer */ -#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ -#define XCHAL_DATA_WIDTH 8 /* data width in bytes */ -#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay - (1 = 5-stage, 2 = 7-stage) */ -#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ -#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ -/* In T1050, applies to selected core load and store instructions (see ISA): */ -#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ -#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ -#define XCHAL_UNALIGNED_LOAD_HW 0 /* unaligned loads work in hw */ -#define XCHAL_UNALIGNED_STORE_HW 0 /* unaligned stores work in hw*/ - -#define XCHAL_SW_VERSION 1200008 /* sw version of this header */ - -#define XCHAL_CORE_ID "cavs2x_LX6HiFi3_2017_8" /* alphanum core name - (CoreID) set in the Xtensa - Processor Generator */ - -#define XCHAL_BUILD_UNIQUE_ID 0x0007AF71 /* 22-bit sw build ID */ - -/* - * These definitions describe the hardware targeted by this software. - */ -#define XCHAL_HW_CONFIGID0 0xC2F3FBFE /* ConfigID hi 32 bits*/ -#define XCHAL_HW_CONFIGID1 0x1CC6C29B /* ConfigID lo 32 bits*/ -#define XCHAL_HW_VERSION_NAME "LX6.0.3" /* full version name */ -#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ -#define XCHAL_HW_VERSION_MINOR 3 /* minor ver# of targeted hw */ -#define XCHAL_HW_VERSION 260003 /* major*100+minor */ -#define XCHAL_HW_REL_LX6 1 -#define XCHAL_HW_REL_LX6_0 1 -#define XCHAL_HW_REL_LX6_0_3 1 -#define XCHAL_HW_CONFIGID_RELIABLE 1 -/* If software targets a *range* of hardware versions, these are the bounds: */ -#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION_MINOR 3 /* minor v of earliest tgt hw */ -#define XCHAL_HW_MIN_VERSION 260003 /* earliest targeted hw */ -#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION_MINOR 3 /* minor v of latest tgt hw */ -#define XCHAL_HW_MAX_VERSION 260003 /* latest targeted hw */ - - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_ICACHE_LINESIZE 64 /* I-cache line size in bytes */ -#define XCHAL_DCACHE_LINESIZE 64 /* D-cache line size in bytes */ -#define XCHAL_ICACHE_LINEWIDTH 6 /* log2(I line size in bytes) */ -#define XCHAL_DCACHE_LINEWIDTH 6 /* log2(D line size in bytes) */ - -#define XCHAL_ICACHE_SIZE 16384 /* I-cache size in bytes or 0 */ -#define XCHAL_DCACHE_SIZE 49152 /* D-cache size in bytes or 0 */ - -#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ -#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ - -#define XCHAL_HAVE_PREFETCH 1 /* PREFCTL register */ -#define XCHAL_HAVE_PREFETCH_L1 1 /* prefetch to L1 dcache */ -#define XCHAL_PREFETCH_CASTOUT_LINES 2 /* dcache pref. castout bufsz */ -#define XCHAL_PREFETCH_ENTRIES 8 /* cache prefetch entries */ -#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ -#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ -#define XCHAL_HAVE_ICACHE_TEST 1 /* Icache test instructions */ -#define XCHAL_HAVE_DCACHE_TEST 1 /* Dcache test instructions */ -#define XCHAL_HAVE_ICACHE_DYN_WAYS 1 /* Icache dynamic way support */ -#define XCHAL_HAVE_DCACHE_DYN_WAYS 1 /* Dcache dynamic way support */ - - - - -/**************************************************************************** - Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code - ****************************************************************************/ - - -#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY - -/*---------------------------------------------------------------------- - CACHE - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_PIF 1 /* any outbound bus present */ - -#define XCHAL_HAVE_AXI 0 /* AXI bus */ -#define XCHAL_HAVE_AXI_ECC 0 /* ECC on AXI bus */ -#define XCHAL_HAVE_ACELITE 0 /* ACELite bus */ - -#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ -#define XCHAL_HAVE_PIF_REQ_ATTR 1 /* pif attribute */ - -/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ - -/* Number of cache sets in log2(lines per way): */ -#define XCHAL_ICACHE_SETWIDTH 6 -#define XCHAL_DCACHE_SETWIDTH 8 - -/* Cache set associativity (number of ways): */ -#define XCHAL_ICACHE_WAYS 4 -#define XCHAL_DCACHE_WAYS 3 - -/* Cache features: */ -#define XCHAL_ICACHE_LINE_LOCKABLE 1 -#define XCHAL_DCACHE_LINE_LOCKABLE 1 -#define XCHAL_ICACHE_ECC_PARITY XTHAL_MEMEP_ECC -#define XCHAL_DCACHE_ECC_PARITY XTHAL_MEMEP_ECC - -/* Cache access size in bytes (affects operation of SICW instruction): */ -#define XCHAL_ICACHE_ACCESS_SIZE 8 -#define XCHAL_DCACHE_ACCESS_SIZE 8 - -#define XCHAL_DCACHE_BANKS 1 /* number of banks */ - -/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ -#define XCHAL_CA_BITS 4 - - -/*---------------------------------------------------------------------- - INTERNAL I/D RAM/ROMs and XLMI - ----------------------------------------------------------------------*/ -#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ -#define XCHAL_NUM_INSTRAM 1 /* number of core instr. RAMs */ -#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ -#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ -#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ -#define XCHAL_NUM_XLMI 1 /* number of core XLMI ports */ - -/* Instruction RAM 0: */ -#define XCHAL_INSTRAM0_VADDR 0x9F100000 /* virtual address */ -#define XCHAL_INSTRAM0_PADDR 0x9F100000 /* physical address */ -#define XCHAL_INSTRAM0_SIZE 1048576 /* size in bytes */ -#define XCHAL_INSTRAM0_ECC_PARITY XTHAL_MEMEP_ECC /* ECC/parity type, 0=none */ -#define XCHAL_HAVE_INSTRAM0 1 -#define XCHAL_INSTRAM0_HAVE_IDMA 0 /* idma supported by this local memory */ - -/* Data RAM 0: */ -#define XCHAL_DATARAM0_VADDR 0x9F000000 /* virtual address */ -#define XCHAL_DATARAM0_PADDR 0x9F000000 /* physical address */ -#define XCHAL_DATARAM0_SIZE 524288 /* size in bytes */ -#define XCHAL_DATARAM0_ECC_PARITY XTHAL_MEMEP_ECC /* ECC/parity type, 0=none */ -#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ -#define XCHAL_HAVE_DATARAM0 1 -#define XCHAL_DATARAM0_HAVE_IDMA 0 /* idma supported by this local memory */ - -/* XLMI Port 0: */ -#define XCHAL_XLMI0_VADDR 0x9F080000 /* virtual address */ -#define XCHAL_XLMI0_PADDR 0x9F080000 /* physical address */ -#define XCHAL_XLMI0_SIZE 65536 /* size in bytes */ -#define XCHAL_XLMI0_ECC_PARITY 0 /* ECC/parity type, 0=none */ - -#define XCHAL_HAVE_IDMA 0 -#define XCHAL_HAVE_IDMA_TRANSPOSE 0 - -#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ - - -/*---------------------------------------------------------------------- - INTERRUPTS and TIMERS - ----------------------------------------------------------------------*/ - -#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ -#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ -#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ -#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ -#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ -#define XCHAL_NUM_INTERRUPTS 21 /* number of interrupts */ -#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ -#define XCHAL_NUM_EXTINTERRUPTS 8 /* num of external interrupts */ -#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels - (not including level zero) */ -#define XCHAL_EXCM_LEVEL 5 /* level masked by PS.EXCM */ - /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ - -/* Masks of interrupts at each interrupt level: */ -#define XCHAL_INTLEVEL1_MASK 0x0000000F -#define XCHAL_INTLEVEL2_MASK 0x000000F0 -#define XCHAL_INTLEVEL3_MASK 0x00000F00 -#define XCHAL_INTLEVEL4_MASK 0x00007000 -#define XCHAL_INTLEVEL5_MASK 0x000F8000 -#define XCHAL_INTLEVEL6_MASK 0x00000000 -#define XCHAL_INTLEVEL7_MASK 0x00100000 - -/* Masks of interrupts at each range 1..n of interrupt levels: */ -#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x0000000F -#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x000000FF -#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x00000FFF -#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x00007FFF -#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x000FFFFF -#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x001FFFFF - -/* Level of each interrupt: */ -#define XCHAL_INT0_LEVEL 1 -#define XCHAL_INT1_LEVEL 1 -#define XCHAL_INT2_LEVEL 1 -#define XCHAL_INT3_LEVEL 1 -#define XCHAL_INT4_LEVEL 2 -#define XCHAL_INT5_LEVEL 2 -#define XCHAL_INT6_LEVEL 2 -#define XCHAL_INT7_LEVEL 2 -#define XCHAL_INT8_LEVEL 3 -#define XCHAL_INT9_LEVEL 3 -#define XCHAL_INT10_LEVEL 3 -#define XCHAL_INT11_LEVEL 3 -#define XCHAL_INT12_LEVEL 4 -#define XCHAL_INT13_LEVEL 4 -#define XCHAL_INT14_LEVEL 4 -#define XCHAL_INT15_LEVEL 5 -#define XCHAL_INT16_LEVEL 5 -#define XCHAL_INT17_LEVEL 5 -#define XCHAL_INT18_LEVEL 5 -#define XCHAL_INT19_LEVEL 5 -#define XCHAL_INT20_LEVEL 7 -#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ -#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ -#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with - EXCSAVE/EPS/EPC_n, RFI n) */ - -/* Type of each interrupt: */ -#define XCHAL_INT0_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT1_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT3_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT4_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT5_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT8_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT9_TYPE XTHAL_INTTYPE_TIMER -#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT11_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT12_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL -#define XCHAL_INT19_TYPE XTHAL_INTTYPE_SOFTWARE -#define XCHAL_INT20_TYPE XTHAL_INTTYPE_NMI - -/* Masks of interrupts for each type of interrupt: */ -#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFE00000 -#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0008D999 -#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 -#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x00072444 -#define XCHAL_INTTYPE_MASK_TIMER 0x00000222 -#define XCHAL_INTTYPE_MASK_NMI 0x00100000 -#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 -#define XCHAL_INTTYPE_MASK_PROFILING 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_DONE 0x00000000 -#define XCHAL_INTTYPE_MASK_IDMA_ERR 0x00000000 -#define XCHAL_INTTYPE_MASK_GS_ERR 0x00000000 - -/* Interrupt numbers assigned to specific interrupt sources: */ -#define XCHAL_TIMER0_INTERRUPT 1 /* CCOMPARE0 */ -#define XCHAL_TIMER1_INTERRUPT 5 /* CCOMPARE1 */ -#define XCHAL_TIMER2_INTERRUPT 9 /* CCOMPARE2 */ -#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED -#define XCHAL_NMI_INTERRUPT 20 /* non-maskable interrupt */ - -/* Interrupt numbers for levels at which only one interrupt is configured: */ -#define XCHAL_INTLEVEL7_NUM 20 -/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ - - -/* - * External interrupt mapping. - * These macros describe how Xtensa processor interrupt numbers - * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) - * map to external BInterrupt<n> pins, for those interrupts - * configured as external (level-triggered, edge-triggered, or NMI). - * See the Xtensa processor databook for more details. - */ - -/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ -#define XCHAL_EXTINT0_NUM 2 /* (intlevel 1) */ -#define XCHAL_EXTINT1_NUM 6 /* (intlevel 2) */ -#define XCHAL_EXTINT2_NUM 10 /* (intlevel 3) */ -#define XCHAL_EXTINT3_NUM 13 /* (intlevel 4) */ -#define XCHAL_EXTINT4_NUM 16 /* (intlevel 5) */ -#define XCHAL_EXTINT5_NUM 17 /* (intlevel 5) */ -#define XCHAL_EXTINT6_NUM 18 /* (intlevel 5) */ -#define XCHAL_EXTINT7_NUM 20 /* (intlevel 7) */ -/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ -#define XCHAL_INT2_EXTNUM 0 /* (intlevel 1) */ -#define XCHAL_INT6_EXTNUM 1 /* (intlevel 2) */ -#define XCHAL_INT10_EXTNUM 2 /* (intlevel 3) */ -#define XCHAL_INT13_EXTNUM 3 /* (intlevel 4) */ -#define XCHAL_INT16_EXTNUM 4 /* (intlevel 5) */ -#define XCHAL_INT17_EXTNUM 5 /* (intlevel 5) */ -#define XCHAL_INT18_EXTNUM 6 /* (intlevel 5) */ -#define XCHAL_INT20_EXTNUM 7 /* (intlevel 7) */ - - -/*---------------------------------------------------------------------- - EXCEPTIONS and VECTORS - ----------------------------------------------------------------------*/ - -#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture - number: 1 == XEA1 (old) - 2 == XEA2 (new) - 0 == XEAX (extern) or TX */ -#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ -#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ -#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ -#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ -#define XCHAL_HAVE_HALT 0 /* halt architecture option */ -#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ -#define XCHAL_HAVE_MEM_ECC_PARITY 1 /* local memory ECC/parity */ -#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ -#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ -#define XCHAL_VECBASE_RESET_VADDR 0x9F180800 /* VECBASE reset value */ -#define XCHAL_VECBASE_RESET_PADDR 0x9F180800 -#define XCHAL_RESET_VECBASE_OVERLAP 0 - -#define XCHAL_RESET_VECTOR0_VADDR 0x9F180000 -#define XCHAL_RESET_VECTOR0_PADDR 0x9F180000 -#define XCHAL_RESET_VECTOR1_VADDR 0xBE800000 -#define XCHAL_RESET_VECTOR1_PADDR 0xBE800000 -#define XCHAL_RESET_VECTOR_VADDR 0x9F180000 -#define XCHAL_RESET_VECTOR_PADDR 0x9F180000 -#define XCHAL_MEMERROR_VECTOR0_VADDR 0x9F180400 -#define XCHAL_MEMERROR_VECTOR0_PADDR 0x9F180400 -#define XCHAL_MEMERROR_VECTOR1_VADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR1_PADDR 0xBE800400 -#define XCHAL_MEMERROR_VECTOR_VADDR 0x9F180400 -#define XCHAL_MEMERROR_VECTOR_PADDR 0x9F180400 -#define XCHAL_USER_VECOFS 0x00000340 -#define XCHAL_USER_VECTOR_VADDR 0x9F180B40 -#define XCHAL_USER_VECTOR_PADDR 0x9F180B40 -#define XCHAL_KERNEL_VECOFS 0x00000300 -#define XCHAL_KERNEL_VECTOR_VADDR 0x9F180B00 -#define XCHAL_KERNEL_VECTOR_PADDR 0x9F180B00 -#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 -#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x9F180BC0 -#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x9F180BC0 -#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 -#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 -#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 -#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 -#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 -#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 -#define XCHAL_WINDOW_VECTORS_VADDR 0x9F180800 -#define XCHAL_WINDOW_VECTORS_PADDR 0x9F180800 -#define XCHAL_INTLEVEL2_VECOFS 0x00000180 -#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x9F180980 -#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x9F180980 -#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 -#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x9F1809C0 -#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x9F1809C0 -#define XCHAL_INTLEVEL4_VECOFS 0x00000200 -#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x9F180A00 -#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x9F180A00 -#define XCHAL_INTLEVEL5_VECOFS 0x00000240 -#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x9F180A40 -#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x9F180A40 -#define XCHAL_INTLEVEL6_VECOFS 0x00000280 -#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x9F180A80 -#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x9F180A80 -#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS -#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR -#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR -#define XCHAL_NMI_VECOFS 0x000002C0 -#define XCHAL_NMI_VECTOR_VADDR 0x9F180AC0 -#define XCHAL_NMI_VECTOR_PADDR 0x9F180AC0 -#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS -#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR -#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR - - -/*---------------------------------------------------------------------- - DEBUG MODULE - ----------------------------------------------------------------------*/ - -/* Misc */ -#define XCHAL_HAVE_DEBUG_ERI 0 /* ERI to debug module */ -#define XCHAL_HAVE_DEBUG_APB 0 /* APB to debug module */ -#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ - -/* On-Chip Debug (OCD) */ -#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ -#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ -#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ -#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ -#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ - -/* TRAX (in core) */ -#define XCHAL_HAVE_TRAX 0 /* TRAX in debug module */ -#define XCHAL_TRAX_MEM_SIZE 0 /* TRAX memory size in bytes */ -#define XCHAL_TRAX_MEM_SHAREABLE 0 /* start/end regs; ready sig. */ -#define XCHAL_TRAX_ATB_WIDTH 0 /* ATB width (bits), 0=no ATB */ -#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ - -/* Perf counters */ -#define XCHAL_NUM_PERF_COUNTERS 0 /* performance counters */ - - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* See core-matmap.h header file for more details. */ - -#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ -#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ -#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ -#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ -#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ -#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ -#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ -#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table - [autorefill] and protection) - usable for an MMU-based OS */ - -/* If none of the above last 5 are set, it's a custom TLB configuration. */ - -#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ -#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ -#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ - -/*---------------------------------------------------------------------- - MPU - ----------------------------------------------------------------------*/ -#define XCHAL_HAVE_MPU 0 -#define XCHAL_MPU_ENTRIES 0 - -#define XCHAL_MPU_ALIGN_REQ 1 /* MPU requires alignment of entries to background map */ -#define XCHAL_MPU_BACKGROUND_ENTRIES 0 /* number of entries in bg map*/ -#define XCHAL_MPU_BG_CACHEADRDIS 0 /* default CACHEADRDIS for bg */ - -#define XCHAL_MPU_ALIGN_BITS 0 -#define XCHAL_MPU_ALIGN 0 - -#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ - - -#endif /* _XTENSA_CORE_CONFIGURATION_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/arch/xtensa/config/core-matmap.h b/src/platform/tigerlake/include/arch/xtensa/config/core-matmap.h deleted file mode 100644 index d7fd7795e3f1..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/core-matmap.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * xtensa/config/core-matmap.h -- Memory access and translation mapping - * parameters (CHAL) of the Xtensa processor core configuration. - * - * If you are using Xtensa Tools, see <xtensa/config/core.h> (which includes - * this file) for more details. - * - * In the Xtensa processor products released to date, all parameters - * defined in this file are derivable (at least in theory) from - * information contained in the core-isa.h header file. - * In particular, the following core configuration parameters are relevant: - * XCHAL_HAVE_CACHEATTR - * XCHAL_HAVE_MIMIC_CACHEATTR - * XCHAL_HAVE_XLT_CACHEATTR - * XCHAL_HAVE_PTP_MMU - * XCHAL_ITLB_ARF_ENTRIES_LOG2 - * XCHAL_DTLB_ARF_ENTRIES_LOG2 - * XCHAL_DCACHE_IS_WRITEBACK - * XCHAL_ICACHE_SIZE (presence of I-cache) - * XCHAL_DCACHE_SIZE (presence of D-cache) - * XCHAL_HW_VERSION_MAJOR - * XCHAL_HW_VERSION_MINOR - */ - -/* Copyright (c) 1999-2018 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_CORE_MATMAP_H -#define XTENSA_CONFIG_CORE_MATMAP_H - - -/*---------------------------------------------------------------------- - CACHE (MEMORY ACCESS) ATTRIBUTES - ----------------------------------------------------------------------*/ - - - -/* Cache Attribute encodings -- lists of access modes for each cache attribute: */ -#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_CACHED XCHAL_SEP \ - XTHAL_FAM_BYPASS XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION XCHAL_SEP \ - XTHAL_FAM_EXCEPTION -#define XCHAL_LCA_LIST XTHAL_LAM_CACHED_NOALLOC XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_CACHED XCHAL_SEP \ - XTHAL_LAM_BYPASSG XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_EXCEPTION XCHAL_SEP \ - XTHAL_LAM_ISOLATE XCHAL_SEP \ - XTHAL_LAM_EXCEPTION -#define XCHAL_SCA_LIST XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_WRITETHRU XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_WRITEBACK XCHAL_SEP \ - XTHAL_SAM_WRITEBACK_NOALLOC XCHAL_SEP \ - XTHAL_SAM_BYPASS XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_EXCEPTION XCHAL_SEP \ - XTHAL_SAM_ISOLATE XCHAL_SEP \ - XTHAL_SAM_EXCEPTION - -#define XCHAL_CA_R (0xC0 | 0x40000000) -#define XCHAL_CA_RX (0xD0 | 0x40000000) -#define XCHAL_CA_RW (0xE0 | 0x40000000) -#define XCHAL_CA_RWX (0xF0 | 0x40000000) - -/* - * Specific encoded cache attribute values of general interest. - * If a specific cache mode is not available, the closest available - * one is returned instead (eg. writethru instead of writeback, - * bypass instead of writethru). - */ -#define XCHAL_CA_BYPASS 2 /* cache disabled (bypassed) mode */ -#define XCHAL_CA_BYPASSBUF 6 /* cache disabled (bypassed) bufferable mode */ -#define XCHAL_CA_WRITETHRU 1 /* cache enabled (write-through) mode */ -#define XCHAL_CA_WRITEBACK 4 /* cache enabled (write-back) mode */ -#define XCHAL_HAVE_CA_WRITEBACK_NOALLOC 1 /* write-back no-allocate availability */ -#define XCHAL_CA_WRITEBACK_NOALLOC 5 /* cache enabled (write-back no-allocate) mode */ -#define XCHAL_CA_ILLEGAL 15 /* no access allowed (all cause exceptions) mode */ -#define XCHAL_CA_ISOLATE 14 /* cache isolate (accesses go to cache not memory) mode */ - -/*---------------------------------------------------------------------- - MMU - ----------------------------------------------------------------------*/ - -/* - * General notes on MMU parameters. - * - * Terminology: - * ASID = address-space ID (acts as an "extension" of virtual addresses) - * VPN = virtual page number - * PPN = physical page number - * CA = encoded cache attribute (access modes) - * TLB = translation look-aside buffer (term is stretched somewhat here) - * I = instruction (fetch accesses) - * D = data (load and store accesses) - * way = each TLB (ITLB and DTLB) consists of a number of "ways" - * that simultaneously match the virtual address of an access; - * a TLB successfully translates a virtual address if exactly - * one way matches the vaddr; if none match, it is a miss; - * if multiple match, one gets a "multihit" exception; - * each way can be independently configured in terms of number of - * entries, page sizes, which fields are writable or constant, etc. - * set = group of contiguous ways with exactly identical parameters - * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE - * from the page table and storing it in one of the auto-refill ways; - * if this PTE load also misses, a miss exception is posted for s/w. - * min-wired = a "min-wired" way can be used to map a single (minimum-sized) - * page arbitrarily under program control; it has a single entry, - * is non-auto-refill (some other way(s) must be auto-refill), - * all its fields (VPN, PPN, ASID, CA) are all writable, and it - * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current - * restriction is that this be the only page size it supports). - * - * TLB way entries are virtually indexed. - * TLB ways that support multiple page sizes: - * - must have all writable VPN and PPN fields; - * - can only use one page size at any given time (eg. setup at startup), - * selected by the respective ITLBCFG or DTLBCFG special register, - * whose bits n*4+3 .. n*4 index the list of page sizes for way n - * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n); - * this list may be sparse for auto-refill ways because auto-refill - * ways have independent lists of supported page sizes sharing a - * common encoding with PTE entries; the encoding is the index into - * this list; unsupported sizes for a given way are zero in the list; - * selecting unsupported sizes results in undefine hardware behaviour; - * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition). - */ - -#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */ -#define XCHAL_MMU_ASID_KERNEL 0 /* ASID value indicating kernel (ring 0) address space */ -#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */ -#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */ -#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 29 /* max page size in a PTE structure (log2) */ -#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 29 /* min page size in a PTE structure (log2) */ - - -/*** Instruction TLB: ***/ - -#define XCHAL_ITLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_ITLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_ITLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_ITLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_ITLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_ITLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* ITLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_ITLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_ITLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_ITLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_ITLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_ITLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of ITLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of ITLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_ITLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_ITLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_ITLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_ITLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_ITLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_ITLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_ITLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_ITLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of ITLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_ITLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_ITLB_SET0_E7_CA_RESET 0x02 - - -/*** Data TLB: ***/ - -#define XCHAL_DTLB_WAY_BITS 0 /* number of bits holding the ways */ -#define XCHAL_DTLB_WAYS 1 /* number of ways (n-way set-associative TLB) */ -#define XCHAL_DTLB_ARF_WAYS 0 /* number of auto-refill ways */ -#define XCHAL_DTLB_SETS 1 /* number of sets (groups of ways with identical settings) */ - -/* Way set to which each way belongs: */ -#define XCHAL_DTLB_WAY0_SET 0 - -/* Ways sets that are used by hardware auto-refill (ARF): */ -#define XCHAL_DTLB_ARF_SETS 0 /* number of auto-refill sets */ - -/* Way sets that are "min-wired" (see terminology comment above): */ -#define XCHAL_DTLB_MINWIRED_SETS 0 /* number of "min-wired" sets */ - - -/* DTLB way set 0 (group of ways 0 thru 0): */ -#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */ -#define XCHAL_DTLB_SET0_WAYS 1 /* number of (contiguous) ways in this way set */ -#define XCHAL_DTLB_SET0_ENTRIES_LOG2 3 /* log2(number of entries in this way) */ -#define XCHAL_DTLB_SET0_ENTRIES 8 /* number of entries in this way (always a power of 2) */ -#define XCHAL_DTLB_SET0_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */ -#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */ -#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 29 /* log2(minimum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 29 /* log2(maximum supported page size) */ -#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 29 /* list of log2(page size)s, separated by XCHAL_SEP; - 2^PAGESZ_BITS entries in list, unsupported entries are zero */ -#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0x00000000 /* constant VPN bits, not including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0xE0000000 /* constant PPN bits, including entry index bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */ -#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */ -#define XCHAL_DTLB_SET0_CA_RESET 1 /* 1 if CA reset values defined (and all writable); 0 otherwise */ -/* Constant VPN values for each entry of DTLB way set 0 (because VPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_VPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_VPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_VPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_VPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_VPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_VPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_VPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_VPN_CONST 0xE0000000 -/* Constant PPN values for each entry of DTLB way set 0 (because PPN_CONSTMASK is non-zero): */ -#define XCHAL_DTLB_SET0_E0_PPN_CONST 0x00000000 -#define XCHAL_DTLB_SET0_E1_PPN_CONST 0x20000000 -#define XCHAL_DTLB_SET0_E2_PPN_CONST 0x40000000 -#define XCHAL_DTLB_SET0_E3_PPN_CONST 0x60000000 -#define XCHAL_DTLB_SET0_E4_PPN_CONST 0x80000000 -#define XCHAL_DTLB_SET0_E5_PPN_CONST 0xA0000000 -#define XCHAL_DTLB_SET0_E6_PPN_CONST 0xC0000000 -#define XCHAL_DTLB_SET0_E7_PPN_CONST 0xE0000000 -/* Reset CA values for each entry of DTLB way set 0 (because SET0_CA_RESET is non-zero): */ -#define XCHAL_DTLB_SET0_E0_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E1_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E2_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E3_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E4_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E5_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E6_CA_RESET 0x02 -#define XCHAL_DTLB_SET0_E7_CA_RESET 0x02 - - - - -#endif /*XTENSA_CONFIG_CORE_MATMAP_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/arch/xtensa/config/defs.h b/src/platform/tigerlake/include/arch/xtensa/config/defs.h deleted file mode 100644 index d93272ae05a3..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/defs.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Definitions for Xtensa instructions, types, and protos. */ - -/* Copyright (c) 2003-2004 Tensilica 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. */ - -/* NOTE: This file exists only for backward compatibility with T1050 - and earlier Xtensa releases. It includes only a subset of the - available header files. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_BASE_HEADER -#define _XTENSA_BASE_HEADER - -#ifdef __XTENSA__ - -#include <xtensa/tie/xt_core.h> -#include <xtensa/tie/xt_misc.h> -#include <xtensa/tie/xt_booleans.h> - -#endif /* __XTENSA__ */ -#endif /* !_XTENSA_BASE_HEADER */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/arch/xtensa/config/specreg.h b/src/platform/tigerlake/include/arch/xtensa/config/specreg.h deleted file mode 100644 index 9d1d2ea95dad..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/specreg.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Xtensa Special Register symbolic names - */ - -/* $Id: //depot/rel/Foxhill/dot.8/Xtensa/SWConfig/hal/specreg.h.tpp#1 $ */ - -/* Copyright (c) 1998-2002 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_SPECREG_H -#define XTENSA_SPECREG_H - -/* Include these special register bitfield definitions, for historical reasons: */ -#include <xtensa/corebits.h> - - -/* Special registers: */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define PREFCTL 40 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define IBREAKENABLE 96 -#define MEMCTL 97 -#define ATOMCTL 99 -#define DDR 104 -#define MEPC 106 -#define MEPS 107 -#define MESAVE 108 -#define MESR 109 -#define MECR 110 -#define MEVADDR 111 -#define IBREAKA_0 128 -#define IBREAKA_1 129 -#define DBREAKA_0 144 -#define DBREAKA_1 145 -#define DBREAKC_0 160 -#define DBREAKC_1 161 -#define EPC_1 177 -#define EPC_2 178 -#define EPC_3 179 -#define EPC_4 180 -#define EPC_5 181 -#define EPC_6 182 -#define EPC_7 183 -#define DEPC 192 -#define EPS_2 194 -#define EPS_3 195 -#define EPS_4 196 -#define EPS_5 197 -#define EPS_6 198 -#define EPS_7 199 -#define EXCSAVE_1 209 -#define EXCSAVE_2 210 -#define EXCSAVE_3 211 -#define EXCSAVE_4 212 -#define EXCSAVE_5 213 -#define EXCSAVE_6 214 -#define EXCSAVE_7 215 -#define CPENABLE 224 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define VECBASE 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE_0 240 -#define CCOMPARE_1 241 -#define CCOMPARE_2 242 - -/* Special cases (bases of special register series): */ -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPS 192 -#define EXCSAVE 208 -#define CCOMPARE 240 - -/* Special names for read-only and write-only interrupt registers: */ -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 - -#endif /* XTENSA_SPECREG_H */ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/arch/xtensa/config/system.h b/src/platform/tigerlake/include/arch/xtensa/config/system.h deleted file mode 100644 index 0e434954c920..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/system.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration - * - * NOTE: The location and contents of this file are highly subject to change. - * - * Source for configuration-independent binaries (which link in a - * configuration-specific HAL library) must NEVER include this file. - * The HAL itself has historically included this file in some instances, - * but this is not appropriate either, because the HAL is meant to be - * core-specific but system independent. - */ - -/* Copyright (c) 2000-2010 Tensilica 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. */ - -#if !defined __XCC__ - -#ifndef XTENSA_CONFIG_SYSTEM_H -#define XTENSA_CONFIG_SYSTEM_H - -/*#include <xtensa/hal.h>*/ - - - -/*---------------------------------------------------------------------- - CONFIGURED SOFTWARE OPTIONS - ----------------------------------------------------------------------*/ - -#define XSHAL_USE_ABSOLUTE_LITERALS 0 /* (sw-only option, whether software uses absolute literals) */ -#define XSHAL_HAVE_TEXT_SECTION_LITERALS 1 /* Set if there is some memory that allows both code and literals. */ - -#define XSHAL_ABI XTHAL_ABI_WINDOWED /* (sw-only option, selected ABI) */ -/* The above maps to one of the following constants: */ -#define XTHAL_ABI_WINDOWED 0 -#define XTHAL_ABI_CALL0 1 -/* Alternatives: */ -/*#define XSHAL_WINDOWED_ABI 1*/ /* set if windowed ABI selected */ -/*#define XSHAL_CALL0_ABI 0*/ /* set if call0 ABI selected */ - -#define XSHAL_CLIB XTHAL_CLIB_NEWLIB /* (sw-only option, selected C library) */ -/* The above maps to one of the following constants: */ -#define XTHAL_CLIB_NEWLIB 0 -#define XTHAL_CLIB_UCLIBC 1 -#define XTHAL_CLIB_XCLIB 2 -/* Alternatives: */ -/*#define XSHAL_NEWLIB 1*/ /* set if newlib C library selected */ -/*#define XSHAL_UCLIBC 0*/ /* set if uCLibC C library selected */ -/*#define XSHAL_XCLIB 0*/ /* set if Xtensa C library selected */ - -#define XSHAL_USE_FLOATING_POINT 1 - -#define XSHAL_FLOATING_POINT_ABI 0 - -/* SW workarounds enabled for HW errata: */ - -/* SW options for functional safety: */ -#define XSHAL_FUNC_SAFETY_ENABLED 0 - -/*---------------------------------------------------------------------- - DEVICE ADDRESSES - ----------------------------------------------------------------------*/ - -/* - * Strange place to find these, but the configuration GUI - * allows moving these around to account for various core - * configurations. Specific boards (and their BSP software) - * will have specific meanings for these components. - */ - -/* I/O Block areas: */ -#define XSHAL_IOBLOCK_CACHED_VADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_PADDR 0x70000000 -#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000 - -#define XSHAL_IOBLOCK_BYPASS_VADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_PADDR 0x50000000 -#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000 - -/* System ROM: */ -#define XSHAL_ROM_VADDR 0xBEFE0000 -#define XSHAL_ROM_PADDR 0xBEFE0000 -#define XSHAL_ROM_SIZE 0x00020000 -/* Largest available area (free of vectors): */ -#define XSHAL_ROM_AVAIL_VADDR 0xBEFE0BC0 -#define XSHAL_ROM_AVAIL_VSIZE 0x0001F440 - -/* System RAM: */ -#define XSHAL_RAM_VADDR 0x80000000 -#define XSHAL_RAM_PADDR 0x80000000 -#define XSHAL_RAM_VSIZE 0x3EFE0000 -#define XSHAL_RAM_PSIZE 0x3EFE0000 -#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE -/* Largest available area (free of vectors): */ -#define XSHAL_RAM_AVAIL_VADDR 0x80000000 -#define XSHAL_RAM_AVAIL_VSIZE 0x3EFE0000 - -/* - * Shadow system RAM (same device as system RAM, at different address). - * (Emulation boards need this for the SONIC Ethernet driver - * when data caches are configured for writeback mode.) - * NOTE: on full MMU configs, this points to the BYPASS virtual address - * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual - * addresses are viewed through the BYPASS static map rather than - * the CACHED static map. - */ -#define XSHAL_RAM_BYPASS_VADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PADDR 0x20000000 -#define XSHAL_RAM_BYPASS_PSIZE 0x20000000 - -/* Alternate system RAM (different device than system RAM): */ -/*#define XSHAL_ALTRAM_[VP]ADDR ...not configured...*/ -/*#define XSHAL_ALTRAM_SIZE ...not configured...*/ - -/* Some available location in which to place devices in a simulation (eg. XTMP): */ -#define XSHAL_SIMIO_CACHED_VADDR 0xC0000000 -#define XSHAL_SIMIO_BYPASS_VADDR 0xC0000000 -#define XSHAL_SIMIO_PADDR 0xC0000000 -#define XSHAL_SIMIO_SIZE 0x20000000 - - -/*---------------------------------------------------------------------- - * For use by reference testbench exit and diagnostic routines. - */ -#define XSHAL_MAGIC_EXIT 0xe0000000 - -/*---------------------------------------------------------------------- - * DEVICE-ADDRESS DEPENDENT... - * - * Values written to CACHEATTR special register (or its equivalent) - * to enable and disable caches in various modes. - *----------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------- - BACKWARD COMPATIBILITY ... - ----------------------------------------------------------------------*/ - -/* - * NOTE: the following two macros are DEPRECATED. Use the latter - * board-specific macros instead, which are specially tuned for the - * particular target environments' memory maps. - */ -#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */ -#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */ - -/*---------------------------------------------------------------------- - GENERIC - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains a system (PIF) RAM, - * system (PIF) ROM, local memory, or XLMI. */ - -/* These set any unused 512MB region to cache-BYPASS attribute: */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x22442222 /* enable caches in write-back mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITEALLOC 0x22112222 /* enable caches in write-allocate mode */ -#define XSHAL_ALLVALID_CACHEATTR_WRITETHRU 0x22112222 /* enable caches in write-through mode */ -#define XSHAL_ALLVALID_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */ -#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set any unused 512MB region to ILLEGAL attribute: */ -#define XSHAL_STRICT_CACHEATTR_WRITEBACK 0xFF44FFFF /* enable caches in write-back mode */ -#define XSHAL_STRICT_CACHEATTR_WRITEALLOC 0xFF11FFFF /* enable caches in write-allocate mode */ -#define XSHAL_STRICT_CACHEATTR_WRITETHRU 0xFF11FFFF /* enable caches in write-through mode */ -#define XSHAL_STRICT_CACHEATTR_BYPASS 0xFF22FFFF /* disable caches in bypass mode */ -#define XSHAL_STRICT_CACHEATTR_DEFAULT XSHAL_STRICT_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/* These set the first 512MB, if unused, to ILLEGAL attribute to help catch - * NULL-pointer dereference bugs; all other unused 512MB regions are set - * to cache-BYPASS attribute: */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEBACK 0x2244222F /* enable caches in write-back mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC 0x2211222F /* enable caches in write-allocate mode */ -#define XSHAL_TRAPNULL_CACHEATTR_WRITETHRU 0x2211222F /* enable caches in write-through mode */ -#define XSHAL_TRAPNULL_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */ -#define XSHAL_TRAPNULL_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -/*---------------------------------------------------------------------- - ISS (Instruction Set Simulator) SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For now, ISS defaults to the TRAPNULL settings: */ -#define XSHAL_ISS_CACHEATTR_WRITEBACK XSHAL_TRAPNULL_CACHEATTR_WRITEBACK -#define XSHAL_ISS_CACHEATTR_WRITEALLOC XSHAL_TRAPNULL_CACHEATTR_WRITEALLOC -#define XSHAL_ISS_CACHEATTR_WRITETHRU XSHAL_TRAPNULL_CACHEATTR_WRITETHRU -#define XSHAL_ISS_CACHEATTR_BYPASS XSHAL_TRAPNULL_CACHEATTR_BYPASS -#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_TRAPNULL_CACHEATTR_WRITEBACK - -#define XSHAL_ISS_PIPE_REGIONS 0 -#define XSHAL_ISS_SDRAM_REGIONS 0 - - -/*---------------------------------------------------------------------- - XT2000 BOARD SPECIFIC ... - ----------------------------------------------------------------------*/ - -/* For the following, a 512MB region is used if it contains any system RAM, - * system ROM, local memory, XLMI, or other XT2000 board device or memory. - * Regions containing devices are forced to cache-BYPASS mode regardless - * of whether the macro is _WRITEBACK vs. _BYPASS etc. */ - -/* These set any 512MB region unused on the XT2000 to ILLEGAL attribute: */ -#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0xFF44422F /* enable caches in write-back mode */ -#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0xFF11122F /* enable caches in write-allocate mode */ -#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0xFF11122F /* enable caches in write-through mode */ -#define XSHAL_XT2000_CACHEATTR_BYPASS 0xFF22222F /* disable caches in bypass mode */ -#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */ - -#define XSHAL_XT2000_PIPE_REGIONS 0x00000000 /* BusInt pipeline regions */ -#define XSHAL_XT2000_SDRAM_REGIONS 0x00000104 /* BusInt SDRAM regions */ - - -/*---------------------------------------------------------------------- - VECTOR INFO AND SIZES - ----------------------------------------------------------------------*/ - -#define XSHAL_VECTORS_PACKED 0 -#define XSHAL_STATIC_VECTOR_SELECT 0 -#define XSHAL_RESET_VECTOR_VADDR 0xBEFE0000 -#define XSHAL_RESET_VECTOR_PADDR 0xBEFE0000 -#define XSHAL_MEMERROR_VECTOR_VADDR 0xBEFE0400 -#define XSHAL_MEMERROR_VECTOR_PADDR 0xBEFE0400 - -/* - * Sizes allocated to vectors by the system (memory map) configuration. - * These sizes are constrained by core configuration (eg. one vector's - * code cannot overflow into another vector) but are dependent on the - * system or board (or LSP) memory map configuration. - * - * Whether or not each vector happens to be in a system ROM is also - * a system configuration matter, sometimes useful, included here also: - */ -#define XSHAL_RESET_VECTOR_SIZE 0x00000300 -#define XSHAL_RESET_VECTOR_ISROM 1 -#define XSHAL_USER_VECTOR_SIZE 0x00000038 -#define XSHAL_USER_VECTOR_ISROM 1 -#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNEL_VECTOR_SIZE 0x00000038 -#define XSHAL_KERNEL_VECTOR_ISROM 1 -#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */ -#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x00000040 -#define XSHAL_DOUBLEEXC_VECTOR_ISROM 1 -#define XSHAL_WINDOW_VECTORS_SIZE 0x00000178 -#define XSHAL_WINDOW_VECTORS_ISROM 1 -#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL2_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL3_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL4_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL5_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL5_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL6_VECTOR_SIZE 0x00000038 -#define XSHAL_INTLEVEL6_VECTOR_ISROM 1 -#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL6_VECTOR_SIZE -#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL6_VECTOR_ISROM -#define XSHAL_NMI_VECTOR_SIZE 0x00000038 -#define XSHAL_NMI_VECTOR_ISROM 1 -#define XSHAL_INTLEVEL7_VECTOR_SIZE XSHAL_NMI_VECTOR_SIZE - - -#endif /*XTENSA_CONFIG_SYSTEM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/arch/xtensa/config/tie-asm.h b/src/platform/tigerlake/include/arch/xtensa/config/tie-asm.h deleted file mode 100644 index f6210e126331..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/tie-asm.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file contains assembly-language definitions (assembly - macros, etc.) for this specific Xtensa processor's TIE extensions - and options. It is customized to this Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_ASM_H -#define _XTENSA_CORE_TIE_ASM_H - -/* Selection parameter values for save-area save/restore macros: */ -/* Option vs. TIE: */ -#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ -#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ -#define XTHAL_SAS_ANYOT 0x0003 /* both of the above */ -/* Whether used automatically by compiler: */ -#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ -#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ -#define XTHAL_SAS_ANYCC 0x000C /* both of the above */ -/* ABI handling across function calls: */ -#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ -#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ -#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ -#define XTHAL_SAS_ANYABI 0x0070 /* all of the above three */ -/* Misc */ -#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ -#define XTHAL_SAS3(optie,ccuse,abi) ( ((optie) & XTHAL_SAS_ANYOT) \ - | ((ccuse) & XTHAL_SAS_ANYCC) \ - | ((abi) & XTHAL_SAS_ANYABI) ) - - - /* - * Macro to store all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger store sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to store. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to store, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any store. - */ - .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - rur.THREADPTR \at1 // threadptr option - s32i \at1, \ptr, .Lxchal_ofs_+0 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - rsr.BR \at1 // boolean option - s32i \at1, \ptr, .Lxchal_ofs_+0 - rsr.SCOMPARE1 \at1 // conditional store option - s32i \at1, \ptr, .Lxchal_ofs_+4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_store - - /* - * Macro to load all non-coprocessor (extra) custom TIE and optional state - * (not including zero-overhead loop registers). - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_NCP_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters: - * continue If macro invoked as part of a larger load sequence, set to 1 - * if this is not the first in the sequence. Defaults to 0. - * ofs Offset from start of larger sequence (from value of first ptr - * in sequence) at which to load. Defaults to next available space - * (or 0 if <continue> is 0). - * select Select what category(ies) of registers to load, as a bitmask - * (see XTHAL_SAS_xxx constants). Defaults to all registers. - * alloc Select what category(ies) of registers to allocate; if any - * category is selected here that is not in <select>, space for - * the corresponding registers is skipped without doing any load. - */ - .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Optional global registers used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select) - xchal_sa_align \ptr, 0, 1016, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.THREADPTR \at1 // threadptr option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1016, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 - .endif - // Optional caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 1012, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wsr.BR \at1 // boolean option - l32i \at1, \ptr, .Lxchal_ofs_+4 - wsr.SCOMPARE1 \at1 // conditional store option - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 1012, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 8 - .endif - .endm // xchal_ncp_load - - -#define XCHAL_NCP_NUM_ATMPS 1 - - /* - * Macro to store the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_FPU_store xchal_cp0_store - .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - rur.FCR \at1 // ureg 232 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.FSR \at1 // ureg 233 - s32i \at1, \ptr, .Lxchal_ofs_+4 - ssi f0, \ptr, .Lxchal_ofs_+8 - ssi f1, \ptr, .Lxchal_ofs_+12 - ssi f2, \ptr, .Lxchal_ofs_+16 - ssi f3, \ptr, .Lxchal_ofs_+20 - ssi f4, \ptr, .Lxchal_ofs_+24 - ssi f5, \ptr, .Lxchal_ofs_+28 - ssi f6, \ptr, .Lxchal_ofs_+32 - ssi f7, \ptr, .Lxchal_ofs_+36 - ssi f8, \ptr, .Lxchal_ofs_+40 - ssi f9, \ptr, .Lxchal_ofs_+44 - ssi f10, \ptr, .Lxchal_ofs_+48 - ssi f11, \ptr, .Lxchal_ofs_+52 - ssi f12, \ptr, .Lxchal_ofs_+56 - ssi f13, \ptr, .Lxchal_ofs_+60 - ssi f14, \ptr, .Lxchal_ofs_+64 - ssi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_store - - /* - * Macro to load the state of TIE coprocessor FPU. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 4 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP0_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_FPU_load xchal_cp0_load - .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 948, 4, 4 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.FCR \at1 // ureg 232 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.FSR \at1 // ureg 233 - lsi f0, \ptr, .Lxchal_ofs_+8 - lsi f1, \ptr, .Lxchal_ofs_+12 - lsi f2, \ptr, .Lxchal_ofs_+16 - lsi f3, \ptr, .Lxchal_ofs_+20 - lsi f4, \ptr, .Lxchal_ofs_+24 - lsi f5, \ptr, .Lxchal_ofs_+28 - lsi f6, \ptr, .Lxchal_ofs_+32 - lsi f7, \ptr, .Lxchal_ofs_+36 - lsi f8, \ptr, .Lxchal_ofs_+40 - lsi f9, \ptr, .Lxchal_ofs_+44 - lsi f10, \ptr, .Lxchal_ofs_+48 - lsi f11, \ptr, .Lxchal_ofs_+52 - lsi f12, \ptr, .Lxchal_ofs_+56 - lsi f13, \ptr, .Lxchal_ofs_+60 - lsi f14, \ptr, .Lxchal_ofs_+64 - lsi f15, \ptr, .Lxchal_ofs_+68 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 948, 4, 4 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 - .endif - .endm // xchal_cp0_load - -#define XCHAL_CP0_NUM_ATMPS 1 - /* - * Macro to store the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_store. - */ -#define xchal_cp_AudioEngineLX_store xchal_cp1_store - .macro xchal_cp1_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - rur.AE_OVF_SAR \at1 // ureg 240 - s32i \at1, \ptr, .Lxchal_ofs_+0 - rur.AE_BITHEAD \at1 // ureg 241 - s32i \at1, \ptr, .Lxchal_ofs_+4 - rur.AE_TS_FTS_BU_BP \at1 // ureg 242 - s32i \at1, \ptr, .Lxchal_ofs_+8 - rur.AE_CW_SD_NO \at1 // ureg 243 - s32i \at1, \ptr, .Lxchal_ofs_+12 - rur.AE_CBEGIN0 \at1 // ureg 246 - s32i \at1, \ptr, .Lxchal_ofs_+16 - rur.AE_CEND0 \at1 // ureg 247 - s32i \at1, \ptr, .Lxchal_ofs_+20 - ae_s64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_s64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_s64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_s64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_s64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_s64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_s64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_s64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_s64.i aed15, \ptr, .Lxchal_ofs_+16 - ae_salign64.i u0, \ptr, .Lxchal_ofs_+24 - ae_salign64.i u1, \ptr, .Lxchal_ofs_+32 - ae_salign64.i u2, \ptr, .Lxchal_ofs_+40 - ae_salign64.i u3, \ptr, .Lxchal_ofs_+48 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 128 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 56 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_store - - /* - * Macro to load the state of TIE coprocessor AudioEngineLX. - * Required parameters: - * ptr Save area pointer address register (clobbered) - * (register must contain a 8 byte aligned address). - * at1..at4 Four temporary address registers (first XCHAL_CP1_NUM_ATMPS - * registers are clobbered, the remaining are unused). - * Optional parameters are the same as for xchal_ncp_load. - */ -#define xchal_cp_AudioEngineLX_load xchal_cp1_load - .macro xchal_cp1_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0 - xchal_sa_start \continue, \ofs - // Custom caller-saved registers not used by default by the compiler: - .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select) - xchal_sa_align \ptr, 0, 0, 8, 8 - l32i \at1, \ptr, .Lxchal_ofs_+0 - wur.AE_OVF_SAR \at1 // ureg 240 - l32i \at1, \ptr, .Lxchal_ofs_+4 - wur.AE_BITHEAD \at1 // ureg 241 - l32i \at1, \ptr, .Lxchal_ofs_+8 - wur.AE_TS_FTS_BU_BP \at1 // ureg 242 - l32i \at1, \ptr, .Lxchal_ofs_+12 - wur.AE_CW_SD_NO \at1 // ureg 243 - l32i \at1, \ptr, .Lxchal_ofs_+16 - wur.AE_CBEGIN0 \at1 // ureg 246 - l32i \at1, \ptr, .Lxchal_ofs_+20 - wur.AE_CEND0 \at1 // ureg 247 - ae_l64.i aed0, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed1, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed2, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed3, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed4, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed5, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed6, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed7, \ptr, .Lxchal_ofs_+16 - ae_l64.i aed8, \ptr, .Lxchal_ofs_+24 - ae_l64.i aed9, \ptr, .Lxchal_ofs_+32 - ae_l64.i aed10, \ptr, .Lxchal_ofs_+40 - ae_l64.i aed11, \ptr, .Lxchal_ofs_+48 - ae_l64.i aed12, \ptr, .Lxchal_ofs_+56 - addi \ptr, \ptr, 64 - ae_l64.i aed13, \ptr, .Lxchal_ofs_+0 - ae_l64.i aed14, \ptr, .Lxchal_ofs_+8 - ae_l64.i aed15, \ptr, .Lxchal_ofs_+16 - addi \ptr, \ptr, 24 - ae_lalign64.i u0, \ptr, .Lxchal_ofs_+0 - ae_lalign64.i u1, \ptr, .Lxchal_ofs_+8 - ae_lalign64.i u2, \ptr, .Lxchal_ofs_+16 - ae_lalign64.i u3, \ptr, .Lxchal_ofs_+24 - .set .Lxchal_pofs_, .Lxchal_pofs_ + 152 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 32 - .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0 - xchal_sa_align \ptr, 0, 0, 8, 8 - .set .Lxchal_ofs_, .Lxchal_ofs_ + 184 - .endif - .endm // xchal_cp1_load - -#define XCHAL_CP1_NUM_ATMPS 1 -#define XCHAL_SA_NUM_ATMPS 1 - - /* Empty macros for unconfigured coprocessors: */ - .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp6_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm - .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm - -#endif /*_XTENSA_CORE_TIE_ASM_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/arch/xtensa/config/tie.h b/src/platform/tigerlake/include/arch/xtensa/config/tie.h deleted file mode 100644 index 6865fad953af..000000000000 --- a/src/platform/tigerlake/include/arch/xtensa/config/tie.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration - * - * NOTE: This header file is not meant to be included directly. - */ - -/* This header file describes this specific Xtensa processor's TIE extensions - that extend basic Xtensa core functionality. It is customized to this - Xtensa processor configuration. - - Copyright (c) 1999-2018 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. */ - -#if !defined __XCC__ - -#ifndef _XTENSA_CORE_TIE_H -#define _XTENSA_CORE_TIE_H - -#define XCHAL_CP_NUM 2 /* number of coprocessors */ -#define XCHAL_CP_MAX 2 /* max CP ID + 1 (0 if none) */ -#define XCHAL_CP_MASK 0x03 /* bitmask of all CPs by ID */ -#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ - -/* Basic parameters of each coprocessor: */ -#define XCHAL_CP0_NAME "FPU" -#define XCHAL_CP0_IDENT FPU -#define XCHAL_CP0_SA_SIZE 72 /* size of state save area */ -#define XCHAL_CP0_SA_ALIGN 4 /* min alignment of save area */ -#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ -#define XCHAL_CP1_NAME "AudioEngineLX" -#define XCHAL_CP1_IDENT AudioEngineLX -#define XCHAL_CP1_SA_SIZE 184 /* size of state save area */ -#define XCHAL_CP1_SA_ALIGN 8 /* min alignment of save area */ -#define XCHAL_CP_ID_AUDIOENGINELX 1 /* coprocessor ID (0..7) */ - -/* Filler info for unassigned coprocessors, to simplify arrays etc: */ -#define XCHAL_CP2_SA_SIZE 0 -#define XCHAL_CP2_SA_ALIGN 1 -#define XCHAL_CP3_SA_SIZE 0 -#define XCHAL_CP3_SA_ALIGN 1 -#define XCHAL_CP4_SA_SIZE 0 -#define XCHAL_CP4_SA_ALIGN 1 -#define XCHAL_CP5_SA_SIZE 0 -#define XCHAL_CP5_SA_ALIGN 1 -#define XCHAL_CP6_SA_SIZE 0 -#define XCHAL_CP6_SA_ALIGN 1 -#define XCHAL_CP7_SA_SIZE 0 -#define XCHAL_CP7_SA_ALIGN 1 - -/* Save area for non-coprocessor optional and custom (TIE) state: */ -#define XCHAL_NCP_SA_SIZE 12 -#define XCHAL_NCP_SA_ALIGN 4 - -/* Total save area for optional and custom state (NCP + CPn): */ -#define XCHAL_TOTAL_SA_SIZE 272 /* with 16-byte align padding */ -#define XCHAL_TOTAL_SA_ALIGN 8 /* actual minimum alignment */ - -/* - * Detailed contents of save areas. - * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) - * before expanding the XCHAL_xxx_SA_LIST() macros. - * - * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, - * dbnum,base,regnum,bitsz,gapsz,reset,x...) - * - * s = passed from XCHAL_*_LIST(s), eg. to select how to expand - * ccused = set if used by compiler without special options or code - * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) - * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) - * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) - * name = lowercase reg name (no quotes) - * galign = group byte alignment (power of 2) (galign >= align) - * align = register byte alignment (power of 2) - * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) - * (not including any pad bytes required to galign this or next reg) - * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) - * base = reg shortname w/o index (or sr=special, ur=TIE user reg) - * regnum = reg index in regfile, or special/TIE-user reg number - * bitsz = number of significant bits (regfile width, or ur/sr mask bits) - * gapsz = intervening bits, if bitsz bits not stored contiguously - * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) - * reset = register reset value (or 0 if undefined at reset) - * x = reserved for future use (0 until then) - * - * To filter out certain registers, e.g. to expand only the non-global - * registers used by the compiler, you can do something like this: - * - * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) - * #define SELCC0(p...) - * #define SELCC1(abikind,p...) SELAK##abikind(p) - * #define SELAK0(p...) REG(p) - * #define SELAK1(p...) REG(p) - * #define SELAK2(p...) - * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ - * ...what you want to expand... - */ - -#define XCHAL_NCP_SA_NUM 3 -#define XCHAL_NCP_SA_LIST(s) \ - XCHAL_SA_REG(s,1,2,1,1, threadptr, 4, 4, 4,0x03E7, ur,231, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,0,1, scompare1, 4, 4, 4,0x020C, sr,12 , 32,0,0,0) - -#define XCHAL_CP0_SA_NUM 18 -#define XCHAL_CP0_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, fcr, 4, 4, 4,0x03E8, ur,232, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f0, 4, 4, 4,0x0030, f,0 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f1, 4, 4, 4,0x0031, f,1 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f2, 4, 4, 4,0x0032, f,2 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f3, 4, 4, 4,0x0033, f,3 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f4, 4, 4, 4,0x0034, f,4 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f5, 4, 4, 4,0x0035, f,5 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f6, 4, 4, 4,0x0036, f,6 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f7, 4, 4, 4,0x0037, f,7 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f8, 4, 4, 4,0x0038, f,8 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f9, 4, 4, 4,0x0039, f,9 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f10, 4, 4, 4,0x003A, f,10 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f11, 4, 4, 4,0x003B, f,11 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f12, 4, 4, 4,0x003C, f,12 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f13, 4, 4, 4,0x003D, f,13 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f14, 4, 4, 4,0x003E, f,14 , 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, f15, 4, 4, 4,0x003F, f,15 , 32,0,0,0) - -#define XCHAL_CP1_SA_NUM 26 -#define XCHAL_CP1_SA_LIST(s) \ - XCHAL_SA_REG(s,0,0,1,0, ae_ovf_sar, 8, 4, 4,0x03F0, ur,240, 8,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_bithead, 4, 4, 4,0x03F1, ur,241, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2, ur,242, 16,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cw_sd_no, 4, 4, 4,0x03F3, ur,243, 29,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cbegin0, 4, 4, 4,0x03F6, ur,246, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,1,0, ae_cend0, 4, 4, 4,0x03F7, ur,247, 32,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed0, 8, 8, 8,0x1000, aed,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed1, 8, 8, 8,0x1001, aed,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed2, 8, 8, 8,0x1002, aed,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed3, 8, 8, 8,0x1003, aed,3 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed4, 8, 8, 8,0x1004, aed,4 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed5, 8, 8, 8,0x1005, aed,5 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed6, 8, 8, 8,0x1006, aed,6 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed7, 8, 8, 8,0x1007, aed,7 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed8, 8, 8, 8,0x1008, aed,8 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed9, 8, 8, 8,0x1009, aed,9 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed10, 8, 8, 8,0x100A, aed,10 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed11, 8, 8, 8,0x100B, aed,11 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed12, 8, 8, 8,0x100C, aed,12 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed13, 8, 8, 8,0x100D, aed,13 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed14, 8, 8, 8,0x100E, aed,14 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, aed15, 8, 8, 8,0x100F, aed,15 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u0, 8, 8, 8,0x1010, u,0 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u1, 8, 8, 8,0x1011, u,1 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u2, 8, 8, 8,0x1012, u,2 , 64,0,0,0) \ - XCHAL_SA_REG(s,0,0,2,0, u3, 8, 8, 8,0x1013, u,3 , 64,0,0,0) - -#define XCHAL_CP2_SA_NUM 0 -#define XCHAL_CP2_SA_LIST(s) /* empty */ - -#define XCHAL_CP3_SA_NUM 0 -#define XCHAL_CP3_SA_LIST(s) /* empty */ - -#define XCHAL_CP4_SA_NUM 0 -#define XCHAL_CP4_SA_LIST(s) /* empty */ - -#define XCHAL_CP5_SA_NUM 0 -#define XCHAL_CP5_SA_LIST(s) /* empty */ - -#define XCHAL_CP6_SA_NUM 0 -#define XCHAL_CP6_SA_LIST(s) /* empty */ - -#define XCHAL_CP7_SA_NUM 0 -#define XCHAL_CP7_SA_LIST(s) /* empty */ - -/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ -#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 -/* Byte length of instruction from its first byte, per FLIX. */ -#define XCHAL_BYTE0_FORMAT_LENGTHS \ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8,\ - 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8, 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 - -#endif /*_XTENSA_CORE_TIE_H*/ - -#else - -#error "xcc should not use this header" - -#endif /* __XCC__ */ diff --git a/src/platform/tigerlake/include/platform/drivers/alh.h b/src/platform/tigerlake/include/platform/drivers/alh.h deleted file mode 100644 index 09af56519550..000000000000 --- a/src/platform/tigerlake/include/platform/drivers/alh.h +++ /dev/null @@ -1,95 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_ALH__ - -#ifndef __PLATFORM_DRIVERS_ALH__ -#define __PLATFORM_DRIVERS_ALH__ - -#include <stdint.h> - -/** - * \brief ALH Handshakes for audio I/O - * Stream ID -> DMA Handshake map - * -1 identifies invalid handshakes/streams - */ -static const uint8_t alh_handshake_map[64] = { - -1, /* 0 - INVALID */ - -1, /* 1 - INVALID */ - -1, /* 2 - INVALID */ - -1, /* 3 - INVALID */ - -1, /* 4 - INVALID */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - 22, /* 7 - BIDIRECTIONAL */ - 23, /* 8 - BIDIRECTIONAL */ - 24, /* 9 - BIDIRECTIONAL */ - 25, /* 10 - BIDIRECTIONAL */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - -1, /* 13 - INVALID */ - -1, /* 14 - INVALID */ - -1, /* 15 - INVALID */ - -1, /* 16 - INVALID */ - -1, /* 17 - INVALID */ - -1, /* 18 - INVALID */ - -1, /* 19 - INVALID */ - -1, /* 20 - INVALID */ - -1, /* 21 - INVALID */ - -1, /* 22 - INVALID */ - 32, /* 23 - BIDIRECTIONAL */ - 33, /* 24 - BIDIRECTIONAL */ - 34, /* 25 - BIDIRECTIONAL */ - 35, /* 26 - BIDIRECTIONAL */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - -1, /* 29 - INVALID */ - -1, /* 30 - INVALID */ - -1, /* 31 - INVALID */ - -1, /* 32 - INVALID */ - -1, /* 33 - INVALID */ - -1, /* 34 - INVALID */ - -1, /* 35 - INVALID */ - -1, /* 36 - INVALID */ - -1, /* 37 - INVALID */ - -1, /* 38 - INVALID */ - 42, /* 39 - BIDIRECTIONAL */ - 43, /* 40 - BIDIRECTIONAL */ - 44, /* 41 - BIDIRECTIONAL */ - 45, /* 42 - BIDIRECTIONAL */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - -1, /* 45 - INVALID */ - -1, /* 46 - INVALID */ - -1, /* 47 - INVALID */ - -1, /* 48 - INVALID */ - -1, /* 49 - INVALID */ - -1, /* 50 - INVALID */ - -1, /* 51 - INVALID */ - -1, /* 52 - INVALID */ - -1, /* 53 - INVALID */ - -1, /* 54 - INVALID */ - 52, /* 55 - BIDIRECTIONAL */ - 53, /* 56 - BIDIRECTIONAL */ - 54, /* 57 - BIDIRECTIONAL */ - 55, /* 58 - BIDIRECTIONAL */ - -1, /* 5 - INVALID */ - -1, /* 6 - INVALID */ - -1, /* 61 - INVALID */ - -1, /* 62 - INVALID */ - -1, /* 63 - INVALID */ -}; - -#define ALH_GPDMA_BURST_LENGTH 4 - -#endif /* __PLATFORM_DRIVERS_ALH__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/alh.h" - -#endif diff --git a/src/platform/tigerlake/include/platform/drivers/dw-dma.h b/src/platform/tigerlake/include/platform/drivers/dw-dma.h deleted file mode 100644 index 2fe0b26450d5..000000000000 --- a/src/platform/tigerlake/include/platform/drivers/dw-dma.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_DW_DMA_H__ - -#ifndef __PLATFORM_DRIVERS_DW_DMA_H__ -#define __PLATFORM_DRIVERS_DW_DMA_H__ - -#include <cavs/drivers/dw-dma.h> - -#endif /* __PLATFORM_DRIVERS_DW_DMA_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/dw-dma.h" - -#endif /* __SOF_DRIVERS_DW_DMA_H__ */ diff --git a/src/platform/tigerlake/include/platform/drivers/idc.h b/src/platform/tigerlake/include/platform/drivers/idc.h deleted file mode 100644 index b8565347f42e..000000000000 --- a/src/platform/tigerlake/include/platform/drivers/idc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_DRIVERS_IDC_H__ - -#ifndef __PLATFORM_DRIVERS_IDC_H__ -#define __PLATFORM_DRIVERS_IDC_H__ - -#include <cavs/drivers/idc.h> - -#endif /* __PLATFORM_DRIVERS_IDC_H__ */ - -#else - -#error "This file shouldn't be included from outside of sof/drivers/idc.h" - -#endif /* __SOF_DRIVERS_IDC_H__ */ diff --git a/src/platform/tigerlake/include/platform/drivers/interrupt.h b/src/platform/tigerlake/include/platform/drivers/interrupt.h deleted file mode 100644 index 057b13be1679..000000000000 --- a/src/platform/tigerlake/include/platform/drivers/interrupt.h +++ /dev/null @@ -1,154 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_DRIVERS_INTERRUPT_H__ - -#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ -#define __PLATFORM_DRIVERS_INTERRUPT_H__ - -#include <cavs/drivers/interrupt.h> -#include <sof/bit.h> -#include <config.h> - -#define PLATFORM_IRQ_HW_NUM XCHAL_NUM_INTERRUPTS -#define PLATFORM_IRQ_FIRST_CHILD PLATFORM_IRQ_HW_NUM -#define PLATFORM_IRQ_CHILDREN 32 - -/* IRQ numbers - wrt Tensilica DSP */ -#if CONFIG_INTERRUPT_LEVEL_1 - -#define IRQ_NUM_SOFTWARE0 0 /* level 1 */ -#define IRQ_NUM_TIMER1 1 /* level 1 */ -#define IRQ_NUM_EXT_LEVEL1 2 /* level 1 */ -#define IRQ_NUM_SOFTWARE1 3 /* level 1 */ - -#define IRQ_MASK_SOFTWARE0 BIT(IRQ_NUM_SOFTWARE0) -#define IRQ_MASK_TIMER1 BIT(IRQ_NUM_TIMER1) -#define IRQ_MASK_EXT_LEVEL1 BIT(IRQ_NUM_EXT_LEVEL1) -#define IRQ_MASK_SOFTWARE1 BIT(IRQ_NUM_SOFTWARE1) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_2 - -#define IRQ_NUM_SOFTWARE2 4 /* level 2 */ -#define IRQ_NUM_TIMER2 5 /* level 2 */ -#define IRQ_NUM_EXT_LEVEL2 6 /* level 2 */ -#define IRQ_NUM_SOFTWARE3 7 /* level 2 */ - -/* IRQ Level 2 bits */ -#define IRQ_BIT_LVL2_HP_GP_DMA0(x) (x + 24) -#define IRQ_BIT_LVL2_WALL_CLK1 23 -#define IRQ_BIT_LVL2_WALL_CLK0 22 -#define IRQ_BIT_LVL2_L2_MEMERR 21 -#define IRQ_BIT_LVL2_SHA256 16 -#define IRQ_BIT_LVL2_L2_CACHE 15 -#define IRQ_BIT_LVL2_IDC 8 -#define IRQ_BIT_LVL2_HOST_IPC 7 -#define IRQ_BIT_LVL2_CSME_IPC 6 -#define IRQ_BIT_LVL2_PMC_IPC 5 - -/* Priority 2 Peripheral IRQ mappings */ -#define IRQ_EXT_HP_GPDMA_LVL2 IRQ_BIT_LVL2_HP_GP_DMA0(0) -#define IRQ_EXT_IDC_LVL2 IRQ_BIT_LVL2_IDC -#define IRQ_EXT_IPC_LVL2 IRQ_BIT_LVL2_HOST_IPC -#define IRQ_EXT_TSTAMP1_LVL2 IRQ_BIT_LVL2_WALL_CLK1 -#define IRQ_EXT_TSTAMP0_LVL2 IRQ_BIT_LVL2_WALL_CLK0 -#define IRQ_EXT_MERR_LVL2 IRQ_BIT_LVL2_L2_MEMERR -#define IRQ_EXT_L2CACHE_LVL2 IRQ_BIT_LVL2_L2_CACHE -#define IRQ_EXT_SHA256_LVL2 IRQ_BIT_LVL2_SHA256 - -#define IRQ_MASK_SOFTWARE2 BIT(IRQ_NUM_SOFTWARE2) -#define IRQ_MASK_TIMER2 BIT(IRQ_NUM_TIMER2) -#define IRQ_MASK_EXT_LEVEL2 BIT(IRQ_NUM_EXT_LEVEL2) -#define IRQ_MASK_SOFTWARE3 BIT(IRQ_NUM_SOFTWARE3) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_3 - -#define IRQ_NUM_SOFTWARE4 8 /* level 3 */ -#define IRQ_NUM_TIMER3 9 /* level 3 */ -#define IRQ_NUM_EXT_LEVEL3 10 /* level 3 */ -#define IRQ_NUM_SOFTWARE5 11 /* level 3 */ - -/* IRQ Level 3 bits */ -#define IRQ_BIT_LVL3_CODE_LOADER 31 -#define IRQ_BIT_LVL3_HOST_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL3_HOST_STREAM_IN(x) (0 + x) - -/* Priority 3 Peripheral IRQ mappings */ -#define IRQ_EXT_CODE_DMA_LVL3 IRQ_BIT_LVL3_CODE_LOADER -#define IRQ_EXT_HOST_DMA_IN_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_IN(channel) -#define IRQ_EXT_HOST_DMA_OUT_LVL3(channel) IRQ_BIT_LVL3_HOST_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE4 BIT(IRQ_NUM_SOFTWARE4) -#define IRQ_MASK_TIMER3 BIT(IRQ_NUM_TIMER3) -#define IRQ_MASK_EXT_LEVEL3 BIT(IRQ_NUM_EXT_LEVEL3) -#define IRQ_MASK_SOFTWARE5 BIT(IRQ_NUM_SOFTWARE5) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_4 - -#define IRQ_NUM_SOFTWARE6 12 /* level 4 */ -#define IRQ_NUM_EXT_LEVEL4 13 /* level 4 */ -#define IRQ_NUM_SOFTWARE7 14 /* level 4 */ - -/* IRQ Level 4 bits */ -#define IRQ_BIT_LVL4_LINK_STREAM_OUT(x) (16 + x) -#define IRQ_BIT_LVL4_LINK_STREAM_IN(x) (0 + x) - -/* Priority 4 Peripheral IRQ mappings */ -#define IRQ_EXT_LINK_DMA_IN_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_IN(channel) -#define IRQ_EXT_LINK_DMA_OUT_LVL4(channel) IRQ_BIT_LVL4_LINK_STREAM_OUT(channel) - -#define IRQ_MASK_SOFTWARE6 BIT(IRQ_NUM_SOFTWARE6) -#define IRQ_MASK_EXT_LEVEL4 BIT(IRQ_NUM_EXT_LEVEL4) -#define IRQ_MASK_SOFTWARE7 BIT(IRQ_NUM_SOFTWARE7) - -#endif - -#if CONFIG_INTERRUPT_LEVEL_5 - -#define IRQ_NUM_SOFTWARE8 15 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL5 16 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL6 17 /* level 5 */ -#define IRQ_NUM_EXT_LEVEL7 18 /* level 5 */ -#define IRQ_NUM_SOFTWARE9 19 /* level 5 */ - -/* IRQ Level 5 bits */ -#define IRQ_BIT_LVL5_LP_GP_DMA1 15 -#define IRQ_BIT_LVL5_LP_GP_DMA0 16 -#define IRQ_BIT_LVL5_DMIC(x) 8 -#define IRQ_BIT_LVL5_SSP(x) (0 + x) - -/* Priority 5 Peripheral IRQ mappings */ -#define IRQ_EXT_LP_GPDMA0_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_LP_GPDMA1_LVL5(channel) IRQ_BIT_LVL5_LP_GP_DMA0 -#define IRQ_EXT_SSPx_LVL5(x) IRQ_BIT_LVL5_SSP(x) -#define IRQ_EXT_DMIC_LVL5(x) IRQ_BIT_LVL5_DMIC(x) - -#define IRQ_MASK_SOFTWARE8 BIT(IRQ_NUM_SOFTWARE8) -#define IRQ_MASK_EXT_LEVEL5 BIT(IRQ_NUM_EXT_LEVEL5) -#define IRQ_MASK_EXT_LEVEL6 BIT(IRQ_NUM_EXT_LEVEL6) -#define IRQ_MASK_EXT_LEVEL7 BIT(IRQ_NUM_EXT_LEVEL7) -#define IRQ_MASK_SOFTWARE9 BIT(IRQ_NUM_SOFTWARE9) - -#endif - -#define IRQ_NUM_NMI 20 /* level 7 */ - -#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/tigerlake/include/platform/lib/clk.h b/src/platform/tigerlake/include/platform/lib/clk.h deleted file mode 100644 index dc13be94b6c1..000000000000 --- a/src/platform/tigerlake/include/platform/lib/clk.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_CLK_H__ - -#ifndef __PLATFORM_LIB_CLK_H__ -#define __PLATFORM_LIB_CLK_H__ - -#include <cavs/lib/clk.h> - -#define CLK_MAX_CPU_HZ 400000000 - -#define CPU_LPRO_FREQ_IDX 0 - -#define CPU_HPRO_FREQ_IDX 1 - -#define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX - -#define SSP_DEFAULT_IDX 1 - -#define NUM_CPU_FREQ 2 - -#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/tigerlake/include/platform/lib/cpu.h b/src/platform/tigerlake/include/platform/lib/cpu.h deleted file mode 100644 index 78a6e78bc889..000000000000 --- a/src/platform/tigerlake/include/platform/lib/cpu.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/lib/cpu.h - * \brief DSP core parameters. - */ - -#ifdef __SOF_LIB_CPU_H__ - -#ifndef __PLATFORM_LIB_CPU_H__ -#define __PLATFORM_LIB_CPU_H__ - -#include <cavs/lib/cpu.h> - -/** \brief Maximum allowed number of DSP cores */ -#define MAX_CORE_COUNT 4 - -#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/tigerlake/include/platform/lib/dai.h b/src/platform/tigerlake/include/platform/lib/dai.h deleted file mode 100644 index 048c9d56164f..000000000000 --- a/src/platform/tigerlake/include/platform/lib/dai.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka <marcin.maka@linux.intel.com> - */ - -#ifdef __SOF_LIB_DAI_H__ - -#ifndef __PLATFORM_LIB_DAI_H__ -#define __PLATFORM_LIB_DAI_H__ - -/* TIGERLAKE */ - -/* 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 6 - -/** \brief Number of 'extended' SSP ports available */ -#define DAI_NUM_SSP_EXT 0 - -/** \brief Number of SSP MCLKs available */ -#define DAI_NUM_SSP_MCLK 2 - -/* 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 7 - -/* ALH */ - -/** \brief Number of ALH bi-directional links */ -#define DAI_NUM_ALH_BI_DIR_LINKS 16 - -/** \brief Number of contiguous ALH bi-dir links */ -#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 4 - -#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/tigerlake/include/platform/lib/dma.h b/src/platform/tigerlake/include/platform/lib/dma.h deleted file mode 100644 index 4dfae664ae11..000000000000 --- a/src/platform/tigerlake/include/platform/lib/dma.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_DMA_H__ - -#ifndef __PLATFORM_LIB_DMA_H__ -#define __PLATFORM_LIB_DMA_H__ - -/* number of supported DMACs */ -#define PLATFORM_NUM_DMACS 6 - -/* max number of supported DMA channels */ -#define PLATFORM_MAX_DMA_CHAN 9 - -/* available DMACs */ -#define DMA_GP_LP_DMAC0 0 -#define DMA_GP_LP_DMAC1 1 -#define DMA_GP_HP_DMAC0 2 -#define DMA_GP_HP_DMAC1 3 -#define DMA_HOST_IN_DMAC 4 -#define DMA_HOST_OUT_DMAC 5 -#define DMA_LINK_IN_DMAC 6 -#define DMA_LINK_OUT_DMAC 7 - -/* mappings - TODO improve API to get type */ -#define DMA_ID_DMAC0 DMA_HOST_IN_DMAC -#define DMA_ID_DMAC1 DMA_GP_LP_DMAC0 -#define DMA_ID_DMAC2 DMA_HOST_OUT_DMAC -#define DMA_ID_DMAC3 DMA_GP_HP_DMAC0 -#define DMA_ID_DMAC4 DMA_GP_LP_DMAC1 -#define DMA_ID_DMAC5 DMA_GP_HP_DMAC1 -#define DMA_ID_DMAC6 DMA_LINK_IN_DMAC -#define DMA_ID_DMAC7 DMA_LINK_OUT_DMAC - -/* handshakes */ -#define DMA_HANDSHAKE_DMIC_CH0 0 -#define DMA_HANDSHAKE_DMIC_CH1 1 -#define DMA_HANDSHAKE_SSP0_TX 2 -#define DMA_HANDSHAKE_SSP0_RX 3 -#define DMA_HANDSHAKE_SSP1_TX 4 -#define DMA_HANDSHAKE_SSP1_RX 5 -#define DMA_HANDSHAKE_SSP2_TX 6 -#define DMA_HANDSHAKE_SSP2_RX 7 -#define DMA_HANDSHAKE_SSP3_TX 8 -#define DMA_HANDSHAKE_SSP3_RX 9 -#define DMA_HANDSHAKE_SSP4_TX 10 -#define DMA_HANDSHAKE_SSP4_RX 11 -#define DMA_HANDSHAKE_SSP5_TX 12 -#define DMA_HANDSHAKE_SSP5_RX 13 - -#define dma_chan_irq(dma, chan) dma_irq(dma) -#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) - -#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/tigerlake/include/platform/lib/memory.h b/src/platform/tigerlake/include/platform/lib/memory.h index 3ca229abc531..63802920ac95 100644 --- a/src/platform/tigerlake/include/platform/lib/memory.h +++ b/src/platform/tigerlake/include/platform/lib/memory.h @@ -14,7 +14,11 @@ #include <cavs/lib/memory.h> #include <sof/lib/cpu.h> -#include <config.h> + +/* prioritize definitions in Zephyr SoC layer */ +#ifdef __ZEPHYR__ +#include <adsp_memory.h> +#endif /* physical DSP addresses */ @@ -130,45 +134,52 @@ #define LOG_ENTRY_ELF_BASE 0x20000000 #define LOG_ENTRY_ELF_SIZE 0x2000000 +#define EXT_MANIFEST_ELF_BASE (LOG_ENTRY_ELF_BASE + LOG_ENTRY_ELF_SIZE) +#define EXT_MANIFEST_ELF_SIZE 0x2000000 + /* * The HP SRAM Region on Tigerlake is organised like this :- - * +--------------------------------------------------------------------------+ - * | Offset | Region | Size | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_SW_REG_BASE | SW Registers W0 | SRAM_SW_REG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_MAILBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_EXCEPT_BASE | Debug data W2 | SRAM_EXCEPT_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_STREAM_BASE | Stream data W2 | SRAM_STREAM_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SRAM_TRACE_BASE | Trace Buffer W3 | SRAM_TRACE_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | HP_SRAM_BASE | DMA | HEAP_HP_BUFFER_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | SOF_FW_START | text | | - * | | data | | - * | | BSS | | - * +------------------+-------------------------+-----------------------------+ - * | | Runtime Heap | HEAP_RUNTIME_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Module Buffers | HEAP_BUFFER_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Master core Sys Heap | HEAP_SYSTEM_M_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Master Sys Runtime Heap | HEAP_SYS_RUNTIME_M_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Master core Stack | SOF_STACK_SIZE | - * +------------------+-------------------------+-----------------------------+ - * | | Slave core Sys Heap | SOF_CORE_S_T_SIZE | - * | | Slave Sys Runtime Heap | | - * | | Slave core Stack | | - * +------------------+-------------------------+-----------------------------+ + * +----------------------------------------------------------------------------+ + * | Offset | Region | Size | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_SW_REG_BASE | SW Registers W0 | SRAM_SW_REG_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_OUTBOX_BASE | Outbox W0 | SRAM_OUTBOX_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_INBOX_BASE | Inbox W1 | SRAM_INBOX_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_DEBUG_BASE | Debug data W2 | SRAM_DEBUG_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_EXCEPT_BASE | Debug data W2 | SRAM_EXCEPT_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_STREAM_BASE | Stream data W2 | SRAM_STREAM_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SRAM_TRACE_BASE | Trace Buffer W3 | SRAM_TRACE_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | HEAP_HP_BUFFER_BASE| DMA | HEAP_HP_BUFFER_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | SOF_FW_START | text | | + * | | data | | + * | | BSS | | + * +--------------------+-------------------------+-----------------------------+ + * | | Runtime Heap | HEAP_RUNTIME_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | | Runtime shared Heap | HEAP_RUNTIME_SHARED_SIZE | + * | |-------------------------+-----------------------------+ + * | | System shared Heap | HEAP_SYSTEM_SHARED_SIZE | + * | |-------------------------+-----------------------------+ + * | | Module Buffers | HEAP_BUFFER_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | | Primary core Sys Heap | HEAP_SYSTEM_M_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | | Pri. Sys Runtime Heap | HEAP_SYS_RUNTIME_M_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | | Primary core Stack | SOF_STACK_SIZE | + * +--------------------+-------------------------+-----------------------------+ + * | | Sec. core Sys Heap | SOF_CORE_S_T_SIZE | + * | | Sec. Sys Runtime Heap | | + * | | Secondary core Stack | | + * +--------------------+-------------------------+-----------------------------+ */ /* HP SRAM */ @@ -179,14 +190,6 @@ #define SRAM_SW_REG_BASE (HP_SRAM_BASE + 0x4000) #define SRAM_SW_REG_SIZE 0x1000 -/* SRAM window 0 FW "registers" */ -#define SRAM_REG_ROM_STATUS 0x0 -#define SRAM_REG_FW_STATUS 0x4 -#define SRAM_REG_FW_TRACEP 0x8 -#define SRAM_REG_FW_IPC_RECEIVED_COUNT 0xc -#define SRAM_REG_FW_IPC_PROCESSED_COUNT 0x10 -#define SRAM_REG_FW_END 0x14 - #define SRAM_OUTBOX_BASE (SRAM_SW_REG_BASE + SRAM_SW_REG_SIZE) #define SRAM_OUTBOX_SIZE 0x1000 @@ -237,27 +240,52 @@ /* max size for all var-size sections (text/rodata/bss) */ #define SOF_FW_MAX_SIZE (HP_SRAM_BASE + HP_SRAM_SIZE - SOF_FW_BASE) +#define SOF_FW_END (HP_SRAM_BASE + HP_SRAM_SIZE) + #define SOF_TEXT_START (SOF_FW_START) #define SOF_TEXT_BASE (SOF_FW_START) -/* Heap section sizes for system runtime heap for master core */ +/* Heap section sizes for system runtime heap for primary core */ #define HEAP_SYS_RT_0_COUNT64 128 #define HEAP_SYS_RT_0_COUNT512 16 #define HEAP_SYS_RT_0_COUNT1024 4 -/* Heap section sizes for system runtime heap for slave core */ +/* Heap section sizes for system runtime heap for secondary core */ #define HEAP_SYS_RT_X_COUNT64 64 #define HEAP_SYS_RT_X_COUNT512 8 #define HEAP_SYS_RT_X_COUNT1024 4 +/* Heap section counts base */ +#define HEAP_COUNT64 128 +#define HEAP_COUNT128 128 +#define HEAP_COUNT256 96 +#define HEAP_COUNT512 8 +#define HEAP_COUNT1024 4 +#define HEAP_COUNT2048 2 +#define HEAP_COUNT4096 1 + +#if HP_SRAM_SIZE < 0x200000 +#define RT_TIMES 3 +#define RT_SHARED_TIMES 6 +#else +/* Reserve more memory for RTNR */ +#if defined(CONFIG_COMP_RTNR) || defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) +#define RT_TIMES 2 +#define RT_SHARED_TIMES 4 +#else +#define RT_TIMES 8 +#define RT_SHARED_TIMES 16 +#endif /* CONFIG_COMP_RTNR */ +#endif + /* Heap section sizes for module pool */ -#define HEAP_RT_COUNT64 128 -#define HEAP_RT_COUNT128 64 -#define HEAP_RT_COUNT256 128 -#define HEAP_RT_COUNT512 8 -#define HEAP_RT_COUNT1024 4 -#define HEAP_RT_COUNT2048 0 -#define HEAP_RT_COUNT4096 1 +#define HEAP_RT_COUNT64 (HEAP_COUNT64 * RT_TIMES) +#define HEAP_RT_COUNT128 (HEAP_COUNT128 * RT_TIMES) +#define HEAP_RT_COUNT256 (HEAP_COUNT256 * RT_TIMES) +#define HEAP_RT_COUNT512 (HEAP_COUNT512 * RT_TIMES) +#define HEAP_RT_COUNT1024 (HEAP_COUNT1024 * RT_TIMES) +#define HEAP_RT_COUNT2048 (HEAP_COUNT2048 * RT_TIMES) +#define HEAP_RT_COUNT4096 (HEAP_COUNT4096 * RT_TIMES) /* Heap configuration */ #define HEAP_RUNTIME_SIZE \ @@ -266,14 +294,28 @@ HEAP_RT_COUNT1024 * 1024 + HEAP_RT_COUNT2048 * 2048 + \ HEAP_RT_COUNT4096 * 4096) -#define HEAP_BUFFER_SIZE 0x50000 +/* Heap section sizes for runtime shared heap */ +#define HEAP_RUNTIME_SHARED_COUNT64 (HEAP_COUNT64 * RT_SHARED_TIMES) +#define HEAP_RUNTIME_SHARED_COUNT128 (HEAP_COUNT128 * RT_SHARED_TIMES) +#define HEAP_RUNTIME_SHARED_COUNT256 (HEAP_COUNT256 * RT_SHARED_TIMES) +#define HEAP_RUNTIME_SHARED_COUNT512 (HEAP_COUNT512 * RT_SHARED_TIMES) +#define HEAP_RUNTIME_SHARED_COUNT1024 (HEAP_COUNT1024 * RT_SHARED_TIMES) + +#define HEAP_RUNTIME_SHARED_SIZE \ + (HEAP_RUNTIME_SHARED_COUNT64 * 64 + HEAP_RUNTIME_SHARED_COUNT128 * 128 + \ + HEAP_RUNTIME_SHARED_COUNT256 * 256 + HEAP_RUNTIME_SHARED_COUNT512 * 512 + \ + HEAP_RUNTIME_SHARED_COUNT1024 * 1024) + +/* Heap section sizes for system shared heap */ +#define HEAP_SYSTEM_SHARED_SIZE 0x1500 + #define HEAP_BUFFER_BLOCK_SIZE 0x100 -#define HEAP_BUFFER_COUNT (HEAP_BUFFER_SIZE / HEAP_BUFFER_BLOCK_SIZE) +#define HEAP_BUFFER_COUNT_MAX (HP_SRAM_SIZE / HEAP_BUFFER_BLOCK_SIZE) -#define HEAP_SYSTEM_M_SIZE 0x8000 /* heap master core size */ -#define HEAP_SYSTEM_S_SIZE 0x6000 /* heap slave core size */ +#define HEAP_SYSTEM_M_SIZE 0x8000 /* heap primary core size */ +#define HEAP_SYSTEM_S_SIZE 0x6000 /* heap secondary core size */ #define HEAP_SYSTEM_T_SIZE \ - (HEAP_SYSTEM_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) + (HEAP_SYSTEM_M_SIZE + ((CONFIG_CORE_COUNT - 1) * HEAP_SYSTEM_S_SIZE)) #define HEAP_SYS_RUNTIME_M_SIZE \ (HEAP_SYS_RT_0_COUNT64 * 64 + HEAP_SYS_RT_0_COUNT512 * 512 + \ @@ -284,18 +326,12 @@ HEAP_SYS_RT_X_COUNT1024 * 1024) #define HEAP_SYS_RUNTIME_T_SIZE \ - (HEAP_SYS_RUNTIME_M_SIZE + ((PLATFORM_CORE_COUNT - 1) * \ + (HEAP_SYS_RUNTIME_M_SIZE + ((CONFIG_CORE_COUNT - 1) * \ HEAP_SYS_RUNTIME_S_SIZE)) /* Stack configuration */ -#define SOF_STACK_SIZE 0x1000 -#define SOF_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * SOF_STACK_SIZE) - -/* SOF Core S configuration */ -#define SOF_CORE_S_SIZE \ - ALIGN((HEAP_SYSTEM_S_SIZE + HEAP_SYS_RUNTIME_S_SIZE + SOF_STACK_SIZE),\ - SRAM_BANK_SIZE) -#define SOF_CORE_S_T_SIZE ((PLATFORM_CORE_COUNT - 1) * SOF_CORE_S_SIZE) +#define SOF_STACK_SIZE (CONFIG_SOF_STACK_SIZE) +#define SOF_STACK_TOTAL_SIZE (CONFIG_CORE_COUNT * SOF_STACK_SIZE) /* * The LP SRAM Heap and Stack on Tigerlake are organised like this :- @@ -320,34 +356,30 @@ */ /* LP SRAM */ -#define LP_SRAM_BASE 0xBE800000 +#ifndef __ZEPHYR__ +#define LP_SRAM_BASE 0xBE800000 +#endif -/* Heap section sizes for module pool */ -#define HEAP_RT_LP_COUNT8 0 -#define HEAP_RT_LP_COUNT16 256 -#define HEAP_RT_LP_COUNT32 128 -#define HEAP_RT_LP_COUNT64 64 -#define HEAP_RT_LP_COUNT128 64 -#define HEAP_RT_LP_COUNT256 96 -#define HEAP_RT_LP_COUNT512 8 -#define HEAP_RT_LP_COUNT1024 4 +#if CONFIG_MULTICORE +/* alternate reset vector */ +#define LP_SRAM_ALT_RESET_VEC_BASE LP_SRAM_BASE +#define LP_SRAM_ALT_RESET_VEC_SIZE 0x180 -/* Heap configuration */ -#define SOF_LP_DATA_SIZE 0x4000 +#define LP_SRAM_ALT_RESET_INT_VEC_BASE (LP_SRAM_ALT_RESET_VEC_BASE + \ + LP_SRAM_ALT_RESET_VEC_SIZE) +#define LP_SRAM_ALT_RESET_INT_VEC_SIZE 0x10 -#define HEAP_LP_SYSTEM_BASE (LP_SRAM_BASE + SOF_LP_DATA_SIZE) -#define HEAP_LP_SYSTEM_SIZE 0x1000 +#define LP_SRAM_CODE_BASE (LP_SRAM_ALT_RESET_INT_VEC_BASE + \ + LP_SRAM_ALT_RESET_INT_VEC_SIZE) +#define LP_SRAM_CODE_SIZE 0x220 -#define HEAP_LP_RUNTIME_BASE \ - (HEAP_LP_SYSTEM_BASE + HEAP_LP_SYSTEM_SIZE) -#define HEAP_LP_RUNTIME_SIZE \ - (HEAP_RT_LP_COUNT8 * 8 + HEAP_RT_LP_COUNT16 * 16 + \ - HEAP_RT_LP_COUNT32 * 32 + HEAP_RT_LP_COUNT64 * 64 + \ - HEAP_RT_LP_COUNT128 * 128 + HEAP_RT_LP_COUNT256 * 256 + \ - HEAP_RT_LP_COUNT512 * 512 + HEAP_RT_LP_COUNT1024 * 1024) +#define LP_SRAM_START (LP_SRAM_CODE_BASE + LP_SRAM_CODE_SIZE) +#else +#define LP_SRAM_START LP_SRAM_BASE +#endif -#define HEAP_LP_BUFFER_BASE LP_SRAM_BASE -#define HEAP_LP_BUFFER_SIZE LP_SRAM_SIZE +#define HEAP_LP_BUFFER_BASE LP_SRAM_START +#define HEAP_LP_BUFFER_SIZE (LP_SRAM_SIZE - (LP_SRAM_START - LP_SRAM_BASE)) #define HEAP_LP_BUFFER_BLOCK_SIZE 0x180 @@ -358,9 +390,11 @@ #define HEAP_LP_BUFFER_COUNT 0 #endif -#define PLATFORM_HEAP_SYSTEM PLATFORM_CORE_COUNT /* one per core */ -#define PLATFORM_HEAP_SYSTEM_RUNTIME PLATFORM_CORE_COUNT /* one per core */ +#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 /* Stack configuration */ @@ -376,6 +410,9 @@ #define SOF_MEM_VECT_SIZE (SOF_MEM_VECT_TEXT_SIZE + \ SOF_MEM_VECT_LIT_SIZE) +/* Size of dynamic vectors unpacked from WindowOverflow4 */ +#define SOF_DYNAMIC_VECTORS_SIZE 0x400 + #define SOF_MEM_ERROR_TEXT_SIZE 0x180 #define SOF_MEM_ERROR_LIT_SIZE 0x8 @@ -390,11 +427,18 @@ #define ROM_RESET_LIT_SIZE 0x200 /* boot loader in IMR */ + +#ifndef __ZEPHYR__ #define IMR_BOOT_LDR_MANIFEST_BASE 0xB0032000 #define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 +#ifndef IMR_BOOT_LDR_TEXT_ENTRY_BASE #define IMR_BOOT_LDR_TEXT_ENTRY_BASE 0xB0038000 +#endif + #define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x120 +#endif + #define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ IMR_BOOT_LDR_TEXT_ENTRY_SIZE) #define IMR_BOOT_LDR_LIT_SIZE 0x22 @@ -410,6 +454,40 @@ #define BOOT_LDR_STACK_BASE HEAP_HP_BUFFER_BASE #define BOOT_LDR_STACK_SIZE SOF_STACK_TOTAL_SIZE +/* L1 memory */ +#define L1_MEM_BASE 0x9F000000 +#define L1_DRAM_SIZE (CONFIG_L1_DRAM_BANKS * CONFIG_L1_DRAM_BANK_SIZE) +#define L1_MEM_REG_BASE 0x9F080000 +#define L1_MEM_CAP (L1_MEM_REG_BASE + 0x00) +#define L1_MEM_DRAM_PGCTL (L1_MEM_REG_BASE + 0x20) +#define L1_MEM_DRAM_PGISTS (L1_MEM_REG_BASE + 0x28) + +/* L1 init */ +#define L1CC_ADDR (0x9F080080) +#define CxL1CCAP (L1CC_ADDR + 0x0000) +#define CxL1CCFG (L1CC_ADDR + 0x0004) +#define CxL1PCFG (L1CC_ADDR + 0x0008) + +#define L1_CACHE_ALL_DATA_WAY_ENABLED_MASK (BIT(XCHAL_DCACHE_WAYS) - 1) +#define L1_CACHE_ALL_INSTR_WAY_ENABLED_MASK ((BIT(XCHAL_ICACHE_WAYS) - 1) << 8) +#define L1_CACHE_ALL_WAY_ENABLED_MASK ((L1_CACHE_ALL_DATA_WAY_ENABLED_MASK) \ + | (L1_CACHE_ALL_INSTR_WAY_ENABLED_MASK)) +#define L1_CACHE_ALL_WAY_ACTIVE_MASK (L1_CACHE_ALL_WAY_ENABLED_MASK << 16) + +#define L1_CACHE_ONE_DATA_WAY_ENABLED_MASK BIT(0) +#define L1_CACHE_ONE_INSTR_WAY_ENABLED_MASK BIT(8) +#define L1_CACHE_ONE_WAY_ENABLED_MASK (L1_CACHE_ONE_DATA_WAY_ENABLED_MASK \ + | L1_CACHE_ONE_INSTR_WAY_ENABLED_MASK) +#define L1_CACHE_ONE_WAY_ACTIVE_MASK (L1_CACHE_ONE_WAY_ENABLED_MASK << 16) + +#define L1_CACHE_PREFETCHER_ENABLED 1 +#define L1_CACHE_PREFETCHER_ACTIVE 0x10000 + +#define L1_CACHE_PREFCTL_VALUE 0x1038 + +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + #endif /* __PLATFORM_LIB_MEMORY_H__ */ #else diff --git a/src/platform/tigerlake/include/platform/lib/pm_runtime.h b/src/platform/tigerlake/include/platform/lib/pm_runtime.h deleted file mode 100644 index 42c027cdc70e..000000000000 --- a/src/platform/tigerlake/include/platform/lib/pm_runtime.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -/** - * \file platform/tigerlake/include/platform/lib/pm_runtime.h - * \brief Runtime power management header file for Tigerlake - * \author Tomasz Lauda <tomasz.lauda@linux.intel.com> - */ - -#ifdef __SOF_LIB_PM_RUNTIME_H__ - -#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ -#define __PLATFORM_LIB_PM_RUNTIME_H__ - -#include <cavs/lib/pm_runtime.h> -#include <stdint.h> - -/** - * \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_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); - -/** - * \brief Power gates platform specific hardware resources. - */ -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/tigerlake/include/platform/lib/shim.h b/src/platform/tigerlake/include/platform/lib/shim.h deleted file mode 100644 index d417c70e9f4c..000000000000 --- a/src/platform/tigerlake/include/platform/lib/shim.h +++ /dev/null @@ -1,373 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2017 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - * Keyon Jie <yang.jie@linux.intel.com> - * Rander Wang <rander.wang@intel.com> - */ - -#ifdef __SOF_LIB_SHIM_H__ - -#ifndef __PLATFORM_LIB_SHIM_H__ -#define __PLATFORM_LIB_SHIM_H__ - -#include <cavs/drivers/sideband-ipc.h> -#include <sof/bit.h> -#include <sof/lib/memory.h> - -#ifndef ASSEMBLY -#include <stdint.h> -#endif - -/* DSP IPC for Host Registers */ -#define IPC_DIPCTDR 0x00 -#define IPC_DIPCTDA 0x04 -#define IPC_DIPCTDD 0x08 -#define IPC_DIPCIDR 0x10 -#define IPC_DIPCIDA 0x14 -#define IPC_DIPCIDD 0x18 -#define IPC_DIPCCTL 0x28 - -#define IPC_DSP_OFFSET 0x10 - -/* DSP IPC for intra DSP communication */ -#define IPC_IDCTFC(x) (0x0 + x * IPC_DSP_OFFSET) -#define IPC_IDCTEFC(x) (0x4 + x * IPC_DSP_OFFSET) -#define IPC_IDCITC(x) (0x8 + x * IPC_DSP_OFFSET) -#define IPC_IDCIETC(x) (0xc + x * IPC_DSP_OFFSET) -#define IPC_IDCCTL 0x50 - -/* IDCTFC */ -#define IPC_IDCTFC_BUSY BIT(31) -#define IPC_IDCTFC_MSG_MASK 0x7FFFFFFF - -/* IDCTEFC */ -#define IPC_IDCTEFC_MSG_MASK 0x3FFFFFFF - -/* IDCITC */ -#define IPC_IDCITC_BUSY BIT(31) -#define IPC_IDCITC_MSG_MASK 0x7FFFFFFF - -/* IDCIETC */ -#define IPC_IDCIETC_DONE BIT(30) -#define IPC_IDCIETC_MSG_MASK 0x3FFFFFFF - -/* IDCCTL */ -#define IPC_IDCCTL_IDCIDIE(x) (0x100 << (x)) -#define IPC_IDCCTL_IDCTBIE(x) BIT(x) - -#define IRQ_CPU_OFFSET 0x40 - -#define REG_IRQ_IL2MSD(xcpu) (0x0 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MCD(xcpu) (0x4 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2MD(xcpu) (0x8 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL2SD(xcpu) (0xc + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL2MD_ALL 0x03F181F0 - -#define REG_IRQ_IL3MSD(xcpu) (0x10 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MCD(xcpu) (0x14 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3MD(xcpu) (0x18 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL3SD(xcpu) (0x1c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL3MD_ALL 0x807F81FF - -#define REG_IRQ_IL4MSD(xcpu) (0x20 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MCD(xcpu) (0x24 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4MD(xcpu) (0x28 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL4SD(xcpu) (0x2c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL4MD_ALL 0x807F81FF - -#define REG_IRQ_IL5MSD(xcpu) (0x30 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MCD(xcpu) (0x34 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5MD(xcpu) (0x38 + (xcpu * IRQ_CPU_OFFSET)) -#define REG_IRQ_IL5SD(xcpu) (0x3c + (xcpu * IRQ_CPU_OFFSET)) - -/* all mask valid bits */ -#define REG_IRQ_IL5MD_ALL 0xFFFFC0CF - -#define REG_IRQ_IL2RSD 0x100 -#define REG_IRQ_IL3RSD 0x104 -#define REG_IRQ_IL4RSD 0x108 -#define REG_IRQ_IL5RSD 0x10c - -#define REG_IRQ_LVL5_LP_GPDMA0_MASK (0xff << 16) -#define REG_IRQ_LVL5_LP_GPDMA1_MASK (0xff << 24) - -/* DSP Shim Registers */ -#define SHIM_DSPWC 0x20 /* DSP Wall Clock */ -#define SHIM_DSPWCTCS 0x28 /* DSP Wall Clock Timer Control & Status */ -#define SHIM_DSPWCT0C 0x30 /* DSP Wall Clock Timer 0 Compare */ -#define SHIM_DSPWCT1C 0x38 /* DSP Wall Clock Timer 1 Compare */ - -#define SHIM_DSPWCTCS_T1T BIT(5) /* Timer 1 triggered */ -#define SHIM_DSPWCTCS_T0T BIT(4) /* Timer 0 triggered */ -#define SHIM_DSPWCTCS_T1A BIT(1) /* Timer 1 armed */ -#define SHIM_DSPWCTCS_T0A BIT(0) /* Timer 0 armed */ - -/** \brief Clock control */ -#define SHIM_CLKCTL 0x78 - -/** \brief Request HP RING Oscillator Clock */ -#define SHIM_CLKCTL_RHROSCC BIT(31) - -/** \brief Request XTAL Oscillator Clock */ -#define SHIM_CLKCTL_RXOSCC BIT(30) - -/** \brief Request LP RING Oscillator Clock */ -#define SHIM_CLKCTL_RLROSCC BIT(29) - -/** \brief Tensilica Core Prevent Local Clock Gating */ -#define SHIM_CLKCTL_TCPLCG_EN(x) BIT(16 + (x)) -#define SHIM_CLKCTL_TCPLCG_DIS(x) 0 -#define SHIM_CLKCTL_TCPLCG_DIS_ALL (SHIM_CLKCTL_TCPLCG_DIS(0) | \ - SHIM_CLKCTL_TCPLCG_DIS(1) | \ - SHIM_CLKCTL_TCPLCG_DIS(2) | \ - SHIM_CLKCTL_TCPLCG_DIS(3)) - -/** \brief Oscillator Clock Select*/ -#define SHIM_CLKCTL_OCS_HP_RING BIT(2) -#define SHIM_CLKCTL_OCS_LP_RING 0 - -/** \brief LP Memory Clock Select */ -#define SHIM_CLKCTL_LMCS_DIV2 0 -#define SHIM_CLKCTL_LMCS_DIV4 BIT(1) - -/** \brief HP Memory Clock Select */ -#define SHIM_CLKCTL_HMCS_DIV2 0 -#define SHIM_CLKCTL_HMCS_DIV4 BIT(0) - -/* Core clock PLL divisor */ -#define SHIM_CLKCTL_DPCS_MASK(x) BIT(2) - -/* Prevent Audio PLL Shutdown */ -#define SHIM_CLKCTL_TCPAPLLS BIT(7) - -/* 0--from PLL, 1--from oscillator */ -#define SHIM_CLKCTL_HDCS BIT(4) - -/* Oscillator select */ -#define SHIM_CLKCTL_HDOCS BIT(2) - -/* HP memory clock PLL divisor */ -#define SHIM_CLKCTL_HPMPCS BIT(0) - -/** \brief Mask for requesting clock - */ -#define SHIM_CLKCTL_OSC_REQUEST_MASK \ - (SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_RXOSCC | \ - SHIM_CLKCTL_RLROSCC) - -/** \brief Mask for setting previously requested clock - */ -#define SHIM_CLKCTL_OSC_SOURCE_MASK \ - (SHIM_CLKCTL_OCS_HP_RING | SHIM_CLKCTL_LMCS_DIV4 | \ - SHIM_CLKCTL_HMCS_DIV4) - -/** \brief Clock status */ -#define SHIM_CLKSTS 0x7C - -/** \brief HP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_HROSCCS BIT(31) - -/** \brief XTAL Oscillator Clock Status */ -#define SHIM_CLKSTS_XOSCCS BIT(30) - -/** \brief LP RING Oscillator Clock Status */ -#define SHIM_CLKSTS_LROSCCS BIT(29) - -#define SHIM_PWRCTL 0x90 -#define SHIM_PWRCTL_TCPDSPPG(x) BIT(x) -#define SHIM_PWRCTL_TCPCTLPG BIT(4) - -#define SHIM_PWRSTS 0x92 - -#define SHIM_LPSCTL 0x94 -#define SHIM_LPSCTL_BID BIT(7) -#define SHIM_LPSCTL_FDSPRUN BIT(9) -#define SHIM_LPSCTL_BATTR_0 BIT(12) - -/** \brief GPDMA shim registers Control */ -#define SHIM_GPDMA_BASE_OFFSET 0x6500 -#define SHIM_GPDMA_BASE(x) (SHIM_GPDMA_BASE_OFFSET + (x) * 0x100) - -/** \brief GPDMA Clock Control */ -#define SHIM_GPDMA_CLKCTL(x) (SHIM_GPDMA_BASE(x) + 0x4) -/* LP GPDMA Force Dynamic Clock Gating bits, 0--enable */ -#define SHIM_CLKCTL_LPGPDMAFDCGB BIT(0) - -/** \brief GPDMA Channel Linear Link Position Control */ -#define SHIM_GPDMA_CHLLPC(x, y) (SHIM_GPDMA_BASE(x) + 0x10 + (y) * 0x10) -#define SHIM_GPDMA_CHLLPC_EN BIT(7) -#define SHIM_GPDMA_CHLLPC_DHRS(x) SET_BITS(6, 0, x) - -/* I2S SHIM Registers */ -#define I2SLCTL 0x71C04 - -/* SPA register should be set for each I2S port and DSP should - * wait for CPA to be set - */ -#define I2SLCTL_SPA(x) BIT(0 + x) -#define I2SLCTL_CPA(x) BIT(8 + x) - -#define L2LMCAP 0x71D00 -#define L2MPAT 0x71D04 - -#define HSPGCTL0 0x71D10 -#define HSRMCTL0 0x71D14 -#define HSPGISTS0 0x71D18 - -#define SHIM_HSPGCTL(x) (HSPGCTL0 + 0x10 * (x)) -#define SHIM_HSPGISTS(x) (HSPGISTS0 + 0x10 * (x)) - -#define HSPGCTL1 0x71D20 -#define HSRMCTL1 0x71D24 -#define HSPGISTS1 0x71D28 - -#define LSPGCTL 0x71D50 -#define LSRMCTL 0x71D54 -#define LSPGISTS 0x71D58 - -#define SHIM_L2_MECS (SHIM_BASE + 0xd0) - -/** \brief LDO Control */ -#define SHIM_LDOCTL 0xA4 -#define SHIM_LDOCTL_HPSRAM_MASK (3 << 0) -#define SHIM_LDOCTL_LPSRAM_MASK (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_ON (3 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_ON (3 << 2) -#define SHIM_LDOCTL_HPSRAM_LDO_BYPASS BIT(0) -#define SHIM_LDOCTL_LPSRAM_LDO_BYPASS BIT(2) -#define SHIM_LDOCTL_HPSRAM_LDO_OFF (0 << 0) -#define SHIM_LDOCTL_LPSRAM_LDO_OFF (0 << 2) - -#define DSP_INIT_LPGPDMA(x) (0x71A60 + (2*x)) -#define LPGPDMA_CTLOSEL_FLAG BIT(15) -#define LPGPDMA_CHOSEL_FLAG 0xFF - -#define DSP_INIT_IOPO 0x71A68 -#define IOPO_DMIC_FLAG BIT(0) -#define IOPO_I2S_FLAG MASK(DAI_NUM_SSP_BASE + DAI_NUM_SSP_EXT + 7, 8) - -#define DSP_INIT_GENO 0x71A6C -#define GENO_MDIVOSEL BIT(1) -#define GENO_DIOPTOSEL BIT(2) - -#define DSP_INIT_ALHO 0x71A70 -#define ALHO_ASO_FLAG BIT(0) -#define ALHO_CSO_FLAG BIT(1) -#define ALHO_CFO_FLAG BIT(2) - -#define SHIM_SVCFG 0xF4 -#define SHIM_SVCFG_FORCE_L1_EXIT BIT(1) - -/* host windows */ -#define DMWBA(x) (HOST_WIN_BASE(x) + 0x0) -#define DMWLO(x) (HOST_WIN_BASE(x) + 0x4) - -#define DMWBA_ENABLE BIT(0) -#define DMWBA_READONLY BIT(1) - -/* DMIC power ON bit */ -#define DMICLCTL_SPA ((uint32_t) BIT(0)) - -/* DMIC disable clock gating */ -#define DMIC_DCGD ((uint32_t) BIT(30)) - -#ifndef ASSEMBLY - -static inline uint16_t shim_read16(uint16_t reg) -{ - return *((volatile uint16_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write16(uint16_t reg, uint16_t val) -{ - *((volatile uint16_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t shim_read(uint32_t reg) -{ - return *((volatile uint32_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint64_t shim_read64(uint32_t reg) -{ - return *((volatile uint64_t*)(SHIM_BASE + reg)); -} - -static inline void shim_write64(uint32_t reg, uint64_t val) -{ - *((volatile uint64_t*)(SHIM_BASE + reg)) = val; -} - -static inline uint32_t sw_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)); -} - -static inline void sw_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)((SRAM_SW_REG_BASE - - SRAM_ALIAS_OFFSET) + reg)) = val; -} - -static inline uint32_t mn_reg_read(uint32_t reg) -{ - return *((volatile uint32_t*)(MN_BASE + reg)); -} - -static inline void mn_reg_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(MN_BASE + reg)) = val; -} - -static inline uint32_t irq_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IRQ_BASE + reg)); -} - -static inline void irq_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IRQ_BASE + reg)) = val; -} - -static inline uint32_t ipc_read(uint32_t reg) -{ - return *((volatile uint32_t*)(IPC_HOST_BASE + reg)); -} - -static inline void ipc_write(uint32_t reg, uint32_t val) -{ - *((volatile uint32_t*)(IPC_HOST_BASE + reg)) = val; -} - -static inline uint32_t idc_read(uint32_t reg, uint32_t core_id) -{ - return *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)); -} - -static inline void idc_write(uint32_t reg, uint32_t core_id, uint32_t val) -{ - *((volatile uint32_t*)(IPC_DSP_BASE(core_id) + reg)) = val; -} -#endif - -#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/tigerlake/include/platform/platform.h b/src/platform/tigerlake/include/platform/platform.h index 992e0828ed28..46bd196ebf44 100644 --- a/src/platform/tigerlake/include/platform/platform.h +++ b/src/platform/tigerlake/include/platform/platform.h @@ -13,47 +13,19 @@ #ifndef __PLATFORM_PLATFORM_H__ #define __PLATFORM_PLATFORM_H__ -#define PLATFORM_RESET_MHE_AT_BOOT 1 - -#define PLATFORM_MEM_INIT_AT_BOOT 1 - #if !defined(__ASSEMBLER__) && !defined(LINKER) -#include <sof/drivers/interrupt.h> -#include <sof/lib/clk.h> -#include <sof/lib/mailbox.h> +#include <rtos/clk.h> #include <stddef.h> #include <stdint.h> +#include <cavs/version.h> + struct ll_schedule_domain; struct timer; -/*! \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 - -#define MAX_GPDMA_COUNT 2 - /* Host page size */ #define HOST_PAGE_SIZE 4096 -#define PLATFORM_PAGE_TABLE_SIZE 256 - -/* IDC Interrupt */ -#define PLATFORM_IDC_INTERRUPT IRQ_EXT_IDC_LVL2 -#define PLATFORM_IDC_INTERRUPT_NAME irq_name_level2 - -/* IPC Interrupt */ -#define PLATFORM_IPC_INTERRUPT IRQ_EXT_IPC_LVL2 -#define PLATFORM_IPC_INTERRUPT_NAME irq_name_level2 - -/* pipeline IRQ */ -#define PLATFORM_SCHEDULE_IRQ IRQ_NUM_SOFTWARE2 -#define PLATFORM_SCHEDULE_IRQ_NAME NULL /* Platform stream capabilities */ #define PLATFORM_MAX_CHANNELS 8 @@ -62,48 +34,6 @@ struct timer; /* local buffer size of DMA tracing */ #define DMA_TRACE_LOCAL_SIZE (HOST_PAGE_SIZE * 2) -/* trace bytes flushed during panic */ -#define DMA_FLUSH_TRACE_SIZE (MAILBOX_TRACE_SIZE >> 2) - -/* the interval of DMA trace copying */ -#define DMA_TRACE_PERIOD 500000 - -/* - * the interval of reschedule DMA trace copying in special case like half - * fullness of local DMA trace buffer - */ -#define DMA_TRACE_RESCHEDULE_TIME 500 - -/* DSP default delay in cycles */ -#define PLATFORM_DEFAULT_DELAY 12 - -/* minimal L1 exit time in cycles */ -#define PLATFORM_FORCE_L1_EXIT_TIME 985 - -/* the SSP port fifo depth */ -#define SSP_FIFO_DEPTH 16 - -/* the watermark for the SSP fifo depth setting */ -#define SSP_FIFO_WATERMARK 8 - -/* minimal SSP port delay in cycles */ -#define PLATFORM_SSP_DELAY 1600 - -/* Platform defined trace code */ -static inline void platform_panic(uint32_t p) -{ - mailbox_sw_reg_write(SRAM_REG_FW_STATUS, p & 0x3fffffff); - ipc_write(IPC_DIPCIDD, MAILBOX_EXCEPTION_OFFSET + 2 * 0x20000); - ipc_write(IPC_DIPCIDR, 0x80000000 | (p & 0x3fffffff)); -} - -/** - * \brief Platform specific CPU entering idle. - * May be power-optimized using platform specific capabilities. - * @param level Interrupt level. - */ -void platform_wait_for_interrupt(int level); - extern intptr_t _module_init_start; extern intptr_t _module_init_end; diff --git a/src/platform/tigerlake/include/platform/trace/trace.h b/src/platform/tigerlake/include/platform/trace/trace.h index 22a480092132..771a13dbfe54 100644 --- a/src/platform/tigerlake/include/platform/trace/trace.h +++ b/src/platform/tigerlake/include/platform/trace/trace.h @@ -10,12 +10,7 @@ #ifndef __PLATFORM_TRACE_TRACE_H__ #define __PLATFORM_TRACE_TRACE_H__ -#include <sof/lib/mailbox.h> -#include <sof/lib/memory.h> - -/* Platform defined trace code */ -#define platform_trace_point(__x) \ - mailbox_sw_reg_write(SRAM_REG_FW_TRACEP, (__x)) +#include <cavs/trace/trace.h> #endif /* __PLATFORM_TRACE_TRACE_H__ */ diff --git a/src/platform/tigerlake/lib/CMakeLists.txt b/src/platform/tigerlake/lib/CMakeLists.txt deleted file mode 100644 index 47a1b5962abf..000000000000 --- a/src/platform/tigerlake/lib/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -add_local_sources(sof clk.c) diff --git a/src/platform/tigerlake/lib/clk.c b/src/platform/tigerlake/lib/clk.c deleted file mode 100644 index 276fded135bc..000000000000 --- a/src/platform/tigerlake/lib/clk.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/common.h> -#include <sof/drivers/ssp.h> -#include <sof/lib/clk.h> - -const struct freq_table platform_cpu_freq[] = { - { 120000000, 120000 }, - { CLK_MAX_CPU_HZ, 400000 }, -}; - -const uint32_t cpu_freq_enc[] = { - SHIM_CLKCTL_RLROSCC | SHIM_CLKCTL_OCS_LP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, - SHIM_CLKCTL_RHROSCC | SHIM_CLKCTL_OCS_HP_RING | - SHIM_CLKCTL_HMCS_DIV2 | SHIM_CLKCTL_LMCS_DIV4, -}; - -const uint32_t cpu_freq_status_mask[] = { - SHIM_CLKSTS_LROSCCS, - SHIM_CLKSTS_HROSCCS, -}; - -STATIC_ASSERT(NUM_CPU_FREQ == ARRAY_SIZE(platform_cpu_freq), - invalid_number_of_cpu_frequencies); - -const struct freq_table *cpu_freq = platform_cpu_freq; - -/* IMPORTANT: array should be filled in increasing order - * (regarding to .freq field) - */ -const struct freq_table platform_ssp_freq[] = { - { 24576000, 24576 }, - { 38400000, 38400 }, - { 96000000, 96000 }, -}; - -const uint32_t platform_ssp_freq_sources[] = { - SSP_CLOCK_AUDIO_CARDINAL, - SSP_CLOCK_XTAL_OSCILLATOR, - SSP_CLOCK_PLL_FIXED, -}; - -STATIC_ASSERT(NUM_SSP_FREQ == ARRAY_SIZE(platform_ssp_freq), - invalid_number_of_ssp_frequencies); - -const struct freq_table *ssp_freq = platform_ssp_freq; -const uint32_t *ssp_freq_sources = platform_ssp_freq_sources; diff --git a/src/platform/tigerlake/rom.x.in b/src/platform/tigerlake/rom.x.in deleted file mode 100644 index d811b63c2c75..000000000000 --- a/src/platform/tigerlake/rom.x.in +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Linker Script for Apollolake Bootloader. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_reset_text : - org = ROM_BASE, - len = ROM_RESET_TEXT_SIZE - vector_reset_lit : - org = ROM_BASE + ROM_RESET_TEXT_SIZE, - len = ROM_RESET_LIT_SIZE - vector_base_text : - org = ROM_BASE + ROM_RESET_TEXT_SIZE + ROM_RESET_LIT_SIZE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = ROM_BASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = ROM_BASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = ROM_BASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = ROM_BASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = ROM_BASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = ROM_BASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = ROM_BASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = ROM_BASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = ROM_BASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = ROM_BASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = ROM_BASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_text : - org = ROM_BASE + 0x800, - len = ROM_SIZE, - sof_stack : - org = BOOT_LDR_STACK_BASE, - len = BOOT_LDR_STACK_SIZE -} - -PHDRS -{ - vector_reset_text_phdr PT_LOAD; - vector_reset_lit_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_text_phdr PT_LOAD; - sof_stack_phdr PT_LOAD; -} - -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = ROM_BASE); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .ResetVector.text : ALIGN(4) - { - _ResetVector_text_start = ABSOLUTE(.); - KEEP (*(.ResetVector.text)) - _ResetVector_text_end = ABSOLUTE(.); - } >vector_reset_text :vector_reset_text_phdr - - .ResetVector.literal : ALIGN(4) - { - _ResetVector_literal_start = ABSOLUTE(.); - *(.ResetVector.literal) - _ResetVector_literal_end = ABSOLUTE(.); - } >vector_reset_lit :vector_reset_lit_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_text :sof_text_phdr - - /* stack */ - _end = BOOT_LDR_STACK_BASE; - PROVIDE(end = BOOT_LDR_STACK_BASE); - _stack_sentry = BOOT_LDR_STACK_BASE; - __stack = BOOT_LDR_STACK_BASE + BOOT_LDR_STACK_SIZE; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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/src/platform/tigerlake/tigerlake.x.in b/src/platform/tigerlake/tigerlake.x.in deleted file mode 100644 index 9880728ab384..000000000000 --- a/src/platform/tigerlake/tigerlake.x.in +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Linker Script for Tigerlake. - * - * This script is run through the GNU C preprocessor to align the memory - * offsets with headers. - * - * Use spaces for formatting as cpp ignore tab sizes. - */ - -#include <config.h> -#include <sof/lib/memory.h> -#include <xtensa/config/core-isa.h> - -OUTPUT_ARCH(xtensa) - -MEMORY -{ - vector_memory_lit : - org = XCHAL_MEMERROR_VECTOR_PADDR + SOF_MEM_ERROR_LIT_SIZE, - len = SOF_MEM_ERROR_LIT_SIZE - vector_memory_text : - org = XCHAL_MEMERROR_VECTOR_PADDR, - len = SOF_MEM_ERROR_TEXT_SIZE - vector_base_text : - org = SOF_MEM_VECBASE, - len = SOF_MEM_VECBASE_LIT_SIZE - vector_int2_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int2_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL2_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int3_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int3_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL3_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int4_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int4_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL4_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int5_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int5_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL5_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int6_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int6_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL6_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_int7_lit : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_int7_text : - org = SOF_MEM_VECBASE + XCHAL_INTLEVEL7_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_kernel_lit : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_kernel_text : - org = SOF_MEM_VECBASE + XCHAL_KERNEL_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_user_lit : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_user_text : - org = SOF_MEM_VECBASE + XCHAL_USER_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - vector_double_lit : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS - SOF_MEM_VECT_LIT_SIZE, - len = SOF_MEM_VECT_LIT_SIZE - vector_double_text : - org = SOF_MEM_VECBASE + XCHAL_DOUBLEEXC_VECOFS, - len = SOF_MEM_VECT_TEXT_SIZE - sof_fw : - org = SOF_FW_BASE, - len = SOF_FW_MAX_SIZE - buffer_hp_heap : - org = HEAP_HP_BUFFER_BASE, - len = HEAP_HP_BUFFER_SIZE - wnd0 : - org = HP_SRAM_WIN0_BASE, - len = HP_SRAM_WIN0_SIZE - wnd1 : - org = HP_SRAM_WIN1_BASE, - len = HP_SRAM_WIN1_SIZE - wnd2 : - org = HP_SRAM_WIN2_BASE, - len = HP_SRAM_WIN2_SIZE - wnd3 : - org = HP_SRAM_WIN3_BASE, - len = HP_SRAM_WIN3_SIZE - static_uuid_entries_seg (!ari) : - org = UUID_ENTRY_ELF_BASE, - len = UUID_ENTRY_ELF_SIZE - static_log_entries_seg (!ari) : - org = LOG_ENTRY_ELF_BASE, - len = LOG_ENTRY_ELF_SIZE - lpsram_mem : - org = LP_SRAM_BASE, - len = LP_SRAM_SIZE -} - -PHDRS -{ - vector_memory_lit_phdr PT_LOAD; - vector_memory_text_phdr PT_LOAD; - vector_base_text_phdr PT_LOAD; - vector_int2_lit_phdr PT_LOAD; - vector_int2_text_phdr PT_LOAD; - vector_int3_lit_phdr PT_LOAD; - vector_int3_text_phdr PT_LOAD; - vector_int4_lit_phdr PT_LOAD; - vector_int4_text_phdr PT_LOAD; - vector_int5_lit_phdr PT_LOAD; - vector_int5_text_phdr PT_LOAD; - vector_int6_lit_phdr PT_LOAD; - vector_int6_text_phdr PT_LOAD; - vector_int7_lit_phdr PT_LOAD; - vector_int7_text_phdr PT_LOAD; - vector_kernel_lit_phdr PT_LOAD; - vector_kernel_text_phdr PT_LOAD; - vector_user_lit_phdr PT_LOAD; - vector_user_text_phdr PT_LOAD; - vector_double_lit_phdr PT_LOAD; - vector_double_text_phdr PT_LOAD; - sof_fw_phdr PT_LOAD; - buffer_hp_heap_phdr PT_LOAD; - wnd0_phdr PT_LOAD; - wnd1_phdr PT_LOAD; - wnd2_phdr PT_LOAD; - wnd3_phdr PT_LOAD; - static_uuid_entries_phdr PT_NOTE; - static_log_entries_phdr PT_NOTE; - lpsram_mem_phdr PT_LOAD; -} - -/* Default entry point: */ -ENTRY(_MainEntry) -_rom_store_table = 0; - -/* ABI0 does not use Window base */ -PROVIDE(_memmap_vecbase_reset = HP_SRAM_VECBASE_RESET); - -/* Various memory-map dependent cache attribute settings: */ -_memmap_cacheattr_wbna_trapnull = 0xFF42FFF2; -PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wbna_trapnull); - -SECTIONS -{ - .MemoryExceptionVector.text : ALIGN(4) - { - _MemoryExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.MemoryExceptionVector.text)) - _MemoryExceptionVector_text_end = ABSOLUTE(.); - } >vector_memory_text :vector_memory_text_phdr - - .buffer_hp_heap (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _buffer_hp_heap_start = ABSOLUTE(.); - . = . + HEAP_HP_BUFFER_SIZE; - _buffer_hp_heap_end = ABSOLUTE(.); - } >buffer_hp_heap :buffer_hp_heap_phdr - - .wnd0 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd0_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN0_SIZE; - _wnd0_end = ABSOLUTE(.); - } >wnd0 :wnd0_phdr - - .wnd1 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd1_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN1_SIZE; - _wnd1_end = ABSOLUTE(.); - } >wnd1 :wnd1_phdr - - .wnd2 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd2_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN2_SIZE; - _wnd2_end = ABSOLUTE(.); - } >wnd2 :wnd2_phdr - - .wnd3 (NOLOAD) : ALIGN(8) - { - . = ALIGN (32); - _wnd3_start = ABSOLUTE(.); - . = . + HP_SRAM_WIN3_SIZE; - _wnd3_end = ABSOLUTE(.); - } >wnd3 :wnd3_phdr - - .WindowVectors.text : ALIGN(4) - { - _WindowVectors_text_start = ABSOLUTE(.); - KEEP (*(.WindowVectors.text)) - _WindowVectors_text_end = ABSOLUTE(.); - } >vector_base_text :vector_base_text_phdr - - .Level2InterruptVector.literal : ALIGN(4) - { - _Level2InterruptVector_literal_start = ABSOLUTE(.); - *(.Level2InterruptVector.literal) - _Level2InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int2_lit :vector_int2_lit_phdr - - .Level2InterruptVector.text : ALIGN(4) - { - _Level2InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level2InterruptVector.text)) - _Level2InterruptVector_text_end = ABSOLUTE(.); - } >vector_int2_text :vector_int2_text_phdr - - .Level3InterruptVector.literal : ALIGN(4) - { - _Level3InterruptVector_literal_start = ABSOLUTE(.); - *(.Level3InterruptVector.literal) - _Level3InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int3_lit :vector_int3_lit_phdr - - .Level3InterruptVector.text : ALIGN(4) - { - _Level3InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level3InterruptVector.text)) - _Level3InterruptVector_text_end = ABSOLUTE(.); - } >vector_int3_text :vector_int3_text_phdr - - .Level4InterruptVector.literal : ALIGN(4) - { - _Level4InterruptVector_literal_start = ABSOLUTE(.); - *(.Level4InterruptVector.literal) - _Level4InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int4_lit :vector_int4_lit_phdr - - .Level4InterruptVector.text : ALIGN(4) - { - _Level4InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level4InterruptVector.text)) - _Level4InterruptVector_text_end = ABSOLUTE(.); - } >vector_int4_text :vector_int4_text_phdr - - .Level5InterruptVector.literal : ALIGN(4) - { - _Level5InterruptVector_literal_start = ABSOLUTE(.); - *(.Level5InterruptVector.literal) - _Level5InterruptVector_literal_end = ABSOLUTE(.); - } >vector_int5_lit :vector_int5_lit_phdr - - .Level5InterruptVector.text : ALIGN(4) - { - _Level5InterruptVector_text_start = ABSOLUTE(.); - KEEP (*(.Level5InterruptVector.text)) - _Level5InterruptVector_text_end = ABSOLUTE(.); - } >vector_int5_text :vector_int5_text_phdr - - .DebugExceptionVector.literal : ALIGN(4) - { - _DebugExceptionVector_literal_start = ABSOLUTE(.); - *(.DebugExceptionVector.literal) - _DebugExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int6_lit :vector_int6_lit_phdr - - .DebugExceptionVector.text : ALIGN(4) - { - _DebugExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DebugExceptionVector.text)) - _DebugExceptionVector_text_end = ABSOLUTE(.); - } >vector_int6_text :vector_int6_text_phdr - - .NMIExceptionVector.literal : ALIGN(4) - { - _NMIExceptionVector_literal_start = ABSOLUTE(.); - *(.NMIExceptionVector.literal) - _NMIExceptionVector_literal_end = ABSOLUTE(.); - } >vector_int7_lit :vector_int7_lit_phdr - - .NMIExceptionVector.text : ALIGN(4) - { - _NMIExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.NMIExceptionVector.text)) - _NMIExceptionVector_text_end = ABSOLUTE(.); - } >vector_int7_text :vector_int7_text_phdr - - .KernelExceptionVector.literal : ALIGN(4) - { - _KernelExceptionVector_literal_start = ABSOLUTE(.); - *(.KernelExceptionVector.literal) - _KernelExceptionVector_literal_end = ABSOLUTE(.); - } >vector_kernel_lit :vector_kernel_lit_phdr - - .KernelExceptionVector.text : ALIGN(4) - { - _KernelExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.KernelExceptionVector.text)) - _KernelExceptionVector_text_end = ABSOLUTE(.); - } >vector_kernel_text :vector_kernel_text_phdr - - .UserExceptionVector.literal : ALIGN(4) - { - _UserExceptionVector_literal_start = ABSOLUTE(.); - *(.UserExceptionVector.literal) - _UserExceptionVector_literal_end = ABSOLUTE(.); - } >vector_user_lit :vector_user_lit_phdr - - .UserExceptionVector.text : ALIGN(4) - { - _UserExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.UserExceptionVector.text)) - _UserExceptionVector_text_end = ABSOLUTE(.); - } >vector_user_text :vector_user_text_phdr - - .DoubleExceptionVector.literal : ALIGN(4) - { - _DoubleExceptionVector_literal_start = ABSOLUTE(.); - *(.DoubleExceptionVector.literal) - _DoubleExceptionVector_literal_end = ABSOLUTE(.); - } >vector_double_lit :vector_double_lit_phdr - - .DoubleExceptionVector.text : ALIGN(4) - { - _DoubleExceptionVector_text_start = ABSOLUTE(.); - KEEP (*(.DoubleExceptionVector.text)) - _DoubleExceptionVector_text_end = ABSOLUTE(.); - } >vector_double_text :vector_double_text_phdr - - .text : ALIGN(4) - { - _stext = .; - _text_start = ABSOLUTE(.); - KEEP (*(.MainEntry.text)) - *(.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) - KEEP (*(.ResetHandler.text)) - _text_end = ABSOLUTE(.); - _etext = .; - } >sof_fw :sof_fw_phdr - - .rodata : ALIGN(4096) - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.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 */ - _bss_table_start = ABSOLUTE(.); - LONG(_bss_start) - LONG(_bss_end) - _bss_table_end = ABSOLUTE(.); - _rodata_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .module_init : ALIGN(4) - { - _module_init_start = ABSOLUTE(.); - *(*.module_init) - _module_init_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .shared_data : ALIGN(PLATFORM_DCACHE_ALIGN) - { - _shared_data_start = ABSOLUTE(.); - *(*.shared_data) - _shared_data_end = ABSOLUTE(.); - . = ALIGN(PLATFORM_DCACHE_ALIGN); - } >sof_fw :sof_fw_phdr - - .data : ALIGN(4) - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - KEEP(*(.gnu.linkonce.d.*personality*)) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - KEEP(*(.jcr)) - _data_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .lit4 : ALIGN(4) - { - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - .fw_ready : ALIGN(4) - { - KEEP (*(.fw_ready)) - KEEP (*(.fw_ready_metadata)) - } >sof_fw :sof_fw_phdr - - .bss (NOLOAD) : ALIGN(4096) - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - - . = ALIGN (SRAM_BANK_SIZE); - _runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_RUNTIME_SIZE; - _runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _buffer_heap_start = ABSOLUTE(.); - . = . + HEAP_BUFFER_SIZE; - _buffer_heap_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _system_heap_start = ABSOLUTE(.); - . = . + HEAP_SYSTEM_M_SIZE; - _system_heap_end = ABSOLUTE(.); - - . = ALIGN (HEAP_BUF_ALIGNMENT); - _system_runtime_heap_start = ABSOLUTE(.); - . = . + HEAP_SYS_RUNTIME_M_SIZE; - _system_runtime_heap_end = ABSOLUTE(.); - - . = ALIGN (4096); - _sof_stack_start = ABSOLUTE(.); - . = . + SOF_STACK_SIZE; - _sof_stack_end = ABSOLUTE(.); - - . = ALIGN (SRAM_BANK_SIZE); - _sof_core_s_start = ABSOLUTE(.); - . = . + SOF_CORE_S_T_SIZE; - _sof_core_s_end = ABSOLUTE(.); - - _bss_end = ABSOLUTE(.); - } >sof_fw :sof_fw_phdr - - /* stack */ - _end = _sof_stack_start; - PROVIDE(end = _sof_stack_start); - _stack_sentry = _sof_stack_start; - __stack = _sof_stack_end; - - /* Slave core size */ - _core_s_size = SOF_CORE_S_SIZE; - - /* System Heap */ - _system_heap = _system_heap_start; - - /* system runtime heap */ - _system_runtime_heap = _system_runtime_heap_start; - - /* module heap */ - _module_heap = _runtime_heap_start; - - /* buffer heap */ - _buffer_heap = _buffer_heap_start; - _buffer_heap_end = _buffer_heap_end; - - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - .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.*)) - } - - .static_uuid_entries (COPY) : ALIGN(1024) - { - *(*.static_uuids) - } > static_uuid_entries_seg :static_uuid_entries_phdr - - .static_log_entries (COPY) : ALIGN(1024) - { - *(*.static_log*) - } > static_log_entries_seg :static_log_entries_phdr - - .lpsram(NOLOAD) : ALIGN(8) - { - _lpsram_start = ABSOLUTE(.); - KEEP (*(*.lpsram)) - _lpsram_end = ABSOLUTE(.); - } >lpsram_mem :lpsram_mem_phdr - -} diff --git a/src/probe/CMakeLists.txt b/src/probe/CMakeLists.txt index e12e3554b94f..4cbc818513dd 100644 --- a/src/probe/CMakeLists.txt +++ b/src/probe/CMakeLists.txt @@ -1,3 +1,8 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof probe.c) +if(CONFIG_PROBE STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(llext ${PROJECT_BINARY_DIR}/probe_llext) + add_dependencies(app probe) +elseif(CONFIG_PROBE) + add_local_sources(sof probe.c) +endif() diff --git a/src/probe/Kconfig b/src/probe/Kconfig index 21374ec80a92..a45947ab5181 100644 --- a/src/probe/Kconfig +++ b/src/probe/Kconfig @@ -5,11 +5,14 @@ menu "Probe" config PROBE - bool "Probes enabled" - default n + tristate "Probes enabled" + default m if LIBRARY_DEFAULT_MODULAR + default y if CAVS help Select for enabling debug probes to extract/inject buffers +if PROBE != n + config PROBE_POINTS_MAX int "Maximum probe points" depends on PROBE @@ -20,7 +23,10 @@ config PROBE_POINTS_MAX config PROBE_DMA_MAX int "Maximum injection probe DMAs attached" depends on PROBE - default 4 + default 0 help Define maximum number of injection DMAs. + +endif + endmenu diff --git a/src/probe/llext/CMakeLists.txt b/src/probe/llext/CMakeLists.txt new file mode 100644 index 000000000000..c77ad93ee88d --- /dev/null +++ b/src/probe/llext/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("probe" + SOURCES ../probe.c +) diff --git a/src/probe/llext/llext.toml.h b/src/probe/llext/llext.toml.h new file mode 100644 index 000000000000..4567111f4c52 --- /dev/null +++ b/src/probe/llext/llext.toml.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../probe.toml" + +[module] +count = __COUNTER__ diff --git a/src/probe/probe.c b/src/probe/probe.c index b7f18a26c0b1..19f62bf81a14 100644 --- a/src/probe/probe.c +++ b/src/probe/probe.c @@ -1,37 +1,55 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2019 Intel Corporation. All rights reserved. +// Copyright(c) 2019-2022 Intel Corporation. All rights reserved. // // Author: Artur Kloniecki <arturx.kloniecki@linux.intel.com> // Author: Adrian Bonislawski <adrian.bonislawski@linux.intel.com> -#include <config.h> #include <sof/audio/buffer.h> #include <sof/audio/component.h> #include <sof/probe/probe.h> #include <sof/trace/trace.h> #include <user/trace.h> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> +#include <rtos/init.h> #include <sof/lib/dma.h> -#include <sof/lib/notifier.h> -#include <ipc/topology.h> -#include <sof/drivers/ipc.h> -#include <sof/drivers/timer.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/driver.h> +#include <rtos/timer.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> +#include <rtos/task.h> +#include <rtos/string_macro.h> +#if CONFIG_IPC_MAJOR_4 +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc4/gateway.h> +#include <ipc4/module.h> +#include <sof/audio/component.h> +#include <sof/audio/component_ext.h> +#include <sof/ut.h> + +SOF_DEFINE_REG_UUID(probe4); +#define PROBE_UUID probe4_uuid + +#elif CONFIG_IPC_MAJOR_3 +SOF_DEFINE_REG_UUID(probe); +#define PROBE_UUID probe_uuid + +#else +#error "No or invalid IPC MAJOR version selected." +#endif /* CONFIG_IPC_MAJOR_4 */ + +DECLARE_TR_CTX(pr_tr, SOF_UUID(PROBE_UUID), LOG_LEVEL_INFO); -#define trace_probe(__e, ...) \ - trace_event(TRACE_CLASS_PROBE, __e, ##__VA_ARGS__) -#define tracev_probe(__e, ...) \ - tracev_event(TRACE_CLASS_PROBE, __e, ##__VA_ARGS__) -#define trace_probe_error(__e, ...) \ - trace_error(TRACE_CLASS_PROBE, __e, ##__VA_ARGS__) +SOF_DEFINE_REG_UUID(probe_task); + +LOG_MODULE_REGISTER(probe, CONFIG_SOF_LOG_LEVEL); #define PROBE_DMA_INVALID 0xFFFFFFFF #define PROBE_POINT_INVALID 0xFFFFFFFF -#define PROBE_BUFFER_LOCAL_SIZE 8192 +#define PROBE_BUFFER_LOCAL_SIZE 8192 #define DMA_ELEM_SIZE 32 /** @@ -61,33 +79,34 @@ struct probe_dma_ext { * Probe main struct */ struct probe_pdata { + struct task dmap_work; /**< probe task */ struct probe_dma_ext ext_dma; /**< extraction DMA */ struct probe_dma_ext inject_dma[CONFIG_PROBE_DMA_MAX]; /**< injection DMA */ struct probe_point probe_points[CONFIG_PROBE_POINTS_MAX]; /**< probe points */ struct probe_data_packet header; /**< data packet header */ - struct task dmap_work; /**< probe task */ }; /** * \brief Allocate and initialize probe buffer with correct alignment. - * \param[out] probe buffer. - * \param[in] buffer size. - * \param[in] buffer address alignment. + * \param[out] buffer return value. + * \param[in] size of buffer. + * \param[in] align the buffer. * \return 0 on success, error code otherwise. */ -static int probe_dma_buffer_init(struct probe_dma_buf *buffer, uint32_t size, uint32_t align) +static int probe_dma_buffer_init(struct probe_dma_buf *buffer, uint32_t size, + uint32_t align) { /* allocate new buffer */ - buffer->addr = (uintptr_t)rballoc_align(SOF_MEM_ZONE_BUFFER, - SOF_MEM_CAPS_DMA, size, align); + buffer->addr = (uintptr_t)rballoc_align(0 | SOF_MEM_FLAG_DMA, + size, align); if (!buffer->addr) { - trace_probe_error("probe_dma_buffer_init() error: alloc failed"); + tr_err(&pr_tr, "alloc failed"); return -ENOMEM; } bzero((void *)buffer->addr, size); - dcache_writeback_region((void *)buffer->addr, size); + dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->addr, size); /* initialise the DMA buffer */ buffer->size = size; @@ -99,32 +118,44 @@ static int probe_dma_buffer_init(struct probe_dma_buf *buffer, uint32_t size, ui return 0; } +#if !CONFIG_ZEPHYR_NATIVE_DRIVERS /** * \brief Request DMA and initialize DMA for probes with correct alignment, * size and specific channel. - * \param[out] probe DMA. - * \param[in] direction. + * + * \param[out] dma probe returned + * \param[in] direction of the DMA * \return 0 on success, error code otherwise. */ static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) { - struct dma_sg_config config; uint32_t elem_addr, addr_align; const uint32_t elem_size = sizeof(uint64_t) * DMA_ELEM_SIZE; const uint32_t elem_num = PROBE_BUFFER_LOCAL_SIZE / elem_size; + uint32_t channel; int err = 0; +#if CONFIG_IPC_MAJOR_4 + channel = ((union ipc4_connector_node_id)dma->stream_tag).f.v_index + 1; +#else + channel = dma->stream_tag; +#endif /* request DMA in the dir LMEM->HMEM with shared access */ - dma->dc.dmac = dma_get(direction, 0, DMA_DEV_HOST, - DMA_ACCESS_SHARED); + dma->dc.dmac = dma_get(direction, 0, SOF_DMA_DEV_HOST, + SOF_DMA_ACCESS_SHARED); if (!dma->dc.dmac) { - trace_probe_error("probe_dma_init() error: dma->dc.dmac = NULL"); + tr_err(&pr_tr, "dma->dc.dmac = NULL"); return -ENODEV; } - + dma->dc.dmac->priv_data = &dma->dc.dmac->chan->index; /* get required address alignment for dma buffer */ - err = dma_get_attribute(dma->dc.dmac, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_get_attribute(dma->dc.dmac->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, &addr_align); +#else + err = dma_get_attribute_legacy(dma->dc.dmac, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); +#endif if (err < 0) return err; @@ -133,49 +164,113 @@ static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) if (err < 0) return err; - err = dma_copy_set_stream_tag(&dma->dc, dma->stream_tag); + err = dma_copy_set_stream_tag(&dma->dc, channel); if (err < 0) return err; elem_addr = (uint32_t)dma->dmapb.addr; - config.direction = direction; - config.src_width = sizeof(uint32_t); - config.dest_width = sizeof(uint32_t); - config.cyclic = 0; + dma->config.direction = direction; + dma->config.src_width = sizeof(uint32_t); + dma->config.dest_width = sizeof(uint32_t); + dma->config.cyclic = 0; - err = dma_sg_alloc(&config.elem_array, SOF_MEM_ZONE_RUNTIME, - config.direction, elem_num, elem_size, elem_addr, 0); + err = dma_sg_alloc(NULL, &dma->config.elem_array, SOF_MEM_FLAG_USER, + dma->config.direction, elem_num, elem_size, elem_addr, 0); if (err < 0) return err; - err = dma_set_config(dma->dc.chan, &config); + err = dma_set_config_legacy(dma->dc.chan, &dma->config); if (err < 0) return err; + return 0; +} +#else +static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) +{ + uint32_t addr_align; + uint32_t channel; + struct dma_config dma_cfg; + struct dma_block_config dma_block_cfg; + int err = 0; + + channel = ((union ipc4_connector_node_id)dma->stream_tag).f.v_index; + + /* request DMA in the dir LMEM->HMEM with shared access */ + dma->dc.dmac = sof_dma_get(direction, 0, SOF_DMA_DEV_HOST, + SOF_DMA_ACCESS_SHARED); + if (!dma->dc.dmac) { + tr_err(&pr_tr, "dma->dc.dmac = NULL"); + return -ENODEV; + } + + /* get required address alignment for dma buffer */ + err = dma_get_attribute(dma->dc.dmac->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (err < 0) + return err; + + channel = dma_request_channel(dma->dc.dmac->z_dev, &channel); + if (channel < 0) { + tr_err(&pr_tr, "dma_request_channel() failed"); + return -EINVAL; + } + dma->dc.chan = &dma->dc.dmac->chan[channel]; + + /* initialize dma buffer */ + err = probe_dma_buffer_init(&dma->dmapb, PROBE_BUFFER_LOCAL_SIZE, addr_align); + if (err < 0) + return err; + + dma_cfg.block_count = 1; + dma_cfg.source_data_size = sizeof(uint32_t); + dma_cfg.dest_data_size = sizeof(uint32_t); + dma_cfg.head_block = &dma_block_cfg; + dma_block_cfg.block_size = (uint32_t)dma->dmapb.size; - dma_sg_free(&config.elem_array); + switch (direction) { + case SOF_DMA_DIR_LMEM_TO_HMEM: + dma_cfg.channel_direction = MEMORY_TO_HOST; + dma_block_cfg.source_address = (uint32_t)dma->dmapb.addr; + break; + case SOF_DMA_DIR_HMEM_TO_LMEM: + dma_cfg.channel_direction = HOST_TO_MEMORY; + dma_block_cfg.dest_address = (uint32_t)dma->dmapb.addr; + break; + } + err = dma_config(dma->dc.dmac->z_dev, dma->dc.chan->index, &dma_cfg); + if (err < 0) + return err; return 0; } - +#endif /** * \brief Stop, deinit and free DMA and buffer used by probes. - * \param[out] probe DMA. + * * \return 0 on success, error code otherwise. */ static int probe_dma_deinit(struct probe_dma_ext *dma) { int err = 0; - - err = dma_stop(dma->dc.chan); + dma_sg_free(NULL, &dma->config.elem_array); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_stop(dma->dc.dmac->z_dev, dma->dc.chan->index); +#else + err = dma_stop_legacy(dma->dc.chan); +#endif if (err < 0) { - trace_probe_error("probe_dma_deinit() error: dma_stop() failed"); + tr_err(&pr_tr, "dma_stop() failed"); return err; } - - dma_channel_put(dma->dc.chan); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + dma_release_channel(dma->dc.dmac->z_dev, dma->dc.chan->index); + sof_dma_put(dma->dc.dmac); +#else + dma_channel_put_legacy(dma->dc.chan); dma_put(dma->dc.dmac); +#endif rfree((void *)dma->dmapb.addr); dma->dmapb.addr = 0; @@ -194,89 +289,151 @@ static int probe_dma_deinit(struct probe_dma_ext *dma) static enum task_state probe_task(void *data) { struct probe_pdata *_probe = probe_get(); + uint32_t copy_align, avail; int err; - if (_probe->ext_dma.dmapb.avail > 0) + if (!_probe->ext_dma.dmapb.avail) + return SOF_TASK_STATE_RESCHEDULE; +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_get_attribute(_probe->ext_dma.dc.dmac->z_dev, DMA_ATTR_COPY_ALIGNMENT, + ©_align); +#else + err = dma_get_attribute_legacy(_probe->ext_dma.dc.dmac, DMA_ATTR_COPY_ALIGNMENT, + ©_align); +#endif + if (err < 0) { + tr_err(&pr_tr, "dma_get_attribute failed."); + return SOF_TASK_STATE_COMPLETED; + } + + avail = ALIGN_DOWN(_probe->ext_dma.dmapb.avail, copy_align); + if (avail + _probe->ext_dma.dmapb.r_ptr >= _probe->ext_dma.dmapb.end_addr) + avail = _probe->ext_dma.dmapb.end_addr - _probe->ext_dma.dmapb.r_ptr; + + if (avail > 0) +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_reload(_probe->ext_dma.dc.dmac->z_dev, + _probe->ext_dma.dc.chan->index, 0, 0, avail); +#else err = dma_copy_to_host_nowait(&_probe->ext_dma.dc, &_probe->ext_dma.config, 0, - (void *)_probe->ext_dma.dmapb.r_ptr, - _probe->ext_dma.dmapb.avail); + (void *)_probe->ext_dma.dmapb.r_ptr, + avail); +#endif else return SOF_TASK_STATE_RESCHEDULE; if (err < 0) { - trace_probe_error("probe_task() error: dma_copy_to_host_nowait() failed."); + tr_err(&pr_tr, "dma_copy_to_host() failed."); return err; } /* buffer data sent, set read pointer and clear avail bytes */ - _probe->ext_dma.dmapb.r_ptr = _probe->ext_dma.dmapb.w_ptr; - _probe->ext_dma.dmapb.avail = 0; + _probe->ext_dma.dmapb.r_ptr += avail; + if (_probe->ext_dma.dmapb.r_ptr >= _probe->ext_dma.dmapb.end_addr) + _probe->ext_dma.dmapb.r_ptr -= _probe->ext_dma.dmapb.size; + _probe->ext_dma.dmapb.avail -= avail; return SOF_TASK_STATE_RESCHEDULE; } -int probe_init(struct probe_dma *probe_dma) +#if CONFIG_LOG_BACKEND_SOF_PROBE_OUTPUT_AUTO_ENABLE +static void probe_auto_enable_logs(uint32_t stream_tag) +{ + struct probe_point log_point = { +#if CONFIG_IPC_MAJOR_4 + .buffer_id = { + .full_id = 0, + }, +#else + .buffer_id = 0, +#endif + .purpose = PROBE_PURPOSE_EXTRACTION, + .stream_tag = stream_tag, + }; + int ret; + + ret = probe_point_add(1, &log_point); + + if (ret) + tr_err(&pr_tr, "failed"); +} +#endif + +int probe_init(const struct probe_dma *probe_dma) { struct probe_pdata *_probe = probe_get(); uint32_t i; int err; - tracev_probe("probe_init()"); + tr_dbg(&pr_tr, "entry"); if (_probe) { - trace_probe_error("probe_init() error: Probes already initialized."); + tr_err(&pr_tr, "Probes already initialized."); return -EINVAL; } /* alloc probes main struct */ - sof_get()->probe = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, + sof_get()->probe = rzalloc(SOF_MEM_FLAG_USER, sizeof(*_probe)); + if (!sof_get()->probe) { + tr_err(&pr_tr, "Alloc failed."); + return -ENOMEM; + } _probe = probe_get(); if (!_probe) { - trace_probe_error("probe_init() error: Alloc failed."); + tr_err(&pr_tr, "Alloc failed."); return -ENOMEM; } + /* initialize injection DMAs as invalid */ + for (i = 0; i < CONFIG_PROBE_DMA_MAX; i++) + _probe->inject_dma[i].stream_tag = PROBE_DMA_INVALID; + + /* initialize probe points as invalid */ + for (i = 0; i < CONFIG_PROBE_POINTS_MAX; i++) + _probe->probe_points[i].stream_tag = PROBE_POINT_INVALID; + /* setup extraction dma if requested */ if (probe_dma) { - tracev_probe("\tstream_tag = %u, dma_buffer_size = %u", - probe_dma->stream_tag, probe_dma->dma_buffer_size); + tr_dbg(&pr_tr, "\tstream_tag = %u, dma_buffer_size = %u", + probe_dma->stream_tag, probe_dma->dma_buffer_size); _probe->ext_dma.stream_tag = probe_dma->stream_tag; _probe->ext_dma.dma_buffer_size = probe_dma->dma_buffer_size; - err = probe_dma_init(&_probe->ext_dma, DMA_DIR_LMEM_TO_HMEM); + err = probe_dma_init(&_probe->ext_dma, SOF_DMA_DIR_LMEM_TO_HMEM); if (err < 0) { - trace_probe_error("probe_init() error: probe_dma_init() failed"); + tr_err(&pr_tr, "probe_dma_init() failed"); _probe->ext_dma.stream_tag = PROBE_DMA_INVALID; return err; } - - err = dma_start(_probe->ext_dma.dc.chan); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_start(_probe->ext_dma.dc.dmac->z_dev, _probe->ext_dma.dc.chan->index); +#else + err = dma_start_legacy(_probe->ext_dma.dc.chan); +#endif if (err < 0) { - trace_probe_error("probe_init() error: failed to start extraction dma"); + tr_err(&pr_tr, "failed to start extraction dma"); return -EBUSY; } /* init task for extraction probes */ - schedule_task_init_ll(&_probe->dmap_work, SOF_SCHEDULE_LL_TIMER, - SOF_TASK_PRI_LOW, probe_task, _probe, 0, 0); + schedule_task_init_ll(&_probe->dmap_work, + SOF_UUID(probe_task_uuid), + SOF_SCHEDULE_LL_TIMER, SOF_TASK_PRI_LOW, + probe_task, _probe, 0, 0); + +#if CONFIG_LOG_BACKEND_SOF_PROBE_OUTPUT_AUTO_ENABLE + probe_auto_enable_logs(probe_dma->stream_tag); +#endif } else { - tracev_probe("\tno extraction DMA setup"); + tr_dbg(&pr_tr, "\tno extraction DMA setup"); _probe->ext_dma.stream_tag = PROBE_DMA_INVALID; } - /* initialize injection DMAs as invalid */ - for (i = 0; i < CONFIG_PROBE_DMA_MAX; i++) - _probe->inject_dma[i].stream_tag = PROBE_DMA_INVALID; - - /* initialize probe points as invalid */ - for (i = 0; i < CONFIG_PROBE_POINTS_MAX; i++) - _probe->probe_points[i].stream_tag = PROBE_POINT_INVALID; - return 0; } @@ -286,10 +443,10 @@ int probe_deinit(void) uint32_t i; int err; - tracev_probe("probe_deinit()"); + tr_dbg(&pr_tr, "entry"); if (!_probe) { - trace_probe_error("probe_deinit() error: Not initialized."); + tr_err(&pr_tr, "Not initialized."); return -EINVAL; } @@ -297,7 +454,7 @@ int probe_deinit(void) /* check for attached injection probe DMAs */ for (i = 0; i < CONFIG_PROBE_DMA_MAX; i++) { if (_probe->inject_dma[i].stream_tag != PROBE_DMA_INVALID) { - trace_probe_error("probe_deinit() error: Cannot deinitialize with injection DMAs attached."); + tr_err(&pr_tr, "Cannot deinitialize with injection DMAs attached."); return -EINVAL; } } @@ -305,13 +462,13 @@ int probe_deinit(void) /* check for connected probe points */ for (i = 0; i < CONFIG_PROBE_POINTS_MAX; i++) { if (_probe->probe_points[i].stream_tag != PROBE_POINT_INVALID) { - trace_probe_error("probe_deinit() error: Cannot deinitialize with probe points connected."); + tr_err(&pr_tr, "Cannot deinitialize with probe points connected."); return -EINVAL; } } if (_probe->ext_dma.stream_tag != PROBE_DMA_INVALID) { - tracev_probe("probe_deinit() Freeing task and extraction DMA."); + tr_dbg(&pr_tr, "Freeing task and extraction DMA."); schedule_task_free(&_probe->dmap_work); err = probe_dma_deinit(&_probe->ext_dma); if (err < 0) @@ -324,7 +481,7 @@ int probe_deinit(void) return 0; } -int probe_dma_add(uint32_t count, struct probe_dma *probe_dma) +int probe_dma_add(uint32_t count, const struct probe_dma *probe_dma) { struct probe_pdata *_probe = probe_get(); uint32_t i; @@ -333,10 +490,10 @@ int probe_dma_add(uint32_t count, struct probe_dma *probe_dma) uint32_t first_free; int err; - tracev_probe("probe_dma_add() count = %u", count); + tr_dbg(&pr_tr, "count = %u", count); if (!_probe) { - trace_probe_error("probe_dma_add() error: Not initialized."); + tr_err(&pr_tr, "Not initialized."); return -EINVAL; } @@ -344,9 +501,9 @@ int probe_dma_add(uint32_t count, struct probe_dma *probe_dma) /* Iterate over all (DMA) fields if there are multiple of them */ /* add them if there is free place and they are not already attached */ for (i = 0; i < count; i++) { - tracev_probe("\tprobe_dma[%u] stream_tag = %u, dma_buffer_size = %u", - i, probe_dma[i].stream_tag, - probe_dma[i].dma_buffer_size); + tr_dbg(&pr_tr, "\tprobe_dma[%u] stream_tag = %u, dma_buffer_size = %u", + i, probe_dma[i].stream_tag, + probe_dma[i].dma_buffer_size); first_free = CONFIG_PROBE_DMA_MAX; @@ -362,14 +519,15 @@ int probe_dma_add(uint32_t count, struct probe_dma *probe_dma) } if (stream_tag == probe_dma[i].stream_tag) { - trace_probe_error("probe_dma_add() error: Probe DMA %u already attached.", - stream_tag); + tr_err(&pr_tr, "Probe DMA %u already attached.", + stream_tag); return -EINVAL; } } if (first_free == CONFIG_PROBE_DMA_MAX) { - trace_probe_error("probe_dma_add() error: Exceeded maximum number of DMAs attached = " META_QUOTE(CONFIG_PROBE_DMA_MAX)); + tr_err(&pr_tr, "Exceeded maximum number of DMAs attached = " + STRINGIFY(CONFIG_PROBE_DMA_MAX)); return -EINVAL; } @@ -379,9 +537,9 @@ int probe_dma_add(uint32_t count, struct probe_dma *probe_dma) probe_dma[i].dma_buffer_size; err = probe_dma_init(&_probe->inject_dma[first_free], - DMA_DIR_HMEM_TO_LMEM); + SOF_DMA_DIR_HMEM_TO_LMEM); if (err < 0) { - trace_probe_error("probe_dma_add() error: probe_dma_init() failed"); + tr_err(&pr_tr, "probe_dma_init() failed"); _probe->inject_dma[first_free].stream_tag = PROBE_DMA_INVALID; return err; @@ -391,47 +549,9 @@ int probe_dma_add(uint32_t count, struct probe_dma *probe_dma) return 0; } -int probe_dma_info(struct sof_ipc_probe_info_params *data, uint32_t max_size) -{ - struct probe_pdata *_probe = probe_get(); - uint32_t i = 0; - uint32_t j = 0; - - tracev_probe("probe_dma_info()"); - - if (!_probe) { - trace_probe_error("probe_dma_info() error: Not initialized."); - - return -EINVAL; - } - - data->rhdr.hdr.size = sizeof(*data); - - /* search all injection DMAs to send them in reply */ - while (i < CONFIG_PROBE_DMA_MAX && - data->rhdr.hdr.size + sizeof(struct probe_dma) < max_size) { - /* save it if valid */ - if (_probe->inject_dma[i].stream_tag != PROBE_DMA_INVALID) { - data->probe_dma[j].stream_tag = - _probe->inject_dma[i].stream_tag; - data->probe_dma[j].dma_buffer_size = - _probe->inject_dma[i].dma_buffer_size; - j++; - /* and increase reply header size */ - data->rhdr.hdr.size += sizeof(struct probe_dma); - } - - i++; - } - - data->num_elems = j; - - return 1; -} - /** * \brief Check if stream_tag is used by probes. - * \param[in] DMA stream_tag. + * \param[in] stream_tag DMA stream tag. * \return 0 if not used, 1 otherwise. */ static int is_probe_stream_used(uint32_t stream_tag) @@ -447,24 +567,24 @@ static int is_probe_stream_used(uint32_t stream_tag) return 0; } -int probe_dma_remove(uint32_t count, uint32_t *stream_tag) +int probe_dma_remove(uint32_t count, const uint32_t *stream_tag) { struct probe_pdata *_probe = probe_get(); uint32_t i; uint32_t j; int err; - tracev_probe("probe_dma_remove() count = %u", count); + tr_dbg(&pr_tr, "count = %u", count); if (!_probe) { - trace_probe_error("probe_dma_remove() error: Not initialized."); + tr_err(&pr_tr, "Not initialized."); return -EINVAL; } /* remove each DMA if they are not used */ for (i = 0; i < count; i++) { - tracev_probe("\tstream_tag[%u] = %u", i, stream_tag[i]); + tr_dbg(&pr_tr, "\tstream_tag[%u] = %u", i, stream_tag[i]); if (is_probe_stream_used(stream_tag[i])) return -EINVAL; @@ -483,12 +603,13 @@ int probe_dma_remove(uint32_t count, uint32_t *stream_tag) /** * \brief Copy data to probe buffer and update buffer pointers. - * \param[out] probe DMA buffer. + * \param[out] pbuf DMA buffer. * \param[in] data pointer. - * \param[in] size. + * \param[in] bytes size. * \return 0 on success, error code otherwise. */ -static int copy_to_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t bytes) +static int copy_to_pbuffer(struct probe_dma_buf *pbuf, void *data, + uint32_t bytes) { uint32_t head; uint32_t tail; @@ -496,6 +617,10 @@ static int copy_to_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t byte if (bytes == 0) return 0; + /* check if there is free room in probe buffer */ + if (pbuf->size - pbuf->avail < bytes) + return -EINVAL; + /* check if it will not exceed end_addr */ if ((char *)pbuf->end_addr - (char *)pbuf->w_ptr < bytes) { head = (char *)pbuf->end_addr - (char *)pbuf->w_ptr; @@ -507,20 +632,20 @@ static int copy_to_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t byte /* copy data to probe buffer */ if (memcpy_s((void *)pbuf->w_ptr, pbuf->end_addr - pbuf->w_ptr, data, head)) { - trace_probe_error("copy_to_pbuffer() error: memcpy_s() failed"); + tr_err(&pr_tr, "memcpy_s() failed"); return -EINVAL; } - dcache_writeback_region((void *)pbuf->w_ptr, head); + dcache_writeback_region((__sparse_force void __sparse_cache *)pbuf->w_ptr, head); /* buffer ended so needs to do a second copy */ if (tail) { pbuf->w_ptr = pbuf->addr; if (memcpy_s((void *)pbuf->w_ptr, (char *)pbuf->end_addr - (char *)pbuf->w_ptr, (char *)data + head, tail)) { - trace_probe_error("copy_to_pbuffer() error: memcpy_s() failed"); + tr_err(&pr_tr, "memcpy_s() failed"); return -EINVAL; } - dcache_writeback_region((void *)pbuf->w_ptr, tail); + dcache_writeback_region((__sparse_force void __sparse_cache *)pbuf->w_ptr, tail); pbuf->w_ptr = pbuf->w_ptr + tail; } else { pbuf->w_ptr = pbuf->w_ptr + head; @@ -533,12 +658,13 @@ static int copy_to_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t byte /** * \brief Copy data from probe buffer and update buffer pointers. - * \param[out] probe DMA buffer. + * \param[out] pbuf DMA buffer. * \param[out] data pointer. - * \param[in] size. + * \param[in] bytes size. * \return 0 on success, error code otherwise. */ -static int copy_from_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t bytes) +static int copy_from_pbuffer(struct probe_dma_buf *pbuf, void *data, + uint32_t bytes) { uint32_t head; uint32_t tail; @@ -561,9 +687,9 @@ static int copy_from_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t by } /* data from DMA so invalidate it */ - dcache_invalidate_region((void *)pbuf->r_ptr, head); + dcache_invalidate_region((__sparse_force void __sparse_cache *)pbuf->r_ptr, head); if (memcpy_s(data, bytes, (void *)pbuf->r_ptr, head)) { - trace_probe_error("copy_from_pbuffer() error: memcpy_s() failed"); + tr_err(&pr_tr, "memcpy_s() failed"); return -EINVAL; } @@ -571,9 +697,9 @@ static int copy_from_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t by if (tail) { /* starting from the beginning of the buffer */ pbuf->r_ptr = pbuf->addr; - dcache_invalidate_region((void *)pbuf->r_ptr, tail); + dcache_invalidate_region((__sparse_force void __sparse_cache *)pbuf->r_ptr, tail); if (memcpy_s((char *)data + head, tail, (void *)pbuf->r_ptr, tail)) { - trace_probe_error("copy_from_pbuffer() error: memcpy_s() failed"); + tr_err(&pr_tr, "memcpy_s() failed"); return -EINVAL; } pbuf->r_ptr = pbuf->r_ptr + tail; @@ -590,34 +716,38 @@ static int copy_from_pbuffer(struct probe_dma_buf *pbuf, void *data, uint32_t by /** * \brief Generate probe data packet header, update timestamp, calc crc * and copy data to probe buffer. - * \param[in] component buffer pointer. - * \param[in] data size. - * \param[in] audio format. + * \param[in] buffer_id component buffer id + * \param[in] size data size. + * \param[in] format audio format. + * \param[out] checksum. * \return 0 on success, error code otherwise. */ -static int probe_gen_header(struct comp_buffer *buffer, uint32_t size, uint32_t format) +static int probe_gen_header(uint32_t buffer_id, uint32_t size, + uint32_t format, uint64_t *checksum) { struct probe_pdata *_probe = probe_get(); struct probe_data_packet *header; uint64_t timestamp; - uint32_t crc; header = &_probe->header; - timestamp = platform_timer_get(timer_get()); + timestamp = sof_cycle_get_64(); header->sync_word = PROBE_EXTRACT_SYNC_WORD; - header->buffer_id = buffer->id; + header->buffer_id = buffer_id; header->format = format; header->timestamp_low = (uint32_t)timestamp; header->timestamp_high = (uint32_t)(timestamp >> 32); - header->checksum = 0; header->data_size_bytes = size; - /* calc crc to check validation by probe parse app */ - crc = crc32(0, header, sizeof(*header)); - header->checksum = crc; + /* calc checksum to check validation by probe parse app */ + *checksum = header->sync_word + + header->buffer_id + + header->format + + header->timestamp_high + + header->timestamp_low + + header->data_size_bytes; - dcache_writeback_region(header, sizeof(*header)); + dcache_writeback_region((__sparse_force void __sparse_cache *)header, sizeof(*header)); return copy_to_pbuffer(&_probe->ext_dma.dmapb, header, sizeof(struct probe_data_packet)); @@ -625,12 +755,13 @@ static int probe_gen_header(struct comp_buffer *buffer, uint32_t size, uint32_t /** * \brief Generate description of audio format for extraction probes. - * \param[in] frame_fmt. - * \param[in] sample rate. - * \param[in] channels num. + * \param[in] frame_fmt format + * \param[in] rate sample rate. + * \param[in] channels number of channels * \return format. */ -static uint32_t probe_gen_format(uint32_t frame_fmt, uint32_t rate, uint32_t channels) +static uint32_t probe_gen_format(uint32_t frame_fmt, uint32_t rate, + uint32_t channels) { uint32_t format = 0; uint32_t sample_rate; @@ -657,9 +788,9 @@ static uint32_t probe_gen_format(uint32_t frame_fmt, uint32_t rate, uint32_t cha float_fmt = 1; break; default: - trace_probe_error("probe_gen_format() error: Invalid frame format specified = 0x%08x", - frame_fmt); - assert(false); + tr_err(&pr_tr, "Invalid frame format specified = 0x%08x", + frame_fmt); + return 0; } switch (rate) { @@ -723,57 +854,98 @@ static uint32_t probe_gen_format(uint32_t frame_fmt, uint32_t rate, uint32_t cha return format; } +/* + * Check if more than 75% of buffer is already used, + * and if yes, rescheduled the probe task immediately. + */ +static void kick_probe_task(struct probe_pdata *_probe) +{ + if (_probe->ext_dma.dmapb.size - _probe->ext_dma.dmapb.avail < + _probe->ext_dma.dmapb.size >> 2) + reschedule_task(&_probe->dmap_work, 0); +} + +#if CONFIG_LOG_BACKEND_SOF_PROBE +static ssize_t probe_logging_hook(uint8_t *buffer, size_t length) +{ + struct probe_pdata *_probe = probe_get(); + uint64_t checksum; + size_t max_len; + int ret; + + max_len = _probe->ext_dma.dmapb.avail - sizeof(struct probe_data_packet) - sizeof(checksum); + length = MIN(max_len, length); + + ret = probe_gen_header(PROBE_LOGGING_BUFFER_ID, length, 0, &checksum); + if (ret < 0) + return ret; + + ret = copy_to_pbuffer(&_probe->ext_dma.dmapb, + buffer, length); + if (ret < 0) + return ret; + + ret = copy_to_pbuffer(&_probe->ext_dma.dmapb, + &checksum, sizeof(checksum)); + if (ret < 0) + return ret; + + kick_probe_task(_probe); + return length; +} +#endif + /** * \brief General extraction probe callback, called from buffer produce. * It will search for probe point connected to this buffer. * Extraction probe: generate format, header and copy data to probe buffer. * Injection probe: find corresponding DMA, check avail data, copy data, * update pointers and request more data from host if needed. - * \param[in] arg pointer (not used). - * \param[in] type of notify. - * \param[in] data pointer. + * \param[in] arg pointer to buffer_id. + * \param[in] cb_data pointer to buffer callback transaction data. */ -static void probe_cb_produce(void *arg, enum notify_id type, void *data) +static void probe_cb_produce(void *arg, struct buffer_cb_transact *cb_data) { struct probe_pdata *_probe = probe_get(); - struct buffer_cb_transact *cb_data = data; struct comp_buffer *buffer = cb_data->buffer; struct probe_dma_ext *dma; uint32_t buffer_id; uint32_t head, tail; uint32_t free_bytes = 0; int32_t copy_bytes = 0; - uint32_t ret, i, j; + int ret; + uint32_t i, j; uint32_t format; + uint64_t checksum; - buffer_id = buffer->id; + buffer_id = *(uint32_t *)arg; /* search for probe point connected to this buffer */ for (i = 0; i < CONFIG_PROBE_POINTS_MAX; i++) - if (_probe->probe_points[i].buffer_id == buffer_id) + if (_probe->probe_points[i].buffer_id.full_id == buffer_id) break; if (i == CONFIG_PROBE_POINTS_MAX) { - trace_probe_error("probe_cb_produce() error: probe not found for buffer id: %d", - buffer_id); + tr_err(&pr_tr, "probe not found for buffer id: %d", + buffer_id); return; } if (_probe->probe_points[i].purpose == PROBE_PURPOSE_EXTRACTION) { - format = probe_gen_format(buffer->stream.frame_fmt, - buffer->stream.rate, - buffer->stream.channels); - ret = probe_gen_header(buffer, + 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); + format, &checksum); if (ret < 0) goto err; /* 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, @@ -783,7 +955,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 { @@ -793,6 +965,13 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) if (ret < 0) goto err; } + + ret = copy_to_pbuffer(&_probe->ext_dma.dmapb, + &checksum, sizeof(checksum)); + if (ret < 0) + goto err; + + kick_probe_task(_probe); } else { /* search for DMA used by this probe point */ for (j = 0; j < CONFIG_PROBE_DMA_MAX; j++) { @@ -804,25 +983,33 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) } } if (j == CONFIG_PROBE_DMA_MAX) { - trace_probe_error("probe_cb_produce() error: dma not found"); + tr_err(&pr_tr, "dma not found"); return; } dma = &_probe->inject_dma[j]; /* get avail data info */ - ret = dma_get_data_size(dma->dc.chan, - &dma->dmapb.avail, - &free_bytes); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + struct dma_status stat; + + ret = dma_get_status(dma->dc.dmac->z_dev, dma->dc.chan->index, &stat); + dma->dmapb.avail = stat.pending_length; + free_bytes = stat.free; +#else + ret = dma_get_data_size_legacy(dma->dc.chan, + &dma->dmapb.avail, + &free_bytes); +#endif if (ret < 0) { - trace_probe_error("probe_cb_produce() error: dma_get_data_size() failed, ret = %u", - ret); + tr_err(&pr_tr, "dma_get_data_size() failed, ret = %u", + ret); goto err; } /* 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 *)cb_data->buffer->stream.end_addr) { - head = (char *)cb_data->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; @@ -832,7 +1019,7 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) goto err; ret = copy_from_pbuffer(&dma->dmapb, - cb_data->buffer->stream.addr, tail); + audio_stream_get_addr(&buffer->stream), tail); if (ret < 0) goto err; } else { @@ -853,10 +1040,15 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) /* check if copy_bytes is still valid for dma copy */ if (copy_bytes > 0) { +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + ret = dma_reload(dma->dc.dmac->z_dev, + dma->dc.chan->index, 0, 0, copy_bytes); +#else ret = dma_copy_to_host_nowait(&dma->dc, &dma->config, 0, (void *)dma->dmapb.r_ptr, copy_bytes); +#endif if (ret < 0) goto err; @@ -868,29 +1060,84 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) } return; err: - trace_probe_error("probe_cb_produce() error: failed to generate probe data"); + tr_err(&pr_tr, "failed to generate probe data"); } /** * \brief Callback for buffer free, it will remove probe point. - * \param[in] arg pointer (not used). - * \param[in] type of notify. - * \param[in] data pointer. + * \param[in] arg pointer to buffer_id. */ -static void probe_cb_free(void *arg, enum notify_id type, void *data) +static void probe_cb_free(void *arg) { - struct buffer_cb_free *cb_data = data; - uint32_t buffer_id = cb_data->buffer->id; - uint32_t ret; + uint32_t buffer_id = *(uint32_t *)arg; + int ret; - tracev_probe("probe_cb_free() buffer_id = %u", buffer_id); + tr_dbg(&pr_tr, "buffer_id = %u", buffer_id); ret = probe_point_remove(1, &buffer_id); if (ret < 0) - trace_probe_error("probe_cb_free() error: probe_point_remove() failed"); + tr_err(&pr_tr, "probe_point_remove() failed"); +} + +static bool probe_purpose_needs_ext_dma(uint32_t purpose) +{ +#if CONFIG_IPC_MAJOR_4 + return purpose == PROBE_PURPOSE_EXTRACTION; +#else + return purpose == PROBE_PURPOSE_EXTRACTION || purpose == PROBE_PURPOSE_LOGGING; +#endif } -int probe_point_add(uint32_t count, struct probe_point *probe) +#if CONFIG_IPC_MAJOR_4 +static struct comp_buffer *ipc4_get_buffer(struct ipc_comp_dev *dev, probe_point_id_t probe_point) +{ + struct comp_buffer *buf; + unsigned int queue_id; + + switch (probe_point.fields.type) { + case PROBE_TYPE_INPUT: + comp_dev_for_each_producer(dev->cd, buf) { + queue_id = IPC4_SINK_QUEUE_ID(buf_get_id(buf)); + + if (queue_id == probe_point.fields.index) + return buf; + } + break; + case PROBE_TYPE_OUTPUT: + comp_dev_for_each_consumer(dev->cd, buf) { + queue_id = IPC4_SRC_QUEUE_ID(buf_get_id(buf)); + + if (queue_id == probe_point.fields.index) + return buf; + } + } + + return NULL; +} +#endif + +static bool enable_logs(const struct probe_point *probe) +{ +#if CONFIG_IPC_MAJOR_4 + return probe->buffer_id.full_id == 0; +#else + return probe->purpose == PROBE_PURPOSE_LOGGING; +#endif +} + +static bool verify_purpose(uint32_t purpose) +{ +#if CONFIG_IPC_MAJOR_4 + return purpose == PROBE_PURPOSE_EXTRACTION || + purpose == PROBE_PURPOSE_INJECTION; +#else + return purpose == PROBE_PURPOSE_EXTRACTION || + purpose == PROBE_PURPOSE_INJECTION || + purpose == PROBE_PURPOSE_LOGGING; +#endif +} + +int probe_point_add(uint32_t count, const struct probe_point *probe) { struct probe_pdata *_probe = probe_get(); uint32_t i; @@ -898,43 +1145,74 @@ int probe_point_add(uint32_t count, struct probe_point *probe) uint32_t buffer_id; uint32_t first_free; uint32_t dma_found; - struct ipc_comp_dev *dev; - - tracev_probe("probe_point_add() count = %u", count); + uint32_t fw_logs; + struct ipc_comp_dev *dev = NULL; +#if CONFIG_IPC_MAJOR_4 + struct comp_buffer *buf = NULL; +#endif + tr_dbg(&pr_tr, "count = %u", count); if (!_probe) { - trace_probe_error("probe_point_add() error: Not initialized."); + tr_err(&pr_tr, "Not initialized."); return -EINVAL; } /* add all probe points if they are corresponding to valid component and DMA */ for (i = 0; i < count; i++) { - tracev_probe("\tprobe[%u] buffer_id = %u, purpose = %u, stream_tag = %u", - i, probe[i].buffer_id, probe[i].purpose, - probe[i].stream_tag); + const probe_point_id_t *buf_id = &probe[i].buffer_id; + uint32_t stream_tag; + + tr_dbg(&pr_tr, "\tprobe[%u] buffer_id = %u, purpose = %u, stream_tag = %u", + i, buf_id->full_id, probe[i].purpose, + probe[i].stream_tag); - if (probe[i].purpose == PROBE_PURPOSE_EXTRACTION && - _probe->ext_dma.stream_tag == PROBE_DMA_INVALID) { - trace_probe_error("probe_point_add() error: Setting probe for extraction, while extraction DMA not enabled."); + if (!verify_purpose(probe[i].purpose)) { + tr_err(&pr_tr, "error: invalid purpose %d", + probe[i].purpose); return -EINVAL; } - /* check if buffer exists */ - dev = ipc_get_comp_by_id(ipc_get(), probe[i].buffer_id); - if (!dev) { - trace_probe_error("probe_point_add() error: No device with ID %u found.", - probe[i].buffer_id); - + if (_probe->ext_dma.stream_tag == PROBE_DMA_INVALID && + probe_purpose_needs_ext_dma(probe[i].purpose)) { + tr_err(&pr_tr, "extraction DMA not enabled."); return -EINVAL; } - if (dev->type != COMP_TYPE_BUFFER) { - trace_probe_error("probe_point_add() error: Device ID %u is not a buffer.", - probe[i].buffer_id); + fw_logs = enable_logs(&probe[i]); + + if (!fw_logs) { +#if CONFIG_IPC_MAJOR_4 + dev = ipc_get_comp_by_id(ipc_get(), + IPC4_COMP_ID(buf_id->fields.module_id, + buf_id->fields.instance_id)); +#else + dev = ipc_get_comp_by_id(ipc_get(), buf_id->full_id); +#endif + /* check if buffer exists */ + if (!dev) { + tr_err(&pr_tr, "No device with ID %u found.", + buf_id->full_id); - return -EINVAL; + return -EINVAL; + } +#if CONFIG_IPC_MAJOR_4 + buf = ipc4_get_buffer(dev, *buf_id); + if (!buf) { + tr_err(&pr_tr, "buffer %u not found.", + buf_id->full_id); + + return -EINVAL; + } +#else + if (dev->type != COMP_TYPE_BUFFER) { + tr_err(&pr_tr, "Device ID %u is not a buffer.", + buf_id->full_id); + + return -EINVAL; + } +#endif } first_free = CONFIG_PROBE_POINTS_MAX; @@ -949,13 +1227,13 @@ int probe_point_add(uint32_t count, struct probe_point *probe) continue; } /* and check if probe is already attached */ - buffer_id = _probe->probe_points[j].buffer_id; - if (buffer_id == probe[i].buffer_id) { + buffer_id = _probe->probe_points[j].buffer_id.full_id; + if (buffer_id == buf_id->full_id) { if (_probe->probe_points[j].purpose == probe[i].purpose) { - trace_probe_error("probe_point_add() error: Probe already attached to buffer %u with purpose %u", - buffer_id, - probe[i].purpose); + tr_err(&pr_tr, "Probe already attached to buffer %u with purpose %u", + buffer_id, + probe[i].purpose); return -EINVAL; } @@ -963,7 +1241,8 @@ int probe_point_add(uint32_t count, struct probe_point *probe) } if (first_free == CONFIG_PROBE_POINTS_MAX) { - trace_probe_error("probe_point_add() error: Maximum number of probe points connected aleady: " META_QUOTE(CONFIG_PROBE_POINTS_MAX)); + tr_err(&pr_tr, "Maximum number of probe points connected aleady: " + STRINGIFY(CONFIG_PROBE_POINTS_MAX)); return -EINVAL; } @@ -983,53 +1262,116 @@ int probe_point_add(uint32_t count, struct probe_point *probe) } if (!dma_found) { - trace_probe_error("probe_point_add() error: No DMA with stream tag %u found for injection.", - probe[i].stream_tag); + tr_err(&pr_tr, "No DMA with stream tag %u found for injection.", + probe[i].stream_tag); return -EINVAL; } - if (dma_start(_probe->inject_dma[j].dc.chan) < 0) { - trace_probe_error("probe_point_add() error: failed to start dma"); +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + if (dma_start(_probe->inject_dma[j].dc.dmac->z_dev, + _probe->inject_dma[j].dc.chan->index) < 0) { +#else + if (dma_start_legacy(_probe->inject_dma[j].dc.chan) < 0) { +#endif + tr_err(&pr_tr, "failed to start dma"); return -EBUSY; } - } else if (probe[i].purpose == PROBE_PURPOSE_EXTRACTION) { + + stream_tag = probe[i].stream_tag; + } else { + /* prepare extraction DMA */ for (j = 0; j < CONFIG_PROBE_POINTS_MAX; j++) { if (_probe->probe_points[j].stream_tag != PROBE_DMA_INVALID && - _probe->probe_points[j].purpose == PROBE_PURPOSE_EXTRACTION) + probe_purpose_needs_ext_dma(_probe->probe_points[j].purpose)) break; } + if (j == CONFIG_PROBE_POINTS_MAX) { - tracev_probe("probe_point_add(): start probe task"); + tr_dbg(&pr_tr, "start probe task"); schedule_task(&_probe->dmap_work, 1000, 1000); } + /* ignore probe stream tag for extraction probes */ + stream_tag = _probe->ext_dma.stream_tag; } /* probe point valid, save it */ - _probe->probe_points[first_free].buffer_id = probe[i].buffer_id; + _probe->probe_points[first_free].buffer_id = *buf_id; _probe->probe_points[first_free].purpose = probe[i].purpose; - _probe->probe_points[first_free].stream_tag = - probe[i].stream_tag; + _probe->probe_points[first_free].stream_tag = stream_tag; - notifier_register(_probe, dev->cb, NOTIFIER_ID_BUFFER_PRODUCE, - &probe_cb_produce); - notifier_register(_probe, dev->cb, NOTIFIER_ID_BUFFER_FREE, - &probe_cb_free); + if (fw_logs) { +#if CONFIG_LOG_BACKEND_SOF_PROBE + probe_logging_init(probe_logging_hook); +#else + return -EINVAL; +#endif + } else { + probe_point_id_t *new_buf_id = &_probe->probe_points[first_free].buffer_id; + +#if CONFIG_IPC_MAJOR_4 + struct comp_buffer *probe_buf = buf; +#else + struct comp_buffer *probe_buf = (struct comp_buffer *)dev->cb; +#endif + probe_buf->probe_cb_produce = probe_cb_produce; + probe_buf->probe_cb_free = probe_cb_free; + probe_buf->probe_cb_arg = &new_buf_id->full_id; + } } return 0; } +#if CONFIG_IPC_MAJOR_3 +int probe_dma_info(struct sof_ipc_probe_info_params *data, uint32_t max_size) +{ + struct probe_pdata *_probe = probe_get(); + uint32_t i = 0; + uint32_t j = 0; + + tr_dbg(&pr_tr, "entry"); + + if (!_probe) { + tr_err(&pr_tr, "Not initialized."); + + return -EINVAL; + } + + data->rhdr.hdr.size = sizeof(*data); + + /* search all injection DMAs to send them in reply */ + while (i < CONFIG_PROBE_DMA_MAX && + data->rhdr.hdr.size + sizeof(struct probe_dma) < max_size) { + /* save it if valid */ + if (_probe->inject_dma[i].stream_tag != PROBE_DMA_INVALID) { + data->probe_dma[j].stream_tag = + _probe->inject_dma[i].stream_tag; + data->probe_dma[j].dma_buffer_size = + _probe->inject_dma[i].dma_buffer_size; + j++; + /* and increase reply header size */ + data->rhdr.hdr.size += sizeof(struct probe_dma); + } + + i++; + } + + data->num_elems = j; + + return 1; +} + int probe_point_info(struct sof_ipc_probe_info_params *data, uint32_t max_size) { struct probe_pdata *_probe = probe_get(); uint32_t i = 0; uint32_t j = 0; - tracev_probe("probe_point_info()"); + tr_dbg(&pr_tr, "entry"); if (!_probe) { - trace_probe_error("probe_point_info() error: Not initialized."); + tr_err(&pr_tr, "Not initialized."); return -EINVAL; } @@ -1056,35 +1398,60 @@ int probe_point_info(struct sof_ipc_probe_info_params *data, uint32_t max_size) return 1; } +#endif -int probe_point_remove(uint32_t count, uint32_t *buffer_id) +int probe_point_remove(uint32_t count, const uint32_t *buffer_id) { struct probe_pdata *_probe = probe_get(); struct ipc_comp_dev *dev; uint32_t i; uint32_t j; +#if CONFIG_IPC_MAJOR_4 + struct comp_buffer *buf; +#endif - tracev_probe("probe_point_remove() count = %u", count); + tr_dbg(&pr_tr, "count = %u", count); if (!_probe) { - trace_probe_error("probe_point_remove() error: Not initialized."); + tr_err(&pr_tr, "Not initialized."); return -EINVAL; } /* remove each requested probe point */ for (i = 0; i < count; i++) { - tracev_probe("\tbuffer_id[%u] = %u", i, buffer_id[i]); + tr_dbg(&pr_tr, "\tbuffer_id[%u] = %u", i, buffer_id[i]); for (j = 0; j < CONFIG_PROBE_POINTS_MAX; j++) { + probe_point_id_t *buf_id = &_probe->probe_points[j].buffer_id; + if (_probe->probe_points[j].stream_tag != PROBE_POINT_INVALID && - _probe->probe_points[j].buffer_id == buffer_id[i]) { - dev = ipc_get_comp_by_id(ipc_get(), buffer_id[i]); + buf_id->full_id == buffer_id[i]) { +#if CONFIG_LOG_BACKEND_SOF_PROBE + if (enable_logs(&_probe->probe_points[j])) + probe_logging_init(NULL); +#endif +#if CONFIG_IPC_MAJOR_4 + dev = ipc_get_comp_by_id(ipc_get(), + IPC4_COMP_ID(buf_id->fields.module_id, + buf_id->fields.instance_id)); if (dev) { - notifier_unregister(_probe, dev->cb, - NOTIFIER_ID_BUFFER_PRODUCE); - notifier_unregister(_probe, dev->cb, - NOTIFIER_ID_BUFFER_FREE); + buf = ipc4_get_buffer(dev, *buf_id); + if (buf) { + buf->probe_cb_produce = NULL; + buf->probe_cb_free = NULL; + buf->probe_cb_arg = NULL; + } } +#else + dev = ipc_get_comp_by_id(ipc_get(), buffer_id[i]); + if (dev) { + struct comp_buffer *probe_buf = + (struct comp_buffer *)dev->cb; + probe_buf->probe_cb_produce = NULL; + probe_buf->probe_cb_free = NULL; + probe_buf->probe_cb_arg = NULL; + } +#endif _probe->probe_points[j].stream_tag = PROBE_POINT_INVALID; } @@ -1096,9 +1463,206 @@ int probe_point_remove(uint32_t count, uint32_t *buffer_id) break; } if (j == CONFIG_PROBE_POINTS_MAX) { - tracev_probe("probe_point_remove(): cancel probe task"); + tr_dbg(&pr_tr, "cancel probe task"); schedule_task_cancel(&_probe->dmap_work); } return 0; } + +#if CONFIG_IPC_MAJOR_4 +static int probe_mod_init(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + struct module_data *mod_data = &mod->priv; + const struct ipc4_probe_module_cfg *probe_cfg = mod_data->cfg.init_data; + int ret; + + comp_info(dev, "entry"); + + ret = probe_init(&probe_cfg->gtw_cfg); + if (ret < 0) + return -EINVAL; + + return 0; +} + +static int probe_free(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + + comp_info(dev, "entry"); + + probe_deinit(); + +#if CONFIG_LOG_BACKEND_SOF_PROBE + probe_logging_init(NULL); +#endif + return 0; +} + +static int probe_set_config(struct processing_module *mod, uint32_t param_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; + + comp_info(dev, "entry"); + + switch (param_id) { + case IPC4_PROBE_MODULE_PROBE_POINTS_ADD: + return probe_point_add(fragment_size / sizeof(struct probe_point), + (const struct probe_point *)fragment); + case IPC4_PROBE_MODULE_DISCONNECT_PROBE_POINTS: + return probe_point_remove(fragment_size / sizeof(uint32_t), + (const uint32_t *)fragment); + case IPC4_PROBE_MODULE_INJECTION_DMA_ADD: + return probe_dma_add(fragment_size / (2 * sizeof(uint32_t)), + (const struct probe_dma *)fragment); + case IPC4_PROBE_MODULE_INJECTION_DMA_DETACH: + return probe_dma_remove(fragment_size / sizeof(uint32_t), + (const uint32_t *)fragment); + default: + return -EINVAL; + } +} + +static int probe_add_point_info_params(struct sof_ipc_probe_info_params *info, + probe_point_id_t id, int index, size_t max_size) +{ + struct probe_pdata *_probe = probe_get(); + struct probe_point pp = { + .buffer_id = id, + .purpose = PROBE_PURPOSE_EXTRACTION, + }; + int i; + + if (offsetof(struct sof_ipc_probe_info_params, probe_point[index]) + + sizeof(pp) > max_size) { + info->num_elems = index; + return -ENOENT; + } + + for (i = 0; i < ARRAY_SIZE(_probe->probe_points); i++) + if (_probe->probe_points[i].stream_tag != PROBE_POINT_INVALID && + _probe->probe_points[i].buffer_id.full_id == id.full_id) + pp.stream_tag = _probe->probe_points[i].stream_tag; + + info->probe_point[index] = pp; + return 0; +} + +static int probe_get_available_points(struct processing_module *mod, + struct sof_ipc_probe_info_params *info, + size_t max_size) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + int i = 0; + + list_for_item(clist, &ipc_get()->comp_list) { + struct comp_buffer *buf; + probe_point_id_t id; + + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + id.fields.module_id = IPC4_MOD_ID(icd->id); + id.fields.instance_id = IPC4_INST_ID(icd->id); + + id.fields.type = PROBE_TYPE_INPUT; + comp_dev_for_each_producer(icd->cd, buf) { + id.fields.index = IPC4_SINK_QUEUE_ID(buf_get_id(buf)); + if (probe_add_point_info_params(info, id, i, max_size)) + return 0; + i++; + } + id.fields.type = PROBE_TYPE_OUTPUT; + comp_dev_for_each_consumer(icd->cd, buf) { + id.fields.index = IPC4_SRC_QUEUE_ID(buf_get_id(buf)); + if (probe_add_point_info_params(info, id, i, max_size)) + return 0; + i++; + } + } + info->num_elems = i; + return 0; +} + +static int probe_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct sof_ipc_probe_info_params *info = + (struct sof_ipc_probe_info_params *)ASSUME_ALIGNED(fragment, 8); + struct probe_pdata *_probe = probe_get(); + struct comp_dev *dev = mod->dev; + int i, j; + + comp_dbg(dev, "config_id %u", config_id); + switch (config_id) { + case IPC4_PROBE_MODULE_PROBE_POINTS_ADD: + for (i = 0, j = 0; i < ARRAY_SIZE(_probe->probe_points); i++) { + if (_probe->probe_points[i].stream_tag == PROBE_POINT_INVALID) + continue; + if (offsetof(struct sof_ipc_probe_info_params, probe_point[j]) + + sizeof(info->probe_point[0]) > fragment_size) + break; + info->probe_point[j++] = _probe->probe_points[i]; + } + info->num_elems = j; + comp_info(dev, "%u probe points sent", j); + break; + case IPC4_PROBE_MODULE_AVAILABLE_PROBE_POINTS: + probe_get_available_points(mod, info, fragment_size); + comp_info(dev, "%u available probe points sent", + info->num_elems); + break; + default: + comp_err(dev, "unknown config_id %u", config_id); + return -EINVAL; + } + return 0; +} + +static int probe_dummy_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 comp_dev *dev = mod->dev; + + comp_warn(dev, "called"); + + return 0; +} + +static const struct module_interface probe_interface = { + .init = probe_mod_init, + .process_audio_stream = probe_dummy_process, + .set_configuration = probe_set_config, + .get_configuration = probe_get_config, + .free = probe_free, +}; + +#if CONFIG_PROBE_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest __section(".module") __used = + SOF_LLEXT_MODULE_MANIFEST("PROBE", &probe_interface, 1, SOF_REG_UUID(probe4), 40); + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_MODULE_ADAPTER(probe_interface, PROBE_UUID, pr_tr); +SOF_MODULE_INIT(probe, sys_comp_module_probe_interface_init); + +#endif /* CONFIG_COMP_PROBE_MODULE */ + +#endif /* CONFIG_IPC_MAJOR_4 */ diff --git a/src/probe/probe.toml b/src/probe/probe.toml new file mode 100644 index 000000000000..5075ad866061 --- /dev/null +++ b/src/probe/probe.toml @@ -0,0 +1,19 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + [[module.entry]] + name = "PROBE" + uuid = UUIDREG_STR_PROBE4 + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = LOAD_TYPE + module_type = "9" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # 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, 4096, 100000, 48, 48, 0, 1000, 0] + + index = __COUNTER__ diff --git a/src/samples/CMakeLists.txt b/src/samples/CMakeLists.txt new file mode 100644 index 000000000000..66fa09c8d69c --- /dev/null +++ b/src/samples/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT CONFIG_LIBRARY) + add_subdirectory(audio) +endif() diff --git a/src/samples/Kconfig b/src/samples/Kconfig new file mode 100644 index 000000000000..630337a12dcb --- /dev/null +++ b/src/samples/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "Samples" + +config SAMPLES + bool "Build samples" + default y + help + Select to build sample code + +if SAMPLES + +rsource "audio/Kconfig" + +endif + +endmenu diff --git a/src/samples/audio/CMakeLists.txt b/src/samples/audio/CMakeLists.txt new file mode 100644 index 000000000000..1dde973de0d7 --- /dev/null +++ b/src/samples/audio/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: BSD-3-Clause + +if(CONFIG_IPC_MAJOR_3) + set(ipc_suffix ipc3) +elseif(CONFIG_IPC_MAJOR_4) + set(ipc_suffix ipc4) +endif() + +if(CONFIG_SAMPLE_SMART_AMP STREQUAL "m" AND DEFINED CONFIG_LLEXT) + add_subdirectory(smart_amp_test_llext ${PROJECT_BINARY_DIR}/smart_amp_test_llext) + add_dependencies(app smart_amp_test) +elseif(CONFIG_SAMPLE_SMART_AMP) + add_local_sources(sof smart_amp_test_${ipc_suffix}.c) +endif() + +if(CONFIG_SAMPLE_KEYPHRASE) + add_local_sources(sof detect_test.c) +endif() + +if(CONFIG_KWD_NN_SAMPLE_KEYPHRASE) + add_local_sources(sof kwd_nn_detect_test.c) +endif() diff --git a/src/samples/audio/Kconfig b/src/samples/audio/Kconfig new file mode 100644 index 000000000000..7463d8c31412 --- /dev/null +++ b/src/samples/audio/Kconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: BSD-3-Clause + +menu "Audio component samples" + + config SAMPLE_SMART_AMP + tristate "Smart amplifier test component" + default m if LIBRARY_DEFAULT_MODULAR + default y + help + Select for test smart amplifier component + + config SAMPLE_KEYPHRASE + depends on CAVS || IMX || ACE + bool "Keyphrase test component" + default y + help + Select for Keyphrase test component. + Provides basic functionality for use in testing of keyphrase detection pipelines. + + config KWD_NN_SAMPLE_KEYPHRASE + depends on IMX + bool "KWD NN Keyphrase test component" + default n + help + Select for KWD NN Keyphrase test component based on neural network. + Provides ML functionality for use in testing of keyphrase detection pipelines. + Use KWD based on NN as alternative to the default KWD component. + Provides neural network as a library. +endmenu diff --git a/src/samples/audio/detect_test.c b/src/samples/audio/detect_test.c new file mode 100644 index 000000000000..35ed6ecd2011 --- /dev/null +++ b/src/samples/audio/detect_test.c @@ -0,0 +1,1117 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/data_blob.h> +#include <sof/audio/format.h> +#include <sof/audio/ipc-config.h> +#include <sof/audio/kpb.h> +#include <sof/common.h> +#include <sof/compiler_attributes.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/init.h> +#include <rtos/wait.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/math/numbers.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <ipc/control.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/detect_test.h> +#include <ipc4/notification.h> +#endif +#include <kernel/abi.h> +#include <sof/samples/audio/detect_test.h> +#include <user/trace.h> +#include <errno.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <sof/samples/audio/kwd_nn_detect_test.h> +#if CONFIG_AMS +#include <sof/lib/ams.h> +#include <sof/lib/ams_msg.h> +#include <ipc4/ams_helpers.h> +#else +#include <sof/lib/notifier.h> +#endif + +#define ACTIVATION_DEFAULT_SHIFT 3 +#define ACTIVATION_DEFAULT_COEF 0.05 + +#define ACTIVATION_DEFAULT_THRESHOLD_S16 \ + Q_CONVERT_FLOAT(ACTIVATION_DEFAULT_COEF, 15) /* Q1.15 */ +#define ACTIVATION_DEFAULT_THRESHOLD_S24 \ + Q_CONVERT_FLOAT(ACTIVATION_DEFAULT_COEF, 23) /* Q1.23 */ +#define ACTIVATION_DEFAULT_THRESHOLD_S32 \ + Q_CONVERT_FLOAT(ACTIVATION_DEFAULT_COEF, 31) /* Q1.31 */ + +#define INITIAL_MODEL_DATA_SIZE 64 + +/* default number of samples before detection is activated */ +#define KEYPHRASE_DEFAULT_PREAMBLE_LENGTH 0 + +#define KWD_NN_BUFF_ALIGN 64 + +static const struct comp_driver comp_keyword; + +LOG_MODULE_REGISTER(kd_test, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(keyword); + +DECLARE_TR_CTX(keyword_tr, SOF_UUID(keyword_uuid), LOG_LEVEL_INFO); + +struct comp_data { +#ifdef CONFIG_IPC_MAJOR_4 + struct ipc4_base_module_cfg base_cfg; +#endif + struct sof_detect_test_config config; + struct comp_data_blob_handler *model_handler; + void *data_blob; + size_t data_blob_size; + uint32_t data_blob_crc; + + int32_t activation; + uint32_t detected; + uint32_t detect_preamble; /**< current keyphrase preamble length */ + uint32_t keyphrase_samples; /**< keyphrase length in samples */ + uint32_t drain_req; /** defines draining size in bytes. */ + uint16_t sample_valid_bytes; + struct kpb_client client_data; + +#if CONFIG_KWD_NN_SAMPLE_KEYPHRASE + int16_t *input; + size_t input_size; +#endif + + struct ipc_msg *msg; /**< host notification */ + + void (*detect_func)(struct comp_dev *dev, + const struct audio_stream *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) +{ + bool ret; + + switch (sf) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + /* FALLTHRU */ +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + /* FALLTHRU */ +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + /* FALLTHRU */ +#endif /* CONFIG_FORMAT_S32LE */ + ret = true; + break; + default: + ret = false; + break; + } + + return ret; +} + +static void notify_host(const struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + +#if CONFIG_IPC_MAJOR_4 + ipc_msg_send(cd->msg, NULL, true); +#else + ipc_msg_send(cd->msg, &cd->event, true); +#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); + + comp_info(dev, "preamble: %u", cd->detect_preamble); + + 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; + cd->event_data.event_id = KPB_EVENT_BEGIN_DRAINING; + cd->event_data.client_data = &cd->client_data; + + notifier_event(dev, NOTIFIER_ID_KPB_CLIENT_EVT, + 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, + const struct audio_stream *source, + uint32_t frames) +{ + struct comp_data *cd = comp_get_drvdata(dev); + void *src; + int32_t diff; + uint32_t count = frames; /**< Assuming single channel */ + uint32_t sample; + uint16_t valid_bits = cd->sample_valid_bytes * 8; + const int32_t activation_threshold = cd->config.activation_threshold; + uint32_t cycles_per_frame; /**< Clock cycles required per frame */ + + /* synthetic load */ + if (cd->config.load_mips) { + /* assuming count is a processing frame size in samples */ + cycles_per_frame = (cd->config.load_mips * 1000000 * count) + / audio_stream_get_rate(source); + wait_delay(cycles_per_frame); + } + + /* perform detection within current period */ + for (sample = 0; sample < count && !cd->detected; ++sample) { + switch (valid_bits) { + case 16: + src = audio_stream_read_frag_s16(source, sample); + diff = abs(*(int16_t *)src) - abs((int16_t)cd->activation); + break; + case 24: + src = audio_stream_read_frag_s32(source, sample); + diff = abs(sign_extend_s24(*(int32_t *)src)) - abs(cd->activation); + break; + case 32: + src = audio_stream_read_frag_s32(source, sample); + diff = abs(*(int32_t *)src) - abs(cd->activation); + break; + default: + comp_err(dev, "Unsupported format"); + return; + } + + diff >>= cd->config.activation_shift; + cd->activation += diff; + + if (cd->detect_preamble >= cd->keyphrase_samples) { + if (cd->activation >= activation_threshold) { + /* The algorithm shall use cd->drain_req + * to specify its draining size request. + * Zero value means default config value + * will be used. + */ + cd->drain_req = 0; + detect_test_notify(dev); + cd->detected = 1; + } + } else { + ++cd->detect_preamble; + } + } +} + +static int test_keyword_get_threshold(struct comp_dev *dev, int sample_width) +{ + switch (sample_width) { +#if CONFIG_FORMAT_S16LE + case 16: + return ACTIVATION_DEFAULT_THRESHOLD_S16; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case 24: + return ACTIVATION_DEFAULT_THRESHOLD_S24; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case 32: + return ACTIVATION_DEFAULT_THRESHOLD_S32; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(dev, "unsupported sample width: %d", + sample_width); + return -EINVAL; + } +} + +static int test_keyword_apply_config(struct comp_dev *dev, + const struct sof_detect_test_config *cfg) +{ + struct comp_data *cd = comp_get_drvdata(dev); + uint16_t sample_width; + int ret; + + ret = memcpy_s(&cd->config, sizeof(cd->config), cfg, + sizeof(struct sof_detect_test_config)); + assert(!ret); + +#if CONFIG_IPC_MAJOR_4 + sample_width = cd->base_cfg.audio_fmt.valid_bit_depth; +#else + sample_width = cd->config.sample_width; +#endif /* CONFIG_IPC_MAJOR_4 */ + + if (!cd->config.activation_shift) + cd->config.activation_shift = ACTIVATION_DEFAULT_SHIFT; + + if (!cd->config.activation_threshold) { + ret = test_keyword_get_threshold(dev, sample_width); + if (ret < 0) { + comp_err(dev, "unsupported sample width %u", + sample_width); + return ret; + } + + cd->config.activation_threshold = ret; + } + + return 0; +} + +#if CONFIG_IPC_MAJOR_4 +#define NOTIFICATION_DEFAULT_WORD_ID 1 +#define NOTIFICATION_DEFAULT_SCORE 100 + +static void test_keyword_set_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_data *cd = comp_get_drvdata(dev); + enum sof_ipc_frame valid_fmt, frame_fmt; + + comp_info(dev, "entry"); + + memset(params, 0, sizeof(*params)); + params->channels = cd->base_cfg.audio_fmt.channels_count; + params->rate = cd->base_cfg.audio_fmt.sampling_frequency; + params->sample_container_bytes = cd->base_cfg.audio_fmt.depth / 8; + params->sample_valid_bytes = + cd->base_cfg.audio_fmt.valid_bit_depth / 8; + params->buffer_fmt = cd->base_cfg.audio_fmt.interleaving_style; + params->buffer.size = cd->base_cfg.ibs; + + audio_stream_fmt_conversion(cd->base_cfg.audio_fmt.depth, + cd->base_cfg.audio_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + cd->base_cfg.audio_fmt.s_type); + + params->frame_fmt = valid_fmt; +} + +static int test_keyword_set_config(struct comp_dev *dev, const char *data, + uint32_t data_size) +{ + const struct sof_detect_test_config *cfg; + size_t cfg_size; + + /* Copy new config */ + cfg = (const struct sof_detect_test_config *)data; + cfg_size = data_size; + + comp_info(dev, "config size = %u", + cfg_size); + + if (cfg_size != sizeof(struct sof_detect_test_config)) { + comp_err(dev, "invalid config size"); + return -EINVAL; + } + + return test_keyword_apply_config(dev, cfg); +} + +static int test_keyword_get_config(struct comp_dev *dev, char *data, + uint32_t *data_size) +{ + struct comp_data *cd = comp_get_drvdata(dev); + size_t cfg_size; + int ret; + + comp_info(dev, "entry"); + + cfg_size = sizeof(struct sof_detect_test_config); + + if (cfg_size > *data_size) { + comp_err(dev, "wrong config size: %d", + *data_size); + return -EINVAL; + } + + *data_size = cfg_size; + + /* Copy back to user space */ + ret = memcpy_s(data, cfg_size, &cd->config, cfg_size); + assert(!ret); + + return 0; +} + +static int test_keyword_set_large_config(struct comp_dev *dev, + uint32_t param_id, + bool first_block, + bool last_block, + uint32_t data_offset, + const char *data) +{ + comp_dbg(dev, "entry"); + struct comp_data *cd = comp_get_drvdata(dev); + + switch (param_id) { + case IPC4_DETECT_TEST_SET_MODEL_BLOB: + return ipc4_comp_data_blob_set(cd->model_handler, + first_block, + last_block, + data_offset, + data); + case IPC4_DETECT_TEST_SET_CONFIG: + return test_keyword_set_config(dev, data, data_offset); + default: + return -EINVAL; + } +} + +static int test_keyword_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, "entry"); + + switch (param_id) { + case IPC4_DETECT_TEST_GET_CONFIG: + return test_keyword_get_config(dev, data, data_offset); + default: + return -EINVAL; + } +} + +static int test_keyword_get_attribute(struct comp_dev *dev, + uint32_t type, + void *value) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + switch (type) { + case COMP_ATTR_BASE_CONFIG: + *(struct ipc4_base_module_cfg *)value = cd->base_cfg; + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct ipc_msg *ipc4_kd_notification_init(uint32_t word_id, + uint32_t score) +{ + struct ipc4_voice_cmd_notification notif; + struct ipc_msg *msg; + + memset_s(¬if, sizeof(notif), 0, sizeof(notif)); + + notif.primary.r.word_id = word_id; + notif.primary.r.notif_type = SOF_IPC4_NOTIFY_PHRASE_DETECTED; + notif.primary.r.type = SOF_IPC4_GLB_NOTIFICATION; + notif.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + notif.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + + notif.extension.r.sv_score = score; + + msg = ipc_msg_w_ext_init(notif.primary.dat, + notif.extension.dat, + 0); + if (!msg) + return NULL; + + return msg; +} + +#else /* CONFIG_IPC_MAJOR_4 */ +static int test_keyword_set_config(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct sof_detect_test_config *cfg; + size_t bs; + + /* Copy new config, find size from header */ + cfg = (struct sof_detect_test_config *)cdata->data->data; + bs = cfg->size; + + comp_info(dev, "blob size = %zu", bs); + + if (bs != sizeof(struct sof_detect_test_config)) { + comp_err(dev, "invalid blob size"); + return -EINVAL; + } + + return test_keyword_apply_config(dev, cfg); +} + +static void test_keyword_set_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{} + +static int test_keyword_ctrl_set_bin_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int ret = 0; + + if (dev->state != COMP_STATE_READY) { + /* It is a valid request but currently this is not + * supported during playback/capture. The driver will + * re-send data in next resume when idle and the new + * configuration will be used when playback/capture + * starts. + */ + comp_err(dev, "keyword_ctrl_set_bin_data(): driver is busy"); + return -EBUSY; + } + + switch (cdata->data->type) { + case SOF_DETECT_TEST_CONFIG: + ret = test_keyword_set_config(dev, cdata); + break; + case SOF_DETECT_TEST_MODEL: + ret = comp_data_blob_set_cmd(cd->model_handler, cdata); + break; + default: + comp_err(dev, "keyword_ctrl_set_bin_data(): unknown binary data type"); + break; + } + + return ret; +} + +static int test_keyword_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, "test_keyword_cmd_set_data(): invalid version"); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_info(dev, "test_keyword_cmd_set_data(), SOF_CTRL_CMD_ENUM"); + break; + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "test_keyword_cmd_set_data(), SOF_CTRL_CMD_BINARY"); + ret = test_keyword_ctrl_set_bin_data(dev, cdata); + break; + default: + comp_err(dev, "test_keyword_cmd_set_data(): invalid cdata->cmd"); + ret = -EINVAL; + break; + } + + return ret; +} + +static int test_keyword_get_config(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, int size) +{ + struct comp_data *cd = comp_get_drvdata(dev); + size_t bs; + int ret = 0; + + comp_info(dev, "entry"); + + /* Copy back to user space */ + bs = cd->config.size; + comp_info(dev, "value of block size: %zu", bs); + + if (bs == 0 || bs > size) + return -EINVAL; + + ret = memcpy_s(cdata->data->data, size, &cd->config, bs); + assert(!ret); + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = bs; + + return ret; +} + +static int test_keyword_ctrl_get_bin_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, + int size) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int ret = 0; + + switch (cdata->data->type) { + case SOF_DETECT_TEST_CONFIG: + ret = test_keyword_get_config(dev, cdata, size); + break; + case SOF_DETECT_TEST_MODEL: + ret = comp_data_blob_get_cmd(cd->model_handler, cdata, size); + break; + default: + comp_err(dev, "unknown binary data type"); + break; + } + + return ret; +} + +static int test_keyword_ctrl_get_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, int size) +{ + int ret = 0; + + comp_info(dev, "size: %d", size); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + ret = test_keyword_ctrl_get_bin_data(dev, cdata, size); + break; + default: + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } + + return ret; +} + +/* used to pass standard and bespoke commands (with data) to component */ +static int test_keyword_cmd(struct comp_dev *dev, int cmd, void *data, + int max_data_size) +{ + struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); + + comp_info(dev, "entry"); + + switch (cmd) { + case COMP_CMD_SET_DATA: + return test_keyword_ctrl_set_data(dev, cdata); + case COMP_CMD_GET_DATA: + return test_keyword_ctrl_get_data(dev, cdata, max_data_size); + default: + return -EINVAL; + } +} +#endif /* CONFIG_IPC_MAJOR_4 */ +static int test_keyword_params(struct comp_dev *dev, struct sof_ipc_stream_params *params); + +static struct comp_dev *test_keyword_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev = NULL; +#if CONFIG_IPC_MAJOR_4 + const struct ipc4_base_module_cfg *base_cfg = spec; +#else + const struct ipc_config_process *ipc_keyword = spec; + const struct sof_detect_test_config *cfg; + size_t bs; +#endif /* CONFIG_IPC_MAJOR_4 */ + struct comp_data *cd = NULL; + int ret = 0; + + comp_cl_info(&comp_keyword, "test_keyword_new()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + + if (!cd) + goto fail; + +#if CONFIG_KWD_NN_SAMPLE_KEYPHRASE + cd->detect_func = kwd_nn_detect_test; +#else + /* using default processing function */ + cd->detect_func = default_detect_test; +#endif + + comp_set_drvdata(dev, cd); + + /* component model data handler */ + cd->model_handler = comp_data_blob_handler_new(dev); + +#if CONFIG_IPC_MAJOR_4 + /* For IPC4 we only receive the base_cfg, make a copy of it */ + memcpy_s(&cd->base_cfg, sizeof(cd->base_cfg), base_cfg, sizeof(*base_cfg)); +#else + cfg = (const struct sof_detect_test_config *)ipc_keyword->data; + bs = ipc_keyword->size; + + if (bs > 0) { + if (bs < sizeof(struct sof_detect_test_config)) { + comp_err(dev, "test_keyword_new(): invalid data size"); + goto cd_fail; + } + + if (test_keyword_apply_config(dev, cfg)) { + comp_err(dev, "test_keyword_new(): failed to apply config"); + goto cd_fail; + } + } +#endif /* CONFIG_IPC_MAJOR_4 */ + + ret = comp_init_data_blob(cd->model_handler, INITIAL_MODEL_DATA_SIZE, + NULL); + if (ret < 0) { + comp_err(dev, "test_keyword_new(): model data initial failed"); + goto cd_fail; + } + + /* build component event */ + ipc_build_comp_event(&cd->event, dev->ipc_config.type, dev->ipc_config.id); + cd->event.event_type = SOF_CTRL_EVENT_KD; + cd->event.num_elems = 0; + +#if CONFIG_IPC_MAJOR_4 + cd->msg = ipc4_kd_notification_init(NOTIFICATION_DEFAULT_WORD_ID, + NOTIFICATION_DEFAULT_SCORE); +#else + cd->msg = ipc_msg_init(cd->event.rhdr.hdr.cmd, sizeof(cd->event)); +#endif /* CONFIG_IPC_MAJOR_4 */ + + if (!cd->msg) { + comp_err(dev, "test_keyword_new(): ipc notification init failed"); + goto cd_fail; + } + +#if CONFIG_KWD_NN_SAMPLE_KEYPHRASE + /* global buffer to accumulate data for processing */ + cd->input = rballoc_align(SOF_MEM_FLAG_USER, + sizeof(int16_t) * KWD_NN_IN_BUFF_SIZE, 64); + if (!cd->input) { + comp_err(dev, "test_keyword_new(): input alloc failed"); + goto cd_fail; + } + bzero(cd->input, sizeof(int16_t) * KWD_NN_IN_BUFF_SIZE); + cd->input_size = 0; +#endif + + dev->direction = SOF_IPC_STREAM_CAPTURE; + dev->direction_set = true; + dev->state = COMP_STATE_READY; + +#if CONFIG_IPC_MAJOR_4 + struct sof_ipc_stream_params params; + + /* retrieve params based on base config for IPC4 */ + ret = test_keyword_params(dev, ¶ms); + if (ret < 0) + goto cd_fail; +#endif + + return dev; + +cd_fail: + comp_data_blob_handler_free(cd->model_handler); + rfree(cd); +fail: + comp_free_device(dev); + return NULL; +} + +static void test_keyword_free(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + +#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, "unregister ams error %d", ret); +#endif + + ipc_msg_free(cd->msg); + comp_data_blob_handler_free(cd->model_handler); + rfree(cd); + comp_free_device(dev); +} + +static int test_keyword_verify_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + int ret; + + comp_dbg(dev, "entry"); + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "verification failed!"); + return ret; + } + + return 0; +} + +/* set component audio stream parameters */ +static int test_keyword_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *sourceb; + unsigned int channels, rate; + enum sof_ipc_frame frame_fmt; + int err; + + test_keyword_set_params(dev, params); + + err = test_keyword_verify_params(dev, params); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return err; + } + + cd->sample_valid_bytes = params->sample_valid_bytes; + + /* + * Threshold might be already set via IPC4_DETECT_TEST_SET_CONFIG, + * otherwise apply default value. + */ + if (!cd->config.activation_threshold) { + err = test_keyword_get_threshold(dev, params->sample_valid_bytes * 8); + if (err < 0) { + comp_err(dev, "unsupported sample width %u", + params->sample_valid_bytes * 8); + return err; + } + + cd->config.activation_threshold = err; + } + + /* keyword components will only ever have 1 source */ + sourceb = comp_dev_get_first_data_producer(dev); + if (sourceb) { + channels = audio_stream_get_channels(&sourceb->stream); + frame_fmt = audio_stream_get_frm_fmt(&sourceb->stream); + rate = audio_stream_get_rate(&sourceb->stream); + + if (channels != 1) { + comp_err(dev, "only single-channel supported"); + return -EINVAL; + } + + if (!detector_is_sample_width_supported(frame_fmt)) { + comp_err(dev, "only 16-bit format supported"); + return -EINVAL; + } + + /* calculate the length of the preamble */ + if (cd->config.preamble_time) { + cd->keyphrase_samples = cd->config.preamble_time * + (rate / 1000); + } else { + cd->keyphrase_samples = KEYPHRASE_DEFAULT_PREAMBLE_LENGTH; + } + } + +#if CONFIG_AMS + cd->kpd_uuid_id = AMS_INVALID_MSG_TYPE; +#endif /* CONFIG_AMS */ + + return 0; +} + +static int test_keyword_trigger(struct comp_dev *dev, int cmd) +{ + int ret; + struct comp_data *cd = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + + ret = comp_set_state(dev, cmd); + if (ret) + return ret; + + if (cmd == COMP_TRIGGER_START || + cmd == COMP_TRIGGER_RELEASE) { + cd->detect_preamble = 0; + cd->detected = 0; + cd->activation = 0; + } + + return 0; +} + +/* process stream data from source buffer */ +static int test_keyword_copy(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *source; + uint32_t frames; + + comp_dbg(dev, "entry"); + + /* keyword components will only ever have 1 source */ + source = comp_dev_get_first_data_producer(dev); + + if (!audio_stream_get_avail(&source->stream)) + return PPL_STATUS_PATH_STOP; + + frames = audio_stream_get_avail_frames(&source->stream); + + /* copy and perform detection */ + buffer_stream_invalidate(source, audio_stream_get_avail_bytes(&source->stream)); + cd->detect_func(dev, &source->stream, frames); + + /* calc new available */ + comp_update_buffer_consume(source, audio_stream_get_avail_bytes(&source->stream)); + + return 0; +} + +static int test_keyword_reset(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + + cd->activation = 0; + cd->detect_preamble = 0; + cd->detected = 0; + + return comp_set_state(dev, COMP_TRIGGER_RESET); +} + +static int test_keyword_prepare(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct sof_ipc_stream_params params; + 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.valid_bit_depth; +#else + sample_width = cd->config.sample_width; +#endif /* CONFIG_IPC_MAJOR_4 */ + + comp_info(dev, "entry"); + + ret = test_keyword_params(dev, ¶ms); + if (ret < 0) { + comp_err(dev, "params config failed."); + return ret; + } + + /* + * FIXME: this condition is always "false" for IPC4 as audio format cannot be changed + * without component re-creation. Does this "if" makes sense for IPC3? + */ + if (valid_bits != sample_width) { + /* Default threshold value has to be changed + * according to host new format. + */ + ret = test_keyword_get_threshold(dev, valid_bits); + + if (ret < 0) { + comp_err(dev, "unsupported sample width %u", + valid_bits); + return ret; + } + + cd->config.activation_threshold = ret; + } + + cd->data_blob = comp_get_data_blob(cd->model_handler, + &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); +} + +uint16_t test_keyword_get_sample_valid_bytes(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + return cd->sample_valid_bytes; +} + +uint32_t test_keyword_get_detected(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + return cd->detected; +} + +void test_keyword_set_detected(struct comp_dev *dev, uint32_t detected) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + cd->detected = detected; +} + +#if CONFIG_KWD_NN_SAMPLE_KEYPHRASE +const int16_t *test_keyword_get_input(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + return cd->input; +} + +int16_t test_keyword_get_input_byte(struct comp_dev *dev, uint32_t index) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + if (index >= KWD_NN_IN_BUFF_SIZE * sizeof(int16_t)) + return -EINVAL; + + return *((unsigned char *)cd->input + index); +} + +int16_t test_keyword_get_input_elem(struct comp_dev *dev, uint32_t index) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + if (index >= KWD_NN_IN_BUFF_SIZE) + return -EINVAL; + return cd->input[index]; +} + +int test_keyword_set_input_elem(struct comp_dev *dev, uint32_t index, int16_t val) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + if (index >= KWD_NN_IN_BUFF_SIZE) + return -EINVAL; + + cd->input[index] = val; + + return 0; +} + +size_t test_keyword_get_input_size(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + return cd->input_size; +} + +void test_keyword_set_input_size(struct comp_dev *dev, size_t input_size) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + cd->input_size = input_size; +} +#endif + +uint32_t test_keyword_get_drain_req(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + return cd->drain_req; +} + +void test_keyword_set_drain_req(struct comp_dev *dev, uint32_t drain_req) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + cd->drain_req = drain_req; +} + +static const struct comp_driver comp_keyword = { + .type = SOF_COMP_KEYWORD_DETECT, + .uid = SOF_RT_UUID(keyword_uuid), + .tctx = &keyword_tr, + .ops = { + .create = test_keyword_new, + .free = test_keyword_free, + .params = test_keyword_params, +#if CONFIG_IPC_MAJOR_4 + .set_large_config = test_keyword_set_large_config, + .get_large_config = test_keyword_get_large_config, + .get_attribute = test_keyword_get_attribute, +#else + .cmd = test_keyword_cmd, +#endif /* CONFIG_IPC_MAJOR_4 */ + .trigger = test_keyword_trigger, + .copy = test_keyword_copy, + .prepare = test_keyword_prepare, + .reset = test_keyword_reset, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_keyword_info = { + .drv = &comp_keyword, +}; + +UT_STATIC void sys_comp_keyword_init(void) +{ + comp_register(platform_shared_get(&comp_keyword_info, + sizeof(comp_keyword_info))); +} + +DECLARE_MODULE(sys_comp_keyword_init); +SOF_MODULE_INIT(keyword, sys_comp_keyword_init); diff --git a/src/samples/audio/detect_test.toml b/src/samples/audio/detect_test.toml new file mode 100644 index 000000000000..3d764d47341f --- /dev/null +++ b/src/samples/audio/detect_test.toml @@ -0,0 +1,19 @@ + [[module.entry]] + name = "KDTEST" + uuid = UUIDREG_STR_KEYWORD + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "8" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xf, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # 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, 480, 1114000, 64, 64, 0, 0, 0] + + index = __COUNTER__ diff --git a/src/samples/audio/kwd_nn_detect_test.c b/src/samples/audio/kwd_nn_detect_test.c new file mode 100644 index 000000000000..5d1f054bb040 --- /dev/null +++ b/src/samples/audio/kwd_nn_detect_test.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2021 NXP +// +// Author: Cristina Feies <cristina.ilie@nxp.com> +// Author: Viorel Suman <viorel.suman@nxp.com> + +#include <sof/compiler_attributes.h> +#include <sof/samples/audio/kwd_nn_detect_test.h> +#include <sof/samples/audio/kwd_nn/kwd_nn_preprocess.h> +#include <sof/samples/audio/kwd_nn/kwd_nn_process.h> +#include <sof/samples/audio/detect_test.h> +#include <sof/audio/component.h> +#include <rtos/wait.h> +#include <stdint.h> + +static __aligned(64) uint8_t preprocessed_data[KWD_NN_CONFIG_PREPROCESSED_SIZE]; +static __aligned(8) uint8_t confidences[KWD_NN_CONFIDENCES_SIZE]; + +static int kwd_nn_detect_postprocess(uint8_t confidences[KWD_NN_CONFIDENCES_SIZE]) +{ + int i; + uint8_t max_confidence = confidences[0]; + int max_idx = 0; + + for (i = 1; i < KWD_NN_CONFIDENCES_SIZE; i++) { + if (max_confidence < confidences[i]) { + max_confidence = confidences[i]; + max_idx = i; + } + } + if (max_confidence < KWD_NN_MIN_ACCEPTABLE_CONFIDENCE) + max_idx = KWD_NN_UNKNOWN; + return max_idx; +} + +void kwd_nn_detect_test(struct comp_dev *dev, + const struct audio_stream *source, + uint32_t frames) +{ + void *src; + uint32_t count = frames; /**< Assuming single channel */ + uint32_t sample; + uint32_t one_sec_samples = KWD_NN_KEY_LEN; + uint32_t half_sec_samples = one_sec_samples / 2; + + /* perform detection within current period */ + for (sample = 0; sample < count && !test_keyword_get_detected(dev); ++sample) { + src = (test_keyword_get_sample_valid_bytes(dev) * 8 == 16U) ? + audio_stream_read_frag_s16(source, sample) : + audio_stream_read_frag_s32(source, sample); + if (test_keyword_get_input_size(dev) < KWD_NN_IN_BUFF_SIZE) { + if (test_keyword_get_sample_valid_bytes(dev) == 16U) + test_keyword_set_input_elem(dev, + test_keyword_get_input_size(dev), + *((int16_t *)src)); + else + test_keyword_set_input_elem(dev, + test_keyword_get_input_size(dev), + *((int32_t *)src)); + test_keyword_set_input_size(dev, test_keyword_get_input_size(dev) + 1); + } + if (test_keyword_get_input_size(dev) > one_sec_samples) { + uint64_t time_start; + uint64_t time_stop; + int result; + int i, j; + + comp_dbg(dev, "Drain values (0-3): 0x%x, 0x%x, 0x%x, 0x%x\n", + test_keyword_get_input_byte(dev, 0), + test_keyword_get_input_byte(dev, 1), + test_keyword_get_input_byte(dev, 2), + test_keyword_get_input_byte(dev, 3) + ); + comp_dbg(dev, "Drain values (4-7): 0x%x, 0x%x, 0x%x, 0x%x\n", + test_keyword_get_input_byte(dev, 4), + test_keyword_get_input_byte(dev, 5), + test_keyword_get_input_byte(dev, 6), + test_keyword_get_input_byte(dev, 7) + ); + time_start = sof_cycle_get_64(); + kwd_nn_preprocess_1s(test_keyword_get_input(dev), preprocessed_data); + kwd_nn_process_data(preprocessed_data, confidences); + result = kwd_nn_detect_postprocess(confidences); + time_stop = sof_cycle_get_64(); + comp_dbg(dev, + "KWD: inference done in %u ms", + (unsigned int)k_cyc_to_ms_near64(time_stop - time_start)); + switch (result) { + case KWD_NN_YES_KEYWORD: + case KWD_NN_NO_KEYWORD: + if (result == KWD_NN_NO_KEYWORD) + comp_info(dev, + "keyword NO detected confidence %d", + confidences[3]); + else + comp_info(dev, + "keyword YES detected confidences %d", + confidences[2]); + /* The algorithm shall use cd->drain_req + * to specify its draining size request. + * Zero value means default config value + * will be used. + */ + test_keyword_set_drain_req(dev, 0); + detect_test_notify(dev); + test_keyword_set_detected(dev, 1); + break; + default: + if (result == KWD_NN_SILENCE) + comp_dbg(dev, + "detect_test_copy(): SILENCE detected conf %d", + confidences[0]); + else if (result == KWD_NN_UNKNOWN) + comp_dbg(dev, + "detect_test_copy(): UNKNOWN detected conf %d", + confidences[1]); + /* now shift input buffer half second left */ + for (i = half_sec_samples, j = 0; + i < test_keyword_get_input_size(dev); i++, j++) + /* input[j] = input[i] */ + test_keyword_set_input_elem(dev, j, + test_keyword_get_input_elem + (dev, i)); + test_keyword_set_input_size(dev, + test_keyword_get_input_size(dev) - + half_sec_samples); + break; + } + } + } +} diff --git a/src/samples/audio/smart_amp_test.toml b/src/samples/audio/smart_amp_test.toml new file mode 100644 index 000000000000..1576ed449bf6 --- /dev/null +++ b/src/samples/audio/smart_amp_test.toml @@ -0,0 +1,31 @@ +#ifndef LOAD_TYPE +#define LOAD_TYPE "0" +#endif + + REM # smart amp test module config + [[module.entry]] + name = "SMATEST" + uuid = UUIDREG_STR_SMART_AMP_TEST + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = LOAD_TYPE + init_config = "1" + module_type = "0xD" + auto_start = "0" + sched_caps = [1, 0x00008000] + + REM # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 0, 0, 0xfeef, 0xf, 0xa, 0x45ff, + 1, 0, 0xfeef, 0xf, 0xa, 0x45ff] + + REM # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] +#ifdef CONFIG_METEORLAKE + mod_cfg = [0, 0, 0, 0, 296, 5000000, 384, 384, 0, 5000, 0] +#elif defined(CONFIG_LUNARLAKE) || defined(CONFIG_SOC_ACE30) || \ + defined(CONFIG_SOC_ACE40) + mod_cfg = [0, 0, 0, 0, 4096, 1000000, 128, 128, 0, 0, 0] +#endif + + index = __COUNTER__ diff --git a/src/samples/audio/smart_amp_test_ipc3.c b/src/samples/audio/smart_amp_test_ipc3.c new file mode 100644 index 000000000000..3e69bb5f308e --- /dev/null +++ b/src/samples/audio/smart_amp_test_ipc3.c @@ -0,0 +1,563 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> + +#include <sof/compiler_attributes.h> +#include <sof/samples/audio/smart_amp_test.h> +#include <sof/audio/ipc-config.h> +#include <sof/trace/trace.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/ut.h> + +#ifndef __ZEPHYR__ +#include <rtos/mutex.h> +#endif + +static const struct comp_driver comp_smart_amp; + +LOG_MODULE_REGISTER(smart_amp_test, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(smart_amp_test); + +DECLARE_TR_CTX(smart_amp_test_comp_tr, SOF_UUID(smart_amp_test_uuid), + LOG_LEVEL_INFO); + +typedef int(*smart_amp_proc)(struct comp_dev *dev, + const struct audio_stream *source, + const struct audio_stream *sink, uint32_t frames, + int8_t *chan_map); + +struct smart_amp_data { + struct sof_smart_amp_config config; + struct comp_data_blob_handler *model_handler; + void *data_blob; + size_t data_blob_size; + + struct comp_buffer *source_buf; /**< stream source buffer */ + struct comp_buffer *feedback_buf; /**< feedback source buffer */ + struct comp_buffer *sink_buf; /**< sink buffer */ + + smart_amp_proc process; + + uint32_t in_channels; + uint32_t out_channels; +}; + +static struct comp_dev *smart_amp_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + const struct ipc_config_process *ipc_sa = spec; + const struct sof_smart_amp_config *cfg; + struct smart_amp_data *sad; + struct comp_dev *dev; + size_t bs; + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + sad = rzalloc(SOF_MEM_FLAG_USER, sizeof(*sad)); + if (!sad) + goto fail; + + comp_set_drvdata(dev, sad); + + /* component model data handler */ + sad->model_handler = comp_data_blob_handler_new(dev); + if (!sad->model_handler) + goto sad_fail; + + + cfg = (struct sof_smart_amp_config *)ipc_sa->data; + bs = ipc_sa->size; + 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); + dev->state = COMP_STATE_READY; + + return dev; + +sad_fail: + comp_data_blob_handler_free(sad->model_handler); + rfree(sad); +fail: + comp_free_device(dev); + return NULL; +} + +static void smart_amp_set_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + /* nothing to do */ +} + +static int smart_amp_set_config(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + struct sof_smart_amp_config *cfg; + size_t bs; + + /* Copy new config, find size from header */ + cfg = (struct sof_smart_amp_config *) + ASSUME_ALIGNED(&cdata->data->data, sizeof(uint32_t)); + bs = cfg->size; + + comp_dbg(dev, "actual blob size = %zu, expected blob size = %zu", + bs, sizeof(struct sof_smart_amp_config)); + + if (bs != sizeof(struct sof_smart_amp_config)) { + comp_err(dev, "invalid blob size, actual blob size = %zu, expected blob size = %zu", + bs, sizeof(struct sof_smart_amp_config)); + return -EINVAL; + } + + memcpy_s(&sad->config, sizeof(struct sof_smart_amp_config), cfg, + sizeof(struct sof_smart_amp_config)); + + return 0; +} + +static int smart_amp_get_config(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, int size) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + size_t bs; + int ret; + + /* Copy back to user space */ + bs = sad->config.size; + + comp_dbg(dev, "smart_amp_set_config(), actual blob size = %zu, expected blob size = %zu", + bs, sizeof(struct sof_smart_amp_config)); + + if (bs == 0 || bs > size) + return -EINVAL; + + ret = memcpy_s(cdata->data->data, size, &sad->config, bs); + assert(!ret); + + cdata->data->abi = SOF_ABI_VERSION; + cdata->data->size = bs; + + return ret; +} + +static int smart_amp_ctrl_get_bin_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, + int size) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + + assert(sad); + + switch (cdata->data->type) { + case SOF_SMART_AMP_CONFIG: + return smart_amp_get_config(dev, cdata, size); + case SOF_SMART_AMP_MODEL: + return comp_data_blob_get_cmd(sad->model_handler, cdata, size); + default: + comp_warn(dev, "unknown binary data type"); + break; + } + + return 0; +} + +static int smart_amp_ctrl_get_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata, int size) +{ + comp_info(dev, "size: %d", size); + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return smart_amp_ctrl_get_bin_data(dev, cdata, size); + default: + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } +} + +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); + + assert(sad); + + if (dev->state < COMP_STATE_READY) { + comp_err(dev, "driver in init!"); + return -EBUSY; + } + + switch (cdata->data->type) { + case SOF_SMART_AMP_CONFIG: + return smart_amp_set_config(dev, cdata); + case SOF_SMART_AMP_MODEL: + return comp_data_blob_set_cmd(sad->model_handler, cdata); + default: + comp_warn(dev, "unknown binary data type"); + break; + } + + return 0; +} + +static int smart_amp_ctrl_set_data(struct comp_dev *dev, + struct sof_ipc_ctrl_data *cdata) +{ + /* Check version from ABI header */ + if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { + comp_err(dev, "invalid version"); + return -EINVAL; + } + + switch (cdata->cmd) { + case SOF_CTRL_CMD_ENUM: + comp_info(dev, "SOF_CTRL_CMD_ENUM"); + break; + case SOF_CTRL_CMD_BINARY: + comp_info(dev, "SOF_CTRL_CMD_BINARY"); + return smart_amp_ctrl_set_bin_data(dev, cdata); + default: + comp_err(dev, "invalid cdata->cmd"); + return -EINVAL; + } + + return 0; +} + +/* used to pass standard and bespoke commands (with data) to component */ +static int smart_amp_cmd(struct comp_dev *dev, int cmd, void *data, + int max_data_size) +{ + struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); + + comp_info(dev, "cmd: %d", cmd); + + switch (cmd) { + case COMP_CMD_SET_DATA: + return smart_amp_ctrl_set_data(dev, cdata); + case COMP_CMD_GET_DATA: + return smart_amp_ctrl_get_data(dev, cdata, max_data_size); + default: + return -EINVAL; + } +} + +static void smart_amp_free(struct comp_dev *dev) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + + comp_info(dev, "entry"); + + comp_data_blob_handler_free(sad->model_handler); + + rfree(sad); + comp_free_device(dev); +} + +static int smart_amp_verify_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + int ret; + + comp_info(dev, "entry"); + + ret = comp_verify_params(dev, BUFF_PARAMS_CHANNELS, params); + if (ret < 0) { + comp_err(dev, "error: comp_verify_params() failed."); + return ret; + } + + return 0; +} + +static int smart_amp_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + int err; + + comp_info(dev, "entry"); + + smart_amp_set_params(dev, params); + + err = smart_amp_verify_params(dev, params); + if (err < 0) { + comp_err(dev, "pcm params verification failed."); + return err; + } + + return 0; +} + +static int smart_amp_trigger(struct comp_dev *dev, int cmd) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + int ret = 0; + + comp_info(dev, "command = %u", cmd); + + ret = comp_set_state(dev, cmd); + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + switch (cmd) { + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + if (sad->feedback_buf) { + buffer_zero(sad->feedback_buf); + } + break; + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + break; + default: + break; + } + + return ret; +} + +static int smart_amp_process_s16(struct comp_dev *dev, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames, int8_t *chan_map) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + int16_t *src; + int16_t *dest; + uint32_t in_frag = 0; + uint32_t out_frag = 0; + int i; + int j; + + comp_dbg(dev, "entry"); + + 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 comp_dev *dev, + const struct audio_stream *source, + const struct audio_stream *sink, + uint32_t frames, int8_t *chan_map) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + int32_t *src; + int32_t *dest; + uint32_t in_frag = 0; + uint32_t out_frag = 0; + int i; + int j; + + comp_dbg(dev, "entry"); + + 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 *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_copy(struct comp_dev *dev) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + struct comp_buffer *source_buf = sad->source_buf; + struct comp_buffer *sink_buf = sad->sink_buf; + uint32_t avail_passthrough_frames; + uint32_t avail_feedback_frames; + uint32_t avail_frames = 0; + uint32_t source_bytes; + uint32_t sink_bytes; + uint32_t feedback_bytes; + + comp_dbg(dev, "entry"); + + /* available bytes and samples calculation */ + avail_passthrough_frames = + audio_stream_avail_frames(&source_buf->stream, + &sink_buf->stream); + + if (sad->feedback_buf) { + struct comp_buffer *buf = sad->feedback_buf; + + if (comp_buffer_get_source_state(buf) == dev->state) { + /* feedback */ + avail_feedback_frames = + audio_stream_get_avail_frames(&buf->stream); + + avail_frames = MIN(avail_passthrough_frames, + avail_feedback_frames); + + feedback_bytes = avail_frames * + audio_stream_frame_bytes(&buf->stream); + + comp_dbg(dev, "processing %d feedback frames (avail_passthrough_frames: %d)", + avail_frames, avail_passthrough_frames); + + /* perform buffer writeback after source_buf process */ + buffer_stream_invalidate(buf, feedback_bytes); + sad->process(dev, &buf->stream, &sink_buf->stream, + avail_frames, sad->config.feedback_ch_map); + + comp_update_buffer_consume(buf, feedback_bytes); + } + } + + if (!avail_frames) + avail_frames = avail_passthrough_frames; + /* bytes calculation */ + source_bytes = avail_frames * + audio_stream_frame_bytes(&source_buf->stream); + + sink_bytes = avail_frames * + audio_stream_frame_bytes(&sink_buf->stream); + + /* process data */ + buffer_stream_invalidate(source_buf, source_bytes); + sad->process(dev, &source_buf->stream, &sink_buf->stream, + avail_frames, sad->config.source_ch_map); + buffer_stream_writeback(sink_buf, sink_bytes); + + /* source/sink buffer pointers update */ + comp_update_buffer_consume(source_buf, source_bytes); + comp_update_buffer_produce(sink_buf, sink_bytes); + + return 0; +} + +static int smart_amp_reset(struct comp_dev *dev) +{ + comp_info(dev, "entry"); + + comp_set_state(dev, COMP_TRIGGER_RESET); + + return 0; +} + +static int smart_amp_prepare(struct comp_dev *dev) +{ + struct smart_amp_data *sad = comp_get_drvdata(dev); + struct comp_buffer *source_buffer; + int ret; + + comp_info(dev, "entry"); + + 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; + + /* searching for stream and feedback source buffers */ + comp_dev_for_each_producer(dev, source_buffer) { + /* FIXME: how often can this loop be run? */ + if (comp_buffer_get_source_component(source_buffer)->ipc_config.type == + SOF_COMP_DEMUX) + sad->feedback_buf = source_buffer; + else + sad->source_buf = source_buffer; + } + + sad->sink_buf = comp_dev_get_first_data_consumer(dev); + if (!sad->sink_buf) { + comp_err(dev, "no sink buffer"); + return -ENOTCONN; + } + + sad->out_channels = audio_stream_get_channels(&sad->sink_buf->stream); + + sad->in_channels = audio_stream_get_channels(&sad->source_buf->stream); + + if (sad->feedback_buf) { + audio_stream_set_channels(&sad->feedback_buf->stream, + sad->config.feedback_channels); + audio_stream_set_rate(&sad->feedback_buf->stream, + audio_stream_get_rate(&sad->source_buf->stream)); + } + + sad->process = get_smart_amp_process(dev, sad->source_buf); + if (!sad->process) { + comp_err(dev, "get_smart_amp_process failed"); + ret = -EINVAL; + } + return ret; +} + +static const struct comp_driver comp_smart_amp = { + .type = SOF_COMP_SMART_AMP, + .uid = SOF_RT_UUID(smart_amp_test_uuid), + .tctx = &smart_amp_test_comp_tr, + .ops = { + .create = smart_amp_new, + .free = smart_amp_free, + .params = smart_amp_params, + .prepare = smart_amp_prepare, + .cmd = smart_amp_cmd, + .trigger = smart_amp_trigger, + .copy = smart_amp_copy, + .reset = smart_amp_reset, + }, +}; + +static SHARED_DATA struct comp_driver_info comp_smart_amp_info = { + .drv = &comp_smart_amp, +}; + +UT_STATIC void sys_comp_smart_amp_test_init(void) +{ + comp_register(platform_shared_get(&comp_smart_amp_info, + sizeof(comp_smart_amp_info))); +} + +DECLARE_MODULE(sys_comp_smart_amp_test_init); +SOF_MODULE_INIT(smart_amp_test, sys_comp_smart_amp_test_init); 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..89d5861fed71 --- /dev/null +++ b/src/samples/audio/smart_amp_test_ipc4.c @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> +#include <sof/compiler_attributes.h> +#include <sof/samples/audio/smart_amp_test.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/ipc-config.h> +#include <sof/trace/trace.h> +#include <sof/ipc/msg.h> +#include <rtos/init.h> +#include <sof/ut.h> + +#ifndef __ZEPHYR__ +#include <rtos/mutex.h> +#endif +#include <ipc4/module.h> + +LOG_MODULE_REGISTER(smart_amp_test, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(smart_amp_test); + +DECLARE_TR_CTX(smart_amp_test_comp_tr, SOF_UUID(smart_amp_test_uuid), + LOG_LEVEL_INFO); + +typedef void (*smart_amp_proc)(int8_t const *src_ptr, + int8_t const *src_begin, + int8_t const *src_end, + int8_t *dst_ptr, + int8_t const *dst_begin, + int8_t const *dst_end, + uint32_t size); + +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; +}; + +/* When building as a loadable module, we need .bss to avoid rimage errors */ +static int keep_bss __attribute__((used)); + +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; + const struct ipc4_base_module_extended_cfg *base_cfg = mod_data->cfg.init_data; + int ret; + + if (!base_cfg) { + comp_err(dev, "No module configuration"); + return -EINVAL; + } + + comp_dbg(dev, "entry"); + + sad = mod_zalloc(mod, sizeof(*sad)); + if (!sad) + return -ENOMEM; + + mod_data->private = sad; + + /* component model data handler */ + sad->model_handler = mod_data_blob_handler_new(mod); + 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, "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->max_sources = SMART_AMP_NUM_IN_PINS; + + return 0; + +sad_fail: + mod_data_blob_handler_free(mod, sad->model_handler); + mod_free(mod, sad); + + return ret; +} + +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, "entry"); + + 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, "invalid config size %u, expect %u", + fragment_size, sizeof(struct sof_smart_amp_config)); + return -EINVAL; + } + comp_dbg(dev, "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, "entry"); + + switch (config_id) { + case SMART_AMP_GET_CONFIG: + ret = memcpy_s(fragment, fragment_size, &sad->config, sizeof(sad->config)); + if (ret) { + comp_err(dev, "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, "entry"); + mod_data_blob_handler_free(mod, sad->model_handler); + mod_free(mod, sad); + + return 0; +} + +static void process_s16(int8_t const *src_ptr, + int8_t const *src_begin, + int8_t const *src_end, + int8_t *dst_ptr, + int8_t const *dst_begin, + int8_t const *dst_end, + uint32_t size) +{ + int16_t const *src_addr = (int16_t const *)src_ptr; + int16_t *dst_addr = (int16_t *)dst_ptr; + int count = size >> 1; + int i; + + for (i = 0; i < count; i++) { + if (src_addr >= (int16_t const *)src_end) + src_addr = (int16_t const *)src_begin; + + if (dst_addr >= (int16_t *)dst_end) + dst_addr = (int16_t *)dst_begin; + + *dst_addr = *src_addr; + src_addr++; + dst_addr++; + } +} + +static void process_s32(int8_t const *src_ptr, + int8_t const *src_begin, + int8_t const *src_end, + int8_t *dst_ptr, + int8_t const *dst_begin, + int8_t const *dst_end, + uint32_t size) +{ + int32_t const *src_addr = (int32_t const *)src_ptr; + int32_t *dst_addr = (int32_t *)dst_ptr; + int count = size >> 2; + int i; + + for (i = 0; i < count; i++) { + if (src_addr >= (int32_t const *)src_end) + src_addr = (int32_t const *)src_begin; + + if (dst_addr >= (int32_t *)dst_end) + dst_addr = (int32_t *)dst_begin; + + *dst_addr = *src_addr; + src_addr++; + dst_addr++; + } +} + +static int smart_amp_process_data(struct processing_module *mod, + struct sof_source *source, + struct sof_source *feedback, + struct sof_sink *sink, + size_t size) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + int8_t const *src_ptr; + int8_t const *src_begin; + int8_t const *src_end; + int8_t *dst_ptr; + int8_t const *dst_begin; + int8_t const *dst_end; + size_t src_size; + size_t dst_size; + int ret; + + ret = sink_get_buffer(sink, size, + (void **)&dst_ptr, + (void **)&dst_begin, + &dst_size); + if (ret) + return ret; + + if (!feedback || !source_get_data_available(feedback)) + goto source; + + ret = source_get_data(feedback, size, + (void const **)&src_ptr, + (void const **)&src_begin, + &src_size); + if (ret) { + if (ret == -EBUSY) + return 0; + else + return ret; + } + + src_end = src_begin + src_size; + dst_end = dst_begin + dst_size; + sad->process(src_ptr, src_begin, src_end, dst_ptr, dst_begin, dst_end, size); + source_release_data(feedback, size); + +source: + ret = source_get_data(source, size, + (void const **)&src_ptr, + (void const **)&src_begin, + &src_size); + if (ret) + return ret; + + src_end = src_begin + src_size; + dst_end = dst_begin + dst_size; + sad->process(src_ptr, src_begin, src_end, dst_ptr, dst_begin, dst_end, size); + source_release_data(source, size); + sink_commit_buffer(sink, size); + return 0; +} + +static int smart_amp_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct sof_source *fb_input = NULL; + /* if there is only one input stream, it should be the source input */ + struct sof_source *src_input = sources[0]; + uint32_t avail_passthrough; + uint32_t avail = 0; + uint32_t i; + int ret; + + if (num_of_sources == SMART_AMP_NUM_IN_PINS) { + for (i = 0; i < num_of_sources; i++) { + if (IPC4_SINK_QUEUE_ID(source_get_id(sources[i])) == + SOF_SMART_AMP_FEEDBACK_QUEUE_ID) { + fb_input = sources[i]; + } else { + src_input = sources[i]; + } + } + } + + avail_passthrough = source_get_data_available(src_input); + + if (fb_input && source_get_data_available(fb_input)) { + /* feedback */ + avail = MIN(avail_passthrough, source_get_data_available(fb_input)); + avail = MIN(avail, sink_get_free_size(sinks[0])); + } else { + avail = MIN(avail_passthrough, sink_get_free_size(sinks[0])); + } + + /* process data */ + ret = smart_amp_process_data(mod, src_input, fb_input, sinks[0], avail); + + return ret; +} + +static int smart_amp_reset(struct processing_module *mod) +{ + return 0; +} + +static smart_amp_proc get_smart_amp_process(struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + /* Find if any of the sources/sinks needs 16bit process, else use 32bit */ + for (int i = 0; i < num_of_sources; i++) { + switch (source_get_frm_fmt(sources[i])) { + case SOF_IPC_FRAME_S16_LE: + return process_s16; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + break; + default: + return NULL; + } + } + for (int i = 0; i < num_of_sinks; i++) { + switch (sink_get_frm_fmt(sinks[i])) { + case SOF_IPC_FRAME_S16_LE: + return process_s16; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + break; + default: + return NULL; + } + } + return process_s32; +} + +static int smart_amp_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + sad->process = get_smart_amp_process(sources, num_of_sources, sinks, num_of_sinks); + if (!sad->process) { + comp_err(dev, "get_smart_amp_process() failed"); + return -EINVAL; + } + + return 0; +} + +static const struct module_interface smart_amp_test_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 +}; + +#if CONFIG_SAMPLE_SMART_AMP_MODULE +/* modular: llext dynamic link */ + +#include <module/module/api_ver.h> +#include <module/module/llext.h> +#include <rimage/sof/user/manifest.h> + +static const struct sof_man_module_manifest mod_manifest[] __section(".module") __used = { + SOF_LLEXT_MODULE_MANIFEST("SMATEST", &smart_amp_test_interface, 1, + SOF_REG_UUID(smart_amp_test), 1), +}; + +SOF_LLEXT_BUILDINFO; + +#else + +DECLARE_MODULE_ADAPTER(smart_amp_test_interface, smart_amp_test_uuid, smart_amp_test_comp_tr); +SOF_MODULE_INIT(smart_amp_test, sys_comp_module_smart_amp_test_interface_init); + +#endif diff --git a/src/samples/audio/smart_amp_test_llext/CMakeLists.txt b/src/samples/audio/smart_amp_test_llext/CMakeLists.txt new file mode 100644 index 000000000000..804ab497d4e7 --- /dev/null +++ b/src/samples/audio/smart_amp_test_llext/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +sof_llext_build("smart_amp_test" + SOURCES ../smart_amp_test_ipc4.c + LIB openmodules +) diff --git a/src/samples/audio/smart_amp_test_llext/llext.toml.h b/src/samples/audio/smart_amp_test_llext/llext.toml.h new file mode 100644 index 000000000000..eb6fcfac7d24 --- /dev/null +++ b/src/samples/audio/smart_amp_test_llext/llext.toml.h @@ -0,0 +1,6 @@ +#include <tools/rimage/config/platform.toml> +#define LOAD_TYPE "2" +#include "../smart_amp_test.toml" + +[module] +count = __COUNTER__ diff --git a/src/schedule/CMakeLists.txt b/src/schedule/CMakeLists.txt index 5726d6586831..622b75e46888 100644 --- a/src/schedule/CMakeLists.txt +++ b/src/schedule/CMakeLists.txt @@ -1,11 +1,61 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof - dma_multi_chan_domain.c - dma_single_chan_domain.c - edf_schedule.c - ll_schedule.c +set(base_files schedule.c - task.c - timer_domain.c ) + +if(CONFIG_SCHEDULE_DMA_MULTI_CHANNEL AND NOT(CONFIG_DMA_DOMAIN)) + list(APPEND base_files dma_multi_chan_domain.c) +endif() + +if(CONFIG_SCHEDULE_DMA_SINGLE_CHANNEL AND NOT(CONFIG_DMA_DOMAIN)) + list(APPEND base_files dma_single_chan_domain.c) +endif() + +is_zephyr(zephyr) +if(zephyr) ### Zephyr ### + +zephyr_library_sources( + ${base_files} + zephyr_domain.c +) + +if (CONFIG_SOC_ACP_6_0) + # Zephyr DMA domain should only be used with zephyr_ll + if (CONFIG_DMA_DOMAIN) + zephyr_library_sources( + zephyr_ll.c + zephyr_dma_domain.c + ) + else() + zephyr_library_sources( + ll_schedule_xtos.c + ) + endif() +else() + zephyr_library_sources( + zephyr_ll.c + ) +endif() + +if (CONFIG_SOF_USERSPACE_APPLICATION) + zephyr_library_sources_ifdef(CONFIG_ZEPHYR_DP_SCHEDULER + zephyr_dp_schedule.c + zephyr_dp_schedule_application.c + ) +else() + zephyr_library_sources_ifdef(CONFIG_ZEPHYR_DP_SCHEDULER + zephyr_dp_schedule.c + zephyr_dp_schedule_thread.c + ) +endif() + +zephyr_library_sources_ifdef(CONFIG_ZEPHYR_TWB_SCHEDULER + zephyr_twb_schedule.c +) + +zephyr_library_sources_ifdef(CONFIG_SOF_USERSPACE_LL + zephyr_ll_user.c +) + +endif() diff --git a/src/schedule/Kconfig b/src/schedule/Kconfig new file mode 100644 index 000000000000..f1383e70103f --- /dev/null +++ b/src/schedule/Kconfig @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config SCHEDULE_DMA_SINGLE_CHANNEL + bool + default n + help + Enable single-channel DMA scheduler + +config SCHEDULE_DMA_MULTI_CHANNEL + bool + default n + help + Enable multi-channel DMA scheduler + +config SCHEDULE_LL_STATS_LOG + bool "Log low-latency scheduler statistics" + default y + depends on !SOF_USERSPACE_LL + help + Log statistics from low-latency scheduler. This is a low overhead + mechanism to gather average and worst-case execution times of + the low-latency scheduler invocations. A report is printed to + logging subsystem (rate defined via SCHEDULE_LL_STATS_LOG_WINDOW_SIZE). + +config SCHEDULE_LL_STATS_LOG_EVERY_OTHER_WINDOW + bool "Log only every other low-latency report" + default y + depends on SCHEDULE_LL_STATS_LOG + help + Output statistics for every other statistics gathering window. + This is useful to filter out impact of the reporting itself. With many + logging implementations, the first iteration has a spike in + execution caused by logging out results for the previous statistics + window. By skipping every other window, the reporting overhead + can be excluded. + +config SCHEDULE_LL_STATS_LOG_WINDOW_SIZE + int "Low latency statistics window size" + default 10 + depends on SCHEDULE_LL_STATS_LOG + help + Size of the statistics window as a power of two. The window size + setting also impacts the rate of reporting. With 1ms scheduler tick, + default of 10 results in 1024msec window size. + +config SCHEDULE_LL_NO_RESCHEDULE_TASK + bool "Low-latency scheduler skips task rescheduling" + default n + help + Select this to instantiate the low-latency scheduler without task + rescheduling, given that the operation is optional. Under such cases, + scheduler_ops::reschedule_task will set to NULL instead, tasks with + the attempt to reschedule (e.g. DMA trace works) will be relinguished + directly and return no error. + +config ZEPHYR_TWB_SCHEDULER + bool "use Zephyr thread based TWB scheduler" + default n + depends on ZEPHYR_SOF_MODULE + depends on TIMESLICE_PER_THREAD + depends on THREAD_RUNTIME_STATS + depends on SCHED_THREAD_USAGE + help + Enable Tasks with Budget preemptive scheduler based on + Zephyr preemptive threads for each SOF task that has pre-allocated + MCPS budget renewed with every system tick. + +config TWB_IPC_TASK + bool "use TWB scheduler for IPC task" + default n + depends on ZEPHYR_TWB_SCHEDULER + help + Switch IPC task to TWB scheduler. diff --git a/src/schedule/Kconfig.threads_prio b/src/schedule/Kconfig.threads_prio new file mode 100644 index 000000000000..a7d51c666b63 --- /dev/null +++ b/src/schedule/Kconfig.threads_prio @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: BSD-3-Clause + +config LL_THREAD_PRIORITY + int "LL thread cooperative high priority" + default -16 + help + LL thread configured priority in the system. + Should be in cooperative range: + -NUM_COOP_PRIORITIES to -1 + +config TWB_THREAD_MEDIUM_PRIORITY + int "TWB thread preemptible medium priority" + default 1 + help + TWB thread configured priority in the system. + Should be in preemptible range: + 0 to NUM_PREEMPT_PRIORITIES-1 + +config TWB_THREAD_LOW_PRIORITY + int "TWB thread preemptible low priority" + default 12 + help + TWB thread configured priority in the system. + Should be in preemptible range: + 0 to NUM_PREEMPT_PRIORITIES-1 + +config DP_THREAD_PRIORITY + int "DP thread preemptible low priority" + default 12 + help + DP thread configured priority in the system. + Should be in preemptible range: + 0 to NUM_PREEMPT_PRIORITIES-1 + +config EDF_THREAD_PRIORITY + int "EDF thread preemptible low priority" + default 1 + help + EDF thread configured priority in the system. + Should be in preemptible range: + 0 to NUM_PREEMPT_PRIORITIES-1 diff --git a/src/schedule/README.md b/src/schedule/README.md new file mode 100644 index 000000000000..493ab092decc --- /dev/null +++ b/src/schedule/README.md @@ -0,0 +1,168 @@ +# SOF Scheduling Architecture + +This directory (`src/schedule`) contains the Sound Open Firmware (SOF) scheduling infrastructure, deeply integrated with the underlying Zephyr RTOS. SOF utilizes a multi-tiered scheduling approach to cater to different real-time constraints, ranging from hard real-time, low-latency requirements to more relaxed, compute-intensive data processing tasks. + +## Overview of Schedulers + +SOF categorizes tasks and assigns them to specialized schedulers: + +1. **LL (Low Latency) Scheduler**: For tasks that require strict, predictable, and lowest possible latency bound to hardware events (Timers, DMA interrupts). +2. **DP (Data Processing) Scheduler**: For compute-intensive components that process large chunks of data and operate on deadlines rather than strict cycles. +3. **TWB (Thread With Budget) Scheduler**: For tasks that are allotted a specific execution "budget" per scheduler tick, expressed in Zephyr time-slice ticks (e.g. derived from `ZEPHYR_TWB_BUDGET_MAX` in OS ticks), which the runtime then uses to limit and account for CPU cycles to prevent starvation. + +Below is a high-level component interaction architecture of the SOF scheduling domains on top of Zephyr. + +```mermaid +graph TD + subgraph Zephyr RTOS + Timer[Hardware Timer] + DMA[DMA Controller] + Threads[Zephyr Threads] + end + + subgraph Generic Scheduler API + API[schedule.c API] + end + + subgraph LL Scheduler Domain + LL[zephyr_ll.c] + LLDomain[zephyr_domain.c] + DMADomain[zephyr_dma_domain.c] + end + + subgraph DP Scheduler Domain + DP[zephyr_dp_schedule.c] + DPThread[zephyr_dp_schedule_thread.c] + end + + subgraph TWB Scheduler Domain + TWB[zephyr_twb_schedule.c] + end + + API --> LL + API --> DP + API --> TWB + + Timer -.->|Interrupt| LLDomain + DMA -.->|Interrupt| DMADomain + + LLDomain --> |Wakeup| LL + DMADomain --> |Wakeup| LL + LL -->|Runs tasks| Threads + + LL -->|NOTIFIER_ID_LL_POST_RUN| DP + DP -->|Recalculate Deadlines| DPThread + DPThread -->|Update Thread Deadlines| Threads + + LL -->|LL Tick Source| TWB + TWB -->|Update Time Slices| Threads +``` + +--- + +## 1. LL (Low Latency) Scheduler + +The LL scheduler (`zephyr_ll.c`) is designed for extreme low-latency processing. It bypasses complex generic Zephyr scheduling for its internal tasks to minimize overhead, executing a list of registered SOF tasks in a strict priority order. + +### Architecture + +- **Domain Threads**: The LL scheduler runs within a dedicated high-priority Zephyr thread (`ll_thread0`, etc.) pinned to each core (`zephyr_domain.c`). +- **Triggers**: It is woken up by a hardware timer (e.g., a 1ms tick) or directly by hardware DMA interrupts (`zephyr_dma_domain.c`). +- **Execution**: Once woken up, it locks the domain, iterates through all scheduled tasks in priority order, moves them to a temporary list, and calls their `.run()` functions. +- **Post-Run**: After all tasks execute, it triggers a `NOTIFIER_ID_LL_POST_RUN` event. This event cascades to wake up other dependent schedulers like DP and TWB. Event not run on LL userspace configuration. + +### Task State Diagram + +```mermaid +stateDiagram-v2 + [*] --> INIT: task_init + INIT --> QUEUED: schedule_task + QUEUED --> RUNNING: zephyr_ll_run (Timer/DMA Tick) + RUNNING --> RUNNING: return RESCHEDULE + RUNNING --> FREE: return COMPLETED + RUNNING --> CANCEL: task_cancel + + QUEUED --> CANCEL: task_cancel + CANCEL --> FREE: task_free + + FREE --> [*] +``` + +*(Note: State transitions handle Zephyr SMP locking to ensure a task is safely dequeued before state shifts)* + +--- + +## 2. DP (Data Processing) Scheduler + +The DP scheduler (`zephyr_dp_schedule.c`) manages asynchronous, compute-heavy tasks that process data when enough input is available and sufficient output space is free. It effectively relies on Zephyr's EDF (Earliest Deadline First) or standard preemptive scheduling capabilities. + +### Architecture + +- **Separate Threads**: Unlike LL which multiplexes tasks inside a single thread, **each DP task is assigned its own Zephyr thread**. +- **Wakeup Mechanism**: DP scheduling is evaluated at the end of each LL tick (`scheduler_dp_recalculate()`). +- **Readiness**: It checks if a component has sufficient data across its sinks and sources. If so, it transitions to `RUNNING` and signals the individual DP thread via a Zephyr Event object. +- **Deadlines**: Once ready, the DP thread computes its deadline absolute timestamp (`module_get_deadline()`) and calls `k_thread_absolute_deadline_set()`, submitting to the Zephyr kernel's EDF scheduler. + +### Task State Diagram + +```mermaid +stateDiagram-v2 + [*] --> INIT: task_init + INIT --> QUEUED: schedule_task + + note right of QUEUED + Wait for LL POST RUN event + to evaluate Readiness. + end note + + QUEUED --> RUNNING: resources ready (set priority/deadline) + RUNNING --> QUEUED: return RESCHEDULE (processed chunk) + RUNNING --> COMPLETED: return COMPLETED + RUNNING --> CANCEL: task_cancel + + QUEUED --> CANCEL: task_cancel + COMPLETED --> FREE: task_free + CANCEL --> FREE: task_free + + FREE --> [*] +``` + +--- + +## 3. TWB (Thread With Budget) Scheduler + +The TWB scheduler (`zephyr_twb_schedule.c`) provides execution budget limits for specific tasks to prevent them from starving the CPU. This is useful for intensive workloads that shouldn't disrupt the overall systemic low-latency chain. + +### Architecture + +- **Separate Threads**: Similar to DP, each TWB task executes in its own Zephyr thread. +- **Time Slicing**: When scheduled, the thread's execution budget is configured in OS ticks via `k_thread_time_slice_set()`. This tick-based budget is internally converted to hardware cycles for accounting against the CPU cycles actually consumed. +- **Budget Exhaustion**: If the thread consumes its budget (as measured in hardware cycles derived from the tick budget) before completing its work for the tick, a callback (`scheduler_twb_task_cb()`) is invoked by the Zephyr kernel. This callback immediately drops the thread's priority to a background level (`CONFIG_TWB_THREAD_LOW_PRIORITY`), preventing starvation of other threads. +- **Replenishment**: On the next LL tick (`scheduler_twb_ll_tick()`), the consumed hardware cycles are reset, and the thread's original priority and time slice are restored, granting it a fresh tick-based budget. + +### Task State Diagram + +```mermaid +stateDiagram-v2 + [*] --> INIT: task_init + INIT --> RUNNING: schedule_task (Thread Created) + + state RUNNING { + [*] --> HighPriority: Budget replenished + HighPriority --> LowPriority: Budget Exhausted (Callback) + LowPriority --> HighPriority: Next LL Tick + } + + RUNNING --> QUEUED: return RESCHEDULE + QUEUED --> RUNNING: Next LL Tick (Restore Priority) + + RUNNING --> CANCEL: task_cancel + QUEUED --> CANCEL: task_cancel + + RUNNING --> COMPLETED: return COMPLETED + + CANCEL --> FREE: task_free + COMPLETED --> FREE: task_free + + FREE --> [*] +``` diff --git a/src/schedule/dma_multi_chan_domain.c b/src/schedule/dma_multi_chan_domain.c index e6c621ae8b7f..7fd478d50afc 100644 --- a/src/schedule/dma_multi_chan_domain.c +++ b/src/schedule/dma_multi_chan_domain.c @@ -5,10 +5,10 @@ // Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> #include <sof/audio/component.h> -#include <sof/bit.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> +#include <rtos/bit.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> #include <sof/lib/cpu.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> @@ -17,12 +17,29 @@ #include <sof/schedule/ll_schedule.h> #include <sof/schedule/ll_schedule_domain.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> +#include <rtos/task.h> #include <ipc/topology.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> +LOG_MODULE_DECLARE(ll_schedule, CONFIG_SOF_LOG_LEVEL); + +/* For i.MX, when building SOF with Zephyr, we use wrapper.c, + * interrupt.c and interrupt-irqsteer.c which causes name + * collisions. + * In order to avoid this and make any second level interrupt + * handling go through interrupt-irqsteer.c define macros to + * rename the duplicated functions. + */ +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +#define interrupt_get_irq mux_interrupt_get_irq +#define interrupt_register mux_interrupt_register +#define interrupt_unregister mux_interrupt_unregister +#define interrupt_enable mux_interrupt_enable +#define interrupt_disable mux_interrupt_disable +#endif + struct dma_domain_data { int irq; struct pipeline_task *task; @@ -36,9 +53,9 @@ struct dma_domain { bool aggregated_irq; /* true if aggregated interrupts */ /* mask of currently running channels */ - uint32_t channel_mask[PLATFORM_NUM_DMACS][PLATFORM_CORE_COUNT]; + uint32_t channel_mask[PLATFORM_NUM_DMACS][CONFIG_CORE_COUNT]; /* array of arguments for aggregated mode */ - struct dma_domain_data *arg[PLATFORM_NUM_DMACS][PLATFORM_CORE_COUNT]; + struct dma_domain_data *arg[PLATFORM_NUM_DMACS][CONFIG_CORE_COUNT]; /* array of registered channels data */ struct dma_domain_data data[PLATFORM_NUM_DMACS][PLATFORM_MAX_DMA_CHAN]; }; @@ -56,7 +73,6 @@ static void dma_multi_chan_domain_irq_handler(void *data) /* just call registered handler */ domain_data->handler(domain_data->arg); - platform_shared_commit(domain_data, sizeof(*domain_data)); } /** @@ -70,7 +86,7 @@ static int dma_multi_chan_domain_irq_register(struct dma_domain_data *data, { int ret; - trace_ll("dma_multi_chan_domain_irq_register()"); + tr_info(&ll_tr, "entry"); /* always go through dma_multi_chan_domain_irq_handler, * so we have different arg registered for every channel @@ -87,8 +103,8 @@ static int dma_multi_chan_domain_irq_register(struct dma_domain_data *data, /** * \brief Registers task to DMA domain. + * * \param[in,out] domain Pointer to schedule domain. - * \param[in] period Period of the scheduled task. * \param[in,out] task Task to be registered. * \param[in,out] handler Pointer to DMA interrupt handler. * \param[in,out] arg Pointer to DMA interrupt handler's argument. @@ -98,7 +114,7 @@ static int dma_multi_chan_domain_irq_register(struct dma_domain_data *data, * DMA interrupts (different irq number per DMA channel). */ static int dma_multi_chan_domain_register(struct ll_schedule_domain *domain, - uint64_t period, struct task *task, + struct task *task, void (*handler)(void *arg), void *arg) { struct dma_domain *dma_domain = ll_sch_domain_get_pdata(domain); @@ -109,14 +125,16 @@ static int dma_multi_chan_domain_register(struct ll_schedule_domain *domain, int i; int j; - trace_ll("dma_multi_chan_domain_register()"); + tr_info(&ll_tr, "entry"); /* check if task should be registered */ if (!pipe_task->registrable) goto out; - for (i = 0; i < dma_domain->num_dma; ++i) { - for (j = 0; j < dmas[i].plat_data.channels; ++j) { + for (i = 0; i < dma_domain->num_dma ; ++i) { + if (dmas[i].chan == NULL) + continue; + for (j = 0; j < dmas[i].plat_data.channels ; ++j) { /* channel not set as scheduling source */ if (!dma_is_scheduling_source(&dmas[i].chan[j])) continue; @@ -133,7 +151,7 @@ static int dma_multi_chan_domain_register(struct ll_schedule_domain *domain, if (dma_domain->channel_mask[i][core] & BIT(j)) continue; - dma_interrupt(&dmas[i].chan[j], DMA_IRQ_CLEAR); + dma_interrupt_legacy(&dmas[i].chan[j], DMA_IRQ_CLEAR); /* register only if not aggregated or not registered */ if (!dma_domain->aggregated_irq || @@ -141,12 +159,8 @@ static int dma_multi_chan_domain_register(struct ll_schedule_domain *domain, ret = dma_multi_chan_domain_irq_register( &dma_domain->data[i][j], handler); - if (ret < 0) { - platform_shared_commit(dmas[i].chan, - sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); + if (ret < 0) goto out; - } dma_domain->data[i][j].handler = handler; dma_domain->data[i][j].arg = arg; @@ -159,26 +173,16 @@ static int dma_multi_chan_domain_register(struct ll_schedule_domain *domain, interrupt_clear_mask(dma_domain->data[i][j].irq, BIT(j)); - dma_interrupt(&dmas[i].chan[j], DMA_IRQ_UNMASK); + dma_interrupt_legacy(&dmas[i].chan[j], DMA_IRQ_UNMASK); dma_domain->data[i][j].task = pipe_task; dma_domain->channel_mask[i][core] |= BIT(j); - platform_shared_commit(dmas[i].chan, - sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); - goto out; } - - platform_shared_commit(dmas[i].chan, sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); } out: - platform_shared_commit(dmas, sizeof(*dmas) * dma_domain->num_dma); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); - return ret; } @@ -188,7 +192,7 @@ static int dma_multi_chan_domain_register(struct ll_schedule_domain *domain, */ static void dma_multi_chan_domain_irq_unregister(struct dma_domain_data *data) { - trace_ll("dma_multi_chan_domain_irq_unregister()"); + tr_info(&ll_tr, "entry"); interrupt_disable(data->irq, data); @@ -200,10 +204,11 @@ static void dma_multi_chan_domain_irq_unregister(struct dma_domain_data *data) * \param[in,out] domain Pointer to schedule domain. * \param[in,out] task Task to be unregistered from the domain.. * \param[in] num_tasks Number of currently scheduled tasks. + * \return Error code. */ -static void dma_multi_chan_domain_unregister(struct ll_schedule_domain *domain, - struct task *task, - uint32_t num_tasks) +static int dma_multi_chan_domain_unregister(struct ll_schedule_domain *domain, + struct task *task, + uint32_t num_tasks) { struct dma_domain *dma_domain = ll_sch_domain_get_pdata(domain); struct pipeline_task *pipe_task = pipeline_task_get(task); @@ -212,14 +217,16 @@ static void dma_multi_chan_domain_unregister(struct ll_schedule_domain *domain, int i; int j; - trace_ll("dma_multi_chan_domain_unregister()"); + tr_info(&ll_tr, "entry"); /* check if task should be unregistered */ - if (!pipe_task->registrable) - goto out; + if (!task || !pipe_task->registrable) + return 0; for (i = 0; i < dma_domain->num_dma; ++i) { - for (j = 0; j < dmas[i].plat_data.channels; ++j) { + if (dmas[i].chan == NULL) + continue; + for (j = 0; j < dmas[i].plat_data.channels ; ++j) { /* channel not set as scheduling source */ if (!dma_is_scheduling_source(&dmas[i].chan[j])) continue; @@ -236,8 +243,8 @@ static void dma_multi_chan_domain_unregister(struct ll_schedule_domain *domain, if (!(dma_domain->channel_mask[i][core] & BIT(j))) continue; - dma_interrupt(&dmas[i].chan[j], DMA_IRQ_MASK); - dma_interrupt(&dmas[i].chan[j], DMA_IRQ_CLEAR); + dma_interrupt_legacy(&dmas[i].chan[j], DMA_IRQ_MASK); + dma_interrupt_legacy(&dmas[i].chan[j], DMA_IRQ_CLEAR); interrupt_clear_mask(dma_domain->data[i][j].irq, BIT(j)); @@ -251,21 +258,12 @@ static void dma_multi_chan_domain_unregister(struct ll_schedule_domain *domain, else if (!dma_domain->channel_mask[i][core]) dma_multi_chan_domain_irq_unregister( dma_domain->arg[i][core]); - - platform_shared_commit(dmas[i].chan, - sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); - - goto out; + return 0; } - - platform_shared_commit(dmas[i].chan, sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); } -out: - platform_shared_commit(dmas, sizeof(*dmas) * dma_domain->num_dma); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); + /* task in running or unregistered at all, can't unregister it */ + return -EINVAL; } /** @@ -275,32 +273,60 @@ static void dma_multi_chan_domain_unregister(struct ll_schedule_domain *domain, * \return True is task should be executed, false otherwise. */ static bool dma_multi_chan_domain_is_pending(struct ll_schedule_domain *domain, - struct task *task) + struct task *task, struct comp_dev **comp) { struct dma_domain *dma_domain = ll_sch_domain_get_pdata(domain); struct pipeline_task *pipe_task = pipeline_task_get(task); struct dma *dmas = dma_domain->dma_array; + struct ll_task_pdata *pdata; uint32_t status; int i; int j; for (i = 0; i < dma_domain->num_dma; ++i) { + if (dmas[i].chan == NULL) + continue; for (j = 0; j < dmas[i].plat_data.channels; ++j) { - status = dma_interrupt(&dmas[i].chan[j], - DMA_IRQ_STATUS_GET); - if (!status) + if (!*comp) { + status = dma_interrupt_legacy(&dmas[i].chan[j], + DMA_IRQ_STATUS_GET); + if (!status) + continue; + + *comp = dma_domain->data[i][j].task->sched_comp; + } else if (!dma_domain->data[i][j].task || + dma_domain->data[i][j].task->sched_comp != *comp) { continue; + } /* not the same scheduling component */ if (dma_domain->data[i][j].task->sched_comp != pipe_task->sched_comp) continue; - /* it's too soon for this task */ - if (!pipe_task->registrable && - pipe_task->task.start > - platform_timer_get(timer_get())) - continue; + /* Schedule task based on the frequency they + * were configured with, not time (task.start) + * + * There are cases when a DMA transfer from a DAI + * is finished earlier than task.start and, + * without full_sync mode, this task will not + * be scheduled + */ + if (domain->full_sync) { + pdata = ll_sch_get_pdata(&pipe_task->task); + pdata->skip_cnt++; + if (pdata->skip_cnt == pdata->ratio) + pdata->skip_cnt = 0; + + if (pdata->skip_cnt != 0) + continue; + } else { + /* it's too soon for this task */ + if (!pipe_task->registrable && + pipe_task->task.start > + sof_cycle_get_64_atomic()) + continue; + } notifier_event(&dmas[i].chan[j], NOTIFIER_ID_DMA_IRQ, NOTIFIER_TARGET_CORE_LOCAL, @@ -309,22 +335,15 @@ static bool dma_multi_chan_domain_is_pending(struct ll_schedule_domain *domain, /* clear interrupt */ if (pipe_task->registrable) { - dma_interrupt(&dmas[i].chan[j], DMA_IRQ_CLEAR); + dma_interrupt_legacy(&dmas[i].chan[j], DMA_IRQ_CLEAR); interrupt_clear_mask(dma_domain->data[i][j].irq, BIT(j)); } - platform_shared_commit(dmas, sizeof(*dmas) * - dma_domain->num_dma); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); - return true; } } - platform_shared_commit(dmas, sizeof(*dmas) * dma_domain->num_dma); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); - return false; } @@ -346,14 +365,22 @@ struct ll_schedule_domain *dma_multi_chan_domain_init(struct dma *dma_array, int i; int j; - trace_ll("dma_multi_chan_domain_init(): num_dma %d, clk %d, " - "aggregated_irq %d", num_dma, clk, aggregated_irq); + tr_info(&ll_tr, "num_dma %d, clk %d, aggregated_irq %d", + num_dma, clk, aggregated_irq); domain = domain_init(SOF_SCHEDULE_LL_DMA, clk, true, &dma_multi_chan_domain_ops); + if (!domain) { + tr_err(&ll_tr, "domain init failed"); + return NULL; + } - dma_domain = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*dma_domain)); + dma_domain = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*dma_domain)); + if (!dma_domain) { + tr_err(&ll_tr, "allocation failed"); + rfree(domain); + return NULL; + } dma_domain->dma_array = dma_array; dma_domain->num_dma = num_dma; dma_domain->aggregated_irq = aggregated_irq; @@ -369,10 +396,6 @@ struct ll_schedule_domain *dma_multi_chan_domain_init(struct dma *dma_array, ll_sch_domain_set_pdata(domain, dma_domain); - platform_shared_commit(dma_array, sizeof(*dma_array) * num_dma); - platform_shared_commit(domain, sizeof(*domain)); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); - return domain; } diff --git a/src/schedule/dma_single_chan_domain.c b/src/schedule/dma_single_chan_domain.c index 9c717d5f06c0..d234c473586a 100644 --- a/src/schedule/dma_single_chan_domain.c +++ b/src/schedule/dma_single_chan_domain.c @@ -5,10 +5,10 @@ // Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> #include <sof/audio/component.h> -#include <sof/bit.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> +#include <rtos/bit.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> #include <sof/lib/cpu.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> @@ -17,15 +17,18 @@ #include <sof/schedule/ll_schedule.h> #include <sof/schedule/ll_schedule_domain.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> +#include <rtos/task.h> #include <ipc/topology.h> #include <errno.h> +#include <limits.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> #define DMA_DOMAIN_OWNER_INVALID 0xFFFFFFFF +LOG_MODULE_DECLARE(ll_schedule, CONFIG_SOF_LOG_LEVEL); + struct dma_domain_data { int irq; struct dma_chan_data *channel; @@ -40,7 +43,7 @@ struct dma_domain { bool channel_changed; /* true if we needed to re-register */ /* data per core */ - struct dma_domain_data data[PLATFORM_CORE_COUNT]; + struct dma_domain_data data[CONFIG_CORE_COUNT]; }; const struct ll_schedule_domain_ops dma_single_chan_domain_ops; @@ -87,13 +90,8 @@ static struct dma_chan_data *dma_chan_min_period(struct dma_domain *dma_domain) channel = &dmas[i].chan[j]; } - - platform_shared_commit(dmas[i].chan, sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); } - platform_shared_commit(dmas, sizeof(*dmas) * dma_domain->num_dma); - return channel; } @@ -103,7 +101,7 @@ static struct dma_chan_data *dma_chan_min_period(struct dma_domain *dma_domain) */ static void dma_domain_notify_change(struct dma_chan_data *channel) { - trace_ll("dma_domain_notify_change()"); + tr_info(&ll_tr, "entry"); notifier_event(channel, NOTIFIER_ID_DMA_DOMAIN_CHANGE, NOTIFIER_TARGET_CORE_ALL_MASK & ~BIT(cpu_get_id()), @@ -126,7 +124,7 @@ static int dma_single_chan_domain_irq_register(struct dma_chan_data *channel, int irq = dma_chan_irq(channel->dma, channel->index); int ret; - trace_ll("dma_single_chan_domain_irq_register()"); + tr_info(&ll_tr, "entry"); data->irq = interrupt_get_irq(irq, dma_irq_name(channel->dma)); if (data->irq < 0) { @@ -147,8 +145,6 @@ static int dma_single_chan_domain_irq_register(struct dma_chan_data *channel, data->arg = arg; out: - platform_shared_commit(channel, sizeof(*channel)); - return ret; } @@ -158,17 +154,16 @@ static int dma_single_chan_domain_irq_register(struct dma_chan_data *channel, */ static void dma_single_chan_domain_irq_unregister(struct dma_domain_data *data) { - trace_ll("dma_single_chan_domain_irq_unregister()"); + tr_info(&ll_tr, "entry"); interrupt_disable(data->irq, data->arg); - interrupt_unregister(data->irq, data->arg); } /** * \brief Registers task to DMA domain. + * * \param[in,out] domain Pointer to schedule domain. - * \param[in] period Period of the scheduled task. * \param[in,out] task Task to be registered. * \param[in,out] handler Pointer to DMA interrupt handler. * \param[in,out] arg Pointer to DMA interrupt handler's argument. @@ -181,7 +176,7 @@ static void dma_single_chan_domain_irq_unregister(struct dma_domain_data *data) * cores need to be notified. */ static int dma_single_chan_domain_register(struct ll_schedule_domain *domain, - uint64_t period, struct task *task, + struct task *task, void (*handler)(void *arg), void *arg) { @@ -193,7 +188,7 @@ static int dma_single_chan_domain_register(struct ll_schedule_domain *domain, bool register_needed = true; int ret = 0; - trace_ll("dma_single_chan_domain_register()"); + tr_info(&ll_tr, "entry"); /* check if task should be registered */ if (!pipe_task->registrable) @@ -211,13 +206,12 @@ static int dma_single_chan_domain_register(struct ll_schedule_domain *domain, if (data->channel->period == channel->period) goto out; - trace_ll("dma_single_chan_domain_register(): " - "lower period detected, registering again"); + tr_info(&ll_tr, "lower period detected, registering again"); /* unregister from current channel */ dma_single_chan_domain_irq_unregister(data); - dma_interrupt(data->channel, DMA_IRQ_MASK); - dma_interrupt(data->channel, DMA_IRQ_CLEAR); + dma_interrupt_legacy(data->channel, DMA_IRQ_MASK); + dma_interrupt_legacy(data->channel, DMA_IRQ_CLEAR); dma_domain->channel_changed = true; @@ -225,8 +219,14 @@ static int dma_single_chan_domain_register(struct ll_schedule_domain *domain, register_needed = false; } - trace_ll("dma_single_chan_domain_register(): " - "registering on channel with period %u", channel->period); + if (channel->period <= UINT_MAX) + tr_info(&ll_tr, + "registering on channel with period %u", + (unsigned int)channel->period); + else + tr_info(&ll_tr, + "registering on channel with period > %u", + UINT_MAX); /* register for interrupt */ ret = dma_single_chan_domain_irq_register(channel, data, handler, arg); @@ -234,7 +234,7 @@ static int dma_single_chan_domain_register(struct ll_schedule_domain *domain, goto out; /* enable channel interrupt */ - dma_interrupt(data->channel, DMA_IRQ_UNMASK); + dma_interrupt_legacy(data->channel, DMA_IRQ_UNMASK); /* unmask if we are the owner */ if (dma_domain->owner == core) @@ -247,13 +247,11 @@ static int dma_single_chan_domain_register(struct ll_schedule_domain *domain, /* register for source change notifications */ if (register_needed) notifier_register(domain, NULL, NOTIFIER_ID_DMA_DOMAIN_CHANGE, - dma_domain_changed); + dma_domain_changed, 0); dma_domain->owner = channel->core; out: - platform_shared_commit(dma_domain, sizeof(*dma_domain)); - return ret; } @@ -285,21 +283,13 @@ static bool dma_chan_is_any_running(struct dma *dmas, uint32_t num) continue; if (dmas[i].chan[j].status == COMP_STATE_ACTIVE) { - platform_shared_commit(dmas[i].chan, - sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); ret = true; goto out; } } - - platform_shared_commit(dmas[i].chan, sizeof(*dmas[i].chan) * - dmas[i].plat_data.channels); } out: - platform_shared_commit(dmas, sizeof(*dmas) * num); - return ret; } @@ -317,46 +307,49 @@ static void dma_domain_unregister_owner(struct ll_schedule_domain *domain, struct dma_domain *dma_domain = ll_sch_domain_get_pdata(domain); struct dma *dmas = dma_domain->dma_array; struct dma_chan_data *channel; - int core = cpu_get_id(); - trace_ll("dma_domain_unregister_owner()"); + tr_info(&ll_tr, "entry"); /* transfers still scheduled on this channel */ if (data->channel->status == COMP_STATE_ACTIVE) return; + channel = dma_chan_min_period(dma_domain); + if (channel && dma_chan_is_any_running(dmas, dma_domain->num_dma)) { + /* another channel is running */ + tr_info(&ll_tr, "domain in use, change owner"); + + /* change owner */ + dma_domain->owner = channel->core; + + /* notify scheduling channel change */ + dma_domain_notify_change(channel); + + data->channel = channel; + dma_domain->channel_changed = true; + + return; + } + + /* no other channel is running */ dma_single_chan_domain_irq_unregister(data); - dma_interrupt(data->channel, DMA_IRQ_MASK); - dma_interrupt(data->channel, DMA_IRQ_CLEAR); + dma_interrupt_legacy(data->channel, DMA_IRQ_MASK); + dma_interrupt_legacy(data->channel, DMA_IRQ_CLEAR); data->channel = NULL; - channel = dma_chan_min_period(dma_domain); - if (!channel) { - dma_domain->owner = DMA_DOMAIN_OWNER_INVALID; - notifier_unregister(domain, NULL, - NOTIFIER_ID_DMA_DOMAIN_CHANGE); + if (channel) { + /* change owner */ + dma_domain->owner = channel->core; + + /* notify scheduling channel change */ + dma_domain_notify_change(channel); return; } - /* change owner */ - dma_domain->owner = channel->core; + dma_domain->owner = DMA_DOMAIN_OWNER_INVALID; - /* notify scheduling channel change */ - dma_domain_notify_change(channel); - - /* check if there is another channel running */ - if (dma_chan_is_any_running(dmas, dma_domain->num_dma)) { - trace_ll("dma_domain_unregister_owner(): " - "some channel is still running, registering again"); - - /* register again and enable */ - dma_single_chan_domain_irq_register(channel, data, - data->handler, data->arg); - dma_interrupt(data->channel, DMA_IRQ_CLEAR); - dma_single_chan_domain_enable(domain, core); - dma_domain->channel_changed = true; - } + notifier_unregister(domain, NULL, NOTIFIER_ID_DMA_DOMAIN_CHANGE); } /** @@ -364,10 +357,11 @@ static void dma_domain_unregister_owner(struct ll_schedule_domain *domain, * \param[in,out] domain Pointer to schedule domain. * \param[in,out] task Task to be unregistered from the domain. * \param[in] num_tasks Number of currently scheduled tasks. + * \return Error code. */ -static void dma_single_chan_domain_unregister(struct ll_schedule_domain *domain, - struct task *task, - uint32_t num_tasks) +static int dma_single_chan_domain_unregister(struct ll_schedule_domain *domain, + struct task *task, + uint32_t num_tasks) { struct dma_domain *dma_domain = ll_sch_domain_get_pdata(domain); struct pipeline_task *pipe_task = pipeline_task_get(task); @@ -375,25 +369,25 @@ static void dma_single_chan_domain_unregister(struct ll_schedule_domain *domain, int core = cpu_get_id(); struct dma_domain_data *data = &dma_domain->data[core]; - trace_ll("dma_single_chan_domain_unregister()"); + tr_info(&ll_tr, "entry"); /* check if task should be unregistered */ - if (!pipe_task->registrable) - goto out; + if (!task || !pipe_task->registrable) + return 0; /* channel not registered */ if (!data->channel) - goto out; + return -EINVAL; /* unregister domain owner */ if (dma_domain->owner == core) { dma_domain_unregister_owner(domain, data); - goto out; + return 0; } /* some channel still running, so return */ if (dma_chan_is_any_running(dmas, dma_domain->num_dma)) - goto out; + return -EBUSY; /* no more transfers scheduled on this core */ dma_single_chan_domain_irq_unregister(data); @@ -401,8 +395,7 @@ static void dma_single_chan_domain_unregister(struct ll_schedule_domain *domain, notifier_unregister(domain, NULL, NOTIFIER_ID_DMA_DOMAIN_CHANGE); -out: - platform_shared_commit(dma_domain, sizeof(*dma_domain)); + return 0; } /** @@ -418,14 +411,10 @@ static void dma_single_chan_domain_enable(struct ll_schedule_domain *domain, /* channel not registered */ if (!data->channel) - goto out; - - dma_interrupt(data->channel, DMA_IRQ_UNMASK); + return; + dma_interrupt_legacy(data->channel, DMA_IRQ_UNMASK); interrupt_unmask(data->irq, core); - -out: - platform_shared_commit(dma_domain, sizeof(*dma_domain)); } /** @@ -441,16 +430,13 @@ static void dma_single_chan_domain_disable(struct ll_schedule_domain *domain, /* channel not registered */ if (!data->channel) - goto out; + return; interrupt_mask(data->irq, core); - -out: - platform_shared_commit(dma_domain, sizeof(*dma_domain)); } /** - * \brief Calculates domain's last tick. + * \brief Calculates domain's next tick. * \param[in,out] domain Pointer to schedule domain. * \param[in] start Offset of last calculated tick. */ @@ -463,21 +449,19 @@ static void dma_single_chan_domain_set(struct ll_schedule_domain *domain, /* channel not registered */ if (!data->channel) - goto out; + return; if (dma_domain->channel_changed) { - domain->last_tick = platform_timer_get(timer_get()); + domain->next_tick = sof_cycle_get_64_atomic(); dma_domain->channel_changed = false; } else { ticks = domain->ticks_per_ms * data->channel->period / 1000 + start; - domain->last_tick = domain->last_tick ? ticks : start; + domain->next_tick = domain->next_tick != UINT64_MAX ? + ticks : start; } - -out: - platform_shared_commit(dma_domain, sizeof(*dma_domain)); } /** @@ -491,12 +475,9 @@ static void dma_single_chan_domain_clear(struct ll_schedule_domain *domain) /* channel not registered */ if (!data->channel) - goto out; - - dma_interrupt(data->channel, DMA_IRQ_CLEAR); + return; -out: - platform_shared_commit(dma_domain, sizeof(*dma_domain)); + dma_interrupt_legacy(data->channel, DMA_IRQ_CLEAR); } /** @@ -506,9 +487,9 @@ static void dma_single_chan_domain_clear(struct ll_schedule_domain *domain) * \return True is task should be executed, false otherwise. */ static bool dma_single_chan_domain_is_pending(struct ll_schedule_domain *domain, - struct task *task) + struct task *task, struct comp_dev **comp) { - return task->start <= platform_timer_get(timer_get()); + return task->start <= sof_cycle_get_64_atomic(); } /** @@ -524,27 +505,23 @@ static void dma_domain_changed(void *arg, enum notify_id type, void *data) int core = cpu_get_id(); struct dma_domain_data *domain_data = &dma_domain->data[core]; - trace_ll("dma_domain_changed()"); + tr_info(&ll_tr, "entry"); /* unregister from current DMA channel */ dma_single_chan_domain_irq_unregister(domain_data); if (domain_data->channel->core == core) { - dma_interrupt(domain_data->channel, DMA_IRQ_MASK); - dma_interrupt(domain_data->channel, DMA_IRQ_CLEAR); + dma_interrupt_legacy(domain_data->channel, DMA_IRQ_MASK); + dma_interrupt_legacy(domain_data->channel, DMA_IRQ_CLEAR); } /* register to the new DMA channel */ if (dma_single_chan_domain_irq_register(data, domain_data, domain_data->handler, domain_data->arg) < 0) - goto out; + return; dma_single_chan_domain_enable(domain, core); - -out: - platform_shared_commit(domain, sizeof(*domain)); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); } /** @@ -561,23 +538,28 @@ struct ll_schedule_domain *dma_single_chan_domain_init(struct dma *dma_array, struct ll_schedule_domain *domain; struct dma_domain *dma_domain; - trace_ll("dma_single_chan_domain_init(): num_dma %d, clk %d", num_dma, - clk); + tr_info(&ll_tr, "num_dma %d, clk %d", + num_dma, clk); domain = domain_init(SOF_SCHEDULE_LL_DMA, clk, false, &dma_single_chan_domain_ops); + if (!domain) { + tr_err(&ll_tr, "domain init failed"); + return NULL; + } - dma_domain = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*dma_domain)); + dma_domain = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*dma_domain)); + if (!dma_domain) { + tr_err(&ll_tr, "allocation failed"); + rfree(domain); + return NULL; + } dma_domain->dma_array = dma_array; dma_domain->num_dma = num_dma; dma_domain->owner = DMA_DOMAIN_OWNER_INVALID; ll_sch_domain_set_pdata(domain, dma_domain); - platform_shared_commit(domain, sizeof(*domain)); - platform_shared_commit(dma_domain, sizeof(*dma_domain)); - return domain; } diff --git a/src/schedule/edf_schedule.c b/src/schedule/edf_schedule.c deleted file mode 100644 index 15b6896214b0..000000000000 --- a/src/schedule/edf_schedule.c +++ /dev/null @@ -1,314 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2017 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -struct edf_schedule_data { - struct list_item list; /* list of tasks in priority queue */ - uint32_t clock; - int irq; -}; - -const struct scheduler_ops schedule_edf_ops; - -static void schedule_edf_task_complete(void *data, struct task *task); -static void schedule_edf_task_running(void *data, struct task *task); -static void schedule_edf(void *data); - -static void schedule_edf_task_run(struct task *task, void *data) -{ - while (1) { - /* execute task run function and remove task from the list - * only if completed - */ - if (task_run(task) == SOF_TASK_STATE_COMPLETED) - schedule_edf_task_complete(data, task); - - /* find new task for execution */ - schedule_edf(data); - } -} - -static void edf_scheduler_run(void *data) -{ - struct edf_schedule_data *edf_sch = data; - uint64_t deadline_next = SOF_TASK_DEADLINE_IDLE; - struct task *task_next = NULL; - struct list_item *tlist; - struct task *task; - uint64_t deadline; - uint32_t flags; - - tracev_edf_sch("edf_scheduler_run()"); - - irq_local_disable(flags); - - /* find next task to run */ - list_for_item(tlist, &edf_sch->list) { - task = container_of(tlist, struct task, list); - - if (task->state != SOF_TASK_STATE_QUEUED && - task->state != SOF_TASK_STATE_RUNNING) - continue; - - deadline = task_get_deadline(task); - - if (deadline == SOF_TASK_DEADLINE_NOW) { - /* task needs to be scheduled ASAP */ - task_next = task; - break; - } - - /* get earliest deadline */ - if (deadline <= deadline_next) { - deadline_next = deadline; - task_next = task; - } - } - - irq_local_enable(flags); - - /* having next task is mandatory */ - assert(task_next); - - schedule_edf_task_running(data, task_next); -} - -static void schedule_edf_task(void *data, struct task *task, uint64_t start, - uint64_t period) -{ - struct edf_schedule_data *edf_sch = data; - uint64_t ticks_per_ms; - uint64_t current; - uint32_t flags; - - irq_local_disable(flags); - - /* not enough MCPS to complete */ - if (task->state == SOF_TASK_STATE_QUEUED || - task->state == SOF_TASK_STATE_RUNNING) { - trace_edf_sch_error - ("schedule_edf_task(), task already queued or running %d", - task->state); - irq_local_enable(flags); - return; - } - - /* get current time */ - current = platform_timer_get(timer_get()); - - ticks_per_ms = clock_ms_to_ticks(edf_sch->clock, 1); - - /* calculate start time */ - task->start = start ? task->start + ticks_per_ms * start / 1000 : - current; - - /* add task to the list */ - list_item_append(&task->list, &edf_sch->list); - - task->state = SOF_TASK_STATE_QUEUED; - - irq_local_enable(flags); - - schedule_edf(data); -} - -int schedule_task_init_edf(struct task *task, uint32_t uid, - const struct task_ops *ops, - void *data, uint16_t core, uint32_t flags) -{ - struct edf_task_pdata *edf_pdata = NULL; - int ret = 0; - - ret = schedule_task_init(task, uid, SOF_SCHEDULE_EDF, 0, ops->run, data, - core, flags); - if (ret < 0) - return ret; - - if (edf_sch_get_pdata(task)) - return -EEXIST; - - edf_pdata = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*edf_pdata)); - if (!edf_pdata) { - trace_edf_sch_error("schedule_task_init_edf() error: alloc " - "failed"); - return -ENOMEM; - } - - edf_sch_set_pdata(task, edf_pdata); - - task->ops.complete = ops->complete; - task->ops.get_deadline = ops->get_deadline; - - if (task_context_alloc(&edf_pdata->ctx) < 0) - goto error; - if (task_context_init(edf_pdata->ctx, &schedule_edf_task_run, - task, scheduler_get_data(SOF_SCHEDULE_EDF), - task->core, NULL, 0) < 0) - goto error; - - /* flush for slave core */ - if (cpu_is_slave(task->core)) - dcache_writeback_invalidate_region(edf_pdata, - sizeof(*edf_pdata)); - return 0; - -error: - trace_edf_sch_error("schedule_task_init_edf() error: init " - "context failed"); - if (edf_pdata->ctx) - task_context_free(edf_pdata->ctx); - rfree(edf_pdata); - edf_sch_set_pdata(task, NULL); - return -EINVAL; -} - -static void schedule_edf_task_running(void *data, struct task *task) -{ - struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task); - uint32_t flags; - - tracev_edf_sch("schedule_edf_task_running()"); - - irq_local_disable(flags); - - task_context_set(edf_pdata->ctx); - task->state = SOF_TASK_STATE_RUNNING; - - irq_local_enable(flags); -} - -static void schedule_edf_task_complete(void *data, struct task *task) -{ - uint32_t flags; - - tracev_edf_sch("schedule_edf_task_complete()"); - - irq_local_disable(flags); - - task_complete(task); - - task->state = SOF_TASK_STATE_COMPLETED; - list_item_del(&task->list); - - irq_local_enable(flags); -} - -static void schedule_edf_task_cancel(void *data, struct task *task) -{ - uint32_t flags; - - tracev_edf_sch("schedule_edf_task_cancel()"); - - irq_local_disable(flags); - - /* cancel and delete only if queued */ - if (task->state == SOF_TASK_STATE_QUEUED) { - task->state = SOF_TASK_STATE_CANCEL; - list_item_del(&task->list); - } - - irq_local_enable(flags); -} - -static void schedule_edf_task_free(void *data, struct task *task) -{ - struct edf_task_pdata *edf_pdata = edf_sch_get_pdata(task); - uint32_t flags; - - irq_local_disable(flags); - - task->state = SOF_TASK_STATE_FREE; - - task_context_free(edf_pdata->ctx); - edf_pdata->ctx = NULL; - rfree(edf_pdata); - edf_sch_set_pdata(task, NULL); - - irq_local_enable(flags); -} - -int scheduler_init_edf(void) -{ - struct edf_schedule_data *edf_sch; - - trace_edf_sch("edf_scheduler_init()"); - - edf_sch = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(*edf_sch)); - list_init(&edf_sch->list); - edf_sch->clock = PLATFORM_DEFAULT_CLOCK; - - scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, edf_sch); - - /* initialize main task context before enabling interrupt */ - task_main_init(); - - /* configure EDF scheduler interrupt */ - edf_sch->irq = interrupt_get_irq(PLATFORM_SCHEDULE_IRQ, - PLATFORM_SCHEDULE_IRQ_NAME); - if (edf_sch->irq < 0) - return edf_sch->irq; - - interrupt_register(edf_sch->irq, edf_scheduler_run, edf_sch); - interrupt_enable(edf_sch->irq, edf_sch); - - return 0; -} - -static void scheduler_free_edf(void *data) -{ - struct edf_schedule_data *edf_sch = data; - uint32_t flags; - - irq_local_disable(flags); - - /* disable and unregister EDF scheduler interrupt */ - interrupt_disable(edf_sch->irq, edf_sch); - interrupt_unregister(edf_sch->irq, edf_sch); - - /* free main task context */ - task_main_free(); - - list_item_del(&edf_sch->list); - - irq_local_enable(flags); -} - -static void schedule_edf(void *data) -{ - struct edf_schedule_data *edf_sch = data; - - interrupt_set(edf_sch->irq); -} - -const struct scheduler_ops schedule_edf_ops = { - .schedule_task = schedule_edf_task, - .schedule_task_running = schedule_edf_task_running, - .schedule_task_complete = schedule_edf_task_complete, - .reschedule_task = NULL, - .schedule_task_cancel = schedule_edf_task_cancel, - .schedule_task_free = schedule_edf_task_free, - .scheduler_free = scheduler_free_edf, - .scheduler_run = schedule_edf -}; diff --git a/src/schedule/ll_schedule.c b/src/schedule/ll_schedule.c deleted file mode 100644 index b6857c8a626d..000000000000 --- a/src/schedule/ll_schedule.c +++ /dev/null @@ -1,523 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/atomic.h> -#include <sof/common.h> -#include <sof/drivers/interrupt.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/clk.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/notifier.h> -#include <sof/lib/perf_cnt.h> -#include <sof/list.h> -#include <sof/platform.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/ll_schedule_domain.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/spinlock.h> -#include <ipc/topology.h> -#include <config.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* one instance of data allocated per core */ -struct ll_schedule_data { - struct list_item tasks; /* list of ll tasks */ - atomic_t num_tasks; /* number of ll tasks */ -#if CONFIG_PERFORMANCE_COUNTERS - struct perf_cnt_data pcd; -#endif - struct ll_schedule_domain *domain; /* scheduling domain */ -}; - -const struct scheduler_ops schedule_ll_ops; - -static bool schedule_ll_is_pending(struct ll_schedule_data *sch) -{ - struct list_item *tlist; - struct task *task; - uint32_t pending_count = 0; - - /* mark each valid task as pending */ - list_for_item(tlist, &sch->tasks) { - task = container_of(tlist, struct task, list); - - if (domain_is_pending(sch->domain, task)) { - task->state = SOF_TASK_STATE_PENDING; - pending_count++; - } - } - - return pending_count > 0; -} - -static void schedule_ll_task_update_start(struct ll_schedule_data *sch, - struct task *task, uint64_t last_tick) -{ - struct ll_task_pdata *pdata = ll_sch_get_pdata(task); - uint64_t next; - - next = sch->domain->ticks_per_ms * pdata->period / 1000; - - if (sch->domain->synchronous) - task->start += next; - else - task->start = next + last_tick; -} - -static void schedule_ll_tasks_execute(struct ll_schedule_data *sch, - uint64_t last_tick) -{ - struct list_item *wlist; - struct list_item *tlist; - struct task *task; - int cpu = cpu_get_id(); - - /* check each task in the list for pending */ - list_for_item_safe(wlist, tlist, &sch->tasks) { - task = container_of(wlist, struct task, list); - - /* run task if its pending and remove from the list */ - if (task->state != SOF_TASK_STATE_PENDING) - continue; - - task->state = task_run(task); - - /* do we need to reschedule this task */ - if (task->state == SOF_TASK_STATE_COMPLETED) { - list_item_del(&task->list); - atomic_sub(&sch->domain->total_num_tasks, 1); - - /* don't enable irq, if no more tasks to do */ - if (!atomic_sub(&sch->num_tasks, 1)) - sch->domain->registered[cpu] = false; - trace_ll("task complete %p %s", (uintptr_t)task, - task->uid); - trace_ll("num_tasks %d total_num_tasks %d", - atomic_read(&sch->num_tasks), - atomic_read(&sch->domain->total_num_tasks)); - } else { - /* update task's start time */ - schedule_ll_task_update_start(sch, task, last_tick); - } - } - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); -} - -static void schedule_ll_clients_enable(struct ll_schedule_data *sch) -{ - int i; - - for (i = 0; i < PLATFORM_CORE_COUNT; i++) { - if (sch->domain->registered[i]) { - atomic_add(&sch->domain->num_clients, 1); - domain_enable(sch->domain, i); - } - } -} - -static void schedule_ll_clients_reschedule(struct ll_schedule_data *sch) -{ - /* rearm only if there is work to do */ - if (atomic_read(&sch->domain->total_num_tasks)) { - domain_set(sch->domain, sch->domain->last_tick); - schedule_ll_clients_enable(sch); - } - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); -} - -static void schedule_ll_tasks_run(void *data) -{ - struct ll_schedule_data *sch = data; - uint32_t num_clients; - uint64_t last_tick; - uint32_t flags; - - domain_disable(sch->domain, cpu_get_id()); - - irq_local_disable(flags); - - spin_lock(&sch->domain->lock); - - last_tick = sch->domain->last_tick; - - /* clear domain only if all clients are done */ - /* TODO: no need for atomic operations, - * already protected by spin_lock - */ - num_clients = atomic_sub(&sch->domain->num_clients, 1); - if (!num_clients) - domain_clear(sch->domain); - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - - spin_unlock(&sch->domain->lock); - - perf_cnt_init(&sch->pcd); - - /* run tasks if there are any pending */ - if (schedule_ll_is_pending(sch)) - schedule_ll_tasks_execute(sch, last_tick); - - perf_cnt_stamp(TRACE_CLASS_SCHEDULE_LL, &sch->pcd, true); - - spin_lock(&sch->domain->lock); - - /* reschedule only if all clients are done */ - if (!num_clients) - schedule_ll_clients_reschedule(sch); - - spin_unlock(&sch->domain->lock); - - irq_local_enable(flags); -} - -static int schedule_ll_domain_set(struct ll_schedule_data *sch, - struct task *task, uint64_t period) -{ - int core = cpu_get_id(); - int ret; - - ret = domain_register(sch->domain, period, task, &schedule_ll_tasks_run, - sch); - if (ret < 0) { - trace_ll_error("schedule_ll_domain_set error: cannot register domain %d", - ret); - return ret; - } - - spin_lock(&sch->domain->lock); - - if (atomic_add(&sch->num_tasks, 1) == 1) - sch->domain->registered[core] = true; - - if (atomic_add(&sch->domain->total_num_tasks, 1) == 1) { - domain_set(sch->domain, platform_timer_get(timer_get())); - atomic_add(&sch->domain->num_clients, 1); - domain_enable(sch->domain, core); - } - - trace_ll("num_tasks %d total_num_tasks %d", - atomic_read(&sch->num_tasks), - atomic_read(&sch->domain->total_num_tasks)); - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - - spin_unlock(&sch->domain->lock); - - return 0; -} - -static void schedule_ll_domain_clear(struct ll_schedule_data *sch, - struct task *task) -{ - spin_lock(&sch->domain->lock); - - if (!atomic_sub(&sch->domain->total_num_tasks, 1)) { - domain_clear(sch->domain); - sch->domain->last_tick = 0; - } - - if (!atomic_sub(&sch->num_tasks, 1)) { - sch->domain->registered[cpu_get_id()] = false; - - /* reschedule if we are the last client */ - if (atomic_read(&sch->domain->num_clients) && - !atomic_sub(&sch->domain->num_clients, 1)) { - domain_clear(sch->domain); - schedule_ll_clients_reschedule(sch); - } - } - - trace_ll("num_tasks %d total_num_tasks %d", - atomic_read(&sch->num_tasks), - atomic_read(&sch->domain->total_num_tasks)); - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - - spin_unlock(&sch->domain->lock); - - domain_unregister(sch->domain, task, atomic_read(&sch->num_tasks)); -} - -static void schedule_ll_task_insert(struct task *task, struct list_item *tasks) -{ - struct list_item *tlist; - struct task *curr_task; - - /* tasks are added into the list from highest to lowest priority - * and tasks with the same priority should be served on - * a first-come-first-serve basis - */ - list_for_item(tlist, tasks) { - curr_task = container_of(tlist, struct task, list); - if (task->priority < curr_task->priority) { - list_item_append(&task->list, &curr_task->list); - return; - } - } - - /* if task has not been added, means that it has the lowest - * priority and should be added at the end of the list - */ - list_item_append(&task->list, tasks); -} - -static void schedule_ll_task(void *data, struct task *task, uint64_t start, - uint64_t period) -{ - struct ll_schedule_data *sch = data; - struct ll_task_pdata *pdata; - struct list_item *tlist; - struct task *curr_task; - uint32_t flags; - - irq_local_disable(flags); - - /* check if task is already scheduled */ - list_for_item(tlist, &sch->tasks) { - curr_task = container_of(tlist, struct task, list); - - /* keep original start */ - if (curr_task == task) - goto out; - } - - pdata = ll_sch_get_pdata(task); - - trace_ll("task add %p %s", (uintptr_t)task, task->uid); - trace_ll("task params pri %d flags %d start %u period %u", - task->priority, task->flags, start, period); - - pdata->period = period; - - /* insert task into the list */ - schedule_ll_task_insert(task, &sch->tasks); - - /* set schedule domain */ - if (schedule_ll_domain_set(sch, task, period) < 0) { - list_item_del(&task->list); - goto out; - } - - task->start = sch->domain->ticks_per_ms * start / 1000; - - if (sch->domain->synchronous) - task->start += platform_timer_get(timer_get()); - else - task->start += sch->domain->last_tick; - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - -out: - irq_local_enable(flags); -} - -int schedule_task_init_ll(struct task *task, - uint32_t uid, uint16_t type, uint16_t priority, - enum task_state (*run)(void *data), void *data, - uint16_t core, uint32_t flags) -{ - struct ll_task_pdata *ll_pdata; - int ret = 0; - - ret = schedule_task_init(task, uid, type, priority, run, data, core, - flags); - if (ret < 0) - return ret; - - if (ll_sch_get_pdata(task)) - return -EEXIST; - - ll_pdata = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, - sizeof(*ll_pdata)); - - if (!ll_pdata) { - trace_ll_error("schedule_task_init_ll() error: alloc failed"); - return -ENOMEM; - } - - ll_sch_set_pdata(task, ll_pdata); - - return 0; -} - -static void schedule_ll_task_free(void *data, struct task *task) -{ - struct ll_task_pdata *ll_pdata; - uint32_t flags; - - irq_local_disable(flags); - - /* release the resources */ - task->state = SOF_TASK_STATE_FREE; - ll_pdata = ll_sch_get_pdata(task); - rfree(ll_pdata); - ll_sch_set_pdata(task, NULL); - - irq_local_enable(flags); -} - -static void schedule_ll_task_cancel(void *data, struct task *task) -{ - struct ll_schedule_data *sch = data; - struct list_item *tlist; - struct task *curr_task; - uint32_t flags; - - irq_local_disable(flags); - - trace_ll("task cancel %p %s", (uintptr_t)task, task->uid); - - /* check to see if we are scheduled */ - list_for_item(tlist, &sch->tasks) { - curr_task = container_of(tlist, struct task, list); - - /* found it */ - if (curr_task == task) { - schedule_ll_domain_clear(sch, task); - break; - } - } - - /* remove work from list */ - task->state = SOF_TASK_STATE_CANCEL; - list_item_del(&task->list); - - irq_local_enable(flags); -} - -static void reschedule_ll_task(void *data, struct task *task, uint64_t start) -{ - struct ll_schedule_data *sch = data; - struct list_item *tlist; - struct task *curr_task; - uint32_t flags; - uint64_t time; - - time = sch->domain->ticks_per_ms * start / 1000; - - if (sch->domain->synchronous) - time += platform_timer_get(timer_get()); - else - time += sch->domain->last_tick; - - irq_local_disable(flags); - - /* check to see if we are already scheduled */ - list_for_item(tlist, &sch->tasks) { - curr_task = container_of(tlist, struct task, list); - /* found it */ - if (curr_task == task) { - /* set start time */ - task->start = time; - goto out; - } - } - - trace_ll_error("reschedule_ll_task() error: task not found"); - -out: - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - - irq_local_enable(flags); -} - -static void scheduler_free_ll(void *data) -{ - struct ll_schedule_data *sch = data; - uint32_t flags; - - irq_local_disable(flags); - - notifier_unregister(sch, NULL, - NOTIFIER_CLK_CHANGE_ID(sch->domain->clk)); - - list_item_del(&sch->tasks); - - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - - irq_local_enable(flags); -} - -static void ll_scheduler_recalculate_tasks(struct ll_schedule_data *sch, - struct clock_notify_data *clk_data) -{ - uint64_t current = platform_timer_get(timer_get()); - struct list_item *tlist; - struct task *task; - uint64_t delta_ms; - - list_for_item(tlist, &sch->tasks) { - task = container_of(tlist, struct task, list); - delta_ms = (task->start - current) / - clk_data->old_ticks_per_msec; - - task->start = delta_ms ? - current + sch->domain->ticks_per_ms * delta_ms : - current + (sch->domain->ticks_per_ms >> 3); - } -} - -static void ll_scheduler_notify(void *arg, enum notify_id type, void *data) -{ - struct ll_schedule_data *sch = arg; - struct clock_notify_data *clk_data = data; - uint32_t flags; - - irq_local_disable(flags); - - /* we need to recalculate tasks when clock frequency changes */ - if (clk_data->message == CLOCK_NOTIFY_POST) { - sch->domain->ticks_per_ms = clock_ms_to_ticks(sch->domain->clk, - 1); - ll_scheduler_recalculate_tasks(sch, clk_data); - platform_shared_commit(sch->domain, sizeof(*sch->domain)); - } - - irq_local_enable(flags); -} - -int scheduler_init_ll(struct ll_schedule_domain *domain) -{ - struct ll_schedule_data *sch; - - /* initialize scheduler private data */ - sch = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(*sch)); - list_init(&sch->tasks); - atomic_init(&sch->num_tasks, 0); - sch->domain = domain; - - /* notification of clock changes */ - notifier_register(sch, NULL, NOTIFIER_CLK_CHANGE_ID(domain->clk), - ll_scheduler_notify); - - scheduler_init(domain->type, &schedule_ll_ops, sch); - - platform_shared_commit(domain, sizeof(*domain)); - - return 0; -} - -const struct scheduler_ops schedule_ll_ops = { - .schedule_task = schedule_ll_task, - .schedule_task_free = schedule_ll_task_free, - .schedule_task_cancel = schedule_ll_task_cancel, - .reschedule_task = reschedule_ll_task, - .scheduler_free = scheduler_free_ll, - .schedule_task_running = NULL, - .schedule_task_complete = NULL, - .scheduler_run = NULL -}; diff --git a/src/schedule/ll_schedule_xtos.c b/src/schedule/ll_schedule_xtos.c new file mode 100644 index 000000000000..10615045d4d2 --- /dev/null +++ b/src/schedule/ll_schedule_xtos.c @@ -0,0 +1,813 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2016 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Tomasz Lauda <tomasz.lauda@linux.intel.com> + +#include <rtos/atomic.h> +#include <sof/audio/pipeline.h> +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/clk.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/perf_cnt.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/platform.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <rtos/spinlock.h> +#include <ipc/topology.h> + +#include <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_REGISTER(ll_schedule, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(ll_sched); + +DECLARE_TR_CTX(ll_tr, SOF_UUID(ll_sched_uuid), LOG_LEVEL_INFO); + +/* + * LL Scheduler Task State Transition Diagram + * + * schedule_task() +---------+ + * +------------------| INIT | + * | +---------+ + * | + * v + * +--------+ is_pending() +---------+ is_pending() +----------+ + * | QUEUED |------------->| PENDING |<-------------|RESCHEDULE| + * +--------+ +---------+ +----------+ + * | ^ + * execute()| | + * v | + * +---------+ task_run() | + * | RUNNING |--------------------+ + * +---------+ reschedule + * | + * task_run()| + * completed v + * +---------+ + * |COMPLETED| + * +---------+ + */ + +/* one instance of data allocated per core */ +struct ll_schedule_data { + struct list_item tasks; /* list of ll tasks */ + atomic_t num_tasks; /* number of ll tasks */ +#if CONFIG_PERFORMANCE_COUNTERS__LL_TASKS + struct perf_cnt_data pcd; +#endif + struct ll_schedule_domain *domain; /* scheduling domain */ +}; + +static const struct scheduler_ops schedule_ll_ops; + +#if CONFIG_PERFORMANCE_COUNTERS__LL_TASKS +static void perf_ll_sched_trace(struct perf_cnt_data *pcd, int ignored) +{ + tr_info(&ll_tr, "perf ll_work peak plat %u cpu %u", + (uint32_t)((pcd)->plat_delta_peak), + (uint32_t)((pcd)->cpu_delta_peak)); +} + +static void perf_avg_ll_sched_trace(struct perf_cnt_data *pcd, int ignored) +{ + tr_info(&ll_tr, "perf ll_work cpu avg %u (current peak %u)", + (uint32_t)((pcd)->cpu_delta_sum), + (uint32_t)((pcd)->cpu_delta_peak)); +} + +#endif + +static bool schedule_ll_is_pending(struct ll_schedule_data *sch) +{ + struct ll_schedule_domain *domain = sch->domain; + struct list_item *tlist; + struct task *task; + uint32_t pending_count = 0; + struct comp_dev *sched_comp; + k_spinlock_key_t key; + + key = k_spin_lock(&domain->lock); + + do { + sched_comp = NULL; + + /* mark each valid task as pending */ + list_for_item(tlist, &sch->tasks) { + task = container_of(tlist, struct task, list); + + /* + * only tasks queued or waiting for reschedule are + * pending for scheduling + */ + if (task->state != SOF_TASK_STATE_QUEUED && + task->state != SOF_TASK_STATE_RESCHEDULE) + continue; + + if (domain_is_pending(domain, task, &sched_comp)) { + task->state = SOF_TASK_STATE_PENDING; + pending_count++; + } + } + } while (sched_comp); + + k_spin_unlock(&domain->lock, key); + + return pending_count > 0; +} + +static void schedule_ll_task_update_start(struct ll_schedule_data *sch, + struct task *task) +{ + struct ll_task_pdata *pdata = ll_sch_get_pdata(task); + uint64_t next; + + next = sch->domain->ticks_per_ms * pdata->period / 1000; + + task->start += next; +} + +/* caller should hold the domain lock */ +static void schedule_ll_task_done(struct ll_schedule_data *sch, + struct task *task) +{ + /* Remove from the task list, schedule_task_cancel() won't handle it again */ + list_item_del(&task->list); + + /* unregister the task */ + domain_unregister(sch->domain, task, atomic_sub(&sch->num_tasks, 1) - 1); + + tr_info(&ll_tr, "task complete %p %pU", task, task->uid); + tr_info(&ll_tr, "num_tasks %ld total_num_tasks %ld", + atomic_read(&sch->num_tasks), + atomic_read(&sch->domain->total_num_tasks)); +} + +/* perf measurement windows size 2^x */ +#define CHECKS_WINDOW_SIZE 10 + +#ifdef CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS +static inline void dsp_load_check(struct task *task, uint32_t cycles0, uint32_t cycles1) +{ + uint32_t diff; + + if (cycles1 > cycles0) + diff = cycles1 - cycles0; + else + diff = UINT32_MAX - cycles0 + cycles1; + + task->cycles_sum += diff; + + if (task->cycles_max < diff) + task->cycles_max = diff; + + if (++task->cycles_cnt == 1 << CHECKS_WINDOW_SIZE) { + task->cycles_sum >>= CHECKS_WINDOW_SIZE; + tr_info(&ll_tr, "task %p %pU avg %u, max %u", task, task->uid, + task->cycles_sum, task->cycles_max); + task->cycles_sum = 0; + task->cycles_max = 0; + task->cycles_cnt = 0; + } +} +#endif + +static void schedule_ll_tasks_execute(struct ll_schedule_data *sch) +{ + struct ll_schedule_domain *domain = sch->domain; + struct list_item *wlist; + struct task *task; + k_spinlock_key_t key; + + /* check each task in the list for pending */ + wlist = sch->tasks.next; + + /* + * Cannot use list_for_item(_safe)() because the task can cancel some + * other tasks, removing them from the list. This happens, e.g. when + * a pipeline task terminates a DMIC task. + */ + while (wlist != &sch->tasks) { +#ifdef CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS + uint32_t cycles0, cycles1; +#endif + task = list_item(wlist, struct task, list); + + if (task->state != SOF_TASK_STATE_PENDING) { + wlist = task->list.next; + continue; + } + + tr_dbg(&ll_tr, "task %p %pU being started...", task, task->uid); + +#ifdef CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS + cycles0 = (uint32_t)sof_cycle_get_64(); +#endif + task->state = SOF_TASK_STATE_RUNNING; + + /* + * The running task might cancel other tasks, which then get + * removed from the list + */ + task->state = task_run(task); + + wlist = task->list.next; + + key = k_spin_lock(&domain->lock); + + /* do we need to reschedule this task */ + if (task->state == SOF_TASK_STATE_COMPLETED) { + schedule_ll_task_done(sch, task); + } else { + /* update task's start time */ + schedule_ll_task_update_start(sch, task); + tr_dbg(&ll_tr, "task %p uid %pU finished, next period ticks %u, domain->next_tick %u", + task, task->uid, (uint32_t)task->start, + (uint32_t)domain->next_tick); + } + + k_spin_unlock(&domain->lock, key); + +#ifdef CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS + cycles1 = (uint32_t)sof_cycle_get_64(); + dsp_load_check(task, cycles0, cycles1); +#endif + } +} + +static void schedule_ll_client_reschedule(struct ll_schedule_data *sch) +{ + struct list_item *tlist; + struct task *task; + struct task *task_take = NULL; + uint64_t next_tick = sch->domain->new_target_tick; + + /* rearm only if there is work to do */ + if (atomic_read(&sch->domain->total_num_tasks)) { + /* traverse to set timer according to the earliest task */ + list_for_item(tlist, &sch->tasks) { + task = container_of(tlist, struct task, list); + + /* only check tasks asked for rescheduling */ + if (task->state != SOF_TASK_STATE_RESCHEDULE) + continue; + + /* update to use the earlier tick */ + if (task->start < next_tick) { + next_tick = task->start; + task_take = task; + } + } + + tr_dbg(&ll_tr, + "schedule_ll_clients_reschedule next_tick %u task_take %p", + (unsigned int)next_tick, task_take); + + /* update the target_tick */ + if (task_take) + sch->domain->new_target_tick = next_tick; + } + +} + +static void schedule_ll_tasks_run(void *data) +{ + struct ll_schedule_data *sch = data; + struct ll_schedule_domain *domain = sch->domain; + k_spinlock_key_t key; + uint32_t flags; + uint32_t core = cpu_get_id(); + + tr_dbg(&ll_tr, "timer interrupt on core %d, at %u, previous next_tick %u", + core, + (unsigned int)sof_cycle_get_64_atomic(), + (unsigned int)domain->next_tick); + + irq_local_disable(flags); + key = k_spin_lock(&domain->lock); + + /* disable domain on current core until tasks are finished */ + domain_disable(domain, core); + + if (!atomic_read(&domain->enabled_cores)) { + /* clear the domain/interrupts */ + domain_clear(domain); + } + + k_spin_unlock(&domain->lock, key); + + perf_cnt_init(&sch->pcd); + + /* run tasks if there are any pending */ + if (schedule_ll_is_pending(sch)) + schedule_ll_tasks_execute(sch); + + notifier_event(sch, NOTIFIER_ID_LL_POST_RUN, + NOTIFIER_TARGET_CORE_LOCAL, NULL, 0); + + perf_cnt_stamp(&sch->pcd, perf_ll_sched_trace, 0 /* ignored */); + perf_cnt_average(&sch->pcd, perf_avg_ll_sched_trace, 0 /* ignored */); + + key = k_spin_lock(&domain->lock); + + /* reset the new_target_tick for the first core */ + if (domain->new_target_tick < sof_cycle_get_64_atomic()) + domain->new_target_tick = UINT64_MAX; + + /* update the new_target_tick according to tasks on current core */ + schedule_ll_client_reschedule(sch); + + /* set the next interrupt according to the new_target_tick */ + if (domain->new_target_tick < domain->next_tick) { + domain_set(domain, domain->new_target_tick); + tr_dbg(&ll_tr, "tasks on core %d done, new_target_tick %u set", + core, (unsigned int)domain->new_target_tick); + } + + /* tasks on current core finished, re-enable domain on it */ + if (atomic_read(&sch->num_tasks)) + domain_enable(domain, core); + + k_spin_unlock(&domain->lock, key); + + irq_local_enable(flags); +} + +static int schedule_ll_domain_set(struct ll_schedule_data *sch, + struct task *task, uint64_t start, + uint64_t period, struct task *reference) +{ + struct ll_schedule_domain *domain = sch->domain; + int core = cpu_get_id(); + uint64_t task_start_us; + uint64_t task_start_ticks; + uint64_t task_start; + uint64_t offset; + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&domain->lock); + + ret = domain_register(domain, task, &schedule_ll_tasks_run, sch); + if (ret < 0) { + tr_err(&ll_tr, "cannot register domain %d", + ret); + goto done; + } + + tr_dbg(&ll_tr, "task->start %u next_tick %u", + (unsigned int)task->start, + (unsigned int)domain->next_tick); + + task_start_us = period ? period : start; + task_start_ticks = domain->ticks_per_ms * task_start_us / 1000; + task_start = task_start_ticks + sof_cycle_get_64_atomic(); + + if (reference) { + task->start = reference->start; + } else if (domain->next_tick == UINT64_MAX) { + /* first task, set domain */ + domain_set(domain, task_start); + task->start = domain->next_tick; + } else if (!period) { + /* one shot task, set domain if it is earlier */ + task->start = task_start; + if (task->start < domain->next_tick) + domain_set(domain, task_start); + } else if (task_start + task_start_ticks < domain->next_tick) { + /* + * Earlier periodic task, try to make it cadence-aligned with the existed task. + * In this case task_start_ticks is the number of ticks per period. + */ + offset = (domain->next_tick - task_start) % task_start_ticks; + task_start += offset; + domain_set(domain, task_start); + task->start = domain->next_tick; + } else { + /* later periodic task, simplify and cover it by the coming interrupt */ + task->start = domain->next_tick; + } + + /* increase task number of the core */ + atomic_add(&sch->num_tasks, 1); + + /* make sure enable domain on the core */ + domain_enable(domain, core); + + tr_info(&ll_tr, "new added task->start %u at %u", + (unsigned int)task->start, + (unsigned int)sof_cycle_get_64_atomic()); + tr_info(&ll_tr, "num_tasks %ld total_num_tasks %ld", + atomic_read(&sch->num_tasks), + atomic_read(&domain->total_num_tasks)); + +done: + k_spin_unlock(&domain->lock, key); + + return ret; +} + +static void schedule_ll_domain_clear(struct ll_schedule_data *sch, + struct task *task) +{ + struct ll_schedule_domain *domain = sch->domain; + k_spinlock_key_t key; + + key = k_spin_lock(&domain->lock); + + /* + * Decrement the number of tasks on the core. + * Disable domain on the core if needed + */ + if (atomic_sub(&sch->num_tasks, 1) == 1) + domain_disable(domain, cpu_get_id()); + + /* unregister the task */ + domain_unregister(domain, task, atomic_read(&sch->num_tasks)); + + tr_info(&ll_tr, "num_tasks %ld total_num_tasks %ld", + atomic_read(&sch->num_tasks), + atomic_read(&domain->total_num_tasks)); + + k_spin_unlock(&domain->lock, key); +} + +static void schedule_ll_task_insert(struct task *task, struct list_item *tasks) +{ + struct list_item *tlist; + struct task *curr_task; + + /* tasks are added into the list from highest to lowest priority + * and tasks with the same priority should be served on + * a first-come-first-serve basis + */ + list_for_item(tlist, tasks) { + curr_task = container_of(tlist, struct task, list); + if (task->priority < curr_task->priority) { + list_item_append(&task->list, &curr_task->list); + return; + } + } + + /* if task has not been added, means that it has the lowest + * priority and should be added at the end of the list + */ + list_item_append(&task->list, tasks); +} + +static void schedule_ll_task_insert_before(struct task *task, struct task *before) +{ + list_item_append(&task->list, &before->list); +} + +static void schedule_ll_task_insert_after(struct task *task, struct task *after) +{ + list_item_prepend(&task->list, &after->list); +} + +static int schedule_ll_task_common(struct ll_schedule_data *sch, struct task *task, + uint64_t start, uint64_t period, + struct task *reference, bool before) +{ + struct ll_task_pdata *pdata; + struct ll_task_pdata *reg_pdata; + struct list_item *tlist; + struct task *curr_task; + struct task *registrable_task = NULL; + struct pipeline_task *pipe_task; + uint32_t flags; + int ret = 0; + + irq_local_disable(flags); + + /* check if task is already scheduled */ + list_for_item(tlist, &sch->tasks) { + curr_task = container_of(tlist, struct task, list); + + /* keep original start */ + if (curr_task == task) + goto out; + } + + pdata = ll_sch_get_pdata(task); + + tr_info(&ll_tr, "task add %p %pU", task, task->uid); + if (start <= UINT_MAX && period <= UINT_MAX) + tr_info(&ll_tr, "task params pri %d flags %d start %u period %u", + task->priority, task->flags, + (unsigned int)start, (unsigned int)period); + else + tr_info(&ll_tr, "task params pri %d flags %d start or period > %u", + task->priority, task->flags, UINT_MAX); + + pdata->period = period; + + /* for full synchronous domain, calculate ratio and initialize skip_cnt for task */ + if (sch->domain->full_sync) { + pdata->ratio = 1; + pdata->skip_cnt = (uint16_t)SOF_TASK_SKIP_COUNT; + + /* get the registrable task */ + list_for_item(tlist, &sch->tasks) { + curr_task = container_of(tlist, struct task, list); + pipe_task = pipeline_task_get(curr_task); + + /* registrable task found */ + if (pipe_task->registrable) { + registrable_task = curr_task; + break; + } + } + + /* we found a registrable task */ + if (registrable_task) { + reg_pdata = ll_sch_get_pdata(registrable_task); + + /* update ratio for all tasks */ + list_for_item(tlist, &sch->tasks) { + curr_task = container_of(tlist, struct task, list); + pdata = ll_sch_get_pdata(curr_task); + + /* the assumption is that the registrable + * task has the smallest period + */ + if (pdata->period < reg_pdata->period) { + tr_err(&ll_tr, + "registrable task has a period longer than current task"); + ret = -EINVAL; + goto out; + } + + pdata->ratio = period / reg_pdata->period; + } + } + } + + /* insert task into the list */ + if (!reference) + schedule_ll_task_insert(task, &sch->tasks); + else if (before) + schedule_ll_task_insert_before(task, reference); + else + schedule_ll_task_insert_after(task, reference); + task->state = SOF_TASK_STATE_QUEUED; + + /* set schedule domain */ + ret = schedule_ll_domain_set(sch, task, start, period, reference); + if (ret < 0) { + list_item_del(&task->list); + goto out; + } + + +out: + irq_local_enable(flags); + + return ret; +} + +static int schedule_ll_task(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + struct ll_schedule_data *sch = data; + + return schedule_ll_task_common(sch, task, start, period, NULL, false); +} + +static int schedule_ll_task_before(void *data, struct task *task, uint64_t start, + uint64_t period, struct task *before) +{ + struct ll_schedule_data *sch = data; + + return schedule_ll_task_common(sch, task, start, period, before, true); +} + +static int schedule_ll_task_after(void *data, struct task *task, uint64_t start, + uint64_t period, struct task *after) +{ + struct ll_schedule_data *sch = data; + + return schedule_ll_task_common(sch, task, start, period, after, false); +} + +int schedule_task_init_ll(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) +{ + struct ll_task_pdata *ll_pdata; + int ret; + + ret = schedule_task_init(task, uid, type, priority, run, data, core, + flags); + if (ret < 0) + return ret; + + if (ll_sch_get_pdata(task)) + return -EEXIST; + + ll_pdata = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(*ll_pdata)); + + if (!ll_pdata) { + tr_err(&ll_tr, "alloc failed"); + return -ENOMEM; + } + + ll_sch_set_pdata(task, ll_pdata); + + return 0; +} + +static int schedule_ll_task_free(void *data, struct task *task) +{ + struct ll_task_pdata *ll_pdata; + uint32_t flags; + + irq_local_disable(flags); + + /* release the resources */ + task->state = SOF_TASK_STATE_FREE; + ll_pdata = ll_sch_get_pdata(task); + rfree(ll_pdata); + ll_sch_set_pdata(task, NULL); + + irq_local_enable(flags); + + return 0; +} + +static int schedule_ll_task_cancel(void *data, struct task *task) +{ + struct ll_schedule_data *sch = data; + struct list_item *tlist; + struct task *curr_task; + uint32_t flags; + + irq_local_disable(flags); + + tr_info(&ll_tr, "task cancel %p %pU", task, task->uid); + + /* check to see if we are scheduled */ + list_for_item(tlist, &sch->tasks) { + curr_task = container_of(tlist, struct task, list); + + /* found it */ + if (curr_task == task) { + schedule_ll_domain_clear(sch, task); + + /* remove work from list */ + task->state = SOF_TASK_STATE_CANCEL; + list_item_del(&task->list); + + break; + } + } + + irq_local_enable(flags); + + return 0; +} + +#if CONFIG_SCHEDULE_LL_NO_RESCHEDULE_TASK +/* As a null function pointer */ +#define reschedule_ll_task ((void*)0) + +#else +static int reschedule_ll_task(void *data, struct task *task, uint64_t start) +{ + struct ll_schedule_data *sch = data; + struct list_item *tlist; + struct task *curr_task; + uint32_t flags; + uint64_t time; + + time = sch->domain->ticks_per_ms * start / 1000; + + time += sof_cycle_get_64_atomic(); + + irq_local_disable(flags); + + /* check to see if we are already scheduled */ + list_for_item(tlist, &sch->tasks) { + curr_task = container_of(tlist, struct task, list); + /* found it */ + if (curr_task == task) { + /* set start time */ + task->start = time; + goto out; + } + } + + tr_err(&ll_tr, "task not found"); + +out: + + irq_local_enable(flags); + + return 0; +} +#endif + +static void scheduler_free_ll(void *data, uint32_t flags) +{ + struct ll_schedule_data *sch = data; + uint32_t irq_flags; + + irq_local_disable(irq_flags); + + domain_unregister(sch->domain, NULL, 0); + + if (!(flags & SOF_SCHEDULER_FREE_IRQ_ONLY)) + notifier_unregister(sch, NULL, + NOTIFIER_CLK_CHANGE_ID(sch->domain->clk)); + + irq_local_enable(irq_flags); +} + +static void ll_scheduler_recalculate_tasks(struct ll_schedule_data *sch, + struct clock_notify_data *clk_data) +{ + uint64_t current = sof_cycle_get_64_atomic(); + struct list_item *tlist; + struct task *task; + uint64_t delta_ms; + + list_for_item(tlist, &sch->tasks) { + task = container_of(tlist, struct task, list); + delta_ms = (task->start - current) / + clk_data->old_ticks_per_msec; + + task->start = delta_ms ? + current + sch->domain->ticks_per_ms * delta_ms : + current + (sch->domain->ticks_per_ms >> 3); + } +} + +static void ll_scheduler_notify(void *arg, enum notify_id type, void *data) +{ + struct ll_schedule_data *sch = arg; + struct clock_notify_data *clk_data = data; + uint32_t flags; + + irq_local_disable(flags); + + /* we need to recalculate tasks when clock frequency changes */ + if (clk_data->message == CLOCK_NOTIFY_POST) { + sch->domain->ticks_per_ms = k_ms_to_cyc_ceil64(1); + ll_scheduler_recalculate_tasks(sch, clk_data); + } + + irq_local_enable(flags); +} + +int scheduler_init_ll(struct ll_schedule_domain *domain) +{ + struct ll_schedule_data *sch; + + /* initialize scheduler private data */ + sch = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*sch)); + if (!sch) { + tr_err(&ll_tr, "allocation failed"); + return -ENOMEM; + } + list_init(&sch->tasks); + atomic_init(&sch->num_tasks, 0); + sch->domain = domain; + + /* notification of clock changes */ + notifier_register(sch, NULL, NOTIFIER_CLK_CHANGE_ID(domain->clk), + ll_scheduler_notify, 0); + + scheduler_init(domain->type, &schedule_ll_ops, sch); + + + return 0; +} + +static const struct scheduler_ops schedule_ll_ops = { + .schedule_task = schedule_ll_task, + .schedule_task_before = schedule_ll_task_before, + .schedule_task_after = schedule_ll_task_after, + .schedule_task_free = schedule_ll_task_free, + .schedule_task_cancel = schedule_ll_task_cancel, + .reschedule_task = reschedule_ll_task, + .scheduler_free = scheduler_free_ll, + .scheduler_restore = NULL, + .schedule_task_running = NULL, +}; diff --git a/src/schedule/schedule.c b/src/schedule/schedule.c index 5dbeb7580031..5e56b6c490e0 100644 --- a/src/schedule/schedule.c +++ b/src/schedule/schedule.c @@ -6,22 +6,29 @@ /* Generic scheduler */ -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> +#include <sof/lib/uuid.h> #include <sof/list.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> +#include <rtos/task.h> #include <ipc/topology.h> #include <errno.h> #include <stdint.h> +#include <ipc4/base_fw.h> + +LOG_MODULE_REGISTER(schedule, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(schedule); + +DECLARE_TR_CTX(sch_tr, SOF_UUID(schedule_uuid), LOG_LEVEL_INFO); int schedule_task_init(struct task *task, - uint32_t uid, uint16_t type, uint16_t priority, - enum task_state (*run)(void *data), void *data, - uint16_t core, uint32_t flags) + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) { if (type >= SOF_SCHEDULE_COUNT) { - trace_schedule_error("schedule_task_init() error: " - "invalid task type"); + tr_err(&sch_tr, "invalid task type"); return -EINVAL; } @@ -43,8 +50,12 @@ static void scheduler_register(struct schedule_data *scheduler) if (!*sch) { /* init schedulers list */ - *sch = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, + *sch = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(**sch)); + if (!*sch) { + tr_err(&sch_tr, "allocation failed"); + return; + } list_init(&(*sch)->list); } @@ -55,7 +66,15 @@ void scheduler_init(int type, const struct scheduler_ops *ops, void *data) { struct schedule_data *sch; - sch = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, sizeof(*sch)); + if (!ops || !ops->schedule_task || !ops->schedule_task_cancel || + !ops->schedule_task_free) + return; + + sch = rzalloc(SOF_MEM_FLAG_KERNEL, sizeof(*sch)); + if (!sch) { + tr_err(&sch_tr, "allocation failed"); + sof_panic(SOF_IPC_PANIC_IPC); + } list_init(&sch->list); sch->type = type; sch->ops = ops; @@ -63,3 +82,41 @@ void scheduler_init(int type, const struct scheduler_ops *ops, void *data) scheduler_register(sch); } + +/* Locks for the list here should be held by the caller, + * as different schedulers use different locks + */ +void scheduler_get_task_info(struct scheduler_props *scheduler_props, + uint32_t *data_off_size, + struct list_item *tasks) +{ + /* TODO + * - container_of(tlist, struct task, list)->uid->id could possibly be used as task id, + * but currently accessing it crashes, so setting the value to 0 for now + */ + struct task_props *task_props; + struct list_item *tlist; + + scheduler_props->core_id = cpu_get_id(); + scheduler_props->task_count = 0; + *data_off_size += sizeof(*scheduler_props); + + task_props = (struct task_props *)((uint8_t *)scheduler_props + sizeof(*scheduler_props)); + list_for_item(tlist, tasks) { + /* Fill SchedulerProps */ + scheduler_props->task_count++; + + /* Fill TaskProps */ + task_props->task_id = 0; + + /* Left unimplemented */ + task_props->module_instance_count = 0; + + /* TODO: after module instances are implemented, remember to increase + * data_off_size and the offset to next task_props by the amount of + * module instances included + */ + *data_off_size += sizeof(*task_props); + task_props++; + } +} diff --git a/src/schedule/task.c b/src/schedule/task.c deleted file mode 100644 index 47ba68e84883..000000000000 --- a/src/schedule/task.c +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - -/* - * Generic audio task. - */ - -#include <sof/audio/component_ext.h> -#include <sof/audio/pipeline.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/agent.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/lib/uuid.h> -#include <sof/lib/wait.h> -#include <sof/platform.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> -#include <ipc/topology.h> -#include <errno.h> -#include <stddef.h> -#include <stdint.h> - -#if STATIC_PIPE -#include <sof/audio/pipeline.h> -#include <ipc/trace.h> -#endif - -typedef enum task_state (*task_main)(void *); - -/* 37f1d41f-252d-448d-b9c4-1e2bee8e1bf1 */ -DECLARE_SOF_UUID("main-task", main_task_uuid, 0x37f1d41f, 0x252d, 0x448d, - 0xb9, 0xc4, 0x1e, 0x2b, 0xee, 0x8e, 0x1b, 0xf1); - -static void sys_module_init(void) -{ - intptr_t *module_init = (intptr_t *)(&_module_init_start); - - for (; module_init < (intptr_t *)&_module_init_end; ++module_init) - ((void(*)(void))(*module_init))(); -} - -static uint64_t task_main_deadline(void *data) -{ - return SOF_TASK_DEADLINE_IDLE; -} - -enum task_state task_main_master_core(void *data) -{ - struct ipc *ipc = ipc_get(); - - /* main audio processing loop */ - while (1) { - /* sleep until next IPC or DMA */ - wait_for_interrupt(0); - - if (!ipc->pm_prepare_D3) - ipc_send_queued_msg(); - - platform_shared_commit(ipc, sizeof(*ipc)); - } - - return SOF_TASK_STATE_COMPLETED; -} - -void task_main_init(void) -{ - struct task **main_task = task_main_get(); - int cpu = cpu_get_id(); - int ret; - task_main main_main = cpu == PLATFORM_MASTER_CORE_ID ? - &task_main_master_core : &task_main_slave_core; - struct task_ops ops = { - .run = main_main, - .get_deadline = task_main_deadline, - }; - - *main_task = rzalloc(SOF_MEM_ZONE_SYS, 0, SOF_MEM_CAPS_RAM, - sizeof(**main_task)); - - ret = schedule_task_init_edf(*main_task, SOF_UUID(main_task_uuid), - &ops, NULL, cpu, 0); - assert(!ret); -} - -void task_main_free(void) -{ - schedule_task_free(*task_main_get()); -} - -int task_main_start(struct sof *sof) -{ - int ret; - - /* init default audio components */ - sys_comp_init(sof); - - /* init self-registered modules */ - sys_module_init(); - - /* init pipeline position offsets */ - pipeline_posn_init(sof); - -#if STATIC_PIPE - /* init static pipeline */ - ret = init_static_pipeline(sof->ipc); - if (ret < 0) - panic(SOF_IPC_PANIC_TASK); -#endif - /* let host know DSP boot is complete */ - ret = platform_boot_complete(0); - if (ret < 0) - return ret; - - /* task initialized in edf_scheduler_init */ - schedule_task(*task_main_get(), 0, UINT64_MAX); - - /* something bad happened */ - return -EIO; -} diff --git a/src/schedule/timer_domain.c b/src/schedule/timer_domain.c deleted file mode 100644 index a93ee7e23319..000000000000 --- a/src/schedule/timer_domain.c +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cpu.h> -#include <sof/lib/memory.h> -#include <sof/platform.h> -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/ll_schedule_domain.h> -#include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <ipc/topology.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -struct timer_domain { - struct timer *timer; - uint64_t timeout; - void *arg[PLATFORM_CORE_COUNT]; -}; - -const struct ll_schedule_domain_ops timer_domain_ops; - -static inline void timer_report_delay(int id, uint64_t delay) -{ - uint32_t ll_delay_us = (delay * 1000) / - clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1); - - trace_ll_error("timer_report_delay(): timer %d delayed by %d uS %d " - "ticks", id, ll_delay_us, delay); - - /* Fix compile error when traces are disabled */ - (void)ll_delay_us; -} - -static int timer_domain_register(struct ll_schedule_domain *domain, - uint64_t period, struct task *task, - void (*handler)(void *arg), void *arg) -{ - struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); - int core = cpu_get_id(); - int ret = 0; - - tracev_ll("timer_domain_register()"); - - /* tasks already registered on this core */ - if (timer_domain->arg[core]) - goto out; - - trace_ll("timer_domain_register domain->type %d domain->clk %d domain->ticks_per_ms %d period %d", - domain->type, domain->clk, domain->ticks_per_ms, period); - - timer_domain->arg[core] = arg; - - ret = timer_register(timer_domain->timer, handler, arg); - -out: - platform_shared_commit(timer_domain, sizeof(*timer_domain)); - - return ret; -} - -static void timer_domain_unregister(struct ll_schedule_domain *domain, - struct task *task, uint32_t num_tasks) -{ - struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); - int core = cpu_get_id(); - - tracev_ll("timer_domain_unregister()"); - - /* tasks still registered on this core */ - if (!timer_domain->arg[core] || num_tasks) - goto out; - - trace_ll("timer_domain_unregister domain->type %d domain->clk %d", - domain->type, domain->clk); - - timer_unregister(timer_domain->timer, timer_domain->arg[core]); - - timer_domain->arg[core] = NULL; - -out: - platform_shared_commit(timer_domain, sizeof(*timer_domain)); -} - -static void timer_domain_enable(struct ll_schedule_domain *domain, int core) -{ - struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); - - timer_enable(timer_domain->timer, timer_domain->arg[core], core); - - platform_shared_commit(timer_domain, sizeof(*timer_domain)); -} - -static void timer_domain_disable(struct ll_schedule_domain *domain, int core) -{ - struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); - - timer_disable(timer_domain->timer, timer_domain->arg[core], core); - - platform_shared_commit(timer_domain, sizeof(*timer_domain)); -} - -static void timer_domain_set(struct ll_schedule_domain *domain, uint64_t start) -{ - struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); - uint64_t ticks_req = domain->ticks_per_ms * timer_domain->timeout / - 1000 + start; - uint64_t ticks_set; - - ticks_set = platform_timer_set(timer_domain->timer, ticks_req); - - /* Was timer set to the value we requested? If no it means some - * delay occurred and we should report that in error log. - */ - if (ticks_req < ticks_set) - timer_report_delay(timer_domain->timer->id, - ticks_set - ticks_req); - - domain->last_tick = ticks_set; - - platform_shared_commit(timer_domain, sizeof(*timer_domain)); -} - -static void timer_domain_clear(struct ll_schedule_domain *domain) -{ - struct timer_domain *timer_domain = ll_sch_domain_get_pdata(domain); - - platform_timer_clear(timer_domain->timer); - - platform_shared_commit(timer_domain, sizeof(*timer_domain)); -} - -static bool timer_domain_is_pending(struct ll_schedule_domain *domain, - struct task *task) -{ - return task->start <= platform_timer_get(timer_get()); -} - -struct ll_schedule_domain *timer_domain_init(struct timer *timer, int clk, - uint64_t timeout) -{ - struct ll_schedule_domain *domain; - struct timer_domain *timer_domain; - - trace_ll("timer_domain_init clk %d timeout %u", clk, timeout); - - domain = domain_init(SOF_SCHEDULE_LL_TIMER, clk, false, - &timer_domain_ops); - - timer_domain = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*timer_domain)); - timer_domain->timer = timer; - timer_domain->timeout = timeout; - - ll_sch_domain_set_pdata(domain, timer_domain); - - platform_shared_commit(domain, sizeof(*domain)); - platform_shared_commit(timer_domain, sizeof(*timer_domain)); - - return domain; -} - -const struct ll_schedule_domain_ops timer_domain_ops = { - .domain_register = timer_domain_register, - .domain_unregister = timer_domain_unregister, - .domain_enable = timer_domain_enable, - .domain_disable = timer_domain_disable, - .domain_set = timer_domain_set, - .domain_clear = timer_domain_clear, - .domain_is_pending = timer_domain_is_pending -}; diff --git a/src/schedule/zephyr_dma_domain.c b/src/schedule/zephyr_dma_domain.c new file mode 100644 index 000000000000..9bb76660ab29 --- /dev/null +++ b/src/schedule/zephyr_dma_domain.c @@ -0,0 +1,636 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2022 NXP +// +// Author: Paul Olaru <paul.olaru@nxp.com> +// Author: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com> + +#include <sof/audio/component.h> +#include <rtos/bit.h> +#include <rtos/interrupt.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <sof/lib/cpu.h> +#include <sof/lib/dma.h> +#include <sof/platform.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <ipc/topology.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +LOG_MODULE_DECLARE(ll_schedule, CONFIG_SOF_LOG_LEVEL); + +#if defined(CONFIG_IMX) || defined(CONFIG_AMD) +#define interrupt_get_irq mux_interrupt_get_irq +#define interrupt_register mux_interrupt_register +#define interrupt_unregister mux_interrupt_unregister +#define interrupt_enable mux_interrupt_enable +#define interrupt_disable mux_interrupt_disable +#endif + +#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); + +struct zephyr_dma_domain_channel { + struct dma_chan_data *channel; + /* used when unregistering a pipeline task - the channel + * which we're disabling is the one that has been tied to the + * passed pipeline task. + */ + struct pipeline_task *pipe_task; + /* pointer to parent struct zephyr_dma_domain_irq. + * + * mostly used during unregister operation to avoid + * having to look for a channel's IRQ parent after it + * has been fetched. + */ + struct zephyr_dma_domain_irq *irq_data; + /* used to keep track of channels using the same INTID */ + struct list_item list; +}; + +struct zephyr_dma_domain_irq { + uint32_t intid; /* IRQ number */ + bool enabled; /* true if IRQ has been enabled */ + struct zephyr_dma_domain_thread *dt; + struct list_item list; /* used to keep track of all IRQs */ + struct list_item channels; /* list of channels using this IRQ */ +}; + +struct zephyr_dma_domain_thread { + struct k_thread ll_thread; /* thread handle */ + struct k_sem sem; /* used to signal when work should be done */ + void (*handler)(void *arg); /* work to be done */ + void *arg; /* data used by work function */ + bool started; /* true if the thread was started */ +}; + +struct zephyr_dma_domain { + struct dma *dma_array; /* array of scheduling DMAs */ + uint32_t num_dma; /* number of scheduling DMAs */ + + struct list_item irqs; /* list of all IRQs used by the DMACs */ + + /* array of Zephyr threads - one for each core */ + struct zephyr_dma_domain_thread domain_thread[CONFIG_CORE_COUNT]; +}; + +static int zephyr_dma_domain_register(struct ll_schedule_domain *domain, + struct task *task, + void (*handler)(void *arg), + void *arg); +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, + struct task *task); + +static const struct ll_schedule_domain_ops zephyr_dma_domain_ops = { + .domain_register = zephyr_dma_domain_register, + .domain_unregister = zephyr_dma_domain_unregister, + .domain_task_cancel = zephyr_dma_domain_task_cancel +}; + +struct ll_schedule_domain *zephyr_dma_domain_init(struct dma *dma_array, + uint32_t num_dma, + int clk) +{ + struct ll_schedule_domain *domain; + struct zephyr_dma_domain *zephyr_dma_domain; + + /* initialize domain */ + domain = domain_init(SOF_SCHEDULE_LL_DMA, + clk, + true, + &zephyr_dma_domain_ops); + if (!domain) { + tr_err(&ll_tr, "domain init failed"); + return NULL; + } + + /* initialize domain pdata */ + zephyr_dma_domain = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*zephyr_dma_domain)); + if (!zephyr_dma_domain) { + tr_err(&ll_tr, "allocation failed"); + rfree(domain); + return NULL; + } + + zephyr_dma_domain->dma_array = dma_array; + zephyr_dma_domain->num_dma = num_dma; + + list_init(&zephyr_dma_domain->irqs); + + /* set pdata */ + ll_sch_domain_set_pdata(domain, zephyr_dma_domain); + + return domain; +} + +static void zephyr_dma_domain_thread_fn(void *p1, void *p2, void *p3) +{ + struct zephyr_dma_domain_thread *dt = p1; + + while (true) { + /* wait for DMA IRQ */ + k_sem_take(&dt->sem, K_FOREVER); + + /* do work */ + dt->handler(dt->arg); + } +} + +static void dma_irq_handler(void *data) +{ + struct zephyr_dma_domain_irq *irq_data; + struct zephyr_dma_domain_thread *dt; + struct k_sem *sem; + struct list_item *i; + struct zephyr_dma_domain_channel *chan_data; + + irq_data = data; + sem = &irq_data->dt->sem; + dt = irq_data->dt; + + /* go through each channel using the INTID which corresponds to the IRQ + * that has been triggered. For each channel, we clear the IRQ bit, thus + * stopping them from asserting the IRQ. + */ + list_for_item(i, &irq_data->channels) { + chan_data = container_of(i, struct zephyr_dma_domain_channel, list); + + if (dma_interrupt_legacy(chan_data->channel, DMA_IRQ_STATUS_GET)) + dma_interrupt_legacy(chan_data->channel, DMA_IRQ_CLEAR); + } + + /* clear IRQ - the mask argument is unused ATM */ + interrupt_clear_mask(irq_data->intid, 0); + + /* give resources to thread semaphore */ + if (dt->handler) + k_sem_give(sem); +} + +static int enable_dma_irq(struct zephyr_dma_domain_irq *irq_data) +{ + struct zephyr_dma_domain_channel *chan_data; + int ret; + + /* ATM, it's impossible to have two channels added to the IRQ list + * without calling enable_dma_irq. Therefore, the channel for which we + * need to UNMASK/CLEAR the IRQ is the last one added to the channel + * list. + */ + chan_data = container_of(irq_data->channels.prev, + struct zephyr_dma_domain_channel, list); + + dma_interrupt_legacy(chan_data->channel, DMA_IRQ_CLEAR); + + /* only enable the interrupt once. Also register the ISR and data once. + * + * note: irq_data->enabled is never set to false but since the irq_data is + * free'd and allocated each time with rzalloc it will be set to false by + * default. + */ + if (!irq_data->enabled) { + /* the mask argument is unused ATM */ + interrupt_clear_mask(irq_data->intid, 0); + + ret = interrupt_register(irq_data->intid, dma_irq_handler, irq_data); + if (ret < 0) + return ret; + + interrupt_enable(irq_data->intid, irq_data); + + irq_data->enabled = true; + } + + dma_interrupt_legacy(chan_data->channel, DMA_IRQ_UNMASK); + + return 0; +} + +static struct zephyr_dma_domain_irq *fetch_irq_data(struct zephyr_dma_domain *domain, + uint32_t intid) +{ + struct zephyr_dma_domain_irq *crt; + struct list_item *i; + + /* go through the list of IRQs used by the DMACs and find the one + * using the same INTID as the one passed as argument to this function. + */ + list_for_item(i, &domain->irqs) { + crt = container_of(i, struct zephyr_dma_domain_irq, list); + + if (crt->intid == intid) + return crt; + } + + return NULL; +} + +bool chan_is_registered(struct zephyr_dma_domain *domain, struct dma_chan_data *chan) +{ + struct zephyr_dma_domain_irq *irq_data; + struct zephyr_dma_domain_channel *chan_data; + struct list_item *i, *j; + + list_for_item(i, &domain->irqs) { + irq_data = container_of(i, struct zephyr_dma_domain_irq, list); + + list_for_item(j, &irq_data->channels) { + chan_data = container_of(j, struct zephyr_dma_domain_channel, list); + + if (chan_data->channel == chan) + return true; + } + } + + return false; +} + +static int register_dma_irq(struct zephyr_dma_domain *domain, + struct zephyr_dma_domain_irq **irq_data, + struct zephyr_dma_domain_thread *dt, + struct pipeline_task *pipe_task, + int core) +{ + struct dma *crt_dma; + struct dma_chan_data *crt_chan; + struct zephyr_dma_domain_irq *crt_irq_data; + struct zephyr_dma_domain_channel *chan_data; + int i, j, irq, ret; + uint32_t flags; + + /* iterate through all available channels in order to find a + * suitable channel for which the DMA IRQs will be enabled. + */ + for (i = 0; i < domain->num_dma; i++) { + crt_dma = domain->dma_array + i; + + for (j = 0; j < crt_dma->plat_data.channels; j++) { + crt_chan = crt_dma->chan + j; + + /* skip if channel is not a scheduling source */ + if (!dma_is_scheduling_source(crt_chan)) + continue; + + /* skip if channel is not active */ + if (crt_chan->status != COMP_STATE_ACTIVE) + continue; + + /* skip if channel not owned by current core */ + if (core != crt_chan->core) + continue; + + /* skip is DMA chan is already registered with domain */ + if (chan_is_registered(domain, crt_chan)) + continue; + + /* get IRQ number for current channel */ + irq = interrupt_get_irq(dma_chan_irq(crt_dma, j), + dma_chan_irq_name(crt_dma, j)); + + crt_irq_data = fetch_irq_data(domain, irq); + + if (!crt_irq_data) { + /* if there's no list item matching given IRQ then + * that IRQ hasn't been allocated yet so we need to do + * so here. + */ + crt_irq_data = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*crt_irq_data)); + if (!crt_irq_data) + return -ENOMEM; + + list_init(&crt_irq_data->channels); + + crt_irq_data->intid = irq; + crt_irq_data->dt = dt; + + list_item_append(&crt_irq_data->list, &domain->irqs); + } + + chan_data = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*chan_data)); + if (!chan_data) + return -ENOMEM; + + irq_local_disable(flags); + + chan_data->channel = crt_chan; + /* bind registrable ptask to channel */ + chan_data->pipe_task = pipe_task; + chan_data->irq_data = crt_irq_data; + + list_item_append(&chan_data->list, &crt_irq_data->channels); + + if (dt->started) { + /* the IRQ should only be enabled after the DT has + * been started to avoid missing some interrupts. + */ + ret = enable_dma_irq(crt_irq_data); + if (ret < 0) { + irq_local_enable(flags); + return ret; + } + } + + /* let caller know we have found a channel */ + *irq_data = crt_irq_data; + + irq_local_enable(flags); + + return 0; + } + } + + /* if this point is reached then that means we weren't able to + * find a suitable channel, let caller know + */ + return -EINVAL; +} + +static int zephyr_dma_domain_register(struct ll_schedule_domain *domain, + struct task *task, + void (*handler)(void *arg), + void *arg) +{ + struct zephyr_dma_domain *zephyr_dma_domain; + struct zephyr_dma_domain_thread *dt; + struct pipeline_task *pipe_task; + struct zephyr_dma_domain_irq *irq_data; + k_tid_t thread; + int core, ret; + uint32_t flags; + char thread_name[] = "dma_domain_thread0"; + + zephyr_dma_domain = ll_sch_get_pdata(domain); + core = cpu_get_id(); + irq_data = NULL; + dt = zephyr_dma_domain->domain_thread + core; + pipe_task = pipeline_task_get(task); + + tr_info(&ll_tr, "entry"); + + /* 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. + * + * this is done because we can have multiple DMA IRQs giving + * resources to the Zephyr thread semaphore on the same core + */ + ret = register_dma_irq(zephyr_dma_domain, + &irq_data, + dt, + pipe_task, + core); + + if (ret < 0) { + tr_err(&ll_tr, + "failed to register DMA IRQ for pipe task %p on core %d", + pipe_task, core); + + return ret; + } + + /* skip if Zephyr thread was already started on this core */ + if (dt->handler) + return 0; + + dt->handler = handler; + dt->arg = arg; + + /* prepare work semaphore */ + 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, + zephyr_dma_domain_thread_fn, + dt, + NULL, + NULL, + CONFIG_LL_THREAD_PRIORITY, + 0, + K_FOREVER); + +#ifdef CONFIG_SCHED_CPU_MASK + k_thread_cpu_mask_clear(thread); + k_thread_cpu_mask_enable(thread, core); +#endif + k_thread_name_set(thread, thread_name); + + k_thread_start(thread); + + dt->started = true; + + if (irq_data && !irq_data->enabled) { + /* enable the DMA IRQ since register_dma_irq wasn't able + * to do so because of the fact that the Zephyr thread + * hadn't started at that point + */ + irq_local_disable(flags); + ret = enable_dma_irq(irq_data); + irq_local_enable(flags); + if (ret < 0) { + tr_err(&ll_tr, + "failed to enable DMA IRQ for pipe task %p on core %d", + pipe_task, + core); + return ret; + } + + return 0; + } + + /* if this point is reached then that means we weren't able to + * enable DMA IRQ either because data was NULL or the IRQ was + * already enabled even though the Zephyr thread wasn't started + */ + + tr_err(&ll_tr, "failed to register pipeline task %p on core %d", + pipe_task, + core); + + return -EINVAL; +} + +static struct zephyr_dma_domain_channel *fetch_channel_by_ptask(struct zephyr_dma_domain *domain, + struct pipeline_task *pipe_task) +{ + struct zephyr_dma_domain_irq *irq_data; + struct zephyr_dma_domain_channel *chan_data; + struct list_item *i, *j; + + /* go through all of the channel and find the one tied to the + * same pipeline task as the one passed as argument to this function. + */ + list_for_item(i, &domain->irqs) { + irq_data = container_of(i, struct zephyr_dma_domain_irq, list); + + list_for_item(j, &irq_data->channels) { + chan_data = container_of(j, struct zephyr_dma_domain_channel, list); + + if (chan_data->pipe_task == pipe_task) + return chan_data; + } + } + + return NULL; +} + +static void disable_dma_irq(struct zephyr_dma_domain_channel *chan_data) +{ + dma_interrupt_legacy(chan_data->channel, DMA_IRQ_MASK); + dma_interrupt_legacy(chan_data->channel, DMA_IRQ_CLEAR); + + /* the IRQ needs to be disable only when there's no more + * channels using it (a.k.a the list of channels is empty) + */ + if (list_is_empty(&chan_data->irq_data->channels)) { + /* the mask argument is unusued ATM */ + interrupt_clear_mask(chan_data->irq_data->intid, 0); + + interrupt_disable(chan_data->irq_data->intid, chan_data->irq_data); + interrupt_unregister(chan_data->irq_data->intid, chan_data->irq_data); + + list_item_del(&chan_data->irq_data->list); + + rfree(chan_data->irq_data); + } +} + +static int zephyr_dma_domain_unregister(struct ll_schedule_domain *domain, + struct task *task, + uint32_t num_tasks) +{ + struct zephyr_dma_domain *zephyr_dma_domain; + struct zephyr_dma_domain_thread *dt; + struct pipeline_task *pipe_task; + struct zephyr_dma_domain_channel *chan_data; + int core; + uint32_t flags; + + zephyr_dma_domain = ll_sch_get_pdata(domain); + pipe_task = pipeline_task_get(task); + core = cpu_get_id(); + dt = zephyr_dma_domain->domain_thread + core; + + tr_info(&ll_tr, "entry"); + + /* 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; + + irq_local_disable(flags); + + chan_data = fetch_channel_by_ptask(zephyr_dma_domain, pipe_task); + if (!chan_data) { + irq_local_enable(flags); + tr_err(&ll_tr, "pipeline task %p doesn't have an associated channel.", pipe_task); + return -EINVAL; + } + + if (chan_data->channel->status == COMP_STATE_ACTIVE) { + tr_warn(&ll_tr, "trying to unregister ptask %p while channel still active.", + pipe_task); + } + + /* remove channel from parent IRQ's list */ + list_item_del(&chan_data->list); + + /* disable DMA IRQ if need be */ + disable_dma_irq(chan_data); + + rfree(chan_data); + + irq_local_enable(flags); + + /* TODO: thread abortion logic goes here */ + + return 0; +} + +static void zephyr_dma_domain_task_cancel(struct ll_schedule_domain *domain, + 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 (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_domain.c b/src/schedule/zephyr_domain.c new file mode 100644 index 000000000000..ebf5aea8d4d2 --- /dev/null +++ b/src/schedule/zephyr_domain.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019-2021 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/symbol.h> +#include <rtos/userspace_helper.h> +#include <sof/lib/cpu.h> +#include <sof/lib/memory.h> +#include <sof/lib/watchdog.h> +#include <sof/math/numbers.h> +#include <sof/platform.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <ipc/topology.h> +#include <limits.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <zephyr/kernel.h> +#include <zephyr/sys_clock.h> + +LOG_MODULE_DECLARE(ll_schedule, CONFIG_SOF_LOG_LEVEL); + +/* + * Currently the Zephyr clock rate is part it's Kconfig known at build time. + * SOF on Intel CAVS platforms currently only aligns with Zephyr when both + * use the CAVS 19.2 MHz SSP clock. TODO - needs runtime alignment. + */ +#if CONFIG_XTENSA && CONFIG_CAVS && !CONFIG_INTEL_ADSP_TIMER +#error "Zephyr uses 19.2MHz clock derived from SSP which must be enabled." +#endif + +#define ZEPHYR_LL_STACK_SIZE 8192 + +#if CONFIG_SOF_USERSPACE_LL +K_THREAD_STACK_ARRAY_DEFINE(ll_sched_stack, CONFIG_CORE_COUNT, ZEPHYR_LL_STACK_SIZE); +#else +K_KERNEL_STACK_ARRAY_DEFINE(ll_sched_stack, CONFIG_CORE_COUNT, ZEPHYR_LL_STACK_SIZE); +#endif + +struct zephyr_domain_thread { + struct k_thread *ll_thread; + struct k_sem *sem; +#ifndef CONFIG_SOF_USERSPACE_LL + struct k_thread ll_thread_obj; + struct k_sem sem_obj; +#endif + void (*handler)(void *arg); + void *arg; +}; + +struct zephyr_domain { + struct k_timer *timer; +#ifndef CONFIG_SOF_USERSPACE_LL + struct k_timer timer_obj; +#endif + struct zephyr_domain_thread domain_thread[CONFIG_CORE_COUNT]; + struct ll_schedule_domain *ll_domain; +#if CONFIG_CROSS_CORE_STREAM + atomic_t block; + struct k_mutex block_mutex; + struct k_condvar block_condvar; +#endif +}; + +/* perf measurement windows size 2^x */ +#define CYCLES_WINDOW_SIZE CONFIG_SCHEDULE_LL_STATS_LOG_WINDOW_SIZE + +#ifdef CONFIG_SCHEDULE_LL_STATS_LOG +static inline void stats_report(unsigned int runs, int core, unsigned int cycles_sum, + unsigned int cycles_max, unsigned int overruns) +{ +#ifdef CONFIG_SCHEDULE_LL_STATS_LOG_EVERY_OTHER_WINDOW + if (runs & BIT(CYCLES_WINDOW_SIZE)) + return; +#endif + tr_info(&ll_tr, "ll core %u timer avg %u, max %u, overruns %u", + core, cycles_sum, cycles_max, overruns); +} +#endif /* CONFIG_SCHEDULE_LL_STATS_LOG */ + +static void zephyr_domain_thread_fn(void *p1, void *p2, void *p3) +{ + struct zephyr_domain *zephyr_domain = p1; + int core = POINTER_TO_INT(p2); + struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + core; +#ifdef CONFIG_SCHEDULE_LL_STATS_LOG + unsigned int runs = 0, overruns = 0, cycles_sum = 0, cycles_max = 0; + unsigned int cycles0, cycles1, diff, timer_fired; +#endif + + tr_dbg(&ll_tr, "ll core %u thread starting", core); + + for (;;) { + /* immediately go to sleep, waiting to be woken up by the timer */ + k_sem_take(dt->sem, K_FOREVER); + +#ifdef CONFIG_SCHEDULE_LL_STATS_LOG + cycles0 = k_cycle_get_32(); +#endif + +#if CONFIG_CROSS_CORE_STREAM + /* + * If zephyr_domain->block is set -- block LL scheduler from starting its + * next cycle. + * Mutex locking might be somewhat expensive, hence first check for + * zephyr_domain->block value is made without locking the mutex. If + * zephyr_domain->block is not set -- no need to do anything. Otherwise, + * usual condvar procedure is performed: mutex is locked to properly check + * zephyr_domain->block value again to avoid race with unblocking procedure + * (clearing zephyr_domain->block and broadcasting the condvar). + */ + if (atomic_get(&zephyr_domain->block)) { + k_mutex_lock(&zephyr_domain->block_mutex, K_FOREVER); + if (atomic_get(&zephyr_domain->block)) + k_condvar_wait(&zephyr_domain->block_condvar, + &zephyr_domain->block_mutex, K_FOREVER); + k_mutex_unlock(&zephyr_domain->block_mutex); + } +#endif + + dt->handler(dt->arg); + +#ifdef CONFIG_SCHEDULE_LL_STATS_LOG + cycles1 = k_cycle_get_32(); + + /* This handles wrapping correctly too */ + diff = cycles1 - cycles0; + + timer_fired = k_timer_status_get(zephyr_domain->timer); + if (timer_fired > 1) + overruns++; + + cycles_sum += diff; + cycles_max = diff > cycles_max ? diff : cycles_max; + + if (!(++runs & MASK(CYCLES_WINDOW_SIZE - 1, 0))) { + cycles_sum >>= CYCLES_WINDOW_SIZE; + stats_report(runs, core, cycles_sum, cycles_max, overruns); + cycles_sum = 0; + cycles_max = 0; + } +#endif /* CONFIG_SCHEDULE_LL_STATS_LOG */ + + /* Feed the watchdog */ + watchdog_feed(core); + } +} + +/* Timer callback: runs in timer IRQ context */ +static void zephyr_domain_timer_fn(struct k_timer *timer) +{ + struct zephyr_domain *zephyr_domain = k_timer_user_data_get(timer); + int core; + + /* + * A race is possible when the Zephyr LL scheduling domain is being + * unregistered while a timer IRQ is processed on a different core. Then + * the timer is removed by the former but then re-added by the latter, + * but this time with no user data and no handler set. This leads to the + * timer continuing to trigger and then leading to a lock up when it is + * registered again next time. + */ + if (!zephyr_domain) { + k_timer_stop(timer); + return; + } + + for (core = 0; core < CONFIG_CORE_COUNT; core++) { + struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + core; + + if (dt->handler) + k_sem_give(dt->sem); + } +} + +/* The normal kernel-space implementation for register/unregister */ +#ifndef CONFIG_SOF_USERSPACE_LL + +static int zephyr_domain_register(struct ll_schedule_domain *domain, + struct task *task, + void (*handler)(void *arg), void *arg) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + int core = cpu_get_id(); + struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + core; + char thread_name[] = "ll_thread0"; + k_tid_t thread; + k_spinlock_key_t key; + + tr_dbg(&ll_tr, "entry"); + + /* domain work only needs registered once on each core */ + if (dt->handler) + return 0; + + dt->handler = handler; + dt->arg = arg; + + /* 10 is rather random, we better not accumulate 10 missed timer interrupts */ + k_sem_init(dt->sem, 0, 10); + + thread_name[sizeof(thread_name) - 2] = '0' + core; + + /* not allocated dynamically when LL in kernel space */ + dt->ll_thread = &dt->ll_thread_obj; + + thread = k_thread_create(dt->ll_thread, ll_sched_stack[core], ZEPHYR_LL_STACK_SIZE, + zephyr_domain_thread_fn, zephyr_domain, INT_TO_POINTER(core), + NULL, CONFIG_LL_THREAD_PRIORITY, 0, K_FOREVER); + +#ifdef CONFIG_SCHED_CPU_MASK + k_thread_cpu_mask_clear(thread); + k_thread_cpu_mask_enable(thread, core); +#endif + k_thread_name_set(thread, thread_name); + + k_thread_start(thread); + + key = k_spin_lock(&domain->lock); + + if (!k_timer_user_data_get(zephyr_domain->timer)) { + k_timeout_t start = {0}; + + k_timer_init(zephyr_domain->timer, zephyr_domain_timer_fn, NULL); + k_timer_user_data_set(zephyr_domain->timer, zephyr_domain); + + k_timer_start(zephyr_domain->timer, start, K_USEC(LL_TIMER_PERIOD_US)); + + /* Enable the watchdog */ + watchdog_enable(core); + } + + k_spin_unlock(&domain->lock, key); + + tr_info(&ll_tr, "domain->type %d domain->clk %d domain->ticks_per_ms %d period %d", + domain->type, domain->clk, domain->ticks_per_ms, (uint32_t)LL_TIMER_PERIOD_US); + + return 0; +} + +static int zephyr_domain_unregister(struct ll_schedule_domain *domain, + struct task *task, uint32_t num_tasks) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + int core = cpu_get_id(); + k_spinlock_key_t key; + + tr_dbg(&ll_tr, "entry"); + + /* tasks still registered on this core */ + if (num_tasks) + return 0; + + key = k_spin_lock(&domain->lock); + + if (!atomic_read(&domain->total_num_tasks)) { + /* Disable the watchdog */ + watchdog_disable(core); + + k_timer_stop(zephyr_domain->timer); + k_timer_user_data_set(zephyr_domain->timer, NULL); + } + + zephyr_domain->domain_thread[core].handler = NULL; + + k_spin_unlock(&domain->lock, key); + + tr_info(&ll_tr, "domain->type %d domain->clk %d", + domain->type, domain->clk); + + /* + * If running in the context of the domain thread, k_thread_abort() will + * not return + */ + k_thread_abort(zephyr_domain->domain_thread[core].ll_thread); + + tr_dbg(&ll_tr, "exit"); + + return 0; +} + +#else /* CONFIG_SOF_USERSPACE_LL */ + +/* User-space implementation for register/unregister */ + +static int zephyr_domain_register_user(struct ll_schedule_domain *domain, + struct task *task, + void (*handler)(void *arg), void *arg) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + int core = cpu_get_id(); + struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + core; + char thread_name[] = "ll_thread0"; + k_tid_t thread; + + tr_dbg(&ll_tr, "entry"); + + /* domain work only needs registered once on each core */ + if (dt->handler) + return 0; + + __ASSERT_NO_MSG(task->core == core); + + dt->handler = handler; + dt->arg = arg; + + /* 10 is rather random, we better not accumulate 10 missed timer interrupts */ + k_sem_init(dt->sem, 0, 10); + + thread_name[sizeof(thread_name) - 2] = '0' + core; + + if (!dt->ll_thread) { + /* Allocate thread structure dynamically */ + dt->ll_thread = k_object_alloc(K_OBJ_THREAD); + if (!dt->ll_thread) { + tr_err(&ll_tr, "Failed to allocate thread object for core %d", core); + dt->handler = NULL; + dt->arg = NULL; + return -ENOMEM; + } + + thread = k_thread_create(dt->ll_thread, ll_sched_stack[core], ZEPHYR_LL_STACK_SIZE, + zephyr_domain_thread_fn, zephyr_domain, + INT_TO_POINTER(core), NULL, CONFIG_LL_THREAD_PRIORITY, + K_USER, K_FOREVER); + +#ifdef CONFIG_SCHED_CPU_MASK + k_thread_cpu_mask_clear(thread); + k_thread_cpu_mask_enable(thread, core); +#endif + k_thread_name_set(thread, thread_name); + + k_mem_domain_add_thread(zephyr_ll_mem_domain(), thread); + k_thread_access_grant(thread, dt->sem, domain->lock, zephyr_domain->timer); + user_grant_dai_access_all(thread); + user_grant_dma_access_all(thread); + tr_dbg(&ll_tr, "granted LL access to thread %p (core %d)", thread, core); + + k_thread_start(thread); + } + + k_mutex_lock(domain->lock, K_FOREVER); + if (!k_timer_user_data_get(zephyr_domain->timer)) { + k_timeout_t start = {0}; + + k_timer_init(zephyr_domain->timer, zephyr_domain_timer_fn, NULL); + k_timer_user_data_set(zephyr_domain->timer, zephyr_domain); + + k_timer_start(zephyr_domain->timer, start, K_USEC(LL_TIMER_PERIOD_US)); + + /* Enable the watchdog */ + watchdog_enable(core); + } + + k_mutex_unlock(domain->lock); + + tr_info(&ll_tr, "domain->type %d domain->clk %d domain->ticks_per_ms %d period %d", + domain->type, domain->clk, domain->ticks_per_ms, (uint32_t)LL_TIMER_PERIOD_US); + + return 0; +} + +static int zephyr_domain_unregister_user(struct ll_schedule_domain *domain, + struct task *task, uint32_t num_tasks) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + int core = task->core; + + tr_dbg(&ll_tr, "entry"); + + /* tasks still registered on this core */ + if (num_tasks) + return 0; + + k_mutex_lock(domain->lock, K_FOREVER); + + if (!atomic_read(&domain->total_num_tasks)) { + /* Disable the watchdog */ + watchdog_disable(core); + + k_timer_stop(zephyr_domain->timer); + k_timer_user_data_set(zephyr_domain->timer, NULL); + } + + zephyr_domain->domain_thread[core].handler = NULL; + + k_mutex_unlock(domain->lock); + + tr_info(&ll_tr, "domain->type %d domain->clk %d", + domain->type, domain->clk); + + /* Thread not removed here, only the timer is stopped. + * Thread object cleanup would require k_thread_abort() which cannot + * be safely called from this context. The thread remains allocated + * but dormant until next registration or system shutdown. + */ + + tr_dbg(&ll_tr, "exit"); + + return 0; +} + +struct k_thread *zephyr_domain_thread_tid(struct ll_schedule_domain *domain) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + int core = cpu_get_id(); + struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + core; + + tr_dbg(&ll_tr, "entry"); + + return dt->ll_thread; +} + +#endif /* CONFIG_SOF_USERSPACE_LL */ + +#if CONFIG_CROSS_CORE_STREAM +static void zephyr_domain_block(struct ll_schedule_domain *domain) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + + tr_dbg(&ll_tr, "Blocking LL scheduler"); + + k_mutex_lock(&zephyr_domain->block_mutex, K_FOREVER); + atomic_set(&zephyr_domain->block, 1); + k_mutex_unlock(&zephyr_domain->block_mutex); +} + +static void zephyr_domain_unblock(struct ll_schedule_domain *domain) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(domain); + + tr_dbg(&ll_tr, "Unblocking LL scheduler"); + + k_mutex_lock(&zephyr_domain->block_mutex, K_FOREVER); + atomic_set(&zephyr_domain->block, 0); + k_condvar_broadcast(&zephyr_domain->block_condvar); + k_mutex_unlock(&zephyr_domain->block_mutex); +} +#endif + +APP_TASK_DATA static const struct ll_schedule_domain_ops zephyr_domain_ops = { +#ifdef CONFIG_SOF_USERSPACE_LL + .domain_register = zephyr_domain_register_user, + .domain_unregister = zephyr_domain_unregister_user, +#else + .domain_register = zephyr_domain_register, + .domain_unregister = zephyr_domain_unregister, +#endif +#if CONFIG_CROSS_CORE_STREAM + .domain_block = zephyr_domain_block, + .domain_unblock = zephyr_domain_unblock, +#endif +}; + +struct ll_schedule_domain *zephyr_domain_init(int clk) +{ + struct ll_schedule_domain *domain; + struct zephyr_domain *zephyr_domain; + struct zephyr_domain_thread *dt; + int core; + + domain = domain_init(SOF_SCHEDULE_LL_TIMER, clk, false, + &zephyr_domain_ops); + if (!domain) { + tr_err(&ll_tr, "domain init failed"); + return NULL; + } + +#if CONFIG_SOF_USERSPACE_LL + zephyr_domain = sof_heap_alloc(zephyr_ll_user_heap(), + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*zephyr_domain), sizeof(void *)); + if (zephyr_domain) + memset(zephyr_domain, 0, sizeof(*zephyr_domain)); +#else + zephyr_domain = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(*zephyr_domain)); +#endif + if (!zephyr_domain) { + tr_err(&ll_tr, "domain allocation failed"); + k_panic(); + return NULL; + } + + zephyr_domain->ll_domain = domain; + +#if CONFIG_SOF_USERSPACE_LL + /* Allocate timer dynamically for userspace access */ + zephyr_domain->timer = k_object_alloc(K_OBJ_TIMER); + if (!zephyr_domain->timer) { + tr_err(&ll_tr, "timer allocation failed"); + k_panic(); + return NULL; + } +#else + /* not allocated dynamically when LL in kernel space */ + zephyr_domain->timer = &zephyr_domain->timer_obj; +#endif + +#if CONFIG_CROSS_CORE_STREAM + atomic_set(&zephyr_domain->block, 0); + k_mutex_init(&zephyr_domain->block_mutex); + k_condvar_init(&zephyr_domain->block_condvar); +#endif + + ll_sch_domain_set_pdata(domain, zephyr_domain); + + for (core = 0; core < CONFIG_CORE_COUNT; core++) { + dt = zephyr_domain->domain_thread + core; +#ifdef CONFIG_SOF_USERSPACE_LL + dt->sem = k_object_alloc(K_OBJ_SEM); + if (!dt->sem) { + tr_err(&ll_tr, "Failed to allocate semaphore for core %d", core); + k_panic(); + } +#else + /* not allocated dynamically when LL in kernel space */ + dt->sem = &dt->sem_obj; +#endif + } + + return domain; +} + +/* Check if currently running in the LL scheduler thread context */ +bool ll_sch_is_current(void) +{ + struct zephyr_domain *zephyr_domain = ll_sch_domain_get_pdata(zephyr_ll_domain()); + + if (!zephyr_domain) + return false; + + struct zephyr_domain_thread *dt = zephyr_domain->domain_thread + cpu_get_id(); + + return k_current_get() == dt->ll_thread; +} +EXPORT_SYMBOL(ll_sch_is_current); diff --git a/src/schedule/zephyr_dp_schedule.c b/src/schedule/zephyr_dp_schedule.c new file mode 100644 index 000000000000..fdb10c7201af --- /dev/null +++ b/src/schedule/zephyr_dp_schedule.c @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Szkudlinski + */ + +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/llext_manager.h> +#include <rtos/task.h> +#include <rtos/userspace_helper.h> +#include <stdint.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/trace/trace.h> +#include <rtos/wait.h> +#include <rtos/interrupt.h> +#include <zephyr/kernel.h> +#include <zephyr/sys_clock.h> +#include <zephyr/sys/sem.h> +#include <zephyr/sys/mutex.h> +#include <sof/lib/notifier.h> +#include <ipc4/base_fw.h> + +#include "zephyr_dp_schedule.h" + +#include <zephyr/kernel/thread.h> + +LOG_MODULE_REGISTER(dp_schedule, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(dp_sched); + +DECLARE_TR_CTX(dp_tr, SOF_UUID(dp_sched_uuid), LOG_LEVEL_INFO); + +#define DP_LOCK_INIT(i, _) Z_SEM_INITIALIZER(dp_lock[i], 1, 1) +#define DP_LOCK_INIT_LIST LISTIFY(CONFIG_MP_MAX_NUM_CPUS, DP_LOCK_INIT, (,)) + +/* User threads don't need access to this array. Access is performed from + * the kernel space via a syscall. Array must be placed in special section + * to be qualified as initialized by the gen_kobject_list.py script. + */ +static +STRUCT_SECTION_ITERABLE_ARRAY(k_sem, dp_lock, CONFIG_MP_MAX_NUM_CPUS) = { DP_LOCK_INIT_LIST }; + +/* Each per-core instance of DP scheduler has separate structures; hence, locks are per-core. + * + * TODO: consider using cpu_get_id() instead of supplying core as a parameter. + */ +unsigned int scheduler_dp_lock(uint16_t core) +{ + k_sem_take(&dp_lock[core], K_FOREVER); + return core; +} + +void scheduler_dp_unlock(unsigned int key) +{ + k_sem_give(&dp_lock[key]); +} + +void scheduler_dp_grant(k_tid_t thread_id, uint16_t core) +{ + k_thread_access_grant(thread_id, &dp_lock[core]); +} + +/* dummy LL task - to start LL on secondary cores */ +static enum task_state scheduler_dp_ll_tick_dummy(void *data) +{ + return SOF_TASK_STATE_RESCHEDULE; +} + +/* + * function called after every LL tick + * + * This function checks if the queued DP tasks are ready to processing (meaning + * the module run by the task has enough data at all sources and enough free space + * on all sinks) + * + * if the task becomes ready, a deadline is set allowing Zephyr to schedule threads + * in right order + * + * TODO: currently there's a limitation - DP module must be surrounded by LL modules. + * it simplifies algorithm - there's no need to browse through DP chains calculating + * deadlines for each module in function of all modules execution status. + * Now is simple - modules deadline is its start + tick time. + * + * example: + * Lets assume we do have a pipeline: + * + * LL1 -> DP1 -> LL2 -> DP2 -> LL3 -> DP3 -> LL4 + * + * all LLs starts in 1ms tick + * + * for simplification lets assume + * - all LLs are on primary core, all DPs on secondary (100% CPU is for DP) + * - context switching requires 0 cycles + * + * DP1 - starts every 1ms, needs 0.5ms to finish processing + * DP2 - starts every 2ms, needs 0.6ms to finish processing + * DP3 - starts every 10ms, needs 0.3ms to finish processing + * + * TICK0 + * only LL1 is ready to run + * LL1 processing (producing data chunk for DP1) + * + * TICK1 + * LL1 is ready to run + * DP1 is ready tu run (has data from LL1) set deadline to TICK2 + * LL1 processing (producing second data chunk for DP1) + * DP1 processing for 0.5ms (consuming first data chunk, producing data chunk for LL2) + * CPU is idle for 0.5ms + * + * TICK2 + * LL1 is ready to run + * DP1 is ready tu run set deadline to TICK3 + * LL2 is ready to run + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing 50% data chunk for DP2) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * CPU is idle for 0.5ms + * + * TICK3 + * LL1 is ready to run + * DP1 is ready tu run set deadline to TICK4 + * LL2 is ready to run + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing rest of data chunk for DP2) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * CPU is idle for 0.5ms + * + * TICK4 + * LL1 is ready to run + * DP1 is ready tu run set deadline to TICK5 + * LL2 is ready to run + * DP2 is ready to run set deadline to TICK6 + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing 50% of second data chunk for DP2) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * DP2 processing for 0.5ms (no data produced as DP2 has 0.1ms to go) + * 100% CPU used + * + * !!!!!! Note here - DP1 must do before DP2 as it MUST finish in this tick. DP2 can wait + * >>>>>>> this is what we call EDF - EARIEST DEADLINE FIRST <<<<<< + * + * TICK5 + * LL1 is ready to run + * DP1 is ready tu run set deadline to TICK6 + * LL2 is ready to run + * DP2 is in progress, deadline is set to TICK6 + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing rest of second data chunk for DP2) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * DP2 processing for 0.1ms (producing TWO data chunks for LL3) + * CPU is idle for 0.4ms (60% used) + * + * TICK6 + * LL1 is ready to run + * DP1 is ready tu run set deadline to TICK7 + * LL2 is ready to run + * DP2 is ready to run set deadline to TICK8 + * LL3 is ready to run + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing 50% of second data chunk for DP2) + * LL3 processing (producing 10% of first data chunk for DP3) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * DP2 processing for 0.5ms (no data produced as DP2 has 0.1ms to go) + * 100% CPU used + * + * + * + * (........ 9 more cycles - LL3 procuces 100% of data for DP3......) + * + * + * TICK15 + * LL1 is ready to run + * DP1 is ready tu run set deadline to TICK16 + * LL2 is ready to run + * DP2 is ready to run set deadline to TICK17 + * LL3 is ready to run + * DP3 is ready to run set deadline to TICK25 + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing 50% of data chunk for DP2) + * LL3 processing (producing 10% of second data chunk for DP3) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * DP2 processing for 0.5ms (no data produced as DP2 has 0.1ms to go) + * 100% CPU used - + * !!! note that DP3 is ready but has no chance to get CPU in this cycle + * + * TICK16 + * LL1 is ready to run set deadline to TICK17 + * DP1 is ready tu run + * LL2 is ready to run + * DP2 is in progress, deadline is set to TICK17 + * LL3 is ready to run + * DP3 is in progress, deadline is set to TICK25 + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing rest of data chunk for DP2) + * LL3 processing (producing 10% of second data chunk for DP3) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * DP2 processing for 0.1ms (producing data) + * DP3 processing for 0.2ms (producing 10 data chunks for LL4) + * 90% CPU used + * + * TICK17 + * LL1 is ready to run + * DP1 is ready tu run + * LL2 is ready to run + * DP2 is ready to run + * LL3 is ready to run + * LL4 is ready to run + * !! NOTE that DP3 is not ready - it will be ready again in TICK25 + * LL1 processing (producing data chunk for DP1) + * LL2 processing (producing rest of data chunk for DP2) + * LL3 processing (producing next 10% of second data chunk for DP3) + * LL4 processing (consuming 10% of data prepared by DP3) + * DP1 processing for 0.5ms (producing data chunk for LL2) + * DP2 processing for 0.5ms (no data produced as DP2 has 0.1ms to go) + * 100% CPU used + * + * + * Now - pipeline is in stable state, CPU used almost in 100% (it would be 100% if DP3 + * needed 1.2ms for processing - but the example would be too complicated) + */ + +void scheduler_dp_ll_tick(void *receiver_data, enum notify_id event_type, void *caller_data) +{ + (void)receiver_data; + (void)event_type; + (void)caller_data; + unsigned int lock_key; + struct scheduler_dp_data *dp_sch = scheduler_get_data(SOF_SCHEDULE_DP); + + /* remember current timestamp as "NOW" */ + dp_sch->last_ll_tick_timestamp = k_cycle_get_32(); + + lock_key = scheduler_dp_lock(cpu_get_id()); + scheduler_dp_recalculate(dp_sch, event_type == NOTIFIER_ID_LL_POST_RUN); + scheduler_dp_unlock(lock_key); +} + +#if CONFIG_SOF_USERSPACE_APPLICATION +static int scheduler_dp_task_cancel(void *data, struct task *task) +{ + /* Should never be called */ + k_panic(); + return -EOPNOTSUPP; +} +#endif + +static int scheduler_dp_task_stop(void *data, struct task *task) +{ + unsigned int lock_key; + struct scheduler_dp_data *dp_sch = (struct scheduler_dp_data *)data; + struct task_dp_pdata *pdata = task->priv_data; + + /* this is asyn cancel - mark the task as canceled and remove it from scheduling */ + lock_key = scheduler_dp_lock(cpu_get_id()); + + task->state = SOF_TASK_STATE_CANCEL; + list_item_del(&task->list); + + /* if there're no more DP task, stop LL tick source */ + if (list_is_empty(&dp_sch->tasks)) + schedule_task_cancel(&dp_sch->ll_tick_src); + + /* if the task is waiting - let it run and self-terminate */ + k_event_set(pdata->event, DP_TASK_EVENT_CANCEL); + + scheduler_dp_unlock(lock_key); + + /* wait till the task has finished, if there was any task created */ + if (pdata->thread_id) + k_thread_join(pdata->thread_id, K_FOREVER); + + return 0; +} + +static int scheduler_dp_task_free(void *data, struct task *task) +{ + struct task_dp_pdata *pdata = task->priv_data; + int ret; + + scheduler_dp_task_stop(data, task); + + /* the thread should be terminated at this moment, + * abort is safe and will ensure no use after free + */ + if (pdata->thread_id) { + k_thread_abort(pdata->thread_id); + pdata->thread_id = NULL; + } + + /* free task stack */ + ret = user_stack_free(pdata->p_stack); + pdata->p_stack = NULL; + + scheduler_dp_internal_free(task); + + return ret; +} + +static int scheduler_dp_task_shedule(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + struct scheduler_dp_data *dp_sch = (struct scheduler_dp_data *)data; + struct task_dp_pdata *pdata = task->priv_data; + unsigned int lock_key; + + lock_key = scheduler_dp_lock(cpu_get_id()); + + if (task_is_active(task)) { + scheduler_dp_unlock(lock_key); + tr_dbg(&dp_tr, "DP task already active"); + return 0; + } + + if (task->state != SOF_TASK_STATE_INIT && + task->state != SOF_TASK_STATE_CANCEL && + task->state != SOF_TASK_STATE_COMPLETED) { + scheduler_dp_unlock(lock_key); + return -EINVAL; + } + + /* if there's no DP tasks scheduled yet, run ll tick source task */ + if (list_is_empty(&dp_sch->tasks)) + schedule_task(&dp_sch->ll_tick_src, 0, 0); + + /* add a task to DP scheduler list */ + task->state = SOF_TASK_STATE_QUEUED; + list_item_prepend(&task->list, &dp_sch->tasks); + + pdata->mod->dp_startup_delay = true; + scheduler_dp_unlock(lock_key); + + tr_dbg(&dp_tr, "DP task scheduled with period %u [us]", (uint32_t)period); + return 0; +} + +static struct scheduler_ops schedule_dp_ops = { + .schedule_task = scheduler_dp_task_shedule, +#if CONFIG_SOF_USERSPACE_APPLICATION + .schedule_task_cancel = scheduler_dp_task_cancel, +#else + .schedule_task_cancel = scheduler_dp_task_stop, +#endif + .schedule_task_free = scheduler_dp_task_free, +}; + +int scheduler_dp_init(void) +{ + int ret; + struct scheduler_dp_data *dp_sch = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct scheduler_dp_data)); + if (!dp_sch) + return -ENOMEM; + + list_init(&dp_sch->tasks); + + scheduler_init(SOF_SCHEDULE_DP, &schedule_dp_ops, dp_sch); + + /* init src of DP tick */ + ret = schedule_task_init_ll(&dp_sch->ll_tick_src, + SOF_UUID(dp_sched_uuid), + SOF_SCHEDULE_LL_TIMER, + 0, scheduler_dp_ll_tick_dummy, dp_sch, + cpu_get_id(), 0); + + if (ret) + return ret; + + notifier_register(NULL, NULL, NOTIFIER_ID_LL_POST_RUN, scheduler_dp_ll_tick, 0); + + return 0; +} + +void scheduler_get_task_info_dp(struct scheduler_props *scheduler_props, uint32_t *data_off_size) +{ + unsigned int lock_key; + + scheduler_props->processing_domain = COMP_PROCESSING_DOMAIN_DP; + struct scheduler_dp_data *dp_sch = + (struct scheduler_dp_data *)scheduler_get_data(SOF_SCHEDULE_DP); + + lock_key = scheduler_dp_lock(cpu_get_id()); + scheduler_get_task_info(scheduler_props, data_off_size, &dp_sch->tasks); + scheduler_dp_unlock(lock_key); +} diff --git a/src/schedule/zephyr_dp_schedule.h b/src/schedule/zephyr_dp_schedule.h new file mode 100644 index 000000000000..c4f37fc812f2 --- /dev/null +++ b/src/schedule/zephyr_dp_schedule.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Szkudlinski + */ + +#include <rtos/task.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/list.h> +#include <sof/compiler_attributes.h> + +#include <zephyr/app_memory/mem_domain.h> + +#include <stdbool.h> +#include <stdint.h> + +struct scheduler_dp_data { + struct list_item tasks; /* list of active dp tasks */ + struct task ll_tick_src; /* LL task - source of DP tick */ + uint32_t last_ll_tick_timestamp;/* a timestamp as k_cycle_get_32 of last LL tick, + * "NOW" for DP deadline calculation + */ +}; + +enum sof_dp_part_type { + SOF_DP_PART_HEAP, + SOF_DP_PART_HEAP_CACHE, + SOF_DP_PART_CFG, + SOF_DP_PART_CFG_CACHE, + SOF_DP_PART_TYPE_COUNT, +}; + +struct ipc4_flat; + +struct task_dp_pdata { + k_tid_t thread_id; /* zephyr thread ID */ + struct k_thread *thread; /* pointer to the kernels' thread object */ + struct k_thread thread_struct; /* thread object for kernel threads */ + uint32_t deadline_clock_ticks; /* dp module deadline in Zephyr ticks */ + k_thread_stack_t *p_stack; /* pointer to thread stack */ + struct processing_module *mod; /* the module to be scheduled */ + uint32_t ll_cycles_to_start; /* current number of LL cycles till delayed start */ +#if CONFIG_SOF_USERSPACE_APPLICATION + struct ipc4_flat *flat; + struct k_mem_partition mpart[SOF_DP_PART_TYPE_COUNT]; +#endif + struct k_event *event; /* pointer to event for task scheduling */ + struct k_event event_struct; /* event for task scheduling for kernel threads */ +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + struct k_work_user *ipc_work_item; /* work item for IPC handling */ +#endif +}; + +void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run); +void dp_thread_fn(void *p1, void *p2, void *p3); +unsigned int scheduler_dp_lock(uint16_t core); +void scheduler_dp_unlock(unsigned int key); +void scheduler_dp_grant(k_tid_t thread_id, uint16_t core); +int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, + const struct task_ops *ops, struct processing_module *mod, + uint16_t core, size_t stack_size, uint32_t options); +void scheduler_dp_internal_free(struct task *task); diff --git a/src/schedule/zephyr_dp_schedule_application.c b/src/schedule/zephyr_dp_schedule_application.c new file mode 100644 index 000000000000..06f2d7b46b12 --- /dev/null +++ b/src/schedule/zephyr_dp_schedule_application.c @@ -0,0 +1,600 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Marcin Szkudlinski + */ + +#include <rtos/task.h> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/llext_manager.h> +#include <sof/objpool.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> + +#include <zephyr/app_memory/mem_domain.h> +#include <zephyr/kernel.h> +#include <zephyr/logging/log.h> +#include <zephyr/sys/slist.h> + +#include <stdbool.h> +#include <stdint.h> + +#include "zephyr_dp_schedule.h" + +LOG_MODULE_DECLARE(dp_schedule, CONFIG_SOF_LOG_LEVEL); +extern struct tr_ctx dp_tr; + +static struct objpool_head dp_mdom_head = {.list = LIST_INIT(dp_mdom_head.list)}; + +/* Synchronization semaphore for the scheduler thread to wait for DP startup */ +#define DP_SYNC_INIT(i, _) Z_SEM_INITIALIZER(dp_sync[i], 0, 1) +#define DP_SYNC_INIT_LIST LISTIFY(CONFIG_CORE_COUNT, DP_SYNC_INIT, (,)) +static STRUCT_SECTION_ITERABLE_ARRAY(k_sem, dp_sync, CONFIG_CORE_COUNT) = { DP_SYNC_INIT_LIST }; + +struct ipc4_flat { + unsigned int cmd; + int ret; + union { + struct { + struct ipc4_module_bind_unbind bu; + enum bind_type type; + } bind; + struct { + unsigned int trigger_cmd; + enum ipc4_pipeline_state state; + int n_sources; + int n_sinks; + struct sof_source *source[CONFIG_MODULE_MAX_CONNECTIONS]; + struct sof_sink *sink[CONFIG_MODULE_MAX_CONNECTIONS]; + } pipeline_state; + }; +}; + +/* Pack IPC input data */ +static int ipc_thread_flatten(unsigned int cmd, const union scheduler_dp_thread_ipc_param *param, + struct ipc4_flat *flat) +{ + flat->cmd = cmd; + + /* + * FIXME: SOF_IPC4_MOD_* and SOF_IPC4_GLB_* aren't fully orthogonal, but + * so far none of the used ones overlap + */ + switch (cmd) { + case SOF_IPC4_MOD_BIND: + case SOF_IPC4_MOD_UNBIND: + flat->bind.bu = *param->bind_data->ipc4_data; + flat->bind.type = param->bind_data->bind_type; + break; + case SOF_IPC4_GLB_SET_PIPELINE_STATE: + flat->pipeline_state.trigger_cmd = param->pipeline_state.trigger_cmd; + switch (param->pipeline_state.trigger_cmd) { + case COMP_TRIGGER_STOP: + break; + case COMP_TRIGGER_PREPARE: + if (param->pipeline_state.n_sources > CONFIG_MODULE_MAX_CONNECTIONS || + param->pipeline_state.n_sinks > CONFIG_MODULE_MAX_CONNECTIONS) + return -ENOMEM; + + flat->pipeline_state.state = param->pipeline_state.state; + flat->pipeline_state.n_sources = param->pipeline_state.n_sources; + flat->pipeline_state.n_sinks = param->pipeline_state.n_sinks; + /* Up to 2 * CONFIG_MODULE_MAX_CONNECTIONS */ + memcpy(flat->pipeline_state.source, param->pipeline_state.sources, + flat->pipeline_state.n_sources * + sizeof(flat->pipeline_state.source[0])); + memcpy(flat->pipeline_state.sink, param->pipeline_state.sinks, + flat->pipeline_state.n_sinks * + sizeof(flat->pipeline_state.sink[0])); + } + } + + return 0; +} + +/* Unpack IPC data and execute a callback */ +static void ipc_thread_unflatten_run(struct processing_module *pmod, struct ipc4_flat *flat) +{ + const struct module_interface *const ops = pmod->dev->drv->adapter_ops; + + switch (flat->cmd) { + case SOF_IPC4_MOD_BIND: + if (ops->bind) { + struct bind_info bind_data = { + .ipc4_data = &flat->bind.bu, + .bind_type = flat->bind.type, + }; + + flat->ret = ops->bind(pmod, &bind_data); + } else { + flat->ret = 0; + } + break; + case SOF_IPC4_MOD_UNBIND: + if (ops->unbind) { + struct bind_info bind_data = { + .ipc4_data = &flat->bind.bu, + .bind_type = flat->bind.type, + }; + + flat->ret = ops->unbind(pmod, &bind_data); + } else { + flat->ret = 0; + } + break; + case SOF_IPC4_MOD_DELETE_INSTANCE: + flat->ret = ops->free(pmod); + break; + case SOF_IPC4_MOD_INIT_INSTANCE: + flat->ret = ops->init(pmod); + break; + case SOF_IPC4_GLB_SET_PIPELINE_STATE: + switch (flat->pipeline_state.trigger_cmd) { + case COMP_TRIGGER_STOP: + flat->ret = ops->reset(pmod); + break; + case COMP_TRIGGER_PREPARE: + flat->ret = ops->prepare(pmod, + flat->pipeline_state.source, + flat->pipeline_state.n_sources, + flat->pipeline_state.sink, + flat->pipeline_state.n_sinks); + } + } +} + +#define DP_THREAD_IPC_TIMEOUT K_MSEC(100) + +/* Signal an IPC and wait for processing completion */ +int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd, + const union scheduler_dp_thread_ipc_param *param) +{ + struct task_dp_pdata *pdata = pmod->dev->task->priv_data; + int ret; + + if (!pmod) { + tr_err(&dp_tr, "no thread module"); + return -EINVAL; + } + + if (cmd == SOF_IPC4_MOD_INIT_INSTANCE) { + /* Wait for the DP thread to start */ + ret = k_sem_take(&dp_sync[pmod->dev->task->core], DP_THREAD_IPC_TIMEOUT); + if (ret < 0) { + tr_err(&dp_tr, "Failed waiting for DP thread to start: %d", ret); + return ret; + } + } + + unsigned int lock_key = scheduler_dp_lock(pmod->dev->task->core); + + /* IPCs are serialised */ + pdata->flat->ret = -ENOSYS; + + ret = ipc_thread_flatten(cmd, param, pdata->flat); + if (!ret) + k_event_post(pdata->event, DP_TASK_EVENT_IPC); + + scheduler_dp_unlock(lock_key); + + if (!ret) { + /* Wait for completion */ + ret = k_sem_take(&dp_sync[cpu_get_id()], DP_THREAD_IPC_TIMEOUT); + if (ret < 0) + tr_err(&dp_tr, "Failed waiting for DP thread: %d", ret); + else + ret = pdata->flat->ret; + } + + return ret; +} + +/* Go through all DP tasks and recalculate their readiness and deadlines + * NOT REENTRANT, called with scheduler_dp_lock() held + */ +void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run) +{ + struct list_item *tlist; + struct task *curr_task; + struct task_dp_pdata *pdata; + + list_for_item(tlist, &dp_sch->tasks) { + curr_task = container_of(tlist, struct task, list); + pdata = curr_task->priv_data; + struct processing_module *mod = pdata->mod; + bool trigger_task = false; + + /* decrease number of LL ticks/cycles left till the module reaches its deadline */ + if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) { + pdata->ll_cycles_to_start--; + if (!pdata->ll_cycles_to_start) + /* delayed start complete, clear startup delay flag. + * see dp_startup_delay comment for details + */ + mod->dp_startup_delay = false; + } + + if (curr_task->state == SOF_TASK_STATE_QUEUED && + mod->dev->state >= COMP_STATE_ACTIVE) { + /* trigger the task */ + curr_task->state = SOF_TASK_STATE_RUNNING; + trigger_task = true; + k_event_post(pdata->event, DP_TASK_EVENT_PROCESS); + } + + if (curr_task->state == SOF_TASK_STATE_RUNNING) { + /* (re) calculate deadline for all running tasks */ + /* get module deadline in us */ + uint32_t deadline = module_get_deadline(mod); + + /* if a deadline cannot be calculated, use a fixed value relative to its + * first start + */ + if (deadline >= UINT32_MAX / 2 && trigger_task) + deadline = module_get_lpt(mod); + + if (deadline < UINT32_MAX) { + /* round down to 1ms */ + deadline = deadline / 1000; + + /* calculate number of ticks */ + deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000); + + /* add to "NOW", overflows are OK */ + deadline = dp_sch->last_ll_tick_timestamp + deadline; + + /* set in Zephyr. Note that it may be in past, it does not matter, + * Zephyr still will schedule the thread with earlier deadline + * first + */ + k_thread_absolute_deadline_set(pdata->thread_id, deadline); + } + } + } +} + +/* Thread function called in component context, on target core */ +void dp_thread_fn(void *p1, void *p2, void *p3) +{ + struct task *task = p1; + struct task_dp_pdata *task_pdata = task->priv_data; + struct processing_module *pmod = task_pdata->mod; + unsigned int lock_key; + enum task_state state; + bool task_stop; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + /* The IPC thread is waiting for the thread to be started, it can proceed now. */ + k_sem_give(&dp_sync[task->core]); + comp_info(pmod->dev, "userspace thread started"); + + do { + uint32_t mask = k_event_wait_safe(task_pdata->event, + DP_TASK_EVENT_PROCESS | DP_TASK_EVENT_CANCEL | + DP_TASK_EVENT_IPC, false, K_FOREVER); + + if (mask & DP_TASK_EVENT_IPC) { + /* handle IPC */ + tr_dbg(&dp_tr, "got IPC wake up for %p state %d", pmod, task->state); + ipc_thread_unflatten_run(pmod, task_pdata->flat); + k_sem_give(&dp_sync[task->core]); + } + + if (mask & DP_TASK_EVENT_PROCESS) { + bool ready; + + if (task->state == SOF_TASK_STATE_RUNNING) { + ready = module_is_ready_to_process(pmod, pmod->sources, + pmod->num_of_sources, + pmod->sinks, pmod->num_of_sinks); + } else { + state = task->state; /* to avoid undefined variable warning */ + ready = false; + } + + if (ready) { + if (pmod->dp_startup_delay && !task_pdata->ll_cycles_to_start) { + /* first time run - use delayed start */ + task_pdata->ll_cycles_to_start = + module_get_lpt(pmod) / LL_TIMER_PERIOD_US; + + /* in case LPT < LL cycle - delay at least cycle */ + if (!task_pdata->ll_cycles_to_start) + task_pdata->ll_cycles_to_start = 1; + } + + state = task_run(task); + } + + lock_key = scheduler_dp_lock(task->core); + /* + * check if task is still running, may have been canceled by external call + * if not, set the state returned by run procedure + */ + if (ready && task->state == SOF_TASK_STATE_RUNNING) { + task->state = state; + switch (state) { + case SOF_TASK_STATE_RESCHEDULE: + /* mark to reschedule, schedule time is already calculated */ + task->state = SOF_TASK_STATE_QUEUED; + break; + + case SOF_TASK_STATE_CANCEL: + case SOF_TASK_STATE_COMPLETED: + /* task already removed from scheduling */ + break; + + default: + /* illegal state, serious defect, won't happen */ + k_oops(); + } + } else { + task->state = SOF_TASK_STATE_QUEUED; + } + } else { + lock_key = scheduler_dp_lock(task->core); + } + + /* if true exit the while loop, terminate the thread */ + task_stop = task->state == SOF_TASK_STATE_COMPLETED || + task->state == SOF_TASK_STATE_CANCEL; + + scheduler_dp_unlock(lock_key); + } while (!task_stop); + + /* call task_complete */ + if (task->state == SOF_TASK_STATE_COMPLETED) + task_complete(task); +} + +/* + * Safe to call with partial successful initialisation, + * k_mem_domain_remove_partition() then just returns -ENOENT + */ +static void scheduler_dp_domain_free(struct task_dp_pdata *pdata) +{ + struct processing_module *pmod = pdata->mod; + struct k_mem_domain *mdom = pmod->mdom; + + llext_manager_rm_domain(pmod->dev->ipc_config.id, mdom); + + k_mem_domain_remove_partition(mdom, pdata->mpart + SOF_DP_PART_HEAP); + k_mem_domain_remove_partition(mdom, pdata->mpart + SOF_DP_PART_HEAP_CACHE); + k_mem_domain_remove_partition(mdom, pdata->mpart + SOF_DP_PART_CFG); + k_mem_domain_remove_partition(mdom, pdata->mpart + SOF_DP_PART_CFG_CACHE); + + if (mdom->num_partitions) { + /* Violation: all partitions should be freed by now */ + unsigned int n = mdom->num_partitions; + + LOG_WRN("%u domain partition(s) not freed, force-freeing them all", n); + + for (unsigned int i = 0; i < arch_mem_domain_max_partitions_get() && n; i++) { + struct k_mem_partition *dpart = &mdom->partitions[i]; + + if (dpart->size) { + k_mem_domain_remove_partition(mdom, dpart); + n--; + } + } + } + + /* All partitions removed, the domain can be freed now */ + pmod->mdom = NULL; + k_mem_domain_deinit(mdom); + objpool_free(&dp_mdom_head, mdom); +} + +/* memory allocation helper structure */ +struct scheduler_dp_task_memory { + struct task task; + struct task_dp_pdata pdata; + struct comp_driver drv; + struct ipc4_flat flat; +}; + +void scheduler_dp_internal_free(struct task *task) +{ + struct task_dp_pdata *pdata = task->priv_data; + + k_object_free(pdata->event); + k_object_free(pdata->thread); + scheduler_dp_domain_free(pdata); + + mod_free(pdata->mod, container_of(task, struct scheduler_dp_task_memory, task)); +} + +/* Called only in IPC context */ +int scheduler_dp_task_init(struct task **task, const struct sof_uuid_entry *uid, + const struct task_ops *ops, struct processing_module *mod, + uint16_t core, size_t stack_size, uint32_t options) +{ + k_thread_stack_t *p_stack; + struct scheduler_dp_task_memory *task_memory; + + int ret; + + /* must be called on the same core the task will be bound to */ + assert(cpu_get_id() == core); + + /* + * allocate memory + * to avoid multiple malloc operations allocate all required memory as a single structure + * and return pointer to task_memory->task + * As the structure contains zephyr kernel specific data, it must be located in + * shared, non cached memory + */ + task_memory = mod_alloc_ext(mod, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*task_memory), 0); + if (!task_memory) { + tr_err(&dp_tr, "memory alloc failed"); + return -ENOMEM; + } + + memset(task_memory, 0, sizeof(*task_memory)); + + task_memory->drv = *mod->dev->drv; + mod->dev->drv = &task_memory->drv; + + /* allocate stack - must be aligned and cached so a separate alloc */ + p_stack = user_stack_allocate(stack_size, options); + if (!p_stack) { + tr_err(&dp_tr, "stack alloc failed"); + ret = -ENOMEM; + goto e_tmem; + } + + struct task *ptask = &task_memory->task; + + /* internal SOF task init */ + ret = schedule_task_init(ptask, uid, SOF_SCHEDULE_DP, 0, ops->run, mod, core, options); + if (ret < 0) { + tr_err(&dp_tr, "schedule_task_init failed"); + goto e_stack; + } + + struct task_dp_pdata *pdata = &task_memory->pdata; + + pdata->flat = &task_memory->flat; + + pdata->event = k_object_alloc(K_OBJ_EVENT); + if (!pdata->event) { + tr_err(&dp_tr, "Event object allocation failed"); + ret = -ENOMEM; + goto e_stack; + } + + pdata->thread = k_object_alloc(K_OBJ_THREAD); + if (!pdata->thread) { + tr_err(&dp_tr, "Thread object allocation failed"); + ret = -ENOMEM; + goto e_kobj; + } + memset(&pdata->thread->arch, 0, sizeof(pdata->thread->arch)); + + /* success, fill the structures */ + pdata->p_stack = p_stack; + pdata->mod = mod; + + /* initialize other task structures */ + ptask->ops.complete = ops->complete; + ptask->ops.get_deadline = ops->get_deadline; + ptask->priv_data = pdata; + list_init(&ptask->list); + *task = ptask; + + /* create a zephyr thread for the task */ + pdata->thread_id = k_thread_create(pdata->thread, p_stack, + stack_size, dp_thread_fn, ptask, NULL, NULL, + CONFIG_DP_THREAD_PRIORITY, ptask->flags, K_FOREVER); + +#ifdef CONFIG_SCHED_CPU_MASK + /* pin the thread to specific core */ + ret = k_thread_cpu_pin(pdata->thread_id, core); + if (ret < 0) { + tr_err(&dp_tr, "zephyr task pin to core failed"); + goto e_thread; + } +#endif + + k_thread_access_grant(pdata->thread_id, pdata->event, &dp_sync[core]); + scheduler_dp_grant(pdata->thread_id, core); + + unsigned int pidx; + size_t size; + uintptr_t start; + bool on_pool = false; + struct k_mem_domain *mdom = objpool_alloc(&dp_mdom_head, sizeof(*mdom), + SOF_MEM_FLAG_COHERENT); + + if (!mdom) { + tr_err(&dp_tr, "objpool allocation failed"); + ret = -ENOMEM; + goto e_thread; + } + + on_pool = true; + + mod->mdom = mdom; + + if (!mdom->arch.ptables) { + ret = k_mem_domain_init(mdom, 0, NULL); + if (ret < 0) + goto e_thread; + } + + /* Module heap partition */ + mod_heap_info(mod, &size, &start); + pdata->mpart[SOF_DP_PART_HEAP] = (struct k_mem_partition){ + .start = (uintptr_t)sys_cache_uncached_ptr_get((void *)start), + .size = size, + .attr = K_MEM_PARTITION_P_RW_U_RW, + }; + pdata->mpart[SOF_DP_PART_HEAP_CACHE] = (struct k_mem_partition){ + .start = start, + .size = size, + .attr = K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB, + }; + /* Host mailbox partition for additional IPC parameters: read-only */ + pdata->mpart[SOF_DP_PART_CFG] = (struct k_mem_partition){ + .start = (uintptr_t)sys_cache_uncached_ptr_get((void *)MAILBOX_HOSTBOX_BASE), + .size = 4096, + .attr = K_MEM_PARTITION_P_RO_U_RO, + }; + pdata->mpart[SOF_DP_PART_CFG_CACHE] = (struct k_mem_partition){ + .start = (uintptr_t)MAILBOX_HOSTBOX_BASE, + .size = 4096, + .attr = K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB, + }; + + for (pidx = 0; pidx < SOF_DP_PART_TYPE_COUNT; pidx++) { + ret = k_mem_domain_add_partition(mdom, pdata->mpart + pidx); + if (ret < 0) + goto e_dom; + } + + ret = llext_manager_add_domain(mod->dev->ipc_config.id, mdom); + if (ret < 0) { + tr_err(&dp_tr, "failed to add LLEXT to domain %d", ret); + goto e_dom; + } + + /* + * Keep this call last, able to fail, otherwise domain will be removed + * before its thread + */ + ret = k_mem_domain_add_thread(mdom, pdata->thread_id); + if (ret < 0) { + tr_err(&dp_tr, "failed to add thread to domain %d", ret); + goto e_dom; + } + + /* start the thread, it should immediately stop at the semaphore */ + k_event_init(pdata->event); + k_thread_start(pdata->thread_id); + + return 0; + +e_dom: + scheduler_dp_domain_free(pdata); + on_pool = false; +e_thread: + if (on_pool) + objpool_free(&dp_mdom_head, mdom); + k_thread_abort(pdata->thread_id); +e_kobj: + /* k_object_free looks for a pointer in the list, any invalid value can be passed */ + k_object_free(pdata->thread); + k_object_free(pdata->event); +e_stack: + user_stack_free(p_stack); +e_tmem: + mod_free(mod, task_memory); + return ret; +} diff --git a/src/schedule/zephyr_dp_schedule_thread.c b/src/schedule/zephyr_dp_schedule_thread.c new file mode 100644 index 000000000000..7fbb3b6a5c21 --- /dev/null +++ b/src/schedule/zephyr_dp_schedule_thread.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Marcin Szkudlinski + * Adrian Warecki + */ + +#include <rtos/task.h> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/library/userspace_proxy.h> +#include <sof/audio/module_adapter/library/userspace_proxy_user.h> +#include <sof/common.h> +#include <sof/list.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/dp_schedule.h> +#include <sof/trace/trace.h> + +#include <zephyr/kernel.h> + +#include <stdbool.h> +#include <stdint.h> + +#include "zephyr_dp_schedule.h" + +LOG_MODULE_DECLARE(dp_schedule, CONFIG_SOF_LOG_LEVEL); +extern struct tr_ctx dp_tr; + +/* Go through all DP tasks and recalculate their readiness and deadlines + * NOT REENTRANT, should be called with scheduler_dp_lock() + */ +void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch, bool is_ll_post_run) +{ + struct list_item *tlist; + struct task *curr_task; + struct task_dp_pdata *pdata; + + list_for_item(tlist, &dp_sch->tasks) { + curr_task = container_of(tlist, struct task, list); + pdata = curr_task->priv_data; + struct processing_module *mod = pdata->mod; + bool trigger_task = false; + + /* decrease number of LL ticks/cycles left till the module reaches its deadline */ + if (mod->dp_startup_delay && is_ll_post_run && pdata->ll_cycles_to_start) { + pdata->ll_cycles_to_start--; + if (!pdata->ll_cycles_to_start) + /* delayed start complete, clear startup delay flag. + * see dp_startup_delay comment for details + */ + mod->dp_startup_delay = false; + } + + if (curr_task->state == SOF_TASK_STATE_QUEUED) { + bool mod_ready; + + mod_ready = module_is_ready_to_process(mod, mod->sources, + mod->num_of_sources, + mod->sinks, + mod->num_of_sinks); + if (mod_ready) { + /* trigger the task */ + curr_task->state = SOF_TASK_STATE_RUNNING; + if (mod->dp_startup_delay && !pdata->ll_cycles_to_start) { + /* first time run - use delayed start */ + pdata->ll_cycles_to_start = + module_get_lpt(pdata->mod) / LL_TIMER_PERIOD_US; + + /* in case LPT < LL cycle - delay at least cycle */ + if (!pdata->ll_cycles_to_start) + pdata->ll_cycles_to_start = 1; + } + trigger_task = true; + k_event_post(pdata->event, DP_TASK_EVENT_PROCESS); + } + } + if (curr_task->state == SOF_TASK_STATE_RUNNING) { + /* (re) calculate deadline for all running tasks */ + /* get module deadline in us*/ + uint32_t deadline = module_get_deadline(mod); + + /* if a deadline cannot be calculated, use a fixed value relative to its + * first start + */ + if (deadline >= UINT32_MAX / 2 && trigger_task) + deadline = module_get_lpt(mod); + + if (deadline < UINT32_MAX) { + /* round down to 1ms */ + deadline = deadline / 1000; + + /* calculate number of ticks */ + deadline = deadline * (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000); + + /* add to "NOW", overflows are OK */ + deadline = dp_sch->last_ll_tick_timestamp + deadline; + + /* set in Zephyr. Note that it may be in past, it does not matter, + * Zephyr still will schedule the thread with earlier deadline + * first + */ + k_thread_absolute_deadline_set(pdata->thread_id, deadline); + } + } + } +} + +/* Thread function called in component context, on target core */ +void dp_thread_fn(void *p1, void *p2, void *p3) +{ + struct task *task = p1; + (void)p2; + (void)p3; + struct task_dp_pdata *task_pdata = task->priv_data; + struct scheduler_dp_data *dp_sch = NULL; + unsigned int lock_key; + enum task_state state; + bool task_stop = false; + uint32_t event; + + if (!(task->flags & K_USER)) + dp_sch = scheduler_get_data(SOF_SCHEDULE_DP); + + do { + /* + * the thread is started immediately after creation, it will stop on event. + * Event will be signalled once the task is ready to process. + */ + event = k_event_wait_safe(task_pdata->event, DP_TASK_EVENT_PROCESS | + DP_TASK_EVENT_CANCEL | DP_TASK_EVENT_IPC, false, + K_FOREVER); + +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + if (event & DP_TASK_EVENT_IPC) { + assert(task_pdata->ipc_work_item); + userspace_proxy_worker_handler(task_pdata->ipc_work_item); + } +#endif + + if (event & DP_TASK_EVENT_PROCESS) { + state = task->state; /* to avoid undefined variable warning */ + if (task->state == SOF_TASK_STATE_RUNNING && event & DP_TASK_EVENT_PROCESS) + state = task_run(task); + + lock_key = scheduler_dp_lock(task->core); + /* + * check if task is still running, may have been canceled by external call + * if not, set the state returned by run procedure + */ + if (task->state == SOF_TASK_STATE_RUNNING) { + task->state = state; + switch (state) { + case SOF_TASK_STATE_RESCHEDULE: + /* mark to reschedule, schedule time is already calculated + */ + task->state = SOF_TASK_STATE_QUEUED; + break; + + case SOF_TASK_STATE_CANCEL: + case SOF_TASK_STATE_COMPLETED: + /* remove from scheduling */ + list_item_del(&task->list); + break; + + default: + /* illegal state, serious defect, won't happen */ + k_panic(); + } + } + + /* if true exit the while loop, terminate the thread */ + task_stop = task->state == SOF_TASK_STATE_COMPLETED || + task->state == SOF_TASK_STATE_CANCEL; + /* recalculate all DP tasks readiness and deadlines + * TODO: it should be for all tasks, for all cores + * currently its limited to current core only + */ + if (dp_sch) + scheduler_dp_recalculate(dp_sch, false); + + scheduler_dp_unlock(lock_key); + } + + if (event & DP_TASK_EVENT_CANCEL) + task_stop = true; + } while (!task_stop); + + /* call task_complete */ + if (task->state == SOF_TASK_STATE_COMPLETED) + task_complete(task); +} + +int scheduler_dp_task_init(struct task **task, + const struct sof_uuid_entry *uid, + const struct task_ops *ops, + struct processing_module *mod, + uint16_t core, + size_t stack_size, + uint32_t options) +{ + void __sparse_cache *p_stack = NULL; + struct k_heap *const user_heap = mod->dev->drv->user_heap; + + /* memory allocation helper structure */ + struct { + struct task task; /* keep first, used for freeing below */ + struct task_dp_pdata pdata; + } *task_memory; + + int ret; + + /* must be called on the same core the task will be binded to */ + assert(cpu_get_id() == core); + + /* + * allocate memory + * to avoid multiple malloc operations allocate all required memory as a single structure + * and return pointer to task_memory->task + * As the structure contains zephyr kernel specific data, it must be located in + * shared, non cached memory + */ + task_memory = sof_heap_alloc(user_heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*task_memory), 0); + if (!task_memory) { + tr_err(&dp_tr, "memory alloc failed"); + return -ENOMEM; + } + + memset(task_memory, 0, sizeof(*task_memory)); + /* allocate stack - must be aligned and cached so a separate alloc */ + p_stack = user_stack_allocate(stack_size, options); + if (!p_stack) { + tr_err(&dp_tr, "stack alloc failed"); + ret = -ENOMEM; + goto err; + } + + /* internal SOF task init */ + ret = schedule_task_init(&task_memory->task, uid, SOF_SCHEDULE_DP, 0, ops->run, + mod, core, options); + if (ret < 0) { + tr_err(&dp_tr, "schedule_task_init failed"); + goto err; + } + + struct task_dp_pdata *pdata = &task_memory->pdata; + + /* Point to event_struct event for kernel threads synchronization */ + /* It will be overwritten for K_USER threads to dynamic ones. */ + pdata->event = &pdata->event_struct; + pdata->thread = &pdata->thread_struct; + +#ifdef CONFIG_USERSPACE + if (options & K_USER) { + pdata->event = k_object_alloc(K_OBJ_EVENT); + if (!pdata->event) { + tr_err(&dp_tr, "Event object allocation failed"); + ret = -ENOMEM; + goto err; + } + + pdata->thread = k_object_alloc(K_OBJ_THREAD); + if (!pdata->thread) { + tr_err(&dp_tr, "Thread object allocation failed"); + ret = -ENOMEM; + goto err; + } + } +#endif /* CONFIG_USERSPACE */ + + /* initialize other task structures */ + task_memory->task.ops.complete = ops->complete; + task_memory->task.ops.get_deadline = ops->get_deadline; + task_memory->task.state = SOF_TASK_STATE_INIT; + task_memory->task.core = core; + task_memory->task.priv_data = pdata; + k_event_init(pdata->event); + + /* success, fill the structures */ + pdata->p_stack = p_stack; + pdata->mod = mod; + + /* create a zephyr thread for the task */ + pdata->thread_id = k_thread_create(pdata->thread, (__sparse_force void *)p_stack, + stack_size, dp_thread_fn, &task_memory->task, NULL, NULL, + CONFIG_DP_THREAD_PRIORITY, task_memory->task.flags, + K_FOREVER); + +#ifdef CONFIG_SCHED_CPU_MASK + /* pin the thread to specific core */ + ret = k_thread_cpu_pin(pdata->thread_id, core); + if (ret < 0) { + tr_err(&dp_tr, "zephyr task pin to core failed"); + goto e_thread; + } +#endif + +#ifdef CONFIG_USERSPACE + if (options & K_USER) { + k_thread_access_grant(pdata->thread_id, pdata->event); + scheduler_dp_grant(pdata->thread_id, core); + + ret = k_mem_domain_add_thread(pdata->mod->user_ctx->comp_dom, pdata->thread_id); + if (ret < 0) { + tr_err(&dp_tr, "k_mem_domain_add_thread() failed %d", ret); + goto e_thread; + } + +#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD) + pdata->ipc_work_item = userspace_proxy_register_ipc_handler(mod, pdata->event); + assert(pdata->ipc_work_item); +#endif + } +#endif /* CONFIG_USERSPACE */ + + /* start the thread, it should immediately stop at an event */ + k_thread_start(pdata->thread_id); + + /* success, fill output parameter */ + *task = &task_memory->task; + return 0; + +e_thread: + k_thread_abort(pdata->thread_id); +err: + /* cleanup - free all allocated resources */ + if (user_stack_free((__sparse_force void *)p_stack)) + tr_err(&dp_tr, "user_stack_free failed!"); + + /* k_object_free looks for a pointer in the list, any invalid value can be passed */ + k_object_free(task_memory->pdata.event); + k_object_free(task_memory->pdata.thread); + sof_heap_free(user_heap, task_memory); + return ret; +} + +void scheduler_dp_internal_free(struct task *task) +{ + struct task_dp_pdata *pdata = task->priv_data; + +#ifdef CONFIG_USERSPACE + if (pdata->event != &pdata->event_struct) + k_object_free(pdata->event); + if (pdata->thread != &pdata->thread_struct) + k_object_free(pdata->thread); +#endif + + /* task is the first member in task_memory above */ + sof_heap_free(pdata->mod->dev->drv->user_heap, task); +} diff --git a/src/schedule/zephyr_ll.c b/src/schedule/zephyr_ll.c new file mode 100644 index 000000000000..575a82d91dda --- /dev/null +++ b/src/schedule/zephyr_ll.c @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> + +#include <sof/list.h> +#include <rtos/spinlock.h> +#include <rtos/symbol.h> +#include <sof/audio/component.h> +#include <rtos/interrupt.h> +#include <sof/lib/notifier.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/schedule.h> +#include <rtos/task.h> +#include <sof/lib/perf_cnt.h> +#include <zephyr/kernel.h> +#include <ipc4/base_fw.h> +#include <sof/debug/telemetry/telemetry.h> + +LOG_MODULE_REGISTER(ll_schedule, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(zll_sched); + +DECLARE_TR_CTX(ll_tr, SOF_UUID(zll_sched_uuid), LOG_LEVEL_INFO); + +/* per-scheduler data */ +struct zephyr_ll { + struct list_item tasks; /* list of ll tasks */ + unsigned int n_tasks; /* task counter */ + struct ll_schedule_domain *ll_domain; /* scheduling domain */ + unsigned int core; /* core ID of this instance */ +#if CONFIG_SOF_USERSPACE_LL + struct k_mutex *lock; /* mutex for userspace */ +#endif + struct k_heap *heap; +}; + +/* per-task scheduler data */ +struct zephyr_ll_pdata { + bool run; + bool freeing; + struct k_sem sem; +}; + +static void zephyr_ll_lock(struct zephyr_ll *sch, uint32_t *flags) +{ +#if CONFIG_SOF_USERSPACE_LL + k_mutex_lock(sch->lock, K_FOREVER); +#else + irq_local_disable(*flags); +#endif +} + +static void zephyr_ll_unlock(struct zephyr_ll *sch, uint32_t *flags) +{ +#if CONFIG_SOF_USERSPACE_LL + k_mutex_unlock(sch->lock); +#else + irq_local_enable(*flags); +#endif +} + +static void zephyr_ll_assert_core(const struct zephyr_ll *sch) +{ + assert(CONFIG_CORE_COUNT == 1 || IS_ENABLED(CONFIG_SOF_USERSPACE_LL) || + sch->core == cpu_get_id()); +} + +/* Locking: caller should hold the domain lock */ +static void zephyr_ll_task_done(struct zephyr_ll *sch, + struct task *task) +{ + struct zephyr_ll_pdata *pdata = task->priv_data; + + list_item_del(&task->list); + + if (!sch->n_tasks) { + tr_info(&ll_tr, "task count underrun!"); + k_panic(); + } + + task->state = SOF_TASK_STATE_FREE; + + if (pdata->freeing) + /* + * zephyr_ll_task_free() is trying to free this task. Complete + * it and signal the semaphore to let the function proceed + */ + k_sem_give(&pdata->sem); + + tr_info(&ll_tr, "task complete %p %pU", task, task->uid); + tr_info(&ll_tr, "num_tasks %d total_num_tasks %ld", + sch->n_tasks, atomic_read(&sch->ll_domain->total_num_tasks)); + + /* + * If this is the last task, domain_unregister() won't return. It is + * important to decrement the task counter last before aborting the + * thread. + */ + domain_unregister(sch->ll_domain, task, --sch->n_tasks); +} + +/* The caller must hold the lock and possibly disable interrupts */ +static void zephyr_ll_task_insert_unlocked(struct zephyr_ll *sch, struct task *task) +{ + struct task *task_iter; + struct list_item *list; + + task->state = SOF_TASK_STATE_QUEUED; + + /* + * Tasks are added into the list in priority order. List order + * defines schedule order. Priority 0 indicates highest + * priority and is run first. Tasks with the same priority are + * served on a first-come-first-served basis. + */ + list_for_item(list, &sch->tasks) { + task_iter = container_of(list, struct task, list); + if (task->priority < task_iter->priority) { + list_item_append(&task->list, &task_iter->list); + break; + } + } + + /* + * If the task has not been added, it means that it has the lowest + * priority and should be added at the end of the list + */ + if (list == &sch->tasks) + list_item_append(&task->list, &sch->tasks); +} + +static void zephyr_ll_task_insert_before_unlocked(struct task *task, struct task *before) +{ + list_item_append(&task->list, &before->list); +} + +static void zephyr_ll_task_insert_after_unlocked(struct task *task, struct task *after) +{ + list_item_prepend(&task->list, &after->list); +} + +/* perf measurement windows size 2^x */ +#define CYCLES_WINDOW_SIZE 10 + +static inline enum task_state do_task_run(struct task *task) +{ + enum task_state state; + +#if CONFIG_PERFORMANCE_COUNTERS_LL_TASKS + perf_cnt_init(&task->pcd); +#endif + + state = task_run(task); + +#if CONFIG_PERFORMANCE_COUNTERS_LL_TASKS + perf_cnt_stamp(&task->pcd, perf_trace_null, NULL); + task_perf_cnt_avg(&task->pcd, task_perf_avg_info, &ll_tr, task); +#endif + + return state; +} + +/* + * Task state machine: + * INIT: initialized + * QUEUED: inserted into the scheduler queue + * RUNNING: the scheduler is running, the task is moved to a temporary list + * and then executed + * CANCEL: the task has been cancelled but it is still active. Transition + * to CANCEL can happen anywhere, where the lock is not held, tasks + * can be cancelled asynchronously from an arbitrary context + * FREE: removed from all lists, ready to be freed + * other: never set, shouldn't be used, but RESCHEDULE and COMPLETED are + * returned by task's .run function, they are assigned to a + * temporary state, but not to the task .state field + */ + +/* + * struct task::start and struct ll_schedule_domain::next are parts of the + * original LL scheduler design, they aren't needed in this Zephyr-only + * implementation and will be removed after an initial upstreaming. + */ +static void zephyr_ll_run(void *data) +{ + struct zephyr_ll *sch = data; + struct task *task; + struct list_item *list, *tmp, task_head = LIST_INIT(task_head); + uint32_t flags; + + tr_dbg(&ll_tr, "entry"); + + zephyr_ll_lock(sch, &flags); + + /* + * We drop the lock while executing tasks, at that time tasks can be + * removed from or added to the list, including the task that was + * executed. Use a temporary list to make sure that the main list is + * always consistent and contains the tasks, that we haven't run in this + * cycle yet. + */ + + for (list = sch->tasks.next; !list_is_empty(&sch->tasks); list = sch->tasks.next) { + enum task_state state; + struct zephyr_ll_pdata *pdata; + + task = container_of(list, struct task, list); + pdata = task->priv_data; + + if (task->state == SOF_TASK_STATE_CANCEL) { + list = list->next; + zephyr_ll_task_done(sch, task); + continue; + } + + pdata->run = true; + task->state = SOF_TASK_STATE_RUNNING; + + /* Move the task to a temporary list */ + list_item_del(list); + list_item_append(list, &task_head); + + zephyr_ll_unlock(sch, &flags); + + /* + * task's .run() should only return either + * SOF_TASK_STATE_COMPLETED or SOF_TASK_STATE_RESCHEDULE + */ + state = do_task_run(task); + if (state != SOF_TASK_STATE_COMPLETED && + state != SOF_TASK_STATE_RESCHEDULE) { + tr_err(&ll_tr, + "invalid return state %u", + state); + state = SOF_TASK_STATE_RESCHEDULE; + } + + zephyr_ll_lock(sch, &flags); + + if (pdata->freeing || state == SOF_TASK_STATE_COMPLETED) { + zephyr_ll_task_done(sch, task); + } else { + /* + * task->state could've been changed to + * SOF_TASK_STATE_CANCEL + */ + switch (task->state) { + case SOF_TASK_STATE_CANCEL: + zephyr_ll_task_done(sch, task); + break; + default: + break; + } + } + } + + /* Move tasks back */ + list_for_item_safe(list, tmp, &task_head) { + list_item_del(list); + list_item_append(list, &sch->tasks); + } + + zephyr_ll_unlock(sch, &flags); + +#ifndef CONFIG_SOF_USERSPACE_LL + /* TODO: to be replaced with direct function calls */ + notifier_event(sch, NOTIFIER_ID_LL_POST_RUN, + NOTIFIER_TARGET_CORE_LOCAL, NULL, 0); +#endif +} + +static void schedule_ll_callback(void *data) +{ +#ifdef CONFIG_SOF_TELEMETRY + const uint32_t begin_stamp = (uint32_t)telemetry_timestamp(); +#endif + zephyr_ll_run(data); +#ifdef CONFIG_SOF_TELEMETRY + const uint32_t current_stamp = (uint32_t)telemetry_timestamp(); + + telemetry_update(begin_stamp, current_stamp); +#endif +} + +/* + * Called once for periodic tasks or multiple times for one-shot tasks + * TODO: start should be ignored in Zephyr LL scheduler implementation. Tasks + * are scheduled to start on the following tick and run on each subsequent timer + * event. In the future we shall add support for long-period tasks with periods + * equal to a multiple of the scheduler tick time. Ignoring start will eliminate + * the use of task::start and ll_schedule_domain::next in this scheduler. + */ +static int zephyr_ll_task_schedule_common(struct zephyr_ll *sch, struct task *task, + uint64_t start, uint64_t period, + struct task *reference, bool before) +{ + struct zephyr_ll_pdata *pdata; + struct task *task_iter; + struct list_item *list; + uint32_t flags; + int ret; + + zephyr_ll_assert_core(sch); + + tr_info(&ll_tr, "task add %p %pU priority %d flags 0x%x", task, task->uid, + task->priority, task->flags); + + zephyr_ll_lock(sch, &flags); + + pdata = task->priv_data; + + if (!pdata || pdata->freeing) { + /* + * The user has called schedule_task_free() and then + * schedule_task(). This is clearly a bug in the application + * code, but we have to protect against it + */ + zephyr_ll_unlock(sch, &flags); + return -EDEADLK; + } + + /* check if the task is already scheduled */ + list_for_item(list, &sch->tasks) { + task_iter = container_of(list, struct task, list); + + if (task_iter == task) { + /* if cancelled, reschedule the task */ + if (task->state == SOF_TASK_STATE_CANCEL) + break; + + /* + * keep original start. TODO: this shouldn't be happening. + * Remove after verification + */ + zephyr_ll_unlock(sch, &flags); + tr_warn(&ll_tr, "task %p (%pU) already scheduled", + task, task->uid); + return 0; + } + } + + if (task->state == SOF_TASK_STATE_CANCEL) { + /* do not queue the same task again */ + task->state = SOF_TASK_STATE_QUEUED; + zephyr_ll_unlock(sch, &flags); + return 0; + } + + if (!reference) + zephyr_ll_task_insert_unlocked(sch, task); + else if (before) + zephyr_ll_task_insert_before_unlocked(task, reference); + else + zephyr_ll_task_insert_after_unlocked(task, reference); + + sch->n_tasks++; + + zephyr_ll_unlock(sch, &flags); + + ret = domain_register(sch->ll_domain, task, &schedule_ll_callback, sch); + if (ret < 0) + tr_err(&ll_tr, "cannot register domain %d", + ret); + +#if CONFIG_SOF_USERSPACE_LL + k_thread_access_grant(zephyr_domain_thread_tid(sch->ll_domain), sch->lock); + + tr_dbg(&ll_tr, "granting access to lock %p for thread %p", sch->lock, + zephyr_domain_thread_tid(sch->ll_domain)); + tr_dbg(&ll_tr, "granting access to domain lock %p for thread %p", &sch->ll_domain->lock, + zephyr_domain_thread_tid(sch->ll_domain)); +#endif + + return 0; +} + +static int zephyr_ll_task_schedule(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + struct zephyr_ll *sch = data; + + return zephyr_ll_task_schedule_common(sch, task, start, period, NULL, false); +} + +static int zephyr_ll_task_schedule_before(void *data, struct task *task, uint64_t start, + uint64_t period, struct task *before) +{ + struct zephyr_ll *sch = data; + + return zephyr_ll_task_schedule_common(sch, task, start, period, before, true); +} + +static int zephyr_ll_task_schedule_after(void *data, struct task *task, uint64_t start, + uint64_t period, struct task *after) +{ + struct zephyr_ll *sch = data; + + return zephyr_ll_task_schedule_common(sch, task, start, period, after, false); +} + +/* + * This is synchronous - after this returns the object can be destroyed! + * Assertion: under Zephyr this is always called from a thread context! + */ +static int zephyr_ll_task_free(void *data, struct task *task) +{ + struct zephyr_ll *sch = data; + uint32_t flags; + struct zephyr_ll_pdata *pdata = task->priv_data; + bool must_wait, on_list = true; + + zephyr_ll_assert_core(sch); + + if (k_is_in_isr()) { + tr_err(&ll_tr, "cannot free tasks from interrupt context!"); + return -EDEADLK; + } + + zephyr_ll_lock(sch, &flags); + + /* + * It is safe to free the task in state INIT or QUEUED. CANCEL is + * unknown, because it can be set either in a safe state or in an unsafe + * one. If this function took the spin-lock while tasks are pending on a + * temporary list in zephyr_ll_run(), no task can be freed, because + * doing so would corrupt the temporary list. We could use an array of + * task pointers instead, but that array would have to be dynamically + * allocated and we anyway have to wait for the task completion at least + * when it is in the RUNNING state. To identify whether CANCEL is a safe + * one an additional flag must be used. + */ + switch (task->state) { + case SOF_TASK_STATE_INIT: + case SOF_TASK_STATE_FREE: + on_list = false; + /* fall through */ + case SOF_TASK_STATE_QUEUED: + must_wait = false; + break; + case SOF_TASK_STATE_CANCEL: + must_wait = pdata->run; + break; + default: + must_wait = true; + } + + if (on_list && !must_wait) + zephyr_ll_task_done(sch, task); + + pdata->freeing = true; + + zephyr_ll_unlock(sch, &flags); + + if (must_wait) + /* Wait for up to 100 periods */ + k_sem_take(&pdata->sem, K_USEC(LL_TIMER_PERIOD_US * 100)); + + /* Protect against racing with schedule_task() */ + zephyr_ll_lock(sch, &flags); + task->priv_data = NULL; + sof_heap_free(sch->heap, pdata); + zephyr_ll_unlock(sch, &flags); + + return 0; +} + +/* This is asynchronous */ +static int zephyr_ll_task_cancel(void *data, struct task *task) +{ + struct zephyr_ll *sch = data; + uint32_t flags; + + zephyr_ll_assert_core(sch); + + /* + * Read-modify-write of task state in zephyr_ll_task_schedule() must be + * kept atomic, so we have to lock here too. + */ + zephyr_ll_lock(sch, &flags); + + /* + * SOF_TASK_STATE_CANCEL can only be assigned to a task which is on scheduler's list. + * Later such task will be removed from the list by zephyr_ll_task_done(). Do nothing + * for tasks which were never scheduled or were already removed from scheduler's list. + */ + if (task->state != SOF_TASK_STATE_INIT && 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, task); + } + + zephyr_ll_unlock(sch, &flags); + + return 0; +} + +/* + * Runs on secondary cores in their shutdown sequence. In theory tasks can still + * be active, but other schedulers ignore them too... And we don't need to free + * the scheduler data - it's allocated in the SYS zone. + */ +static void zephyr_ll_scheduler_free(void *data, uint32_t flags) +{ + struct zephyr_ll *sch = data; + + zephyr_ll_assert_core(sch); + + if (sch->n_tasks) + tr_err(&ll_tr, "%u tasks are still active!", + sch->n_tasks); +} + +static const struct scheduler_ops zephyr_ll_ops = { + .schedule_task = zephyr_ll_task_schedule, + .schedule_task_before = zephyr_ll_task_schedule_before, + .schedule_task_after = zephyr_ll_task_schedule_after, + .schedule_task_free = zephyr_ll_task_free, + .schedule_task_cancel = zephyr_ll_task_cancel, + .scheduler_free = zephyr_ll_scheduler_free, +}; + +#if CONFIG_SOF_USERSPACE_LL +struct task *zephyr_ll_task_alloc(void) +{ + return sof_heap_alloc(zephyr_ll_user_heap(), SOF_MEM_FLAG_USER, + sizeof(struct task), sizeof(void *)); +} +#endif /* CONFIG_SOF_USERSPACE_LL */ + +int zephyr_ll_task_init(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) +{ + struct zephyr_ll_pdata *pdata; + struct k_heap *heap = sof_sys_heap_get(); + int alloc_flags = SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT; + int ret; + + tr_dbg(&ll_tr, "ll-scheduler task %p init", data); + + if (task->priv_data) + return -EEXIST; + + ret = schedule_task_init(task, uid, type, priority, run, data, core, + flags); + if (ret < 0) + return ret; + +#if CONFIG_SOF_USERSPACE_LL + heap = zephyr_ll_user_heap(); + alloc_flags = SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT; +#endif + pdata = sof_heap_alloc(heap, alloc_flags, sizeof(*pdata), 0); + if (!pdata) { + tr_err(&ll_tr, "alloc failed"); + return -ENOMEM; + } + + memset(pdata, 0, sizeof(*pdata)); + + k_sem_init(&pdata->sem, 0, 1); + + task->priv_data = pdata; + + return 0; +} +EXPORT_SYMBOL(zephyr_ll_task_init); + +/* TODO: low-power mode clock support */ +/* Runs on each core during initialisation with the same domain argument */ +int zephyr_ll_scheduler_init(struct ll_schedule_domain *domain) +{ + struct zephyr_ll *sch; + int core = cpu_get_id(); + struct k_heap *heap = sof_sys_heap_get(); + int flags = SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT; + +#if CONFIG_SOF_USERSPACE_LL + heap = zephyr_ll_user_heap(); + flags = SOF_MEM_FLAG_USER; +#endif + tr_dbg(&ll_tr, "init on core %d", core); + + /* initialize per-core scheduler private data */ + sch = sof_heap_alloc(heap, flags, sizeof(*sch), 0); + if (!sch) { + tr_err(&ll_tr, "allocation failed"); + return -ENOMEM; + } + + memset(sch, 0, sizeof(*sch)); + + list_init(&sch->tasks); + sch->ll_domain = domain; + sch->core = core; + sch->n_tasks = 0; + sch->heap = heap; + +#if CONFIG_SOF_USERSPACE_LL + /* Allocate mutex dynamically for userspace access */ + sch->lock = k_object_alloc(K_OBJ_MUTEX); + if (!sch->lock) { + tr_err(&ll_tr, "mutex allocation failed"); + sof_heap_free(sch->heap, sch); + return -ENOMEM; + } + k_mutex_init(sch->lock); + + tr_dbg(&ll_tr, "ll-scheduler init done, sch %p sch->lock %p", sch, sch->lock); +#endif + + scheduler_init(domain->type, &zephyr_ll_ops, sch); + + return 0; +} + +void scheduler_get_task_info_ll(struct scheduler_props *scheduler_props, + uint32_t *data_off_size) +{ + uint32_t flags; + + scheduler_props->processing_domain = COMP_PROCESSING_DOMAIN_LL; + struct zephyr_ll *ll_sch = (struct zephyr_ll *)scheduler_get_data(SOF_SCHEDULE_LL_TIMER); + + zephyr_ll_lock(ll_sch, &flags); + scheduler_get_task_info(scheduler_props, data_off_size, &ll_sch->tasks); + zephyr_ll_unlock(ll_sch, &flags); +} + +/* Return a pointer to the LL scheduler timer domain */ +struct ll_schedule_domain *zephyr_ll_domain(void) +{ + struct zephyr_ll *ll_sch = scheduler_get_data(SOF_SCHEDULE_LL_TIMER); + + return ll_sch->ll_domain; +} diff --git a/src/schedule/zephyr_ll_user.c b/src/schedule/zephyr_ll_user.c new file mode 100644 index 000000000000..aa33807b4aa3 --- /dev/null +++ b/src/schedule/zephyr_ll_user.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. + +#include <zephyr/cache.h> +#include <zephyr/kernel.h> +#include <zephyr/logging/log.h> + +#include <rtos/userspace_helper.h> + +#include <sof/schedule/ll_schedule_domain.h> + +LOG_MODULE_DECLARE(ll_schedule, CONFIG_SOF_LOG_LEVEL); + +/** + * Memory resources for userspace LL scheduler + * + * This structure encapsulates the memory management resources required for the + * low-latency (LL) scheduler in userspace mode. It provides memory isolation + * and heap management for LL scheduler threads. + */ +struct zephyr_ll_mem_resources { + struct k_mem_domain mem_domain; /**< Memory domain for LL thread isolation */ + struct k_heap *heap; /**< Heap allocator for LL scheduler memory */ +}; + +static struct zephyr_ll_mem_resources ll_mem_resources; + +static struct k_heap *zephyr_ll_heap_init(void) +{ + struct k_heap *heap = module_driver_heap_init(); + struct k_mem_partition mem_partition; + int ret; + + /* + * TODO: the size of LL heap should be independently configurable and + * not tied to CONFIG_SOF_ZEPHYR_USERSPACE_MODULE_HEAP_SIZE + */ + + if (!heap) { + tr_err(&ll_tr, "heap alloc fail"); + k_panic(); + } + + /* Create memory partition for sch_data array */ + mem_partition.start = (uintptr_t)sys_cache_cached_ptr_get(heap->heap.init_mem); + mem_partition.size = heap->heap.init_bytes; + mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW | XTENSA_MMU_CACHED_WB; + + ret = k_mem_domain_add_partition(&ll_mem_resources.mem_domain, &mem_partition); + tr_dbg(&ll_tr, "init ll heap %p, size %u (cached), ret %d", + (void *)mem_partition.start, heap->heap.init_bytes, ret); + if (ret) + k_panic(); + + mem_partition.start = (uintptr_t)sys_cache_uncached_ptr_get(heap->heap.init_mem); + mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW; + ret = k_mem_domain_add_partition(&ll_mem_resources.mem_domain, &mem_partition); + tr_dbg(&ll_tr, "init ll heap %p, size %u (uncached), ret %d", + (void *)mem_partition.start, heap->heap.init_bytes, ret); + if (ret) + k_panic(); + + return heap; +} + +void zephyr_ll_user_resources_init(void) +{ + k_mem_domain_init(&ll_mem_resources.mem_domain, 0, NULL); + + ll_mem_resources.heap = zephyr_ll_heap_init(); + + /* attach common partition to LL domain */ + user_memory_attach_common_partition(zephyr_ll_mem_domain()); +} + +struct k_heap *zephyr_ll_user_heap(void) +{ + return ll_mem_resources.heap; +} + +struct k_mem_domain *zephyr_ll_mem_domain(void) +{ + return &ll_mem_resources.mem_domain; +} diff --git a/src/schedule/zephyr_twb_schedule.c b/src/schedule/zephyr_twb_schedule.c new file mode 100644 index 000000000000..aee61360d697 --- /dev/null +++ b/src/schedule/zephyr_twb_schedule.c @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Adrian Bonislawski <adrian.bonislawski@intel.com> + */ + +#include <rtos/task.h> +#include <stdint.h> +#include <sof/lib/uuid.h> +#include <sof/schedule/schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/twb_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/trace/trace.h> +#include <rtos/wait.h> +#include <rtos/interrupt.h> +#include <zephyr/init.h> +#include <zephyr/kernel.h> +#include <zephyr/kernel/thread.h> +#include <zephyr/sys_clock.h> + +LOG_MODULE_REGISTER(twb_schedule, CONFIG_SOF_LOG_LEVEL); +SOF_DEFINE_REG_UUID(twb_sched); + +DECLARE_TR_CTX(twb_tr, SOF_UUID(twb_sched_uuid), LOG_LEVEL_INFO); + +struct scheduler_twb_data { + struct list_item tasks; /* list of active TWB tasks */ + struct task ll_tick_src; /* LL task - source of TWB tick */ +}; + +struct task_twb_data { + k_tid_t thread_id; /* zephyr thread ID */ + k_thread_stack_t __sparse_cache *p_stack; /* pointer to thread stack */ + struct k_sem sem; /* thread semaphore */ + int32_t thread_prio; /* thread default priority */ + uint32_t cycles_granted; /* cycles budget for the task */ + uint32_t cycles_consumed; /* cycles consumed by the task */ + uint64_t cycles_ref; /* reference cycles for the task */ +}; + +/* Single CPU-wide lock + * as each per-core instance if TWB-scheduler has separate structures, it is enough to + * use irq_lock instead of cross-core spinlocks + */ +static inline unsigned int scheduler_twb_lock(void) +{ + return irq_lock(); +} + +static inline void scheduler_twb_unlock(unsigned int key) +{ + irq_unlock(key); +} + +/** + * @brief Callback function for the TWB scheduler task. + * + * This function is called when the TWB scheduler task runs out of budget. + * It lowers the priority of the thread and sets the time slice to 0. + * + * @param thread Pointer to the thread structure. + * @param data Pointer to additional data (not used). + */ +static void scheduler_twb_task_cb(struct k_thread *thread, void *data) +{ + tr_dbg(&twb_tr, "TWB task %p out of budget, lowering priority", data); + + k_thread_priority_set(thread, CONFIG_TWB_THREAD_LOW_PRIORITY); + k_thread_time_slice_set(thread, 0, &scheduler_twb_task_cb, data); +} + +/** + * @brief Executes the LL tick of the TWB scheduler. + * + * This function is responsible for executing the LL tick of the TWB scheduler. + * It iterates through the list of tasks and performs the necessary operations + * based on the task's state. + * If a task is in the QUEUED state, it is transitioned to the RUNNING state + * and its associated thread is resumed. + * If a task is in the RUNNING state, its thread's priority and time slice + * are set based on the task's budget. + * The function also retrieves the runtime statistics of the thread and + * updates the task's reference cycle count. + * If a task is in the CANCEL or COMPLETED state, it is removed from the list. + * + * @param data Pointer to the scheduler_twb_data structure. + * @return The state of the task after the LL tick execution. + * If no task requires further execution, SOF_TASK_STATE_COMPLETED is returned. + * Otherwise, SOF_TASK_STATE_RESCHEDULE is returned. + */ +static enum task_state scheduler_twb_ll_tick(void *data) +{ + struct scheduler_twb_data *twb_sch = data; + k_thread_runtime_stats_t rt_stats_thread; + struct list_item *tlist, *tmp; + struct task_twb_data *pdata; + struct task *curr_task; + unsigned int lock_key; + bool keep_ll_tick_src = false; + + lock_key = scheduler_twb_lock(); + + /* Iterate through the list of tasks */ + list_for_item_safe(tlist, tmp, &twb_sch->tasks) { + curr_task = container_of(tlist, struct task, list); + pdata = curr_task->priv_data; + + /* Reset consumed cycles */ + pdata->cycles_consumed = 0; + + switch (curr_task->state) { + case SOF_TASK_STATE_QUEUED: + curr_task->state = SOF_TASK_STATE_RUNNING; + k_sem_give(&pdata->sem); + COMPILER_FALLTHROUGH; + case SOF_TASK_STATE_RUNNING: + if (pdata->cycles_granted) { + /* Reset thread's priority and time slice based on task's budget */ + k_thread_priority_set(pdata->thread_id, pdata->thread_prio); + k_thread_time_slice_set(pdata->thread_id, pdata->cycles_granted, + &scheduler_twb_task_cb, curr_task); + + /* Retrieve runtime statistics of the thread & update ref cycle */ + k_thread_runtime_stats_get(pdata->thread_id, &rt_stats_thread); + pdata->cycles_ref = rt_stats_thread.execution_cycles; + } + keep_ll_tick_src = true; + break; + case SOF_TASK_STATE_CANCEL: + case SOF_TASK_STATE_COMPLETED: + /* Finally remove task from the list */ + list_item_del(&curr_task->list); + break; + default: + break; + } + } + + scheduler_twb_unlock(lock_key); + + if (!keep_ll_tick_src) + return SOF_TASK_STATE_COMPLETED; + + return SOF_TASK_STATE_RESCHEDULE; +} + +/** + * @brief Thread function for a TWB task. + * + * This function is responsible for executing the TWB task in a loop. + * It checks the state of the task, runs the task if it is in the running state, + * and handles different task states such as rescheduling, cancellation, and completion. + * It also updates the runtime statistics of the thread and suspends the + * thread if the task is not in the running state. + * + * @param p1 Pointer to the task structure. + * @param p2 Unused parameter. + * @param p3 Unused parameter. + */ +static void twb_thread_fn(void *p1, void *p2, void *p3) +{ + struct task *task = p1; + struct task *ll_tick_src = p2; + (void)p3; + struct task_twb_data *pdata = task->priv_data; + k_thread_runtime_stats_t rt_stats_thread; + enum task_state state; + unsigned int lock_key; + + while (1) { + if (ll_tick_src->state == SOF_TASK_STATE_INIT || ll_tick_src->state == SOF_TASK_STATE_FREE) + schedule_task(ll_tick_src, 0, 0); + + if (task->state == SOF_TASK_STATE_RUNNING) { + state = task_run(task); + } else { + state = task->state; /* to avoid undefined variable warning */ + } + + lock_key = scheduler_twb_lock(); + /* + * check if task is still running, may have been canceled by external call + * if not, set the state returned by run procedure + */ + if (task->state == SOF_TASK_STATE_RUNNING) { + if (pdata->cycles_granted) { + k_thread_runtime_stats_get(pdata->thread_id, &rt_stats_thread); + pdata->cycles_consumed += rt_stats_thread.execution_cycles - pdata->cycles_ref; + pdata->cycles_ref = rt_stats_thread.execution_cycles; + } + switch (state) { + case SOF_TASK_STATE_RESCHEDULE: + /* mark to reschedule, schedule time is already calculated */ + task->state = SOF_TASK_STATE_QUEUED; + break; + case SOF_TASK_STATE_CANCEL: + task->state = SOF_TASK_STATE_CANCEL; + break; + case SOF_TASK_STATE_COMPLETED: + break; + + default: + /* illegal state, serious defect, won't happen */ + scheduler_twb_unlock(lock_key); + k_panic(); + } + } + + scheduler_twb_unlock(lock_key); + + if (state == SOF_TASK_STATE_COMPLETED) { + task->state = SOF_TASK_STATE_COMPLETED; + task_complete(task); + } + + if (state != SOF_TASK_STATE_RUNNING) + k_sem_take(&pdata->sem, K_FOREVER); + }; + /* never be here */ +} + +/** + * Schedule a task in the TWB scheduler. + * + * This function adds a task to the TWB scheduler list, + * recalculate budget and starts the thread associated with the task. + * If there are no TWB tasks scheduled yet, it also runs the LL tick source task. + * + * @param data Pointer to the TWB scheduler data. + * @param task Pointer to the task to be scheduled. + * @param start The start time of the task. + * @param period The period of the task. + * @return 0 on success, or a negative error code on failure. + */ +static int scheduler_twb_task_shedule(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + struct scheduler_twb_data *twb_sch = (struct scheduler_twb_data *)data; + struct task_twb_data *pdata = task->priv_data; + struct list_item *tlist; + struct task *task_iter; + unsigned int lock_key; + bool list_prepend = true; + bool thread_started = true; + uint32_t budget_left = 0; + + lock_key = scheduler_twb_lock(); + + if (task->state != SOF_TASK_STATE_INIT && + task->state != SOF_TASK_STATE_CANCEL && + task->state != SOF_TASK_STATE_COMPLETED) { + scheduler_twb_unlock(lock_key); + return -EINVAL; + } else if (task->state == SOF_TASK_STATE_INIT) { + thread_started = false; + } + + /* add a task to TWB scheduler list */ + task->state = SOF_TASK_STATE_RUNNING; + + /* if there's no TWB tasks scheduled yet, run ll tick source task */ + if (list_is_empty(&twb_sch->tasks)) { + if (!k_is_in_isr()) + schedule_task(&twb_sch->ll_tick_src, 0, 0); + } else { + list_for_item(tlist, &twb_sch->tasks) { + task_iter = container_of(tlist, struct task, list); + if (task == task_iter) { + list_prepend = false; + break; + } + } + } + + if (list_prepend) + list_item_prepend(&task->list, &twb_sch->tasks); + + /* If the task has a cycles budget, calculate the budget_left and set the thread priority */ + if (pdata->cycles_granted) { + if (pdata->cycles_consumed < SYS_TICKS_TO_HW_CYCLES(pdata->cycles_granted)) { + budget_left = HW_CYCLES_TO_SYS_TICKS(SYS_TICKS_TO_HW_CYCLES(pdata->cycles_granted) - pdata->cycles_consumed); + k_thread_priority_set(pdata->thread_id, pdata->thread_prio); + } else { + k_thread_priority_set(pdata->thread_id, CONFIG_TWB_THREAD_LOW_PRIORITY); + } + k_thread_time_slice_set(pdata->thread_id, budget_left, &scheduler_twb_task_cb, task); + } + + tr_dbg(&twb_tr, "TWB task %p scheduled with budget %d/%d", task, budget_left, pdata->cycles_granted); + + /* start the thread */ + if (!thread_started) + k_thread_start(pdata->thread_id); + else + k_sem_give(&pdata->sem); + + scheduler_twb_unlock(lock_key); + + return 0; +} + +static int scheduler_twb_task_cancel(void *data, struct task *task) +{ + struct task_twb_data *task_pdata = task->priv_data; + k_thread_runtime_stats_t rt_stats_thread; + unsigned int lock_key; + + lock_key = scheduler_twb_lock(); + + if (task_pdata->cycles_granted) { + /* Get the stats and update the consumed cycles */ + k_thread_runtime_stats_get(task_pdata->thread_id, &rt_stats_thread); + task_pdata->cycles_consumed += rt_stats_thread.execution_cycles - task_pdata->cycles_ref; + task_pdata->cycles_ref = rt_stats_thread.execution_cycles; + } + + /* Set the task state to CANCEL */ + task->state = SOF_TASK_STATE_CANCEL; + + scheduler_twb_unlock(lock_key); + + return 0; +} + +static int scheduler_twb_task_free(void *data, struct task *task) +{ + struct task_twb_data *pdata = task->priv_data; + + scheduler_twb_task_cancel(data, task); + + list_item_del(&task->list); + + /* abort the execution of the thread */ + k_thread_abort(pdata->thread_id); + + /* free task stack */ + rfree((__sparse_force void *)pdata->p_stack); + + /* all other memory has been allocated as a single malloc, will be freed later by caller */ + return 0; +} + +static struct scheduler_ops schedule_twb_ops = { + .schedule_task = scheduler_twb_task_shedule, + .schedule_task_cancel = scheduler_twb_task_cancel, + .schedule_task_free = scheduler_twb_task_free, +}; + +int scheduler_twb_init(void) +{ + struct scheduler_twb_data *twb_sch = rzalloc(SOF_MEM_FLAG_KERNEL, + sizeof(struct scheduler_twb_data)); + int ret; + + if (!twb_sch) + return -ENOMEM; + + list_init(&twb_sch->tasks); + + scheduler_init(SOF_SCHEDULE_TWB, &schedule_twb_ops, twb_sch); + + /* init src of TWB tick */ + ret = schedule_task_init_ll(&twb_sch->ll_tick_src, + SOF_UUID(twb_sched_uuid), + SOF_SCHEDULE_LL_TIMER, + 0, scheduler_twb_ll_tick, twb_sch, + cpu_get_id(), 0); + + return ret; +} + +int scheduler_twb_task_init(struct task **task, + const struct sof_uuid_entry *uid, + const struct task_ops *ops, + void *data, + int32_t core, + const char *name, + size_t stack_size, + int32_t thread_priority, + uint32_t cycles_granted) +{ + struct scheduler_twb_data *twb_sch; + void __sparse_cache *p_stack = NULL; + k_tid_t thread_id = NULL; + int ret; + + /* memory allocation helper structure */ + struct { + struct task task; + struct task_twb_data pdata; + struct k_thread thread; + } *task_memory; + + twb_sch = scheduler_get_data(SOF_SCHEDULE_TWB); + if (!twb_sch) { + tr_err(&twb_tr, "TWB not initialized"); + return -EINVAL; + } + + /* must be called on the same core the task will be binded to */ + assert(cpu_get_id() == core); + + if (thread_priority < 0) { + tr_err(&twb_tr, "non preemptible priority"); + return -EINVAL; + } + + /* + * allocate memory + * to avoid multiple malloc operations allocate all required memory as a single structure + * and return pointer to task_memory->task + * As the structure contains zephyr kernel specific data, it must be located in + * shared, non cached memory + */ + task_memory = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(*task_memory)); + if (!task_memory) { + tr_err(&twb_tr, "memory alloc failed"); + return -ENOMEM; + } + + /* allocate stack - must be aligned and cached so a separate alloc */ + stack_size = Z_KERNEL_STACK_SIZE_ADJUST(stack_size); + p_stack = (__sparse_force void __sparse_cache *) + rballoc_align(SOF_MEM_FLAG_KERNEL, stack_size, Z_KERNEL_STACK_OBJ_ALIGN); + if (!p_stack) { + tr_err(&twb_tr, "stack alloc failed"); + ret = -ENOMEM; + goto err; + } + + /* create a zephyr thread for the task */ + thread_id = k_thread_create(&task_memory->thread, (__sparse_force void *)p_stack, + stack_size, twb_thread_fn, &task_memory->task, &twb_sch->ll_tick_src, NULL, + thread_priority, K_USER, K_FOREVER); + if (!thread_id) { + ret = -EFAULT; + tr_err(&twb_tr, "zephyr thread create failed"); + goto err; + } + +#ifdef CONFIG_SCHED_CPU_MASK + /* pin the thread to specific core */ + ret = k_thread_cpu_pin(thread_id, core); + if (ret < 0) { + ret = -EFAULT; + tr_err(&twb_tr, "zephyr task pin to core %d failed", core); + goto err; + } +#endif + + /* set the thread name */ + if (name) { + ret = k_thread_name_set(thread_id, name); + if (ret < 0) + tr_warn(&twb_tr, "failed to set thread name"); + } + + /* internal SOF task init */ + ret = schedule_task_init(&task_memory->task, uid, SOF_SCHEDULE_TWB, thread_priority, + ops->run, data, core, 0); + if (ret < 0) { + tr_err(&twb_tr, "schedule_task_init failed"); + goto err; + } + + /* unlimited mcps budget */ + if (cycles_granted >= ZEPHYR_TWB_BUDGET_MAX) + cycles_granted = 0; + + /* initialize other task structures */ + task_memory->task.ops.complete = ops->complete; + task_memory->task.ops.get_deadline = ops->get_deadline; + + /* success, fill the structures */ + task_memory->task.priv_data = &task_memory->pdata; + task_memory->pdata.thread_id = thread_id; + task_memory->pdata.p_stack = p_stack; + task_memory->pdata.thread_prio = thread_priority; + task_memory->pdata.cycles_granted = cycles_granted; + task_memory->pdata.cycles_consumed = 0; + task_memory->pdata.cycles_ref = 0; + *task = &task_memory->task; + + k_sem_init(&task_memory->pdata.sem, 0, 10); + + tr_dbg(&twb_tr, "TWB task %p initialized: thread: %p, core: %d, prio: %d, budget: %d", + task, thread_id, core, thread_priority, cycles_granted); + + return 0; +err: + /* cleanup - free all allocated resources */ + if (thread_id) + k_thread_abort(thread_id); + + rfree((__sparse_force void *)p_stack); + rfree(task_memory); + return ret; +} diff --git a/src/spinlock.c b/src/spinlock.c deleted file mode 100644 index 2384d0553eb1..000000000000 --- a/src/spinlock.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2020 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/drivers/interrupt.h> -#include <sof/spinlock.h> -#include <config.h> -#include <stdint.h> - -uint32_t _spin_lock_irq(spinlock_t *lock) -{ - uint32_t flags; - - flags = interrupt_global_disable(); -#if CONFIG_DEBUG_LOCKS - lock_dbg_atomic++; -#endif - spin_lock(lock); -#if CONFIG_DEBUG_LOCKS - if (lock_dbg_atomic < DBG_LOCK_USERS) - lock_dbg_user[lock_dbg_atomic - 1] = (lock)->user; -#endif - return flags; -} - -void _spin_unlock_irq(spinlock_t *lock, uint32_t flags, int line) -{ - _spin_unlock(lock, line); -#if CONFIG_DEBUG_LOCKS - lock_dbg_atomic--; -#endif - interrupt_global_enable(flags); -} diff --git a/src/trace/CMakeLists.txt b/src/trace/CMakeLists.txt index 75b843876df4..7fab6cf5eaaa 100644 --- a/src/trace/CMakeLists.txt +++ b/src/trace/CMakeLists.txt @@ -1,3 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -add_local_sources(sof dma-trace.c trace.c) +if(CONFIG_TRACE) + add_local_sources(sof dma-trace.c trace.c) +endif() diff --git a/src/trace/Kconfig b/src/trace/Kconfig index fdcd70878f7b..92ccb461ed18 100644 --- a/src/trace/Kconfig +++ b/src/trace/Kconfig @@ -6,16 +6,20 @@ menu "Trace" config TRACE bool "Trace" + default n if ZEPHYR_SOF_MODULE default y help - Enabling traces. All traces (normal and error) are sent by dma. + Enable SOF DMA based traces compatible with the sof-logger tool. + With Zephyr, RTOS side events are not seen in the SOF trace, so native + Zephyr logging (CONFIG_ZEPHYR_LOG) is recommended instead. config TRACEV bool "Trace verbose" depends on TRACE default n help - Enabling verbose traces. + Enabling verbose traces. tr_dbg() statements depend on this at + compile-time and on run-time filtering below too. config TRACEE bool "Trace error" @@ -31,4 +35,105 @@ config TRACEM help Sending all traces by mailbox additionally. +config TRACE_FILTERING + bool "Trace filtering" + depends on TRACE + default y + help + Filtering of trace messages based on their verbosity level and/or frequency. + +config TRACE_FILTERING_VERBOSITY + bool "Filter by verbosity" + depends on TRACE_FILTERING + default y + help + Filtering by log verbosity level, where maximum verbosity allowed is specified for each + context and may be adjusted in runtime. Most basic feature found in every logger. + +config TRACE_FILTERING_ADAPTIVE + bool "Adaptive rate limiting" + depends on TRACE_FILTERING + default y + help + Adaptive filtering of repeating trace messages, tracking up to + CONFIG_TRACE_RECENT_ENTRIES_COUNT and suppressing messages repeated in less than + CONFIG_TRACE_RECENT_TIME_THRESHOLD microseconds. This filtering and suppression are + turned off as soon as the user makes any runtime configuration change using the + sof-logger -F flag. Warning: log message parameters (formatted with a conversion + specifier %_) are ignored when comparing repeated messages and they are dropped by + this filtering. + +config TRACE_RECENT_ENTRIES_COUNT + int "How many recent log messages are stored" + depends on TRACE_FILTERING_ADAPTIVE + default 5 + help + The most recent log messages are stored to match the currently processed + message. The size of that window affects effectiveness and performance. More recent + entries allow to better filter repetitive messages out, but also slightly decrease + performance due to the increased number of comparisons necessary. + +config TRACE_RECENT_TIME_THRESHOLD + int "Period of time considered recent (microseconds)" + depends on TRACE_FILTERING_ADAPTIVE + default 1500 + range 1 TRACE_RECENT_MAX_TIME + help + Period of time during which entries are tracked and will be suppressed if reported again. + Entries expire after this time. + +config TRACE_RECENT_MAX_TIME + int "Maximum period of time that message can be suppressed (microseconds)" + depends on TRACE_FILTERING_ADAPTIVE + default 5000000 + help + Maximum amount of time message can be suppressed for, due to repeated suppression. + +config TRACE_BURST_COUNT + int "Allowed amount of rapidly repeated messages, that will not be suppressed by the filter" + depends on TRACE_FILTERING_ADAPTIVE + default 4 + help + Amount of messages that will pass through the filter even if sent in rapid succession. + Allowed message burst size before filter suppresses the message. + +config LOG_BACKEND_SOF_PROBE + bool "Logging backend with SOF probes" + depends on LOG + select LOG_OUTPUT + help + Enable backend for log output via SOF probe interface. + Probe interface allows to transmit logs and PCM data, muxed over + a shared DMA channel. + Logging is enabled by setting up a probe point with + probe purpose value of PROBE_PURPOSE_LOGGING. + +config LOG_BACKEND_SOF_PROBE_OUTPUT_AUTO_ENABLE + bool "Automatically enable probes logging when probe dma is started" + depends on LOG_BACKEND_SOF_PROBE + help + Automatically enable logging as soon as probes DMA + starts. This option simplifies probes logging back + end usage as there is no need to enable logs after + every boot. The probes DMA is still needed before the + log output can be enabled. + +config LOG_BACKEND_SOF_PROBE_OUTPUT_DICTIONARY + bool "Dictionary" + select LOG_DICTIONARY_SUPPORT + help + Set output format of the SOF probe logging backend to + Zephyr log dictionary. + The resulting log file can be parsed with tools in + zephyr/scripts/logging/dictionary + A dictionary for the binary is created during build. + +config LOG_BACKEND_SOF_PROBE_OUTPUT + int "Set logging output format" + default 1 if LOG_MIPI_SYST_ENABLE + default 2 if LOG_BACKEND_SOF_PROBE_OUTPUT_DICTIONARY + default 0 # Text encoding is default + help + Set the logging format for SOF probe output. + endmenu diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index 19583d66a019..554204ac5c70 100644 --- a/src/trace/dma-trace.c +++ b/src/trace/dma-trace.c @@ -6,10 +6,10 @@ #include <sof/audio/buffer.h> #include <sof/common.h> -#include <sof/debug/panic.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/lib/cpu.h> #include <sof/lib/dma.h> #include <sof/lib/memory.h> @@ -17,36 +17,58 @@ #include <sof/platform.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/schedule.h> -#include <sof/schedule/task.h> -#include <sof/sof.h> -#include <sof/spinlock.h> -#include <sof/string.h> +#include <rtos/task.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <rtos/string.h> +#include <rtos/string_macro.h> #include <sof/trace/dma-trace.h> #include <ipc/topology.h> #include <ipc/trace.h> -#include <config.h> +#include <kernel/abi.h> +#include <user/abi_dbg.h> +#include <sof_versions.h> + +#ifdef __ZEPHYR__ +#include <version.h> +#endif + #include <errno.h> #include <stddef.h> #include <stdint.h> -/* 2b972272-c5b1-4b7e-926f-0fc5cb4c4690 */ -DECLARE_SOF_UUID("dma-trace-task", dma_trace_task_uuid, 0x2b972272, 0xc5b1, - 0x4b7e, 0x92, 0x6f, 0x0f, 0xc5, 0xcb, 0x4c, 0x46, 0x90); +LOG_MODULE_REGISTER(dma_trace, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(dma_trace); + +DECLARE_TR_CTX(dt_tr, SOF_UUID(dma_trace_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(dma_trace_task); static int dma_trace_get_avail_data(struct dma_trace_data *d, struct dma_trace_buf *buffer, int avail); +/** Periodically runs and starts the DMA even when the buffer is not + * full. + */ static enum task_state trace_work(void *data) { struct dma_trace_data *d = data; struct dma_trace_buf *buffer = &d->dmatb; struct dma_sg_config *config = &d->config; - unsigned long flags; + k_spinlock_key_t key; uint32_t avail = buffer->avail; int32_t size; uint32_t overflow; + /* The host DMA channel is not available */ + if (!d->dc.chan) + return SOF_TASK_STATE_RESCHEDULE; + + if (!ipc_trigger_trace_xfer(avail)) + return SOF_TASK_STATE_RESCHEDULE; + /* make sure we don't write more than buffer */ if (avail > DMA_TRACE_LOCAL_SIZE) { overflow = avail - DMA_TRACE_LOCAL_SIZE; @@ -62,7 +84,6 @@ static enum task_state trace_work(void *data) /* any data to copy ? */ if (size == 0) { - platform_shared_commit(d, sizeof(*d)); return SOF_TASK_STATE_RESCHEDULE; } @@ -72,11 +93,10 @@ static enum task_state trace_work(void *data) d->copy_in_progress = 1; /* copy this section to host */ - size = dma_copy_to_host_nowait(&d->dc, config, d->posn.host_offset, - buffer->r_ptr, size); + size = dma_copy_to_host(&d->dc, config, d->posn.host_offset, + buffer->r_ptr, size); if (size < 0) { - trace_buffer_error("trace_work() error: " - "dma_copy_to_host_nowait() failed"); + tr_err(&dt_tr, "dma_copy_to_host() failed"); goto out; } @@ -90,8 +110,10 @@ static enum task_state trace_work(void *data) if (buffer->r_ptr >= buffer->end_addr) buffer->r_ptr = (char *)buffer->r_ptr - DMA_TRACE_LOCAL_SIZE; + ipc_msg_send(d->msg, &d->posn, false); + out: - spin_lock_irq(&d->lock, flags); + key = k_spin_lock(&d->lock); /* disregard any old messages and don't resend them if we overflow */ if (size > 0) { @@ -104,52 +126,89 @@ static enum task_state trace_work(void *data) /* DMA trace copying is done, allow reschedule */ d->copy_in_progress = 0; - platform_shared_commit(d, sizeof(*d)); - - spin_unlock_irq(&d->lock, flags); + k_spin_unlock(&d->lock, key); /* reschedule the trace copying work */ return SOF_TASK_STATE_RESCHEDULE; } +/** Do this early so we can log at initialization time even before the + * DMA runs. The rest happens later in dma_trace_init_complete() and + * dma_trace_enable() + */ int dma_trace_init_early(struct sof *sof) { - sof->dmat = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*sof->dmat)); + int ret; + + /* If this assert is wrong then traces have been corrupting + * random parts of memory. Some functions run before _and_ after + * DMA trace initialization and we don't want to ask them to + * never trace. So dma_trace_initialized() must be either + * clearly false/NULL or clearly true, we can't tolerate random + * uninitialized values in sof->dmat etc. + */ + assert(!dma_trace_initialized(sof->dmat)); + + sof->dmat = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*sof->dmat)); + if (!sof->dmat) { + mtrace_printf(LOG_LEVEL_ERROR, + "alloc failed"); + return -ENOMEM; + } + dma_sg_init(&sof->dmat->config.elem_array); - spinlock_init(&sof->dmat->lock); + k_spinlock_init(&sof->dmat->lock); ipc_build_trace_posn(&sof->dmat->posn); sof->dmat->msg = ipc_msg_init(sof->dmat->posn.rhdr.hdr.cmd, - sizeof(sof->dmat->posn)); - if (!sof->dmat->msg) - return -ENOMEM; - - platform_shared_commit(sof->dmat, sizeof(*sof->dmat)); + sof->dmat->posn.rhdr.hdr.size); + if (!sof->dmat->msg) { + ret = -ENOMEM; + goto err; + } return 0; + +err: + mtrace_printf(LOG_LEVEL_ERROR, + "failed: %d", ret); + + rfree(sof->dmat); + sof->dmat = NULL; + + return ret; } +/** Run after dma_trace_init_early() and before dma_trace_enable() */ int dma_trace_init_complete(struct dma_trace_data *d) { int ret = 0; - trace_buffer("dma_trace_init_complete()"); + tr_info(&dt_tr, "entry"); + + if (!d) { + mtrace_printf(LOG_LEVEL_ERROR, + "failed, no dma_trace_data"); + return -ENOMEM; + } /* init DMA copy context */ ret = dma_copy_new(&d->dc); if (ret < 0) { - trace_buffer_error("dma_trace_init_complete() error: " - "dma_copy_new() failed"); + mtrace_printf(LOG_LEVEL_ERROR, + "dma_copy_new() failed: %d", ret); goto out; } - - ret = dma_get_attribute(d->dc.dmac, DMA_ATTR_COPY_ALIGNMENT, +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + ret = dma_get_attribute(d->dc.dmac->z_dev, DMA_ATTR_COPY_ALIGNMENT, &d->dma_copy_align); - +#else + ret = dma_get_attribute_legacy(d->dc.dmac, DMA_ATTR_COPY_ALIGNMENT, + &d->dma_copy_align); +#endif if (ret < 0) { - trace_buffer("dma_trace_init_complete() " - "error: dma_get_attribute()"); + mtrace_printf(LOG_LEVEL_ERROR, + "dma_get_attribute() failed: %d", ret); goto out; } @@ -159,7 +218,6 @@ int dma_trace_init_complete(struct dma_trace_data *d) SOF_TASK_PRI_MED, trace_work, d, 0, 0); out: - platform_shared_commit(d, sizeof(*d)); return ret; } @@ -172,32 +230,70 @@ int dma_trace_host_buffer(struct dma_trace_data *d, d->host_size = host_size; d->config.elem_array = *elem_array; - platform_shared_commit(d, sizeof(*d)); - return 0; } #endif +static void dma_trace_buffer_free(struct dma_trace_data *d) +{ + struct dma_trace_buf *buffer = &d->dmatb; + k_spinlock_key_t key; + + key = k_spin_lock(&d->lock); + + rfree(buffer->addr); + memset(buffer, 0, sizeof(*buffer)); + + k_spin_unlock(&d->lock, key); +} + static int dma_trace_buffer_init(struct dma_trace_data *d) { struct dma_trace_buf *buffer = &d->dmatb; void *buf; - unsigned int flags; + k_spinlock_key_t key; + uint32_t addr_align; + int err; - /* allocate new buffer */ - buf = rballoc(0, SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, - DMA_TRACE_LOCAL_SIZE); + /* + * Keep the existing dtrace buffer to avoid memory leak, unlikely to + * happen if host correctly using the dma_trace_disable(). + * + * The buffer can not be freed up here as it is likely in use. + * The (re-)initialization will happen in dma_trace_start() when it is + * safe to do (the DMA is stopped) + */ + if (dma_trace_initialized(d)) + return 0; + + if (!d || !d->dc.dmac) { + mtrace_printf(LOG_LEVEL_ERROR, + "failed, no DMAC! d=%p", d); + return -ENODEV; + } +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_get_attribute(d->dc.dmac->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); +#else + err = dma_get_attribute_legacy(d->dc.dmac, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); +#endif + if (err < 0) + return err; + + /* For DMA to work properly the buffer must be correctly aligned */ + buf = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, + DMA_TRACE_LOCAL_SIZE, addr_align); if (!buf) { - trace_buffer_error("dma_trace_buffer_init() error: " - "alloc failed"); + mtrace_printf(LOG_LEVEL_ERROR, "alloc failed"); return -ENOMEM; } bzero(buf, DMA_TRACE_LOCAL_SIZE); - dcache_writeback_region(buf, DMA_TRACE_LOCAL_SIZE); + dcache_writeback_region((__sparse_force void __sparse_cache *)buf, DMA_TRACE_LOCAL_SIZE); /* initialise the DMA buffer, whole sequence in section */ - spin_lock_irq(&d->lock, flags); + key = k_spin_lock(&d->lock); buffer->addr = buf; buffer->size = DMA_TRACE_LOCAL_SIZE; @@ -206,71 +302,36 @@ static int dma_trace_buffer_init(struct dma_trace_data *d) buffer->end_addr = (char *)buffer->addr + buffer->size; buffer->avail = 0; - spin_unlock_irq(&d->lock, flags); - - return 0; -} + k_spin_unlock(&d->lock, key); -#if CONFIG_DMA_GW - -static int dma_trace_start(struct dma_trace_data *d) -{ - struct dma_sg_config config; - uint32_t elem_size, elem_addr, elem_num; - int err = 0; - - err = dma_copy_set_stream_tag(&d->dc, d->stream_tag); - if (err < 0) - return err; - - /* size of every trace record */ - elem_size = sizeof(uint64_t) * 2; - - /* Initialize address of local elem */ - elem_addr = (uint32_t)d->dmatb.addr; +#ifdef __ZEPHYR__ +#define ZEPHYR_VER_OPT " zephyr:" STRINGIFY(BUILD_VERSION) +#else +#define ZEPHYR_VER_OPT +#endif - /* the number of elem list */ - elem_num = DMA_TRACE_LOCAL_SIZE / elem_size; + /* STRINGIFY(SOF_SRC_HASH) is part of the format string so it + * goes to the .ldc file and does not go to the firmware + * binary. It will be different from SOF_SRC_HASH in case of + * mismatch. + */ +#define SOF_BANNER_COMMON \ + "FW ABI 0x%x DBG ABI 0x%x tags SOF:" SOF_GIT_TAG ZEPHYR_VER_OPT \ + " src hash 0x%08x (ldc hash " STRINGIFY(SOF_SRC_HASH) ")" - config.direction = DMA_DIR_LMEM_TO_HMEM; - config.src_width = sizeof(uint32_t); - config.dest_width = sizeof(uint32_t); - config.cyclic = 0; + /* It should be the very first sent log for easy identification. */ + mtrace_printf(LOG_LEVEL_INFO, + "SHM: " SOF_BANNER_COMMON, + SOF_ABI_VERSION, SOF_ABI_DBG_VERSION, SOF_SRC_HASH); - err = dma_sg_alloc(&config.elem_array, SOF_MEM_ZONE_SYS, - config.direction, - elem_num, elem_size, elem_addr, 0); - if (err < 0) - return err; + /* Use a different, DMA: prefix to ease identification of log files */ + tr_info(&dt_tr, + "DMA: " SOF_BANNER_COMMON, + SOF_ABI_VERSION, SOF_ABI_DBG_VERSION, SOF_SRC_HASH); - err = dma_set_config(d->dc.chan, &config); - if (err < 0) - return err; - - err = dma_start(d->dc.chan); - - return err; + return 0; } -static int dma_trace_get_avail_data(struct dma_trace_data *d, - struct dma_trace_buf *buffer, - int avail) -{ - /* there isn't DMA completion callback in GW DMA copying. - * so we send previous position always before the next copying - * for guaranteeing previous DMA copying is finished. - * This function will be called once every 500ms at least even - * if no new trace is filled. - */ - if (d->old_host_offset != d->posn.host_offset) { - ipc_msg_send(d->msg, &d->posn, false); - d->old_host_offset = d->posn.host_offset; - } - - /* align data to HD-DMA burst size */ - return ALIGN_DOWN(avail, d->dma_copy_align); -} -#else static int dma_trace_get_avail_data(struct dma_trace_data *d, struct dma_trace_buf *buffer, int avail) @@ -302,31 +363,22 @@ static int dma_trace_get_avail_data(struct dma_trace_data *d, return size; } -#endif +/** Invoked remotely by SOF_IPC_TRACE_DMA_PARAMS* Depends on + * dma_trace_init_complete() + */ int dma_trace_enable(struct dma_trace_data *d) { int err; - /* initialize dma trace buffer */ + /* Allocate and initialize the dma trace buffer if needed */ err = dma_trace_buffer_init(d); if (err < 0) - goto out; - -#if CONFIG_DMA_GW - /* - * GW DMA need finish DMA config and start before - * host driver trigger start DMA - */ - err = dma_trace_start(d); - if (err < 0) - goto out; -#endif + return err; /* validate DMA context */ if (!d->dc.dmac || !d->dc.chan) { - trace_buffer_error_atomic("dma_trace_enable() error: not " - "valid"); + tr_err_atomic(&dt_tr, "not valid"); err = -ENODEV; goto out; } @@ -335,11 +387,33 @@ int dma_trace_enable(struct dma_trace_data *d) schedule_task(&d->dmat_work, DMA_TRACE_PERIOD, DMA_TRACE_PERIOD); out: - platform_shared_commit(d, sizeof(*d)); + if (err < 0) + dma_trace_buffer_free(d); return err; } +void dma_trace_disable(struct dma_trace_data *d) +{ + /* cancel trace work */ + schedule_task_cancel(&d->dmat_work); + + if (d->dc.chan) { + dma_stop_legacy(d->dc.chan); + dma_channel_put_legacy(d->dc.chan); + d->dc.chan = NULL; + } + +#if (CONFIG_HOST_PTABLE) + /* Free up the host SG if it is set */ + if (d->host_size) { + dma_sg_free(NULL, &d->config.elem_array); + d->host_size = 0; + } +#endif +} + +/** Sends all pending DMA messages to mailbox (for emergencies) */ void dma_trace_flush(void *t) { struct dma_trace_data *trace_data = dma_trace_data_get(); @@ -349,10 +423,8 @@ void dma_trace_flush(void *t) int32_t wrap_count; int ret; - if (!trace_data || !trace_data->dmatb.addr) { - platform_shared_commit(trace_data, sizeof(*trace_data)); + if (!dma_trace_initialized(trace_data)) return; - } buffer = &trace_data->dmatb; avail = buffer->avail; @@ -371,8 +443,10 @@ void dma_trace_flush(void *t) (char *)buffer->addr; } + size = MIN(size, MAILBOX_TRACE_SIZE); + /* invalidate trace data */ - dcache_invalidate_region((void *)t, size); + dcache_invalidate_region((__sparse_force void __sparse_cache *)t, size); /* check for buffer wrap */ if ((char *)buffer->w_ptr - size < (char *)buffer->addr) { @@ -390,17 +464,18 @@ void dma_trace_flush(void *t) } /* writeback trace data */ - dcache_writeback_region((void *)t, size); + dcache_writeback_region((__sparse_force void __sparse_cache *)t, size); - platform_shared_commit(trace_data, sizeof(*trace_data)); } void dma_trace_on(void) { + if (!dma_trace_initialized(sof_get()->dmat)) + return; + struct dma_trace_data *trace_data = dma_trace_data_get(); if (trace_data->enabled) { - platform_shared_commit(trace_data, sizeof(*trace_data)); return; } @@ -408,7 +483,6 @@ void dma_trace_on(void) schedule_task(&trace_data->dmat_work, DMA_TRACE_PERIOD, DMA_TRACE_PERIOD); - platform_shared_commit(trace_data, sizeof(*trace_data)); } void dma_trace_off(void) @@ -416,14 +490,12 @@ void dma_trace_off(void) struct dma_trace_data *trace_data = dma_trace_data_get(); if (!trace_data->enabled) { - platform_shared_commit(trace_data, sizeof(*trace_data)); return; } schedule_task_cancel(&trace_data->dmat_work); trace_data->enabled = 0; - platform_shared_commit(trace_data, sizeof(*trace_data)); } static int dtrace_calc_buf_overflow(struct dma_trace_buf *buffer, @@ -449,12 +521,13 @@ static int dtrace_calc_buf_overflow(struct dma_trace_buf *buffer, return overflow; } +/** Ring buffer implementation, drops on overflow. */ static void dtrace_add_event(const char *e, uint32_t length) { struct dma_trace_data *trace_data = dma_trace_data_get(); struct dma_trace_buf *buffer = &trace_data->dmatb; uint32_t margin; - uint32_t overflow = 0; + uint32_t overflow; int ret; margin = dtrace_calc_buf_margin(buffer); @@ -470,16 +543,9 @@ static void dtrace_add_event(const char *e, uint32_t length) uint32_t tmp_dropped_entries = trace_data->dropped_entries; trace_data->dropped_entries = 0; - /* - * this trace_error invocation causes recursion, - * so after it we have to recalculate margin and - * overflow - */ - trace_error(0, "dtrace_add_event() error: " - "number of dropped logs = %u", - tmp_dropped_entries); - margin = dtrace_calc_buf_margin(buffer); - overflow = dtrace_calc_buf_overflow(buffer, length); + mtrace_printf(LOG_LEVEL_WARNING, + "number of dropped logs = %u", + tmp_dropped_entries); } } @@ -488,25 +554,29 @@ static void dtrace_add_event(const char *e, uint32_t length) /* check for buffer wrap */ if (margin > length) { /* no wrap */ - dcache_invalidate_region(buffer->w_ptr, length); + dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->w_ptr, + length); ret = memcpy_s(buffer->w_ptr, length, e, length); assert(!ret); - dcache_writeback_region(buffer->w_ptr, length); + dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, + length); buffer->w_ptr = (char *)buffer->w_ptr + length; } else { /* data is bigger than remaining margin so we wrap */ - dcache_invalidate_region(buffer->w_ptr, margin); + dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->w_ptr, + margin); ret = memcpy_s(buffer->w_ptr, margin, e, margin); assert(!ret); - dcache_writeback_region(buffer->w_ptr, margin); + dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, + margin); buffer->w_ptr = buffer->addr; - dcache_invalidate_region(buffer->w_ptr, + dcache_invalidate_region((__sparse_force void __sparse_cache *)buffer->w_ptr, length - margin); ret = memcpy_s(buffer->w_ptr, length - margin, e + margin, length - margin); assert(!ret); - dcache_writeback_region(buffer->w_ptr, + dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->w_ptr, length - margin); buffer->w_ptr = (char *)buffer->w_ptr + length - margin; } @@ -518,37 +588,35 @@ static void dtrace_add_event(const char *e, uint32_t length) trace_data->dropped_entries++; } - platform_shared_commit(trace_data, sizeof(*trace_data)); } +/** Main dma-trace entry point */ void dtrace_event(const char *e, uint32_t length) { struct dma_trace_data *trace_data = dma_trace_data_get(); struct dma_trace_buf *buffer = NULL; - unsigned long flags; + k_spinlock_key_t key; - if (!trace_data || !trace_data->dmatb.addr || + if (!dma_trace_initialized(trace_data) || length > DMA_TRACE_LOCAL_SIZE / 8 || length == 0) { - platform_shared_commit(trace_data, sizeof(*trace_data)); return; } buffer = &trace_data->dmatb; - spin_lock_irq(&trace_data->lock, flags); + key = k_spin_lock(&trace_data->lock); dtrace_add_event(e, length); - /* if DMA trace copying is working or slave core + /* if DMA trace copying is working or secondary core * don't check if local buffer is half full */ if (trace_data->copy_in_progress || - cpu_get_id() != PLATFORM_MASTER_CORE_ID) { - platform_shared_commit(trace_data, sizeof(*trace_data)); - spin_unlock_irq(&trace_data->lock, flags); + cpu_get_id() != PLATFORM_PRIMARY_CORE_ID) { + k_spin_unlock(&trace_data->lock, key); return; } - spin_unlock_irq(&trace_data->lock, flags); + k_spin_unlock(&trace_data->lock, key); /* schedule copy now if buffer > 50% full */ if (trace_data->enabled && @@ -561,16 +629,14 @@ void dtrace_event(const char *e, uint32_t length) trace_data->copy_in_progress = 1; } - platform_shared_commit(trace_data, sizeof(*trace_data)); } void dtrace_event_atomic(const char *e, uint32_t length) { struct dma_trace_data *trace_data = dma_trace_data_get(); - if (!trace_data || !trace_data->dmatb.addr || + if (!dma_trace_initialized(trace_data) || length > DMA_TRACE_LOCAL_SIZE / 8 || length == 0) { - platform_shared_commit(trace_data, sizeof(*trace_data)); return; } diff --git a/src/trace/trace.c b/src/trace/trace.c index fc2fbf0491fd..bc17c848a902 100644 --- a/src/trace/trace.c +++ b/src/trace/trace.c @@ -4,29 +4,58 @@ // // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> // Artur Kloniecki <arturx.kloniecki@linux.intel.com> - -#include <sof/debug/panic.h> -#include <sof/drivers/timer.h> -#include <sof/lib/alloc.h> -#include <sof/lib/cache.h> +// Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <rtos/timer.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> #include <sof/lib/cpu.h> #include <sof/lib/mailbox.h> #include <sof/lib/memory.h> #include <sof/platform.h> -#include <sof/string.h> -#include <sof/sof.h> -#include <sof/spinlock.h> +#include <rtos/string.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> #include <sof/trace/dma-trace.h> -#include <sof/trace/preproc.h> #include <sof/trace/trace.h> #include <ipc/topology.h> #include <user/trace.h> +#include <stdarg.h> #include <stdint.h> +/* every trace calls uses IPC context in this file */ +LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx dt_tr; + +#if CONFIG_TRACE_FILTERING_ADAPTIVE +struct recent_log_entry { + uint32_t entry_id; + uint64_t message_ts; + uint64_t first_suppression_ts; + uint32_t trigger_count; +}; + +struct recent_trace_context { + struct recent_log_entry recent_entries[CONFIG_TRACE_RECENT_ENTRIES_COUNT]; +}; +#endif /* CONFIG_TRACE_FILTERING_ADAPTIVE */ + +/** MAILBOX_TRACE_BASE ring buffer */ struct trace { - uint32_t pos ; /* trace position */ + uintptr_t pos ; /**< offset of the next byte to write */ uint32_t enable; - spinlock_t lock; /* locking mechanism */ +#if CONFIG_TRACE_FILTERING_ADAPTIVE + bool user_filter_override; /* whether filtering was overridden by user or not */ +#endif /* CONFIG_TRACE_FILTERING_ADAPTIVE */ + struct k_spinlock lock; /* locking mechanism */ + +#if CONFIG_TRACE_FILTERING_ADAPTIVE + struct recent_trace_context trace_core_context[CONFIG_CORE_COUNT]; +#endif }; /* calculates total message size, both header and payload in bytes */ @@ -43,176 +72,394 @@ struct trace { #define TRACE_ID_MASK ((1 << TRACE_ID_LENGTH) - 1) -static void put_header(uint32_t *dst, uint32_t id_0, +static void put_header(void *dst, const struct sof_uuid_entry *uid, uint32_t id_1, uint32_t id_2, uint32_t entry, uint64_t timestamp) { - struct timer *timer = timer_get(); + struct dma_trace_data *trace_data = dma_trace_data_get(); + /* Support very early tracing */ + uint64_t delta = dma_trace_initialized(trace_data) ? trace_data->time_delta : 0; struct log_entry_header header; int ret; - header.uid = id_0; + header.uid = (uintptr_t)uid; header.id_0 = id_1 & TRACE_ID_MASK; header.id_1 = id_2 & TRACE_ID_MASK; header.core_id = cpu_get_id(); - header.timestamp = timestamp + timer->delta; + header.timestamp = timestamp + delta; header.log_entry_address = entry; ret = memcpy_s(dst, sizeof(header), &header, sizeof(header)); assert(!ret); +} + +#ifndef __ZEPHYR__ +/** Ring buffer for the mailbox trace */ +void mtrace_event(const char *data, uint32_t length) +{ + struct trace *trace = trace_get(); + char *t = (char *)MAILBOX_TRACE_BASE; + const int32_t available = MAILBOX_TRACE_SIZE - trace->pos; + + if (available < length) { /* wrap */ + memset(t + trace->pos, 0xff, available); + dcache_writeback_region((__sparse_force char __sparse_cache *)t + trace->pos, + available); + trace->pos = 0; + } + + memcpy_s(t + trace->pos, MAILBOX_TRACE_SIZE - trace->pos, + data, length); + dcache_writeback_region((__sparse_force char __sparse_cache *)t + trace->pos, length); + trace->pos += length; +} +#endif /* __ZEPHYR__ */ + +#if CONFIG_TRACE_FILTERING_VERBOSITY +/** + * \brief Runtime trace filtering based on verbosity level + * \param lvl log level (LOG_LEVEL_ ERROR, INFO, DEBUG ...) + * \param uuid uuid address + * \return false when trace is filtered out, otherwise true + */ +static inline bool trace_filter_verbosity(uint32_t lvl, const struct tr_ctx *ctx) +{ + STATIC_ASSERT(LOG_LEVEL_CRITICAL < LOG_LEVEL_VERBOSE, + LOG_LEVEL_CRITICAL_MUST_HAVE_LOWEST_VALUE); + return lvl <= ctx->level; +} +#endif /* CONFIG_TRACE_FILTERING_VERBOSITY */ + +#if CONFIG_TRACE_FILTERING_ADAPTIVE +/** Report how many times an entry was suppressed and clear it. */ +static void emit_suppressed_entry(struct recent_log_entry *entry) +{ + _log_message(trace_log_unfiltered, false, LOG_LEVEL_INFO, _TRACE_INV_CLASS, &dt_tr, + _TRACE_INV_ID, _TRACE_INV_ID, "Suppressed %u similar messages: %pQ", + entry->trigger_count - CONFIG_TRACE_BURST_COUNT, + (void *)entry->entry_id); + + memset(entry, 0, sizeof(*entry)); +} + +/** Flush entries that have not been seen again in the last + * CONFIG_TRACE_RECENT_TIME_THRESHOLD microseconds before current_ts. + */ +static void emit_recent_entries(uint64_t current_ts) +{ + struct trace *trace = trace_get(); + struct recent_log_entry *recent_entries = + trace->trace_core_context[cpu_get_id()].recent_entries; + int i; + + /* Check if any tracked entries were dormant long enough to unsuppress them */ + for (i = 0; i < CONFIG_TRACE_RECENT_ENTRIES_COUNT; i++) { + if (recent_entries[i].entry_id) { + if (current_ts - recent_entries[i].message_ts > + CONFIG_TRACE_RECENT_TIME_THRESHOLD) { + if (recent_entries[i].trigger_count > CONFIG_TRACE_BURST_COUNT) + emit_suppressed_entry(&recent_entries[i]); + else + memset(&recent_entries[i], 0, sizeof(recent_entries[i])); + } + } + } - platform_shared_commit(timer, sizeof(*timer)); } -static void mtrace_event(const char *data, uint32_t length) +/** + * \brief Runtime trace flood suppression + * \param log_level log verbosity level + * \param entry ID of log entry + * \param message_ts message timestamp + * \return true when the message must be printed by the caller because it was not filtered + */ +static bool trace_filter_flood(uint32_t log_level, uint32_t entry, uint64_t message_ts) { struct trace *trace = trace_get(); - volatile char *t; - uint32_t i, available; + struct recent_log_entry *recent_entries = + trace->trace_core_context[cpu_get_id()].recent_entries; + struct recent_log_entry *oldest_entry = recent_entries; + int i; + + /* don't attempt to suppress debug messages using this method, it would be uneffective */ + if (log_level >= LOG_LEVEL_DEBUG) + return true; + + /* check if same log entry was sent recently */ + for (i = 0; i < CONFIG_TRACE_RECENT_ENTRIES_COUNT; i++) { + /* Identify the oldest (or empty) entry to evict if we have no match */ + if (oldest_entry->first_suppression_ts > recent_entries[i].first_suppression_ts) + oldest_entry = &recent_entries[i]; + + if (recent_entries[i].entry_id == entry) { + /* We have a match but include this message in this burst only if the + * burst: + - 1. hasn't lasted for too long; + - 2. hasn't been quiet for too long. + */ + if (message_ts - recent_entries[i].first_suppression_ts < + CONFIG_TRACE_RECENT_MAX_TIME && + message_ts - recent_entries[i].message_ts < + CONFIG_TRACE_RECENT_TIME_THRESHOLD) { + recent_entries[i].trigger_count++; + /* Refresh last seen time */ + recent_entries[i].message_ts = message_ts; + + /* Allow the start of a burst to be printed normally */ + return recent_entries[i].trigger_count <= CONFIG_TRACE_BURST_COUNT; + } + + /* Emit and clear this burst */ + if (recent_entries[i].trigger_count > CONFIG_TRACE_BURST_COUNT) + emit_suppressed_entry(&recent_entries[i]); + else + memset(&recent_entries[i], 0, sizeof(recent_entries[i])); + + return true; + } + } - available = MAILBOX_TRACE_SIZE - trace->pos; + /* Make room for tracking new entry, by emitting the oldest one in the filter */ + if (oldest_entry->entry_id && oldest_entry->trigger_count > CONFIG_TRACE_BURST_COUNT) + emit_suppressed_entry(oldest_entry); - t = (volatile char *)(MAILBOX_TRACE_BASE); + /* Start a new burst */ + oldest_entry->entry_id = entry; + oldest_entry->message_ts = message_ts; + oldest_entry->first_suppression_ts = message_ts; + oldest_entry->trigger_count = 1; - /* write until we run out of space */ - for (i = 0; i < available && i < length; i++) - t[trace->pos + i] = data[i]; + return true; +} +#endif /* CONFIG_TRACE_FILTERING_ADAPTIVE */ - dcache_writeback_region((void *)&t[trace->pos], i); - trace->pos += length; +/** Implementation shared and invoked by both adaptive filtering and + * not. Serializes events into trace messages and passes them to + * dtrace_event() + */ +static void dma_trace_log(bool send_atomic, uint32_t log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list vargs) +{ + uint32_t data[MESSAGE_SIZE_DWORDS(_TRACE_EVENT_MAX_ARGUMENT_COUNT)]; + const int message_size = MESSAGE_SIZE(arg_count); + int i; - /* if there was more data than space available, wrap back */ - if (length > available) { - for (i = 0; i < length - available; i++) - t[i] = data[available + i]; + /* fill log content. arg_count is in the dictionary. */ + put_header(data, ctx->uuid_p, id_1, id_2, log_entry, sof_cycle_get_64_safe()); + + for (i = 0; i < arg_count; ++i) + data[PAYLOAD_OFFSET(i)] = va_arg(vargs, uint32_t); + + /* send event by */ + if (send_atomic) + dtrace_event_atomic((const char *)data, message_size); + else + dtrace_event((const char *)data, message_size); + +} + +void trace_log_unfiltered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list vl) +{ + struct trace *trace = trace_get(); - dcache_writeback_region((void *)t, i); - trace->pos = i; + if (!trace->enable) { + return; } - platform_shared_commit(trace, sizeof(*trace)); + dma_trace_log(send_atomic, (uint32_t)log_entry, ctx, lvl, id_1, id_2, arg_count, vl); } -#define _TRACE_EVENT_NTH_IMPL_PAYLOAD_STEP(i, _) \ - dt[PAYLOAD_OFFSET(i)] = META_CONCAT(param, i); - -#define _TRACE_EVENT_NTH_PAYLOAD_IMPL(arg_count) \ - META_SEQ_FROM_0_TO(arg_count, _TRACE_EVENT_NTH_IMPL_PAYLOAD_STEP) - - /* _trace_event function with poor people's version of constexpr if */ -#define _TRACE_EVENT_NTH_IMPL(is_mbox, is_atomic, arg_count) \ -_TRACE_EVENT_NTH(META_CONCAT( \ -/*if is_mbox , append _mbox to function name*/ \ -META_IF_ELSE(is_mbox)(_mbox)(), \ -/*if is_atomic, append _atomic to function name*/ \ -META_IF_ELSE(is_atomic)(_atomic)() \ -), arg_count) \ -{ \ - uint32_t dt[MESSAGE_SIZE_DWORDS(arg_count)]; \ - struct trace *trace = trace_get(); \ - META_IF_ELSE(is_mbox) \ - ( \ - META_IF_ELSE(is_atomic)()(unsigned long flags;) \ - )() \ - \ - if (!trace->enable) { \ - platform_shared_commit(trace, sizeof(*trace)); \ - return; \ - } \ - \ - put_header(dt, id_0, id_1, id_2, log_entry, \ - platform_timer_get(timer_get())); \ - \ - _TRACE_EVENT_NTH_PAYLOAD_IMPL(arg_count) \ - META_IF_ELSE(is_atomic) \ - (dtrace_event_atomic) \ - (dtrace_event) \ - ((const char *)dt, MESSAGE_SIZE(arg_count)); \ - /* send event by mail box too. */ \ - META_IF_ELSE(is_mbox) \ - ( \ - META_IF_ELSE(is_atomic)()( \ - spin_lock_irq(&trace->lock, flags); \ - ) \ - mtrace_event((const char *)dt, MESSAGE_SIZE(arg_count));\ - \ - META_IF_ELSE(is_atomic)()(spin_unlock_irq(&trace->lock, \ - flags);) \ - )() \ +void trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, va_list vl) +{ + struct trace *trace = trace_get(); + + if (!trace->enable) { + return; + } + +#if CONFIG_TRACE_FILTERING_VERBOSITY + if (!trace_filter_verbosity(lvl, ctx)) + return; +#endif /* CONFIG_TRACE_FILTERING_VERBOSITY */ + +#if CONFIG_TRACE_FILTERING_ADAPTIVE + if (!trace->user_filter_override) { + const uint64_t current_ts = sof_cycle_get_64_safe(); + + emit_recent_entries(current_ts); + + if (!trace_filter_flood(lvl, (uint32_t)log_entry, current_ts)) + return; + } +#endif /* CONFIG_TRACE_FILTERING_ADAPTIVE */ + + dma_trace_log(send_atomic, (uint32_t)log_entry, ctx, lvl, id_1, id_2, arg_count, vl); } -#define _TRACE_EVENT_NTH_IMPL_GROUP(arg_count) \ - /* send trace events only to the local trace buffer */ \ - _TRACE_EVENT_NTH_IMPL(0, 0, arg_count) \ - _TRACE_EVENT_NTH_IMPL(0, 1, arg_count) \ - /* send trace events to the local trace buffer and mailbox */ \ - _TRACE_EVENT_NTH_IMPL(1, 0, arg_count) \ - _TRACE_EVENT_NTH_IMPL(1, 1, arg_count) +struct sof_ipc_trace_filter_elem *trace_filter_fill(struct sof_ipc_trace_filter_elem *elem, + struct sof_ipc_trace_filter_elem *end, + struct trace_filter *filter) +{ + filter->log_level = -1; + filter->uuid_id = 0; + filter->comp_id = -1; + filter->pipe_id = -1; + + while (elem <= end) { + switch (elem->key & SOF_IPC_TRACE_FILTER_ELEM_TYPE_MASK) { + case SOF_IPC_TRACE_FILTER_ELEM_SET_LEVEL: + filter->log_level = elem->value; + break; + case SOF_IPC_TRACE_FILTER_ELEM_BY_UUID: + filter->uuid_id = elem->value; + break; + case SOF_IPC_TRACE_FILTER_ELEM_BY_COMP: + filter->comp_id = elem->value; + break; + case SOF_IPC_TRACE_FILTER_ELEM_BY_PIPE: + filter->pipe_id = elem->value; + break; + default: + tr_err(&ipc_tr, "Invalid SOF_IPC_TRACE_FILTER_ELEM 0x%x", + elem->key); + return NULL; + } + + /* each filter set must be terminated with FIN flag and have new log level */ + if (elem->key & SOF_IPC_TRACE_FILTER_ELEM_FIN) { + if (filter->log_level < 0) { + tr_err(&ipc_tr, "Each trace filter set must specify new log level"); + return NULL; + } else { + return elem + 1; + } + } + + ++elem; + } + tr_err(&ipc_tr, "Trace filter elements set is not properly terminated"); + return NULL; +} -/* Implementation of - * void _trace_event1( uintptr_t log_entry, uint32_t ids...) {...} - * void _trace_event_mbox1( uintptr_t log_entry, uint32_t ids...) {...} - * void _trace_event_atomic1( uintptr_t log_entry, uint32_t ids...) {...} - * void _trace_event_mbox_atomic1(uintptr_t log_entry, uint32_t ids...) {...} - */ -_TRACE_EVENT_NTH_IMPL_GROUP(0) - -/* Implementation of - * void _trace_event1( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox1( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_atomic1( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox_atomic1(uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - */ -_TRACE_EVENT_NTH_IMPL_GROUP(1) - -/* Implementation of - * void _trace_event2( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox2( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_atomic2( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox_atomic2(uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - */ -_TRACE_EVENT_NTH_IMPL_GROUP(2) - -/* Implementation of - * void _trace_event3( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox3( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_atomic3( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox_atomic3(uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - */ -_TRACE_EVENT_NTH_IMPL_GROUP(3) - -/* Implementation of - * void _trace_event4( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox4( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_atomic4( uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - * void _trace_event_mbox_atomic4(uintptr_t log_entry, uint32_t ids..., - * uint32_t params...) {...} - */ -_TRACE_EVENT_NTH_IMPL_GROUP(4) +/* update global components, which tr_ctx is stored inside special section */ +static int trace_filter_update_global(int32_t log_level, uint32_t uuid_id) +{ + int cnt = 0; +#if !defined(CONFIG_LIBRARY) + extern void *_trace_ctx_start; + extern void *_trace_ctx_end; + struct tr_ctx *ptr = (struct tr_ctx *)&_trace_ctx_start; + struct tr_ctx *end = (struct tr_ctx *)&_trace_ctx_end; + + /* iterate over global `tr_ctx` entries located in their own section */ + /* cppcheck-suppress comparePointers */ + while (ptr < end) { + /* + * when looking for specific uuid element, + * then find, update and stop searching + */ + if ((uintptr_t)ptr->uuid_p == uuid_id) { + ptr->level = log_level; + return 1; + } + /* otherwise each element should be updated */ + if (!ptr->uuid_p) { + ptr->level = log_level; + ++cnt; + } + ++ptr; + } +#endif + + return cnt; +} + +/* return trace context from any ipc component type */ +static struct tr_ctx *trace_filter_ipc_comp_context(struct ipc_comp_dev *icd) +{ + switch (icd->type) { + case COMP_TYPE_COMPONENT: + return &icd->cd->tctx; + case COMP_TYPE_BUFFER: + return &icd->cb->tctx; + case COMP_TYPE_PIPELINE: + return &icd->pipeline->tctx; + /* each COMP_TYPE must be specified */ + default: + tr_err(&ipc_tr, "Unknown trace context for ipc component type 0x%X", + icd->type); + return NULL; + } +} -void trace_flush(void) +/* update ipc components, wchich tr_ctx may be read from ipc_comp_dev structure */ +static int trace_filter_update_instances(int32_t log_level, uint32_t uuid_id, + int32_t pipe_id, int32_t comp_id) +{ + struct ipc *ipc = ipc_get(); + struct ipc_comp_dev *icd; + struct list_item *clist; + struct tr_ctx *ctx; + bool correct_comp; + int cnt = 0; + + /* compare each ipc component with filter settings and update log level after pass */ + list_for_item(clist, &ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + ctx = trace_filter_ipc_comp_context(icd); + if (!ctx) + return -EINVAL; + correct_comp = comp_id == -1 || icd->id == comp_id; /* todo: icd->topo_id */ + correct_comp &= uuid_id == 0 || (uintptr_t)ctx->uuid_p == uuid_id; + correct_comp &= pipe_id == -1 || ipc_comp_pipe_id(icd) == pipe_id; + if (correct_comp) { + ctx->level = log_level; + ++cnt; + } + + } + return cnt; +} + +int trace_filter_update(const struct trace_filter *filter) +{ + int ret = 0; +#if CONFIG_TRACE_FILTERING_ADAPTIVE + struct trace *trace = trace_get(); + + if (!trace->user_filter_override) { + trace->user_filter_override = true; + tr_info(&ipc_tr, "Adaptive filtering disabled by user"); + } +#endif /* CONFIG_TRACE_FILTERING_ADAPTIVE */ + + /* validate log level, LOG_LEVEL_CRITICAL has low value, LOG_LEVEL_VERBOSE high */ + if (filter->log_level < LOG_LEVEL_CRITICAL || + filter->log_level > LOG_LEVEL_VERBOSE) + return -EINVAL; + + /* update `*`, `name*` or global `name` */ + if (filter->pipe_id == -1 && filter->comp_id == -1) + ret = trace_filter_update_global(filter->log_level, filter->uuid_id); + + /* update `*`, `name*`, `nameX.*` or `nameX.Y`, `name` may be '*' */ + ret += trace_filter_update_instances(filter->log_level, filter->uuid_id, + filter->pipe_id, filter->comp_id); + return ret > 0 ? ret : -EINVAL; +} + +/** Sends all pending DMA messages to mailbox (for emergencies) */ +void trace_flush_dma_to_mbox(void) { struct trace *trace = trace_get(); volatile uint64_t *t; - uint32_t flags; + k_spinlock_key_t key; - spin_lock_irq(&trace->lock, flags); + key = k_spin_lock(&trace->lock); /* get mailbox position */ t = (volatile uint64_t *)(MAILBOX_TRACE_BASE + trace->pos); @@ -220,54 +467,113 @@ void trace_flush(void) /* flush dma trace messages */ dma_trace_flush((void *)t); - platform_shared_commit(trace, sizeof(*trace)); - - spin_unlock_irq(&trace->lock, flags); + k_spin_unlock(&trace->lock, key); } void trace_on(void) { struct trace *trace = trace_get(); - uint32_t flags; + k_spinlock_key_t key; - spin_lock_irq(&trace->lock, flags); + key = k_spin_lock(&trace->lock); trace->enable = 1; dma_trace_on(); - platform_shared_commit(trace, sizeof(*trace)); - - spin_unlock_irq(&trace->lock, flags); + k_spin_unlock(&trace->lock, key); } void trace_off(void) { struct trace *trace = trace_get(); - uint32_t flags; + k_spinlock_key_t key; - spin_lock_irq(&trace->lock, flags); + key = k_spin_lock(&trace->lock); trace->enable = 0; dma_trace_off(); - platform_shared_commit(trace, sizeof(*trace)); - - spin_unlock_irq(&trace->lock, flags); + k_spin_unlock(&trace->lock, key); } void trace_init(struct sof *sof) { - dma_trace_init_early(sof); + sof->trace = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*sof->trace)); + if (!sof->trace) { + mtrace_printf(LOG_LEVEL_ERROR, "allocation failed"); + sof_panic(SOF_IPC_PANIC_IPC); + } - sof->trace = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*sof->trace)); sof->trace->enable = 1; sof->trace->pos = 0; - spinlock_init(&sof->trace->lock); - - platform_shared_commit(sof->trace, sizeof(*sof->trace)); - +#if CONFIG_TRACE_FILTERING_ADAPTIVE + sof->trace->user_filter_override = false; +#endif /* CONFIG_TRACE_FILTERING_ADAPTIVE */ + k_spinlock_init(&sof->trace->lock); + +#ifndef __ZEPHYR__ + /* Zephyr owns and has already initialized this buffer (and + * likely has already logged to it by the time we get here). + * Don't touch. + */ bzero((void *)MAILBOX_TRACE_BASE, MAILBOX_TRACE_SIZE); - dcache_writeback_invalidate_region((void *)MAILBOX_TRACE_BASE, + dcache_writeback_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_TRACE_BASE, MAILBOX_TRACE_SIZE); +#endif + + dma_trace_init_early(sof); +} + +static void mtrace_dict_entry_vl(bool atomic_context, uint32_t dict_entry_address, + int n_args, va_list ap) +{ + int i; + char packet[MESSAGE_SIZE(_TRACE_EVENT_MAX_ARGUMENT_COUNT)]; + uint32_t *args = (uint32_t *)&packet[MESSAGE_SIZE(0)]; + const uint64_t tstamp = sof_cycle_get_64_safe(); + + put_header(packet, dt_tr.uuid_p, _TRACE_INV_ID, _TRACE_INV_ID, + dict_entry_address, tstamp); + + for (i = 0; i < MIN(n_args, _TRACE_EVENT_MAX_ARGUMENT_COUNT); i++) + args[i] = va_arg(ap, uint32_t); + + if (atomic_context) { + mtrace_event(packet, MESSAGE_SIZE(n_args)); + } else { + struct trace * const trace = trace_get(); + k_spinlock_key_t key; + + key = k_spin_lock(&trace->lock); + mtrace_event(packet, MESSAGE_SIZE(n_args)); + k_spin_unlock(&trace->lock, key); + } +} + +void mtrace_dict_entry(bool atomic_context, uint32_t dict_entry_address, int n_args, ...) +{ + va_list ap; + + va_start(ap, n_args); + mtrace_dict_entry_vl(atomic_context, dict_entry_address, n_args, ap); + va_end(ap); +} + +void _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry, + const struct tr_ctx *ctx, const uint32_t lvl, + uint32_t id_1, uint32_t id_2, int arg_count, ...) +{ + va_list ap; + +#ifndef __ZEPHYR__ /* for Zephyr see _log_nodict() in trace.h */ + if (lvl <= MTRACE_DUPLICATION_LEVEL) { + va_start(ap, arg_count); + mtrace_dict_entry_vl(atomic, (uint32_t)log_entry, arg_count, ap); + va_end(ap); + } +#endif + + va_start(ap, arg_count); + sofdict_logf(atomic, log_entry, ctx, lvl, id_1, id_2, arg_count, ap); + va_end(ap); } diff --git a/submanifests/README.txt b/submanifests/README.txt new file mode 100644 index 000000000000..db2f61692fe9 --- /dev/null +++ b/submanifests/README.txt @@ -0,0 +1,12 @@ +This directory can contain additional west manifest files. Any files +in this directory will be included in the main west.yml file sorted by +filename. + +For more details about how this works, see this part of the west +documentation: + +https://docs.zephyrproject.org/latest/guides/west/manifest.html#example-2-2-downstream-with-directory-of-manifest-files + +Note: do not delete this file if there is no other content in submanifests directory. +Submanifests directory must exist for west update command to work (even if does not contain any actual manifests). +This is a known bug, see: https://github.com/zephyrproject-rtos/west/issues/594 diff --git a/submanifests/sof-ci-jenkins/zephyr-override-template.yml b/submanifests/sof-ci-jenkins/zephyr-override-template.yml new file mode 100644 index 000000000000..f9b0f5f99763 --- /dev/null +++ b/submanifests/sof-ci-jenkins/zephyr-override-template.yml @@ -0,0 +1,27 @@ +--- +# This file is used by sof-ci/jenkins (Linux CI) like this: +# +# sed -e 's/=sof_zephyr_revision_override=/zephyr_version_to_test/' \ +# submanifests/sof-ci-jenkins/zephyr-override-template.yml \ +# > submanifests/50-sof-ci-jenkins-zephyr-override.yml +# +# where 'zephyr_version_to_test' is a fetchable git version (branch, tag, +# complete SHA1,...) +# You can override this substitution by changing the revision: below. +# +# The number prefix '50-' is just an example, you must adjust it if you +# use other submanifests/*.yml files. West sorts submanifests/*.yml +# files before reading them, see west's documentation currently hosted +# on the Zephyr website. + +manifest: + projects: + # override zephyr project in west.yml + - name: zephyr + url: https://github.com/zephyrproject-rtos/zephyr + revision: =sof_zephyr_revision_override= + import: + # Download only what sof-ci-jenkins uses to save a lot of time + name-allowlist: + - hal_xtensa + - hal_nxp diff --git a/test/cmocka/CMakeLists.txt b/test/cmocka/CMakeLists.txt index b7f014a56f67..5e3591df6a61 100644 --- a/test/cmocka/CMakeLists.txt +++ b/test/cmocka/CMakeLists.txt @@ -4,6 +4,25 @@ include(ExternalProject) add_library(cmocka STATIC IMPORTED) +# Default use XCC unless user asks for GCC +if(BUILD_UNIT_TESTS_HOST) + set(UT_CC_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/cmocka-host-gcc-toolchain.cmake) + set(UT_TOOLCHAIN "") + # TODO: add an option to support valgrind. + # In the mean time use scripts/run-mocks.sh for valgrind. + set(SIMULATOR "") +elseif(BUILD_UNIT_TESTS_XTENSA_GCC) + # GCC xtensa build for future Qemu. + set(UT_CC_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/cmocka-xtensa-gcc-toolchain.cmake) + set(UT_TOOLCHAIN "-DTOOLCHAIN=${TOOLCHAIN}") + set(SIMULATOR xt-run --exit_with_target_code) +else() + # xtensa XCC build for xt-run. + set(UT_CC_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/cmocka-xtensa-xt-toolchain.cmake) + set(UT_TOOLCHAIN "") + set(SIMULATOR xt-run --exit_with_target_code) +endif() + if(DEFINED CMOCKA_DIRECTORY) # Prebuilt Cmocka lib set_property(TARGET cmocka PROPERTY IMPORTED_LOCATION "${CMOCKA_DIRECTORY}/lib/libcmocka-static.a") @@ -19,12 +38,13 @@ else() PREFIX "${PROJECT_BINARY_DIR}/cmocka_git" BINARY_DIR ${cmocka_binary_directory} CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release - -DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmocka-xtensa-xt-toolchain.cmake + -DCMAKE_TOOLCHAIN_FILE=${UT_CC_CONFIG} -DWITH_SHARED_LIB=OFF -DWITH_STATIC_LIB=ON -DWITH_EXAMPLES=OFF -DWITH_POSITION_INDEPENDENT_CODE=OFF -DWITH_TINY_CONFIG=ON + ${UT_TOOLCHAIN} BUILD_BYPRODUCTS "${cmocka_binary_directory}/src/libcmocka-static.a" INSTALL_COMMAND "" ) @@ -39,7 +59,10 @@ endif() if(CONFIG_CAVS) target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/intel/cavs/include) +elseif(CONFIG_ACE) + target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/intel/ace/include) endif() +target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/arch/xtos-wrapper/include) # linker script, just for log entries set(memory_mock_lds_in ${PROJECT_SOURCE_DIR}/test/cmocka/memory_mock.x.in) @@ -60,6 +83,14 @@ add_library(common_mock STATIC ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mock add_dependencies(common_mock cmocka) target_include_directories(common_mock PRIVATE ${CMOCKA_INCLUDE_DIR}) target_link_libraries(common_mock PRIVATE sof_options) +target_link_libraries(common_mock PRIVATE m) + +# xtensa GCC require some extra options to link +if(BUILD_UNIT_TESTS_XTENSA_GCC) + target_link_libraries(common_mock PRIVATE gcc) + target_link_libraries(common_mock PRIVATE c) + target_link_libraries(common_mock PRIVATE -nostdlib) +endif() link_libraries(common_mock) sof_append_relative_path_definitions(common_mock) @@ -79,7 +110,16 @@ function(cmocka_test test_name) # Cmocka requires this define for stdint.h that defines uintptr target_compile_definitions(${test_name} PRIVATE -D_UINTPTR_T_DEFINED) - add_test(NAME ${test_name} COMMAND xt-run --exit_with_target_code ${test_name}) + # Enable features those would be disabled in some platforms + target_compile_definitions(${test_name} PRIVATE -DCONFIG_NUMBERS_NORM -DCONFIG_NUMBERS_VECTOR_FIND) + + # Skip running alloc test on HOST until it's fixed (it passes and is run + # with xt-run) + if( "alloc" STREQUAL "${test_name}" AND BUILD_UNIT_TESTS_HOST) + message(WARNING "SKIP alloc test on HOST, built but not run") + else() + add_test(NAME ${test_name} COMMAND ${SIMULATOR} ${test_name}) + endif() sof_append_relative_path_definitions(${test_name}) endfunction() diff --git a/test/cmocka/cmocka-host-gcc-toolchain.cmake b/test/cmocka/cmocka-host-gcc-toolchain.cmake new file mode 100644 index 000000000000..e391cd43c4ef --- /dev/null +++ b/test/cmocka/cmocka-host-gcc-toolchain.cmake @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-3-Clause + +message(STATUS "Preparing Host GCC toolchain") + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_ASM_COMPILER_FORCED 1) +set(CMAKE_C_COMPILER_FORCED 1) + +set(CMAKE_ASM_COMPILER_ID GNU) +set(CMAKE_C_COMPILER_ID GNU) + +set(CMAKE_C_COMPILER gcc) + +find_program(CMAKE_LD NAMES "$ld" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_AR NAMES "$ar" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_OBJCOPY NAMES "objcopy" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_OBJDUMP NAMES "objdump" PATHS ENV PATH NO_DEFAULT_PATH) + +set(CMAKE_FIND_ROOT_PATH ".") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Cmocka is written in C99, but for some reason it sets this flag, only on Posix +# We set up it here, because our system is Generic +add_definitions("-std=gnu99") diff --git a/test/cmocka/cmocka-xtensa-gcc-toolchain.cmake b/test/cmocka/cmocka-xtensa-gcc-toolchain.cmake new file mode 100644 index 000000000000..32183a37c82f --- /dev/null +++ b/test/cmocka/cmocka-xtensa-gcc-toolchain.cmake @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: BSD-3-Clause + +message(STATUS "Preparing Xtensa GCC toolchain using ${TOOLCHAIN}") + +set(CROSS_COMPILE "${TOOLCHAIN}-") + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_ASM_COMPILER_FORCED 1) +set(CMAKE_C_COMPILER_FORCED 1) + +set(CMAKE_ASM_COMPILER_ID GNU) +set(CMAKE_C_COMPILER_ID GNU) + +set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc) + +# required for checking flags +set(CMAKE_REQUIRED_FLAGS "-nostdlib") + +find_program(CMAKE_LD NAMES "${CROSS_COMPILE}ld" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_AR NAMES "${CROSS_COMPILE}ar" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_OBJCOPY NAMES "${CROSS_COMPILE}objcopy" PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_OBJDUMP NAMES "${CROSS_COMPILE}objdump" PATHS ENV PATH NO_DEFAULT_PATH) + +set(CMAKE_FIND_ROOT_PATH ".") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Cmocka is written in C99, but for some reason it sets this flag, only on Posix +# We set up it here, because our system is Generic +add_definitions("-std=gnu99") diff --git a/test/cmocka/include/cmocka_chirp_2ch.h b/test/cmocka/include/cmocka_chirp_2ch.h new file mode 100644 index 000000000000..23bbd905ac86 --- /dev/null +++ b/test/cmocka/include/cmocka_chirp_2ch.h @@ -0,0 +1,1609 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#define CHIRP_2CH_LENGTH 9600 + +int32_t chirp_2ch[CHIRP_2CH_LENGTH] = { + 1632025916LL, 1395804306LL, 1650166543LL, 1374310239LL, 1668043675LL, 1352556303LL, + 1685653315LL, 1330545435LL, 1702991495LL, 1308280635LL, 1720054273LL, 1285764967LL, + 1736837736LL, 1263001556LL, 1753338002LL, 1239993590LL, 1769551217LL, 1216744321LL, + 1785473561LL, 1193257061LL, 1801101246LL, 1169535187LL, 1816430518LL, 1145582134LL, + 1831457656LL, 1121401404LL, 1846178976LL, 1096996555LL, 1860590830LL, 1072371211LL, + 1874689610LL, 1047529054LL, 1888471743LL, 1022473828LL, 1901933697LL, 997209338LL, + 1915071983LL, 971739447LL, 1927883150LL, 946068081LL, 1940363792LL, 920199223LL, + 1952510545LL, 894136916LL, 1964320092LL, 867885263LL, 1975789159LL, 841448425LL, + 1986914521LL, 814830620LL, 1997693000LL, 788036123LL, 2008121465LL, 761069270LL, + 2018196837LL, 733934451LL, 2027916088LL, 706636111LL, 2037276239LL, 679178755LL, + 2046274365LL, 651566939LL, 2054907596LL, 623805277LL, 2063173116LL, 595898437LL, + 2071068163LL, 567851139LL, 2078590035LL, 539668157LL, 2085736084LL, 511354320LL, + 2092503724LL, 482914505LL, 2098890426LL, 454353644LL, 2104893723LL, 425676718LL, + 2110511210LL, 396888758LL, 2115740543LL, 367994846LL, 2120579444LL, 339000112LL, + 2125025696LL, 309909733LL, 2129077152LL, 280728935LL, 2132731726LL, 251462991LL, + 2135987405LL, 222117219LL, 2138842240LL, 192696982LL, 2141294352LL, 163207687LL, + 2143341935LL, 133654786LL, 2144983251LL, 104043773LL, 2146216634LL, 74380185LL, + 2147040493LL, 44669597LL, 2147453310LL, 14917627LL, 2147453639LL, -14870067LL, + 2147040115LL, -44687793LL, 2146211443LL, -74529816LL, 2144966411LL, -104390369LL, + 2143303881LL, -134263646LL, 2141222796LL, -164143810LL, 2138722179LL, -194024987LL, + 2135801131LL, -223901273LL, 2132458839LL, -253766730LL, 2128694567LL, -283615393LL, + 2124507667LL, -313441264LL, 2119897570LL, -343238319LL, 2114863796LL, -373000506LL, + 2109405947LL, -402721747LL, 2103523711LL, -432395939LL, 2097216867LL, -462016955LL, + 2090485276LL, -491578646LL, 2083328890LL, -521074840LL, 2075747750LL, -550499348LL, + 2067741985LL, -579845958LL, 2059311816LL, -609108444LL, 2050457554LL, -638280559LL, + 2041179601LL, -667356045LL, 2031478450LL, -696328628LL, 2021354690LL, -725192021LL, + 2010809001LL, -753939928LL, 1999842156LL, -782566038LL, 1988455023LL, -811064038LL, + 1976648566LL, -839427601LL, 1964423844LL, -867650399LL, 1951782009LL, -895726097LL, + 1938724314LL, -923648358LL, 1925252104LL, -951410841LL, 1911366825LL, -979007208LL, + 1897070018LL, -1006431119LL, 1882363324LL, -1033676240LL, 1867248481LL, -1060736237LL, + 1851727325LL, -1087604784LL, 1835801793LL, -1114275563LL, 1819473920LL, -1140742261LL, + 1802745841LL, -1166998579LL, 1785619792LL, -1193038228LL, 1768098106LL, -1218854930LL, + 1750183219LL, -1244442426LL, 1731877668LL, -1269794471LL, 1713184088LL, -1294904836LL, + 1694105217LL, -1319767315LL, 1674643895LL, -1344375721LL, 1654803059LL, -1368723890LL, + 1634585752LL, -1392805684LL, 1613995115LL, -1416614987LL, 1593034391LL, -1440145715LL, + 1571706925LL, -1463391811LL, 1550016164LL, -1486347249LL, 1527965653LL, -1509006036LL, + 1505559041LL, -1531362213LL, 1482800077LL, -1553409857LL, 1459692612LL, -1575143083LL, + 1436240596LL, -1596556045LL, 1412448080LL, -1617642937LL, 1388319218LL, -1638397999LL, + 1363858259LL, -1658815511LL, 1339069557LL, -1678889804LL, 1313957563LL, -1698615252LL, + 1288526827LL, -1717986283LL, 1262782000LL, -1736997373LL, 1236727828LL, -1755643054LL, + 1210369159LL, -1773917910LL, 1183710937LL, -1791816584LL, 1156758201LL, -1809333777LL, + 1129516092LL, -1826464249LL, 1101989842LL, -1843202822LL, 1074184781LL, -1859544382LL, + 1046106334LL, -1875483882LL, 1017760021LL, -1891016338LL, 989151454LL, -1906136840LL, + 960286340LL, -1920840545LL, 931170477LL, -1935122682LL, 901809756LL, -1948978557LL, + 872210157LL, -1962403551LL, 842377752LL, -1975393119LL, 812318701LL, -1987942801LL, + 782039253LL, -2000048214LL, 751545744LL, -2011705060LL, 720844598LL, -2022909123LL, + 689942322LL, -2033656275LL, 658845510LL, -2043942476LL, 627560839LL, -2053763776LL, + 596095066LL, -2063116314LL, 564455034LL, -2071996324LL, 532647661LL, -2080400135LL, + 500679949LL, -2088324170LL, 468558975LL, -2095764953LL, 436291894LL, -2102719105LL, + 403885934LL, -2109183350LL, 371348401LL, -2115154514LL, 338686671LL, -2120629527LL, + 305908191LL, -2125605427LL, 273020481LL, -2130079358LL, 240031128LL, -2134048573LL, + 206947784LL, -2137510437LL, 173778171LL, -2140462427LL, 140530072LL, -2142902133LL, + 107211333LL, -2144827262LL, 73829863LL, -2146235636LL, 40393628LL, -2147125196LL, + 6910652LL, -2147483648LL, -26610983LL, -2147340240LL, -60163142LL, -2146662211LL, + -93737638LL, -2145458344LL, -127326232LL, -2143727194LL, -160920636LL, -2141467441LL, + -194512515LL, -2138677894LL, -228093491LL, -2135357490LL, -261655138LL, -2131505299LL, + -295188992LL, -2127120521LL, -328686550LL, -2122202489LL, -362139268LL, -2116750671LL, + -395538570LL, -2110764670LL, -428875844LL, -2104244226LL, -462142450LL, -2097189216LL, + -495329714LL, -2089599657LL, -528428940LL, -2081475704LL, -561431404LL, -2072817655LL, + -594328360LL, -2063625948LL, -627111041LL, -2053901165LL, -659770664LL, -2043644031LL, + -692298427LL, -2032855416LL, -724685516LL, -2021536335LL, -756923107LL, -2009687952LL, + -789002364LL, -1997311574LL, -820914447LL, -1984408658LL, -852650512LL, -1970980811LL, + -884201711LL, -1957029787LL, -915559199LL, -1942557491LL, -946714133LL, -1927565979LL, + -977657678LL, -1912057457LL, -1008381004LL, -1896034283LL, -1038875294LL, -1879498969LL, + -1069131744LL, -1862454178LL, -1099141567LL, -1844902726LL, -1128895993LL, -1826847582LL, + -1158386274LL, -1808291871LL, -1187603687LL, -1789238870LL, -1216539534LL, -1769692012LL, + -1245185147LL, -1749654881LL, -1273531890LL, -1729131220LL, -1301571163LL, -1708124925LL, + -1329294402LL, -1686640046LL, -1356693083LL, -1664680790LL, -1383758727LL, -1642251515LL, + -1410482899LL, -1619356738LL, -1436857213LL, -1596001128LL, -1462873336LL, -1572189510LL, + -1488522987LL, -1547926862LL, -1513797943LL, -1523218316LL, -1538690043LL, -1498069159LL, + -1563191185LL, -1472484829LL, -1587293335LL, -1446470920LL, -1610988528LL, -1420033174LL, + -1634268869LL, -1393177489LL, -1657126539LL, -1365909912LL, -1679553793LL, -1338236641LL, + -1701542971LL, -1310164024LL, -1723086491LL, -1281698559LL, -1744176861LL, -1252846891LL, + -1764806674LL, -1223615812LL, -1784968618LL, -1194012264LL, -1804655473LL, -1164043331LL, + -1823860119LL, -1133716243LL, -1842575534LL, -1103038374LL, -1860794801LL, -1072017240LL, + -1878511107LL, -1040660499LL, -1895717751LL, -1008975947LL, -1912408141LL, -976971522LL, + -1928575802LL, -944655297LL, -1944214375LL, -912035480LL, -1959317622LL, -879120417LL, + -1973879429LL, -845918585LL, -1987893807LL, -812438591LL, -2001354897LL, -778689174LL, + -2014256970LL, -744679201LL, -2026594433LL, -710417664LL, -2038361830LL, -675913679LL, + -2049553845LL, -641176488LL, -2060165305LL, -606215449LL, -2070191180LL, -571040043LL, + -2079626592LL, -535659865LL, -2088466811LL, -500084625LL, -2096707261LL, -464324146LL, + -2104343523LL, -428388361LL, -2111371336LL, -392287311LL, -2117786599LL, -356031142LL, + -2123585376LL, -319630103LL, -2128763898LL, -283094545LL, -2133318562LL, -246434915LL, + -2137245938LL, -209661758LL, -2140542770LL, -172785710LL, -2143205977LL, -135817500LL, + -2145232656LL, -98767940LL, -2146620084LL, -61647932LL, -2147365723LL, -24468456LL, + -2147467217LL, 12759426LL, -2146922401LL, 50024580LL, -2145729294LL, 87315794LL, + -2143886112LL, 124621789LL, -2141391261LL, 161931220LL, -2138243343LL, 199232676LL, + -2134441158LL, 236514686LL, -2129983705LL, 273765723LL, -2124870183LL, 310974205LL, + -2119099998LL, 348128501LL, -2112672755LL, 385216931LL, -2105588269LL, 422227774LL, + -2097846563LL, 459149266LL, -2089447869LL, 495969610LL, -2080392630LL, 532676973LL, + -2070681502LL, 569259494LL, -2060315354LL, 605705288LL, -2049295272LL, 642002447LL, + -2037622558LL, 678139046LL, -2025298731LL, 714103144LL, -2012325532LL, 749882794LL, + -1998704920LL, 785466038LL, -1984439074LL, 820840920LL, -1969530397LL, 855995483LL, + -1953981516LL, 890917778LL, -1937795280LL, 925595866LL, -1920974763LL, 960017819LL, + -1903523265LL, 994171732LL, -1885444311LL, 1028045719LL, -1866741655LL, 1061627923LL, + -1847419274LL, 1094906516LL, -1827481375LL, 1127869708LL, -1806932391LL, 1160505746LL, + -1785776986LL, 1192802922LL, -1764020047LL, 1224749577LL, -1741666693LL, 1256334105LL, + -1718722270LL, 1287544955LL, -1695192351LL, 1318370641LL, -1671082736LL, 1348799741LL, + -1646399456LL, 1378820904LL, -1621148765LL, 1408422854LL, -1595337146LL, 1437594395LL, + -1568971306LL, 1466324416LL, -1542058181LL, 1494601893LL, -1514604927LL, 1522415898LL, + -1486618929LL, 1549755598LL, -1458107790LL, 1576610264LL, -1429079339LL, 1602969275LL, + -1399541624LL, 1628822119LL, -1369502913LL, 1654158404LL, -1338971693LL, 1678967855LL, + -1307956668LL, 1703240326LL, -1276466757LL, 1726965799LL, -1244511095LL, 1750134391LL, + -1212099027LL, 1772736360LL, -1179240111LL, 1794762105LL, -1145944113LL, 1816202175LL, + -1112221007LL, 1837047274LL, -1078080969LL, 1857288259LL, -1043534381LL, 1876916154LL, + -1008591825LL, 1895922146LL, -973264081LL, 1914297595LL, -937562124LL, 1932034036LL, + -901497124LL, 1949123185LL, -865080440LL, 1965556940LL, -828323621LL, 1981327391LL, + -791238400LL, 1996426820LL, -753836692LL, 2010847705LL, -716130592LL, 2024582729LL, + -678132371LL, 2037624779LL, -639854473LL, 2049966952LL, -601309512LL, 2061602562LL, + -562510267LL, 2072525139LL, -523469681LL, 2082728438LL, -484200856LL, 2092206439LL, + -444717048LL, 2100953355LL, -405031667LL, 2108963632LL, -365158269LL, 2116231956LL, + -325110554LL, 2122753255LL, -284902361LL, 2128522703LL, -244547667LL, 2133535725LL, + -204060577LL, 2137788000LL, -163455325LL, 2141275463LL, -122746266LL, 2143994311LL, + -81947874LL, 2145941005LL, -41074735LL, 2147112274LL, -141544LL, 2147483647LL, + 40836900LL, 2147116811LL, 81845702LL, 2145944905LL, 122869869LL, 2143987231LL, + 163894324LL, 2141241907LL, 204903903LL, 2137707333LL, 245883366LL, 2133382203LL, + 286817399LL, 2128265499LL, 327690623LL, 2122356499LL, 368487595LL, 2115654779LL, + 409192816LL, 2108160215LL, 449790737LL, 2099872983LL, 490265765LL, 2090793565LL, + 530602267LL, 2080922749LL, 570784576LL, 2070261631LL, 610797001LL, 2058811617LL, + 650623827LL, 2046574428LL, 690249326LL, 2033552094LL, 729657759LL, 2019746966LL, + 768833386LL, 2005161708LL, 807760472LL, 1989799305LL, 846423288LL, 1973663059LL, + 884806127LL, 1956756595LL, 922893300LL, 1939083858LL, 960669150LL, 1920649118LL, + 998118057LL, 1901456967LL, 1035224440LL, 1881512320LL, 1071972771LL, 1860820419LL, + 1108347577LL, 1839386827LL, 1144333448LL, 1817217437LL, 1179915042LL, 1794318463LL, + 1215077095LL, 1770696447LL, 1249804426LL, 1746358254LL, 1284081944LL, 1721311074LL, + 1317894657LL, 1695562422LL, 1351227674LL, 1669120136LL, 1384066216LL, 1641992376LL, + 1416395624LL, 1614187625LL, 1448201363LL, 1585714686LL, 1479469028LL, 1556582683LL, + 1510184357LL, 1526801055LL, 1540333230LL, 1496379561LL, 1569901685LL, 1465328274LL, + 1598875916LL, 1433657580LL, 1627242288LL, 1401378175LL, 1654987336LL, 1368501067LL, + 1682097781LL, 1335037568LL, 1708560530LL, 1300999296LL, 1734362686LL, 1266398170LL, + 1759491556LL, 1231246409LL, 1783934653LL, 1195556526LL, 1807679709LL, 1159341331LL, + 1830714680LL, 1122613919LL, 1853027751LL, 1085387675LL, 1874607344LL, 1047676266LL, + 1895442126LL, 1009493636LL, 1915521013LL, 970854006LL, 1934833180LL, 931771870LL, + 1953368067LL, 892261984LL, 1971115381LL, 852339372LL, 1988065112LL, 812019313LL, + 2004207528LL, 771317340LL, 2019533191LL, 730249233LL, 2034032959LL, 688831019LL, + 2047697993LL, 647078960LL, 2060519763LL, 605009554LL, 2072490053LL, 562639522LL, + 2083600971LL, 519985812LL, 2093844951LL, 477065585LL, 2103214761LL, 433896212LL, + 2111703506LL, 390495268LL, 2119304639LL, 346880529LL, 2126011960LL, 303069957LL, + 2131819628LL, 259081702LL, 2136722160LL, 214934091LL, 2140714442LL, 170645622LL, + 2143791732LL, 126234957LL, 2145949660LL, 81720916LL, 2147184243LL, 37122466LL, + 2147483647LL, -7541283LL, 2146869367LL, -52251084LL, 2145313885LL, -96987566LL, + 2142823023LL, -141731240LL, 2139394771LL, -186462503LL, 2135027527LL, -231161652LL, + 2129720101LL, -275808889LL, 2123471718LL, -320384328LL, 2116282020LL, -364868008LL, + 2108151076LL, -409239898LL, 2099079376LL, -453479907LL, 2089067841LL, -497567894LL, + 2078117823LL, -541483673LL, 2066231107LL, -585207028LL, 2053409917LL, -628717716LL, + 2039656914LL, -671995481LL, 2024975200LL, -715020063LL, 2009368323LL, -757771203LL, + 1992840271LL, -800228659LL, 1975395483LL, -842372210LL, 1957038842LL, -884181670LL, + 1937775681LL, -925636895LL, 1917611785LL, -966717794LL, 1896553386LL, -1007404341LL, + 1874607169LL, -1047676580LL, 1851780268LL, -1087514639LL, 1828080272LL, -1126898741LL, + 1803515217LL, -1165809210LL, 1778093592LL, -1204226487LL, 1751824335LL, -1242131133LL, + 1724716835LL, -1279503846LL, 1696780926LL, -1316325470LL, 1668026890LL, -1352577002LL, + 1638465457LL, -1388239604LL, 1608107796LL, -1423294618LL, 1576965520LL, -1457723568LL, + 1545050680LL, -1491508179LL, 1512375765LL, -1524630381LL, 1478953695LL, -1557072324LL, + 1444797823LL, -1588816385LL, 1409921928LL, -1619845181LL, 1374340215LL, -1650141578LL, + 1338067306LL, -1679688702LL, 1301118243LL, -1708469950LL, 1263508475LL, -1736468999LL, + 1225253862LL, -1763669818LL, 1186370666LL, -1790056674LL, 1146875545LL, -1815614149LL, + 1106785549LL, -1840327145LL, 1066118116LL, -1864180897LL, 1024891064LL, -1887160979LL, + 983122585LL, -1909253319LL, 940831241LL, -1930444205LL, 898035953LL, -1950720298LL, + 854756000LL, -1970068637LL, 811011007LL, -1988476653LL, 766820938LL, -2005932178LL, + 722206094LL, -2022423450LL, 677187097LL, -2037939128LL, 631784888LL, -2052468297LL, + 586020715LL, -2066000478LL, 539916127LL, -2078525638LL, 493492965LL, -2090034197LL, + 446773349LL, -2100517038LL, 399779676LL, -2109965512LL, 352534602LL, -2118371452LL, + 305061038LL, -2125727173LL, 257382139LL, -2132025489LL, 209521293LL, -2137259713LL, + 161502108LL, -2141423667LL, 113348408LL, -2144511691LL, 65084214LL, -2146518646LL, + 16733739LL, -2147439926LL, -31678627LL, -2147271459LL, -80128324LL, -2146009717LL, + -128590642LL, -2143651721LL, -177040723LL, -2140195046LL, -225453582LL, -2135637829LL, + -273804112LL, -2129978770LL, -322067104LL, -2123217142LL, -370217252LL, -2115352793LL, + -418229171LL, -2106386150LL, -466077410LL, -2096318225LL, -513736463LL, -2085150618LL, + -561180782LL, -2072885521LL, -608384795LL, -2059525721LL, -655322914LL, -2045074603LL, + -701969554LL, -2029536153LL, -748299141LL, -2012914963LL, -794286133LL, -1995216227LL, + -839905030LL, -1976445747LL, -885130389LL, -1956609937LL, -929936838LL, -1935715818LL, + -974299093LL, -1913771023LL, -1018191969LL, -1890783797LL, -1061590399LL, -1866762994LL, + -1104469445LL, -1841718083LL, -1146804314LL, -1815659141LL, -1188570376LL, -1788596856LL, + -1229743173LL, -1760542525LL, -1270298440LL, -1731508050LL, -1310212117LL, -1701505939LL, + -1349460364LL, -1670549304LL, -1388019579LL, -1638651855LL, -1425866409LL, -1605827898LL, + -1462977767LL, -1572092333LL, -1499330851LL, -1537460651LL, -1534903150LL, -1501948925LL, + -1569672470LL, -1465573809LL, -1603616940LL, -1428352534LL, -1636715034LL, -1390302899LL, + -1668945579LL, -1351443268LL, -1700287778LL, -1311792561LL, -1730721218LL, -1271370252LL, + -1760225888LL, -1230196356LL, -1788782194LL, -1188291428LL, -1816370970LL, -1145676548LL, + -1842973498LL, -1102373321LL, -1868571518LL, -1058403862LL, -1893147245LL, -1013790788LL, + -1916683380LL, -968557213LL, -1939163126LL, -922726733LL, -1960570203LL, -876323417LL, + -1980888858LL, -829371801LL, -2000103881LL, -781896871LL, -2018200618LL, -733924053LL, + -2035164983LL, -685479207LL, -2050983471LL, -636588606LL, -2065643171LL, -587278931LL, + -2079131778LL, -537577254LL, -2091437604LL, -487511027LL, -2102549593LL, -437108067LL, + -2112457328LL, -386396543LL, -2121151047LL, -335404962LL, -2128621649LL, -284162153LL, + -2134860707LL, -232697254LL, -2139860482LL, -181039696LL, -2143613924LL, -129219186LL, + -2146114691LL, -77265693LL, -2147357152LL, -25209430LL, -2147336399LL, 26919159LL, + -2146048256LL, 79089422LL, -2143489283LL, 131270509LL, -2139656789LL, 183431395LL, + -2134548837LL, 235540897LL, -2128164251LL, 287567688LL, -2120502621LL, 339480319LL, + -2111564314LL, 391247239LL, -2101350474LL, 442836808LL, -2089863032LL, 494217321LL, + -2077104708LL, 545357026LL, -2063079015LL, 596224143LL, -2047790267LL, 646786884LL, + -2031243578LL, 697013472LL, -2013444865LL, 746872163LL, -1994400855LL, 796331265LL, + -1974119081LL, 845359158LL, -1952607890LL, 893924314LL, -1929876438LL, 941995323LL, + -1905934692LL, 989540904LL, -1880793434LL, 1036529937LL, -1854464255LL, 1082931476LL, + -1826959555LL, 1128714772LL, -1798292545LL, 1173849298LL, -1768477241LL, 1218304765LL, + -1737528460LL, 1262051149LL, -1705461823LL, 1305058705LL, -1672293744LL, 1347297995LL, + -1638041428LL, 1388739908LL, -1602722869LL, 1429355679LL, -1566356839LL, 1469116913LL, + -1528962887LL, 1507995605LL, -1490561327LL, 1545964160LL, -1451173235LL, 1582995418LL, + -1410820440LL, 1619062673LL, -1369525513LL, 1654139693LL, -1327311760LL, 1688200742LL, + -1284203212LL, 1721220602LL, -1240224616LL, 1753174593LL, -1195401421LL, 1784038592LL, + -1149759767LL, 1813789053LL, -1103326478LL, 1842403033LL, -1056129042LL, 1869858203LL, + -1008195602LL, 1896132875LL, -959554942LL, 1921206019LL, -910236471LL, 1945057279LL, + -860270210LL, 1967666999LL, -809686774LL, 1989016235LL, -758517358LL, 2009086775LL, + -706793721LL, 2027861161LL, -654548164LL, 2045322702LL, -601813519LL, 2061455491LL, + -548623126LL, 2076244426LL, -495010814LL, 2089675225LL, -441010885LL, 2101734439LL, + -386658090LL, 2112409471LL, -331987614LL, 2121688591LL, -277035047LL, 2129560949LL, + -221836371LL, 2136016591LL, -166427933LL, 2141046472LL, -110846424LL, 2144642470LL, + -55128855LL, 2146797397LL, 687463LL, 2147483647LL, 56564946LL, 2146760038LL, + 112465762LL, 2144558161LL, 168351852LL, 2140896052LL, 224184957LL, 2135771373LL, + 279926643LL, 2129182784LL, 335538329LL, 2121129954LL, 390981309LL, 2111613570LL, + 446216781LL, 2100635341LL, 501205875LL, 2088198009LL, 555909677LL, 2074305350LL, + 610289260LL, 2058962183LL, 664305707LL, 2042174375LL, 717920146LL, 2023948842LL, + 771093770LL, 2004293554LL, 823787872LL, 1983217536LL, 875963869LL, 1960730872LL, + 927583337LL, 1936844704LL, 978608032LL, 1911571231LL, 1028999925LL, 1884923714LL, + 1078721230LL, 1856916465LL, 1127734433LL, 1827564855LL, 1176002321LL, 1796885303LL, + 1223488012LL, 1764895276LL, 1270154986LL, 1731613284LL, 1315967111LL, 1697058872LL, + 1360888677LL, 1661252618LL, 1404884424LL, 1624216121LL, 1447919570LL, 1585971996LL, + 1489959841LL, 1546543865LL, 1530971503LL, 1505956344LL, 1570921389LL, 1464235036LL, + 1609776928LL, 1421406520LL, 1647506173LL, 1377498334LL, 1684077835LL, 1332538966LL, + 1719461305LL, 1286557839LL, 1753626686LL, 1239585294LL, 1786544819LL, 1191652577LL, + 1818187314LL, 1142791820LL, 1848526574LL, 1093036028LL, 1877535824LL, 1042419052LL, + 1905189138LL, 990975580LL, 1931461463LL, 938741110LL, 1956328646LL, 885751930LL, + 1979767462LL, 832045099LL, 2001755636LL, 777658424LL, 2022271868LL, 722630434LL, + 2041295857LL, 667000358LL, 2058808325LL, 610808100LL, 2074791039LL, 554094213LL, + 2089226835LL, 496899872LL, 2102099638LL, 439266848LL, 2113394482LL, 381237479LL, + 2123097533LL, 322854642LL, 2131196105LL, 264161724LL, 2137678683LL, 205202589LL, + 2142534938LL, 146021552LL, 2145755745LL, 86663344LL, 2147333201LL, 27173079LL, + 2147260638LL, -32403773LL, 2145532640LL, -92021425LL, 2142145056LL, -151633807LL, + 2137095013LL, -211194595LL, 2130380929LL, -270657252LL, 2122002524LL, -329975059LL, + 2111960829LL, -389101156LL, 2100258196LL, -447988572LL, 2086898309LL, -506590270LL, + 2071886185LL, -564859175LL, 2055228188LL, -622748221LL, 2036932028LL, -680210383LL, + 2017006768LL, -737198718LL, 1995462827LL, -793666402LL, 1972311982LL, -849566772LL, + 1947567366LL, -904853363LL, 1921243473LL, -959479948LL, 1893356152LL, -1013400578LL, + 1863922608LL, -1066569624LL, 1832961395LL, -1118941812LL, 1800492412LL, -1170472267LL, + 1766536899LL, -1221116554LL, 1731117427LL, -1270830715LL, 1694257893LL, -1319571311LL, + 1655983505LL, -1367295463LL, 1616320776LL, -1413960891LL, 1575297511LL, -1459525952LL, + 1532942790LL, -1503949685LL, 1489286960LL, -1547191845LL, 1444361610LL, -1589212947LL, + 1398199565LL, -1629974303LL, 1350834860LL, -1669438059LL, 1302302720LL, -1707567239LL, + 1252639547LL, -1744325778LL, 1201882888LL, -1779678560LL, 1150071421LL, -1813591459LL, + 1097244924LL, -1846031373LL, 1043444253LL, -1876966260LL, 988711314LL, -1906365177LL, + 933089036LL, -1934198310LL, 876621339LL, -1960437013LL, 819353108LL, -1985053837LL, + 761330160LL, -2008022570LL, 702599208LL, -2029318261LL, 643207834LL, -2048917259LL, + 583204447LL, -2066797238LL, 522638254LL, -2082937231LL, 461559217LL, -2097317654LL, + 400018019LL, -2109920339LL, 338066023LL, -2120728558LL, 275755233LL, -2129727049LL, + 213138255LL, -2136902042LL, 150268249LL, -2142241281LL, 87198893LL, -2145734048LL, + 23984335LL, -2147371185LL, -39320849LL, -2147145110LL, -102661702LL, -2145049843LL, + -165982933LL, -2141081016LL, -229228961LL, -2135235897LL, -292343965LL, -2127513398LL, + -355271932LL, -2117914093LL, -417956706LL, -2106440230LL, -480342037LL, -2093095741LL, + -542371632LL, -2077886249LL, -603989205LL, -2060819083LL, -665138530LL, -2041903276LL, + -725763489LL, -2021149577LL, -785808129LL, -1998570449LL, -845216710LL, -1974180074LL, + -903933763LL, -1947994354LL, -961904137LL, -1920030907LL, -1019073055LL, -1890309065LL, + -1075386171LL, -1858849869LL, -1130789617LL, -1825676065LL, -1185230061LL, -1790812094LL, + -1238654760LL, -1754284081LL, -1291011614LL, -1716119828LL, -1342249218LL, -1676348797LL, + -1392316917LL, -1635002097LL, -1441164858LL, -1592112466LL, -1488744045LL, -1547714257LL, + -1535006390LL, -1501843413LL, -1579904765LL, -1454537447LL, -1623393057LL, -1405835422LL, + -1665426216LL, -1355777921LL, -1705960307LL, -1304407023LL, -1744952563LL, -1251766274LL, + -1782361431LL, -1197900657LL, -1818146622LL, -1142856558LL, -1852269164LL, -1086681737LL, + -1884691441LL, -1029425288LL, -1915377249LL, -971137605LL, -1944291833LL, -911870341LL, + -1971401940LL, -851676372LL, -1996675856LL, -790609751LL, -2020083453LL, -728725664LL, + -2041596229LL, -666080392LL, -2061187349LL, -602731256LL, -2078831681LL, -538736574LL, + -2094505839LL, -474155612LL, -2108188216LL, -409048529LL, -2119859020LL, -343476330LL, + -2129500306LL, -277500808LL, -2137096012LL, -211184492LL, -2142631983LL, -144590590LL, + -2146096006LL, -77782931LL, -2147477835LL, -10825906LL, -2146769214LL, 56215590LL, + -2143963905LL, 123276221LL, -2139057705LL, 190290269LL, -2132048471LL, 257191702LL, + -2122936133LL, 323914231LL, -2111722714LL, 390391382LL, -2098412344LL, 456556556LL, + -2083011268LL, 522343097LL, -2065527860LL, 587684363LL, -2045972632LL, 652513786LL, + -2024358235LL, 716764948LL, -2000699465LL, 780371644LL, -1975013267LL, 843267958LL, + -1947318730LL, 905388324LL, -1917637087LL, 966667603LL, -1885991709LL, 1027041152LL, + -1852408095LL, 1086444891LL, -1816913867LL, 1144815379LL, -1779538753LL, 1202089879LL, + -1740314576LL, 1258206433LL, -1699275234LL, 1313103930LL, -1656456683LL, 1366722177LL, + -1611896915LL, 1419001969LL, -1565635933LL, 1469885158LL, -1517715724LL, 1519314725LL, + -1468180235LL, 1567234842LL, -1417075334LL, 1613590949LL, -1364448783LL, 1658329814LL, + -1310350199LL, 1701399603LL, -1254831016LL, 1742749946LL, -1197944447LL, 1782331999LL, + -1139745437LL, 1820098512LL, -1080290619LL, 1856003888LL, -1019638268LL, 1890004247LL, + -957848252LL, 1922057486LL, -894981976LL, 1952123335LL, -831102331LL, 1980163420LL, + -766273636LL, 2006141313LL, -700561583LL, 2030022591LL, -634033169LL, 2051774888LL, + -566756643LL, 2071367944LL, -498801433LL, 2088773655LL, -430238085LL, 2103966122LL, + -361138190LL, 2116921694LL, -291574318LL, 2127619014LL, -221619943LL, 2136039057LL, + -151349370LL, 2142165171LL, -80837661LL, 2145983114LL, -10160554LL, 2147481086LL, + 60605610LL, 2146649765LL, 131383974LL, 2143482331LL, 202097238LL, 2137974499LL, + 272667752LL, 2130124539LL, 343017589LL, 2119933298LL, 413068639LL, 2107404221LL, + 482742691LL, 2092543368LL, 551961519LL, 2075359423LL, 620646975LL, 2055863708LL, + 688721073LL, 2034070190LL, 756106079LL, 2009995485LL, 822724605LL, 1983658861LL, + 888499694LL, 1955082235LL, 953354917LL, 1924290169LL, 1017214459LL, 1891309863LL, + 1080003213LL, 1856171143LL, 1141646872LL, 1818906450LL, 1202072019LL, 1779550818LL, + 1261206220LL, 1738141859LL, 1318978114LL, 1694719737LL, 1375317504LL, 1649327140LL, + 1430155448LL, 1602009253LL, 1483424347LL, 1552813723LL, 1535058037LL, 1501790623LL, + 1584991875LL, 1448992411LL, 1633162827LL, 1394473891LL, 1679509555LL, 1338292161LL, + 1723972499LL, 1280506570LL, 1766493965LL, 1221178662LL, 1807018205LL, 1160372121LL, + 1845491500LL, 1098152710LL, 1881862236LL, 1034588216LL, 1916080984LL, 969748377LL, + 1948100575LL, 903704819LL, 1977876175LL, 836530986LL, 2005365352LL, 768302061LL, + 2030528153LL, 699094897LL, 2053327163LL, 628987929LL, 2073727576LL, 558061101LL, + 2091697254LL, 486395773LL, 2107206787LL, 414074642LL, 2120229549LL, 341181643LL, + 2130741752LL, 267801866LL, 2138722499LL, 194021455LL, 2144153829LL, 119927513LL, + 2147020764LL, 45608004LL, 2147311348LL, -28848348LL, 2145016686LL, -103352162LL, + 2140130980LL, -177813505LL, 2132651557LL, -252142001LL, 2122578901LL, -326246935LL, + 2109916672LL, -400037362LL, 2094671729LL, -473422223LL, 2076854145LL, -546310454LL, + 2056477221LL, -618611099LL, 2033557492LL, -690233425LL, 2008114731LL, -761087037LL, + 1980171955LL, -831081995LL, 1949755412LL, -900128928LL, 1916894581LL, -968139152LL, + 1881622156LL, -1035024789LL, 1843974030LL, -1100698883LL, 1803989273LL, -1165075514LL, + 1761710112LL, -1228069922LL, 1717181896LL, -1289598616LL, 1670453063LL, -1349579496LL, + 1621575107LL, -1407931968LL, 1570602529LL, -1464577054LL, 1517592797LL, -1519437513LL, + 1462606287LL, -1572437948LL, 1405706237LL, -1623504920LL, 1346958680LL, -1672567059LL, + 1286432384LL, -1719555167LL, 1224198782LL, -1764402333LL, 1160331902LL, -1807044031LL, + 1094908287LL, -1847418224LL, 1028006919LL, -1885465467LL, 959709131LL, -1921129000LL, + 890098521LL, -1954354849LL, 819260858LL, -1985091912LL, 747283985LL, -2013292055LL, + 674257722LL, -2038910193LL, 600273761LL, -2061904378LL, 525425558LL, -2082235874LL, + 449808224LL, -2099869237LL, 373518410LL, -2114772387LL, 296654191LL, -2126916675LL, + 219314945LL, -2136276950LL, 141601230LL, -2142831618LL, 63614660LL, -2146562701LL, + -14542228LL, -2147455885LL, -92766099LL, -2145500572LL, -170952961LL, -2140689921LL, + -248998292LL, -2133020887LL, -326797187LL, -2122494252LL, -404244490LL, -2109114659LL, + -481234940LL, -2092890629LL, -557663313LL, -2073834584LL, -633424565LL, -2051962859LL, + -708413980LL, -2027295708LL, -782527314LL, -1999857309LL, -855660944LL, -1969675760LL, + -927712017LL, -1936783071LL, -998578594LL, -1901215149LL, -1068159804LL, -1863011778LL, + -1136355989LL, -1822216595LL, -1203068852LL, -1778877059LL, -1268201607LL, -1733044413LL, + -1331659125LL, -1684773643LL, -1393348080LL, -1634123428LL, -1453177097LL, -1581156089LL, + -1511056888LL, -1525937526LL, -1566900404LL, -1468537155LL, -1620622970LL, -1409027836LL, + -1672142422LL, -1347485797LL, -1721379250LL, -1283990550LL, -1768256722LL, -1218624806LL, + -1812701025LL, -1151474380LL, -1854641385LL, -1082628092LL, -1894010198LL, -1012177663LL, + -1930743148LL, -940217607LL, -1964779326LL, -866845116LL, -1996061343LL, -792159938LL, + -2024535445LL, -716264257LL, -2050151612LL, -639262559LL, -2072863666LL, -561261504LL, + -2092629362LL, -482369782LL, -2109410486LL, -402697970LL, -2123172937LL, -322358392LL, + -2133886812LL, -241464960LL, -2141526481LL, -160133022LL, -2146070657LL, -78479207LL, + -2147483648LL, 3378745LL, -2145809494LL, 85322139LL, -2140983857LL, 167231503LL, + -2133022234LL, 248986751LL, -2121925912LL, 330467361LL, -2107700821LL, 411552551LL, + -2090357559LL, 492121458LL, -2069911413LL, 572053316LL, -2046382373LL, 651227639LL, + -2019795137LL, 729524406LL, -1990179111LL, 806824243LL, -1957568402LL, 883008610LL, + -1922001800LL, 957959986LL, -1883522758LL, 1031562056LL, -1842179360LL, 1103699894LL, + -1798024288LL, 1174260155LL, -1751114770LL, 1243131255LL, -1701512532LL, 1310203555LL, + -1649283740LL, 1375369550LL, -1594498928LL, 1438524043LL, -1537232926LL, 1499564332LL, + -1477564777LL, 1558390381LL, -1415577650LL, 1614905004LL, -1351358735LL, 1669014027LL, + -1284999151LL, 1720626466LL, -1216593821LL, 1769654691LL, -1146241366LL, 1816014588LL, + -1074043969LL, 1859625716LL, -1000107249LL, 1900411467LL, -924540120LL, 1938299208LL, + -847454643LL, 1973220434LL, -768965877LL, 2005110903LL, -689191716LL, 2033910773LL, + -608252730LL, 2059564728LL, -526271988LL, 2082022105LL, -443374886LL, 2101237008LL, + -359688965LL, 2117168416LL, -275343719LL, 2129780291LL, -190470409LL, 2139041672LL, + -105201860LL, 2144926764LL, -19672266LL, 2147415017LL, 65983022LL, 2146491205LL, + 151627702LL, 2142145488LL, 237124735LL, 2134373471LL, 322336562LL, 2123176251LL, + 407125325LL, 2108560462LL, 491353087LL, 2090538303LL, 574882057LL, 2069127563LL, + 657574818LL, 2044351636LL, 739294556LL, 2016239522LL, 819905287LL, 1984825829LL, + 899272088LL, 1950150754LL, 977261330LL, 1912260062LL, 1053740907LL, 1871205054LL, + 1128580469LL, 1827042522LL, 1201651651LL, 1779834701LL, 1272828300LL, 1729649205LL, + 1341986706LL, 1676558956LL, 1409005829LL, 1620642103LL, 1473767517LL, 1561981933LL, + 1536156732LL, 1500666768LL, 1596061765LL, 1436789858LL, 1653374452LL, 1370449260LL, + 1707990384LL, 1301747711LL, 1759809111LL, 1230792487LL, 1808734346LL, 1157695261LL, + 1854674162LL, 1082571941LL, 1897541176LL, 1005542509LL, 1937252743LL, 926730847LL, + 1973731126LL, 846264553LL, 2006903673LL, 764274754LL, 2036702978LL, 680895903LL, + 2063067041LL, 596265576LL, 2085939413LL, 510524259LL, 2105269340LL, 423815124LL, + 2121011894LL, 336283806LL, 2133128097LL, 248078162LL, 2141585033LL, 159348038LL, + 2146355956LL, 70245016LL, 2147420380LL, -19077833LL, 2144764167LL, -108466212LL, + 2138379601LL, -197764852LL, 2128265447LL, -286817785LL, 2114427009LL, -375468610LL, + 2096876168LL, -463560771LL, 2075631413LL, -550937827LL, 2050717858LL, -637443738LL, + 2022167250LL, -722923140LL, 1990017961LL, -807221634LL, 1954314976LL, -890186063LL, + 1915109857LL, -971664802LL, 1872460706LL, -1051508040LL, 1826432107LL, -1129568064LL, + 1777095065LL, -1205699541LL, 1724526921LL, -1279759803LL, 1668811265LL, -1351609120LL, + 1610037832LL, -1421110986LL, 1548302383LL, -1488132381LL, 1483706582LL, -1552544051LL, + 1416357851LL, -1614220768LL, 1346369220LL, -1673041594LL, 1273859163LL, -1728890131LL, + 1198951419LL, -1781654778LL, 1121774809LL, -1831228967LL, 1042463034LL, -1877511405LL, + 961154465LL, -1920406297LL, 877991925LL, -1959823572LL, 793122452LL, -1995679090LL, + 706697064LL, -2027894847LL, 618870503LL, -2056399171LL, 529800975LL, -2081126901LL, + 439649880LL, -2102019561LL, 348581532LL, -2119025523LL, 256762874LL, -2132100157LL, + 164363179LL, -2141205968LL, 71553754LL, -2146312725LL, -21492379LL, -2147397572LL, + -114600791LL, -2144445129LL, -207595970LL, -2137447582LL, -300301650LL, -2126404753LL, + -392541139LL, -2111324160LL, -484137659LL, -2092221064LL, -574914683LL, -2069118498LL, + -664696276LL, -2042047285LL, -753307443LL, -2011046034LL, -840574471LL, -1976161130LL, + -926325279LL, -1937446704LL, -1010389766LL, -1894964584LL, -1092600153LL, -1848784238LL, + -1172791334LL, -1798982696LL, -1250801216LL, -1745644457LL, -1326471063LL, -1688861383LL, + -1399645833LL, -1628732573LL, -1470174511LL, -1565364226LL, -1537910441LL, -1498869484LL, + -1602711645LL, -1429368264LL, -1664441149LL, -1356987072LL, -1722967284LL, -1281858803LL, + -1778163998LL, -1204122522LL, -1829911145LL, -1123923241LL, -1878094776LL, -1041411670LL, + -1922607409LL, -956743959LL, -1963348303LL, -870081429LL, -2000223708LL, -781590284LL, + -2033147106LL, -691441318LL, -2062039451LL, -599809599LL, -2086829376LL, -506874154LL, + -2107453406LL, -412817628LL, -2123856144LL, -317825949LL, -2135990446LL, -222087967LL, + -2143817587LL, -125795095LL, -2147307397LL, -29140933LL, -2146438397LL, 67679109LL, + -2141197904LL, 164468202LL, -2131582130LL, 261028492LL, -2117596259LL, 357161501LL, + -2099254499LL, 452668532LL, -2076580132LL, 547351084LL, -2049605527LL, 641011260LL, + -2018372150LL, 733452192LL, -1982930542LL, 824478453LL, -1943340287LL, 913896484LL, + -1899669956LL, 1001515008LL, -1851997032LL, 1087145458LL, -1800407816LL, 1170602386LL, + -1744997314LL, 1251703890LL, -1685869098LL, 1330272016LL, -1623135162LL, 1406133173LL, + -1556915739LL, 1479118533LL, -1487339116LL, 1549064430LL, -1414541418LL, 1615812746LL, + -1338666380LL, 1679211296LL, -1259865095LL, 1739114198LL, -1178295748LL, 1795382239LL, + -1094123330LL, 1847883219LL, -1007519333LL, 1896492301LL, -918661430LL, 1941092329LL, + -827733139LL, 1981574148LL, -734923466LL, 2017836899LL, -640426540LL, 2049788306LL, + -544441224LL, 2077344941LL, -447170722LL, 2100432479LL, -348822162LL, 2118985925LL, + -249606173LL, 2132949838LL, -149736450LL, 2142278518LL, -49429306LL, 2146936188LL, + 51096791LL, 2146897150LL, 151621680LL, 2142145914LL, 251923985LL, 2132677322LL, + 351781599LL, 2118496627LL, 450972173LL, 2099619573LL, 549273614LL, 2076072434LL, + 646464580LL, 2047892038LL, 742324986LL, 2015125770LL, 836636512LL, 1977831540LL, + 929183100LL, 1936077741LL, 1019751472LL, 1889943170LL, 1108131625LL, 1839516935LL, + 1194117337LL, 1784898327LL, 1277506667LL, 1726196677LL, 1358102446LL, 1663531183LL, + 1435712767LL, 1597030715LL, 1510151462LL, 1526833591LL, 1581238578LL, 1453087339LL, + 1648800835LL, 1375948421LL, 1712672082LL, 1295581951LL, 1772693732LL, 1212161370LL, + 1828715188LL, 1125868116LL, 1880594257LL, 1036891263LL, 1928197545LL, 945427141LL, + 1971400835LL, 851678930LL, 2010089448LL, 755856247LL, 2044158586LL, 658174694LL, + 2073513656LL, 558855411LL, 2098070570LL, 458124586LL, 2117756022LL, 356212973LL, + 2132507751LL, 253355372LL, 2142274766LL, 149790111LL, 2147017562LL, 45758508LL, + 2146708296LL, -58495684LL, 2141330948LL, -162726835LL, 2130881451LL, -266688013LL, + 2115367788LL, -370131561LL, 2094810075LL, -472809688LL, 2069240598LL, -574475065LL, + 2038703834LL, -674881420LL, 2003256437LL, -773784144LL, 1962967196LL, -870940895LL, + 1917916960LL, -966112202LL, 1868198538LL, -1059062073LL, 1813916564LL, -1149558590LL, + 1755187331LL, -1237374514LL, 1692138601LL, -1322287869LL, 1624909378LL, -1404082535LL, + 1553649655LL, -1482548819LL, 1478520128LL, -1557484024LL, 1399691882LL, -1628693000LL, + 1317346053LL, -1695988688LL, 1231673450LL, -1759192646LL, 1142874164LL, -1818135556LL, + 1051157132LL, -1872657720LL, 956739694LL, -1922609532LL, 859847108LL, -1967851926LL, + 760712051LL, -2008256813LL, 659574089LL, -2043707482LL, 556679130LL, -2074098985LL, + 452278850LL, -2099338490LL, 346630107LL, -2119345612LL, 239994322LL, -2134052712LL, + 132636860LL, -2143405168LL, 24826378LL, -2147361615LL, -83165830LL, -2145894149LL, + -191066510LL, -2138988509LL, -298601125LL, -2126644216LL, -405494561LL, -2108874679LL, + -511471820LL, -2085707273LL, -616258735LL, -2057183372LL, -719582683LL, -2023358351LL, + -821173304LL, -1984301554LL, -920763220LL, -1940096221LL, -1018088751LL, -1890839377LL, + -1112890634LL, -1836641688LL, -1204914733LL, -1777627278LL, -1293912744LL, -1713933506LL, + -1379642892LL, -1645710711LL, -1461870615LL, -1573121914LL, -1540369243LL, -1496342490LL, + -1614920651LL, -1415559798LL, -1685315909LL, -1330972780LL, -1751355900LL, -1242791521LL, + -1812851934LL, -1151236778LL, -1869626324LL, -1056539474LL, -1921512950LL, -958940163LL, + -1968357790LL, -858688456LL, -2010019429LL, -756042425LL, -2046369536LL, -651267976LL, + -2077293310LL, -544638190LL, -2102689896LL, -436432644LL, -2122472766LL, -326936705LL, + -2136570063LL, -216440800LL, -2144924909LL, -105239667LL, -2147483648LL, 6368414LL, + -2144256234LL, 118082407LL, -2135196104LL, 229599325LL, -2120320647LL, 340615042LL, + -2099651153LL, 450825120LL, -2073224909LL, 559925647LL, -2041095220LL, 667614076LL, + -2003331387LL, 773590076LL, -1960018637LL, 877556377LL, -1911258011LL, 979219623LL, + -1857166203LL, 1078291217LL, -1797875359LL, 1174488164LL, -1733532825LL, 1267533903LL, + -1664300855LL, 1357159135LL, -1590356264LL, 1443102632LL, -1511890052LL, 1525112037LL, + -1429106968LL, 1602944643LL, -1342225042LL, 1676368154LL, -1251475071LL, 1745161425LL, + -1157100057LL, 1809115173LL, -1059354618LL, 1868032668LL, -958504345LL, 1921730385LL, + -854825134LL, 1970038640LL, -748602471LL, 2012802174LL, -640130690LL, 2049880717LL, + -529712195LL, 2081149500LL, -417656648LL, 2106499745LL, -304280133LL, 2125839094LL, + -189904291LL, 2139092007LL, -74855428LL, 2146200111LL, 40536394LL, 2147122505LL, + 155938295LL, 2141836012LL, 271015526LL, 2130335381LL, 385432428LL, 2112633450LL, + 498853421LL, 2088761240LL, 610943979LL, 2058768007LL, 721371633LL, 2022721241LL, + 829806964LL, 1980706605LL, 935924603LL, 1932827822LL, 1039404227LL, 1879206510LL, + 1139931548LL, 1819981955LL, 1237199302LL, 1755310839LL, 1330908212LL, 1685366899LL, + 1420767952LL, 1610340547LL, 1506498086LL, 1530438424LL, 1587828983LL, 1445882904LL, + 1664502718LL, 1356911550LL, 1736273936LL, 1263776512LL, 1802910697LL, 1166743876LL, + 1864195278LL, 1066092970LL, 1919924947LL, 962115612LL, 1969912698LL, 855115323LL, + 2013987939LL, 745406489LL, 2051997144LL, 633313487LL, 2083804456LL, 519169761LL, + 2109292239LL, 403316877LL, 2128361582LL, 286103528LL, 2140932750LL, 167884518LL, + 2146945579LL, 49019707LL, 2146359813LL, -70127059LL, 2139155384LL, -189189051LL, + 2125332629LL, -307797774LL, 2104912450LL, -425584104LL, 2077936407LL, -542179435LL, + 2044466746LL, -657216842LL, 2004586365LL, -770332239LL, 1958398714LL, -881165553LL, + 1906027626LL, -989361887LL, 1847617085LL, -1094572683LL, 1783330927LL, -1196456876LL, + 1713352471LL, -1294682031LL, 1637884089LL, -1388925471LL, 1557146706LL, -1478875380LL, + 1471379241LL, -1564231882LL, 1380837979LL, -1644708098LL, 1285795885LL, -1720031161LL, + 1186541851LL, -1789943208LL, 1083379894LL, -1854202324LL, 976628288LL, -1912583446LL, + 866618644LL, -1964879227LL, 753694937LL, -2010900841LL, 638212486LL, -2050478743LL, + 520536881LL, -2083463369LL, 401042868LL, -2109725781LL, 280113198LL, -2129158249LL, + 158137428LL, -2141674767LL, 35510698LL, -2147211504LL, -87367532LL, -2145727188LL, + -210094764LL, -2137203416LL, -332266774LL, -2121644891LL, -453478935LL, -2099079586LL, + -573327562LL, -2069558832LL, -691411263LL, -2033157328LL, -807332294LL, -1989973070LL, + -920697925LL, -1940127208LL, -1031121786LL, -1883763816LL, -1138225223LL, -1821049586LL, + -1241638630LL, -1752173441LL, -1341002763LL, -1677346071LL, -1435970040LL, -1596799391LL, + -1526205810LL, -1510785914LL, -1611389586LL, -1419578056LL, -1691216248LL, -1323467361LL, + -1765397204LL, -1222763658LL, -1833661505LL, -1117794139LL, -1895756908LL, -1008902374LL, + -1951450889LL, -896447255LL, -2000531596LL, -780801885LL, -2042808742LL, -662352396LL, + -2078114424LL, -541496716LL, -2106303885LL, -418643283LL, -2127256191LL, -294209705LL, + -2140874840LL, -168621381LL, -2147088287LL, -42310076LL, -2145850382LL, 84287538LL, + -2137140739LL, 210731376LL, -2120964998LL, 336579457LL, -2097355009LL, 461389445LL, + -2066368925LL, 584720204LL, -2028091200LL, 706133371LL, -1982632490LL, 825194925LL, + -1930129466LL, 941476764LL, -1870744530LL, 1054558275LL, -1804665434LL, 1164027888LL, + -1732104805LL, 1269484619LL, -1653299576LL, 1370539589LL, -1568510327LL, 1466817510LL, + -1478020527LL, 1557958143LL, -1382135693LL, 1643617711LL, -1281182454LL, 1723470270LL, + -1175507534LL, 1797209028LL, -1065476648LL, 1864547603LL, -951473322LL, 1925221226LL, + -833897630LL, 1978987871LL, -713164864LL, 2025629317LL, -589704129LL, 2064952129LL, + -463956876LL, 2096788561LL, -336375378LL, 2120997373LL, -207421144LL, 2137464554LL, + -77563289LL, 2146103956LL, 52723149LL, 2146857825LL, 182958915LL, 2139697242LL, + 312662295LL, 2124622447LL, 441350886LL, 2101663067LL, 568543396LL, 2070878234LL, + 693761448LL, 2032356589LL, 816531401LL, 1986216183LL, 936386163LL, 1932604255LL, + 1052867005LL, 1871696910LL, 1165525354LL, 1803698673LL, 1273924569LL, 1728841938LL, + 1377641690LL, 1647386301LL, 1476269151LL, 1559617788LL, 1569416450LL, 1465847966LL, + 1656711771LL, 1366412953LL, 1737803554LL, 1261672327LL, 1812361994LL, 1152007923LL, + 1880080483LL, 1037822542LL, 1940676965LL, 919538564LL, 1993895215LL, 797596468LL, + 2039506032LL, 672453268LL, 2077308337LL, 544580872LL, 2107130168LL, 414464364LL, + 2128829577LL, 282600219LL, 2142295419LL, 149494453LL, 2147448019LL, 15660717LL, + 2144239734LL, -118381651LL, 2132655385LL, -252109625LL, 2112712567LL, -384998523LL, + 2084461837LL, -516524056LL, 2047986769LL, -646164412LL, 2003403874LL, -773402334LL, + 1950862399LL, -897727216LL, 1890543982LL, -1018637180LL, 1822662181LL, -1135641152LL, + 1747461869LL, -1248260898LL, 1665218491LL, -1356033049LL, 1576237200LL, -1458511070LL, + 1480851860LL, -1555267187LL, 1379423917LL, -1645894259LL, 1272341157LL, -1730007582LL, + 1160016341LL, -1807246619LL, 1042885717LL, -1877276653LL, 921407436LL, -1939790347LL, + 796059848LL, -1994509206LL, 667339705LL, -2041184943LL, 535760276LL, -2079600726LL, + 401849360LL, -2109572313LL, 266147236LL, -2130949061LL, 129204530LL, -2143614807LL, + -8419981LL, -2147483648LL, -146161614LL, -2142525387LL, -283452079LL, -2128716320LL, + -419721815LL, -2106089231LL, -554402350LL, -2074708723LL, -686928685LL, -2034676199LL, + -816741686LL, -1986129722LL, -943290472LL, -1929243722LL, -1066034797LL, -1864228544LL, + -1184447406LL, -1791329840LL, -1298016362LL, -1710827804LL, -1406247332LL, -1623036258LL, + -1508665815LL, -1528301577LL, -1604819320LL, -1427001472LL, -1694279456LL, -1319543625LL, + -1776643949LL, -1206364178LL, -1851538569LL, -1087926090LL, -1918618947LL, -964717362LL, + -1977572287LL, -837249128LL, -2028118959LL, -706053640LL, -2070013960LL, -571682131LL, + -2103048244LL, -434702581LL, -2127049908LL, -295697381LL, -2141885221LL, -155260917LL, + -2147459507LL, -13997077LL, -2143717859LL, 127483314LL, -2130645685LL, 268565108LL, + -2108269089LL, 408631496LL, -2076655068LL, 547066707LL, -2035911533LL, 683258723LL, + -1986187153LL, 816602011LL, -1927671013LL, 946500247LL, -1860592086LL, 1072369032LL, + -1785218531LL, 1193638576LL, -1701856797LL, 1309756350LL, -1610850556LL, 1420189684LL, + -1512579459LL, 1524428297LL, -1407457705LL, 1621986763LL, -1295932459LL, 1712406878LL, + -1178482088LL, 1795259932LL, -1055614248LL, 1870148874LL, -927863822LL, 1936710350LL, + -795790699LL, 1994616609LL, -659977433LL, 2043577266LL, -521026769LL, 2083340913LL, + -379559047LL, 2113696568LL, -236209508LL, 2134474952LL, -91625499LL, 2145549585LL, + 53536403LL, 2146837699LL, 198613339LL, 2138300960LL, 342939177LL, 2119945984LL, + 485847560LL, 2091824658LL, 626674992LL, 2054034252LL, 764763938LL, 2006717313LL, + 899465925LL, 1950061359LL, 1030144637LL, 1884298352LL, 1156178983LL, 1809703957LL, + 1276966115LL, 1726596592LL, 1391924405LL, 1635336266LL, 1500496336LL, 1536323207LL, + 1602151325LL, 1429996289LL, 1696388426LL, 1316831258LL, 1782738940LL, 1197338768LL, + 1860768882LL, 1072062229LL, 1930081313LL, 941575476LL, 1990318522LL, 806480275LL, + 2041164032LL, 667403661LL, 2082344437LL, 524995141LL, 2113631046LL, 379923745LL, + 2134841329LL, 232874971LL, 2145840151LL, 84547604LL, 2146540796LL, -64349551LL, + 2136905756LL, -213101018LL, 2116947299LL, -360988071LL, 2086727792LL, -507292200LL, + 2046359786LL, -651298608LL, 1996005859LL, -792299732LL, 1935878200LL, -929598756LL, + 1866237962LL, -1062513116LL, 1787394355LL, -1190377954LL, 1699703494LL, -1312549536LL, + 1603567009LL, -1428408591LL, 1499430408LL, -1537363556LL, 1387781213LL, -1638853733LL, + 1269146861LL, -1732352302LL, 1144092389LL, -1817369213LL, 1013217907LL, -1893453914LL, + 877155868LL, -1960197907LL, 736568152LL, -2017237123LL, 592142968LL, -2064254092LL, + 444591597LL, -2100979906LL, 294644982LL, -2127195945LL, 143050183LL, -2142735377LL, + -9433276LL, -2147483648LL, -162037173LL, -2141383246LL, -313988426LL, -2124426869LL, + -464512998LL, -2096665430LL, -612839847LL, -2058204454LL, -758204894LL, -2009204716LL, + -899855004LL, -1949881849LL, -1037051943LL, -1880505655LL, -1169076299LL, -1801399139LL, + -1295231344LL, -1712937249LL, -1414846821LL, -1615545334LL, -1527282625LL, -1509697333LL, + -1631932364LL, -1395913683LL, -1728226787LL, -1274758968LL, -1815637038LL, -1146839308LL, + -1893677745LL, -1012799512LL, -1961909898LL, -873319991LL, -2019943519LL, -729113458LL, + -2067440097LL, -580921421LL, -2104114776LL, -429510489LL, -2129738276LL, -275668512LL, + -2144138540LL, -120200560LL, -2147202094LL, 36075218LL, -2138875104LL, 192331856LL, + -2119164126LL, 347737916LL, -2088136540LL, 501461906LL, -2045920656LL, 652676738LL, + -1992705499LL, 800564205LL, -1928740263LL, 944319463LL, -1854333428LL, 1083155478LL, + -1769851550LL, 1216307421LL, -1675717728LL, 1343036988LL, -1572409735LL, 1462636619LL, + -1460457846LL, 1574433591LL, -1340442348LL, 1677793958LL, -1212990750LL, 1772126320LL, + -1078774712LL, 1856885396LL, -938506696LL, 1931575376LL, -792936354LL, 1995753039LL, + -642846686LL, 2049030598LL, -489049961LL, 2091078284LL, -332383446LL, 2121626616LL, + -173704943LL, 2140468371LL, -13888177LL, 2147460214LL, 146181959LL, 2142523999LL, + 305614266LL, 2125647707LL, 463516183LL, 2096886025LL, 618998792LL, 2056360559LL, + 771181849LL, 2004259666LL, 919198820LL, 1940837907LL, 1062201882LL, 1866415124LL, + 1199366875LL, 1781375130LL, 1329898166LL, 1686164026LL, 1453033398LL, 1581288145LL, + 1568048096LL, 1467311630LL, 1674260102LL, 1344853659LL, 1771033810LL, 1214585318LL, + 1857784180LL, 1077226158LL, 1933980490LL, 933540421LL, 1999149823LL, 784332988LL, + 2052880248LL, 630445035LL, 2094823672LL, 472749443LL, 2124698365LL, 312145978LL, + 2142291105LL, 149556264LL, 2147458956LL, -14081422LL, 2140130647LL, -177817505LL, + 2120307546LL, -340696584LL, 2088064211LL, -501762995LL, 2043548522LL, -660066431LL, + 1986981374LL, -814667585LL, 1918655941LL, -964643785LL, 1838936498LL, -1109094589LL, + 1748256811LL, -1247147295LL, 1647118092LL, -1377962351LL, 1536086541LL, -1500738615LL, + 1415790460LL, -1614718436LL, 1286916977LL, -1719192528LL, 1150208377LL, -1813504602LL, + 1006458069LL, -1897055721LL, 856506195LL, -1969308353LL, 701234924LL, -2029790096LL, + 541563434LL, -2078097038LL, 378442624LL, -2113896741LL, 212849578LL, -2136930815LL, + 45781818LL, -2147017065LL, -121748635LL, -2144051194LL, -288721337LL, -2128008046LL, + -454113616LL, -2098942371LL, -616906842LL, -2056989111LL, -776092731LL, -2002363185LL, + -930679650LL, -1935358789LL, -1079698888LL, -1856348180LL, -1222210829LL, -1765779981LL, + -1357311029LL, -1664176981LL, -1484136113LL, -1552133452LL, -1601869485LL, -1430311996LL, + -1709746802LL, -1299439927LL, -1807061166LL, -1160305216LL, -1893168014LL, -1013752003LL, + -1967489657LL, -860675724LL, -2029519447LL, -702017853LL, -2078825531LL, -538760303LL, + -2115054166LL, -371919517LL, -2137932573LL, -202540280LL, -2147271301LL, -31689281LL, + -2142966081LL, 139551519LL, -2124999153LL, 310091687LL, -2093440047LL, 478839246LL, + -2048445818LL, 644707673LL, -1990260709LL, 806622936LL, -1919215254LL, 963530520LL, + -1835724802LL, 1114402397LL, -1740287494LL, 1258243891LL, -1633481659LL, 1394100398LL, + -1515962678LL, 1521063908LL, -1388459301LL, 1638279287LL, -1251769456LL, 1744950281LL, + -1106755553LL, 1840345184LL, -954339327LL, 1923802147LL, -795496223LL, 1994734070LL, + -631249390LL, 2052633055LL, -462663280LL, 2097074377LL, -290836919LL, 2127719939LL, + -116896882LL, 2144321191LL, 58009991LL, 2146721476LL, 232724086LL, 2134857783LL, + 406080664LL, 2108761899LL, 576917620LL, 2068560928LL, 744083306LL, 2014477175LL, + 906444356LL, 1946827389LL, 1062893473LL, 1866021361LL, 1212357105LL, 1772559873LL, + 1353802982LL, 1667032015LL, 1486247438LL, 1550111869LL, 1608762478LL, 1422554583LL, + 1720482533LL, 1285191856LL, 1820610859LL, 1138926843LL, 1908425522LL, 984728531LL, + 1983284934LL, 823625597LL, 2044632883LL, 656699800LL, 2092003031LL, 485078935LL, + 2125022828LL, 309929402LL, 2143416820LL, 132448430LL, 2147009312LL, -46143988LL, + 2135726357LL, -224613400LL, 2109597067LL, -401719386LL, 2068754203LL, -576224174LL, + 2013434051LL, -746901317LL, 1943975563LL, -912544390LL, 1860818776LL, -1071975623LL, + 1764502490LL, -1224054417LL, 1655661231LL, -1367685687LL, 1535021504LL, -1501827964LL, + 1403397351LL, -1625501193LL, 1261685245LL, -1737794175LL, 1110858343LL, -1837871594LL, + 951960135LL, -1924980559LL, 786097523LL, -1998456639LL, 614433374LL, -2057729302LL, + 438178602LL, -2102326750LL, 258583815LL, -2131880077LL, 76930601LL, -2146126729LL, + -105477504LL, -2144913226LL, -287324294LL, -2128197125LL, -467290359LL, -2096048180LL, + -644062666LL, -2048648709LL, -816344187LL, -1986293136LL, -982863511LL, -1909386701LL, + -1142384359LL, -1818443353LL, -1293714941LL, -1714082817LL, -1435717067LL, -1597026849LL, + -1567314965LL, -1468094701LL, -1687503717LL, -1328197824LL, -1795357252LL, -1178333819LL, + -1890035840LL, -1019579707LL, -1970793003LL, -853084517LL, -2036981813LL, -680061281LL, + -2088060495LL, -501778457LL, -2123597302LL, -319550859LL, -2143274607LL, -134730138LL, + -2146892182LL, 51305099LL, -2134369610LL, 237159480LL, -2105747830LL, 421431284LL, + -2061189760LL, 602723010LL, -2000980006LL, 779652018LL, -1925523641LL, 950861167LL, + -1835344052LL, 1115029356LL, -1731079849LL, 1270881902LL, -1613480873LL, 1417200665LL, + -1483403302LL, 1552833828LL, -1341803883LL, 1676705279LL, -1189733343LL, 1787823489LL, + -1028328990LL, 1885289830LL, -858806584LL, 1968306252LL, -682451508LL, 2036182259LL, + -500609305LL, 2088341106LL, -314675663LL, 2124325182LL, -126085896LL, 2143800504LL, + 63695984LL, 2146560289LL, 253188533LL, 2132527566LL, 440904392LL, 2101756782LL, + 625361956LL, 2054434393LL, 805097129LL, 1990878415LL, 978675045LL, 1911536923LL, + 1144701674LL, 1816985506LL, 1301835230LL, 1707923677LL, 1448797261LL, 1585170259LL, + 1584383348LL, 1449657773LL, 1707473325LL, 1302425851LL, 1817040907LL, 1144613732LL, + 1912162674LL, 977451871LL, 1992026305LL, 802252735LL, 2055937997LL, 620400841LL, + 2103328996LL, 433342112LL, 2133761180LL, 242572623LL, 2146931631LL, 49626835LL, + 2142676149LL, -143934609LL, 2120971668LL, -336537423LL, 2081937536LL, -526606446LL, + 2025835642LL, -712578559LL, 1953069367LL, -892915617LL, 1864181358LL, -1066117310LL, + 1759850125LL, -1230733842LL, 1640885488LL, -1385378312LL, 1508222872LL, -1528738703LL, + 1362916515LL, -1659589354LL, 1206131606LL, -1776801846LL, 1039135424LL, -1879355162LL, + 863287526LL, -1966345061LL, 680029070LL, -2036992567LL, 490871340LL, -2090651473LL, + 297383566LL, -2126814817LL, 101180131LL, -2145120238LL, -96092725LL, -2145354153LL, + -292770616LL, -2127454728LL, -487185002LL, -2091513573LL, -677677357LL, -2037776154LL, + -862613399LL, -1966640886LL, -1040397247LL, -1878656920LL, -1209485392LL, -1774520594LL, + -1368400361LL, -1655070604LL, -1515743939LL, -1521281882LL, -1650209843LL, -1374258246LL, + -1770595729LL, -1215223854LL, -1875814409LL, -1045513536LL, -1964904185LL, -866562056LL, + -2037038185LL, -679892406LL, -2091532624LL, -487103208LL, -2127853882LL, -289855327LL, + -2145624344LL, -89857806LL, -2144626926LL, 111146763LL, -2124808220LL, 311397306LL, + -2086280241LL, 509129658LL, -2029320715LL, 702592122LL, -1954371902LL, 890061078LL, + -1862037946LL, 1069856504LL, -1753080758LL, 1240357251LL, -1628414440LL, 1400015951LL, + -1489098304LL, 1547373418LL, -1336328506LL, 1681072389LL, -1171428375LL, 1799870500LL, + -995837498LL, 1902652341LL, -811099644LL, 1988440500LL, -618849626LL, 2056405455LL, + -420799206LL, 2105874232LL, -218722164LL, 2136337723LL, -14438646LL, 2147456584LL, + 190201062LL, 2139065639LL, 393333199LL, 2111176745LL, 593097481LL, 2063980046LL, + 787654198LL, 1997843617LL, 975201280LL, 1913311453LL, 1153991199LL, 1811099822LL, + 1322347521LL, 1692091985LL, 1478680975LL, 1557331316LL, 1621504867LL, 1408012862LL, + 1749449691LL, 1245473416LL, 1861276800LL, 1071180156LL, 1955890977LL, 886717958LL, + 2032351798LL, 693775484LL, 2089883646LL, 494130143LL, 2127884280LL, 289632081LL, + 2145931848LL, 82187314LL, 2143790267LL, -126259828LL, 2121412893LL, -333744799LL, + 2078944433LL, -538301305LL, 2016721053LL, -737979976LL, 1935268656LL, -930867059LL, + 1835299333LL, -1115102959LL, 1717705999LL, -1288900444LL, 1583555226LL, -1450562339LL, + 1434078348LL, -1598498528LL, 1270660880LL, -1731242092LL, 1094830341LL, -1847464418LL, + 908242583LL, -1945989122LL, 712666736LL, -2025804624LL, 509968902LL, -2086075256LL, + 302094739LL, -2126150752LL, 91051097LL, -2145574037LL, -121113132LL, -2144087186LL, + -332326767LL, -2121635495LL, -540516503LL, -2078369592LL, -743627303LL, -2014645549LL, + -939642809LL, -1931022953LL, -1126605577LL, -1828260957LL, -1302636926LL, -1707312301LL, + -1465956201LL, -1569315351LL, -1614899252LL, -1415584211LL, -1747935938LL, -1247596974LL, + -1863686452LL, -1066982221LL, -1960936312LL, -875503875LL, -2038649831LL, -675044532LL, + -2095981925LL, -467587449LL, -2132288109LL, -255197318LL, -2147132565LL, -40000034LL, + -2140294167LL, 175838363LL, -2111770398LL, 390133362LL, -2061779057LL, 600704064LL, + -1990757755LL, 805395440LL, -1899361139LL, 1002100552LL, -1788455873LL, 1188782505LL, + -1659113383LL, 1363495887LL, -1512600426LL, 1524407493LL, -1350367542LL, 1669816084LL, + -1174035492LL, 1798170992LL, -985379800LL, 1908089333LL, -786313522LL, 1998371662LL, + -578868423LL, 2068015861LL, -365174717LL, 2116229118LL, -147439579LL, 2142437822LL, + 72075359LL, 2146295272LL, 291077319LL, 2127687065LL, 507266241LL, 2086734102LL, + 718358960LL, 2023793136LL, 922113452LL, 1939454829LL, 1116352883LL, 1834539314LL, + 1298989198LL, 1710089271LL, 1468046015LL, 1567360568LL, 1621680536LL, 1407810531LL, + 1758204266LL, 1233083943LL, 1876102274LL, 1044996895LL, 1974050781LL, 845518637LL, + 2050932874LL, 636751598LL, 2105852137LL, 420909766LL, 2138144032LL, 200295659LL, + 2147384892LL, -22723910LL, 2133398377LL, -245742995LL, 2096259301LL, -466342360LL, + 2036294770LL, -682115725LL, 1954082561LL, -890696130LL, 1850446744LL, -1089782135LL, + 1726450552LL, -1277163554LL, 1583386556LL, -1450746452LL, 1422764203LL, -1608577097LL, + 1246294840LL, -1748864610LL, 1055874349LL, -1870002035LL, 853563560LL, -1970585573LL, + 641566635LL, -2049431752LL, 422207639LL, -2105592307LL, 197905535LL, -2138366585LL, + -28852132LL, -2147311297LL, -255536580LL, -2132247478LL, -479605876LL, -2093264545LL, + -698533449LL, -2030721368LL, -909836709LL, -1945244307LL, -1111105461LL, -1837722206LL, + -1300029772LL, -1709298349LL, -1474426984LL, -1561359447LL, -1632267537LL, -1395521744LL, + -1771699310LL, -1213614358LL, -1891070159LL, -1017660015LL, -1988948404LL, -809853381LL, + -2064140967LL, -592537191LL, -2115708951LL, -368176436LL, -2142980438LL, -139330887LL, + -2145560320LL, 91373766LL, -2123337022LL, 321275807LL, -2076485989LL, 547708126LL, + -2005469870LL, 768029200LL, -1911035349LL, 979654097LL, -1794206613LL, 1180085117LL, + -1656275512LL, 1366941726LL, -1498788465LL, 1537989399LL, -1323530241LL, 1691167039LL, + -1132504764LL, 1824612620LL, -927913132LL, 1936686725LL, -712129079LL, 2025993689LL, + -487672146LL, 2091400041LL, -257178838LL, 2132050022LL, -23372107LL, 2147377935LL, + 210970510LL, 2137117146LL, 443049719LL, 2101305594LL, 670077891LL, 2040287694LL, + 889312674LL, 1954712567LL, 1098090392LL, 1845528581LL, 1293858829LL, 1713974207LL, + 1474208986LL, 1561565278LL, 1636905413LL, 1390078747LL, 1779914734LL, 1201533101LL, + 1901431989LL, 998165640LL, 1999904442LL, 782406847LL, 2074052543LL, 556852138LL, + 2122887730LL, 324231303LL, 2145726844LL, 87375992LL, 2142202902LL, -150814385LL, + 2112272082LL, -387407930LL, 2056216764LL, -619476290LL, 1974644555LL, -844130994LL, + 1868483256LL, -1058559669LL, 1738971785LL, -1260061659LL, 1587647115LL, -1446082602LL, + 1416327358LL, -1614247524LL, 1227091142LL, -1762392006LL, 1022253507LL, -1888591014LL, + 804338579LL, -1991185000LL, 576049332LL, -2068802895LL, 340234776LL, -2120381699LL, + 99854976LL, -2145182332LL, -142055705LL, -2142801538LL, -382426664LL, -2113179618LL, + -618189966LL, -2056603856LL, -846319601LL, -1973707523LL, -1063870597LL, -1865464448LL, + -1268017480LL, -1733179138LL, -1456091575LL, -1578472546LL, -1625616653LL, -1403263607LL, + -1774342442LL, -1209746730LL, -1900275543LL, -1000365489LL, -2001707306LL, -777782819LL, + -2077238277LL, -544848046LL, -2125798850LL, -304561163LL, -2146665805LL, -60034770LL, + -2139474467LL, 185545840LL, -2104226268LL, 428963942LL, -2041291569LL, 667013481LL, + -1951407622LL, 896541435LL, -1835671676LL, 1114489907LL, -1695529216LL, 1317937378LL, + -1532757475LL, 1504138549LL, -1349444352LL, 1670562239LL, -1147962968LL, 1814926797LL, + -930942161LL, 1935232530LL, -701233251LL, 2029790674LL, -461873487LL, 2097248468LL, + -216046618LL, 2136609958LL, 32958895LL, 2147252189LL, 281793514LL, 2128936511LL, + 527091506LL, 2081814785LL, 765516508LL, 2006430345LL, 993807139LL, 1903713640LL, + 1208822035LL, 1774972546LL, 1407583710LL, 1621877416LL, 1587320585LL, 1446441017LL, + 1745506625LL, 1250993555LL, 1879897980LL, 1038153090LL, 1988566095LL, 810791673LL, + 2069926800LL, 571997637LL, 2122764899LL, 325034517LL, 2146253896LL, 73297124LL, + 2139970492LL, -179734650LL, 2103903611LL, -430543666LL, 2038457739LL, -675624377LL, + 1944450485LL, -911531987LL, 1823104308LL, -1134931247LL, 1676032460LL, -1342644199LL, + 1505219287LL, -1531696168LL, 1312995071LL, -1699359349LL, 1102005735LL, -1843193320LL, + 875177751LL, -1961081884LL, 635678716LL, -2051265664LL, 386874087LL, -2112369923LL, + 132280664LL, -2143427181LL, -124482567LL, -2143894201LL, -379745538LL, -2113663071LL, + -629839454LL, -2053066125LL, -871149650LL, -1962874560LL, -1100168194LL, -1844290703LL, + -1313545460LL, -1698933953LL, -1508139929LL, -1528820528LL, -1681065446LL, -1336337240LL, + -1829735234LL, -1124209600LL, -1951901969LL, -895464659LL, -2045693277LL, -653389065LL, + -2109642089LL, -401482886LL, -2142711336LL, -143409839LL, -2144312544LL, 117055392LL, + -2114317994LL, 376082001LL, -2053066177LL, 629839286LL, -1961360384LL, 874553426LL, + -1840460376LL, 1106563987LL, -1692067155LL, 1322379294LL, -1518301005LL, 1518729835LL, + -1321673030LL, 1692618875LL, -1105050545LL, 1841369476LL, -871616769LL, 1962667181LL, + -624825352LL, 2054597657LL, -368350369LL, 2115678675LL, -106032477LL, 2144885863LL, + 158177994LL, 2141671771LL, 420280180LL, 2105977878LL, 676283181LL, 2038239267LL, + 922267014LL, 1939381811LL, 1154443080LL, 1810811814LL, 1369213232LL, 1654398192LL, + 1563226488LL, 1472447351LL, 1733432510LL, 1267671088LL, 1877130975LL, 1043147907LL, + 1992016019LL, 802278275LL, 2076215008LL, 548734445LL, 2128320961LL, 286405547LL, + 2147418046LL, 19338764LL, 2133099660LL, -248322555LL, 2085478728LL, -512402895LL, + 2005189952LL, -768759722LL, 1893383889LL, -1013348756LL, 1751712847LL, -1242288354LL, + 1582308717LL, -1451921960LL, 1387753003LL, -1638877621LL, 1171039426LL, -1800123584LL, + 935529602LL, -1933019042LL, 684902431LL, -2035359161LL, 423097904LL, -2105413597LL, + 154256192LL, -2141957815LL, -117347094LL, -2144296601LL, -387368456LL, -2112279321LL, + -651465830LL, -2046306557LL, -905368572LL, -1947327913LL, -1144946990LL, -1816830934LL, + -1366280286LL, -1656821183LL, -1565721771LL, -1469793723LL, -1739960288LL, -1258696330LL, + -1886076750LL, -1026884973LL, -2001594854LL, -778072164LL, -2084525033LL, -516268960LL, + -2133400855LL, -245721481LL, -2147307178LL, 29157068LL, -2125899499LL, 303857815LL, + -2069414052LL, 573849923LL, -1978668397LL, 834655394LL, -1855052361LL, 1081923746LL, + -1700509365LL, 1311505300LL, -1517508342LL, 1519521861LL, -1309006581LL, 1702433559LL, + -1078404036LL, 1857100694LL, -829489738LL, 1980839475LL, -566381139LL, 2071470651LL, + -293457302LL, 2127360116LL, -15287020LL, 2147450712LL, 263447003LL, 2131284573LL, + 538026657LL, 2079015529LL, 803778318LL, 1991411225LL, 1056152768LL, 1869844802LL, + 1290803799LL, 1716276145LL, 1503664113LL, 1533222909LL, 1691017200LL, 1323721679LL, + 1849563896LL, 1091279821LL, 1976482414LL, 839818742LL, 2069480724LL, 573609435LL, + 2126840291LL, 297201324LL, 2147450294LL, 15345580LL, 2130831623LL, -267085845LL, + 2077150107LL, -545184084LL, 1987218616LL, -814088708LL, 1862487852LL, -1069073082LL, + 1705025866LL, -1305628220LL, 1517486521LL, -1519543652LL, 1303067317LL, -1706983837LL, + 1065457198LL, -1864558718LL, 808775145LL, -1989387096LL, 537500533LL, -2079151613LL, + 256396384LL, -2132144260LL, -29573192LL, -2147301488LL, -315329970LL, -2124228157LL, + -595771489LL, -2063209778LL, -865862262LL, -1965212659LL, -1120724693LL, -1831871834LL, + -1355728051LL, -1665466813LL, -1566573880LL, -1468885473LL, -1749376244LL, -1245576577LL, + -1900735300LL, -999491657LL, -2017802765LL, -735017179LL, -2098338000LL, -456898118LL, + -2140753557LL, -170154228LL, -2144149239LL, 120009549LL, -2108333904LL, 408296954LL, + -2033834454LL, 689416902LL, -1921891708LL, 958180837LL, -1774443047LL, 1209599160LL, + -1594092021LL, 1438974941LL, -1384065300LL, 1641993148LL, -1148157625LL, 1814803659LL, + -890665639LL, 1954096459LL, -616311698LL, 2057167505LL, -330158960LL, 2121973919LL, + -37519247LL, 2147177347LL, 256144677LL, 2132174514LL, 545320652LL, 2077114258LL, + 824550599LL, 1982900543LL, 1088534014LL, 1851181232LL, 1332229501LL, 1684322656LL, + 1550952403LL, 1485370289LL, 1740466616LL, 1257996110LL, 1897068759LL, 1006433494LL, + 2017663010LL, 735400728LL, 2099825046LL, 450014476LL, 2141853730LL, 155694734LL, + 2142809404LL, -141936990LL, 2102537880LL, -437164405LL, 2021679492LL, -724286051LL, + 1901662860LL, -997725723LL, 1744683284LL, -1252141562LL, 1553666016LL, -1482531674LL, + 1332214939LL, -1684334174LL, 1084547475LL, -1853519632LL, 815416834LL, -1986674014LL, + 530022972LL, -2081070374LL, 233913887LL, -2134727745LL, -67120943LL, -2146455924LL, + -367162933LL, -2115885071LL, -660280460LL, -2043479377LL, -940646328LL, -1930534314LL, + -1202654335LL, -1779157329LL, -1441032603LL, -1592232172LL, -1650951344LL, -1373367363LL, + -1828122867LL, -1126829638LL, -1968891702LL, -857463537LL, -2070312906LL, -570598566LL, + -2130216844LL, -271945674LL, -2147258957LL, 32515009LL, -2120953326LL, 336652997LL, + -2051689167LL, 634310503LL, -1940729692LL, 919427276LL, -1790193163LL, 1186164699LL, + -1603016304LL, 1429026586LL, -1382900596LL, 1642974191LL, -1134242366LL, 1823532974LL, + -862047892LL, 1966888834LL, -571835109LL, 2069971705LL, -269523772LL, 2130524628LL, + 38683788LL, 2147156682LL, 346428949LL, 2119378502LL, 647327592LL, 2047619408LL, + 935102723LL, 1933225582LL, 1203716187LL, 1778439089LL, 1447496693LL, 1586357959LL, + 1661261426LL, 1360877926LL, 1840428606LL, 1106616826LL, 1981118523LL, 828823052LL, + 2080240753LL, 533269782LL, 2135565565LL, 226137065LL, 2145777786LL, -86115897LL, + 2110511792LL, -396885662LL, 2030366628LL, -699563870LL, 1906900699LL, -987678073LL, + 1742605904LL, -1255031042LL, 1540861505LL, -1495835578LL, 1305868486LL, -1704841855LL, + 1042565572LL, -1877454468LL, 756528503LL, -2009836530LL, 453854534LL, -2098998407LL, + 141034484LL, -2142868994LL, -175185027LL, -2140347743LL, -487946283LL, -2091336099LL, + -790429038LL, -1996747402LL, -1075999746LL, -1858494767LL, -1338358179LL, -1679456947LL, + -1571678203LL, -1463422659LL, -1770739507LL, -1215014342LL, -1931047303LL, -939592765LL, + -2048937177LL, -643144383LL, -2121662596LL, -332153702LL, -2147462920LL, -13463330LL, + -2125610156LL, 305875331LL, -2056433163LL, 618757544LL, -1941318485LL, 918183420LL, + -1782687510LL, 1197415340LL, -1583950181LL, 1450131055LL, -1349436018LL, 1670568971LL, + -1084303724LL, 1853662237LL, -794431161LL, 1995158486LL, -486287958LL, 2091722323LL, + -166793413LL, 2141018031LL, 156837233LL, 2141770374LL, 477254799LL, 2093801831LL, + 787142843LL, 1998045144LL, 1079385248LL, 1856530565LL, 1347230875LL, 1672347817LL, + 1584451480LL, 1449583305LL, 1785489140LL, 1193233751LL, 1945589676LL, 909097941LL, + 2060918807LL, 603648840LL, 2128658123LL, 283888799LL, 2147078397LL, -42808994LL, + 2115588268LL, -368869265LL, 2034756829LL, -686689813LL, 1906309303LL, -988819041LL, + 1733095554LL, -1268131718LL, 1519031866LL, -1517998828LL, 1269017020LL, -1732447418LL, + 988824349LL, -1906306549LL, 684972022LL, -2035335742LL, 364574395LL, -2116332621LL, + 35177696LL, -2147216985LL, -295416189LL, -2127088980LL, -619333804LL, -2056259685LL, + -928817739LL, -1936253047LL, -1216413343LL, -1769778752LL, -1475150017LL, -1560676354LL, + -1698712660LL, -1313831630LL, -1881599006LL, -1035066874LL, -2019258866LL, -731007444LL, + -2108211692LL, -408927519LL, -2146139319LL, -76578563LL, -2131951349LL, 257995535LL, + -2065821225LL, 586652297LL, -1949191765LL, 901348832LL, -1784749649LL, 1194339543LL, + -1576369112LL, 1458368498LL, -1329025837LL, 1686851676LL, -1048682839LL, 1874044438LL, + -742150791LL, 2015189931LL, -416925972LL, 2106644485LL, -81009578LL, 2145976631LL, + 257287340LL, 2132036931LL, 589548592LL, 2064996540LL, 907462237LL, 1946353139LL, + 1203029451LL, 1778903705LL, 1468767596LL, 1566684397LL, 1697902343LL, 1314878658LL, + 1884543836LL, 1029695481LL, 2023842259LL, 718220554LL, 2112118623LL, 388243708LL, + 2146967125LL, 48066789LL, 2127326152LL, -293703414LL, 2053515714LL, -628372074LL, + 1927239961LL, -947377636LL, 1751554276LL, -1242511920LL, 1530797370LL, -1506133349LL, + 1270489699LL, -1731367718LL, 977200407LL, -1912291196LL, 658385854LL, -2044090585LL, + 322203578LL, -2123196436LL, -22693798LL, -2147385211LL, -367379574LL, -2115847466LL, + -702883330LL, -2029219869LL, -1020424711LL, -1889579758LL, -1311644568LL, -1700401946LL, + -1568827352LL, -1466478432LL, -1785108793LL, -1193802685LL, -1954663224LL, -889421122LL, + -2072865345LL, -561255304LL, -2136421819LL, -217899201LL, -2143468871LL, 131603390LL, + -2093632836LL, 477995606LL, -1988051637LL, 812052302LL, -1829356103LL, 1124826431LL, + -1621611170LL, 1407890431LL, -1370218028LL, 1653566088LL, -1081779395LL, 1855136543LL, + -763931081LL, 2007034518LL, -425143993LL, 2105001387LL, -74501578LL, 2146212424LL, + 278541559LL, 2129364424LL, 624413517LL, 2054722855LL, 953684686LL, 1924126756LL, + 1257326035LL, 1740950744LL, 1526959012LL, 1510024645LL, 1755090096LL, 1237512427LL, + 1935323377LL, 930753285LL, 2062545026LL, 598068782LL, 2133074223LL, 248540970LL, + 2144775962LL, -108232736LL, 2097132137LL, -462401396LL, 1991268420LL, -804132035LL, + 1829935652LL, -1123883341LL, 1617445706LL, -1412673933LL, 1359563075LL, -1662337661LL, + 1063354662LL, -1865758590LL, 737001516LL, -2017078833LL, 389577323LL, -2111873046LL, + 30799527LL, -2147284248LL, -329240235LL, -2122116660LL, -680358970LL, -2036882403LL, + -1012570584LL, -1893800165LL, -1316371397LL, -1696745295LL, -1583014741LL, -1451152157LL, + -1804766654LL, -1163870946LL, -1975135110LL, -842982532LL, -2089065879LL, -497576129LL, + -2143098965LL, -137495739LL, -2135480634LL, 226937688LL, -2066227251LL, 585220641LL, + -1937138489LL, 926969647LL, -1751758903LL, 1242223409LL, -1515288374LL, 1521735652LL, + -1234443398LL, 1757250053LL, -917272685LL, 1941748973LL, -572931919LL, 2069668396LL, + -211423784LL, 2137072352LL, 156689499LL, 2141781187LL, 520592990LL, 2083449349LL, + 869536372LL, 1963589761LL, 1193152523LL, 1785543422LL, 1481767903LL, 1554394459LL, + 1726695395LL, 1276832513LL, 1920500664LL, 960965895LL, 2057233754LL, 616090524LL, + 2132618551LL, 252421011LL, 2144193925LL, -119208485LL, 2091401704LL, -487665011LL, + 1975618190LL, -841849761LL, 1800127570LL, -1171033298LL, 1570037326LL, -1465182940LL, + 1292137502LL, -1715272261LL, 974707426LL, -1913563086LL, 627275142LL, -2053851053LL, + 260336320LL, -2131666778LL, -114959231LL, -2144425944LL, -487144232LL, -2091523069LL, + -844783711LL, -1974365400LL, -1176827254LL, -1796345141LL, -1472952903LL, -1562750139LL, + -1723891928LL, -1280615037LL, -1921724182LL, -958516783LL, -2060134481LL, -606320189LL, + -2134621568LL, -234880848LL, -2142652527LL, 144285826LL, -2083757179LL, 519359484LL, + -1959558747LL, 878582820LL, -1773739067LL, 1210631229LL, -1531938634LL, 1504972517LL, + -1241593840LL, 1752205179LL, -911715817LL, 1944364297LL, -552617154LL, 2075184940LL, + -175594568LL, 2140314183LL, 207422919LL, 2137464382LL, 584249462LL, 2066502073LL, + 942829835LL, 1929468879LL, 1271626531LL, 1730532929LL, 1559994092LL, 1475871500LL, + 1798528446LL, 1173487828LL, 1979379677LL, 832967196LL, 2096517668LL, 465179451LL, + 2145941422LL, 81936954LL, 2125824584LL, -304381489LL, 2036591638LL, -681228856LL, + 1880921463LL, -1036297594LL, 1663677237LL, -1357923527LL, 1391764092LL, -1635472704LL, + 1073918320LL, -1859698281LL, 720434235LL, -2023055304LL, 342836948LL, -2119962518LL, + -46488791LL, -2147001874LL, -434701907LL, -2103048384LL, -808927473LL, -1989325161LL, + -1156684509LL, -1809380889LL, -1466304905LL, -1568989540LL, -1727329349LL, -1275974754LL, + -1930866714LL, -939963822LL, -2069904394LL, -572078711LL, -2139558550LL, -184573741LL, + -2137255083LL, 209568518LL, -2062834392LL, 597069950LL, -1918575421LL, 964803921LL, + -1709137215LL, 1300241606LL, -1441418950LL, 1591882428LL, -1124342243LL, 1829653731LL, + -768562211LL, 2005265663LL, -386116327LL, 2112508564LL, 9977639LL, 2147481944LL, + 406161385LL, 2108746353LL, 788798824LL, 1997391966LL, 1144646140LL, 1817020492LL, + 1461312920LL, 1573639985LL, 1727698291LL, 1275475154LL, 1934386552LL, 932698729LL, + 2073988049LL, 557092294LL, 2141412691LL, 161647579LL, 2134065728LL, -239878556LL, + 2051957972LL, -633440394LL, 1897725540LL, -1005194522LL, 1676557325LL, -1341988744LL, + 1396031635LL, -1631831464LL, 1065866681LL, -1864324669LL, 697592706LL, -2031044724LL, + 304156472LL, -2125856790LL, -100528625LL, -2145150868LL, -502071420LL, -2087990072LL, + -886113788LL, -1956164770LL, -1238845350LL, -1754149495LL, -1547503612LL, -1488963002LL, + -1800841356LL, -1169935325LL, -1989543990LL, -808389116LL, -2106581170LL, -417245764LL, + -2147479112LL, -10569648LL, -2110502766LL, 396933658LL, -1996740093LL, 790447503LL, + -1810084191LL, 1155583607LL, -1557112681LL, 1478911205LL, -1246867516LL, 1748456362LL, + -890542108LL, 1954152759LL, -501086156LL, 2088226740LL, -92741761LL, 2145501624LL, + 319472842LL, 2123609040LL, 720313445LL, 2023098315LL, 1094873879LL, 1847438616LL, + 1429143065LL, 1602912459LL, 1710534208LL, 1298403241LL, 1928366026LL, 945083447LL, + 2074277385LL, 556014013LL, 2142558949LL, 145668815LL, 2130388363LL, -270598731LL, + 2037958919LL, -677127535LL, 1868495530LL, -1058538005LL, 1628156065LL, -1400316421LL, + 1325820371LL, -1689372250LL, 972773654LL, -1914546858LL, 582295024LL, -2067053642LL, + 169165761LL, -2140831894LL, -250884823LL, -2132799817LL, -661775411LL, -2042995731LL, + -1047688167LL, -1874600693LL, -1393680188LL, -1633840196LL, -1686267231LL, -1329767302LL, + -1913956778LL, -973934137LL, -2067709112LL, -579963173LL, -2141307604LL, -163033737LL, + -2131622667LL, 260697253LL, -2038757762LL, 674718489LL, -1866070307LL, 1062807538LL, + -1620065147LL, 1409669171LL, -1310163232LL, 1701543581LL, -948353092LL, 1926760147LL, + -548737464LL, 2076214210LL, -126991747LL, 2143747035LL, 300245307LL, 2126412709LL, + 716025236LL, 2024619992LL, 1103762361LL, 1842141933LL, 1447898460LL, 1585991268LL, + 1734532953LL, 1266164952LL, 1951992868LL, 895266493LL, 2091318951LL, 488019772LL, + 2146647306LL, 60692631LL, 2115469886LL, -369547579LL, 1998761811LL, -785321256LL, + 1800968735LL, -1169739231LL, 1529853072LL, -1507092509LL, 1196203629LL, -1783500808LL, + 813418847LL, -1987492901LL, 396979156LL, -2110494208LL, -36171246LL, -2147200478LL, + -468308896LL, -2095820849LL, -881654456LL, -1958178662LL, -1259105587LL, -1739664155LL, + -1584949122LL, -1449039176LL, -1845522728LL, -1098100229LL, -2029797971LL, -701212128LL, + -2129859532LL, -274730101LL, -2141259304LL, 163666878LL, -2063229054LL, 595704729LL, + -1898740995LL, 1003275080LL, -1654411888LL, 1369196683LL, -1340252803LL, 1677945374LL, + -969273224LL, 1916321390LL, -556954474LL, 2074025064LL, -120613191LL, 2144115368LL, + 321319450LL, 2123330418LL, 750073096LL, 2012254607LL, 1147335744LL, 1815323372LL, + 1496039599LL, 1540663419LL, 1781101452LL, 1199773257LL, 1990085219LL, 807055807LL, + 2113757168LL, 379221422LL, 2146508606LL, -65414510LL, 2086626104LL, -507710306LL, + 1936395730LL, -928520235LL, 1702034728LL, -1309525118LL, 1393451522LL, -1634035223LL, + 1023842428LL, -1887730101LL, 609140724LL, -2059302268LL, 167340396LL, -2140975349LL, + -282277245LL, -2128872427LL, -719981254LL, -2023216559LL, -1126456872LL, -1828352583LL, + -1483661565LL, -1552587071LL, -1775633253LL, -1207851317LL, -1989214254LL, -809200164LL, + -2114657735LL, -374166965LL, -2146088190LL, 77998303LL, -2081793601LL, 527175165LL, + -1924334157LL, 953266124LL, -1680460412LL, 1337097999LL, -1360842256LL, 1661290645LL, + -979618618LL, 1911053535LL, -553786058LL, 2074873311LL, -102451964LL, 2145059870LL, + 354015381LL, 2118124492LL, 794902495LL, 1994970746LL, 1200091209LL, 1780887235LL, + 1550981339LL, 1485340075LL, 1831353073LL, 1121572189LL, 2028128775LL, 706025441LL, + 2131997965LL, 257610031LL, 2137875004LL, -203147042LL, 2045166325LL, -655036605LL, + 1857832534LL, -1077142761LL, 1584239987LL, -1449814442LL, 1236806208LL, -1755587838LL, + 831453145LL, -1980016142LL, 386891460LL, -2112366742LL, -76232706LL, -2146151632LL, + -536290167LL, -2079464140LL, -971676759LL, -1915103791LL, -1361830231LL, -1660480857LL, + -1688208087LL, -1327302418LL, -1935179626LL, -931052130LL, -2090788853LL, -490285860LL, + -2147350445LL, -25774419LL, -2101848354LL, 440467647LL, -1956115643LL, 886222231LL, + -1716784272LL, 1290127906LL, -1395004471LL, 1632709643LL, -1005944356LL, 1897328175LL, + -568091241LL, 2071002316LL, -102385910LL, 2145063024LL, 368770281LL, 2115605524LL, + 822588918LL, 1983715132LL, 1236997491LL, 1755453064LL, 1591718471LL, 1441600001LL, + 1869271581LL, 1057166974LL, 2055849311LL, 620694663LL, 2142021245LL, 153372875LL, + 2123230540LL, -321978766LL, 2000055584LL, -782020405LL, 1778221085LL, -1204038216LL, + 1468355000LL, -1567071105LL, 1085500246LL, -1852961810LL, 648402473LL, -2047279289LL, + 178606606LL, -2140064937LL, -300595117LL, -2126363287LL, -765312822LL, -2006508045LL, + -1192250024LL, -1786146168LL, -1559876690LL, -1475995585LL, -1849525124LL, -1091345530LL, + -2046352489LL, -651321536LL, -2140119687LL, -177949373LL, -2125744956LL, 304937098LL, + -2003601334LL, 772890644LL, -1779539745LL, 1202088411LL, -1464633215LL, 1570550158LL, + -1074651882LL, 1859274478LL, -629292416LL, 2053233866LL, -151198404LL, 2142175832LL, + 335180466LL, 2121186533LL, 804833580LL, 1990984973LL, 1233475895LL, 1757929313LL, + 1598809658LL, 1433731471LL, 1881695602LL, 1034891257LL, 2067171612LL, 581876084LL, + 2145263949LL, 98085882LL, 2111546136LL, -391345332LL, 1967413199LL, -860850485LL, + 1720053423LL, -1285766104LL, 1382115431LL, -1643634749LL, 971084423LL, -1915404212LL, + 508396984LL, -2086458904LL, 18338107LL, -2147426824LL, -473223697LL, -2094716588LL, + -940197984LL, -1930752704LL, -1357659267LL, -1663892895LL, -1703185526LL, -1308028026LL, + -1958076120LL, -881882169LL, -2108382348LL, -408046720LL, -2145693016LL, 88202801LL, + -2067629718LL, 580246156LL, -1878021595LL, 1041543634LL, -1586746210LL, 1447071082LL, + -1209241124LL, 1774687059LL, -765708702LL, 2006357006LL, -280053713LL, 2129166074LL, + 221391538LL, 2136062742LL, 711287422LL, 2026289332LL, 1162776479LL, 1805471991LL, + 1550961208LL, 1485361096LL, 1854288674LL, 1083232092LL, 2055764431LL, 620975730LL, + 2143926549LL, 123924197LL, 2113522884LL, -380524996LL, 1965850371LL, -864413425LL, + 1708733356LL, -1300772298LL, 1356137786LL, -1665133196LL, 927438416LL, -1936914102LL, + 446375861LL, -2100601543LL, -60241713LL, -2146660008LL, -564022317LL, -2072114157LL, + -1036577855LL, -1880767025LL, -1451127366LL, -1583037466LL, -1784025194LL, -1195421415LL, + -2016126400LL, -739602996LL, -2133909793LL, -241261784LL, -2130291598LL, 271359470LL, + -2005079516LL, 769047715LL, -1765036816LL, 1223283815LL, -1423548037LL, 1607883466LL, + -999900701LL, 1900520150LL, -518219775LL, 2084040911LL, -6112220LL, 2147483647LL, + 506903415LL, 2086822269LL, 991093848LL, 1905127617LL, 1418237228LL, 1612569818LL, + 1763278371LL, 1225817132LL, 2005815530LL, 767126009LL, 2131329628LL, 263082249LL, + 2132080722LL, -256924206LL, 2007614950LL, -762404399LL, 1764847367LL, -1223557119LL, + 1417710639LL, -1613032795LL, 986385093LL, -1907569842LL, 496150741LL, -2089404866LL, + -24075104LL, -2147370169LL, -543431303LL, -2077609365LL, -1030939167LL, -1883863765LL, + -1457353872LL, -1577307181LL, -1796930300LL, -1175933566LL, -2028996148LL, -703528880LL, + -2139235230LL, -188284050LL, -2120599981LL, 338871615LL, -1973793476LL, 846119120LL, + -1707286510LL, 1302670728LL, -1336863067LL, 1680647314LL, -884716126LL, 1956797289LL, + -378143534LL, 2113950264LL, 152081158LL, 2142113343LL, 673566969LL, 2039138492LL, + 1154281506LL, 1810914812LL, 1564524507LL, 1471068088LL, 1878777110LL, 1040180189LL, + 2077310988LL, 544570758LL, 2147454732LL, 14711381LL, 2084434654LL, -516633743LL, + 1891732529LL, -1016428203LL, 1580932090LL, -1453420785LL, 1171057683LL, -1800111706LL, + 687440332LL, -2034503390LL, 160176712LL, -2141523213LL, -377726955LL, -2114024740LL, + -892412832LL, -1953299155LL, -1351303608LL, -1669058660LL, -1725174689LL, -1278886448LL, + -1990034149LL, -807181727LL, -2128688520LL, -283660779LL, -2131890756LL, 258495757LL, + -1998991947LL, 784735272LL, -1738049030LL, 1261334144LL, -1365374981LL, 1657567318LL, + -904553663LL, 1947706581LL, -384976339LL, 2112716609LL, 160011388LL, 2141535573LL, + 695236963LL, 2031852312LL, 1185967858LL, 1790323572LL, 1600172412LL, 1432210356LL, + 1910627099LL, 980450070LL, 2096730719LL, 464218209LL, 2145903181LL, -82932432LL, + 2054472094LL, -625238088LL, 1827982626LL, -1127057129LL, 1480903249LL, -1555218255LL, + 1035739459LL, -1881228860LL, 521606958LL, -2083195726LL, -27647625LL, -2147327144LL, + -575659018LL, -2068911537LL, -1085945254LL, -1852701044LL, -1524341213LL, -1512667221LL, + -1861301286LL, -1071137607LL, -2073915168LL, -557363552LL, -2147483648LL, -5608651LL, + -2076641224LL, 547119255LL, -1865650818LL, 1063543737LL, -1528328905LL, 1508638131LL, + -1087112541LL, 1852016354LL, -571616201LL, 2070032167LL, -16671408LL, 2147440411LL, + 540009002LL, 2078501511LL, 1060386775LL, 1867446957LL, 1508701745LL, 1528266108LL, + 1853944683LL, 1083820725LL, 2072027639LL, 564340071LL, 2147483647LL, 5392884LL, + 2074674646LL, -554529859LL, 1858113167LL, -1076658586LL, 1512371815LL, -1524634299LL, + 1061073867LL, -1867056641LL, 535330609LL, -2079711372LL, -28375033LL, -2147317655LL, + -590702076LL, -2064666876LL, -1112190609LL, -1837065677LL, -1556036411LL, -1480043560LL, + -1890705798LL, -1018336799LL, -2092203932LL, -484211687LL, -2145831690LL, 84762090LL, + -2047300170LL, 648336538LL, -1803115750LL, 1166426956LL, -1430199392LL, 1601970023LL, + -954758116LL, 1923594342LL, -410480427LL, 2107909882LL, 163823000LL, 2141247365LL, + 726970346LL, 2020715806LL, 1238357819LL, 1754493706LL, 1660896271LL, 1361323558LL, + 1963722471LL, 869236625LL, 2124485540LL, 313591200LL, 2131037112LL, -265441291LL, + 1982394786LL, -825765804LL, 1688899705LL, -1326422270LL, 1271546937LL, -1730591413LL, + 760527781LL, -2008326604LL, 193081625LL, -2138807551LL, -389192701LL, -2111943961LL, + -943374060LL, -1929202850LL, -1428384061LL, -1603588859LL, -1808046781LL, -1158768782LL, + -2053814441LL, -627395008LL, -2146951877LL, -48743098LL, -2080010177LL, 534168433LL, + -1857470558LL, 1077766848LL, -1495500165LL, 1541187046LL, -1020827382LL, 1889362249LL, + -468810699LL, 2095708658LL, 119162844LL, 2144196462LL, 698760937LL, 2030643101LL, + 1226043049LL, 1763121293LL, 1660800747LL, 1361440094LL, 1969646940LL, 855727285LL, + 2128615208LL, 284210392LL, 2125064488LL, -309643628LL, 1958734651LL, -880418548LL, + 1641861631LL, -1384221311LL, 1198331812LL, -1782071581LL, 661929312LL, -2042945872LL, + 73800708LL, -2146236638LL, -520675783LL, -2083428660LL, -1075380697LL, -1858853036LL, + -1547035940LL, -1489448910LL, -1898601250LL, -1003539508LL, -2102216707LL, -438706245LL, + -2141455199LL, 161083460LL, -2012699634LL, 748878117LL, -1725525884LL, 1278412560LL, + -1302049233LL, 1707760535LL, -775273426LL, 2002680545LL, -186561036LL, 2139386181LL, + 417584661LL, 2106514017LL, 989178564LL, 1906122772LL, 1482566973LL, 1553632332LL, + 1858092262LL, 1076694664LL, 2085313692LL, 513074126LL, 2145520472LL, -92304684LL, + 2033326318LL, -690914132LL, 1757205836LL, -1234506340LL, 1338916591LL, -1679011797LL, + 811840149LL, -1988138281LL, 218363648LL, -2136374398LL, -393496776LL, -2111146262LL, + -973964643LL, -1913941255LL, -1475553822LL, -1560294578LL, -1856971830LL, -1078625920LL, + -2086553703LL, -508007771LL, -2144938414LL, 104964053LL, -2026758086LL, 709950643LL, + -1741188565LL, 1256996672LL, -1311301988LL, 1700666148LL, -772260546LL, 2003844281LL, + -168487571LL, 2140885375LL, 449960729LL, 2099836564LL, 1031529637LL, 1883540512LL, + 1527466532LL, 1509511260LL, 1895929098LL, 1008578757LL, 2105553504LL, 422401107LL, + 2138175484LL, -199959623LL, 1990464340LL, -806120316LL, 1674318476LL, -1344780983LL, + 1215973950LL, -1770080678LL, 653886195LL, -2045534428LL, 35550473LL, -2147210846LL, + -586480435LL, -2065870023LL, -1159050380LL, -1807866275LL, -1632949753LL, -1394723398LL, + -1967171413LL, -861402858LL, -2132502660LL, -253398216LL, -2114135287LL, 377107732LL, + -1913056107LL, 975702098LL, -1546082711LL, 1490438360LL, -1044524931LL, 1876365082LL, + -451571922LL, 2099490665LL, 181382649LL, 2139831439LL, 799168845LL, 1993265514LL, + 1347643272LL, 1672015510LL, 1778449245LL, 1203701181LL, 2053314882LL, 629028019LL, + 2147483647LL, -1700832LL, 2052107671LL, -632955258LL, 1774950123LL, -1208854960LL, + 1340027222LL, -1678125531LL, 785494308LL, -1998693809LL, 160374564LL, -2141508406LL, + -479736545LL, -2093234602LL, -1077597743LL, -1857568668LL, -1579444784LL, -1455036916LL, + -1939851231LL, -921279249LL, -2125885806LL, -303953599LL, -2120182202LL, 341475744LL, + -1922630240LL, 956698078LL, -1550518252LL, 1485823476LL, -1037094990LL, 1880481915LL, + -428663023LL, 2104287591LL, 219548645LL, 2136252945LL, 848369676LL, 1972827196LL, + 1400084263LL, 1628355707LL, 1823746586LL, 1133898867LL, 2079925136LL, 534499467LL, + 2144430842LL, -114867829LL, 2010671707LL, -754305999LL, 1690398937LL, -1324511113LL, + 1212755749LL, -1772287151LL, 621696962LL, -2055546433LL, -27999436LL, -2147322585LL, + -675772566LL, -2038408618LL, -1260910878LL, -1738356123LL, -1728254154LL, -1274721865LL, + -2033429117LL, -690611526LL, -2147118806LL, -40731884LL, -2057950176LL, 613693184LL, + -1773709458LL, 1210674611LL, -1320749581LL, 1693339540LL, -741624242LL, 2015383769LL, + -91152942LL, 2145569713LL, 568725636LL, 2070828193LL, 1174833275LL, 1797649862LL, + 1668808974LL, 1351611949LL, 2002761869LL, 775063318LL, 2143970070LL, 123168954LL, + 2078159543LL, -541323533LL, 1811028149LL, -1154103677LL, 1367845624LL, -1655529100LL, + 791145176LL, -1996463765LL, 136708788LL, -2143149309LL, -531781930LL, -2080621597LL, + -1148921445LL, -1814320194LL, -1653986191LL, -1369710893LL, -1996943122LL, -789934441LL, + -2143463585LL, -131689453LL, -2078435006LL, 540264916LL, -1807604392LL, 1159458760LL, + -1357167960LL, 1664293658LL, -771322881LL, 2004205395LL, -108000604LL, 2144787664LL, + 566813902LL, 2071352276LL, 1185625241LL, 1790550485LL, 1686186809LL, 1329869278LL, + 2017798956LL, 735027636LL, 2146505699LL, 65509817LL, 2058651742LL, -611335635LL, + 1762419885LL, -1227051099LL, 1287168457LL, -1719004251LL, 680609542LL, -2036798690LL, + 4089477LL, -2147483648LL, -673569329LL, -2039137713LL, -1283052355LL, -1722078659LL, + -1761656313LL, -1228147095LL, -2059783109LL, -607512795LL, -2146148036LL, 76333863LL, + -2011148936LL, 753032675LL, -1668025482LL, 1352578739LL, -1151661684LL, 1812582031LL, + -515127599LL, 2084807379LL, 175706865LL, 2140304967LL, 848947094LL, 1972578791LL, + 1434145880LL, 1598437939LL, 1869697541LL, 1056413441LL, 2109376181LL, 402877626LL, + 2127319293LL, -293753093LL, 1920911995LL, -960143406LL, 1511241503LL, -1525754690LL, + 941044327LL, -1930340340LL, 270333991LL, -2130421974LL, -429853291LL, -2104044772LL, + -1084950404LL, -1853283808LL, -1624802476LL, -1404206241LL, -1991215657LL, -804262681LL, + -2144296066LL, -117356866LL, -2066882062LL, 582903761LL, -1766568729LL, 1221070505LL, + -1275076661LL, 1727992408LL, -645001373LL, 2048353359LL, 55735361LL, 2146781736LL, + 751156219LL, 2011850538LL, 1365449016LL, 1657506331LL, 1831250407LL, 1121739809LL, + 2097086069LL, 462610281LL, 2133140501LL, -247971479LL, 1934701557LL, -932045138LL, + 1522871886LL, -1514146450LL, 942435704LL, -1929661420LL, 257082752LL, -2132061611LL, + -457512412LL, -2098204148LL, -1122012006LL, -1831083644LL, -1662226857LL, -1359698543LL, + -2017440109LL, -736011998LL, -2147305063LL, -29312447LL, -2036526087LL, 681424793LL, + -1696769503LL, 1316340194LL, -1165555713LL, 1803679054LL, -502221257LL, 2087954037LL, + 218627568LL, 2136347406LL, 915457236LL, 1942605544LL, 1509019049LL, 1527952802LL, + 1931391720LL, 938884591LL, 2133820068LL, 242054060LL, 2092438355LL, -483197666LL, + 1811196460LL, -1153839519LL, 1321618868LL, -1692661166LL, 679386000LL, -2037207136LL, + -41905815LL, -2147096215LL, -759117950LL, -2008859923LL, -1389131635LL, -1637709239LL, + -1858502009LL, -1075987237LL, -2112081089LL, -388447840LL, -2119590963LL, 345126649LL, + -1879353752LL, 1039137972LL, -1418706906LL, 1612156620LL, -791015038LL, 1996515330LL, + -69589051LL, 2146377324LL, 660807377LL, 2043309047LL, 1313888818LL, 1698668428LL, + 1812057217LL, 1152487265LL, 2095680134LL, 468938194LL, 2130322662LL, -271115487LL, + 1911045799LL, -979633710LL, 1463222101LL, -1571864923LL, 839728924LL, -1976520576LL, + 114812541LL, -2144433802LL, -624678758LL, -2054642232LL, -1289667173LL, -1717130408LL, + -1799589418LL, -1171860136LL, -2092215559LL, -484161449LL, -2131339744LL, 263000285LL, + -1911381715LL, 978978136LL, -1458300897LL, 1576431650LL, -826666943LL, 1982019177LL, + -93199090LL, 2145481807LL, 652475484LL, 2045984847LL, 1318741353LL, 1694903979LL, + 1823267013LL, 1134669842LL, 2103241563LL, 433766275LL, 2123296267LL, -321545043LL, + 1880100434LL, -1037786399LL, 1403020138LL, -1625826788LL, 750710270LL, -2012016984LL, + 4016458LL, -2147483648LL, -743969357LL, -2014519260LL, -1399486815LL, -1628869211LL, + -1879882975LL, -1038180261LL, -2124105161LL, -316157428LL, -2100570768LL, 446520659LL, + -1811386772LL, 1153540730LL, -1292339969LL, 1715119721LL, -608608245LL, 2059459700LL, + 153312536LL, 2142025564LL, 896481298LL, 1951435250LL, 1525827234LL, 1511168259LL, + 1960346768LL, 876823130LL, 2143613721LL, 129222558LL, 2051229248LL, -635796213LL, + 1694213479LL, -1319628334LL, 1117851405LL, -1833626594LL, 396087832LL, -2110661669LL, + -377854274LL, -2114001987LL, -1103456461LL, -1842325186LL, -1685956794LL, -1330160871LL, + -2048777845LL, -643651766LL, -2143694961LL, 127867768LL, -1957382547LL, 883420521LL, + -1513433355LL, 1523580563LL, -869530001LL, 1963592583LL, -110084127LL, 2144681733LL, + 664736423LL, 2042034216LL, 1352179416LL, 1668349208LL, 1860553309LL, 1072436310LL, + 2121532152LL, 332985857LL, 2099460167LL, -451713692LL, 1796373976LL, -1176783238LL, + 1252016997LL, -1744772676LL, 538783776LL, -2078819448LL, -247785369LL, -2133162128LL, + -1001729027LL, -1899557109LL, -1620924938LL, -1408680445LL, -2020969664LL, -726264324LL, + -2146786025LL, 55569932LL, -1980349353LL, 830659192LL, -1543430804LL, 1493184385LL, + -894922308LL, 1952150690LL, -123044866LL, 2143977195LL, 666550429LL, 2041442818LL, + 1365198940LL, 1657712312LL, 1876196689LL, 1044827372LL, 2128267170LL, 286804998LL, + 2085635396LL, -511764836LL, 1753268482LL, -1240091885LL, 1176494793LL, -1796562900LL, + 434987191LL, -2102989395LL, -368115875LL, -2115719489LL, -1120484954LL, -1832018482LL, + -1716305396LL, -1290764905LL, -2071220390LL, -567295646LL, -2134393667LL, 236942874LL, + -1895951516LL, 1008536614LL, -1388693894LL, 1638080438LL, -683762707LL, 2035742325LL, + 119188900LL, 2144195014LL, 905990085LL, 1947038833LL, 1564158349LL, 1471457411LL, + 1999022890LL, 784656445LL, 2147449344LL, -15477928LL, 1987162171LL, -814226478LL, + 1540267433LL, -1496447288LL, 870397099LL, -1963208380LL, 73811796LL, -2146236257LL, + -734319198LL, -2018056879LL, -1436522864LL, -1596302075LL, -1930126209LL, -941483442LL, + -2142365938LL, -148480443LL, -2041267691LL, 667086551LL, -1640647532LL, 1385660105LL, + -998429510LL, 1901293445LL, -208446911LL, 2137364765LL, 613140145LL, 2058115015LL, + 1344864900LL, 1674251072LL, 1877928363LL, 1041711725LL, 2132467044LL, 253697774LL, + 2069669697LL, -572927221LL, 1697883855LL, -1314902531LL, 1071726118LL, -1860962488LL, + 284245532LL, -2128610516LL, -546765540LL, -2076734383LL, -1296321423LL, -1712112444LL, + -1851051077LL, -1088755327LL, -2126433707LL, -300096557LL, -2079829939LL, 534869775LL, + -1717277988LL, 1289470653LL, -1092944992LL, 1848580400LL, -301229014LL, 2126273579LL, + 537368631LL, 2079185708LL, 1294510121LL, 1713482360LL, 1853670658LL, 1084289327LL, + 2128162452LL, 287581000LL, 2074732832LL, -554312122LL, 1700580818LL, -1311412649LL, + 1062625843LL, -1866173778LL, 259049144LL, -2131823584LL, -585668565LL, -2066100333LL, + -1339957542LL, -1678181169LL, -1885665800LL, -1027639404LL, -2136665360LL, -215498013LL, + -2052614106LL, 631311006LL, -1645649830LL, 1379715511LL, -978876105LL, 1911433970LL, + -156780702LL, 2141774513LL, 690992915LL, 2033299546LL, 1430025151LL, 1602125563LL, + 1942459213LL, 915767689LL, 2145909412LL, 82771052LL, 2006889031LL, -764313202LL, + 1546542155LL, -1489961615LL, 837667446LL, -1977395131LL, -6592110LL, -2147483648LL, + -850670861LL, -1971836033LL, -1558298568LL, -1477661607LL, -2014545353LL, -743898697LL, + -2144621655LL, 111248418LL, -1926338162LL, 949209955LL, -1394119788LL, 1633465111LL, + -633816976LL, 2051841683LL, 230947094LL, 2135050747LL, 1058756186LL, 1868371909LL, + 1713500094LL, 1294486648LL, 2086826280LL, 506886901LL, 2116230583LL, -365166228LL, + 1795742251LL, -1177747011LL, 1177343172LL, -1796007045LL, 362774373LL, -2116641917LL, + -513021346LL, -2085326677LL, -1304158219LL, -1706150519LL, -1878113987LL, -1041377023LL, + -2138035195LL, -201454107LL, -2039271088LL, 673165418LL, -1597283985LL, 1435430989LL, + -885498351LL, 1956443437LL, -23331546LL, 2147378376LL, 843683683LL, 1974835714LL, + 1568404835LL, 1466930307LL, 2027099095LL, 708976383LL, 2140716235LL, -170623133LL, + 1888734543LL, -1021988297LL, 1313119332LL, -1699263333LL, 511596042LL, -2085676807LL, + -378733015LL, -2113844733LL, -1204719676LL, -1777759476LL, -1823501160LL, -1134293512LL, + -2127308396LL, -293831998LL, -2062428437LL, 598470713LL, -1638953385LL, 1387663523LL, + -929506380LL, 1935922556LL, -57035075LL, 2146747599LL, 826321829LL, 1982163083LL, + 1565694816LL, 1469822437LL, 2030682686LL, 698645890LL, 2138507488LL, -196377133LL, + 1868988428LL, -1057667485LL, 1268587153LL, -1732762213LL, 442676081LL, -2101384339LL, + -462737221LL, -2097058062LL, -1286700928LL, -1719354232LL, -1881928270LL, -1034468096LL, + -2141242526LL, -163886228LL, -2017090953LL, 736968345LL, -1530538703LL, 1506396206LL, + -767997393LL, 2005482051LL, 133868298LL, 2143328610LL, 1012468111LL, 1893854951LL, + 1708549501LL, 1301013780LL, 2095140919LL, 471341472LL, 2100903015LL, -444954801LL, + 1723561198LL, -1281060128LL, 1030845148LL, -1883915214LL, 148613598LL, -2142356705LL, + -761808678LL, -2007841077LL, -1533040628LL, -1503849955LL, -2022458849LL, -722106956LL, + -2138737806LL, 193852655LL, -1859149651LL, 1074867819LL, -1234301993LL, 1757349380LL, + -379281934LL, 2113746311LL, 547305366LL, 2076592182LL, 1372632335LL, 1651562510LL, + 1941893475LL, 916966731LL, 2147483631LL, 9607775LL, 1949586460LL, -900494801LL, + 1384190276LL, -1641887795LL, 556866917LL, -2074048574LL, -376679176LL, -2114211685LL, + -1239760359LL, -1753502924LL, -1868128365LL, -1059185849LL, -2141353742LL, -162426613LL, + -2006146487LL, 766260090LL, -1487059272LL, 1549333074LL, -682369888LL, 2036209613LL, + 254243058LL, 2132402101LL, 1142871977LL, 1818136930LL, 1811898898LL, 1152736153LL, + 2131247827LL, 263744101LL, 2037909708LL, -677275627LL, 1548688788LL, -1487730248LL, + 757535960LL, -2009457022LL, -182194909LL, -2139762433LL, -1087278298LL, -1851919047LL, + -1780289797LL, -1200977307LL, -2124487884LL, -313575324LL, -2051029897LL, 636439012LL, + -1573062312LL, 1461934751LL, -783743151LL, 1999381136LL, 161603770LL, 2141415997LL, + 1075849412LL, 1858581797LL, 1777043782LL, 1205775124LL, 2124728475LL, 311940960LL, + 2048313123LL, -645129138LL, 1561738113LL, -1474025888LL, 761316913LL, -2008027592LL, + -193008998LL, -2138814106LL, -1109422283LL, -1838738821LL, -1802730158LL, -1167022805LL, + -2131899330LL, -258425034LL, -2028998544LL, 703521969LL, -1513561267LL, 1523453492LL, + -689267663LL, 2033885036LL, 276587739LL, 2129619092LL, 1186846236LL, 1789741396LL, + 1854688708LL, 1082547019LL, 2142106332LL, 152179881LL, 1988692931LL, -810480524LL, + 1424699553LL, -1606863228LL, 565462537LL, -2071721596LL, -411862084LL, -2107640357LL, + -1304634824LL, -1705786103LL, -1926729183LL, -948415999LL, -2147483648LL, 7596593LL, + -1919481135LL, 963000739LL, -1289039126LL, 1717601928LL, -387266571LL, 2112298003LL, + 596928155LL, 2062875428LL, 1456237617LL, 1578337814LL, 2008637193LL, 759707101LL, + 2136136198LL, -220681661LL, 1810311054LL, -1155228176LL, 1099029369LL, -1844969566LL, + 152706502LL, -2142068854LL, -827212288LL, -1981791635LL, -1631005498LL, -1396996535LL, + -2085621744LL, -511820469LL, -2092176291LL, 484331108LL, -1647825250LL, 1377116624LL, + -847105176LL, 1973370486LL, 137796944LL, 2143079619LL, 1093813381LL, 1848066704LL, + 1813012365LL, 1150984107LL, 2137943617LL, 202423669LL, 1996401064LL, -791303384LL, + 1417867812LL, -1612894640LL, 527817726LL, -2081630779LL, -479137756LL, -2093371745LL, + -1381593904LL, -1644073154LL, -1980023972LL, -831434497LL, -2141083860LL, 165946242LL, + -1827674057LL, 1127557446LL, -1107908695LL, 1839651210LL, -140742908LL, 2142888165LL, + 858811979LL, 1968303899LL, 1667348435LL, 1353413259LL, 2103068206LL, 434605997LL, + 2066928090LL, -582740527LL, 1565557471LL, -1469968727LL, 710559923LL, -2026544559LL, + -305924581LL, -2125603068LL, -1254142277LL, -1743245651LL, -1918606274LL, -964742566LL, + -2147235228LL, 34045964LL, -1886510446LL, 1026088003LL, -1194449272LL, 1784676214LL, + -228158919LL, 2135350501LL, 791474966LL, 1996333046LL, 1630113879LL, 1398036836LL, + 2093882490LL, 476900799LL, 2074460679LL, -555329763LL, 1574805528LL, -1460056781LL, + 709303840LL, -2026984538LL, -321984698LL, -2123229641LL, -1279299382LL, -1724868500LL, + -1938868813LL, -923344994LL, -2145400127LL, 95060761LL, -1849016463LL, 1092207110LL, + -1117774270LL, 1833673617LL, -122520852LL, 2144007205LL, 902661887LL, 1948584043LL, + 1715358570LL, 1292022921LL, 2122230623LL, 328504846LL, 2025322751LL, -714035018LL, + 1446105573LL, -1587626191LL, 521251372LL, -2083284728LL, -529182976LL, -2081284130LL, + -1453867544LL, -1580521249LL, -2030328591LL, -699674255LL, -2118715390LL, 350461622LL, + -1696157170LL, 1317129115LL, -863172451LL, 1966395579LL, 179754637LL, 2139968814LL, + 1180097829LL, 1794198252LL, 1894340929LL, 1011558548LL, 2147425330LL, -18512254LL, + 1876044272LL, -1045101020LL, 1144987390LL, -1816805474LL, 132203119LL, -2143431965LL, + -914118293LL, -1943235961LL, -1736193378LL, -1263887181LL, -2130252357LL, -271667345LL, + -1997390551LL, 788802408LL, -1368894780LL, 1654661698LL, -399443485LL, 2110029184LL, + 670506595LL, 2040146847LL, 1574119520LL, 1460796355LL, 2084757074LL, 515331149LL, + 2073119436LL, -560316032LL, 1540474038LL, -1496234605LL, 619317761LL, -2056264517LL, + -459081553LL, -2097861383LL, -1422445567LL, -1608858869LL, -2026203177LL, -711532810LL, + -2115834547LL, 367453974LL, -1666889993LL, 1353977845LL, -792205830LL, 1996043130LL, + 285917748LL, 2128386547LL, 1291861913LL, 1715479831LL, 1967072561LL, 861628569LL, + 2136733341LL, -214822912LL, 1755484826LL, -1236952415LL, 920121567LL, -1940400617LL, + -154414553LL, -2141946404LL, -1189947088LL, -1787681230LL, -1916962219LL, -968005219LL, + -2144943543LL, 104859199LL, -1812745380LL, 1151404552LL, -1005575274LL, 1897523813LL, + 66267704LL, 2146482435LL, 1121760193LL, 1831237920LL, 1882689169LL, 1033082643LL, + 2147156131LL, -38714334LL, 1843591456LL, -1101339546LL, 1050717398LL, -1872904483LL, + -22251821LL, -2147389836LL, -1090368676LL, -1850101187LL, -1868462216LL, -1058596807LL, + -2147438449LL, 16922223LL, -1850918204LL, 1088981200LL, -1056757318LL, 1869503202LL, + 22763473LL, 2147384473LL, 1097221682LL, 1846045187LL, 1876016738LL, 1045150445LL, + 2147136069LL, -39811498LL, 1835334430LL, -1115045194LL, 1023642588LL, -1887838474LL, + -68097795LL, -2146425154LL, -1142312965LL, -1818488202LL, -1904646102LL, -992018890LL, + -2144805672LL, 107642378LL, -1795061647LL, 1178784092LL, -949991327LL, 1925952941LL, + 158441977LL, 2141652258LL, 1224103383LL, 1764468521LL, 1951099734LL, 897211281LL, + 2136159764LL, -220453430LL, 1725990250LL, -1277785549LL, 833286945LL, -1979245089LL, + -293572223LL, -2127344260LL, -1339196041LL, -1678788914LL, -2009355234LL, -757805909LL, + -2114046312LL, 377606201LL, -1621924854LL, 1407529048LL, -670363317LL, 2040193931LL, + 472244606LL, 2094937537LL, 1481783331LL, 1554379752LL, 2070313631LL, 570595935LL, + 2068531606LL, -577022744LL, 1475086032LL, -1560736829LL, 458222393LL, -2098049211LL, + -691282782LL, -2033201015LL, -1642921247LL, -1382963495LL, -2121515849LL, -333089708LL, + -1987201089LL, 814131490LL, -1276964006LL, 1726598152LL, -195225957LL, 2138612886LL, + 944396066LL, 1928702757LL, 1809738474LL, 1156124954LL, 2147035716LL, 44898645LL, + 1855835643LL, -1080579622LL, 1019631940LL, -1890007661LL, -117322103LL, -2144297968LL, + -1220818394LL, -1766742965LL, -1964759164LL, -866890813LL, -2127766379LL, 290496966LL, + -1659649495LL, 1362843280LL, -697608660LL, 2031039244LL, 473249533LL, 2094710751LL, + 1503948948LL, 1532943513LL, 2085606472LL, 511882699LL, 2042371328LL, -663699941LL, + 1385273123LL, -1640974292LL, 310295203LL, -2124969444LL, -859403739LL, -1968045596LL, + -1770298673LL, -1215656555LL, -2145446359LL, -94011568LL, -1869196002LL, 1057300599LL, + -1023605074LL, 1887858815LL, 135122536LL, 2143249904LL, 1253678435LL, 1743579259LL, + 1989191608LL, 809255830LL, 2114600503LL, -374490273LL, 1589396749LL, -1444159349LL, + 573510503LL, -2069508143LL, -620625768LL, -2055870110LL, -1623714603LL, -1405464030LL, + -2123804062LL, -318173786LL, -1963757538LL, 869157398LL, -1191395514LL, 1786716257LL, + -46083803LL, 2147010604LL, 1114781685LL, 1835494496LL, 1927033224LL, 947798084LL, + 2134189432LL, -238775466LL, 1669079189LL, -1351278251LL, 676464784LL, -2038179003LL, + -531191768LL, -2080772347LL, -1571576921LL, -1463531425LL, -2113517157LL, -380556802LL, + -1982844262LL, 824685931LL, -1219159691LL, 1767887977LL, -64759000LL, 2146528482LL, + 1111532124LL, 1837464174LL, 1931905599LL, 937826747LL, 2131140668LL, -264608589LL, + 1643014461LL, -1382852752LL, 623196082LL, -2055092430LL, -599543279LL, -2062116900LL, + -1628803183LL, -1399563662LL, -2129049657LL, -280937379LL, -1935494308LL, 930397784LL, + -1109222131LL, 1838859570LL, 81134643LL, 2145971906LL, 1246025555LL, 1749056480LL, + 2002219227LL, 776464049LL, 2099179419LL, -453016579LL, 1502816612LL, -1534053612LL, + 408383584LL, -2108317125LL, -822597751LL, -1983711469LL, -1781299152LL, -1199479714LL, + -2147453790LL, -14848273LL, -1796955031LL, 1175895774LL, -844844169LL, 1974339531LL, + 391490287LL, 2111519265LL, 1497471492LL, 1539271705LL, 2100235325LL, 448095782LL, + 1994784956LL, -795368614LL, 1214574720LL, -1771041079LL, 21942246LL, -2147393022LL, + -1179303118LL, -1794720705LL, -1980291380LL, -830797391LL, -2106537543LL, 417465963LL, + -1512779243LL, 1524230040LL, -400186304LL, 2109888427LL, 850879502LL, 1971746009LL, + 1810408392LL, 1155075628LL, 2146648461LL, -60651764LL, 1741473895LL, -1256601339LL, + 732877224LL, -2018580994LL, -531018535LL, -2080816563LL, -1611471615LL, -1419484937LL, + -2131362909LL, -262812483LL, -1907371493LL, 986768586LL, -1015579054LL, 1892188531LL, + 233293238LL, 2134795662LL, 1401370618LL, 1627248796LL, 2076935460LL, 546001233LL, + 2019971188LL, -729036797LL, 1248350785LL, -1747397656LL, 33412083LL, -2147245185LL, + -1194571257LL, -1784594566LL, -1998418071LL, -786195564LL, -2089987926LL, 493688891LL, + -1434323086LL, 1598278929LL, -264052207LL, 2131209676LL, 1002170212LL, 1899324385LL, + 1908957739LL, 983696399LL, 2128162622LL, -287579737LL, 1578423653LL, -1456144575LL, + 456464081LL, -2098432461LL, -832257051LL, -1979678371LL, -1819490869LL, -1140715227LL, + -2144430680LL, 114870845LL, -1686318503LL, 1329702282LL, -610432195LL, 2058919811LL, + 690435836LL, 2033488778LL, 1738714026LL, 1260417307LL, 2147390198LL, 22216908LL, + 1763585146LL, -1225375733LL, 726856030LL, -2020756929LL, -580392073LL, -2067588763LL, + -1673220076LL, -1346147402LL, -2143996128LL, -122714524LL, -1815101051LL, 1147687427LL, + -807060843LL, 1990083176LL, 504423341LL, 2087423135LL, 1627706693LL, 1400838740LL, + 2139406352LL, 186329582LL, 1844614472LL, -1099625255LL, 852267102LL, -1971146631LL, + -463879162LL, -2096805755LL, -1605184806LL, -1426590338LL, -2136914712LL, -213011184LL, + -1854460874LL, 1082937264LL, -863219423LL, 1966374959LL, 459475841LL, 2097775060LL, + 1607134606LL, 1424393418LL, 2137920445LL, 202668255LL, 1845393374LL, -1098317599LL, + 839970848LL, -1976417776LL, -491465532LL, -2090511871LL, -1633574673LL, -1393991406LL, + -2141900633LL, -155048159LL, -1816506916LL, 1145460989LL, -781820144LL, 2000133874LL, + 559647110LL, 2073300114LL, 1683025924LL, 1333867306LL, 2146371079LL, 69781402LL, + 1765250997LL, -1222974721LL, 687405843LL, -2034515043LL, -663212000LL, -2042529827LL, + -1752367611LL, -1241364576LL, -2146841077LL, 53400769LL, -1687542873LL, 1328148074LL, + -554968141LL, 2074557450LL, 800423673LL, 1992761952LL, 1836599329LL, 1112960536LL, + 2136788973LL, -214268842LL, 1578010523LL, -1456592271LL, 382795511LL, -2113112834LL, + -968138304LL, -1916895009LL, -1928543025LL, -944722210LL, -2107708198LL, 411514766LL, + -1430410026LL, 1601781948LL, -169873469LL, 2140775854LL, 1161189336LL, 1806493171LL, + 2018543752LL, 732979791LL, 2049296596LL, -641998219LL, 1238272210LL, -1754554127LL, + -83255737LL, -2145890662LL, -1371683502LL, -1652350636LL, -2094258138LL, -475248467LL, + -1949882872LL, 899852786LL, -995833938LL, 1902654204LL, 373436112LL, 2114786921LL, + 1588292434LL, 1445373791LL, 2140653401LL, 171409659LL, 1797197980LL, -1175524425LL, + 699294013LL, -2030459588LL, -693697799LL, -2032378315LL, -1795672451LL, -1177853430LL, + -2140372859LL, 174877891LL, -1579598356LL, 1454870196LL, -348394995LL, 2119056200LL, + 1032029893LL, 1883266458LL, 1974202179LL, 845165079LL, 2074646960LL, -554633433LL, + 1287821276LL, -1718515235LL, -51737088LL, -2146881815LL, -1370325052LL, -1653477398LL, + -2100284253LL, -447866397LL, -1924927762LL, 952066891LL, -917287213LL, 1941742110LL, + 488668189LL, 2091167534LL, 1683791734LL, 1332900465LL, 2147483647LL, -5952078LL, + 1675380122LL, -1343458113LL, 470847323LL, -2095252026LL, -940958850LL, -1930382008LL, + -1941224149LL, -918382849LL, -2088877844LL, 498364930LL, -1316252188LL, 1696837774LL, + 38301141LL, 2147163542LL, 1377165492LL, 1647784410LL, 2106581367LL, 417244768LL, + 1900544341LL, -999854720LL, 847951177LL, -1973007109LL, -584036946LL, -2066562145LL, + -1756159897LL, -1235993798LL, -2142310305LL, 149280978LL, -1566659315LL, 1468794351LL, + -285359547LL, 2128461459LL, 1125832886LL, 1828736877LL, 2029467989LL, 702166599LL, + 2014695863LL, -743490977LL, 1085421070LL, -1853008190LL, -338440915LL, -2120668762LL, + -1609344513LL, -1421896090LL, -2146265752LL, -72949133LL, -1701178372LL, 1310637402LL, + -475273357LL, 2094252489LL, 970254106LL, 1915824946LL, 1970125090LL, 854625872LL, + 2061370020LL, -602106215LL, 1199008465LL, -1781616388LL, -220043168LL, -2136202064LL, + -1538165891LL, -1498607335LL, -2141334659LL, -162678000LL, -1745944249LL, 1250382714LL, + -533833181LL, 2080096245LL, 929526582LL, 1935912856LL, 1957763946LL, 882574975LL, + 2065714700LL, -587027282LL, 1199678326LL, -1781165395LL, -234057929LL, -2134711957LL, + -1558270234LL, -1477691487LL, -2144215074LL, -118827471LL, -1710999524LL, 1297789999LL, + -461986301LL, 2097223620LL, 1008801799LL, 1895810429LL, 1998137785LL, 786907646LL, + 2030075725LL, -700407599LL, 1086362322LL, -1852456520LL, -381437532LL, -2113358385LL, + -1666476237LL, -1354487063LL, -2146661112LL, 60202338LL, -1586809419LL, 1447001769LL, + -255702847LL, 2132227546LL, 1201078789LL, 1780221333LL, 2073328033LL, 559543671LL, + 1932910169LL, -935754525LL, 845543055LL, -1974040322LL, -657871305LL, -2044256246LL, + -1839033994LL, -1108932920LL, -2114705772LL, 373895372LL, -1345966213LL, 1673365832LL, + 89781631LL, 2145627533LL, 1482291688LL, 1553894978LL, 2139160912LL, 189126532LL, + 1730920581LL, -1271098814LL, 458164429LL, -2098061870LL, -1044961165LL, -1876122175LL, + -2025552441LL, -713383179LL, -1989369296LL, 808818926LL, -951560329LL, 1925178224LL, + 567282342LL, 2071224034LL, 1800677261LL, 1170187871LL, 2122837639LL, -324559103LL, + 1367441723LL, -1655862732LL, -84403775LL, -2145845814LL, -1494520923LL, -1542136655LL, + -2142266190LL, -149912720LL, -1693670459LL, 1320325198LL, -375615920LL, 2114400845LL, + 1136765970LL, 1821960862LL, 2064745995LL, 590425463LL, 1927378300LL, -947096163LL, + 792540149LL, -1995910410LL, -754291219LL, -2010677252LL, -1910543506LL, -980612954LL, + -2072928396LL, 561022387LL, -1153718423LL, 1811273600LL, 369641855LL, 2115453415LL, + 1700656395LL, 1311314638LL, 2139763861LL, -182178136LL, 1453201767LL, -1581133415LL, + -340133LL, -2147483648LL, -1454999875LL, -1579478907LL, -2140406006LL, -174471725LL, + -1690500684LL, 1324381248LL, -341148743LL, 2120234843LL, 1191217693LL, 1786834816LL, + 2088761332LL, 498853033LL, 1869221566LL, -1057255404LL, 646993633LL, -2047724955LL, + -924043930LL, -1938535805LL, -1998809140LL, -785200785LL, -1995752184LL, 792938506LL, + -913299314LL, 1943621006LL, 665106491LL, 2041913712LL, 1883676165LL, 1031281900LL, + 2078103917LL, -541537037LL, 1139282889LL, -1820388077LL, -423053216LL, -2105422577LL, + -1755061396LL, -1237553130LL, -2124964963LL, 310325894LL, -1326436235LL, 1688888737LL, + 203888725LL, 2137804397LL, 1622950325LL, 1406346506LL, 2144977914LL, -104153747LL, + 1477748697LL, -1558215981LL, -11427115LL, -2147474720LL, -1495548955LL, -1541139700LL, + -2146227175LL, -74075394LL, -1597032165LL, 1435711153LL, -152213395LL, 2142103951LL, + 1379369331LL, 1645940005LL, 2135905059LL, 222907674LL, 1688365720LL, -1327101898LL, + 286126902LL, -2128358440LL, -1279405994LL, -1724789423LL, -2120117793LL, -341875411LL, + -1755659436LL, 1236704572LL, -390182130LL, 2111761388LL, 1199353226LL, 1781384319LL, + 2103791586LL, 431090728LL, 1802326200LL, -1167646574LL, 464651014LL, -2096634848LL, + -1141824017LL, -1818795252LL, -2090642021LL, -490911593LL, -1831045208LL, 1122074729LL, + -509913801LL, 2086088725LL, 1108541774LL, 1839269798LL, 2083175705LL, 521686914LL, + 1843600002LL, -1101325241LL, 526244624LL, -2082029022LL, -1100484339LL, -1844102078LL, + -2082700002LL, -523582807LL, -1840776287LL, 1106038387LL, -513678561LL, 2085164883LL, + 1117966670LL, 1833556320LL, 2089324145LL, 496490553LL, 1822309409LL, -1136207142LL, + 471960692LL, -2095001517LL, -1160653959LL, -1806837192LL, -2101942711LL, -440017151LL, + -1786877355LL, 1191153883LL, -400578785LL, 2109813947LL, 1227501562LL, 1762106174LL, + 2118200388LL, 353560982LL, 1732142069LL, -1269433774LL, 298882986LL, -2126604621LL, + -1316622702LL, -1696550298LL, -2134445362LL, -236476744LL, -1654848985LL, 1368668364LL, + -166297281LL, 2141056624LL, 1425090359LL, 1606516642LL, 2145687592LL, 88334644LL, + 1551001405LL, -1485319122LL, 2627380LL, -2147483648LL, -1548686937LL, -1487732175LL, + -2145587957LL, 90722496LL, -1416131880LL, 1614419014LL, 191533131LL, 2138946776LL, + 1681624999LL, 1335633039LL, 2126514259LL, -299525224LL, 1245695805LL, -1749291346LL, + -414303401LL, -2107161822LL, -1816275052LL, -1145828603LL, -2079709756LL, 535336887LL, + -1035611440LL, 1881299338LL, 661939879LL, 2042942449LL, 1942951923LL, 914721858LL, + 1995627535LL, -793252163LL, 782963443LL, -1999686600LL, -928220601LL, -1936539380LL, + -2049828893LL, -640296620LL, -1864487226LL, 1065582299LL, -486871358LL, 2091586607LL, + 1203850358LL, 1778348270LL, 2123066109LL, 323061216LL, 1677105764LL, -1341303287LL, + 149497940LL, -2142295175LL, -1475979285LL, -1559892112LL, -2147253178LL, 32894384LL, + -1426036673LL, 1605676699LL, 222866878LL, 2135909316LL, 1727962094LL, 1275117741LL, + 2106269424LL, -418816628LL, 1107017868LL, -1840187407LL, -618762426LL, -2056431694LL, + -1939517654LL, -921981303LL, -1984651354LL, 820327529LL, -720671943LL, 2022970638LL, + 1020731672LL, 1889413958LL, 2087469906LL, 504229753LL, 1769516514LL, -1216794789LL, + 274323141LL, -2129911986LL, -1404954962LL, -1624155106LL, -2147248563LL, -33194308LL, + -1453017047LL, 1581303169LL, 216305820LL, 2136583732LL, 1741637261LL, 1256374905LL, + 2095285828LL, -470696880LL, 1035178960LL, -1881537343LL, -725866679LL, -2021112520LL, + -1996464271LL, -791143898LL, -1912346919LL, 977091355LL, -526824742LL, 2081882308LL, + 1219082322LL, 1767941329LL, 2133406056LL, 245676321LL, 1587664095LL, -1446063959LL, + -47910032LL, -2146970629LL, -1651885440LL, -1372243690LL, -2119022604LL, 348599275LL, + -1123502918LL, 1830169240LL, 650141786LL, 2046727610LL, 1974497526LL, 844474850LL, + 1928188552LL, -945445482LL, 539491040LL, -2078636012LL, -1226696888LL, -1762666446LL, + -2136792692LL, -214231757LL, -1550793747LL, 1485535932LL, 124272439LL, 2143906391LL, + 1713287466LL, 1294768054LL, 2095957189LL, -467698315LL, 998512239LL, -1901250000LL, + -806556485LL, -1990287640LL, -2041039078LL, -667785694LL, -1825920481LL, 1130394909LL, + -310230540LL, 2124978886LL, 1428084829LL, 1603855347LL, 2146531368LL, -64663286LL, + 1327324157LL, -1688190995LL, -445689034LL, -2100747376LL, -1899423358LL, -1001982615LL, + -1984719414LL, 820162851LL, -636013965LL, 2051161741LL, 1174280900LL, 1798010740LL, + 2134038439LL, 240121201LL, 1543031314LL, -1493597207LL, -172614421LL, -2140556590LL, + -1763618478LL, -1225327758LL, -2065714780LL, 587027003LL, -853752767LL, 1970503607LL, + 986324267LL, 1907601293LL, 2101845836LL, 440479666LL, 1667915263LL, -1352714651LL, + 830786LL, -2147483648LL, -1668196721LL, -1352367536LL, -2100446313LL, 447105735LL, + -970912076LL, 1915491580LL, 883086661LL, 1957533193LL, 2079084495LL, 537760090LL, + 1720211269LL, -1285554917LL, 71134494LL, -2146326661LL, -1632698112LL, -1395017967LL, + -2108532996LL, 407267548LL, -993848697LL, 1903691945LL, 873121074LL, 1961998431LL, + 2080075053LL, 533915748LL, 1708844975LL, -1300625658LL, 37346075LL, -2147180366LL, + -1663935794LL, -1357606691LL, -2095527800LL, 469618453LL, -923461264LL, 1938813438LL, + 957830205LL, 1922066479LL, 2104417089LL, 428026830LL, 1631143971LL, -1396834850LL, + -101337811LL, -2145112794LL, -1756804132LL, -1235077931LL, -2052167288LL, 632761942LL, + -754214321LL, 2010706097LL, 1131613694LL, 1825165390LL, 2136576430LL, 216377935LL, + 1472986508LL, -1562718465LL, -344343699LL, -2119718300LL, -1892937732LL, -1014181935LL, + -1954630509LL, 889493015LL, -476618464LL, 2093946774LL, 1378760987LL, 1646449632LL, + 2144999715LL, -103703776LL, 1211696094LL, -1773011796LL, -684690351LL, -2035430514LL, + -2037621981LL, -678140779LL, -1766616028LL, 1221002073LL, -83660153LL, 2145874934LL, + 1667579453LL, 1353128604LL, 2082096982LL, -525975674LL, 822836318LL, -1983612524LL, + -1100338866LL, -1844188882LL, -2136637657LL, -215772505LL, -1445205204LL, 1588445835LL, + 418307169LL, 2106370662LL, 1943446150LL, 913671338LL, 1887842123LL, -1023635860LL, + 292408153LL, -2127504577LL, -1543223667LL, -1493398462LL, -2116389826LL, 364242166LL, + -953180338LL, 1924376651LL, 994734160LL, 1903229414LL, 2124455563LL, 313794218LL, + 1500889976LL, -1535938649LL, -364947274LL, -2116268352LL, -1929625851LL, -942508528LL, + -1892427654LL, 1015133404LL, -279838782LL, 2129194333LL, 1567391043LL, 1468013477LL, + 2105891129LL, -420714638LL, 880976718LL, -1958483667LL, -1084234992LL, -1853702440LL, + -2139091766LL, -189907006LL, -1392123791LL, 1635166537LL, 530937135LL, 2080837334LL, + 2006184689LL, 766160066LL, 1781556925LL, -1199096816LL, 43163434LL, -2147071301LL, + -1733267961LL, -1267896063LL, -2032438430LL, 693521651LL, -594509609LL, 2063573739LL, + 1353703683LL, 1667112651LL, 2141499513LL, -160493266LL, 1088126716LL, -1851420672LL, + -903748173LL, -1948080464LL, -2116675164LL, -362580342LL, -1498958106LL, 1537824063LL, + 418884470LL, 2106255933LL, 1974203316LL, 845162422LL, 1811961617LL, -1152637563LL, + 68936894LL, -2146398369LL, -1735622764LL, -1264670659LL, -2021270878LL, 725425592LL, + -533100816LL, 2080284060LL, 1424996196LL, 1606600166LL, 2128744305LL, -283241831LL, + 953243458LL, -1924345385LL, -1066569964LL, -1863922414LL, -2142200168LL, -150853214LL, + -1315424718LL, 1697479326LL, 682977170LL, 2036006002LL, 2073584922LL, 558590927LL, + 1611737061LL, -1419183533LL, -294005217LL, -2127284463LL, -1937258728LL, -926718336LL, + -1839535757LL, 1108100380LL, -84113049LL, 2145857229LL, 1748518030LL, 1246781036LL, + 2000459447LL, -780986718LL, 438964205LL, -2102162857LL, -1522417894LL, -1514602921LL, + -2099380971LL, 452081618LL, -761873304LL, 2007816556LL, 1272910732LL, 1729588541LL, + 2143394086LL, -132815833LL, 1047578153LL, -1874662174LL, -1012284593LL, -1893953050LL, + -2140907409LL, -168207364LL, -1293751813LL, 1714054987LL, 750862777LL, 2011960075LL, + 2100886427LL, 445033113LL, 1500451741LL, -1536366761LL, -496915548LL, -2089223107LL, + -2032259507LL, -694045784LL, -1669556591LL, 1350688358LL, 256731769LL, 2132103903LL, + 1943485354LL, 913587944LL, 1804234137LL, -1164696284LL, -34801054LL, -2147223123LL, + -1842266884LL, -1103553795LL, -1908467832LL, 984646528LL, -165936707LL, 2141084599LL, + 1735389231LL, 1264991094LL, 1986656241LL, -815460135LL, 343809606LL, -2119804993LL, + -1628656563LL, -1399734280LL, -2043289239LL, 660868623LL, -498126547LL, 2088934704LL, + 1526902306LL, 1510081985LL, 2082697573LL, -523592467LL, 628903655LL, -2053352976LL, + -1434049310LL, -1598524579LL, -2108867617LL, 405531291LL, -736616580LL, 2017219439LL, + 1353199499LL, 1667521925LL, 2125310622LL, -307949689LL, 821985658LL, -1983965179LL, + -1286736074LL, -1719327929LL, -2134974911LL, 231647103LL, -885797031LL, 1956308225LL, + 1236424757LL, 1755856507LL, 2140189818LL, -177103911LL, 928760188LL, -1936280652LL, + -1203503749LL, -1778582857LL, -2142631439LL, 144598642LL, -951401010LL, 1925256962LL, + 1188754801LL, 1788474287LL, 2143302031LL, -134293173LL, 953988887LL, -1923975950LL, + -1192550034LL, -1785945875LL, -2142517037LL, 146283965LL, -936496745LL, 1932550672LL, + 1214871030LL, 1770837834LL, 2139896113LL, -180618042LL, 898593554LL, -1950463503LL, + -1255298315LL, -1742413382LL, -2134357016LL, 237272799LL, -839669937LL, 1976545636LL, + 1312970852LL, 1699378061LL, 2124113871LL, -316098901LL, 758898622LL, -2008942790LL, + -1386516788LL, -1639923611LL, -2106684059LL, 416725964LL, -655332420LL, 2045071557LL, + 1473958617LL, 1561801603LL, 2078910722LL, -538431483LL, 528042942LL, -2081573660LL, + -1572598344LL, -1462433828LL, -2037010648LL, 679974904LL, -376303120LL, 2114278651LL, + 1678891319LL, 1339067658LL, 1976659782LL, -839401190LL, 199815386LL, -2138188968LL, + -1788321280LL, -1188984968LL, -1893130668LL, 1013821744LL, 1015206LL, 2147483647LL, + 1895293708LL, 1009772258LL, 1781497239LL, -1199185490LL, -224767936LL, -2135710099LL, + -1993069770LL, -799656892LL, -1636922019LL, 1390059192LL, 468664761LL, 2095741300LL, + 2073768426LL, 557909285LL, 1455038239LL, -1579443565LL, -728219915LL, -2020265826LL, + -2128469041LL, -285302989LL, -1232433825LL, 1758660035LL, 996911183LL, 1902089994LL, + 2147450001LL, -15386527LL, 967234719LL, -1917351103LL, -1265915548LL, -1734714985LL, + -2120598948LL, 338878083LL, -659770976LL, 2043643930LL, 1523964714LL, 1513046530LL, + 2038025538LL, -676926997LL, 313289960LL, -2124529984LL, -1757387716LL, -1234247410LL, + -1890896082LL, 1017983428LL, 65342818LL, 2146510789LL, 1950415709LL, 898697287LL, + 1672488991LL, -1347055614LL, -465041969LL, -2096548168LL, -2085824742LL, -510992562LL, + -1379439123LL, 1645881514LL, 870114378LL, 1963333701LL, 2145981477LL, 80881094LL, + 1013097346LL, -1893518423LL, -1260224334LL, -1738853898LL, -2114330097LL, 376013957LL, + -580880168LL, 2067451688LL, 1610864856LL, 1420173464LL, 1977311721LL, -837864316LL, + 97427223LL, -2145293963LL, -1894484197LL, -1011290205LL, -1726638353LL, 1276909649LL, + 414670796LL, 2107089553LL, 2082384451LL, 524836402LL, 1361752252LL, -1660544807LL, + -924852804LL, -1938150031LL, -2147440364LL, 16677375LL, -892194744LL, 1953398779LL, + 1395568160LL, 1632227853LL, 2067574378LL, -580443315LL, 339498498LL, -2120499711LL, + -1784514260LL, -1194691219LL, -1829768090LL, 1124156123LL, 261874801LL, 2131478323LL, + 2048286766LL, 645212817LL, 1434199594LL, -1598389745LL, -865074717LL, -1965559459LL, + -2147417896LL, -19355413LL, -897892940LL, 1950786129LL, 1413367347LL, 1616839818LL, + 2052515324LL, -631632091LL, 257088095LL, -2132060966LL, -1844939931LL, -1099079116LL, + -1750883954LL, 1243456325LL, 432559215LL, 2103490142LL, 2100043609LL, 448993423LL, + 1252656025LL, -1744313944LL, -1098794698LL, -1845109337LL, -2130069884LL, 273094381LL, + -595141609LL, 2063391557LL, 1659197184LL, 1363393912LL, 1907595553LL, -986335368LL, + -156060339LL, -2141827123LL, -2031322735LL, -696782749LL, -1435830460LL, 1596924902LL, + 910566537LL, 1944902783LL, 2145908301LL, -82799844LL, 755393985LL, -2010263211LL, + -1562259500LL, -1473473280LL, -1961546882LL, 874135049LL, 53893095LL, 2146828774LL, + 2003941305LL, 772008743LL, 1478282085LL, -1557709964LL, -878288589LL, -1959690641LL, + -2146376395LL, 69617686LL, -746823549LL, 2013462898LL, 1583711717LL, 1450391482LL, + 1938991652LL, -923087009LL, -130131588LL, -2143558728LL, -2037310308LL, -679076550LL, + -1388052087LL, 1638624319LL, 1007357365LL, 1896578338LL, 2134567925LL, -235367855LL, + 567201170LL, -2071246264LL, -1718536565LL, -1287792812LL, -1827162208LL, 1128386688LL, + 384633336LL, 2112779082LL, 2108144988LL, 409271256LL, 1144834605LL, -1816901753LL, + -1281367823LL, -1723332456LL, -2068841606LL, 575910288LL, -203762881LL, 2137816396LL, + 1924065071LL, 953809129LL, 1576114318LL, -1458643859LL, -804877869LL, -1990967069LL, + -2146938105LL, 49345967LL, -709847105LL, 2026794351LL, 1648842311LL, 1375898719LL, + 1865556995LL, -1063708301LL, -347142718LL, -2119261708LL, -2107985893LL, -410089903LL, + -1113857687LL, 1836055366LL, 1339757351LL, 1678340994LL, 2036307367LL, -682078118LL, + 55632195LL, -2146784412LL, -1999306508LL, -783933505LL, -1416194428LL, 1614364145LL, + 1040157494LL, 1878789675LL, 2119417475LL, -346190438LL, 385411706LL, -2112637231LL, + -1862096907LL, -1069753879LL, -1629003578LL, 1399330409LL, 779406748LL, 2001075554LL, + 2146227733LL, -74059248LL, 636821825LL, -2050911070LL, -1728558309LL, -1274309391LL, + -1769131362LL, 1217354704LL, 575366464LL, 2068992916LL, 2143786402LL, 126325432LL, + 811653485LL, -1988214494LL, -1621656671LL, -1407838021LL, -1853012225LL, 1085414182LL, + 437741150LL, 2102417879LL, 2132583441LL, 252717470LL, 914325600LL, -1943138428LL, + -1556182166LL, -1479890306LL, -1893366249LL, 1013381714LL, 371196954LL, 2115181097LL, + 2125707202LL, 305200168LL, 948644107LL, -1926616882LL, -1540084066LL, -1496636001LL, + -1897293197LL, 1006010326LL, 377637603LL, 2114040703LL, 2128649591LL, 283952763LL, + 915875003LL, -1942408616LL, -1575405780LL, -1459409086LL, -1865346604LL, 1064077206LL, + 457334911LL, 2098242844LL, 2139233838LL, 188299860LL, 814063181LL, -1987229073LL, + -1658450143LL, -1364302523LL, -1791336338LL, 1184437578LL, 608779012LL, 2059409228LL, + 2147437131LL, 17088601LL, 638588540LL, -2050361658LL, -1779065160LL, -1202790675LL, + -1662858487LL, 1358926012LL, 827205960LL, 1981794276LL, 2135201440LL, -229549696LL, + 384064818LL, -2112882502LL, -1919199960LL, -963560982LL, -1462825426LL, 1572234087LL, + 1101868687LL, 1843275251LL, 2076668650LL, -547015148LL, 47758141LL, -2146974013LL, + -2051199279LL, -635892892LL, -1172501340LL, 1799171715LL, 1412341265LL, 1617736197LL, + 1939626687LL, -921751901LL, -365380340LL, -2116193625LL, -2136723288LL, -214922878LL, + -776639943LL, 2002151006LL, 1724575092LL, 1279694887LL, 1689243211LL, -1325984776LL, + -836338024LL, -1977957776LL, -2127675279LL, 291163456LL, -271116657LL, 2130322513LL, + 1988098139LL, 811938448LL, 1295227957LL, -1712939810LL, -1325354317LL, -1689737905LL, + -1970947641LL, 852727183LL, 327255879LL, 2122423578LL, 2136580928LL, 216333515LL, + 743122792LL, -2014831697LL, -1767145576LL, -1220235537LL, -1618830293LL, 1411087076LL, + 970421831LL, 1915739993LL, 2094675357LL, -473406171LL, 49113839LL, -2146943428LL, + -2071666428LL, -565664620LL, -1046044737LL, 1875518238LL, 1572024305LL, 1463050866LL, + 1793937568LL, -1180494072LL, -724672157LL, -2021541124LL, -2135022834LL, 231204995LL, + -271976572LL, 2130212899LL, 2009560733LL, 757260797LL, 1198854755LL, -1781719823LL, + -1460814052LL, -1574103096LL, -1864564655LL, 1065446808LL, 617523974LL, 2056803927LL, + 2142873454LL, -140966715LL, 339609818LL, -2120481885LL, -1992859891LL, -800179796LL, + -1218487592LL, 1768351278LL, 1459769048LL, 1575072246LL, 1854093979LL, -1083565304LL, + -658869619LL, -2043934705LL, -2137558296LL, 206452856LL, -252327371LL, 2132629633LL, + 2031403566LL, 696547059LL, 1106655405LL, -1840405408LL, -1569932932LL, -1465294797LL, + -1757971322LL, 1233416022LL, 846673890LL, 1973555567LL, 2104603098LL, -427111287LL, + 7105533LL, -2147483648LL, -2102394209LL, -437854817LL, -847813115LL, 1973066439LL, + 1766529009LL, 1221127967LL, 1543986667LL, -1492609602LL, -1163408424LL, -1805064844LL, + -1995845223LL, 792704294LL, 395332043LL, 2110803361LL, 2147463059LL, 13441110LL, + 418514972LL, -2106329383LL, -1990711567LL, -805509596LL, -1161254207LL, 1806451472LL, + 1561575667LL, 1474197982LL, 1734733192LL, -1265890598LL, -930540752LL, -1935425576LL, + -2071150890LL, 567549332LL, 189359818LL, 2139140274LL, 2138940340LL, 191604992LL, + 563352066LL, -2072296480LL, -1942969975LL, -914683514LL, -1235509167LL, 1756500882LL, + 1519929506LL, 1517100046LL, 1752279129LL, -1241489471LL, -930285185LL, -1935548431LL, + -2063153673LL, 595965749LL, 248406300LL, 2133089910LL, 2145053104LL, 102593546LL, + 447586074LL, -2100344010LL, -2001731639LL, -777720193LL, -1084949756LL, 1853284188LL, + 1660175561LL, 1362202393LL, 1603507340LL, -1428475574LL, -1164931593LL, -1804082215LL, + -1960379992LL, 876748847LL, 571375919LL, 2070098503LL, 2132155718LL, -256301087LL, + 61135739LL, -2146634732LL, -2114702884LL, -373911710LL, -675467568LL, 2038509705LL, + 1921068533LL, 959830164LL, 1221709988LL, -1766126541LL, -1578027766LL, -1456573589LL, + -1660691445LL, 1361573420LL, 1121883336LL, 1831162481LL, 1965916948LL, -864262000LL, + -594072042LL, -2063699751LL, -2124036615LL, 316617610LL, 37039449LL, 2147185677LL, + 2134077146LL, 239776950LL, 509279299LL, -2086243717LL, -2005744326LL, -767312161LL, + -1010166297LL, 1895083720LL, 1757130129LL, 1234614095LL, 1437931730LL, -1595033101LL, + -1412143325LL, -1617908985LL, -1772847813LL, 1211936007LL, 997939073LL, 1901550909LL, + 2003301586LL, -773667245LL, -542562734LL, -2077836358LL, -2125311580LL, 307943082LL, + 72956446LL, 2146265503LL, 2141577029LL, 159455583LL, 386587711LL, -2112422352LL, + -2060230609LL, -605993474LL, -815500912LL, 1986639503LL, 1893451787LL, 1013221882LL, + 1197555538LL, -1782593332LL, -1656073399LL, -1367186582LL, -1521078918LL, 1515947617LL, + 1364284023LL, 1658465362LL, 1778834048LL, -1203132445LL, -1034497388LL, -1881912168LL, + -1967647639LL, 860314490LL, 682430559LL, 2036189280LL, 2087866006LL, -502587100LL, + -322407206LL, -2123165525LL, -2142712955LL, 143385645LL, -33118093LL, 2147249740LL, + 2137613161LL, 205884009LL, 373833346LL, -2114716738LL, -2079531699LL, -536028138LL, + -691668843LL, 2033069715LL, 1976366997LL, 840090320LL, 980756426LL, -1910469860LL, + -1836421774LL, -1113253484LL, -1237282859LL, 1755251942LL, 1667965366LL, 1352652871LL, + 1459270246LL, -1575534386LL, -1478891620LL, -1557131282LL, -1646312910LL, 1378924239LL, + 1276469496LL, 1726963774LL, 1799295475LL, -1172311411LL, -1067178514LL, -1863574059LL, + -1920111852LL, 961742547LL, 856618029LL, 1969259710LL, 2011399718LL, -752362563LL, + -649477809LL, -2046938404LL, -2076300463LL, 548411013LL, 449557001LL, 2099923036LL, + 2118250510LL, -353260571LL, -259819179LL, -2131729872LL, -2140806576LL, 169485864LL, + 82472348LL, 2145920913LL, 2147483647LL, 1047758LL, 80935692LL, -2145979419LL, + -2141752271LL, -157084251LL, -229414545LL, 2135215966LL, 2126746354LL, 297872792LL, + 362427211LL, -2116701389LL, -2105420205LL, -423065022LL, -479789567LL, 2093222450LL, + 2080407835LL, 532617587LL, 581576642LL, -2067255877LL, -2054025799LL, -626702695LL, + -668037870LL, 2040956554LL, 2028266959LL, 705628369LL, 739522569LL, -2016155902LL, + -2004802607LL, -769769290LL, -796416224LL, 1994366930LL, 1984989673LL, 819508543LL, + 839087667LL, -1976792892LL, -1969880196LL, -855190193LL, -867846986LL, 1964337003LL, + 1960230768LL, 877082430LL, 882913826LL, -1957611154LL, -1956510145LL, -885350951LL, + -884395768LL, 1956942099LL, 1958903731LL, 880042285LL, 872276570LL, -1962374031LL, + -1967314107LL, -861076917LL, -846414176LL, 1973666967LL, 1981357235LL, 828252233LL, + 806548658LL, -1990290812LL, -2000354483LL, -781255524LL, -752320391LL, 2011415492LL, + 2023321078LL, 719687478LL, 683299011LL, -2035898012LL, -2048952124LL, -643096763LL, + -599023792LL, 2062267865LL, 2075607908LL, 551026374LL, 499056140LL, -2088712814LL, + -2101300807LL, -443072421LL, -383044797LL, 2113067660LL, 2123686752LL, 318955846LL, + 250804104LL, -2132809310LL, -2140064887LL, -178607202LL, -102405192LL, 2145062104LL, + 2147389710LL, 22264034LL, -61720779LL, -2146617991LL, -2142300579LL, 149420482LL, + 240669219LL, 2133976705LL, 2121173934LL, -335260188LL, -432941801LL, -2103411431LL, + -2080203800LL, 533413914LL, 636324191LL, 2051065522LL, 2015516040LL, -741264694LL, + -847768760LL, -1973085498LL, -1923321174LL, 955308281LL, 1063291488LL, 1865794593LL, + 1800109329LL, -1171061338LL, -1277894654LL, -1725909472LL, -1642888735LL, 1383002118LL, + 1485529269LL, 1550800130LL, 1449466158LL, -1584558648LL, -1679113216LL, -1338789401LL, + -1218763406LL, 1768161196LL, 1850622468LL, 1089483701LL, 951158777LL, -1925376647LL, + -1991272952LL, -804120815LL, -648835928LL, 2047141957LL, 2091809306LL, 485913656LL, + 316115397LL, -2124111416LL, -2142913183LL, -140361472LL, 40263541LL, 2147127639LL, + 2135737484LL, -224507577LL, -410950319LL, -2107818324LL, -2062563424LL, 598005330LL, + 783925429LL, 1999309674LL, 1917564424LL, -966811735LL, -1144626701LL, -1817032737LL, + -1697644551LL, 1315211477LL, 1476307872LL, 1559581136LL, 1403300164LL, -1625585096LL, + -1760671415LL, -1229558628LL, -1039432778LL, 1879190717LL, 1978803868LL, 834334169LL, + 616020903LL, -2057254603LL, -2112419539LL, -386603081LL, -148541519LL, 2142361704LL, + 2145386792LL, -95361228LL, -341978393LL, -2120101184LL, -2065470513LL, 587885883LL, + 829399143LL, 1980877410LL, 1866176826LL, -1062620490LL, -1283497151LL, -1721747170LL, + -1548535341LL, 1487889965LL, 1671652430LL, 1348093619LL, 1122606279LL, -1830719365LL, + -1961204102LL, -874903836LL, -608462790LL, 2059502679LL, 2122403053LL, 327388961LL, + 36382652LL, -2147196906LL, -2131791166LL, 259315786LL, 554000983LL, 2074815935LL, + 1975725154LL, -841598698LL, -1115782941LL, -1834886013LL, -1653652904LL, 1370113253LL, + 1598190499LL, 1434421619LL, 1180659549LL, -1793828666LL, -1951239249LL, -896907825LL, + -588751770LL, 2065223863LL, 2131369797LL, 262756618LL, -73633741LL, -2146242373LL, + -2107567219LL, 412236184LL, 744305898LL, 2014394942LL, 1867240322LL, -1060750599LL, + -1352378332LL, -1668187969LL, -1420956603LL, 1610174086LL, 1825598651LL, 1130914593LL, + 805040350LL, -1990901375LL, -2099436762LL, -451822460LL, -81096219LL, 2145973359LL, + 2126982117LL, -296184616LL, -668239500LL, -2040890547LL, -1888288611LL, 1022811993LL, + 1347572555LL, 1672072505LL, 1397513330LL, -1630562708LL, -1860666864LL, -1072239280LL, + -706122327LL, 2028095045LL, 2124857107LL, 311063543LL, -99324907LL, -2145206940LL, + -2086033781LL, 510138526LL, 905692346LL, 1947177349LL, 1731644205LL, -1270112829LL, + -1587991228LL, -1445704711LL, -1098853201LL, 1845074496LL, 2028965008LL, 703618680LL, + 275219306LL, -2129796372LL, -2140849807LL, 168938915LL, 609910657LL, 2059074366LL, + 1885474852LL, -1027989706LL, -1403590961LL, -1625334017LL, -1288240577LL, 1718200939LL, + 1955353825LL, 887901836LL, 441729183LL, -2101583589LL, -2147298298LL, 29803890LL, + 504018661LL, 2087520884LL, 1922441916LL, -957076451LL, -1365171763LL, -1657734693LL, + -1304591428LL, 1705819292LL, 1959169080LL, 879451403LL, 403407502LL, -2109274909LL, + -2145235595LL, 98704079LL, 599505760LL, 2062127808LL, 1861653342LL, -1070525612LL, + -1483822075LL, -1552433671LL, -1149900319LL, 1813699950LL, 2038415846LL, 675750761LL, + 156965411LL, -2141760984LL, -2114405567LL, 375589336LL, 888915894LL, 1954893037LL, + 1670185129LL, -1349911067LL, -1727547030LL, -1275680020LL, -794655486LL, 1995069149LL, + 2132056423LL, 257125774LL, -301857127LL, -2126184500LL, -1974537010LL, 844382524LL, + 1332221125LL, 1684329281LL, 1272939745LL, -1729567188LL, -2005792026LL, -767187463LL, + -201847262LL, 2137998114LL, 2113157985LL, -382546186LL, -942491591LL, -1929634124LL, + -1597906633LL, 1434737832LL, 1819698511LL, 1140383963LL, 590236763LL, -2064799946LL, + -2147478326LL, 10728041LL, 615051639LL, 2057544589LL, 1798663694LL, -1173280516LL, + -1638033745LL, -1388748971LL, -859150212LL, 1968156286LL, 2132595954LL, 252611856LL, + -379912056LL, -2113633148LL, -1909117958LL, 983385416LL, 1503452390LL, 1533430522LL, + 1016975687LL, -1891438264LL, -2109133387LL, -404146767LL, 250163671LL, 2132884523LL, + 1956543252LL, -885277785LL, -1440300299LL, -1592894630LL, -1073309191LL, 1860049901LL, + 2100783203LL, 445520130LL, -230387125LL, -2135111244LL, -1955540371LL, 887490906LL, + 1458588582LL, 1576165474LL, 1032200672LL, -1883172861LL, -2114111676LL, -377240073LL, + 321618747LL, 2123285104LL, 1905484793LL, -990406964LL, -1556061032LL, -1480017675LL, + -889669664LL, 1954550113LL, 2138453888LL, 196959948LL, -522073833LL, -2083078771LL, + -1790296759LL, 1186008333LL, 1717259734LL, 1289494962LL, 635321655LL, -2051376281LL, + -2145280628LL, 97720420LL, 823389820LL, 1983382832LL, 1580662827LL, -1453713617LL, + -1909763720LL, -982130737LL, -258487971LL, 2131891700LL, 2088076492LL, -501711885LL, + -1202622899LL, -1779178579LL, -1240206851LL, 1753187160LL, 2079238092LL, 537165906LL, + -240386160LL, -2134008610LL, -1905517389LL, 990344250LL, 1611354019LL, 1419618427LL, + 738009857LL, -2016710119LL, -2146949543LL, 48845784LL, 833216313LL, 1979274824LL, + 1532256359LL, -1504649030LL, -1965665871LL, -864832895LL, -69394176LL, 2146383633LL, + 2015831529LL, -740406308LL, -1445620026LL, -1588068321LL, -921850213LL, 1939579964LL, + 2144503760LL, 113498345LL, -716355987LL, -2024502989LL, -1592749524LL, 1440460762LL, + 1944553868LL, 911311421LL, 83236177LL, -2145891421LL, -2007648030LL, 762317284LL, + 1489902891LL, 1546598729LL, 832415927LL, -1979611572LL, -2147394416LL, 21805415LL, + 876730339LL, 1960388269LL, 1444350860LL, -1589222717LL, -2036512340LL, -681465878LL, + 201670467LL, 2138014798LL, 1870856248LL, -1054360067LL, -1727313129LL, -1275996711LL, + -453313801LL, 2099115254LL, 2098943598LL, -454107945LL, -1284248972LL, -1721186460LL, + -1028817246LL, 1885023429LL, 2142654665LL, 144254082LL, -771295848LL, -2004215798LL, + -1489741823LL, 1546753876LL, 2033293260LL, 691011412LL, -243516023LL, -2133653720LL, + -1822781397LL, 1135449793LL, 1810295663LL, 1155252295LL, 257271784LL, -2132038809LL, + -2031591496LL, 695998740LL, 1514007057LL, 1523010468LL, 703499995LL, -2029006163LL, + -2131255110LL, 263685243LL, 1180806936LL, 1793731650LL, 1080593863LL, -1855827351LL, + -2143148666LL, -136718859LL, 840457033LL, 1976211079LL, 1384466307LL, -1641655048LL, + -2090811322LL, -490190034LL, 515234481LL, 2084780967LL, 1618579736LL, -1411374468LL, + -1997020476LL, -789738862LL, 220308137LL, 2136174753LL, 1791127610LL, -1184753197LL, + -1882007992LL, -1034323049LL, -35153543LL, 2147217381LL, 1912644065LL, -976509567LL, + -1762605720LL, -1226784140LL, -246554385LL, 2133304757LL, 1994158416LL, -796938181LL, + -1652056657LL, -1372037555LL, -412412427LL, 2107532738LL, 2045882689LL, -652795738LL, + -1560236272LL, -1475615474LL, -533051118LL, 2080296796LL, 2076348595LL, -548228753LL, + -1494068405LL, -1542575072LL, -609532906LL, 2059186220LL, 2091882806LL, -485597134LL, + -1457970885LL, -1576736868LL, -642871256LL, 2049022889LL, 2096312234LL, -466104356LL, + -1454215166LL, -1580201413LL, -633526516LL, 2051931384LL, 2090812709LL, -490184117LL, + -1483126469LL, -1553098236LL, -581181031LL, 2067367133LL, 2073846918LL, -557617444LL, + -1543085729LL, -1493540989LL, -484792519LL, 2092069422LL, 2041175469LL, -667368683LL, + -1630325309LL, -1397790270LL, -342934553LL, 2119946732LL, 1985965692LL, -817140455LL, + -1738541669LL, -1260655035LL, -154441488LL, 2141944462LL, 1899063692LL, -1002664124LL, + -1858385464LL, -1076188515LL, 80625921LL, 2145991080LL, 1769532795LL, -1216771113LL, + -1976937107LL, -838747833LL, 359697429LL, 2117166978LL, 1585589372LL, -1448338564LL, + -2077335271LL, -544478120LL, 676143182LL, 2038285713LL, 1336074343LL, -1681274398LL, + -2138793277LL, -193239677LL, 1017589936LL, 1891107870LL, 1012569480LL, -1893800755LL, + -2137301703LL, 209092520LL, 1364358841LL, 1658403813LL, 612182079LL, -2058400193LL, + -2047351525LL, 648174349LL, 1688434000LL, 1327015027LL, 140859470LL, -2142880506LL, + -1844984131LL, 1099004918LL, 1953532460LL, 891902002LL, -383155795LL, -2113047536LL, + -1512335664LL, 1524670159LL, 2116965439LL, 360881672LL, -926448873LL, -1937387607LL, + -1043543997LL, 1876910808LL, 2133977959LL, -240658104LL, -1439212478LL, -1593877566LL, + -451395848LL, 2099528528LL, 1965025194LL, -866287621LL, -1857047228LL, -1078496103LL, + 226573952LL, 2135519257LL, 1585881416LL, -1448018780LL, -2107184336LL, -414188877LL, + 924553265LL, 1938292938LL, 999516904LL, -1900722024LL, -2120102478LL, 341970371LL, + 1550086948LL, 1486273429LL, 247370580LL, -2133210268LL, -1846396566LL, 1096630282LL, + 1993508546LL, 798562415LL, -583756133LL, -2066641486LL, -1276860029LL, 1726675047LL, + 2146861559LL, -52570901LL, -1363935428LL, -1658752062LL, -461245763LL, 2097386612LL, + 1931694257LL, -938261984LL, -1936008844LL, -929326642LL, 481295836LL, 2092876626LL, + 1331385848LL, -1684989607LL, -2147401288LL, 21117760LL, 1368381685LL, 1655086045LL, + 419135525LL, -2106205988LL, -1895255468LL, 1009844028LL, 1983999855LL, 821901958LL, + -631023488LL, -2052702514LL, -1175215396LL, 1797400074LL, 2132845201LL, -250498706LL, + -1563383230LL, -1472280927LL, -116773016LL, 2144327940LL, 1710763536LL, -1298101065LL, + -2097748686LL, -459596238LL, 1016061102LL, 1891929726LL, 770367534LL, -2004572801LL, + -2019753835LL, 729638745LL, 1876270181LL, 1044695392LL, -448867648LL, -2100070496LL, + -1280898421LL, 1723681377LL, 2139825995LL, -181446863LL, -1556596879LL, -1479454091LL, + -67096470LL, 2146456689LL, 1642452191LL, -1383520529LL, -2127403273LL, -293144277LL, + 1211581713LL, 1773089960LL, 494670922LL, -2089755711LL, -1875230852LL, 1046559842LL, + 2040014555LL, 670908986LL, -892986934LL, -1953036761LL, -822023684LL, 1983949424LL, + 2010674512LL, -754298522LL, -1926533564LL, -948813300LL, 633008420LL, 2052091273LL, + 1052445723LL, -1871933827LL, -2080849806LL, 530888253LL, 1823537178LL, 1134235607LL, + -449137579LL, -2100012783LL, -1195462799LL, 1783997464LL, 2112065123LL, -388534640LL, + -1755289012LL, -1237230268LL, 349560999LL, 2118864168LL, 1260358653LL, -1738756544LL, + -2121609013LL, 332495786LL, 1735153551LL, 1265314351LL, -337476908LL, -2120822385LL, + -1252168732LL, 1744663784LL, 2116340678LL, -364527624LL, -1766902774LL, -1220587088LL, + 413547562LL, 2107310292LL, 1169847409LL, -1800898468LL, -2092190962LL, 484267726LL, + 1845052277LL, 1098890508LL, -576169627LL, -2068769396LL, -1006404450LL, 1897084167LL, + 2034189196LL, -688369498LL, -1953968078LL, -890947249LL, 819470066LL, 1985005558LL, + 751112266LL, -2011866948LL, -1917275527LL, 967384518LL, 2066080016LL, 585740233LL, + -1129140636LL, -1826696383LL, -394180153LL, 2111018773LL, 1708805589LL, -1300677405LL, + -2140231625LL, -176597975LL, 1476652024LL, 1559255287LL, -65673388LL, -2146500701LL, + -1374171846LL, 1650281791LL, 2122036481LL, -329756618LL, -1813252493LL, -1150605775LL, + 610848956LL, 2058796203LL, 887068774LL, -1955731894LL, -1948949112LL, 901873390LL, + 2066532427LL, 584142089LL, -1193211241LL, -1785504183LL, -245123452LL, 2133469650LL, + 1563102624LL, -1472578840LL, -2143960181LL, 123340967LL, 1725122388LL, 1278956997LL, + -510716962LL, -2085892240LL, -933890625LL, 1933811406LL, 1948780966LL, -902236665LL, + -2080208526LL, -533395482LL, 1278869465LL, 1725187278LL, 88586075LL, -2145677226LL, + -1412332028LL, 1617744261LL, 2113054972LL, -383114784LL, -1893154277LL, -1013777656LL, + 857757936LL, 1968763464LL, 540981456LL, -2078248618LL, -1705248926LL, 1305336873LL, + 2147456466LL, 14456107LL, -1691154552LL, -1323546196LL, 535782851LL, 2079594910LL, + 835649125LL, -1978248921LL, -1861479003LL, 1070828733LL, 2130934692LL, 266262256LL, + -1544875398LL, -1491689732LL, 346571347LL, 2119355221LL, 983979706LL, -1908811722LL, + -1924717043LL, 952492812LL, 2115454080LL, 369638047LL, -1491955799LL, -1544618447LL, + 301961546LL, 2126169673LL, 997619158LL, -1901718767LL, -1918280677LL, 965389815LL, + 2122618579LL, 325988682LL, -1544345749LL, -1492238071LL, 404508224LL, 2109064093LL, + 877188938LL, -1960183109LL, -1839116628LL, 1108795870LL, 2143361705LL, 133337373LL, + -1691228057LL, -1323452270LL, 650459600LL, 2046626630LL, 611070961LL, -2058730321LL, + -1657879553LL, 1364995839LL, 2137164211LL, -210493197LL, -1895175200LL, -1009994661LL, + 1022316657LL, 1888556831LL, 184496468LL, -2139565214LL, -1325754951LL, 1689423588LL, + 2032385660LL, -693676279LL, -2083494074LL, -520413967LL, 1471937374LL, 1563706692LL, + -399600436LL, -2109999465LL, -792562371LL, 1995901586LL, 1734641616LL, -1266016080LL, + -2142094235LL, 152350066LL, 1899224227LL, 1002360009LL, -1088249610LL, -1851348438LL, + -41866617LL, 2147096979LL, 1154418027LL, -1810827786LL, -1926113643LL, 949665460LL, + 2139888992LL, 180702394LL, -1743192990LL, -1254215473LL, 857072513LL, 1969061949LL, + 263811489LL, -2131239487LL, -1306417408LL, 1704421253LL, 1987146461LL, -814264819LL +}; diff --git a/test/cmocka/include/log2_tables.h b/test/cmocka/include/log2_tables.h new file mode 100644 index 000000000000..035b93d5e307 --- /dev/null +++ b/test/cmocka/include/log2_tables.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + */ +/* Include Files */ +#include <stdint.h> + +/* Reference table generated by Matlab log2() */ +static const double log2_lookup_table[] = { + 0.0000000000000000, 25.3706434118312352, 26.3706433952040058, 26.9556058903827527, + 27.3706433868903893, 27.6925714801150313, 27.9556058848403417, 28.1779983053850174, + 28.3706433827335829, 28.5405683837140280, 28.6925714767895848, 28.8300750002372048, + 28.9556058820691362, 29.0710830992759028, 29.1779983030096979, 29.2775339764022569, + 29.3706433806551779, 29.4581062237394029, 29.5405683837140280, 29.6185708955208291, + 29.6925714767895848, 29.7629608045226277, 29.8300750002372048, 29.8942053375254808, + 29.9556058820691362, 30.0144995710118572, 30.0710830992759028, 30.1255308832035382, + 30.1779983030096979, 30.2286243759977573, 30.2775339764022569, 30.3248396911091014, + 30.3706433806551779, 30.4150374999506496, 30.4581062217832610, 30.4999263974219978, + 30.5405683818665565, 30.5800967460032638, 30.6185708937705954, 30.6560455991443810, + 30.6925714751268615, 30.7281953848170275, 30.7629608029390802, 30.7969081348255926, + 30.8300749987256388, 30.8624964763844254, 30.8942053360796365, 30.9252322316694972, + 30.9556058806835352, 30.9853532240493088, 31.0144995703467679, 31.0430687225044153, + 31.0710830986363931, 31.0985638350223041, 31.1255308825877144, 31.1520030939153152, + 31.1779983024158689, 31.2035333944917532, 31.2286243754244062, 31.2532864296295223, + 31.2775339758480158, 31.3013807177751282, 31.3248396905727375, 31.3479233036602380, + 31.3706433801355793, 31.3930111931400511, 31.4150374994467967, 31.4367325705235530, + 31.4581062212942228, 31.4791678368007908, 31.4999263969469325, 31.5203904994865773, + 31.5405683814046895, 31.5604679388234146, 31.5800967455538810, 31.5994620704028364, + 31.6185708933330361, 31.6374299205673069, 31.6560455987180411, 31.6744241280167067, + 31.6925714747111797, 31.7104933826930484, 31.7281953844114852, 31.7456828115263257, + 31.7629608029390802, 31.7800343162793943, 31.7969081348255926, 31.8135868759544458, + 31.8300749987256388, 31.8463768110377572, 31.8624964763844254, 31.8784380202372049, + 31.8942053360796365, 31.9098021911151051, 31.9252322316694972, 31.9404989883079118, + 31.9556058806835352, 31.9705562221352224, 31.9853532240493088, 31.9999999996640980}; diff --git a/test/cmocka/include/mock_memory.h b/test/cmocka/include/mock_memory.h index fb39e31738c3..f06e4a71d4bf 100644 --- a/test/cmocka/include/mock_memory.h +++ b/test/cmocka/include/mock_memory.h @@ -5,10 +5,11 @@ * Author: Adrian Bonislawski <adrian.bonislawski@linux.intel.com> */ - /* Memory mock for memmap */ -#define HEAP_RUNTIME_BASE 0xBE200000 -#define HEAP_BUFFER_BASE 0xBE2F0000 -#define HEAP_SYSTEM_0_BASE 0xBE30F000 -#define HEAP_SYS_RUNTIME_0_BASE 0xBE32F000 -#define SOF_CORE_S_START 0xBE390000 +#define HEAP_SYSTEM_0_BASE 0xBE200000 +#define HEAP_SYS_RUNTIME_0_BASE 0xBE220000 +#define SOF_CORE_S_START 0xBE280000 +#define HEAP_RUNTIME_SHARED_BASE 0xBE290000 +#define HEAP_SYSTEM_SHARED_BASE 0xBE2B0000 +#define HEAP_RUNTIME_BASE 0xBE2C0000 +#define HEAP_BUFFER_BASE 0xBE3B0000 diff --git a/test/cmocka/include/mock_trace.h b/test/cmocka/include/mock_trace.h deleted file mode 100644 index e59b7ad1386d..000000000000 --- a/test/cmocka/include/mock_trace.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - */ - -#include <sof/trace/preproc.h> -#include <sof/trace/trace.h> - -#define _TRACE_EVENT_NTH_PARAMS(id_count, param_count) \ - uintptr_t log_entry \ - META_SEQ_FROM_0_TO(id_count , META_SEQ_STEP_id_uint32_t) \ - META_SEQ_FROM_0_TO(param_count, META_SEQ_STEP_param_uint32_t) - -#define _TRACE_EVENT_NTH(postfix, param_count) \ - META_FUNC_WITH_VARARGS( \ - _trace_event, META_CONCAT(postfix, param_count),\ - void, _TRACE_EVENT_NTH_PARAMS(3, param_count) \ - ) - -#define META_SEQ_STEP_void_param(i, _) (void)META_CONCAT(param,i); - -#define _TRACE_N(N, mbox, atomic) \ - _TRACE_EVENT_NTH(META_CONCAT(META_IF_ELSE(mbox)(_mbox)(), \ - META_IF_ELSE(atomic)(_atomic)()), N) \ - { \ - (void)log_entry; \ - (void)id_0; \ - (void)id_1; \ - (void)id_2; \ - META_SEQ_FROM_0_TO(N, META_SEQ_STEP_void_param) \ - } - -#define _TRACE_GROUP(N) \ - _TRACE_N(N, 0, 0) \ - _TRACE_N(N, 0, 1) \ - _TRACE_N(N, 1, 0) \ - _TRACE_N(N, 1, 1) - -#define TRACE_IMPL() \ - _TRACE_GROUP(0) \ - _TRACE_GROUP(1) \ - _TRACE_GROUP(2) \ - _TRACE_GROUP(3) \ - _TRACE_GROUP(4) diff --git a/test/cmocka/include/power_tables.h b/test/cmocka/include/power_tables.h new file mode 100644 index 000000000000..1b495fece6ee --- /dev/null +++ b/test/cmocka/include/power_tables.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + */ + +/* Include Files */ +#include <string.h> + +/* Reference table generated by Matlab power() */ +static const double power_table[64][6] = { + {-1.0000000000000000, 1.0000000000000000, -1.0000000000000000 + , -1.0000000000000000, 1.0000000000000000, -1.0000000000000000}, + {-0.5000000000000000, 0.2500000000000000, -0.1250000000000000 + , -2.0000000000000000, 4.0000000000000000, -8.0000000000000000}, + {-0.3333333333333333, 0.1111111111111111, -0.0370370370370370 + , -3.0000000000000000, 9.0000000000000000, -27.0000000000000000}, + {-0.2500000000000000, 0.0625000000000000, -0.0156250000000000 + , -4.0000000000000000, 16.0000000000000000, -64.0000000000000000}, + {-0.2000000000000000, 0.0400000000000000, -0.0080000000000000 + , -5.0000000000000000, 25.0000000000000000, -125.0000000000000000}, + {-0.1666666666666667, 0.0277777777777778, -0.0046296296296296 + , -6.0000000000000000, 36.0000000000000000, -216.0000000000000000}, + {-0.1428571428571428, 0.0204081632653061, -0.0029154518950437 + , -7.0000000000000000, 49.0000000000000000, -343.0000000000000000}, + {-0.1250000000000000, 0.0156250000000000, -0.0019531250000000 + , -8.0000000000000000, 64.0000000000000000, -512.0000000000000000}, + {-0.1111111111111111, 0.0123456790123457, -0.0013717421124829 + , -9.0000000000000000, 81.0000000000000000, -729.0000000000000000}, + {-0.1000000000000000, 0.0100000000000000, -0.0010000000000000 + , -10.0000000000000000, 100.0000000000000000, -1000.0000000000000000}, + {-0.0909090909090909, 0.0082644628099174, -0.0007513148009016 + , -11.0000000000000000, 121.0000000000000000, -1331.0000000000000000}, + {-0.0833333333333333, 0.0069444444444444, -0.0005787037037037 + , -12.0000000000000000, 144.0000000000000000, -1728.0000000000000000}, + {-0.0769230769230769, 0.0059171597633136, -0.0004551661356395 + , -13.0000000000000000, 169.0000000000000000, -2197.0000000000000000}, + {-0.0714285714285714, 0.0051020408163265, -0.0003644314868805 + , -14.0000000000000000, 196.0000000000000000, -2744.0000000000000000}, + {-0.0666666666666667, 0.0044444444444444, -0.0002962962962963 + , -15.0000000000000000, 225.0000000000000000, -3375.0000000000000000}, + {-0.0625000000000000, 0.0039062500000000, -0.0002441406250000 + , -16.0000000000000000, 256.0000000000000000, -4096.0000000000000000}, + {-0.0588235294117647, 0.0034602076124567, -0.0002035416242622 + , -17.0000000000000000, 289.0000000000000000, -4913.0000000000000000}, + {-0.0555555555555556, 0.0030864197530864, -0.0001714677640604 + , -18.0000000000000000, 324.0000000000000000, -5832.0000000000000000}, + {-0.0526315789473684, 0.0027700831024931, -0.0001457938474996 + , -19.0000000000000000, 361.0000000000000000, -6859.0000000000000000}, + {-0.0500000000000000, 0.0025000000000000, -0.0001250000000000 + , -20.0000000000000000, 400.0000000000000000, -8000.0000000000000000}, + {-0.0476190476190476, 0.0022675736961451, -0.0001079796998164 + , -21.0000000000000000, 441.0000000000000000, -9261.0000000000000000}, + {-0.0454545454545455, 0.0020661157024793, -0.0000939143501127 + , -22.0000000000000000, 484.0000000000000000, -10648.0000000000000000}, + {-0.0434782608695652, 0.0018903591682420, -0.0000821895290540 + , -23.0000000000000000, 529.0000000000000000, -12167.0000000000000000}, + {-0.0416666666666667, 0.0017361111111111, -0.0000723379629630 + , -24.0000000000000000, 576.0000000000000000, -13824.0000000000000000}, + {-0.0400000000000000, 0.0016000000000000, -0.0000640000000000 + , -25.0000000000000000, 625.0000000000000000, -15625.0000000000000000}, + {-0.0384615384615385, 0.0014792899408284, -0.0000568957669549 + , -26.0000000000000000, 676.0000000000000000, -17576.0000000000000000}, + {-0.0370370370370370, 0.0013717421124829, -0.0000508052634253 + , -27.0000000000000000, 729.0000000000000000, -19683.0000000000000000}, + {-0.0357142857142857, 0.0012755102040816, -0.0000455539358601 + , -28.0000000000000000, 784.0000000000000000, -21952.0000000000000000}, + {-0.0344827586206897, 0.0011890606420927, -0.0000410020911066 + , -29.0000000000000000, 841.0000000000000000, -24389.0000000000000000}, + {-0.0333333333333333, 0.0011111111111111, -0.0000370370370370 + , -30.0000000000000000, 900.0000000000000000, -27000.0000000000000000}, + {-0.0322580645161290, 0.0010405827263267, -0.0000335671847202 + , -31.0000000000000000, 961.0000000000000000, -29791.0000000000000000}, + {-0.0312500000000000, 0.0009765625000000, -0.0000305175781250 + , -32.0000000000000000, 1024.0000000000000000, -32768.0000000000000000}, + {1.0000000000000000, 1.0000000000000000, 1.0000000000000000 + , 1.0000000000000000, 1.0000000000000000, 1.0000000000000000}, + {0.5000000000000000, 0.2500000000000000, 0.1250000000000000 + , 2.0000000000000000, 4.0000000000000000, 8.0000000000000000}, + {0.3333333333333333, 0.1111111111111111, 0.0370370370370370 + , 3.0000000000000000, 9.0000000000000000, 27.0000000000000000}, + {0.2500000000000000, 0.0625000000000000, 0.0156250000000000 + , 4.0000000000000000, 16.0000000000000000, 64.0000000000000000}, + {0.2000000000000000, 0.0400000000000000, 0.0080000000000000 + , 5.0000000000000000, 25.0000000000000000, 125.0000000000000000}, + {0.1666666666666667, 0.0277777777777778, 0.0046296296296296 + , 6.0000000000000000, 36.0000000000000000, 216.0000000000000000}, + {0.1428571428571428, 0.0204081632653061, 0.0029154518950437 + , 7.0000000000000000, 49.0000000000000000, 343.0000000000000000}, + {0.1250000000000000, 0.0156250000000000, 0.0019531250000000 + , 8.0000000000000000, 64.0000000000000000, 512.0000000000000000}, + {0.1111111111111111, 0.0123456790123457, 0.0013717421124829 + , 9.0000000000000000, 81.0000000000000000, 729.0000000000000000}, + {0.1000000000000000, 0.0100000000000000, 0.0010000000000000 + , 10.0000000000000000, 100.0000000000000000, 1000.0000000000000000}, + {0.0909090909090909, 0.0082644628099174, 0.0007513148009016 + , 11.0000000000000000, 121.0000000000000000, 1331.0000000000000000}, + {0.0833333333333333, 0.0069444444444444, 0.0005787037037037 + , 12.0000000000000000, 144.0000000000000000, 1728.0000000000000000}, + {0.0769230769230769, 0.0059171597633136, 0.0004551661356395 + , 13.0000000000000000, 169.0000000000000000, 2197.0000000000000000}, + {0.0714285714285714, 0.0051020408163265, 0.0003644314868805 + , 14.0000000000000000, 196.0000000000000000, 2744.0000000000000000}, + {0.0666666666666667, 0.0044444444444444, 0.0002962962962963 + , 15.0000000000000000, 225.0000000000000000, 3375.0000000000000000}, + {0.0625000000000000, 0.0039062500000000, 0.0002441406250000 + , 16.0000000000000000, 256.0000000000000000, 4096.0000000000000000}, + {0.0588235294117647, 0.0034602076124567, 0.0002035416242622 + , 17.0000000000000000, 289.0000000000000000, 4913.0000000000000000}, + {0.0555555555555556, 0.0030864197530864, 0.0001714677640604 + , 18.0000000000000000, 324.0000000000000000, 5832.0000000000000000}, + {0.0526315789473684, 0.0027700831024931, 0.0001457938474996 + , 19.0000000000000000, 361.0000000000000000, 6859.0000000000000000}, + {0.0500000000000000, 0.0025000000000000, 0.0001250000000000 + , 20.0000000000000000, 400.0000000000000000, 8000.0000000000000000}, + {0.0476190476190476, 0.0022675736961451, 0.0001079796998164 + , 21.0000000000000000, 441.0000000000000000, 9261.0000000000000000}, + {0.0454545454545455, 0.0020661157024793, 0.0000939143501127 + , 22.0000000000000000, 484.0000000000000000, 10648.0000000000000000}, + {0.0434782608695652, 0.0018903591682420, 0.0000821895290540 + , 23.0000000000000000, 529.0000000000000000, 12167.0000000000000000}, + {0.0416666666666667, 0.0017361111111111, 0.0000723379629630 + , 24.0000000000000000, 576.0000000000000000, 13824.0000000000000000}, + {0.0400000000000000, 0.0016000000000000, 0.0000640000000000 + , 25.0000000000000000, 625.0000000000000000, 15625.0000000000000000}, + {0.0384615384615385, 0.0014792899408284, 0.0000568957669549 + , 26.0000000000000000, 676.0000000000000000, 17576.0000000000000000}, + {0.0370370370370370, 0.0013717421124829, 0.0000508052634253 + , 27.0000000000000000, 729.0000000000000000, 19683.0000000000000000}, + {0.0357142857142857, 0.0012755102040816, 0.0000455539358601 + , 28.0000000000000000, 784.0000000000000000, 21952.0000000000000000}, + {0.0344827586206897, 0.0011890606420927, 0.0000410020911066 + , 29.0000000000000000, 841.0000000000000000, 24389.0000000000000000}, + {0.0333333333333333, 0.0011111111111111, 0.0000370370370370 + , 30.0000000000000000, 900.0000000000000000, 27000.0000000000000000}, + {0.0322580645161290, 0.0010405827263267, 0.0000335671847202 + , 31.0000000000000000, 961.0000000000000000, 29791.0000000000000000}, + {0.0312500000000000, 0.0009765625000000, 0.0000305175781250 + , 32.0000000000000000, 1024.0000000000000000, 32768.0000000000000000}}; +/* base testvector */ +static const int32_t b[64] = { + -33554432, -67108864, -100663296, -134217728, -167772160, -201326592, -234881024, + -268435456, -301989888, -335544320, -369098752, -402653184, -436207616, -469762048, + -503316480, -536870912, -570425344, -603979776, -637534208, -671088640, -704643072, + -738197504, -771751936, -805306368, -838860800, -872415232, -905969664, -939524096, + -973078528, -1006632960, -1040187392, -1073741824, 33554432, 67108864, 100663296, + 134217728, 167772160, 201326592, 234881024, 268435456, 301989888, 335544320, + 369098752, 402653184, 436207616, 469762048, 503316480, 536870912, 570425344, + 603979776, 637534208, 671088640, 704643072, 738197504, 771751936, 805306368, + 838860800, 872415232, 905969664, 939524096, 973078528, 1006632960, 1040187392, + 1073741824}; +/* exponent testvector */ +static const int32_t e[6] = {-536870912, -1073741824, -1610612736, + 536870912, 1073741824, 1610612736}; diff --git a/test/cmocka/include/test_group_generator.h b/test/cmocka/include/test_group_generator.h index 7df0f568e242..b3cba0c320ae 100644 --- a/test/cmocka/include/test_group_generator.h +++ b/test/cmocka/include/test_group_generator.h @@ -7,8 +7,8 @@ #include <test_simple_macro.h> #include <sof/trace/preproc.h> -#include <sof/sof.h> -#include <sof/lib/alloc.h> +#include <rtos/sof.h> +#include <rtos/alloc.h> /* CMOCKA SETUP */ #define setup_alloc(ptr, type, size, offset) do {\ @@ -25,49 +25,3 @@ return result;\ } while (0) -/* TEST GROUPS GENERATORS */ - -#define gen_test_concat(prefix, name) META_CONCAT_SEQ_DELIM_(prefix, name) -#define gen_test_concat_base(prefix) META_CONCAT_SEQ_DELIM_(prefix, base) -#define gen_test_concat_func(prefix, name, ...) \ -META_CONCAT_SEQ_DELIM_(prefix, name, for, __VA_ARGS__) -#define gen_test_concat_flag(prefix, ...) \ -META_CONCAT_SEQ_DELIM_(prefix, isetup, for, __VA_ARGS__) - -// make function body for "${prefix}_${name}_for_${dlen}_${cbeg}_${cend}" -#define gen_test_with_prefix(prefix_check, prefix_setup, name, ...) \ -static void gen_test_concat_func(prefix_setup, name, __VA_ARGS__) \ -(void **state) {\ - if (!gen_test_concat_flag(prefix_setup, __VA_ARGS__)) {\ - if (_setup(state, __VA_ARGS__))\ - exit(1);\ - gen_test_concat_base(prefix_setup)(state);\ - ++gen_test_concat_flag(prefix_setup, __VA_ARGS__);\ - } \ - gen_test_concat(prefix_check, name)(state);\ -} - -#define c_u_t_concat(prefix_check, prefix_setup, name, ...)\ - c_u_t(gen_test_concat_func(prefix_setup, name, __VA_ARGS__)), - -/* make function bodies for - * function group "${prefix}_for_${dlen}_${cbeg}_${cend}" - */ -#define gen_test_group(bind_macro, ...)\ - bind_macro(gen_test_with_prefix, __VA_ARGS__) - -/* create 1 flag for - * function group "${prefix}_for_${dlen}_${cbeg}_${cend}" - */ -#define flg_test_group(prefix, ...)\ - static int gen_test_concat_flag(prefix, __VA_ARGS__); - -/* paste instances to - * function grup "${prefix}_for_${dlen}_${cbeg}_${cend}" - */ -#define use_test_group(bind_macro, ...)\ - bind_macro(c_u_t_concat, __VA_ARGS__) - -/* for example usage, see /test/cmocka/src/lib/lib/strcheck.c - * section TEST GROUPS GENERATORS - */ diff --git a/test/cmocka/include/test_simple_macro.h b/test/cmocka/include/test_simple_macro.h deleted file mode 100644 index f62129c5d335..000000000000 --- a/test/cmocka/include/test_simple_macro.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - */ - -#define c_u_t(x) cmocka_unit_test(x) - -#define TEST_HERE_DECLARE(test_func, ...)\ - TEST_FUNC(TEST_PREFIX, test_func, __VA_ARGS__) - -#define TEST_HERE_USE(test_func, postfix)\ - c_u_t(META_CONCAT_SEQ_DELIM_(TEST_PREFIX, test_func, postfix)) diff --git a/test/cmocka/m/export_comment.m b/test/cmocka/m/export_comment.m new file mode 100644 index 000000000000..3c879b59433b --- /dev/null +++ b/test/cmocka/m/export_comment.m @@ -0,0 +1,15 @@ +% export_comment(fh, text) +% +% Inputs +% fh - file handle +% text - text comment + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function export_comment(fh, text) + + fprintf(fh, '/* %s */\n\n', text); + +end diff --git a/test/cmocka/m/export_get_git_describe.m b/test/cmocka/m/export_get_git_describe.m new file mode 100644 index 000000000000..b5fd3d2a428d --- /dev/null +++ b/test/cmocka/m/export_get_git_describe.m @@ -0,0 +1,19 @@ +% description = export_get_git_describe() +% +% Outputs +% description - git describe output in successful run, otherwise Unknown + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function description = export_get_git_describe() + + git_cmd = 'git describe --dirty --long --always'; + [status, out] = system(git_cmd); + description = strtrim(out); + if status + description = 'Unknown' + end + +end diff --git a/test/cmocka/m/export_headerfile_open.m b/test/cmocka/m/export_headerfile_open.m new file mode 100644 index 000000000000..5b83e202d8a7 --- /dev/null +++ b/test/cmocka/m/export_headerfile_open.m @@ -0,0 +1,29 @@ +% fh = export_headerfile_open(headerfn, corp) +% +% Inputs +% headerfn - File name of exported header file +% corp - optional corporation name, defaults to Intel Corporation +% +% Outputs +% fh - file handle + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022-2025 Intel Corporation. + +function fh = export_headerfile_open(headerfn, corp) + + if nargin < 2 + corp = 'Intel Corporation'; + end + + fh = fopen(headerfn, 'w'); + if fh < 0 + error('Could not open file'); + end + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s %s.\n', ... + datestr(now, 'yyyy'), corp); + fprintf(fh, ' */\n\n'); +end diff --git a/test/cmocka/m/export_ndefine.m b/test/cmocka/m/export_ndefine.m new file mode 100644 index 000000000000..94214406729b --- /dev/null +++ b/test/cmocka/m/export_ndefine.m @@ -0,0 +1,16 @@ +% export_ndefine(fh, dn, val) +% +% Inputs +% fh - file handle +% dn - define macro name +% val - value for macro + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function export_ndefine(fh, dn, dval) + + fprintf(fh, '#define %s %d\n', dn, dval); + +end diff --git a/test/cmocka/m/export_quant_qxy.m b/test/cmocka/m/export_quant_qxy.m new file mode 100644 index 000000000000..223358d1f880 --- /dev/null +++ b/test/cmocka/m/export_quant_qxy.m @@ -0,0 +1,52 @@ +% [ival, qval] = export_quant_qxy(val, bits, fracbits, saturate) +% +% Inputs +% val - values to quantize +% bits - number of bits +% fracbits - the number of bits y in Qx.y format +% saturate - true or false, when false overflow is an error. +% false if omitted. +% +% Outputs +% ival - quantized value as integer +% qval - quantized value as float, same scale as val + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function [ival, qval] = export_quant_qxy(val, bits, fracbits, saturate) + + if nargin < 4 + saturate = false; + end + intmax = 2^(bits - 1) - 1; + intmin = -intmax - 1; + scale = 2^fracbits; + yf = round(val * scale); + if saturate == true + yf(yf > intmax) = intmax; + yf(yf < intmin) = intmin; + end + + min_y = min(min(yf)); + max_y = max(max(yf)); + if max_y > intmax || min_y < intmin + fprintf(1, 'max = %d (%d), min = %d (%d)\n', ... + max_y, intmax, min_y, intmin); + error('Overflow, use other Q format'); + end + + switch bits + case 8 + ival = int8(yf); + case 16 + ival = int16(yf); + case 32 + ival = int32(yf); + otherwise + error('Unknown bits'); + end + + qval = double(ival) / scale; +end diff --git a/test/cmocka/m/export_sdefine.m b/test/cmocka/m/export_sdefine.m new file mode 100644 index 000000000000..19f4448b98fd --- /dev/null +++ b/test/cmocka/m/export_sdefine.m @@ -0,0 +1,16 @@ +% export_sdefine(fh, dn, str) +% +% Inputs +% fh - file handle +% dn - define macro name +% str - string for macro + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function export_sdefine(fh, dn, dstr) + + fprintf(fh, '#define %s %s\n', dn, dstr); + +end diff --git a/test/cmocka/m/export_vector.m b/test/cmocka/m/export_vector.m new file mode 100644 index 000000000000..572646e7468f --- /dev/null +++ b/test/cmocka/m/export_vector.m @@ -0,0 +1,60 @@ +% export_vector(fh, bits, vname, data, msize) +% +% Inputs +% fh - file handle +% bits - number of bits +% vname - variable name +% data - vector of integer data +% msize - optional, size of original matrix to guide formatting + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function export_vector(fh, bits, vname, data, msize) + switch bits + case 8 + vtype = 'int8_t'; + maxcol = 10; + case 16 + vtype = 'int16_t'; + maxcol = 10; + case 32 + vtype = 'int32_t'; + maxcol = 6; + otherwise + error('Unkown bits format') + end + + if nargin == 5 + columns = msize(2); + columns = min(columns, maxcol); + else + columns = maxcol; + end + + rows = ceil(length(data) / columns); + fprintf(fh, '\nstatic const %s %s[%d] = {\n', ... + vtype, vname, length(data)); + i = 1; + for j = 1:rows + if bits > 16 + fprintf(fh, '\t%11d,', data(i)); + else + fprintf(fh, '\t%6d,', data(i)); + end + i = i + 1; + for k = 2:columns + if i <= length(data) + if bits > 16 + fprintf(fh, ' %11d,', data(i)); + else + fprintf(fh, ' %6d,', data(i)); + end + i = i + 1; + end + end + fprintf(fh, '\n'); + end + fprintf(fh, '};\n'); +end diff --git a/test/cmocka/memory_mock.x.in b/test/cmocka/memory_mock.x.in index 8c70d5d14979..add0b217b077 100644 --- a/test/cmocka/memory_mock.x.in +++ b/test/cmocka/memory_mock.x.in @@ -14,11 +14,13 @@ SECTIONS _comp_init_start = .; _comp_init_end = .; - _module_heap = HEAP_RUNTIME_BASE; - _buffer_heap = HEAP_BUFFER_BASE; _system_heap = HEAP_SYSTEM_0_BASE; _system_heap_start = HEAP_SYSTEM_0_BASE; _system_runtime_heap = HEAP_SYS_RUNTIME_0_BASE; _sof_core_s_start = SOF_CORE_S_START; + _runtime_shared_heap = HEAP_RUNTIME_SHARED_BASE; + _system_shared_heap = HEAP_SYSTEM_SHARED_BASE; + _module_heap = HEAP_RUNTIME_BASE; + _buffer_heap = HEAP_BUFFER_BASE; } INSERT AFTER .text; diff --git a/test/cmocka/src/CMakeLists.txt b/test/cmocka/src/CMakeLists.txt index 62e12651825c..2c244aea9d0d 100644 --- a/test/cmocka/src/CMakeLists.txt +++ b/test/cmocka/src/CMakeLists.txt @@ -1,7 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause add_subdirectory(audio) -add_subdirectory(debugability) add_subdirectory(lib) -add_subdirectory(list) add_subdirectory(math) diff --git a/test/cmocka/src/audio/CMakeLists.txt b/test/cmocka/src/audio/CMakeLists.txt index 61ccb2153a23..d199fd18a0ea 100644 --- a/test/cmocka/src/audio/CMakeLists.txt +++ b/test/cmocka/src/audio/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(buffer) add_subdirectory(component) +add_subdirectory(pcm_converter) if(CONFIG_COMP_MIXER) add_subdirectory(mixer) endif() @@ -15,4 +16,12 @@ endif() if(CONFIG_COMP_SEL) add_subdirectory(selector) endif() - +if(CONFIG_COMP_IIR) + add_subdirectory(eq_iir) +endif() +if(CONFIG_COMP_FIR) + add_subdirectory(eq_fir) +endif() +if(CONFIG_COMP_DRC) + add_subdirectory(drc) +endif() diff --git a/test/cmocka/src/audio/buffer/CMakeLists.txt b/test/cmocka/src/audio/buffer/CMakeLists.txt index 6156fa0006fb..f97c77f3679b 100644 --- a/test/cmocka/src/audio/buffer/CMakeLists.txt +++ b/test/cmocka/src/audio/buffer/CMakeLists.txt @@ -2,28 +2,96 @@ cmocka_test(buffer_copy buffer_copy.c - mock.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) cmocka_test(buffer_new buffer_new.c - mock.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) cmocka_test(buffer_wrap buffer_wrap.c - mock.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) cmocka_test(buffer_write buffer_write.c - mock.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) diff --git a/test/cmocka/src/audio/buffer/buffer_copy.c b/test/cmocka/src/audio/buffer/buffer_copy.c index 4d126a95a46e..f4e958d7fe19 100644 --- a/test/cmocka/src/audio/buffer/buffer_copy.c +++ b/test/cmocka/src/audio/buffer/buffer_copy.c @@ -6,7 +6,10 @@ #include <sof/audio/component.h> #include <sof/audio/buffer.h> -#include <sof/drivers/ipc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> #include <stdio.h> #include <stdarg.h> @@ -26,8 +29,8 @@ static void test_audio_buffer_copy_underrun(void **state) .size = 256 }; - struct comp_buffer *src = buffer_new(&test_buf_desc); - struct comp_buffer *snk = buffer_new(&test_buf_desc); + struct comp_buffer *src = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *snk = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(src); assert_non_null(snk); @@ -36,7 +39,7 @@ static void test_audio_buffer_copy_underrun(void **state) copy_bytes = audio_stream_can_copy_bytes(&src->stream, &snk->stream, 16); - assert_int_equal(src->stream.avail, 10); + assert_int_equal(audio_stream_get_avail_bytes(&src->stream), 10); assert_int_equal(copy_bytes, -1); buffer_free(src); @@ -53,8 +56,8 @@ static void test_audio_buffer_copy_overrun(void **state) .size = 256 }; - struct comp_buffer *src = buffer_new(&test_buf_desc); - struct comp_buffer *snk = buffer_new(&test_buf_desc); + struct comp_buffer *src = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *snk = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(src); assert_non_null(snk); @@ -64,8 +67,8 @@ static void test_audio_buffer_copy_overrun(void **state) copy_bytes = audio_stream_can_copy_bytes(&src->stream, &snk->stream, 16); - assert_int_equal(src->stream.avail, 16); - assert_int_equal(snk->stream.free, 10); + assert_int_equal(audio_stream_get_avail_bytes(&src->stream), 16); + assert_int_equal(audio_stream_get_free_bytes(&snk->stream), 10); assert_int_equal(copy_bytes, 1); buffer_free(src); @@ -82,8 +85,8 @@ static void test_audio_buffer_copy_success(void **state) .size = 256 }; - struct comp_buffer *src = buffer_new(&test_buf_desc); - struct comp_buffer *snk = buffer_new(&test_buf_desc); + struct comp_buffer *src = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *snk = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(src); assert_non_null(snk); @@ -91,7 +94,7 @@ static void test_audio_buffer_copy_success(void **state) comp_update_buffer_produce(src, 10); copy_bytes = audio_stream_can_copy_bytes(&src->stream, &snk->stream, 0); - assert_int_equal(src->stream.avail, 10); + assert_int_equal(audio_stream_get_avail_bytes(&src->stream), 10); assert_int_equal(copy_bytes, 0); buffer_free(src); @@ -108,8 +111,8 @@ static void test_audio_buffer_copy_fit_space_constraint(void **state) .size = 256 }; - struct comp_buffer *src = buffer_new(&test_buf_desc); - struct comp_buffer *snk = buffer_new(&test_buf_desc); + struct comp_buffer *src = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *snk = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(src); assert_non_null(snk); @@ -118,8 +121,8 @@ static void test_audio_buffer_copy_fit_space_constraint(void **state) comp_update_buffer_produce(snk, 246); copy_bytes = audio_stream_get_copy_bytes(&src->stream, &snk->stream); - assert_int_equal(src->stream.avail, 16); - assert_int_equal(snk->stream.free, 10); + assert_int_equal(audio_stream_get_avail_bytes(&src->stream), 16); + assert_int_equal(audio_stream_get_free_bytes(&snk->stream), 10); assert_int_equal(copy_bytes, 10); buffer_free(src); @@ -136,8 +139,8 @@ static void test_audio_buffer_copy_fit_no_space_constraint(void **state) .size = 256 }; - struct comp_buffer *src = buffer_new(&test_buf_desc); - struct comp_buffer *snk = buffer_new(&test_buf_desc); + struct comp_buffer *src = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *snk = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(src); assert_non_null(snk); @@ -145,7 +148,7 @@ static void test_audio_buffer_copy_fit_no_space_constraint(void **state) comp_update_buffer_produce(src, 16); copy_bytes = audio_stream_get_copy_bytes(&src->stream, &snk->stream); - assert_int_equal(src->stream.avail, 16); + assert_int_equal(audio_stream_get_avail_bytes(&src->stream), 16); assert_int_equal(copy_bytes, 16); buffer_free(src); diff --git a/test/cmocka/src/audio/buffer/buffer_new.c b/test/cmocka/src/audio/buffer/buffer_new.c index f538acb862ab..1561c94ec675 100644 --- a/test/cmocka/src/audio/buffer/buffer_new.c +++ b/test/cmocka/src/audio/buffer/buffer_new.c @@ -6,7 +6,10 @@ #include <sof/audio/component.h> #include <sof/audio/buffer.h> -#include <sof/drivers/ipc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> #include <stdio.h> #include <stdarg.h> @@ -24,11 +27,11 @@ static void test_audio_buffer_new(void **state) .size = 256 }; - struct comp_buffer *buf = buffer_new(&test_buf_desc); + struct comp_buffer *buf = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(buf); - assert_int_equal(buf->stream.avail, 0); - assert_int_equal(buf->stream.free, 256); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 0); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 256); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); buffer_free(buf); diff --git a/test/cmocka/src/audio/buffer/buffer_wrap.c b/test/cmocka/src/audio/buffer/buffer_wrap.c index 20a0095d7896..a1fc37383274 100644 --- a/test/cmocka/src/audio/buffer/buffer_wrap.c +++ b/test/cmocka/src/audio/buffer/buffer_wrap.c @@ -6,7 +6,10 @@ #include <sof/audio/component.h> #include <sof/audio/buffer.h> -#include <sof/drivers/ipc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> #include <stdio.h> #include <stdarg.h> @@ -24,36 +27,51 @@ static void test_audio_buffer_write_fill_10_bytes_and_write_5(void **state) .size = 10 }; - struct comp_buffer *buf = buffer_new(&test_buf_desc); + struct comp_buffer *buf = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(buf); - assert_int_equal(buf->stream.avail, 0); - assert_int_equal(buf->stream.free, 10); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 0); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 10); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); uint8_t bytes[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - memcpy_s(buf->stream.w_ptr, test_buf_desc.size, &bytes, 10); - comp_update_buffer_produce(buf, 10); + int i; + uint8_t *ptr; - assert_int_equal(buf->stream.avail, 10); - assert_int_equal(buf->stream.free, 0); + for (i = 0; i < ARRAY_SIZE(bytes); i++) { + ptr = audio_stream_write_frag(&buf->stream, i, sizeof(uint8_t)); + *ptr = bytes[i]; + } + comp_update_buffer_produce(buf, sizeof(bytes)); + + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), sizeof(bytes)); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 0); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); uint8_t more_bytes[5] = {10, 11, 12, 13, 14}; - memcpy_s(buf->stream.w_ptr, test_buf_desc.size, &more_bytes, 5); - comp_update_buffer_produce(buf, 5); + for (i = 0; i < ARRAY_SIZE(more_bytes); i++) { + ptr = audio_stream_write_frag(&buf->stream, i, sizeof(uint8_t)); + *ptr = more_bytes[i]; + } + comp_update_buffer_produce(buf, sizeof(more_bytes)); uint8_t ref_1[5] = {5, 6, 7, 8, 9}; uint8_t ref_2[5] = {10, 11, 12, 13, 14}; - assert_int_equal(buf->stream.avail, 10); - assert_int_equal(buf->stream.free, 0); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 10); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 0); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); - assert_int_equal(memcmp(buf->stream.r_ptr, &ref_1, 5), 0); - comp_update_buffer_consume(buf, 5); - assert_int_equal(memcmp(buf->stream.r_ptr, &ref_2, 5), 0); + for (i = 0; i < ARRAY_SIZE(ref_1); i++) { + ptr = audio_stream_read_frag(&buf->stream, i, sizeof(uint8_t)); + assert_int_equal(*ptr, ref_1[i]); + } + comp_update_buffer_consume(buf, sizeof(ref_1)); + for (i = 0; i < ARRAY_SIZE(ref_2); i++) { + ptr = audio_stream_read_frag(&buf->stream, i, sizeof(uint8_t)); + assert_int_equal(*ptr, ref_2[i]); + } buffer_free(buf); } diff --git a/test/cmocka/src/audio/buffer/buffer_write.c b/test/cmocka/src/audio/buffer/buffer_write.c index 6416879c2b68..3fd5504560d8 100644 --- a/test/cmocka/src/audio/buffer/buffer_write.c +++ b/test/cmocka/src/audio/buffer/buffer_write.c @@ -6,7 +6,10 @@ #include <sof/audio/component.h> #include <sof/audio/buffer.h> -#include <sof/drivers/ipc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> #include <stdio.h> #include <stdarg.h> @@ -25,11 +28,11 @@ static void test_audio_buffer_write_10_bytes_out_of_256_and_read_back .size = 256 }; - struct comp_buffer *buf = buffer_new(&test_buf_desc); + struct comp_buffer *buf = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(buf); - assert_int_equal(buf->stream.avail, 0); - assert_int_equal(buf->stream.free, 256); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 0); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 256); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); uint8_t bytes[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -37,16 +40,16 @@ static void test_audio_buffer_write_10_bytes_out_of_256_and_read_back memcpy_s(buf->stream.w_ptr, test_buf_desc.size, &bytes, 10); comp_update_buffer_produce(buf, 10); - assert_int_equal(buf->stream.avail, 10); - assert_int_equal(buf->stream.free, 246); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 10); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 246); assert_ptr_equal(buf->stream.w_ptr, (char *)buf->stream.r_ptr + 10); assert_int_equal(memcmp(buf->stream.r_ptr, &bytes, 10), 0); comp_update_buffer_consume(buf, 10); - assert_int_equal(buf->stream.avail, 0); - assert_int_equal(buf->stream.free, 256); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 0); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 256); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); buffer_free(buf); @@ -60,11 +63,11 @@ static void test_audio_buffer_fill_10_bytes(void **state) .size = 10 }; - struct comp_buffer *buf = buffer_new(&test_buf_desc); + struct comp_buffer *buf = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); assert_non_null(buf); - assert_int_equal(buf->stream.avail, 0); - assert_int_equal(buf->stream.free, 10); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 0); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 10); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); uint8_t bytes[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -72,8 +75,8 @@ static void test_audio_buffer_fill_10_bytes(void **state) memcpy_s(buf->stream.w_ptr, test_buf_desc.size, &bytes, 10); comp_update_buffer_produce(buf, 10); - assert_int_equal(buf->stream.avail, 10); - assert_int_equal(buf->stream.free, 0); + assert_int_equal(audio_stream_get_avail_bytes(&buf->stream), 10); + assert_int_equal(audio_stream_get_free_bytes(&buf->stream), 0); assert_ptr_equal(buf->stream.w_ptr, buf->stream.r_ptr); buffer_free(buf); diff --git a/test/cmocka/src/audio/buffer/mock.c b/test/cmocka/src/audio/buffer/mock.c deleted file mode 100644 index 76d2eb6b9a6c..000000000000 --- a/test/cmocka/src/audio/buffer/mock.c +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <stdint.h> -#include <stdlib.h> - -#include <config.h> -#include <sof/lib/alloc.h> -#include <sof/trace/trace.h> - -#include <mock_trace.h> - -TRACE_IMPL() diff --git a/test/cmocka/src/audio/component/CMakeLists.txt b/test/cmocka/src/audio/component/CMakeLists.txt index 3f4fe40acb74..61abb66332c2 100644 --- a/test/cmocka/src/audio/component/CMakeLists.txt +++ b/test/cmocka/src/audio/component/CMakeLists.txt @@ -2,6 +2,24 @@ cmocka_test(comp_set_state comp_set_state.c - mock.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 + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ) diff --git a/test/cmocka/src/audio/component/comp_set_state.c b/test/cmocka/src/audio/component/comp_set_state.c index 5a4e6285c3c6..c643110e167d 100644 --- a/test/cmocka/src/audio/component/comp_set_state.c +++ b/test/cmocka/src/audio/component/comp_set_state.c @@ -12,7 +12,7 @@ #include <setjmp.h> #include <stdint.h> #include <cmocka.h> -#include <sof/sof.h> +#include <rtos/sof.h> enum test_type { SUCCEED = 0, @@ -34,7 +34,6 @@ struct test_case { ("test_audio_component_comp_set_state__" \ #type "__" #in_state "__" #cmd "__" #out_state)} - /* * NULL_STATE enum is used in every case, when new state of component is * insignificant due to action of testing function @@ -47,8 +46,12 @@ struct test_case test_cases[] = { /*succeed set state*/ TEST_CASE(SUCCEED, COMP_STATE_PREPARE, + COMP_TRIGGER_PRE_START, NULL_STATE), + TEST_CASE(SUCCEED, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_START, NULL_STATE), TEST_CASE(SUCCEED, COMP_STATE_PAUSED, + COMP_TRIGGER_PRE_RELEASE, NULL_STATE), + TEST_CASE(SUCCEED, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_RELEASE, NULL_STATE), TEST_CASE(SUCCEED, COMP_STATE_ACTIVE, COMP_TRIGGER_STOP, NULL_STATE), @@ -78,6 +81,8 @@ struct test_case test_cases[] = { NULL_STATE), TEST_CASE(FAIL, COMP_STATE_PAUSED, COMP_TRIGGER_START, NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PREPARE, COMP_TRIGGER_START, + NULL_STATE), TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_RELEASE, NULL_STATE), TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_RELEASE, @@ -86,12 +91,16 @@ struct test_case test_cases[] = { NULL_STATE), TEST_CASE(FAIL, COMP_STATE_PREPARE, COMP_TRIGGER_RELEASE, NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PAUSED, COMP_TRIGGER_RELEASE, + NULL_STATE), TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_STOP, NULL_STATE), TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_STOP, NULL_STATE), TEST_CASE(FAIL, COMP_STATE_SUSPEND, COMP_TRIGGER_STOP, NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_STOP, + NULL_STATE), TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_PAUSE, NULL_STATE), TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_PAUSE, @@ -100,6 +109,8 @@ struct test_case test_cases[] = { NULL_STATE), TEST_CASE(FAIL, COMP_STATE_PREPARE, COMP_TRIGGER_PAUSE, NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_PAUSE, + NULL_STATE), TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_PREPARE, NULL_STATE), TEST_CASE(FAIL, COMP_STATE_SUSPEND, COMP_TRIGGER_PREPARE, @@ -108,26 +119,52 @@ struct test_case test_cases[] = { NULL_STATE), TEST_CASE(FAIL, COMP_STATE_ACTIVE, COMP_TRIGGER_PREPARE, NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_PREPARE, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_PRE_START, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_PRE_START, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_SUSPEND, COMP_TRIGGER_PRE_START, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PAUSED, COMP_TRIGGER_PRE_START, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_ACTIVE, COMP_TRIGGER_PRE_START, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_INIT, COMP_TRIGGER_PRE_RELEASE, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_READY, COMP_TRIGGER_PRE_RELEASE, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_SUSPEND, COMP_TRIGGER_PRE_RELEASE, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_ACTIVE, COMP_TRIGGER_PRE_RELEASE, + NULL_STATE), + TEST_CASE(FAIL, COMP_STATE_PREPARE, COMP_TRIGGER_PRE_RELEASE, + NULL_STATE), /*correct output state*/ TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PREPARE, + COMP_TRIGGER_PRE_START, COMP_STATE_PRE_ACTIVE), + TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_START, COMP_STATE_ACTIVE), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PAUSED, + COMP_TRIGGER_PRE_RELEASE, COMP_STATE_PRE_ACTIVE), + TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PRE_ACTIVE, COMP_TRIGGER_RELEASE, COMP_STATE_ACTIVE), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_ACTIVE, COMP_TRIGGER_STOP, COMP_STATE_PREPARE), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PAUSED, COMP_TRIGGER_STOP, COMP_STATE_PREPARE), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_INIT, - COMP_TRIGGER_XRUN, COMP_STATE_READY), + COMP_TRIGGER_XRUN, COMP_STATE_INIT), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_SUSPEND, - COMP_TRIGGER_XRUN, COMP_STATE_READY), + COMP_TRIGGER_XRUN, COMP_STATE_SUSPEND), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PREPARE, - COMP_TRIGGER_XRUN, COMP_STATE_READY), + COMP_TRIGGER_XRUN, COMP_STATE_PREPARE), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_PAUSED, - COMP_TRIGGER_XRUN, COMP_STATE_READY), + COMP_TRIGGER_XRUN, COMP_STATE_PAUSED), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_ACTIVE, - COMP_TRIGGER_XRUN, COMP_STATE_READY), + COMP_TRIGGER_XRUN, COMP_STATE_ACTIVE), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_ACTIVE, COMP_TRIGGER_PAUSE, COMP_STATE_PAUSED), TEST_CASE(CORRECT_OUTPUT_STATE, COMP_STATE_INIT, diff --git a/test/cmocka/src/audio/component/mock.c b/test/cmocka/src/audio/component/mock.c deleted file mode 100644 index 31b6b843e736..000000000000 --- a/test/cmocka/src/audio/component/mock.c +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> - -#include <stdint.h> -#include <stdlib.h> - -#include <sof/lib/alloc.h> -#include <sof/trace/trace.h> -#include <sof/audio/component.h> - -#include <mock_trace.h> - -TRACE_IMPL() - -static struct sof sof; - -#if !CONFIG_LIBRARY - -void *_zalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - (void)zone; - (void)flags; - (void)caps; - - return calloc(bytes, 1); -} - -void *_realloc(void *ptr, enum mem_zone zone, uint32_t flags, uint32_t caps, - size_t bytes) -{ - (void)ptr; - (void)zone; - (void)flags; - (void)caps; - - return realloc(ptr, bytes); -} - -int buffer_set_size(struct comp_buffer *buffer, uint32_t size) -{ - (void)buffer; - (void)size; - - return 0; -} - -void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes) -{ -} - -struct sof *sof_get(void) -{ - return &sof; -} - -#endif diff --git a/test/cmocka/src/audio/drc/CMakeLists.txt b/test/cmocka/src/audio/drc/CMakeLists.txt new file mode 100644 index 000000000000..f0c351e5c90a --- /dev/null +++ b/test/cmocka/src/audio/drc/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(drc_math_test + drc_math_test.c + ${PROJECT_SOURCE_DIR}/src/audio/drc/drc_math_generic.c + ${PROJECT_SOURCE_DIR}/src/audio/drc/drc_math_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c + ${PROJECT_SOURCE_DIR}/src/math/exp_fcn.c + ${PROJECT_SOURCE_DIR}/src/math/exp_fcn_hifi.c +) + +target_include_directories(drc_math_test PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) diff --git a/test/cmocka/src/audio/drc/drc_math_test.c b/test/cmocka/src/audio/drc/drc_math_test.c new file mode 100644 index 000000000000..03b23577f0c7 --- /dev/null +++ b/test/cmocka/src/audio/drc/drc_math_test.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. + +#include <math.h> +#include <stdbool.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <stdint.h> +#include <stdio.h> +#include <cmocka.h> + +#include <drc/drc_math.h> + +#define TEST_POINTS 500 + +#define ABS_DELTA_TOLERANCE_T1 1.0e-9 +#define REL_DELTA_TOLERANCE_T1 1.4e-4 +#define ABS_DELTA_TOLERANCE_T2 7.4e-7 +#define REL_DELTA_TOLERANCE_T2 7.5e-6 +#define ABS_DELTA_TOLERANCE_T3 3.8e-4 +#define REL_DELTA_TOLERANCE_T3 1.9e-6 + +static int32_t drc_inv_ref(int32_t x, int32_t precision_x, int32_t precision_y) +{ + double xf, yf, ys; + + xf = (double)x / ((int64_t)1 << precision_x); + yf = 1 / xf; + ys = round(yf * ((int64_t)1 << precision_y)); + if (ys > INT32_MAX) + ys = INT32_MAX; + + if (ys < INT32_MIN) + ys = INT32_MIN; + + return (int32_t)ys; +} + +static void drc_math_inv_fixed_test_helper(int32_t x_start, int32_t x_end, + int32_t x_step, int q_in, int q_out, + double abs_delta_tolerance, double rel_delta_tolerance) +{ + double fx, fy1, fy2; + double abs_delta, rel_delta; + int64_t x1; + int32_t x, y1, y2; + int32_t differences = 0; + double abs_delta_max = 0; + double rel_delta_max = 0; + + printf("%s: Testing q_in = %d q_out = %d in = %d:%d:%d\n", __func__, + q_in, q_out, x_start, x_step, x_end); + + x1 = x_start; + while (x1 <= x_end) { + x = (int32_t)x1; + y1 = drc_inv_ref(x, q_in, q_out); + y2 = drc_inv_fixed(x, q_in, q_out); + if (y1 != y2) + differences++; + + fx = (double)x / (1 << q_in); + fy1 = (double)y1 / (1 << q_out); + fy2 = (double)y2 / (1 << q_out); + abs_delta = fabs(fy1 - fy2); + rel_delta = abs_delta / fy1; + if (rel_delta > rel_delta_max) + rel_delta_max = rel_delta; + + if (abs_delta > abs_delta_max) + abs_delta_max = abs_delta; + + if (rel_delta > rel_delta_tolerance) { + printf("%s: Relative error %g exceeds limit %g, input %g output %g ref %g.\n", + __func__, rel_delta, rel_delta_tolerance, fx, fy2, fy1); + assert_true(false); + } + + if (abs_delta > abs_delta_tolerance) { + printf("%s: Absolute error %g exceeds limit %g, input %g output %g ref %g.\n", + __func__, abs_delta, abs_delta_tolerance, fx, fy2, fy1); + assert_true(false); + } + + x1 += x_step; + } + + printf("%s: bit exact differences count = %d\n", __func__, differences); + printf("%s: Absolute max error was %.6e.\n", __func__, abs_delta_max); + printf("%s: Relative max error was %.6e.\n", __func__, rel_delta_max); +} + +static void test_function_drc_inv_fixed_q12_q30(void **state) +{ + (void)state; + + int32_t x_start = 1; + int32_t x_end = INT32_MAX; + int32_t x_step = (int32_t)(((int64_t)x_end - (int64_t)x_start) / (TEST_POINTS - 1)); + int q_in = 12; + int q_out = 30; + + drc_math_inv_fixed_test_helper(x_start, x_end, x_step, q_in, q_out, + ABS_DELTA_TOLERANCE_T1, REL_DELTA_TOLERANCE_T1); +} + +static void test_function_drc_inv_fixed_q22_q26(void **state) +{ + (void)state; + + int32_t x_start = 1; + int32_t x_end = INT32_MAX; + int32_t x_step = (int32_t)(((int64_t)x_end - (int64_t)x_start) / TEST_POINTS); + int q_in = 22; + int q_out = 26; + + drc_math_inv_fixed_test_helper(x_start, x_end, x_step, q_in, q_out, + ABS_DELTA_TOLERANCE_T2, REL_DELTA_TOLERANCE_T2); +} + +static void test_function_drc_inv_fixed_q31_q20(void **state) +{ + (void)state; + + int32_t x_start = 1; + int32_t x_end = INT32_MAX; + int32_t x_step = (int32_t)(((int64_t)x_end - (int64_t)x_start) / TEST_POINTS); + int q_in = 31; + int q_out = 20; + + drc_math_inv_fixed_test_helper(x_start, x_end, x_step, q_in, q_out, + ABS_DELTA_TOLERANCE_T3, REL_DELTA_TOLERANCE_T3); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_function_drc_inv_fixed_q12_q30), + cmocka_unit_test(test_function_drc_inv_fixed_q22_q26), + cmocka_unit_test(test_function_drc_inv_fixed_q31_q20), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/audio/eq_fir/CMakeLists.txt b/test/cmocka/src/audio/eq_fir/CMakeLists.txt new file mode 100644 index 000000000000..226128b220d2 --- /dev/null +++ b/test/cmocka/src/audio/eq_fir/CMakeLists.txt @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(eq_fir_process + eq_fir_process.c +) + +target_include_directories(eq_fir_process PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) + +# make small version of libaudio so we don't have to care +# about unused missing references + +add_compile_options(-DUNIT_TEST) + +add_library(audio_for_eq_fir STATIC + ${PROJECT_SOURCE_DIR}/src/audio/eq_fir/eq_fir.c + ${PROJECT_SOURCE_DIR}/src/audio/eq_fir/eq_fir_ipc3.c + ${PROJECT_SOURCE_DIR}/src/audio/eq_fir/eq_fir_generic.c + ${PROJECT_SOURCE_DIR}/src/audio/eq_fir/eq_fir_hifi2ep.c + ${PROJECT_SOURCE_DIR}/src/audio/eq_fir/eq_fir_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/fir_generic.c + ${PROJECT_SOURCE_DIR}/src/math/fir_hifi2ep.c + ${PROJECT_SOURCE_DIR}/src/math/fir_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter_ipc3.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module/generic.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/lib/objpool.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c +) +sof_append_relative_path_definitions(audio_for_eq_fir) + +target_link_libraries(audio_for_eq_fir PRIVATE sof_options) + +target_link_libraries(eq_fir_process PRIVATE audio_for_eq_fir) diff --git a/test/cmocka/src/audio/eq_fir/cmocka_fir_coef_2ch.h b/test/cmocka/src/audio/eq_fir/cmocka_fir_coef_2ch.h new file mode 100644 index 000000000000..dc8f341ba71a --- /dev/null +++ b/test/cmocka/src/audio/eq_fir/cmocka_fir_coef_2ch.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +uint32_t fir_coef_2ch[146] = { + 0x00464f53, 0x00000000, 0x00000228, 0x03016001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000228, 0x00010002, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x000000fc, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00010001, 0x00010001, 0x00010001, 0x00010001, + 0x00020001, 0x00020002, 0x00020002, 0x00030003, + 0x00030003, 0x00040003, 0x00040004, 0x00050005, + 0x00060005, 0x00060006, 0x00070007, 0x00080008, + 0x00090009, 0x000a000a, 0x000b000b, 0x000c000c, + 0x000d000d, 0x000f000e, 0x0010000f, 0x00120011, + 0x00130012, 0x00150014, 0x00170016, 0x00190018, + 0x001b001a, 0x001e001d, 0x0021001f, 0x00240022, + 0x00280026, 0x002b0029, 0x002f002d, 0x00340032, + 0x00380036, 0x003d003b, 0x00420040, 0x00480045, + 0x004d004b, 0x00540051, 0x005b0057, 0x0062005e, + 0x00680065, 0x006f006c, 0x00760072, 0x007d0079, + 0x00860081, 0x0092008c, 0x009f0098, 0x00ac00a5, + 0x00b800b2, 0x00c600be, 0x00d800ce, 0x00ea00e1, + 0x00f500ef, 0x00fc00fc, 0x00ff0118, 0x0170012f, + 0x043900c3, 0xe9ae02d3, 0xe9ae6cbf, 0x043902d3, + 0x017000c3, 0x00ff012f, 0x00fc0118, 0x00f500fc, + 0x00ea00ef, 0x00d800e1, 0x00c600ce, 0x00b800be, + 0x00ac00b2, 0x009f00a5, 0x00920098, 0x0086008c, + 0x007d0081, 0x00760079, 0x006f0072, 0x0068006c, + 0x00620065, 0x005b005e, 0x00540057, 0x004d0051, + 0x0048004b, 0x00420045, 0x003d0040, 0x0038003b, + 0x00340036, 0x002f0032, 0x002b002d, 0x00280029, + 0x00240026, 0x00210022, 0x001e001f, 0x001b001d, + 0x0019001a, 0x00170018, 0x00150016, 0x00130014, + 0x00120012, 0x00100011, 0x000f000f, 0x000d000e, + 0x000c000d, 0x000b000c, 0x000a000b, 0x0009000a, + 0x00080009, 0x00070008, 0x00060007, 0x00060006, + 0x00050005, 0x00040005, 0x00040004, 0x00030003, + 0x00030003, 0x00020003, 0x00020002, 0x00020002, + 0x00010001, 0x00010001, 0x00010001, 0x00010001, + 0x00000001, 0x00000000 +}; diff --git a/test/cmocka/src/audio/eq_fir/cmocka_fir_ref.h b/test/cmocka/src/audio/eq_fir/cmocka_fir_ref.h new file mode 100644 index 000000000000..fdc43bb07bde --- /dev/null +++ b/test/cmocka/src/audio/eq_fir/cmocka_fir_ref.h @@ -0,0 +1,1609 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#define FIR_REF_2CH_LENGTH 9600 + +int32_t fir_ref_2ch[FIR_REF_2CH_LENGTH] = { + 49805LL, 42597LL, 100165LL, 84537LL, 151069LL, 125814LL, + 202511LL, 166419LL, 254482LL, 206345LL, 306974LL, 245583LL, + 359978LL, 284127LL, 413486LL, 321968LL, 467488LL, 359100LL, + 571782LL, 438112LL, 677107LL, 515744LL, 783444LL, 591981LL, + 890778LL, 666809LL, 999090LL, 740212LL, 1158168LL, 854773LL, + 1318742LL, 967226LL, 1480786LL, 1077547LL, 1644273LL, 1185717LL, + 1809176LL, 1291713LL, 2025273LL, 1438111LL, 2243284LL, 1581638LL, + 2463174LL, 1722266LL, 2734711LL, 1902563LL, 3008607LL, 2079250LL, + 3284816LL, 2252291LL, 3613097LL, 2464249LL, 3944152LL, 2671838LL, + 4277925LL, 2875016LL, 4664167LL, 3116339LL, 5053569LL, 3352515LL, + 5495872LL, 3626094LL, 5941756LL, 3893776LL, 6440954LL, 4198105LL, + 6944138LL, 4495776LL, 7501027LL, 4829325LL, 8062286LL, 5155441LL, + 8677625LL, 5516656LL, 9297697LL, 5869652LL, 9972201LL, 6256955LL, + 10651782LL, 6635243LL, 11386128LL, 7047035LL, 12125871LL, 7449003LL, + 12920692LL, 7883664LL, 13771017LL, 8350280LL, 14627458LL, 8805512LL, + 15539674LL, 9291864LL, 16508072LL, 9808589LL, 17533047LL, 10354935LL, + 18565182LL, 10887544LL, 19654105LL, 11448906LL, 20800192LL, 12038256LL, + 22003808LL, 12654826LL, 23265308LL, 13297842LL, 24585039LL, 13966524LL, + 25963335LL, 14660086LL, 27400521LL, 15377740LL, 28896912LL, 16118688LL, + 30452812LL, 16882130LL, 32118321LL, 17709858LL, 33844469LL, 18557809LL, + 35631522LL, 19425160LL, 37529539LL, 20353681LL, 39489509LL, 21299288LL, + 41561463LL, 22303734LL, 43746165LL, 23365516LL, 46044363LL, 24483120LL, + 48406978LL, 25612423LL, 50883969LL, 26795140LL, 53476030LL, 28029731LL, + 56183839LL, 29314644LL, 59057854LL, 30690916LL, 62049459LL, 32113721LL, + 65159260LL, 33581470LL, 68387841LL, 35092564LL, 71785573LL, 36687989LL, + 75303747LL, 38322877LL, 78992682LL, 40038189LL, 82803617LL, 41789029LL, + 86786820LL, 43616334LL, 90943284LL, 45517782LL, 95273974LL, 47491034LL, + 99730015LL, 49491139LL, 104411368LL, 51601579LL, 109269658LL, 53776727LL, + 114305726LL, 56014184LL, 119570184LL, 58354139LL, 125014557LL, 60750914LL, + 130689387LL, 63244663LL, 136546125LL, 65789676LL, 142585433LL, 68383478LL, + 148857747LL, 71066179LL, 155314411LL, 73792026LL, 161955980LL, 76558505LL, + 168832780LL, 79405684LL, 175896048LL, 82287776LL, 183196033LL, 85244825LL, + 190733699LL, 88273613LL, 198559772LL, 91413504LL, 206725490LL, 94703190LL, + 215232787LL, 98138087LL, 224083537LL, 101713584LL, 233329359LL, 105467633LL, + 242922753LL, 109352311LL, 252915210LL, 113405509LL, 263259097LL, 117579241LL, + 273955967LL, 121868738LL, 285007307LL, 126269208LL, 296514151LL, 130861028LL, + 308478967LL, 135638044LL, 321003753LL, 140679260LL, 334042117LL, 145934537LL, + 347596818LL, 151396939LL, 361471306LL, 156889099LL, 375715750LL, 162449215LL, + 390380814LL, 168114820LL, 405119201LL, 173582002LL, 421322856LL, 180042297LL, + 436364959LL, 185218587LL, 453864592LL, 192235495LL, 474692324LL, 201784590LL, + 487027329LL, 203683818LL, 543514182LL, 243154512LL, 582683068LL, 266624880LL, + 301558861LL, 15377733LL, 1688292395LL, 1197067573LL, 1419257460LL, 931246785LL, + 1467375848LL, 943141065LL, 1533485973LL, 969632150LL, 1555819320LL, 957492175LL, + 1586617768LL, 952406440LL, 1614118783LL, 944125022LL, 1639127087LL, 933414936LL, + 1665246434LL, 923418051LL, 1689845880LL, 911861645LL, 1714299192LL, 899957960LL, + 1738252671LL, 887410289LL, 1761747194LL, 874267365LL, 1784824257LL, 860577394LL, + 1807276942LL, 846175069LL, 1829095387LL, 831068202LL, 1850220014LL, 815222158LL, + 1870740194LL, 798730888LL, 1890646895LL, 781601992LL, 1910030779LL, 763928397LL, + 1928884092LL, 745716660LL, 1947199151LL, 726973454LL, 1964918545LL, 707662974LL, + 1982083996LL, 687835377LL, 1998638252LL, 667455099LL, 2014623204LL, 646572535LL, + 2030031577LL, 625194953LL, 2044856181LL, 603329731LL, 2059139718LL, 581026958LL, + 2072925531LL, 558336179LL, 2086207792LL, 535263786LL, 2099030555LL, 511858864LL, + 2111338890LL, 488084743LL, 2123176999LL, 463990683LL, 2134539907LL, 439582786LL, + 2145372910LL, 414824641LL, 2147483647LL, 389765766LL, 2147483647LL, 364412517LL, + 2147483647LL, 338728734LL, 2147483647LL, 312764186LL, 2147483647LL, 286482881LL, + 2147483647LL, 259934751LL, 2147483647LL, 233126564LL, 2147483647LL, 206022565LL, + 2147483647LL, 178715522LL, 2147483647LL, 151169181LL, 2147483647LL, 123390608LL, + 2147483647LL, 95386941LL, 2147483647LL, 67207984LL, 2147483647LL, 38817765LL, + 2147483647LL, 10266218LL, 2147483647LL, -18482499LL, 2147483647LL, -47378323LL, + 2147483647LL, -76414377LL, 2147483647LL, -105583727LL, 2147483647LL, -134921981LL, + 2147483647LL, -164378842LL, 2147483647LL, -193947203LL, 2147483647LL, -223619908LL, + 2147483647LL, -253347152LL, 2147483647LL, -283164928LL, 2147483647LL, -313065938LL, + 2147483647LL, -343042836LL, 2147483647LL, -373045632LL, 2147483647LL, -403110142LL, + 2147483647LL, -433186296LL, 2147483647LL, -463267237LL, 2147483647LL, -493388668LL, + 2147483647LL, -523500414LL, 2147483647LL, -553595512LL, 2147483647LL, -583666974LL, + 2147483647LL, -613707779LL, 2147483647LL, -643710884LL, 2147483647LL, -673669220LL, + 2147483647LL, -703575695LL, 2147483647LL, -733423194LL, 2147105689LL, -763204582LL, + 2136689924LL, -792870108LL, 2125789689LL, -822455853LL, 2114405332LL, -851954638LL, + 2102537304LL, -881359267LL, 2090235972LL, -910619937LL, 2077452751LL, -939772681LL, + 2064188408LL, -968810278LL, 2050493624LL, -997682901LL, 2036320132LL, -1026426565LL, + 2021718825LL, -1054991439LL, 2006641647LL, -1083413538LL, 1991139701LL, -1111643033LL, + 1975165146LL, -1139715942LL, 1958769300LL, -1167582445LL, 1941904535LL, -1195278573LL, + 1924622385LL, -1222754519LL, 1906875437LL, -1250046332LL, 1888715442LL, -1277104228LL, + 1870095205LL, -1303964280LL, 1851066692LL, -1330576732LL, 1831582929LL, -1356977688LL, + 1811696099LL, -1383117427LL, 1791409251LL, -1408989496LL, 1770675731LL, -1434630065LL, + 1749548050LL, -1459989480LL, 1728029580LL, -1485061364LL, 1706073993LL, -1509881965LL, + 1683734124LL, -1534401717LL, 1661013670LL, -1558614330LL, 1637866628LL, -1582556150LL, + 1614346157LL, -1606177711LL, 1590456280LL, -1629472830LL, 1566201123LL, -1652435368LL, + 1541584916LL, -1675059228LL, 1516562192LL, -1697380955LL, 1491186643LL, -1719351292LL, + 1465462823LL, -1740964277LL, 1439395388LL, -1762213995LL, 1412989100LL, -1783094588LL, + 1386199017LL, -1803642847LL, 1359079359LL, -1823809768LL, 1331635203LL, -1843589654LL, + 1303871729LL, -1862976864LL, 1275794218LL, -1881965820LL, 1247408052LL, -1900551009LL, + 1218718714LL, -1918726981LL, 1189731787LL, -1936488356LL, 1160452951LL, -1953829819LL, + 1130838183LL, -1970788726LL, 1100942612LL, -1987316656LL, 1070772221LL, -2003408505LL, + 1040333089LL, -2019059247LL, 1009631393LL, -2034263934LL, 978673402LL, -2049017698LL, + 947465480LL, -2063315753LL, 916014085LL, -2077153395LL, 884325765LL, -2090526008LL, + 852407161LL, -2103429061LL, 820265003LL, -2115858114LL, 787906112LL, -2127808815LL, + 755337394LL, -2139276907LL, 722565845LL, -2147483648LL, 689598545LL, -2147483648LL, + 656442658LL, -2147483648LL, 623105435LL, -2147483648LL, 589594205LL, -2147483648LL, + 555916380LL, -2147483648LL, 522079452LL, -2147483648LL, 488090990LL, -2147483648LL, + 453958640LL, -2147483648LL, 419690126LL, -2147483648LL, 385293244LL, -2147483648LL, + 350775861LL, -2147483648LL, 316145919LL, -2147483648LL, 281411427LL, -2147483648LL, + 246580462LL, -2147483648LL, 211661169LL, -2147483648LL, 176661756LL, -2147483648LL, + 141590495LL, -2147483648LL, 106455719LL, -2147483648LL, 71265822LL, -2147483648LL, + 36029253LL, -2147483648LL, 754519LL, -2147483648LL, -34549817LL, -2147483648LL, + -69875144LL, -2147483648LL, -105212798LL, -2147483648LL, -140554065LL, -2147483648LL, + -175890189LL, -2147483648LL, -211212364LL, -2147483648LL, -246511745LL, -2147483648LL, + -281779447LL, -2147483648LL, -317006544LL, -2147483648LL, -352184075LL, -2147483648LL, + -387303046LL, -2147483648LL, -422354431LL, -2147483648LL, -457329171LL, -2147483648LL, + -492218185LL, -2147483648LL, -527012362LL, -2147483648LL, -561702570LL, -2147483648LL, + -596279659LL, -2147483648LL, -630734456LL, -2147483648LL, -665057775LL, -2147483648LL, + -699240418LL, -2144831948LL, -733273172LL, -2133102132LL, -767146820LL, -2120818381LL, + -800852136LL, -2107982187LL, -834379891LL, -2094595196LL, -867720856LL, -2080659207LL, + -900865804LL, -2066176176LL, -933805511LL, -2051148219LL, -966530760LL, -2035577603LL, + -999032343LL, -2019466758LL, -1031301067LL, -2002818269LL, -1063327750LL, -1985634881LL, + -1095103230LL, -1967919499LL, -1126618365LL, -1949675184LL, -1157864034LL, -1930905160LL, + -1188831145LL, -1911612809LL, -1219510631LL, -1891801673LL, -1249893459LL, -1871475456LL, + -1279970629LL, -1850638020LL, -1309733177LL, -1829293390LL, -1339172182LL, -1807445749LL, + -1368278761LL, -1785099442LL, -1397044081LL, -1762258974LL, -1425459354LL, -1738929011LL, + -1453515845LL, -1715114378LL, -1481204873LL, -1690820060LL, -1508517814LL, -1666051202LL, + -1535446103LL, -1640813110LL, -1561981240LL, -1615111244LL, -1588114789LL, -1588951228LL, + -1613838383LL, -1562338842LL, -1639143730LL, -1535280021LL, -1664022608LL, -1507780862LL, + -1688466876LL, -1479847613LL, -1712468472LL, -1451486680LL, -1736019420LL, -1422704626LL, + -1759111828LL, -1393508164LL, -1781737894LL, -1363904161LL, -1803889912LL, -1333899640LL, + -1825560267LL, -1303501770LL, -1846741446LL, -1272717874LL, -1867426035LL, -1241555421LL, + -1887606727LL, -1210022032LL, -1907276322LL, -1178125471LL, -1926427728LL, -1145873649LL, + -1945053969LL, -1113274623LL, -1963148185LL, -1080336589LL, -1980703635LL, -1047067889LL, + -1997713699LL, -1013477001LL, -2014171885LL, -979572542LL, -2030071826LL, -945363268LL, + -2045407288LL, -910858068LL, -2060172170LL, -876065967LL, -2074360507LL, -840996117LL, + -2087966475LL, -805657803LL, -2100984390LL, -770060438LL, -2113408716LL, -734213559LL, + -2125234063LL, -698126829LL, -2136455192LL, -661810030LL, -2147067017LL, -625273066LL, + -2147483648LL, -588525959LL, -2147483648LL, -551578841LL, -2147483648LL, -514441964LL, + -2147483648LL, -477125686LL, -2147483648LL, -439640472LL, -2147483648LL, -401996896LL, + -2147483648LL, -364205633LL, -2147483648LL, -326277459LL, -2147483648LL, -288223247LL, + -2147483648LL, -250053964LL, -2147483648LL, -211780672LL, -2147483648LL, -173414519LL, + -2147483648LL, -134966742LL, -2147483648LL, -96448660LL, -2147483648LL, -57871673LL, + -2147483648LL, -19247258LL, -2147483648LL, 19413035LL, -2147483648LL, 58097582LL, + -2147483648LL, 96794693LL, -2147483648LL, 135492614LL, -2147483648LL, 174179529LL, + -2147483648LL, 212843564LL, -2147483648LL, 251472793LL, -2147483648LL, 290055233LL, + -2147483648LL, 328578862LL, -2147483648LL, 367031608LL, -2147483648LL, 405401361LL, + -2147483648LL, 443675976LL, -2147483648LL, 481843273LL, -2147483648LL, 519891044LL, + -2147483648LL, 557807057LL, -2143491658LL, 595579057LL, -2132294659LL, 633194773LL, + -2120424057LL, 670641922LL, -2107881585LL, 707908207LL, -2094669200LL, 744981332LL, + -2080789087LL, 781848994LL, -2066243658LL, 818498898LL, -2051035554LL, 854918753LL, + -2035167646LL, 891096280LL, -2018643035LL, 927019216LL, -2001465051LL, 962675317LL, + -1983637258LL, 998052364LL, -1965163448LL, 1033138167LL, -1946047650LL, 1067920567LL, + -1926294121LL, 1102387443LL, -1905907353LL, 1136526716LL, -1884892071LL, 1170326352LL, + -1863253233LL, 1203774370LL, -1840996029LL, 1236858842LL, -1818125881LL, 1269567900LL, + -1794648448LL, 1301889739LL, -1770569616LL, 1333812625LL, -1745895507LL, 1365324895LL, + -1720632473LL, 1396414965LL, -1694787098LL, 1427071335LL, -1668366195LL, 1457282587LL, + -1641376810LL, 1487037399LL, -1613826214LL, 1516324546LL, -1585721909LL, 1545132901LL, + -1557071624LL, 1573451443LL, -1527883314LL, 1601269263LL, -1498165157LL, 1628575566LL, + -1467925558LL, 1655359677LL, -1437173142LL, 1681611044LL, -1405916756LL, 1707319246LL, + -1374165466LL, 1732473994LL, -1341928556LL, 1757065139LL, -1309215526LL, 1781082671LL, + -1276036091LL, 1804516733LL, -1242400176LL, 1827357616LL, -1208317919LL, 1849595768LL, + -1173799664LL, 1871221803LL, -1138855963LL, 1892226494LL, -1103497569LL, 1912600789LL, + -1067735439LL, 1932335810LL, -1031580726LL, 1951422859LL, -995044781LL, 1969853421LL, + -958139148LL, 1987619171LL, -920875561LL, 2004711974LL, -883265940LL, 2021123898LL, + -845322394LL, 2036847205LL, -807057209LL, 2051874370LL, -768482852LL, 2066198074LL, + -729611963LL, 2079811213LL, -690457356LL, 2092706903LL, -651032009LL, 2104878482LL, + -611349070LL, 2116319515LL, -571421842LL, 2127023800LL, -531263788LL, 2136985367LL, + -490888525LL, 2146198490LL, -450309816LL, 2147483647LL, -409541571LL, 2147483647LL, + -368597840LL, 2147483647LL, -327492809LL, 2147483647LL, -286240798LL, 2147483647LL, + -244856251LL, 2147483647LL, -203353740LL, 2147483647LL, -161747950LL, 2147483647LL, + -120053683LL, 2147483647LL, -78285850LL, 2147483647LL, -36459463LL, 2147483647LL, + 5410364LL, 2147483647LL, 47308424LL, 2147483647LL, 89219424LL, 2147483647LL, + 131127985LL, 2147483647LL, 173018649LL, 2147483647LL, 214875890LL, 2147483647LL, + 256684110LL, 2147483647LL, 298427653LL, 2147483647LL, 340090806LL, 2147483647LL, + 381657806LL, 2147483647LL, 423112846LL, 2147483647LL, 464440081LL, 2142219254LL, + 505623633LL, 2132435162LL, 546647598LL, 2121847243LL, 587496052LL, 2110457141LL, + 628153057LL, 2098266812LL, 668602667LL, 2085278532LL, 708828935LL, 2071494897LL, + 748815918LL, 2056918826LL, 788547685LL, 2041553557LL, 828008323LL, 2025402656LL, + 867181942LL, 2008470011LL, 906052684LL, 1990759835LL, 944604728LL, 1972276668LL, + 982822297LL, 1953025376LL, 1020689664LL, 1933011150LL, 1058191163LL, 1912239510LL, + 1095311187LL, 1890716305LL, 1132034205LL, 1868447707LL, 1168344762LL, 1845440218LL, + 1204227487LL, 1821700666LL, 1239667102LL, 1797236205LL, 1274648428LL, 1772054317LL, + 1309156391LL, 1746162807LL, 1343176030LL, 1719569805LL, 1376692504LL, 1692283764LL, + 1409691100LL, 1664313458LL, 1442157234LL, 1635667984LL, 1474076470LL, 1606356759LL, + 1505434513LL, 1576389513LL, 1536217228LL, 1545776297LL, 1566410640LL, 1514527474LL, + 1596000941LL, 1482653719LL, 1624974503LL, 1450166017LL, 1653317877LL, 1417075660LL, + 1681017808LL, 1383394247LL, 1708061236LL, 1349133677LL, 1734435304LL, 1314306148LL, + 1760127367LL, 1278924156LL, 1785124999LL, 1243000490LL, 1809415996LL, 1206548227LL, + 1832988389LL, 1169580734LL, 1855830445LL, 1132111656LL, 1877930676LL, 1094154921LL, + 1899277848LL, 1055724730LL, 1919860983LL, 1016835556LL, 1939669371LL, 977502137LL, + 1958692571LL, 937739473LL, 1976920422LL, 897562824LL, 1994343046LL, 856987699LL, + 2010950859LL, 816029859LL, 2026734572LL, 774705305LL, 2041685198LL, 733030277LL, + 2055794064LL, 691021244LL, 2069052808LL, 648694906LL, 2081453395LL, 606068180LL, + 2092988114LL, 563158201LL, 2103649588LL, 519982311LL, 2113430779LL, 476558055LL, + 2122324994LL, 432903175LL, 2130325891LL, 389035604LL, 2137427475LL, 344973456LL, + 2143624138LL, 300735023LL, 2147483647LL, 256338768LL, 2147483647LL, 211803314LL, + 2147483647LL, 167147441LL, 2147483647LL, 122390077LL, 2147483647LL, 77550290LL, + 2147483647LL, 32647284LL, 2147483647LL, -12299615LL, 2147483647LL, -57270964LL, + 2147483647LL, -102247208LL, 2147483647LL, -147208690LL, 2147483647LL, -192135663LL, + 2145864842LL, -237008295LL, 2139958256LL, -281806675LL, 2133108471LL, -326510826LL, + 2125315797LL, -371100712LL, 2116581018LL, -415556248LL, 2106905292LL, -459857306LL, + 2096290240LL, -503983728LL, 2084737906LL, -547915329LL, 2072250771LL, -591631916LL, + 2058831754LL, -635113287LL, 2044484214LL, -678339247LL, 2029211952LL, -721289615LL, + 2013019210LL, -763944235LL, 1995910675LL, -806282984LL, 1977891479LL, -848285782LL, + 1958967201LL, -889932603LL, 1939143864LL, -931203483LL, 1918427940LL, -972078534LL, + 1896826347LL, -1012537949LL, 1874346448LL, -1052562013LL, 1850996056LL, -1092131117LL, + 1826783427LL, -1131225763LL, 1801717264LL, -1169826578LL, 1775806713LL, -1207914322LL, + 1749061365LL, -1245469901LL, 1721491250LL, -1282474371LL, 1693106840LL, -1318908956LL, + 1663919046LL, -1354755054LL, 1633939211LL, -1389994248LL, 1603179117LL, -1424608316LL, + 1571650972LL, -1458579242LL, 1539367415LL, -1491889227LL, 1506341510LL, -1524520696LL, + 1472586741LL, -1556456312LL, 1438117011LL, -1587678986LL, 1402946638LL, -1618171884LL, + 1367090349LL, -1647918439LL, 1330563276LL, -1676902363LL, 1293380956LL, -1705107654LL, + 1255559318LL, -1732518608LL, 1217114685LL, -1759119828LL, 1178063765LL, -1784896235LL, + 1138423646LL, -1809833076LL, 1098211792LL, -1833915936LL, 1057446035LL, -1857130745LL, + 1016144569LL, -1879463791LL, 974325943LL, -1900901727LL, 932009055LL, -1921431579LL, + 889213146LL, -1941040761LL, 845957791LL, -1959717077LL, 802262891LL, -1977448735LL, + 758148666LL, -1994224354LL, 713635648LL, -2010032974LL, 668744673LL, -2024864063LL, + 623496867LL, -2038707525LL, 577913646LL, -2051553712LL, 532016701LL, -2063393429LL, + 485827990LL, -2074217943LL, 439369729LL, -2084018989LL, 392664381LL, -2092788781LL, + 345734651LL, -2100520018LL, 298603468LL, -2107205889LL, 251293982LL, -2112840086LL, + 203829548LL, -2117416802LL, 156233720LL, -2120930748LL, 108530236LL, -2123377151LL, + 60743008LL, -2124751763LL, 12896114LL, -2125050870LL, -34986219LL, -2124271294LL, + -82879623LL, -2122410400LL, -130759604LL, -2119466100LL, -178601550LL, -2115436861LL, + -226380745LL, -2110321707LL, -274072384LL, -2104120225LL, -321651583LL, -2096832568LL, + -369093392LL, -2088459460LL, -416372807LL, -2079002201LL, -463464787LL, -2068462665LL, + -510344262LL, -2056843312LL, -556986151LL, -2044147183LL, -603365373LL, -2030377906LL, + -649456861LL, -2015539697LL, -695235574LL, -1999637364LL, -740676516LL, -1982676305LL, + -785754744LL, -1964662515LL, -830445387LL, -1945602580LL, -874723656LL, -1925503682LL, + -918564862LL, -1904373602LL, -961944426LL, -1882220711LL, -1004837898LL, -1859053978LL, + -1047220968LL, -1834882966LL, -1089069484LL, -1809717832LL, -1130359461LL, -1783569324LL, + -1171067101LL, -1756448780LL, -1211168807LL, -1728368127LL, -1250641192LL, -1699339878LL, + -1289461102LL, -1669377127LL, -1327605625LL, -1638493550LL, -1365052106LL, -1606703397LL, + -1401778164LL, -1574021491LL, -1437761706LL, -1540463223LL, -1472980940LL, -1506044549LL, + -1507414391LL, -1470781980LL, -1541040915LL, -1434692582LL, -1573839712LL, -1397793966LL, + -1605790344LL, -1360104288LL, -1636872746LL, -1321642233LL, -1667067242LL, -1282427018LL, + -1696354557LL, -1242478378LL, -1724715835LL, -1201816561LL, -1752132646LL, -1160462319LL, + -1778587009LL, -1118436901LL, -1804061397LL, -1075762043LL, -1828538756LL, -1032459960LL, + -1852002515LL, -988553334LL, -1874436602LL, -944065307LL, -1895825454LL, -899019470LL, + -1916154033LL, -853439849LL, -1935407835LL, -807350901LL, -1953572906LL, -760777496LL, + -1970635850LL, -713744909LL, -1986583847LL, -666278805LL, -2001404658LL, -618405231LL, + -2015086640LL, -570150598LL, -2027618758LL, -521541674LL, -2038990592LL, -472605564LL, + -2049192353LL, -423369699LL, -2058214888LL, -373861826LL, -2066049695LL, -324109986LL, + -2072688929LL, -274142505LL, -2078125412LL, -223987977LL, -2082352645LL, -173675248LL, + -2085364813LL, -123233400LL, -2087156796LL, -72691739LL, -2087724175LL, -22079775LL, + -2087063243LL, 28572797LL, -2085171007LL, 79236107LL, -2082045200LL, 129880130LL, + -2077684287LL, 180474706LL, -2072087467LL, 230989556LL, -2065254684LL, 281394296LL, + -2057186628LL, 331658461LL, -2047884744LL, 381751518LL, -2037351232LL, 431642889LL, + -2025589054LL, 481301967LL, -2012601938LL, 530698135LL, -1998394380LL, 579800785LL, + -1982971645LL, 628579337LL, -1966339772LL, 677003263LL, -1948505575LL, 725042096LL, + -1929476644LL, 772665462LL, -1909261345LL, 819843089LL, -1887868820LL, 866544835LL, + -1865308989LL, 912740704LL, -1841592548LL, 958400866LL, -1816730967LL, 1003495678LL, + -1790736489LL, 1047995705LL, -1763622126LL, 1091871739LL, -1735401661LL, 1135094818LL, + -1706089638LL, 1177636251LL, -1675701362LL, 1219467633LL, -1644252896LL, 1260560870LL, + -1611761052LL, 1300888195LL, -1578243387LL, 1340422189LL, -1543718200LL, 1379135807LL, + -1508204519LL, 1417002391LL, -1471722102LL, 1453995691LL, -1434291420LL, 1490089892LL, + -1395933657LL, 1525259623LL, -1356670697LL, 1559479987LL, -1316525115LL, 1592726574LL, + -1275520167LL, 1624975483LL, -1233679780LL, 1656203344LL, -1191028542LL, 1686387331LL, + -1147591689LL, 1715505185LL, -1103395093LL, 1743535236LL, -1058465249LL, 1770456411LL, + -1012829262LL, 1796248266LL, -966514835LL, 1820890992LL, -919550252LL, 1844365441LL, + -871964366LL, 1866653137LL, -823786580LL, 1887736300LL, -775046835LL, 1907597859LL, + -725775590LL, 1926221469LL, -676003808LL, 1943591527LL, -625762938LL, 1959693190LL, + -575084896LL, 1974512385LL, -524002047LL, 1988035828LL, -472547186LL, 2000251046LL, + -420753520LL, 2011146354LL, -368654646LL, 2020710975LL, -316284533LL, 2028934840LL, + -263677499LL, 2035808859LL, -210868192LL, 2041324939LL, -157891565LL, 2045474858LL, + -104782860LL, 2048253636LL, -51577580LL, 2049658843LL, 1688534LL, 2049655780LL, + 54979520LL, 2048310531LL, 108259226LL, 2045550461LL, 161491329LL, 2041403742LL, + 214639360LL, 2035866305LL, 267666733LL, 2028936689LL, 320536762LL, 2020616743LL, + 373212694LL, 2010908275LL, 425657729LL, 1999814200LL, 477835048LL, 1987338529LL, + 529707840LL, 1973486123LL, 581239326LL, 1958262907LL, 632392787LL, 1941675770LL, + 683131591LL, 1923732596LL, 733419216LL, 1904442268LL, 783219284LL, 1883814659LL, + 832495582LL, 1861860637LL, 881212092LL, 1838592064LL, 929333017LL, 1814021796LL, + 976822810LL, 1788163677LL, 1023646202LL, 1761032541LL, 1069768227LL, 1732644203LL, + 1115154252LL, 1703015459LL, 1159770004LL, 1672164073LL, 1203581595LL, 1640108783LL, + 1246555555LL, 1606869282LL, 1288658856LL, 1572466218LL, 1329858938LL, 1536921182LL, + 1370123741LL, 1500256700LL, 1409421726LL, 1462496224LL, 1447721910LL, 1423664119LL, + 1484993884LL, 1383785653LL, 1521207848LL, 1342886983LL, 1556334631LL, 1300995143LL, + 1590345723LL, 1258138030LL, 1623213293LL, 1214344388LL, 1654910226LL, 1169643794LL, + 1685410136LL, 1124066641LL, 1714687402LL, 1077644120LL, 1742717185LL, 1030408201LL, + 1769475457LL, 982391622LL, 1794939022LL, 933627855LL, 1819085540LL, 884151103LL, + 1841893553LL, 833996264LL, 1863342504LL, 783198919LL, 1883412760LL, 731795305LL, + 1902085636LL, 679822294LL, 1919343411LL, 627317369LL, 1935169354LL, 574318594LL, + 1949547740LL, 520864601LL, 1962463871LL, 466994550LL, 1973904096LL, 412748113LL, + 1983855824LL, 358165439LL, 1992307546LL, 303287134LL, 1999248852LL, 248154224LL, + 2004670441LL, 192808135LL, 2008564144LL, 137290654LL, 2010922932LL, 81643906LL, + 2011740933LL, 25910320LL, 2011013443LL, -29867402LL, 2008736940LL, -85646317LL, + 2004909093LL, -141383271LL, 1999528773LL, -197034937LL, 1992596062LL, -252557842LL, + 1984112262LL, -307908404LL, 1974079905LL, -363042967LL, 1962502753LL, -417917832LL, + 1949385810LL, -472489295LL, 1934735324LL, -526713682LL, 1918558790LL, -580547380LL, + 1900864956LL, -633946879LL, 1881663821LL, -686868803LL, 1860966637LL, -739269949LL, + 1838785909LL, -791107321LL, 1815135395LL, -842338168LL, 1790030099LL, -892920022LL, + 1763486274LL, -942810730LL, 1735521412LL, -991968497LL, 1706154241LL, -1040351917LL, + 1675404716LL, -1087920013LL, 1643294015LL, -1134632275LL, 1609844526LL, -1180448693LL, + 1575079841LL, -1225329796LL, 1539024741LL, -1269236689LL, 1501705185LL, -1312131088LL, + 1463148297LL, -1353975356LL, 1423382354LL, -1394732542LL, 1382436764LL, -1434366412LL, + 1340342057LL, -1472841489LL, 1297129860LL, -1510123084LL, 1252832885LL, -1546177336LL, + 1207484901LL, -1580971239LL, 1161120720LL, -1614472684LL, 1113776173LL, -1646650486LL, + 1065488084LL, -1677474422LL, 1016294246LL, -1706915258LL, 966233400LL, -1734944789LL, + 915345202LL, -1761535861LL, 863670203LL, -1786662407LL, 811249811LL, -1810299477LL, + 758126270LL, -1832423264LL, 704342625LL, -1853011140LL, 649942692LL, -1872041673LL, + 594971024LL, -1889494663LL, 539472877LL, -1905351163LL, 483494178LL, -1919593508LL, + 427081490LL, -1932205334LL, 370281972LL, -1943171610LL, 313143344LL, -1952478651LL, + 255713849LL, -1960114145LL, 198042217LL, -1966067174LL, 140177618LL, -1970328227LL, + 82169631LL, -1972889229LL, 24068195LL, -1973743548LL, -34076427LL, -1972886015LL, + -92213695LL, -1970312940LL, -150292832LL, -1966022123LL, -208262869LL, -1960012871LL, + -266072688LL, -1952286003LL, -323671068LL, -1942843863LL, -381006732LL, -1931690329LL, + -438028388LL, -1918830819LL, -494684779LL, -1904272300LL, -550924731LL, -1888023286LL, + -606697194LL, -1870093847LL, -661951295LL, -1850495608LL, -716636382LL, -1829241753LL, + -770702075LL, -1806347016LL, -824098311LL, -1781827688LL, -876775393LL, -1755701604LL, + -928684039LL, -1727988143LL, -979775430LL, -1698708222LL, -1030001256LL, -1667884282LL, + -1079313769LL, -1635540281LL, -1127665824LL, -1601701683LL, -1175010937LL, -1566395445LL, + -1221303321LL, -1529649999LL, -1266497944LL, -1491495241LL, -1310550571LL, -1451962508LL, + -1353417809LL, -1411084563LL, -1395057161LL, -1368895571LL, -1435427063LL, -1325431079LL, + -1474486939LL, -1280727991LL, -1512197238LL, -1234824542LL, -1548519484LL, -1187760274LL, + -1583416316LL, -1139576002LL, -1616851536LL, -1090313791LL, -1648790148LL, -1040016919LL, + -1679198399LL, -988729848LL, -1708043824LL, -936498186LL, -1735295282LL, -883368655LL, + -1760922999LL, -829389052LL, -1784898602LL, -774608209LL, -1807195158LL, -719075956LL, + -1827787211LL, -662843080LL, -1846650818LL, -605961279LL, -1863763578LL, -548483119LL, + -1879104668LL, -490461992LL, -1892654875LL, -431952068LL, -1904396625LL, -373008246LL, + -1914314009LL, -313686105LL, -1922392815LL, -254041859LL, -1928620550LL, -194132300LL, + -1932986466LL, -134014749LL, -1935481582LL, -73747004LL, -1936098706LL, -13387283LL, + -1934832454LL, 47005826LL, -1931679267LL, 107373427LL, -1926637430LL, 167656367LL, + -1919707083LL, 227795296LL, -1910890236LL, 287730726LL, -1900190781LL, 347403087LL, + -1887614496LL, 406752786LL, -1873169061LL, 465720272LL, -1856864053LL, 524246090LL, + -1838710958LL, 582270945LL, -1818723170LL, 639735763LL, -1796915987LL, 696581755LL, + -1773306614LL, 752750472LL, -1747914156LL, 808183874LL, -1720759611LL, 862824388LL, + -1691865865LL, 916614973LL, -1661257677LL, 969499181LL, -1628961669LL, 1021421218LL, + -1595006312LL, 1072326007LL, -1559421908LL, 1122159252LL, -1522240572LL, 1170867496LL, + -1483496211LL, 1218398185LL, -1443224502LL, 1264699727LL, -1401462865LL, 1309721557LL, + -1358250438LL, 1353414188LL, -1313628048LL, 1395729281LL, -1267638178LL, 1436619694LL, + -1220324935LL, 1476039548LL, -1171734016LL, 1513944278LL, -1121912667LL, 1550290693LL, + -1070909648LL, 1585037028LL, -1018775189LL, 1618143002LL, -965560948LL, 1649569869LL, + -911319966LL, 1679280468LL, -856106618LL, 1707239277LL, -799976567LL, 1733412462LL, + -742986711LL, 1757767923LL, -685195132LL, 1780275340LL, -626661040LL, 1800906221LL, + -567444716LL, 1819633944LL, -507607460LL, 1836433799LL, -447211524LL, 1851283025LL, + -386320056LL, 1864160854LL, -324997036LL, 1875048542LL, -263307210LL, 1883929406LL, + -201316029LL, 1890788856LL, -139089579LL, 1895614427LL, -76694511LL, 1898395805LL, + -14197977LL, 1899124852LL, 48332445LL, 1897795636LL, 110828821LL, 1894404446LL, + 173222936LL, 1888949817LL, 235446363LL, 1881432541LL, 297430543LL, 1871855689LL, + 359106857LL, 1860224617LL, 420406703LL, 1846546980LL, 481261574LL, 1830832736LL, + 541603136LL, 1813094155LL, 601363301LL, 1793345817LL, 660474314LL, 1771604612LL, + 718868824LL, 1747889739LL, 776479967LL, 1722222702LL, 833241444LL, 1694627293LL, + 889087600LL, 1665129592LL, 943953507LL, 1633757944LL, 997775035LL, 1600542948LL, + 1050488941LL, 1565517433LL, 1102032937LL, 1528716441LL, 1152345777LL, 1490177197LL, + 1201367331LL, 1449939084LL, 1249038663LL, 1408043611LL, 1295302104LL, 1364534382LL, + 1340101332LL, 1319457058LL, 1383381447LL, 1272859317LL, 1425089039LL, 1224790815LL, + 1465172266LL, 1175303140LL, 1503580927LL, 1124449767LL, 1540266522LL, 1072286005LL, + 1575182333LL, 1018868949LL, 1608283485LL, 964257419LL, 1639527009LL, 908511911LL, + 1668871914LL, 851694528LL, 1696279242LL, 793868926LL, 1721712131LL, 735100241LL, + 1745135871LL, 675455029LL, 1766517968LL, 615001191LL, 1785828185LL, 553807905LL, + 1803038606LL, 491945549LL, 1818123678LL, 429485626LL, 1831060263LL, 366500687LL, + 1841827677LL, 303064250LL, 1850407738LL, 239250716LL, 1856784798LL, 175135287LL, + 1860945788LL, 110793881LL, 1862880243LL, 46303042LL, 1862580340LL, -18260146LL, + 1860040920LL, -82818151LL, 1855259519LL, -147293085LL, 1848236380LL, -211606797LL, + 1838974482LL, -275680965LL, 1827479547LL, -339437196LL, 1813760057LL, -402797116LL, + 1797827260LL, -465682472LL, 1779695174LL, -528015230LL, 1759380593LL, -589717667LL, + 1736903078LL, -650712478LL, 1712284962LL, -710922872LL, 1685551330LL, -770272670LL, + 1656730013LL, -828686405LL, 1625851572LL, -886089424LL, 1592949275LL, -942407987LL, + 1558059075LL, -997569365LL, 1521219587LL, -1051501936LL, 1482472048LL, -1104135292LL, + 1441860295LL, -1155400327LL, 1399430717LL, -1205229340LL, 1355232215LL, -1253556128LL, + 1309316164LL, -1300316084LL, 1261736355LL, -1345446286LL, 1212548947LL, -1388885595LL, + 1161812413LL, -1430574738LL, 1109587475LL, -1470456408LL, 1055937047LL, -1508475341LL, + 1000926163LL, -1544578406LL, 944621912LL, -1578714693LL, 887093362LL, -1610835584LL, + 828411484LL, -1640894842LL, 768649076LL, -1668848684LL, 707880672LL, -1694655852LL, + 646182464LL, -1718277689LL, 583632212LL, -1739678206LL, 520309149LL, -1758824147LL, + 456293888LL, -1775685054LL, 391668328LL, -1790233321LL, 326515549LL, -1802444258LL, + 260919713LL, -1812296137LL, 194965959LL, -1819770245LL, 128740295LL, -1824850928LL, + 62329492LL, -1827525633LL, -4179032LL, -1827784948LL, -70697320LL, -1825622633LL, + -137136995LL, -1821035654LL, -203409373LL, -1814024203LL, -269425581LL, -1804591728LL, + -335096679LL, -1792744944LL, -400333778LL, -1778493848LL, -465048160LL, -1761851731LL, + -529151403LL, -1742835177LL, -592555503LL, -1721464069LL, -655172996LL, -1697761578LL, + -716917083LL, -1671754158LL, -777701753LL, -1643471534LL, -837441909LL, -1612946675LL, + -896053489LL, -1580215781LL, -953453590LL, -1545318246LL, -1009560594LL, -1508296634LL, + -1064294288LL, -1469196633LL, -1117575983LL, -1428067018LL, -1169328638LL, -1384959603LL, + -1219476978LL, -1339929188LL, -1267947612LL, -1293033505LL, -1314669147LL, -1244333154LL, + -1359572305LL, -1193891539LL, -1402590032LL, -1141774798LL, -1443657611LL, -1088051727LL, + -1482712770LL, -1032793701LL, -1519695784LL, -976074591LL, -1554549582LL, -917970675LL, + -1587219842LL, -858560547LL, -1617655092LL, -797925018LL, -1645806796LL, -736147016LL, + -1671629451LL, -673311485LL, -1695080676LL, -609505270LL, -1716121264LL, -544817012LL, + -1734715353LL, -479337026LL, -1750830314LL, -413157185LL, -1764437044LL, -346370796LL, + -1775510045LL, -279072473LL, -1784026474LL, -211358013LL, -1789969164LL, -143324257LL, + -1793326057LL, -75068960LL, -1794059572LL, -6690651LL, -1792223825LL, 61711502LL, + -1787753717LL, 130037840LL, -1780675917LL, 198188353LL, -1770991703LL, 266062826LL, + -1758707667LL, 333560989LL, -1743836341LL, 400582660LL, -1726393250LL, 467027903LL, + -1706397919LL, 532797170LL, -1683873864LL, 597791461LL, -1658848354LL, 661912471LL, + -1631352586LL, 725062742LL, -1601421573LL, 787145821LL, -1569094145LL, 848066406LL, + -1534412916LL, 907730505LL, -1497424235LL, 966045578LL, -1458178153LL, 1022920699LL, + -1416728364LL, 1078266697LL, -1373132151LL, 1131996305LL, -1327450323LL, 1184024312LL, + -1279747148LL, 1234267702LL, -1230090273LL, 1282645798LL, -1178550646LL, 1329080403LL, + -1125202426LL, 1373495939LL, -1070122895LL, 1415819579LL, -1013392358LL, 1455981378LL, + -955094034LL, 1493914406LL, -895313954LL, 1529554867LL, -834140840LL, 1562842225LL, + -771665989LL, 1593719316LL, -707983144LL, 1622132466LL, -643188365LL, 1648031595LL, + -577379896LL, 1671370322LL, -510658018LL, 1692106061LL, -443124913LL, 1710200118LL, + -374884511LL, 1725617777LL, -306042334LL, 1738328382LL, -236705344LL, 1748305414LL, + -166981781LL, 1755526561LL, -96980997LL, 1759973781LL, -26813290LL, 1761633365LL, + 43410268LL, 1760495982LL, 113578001LL, 1756556728LL, 183577810LL, 1749815165LL, + 253297346LL, 1740275347LL, 322624194LL, 1727945849LL, 391446053LL, 1712839784LL, + 459650920LL, 1694974807LL, 527127274LL, 1674373125LL, 593764262LL, 1651061485LL, + 659451885LL, 1625071167LL, 724081183LL, 1596437957LL, 787544424LL, 1565202126LL, + 849735287LL, 1531408388LL, 910549048LL, 1495105861LL, 969882763LL, 1456348015LL, + 1027635455LL, 1415192610LL, 1083708291LL, 1371701631LL, 1138004761LL, 1325941217LL, + 1190430860LL, 1277981573LL, 1240895254LL, 1227896883LL, 1289309460LL, 1175765216LL, + 1335588009LL, 1121668415LL, 1379648612LL, 1065691989LL, 1421412317LL, 1007924994LL, + 1460803673LL, 948459905LL, 1497750874LL, 887392482LL, 1532185910LL, 824821632LL, + 1564044706LL, 760849261LL, 1593267262LL, 695580119LL, 1619797780LL, 629121645LL, + 1643584787LL, 561583794LL, 1664581258LL, 493078874LL, 1682744723LL, 423721360LL, + 1698037372LL, 353627718LL, 1710426153LL, 282916215LL, 1719882862LL, 211706726LL, + 1726384225LL, 140120536LL, 1729911967LL, 68280143LL, 1730452887LL, -3690955LL, + 1727998909LL, -75668460LL, 1722547133LL, -147527492LL, 1714099875LL, -219142804LL, + 1702664700LL, -290388998LL, 1688254443LL, -361140744LL, 1670887220LL, -431273005LL, + 1650586437LL, -500661258LL, 1627380781LL, -569181718LL, 1601304207LL, -636711566LL, + 1572395910LL, -703129173LL, 1540700294LL, -768314321LL, 1506266928LL, -832148437LL, + 1469150489LL, -894514808LL, 1429410703LL, -955298807LL, 1387112269LL, -1014388115LL, + 1342324775LL, -1071672938LL, 1295122610LL, -1127046222LL, 1245584856LL, -1180403867LL, + 1193795181LL, -1231644938LL, 1139841715LL, -1280671865LL, 1083816921LL, -1327390651LL, + 1025817456LL, -1371711062LL, 965944019LL, -1413546821LL, 904301197LL, -1452815796LL, + 840997300LL, -1489440173LL, 776144181LL, -1523346634LL, 709857057LL, -1554466523LL, + 642254321LL, -1582736003LL, 573457338LL, -1608096207LL, 503590242LL, -1630493384LL, + 432779726LL, -1649879034LL, 361154816LL, -1666210030LL, 288846654LL, -1679448741LL, + 215988258LL, -1689563136LL, 142714288LL, -1696526887LL, 69160804LL, -1700319452LL, + -4534984LL, -1700926156LL, -78234964LL, -1698338260LL, -151800382LL, -1692553016LL, + -225092102LL, -1683573714LL, -297970866LL, -1671409714LL, -370297557LL, -1656076477LL, + -441933476LL, -1637595568LL, -512740598LL, -1615994661LL, -582581852LL, -1591307527LL, + -651321391LL, -1563574010LL, -718824853LL, -1532839992LL, -784959645LL, -1499157344LL, + -849595202LL, -1462583865LL, -912603261LL, -1423183216LL, -973858122LL, -1381024829LL, + -1033236914LL, -1336183814LL, -1090619853LL, -1288740849LL, -1145890499LL, -1238782062LL, + -1198936009LL, -1186398899LL, -1249647380LL, -1131687977LL, -1297919694LL, -1074750929LL, + -1343652351LL, -1015694241LL, -1386749300LL, -954629068LL, -1427119260LL, -891671052LL, + -1464675934LL, -826940115LL, -1499338216LL, -760560252LL, -1531030386LL, -692659314LL, + -1559682302LL, -623368770LL, -1585229580LL, -552823476LL, -1607613755LL, -481161420LL, + -1626782451LL, -408523471LL, -1642689516LL, -335053105LL, -1655295170LL, -260896143LL, + -1664566120LL, -186200460LL, -1670475674LL, -111115705LL, -1673003847LL, -35793008LL, + -1672137437LL, 39615327LL, -1667870108LL, 114956114LL, -1660202442LL, 190075605LL, + -1649141991LL, 264819796LL, -1634703306LL, 339034742LL, -1616907952LL, 412566883LL, + -1595784520LL, 485263357LL, -1571368605LL, 556972325LL, -1543702785LL, 627543295LL, + -1512836581LL, 696827444LL, -1478826398LL, 764677941LL, -1441735455LL, 830950267LL, + -1401633698LL, 895502534LL, -1358597699LL, 958195805LL, -1312710541LL, 1018894402LL, + -1264061687LL, 1077466218LL, -1212746829LL, 1133783020LL, -1158867735LL, 1187720750LL, + -1102532068LL, 1239159811LL, -1043853199LL, 1287985362LL, -982950007LL, 1334087586LL, + -919946654LL, 1377361966LL, -854972362LL, 1417709544LL, -788161166LL, 1455037168LL, + -719651660LL, 1489257739LL, -649586726LL, 1520290433LL, -578113257LL, 1548060926LL, + -505381863LL, 1572501593LL, -431546572LL, 1593551706LL, -356764516LL, 1611157610LL, + -281195606LL, 1625272890LL, -205002207LL, 1635858521LL, -128348795LL, 1642883006LL, + -51401610LL, 1646322493LL, 25671698LL, 1646160884LL, 102702428LL, 1642389920LL, + 179521195LL, 1635009254LL, 255958304LL, 1624026507LL, 331844118LL, 1609457302LL, + 407009445LL, 1591325289LL, 481285909LL, 1569662143LL, 554506341LL, 1544507548LL, + 626505157LL, 1515909164LL, 697118742LL, 1483922576LL, 766185833LL, 1448611219LL, + 833547896LL, 1410046292LL, 899049506LL, 1368306646LL, 962538722LL, 1323478663LL, + 1023867449LL, 1275656106LL, 1082891809LL, 1224939960LL, 1139472494LL, 1171438248LL, + 1193475119LL, 1115265832LL, 1244770557LL, 1056544201LL, 1293235279LL, 995401229LL, + 1338751673LL, 931970934LL, 1381208355LL, 866393204LL, 1420500471LL, 798813515LL, + 1456529983LL, 729382633LL, 1489205945LL, 658256302LL, 1518444759LL, 585594911LL, + 1544170427LL, 511563155LL, 1566314774LL, 436329680LL, 1584817663LL, 360066713LL, + 1599627196LL, 282949681LL, 1610699883LL, 205156824LL, 1618000812LL, 126868793LL, + 1621503781LL, 48268236LL, 1621191428LL, -30460618LL, 1617055327LL, -109132383LL, + 1609096070LL, -187560955LL, 1597323329LL, -265559946LL, 1581755892LL, -342943129LL, + 1562421687LL, -419524886LL, 1539357768LL, -495120654LL, 1512610295LL, -569547381LL, + 1482234484LL, -642623975LL, 1448294533LL, -714171752LL, 1410863530LL, -784014891LL, + 1370023338LL, -851980875LL, 1325864453LL, -917900937LL, 1278485843LL, -981610493LL, + 1227994767LL, -1042949576LL, 1174506564LL, -1101763257LL, 1118144433LL, -1157902059LL, + 1059039175LL, -1211222366LL, 997328931LL, -1261586809LL, 933158886LL, -1308864658LL, + 866680960LL, -1352932182LL, 798053476LL, -1393673008LL, 727440811LL, -1430978461LL, + 655013029LL, -1464747887LL, 580945494LL, -1494888955LL, 505418469LL, -1521317953LL, + 428616696LL, -1543960050LL, 350728964LL, -1562749548LL, 271947658LL, -1577630107LL, + 192468304LL, -1588554958LL, 112489089LL, -1595487080LL, 32210384LL, -1598399361LL, + -48165757LL, -1597274741LL, -128436095LL, -1592106317LL, -208396718LL, -1582897435LL, + -287843560LL, -1569661749LL, -366572919LL, -1552423258LL, -444381986LL, -1531216316LL, + -521069372LL, -1506085611LL, -596435635LL, -1477086125LL, -670283816LL, -1444283060LL, + -742419956LL, -1407751739LL, -812653630LL, -1367577480LL, -880798461LL, -1323855444LL, + -946672637LL, -1276690452LL, -1010099414LL, -1226196778LL, -1070907619LL, -1172497916LL, + -1128932133LL, -1115726316LL, -1184014369LL, -1056023099LL, -1236002736LL, -993537745LL, + -1284753086LL, -928427753LL, -1330129146LL, -860858281LL, -1372002935LL, -791001757LL, + -1410255166LL, -719037474LL, -1444775603LL, -645151157LL, -1475463477LL, -569534512LL, + -1502227702LL, -492384749LL, -1524987327LL, -413904099LL, -1543671834LL, -334299297LL, + -1558220750LL, -253781059LL, -1568585780LL, -172563538LL, -1574730619LL, -90863771LL, + -1576611510LL, -8901107LL, -1574252330LL, 73103373LL, -1567609814LL, 154927446LL, + -1556708541LL, 236348347LL, -1541566056LL, 317143374LL, -1522212522LL, 397090502LL, + -1498691104LL, 475968995LL, -1471056043LL, 553560025LL, -1439373226LL, 629647288LL, + -1403720077LL, 704017623LL, -1364185282LL, 776461622LL, -1320868734LL, 846774239LL, + -1273881277LL, 914755391LL, -1223344489LL, 980210552LL, -1169390412LL, 1042951333LL, + -1112161255LL, 1102796056LL, -1051809062LL, 1159570309LL, -988495352LL, 1213107485LL, + -922390732LL, 1263249312LL, -853674471LL, 1309846353LL, -782534056LL, 1352758490LL, + -709164713LL, 1391855393LL, -633768905LL, 1427016949LL, -556555803LL, 1458133685LL, + -477740736LL, 1485107145LL, -397544612LL, 1507850257LL, -316193327LL, 1526287653LL, + -233917145LL, 1540355976LL, -150950064LL, 1550004134LL, -67529167LL, 1555193545LL, + 16106047LL, 1555898324LL, 99714340LL, 1552105452LL, 183053425LL, 1543814902LL, + 265880668LL, 1531039725LL, 347953795LL, 1513806105LL, 429031600LL, 1492153373LL, + 508874668LL, 1466133981LL, 587246086LL, 1435813437LL, 663912163LL, 1401270202LL, + 738643142LL, 1362595552LL, 811213906LL, 1319893388LL, 881404682LL, 1273280019LL, + 949001729LL, 1222883903LL, 1013798019LL, 1168845343LL, 1075593903LL, 1111316153LL, + 1134197755LL, 1050459282LL, 1189426608LL, 986448397LL, 1241106765LL, 919467443LL, + 1289074381LL, 849710150LL, 1333176031LL, 777379522LL, 1373269246LL, 702687282LL, + 1409223019LL, 625853290LL, 1440918284LL, 547104932LL, 1468248363LL, 466676477LL, + 1491119375LL, 384808409LL, 1509450612LL, 301746734LL, 1523174881LL, 217742261LL, + 1532238800LL, 133049867LL, 1536603059LL, 47927735LL, 1536242641LL, -37363417LL, + 1531146993LL, -122561127LL, 1521320167LL, -207401992LL, 1506780898LL, -291622481LL, + 1487562657LL, -374959756LL, 1463713640LL, -457152495LL, 1435296725LL, -537941725LL, + 1402389373LL, -617071645LL, 1365083483LL, -694290460LL, 1323485209LL, -769351194LL, + 1277714718LL, -842012511LL, 1227905906LL, -912039512LL, 1174206073LL, -979204527LL, + 1116775541LL, -1043287891LL, 1055787239LL, -1104078695LL, 991426234LL, -1161375523LL, + 923889225LL, -1214987162LL, 853383990LL, -1264733286LL, 780128800LL, -1310445110LL, + 704351779LL, -1351966013LL, 626290245LL, -1389152131LL, 546190003LL, -1421872907LL, + 464304604LL, -1450011611LL, 380894576LL, -1473465810LL, 296226623LL, -1492147805LL, + 210572800LL, -1505985015LL, 124209655LL, -1514920324LL, 37417361LL, -1518912373LL, + -49521190LL, -1517935802LL, -136321291LL, -1511981452LL, -222697352LL, -1501056499LL, + -308363836LL, -1485184549LL, -393036207LL, -1464405671LL, -476431882LL, -1438776381LL, + -558271190LL, -1408369562LL, -638278314LL, -1373274340LL, -716182255LL, -1333595897LL, + -791717762LL, -1289455226LL, -864626268LL, -1240988842LL, -934656807LL, -1188348420LL, + -1001566912LL, -1131700396LL, -1065123495LL, -1071225506LL, -1125103703LL, -1007118267LL, + -1181295741LL, -939586417LL, -1233499676LL, -868850301LL, -1281528198LL, -795142199LL, + -1325207348LL, -718705624LL, -1364377208LL, -639794559LL, -1398892546LL, -558672660LL, + -1428623419LL, -475612415LL, -1453455729LL, -390894267LL, -1473291722LL, -304805697LL, + -1488050447LL, -217640278LL, -1497668147LL, -129696702LL, -1502098607LL, -41277767LL, + -1501313432LL, 47310640LL, -1495302271LL, 135760598LL, -1484072981LL, 223763215LL, + -1467651723LL, 311009704LL, -1446082998LL, 397192468LL, -1419429620LL, 482006201LL, + -1387772617LL, 565148974LL, -1351211073LL, 646323333LL, -1309861904LL, 725237383LL, + -1263859559LL, 801605867LL, -1213355673LL, 875151230LL, -1158518634LL, 945604661LL, + -1099533103LL, 1012707117LL, -1036599465LL, 1076210326LL, -969933214LL, 1135877745LL, + -899764281LL, 1191485504LL, -826336309LL, 1242823297LL, -749905861LL, 1289695241LL, + -670741582LL, 1331920682LL, -589123304LL, 1369334966LL, -505341106LL, 1401790143LL, + -419694326LL, 1429155627LL, -332490525LL, 1451318797LL, -244044422LL, 1468185529LL, + -154676786LL, 1479680677LL, -64713291LL, 1485748480LL, 25516648LL, 1486352900LL, + 115681069LL, 1481477899LL, 205446676LL, 1471127631LL, 294480073LL, 1455326572LL, + 382448998LL, 1434119568LL, 469023578LL, 1407571811LL, 553877577LL, 1375768736LL, + 636689647LL, 1338815840LL, 717144566LL, 1296838430LL, 794934471LL, 1249981283LL, + 869760073LL, 1198408240LL, 941331845LL, 1142301717LL, 1009371191LL, 1081862143LL, + 1073611581LL, 1017307324LL, 1133799648LL, 948871734LL, 1189696248LL, 876805739LL, + 1241077476LL, 801374745LL, 1287735627LL, 722858290LL, 1329480111LL, 641549067LL, + 1366138302LL, 557751890LL, 1397556334LL, 471782597LL, 1423599825LL, 383966912LL, + 1444154533LL, 294639249LL, 1459126941LL, 204141472LL, 1468444768LL, 112821618LL, + 1472057394LL, 21032578LL, 1469936216LL, -70869241LL, 1462074909LL, -162525296LL, + 1448489607LL, -253576300LL, 1429218998LL, -343663626LL, 1404324329LL, -432430734LL, + 1373889319LL, -519524588LL, 1338019986LL, -604597086LL, 1296844383LL, -687306471LL, + 1250512238LL, -767318741LL, 1199194514LL, -844309031LL, 1143082870LL, -917962977LL, + 1082389038LL, -987978052LL, 1017344114LL, -1054064859LL, 948197766LL, -1115948387LL, + 875217351LL, -1173369226LL, 798686964LL, -1226084720LL, 718906399LL, -1273870065LL, + 636190047LL, -1316519365LL, 550865714LL, -1353846557LL, 463273384LL, -1385686365LL, + 373763906LL, -1411895125LL, 282697644LL, -1432351258LL, 190443055LL, -1446956706LL, + 97375234LL, -1455637337LL, 3874416LL, -1458335312LL, -89675564LL, -1455040411LL, + -182888830LL, -1445734608LL, -275379058LL, -1430447954LL, -366761073LL, -1409227711LL, + -456652469LL, -1382146433LL, -544675220LL, -1349301992LL, -630457300LL, -1310816568LL, + -713634279LL, -1266836566LL, -793850913LL, -1217532174LL, -870762707LL, -1163096749LL, + -944037439LL, -1103746213LL, -1013356660LL, -1039718274LL, -1078417135LL, -971271577LL, + -1138932245LL, -898684749LL, -1194633317LL, -822255353LL, -1245270907LL, -742298749LL, + -1290615993LL, -659146869LL, -1330461107LL, -573146911LL, -1364621375LL, -484659953LL, + -1392935471LL, -394059491LL, -1415266482LL, -301729921LL, -1431502671LL, -208064944LL, + -1441558134LL, -113465928LL, -1445373360LL, -18340217LL, -1442915672LL, 76900602LL, + -1434179559LL, 171842465LL, -1419186892LL, 266070627LL, -1397987017LL, 359171476LL, + -1370656734LL, 450734357LL, -1337300149LL, 540353400LL, -1298048409LL, 627629349LL, + -1253059308LL, 712171372LL, -1202516780LL, 793598854LL, -1146630258LL, 871543157LL, + -1085633927LL, 945649350LL, -1019785847LL, 1015577887LL, -949366974LL, 1081006233LL, + -874680052LL, 1141630429LL, -796048414LL, 1197166591LL, -713814668LL, 1247352324LL, + -628339283LL, 1291948064LL, -539999092LL, 1330738315LL, -449185692LL, 1363532795LL, + -356303773LL, 1390167486LL, -261769367LL, 1410505552LL, -166008030LL, 1424438166LL, + -69452963LL, 1431885198LL, 27456920LL, 1432795785LL, 124278967LL, 1427148773LL, + 220568798LL, 1414953017LL, 315882342LL, 1396247559LL, 409777896LL, 1371101655LL, + 501818182LL, 1339614666LL, 591572415LL, 1301915812LL, 678618347LL, 1258163778LL, + 762544299LL, 1208546181LL, 842951162LL, 1153278900LL, 919454349LL, 1092605259LL, + 991685708LL, 1026795080LL, 1059295368LL, 956143602LL, 1121953515LL, 880970264LL, + 1179352094LL, 801617369LL, 1231206422LL, 718448622LL, 1277256702LL, 631847555LL, + 1317269432LL, 542215841LL, 1351038709LL, 449971511LL, 1378387401LL, 355547066LL, + 1399168201LL, 259387511LL, 1413264544LL, 161948310LL, 1420591384LL, 63693263LL, + 1421095822LL, -34907663LL, 1414757596LL, -133380570LL, 1401589400LL, -231249885LL, + 1381637062LL, -328040665LL, 1354979549LL, -423280906LL, 1321728819LL, -516503864LL, + 1282029508LL, -607250372LL, 1236058447LL, -695071145LL, 1184024025LL, -779529045LL, + 1126165389LL, -860201324LL, 1062751477LL, -936681804LL, 994079904LL, -1008583002LL, + 920475693LL, -1075538176LL, 842289850LL, -1137203293LL, 759897806LL, -1193258898LL, + 673697723LL, -1243411881LL, 584108659LL, -1287397120LL, 491568622LL, -1324979015LL, + 396532510LL, -1355952873LL, 299469939LL, -1380146122LL, 200862984LL, -1397419517LL, + 101203835LL, -1407668063LL, 992376LL, -1410820546LL, -99266296LL, -1406844847LL, + -199064398LL, -1395739898LL, -297894026LL, -1377544395LL, -395249755LL, -1352332161LL, + -490631230LL, -1320213254LL, -583545777LL, -1281333683LL, -673510981LL, -1235874793LL, + -760057246LL, -1184052619LL, -842730309LL, -1126117019LL, -921093694LL, -1062350612LL, + -994731103LL, -993067546LL, -1063248719LL, -918612095LL, -1126277418LL, -839357072LL, + -1183474862LL, -755702091LL, -1234527489LL, -668071663LL, -1279152348LL, -576913152LL, + -1317098810LL, -482694582LL, -1348150111LL, -385902324LL, -1372124735LL, -287038659LL, + -1388877625LL, -186619232LL, -1398301208LL, -85170420LL, -1400326228LL, 16773391LL, + -1394922391LL, 118672591LL, -1382098799LL, 219985189LL, -1361904179LL, 320169690LL, + -1334426905LL, 418688002LL, -1299794801LL, 515008346LL, -1258174735LL, 608608164LL, + -1209771994LL, 698977000LL, -1154829444LL, 785619346LL, -1093626487LL, 868057429LL, + -1026477796LL, 945833932LL, -953731858LL, 1018514625LL, -875769311LL, 1085690896LL, + -793001091LL, 1146982163LL, -705866399LL, 1202038160LL, -614830489LL, 1250541071LL, + -520382294LL, 1292207507LL, -423031899LL, 1326790316LL, -323307873LL, 1354080199LL, + -221754474LL, 1373907141LL, -118928738LL, 1386141630LL, -15397477LL, 1390695665LL, + 88265816LL, 1387523541LL, 191484119LL, 1376622404LL, 293680088LL, 1358032567LL, + 394279290LL, 1331837596LL, 492713458LL, 1298164140LL, 588423732LL, 1257181526LL, + 680863885LL, 1209101108LL, 769503500LL, 1154175361LL, 853831094LL, 1092696749LL, + 933357158LL, 1024996340LL, 1007617100LL, 951442198LL, 1076174076LL, 872437538LL, + 1138621686LL, 788418676LL, 1194586520LL, 699852756LL, 1243730535LL, 607235285LL, + 1285753260LL, 511087481LL, 1320393789LL, 411953447LL, 1347432575LL, 310397186LL, + 1366692997LL, 206999469LL, 1378042687LL, 102354585LL, 1381394620LL, -2933030LL, + 1376707938LL, -108252243LL, 1363988521LL, -212988754LL, 1343289282LL, -316528675LL, + 1314710191LL, -418262136LL, 1278398018LL, -517586908LL, 1234545804LL, -613912009LL, + 1183392043LL, -706661277LL, 1125219593LL, -795276893LL, 1060354313LL, -879222824LL, + 989163426LL, -957988164LL, 912053621LL, -1031090367LL, 829468907LL, -1098078330LL, + 741888212LL, -1158535319LL, 649822757LL, -1212081717LL, 553813210LL, -1258377573LL, + 454426631LL, -1297124930LL, 352253236LL, -1328069931LL, 247902981LL, -1351004668LL, + 142002002LL, -1365768766LL, 35188920LL, -1372250704LL, -71888965LL, -1370388839LL, + -178579573LL, -1360172136LL, -284229994LL, -1341640599LL, -388190503LL, -1314885383LL, + -489818567LL, -1280048604LL, -588482870LL, -1237322819LL, -683567283LL, -1186950199LL, + -774474795LL, -1129221378LL, -860631354LL, -1064473998LL, -941489595LL, -993090941LL, + -1016532449LL, -915498266LL, -1085276586LL, -832162852LL, -1147275682LL, -743589765LL, + -1202123483LL, -650319364LL, -1249456644LL, -552924149LL, -1288957326LL, -452005387LL, + -1320355529LL, -348189512LL, -1343431139LL, -242124346LL, -1358015681LL, -134475135LL, + -1363993758LL, -25920446LL, -1361304165LL, 82852063LL, -1349940664LL, 191149968LL, + -1329952420LL, 298280480LL, -1301444073LL, 403554887LL, -1264575469LL, 506293006LL, + -1219561016LL, 605827630LL, -1166668694LL, 701508928LL, -1106218699LL, 792708773LL, + -1038581741LL, 878824972LL, -964176993LL, 959285364LL, -883469706LL, 1033551763LL, + -796968503LL, 1101123710LL, -705222355LL, 1161542020LL, -608817273LL, 1214392088LL, + -508372723LL, 1259306929LL, -404537777LL, 1295969934LL, -297987050LL, 1324117324LL, + -189416412LL, 1343540267LL, -79538527LL, 1354086657LL, 30921758LL, 1355662529LL, + 141232157LL, 1348233102LL, 250657776LL, 1331823427LL, 358466013LL, 1306518655LL, + 463931482LL, 1272463890LL, 566340940LL, 1229863643LL, 664998172LL, 1178980881LL, + 759228816LL, 1120135669LL, 848385074LL, 1053703414LL, 931850294LL, 980112715LL, + 1009043382LL, 899842834LL, 1079423012LL, 813420795LL, 1142491599LL, 721418127LL, + 1197799019LL, 624447279LL, 1244946029LL, 523157713LL, 1283587375LL, 418231710LL, + 1313434552LL, 310379909LL, 1334258200LL, 200336606LL, 1345890115LL, 88854849LL, + 1348224848LL, -23298644LL, 1341220889LL, -135348713LL, 1324901412LL, -246517088LL, + 1299354577LL, -356027795LL, 1264733378LL, -463112595LL, 1221255035LL, -567016422LL, + 1169199932LL, -667002775LL, 1108910090LL, -762359038LL, 1040787204LL, -852401669LL, + 965290228LL, -936481242LL, 882932534LL, -1013987292LL, 794278662LL, -1084352923LL, + 699940665LL, -1147059155LL, 600574090LL, -1201638967LL, 496873606LL, -1247681006LL, + 389568308LL, -1284832932LL, 279416736LL, -1312804365LL, 167201623LL, -1331369424LL, + 53724435LL, -1340368814LL, -60200289LL, -1339711453LL, -173750741LL, -1329375624LL, + -286103750LL, -1309409627LL, -396440763LL, -1279931930LL, -503953839LL, -1241130812LL, + -607851631LL, -1193263487LL, -707365292LL, -1136654712LL, -801754281LL, -1071694897LL, + -890312008LL, -998837699LL, -972371284LL, -918597138LL, -1047309535LL, -831544232LL, + -1114553723LL, -738303181LL, -1173584956LL, -639547120LL, -1223942735LL, -535993464LL, + -1265228802LL, -428398885LL, -1297110559LL, -317553943LL, -1319324033LL, -204277414LL, + -1331676345LL, -89410352LL, -1334047672LL, 26190070LL, -1326392673LL, 141656903LL, + -1308741371LL, 256119894LL, -1281199462LL, 368712050LL, -1243948063LL, 478576227LL, + -1197242872LL, 584871724LL, -1141412765LL, 686780797LL, -1076857805LL, 783515067LL, + -1004046699LL, 874321765LL, -923513696LL, 958489753LL, -835854955LL, 1035355293LL, + -741724400LL, 1104307495LL, -641829091LL, 1164793414LL, -536924137LL, 1216322742LL, + -427807187LL, 1258472061LL, -315312546LL, 1290888612LL, -200304937LL, 1313293552LL, + -83672978LL, 1325484662LL, 33677596LL, 1327338478LL, 150830907LL, 1318811828LL, + 266868055LL, 1299942752LL, 380874329LL, 1270850782LL, 491946455LL, 1231736592LL, + 599199815LL, 1182880994LL, 701775596LL, 1124643293LL, 798847793LL, 1057458996LL, + 889630021LL, 981836899LL, 973382071LL, 898355557LL, 1049416163LL, 807659161LL, + 1117102833LL, 710452854LL, 1175876408LL, 607497505LL, 1225240018LL, 499603991LL, + 1264770099LL, 387627022LL, 1294120349LL, 272458544LL, 1313025088LL, 155020785LL, + 1321301996LL, 36258989LL, 1318854203LL, -82866109LL, 1305671692LL, -201386007LL, + 1281832013LL, -318332290LL, 1247500275LL, -432744567LL, 1202928428LL, -543678406LL, + 1148453818LL, -650213223LL, 1084497022LL, -751460042LL, 1011558974LL, -846569067LL, + 930217403LL, -934737007LL, 841122588LL, -1015214072LL, 744992480LL, -1087310603LL, + 642607201LL, -1150403252LL, 534802984LL, -1203940667LL, 422465572LL, -1247448637LL, + 306523150LL, -1280534622LL, 187938841LL, -1302891648LL, 67702845LL, -1314301516LL, + -53175728LL, -1314637285LL, -173677263LL, -1303865008LL, -292780218LL, -1282044696LL, + -409469790LL, -1249330486LL, -522746615LL, -1205970012LL, -631635415LL, -1152302967LL, + -735193517LL, -1088758863LL, -832519177LL, -1015853998LL, -922759631LL, -934187646LL, + -1005118794LL, -844437499LL, -1078864548LL, -747354381LL, -1143335540LL, -643756280LL, + -1197947431LL, -534521746LL, -1242198536LL, -420582690LL, -1275674795LL, -302916656LL, + -1298054021LL, -182538614LL, -1309109387LL, -60492356LL, -1308712111LL, 62158451LL, + -1296833296LL, 184339470LL, -1273544912LL, 304975074LL, -1239019894LL, 422997835LL, + -1193531345LL, 537358028LL, -1137450842LL, 647033064LL, -1071245853LL, 751036774LL, + -995476268LL, 848428460LL, -910790076LL, 938321617LL, -817918208LL, 1019892260LL, + -717668591LL, 1092386762LL, -610919444LL, 1155129142LL, -498611888LL, 1207527712LL, + -381741905LL, 1249081032LL, -261351735LL, 1279383103LL, -138520763LL, 1298127741LL, + -14355984LL, 1305112082LL, 110017874LL, 1300239188LL, 233468481LL, 1283519698LL, + 354866207LL, 1255072516LL, 473094493LL, 1215124509LL, 587060202LL, 1164009212LL, + 695703851LL, 1102164535LL, 798009631LL, 1030129482LL, 893015120LL, 948539906LL, + 979820587LL, 858123324LL, 1057597806LL, 759692827LL, 1125598286LL, 654140139LL, + 1183160836LL, 542427871LL, 1229718381LL, 425581041LL, 1264803961LL, 304677924LL, + 1288055852LL, 180840318LL, 1299221729LL, 55223304LL, 1298161856LL, -70995405LL, + 1284851217LL, -196626431LL, 1259380600LL, -320479911LL, 1221956577LL, -441376790LL, + 1172900385LL, -558160123LL, 1112645701LL, -669706264LL, 1041735318LL, -774935848LL, + 960816745LL, -872824459LL, 870636758LL, -962412856LL, 772034936LL, -1042816688LL, + 665936252LL, -1113235559LL, 553342755LL, -1172961385LL, 435324430LL, -1221385919LL, + 313009312LL, -1258007389LL, 187572936LL, -1282436160LL, 60227226LL, -1294399346LL, + -67791082LL, -1293744339LL, -195232362LL, -1280441179LL, -320846277LL, -1254583745LL, + -443394059LL, -1216389745LL, -561660815LL, -1166199469LL, -674467696LL, -1104473330LL, + -780683837LL, -1031788186LL, -879237925LL, -948832467LL, -969129295LL, -856400150LL, + -1049438413LL, -755383614LL, -1119336664LL, -646765457LL, -1178095305LL, -531609311LL, + -1225093514LL, -411049772LL, -1259825423LL, -286281514LL, -1281906058LL, -158547683LL, + -1291076111LL, -29127706LL, -1287205493LL, 100675397LL, -1270295595LL, 229548055LL, + -1240480246LL, 356179424LL, -1198025314LL, 479274763LL, -1143326966LL, 597568774LL, + -1076908571LL, 709838762LL, -999416261LL, 814917497LL, -911613195LL, 911705609LL, + -814372557LL, 999183423LL, -708669349LL, 1076422062LL, -595571047LL, 1142593733LL, + -476227216LL, 1196981051LL, -351858160LL, 1238985307LL, -223742738LL, 1268133577LL, + -93205438LL, 1284084583LL, 38397141LL, 1286633231LL, 169690278LL, 1275713767LL, + 299295444LL, 1251401486LL, 425844789LL, 1213912985LL, 547995664LL, 1163604907LL, + 664445003LL, 1100971209LL, 773943433LL, 1026638926LL, 875308943LL, 941362496LL, + 967439966LL, 846016659LL, 1049327727LL, 741588011LL, 1120067719LL, 629165273LL, + 1178870161LL, 509928374LL, 1225069333LL, 385136445LL, 1258131656LL, 256114848LL, + 1277662419LL, 124241361LL, 1283411079LL, -9068335LL, 1275275029LL, -142375719LL, + 1253301811LL, -274234891LL, 1217689703LL, -403208254LL, 1168786663LL, -527882260LL, + 1107087633LL, -646883049LL, 1033230198LL, -758891789LL, 947988632LL, -862659572LL, + 852266388LL, -957021674LL, 747087082LL, -1040911027LL, 633584065LL, -1113370734LL, + 512988673LL, -1173565484LL, 386617276LL, -1220791728LL, 255857257LL, -1254486480LL, + 122152064LL, -1274234632LL, -13014518LL, -1279774689LL, -148134686LL, -1271002831LL, + -281693373LL, -1247975243LL, -412185246LL, -1210908664LL, -538131749LL, -1160179130LL, + -658098014LL, -1096318898LL, -770709439LL, -1020011573LL, -874667737LL, -932085466LL, + -968766268LL, -833505237LL, -1051904482LL, -725361905LL, -1123101272LL, -608861313LL, + -1181507100LL, -485311166LL, -1226414715LL, -356106773LL, -1257268347LL, -222715646LL, + -1273671230LL, -86661113LL, -1275391364LL, 50494872LL, -1262365420LL, 187169527LL, + -1234700721LL, 321777461LL, -1192675259LL, 452749092LL, -1136735713LL, 578549064LL, + -1067493484LL, 697694433LL, -985718749LL, 808772420LL, -892332602LL, 910457510LL, + -788397339LL, 1001527681LL, -675104980LL, 1080879580LL, -553764152LL, 1147542429LL, + -425785458LL, 1200690501LL, -292665495LL, 1239653991LL, -155969698LL, 1263928134LL, + -17314192LL, 1273180442LL, 121653132LL, 1267255953LL, 259272109LL, 1246180397LL, + 393890123LL, 1210161231LL, 523882030LL, 1159586485LL, 647669949LL, 1095021429LL, + 763742657LL, 1017203056LL, 870674381LL, 927032439LL, 967142719LL, 825565017LL, + 1051945484LL, 713998906LL, 1124016237LL, 593661365LL, 1182438319LL, 465993542LL, + 1226457175LL, 332533690LL, 1255490808LL, 194899017LL, 1269138215LL, 54766401LL, + 1267185666LL, -86147830LL, 1249610732LL, -226108790LL, 1216583979LL, -363384358LL, + 1168468288LL, -496266684LL, 1105815769LL, -623093584LL, 1029362291LL, -742269586LL, + 940019657LL, -852286337LL, 838865506LL, -951742114LL, 727131031LL, -1039360197LL, + 606186651LL, -1114005830LL, 477525785LL, -1174701565LL, 342746919LL, -1220640769LL, + 203534170LL, -1251199090LL, 61636570LL, -1265943725LL, -81153669LL, -1264640339LL, + -223023653LL, -1247257525LL, -362162785LL, -1213968706LL, -496785936LL, -1165151443LL, + -625156512LL, -1101384108LL, -745609124LL, -1023439948LL, -856571549LL, -932278577LL, + -956585711LL, -829034979LL, -1044327376LL, -715006139LL, -1118624311LL, -591635433LL, + -1178472634LL, -460494976LL, -1223051130LL, -323266114LL, -1251733322LL, -181718303LL, + -1264097102LL, -37686632LL, -1259931789LL, 106951731LL, -1239242457LL, 250301877LL, + -1202251476LL, 390475962LL, -1149397192LL, 525618152LL, -1081329739LL, 653929398LL, + -998904000LL, 773691683LL, -903169777LL, 883291440LL, -795359276LL, 981241791LL, + -676872025LL, 1066203319LL, -549257420LL, 1137003063LL, -414195083LL, 1192651467LL, + -273473286LL, 1232357025LL, -128965702LL, 1255538399LL, 17393227LL, 1261833825LL, + 163633968LL, 1251107626LL, 307778317LL, 1223453736LL, 447866173LL, 1179196131LL, + 581982343LL, 1118886130LL, 708282973LL, 1043296571LL, 825021280LL, 953412903LL, + 930572180LL, 850421269LL, 1023455499LL, 735693727LL, 1102357405LL, 610770760LL, + 1166149752LL, 477341296LL, 1213907044LL, 337220487LL, 1244920757LL, 192325518LL, + 1258710778LL, 44649762LL, 1255033785LL, -103764362LL, 1233888395LL, -250853493LL, + 1195516984LL, -394561984LL, 1140404107LL, -532870734LL, 1069271505LL, -663825783LL, + 983069719LL, -785566266LL, 882966405LL, -896351323LL, 770331453LL, -994585576LL, + 646719114LL, -1078842784LL, 513847322LL, -1147887336LL, 373574497LL, -1200693226LL, + 227874113LL, -1236460234LL, 78807380LL, -1254627023LL, -71505594LL, -1254880958LL, + -220915765LL, -1237164430LL, -367275829LL, -1201677589LL, -508471155LL, -1148877376LL, + -642450558LL, -1079472835LL, -767256441LL, -994416739LL, -881053874LL, -894893583LL, + -982158174LL, -782304102LL, -1069060547LL, -658246481LL, -1140451425LL, -524494496LL, + -1195241101LL, -382972882LL, -1232577337LL, -235730240LL, -1251859655LL, -84909862LL, + -1252750049LL, 67281122LL, -1235179927LL, 218603833LL, -1199353134LL, 366820522LL, + -1145744952LL, 509727738LL, -1075097067LL, 645189319LL, -988408506LL, 771168687LL, + -886922654LL, 885759977LL, -772110474LL, 987217504LL, -645650165LL, 1073983116LL, + -509403499LL, 1144710991LL, -365389164LL, 1198289471LL, -215753486LL, 1233859577LL, + -62738930LL, 1250829871LL, 91349161LL, 1248887414LL, 244177099LL, 1228004587LL, + 393418155LL, 1188441635LL, 536788098LL, 1130744845LL, 672080420LL, 1055740321LL, + 797200719LL, 964523416LL, 910199684LL, 858443918LL, 1009304169LL, 739087179LL, + 1092945847LL, 608251423LL, 1159786967LL, 467921537LL, 1208742795LL, 320239726LL, + 1239000329LL, 167473429LL, 1250032974LL, 11980981LL, 1241610884LL, -143824481LL, + 1213806756LL, -297512308LL, 1166996955LL, -446672277LL, 1101857859LL, -588952563LL, + 1019357459LL, -722097167LL, 920742271LL, -843982186LL, 807519719LL, -952650354LL, + 681436211LL, -1046343266LL, 544451207LL, -1123530763LL, 398707647LL, -1182936962LL, + 246499167LL, -1223562481LL, 90234582LL, -1244702466LL, -67599811LL, -1245960060LL, + -224479545LL, -1227255070LL, -377882286LL, -1188827607LL, -525328490LL, -1131236607LL, + -664421768LL, -1055353175LL, -792888286LL, -962348817LL, -908614558LL, -853678666LL, + -1009682998LL, -731059949LL, -1094404620LL, -596445955LL, -1161348315LL, -451995907LL, + -1209366188LL, -300041156LL, -1237614494LL, -143048236LL, -1245569770LL, 16420670LL, + -1233039839LL, 175749222LL, -1200169452LL, 332309710LL, -1147440400LL, 483506443LL, + -1075666040LL, 626819025LL, -985980239LL, 759844796LL, -879820887LL, 880339729LL, + -758908154LL, 986257055LL, -625217823LL, 1075782979LL, -480950069LL, 1147368814LL, + -328494164LL, 1199758976LL, -170389655LL, 1232014312LL, -9284630LL, 1243530296LL, + 152108264LL, 1234049756LL, 311057312LL, 1203669808LL, 464857999LL, 1152842852LL, + 610879250LL, 1082371511LL, 746608868LL, 993397547LL, 869697378LL, 887384862LL, + 977999500LL, 766096810LL, 1069612516LL, 631568141LL, 1142910822LL, 486071999LL, + 1196576040LL, 332082482LL, 1229622093LL, 172233369LL, 1241414765LL, 9273673LL, + 1231685337LL, -153979240LL, 1200537982LL, -314688167LL, 1148450726LL, -470045409LL, + 1076269872LL, -617322067LL, 985197923LL, -753916432LL, 876775115LL, -877400613LL, + 752854835LL, -985564547LL, 615573267LL, -1076456598LL, 467313746LL, -1148419969LL, + 310666385LL, -1200124241LL, 148383634LL, -1230591423LL, -16667471LL, -1239215974LL, + -181555581LL, -1225778366LL, -343336925LL, -1190451888LL, -499107939LL, -1133802465LL, + -646057678LL, -1056781422LL, -781519061LL, -960711243LL, -903018024LL, -847264495LL, + -1008319651LL, -718436217LL, -1095470422LL, -576510200LL, -1162835754LL, -424019691LL, + -1209132105LL, -263703185LL, -1233452975LL, -98456041LL, -1235288279LL, 68721241LL, + -1214536627LL, 234777160LL, -1171510234LL, 396664822LL, -1106932254LL, 551397999LL, + -1021926513LL, 696106607LL, -917999740LL, 828090575LL, -797016526LL, 944871089LL, + -661167400LL, 1044238217LL, -512930537LL, 1124293997LL, -355027720LL, 1183490118LL, + -190375337LL, 1220659435LL, -22031251LL, 1235040648LL, 146861499LL, 1226295600LL, + 313133136LL, 1194518784LL, 473646663LL, 1140238781LL, 625357325LL, 1064411514LL, + 765370911LL, 968405341LL, 890999748LL, 853978178LL, 999815322LL, 723246988LL, + 1089696457LL, 578650138LL, 1158872091LL, 422903243LL, 1205957765LL, 258949284LL, + 1229985042LL, 89903872LL, 1230423209LL, -81003331LL, 1207192760LL, -250489953LL, + 1160670283LL, -415283870LL, 1091684572LL, -572186571LL, 1001503929LL, -718135709LL, + 891814791LL, -850265600LL, 764692010LL, -965964490LL, 622561257LL, -1062927401LL, + 468154194LL, -1139203493LL, 304457216LL, -1193236935LL, 134654685LL, -1223900397LL, + -37932279LL, -1230520442LL, -209910308LL, -1212894177LL, -377880337LL, -1171296778LL, + -538504921LL, -1106479585LL, -688574973LL, -1019658728LL, -825074589LL, -912494380LL, + -945242646LL, -787060944LL, -1046629896LL, -645808667LL, -1127150356LL, -491517342LL, + -1185125897LL, -327242948LL, -1219323049LL, -156258202LL, -1228981184LL, 18011829LL, + -1213831410LL, 192057824LL, -1174105677LL, 362356671LL, -1110535788LL, 525442889LL, + -1024342238LL, 677979566LL, -917212951LL, 816827360LL, -791272272LL, 939110124LL, + -649040699LL, 1042275772LL, -493386094LL, 1124151074LL, -327467270LL, 1182989184LL, + -154671032LL, 1217508820LL, 21456109LL, 1226924207LL, 197280187LL, 1210965034LL, + 369154552LL, 1169885894LL, 533495619LL, 1104464897LL, 686858042LL, 1015991344LL, + 826007715LL, 906242588LL, 947991060LL, 777450461LL, 1050199090LL, 632257813LL, + 1130424832LL, 473665997LL, 1186912839LL, 304974276LL, 1218399620LL, 129712351LL, + 1224144049LL, -48432646LL, 1203946973LL, -225693207LL, 1158159478LL, -398300953LL, + 1087679494LL, -562566935LL, 993936690LL, -714961000LL, 878865829LL, -852188536LL, + 744869017LL, -971262889LL, 594767543LL, -1069571861LL, 431744206LL, -1144936776LL, + 259277283LL, -1195662745LL, 81067450LL, -1220578943LL, -99040821LL, -1219067896LL, + -277141758LL, -1191083016LL, -449352913LL, -1137153864LL, -611900100LL, -1058378868LL, + -761200774LL, -956405521LL, -893944016LL, -833398336LL, -1007165314LL, -691995119LL, + -1098314433LL, -535252396LL, -1165314783LL, -366581051LL, -1206612884LL, -189673508LL, + -1221216688LL, -8423960LL, -1208721806LL, 173156661LL, -1169324871LL, 351029133LL, + -1103823624LL, 521215880LL, -1013603534LL, 679890397LL, -900611116LL, 823464148LL, + -767314361LL, 948668955LL, -616651056LL, 1052632958LL, -451965976LL, 1132948372LL, + -276938272LL, 1187729377LL, -95500572LL, 1215658746LL, 88248466LL, 1216021984LL, + 270136220LL, 1188728078LL, 446010755LL, 1134316204LL, 611835905LL, 1053948079LL, + 763784626LL, 949385973LL, 898328441LL, 822956695LL, 1012320869LL, 677502232LL, + 1103072847LL, 516318025LL, 1168418290LL, 343080154LL, 1206768167LL, 161762992LL, + 1217151681LL, -23450858LL, 1199243460LL, -208266355LL, 1153375935LL, -388375351LL, + 1080536461LL, -559557190LL, 982349051LL, -717778233LL, 861040982LL, -859287943LL, + 719394872LL, -980709229LL, 560687189LL, -1079120860LL, 388614487LL, -1152129883LL, + 207208982LL, -1197932225LL, 20745327LL, -1215359893LL, -166359269LL, -1203913478LL, + -349649302LL, -1163779037LL, -524737144LL, -1095828732LL, -687408616LL, -1001605046LL, + -833725413LL, -883288743LL, -960121883LL, -743651154LL, -1063493740LL, -585991766LL, + -1141276490LL, -414062431LL, -1191511528LL, -231979888LL, -1212898166LL, -44128586LL, + -1204830150LL, 144943957LL, -1167415593LL, 330636771LL, -1101479640LL, 508407415LL, + -1008549598LL, 673883616LL, -890822680LL, 822971792LL, -751116953LL, 951959778LL, + -592806515LL, 1057611128LL, -419742294LL, 1137248580LL, -236160280LL, 1188824468LL, + -46579312LL, 1210976194LL, 144309158LL, 1203065186LL, 331756664LL, 1165198189LL, + 511075870LL, 1098230132LL, 677758317LL, 1003748296LL, 827588823LL, 884037939LL, + 956753607LL, 742030049LL, 1061939336LL, 581232305LL, 1140420493LL, 405644810LL, + 1190132695LL, 219662540LL, 1209729954LL, 27966838LL, 1198624217LL, -164591424LL, + 1157005971LL, -353114129LL, 1085845164LL, -532780589LL, 986872185LL, -698971433LL, + 862539149LL, -847388532LL, 715962253LL, -974167817LL, 550846469LL, -1075982007LL, + 371394303LL, -1150130458LL, 182200799LL, -1194613672LL, -11862652LL, -1208190327LL, + -205772806LL, -1190415164LL, -394484218LL, -1141656483LL, -573060723LL, -1063092587LL, + -736805329LL, -956686980LL, -881385086LL, -825142745LL, -1002947598LL, -671837044LL, + -1098225999LL, -500737225LL, -1164629485LL, -316300548LL, -1200316836LL, -123359981LL, + -1204250770LL, 73001071LL, -1176231463LL, 267581896LL, -1116908092LL, 455202013LL, + -1027767826LL, 630839503LL, -911102298LL, 789766426LL, -769952193LL, 927677667LL, + -608031172LL, 1040809671LL, -429630947LL, 1126045733LL, -239509840LL, 1181004861LL, + -42767646LL, 1204111588LL, 155289962LL, 1194644637LL, 349293928LL, 1152762847LL, + 533957418LL, 1079507398LL, 704220576LL, 976779976LL, 855390474LL, 847297206LL, + 983272364LL, 694522316LL, 1084288509LL, 522575629LL, 1155581183LL, 336126117LL, + 1195096803LL, 140266770LL, 1201648643LL, -59622964LL, 1174956140LL, -258023999LL, + 1115659420LL, -449429722LL, 1025308336LL, -628499230LL, 906326042LL, -790207428LL, + 761947798LL, -929987743LL, 596136441LL, -1043863374LL, 413476607LL, -1128563258LL, + 219050455LL, -1181619292LL, 18298139LL, -1201441864LL, -183133162LL, -1187371276LL, + -379547549LL, -1139703339LL, -565361616LL, -1059688090LL, -735264016LL, -949501355LL, + -884368818LL, -812189644LL, -1008358190LL, -651589637LL, -1103610191LL, -472224271LL, + -1167307830LL, -279178127LL, -1197526029LL, -77955457LL, -1193293716LL, 125675248LL, + -1154628967LL, 325845835LL, -1082545841LL, 516757531LL, -979032394LL, 692849616LL, + -847000156LL, 848962797LL, -690206205LL, 980492464LL, -513149797LL, 1083527231LL, + -320946271LL, 1154968519LL, -119181666LL, 1192627460LL, 86247908LL, 1195295988LL, + 289307592LL, 1162789717LL, 484000841LL, 1095961016LL, 664547080LL, 996681515LL, + 825554662LL, 867794228LL, 962183944LL, 713036323LL, 1070295492LL, 536934524LL, + 1146578819LL, 344675921LL, 1188657563LL, 141957770LL, 1195167672LL, -65179449LL, + 1165805922LL, -270530916LL, 1101346958LL, -467913021LL, 1003627956LL, -651350083LL, + 875501004LL, -815256577LL, 720754244LL, -954609296LL, 544003811LL, -1065104101LL, + 350559517LL, -1143292279LL, 146268057LL, -1186692126LL, -62661719LL, -1193872025LL, + -269846323LL, -1164502145LL, -468922339LL, -1099372792LL, -653742386LL, -1000378445LL, + -818566321LL, -870467574LL, -958241700LL, -713559377LL, -1068367765LL, -534429619LL, + -1145437686LL, -338568770LL, -1186954337LL, -132016512LL, -1191515706LL, 78822485LL, + -1158866885LL, 287375991LL, -1089916626LL, 487108794LL, -986717504LL, 671728117LL, + -852409901LL, 835383376LL, -691131119LL, 972853939LL, -507892115LL, 1079718788LL, + -308425343LL, 1152502487LL, -99008234LL, 1188792549LL, 113732398LL, 1187324111LL, + 323028977LL, 1148028831LL, 522188308LL, 1072046021LL, 704806427LL, 961695198LL, + 864976252LL, 820410483LL, 997481255LL, 652638504LL, 1097968751LL, 463702660LL, + 1163096951LL, 259637736LL, 1190650700LL, 46999874LL, 1179621777LL, -167342227LL, + 1130250700LL, -376428295LL, 1044028242LL, -573432608LL, 923656100LL, -751887909LL, + 772967533LL, -905899758LL, 596810100LL, -1030344171LL, 400893895LL, -1121041831LL, + 191609878LL, -1174902856LL, -24176051LL, -1190036979LL, -239346695LL, -1165825093LL, + -446767723LL, -1102949293LL, -639524671LL, -1003379965LL, -811154915LL, -870319791LL, + -955866813LL, -708106069LL, -1068738509LL, -522074091LL, -1145889493LL, -318385725LL, + -1184618813LL, -103828527LL, -1183504884LL, 114408167LL, -1142463065LL, 328972907LL, + -1062758547LL, 532599600LL, -946973576LL, 718354498LL, -798929593LL, 879874286LL, + -623566391LL, 1011587050LL, -426781922LL, 1108908373LL, -215237747LL, 1168405543LL, + 3863580LL, 1187923868LL, 223021900LL, 1166670279LL, 434695444LL, 1105250860LL, + 631560763LL, 1005660429LL, 806767624LL, 871223974LL, 954179983LL, 706491399LL, + 1068594484LL, 517088676LL, 1145928594LL, 309530071LL, 1183371450LL, 90997543LL, + 1179491695LL, -130905366LL, 1134297987LL, -348416809LL, 1049249514LL, -553888044LL, + 927215523LL, -740053495LL, 772384703LL, -900289924LL, 590127010LL, -1028855403LL, + 386812279LL, -1121099376LL, 169591554LL, -1173635994LL, -53851532LL, -1184474107LL, + -275570795LL, -1153098759LL, -487639560LL, -1080500690LL, -682434762LL, -969152155LL, + -852912913LL, -822929302LL, -992867896LL, -646983253LL, -1097161048LL, -447563932LL, + -1161914905LL, -231802457LL, -1184663117LL, -7459472LL, -1164450587LL, 217351833LL, + -1101879582LL, 434458219LL, -999099479LL, 635923953LL, -859739865LL, 814342562LL, + -688788744LL, 963112050LL, -492419686LL, 1076683252LL, -277773665LL, 1150771864LL, + -52703086LL, 1182525896LL, 174512967LL, 1170641810LL, 395472070LL, 1115424435LL, + 601959331LL, 1018787752LL, 786254310LL, 884195824LL, 941422502LL, 716545339LL, + 1061580277LL, 521993483LL, 1142123056LL, 307736915LL, 1179907693LL, 81749579LL, + 1173381659LL, -147511280LL, 1122653524LL, -371420195LL, 1029501355LL, -581507970LL, + 897317977LL, -769783426LL, 730994427LL, -929040146LL, 536745278LL, -1053136350LL, + 321881818LL, -1137236928LL, 94541113LL, -1178007905LL, -136619180LL, -1173755342LL, + -362748955LL, -1124502642LL, -575144401LL, -1032002590LL, -765584401LL, -899682844LL, + -926651578LL, -732526209LL, -1052025352LL, -536889546LL, -1136735302LL, -320267602LL, + -1177364512LL, -91010301LL, -1172194354LL, 141996045LL, -1121284367LL, 369671586LL, + -1026483323LL, 583096697LL, -891370209LL, 773862907LL, -721126630LL, 934407153LL, + -522344818LL, 1058315998LL, -302778078LL, 1140587405LL, -71042850LL, 1177839232LL, + 163716357LL, 1168455503LL, 392186300LL, 1112663919LL, 605254547LL, 1012540676LL, + 794374623LL, 871941545LL, 951912066LL, 696361073LL, 1071457291LL, 492724710LL, + 1148092286LL, 269121398LL, 1178599831LL, 34486702LL, 1161606123LL, -201751329LL, + 1097650205LL, -430049665LL, 989176545LL, -641136156LL, 840450111LL, -826388140LL, + 657396496LL, -978188301LL, 447372717LL, -1090242970LL, 218877230LL, -1157849403LL, + -18789663LL, -1178100442LL, -255901661LL, -1150017430LL, -482703515LL, -1074605014LL, + -689813151LL, -954824662LL, -868612270LL, -795487002LL, -1011609128LL, -603066480LL, + -1112758046LL, -385445106LL, -1167721862LL, -151595120LL, -1174065661LL, 88786927LL, + -1131372873LL, 325679940LL, -1041277938LL, 549155540LL, -907413160LL, 749795508LL, + -735270969LL, 919091829LL, -531986390LL, 1049812252LL, -306047945LL, 1136315488LL, + -66948420LL, 1174802088LL, 175210436LL, 1163489582LL, 410142958LL, 1102703490LL, + 627816617LL, 994879352LL, 818882510LL, 844474588LL, 975080774LL, 657792914LL, + 1089603210LL, 442727787LL, 1157396998LL, 208434960LL, 1175395695LL, -35052575LL, + 1142666661LL, -277251312LL, 1060467527LL, -507677623LL, 932208158LL, -716302553LL, + 763318636LL, -893991279LL, 561027904LL, -1032907880LL, 334061657LL, -1126867323LL, + 92271762LL, -1171618599LL, -153787356LL, -1165045770LL, -393317352LL, -1107277090LL, + -615749829LL, -1000696286LL, -811214673LL, -849854342LL, -970982056LL, -661284478LL, + -1087858162LL, -443227402LL, -1156516495LL, -205277954LL, -1173749216LL, 42032027LL, + -1138626324LL, 287696748LL, -1052554463LL, 520725248LL, -919231492LL, 730634279LL, + -744497627LL, 907923194LL, -536088624LL, 1044509187LL, -303300967LL, 1134102794LL, + -56583171LL, 1172505906LL, 192929141LL, 1157817860LL, 433913932LL, 1090539138LL, + 655376832LL, 973566717LL, 847155269LL, 812079984LL, 1000389487LL, 613321126LL, + 1107938432LL, 386278806LL, 1164720731LL, 141288500LL, 1167964157LL, -110433083LL, + 1117350975LL, -357298810LL, 1015051174LL, -587884038LL, 865640725LL, -791457222LL, + 675907270LL, -958483503LL, 454550936LL, -1081077499LL, 211793007LL, -1153383577LL, + -41090371LL, -1171864911LL, -292288474LL, -1135486707LL, -530006476LL, -1045783710LL, + -743020560LL, -906807417LL, -921211520LL, -724954056LL, -1056051359LL, -508680031LL, + -1141019251LL, -268116965LL, -1171926261LL, -14603445LL, -1147132271LL, 239845266LL, + -1067643459LL, 483104968LL, -937084252LL, 703521021LL, -761543571LL, 890470022LL, + -549301261LL, 1034877447LL, -310446427LL, 1129665854LL, -56404794LL, 1170111162LL, + 200603153LL, 1154088685LL, 448147821LL, 1082195692LL, 674192048LL, 957743030LL, + 867679435LL, 786614674LL, 1019080623LL, 577000451LL, 1120870308LL, 339013488LL, + 1167910798LL, 84209731LL, 1157722149LL, -174968042LL, 1090624232LL, -425795266LL, + 969742191LL, -655890458LL, 800873373LL, -853829246LL, 592220663LL, -1009717039LL, + 354003853LL, -1115691395LL, 97966911LL, -1166328272LL, -163195533LL, -1158930727LL, + -416464804LL, -1093684258LL, -649147153LL, -973669375LL, -849512792LL, -804729078LL, + -1007392729LL, -595196148LL, -1114702812LL, -355492323LL, -1165867633LL, -97618055LL, + -1158121629LL, 165442628LL, -1091670626LL, 420372972LL, -969703929LL, 654197652LL, + -798254549LL, 854946137LL, -585912880LL, 1012271264LL, -343406714LL, 1117990822LL, + -83067538LL, 1166523425LL, 181790824LL, 1155195010LL, 437550256LL, 1084398590LL, + 670988755LL, 957597276LL, 869967219LL, 781168493LL, 1024066824LL, 564095589LL, + 1125143281LL, 317521004LL, 1167768087LL, 54182634LL, 1149532370LL, -212238609LL, + 1071195791LL, -467826954LL, 936670817LL, -699159203LL, 752841208LL, -894013413LL, + 529222297LL, -1042021309LL, 277479074LL, -1135229273LL, 10825863LL, -1168537175LL, + -256662003LL, -1139990275LL, -510788999LL, -1050906926LL, -737993899LL, -905833319LL, + -926077844LL, -712325566LL, -1064866714LL, -480568731LL, -1146771523LL, -222851248LL, + -1167215492LL, 47078777LL, -1124903210LL, 314742146LL, -1021915447LL, 565703739LL, + -863622395LL, 786352922LL, -658417859LL, 964646951LL, -417286661LL, 1090776561LL, + -153226821LL, 1157716561LL, 119443745LL, 1161630014LL, 385859466LL, 1102102146LL, + 631416946LL, 982189103LL, 842578372LL, 808276659LL, 1007624182LL, 589754351LL, + 1117312894LL, 338520796LL, 1165410482LL, 68345499LL, 1149058408LL, -205879220LL, + 1068957927LL, -468955976LL, 929358202LL, -706225079LL, 737846515LL, -904385594LL, + 504949925LL, -1052248584LL, 243568403LL, -1141379486LL, -31730762LL, -1166592259LL, + -305519263LL, -1126265691LL, -562370532LL, -1022461901LL, -787730886LL, -860837946LL, + -968749825LL, -650353045LL, -1095021869LL, -402785604LL, -1159196663LL, -132085099LL, + -1157420990LL, 146405932LL, -1089585412LL, 416817399LL, -959359048LL, 663655727LL, + -774007959LL, 872694531LL, -544004956LL, 1031803874LL, -282450816LL, 1131664530LL, + -4338061LL, 1166306616LL, 274301977LL, 1133559164LL, 537320730LL, 1035063669LL, + 769389850LL, 876349202LL, 956900101LL, 666461071LL, 1088768745LL, 417480575LL, + 1157107038LL, 143841839LL, 1157707006LL, -138498378LL, 1090316720LL, -412985853LL, + 958685267LL, -663439043LL, 770372016LL, -875006924LL, 536328605LL, -1035057264LL, + 270275712LL, -1133942288LL, -12090839LL, -1165594464LL, -294019389LL, -1127914989LL, + -558693808LL, -1022929252LL, -790238466LL, -856697158LL, -974676726LL, -638980751LL, + -1100784782LL, -382686159LL, -1160788166LL, -103110782LL, -1150856994LL, 182961229LL, + -1071367549LL, 458262274LL, -926911542LL, 706083789LL, -726049438LL, 911295021LL, + -480819778LL, 1061275800LL, -206031502LL, 1146705320LL, 81620056LL, 1162156979LL, + 364561463LL, 1106460460LL, 625413312LL, 982806015LL, 848060959LL, 798581423LL, + 1018657785LL, 564948454LL, 1126498133LL, 296181885LL, 1164704270LL, 8809179LL, + 1130682433LL, -279398163LL, 1026316834LL, -550520576LL, 857886318LL, -787606412LL, + 635705579LL, -975738422LL, 373510064LL, -1102983301LL, 87620113LL, -1161163278LL, + -204065734LL, -1146399050LL, -483186829LL, -1059387047LL, -732076690LL, -905390330LL, + -934886685LL, -693940204LL, -1078605415LL, -438264049LL, -1153907668LL, -154472426LL, + -1155776762LL, 139445576LL, -1083857779LL, 424756888LL, -942515822LL, 683177795LL, + -740591993LL, 898050181LL, -490869158LL, 1055424818LL, -209278427LL, 1144980731LL, + 86105508LL, 1160719283LL, 376217659LL, 1101385307LL, 642231621LL, 970584680LL, + 866785033LL, 776587016LL, 1035121695LL, 531822563LL, 1136074763LL, 252102456LL, + 1162824700LL, -44389942LL, 1113379593LL, -338273211LL, 990742857LL, -610232351LL, + 802753534LL, -842291316LL, 561605807LL, -1019009681LL, 283075547LL, -1128523322LL, + -14498048LL, -1163358190LL, -311411477LL, -1120960358LL, -587898468LL, -1003903613LL, + -825447750LL, -819756819LL, -1008052789LL, -580615857LL, -1123303301LL, -302327454LL, + -1163223360LL, -3453377LL, -1124929110LL, 295958390LL, -1010706164LL, 575714859LL, + -828050730LL, 816842257LL, -589114167LL, 1002881044LL, -309936329LL, 1121022886LL, + -9384104LL, 1163010270LL, 292116282LL, 1125734492LL, 573962943LL, 1011487467LL, + 816787649LL, 827845955LL, 1003797513LL, 587191692LL, 1121949631LL, 305896083LL, + 1162855415LL, 3221670LL, 1123486196LL, -299987081LL, 1006261911LL, -582735496LL, + 819086988LL, -825334929LL, 574751667LL, -1010782472LL, 290101575LL, -1125966955LL, + -15107991LL, -1162614827LL, -319575545LL, -1117906513LL, -601935807LL, -994715974LL, + -842261986LL, -801452079LL, -1023481606LL, -551508157LL, -1132604274LL, -262353923LL, + -1161672696LL, 45670234LL, -1108365744LL, 350774584LL, -976206620LL, 631258482LL, + -774356454LL, 867057617LL, -517003084LL, 1041189615LL, -222383919LL, 1140993224LL, + 88491418LL, 1159069677LL, 393330397LL, 1093854877LL, 670154024LL, 949776739LL, + 898886399LL, 736981279LL, 1062822178LL, 470642089LL, 1149863997LL, 169898275LL, + 1153437077LL, -143506398LL, 1073010452LL, -446787571LL, 914181989LL, -717775777LL, + 688315711LL, -936543256LL, 411752620LL, -1086882405LL, 104647892LL, -1157525357LL, + -210484386LL, -1143011699LL, -510414994LL, -1044135983LL, -772912496LL, -867936849LL, + -978399075LL, -627223001LL, -1111425494LL, -339665705LL, -1161853125LL, -26520156LL, + -1125651244LL, 288933290LL, -1005245271LL, 583114771LL, -809384426LL, 833910062LL, + -552532931LL, 1022343022LL, -253824846LL, 1134028249LL, 64343814LL, 1160291633LL, + 377983596LL, 1098870011LL, 663317359LL, 954131792LL, 898587736LL, 736795995LL, + 1065728678LL, 463165025LL, 1151771855LL, 153923879LL, 1149877142LL, -167407643LL, + 1059903652LL, -476255240LL, 888471895LL, -748868990LL, 648506110LL, -964157330LL, + 358285815LL, -1105334080LL, 40073967LL, -1161248889LL, -281577049LL, -1127294161LL, + -581713943LL, -1005812890LL, -836920890LL, -805969643LL, -1027157134LL, -543088236LL, + -1137348941LL, -237501457LL, -1158608191LL, 87002944LL, -1088977394LL, 405022843LL, + -933636786LL, 691527532LL, -704550649LL, 923833824LL, -419574039LL, 1083416167LL, + -101084161LL, 1157405369LL, 225760702LL, 1139653160LL, 535000677LL, 1031272655LL, + 801937231LL, 840605277LL, 1005115709LL, 582609847LL, 1128067703LL, 277715780LL, + 1160670499LL, -49774029LL, 1100009608LL, -373607614LL, 950668854LL, -667684427LL, + 724417620LL, -908164347LL, 439313331LL, -1075414514LL, 118284919LL, -1155634050LL, + -212693798LL, -1142020620LL, -526696879LL, -1035378223LL, -798037447LL, -844109799LL, + -1004379081LL, -583587824LL, -1128593234LL, -274947017LL, -1160206866LL, 56608548LL, + -1096316046LL, 383850302LL, -941883610LL, 679757368LL, -709388822LL, 919753586LL, + -417850223LL, 1083763881LL, -91295372LL, 1157916819LL, 243201734LL, 1135747251LL, + 557756909LL, 1018792559LL, 826001855LL, 816525310LL, 1025306097LL, 545619935LL, + 1138706749LL, 228607021LL, 1156380042LL, -107978814LL, 1076524851LL, -435807233LL, + 905576374LL, -727134163LL, 657723747LL, -957157551LL, 353764205LL, -1106146434LL, + 19383321LL, -1161159235LL, -316998790LL, -1117199707LL, -626636345LL, -977704837LL, + -882918419LL, -754314834LL, -1063670356LL, -465936291LL, -1153096021LL, -137170650LL, + -1143188924LL, 203764081LL, -1034483813LL, 527444767LL, -836075664LL, 805782751LL, + -564895401LL, 1014472613LL, -244296877LL, 1135135818LL, 97930694LL, 1156968562LL, + 431957330LL, 1077743786LL, 728508110LL, 904071746LL, 961440162LL, 650887325LL, + 1110065671LL, 340199882LL, 1160983686LL, -793011LL, 1109446970LL, -342068878LL, + 959620519LL, -653417099LL, 724508232LL, -907118333LL, 424736246LL, -1080428731LL, + 86806658LL, -1157645052LL, -259224344LL, -1131561107LL, -582413175LL, -1004177738LL, + -853697119LL, -786593611LL, -1048521808LL, -498076767LL, -1149088477LL, -164390758LL, + -1146012702LL, 184482400LL, -1039238081LL, 517023558LL, -838112532LL, 803023598LL, + -560610343LL, 1016339534LL, -231760540LL, 1137307218LL, 118584450LL, 1154586174LL, + 458443523LL, 1066260813LL, 756623393LL, 880088048LL, 985591366LL, 612858248LL, + 1124039187LL, 288917722LL, 1158897439LL, -62020919LL, 1086607489LL, -407586483LL, + 913524013LL, -715730093LL, 655400238LL, -957705462LL, 335992770LL, -1110770931LL, + -15094333LL, -1160357619LL, -365133709LL, -1101494409LL, -681318455LL, -939347183LL, + -933843333LL, -688810942LL, -1098733656LL, -373181824LL, -1160151830LL, -22023256LL, + -1111957029LL, 331581618LL, -958361183LL, 654138149LL, -713608006LL, 914918097LL, + -400693895LL, 1088905472LL, -49241178LL, 1159226393LL, 307283116LL, 1118824387LL, + 634744279LL, 971211423LL, 901612344LL, 730211427LL, 1082016050LL, 418708798LL, + 1158281047LL, 66510675LL, 1122700753LL, -292481048LL, 978358970LL, -623522246LL, + 738912956LL, -894392897LL, 427345538LL, -1078550959LL, 73795519LL, -1157763616LL, + -287332633LL, -1123952367LL, -620705367LL, -980061734LL, -893520694LL, -739854505LL, + -1078753882LL, -426640723LL, -1157865532LL, -71052879LL, -1122697942LL, 291924308LL, + -976362107LL, 626384350LL, -733015164LL, 899054715LL, -416537013LL, 1082625621LL, + -58224782LL, 1158517279LL, 306276367LL, 1118802322LL, 640507961LL, 967080757LL, + 910849372LL, 718206858LL, 1089919592LL, 396881972LL, 1159383742LL, 35240766LL, + 1111873624LL, -330336832LL, 951817206LL, -662873855LL, 695079710LL, -928544662LL, + 367438445LL, -1100136692LL, 2032758LL, -1159844632LL, -363962854LL, -1101267220LL, + -693111334LL, -929957503LL, -951549733LL, -663136901LL, -1112496357LL, -327907107LL, + -1159063055LL, 41436904LL, -1086073907LL, 406891153LL, -900690126LL, 730648109LL, + -621761967LL, 979016611LL, -277959638LL, 1125953612LL, 95136830LL, 1155834444LL, + 458697523LL, 1065162665LL, 774678562LL, 863028453LL, 1009815360LL, 570252017LL, + 1139153128LL, 217286323LL, 1148737250LL, -158915019LL, 1037169470LL, -518746613LL, + 815851604LL, -824118450LL, 507875140LL, -1042503502LL, 145658340LL, -1150434311LL, + -232432682LL, -1136069669LL, -586130613LL, -1000546316LL, -877556688LL, -757956461LL, + -1075296703LL, -433937003LL, -1157822987LL, -63005205LL, -1115886090LL, 315087478LL, + -953605808LL, 659601933LL, -688127906LL, 933206434LL, -347866465LL, 1106045797LL, + 30494330LL, 1159038893LL, 405927630LL, 1086036377LL, 737503469LL, 894589603LL, + 988861329LL, 605229965LL, 1132226244LL, 249319669LL, 1151522043LL, -134307316LL, + 1044228392LL, -503559132LL, 821761743LL, -817700411LL, 508320372LL, -1041862093LL, + 138302900LL, -1150946006LL, -247430323LL, -1132483586LL, -606051070LL, -988118216LL, + -897520486LL, -733529393LL, -1089081438LL, -396788474LL, -1158979846LL, -15311243LL, + -1098988204LL, 368267628LL, -915433116LL, 710847287LL, -628593118LL, 973712488LL, + -270515204LL, 1126937720LL, 118521778LL, 1152839792LL, 494511925LL, 1048075839LL, + 814694800LL, 824131982LL, 1042434745LL, 506127659LL, 1151448787LL, 130051947LL, + 1128891501LL, -261270690LL, 976929392LL, -623037818LL, 712605720LL, -913601240LL, + 365990864LL, -1099286151LL, -23188821LL, -1158337220LL, -410071907LL, -1083524640LL, + -749822185LL, -883091956LL, -1002836451LL, -579915697LL, -1139393937LL, -208953224LL, + -1143198134LL, 186743835LL, -1013383532LL, 561001544LL, -764733690LL, 869910027LL, + -426063624LL, 1076996532LL, -36934964LL, 1157573658LL, 356928529LL, 1101739902LL, + 708998605LL, 915661636LL, 977447725LL, 620964060LL, 1130149867LL, 252280836LL, + 1148575743LL, -146767999LL, 1030104653LL, -528708912LL, 788457699LL, -847858327LL, + 452178027LL, -1065806697LL, 61317185LL, -1156082942LL, -337295155LL, -1107428272LL, + -695644692LL, -925268021LL, -970323608LL, -631182120LL, -1127820357LL, -260414420LL, + -1148660133LL, 142300280LL, -1029878673LL, 528104028LL, -785507966LL, 849938315LL, + -444990757LL, 1068304555LL, -49693244LL, 1156155288LL, 352078890LL, 1102305617LL, + 710966120LL, 912927592LL, 982627883LL, 610920850LL, 1133254779LL, 233211259LL, + 1143831227LL, -173712280LL, 1012604932LL, -559489525LL, 755434747LL, -876120823LL, + 403948279LL, -1083962512LL, 1713105LL, -1156709488LL, -401123044LL, -1084893621LL, + -754069285LL, -877005590LL, -1012632443LL, -558755739LL, -1143964376LL, -169858851LL, + -1131094686LL, 240842938LL, -975196478LL, 621487515LL, -695574451LL, 923745577LL, + -327349616LL, 1108984796LL, 82892053LL, 1153260479LL, 482956114LL, 1050481105LL, + 821670317LL, 813321550LL, 1055448856LL, 471740666LL, 1153946303LL, 69264665LL, + 1104062535LL, -342511851LL, 911762299LL, -710519135LL, 601448054LL, -987060468LL, + 212938120LL, -1136030991LL, -203586100LL, -1137692147LL, -594030534LL, -991363123LL, + -907411944LL, -715653412LL, -1102543330LL, -346176667LL, -1153501501LL, 68984772LL, + -1053144443LL, 475496161LL, -814192438LL, 819869712LL, -467701244LL, 1056521508LL, + -59097910LL, 1153852967LL, 357724941LL, 1098539831LL, 727495794LL, 897438009LL, + 1000903393LL, 576824285LL, 1141213105LL, 179041227LL, 1129267941LL, -243036540LL, + 966185374LL, -632999877LL, 673360535LL, -938445096LL, 289743148LL, -1118048961LL, + -133277457LL, -1147219674LL, -538717020LL, -1021543637LL, -871664986LL, -757535066LL, + -1086746685LL, -390554519LL, -1154362148LL, 29854576LL, -1064836921LL, 446606895LL, + -829893137LL, 802810609LL, -481207497LL, 1049551746LL, -66219049LL, 1152660597LL, + 358269942LL, 1097517999LL, 733845024LL, 891216039LL, 1008528717LL, 561743269LL, + 1144017796LL, 154271554LL, 1121095601LL, -274975299LL, 942445499LL, -666448119LL, + 632442639LL, -965537279LL, 233916927LL, -1130228969LL, -197696261LL, -1137074717LL, + -602028993LL, -984617275LL, -922221275LL, -693761200LL, -1112950042LL, -304999438LL, + -1146908942LL, 127150383LL, -1018804158LL, 541746598LL, -746270367LL, 880008398LL, + -367539942LL, 1093677533LL, 63841670LL, 1151964071LL, 486535884LL, 1046068595LL, + 840117991LL, 790605436LL, 1073738052LL, 421686035LL, 1153491639LL, -8102269LL, + 1067424484LL, -437136606LL, 827421110LL, -803574082LL, 467667298LL, -1054284856LL, + 39868208LL, -1152610400LL, -394122509LL, -1083806846LL, -771221289LL, -857353978LL, + -1036299211LL, -505755880LL, -1150293876LL, -79966613LL, -1096048056LL, 357929550LL, + -880991288LL, 743741991LL, -536232414LL, 1020594997LL, -112154035LL, 1147362646LL, + 328882106LL, 1104859736LL, 721673481LL, 898845638LL, 1007825204LL, 559357499LL, + 1144480203LL, 136428202LL, 1110819470LL, -307215973LL, 911335241LL, -705423601LL, + 575348891LL, -998488750LL, 152801143LL, -1142150896LL, -293097078LL, -1114361129LL, + -695283534LL, -918768900LL, -992936166LL, -584363988LL, -1140718554LL, -161282107LL, + -1115767582LL, 286635588LL, -921334771LL, 691437180LL, -586487004LL, 991373505LL, + -161865476LL, 1140365203LL, 287895407LL, 1115165385LL, 693966967LL, 919092752LL, + 993864249LL, 581720966LL, 1141109718LL, 154524048LL, 1112521434LL, -296898500LL, + 911970693LL, -702855437LL, 569984939LL, -1000328592LL, 139208257LL, -1142805874LL, + -313623356LL, -1107641210LL, -717981864LL, -899764212LL, -1010539386LL, -551116374LL, + -1145139188LL, -115851345LL, -1100168105LL, 337997606LL, -882139704LL, 739114050LL, + -524878231LL, 1024115037LL, -84380008LL, 1147623004LL, 369885400LL, 1089584414LL, + 765896097LL, 858641194LL, 1040510432LL, 490971487LL, 1149595105LL, 44730996LL, + 1075215537LL, -409069013LL, 828702545LL, -797832050LL, 449054301LL, -1059008260LL, + -3124940LL, -1150205924LL, -455225781LL, -1056239900LL, -834266028LL, -791665471LL, + -1078696135LL, -398768286LL, -1148465156LL, 59152726LL, -1031690413LL, 507895526LL, + -746804068LL, 874357195LL, -339772319LL, 1098475145LL, 123216441LL, 1143148700LL, + 566449631LL, 1000493226LL, 917057108LL, 693354998LL, 1117029820LL, 271780572LL, + 1132902888LL, -195036372LL, 961473779LL, -630052875LL, 630560539LL, -961085154LL, + 194615038LL, -1132833432LL, -274139800LL, -1116213162LL, -697623461LL, -913403706LL, + -1004906413LL, -557719283LL, -1144147009LL, -108262063LL, -1091439357LL, 359806882LL, + -855046210LL, 767793637LL, -474247897LL, 1046715164LL, -12937623LL, 1149030581LL, + 451014562LL, 1056854664LL, 838873920LL, 785217157LL, 1084427922LL, 379754207LL, + 1145368508LL, -90840878LL, 1010700717LL, -546380059LL, 702861459LL, -908823942LL, + 274121608LL, -1115689296LL, -202177981LL, -1130911719LL, -644107484LL, -951260552LL, + -975234349LL, -607144667LL, -1137895139LL, -157602652LL, -1103340423LL, 319722841LL, + -876951252LL, 741943128LL, -497559299LL, 1035325820LL, -30918916LL, 1148238574LL, + 441596133LL, 1060351282LL, 837145624LL, 786437838LL, 1085971538LL, 374044615LL, + 1143784018LL, -104636846LL, 999771916LL, -565327231LL, 678768196LL, -926477863LL, + 237116401LL, -1123749380LL, -247102502LL, -1121573494LL, -687809587LL, -919703784LL, + -1006228746LL, -553526385LL, -1145030385LL, -88000477LL, -1078768667LL, 393761226LL, + -818692864LL, 805284342LL, -410999341LL, 1072274002LL, 71238730LL, 1146109965LL, + 541079997LL, 1012830827LL, 913363283LL, 695925245LL, 1120185040LL, 252349324LL, + 1123386662LL, -237585793LL, 921738078LL, -684684585LL, 551441099LL, -1007102655LL, + 79780605LL, -1145393623LL, -406992473LL, -1073590475LL, -819385535LL, -804235045LL, + -1081139387LL, -386355970LL, -1143418234LL, 103315256LL, -994059216LL, 574343876LL, + -660105783LL, 939270778LL, -203073612LL, 1129900117LL, 292254998LL, 1110154681LL, + 733491896LL, 883056387LL, 1037879912LL, 490454994LL, 1147890287LL, 5469542LL, + 1042228171LL, -481022922LL, 740117519LL, -877376009LL, 297976104LL, -1108472952LL, + -200980625LL, -1130065384LL, -662319057LL, -937396897LL, -998250466LL, -566404086LL, + -1144401753LL, -87177927LL, -1072279066LL, 409158281LL, -794988316LL, 827722068LL, + -365035488LL, 1088033356LL, 135464810LL, 1139585012LL, 610377251LL, 971792985LL, + 967990656LL, 616338796LL, 1138786288LL, 141360787LL, 1089077378LL, -361476883LL, + 827821186LL, -794610329LL, 405196214LL, -1073521527LL, -96875824LL, -1143322837LL, + -580505945LL, -989709666LL, -950895409LL, -642068142LL, -1134971488LL, -168034145LL, + -1095928950LL, 339527234LL, -840760571LL, 780644032LL, -419204789LL, 1067940313LL, + 85783232LL, 1144035628LL, 574246409LL, 993159571LL, 948980187LL, 644601923LL, + 1134930213LL, 167213245LL, 1094353135LL, -344051806LL, 834654223LL, -786948641LL, + 407241711LL, -1072402610LL, -102478786LL, -1142519413LL, -592058722LL, -982486854LL, + -962568175LL, -623891072LL, -1138645273LL, -138673601LL, -1083959983LL, 375156446LL, + -808893653LL, 813248555LL, -368776707LL, 1086121013LL, 147068306LL, 1137541836LL, + 633345851LL, 956285212LL, 990257616LL, 578773330LL, 1144052190LL, 81951790LL, + 1062410604LL, -432250546LL, 761429838LL, -857769914LL, 302659437LL, -1106314653LL, + -219312897LL, -1125801662LL, -696262344LL, -911450192LL, -1028755331LL, -507135148LL, + -1146949718LL, 3398952LL, -1025470694LL, 513747158LL, -688980089LL, 916970261LL, + -207461111LL, 1128049272LL, 318215554LL, 1101945362LL, 777321095LL, 843402736LL, + 1072600255LL, 406323076LL, 1140977825LL, -117280695LL, 967208664LL, -616530485LL, + 587484059LL, -985131421LL, 82104710LL, -1144072074LL, -441344761LL, -1058715784LL, + -870829254LL, -746555015LL, -1113875161LL, -273852384LL, -1117609185LL, 258242079LL, + -880456129LL, 735230330LL, -452868267LL, 1053900048LL, 73202940LL, 1144755647LL, + 583942814LL, 987352435LL, 968255694LL, 615114127LL, 1141994849LL, 108457828LL, + 1066543392LL, -422411734LL, 757611208LL, -861395986LL, 282200991LL, -1111922541LL, + -255731096LL, -1118321070LL, -737895947LL, -878396869LL, -1057677433LL, -444320505LL, + -1143809351LL, 88503016LL, -976444785LL, 602260753LL, -591955520LL, 982741197LL, + -75257915LL, 1144795287LL, 458770809LL, 1051559265LL, 890758951LL, 723064733LL, + 1123562433LL, 232179005LL, 1104253976LL, -311363397LL, 836371874LL, -785384786LL, + 379548357LL, -1082733629LL, -163548933LL, -1135623786LL, -670154253LL, -931290566LL, + -1025128263LL, -515304458LL, -1147216616LL, 18358725LL, -1007835708LL, 548384081LL, + -638002451LL, 953637363LL, -121679428LL, 1140910781LL, 423098413LL, 1066527769LL, + 871118674LL, 746763000LL, 1118802287LL, 254542083LL, 1108295722LL, -296979613LL, + 841209581LL, -780312377LL, 378692288LL, -1083104995LL, -172340642LL, -1134383092LL, + -683776673LL, -921399232LL, -1036065059LL, -493047568LL, -1146260195LL, 51115768LL, + -987750732LL, 583841837LL, -596937717LL, 979890194LL, -65133537LL, 1145544788LL, + 482581030LL, 1040973522LL, 916693761LL, 690056038LL, 1133932737LL, 175200687LL, + 1082000133LL, -381795742LL, 772407371LL, -848452937LL, 278207299LL, -1113139399LL, + -283013366LL, -1111924054LL, -776979626LL, -844255561LL, -1084851682LL, -373570534LL, + -1131944157LL, 187494505LL, -906072314LL, 703902562LL, -460966755LL, 1050690324LL, + 96247892LL, 1143316307LL, 630659089LL, 958488947LL, 1012181753LL, 540293494LL, + 1147312491LL, -10050903LL, 1002252191LL, -558494971LL, 611631445LL, -970738571LL, + 70526250LL, -1145187342LL, -488470537LL, -1038184719LL, -927647496LL, -675207764LL, + -1138151577LL, -145094223LL, -1067150666LL, 421471618LL, -731361528LL, 884063538LL, + -213417358LL, 1127351713LL, 358223963LL, 1090026137LL, 841009344LL, 780511968LL, + 1113855396LL, 275386663LL, 1107674576LL, -299309948LL, 823129882LL, -799378574LL, + 330993765LL, -1098641553LL, -245186495LL, -1120926691LL, -759942261LL, -859712407LL, + -1082594510LL, -380306476LL, -1130564433LL, 196203329LL, -890761112LL, 723357191LL, + -423446308LL, 1066501261LL, 152620905LL, 1137308512LL, 690175518LL, 916763263LL, + 1051051160LL, 460568206LL, 1141808956LL, -114627466LL, 938176094LL, -660854922LL, + 491842643LL, -1036837355LL, -82354774LL, -1144638166LL, -635768662LL, -955413810LL, + -1024359283LL, -517440149LL, -1146285952LL, 55892184LL, -968837018LL, 615215038LL, + -537518212LL, 1014025709LL, 35298858LL, 1147156061LL, 599425863LL, 978744300LL, + 1006157820LL, 552210511LL, 1147563794LL, -20613952LL, 985365654LL, -588573626LL, + 561618406LL, -1000992003LL, -11864643LL, -1147734373LL, -582777074LL, -988857592LL, + -998681983LL, -565804614LL, -1147801748LL, 9071917LL, -989299670LL, 582105017LL, + -564789010LL, 999300068LL, 12254061LL, 1147807633LL, 586578226LL, 986692343LL, + 1002837357LL, 558546508LL, 1147700656LL, -21427814LL, 980956060LL, -596169322LL, + 547007037LL, -1009202811LL, -36607117LL, -1147335559LL, -610800609LL, -971931621LL, + -1018221165LL, -530057654LL, -1146472482LL, 57799428LL, -959381860LL, 630339827LL, + -507546869LL, 1029629741LL, 84999537LL, 1144776458LL, 654593888LL, 942994809LL, + 1043074306LL, 479291324LL, 1141817332LL, -118180876LL, 922388579LL, -683300669LL, + 445084982LL, -1058104188LL, -157284269LL, -1137070415LL, -716119026LL, -897118268LL, + -1074166996LL, -404711015LL, -1129918289LL, 202204145LL, -866685251LL, 752617287LL, + -357956608LL, 1090603356LL, 252772283LL, 1119654269LL, 792260548LL, 830549308LL, + 1106642243LL, 304630863LL, 1105488138LL, -308739205LL, 788144039LL, -834397249LL, + 244585961LL, -1121397569LL, -369753484LL, -1086554857LL, -878245655LL, -738896079LL, + -1133866884LL, -177741685LL, -1061927037LL, 435339342LL, -682248562LL, 922881023LL, + -104113249LL, 1142933131LL, 504873132LL, 1030632009LL, 967224447LL, 617689270LL, + 1147370584LL, 23842261LL, 991674364LL, -577559488LL, 544783750LL, -1010034586LL, + -62769628LL, -1145856189LL, -652408252LL, -944064782LL, -1049903704LL, -463213519LL, + -1136987622LL, 155225103LL, -886855905LL, 728213538LL, -372819198LL, 1085259649LL, + 252794668LL, 1119309410LL, 803536681LL, 819185789LL, 1114375628LL, 273648060LL, + 1091348431LL, -354480752LL, 740329218LL, -876695135LL, 166005028LL, -1135389715LL, + -458984435LL, -1051659932LL, -945759742LL, -649756717LL, -1146336140LL, -50505571LL, + -998884935LL, 564677291LL, -547200554LL, 1008563048LL, 71871675LL, 1145190262LL, + 669581407LL, 931819450LL, 1062721592LL, 432726323LL, 1129928968LL, -199735498LL, + 849495264LL, -771361109LL, 306807840LL, -1105675089LL, -331239605LL, -1098607697LL, + -867330344LL, -751271217LL, -1134745327LL, -170402095LL, -1049454654LL, 464051493LL, + -636932824LL, 954479928LL, -25019922LL, 1147217169LL, 595337879LL, 980981750LL, + 1029528884LL, 506796804LL, 1140443324LL, -127213069LL, 892110495LL, -721772405LL, + 361815619LL, -1089003800LL, -283511858LL, -1111973428LL, -839571617LL, -782309477LL, + -1129349457LL, -203675592LL, -1059706449LL, 440411172LL, -651738171LL, 944565156LL, + -34880521LL, 1147072735LL, 593776609LL, 982063447LL, 1032305476LL, 501389671LL, + 1138920084LL, -141188700LL, 878175297LL, -738856132LL, 333222759LL, -1098221207LL, + -320249235LL, -1102086454LL, -870379993LL, -748077238LL, -1137816306LL, -150271500LL, + -1034450573LL, 497137664LL, -592899067LL, 982715972LL, 43281366LL, 1146914380LL, + 665889061LL, 934827926LL, 1070084753LL, 415036703LL, 1121943868LL, -242082389LL, + 803228754LL, -819884331LL, 218287948LL, -1126837029LL, -439652519LL, -1060255310LL, + -952074190LL, -641104153LL, -1147789540LL, -7932875LL, -960456682LL, 628514547LL, + -451559171LL, 1055284604LL, 209262174LL, 1128611652LL, 800416009LL, 822747070LL, + 1122603230LL, 239508128LL, 1066247376LL, -425138071LL, 649223167LL, -946656709LL, + 11744732LL, -1147839562LL, -630353064LL, -959350181LL, -1058523877LL, -444127638LL, + -1126042903LL, 223101387LL, -808700032LL, 814724571LL, -214004204LL, 1127829536LL, + 454748697LL, 1054052505LL, 967710380LL, 617564508LL, 1147533942LL, -32277981LL, + 931043615LL, -671610760LL, 391959437LL, -1079026764LL, -283667338LL, -1112426208LL, + -861320299LL, -759022656LL, -1139387511LL, -140760537LL, -1019819295LL, 527272205LL, + -543215686LL, 1011431957LL, 124382694LL, 1141331635LL, 748924788LL, 870202418LL, + 1110288460LL, 292288037LL, 1080089258LL, -389374712LL, 667781258LL, -933973711LL, + 18331474LL, -1148014107LL, -638275783LL, -954416401LL, -1068291032LL, -420827255LL, + -1117575913LL, 263439722LL, -767312382LL, 854191801LL, -141754069LL, 1139453210LL, + 535328869LL, 1015828293LL, 1020439397LL, 526520849LL, 1138025151LL, -153155230LL, + 844434526LL, -778155155LL, 244710401LL, -1121940114LL, -444430542LL, -1058844804LL, + -972598833LL, -610541324LL, -1146758802LL, 60763307LL, -902176583LL, 710538142LL, + -327075695LL, 1100839701LL, 368592002LL, 1087661007LL, 929434691LL, 674579985LL, + 1148386159LL, 12540493LL, 943526903LL, -654787511LL, 389330546LL, -1080487760LL, + -309789725LL, -1105941032LL, -894481693LL, -720431673LL, -1146637111LL, -66239503LL, + -971103964LL, 613325016LL, -432191442LL, 1064174997LL, 269248811LL, 1116607225LL, + 870253972LL, 749676539LL, 1144277686LL, 100186918LL, 986924368LL, -587743931LL, + 456324464LL, -1054175709LL, -247680455LL, -1121708883LL, -858358005LL, -763451568LL, + -1143074401LL, -114370168LL, -992249755LL, 578969439LL, -462144015LL, 1051787313LL, + 245453815LL, 1122344689LL, 859578941LL, 762301794LL, 1143778969LL, 108756203LL, + 987494576LL, -587362414LL, 449693464LL, -1057355966LL, -262691628LL, -1118619075LL, + -873922171LL, -746102774LL, -1146115814LL, -83221849LL, -972184587LL, 612753505LL, + -418607956LL, 1070272857LL, 299280699LL, 1109621176LL, 900597524LL, 714050679LL, + 1148761732LL, 37572872LL, 944960948LL, -654400380LL, 368159830LL, -1088935298LL, + -354794344LL, -1093425030LL, -937945064LL, -664723117LL, -1149321390LL, 28343834LL, + -903637942LL, 710866748LL, -297395312LL, 1110677193LL, 428322608LL, 1067120846LL, + 983306281LL, 596221273LL, 1144309894LL, -114430006LL, 845327692LL, -779828852LL, + 205369908LL, -1131685390LL, -518215746LL, -1026899031LL, -1032861000LL, -506410444LL, + -1129172283LL, 220024856LL, -766660104LL, 857825164LL, -91496638LL, 1146932315LL, + 621748744LL, 968220100LL, 1081458084LL, 393279505LL, 1098376590LL, -343496798LL, + 664125468LL, -939979371LL, -43990797LL, -1150170800LL, -734736441LL, -886112762LL, + -1122493393LL, -255437516LL, -1045637642LL, 481755631LL, -534576139LL, 1019746046LL, + 199461721LL, 1134052796LL, 851140639LL, 775646296LL, 1147898332LL, 92754392LL, + 964326741LL, -629725040LL, 375904489LL, -1088751739LL, -371234792LL, -1090446233LL, + -962748995LL, -632617586LL, -1148332034LL, 92870907LL, -848132967LL, 779846821LL, + -187904103LL, 1136828917LL, 552904851LL, 1011029036LL, 1059023786LL, 454473188LL, + 1113668259LL, -296668704LL, 692011529LL, -921726480LL, -26732711LL, -1152360077LL, + -734768998LL, -888228588LL, -1127264111LL, -241447182LL, -1033881696LL, 510189887LL, + -493434307LL, 1042070507LL, 261368141LL, 1123056799LL, 903506154LL, 716541900LL, + 1153213771LL, -2166024LL, 900394822LL, -720698974LL, 253870390LL, -1125097672LL, + -504506186LL, -1037280641LL, -1042314771LL, -494206859LL, -1122354296LL, 266769814LL, + -707887477LL, 911003278LL, 19634933LL, 1153618121LL, 739248946LL, 885958634LL, + 1131785514LL, 225095417LL, 1021739133LL, -536520224LL, 456510956LL, -1060002423LL, + -313082558LL, -1110942770LL, -943476931LL, -665039736LL, -1151665543LL, 79437707LL, + -842776603LL, 789046520LL, -154186385LL, 1144256241LL, 604713534LL, 983693413LL, + 1091091652LL, 378275557LL, 1083734756LL, -399176257LL, 584385150LL, -996279774LL, + -181380840LL, -1140808758LL, -865316179LL, -765404117LL, -1154687995LL, -39885860LL, + -915727231LL, 704717266LL, -256348545LL, 1126837899LL, 521650831LL, 1031339910LL, + 1060190232LL, 460531837LL, 1109823016LL, -323581431LL, 645979394LL, -958879350LL, + -117945491LL, -1150287926LL, -827958941LL, -807402756LL, -1153254795LL, -88132653LL, + -940763175LL, 673115196LL, -288076944LL, 1120487768LL, 500389476LL, 1043292493LL, + 1054800263LL, 476044650LL, 1113460593LL, -315920892LL, 647059348LL, -959842592LL, + -125717170LL, -1150897956LL, -839883582LL, -797093143LL, -1156283101LL, -64540191LL, + -923102054LL, 699596566LL, -249653347LL, 1131204977LL, 543857887LL, 1023020197LL, + 1078009549LL, 425027484LL, 1095719039LL, -377563872LL, 586752978LL, -999638646LL, + -205470744LL, -1140938052LL, -899468431LL, -731652190LL, -1159193559LL, 32060713LL, + -857294144LL, 781154161LL, -138564319LL, 1151672855LL, 648486420LL, 961981669LL, + 1120120025LL, 302761903LL, 1044715887LL, -505262110LL, 457402493LL, -1066718593LL, + -355172397LL, -1105142377LL, -993975368LL, -599898762LL, -1143483368LL, 201709477LL, + -728212957LL, 904609918LL, 48093071LL, 1160460922LL, 801453160LL, 840845864LL, + 1157215704LL, 102784261LL, 936811120LL, -687356773LL, 248394566LL, -1135224353LL, + -565114253LL, -1015597585LL, -1096217941LL, -386595652LL, -1077122306LL, 437394946LL, + -515637189LL, 1042104493LL, 306691848LL, 1121677584LL, 974898253LL, 634154373LL, + 1149875599LL, -175282279LL, 741152214LL, -896656450LL, -45199690LL, -1162592334LL, + -809423416LL, -835981960LL, -1160911653LL, -81783745LL, -918310645LL, 715183229LL, + -204163901LL, 1146071903LL, 615822014LL, 988086447LL, 1119417388LL, 320702983LL, + 1045502827LL, -513098924LL, 430422094LL, -1082354826LL, -408623786LL, -1090962071LL, + -1036313717LL, -532588518LL, -1125037984LL, 303841837LL, -626697419LL, 982712206LL, + 200026186LL, 1148439650LL, 922929504LL, 712451096LL, 1161979412LL, -98276013LL, + 789734562LL, -858288753LL, 480725LL, -1166524721LL, -790018658LL, -858602210LL, + -1163060926LL, -95484553LL, -919228710LL, 719280140LL, -186133208LL, 1152485956LL, + 647116818LL, 971927233LL, 1135771398LL, 271968117LL, 1017088342LL, -574476030LL, + 352664843LL, -1113855465LL, -502197370LL, -1055180569LL, -1087646935LL, -428018755LL, + -1086726322LL, 431015914LL, -497929987LL, 1058013161LL, 361565890LL, 1112284652LL, + 1025772901LL, 562388513LL, 1132437033LL, -294386569LL, 621460904LL, -991691212LL, + -229927938LL, -1147775041LL, -956475082LL, -675277506LL, -1158888444LL, 168557495LL, + -724018983LL, 920771115LL, 110568971LL, 1166355322LL, 885165992LL, 767904004LL, + 1170735049LL, -56191157LL, 807179082LL, -850188029LL, -5595640LL, -1172562616LL, + -816308528LL, -842109291LL, -1172343137LL, -41095451LL, -872968878LL, 783944029LL, + -83800843LL, 1170547643LL, 753460143LL, 900032992LL, 1167610906LL, 122472046LL, + 923571382LL, -725175610LL, 157086751LL, -1163929999LL, -699365519LL, -943842899LL, + -1159862513LL, -187642728LL, -961089849LL, 676264577LL, -214151326LL, 1155725313LL, + 656071229LL, 975533077LL, 1151794651LL, 236631610LL, 987368725LL, -638951562LL, + 255106130LL, -1148306528LL, -625041864LL, -996765584LL, -1145456192LL, -269597366LL, + -1003861977LL, 614450791LL, -280123823LL, 1143397687LL, 607262054LL, 1008763126LL, + 1142244363LL, 286696827LL, 1011539953LL, -603536575LL, 289318970LL, -1142069293LL, + -603313100LL, -1012228287LL, -1142904589LL, -287983315LL, -1010827508LL, 606608128LL, + -282672301LL, 1144740451LL, 613416232LL, 1007299441LL, 1147525085LL, 273357276LL, + 1001568748LL, -623709858LL, 259999870LL, -1151164584LL, -637437329LL, -993523851LL, + -1155521507LL, -242554271LL, -983017186LL, 654520098LL, -220969151LL, 1160413225LL, + 674850530LL, 969865804LL, 1165611452LL, 195190210LL, 953853859LL, -698289337LL, + 165164914LL, -1170842008LL, -724661039LL, -934735942LL, -1175783407LL, -130848245LL, + -912239749LL, 753748957LL, -92207991LL, 1180065380LL, 785290872LL, 886070069LL, + 1183269834LL, 49230794LL, 855912217LL, -818979070LL, 1929365LL, -1184914874LL, + -854435772LL, -821447654LL, -1184539376LL, 49645969LL, -782337659LL, 891244457LL, + 105400150LL, 1181537105LL, 928907061LL, 738270174LL, 1175328355LL, -165185585LL, + 688933613LL, -966863534LL, -228788632LL, -1165281572LL, -1004479062LL, -634047898LL, + -1150736421LL, 295919256LL, -573372461LL, 1041043506LL, 366200830LL, 1131011265LL, + 1075770700LL, 506720355LL, 1105414762LL, -439159925LL, 433974745LL, -1107800003LL, + -514215309LL, -1073259447LL, -1136198663LL, -355106596LL, -1033876568LL, 590668026LL, + -270192050LL, 1159967068LL, 667694150LL, 986633846LL, 1178048316LL, 179430815LL, + 930957129LL, -744339259LL, 83165990LL, -1189341143LL, -819514459LL, -866354613LL, + -1192715825LL, 18096454LL, -792442688LL, 891995912LL, 123670038LL, 1187034640LL, + 960429434LL, 708974315LL, 1171178046LL, -232671610LL, 615870290LL, -1023339878LL, + -344006910LL, -1144075665LL, -1079145448LL, -513251705LL, -1104741511LL, 456359966LL, + -401472104LL, 1126178729LL, 568188261LL, 1052314231LL, 1162715885LL, 281149080LL, + 986102702LL, -677724200LL, 153194686LL, -1187013843LL, -782983631LL, -905635485LL, + -1197355190LL, -18842159LL, -810712368LL, 881783707LL, 120333698LL, 1192101753LL, + 971772297LL, 701457325LL, 1169757397LL, -262403828LL, 578371748LL, -1050469466LL, + -405081631LL, -1129038618LL, -1115321383LL, -442384755LL, -1068950979LL, 545732260LL, + -294897061LL, 1163768096LL, 681397748LL, 988870303LL, 1193326062LL, 137815824LL, + 888626749LL, -808839573LL, -26422424LL, -1201684198LL, -924599938LL, -768587772LL, + -1186811343LL, 194845361LL, -629735075LL, 1025083995LL, 363959748LL, 1147073514LL, + 1106664586LL, 473731487LL, 1081358370LL, -529790707LL, 302973146LL, -1165808547LL, + -687948042LL, -989201554LL, -1199222332LL, -120620368LL, -870908343LL, 833723107LL, + 69399730LL, 1204014816LL, 962218764LL, 727664410LL, 1177873635LL, -262424141LL, + 561628683LL, -1068512081LL, -453123043LL, -1119248110LL, -1147847313LL, -375998922LL, + -1027529681LL, 635612257LL, -175039858LL, 1195856337LL, 803613367LL, 903220708LL, + 1208801641LL, -35934450LL, 748081418LL, -950661751LL, -250631294LL, -1183832420LL, + -1070359859LL, -565241466LL, -1119241149LL, 461911029LL, -359261436LL, 1156671896LL, + 661986209LL, 1014707360LL, 1204253118LL, 136131684LL, 871513674LL, -842689284LL, + -96802415LL, -1208800503LL, -995805522LL, -692714551LL, -1167406790LL, 331000754LL, + -483236811LL, 1113465561LL, 556982774LL, 1078899442LL, 1188588044LL, 249893579LL, + 944138324LL, -764682622LL, 1293956LL, -1215333608LL, -943871003LL, -766259189LL, + -1189672198LL, 252362877LL, -550787635LL, 1084719642LL, 499628179LL, 1109656957LL, + 1178350170LL, 305697831LL, 976000407LL, -728275979LL, 41244883LL, -1217486620LL, + -925895347LL, -792284279LL, -1197073876LL, 230308668LL, -565140659LL, 1080594523LL, + 495169208LL, 1114865587LL, 1181783854LL, 304241120LL, 971917678LL, -738659711LL, + 22082681LL, -1220995205LL, -946028264LL, -772936173LL, -1192682854LL, 266454084LL, + -526424398LL, 1103387811LL, 544783991LL, 1094943353LL, 1198740322LL, 244583265LL, + 930084741LL, -795522247LL, -57071511LL, -1223018715LL, -1001583926LL, -704971213LL, + -1171065777LL, 360397001LL, -431074740LL, 1147425183LL, 645613958LL, 1042460294LL, + 1220349405LL, 124179002LL, 842095356LL, -892570288LL, -196299412LL, -1211778290LL, + -1082216195LL, -580415420LL, -1118371965LL, 508381267LL, -273232604LL, 1198200201LL, + 788959567LL, 942875153LL, 1228465337LL, -58931767LL, 694567792LL, -1015530940LL, + -391999870LL, -1166700130LL, -1168114116LL, -389212142LL, -1013485763LL, 699960531LL, + -48417872LL, 1231207976LL, 956887257LL, 776982117LL, 1195609384LL, -301608578LL, + 473012139LL, -1139220135LL, -631907713LL, -1059890480LL, -1228129235LL, -124438797LL, + -831333821LL, 913116170LL, 240215795LL, 1211735877LL, 1118163397LL, 526145186LL, + 1086941827LL, -588886391LL, 168808865LL, -1225090382LL, -888708866LL, -860613067LL, + -1219710876LL, 209480319LL, -549891310LL, 1109197015LL, 573281355LL, 1097803712LL, + 1225571535LL, 181465853LL, 866522778LL, -886132240LL, -210270947LL, -1221892502LL, + -1114287386LL, -544746757LL, -1093608584LL, 586143101LL, -162169086LL, 1230614127LL, + 906006299LL, 849139569LL, 1218213823LL, -242951818LL, 510161104LL, -1133137865LL, + -627309116LL, -1073291666LL, -1238752610LL, -110366411LL, -806813286LL, 947084765LL, + 307363033LL, 1206103358LL, 1163086809LL, 444565403LL, 1033587333LL, -695248551LL, + 25384042LL, -1245915358LL, -1006020910LL, -736314848LL, -1180486621LL, 402478737LL, + -345715840LL, 1198887099LL, 786627228LL, 969221709LL, 1245331969LL, -93037362LL, + 633280182LL, -1076944369LL, -525739639LL, -1133934029LL, -1232430640LL, -211396763LL, + -873384030LL, 895627520LL, 243841896LL, 1227547289LL, 1150931743LL, 493029404LL, + 1057079090LL, -672088804LL, 40531088LL, -1252549711LL, -1013115622LL, -738599893LL, + -1180710029LL, 423404244LL, -311850475LL, 1215530681LL, 832802952LL, 939481899LL, + 1245107405LL, -165283019LL, 558146690LL, -1125836991LL, -624004371LL, -1091367074LL, + -1254593353LL, -88806047LL, -771137618LL, 994316479LL, 399872878LL, 1193669656LL, + 1215939600LL, 328120042LL, 946030959LL, -832239478LL, -171973720LL, -1248777864LL, + -1137382601LL, -544797730LL, -1081103386LL, 650446379LL, -50147942LL, 1261257403LL, + 1027765678LL, 733758649LL, 1177151107LL, -458734737LL, 259143355LL, -1237087255LL, + -895846705LL, -892421860LL, -1236891463LL, 265473480LL, -449833511LL, 1182981952LL, + 749784261LL, 1020314577LL, 1264377127LL, -77415962LL, 619035435LL, -1105832623LL, + -596795999LL, -1118631885LL, -1264466039LL, -100326869LL, -765294215LL, 1012278371LL, + 442970009LL, 1189794020LL, 1242373232LL, 264192860LL, 888566542LL, -908407138LL, + -293202554LL, -1237036719LL, -1203316353LL, -411995232LL, -989892445LL, 799572191LL, + 151232674LL, 1264054576LL, 1152255482LL, 542702120LL, 1071082203LL, -690307744LL, + -19744770LL, -1274710235LL, -1093719818LL, -656199414LL, -1134436166LL, 584320390LL, + -99486785LL, 1272809203LL, 1031708829LL, 753055591LL, 1182507132LL, -484537834LL, + 205432567LL, -1261939093LL, -969653011LL, -834305987LL, -1217908384LL, 393192506LL, + -297639208LL, 1245361878LL, 910418963LL, 901261539LL, 1243165699LL, -311927192LL, + 376068520LL, -1225952785LL, -856344476LL, -955349649LL, -1260608428LL, 241905485LL, + -440952136LL, 1206170592LL, 809291156LL, 997982609LL, 1272293007LL, -183922040LL, + 492665748LL, -1188053947LL, -770704320LL, -1030456479LL, -1279951629LL, 138500462LL, + -531624438LL, 1173228785LL, 741672101LL, 1053870839LL, 1284959034LL, -105980466LL, + 558198979LL, -1162925394LL, -722977664LL, -1069072005LL, -1288311162LL, 86584704LL, + -572652199LL, 1157991713LL, 715140064LL, 1076608521LL, 1290610599LL, -80471210LL, + 575094372LL, -1158906053LL, -718440498LL, -1076704210LL, -1292055110LL, 87761730LL, + -565457030LL, 1165777106LL, 732931674LL, 1069237916LL, 1292427142LL, -108554278LL, + 543485353LL, -1178339059LL, -758428830LL, -1053739689LL, -1291083843LL, 142908350LL, + -508750209LL, 1195930562LL, 794481753LL, 1029393433LL, 1286948973LL, -190813262LL, + 460681806LL, -1217470779LL, -840328227LL, -995061356LL, -1278509952LL, 252125671LL, + -398627550LL, 1241421992LL, 894830705LL, 949320319LL, 1263825198LL, -326490662LL, + 321936866LL, -1265758954LL, -956399869LL, -890531063LL, -1240548632LL, 413231121LL, + -230075279LL, 1287935327LL, 1022911000LL, 816928318LL, 1205979678LL, -511226473LL, + 122768734LL, -1304875894LL, -1091621741LL, -726757401LL, -1157147896LL, 618771041LL, + -177026LL, 1312963847LL, 1159102628LL, 618440906LL, 1090941502LL, -733413873LL, + -136907883LL, -1308194642LL, -1221194570LL, -490780646LL, -1004288107LL, 851852002LL, + 286846753LL, 1286090143LL, 1273009973LL, 343240361LL, 894394035LL, -969784945LL, + -446933919LL, -1242064233LL, -1308996310LL, -176200464LL, -759045185LL, 1081853791LL, + 613192379LL, 1171574617LL, 1323082265LL, -8718183LL, 596967509LL, -1181642685LL, + -780207624LL, -1070490289LL, -1308926876LL, 208340044LL, -408238050LL, 1261767907LL, + 941031814LL, 935520431LL, 1260290450LL, -417651665LL, 194727648LL, -1314106425LL, + -1087197297LL, -764742895LL, -1171541300LL, 629573705LL, 39456981LL, 1330175512LL, + 1208885272LL, 558196007LL, 1038302524LL, -834858734LL, -287581137LL, -1301709037LL, + -1295299201LL, -318514874LL, -858226133LL, 1022163185LL, 540009242LL, 1221431184LL, + 1335290097LL, 51536448LL, 631855913LL, -1178381289LL, -784140181LL, -1084036117LL, + -1318267479LL, 233203127LL, -363505394LL, 1289300662LL, 1004654523LL, 887320450LL, + 1235401162LL, -522210437LL, 62035727LL, -1340648069LL, -1184179261LL, -633391126LL, + -1081072372LL, 798147072LL, 258623521LL, 1319535017LL, 1304456871LL, 329793270LL, + 854468688LL, -1040468988LL, -579399518LL, -1216271754LL, -1348058729LL, 9635084LL, + -561141936LL, 1226708797LL, 876645385LL, 1026416879LL, 1300604934LL, -364435478LL, + 214273065LL, -1334475232LL, -1123525589LL, -752848344LL, -1153346243LL, 707982134LL, + 164670576LL, 1344131170LL, 1292318392LL, 407529369LL, 905839097LL, -1008954077LL, + -546223515LL, -1241991513LL, -1357615754LL, -12577591LL, -568318473LL, 1233967267LL, + 894463738LL, 1023711947LL, 1300234427LL, -399802211LL, 163268342LL, -1351371688LL, + -1170015752LL, -697386513LL, -1111450579LL, 788922647LL, 274366884LL, 1335999952LL, + 1334543132LL, 285720036LL, 796955469LL, -1109048775LL, -698862344LL, -1174403299LL, + -1356493937LL, 173435148LL, -379735412LL, 1314724486LL, 1057676724LL, 869818213LL, + 1217523004LL, -628877011LL, -99043018LL, -1367714895LL, -1297804225LL, -445850280LL, + -918635121LL, 1020701509LL, 582042369LL, 1244833587LL, 1374163975LL, -52309054LL, + 484743593LL, -1287936704LL, -1001317619LL, -945425168LL, -1259077885LL, 560276147LL, + 33866015LL, 1378684510LL, 1287566346LL, 496820991LL, 951232181LL, -1001280657LL, + -564591480LL, -1261505007LL, -1382377310LL, 44136005LL, -481970875LL, 1297450598LL, + 1020999945LL, 935945077LL, 1251763733LL, -595215773LL, -83438845LL, -1384554681LL, + -1316648045LL, -439488117LL, -898256520LL, 1059529989LL, 651560442LL, 1227881453LL, + 1382713203LL, -151928687LL, 368164126LL, -1342455635LL, -1114449555LL, -835756204LL, + -1186325592LL, 732033969LL, 249352403LL, 1372524827LL, 1370297187LL, 266552119LL, + 745173037LL, -1181630693LL, -833696539LL, -1122168180LL, -1347871902LL, 374619408LL, + -133430189LL, 1393590020LL, 1254920077LL, 622803187LL, 1029404464LL, -951767146LL, + -525175317LL, -1300986989LL, -1403653361LL, 31506365LL, -465181582LL, 1325789856LL, + 1079023583LL, 901508043LL, 1222799723LL, -696192942LL, -226701797LL, -1389771350LL, + -1383068965LL, -270058614LL, -732324692LL, 1205190327LL, 879645462LL, 1103628764LL, + 1339575270LL, -447567508LL, 37713097LL, -1412932263LL, -1316487175LL, -517393923LL, + -934365368LL, 1063411307LL, 685188082LL, 1239942470LL, 1399383545LL, -227447283LL, + 255721397LL, -1395595466LL, -1230666230LL, -708251166LL, -1078594830LL, 925135170LL, + 515176439LL, 1325488756LL, 1422357244LL, -48101819LL, 423239863LL, -1359915137LL, + -1146751020LL, -846493057LL, -1175566760LL, 807909754LL, 381714148LL, 1375520444LL, + 1426066702LL, 84752540LL, 540956247LL, -1323368289LL, -1080008002LL, -938408307LL, + -1235752831LL, 723212255LL, 291591241LL, 1402923448LL, 1423972324LL, 169197941LL, + 611366538LL, -1298333694LL, -1040459045LL, -989954357LL, -1267324223LL, 677932329LL, + 248323481LL, 1416753960LL, 1424803365LL, 204846910LL, 636588924LL, -1292273589LL, + -1033726312LL, -1004906347LL, -1274803346LL, 675674374LL, 253679979LL, 1421464675LL, + 1432339351LL, 191309752LL, 617004132LL, -1307977862LL, -1061600154LL, -983785978LL, + -1258327107LL, 717493360LL, 308442866LL, 1416483253LL, 1445233936LL, 127520753LL, + 550728662LL, -1343533809LL, -1122049011LL, -923489970LL, -1213390799LL, 801854895LL, + 412260733LL, 1395996629LL, 1456747212LL, 12004479LL, 433967697LL, -1391916494LL, + -1208599091LL, -817655445LL, -1131122584LL, 923771737LL, 562555042LL, 1349018266LL, + 1454494866LL, -155861727LL, 262341423LL, -1440332331LL, -1309223472LL, -657911341LL, + -999302475LL, 1073238740LL, 752555453LL, 1260015921LL, 1420542821LL, -373591155LL, + 33279491LL, -1469672373LL, -1405093310LL, -436222112LL, -804447359LL, 1233278240LL, + 968697164LL, 1110528214LL, 1332361621LL, -632455572LL, -250490917LL, -1454643696LL, + -1469772893LL, -148513130LL, -535323766LL, 1378144276LL, 1187845977LL, 882299298LL, + 1165319233LL, -913812133LL, -576523004LL, -1365375734LL, -1469730698LL, 200370271LL, + -188177876LL, 1472580390LL, 1375208444LL, 562472125LL, 897503037LL, -1185644929LL, + -917882391LL, -1171526451LL, -1367393520LL, 590727366LL, 226385598LL, 1473512755LL, + 1484401269LL, 151109761LL, 517514617LL, -1400812284LL, -1229454842LL, -849926906LL, + -1128179313LL, 982347697LL, 675870291LL, 1335992466LL, 1461830202LL, -329588339LL, + 35059634LL, -1499420912LL, -1447932368LL, -396125153LL, -732475573LL, 1311810335LL, + 1100311301LL, 1025005134LL, 1257666237LL, -826775549LL, -507698999LL, -1418270729LL, + -1499028101LL, 161670664LL, -191754186LL, 1496806010LL, 1413115902LL, 533177051LL, + 844412628LL, -1253841434LL, -1028740602LL, -1109423451LL, -1315088402LL, 750763767LL, + 435237022LL, 1451774016LL, 1513690869LL, -98963318LL, 240705841LL, -1499029553LL, + -1409882887LL, -566776828LL, -863452034LL, 1251972839LL, 1034209715LL, 1116861387LL, + 1315657676LL, -768116841LL, -467158138LL, -1451454307LL, -1519093763LL, 146009148LL, + -180188171LL, 1516745595LL, 1445841522LL, 496549942LL, 789121557LL, -1310861435LL, + -1118990528LL, -1045466871LL, -1255152562LL, 879672823LL, 604089144LL, 1410114122LL, + 1504893984LL, -304593887LL, 5881301LL, -1536745016LL, -1505655260LL, -314385248LL, + -608495930LL, 1414137610LL, 1267081538LL, 876813561LL, 1109355799LL, -1071401106LL, + -835664838LL, -1297897095LL, -1436200487LL, 569676608LL, 284033268LL, 1520159997LL, + 1547849896LL, 10320039LL, 302520293LL, -1519485942LL, -1437306795LL, -582185793LL, + -839770426LL, 1305386862LL, 1129393752LL, 1066863630LL, 1256429343LL, -916303325LL, + -674085878LL, -1402979204LL, -1502678344LL, 411378038LL, 137153985LL, 1553385916LL, + 1554634627LL, 139592697LL, 410146453LL, -1507554332LL, -1414746569LL, -666337135LL, + -900770124LL, 1280118995LL, 1108689042LL, 1107014933LL, 1279749681LL, -906365499LL, + -679716848LL, -1414859788LL, -1509491178LL, 435735629LL, 181607145LL, 1562060620LL, + 1572226789LL, 75510872LL, 328691843LL, -1540825911LL, -1469776822LL, -571421726LL, + -797754322LL, 1361961554LL, 1221087458LL, 1002438458LL, 1181015890LL, -1051536282LL, + -858205699LL, -1329889227LL, -1446360396LL, 646349083LL, 421418528LL, 1528641649LL, + 1575841470LL, -188914937LL, 45751357LL, -1587927757LL, -1565671295LL, -277386115LL, + -501120589LL, 1510573379LL, 1424781194LL, 712503730LL, 907576513LL, -1310994029LL, + -1172363621LL, -1082927732LL, -1235731562LL, 1012392229LL, 834831341LL, 1363768147LL, + 1465428417LL, -643583158LL, -442606966LL, -1539704222LL, -1586165474LL, 235832661LL, + 27082778LL, 1604926618LL, 1596604298LL, 179996385LL, 381993832LL, -1562267730LL, + -1503383714LL, -575782376LL, -758556592LL, 1421758522LL, 1319478247LL, 927860913LL, + 1081608196LL, -1198848658LL, -1062336014LL, -1218088912LL, -1335971842LL, 912510460LL, + 751992828LL, 1434297623LL, 1512465902LL, -583405137LL, -409325558LL, -1570216560LL, + -1607606187LL, 232248788LL, 54551887LL, 1624981266LL, 1622948781LL, 121534824LL, + 293951564LL, -1602344580LL, -1564200571LL, -460827179LL, -620491976LL, 1509712063LL, + 1440205608LL, 771486208LL, 912564259LL, -1357107346LL, -1261912661LL, -1042694303LL, + -1161054270LL, 1156158198LL, 1041396171LL, 1267025213LL, 1360182142LL, -919170551LL, + -790995725LL, -1440282159LL, -1507250768LL, 658338377LL, 522602174LL, 1561167501LL, + 1602250804LL, -385114513LL, -247115740LL, -1630841827LL, -1647387970LL, 109751453LL, + -25932788LL, 1652427252LL, 1646573195LL, 158995306LL, 288600362LL, -1630499680LL, + -1604926451LL, -414017784LL, -534620977LL, 1570606343LL, 1528313672LL, 649884456LL, + 759380454LL, -1478832916LL, -1422948385LL, -862773810LL, -959816056LL, 1361435941LL, + 1295055969LL, 1050339929LL, 1134253660LL, -1224546492LL, -1150617198LL, -1211534090LL, + -1282219538LL, 1073945468LL, 995173496LL, 1346403757LL, 1404230169LL, -914905126LL, + -833703304LL, -1455885088LL, -1501591050LL, 752089471LL, 670543673LL, 1541601675LL, + 1576196939LL, -589503953LL, -509366137LL, -1605677556LL, -1630359445LL, 430485375LL, + 353178000LL, 1650570046LL, 1666645277LL, -277722788LL, -204361904LL, -1678924770LL, + -1687748790LL, 133301612LL, 64723957LL, 1693454047LL, 1696357152LL, 1236218LL, + 64452119LL, -1696837955LL, -1695160131LL, -124821798LL, -182284936LL, 1691646988LL, + 1686594511LL, 236783619LL, 288285236LL, -1680284213LL, -1672983506LL, -336770649LL, + -382233230LL, 1664944822LL, 1656406265LL, 424677554LL, 464117651LL, -1647590353LL, + -1638703155LL, -500574467LL, -534073398LL, 1629935027LL, 1621461216LL, 564643272LL, + 592315413LL, -1613441310LL, -1606018825LL, -617121556LL, -639091973LL, 1599322081LL, + 1593465001LL, 658254984LL, 674636449LL, -1588546728LL, -1584651387LL, -688258283LL, + -699137231LL, 1581848879LL, 1580195513LL, 707284788LL, 712707136LL, -1579733635LL, + -1580491273LL, -715404254LL, -715369243LL, 1582482656LL, 1585708571LL, 712588664LL, + 707042902LL, -1590155773LL, -1595796445LL, -698705821LL, -687544652LL, 1602588356LL, + 1610474865LL, 673520761LL, 656590455LL, -1619384133LL, -1629228373LL, -636705253LL, + -613812359LL, 1639903707LL, 1651289929LL, 587855947LL, 558778530LL, -1663249630LL, + -1675627367LL, -526521908LL, -491028325LL, 1688249446LL, 1700923694LL, 452242392LL, + 410113124LL, -1713438731LL, -1725563381LL, -364595643LL, -315653101LL, 1737046728LL, + 1747618256LL, 263259298LL, 207401429LL, -1756987680LL, -1764845037LL, -148082532LL, + -85324147LL, 1770861465LL, 1774690207LL, 19169558LL, -50312887LL, -1775967512LL, + -1774313920LL, 123026750LL, 198844358LL, 1769336324LL, 1760630402LL, -277603243LL, + -359102628LL, -1747783142LL, -1730375907LL, 443100292LL, 529309506LL, 1707988341LL, + 1680202790LL, -617395811LL, -706974071LL, -1646608991LL, -1606809393LL, 797606134LL, + 888798860LL, 1560425357LL, 1507103931LL, -980002382LL, -1070609019LL, -1446524954LL, + -1378408770LL, 1159953145LL, 1247311870LL, 1302524700LL, 1218699950LL, -1331906466LL, + -1412904907LL, -1126828701LL, -1026881511LL, 1489425829LL, 1560543799LL, 918915073LL, + 803081957LL, -1625295845LL, -1682689554LL, -679640019LL, -548961458LL, 1731712990LL, + 1771346271LL, 411541436LL, 268005847LL, -1800574748LL, -1818403948LL, -119117792LL, + 34217329LL, 1823876390LL, 1816090037LL, -190948338LL, -349876879LL, -1794218171LL, + -1757530675LL, 509658541LL, 668806725LL, 1705416587LL, 1637407525LL, -825699474LL, + -978589734LL, -1553201533LL, -1452687045LL, 1125619435LL, 1264837534LL, 1335966547LL, + 1203379264LL, -1394222173LL, -1511707187LL, -1055522125LL, -893268397LL, 1615213117LL, + 1702682580LL, 717783248LL, 530535322LL, -1772119768LL, -1821633864LL, -333303357LL, + -128177042LL, 1849485944LL, 1854138659LL, -82448729LL, -295887123LL, -1834307775LL, + -1789014626LL, 509180992LL, 719133413LL, 1717638276LL, 1619965911LL, -922347610LL, + -1115276576LL, -1496239805LL, -1347199168LL, 1294282481LL, 1455705534LL, 1174115080LL, + 978816511LL, -1595941667LL, -1711528127LL, -763705465LL, -531759404LL, 1799235679LL, + 1856165629LL, 286519237LL, 32061252LL, -1879849492LL, -1868348843LL, 227048340LL, + 485817126LL, 1820352467LL, 1735267582LL, -738908963LL, -980745208LL, -1613301616LL, + -1455530903LL, 1205624100LL, 1407856958LL, 1263952528LL, 1041515521LL, -1581919145LL, + -1722612988LL, -792127722LL, -520634993LL, 1825239013LL, 1885770992LL, 232769886LL, + -64932514LL, -1901029501LL, -1868847966LL, 365252994LL, 660441204LL, 1788224556LL, + 1659452789LL, -942402330LL, -1202915139LL, -1484223440LL, -1265690455LL, 1433877497LL, + 1627573771LL, 1008493875LL, 718733523LL, -1776956805LL, -1875935540LL, -403888338LL, + -72677818LL, 1919657847LL, 1904776818LL, -265135979LL, -599005131LL, -1829687940LL, + -1694724092LL, 917907780LL, 1210708975LL, 1502295452LL, 1256962133LL, -1466561081LL, + -1675331428LL, -965428819LL, -636452821LL, 1828042121LL, 1917304378LL, 280659840LL, + -89734773LL, -1937727888LL, -1886284387LL, 461297351LL, 819833378LL, 1762604174LL, + 1569184899LL, -1150919753LL, -1440495550LL, -1311493505LL, -997945077LL, 1675490129LL, + 1844462979LL, 639746322LL, 250596631LL, -1938225948LL, -1950415708LL, 153754030LL, + 556083879LL, 1877982860LL, 1721564242LL, -938400280LL, -1282740162LL, -1485707003LL, + -1178917124LL, 1572038910LL, 1791029183LL, 813511302LL, 405259486LL, -1927124604LL, + -1971238636LL, 27184248LL, 463052914LL, 1918486633LL, 1768719630LL, -880417289LL, + -1257280031LL, -1526842322LL, -1202875102LL, 1572764319LL, 1808336605LL, 811731026LL, + 372692895LL, -1948993966LL, -1984340917LL, 91407244LL, 555284663LL, 1909479052LL, + 1725636446LL, -992533028LL, -1377128533LL, -1440472558LL, -1068008717LL, 1685027657LL, + 1895764219LL, 628153694LL, 145817797LL, -1993941353LL, -1970509940LL, 350363822LL, + 829648893LL, 1823728170LL, 1559707881LL, -1261067985LL, -1615461025LL, -1192472405LL, + -743477612LL, 1867542335LL, 1997850461LL, 240581550LL, -283512948LL, -1994432375LL, + -1854115470LL, 793276485LL, 1252724162LL, 1583236516LL, 1197724584LL, -1627993076LL, + -1889948505LL, -722474474LL, -189996493LL, 2016620221LL, 1995263483LL, -361615068LL, + -891292804LL, -1823848523LL, -1511809433LL, 1358026415LL, 1724101087LL, 1079927897LL, + 559287868LL, -1958294151LL, -2038758824LL, 10689661LL, 585042069LL, 1955324220LL, + 1710965552LL, -1116719426LL, -1560451436LL, -1322248196LL, -818622557LL, 1876720002LL, + 2035491527LL, 240539277LL, -363540138LL, -2019352380LL, -1825712849LL, 941052459LL, + 1439872969LL, 1467801174LL, 974258470LL, -1813111170LL, -2023726848LL, -387262553LL, + 240754552LL, 2048508678LL, 1880978334LL, -851585905LL, -1386577493LL, -1532850265LL, + -1033789616LL, 1792338722LL, 2026288146LL, 429361515LL, -222757301LL, -2061454484LL, + -1889978822LL, 858044828LL, 1411438243LL, 1524852098LL, 999570052LL, -1824085682LL, + -2049853536LL, -365586116LL, 312325414LL, 2060863237LL, 1851375844LL, -962441026LL, + -1513612997LL, -1439469408LL, -866157482LL, 1903184365LL, 2084419472LL, 191861865LL, + -509546167LL, -2032557002LL, -1748678516LL, 1158616581LL, 1679311199LL, 1260777448LL, + 621699340LL, -2008119609LL, -2102206389LL, 96021560LL, 808018563LL, 1945523104LL, + 1551983513LL, -1427859742LL, -1877637091LL, -965096395LL, -253853335LL, 2098092753LL, + 2056950916LL, -494863243LL, -1186608872LL, -1754249080LL, -1223761033LL, 1731276281LL, + 2055093151LL, 530053469LL, -238727192LL, -2111113902LL, -1886678270LL, 981648454LL, + 1598125465LL, 1406607660LL, 731409658LL, -2001728402LL, -2132770657LL, 49589902LL, + 829548783LL, 1967811452LL, 1524507576LL, -1498515421LL, -1959056876LL, -860807210LL, + -68235945LL, 2140898931LL, 2012348446LL, -740113975LL, -1445436865LL, -1586583061LL, + -921528632LL, 1940761082LL, 2147483647LL, 112932912LL, -718730169LL, -2029222564LL, + -1597836740LL, 1445876730LL, 1953461322LL, 914873099LL, 83174642LL, -2147483648LL, + -2020503853LL, 767727908LL, 1501444265LL, 1557876324LL, 839060506LL, -1996695292LL, + -2147483648LL, 22535469LL, 886518239LL, 1980900881LL, 1460659877LL, -1608076717LL, + -2062444628LL, -689435808LL, 205156439LL, 2147483647LL, 1897916708LL, -1070531381LL, + -1754938961LL, -1295327688LL, -459988096LL, 2134397349LL, 2135959916LL, -463111020LL, + -1309138535LL, -1752857827LL, -1048250460LL, 1922781703LL, 2147483647LL, 146215712LL, + -789077584LL, -2047545728LL, -1523013887LL, 1582760189LL, 2082094165LL, 706558258LL, + -250509800LL, -2147483648LL, -1869504050LL, 1165614956LL, 1859490301LL, 1185631365LL, + 263654602LL, -2147483648LL, -2090211073LL, 716903715LL, 1559972070LL, 1568181028LL, + 724634085LL, -2092219228LL, -2147483648LL, 272875426LL, 1220506505LL, 1852657873LL, + 1116760543LL, -1919513763LL, -2147483648LL, -140682804LL, 871643793LL, 2047246684LL, + 1435124057LL, -1703224578LL, -2147483648LL, -507859441LL, 536473906LL, 2147483647LL, + 1682679390LL, -1468861267LL, -2079500736LL, -820986357LL, 230902361LL, 2147483647LL, + 1867393914LL, -1236871993LL, -1965465687LL, -1078550662LL, -35268439LL, 2147483647LL, + 1999784802LL, -1022660976LL, -1846084892LL, -1283082496LL, -256893594LL, 2147483647LL, + 2090992504LL, -837195208LL, -1735245884LL, -1439283130LL, -431999921LL, 2147483647LL, + 2147483647LL, -687877209LL, -1643456741LL, -1552514842LL, -560459856LL, 2147483647LL, + 2147483647LL, -579452313LL, -1578215145LL, -1627673322LL, -642921391LL, 2147483647LL, + 2147483647LL, -514808680LL, -1544416984LL, -1668405339LL, -680020557LL, 2147483647LL, + 2147483647LL, -495594185LL, -1544699132LL, -1676610584LL, -671868452LL, 2147483647LL, + 2147483647LL, -522609569LL, -1579641952LL, -1652169039LL, -617800840LL, 2147483647LL, + 2147483647LL, -595946814LL, -1647775455LL, -1592859181LL, -516395762LL, 2147483647LL, + 2147483647LL, -714839763LL, -1745354076LL, -1494472885LL, -365790216LL, 2147483647LL, + 2128044652LL, -877197553LL, -1865902521LL, -1351179763LL, -164344062LL, 2147483647LL, + 2040106599LL, -1078815259LL, -1999594005LL, -1156230616LL, 88307530LL, 2147483647LL, + 1905766400LL, -1312306874LL, -2132596741LL, -903099862LL, 389811741LL, 2147483647LL, + 1711876024LL, -1565880572LL, -2147483648LL, -587138971LL, 733338398LL, 2147483647LL, + 1445841197LL, -1822166519LL, -2147483648LL, -207743400LL, 1105678171LL, 2051045622LL, + 1097989236LL, -2057402527LL, -2147483648LL, 229074833LL, 1485498607LL, 1802743966LL, + 664663583LL, -2147483648LL, -2147483648LL, 707966075LL, 1842196891LL, 1445509003LL, + 151877054LL, -2147483648LL, -2014016895LL, 1201818828LL, 2135932772LL, 973190067LL, + -420873838LL, -2147483648LL, -1654298049LL, 1670306599LL, 2147483647LL, 393635672LL, + -1017350082LL, -2123433560LL, -1143536174LL, 2060338366LL, 2147483647LL, -266008259LL, + -1582996460LL, -1750495852LL, -494738536LL, 2147483647LL, 2147483647LL, -955190329LL, + -2046606124LL, -1186456869LL, 251655421LL, 2147483647LL, 1748361490LL, -1598993791LL, + -2147483648LL, -455360086LL, 1023427064LL, 2140824013LL, 1103365586LL, -2102727213LL, + -2147483648LL, 380548096LL, 1718047409LL, 1644250791LL, 271875346LL, -2147483648LL, + -2046340805LL, 1218066862LL, 2147483647LL, 883982669LL, -650520731LL, -2147483648LL, + -1416924301LL, 1920122516LL, 2147483647LL, -60880303LL, -1519551844LL, -1844159292LL, + -511178705LL, 2147483647LL, 2147483647LL, -1047656157LL, -2147483648LL, -1033936134LL, + 539449829LL, 2147483647LL, 1484537216LL, -1882894188LL, -2147483648LL, 26143608LL, + 1531945859LL, 1848886484LL, 466417011LL, -2147483648LL, -2120811210LL, 1132982465LL, + 2147483647LL, 918473952LL, -710033378LL, -2147483648LL, -1316406068LL, 2018133139LL, + 2147483647LL, -283843937LL, -1758293955LL, -1652292991LL, -128756249LL, 2147483647LL, + 1923169246LL, -1462382262LL, -2147483648LL, -515042126LL, 1146625905LL, 2130115944LL +}; diff --git a/test/cmocka/src/audio/eq_fir/debug_files_plot.m b/test/cmocka/src/audio/eq_fir/debug_files_plot.m new file mode 100644 index 000000000000..c8cd62998594 --- /dev/null +++ b/test/cmocka/src/audio/eq_fir/debug_files_plot.m @@ -0,0 +1,56 @@ +% debug_files_plot() - plot optional debug output + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +load ../../../../../build_ut/test/cmocka/src/audio/eq_fir/fir_test_16.txt; +iref = fir_test_16(:,1); +iout = fir_test_16(:,2); +ref = reshape(iref, size(iref, 1)/2, 2); +out = reshape(iout, size(iout, 1)/2, 2); +figure; +subplot(2,1,1); +plot(ref) +hold on +plot(out) +hold off +grid on +title('16 bit FIR'); +subplot(2,1,2); +plot(ref - out); +grid on + +load ../../../../../build_ut/test/cmocka/src/audio/eq_fir/fir_test_24.txt; +iref = fir_test_24(:,1); +iout = fir_test_24(:,2); +ref = reshape(iref, size(iref, 1)/2, 2); +out = reshape(iout, size(iout, 1)/2, 2); +figure; +subplot(2,1,1); +plot(ref) +hold on +plot(out) +hold off +grid on +title('24 bit FIR'); +subplot(2,1,2); +plot(ref - out); +grid on + +load ../../../../../build_ut/test/cmocka/src/audio/eq_fir/fir_test_32.txt; +iref = fir_test_32(:,1); +iout = fir_test_32(:,2); +ref = reshape(iref, size(iref, 1)/2, 2); +out = reshape(iout, size(iout, 1)/2, 2); +figure; +subplot(2,1,1); +plot(ref) +hold on +plot(out) +hold off +grid on +title('32 bit FIR'); +subplot(2,1,2); +plot(ref - out); +grid on diff --git a/test/cmocka/src/audio/eq_fir/eq_fir_process.c b/test/cmocka/src/audio/eq_fir/eq_fir_process.c new file mode 100644 index 000000000000..5e3b1dd5b156 --- /dev/null +++ b/test/cmocka/src/audio/eq_fir/eq_fir_process.c @@ -0,0 +1,539 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <stdint.h> +#include <cmocka.h> +#include <kernel/header.h> +#include <sof/audio/component_ext.h> +#include <eq_fir/eq_fir.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc/control.h> + +#include "../../util.h" +#include "../../../include/cmocka_chirp_2ch.h" +#include "cmocka_fir_ref.h" +#include "cmocka_fir_coef_2ch.h" + +/* Allow some small error for fixed point */ +#define ERROR_TOLERANCE_S16 1 +#define ERROR_TOLERANCE_S24 2 +#define ERROR_TOLERANCE_S32 4 + +/* Thresholds for frames count jitter for rand() function */ +#define THR_RAND_PLUS_ONE ((RAND_MAX >> 1) + (RAND_MAX >> 2)) +#define THR_RAND_MINUS_ONE ((RAND_MAX >> 1) - (RAND_MAX >> 2)) + +/* Export optionally data to files for easier debug */ +#undef DEBUG_FILES +#ifdef DEBUG_FILES +FILE *debug_fh_16; +FILE *debug_fh_24; +FILE *debug_fh_32; +#endif + +struct buffer_fill { + int idx; +} buffer_fill_data; + +struct buffer_verify { + int idx; +} buffer_verify_data; + +struct test_parameters { + uint32_t channels; + uint32_t frames; + uint32_t buffer_size_mult; + uint32_t source_format; + uint32_t sink_format; +}; + +struct test_data { + struct comp_dev *dev; + struct comp_buffer *sink; + struct comp_buffer *source; + struct test_parameters *params; + struct processing_module *mod; + bool continue_loop; +}; + +static int setup_group(void **state) +{ + sys_comp_init(sof_get()); + sys_comp_module_eq_fir_interface_init(); + return 0; +} + +static struct sof_ipc_comp_process *create_eq_fir_comp_ipc(struct test_data *td) +{ + struct sof_ipc_comp_process *ipc; + size_t ipc_size = sizeof(struct sof_ipc_comp_process); + const struct sof_uuid uuid = SOF_REG_UUID(eq_fir); + + ipc = calloc(1, ipc_size + SOF_UUID_SIZE); + memcpy_s(ipc + 1, SOF_UUID_SIZE, &uuid, SOF_UUID_SIZE); + ipc->comp.hdr.size = ipc_size + SOF_UUID_SIZE; + ipc->comp.type = SOF_COMP_MODULE_ADAPTER; + ipc->config.hdr.size = sizeof(struct sof_ipc_comp_config); + ipc->size = 0; + ipc->comp.ext_data_length = SOF_UUID_SIZE; + return ipc; +} + +static int eq_fir_send_config(struct processing_module *mod) +{ + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + struct sof_abi_hdr *blob = (struct sof_abi_hdr *)fir_coef_2ch; + size_t cdata_size = sizeof(struct sof_ipc_ctrl_data) + + sizeof(struct sof_abi_hdr) + blob->size; + struct sof_ipc_ctrl_data *cdata; + int ret; + + cdata = calloc(1, cdata_size); + if (!cdata) + return -ENOMEM; + + cdata->cmd = SOF_CTRL_CMD_BINARY; + cdata->num_elems = blob->size; + cdata->data[0].magic = blob->magic; + cdata->data[0].type = blob->type; + cdata->data[0].size = blob->size; + cdata->data[0].abi = blob->abi; + memcpy_s(cdata->data[0].data, blob->size, blob->data, blob->size); + + ret = ops->set_configuration(mod, 0, MODULE_CFG_FRAGMENT_SINGLE, + blob->size, (const uint8_t *)cdata, + blob->size, NULL, 0); + + free(cdata); + return ret; +} + +static void prepare_sink(struct test_data *td, struct processing_module *mod) +{ + struct test_parameters *parameters = td->params; + struct module_data *md = &mod->priv; + size_t size; + size_t free; + + /* allocate new sink buffer */ + size = parameters->frames * get_frame_bytes(parameters->sink_format, parameters->channels) * + parameters->buffer_size_mult; + + md->mpd.out_buff_size = parameters->frames * get_frame_bytes(parameters->sink_format, + parameters->channels); + + td->sink = create_test_sink(td->dev, 0, parameters->sink_format, + parameters->channels, size); + free = audio_stream_get_free_bytes(&td->sink->stream); + assert_int_equal(free, size); +} + +static void prepare_source(struct test_data *td, struct processing_module *mod) +{ + struct test_parameters *parameters = td->params; + struct module_data *md = &mod->priv; + size_t size; + size_t free; + + md->mpd.in_buff_size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->channels); + + size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->channels) * parameters->buffer_size_mult; + + td->source = create_test_source(td->dev, 0, parameters->source_format, + parameters->channels, size); + free = audio_stream_get_free_bytes(&td->source->stream); + assert_int_equal(free, size); +} + +static int setup(void **state) +{ + struct test_parameters *params = *state; + struct processing_module *mod; + struct test_data *td; + struct sof_ipc_comp_process *ipc; + struct comp_dev *dev; + int ret; + + td = test_malloc(sizeof(*td)); + if (!td) + return -EINVAL; + + td->params = test_malloc(sizeof(*params)); + if (!td->params) + return -EINVAL; + + memcpy_s(td->params, sizeof(*td->params), params, sizeof(*params)); + ipc = create_eq_fir_comp_ipc(td); + buffer_fill_data.idx = 0; + buffer_verify_data.idx = 0; + + dev = comp_new((struct sof_ipc_comp *)ipc); + free(ipc); + if (!dev) + return -EINVAL; + + td->dev = dev; + dev->frames = params->frames; + mod = comp_mod(dev); + + ret = eq_fir_send_config(mod); + if (ret) + return ret; + + prepare_sink(td, mod); + prepare_source(td, mod); + + /* allocate intermediate buffers */ + mod->input_buffers = test_malloc(sizeof(struct input_stream_buffer)); + mod->input_buffers[0].data = &td->source->stream; + mod->output_buffers = test_malloc(sizeof(struct output_stream_buffer)); + mod->output_buffers[0].data = &td->sink->stream; + mod->stream_params = test_malloc(sizeof(struct sof_ipc_stream_params)); + mod->stream_params->channels = params->channels; + mod->period_bytes = get_frame_bytes(params->source_format, params->channels) * 48000 / 1000; + + ret = module_prepare(mod, NULL, 0, NULL, 0); + if (ret) + return ret; + + td->continue_loop = true; + + *state = td; + return 0; +} + +static int teardown(void **state) +{ + struct test_data *td = *state; + struct processing_module *mod = comp_mod(td->dev); + + test_free(mod->input_buffers); + test_free(mod->output_buffers); + test_free(mod->stream_params); + mod->stream_params = NULL; + test_free(td->params); + free_test_source(td->source); + free_test_sink(td->sink); + comp_free(td->dev); + test_free(td); + return 0; +} + +#if CONFIG_FORMAT_S16LE +static void fill_source_s16(struct test_data *td, int frames_max) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int16_t *x; + int bytes_total; + int samples; + int frames; + int i; + int samples_processed = 0; + + sb = comp_dev_get_first_data_producer(dev); + ss = &sb->stream; + frames = MIN(audio_stream_get_free_frames(ss), frames_max); + samples = frames * audio_stream_get_channels(ss); + for (i = 0; i < samples; i++) { + x = audio_stream_write_frag_s16(ss, i); + *x = sat_int16(Q_SHIFT_RND(chirp_2ch[buffer_fill_data.idx++], 31, 15)); + samples_processed++; + if (buffer_fill_data.idx == CHIRP_2CH_LENGTH) { + td->continue_loop = false; + break; + } + } + + if (samples_processed > 0) { + bytes_total = samples_processed * audio_stream_sample_bytes(ss); + comp_update_buffer_produce(sb, bytes_total); + } + + mod->input_buffers[0].size = samples_processed / audio_stream_get_channels(ss); +} + +static void verify_sink_s16(struct test_data *td) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t delta; + int32_t ref; + int32_t out; + int16_t *x; + int samples; + int i; + + sb = comp_dev_get_first_data_consumer(dev); + ss = &sb->stream; + samples = mod->output_buffers[0].size >> 1; + for (i = 0; i < samples; i++) { + x = audio_stream_read_frag_s16(ss, i); + out = *x; + ref = sat_int16(Q_SHIFT_RND(fir_ref_2ch[buffer_verify_data.idx++], 31, 15)); + delta = ref - out; + if (delta > ERROR_TOLERANCE_S16 || delta < -ERROR_TOLERANCE_S16) + assert_int_equal(out, ref); +#ifdef DEBUG_FILES + fprintf(debug_fh_16, "%d %d\n", ref, out); +#endif + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void fill_source_s24(struct test_data *td, int frames_max) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t *x; + int bytes_total; + int samples; + int frames; + int i; + int samples_processed = 0; + + sb = comp_dev_get_first_data_producer(dev); + ss = &sb->stream; + frames = MIN(audio_stream_get_free_frames(ss), frames_max); + samples = frames * audio_stream_get_channels(ss); + for (i = 0; i < samples; i++) { + x = audio_stream_write_frag_s32(ss, i); + *x = sat_int24(Q_SHIFT_RND(chirp_2ch[buffer_fill_data.idx++], 31, 23)); + samples_processed++; + if (buffer_fill_data.idx == CHIRP_2CH_LENGTH) { + td->continue_loop = false; + break; + } + } + + if (samples_processed > 0) { + bytes_total = samples_processed * audio_stream_sample_bytes(ss); + comp_update_buffer_produce(sb, bytes_total); + } + + mod->input_buffers[0].size = samples_processed / audio_stream_get_channels(ss); +} + +static void verify_sink_s24(struct test_data *td) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t delta; + int32_t ref; + int32_t out; + int32_t *x; + int samples; + int i; + + sb = comp_dev_get_first_data_consumer(dev); + ss = &sb->stream; + samples = mod->output_buffers[0].size >> 2; + for (i = 0; i < samples; i++) { + x = audio_stream_read_frag_s32(ss, i); + out = (*x << 8) >> 8; /* Make sure there's no 24 bit overflow */ + ref = sat_int24(Q_SHIFT_RND(fir_ref_2ch[buffer_verify_data.idx++], 31, 23)); + delta = ref - out; + if (delta > ERROR_TOLERANCE_S24 || delta < -ERROR_TOLERANCE_S24) + assert_int_equal(out, ref); +#ifdef DEBUG_FILES + fprintf(debug_fh_24, "%d %d\n", ref, out); +#endif + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void fill_source_s32(struct test_data *td, int frames_max) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t *x; + int bytes_total; + int samples; + int frames; + int i; + int samples_processed = 0; + + sb = comp_dev_get_first_data_producer(dev); + ss = &sb->stream; + frames = MIN(audio_stream_get_free_frames(ss), frames_max); + samples = frames * audio_stream_get_channels(ss); + for (i = 0; i < samples; i++) { + x = audio_stream_write_frag_s32(ss, i); + *x = chirp_2ch[buffer_fill_data.idx++]; + samples_processed++; + if (buffer_fill_data.idx == CHIRP_2CH_LENGTH) { + td->continue_loop = false; + break; + } + } + + if (samples_processed > 0) { + bytes_total = samples_processed * audio_stream_sample_bytes(ss); + comp_update_buffer_produce(sb, bytes_total); + } + + mod->input_buffers[0].size = samples_processed / audio_stream_get_channels(ss); +} + +static void verify_sink_s32(struct test_data *td) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int64_t delta; + int32_t ref; + int32_t out; + int32_t *x; + int samples; + int i; + + sb = comp_dev_get_first_data_consumer(dev); + ss = &sb->stream; + samples = mod->output_buffers[0].size >> 2; + for (i = 0; i < samples; i++) { + x = audio_stream_read_frag_s32(ss, i); + out = *x; + ref = fir_ref_2ch[buffer_verify_data.idx++]; + delta = (int64_t)ref - (int64_t)out; + if (delta > ERROR_TOLERANCE_S32 || delta < -ERROR_TOLERANCE_S32) + assert_int_equal(out, ref); +#ifdef DEBUG_FILES + fprintf(debug_fh_32, "%d %d\n", ref, out); +#endif + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +static int frames_jitter(int frames) +{ + int r = rand(); + + if (r > THR_RAND_PLUS_ONE) + return frames + 1; + else if (r < THR_RAND_MINUS_ONE) + return frames - 1; + else + return frames; +} + +static void test_audio_eq_fir(void **state) +{ + struct test_data *td = *state; + struct processing_module *mod = comp_mod(td->dev); + + struct comp_buffer *source = td->source; + struct comp_buffer *sink = td->sink; + int ret; + int frames; + + while (td->continue_loop) { + frames = frames_jitter(td->params->frames); + switch (audio_stream_get_frm_fmt(&source->stream)) { + case SOF_IPC_FRAME_S16_LE: + fill_source_s16(td, frames); + break; + case SOF_IPC_FRAME_S24_4LE: + fill_source_s24(td, frames); + break; + case SOF_IPC_FRAME_S32_LE: + fill_source_s32(td, frames); + break; + case SOF_IPC_FRAME_S24_3LE: + break; + default: + assert(0); + break; + } + + mod->input_buffers[0].consumed = 0; + mod->output_buffers[0].size = 0; + + ret = module_process_legacy(mod, mod->input_buffers, 1, + mod->output_buffers, 1); + assert_int_equal(ret, 0); + + comp_update_buffer_consume(source, mod->input_buffers[0].consumed); + comp_update_buffer_produce(sink, mod->output_buffers[0].size); + + switch (audio_stream_get_frm_fmt(&sink->stream)) { + case SOF_IPC_FRAME_S16_LE: + verify_sink_s16(td); + break; + case SOF_IPC_FRAME_S24_4LE: + verify_sink_s24(td); + break; + case SOF_IPC_FRAME_S32_LE: + verify_sink_s32(td); + break; + default: + assert(0); + break; + } + + comp_update_buffer_consume(sink, mod->output_buffers[0].size); + } +} + +static struct test_parameters parameters[] = { +#if CONFIG_FORMAT_S16LE + { 2, 48, 2, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { 2, 48, 2, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { 2, 48, 2, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE }, +#endif /* CONFIG_FORMAT_S32LE */ +}; + +int main(void) +{ + int ret; + int i; + + struct CMUnitTest tests[ARRAY_SIZE(parameters)]; + + for (i = 0; i < ARRAY_SIZE(parameters); i++) { + tests[i].name = "test_audio_eq_fir"; + tests[i].test_func = test_audio_eq_fir; + tests[i].setup_func = setup; + tests[i].teardown_func = teardown; + tests[i].initial_state = ¶meters[i]; + } + + cmocka_set_message_output(CM_OUTPUT_TAP); + +#ifdef DEBUG_FILES + debug_fh_16 = fopen("fir_test_16.txt", "w"); + debug_fh_24 = fopen("fir_test_24.txt", "w"); + debug_fh_32 = fopen("fir_test_32.txt", "w"); +#endif + ret = cmocka_run_group_tests(tests, setup_group, NULL); + +#ifdef DEBUG_FILES + fclose(debug_fh_16); + fclose(debug_fh_24); + fclose(debug_fh_32); +#endif + return ret; +} diff --git a/test/cmocka/src/audio/eq_iir/CMakeLists.txt b/test/cmocka/src/audio/eq_iir/CMakeLists.txt new file mode 100644 index 000000000000..b5ff8770eec2 --- /dev/null +++ b/test/cmocka/src/audio/eq_iir/CMakeLists.txt @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(eq_iir_process + eq_iir_process.c +) + +target_include_directories(eq_iir_process PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) + +# make small version of libaudio so we don't have to care +# about unused missing references + +add_compile_options(-DUNIT_TEST) + +add_library(audio_for_eq_iir STATIC + ${PROJECT_SOURCE_DIR}/src/audio/eq_iir/eq_iir.c + ${PROJECT_SOURCE_DIR}/src/audio/eq_iir/eq_iir_generic.c + ${PROJECT_SOURCE_DIR}/src/audio/eq_iir/eq_iir_ipc3.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df1.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df1_generic.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df1_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df1_hifi4.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df1_hifi5.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df2t.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df2t_generic.c + ${PROJECT_SOURCE_DIR}/src/math/iir_df2t_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter_ipc3.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module/generic.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/lib/objpool.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c +) +sof_append_relative_path_definitions(audio_for_eq_iir) + +target_link_libraries(audio_for_eq_iir PRIVATE sof_options) + +target_link_libraries(eq_iir_process PRIVATE audio_for_eq_iir) diff --git a/test/cmocka/src/audio/eq_iir/cmocka_chirp_iir_ref_2ch.h b/test/cmocka/src/audio/eq_iir/cmocka_chirp_iir_ref_2ch.h new file mode 100644 index 000000000000..c22bf901db85 --- /dev/null +++ b/test/cmocka/src/audio/eq_iir/cmocka_chirp_iir_ref_2ch.h @@ -0,0 +1,1609 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +#define CHIRP_IIR_REF_2CH_LENGTH 9600 + +int32_t chirp_iir_ref_2ch[CHIRP_IIR_REF_2CH_LENGTH] = { + 434287711LL, 371428328LL, 1206282873LL, 1021835658LL, 1476371815LL, 1225577310LL, + 1490520109LL, 1204576307LL, 1614709611LL, 1277705264LL, 1640725575LL, 1264391213LL, + 1610540734LL, 1202783252LL, 1574934933LL, 1137588117LL, 1527755834LL, 1063656296LL, + 1483545514LL, 993675736LL, 1453309770LL, 936977646LL, 1438676498LL, 894623969LL, + 1439994840LL, 866549444LL, 1454911684LL, 850373485LL, 1478882820LL, 841898665LL, + 1506918180LL, 836652467LL, 1534223686LL, 830445242LL, 1556788650LL, 819866986LL, + 1571827558LL, 802646288LL, 1577879636LL, 777706783LL, 1574718639LL, 745059323LL, + 1563126690LL, 705580238LL, 1544578367LL, 660718250LL, 1520906802LL, 612193399LL, + 1494000311LL, 561729819LL, 1465561323LL, 510848734LL, 1436945798LL, 460735796LL, + 1409085426LL, 412182790LL, 1382483154LL, 365593749LL, 1357265284LL, 321039449LL, + 1333269734LL, 278341548LL, 1310150071LL, 237168125LL, 1287477725LL, 197125237LL, + 1264829229LL, 157833314LL, 1241850474LL, 118981891LL, 1218294980LL, 80360671LL, + 1194037370LL, 41868524LL, 1169066289LL, 3504623LL, 1143462722LL, -34652706LL, + 1117370241LL, -72473534LL, 1090963185LL, -109804937LL, 1064417647LL, -146496482LL, + 1037888576LL, -182419800LL, 1011494704LL, -217480965LL, 985311520LL, -251625647LL, + 959371396LL, -284837992LL, 933669207LL, -317134826LL, 908171435LL, -348557011LL, + 882826762LL, -379159746LL, 857576422LL, -409003316LL, 832363015LL, -438145401LL, + 807137016LL, -466635555LL, 781860664LL, -494512070LL, 756509384LL, -521801042LL, + 731071133LL, -548517239LL, 705544292LL, -574666192LL, 679934731LL, -600246950LL, + 654252646LL, -625254950LL, 628509669LL, -649684594LL, 602716551LL, -673531251LL, + 576881621LL, -696792564LL, 551010021LL, -719469041LL, 525103647LL, -741564034LL, + 499161622LL, -763083260LL, 473181118LL, -784034038LL, 447158320LL, -804424417LL, + 421089370LL, -824262351LL, 394971162LL, -843555020LL, 368801908LL, -862308360LL, + 342581460LL, -880526828LL, 316311379LL, -898213370LL, 289994818LL, -915369572LL, + 263636254LL, -931995916LL, 237241151LL, -948092105LL, 210815602LL, -963657386LL, + 184366006LL, -978690848LL, 157898798LL, -993191649LL, 131420268LL, -1007159178LL, + 104936457LL, -1020593137LL, 78453127LL, -1033493563LL, 51975787LL, -1045860795LL, + 25509752LL, -1057695419LL, -939769LL, -1068998191LL, -27367598LL, -1079769965LL, + -53768518LL, -1090011634LL, -80137222LL, -1099724088LL, -106468292LL, -1108908196LL, + -132756190LL, -1117564803LL, -158995276LL, -1125694744LL, -185179837LL, -1133298871LL, + -211304113LL, -1140378083LL, -237362342LL, -1146933355LL, -263348784LL, -1152965765LL, + -289257745LL, -1158476512LL, -315083597LL, -1163466931LL, -340820784LL, -1167938495LL, + -366463820LL, -1171892814LL, -392007286LL, -1175331629LL, -417445824LL, -1178256801LL, + -442774117LL, -1180670302LL, -467986888LL, -1182574204LL, -493078886LL, -1183970666LL, + -518044880LL, -1184861932LL, -542879650LL, -1185250325LL, -567577993LL, -1185138240LL, + -592134714LL, -1184528150LL, -616544634LL, -1183422598LL, -640802585LL, -1181824205LL, + -664903417LL, -1179735669LL, -688842001LL, -1177159764LL, -712613224LL, -1174099342LL, + -736211999LL, -1170557333LL, -759633256LL, -1166536746LL, -782871949LL, -1162040664LL, + -805923052LL, -1157072246LL, -828781559LL, -1151634727LL, -851442482LL, -1145731409LL, + -873900851LL, -1139365668LL, -896151716LL, -1132540950LL, -918190141LL, -1125260766LL, + -940011211LL, -1117528699LL, -961610026LL, -1109348397LL, -982981707LL, -1100723575LL, + -1004121393LL, -1091658018LL, -1025024246LL, -1082155577LL, -1045685447LL, -1072220172LL, + -1066100202LL, -1061855789LL, -1086263742LL, -1051066484LL, -1106171320LL, -1039856380LL, + -1125818220LL, -1028229671LL, -1145199749LL, -1016190616LL, -1164311247LL, -1003743545LL, + -1183148079LL, -990892853LL, -1201705644LL, -977643008LL, -1219979371LL, -963998541LL, + -1237964723LL, -949964053LL, -1255657194LL, -935544214LL, -1273052316LL, -920743759LL, + -1290145656LL, -905567493LL, -1306932817LL, -890020288LL, -1323409442LL, -874107082LL, + -1339571213LL, -857832882LL, -1355413854LL, -841202761LL, -1370933128LL, -824221860LL, + -1386124846LL, -806895386LL, -1400984859LL, -789228612LL, -1415509067LL, -771226879LL, + -1429693416LL, -752895594LL, -1443533900LL, -734240228LL, -1457026562LL, -715266319LL, + -1470167496LL, -695979469LL, -1482952848LL, -676385347LL, -1495378817LL, -656489683LL, + -1507441657LL, -636298274LL, -1519137675LL, -615816978LL, -1530463237LL, -595051718LL, + -1541414767LL, -574008479LL, -1551988745LL, -552693307LL, -1562181716LL, -531112311LL, + -1571990282LL, -509268906LL, -1581411111LL, -487172719LL, -1590440934LL, -464834748LL, + -1599076547LL, -442254395LL, -1607314812LL, -419437323LL, -1615152659LL, -396393669LL, + -1622587089LL, -373128353LL, -1629615170LL, -349647902LL, -1636234043LL, -325959317LL, + -1642440922LL, -302069157LL, -1648233093LL, -277984191LL, -1653607918LL, -253711280LL, + -1658562837LL, -229257281LL, -1663095365LL, -204629118LL, -1667203097LL, -179833758LL, + -1670883708LL, -154878210LL, -1674134952LL, -129769526LL, -1676954669LL, -104514806LL, + -1679340779LL, -79121191LL, -1681291290LL, -53595870LL, -1682804292LL, -27946079LL, + -1683877967LL, -2179098LL, -1684510580LL, 23697745LL, -1684700490LL, 49677080LL, + -1684446144LL, 75751491LL, -1683746081LL, 101913522LL, -1682598935LL, 128155676LL, + -1681003431LL, 154470419LL, -1678958391LL, 180850178LL, -1676462734LL, 207287347LL, + -1673515475LL, 233774285LL, -1670115728LL, 260303318LL, -1666262706LL, 286866742LL, + -1661955725LL, 313456823LL, -1657194201LL, 340065797LL, -1651977652LL, 366685876LL, + -1646305701LL, 393309240LL, -1640178077LL, 419928049LL, -1633594613LL, 446534437LL, + -1626555249LL, 473120515LL, -1619060035LL, 499678376LL, -1611109127LL, 526200090LL, + -1602702793LL, 552677713LL, -1593841410LL, 579103281LL, -1584525468LL, 605468819LL, + -1574755569LL, 631766337LL, -1564532427LL, 657987834LL, -1553856873LL, 684125301LL, + -1542729852LL, 710170720LL, -1531152422LL, 736116066LL, -1519125762LL, 761953311LL, + -1506651166LL, 787674425LL, -1493730047LL, 813271375LL, -1480363935LL, 838736130LL, + -1466554482LL, 864060661LL, -1452303459LL, 889236945LL, -1437612758LL, 914256964LL, + -1422484392LL, 939112708LL, -1406920497LL, 963796178LL, -1390923332LL, 988299386LL, + -1374495277LL, 1012614361LL, -1357638837LL, 1036733143LL, -1340356641LL, 1060647795LL, + -1322651443LL, 1084350397LL, -1304526122LL, 1107833051LL, -1285983682LL, 1131087885LL, + -1267027252LL, 1154107052LL, -1247660088LL, 1176882732LL, -1227885572LL, 1199407138LL, + -1207707213LL, 1221672514LL, -1187128647LL, 1243671138LL, -1166153635LL, 1265395326LL, + -1144786068LL, 1286837432LL, -1123029963LL, 1307989853LL, -1100889464LL, 1328845026LL, + -1078368842LL, 1349395437LL, -1055472497LL, 1369633617LL, -1032204955LL, 1389552150LL, + -1008570870LL, 1409143669LL, -984575023LL, 1428400865LL, -960222323LL, 1447316484LL, + -935517803LL, 1465883331LL, -910466627LL, 1484094272LL, -885074081LL, 1501942240LL, + -859345579LL, 1519420230LL, -833286663LL, 1536521310LL, -806902996LL, 1553238614LL, + -780200369LL, 1569565353LL, -753184697LL, 1585494813LL, -725862017LL, 1601020355LL, + -698238492LL, 1616135426LL, -670320405LL, 1630833550LL, -642114164LL, 1645108340LL, + -613626296LL, 1658953495LL, -584863450LL, 1672362804LL, -555832395LL, 1685330149LL, + -526540017LL, 1697849507LL, -496993322LL, 1709914950LL, -467199433LL, 1721520653LL, + -437165589LL, 1732660890LL, -406899144LL, 1743330041LL, -376407566LL, 1753522593LL, + -345698436LL, 1763233140LL, -314779447LL, 1772456391LL, -283658403LL, 1781187166LL, + -252343216LL, 1789420404LL, -220841908LL, 1797151160LL, -189162606LL, 1804374612LL, + -157313543LL, 1811086060LL, -125303054LL, 1817280932LL, -93139579LL, 1822954782LL, + -60831656LL, 1828103296LL, -28387924LL, 1832722291LL, 4182881LL, 1836807722LL, + 36871929LL, 1840355677LL, 69670295LL, 1843362389LL, 102568962LL, 1845824228LL, + 135558822LL, 1847737711LL, 168630681LL, 1849099500LL, 201775257LL, 1849906407LL, + 234983185LL, 1850155393LL, 268245017LL, 1849843573LL, 301551226LL, 1848968217LL, + 334892206LL, 1847526751LL, 368258277LL, 1845516761LL, 401639684LL, 1842935995LL, + 435026604LL, 1839782362LL, 468409142LL, 1836053938LL, 501777340LL, 1831748965LL, + 535121174LL, 1826865856LL, 568430561LL, 1821403194LL, 601695358LL, 1815359734LL, + 634905369LL, 1808734407LL, 668050341LL, 1801526320LL, 701119974LL, 1793734758LL, + 734103919LL, 1785359186LL, 766991782LL, 1776399252LL, 799773129LL, 1766854786LL, + 832437486LL, 1756725802LL, 864974342LL, 1746012504LL, 897373155LL, 1734715281LL, + 929623354LL, 1722834711LL, 961714338LL, 1710371566LL, 993635487LL, 1697326807LL, + 1025376156LL, 1683701591LL, 1056925688LL, 1669497269LL, 1088273409LL, 1654715387LL, + 1119408635LL, 1639357690LL, 1150320677LL, 1623426120LL, 1180998840LL, 1606922821LL, + 1211432432LL, 1589850133LL, 1241610761LL, 1572210602LL, 1271523146LL, 1554006974LL, + 1301158913LL, 1535242198LL, 1330507406LL, 1515919428LL, 1359557982LL, 1496042022LL, + 1388300025LL, 1475613543LL, 1416722942LL, 1454637761LL, 1444816168LL, 1433118651LL, + 1472569173LL, 1411060395LL, 1499971463LL, 1388467384LL, 1527012584LL, 1365344216LL, + 1553682130LL, 1341695694LL, 1579969738LL, 1317526833LL, 1605865102LL, 1292842854LL, + 1631357971LL, 1267649186LL, 1656438153LL, 1241951467LL, 1681095524LL, 1215755542LL, + 1705320026LL, 1189067466LL, 1729101673LL, 1161893498LL, 1752430559LL, 1134240108LL, + 1775296855LL, 1106113971LL, 1797690819LL, 1077521967LL, 1819602799LL, 1048471185LL, + 1841023235LL, 1018968916LL, 1861942666LL, 989022658LL, 1882351729LL, 958640110LL, + 1902241172LL, 927829174LL, 1921601849LL, 896597957LL, 1940424731LL, 864954762LL, + 1958700906LL, 832908095LL, 1976421586LL, 800466657LL, 1993578109LL, 767633635LL, + 2010161945LL, 734425172LL, 2026164698LL, 700860315LL, 2041578115LL, 666934141LL, + 2056394084LL, 632654779LL, 2070604641LL, 598039700LL, 2084201978LL, 563095628LL, + 2097178439LL, 527832686LL, 2109526531LL, 492262048LL, 2121238927LL, 456394037LL, + 2132308468LL, 420239476LL, 2142728168LL, 383809442LL, 2147483647LL, 347115077LL, + 2147483647LL, 310167713LL, 2147483647LL, 272978845LL, 2147483647LL, 235560108LL, + 2147483647LL, 197923295LL, 2147483647LL, 160080349LL, 2147483647LL, 122043366LL, + 2147483647LL, 83824596LL, 2147483647LL, 45436439LL, 2147483647LL, 6891449LL, + 2147483647LL, -31797674LL, 2147483647LL, -70618082LL, 2147483647LL, -109556786LL, + 2147483647LL, -148600662LL, 2147483647LL, -187736451LL, 2147483647LL, -226950768LL, + 2147483647LL, -266230106LL, 2147483647LL, -305560839LL, 2147483647LL, -344929230LL, + 2147483647LL, -384321431LL, 2147483647LL, -423723491LL, 2147483647LL, -463121358LL, + 2147483647LL, -502500884LL, 2147483647LL, -541847830LL, 2147483647LL, -581147869LL, + 2147483647LL, -620386589LL, 2147483647LL, -659549502LL, 2147483647LL, -698622044LL, + 2137998190LL, -737589586LL, 2126695638LL, -776437430LL, 2114633830LL, -815150824LL, + 2101813307LL, -853714960LL, 2088234898LL, -892114985LL, 2073899720LL, -930336001LL, + 2058809182LL, -968363075LL, 2042964986LL, -1006181244LL, 2026369133LL, -1043775517LL, + 2009023916LL, -1081130884LL, 1990931933LL, -1118232323LL, 1972096081LL, -1155064803LL, + 1952519558LL, -1191613288LL, 1932205869LL, -1227862749LL, 1911158825LL, -1263798166LL, + 1889382541LL, -1299404533LL, 1866881444LL, -1334666868LL, 1843660267LL, -1369570215LL, + 1819724055LL, -1404099656LL, 1795078164LL, -1438240309LL, 1769728261LL, -1471977344LL, + 1743680326LL, -1505295980LL, 1716940651LL, -1538181499LL, 1689515841LL, -1570619249LL, + 1661412815LL, -1602594652LL, 1632638804LL, -1634093209LL, 1603201355LL, -1665100506LL, + 1573108324LL, -1695602227LL, 1542367882LL, -1725584150LL, 1510988513LL, -1755032165LL, + 1478979010LL, -1783932272LL, 1446348478LL, -1812270593LL, 1413106332LL, -1840033378LL, + 1379262295LL, -1867207008LL, 1344826398LL, -1893778010LL, 1309808979LL, -1919733054LL, + 1274220678LL, -1945058968LL, 1238072441LL, -1969742740LL, 1201375513LL, -1993771528LL, + 1164139249LL, -2017132665LL, 1126378192LL, -2039813668LL, 1088108223LL, -2061802240LL, + 1049336245LL, -2083086285LL, 1010074388LL, -2103653908LL, 970338575LL, -2123493424LL, + 930140821LL, -2142593366LL, 889494656LL, -2147483648LL, 848414219LL, -2147483648LL, + 806913529LL, -2147483648LL, 765006997LL, -2147483648LL, 722709334LL, -2147483648LL, + 680035471LL, -2147483648LL, 637000604LL, -2147483648LL, 593620184LL, -2147483648LL, + 549909902LL, -2147483648LL, 505885692LL, -2147483648LL, 461563727LL, -2147483648LL, + 416960414LL, -2147483648LL, 372092391LL, -2147483648LL, 326976524LL, -2147483648LL, + 281629900LL, -2147483648LL, 236069823LL, -2147483648LL, 190313810LL, -2147483648LL, + 144379582LL, -2147483648LL, 98285060LL, -2147483648LL, 52048358LL, -2147483648LL, + 5687775LL, -2147483648LL, -40778210LL, -2147483648LL, -87330947LL, -2147483648LL, + -133951619LL, -2147483648LL, -180621252LL, -2147483648LL, -227320721LL, -2147483648LL, + -274030757LL, -2147483648LL, -320731953LL, -2147483648LL, -367404774LL, -2147483648LL, + -414029564LL, -2147483648LL, -460586550LL, -2147483648LL, -507055855LL, -2147483648LL, + -553417505LL, -2147483648LL, -599651434LL, -2147483648LL, -645737494LL, -2147483648LL, + -691655467LL, -2147483648LL, -737385069LL, -2147483648LL, -782905960LL, -2147483648LL, + -828197755LL, -2147483648LL, -873240030LL, -2147483648LL, -918012334LL, -2147483648LL, + -962494196LL, -2147483648LL, -1006665137LL, -2147045649LL, -1050504676LL, -2126699605LL, + -1093992343LL, -2105424305LL, -1137107685LL, -2083224645LL, -1179830280LL, -2060105976LL, + -1222139743LL, -2036074100LL, -1264015739LL, -2011135274LL, -1305437990LL, -1985296215LL, + -1346386290LL, -1958564094LL, -1386840509LL, -1930946542LL, -1426780607LL, -1902451646LL, + -1466186645LL, -1873087955LL, -1505038793LL, -1842864475LL, -1543317343LL, -1811790671LL, + -1581002717LL, -1779876466LL, -1618075478LL, -1747132241LL, -1654516345LL, -1713568833LL, + -1690306197LL, -1679197536LL, -1725426087LL, -1644030095LL, -1759857255LL, -1608078711LL, + -1793581134LL, -1571356033LL, -1826579365LL, -1533875159LL, -1858833805LL, -1495649635LL, + -1890326539LL, -1456693448LL, -1921039891LL, -1417021026LL, -1950956436LL, -1376647234LL, + -1980059006LL, -1335587373LL, -2008330708LL, -1293857173LL, -2035754928LL, -1251472788LL, + -2062315347LL, -1208450798LL, -2087995947LL, -1164808198LL, -2112781027LL, -1120562397LL, + -2136655209LL, -1075731211LL, -2147483648LL, -1030332859LL, -2147483648LL, -984385958LL, + -2147483648LL, -937909514LL, -2147483648LL, -890922920LL, -2147483648LL, -843445946LL, + -2147483648LL, -795498737LL, -2147483648LL, -747101799LL, -2147483648LL, -698276001LL, + -2147483648LL, -649042558LL, -2147483648LL, -599423030LL, -2147483648LL, -549439312LL, + -2147483648LL, -499113626LL, -2147483648LL, -448468511LL, -2147483648LL, -397526815LL, + -2147483648LL, -346311688LL, -2147483648LL, -294846570LL, -2147483648LL, -243155182LL, + -2147483648LL, -191261518LL, -2147483648LL, -139189831LL, -2147483648LL, -86964629LL, + -2147483648LL, -34610656LL, -2147483648LL, 17847110LL, -2147483648LL, 70383476LL, + -2147483648LL, 122973038LL, -2147483648LL, 175590199LL, -2147483648LL, 228209177LL, + -2147483648LL, 280804018LL, -2147483648LL, 333348609LL, -2147483648LL, 385816689LL, + -2147483648LL, 438181863LL, -2147483648LL, 490417613LL, -2147483648LL, 542497314LL, + -2147483648LL, 594394246LL, -2147483648LL, 646081607LL, -2147483648LL, 697532527LL, + -2147483648LL, 748720082LL, -2147483648LL, 799617309LL, -2147483648LL, 850197217LL, + -2147483648LL, 900432806LL, -2147483648LL, 950297081LL, -2147483648LL, 999763061LL, + -2147483648LL, 1048803801LL, -2147483648LL, 1097392405LL, -2126773805LL, 1145502038LL, + -2100888149LL, 1193105947LL, -2073895655LL, 1240177469LL, -2045805824LL, 1286690056LL, + -2016628807LL, 1332617281LL, -1986375402LL, 1377932860LL, -1955057057LL, 1422610669LL, + -1922685867LL, 1466624753LL, -1889274575LL, 1509949348LL, -1854836567LL, 1552558896LL, + -1819385874LL, 1594428061LL, -1782937168LL, 1635531742LL, -1745505759LL, 1675845094LL, + -1707107594LL, 1715343543LL, -1667759249LL, 1754002800LL, -1627477930LL, 1791798880LL, + -1586281468LL, 1828708116LL, -1544188311LL, 1864707179LL, -1501217521LL, 1899773087LL, + -1457388770LL, 1933883232LL, -1412722332LL, 1967015386LL, -1367239076LL, 1999147722LL, + -1320960461LL, 2030258832LL, -1273908528LL, 2060327737LL, -1226105893LL, 2089333909LL, + -1177575736LL, 2117257283LL, -1128341798LL, 2144078274LL, -1078428365LL, 2147483647LL, + -1027860265LL, 2147483647LL, -976662855LL, 2147483647LL, -924862010LL, 2147483647LL, + -872484114LL, 2147483647LL, -819556050LL, 2147483647LL, -766105184LL, 2147483647LL, + -712159358LL, 2147483647LL, -657746874LL, 2147483647LL, -602896485LL, 2147483647LL, + -547637375LL, 2147483647LL, -491999156LL, 2147483647LL, -436011841LL, 2147483647LL, + -379705842LL, 2147483647LL, -323111945LL, 2147483647LL, -266261302LL, 2147483647LL, + -209185412LL, 2147483647LL, -151916103LL, 2147483647LL, -94485521LL, 2147483647LL, + -36926108LL, 2147483647LL, 20729411LL, 2147483647LL, 78448050LL, 2147483647LL, + 136196574LL, 2147483647LL, 193941526LL, 2147483647LL, 251649234LL, 2147483647LL, + 309285842LL, 2147483647LL, 366817320LL, 2147483647LL, 424209489LL, 2147483647LL, + 481428037LL, 2147483647LL, 538438542LL, 2147483647LL, 595206494LL, 2147483647LL, + 651697310LL, 2147483647LL, 707876360LL, 2147483647LL, 763708986LL, 2147483647LL, + 819160527LL, 2147483647LL, 874196334LL, 2147483647LL, 928781800LL, 2147483647LL, + 982882375LL, 2147483647LL, 1036463594LL, 2147483647LL, 1089491096LL, 2147483647LL, + 1141930648LL, 2135537039LL, 1193748170LL, 2106801760LL, 1244909755LL, 2076763842LL, + 1295381692LL, 2045436682LL, 1345130493LL, 2012834565LL, 1394122913LL, 1978972663LL, + 1442325975LL, 1943867032LL, 1489706993LL, 1907534610LL, 1536233597LL, 1869993213LL, + 1581873755LL, 1831261531LL, 1626595797LL, 1791353438LL, 1670368441LL, 1750296371LL, + 1713160814LL, 1708121324LL, 1754942477LL, 1664836094LL, 1795683449LL, 1620462128LL, + 1835354229LL, 1575030809LL, 1873925821LL, 1528563474LL, 1911369759LL, 1481085476LL, + 1947658127LL, 1432623836LL, 1982763584LL, 1383205352LL, 2016659388LL, 1332857925LL, + 2049319416LL, 1281610311LL, 2080718191LL, 1229491920LL, 2110830900LL, 1176532928LL, + 2139633421LL, 1122764241LL, 2147483647LL, 1068217464LL, 2147483647LL, 1012924897LL, + 2147483647LL, 956919524LL, 2147483647LL, 900234996LL, 2147483647LL, 842905620LL, + 2147483647LL, 784966342LL, 2147483647LL, 726452733LL, 2147483647LL, 667400968LL, + 2147483647LL, 607847808LL, 2147483647LL, 547830580LL, 2147483647LL, 487387152LL, + 2147483647LL, 426555916LL, 2147483647LL, 365375759LL, 2147483647LL, 303886042LL, + 2147483647LL, 242126577LL, 2147483647LL, 180137599LL, 2147483647LL, 117959746LL, + 2147483647LL, 55634030LL, 2147483647LL, -6798185LL, 2147483647LL, -69295213LL, + 2147483647LL, -131815068LL, 2147483647LL, -194315493LL, 2147483647LL, -256753986LL, + 2147483647LL, -319087830LL, 2147483647LL, -381274120LL, 2147483647LL, -443269790LL, + 2147483647LL, -505031648LL, 2147483647LL, -566516400LL, 2147483647LL, -627680684LL, + 2147483647LL, -688481097LL, 2147483647LL, -748874232LL, 2147483647LL, -808816703LL, + 2147483647LL, -868265182LL, 2147483647LL, -927176425LL, 2147483647LL, -985507310LL, + 2147483647LL, -1043214867LL, 2141714174LL, -1100256308LL, 2111617542LL, -1156589065LL, + 2080002301LL, -1212170820LL, 2046885330LL, -1266959537LL, 2012284690LL, -1320913497LL, + 1976219625LL, -1373991334LL, 1938710552LL, -1426152062LL, 1899779059LL, -1477355115LL, + 1859447899LL, -1527560377LL, 1817740982LL, -1576728218LL, 1774683368LL, -1624819525LL, + 1730301255LL, -1671795739LL, 1684621971LL, -1717618885LL, 1637673965LL, -1762251608LL, + 1589486790LL, -1805657204LL, 1540091094LL, -1847799657LL, 1489518604LL, -1888643669LL, + 1437802111LL, -1928154692LL, 1384975457LL, -1966298964LL, 1331073513LL, -2003043538LL, + 1276132163LL, -2038356315LL, 1220188288LL, -2072206078LL, 1163279741LL, -2104562519LL, + 1105445331LL, -2135396272LL, 1046724797LL, -2147483648LL, 987158787LL, -2147483648LL, + 926788833LL, -2147483648LL, 865657328LL, -2147483648LL, 803807499LL, -2147483648LL, + 741283380LL, -2147483648LL, 678129785LL, -2147483648LL, 614392280LL, -2147483648LL, + 550117151LL, -2147483648LL, 485351376LL, -2147483648LL, 420142592LL, -2147483648LL, + 354539067LL, -2147483648LL, 288589661LL, -2147483648LL, 222343795LL, -2147483648LL, + 155851417LL, -2147483648LL, 89162966LL, -2147483648LL, 22329337LL, -2147483648LL, + -44598161LL, -2147483648LL, -111567834LL, -2147483648LL, -178527652LL, -2147483648LL, + -245425277LL, -2147483648LL, -312208113LL, -2147483648LL, -378823338LL, -2147483648LL, + -445217953LL, -2147483648LL, -511338816LL, -2147483648LL, -577132688LL, -2147483648LL, + -642546278LL, -2147483648LL, -707526280LL, -2147483648LL, -772019423LL, -2147483648LL, + -835972511LL, -2147483648LL, -899332469LL, -2147483648LL, -962046389LL, -2147483648LL, + -1024061571LL, -2147483648LL, -1085325575LL, -2144001505LL, -1145786261LL, -2112306032LL, + -1205391839LL, -2078867490LL, -1264090911LL, -2043706854LL, -1321832522LL, -2006846639LL, + -1378566203LL, -1968310894LL, -1434242020LL, -1928125194LL, -1488810618LL, -1886316635LL, + -1542223269LL, -1842913819LL, -1594431920LL, -1797946845LL, -1645389235LL, -1751447294LL, + -1695048646LL, -1703448216LL, -1743364397LL, -1653984111LL, -1790291588LL, -1603090918LL, + -1835786225LL, -1550805987LL, -1879805262LL, -1497168066LL, -1922306645LL, -1442217276LL, + -1963249360LL, -1385995087LL, -2002593474LL, -1328544296LL, -2040300181LL, -1269908998LL, + -2076331841LL, -1210134560LL, -2110652030LL, -1149267592LL, -2143225572LL, -1087355916LL, + -2147483648LL, -1024448533LL, -2147483648LL, -960595593LL, -2147483648LL, -895848357LL, + -2147483648LL, -830259163LL, -2147483648LL, -763881389LL, -2147483648LL, -696769411LL, + -2147483648LL, -628978568LL, -2147483648LL, -560565117LL, -2147483648LL, -491586191LL, + -2147483648LL, -422099758LL, -2147483648LL, -352164570LL, -2147483648LL, -281840124LL, + -2147483648LL, -211186611LL, -2147483648LL, -140264864LL, -2147483648LL, -69136317LL, + -2147483648LL, 2137054LL, -2147483648LL, 73492779LL, -2147483648LL, 144867947LL, + -2147483648LL, 216199258LL, -2147483648LL, 287423083LL, -2147483648LL, 358475514LL, + -2147483648LL, 429292421LL, -2147483648LL, 499809514LL, -2147483648LL, 569962395LL, + -2147483648LL, 639686620LL, -2147483648LL, 708917756LL, -2147483648LL, 777591445LL, + -2147483648LL, 845643459LL, -2147483648LL, 913009765LL, -2147483648LL, 979626585LL, + -2147483648LL, 1045430458LL, -2132163529LL, 1110358301LL, -2097622933LL, 1174347472LL, + -2061118735LL, 1237335837LL, -2022677675LL, 1299261823LL, -1982328454LL, 1360064493LL, + -1940101722LL, 1419683598LL, -1896030071LL, 1478059647LL, -1850148014LL, 1535133969LL, + -1802491968LL, 1590848771LL, -1753100239LL, 1645147207LL, -1702012996LL, 1697973437LL, + -1649272250LL, 1749272689LL, -1594921829LL, 1798991320LL, -1539007348LL, 1847076878LL, + -1481576182LL, 1893478165LL, -1422677432LL, 1938145290LL, -1362361895LL, 1981029738LL, + -1300682023LL, 2022084417LL, -1237691892LL, 2061263728LL, -1173447154LL, 2098523612LL, + -1108005003LL, 2133821609LL, -1041424127LL, 2147483647LL, -973764664LL, 2147483647LL, + -905088152LL, 2147483647LL, -835457483LL, 2147483647LL, -764936849LL, 2147483647LL, + -693591689LL, 2147483647LL, -621488635LL, 2147483647LL, -548695455LL, 2147483647LL, + -475280992LL, 2147483647LL, -401315107LL, 2147483647LL, -326868616LL, 2147483647LL, + -252013223LL, 2147483647LL, -176821461LL, 2147483647LL, -101366619LL, 2147483647LL, + -25722678LL, 2147483647LL, 50035760LL, 2147483647LL, 125833545LL, 2147483647LL, + 201595049LL, 2147483647LL, 277244239LL, 2147483647LL, 352704754LL, 2147483647LL, + 427899979LL, 2147483647LL, 502753126LL, 2147483647LL, 577187305LL, 2147483647LL, + 651125611LL, 2147483647LL, 724491195LL, 2147483647LL, 797207353LL, 2147483647LL, + 869197602LL, 2147483647LL, 940385762LL, 2147483647LL, 1010696042LL, 2147483647LL, + 1080053117LL, 2147483647LL, 1148382217LL, 2113060133LL, 1215609207LL, 2075138331LL, + 1281660671LL, 2035030914LL, 1346463996LL, 1992771855LL, 1409947455LL, 1948397583LL, + 1472040293LL, 1901946958LL, 1532672807LL, 1853461256LL, 1591776431LL, 1802984137LL, + 1649283820LL, 1750561624LL, 1705128928LL, 1696242070LL, 1759247096LL, 1640076123LL, + 1811575125LL, 1582116694LL, 1862051365LL, 1522418916LL, 1910615788LL, 1461040100LL, + 1957210068LL, 1398039694LL, 2001777659LL, 1333479235LL, 2044263872LL, 1267422296LL, + 2084615948LL, 1199934436LL, 2122783133LL, 1131083143LL, 2147483647LL, 1060937775LL, + 2147483647LL, 989569501LL, 2147483647LL, 917051231LL, 2147483647LL, 843457558LL, + 2147483647LL, 768864683LL, 2147483647LL, 693350346LL, 2147483647LL, 616993747LL, + 2147483647LL, 539875479LL, 2147483647LL, 462077438LL, 2147483647LL, 383682750LL, + 2147483647LL, 304775684LL, 2147483647LL, 225441565LL, 2147483647LL, 145766689LL, + 2147483647LL, 65838234LL, 2147483647LL, -14255836LL, 2147483647LL, -94426863LL, + 2147483647LL, -174585587LL, 2147483647LL, -254642247LL, 2147483647LL, -334506680LL, + 2147483647LL, -414088417LL, 2147483647LL, -493296789LL, 2147483647LL, -572041027LL, + 2147483647LL, -650230369LL, 2147483647LL, -727774160LL, 2147483647LL, -804581964LL, + 2147483647LL, -880563667LL, 2147483647LL, -955629586LL, 2147483647LL, -1029690576LL, + 2138059664LL, -1102658142LL, 2099484744LL, -1174444543LL, 2058451131LL, -1244962906LL, + 2014997753LL, -1314127332LL, 1969166586LL, -1381853009LL, 1921002632LL, -1448056315LL, + 1870553885LL, -1512654934LL, 1817871303LL, -1575567961LL, 1763008768LL, -1636716008LL, + 1706023046LL, -1696021313LL, 1646973742LL, -1753407849LL, 1585923255LL, -1808801423LL, + 1522936717LL, -1862129786LL, 1458081946LL, -1913322731LL, 1391429380LL, -1962312198LL, + 1323052014LL, -2009032372LL, 1253025333LL, -2053419779LL, 1181427240LL, -2095413387LL, + 1108337978LL, -2134954695LL, 1033840054LL, -2147483648LL, 958018157LL, -2147483648LL, + 880959067LL, -2147483648LL, 802751570LL, -2147483648LL, 723486359LL, -2147483648LL, + 643255945LL, -2147483648LL, 562154551LL, -2147483648LL, 480278010LL, -2147483648LL, + 397723661LL, -2147483648LL, 314590237LL, -2147483648LL, 230977753LL, -2147483648LL, + 146987396LL, -2147483648LL, 62721399LL, -2147483648LL, -21717071LL, -2147483648LL, + -106224042LL, -2147483648LL, -190694857LL, -2147483648LL, -275024305LL, -2147483648LL, + -359106747LL, -2147483648LL, -442836248LL, -2147483648LL, -526106711LL, -2147483648LL, + -608812010LL, -2147483648LL, -690846124LL, -2147483648LL, -772103279LL, -2147483648LL, + -852478080LL, -2147483648LL, -931865654LL, -2147483648LL, -1010161788LL, -2147483648LL, + -1087263070LL, -2144801896LL, -1163067030LL, -2104608552LL, -1237472280LL, -2061685455LL, + -1310378655LL, -2016078253LL, -1381687353LL, -1967836325LL, -1451301078LL, -1917012748LL, + -1519124177LL, -1863664257LL, -1585062779LL, -1807851200LL, -1649024938LL, -1749637485LL, + -1710920762LL, -1689090528LL, -1770662554LL, -1626281188LL, -1828164945LL, -1561283702LL, + -1883345026LL, -1494175616LL, -1936122479LL, -1425037703LL, -1986419701LL, -1353953884LL, + -2034161937LL, -1281011141LL, -2079277397LL, -1206299424LL, -2121697379LL, -1129911554LL, + -2147483648LL, -1051943120LL, -2147483648LL, -972492373LL, -2147483648LL, -891660114LL, + -2147483648LL, -809549577LL, -2147483648LL, -726266308LL, -2147483648LL, -641918041LL, + -2147483648LL, -556614567LL, -2147483648LL, -470467599LL, -2147483648LL, -383590638LL, + -2147483648LL, -296098826LL, -2147483648LL, -208108804LL, -2147483648LL, -119738560LL, + -2147483648LL, -31107279LL, -2147483648LL, 57664813LL, -2147483648LL, 146456612LL, + -2147483648LL, 235146293LL, -2147483648LL, 323611476LL, -2147483648LL, 411729395LL, + -2147483648LL, 499377065LL, -2147483648LL, 586431455LL, -2147483648LL, 672769658LL, + -2147483648LL, 758269071LL, -2147483648LL, 842807566LL, -2147483648LL, 926263671LL, + -2147483648LL, 1008516745LL, -2141205673LL, 1089447159LL, -2098816391LL, 1168936476LL, + -2053421250LL, 1246867624LL, -2005072863LL, 1323125084LL, -1953836373LL, 1397595063LL, + -1899771805LL, 1470165672LL, -1842946412LL, 1540727106LL, -1783432547LL, 1609171816LL, + -1721305942LL, 1675394685LL, -1656646808LL, 1739293202LL, -1589539539LL, 1800767631LL, + -1520072464LL, 1859721177LL, -1448337855LL, 1916060154LL, -1374431803LL, 1969694146LL, + -1298454092LL, 2020536167LL, -1220508096LL, 2068502816LL, -1140700655LL, 2113514430LL, + -1059141945LL, 2147483647LL, -975945346LL, 2147483647LL, -891227301LL, 2147483647LL, + -805107167LL, 2147483647LL, -717707063LL, 2147483647LL, -629151706LL, 2147483647LL, + -539568248LL, 2147483647LL, -449086101LL, 2147483647LL, -357836756LL, 2147483647LL, + -265953606LL, 2147483647LL, -173571752LL, 2147483647LL, -80827817LL, 2147483647LL, + 12140257LL, 2147483647LL, 105193404LL, 2147483647LL, 198191639LL, 2147483647LL, + 290994268LL, 2147483647LL, 383460091LL, 2147483647LL, 475447625LL, 2147483647LL, + 566815309LL, 2147483647LL, 657421730LL, 2147483647LL, 747125841LL, 2147483647LL, + 835787181LL, 2147483647LL, 923266099LL, 2147483647LL, 1009423982LL, 2147483647LL, + 1094123473LL, 2137014848LL, 1177228704LL, 2092351346LL, 1258605516LL, 2044401771LL, + 1338121685LL, 1993229421LL, 1415647147LL, 1938902997LL, 1491054223LL, 1881496533LL, + 1564217835LL, 1821089324LL, 1635015729LL, 1757765843LL, 1703328691LL, 1691615643LL, + 1769040764LL, 1622733260LL, 1832039453LL, 1551218097LL, 1892215939LL, 1477174306LL, + 1949465282LL, 1400710658LL, 2003686617LL, 1321940403LL, 2054783352LL, 1240981127LL, + 2102663359LL, 1157954592LL, 2147239156LL, 1072986572LL, 2147483647LL, 986206685LL, + 2147483647LL, 897748207LL, 2147483647LL, 807747888LL, 2147483647LL, 716345752LL, + 2147483647LL, 623684900LL, 2147483647LL, 529911289LL, 2147483647LL, 435173527LL, + 2147483647LL, 339622636LL, 2147483647LL, 243411834LL, 2147483647LL, 146696288LL, + 2147483647LL, 49632877LL, 2147483647LL, -47620055LL, 2147483647LL, -144902955LL, + 2147483647LL, -242055314LL, 2147483647LL, -338915933LL, 2147483647LL, -435323185LL, + 2147483647LL, -531115284LL, 2147483647LL, -626130558LL, 2147483647LL, -720207723LL, + 2147483647LL, -813186158LL, 2147483647LL, -904906185LL, 2147483647LL, -995209348LL, + 2141127224LL, -1083938690LL, 2094787591LL, -1170939040LL, 2044856252LL, -1256057284LL, + 1991405758LL, -1339142654LL, 1934515087LL, -1420046998LL, 1874269551LL, -1498625060LL, + 1810760703LL, -1574734756LL, 1744086226LL, -1648237442LL, 1674349812LL, -1718998183LL, + 1601661030LL, -1786886017LL, 1526135182LL, -1851774219LL, 1447893144LL, -1913540549LL, + 1367061200LL, -1972067508LL, 1283770866LL, -2027242578LL, 1198158692LL, -2078958463LL, + 1110366072LL, -2127113316LL, 1020539021LL, -2147483648LL, 928827961LL, -2147483648LL, + 835387487LL, -2147483648LL, 740376121LL, -2147483648LL, 643956065LL, -2147483648LL, + 546292936LL, -2147483648LL, 447555502LL, -2147483648LL, 347915397LL, -2147483648LL, + 247546838LL, -2147483648LL, 146626334LL, -2147483648LL, 45332378LL, -2147483648LL, + -56154854LL, -2147483648LL, -157653819LL, -2147483648LL, -258981932LL, -2147483648LL, + -359955880LL, -2147483648LL, -460391963LL, -2147483648LL, -560106420LL, -2147483648LL, + -658915767LL, -2147483648LL, -756637142LL, -2147483648LL, -853088639LL, -2147483648LL, + -948089661LL, -2147483648LL, -1041461258LL, -2147483648LL, -1133026475LL, -2114353581LL, + -1222610698LL, -2063808689LL, -1310041997LL, -2009406689LL, -1395151470LL, -1951235148LL, + -1477773582LL, -1889389142LL, -1557746502LL, -1823971137LL, -1634912441LL, -1755090853LL, + -1709117976LL, -1682865118LL, -1780214379LL, -1607417698LL, -1848057934LL, -1528879122LL, + -1912510249LL, -1447386484LL, -1973438564LL, -1363083238LL, -2030716046LL, -1276118970LL, + -2084222081LL, -1186649163LL, -2133842551LL, -1094834946LL, -2147483648LL, -1000842829LL, + -2147483648LL, -904844421LL, -2147483648LL, -807016147LL, -2147483648LL, -707538938LL, + -2147483648LL, -606597919LL, -2147483648LL, -504382081LL, -2147483648LL, -401083947LL, + -2147483648LL, -296899220LL, -2147483648LL, -192026429LL, -2147483648LL, -86666559LL, + -2147483648LL, 18977320LL, -2147483648LL, 124700442LL, -2147483648LL, 230296729LL, + -2147483648LL, 335559194LL, -2147483648LL, 440280341LL, -2147483648LL, 544252573LL, + -2147483648LL, 647268605LL, -2147483648LL, 749121879LL, -2147483648LL, 849606986LL, + -2147483648LL, 948520082LL, -2147483648LL, 1045659314LL, -2108672310LL, 1140825239LL, + -2055596488LL, 1233821245LL, -1998355169LL, 1324453975LL, -1937049136LL, 1412533739LL, + -1871787942LL, 1497874933LL, -1802689754LL, 1580296446LL, -1729881180LL, 1659622065LL, + -1653497079LL, 1735680876LL, -1573680346LL, 1808307654LL, -1490581686LL, 1877343246LL, + -1404359362LL, 1942634950LL, -1315178931LL, 2004036881LL, -1223212956LL, 2061410320LL, + -1128640707LL, 2114624064LL, -1031647840LL, 2147483647LL, -932426060LL, 2147483647LL, + -831172771LL, 2147483647LL, -728090706LL, 2147483647LL, -623387547LL, 2147483647LL, + -517275524LL, 2147483647LL, -409971008LL, 2147483647LL, -301694085LL, 2147483647LL, + -192668120LL, 2147483647LL, -83119312LL, 2147483647LL, 26723767LL, 2147483647LL, + 136630639LL, 2147483647LL, 246369394LL, 2147483647LL, 355707180LL, 2147483647LL, + 464410687LL, 2147483647LL, 572246651LL, 2147483647LL, 678982353LL, 2147483647LL, + 784386126LL, 2147483647LL, 888227863LL, 2147483647LL, 990279531LL, 2147483647LL, + 1090315678LL, 2133631293LL, 1188113947LL, 2080707887LL, 1283455585LL, 2023237656LL, + 1376125948LL, 1961329785LL, 1465915004LL, 1895103735LL, 1552617834LL, 1824689062LL, + 1636035116LL, 1750225212LL, 1715973616LL, 1671861292LL, 1792246658LL, 1589755813LL, + 1864674592LL, 1504076417LL, 1933085247LL, 1414999573LL, 1997314371LL, 1322710256LL, + 2057206064LL, 1227401603LL, 2112613189LL, 1129274540LL, 2147483647LL, 1028537399LL, + 2147483647LL, 925405506LL, 2147483647LL, 820100751LL, 2147483647LL, 712851140LL, + 2147483647LL, 603890326LL, 2147483647LL, 493457130LL, 2147483647LL, 381795031LL, + 2147483647LL, 269151655LL, 2147483647LL, 155778241LL, 2147483647LL, 41929093LL, + 2147483647LL, -72138973LL, 2147483647LL, -186167205LL, 2147483647LL, -299895491LL, + 2147483647LL, -413062950LL, 2147483647LL, -525408528LL, 2147483647LL, -636671601LL, + 2147483647LL, -746592584LL, 2147483647LL, -854913543LL, 2147483647LL, -961378810LL, + 2144346503LL, -1065735596LL, 2090499674LL, -1167734610LL, 2031736068LL, -1267130667LL, + 1968176280LL, -1363683297LL, 1899952824LL, -1457157356LL, 1827209917LL, -1547323614LL, + 1750103229LL, -1633959351LL, 1668799600LL, -1716848933LL, 1583476736LL, -1795784384LL, + 1494322868LL, -1870565939LL, 1401536383LL, -1941002586LL, 1305325432LL, -2006912595LL, + 1205907506LL, -2068124025LL, 1103508985LL, -2124475212LL, 998364664LL, -2147483648LL, + 890717247LL, -2147483648LL, 780816830LL, -2147483648LL, 668920342LL, -2147483648LL, + 555290982LL, -2147483648LL, 440197622LL, -2147483648LL, 323914194LL, -2147483648LL, + 206719064LL, -2147483648LL, 88894376LL, -2147483648LL, -29274604LL, -2147483648LL, + -147500174LL, -2147483648LL, -265492883LL, -2147483648LL, -382962235LL, -2147483648LL, + -499617403LL, -2147483648LL, -615167950LL, -2147483648LL, -729324553LL, -2147483648LL, + -841799738LL, -2147483648LL, -952308612LL, -2147483648LL, -1060569598LL, -2145238212LL, + -1166305173LL, -2089583525LL, -1269242594LL, -2028650309LL, -1369114626LL, -1962573642LL, + -1465660266LL, -1891502311LL, -1558625447LL, -1815598542LL, -1647763744LL, -1735037697LL, + -1732837061LL, -1650007924LL, -1813616302LL, -1560709781LL, -1889882030LL, -1467355819LL, + -1961425106LL, -1370170129LL, -2028047306LL, -1269387857LL, -2089561918LL, -1165254686LL, + -2145794317LL, -1058026282LL, -2147483648LL, -947967711LL, -2147483648LL, -835352823LL, + -2147483648LL, -720463615LL, -2147483648LL, -603589551LL, -2147483648LL, -485026872LL, + -2147483648LL, -365077869LL, -2147483648LL, -244050140LL, -2147483648LL, -122255821LL, + -2147483648LL, -10799LL, -2147483648LL, 122366091LL, -2147483648LL, 244553890LL, + -2147483648LL, 366230345LL, -2147483648LL, 487072762LL, -2147483648LL, 606758857LL, + -2147483648LL, 724967621LL, -2147483648LL, 841380194LL, -2147483648LL, 955680730LL, + -2140044950LL, 1067557274LL, -2081968153LL, 1176702632LL, -2018254786LL, 1282815238LL, + -1949057180LL, 1385600014LL, -1874543809LL, 1484769220LL, -1794897884LL, 1580043298LL, + -1710317739LL, 1671151691LL, -1621016265LL, 1757833657LL, -1527220339LL, 1839839060LL, + -1429170381LL, 1916929133LL, -1327119786LL, 1988877232LL, -1221334318LL, 2055469546LL, + -1112091480LL, 2116505796LL, -999679842LL, 2147483647LL, -884398325LL, 2147483647LL, + -766555452LL, 2147483647LL, -646468571LL, 2147483647LL, -524463033LL, 2147483647LL, + -400871349LL, 2147483647LL, -276032309LL, 2147483647LL, -150290084LL, 2147483647LL, + -23993293LL, 2147483647LL, 102505943LL, 2147483647LL, 228852975LL, 2147483647LL, + 354691607LL, 2147483647LL, 479665101LL, 2147483647LL, 603417189LL, 2147483647LL, + 725593091LL, 2147483647LL, 845840543LL, 2147483647LL, 963810827LL, 2147483647LL, + 1079159803LL, 2132293834LL, 1191548930LL, 2071515791LL, 1300646292LL, 2004741366LL, + 1406127606LL, 1932142496LL, 1507677227LL, 1853908888LL, 1604989125LL, 1770247607LL, + 1697767860LL, 1681382603LL, 1785729520LL, 1587554197LL, 1868602645LL, 1489018501LL, + 1946129119LL, 1386046791LL, 2018065033LL, 1278924830LL, 2084181516LL, 1167952137LL, + 2144265524LL, 1053441211LL, 2147483647LL, 935716710LL, 2147483647LL, 815114582LL, + 2147483647LL, 691981152LL, 2147483647LL, 566672179LL, 2147483647LL, 439551859LL, + 2147483647LL, 310991808LL, 2147483647LL, 181370003LL, 2147483647LL, 51069698LL, + 2147483647LL, -79521693LL, 2147483647LL, -210013727LL, 2147483647LL, -340014092LL, + 2147483647LL, -469129785LL, 2147483647LL, -596968294LL, 2147483647LL, -723138800LL, + 2147483647LL, -847253386LL, 2147483647LL, -968928240LL, 2125756855LL, -1087784867LL, + 2062398857LL, -1203451293LL, 1992672115LL, -1315563259LL, 1916769302LL, -1423765409LL, + 1834903178LL, -1527712453LL, 1747306089LL, -1627070321LL, 1654229398LL, -1721517282LL, + 1555942852LL, -1810745049LL, 1452733879LL, -1894459839LL, 1344906833LL, -1972383410LL, + 1232782166LL, -2044254048LL, 1116695554LL, -2109827525LL, 996996952LL, -2147483648LL, + 874049604LL, -2147483648LL, 748229001LL, -2147483648LL, 619921780LL, -2147483648LL, + 489524590LL, -2147483648LL, 357442902LL, -2147483648LL, 224089786LL, -2147483648LL, + 89884652LL, -2147483648LL, -44748050LL, -2147483648LL, -179380146LL, -2147483648LL, + -313581097LL, -2147483648LL, -446919360LL, -2147483648LL, -578963780LL, -2147483648LL, + -709284990LL, -2147483648LL, -837456819LL, -2147483648LL, -963057700LL, -2147483648LL, + -1085672087LL, -2124535524LL, -1204891855LL, -2059175621LL, -1320317700LL, -1987048579LL, + -1431560512LL, -1908367459LL, -1538242741LL, -1823367979LL, -1639999727LL, -1732307924LL, + -1736481011LL, -1635466457LL, -1827351602LL, -1533143365LL, -1912293210LL, -1425658224LL, + -1991005437LL, -1313349488LL, -2063206919LL, -1196573507LL, -2128636407LL, -1075703477LL, + -2147483648LL, -951128319LL, -2147483648LL, -823251497LL, -2147483648LL, -692489772LL, + -2147483648LL, -559271904LL, -2147483648LL, -424037289LL, -2147483648LL, -287234560LL, + -2147483648LL, -149320134LL, -2147483648LL, -10756719LL, -2147483648LL, 127988214LL, + -2147483648LL, 266443994LL, -2147483648LL, 404138332LL, -2147483648LL, 540598934LL, + -2147483648LL, 675355124LL, -2147483648LL, 807939480LL, -2147483648LL, 937889473LL, + -2132662129LL, 1064749107LL, -2066402479LL, 1188070553LL, -1992933886LL, 1307415773LL, + -1912487302LL, 1422358116LL, -1825319247LL, 1532483904LL, -1731711107LL, 1637393977LL, + -1631968340LL, 1736705209LL, -1526419591LL, 1830051979LL, -1415415708LL, 1917087595LL, + -1299328681LL, 1997485668LL, -1178550484LL, 2070941423LL, -1053491844LL, 2137172948LL, + -924580921LL, 2147483647LL, -792261921LL, 2147483647LL, -656993630LL, 2147483647LL, + -519247888LL, 2147483647LL, -379507996LL, 2147483647LL, -238267068LL, 2147483647LL, + -96026326LL, 2147483647LL, 46706642LL, 2147483647LL, 189419676LL, 2147483647LL, + 331597860LL, 2147483647LL, 472725380LL, 2147483647LL, 612287391LL, 2147483647LL, + 749771909LL, 2147483647LL, 884671705LL, 2147483647LL, 1016486202LL, 2147483647LL, + 1144723371LL, 2088028682LL, 1268901605LL, 2014865411LL, 1388551583LL, 1934232350LL, + 1503218100LL, 1846401862LL, 1612461865LL, 1751674418LL, 1715861259LL, 1650377695LL, + 1813014039LL, 1542865569LL, 1903538997LL, 1429516997LL, 1987077542LL, 1310734788LL, + 2063295226LL, 1186944283LL, 2131883185LL, 1058591929LL, 2147483647LL, 926143758LL, + 2147483647LL, 790083780LL, 2147483647LL, 650912292LL, 2147483647LL, 509144108LL, + 2147483647LL, 365306709LL, 2147483647LL, 219938336LL, 2147483647LL, 73586019LL, + 2147483647LL, -73196451LL, 2147483647LL, -219850592LL, 2147483647LL, -365815341LL, + 2147483647LL, -510529197LL, 2147483647LL, -653432382LL, 2147483647LL, -793969023LL, + 2147483647LL, -931589338LL, 2126553466LL, -1065751815LL, 2056040308LL, -1195925393LL, + 1977477010LL, -1321591610LL, 1891143090LL, -1442246729LL, 1797349968LL, -1557403830LL, + 1696439995LL, -1666594851LL, 1588785339LL, -1769372580LL, 1474786750LL, -1865312578LL, + 1354872192LL, -1954015035LL, 1229495360LL, -2035106549LL, 1099134076LL, -2108241809LL, + 964288570LL, -2147483648LL, 825479659LL, -2147483648LL, 683246823LL, -2147483648LL, + 538146185LL, -2147483648LL, 390748408LL, -2147483648LL, 241636507LL, -2147483648LL, + 91403591LL, -2147483648LL, -59349454LL, -2147483648LL, -210016344LL, -2147483648LL, + -359987818LL, -2147483648LL, -508654093LL, -2147483648LL, -655407353LL, -2147483648LL, + -799644243LL, -2147483648LL, -940768385LL, -2147483648LL, -1078192872LL, -2117053835LL, + -1211342768LL, -2043646033LL, -1339657562LL, -1961779408LL, -1462593605LL, -1871763538LL, + -1579626491LL, -1773943126LL, -1690253380LL, -1668697156LL, -1793995263LL, -1556437522LL, + -1890399143LL, -1437607520LL, -1979040127LL, -1312680269LL, -2059523426LL, -1182156950LL, + -2131486245LL, -1046564915LL, -2147483648LL, -906455674LL, -2147483648LL, -762402751LL, + -2147483648LL, -614999434LL, -2147483648LL, -464856412LL, -2147483648LL, -312599318LL, + -2147483648LL, -158866181LL, -2147483648LL, -4304800LL, -2147483648LL, 150429950LL, + -2147483648LL, 304678867LL, -2147483648LL, 457781223LL, -2147483648LL, 609077593LL, + -2147483648LL, 757912711LL, -2147483648LL, 903638333LL, -2129915237LL, 1045616102LL, + -2056502131LL, 1183220395LL, -1974115089LL, 1315841141LL, -1883082711LL, 1442886607LL, + -1783773072LL, 1563786118LL, -1676592409LL, 1677992725LL, -1561983635LL, 1784985787LL, + -1440424669LL, 1884273464LL, -1312426602LL, 1975395108LL, -1178531690LL, 2057923536LL, + -1039311196LL, 2131467185LL, -895363074LL, 2147483647LL, -747309517LL, 2147483647LL, + -595794369LL, 2147483647LL, -441480411LL, 2147483647LL, -285046544LL, 2147483647LL, + -127184862LL, 2147483647LL, 31402360LL, 2147483647LL, 190005749LL, 2147483647LL, + 347911991LL, 2147483647LL, 504407029LL, 2147483647LL, 658779293LL, 2147483647LL, + 810322964LL, 2147483647LL, 958341229LL, 2147483647LL, 1102149538LL, 2097366804LL, + 1241078830LL, 2018091406LL, 1374478724LL, 1929524070LL, 1501720653LL, 1832040426LL, + 1622200931LL, 1726059136LL, 1735343730LL, 1612040289LL, 1840603962LL, 1490483593LL, + 1937470046LL, 1361926359LL, 2025466539LL, 1226941290LL, 2104156638LL, 1086134087LL, + 2147483647LL, 940140868LL, 2147483647LL, 789625429LL, 2147483647LL, 635276339LL, + 2147483647LL, 477803895LL, 2147483647LL, 317936939LL, 2147483647LL, 156419558LL, + 2147483647LL, -5992318LL, 2147483647LL, -168534414LL, 2147483647LL, -330437681LL, + 2147483647LL, -490931919LL, 2147483647LL, -649249453LL, 2147483647LL, -804628819LL, + 2147483647LL, -956318473LL, 2092510290LL, -1103580472LL, 2010956767LL, -1245694141LL, + 1919660590LL, -1381959680LL, 1819030526LL, -1511701714LL, 1709522720LL, -1634272754LL, + 1591638836LL, -1749056562LL, 1465923962LL, -1855471388LL, 1332964286LL, -1952973081LL, + 1193384537LL, -2041058032LL, 1047845218LL, -2119265963LL, 897039637LL, -2147483648LL, + 741690740LL, -2147483648LL, 582547770LL, -2147483648LL, 420382761LL, -2147483648LL, + 255986882LL, -2147483648LL, 90166658LL, -2147483648LL, -76259938LL, -2147483648LL, + -242467474LL, -2147483648LL, -407627135LL, -2147483648LL, -570910852LL, -2147483648LL, + -731495468LL, -2147483648LL, -888566926LL, -2147483648LL, -1041324440LL, -2119895861LL, + -1188984653LL, -2040529808LL, -1330785743LL, -1950790391LL, -1465991453LL, -1851098737LL, + -1593895044LL, -1741928770LL, -1713823120LL, -1623805248LL, -1825139333LL, -1497301457LL, + -1927247928LL, -1363036636LL, -2019597110LL, -1221673155LL, -2101682228LL, -1073913430LL, + -2147483648LL, -920496605LL, -2147483648LL, -762195011LL, -2147483648LL, -599810414LL, + -2147483648LL, -434170079LL, -2147483648LL, -266122655LL, -2147483648LL, -96533908LL, + -2147483648LL, 73717669LL, -2147483648LL, 243745369LL, -2147483648LL, 412658864LL, + -2147483648LL, 579568866LL, -2147483648LL, 743591823LL, -2147483648LL, 903854640LL, + -2106125973LL, 1059499382LL, -2023364891LL, 1209687950LL, -1929803137LL, 1353606690LL, + -1825903713LL, 1490470926LL, -1712187260LL, 1619529369LL, -1589229710LL, 1740068406LL, + -1457659617LL, 1851416213LL, -1318155169LL, 1952946697LL, -1171440915LL, 2044083214LL, + -1018284200LL, 2124302071LL, -859491330LL, 2147483647LL, -695903496LL, 2147483647LL, + -528392458LL, 2147483647LL, -357856026LL, 2147483647LL, -185213348LL, 2147483647LL, + -11400042LL, 2147483647LL, 162636823LL, 2147483647LL, 335943844LL, 2147483647LL, + 507566501LL, 2147483647LL, 676554416LL, 2147483647LL, 841966660LL, 2147483647LL, + 1002877037LL, 2128758758LL, 1158379359LL, 2048045411LL, 1307592649LL, 1955885061LL, + 1449666254LL, 1852754819LL, 1583784845LL, 1739195667LL, 1709173261LL, 1615809912LL, + 1825101175LL, 1483258257LL, 1930887555LL, 1342256525LL, 2025904887LL, 1193572034LL, + 2109583137LL, 1038019639LL, 2147483647LL, 876457472LL, 2147483647LL, 709782388LL, + 2147483647LL, 538925148LL, 2147483647LL, 364845356LL, 2147483647LL, 188526185LL, + 2147483647LL, 10968912LL, 2147483647LL, -166812702LL, 2147483647LL, -343798163LL, + 2147483647LL, -518966088LL, 2147483647LL, -691300111LL, 2147483647LL, -859794826LL, + 2113538466LL, -1023461707LL, 2029242945LL, -1181335008LL, 1933064585LL, -1332477574LL, + 1825527308LL, -1475986545LL, 1707224349LL, -1610998915LL, 1578815298LL, -1736696911LL, + 1441022715LL, -1852313153LL, 1294628341LL, -1957135576LL, 1140468917LL, -2050512057LL, + 979431639LL, -2131854746LL, 812449264LL, -2147483648LL, 640494899LL, -2147483648LL, + 464576491LL, -2147483648LL, 285731064LL, -2147483648LL, 105018711LL, -2147483648LL, + -76483598LL, -2147483648LL, -257688385LL, -2147483648LL, -437504143LL, -2147483648LL, + -614841922LL, -2147483648LL, -788621946LL, -2147483648LL, -957780250LL, -2138565363LL, + -1121275285LL, -2057257530LL, -1278094442LL, -1963364026LL, -1427260475LL, -1857418376LL, + -1567837760LL, -1740030720LL, -1698938361LL, -1611884650LL, -1819727863LL, -1473733546LL, + -1929430930LL, -1326396460LL, -2027336547LL, -1170753542LL, -2112802920LL, -1007741042LL, + -2147483648LL, -838345920LL, -2147483648LL, -663600079LL, -2147483648LL, -484574260LL, + -2147483648LL, -302371643LL, -2147483648LL, -118121166LL, -2147483648LL, 67029367LL, + -2147483648LL, 251920380LL, -2147483648LL, 435387752LL, -2147483648LL, 616270147LL, + -2147483648LL, 793416403LL, -2128966591LL, 965692922LL, -2045071025LL, 1131991020LL, + -1948097959LL, 1291234198LL, -1838625312LL, 1442385265LL, -1717314053LL, 1584453289LL, + -1584904587LL, 1716500314LL, -1442212584LL, 1837647799LL, -1290124281LL, 1947082734LL, + -1129591288LL, 2044063401LL, -961624905LL, 2127924712LL, -787290011LL, 2147483647LL, + -607698525LL, 2147483647LL, -424002511LL, 2147483647LL, -237386947LL, 2147483647LL, + -49062198LL, 2147483647LL, 139743735LL, 2147483647LL, 327793174LL, 2147483647LL, + 513846851LL, 2147483647LL, 696672099LL, 2147483647LL, 875051066LL, 2147483647LL, + 1047788922LL, 2083103113LL, 1213721979LL, 1990629790LL, 1371725696LL, 1884844495LL, + 1520722495LL, 1766411543LL, 1659689327LL, 1636083367LL, 1787664967LL, 1494696130LL, + 1903756938LL, 1343164721LL, 2007148057LL, 1182477181LL, 2097102525LL, 1013688569LL, + 2147483647LL, 837914321LL, 2147483647LL, 656323128LL, 2147483647LL, 470129378LL, + 2147483647LL, 280585222LL, 2147483647LL, 88972295LL, 2147483647LL, -103406844LL, + 2147483647LL, -295237500LL, 2147483647LL, -485201796LL, 2147483647LL, -671987742LL, + 2147483647LL, -854298345LL, 2084690021LL, -1030860713LL, 1991481747LL, -1200435068LL, + 1884386360LL, -1361823626LL, 1764106224LL, -1513879266LL, 1631439397LL, -1655513925LL, + 1487274755LL, -1785706668LL, 1332586439LL, -1903511358LL, 1168427638LL, -2008063875LL, + 995923753LL, -2098588822LL, 816264990LL, -2147483648LL, 630698412LL, -2147483648LL, + 440519514LL, -2147483648LL, 247063370LL, -2147483648LL, 51695411LL, -2147483648LL, + -144198109LL, -2147483648LL, -339219882LL, -2147483648LL, -531971491LL, -2147483648LL, + -721063468LL, -2147483648LL, -905125371LL, -2135487129LL, -1082815837LL, -2050705943LL, + -1252832508LL, -1951055422LL, -1413921776LL, -1837211762LL, -1564888270LL, -1709957770LL, + -1704604004LL, -1570177954LL, -1832017122LL, -1418852823LL, -1946160172LL, -1257052423LL, + -2046157838LL, -1085929157LL, -2131234063LL, -906709925LL, -2147483648LL, -720687636LL, + -2147483648LL, -529212153LL, -2147483648LL, -333680721LL, -2147483648LL, -135527955LL, + -2147483648LL, 63784547LL, -2147483648LL, 262778902LL, -2147483648LL, 459971856LL, + -2147483648LL, 653885847LL, -2147483648LL, 843060138LL, -2072173321LL, 1026061923LL, + -1975175058LL, 1201497335LL, -1863230518LL, 1368022267LL, -1737139926LL, 1524352913LL, + -1597814827LL, 1669275965LL, -1446271989LL, 1801658355LL, -1283626438LL, 1920456499LL, + -1111083679LL, 2024724924LL, -929931141LL, 2113624245LL, -741528910LL, 2147483647LL, + -547299821LL, 2147483647LL, -348718956LL, 2147483647LL, -147302644LL, 2147483647LL, + 55402963LL, 2147483647LL, 257833667LL, 2147483647LL, 458419243LL, 2147483647LL, + 655595635LL, 2147483647LL, 847817205LL, 2143954637LL, 1033568973LL, 2060380053LL, + 1211378727LL, 1960632799LL, 1379828908LL, 1845446693LL, 1537568189LL, 1715680797LL, + 1683322634LL, 1572313566LL, 1815906356LL, 1416435995LL, 1934231575LL, 1249243805LL, + 2037317991LL, 1072028717LL, 2124301398LL, 886168876LL, 2147483647LL, 693118492LL, + 2147483647LL, 494396770LL, 2147483647LL, 291576214LL, 2147483647LL, 86270381LL, + 2147483647LL, -119878809LL, 2147483647LL, -325214113LL, 2147483647LL, -528076262LL, + 2147483647LL, -726817394LL, 2105697194LL, -919814539LL, 2013926533LL, -1105483009LL, + 1905700003LL, -1282289626LL, 1781852078LL, -1448765640LL, 1643349426LL, -1603519251LL, + 1491283941LL, -1745247612LL, 1326864681LL, -1872748222LL, 1151408761LL, -1984929589LL, + 966331256LL, -2080821085LL, 773134199LL, -2147483648LL, 573394743LL, -2147483648LL, + 368752589LL, -2147483648LL, 160896766LL, -2147483648LL, -48448135LL, -2147483648LL, + -257536147LL, -2147483648LL, -464614439LL, -2147483648LL, -667938024LL, -2147483648LL, + -865784537LL, -2120150699LL, -1056468971LL, -2031341914LL, -1238358234LL, -1925303427LL, + -1409885402LL, -1802883311LL, -1569563551LL, -1665073254LL, -1715999031LL, -1513001163LL, + -1847904077LL, -1347922527LL, -1964108619LL, -1171210598LL, -2063571211LL, -984345467LL, + -2145388936LL, -788902112LL, -2147483648LL, -586537515LL, -2147483648LL, -378976933LL, + -2147483648LL, -167999460LL, -2147483648LL, 44577031LL, -2147483648LL, 256911423LL, + -2147483648LL, 467155244LL, -2147483648LL, 673468772LL, -2107901011LL, 874037220LL, + -2016493753LL, 1067086857LL, -1907326612LL, 1250900918LL, -1781308682LL, 1423835167LL, + -1639502465LL, 1584332971LL, -1483115585LL, 1730939726LL, -1313491135LL, 1862316536LL, + -1132096720LL, 1977252969LL, -940512288LL, 2074678805LL, -740416830LL, 2147483647LL, + -533574073LL, 2147483647LL, -321817264LL, 2147483647LL, -107033188LL, 2147483647LL, + 108854455LL, 2147483647LL, 323902162LL, 2147483647LL, 536164091LL, 2147483647LL, + 743709705LL, 2147483647LL, 944641447LL, 2067687349LL, 1137112293LL, 1967807091LL, + 1319342995LL, 1849926100LL, 1489638876LL, 1715069866LL, 1646406012LL, 1564424718LL, + 1788166630LL, 1399328087LL, 1913573587LL, 1221257288LL, 2021423777LL, 1031816889LL, + 2110670331LL, 832724791LL, 2147483647LL, 625797109LL, 2147483647LL, 412931997LL, + 2147483647LL, 196092557LL, 2147483647LL, -22711028LL, 2147483647LL, -241439978LL, + 2147483647LL, -458045837LL, 2147483647LL, -670489670LL, 2088028562LL, -876761354LL, + 1992651538LL, -1074898783LL, 1878395020LL, -1263006794LL, 1746287139LL, -1439275644LL, + 1597530798LL, -1601998846LL, 1433493488LL, -1749590192LL, 1255695425LL, -1880599785LL, + 1065796112LL, -1993728917LL, 865579431LL, -2087843635LL, 656937402LL, -2147483648LL, + 441852731LL, -2147483648LL, 222380323LL, -2147483648LL, 627914LL, -2147483648LL, + -221263992LL, -2147483648LL, -441142700LL, -2147483648LL, -656864216LL, -2147483648LL, + -866314249LL, -2082569005LL, -1067429124LL, -1986344746LL, -1258216403LL, -1870623123LL, + -1436774989LL, -1736484571LL, -1601314532LL, -1585196237LL, -1750173912LL, -1418200824LL, + -1881838627LL, -1237103590LL, -1994956884LL, -1043657610LL, -2088354225LL, -839747418LL, + -2147483648LL, -627371191LL, -2147483648LL, -408621619LL, -2147483648LL, -185665648LL, + -2147483648LL, 39276717LL, -2147483648LL, 263954342LL, -2147483648LL, 486107420LL, + -2133675122LL, 703490230LL, -2051714426LL, 913893960LL, -1948945971LL, 1115169386LL, + -1826354126LL, 1305249149LL, -1685129914LL, 1482169411LL, -1526660350LL, 1644090662LL, + -1352515671LL, 1789317444LL, -1164434563LL, 1916316785LL, -964307511LL, 2023735139LL, + -754158424LL, 2110413626LL, -536124712LL, 2147483647LL, -312435986LL, 2147483647LL, + -85391611LL, 2147483647LL, 142662691LL, 2147483647LL, 369358935LL, 2147483647LL, + 592331438LL, 2147483647LL, 809241582LL, 2085180731LL, 1017802536LL, 1990999277LL, + 1215803663LL, 1875890143LL, 1401134358LL, 1741005427LL, 1571807046LL, 1587711489LL, + 1725979106LL, 1417576041LL, 1861973456LL, 1232352987LL, 1978297567LL, 1033965127LL, + 2073660700LL, 824484903LL, 2146989139LL, 606113358LL, 2147483647LL, 381157521LL, + 2147483647LL, 152006437LL, 2147483647LL, -78893909LL, 2147483647LL, -309066524LL, + 2147483647LL, -536029919LL, 2094228819LL, -757324912LL, 2003603310LL, -970541456LL, + 1891209265LL, -1173345177LL, 1758208570LL, -1363503336LL, 1605993512LL, -1538909934LL, + 1436173223LL, -1697609658LL, 1250557592LL, -1837820402LL, 1051138837LL, -1957954094LL, + 840070879LL, -2056635581LL, 619646739LL, -2132719336LL, 392274176LL, -2147483648LL, + 160449831LL, -2147483648LL, -73267873LL, -2147483648LL, -306286770LL, -2147483648LL, + -536009632LL, -2147483648LL, -759863179LL, -2082504117LL, -975327092LL, -1989946809LL, + -1179962705LL, -1875038155LL, -1371441045LL, -1739008743LL, -1547569902LL, -1583333285LL, + -1706319596LL, -1409715698LL, -1845847152LL, -1220071439LL, -1964518572LL, -1016507264LL, + -2060928936LL, -801298626LL, -2133920076LL, -576864919LL, -2147483648LL, -345742851LL, + -2147483648LL, -110558213LL, -2147483648LL, 126003639LL, -2147483648LL, 361228266LL, + -2125969458LL, 592403253LL, -2049459451LL, 816849585LL, -1949213484LL, 1031952929LL, + -1826329847LL, 1235194461LL, -1682175439LL, 1424180865LL, -1518371743LL, 1596673149LL, + -1336777696LL, 1750613932LL, -1139469600LL, 1884152844LL, -928718303LL, 1995669741LL, + -706963860LL, 2083795417LL, -476787964LL, 2147429551LL, -240884439LL, 2147483647LL, + -2028122LL, 2147483647LL, 236957502LL, 2147483647LL, 473233557LL, 2145199580LL, + 703979526LL, 2080141908LL, 926427095LL, 1990238712LL, 1137893694LL, 1876498999LL, + 1335815318LL, 1740222619LL, 1517778223LL, 1582986702LL, 1681549117LL, 1406628616LL, + 1825103435LL, 1213225612LL, 1946651354LL, 1005071375LL, 2044661202LL, 784649717LL, + 2117879931LL, 554605711LL, 2147483647LL, 317714581LL, 2147483647LL, 76848712LL, + 2147483647LL, -165056841LL, 2147483647LL, -405039946LL, 2089631703LL, -640147639LL, + 2005116332LL, -867472607LL, 1895831702LL, -1084189447LL, 1763063857LL, -1287590237LL, + 1608396332LL, -1475118994LL, 1433692562LL, -1644404554LL, 1241074642LL, -1793291446LL, + 1032898641LL, -1919868372LL, 811726762LL, -2022493871LL, 580296639LL, -2099818848LL, + 341488148LL, -2147483648LL, 98288101LL, -2147483648LL, -146246733LL, -2147483648LL, + -389027846LL, -2140324081LL, -626973969LL, -2082259649LL, -857050316LL, -1997731773LL, + -1076307608LL, -1887747183LL, -1281920364LL, -1753642453LL, -1471223962LL, -1597069221LL, + -1641749977LL, -1419975226LL, -1791259326LL, -1224581351LL, -1917772756LL, -1013354930LL, + -2019598259LL, -788979611LL, -2095355015LL, -554322140LL, -2143993518LL, -312396450LL, + -2147483648LL, -66325504LL, -2147483648LL, 180698648LL, -2121979143LL, 425456079LL, + -2058742235LL, 664740952LL, -1968511775LL, 895403691LL, -1852402722LL, 1114392801LL, + -1711876213LL, 1318795784LL, -1548722712LL, 1505878602LL, -1365040626LL, 1673123133LL, + -1163210640LL, 1818262110LL, -945866044LL, 1939311053LL, -715859420LL, 2034596709LL, + -476226084LL, 2102781603LL, -230144739LL, 2142884317LL, 19104169LL, 2147483647LL, + 268181846LL, 2136787027LL, 513735739LL, 2090521088LL, 752444723LL, 2016047417LL, + 981064290LL, 1914300252LL, 1196471101LL, 1786588035LL, 1395706320LL, 1634578254LL, + 1576017094LL, 1460277248LL, 1734895606LL, 1266005189LL, 1870115129LL, 1054366530LL, + 1979762557LL, 828216274LL, 2062266915LL, 590622479LL, 2116423420LL, 344825479LL, + 2141412693LL, 94194338LL, 2136814815LL, -157818878LL, 2102617961LL, -407726408LL, + 2039221431LL, -652053042LL, 1947432977LL, -887384633LL, 1828460394LL, -1110416210LL, + 1683897421LL, -1317999006LL, 1515704096LL, -1507185726LL, 1326181772LL, -1675273399LL, + 1117943085LL, -1819843182LL, 893877240LL, -1938796512LL, 657111064LL, -2030387058LL, + 410966312LL, -2093247963LL, 158913816LL, -2126413940LL, -95474927LL, -2129337837LL, + -348578051LL, -2101901391LL, -596774801LL, -2044419919LL, -836497481LL, -1957640836LL, + -1064283109LL, -1842735943LL, -1276824051LL, -1701287509LL, -1471016862LL, -1535268304LL, + -1644008639LL, -1347015783LL, -1793240147LL, -1139200731LL, -1916485081LL, -914790779LL, + -2011884829LL, -677009242LL, -2077978183LL, -429289843LL, -2113725504LL, -175227938LL, + -2118526917LL, 81471088LL, -2092234201LL, 337045515LL, -2035156137LL, 587732313LL, + -1948057134LL, 829822691LL, -1832149108LL, 1059717361LL, -1689076634LL, 1273980681LL, + -1520895521LL, 1469392862LL, -1330045063LL, 1642999442LL, -1119314294LL, 1792157250LL, + -891802700LL, 1914576125LL, -650875901LL, 2008355728LL, -400116927LL, 2072016821LL, + -143273760LL, 2104526491LL, 115796100LL, 2105316852LL, 373183235LL, 2074296887LL, + 624985231LL, 2011857147LL, 867366038LL, 1918867173LL, 1096614859LL, 1796665595LL, + 1309203676LL, 1647042959LL, 1501842499LL, 1472217484LL, 1671531473LL, 1274804026LL, + 1815609000LL, 1057776655LL, 1931795091LL, 824425348LL, 2018229216LL, 578307400LL, + 2073502009LL, 323194253LL, 2096680261LL, 63014508LL, 2087324734LL, -198206037LL, + 2045500439LL, -456406406LL, 1971779126LL, -707553595LL, 1867233869LL, -947705855LL, + 1733425719LL, -1173075131LL, 1572382570LL, -1380087659LL, 1386570466LL, -1565441733LL, + 1178857720LL, -1726161713LL, 952472336LL, -1859647362LL, 710953326LL, -1963717681LL, + 458096637LL, -2036648473LL, 197896486LL, -2077202975LL, -65517020LL, -2084654981LL, + -327943001LL, -2058804003LL, -585176664LL, -1999982134LL, -833076839LL, -1909052405LL, + -1067633104LL, -1787398573LL, -1285031420LL, -1636906401LL, -1481717186LL, -1459936632LL, + -1654454661LL, -1259290016LL, -1800381751LL, -1038164853LL, -1917059200LL, -800107669LL, + -2002513335LL, -548957749LL, -2055271567LL, -288786373LL, -2074390010LL, -23831675LL, + -2059472644LL, 241569822LL, -2010681634LL, 503053935LL, -1928738521LL, 756300649LL, + -1814916157LL, 997105873LL, -1671021421LL, 1221451931LL, -1499368906LL, 1425575601LL, + -1302745881LL, 1606032532LL, -1084369062LL, 1759756927LL, -847833775LL, 1884115441LL, + -597056316LL, 1976954307LL, -336210378LL, 2036638837LL, -69658559LL, 2062084534LL, + 198119945LL, 2052779194LL, 462604287LL, 2008795530LL, 719308305LL, 1930793975LL, + 963856974LL, 1820015531LL, 1192061656LL, 1678264650LL, 1399992858LL, 1507882336LL, + 1584049224LL, 1311709821LL, 1741021526LL, 1093043321LL, 1868150494LL, 855580558LL, + 1963177432LL, 603359874LL, 2024386641LL, 340692904LL, 2050638842LL, 72091903LL, + 2041394891LL, -197807068LL, 1996729296LL, -464323823LL, 1917333145LL, -722815211LL, + 1804506310LL, -968756392LL, 1660138914LL, -1197820768LL, 1486682274LL, -1405957178LL, + 1287109725LL, -1589462954LL, 1064867872LL, -1745051502LL, 823819048LL, -1869913154LL, + 568175887LL, -1961768142LL, 302429087LL, -2018910644LL, 31269565LL, -2040243044LL, + -240493662LL, -2025299659LL, -508018456LL, -1974259399LL, -766515910LL, -1887947015LL, + -1011336526LL, -1767822766LL, -1238054683LL, -1615960572LL, -1442549837LL, -1435014912LL, + -1621082960LL, -1228176935LL, -1770366763LL, -999120458LL, -1887628381LL, -751938724LL, + -1970663267LL, -491072946LL, -2017879232LL, -221233875LL, -2028329708LL, 52682284LL, + -2001735492LL, 325682108LL, -1938494460LL, 592765781LL, -1839678919LL, 849018872LL, + -1707020511LL, 1089703366LL, -1542882807LL, 1310346284LL, -1350221962LL, 1506824193LL, + -1132536017LL, 1675442014LL, -893803668LL, 1813004587LL, -638413525LL, 1916879571LL, + -371085074LL, 1985050420LL, -96782722LL, 2016158311LL, 179375529LL, 2009532131LL, + 452213131LL, 1965205802LL, 716592006LL, 1883922495LL, 967509725LL, 1767125487LL, + 1200195002LL, 1616935691LL, 1410199677LL, 1436116132LL, 1593485403LL, 1228023897LL, + 1746503308LL, 996550331LL, 1866265049LL, 746050495LL, 1950403785LL, 481263096LL, + 1997223794LL, 207222352LL, 2005737639LL, -70836648LL, 1975690040LL, -347577296LL, + 1907567828LL, -617663696LL, 1802595630LL, -875863802LL, 1662717219LL, -1117151493LL, + 1490562709LL, -1336805571LL, 1289402097LL, -1530503722LL, 1063085882LL, -1694409553LL, + 815973795LL, -1825250913LL, 552852890LL, -1920387865LL, 278846498LL, -1977868864LL, + -684273LL, -1996473877LL, -280244631LL, -1975743472LL, -554313783LL, -1915993119LL, + -817454112LL, -1818312263LL, -1064419703LL, -1684548011LL, -1290262036LL, -1517273582LL, + -1490430706LL, -1319741979LL, -1660867101LL, -1095825646LL, -1798089074LL, -849943152LL, + -1899264805LL, -586974240LL, -1962274240LL, -312164813LL, -1985756729LL, -31023670LL, + -1969143737LL, 250787023LL, -1912675798LL, 527565361LL, -1817403188LL, 793685176LL, + -1685170113LL, 1043711021LL, -1518582561LL, 1272510307LL, -1320960271LL, 1475360273LL, + -1096273645LL, 1648047527LL, -849066712LL, 1786958028LL, -584367586LL, 1889155557LL, + -307588114LL, 1952446906LL, -24414680LL, 1975432300LL, 259307680LL, 1957539841LL, + 537695510LL, 1899043052LL, 804949067LL, 1801061001LL, 1055473814LL, 1665540767LL, + 1283998733LL, 1495222444LL, 1485688929LL, 1293587200LL, 1656250112LL, 1064789295LL, + 1792022637LL, 813573321LL, 1890063017LL, 545178220LL, 1948211038LL, 265229987LL, + 1965140882LL, -20374818LL, 1940394996LL, -305592357LL, 1874399788LL, -584359067LL, + 1768462605LL, -850720785LL, 1624749850LL, -1098960724LL, 1446246492LL, -1323723518LL, + 1236697625LL, -1520132637LL, 1000533135LL, -1683898573LL, 742776905LL, -1811415334LL, + 468942355LL, -1899843053LL, 184916418LL, -1947174744LL, -103165650LL, -1952285575LL, + -389052006LL, -1914963395LL, -666509703LL, -1835919630LL, -929460986LL, -1716780086LL, + -1172117442LL, -1560055630LL, -1389109009LL, -1369093177LL, -1575604959LL, -1148007821LL, + -1727424084LL, -901597407LL, -1841131532LL, -635241234LL, -1914119984LL, -354784947LL, + -1944673206LL, -66414028LL, -1932010333LL, 223481430LL, -1876309713LL, 508447751LL, + -1778711514LL, 782111399LL, -1641298812LL, 1038322228LL, -1467057331LL, 1271293019LL, + -1259814511LL, 1475732118LL, -1024159029LL, 1646966114LL, -765342381LL, 1781049655LL, + -489164557LL, 1874859778LL, -201846212LL, 1926172426LL, 90109897LL, 1933719203LL, + 380065174LL, 1897222865LL, 661395881LL, 1817410466LL, 927644878LL, 1696003634LL, + 1172670912LL, 1535685907LL, 1390792015LL, 1340047659LL, 1576919604LL, 1113509592LL, + 1726680101LL, 861226352LL, 1836521097LL, 588972262LL, 1903799425LL, 303011620LL, + 1926848880LL, 9956426LL, 1905025778LL, -283385313LL, 1838731033LL, -570167230LL, + 1729407974LL, -843664596LL, 1579515663LL, -1097432911LL, 1392478085LL, -1325461360LL, + 1172610111LL, -1522317443LL, 925021741LL, -1683279259LL, 655502636LL, -1804452168LL, + 370389462LL, -1882866885LL, 76419010LL, -1916556458LL, -219429564LL, -1904610048LL, + -510099738LL, -1847201967LL, -788625975LL, -1745594995LL, -1048301440LL, -1602117602LL, + -1282841020LL, -1420115321LL, -1486535668LL, -1203877170LL, -1654394247LL, -958538587LL, + -1782269273LL, -689962996LL, -1866963348LL, -404604613LL, -1906313446LL, -109355626LL, + -1899250762LL, 188618691LL, -1845834368LL, 482053056LL, -1747257565LL, 763759286LL, + -1605826455LL, 1026803125LL, -1424910949LL, 1264676461LL, -1208869101LL, 1471460598LL, + -962946342LL, 1641976476LL, -693151814LL, 1771917948LL, -406114622LL, 1857964608LL, + -108923355LL, 1897871155LL, 191047325LL, 1890530762LL, 486318818LL, 1836010592LL, + 769495005LL, 1735558250LL, 1033448293LL, 1591578669LL, 1271500625LL, 1407581683LL, + 1477594808LL, 1188101269LL, 1646451741LL, 938588185LL, 1773709373LL, 665278402LL, + 1856039683LL, 375040424LL, 1891240427LL, 75205104LL, 1878299039LL, -226617869LL, + 1817426740LL, -522732299LL, 1710061621LL, -805551785LL, 1558840283LL, -1067795015LL, + 1367538406LL, -1302675002LL, 1140981406LL, -1504077323LL, 884927171LL, -1666722621LL, + 605923576LL, -1786308992LL, 311144201LL, -1859630311LL, 8206267LL, -1884667169LL, + -295024662LL, -1860647712LL, -590638253LL, -1788076463LL, -870886026LL, -1668730007LL, + -1128385626LL, -1505619255LL, -1356317357LL, -1302918927LL, -1548607686LL, -1065865708LL, + -1700094741LL, -800627431LL, -1806671202LL, -514146414LL, -1865400534LL, -213960805LL, + -1874603171LL, 91991549LL, -1833909998LL, 395581693LL, -1744281340LL, 688705172LL, + -1607990549LL, 963498982LL, -1428572217LL, 1212554028LL, -1210736023LL, 1429117354LL, + -960248113LL, 1607278548LL, -683782875LL, 1742135124LL, -388748766LL, 1829932156LL, + -83092626LL, 1868172072LL, 224912450LL, 1855691292LL, 526890076LL, 1792701231LL, + 814588427LL, 1680792148LL, 1080106776LL, 1522899290LL, 1316114503LL, 1323231859LL, + 1516056451LL, 1087166295LL, 1674338824LL, 821106435LL, 1786490260LL, 532314007LL, + 1849293344LL, 228713834LL, 1860882558LL, -81321160LL, 1820805579LL, -389199370LL, + 1730045772LL, -686348157LL, 1591004827LL, -964453154LL, 1407445552LL, -1215692561LL, + 1184395975LL, -1432959805LL, 928017007LL, -1610068149LL, 645436976LL, -1741931307LL, + 344557325LL, -1824714662LL, 33834635LL, -1855952479LL, -277955097LL, -1834627396LL, + -581963454LL, -1761209507LL, -869520936LL, -1637653435LL, -1132385526LL, -1467353027LL, + -1362981332LL, -1255054453LL, -1554620348LL, -1006729735LL, -1701700763LL, -729413888LL, + -1799875837LL, -431009938LL, -1846188121LL, -120067085LL, -1839164753LL, 194461886LL, + -1778870595LL, 503477137LL, -1666917203LL, 797994976LL, -1506426844LL, 1069410109LL, + -1301952099LL, 1309749293LL, -1059352893LL, 1511908865LL, -785634058LL, 1669868990LL, + -488747764LL, 1778878071LL, -177366217LL, 1835601530LL, 139369001LL, 1838230179LL, + 452113803LL, 1786544480LL, 751596956LL, 1681932310LL, 1028895841LL, 1527359130LL, + 1275704406LL, 1327290938LL, 1484585218LL, 1087571719LL, 1649197902LL, 815258567LL, + 1764496824LL, 518418908LL, 1826891749LL, 205895496LL, 1834366180LL, -112954125LL, + 1786549340LL, -428536114LL, 1684739060LL, -731308575LL, 1531874336LL, -1012070911LL, + 1332457786LL, -1262245525LL, 1092429799LL, -1474143182LL, 818997647LL, -1641203767LL, + 520424286LL, -1758204769LL, 205782822LL, -1821430739LL, -115316180LL, -1828798059LL, + -433016488LL, -1779930664LL, -737518295LL, -1676183809LL, -1019381407LL, -1520614544LL, + -1269820117LL, -1317899198LL, -1480980530LL, -1074199811LL, -1646191497LL, -796983096LL, + -1760181009LL, -494797008LL, -1819250902LL, -177011430LL, -1821403895LL, 146469318LL, + -1766418435LL, 465513444LL, -1655868372LL, 770078692LL, -1493086207LL, 1050529499LL, + -1283070422LL, 1297944281LL, -1032339174LL, 1504402991LL, -748734381LL, 1663245596LL, + -441181843LL, 1769292892LL, -119414569LL, 1819022192LL, 206332309LL, 1810691732LL, + 525645561LL, 1744409219LL, 828266662LL, 1622141660LL, 1104422738LL, 1447665488LL, + 1345144991LL, 1226457880LL, 1542564130LL, 965532103LL, 1690173001LL, 673221573LL, + 1783047477LL, 358919038LL, 1818017952LL, 32778836LL, 1793785266LL, -294608466LL, + 1710976614LL, -612558764LL, 1572138925LL, -910643408LL, 1381669174LL, -1179033103LL, + 1145683204LL, -1408825356LL, 871826659LL, -1592344464LL, 569033594LL, -1723403826LL, + 247240148LL, -1797521436LL, -82937735LL, -1812080864LL, -410552238LL, -1766431722LL, + -724685966LL, -1661925574LL, -1014816649LL, -1501885317LL, -1271172080LL, -1291508291LL, + -1485063253LL, -1037705585LL, -1649184246LL, -748882207LL, -1757868342LL, -434664830LL, + -1807291232LL, -105585694LL, -1795613781LL, 227267135LL, -1723058827LL, 552621684LL, + -1591918608LL, 859403777LL, -1406491753LL, 1137115627LL, -1172951175LL, 1376198353LL, + -899146558LL, 1568365802LL, -594347470LL, 1706897913LL, -268935212LL, 1786883035LL, + 65946550LL, 1805400258LL, 398770813LL, 1761634750LL, 718023132LL, 1656921327LL, + 1012600859LL, 1494713890LL, 1272201877LL, 1280480924LL, 1487689157LL, 1021529832LL, + 1651418128LL, 726765403LL, 1757514955LL, 406390081LL, 1802095392LL, 71555878LL, + 1783415808LL, -266020404LL, 1701950276LL, -594465527LL, 1560390119LL, -902167593LL, + 1363565019LL, -1178188576LL, 1118287568LL, -1412656901LL, 833125870LL, -1597125911LL, + 518111461LL, -1724885003LL, 184392200LL, -1791211814LL, -156158096LL, -1793555692LL, + -491359775LL, -1731645094LL, -809162498LL, -1607514136LL, -1098079906LL, -1425446375LL, + -1347608103LL, -1191836900LL, -1548612641LL, -914976723LL, -1693669580LL, -604766394LL, + -1777347698LL, -272368390LL, -1796420878LL, 70189763LL, -1750002079LL, 410447766LL, + -1639593074LL, 735964789LL, -1469047127LL, 1034775368LL, -1244444945LL, 1295832226LL, + -973887456LL, 1509419571LL, -667212056LL, 1667521256LL, -335641925LL, 1764129656LL, + 8619380LL, 1795483107LL, 352833662LL, 1760222233LL, 684198015LL, 1659458379LL, + 990321708LL, 1496750553LL, 1259692275LL, 1277990652LL, 1482113207LL, 1011200174LL, + 1649096466LL, 706245020LL, 1754194513LL, 374478117LL, 1793258603LL, 28322515LL, + 1764612690LL, -319190004LL, 1669135362LL, -654907845LL, 1510245587LL, -966057807LL, + 1293791674LL, -1240733722LL, 1027846519LL, -1468356779LL, 722415863LL, -1640089593LL, + 389069679LL, -1749187591LL, 40509954LL, -1791273500LL, -309909291LL, -1764523418LL, + -648691774LL, -1669756274LL, -962719186LL, -1510422033LL, -1239761850LL, -1292487908LL, + -1468959863LL, -1024225773LL, -1641255656LL, -715907874LL, -1749760502LL, -379421591LL, + -1790039878LL, -27817353LL, -1760305524LL, 325193390LL, -1661505532LL, 665771037LL, + -1497307717LL, 980490940LL, -1273975628LL, 1256875462LL, -1000140828LL, 1483893829LL, + -686479199LL, 1652409587LL, -345302987LL, 1755557288LL, 9916217LL, 1789032559LL, + 365075357LL, 1751282956LL, 705998177LL, 1643590790LL, 1019001894LL, 1470043299LL, + 1291449621LL, 1237390020LL, 1512266167LL, 954791730LL, 1672395972LL, 633469782LL, + 1765183992LL, 286268794LL, 1786663175LL, -72850651LL, 1735735749LL, -429369535LL, + 1614239665LL, -768796127LL, 1426896106LL, -1077256343LL, 1181138765LL, -1342064701LL, + 886830467LL, -1552252263LL, 555877385LL, -1699029384LL, 201755488LL, -1776163460LL, + -161032335LL, -1780255088LL, -517546895LL, -1710899992LL, -853027190LL, -1570728650LL, + -1153503575LL, -1365320491LL, -1406384106LL, -1102994708LL, -1600989297LL, -794484926LL, + -1729012353LL, -452509875LL, -1784884711LL, -91256804LL, -1766030417LL, 274201786LL, + -1672997291LL, 628534357LL, -1509457883LL, 956793670LL, -1282078576LL, 1245050267LL, + -1000260790LL, 1480989195LL, -675763704LL, 1654444217LL, -322223094LL, 1757846062LL, + 45414501LL, 1786564561LL, 411519139LL, 1739128805LL, 760440296LL, 1617314401LL, + 1077177150LL, 1426092478LL, 1348027629LL, 1173440964LL, 1561188025LL, 870024566LL, + 1707276679LL, 528755675LL, 1779758188LL, 164253732LL, 1775248517LL, -207774745LL, + 1693686325LL, -571209523LL, 1538361407LL, -910214718LL, 1315797279LL, -1209931440LL, + 1035491245LL, -1457134634LL, 709521616LL, -1640824925LL, 352037689LL, -1752728657LL, + -21346476LL, -1787683023LL, -394228940LL, -1743887860LL, -750138346LL, -1623011387LL, + -1073262655LL, -1430143379LL, -1349155910LL, -1173596017LL, -1565391321LL, -864559400LL, + -1712130872LL, -516625299LL, -1782584989LL, -145198837LL, -1773340311LL, 233176928LL, + -1684539251LL, 601554274LL, -1519901434LL, 943339640LL, -1286584130LL, 1243044123LL, + -994885978LL, 1486991612LL, -657805534LL, 1663951982LL, -290472872LL, 1765669680LL, + 90521464LL, 1787262382LL, 467870816LL, 1727469941LL, 824336974LL, 1588740415LL, + 1143539522LL, 1377147238LL, 1410713792LL, 1102139249LL, 1613402194LL, 776133018LL, + 1742046220LL, 413964332LL, 1790450578LL, 32222418LL, 1756096367LL, -351503697LL, + 1640286916LL, -719432820LL, 1448117449LL, -1054416330LL, 1188267795LL, -1340741791LL, + 872625661LL, -1564877668LL, 515755994LL, -1716123538LL, 134239435LL, -1787134145LL, + -254090674LL, -1774291105LL, -630978005LL, -1677902852LL, -978601365LL, -1502221274LL, + -1280420941LL, -1255271977LL, -1521972395LL, -948503918LL, -1691570430LL, -596272832LL, + -1780887184LL, -215180989LL, -1785376289LL, 176696970LL, -1704520399LL, 560666503LL, + -1541888124LL, 918304023LL, -1304995273LL, 1232343832LL, -1004974660LL, 1487518348LL, + -656068028LL, 1671310502LL, -274962466LL, 1774580824LL, 119998457LL, 1792037255LL, + 509692062LL, 1722522909LL, 875140818LL, 1569105503LL, 1198438983LL, 1338961640LL, + 1463636317LL, 1043059034LL, 1657535050LL, 695649739LL, 1770359857LL, 313596927LL, + 1796266281LL, -84433721LL, 1733660523LL, -478879814LL, 1585312410LL, -850241660LL, + 1358253391LL, -1180048419LL, 1063461912LL, -1451783094LL, 715349207LL, -1651719829LL, + 331068635LL, -1769630643LL, -70319107LL, -1799324640LL, -468784880LL, -1738990598LL, + -844328266LL, -1591323267LL, -1177983561LL, -1363424325LL, -1452783971LL, -1066480158LL, + -1654634764LL, -715229958LL, -1773050010LL, -327248453LL, -1801713815LL, 77922650LL, + -1738835274LL, 479752211LL, -1587276484LL, 857757732LL, -1354444221LL, 1192551680LL, + -1051947852LL, 1466842567LL, -695038119LL, 1666338874LL, -301852890LL, 1780508076LL, + 107493657LL, 1803149850LL, 511933346LL, 1732751509LL, 890526283LL, 1572604517LL, + 1223547706LL, 1330673049LL, 1493522954LL, 1019218298LL, 1686155962LL, 654195028LL, + 1791101449LL, 254449036LL, 1802538423LL, -159244998LL, 1719512402LL, -565256807LL, + 1546025460LL, -942229960LL, 1290866149LL, -1270208619LL, 967185021LL, -1531702097LL, + 591834980LL, -1712630112LL, 184508479LL, -1803097085LL, -233285140LL, -1797952182LL, + -639349722LL, -1697102561LL, -1011980822LL, -1505559966LL, -1331130236LL, -1233214829LL, + -1579493935LL, -894346511LL, -1743463965LL, -506892683LL, -1813891333LL, -91514126LL, + -1786616316LL, 329497170LL, -1662734558LL, 733409531LL, -1448581182LL, 1098279432LL, + -1155430199LL, 1404149399LL, -798921976LL, 1634150375LL, -398246527LL, 1775447200LL, + 24875785LL, 1819973508LL, 447362887LL, 1764913085LL, 846026660LL, 1612898049LL, + 1198847640LL, 1371909314LL, 1486198686LL, 1054881064LL, 1691949304LL, 679027327LL, + 1804387930LL, 264924416LL, 1816908661LL, -164602921LL, 1728421186LL, -585732159LL, + 1543457556LL, -974962469LL, 1271965947LL, -1310430128LL, 928798973LL, -1573146150LL, + 532921378LL, -1748085646LL, 106378096LL, -1825065771LL, -326922200LL, -1799360023LL, + -742541689LL, -1672010837LL, -1116892061LL, -1449818910LL, -1428579569LL, -1145005727LL, + -1659639549LL, -774564299LL, -1796588623LL, -359331136LL, -1831232133LL, 77171105LL, + -1761177472LL, 510056974LL, -1590020058LL, 914493790LL, -1327187088LL, 1267129191LL, + -987443677LL, 1547448563LL, -590085567LL, 1738983060LL, -157861115LL, 1830292976LL, + 284318382LL, 1815684181LL, 710807791LL, 1695581634LL, 1096715185LL, 1476540646LL, + 1419360768LL, 1170937796LL, 1659621937LL, 796294015LL, 1803084152LL, 374279467LL, + 1840927475LL, -70515831LL, 1770493154LL, -512006231LL, 1595492697LL, -924137810LL, + 1325842453LL, -1282428259LL, 977128686LL, -1565431029LL, 569730160LL, -1756034774LL, + 127646054LL, -1842518450LL, -322904637LL, -1819296230LL, -755031419LL, -1687303586LL, + -1142777425LL, -1453996747LL, -1462685684LL, -1132960597LL, -1695231736LL, -743143558LL, + -1826034443LL, -307760775LL, -1846768911LL, 147072348LL, -1755722357LL, 593896979LL, + -1557954553LL, 1005565949LL, -1265047942LL, 1356897679LL, -894457371LL, 1626228036LL, + -468493988LL, 1796763943LL, -13000811LL, 1857653254LL, 444202723LL, 1804701539LL, + 875014531LL, 1640687088LL, 1252779324LL, 1375249504LL, 1553947318LL, 1024353230LL, + 1759558574LL, 609353711LL, 1856458565LL, 155718993LL, 1838165886LL, -308518209LL, + 1705333476LL, -754484985LL, 1465769266LL, -1154263812LL, 1134009220LL, -1482647744LL, + 730463729LL, -1718744573LL, 280185489LL, -1847327092LL, -188668427LL, -1859841092LL, + -646587163LL, -1755002949LL, -1064561295LL, -1538943634LL, -1415926368LL, -1224884097LL, + -1678077387LL, -832356551LL, -1833943370LL, -386015324LL, -1873124663LL, 85892125LL, + -1792615848LL, 553300659LL, -1597062473LL, 986238718LL, -1298529000LL, 1356754354LL, + -915786545LL, 1640732152LL, -473160083LL, 1819482362LL, 996052LL, 1880996435LL, + 476100423LL, 1820783228LL, 921311026LL, 1642226032LL, 1307530227LL, 1356430916LL, + 1609317756LL, 981569612LL, 1806585455LL, 541753293LL, 1885959848LL, 65504900LL, + 1841718672LL, -416074903LL, 1676234131LL, -871331432LL, 1399887159LL, -1270138347LL, + 1030451418LL, -1585901748LL, 591980868LL, -1797352222LL, 113268272LL, -1890003026LL, + -374028439LL, -1857173008LL, -837471346LL, -1700500300LL, -1246002678LL, -1429905764LL, + -1572036202LL, -1063001403LL, -1793338576LL, -623976123LL, -1894567550LL, -142026951LL, + -1868378305LL, 350564532LL, -1715983352LL, 820585222LL, -1447128376LL, 1236130239LL, + -1079530129LL, 1568778527LL, -637739628LL, 1795555486LL, -151516822LL, 1900546075LL, + 346146130LL, 1876043569LL, 821255355LL, 1723149201LL, 1241138672LL, 1451774305LL, + 1576701641LL, 1080036912LL, 1804463052LL, 633086376LL, 1908221393LL, 141429629LL, + 1880252169LL, -361131683LL, 1721911699LL, -839815276LL, 1443605252LL, -1261265975LL, + 1064167463LL, -1595890671LL, 609620054LL, -1819956503LL, 111402416LL, -1917302356LL, + -395774072LL, -1880538522LL, -876336529LL, -1711643473LL, -1296348020LL, -1421907703LL, + -1625915022LL, -1031219954LL, -1841336740LL, -566737582LL, -1926839352LL, -61027132LL, + -1875766327LL, 450199826LL, -1691133157LL, 930599788LL, -1385498386LL, 1345783344LL, + -980151041LL, 1665790217LL, -503663646LL, 1867274482LL, 10093722LL, 1935239187LL, + 524342585LL, 1864189545LL, 1002021458LL, 1658613793LL, 1408460874LL, 1332748006LL, + 1713914928LL, 909632372LL, 1895763629LL, 419518001LL, 1940221478LL, -102268468LL, + 1843421075LL, -617853997LL, 1611784281LL, -1089562454LL, 1261644234LL, -1482674055LL, + 818135973LL, -1767998655LL, 313427505LL, -1924071123LL, -215587098LL, -1938801966LL, + -729969349LL, -1810453968LL, -1191599224LL, -1547863573LL, -1566009290LL, -1169880481LL, + -1824978972LL, -704056688LL, -1948692449LL, -184672619LL, -1927293210LL, 349761108LL, + -1761710842LL, 859346330LL, -1463688325LL, 1305775816LL, -1054997084LL, 1655225503LL, + -565888039LL, 1880941484LL, -32885378LL, 1965322366LL, 503918852LL, 1901332697LL, + 1003870887LL, 1693131331LL, 1428837748LL, 1355856486LL, 1746132372LL, 914572542LL, + 1931056060LL, 402447725LL, 1968858635LL, -141708265LL, 1855958280LL, -676366526LL, + 1600317422LL, -1160442844LL, 1220934387LL, -1556462866LL, 746478194LL, -1833484404LL, + 213160522LL, -1969547660LL, -338000501LL, -1953457189LL, -864320386LL, -1785748248LL, + -1324753325LL, -1478751372LL, -1683106624LL, -1055738022LL, -1910912093LL, -549201722LL, + -1989724864LL, 1602289LL, -1912661482LL, 553675749LL, -1685046032LL, 1063624430LL, + -1324101366LL, 1491074099LL, -857696978LL, 1801886416LL, -322239958LL, 1970917433LL, + 240135133LL, 1984093631LL, 784863442LL, 1839631214LL, 1268477827LL, 1548289929LL, + 1652089012LL, 1132628140LL, 1904538673LL, 625305315LL, 2004968108LL, 66555272LL, + 1944588111LL, -498977880LL, 1727496666LL, -1025794760LL, 1370465625LL, -1471204939LL, + 901699685LL, -1798805330LL, 358654467LL, -1981488167LL, -214921710LL, -2003727762LL, + -772491868LL, -1862950055LL, -1268501615LL, -1569860790LL, -1662112702LL, -1147691406LL, + -1920592311LL, -630409835LL, -2022074982LL, -60029229LL, -1957461308LL, 516776005LL, + -1731285043LL, 1052476997LL, -1361462996LL, 1502610972LL, -877933327LL, 1829492197LL, + -320280288LL, 2005402306LL, 265470588LL, 2014987406LL, 830630770LL, 1856651314LL, + 1327892397LL, 1542814854LL, 1715302191LL, 1099004156LL, 1959831016LL, 561828654LL, + 2040233299LL, -23996138LL, 1948945579LL, -609342953LL, 1692850745LL, -1144781746LL, + 1292827875LL, -1584760955LL, 782109436LL, -1891507171LL, 203569402LL, -2038307715LL, + -393841036LL, -2011887977LL, -959217257LL, -1813668152LL, -1444039046LL, -1459776604LL, + -1806353227LL, -979801859LL, -2014439369LL, -414373418LL, -2049635700LL, 188236038LL, + -1908069812LL, 776206919LL, -1601129520LL, 1298622457LL, -1154615966LL, 1709890782LL, + -606634671LL, 1973754625LL, -4391122LL, 2066533793LL, 599844259LL, 1979306956LL, + 1153260057LL, 1718827494LL, 1607126718LL, 1307075911LL, 1921113518LL, 779469648LL, + 2066909818LL, 181869667LL, 2030850181LL, -433368358LL, 1815247876LL, -1011962047LL, + 1438311869LL, -1502493057LL, 932711575LL, -1860998122LL, 342799710LL, -2054949008LL, + -279253441LL, -2066258071LL, -878036050LL, -1893027506LL, -1399829121LL, -1549868476LL, + -1797444645LL, -1066742063LL, -2034528348LL, -486406209LL, -2088936408LL, 139320060LL, + -1954866775LL, 754153641LL, -1643534948LL, 1302400955LL, -1182313505LL, 1734015710LL, + -612392615LL, 2009200840LL, 14845343LL, 2102128945LL, 642423326LL, 2003429386LL, + 1212931684LL, 1721197577LL, 1673788795LL, 1280413761LL, 1982117936LL, 720803105LL, + 2108785810LL, 93313067LL, 2041218369LL, -544485466LL, 1784716747LL, -1133662326LL, + 1362130836LL, -1619378325LL, 811898508LL, -1956017602LL, 184610889LL, -2111519662LL, + -461595751LL, -2070495861LL, -1066406363LL, -1835822226LL, -1572958968LL, -1428538583LL, + -1933216445LL, -886040399LL, -2112568943LL, -258710387LL, -2093222149LL, 394713532LL, + -1876034489LL, 1012613050LL, -1480608032LL, 1536299706LL, -943600728LL, 1915613268LL, + -315396392LL, 2113772514LL, 344572237LL, 2111005553LL, 973418637LL, 1906596036LL, + 1510792294LL, 1519127688LL, 1904693470LL, 984879169LL, 2116551090LL, 354498538LL, + 2125064100LL, -311745426LL, 1928418285LL, -949695530LL, 1544641759LL, -1497480372LL, + 1010039319LL, -1901537228LL, 375831797LL, -2121895803LL, -296696429LL, -2136197763LL, + -942088073LL, -1942042233LL, -1497079186LL, -1557404881LL, -1906822926LL, -1019063283LL, + -2130357016LL, -379156267LL, -2144765907LL, 299809137LL, -1947608910LL, 951031212LL, + -1557350457LL, 1509981226LL, -1011722650LL, 1920820667LL, -364154737LL, 2142028210LL, + 321401137LL, 2147483647LL, 976753247LL, 1944835763LL, 1536249216LL, 1544069780LL, + 1943377719LL, 987564024LL, 2147483647LL, 330427143LL, 2147483647LL, -361719422LL, + 1933002455LL, -1019262539LL, 1516805838LL, -1575596305LL, 945913307LL, -1973896042LL, + 277506094LL, -2147483648LL, -420914734LL, -2147483648LL, -1078314704LL, -1910945349LL, + -1627350702LL, -1474464398LL, -2011299944LL, -885900374LL, -2147483648LL, -204896184LL, + -2144022251LL, 498991560LL, -1877080161LL, 1153357955LL, -1415642552LL, 1690403157LL, + -806512534LL, 2053993312LL, -112137452LL, 2147483647LL, 595738565LL, 2128412570LL, + 1243462839LL, 1829396686LL, 1763145619LL, 1338677235LL, 2099815651LL, 706653857LL, + 2147483647LL, -1108501LL, 2102208279LL, -710629664LL, 1765529694LL, -1347227239LL, + 1241718679LL, -1843391279LL, 585255037LL, -2145989591LL, -134944413LL, -2147483648LL, + -842713567LL, -2062352029LL, -1462678057LL, -1682814019LL, -1928302925LL, -1122836459LL, + -2147483648LL, -441400203LL, -2147483648LL, 289092961LL, -2005373498LL, 990471168LL, + -1578388818LL, 1587150913LL, -980157187LL, 2014310913LL, -274488385LL, 2147483647LL, + 462731486LL, 2147483647LL, 1151665856LL, 1927478533LL, 1717175151LL, 1449339761LL, + 2097049856LL, 812045691LL, 2147483647LL, 84433721LL, 2147483647LL, -654296430LL, + 1824681532LL, -1323177309LL, 1292883883LL, -1848359671LL, 617322823LL, -2147483648LL, + -128108909LL, -2147483648LL, -861277895LL, -2090282041LL, -1500843722LL, -1692991865LL, + -1975306229LL, -1106607672LL, -2147483648LL, -395528201LL, -2147483648LL, 361488468LL, + -1995722824LL, 1080004711LL, -1528665607LL, 1679317564LL, -888762067LL, 2091559027LL, + -147223721LL, 2147483647LL, 612783943LL, 2147483647LL, 1305437304LL, 1866287310LL, + 1851955985LL, 1328525280LL, 2147483647LL, 638610417LL, 2147483647LL, -125673519LL, + 2108821445LL, -877530653LL, 1697262641LL, -1530992629LL, 1090348412LL, -2010773526LL, + 356820862LL, -2147483648LL, -419546373LL, -2147483648LL, -1149471452LL, -1983167245LL, + -1748430557LL, -1484780423LL, -2146487617LL, -813323984LL, -2147483648LL, -45891303LL, + -2147483648LL, 728742378LL, -1809227742LL, 1420361420LL, -1226337079LL, 1947833558LL, + -498562450LL, 2147483647LL, 289419249LL, 2147483647LL, 1045283530LL, 2055934304LL, + 1679866533LL, 1582609746LL, 2117720018LL, 921390819LL, 2147483647LL, 149630424LL, + 2147483647LL, -641693954LL, 1873185799LL, -1358669751LL, 1300859704LL, -1915606832LL, + 572008359LL, -2147483648LL, -226932260LL, -2147483648LL, -1000549139LL, -2093186794LL, + -1655833497LL, -1627143323LL, -2113398219LL, -964233001LL, -2147483648LL, -183518890LL, + -2147483648LL, 621170198LL, -1894003568LL, 1352477587LL, -1315939576LL, 1921308786LL, + -576499961LL, 2147483647LL, 234889746LL, 2147483647LL, 1019421092LL, 2098505324LL, + 1680921733LL, 1619869684LL, 2137682708LL, 941425286LL, 2147483647LL, 145715070LL, + 2147483647LL, -669722041LL, 1871694138LL, -1404269475LL, 1270347298LL, -1966662805LL, + 510132515LL, -2147483648LL, -315150399LL, -2147483648LL, -1102981806LL, -2069712969LL, + -1754848703LL, -1557870761LL, -2147483648LL, -850038777LL, -2147483648LL, -34120098LL, + -2147483648LL, 787836539LL, -1800954267LL, 1512356781LL, -1159293364LL, 2047592239LL, + -369680845LL, 2147483647LL, 468443105LL, 2147483647LL, 1248833919LL, 1998633617LL, + 1871911961LL, 1433810972LL, 2147483647LL, 684935582LL, 2147483647LL, -153039138LL, + 2147483647LL, -973133867LL, 1671380672LL, -1669979887LL, 975052061LL, -2147483648LL, + 151596040LL, -2147483648LL, -693108301LL, -2147483648LL, -1449755617LL, -1871416925LL, + -2019776102LL, -1236840244LL, -2147483648LL, -440150831LL, -2147483648LL, 415477311LL, + -2034694159LL, 1218517285LL, -1468579014LL, 1863623499LL, -708715313LL, 2147483647LL, + 145786058LL, 2147483647LL, 982719812LL, 2147483647LL, 1691497160LL, 1669815849LL, + 2147483647LL, 954671752LL, 2147483647LL, 111583841LL, 2147483647LL, -747912378LL, + 1841149438LL, -1509401012LL, 1176546138LL, -2070839540LL, 353347779LL, -2147483648LL, + -518720082LL, -2147483648LL, -1322686810LL, -1984011213LL, -1950030933LL, -1373841173LL, + -2147483648LL, -577218548LL, -2147483648LL, 298868777LL, -2100460956LL, 1136005725LL, + -1546865335LL, 1820343005LL, -781786881LL, 2147483647LL, 91241880LL, 2147483647LL, + 953299169LL, 2147483647LL, 1686244007LL, 1696563940LL, 2147483647LL, 966390060LL, + 2147483647LL, 102039095LL, 2147483647LL, -777821720LL, 1824356829LL, -1551666442LL, + 1130974297LL, -2111922316LL, 279516280LL, -2147483648LL, -612190693LL, -2147483648LL, + -1420004814LL, -1931990396LL, -2030764809LL, -1275960676LL, -2147483648LL, -440290363LL, + -2147483648LL, 458451384LL, -2021408332LL, 1294135401LL, -1402120762LL, 1948773397LL, + -583915899LL, 2147483647LL, 318150301LL, 2147483647LL, 1176450646LL, 2094639697LL, + 1868831534LL, 1510462614LL, 2147483647LL, 710299397LL, 2147483647LL, -192413017LL, + 2147483647LL, -1068904512LL, 1602127619LL, -1793417057LL, 819602113LL, -2147483648LL, + -82023678LL, -2147483648LL, -973065356LL, -2147483648LL, -1724623315LL, -1678300740LL, + -2147483648LL, -912151632LL, -2147483648LL, -12499064LL, -2147483648LL, 890170431LL, + -1740135399LL, 1664186565LL, -988364862LL, 2147483647LL, -90833453LL, 2147483647LL, + 821177483LL, 2147483647LL, 1613514784LL, 1788690829LL, 2147483647LL, 1048681623LL, + 2147483647LL, 152793751LL, 2147483647LL, -766812198LL, 1824879858LL, -1573716191LL, + 1093507978LL, -2147483648LL, 198277259LL, -2147483648LL, -727610505LL, -2147483648LL, + -1545626008LL, -1849427405LL, -2132664825LL, -1123170556LL, -2147483648LL, -227221401LL, + -2147483648LL, 703952868LL, -1862839705LL, 1529828183LL, -1137882710LL, 2125054113LL, + -239572484LL, 2147483647LL, 696088373LL, 2147483647LL, 1526669554LL, 1865382339LL, + 2125017882LL, 1137721301LL, 2147483647LL, 235265560LL, 2147483647LL, -704148694LL, + 1857065635LL, -1536266267LL, 1122613238LL, -2132589272LL, 214214981LL, -2147483648LL, + -728152045LL, -2147483648LL, -1558502452LL, -1837638152LL, -2147483648LL, -1092332794LL, + -2147483648LL, -176316911LL, -2147483648LL, 767995806LL, -1806589129LL, 1593019962LL, + -1046510791LL, 2147483647LL, -121464875LL, 2147483647LL, 823436876LL, 2147483647LL, + 1639198542LL, 1763159804LL, 2147483647LL, 984655577LL, 2147483647LL, 49578122LL, + 2147483647LL, -894060382LL, 1706364078LL, -1696127521LL, 906186062LL, -2147483648LL, + -39357398LL, -2147483648LL, -979237533LL, -2147483648LL, -1762570561LL, -1635020522LL, + -2147483648LL, -810477581LL, -2147483648LL, 145234745LL, -2147173496LL, 1078072512LL, + -1547797918LL, 1836924254LL, -696927364LL, 2147483647LL, 267757529LL, 2147483647LL, + 1189341491LL, 2084956214LL, 1917175022LL, 1443276059LL, 2147483647LL, 565024253LL, + 2147483647LL, -406359456LL, 2007326447LL, -1311419157LL, 1320024444LL, -2000850256LL, + 414449867LL, -2147483648LL, -560111264LL, -2147483648LL, -1442207966LL, -1911924074LL, + -2084981596LL, -1176697631LL, -2147483648LL, -245183614LL, -2147483648LL, 727618580LL, + -1796349961LL, 1579060545LL, -1012155114LL, 2147483647LL, -57628654LL, 2147483647LL, + 906914338LL, 2147483647LL, 1718711687LL, 1658280341LL, 2147483647LL, 825600283LL, + 2147483647LL, -147249600LL, 2119171481LL, -1095347499LL, 1495612856LL, -1857217705LL, + 616742154LL, -2147483648LL, -367776014LL, -2147483648LL, -1289479279LL, -2002299272LL, + -1989919485LL, -1306637680LL, -2147483648LL, -385972507LL, -2147483648LL, 601417189LL, + -1856547732LL, 1484994671LL, -1090241876LL, 2111435994LL, -134560292LL, 2147483647LL, + 844635809LL, 2147483647LL, 1676637514LL, 1679181318LL, 2147483647LL, 846138902LL, + 2147483647LL, -135149055LL, 2102362641LL, -1092763194LL, 1468159211LL, -1858185277LL, + 575117335LL, -2147483648LL, -419540974LL, -2147483648LL, -1339905470LL, -1948181439LL, + -2022479998LL, -1222426219LL, -2147483648LL, -279299247LL, -2147483648LL, 713560453LL, + -1753106277LL, 1578900203LL, -942233628LL, 2147483647LL, 37605511LL, 2147483647LL, + 1010580501LL, 2127431936LL, 1801342990LL, 1515226439LL, 2147483647LL, 629474184LL, + 2147483647LL, -370071857LL, 1955707783LL, -1302336234LL, 1234211778LL, -1997708086LL, + 288009925LL, -2147483648LL, -710586095LL, -2147483648LL, -1578952719LL, -1732157741LL, + -2147483648LL, -911741378LL, -2147483648LL, 76034401LL, -2090615152LL, 1049557920LL, + -1455836013LL, 1829095376LL, -551924013LL, 2147483647LL, 454047639LL, 2147483647LL, + 1375353790LL, 1884544385LL, 2040271888LL, 1128257534LL, 2147483647LL, 161671209LL, + 2147483647LL, -834822135LL, 1615276485LL, -1674491411LL, 753927995LL, -2147483648LL, + -249025977LL, -2147483648LL, -1204606014LL, -1984648838LL, -1932033658LL, -1284264037LL, + -2147483648LL, -340806245LL, -2147483648LL, 666972896LL, -1721619608LL, 1547367459LL, + -896639402LL, 2132213272LL, 99365276LL, 2147483647LL, 1075862445LL, 2043677652LL, + 1845317827LL, 1385903692LL, 2147483647LL, 461774352LL, 2147483647LL, -550937857LL, + 1783062871LL, -1456645756LL, 983610152LL, -2079731627LL, -6346842LL, -2147483648LL, + -994522919LL, -2070470525LL, -1788240171LL, -1438621391LL, -2147483648LL, -526030334LL, + -2147483648LL, 489038459LL, -1805708379LL, 1407526237LL, -1017954966LL, 2048615359LL, + -30028889LL, 2147483647LL, 963210479LL, 2070713189LL, 1765116437LL, 1446104745LL, + 2147483647LL, 534965810LL, 2147483647LL, -481954566LL, 1792846279LL, -1402147318LL, + 1001491128LL, -2041668911LL, 10215159LL, -2147483648LL, -982419164LL, -2046535775LL, + -1776841131LL, -1409706084LL, -2147483648LL, -489295648LL, -2147483648LL, 529249612LL, + -1744635194LL, 1439940879LL, -934363946LL, 2057911372LL, 65216116LL, 2147483647LL, + 1050748626LL, 1996391992LL, 1821006064LL, 1328290982LL, 2147483647LL, 388941107LL, + 2147483647LL, -629419501LL, 1658126326LL, -1517620836LL, 815140801LL, -2092548985LL, + -195404754LL, -2147483648LL, -1164696606LL, -1915187531LL, -1891725862LL, -1198504818LL, + -2147483648LL, -233417647LL, -2094899463LL, 779452311LL, -1527641055LL, 1628799649LL, + -641387939LL, 2136772307LL, 378521453LL, 2147483647LL, 1318022372LL, 1794695140LL, + 1979225032LL, 1015491189LL, 2147483647LL, 22740896LL, 1995209538LL, -973920117LL, + 1345570023LL, -1763295596LL, 410771198LL, -2147483648LL, -610587865LL, -2127834749LL, + -1500754579LL, -1624369012LL, -2069269542LL, -774137413LL, -2147483648LL, 241137929LL, + -1847418567LL, 1203670051LL, -1103715189LL, 1906272945LL, -122715084LL, 2147483647LL, + 883850446LL, 2012811460LL, 1697988588LL, 1392726985LL, 2142736149LL, 470932388LL, + 2120892714LL, -552396484LL, 1636662451LL, -1454265170LL, 795302962LL, -2037463975LL, + -219362165LL, -2147483648LL, -1184851932LL, -1833111934LL, -1888751472LL, -1089488122LL, + -2147483648LL, -106478733LL, -1981532518LL, 899034343LL, -1348972841LL, 1704459337LL, + -417766764LL, 2130856890LL, 605355862LL, 2082976507LL, 1492490534LL, 1570949401LL, + 2045346868LL, 708608789LL, 2139800539LL, -311418834LL, 1754149567LL, -1260493266LL, + 974558829LL, -1925168471LL, -23760782LL, -2147483648LL, -1015628491LL, -1898642732LL, + -1776580867LL, -1212542399LL, -2133786768LL, -252202828LL, -2005616847LL, 764400249LL, + -1420739524LL, 1605758902LL, -512180316LL, 2079613273LL, 512543642LL, 2077156468LL, + 1418600963LL, 1598441139LL, 1997662775LL, 752962382LL, 2116027827LL, -264962495LL, + 1745889914LL, -1220582470LL, 972347319LL, -1892794981LL, -25710188LL, -2125477651LL, + -1016652963LL, -1864114436LL, -1769757774LL, -1169041827LL, -2109052347LL, -201993370LL, + -1954765898LL, 811173099LL, -1342547289LL, 1633062678LL, -415717372LL, 2070441710LL, + 607885452LL, 2019964316LL, 1486893216LL, 1493039915LL, 2013348047LL, 613756517LL, + 2062158103LL, -409912571LL, 1621250421LL, -1335042284LL, 795054302LL, -1941379882LL, + -219777163LL, -2083998986LL, -1180875432LL, -1728347224LL, -1857969726LL, -959118033LL, + -2088234317LL, 39439886LL, -1815827288LL, 1027316879LL, -1105930895LL, 1766314816LL, + -129650711LL, 2077617985LL, 876853731LL, 1885417851LL, 1669337892LL, 1235865668LL, + 2054838985LL, 286501176LL, 1938989986LL, -731553692LL, 1349602540LL, -1569664491LL, + 430512308LL, -2022465725LL, -593093077LL, -1978483844LL, -1469614304LL, -1448052302LL, + -1982904907LL, -561416688LL, -2005845857LL, 462792664LL, -1532286606LL, 1371204559LL, + -679217255LL, 1938373896LL, 341658256LL, 2022978085LL, 1276162463LL, 1603476725LL, + 1890884293LL, 784129424LL, 2031698462LL, -230422884LL, 1662840725LL, -1185943579LL, + 876527634LL, -1842234032LL, -129589075LL, -2033710073LL, -1101754301LL, -1711598178LL, + -1794006395LL, -956896436LL, -2030578463LL, 39470351LL, -1750932229LL, 1024577274LL, + -1025786781LL, 1747574834LL, -39769409LL, 2023716281LL, 955197954LL, 1781959027LL, + 1704111768LL, 1083778286LL, 2014373759LL, 108080181LL, 1805703544LL, -894230431LL, + 1131447177LL, -1664599331LL, 165493955LL, -2003633146LL, -842141681LL, -1823080378LL, + -1629841030LL, -1169339105LL, -1992406176LL, -212096587LL, -1834878925LL, 799274029LL, + -1197946667LL, 1600473864LL, -248003710LL, 1981434114LL, 765865062LL, 1841752714LL, + 1576979915LL, 1217691843LL, 1971289389LL, 273341321LL, 1844212108LL, -742064007LL, + 1228912870LL, -1559696208LL, 288230948LL, -1962377597LL, -727944357LL, -1842619293LL, + -1548822439LL, -1231854727LL, -1954939401LL, -292778859LL, -1837185184LL, 723513013LL, + -1226663060LL, 1544426665LL, -287069368LL, 1949052421LL, 728715745LL, 1827968405LL, + 1546448684LL, 1213381833LL, 1944632806LL, 271162642LL, 1814876118LL, -743438427LL, + 1191954562LL, -1554700523LL, 245096964LL, -1941435972LL, -767504107LL, -1797666219LL, + -1568864103LL, -1162228724LL, -1939056590LL, -208895030LL, -1775951042LL, 800666344LL, + -1123963440LL, 1588486622LL, -162574314LL, 1936928459LL, 842598948LL, 1749203217LL, + 1612973933LL, 1076841029LL, 1934324657LL, 106161912LL, 1716764101LL, -892881938LL, + 1020482711LL, -1641581960LL, 39713908LL, -1930358151LL, -950983969LL, -1677854927LL, + -1673406700LL, -954468434LL, -1923983555LL, 36661116LL, -1631591309LL, 1016242021LL, + -878361137LL, 1707373889LL, 122774541LL, 1914001235LL, 1087838944LL, 1577002162LL, + 1742229330LL, 791736140LL, 1899064878LL, -218326050LL, 1513053911LL, -1164779319LL, + 694216010LL, -1776530694LL, -322868136LL, -1877693376LL, -1245864564LL, -1438680550LL, + -1808642101LL, -585510815LL, -1848288289LL, 435767653LL, -1352820285LL, 1329668820LL, + -465463701LL, 1836733312LL, 556165390LL, 1809158532LL, 1414517258LL, 1254459764LL, + 1858785423LL, 334101797LL, 1758553821LL, -682934606LL, 1142686552LL, -1498468460LL, + 191691985LL, -1872604777LL, -814640099LL, -1694708027LL, -1579302990LL, -1016749877LL, + -1875847111LL, -38800246LL, -1615893582LL, 949500130LL, -876129450LL, 1654520954LL, + 123647099LL, 1866054325LL, 1085353947LL, 1520488149LL, 1721351524LL, 720611891LL, + 1840706121LL, -294302259LL, 1407054249LL, -1219637892LL, 550373563LL, -1776777340LL, + -471337809LL, -1797288262LL, -1349373645LL, -1274431624LL, -1817576867LL, -366067473LL, + -1733378850LL, 652395404LL, -1121841385LL, 1471172965LL, -168910938LL, 1840388025LL, + 834546090LL, 1646753720LL, 1581263588LL, 949000229LL, 1841796111LL, -39230077LL, + 1535511100LL, -1014267459LL, 756241749LL, -1675540831LL, -255765281LL, -1818448116LL, + -1187443574LL, -1398214171LL, -1749649353LL, -544640070LL, -1767194614LL, 477319872LL, + -1234048615LL, 1349394412LL, -316129399LL, 1799099338LL, 699697879LL, 1685259264LL, + 1494941778LL, 1042990584LL, 1819420416LL, 73611538LL, 1570434125LL, -917877785LL, + 825978352LL, -1618518150LL, -178958319LL, -1806354896LL, -1126049809LL, -1421296352LL, + -1714324042LL, -585078189LL, -1756089647LL, 436519118LL, -1237438918LL, 1317704636LL, + -323632364LL, 1776538160LL, 692897773LL, 1665523308LL, 1485782867LL, 1019704969LL, + 1799582252LL, 46374894LL, 1532562013LL, -940862762LL, 770411922LL, -1622892735LL, + -240501449LL, -1778438874LL, -1172250775LL, -1356432227LL, -1721600892LL, -493547518LL, + -1709015776LL, 529345215LL, -1137994453LL, 1378178621LL, -194916555LL, 1774797309LL, + 811132424LL, 1588545310LL, 1549349964LL, 880036645LL, 1776130026LL, -117785508LL, + 1416001076LL, -1075656720LL, 587521342LL, -1676461699LL, -434997387LL, -1720498390LL, + -1311838626LL, -1192506876LL, -1750708205LL, -267755962LL, -1604585114LL, 745440623LL, + -921705962LL, 1508164180LL, 69547420LL, 1764373389LL, 1036415056LL, 1427398524LL, + 1653255696LL, 610052347LL, 1711490107LL, -412357250LL, 1190786945LL, -1294258468LL, + 266981103LL, -1736566797LL, -746584936LL, -1588534427LL, -1504978709LL, -899877873LL, + -1749180546LL, 95088041LL, -1395109240LL, 1056551222LL, -563386947LL, 1655054094LL, + 460958473LL, 1684674277LL, 1325673010LL, 1134559368LL, 1732381581LL, 193737354LL, + 1539997995LL, -813114320LL, 814449612LL, -1537371626LL, -193069591LL, -1727332358LL, + -1132454361LL, -1316296150LL, -1676182946LL, -446829760LL, -1633852403LL, 577885982LL, + -1019587352LL, 1399310307LL, -48208664LL, 1729024988LL, 939190752LL, 1450523315LL, + 1594732401LL, 661205875LL, 1686550477LL, -360834257LL, 1181478422LL, -1254222282LL, + 257905057LL, -1701993633LL, -756455747LL, -1544482492LL, -1500456011LL, -837053677LL, + -1708227600LL, 168471497LL, -1304803952LL, 1112802445LL, -434045980LL, 1657373366LL, + 591826674LL, 1606077381LL, 1403701702LL, 976650919LL, 1708422678LL, -4542394LL, + 1395197488LL, -983197259LL, 576749821LL, -1604729781LL, -450372577LL, -1643024223LL, + -1312686254LL, -1083423144LL, -1695539549LL, -129244596LL, -1458425831LL, 871309894LL, + -687407141LL, 1551872153LL, 335213907LL, 1662268586LL, 1233635504LL, 1161179821LL, + 1676554392LL, 232531293LL, 1499790990LL, -781193335LL, 767994330LL, -1504849364LL, + -248067348LL, -1669616882LL, -1171021551LL, -1213531064LL, -1656893298LL, -305720374LL, + -1523719159LL, 715451956LL, -820535022LL, 1468048024LL, 189722096LL, 1669526650LL, + 1127824645LL, 1243469349LL, 1640414091LL, 349508927LL, 1533498091LL, -675594942LL, + 846708341LL, -1444326657LL, -160413579LL, -1665001819LL, -1105764687LL, -1253090788LL, + -1629435773LL, -364553119LL, -1531122938LL, 662306277LL, -847591542LL, 1435138318LL, + 160079103LL, 1657550479LL, 1105467974LL, 1243432356LL, 1624776890LL, 351264940LL, + 1517221644LL, -675609301LL, 823526796LL, -1440609020LL, -188486038LL, -1647174495LL, + -1126546333LL, -1214406420LL, -1625776508LL, -309738248LL, -1491039590LL, 714915389LL, + -774103028LL, 1459555454LL, 245230803LL, 1632376323LL, 1167580878LL, 1164824814LL, + 1630290063LL, 239803864LL, 1450479881LL, -778952847LL, 698253656LL, -1489438566LL, + -329606391LL, -1610182941LL, -1226010701LL, -1092515139LL, -1634665059LL, -141215321LL, + -1392207150LL, 865580046LL, -594475695LL, 1526264713LL, 440341531LL, 1576203720LL, + 1297941424LL, 994544149LL, 1633720789LL, 13969609LL, 1311839729LL, -971494505LL, + 461184379LL, -1564460851LL, -575216906LL, -1524754220LL, -1377899809LL, -867571614LL, + -1620770417LL, 141235220LL, -1204264455LL, 1091862720LL, -297216238LL, 1596768507LL, + 730576935LL, 1449093383LL, 1458581342LL, 708363522LL, 1587743822LL, -322411216LL, + 1064119308LL, -1219912866LL, 102490642LL, -1614220437LL, -900770757LL, -1341832837LL, + -1530657115LL, -514490176LL, -1525482707LL, 525583943LL, -886487178LL, 1346557687LL, + 121179083LL, 1606284646LL, 1077585628LL, 1195582678LL, 1582734361LL, 285220920LL, + 1424292782LL, -744040085LL, 667835526LL, -1460145202LL, -369161374LL, -1561277368LL, + -1249769760LL, -1003891223LL, -1601587439LL, -22596709LL, -1274835078LL, 967613194LL, + -407205565LL, 1546468913LL, 633054189LL, 1467154853LL, 1402787101LL, 762511338LL, + 1572796503LL, -267387790LL, 1069421542LL, -1182154009LL, 107605361LL, -1589198735LL, + -899849894LL, -1312782604LL, -1518987454LL, -470974515LL, -1481928906LL, 573632139LL, + -803729552LL, 1369389808LL, 222519560LL, 1570908155LL, 1151434414LL, 1089738946LL, + 1578402144LL, 134370068LL, 1316366447LL, -879036499LL, 478865633LL, -1507427260LL, + -567967360LL, -1474854623LL, -1364735522LL, -794623773LL, -1560422073LL, 234891542LL, + -1067814412LL, 1160190056LL, -103575408LL, 1572174728LL, 905957541LL, 1287598382LL, + 1512786137LL, 431703558LL, 1446389104LL, -615697524LL, 735330273LL, -1388043088LL, + -303767107LL, -1539923328LL, -1206280826LL, -1002398919LL, -1567153073LL, -15529488LL, + -1223324590LL, 977749278LL, -328596447LL, 1529987523LL, 713963610LL, 1391196733LL, + 1432925314LL, 623094391LL, 1501832160LL, -427065472LL, 888365365LL, -1282602249LL, + -129230451LL, -1553689575LL, -1087294674LL, -1115726647LL, -1547675115LL, -167854564LL, + -1298642564LL, 856406875LL, -453432634LL, 1486859063LL, 599966650LL, 1432777179LL, + 1376128439LL, 718020609LL, 1515942339LL, -328157863LL, 953654686LL, -1221806118LL, + -50903879LL, -1547962551LL, -1031255417LL, -1154043595LL, -1530471037LL, -222488744LL, + -1314632024LL, 812488380LL, -483615687LL, 1466654628LL, 573797350LL, 1432583274LL, + 1360968233LL, 725186079LL, 1506695181LL, -323423523LL, 941162339LL, -1218836696LL, + -69270288LL, -1537263786LL, -1046357527LL, -1126834449LL, -1525907011LL, -181334652LL, + -1278833914LL, 850015125LL, -421824267LL, 1475359753LL, 636418071LL, 1395093881LL, + 1389254588LL, 646522768LL, 1474766709LL, -412068442LL, 850726324LL, -1271900671LL, + -183165841LL, -1518110133LL, -1128068150LL, -1030739606LL, -1526349599LL, -44552687LL, + -1183871872LL, 962784479LL, -265934663LL, 1501524588LL, 781149961LL, 1308397838LL, + 1446328509LL, 476496259LL, 1403491489LL, -588177576LL, 672472389LL, -1363950201LL, + -388658067LL, -1469140545LL, -1257921463LL, -850837365LL, -1506046600LL, 187050138LL, + -1009298878LL, 1131974047LL, -12603176LL, 1515515661LL, 989910773LL, 1146268671LL, + 1499345540LL, 206732133LL, 1260815695LL, -835494038LL, 392275121LL, -1459715474LL, + -672351692LL, -1352607142LL, -1399080366LL, -566694138LL, -1421840301LL, 503899735LL, + -727972582LL, 1320071495LL, 333282584LL, 1469168076LL, 1225406819LL, 874597391LL, + 1495622531LL, -163330889LL, 1005529569LL, -1117813102LL, 3465520LL, -1502540115LL, + -999959503LL, -1120166809LL, -1491489784LL, -164972035LL, -1218299862LL, 874401987LL, + -319411870LL, 1464204966LL, 743539277LL, 1300064214LL, 1422521595LL, 465357943LL, + 1365890133LL, -609580526LL, 601716862LL, -1368323831LL, -474522953LL, -1416453582LL, + -1303497032LL, -727707567LL, -1452628579LL, 340137662LL, -842835426LL, 1229887391LL, + 207963408LL, 1475441402LL, 1149268973LL, 946862596LL, 1486028335LL, -79307801LL, + 1039776809LL, -1063312777LL, 44746017LL, -1485588100LL, -973596503LL, -1121756978LL, + -1475399106LL, -163329000LL, -1193159419LL, 881535355LL, -275772241LL, 1456689456LL, + 788423766LL, 1254453348LL, 1430712436LL, 381589645LL, 1306229364LL, -695418898LL, + 480462630LL, -1398678373LL, -603528774LL, -1349151441LL, -1361743987LL, -572215181LL, + -1383940385LL, 513630783LL, -656799817LL, 1321008246LL, 426468741LL, 1411355425LL, + 1277495390LL, 734278703LL, 1432169769LL, -342663823LL, 804801115LL, -1232153638LL, + -262725977LL, -1447159626LL, -1185851850LL, -868590390LL, -1457089195LL, 187061184LL, + -925925060LL, 1139376804LL, 115985447LL, 1462699375LL, 1093436811LL, 977125002LL, + 1464700947LL, -49733902LL, 1022539050LL, -1048661210LL, 11528165LL, -1463764371LL, + -1005604652LL, -1062529611LL, -1460516075LL, -67691413LL, -1097464103LL, 964754079LL, + -118694606LL, 1455536851LL, 926530917LL, 1127707381LL, 1449356620LL, 164516311LL, + 1153611210LL, -891295084LL, 205163748LL, -1442451900LL, -859352126LL, -1175506557LL, + -1435246676LL, -240663877LL, -1193699322LL, 830959111LL, -271057573LL, 1428113046LL, + 806328038LL, 1208466501LL, 1421369992LL, 296394372LL, 1220050794LL, -785629031LL, + 316725532LL, -1415282513LL, -768995739LL, -1228656106LL, -1410063709LL, -332098195LL, + -1234446576LL, 756529867LL, -342553249LL, 1405876458LL, 748302286LL, 1237545695LL, + 1402832353LL, 348123491LL, 1238033405LL, -744354100LL, 348830205LL, -1400991173LL, + -744699311LL, -1235944354LL, -1400362393LL, -344681245LL, -1231268776LL, 749326149LL, + -335672060LL, 1400905958LL, 758195608LL, 1223953351LL, 1402530865LL, 321787162LL, + 1213900593LL, -771239606LL, 303000564LL, -1405093890LL, -788360274LL, -1200969072LL, + -1408400052LL, -279277435LL, -1184976060LL, 809428207LL, -250578529LL, 1412202658LL, + 834278175LL, 1165700476LL, 1416201538LL, 216865252LL, 1142884781LL, -862704481LL, + 178103980LL, -1420041650LL, -894457420LL, -1116237935LL, -1423313565LL, -134271618LL, + -1085440887LL, 929238992LL, -85363750LL, 1425554066LL, 966696662LL, 1050152854LL, + 1426245761LL, 31403552LL, 1010017224LL, -1006411826LL, -27549842LL, -1424808312LL, + -1047921422LL, -964665803LL, -1420648146LL, 91391869LL, -913744655LL, 1090661570LL, + 159960943LL, 1413069269LL, 1134008042LL, 856893832LL, 1401370304LL, -233026637LL, + 793793278LL, -1177258892LL, -310275358LL, -1384805803LL, -1219620245LL, -724155644LL, + -1362600435LL, 391304320LL, -647749008LL, 1260219154LL, 475603889LL, 1333968432LL, + 1298094851LL, 564417492LL, 1298119350LL, -562544670LL, 474094145LL, -1332203045LL, + -651370655LL, -1254278034LL, -1361423434LL, -376824846LL, -1201704472LL, 741186232LL, + -272788319LL, 1384566231LL, 830950575LL, 1139715684LL, 1400387263LL, 162318380LL, + 1067713849LL, -919471003LL, 45927255LL, -1407602436LL, -1005400883LL, -985211996LL, + -1404909988LL, 75677042LL, -891866885LL, 1087246351LL, 201569499LL, 1391021299LL, + 1163372373LL, 787516299LL, 1364691124LL, -330588627LL, 672212141LL, -1232015085LL, + -461326252LL, -1324754203LL, -1291306126LL, -546255436LL, -1270171601LL, 592121217LL, + -410234629LL, 1339303727LL, 721056533LL, 1200081175LL, 1374029536LL, 265061248LL, + 1113849646LL, -845965260LL, 111999151LL, -1393514904LL, -964449184LL, -1011128131LL, + -1395859662LL, 47311938LL, -891912734LL, 1073909066LL, 210837543LL, 1379300373LL, + 1171584486LL, 756605218LL, 1342284027LL, -376139953LL, 606067977LL, -1254607929LL, + -540385960LL, -1283549605LL, -1320076931LL, -441674017LL, -1202218470LL, 700369865LL, + -265351127LL, 1365141120LL, 852551956LL, 1097887674LL, 1387101599LL, 79613186LL, + 970720748LL, -993117848LL, -112427564LL, -1383524468LL, -1118062604LL, -821534653LL, + -1352368472LL, 307068911LL, -651880071LL, 1223298232LL, 500049867LL, 1292121043LL, + 1304782706LL, 464106983LL, 1201936259LL, -686611043LL, 261407268LL, -1358671909LL, + -861589594LL, -1081771315LL, -1381494088LL, -47830032LL, -932516458LL, 1019548897LL, + 171735080LL, 1370340467LL, 1154942204LL, 756108020LL, 1323064242LL, -391615102LL, + 555613548LL, -1262311679LL, -605458812LL, -1238481978LL, -1336521712LL, -335281132LL, + -1116569128LL, 806391985LL, -100544446LL, 1373019256LL, 987223506LL, 958635935LL, + 1368111356LL, -142028048LL, 767468674LL, -1140703821LL, -384849995LL, -1319250340LL, + -1259833747LL, -547423343LL, -1225313865LL, 619505199LL, -304458307LL, 1338214672LL, + 837009214LL, 1086861056LL, 1370427101LL, 46089881LL, 906343792LL, -1028145925LL, + -218743319LL, -1352422881LL, -1183875557LL, -688253444LL, -1281911762LL, 479915620LL, + -439182728LL, 1295802047LL, 726453237LL, 1158716070LL, 1356681556LL, 167780668LL, + 985064129LL, -946972014LL, -115418440LL, -1360939725LL, -1130246922LL, -765790101LL, + -1305238820LL, 398303960LL, -508434332LL, 1265778060LL, 667641057LL, 1188847422LL, + 1344514998LL, 223143629LL, 1014121254LL, -909664468LL, -77531589LL, -1359537404LL, + -1110797118LL, -786706450LL, -1306712613LL, 379087677LL, -515625390LL, 1258479095LL, + 665681878LL, 1185304371LL, 1342045849LL, 213157034LL, 998423843LL, -920934803LL, + -105537349LL, -1353619404LL, -1128901420LL, -753301157LL, -1288948719LL, 423029788LL, + -461311624LL, 1275147278LL, 720497008LL, 1148112947LL, 1347884033LL, 137706633LL, + 936024331LL, -978822293LL, -198971242LL, -1339077789LL, -1179876462LL, -662644717LL, + -1245437752LL, 527809148LL, -342853844LL, 1307916192LL, 826755174LL, 1069191572LL, + 1350993880LL, -4075606LL, 818534684LL, -1074110123LL, -355430389LL, -1302265218LL, + -1250207396LL, -507665350LL, -1161073292LL, 686420083LL, -156339223LL, 1339159236LL, + 971896042LL, 933669172LL, 1330522583LL, -211104208LL, 633442376LL, -1188337227LL, + -567243364LL, -1220726115LL, -1315966097LL, -280564611LL, -1014088946LL, 883547785LL, + 99013319LL, 1340814587LL, 1132710323LL, 723266074LL, 1256532522LL, -475222058LL, + 368983402LL, -1291173266LL, -816137081LL, -1065724067LL, -1341633093LL, 21020573LL, + -780608094LL, 1090710697LL, 413860750LL, 1275264730LL, 1271764579LL, 422826455LL, + 1093390455LL, -774115748LL, 22286587LL, -1338975411LL, -1067024348LL, -808336581LL, + -1281537427LL, 384982290LL, -443264665LL, 1262010471LL, 759873838LL, 1100161101LL, + 1336197790LL, 30838901LL, 808085755LL, -1063949984LL, -389295553LL, -1277521413LL, + -1263568295LL, -430848153LL, -1087023069LL, 774107387LL, -4653460LL, 1333967789LL, + 1081581716LL, 779940449LL, 1262823124LL, -426663947LL, 385285235LL, -1275523939LL, + -815927352LL, -1052764623LL, -1330238467LL, 56252404LL, -722408478LL, 1117799676LL, + 496047351LL, 1234480616LL, 1294333790LL, 305556035LL, 994076624LL, -882688362LL, + -151591517LL, -1320232133LL, -1168060761LL, -632689287LL, -1187087821LL, 595110214LL, + -190374505LL, 1313684404LL, 969553993LL, 905899235LL, 1296484192LL, -280178325LL, + 507280020LL, -1225040475LL, -719516770LL, -1113122548LL, -1324354562LL, -39027857LL, + -782093446LL, 1068860718LL, 438952020LL, 1249060931LL, 1278240591LL, 342980000LL, + 1003607327LL, -861981505LL, -147387931LL, -1314239350LL, -1169412115LL, -616550837LL, + -1166130368LL, 621702465LL, -138351503LL, 1313754333LL, 1011215546LL, 849267724LL, + 1268768441LL, -364367147LL, 404850777LL, -1255929879LL, -817637363LL, -1035115076LL, + -1314472071LL, 104355913LL, -642354294LL, 1151018620LL, 602159510LL, 1172009358LL, + 1308999165LL, 146511019LL, 844660327LL, -1010068566LL, -376934842LL, -1261093883LL, + -1259910595LL, -379227860LL, -1008763964LL, 844000831LL, 152268463LL, 1305952951LL, + 1175676623LL, 587573808LL, 1134346530LL, -662932199LL, 63631865LL, -1311845096LL, + -1064941627LL, -767889308LL, -1223197666LL, 475723579LL, -264689964LL, 1285005174LL, + 935963575LL, 918720732LL, 1278634722LL, -289738188LL, 446835214LL, -1232061426LL, + -796226556LL, -1040406191LL, -1304967648LL, 110763358LL, -607771519LL, 1159574429LL, + 652207681LL, 1134643978LL, 1307036929LL, 56936454LL, 746686784LL, -1073705857LL, + -509274299LL, -1204087120LL, -1289839832LL, -210481627LL, -863941853LL, 979999768LL, + 371681726LL, 1251980884LL, 1258246071LL, 348182774LL, 960765504LL, -883265307LL, + -242644628LL, -1281860979LL, -1216798408LL, -469323018LL, -1038975465LL, 787536268LL, + 124455530LL, 1297311689LL, 1169586207LL, 573934482LL, 1100735062LL, -696091479LL, + -18630340LL, -1301785192LL, -1120179755LL, -662587522LL, -1148351214LL, 611514425LL, + -73937021LL, 1298472785LL, 1071610220LL, 736199698LL, 1184112556LL, -535778368LL, + 152822212LL, -1290221394LL, -1026382916LL, -795871323LL, -1210165540LL, 470342299LL, + -217929883LL, 1279484577LL, 986510871LL, 842748155LL, 1228422438LL, -416248269LL, + 269369294LL, -1268299209LL, -953559494LL, -877910939LL, -1240496388LL, 374212324LL, + -307350090LL, 1258279398LL, 928693129LL, 902290014LL, 1247656676LL, -344703062LL, + 332098629LL, -1250619529LL, -912717940LL, -916601412LL, -1250799887LL, 328005228LL, + -343796054LL, 1246101803LL, 906115487LL, 921303308LL, 1250431695LL, -324264189LL, + 342537115LL, -1245101878LL, -909064460LL, -916568558LL, -1246656989LL, 333511997LL, + -328310310LL, 1247592069LL, 921447712LL, 902274540LL, 1239175774LL, -355671368LL, + 300998606LL, -1253137664LL, -942844438LL, -878006819LL, -1227285306LL, 390540365LL, + -260401823LL, 1260889812LL, 972506994LL, 843080875LL, 1209888977LL, -437754098LL, + 206280718LL, -1269572721LL, -1009324495LL, -796579721LL, -1185515409LL, 496728112LL, + -138424390LL, 1277472674LL, 1051775351LL, 737414501LL, 1152351385LL, -566580355LL, + 56741203LL, -1282429225LL, -1097873863LL, -664406777LL, -1108294879LL, 646039243LL, + 38625871LL, 1281840378LL, 1145116740LL, 576401228LL, 1051034317LL, -733337032LL, + -147161030LL, -1272685073LL, -1190438864LL, -472406658LL, -978161994LL, 826095175LL, + 267817026LL, 1251568908LL, 1230189053LL, 351769631LL, 887328325LL, -921245302LL, + -398842745LL, -1214870044LL, -1260140237LL, -214397855LL, -776443452LL, 1014887483LL, + 537606700LL, 1158784606LL, 1275549789LL, 60965002LL, 643929053LL, -1102289337LL, + -680432272LL, -1079650191LL, -1271288229LL, 106805625LL, -489019507LL, 1177875233LL, + 822465608LL, 974181710LL, 1242053772LL, -285890724LL, 312103891LL, -1235303730LL, + -957604283LL, -839840526LL, -1182688778LL, 471741852LL, -115091711LL, 1267676544LL, + 1078519865LL, 675279927LL, 1088607896LL, -658103152LL, -98227139LL, -1267863699LL, + -1176812437LL, -480834364LL, -956338598LL, 836940822LL, 321870577LL, 1228990443LL, + 1243335154LL, 259037347LL, 784159190LL, -998520089LL, -547457816LL, -1145078891LL, + -1268722919LL, -15099776LL, -572799634LL, 1131705608LL, 764177324LL, 1011860221LL, + 1244146277LL, -242692024LL, 326144497LL, -1224500641LL, -959007067LL, -827678891LL, + -1162290063LL, 502797494LL, -51849215LL, 1264915956LL, 1117263922LL, 594473862LL, + 1018522433LL, -750511491LL, -238248204LL, -1242124189LL, -1223546075LL, -318670781LL, + -812175834LL, 968488036LL, 528060414LL, 1147925746LL, 1263100366LL, 11889771LL, + 547807578LL, -1137740866LL, -797679673LL, -978386412LL, -1223594172LL, 308767247LL, + -236251368LL, 1239230750LL, 1024440778LL, 735538002LL, 1097195640LL, -621002881LL, + -104779616LL, -1255982958LL, -1184713020LL, -428856462LL, -882771597LL, 898425861LL, + 450807450LL, 1175678262LL, 1256432857LL, 76257047LL, 587907461LL, -1112562854LL, + -771684851LL, -993442454LL, -1222263625LL, 295791405LL, -230356136LL, 1235861216LL, + 1033871587LL, 714508383LL, 1073104859LL, -653341128LL, -161542388LL, -1245515873LL, + -1203959776LL, -356209323LL, -811489493LL, 957542860LL, 549929934LL, 1127820844LL, + 1253305883LL, -51247250LL, 454232930LL, -1168791722LL, -890350582LL, -882427600LL, + -1163349831LL, 465856011LL, -33580735LL, 1252309553LL, 1136664943LL, 525739154LL, + 930887980LL, -837172955LL, -403901893LL, -1184600074LL, -1247746542LL, -92449084LL, + -572276462LL, 1112170204LL, 801286949LL, 959878402LL, 1195282377LL, -365693353LL, + 125358720LL, -1243270536LL, -1098291417LL, -595145583LL, -971485981LL, 784642464LL, + 352062850LL, 1197709041LL, 1240936662LL, 132429068LL, 595081698LL, -1096515077LL, + -788061882LL, -966660811LL, -1192690394LL, 363279661LL, -113686548LL, 1241195280LL, + 1106890652LL, 572093436LL, 945119058LL, -811329258LL, -399130339LL, -1179494862LL, + -1242883084LL, -69017878LL, -525453600LL, 1128020022LL, 853152279LL, 905356431LL, + 1155860457LL, -458839625LL, -1709896LL, -1243202597LL, -1156975171LL, -453842614LL, + -844779903LL, 910999924LL, 540831002LL, 1118071861LL, 1237706486LL, -98356329LL, + 355656576LL, -1189162822LL, -980835894LL, -759980094LL, -1061139678LL, 642339957LL, + 220038265LL, 1220331968LL, 1218180828LL, 229501149LL, 647181670LL, -1056787291LL, + -758909750LL, -979136338LL, -1183555800LL, 364494670LL, -74889150LL, 1235742990LL, + 1130818443LL, 502918060LL, 865758843LL, -883824643LL, -527319193LL, -1118761104LL, + -1231779422LL, 106860313LL, -324967805LL, 1192519618LL, 1007577056LL, 715193938LL, + 1016923335LL, -701132723LL, -311560651LL, -1194845738LL, -1229161299LL, -113556843LL, + -523342122LL, 1117520314LL, 874829421LL, 869722590LL, 1112991517LL, -531035235LL, + -127228970LL, -1226199716LL, -1197916065LL, -289403566LL, -671154470LL, 1033108424LL, + 752124877LL, 975229602LL, 1168437144LL, -387971369LL, 17735104LL, -1230631860LL, + -1156582985LL, -419627331LL, -773687598LL, 956127800LL, 652669428LL, 1042015480LL, + 1196758502LL, -280254676LL, 120389813LL, -1222816149LL, -1119080394LL, -506390417LL, + -837319461LL, 898146390LL, 584592957LL, 1079360770LL, 1208631016LL, -212076727LL, + 180404939LL, -1213348992LL, -1094680831LL, -552658494LL, -867403167LL, 866235814LL, + 552326386LL, 1093929880LL, 1210963449LL, -185223756LL, 198271214LL, -1208478962LL, + -1088340898LL, -560570211LL, -866970663LL, 863758078LL, 557663679LL, 1088906625LL, + 1206484500LL, -200226819LL, 174225656LL, -1210094798LL, -1100990977LL, -530556826LL, + -836108998LL, 890831218LL, 600276376LL, 1063631766LL, 1193596635LL, -256818895LL, + 107921559LL, -1215716036LL, -1129567714LL, -461163930LL, -771913275LL, 944313070LL, + 677579917LL, 1013628843LL, 1166391627LL, -353649596LL, -1141525LL, -1218406587LL, + -1166742637LL, -349578360LL, -669028438LL, 1017285980LL, 783951257LL, 931056048LL, + 1114899798LL, -487254774LL, -152401583LL, -1206716715LL, -1200475409LL, -192929724LL, + -520906919LL, 1098175513LL, 909411249LL, 805775196LL, 1025824970LL, -650348569LL, + -342228243LL, -1164953374LL, -1213717733LL, 9538607LL, -321981282LL, 1169826313LL, + 1038059033LL, 627344678LL, 884172773LL, -829654938LL, -561241886LL, -1074269943LL, + -1184815499LL, 253414283LL, -70915667LL, 1209104730LL, 1146809961LL, 388259367LL, + 676253911LL, -1003769238LL, -791344351LL, -915203966LL, -1089362215LL, 525418683LL, + 225126438LL, 1187872868LL, 1205331645LL, 88582523LL, 394433428LL, -1141945382LL, + -1003303454LL, -672267298LL, -904336598LL, 799799334LL, 545761837LL, 1076377472LL, + 1178400610LL, -258370815LL, 43558620LL, -1205165309LL, -1156324785LL, -340836242LL, + -615117317LL, 1036253270LL, 853585281LL, 850008399LL, 1031995702LL, -620513565LL, + -351904239LL, -1151148938LL, -1201571060LL, 64295079LL, -225154618LL, 1181582310LL, + 1093644151LL, 499696273LL, 743945929LL, -944043922LL, -742373967LL, -944708405LL, + -1091631881LL, 500848800LL, 233510117LL, 1177666032LL, 1199310276LL, 44627760LL, + 318439906LL, -1156651736LL, -1053204576LL, -573511694LL, -796875994LL, 895572659LL, + 692965637LL, 977632043LL, 1107420499LL, -456604316LL, -199054468LL, -1180739027LL, + -1195092614LL, -66471004LL, -326803099LL, 1150982036LL, 1051742106LL, 569465849LL, + 783253385LL, -903248333LL, -713515902LL, -958710969LL, -1088502900LL, 492218415LL, + 250155558LL, 1167657151LL, 1193683563LL, 1300810LL, 250754022LL, -1166569002LL, + -1088658629LL, -487298040LL, -700979250LL, 964437011LL, 800226403LL, 883187151LL, + 1026961241LL, -603819506LL, -384085997LL, -1127201949LL, -1180814916LL, 150521140LL, + -87163462LL, 1186694290LL, 1145710625LL, 319447369LL, 537385491LL, -1060552361LL, + -935529375LL, -732934226LL, -899214656LL, 776318191LL, 589672141LL, 1030723391LL, + 1123468442LL, -383103369LL, -164560749LL, -1175036747LL, -1184600750LL, -57886843LL, + -276354461LL, 1152863311LL, 1081946685LL, 483415184LL, 672337191LL, -975239255LL, + -837207256LL, -837281361LL, -973452593LL, 673179445LL, 489117563LL, 1077202729LL, + 1146087560LL, -291381286LL, -86495170LL, -1178878078LL, -1175529074LL, -119072333LL, + -319111716LL, 1137111702LL, 1065713984LL, 507853177LL, 680118983LL, -964314479LL, + -836638198LL, -831444537LL, -958169596LL, 687000615LL, 520143266LL, 1057498176LL, + 1127525509LL, -341068521LL, -154881130LL, -1167235968LL, -1176476633LL, -33361092LL, + -218785356LL, 1155907478LL, 1106930356LL, 396825584LL, 563324215LL, -1031602719LL, + -932541247LL, -714614605LL, -847584555LL, 812817674LL, 675849390LL, 959719554LL, + 1049125168LL, -525289697LL, -364922148LL, -1114531137LL, -1155280158LL, 198560363LL, + 29954128LL, 1171301965LL, 1163073388LL, 137295049LL, 299806127LL, -1131568097LL, + -1078199809LL, -454479076LL, -598544734LL, 1004759771LL, 913349331LL, 729602428LL, + 845644299LL, -806311148LL, -686162187LL, -945068406LL, -1026682631LL, 555528651LL, + 417083098LL, 1089698959LL, 1133718132LL, -273486249LL, -127335510LL, -1158707221LL, + -1164972480LL, -18880425LL, -162821568LL, 1153127487LL, 1124056732LL, 302329771LL, + 435453928LL, -1078877034LL, -1018898915LL, -560468578LL, -675887237LL, 945587778LL, + 860524717LL, 780469725LL, 873222978LL, -765368842LL, -661822764LL, -953397001LL, + -1020477604LL, 551600653LL, 436398240LL, 1074175441LL, 1114411039LL, -317866131LL, + -197587562LL, -1141297481LL, -1155122320LL, 77059591LL, -42323192LL, 1156328240LL, + 1145492069LL, 159281533LL, 272660170LL, -1123303623LL, -1090545694LL, -381433498LL, + -484709337LL, 1048074572LL, 996800515LL, 581730135LL, 671870988LL, -937669380LL, + -871646456LL, -754635732LL, -829652247LL, 799701719LL, 722795769LL, 896666336LL, + 955533632LL, -641867394LL, -557823622LL, -1006210697LL, -1048746368LL, 471531331LL, + 383809594LL, 1083272695LL, 1109994894LL, -295423540LL, -207080437LL, -1129181327LL, + -1141154469LL, 119427046LL, 33047371LL, 1146282129LL, 1144968299LL, 51538477LL, + 133873691LL, -1137644521LL, -1124762597LL, -213563379LL, -290273203LL, 1106787858LL, + 1084192343LL, 363727404LL, 433705585LL, -1057448668LL, -1027025277LL, -500039148LL, + -562608155LL, 993382319LL, 956967457LL, 621337946LL, 676194945LL, -918212320LL, + -877530222LL, -727182435LL, -774337015LL, 835314388LL, 791936024LL, 817725082LL, + 857438762LL, -747742877LL, -703058856LL, -893592005LL, -926317484LL, 658184004LL, + 613394167LL, 955763658LL, 982091417LL, -568940981LL, -525052725LL, -1005470972LL, + -1026079580LL, 481935342LL, 439767403LL, 1044099441LL, 1059705288LL, -398729118LL, + -358950670LL, -1073112048LL, -1084473653LL, 320553493LL, 283655032LL, 1093981638LL, + 1101813309LL, -248349121LL, -214709592LL, -1108141150LL, -1113130104LL, 182805654LL, + 152690633LL, 1116941564LL, 1119725878LL, -124406451LL, -97989602LL, -1121624550LL, + -1122773897LL, 73467911LL, 50859952LL, 1123299764LL, 1123317216LL, -30180019LL, + -11438053LL, -1122933075LL, -1122244000LL, -5360861LL, -20213774LL, 1121336302LL, + 1120287456LL, 33120080LL, 44081866LL, -1119164449LL, -1118023515LL, -53101457LL, + -60181479LL, 1116911906LL, 1115866615LL, 65325862LL, 68537656LL, -1114913539LL, + -1114069763LL, -69818596LL, -69171458LL, 1113343128LL, 1112729674LL, 66599008LL, + 62101549LL, -1112215070LL, -1111776909LL, -55678756LL, -47331973LL, 1111382832LL, + 1110988638LL, 37062604LL, 24870807LL, -1110540110LL, -1109974546LL, -10757676LL, + 5272784LL, 1109219199LL, 1108189934LL, -23214438LL, -43059657LL, -1106792597LL, + -1104924494LL, 64797288LL, 88410341LL, 1102473367LL, 1099316148LL, -113876140LL, + -141166756LL, -1095320380LL, -1090346072LL, 170246688LL, 201070155LL, 1084244951LL, + 1076859537LL, -233581053LL, -267713094LL, -1068025079LL, -1057571810LL, 303387176LL, + 340508620LL, 1045324679LL, 1031103190LL, -378966995LL, -418635990LL, -1014723969LL, + -996003542LL, 459370852LL, 501005879LL, 974758968LL, 950808690LL, -543354261LL, + -586208070LL, -923975832LL, -894091783LL, 629336230LL, 672482617LL, 860997942LL, + 824547629LL, -715366438LL, -757682946LL, -784610267LL, -741075875LL, 799102495LL, + 839269855LL, 693857839LL, 642895771LL, -877805875LL, -914309692LL, -588160435LL, + -529658881LL, 948359581LL, 979514302LL, 467437797LL, 401586808LL, -1007316873LL, + -1031299060LL, -332243497LL, -259598339LL, 1050984824LL, 1065894439LL, 183897682LL, + 105446338LL, -1075551050LL, -1079488051LL, -24611378LL, 58174610LL, 1077255581LL, + 1068427732LL, -142412569LL, -227536933LL, -1052612011LL, -1029459508LL, 312915023LL, + 397847568LL, 998674071LL, 960021902LL, -481572013LL, -563267319LL, -913342921LL, + -858562313LL, 642058873LL, 717025078LL, 795700551LL, 724883108LL, -787207151LL, + -851620825LL, -646350982LL, -560470397LL, 909268605LL, 959153933LL, 467739959LL, + 368796289LL, -1000298566LL, -1031761761LL, -264419073LL, -155533861LL, 1052659801LL, + 1062186951LL, 43210966LL, -71338631LL, -1059638771LL, -1044436183LL, 186769512LL, + 301611719LL, 1016148654LL, 974517174LL, -414285773LL, -523121818LL, -919477577LL, + -851182364LL, 626381890LL, 722286495LL, 770019174LL, 676626274LL, -809046499LL, + -884898957LL, -571905279LL, -457029165LL, 948145506LL, 997193865LL, 333443718LL, + 202862706LL, -1030602728LL, -1047128119LL, -67256978LL, 71164159LL, 1045769203LL, + 1025813357LL, -209980707LL, -346598209LL, -986879983LL, -928960586LL, 478291655LL, + 602257868LL, 852452591LL, 758186169LL, -715676762LL, -815779731LL, -647443153LL, + -521965432LL, 899923269LL, 965667192LL, 383950488LL, 236033528LL, -1010856369LL, + -1033702851LL, -81255839LL, 76982318LL, 1032865113LL, 1007522400LL, -234985311LL, + -388841303LL, -957441776LL, -883033842LL, 534515576LL, 667957444LL, 785393237LL, + 666321523LL, -785219312LL, -882584353LL, -528330125LL, -374620029LL, 956698712LL, + 1004704823LL, 209035662LL, 35992373LL, -1024371623LL, -1014215707LL, 139622346LL, + 312573985LL, 973607297LL, 902855983LL, -477431220LL, -628737534LL, -803271033LL, + -677190335LL, 761199459LL, 869886492LL, 527972835LL, 359951350LL, -950436309LL, + -999256753LL, -178343718LL, 10879251LL, 1013715429LL, 992308122LL, -201168524LL, + -385610812LL, -934796871LL, -842307777LL, 557176294LL, 708993321LL, 717379590LL, + 563956206LL, -834640923LL, -928447102LL, -387317816LL, -193946913LL, 985779401LL, + 1003313816LL, -8671568LL, -212312750LL, -979267238LL, -913577945LL, 408330400LL, + 588022129LL, 808019745LL, 666237853LL, -743027930LL, -865744763LL, -493697062LL, + -297535687LL, 949737288LL, 990123392LL, 86323412LL, -130273158LL, -983911839LL, + -930268833LL, 341908105LL, 538042665LL, 830691978LL, 689073533LL, -708480410LL, + -843925428LL, -511638977LL, -306752280LL, 936533798LL, 980426259LL, 84586446LL, + -143333551LL, -972128575LL, -910906391LL, 364700047LL, 567080489LL, 798964688LL, + 641487576LL, -738631723LL, -868831300LL, -446501596LL, -224554952LL, 949181318LL, + 973837749LL, -11783322LL, -248587567LL, -940117978LL, -848842316LL, 471373881LL, + 665991533LL, 704472236LL, 515018636LL, -819555379LL, -921358828LL, -291706570LL, + -48398651LL, 963702385LL, 942572579LL, -199202818LL, -434536583LL, -858110224LL, + -714816326LL, 641290539LL, 804566792LL, 521458788LL, 290662263LL, -912021819LL, + -954893692LL, -38185981LL, 218080948LL, 928828856LL, 834428426LL, -459351866LL, + -667324098LL, -677448565LL, -468611243LL, 825611972LL, 921120162LL, 223009796LL, + -40874042LL, -945240543LL, -894759693LL, 302490931LL, 540798293LL, 772378651LL, + 586770962LL, -735974149LL, -871133699LL, -352138446LL, -87265003LL, 933899496LL, + 917675664LL, -185885976LL, -443939509LL, -822489861LL, -655294382LL, 664109687LL, + 826266997LL, 429658757LL, 164837522LL, -914885104LL, -920675107LL, 115745170LL, + 386492309LL, 841729013LL, 684026632LL, -621954273LL, -799269207LL, -461210400LL, + -193598018LL, 900491001LL, 914563810LL, -93522216LL, -372191219LL, -838717819LL, + -679102389LL, 614480060LL, 795339377LL, 450537828LL, 175350798LL, -895307734LL, + -902780906LL, 118646015LL, 400870850LL, 815567739LL, 641514363LL, -641137342LL, + -812947559LL, -398064647LL, -110734512LL, 896554655LL, 881433548LL, -189399782LL, + -468977600LL, -767837495LL, -567200135LL, 696065699LL, 843899670LL, 301260402LL, + -69348LL, -894213472LL, -839731332LL, 301918151LL, 568434078LL, 685466060LL, + 448588023LL, -767085363LL, -872771934LL, -156789752LL, 154743685LL, 871219507LL, + 761180081LL, -447461368LL, -684209078LL, -555081354LL, -277944307LL, 834048954LL, + 876506682LL, -35395676LL, -344499437LL, -804646603LL, -626490157LL, 608488588LL, + 791520403LL, 364484599LL, 52977069LL, -867839625LL, -825680394LL, 266075320LL, + 548662339LL, 669402072LL, 419450848LL, -754830675LL, -854503175LL, -110023975LL, + 215359296LL, 832146336LL, 689534299LL, -509852536LL, -730045151LL, -446088882LL, + -136604941LL, 842524961LL, 829234946LL, -193444302LL, -494441668LL, -690735243LL, + -446747072LL, 720094129LL, 834719775LL, 133740460LL, -200219185LL, -819192098LL, + -674517874LL, 502696280LL, 725131415LL, 422340511LL, 102116978LL, -830820897LL, + -801300892LL, 234749598LL, 533011449LL, 639987150LL, 372309362LL, -742670906LL, + -827577577LL, -42127825LL, 295152242LL, 772026554LL, 584107231LL, -581751387LL, + -767487570LL, -295043612LL, 45568749LL, 818827906LL, 725355220LL, -377993630LL, + -642749156LL, -502347399LL, -188797765LL, 791385490LL, 795681387LL, -158994527LL, + -477300582LL, -653468822LL, -389820265LL, 706628158LL, 803057964LL, 53138088LL, + -293363331LL, -747063144LL, -547981028LL, 583368570LL, 760239390LL, 243047287LL, + -109087870LL, -788395238LL, -660962995LL, 439344926LL, 681716660LL, 401976110LL, + 62410180LL, -786671223LL, -731708227LL, 289433851LL, 581485080LL, 526748686LL, + 212985315LL, -752758156LL, -766442958LL, 144878382LL, 471665419LL, 618362077LL, + 338761629LL, -697491650LL, -772975470LL, 13267082LL, 361861265LL, 680540547LL, + 439135615LL, -630594977LL, -759405462LL, -101014718LL, 259065045LL, 718467667LL, + 515730542LL, -560126761LL, -733262464LL, -196100816LL, 167916632LL, 737795767LL, + 571456182LL, -492326865LL, -701017882LL, -271903552LL, 91145697LL, 743948990LL, + 609748211LL, -431723707LL, -667881988LL, -329428853LL, 30071033LL, 741685751LL, + 634004684LL, -381383594LL, -637791596LL, -370205357LL, -14927172LL, 734862827LL, + 647202258LL, -343209935LL, -613504669LL, -395847637LL, -44010493LL, 726338595LL, + 651658523LL, -318228310LL, -596735876LL, -407750146LL, -57583445LL, 717959741LL, + 648903612LL, -306817330LL, -588286334LL, -406897520LL, -56099319LL, 710588329LL, + 639629497LL, -308863422LL, -588138409LL, -393774981LL, -39969130LL, 704140898LL, + 623695295LL, -323830426LL, -595501633LL, -368366312LL, -9569279LL, 697626153LL, + 600178867LL, -350743757LL, -608808863LL, -330233429LL, 34656829LL, 689182260LL, + 567477149LL, -388096106LL, -625673942LL, -278678344LL, 92008494LL, 676128317LL, + 523468693LL, -433689264LL, -642834415LL, -212993079LL, 161257242LL, 655057261LL, + 465760063LL, -484436802LL, -656116047LL, -132803402LL, 240312881LL, 622008280LL, + 392041123LL, -536166219LL, -660469672LL, -38505598LL, 325857894LL, 572763869LL, + 300569876LL, -583476957LL, -650143367LL, 68220617LL, 413004730LL, 503316446LL, + 190791729LL, -619730709LL, -619059936LL, 183867529LL, 495059785LL, 410537093LL, + 64067366LL, -637268081LL, -561464790LL, 302606866LL, 563509367LL, 293048325LL, + -75564741LL, -627953057LL, -472883669LL, 415980286LL, 608367526LL, 152248609LL, + -220729229LL, -584132159LL, -351374020LL, 512950472LL, 619029099LL, -6643465LL, + -360368228LL, -500044641LL, -198961416LL, 580519175LL, 585734138LL, -173757319LL, + -479980960LL, -373620471LL, -23024324LL, 605104733LL, 501651239LL, -334284253LL, + -562741149LL, -208448648LL, 162756761LL, 574784870LL, 365412211LL, -469138566LL, + -591724058LL, -15501274LL, 338397868LL, 482323578LL, 183682316LL, -556949417LL, + -553289454LL, 186001807LL, 479114285LL, 328604376LL, -26933868LL, -577601089LL, + -441329402LL, 369331436LL, 558760804LL, 125715855LL, -239586275LL, -517174466LL, + -261616866LL, 503281956LL, 555270699LL, -101429716LL, -419459424LL, -373573729LL, + -34974109LL, 557837757LL, 457497426LL, -316255672LL, -529328707LL, -161434354LL, + 202392141LL, 512082758LL, 271989131LL, -475571095LL, -538304608LL, 85686113LL, + 402993867LL, 362892996LL, 27365864LL, -538833522LL, -432410699LL, 317994128LL, + 517450317LL, 131784241LL, -226467026LL, -480490677LL, -224124634LL, 478515980LL, + 508382425LL, -133497964LL, -426530927LL, -302365981LL, 43199803LL, 518248453LL, + 365715263LL, -365798428LL, -512807053LL, -41331480LL, 300192142LL, 414369450LL, + 117972405LL, -495028121LL, -449267281LL, 233017756LL, 467892273LL, 185467872LL, + -166953303LL, -471854385LL, -243293056LL, 434214541LL, 483876598LL, -104050335LL, + -396527967LL, -291502105LL, 45778130LL, 487209169LL, 330578869LL, -357018614LL, + -483724258LL, -6905018LL, 317501603LL, 361299917LL, 53466442LL, -475195077LL, + -384616006LL, 279427639LL, 463232332LL, 93709722LL, -243910470LL, -401554662LL, + -127688668LL, 449247348LL, 413143830LL, -211767085LL, -434436079LL, -155629448LL, + 183563817LL, 420354886LL, 177863361LL, -419778376LL, -424062557LL, 159663151LL, + 406047313LL, 194771249LL, -140267721LL, -425018839LL, -206739628LL, 393824184LL, + 423837772LL, -125459137LL, -383515913LL, -214127935LL, 115230061LL, 420988263LL, + 217245710LL, -375372362LL, -416792759LL, 109508722LL, 369501675LL, 216338537LL, + -108175768LL, -411430034LL, -211581785LL, 365882473LL, 404940776LL, -111073610LL, + -364372525LL, -203081383LL, 118008555LL, 397235219LL, 190880917LL, -364713970LL, + -388102764LL, 128746139LL, 366535484LL, 174974640LL, -143000462LL, -377223988LL, + -155326332LL, 369352270LL, 364185708LL, -160418434LL, -372565289LL, -131894036LL, + 180559956LL, 348500109LL, 104660569LL, -375461577LL, -329629366LL, 202875441LL, + 377217726LL, 73669505LL, -226682685LL, -307017226LL, -39066190LL, 376909001LL, + 280128775LL, -251145632LL, -373527008LL, -1142640LL, 275258127LL, 248499308LL, + -39615734LL, -366008908LL, -211792658LL, 297836425LL, 353280929LL, -82484716LL, + -317525031LL, -169868295LL, 126461466LL, 334318466LL, 122854902LL, -332820818LL, + -308224164LL, 170235976LL, 342120321LL, 71226291LL, -212180910LL, -274323761LL, + -15873368LL, 343794578LL, 232276990LL, -250367963LL, -336294622LL, 41836638LL, + 282619159LL, 182197737LL, -100024976LL, -318288237LL, -124774029LL, 306600965LL, + 288824737LL, -156303485LL, -319967167LL, -61374170LL, 207828107LL, 247519557LL, + -5878869LL, -320552586LL, -194744256LL, 251417200LL, 306613595LL, -74086064LL, + -283744944LL, -131800704LL, 139626730LL, 277103188LL, 61051310LL, -301613811LL, + -231958373LL, 198310209LL, 302300132LL, -14028114LL, -245640984LL, -172366534LL, + 88908365LL, 283953390LL, 100966836LL, -277202707LL, -246013718LL, 158212397LL, + 289150156LL, 21935112LL, -216089163LL, -189594890LL, 59101152LL, 278776341LL, + 117764604LL, -256760087LL, -245096693LL, 135364118LL, 275215125LL, 35644361LL, + -199470855LL, -189366640LL, 49747550LL, 268000585LL, 115428352LL, -244218090LL, + -234002622LL, 129969959LL, 263556972LL, 29773886LL, -195974189LL, -175095024LL, + 58777312LL, 253654728LL, 96496950LL, -239230138LL, -213885802LL, 139852120LL, + 253060840LL, 6686628LL, -202749085LL, -147552368LL, 83249064LL, 234005194LL, + 62118302LL, -238024311LL, -182959771LL, 160875054LL, 239239833LL, -31232407LL, + -214210889LL, -105811963LL, 118820508LL, 204574184LL, 13291094LL, -233866894LL, + -137925381LL, 186449387LL, 215160500LL, -80149844LL, -221923623LL, -49132021LL, + 158444371LL, 159750116LL, -46973541LL, -217700348LL, -76293130LL, 206806717LL, + 173105521LL, -132771287LL, -214944017LL, 20277043LL, 191122244LL, 95482472LL, + -111030727LL, -179898295LL, 273021LL, 209169124LL, 107723446LL, -176697226LL, + -181840853LL, 94065837LL, 202088576LL, 13288350LL, -164675947LL, -114077472LL, + 82178854LL, 180298082LL, 20880746LL, -194851333LL, -115470438LL, 155644347LL +}; diff --git a/test/cmocka/src/audio/eq_iir/cmocka_iir_coef_2ch.h b/test/cmocka/src/audio/eq_iir/cmocka_iir_coef_2ch.h new file mode 100644 index 000000000000..c72679b7e4a2 --- /dev/null +++ b/test/cmocka/src/audio/eq_iir/cmocka_iir_coef_2ch.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + */ + +uint32_t iir_coef_2ch[51] = { + 0x00464f53, 0x00000000, 0x000000ac, 0x03013000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x000000ac, 0x00000002, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000004, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xc12c82bd, + 0x7ed0b52e, 0x1fc7cc0c, 0xc07067e9, 0x1fc7cc0c, + 0x00000000, 0x00004000, 0xcad0cdef, 0x742e8c5d, + 0x0cdc9086, 0xe2f11723, 0x10b2f932, 0x00000000, + 0x00004000, 0xcf45334a, 0x68260de9, 0x0a54e176, + 0xe5d6cb75, 0x11fc1f3d, 0x00000000, 0x00004000, + 0xf2940609, 0xe25f3930, 0x0d69ba64, 0x1ad374c8, + 0x0d69ba64, 0xfffffffb, 0x000045bf +}; diff --git a/test/cmocka/src/audio/eq_iir/eq_iir_process.c b/test/cmocka/src/audio/eq_iir/eq_iir_process.c new file mode 100644 index 000000000000..756a4606c68b --- /dev/null +++ b/test/cmocka/src/audio/eq_iir/eq_iir_process.c @@ -0,0 +1,524 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <stdint.h> +#include <cmocka.h> +#include <kernel/header.h> +#include <sof/audio/component_ext.h> +#include <eq_iir/eq_iir.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <ipc/control.h> + +#include "../../util.h" +#include "../../../include/cmocka_chirp_2ch.h" +#include "cmocka_chirp_iir_ref_2ch.h" +#include "cmocka_iir_coef_2ch.h" + +/* Allow some small error for fixed point. In IIR case due to float + * reference with float coefficients the difference can be quite + * large to scaled integer bi-quads. This could be re-visited with + * a more implementation like reference in Octave test vector + * generate script. + */ +#define ERROR_TOLERANCE_S16 2 +#define ERROR_TOLERANCE_S24 128 +#define ERROR_TOLERANCE_S32 32768 + +/* Thresholds for frames count jitter for rand() function */ +#define THR_RAND_PLUS_ONE ((RAND_MAX >> 1) + (RAND_MAX >> 2)) +#define THR_RAND_MINUS_ONE ((RAND_MAX >> 1) - (RAND_MAX >> 2)) + +struct buffer_fill { + int idx; +} buffer_fill_data; + +struct buffer_verify { + int idx; +} buffer_verify_data; + +struct test_parameters { + uint32_t channels; + uint32_t frames; + uint32_t buffer_size_mult; + uint32_t source_format; + uint32_t sink_format; +}; + +struct test_data { + struct comp_dev *dev; + struct comp_buffer *sink; + struct comp_buffer *source; + struct test_parameters *params; + struct processing_module *mod; + bool continue_loop; +}; + +static int setup_group(void **state) +{ + sys_comp_init(sof_get()); + sys_comp_module_eq_iir_interface_init(); + return 0; +} + +static struct sof_ipc_comp_process *create_eq_iir_comp_ipc(struct test_data *td) +{ + struct sof_ipc_comp_process *ipc; + size_t ipc_size = sizeof(struct sof_ipc_comp_process); + const struct sof_uuid uuid = SOF_REG_UUID(eq_iir); + + ipc = calloc(1, ipc_size + SOF_UUID_SIZE); + memcpy_s(ipc + 1, SOF_UUID_SIZE, &uuid, SOF_UUID_SIZE); + ipc->comp.hdr.size = ipc_size + SOF_UUID_SIZE; + ipc->comp.type = SOF_COMP_MODULE_ADAPTER; + ipc->config.hdr.size = sizeof(struct sof_ipc_comp_config); + ipc->size = 0; + ipc->comp.ext_data_length = SOF_UUID_SIZE; + return ipc; +} + +static int eq_iir_send_config(struct processing_module *mod) +{ + const struct module_interface *const ops = mod->dev->drv->adapter_ops; + struct sof_abi_hdr *blob = (struct sof_abi_hdr *)iir_coef_2ch; + size_t cdata_size = sizeof(struct sof_ipc_ctrl_data) + sizeof(struct sof_abi_hdr) + + blob->size; + struct sof_ipc_ctrl_data *cdata; + int ret; + + cdata = calloc(1, cdata_size); + if (!cdata) + return -ENOMEM; + + cdata->cmd = SOF_CTRL_CMD_BINARY; + cdata->num_elems = blob->size; + cdata->data[0].magic = blob->magic; + cdata->data[0].type = blob->type; + cdata->data[0].size = blob->size; + cdata->data[0].abi = blob->abi; + memcpy_s(cdata->data[0].data, blob->size, blob->data, blob->size); + + ret = ops->set_configuration(mod, 0, MODULE_CFG_FRAGMENT_SINGLE, + blob->size, (const uint8_t *)cdata, + blob->size, NULL, 0); + + free(cdata); + return ret; +} + +static void prepare_sink(struct test_data *td, struct processing_module *mod) +{ + struct test_parameters *parameters = td->params; + struct module_data *md = &mod->priv; + size_t size; + size_t free; + + /* allocate new sink buffer */ + size = parameters->frames * get_frame_bytes(parameters->sink_format, parameters->channels) * + parameters->buffer_size_mult; + + md->mpd.out_buff_size = parameters->frames * get_frame_bytes(parameters->sink_format, + parameters->channels); + + td->sink = create_test_sink(td->dev, 0, parameters->sink_format, + parameters->channels, size); + free = audio_stream_get_free_bytes(&td->sink->stream); + assert_int_equal(free, size); +} + +static void prepare_source(struct test_data *td, struct processing_module *mod) +{ + struct test_parameters *parameters = td->params; + struct module_data *md = &mod->priv; + size_t size; + size_t free; + + md->mpd.in_buff_size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->channels); + + size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->channels) * parameters->buffer_size_mult; + + td->source = create_test_source(td->dev, 0, parameters->source_format, + parameters->channels, size); + free = audio_stream_get_free_bytes(&td->source->stream); + assert_int_equal(free, size); +} + +static int setup(void **state) +{ + struct test_parameters *params = *state; + struct processing_module *mod; + struct test_data *td; + struct sof_ipc_comp_process *ipc; + struct comp_dev *dev; + int ret; + + td = test_malloc(sizeof(*td)); + if (!td) + return -EINVAL; + + td->params = test_malloc(sizeof(*params)); + if (!td->params) + return -EINVAL; + + memcpy_s(td->params, sizeof(*td->params), params, sizeof(*params)); + ipc = create_eq_iir_comp_ipc(td); + buffer_fill_data.idx = 0; + buffer_verify_data.idx = 0; + + dev = comp_new((struct sof_ipc_comp *)ipc); + free(ipc); + if (!dev) + return -EINVAL; + + td->dev = dev; + dev->frames = params->frames; + mod = comp_mod(dev); + + ret = eq_iir_send_config(mod); + if (ret) + return ret; + + prepare_sink(td, mod); + prepare_source(td, mod); + + /* allocate intermediate buffers */ + mod->input_buffers = test_malloc(sizeof(struct input_stream_buffer)); + mod->input_buffers[0].data = &td->source->stream; + mod->output_buffers = test_malloc(sizeof(struct output_stream_buffer)); + mod->output_buffers[0].data = &td->sink->stream; + mod->stream_params = test_malloc(sizeof(struct sof_ipc_stream_params)); + mod->stream_params->channels = params->channels; + mod->period_bytes = get_frame_bytes(params->source_format, params->channels) * 48000 / 1000; + + ret = module_prepare(mod, NULL, 0, NULL, 0); + if (ret) + return ret; + + td->continue_loop = true; + + *state = td; + return 0; +} + +static int teardown(void **state) +{ + struct test_data *td = *state; + struct processing_module *mod = comp_mod(td->dev); + + test_free(mod->input_buffers); + test_free(mod->output_buffers); + test_free(mod->stream_params); + mod->stream_params = NULL; + test_free(td->params); + free_test_source(td->source); + free_test_sink(td->sink); + comp_free(td->dev); + test_free(td); + return 0; +} + +#if CONFIG_FORMAT_S16LE +static void fill_source_s16(struct test_data *td, int frames_max) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int16_t *x; + int bytes_total; + int samples; + int frames; + int i; + int samples_processed = 0; + + sb = comp_dev_get_first_data_producer(dev); + ss = &sb->stream; + frames = MIN(audio_stream_get_free_frames(ss), frames_max); + samples = frames * audio_stream_get_channels(ss); + for (i = 0; i < samples; i++) { + x = audio_stream_write_frag_s16(ss, i); + *x = sat_int16(Q_SHIFT_RND(chirp_2ch[buffer_fill_data.idx++], 31, 15)); + samples_processed++; + if (buffer_fill_data.idx == CHIRP_2CH_LENGTH) { + td->continue_loop = false; + break; + } + } + + if (samples_processed > 0) { + bytes_total = samples_processed * audio_stream_sample_bytes(ss); + comp_update_buffer_produce(sb, bytes_total); + } + + mod->input_buffers[0].size = samples_processed / audio_stream_get_channels(ss); +} + +static void verify_sink_s16(struct test_data *td) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t delta; + int32_t ref; + int32_t out; + int16_t *x; + int samples; + int i; + + sb = comp_dev_get_first_data_consumer(dev); + ss = &sb->stream; + samples = mod->output_buffers[0].size >> 1; + for (i = 0; i < samples; i++) { + x = audio_stream_read_frag_s16(ss, i); + out = *x; + ref = sat_int16(Q_SHIFT_RND(chirp_iir_ref_2ch[buffer_verify_data.idx++], 31, 15)); + delta = ref - out; + if (delta > ERROR_TOLERANCE_S16 || delta < -ERROR_TOLERANCE_S16) + assert_int_equal(out, ref); + } +} +#endif /* CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S24LE +static void fill_source_s24(struct test_data *td, int frames_max) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t *x; + int bytes_total; + int samples; + int frames; + int i; + int samples_processed = 0; + + sb = comp_dev_get_first_data_producer(dev); + ss = &sb->stream; + frames = MIN(audio_stream_get_free_frames(ss), frames_max); + samples = frames * audio_stream_get_channels(ss); + for (i = 0; i < samples; i++) { + x = audio_stream_write_frag_s32(ss, i); + *x = sat_int24(Q_SHIFT_RND(chirp_2ch[buffer_fill_data.idx++], 31, 23)); + samples_processed++; + if (buffer_fill_data.idx == CHIRP_2CH_LENGTH) { + td->continue_loop = false; + break; + } + } + + if (samples_processed > 0) { + bytes_total = samples_processed * audio_stream_sample_bytes(ss); + comp_update_buffer_produce(sb, bytes_total); + } + + mod->input_buffers[0].size = samples_processed / audio_stream_get_channels(ss); +} + +static void verify_sink_s24(struct test_data *td) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t delta; + int32_t ref; + int32_t out; + int32_t *x; + int samples; + int i; + + sb = comp_dev_get_first_data_consumer(dev); + ss = &sb->stream; + samples = mod->output_buffers[0].size >> 2; + for (i = 0; i < samples; i++) { + x = audio_stream_read_frag_s32(ss, i); + out = (*x << 8) >> 8; /* Make sure there's no 24 bit overflow */ + ref = sat_int24(Q_SHIFT_RND(chirp_iir_ref_2ch[buffer_verify_data.idx++], 31, 23)); + delta = ref - out; + if (delta > ERROR_TOLERANCE_S24 || delta < -ERROR_TOLERANCE_S24) + assert_int_equal(out, ref); + } +} +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE +static void fill_source_s32(struct test_data *td, int frames_max) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int32_t *x; + int bytes_total; + int samples; + int frames; + int i; + int samples_processed = 0; + + sb = comp_dev_get_first_data_producer(dev); + ss = &sb->stream; + frames = MIN(audio_stream_get_free_frames(ss), frames_max); + samples = frames * audio_stream_get_channels(ss); + for (i = 0; i < samples; i++) { + x = audio_stream_write_frag_s32(ss, i); + *x = chirp_2ch[buffer_fill_data.idx++]; + samples_processed++; + if (buffer_fill_data.idx == CHIRP_2CH_LENGTH) { + td->continue_loop = false; + break; + } + } + + if (samples_processed > 0) { + bytes_total = samples_processed * audio_stream_sample_bytes(ss); + comp_update_buffer_produce(sb, bytes_total); + } + + mod->input_buffers[0].size = samples_processed / audio_stream_get_channels(ss); +} + +static void verify_sink_s32(struct test_data *td) +{ + struct processing_module *mod = comp_mod(td->dev); + struct comp_dev *dev = td->dev; + struct comp_buffer *sb; + struct audio_stream *ss; + int64_t delta; + int32_t ref; + int32_t out; + int32_t *x; + int samples; + int i; + + sb = comp_dev_get_first_data_consumer(dev); + ss = &sb->stream; + samples = mod->output_buffers[0].size >> 2; + for (i = 0; i < samples; i++) { + x = audio_stream_read_frag_s32(ss, i); + out = *x; + ref = chirp_iir_ref_2ch[buffer_verify_data.idx++]; + delta = (int64_t)ref - (int64_t)out; + if (delta > ERROR_TOLERANCE_S32 || delta < -ERROR_TOLERANCE_S32) + assert_int_equal(out, ref); + } +} +#endif /* CONFIG_FORMAT_S32LE */ + +static int frames_jitter(int frames) +{ + int r = rand(); + + if (r > THR_RAND_PLUS_ONE) + return frames + 1; + else if (r < THR_RAND_MINUS_ONE) + return frames - 1; + else + return frames; +} + +static void test_audio_eq_iir(void **state) +{ + struct test_data *td = *state; + struct processing_module *mod = comp_mod(td->dev); + + struct comp_buffer *source = td->source; + struct comp_buffer *sink = td->sink; + int ret; + int frames; + + while (td->continue_loop) { + frames = frames_jitter(td->params->frames); + switch (audio_stream_get_frm_fmt(&source->stream)) { + case SOF_IPC_FRAME_S16_LE: + fill_source_s16(td, frames); + break; + case SOF_IPC_FRAME_S24_4LE: + fill_source_s24(td, frames); + break; + case SOF_IPC_FRAME_S32_LE: + fill_source_s32(td, frames); + break; + case SOF_IPC_FRAME_S24_3LE: + break; + default: + assert(0); + break; + } + + mod->input_buffers[0].consumed = 0; + mod->output_buffers[0].size = 0; + ret = module_process_legacy(mod, mod->input_buffers, 1, + mod->output_buffers, 1); + assert_int_equal(ret, 0); + + comp_update_buffer_consume(source, mod->input_buffers[0].consumed); + comp_update_buffer_produce(sink, mod->output_buffers[0].size); + + switch (audio_stream_get_frm_fmt(&sink->stream)) { + case SOF_IPC_FRAME_S16_LE: + verify_sink_s16(td); + break; + case SOF_IPC_FRAME_S24_4LE: + verify_sink_s24(td); + break; + case SOF_IPC_FRAME_S32_LE: + verify_sink_s32(td); + break; + default: + assert(0); + break; + } + + comp_update_buffer_consume(sink, mod->output_buffers[0].size); + } +} + +static struct test_parameters parameters[] = { +#if CONFIG_FORMAT_S16LE + { 2, 48, 2, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE }, +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + { 2, 48, 2, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE }, +#endif /* CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_S32LE + { 2, 48, 2, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE }, +#endif /* CONFIG_FORMAT_S32LE */ + +#if CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S16LE + { 2, 48, 2, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE }, +#endif /* CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S24LE + { 2, 48, 2, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE }, +#endif /* CONFIG_FORMAT_S32LE && CONFIG_FORMAT_S24LE */ + +}; + +int main(void) +{ + int i; + + struct CMUnitTest tests[ARRAY_SIZE(parameters)]; + + for (i = 0; i < ARRAY_SIZE(parameters); i++) { + tests[i].name = "test_audio_eq_iir"; + tests[i].test_func = test_audio_eq_iir; + tests[i].setup_func = setup; + tests[i].teardown_func = teardown; + tests[i].initial_state = ¶meters[i]; + } + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, setup_group, NULL); +} diff --git a/test/cmocka/src/audio/mixer/CMakeLists.txt b/test/cmocka/src/audio/mixer/CMakeLists.txt index e74f3ac04624..c0dbb8a0a4fc 100644 --- a/test/cmocka/src/audio/mixer/CMakeLists.txt +++ b/test/cmocka/src/audio/mixer/CMakeLists.txt @@ -2,10 +2,35 @@ cmocka_test(mixer mixer_test.c - mock.c - comp_mock.c + ../module_adapter_test.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/buffer.c - ${PROJECT_SOURCE_DIR}/src/audio/mixer.c + ${PROJECT_SOURCE_DIR}/src/audio/mixer/mixer.c + ${PROJECT_SOURCE_DIR}/src/audio/mixer/mixer_generic.c + ${PROJECT_SOURCE_DIR}/src/audio/mixer/mixer_hifi3.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/lib/objpool.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter_ipc3.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module/generic.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) + +target_include_directories(mixer PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) target_link_libraries(mixer PRIVATE -lm) diff --git a/test/cmocka/src/audio/mixer/comp_mock.c b/test/cmocka/src/audio/mixer/comp_mock.c index cf09359ec453..3016c6b86afc 100644 --- a/test/cmocka/src/audio/mixer/comp_mock.c +++ b/test/cmocka/src/audio/mixer/comp_mock.c @@ -6,19 +6,24 @@ #include <stdint.h> #include <stddef.h> -#include <malloc.h> #include <sof/list.h> #include <sof/audio/stream.h> #include <sof/audio/component.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif + #include "comp_mock.h" static struct comp_dev *mock_comp_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) + const struct comp_ipc_config *config, + const void *spec) { - struct comp_dev *dev = calloc(1, sizeof(struct comp_dev)); + struct comp_dev *dev = comp_alloc(drv, sizeof(*dev)); - dev->drv = drv; return dev; } @@ -57,7 +62,7 @@ static int mock_comp_prepare(struct comp_dev *dev) static const struct comp_driver comp_mock = { .type = SOF_COMP_MOCK, .ops = { - .new = mock_comp_new, + .create = mock_comp_new, .free = mock_comp_free, .params = mock_comp_params, .cmd = mock_comp_cmd, @@ -73,11 +78,6 @@ static struct comp_driver_info comp_mock_info = { void sys_comp_mock_init(void) { - comp_register(&comp_mock_info); + mock_comp_register(&comp_mock_info); } -int comp_verify_params(struct comp_dev *dev, uint32_t flag, - struct sof_ipc_stream_params *params) -{ - return 0; -} diff --git a/test/cmocka/src/audio/mixer/comp_mock.h b/test/cmocka/src/audio/mixer/comp_mock.h index 63e78e16009a..9a83c5a84c24 100644 --- a/test/cmocka/src/audio/mixer/comp_mock.h +++ b/test/cmocka/src/audio/mixer/comp_mock.h @@ -11,3 +11,4 @@ #define SOF_COMP_MOCK ((uint32_t)-1) void sys_comp_mock_init(void); +int mock_comp_register(struct comp_driver_info *info); diff --git a/test/cmocka/src/audio/mixer/mixer_test.c b/test/cmocka/src/audio/mixer/mixer_test.c index b5d20619e985..bf6a7ad6b48d 100644 --- a/test/cmocka/src/audio/mixer/mixer_test.c +++ b/test/cmocka/src/audio/mixer/mixer_test.c @@ -9,62 +9,34 @@ #include <math.h> #include <setjmp.h> #include <stdint.h> -#include <malloc.h> #include <cmocka.h> #include <sof/list.h> -#include <sof/drivers/ipc.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> #include <sof/audio/buffer.h> #include <sof/audio/component.h> #include <sof/audio/format.h> -#include <sof/audio/mixer.h> - -#include "comp_mock.h" - -#define MIX_TEST_SAMPLES 32 - -struct comp_driver drv_mock; +#include <sof/audio/module_adapter/module/generic.h> -struct comp_driver mixer_drv_mock; -struct comp_dev *mixer_dev_mock; +#include "mixer/mixer.h" +#include "../module_adapter.h" -struct comp_dev *post_mixer_comp; -struct comp_buffer *post_mixer_buf; - -/* Mocking comp_register here so we can register our components properly */ -int comp_register(struct comp_driver_info *info) -{ - void *dst; - int err; - switch (info->drv->type) { - case SOF_COMP_MIXER: - dst = &mixer_drv_mock; - err = memcpy_s(dst, sizeof(mixer_drv_mock), - info->drv, sizeof(struct comp_driver)); - break; - - case SOF_COMP_MOCK: - dst = &drv_mock; - err = memcpy_s(dst, sizeof(drv_mock), info->drv, - sizeof(struct comp_driver)); - break; - } - - if (err) - return -EINVAL; +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif - return 0; -} +#include "comp_mock.h" -struct source { - struct comp_dev *comp; - struct comp_buffer *buf; -}; +#define MIX_TEST_SAMPLES 32 struct mix_test_case { int num_sources; int num_chans; const char *name; - struct source *sources; }; #define TEST_CASE(_num_sources, _num_chans) \ @@ -74,7 +46,6 @@ struct mix_test_case { .name = ("test_audio_mixer_copy_" \ #_num_sources "_srcs_" \ #_num_chans "ch"), \ - .sources = NULL \ } static struct mix_test_case mix_test_cases[] = { @@ -90,208 +61,88 @@ static struct mix_test_case mix_test_cases[] = { TEST_CASE(8, 2) }; -static struct sof_ipc_comp mock_comp = { - .type = SOF_COMP_MOCK -}; - -static struct comp_dev *create_comp(struct sof_ipc_comp *comp, - struct comp_driver *drv) -{ - struct comp_dev *cd = drv->ops.new(drv, comp); - - assert_non_null(cd); - - memcpy_s(COMP_GET_IPC(cd, sof_ipc_comp), sizeof(struct sof_ipc_comp), - comp, sizeof(*comp)); - cd->drv = drv; - list_init(&cd->bsource_list); - list_init(&cd->bsink_list); - - return cd; -} - -static void destroy_comp(struct comp_driver *drv, struct comp_dev *dev) -{ - drv->ops.free(dev); -} - -static void init_buffer_pcm_params(struct comp_buffer *buf, int num_chans) -{ - buf->stream.channels = num_chans; - buf->stream.frame_fmt = SOF_IPC_FRAME_S32_LE; -} - -static void create_sources(struct mix_test_case *tc) -{ - int src_idx; - - tc->sources = malloc(tc->num_sources * sizeof(struct source)); - - for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) { - struct source *src = &tc->sources[src_idx]; - - struct sof_ipc_buffer buf = { - .size = (MIX_TEST_SAMPLES * sizeof(uint32_t)) * - tc->num_chans - }; - - src->comp = create_comp(&mock_comp, &drv_mock); - src->buf = buffer_new(&buf); - init_buffer_pcm_params(src->buf, tc->num_chans); - - src->buf->source = src->comp; - src->buf->sink = mixer_dev_mock; - - list_item_prepend(&src->buf->source_list, - &src->comp->bsink_list); - list_item_prepend(&src->buf->sink_list, - &mixer_dev_mock->bsource_list); - } -} - -static void destroy_sources(struct mix_test_case *tc) -{ - int src_idx; - - for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) - destroy_comp(&drv_mock, tc->sources[src_idx].comp); - - free(tc->sources); -} - -static void activate_periph_comps(struct mix_test_case *tc) -{ - int src_idx; - - for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) - tc->sources[src_idx].comp->state = COMP_STATE_ACTIVE; - - post_mixer_comp->state = COMP_STATE_ACTIVE; -} - -static int test_group_setup(void **state) -{ - sys_comp_mixer_init(); - sys_comp_mock_init(); - - return 0; -} - static int test_setup(void **state) { - static struct sof_ipc_comp_mixer mixer = { - .comp = { - .type = SOF_COMP_MIXER, - }, - .config = { - .hdr = { - .size = sizeof(struct sof_ipc_comp_config) - } - } - }; - - mixer_dev_mock = create_comp((struct sof_ipc_comp *)&mixer, - &mixer_drv_mock); - struct mix_test_case *tc = *((struct mix_test_case **)state); + struct processing_module_test_parameters test_parameters = { + tc->num_chans, 48, 1, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, NULL + }; + struct processing_module_test_data *test_data; + struct module_data *mod_data; + struct mixer_data *md; - if (tc) { - struct sof_ipc_buffer buf = { - .size = (MIX_TEST_SAMPLES * sizeof(uint32_t)) * - tc->num_chans - }; - - post_mixer_buf = buffer_new(&buf); - - create_sources(tc); - post_mixer_comp = create_comp(&mock_comp, &drv_mock); - - post_mixer_buf->source = mixer_dev_mock; - post_mixer_buf->sink = post_mixer_comp; - init_buffer_pcm_params(post_mixer_buf, tc->num_chans); - list_item_prepend(&post_mixer_buf->source_list, - &mixer_dev_mock->bsink_list); - list_item_prepend(&post_mixer_buf->sink_list, - &post_mixer_comp->bsource_list); + /* allocate and set new processing module, device and mixer data */ + test_data = test_malloc(sizeof(*test_data)); + test_data->parameters = test_parameters; + test_data->num_sources = tc->num_sources; + test_data->num_sinks = 1; + module_adapter_test_setup(test_data); - mixer_drv_mock.ops.prepare(mixer_dev_mock); + mod_data = &test_data->mod->priv; + md = test_malloc(sizeof(*md)); + mod_data->private = md; - mixer_dev_mock->state = COMP_STATE_ACTIVE; - activate_periph_comps(tc); + md->mix_func = mixer_get_processing_function(test_data->mod->dev, test_data->sinks[0]); - mixer_dev_mock->frames = MIX_TEST_SAMPLES; - } + *state = test_data; return 0; } static int test_teardown(void **state) { - destroy_comp(&mixer_drv_mock, mixer_dev_mock); + struct processing_module_test_data *test_data = *state; + struct mixer_data *md = module_get_private_data(test_data->mod); - struct mix_test_case *tc = *((struct mix_test_case **)state); - - if (tc) { - buffer_free(post_mixer_buf); - destroy_sources(tc); - } + test_free(md); + module_adapter_test_free(test_data); + test_free(test_data); return 0; } -/* - * Tests - */ - -static void test_audio_mixer_new(void **state) -{ - assert_non_null(mixer_dev_mock->private); -} - -static void test_audio_mixer_prepare_no_sources(void **state) -{ - int downstream = mixer_drv_mock.ops.prepare(mixer_dev_mock); - - assert_int_equal(downstream, 0); -} - static void test_audio_mixer_copy(void **state) { int src_idx; int smp; - struct mix_test_case *tc = *((struct mix_test_case **)state); + struct processing_module_test_data *tc = *state; + struct processing_module *mod = tc->mod; + struct mixer_data *md = module_get_private_data(tc->mod); + const struct audio_stream *sources_stream[PLATFORM_MAX_STREAMS]; for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) { - uint32_t *samples = tc->sources[src_idx].buf->stream.addr; + uint32_t *samples = tc->sources[src_idx]->stream.addr; - for (smp = 0; smp < MIX_TEST_SAMPLES; ++smp) { + for (smp = 0; smp < tc->sources[src_idx]->stream.size / sizeof(int32_t); ++smp) { double rad = M_PI / (180.0 / (smp * (src_idx + 1))); samples[smp] = ((sin(rad) + 1) / 2) * (0xFFFFFFFF / 2); } - tc->sources[src_idx].buf->stream.avail = - tc->sources[src_idx].buf->stream.size; + audio_stream_produce(&tc->sources[src_idx]->stream, + tc->sources[src_idx]->stream.size / sizeof(int32_t)); + + sources_stream[src_idx] = &tc->sources[src_idx]->stream; } - mixer_drv_mock.ops.copy(mixer_dev_mock); + md->mix_func(mod->dev, &tc->sinks[0]->stream, sources_stream, tc->num_sources, + mod->dev->frames); - for (smp = 0; smp < MIX_TEST_SAMPLES; ++smp) { + for (smp = 0; smp < tc->sinks[0]->stream.size / sizeof(int32_t); ++smp) { uint64_t sum = 0; for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) { - assert_non_null(tc->sources[src_idx].buf); + assert_non_null(tc->sources[src_idx]); - uint32_t *samples = - tc->sources[src_idx].buf->stream.addr; + uint32_t *samples = tc->sources[src_idx]->stream.addr; sum += samples[smp]; } sum = sat_int32(sum); - uint32_t *out_samples = post_mixer_buf->stream.addr; + uint32_t *out_samples = tc->sinks[0]->stream.addr; assert_int_equal(out_samples[smp], sum); } @@ -299,24 +150,12 @@ static void test_audio_mixer_copy(void **state) int main(void) { - struct CMUnitTest tests[ARRAY_SIZE(mix_test_cases) + 2]; + struct CMUnitTest tests[ARRAY_SIZE(mix_test_cases)]; int i; int cur_test_case = 0; - tests[0].test_func = test_audio_mixer_new; - tests[0].initial_state = NULL; - tests[0].setup_func = test_setup; - tests[0].teardown_func = test_teardown; - tests[0].name = "test_audio_mixer_new"; - - tests[1].test_func = test_audio_mixer_prepare_no_sources; - tests[1].initial_state = NULL; - tests[1].setup_func = test_setup; - tests[1].teardown_func = test_teardown; - tests[1].name = "test_audio_mixer_prepare_no_sources"; - - for (i = 2; i < ARRAY_SIZE(tests); (++i, ++cur_test_case)) { + for (i = 0; i < ARRAY_SIZE(tests); (++i, ++cur_test_case)) { tests[i].test_func = test_audio_mixer_copy; tests[i].initial_state = &mix_test_cases[cur_test_case]; tests[i].setup_func = test_setup; @@ -326,5 +165,5 @@ int main(void) cmocka_set_message_output(CM_OUTPUT_TAP); - return cmocka_run_group_tests(tests, test_group_setup, NULL); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/test/cmocka/src/audio/mixer/mock.c b/test/cmocka/src/audio/mixer/mock.c deleted file mode 100644 index 560cccc4d259..000000000000 --- a/test/cmocka/src/audio/mixer/mock.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <malloc.h> -#include <cmocka.h> - -#include <sof/lib/alloc.h> -#include <sof/audio/component.h> - -#include "comp_mock.h" - -#include <mock_trace.h> - -TRACE_IMPL() - -void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes) -{ -} - -int comp_set_state(struct comp_dev *dev, int cmd) -{ - return 0; -} diff --git a/test/cmocka/src/audio/module_adapter.h b/test/cmocka/src/audio/module_adapter.h new file mode 100644 index 000000000000..1f913fa5cbcd --- /dev/null +++ b/test/cmocka/src/audio/module_adapter.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// + +struct processing_module_test_parameters { + uint32_t channels; + uint32_t frames; + uint32_t buffer_size_ms; + uint32_t source_format; + uint32_t sink_format; + void (*verify)(struct processing_module *mod, struct comp_buffer *sink, + struct comp_buffer *source); +}; + +struct processing_module_test_data { + struct processing_module *mod; + struct comp_buffer **sinks; + struct comp_buffer **sources; + struct input_stream_buffer **input_buffers; + struct output_stream_buffer **output_buffers; + uint32_t num_sources; + uint32_t num_sinks; + struct processing_module_test_parameters parameters; + void (*verify)(struct processing_module *mod, struct comp_buffer *sink, + struct comp_buffer *source); +}; + +int module_adapter_test_setup(struct processing_module_test_data *test_data); +void module_adapter_test_free(struct processing_module_test_data *test_data); diff --git a/test/cmocka/src/audio/module_adapter_test.c b/test/cmocka/src/audio/module_adapter_test.c new file mode 100644 index 000000000000..81ec6cadc1b7 --- /dev/null +++ b/test/cmocka/src/audio/module_adapter_test.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// + +#include "../util.h" + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <stdint.h> +#include <cmocka.h> +#include <sof/audio/component.h> +#include <sof/audio/module_adapter/module/generic.h> +#include "module_adapter.h" + +int module_adapter_test_setup(struct processing_module_test_data *test_data) +{ + struct processing_module_test_parameters *parameters = &test_data->parameters; + struct processing_module *mod; + struct comp_dev *dev; + uint32_t size; + int i; + + /* allocate and set new device */ + mod = test_malloc(sizeof(struct processing_module)); + test_data->mod = mod; + dev = test_malloc(sizeof(struct comp_dev)); + dev->frames = parameters->frames; + mod->dev = dev; + dev->mod = mod; + + test_data->sinks = test_calloc(test_data->num_sinks, sizeof(struct comp_buffer *)); + test_data->sources = test_calloc(test_data->num_sources, sizeof(struct comp_buffer *)); + + test_data->input_buffers = test_calloc(test_data->num_sources, + sizeof(struct input_stream_buffer *)); + test_data->output_buffers = test_calloc(test_data->num_sinks, + sizeof(struct output_stream_buffer *)); + + list_init(&dev->bsource_list); + list_init(&dev->bsink_list); + + /* allocate sink buffers */ + size = parameters->frames * + get_frame_bytes(parameters->sink_format, parameters->channels) * + parameters->buffer_size_ms; + for (i = 0; i < test_data->num_sinks; i++) { + test_data->sinks[i] = create_test_sink(dev, 0, parameters->sink_format, + parameters->channels, size); + test_data->output_buffers[i] = test_malloc(sizeof(struct output_stream_buffer)); + test_data->output_buffers[i]->data = &test_data->sinks[i]->stream; + } + + /* allocate source buffers */ + size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->channels) * parameters->buffer_size_ms; + for (i = 0; i < test_data->num_sources; i++) { + test_data->sources[i] = create_test_source(dev, 0, parameters->source_format, + parameters->channels, size); + test_data->input_buffers[i] = test_malloc(sizeof(struct input_stream_buffer)); + test_data->input_buffers[i]->data = &test_data->sources[i]->stream; + } + + test_data->verify = parameters->verify; + + return 0; +} + +void module_adapter_test_free(struct processing_module_test_data *test_data) +{ + int i; + + for (i = 0; i < test_data->num_sinks; i++) { + free_test_sink(test_data->sinks[i]); + test_free(test_data->output_buffers[i]); + } + + for (i = 0; i < test_data->num_sources; i++) { + free_test_source(test_data->sources[i]); + test_free(test_data->input_buffers[i]); + } + + test_free(test_data->input_buffers); + test_free(test_data->output_buffers); + test_free(test_data->sinks); + test_free(test_data->sources); + test_free(test_data->mod->dev); + test_free(test_data->mod); +} diff --git a/test/cmocka/src/audio/mux/CMakeLists.txt b/test/cmocka/src/audio/mux/CMakeLists.txt index da4ad31605fa..a4a72613fd6b 100644 --- a/test/cmocka/src/audio/mux/CMakeLists.txt +++ b/test/cmocka/src/audio/mux/CMakeLists.txt @@ -10,8 +10,26 @@ add_library( audio_mux STATIC ${PROJECT_SOURCE_DIR}/src/audio/mux/mux.c + ${PROJECT_SOURCE_DIR}/src/audio/mux/mux_ipc3.c ${PROJECT_SOURCE_DIR}/src/audio/mux/mux_generic.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/lib/objpool.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter_ipc3.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module/generic.c ) sof_append_relative_path_definitions(audio_mux) @@ -22,42 +40,19 @@ link_libraries(audio_mux) cmocka_test( mux_get_processing_function mux_get_processing_function.c - mock.c ) cmocka_test( mux_copy mux_copy.c - mock.c ) cmocka_test( demux_copy demux_copy.c - mock.c ) -if(CONFIG_FORMAT_S16LE) -cmocka_test( - mux_generic_calc_sample_s16le - mux_generic_calc_sample_s16le.c - mock.c -) -endif() - -if(CONFIG_FORMAT_S24LE) -cmocka_test( - mux_generic_calc_sample_s24le - mux_generic_calc_sample_s24le.c - mock.c -) -endif() - - -if(CONFIG_FORMAT_S32LE) -cmocka_test( - mux_generic_calc_sample_s32le - mux_generic_calc_sample_s32le.c - mock.c -) -endif() +target_include_directories(audio_mux PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) +target_include_directories(mux_get_processing_function PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) +target_include_directories(mux_copy PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) +target_include_directories(demux_copy PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) diff --git a/test/cmocka/src/audio/mux/demux_copy.c b/test/cmocka/src/audio/mux/demux_copy.c index 6024eb9dc7cd..8e331446bbf4 100644 --- a/test/cmocka/src/audio/mux/demux_copy.c +++ b/test/cmocka/src/audio/mux/demux_copy.c @@ -5,11 +5,12 @@ // Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> // Janusz Jankowski <janusz.jankowski@linux.intel.com> -#include "util.h" +#include "../../util.h" +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/component_ext.h> #include <sof/audio/format.h> -#include <sof/audio/mux.h> +#include <mux/mux.h> #include <stdarg.h> #include <stddef.h> @@ -20,12 +21,14 @@ #include <cmocka.h> struct test_data { - uint32_t format; - uint8_t mask[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS]; - void *outputs[MUX_MAX_STREAMS]; struct comp_dev *dev; - struct comp_buffer *source; + struct processing_module *mod; + struct comp_data *cd; struct comp_buffer *sinks[MUX_MAX_STREAMS]; + struct comp_buffer *source; + void *outputs[MUX_MAX_STREAMS]; + uint32_t format; + uint8_t mask[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS]; }; static int16_t input_16b[PLATFORM_MAX_CHANNELS] = { @@ -33,6 +36,11 @@ static int16_t input_16b[PLATFORM_MAX_CHANNELS] = { 0x111, 0x112, 0x114, 0x118, }; +static int32_t input_24b[PLATFORM_MAX_CHANNELS] = { + 0x1a1001, 0x2a2002, 0x4a4004, 0x8a8008, + 0x1b1011, 0x2b2012, 0x4b4014, 0x8b8018, +}; + static int32_t input_32b[PLATFORM_MAX_CHANNELS] = { 0xd1a1001, 0xd2a2002, 0xd4a4004, 0xd8a8008, 0xe1b1011, 0xe2b2012, 0xe4b4014, 0xe8b8018, @@ -46,69 +54,63 @@ static uint16_t valid_formats[] = { static uint8_t masks[][MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { { { 0x01, }, }, + { { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, + { { }, + { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80}, }, { { 0x01, }, - { 0x01, }, - { 0x01, }, - { 0x01, }, }, - { { 0x00, 0x00, 0x00, 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10}, }, + { { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10}, { 0x00, 0x00, 0x01, }, { 0x00, 0x01, }, { 0x01, }, }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, - { 0x00, 0x00, 0x00, 0x00, 0x01, }, }, - { { 0x02, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, }, - { 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, }, - { 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x3f, }, - { 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xff, }, }, - { { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, - { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, }, - { { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, - { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, }, - { { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, - { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, }, - { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, }, + { 0x10, 0x08, 0x04, 0x02, 0x01, },}, + { { 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, },}, }; static int setup_group(void **state) { sys_comp_init(sof_get()); - sys_comp_mux_init(); - + sys_comp_module_demux_interface_init(); return 0; } static struct sof_ipc_comp_process *create_demux_comp_ipc(struct test_data *td) { + struct sof_ipc_comp_process *ipc; + struct sof_mux_config *mux; size_t ipc_size = sizeof(struct sof_ipc_comp_process); - size_t mux_size = sizeof(struct sof_mux_config) - + MUX_MAX_STREAMS * sizeof(struct mux_stream_data); - struct sof_ipc_comp_process *ipc = calloc(1, ipc_size + mux_size); - struct sof_mux_config *mux = (struct sof_mux_config *)&ipc->data; + size_t mux_size = sizeof(struct sof_mux_config) + + MUX_MAX_STREAMS * sizeof(struct mux_stream_data); + const struct sof_uuid uuid = SOF_REG_UUID(demux); int i, j; - ipc->comp.hdr.size = sizeof(struct sof_ipc_comp_process); - ipc->comp.type = SOF_COMP_DEMUX; + ipc = calloc(1, ipc_size + mux_size + SOF_UUID_SIZE); + memcpy_s(ipc + 1, SOF_UUID_SIZE, &uuid, SOF_UUID_SIZE); + mux = (struct sof_mux_config *)((char *)(ipc + 1) + SOF_UUID_SIZE); + ipc->comp.hdr.size = ipc_size + SOF_UUID_SIZE; + ipc->comp.type = SOF_COMP_MODULE_ADAPTER; ipc->config.hdr.size = sizeof(struct sof_ipc_comp_config); ipc->size = mux_size; + ipc->comp.ext_data_length = SOF_UUID_SIZE; - mux->frame_format = td->format; - mux->num_channels = PLATFORM_MAX_CHANNELS; mux->num_streams = MUX_MAX_STREAMS; - for (i = 0; i < MUX_MAX_STREAMS; ++i) { mux->streams[i].pipeline_id = i; - mux->streams[i].num_channels = PLATFORM_MAX_CHANNELS; for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) mux->streams[i].mask[j] = td->mask[i][j]; } @@ -119,55 +121,66 @@ static struct sof_ipc_comp_process *create_demux_comp_ipc(struct test_data *td) static void prepare_sinks(struct test_data *td, size_t sample_size) { int i; + uint16_t buffer_size = sample_size * PLATFORM_MAX_CHANNELS; for (i = 0; i < MUX_MAX_STREAMS; ++i) { - td->sinks[i] = create_test_sink(td->dev, - i, - td->format, - PLATFORM_MAX_CHANNELS); - td->sinks[i]->stream.free = sample_size * PLATFORM_MAX_CHANNELS; - td->outputs[i] = malloc(sample_size * PLATFORM_MAX_CHANNELS); - td->sinks[i]->stream.w_ptr = td->outputs[i]; + td->sinks[i] = create_test_sink(td->dev, i, td->format, PLATFORM_MAX_CHANNELS, + buffer_size); + + td->outputs[i] = td->sinks[i]->stream.addr; + assert_int_equal(audio_stream_get_free_bytes(&td->sinks[i]->stream), buffer_size); } } static void prepare_source(struct test_data *td, size_t sample_size) { - td->source = create_test_source(td->dev, - MUX_MAX_STREAMS + 1, - td->format, - PLATFORM_MAX_CHANNELS); - td->source->stream.avail = sample_size * PLATFORM_MAX_CHANNELS; + uint16_t buffer_size = sample_size * PLATFORM_MAX_CHANNELS; + + td->source = create_test_source(td->dev, MUX_MAX_STREAMS + 1, td->format, + PLATFORM_MAX_CHANNELS, buffer_size); if (td->format == SOF_IPC_FRAME_S16_LE) - td->source->stream.r_ptr = input_16b; + memcpy_s(td->source->stream.addr, buffer_size, input_16b, buffer_size); + else if (td->format == SOF_IPC_FRAME_S24_4LE) + memcpy_s(td->source->stream.addr, buffer_size, input_24b, buffer_size); else - td->source->stream.r_ptr = input_32b; + memcpy_s(td->source->stream.addr, buffer_size, input_32b, buffer_size); + + audio_stream_produce(&td->source->stream, buffer_size); + assert_int_equal(audio_stream_get_avail_bytes(&td->source->stream), buffer_size); } static int setup_test_case(void **state) { struct test_data *td = *((struct test_data **)state); - struct sof_ipc_comp_process *ipc = create_demux_comp_ipc(td); - size_t sample_size = td->format == SOF_IPC_FRAME_S16_LE ? - sizeof(int16_t) : sizeof(int32_t); - int ret = 0; + struct comp_dev *dev; + struct processing_module *mod; + struct sof_ipc_comp_process *ipc; + size_t sample_size = td->format == SOF_IPC_FRAME_S16_LE ? sizeof(int16_t) : sizeof(int32_t); + struct pipeline *dummy_pipe; - td->dev = comp_new((struct sof_ipc_comp *)ipc); + ipc = create_demux_comp_ipc(td); + dev = comp_new((struct sof_ipc_comp *)ipc); free(ipc); - - if (!td->dev) + if (!dev) return -EINVAL; - prepare_sinks(td, sample_size); + /* Add dummy pipeline to bypass comp_check_eos() */ + dummy_pipe = test_malloc(sizeof(*dummy_pipe)); + if (!dummy_pipe) + return -ENOMEM; + dummy_pipe->expect_eos = false; + dev->pipeline = dummy_pipe; - prepare_source(td, sample_size); + mod = comp_mod(dev); + td->dev = dev; + td->mod = mod; + td->cd = module_get_private_data(mod); - ret = comp_prepare(td->dev); - if (ret) - return ret; + prepare_sinks(td, sample_size); + prepare_source(td, sample_size); - return 0; + return comp_prepare(td->dev); } static int teardown_test_case(void **state) @@ -175,13 +188,16 @@ static int teardown_test_case(void **state) struct test_data *td = *((struct test_data **)state); int i; + rfree(td->mod->input_buffers); + rfree(td->mod->output_buffers); + free_test_source(td->source); - for (i = 0; i < MUX_MAX_STREAMS; ++i) { - free(td->outputs[i]); + for (i = 0; i < MUX_MAX_STREAMS; ++i) free_test_sink(td->sinks[i]); - } + test_free(td->dev->pipeline); + td->dev->pipeline = NULL; comp_free(td->dev); return 0; @@ -201,9 +217,9 @@ static void test_demux_copy_proc_16(void **state) for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) if (td->mask[i][j] & BIT(k)) - sample += input_16b[k]; + sample = input_16b[k]; - expected_results[i][j] = sat_int16(sample); + expected_results[i][j] = sample; } } @@ -222,13 +238,13 @@ static void test_demux_copy_proc_24(void **state) for (i = 0; i < MUX_MAX_STREAMS; ++i) { for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) { - int64_t sample = 0; + int32_t sample = 0; for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) if (td->mask[i][j] & BIT(k)) - sample += sign_extend_s24(input_32b[k]); + sample = input_24b[k]; - expected_results[i][j] = sat_int24(sample); + expected_results[i][j] = sample; } } @@ -247,13 +263,13 @@ static void test_demux_copy_proc_32(void **state) for (i = 0; i < MUX_MAX_STREAMS; ++i) { for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) { - int64_t sample = 0; + int32_t sample = 0; for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) if (td->mask[i][j] & BIT(k)) - sample += input_32b[k]; + sample = input_32b[k]; - expected_results[i][j] = sat_int32(sample); + expected_results[i][j] = sample; } } @@ -276,13 +292,14 @@ static char *get_test_name(int mask_index, const char *format_name) int main(void) { - int i, j; struct CMUnitTest tests[ARRAY_SIZE(valid_formats) * ARRAY_SIZE(masks)]; + struct test_data *td; + int i, j, ti, ret; for (i = 0; i < ARRAY_SIZE(valid_formats); ++i) { for (j = 0; j < ARRAY_SIZE(masks); ++j) { - int ti = i * ARRAY_SIZE(masks) + j; - struct test_data *td = malloc(sizeof(struct test_data)); + ti = i * ARRAY_SIZE(masks) + j; + td = malloc(sizeof(struct test_data)); td->format = valid_formats[i]; @@ -308,6 +325,10 @@ int main(void) tests[ti].test_func = test_demux_copy_proc_32; break; #endif /* CONFIG_FORMAT_S32LE */ +#if CONFIG_FORMAT_S24_3LE + case SOF_IPC_FRAME_S24_3LE: + break; +#endif /* CONFIG_FORMAT_S24_3LE */ default: return -EINVAL; } @@ -319,6 +340,12 @@ int main(void) } cmocka_set_message_output(CM_OUTPUT_TAP); + ret = cmocka_run_group_tests(tests, setup_group, NULL); + + for (ti = 0; ti < ARRAY_SIZE(valid_formats) * ARRAY_SIZE(masks); ti++) { + free(tests[ti].initial_state); + free((void *)tests[ti].name); + } - return cmocka_run_group_tests(tests, setup_group, NULL); + return ret; } diff --git a/test/cmocka/src/audio/mux/mock.c b/test/cmocka/src/audio/mux/mock.c deleted file mode 100644 index fde71d551190..000000000000 --- a/test/cmocka/src/audio/mux/mock.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> - -#include <mock_trace.h> - -#include <sof/audio/component.h> -#include <sof/lib/alloc.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <stdlib.h> -#include <cmocka.h> - -TRACE_IMPL() - -static struct sof sof; - -void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes) -{ -} - -void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes) -{ -} - -void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes) -{ -} - -struct sof *sof_get(void) -{ - return &sof; -} - -struct schedulers **arch_schedulers_get(void) -{ - return NULL; -} - -#if CONFIG_SMP - -int idc_send_msg(struct idc_msg *msg, uint32_t mode) -{ - (void)msg; - (void)mode; - - return 0; -} - -#endif diff --git a/test/cmocka/src/audio/mux/mux_copy.c b/test/cmocka/src/audio/mux/mux_copy.c index f56b6e481058..66b21b0df27c 100644 --- a/test/cmocka/src/audio/mux/mux_copy.c +++ b/test/cmocka/src/audio/mux/mux_copy.c @@ -5,11 +5,12 @@ // Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> // Janusz Jankowski <janusz.jankowski@linux.intel.com> -#include "util.h" +#include "../../util.h" +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/component_ext.h> #include <sof/audio/format.h> -#include <sof/audio/mux.h> +#include <mux/mux.h> #include <stdarg.h> #include <stddef.h> @@ -20,12 +21,14 @@ #include <cmocka.h> struct test_data { - uint32_t format; - uint8_t mask[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS]; - void *output; struct comp_dev *dev; + struct processing_module *mod; + struct comp_data *cd; struct comp_buffer *sources[MUX_MAX_STREAMS]; struct comp_buffer *sink; + void *output; + uint32_t format; + uint8_t mask[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS]; }; static int16_t input_16b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { @@ -39,6 +42,17 @@ static int16_t input_16b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { 0x411, 0x412, 0x414, 0x418, }, }; +static int32_t input_24b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { + { 0x1a1001, 0x2a2002, 0x4a4004, 0x8a8008, + 0x1b1011, 0x2b2012, 0x4b4014, 0x8b8018, }, + { 0x1a1101, 0x2a2102, 0x4a4104, 0x8a8108, + 0x1b1111, 0x2b2112, 0x4b4114, 0x8b8118, }, + { 0x1a1201, 0x2a2202, 0x4a4204, 0x8a8208, + 0x1b1211, 0x2b2212, 0x4b4214, 0x8b8218, }, + { 0x1a1401, 0x2a2402, 0x4a4404, 0x8a8408, + 0x1b1411, 0x2b2412, 0x4b4414, 0x8b8418, }, +}; + static int32_t input_32b[MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { { 0xd1a1001, 0xd2a2002, 0xd4a4004, 0xd8a8008, 0xe1b1011, 0xe2b2012, 0xe4b4014, 0xe8b8018, }, @@ -58,69 +72,63 @@ static uint16_t valid_formats[] = { static uint8_t masks[][MUX_MAX_STREAMS][PLATFORM_MAX_CHANNELS] = { { { 0x01, }, }, + { { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80 }, }, + { { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80 }, }, + { { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80 }, }, + { { }, + { }, + { }, + { 0x01, 0x02, 0x04, 0x10, 0x20, 0x40, 0x80 }, }, { { 0x01, }, - { 0x01, }, - { 0x01, }, - { 0x01, }, }, - { { 0x00, 0x00, 0x00, 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10 }, }, + { { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10 }, { 0x00, 0x00, 0x01, }, { 0x00, 0x01, }, { 0x01, }, }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, - { 0x00, 0x00, 0x00, 0x00, 0x01, }, }, - { { 0x02, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, }, - { 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, }, - { 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x3f, }, - { 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xff, }, }, - { { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, - { 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, }, - { 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, }, }, - { { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, - { 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, 0x00, }, - { 0x00, 0xf0, 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x0f, }, }, - { { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, - { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, }, - { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, }, - { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, }, + { 0x10, 0x08, 0x04, 0x02, 0x01, }, }, + { { 0x01, }, + { 0x00, 0x01, }, + { 0x00, 0x00, 0x01, }, + { 0x00, 0x00, 0x00, 0x01, }, }, }; static int setup_group(void **state) { sys_comp_init(sof_get()); - sys_comp_mux_init(); - + sys_comp_module_mux_interface_init(); return 0; } static struct sof_ipc_comp_process *create_mux_comp_ipc(struct test_data *td) { + struct sof_ipc_comp_process *ipc; + struct sof_mux_config *mux; size_t ipc_size = sizeof(struct sof_ipc_comp_process); - size_t mux_size = sizeof(struct sof_mux_config) - + MUX_MAX_STREAMS * sizeof(struct mux_stream_data); - struct sof_ipc_comp_process *ipc = calloc(1, ipc_size + mux_size); - struct sof_mux_config *mux = (struct sof_mux_config *)&ipc->data; + size_t mux_size = sizeof(struct sof_mux_config) + + MUX_MAX_STREAMS * sizeof(struct mux_stream_data); + const struct sof_uuid uuid = SOF_REG_UUID(mux); int i, j; - ipc->comp.hdr.size = sizeof(struct sof_ipc_comp_process); - ipc->comp.type = SOF_COMP_MUX; + ipc = calloc(1, ipc_size + mux_size + SOF_UUID_SIZE); + memcpy_s(ipc + 1, SOF_UUID_SIZE, &uuid, SOF_UUID_SIZE); + mux = (struct sof_mux_config *)((char *)(ipc + 1) + SOF_UUID_SIZE); + ipc->comp.hdr.size = ipc_size + SOF_UUID_SIZE; + ipc->comp.type = SOF_COMP_MODULE_ADAPTER; ipc->config.hdr.size = sizeof(struct sof_ipc_comp_config); ipc->size = mux_size; + ipc->comp.ext_data_length = SOF_UUID_SIZE; - mux->frame_format = td->format; - mux->num_channels = PLATFORM_MAX_CHANNELS; mux->num_streams = MUX_MAX_STREAMS; - for (i = 0; i < MUX_MAX_STREAMS; ++i) { mux->streams[i].pipeline_id = i; - mux->streams[i].num_channels = PLATFORM_MAX_CHANNELS; for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) mux->streams[i].mask[j] = td->mask[i][j]; } @@ -130,57 +138,72 @@ static struct sof_ipc_comp_process *create_mux_comp_ipc(struct test_data *td) static void prepare_sink(struct test_data *td, size_t sample_size) { - td->sink = create_test_sink(td->dev, - MUX_MAX_STREAMS + 1, - td->format, - PLATFORM_MAX_CHANNELS); - td->sink->stream.free = sample_size * PLATFORM_MAX_CHANNELS; - td->output = malloc(sample_size * PLATFORM_MAX_CHANNELS); - td->sink->stream.w_ptr = td->output; + uint16_t buffer_size = sample_size * PLATFORM_MAX_CHANNELS; + + td->sink = create_test_sink(td->dev, MUX_MAX_STREAMS + 1, td->format, PLATFORM_MAX_CHANNELS, + buffer_size); + td->output = td->sink->stream.addr; + + assert_int_equal(audio_stream_get_free_bytes(&td->sink->stream), buffer_size); } static void prepare_sources(struct test_data *td, size_t sample_size) { int i; + uint16_t buffer_size = sample_size * PLATFORM_MAX_CHANNELS; for (i = 0; i < MUX_MAX_STREAMS; ++i) { - td->sources[i] = create_test_source(td->dev, - i, - td->format, - PLATFORM_MAX_CHANNELS); - td->sources[i]->stream.avail = sample_size * - PLATFORM_MAX_CHANNELS; + td->sources[i] = create_test_source(td->dev, i, td->format, PLATFORM_MAX_CHANNELS, + buffer_size); if (td->format == SOF_IPC_FRAME_S16_LE) - td->sources[i]->stream.r_ptr = input_16b[i]; + memcpy_s(td->sources[i]->stream.addr, buffer_size, &input_16b[i], + buffer_size); + else if (td->format == SOF_IPC_FRAME_S24_4LE) + memcpy_s(td->sources[i]->stream.addr, buffer_size, &input_24b[i], + buffer_size); else - td->sources[i]->stream.r_ptr = input_32b[i]; + memcpy_s(td->sources[i]->stream.addr, buffer_size, &input_32b[i], + buffer_size); + + audio_stream_produce(&td->sources[i]->stream, buffer_size); + assert_int_equal(audio_stream_get_avail_bytes(&td->sources[i]->stream), + buffer_size); } } static int setup_test_case(void **state) { struct test_data *td = *((struct test_data **)state); - struct sof_ipc_comp_process *ipc = create_mux_comp_ipc(td); - size_t sample_size = td->format == SOF_IPC_FRAME_S16_LE ? - sizeof(int16_t) : sizeof(int32_t); - int ret = 0; + struct comp_dev *dev; + struct processing_module *mod; + struct sof_ipc_comp_process *ipc; + size_t sample_size = td->format == SOF_IPC_FRAME_S16_LE ? sizeof(int16_t) : sizeof(int32_t); + struct pipeline *dummy_pipe; - td->dev = comp_new((struct sof_ipc_comp *)ipc); + ipc = create_mux_comp_ipc(td); + dev = comp_new((struct sof_ipc_comp *)ipc); free(ipc); - - if (!td->dev) + if (!dev) return -EINVAL; - prepare_sink(td, sample_size); + /* Add dummy pipeline to bypass comp_check_eos() */ + dummy_pipe = test_malloc(sizeof(*dummy_pipe)); + if (!dummy_pipe) + return -ENOMEM; + dummy_pipe->expect_eos = false; + dev->pipeline = dummy_pipe; + mod = comp_mod(dev); + td->dev = dev; + td->mod = mod; + td->cd = module_get_private_data(mod); + + prepare_sink(td, sample_size); prepare_sources(td, sample_size); - ret = comp_prepare(td->dev); - if (ret) - return ret; + return comp_prepare(td->dev); - return 0; } static int teardown_test_case(void **state) @@ -188,14 +211,16 @@ static int teardown_test_case(void **state) struct test_data *td = *((struct test_data **)state); int i; + rfree(td->mod->input_buffers); + rfree(td->mod->output_buffers); + for (i = 0; i < MUX_MAX_STREAMS; ++i) free_test_source(td->sources[i]); - free(td->output); free_test_sink(td->sink); - + test_free(td->dev->pipeline); + td->dev->pipeline = NULL; comp_free(td->dev); - return 0; } @@ -212,11 +237,11 @@ static void test_mux_copy_proc_16(void **state) for (j = 0; j < MUX_MAX_STREAMS; ++j) { for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) { - if (td->mask[j][i] & BIT(k)) - sample += input_16b[j][k]; + if (td->mask[j][k] & BIT(i)) + sample = input_16b[j][k]; } } - expected_result[i] = sat_int16(sample); + expected_result[i] = sample; } assert_memory_equal(td->output, expected_result, @@ -228,22 +253,19 @@ static void test_mux_copy_proc_24(void **state) struct test_data *td = *((struct test_data **)state); int32_t expected_result[PLATFORM_MAX_CHANNELS]; int i, j, k; - int32_t val; assert_int_equal(comp_copy(td->dev), 0); for (i = 0; i < PLATFORM_MAX_CHANNELS; ++i) { - int64_t sample = 0; + int32_t sample = 0; for (j = 0; j < MUX_MAX_STREAMS; ++j) { for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) { - if (td->mask[j][i] & BIT(k)) { - val = input_32b[j][k]; - sample += sign_extend_s24(val); - } + if (td->mask[j][k] & BIT(i)) + sample = input_24b[j][k]; } } - expected_result[i] = sat_int24(sample); + expected_result[i] = sample; } assert_memory_equal(td->output, expected_result, @@ -259,15 +281,15 @@ static void test_mux_copy_proc_32(void **state) assert_int_equal(comp_copy(td->dev), 0); for (i = 0; i < PLATFORM_MAX_CHANNELS; ++i) { - int64_t sample = 0; + int32_t sample = 0; for (j = 0; j < MUX_MAX_STREAMS; ++j) { for (k = 0; k < PLATFORM_MAX_CHANNELS; ++k) { - if (td->mask[j][i] & BIT(k)) - sample += input_32b[j][k]; + if (td->mask[j][k] & BIT(i)) + sample = input_32b[j][k]; } } - expected_result[i] = sat_int32(sample); + expected_result[i] = sample; } assert_memory_equal(td->output, expected_result, @@ -288,13 +310,14 @@ static char *get_test_name(int mask_index, const char *format_name) int main(void) { - int i, j; + struct test_data *td; struct CMUnitTest tests[ARRAY_SIZE(valid_formats) * ARRAY_SIZE(masks)]; + int i, j, ti, ret; for (i = 0; i < ARRAY_SIZE(valid_formats); ++i) { for (j = 0; j < ARRAY_SIZE(masks); ++j) { - int ti = i * ARRAY_SIZE(masks) + j; - struct test_data *td = malloc(sizeof(struct test_data)); + ti = i * ARRAY_SIZE(masks) + j; + td = malloc(sizeof(struct test_data)); td->format = valid_formats[i]; @@ -320,6 +343,10 @@ int main(void) tests[ti].test_func = test_mux_copy_proc_32; break; #endif /* CONFIG_FORMAT_S32LE */ +#if CONFIG_FORMAT_S24_3LE + case SOF_IPC_FRAME_S24_3LE: + break; +#endif /* CONFIG_FORMAT_S24_3LE */ default: return -EINVAL; } @@ -331,6 +358,12 @@ int main(void) } cmocka_set_message_output(CM_OUTPUT_TAP); + ret = cmocka_run_group_tests(tests, setup_group, NULL); + + for (ti = 0; ti < ARRAY_SIZE(valid_formats) * ARRAY_SIZE(masks); ti++) { + free(tests[ti].initial_state); + free((void *)tests[ti].name); + } - return cmocka_run_group_tests(tests, setup_group, NULL); + return ret; } diff --git a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s16le.c b/test/cmocka/src/audio/mux/mux_generic_calc_sample_s16le.c deleted file mode 100644 index 0c857767787c..000000000000 --- a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s16le.c +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/audio/mux.h> - -#include <stdarg.h> -#include <stddef.h> -#include <stdint.h> -#include <setjmp.h> -#include <stdlib.h> -#include <cmocka.h> - -struct test_data { - const char *name; - uint32_t channels; - uint8_t mask; - int16_t *input; - struct comp_buffer *buffer; - int32_t expected_result; -}; - -static int16_t input_samples[][PLATFORM_MAX_CHANNELS] = { - { 0x1, 0x2, 0x4, 0x8, - 0x10, 0x20, 0x40, 0x80, }, - { 0x100, 0x200, 0x400, 0x800, - 0x1000, 0x2000, 0x4000, 0x8000, }, - { 0x8000, 0xf000, 0x8000, 0xf000, - 0xf000, 0x8000, 0xf000, 0x8000, }, -}; - -#define TEST_CASE(channels, mask, input_index) \ - { ("test_calc_sample_s16le_ch_" #channels "_mask_" #mask \ - "_input_" #input_index), channels, mask, \ - input_samples[input_index], NULL, 0 } - -static struct test_data test_cases[] = { - TEST_CASE(1, 0x0, 0), - TEST_CASE(1, 0x0, 1), - TEST_CASE(1, 0x0, 2), - TEST_CASE(1, 0x1, 0), - TEST_CASE(1, 0x1, 1), - TEST_CASE(1, 0x1, 2), - TEST_CASE(2, 0x0, 0), - TEST_CASE(2, 0x0, 1), - TEST_CASE(2, 0x0, 2), - TEST_CASE(2, 0x1, 0), - TEST_CASE(2, 0x1, 2), - TEST_CASE(2, 0x2, 0), - TEST_CASE(2, 0x2, 2), - TEST_CASE(2, 0x3, 0), - TEST_CASE(2, 0x3, 2), - TEST_CASE(3, 0x1, 1), - TEST_CASE(3, 0x7, 1), - TEST_CASE(5, 0x4, 1), - TEST_CASE(5, 0x12, 1), - TEST_CASE(7, 0x10, 1), - TEST_CASE(7, 0x11, 1), - TEST_CASE(8, 0x0f, 1), - TEST_CASE(8, 0x0f, 2), - TEST_CASE(8, 0x10, 0), - TEST_CASE(8, 0x11, 0), - TEST_CASE(8, 0xf0, 1), - TEST_CASE(8, 0xf0, 2), - TEST_CASE(8, 0xff, 1), - TEST_CASE(8, 0xff, 2), -}; - -static void test_calc_sample(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - int32_t ret = calc_sample_s16le(&td->buffer->stream, - td->channels, - 0, - td->mask); - - assert_int_equal(ret, td->expected_result); -} - -static int setup(void **state) -{ - struct test_data *td = *((struct test_data **)state); - int ch; - - td->buffer = calloc(1, sizeof(struct comp_buffer)); - td->buffer->stream.r_ptr = td->input; - - td->expected_result = 0; - - for (ch = 0; ch < td->channels; ++ch) { - if (td->mask & BIT(ch)) - td->expected_result += td->input[ch]; - } - - return 0; -} - -static int teardown(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - free(td->buffer); - - return 0; -} - -int main(void) -{ - int i; - struct CMUnitTest tests[ARRAY_SIZE(test_cases)]; - - for (i = 0; i < ARRAY_SIZE(test_cases); ++i) { - tests[i].name = test_cases[i].name; - tests[i].test_func = test_calc_sample; - tests[i].initial_state = &test_cases[i]; - tests[i].setup_func = setup; - tests[i].teardown_func = teardown; - } - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s24le.c b/test/cmocka/src/audio/mux/mux_generic_calc_sample_s24le.c deleted file mode 100644 index 6a506d13472b..000000000000 --- a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s24le.c +++ /dev/null @@ -1,131 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/audio/mux.h> - -#include <stdarg.h> -#include <stddef.h> -#include <stdint.h> -#include <setjmp.h> -#include <stdlib.h> -#include <cmocka.h> - -struct test_data { - const char *name; - uint32_t channels; - uint8_t mask; - int32_t *input; - struct comp_buffer *buffer; - int32_t expected_result; -}; - -static int32_t input_samples[][PLATFORM_MAX_CHANNELS] = { - { 0x1, 0x2, 0x4, 0x8, - 0x10, 0x20, 0x40, 0x80, }, - { 0x10000, 0x20000, 0x40000, 0x80000, - 0x100000, 0x200000, 0x400000, 0x800000, }, - { 0x1000000, 0x2000000, 0x4000000, 0x8000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, }, - { 0x80000000, 0xf0000000, 0x80000000, 0xf0000000, - 0xf0000000, 0x80000000, 0xf0000000, 0x80000000, }, -}; - -#define TEST_CASE(channels, mask, input_index) \ - { ("test_calc_sample_s24le_ch_" #channels "_mask_" #mask \ - "_input_" #input_index), channels, mask, \ - input_samples[input_index], NULL, 0 } - -static struct test_data test_cases[] = { - TEST_CASE(1, 0x0, 0), - TEST_CASE(1, 0x0, 1), - TEST_CASE(1, 0x0, 2), - TEST_CASE(1, 0x1, 0), - TEST_CASE(1, 0x1, 1), - TEST_CASE(1, 0x1, 2), - TEST_CASE(2, 0x0, 0), - TEST_CASE(2, 0x0, 1), - TEST_CASE(2, 0x0, 2), - TEST_CASE(2, 0x1, 0), - TEST_CASE(2, 0x1, 2), - TEST_CASE(2, 0x2, 0), - TEST_CASE(2, 0x2, 2), - TEST_CASE(2, 0x3, 0), - TEST_CASE(2, 0x3, 2), - TEST_CASE(3, 0x1, 1), - TEST_CASE(3, 0x7, 1), - TEST_CASE(5, 0x4, 1), - TEST_CASE(5, 0x12, 1), - TEST_CASE(7, 0x10, 2), - TEST_CASE(7, 0x11, 2), - TEST_CASE(8, 0x0f, 1), - TEST_CASE(8, 0x0f, 3), - TEST_CASE(8, 0x10, 0), - TEST_CASE(8, 0x11, 0), - TEST_CASE(8, 0xf0, 2), - TEST_CASE(8, 0xf0, 3), - TEST_CASE(8, 0xff, 2), - TEST_CASE(8, 0xff, 3), -}; - -static void test_calc_sample(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - int32_t ret = calc_sample_s24le(&td->buffer->stream, - td->channels, - 0, - td->mask); - - assert_int_equal(ret, td->expected_result); -} - -static int setup(void **state) -{ - struct test_data *td = *((struct test_data **)state); - int ch; - - td->buffer = calloc(1, sizeof(struct comp_buffer)); - td->buffer->stream.r_ptr = td->input; - - td->expected_result = 0; - - for (ch = 0; ch < td->channels; ++ch) { - /* 8 MSB should be ignored */ - if (td->mask & BIT(ch)) - td->expected_result += (td->input[ch] & 0x00ffffff); - } - - return 0; -} - -static int teardown(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - free(td->buffer); - - return 0; -} - -int main(void) -{ - int i; - struct CMUnitTest tests[ARRAY_SIZE(test_cases)]; - - for (i = 0; i < ARRAY_SIZE(test_cases); ++i) { - tests[i].name = test_cases[i].name; - tests[i].test_func = test_calc_sample; - tests[i].initial_state = &test_cases[i]; - tests[i].setup_func = setup; - tests[i].teardown_func = teardown; - } - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s32le.c b/test/cmocka/src/audio/mux/mux_generic_calc_sample_s32le.c deleted file mode 100644 index 9c4879aa5dc2..000000000000 --- a/test/cmocka/src/audio/mux/mux_generic_calc_sample_s32le.c +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/audio/mux.h> - -#include <stdarg.h> -#include <stddef.h> -#include <stdint.h> -#include <setjmp.h> -#include <stdlib.h> -#include <cmocka.h> - -struct test_data { - const char *name; - uint32_t channels; - uint8_t mask; - int32_t *input; - struct comp_buffer *buffer; - int64_t expected_result; -}; - -static int32_t input_samples[][PLATFORM_MAX_CHANNELS] = { - { 0x1, 0x2, 0x4, 0x8, - 0x10, 0x20, 0x40, 0x80, }, - { 0x10000, 0x20000, 0x40000, 0x80000, - 0x100000, 0x200000, 0x400000, 0x800000, }, - { 0x1000000, 0x2000000, 0x4000000, 0x8000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, }, - { 0x80000000, 0xf0000000, 0x80000000, 0xf0000000, - 0xf0000000, 0x80000000, 0xf0000000, 0x80000000, }, -}; - -#define TEST_CASE(channels, mask, input_index) \ - { ("test_calc_sample_s32le_ch_" #channels "_mask_" #mask \ - "_input_" #input_index), channels, mask, \ - input_samples[input_index], NULL, 0 } - -static struct test_data test_cases[] = { - TEST_CASE(1, 0x0, 0), - TEST_CASE(1, 0x0, 1), - TEST_CASE(1, 0x0, 2), - TEST_CASE(1, 0x1, 0), - TEST_CASE(1, 0x1, 1), - TEST_CASE(1, 0x1, 2), - TEST_CASE(2, 0x0, 0), - TEST_CASE(2, 0x0, 1), - TEST_CASE(2, 0x0, 2), - TEST_CASE(2, 0x1, 0), - TEST_CASE(2, 0x1, 2), - TEST_CASE(2, 0x2, 0), - TEST_CASE(2, 0x2, 2), - TEST_CASE(2, 0x3, 0), - TEST_CASE(2, 0x3, 2), - TEST_CASE(3, 0x1, 1), - TEST_CASE(3, 0x7, 1), - TEST_CASE(5, 0x4, 1), - TEST_CASE(5, 0x12, 1), - TEST_CASE(7, 0x10, 2), - TEST_CASE(7, 0x11, 2), - TEST_CASE(8, 0x0f, 1), - TEST_CASE(8, 0x0f, 3), - TEST_CASE(8, 0x10, 0), - TEST_CASE(8, 0x11, 0), - TEST_CASE(8, 0xf0, 2), - TEST_CASE(8, 0xf0, 3), - TEST_CASE(8, 0xff, 2), - TEST_CASE(8, 0xff, 3), -}; - -static void test_calc_sample(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - int64_t ret = calc_sample_s32le(&td->buffer->stream, - td->channels, - 0, - td->mask); - - assert_int_equal(ret, td->expected_result); -} - -static int setup(void **state) -{ - struct test_data *td = *((struct test_data **)state); - int ch; - - td->buffer = calloc(1, sizeof(struct comp_buffer)); - td->buffer->stream.r_ptr = td->input; - - td->expected_result = 0; - - for (ch = 0; ch < td->channels; ++ch) { - if (td->mask & BIT(ch)) - td->expected_result += td->input[ch]; - } - - return 0; -} - -static int teardown(void **state) -{ - struct test_data *td = *((struct test_data **)state); - - free(td->buffer); - - return 0; -} - -int main(void) -{ - int i; - struct CMUnitTest tests[ARRAY_SIZE(test_cases)]; - - for (i = 0; i < ARRAY_SIZE(test_cases); ++i) { - tests[i].name = test_cases[i].name; - tests[i].test_func = test_calc_sample; - tests[i].initial_state = &test_cases[i]; - tests[i].setup_func = setup; - tests[i].teardown_func = teardown; - } - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/audio/mux/mux_get_processing_function.c b/test/cmocka/src/audio/mux/mux_get_processing_function.c index ba8aefb9f236..0e4f22ff7021 100644 --- a/test/cmocka/src/audio/mux/mux_get_processing_function.c +++ b/test/cmocka/src/audio/mux/mux_get_processing_function.c @@ -5,8 +5,11 @@ // Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> // Janusz Jankowski <janusz.jankowski@linux.intel.com> +#include "../../util.h" + +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/component_ext.h> -#include <sof/audio/mux.h> +#include <mux/mux.h> #include <stdarg.h> #include <stddef.h> @@ -17,42 +20,73 @@ struct test_data { struct comp_dev *dev; + struct processing_module *mod; struct comp_data *cd; + struct comp_buffer *sink; }; static int setup_group(void **state) { sys_comp_init(sof_get()); - sys_comp_mux_init(); + sys_comp_module_mux_interface_init(); return 0; } +static struct sof_ipc_comp_process *create_mux_comp_ipc(struct test_data *td) +{ + struct sof_ipc_comp_process *ipc; + struct sof_mux_config *mux; + size_t ipc_size = sizeof(struct sof_ipc_comp_process); + size_t mux_size = sizeof(struct sof_mux_config) + + MUX_MAX_STREAMS * sizeof(struct mux_stream_data); + const struct sof_uuid uuid = SOF_REG_UUID(mux); + int i, j; + + ipc = calloc(1, ipc_size + mux_size + SOF_UUID_SIZE); + memcpy_s(ipc + 1, SOF_UUID_SIZE, &uuid, SOF_UUID_SIZE); + mux = (struct sof_mux_config *)((char *)(ipc + 1) + SOF_UUID_SIZE); + ipc->comp.hdr.size = ipc_size + SOF_UUID_SIZE; + ipc->comp.type = SOF_COMP_MODULE_ADAPTER; + ipc->config.hdr.size = sizeof(struct sof_ipc_comp_config); + ipc->size = mux_size; + ipc->comp.ext_data_length = SOF_UUID_SIZE; + + mux->num_streams = MUX_MAX_STREAMS; + for (i = 0; i < MUX_MAX_STREAMS; ++i) { + mux->streams[i].pipeline_id = i; + for (j = 0; j < PLATFORM_MAX_CHANNELS; ++j) + mux->streams[i].mask[j] = 0; + } + + return ipc; +} + + static int setup_test_case(void **state) { - struct test_data *td = malloc(sizeof(struct test_data)); - struct sof_ipc_comp_process ipc = { - .comp = { - .hdr = { - .size = sizeof(struct sof_ipc_comp_process) - }, - .type = SOF_COMP_MUX - }, - .config = { - .hdr = { - .size = sizeof(struct sof_ipc_comp_config) - } - } - }; + struct test_data *td; + struct comp_dev *dev; + struct processing_module *mod; + struct sof_ipc_comp_process *ipc; - td->dev = comp_new((struct sof_ipc_comp *)&ipc); - if (!td->dev) + td = test_malloc(sizeof(*td)); + if (!td) + return -ENOMEM; + + ipc = create_mux_comp_ipc(td); + dev = comp_new((struct sof_ipc_comp *)ipc); + free(ipc); + if (!dev) return -EINVAL; - td->cd = (struct comp_data *)td->dev->private; + mod = comp_mod(dev); + td->dev = dev; + td->mod = mod; + td->cd = module_get_private_data(mod); + td->sink = create_test_sink(dev, 0, 0, 0, 4); *state = td; - return 0; } @@ -60,8 +94,9 @@ static int teardown_test_case(void **state) { struct test_data *td = *state; + free_test_sink(td->sink); comp_free(td->dev); - free(td); + test_free(td); return 0; } @@ -73,9 +108,9 @@ static void test_mux_get_processing_function_invalid_float(void **state) mux_func func = NULL; /* set frame format value to unsupported value */ - td->cd->config.frame_format = SOF_IPC_FRAME_FLOAT; + audio_stream_set_frm_fmt(&td->sink->stream, SOF_IPC_FRAME_FLOAT); - func = mux_get_processing_function(td->dev); + func = mux_get_processing_function(td->mod); assert_ptr_equal(func, NULL); } @@ -87,9 +122,9 @@ static void test_mux_get_processing_function_valid_s16le(void **state) struct test_data *td = *state; mux_func func = NULL; - td->cd->config.frame_format = SOF_IPC_FRAME_S16_LE; + audio_stream_set_frm_fmt(&td->sink->stream, SOF_IPC_FRAME_S16_LE); - func = mux_get_processing_function(td->dev); + func = mux_get_processing_function(td->mod); assert_ptr_not_equal(func, NULL); } @@ -101,9 +136,9 @@ static void test_mux_get_processing_function_valid_s24_4le(void **state) struct test_data *td = *state; mux_func func = NULL; - td->cd->config.frame_format = SOF_IPC_FRAME_S24_4LE; + audio_stream_set_frm_fmt(&td->sink->stream, SOF_IPC_FRAME_S24_4LE); - func = mux_get_processing_function(td->dev); + func = mux_get_processing_function(td->mod); assert_ptr_not_equal(func, NULL); } @@ -115,9 +150,9 @@ static void test_mux_get_processing_function_valid_s32le(void **state) struct test_data *td = *state; mux_func func = NULL; - td->cd->config.frame_format = SOF_IPC_FRAME_S32_LE; + audio_stream_set_frm_fmt(&td->sink->stream, SOF_IPC_FRAME_S32_LE); - func = mux_get_processing_function(td->dev); + func = mux_get_processing_function(td->mod); assert_ptr_not_equal(func, NULL); } diff --git a/test/cmocka/src/audio/mux/util.h b/test/cmocka/src/audio/mux/util.h deleted file mode 100644 index ca04d7fa9af8..000000000000 --- a/test/cmocka/src/audio/mux/util.h +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/sof.h> -#include <sof/audio/component.h> -#include <sof/audio/mux.h> -#include <sof/lib/alloc.h> - -#include <stdlib.h> - -static inline struct comp_buffer *create_test_sink(struct comp_dev *dev, - uint32_t pipeline_id, - uint32_t frame_fmt, - uint16_t channels) -{ - struct comp_buffer *buffer = calloc(1, sizeof(struct comp_buffer)); - - /* set bsink list */ - list_item_append(&buffer->source_list, &dev->bsink_list); - - /* alloc sink and set default parameters */ - buffer->sink = calloc(1, sizeof(struct comp_dev)); - buffer->sink->state = COMP_STATE_PREPARE; - buffer->stream.frame_fmt = frame_fmt; - buffer->stream.channels = channels; - buffer->stream.free = 0; - buffer->stream.avail = 0; - buffer->pipeline_id = pipeline_id; - - return buffer; -} - -static inline void free_test_sink(struct comp_buffer *buffer) -{ - free(buffer->sink); - free(buffer); -} - -static inline struct comp_buffer *create_test_source(struct comp_dev *dev, - uint32_t pipeline_id, - uint32_t frame_fmt, - uint16_t channels) -{ - struct comp_buffer *buffer = calloc(1, sizeof(struct comp_buffer)); - - /*set bsource list */ - list_item_append(&buffer->sink_list, &dev->bsource_list); - - /* alloc source and set default parameters */ - buffer->source = calloc(1, sizeof(struct comp_dev)); - buffer->source->state = COMP_STATE_PREPARE; - buffer->stream.frame_fmt = frame_fmt; - buffer->stream.channels = channels; - buffer->stream.free = 0; - buffer->stream.avail = 0; - buffer->pipeline_id = pipeline_id; - - return buffer; -} - -static inline void free_test_source(struct comp_buffer *buffer) -{ - free(buffer->source); - free(buffer); -} diff --git a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt new file mode 100644 index 000000000000..4ef68bc32b96 --- /dev/null +++ b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: BSD-3-Clause + +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/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ) + target_include_directories(pcm_float_generic PRIVATE ${PROJECT_SOURCE_DIR}/src/include) + target_compile_definitions(pcm_float_generic PRIVATE PCM_CONVERTER_GENERIC) + target_link_libraries(pcm_float_generic PRIVATE sof_options) +endif() diff --git a/test/cmocka/src/audio/pcm_converter/pcm_float.c b/test/cmocka/src/audio/pcm_converter/pcm_float.c new file mode 100644 index 000000000000..70ccd3621758 --- /dev/null +++ b/test/cmocka/src/audio/pcm_converter/pcm_float.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#include <sof/audio/pcm_converter.h> +#include <sof/audio/format.h> +#include <sof/common.h> +#include <sof/audio/buffer.h> +#include <ipc/stream.h> +#include <ipc/stream.h> + +#include <stdio.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <stdint.h> +#include <cmocka.h> + +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif + +#include "../../util.h" + +/* used during float assertions */ +#define EPSILON 0.01f + +/* base number to check combinations for each data format */ +#define PCM_TEST_INT_NUMBERS \ + -0, 0, 0, 0, -1, 1, -2, 2, \ + -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -25, 25, -57, 57, -100, 100 +#define PCM_TEST_FLOAT_NUMBERS \ + -0, 0, 0.1, -0.1f, -0.8f, 0.8f, -1.9f, 1.9f, \ + -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -25, 25, -57, 57, -100, 100 + +/* generate biggest signed value on a 24 bits number */ +#define INT24_MAX ((1 << (24 - 1)) - 1) + +/* generate smallest signed value on a 24 bits number */ +#define INT24_MIN (-INT24_MAX - 1) + +/* conversion ration */ +const float ratio16 = 1.f / (1u << 15); +const float ratio24 = 1.f / (1u << 23); +const float ratio32 = 1.f / (1u << 31); + +/* + * Function design to help debugging conversion between fixed and float numbers. + * + * Usage: + * add declaration of this function for example to pcm_converter_generic.c + * And feel free to use pcm_float_print_values in functions like + * _pcm_convert_i_to_f or _pcm_convert_f_to_i during debugging + * + * param it int number to show + * param fl pointer to float number to show + * param ex expected number + */ +static void pcm_float_print_values(int32_t it, int32_t *fl, double ep, + const char *func_name) +{ + const int32_t mantissa_mask = (1 << 23) - 1; + int32_t ex = ((*fl >> 23) & 0xFF) - 127; + int32_t mt = *fl & mantissa_mask; + float mantissa_value = mt * (1.0f / mantissa_mask) + 1.f; + + print_message("%s: 0x%08Xf => %.3f * 2**%3d = %10.3e f <=> %7d d \t(expected: %10.3e)\n", + func_name, *fl, mantissa_value, ex, *((float *)fl), it, + ep); +} + +static struct comp_buffer *_test_pcm_convert(enum sof_ipc_frame frm_in, enum sof_ipc_frame frm_out, + int samples, const void *data) +{ + /* create buffers - output buffer may be too big for test */ + struct comp_buffer *source; + struct comp_buffer *sink; + pcm_converter_func fun; + const uint8_t fillval = 0xAB; + const int inbytes = samples * get_sample_bytes(frm_in); + const int outbytes = (samples + 1) * get_sample_bytes(frm_out); + + /* create buffers */ + source = create_test_source(NULL, 0, frm_in, 1, inbytes); + sink = create_test_sink(NULL, 0, frm_out, 1, outbytes); + + /* fill source */ + memcpy_s(source->stream.w_ptr, source->stream.size, data, inbytes); + audio_stream_produce(&source->stream, inbytes); + + /* fill sink memory - to validate last value */ + memset(sink->stream.w_ptr, fillval, outbytes); + + /* run conversion */ + fun = pcm_get_conversion_function(frm_in, frm_out); + assert_non_null(fun); + fun(&source->stream, 0, &sink->stream, 0, samples, DUMMY_CHMAP); + + /* assert last value in sink is untouched */ + assert_int_equal(((uint8_t *)sink->stream.w_ptr)[outbytes - 1], fillval); + + /* free source and return sink */ + free_test_source(source); + return sink; +} + +static void mask_array(int32_t mask, int32_t *parray, int cnt) +{ + assert_non_null(parray); + while (cnt--) + parray[cnt] &= mask; +} + +static void scale_array(float ratio, float *parray, int cnt) +{ + assert_non_null(parray); + while (cnt--) + parray[cnt] *= ratio; +} + +#if CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S16LE +static void test_pcm_convert_s16_to_f(void **state) +{ + typedef int16_t Tin; + typedef float Tout; + static const Tin source_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + }; + static Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio16, expected_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_FLOAT, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(source_buf[i], (int32_t *)read_val, + expected_buf[i], __func__); + assert_float_equal(*read_val, expected_buf[i], EPSILON); + } + + /* free memory */ + free_test_sink(sink); +} + +static void test_pcm_convert_f_to_s16(void **state) +{ + typedef float Tin; + typedef int16_t Tout; + static Tin source_buf[] = { + PCM_TEST_FLOAT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + }; + static const Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio16, source_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S16_LE, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(*read_val, (int32_t *)&source_buf[i], + (float)expected_buf[i], __func__); + assert_int_equal(*read_val, expected_buf[i]); + } + + /* free memory */ + free_test_sink(sink); +} +#endif /* CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S16LE */ + +#if CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S24LE +static void test_pcm_convert_s24_in_s32_to_f(void **state) +{ + typedef int32_t Tin; + typedef float Tout; + static const Tin source_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + }; + static Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio24, expected_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_FLOAT, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(source_buf[i], (int32_t *)read_val, + expected_buf[i], __func__); + assert_float_equal(*read_val, expected_buf[i], EPSILON); + } + + /* free memory */ + free_test_sink(sink); +} + +static void test_pcm_convert_s24_to_f(void **state) +{ + typedef int32_t Tin; + typedef float Tout; + static Tin source_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + }; + static Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + mask_array(MASK(24, 0), source_buf, N); + scale_array(ratio24, expected_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_FLOAT, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(sign_extend_s24(source_buf[i]), + (int32_t *)read_val, expected_buf[i], + __func__); + assert_float_equal(*read_val, expected_buf[i], EPSILON); + } + + /* free memory */ + free_test_sink(sink); +} + +static void test_pcm_convert_f_to_s24(void **state) +{ + typedef float Tin; + typedef int32_t Tout; + static Tin source_buf[] = { + PCM_TEST_FLOAT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + INT24_MIN - 1, INT24_MAX + 1, + }; + static const Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + INT24_MIN, INT24_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio24, source_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S24_4LE, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(*read_val, (int32_t *)&source_buf[i], + (float)expected_buf[i], __func__); + assert_int_equal(*read_val, expected_buf[i]); + } + + /* free memory */ + free_test_sink(sink); +} +#endif /* CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S24LE */ + +#if CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S32LE +#define S24TOS32MULT (1 << (32 - 24)) +static void test_pcm_convert_s32_to_f(void **state) +{ + typedef int32_t Tin; + typedef float Tout; + + static const Tin source_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + INT32_MIN + 1, INT32_MIN, + INT32_MAX - 1, INT32_MAX, + }; + static Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + INT24_MIN*S24TOS32MULT, INT24_MIN * S24TOS32MULT, + INT24_MAX*S24TOS32MULT, INT24_MAX * S24TOS32MULT, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio32, expected_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_FLOAT, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(source_buf[i], (int32_t *)read_val, + expected_buf[i], __func__); + assert_float_equal(*read_val, expected_buf[i], EPSILON); + } + + /* free memory */ + free_test_sink(sink); +} + +static void test_pcm_convert_f_to_s32(void **state) +{ + typedef float Tin; + typedef int32_t Tout; + static Tin source_buf[] = { + PCM_TEST_FLOAT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + }; + static const Tout expected_buf[] = { + PCM_TEST_INT_NUMBERS, + INT16_MIN + 1, INT16_MIN, + INT16_MAX - 1, INT16_MAX, + INT24_MIN + 1, INT24_MIN, + INT24_MAX - 1, INT24_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio32, source_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(*read_val, (int32_t *)&source_buf[i], + (float)expected_buf[i], __func__); + assert_int_equal(*read_val, expected_buf[i]); + } + + /* free memory */ + free_test_sink(sink); +} + +static void test_pcm_convert_f_to_s32_big_neg(void **state) +{ + typedef float Tin; + typedef int32_t Tout; + static Tin source_buf[] = { + INT24_MIN - 127, INT24_MIN - 128, /* 24B mantissa trimming */ + INT32_MIN + 1, INT32_MIN, /* 24B mantissa trimming */ + INT32_MIN * 2.f, INT32_MIN * 10.f, + -INFINITY + }; + static const Tout expected_buf[] = { + INT24_MIN - 127, INT24_MIN - 128, + INT32_MIN + 1, INT32_MIN, + INT32_MIN, INT32_MIN, + INT32_MIN + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio32, source_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(*read_val, (int32_t *)&source_buf[i], + (float)expected_buf[i], __func__); + /* assert as float because of possible rounding effects */ + assert_float_equal(*read_val, expected_buf[i], 1); + } + + /* free memory */ + free_test_sink(sink); +} + +static void test_pcm_convert_f_to_s32_big_pos(void **state) +{ + typedef float Tin; + typedef int32_t Tout; + static Tin source_buf[] = { + INT24_MAX + 127, INT24_MAX + 128, + INT32_MAX - 255, INT32_MAX - 127, + INT32_MAX - 1, INT32_MAX, + INT32_MAX * 2.f, INT32_MAX * 10.f, + INFINITY, + }; + /* remember about 24B mantissa trimming */ + static const Tout expected_buf[] = { + INT24_MAX + 127, INT24_MAX + 128, + INT32_MAX - 254, INT32_MAX - 126, + INT32_MAX - 1, INT32_MAX, + INT32_MAX, INT32_MAX, + INT32_MAX, + }; + + struct comp_buffer *sink; + int i, N = ARRAY_SIZE(source_buf); + Tout *read_val; + + assert_int_equal(ARRAY_SIZE(source_buf), ARRAY_SIZE(expected_buf)); + scale_array(ratio32, source_buf, N); + + /* run test */ + sink = _test_pcm_convert(SOF_IPC_FRAME_FLOAT, SOF_IPC_FRAME_S32_LE, + N, source_buf); + + /* check results */ + for (i = 0; i < N; ++i) { + read_val = audio_stream_read_frag(&sink->stream, i, sizeof(Tout)); + print_message("%2d/%02d ", i + 1, N); + pcm_float_print_values(*read_val, (int32_t *)&source_buf[i], + (float)expected_buf[i], __func__); + /* assert as float because of possible rounding effects */ + assert_float_equal(*read_val, expected_buf[i], 1); + } + + /* free memory */ + free_test_sink(sink); +} +#endif /* CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S32LE */ + +int main(void) +{ + const struct CMUnitTest tests[] = { +#if CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S16LE + cmocka_unit_test(test_pcm_convert_s16_to_f), + cmocka_unit_test(test_pcm_convert_f_to_s16), +#endif /* CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S24LE + cmocka_unit_test(test_pcm_convert_s24_to_f), + cmocka_unit_test(test_pcm_convert_s24_in_s32_to_f), + cmocka_unit_test(test_pcm_convert_f_to_s24), +#endif /* CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S32LE + cmocka_unit_test(test_pcm_convert_s32_to_f), + cmocka_unit_test(test_pcm_convert_f_to_s32), + cmocka_unit_test(test_pcm_convert_f_to_s32_big_neg), + cmocka_unit_test(test_pcm_convert_f_to_s32_big_pos), +#endif /* CONFIG_FORMAT_FLOAT && CONFIG_FORMAT_S32LE */ + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + /* log number of converting functions for current configuration */ + print_message("%s start tests, count(pcm_func_map)=%zu\n", + __FILE__, pcm_func_count); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/audio/pipeline/CMakeLists.txt b/test/cmocka/src/audio/pipeline/CMakeLists.txt index b9f51384e985..6ba4fecd4c97 100644 --- a/test/cmocka/src/audio/pipeline/CMakeLists.txt +++ b/test/cmocka/src/audio/pipeline/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause -if(CONFIG_SMP) +if(CONFIG_MULTICORE AND NOT BUILD_UNIT_TESTS_HOST) SET(arch_src ${PROJECT_SOURCE_DIR}/src/drivers/intel/cavs/idc.c) # make small lib for stripping so we don't have to care @@ -19,26 +19,74 @@ endif() cmocka_test(pipeline_new pipeline_new.c - pipeline_mocks.c - pipeline_mocks_rzalloc.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 + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/pipeline.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c ) cmocka_test(pipeline_connect_upstream pipeline_connect_upstream.c - pipeline_mocks.c - pipeline_mocks_rzalloc.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 + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/pipeline.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c ) cmocka_test(pipeline_free pipeline_free.c - pipeline_mocks.c - pipeline_mocks_rzalloc.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 + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/pipeline.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c ) diff --git a/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c b/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c index a553999dffd5..e911f0238162 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c +++ b/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c @@ -7,6 +7,7 @@ #include <stdint.h> #include <sof/audio/component.h> #include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> #include <sof/schedule/edf_schedule.h> #include "pipeline_mocks.h" #include "pipeline_connection_mocks.h" @@ -23,6 +24,7 @@ static int setup(void **state) static int teardown(void **state) { + free_standard_connect_objects(*state); free(*state); return 0; } @@ -128,13 +130,13 @@ static void test_audio_pipeline_complete_connect_upstream_ignore_source */ list_item_append(&result.sched_comp->bsource_list, &test_data->b1->sink_list); - test_data->b1->sink = result.sched_comp; - test_data->b1->source = test_data->second; + comp_buffer_set_sink_component(test_data->b1, result.sched_comp); + comp_buffer_set_source_component(test_data->b1, test_data->second); list_item_append(&test_data->b1->source_list, &test_data->second->bsink_list); list_item_append(&test_data->second->bsource_list, &test_data->b2->sink_list); - test_data->b2->sink = test_data->second; + comp_buffer_set_sink_component(test_data->b2, test_data->second); /*Testing component*/ pipeline_complete(&result, test_data->first, test_data->second); @@ -148,21 +150,18 @@ static void test_audio_pipeline_complete_connect_downstream_full(void **state) { struct pipeline_connect_data *test_data = *state; struct pipeline result = test_data->p; - struct sof_ipc_comp *comp; + struct comp_ipc_config *comp; cleanup_test_data(test_data); /*Connecting first comp to second*/ - comp = dev_comp(test_data->second); + comp = &test_data->second->ipc_config; comp->pipeline_id = PIPELINE_ID_SAME; - list_item_append(&result.sched_comp->bsink_list, - &test_data->b1->source_list); - test_data->b1->source = result.sched_comp; - list_item_append(&test_data->b1->source_list, - &result.sched_comp->bsink_list); - test_data->b1->sink = test_data->second; - list_item_append(&test_data->b1->sink_list, - &test_data->second->bsource_list); + list_item_append(&result.sched_comp->bsink_list, &test_data->b1->source_list); + comp_buffer_set_source_component(test_data->b1, result.sched_comp); + list_item_append(&test_data->b1->source_list, &result.sched_comp->bsink_list); + comp_buffer_set_sink_component(test_data->b1, test_data->second); + list_item_append(&test_data->b1->sink_list, &test_data->second->bsource_list); test_data->first->frames = 0; test_data->second->frames = 0; @@ -179,17 +178,17 @@ static void test_audio_pipeline_complete_connect_upstream_full(void **state) { struct pipeline_connect_data *test_data = *state; struct pipeline result = test_data->p; - struct sof_ipc_comp *comp; + struct comp_ipc_config *comp; cleanup_test_data(test_data); /*Connecting first comp to second*/ - comp = dev_comp(test_data->second); + comp = &test_data->second->ipc_config; comp->pipeline_id = PIPELINE_ID_SAME; list_item_append(&result.sched_comp->bsource_list, &test_data->b1->sink_list); - test_data->b1->sink = test_data->first; - test_data->b1->source = test_data->second; + comp_buffer_set_sink_component(test_data->b1, test_data->first); + comp_buffer_set_source_component(test_data->b1, test_data->second); /*Testing component*/ pipeline_complete(&result, test_data->first, test_data->second); @@ -204,19 +203,17 @@ static void test_audio_pipeline_complete_connect_upstream_other_pipeline { struct pipeline_connect_data *test_data = *state; struct pipeline result = test_data->p; - struct sof_ipc_comp *comp; + struct comp_ipc_config *comp; cleanup_test_data(test_data); /*Connecting first comp to second*/ - comp = dev_comp(test_data->second); + comp = &test_data->second->ipc_config; comp->pipeline_id = PIPELINE_ID_DIFFERENT; - list_item_append(&result.sched_comp->bsource_list, - &test_data->b1->sink_list); - test_data->b1->sink = test_data->first; - test_data->b1->source = test_data->second; - list_item_append(&test_data->second->bsource_list, - &test_data->b1->source_list); + list_item_append(&result.sched_comp->bsource_list, &test_data->b1->sink_list); + comp_buffer_set_sink_component(test_data->b1, test_data->first); + comp_buffer_set_source_component(test_data->b1, test_data->second); + list_item_append(&test_data->second->bsource_list, &test_data->b1->source_list); /*Testing component*/ pipeline_complete(&result, test_data->first, test_data->second); diff --git a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c index 83a6650e4ba0..de05f8e3b284 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c +++ b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c @@ -4,6 +4,7 @@ // // Author: Jakub Dabek <jakub.dabek@linux.intel.com> +#include <sof/audio/ipc-config.h> #include "pipeline_connection_mocks.h" extern struct schedulers *schedulers; @@ -16,12 +17,12 @@ void cleanup_test_data(struct pipeline_connect_data *data) { list_init(&data->first->bsource_list); list_init(&data->second->bsource_list); - list_init(&data->b1->sink_list); - list_init(&data->b1->source_list); + comp_buffer_reset_sink_list(data->b1); + comp_buffer_reset_source_list(data->b1); list_init(&data->first->bsink_list); list_init(&data->second->bsink_list); - list_init(&data->b2->sink_list); - list_init(&data->b2->source_list); + comp_buffer_reset_sink_list(data->b2); + comp_buffer_reset_source_list(data->b2); } struct pipeline_connect_data *get_standard_connect_objects(void) @@ -29,13 +30,10 @@ struct pipeline_connect_data *get_standard_connect_objects(void) struct pipeline_connect_data *pipeline_connect_data = calloc (sizeof(struct pipeline_connect_data), 1); - struct sof_ipc_pipe_new pipe_desc = { - .frames_per_sched = 5, - .pipeline_id = PIPELINE_ID_SAME }; + struct pipeline *pipe = &pipeline_connect_data->p; - struct pipeline *pipe = calloc(sizeof(struct pipeline), 1); - - pipe->ipc_pipe = pipe_desc; + pipe->frames_per_sched = 5; + pipe->pipeline_id = PIPELINE_ID_SAME; pipe->status = COMP_STATE_INIT; pipe->pipe_task = calloc(sizeof(struct task), 1); @@ -52,7 +50,7 @@ struct pipeline_connect_data *get_standard_connect_objects(void) list_item_append(&sch->list, &schedulers->list); struct comp_dev *first = calloc(sizeof(struct comp_dev), 1); - struct sof_ipc_comp *first_comp = dev_comp(first); + struct comp_ipc_config *first_comp = &first->ipc_config; first_comp->id = 3; first_comp->pipeline_id = PIPELINE_ID_SAME; @@ -62,7 +60,7 @@ struct pipeline_connect_data *get_standard_connect_objects(void) pipe->sched_comp = first; struct comp_dev *second = calloc(sizeof(struct comp_dev), 1); - struct sof_ipc_comp *second_comp = dev_comp(second); + struct comp_ipc_config *second_comp = &second->ipc_config; second_comp->id = 4; second_comp->pipeline_id = PIPELINE_ID_DIFFERENT; @@ -72,20 +70,27 @@ struct pipeline_connect_data *get_standard_connect_objects(void) struct comp_buffer *buffer = calloc(sizeof(struct comp_buffer), 1); - buffer->source = first; - buffer->sink = second; - list_init(&buffer->sink_list); - list_init(&buffer->source_list); + comp_buffer_set_source_component(buffer, first); + comp_buffer_set_sink_component(buffer, second); + comp_buffer_reset_sink_list(buffer); + comp_buffer_reset_source_list(buffer); pipeline_connect_data->b1 = buffer; struct comp_buffer *buffer_2 = calloc(sizeof(struct comp_buffer), 1); - buffer_2->source = second; - list_init(&buffer_2->sink_list); - list_init(&buffer_2->source_list); + comp_buffer_set_source_component(buffer_2, second); + comp_buffer_reset_sink_list(buffer_2); + comp_buffer_reset_source_list(buffer_2); pipeline_connect_data->b2 = buffer_2; - pipeline_connect_data->p = *pipe; - return pipeline_connect_data; } + +void free_standard_connect_objects(struct pipeline_connect_data *data) +{ + free(data->p.pipe_task); + free(data->p.sched_comp); + free(data->second); + free(data->b1); + free(data->b2); +} diff --git a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h index 01c93c116262..60eedabbd43b 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h +++ b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.h @@ -12,9 +12,14 @@ #include <stddef.h> #include <setjmp.h> #include <stdint.h> -#include <malloc.h> #include <cmocka.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif + #define PIPELINE_ID_SAME 3 #define PIPELINE_ID_DIFFERENT 4 @@ -27,12 +32,15 @@ struct pipeline_connect_data { }; struct pipeline_connect_data *get_standard_connect_objects(void); +void free_standard_connect_objects(struct pipeline_connect_data *data); void cleanup_test_data(struct pipeline_connect_data *data); -static inline void schedule_task_mock_free(void *data, struct task *task) +static inline int schedule_task_mock_free(void *data, struct task *task) { task->state = SOF_TASK_STATE_FREE; task->ops.run = NULL; task->data = NULL; + + return 0; } diff --git a/test/cmocka/src/audio/pipeline/pipeline_free.c b/test/cmocka/src/audio/pipeline/pipeline_free.c index cafe1fa41871..9878f4f5e42a 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_free.c +++ b/test/cmocka/src/audio/pipeline/pipeline_free.c @@ -7,16 +7,26 @@ #include <stdint.h> #include <sof/audio/component.h> #include <sof/audio/pipeline.h> +#include <sof/audio/ipc-config.h> #include <sof/schedule/edf_schedule.h> -#include <sof/schedule/task.h> -#include "pipeline_mocks.h" +#include <rtos/task.h> #include "pipeline_connection_mocks.h" #include <stdarg.h> #include <stddef.h> #include <setjmp.h> -#include <malloc.h> #include <cmocka.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif + +/* mock free() - dont free as we inspect contents */ +void sof_heap_free(struct k_heap *heap, void *addr) +{ +} + static int setup(void **state) { pipeline_posn_init(sof_get()); @@ -26,26 +36,11 @@ static int setup(void **state) static int teardown(void **state) { + free_standard_connect_objects(*state); free(*state); return 0; } -static void test_audio_pipeline_free_comp_busy(void **state) -{ - struct pipeline_connect_data *test_data = *state; - struct pipeline result = test_data->p; - - cleanup_test_data(test_data); - - result.source_comp = test_data->first; - result.sched_comp->state = 3; - - /*Testing component*/ - int err = pipeline_free(&result); - - assert_int_equal(err, -EBUSY); -} - static void test_audio_pipeline_free_return_value(void **state) { struct pipeline_connect_data *test_data = *state; @@ -53,9 +48,6 @@ static void test_audio_pipeline_free_return_value(void **state) cleanup_test_data(test_data); - result.source_comp = test_data->first; - result.sched_comp->state = COMP_STATE_READY; - /*Testing component*/ int err = pipeline_free(&result); @@ -69,8 +61,6 @@ static void test_audio_pipeline_free_sheduler_task_free(void **state) cleanup_test_data(test_data); - result.source_comp = test_data->first; - /*Testing component*/ pipeline_free(&result); @@ -79,74 +69,15 @@ static void test_audio_pipeline_free_sheduler_task_free(void **state) assert_ptr_equal(NULL, result.pipe_task->ops.run); } -static void test_audio_pipeline_free_disconnect_full(void **state) -{ - struct pipeline_connect_data *test_data = *state; - struct pipeline result = test_data->p; - struct sof_ipc_comp *first_comp; - struct sof_ipc_comp *second_comp; - - cleanup_test_data(test_data); - - /*Set pipeline to check that is null later*/ - result.source_comp = test_data->first; - test_data->first->pipeline = &result; - test_data->second->pipeline = &result; - first_comp = dev_comp(test_data->first); - second_comp = dev_comp(test_data->second); - second_comp->pipeline_id = PIPELINE_ID_SAME; - first_comp->pipeline_id = PIPELINE_ID_SAME; - test_data->b1->source = test_data->first; - list_item_append(&result.sched_comp->bsink_list, - &test_data->b1->source_list); - test_data->b1->sink = test_data->second; - - /*Testing component*/ - pipeline_free(&result); - - assert_ptr_equal(NULL, test_data->second->pipeline); - assert_ptr_equal(NULL, test_data->first->pipeline); -} - -static void test_audio_pipeline_free_disconnect_list_del -(void **state) -{ - struct pipeline_connect_data *test_data = *state; - struct pipeline result = test_data->p; - - cleanup_test_data(test_data); - - result.source_comp = test_data->first; - test_data->b1->source = test_data->first; - list_item_append(&result.sched_comp->bsink_list, - &test_data->b1->source_list); - test_data->b1->sink = test_data->second; - - /*Testing component*/ - pipeline_free(&result); - - assert_true(list_is_empty(&test_data->second->bsink_list)); - assert_true(list_is_empty(&test_data->first->bsink_list)); -} - int main(void) { const struct CMUnitTest tests[] = { - cmocka_unit_test( - test_audio_pipeline_free_comp_busy - ), cmocka_unit_test( test_audio_pipeline_free_return_value ), cmocka_unit_test( test_audio_pipeline_free_sheduler_task_free ), - cmocka_unit_test( - test_audio_pipeline_free_disconnect_full - ), - cmocka_unit_test( - test_audio_pipeline_free_disconnect_list_del - ), }; cmocka_set_message_output(CM_OUTPUT_TAP); diff --git a/test/cmocka/src/audio/pipeline/pipeline_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_mocks.c deleted file mode 100644 index 53b032a6e53c..000000000000 --- a/test/cmocka/src/audio/pipeline/pipeline_mocks.c +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Jakub Dabek <jakub.dabek@linux.intel.com> - -#include "pipeline_mocks.h" - -#include <mock_trace.h> - -TRACE_IMPL() - -struct ipc *_ipc; -struct timer *platform_timer; -struct schedulers *schedulers; -static struct sof sof; - -struct sof *sof_get(void) -{ - return &sof; -} - -struct schedulers **arch_schedulers_get(void) -{ - return &schedulers; -} - -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn) -{ - (void)dai; - (void)posn; -} - -int schedule_task_init(struct task *task, uint32_t uid, uint16_t type, - uint16_t priority, enum task_state (*run)(void *data), - void *data, uint16_t core, uint32_t flags) -{ - (void)task; - (void)uid; - (void)type; - (void)priority; - (void)run; - (void)data; - (void)core; - (void)flags; - - return 0; -} - -int schedule_task_init_ll(struct task *task, uint32_t uid, uint16_t type, - uint16_t priority, enum task_state (*run)(void *data), - void *data, uint16_t core, uint32_t flags) -{ - return 0; -} - -void rfree(void *ptr) -{ - (void)ptr; -} - -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn) -{ - (void)host; - (void)posn; -} - -int ipc_stream_send_xrun(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn) -{ - return 0; -} - -void cpu_power_down_core(void) { } - -void notifier_notify(void) { } - -struct ipc_comp_dev *ipc_get_comp_by_id(struct ipc *ipc, uint32_t id) -{ - (void)ipc; - (void)id; - - return NULL; -} - -struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, - uint32_t ppl_id) -{ - (void)ipc; - (void)type; - (void)ppl_id; - - return NULL; -} - -void heap_trace_all(int force) -{ - (void)force; -} - -uint64_t platform_timer_get(struct timer *timer) -{ - (void)timer; - - return 0; -} - -uint64_t clock_ms_to_ticks(int clock, uint64_t ms) -{ - (void)clock; - (void)ms; - - return 0; -} - -void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) -{ - (void)msg; - (void)data; - (void)high_priority; -} diff --git a/test/cmocka/src/audio/pipeline/pipeline_mocks.h b/test/cmocka/src/audio/pipeline/pipeline_mocks.h index 41dddef25942..636caac3dc9f 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_mocks.h +++ b/test/cmocka/src/audio/pipeline/pipeline_mocks.h @@ -7,7 +7,11 @@ #include <sof/audio/component.h> #include <sof/audio/pipeline.h> -#include <sof/lib/clk.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/schedule.h> +#include <rtos/clk.h> #include <sof/schedule/edf_schedule.h> #include <sof/schedule/ll_schedule.h> #include <sof/schedule/schedule.h> @@ -17,29 +21,9 @@ #include <stdint.h> #include <cmocka.h> -int ipc_stream_send_xrun(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn); - -int arch_cpu_is_core_enabled(int id); - -void cpu_power_down_core(void); - -struct ipc_comp_dev *ipc_get_comp_by_id(struct ipc *ipc, uint32_t id); - -struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, - uint32_t ppl_id); - -void notifier_notify(void); - -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn); - -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn); - -uint64_t platform_timer_get(struct timer *timer); - struct pipeline_new_setup_data { - struct sof_ipc_pipe_new ipc_data; + uint32_t pipe_id; + uint32_t priority; + uint32_t comp_id; struct comp_dev *comp_data; }; diff --git a/test/cmocka/src/audio/pipeline/pipeline_mocks_rzalloc.c b/test/cmocka/src/audio/pipeline/pipeline_mocks_rzalloc.c deleted file mode 100644 index 361556c61390..000000000000 --- a/test/cmocka/src/audio/pipeline/pipeline_mocks_rzalloc.c +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Jakub Dabek <jakub.dabek@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/audio/pipeline.h> -#include <sof/schedule/edf_schedule.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <malloc.h> -#include <cmocka.h> -#include <sof/lib/alloc.h> - -void *rzalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - (void)zone; - (void)flags; - (void)caps; - return calloc(bytes, 1); -} diff --git a/test/cmocka/src/audio/pipeline/pipeline_new.c b/test/cmocka/src/audio/pipeline/pipeline_new.c index ec8ea76aa0a3..a68afe49e4be 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_new.c +++ b/test/cmocka/src/audio/pipeline/pipeline_new.c @@ -12,9 +12,14 @@ #include <stdarg.h> #include <stddef.h> #include <setjmp.h> -#include <malloc.h> #include <cmocka.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif + static int setup(void **state) { struct pipeline_new_setup_data *pipeline_data = malloc( @@ -22,12 +27,12 @@ static int setup(void **state) pipeline_posn_init(sof_get()); - if (pipeline_data == NULL) + if (!pipeline_data) return -1; - struct sof_ipc_pipe_new pipe_desc = { .core = 1, .priority = 2 }; - - pipeline_data->ipc_data = pipe_desc; + pipeline_data->pipe_id = 1; + pipeline_data->priority = 2; + pipeline_data->comp_id = 3; *state = pipeline_data; return 0; @@ -44,30 +49,24 @@ static void test_audio_pipeline_pipeline_new_creation(void **state) struct pipeline_new_setup_data *test_data = *state; /*Testing component*/ - struct pipeline *result = pipeline_new(&test_data->ipc_data, - test_data->comp_data); + struct pipeline *result = pipeline_new(NULL, + test_data->pipe_id, + test_data->priority, + test_data->comp_id, + NULL); /*Pipeline should have been created so pointer can't be null*/ assert_non_null(result); -} - -static void test_audio_pipeline_new_ipc_data_coppy(void **state) -{ - struct pipeline_new_setup_data *test_data = *state; - - /*Testing component*/ - struct pipeline *result = pipeline_new(&test_data->ipc_data, - test_data->comp_data); - assert_memory_equal(&test_data->ipc_data, &result->ipc_pipe, - sizeof(struct sof_ipc_pipe_new)); + rfree(result->msg->tx_data); + rfree(result->msg); + rfree(result); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_audio_pipeline_pipeline_new_creation), - cmocka_unit_test(test_audio_pipeline_new_ipc_data_coppy), }; cmocka_set_message_output(CM_OUTPUT_TAP); diff --git a/test/cmocka/src/audio/selector/CMakeLists.txt b/test/cmocka/src/audio/selector/CMakeLists.txt index 06053f483420..d5c9ed31ad4e 100644 --- a/test/cmocka/src/audio/selector/CMakeLists.txt +++ b/test/cmocka/src/audio/selector/CMakeLists.txt @@ -12,8 +12,28 @@ 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/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c ) sof_append_relative_path_definitions(audio_for_selector) diff --git a/test/cmocka/src/audio/selector/selector_test.c b/test/cmocka/src/audio/selector/selector_test.c index ab4ca441df13..4bcc8df7fea5 100644 --- a/test/cmocka/src/audio/selector/selector_test.c +++ b/test/cmocka/src/audio/selector/selector_test.c @@ -4,19 +4,25 @@ // // Author: Lech Betlej <lech.betlej@linux.intel.com> +#include "../../util.h" + #include <stdarg.h> #include <stddef.h> #include <setjmp.h> #include <stdint.h> #include <cmocka.h> +#include <sof/audio/buffer.h> #include <sof/audio/component.h> +#if CONFIG_IPC_MAJOR_4 +#include <sof/audio/module_adapter/module/generic.h> +#endif #include <sof/audio/selector.h> - +#if CONFIG_IPC_MAJOR_3 struct sel_test_state { struct comp_dev *dev; - struct audio_stream *sink; - struct audio_stream *source; + struct comp_buffer *sink; + struct comp_buffer *source; void (*verify)(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source); }; @@ -39,15 +45,17 @@ static int setup(void **state) struct sel_test_state *sel_state; struct comp_data *cd; uint32_t size = 0; - void *pbuff; /* allocate new state */ sel_state = test_malloc(sizeof(*sel_state)); /* allocate and set new device */ - sel_state->dev = test_malloc(COMP_SIZE(struct sof_ipc_comp_volume)); + sel_state->dev = test_malloc(sizeof(struct comp_dev)); sel_state->dev->frames = parameters->frames; + list_init(&sel_state->dev->bsink_list); + list_init(&sel_state->dev->bsource_list); + /* allocate and set new data */ cd = test_malloc(sizeof(*cd)); comp_set_drvdata(sel_state->dev, cd); @@ -62,22 +70,18 @@ static int setup(void **state) cd->sel_func = sel_get_processing_function(sel_state->dev); /* allocate new sink buffer */ - sel_state->sink = test_malloc(sizeof(*sel_state->sink)); - sel_state->sink->frame_fmt = parameters->sink_format; - sel_state->sink->channels = parameters->out_channels; - size = parameters->frames * audio_stream_frame_bytes(sel_state->sink); - pbuff = test_calloc(parameters->buffer_size_ms, size); - audio_stream_init(sel_state->sink, pbuff, - parameters->buffer_size_ms * size); + size = parameters->frames * get_frame_bytes(parameters->sink_format, + parameters->out_channels) * parameters->buffer_size_ms; + + sel_state->sink = create_test_sink(sel_state->dev, 0, parameters->sink_format, + parameters->out_channels, size); /* allocate new source buffer */ - sel_state->source = test_malloc(sizeof(*sel_state->source)); - sel_state->source->frame_fmt = parameters->source_format; - sel_state->source->channels = parameters->in_channels; - size = parameters->frames * audio_stream_frame_bytes(sel_state->source); - pbuff = test_calloc(parameters->buffer_size_ms, size); - audio_stream_init(sel_state->source, pbuff, - parameters->buffer_size_ms * size); + size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->in_channels) * parameters->buffer_size_ms; + + sel_state->source = create_test_source(sel_state->dev, 0, parameters->source_format, + parameters->in_channels, size); /* assigns verification function */ sel_state->verify = parameters->verify; @@ -96,31 +100,149 @@ static int teardown(void **state) /* free everything */ test_free(cd); test_free(sel_state->dev); - test_free(sel_state->sink->addr); - test_free(sel_state->sink); - test_free(sel_state->source->addr); - test_free(sel_state->source); + free_test_sink(sel_state->sink); + free_test_source(sel_state->source); + test_free(sel_state); + + return 0; +} +#else +struct sel_test_state { + struct processing_module *mod; + struct comp_buffer *sink; + struct comp_buffer *source; + struct input_stream_buffer *input; + struct output_stream_buffer *output; + size_t size; + uint32_t channels; + void (*verify)(struct processing_module *mod, struct audio_stream *sink, + struct audio_stream *source); +}; + +struct sel_test_parameters { + uint32_t in_channels; + uint32_t out_channels; + uint32_t sel_channel; + uint32_t frames; + uint32_t buffer_size_ms; + uint32_t source_format; + uint32_t sink_format; + void (*verify)(struct processing_module *mod, struct audio_stream *sink, + struct audio_stream *source); +}; + +static int setup(void **state) +{ + struct sel_test_parameters *parameters = *state; + struct sel_test_state *sel_state; + struct module_data *md; + struct comp_dev *dev; + struct comp_data *cd; + uint32_t size = 0; + + /* allocate new state */ + sel_state = test_malloc(sizeof(*sel_state)); + + /* allocate and set new device */ + sel_state->mod = test_malloc(sizeof(struct processing_module)); + dev = test_malloc(sizeof(struct comp_dev)); + dev->frames = parameters->frames; + sel_state->mod->dev = dev; + + list_init(&dev->bsink_list); + list_init(&dev->bsource_list); + + /* allocate and set new data */ + cd = test_malloc(sizeof(*cd)); + md = &sel_state->mod->priv; + comp_set_drvdata(dev, sel_state->mod); + md->private = cd; + + cd->source_format = parameters->source_format; + cd->sink_format = parameters->sink_format; + + /* prepare parameters that will be used by sel_get_processing_function */ + cd->config.in_channels_count = parameters->in_channels; + cd->config.out_channels_count = parameters->out_channels; + cd->config.sel_channel = parameters->sel_channel; + + cd->sel_func = sel_get_processing_function(sel_state->mod); + + /* allocate new sink buffer */ + size = parameters->frames * get_frame_bytes(parameters->sink_format, + parameters->out_channels) * parameters->buffer_size_ms; + sel_state->size = size; + sel_state->sink = create_test_sink(dev, 0, parameters->sink_format, + parameters->out_channels, size); + + /* allocate new source buffer */ + size = parameters->frames * get_frame_bytes(parameters->source_format, + parameters->in_channels) * parameters->buffer_size_ms; + + sel_state->source = create_test_source(dev, 0, parameters->source_format, + parameters->in_channels, size); + + sel_state->input = test_malloc(sizeof(struct input_stream_buffer)); + sel_state->input->data = &sel_state->source->stream; + sel_state->output = test_malloc(sizeof(struct output_stream_buffer)); + sel_state->output->data = &sel_state->sink->stream; + + /* assigns verification function */ + sel_state->verify = parameters->verify; + + /* assign test state */ + *state = sel_state; + + return 0; +} + +static int teardown(void **state) +{ + struct sel_test_state *sel_state = *state; + struct comp_data *cd = module_get_private_data(sel_state->mod); + + /* free everything */ + test_free(cd); + test_free(sel_state->mod->dev); + test_free(sel_state->mod); + test_free(sel_state->input); + test_free(sel_state->output); + free_test_sink(sel_state->sink); + free_test_source(sel_state->source); test_free(sel_state); return 0; } +#endif #if CONFIG_FORMAT_S16LE static void fill_source_s16(struct sel_test_state *sel_state) { - int16_t *src = (int16_t *)sel_state->source->r_ptr; + struct audio_stream *stream = &sel_state->source->stream; + int16_t *w_ptr; int i; - for (i = 0; i < sel_state->source->size / sizeof(int16_t); i++) - src[i] = i; + for (i = 0; i < audio_stream_get_free_samples(stream); i++) { + w_ptr = audio_stream_write_frag_s16(stream, i); + *w_ptr = i; + } + audio_stream_produce(stream, audio_stream_get_free_bytes(stream)); } +#if CONFIG_IPC_MAJOR_3 static void verify_s16le_Xch_to_1ch(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source) { struct comp_data *cd = comp_get_drvdata(dev); +#else +static void verify_s16le_Xch_to_1ch(struct processing_module *mod, + struct audio_stream *sink, + struct audio_stream *source) +{ + struct comp_data *cd = module_get_private_data(mod); +#endif const uint16_t *src = (uint16_t *)source->r_ptr; const uint16_t *dst = (uint16_t *)sink->w_ptr; uint32_t in_channels = cd->config.in_channels_count; @@ -141,13 +263,19 @@ static void verify_s16le_Xch_to_1ch(struct comp_dev *dev, } } +#if CONFIG_IPC_MAJOR_3 static void verify_s16le_2ch_to_2ch(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source) +#else +static void verify_s16le_2ch_to_2ch(struct processing_module *mod, + struct audio_stream *sink, + struct audio_stream *source) +#endif { const uint16_t *src = (uint16_t *)source->r_ptr; const uint16_t *dst = (uint16_t *)sink->w_ptr; - uint32_t channels = source->channels; + uint32_t channels = audio_stream_get_channels(source); uint32_t channel; uint32_t i; double processed; @@ -160,13 +288,19 @@ static void verify_s16le_2ch_to_2ch(struct comp_dev *dev, } } +#if CONFIG_IPC_MAJOR_3 static void verify_s16le_4ch_to_4ch(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source) +#else +static void verify_s16le_4ch_to_4ch(struct processing_module *mod, + struct audio_stream *sink, + struct audio_stream *source) +#endif { const uint16_t *src = (uint16_t *)source->r_ptr; const uint16_t *dst = (uint16_t *)sink->w_ptr; - uint32_t channels = source->channels; + uint32_t channels = audio_stream_get_channels(source); uint32_t channel; uint32_t i; double processed; @@ -184,18 +318,32 @@ static void verify_s16le_4ch_to_4ch(struct comp_dev *dev, #if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE static void fill_source_s32(struct sel_test_state *sel_state) { - int32_t *src = (int32_t *)sel_state->source->r_ptr; + struct audio_stream *stream = &sel_state->source->stream; + int32_t *w_ptr; int i; - for (i = 0; i < sel_state->source->size / sizeof(int32_t); i++) - src[i] = i << 16; + for (i = 0; i < audio_stream_get_free_samples(stream); i++) { + w_ptr = audio_stream_write_frag_s32(stream, i); + *w_ptr = i << 16; + } + + audio_stream_produce(stream, audio_stream_get_free_bytes(stream)); } +#if CONFIG_IPC_MAJOR_3 static void verify_s32le_Xch_to_1ch(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source) { struct comp_data *cd = comp_get_drvdata(dev); + +#else +static void verify_s32le_Xch_to_1ch(struct processing_module *mod, + struct audio_stream *sink, + struct audio_stream *source) +{ + struct comp_data *cd = module_get_private_data(mod); +#endif const uint32_t *src = (uint32_t *)source->r_ptr; const uint32_t *dst = (uint32_t *)sink->w_ptr; uint32_t in_channels = cd->config.in_channels_count; @@ -216,13 +364,19 @@ static void verify_s32le_Xch_to_1ch(struct comp_dev *dev, } } +#if CONFIG_IPC_MAJOR_3 static void verify_s32le_2ch_to_2ch(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source) +#else +static void verify_s32le_2ch_to_2ch(struct processing_module *mod, + struct audio_stream *sink, + struct audio_stream *source) +#endif { const uint32_t *src = (uint32_t *)source->r_ptr; const uint32_t *dst = (uint32_t *)sink->w_ptr; - uint32_t channels = source->channels; + uint32_t channels = audio_stream_get_channels(source); uint32_t channel; uint32_t i; uint32_t processed; @@ -235,13 +389,19 @@ static void verify_s32le_2ch_to_2ch(struct comp_dev *dev, } } +#if CONFIG_IPC_MAJOR_3 static void verify_s32le_4ch_to_4ch(struct comp_dev *dev, struct audio_stream *sink, struct audio_stream *source) +#else +static void verify_s32le_4ch_to_4ch(struct processing_module *mod, + struct audio_stream *sink, + struct audio_stream *source) +#endif { const uint32_t *src = (uint32_t *)source->r_ptr; const uint32_t *dst = (uint32_t *)sink->w_ptr; - uint32_t channels = source->channels; + uint32_t channels = audio_stream_get_channels(source); uint32_t channel; uint32_t i; uint32_t processed; @@ -258,7 +418,12 @@ static void verify_s32le_4ch_to_4ch(struct comp_dev *dev, static void test_audio_sel(void **state) { struct sel_test_state *sel_state = *state; +#if CONFIG_IPC_MAJOR_3 struct comp_data *cd = comp_get_drvdata(sel_state->dev); +#else + struct processing_module *mod = sel_state->mod; + struct comp_data *cd = module_get_private_data(mod); +#endif switch (cd->source_format) { #if CONFIG_FORMAT_S16LE @@ -273,14 +438,30 @@ static void test_audio_sel(void **state) fill_source_s32(sel_state); break; #endif /* CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE */ + + /* TODO: add S24_3LE support */ + /* TODO: add S24_4LE_MSB support */ + /* TODO: add U8 support */ + default: + break; } - cd->sel_func(sel_state->dev, sel_state->sink, sel_state->source, +#if CONFIG_IPC_MAJOR_3 + cd->sel_func(sel_state->dev, &sel_state->sink->stream, &sel_state->source->stream, sel_state->dev->frames); - sel_state->verify(sel_state->dev, sel_state->sink, sel_state->source); -} + sel_state->verify(sel_state->dev, &sel_state->sink->stream, &sel_state->source->stream); + +#else + sel_state->input->consumed = 0; + sel_state->output->size = 0; + cd->sel_func(mod, sel_state->input, sel_state->output, + mod->dev->frames); + + sel_state->verify(mod, &sel_state->sink->stream, &sel_state->source->stream); +#endif +} static struct sel_test_parameters parameters[] = { #if CONFIG_FORMAT_S16LE diff --git a/test/cmocka/src/audio/volume/CMakeLists.txt b/test/cmocka/src/audio/volume/CMakeLists.txt index fb008c7c532b..0385441e5878 100644 --- a/test/cmocka/src/audio/volume/CMakeLists.txt +++ b/test/cmocka/src/audio/volume/CMakeLists.txt @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause cmocka_test(volume_process - volume_process.c + volume_process.c ../module_adapter_test.c ) target_include_directories(volume_process PRIVATE ${PROJECT_SOURCE_DIR}/src/audio) @@ -13,8 +13,36 @@ add_compile_options(-DUNIT_TEST) add_library(audio_for_volume STATIC ${PROJECT_SOURCE_DIR}/src/audio/volume/volume.c + ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_ipc3.c ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_generic.c ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_hifi3.c + ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_hifi4.c + ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_generic_with_peakvol.c + ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_hifi3_with_peakvol.c + ${PROJECT_SOURCE_DIR}/src/audio/volume/volume_hifi4_with_peakvol.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module_adapter_ipc3.c + ${PROJECT_SOURCE_DIR}/src/audio/module_adapter/module/generic.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/lib/objpool.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) sof_append_relative_path_definitions(audio_for_volume) diff --git a/test/cmocka/src/audio/volume/volume_process.c b/test/cmocka/src/audio/volume/volume_process.c index 45a71af6644a..389a4e75a503 100644 --- a/test/cmocka/src/audio/volume/volume_process.c +++ b/test/cmocka/src/audio/volume/volume_process.c @@ -4,13 +4,17 @@ // // Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> +#include "../../util.h" + #include <stdarg.h> #include <stddef.h> #include <setjmp.h> #include <stdint.h> #include <cmocka.h> #include <sof/audio/component.h> -#include <sof/audio/volume.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <volume/volume.h> +#include "../module_adapter.h" /* Add macro for a volume test level. The levels to test with this code * are: @@ -27,23 +31,9 @@ /* Min S24_4LE format value */ #define INT24_MIN -8388608 -struct vol_test_state { - struct comp_dev *dev; - struct comp_buffer *sink; - struct comp_buffer *source; - void (*verify)(struct comp_dev *dev, struct comp_buffer *sink, - struct comp_buffer *source); -}; - struct vol_test_parameters { int32_t volume; - uint32_t channels; - uint32_t frames; - uint32_t buffer_size_ms; - uint32_t source_format; - uint32_t sink_format; - void (*verify)(struct comp_dev *dev, struct comp_buffer *sink, - struct comp_buffer *source); + struct processing_module_test_parameters module_parameters; }; static void set_volume(int32_t *vol, int32_t value, uint32_t channels) @@ -56,58 +46,38 @@ static void set_volume(int32_t *vol, int32_t value, uint32_t channels) static int setup(void **state) { - struct vol_test_parameters *parameters = *state; - struct vol_test_state *vol_state; - struct comp_data *cd; - uint32_t size = 0; + struct vol_test_parameters *vol_parameters = *state; + struct processing_module_test_data *vol_state; + struct module_data *md; + struct vol_data *cd; /* allocate new state */ vol_state = test_malloc(sizeof(*vol_state)); - - /* allocate and set new device */ - vol_state->dev = test_malloc(COMP_SIZE(struct sof_ipc_comp_volume)); - vol_state->dev->frames = parameters->frames; + vol_state->parameters = vol_parameters->module_parameters; + vol_state->num_sources = 1; + vol_state->num_sinks = 1; + module_adapter_test_setup(vol_state); /* allocate and set new data */ cd = test_malloc(sizeof(*cd)); - comp_set_drvdata(vol_state->dev, cd); - - list_init(&vol_state->dev->bsource_list); - list_init(&vol_state->dev->bsink_list); - - /* allocate new sink buffer */ - vol_state->sink = test_malloc(sizeof(*vol_state->sink)); - vol_state->sink->stream.frame_fmt = parameters->sink_format; - vol_state->sink->stream.channels = parameters->channels; - size = parameters->frames * - audio_stream_frame_bytes(&vol_state->sink->stream); - - vol_state->sink->stream.addr = test_calloc(parameters->buffer_size_ms, - size); - buffer_init(vol_state->sink, parameters->buffer_size_ms * size, 0); - - list_item_prepend(&vol_state->sink->source_list, - &vol_state->dev->bsink_list); - - /* allocate new source buffer */ - vol_state->source = test_malloc(sizeof(*vol_state->source)); - vol_state->source->stream.frame_fmt = parameters->source_format; - vol_state->source->stream.channels = parameters->channels; - size = parameters->frames * - audio_stream_frame_bytes(&vol_state->source->stream); - vol_state->source->stream.addr = test_calloc(parameters->buffer_size_ms, - size); - buffer_init(vol_state->source, parameters->buffer_size_ms * size, 0); - - list_item_prepend(&vol_state->source->sink_list, - &vol_state->dev->bsource_list); + md = &vol_state->mod->priv; + md->private = cd; + cd->is_passthrough = false; - /* set processing function and volume */ - cd->scale_vol = vol_get_processing_function(vol_state->dev); - set_volume(cd->volume, parameters->volume, parameters->channels); + /* malloc memory to store current volume 4 times to ensure the address + * is 8-byte aligned for multi-way xtensa intrinsic operations. + */ + const size_t vol_size = sizeof(int32_t) * SOF_IPC_MAX_CHANNELS * 4; - /* assigns verification function */ - vol_state->verify = parameters->verify; + cd->vol = test_malloc(vol_size); + + /* set processing function and volume */ +#if CONFIG_IPC_MAJOR_4 + cd->scale_vol = vol_get_processing_function(vol_state->mod->dev, cd); +#else + cd->scale_vol = vol_get_processing_function(vol_state->mod->dev, vol_state->sinks[0], cd); +#endif + set_volume(cd->volume, vol_parameters->volume, vol_state->parameters.channels); /* assign test state */ *state = vol_state; @@ -117,30 +87,26 @@ static int setup(void **state) static int teardown(void **state) { - struct vol_test_state *vol_state = *state; - struct comp_data *cd = comp_get_drvdata(vol_state->dev); + struct processing_module_test_data *vol_state = *state; + struct vol_data *cd = module_get_private_data(vol_state->mod); - /* free everything */ + test_free(cd->vol); test_free(cd); - test_free(vol_state->dev); - test_free(vol_state->sink->stream.addr); - test_free(vol_state->sink); - test_free(vol_state->source->stream.addr); - test_free(vol_state->source); + module_adapter_test_free(vol_state); test_free(vol_state); return 0; } #if CONFIG_FORMAT_S16LE -static void fill_source_s16(struct vol_test_state *vol_state) +static void fill_source_s16(struct processing_module_test_data *vol_state) { int64_t val; - int16_t *src = (int16_t *)vol_state->source->stream.r_ptr; + int16_t *src = (int16_t *)vol_state->sources[0]->stream.r_ptr; int i; int sign = 1; - for (i = 0; i < vol_state->source->stream.size / sizeof(int16_t); i++) { + for (i = 0; i < vol_state->sources[0]->stream.size / sizeof(int16_t); i++) { val = (INT16_MIN + (i >> 1)) * sign; val = (val > INT16_MAX) ? INT16_MAX : val; src[i] = (int16_t)val; @@ -148,14 +114,14 @@ static void fill_source_s16(struct vol_test_state *vol_state) } } -static void verify_s16_to_s16(struct comp_dev *dev, struct comp_buffer *sink, +static void verify_s16_to_s16(struct processing_module *mod, struct comp_buffer *sink, struct comp_buffer *source) { - struct comp_data *cd = comp_get_drvdata(dev); + struct vol_data *cd = module_get_private_data(mod); const int16_t *src = (int16_t *)source->stream.r_ptr; const int16_t *dst = (int16_t *)sink->stream.w_ptr; double processed; - int channels = sink->stream.channels; + int channels = audio_stream_get_channels(&sink->stream); int channel; int delta; int i; @@ -182,14 +148,14 @@ static void verify_s16_to_s16(struct comp_dev *dev, struct comp_buffer *sink, #endif /* CONFIG_FORMAT_S16LE */ #if CONFIG_FORMAT_S24LE -static void fill_source_s24(struct vol_test_state *vol_state) +static void fill_source_s24(struct processing_module_test_data *vol_state) { int64_t val; - int32_t *src = (int32_t *)vol_state->source->stream.r_ptr; + int32_t *src = (int32_t *)vol_state->sources[0]->stream.r_ptr; int i; int sign = 1; - for (i = 0; i < vol_state->source->stream.size / sizeof(int32_t); i++) { + for (i = 0; i < vol_state->sources[0]->stream.size / sizeof(int32_t); i++) { val = (INT24_MIN + (i >> 1)) * sign; val = (val > INT24_MAX) ? INT24_MAX : val; src[i] = (int32_t)val; @@ -197,17 +163,17 @@ static void fill_source_s24(struct vol_test_state *vol_state) } } -static void verify_s24_to_s24_s32(struct comp_dev *dev, +static void verify_s24_to_s24_s32(struct processing_module *mod, struct comp_buffer *sink, struct comp_buffer *source) { - struct comp_data *cd = comp_get_drvdata(dev); + struct vol_data *cd = module_get_private_data(mod); const int32_t *src = (int32_t *)source->stream.r_ptr; const int32_t *dst = (int32_t *)sink->stream.w_ptr; double processed; int32_t dst_sample; int32_t sample; - int channels = sink->stream.channels; + int channels = audio_stream_get_channels(&sink->stream); int channel; int delta; int i; @@ -239,14 +205,14 @@ static void verify_s24_to_s24_s32(struct comp_dev *dev, #endif /* CONFIG_FORMAT_S24LE */ #if CONFIG_FORMAT_S32LE -static void fill_source_s32(struct vol_test_state *vol_state) +static void fill_source_s32(struct processing_module_test_data *vol_state) { int64_t val; - int32_t *src = (int32_t *)vol_state->source->stream.r_ptr; + int32_t *src = (int32_t *)vol_state->sources[0]->stream.r_ptr; int i; int sign = 1; - for (i = 0; i < vol_state->source->stream.size / sizeof(int32_t); i++) { + for (i = 0; i < vol_state->sources[0]->stream.size / sizeof(int32_t); i++) { val = (INT32_MIN + (i >> 1)) * sign; val = (val > INT32_MAX) ? INT32_MAX : val; src[i] = (int32_t)val; @@ -254,17 +220,17 @@ static void fill_source_s32(struct vol_test_state *vol_state) } } -static void verify_s32_to_s24_s32(struct comp_dev *dev, +static void verify_s32_to_s24_s32(struct processing_module *mod, struct comp_buffer *sink, struct comp_buffer *source) { - struct comp_data *cd = comp_get_drvdata(dev); + struct vol_data *cd = module_get_private_data(mod); double processed; const int32_t *src = (int32_t *)source->stream.r_ptr; const int32_t *dst = (int32_t *)sink->stream.w_ptr; int32_t dst_sample; int32_t sample; - int channels = sink->stream.channels; + int channels = audio_stream_get_channels(&sink->stream); int channel; int delta; int i; @@ -295,101 +261,13 @@ static void verify_s32_to_s24_s32(struct comp_dev *dev, } #endif /* CONFIG_FORMAT_S32LE */ -#if 0 - -#if CONFIG_FORMAT_S16LE && (CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE) -static void verify_s16_to_sX(struct comp_dev *dev, struct comp_buffer *sink, - struct comp_buffer *source) -{ - struct comp_data *cd = comp_get_drvdata(dev); - const int16_t *src = (int16_t *)source->r_ptr; - const int32_t *dst = (int32_t *)sink->w_ptr; - double processed; - int32_t dst_sample; - int32_t sample; - int channels = sink->channels; - int channel; - int delta; - int i; - int shift = 0; - - /* get shift value */ - if (cd->sink_format == SOF_IPC_FRAME_S24_4LE) - shift = 8; - else if (cd->sink_format == SOF_IPC_FRAME_S32_LE) - shift = 0; - - for (i = 0; i < sink->size / sizeof(uint32_t); i += channels) { - for (channel = 0; channel < channels; channel++) { - processed = 65536.0 * (double)src[i + channel] * - (double)cd->volume[channel] / - (double)VOL_ZERO_DB + 0.5 * (1 << shift); - if (processed > INT32_MAX) - processed = INT32_MAX; - - if (processed < INT32_MIN) - processed = INT32_MIN; - - sample = ((int32_t)processed) >> shift; - dst_sample = dst[i + channel]; - delta = dst_sample - sample; - if (delta > 1 || delta < -1) - assert_int_equal(dst_sample, sample); - - if (shift && (dst_sample < INT24_MIN || - dst_sample > INT24_MAX)) - assert_int_equal(dst_sample, sample); - } - } -} - -static void verify_sX_to_s16(struct comp_dev *dev, struct comp_buffer *sink, - struct comp_buffer *source) -{ - struct comp_data *cd = comp_get_drvdata(dev); - const int32_t *src = (int32_t *)source->r_ptr; - const int16_t *dst = (int16_t *)sink->w_ptr; - double processed; - int channels = dev->params.channels; - int channel; - int delta; - int i; - int shift = 0; - int16_t sample; - - /* get shift value */ - if (cd->source_format == SOF_IPC_FRAME_S24_4LE) - shift = 8; - - for (i = 0; i < sink->size / sizeof(uint16_t); i += channels) { - for (channel = 0; channel < channels; channel++) { - processed = (double)(src[i + channel] << shift) * - (double)cd->volume[channel] / - (double)VOL_ZERO_DB; - processed = processed / 65536.0 + 0.5; - if (processed > INT16_MAX) - processed = INT16_MAX; - - if (processed < INT16_MIN) - processed = INT16_MIN; - - sample = (int16_t)processed; - delta = dst[i + channel] - sample; - if (delta > 1 || delta < -1) - assert_int_equal(dst[i + channel], sample); - } - } -} -#endif /* CONFIG_FORMAT_S16LE && (CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE) */ - -#endif - static void test_audio_vol(void **state) { - struct vol_test_state *vol_state = *state; - struct comp_data *cd = comp_get_drvdata(vol_state->dev); + struct processing_module_test_data *vol_state = *state; + struct processing_module *mod = vol_state->mod; + struct vol_data *cd = module_get_private_data(mod); - switch (vol_state->sink->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&vol_state->sinks[0]->stream)) { case SOF_IPC_FRAME_S16_LE: fill_source_s16(vol_state); break; @@ -400,50 +278,57 @@ static void test_audio_vol(void **state) case SOF_IPC_FRAME_FLOAT: fill_source_s32(vol_state); break; + + /* TODO: add 3LE support */ + /* TODO: add 4LE_MSB support */ + /* TODO: add U8 support */ + default: + break; } - cd->scale_vol(vol_state->dev, &vol_state->sink->stream, - &vol_state->source->stream, vol_state->dev->frames); + vol_state->input_buffers[0]->consumed = 0; + vol_state->output_buffers[0]->size = 0; - vol_state->verify(vol_state->dev, vol_state->sink, vol_state->source); + cd->scale_vol(mod, vol_state->input_buffers[0], vol_state->output_buffers[0], + mod->dev->frames, cd->attenuation); + + vol_state->verify(mod, vol_state->sinks[0], vol_state->sources[0]); } -static struct vol_test_parameters parameters[] = { +static struct processing_module_test_parameters test_parameters[] = { #if CONFIG_FORMAT_S16LE - { VOL_MAX, 2, 48, 1, SOF_IPC_FRAME_S16_LE, - SOF_IPC_FRAME_S16_LE, verify_s16_to_s16 }, /* 1 */ - { VOL_ZERO_DB, 2, 48, 1, SOF_IPC_FRAME_S16_LE, - SOF_IPC_FRAME_S16_LE, verify_s16_to_s16 }, /* 2 */ - { VOL_MINUS_80DB, 2, 48, 1, SOF_IPC_FRAME_S16_LE, - SOF_IPC_FRAME_S16_LE, verify_s16_to_s16 }, /* 3 */ + { 2, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16_to_s16 }, #endif /* CONFIG_FORMAT_S16LE */ #if CONFIG_FORMAT_S24LE - { VOL_MAX, 2, 48, 1, SOF_IPC_FRAME_S24_4LE, - SOF_IPC_FRAME_S24_4LE, verify_s24_to_s24_s32 }, /* 4 */ - { VOL_ZERO_DB, 2, 48, 1, SOF_IPC_FRAME_S24_4LE, - SOF_IPC_FRAME_S24_4LE, verify_s24_to_s24_s32 }, /* 5 */ - { VOL_MINUS_80DB, 2, 48, 1, SOF_IPC_FRAME_S24_4LE, - SOF_IPC_FRAME_S24_4LE, verify_s24_to_s24_s32 }, /* 6 */ + { 2, 48, 1, SOF_IPC_FRAME_S24_4LE, + SOF_IPC_FRAME_S24_4LE, verify_s24_to_s24_s32 }, #endif /* CONFIG_FORMAT_S24LE */ #if CONFIG_FORMAT_S32LE - { VOL_MAX, 2, 48, 1, SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_S32_LE, verify_s32_to_s24_s32 }, /* 7 */ - { VOL_ZERO_DB, 2, 48, 1, SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_S32_LE, verify_s32_to_s24_s32 }, /* 8 */ - { VOL_MINUS_80DB, 2, 48, 1, SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_S32_LE, verify_s32_to_s24_s32 }, /* 9 */ + { 2, 48, 1, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, verify_s32_to_s24_s32 }, #endif /* CONFIG_FORMAT_S32LE */ }; int main(void) { - int i; + struct vol_test_parameters *parameters; + uint32_t volume_values[] = {VOL_MAX, VOL_ZERO_DB, VOL_MINUS_80DB}; + int num_tests = ARRAY_SIZE(test_parameters) * ARRAY_SIZE(volume_values); + int i, j, ret; + + parameters = test_calloc(num_tests, sizeof(struct vol_test_parameters)); + for (i = 0; i < ARRAY_SIZE(test_parameters); i++) { + for (j = 0; j < ARRAY_SIZE(volume_values); j++) { + parameters[i * ARRAY_SIZE(test_parameters) + j].volume = volume_values[j]; + parameters[i * ARRAY_SIZE(test_parameters) + j].module_parameters = + test_parameters[i]; + } + } - struct CMUnitTest tests[ARRAY_SIZE(parameters)]; + struct CMUnitTest tests[num_tests]; - for (i = 0; i < ARRAY_SIZE(parameters); i++) { + for (i = 0; i < num_tests; i++) { tests[i].name = "test_audio_vol"; tests[i].test_func = test_audio_vol; tests[i].setup_func = setup; @@ -453,5 +338,9 @@ int main(void) cmocka_set_message_output(CM_OUTPUT_TAP); - return cmocka_run_group_tests(tests, NULL, NULL); + ret = cmocka_run_group_tests(tests, NULL, NULL); + + test_free(parameters); + + return ret; } diff --git a/test/cmocka/src/common_mocks.c b/test/cmocka/src/common_mocks.c index ad60c88057f1..16fee8f2ff48 100644 --- a/test/cmocka/src/common_mocks.c +++ b/test/cmocka/src/common_mocks.c @@ -6,7 +6,23 @@ // Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> #include <errno.h> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> +#include <rtos/timer.h> +#include <sof/lib/mm_heap.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/driver.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/schedule.h> +#include <user/trace.h> +#include <rtos/spinlock.h> +#include <sof/audio/component_ext.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <rtos/clk.h> +#include <sof/lib/notifier.h> +#include <rtos/wait.h> +#include <arch/lib/cpu.h> #include <stdlib.h> #include <stdarg.h> #include <stddef.h> @@ -16,32 +32,46 @@ #define WEAK __attribute__((weak)) -void WEAK *_balloc(uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment) +/* global contexts */ +WEAK struct ipc *_ipc; +WEAK struct timer *platform_timer; +WEAK struct schedulers *schedulers; +WEAK struct sof sof; +WEAK struct tr_ctx buffer_tr; +WEAK struct tr_ctx comp_tr; +WEAK struct tr_ctx ipc_tr; + +int host_trace_level = LOG_LEVEL_ERROR; + +void WEAK *rballoc_align(uint32_t flags, size_t bytes, + uint32_t alignment) { (void)flags; - (void)caps; - return malloc(bytes); + return calloc(bytes, 1); } -void WEAK *_zalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, +void WEAK *rzalloc(uint32_t flags, size_t bytes) { - (void)zone; (void)flags; - (void)caps; return calloc(bytes, 1); } -void WEAK *_brealloc(void *ptr, uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment) +void WEAK *rmalloc_align(uint32_t flags, size_t bytes, uint32_t alignment) { (void)flags; - (void)caps; + (void)alignment; - return realloc(ptr, bytes); + return malloc(bytes); +} + +void WEAK *rmalloc(uint32_t flags, size_t bytes) +{ + (void)flags; + + return malloc(bytes); } void WEAK rfree(void *ptr) @@ -49,39 +79,470 @@ void WEAK rfree(void *ptr) free(ptr); } +void WEAK *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment) +{ + void *ret; + (void)mod; + (void)alignment; + + ret = malloc(size); + + assert(ret); + + return ret; +} + +void WEAK *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, + size_t alignment) +{ + void *ret; + (void)mod; + (void)flags; + (void)alignment; + + ret = malloc(size); + + assert(ret); + + return ret; +} + +int WEAK mod_free(struct processing_module *mod, const void *ptr) +{ + (void)mod; + free((void *)ptr); + return 0; +} + +struct k_heap * WEAK sof_sys_heap_get(void) +{ + return NULL; +} + +void WEAK *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + (void)heap; + (void)flags; + (void)alignment; + + return malloc(bytes); +} + +void WEAK sof_heap_free(struct k_heap *heap, void *addr) +{ + (void)heap; + + free(addr); +} + int WEAK memcpy_s(void *dest, size_t dest_size, - const void *src, size_t src_size) + const void *src, size_t count) { if (!dest || !src) return -EINVAL; - if ((dest >= src && (char *)dest < ((char *)src + src_size)) || + if ((dest >= src && (char *)dest < ((char *)src + count)) || (src >= dest && (char *)src < ((char *)dest + dest_size))) return -EINVAL; - if (src_size > dest_size) + if (count > dest_size) + return -EINVAL; + + memcpy(dest, src, count); + + return 0; +} + +int WEAK memset_s(void *dest, size_t size1, + int c, size_t size2) +{ + if (!dest) return -EINVAL; - memcpy(dest, src, src_size); + memset(dest, c, size1); return 0; } -void WEAK __panic(uint32_t p, char *filename, uint32_t linenum) +int WEAK rstrlen(const char *s) +{ + return strlen(s); +} + +void WEAK __panic(uint32_t p, const char *filename, uint32_t linenum) { - fail_msg("panic: %s:%d (code 0x%X)\n", filename, linenum, p); + fail_msg("panic: %s:%d (code 0x%x)\n", filename, linenum, p); + exit(EXIT_FAILURE); } -uint32_t WEAK _spin_lock_irq(spinlock_t *lock) +#if CONFIG_TRACE +void WEAK trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx, + uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count, + va_list args) { - (void)lock; + (void) send_atomic; + (void) log_entry; + (void) ctx; + (void) lvl; + (void) id_1; + (void) id_2; + (void) arg_count; + (void) args; +} +void WEAK _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry, + const struct tr_ctx *ctx, const uint32_t lvl, + uint32_t id_1, uint32_t id_2, int arg_count, ...) +{ +} + +void WEAK trace_flush_dma_to_mbox(void) +{ +} +#endif + +#if CONFIG_LIBRARY +volatile void *task_context_get(void); +#endif +volatile void * WEAK task_context_get(void) +{ + return NULL; +} + +uint64_t WEAK platform_timer_get(struct timer *timer) +{ + (void)timer; + + return 0; +} + +#if !CONFIG_LIBRARY +uint64_t WEAK arch_timer_get_system(struct timer *timer) +{ + (void)timer; + + return 0; +} +#endif + +#if CONFIG_LIBRARY +void WEAK arch_dump_regs_a(void *dump_buf); +#endif +void WEAK arch_dump_regs_a(void *dump_buf) +{ + (void)dump_buf; +} + +void WEAK heap_trace_all(int force) +{ + (void)force; +} + +void WEAK ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) +{ + (void)msg; + (void)data; + (void)high_priority; +} + +int WEAK platform_ipc_init(struct ipc *ipc) +{ return 0; } -void WEAK _spin_unlock_irq(spinlock_t *lock, uint32_t flags, int line) +enum task_state WEAK ipc_platform_do_cmd(struct ipc *ipc) +{ + return 0; +} + +void WEAK ipc_platform_complete_cmd(struct ipc *ipc) +{ +} + +#if !CONFIG_LIBRARY +int WEAK ipc_platform_send_msg(const struct ipc_msg *msg) +{ + return 0; +} + +void WEAK wait_delay(uint64_t number_of_clks) +{ +} + +void WEAK wait_delay_ms(uint64_t ms) +{ +} + +void WEAK wait_delay_us(uint64_t us) +{ +} + +void WEAK xthal_icache_region_invalidate(void *addr, unsigned size) +{ +} + +void WEAK xthal_dcache_region_invalidate(void *addr, unsigned size) +{ +} + +void WEAK xthal_dcache_region_writeback(void *addr, unsigned size) +{ +} + +void WEAK xthal_dcache_region_writeback_inv(void *addr, unsigned size) +{ +} +#endif + +struct sof * WEAK sof_get(void) +{ + return &sof; +} + +struct schedulers ** WEAK arch_schedulers_get(void) +{ + return &schedulers; +} + +int WEAK schedule_task_init(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) { - (void)lock; + (void)task; + (void)uid; + (void)type; + (void)priority; + (void)run; + (void)data; + (void)core; (void)flags; - (void)line; + + return 0; +} + +int WEAK schedule_task_init_ll(struct task *task, + const struct sof_uuid_entry *uid, uint16_t type, + uint16_t priority, enum task_state (*run)(void *data), + void *data, uint16_t core, uint32_t flags) +{ + return 0; +} + +void WEAK platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + (void)host; + (void)posn; +} + +void WEAK platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + (void)dai; + (void)posn; +} + +struct ipc_comp_dev *WEAK ipc_get_comp_dev(struct ipc *ipc, uint16_t type, uint32_t id) +{ + (void)ipc; + (void)type; + (void)id; + + return NULL; +} + +struct ipc_comp_dev *WEAK ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, + uint32_t ppl_id, uint32_t ignore_remote) +{ + (void)ipc; + (void)type; + (void)ppl_id; + (void)ignore_remote; + + return NULL; +} + +uint32_t WEAK crc32(uint32_t base, const void *data, uint32_t bytes) +{ + return 0; +} + +int WEAK comp_set_state(struct comp_dev *dev, int cmd) +{ + return 0; +} + +uint64_t WEAK clock_ms_to_ticks(int clock, uint64_t ms) +{ + (void)clock; + (void)ms; + + return 0; +} + +uint64_t WEAK clock_us_to_ticks(int clock, uint64_t us) +{ + (void)clock; + (void)us; + + return 0; +} + +uint64_t WEAK clock_ns_to_ticks(int clock, uint64_t us) +{ + (void)clock; + (void)us; + + return 0; +} + +#if CONFIG_MULTICORE && !CONFIG_LIBRARY + +int WEAK idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + (void)msg; + (void)mode; + + return 0; +} + +int WEAK arch_cpu_is_core_enabled(int id) +{ + return 0; +} + +#endif + +#if CONFIG_LIBRARY +/* enable trace by default in testbench */ +int WEAK test_bench_trace = 1; +int WEAK debug; + +/* ... but not always in unit tests */ +#if CONFIG_TRACE +/* look up subsystem class name from table */ +char * WEAK get_trace_class(uint32_t trace_class) +{ + (void)trace_class; + /* todo: trace class is deprecated, + * uuid should be used only + */ + return "unknown"; +} +#endif + +uint8_t * WEAK get_library_mailbox(void) +{ + return NULL; +} +#endif + +/* + * GCC xtensa requires us to fake some of the standard C library calls + * as this is "bare metal" support (i.e. with no host OS implementation + * methods for these calls). + * + * None of these IO calls are used in the Mocks for testing. + */ +#if !CONFIG_LIBRARY && !__XCC__ +void _exit(int status); +unsigned int _getpid_r(void); +int _kill_r(int id, int sig); +void _sbrk_r(int id); +int _fstat_r(int fd, void *buf); +int _open_r(const char *pathname, int flags); +int _write_r(int fd, char *buf, int count); +int _read_r(int fd, char *buf, int count); +int _lseek_r(int fd, int count); +int _close_r(int fd); +int _isatty(int fd); + +void _exit(int status) +{ + while (1); +} + +unsigned int _getpid_r(void) +{ + return 0; +} + +int _kill_r(int id, int sig) +{ + return 0; +} + +void _sbrk_r(int id) +{ +} + +int _fstat_r(int fd, void *buf) +{ + return 0; +} + +int _open_r(const char *pathname, int flags) +{ + return 0; +} + +int _write_r(int fd, char *buf, int count) +{ + return 0; +} + +int _read_r(int fd, char *buf, int count) +{ + return 0; +} + +int _lseek_r(int fd, int count) +{ + return 0; +} + +int _close_r(int fd) +{ + return 0; +} + +int _isatty(int fd) +{ + return 0; +} + +/* TODO: work around some linker warnings. Both will need fixed for qemu. */ +int _start = 0; +int *__errno _PARAMS ((void)); + +/* + * TODO: Math support for GCC xtensa requires a little more work to use the + * newlib versions. This is just to build test only today ! + */ +double __floatsidf(int i); +double __divdf3(double a, double b); +int __ledf2(double a, double b); +int __eqdf2(double a, double b); + +double __floatsidf(int i) +{ + return i; +} + +double __divdf3(double a, double b) +{ + return a / b; +} + +int WEAK __ledf2(double a, double b) +{ + return a <= b ? 0 : 1; +} + +int WEAK __eqdf2(double a, double b) +{ + return a == b ? 0 : 1; } +#endif diff --git a/test/cmocka/src/debugability/CMakeLists.txt b/test/cmocka/src/debugability/CMakeLists.txt deleted file mode 100644 index 6c23edb4f80a..000000000000 --- a/test/cmocka/src/debugability/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmocka_test(debugability_macros - macros.c -) diff --git a/test/cmocka/src/debugability/macros.c b/test/cmocka/src/debugability/macros.c deleted file mode 100644 index e4f7af3c7c55..000000000000 --- a/test/cmocka/src/debugability/macros.c +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <sof/lib/alloc.h> - -#include <stdio.h> -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <malloc.h> -#include <cmocka.h> - -#include <sof/trace/preproc.h> -#include <sof/sof.h> -#include <sof/trace/trace.h> -#include <user/trace.h> - -#define CAPTURE(aggr, ...)\ - META_RECURSE(META_MAP(1, META_QUOTE, aggr, __VA_ARGS__)) - -static void test_debugability_macros_declare_log_entry(void **state) -{ - const char *macro_result = CAPTURE(_DECLARE_LOG_ENTRY( - LOG_LEVEL_CRITICAL, - "Message", - TRACE_CLASS_DMA, - 1 - )); - const char *should_be_eq = - "__attribute__((section(\".static_log.\"" - " \"LOG_LEVEL_CRITICAL\"))) " - "static const struct " - "{ " - "uint32_t level; " - "uint32_t component_class; " - "uint32_t params_num; " - "uint32_t line_idx; " - "uint32_t file_name_len; " - "uint32_t text_len; " - "const char file_name[sizeof(\"" RELATIVE_FILE "\")]; " - "const char text[sizeof(\"Message\")]; " - "} log_entry = { " - "1" - "(6 << 24)" - "1" - "31" - "sizeof(\"" RELATIVE_FILE "\")" - "sizeof(\"Message\")" - "\"" RELATIVE_FILE "\"" - "\"Message\" " - "}"; - (void)state; - assert_string_equal(macro_result, should_be_eq); -} - -static char *get_param_list(const int param_count) -{ - char *result = malloc(sizeof(char) * 128); - int current; - - strcpy(result, ""); - for (current = 0; current < param_count; ++current) { - char newparam[11]; - - sprintf(newparam, ", param%d", current); - strcat(result, newparam); - } - return result; -} - -static char *get_should_be(const int param_count) -{ - char *result = malloc(sizeof(char) * 1024); - char *paramlist = get_param_list(param_count); - - /* which format: 0 1 2 3 4 5 6 7 8*/ - sprintf(result, "%s%d%s%d%s%d%s%s%s", - /*0*/"{ __attribute__((unused)) typedef char assertion_failed_" - META_QUOTE(BASE_LOG_ASSERT_FAIL_MSG) - "[(", - /*1*/_TRACE_EVENT_MAX_ARGUMENT_COUNT, - /*2*/" >= ", - /*3*/param_count, - /*4*/") ? 1 : -1]; _trace_event", - /*5*/param_count, - /*6*/" ((uint32_t)&log_entry, 0, 1, 1", - /*7*/paramlist, - /*8*/"); }" - ); - if (paramlist) - free(paramlist); - // TODO: maybe remove all whitespace chars; they're not important here - return result; -} - -#define test_debugability_macros_base_base(...) \ -do { \ - _DECLARE_LOG_ENTRY( \ - LOG_LEVEL_CRITICAL, \ - "Message", \ - TRACE_CLASS_DMA, \ - META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__) \ - ); \ - const char *macro_result = CAPTURE(BASE_LOG( \ - _trace_event, \ - 0, \ - 1, \ - 1, \ - &log_entry, \ - ##__VA_ARGS__ \ - )); \ - char *should_be_eq = get_should_be( \ - META_COUNT_VARAGS_BEFORE_COMPILE(__VA_ARGS__)); \ - \ - /* to avoid "log_entry not used" warning */ \ - assert_true(log_entry.level == log_entry.level); \ - \ - (void)state; \ - \ - assert_string_equal(macro_result, should_be_eq); \ - if (should_be_eq) \ - free(should_be_eq); \ -} while (0) - -#define TEST_FUNC_(param_count, ...) \ -static void META_CONCAT_SEQ_DELIM_( \ - test_debugability_macros_base_log, \ - param_count, \ - params) \ -(void **state) \ -{ \ - test_debugability_macros_base_base(__VA_ARGS__);\ -} - -TEST_FUNC_(0,) -TEST_FUNC_(1, param0) -TEST_FUNC_(2, param0, param1) -TEST_FUNC_(3, param0, param1, param2) -TEST_FUNC_(4, param0, param1, param2, param3) -TEST_FUNC_(5, param0, param1, param2, param3, param4) -#undef TEST_FUNC_ -#undef CAPTURE - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_debugability_macros_declare_log_entry), - cmocka_unit_test(test_debugability_macros_base_log_0_params), - cmocka_unit_test(test_debugability_macros_base_log_1_params), - cmocka_unit_test(test_debugability_macros_base_log_2_params), - cmocka_unit_test(test_debugability_macros_base_log_3_params), - cmocka_unit_test(test_debugability_macros_base_log_4_params), - cmocka_unit_test(test_debugability_macros_base_log_5_params), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/lib/CMakeLists.txt b/test/cmocka/src/lib/CMakeLists.txt index f6d4a6dc878c..ad3788bc98f0 100644 --- a/test/cmocka/src/lib/CMakeLists.txt +++ b/test/cmocka/src/lib/CMakeLists.txt @@ -2,4 +2,4 @@ add_subdirectory(alloc) add_subdirectory(lib) -add_subdirectory(preproc) +add_subdirectory(fast-get) diff --git a/test/cmocka/src/lib/alloc/CMakeLists.txt b/test/cmocka/src/lib/alloc/CMakeLists.txt index b08c55d985d0..c9ba91a9a1d7 100644 --- a/test/cmocka/src/lib/alloc/CMakeLists.txt +++ b/test/cmocka/src/lib/alloc/CMakeLists.txt @@ -1,12 +1,21 @@ # SPDX-License-Identifier: BSD-3-Clause -cmocka_test(alloc - alloc.c - mock.c - ${PROJECT_SOURCE_DIR}/src/lib/alloc.c - ${PROJECT_SOURCE_DIR}/src/debug/panic.c - ${PROJECT_SOURCE_DIR}/src/platform/intel/cavs/lib/memory.c - ${PROJECT_SOURCE_DIR}/src/spinlock.c -) +if(BUILD_UNIT_TESTS_HOST) + cmocka_test(alloc + alloc.c + ${PROJECT_SOURCE_DIR}/src/lib/alloc.c + ${PROJECT_SOURCE_DIR}/src/platform/library/lib/memory.c + ) +else() + if(CONFIG_CAVS) + set(MEMORY_FILE ${PROJECT_SOURCE_DIR}/src/platform/intel/cavs/lib/memory.c) + endif() + cmocka_test(alloc + alloc.c + ${PROJECT_SOURCE_DIR}/src/lib/alloc.c + ${PROJECT_SOURCE_DIR}/src/debug/panic.c + ${MEMORY_FILE} + ) +endif() target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/intel/cavs/include) diff --git a/test/cmocka/src/lib/alloc/alloc.c b/test/cmocka/src/lib/alloc/alloc.c index ee466dd02d22..d666141c45b2 100644 --- a/test/cmocka/src/lib/alloc/alloc.c +++ b/test/cmocka/src/lib/alloc/alloc.c @@ -11,8 +11,10 @@ #include <setjmp.h> #include <cmocka.h> -#include <sof/sof.h> -#include <sof/lib/alloc.h> +#include <rtos/sof.h> +#include <rtos/alloc.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> #include <ipc/header.h> #include <ipc/topology.h> @@ -24,46 +26,43 @@ enum test_type { struct test_case { size_t alloc_size; - int alloc_zone; - uint32_t alloc_caps; + uint32_t alloc_flags; uint16_t alloc_num; enum test_type type; const char *name; }; -#define TEST_CASE(bytes, zone, caps, num, type, name_base) \ - {(bytes), (zone), (caps), (num), (type), \ - ("test_lib_alloc_" name_base "__" #zone "__" #bytes "x" #num)} +#define TEST_CASE(bytes, flags, num, type, name_base) \ + {(bytes), (flags), (num), (type), \ + ("test_lib_alloc_" name_base "__" #flags "__" #bytes "x" #num)} static struct test_case test_cases[] = { /* * rmalloc tests */ - TEST_CASE(1, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 2, TEST_BULK, + TEST_CASE(1, SOF_MEM_FLAG_USER, 2, TEST_BULK, "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 2, TEST_BULK, + TEST_CASE(4, SOF_MEM_FLAG_USER, 2, TEST_BULK, "rmalloc"), - TEST_CASE(256, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 2, TEST_BULK, + TEST_CASE(256, SOF_MEM_FLAG_USER, 2, TEST_BULK, "rmalloc"), - TEST_CASE(1, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 4, TEST_BULK, + TEST_CASE(1, SOF_MEM_FLAG_USER, 4, TEST_BULK, "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 4, TEST_BULK, + TEST_CASE(4, SOF_MEM_FLAG_USER, 4, TEST_BULK, "rmalloc"), - TEST_CASE(256, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 4, TEST_BULK, + TEST_CASE(256, SOF_MEM_FLAG_USER, 4, TEST_BULK, "rmalloc"), - TEST_CASE(1, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 8, TEST_BULK, + TEST_CASE(1, SOF_MEM_FLAG_USER, 8, TEST_BULK, "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 8, TEST_BULK, + TEST_CASE(4, SOF_MEM_FLAG_USER, 8, TEST_BULK, "rmalloc"), - TEST_CASE(256, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 8, TEST_BULK, + TEST_CASE(256, SOF_MEM_FLAG_USER, 8, TEST_BULK, "rmalloc"), - TEST_CASE(16, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 128, TEST_BULK, - "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 256, TEST_BULK, + TEST_CASE(16, SOF_MEM_FLAG_USER, 128, TEST_BULK, "rmalloc"), /* @@ -71,143 +70,95 @@ static struct test_case test_cases[] = { * the RZONE_BUFFER and RZONE_RUNTIME tests will not work. */ - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 2, TEST_BULK, + TEST_CASE(1, SOF_MEM_FLAG_USER, 2, TEST_BULK, "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 2, TEST_BULK, + TEST_CASE(4, SOF_MEM_FLAG_USER, 2, TEST_BULK, "rmalloc"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 2, TEST_BULK, + TEST_CASE(256, SOF_MEM_FLAG_USER, 2, TEST_BULK, "rmalloc"), - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 4, TEST_BULK, + TEST_CASE(1, SOF_MEM_FLAG_USER, 4, TEST_BULK, "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 4, TEST_BULK, + TEST_CASE(4, SOF_MEM_FLAG_USER, 4, TEST_BULK, "rmalloc"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 4, TEST_BULK, + TEST_CASE(256, SOF_MEM_FLAG_USER, 4, TEST_BULK, "rmalloc"), - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 8, TEST_BULK, + TEST_CASE(1, SOF_MEM_FLAG_USER, 8, TEST_BULK, "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 8, TEST_BULK, + TEST_CASE(4, SOF_MEM_FLAG_USER, 8, TEST_BULK, "rmalloc"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 8, TEST_BULK, + TEST_CASE(256, SOF_MEM_FLAG_USER, 8, TEST_BULK, "rmalloc"), - TEST_CASE(16, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 128, TEST_BULK, - "rmalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 256, TEST_BULK, + TEST_CASE(16, SOF_MEM_FLAG_USER, 128, TEST_BULK, "rmalloc"), - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 2, TEST_BULK, "rmalloc_dma"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 2, TEST_BULK, "rmalloc_dma"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 2, TEST_BULK, "rmalloc_dma"), + TEST_CASE(1, (SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA), + 2, TEST_BULK, "rmalloc_dma"), + TEST_CASE(4, (SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA), + 2, TEST_BULK, "rmalloc_dma"), + TEST_CASE(256, (SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA), + 2, TEST_BULK, "rmalloc_dma"), /* * rzalloc tests */ - TEST_CASE(1, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 2, TEST_ZERO, + TEST_CASE(1, SOF_MEM_FLAG_USER, 2, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 2, TEST_ZERO, + TEST_CASE(4, SOF_MEM_FLAG_USER, 2, TEST_ZERO, "rzalloc"), - TEST_CASE(256, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 2, TEST_ZERO, + TEST_CASE(256, SOF_MEM_FLAG_USER, 2, TEST_ZERO, "rzalloc"), - TEST_CASE(1, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 4, TEST_ZERO, + TEST_CASE(1, SOF_MEM_FLAG_USER, 4, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 4, TEST_ZERO, + TEST_CASE(4, SOF_MEM_FLAG_USER, 4, TEST_ZERO, "rzalloc"), - TEST_CASE(256, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 4, TEST_ZERO, + TEST_CASE(256, SOF_MEM_FLAG_USER, 4, TEST_ZERO, "rzalloc"), - TEST_CASE(1, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 8, TEST_ZERO, + TEST_CASE(1, SOF_MEM_FLAG_USER, 8, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 8, TEST_ZERO, + TEST_CASE(4, SOF_MEM_FLAG_USER, 8, TEST_ZERO, "rzalloc"), - TEST_CASE(256, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 8, TEST_ZERO, + TEST_CASE(256, SOF_MEM_FLAG_USER, 8, TEST_ZERO, "rzalloc"), - TEST_CASE(16, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 128, TEST_ZERO, - "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_SYS, SOF_MEM_CAPS_RAM, 256, TEST_ZERO, + TEST_CASE(16, SOF_MEM_FLAG_USER, 128, TEST_ZERO, "rzalloc"), - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 2, TEST_ZERO, + TEST_CASE(1, SOF_MEM_FLAG_USER, 2, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 2, TEST_ZERO, + TEST_CASE(4, SOF_MEM_FLAG_USER, 2, TEST_ZERO, "rzalloc"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 2, TEST_ZERO, + TEST_CASE(256, SOF_MEM_FLAG_USER, 2, TEST_ZERO, "rzalloc"), - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 4, TEST_ZERO, + TEST_CASE(1, SOF_MEM_FLAG_USER, 4, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 4, TEST_ZERO, + TEST_CASE(4, SOF_MEM_FLAG_USER, 4, TEST_ZERO, "rzalloc"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 4, TEST_ZERO, + TEST_CASE(256, SOF_MEM_FLAG_USER, 4, TEST_ZERO, "rzalloc"), - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 8, TEST_ZERO, + TEST_CASE(1, SOF_MEM_FLAG_USER, 8, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 8, TEST_ZERO, + TEST_CASE(4, SOF_MEM_FLAG_USER, 8, TEST_ZERO, "rzalloc"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 8, TEST_ZERO, + TEST_CASE(256, SOF_MEM_FLAG_USER, 8, TEST_ZERO, "rzalloc"), - TEST_CASE(16, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 128, TEST_ZERO, + TEST_CASE(16, SOF_MEM_FLAG_USER, 128, TEST_ZERO, "rzalloc"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM, 256, TEST_ZERO, - "rzalloc"), - - TEST_CASE(1, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 2, TEST_ZERO, "rzalloc_dma"), - TEST_CASE(4, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 2, TEST_ZERO, "rzalloc_dma"), - TEST_CASE(256, SOF_MEM_ZONE_RUNTIME, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 2, TEST_ZERO, "rzalloc_dma"), - /* - * rballoc tests - */ - - TEST_CASE(4, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 1024, - TEST_IMMEDIATE_FREE, "rballoc"), - - TEST_CASE(1, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 2, TEST_BULK, - "rballoc"), - TEST_CASE(4, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 2, TEST_BULK, - "rballoc"), - TEST_CASE(256, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 2, TEST_BULK, - "rballoc"), - - TEST_CASE(1, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 4, TEST_BULK, - "rballoc"), - TEST_CASE(4, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 4, TEST_BULK, - "rballoc"), - TEST_CASE(256, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 4, TEST_BULK, - "rballoc"), - - TEST_CASE(1, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 8, TEST_BULK, - "rballoc"), - TEST_CASE(4, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 8, TEST_BULK, - "rballoc"), - TEST_CASE(256, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 8, TEST_BULK, - "rballoc"), - - TEST_CASE(16, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 64, TEST_BULK, - "rballoc"), - TEST_CASE(4, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM, 64, TEST_BULK, - "rballoc"), - - TEST_CASE(1, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, - 2, TEST_BULK, "rballoc_dma"), - TEST_CASE(4, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, - 2, TEST_BULK, "rballoc_dma"), - TEST_CASE(256, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM | SOF_MEM_CAPS_DMA, - 2, TEST_BULK, "rballoc_dma"), - TEST_CASE(2048, SOF_MEM_ZONE_BUFFER, SOF_MEM_CAPS_RAM | - SOF_MEM_CAPS_DMA, 100, TEST_IMMEDIATE_FREE, "rballoc_dma"), + TEST_CASE(1, (SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA), + 2, TEST_ZERO, "rzalloc_dma"), + TEST_CASE(4, (SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA), + 2, TEST_ZERO, "rzalloc_dma"), + TEST_CASE(256, (SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA), + 2, TEST_ZERO, "rzalloc_dma"), }; static int setup(void **state) @@ -242,11 +193,8 @@ static void *alloc(struct test_case *tc) { void *mem; - if (tc->alloc_zone == SOF_MEM_ZONE_BUFFER) - mem = rballoc(0, tc->alloc_caps, tc->alloc_size); - else - mem = rmalloc(tc->alloc_zone, 0, tc->alloc_caps, - tc->alloc_size); + mem = rmalloc(tc->alloc_flags, + tc->alloc_size); return mem; } @@ -255,10 +203,8 @@ static void alloc_free(void **mem, struct test_case *tc) { int i; - if (tc->alloc_zone != SOF_MEM_ZONE_SYS) { - for (i = 0; i < tc->alloc_num; ++i) - rfree(mem[i]); - } + for (i = 0; i < tc->alloc_num; ++i) + rfree(mem[i]); } static void test_lib_alloc_bulk_free(struct test_case *tc) @@ -296,7 +242,7 @@ static void test_lib_alloc_zero(struct test_case *tc) int i; for (i = 0; i < tc->alloc_num; ++i) { - char *mem = rzalloc(tc->alloc_zone, 0, tc->alloc_caps, + char *mem = rzalloc(tc->alloc_flags, tc->alloc_size); int j; diff --git a/test/cmocka/src/lib/alloc/mock.c b/test/cmocka/src/lib/alloc/mock.c deleted file mode 100644 index cf3e994a4027..000000000000 --- a/test/cmocka/src/lib/alloc/mock.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <stdint.h> - -#include <sof/lib/alloc.h> -#include <sof/trace/trace.h> -#include <sof/debug/panic.h> -#include <sof/schedule/task.h> - -#include <mock_trace.h> - -TRACE_IMPL() - -struct dma_copy; -struct dma_sg_config; - -static struct sof sof; - -void arch_dump_regs_a(void *dump_buf) -{ - (void)dump_buf; -} - -int rstrlen(const char *s) -{ - (void)s; - - return 0; -} - -void trace_flush(void) -{ -} - -volatile void *task_context_get(void) -{ - return NULL; -} - -struct sof *sof_get(void) -{ - return &sof; -} diff --git a/test/cmocka/src/lib/fast-get/CMakeLists.txt b/test/cmocka/src/lib/fast-get/CMakeLists.txt new file mode 100644 index 000000000000..8449320f4e6b --- /dev/null +++ b/test/cmocka/src/lib/fast-get/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(fast-get-tests + fast-get-tests.c + ${PROJECT_SOURCE_DIR}/src/lib/objpool.c + ${PROJECT_SOURCE_DIR}/zephyr/lib/fast-get.c + ${PROJECT_SOURCE_DIR}/src/lib/alloc.c + ${PROJECT_SOURCE_DIR}/src/platform/library/lib/memory.c +) + +target_link_libraries(fast-get-tests PRIVATE "-Wl,--wrap=rzalloc,--wrap=rmalloc,--wrap=rfree") diff --git a/test/cmocka/src/lib/fast-get/fast-get-tests.c b/test/cmocka/src/lib/fast-get/fast-get-tests.c new file mode 100644 index 000000000000..bd4a6fedfea3 --- /dev/null +++ b/test/cmocka/src/lib/fast-get/fast-get-tests.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Jyri Sarha <jyri.sarha@linux.intel.com> + +#include <sof/lib/fast-get.h> +#include <rtos/sof.h> +#include <rtos/alloc.h> +#include <sof/lib/mm_heap.h> +#include <sof/lib/memory.h> +#include <sof/common.h> + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <cmocka.h> +#include <assert.h> + +static const int testdata[33][100] = { + { + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + }, + { 2 }, + { 3 }, + { 4 }, + { 5 }, + { 6 }, + { 7 }, + { 8 }, + { 9 }, + { 10 }, + { 11 }, + { 12 }, + { 13 }, + { 14 }, + { 15 }, + { 16 }, + { 17 }, + { 18 }, + { 19 }, + { 20 }, + { 21 }, + { 23 }, + { 24 }, + { 25 }, + { 26 }, + { 27 }, + { 28 }, + { 29 }, + { 30 }, + { 31 }, + { 32 }, + { 33 }, +}; + +static void test_simple_fast_get_put(void **state) +{ + const void *ret; + + (void)state; /* unused */ + + ret = fast_get(NULL, testdata[0], sizeof(testdata[0])); + + assert(ret); + assert(!memcmp(ret, testdata[0], sizeof(testdata[0]))); + + fast_put(NULL, NULL, ret); +} + +static void test_fast_get_size_missmatch_test(void **state) +{ + const void *ret[2]; + + (void)state; /* unused */ + + ret[0] = fast_get(NULL, testdata[0], sizeof(testdata[0])); + + assert(ret[0]); + assert(!memcmp(ret[0], testdata[0], sizeof(testdata[0]))); + + ret[1] = fast_get(NULL, testdata[0], sizeof(testdata[0]) + 1); + assert(!ret[1]); + + fast_put(NULL, NULL, ret); +} + +static void test_over_32_fast_gets_and_puts(void **state) +{ + const void *copy[ARRAY_SIZE(testdata)]; + int i; + + (void)state; /* unused */ + + for (i = 0; i < ARRAY_SIZE(copy); i++) + copy[i] = fast_get(NULL, testdata[i], sizeof(testdata[0])); + + for (i = 0; i < ARRAY_SIZE(copy); i++) + assert(!memcmp(copy[i], testdata[i], sizeof(testdata[0]))); + + for (i = 0; i < ARRAY_SIZE(copy); i++) + fast_put(NULL, NULL, copy[i]); +} + +static void test_fast_get_refcounting(void **state) +{ + const void *copy[2][ARRAY_SIZE(testdata)]; + int i; + (void)state; /* unused */ + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + copy[0][i] = fast_get(NULL, testdata[i], sizeof(testdata[0])); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + copy[1][i] = fast_get(NULL, testdata[i], sizeof(testdata[0])); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + assert(copy[0][i] == copy[1][i]); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + assert(!memcmp(copy[0][i], testdata[i], sizeof(testdata[0]))); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + fast_put(NULL, NULL, copy[0][i]); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + assert(!memcmp(copy[1][i], testdata[i], sizeof(testdata[0]))); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + fast_put(NULL, NULL, copy[1][i]); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_simple_fast_get_put), + cmocka_unit_test(test_fast_get_size_missmatch_test), + cmocka_unit_test(test_over_32_fast_gets_and_puts), + cmocka_unit_test(test_fast_get_refcounting), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} + +void *__wrap_rzalloc(uint32_t flags, size_t bytes); +void *__wrap_rmalloc(uint32_t flags, size_t bytes); +void __wrap_rfree(void *ptr); + +void *__wrap_rzalloc(uint32_t flags, size_t bytes) +{ + void *ret; + (void)flags; + + ret = malloc(bytes); + + assert(ret); + + memset(ret, 0, bytes); + + return ret; +} + +void *__wrap_rmalloc(uint32_t flags, size_t bytes) +{ + void *ret; + (void)flags; + + ret = malloc(bytes); + + assert(ret); + + return ret; +} + +void __wrap_rfree(void *ptr) +{ + free(ptr); +} diff --git a/test/cmocka/src/lib/lib/CMakeLists.txt b/test/cmocka/src/lib/lib/CMakeLists.txt index 8f0c6880e39e..1287a1d14f94 100644 --- a/test/cmocka/src/lib/lib/CMakeLists.txt +++ b/test/cmocka/src/lib/lib/CMakeLists.txt @@ -9,8 +9,3 @@ cmocka_test(rstrlen rstrlen.c ${PROJECT_SOURCE_DIR}/src/lib/lib.c ) - -cmocka_test(strcheck - strcheck.c - ${PROJECT_SOURCE_DIR}/src/lib/lib.c -) diff --git a/test/cmocka/src/lib/lib/rstrcmp.c b/test/cmocka/src/lib/lib/rstrcmp.c index 27cbc9f6497c..8cde07bcd4a6 100644 --- a/test/cmocka/src/lib/lib/rstrcmp.c +++ b/test/cmocka/src/lib/lib/rstrcmp.c @@ -4,7 +4,7 @@ // // Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> #include <stdarg.h> #include <setjmp.h> diff --git a/test/cmocka/src/lib/lib/rstrlen.c b/test/cmocka/src/lib/lib/rstrlen.c index ac3db3620c42..71e9cf8b6248 100644 --- a/test/cmocka/src/lib/lib/rstrlen.c +++ b/test/cmocka/src/lib/lib/rstrlen.c @@ -4,7 +4,7 @@ // // Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> #include <stdarg.h> #include <setjmp.h> diff --git a/test/cmocka/src/lib/lib/strcheck.c b/test/cmocka/src/lib/lib/strcheck.c deleted file mode 100644 index 3da0f98f3820..000000000000 --- a/test/cmocka/src/lib/lib/strcheck.c +++ /dev/null @@ -1,367 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <sof/lib/alloc.h> -#include <sof/lib/dma.h> - -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <stdlib.h> -#include <malloc.h> -#include <cmocka.h> - -#include <test_group_generator.h> - -struct test_data_t { - size_t len; - char *before; - char *after; - char *func_ret; -}; - -struct test_data_change_t { - size_t beg; - size_t end; - size_t len; -}; - -static struct test_data_t *test_data; -static struct test_data_change_t *test_data_change; -static char default_char = 'a'; -static char change_char = 'b'; - -/* SETUP */ - -static int setup_change(void **state, - const size_t change_beg, const size_t change_end) -{ - setup_alloc(test_data_change, struct test_data_change_t, 1, 0); - - test_data_change->beg = change_beg; - test_data_change->end = change_end; - test_data_change->len = change_end - change_beg; - - if (test_data_change->len > test_data->len) - return -1; - - return 0; -} - -static int setup_test_data(void **state, const size_t len) -{ - setup_alloc(test_data, struct test_data_t, 1, 0); - - test_data->len = len; - test_data->before = NULL; - test_data->after = NULL; - - setup_alloc(test_data->before, char, (len + 1), 0); - setup_alloc(test_data->after, char, (len + 1), 0); - - int counter = test_data->len; - char *it = test_data->before; - - while (counter--) - *(it++) = default_char; - *it = 0; // null terminator - - return 0; -} - -static int _setup(void **state, size_t data_len, - size_t change_beg, size_t change_end) -{ - int result = 0; - - setup_part(result, setup_test_data(state, data_len)); - setup_part(result, setup_change(state, change_beg, change_end)); - - return 0; -} - -static int setup(void **state) -{ - return _setup(state, 8, 3, 6); -} - -static int teardown(void **state) -{ - free(test_data->before); - free(test_data->after); - free(test_data); - free(test_data_change); - - return 0; -} - -/* Test helper functions */ - -static void reset_test_arr(void) -{ - int counter = test_data->len; - char *p_bef = test_data->before; - char *p_aft = test_data->after; - - while (counter--) - (*p_aft++) = (*p_bef++); - - test_data->func_ret = NULL; -} - -static int check_arr(const char *arr, const size_t n, const char should_be) -{ - size_t i; - const char *it = arr; - - for (i = 0; i < n; ++i) - if ((*it++) != should_be) - return i; - return -1; -} - -static int check_arrs(const char *arr1, const char *arr2, const size_t n) -{ - size_t i; - const char *it1 = arr1; - const char *it2 = arr2; - - for (i = 0; i < n; ++i) - if ((*it1++) != (*it2++)) - return i; - return -1; -} - -static int check_test_arrs(void) -{ - return check_arrs( - test_data->before, - test_data->after, - test_data->len - ); -} - -static int check_test_arrs_with_offset(const size_t offset) -{ - return check_arrs( - test_data->before + offset, - test_data->after + offset, - test_data->len - offset - ); -} - -/* Tests */ - -static void test_lib_lib_strcheck_self_test_arrs_equal_neg1(void **state) -{ - const char *str1 = "aaa"; - const char *str2 = "aaa"; - const int len = 2; - - assert_int_equal( - check_arrs( - str1, - str2, - len - ), - -1 - ); -} - -static void test_lib_lib_strcheck_self_test_arrs_equal_1(void **state) -{ - const char str1[] = "aaa"; - const char str2[] = "aba"; - const int len = 4; - - assert_int_equal( - check_arrs( - str1, - str2, - len - ), - 1 - ); -} - -static void test_lib_lib_strcheck_self_no_change(void **state) -{ - reset_test_arr(); - - assert_int_equal( - check_test_arrs(), - -1 - ); -} - -/* don't change below function names; - *used as literals in macros generating test groups - */ -static void test_lib_lib_memset_change_base(void **state) -{ - reset_test_arr(); - - test_data->func_ret = memset( - test_data->after + test_data_change->beg, - change_char, - test_data_change->len - ); -} - -static void test_lib_lib_bzero_change_base(void **state) -{ - change_char = 0; - - reset_test_arr(); - - bzero( - test_data->after + test_data_change->beg, - test_data_change->len - ); -} - -static void test_lib_lib_memcpy_change_base(void **state) -{ - int counter = test_data_change->len; - char *src = malloc(sizeof(char) * counter); - char *ptr = src; - - reset_test_arr(); - - while (counter--) - *(ptr++) = change_char; - *ptr = 0; - - test_data->func_ret = memcpy( - test_data->after + test_data_change->beg, - src, - test_data_change->len - ); - - free(src); -} - -static void test_lib_lib_strcheck_change_ref_beg(void **state) -{ - const int expected = (test_data_change->len > 0) - ? test_data_change->beg - : -1; - assert_int_equal(expected, - check_test_arrs()); -} - -static void test_lib_lib_strcheck_change_ret_beg(void **state) -{ - const int expected = (test_data_change->len > 0) ? 0 : -1; - // baa - assert_int_equal(expected, - check_arrs(test_data->before + test_data_change->beg, - test_data->func_ret, - test_data->len - test_data_change->beg)); -} - -static void test_lib_lib_strcheck_change_ref_mid(void **state) -{ - assert_int_equal(-1, - check_arr(test_data->after + test_data_change->beg, - test_data_change->len, - change_char)); -} - -static void test_lib_lib_strcheck_change_ret_mid(void **state) -{ - assert_int_equal(-1, - check_arr(test_data->func_ret, - test_data_change->len, - change_char)); -} - -static void test_lib_lib_strcheck_change_ref_end(void **state) -{ - assert_int_equal(-1, - check_test_arrs_with_offset(test_data_change->end)); -} - -static void test_lib_lib_strcheck_change_ret_end(void **state) -{ - assert_int_equal(-1, - check_arrs(test_data->func_ret + test_data_change->len, - test_data->before + test_data_change->end, - test_data->len - test_data_change->end)); -} - -/* TEST GROUPS GENERATORS */ - -#define test_prefix_base test_lib_lib_strcheck_change -#define test_prefix_memset test_lib_lib_memset_change -#define test_prefix_bzero test_lib_lib_bzero_change -#define test_prefix_memcpy test_lib_lib_memcpy_change - -// here used are macros from "test_group_generator.h" -// define test configuration - which functions to test with -#define bind_test_group_ref_ret(bind, ...)\ - bind(ref_beg, __VA_ARGS__)\ - bind(ret_beg, __VA_ARGS__)\ - bind(ref_mid, __VA_ARGS__)\ - bind(ret_mid, __VA_ARGS__)\ - bind(ref_end, __VA_ARGS__)\ - bind(ret_end, __VA_ARGS__) - -#define bind_test_group_ref(bind, ...)\ - bind(ref_beg, __VA_ARGS__)\ - bind(ref_mid, __VA_ARGS__)\ - bind(ref_end, __VA_ARGS__) - -// combine test configurations with functions to test -#define bind_test_to_prefix(name, prefix_setup, action, ...)\ - action(test_prefix_base, prefix_setup, name, __VA_ARGS__) - -#define bind_test_group_memset(...)\ - bind_test_group_ref_ret(bind_test_to_prefix, \ - test_prefix_memset, __VA_ARGS__) - -#define bind_test_group_bzero(...)\ - bind_test_group_ref(bind_test_to_prefix, \ - test_prefix_bzero, __VA_ARGS__) - -#define bind_test_group_memcpy(...)\ - bind_test_group_ref_ret(bind_test_to_prefix, \ - test_prefix_memcpy, __VA_ARGS__) - -// define with what arguments to run test groups -#define run_test_group_action(action, bind_macro) \ - action(bind_macro, 3, 2, 2) /*change none characters*/\ - action(bind_macro, 5, 0, 1) /*change first character */\ - action(bind_macro, 7, 0, 7) /*change all characters*/\ - action(bind_macro, 9, 3, 6) /*change some characters*/\ - action(bind_macro, 2048, 512, 1024) /*change some character - long*/ - -// use macros to generate function bodies and create flags -run_test_group_action(flg_test_group, test_prefix_memset) -run_test_group_action(flg_test_group, test_prefix_bzero) -run_test_group_action(flg_test_group, test_prefix_memcpy) -run_test_group_action(gen_test_group, bind_test_group_memset) -run_test_group_action(gen_test_group, bind_test_group_bzero) -run_test_group_action(gen_test_group, bind_test_group_memcpy) - -/* TEST RUNNER */ - -int main(void) -{ - const struct CMUnitTest tests[] = { - c_u_t(test_lib_lib_strcheck_self_test_arrs_equal_neg1), - c_u_t(test_lib_lib_strcheck_self_test_arrs_equal_1), - c_u_t(test_lib_lib_strcheck_self_no_change), - - // use macros to fill array with generated function calls - run_test_group_action(use_test_group, bind_test_group_memset) - run_test_group_action(use_test_group, bind_test_group_bzero) - run_test_group_action(use_test_group, bind_test_group_memcpy) - }; - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, setup, teardown); -} diff --git a/test/cmocka/src/lib/preproc/CMakeLists.txt b/test/cmocka/src/lib/preproc/CMakeLists.txt deleted file mode 100644 index 2d4d1db0d9db..000000000000 --- a/test/cmocka/src/lib/preproc/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmocka_test(preproc_varargs_count - varargs_count.c -) - -cmocka_test(preproc_concat - concat.c -) - -cmocka_test(preproc_seq - seq.c -) - -cmocka_test(preproc_defer - defer.c -) - -cmocka_test(preproc_get_arg - get_arg.c -) diff --git a/test/cmocka/src/lib/preproc/concat.c b/test/cmocka/src/lib/preproc/concat.c deleted file mode 100644 index 853dc9af89e4..000000000000 --- a/test/cmocka/src/lib/preproc/concat.c +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <test_simple_macro.h> - -#include <sof/lib/alloc.h> -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -#include <sof/trace/preproc.h> -#include <sof/sof.h> - -#define TEST_PREFIX test_lib_preproc - -#define TEST_FUNC(prefix, test_func, postfix, should_be, ...)\ -static void META_CONCAT_SEQ_DELIM_(prefix, test_func, postfix)(void **state)\ -{\ - const int r = test_func(__VA_ARGS__);\ - (void)state;\ -\ - assert_int_equal(r, should_be);\ -} -#define A 1 -#define B 2 -#define C 3 - -TEST_HERE_DECLARE(META_CONCAT, 1_nothing, 1, A, ) -TEST_HERE_DECLARE(META_CONCAT, nothing_2, 2, , B ) -TEST_HERE_DECLARE(META_CONCAT, 1_2, 12, A, B ) -TEST_HERE_DECLARE(META_CONCAT_SEQ, 1_nothing, 1, A, ) -TEST_HERE_DECLARE(META_CONCAT_SEQ, nothing_2, 2, , B ) -TEST_HERE_DECLARE(META_CONCAT_SEQ, 1_2, 12, A, B ) -TEST_HERE_DECLARE(META_CONCAT_SEQ, 1_2_3, 123, A, B, C) - -#undef C -#undef B -#undef A -#undef TEST_FUNC - -int main(void) -{ - const struct CMUnitTest tests[] = { - TEST_HERE_USE(META_CONCAT, 1_nothing), - TEST_HERE_USE(META_CONCAT, nothing_2), - TEST_HERE_USE(META_CONCAT, 1_2 ), - - TEST_HERE_USE(META_CONCAT_SEQ, 1_nothing), - TEST_HERE_USE(META_CONCAT_SEQ, nothing_2), - TEST_HERE_USE(META_CONCAT_SEQ, 1_2 ), - TEST_HERE_USE(META_CONCAT_SEQ, 1_2_3 ), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#undef TEST_PREFIX diff --git a/test/cmocka/src/lib/preproc/defer.c b/test/cmocka/src/lib/preproc/defer.c deleted file mode 100644 index 645f68021191..000000000000 --- a/test/cmocka/src/lib/preproc/defer.c +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <test_simple_macro.h> - -#include <sof/lib/alloc.h> -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -#include <sof/trace/preproc.h> -#include <sof/sof.h> - -#define TEST_PREFIX test_lib_preproc - -#define TEST_FUNC(prefix, test_func, postfix, should_be, ...)\ -static void META_CONCAT_SEQ_DELIM_(prefix, test_func, postfix)(void **state)\ -{\ - const char *r = META_QUOTE(test_func(__VA_ARGS__));\ - (void)state;\ -\ - assert_string_equal(r, should_be);\ -} -#define TEST() FINAL - -TEST_HERE_DECLARE(META_DEFER, 0,\ - "TEST"\ - , 0, TEST) -TEST_HERE_DECLARE(META_DEFER, 1,\ - "TEST _META_EMPTY"\ - " ()"\ - , 1, TEST) -TEST_HERE_DECLARE(META_DEFER, 2,\ - "TEST _META_EMPTY _META_EMPTY"\ - " () ()"\ - , 2, TEST) -TEST_HERE_DECLARE(META_DEFER, 3,\ - "TEST _META_EMPTY _META_EMPTY _META_EMPTY"\ - " () () ()"\ - , 3, TEST) -TEST_HERE_DECLARE(META_DEFER, 4,\ - "TEST _META_EMPTY _META_EMPTY _META_EMPTY _META_EMPTY"\ - " () () () ()"\ - , 4, TEST) -TEST_HERE_DECLARE(META_DEFER, 5,\ - "TEST _META_EMPTY _META_EMPTY _META_EMPTY _META_EMPTY _META_EMPTY"\ - " () () () () ()"\ - , 5, TEST) - -#undef TEST -#undef TEST_FUNC - -int main(void) -{ - const struct CMUnitTest tests[] = { - TEST_HERE_USE(META_DEFER, 0), - TEST_HERE_USE(META_DEFER, 1), - TEST_HERE_USE(META_DEFER, 2), - TEST_HERE_USE(META_DEFER, 3), - TEST_HERE_USE(META_DEFER, 4), - TEST_HERE_USE(META_DEFER, 5), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#undef TEST_PREFIX diff --git a/test/cmocka/src/lib/preproc/get_arg.c b/test/cmocka/src/lib/preproc/get_arg.c deleted file mode 100644 index 425cded06142..000000000000 --- a/test/cmocka/src/lib/preproc/get_arg.c +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <sof/lib/alloc.h> - -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -#include <sof/trace/preproc.h> -#include <sof/sof.h> - -static void test_lib_preproc_get_arg_1(void **state) -{ - const char* what_we_get = _META_GET_ARG_1("a", "B", "c", "D", "e"); - const char* what_we_should_get = "a"; - - (void)state; - - assert_string_equal(what_we_get, what_we_should_get); -} - -static void test_lib_preproc_get_arg_2(void **state) -{ - const char* what_we_get = _META_GET_ARG_2("a", "B", "c", "D", "e"); - const char* what_we_should_get = "B"; - - (void)state; - - assert_string_equal(what_we_get, what_we_should_get); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_lib_preproc_get_arg_1), - cmocka_unit_test(test_lib_preproc_get_arg_2), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/lib/preproc/seq.c b/test/cmocka/src/lib/preproc/seq.c deleted file mode 100644 index 79ddbe41c25a..000000000000 --- a/test/cmocka/src/lib/preproc/seq.c +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <test_simple_macro.h> - -#include <sof/lib/alloc.h> -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -#include <sof/trace/preproc.h> -#include <sof/sof.h> - -#define TEST_PREFIX test_lib_preproc - -#define TEST_FUNC(prefix, test_func, postfix, should_be, ...)\ -static void META_CONCAT_SEQ_DELIM_(prefix, test_func, postfix)(void **state)\ -{\ - const char* r = META_QUOTE(test_func(__VA_ARGS__));\ - (void)state;\ -\ - assert_string_equal(r, should_be);\ -} - -TEST_HERE_DECLARE(META_SEQ_FROM_0_TO, int_0, "", 0, META_SEQ_STEP) -TEST_HERE_DECLARE(META_SEQ_FROM_0_TO, int_1, "0", 1, META_SEQ_STEP) -TEST_HERE_DECLARE(META_SEQ_FROM_0_TO, int_3, "0 1 2", 3, META_SEQ_STEP) - -#undef TEST_FUNC - -#define CAPTURE_PARAMS_PART(x, y) x " , " META_QUOTE(y) -#define CAPTURE_PARAMS(aggr, ...) META_RECURSE(\ - META_MAP_AGGREGATE(1, CAPTURE_PARAMS_PART, aggr, __VA_ARGS__)) - -#define TEST_FUNC(prefix, test_func, postfix, should_be, ...)\ -static void META_CONCAT_SEQ_DELIM_(prefix, test_func, postfix)(void **state)\ -{\ - const char *r = CAPTURE_PARAMS(test_func(__VA_ARGS__));\ - (void)state;\ -\ - assert_string_equal(r, " , " should_be);\ -} - -TEST_HERE_DECLARE(META_SEQ_FROM_0_TO, param_0,\ - "",\ - 0, META_SEQ_STEP_param_uint32_t) -TEST_HERE_DECLARE(META_SEQ_FROM_0_TO, param_1,\ - "uint32_t param0",\ - 1, META_SEQ_STEP_param_uint32_t) -TEST_HERE_DECLARE(META_SEQ_FROM_0_TO, param_3,\ - "uint32_t param0 , uint32_t param1 , uint32_t param2",\ - 3, META_SEQ_STEP_param_uint32_t) - -#undef TEST_FUNC -#undef CAPTURE_PARAMS -#undef CAPTURE_PARAMS_PART - -int main(void) -{ - const struct CMUnitTest tests[] = { - TEST_HERE_USE(META_SEQ_FROM_0_TO, int_0), - TEST_HERE_USE(META_SEQ_FROM_0_TO, int_1), - TEST_HERE_USE(META_SEQ_FROM_0_TO, int_3), - - TEST_HERE_USE(META_SEQ_FROM_0_TO, param_0), - TEST_HERE_USE(META_SEQ_FROM_0_TO, param_1), - TEST_HERE_USE(META_SEQ_FROM_0_TO, param_3), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#undef TEST_PREFIX diff --git a/test/cmocka/src/lib/preproc/varargs_count.c b/test/cmocka/src/lib/preproc/varargs_count.c deleted file mode 100644 index a52780780920..000000000000 --- a/test/cmocka/src/lib/preproc/varargs_count.c +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Michal Jerzy Wierzbicki <michalx.wierzbicki@linux.intel.com> - -#include <test_simple_macro.h> - -#include <sof/lib/alloc.h> -#include <stdarg.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -#include <sof/trace/preproc.h> -#include <sof/sof.h> - -#define TEST_PREFIX test_lib_preproc - -#define TEST_FUNC(prefix, test_func, postfix, should_be, ...)\ -static void META_CONCAT_SEQ_DELIM_(prefix, test_func, postfix)(void **state)\ -{\ - const int r = test_func(__VA_ARGS__);\ - (void)state;\ -\ - assert_int_equal(r, should_be);\ -} -#define A 1 -#define B 2 -#define C 3 -#define PARENTHESIS_PRE() (1+3)/2 -#define PARENTHESIS_POST() 4/(3-1) - -#define META_NAME META_COUNT_VARAGS_BEFORE_COMPILE -#define TEST_HERE_DECLARE_GROUP(func_name)\ - TEST_HERE_DECLARE(func_name, 0, 0, )\ - TEST_HERE_DECLARE(func_name, 1, 1, A )\ - TEST_HERE_DECLARE(func_name, 3, 3, A, B, C)\ - TEST_HERE_DECLARE(func_name, with_parenthesis_pre, 1,\ - PARENTHESIS_PRE())\ - TEST_HERE_DECLARE(func_name, with_parenthesis_post, 1,\ - PARENTHESIS_POST()) - -TEST_HERE_DECLARE_GROUP(META_NAME) -TEST_HERE_DECLARE_GROUP(PP_NARG) - -#undef TEST_HERE_DECLARE_GROUP -#undef PARENTHESIS_POST -#undef PARENTHESIS_PRE -#undef C -#undef B -#undef A -#undef TEST_FUNC - -#define TEST_HERE_USE_GROUP(func_name)\ - TEST_HERE_USE(func_name, 0),\ - TEST_HERE_USE(func_name, 1),\ - TEST_HERE_USE(func_name, 3),\ - TEST_HERE_USE(func_name, with_parenthesis_pre),\ - TEST_HERE_USE(func_name, with_parenthesis_post), - -int main(void) -{ - const struct CMUnitTest tests[] = { - TEST_HERE_USE_GROUP(META_NAME) - TEST_HERE_USE_GROUP(PP_NARG) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} - -#undef TEST_HERE_USE_GROUP -#undef META_NAME -#undef TEST_PREFIX diff --git a/test/cmocka/src/list/CMakeLists.txt b/test/cmocka/src/list/CMakeLists.txt deleted file mode 100644 index 5b8c5699512e..000000000000 --- a/test/cmocka/src/list/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmocka_test(list_init - list_init.c -) - -cmocka_test(list_is_empty - list_is_empty.c -) - -cmocka_test(list_item_append - list_item_append.c -) - -cmocka_test(list_item_del - list_item_del.c -) - -cmocka_test(list_item_is_last - list_item_is_last.c -) - -cmocka_test(list_item_prepend - list_item_prepend.c -) - -cmocka_test(list_item - list_item.c -) diff --git a/test/cmocka/src/list/list_init.c b/test/cmocka/src/list/list_init.c deleted file mode 100644 index 08ac2a9f0c4f..000000000000 --- a/test/cmocka/src/list/list_init.c +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_list_list_init_prev_equal_to_root(void **state) -{ - (void) state; /* unused */ - - struct list_item list = {.prev = NULL, .next = NULL}; - - list_init(&list); - - assert_ptr_equal(&list, list.prev); -} - -static void test_list_list_init_next_equal_to_root(void **state) -{ - (void) state; /* unused */ - - struct list_item list = {.prev = NULL, .next = NULL}; - - list_init(&list); - - assert_ptr_equal(&list, list.next); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_list_list_init_prev_equal_to_root), - cmocka_unit_test(test_list_list_init_next_equal_to_root), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/list/list_is_empty.c b/test/cmocka/src/list/list_is_empty.c deleted file mode 100644 index 300967dd80ec..000000000000 --- a/test/cmocka/src/list/list_is_empty.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_list_list_is_empty_when_empty_then_true(void **state) -{ - (void) state; /* unused */ - - struct list_item list; - - list_init(&list); - - assert_true(list_is_empty(&list)); -} - -static void test_list_list_is_empty_when_not_empty_then_false(void **state) -{ - (void) state; /* unused */ - - struct list_item list, item; - - list_init(&list); - list_init(&item); - - list_item_append(&item, &list); - - assert_false(list_is_empty(&list)); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_list_list_is_empty_when_empty_then_true), - cmocka_unit_test(test_list_list_is_empty_when_not_empty_then_false), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/list/list_item.c b/test/cmocka/src/list/list_item.c deleted file mode 100644 index d8d0b45ab2a8..000000000000 --- a/test/cmocka/src/list/list_item.c +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -struct test_list_container { - void *field1; - struct list_item list; - void *field2; -}; - -static void test_list_list_item_when_valid_offset_then_ptr_equal(void **state) -{ - (void) state; /* unused */ - - struct test_list_container container; - - list_init(&(container.list)); - - struct test_list_container *result_container = list_item( - &(container.list), struct test_list_container, list); - - assert_ptr_equal(result_container, &container); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_list_list_item_when_valid_offset_then_ptr_equal), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/list/list_item_append.c b/test/cmocka/src/list/list_item_append.c deleted file mode 100644 index 5bf2ab93bf41..000000000000 --- a/test/cmocka/src/list/list_item_append.c +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -struct test_data { - struct list_item *head; - struct list_item *tail_minus_1; - struct list_item *tail; -}; - -static int setup(void **state) -{ - struct test_data *data = malloc(sizeof(struct test_data)); - - if (data == NULL) - return -1; - - data->head = malloc(sizeof(struct list_item)); - data->tail_minus_1 = malloc(sizeof(struct list_item)); - data->tail = malloc(sizeof(struct list_item)); - - if (data->head == NULL - || data->tail_minus_1 == NULL - || data->tail == NULL) { - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - - return -1; - } - - list_init(data->head); - list_init(data->tail_minus_1); - list_init(data->tail); - - list_item_append(data->tail_minus_1, data->head); - list_item_append(data->tail, data->head); - - *state = data; - return 0; -} - -static int teardown(void **state) -{ - struct test_data *data = *state; - - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - return 0; -} - -static void test_list_list_item_append_head_prev_is_tail(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->head->prev, data->tail); -} - -static void test_list_list_item_append_head_next_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->head->next, data->tail_minus_1); -} - -static void test_list_list_item_append_tail_minus_1_prev_is_head(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail_minus_1->prev, data->head); -} - -static void test_list_list_item_append_tail_minus_1_next_is_tail(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail_minus_1->next, data->tail); -} - -static void test_list_list_item_append_tail_prev_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail->prev, data->tail_minus_1); -} - -static void test_list_list_item_append_tail_next_is_head(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail->next, data->head); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_list_list_item_append_head_prev_is_tail), - cmocka_unit_test(test_list_list_item_append_head_next_is_tail_minus_1), - cmocka_unit_test(test_list_list_item_append_tail_minus_1_prev_is_head), - cmocka_unit_test(test_list_list_item_append_tail_minus_1_next_is_tail), - cmocka_unit_test(test_list_list_item_append_tail_prev_is_tail_minus_1), - cmocka_unit_test(test_list_list_item_append_tail_next_is_head), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, setup, teardown); -} diff --git a/test/cmocka/src/list/list_item_del.c b/test/cmocka/src/list/list_item_del.c deleted file mode 100644 index 1dc15a7d07a4..000000000000 --- a/test/cmocka/src/list/list_item_del.c +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -struct test_data { - struct list_item *head; - struct list_item *tail_minus_1; - struct list_item *tail; -}; - -static int setup(void **state) -{ - struct test_data *data = malloc(sizeof(struct test_data)); - - if (data == NULL) - return -1; - - data->head = malloc(sizeof(struct list_item)); - data->tail_minus_1 = malloc(sizeof(struct list_item)); - data->tail = malloc(sizeof(struct list_item)); - - if (data->head == NULL - || data->tail_minus_1 == NULL - || data->tail == NULL) { - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - - return -1; - } - - list_init(data->head); - list_init(data->tail_minus_1); - list_init(data->tail); - - list_item_append(data->tail_minus_1, data->head); - list_item_append(data->tail, data->head); - - *state = data; - return 0; -} - -static int teardown(void **state) -{ - struct test_data *data = *state; - - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - return 0; -} - -static void test_list_list_item_del_when_delete_head_then_tail_minus_1_prev_is_tail(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->head); - - assert_ptr_equal(data->tail_minus_1->prev, data->tail); -} - -static void test_list_list_item_del_when_delete_head_then_tail_minus_1_next_is_tail(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->head); - - assert_ptr_equal(data->tail_minus_1->next, data->tail); -} - -static void test_list_list_item_del_when_delete_head_then_tail_prev_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->head); - - assert_ptr_equal(data->tail->prev, data->tail_minus_1); -} - -static void test_list_list_item_del_when_delete_head_then_tail_next_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->head); - - assert_ptr_equal(data->tail->next, data->tail_minus_1); -} - -static void test_list_list_item_del_when_delete_tail_minus_1_then_head_prev_is_tail(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail_minus_1); - - assert_ptr_equal(data->head->prev, data->tail); -} - -static void test_list_list_item_del_when_delete_tail_minus_1_then_head_next_is_tail(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail_minus_1); - - assert_ptr_equal(data->head->next, data->tail); -} - -static void test_list_list_item_del_when_delete_tail_minus_1_then_tail_prev_is_head(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail_minus_1); - - assert_ptr_equal(data->tail->prev, data->head); -} - -static void test_list_list_item_del_when_delete_tail_minus_1_then_tail_next_is_head(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail_minus_1); - - assert_ptr_equal(data->tail->next, data->head); -} - -static void test_list_list_item_del_when_delete_tail_then_head_prev_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail); - - assert_ptr_equal(data->head->prev, data->tail_minus_1); -} - -static void test_list_list_item_del_when_delete_tail_then_head_next_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail); - - assert_ptr_equal(data->head->next, data->tail_minus_1); -} - -static void test_list_list_item_del_when_delete_tail_then_tail_minus_1_prev_is_head(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail); - - assert_ptr_equal(data->tail_minus_1->prev, data->head); -} - -static void test_list_list_item_del_when_delete_tail_then_tail_minus_1_next_is_head(void **state) -{ - struct test_data *data = *state; - - list_item_del(data->tail); - - assert_ptr_equal(data->tail_minus_1->next, data->head); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_head_then_tail_minus_1_prev_is_tail, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_head_then_tail_minus_1_next_is_tail, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_head_then_tail_prev_is_tail_minus_1, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_head_then_tail_next_is_tail_minus_1, setup, teardown), - - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_minus_1_then_head_prev_is_tail, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_minus_1_then_head_next_is_tail, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_minus_1_then_tail_prev_is_head, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_minus_1_then_tail_next_is_head, setup, teardown), - - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_then_head_prev_is_tail_minus_1, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_then_head_next_is_tail_minus_1, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_then_tail_minus_1_prev_is_head, setup, teardown), - cmocka_unit_test_setup_teardown(test_list_list_item_del_when_delete_tail_then_tail_minus_1_next_is_head, setup, teardown), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/list/list_item_is_last.c b/test/cmocka/src/list/list_item_is_last.c deleted file mode 100644 index a6e2373acddf..000000000000 --- a/test/cmocka/src/list/list_item_is_last.c +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -struct test_data { - struct list_item *head; - struct list_item *tail_minus_1; - struct list_item *tail; -}; - -static int setup(void **state) -{ - struct test_data *data = malloc(sizeof(struct test_data)); - - if (data == NULL) - return -1; - - data->head = malloc(sizeof(struct list_item)); - data->tail_minus_1 = malloc(sizeof(struct list_item)); - data->tail = malloc(sizeof(struct list_item)); - - if (data->head == NULL - || data->tail_minus_1 == NULL - || data->tail == NULL) { - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - - return -1; - } - - list_init(data->head); - list_init(data->tail_minus_1); - list_init(data->tail); - - list_item_append(data->tail_minus_1, data->head); - list_item_append(data->tail, data->head); - - *state = data; - return 0; -} - -static int teardown(void **state) -{ - struct test_data *data = *state; - - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - return 0; -} - -static void test_list_list_item_is_last_when_head_then_false(void **state) -{ - struct test_data *data = *state; - - assert_false(list_item_is_last(data->head, data->head)); -} - -static void test_list_list_item_is_last_when_tail_minus_1_then_false(void **state) -{ - struct test_data *data = *state; - - assert_false(list_item_is_last(data->tail_minus_1, data->head)); -} - -static void test_list_list_item_is_last_when_tail_then_true(void **state) -{ - struct test_data *data = *state; - - assert_true(list_item_is_last(data->tail, data->head)); -} - -static void test_list_list_item_is_last_when_not_in_list_then_false(void **state) -{ - struct list_item other_list; - struct test_data *data = *state; - - list_init(&other_list); - - assert_false(list_item_is_last(&other_list, data->head)); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_list_list_item_is_last_when_head_then_false), - cmocka_unit_test(test_list_list_item_is_last_when_tail_minus_1_then_false), - cmocka_unit_test(test_list_list_item_is_last_when_tail_then_true), - cmocka_unit_test(test_list_list_item_is_last_when_not_in_list_then_false), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, setup, teardown); -} diff --git a/test/cmocka/src/list/list_item_prepend.c b/test/cmocka/src/list/list_item_prepend.c deleted file mode 100644 index aa9e8fdad806..000000000000 --- a/test/cmocka/src/list/list_item_prepend.c +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/list.h> - -#include <stdlib.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -struct test_data { - struct list_item *head; - struct list_item *tail_minus_1; - struct list_item *tail; -}; - -static int setup(void **state) -{ - struct test_data *data = malloc(sizeof(struct test_data)); - - if (data == NULL) - return -1; - - data->head = malloc(sizeof(struct list_item)); - data->tail_minus_1 = malloc(sizeof(struct list_item)); - data->tail = malloc(sizeof(struct list_item)); - - if (data->head == NULL - || data->tail_minus_1 == NULL - || data->tail == NULL) { - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - - return -1; - } - - list_init(data->head); - list_init(data->tail_minus_1); - list_init(data->tail); - - list_item_prepend(data->tail, data->head); - list_item_prepend(data->tail_minus_1, data->head); - - *state = data; - return 0; -} - -static int teardown(void **state) -{ - struct test_data *data = *state; - - free(data->head); - free(data->tail_minus_1); - free(data->tail); - - free(data); - return 0; -} - -static void test_list_list_item_prepend_head_prev_is_tail(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->head->prev, data->tail); -} - -static void test_list_list_item_prepend_head_next_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->head->next, data->tail_minus_1); -} - -static void test_list_list_item_prepend_tail_minus_1_prev_is_head(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail_minus_1->prev, data->head); -} - -static void test_list_list_item_prepend_tail_minus_1_next_is_tail(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail_minus_1->next, data->tail); -} - -static void test_list_list_item_prepend_tail_prev_is_tail_minus_1(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail->prev, data->tail_minus_1); -} - -static void test_list_list_item_prepend_tail_next_is_head(void **state) -{ - struct test_data *data = *state; - - assert_ptr_equal(data->tail->next, data->head); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_list_list_item_prepend_head_prev_is_tail), - cmocka_unit_test(test_list_list_item_prepend_head_next_is_tail_minus_1), - cmocka_unit_test(test_list_list_item_prepend_tail_minus_1_prev_is_head), - cmocka_unit_test(test_list_list_item_prepend_tail_minus_1_next_is_tail), - cmocka_unit_test(test_list_list_item_prepend_tail_prev_is_tail_minus_1), - cmocka_unit_test(test_list_list_item_prepend_tail_next_is_head), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, setup, teardown); -} diff --git a/test/cmocka/src/math/CMakeLists.txt b/test/cmocka/src/math/CMakeLists.txt index 64b14ddf2c05..83180953eb55 100644 --- a/test/cmocka/src/math/CMakeLists.txt +++ b/test/cmocka/src/math/CMakeLists.txt @@ -1,4 +1,8 @@ # SPDX-License-Identifier: BSD-3-Clause -add_subdirectory(numbers) -add_subdirectory(trig) +add_subdirectory(arithmetic) +add_subdirectory(fft) +add_subdirectory(window) +add_subdirectory(matrix) +add_subdirectory(auditory) +add_subdirectory(dct) diff --git a/test/cmocka/src/math/arithmetic/CMakeLists.txt b/test/cmocka/src/math/arithmetic/CMakeLists.txt new file mode 100644 index 000000000000..721c50020ba5 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/CMakeLists.txt @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(scalar_power + scalar_power.c + ${PROJECT_SOURCE_DIR}/src/math/power.c +) + +cmocka_test(base2_logarithm + base2_logarithm.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c +) + +cmocka_test(exponential + exponential.c + ${PROJECT_SOURCE_DIR}/src/math/exp_fcn.c + ${PROJECT_SOURCE_DIR}/src/math/exp_fcn_hifi.c +) +cmocka_test(square_root + square_root.c + ${PROJECT_SOURCE_DIR}/src/math/sqrt_int16.c +) + +cmocka_test(base_10_logarithm + base_10_logarithm.c + ${PROJECT_SOURCE_DIR}/src/math/log_10.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c +) + +cmocka_test(base_e_logarithm + base_e_logarithm.c + ${PROJECT_SOURCE_DIR}/src/math/log_e.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c +) + +cmocka_test(a_law_codec + a_law_codec.c + ${PROJECT_SOURCE_DIR}/src/math/a_law.c +) + +cmocka_test(mu_law_codec + mu_law_codec.c + ${PROJECT_SOURCE_DIR}/src/math/mu_law.c +) diff --git a/test/cmocka/src/math/arithmetic/a_law_codec.c b/test/cmocka/src/math/arithmetic/a_law_codec.c new file mode 100644 index 000000000000..a0bc4f7aef41 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/a_law_codec.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <stdio.h> +#include <stdint.h> +#include <setjmp.h> +#include <stdbool.h> +#include <cmocka.h> +#include <sof/math/a_law.h> + +#include "ref_chirp_mono_8k_s16.h" +#include "a_law_codec.h" + +static void test_a_law_encode(void **state) +{ + (void)state; + + uint8_t a_law_sample, a_law_ref; + int i; + + for (i = 0; i < REF_DATA_SAMPLE_COUNT; i++) { + a_law_sample = sofm_a_law_encode(chirp_mono_8k_s16[i]); + a_law_ref = ref_alaw_enc_data[i]; + + if (a_law_sample != a_law_ref) { + printf("%s: difference found at %d, encoded %d, ref %d, lin %d\n", + __func__, i, a_law_sample, a_law_ref, chirp_mono_8k_s16[i]); + assert_true(false); + } + } +} + +static void test_a_law_decode(void **state) +{ + (void)state; + + int16_t s16_sample, s16_ref; + int i; + + for (i = 0; i < REF_DATA_SAMPLE_COUNT; i++) { + s16_sample = sofm_a_law_decode(ref_alaw_enc_data[i]); + s16_ref = ref_alaw_dec_data[i]; + if (s16_sample != s16_ref) { + printf("%s: difference found at %d, decoded %d, ref %d\n", + __func__, i, s16_sample, s16_ref); + assert_true(false); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_a_law_encode), + cmocka_unit_test(test_a_law_decode), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/a_law_codec.h b/test/cmocka/src/math/arithmetic/a_law_codec.h new file mode 100644 index 000000000000..403b368f074f --- /dev/null +++ b/test/cmocka/src/math/arithmetic/a_law_codec.h @@ -0,0 +1,814 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 13-May-2025 18:29:28 with script a_law_mu_law_test_vectors.m */ + +#include <stdint.h> + +static const uint8_t ref_alaw_enc_data[4000] = { + 168, 169, 174, 172, 173, 163, 161, 167, 165, 185, + 178, 182, 137, 135, 148, 79, 18, 0, 10, 49, + 60, 59, 36, 38, 32, 34, 45, 47, 46, 41, + 40, 43, 42, 42, 42, 42, 42, 42, 43, 40, + 41, 46, 47, 45, 35, 33, 39, 37, 57, 50, + 55, 14, 4, 111, 251, 153, 141, 180, 179, 190, + 165, 167, 161, 163, 173, 172, 174, 169, 168, 171, + 170, 170, 170, 170, 170, 170, 171, 168, 169, 174, + 172, 173, 163, 161, 167, 186, 190, 179, 181, 130, + 157, 205, 23, 1, 11, 49, 60, 59, 36, 38, + 32, 34, 44, 46, 41, 40, 43, 42, 42, 42, + 42, 42, 42, 43, 40, 41, 47, 44, 34, 32, + 38, 36, 56, 61, 54, 14, 5, 102, 236, 132, + 137, 182, 188, 187, 164, 166, 160, 162, 172, 174, + 169, 168, 171, 170, 170, 170, 170, 170, 171, 171, + 168, 174, 175, 173, 163, 161, 164, 186, 188, 177, + 136, 135, 238, 103, 5, 14, 54, 61, 59, 36, + 38, 35, 45, 44, 46, 41, 43, 43, 42, 42, + 42, 42, 42, 43, 40, 41, 47, 44, 34, 32, + 39, 37, 62, 48, 10, 1, 21, 248, 154, 142, + 182, 188, 187, 164, 161, 163, 173, 175, 174, 168, + 171, 170, 170, 170, 170, 170, 171, 171, 169, 174, + 172, 162, 160, 166, 165, 185, 179, 181, 128, 150, + 112, 24, 14, 54, 60, 59, 39, 33, 35, 45, + 47, 41, 40, 43, 42, 42, 42, 42, 42, 43, + 40, 41, 47, 45, 35, 33, 36, 59, 61, 55, + 13, 18, 216, 158, 143, 182, 188, 187, 167, 161, + 162, 172, 175, 169, 168, 171, 170, 170, 170, 170, + 170, 171, 168, 174, 172, 162, 160, 167, 165, 191, + 177, 137, 155, 246, 16, 2, 55, 61, 59, 36, + 33, 35, 44, 46, 41, 40, 43, 42, 42, 42, + 42, 43, 40, 41, 47, 45, 35, 33, 36, 56, + 50, 52, 0, 106, 224, 135, 138, 179, 185, 164, + 166, 163, 173, 175, 169, 168, 171, 170, 170, 170, + 170, 171, 168, 169, 175, 173, 163, 166, 165, 190, + 176, 139, 133, 243, 16, 13, 55, 60, 58, 39, + 32, 34, 47, 46, 40, 43, 42, 42, 42, 42, + 42, 40, 41, 47, 45, 35, 38, 37, 62, 48, + 9, 24, 89, 159, 142, 177, 190, 165, 166, 163, + 173, 175, 169, 168, 170, 170, 170, 170, 170, 171, + 168, 174, 172, 162, 161, 164, 184, 179, 138, 132, + 240, 18, 15, 49, 63, 37, 38, 35, 45, 47, + 41, 43, 42, 42, 42, 42, 42, 43, 41, 47, + 45, 35, 38, 37, 63, 54, 2, 23, 227, 129, + 180, 189, 186, 167, 160, 173, 175, 169, 168, 170, + 170, 170, 170, 170, 171, 169, 175, 173, 163, 166, + 186, 188, 183, 128, 236, 20, 2, 54, 63, 37, + 38, 35, 44, 46, 40, 43, 42, 42, 42, 42, + 43, 40, 46, 44, 35, 33, 37, 63, 54, 13, + 20, 239, 131, 183, 188, 165, 166, 163, 172, 174, + 168, 171, 170, 170, 170, 170, 171, 169, 174, 173, + 163, 166, 186, 189, 181, 135, 247, 30, 8, 51, + 56, 39, 32, 45, 47, 41, 43, 42, 42, 42, + 42, 43, 40, 46, 44, 35, 38, 37, 61, 52, + 7, 118, 158, 136, 179, 187, 167, 160, 173, 175, + 169, 171, 170, 170, 170, 170, 171, 169, 175, 173, + 160, 164, 185, 176, 143, 145, 108, 3, 54, 62, + 36, 33, 34, 47, 41, 43, 42, 42, 42, 42, + 43, 41, 47, 45, 32, 39, 57, 48, 15, 23, + 235, 141, 177, 185, 164, 160, 173, 175, 169, 171, + 170, 170, 170, 170, 168, 169, 172, 162, 166, 165, + 188, 180, 132, 86, 4, 52, 60, 37, 33, 34, + 47, 41, 43, 42, 42, 42, 42, 43, 41, 47, + 34, 33, 37, 60, 52, 5, 219, 135, 180, 191, + 164, 161, 162, 175, 169, 171, 170, 170, 170, 170, + 168, 174, 172, 163, 167, 184, 176, 143, 149, 22, + 14, 51, 59, 38, 35, 44, 41, 40, 42, 42, + 42, 42, 43, 41, 44, 35, 38, 59, 51, 14, + 23, 148, 142, 179, 187, 166, 163, 172, 169, 171, + 170, 170, 170, 170, 168, 174, 172, 160, 167, 185, + 182, 128, 243, 26, 52, 63, 36, 33, 45, 46, + 40, 43, 42, 42, 42, 43, 41, 47, 35, 38, + 59, 51, 15, 105, 146, 139, 189, 165, 161, 162, + 175, 168, 171, 170, 170, 170, 171, 169, 172, 163, + 166, 187, 176, 130, 229, 27, 52, 63, 36, 32, + 45, 46, 40, 42, 42, 42, 42, 40, 46, 45, + 32, 36, 60, 53, 31, 239, 143, 179, 186, 166, + 162, 175, 168, 171, 170, 170, 170, 171, 174, 172, + 160, 164, 191, 180, 155, 102, 13, 51, 58, 38, + 34, 47, 40, 43, 42, 42, 42, 40, 46, 45, + 32, 36, 61, 11, 17, 145, 139, 188, 164, 160, + 173, 174, 168, 170, 170, 170, 171, 169, 175, 163, + 167, 184, 182, 135, 116, 3, 48, 58, 38, 34, + 47, 40, 42, 42, 42, 43, 40, 47, 34, 38, + 59, 49, 1, 222, 128, 176, 187, 166, 162, 174, + 168, 170, 170, 170, 171, 169, 175, 163, 167, 185, + 183, 155, 109, 14, 61, 37, 32, 45, 46, 43, + 42, 42, 42, 43, 46, 45, 33, 37, 50, 12, + 121, 135, 182, 187, 166, 162, 174, 168, 170, 170, + 170, 171, 169, 172, 160, 164, 188, 137, 238, 27, + 55, 56, 38, 34, 47, 40, 42, 42, 42, 43, + 41, 44, 32, 36, 50, 15, 123, 135, 177, 187, + 161, 173, 174, 171, 170, 170, 170, 168, 174, 173, + 166, 187, 182, 132, 98, 9, 60, 36, 35, 47, + 41, 43, 42, 42, 43, 41, 44, 32, 37, 50, + 13, 65, 131, 179, 165, 160, 172, 169, 171, 170, + 170, 171, 169, 172, 163, 164, 189, 140, 246, 0, + 51, 37, 32, 44, 41, 43, 42, 42, 43, 41, + 44, 32, 37, 51, 0, 241, 143, 189, 164, 163, + 175, 168, 170, 170, 170, 171, 174, 162, 166, 185, + 180, 144, 30, 55, 59, 33, 45, 41, 43, 42, + 42, 43, 41, 44, 32, 37, 48, 7, 236, 139, + 190, 167, 162, 174, 171, 170, 170, 170, 168, 172, + 160, 165, 179, 129, 103, 8, 63, 39, 34, 46, + 43, 42, 42, 42, 41, 44, 32, 37, 49, 5, + 148, 181, 185, 166, 173, 169, 171, 170, 170, 171, + 169, 173, 166, 185, 181, 235, 7, 48, 37, 32, + 47, 40, 42, 42, 42, 40, 47, 35, 37, 48, + 7, 234, 181, 184, 161, 173, 169, 171, 170, 170, + 171, 174, 162, 167, 189, 130, 118, 9, 62, 38, + 45, 46, 43, 42, 42, 43, 46, 34, 39, 60, + 13, 241, 136, 190, 166, 173, 169, 171, 170, 170, + 171, 174, 163, 164, 179, 134, 106, 52, 59, 33, + 44, 41, 42, 42, 42, 40, 44, 32, 59, 55, + 20, 135, 179, 164, 163, 174, 171, 170, 170, 171, + 174, 162, 167, 178, 129, 105, 52, 59, 33, 44, + 40, 42, 42, 42, 41, 45, 38, 62, 14, 208, + 137, 190, 166, 173, 169, 170, 170, 170, 169, 172, + 161, 185, 136, 194, 14, 62, 38, 45, 41, 42, + 42, 42, 41, 45, 38, 62, 14, 206, 139, 185, + 161, 172, 168, 170, 170, 171, 169, 162, 167, 178, + 134, 22, 54, 37, 35, 47, 43, 42, 42, 40, + 47, 32, 58, 52, 108, 130, 188, 166, 173, 169, + 170, 170, 170, 169, 173, 167, 178, 135, 18, 49, + 36, 35, 46, 43, 42, 42, 40, 44, 33, 62, + 12, 231, 180, 186, 160, 175, 171, 170, 170, 168, + 172, 161, 185, 137, 116, 53, 59, 32, 47, 43, + 42, 42, 40, 44, 33, 57, 15, 228, 180, 186, + 163, 174, 171, 170, 170, 168, 172, 166, 188, 129, + 19, 48, 36, 34, 41, 42, 42, 43, 41, 34, + 36, 49, 23, 131, 191, 161, 172, 168, 170, 170, + 168, 175, 161, 190, 140, 110, 54, 37, 34, 41, + 43, 42, 43, 46, 34, 37, 55, 102, 142, 184, + 160, 175, 171, 170, 170, 169, 173, 167, 179, 156, + 1, 63, 33, 44, 40, 42, 42, 40, 44, 38, + 61, 26, 132, 189, 166, 172, 168, 170, 170, 168, + 172, 166, 178, 155, 7, 60, 38, 44, 40, 42, + 42, 40, 45, 39, 48, 22, 141, 185, 160, 175, + 171, 170, 170, 169, 162, 165, 180, 208, 53, 37, + 34, 41, 42, 42, 43, 47, 33, 62, 0, 158, + 178, 166, 172, 168, 170, 170, 169, 173, 164, 183, + 252, 10, 37, 35, 41, 42, 42, 43, 47, 33, + 60, 5, 134, 191, 161, 175, 171, 170, 171, 174, + 160, 184, 140, 16, 51, 38, 44, 40, 42, 42, + 41, 34, 58, 11, 227, 177, 167, 173, 168, 170, + 170, 169, 162, 165, 138, 103, 49, 39, 45, 40, + 42, 42, 41, 34, 58, 8, 235, 176, 166, 172, + 171, 170, 170, 174, 163, 184, 131, 25, 60, 33, + 47, 43, 42, 43, 47, 33, 61, 29, 140, 187, + 163, 169, 170, 170, 168, 173, 164, 180, 116, 54, + 39, 44, 40, 42, 42, 46, 32, 62, 4, 129, + 185, 163, 174, 170, 170, 168, 173, 164, 181, 102, + 48, 38, 44, 43, 42, 43, 47, 38, 51, 107, + 138, 165, 173, 168, 170, 170, 174, 160, 190, 133, + 3, 56, 35, 41, 42, 42, 41, 35, 56, 3, + 132, 190, 163, 169, 170, 170, 169, 162, 187, 141, + 26, 62, 32, 41, 42, 42, 41, 34, 59, 3, + 132, 185, 163, 169, 170, 170, 169, 163, 185, 132, + 2, 59, 34, 40, 42, 42, 46, 33, 61, 20, + 181, 164, 172, 171, 170, 171, 172, 167, 183, 121, + 51, 33, 46, 42, 42, 40, 34, 59, 3, 134, + 184, 162, 168, 170, 170, 174, 161, 179, 240, 54, + 38, 47, 43, 42, 40, 34, 58, 3, 129, 187, + 162, 168, 170, 171, 175, 166, 183, 103, 50, 33, + 46, 42, 42, 41, 32, 60, 21, 180, 167, 175, + 171, 170, 168, 162, 184, 135, 12, 37, 45, 43, + 42, 43, 45, 37, 13, 134, 187, 162, 168, 170, + 171, 172, 164, 137, 5, 56, 34, 40, 42, 43, + 44, 36, 9, 133, 184, 162, 168, 170, 171, 172, + 165, 140, 6, 58, 45, 40, 42, 43, 45, 58, + 6, 143, 164, 172, 171, 170, 168, 163, 191, 150, + 52, 38, 47, 42, 42, 46, 33, 48, 253, 189, + 160, 169, 170, 171, 172, 164, 142, 6, 58, 45, + 43, 42, 40, 35, 63, 21, 182, 166, 174, 170, + 170, 175, 167, 181, 25, 56, 45, 43, 42, 40, + 34, 63, 107, 182, 161, 174, 170, 170, 175, 164, + 143, 0, 37, 44, 43, 42, 41, 33, 48, 224, + 191, 163, 168, 170, 168, 162, 190, 234, 49, 33, + 41, 42, 43, 44, 37, 7, 139, 167, 174, 170, + 170, 175, 164, 140, 2, 36, 47, 42, 42, 46, + 39, 11, 135, 165, 172, 171, 170, 174, 166, 181, + 4, 37, 44, 43, 42, 46, 38, 10, 135, 165, + 172, 170, 170, 174, 167, 137, 3, 36, 47, 42, + 42, 47, 36, 0, 136, 167, 174, 170, 171, 172, + 187, 157, 54, 33, 41, 42, 43, 34, 60, 213, + 188, 162, 171, 170, 169, 161, 183, 27, 37, 44, + 42, 42, 47, 37, 7, 181, 161, 169, 170, 171, + 162, 189, 117, 63, 34, 43, 42, 46, 39, 14, + 140, 167, 174, 170, 171, 162, 191, 223, 60, 34, + 43, 42, 46, 39, 13, 137, 166, 169, 170, 171, + 163, 178, 104, 56, 44, 42, 42, 47, 58, 18, + 176, 163, 168, 170, 169, 166, 137, 15, 38, 41, + 42, 40, 35, 48, 157, 165, 175, 170, 171, 173, + 191, 80, 62, 45, 43, 42, 47, 58, 20, 178, + 162, 171, 170, 174, 164, 154, 49, 35, 40, 42, + 46, 39, 1, 183, 160, 168, 170, 169, 167, 131, + 52, 32, 40, 42, 41, 39, 0, 180, 160, 168, + 170, 174, 167, 135, 54, 35, 43, 42, 46, 37, + 31, 179, 162, 171, 170, 175, 187, 230, 63, 45, + 42, 42, 45, 60, 226, 186, 175, 170, 171, 163, + 182, 7, 39, 41, 42, 41, 38, 13, 180, 160, + 168, 170, 175, 165, 238, 60, 45, 42, 43, 34, + 51, 158, 164, 174, 170, 168, 166, 130, 55, 35, + 43, 42, 44, 57, 202, 187, 175, 170, 168, 160, + 138, 8, 32, 40, 42, 47, 59, 89, 184, 175, + 170, 168, 160, 136, 53, 32, 43, 42, 44, 62, + 226, 165, 174, 170, 169, 166, 135, 48, 34, 42, + 43, 34, 49, 128, 166, 168, 170, 175, 184, 66, + 58, 46, 42, 41, 39, 5, 178, 173, 170, 171, + 163, 181, 10, 32, 43, 42, 45, 50, 132, 166, + 168, 170, 175, 185, 98, 37, 41, 42, 46, 37, + 123, 184, 175, 170, 169, 167, 147, 63, 44, 42, + 40, 38, 5, 189, 172, 170, 168, 161, 129, 51, + 45, 42, 40, 33, 0, 179, 173, 170, 168, 161, + 129, 51, 45, 42, 40, 38, 4, 189, 172, 170, + 168, 167, 157, 62, 47, 42, 41, 36, 103, 187, + 174, 170, 174, 187, 102, 36, 41, 42, 47, 60, + 133, 166, 168, 170, 162, 182, 11, 35, 42, 43, + 32, 3, 178, 172, 170, 169, 164, 231, 58, 46, + 42, 47, 63, 154, 166, 171, 170, 162, 181, 55, + 45, 42, 40, 39, 21, 187, 174, 170, 175, 188, + 7, 33, 43, 43, 32, 13, 178, 172, 170, 169, + 186, 110, 39, 40, 42, 34, 53, 182, 173, 170, + 169, 165, 112, 36, 40, 42, 34, 53, 182, 173, + 170, 169, 165, 108, 39, 40, 42, 35, 12, 178, + 175, 170, 174, 190, 7, 32, 43, 43, 38, 17, + 187, 169, 170, 173, 183, 55, 45, 42, 41, 59, + 156, 161, 171, 171, 166, 145, 58, 41, 42, 34, + 10, 176, 172, 170, 175, 188, 13, 35, 42, 40, + 37, 233, 166, 171, 171, 166, 151, 37, 40, 42, + 35, 2, 191, 174, 170, 173, 180, 49, 44, 42, + 47, 51, 138, 173, 170, 174, 190, 3, 35, 42, + 41, 59, 155, 160, 170, 168, 165, 17, 33, 42, + 40, 36, 239, 161, 171, 168, 164, 102, 38, 43, + 43, 36, 230, 166, 171, 168, 164, 111, 33, 43, + 40, 37, 145, 161, 170, 168, 186, 26, 35, 42, + 41, 57, 131, 162, 170, 174, 189, 10, 45, 42, + 47, 54, 177, 175, 170, 173, 142, 63, 41, 42, + 32, 31, 165, 168, 171, 167, 113, 38, 42, 40, + 59, 129, 162, 170, 174, 176, 54, 47, 42, 34, + 3, 184, 168, 170, 166, 84, 38, 42, 40, 56, + 141, 173, 170, 172, 181, 60, 41, 42, 32, 96, + 167, 171, 168, 184, 13, 45, 42, 44, 8, 190, + 169, 170, 166, 101, 33, 42, 46, 50, 182, 175, + 170, 163, 145, 39, 43, 40, 57, 137, 172, 170, + 162, 135, 37, 43, 40, 58, 141, 173, 170, 173, + 129, 37, 43, 40, 59, 140, 172, 170, 162, 154, + 36, 43, 40, 62, 181, 175, 170, 160, 231, 38, + 42, 46, 49, 178, 169, 170, 167, 28, 34, 42, + 45, 0, 165, 171, 168, 191, 55, 46, 42, 33, + 227, 163, 170, 172, 141, 37, 43, 40, 63, 182, + 174, 170, 166, 18, 34, 42, 34, 25, 167, 170, + 174, 182, 63, 40, 43, 56, 181, 175, 170, 166, + 16, 34, 42, 34, 22, 166, 170, 175, 137, 37, + 43, 41, 51, 189, 168, 171, 187, 53, 46, 42, + 39, 134, 172, 170, 161, 108, 34, 42, 34, 99, + 160, 170, 173, 154, 38, 42, 47, 13, 164, 170, + 174, 181, 58, 43, 41, 54, 184, 171, 169, 176, + 62, 40, 40, 50, 188, 168, 168, 178, 61, 40, + 40, 61, 189, 168, 168, 178, 60, 40, 40, 51, + 191, 171, 169, 177, 57, 43, 41, 55, 187, 171, + 174, 139, 37, 42, 47, 3, 167, 170, 172, 159, + 33, 42, 34, 116, 163, 170, 160, 17, 45, 42, + 39, 141, 174, 170, 186, 54, 41, 40, 50, 190, + 171, 174, 136, 36, 42, 44, 16, 160, 170, 160, + 17, 44, 42, 36, 181, 169, 171, 189, 62, 43, + 46, 13, 166, 170, 162, 118, 45, 42, 39, 139, + 169, 171, 178, 56, 43, 47, 5, 160, 170, 160, + 26, 47, 43, 57, 189, 171, 174, 130, 38, 42, + 35, 156, 175, 170, 185, 61, 43, 46, 6, 161, + 170, 161, 0, 46, 43, 50, 187, 170, 172, 254, + 34, 42, 37, 177, 168, 174, 130, 33, 42, 33, + 141, 169, 168, 183, 36, 42, 35, 157, 175, 171, + 178, 58, 42, 45, 225, 172, 171, 191, 56, 42, + 45, 243, 172, 170, 191, 56, 42, 45, 224, 172, + 171, 189, 58, 42, 34, 159, 174, 171, 182, 39, + 42, 33, 140, 169, 169, 141, 32, 42, 36, 176, + 171, 175, 228, 45, 42, 60, 186, 170, 163, 1, + 41, 41, 13, 160, 170, 165, 61, 42, 45, 149, + 175, 168, 181, 33, 42, 36, 179, 171, 173, 111, + 47, 40, 10, 161, 170, 165, 60, 42, 34, 155, + 169, 169, 134, 35, 42, 63, 165, 170, 161, 52, + 43, 44, 252, 175, 168, 142, 32, 42, 57, 186, + 170, 161, 55, 43, 44, 151, 174, 169, 132, 34, + 43, 48, 166, 170, 165, 62, 42, 32, 181, 171, + 172, 18, 41, 41, 22, 172, 171, 136, 35, 42, + 61, 167, 170, 165, 56, 42, 38, 176, 170, 163, + 15, 43, 44, 157, 169, 174, 201, 47, 41, 24, + 172, 171, 143, 34, 43, 55, 160, 170, 178, 38, + 42, 62, 164, 170, 187, 37, 42, 37, 184, 170, + 164, 62, 42, 39, 188, 170, 166, 61, 42, 38, + 178, 170, 161, 51, 42, 33, 179, 170, 161, 50, + 42, 38, 189, 170, 166, 60, 42, 39, 190, 170, + 164, 59, 42, 58, 165, 170, 185, 39, 42, 61, + 166, 170, 177, 32, 43, 11, 162, 171, 134, 44, + 41, 108, 174, 174, 107, 40, 44, 131, 171, 163, + 54, 42, 38, 190, 170, 186, 36, 42, 51, 160, + 171, 143, 45, 40, 97, 174, 175, 4, 43, 35, + 177, 170, 167, 58, 42, 61, 160, 171, 141, 44, + 41, 254, 168, 173, 53, 42, 38, 187, 170, 189, + 32, 43, 7, 175, 174, 25, 43, 32, 178, 170, + 184, 38, 42, 12, 172, 174, 29, 43, 32, 189, + 170, 190, 33, 43, 5, 174, 175, 12, 42, 39, + 165, 170, 180, 45, 41, 148, 171, 160, 63, 42, + 50, 163, 168, 95, 40, 35, 189, 170, 189, 35, + 40, 219, 168, 163, 60, 42, 48, 162, 169, 22, + 43, 33, 186, 170, 139, 47, 47, 142, 170, 165, + 33, 43, 104, 168, 163, 63, 42, 54, 172, 174, + 13, 42, 58, 161, 171, 204, 40, 33, 186, 170, + 130, 46, 45, 176, 170, 176, 45, 46, 142, 170, + 185, 35, 41, 153, 170, 165, 33, 40, 231, 171, + 167, 39, 43, 78, 171, 166, 39, 43, 100, 171, + 166, 36, 43, 120, 171, 166, 39, 43, 217, 171, + 167, 38, 40, 148, 170, 165, 32, 41, 129, 170, + 191, 45, 47, 180, 170, 183, 47, 45, 191, 170, + 132, 40, 33, 167, 171, 110, 42, 59, 162, 174, + 52, 42, 53, 174, 163, 58, 43, 89, 171, 186, + 35, 46, 180, 170, 137, 41, 32, 164, 171, 31, + 42, 61, 172, 173, 57, 42, 119, 171, 187, 34, + 47, 178, 170, 145, 43, 37, 162, 175, 51, 42, + 16, 171, 165, 34, 47, 189, 170, 251, 42, 62, + 172, 173, 59, 43, 144, 170, 177, 46, 32, 166, + 169, 53, 42, 5, 171, 186, 45, 45, 187, 171, + 27, 42, 10, 168, 167, 35, 47, 191, 171, 16, + 42, 53, 168, 167, 34, 44, 184, 171, 7, 42, + 3, 171, 187, 44, 34, 167, 169, 54, 42, 194, + 170, 180, 40, 36, 173, 173, 36, 41, 183, 170, + 123, 42, 8, 168, 187, 44, 32, 161, 175, 62, + 43, 140, 170, 228, 42, 53, 168, 187, 47, 33, + 160, 172, 37, 40, 177, 170, 27, 42, 22, 170, + 180, 40, 57, 174, 166, 34, 34, 166, 175, 59, + 40, 177, 171, 0, 42, 246, 170, 133, 42, 52, + 171, 188, 41, 37, 175, 166, 34, 35, 160, 172, + 39, 46, 187, 169, 61, 43, 183, 171, 15, 42, + 155, 170, 97, 42, 103, 170, 159, 42, 0, 170, + 136, 43, 52, 171, 177, 43, 50, 168, 188, 40, + 62, 169, 185, 41, 59, 169, 187, 46, 58, 174, + 186, 46, 58, 174, 186, 41, 59, 169, 184, 41, + 57, 169, 191, 40, 61, 168, 176, 43, 55, 171, + 138, 42, 13, 170, 133, 42, 104, 170, 119, 42, + 156, 170, 2, 42, 180, 171, 50, 40, 184, 174, + 36, 44, 161, 162, 34, 33, 175, 165, 41, 60, + 171, 180, 42, 5, 170, 126, 42, 130, 171, 48, + 40, 186, 175, 33, 35, 173, 164, 41, 60, 171, + 143, 42, 83, 170, 15, 43, 191, 174, 38, 34, + 173, 164, 41, 48, 170, 158, 42, 135, 171, 61, + 46, 166, 163, 44, 58, 168, 136, 42, 226, 170, + 49, 41, 167, 163, 44, 59, 171, 130, 42, 132, + 171, 57, 47, 163, 167, 41, 55, 170, 104, 42, + 188, 175, 35, 39, 169, 181, 42, 158, 171, 56, + 45, 173, 186, 43, 24, 170, 52, 41, 161, 161, + 41, 53, 170, 1, 40, 164, 163, 46, 49, 170, + 24, 43, 164, 163, 46, 49, 170, 7, 40, 167, + 161, 41, 8, 170, 53, 41, 160, 164, 43, 21, + 170, 62, 45, 175, 176, 42, 130, 169, 32, 36, + 171, 225, 42, 186, 163, 41, 9, 170, 48, 44, + 172, 179, 42, 142, 174, 34, 57, 170, 4, 41, + 160, 165, 42, 146, 168, 32, 37, 170, 18, 40, + 160, 186, 42, 132, 169, 35, 62, 170, 14, 46, + 173, 176, 42, 176, 173, 46, 2, 170, 58, 33, + 171, 91, 40, 160, 184, 42, 139, 175, 47, 9, + 170, 37, 38, 171, 16, 41, 173, 176, 42, 191, + 160, 43, 230, 168, 34, 48, 170, 57, 33, 171, + 28, 46, 172, 139, 42, 164, 164, 42, 180, 173, + 41, 113, 168, 34, 55, 170, 36, 36, 170, 54, + 34, 168, 23, 46, 175, 135, 43, 163, 179, 42, + 164, 165, 42, 189, 160, 42, 137, 173, 40, 150, + 174, 46, 105, 168, 44, 0, 171, 34, 53, 170, + 32, 48, 170, 38, 60, 170, 39, 57, 170, 36, + 59, 170, 37, 59, 170, 37, 59, 170, 37, 56, + 170, 36, 62, 170, 39, 61, 170, 33, 49, 170, + 35, 8, 171, 45, 5, 168, 47, 66, 174, 41, + 133, 173, 43, 180, 161, 42, 185, 165, 42, 166, + 176, 43, 173, 154, 41, 169, 30, 45, 171, 51, + 39, 170, 39, 48, 171, 44, 109, 175, 40, 181, + 161, 42, 164, 179, 43, 172, 196, 44, 171, 51, + 36, 170, 32, 3, 169, 40, 137, 161, 42, 166, + 138, 40, 169, 12, 33, 170, 38, 9, 169, 40, + 181, 167, 42, 163, 156, 47, 171, 63, 63, 171, + 47, 154, 160, 42, 161, 134, 46, 171, 62, 61, + 171, 46, 137, 167, 42, 173, 103, 35, 170, 33, + 27, 172, 42, 164, 139, 46, 171, 56, 49, 169, + 40, 188, 178, 40, 168, 50, 60, 168, 40, 189, + 189, 40, 168, 63, 48, 169, 43, 187, 181, 46, + 170, 39, 6, 172, 42, 160, 217, 32, 170, 44, + 131, 165, 43, 169, 61, 48, 174, 42, 166, 150, + 35, 170, 44, 142, 187, 40, 171, 37, 6, 173, + 42, 172, 14, 56, 168, 43, 167, 232, 32, 170, + 46, 189, 180, 44, 170, 45, 142, 190, 41, 170, + 32, 156, 165, 40, 171, 38, 231, 164, 43, 171, + 38, 251, 164, 40, 171, 33, 150, 165, 40, 170, + 35, 130, 191, 46, 170, 44, 176, 138, 34, 170, + 40, 164, 244, 36, 168, 42, 162, 52, 55, 173, + 42, 168, 39, 235, 187, 46, 170, 46, 184, 148, + 39, 168, 42, 172, 60, 25, 167, 40, 170, 47, + 190, 148, 36, 169, 42, 174, 37, 238, 190, 44, + 170, 43, 160, 53, 14, 161, 40, 170, 46, 165, + 18, 50, 162, 43, 170, 44, 184, 103, 60, 173, + 43, 170, 47, 165, 28, 49, 163, 40, 170, 41, + 161, 52, 4, 165, 47, 170, 42, 175, 36, 130, +}; + +static const int16_t ref_alaw_dec_data[4000] = { + 30208, 29184, 28160, 26112, 25088, 23040, 20992, 18944, 16896, 14592, + 12032, 9984, 7296, 4736, 2240, -424, -3008, -5504, -8064, -10496, + -13056, -15616, -17920, -19968, -22016, -24064, -25088, -27136, -28160, -29184, + -30208, -31232, -32256, -32256, -32256, -32256, -32256, -32256, -31232, -30208, + -29184, -28160, -27136, -25088, -23040, -20992, -18944, -16896, -14592, -12032, + -9472, -7040, -4480, -1696, 976, 3648, 6272, 8960, 11520, 14080, + 16896, 18944, 20992, 23040, 25088, 26112, 28160, 29184, 30208, 31232, + 32256, 32256, 32256, 32256, 32256, 32256, 31232, 30208, 29184, 28160, + 26112, 25088, 23040, 20992, 18944, 16128, 14080, 11520, 8448, 6016, + 3136, 392, -2368, -5248, -7808, -10496, -13056, -15616, -17920, -19968, + -22016, -24064, -26112, -28160, -29184, -30208, -31232, -32256, -32256, -32256, + -32256, -32256, -32256, -31232, -30208, -29184, -27136, -26112, -24064, -22016, + -19968, -17920, -15104, -12544, -9984, -7040, -4224, -1248, 1632, 4480, + 7296, 9984, 13056, 15616, 17920, 19968, 22016, 24064, 26112, 28160, + 29184, 30208, 31232, 32256, 32256, 32256, 32256, 32256, 31232, 31232, + 30208, 28160, 27136, 25088, 23040, 20992, 17920, 16128, 13056, 10496, + 7552, 4736, 1760, -1184, -4224, -7040, -9984, -12544, -15616, -17920, + -19968, -23040, -25088, -26112, -28160, -29184, -31232, -31232, -32256, -32256, + -32256, -32256, -32256, -31232, -30208, -29184, -27136, -26112, -24064, -22016, + -18944, -16896, -14080, -11008, -8064, -5248, -2112, 944, 4032, 7040, + 9984, 13056, 15616, 17920, 20992, 23040, 25088, 27136, 28160, 30208, + 31232, 32256, 32256, 32256, 32256, 32256, 31232, 31232, 29184, 28160, + 26112, 24064, 22016, 19968, 16896, 14592, 11520, 8448, 5504, 2496, + -688, -3776, -7040, -9984, -13056, -15616, -18944, -20992, -23040, -25088, + -27136, -29184, -30208, -31232, -32256, -32256, -32256, -32256, -32256, -31232, + -30208, -29184, -27136, -25088, -23040, -20992, -17920, -15616, -12544, -9472, + -6272, -3008, 216, 3520, 6784, 9984, 13056, 15616, 18944, 20992, + 24064, 26112, 27136, 29184, 30208, 31232, 32256, 32256, 32256, 32256, + 32256, 31232, 30208, 28160, 26112, 24064, 22016, 18944, 16896, 13568, + 10496, 7296, 3904, 624, -2752, -6016, -9472, -12544, -15616, -17920, + -20992, -23040, -26112, -28160, -29184, -30208, -31232, -32256, -32256, -32256, + -32256, -31232, -30208, -29184, -27136, -25088, -23040, -20992, -17920, -15104, + -12032, -8960, -5504, -2016, 1376, 4736, 8064, 11520, 14592, 17920, + 19968, 23040, 25088, 27136, 29184, 30208, 31232, 32256, 32256, 32256, + 32256, 31232, 30208, 29184, 27136, 25088, 23040, 19968, 16896, 14080, + 11008, 7808, 4224, 720, -2752, -6272, -9472, -13056, -16128, -18944, + -22016, -24064, -27136, -28160, -30208, -31232, -32256, -32256, -32256, -32256, + -32256, -30208, -29184, -27136, -25088, -23040, -19968, -16896, -14080, -11008, + -7296, -3776, -200, 3392, 7040, 10496, 14080, 16896, 19968, 23040, + 25088, 27136, 29184, 30208, 32256, 32256, 32256, 32256, 32256, 31232, + 30208, 28160, 26112, 24064, 20992, 17920, 15104, 11520, 8064, 4480, + 688, -3008, -6784, -10496, -13568, -16896, -19968, -23040, -25088, -27136, + -29184, -31232, -32256, -32256, -32256, -32256, -32256, -31232, -29184, -27136, + -25088, -23040, -19968, -16896, -13568, -9984, -6016, -2368, 1440, 5248, + 8960, 12544, 16128, 18944, 22016, 25088, 27136, 29184, 30208, 32256, + 32256, 32256, 32256, 32256, 31232, 29184, 27136, 25088, 23040, 19968, + 16128, 13056, 9472, 5504, 1632, -2240, -6016, -9984, -13568, -16896, + -19968, -23040, -26112, -28160, -30208, -31232, -32256, -32256, -32256, -32256, + -31232, -30208, -28160, -26112, -23040, -20992, -16896, -13568, -9984, -6272, + -2240, 1696, 5760, 9472, 13056, 16896, 19968, 23040, 26112, 28160, + 30208, 31232, 32256, 32256, 32256, 32256, 31232, 29184, 28160, 25088, + 23040, 19968, 16128, 12544, 8448, 4736, 592, -3520, -7552, -11520, + -15104, -18944, -22016, -25088, -27136, -29184, -31232, -32256, -32256, -32256, + -32256, -31232, -30208, -28160, -26112, -23040, -19968, -16896, -12544, -8960, + -4736, -624, 3520, 7552, 11520, 15616, 18944, 22016, 25088, 27136, + 29184, 31232, 32256, 32256, 32256, 32256, 31232, 29184, 27136, 25088, + 22016, 17920, 14592, 11008, 6784, 2624, -1632, -5760, -9984, -14080, + -17920, -20992, -24064, -27136, -29184, -31232, -32256, -32256, -32256, -32256, + -31232, -29184, -27136, -25088, -22016, -18944, -14592, -11008, -6784, -2368, + 1952, 6272, 10496, 14592, 17920, 22016, 25088, 27136, 29184, 31232, + 32256, 32256, 32256, 32256, 30208, 29184, 26112, 24064, 19968, 16896, + 13056, 8960, 4480, -56, -4480, -8960, -13056, -16896, -20992, -24064, + -27136, -29184, -31232, -32256, -32256, -32256, -32256, -31232, -29184, -27136, + -24064, -20992, -16896, -13056, -8960, -4224, 232, 4736, 8960, 13568, + 17920, 20992, 24064, 27136, 29184, 31232, 32256, 32256, 32256, 32256, + 30208, 28160, 26112, 23040, 18944, 15104, 11008, 6784, 2112, -2496, + -7040, -11520, -15616, -19968, -23040, -26112, -29184, -30208, -32256, -32256, + -32256, -32256, -31232, -29184, -26112, -23040, -19968, -15616, -11520, -7040, + -2368, 2240, 7040, 11520, 15616, 19968, 23040, 26112, 29184, 31232, + 32256, 32256, 32256, 32256, 30208, 28160, 26112, 22016, 18944, 14592, + 9984, 5504, 720, -4032, -8960, -13568, -17920, -20992, -25088, -28160, + -30208, -31232, -32256, -32256, -32256, -31232, -29184, -27136, -23040, -19968, + -15616, -11520, -6784, -1824, 3008, 7808, 12544, 16896, 20992, 24064, + 27136, 30208, 31232, 32256, 32256, 32256, 31232, 29184, 26112, 23040, + 19968, 15616, 11008, 6016, 1056, -3904, -8960, -13568, -17920, -22016, + -25088, -28160, -30208, -32256, -32256, -32256, -32256, -30208, -28160, -25088, + -22016, -17920, -13056, -8448, -3392, 1696, 6784, 11520, 16128, 19968, + 24064, 27136, 30208, 31232, 32256, 32256, 32256, 31232, 28160, 26112, + 22016, 17920, 13568, 8960, 3904, -1248, -6272, -11520, -16128, -19968, + -24064, -27136, -30208, -31232, -32256, -32256, -32256, -30208, -28160, -25088, + -22016, -17920, -12544, -7808, -2624, 2624, 7808, 13056, 17920, 22016, + 25088, 28160, 30208, 32256, 32256, 32256, 31232, 29184, 27136, 23040, + 18944, 15104, 9984, 4736, -560, -5760, -11008, -16128, -19968, -24064, + -27136, -30208, -32256, -32256, -32256, -31232, -30208, -27136, -24064, -19968, + -15616, -10496, -5248, 184, 5504, 11008, 15616, 19968, 24064, 28160, + 30208, 32256, 32256, 32256, 31232, 29184, 27136, 23040, 18944, 14592, + 9472, 3904, -1568, -7040, -12544, -16896, -22016, -25088, -28160, -31232, + -32256, -32256, -32256, -31232, -28160, -25088, -20992, -16896, -12032, -6528, + -912, 4736, 9984, 15616, 19968, 24064, 28160, 30208, 32256, 32256, + 32256, 31232, 29184, 26112, 22016, 17920, 13056, 7296, 1760, -3904, + -9472, -15104, -19968, -24064, -27136, -30208, -32256, -32256, -32256, -31232, + -29184, -26112, -22016, -17920, -12032, -6784, -976, 4736, 10496, 15616, + 20992, 25088, 28160, 31232, 32256, 32256, 32256, 30208, 28160, 25088, + 19968, 15616, 9984, 4480, -1504, -7296, -13056, -17920, -23040, -27136, + -29184, -31232, -32256, -32256, -31232, -29184, -26112, -22016, -16896, -12032, + -6272, -328, 5760, 11520, 16896, 22016, 26112, 29184, 31232, 32256, + 32256, 31232, 29184, 26112, 23040, 17920, 12544, 6528, 624, -5504, + -11520, -16896, -22016, -26112, -29184, -31232, -32256, -32256, -31232, -29184, + -26112, -22016, -16896, -11520, -5504, 656, 6784, 12544, 17920, 23040, + 27136, 30208, 32256, 32256, 32256, 31232, 28160, 24064, 19968, 14592, + 8960, 2752, -3520, -9472, -15616, -20992, -25088, -29184, -31232, -32256, + -32256, -31232, -29184, -26112, -22016, -16896, -11008, -4736, 1632, 7808, + 14080, 18944, 24064, 28160, 31232, 32256, 32256, 32256, 30208, 26112, + 22016, 16896, 11520, 5248, -1184, -7552, -13568, -18944, -24064, -28160, + -31232, -32256, -32256, -32256, -29184, -26112, -22016, -16896, -10496, -4224, + 2240, 8448, 14592, 19968, 25088, 29184, 31232, 32256, 32256, 31232, + 29184, 25088, 19968, 14592, 8448, 1952, -4736, -11008, -16896, -22016, + -27136, -30208, -32256, -32256, -32256, -30208, -27136, -23040, -16896, -11008, + -4736, 2016, 8448, 15104, 20992, 25088, 29184, 31232, 32256, 32256, + 31232, 28160, 24064, 18944, 12544, 6016, -624, -7296, -14080, -19968, + -25088, -28160, -31232, -32256, -32256, -31232, -28160, -24064, -18944, -13056, + -6272, 656, 7552, 14080, 19968, 25088, 29184, 31232, 32256, 32256, + 31232, 28160, 23040, 17920, 11520, 4992, -2016, -8960, -15616, -20992, + -26112, -29184, -32256, -32256, -32256, -30208, -26112, -22016, -15616, -9472, + -2240, 4736, 11520, 17920, 23040, 28160, 31232, 32256, 32256, 31232, + 28160, 24064, 18944, 12032, 5248, -1824, -8960, -15616, -20992, -26112, + -30208, -32256, -32256, -32256, -29184, -25088, -19968, -14080, -7040, 88, + 7296, 14080, 19968, 25088, 29184, 32256, 32256, 32256, 29184, 26112, + 20992, 14592, 7552, 376, -7040, -14080, -19968, -25088, -29184, -32256, + -32256, -32256, -29184, -25088, -19968, -14080, -7040, 440, 7808, 14592, + 20992, 26112, 30208, 32256, 32256, 31232, 29184, 24064, 18944, 12032, + 4992, -2496, -9984, -16896, -23040, -27136, -31232, -32256, -32256, -30208, + -27136, -22016, -16128, -8960, -1632, 6016, 13056, 19968, 25088, 29184, + 32256, 32256, 32256, 29184, 25088, 18944, 12032, 4736, -3008, -10496, + -17920, -23040, -28160, -31232, -32256, -32256, -30208, -26112, -20992, -14080, + -6528, 1184, 8960, 16128, 22016, 27136, 31232, 32256, 32256, 30208, + 26112, 20992, 14592, 7296, -560, -8448, -15616, -22016, -27136, -31232, + -32256, -32256, -30208, -26112, -20992, -14592, -6784, 1120, 8960, 16128, + 23040, 28160, 31232, 32256, 32256, 30208, 26112, 19968, 13056, 5248, + -2880, -11008, -17920, -24064, -29184, -32256, -32256, -31232, -29184, -24064, + -17920, -10496, -2368, 5760, 13568, 20992, 26112, 30208, 32256, 32256, + 30208, 27136, 20992, 14080, 6528, -1760, -9984, -16896, -24064, -29184, + -31232, -32256, -31232, -28160, -24064, -16896, -9472, -1248, 7040, 15104, + 22016, 27136, 31232, 32256, 32256, 29184, 25088, 18944, 11520, 3264, + -5248, -13568, -20992, -26112, -30208, -32256, -32256, -30208, -26112, -19968, + -12544, -4032, 4480, 12544, 19968, 26112, 30208, 32256, 32256, 30208, + 26112, 19968, 12032, 3904, -4736, -13056, -19968, -26112, -30208, -32256, + -32256, -30208, -25088, -18944, -11008, -2496, 6272, 14592, 22016, 27136, + 31232, 32256, 32256, 29184, 24064, 16896, 8960, 88, -8448, -16896, + -24064, -29184, -32256, -32256, -31232, -27136, -20992, -14080, -5504, 3520, + 12032, 19968, 26112, 30208, 32256, 32256, 29184, 25088, 17920, 9472, + 816, -8064, -16896, -23040, -29184, -32256, -32256, -31232, -27136, -20992, + -13056, -4224, 4992, 13568, 20992, 27136, 31232, 32256, 31232, 28160, + 22016, 15104, 6528, -2752, -11520, -19968, -26112, -30208, -32256, -32256, + -29184, -24064, -16128, -7808, 1440, 10496, 18944, 25088, 30208, 32256, + 32256, 29184, 24064, 16896, 8064, -1184, -10496, -18944, -25088, -30208, + -32256, -32256, -29184, -24064, -16128, -7552, 1952, 11008, 19968, 26112, + 31232, 32256, 32256, 28160, 23040, 15104, 5760, -3648, -13056, -20992, + -27136, -31232, -32256, -31232, -27136, -20992, -12544, -3136, 6528, 15616, + 23040, 29184, 32256, 32256, 30208, 25088, 17920, 8960, -560, -9984, + -18944, -26112, -30208, -32256, -32256, -28160, -22016, -14080, -4480, 5248, + 14592, 23040, 28160, 32256, 32256, 30208, 25088, 17920, 8448, -1248, + -11008, -19968, -26112, -31232, -32256, -31232, -27136, -19968, -11520, -1952, + 8064, 16896, 25088, 30208, 32256, 32256, 28160, 22016, 14080, 4224, + -5760, -15104, -23040, -29184, -32256, -32256, -29184, -23040, -15104, -5760, + 4480, 14080, 23040, 29184, 32256, 32256, 29184, 24064, 15616, 6272, + -4032, -14080, -22016, -29184, -32256, -32256, -29184, -24064, -15616, -5760, + 4480, 14592, 23040, 29184, 32256, 32256, 29184, 23040, 14592, 4480, + -6016, -15616, -24064, -30208, -32256, -32256, -28160, -20992, -12544, -2240, + 8448, 17920, 26112, 31232, 32256, 31232, 26112, 18944, 9472, -912, + -11520, -20992, -28160, -32256, -32256, -30208, -24064, -15616, -5760, 4992, + 15104, 24064, 30208, 32256, 32256, 28160, 20992, 11520, 688, -9984, + -19968, -27136, -31232, -32256, -30208, -24064, -16128, -5760, 5248, 15616, + 24064, 30208, 32256, 31232, 27136, 19968, 9472, -1184, -12032, -20992, + -28160, -32256, -32256, -29184, -22016, -13056, -2112, 8960, 18944, 27136, + 31232, 32256, 30208, 24064, 15104, 4736, -6528, -16896, -25088, -31232, + -32256, -31232, -25088, -16896, -6272, 4992, 15616, 24064, 30208, 32256, + 31232, 26112, 17920, 7296, -4224, -15104, -24064, -30208, -32256, -31232, + -26112, -17920, -7296, 4224, 15104, 24064, 30208, 32256, 31232, 26112, + 16896, 6528, -4992, -16128, -25088, -30208, -32256, -31232, -25088, -16128, + -4992, 6784, 17920, 26112, 31232, 32256, 30208, 23040, 13568, 2496, + -8960, -19968, -27136, -32256, -32256, -28160, -20992, -11008, 784, 12544, + 22016, 29184, 32256, 31232, 26112, 17920, 7040, -4992, -16128, -25088, + -31232, -32256, -30208, -23040, -13568, -2112, 9984, 19968, 28160, 32256, + 32256, 27136, 18944, 8448, -3648, -15104, -25088, -31232, -32256, -30208, + -24064, -13568, -1952, 9984, 20992, 28160, 32256, 32256, 27136, 17920, + 6784, -5504, -16896, -26112, -31232, -32256, -29184, -20992, -11008, 1376, + 13568, 23040, 30208, 32256, 30208, 24064, 14080, 2016, -10496, -20992, + -29184, -32256, -31232, -26112, -16896, -4736, 7808, 18944, 28160, 32256, + 32256, 27136, 17920, 6528, -6016, -17920, -27136, -32256, -32256, -28160, + -18944, -7808, 4736, 16896, 26112, 31232, 32256, 28160, 19968, 8448, + -4480, -16896, -26112, -31232, -32256, -28160, -19968, -8064, 4736, 16896, + 26112, 32256, 32256, 28160, 18944, 7296, -5760, -17920, -27136, -32256, + -32256, -27136, -17920, -5504, 7552, 18944, 28160, 32256, 31232, 26112, + 15616, 3136, -9984, -20992, -29184, -32256, -31232, -24064, -13056, 8, + 13056, 24064, 31232, 32256, 29184, 20992, 9472, -3904, -16896, -26112, + -32256, -32256, -27136, -16896, -4736, 8448, 20992, 29184, 32256, 31232, + 24064, 12544, -528, -13568, -24064, -31232, -32256, -28160, -18944, -7040, + 6528, 18944, 28160, 32256, 31232, 24064, 13568, 168, -13056, -24064, + -31232, -32256, -28160, -18944, -6272, 7296, 19968, 29184, 32256, 31232, + 23040, 12032, -1888, -15104, -26112, -32256, -32256, -27136, -16128, -3008, + 11008, 23040, 30208, 32256, 29184, 19968, 7296, -6784, -19968, -29184, + -32256, -30208, -23040, -11008, 3136, 16896, 27136, 32256, 31232, 25088, + 13568, -88, -14080, -25088, -31232, -32256, -27136, -16128, -2240, 12032, + 24064, 31232, 32256, 28160, 17920, 4032, -10496, -23040, -30208, -32256, + -28160, -18944, -5248, 9472, 22016, 30208, 32256, 29184, 18944, 5760, + -8960, -22016, -30208, -32256, -29184, -18944, -5504, 8960, 22016, 30208, + 32256, 28160, 18944, 4736, -9984, -23040, -31232, -32256, -28160, -16896, + -3392, 11520, 24064, 31232, 32256, 27136, 15616, 1248, -13568, -25088, + -32256, -32256, -25088, -13056, 1504, 16128, 27136, 32256, 31232, 23040, + 9984, -4736, -18944, -29184, -32256, -29184, -19968, -6272, 8960, 22016, + 30208, 32256, 27136, 16896, 1760, -13056, -25088, -32256, -31232, -24064, + -11520, 3520, 17920, 28160, 32256, 30208, 19968, 6016, -9472, -23040, + -31232, -32256, -26112, -14592, 504, 15616, 27136, 32256, 30208, 22016, + 8064, -7552, -22016, -30208, -32256, -27136, -15616, -200, 15104, 27136, + 32256, 30208, 22016, 7552, -8448, -22016, -31232, -32256, -26112, -14080, + 1504, 16896, 28160, 32256, 29184, 19968, 4736, -11008, -24064, -32256, + -31232, -24064, -10496, 5504, 19968, 30208, 32256, 27136, 15104, -376, + -16128, -28160, -32256, -29184, -18944, -4224, 12032, 25088, 32256, 31232, + 23040, 8448, -8064, -22016, -31232, -32256, -25088, -12032, 4480, 19968, + 30208, 32256, 27136, 14592, -1504, -16896, -29184, -32256, -28160, -16896, + -976, 15104, 27136, 32256, 29184, 18944, 2880, -13568, -26112, -32256, + -30208, -19968, -4224, 12544, 26112, 32256, 30208, 20992, 5248, -11520, + -25088, -32256, -30208, -20992, -5504, 11520, 25088, 32256, 30208, 20992, + 5248, -11520, -25088, -32256, -30208, -19968, -4480, 12544, 26112, 32256, + 30208, 18944, 3136, -14080, -27136, -32256, -29184, -17920, -1184, 15616, + 28160, 32256, 28160, 15616, -1248, -17920, -29184, -32256, -27136, -13056, + 4224, 19968, 30208, 32256, 24064, 9984, -7808, -23040, -32256, -31232, + -22016, -5760, 12032, 26112, 32256, 29184, 17920, 1184, -16128, -28160, + -32256, -27136, -13568, 4032, 19968, 31232, 32256, 24064, 8448, -9472, + -25088, -32256, -30208, -18944, -2112, 15616, 28160, 32256, 27136, 13056, + -4736, -20992, -31232, -31232, -22016, -6272, 12032, 26112, 32256, 29184, + 16128, -1760, -18944, -30208, -32256, -24064, -8448, 9984, 25088, 32256, + 29184, 16896, -688, -17920, -30208, -32256, -24064, -8448, 9984, 25088, + 32256, 29184, 16896, -1632, -18944, -30208, -32256, -23040, -6528, 12032, + 27136, 32256, 28160, 14080, -4736, -22016, -31232, -31232, -19968, -2624, + 15616, 29184, 32256, 25088, 9472, -9472, -25088, -32256, -29184, -15616, + 3264, 20992, 31232, 31232, 19968, 2624, -16128, -29184, -32256, -24064, + -8064, 11008, 26112, 32256, 27136, 13056, -6272, -23040, -32256, -30208, + -16896, 1824, 19968, 31232, 31232, 19968, 2368, -16896, -30208, -32256, + -23040, -6016, 13568, 28160, 32256, 25088, 8960, -10496, -26112, -32256, + -27136, -11520, 8064, 25088, 32256, 28160, 14080, -5760, -23040, -32256, + -29184, -15616, 3904, 22016, 32256, 30208, 16896, -2624, -20992, -32256, + -30208, -17920, 1696, 20992, 31232, 30208, 17920, -1248, -19968, -31232, + -31232, -17920, 1248, 19968, 31232, 30208, 17920, -1696, -20992, -31232, + -30208, -16896, 2624, 20992, 32256, 30208, 16128, -4032, -23040, -32256, + -29184, -14592, 5760, 24064, 32256, 28160, 12544, -8064, -25088, -32256, + -27136, -9984, 10496, 27136, 32256, 25088, 7040, -13568, -29184, -32256, + -22016, -3392, 16896, 30208, 31232, 18944, -656, -19968, -32256, -30208, + -15616, 5248, 24064, 32256, 28160, 11008, -9984, -27136, -32256, -24064, + -5760, 15104, 30208, 32256, 19968, -24, -19968, -32256, -30208, -15104, + 6272, 25088, 32256, 26112, 8448, -13056, -29184, -32256, -22016, -1376, + 18944, 31232, 30208, 15104, -6272, -25088, -32256, -26112, -7552, 14080, + 29184, 32256, 19968, -1056, -20992, -32256, -28160, -12032, 9984, 27136, + 32256, 23040, 2624, -18944, -31232, -30208, -14592, 7296, 26112, 32256, + 24064, 4736, -16896, -31232, -30208, -16128, 6272, 25088, 32256, 25088, + 5248, -16896, -31232, -30208, -15616, 6528, 26112, 32256, 24064, 4032, + -17920, -31232, -30208, -14080, 8448, 27136, 32256, 22016, 1184, -19968, + -32256, -28160, -10496, 12032, 29184, 32256, 18944, -3264, -24064, -32256, + -25088, -5504, 16896, 31232, 30208, 13568, -9472, -28160, -32256, -20992, + 1440, 23040, 32256, 26112, 6272, -16896, -31232, -30208, -13568, 9984, + 28160, 32256, 19968, -3008, -24064, -32256, -24064, -3648, 18944, 32256, + 28160, 9984, -13568, -30208, -31232, -15104, 8448, 27136, 32256, 19968, + -2752, -24064, -32256, -24064, -2496, 19968, 32256, 27136, 7296, -16896, + -31232, -29184, -11520, 12544, 30208, 31232, 15616, -8448, -28160, -32256, + -18944, 4992, 26112, 32256, 20992, -1632, -24064, -32256, -24064, -1440, + 22016, 32256, 25088, 4032, -19968, -32256, -27136, -6272, 17920, 32256, + 28160, 8448, -16128, -31232, -29184, -9984, 15104, 31232, 29184, 11008, + -14080, -30208, -30208, -12032, 13056, 30208, 30208, 12032, -12544, -30208, + -30208, -12544, 12544, 30208, 30208, 12032, -13056, -30208, -30208, -11520, + 13568, 31232, 29184, 10496, -14592, -31232, -29184, -9472, 15616, 31232, + 28160, 7808, -16896, -32256, -27136, -5760, 18944, 32256, 26112, 3392, + -20992, -32256, -24064, -560, 23040, 32256, 22016, -2624, -25088, -32256, + -18944, 6272, 28160, 32256, 16128, -9984, -29184, -30208, -12032, 14080, + 31232, 28160, 7552, -17920, -32256, -26112, -2752, 22016, 32256, 22016, + -2624, -26112, -32256, -17920, 8448, 29184, 31232, 12544, -14080, -31232, + -28160, -6272, 19968, 32256, 24064, -624, -25088, -32256, -18944, 7808, + 29184, 31232, 12032, -15104, -31232, -27136, -4224, 22016, 32256, 22016, + -4032, -27136, -31232, -14592, 12544, 31232, 28160, 6016, -19968, -32256, + -23040, 3264, 27136, 32256, 14592, -12544, -31232, -28160, -4992, 20992, + 32256, 20992, -5504, -28160, -31232, -12032, 15616, 32256, 26112, 880, + -24064, -32256, -16896, 10496, 30208, 28160, 6016, -20992, -32256, -20992, + 6272, 29184, 30208, 9472, -17920, -32256, -23040, 3136, 27136, 31232, + 12032, -16128, -32256, -25088, 1312, 26112, 31232, 13568, -15104, -32256, + -25088, 720, 26112, 32256, 13568, -15104, -32256, -25088, 1376, 26112, + 31232, 12544, -16128, -32256, -24064, 3392, 28160, 31232, 9984, -18944, + -32256, -20992, 6528, 29184, 29184, 6272, -22016, -32256, -17920, 11008, + 31232, 27136, 1120, -25088, -32256, -13056, 16128, 32256, 23040, -5248, + -29184, -29184, -6272, 22016, 32256, 16896, -12544, -32256, -25088, 2112, + 27136, 30208, 8448, -20992, -32256, -17920, 11520, 31232, 25088, -1696, + -27136, -30208, -8064, 20992, 32256, 16896, -13056, -32256, -24064, 3904, + 29184, 29184, 4992, -23040, -32256, -13568, 16896, 32256, 20992, -8960, + -31232, -26112, 816, 27136, 30208, 7040, -22016, -32256, -14592, 16128, + 32256, 20992, -9472, -31232, -26112, 2368, 28160, 29184, 4480, -24064, + -31232, -11008, 19968, 32256, 16896, -14080, -32256, -22016, 8448, 31232, + 26112, -3008, -29184, -29184, -2496, 26112, 31232, 7552, -23040, -32256, + -12544, 18944, 32256, 16896, -15104, -32256, -19968, 11008, 32256, 23040, + -6784, -31232, -26112, 3136, 29184, 28160, 456, -27136, -29184, -3776, + 26112, 31232, 6784, -24064, -31232, -9472, 22016, 32256, 12032, -19968, + -32256, -14080, 17920, 32256, 15616, -16896, -32256, -16896, 15104, 32256, + 17920, -14080, -32256, -18944, 13056, 32256, 19968, -12544, -32256, -19968, + 12032, 32256, 20992, -11520, -32256, -20992, 11520, 32256, 20992, -12032, + -32256, -19968, 12544, 32256, 19968, -13056, -32256, -18944, 14080, 32256, + 17920, -15616, -32256, -16128, 16896, 32256, 14592, -18944, -32256, -12544, + 19968, 32256, 10496, -22016, -31232, -7808, 24064, 31232, 4992, -26112, + -29184, -1632, 28160, 28160, -1952, -30208, -26112, 5760, 31232, 23040, + -9984, -32256, -19968, 14080, 32256, 16128, -17920, -32256, -11520, 22016, + 31232, 6784, -25088, -30208, -1312, 28160, 27136, -4480, -31232, -23040, + 10496, 32256, 18944, -16128, -32256, -12544, 22016, 31232, 6272, -26112, + -29184, 880, 30208, 25088, -8448, -32256, -19968, 15616, 32256, 12544, + -22016, -31232, -4736, 27136, 28160, -3648, -31232, -22016, 12032, 32256, + 15104, -19968, -32256, -6528, 26112, 28160, -3136, -31232, -22016, 12544, + 32256, 14080, -20992, -31232, -4224, 28160, 27136, -6528, -32256, -18944, + 16896, 32256, 8960, -25088, -29184, 2240, 31232, 22016, -13568, -32256, + -12032, 23040, 30208, -168, -30208, -23040, 12544, 32256, 12544, -23040, + -30208, 232, 30208, 23040, -13056, -32256, -11008, 24064, 29184, -2496, + -31232, -20992, 16128, 32256, 7808, -27136, -27136, 7040, 32256, 16896, + -20992, -31232, -1888, 30208, 23040, -13568, -32256, -9984, 26112, 28160, + -6272, -32256, -16128, 20992, 31232, 408, -30208, -20992, 16128, 32256, + 6016, -28160, -25088, 11008, 32256, 11008, -25088, -28160, 7040, 32256, + 14592, -23040, -29184, 3648, 32256, 16896, -20992, -30208, 1184, 31232, + 18944, -18944, -31232, -440, 31232, 19968, -18944, -31232, -1120, 31232, + 19968, -17920, -31232, -944, 31232, 19968, -18944, -31232, 200, 31232, + 18944, -19968, -30208, 2240, 32256, 16896, -22016, -29184, 5248, 32256, + 13568, -25088, -27136, 8960, 32256, 9472, -27136, -25088, 13568, 32256, + 4480, -30208, -20992, 18944, 31232, -1760, -32256, -15616, 24064, 28160, + -8960, -32256, -8448, 28160, 23040, -16128, -31232, -200, 31232, 16128, + -23040, -28160, 8960, 32256, 7296, -29184, -22016, 17920, 31232, -3392, + -32256, -12544, 26112, 25088, -14592, -32256, -592, 31232, 15616, -24064, + -27136, 12032, 32256, 2624, -31232, -16896, 24064, 27136, -11520, -32256, + -2752, 31232, 16896, -24064, -27136, 12544, 32256, 976, -32256, -14080, + 26112, 25088, -15616, -31232, 2752, 32256, 10496, -28160, -22016, 19968, + 29184, -8448, -32256, -4224, 31232, 16128, -25088, -25088, 15616, 31232, + -3904, -32256, -8064, 30208, 18944, -23040, -27136, 13568, 31232, -2752, + -32256, -8448, 30208, 18944, -24064, -26112, 15104, 31232, -4736, -32256, + -5760, 31232, 15616, -26112, -24064, 18944, 29184, -9984, -32256, 376, + 32256, 8960, -30208, -17920, 25088, 25088, -17920, -29184, 9472, 32256, + -976, -32256, -7552, 30208, 15616, -26112, -22016, 20992, 27136, -14080, + -31232, 6528, 32256, 1120, -32256, -8448, 30208, 15616, -27136, -20992, + 22016, 26112, -16896, -30208, 10496, 32256, -3904, -32256, -2496, 32256, + 8960, -30208, -14592, 28160, 19968, -24064, -24064, 19968, 27136, -15616, + -30208, 10496, 31232, -5504, -32256, 624, 32256, 4224, -32256, -8960, + 31232, 13056, -29184, -16896, 27136, 19968, -24064, -23040, 22016, 26112, + -18944, -28160, 15616, 29184, -12544, -31232, 9472, 31232, -6784, -32256, + 3904, 32256, -1312, -32256, -1184, 32256, 3392, -32256, -5504, 32256, + 7552, -31232, -8960, 31232, 10496, -31232, -12032, 30208, 13056, -30208, + -14080, 29184, 14592, -29184, -15616, 29184, 15616, -28160, -16128, 28160, + 16128, -28160, -16128, 28160, 16128, -29184, -15616, 29184, 15104, -29184, + -14592, 29184, 13568, -30208, -12544, 30208, 11008, -31232, -9472, 31232, + 8064, -32256, -6272, 32256, 4224, -32256, -1888, 32256, -592, -32256, + 3264, 32256, -6016, -32256, 8960, 31232, -12032, -30208, 15104, 28160, + -17920, -26112, 20992, 24064, -24064, -20992, 27136, 16896, -29184, -13056, + 31232, 8960, -32256, -4224, 32256, -880, -32256, 6016, 31232, -11008, + -30208, 16128, 27136, -20992, -23040, 25088, 17920, -29184, -13056, 31232, + 6784, -32256, -104, 32256, -6784, -31232, 13568, 28160, -19968, -24064, + 25088, 17920, -29184, -11008, 32256, 3520, -32256, 4736, 31232, -12544, + -28160, 19968, 23040, -26112, -16128, 30208, 7552, -32256, 1504, 32256, + -10496, -29184, 18944, 23040, -26112, -15616, 31232, 6016, -32256, 4480, + 31232, -14592, -27136, 23040, 18944, -29184, -9472, 32256, -1888, -32256, + 13056, 27136, -23040, -18944, 29184, 8448, -32256, 3520, 31232, -15104, + -25088, 25088, 16128, -31232, -3776, 32256, -8960, -29184, 20992, 20992, + -29184, -8448, 32256, -5248, -30208, 17920, 23040, -28160, -10496, 32256, + -3776, -31232, 17920, 23040, -28160, -10496, 32256, -4736, -30208, 18944, + 20992, -29184, -7552, 32256, -8448, -29184, 22016, 17920, -31232, -2112, + 32256, -14080, -25088, 27136, 11008, -32256, 6016, 29184, -22016, -17920, + 31232, 1312, -32256, 16128, 23040, -29184, -7296, 32256, -11008, -26112, + 26112, 11520, -32256, 7040, 28160, -24064, -14592, 32256, -4480, -29184, + 22016, 16896, -32256, 3008, 30208, -22016, -16896, 32256, -3008, -30208, + 22016, 16128, -32256, 4480, 29184, -23040, -14080, 32256, -7040, -28160, + 25088, 11008, -32256, 11008, 25088, -28160, -6016, 32256, -16128, -20992, + 31232, -232, -30208, 22016, 15104, -32256, 7808, 27136, -27136, -7296, + 32256, -16896, -19968, 31232, -2752, -29184, 25088, 11008, -32256, 13568, + 22016, -31232, 1248, 30208, -24064, -11008, 32256, -14592, -20992, 31232, + -3264, -28160, 26112, 7808, -32256, 17920, 17920, -32256, 8960, 25088, + -29184, -656, 30208, -24064, -9472, 32256, -17920, -17920, 32256, -9984, + -24064, 30208, -2368, -28160, 27136, 4736, -31232, 23040, 11520, -32256, + 17920, 16896, -32256, 12544, 22016, -32256, 7296, 25088, -30208, 2496, + 28160, -28160, -1824, 30208, -26112, -5504, 31232, -24064, -8448, 32256, + -22016, -11008, 32256, -19968, -13056, 32256, -18944, -14592, 32256, -17920, + -15616, 32256, -16896, -15616, 32256, -16896, -15616, 32256, -16896, -15104, + 32256, -17920, -14080, 32256, -18944, -12544, 32256, -20992, -10496, 32256, + -23040, -7552, 31232, -25088, -4224, 30208, -27136, -376, 28160, -29184, + 4224, 25088, -31232, 8960, 20992, -32256, 14592, 16896, -32256, 19968, + 11008, -31232, 25088, 4032, -29184, 29184, -3520, -25088, 31232, -11520, + -18944, 32256, -18944, -11008, 31232, -26112, -1568, 27136, -30208, 8448, + 20992, -32256, 17920, 11520, -31232, 26112, 280, -26112, 31232, -11520, + -17920, 32256, -22016, -5760, 29184, -30208, 7296, 20992, -32256, 19968, + 8064, -30208, 29184, -6528, -20992, 32256, -19968, -7296, 29184, -30208, + 8448, 18944, -32256, 23040, 3264, -27136, 31232, -13568, -13568, 31232, + -27136, 4032, 22016, -32256, 20992, 4992, -28160, 31232, -14080, -12544, + 31232, -28160, 7296, 18944, -32256, 25088, -1184, -23040, 32256, -20992, + -3904, 26112, -32256, 17920, 7808, -28160, 31232, -15104, -10496, 29184, + -30208, 13056, 12032, -30208, 30208, -12032, -13056, 30208, -30208, 12544, + 12544, -30208, 30208, -13568, -11008, 29184, -31232, 15616, 8448, -28160, + 32256, -18944, -4992, 26112, -32256, 22016, 200, -22016, 32256, -26112, + 5760, 16896, -31232, 29184, -12544, -11008, 28160, -32256, 19968, 2496, + -23040, 32256, -26112, 7040, 15616, -30208, 31232, -16896, -4992, 25088, + -32256, 26112, -7040, -15104, 30208, -31232, 18944, 1888, -22016, 32256, + -28160, 12544, 8960, -26112, 32256, -25088, 7040, 14080, -29184, 32256, + -22016, 3264, 16896, -30208, 31232, -19968, 1184, 17920, -31232, 31232, + -19968, 976, 17920, -30208, 31232, -20992, 2496, 16896, -30208, 32256, + -23040, 6016, 13568, -28160, 32256, -26112, 11008, 8064, -24064, 32256, + -30208, 17920, 560, -17920, 30208, -32256, 24064, -8960, -9472, 25088, + -32256, 30208, -18944, 1952, 15616, -28160, 32256, -28160, 15104, 2240, + -18944, 30208, -32256, 26112, -13056, -3648, 18944, -30208, 32256, -27136, + 14080, 2240, -17920, 29184, -32256, 28160, -16896, 1760, 14080, -26112, + 32256, -31232, 22016, -8448, -7040, 20992, -30208, 32256, -28160, 16896, + -3008, -12032, 24064, -31232, 32256, -26112, 15104, -1184, -13056, 25088, + -31232, 32256, -27136, 16896, -3264, -10496, 23040, -30208, 32256, -29184, + 20992, -8960, -4480, 16896, -27136, 32256, -32256, 27136, -17920, 6016, +}; diff --git a/test/cmocka/src/math/arithmetic/a_law_mu_law_test_vectors.m b/test/cmocka/src/math/arithmetic/a_law_mu_law_test_vectors.m new file mode 100644 index 000000000000..b9f5b6b6a8e5 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/a_law_mu_law_test_vectors.m @@ -0,0 +1,229 @@ +% a_law_mu_law_test_vectors() - Create A-law and mu-law test vectors +% +% Running this script creates header files ref_chirp_mono_8k_s16.h, +% a_law_codec.h, and mu_law_codec.h. The chirp waveform for test +% input is created with sox, and then ended and decoded as +% A-law and mu-law. + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2025 Intel Corporation. + +function a_law_mu_law_test_vectors() + + sox = 0; + alaw = 1; + mulaw = 1; + bits = 16; + ts = 0.5; + fs = 8e3; + t = (0:round(ts*fs - 1))/fs; + x = round(2^(bits - 1) * chirp(t, 100, ts, 3.5e3, 'logarithmic')); + xmax = 2^(bits - 1) - 1; + xmin = -2^(bits - 1); + x = max(min(x, xmax), xmin); + ref_s16_data = int16(x); + + ref_s16_header_fn = 'ref_chirp_mono_8k_s16.h'; + ref_alaw_header_fn = 'a_law_codec.h'; + ref_mulaw_header_fn = 'mu_law_codec.h'; + + close all; + path(path(), '../../../m'); + + if sox + ref_s16 = '/tmp/chirp_mono_8k_s16.raw'; + ref_alaw_enc = '/tmp/ref_alaw_enc.raw'; + ref_alaw_dec = '/tmp/ref_alaw_dec.raw'; + ref_mulaw_enc = '/tmp/ref_mulaw_enc.raw'; + ref_mulaw_dec = '/tmp/ref_mulaw_dec.raw'; + sox_s16_chirp_gen = sprintf('sox -c 1 -r 8000 -b 16 --encoding signed-integer -n %s synth 0.5 sine 100-3500', ref_s16); + sox_alaw_enc = sprintf('sox -c 1 -r 8000 -b 16 --encoding signed-integer %s --encoding a-law %s', ref_s16, ref_alaw_enc); + sox_alaw_dec = sprintf('sox -c 1 -r 8000 --encoding a-law %s -b 16 --encoding signed-integer %s', ref_alaw_enc, ref_alaw_dec); + sox_mulaw_enc = sprintf('sox -c 1 -r 8000 -b 16 --encoding signed-integer %s --encoding a-law %s', ref_s16, ref_mulaw_enc); + sox_mulaw_dec = sprintf('sox -c 1 -r 8000 --encoding a-law %s -b 16 --encoding signed-integer %s', ref_mulaw_enc, ref_mulaw_dec); + system(sox_s16_chirp_gen); + system(sox_alaw_enc); + system(sox_alaw_dec); + system(sox_mulaw_enc); + system(sox_mulaw_dec); + ref_s16_data = readbin(ref_s16, 'int16'); figure; + ref_alaw_enc_data = readbin(ref_alaw_enc, 'uint8'); + ref_alaw_dec_data = readbin(ref_alaw_dec, 'int16'); + ref_mulaw_enc_data = readbin(ref_mulaw_enc, 'uint8'); + ref_mulaw_dec_data = readbin(ref_mulaw_dec, 'int16'); + else + if alaw + ref_alaw_enc_data = alaw_enc(ref_s16_data); + ref_alaw_dec_data = alaw_dec(ref_alaw_enc_data); + end + if mulaw + ref_mulaw_enc_data = mulaw_enc(ref_s16_data); + ref_mulaw_dec_data = mulaw_dec(ref_mulaw_enc_data); + end + end + + if alaw + plot(ref_s16_data); grid on; title('Input s16'); + figure; plot(ref_alaw_enc_data); grid on; title('A-law data'); + figure; plot(ref_alaw_dec_data); grid on; title('A-law decode s16'); + end + + if mulaw + figure; plot(ref_mulaw_enc_data); grid on; title('mu-law data'); + figure; plot(ref_mulaw_dec_data); grid on; title('mu-law decode s16'); + end + + fh = export_headerfile_open(ref_s16_header_fn); + comment = sprintf('Created %s with script a_law_mu_law_test_vectors.m %s', ... + datestr(now, 0), export_get_git_describe()); + export_comment(fh, comment); + fprintf(fh, '#include <stdint.h>\n'); + export_ndefine(fh, 'REF_DATA_SAMPLE_COUNT', length(ref_s16_data)); + export_vector(fh, 16, 'chirp_mono_8k_s16', ref_s16_data); + fclose(fh); + + if alaw + fh = export_headerfile_open(ref_alaw_header_fn); + comment = sprintf('Created %s with script a_law_mu_law_test_vectors.m %s', ... + datestr(now, 0), export_get_git_describe()); + export_comment(fh, comment); + fprintf(fh, '#include <stdint.h>\n'); + export_vector(fh, 8, 'ref_alaw_enc_data', ref_alaw_enc_data); + export_vector(fh, 16, 'ref_alaw_dec_data', ref_alaw_dec_data); + fclose(fh); + end + + if mulaw + fh = export_headerfile_open(ref_mulaw_header_fn); + comment = sprintf('Created %s with script a_law_mu_law_test_vectors.m %s', ... + datestr(now, 0), export_get_git_describe()); + export_comment(fh, comment); + fprintf(fh, '#include <stdint.h>\n'); + export_vector(fh, 8, 'ref_mulaw_enc_data', ref_mulaw_enc_data); + export_vector(fh, 16, 'ref_mulaw_dec_data', ref_mulaw_dec_data); + fclose(fh); + end + +end + +function x = readbin(fn, itype) + fh = fopen(fn, 'r'); + if fh == -1 + fprintf(1, 'Could not open file %s.\n', fn); + error("Failed."); + end + x = fread(fh, inf, itype); + fclose(fh); +end + +% See G.711 alaw compress from +% https://www.itu.int/rec/T-REC-G.191/ +function encoded = alaw_enc(input_samples) + num_samples = length(input_samples); + in16 = int16(input_samples); + encoded_samples = uint8(zeros(num_samples, 1)); + for n = 1:num_samples + if in16(n) < 0 + ix = bitshift(-in16(n) -1, -4); % 1's complement + else + ix = bitshift(in16(n), -4); + end + + if ix > 15 + iexp = 1; + while (ix > 16 + 15) + ix = bitshift(ix, -1); + iexp = iexp + 1; + end + + ix = ix - 16; + ix = ix + bitshift(iexp, 4); + end + + if in16(n) >= 0 + ix = bitor(ix, 128); + end + + encoded(n) = bitxor(ix, 85); + end +end + +% See G.711 alaw expand from +% https://www.itu.int/rec/T-REC-G.191/ +function samples_s16 = alaw_dec(input_bytes) + num_samples = length(input_bytes); + samples_s16 = int16(zeros(num_samples, 1)); + for n = 1:num_samples + ix = bitxor(int16(input_bytes(n)), 85); + ix = bitand(ix, 127); + iexp = bitshift(ix, -4); + mant = bitand(ix, 15); + if iexp > 0 + mant = mant + 16; + end + + mant = bitshift(mant, 4) + 8; + if iexp > 1 + mant = bitshift(mant, iexp - 1); + end + + if input_bytes(n) > 127 + samples_s16(n) = mant; + else + samples_s16(n) = -mant; + end + end +end + +% See G.711 ulaw compress from +% https://www.itu.int/rec/T-REC-G.191/ +function encoded = mulaw_enc(input_samples) + num_samples = length(input_samples); + in16 = int16(input_samples); + encoded_samples = uint8(zeros(num_samples, 1)); + for n = 1:num_samples + if in16(n) < 0 + absno = bitshift(-in16(n) -1, -2) + 33; % 1's complement + else + absno = bitshift(in16(n), -2) + 33; + end + + absno = min(absno, 8191); + i = bitshift(absno, -6); + segno = 1; + while i > 0 + segno = segno + 1; + i = bitshift(i, -1); + end + + high_nibble = 8 - segno; + low_nibble = bitand(bitshift(absno, -segno), 15); + low_nibble = 15 - low_nibble; + encoded(n) = bitor(bitshift(high_nibble, 4), low_nibble); + if in16(n) >= 0 + encoded(n) = bitor(encoded(n), 128); + end + end +end + +% See G.711 alaw expand from +% https://www.itu.int/rec/T-REC-G.191/ +function samples_s16 = mulaw_dec(input_bytes) + num_samples = length(input_bytes); + samples_s16 = int16(zeros(num_samples, 1)); + for n = 1:num_samples + if input_bytes(n) < 128 + sign = -1; + else + sign = 1; + end + + mantissa = -int16(input_bytes(n)) - 1; % 1's complement + exponent = bitand(bitshift(mantissa, -4), 7); + segment = exponent + 1; + mantissa = bitand(mantissa, 15); + step = bitshift(4, segment); + samples_s16(n) = sign * (bitshift(128, exponent) + step * mantissa + step / 2 - 4 * 33); + end +end diff --git a/test/cmocka/src/math/arithmetic/base2_logarithm.c b/test/cmocka/src/math/arithmetic/base2_logarithm.c new file mode 100644 index 000000000000..a06e44d09b78 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/base2_logarithm.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> +#include <string.h> + +#include <sof/math/log.h> +#include <sof/audio/format.h> +#include <rtos/string.h> +#include <sof/common.h> +#include "log2_tables.h" +/* 'Error[max] = 0.0000236785999981,THD(-dBc) = -92.5128795787487235' */ +#define CMP_TOLERANCE 0.0000236785691029 + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +static void test_math_arithmetic_base2log_fixed(void **state) +{ + (void)state; + + uint32_t u[100]; + int i; + + memcpy_s((void *)&u[0], sizeof(u), (void *)&uv[0], 100U * sizeof(uint32_t)); + for (i = 0; i < ARRAY_SIZE(log2_lookup_table); i++) { + float y = Q_CONVERT_QTOF(base2_logarithm(u[i]), 0); + float diff = fabs(log2_lookup_table[i] - (double)y / (1 << 16)); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: value = %.16f, log2 = %.16f\n", __func__, diff, + (double)u[i], (double)y / (1 << 16)); + assert_true(diff <= CMP_TOLERANCE); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_base2log_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/base_10_logarithm.c b/test/cmocka/src/math/arithmetic/base_10_logarithm.c new file mode 100644 index 000000000000..3973df31a515 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/base_10_logarithm.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> +// +// + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> +#include <string.h> + +#include <sof/math/log.h> +#include <sof/audio/format.h> +#include <rtos/string.h> +#include <sof/common.h> +#include "log2_tables.h" +/* 'Error[max] = 0.0000071279028671,THD = -102.9407645424143993 ' */ +/* 'Error[max] = rms(log10() - double(log10_int32()))' */ +/* 'THD = 20*log10(Error[max])' */ +#define CMP_TOLERANCE 0.0000071279028671 +/* Natural logarithm log10(X) reference table generated by matlab/Octave */ +/* UQ4.28 */ +static const double common_log10_ref_table[] = { + 0.0000000000000000, 7.6373246662453802, 7.9383546619093615, 8.1144459209650428, + 8.2393846575733427, 8.3362946705813989, 8.4154759166290241, 8.4824227062596371, + 8.5404146532373240, 8.5915671756847054, 8.6373246662453802, 8.6787173514036056, + 8.7165059122930053, 8.7512680193222625, 8.7834527026386606, 8.8134159259684335, + 8.8414446495269665, 8.8677735882125130, 8.8925971719048302, 8.9160782677250818, + 8.9383546624098908, 8.9595439614559940, 8.9797473475226131, 8.9990525026982162, + 9.0175359083740947, 9.0352646753178405, 9.0522980146012202, 9.0686884307751292, + 9.0844826979451199, 9.0997226644895282, 9.1144459212987297, 9.1286863604025754, + 9.1424746448781171, 9.1558386064266184, 9.1688035835820649, 9.1813927108816724, + 9.1936271672907388, 9.2055263908534872, 9.2171082633890631, 9.2283892737852433, + 9.2393846580738721, 9.2501085234534361, 9.2605739571199752, 9.2707931222905753, + 9.2807773431865943, 9.2905371804656394, 9.3000824983621975, 9.3094225246070792, + 9.3185659040380759, 9.3275207466824899, 9.3362946709818218, 9.3448948427358882, + 9.3533280102652014, 9.3616005362239267, 9.3697184264391105, 9.3776873561036460, + 9.3855126936091011, 9.3931995222691196, 9.4007526601535094, 9.4081766782268659, + 9.4154759169627091, 9.4226545015843630, 9.4297163562280168, 9.4366652161756566, + 9.4435046406985137, 9.4502380233502628, 9.4568686022422757, 9.4633994693944423, + 9.4698335793932600, 9.4761737574178788, 9.4824227066886628, 9.4885830153874373, + 9.4946571630937573, 9.5006475267772306, 9.5065563863821918, 9.5123859300375031, + 9.5181382589213257, 9.5238153918078847, 9.5294192693208828, 9.5349517579159713, + 9.5404146536127215, 9.5458096854947918, 9.5511385189953373, 9.5564027589832818, + 9.5616039526647825, 9.5667435923129869, 9.5718231178381536, 9.5768439193242560, + 9.5818073388505756, 9.5867146733402073, 9.5915671761296206, 9.5963660590064990, + 9.6011124940261787, 9.6058076152298781, 9.6104525202710605, 9.6150482719557271, + 9.6195958997020572, 9.6240964009244330, 9.6285507423464711, 9.6329598611462810}; + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +static void test_math_arithmetic_base10log_fixed(void **state) +{ + (void)state; + + double clogfxp; + double diff; + int i; + + for (i = 0; i < ARRAY_SIZE(common_log10_ref_table); i++) { + clogfxp = log10_int32(uv[i]); + diff = fabs(common_log10_ref_table[i] - (double)clogfxp / (1 << 28)); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: val = %16d, log10() = %.16f\n", __func__, diff, + uv[i], clogfxp / (1 << 28)); + assert_true(diff <= CMP_TOLERANCE); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_base10log_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/base_e_logarithm.c b/test/cmocka/src/math/arithmetic/base_e_logarithm.c new file mode 100644 index 000000000000..c2c1d2083c8b --- /dev/null +++ b/test/cmocka/src/math/arithmetic/base_e_logarithm.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> +#include <string.h> + +#include <sof/math/log.h> +#include <sof/audio/format.h> +#include <rtos/string.h> +#include <sof/common.h> +#include "log2_tables.h" +/* 'Error[max] = 0.0000164133276926,THD(-dBc) = -95.6960671942683234' */ +/* 'Error[max] = rms(log() - double(log_int32()))' */ +/* 'THD = 20*log10(Error[max])' */ +#define CMP_TOLERANCE 0.0000164133276926 + +/* Natural logarithm loge(X) reference table generated by matlab/Octave */ +/* UQ5.27 */ +static const double natural_log_lookup_table[] = { + 0.0000000000000000, 17.5855899268523359, 18.2787371074122831, 18.6842022155204468, + 18.9718842879722267, 19.1950278392864391, 19.3773493960803940, 19.5315000759076511, + 19.6650314685321739, 19.7828145041885577, 19.8881750198463827, 19.9834851996507084, + 20.0704965766403376, 20.1505392860869676, 20.2246472581140395, 20.2936401294912301, + 20.3581786505327571, 20.4188032722644479, 20.4759616860290699, 20.5300289072319480, + 20.5813222015588408, 20.6301123656733907, 20.6766323812583899, 20.7210841437836706, + 20.7636437581607112, 20.8044657526425461, 20.8436864657603671, 20.8814267937103786, + 20.9177944378507625, 20.9528857576336485, 20.9867873092828354, 21.0195771320810394, + 21.0513258303723845, 21.0820974890173112, 21.1119504521464485, 21.1409379890003279, + 21.1691088659487328, 21.1965078407425196, 21.2231760877918916, 21.2491515741640455, + 21.2744693821187845, 21.2991619946810467, 21.3232595462333343, 21.3467900436180038, + 21.3697795618183370, 21.3922524176471107, 21.4142313243436178, 21.4357375295432568, + 21.4567909387206548, 21.4774102259037889, 21.4976129332024932, 21.5174155604805932, + 21.5368336463203107, 21.5558818412742781, 21.5745739742703257, 21.5929231129229997, + 21.6109416184107097, 21.6286411954956677, 21.6460329381935921, 21.6631273715394208, + 21.6799344898427790, 21.6964637917813938, 21.7127243130127638, 21.7287246543415016, + 21.7444730112924880, 21.7599771978118319, 21.7752446699265008, 21.7902825472754031, + 21.8050976330453672, 21.8196964324517815, 21.8340851698895619, 21.8482698048676056, + 21.8622560468288185, 21.8760493689479993, 21.8896550209909755, 21.9030780413106569, + 21.9163232680485471, 21.9293953496040821, 21.9422987544284780, 21.9550377801946830, + 21.9676165623906030, 21.9800390823784895, 21.9923091749598925, 22.0044305354820757, + 22.0164067265188734, 22.0282411841561903, 22.0399372239099236, 22.0514980465667030, + 22.0629267423782807, 22.0742262976204415, 22.0853995982070579, 22.0964494343823858, + 22.1073785049035614, 22.1181894209970018, 22.1288847101032040, 22.1394668194234150, + 22.1499381192805984, 22.1603009063062437, 22.1705574064637361, 22.1807097776854185}; + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +static void test_math_arithmetic_base_e_log_fixed(void **state) +{ + (void)state; + + double logefxp; + double diff; + int i; + + for (i = 0; i < ARRAY_SIZE(natural_log_lookup_table); i++) { + logefxp = ln_int32(uv[i]); + diff = fabs(natural_log_lookup_table[i] - (double)logefxp / (1 << 27)); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: value = %16d, log() = %.16f\n", __func__, diff, + uv[i], logefxp / (1 << 27)); + assert_true(diff <= CMP_TOLERANCE); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_base_e_log_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/exponential.c b/test/cmocka/src/math/arithmetic/exponential.c new file mode 100644 index 000000000000..3e44bf0c3743 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/exponential.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022-2025 Intel Corporation. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> +#include <string.h> +#include <time.h> +#include <stdlib.h> + +#include <sof/math/exp_fcn.h> +#include <sof/audio/format.h> +#include <rtos/string.h> +#include <sof/common.h> + +#define ULP_TOLERANCE 1.0 +#define ULP_SCALE 1.9073e-06 /* For exp() output Q13.19, 1 / 2^19 */ +#define NUMTESTSAMPLES 256 + +#define NUMTESTSAMPLES_TEST2 100 +#define ABS_DELTA_TOLERANCE_TEST2 2.0e-6 +#define REL_DELTA_TOLERANCE_TEST2 1000.0 /* rel. error is large with values near zero */ +#define NUMTESTSAMPLES_TEST3 100 +#define ABS_DELTA_TOLERANCE_TEST3 2.0e-6 +#define REL_DELTA_TOLERANCE_TEST3 10.0e-2 +#define SOFM_EXP_FIXED_ARG_MIN -11.5 +#define SOFM_EXP_FIXED_ARG_MAX 7.6245 + +#define NUMTESTSAMPLES_TEST4 100 +#define ABS_DELTA_TOLERANCE_TEST4 2.5e-5 +#define REL_DELTA_TOLERANCE_TEST4 1000.0 /* rel. error is large with values near zero */ + +/** + * Saturates input to 32 bits + * @param x Input value + * @return Saturated output value + */ +static int32_t saturate32(int64_t x) +{ + if (x < INT32_MIN) + return INT32_MIN; + else if (x > INT32_MAX) + return INT32_MAX; + + return x; +} + +/** + * Generates linearly spaced values for a vector with end points and number points in + * desired fractional Q-format for 32 bit integer. If the test values exceed int32_t + * range, the values are saturated to INT32_MIN to INT32_MAX range. + * + * @param a First value of test vector + * @param b Last value of test vector + * @param step_count Number of values in vector + * @param point Calculate n-th point of vector 0 .. step_count - 1 + * @param qformat Number of fractional bits y in Qx.y format + * @param fout Pointer to calculated test vector value, double + * @param iout Pointer to calculated test vector value, int32_t + */ +static void gen_testvector_linspace_int32(double a, double b, int step_count, int point, + int qformat, double *fout, int32_t *iout) +{ + double fstep = (b - a) / (step_count - 1); + double fvalue = a + fstep * point; + int64_t itmp; + + itmp = (int64_t)round(fvalue * (double)(1 << qformat)); + *iout = saturate32(itmp); + *fout = (double)*iout / (1 << qformat); + return; +} + +/** + * Test for sofm_exp_approx() + * @param state Cmocka internal state + */ +static void test_function_sofm_exp_approx(void **state) +{ + (void)state; + + int32_t accum; + int i; + double a_i; + double max_ulp = 0; + double ulp; + double a_tmp = -8; + double b_tmp = 8; + int32_t b_i; + + for (i = 0; i < NUMTESTSAMPLES; i++) { + gen_testvector_linspace_int32(a_tmp, b_tmp, NUMTESTSAMPLES, i, 28, &a_i, &b_i); + accum = sofm_exp_approx(b_i); + ulp = fabs(exp(a_i) - (double)accum / (1 << 19)) / ULP_SCALE; + if (ulp > max_ulp) + max_ulp = ulp; + + if (ulp > ULP_TOLERANCE) { + printf("%s: ULP for %.16f: value = %.16f, Exp = %.16f\n", __func__, + ulp, (double)b_i / (1 << 28), (double)accum / (1 << 19)); + assert_true(false); + } + } + printf("%s: Worst-case ULP: %g ULP_SCALE %g\n", __func__, max_ulp, ULP_SCALE); +} + + +/** + * Calculate reference exponent value + * @param x Input value + * @param qformat Fractional bits y in Qx.y format + * @return Saturated exponent value to match fractional format + */ +static double ref_exp(double x, int qformat) +{ + double yf; + int64_t yi; + + yf = exp(x); + yi = yf * (1 << qformat); + if (yi > INT32_MAX) + yi = INT32_MAX; + else if (yi < INT32_MIN) + yi = INT32_MIN; + + yf = (double)yi / (1 << qformat); + return yf; +} + +/** + * Calculates test exponent function and compares result to reference exponent. + * @param ivalue Fractional format input value Q5.27 + * @param iexp_value Fractional format output value Q12.20 + * @param abs_delta_max Calculated absolute error + * @param rel_delta_max Calculated relative error + * @param abs_delta_tolerance Tolerance for absolute error + * @param rel_delta_tolerance Tolerance for relative error + */ +static void test_exp_with_input_value(int32_t ivalue, int32_t *iexp_value, + double *abs_delta_max, double *rel_delta_max, + double abs_delta_tolerance, double rel_delta_tolerance) +{ + double fvalue, fexp_value, ref_exp_value; + double rel_delta, abs_delta; + double eps = 1e-9; + + *iexp_value = sofm_exp_fixed(ivalue); + fvalue = (double)ivalue / (1 << 27); /* Q5.27 */ + fexp_value = (double)*iexp_value / (1 << 20); /* Q12.20 */ + ref_exp_value = ref_exp(fvalue, 20); + abs_delta = fabs(ref_exp_value - fexp_value); + rel_delta = abs_delta / (ref_exp_value + eps); + if (abs_delta > *abs_delta_max) + *abs_delta_max = abs_delta; + + if (rel_delta > *rel_delta_max) + *rel_delta_max = rel_delta; + + if (abs_delta > abs_delta_tolerance) { + printf("%s: Absolute error %g exceeds limit %g, input %g output %g.\n", + __func__, abs_delta, abs_delta_tolerance, fvalue, fexp_value); + assert_true(false); + } + + if (rel_delta > rel_delta_tolerance) { + printf("%s: Relative error %g exceeds limit %g, input %g output %g.\n", + __func__, rel_delta, rel_delta_tolerance, fvalue, fexp_value); + assert_true(false); + } +} + +/** + * Test for sofm_exp_fixed() + * @param state Cmocka internal state + */ +static void test_function_sofm_exp_fixed(void **state) +{ + (void)state; + double rel_delta_max, abs_delta_max; + double tmp; + int32_t ivalue, iexp_value; + int i; + + /* Test max int32_t range with coarse grid */ + rel_delta_max = 0; + abs_delta_max = 0; + for (i = 0; i < NUMTESTSAMPLES_TEST2; i++) { + gen_testvector_linspace_int32(-16, 16, NUMTESTSAMPLES_TEST2, i, 27, &tmp, &ivalue); + test_exp_with_input_value(ivalue, &iexp_value, &abs_delta_max, &rel_delta_max, + ABS_DELTA_TOLERANCE_TEST2, REL_DELTA_TOLERANCE_TEST2); + } + + printf("%s: Absolute max error was %.6e (max range).\n", __func__, abs_delta_max); + printf("%s: Relative max error was %.6e (max range).\n", __func__, rel_delta_max); + + /* Test max int32_t middle range with fine grid */ + rel_delta_max = 0; + abs_delta_max = 0; + for (i = 0; i < NUMTESTSAMPLES_TEST3; i++) { + gen_testvector_linspace_int32(SOFM_EXP_FIXED_ARG_MIN, SOFM_EXP_FIXED_ARG_MAX, + NUMTESTSAMPLES_TEST3, i, 27, &tmp, &ivalue); + test_exp_with_input_value(ivalue, &iexp_value, &abs_delta_max, &rel_delta_max, + ABS_DELTA_TOLERANCE_TEST3, REL_DELTA_TOLERANCE_TEST3); + } + + printf("%s: Absolute max error was %.6e (middle).\n", __func__, abs_delta_max); + printf("%s: Relative max error was %.6e (middle).\n", __func__, rel_delta_max); +} + +/** + * Reference function for dB to linear conversion + * @param x Input value + * @param qformat Fractional bits y in Qx.y format for saturation + * @return Saturated linear value + */ +static double ref_db2lin(double x, int qformat) +{ + double fref; + int64_t iref; + + fref = pow(10, x / 20); + iref = fref * (1 << qformat); + return (double)saturate32(iref) / (1 << qformat); +} + +/** + * Test for sofm_db2lin_fixed() + * @param state Cmocka internal state + */ +static void test_function_sofm_db2lin_fixed(void **state) +{ + (void)state; + double abs_delta, rel_delta, abs_delta_max, rel_delta_max; + double fin, fout, fref; + double eps = 1e-9; + int32_t iin, iout; + int i; + + rel_delta_max = 0; + abs_delta_max = 0; + for (i = 0; i < NUMTESTSAMPLES_TEST2; i++) { + gen_testvector_linspace_int32(-128, 128, NUMTESTSAMPLES_TEST4, i, 24, &fin, &iin); + iout = sofm_db2lin_fixed(iin); + fout = (double)iout / (1 << 20); + fref = ref_db2lin(fin, 20); + abs_delta = fabs(fref - fout); + rel_delta = abs_delta / (fref + eps); + if (abs_delta > abs_delta_max) + abs_delta_max = abs_delta; + + if (rel_delta > rel_delta_max) + rel_delta_max = rel_delta; + + if (abs_delta > ABS_DELTA_TOLERANCE_TEST4) { + printf("%s: Absolute error %g exceeds limit %g, input %g output %g.\n", + __func__, abs_delta, ABS_DELTA_TOLERANCE_TEST4, fin, fout); + assert_true(false); + } + + if (rel_delta > REL_DELTA_TOLERANCE_TEST4) { + printf("%s: Relative error %g exceeds limit %g, input %g output %g.\n", + __func__, rel_delta, REL_DELTA_TOLERANCE_TEST4, fin, fout); + assert_true(false); + } + } + printf("%s: Absolute max error was %.6e.\n", __func__, abs_delta_max); + printf("%s: Relative max error was %.6e.\n", __func__, rel_delta_max); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_function_sofm_exp_approx), + cmocka_unit_test(test_function_sofm_exp_fixed), + cmocka_unit_test(test_function_sofm_db2lin_fixed), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/mu_law_codec.c b/test/cmocka/src/math/arithmetic/mu_law_codec.c new file mode 100644 index 000000000000..cee690e9e947 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/mu_law_codec.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <stdio.h> +#include <stdint.h> +#include <setjmp.h> +#include <stdbool.h> +#include <cmocka.h> +#include <sof/math/mu_law.h> + +#include "ref_chirp_mono_8k_s16.h" +#include "mu_law_codec.h" + +static void test_mu_law_encode(void **state) +{ + (void)state; + + uint8_t mu_law_sample, mu_law_ref; + int i; + + for (i = 0; i < REF_DATA_SAMPLE_COUNT; i++) { + mu_law_sample = sofm_mu_law_encode(chirp_mono_8k_s16[i]); + mu_law_ref = ref_mulaw_enc_data[i]; + + if (mu_law_sample != mu_law_ref) { + printf("%s: difference found at %d, encoded %d, ref %d, lin %d\n", + __func__, i, mu_law_sample, mu_law_ref, chirp_mono_8k_s16[i]); + assert_true(false); + } + } +} + +static void test_mu_law_decode(void **state) +{ + (void)state; + + int16_t s16_sample, s16_ref; + int i; + + for (i = 0; i < REF_DATA_SAMPLE_COUNT; i++) { + s16_sample = sofm_mu_law_decode(ref_mulaw_enc_data[i]); + s16_ref = ref_mulaw_dec_data[i]; + if (s16_sample != s16_ref) { + printf("%s: difference found at %d, byte %d, decoded %d, ref %d\n", + __func__, i, ref_mulaw_enc_data[i], s16_sample, s16_ref); + assert_true(false); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_mu_law_encode), + cmocka_unit_test(test_mu_law_decode), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/mu_law_codec.h b/test/cmocka/src/math/arithmetic/mu_law_codec.h new file mode 100644 index 000000000000..802b2c4fd235 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/mu_law_codec.h @@ -0,0 +1,814 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 13-May-2025 18:29:28 with script a_law_mu_law_test_vectors.m */ + +#include <stdint.h> + +static const uint8_t ref_mulaw_enc_data[4000] = { + 130, 131, 132, 134, 135, 137, 139, 141, 143, 147, + 151, 156, 162, 172, 189, 94, 55, 41, 31, 26, + 22, 17, 14, 12, 10, 8, 6, 5, 4, 2, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 2, + 3, 4, 5, 7, 9, 11, 13, 15, 19, 23, + 28, 35, 46, 67, 206, 178, 166, 158, 153, 148, + 143, 141, 139, 137, 135, 134, 132, 131, 130, 129, + 128, 128, 128, 128, 128, 128, 129, 130, 131, 132, + 133, 135, 137, 139, 141, 143, 148, 153, 158, 168, + 182, 223, 60, 43, 32, 27, 21, 17, 14, 11, + 9, 7, 6, 4, 3, 2, 1, 0, 0, 0, + 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, + 12, 14, 18, 23, 28, 36, 47, 74, 196, 173, + 162, 155, 150, 145, 142, 140, 137, 135, 134, 132, + 131, 130, 129, 128, 128, 128, 128, 128, 128, 129, + 130, 132, 133, 135, 137, 139, 141, 144, 149, 155, + 161, 173, 194, 75, 47, 35, 28, 22, 17, 14, + 11, 9, 7, 5, 4, 2, 1, 0, 0, 0, + 0, 0, 0, 1, 2, 3, 5, 6, 8, 10, + 13, 15, 20, 26, 31, 43, 62, 207, 175, 164, + 156, 150, 145, 142, 139, 137, 135, 133, 131, 130, + 129, 128, 128, 128, 128, 128, 128, 129, 130, 132, + 134, 135, 138, 140, 142, 147, 152, 158, 169, 187, + 86, 49, 36, 28, 22, 16, 13, 11, 9, 6, + 5, 3, 2, 1, 0, 0, 0, 0, 0, 1, + 2, 3, 5, 7, 9, 11, 14, 17, 23, 29, + 39, 55, 234, 179, 165, 156, 150, 144, 141, 139, + 136, 134, 132, 131, 130, 129, 128, 128, 128, 128, + 128, 129, 130, 132, 134, 136, 138, 141, 143, 149, + 155, 163, 176, 216, 57, 39, 29, 23, 17, 13, + 11, 8, 6, 4, 3, 1, 0, 0, 0, 0, + 0, 0, 1, 3, 4, 6, 9, 11, 14, 18, + 24, 30, 42, 63, 200, 172, 159, 153, 147, 142, + 139, 137, 135, 133, 131, 130, 128, 128, 128, 128, + 128, 128, 130, 131, 133, 135, 137, 140, 142, 147, + 154, 161, 174, 213, 57, 38, 28, 22, 16, 13, + 10, 8, 5, 3, 2, 1, 0, 0, 0, 0, + 0, 1, 3, 5, 7, 9, 12, 14, 20, 26, + 34, 49, 107, 180, 164, 155, 148, 143, 140, 137, + 135, 133, 131, 129, 128, 128, 128, 128, 128, 129, + 130, 132, 134, 136, 139, 142, 146, 153, 160, 174, + 214, 55, 37, 27, 20, 15, 12, 9, 7, 4, + 3, 1, 0, 0, 0, 0, 0, 1, 3, 5, + 7, 9, 12, 15, 21, 28, 39, 60, 199, 171, + 158, 151, 144, 141, 138, 135, 133, 131, 129, 128, + 128, 128, 128, 128, 129, 131, 133, 135, 137, 140, + 143, 150, 157, 170, 196, 61, 39, 28, 21, 15, + 12, 9, 6, 4, 2, 1, 0, 0, 0, 0, + 1, 2, 4, 6, 8, 11, 15, 20, 28, 39, + 61, 195, 169, 157, 149, 143, 140, 137, 134, 132, + 130, 129, 128, 128, 128, 128, 129, 130, 132, 135, + 137, 140, 144, 151, 158, 173, 216, 51, 34, 25, + 18, 13, 10, 7, 5, 3, 1, 0, 0, 0, + 0, 1, 2, 4, 6, 9, 12, 15, 22, 30, + 44, 88, 179, 161, 153, 145, 141, 138, 135, 132, + 130, 129, 128, 128, 128, 128, 129, 131, 133, 135, + 138, 141, 146, 154, 164, 186, 68, 40, 28, 20, + 14, 11, 8, 5, 3, 1, 0, 0, 0, 0, + 1, 2, 4, 7, 10, 13, 18, 26, 37, 60, + 191, 166, 155, 147, 142, 138, 135, 133, 130, 129, + 128, 128, 128, 128, 129, 131, 133, 136, 139, 143, + 150, 158, 174, 121, 45, 30, 22, 15, 11, 8, + 5, 3, 1, 0, 0, 0, 0, 1, 3, 5, + 8, 11, 15, 22, 30, 46, 233, 172, 157, 149, + 142, 139, 136, 133, 131, 129, 128, 128, 128, 128, + 130, 132, 134, 137, 141, 145, 154, 165, 190, 59, + 35, 25, 16, 12, 9, 6, 3, 1, 0, 0, + 0, 0, 1, 3, 6, 9, 12, 16, 25, 35, + 60, 189, 164, 153, 144, 140, 137, 134, 131, 129, + 128, 128, 128, 128, 130, 132, 134, 137, 141, 147, + 155, 170, 213, 47, 30, 21, 14, 10, 7, 4, + 2, 1, 0, 0, 0, 1, 3, 5, 8, 12, + 16, 25, 37, 65, 183, 160, 151, 143, 139, 135, + 133, 130, 129, 128, 128, 128, 129, 131, 133, 137, + 140, 145, 154, 168, 205, 48, 30, 21, 14, 10, + 7, 4, 2, 0, 0, 0, 0, 2, 4, 7, + 10, 14, 22, 31, 52, 195, 165, 153, 144, 139, + 136, 133, 130, 129, 128, 128, 128, 129, 131, 134, + 138, 142, 148, 158, 176, 74, 38, 25, 16, 11, + 8, 5, 2, 0, 0, 0, 0, 2, 4, 7, + 10, 14, 22, 33, 58, 186, 160, 150, 142, 138, + 135, 132, 129, 128, 128, 128, 129, 131, 133, 136, + 140, 146, 156, 172, 90, 40, 26, 16, 11, 8, + 4, 2, 0, 0, 0, 0, 2, 5, 8, 12, + 17, 27, 43, 236, 169, 154, 144, 139, 136, 132, + 130, 128, 128, 128, 129, 130, 133, 137, 141, 147, + 157, 176, 69, 35, 23, 14, 10, 6, 3, 1, + 0, 0, 0, 1, 4, 7, 10, 15, 24, 38, + 79, 173, 155, 145, 140, 136, 132, 130, 128, 128, + 128, 129, 131, 134, 138, 142, 150, 162, 194, 48, + 29, 18, 12, 8, 5, 2, 0, 0, 0, 1, + 3, 6, 10, 14, 23, 37, 78, 172, 155, 144, + 139, 135, 132, 129, 128, 128, 128, 129, 132, 135, + 139, 145, 155, 174, 70, 34, 22, 14, 9, 5, + 2, 0, 0, 0, 1, 3, 6, 10, 14, 24, + 38, 99, 169, 153, 143, 138, 134, 131, 129, 128, + 128, 128, 130, 133, 137, 142, 151, 165, 216, 42, + 25, 15, 10, 6, 3, 1, 0, 0, 1, 3, + 6, 10, 15, 25, 42, 215, 164, 150, 142, 137, + 133, 130, 128, 128, 128, 129, 132, 135, 140, 146, + 158, 185, 51, 28, 17, 11, 7, 3, 1, 0, + 0, 0, 3, 6, 10, 15, 26, 45, 196, 160, + 148, 140, 136, 132, 129, 128, 128, 128, 130, 133, + 138, 143, 153, 170, 75, 33, 21, 13, 8, 4, + 1, 0, 0, 0, 2, 6, 10, 15, 26, 46, + 189, 158, 146, 140, 135, 131, 129, 128, 128, 129, + 131, 135, 140, 147, 159, 191, 45, 26, 15, 10, + 5, 2, 0, 0, 0, 2, 5, 9, 15, 25, + 45, 191, 158, 146, 139, 135, 131, 129, 128, 128, + 129, 132, 136, 141, 151, 167, 87, 34, 20, 12, + 7, 3, 1, 0, 0, 1, 4, 8, 13, 22, + 39, 215, 162, 148, 140, 135, 131, 129, 128, 128, + 129, 132, 137, 142, 152, 172, 63, 30, 17, 11, + 6, 2, 0, 0, 0, 2, 6, 10, 16, 29, + 61, 172, 152, 142, 136, 132, 129, 128, 128, 129, + 132, 136, 141, 151, 170, 65, 30, 17, 10, 6, + 2, 0, 0, 0, 3, 7, 12, 20, 35, 244, + 162, 148, 140, 134, 131, 128, 128, 128, 130, 134, + 139, 147, 161, 224, 36, 20, 12, 7, 3, 0, + 0, 0, 3, 6, 12, 20, 36, 222, 160, 146, + 139, 134, 130, 128, 128, 129, 131, 135, 141, 151, + 172, 59, 28, 15, 9, 4, 1, 0, 0, 1, + 5, 10, 16, 29, 68, 168, 149, 140, 135, 131, + 128, 128, 128, 131, 135, 141, 152, 173, 55, 27, + 14, 8, 4, 1, 0, 0, 2, 6, 11, 20, + 37, 203, 158, 144, 137, 133, 129, 128, 128, 130, + 133, 139, 147, 163, 90, 31, 17, 10, 5, 1, + 0, 0, 2, 5, 11, 19, 36, 204, 158, 143, + 137, 132, 129, 128, 128, 130, 134, 140, 150, 171, + 56, 26, 14, 8, 3, 0, 0, 0, 3, 8, + 14, 27, 60, 168, 149, 139, 134, 130, 128, 128, + 129, 133, 139, 147, 166, 66, 28, 14, 8, 3, + 0, 0, 0, 3, 8, 15, 29, 74, 163, 146, + 138, 133, 129, 128, 128, 130, 135, 141, 153, 181, + 43, 21, 11, 6, 2, 0, 0, 2, 6, 12, + 23, 47, 174, 150, 140, 134, 130, 128, 128, 130, + 134, 140, 151, 176, 44, 22, 11, 6, 2, 0, + 0, 2, 7, 13, 26, 59, 167, 147, 138, 133, + 129, 128, 128, 131, 136, 143, 158, 244, 30, 15, + 8, 3, 0, 0, 1, 5, 11, 20, 42, 179, + 152, 140, 134, 130, 128, 128, 131, 135, 142, 156, + 210, 31, 15, 8, 3, 0, 0, 1, 5, 11, + 22, 47, 172, 149, 139, 133, 129, 128, 128, 132, + 137, 146, 166, 57, 24, 12, 6, 1, 0, 0, + 3, 8, 15, 33, 199, 155, 141, 134, 130, 128, + 128, 131, 136, 143, 159, 75, 27, 13, 6, 2, + 0, 0, 3, 8, 16, 34, 191, 153, 140, 134, + 129, 128, 128, 132, 137, 146, 168, 50, 22, 11, + 5, 1, 0, 1, 5, 11, 23, 54, 166, 145, + 137, 131, 128, 128, 130, 135, 142, 158, 90, 27, + 13, 6, 1, 0, 0, 4, 10, 20, 45, 170, + 147, 137, 131, 128, 128, 130, 135, 142, 158, 74, + 26, 12, 5, 1, 0, 1, 5, 11, 24, 63, + 160, 143, 135, 130, 128, 128, 132, 138, 148, 174, + 40, 17, 9, 3, 0, 0, 3, 8, 17, 41, + 174, 148, 137, 131, 128, 128, 130, 136, 144, 167, + 47, 20, 9, 3, 0, 0, 2, 8, 17, 40, + 173, 147, 137, 131, 128, 128, 131, 137, 147, 173, + 40, 16, 8, 2, 0, 0, 4, 10, 23, 61, + 159, 142, 134, 129, 128, 129, 133, 141, 156, 79, + 25, 11, 4, 0, 0, 2, 8, 16, 41, 171, + 146, 136, 130, 128, 128, 132, 139, 153, 213, 28, + 12, 5, 0, 0, 2, 8, 16, 41, 171, 145, + 136, 130, 128, 128, 133, 140, 156, 75, 24, 11, + 4, 0, 0, 3, 10, 22, 62, 158, 141, 133, + 129, 128, 130, 136, 145, 173, 38, 15, 7, 1, + 0, 1, 7, 15, 38, 172, 145, 136, 130, 128, + 129, 134, 142, 163, 47, 18, 8, 2, 0, 1, + 6, 14, 35, 175, 146, 136, 130, 128, 129, 134, + 143, 166, 43, 16, 7, 1, 0, 1, 7, 16, + 44, 165, 142, 134, 129, 128, 130, 137, 148, 187, + 29, 12, 4, 0, 0, 3, 11, 26, 211, 151, + 138, 131, 128, 128, 133, 142, 164, 44, 16, 7, + 1, 0, 2, 8, 20, 62, 156, 140, 132, 128, + 128, 132, 141, 159, 50, 18, 7, 1, 0, 2, + 8, 20, 63, 156, 139, 131, 128, 128, 133, 142, + 164, 42, 15, 6, 1, 0, 3, 10, 26, 200, + 149, 136, 130, 128, 130, 136, 148, 191, 27, 11, + 3, 0, 1, 6, 15, 45, 161, 141, 132, 128, + 128, 133, 142, 165, 40, 14, 5, 0, 0, 4, + 12, 32, 172, 143, 134, 128, 128, 132, 140, 159, + 46, 15, 6, 0, 0, 4, 12, 31, 173, 143, + 134, 128, 128, 132, 141, 163, 41, 14, 5, 0, + 0, 5, 14, 41, 162, 140, 132, 128, 128, 134, + 145, 182, 28, 10, 3, 0, 1, 8, 22, 253, + 150, 136, 129, 128, 131, 139, 157, 48, 15, 6, + 0, 0, 5, 14, 44, 159, 139, 131, 128, 129, + 136, 150, 91, 20, 7, 1, 0, 4, 13, 36, + 165, 141, 132, 128, 129, 135, 149, 237, 21, 8, + 1, 0, 4, 13, 38, 162, 140, 131, 128, 129, + 137, 152, 64, 17, 6, 0, 0, 5, 15, 55, + 154, 137, 130, 128, 131, 140, 162, 37, 12, 3, + 0, 1, 9, 26, 182, 143, 133, 128, 128, 135, + 148, 116, 20, 7, 0, 0, 5, 16, 60, 152, + 136, 129, 128, 132, 142, 175, 27, 9, 1, 0, + 4, 13, 43, 157, 138, 130, 128, 131, 141, 169, + 30, 10, 2, 0, 3, 13, 41, 157, 138, 130, + 128, 132, 141, 172, 28, 9, 1, 0, 4, 14, + 52, 153, 136, 129, 128, 133, 145, 202, 21, 7, + 0, 0, 7, 21, 198, 144, 133, 128, 129, 137, + 155, 44, 13, 3, 0, 2, 12, 38, 158, 138, + 129, 128, 133, 143, 194, 21, 7, 0, 0, 8, + 24, 179, 142, 132, 128, 130, 140, 167, 29, 9, + 1, 0, 5, 19, 220, 145, 133, 128, 129, 138, + 160, 33, 10, 2, 0, 5, 17, 107, 146, 133, + 128, 129, 138, 161, 31, 10, 1, 0, 6, 20, + 198, 143, 132, 128, 130, 140, 172, 26, 8, 0, + 0, 8, 27, 169, 140, 130, 128, 133, 145, 95, + 16, 4, 0, 2, 12, 46, 152, 135, 128, 129, + 137, 159, 32, 10, 1, 0, 7, 24, 173, 140, + 130, 128, 133, 147, 70, 14, 3, 0, 4, 15, + 78, 146, 133, 128, 131, 141, 184, 21, 5, 0, + 2, 12, 46, 151, 134, 128, 130, 139, 171, 24, + 7, 0, 1, 11, 42, 153, 135, 128, 129, 139, + 171, 24, 6, 0, 2, 12, 46, 151, 134, 128, + 130, 141, 182, 20, 5, 0, 3, 14, 75, 145, + 132, 128, 132, 145, 74, 14, 3, 0, 5, 22, + 174, 139, 129, 128, 135, 156, 32, 9, 0, 1, + 10, 40, 152, 134, 128, 130, 142, 203, 16, 3, + 0, 5, 21, 175, 139, 129, 128, 136, 159, 28, + 7, 0, 2, 13, 62, 145, 132, 128, 133, 150, + 44, 11, 1, 0, 10, 39, 152, 134, 128, 131, + 144, 66, 13, 2, 0, 8, 31, 155, 135, 128, + 131, 143, 85, 13, 2, 0, 8, 31, 155, 135, + 128, 131, 143, 67, 13, 1, 0, 9, 37, 152, + 133, 128, 132, 148, 45, 10, 0, 1, 12, 58, + 144, 131, 128, 135, 157, 29, 7, 0, 3, 17, + 181, 139, 129, 129, 139, 186, 16, 3, 0, 7, + 31, 153, 133, 128, 132, 150, 38, 9, 0, 2, + 15, 193, 140, 129, 129, 139, 188, 15, 2, 0, + 9, 40, 149, 132, 128, 134, 157, 27, 6, 0, + 5, 24, 160, 135, 128, 132, 148, 41, 9, 0, + 3, 17, 176, 138, 128, 130, 143, 58, 11, 0, + 2, 14, 195, 139, 129, 129, 142, 74, 12, 1, + 1, 14, 202, 140, 129, 129, 142, 67, 11, 0, + 2, 15, 186, 138, 128, 130, 144, 47, 9, 0, + 3, 19, 168, 136, 128, 132, 151, 31, 6, 0, + 5, 28, 154, 133, 128, 135, 164, 20, 3, 0, + 9, 51, 143, 130, 129, 140, 87, 11, 0, 2, + 17, 171, 136, 128, 132, 154, 27, 5, 0, 7, + 40, 146, 130, 128, 140, 124, 12, 0, 2, 18, + 166, 135, 128, 134, 159, 22, 3, 0, 10, 72, + 140, 128, 130, 146, 38, 7, 0, 6, 34, 148, + 130, 128, 140, 77, 10, 0, 3, 24, 156, 132, + 128, 137, 186, 13, 1, 2, 19, 162, 134, 128, + 136, 172, 15, 1, 2, 16, 167, 135, 128, 135, + 171, 15, 1, 2, 17, 165, 134, 128, 136, 175, + 14, 1, 2, 20, 158, 133, 128, 138, 203, 11, + 0, 4, 26, 151, 131, 128, 141, 52, 8, 0, + 7, 41, 143, 129, 130, 149, 29, 4, 0, 11, + 199, 137, 128, 134, 166, 15, 1, 2, 21, 156, + 132, 128, 140, 55, 8, 0, 7, 50, 141, 128, + 132, 156, 20, 2, 1, 17, 159, 133, 128, 140, + 57, 8, 0, 8, 59, 139, 128, 133, 163, 15, + 1, 3, 25, 151, 130, 129, 145, 30, 4, 0, + 13, 172, 134, 128, 138, 68, 8, 0, 8, 71, + 138, 128, 134, 175, 12, 0, 5, 38, 142, 128, + 132, 159, 16, 1, 3, 28, 146, 129, 131, 154, + 20, 1, 2, 24, 150, 130, 130, 151, 22, 2, + 2, 23, 150, 130, 130, 151, 22, 2, 2, 25, + 149, 129, 130, 154, 19, 1, 3, 29, 144, 129, + 132, 160, 14, 0, 5, 40, 141, 128, 134, 180, + 11, 0, 8, 90, 137, 128, 138, 58, 6, 0, + 13, 167, 132, 128, 144, 28, 2, 2, 24, 148, + 129, 132, 161, 14, 0, 6, 57, 138, 128, 138, + 57, 6, 0, 14, 159, 131, 129, 151, 20, 1, + 4, 39, 140, 128, 136, 88, 7, 0, 13, 161, + 131, 129, 152, 18, 0, 5, 46, 138, 128, 138, + 47, 5, 0, 19, 151, 129, 132, 167, 12, 0, + 9, 181, 133, 128, 147, 22, 1, 4, 43, 139, + 128, 139, 42, 4, 1, 24, 145, 128, 134, 207, + 7, 0, 15, 155, 130, 131, 168, 11, 0, 11, + 166, 131, 130, 156, 14, 0, 9, 181, 133, 129, + 151, 16, 0, 7, 201, 134, 128, 149, 18, 0, + 7, 213, 134, 128, 149, 18, 0, 7, 199, 133, + 129, 151, 15, 0, 8, 180, 132, 129, 156, 13, + 0, 10, 165, 131, 131, 167, 10, 0, 14, 154, + 129, 133, 204, 7, 0, 22, 143, 128, 137, 42, + 3, 3, 39, 138, 128, 143, 22, 0, 7, 190, + 132, 130, 159, 11, 0, 14, 153, 129, 134, 67, + 5, 2, 31, 139, 128, 143, 22, 0, 8, 176, + 131, 131, 171, 8, 0, 21, 143, 128, 139, 30, + 1, 6, 210, 133, 130, 163, 10, 0, 19, 144, + 128, 139, 29, 1, 6, 188, 132, 131, 174, 7, + 0, 26, 140, 128, 143, 19, 0, 10, 158, 129, + 134, 55, 3, 3, 59, 134, 129, 161, 9, 0, + 23, 141, 128, 143, 18, 0, 12, 154, 128, 137, + 36, 1, 6, 182, 131, 132, 221, 4, 2, 49, + 134, 129, 165, 8, 0, 29, 138, 128, 152, 12, + 0, 20, 142, 128, 145, 15, 0, 15, 146, 128, + 142, 20, 0, 13, 150, 128, 140, 23, 0, 11, + 152, 128, 139, 25, 0, 11, 153, 128, 139, 24, + 0, 12, 151, 128, 140, 21, 0, 13, 147, 128, + 142, 17, 0, 15, 143, 128, 147, 13, 0, 22, + 139, 128, 155, 10, 0, 32, 136, 129, 172, 6, + 2, 68, 132, 132, 63, 2, 6, 168, 129, 137, + 28, 0, 12, 148, 128, 144, 14, 0, 24, 138, + 128, 165, 6, 2, 73, 131, 133, 46, 1, 9, + 155, 128, 141, 16, 0, 22, 138, 128, 167, 6, + 3, 208, 130, 135, 31, 0, 12, 145, 128, 151, + 10, 1, 44, 133, 132, 50, 1, 9, 151, 128, + 146, 12, 0, 38, 133, 132, 54, 1, 10, 150, + 128, 148, 11, 1, 47, 132, 133, 38, 0, 13, + 143, 128, 157, 7, 3, 189, 129, 138, 21, 0, + 24, 136, 130, 109, 2, 9, 151, 128, 151, 9, + 2, 232, 130, 137, 21, 0, 25, 136, 131, 59, + 1, 11, 144, 128, 161, 5, 5, 164, 128, 143, + 11, 1, 64, 130, 137, 21, 0, 28, 134, 132, + 39, 0, 15, 139, 129, 223, 1, 10, 144, 128, + 167, 4, 7, 153, 128, 154, 6, 4, 163, 128, + 147, 9, 2, 178, 128, 143, 11, 1, 203, 129, + 141, 12, 1, 93, 129, 140, 13, 1, 76, 129, + 140, 13, 1, 79, 129, 140, 13, 1, 235, 129, + 141, 12, 2, 189, 128, 143, 10, 3, 171, 128, + 149, 7, 4, 158, 128, 157, 5, 7, 149, 128, + 174, 2, 11, 141, 129, 66, 0, 17, 136, 132, + 30, 0, 31, 132, 137, 16, 0, 106, 128, 143, + 9, 4, 158, 128, 162, 3, 10, 141, 129, 52, + 0, 23, 134, 135, 19, 0, 89, 128, 145, 7, + 5, 152, 128, 186, 1, 15, 136, 133, 25, 0, + 57, 129, 143, 8, 5, 150, 128, 206, 0, 19, + 134, 135, 17, 1, 185, 128, 155, 4, 10, 140, + 131, 31, 0, 46, 129, 144, 7, 6, 145, 129, + 48, 0, 32, 130, 141, 9, 5, 148, 128, 57, + 0, 31, 130, 141, 8, 6, 146, 129, 44, 0, + 41, 129, 145, 6, 8, 141, 131, 28, 0, 224, + 128, 157, 2, 14, 135, 135, 14, 2, 156, 128, + 78, 0, 33, 129, 145, 5, 10, 139, 132, 20, + 1, 165, 128, 204, 0, 30, 130, 145, 5, 10, + 138, 134, 15, 2, 155, 128, 48, 0, 58, 128, + 158, 1, 19, 132, 140, 8, 8, 140, 133, 17, + 2, 154, 128, 41, 0, 216, 128, 174, 0, 30, + 129, 150, 3, 15, 133, 140, 8, 9, 138, 134, + 13, 4, 145, 131, 23, 1, 156, 128, 37, 0, + 176, 128, 73, 0, 75, 128, 179, 0, 41, 128, + 162, 0, 29, 129, 154, 1, 24, 130, 150, 2, + 20, 131, 146, 3, 17, 131, 144, 3, 16, 132, + 144, 4, 16, 131, 144, 3, 17, 131, 146, 3, + 19, 130, 149, 2, 23, 130, 153, 1, 28, 129, + 160, 0, 39, 128, 175, 0, 64, 128, 89, 0, + 181, 128, 39, 0, 158, 129, 24, 2, 146, 132, + 14, 6, 139, 136, 8, 11, 133, 143, 3, 21, + 129, 158, 0, 47, 128, 80, 0, 167, 129, 25, + 2, 143, 133, 11, 9, 135, 141, 3, 22, 129, + 165, 0, 114, 128, 37, 1, 149, 132, 12, 8, + 135, 142, 3, 25, 128, 179, 0, 173, 129, 23, + 4, 140, 137, 6, 16, 130, 161, 0, 198, 128, + 26, 3, 141, 137, 6, 17, 129, 168, 0, 174, + 129, 19, 5, 137, 141, 3, 29, 128, 64, 0, + 150, 133, 9, 13, 131, 159, 0, 179, 129, 17, + 6, 135, 144, 1, 49, 128, 29, 3, 139, 139, + 3, 31, 128, 43, 2, 142, 137, 4, 27, 128, + 49, 1, 142, 137, 4, 27, 128, 44, 2, 141, + 138, 3, 34, 128, 31, 3, 138, 142, 1, 62, + 128, 20, 7, 133, 154, 0, 168, 131, 10, 14, + 129, 201, 0, 144, 137, 3, 35, 128, 26, 5, + 134, 152, 0, 163, 131, 8, 19, 128, 46, 2, + 138, 143, 0, 183, 130, 10, 15, 128, 55, 2, + 138, 144, 0, 174, 131, 9, 19, 128, 35, 4, + 134, 154, 0, 154, 135, 4, 39, 128, 16, 11, + 129, 104, 1, 138, 145, 0, 160, 133, 5, 35, + 128, 15, 11, 129, 57, 3, 135, 154, 0, 148, + 138, 1, 202, 130, 8, 26, 128, 19, 11, 129, + 53, 3, 134, 161, 0, 142, 142, 0, 158, 135, + 3, 87, 130, 8, 28, 128, 14, 14, 128, 28, + 8, 130, 60, 4, 133, 172, 1, 137, 153, 0, + 142, 143, 0, 151, 138, 0, 163, 135, 2, 187, + 132, 4, 65, 130, 6, 41, 129, 8, 30, 128, + 10, 25, 128, 12, 22, 128, 13, 19, 128, 14, + 17, 128, 15, 16, 128, 15, 16, 128, 14, 18, + 128, 14, 20, 128, 12, 23, 128, 11, 27, 128, + 9, 33, 129, 7, 46, 130, 5, 96, 132, 2, + 175, 135, 1, 157, 139, 0, 147, 143, 0, 140, + 154, 0, 135, 175, 3, 131, 51, 7, 128, 25, + 13, 128, 13, 26, 129, 6, 68, 133, 2, 159, + 139, 0, 142, 153, 1, 134, 230, 6, 129, 25, + 14, 128, 10, 40, 131, 2, 162, 139, 0, 140, + 159, 2, 131, 38, 11, 128, 12, 35, 131, 2, + 158, 141, 0, 137, 181, 5, 129, 20, 20, 129, + 5, 175, 138, 0, 139, 171, 4, 129, 20, 22, + 129, 3, 163, 141, 0, 135, 75, 9, 128, 11, + 48, 134, 0, 142, 161, 4, 129, 18, 27, 130, + 1, 149, 151, 2, 130, 23, 22, 130, 2, 151, + 151, 2, 130, 21, 26, 131, 1, 145, 158, 4, + 128, 13, 43, 134, 0, 138, 235, 10, 128, 6, + 169, 142, 1, 131, 23, 26, 131, 0, 140, 187, + 9, 128, 6, 164, 145, 2, 129, 15, 43, 135, + 0, 134, 36, 18, 130, 1, 141, 192, 10, 128, + 3, 151, 158, 6, 128, 7, 163, 148, 3, 128, + 10, 181, 143, 2, 128, 11, 203, 141, 1, 129, + 12, 206, 141, 1, 128, 11, 187, 143, 2, 128, + 9, 168, 149, 4, 128, 6, 154, 160, 8, 128, + 2, 142, 218, 13, 130, 0, 136, 30, 29, 135, + 0, 130, 13, 191, 145, 4, 128, 4, 146, 189, + 13, 130, 0, 133, 21, 50, 140, 2, 128, 5, + 148, 189, 14, 131, 0, 132, 15, 193, 148, 6, + 128, 1, 138, 31, 35, 139, 2, 128, 4, 142, + 55, 24, 136, 1, 128, 6, 145, 75, 22, 135, + 1, 128, 5, 143, 53, 26, 137, 2, 128, 3, + 139, 30, 46, 143, 5, 128, 0, 133, 14, 168, +}; + +static const int16_t ref_mulaw_dec_data[4000] = { + 30076, 29052, 28028, 25980, 24956, 22908, 20860, 18812, 16764, 14460, + 12412, 9852, 7420, 4860, 2236, -428, -3004, -5628, -8316, -10876, + -12924, -15484, -17788, -19836, -21884, -23932, -25980, -27004, -28028, -30076, + -31100, -31100, -32124, -32124, -32124, -32124, -32124, -32124, -31100, -30076, + -29052, -28028, -27004, -24956, -22908, -20860, -18812, -16764, -14460, -12412, + -9852, -7164, -4348, -1692, 988, 3644, 6396, 8828, 11388, 13948, + 16764, 18812, 20860, 22908, 24956, 25980, 28028, 29052, 30076, 31100, + 32124, 32124, 32124, 32124, 32124, 32124, 31100, 30076, 29052, 28028, + 27004, 24956, 22908, 20860, 18812, 16764, 13948, 11388, 8828, 5884, + 3132, 396, -2364, -5116, -7932, -10364, -13436, -15484, -17788, -20860, + -22908, -24956, -25980, -28028, -29052, -30076, -31100, -32124, -32124, -32124, + -32124, -32124, -32124, -31100, -30076, -29052, -28028, -25980, -23932, -21884, + -19836, -17788, -14972, -12412, -9852, -6908, -4092, -1244, 1628, 4604, + 7420, 10364, 12924, 15484, 17788, 19836, 22908, 24956, 25980, 28028, + 29052, 30076, 31100, 32124, 32124, 32124, 32124, 32124, 32124, 31100, + 30076, 28028, 27004, 24956, 22908, 20860, 18812, 15996, 13436, 10364, + 7676, 4604, 1756, -1180, -4092, -7164, -9852, -12924, -15484, -17788, + -20860, -22908, -24956, -27004, -28028, -30076, -31100, -32124, -32124, -32124, + -32124, -32124, -32124, -31100, -30076, -29052, -27004, -25980, -23932, -21884, + -18812, -16764, -13948, -10876, -8316, -5116, -2108, 924, 4092, 6908, + 9852, 12924, 15484, 17788, 20860, 22908, 24956, 27004, 29052, 30076, + 31100, 32124, 32124, 32124, 32124, 32124, 32124, 31100, 30076, 28028, + 25980, 24956, 21884, 19836, 17788, 14460, 11900, 8828, 5628, 2492, + -684, -3772, -6908, -9852, -12924, -15996, -18812, -20860, -22908, -25980, + -27004, -29052, -30076, -31100, -32124, -32124, -32124, -32124, -32124, -31100, + -30076, -29052, -27004, -24956, -22908, -20860, -17788, -15484, -12412, -9340, + -6140, -3004, 212, 3516, 6652, 9852, 12924, 15996, 18812, 20860, + 23932, 25980, 28028, 29052, 30076, 31100, 32124, 32124, 32124, 32124, + 32124, 31100, 30076, 28028, 25980, 23932, 21884, 18812, 16764, 13436, + 10364, 7164, 3900, 620, -2748, -6140, -9340, -12412, -15484, -18812, + -20860, -23932, -25980, -28028, -29052, -31100, -32124, -32124, -32124, -32124, + -32124, -32124, -31100, -29052, -28028, -25980, -22908, -20860, -17788, -14972, + -11900, -8828, -5372, -1980, 1372, 4860, 8316, 11388, 14460, 17788, + 20860, 22908, 24956, 27004, 29052, 30076, 32124, 32124, 32124, 32124, + 32124, 32124, 30076, 29052, 27004, 24956, 22908, 19836, 17788, 14460, + 10876, 7676, 4348, 716, -2748, -6396, -9852, -12924, -15996, -18812, + -21884, -23932, -27004, -29052, -30076, -31100, -32124, -32124, -32124, -32124, + -32124, -31100, -29052, -27004, -24956, -22908, -19836, -17788, -13948, -10876, + -7420, -3772, -196, 3388, 6908, 10364, 13948, 16764, 19836, 22908, + 24956, 27004, 29052, 31100, 32124, 32124, 32124, 32124, 32124, 31100, + 30076, 28028, 25980, 23932, 20860, 17788, 14972, 11388, 7932, 4348, + 684, -3004, -6652, -10364, -13948, -16764, -19836, -22908, -24956, -28028, + -29052, -31100, -32124, -32124, -32124, -32124, -32124, -31100, -29052, -27004, + -24956, -22908, -19836, -16764, -13436, -9852, -6140, -2364, 1436, 5116, + 8828, 12412, 15996, 18812, 21884, 24956, 27004, 29052, 31100, 32124, + 32124, 32124, 32124, 32124, 31100, 29052, 27004, 24956, 22908, 19836, + 16764, 12924, 9340, 5372, 1628, -2236, -6140, -9852, -13436, -16764, + -19836, -22908, -25980, -28028, -30076, -31100, -32124, -32124, -32124, -32124, + -31100, -30076, -28028, -25980, -23932, -20860, -16764, -13948, -9852, -6140, + -2236, 1692, 5628, 9340, 13436, 16764, 19836, 22908, 25980, 28028, + 30076, 31100, 32124, 32124, 32124, 32124, 31100, 30076, 28028, 24956, + 22908, 19836, 15996, 12412, 8828, 4604, 620, -3516, -7420, -11388, + -14972, -18812, -21884, -24956, -27004, -29052, -31100, -32124, -32124, -32124, + -32124, -31100, -30076, -28028, -25980, -22908, -19836, -16764, -12924, -8828, + -4860, -620, 3516, 7676, 11388, 15484, 18812, 21884, 24956, 28028, + 30076, 31100, 32124, 32124, 32124, 32124, 31100, 29052, 27004, 24956, + 21884, 18812, 14972, 10876, 6908, 2620, -1628, -5884, -9852, -13948, + -17788, -20860, -23932, -27004, -29052, -31100, -32124, -32124, -32124, -32124, + -31100, -30076, -28028, -24956, -21884, -18812, -14972, -10876, -6652, -2364, + 1980, 6396, 10364, 14460, 17788, 21884, 24956, 27004, 30076, 31100, + 32124, 32124, 32124, 32124, 31100, 29052, 27004, 23932, 20860, 16764, + 12924, 8828, 4348, -48, -4604, -8828, -12924, -16764, -20860, -23932, + -27004, -29052, -31100, -32124, -32124, -32124, -32124, -31100, -29052, -27004, + -23932, -20860, -16764, -12924, -8828, -4348, 228, 4860, 9340, 13436, + 17788, 20860, 23932, 27004, 29052, 31100, 32124, 32124, 32124, 32124, + 30076, 28028, 25980, 22908, 18812, 15484, 10876, 6652, 2108, -2492, + -7164, -11388, -15996, -19836, -22908, -25980, -29052, -31100, -32124, -32124, + -32124, -32124, -31100, -29052, -25980, -22908, -19836, -15996, -11388, -7164, + -2364, 2236, 6908, 11388, 15996, 19836, 22908, 25980, 29052, 31100, + 32124, 32124, 32124, 32124, 30076, 28028, 25980, 22908, 18812, 14460, + 10364, 5372, 716, -4092, -8828, -13436, -17788, -21884, -24956, -28028, + -30076, -31100, -32124, -32124, -32124, -31100, -29052, -27004, -23932, -19836, + -15996, -11388, -6652, -1820, 3004, 7932, 12412, 16764, 20860, 24956, + 27004, 30076, 31100, 32124, 32124, 32124, 31100, 29052, 27004, 22908, + 19836, 15484, 10876, 5884, 1052, -3900, -8828, -13436, -17788, -21884, + -24956, -28028, -30076, -32124, -32124, -32124, -32124, -30076, -28028, -24956, + -21884, -17788, -12924, -8316, -3388, 1692, 6652, 11388, 15996, 20860, + 23932, 27004, 30076, 31100, 32124, 32124, 32124, 31100, 29052, 25980, + 21884, 17788, 13948, 8828, 3900, -1244, -6396, -11388, -15996, -20860, + -23932, -27004, -30076, -32124, -32124, -32124, -32124, -30076, -28028, -24956, + -21884, -17788, -12924, -7676, -2620, 2620, 7932, 12924, 17788, 21884, + 24956, 28028, 31100, 32124, 32124, 32124, 31100, 29052, 27004, 23932, + 19836, 14972, 9852, 4860, -556, -5884, -10876, -15996, -20860, -23932, + -28028, -30076, -32124, -32124, -32124, -32124, -30076, -27004, -23932, -19836, + -15484, -10364, -5116, 180, 5628, 10876, 15996, 20860, 23932, 28028, + 30076, 32124, 32124, 32124, 31100, 30076, 27004, 22908, 18812, 14460, + 9340, 3900, -1564, -7164, -12412, -17788, -21884, -25980, -29052, -31100, + -32124, -32124, -32124, -31100, -28028, -24956, -21884, -16764, -11900, -6396, + -924, 4604, 10364, 15484, 19836, 23932, 28028, 30076, 32124, 32124, + 32124, 31100, 29052, 25980, 21884, 17788, 12924, 7420, 1756, -3900, + -9340, -14972, -19836, -23932, -27004, -30076, -32124, -32124, -32124, -31100, + -29052, -25980, -21884, -17788, -12412, -6652, -988, 4860, 10364, 15996, + 20860, 24956, 28028, 31100, 32124, 32124, 32124, 31100, 28028, 24956, + 20860, 15484, 10364, 4348, -1500, -7420, -12924, -17788, -22908, -27004, + -30076, -32124, -32124, -32124, -31100, -29052, -25980, -21884, -17788, -11900, + -6396, -324, 5628, 11388, 16764, 21884, 25980, 29052, 31100, 32124, + 32124, 32124, 30076, 27004, 22908, 17788, 12412, 6652, 620, -5372, + -11388, -16764, -21884, -25980, -29052, -31100, -32124, -32124, -31100, -29052, + -25980, -21884, -16764, -11388, -5372, 652, 6908, 12924, 17788, 22908, + 27004, 30076, 32124, 32124, 32124, 31100, 28028, 24956, 19836, 14972, + 8828, 2748, -3516, -9852, -15484, -20860, -24956, -29052, -31100, -32124, + -32124, -32124, -29052, -25980, -21884, -16764, -10876, -4604, 1628, 7932, + 13948, 19836, 23932, 28028, 31100, 32124, 32124, 32124, 30076, 27004, + 21884, 16764, 11388, 5372, -1180, -7676, -13436, -18812, -23932, -28028, + -31100, -32124, -32124, -32124, -30076, -25980, -21884, -16764, -10876, -4348, + 2236, 8828, 14972, 19836, 24956, 29052, 31100, 32124, 32124, 31100, + 29052, 24956, 19836, 14460, 8316, 1980, -4604, -10876, -16764, -21884, + -27004, -30076, -32124, -32124, -32124, -30076, -27004, -22908, -16764, -11388, + -4604, 1980, 8828, 14972, 20860, 24956, 29052, 31100, 32124, 32124, + 31100, 28028, 23932, 18812, 12412, 6140, -652, -7420, -13948, -19836, + -24956, -29052, -31100, -32124, -32124, -31100, -28028, -23932, -18812, -12924, + -6140, 652, 7420, 13948, 19836, 24956, 29052, 31100, 32124, 32124, + 31100, 28028, 22908, 17788, 11900, 4860, -1980, -8828, -15484, -20860, + -25980, -30076, -32124, -32124, -32124, -30076, -25980, -21884, -15996, -9340, + -2236, 4860, 11900, 17788, 23932, 28028, 31100, 32124, 32124, 31100, + 28028, 23932, 18812, 12412, 5372, -1820, -8828, -15484, -21884, -25980, + -30076, -32124, -32124, -32124, -29052, -24956, -19836, -13948, -7164, 88, + 7420, 13948, 19836, 25980, 29052, 32124, 32124, 32124, 30076, 25980, + 20860, 14460, 7676, 372, -6908, -13948, -19836, -24956, -29052, -32124, + -32124, -32124, -29052, -25980, -19836, -13948, -6908, 428, 7932, 14972, + 20860, 25980, 30076, 32124, 32124, 31100, 29052, 24956, 18812, 12412, + 4860, -2492, -9852, -16764, -22908, -28028, -31100, -32124, -32124, -31100, + -27004, -21884, -15996, -9340, -1628, 5884, 13436, 19836, 24956, 29052, + 32124, 32124, 32124, 29052, 24956, 18812, 11900, 4604, -3004, -10364, + -17788, -23932, -28028, -31100, -32124, -32124, -30076, -25980, -20860, -13948, + -6652, 1180, 8828, 15996, 22908, 27004, 31100, 32124, 32124, 30076, + 27004, 20860, 14460, 7164, -556, -8316, -15484, -21884, -27004, -31100, + -32124, -32124, -30076, -27004, -20860, -14460, -6908, 1116, 8828, 16764, + 22908, 28028, 31100, 32124, 32124, 30076, 25980, 19836, 12924, 5116, + -2876, -10876, -17788, -23932, -29052, -32124, -32124, -32124, -29052, -23932, + -17788, -10364, -2364, 5884, 13436, 20860, 25980, 30076, 32124, 32124, + 31100, 27004, 20860, 14460, 6396, -1756, -9852, -17788, -23932, -29052, + -32124, -32124, -32124, -29052, -23932, -16764, -9340, -1244, 7164, 14972, + 21884, 27004, 31100, 32124, 32124, 30076, 24956, 18812, 11388, 3260, + -5116, -13436, -20860, -25980, -30076, -32124, -32124, -30076, -25980, -19836, + -12412, -4092, 4348, 12924, 19836, 25980, 30076, 32124, 32124, 30076, + 25980, 19836, 12412, 3900, -4860, -12924, -20860, -25980, -30076, -32124, + -32124, -30076, -24956, -18812, -10876, -2492, 6140, 14460, 21884, 27004, + 31100, 32124, 32124, 29052, 23932, 16764, 8828, 88, -8828, -16764, + -23932, -29052, -32124, -32124, -31100, -27004, -20860, -13948, -5372, 3516, + 11900, 19836, 25980, 30076, 32124, 32124, 29052, 24956, 17788, 9852, + 812, -8316, -16764, -23932, -29052, -32124, -32124, -31100, -27004, -20860, + -12924, -4092, 4860, 13436, 20860, 27004, 31100, 32124, 32124, 28028, + 22908, 14972, 6396, -2748, -11900, -19836, -25980, -31100, -32124, -32124, + -29052, -23932, -16764, -7676, 1436, 10364, 18812, 25980, 30076, 32124, + 32124, 29052, 23932, 16764, 8316, -1180, -10364, -18812, -25980, -30076, + -32124, -32124, -29052, -23932, -15996, -7420, 1980, 11388, 19836, 25980, + 31100, 32124, 32124, 28028, 22908, 14972, 5884, -3644, -12924, -20860, + -27004, -31100, -32124, -31100, -27004, -20860, -12412, -3132, 6396, 15484, + 22908, 29052, 32124, 32124, 30076, 24956, 17788, 8828, -556, -10364, + -18812, -25980, -31100, -32124, -32124, -28028, -21884, -13948, -4604, 5372, + 14460, 22908, 29052, 32124, 32124, 30076, 24956, 17788, 8828, -1244, + -10876, -19836, -27004, -31100, -32124, -31100, -27004, -20860, -11900, -1980, + 7932, 16764, 24956, 30076, 32124, 32124, 28028, 21884, 13948, 4348, + -5884, -15484, -22908, -29052, -32124, -32124, -29052, -23932, -15484, -5628, + 4348, 13948, 22908, 29052, 32124, 32124, 30076, 23932, 15996, 6140, + -4092, -13948, -22908, -29052, -32124, -32124, -30076, -23932, -15484, -5884, + 4604, 14460, 22908, 29052, 32124, 32124, 29052, 22908, 14460, 4604, + -5884, -15996, -23932, -30076, -32124, -32124, -28028, -21884, -12412, -2236, + 8316, 17788, 25980, 31100, 32124, 31100, 27004, 18812, 9852, -924, + -11388, -20860, -28028, -32124, -32124, -30076, -23932, -15996, -5628, 5116, + 14972, 23932, 30076, 32124, 32124, 28028, 20860, 11388, 716, -9852, + -19836, -27004, -32124, -32124, -30076, -23932, -15996, -5628, 5116, 15484, + 23932, 30076, 32124, 32124, 27004, 19836, 9852, -1180, -11900, -20860, + -28028, -32124, -32124, -29052, -21884, -12924, -2108, 8828, 18812, 27004, + 31100, 32124, 30076, 23932, 15484, 4604, -6396, -16764, -24956, -31100, + -32124, -31100, -24956, -16764, -6396, 4860, 15484, 23932, 30076, 32124, + 31100, 25980, 17788, 7164, -4092, -14972, -23932, -30076, -32124, -31100, + -25980, -17788, -7164, 4092, 14972, 23932, 30076, 32124, 31100, 25980, + 16764, 6396, -5116, -15996, -24956, -31100, -32124, -31100, -24956, -15996, + -4860, 6652, 17788, 25980, 31100, 32124, 30076, 22908, 13948, 2492, + -9340, -19836, -28028, -32124, -32124, -29052, -20860, -10876, 780, 12412, + 21884, 29052, 32124, 32124, 27004, 17788, 6908, -4860, -15996, -24956, + -31100, -32124, -30076, -23932, -13948, -2108, 9852, 19836, 28028, 32124, + 32124, 28028, 18812, 8316, -3644, -14972, -24956, -31100, -32124, -30076, + -23932, -13948, -1980, 9852, 20860, 29052, 32124, 32124, 27004, 17788, + 6908, -5372, -16764, -25980, -31100, -32124, -29052, -21884, -10876, 1372, + 13436, 23932, 30076, 32124, 30076, 23932, 13948, 1980, -10364, -20860, + -29052, -32124, -31100, -25980, -16764, -4604, 7676, 18812, 28028, 32124, + 32124, 27004, 17788, 6652, -5884, -17788, -27004, -32124, -32124, -28028, + -19836, -7932, 4860, 16764, 25980, 32124, 32124, 28028, 19836, 8316, + -4348, -16764, -25980, -32124, -32124, -28028, -19836, -8316, 4604, 16764, + 25980, 32124, 32124, 28028, 18812, 7164, -5628, -17788, -27004, -32124, + -32124, -27004, -17788, -5628, 7420, 19836, 28028, 32124, 32124, 25980, + 15484, 3132, -9852, -21884, -29052, -32124, -31100, -23932, -12924, 16, + 12924, 23932, 31100, 32124, 29052, 20860, 9340, -3900, -16764, -25980, + -32124, -32124, -27004, -17788, -4860, 8316, 20860, 29052, 32124, 31100, + 23932, 12924, -524, -13948, -24956, -31100, -32124, -28028, -18812, -6908, + 6652, 18812, 28028, 32124, 31100, 24956, 13436, 164, -13436, -23932, + -31100, -32124, -28028, -18812, -6396, 7420, 19836, 29052, 32124, 31100, + 22908, 11900, -1884, -15484, -25980, -32124, -32124, -27004, -16764, -3004, + 10876, 22908, 30076, 32124, 29052, 19836, 7420, -6652, -19836, -29052, + -32124, -31100, -22908, -10876, 3132, 16764, 27004, 32124, 32124, 24956, + 13948, -88, -13948, -24956, -32124, -32124, -27004, -15996, -2364, 11900, + 23932, 31100, 32124, 28028, 17788, 4092, -10364, -22908, -31100, -32124, + -28028, -18812, -5116, 9340, 21884, 30076, 32124, 29052, 18812, 5628, + -8828, -21884, -30076, -32124, -29052, -18812, -5628, 9340, 21884, 30076, + 32124, 28028, 18812, 4860, -9852, -22908, -31100, -32124, -28028, -17788, + -3388, 11388, 23932, 31100, 32124, 27004, 15484, 1244, -13436, -24956, + -32124, -32124, -24956, -13436, 1500, 15996, 27004, 32124, 31100, 22908, + 10364, -4860, -18812, -29052, -32124, -30076, -19836, -6396, 8828, 21884, + 31100, 32124, 27004, 16764, 1756, -13436, -24956, -32124, -32124, -23932, + -11900, 3516, 17788, 28028, 32124, 30076, 19836, 6140, -9340, -22908, + -31100, -32124, -27004, -14460, 492, 15484, 27004, 32124, 31100, 21884, + 7932, -7676, -21884, -30076, -32124, -27004, -15484, -196, 14972, 27004, + 32124, 31100, 21884, 7676, -8316, -21884, -31100, -32124, -25980, -13948, + 1500, 16764, 28028, 32124, 30076, 19836, 4860, -10876, -23932, -32124, + -32124, -23932, -10364, 5628, 19836, 30076, 32124, 27004, 15484, -396, + -15996, -28028, -32124, -30076, -19836, -4348, 11900, 24956, 32124, 31100, + 22908, 8316, -7932, -21884, -31100, -32124, -24956, -11900, 4604, 19836, + 30076, 32124, 27004, 14460, -1500, -17788, -29052, -32124, -28028, -16764, + -988, 14972, 27004, 32124, 29052, 18812, 2876, -13436, -27004, -32124, + -30076, -19836, -4348, 12412, 25980, 32124, 30076, 20860, 5116, -11900, + -24956, -32124, -31100, -20860, -5372, 11388, 24956, 32124, 31100, 20860, + 5116, -11900, -25980, -32124, -30076, -19836, -4348, 12412, 25980, 32124, + 30076, 18812, 3132, -13948, -27004, -32124, -29052, -17788, -1180, 15484, + 28028, 32124, 28028, 15484, -1244, -17788, -29052, -32124, -27004, -12924, + 4348, 20860, 31100, 32124, 24956, 9852, -7932, -22908, -32124, -31100, + -21884, -5884, 11900, 25980, 32124, 30076, 17788, 1180, -15996, -29052, + -32124, -27004, -13436, 4092, 20860, 31100, 32124, 23932, 8316, -9852, + -24956, -32124, -30076, -18812, -2108, 15484, 28028, 32124, 27004, 12924, + -4860, -20860, -31100, -32124, -21884, -6140, 11900, 25980, 32124, 29052, + 15996, -1756, -18812, -30076, -32124, -23932, -8316, 10364, 24956, 32124, + 29052, 16764, -716, -18812, -30076, -32124, -23932, -8316, 10364, 24956, + 32124, 29052, 16764, -1692, -18812, -31100, -32124, -22908, -6652, 11900, + 27004, 32124, 28028, 13948, -4604, -21884, -32124, -31100, -19836, -2620, + 15996, 29052, 32124, 24956, 9340, -9340, -24956, -32124, -29052, -15484, + 3260, 20860, 31100, 31100, 20860, 2620, -15996, -29052, -32124, -24956, + -8316, 11388, 27004, 32124, 28028, 12924, -6396, -22908, -32124, -30076, + -16764, 1820, 19836, 31100, 31100, 20860, 2364, -16764, -30076, -32124, + -22908, -5884, 13436, 28028, 32124, 25980, 9340, -10364, -25980, -32124, + -27004, -11900, 7932, 24956, 32124, 28028, 13948, -5628, -22908, -32124, + -29052, -15484, 3900, 21884, 32124, 30076, 16764, -2620, -20860, -32124, + -30076, -17788, 1692, 20860, 31100, 31100, 17788, -1244, -19836, -31100, + -31100, -17788, 1244, 19836, 31100, 31100, 17788, -1692, -20860, -32124, + -30076, -16764, 2620, 21884, 32124, 30076, 15996, -4092, -22908, -32124, + -29052, -14460, 5884, 23932, 32124, 28028, 12412, -8316, -25980, -32124, + -27004, -9852, 10876, 27004, 32124, 24956, 6908, -13948, -29052, -32124, + -22908, -3516, 16764, 30076, 31100, 19836, -652, -20860, -32124, -30076, + -15484, 5116, 23932, 32124, 28028, 10876, -10364, -27004, -32124, -24956, + -5884, 14972, 30076, 32124, 19836, -24, -19836, -32124, -30076, -14972, + 6396, 24956, 32124, 25980, 8316, -12924, -29052, -32124, -21884, -1372, + 19836, 32124, 30076, 14972, -6396, -24956, -32124, -25980, -7420, 13948, + 30076, 32124, 19836, -1052, -21884, -32124, -29052, -11900, 9852, 28028, + 32124, 22908, 2620, -18812, -31100, -30076, -14460, 7420, 25980, 32124, + 23932, 4860, -16764, -31100, -30076, -15996, 6140, 24956, 32124, 24956, + 5116, -16764, -31100, -30076, -15484, 6652, 25980, 32124, 23932, 4092, + -17788, -31100, -30076, -13948, 8828, 27004, 32124, 21884, 1180, -20860, + -32124, -28028, -10876, 12412, 29052, 32124, 18812, -3388, -23932, -32124, + -24956, -5628, 16764, 31100, 30076, 13436, -9340, -28028, -32124, -20860, + 1436, 22908, 32124, 25980, 6396, -16764, -31100, -30076, -13436, 9852, + 28028, 32124, 19836, -3004, -23932, -32124, -24956, -3644, 18812, 32124, + 28028, 9852, -13948, -30076, -31100, -15484, 8316, 27004, 32124, 19836, + -2748, -23932, -32124, -23932, -2492, 20860, 32124, 27004, 7164, -16764, + -31100, -29052, -11388, 12412, 30076, 31100, 15484, -8828, -28028, -32124, + -18812, 4860, 25980, 32124, 21884, -1628, -23932, -32124, -23932, -1436, + 21884, 32124, 25980, 4092, -19836, -32124, -27004, -6396, 17788, 32124, + 28028, 8316, -15996, -31100, -29052, -9852, 14972, 31100, 29052, 10876, + -13948, -31100, -30076, -11900, 12924, 30076, 30076, 12412, -12924, -30076, + -30076, -12412, 12924, 30076, 30076, 12412, -12924, -30076, -30076, -11388, + 13436, 31100, 30076, 10876, -14460, -31100, -29052, -9340, 15996, 31100, + 28028, 7932, -17788, -32124, -27004, -5884, 18812, 32124, 25980, 3388, + -20860, -32124, -23932, -556, 22908, 32124, 21884, -2620, -25980, -32124, + -18812, 6140, 28028, 32124, 15996, -9852, -30076, -30076, -11900, 13948, + 31100, 28028, 7676, -17788, -32124, -25980, -2748, 21884, 32124, 21884, + -2748, -25980, -32124, -17788, 8316, 29052, 31100, 12412, -13948, -31100, + -28028, -6140, 19836, 32124, 23932, -620, -24956, -32124, -18812, 7676, + 29052, 31100, 11900, -14972, -32124, -27004, -4348, 21884, 32124, 21884, + -4092, -27004, -32124, -14460, 12412, 31100, 28028, 6140, -19836, -32124, + -22908, 3260, 27004, 32124, 14460, -12924, -31100, -28028, -5116, 20860, + 32124, 20860, -5372, -28028, -31100, -11900, 15484, 32124, 25980, 924, + -24956, -32124, -16764, 10364, 30076, 29052, 5884, -20860, -32124, -20860, + 6396, 29052, 30076, 9852, -17788, -32124, -22908, 3260, 27004, 31100, + 12412, -15996, -32124, -24956, 1308, 25980, 32124, 13436, -14972, -32124, + -24956, 716, 25980, 32124, 13436, -14972, -32124, -24956, 1436, 27004, + 31100, 12412, -16764, -32124, -23932, 3388, 28028, 31100, 9852, -18812, + -32124, -21884, 6652, 29052, 29052, 6140, -21884, -32124, -17788, 10876, + 31100, 27004, 1116, -24956, -32124, -12924, 16764, 32124, 22908, -5372, + -29052, -29052, -6140, 21884, 32124, 16764, -12924, -32124, -24956, 2108, + 28028, 30076, 8316, -20860, -32124, -17788, 11388, 31100, 25980, -1692, + -27004, -30076, -8316, 20860, 32124, 16764, -12924, -32124, -23932, 3900, + 29052, 29052, 5116, -23932, -32124, -13436, 16764, 32124, 20860, -8828, + -31100, -25980, 812, 27004, 30076, 7164, -21884, -32124, -14460, 15996, + 32124, 20860, -9340, -31100, -25980, 2364, 28028, 29052, 4348, -24956, + -32124, -10876, 19836, 32124, 16764, -14460, -32124, -21884, 8828, 31100, + 25980, -3004, -29052, -29052, -2492, 25980, 31100, 7676, -22908, -32124, + -12412, 18812, 32124, 16764, -14972, -32124, -19836, 10876, 32124, 22908, + -6908, -31100, -25980, 3132, 29052, 28028, 460, -28028, -30076, -3772, + 25980, 31100, 6652, -23932, -32124, -9340, 21884, 32124, 11900, -19836, + -32124, -13948, 17788, 32124, 15484, -16764, -32124, -16764, 14972, 32124, + 17788, -13948, -32124, -18812, 12924, 32124, 19836, -12412, -32124, -20860, + 11900, 32124, 20860, -11388, -32124, -20860, 11388, 32124, 20860, -11900, + -32124, -19836, 12412, 32124, 19836, -13436, -32124, -18812, 14460, 32124, + 17788, -15484, -32124, -16764, 16764, 32124, 14460, -18812, -32124, -12924, + 20860, 32124, 10364, -21884, -32124, -7932, 23932, 31100, 4860, -25980, + -30076, -1628, 28028, 28028, -1980, -30076, -25980, 5884, 31100, 22908, + -9852, -32124, -19836, 13948, 32124, 15996, -17788, -32124, -11900, 21884, + 32124, 6652, -25980, -30076, -1308, 29052, 27004, -4348, -31100, -22908, + 10364, 32124, 18812, -15996, -32124, -12924, 21884, 32124, 6140, -25980, + -29052, 876, 30076, 24956, -8316, -32124, -19836, 15484, 32124, 12412, + -21884, -31100, -4860, 27004, 28028, -3644, -31100, -22908, 12412, 32124, + 14972, -19836, -32124, -6396, 27004, 28028, -3132, -31100, -21884, 12924, + 32124, 13948, -20860, -31100, -4092, 28028, 27004, -6396, -32124, -18812, + 16764, 32124, 9340, -24956, -29052, 2236, 31100, 21884, -13436, -32124, + -11900, 23932, 30076, -164, -30076, -22908, 12412, 32124, 12412, -22908, + -30076, 244, 30076, 22908, -13436, -32124, -11388, 23932, 29052, -2492, + -31100, -20860, 15996, 32124, 7676, -27004, -27004, 6908, 32124, 16764, + -20860, -31100, -1884, 30076, 22908, -13436, -32124, -9852, 25980, 28028, + -6140, -32124, -16764, 20860, 31100, 396, -31100, -21884, 15996, 32124, + 6140, -28028, -24956, 11388, 32124, 10876, -25980, -28028, 7164, 32124, + 14460, -22908, -30076, 3644, 32124, 16764, -20860, -31100, 1180, 31100, + 18812, -19836, -31100, -460, 31100, 19836, -18812, -31100, -1116, 31100, + 19836, -18812, -31100, -924, 31100, 19836, -18812, -31100, 196, 31100, + 18812, -19836, -30076, 2236, 32124, 16764, -21884, -29052, 5116, 32124, + 13436, -24956, -28028, 8828, 32124, 9340, -27004, -24956, 13436, 32124, + 4348, -30076, -20860, 18812, 31100, -1756, -32124, -15484, 23932, 28028, + -8828, -32124, -8316, 28028, 22908, -15996, -32124, -212, 32124, 16764, + -22908, -28028, 8828, 32124, 7420, -29052, -21884, 18812, 31100, -3388, + -32124, -12412, 25980, 24956, -14460, -32124, -588, 32124, 15484, -24956, + -27004, 11900, 32124, 2620, -31100, -16764, 23932, 27004, -11388, -32124, + -2748, 31100, 16764, -23932, -27004, 12924, 32124, 988, -32124, -14460, + 25980, 24956, -15484, -31100, 2748, 32124, 10364, -28028, -21884, 19836, + 29052, -8316, -32124, -4348, 31100, 15996, -24956, -25980, 15484, 31100, + -3900, -32124, -7932, 30076, 18812, -22908, -27004, 13948, 32124, -2748, + -32124, -8316, 30076, 18812, -23932, -25980, 14972, 31100, -4860, -32124, + -5628, 31100, 15484, -25980, -23932, 18812, 29052, -9852, -32124, 372, + 32124, 9340, -30076, -17788, 24956, 24956, -17788, -30076, 9852, 32124, + -988, -32124, -7676, 31100, 15484, -27004, -21884, 20860, 28028, -13948, + -31100, 6652, 32124, 1116, -32124, -8828, 30076, 15484, -27004, -21884, + 21884, 25980, -16764, -30076, 10364, 32124, -3900, -32124, -2620, 32124, + 8828, -31100, -14460, 28028, 19836, -23932, -23932, 19836, 27004, -15484, + -30076, 10876, 32124, -5628, -32124, 620, 32124, 4348, -32124, -8828, + 31100, 12924, -29052, -16764, 27004, 19836, -23932, -22908, 21884, 25980, + -18812, -28028, 15484, 29052, -12412, -31100, 9852, 32124, -6652, -32124, + 3900, 32124, -1308, -32124, -1180, 32124, 3516, -32124, -5628, 32124, + 7420, -32124, -9340, 31100, 10876, -31100, -11900, 30076, 12924, -30076, + -13948, 29052, 14972, -29052, -15484, 29052, 15996, -29052, -15996, 28028, + 15996, -28028, -15996, 29052, 15996, -29052, -15484, 29052, 14972, -29052, + -14460, 30076, 13436, -30076, -12412, 30076, 11388, -31100, -9852, 31100, + 7932, -32124, -6140, 32124, 4092, -32124, -1884, 32124, -588, -32124, + 3260, 32124, -6140, -32124, 8828, 31100, -11900, -30076, 14972, 28028, + -17788, -25980, 20860, 23932, -23932, -20860, 27004, 16764, -29052, -13436, + 31100, 8828, -32124, -4092, 32124, -876, -32124, 6140, 31100, -11388, + -30076, 16764, 27004, -20860, -22908, 24956, 18812, -29052, -12924, 31100, + 6652, -32124, -104, 32124, -6652, -31100, 13436, 28028, -19836, -23932, + 24956, 17788, -29052, -11388, 32124, 3516, -32124, 4604, 31100, -12412, + -28028, 19836, 22908, -25980, -15996, 30076, 7676, -32124, 1500, 32124, + -10876, -29052, 18812, 22908, -25980, -15484, 31100, 5884, -32124, 4348, + 31100, -14460, -27004, 22908, 18812, -29052, -9340, 32124, -1884, -32124, + 12924, 27004, -22908, -18812, 29052, 8316, -32124, 3516, 31100, -15484, + -25980, 24956, 15996, -31100, -3772, 32124, -9340, -29052, 20860, 20860, + -29052, -8316, 32124, -5116, -30076, 17788, 22908, -28028, -10364, 32124, + -3772, -31100, 17788, 22908, -28028, -10364, 32124, -4860, -30076, 18812, + 21884, -29052, -7420, 32124, -8316, -29052, 21884, 17788, -31100, -2108, + 32124, -13948, -24956, 27004, 10876, -32124, 5884, 29052, -21884, -17788, + 31100, 1308, -32124, 15996, 22908, -29052, -7164, 32124, -10876, -27004, + 25980, 11900, -32124, 7164, 29052, -23932, -14460, 32124, -4348, -30076, + 21884, 16764, -32124, 3004, 30076, -21884, -16764, 32124, -3004, -30076, + 21884, 15996, -32124, 4348, 29052, -22908, -14460, 32124, -7164, -28028, + 25980, 10876, -32124, 10876, 24956, -28028, -6140, 32124, -15996, -20860, + 31100, -244, -31100, 21884, 15484, -32124, 7932, 27004, -27004, -7164, + 32124, -16764, -20860, 31100, -2748, -29052, 24956, 10876, -32124, 13948, + 21884, -31100, 1244, 30076, -23932, -10876, 32124, -14460, -20860, 31100, + -3260, -29052, 25980, 7676, -32124, 17788, 17788, -32124, 8828, 24956, + -29052, -652, 30076, -23932, -9852, 32124, -17788, -17788, 32124, -9852, + -23932, 30076, -2364, -28028, 27004, 4860, -31100, 22908, 11388, -32124, + 17788, 16764, -32124, 12412, 21884, -32124, 7164, 24956, -30076, 2492, + 28028, -28028, -1820, 30076, -25980, -5628, 31100, -23932, -8828, 32124, + -21884, -11388, 32124, -19836, -12924, 32124, -18812, -14460, 32124, -17788, + -15484, 32124, -16764, -15996, 32124, -16764, -15996, 32124, -17788, -14972, + 32124, -17788, -13948, 32124, -19836, -12412, 32124, -20860, -10364, 32124, + -22908, -7676, 31100, -24956, -4348, 30076, -27004, -372, 28028, -30076, + 4092, 24956, -31100, 9340, 20860, -32124, 14460, 16764, -32124, 19836, + 10876, -32124, 24956, 4092, -29052, 29052, -3516, -24956, 32124, -11388, + -18812, 32124, -18812, -10876, 31100, -25980, -1628, 27004, -30076, 8316, + 20860, -32124, 17788, 11388, -31100, 25980, 276, -25980, 31100, -11388, + -17788, 32124, -21884, -5884, 29052, -30076, 7420, 20860, -32124, 19836, + 8316, -30076, 29052, -6396, -20860, 32124, -19836, -7164, 29052, -30076, + 8828, 18812, -32124, 22908, 3260, -27004, 31100, -13948, -13948, 31100, + -27004, 4092, 21884, -32124, 20860, 5116, -28028, 31100, -13948, -12924, + 31100, -29052, 7164, 18812, -32124, 24956, -1180, -22908, 32124, -20860, + -3900, 25980, -32124, 17788, 7676, -28028, 31100, -14972, -10364, 30076, + -31100, 13436, 12412, -30076, 30076, -12412, -12924, 30076, -30076, 12412, + 12412, -30076, 30076, -13436, -10876, 29052, -31100, 15484, 8828, -28028, + 32124, -18812, -5116, 25980, -32124, 21884, 196, -21884, 32124, -25980, + 5628, 17788, -31100, 29052, -12412, -10876, 29052, -32124, 19836, 2492, + -22908, 32124, -25980, 6908, 15484, -30076, 31100, -16764, -5116, 24956, + -32124, 25980, -6908, -14972, 30076, -31100, 18812, 1884, -21884, 32124, + -29052, 12412, 8828, -25980, 32124, -24956, 7164, 13948, -29052, 32124, + -21884, 3260, 16764, -30076, 32124, -20860, 1180, 18812, -31100, 31100, + -19836, 988, 18812, -31100, 32124, -20860, 2492, 16764, -30076, 32124, + -22908, 5884, 13436, -28028, 32124, -25980, 10876, 7932, -23932, 32124, + -30076, 17788, 556, -18812, 30076, -32124, 23932, -8828, -9340, 24956, + -32124, 30076, -18812, 1980, 15484, -28028, 32124, -28028, 14972, 2236, + -18812, 30076, -32124, 27004, -13436, -3644, 19836, -30076, 32124, -27004, + 13948, 2236, -17788, 29052, -32124, 28028, -16764, 1820, 13948, -25980, + 32124, -31100, 21884, -8316, -7164, 20860, -30076, 32124, -28028, 17788, + -3004, -11900, 23932, -31100, 32124, -25980, 15484, -1180, -12924, 24956, + -31100, 32124, -27004, 16764, -3260, -10876, 22908, -30076, 32124, -29052, + 20860, -8828, -4348, 16764, -27004, 32124, -32124, 27004, -17788, 5884, +}; diff --git a/test/cmocka/src/math/arithmetic/ref_chirp_mono_8k_s16.h b/test/cmocka/src/math/arithmetic/ref_chirp_mono_8k_s16.h new file mode 100644 index 000000000000..29c4493969a5 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/ref_chirp_mono_8k_s16.h @@ -0,0 +1,412 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 13-May-2025 18:29:28 with script a_law_mu_law_test_vectors.m */ + +#include <stdint.h> +#define REF_DATA_SAMPLE_COUNT 4000 + +static const int16_t chirp_mono_8k_s16[4000] = { + 30209, 29119, 27848, 26404, 24795, 23030, 21121, 19078, 16914, 14643, + 12277, 9833, 7324, 4767, 2178, -427, -3032, -5620, -8175, -10680, + -13119, -15476, -17736, -19885, -21907, -23791, -25522, -27091, -28485, -29696, + -30715, -31535, -32151, -32557, -32751, -32730, -32494, -32044, -31383, -30515, + -29443, -28176, -26721, -25087, -23284, -21325, -19221, -16987, -14637, -12186, + -9651, -7049, -4398, -1714, 984, 3678, 6349, 8979, 11551, 14045, + 16446, 18736, 20899, 22920, 24784, 26480, 27993, 29313, 30431, 31339, + 32028, 32495, 32734, 32744, 32524, 32076, 31400, 30503, 29389, 28066, + 26542, 24829, 22937, 20879, 18671, 16327, 13863, 11298, 8650, 5936, + 3178, 393, -2396, -5171, -7910, -10594, -13203, -15718, -18120, -20391, + -22515, -24474, -26254, -27842, -29225, -30392, -31334, -32044, -32516, -32745, + -32729, -32467, -31962, -31215, -30233, -29021, -27588, -25946, -24104, -22078, + -19882, -17532, -15046, -12442, -9740, -6962, -4127, -1258, 1624, 4495, + 7334, 10119, 12827, 15438, 17930, 20285, 22482, 24505, 26336, 27962, + 29369, 30544, 31478, 32164, 32594, 32765, 32674, 32323, 31712, 30846, + 29731, 28376, 26791, 24989, 22982, 20787, 18421, 15903, 13254, 10493, + 7645, 4731, 1776, -1196, -4161, -7095, -9972, -12769, -15463, -18031, + -20451, -22702, -24766, -26624, -28260, -29660, -30812, -31705, -32332, -32685, + -32761, -32559, -32080, -31327, -30306, -29025, -27494, -25726, -23735, -21538, + -19153, -16600, -13901, -11079, -8159, -5165, -2123, 940, 3998, 7023, + 9989, 12870, 15640, 18275, 20750, 23043, 25134, 27003, 28634, 30010, + 31119, 31950, 32495, 32749, 32708, 32372, 31743, 30826, 29628, 28161, + 26436, 24468, 22275, 19876, 17293, 14549, 11669, 8678, 5605, 2477, + -676, -3826, -6944, -9999, -12964, -15810, -18511, -21040, -23374, -25490, + -27368, -28988, -30336, -31397, -32161, -32620, -32768, -32603, -32127, -31342, + -30255, -28877, -27219, -25297, -23129, -20734, -18137, -15361, -12433, -9381, + -6234, -3024, 219, 3462, 6674, 9824, 12879, 15809, 18585, 21179, + 23565, 25718, 27616, 29240, 30572, 31599, 32309, 32694, 32750, 32474, + 31870, 30942, 29698, 28151, 26316, 24210, 21855, 19274, 16492, 13538, + 10442, 7235, 3951, 623, -2715, -6027, -9279, -12438, -15469, -18341, + -21023, -23486, -25705, -27654, -29313, -30663, -31689, -32379, -32725, -32723, + -32371, -31673, -30635, -29267, -27582, -25600, -23339, -20823, -18080, -15138, + -12030, -8787, -5446, -2042, 1388, 4805, 8172, 11452, 14609, 17608, + 20414, 22996, 25325, 27375, 29121, 30544, 31627, 32356, 32722, 32721, + 32352, 31617, 30524, 29084, 27313, 25230, 22859, 20224, 17356, 14287, + 11051, 7685, 4228, 719, -2801, -6292, -9713, -13024, -16187, -19164, + -21920, -24422, -26641, -28548, -30122, -31343, -32195, -32667, -32753, -32451, + -31762, -30696, -29262, -27477, -25362, -22942, -20243, -17299, -14144, -10815, + -7353, -3798, -194, 3415, 6987, 10476, 13840, 17037, 20029, 22777, + 25247, 27407, 29232, 30696, 31781, 32472, 32759, 32639, 32111, 31181, + 29859, 28162, 26108, 23725, 21039, 18085, 14900, 11523, 7996, 4364, + 674, -3029, -6696, -10280, -13736, -17017, -20083, -22891, -25406, -27594, + -29426, -30876, -31926, -32559, -32768, -32547, -31900, -30832, -29357, -27494, + -25266, -22701, -19833, -16699, -13339, -9799, -6125, -2366, 1428, 5207, + 8919, 12514, 15943, 19159, 22119, 24781, 27109, 29069, 30635, 31783, + 32497, 32766, 32585, 31955, 30883, 29384, 27478, 25188, 22547, 19589, + 16356, 12891, 9244, 5463, 1602, -2284, -6142, -9916, -13554, -17003, + -20214, -23140, -25740, -27974, -29811, -31222, -32187, -32691, -32725, -32286, + -31381, -30022, -28225, -26018, -23430, -20498, -17265, -13776, -10082, -6237, + -2297, 1680, 5636, 9512, 13251, 16797, 20096, 23099, 25760, 28039, + 29900, 31315, 32260, 32721, 32689, 32164, 31152, 29666, 27730, 25369, + 22621, 19524, 16127, 12479, 8637, 4659, 605, -3462, -7478, -11383, + -15114, -18614, -21827, -24703, -27196, -29265, -30878, -32007, -32634, -32748, + -32344, -31429, -30015, -28124, -25783, -23031, -19908, -16464, -12754, -8836, + -4773, -629, 3529, 7633, 11618, 15417, 18970, 22217, 25105, 27586, + 29618, 31166, 32204, 32714, 32685, 32117, 31018, 29404, 27301, 24742, + 21769, 18431, 14781, 10881, 6796, 2592, -1659, -5886, -10017, -13982, + -17714, -21148, -24226, -26894, -29105, -30821, -32010, -32651, -32732, -32249, + -31209, -29629, -27535, -24962, -21952, -18558, -14838, -10855, -6678, -2381, + 1962, 6274, 10479, 14503, 18275, 21726, 24794, 27424, 29568, 31187, + 32250, 32736, 32636, 31949, 30686, 28869, 26529, 23707, 20452, 16824, + 12886, 8709, 4370, -52, -4478, -8826, -13015, -16968, -20611, -23877, + -26703, -29036, -30832, -32056, -32683, -32699, -32104, -30907, -29127, -26798, + -23962, -20671, -16986, -12976, -8716, -4286, 229, 4744, 9172, 13428, + 17430, 21101, 24369, 27170, 29448, 31158, 32265, 32747, 32592, 31801, + 30388, 28380, 25813, 22738, 19212, 15305, 11092, 6656, 2085, -2532, + -7103, -11536, -15743, -19640, -23146, -26191, -28713, -30659, -31988, -32673, + -32696, -32058, -30767, -28849, -26342, -23295, -19768, -15834, -11571, -7066, + -2412, 2296, 6961, 11486, 15777, 19743, 23302, 26378, 28906, 30830, + 32111, 32717, 32636, 31867, 30425, 28337, 25647, 22410, 18694, 14576, + 10144, 5490, 715, -4079, -8790, -13316, -17559, -21426, -24833, -27704, + -29976, -31597, -32531, -32755, -32263, -31063, -29181, -26654, -23538, -19900, + -15818, -11382, -6690, -1845, 3045, 7872, 12527, 16906, 20909, 24446, + 27436, 29810, 31513, 32504, 32759, 32270, 31047, 29115, 26516, 23309, + 19565, 15369, 10815, 6008, 1059, -3920, -8812, -13504, -17886, -21856, + -25319, -28194, -30412, -31918, -32676, -32666, -31886, -30352, -28099, -25178, + -21657, -17617, -13154, -8374, -3389, 1682, 6717, 11595, 16198, 20414, + 24141, 27286, 29773, 31538, 32538, 32745, 32152, 30773, 28637, 25797, + 22320, 18290, 13804, 8974, 3916, -1242, -6375, -11353, -16053, -20355, + -24152, -27346, -29855, -31616, -32581, -32723, -32038, -30540, -28265, -25269, + -21626, -17428, -12780, -7801, -2617, 2638, 7830, 12825, 17493, 21712, + 25371, 28374, 30641, 32111, 32743, 32519, 31442, 29538, 26856, 23463, + 19447, 14914, 9981, 4779, -555, -5879, -11050, -15931, -20389, -24304, + -27569, -30095, -31811, -32669, -32644, -31733, -29959, -27369, -24030, -20032, + -15482, -10504, -5233, 187, 5606, 10875, 15848, 20387, 24363, 27666, + 30202, 31896, 32701, 32592, 31567, 29655, 26907, 23398, 19224, 14503, + 9366, 3959, -1565, -7050, -12338, -17278, -21727, -25557, -28655, -30931, + -32316, -32768, -32271, -30838, -28508, -25346, -21441, -16907, -11874, -6488, + -908, 4705, 10184, 15367, 20100, 24241, 27667, 30272, 31979, 32732, + 32507, 31309, 29170, 26153, 22345, 17861, 12832, 7411, 1760, -3949, + -9543, -14852, -19711, -23971, -27501, -30189, -31951, -32730, -32500, -31264, + -29059, -25951, -22032, -17425, -12269, -6726, -967, 4827, 10475, 15798, + 20627, 24809, 28210, 30720, 32256, 32767, 32236, 30674, 28130, 24682, + 20440, 15536, 10128, 4388, -1499, -7342, -12952, -18147, -22755, -26625, + -29629, -31666, -32667, -32595, -31451, -29270, -26120, -22103, -17351, -12018, + -6281, -330, 5638, 11422, 16829, 21676, 25798, 29056, 31337, 32561, + 32684, 31698, 29636, 26563, 22581, 17826, 12456, 6654, 619, -5442, + -11321, -16815, -21733, -25901, -29175, -31438, -32608, -32641, -31534, -29322, + -26080, -21918, -16982, -11443, -5494, 654, 6784, 12679, 18128, 22935, + 26929, 29963, 31926, 32745, 32388, 30864, 28225, 24564, 20010, 14727, + 8904, 2751, -3507, -9643, -15431, -20658, -25132, -28684, -31183, -32533, + -32681, -31618, -29381, -26049, -21744, -16624, -10879, -4720, 1620, 7906, + 13899, 19374, 24121, 27959, 30741, 32358, 32745, 31885, 29806, 26585, + 22343, 17239, 11468, 5251, -1175, -7562, -13661, -19235, -24066, -27965, + -30777, -32388, -32734, -31796, -29608, -26253, -21860, -16601, -10680, -4330, + 2197, 8642, 14749, 20272, 24990, 28711, 31283, 32600, 32605, 31295, + 28720, 24979, 20223, 14640, 8457, 1924, -4694, -11126, -17107, -22391, + -26758, -30027, -32059, -32768, -32119, -30137, -26901, -22541, -17238, -11209, + -4705, 2001, 8630, 14900, 20549, 25334, 29051, 31540, 32692, 32454, + 30833, 27894, 23760, 18604, 12645, 6138, -640, -7396, -13839, -19687, + -24687, -28619, -31308, -32634, -32536, -31014, -28131, -24010, -18828, -12813, + -6227, 641, 7486, 14005, 19907, 24927, 28840, 31466, 32686, 32440, + 30737, 27648, 23309, 17914, 11703, 4956, -2023, -8915, -15407, -21201, + -26030, -29671, -31952, -32767, -32072, -29897, -26338, -21556, -15769, -9244, + -2284, 4790, 11645, 17962, 23442, 27825, 30903, 32527, 32616, 31162, + 28230, 23955, 18537, 12231, 5336, -1820, -8896, -15551, -21464, -26348, + -29966, -32139, -32758, -31789, -29275, -25333, -20154, -13985, -7126, 87, + 7303, 14166, 20337, 25509, 29424, 31886, 32767, 32019, 29677, 25852, + 20732, 14569, 7670, 379, -6936, -13909, -20185, -25445, -29420, -31904, + -32768, -31962, -29524, -25574, -20310, -14000, -6964, 437, 7822, 14809, + 21035, 26176, 29960, 32189, 32741, 31583, 28771, 24449, 18838, 12232, + 4975, -2550, -9948, -16825, -22814, -27596, -30913, -32582, -32511, -30700, + -27239, -22312, -16180, -9169, -1657, 5951, 13243, 19823, 25329, 29460, + 31986, 32764, 31748, 28988, 24631, 18914, 12149, 4705, -3005, -10556, + -17526, -23527, -28221, -31342, -32711, -32248, -29972, -26009, -20575, -13975, + -6579, 1196, 8911, 16125, 22427, 27455, 30917, 32612, 32436, 30397, + 26605, 21276, 14712, 7291, -559, -8384, -15727, -22160, -27305, -30856, + -32603, -32436, -30362, -26497, -21065, -14382, -6842, 1110, 9004, 16369, + 22763, 27803, 31182, 32695, 32245, 29853, 25660, 19914, 12957, 5210, + -2861, -10765, -18020, -24181, -28869, -31793, -32768, -31729, -28736, -23968, + -17714, -10358, -2353, 5805, 13609, 20571, 26254, 30300, 32450, 32564, + 30629, 26763, 21205, 14300, 6484, -1751, -9882, -17390, -23795, -28686, + -31743, -32768, -31688, -28567, -23602, -17108, -9501, -1272, 7048, 14915, + 21818, 27302, 31006, 32681, 32213, 29627, 25087, 18888, 11436, 3219, + -5218, -13316, -20534, -26390, -30487, -32548, -32429, -30132, -25806, -19737, + -12330, -4083, 4448, 12684, 20066, 26087, 30333, 32509, 32462, 30188, + 25837, 19704, 12207, 3860, -4762, -13060, -20459, -26441, -30585, -32598, + -32332, -29801, -25176, -18776, -11049, -2535, 6166, 14437, 21691, 27411, + 31183, 32736, 31951, 28879, 23733, 16879, 8804, 88, -8642, -16755, + -23661, -28855, -31955, -32731, -31119, -27230, -21344, -13888, -5404, 3485, + 12125, 19876, 26163, 30516, 32606, 32272, 29532, 24585, 17794, 9665, + 802, -8128, -16454, -23545, -28862, -31999, -32710, -30937, -26806, -20628, + -12868, -4116, 4958, 13660, 21318, 27340, 31255, 32757, 31722, 28223, + 22526, 15070, 6431, -2718, -11662, -19698, -26194, -30633, -32660, -32109, + -29015, -23618, -16341, -7757, 1453, 10554, 18820, 25584, 30300, 32584, + 32245, 29304, 23991, 16730, 8106, -1185, -10387, -18749, -25587, -30337, + -32604, -32194, -29135, -23672, -16249, -7476, 1924, 11173, 19500, 26210, + 30739, 32702, 31928, 28474, 22625, 14865, 5845, -3676, -12895, -21028, + -27382, -31412, -32768, -31326, -27204, -20747, -12504, -3178, 6430, 15491, + 23221, 28946, 32165, 32591, 30181, 25135, 17890, 9072, -549, -10130, + -18828, -25874, -30641, -32701, -31866, -28202, -22026, -13883, -4493, 5306, + 14638, 22665, 28662, 32084, 32615, 30199, 25049, 17622, 8589, -1234, + -10952, -19679, -26614, -31115, -32764, -31402, -27146, -20381, -11726, -1977, + 7963, 17172, 24790, 30102, 32607, 32062, 28510, 22278, 13944, 4288, + -5780, -15311, -23399, -29273, -32368, -32383, -29307, -23427, -15298, -5695, + 4463, 14201, 22578, 28780, 32202, 32506, 29652, 23910, 15834, 6204, + -4041, -13898, -22400, -28707, -32191, -32502, -29600, -23764, -15566, -5814, + 4526, 14422, 22887, 29068, 32340, 32367, 29138, 22969, 14475, 4510, + -5920, -15758, -24003, -29810, -32580, -32022, -28184, -21452, -12510, -2272, + 8208, 17850, 25653, 30803, 32758, 31307, 26592, 19097, 9598, -915, + -11341, -20584, -27666, -31835, -32643, -29995, -24163, -15759, -5669, 5033, + 15207, 23762, 29777, 32600, 31918, 27796, 20669, 11301, 701, -9985, + -19594, -27077, -31613, -32697, -30202, -24392, -15897, -5646, 5238, 15552, + 24154, 30086, 32682, 31645, 27080, 19489, 9712, -1162, -11914, -21336, + -28364, -32197, -32395, -28926, -22173, -12895, -2141, 8866, 18870, 26723, + 31520, 32702, 30123, 24071, 15236, 4631, -6519, -16922, -25367, -30866, + -32768, -30843, -25305, -16795, -6305, 4936, 15605, 24440, 30391, 32745, + 31214, 25968, 17625, 7170, -4151, -14984, -24028, -30193, -32727, -31315, + -26119, -17756, -7233, 4177, 15089, 24171, 30309, 32744, 31169, 25766, + 17190, 6488, -5023, -15923, -24860, -30720, -32768, -30738, -24872, -15894, + -4918, 6683, 17454, 26039, 31349, 32705, 29926, 23352, 13808, 2500, + -9135, -19615, -27596, -32051, -32397, -28581, -21082, -10858, 778, 12322, + 22279, 29351, 32611, 31623, 26506, 17918, 6975, -4893, -16127, -25247, + -31044, -32742, -30106, -23475, -13720, -2129, 9755, 20346, 28224, 32325, + 32089, 27536, 19269, 8394, -3626, -15164, -24655, -30802, -32759, -30249, + -23603, -13721, -1948, 10103, 20773, 28589, 32462, 31848, 26819, 18063, + 6786, -5445, -16927, -26051, -31535, -32599, -29081, -21466, -10817, 1370, + 13373, 23491, 30279, 32765, 30583, 24031, 14037, 2022, -10293, -21138, + -28947, -32586, -31517, -25883, -16489, -4691, 7800, 19164, 27738, 32259, + 32055, 27144, 18234, 6630, -5963, -17685, -26796, -31938, -32336, -27918, + -19330, -7847, 4822, 16777, 26222, 31728, 32455, 28280, 19822, 8353, + -4395, -16485, -26073, -31689, -32464, -28267, -19729, -8151, 4692, 16822, + 26363, 31831, 32367, 27875, 19041, 7232, -5716, -17782, -27070, -32117, + -32117, -27057, -17723, -5579, 7459, 19325, 28129, 32462, 31621, 25728, + 15712, 3168, -9895, -21377, -29423, -32725, -30737, -23767, -12934, 12, + 12966, 23816, 30782, 32714, 29281, 21034, 9318, -3944, -16566, -26457, + -31972, -32181, -27038, -17385, -4822, 8558, 20516, 29041, 32691, 30839, + 23784, 12703, -537, -13698, -24542, -31219, -32580, -28378, -19317, -6939, + 6641, 19090, 28261, 32562, 31238, 24502, 13510, 161, -13227, -24320, + -31173, -32576, -28269, -18994, -6369, 7389, 19853, 28817, 32683, 30752, + 23351, 11785, -1893, -15244, -25877, -31878, -32156, -26647, -16329, -3053, + 10787, 22683, 30470, 32722, 29013, 20006, 7334, -6693, -19503, -28739, + -32691, -30617, -22883, -10908, 3100, 16543, 26920, 32288, 31631, 25057, + 13782, -88, -13954, -25203, -31706, -32221, -26635, -15992, -2302, 11838, + 23732, 31103, 32529, 27720, 17584, 4058, -10262, -22612, -30601, -32668, + -28398, -18604, -5180, 9266, 21914, 30282, 32719, 28731, 19086, 5671, + -8876, -21678, -30196, -32726, -28751, -19045, -5531, 9100, 21921, 30355, + 32697, 28458, 18477, 4756, -9939, -22632, -30739, -32600, -27819, -17356, + -3335, 11381, 23774, 31290, 32368, 26771, 15636, 1256, -13396, -25278, + -31910, -31895, -25220, -13263, 1482, 15929, 27038, 32460, 31037, 23052, + 10179, -4864, -18886, -28899, -32758, -29623, -20146, -6343, 8834, 22123, + 30655, 32577, 27457, 16384, 1747, -13282, -25431, -32042, -31658, -24343, + -11684, 3551, 18018, 28525, 32742, 29719, 20109, 6028, -9406, -22757, + -31041, -32394, -26494, -14646, 502, 15550, 27103, 32545, 30626, 21764, + 7953, -7678, -21573, -30555, -32558, -27105, -15429, -197, 15093, 26915, + 32527, 30615, 21603, 7566, -8242, -22143, -30885, -32410, -26343, -14088, + 1489, 16728, 28033, 32722, 29667, 19574, 4822, -11090, -24371, -31842, + -31701, -23962, -10465, 5561, 20259, 30081, 32638, 27293, 15322, -382, + -16006, -27739, -32705, -29672, -19362, -4289, 11851, 25084, 32136, 31246, + 22615, 8366, -7975, -22344, -31150, -32180, -25155, -11816, 4501, 19699, + 29944, 32636, 27075, 14649, -1505, -17290, -28683, -32767, -28480, -16896, + -970, 15219, 27503, 32707, 29467, 18600, 2904, -13559, -26508, -32562, + -30123, -19806, -4294, 12358, 25775, 32417, 30515, 20551, 5140, -11647, + -25353, -32327, -30691, -20861, -5445, 11443, 25273, 32321, 30671, 20747, + 5208, -11753, -25540, -32402, -30452, -20201, -4425, 12573, 26140, 32544, + 30005, 19199, 3088, -13889, -27035, -32693, -29273, -17703, -1189, 15671, + 28161, 32767, 28180, 15664, -1275, -17868, -29423, -32655, -26627, -13027, + 4291, 20400, 30695, 32215, 24502, 9748, -7822, -23152, -31812, -31281, + -21690, -5797, 11792, 25963, 32573, 29672, 18084, 1186, -16074, -28619, + -32740, -27200, -13611, 4020, 20473, 30852, 32054, 23694, 8248, -9679, + -24718, -32345, -30246, -19028, -2057, 15550, 28460, 32742, 27074, 13155, + -4788, -21282, -31274, -31683, -22359, -6147, 11972, 26409, 32688, 28843, + 16042, -1757, -19024, -30368, -32229, -24001, -8238, 10125, 25316, 32538, + 29489, 17108, -704, -18307, -30102, -32317, -24220, -8375, 10165, 25458, + 32584, 29226, 16442, -1662, -19244, -30601, -32033, -23046, -6545, 12106, + 26814, 32751, 27949, 13958, -4638, -21720, -31641, -31099, -20248, -2665, + 15818, 29045, 32588, 25237, 9428, -9556, -25344, -32612, -28887, -15400, + 3309, 20911, 31426, 31258, 20439, 2634, -16085, -29309, -32487, -24501, + -8073, 11152, 26539, 32754, 27617, 12886, -6340, -23371, -32257, -29870, + -17018, 1816, 20027, 31199, 31376, 20467, 2306, -16688, -29769, -32269, + -23272, -5959, 13498, 28135, 32687, 25493, 9113, -10567, -26443, -32761, + -27205, -11764, 7969, 24813, 32612, 28490, 13928, -5756, -23340, -32342, + -29422, -15627, 3962, 22098, 32040, 30069, 16890, -2605, -21141, -31771, + -30486, -17740, 1696, 20507, 31584, 30715, 18199, -1239, -20220, -31510, + -30778, -18275, 1238, 20292, 31559, 30683, 17970, -1696, -20720, -31726, + -30418, -17274, 2612, 21493, 31984, 29953, 16166, -3986, -22584, -32288, + -29242, -14619, 5811, 23948, 32572, 28222, 12601, -8070, -25525, -32750, + -26817, -10081, 10733, 27227, 32714, 24942, 7034, -13748, -28944, -32336, + -22508, -3453, 17034, 30534, 31474, 19433, -646, -20472, -31827, -29973, + -15650, 5206, 23904, 32621, 27682, 11125, -10120, -27121, -32697, -24465, + -5873, 15222, 29869, 31823, 20219, -23, -20271, -31852, -29778, -14905, + 6395, 24954, 32748, 26378, 8571, -12971, -28888, -32231, -21511, -1380, + 19371, 31641, 30016, 15179, -6362, -25109, -32762, -25901, -7537, 14192, + 29616, 31836, 19828, -1066, -21498, -32287, -28554, -11945, 10070, 27546, + 32554, 22789, 2656, -18702, -31544, -29979, -14690, 7348, 26026, 32743, + 24373, 4744, -17094, -31029, -30574, -15906, 6180, 25399, 32765, 24801, + 5203, -16853, -30997, -30544, -15672, 6621, 25794, 32743, 24135, 4030, + -18012, -31465, -29872, -13958, 8670, 27144, 32554, 22256, 1192, -20466, + -32211, -28313, -10631, 12248, 29161, 31820, 18887, -3327, -23922, -32748, + -25422, -5526, 17120, 31293, 29930, 13672, -9413, -27815, -32317, -20632, + 1417, 22769, 32671, 26099, 6335, -16650, -31210, -29930, -13422, 9938, + 28242, 32117, 19545, -3064, -24115, -32766, -24526, -3610, 19189, 32058, + 28292, 9809, -13798, -30221, -30858, -15338, 8239, 27504, 32307, 20082, + -2757, -24154, -32768, -23995, -2458, 20403, 32396, 27086, 7272, -16455, + -31360, -29404, -11600, 12479, 29828, 31031, 15399, -8615, -27955, -32064, + -18659, 4965, 25884, 32607, 21401, -1603, -23739, -32768, -23659, -1421, + 21622, 32648, 25481, 4080, -19619, -32342, -26922, -6362, 17795, 31930, + 28034, 8266, -16201, -31485, -28868, -9799, 14877, 31064, 29471, 10968, + -13850, -30714, -29878, -11785, 13140, 30467, 30119, 12257, -12757, -30345, + -30210, -12389, 12710, 30361, 30159, 12182, -13000, -30511, -29960, -11631, + 13624, 30786, 29599, 10729, -14574, -31159, -29047, -9464, 15834, 31594, + 28268, 7823, -17381, -32042, -27215, -5795, 19179, 32439, 25835, 3371, + -21180, -32706, -24068, -554, 23319, 32753, 21855, -2643, -25512, -32475, + -19141, 6187, 27652, 31758, 15881, -10019, -29610, -30485, -12047, 14050, + 31232, 28539, 7640, -18154, -32347, -25814, -2700, 22166, 32767, 22230, + -2686, -25879, -32303, -17743, 8373, 29049, 30770, 12367, -14151, -31400, + -28020, -6187, 19741, 32644, 23953, -622, -24801, -32500, -18553, 7784, + 28936, 30727, 11911, -14919, -31728, -27162, -4254, 21547, 32767, 21761, + -4044, -27113, -31707, -14644, 12450, 31029, 28317, 6131, -20294, -32733, + -22558, 3241, 26809, 31771, 14632, -12717, -31205, -27886, -5033, 21366, + 32767, 21111, -5439, -28165, -30980, -11844, 15711, 32114, 25657, 893, + -24525, -32407, -17060, 10547, 30586, 28600, 5972, -20988, -32768, -20789, + 6302, 28823, 30349, 9717, -18036, -32593, -23244, 3196, 27300, 31287, + 12165, -15970, -32287, -24646, 1327, 26328, 31703, 13389, -14958, -32108, + -25155, 726, 26077, 31762, 13438, -15074, -32169, -24834, 1406, 26591, + 31488, 12305, -16317, -32435, -23633, 3370, 27791, 30761, 9931, -18608, + -32720, -21398, 6597, 29463, 29320, 6227, -21763, -32679, -17896, 10997, + 31228, 26786, 1130, -25437, -31813, -12877, 16334, 32523, 22713, -5297, + -29074, -29500, -6179, 22139, 32593, 16687, -12751, -31857, -25076, 2130, + 27615, 30554, 8491, -20545, -32731, -18006, 11561, 31606, 25543, -1670, + -27514, -30522, -8140, 21038, 32675, 17001, -12918, -32021, -24232, 3953, + 28823, 29373, 5083, -23528, -32193, -13504, 16691, 32673, 20760, -8919, + -30973, -26458, 805, 27391, 30369, 7113, -22311, -32415, -14384, 16166, + 32653, 20664, -9390, -31242, -25718, 2394, 28416, 29419, 4461, -24454, + -31737, -10880, 19653, 32719, 16635, -14306, -32475, -21572, 8686, 31158, + 25604, -3032, -28947, -28700, -2456, 26031, 30879, 7623, -22596, -32198, + -12355, 18819, 32741, 16577, -14858, -32610, -20252, 10850, 31915, 23369, + -6907, -30768, -25946, 3119, 29281, 28015, 448, -27556, -29622, -3745, + 25685, 30823, 6744, -23751, -31675, -9431, 21824, 32240, 11800, -19965, + -32574, -13858, 18220, 32733, 15616, -16629, -32767, -17088, 15224, 32719, + 18290, -14026, -32626, -19238, 13055, 32521, 19948, -12322, -32427, -20431, + 11837, 32363, 20696, -11605, -32338, -20747, 11629, 32356, 20585, -11909, + -32416, -20206, 12444, 32507, 19602, -13229, -32612, -18761, 14254, 32709, + 17668, -15508, -32765, -16306, 16972, 32742, 14656, -18622, -32595, -12701, + 20425, 32272, 10425, -22338, -31716, -7819, 24308, 30863, 4880, -26269, + -29649, -1619, 28143, 28009, -1942, -29838, -25882, 5761, 31248, 23216, + -9772, -32257, -19973, 13888, 32743, 16133, -17992, -32579, -11707, 21940, + 31643, 6739, -25561, -29828, -1314, 28661, 27049, -4435, -31029, -23260, + 10322, 32449, 18466, -16113, -32715, -12734, 21522, 31646, 6210, -26228, + -29112, 876, 29888, 25057, -8206, -32159, -19521, 15377, 32734, 12664, + -21921, -31374, -4780, 27328, 27950, -3697, -31083, -22482, 12203, 32726, + 15176, -20071, -31903, -6439, 26578, 28436, -3111, -31012, -22378, 12674, + 32759, 14064, -21319, -31394, -4125, 28072, 26781, -6523, -32033, -19143, + 16743, 32505, 9113, -25286, -29141, 2277, 30948, 22052, -13667, -32754, + -11889, 23513, 30154, -164, -30294, -23187, 12479, 32767, 12584, -23179, + -30232, 237, 30425, 22743, -13305, -32750, -11234, 24366, 29404, -2513, + -31280, -20622, 16081, 32461, 7729, -26819, -27304, 6960, 32366, 16464, + -20496, -31224, -1908, 29871, 23231, -13347, -32714, -9802, 25810, 27969, + -6193, -32314, -16350, 20953, 30890, 403, -30625, -21459, 15927, 32352, + 6112, -28213, -25224, 11191, 32767, 10797, -25556, -27848, 7048, 32531, + 14447, -23026, -29573, 3676, 31983, 17126, -20891, -30634, 1165, 31394, + 18926, -19333, -31224, -446, 30954, 19931, -18462, -31481, -1148, 30780, + 20198, -18334, -31473, -937, 30913, 19739, -18961, -31197, 193, 31324, + 18523, -20307, -30575, 2243, 31907, 16476, -22287, -29461, 5201, 32478, + 13500, -24744, -27646, 9013, 32767, 9495, -27435, -24876, 13554, 32423, + 4402, -30005, -20892, 18580, 31027, -1742, -31979, -15476, 23690, 28132, + -8738, -32768, -8538, 28296, 23334, -16157, -31716, -205, 31620, 16382, + -23286, -28194, 9061, 32756, 7323, -29119, -21760, 18391, 30799, -3339, + -32433, -12368, 26481, 25075, -14517, -31980, -600, 31707, 15446, -24519, + -26818, 12155, 32404, 2639, -31214, -16749, 23691, 27352, -11525, -32462, + -2766, 31259, 16385, -24167, -26805, 12684, 32219, 970, -31818, -14308, + 25863, 25031, -15555, -31410, 2765, 32537, 10333, -28410, -21637, 19861, + 29448, -8363, -32702, -4252, 31080, 16095, -24993, -25501, 15468, 31251, + -3941, -32703, -7965, 29830, 18682, -23170, -26897, 13709, 31695, -2713, + -32636, -8453, 29772, 18495, -23586, -26337, 14904, 31222, -4762, -32764, + -5721, 30954, 15474, -26124, -23577, 18877, 29341, -10003, -32348, 378, + 32466, 9122, -29826, -17701, 24785, 24707, -17871, -29671, 9714, 32323, + -991, -32594, -7643, 30594, 15593, -26588, -22368, 20951, 27601, -14135, + -31062, 6621, 32652, 1111, -32397, -8618, 30427, 15513, -26956, -21484, + 22259, 26301, -16642, -29817, 10428, 31968, -3931, -32761, -2559, 32265, + 8782, -30598, -14525, 27914, 19619, -24390, -23943, 20213, 27421, -15573, + -30019, 10651, 31742, -5614, -32621, 608, 32716, 4238, -32103, -8824, + 30869, 13070, -29109, -16919, 26920, 20335, -24398, -23300, 21632, 25814, + -18705, -27888, 15693, 29543, -12661, -30811, 9665, 31727, -6752, -32330, + 3958, 32663, -1312, -32768, -1164, 32685, 3455, -32454, -5553, 32111, + 7453, -31692, -9155, 31226, 10661, -30743, -11973, 30266, 13099, -29815, + -14043, 29410, 14812, -29065, -15410, 28791, 15843, -28597, -16114, 28489, + 16225, -28472, -16177, 28544, 15969, -28705, -15599, 28949, 15063, -29270, + -14357, 29656, 13474, -30094, -12409, 30567, 11154, -31056, -9703, 31535, + 8051, -31979, -6194, 32355, 4132, -32628, -1865, 32761, -597, -32713, + 3243, 32440, -6052, -31896, 8997, 31037, -12040, -29819, 15136, 28202, + -18226, -26149, 21242, 23634, -24103, -20642, 26722, 17170, -28999, -13234, + 30830, 8870, -32107, -4139, 32726, -873, -32586, 6054, 31602, -11262, + -29708, 16332, 26868, -21075, -23082, 25283, 18391, -28744, -12890, 31243, + 6727, -32585, -108, 32602, -6707, -31175, 13407, 28248, -19644, -23846, + 25050, 18085, -29256, -11184, 31921, 3466, -32763, 4650, 31591, -12664, + -28334, 20019, 23070, -26144, -16041, 30497, 7660, -32618, 1498, 32185, + -10726, -29070, 19235, 23374, -26215, -15455, 30921, 5931, -32758, 4355, + 31369, -14394, -26711, 23101, 19100, -29440, -9225, 32553, -1889, -31894, + 12970, 27339, -22632, -19260, 29553, 8533, -32667, 3519, 31348, -15274, + -25563, 25014, 15944, -31181, -3766, 32653, -9184, -28972, 20850, 20502, + -29226, -8454, 32725, -5235, -30509, 18180, 22726, -27960, -10592, 32577, + -3742, -30907, 17529, 23021, -27936, -10289, 32643, -4786, -30406, 19013, + 21438, -29171, -7506, 32766, -8341, -28693, 22392, 17643, -31135, -2092, + 32173, -14173, -24950, 26936, 11069, -32659, 5958, 29520, -21528, -18083, + 31171, 1337, -31878, 15983, 23130, -28688, -7261, 32711, -11030, -26493, + 26004, 11695, -32678, 7098, 28558, -23694, -14697, 32318, -4403, -29685, + 22127, 16387, -32005, 3038, 30135, -21510, -16864, 31944, -3033, -30028, + 21918, 16156, -32170, 4395, 29331, -23308, -14208, 32548, -7103, -27857, + 25510, 10900, -32768, 11077, 25285, -28186, -6100, 32337, -16103, -21210, + 30790, -237, -30604, 21738, 15243, -32530, 7935, 26832, -27212, -7173, + 32394, -16423, -20359, 31369, -2802, -29271, 24587, 10870, -32731, 13816, + 22246, -30723, 1232, 29756, -24146, -11062, 32718, -14459, -21372, 31251, + -3315, -28600, 26075, 7741, -32265, 18257, 17474, -32432, 8981, 25056, + -29562, -649, 30075, -24357, -9722, 32482, -17607, -17590, 32500, -10076, + -23868, 30528, -2421, -28411, 27049, 4849, -31260, 22560, 11383, -32592, + 17514, 16983, -32661, 12297, 21573, -31755, 7208, 25174, -30164, 2462, + 27874, -28156, -1801, 29801, -25961, -5503, 31098, -23773, -8615, 31914, + -21741, -11138, 32382, -19980, -13092, 32621, -18572, -14507, 32722, -17575, + -15409, 32756, -17023, -15820, 32762, -16936, -15749, 32756, -17317, -15192, + 32724, -18157, -14135, 32625, -19427, -12550, 32390, -21081, -10406, 31924, + -23046, -7672, 31105, -25218, -4328, 29791, -27456, -379, 27830, -29576, + 4132, 25066, -31346, 9106, 21361, -32496, 14369, 16622, -32719, 19661, + 10824, -31701, 24626, 4054, -29151, 28815, -3465, -24849, 31711, -11338, + -18706, 32767, -18989, -10833, 31485, -25676, -1599, 27503, -30544, 8325, + 20720, -32722, 17961, 11402, -31475, 26091, 282, -26390, 31389, -11417, + -17568, 32649, -22050, -5792, 29076, -29749, 7416, 20594, -32764, 19887, + 8101, -29906, 29112, -6444, -21010, 32763, -20185, -7289, 29354, -29874, + 8596, 18893, -32667, 22887, 3292, -27076, 31567, -13701, -13792, 31558, + -27243, 3983, 21995, -32761, 21019, 5066, -27658, 31478, -14069, -12751, + 31003, -28603, 7272, 18812, -32508, 24955, -1199, -23287, 32735, -21190, + -3847, 26394, -32224, 17784, 7755, -28415, 31426, -15051, -10527, 29626, + -30683, 13183, 12214, -30246, 30221, -12282, -12865, 30409, -30160, 12391, + 12502, -30153, 30516, -13510, -11109, 29417, -31202, 15591, 8631, -28038, + 32019, -18518, -5005, 25773, -32652, 22076, 203, -22324, 32663, -25909, + 5707, 17398, -31506, 29478, -12473, -10794, 28581, -32043, 19577, 2530, + -23339, 32699, -26160, 7010, 15455, -30491, 31027, -16934, -5059, 24638, + -32757, 25776, -7021, -14878, 29993, -31595, 19086, 1858, -21925, 32330, + -28627, 12545, 8886, -26461, 32751, -25207, 7118, 13884, -29080, 32279, + -22285, 3279, 16992, -30401, 31679, -20438, 1211, 18430, -30877, 31414, + -19954, 963, 18333, -30712, 31646, -20906, 2545, 16683, -29827, 32236, + -23165, 5940, 13313, -27866, 32739, -26362, 11028, 7983, -24250, 32386, + -29790, 17431, 559, -18305, 30122, -32315, 24302, -8708, -9536, 24774, + -32381, 30137, -18832, 1947, 15451, -28246, 32765, -27801, 14892, 2199, + -18604, 29748, -32607, 26498, -13198, -3613, 19389, -29956, 32602, -26737, + 13987, 2293, -17922, 28978, -32763, 28438, -17172, 1789, 13956, -26311, + 32406, -30905, 22258, -8549, -7039, 20974, -30175, 32681, -28041, 17361, + -3016, -11900, 24250, -31505, 32250, -26431, 15320, -1211, -13067, 24724, + -31549, 32316, -26972, 16615, -3240, -10657, 22555, -30355, 32746, -29397, + 20984, -9030, -4385, 16993, -26725, 32041, -32162, 27156, -17905, 5921, +}; diff --git a/test/cmocka/src/math/arithmetic/scalar_power.c b/test/cmocka/src/math/arithmetic/scalar_power.c new file mode 100644 index 000000000000..8b23791e979e --- /dev/null +++ b/test/cmocka/src/math/arithmetic/scalar_power.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> + +#include <sof/audio/format.h> +#include <sof/math/power.h> +#include <sof/common.h> +#include "power_tables.h" +/* 'Error (max = 0.000034912111005), THD+N = -96.457180359025074' */ +#define CMP_TOLERANCE 0.0000150363575813 + +static void test_math_arithmetic_power_fixed(void **state) +{ + (void)state; + + double p; + int i; + int j; + + for (i = 0; i < ARRAY_SIZE(b); i++) { + for (j = 0; j < ARRAY_SIZE(e); j++) { + p = power_int32(b[i], e[j]); + float diff = fabsf(power_table[i][j] - (double)p / (1 << 15)); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: base = %.16f", + __func__, diff, (double)b[i] / (1 << 25)); + printf(", exponent = %.16f, power = %.16f\n", + (double)e[j] / (1 << 29), (double)p / (1 << 15)); + assert_true(diff <= CMP_TOLERANCE); + } + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_power_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/square_root.c b/test/cmocka/src/math/arithmetic/square_root.c new file mode 100644 index 000000000000..6a31588c1235 --- /dev/null +++ b/test/cmocka/src/math/arithmetic/square_root.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> + +#include <sof/math/sqrt.h> +#include <sof/audio/format.h> +#include <rtos/string.h> +#include <sof/common.h> + +/* 'Error[max] = 0.0003000860000000,THD(-dBc) = -87.1210823527511309' */ +#define CMP_TOLERANCE 0.0001689942 + +static const double sqrt_ref_table[] = { + 0.0000000000000000, 0.2529127196287289, 0.3580137261684250, 0.4383362543470480, + 0.5060667106469264, 0.5657458434447398, 0.6199010757774179, 0.6695089151758922, + 0.7156864056624241, 0.7590598625931949, 0.8002380017063674, 0.8392530626247365, + 0.8765332548597343, 0.9124250825410271, 0.9468285879714448, 0.9800251112854200, + 1.0121334212938529, 1.0433710015497843, 1.0735864616438677, 1.1029744939820685, + 1.1317074351394887, 1.1596234572049671, 1.1868830634270588, 1.2135304899342250, + 1.2397036881347898, 1.2652391387105444, 1.2902693214499832, 1.3148230929007141, + 1.3390178303517843, 1.3626935069009465, 1.3859648038460428, 1.4089384024417106, + 1.4314580907679415, 1.4536289448738284, 1.4754666899408471, 1.4970674458754356, + 1.5182805344369004, 1.5392012945030940, 1.5598414883410430, 1.5802893574042065, + 1.6003997303408295, 1.6202605162827983, 1.6399552204252408, 1.6593426315110451, + 1.6785061252494731, 1.6974532854396907, 1.7162624043615824, 1.7347972458979175, + 1.7531361407845656, 1.7712851751976586, 1.7893183496097054, 1.8071040368501201, + 1.8247163735084968, 1.8422265952170487, 1.8595062978852748, 1.8766268983537990, + 1.8935927121149891, 1.9104717594746068, 1.9271396388170734, 1.9436645881555799, + 1.9601125007572908, 1.9763617734046062, 1.9924785326635266, 2.0084659685628234, + 2.0243874459327196, 2.0401248429936829, 2.0557417684986605, 2.0712409474756917, + 2.0866835042418388, 2.1019545405705138, 2.1171154277400652, 2.1322257663648099, + 2.1471729232877355, 2.1620167451363552, 2.1767593459084997, 2.1914584719713490, + 2.2060043241401410, 2.2204548907543695, 2.2348120201987909, 2.2491317769308226, + 2.2633070038662453, 2.2773940013752560, 2.2914476694602910, 2.3053627188850347, + 2.3191942802134968, 2.3329438383992445, 2.3466648541067809, 2.3602543890966499, + 2.3737661268541177, 2.3872013883939496, 2.4006123079591588, 2.4138981537908761, + 2.4271112748749282, 2.4403028756693299, 2.4533737931163282, 2.4663754402969551, + 2.4793089069839604, 2.4922242356226696, 2.5050242482608827, 2.5177591878742098, + 2.5304782774210888, 2.5430857547967194, 2.5556310375326090, 2.5681150370943278, + 2.5805859466650203, 2.5929498012639969, 2.6052549809231724, 2.6175023131556161, + 2.6297390257875399, 2.6418728560436060, 2.6539512111660981, 2.6660206330081166, + 2.6779900782816579, 2.6899062628881700, 2.7017698915479462, 2.7136266381449752, + 2.7253870138018930, 2.7370968595849874, 2.7487568212739375, 2.7604117531402812, + 2.7719736453698474, 2.7834875128828940, 2.7949976241045360, 2.8064170328908711, + 2.8177901636300033, 2.8291175744390689, 2.8404427884354582, 2.8516802201728368, + 2.8628735427669523, 2.8740232715872360, 2.8851722218959477, 2.8962361080806240, + 2.9072578897476569, 2.9182798738083706, 2.9292187124939990, 2.9401168530136688, + 2.9509747462702896, 2.9618340496219568, 2.9726126187665289, 2.9833522462156559, + 2.9940941216626773, 3.0047569707257522, 3.0153821145710538, 3.0259699503836783, + 3.0365610688738007, 3.0470753139280951, 3.0575534030495688, 3.0679957066870220, + 3.0784422425351754, 3.0888139284157279, 3.0991509043809078, 3.1094927741514371, + 3.1197612338526808, 3.1299960063872287, 3.1401974211424988, 3.1504045499149789, + 3.1605400917999757, 3.1706432337342845, 3.1807142844611178, 3.1907918051402224, + 3.2007994606816590, 3.2107759235502562, 3.2207593849316032, 3.2306742112715421, + 3.2405587023112234, 3.2504131347991749, 3.2602752232365293, 3.2700702400713046, + 3.2798360048560355, 3.2895727781126838, 3.2993178153786578, 3.3089972636170311, + 3.3186484800856810, 3.3283083869662677, 3.3379037677111065, 3.3474716438306089, + 3.3570122504989461, 3.3665620793882591, 3.3760487375221642, 3.3855088128485207, + 3.3949784839156196, 3.4043859578490805, 3.4137675072784321, 3.4231233453528955, + 3.4324892457042018, 3.4417941928048226, 3.4510740515635128, 3.4603290238249023, + 3.4695944917958350, 3.4788001927748020, 3.4879815975718680, 3.4971738031409019, + 3.5063070962374359, 3.5154166604934614, 3.5245026799003858, 3.5335998818485379, + 3.5426392659640071, 3.5516556438511886, 3.5606491902811768, 3.5696542746637245, + 3.5786025882144274, 3.5875285822032135, 3.5964663647113397, 3.6053481324623839, + 3.6142080737002402, 3.6230463485511746, 3.6318967259718442, 3.6406920594682268, + 3.6494661959833250, 3.6582526566654741, 3.6669847755001657, 3.6756961500510350, + 3.6843869274616097, 3.6930903069956198, 3.7017402474207994, 3.7103700224000571, + 3.7189797723132347, 3.7276023837381045, 3.7361724230822109, 3.7447228493908598, + 3.7532863204297375, 3.7617978476886553, 3.7702901600042669, 3.7787633869263368, + 3.7872498886065071, 3.7956852559847478, 3.8041019184887777, 3.8125000000000000, + 3.8209115711273665, 3.8292727871131094, 3.8376157861196840, 3.8459724266107265, + 3.8542792776341468, 3.8625682639598748, 3.8708395003538962, 3.8791245690071618, + 3.8873605782876637, 3.8955791750874478, 3.9037804693815712, 3.9119957742180653, + 3.9201627238228260, 3.9283126944020128, 3.9364768015796816, 3.9445930655930783, + 3.9526926641056979, 3.9607756993580185, 3.9688730295891301, 3.9769231786332004, + 3.9849570653270532, 3.9930053589840071, 3.9999694823054588, 3.9999694823054588}; +/* testvector in Q4.12 */ +static const uint32_t uv[252] = { + 0U, 262U, 525U, 787U, 1049U, 1311U, + 1574U, 1836U, 2098U, 2360U, 2623U, 2885U, + 3147U, 3410U, 3672U, 3934U, 4196U, 4459U, + 4721U, 4983U, 5246U, 5508U, 5770U, 6032U, + 6295U, 6557U, 6819U, 7081U, 7344U, 7606U, + 7868U, 8131U, 8393U, 8655U, 8917U, 9180U, + 9442U, 9704U, 9966U, 10229U, 10491U, 10753U, + 11016U, 11278U, 11540U, 11802U, 12065U, 12327U, + 12589U, 12851U, 13114U, 13376U, 13638U, 13901U, + 14163U, 14425U, 14687U, 14950U, 15212U, 15474U, + 15737U, 15999U, 16261U, 16523U, 16786U, 17048U, + 17310U, 17572U, 17835U, 18097U, 18359U, 18622U, + 18884U, 19146U, 19408U, 19671U, 19933U, 20195U, + 20457U, 20720U, 20982U, 21244U, 21507U, 21769U, + 22031U, 22293U, 22556U, 22818U, 23080U, 23342U, + 23605U, 23867U, 24129U, 24392U, 24654U, 24916U, + 25178U, 25441U, 25703U, 25965U, 26228U, 26490U, + 26752U, 27014U, 27277U, 27539U, 27801U, 28063U, + 28326U, 28588U, 28850U, 29113U, 29375U, 29637U, + 29899U, 30162U, 30424U, 30686U, 30948U, 31211U, + 31473U, 31735U, 31998U, 32260U, 32522U, 32784U, + 33047U, 33309U, 33571U, 33833U, 34096U, 34358U, + 34620U, 34883U, 35145U, 35407U, 35669U, 35932U, + 36194U, 36456U, 36719U, 36981U, 37243U, 37505U, + 37768U, 38030U, 38292U, 38554U, 38817U, 39079U, + 39341U, 39604U, 39866U, 40128U, 40390U, 40653U, + 40915U, 41177U, 41439U, 41702U, 41964U, 42226U, + 42489U, 42751U, 43013U, 43275U, 43538U, 43800U, + 44062U, 44324U, 44587U, 44849U, 45111U, 45374U, + 45636U, 45898U, 46160U, 46423U, 46685U, 46947U, + 47210U, 47472U, 47734U, 47996U, 48259U, 48521U, + 48783U, 49045U, 49308U, 49570U, 49832U, 50095U, + 50357U, 50619U, 50881U, 51144U, 51406U, 51668U, + 51930U, 52193U, 52455U, 52717U, 52980U, 53242U, + 53504U, 53766U, 54029U, 54291U, 54553U, 54816U, + 55078U, 55340U, 55602U, 55865U, 56127U, 56389U, + 56651U, 56914U, 57176U, 57438U, 57701U, 57963U, + 58225U, 58487U, 58750U, 59012U, 59274U, 59536U, + 59799U, 60061U, 60323U, 60586U, 60848U, 61110U, + 61372U, 61635U, 61897U, 62159U, 62421U, 62684U, + 62946U, 63208U, 63471U, 63733U, 63995U, 64257U, + 64520U, 64782U, 65044U, 65307U, UINT16_MAX, UINT16_MAX}; +static void test_math_arithmetic_sqrt_fixed(void **state) +{ + (void)state; + + uint32_t u[252]; + int i; + double y; + double diff; + + memcpy_s((void *)&u[0], sizeof(u), (void *)&uv[0], 252U * sizeof(uint32_t)); + for (i = 0; i < ARRAY_SIZE(sqrt_ref_table); i++) { + y = Q_CONVERT_QTOF(sofm_sqrt_int16(u[i]), 12); + diff = fabs(sqrt_ref_table[i] - y); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: reftbl = %.16f, sqrt = %.16f\n", __func__, + diff, (double)sqrt_ref_table[i], y); + assert_true(diff <= CMP_TOLERANCE); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_sqrt_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/auditory/CMakeLists.txt b/test/cmocka/src/math/auditory/CMakeLists.txt new file mode 100644 index 000000000000..fe200e6b15eb --- /dev/null +++ b/test/cmocka/src/math/auditory/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(auditory + auditory.c + ${PROJECT_SOURCE_DIR}/src/math/auditory/auditory.c + ${PROJECT_SOURCE_DIR}/src/math/auditory/mel_filterbank_16.c + ${PROJECT_SOURCE_DIR}/src/math/auditory/mel_filterbank_32.c + ${PROJECT_SOURCE_DIR}/src/math/log_e.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c + ${PROJECT_SOURCE_DIR}/src/math/decibels.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c +) diff --git a/test/cmocka/src/math/auditory/auditory.c b/test/cmocka/src/math/auditory/auditory.c new file mode 100644 index 000000000000..ff222e52fadd --- /dev/null +++ b/test/cmocka/src/math/auditory/auditory.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <cmocka.h> +#include <math.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/math/auditory.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/fft.h> +#include "ref_hz_to_mel.h" +#include "ref_mel_filterbank_16_test1.h" +#include "ref_mel_filterbank_32_test1.h" +#include "ref_mel_filterbank_16_test2.h" +#include "ref_mel_filterbank_32_test2.h" +#include "ref_mel_filterbank_16_test3.h" +#include "ref_mel_filterbank_32_test3.h" +#include "ref_mel_filterbank_16_test4.h" +#include "ref_mel_filterbank_32_test4.h" + +#define HZ_TO_MEL_MAX_ERROR_ABS 1.5 +#define HZ_TO_MEL_MAX_ERROR_RMS 0.5 +#define MEL_TO_HZ_MAX_ERROR_ABS 5.0 +#define MEL_TO_HZ_MAX_ERROR_RMS 1.5 + +#define MEL_FB16_MAX_ERROR_ABS 5.0 +#define MEL_FB16_MAX_ERROR_RMS 3.0 +#define MEL_FB32_MAX_ERROR_ABS 5.0 +#define MEL_FB32_MAX_ERROR_RMS 3.0 + +#undef DEBUGFILES /* Change this to #define to get output data files for debugging */ + +struct processing_module dummy; + +static void filterbank_16_test(const int16_t *fft_real, const int16_t *fft_imag, + const int16_t *ref_mel_log, + int num_fft_bins, int num_mel_bins, int norm_slaney, + enum psy_mel_log_scale mel_log_type, int shift) +{ + struct psy_mel_filterbank fb; + struct icomplex16 *fft_buf; + struct icomplex16 *fft_out; + float delta; + float sum_squares = 0; + float error_rms; + float delta_max = 0; + int32_t *power_spectra; + int16_t *mel_log; + int i; + const int half_fft = num_fft_bins / 2 + 1; + const int fft_size = num_fft_bins * sizeof(struct icomplex16); + int ret; + + fft_buf = malloc(fft_size); + if (!fft_buf) { + fprintf(stderr, "Failed to allocate fft_buf\n"); + exit(EXIT_FAILURE); + } + + fft_out = malloc(fft_size); + if (!fft_out) { + fprintf(stderr, "Failed to allocate fft_out\n"); + goto err_out_alloc; + } + + mel_log = malloc(num_mel_bins * sizeof(int16_t)); + if (!mel_log) { + fprintf(stderr, "Failed to allocate output vector\n"); + goto err_mel_alloc; + } + + fb.samplerate = 16000; + fb.start_freq = 100; + fb.end_freq = 7500; + fb.mel_bins = num_mel_bins; + fb.slaney_normalize = (norm_slaney > 0); + fb.mel_log_scale = mel_log_type; + fb.fft_bins = num_fft_bins; + fb.half_fft_bins = half_fft; + fb.scratch_data1 = (int16_t *)fft_buf; + fb.scratch_data2 = (int16_t *)fft_out; + fb.scratch_length1 = fft_size / sizeof(int16_t); + fb.scratch_length2 = fft_size / sizeof(int16_t); + ret = mod_psy_get_mel_filterbank(&dummy, &fb); + if (ret < 0) { + fprintf(stderr, "Failed Mel filterbank\n"); + goto err_get_filterbank; + } + + /* Copy input from test vectors */ + for (i = 0; i < half_fft; i++) { + fft_out[i].real = fft_real[i]; + fft_out[i].imag = fft_imag[i]; + } + + /* Run filterbank */ + power_spectra = (int32_t *)&fft_buf[0]; + psy_apply_mel_filterbank_16(&fb, fft_out, power_spectra, mel_log, shift); + + /* Check */ + for (i = 0; i < num_mel_bins; i++) { + delta = (float)ref_mel_log[i] - (float)mel_log[i]; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + } + + error_rms = sqrt(sum_squares / (float)num_mel_bins); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, MEL_FB16_MAX_ERROR_ABS, error_rms, MEL_FB16_MAX_ERROR_RMS); + +#ifdef DEBUGFILES + FILE *fh = fopen("mel_filterbank_16.txt", "w"); + + for (i = 0; i < num_mel_bins; i++) + fprintf(fh, "%d %d\n", ref_mel_log[i], mel_log[i]); + + fclose(fh); +#endif + + assert_true(error_rms < MEL_FB16_MAX_ERROR_RMS); + assert_true(delta_max < MEL_FB16_MAX_ERROR_ABS); + free(mel_log); + free(fft_buf); + free(fft_out); + mod_psy_free_mel_filterbank(&dummy, &fb); + return; + +err_get_filterbank: + free(mel_log); + +err_mel_alloc: + free(fft_buf); + +err_out_alloc: + free(fft_out); + exit(EXIT_FAILURE); +} + +static void filterbank_32_test(const int32_t *fft_real, const int32_t *fft_imag, + const int16_t *ref_mel_log, + int num_fft_bins, int num_mel_bins, int norm_slaney, + enum psy_mel_log_scale mel_log_type, int shift) +{ + struct psy_mel_filterbank fb; + struct icomplex32 *fft_buf; + struct icomplex32 *fft_out; + float delta; + float sum_squares = 0; + float error_rms; + float delta_max = 0; + int32_t *power_spectra; + int32_t *mel_log; + int16_t mel_log_16; + int i; + const int half_fft = num_fft_bins / 2 + 1; + const int fft_size = num_fft_bins * sizeof(struct icomplex32); + int ret; + + fft_buf = malloc(fft_size); + if (!fft_buf) { + fprintf(stderr, "Failed to allocate fft_buf\n"); + exit(EXIT_FAILURE); + } + + fft_out = malloc(fft_size); + if (!fft_out) { + fprintf(stderr, "Failed to allocate fft_out\n"); + goto err_out_alloc; + } + + mel_log = malloc(num_mel_bins * sizeof(int32_t)); + if (!mel_log) { + fprintf(stderr, "Failed to allocate output vector\n"); + goto err_mel_alloc; + } + + fb.samplerate = 16000; + fb.start_freq = 100; + fb.end_freq = 7500; + fb.mel_bins = num_mel_bins; + fb.slaney_normalize = (norm_slaney > 0); + fb.mel_log_scale = mel_log_type; + fb.fft_bins = num_fft_bins; + fb.half_fft_bins = half_fft; + fb.scratch_data1 = (int16_t *)fft_buf; + fb.scratch_data2 = (int16_t *)fft_out; + fb.scratch_length1 = fft_size / sizeof(int16_t); + fb.scratch_length2 = fft_size / sizeof(int16_t); + ret = mod_psy_get_mel_filterbank(&dummy, &fb); + if (ret < 0) { + fprintf(stderr, "Failed Mel filterbank\n"); + goto err_get_filterbank; + } + + /* Copy input from test vectors */ + for (i = 0; i < half_fft; i++) { + fft_out[i].real = fft_real[i]; + fft_out[i].imag = fft_imag[i]; + } + + /* Run filterbank */ + power_spectra = (int32_t *)&fft_buf[0]; + psy_apply_mel_filterbank_32(&fb, fft_out, power_spectra, mel_log, shift); + + /* Check: convert Q9.23 output to Q9.7 for comparison with reference */ + for (i = 0; i < num_mel_bins; i++) { + mel_log_16 = (int16_t)(mel_log[i] >> 16); + delta = (float)ref_mel_log[i] - (float)mel_log_16; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + } + + error_rms = sqrt(sum_squares / (float)num_mel_bins); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, MEL_FB32_MAX_ERROR_ABS, error_rms, MEL_FB32_MAX_ERROR_RMS); + +#ifdef DEBUGFILES + FILE *fh = fopen("mel_filterbank_32.txt", "w"); + + for (i = 0; i < num_mel_bins; i++) + fprintf(fh, "%d %d\n", ref_mel_log[i], (int16_t)(mel_log[i] >> 16)); + + fclose(fh); +#endif + + assert_true(error_rms < MEL_FB32_MAX_ERROR_RMS); + assert_true(delta_max < MEL_FB32_MAX_ERROR_ABS); + free(mel_log); + free(fft_buf); + free(fft_out); + mod_psy_free_mel_filterbank(&dummy, &fb); + return; + +err_get_filterbank: + free(mel_log); + +err_mel_alloc: + free(fft_buf); + +err_out_alloc: + free(fft_out); + exit(EXIT_FAILURE); +} + +static void test_hz_to_mel(void **state) +{ + float error_rms; + float delta_max = 0.0; + float delta; + float sum_squares = 0.0; + int16_t test_mel; + int i; + + (void)state; + + for (i = 0; i < HZ_TO_MEL_NPOINTS; i++) { + test_mel = psy_hz_to_mel(ref_hz[i]); + delta = (float)ref_mel[i] - (float)test_mel; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + } + + error_rms = sqrt(sum_squares / (float)HZ_TO_MEL_NPOINTS); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, HZ_TO_MEL_MAX_ERROR_ABS, error_rms, HZ_TO_MEL_MAX_ERROR_RMS); + + assert_true(error_rms < HZ_TO_MEL_MAX_ERROR_RMS); + assert_true(delta_max < HZ_TO_MEL_MAX_ERROR_ABS); +} + +static void test_mel_to_hz(void **state) +{ + float error_rms; + float delta_max = 0.0; + float delta; + float sum_squares = 0.0; + int16_t test_hz; + int i; + + (void)state; + + for (i = 0; i < HZ_TO_MEL_NPOINTS; i++) { + test_hz = psy_mel_to_hz(ref_mel[i]); + delta = (float)ref_revhz[i] - (float)test_hz; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + } + + error_rms = sqrt(sum_squares / (float)HZ_TO_MEL_NPOINTS); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, MEL_TO_HZ_MAX_ERROR_ABS, error_rms, MEL_TO_HZ_MAX_ERROR_RMS); + + assert_true(error_rms < MEL_TO_HZ_MAX_ERROR_RMS); + assert_true(delta_max < MEL_TO_HZ_MAX_ERROR_ABS); +} + +static void test_mel_filterbank_16_test1(void **state) +{ + (void)state; + + filterbank_16_test(mel_filterbank_16_test1_real, + mel_filterbank_16_test1_imag, + mel_filterbank_16_test1_mel_log, + MEL_FILTERBANK_16_TEST1_FFT_SIZE, + MEL_FILTERBANK_16_TEST1_NUM_MEL_BINS, + MEL_FILTERBANK_16_TEST1_NORM_SLANEY, + MEL_FILTERBANK_16_TEST1_MEL_LOG, + MEL_FILTERBANK_16_TEST1_SHIFT); +} + +static void test_mel_filterbank_32_test1(void **state) +{ + (void)state; + + filterbank_32_test(mel_filterbank_32_test1_real, + mel_filterbank_32_test1_imag, + mel_filterbank_32_test1_mel_log, + MEL_FILTERBANK_32_TEST1_FFT_SIZE, + MEL_FILTERBANK_32_TEST1_NUM_MEL_BINS, + MEL_FILTERBANK_32_TEST1_NORM_SLANEY, + MEL_FILTERBANK_32_TEST1_MEL_LOG, + MEL_FILTERBANK_32_TEST1_SHIFT); +} + +static void test_mel_filterbank_16_test2(void **state) +{ + (void)state; + + filterbank_16_test(mel_filterbank_16_test2_real, + mel_filterbank_16_test2_imag, + mel_filterbank_16_test2_mel_log, + MEL_FILTERBANK_16_TEST2_FFT_SIZE, + MEL_FILTERBANK_16_TEST2_NUM_MEL_BINS, + MEL_FILTERBANK_16_TEST2_NORM_SLANEY, + MEL_FILTERBANK_16_TEST2_MEL_LOG, + MEL_FILTERBANK_16_TEST2_SHIFT); +} + +static void test_mel_filterbank_32_test2(void **state) +{ + (void)state; + + filterbank_32_test(mel_filterbank_32_test2_real, + mel_filterbank_32_test2_imag, + mel_filterbank_32_test2_mel_log, + MEL_FILTERBANK_32_TEST2_FFT_SIZE, + MEL_FILTERBANK_32_TEST2_NUM_MEL_BINS, + MEL_FILTERBANK_32_TEST2_NORM_SLANEY, + MEL_FILTERBANK_32_TEST2_MEL_LOG, + MEL_FILTERBANK_32_TEST2_SHIFT); +} + +static void test_mel_filterbank_16_test3(void **state) +{ + (void)state; + + filterbank_16_test(mel_filterbank_16_test3_real, + mel_filterbank_16_test3_imag, + mel_filterbank_16_test3_mel_log, + MEL_FILTERBANK_16_TEST3_FFT_SIZE, + MEL_FILTERBANK_16_TEST3_NUM_MEL_BINS, + MEL_FILTERBANK_16_TEST3_NORM_SLANEY, + MEL_FILTERBANK_16_TEST3_MEL_LOG, + MEL_FILTERBANK_16_TEST3_SHIFT); +} + +static void test_mel_filterbank_32_test3(void **state) +{ + (void)state; + + filterbank_32_test(mel_filterbank_32_test3_real, + mel_filterbank_32_test3_imag, + mel_filterbank_32_test3_mel_log, + MEL_FILTERBANK_32_TEST3_FFT_SIZE, + MEL_FILTERBANK_32_TEST3_NUM_MEL_BINS, + MEL_FILTERBANK_32_TEST3_NORM_SLANEY, + MEL_FILTERBANK_32_TEST3_MEL_LOG, + MEL_FILTERBANK_32_TEST3_SHIFT); +} + +static void test_mel_filterbank_16_test4(void **state) +{ + (void)state; + + filterbank_16_test(mel_filterbank_16_test4_real, + mel_filterbank_16_test4_imag, + mel_filterbank_16_test4_mel_log, + MEL_FILTERBANK_16_TEST4_FFT_SIZE, + MEL_FILTERBANK_16_TEST4_NUM_MEL_BINS, + MEL_FILTERBANK_16_TEST4_NORM_SLANEY, + MEL_FILTERBANK_16_TEST4_MEL_LOG, + MEL_FILTERBANK_16_TEST4_SHIFT); +} + +static void test_mel_filterbank_32_test4(void **state) +{ + (void)state; + + filterbank_32_test(mel_filterbank_32_test4_real, + mel_filterbank_32_test4_imag, + mel_filterbank_32_test4_mel_log, + MEL_FILTERBANK_32_TEST4_FFT_SIZE, + MEL_FILTERBANK_32_TEST4_NUM_MEL_BINS, + MEL_FILTERBANK_32_TEST4_NORM_SLANEY, + MEL_FILTERBANK_32_TEST4_MEL_LOG, + MEL_FILTERBANK_32_TEST4_SHIFT); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_mel_filterbank_16_test1), + cmocka_unit_test(test_mel_filterbank_32_test1), + cmocka_unit_test(test_mel_filterbank_16_test2), + cmocka_unit_test(test_mel_filterbank_32_test2), + cmocka_unit_test(test_mel_filterbank_16_test3), + cmocka_unit_test(test_mel_filterbank_32_test3), + cmocka_unit_test(test_mel_filterbank_16_test4), + cmocka_unit_test(test_mel_filterbank_32_test4), + cmocka_unit_test(test_hz_to_mel), + cmocka_unit_test(test_mel_to_hz), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/auditory/mfcc_get_mel_filterbank.m b/test/cmocka/src/math/auditory/mfcc_get_mel_filterbank.m new file mode 100644 index 000000000000..b9d33b10b8a9 --- /dev/null +++ b/test/cmocka/src/math/auditory/mfcc_get_mel_filterbank.m @@ -0,0 +1,96 @@ +% state = mfcc_get_mel_filterbank(param, stream, state) +% +% Input +% param.sample_frequency +% param.high_freq +% param.low_frew +% param.num_mel_bins +% param.nowm - use 'slaney' or 'none' +% param.mel_log - use 'log', 'log10', 'db' +% state.fft_padded_size - e.g. 512 +% state.half_fft_size - e.g. 257 +% +% Output +% state.triangles - Mel filter bank coefficients + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function state = mfcc_get_mel_filterbank(param, state) + +plot_triangles = 0; +plot_matlab_triangles = 0; +fn = param.sample_frequency / 2; +state.fft_f = linspace(0, fn, state.half_fft_size); + +% Mel frequencies +if param.high_freq == 0 + high_freq = fn; +else + high_freq = param.high_freq; +end + +if param.low_freq < 0 || param.low_freq > fn || high_freq > fn || param.low_freq > high_freq + error('Illegal start/end frequencies'); +end + +ms = mfcc_hz_to_mel(param.low_freq); +me = mfcc_hz_to_mel(high_freq); + +fft_bin_width = param.sample_frequency / state.fft_padded_size; +mel_freq_delta = (me - ms) / (param.num_mel_bins + 1); +mel = mfcc_hz_to_mel((0:(state.fft_padded_size / 2)) * fft_bin_width); +for i = 0:param.num_mel_bins - 1 + left_mel = ms + i * mel_freq_delta; + center_mel = ms + (i + 1) * mel_freq_delta; + right_mel = ms + (i + 2) * mel_freq_delta; + up_slope = (mel - left_mel) / (center_mel - left_mel); + down_slope = (right_mel - mel) / (right_mel - center_mel); + bins = min(up_slope, down_slope); + bins(bins < 0) = 0; + if param.norm_slaney + left_hz = mfcc_mel_to_hz(left_mel); + right_hz = mfcc_mel_to_hz(right_mel); + s = 2 / (right_hz - left_hz); + else + s = 1; + end + state.triangles(:,i + 1) = s * bins; +end + +% Pytorch uses log, librosa uses dB, matlab uses log10 +switch param.mel_log + case 'MEL_LOG' + state.log_scale = 1; + case 'MEL_LOG10' + state.log_scale = 1/log(10); + case 'MEL_DB' + state.log_scale = 10/log(10); + otherwise + error('Invalid mel_log'); +end + +if plot_triangles + figure; + plot(state.triangles); + grid on; + xlabel('FFT bin'); + ylabel('Weight') + title('This version computed'); +end + +if plot_matlab_triangles && exist('OCTAVE_VERSION', 'builtin') == 0 + % Reference in Matlab + [fb,cf] = designAuditoryFilterBank(param.sample_frequency, ... + "FFTLength", state.fft_padded_size, "NumBands", param.num_mel_bins, ... + "FrequencyRange", [0 fn], "Normalization", 'bandwidth'); + figure; + plot(fb'); + grid on; + xlabel('FFT bin'); + ylabel('Weight') + title('Matlab computed'); +end + +end diff --git a/test/cmocka/src/math/auditory/mfcc_hz_to_mel.m b/test/cmocka/src/math/auditory/mfcc_hz_to_mel.m new file mode 100644 index 000000000000..585f18b7c47a --- /dev/null +++ b/test/cmocka/src/math/auditory/mfcc_hz_to_mel.m @@ -0,0 +1,14 @@ +% mel = mfcc_hz_to_mel(hz) +% +% Wikipedia https://en.wikipedia.org/wiki/Mel_scale + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function mel = mfcc_hz_to_mel(hz) + +% Magic value is 2595/log(10) +mel = 1126.9941805389 * log(1 + hz / 700); + +end diff --git a/test/cmocka/src/math/auditory/mfcc_mel_to_hz.m b/test/cmocka/src/math/auditory/mfcc_mel_to_hz.m new file mode 100644 index 000000000000..d60118d981d1 --- /dev/null +++ b/test/cmocka/src/math/auditory/mfcc_mel_to_hz.m @@ -0,0 +1,13 @@ +% hz = mfcc_mel_to_hz(mel) +% +% Wikipedia https://en.wikipedia.org/wiki/Mel_scale + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function hz = mfcc_mel_to_hz(mel) + +hz = 700 * (exp(mel / 1126.9941805389) - 1); + +end diff --git a/test/cmocka/src/math/auditory/mfcc_power_to_mel_log.m b/test/cmocka/src/math/auditory/mfcc_power_to_mel_log.m new file mode 100644 index 000000000000..593629b906b6 --- /dev/null +++ b/test/cmocka/src/math/auditory/mfcc_power_to_mel_log.m @@ -0,0 +1,34 @@ +% mel_log = mfcc_power_to_mel_log(state, param, s_half) +% +% Inputs +% state.triangles - the Mel band triangles to integrate power +% state.log_scale - coefficient to output desired log scale +% param.pmin - min linear power to avoid log() of zero +% param.top_db - limit lowest mel log value distance from peak +% s_half - first half (N/2 + 1) of complex FFT data +% shift - apply 2^(2 * shift) gain to Mel spectra +% +% Output +% mel_log - logarithmic Mel band spectra + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function mel_log = mfcc_power_to_mel_log(state, param, s_half, shift) + +p_lin = s_half .* conj(s_half); +mel_log = zeros(1, param.num_mel_bins); +for i = 1:param.num_mel_bins + p = sum(p_lin .* state.triangles(:, i)); + p = max(p, param.pmin); + % Compensate linear spectra shift to logarithmic Mel power spectra + mel_log(i) = (log(p) - 2 * shift * log(2)) * state.log_scale; +end + +if param.top_db > 0 + peak_db = max(mel_log); + mel_log = max(mel_log, peak_db - param.top_db); +end + +end diff --git a/test/cmocka/src/math/auditory/plot_filterbank_test.m b/test/cmocka/src/math/auditory/plot_filterbank_test.m new file mode 100644 index 000000000000..115d0b01b448 --- /dev/null +++ b/test/cmocka/src/math/auditory/plot_filterbank_test.m @@ -0,0 +1,33 @@ +% plot_filterbank_test - A helper for debugging unit test auditory + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +% Load unit test debug data +load ../../../../../build_ut/test/cmocka/src/math/auditory/mel_filterbank_16.txt +load ../../../../../build_ut/test/cmocka/src/math/auditory/mel_filterbank_32.txt + +scale = 1/2^7; % Q8.7 +ref16 = mel_filterbank_16(:,1) * scale; +tst16 = mel_filterbank_16(:,2) * scale; +ref32 = mel_filterbank_32(:,1) * scale; +tst32 = mel_filterbank_32(:,2) * scale; + +figure(1) +subplot(2, 1, 1); +plot(ref16); hold on; plot(tst16); hold off; +grid on; +title('16 bit'); +subplot(2, 1, 2); +plot(ref16 - tst16); +grid on; + +figure(2) +subplot(2, 1, 1); +plot(ref32); hold on; plot(tst32); hold off; +grid on; +title('32 bit'); +subplot(2, 1, 2); +plot(ref32 - tst32); +grid on; diff --git a/test/cmocka/src/math/auditory/ref_auditory.m b/test/cmocka/src/math/auditory/ref_auditory.m new file mode 100644 index 000000000000..39ea0f6a4d32 --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_auditory.m @@ -0,0 +1,158 @@ +% ref_auditory - Generate C header files for auditory library unit tests + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function ref_auditory() + + path(path(), '../../../m'); + opt.describe = export_get_git_describe(); + + %% Test 0, Mel <-> Hz conversions + get_ref_hz_to_mel(opt, 'ref_hz', 'ref_mel', 'ref_revhz', 'ref_hz_to_mel.h'); + + %% Test 1, largest input, Slaney off, Mel dB + opt.test_n = 1; + opt.input = 'ones'; + opt.num_mel_bins = 23; + opt.fft_size = 512; + opt.norm_slaney = 0; + opt.mel_log = 'MEL_DB'; + opt.shift = 0; + opt.bits = 16; + get_ref_mel_filterbank(opt); + opt.bits = 32; + get_ref_mel_filterbank(opt); + + %% Test 2, random input, Slaney norm, Mel log + opt.test_n = 2; + opt.input = 'random'; + opt.num_mel_bins = 23; + opt.fft_size = 512; + opt.norm_slaney = 1; + opt.mel_log = 'MEL_LOG'; + opt.shift = 1; + opt.bits = 16; + get_ref_mel_filterbank(opt); + opt.bits = 32; + get_ref_mel_filterbank(opt); + + %% Test 3, random input, Slaney off, Mel log10, 128 size, 10 bands + opt.test_n = 3; + opt.input = 'random'; + opt.num_mel_bins = 10; + opt.fft_size = 128; + opt.norm_slaney = 0; + opt.mel_log = 'MEL_LOG10'; + opt.shift = 2; + opt.bits = 16; + get_ref_mel_filterbank(opt); + opt.bits = 32; + get_ref_mel_filterbank(opt); + + %% Test 4, random input, Slaney norm, Mel dB,1024 size, 23 bands + opt.test_n = 4; + opt.input = 'random'; + opt.num_mel_bins = 23; + opt.fft_size = 1024; + opt.norm_slaney = 1; + opt.mel_log = 'MEL_DB'; + opt.shift = 3; + opt.bits = 16; + get_ref_mel_filterbank(opt); + opt.bits = 32; + get_ref_mel_filterbank(opt); + +end + +function get_ref_mel_filterbank(opt) + + header_fn = sprintf('ref_mel_filterbank_%d_test%d.h', opt.bits, opt.test_n); + + %% Initialize filterbank + param.sample_frequency = 16e3; + param.high_freq = 7.5e3; + param.low_freq = 100; + param.num_mel_bins = opt.num_mel_bins; + param.pmin = 1e-9; + param.norm_slaney = opt.norm_slaney; + param.mel_log = opt.mel_log; + param.top_db = 100; + state.fft_padded_size = opt.fft_size; + state.half_fft_size = state.fft_padded_size / 2 + 1; + state = mfcc_get_mel_filterbank(param, state); + + %% Data to process + switch lower(opt.input) + case 'random' + real = 2 * rand(state.half_fft_size, 1) - 1; + imag = 2 * rand(state.half_fft_size, 1) - 1; + case 'ones' + real = ones(state.half_fft_size, 1); + imag = ones(state.half_fft_size, 1); + otherwise + error('Illegal input'); + end + + switch opt.bits + case 16 + [q_real, f_real] = export_quant_qxy(real, 16, 15, true); % Q1.15 + [q_imag, f_imag] = export_quant_qxy(imag, 16, 15, true); % Q1.15 + case 32 + [q_real, f_real] = export_quant_qxy(real, 32, 31, true); % Q1.31 + [q_imag, f_imag] = export_quant_qxy(imag, 32, 31, true); % Q1.31 + otherwise + error('Illegal bits value'); + end + + s_half = complex(f_real, f_imag); + mel_log = mfcc_power_to_mel_log(state, param, s_half, opt.shift); + q_mel_log = export_quant_qxy(mel_log, 16, 7); %Q8.7 + + define_prefix = sprintf('MEL_FILTERBANK_%d_TEST%d_', opt.bits, opt.test_n); + vector_prefix = sprintf('mel_filterbank_%d_test%d_', opt.bits, opt.test_n); + + fh = export_headerfile_open(header_fn); + comment = sprintf('Created %s with script ref_matrix.m %s', ... + datestr(now, 0), opt.describe); + export_comment(fh, comment); + export_ndefine(fh, [define_prefix 'FFT_SIZE'], opt.fft_size); + export_ndefine(fh, [define_prefix 'NUM_MEL_BINS'], opt.num_mel_bins); + export_ndefine(fh, [define_prefix 'NORM_SLANEY'], opt.norm_slaney); + export_sdefine(fh, [define_prefix 'MEL_LOG'], opt.mel_log); + export_ndefine(fh, [define_prefix 'SHIFT'], opt.shift); + + export_vector(fh, opt.bits, [vector_prefix 'real'], q_real); + export_vector(fh, opt.bits, [vector_prefix 'imag'], q_imag); + export_vector(fh, 16, [vector_prefix 'mel_log'], q_mel_log); + fclose(fh); + fprintf(1, 'Exported %s.\n', header_fn); + +end + +function get_ref_hz_to_mel(opt, hz_name, mel_name, rev_hz_name, header_fn) + + n = 100; + hz_min = 0; + hz_max = 32767; + + hz = linspace(hz_min, hz_max, n); + mel = mfcc_hz_to_mel(hz); + [qhz, fqhz] = export_quant_qxy(hz, 16, 0); % Q15.0 + [qmel, fqmel] = export_quant_qxy(mel, 16, 2); % Q14.2 + revhz = mfcc_mel_to_hz(fqmel); + qrevhz = export_quant_qxy(hz, 16, 0); % Q16.0 + + fh = export_headerfile_open(header_fn); + comment = sprintf('Created %s with script ref_matrix.m %s', ... + datestr(now, 0), opt.describe); + export_comment(fh, comment); + export_ndefine(fh, 'HZ_TO_MEL_NPOINTS', n); + export_vector(fh, 16, hz_name, qhz); + export_vector(fh, 16, mel_name, qmel); + export_vector(fh, 16, rev_hz_name, qrevhz); + fclose(fh); + fprintf(1, 'Exported %s.\n', header_fn); + +end diff --git a/test/cmocka/src/math/auditory/ref_hz_to_mel.h b/test/cmocka/src/math/auditory/ref_hz_to_mel.h new file mode 100644 index 000000000000..0db44e035e48 --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_hz_to_mel.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 01-Sep-2022 13:41:14 with script ref_matrix.m v1.9-rc1-1702-gba40860ea */ + +#define HZ_TO_MEL_NPOINTS 100 + +static const int16_t ref_hz[100] = { + 0, 331, 662, 993, 1324, 1655, 1986, 2317, 2648, 2979, + 3310, 3641, 3972, 4303, 4634, 4965, 5296, 5627, 5958, 6289, + 6620, 6951, 7282, 7613, 7944, 8274, 8605, 8936, 9267, 9598, + 9929, 10260, 10591, 10922, 11253, 11584, 11915, 12246, 12577, 12908, + 13239, 13570, 13901, 14232, 14563, 14894, 15225, 15556, 15887, 16218, + 16549, 16880, 17211, 17542, 17873, 18204, 18535, 18866, 19197, 19528, + 19859, 20190, 20521, 20852, 21183, 21514, 21845, 22176, 22507, 22838, + 23169, 23500, 23831, 24162, 24493, 24823, 25154, 25485, 25816, 26147, + 26478, 26809, 27140, 27471, 27802, 28133, 28464, 28795, 29126, 29457, + 29788, 30119, 30450, 30781, 31112, 31443, 31774, 32105, 32436, 32767, +}; + +static const int16_t ref_mel[100] = { + 0, 1745, 3001, 3981, 4786, 5469, 6062, 6586, 7055, 7480, + 7868, 8226, 8557, 8866, 9154, 9426, 9682, 9924, 10154, 10373, + 10581, 10781, 10972, 11155, 11331, 11500, 11663, 11821, 11973, 12120, + 12263, 12401, 12535, 12666, 12792, 12915, 13035, 13152, 13266, 13377, + 13485, 13591, 13694, 13795, 13894, 13991, 14085, 14178, 14269, 14358, + 14445, 14531, 14615, 14698, 14779, 14858, 14937, 15014, 15089, 15164, + 15237, 15309, 15380, 15449, 15518, 15586, 15652, 15718, 15783, 15847, + 15910, 15972, 16033, 16093, 16153, 16212, 16270, 16327, 16384, 16440, + 16495, 16550, 16604, 16657, 16710, 16762, 16813, 16864, 16914, 16964, + 17013, 17062, 17110, 17158, 17205, 17251, 17298, 17343, 17389, 17433, +}; + +static const int16_t ref_revhz[100] = { + 0, 331, 662, 993, 1324, 1655, 1986, 2317, 2648, 2979, + 3310, 3641, 3972, 4303, 4634, 4965, 5296, 5627, 5958, 6289, + 6620, 6951, 7282, 7613, 7944, 8274, 8605, 8936, 9267, 9598, + 9929, 10260, 10591, 10922, 11253, 11584, 11915, 12246, 12577, 12908, + 13239, 13570, 13901, 14232, 14563, 14894, 15225, 15556, 15887, 16218, + 16549, 16880, 17211, 17542, 17873, 18204, 18535, 18866, 19197, 19528, + 19859, 20190, 20521, 20852, 21183, 21514, 21845, 22176, 22507, 22838, + 23169, 23500, 23831, 24162, 24493, 24823, 25154, 25485, 25816, 26147, + 26478, 26809, 27140, 27471, 27802, 28133, 28464, 28795, 29126, 29457, + 29788, 30119, 30450, 30781, 31112, 31443, 31774, 32105, 32436, 32767, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test1.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test1.h new file mode 100644 index 000000000000..2104d1cf1f0e --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test1.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_16_TEST1_FFT_SIZE 512 +#define MEL_FILTERBANK_16_TEST1_NUM_MEL_BINS 23 +#define MEL_FILTERBANK_16_TEST1_NORM_SLANEY 0 +#define MEL_FILTERBANK_16_TEST1_MEL_LOG MEL_DB +#define MEL_FILTERBANK_16_TEST1_SHIFT 0 + +static const int16_t mel_filterbank_16_test1_real[257] = { + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, +}; + +static const int16_t mel_filterbank_16_test1_imag[257] = { + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, + 32767, 32767, 32767, 32767, 32767, 32767, 32767, +}; + +static const int16_t mel_filterbank_16_test1_mel_log[23] = { + 947, 994, 1057, 1103, 1164, 1211, 1272, 1321, 1377, 1430, + 1486, 1536, 1593, 1646, 1700, 1753, 1808, 1861, 1915, 1969, + 2023, 2077, 2131, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test2.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test2.h new file mode 100644 index 000000000000..8835611decd0 --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test2.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_16_TEST2_FFT_SIZE 512 +#define MEL_FILTERBANK_16_TEST2_NUM_MEL_BINS 23 +#define MEL_FILTERBANK_16_TEST2_NORM_SLANEY 1 +#define MEL_FILTERBANK_16_TEST2_MEL_LOG MEL_LOG +#define MEL_FILTERBANK_16_TEST2_SHIFT 1 + +static const int16_t mel_filterbank_16_test2_real[257] = { + -7809, 8820, -8963, -6054, -8605, -2071, 224, 26905, -19239, -10577, + 4858, -856, -15583, 5216, 24794, -28774, -3875, -27246, 4144, 2576, + 17567, -17492, 5725, -2689, 23657, 10541, -9576, -10015, -16140, 29657, + -13225, -22387, -9090, 15835, 13494, 13166, -32360, -8235, 26312, -11905, + 6362, -13252, -24575, -7317, 20820, 31534, 23723, -27275, -10636, -17293, + -11940, 31749, 3162, 16335, 22404, -21831, 26417, -25879, 16062, 15032, + 14252, -24023, -3553, 576, 1998, 23574, 11647, 20043, 2048, 29878, + -28398, 2721, -14309, -1252, 12115, -19120, 7088, -11392, 24959, -24026, + -26057, 30089, -22747, -22771, -22574, -26898, -2987, 11069, 21712, 19021, + 13940, -1796, 13670, 30019, 379, -12776, 18993, -17276, -17413, -2313, + 7824, 7558, -24732, -24655, -14126, 15449, -5813, 21560, 28516, -6615, + -29346, 4665, 16231, -11781, -463, -18242, 28788, -1160, 2621, -18281, + -26480, -28825, 20939, 17792, -19943, 25894, 12078, 10279, 32138, -30560, + -4964, -656, 5473, -27311, 10496, -29340, 3724, 13895, -792, 7707, + -18758, 9546, -7822, -25971, -8027, -15541, -16955, 8056, 1503, -5686, + -18495, 23498, 23659, -14160, 7562, 18317, 29809, 27499, -7549, -22109, + 19448, -25309, -22359, -9448, 22791, 5425, 5648, 27908, 4920, -32114, + 20275, 7131, -1316, -15176, -15853, -1245, -17869, -29583, -21677, -15830, + -19798, 6927, 21214, 20356, 19807, 13639, 23552, 18421, -19412, 32332, + -26632, 9871, -18666, -16786, -10506, -19801, 448, 29541, -6907, 5535, + 6982, 14067, -6453, 23507, 27557, 16439, -14051, 19452, -23412, 298, + 7254, 13356, -7645, 14987, 25381, -29108, -23710, 23794, -5128, -5812, + 30090, 16400, 31523, -17464, -26462, -7564, 18, 4604, 31237, -468, + -6496, 32440, -15663, 10835, 30426, 11217, -13161, 2040, -32672, 25152, + -6266, -13028, 29529, -2579, -13917, -27222, 5386, -22736, -27978, 5280, + -13958, -9049, 14734, 23482, -9967, 30261, 29725, +}; + +static const int16_t mel_filterbank_16_test2_imag[257] = { + -19265, 17580, 7571, 27455, 6720, 13247, 15969, -7530, -16285, -30359, + -1827, 9507, -14485, 1171, -16668, -13271, 9861, 25650, 23665, -19011, + -6613, 25420, -15956, 30592, 7809, -21932, 21378, 10204, 3044, -16297, + -30136, -17474, -9102, 8746, 31857, -19192, 16848, 25318, -1820, -22353, + 20377, -1540, -25147, 24623, 8860, -26393, 26767, -30473, -30163, 32019, + 12202, -8081, 283, 17268, -29565, 14806, 13194, -2694, 5393, -10545, + -21586, -6606, 27511, -17954, -9109, -11498, -27290, 830, 21815, 26517, + 14654, -7668, -13237, 12564, 24934, 27823, -27443, -1136, -24362, -16193, + 25163, -19905, -24815, 2864, -12149, -7731, 19106, 22228, 11812, -5445, + 9364, -18738, 7685, 11481, 6621, -10072, -8887, -21530, 19357, -481, + -9527, 18026, -17249, 22599, 20744, 22690, -8507, -7653, 23680, -2365, + 4623, 12800, 30207, 3035, 8951, 4646, 27991, 23840, -21637, -21057, + -16810, 16501, -19718, 31650, 13739, -21271, 23481, 26831, 30256, 4627, + 4121, -21190, 896, 3177, -21936, -400, 2301, -19739, 8072, -31043, + -11876, 2163, -11353, 6697, -9048, -23926, 27120, 9212, 10405, 11490, + 16027, 22425, 1092, -22815, -7821, 21038, -21537, -11143, 30571, 20073, + -18207, 32753, -28591, -4884, -6269, -6534, -25433, -4960, 7441, 31986, + -18357, -9563, -15320, -13664, -20422, -31270, -3316, -16801, 24165, 1875, + 27141, 31059, 5598, -24971, 27953, 6132, 25141, -4950, 7029, -28130, + 27838, 9311, -25920, 13122, -6829, -27204, -18712, -16463, -17914, 13304, + 16656, 3099, 3505, 8557, 31815, 8800, 6583, 26816, 4642, -10786, + 29959, -3937, 6655, 14435, 11716, -18825, -27419, -14780, 24086, 3890, + -2318, -4568, 17956, 10087, 10337, -22215, -4432, 333, -8170, -1286, + -10327, 18163, -7606, 13865, -1250, 15020, 28676, 1131, 26416, -18469, + 24459, -27349, -2267, -31331, 20203, -21023, -21929, -20866, 12546, -18759, + -13231, 17586, 75, 26835, -28977, -4145, 4735, +}; + +static const int16_t mel_filterbank_16_test2_mel_log[23] = { + -757, -693, -773, -673, -694, -689, -690, -668, -673, -619, + -660, -698, -684, -657, -694, -717, -686, -654, -716, -670, + -667, -677, -692, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test3.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test3.h new file mode 100644 index 000000000000..fa5def0bf38c --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test3.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_16_TEST3_FFT_SIZE 128 +#define MEL_FILTERBANK_16_TEST3_NUM_MEL_BINS 10 +#define MEL_FILTERBANK_16_TEST3_NORM_SLANEY 0 +#define MEL_FILTERBANK_16_TEST3_MEL_LOG MEL_LOG10 +#define MEL_FILTERBANK_16_TEST3_SHIFT 2 + +static const int16_t mel_filterbank_16_test3_real[65] = { + 27076, 11961, 29277, -26274, 723, -25551, 2966, 12372, -23107, 18190, + -6616, 26103, -12646, -28767, -18385, -27339, 29517, -31695, -25253, -31955, + -18597, -32019, 9336, 1114, -16676, -20071, -26813, -8622, -32257, 6731, + -1386, -12575, 16020, 22240, -15569, 933, -3488, -10406, 22226, 31621, + 8288, -20888, -24706, 5241, -11237, -15192, 3292, -20938, 11698, -29118, + -30536, -13991, -27696, 26252, 22715, -6836, -21678, -4558, -5491, 14992, + -6129, 29610, 27000, 29584, -10092, +}; + +static const int16_t mel_filterbank_16_test3_imag[65] = { + -13747, 25343, -19003, -24191, 1345, 26572, -6388, -18628, -27608, 28381, + 6742, -8029, 10809, 19149, -10912, 12626, -19411, 30062, 13883, -21830, + -3750, 8716, 28178, 1922, 8289, 11850, 27735, -22752, -6179, -12290, + 12707, 25604, -611, 20042, -11374, 3269, -7289, 26007, 11542, 21522, + -25553, -14469, 17540, -18609, -30536, -4158, 28630, -15592, 4571, -9204, + -31009, 27, 21431, -15795, -29761, -16615, 10534, -11180, 10453, -31916, + 14291, -7136, -30572, -6159, 14176, +}; + +static const int16_t mel_filterbank_16_test3_mel_log[10] = { + -123, -141, -130, -111, -99, -62, -79, -78, -62, -38, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test4.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test4.h new file mode 100644 index 000000000000..fcb29d239422 --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_16_test4.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_16_TEST4_FFT_SIZE 1024 +#define MEL_FILTERBANK_16_TEST4_NUM_MEL_BINS 23 +#define MEL_FILTERBANK_16_TEST4_NORM_SLANEY 1 +#define MEL_FILTERBANK_16_TEST4_MEL_LOG MEL_DB +#define MEL_FILTERBANK_16_TEST4_SHIFT 3 + +static const int16_t mel_filterbank_16_test4_real[513] = { + -25313, 30464, -4423, -27226, 14200, 445, -11266, 16615, 22020, -16140, + 2256, -4249, -22433, 6585, 28669, -25706, 26213, 3307, -4761, -22782, + -16545, -3449, 2148, -9526, 17899, 25014, 15341, -6132, 6827, 9247, + -24414, -250, -12421, 5149, 29072, -4788, -30597, 28143, 27852, -9286, + -15729, 18800, 759, 4098, 12111, -26713, 24417, 29028, -26438, 22668, + 26830, -32025, 1552, 9853, -7527, 9785, 17226, 4960, 8645, -14536, + 22272, -4795, 8626, 21854, -15061, -6501, 3556, -3679, -26845, 16016, + -30631, -4604, -30326, 31182, 1464, 26846, -7651, 25195, -16055, 26807, + 25858, -6651, 8193, 4430, 25855, -18732, -32515, 24942, -17359, -16721, + 9235, -12811, 21340, 25145, 29188, -7157, 19747, -22471, 8203, 13041, + -27140, 2043, 25465, -15488, -17381, 22260, -292, -22783, -17644, 10352, + 4125, -13643, 8015, 14150, -14370, -5749, -9030, 18441, -23889, 26350, + -13786, -29, 18585, 11604, -22950, 12886, -24313, 29226, 25324, 983, + 11758, 31247, -24546, 16531, 21434, 18444, -20258, -4677, -31821, -11450, + -23940, -3243, 4737, 19138, -5260, 2132, 27899, 26154, 2938, 26288, + -29371, 20225, -10820, -17781, 21129, -9946, -21924, -30924, 29843, 11816, + 23630, 28776, 11809, 27356, -15945, 25272, 27528, -13103, -27958, 17524, + -27201, 14992, -3415, 9912, -21660, 2061, 8769, -31844, -1942, 25318, + -25295, -3766, 10456, -13450, 29515, 12733, -19215, 3589, 24856, 3792, + 16537, 25880, 22403, -24192, -20372, -22699, -30874, -32173, 6321, 7147, + 27455, 15308, -13032, -290, -15849, 15260, -25116, 16125, 20302, 16072, + -10673, 5526, -2035, -27049, 21543, 12186, -15249, 30768, -20724, -13111, + -5821, -17269, -19985, 13460, -20936, 1464, -13358, -2439, 27868, -18619, + -32702, 26647, 11799, 980, 1446, -26023, 32564, -9243, 8208, -6988, + -32266, 2968, 597, -16595, -29793, 22396, -29606, -12038, 18574, 30959, + 5667, 18222, 14922, 9895, 10788, 28756, 2299, -6656, 11171, -3897, + -24060, -3984, 3122, -6872, -6667, 16472, 1465, -627, -26956, -16328, + -3437, 9041, 13726, 32284, 28324, -26724, 29723, -22099, 30832, 6357, + -17024, -28161, -13104, 20548, -27741, -9537, -24117, -22402, -28695, 13228, + -27100, 7654, -21380, 9922, -85, -14122, 21664, 20864, 28716, -32747, + 9201, -32286, -25794, -25769, -8709, -17065, -10083, -16409, -7401, -5175, + 9180, 18845, -15074, 22543, 15759, 21371, -20828, -28480, 7232, 13209, + -25453, -26488, 6412, 20462, 20616, -26907, 15157, 26467, -3131, -28135, + -16956, 15196, -30114, -4946, 2636, 29742, -19077, -25144, 9583, -25663, + 31686, -16493, 6970, 20755, 21630, -718, 17087, 27205, 26278, -18728, + 3084, 18659, -20025, 16180, -1602, 5456, -15693, -27209, -13230, 27337, + -1932, -15108, 17234, 17837, -31372, 24903, 19541, -11524, 11078, -13350, + 28177, -14289, -21700, 16067, -1499, 10056, 30578, -12253, -27758, 19098, + -8822, 5577, -20753, -27727, -22698, 21422, -13044, -7610, 9879, 20799, + 17450, -8246, -20325, 9601, -32532, -14229, 9083, 6034, -11450, 32044, + -24692, 15458, -22504, -4283, 21774, -9181, -27772, 3731, -14816, -24114, + 13085, -924, -20794, -26135, -19557, -23937, -11548, 29527, 2106, -16536, + -4111, 11081, 3126, 7147, 23798, -7819, 16316, -22499, -28959, -10505, + 20786, -8025, 30973, 6902, -10601, 28048, 26111, 22984, -15939, -14058, + 18347, 13199, -491, 30649, -1562, 32434, -617, 226, 17614, -7334, + -3063, -24061, 16941, 4275, 9741, 19534, -18321, 23455, 26524, -13630, + 14803, -10522, -14898, -21609, 10749, 2350, 21569, -15246, -21223, -4510, + -1595, 18692, -24206, -29402, 8356, -30862, -23842, 12750, 1028, 2791, + 20217, 19247, 122, -14639, -24926, 25336, 30821, 29001, 9052, -26831, + -27872, -20811, -30691, 14741, -23320, 8908, 18995, 4342, -8034, 21075, + -12787, -11838, 18676, 245, -15663, 15236, -22089, 27596, -18204, -27289, + -27938, 17665, 20819, +}; + +static const int16_t mel_filterbank_16_test4_imag[513] = { + 15757, 16925, 30225, -2200, 18809, -5075, 29080, -32682, 31540, 4600, + -10062, 3769, -13121, -22343, 10830, 12072, 19163, -9921, -16379, -10158, + -11231, 28016, 16782, -13878, 6959, 17435, 22685, 26344, 6272, -28276, + -18478, 24210, -5622, 10565, 18578, -16523, 3567, -17722, -32315, 17474, + -31337, -7006, -16218, -19384, 10635, 27181, -32316, 16150, 19639, 26726, + 31102, -24913, 1243, 21101, 8980, 29747, 29290, 30579, -28355, -4094, + -11741, -23983, -23948, 20051, 1623, 29115, 32004, -5905, -8442, -17901, + -3537, -15321, -2681, -4397, -15753, -24005, -5293, 450, -11513, 12104, + -3729, -4216, 19204, 20680, 16522, 18957, 83, 3616, 8569, -26346, + -16667, 7584, -12782, 17496, -15255, -30179, -13333, 3694, 30741, 12394, + 14279, 3869, 2186, 24623, -7006, -2748, -19120, 16861, 3060, -9346, + 13173, -25610, -32335, 6377, 10432, 5243, 26867, 8913, 1675, -15753, + -29414, 15201, -22001, -14392, -15766, 3086, 2705, 18882, 24222, 18844, + 30764, -20941, 28220, -29809, -16997, -32188, 11246, 26530, 4746, -22580, + 155, 4439, -20429, -11521, 14158, 3469, -23443, -7840, -6778, 5029, + -31497, 5084, 28324, -25764, 15214, 30836, 7136, 14396, -12927, -2686, + -29620, -7514, -9063, -13921, 20756, -3242, 20095, 19017, -14224, -28291, + -29168, 9013, -4962, 26577, -5418, -22672, 2621, 28645, 10548, -6904, + -15795, 22801, 29167, -8061, -28359, -20868, 4964, -20586, -13668, -2512, + -10028, -11917, -2627, -17308, -30949, 10384, -22361, 19835, -5991, -11312, + 16123, 16145, -21368, -25065, -21362, 8350, 22406, 661, -21905, 14045, + 26676, -18446, 24311, -18885, 22064, 23547, 1532, -1484, 25551, -28503, + 620, 7917, 15307, -17695, -31335, -23659, 17662, 30787, -7419, 32337, + -11377, -23779, -7553, 4105, 8771, 2727, -12125, -22326, -22766, -23793, + 13750, -2303, -25345, 13165, -20972, 19901, 915, 3174, -19147, 18651, + 1736, 4655, -5109, 14494, -27975, 6217, 23723, -3355, 9999, -12880, + 7041, -14490, 19632, 19410, 29759, -3648, -2826, 6542, 22454, -30723, + -20495, 29071, 29355, -3081, 20371, 28107, 11319, -8367, -6180, -4009, + 11708, -2289, 29705, -9523, -10550, 25943, 2978, 16337, -24584, -3065, + -27869, 10705, 13347, 27456, 10490, 12459, 23182, -2104, -2721, 20061, + 21284, -20288, -31085, -29045, -23401, -21534, 8247, -30834, -1813, 11694, + -25245, -17297, -13823, -21446, -11554, 19734, -13131, 18063, 3458, 3584, + 15116, 17932, 26270, -23713, 19273, -20355, -30869, -24420, -24003, -24359, + 28525, -14862, 29011, 9054, 24414, -8711, -17288, -20492, 2992, -16049, + -12726, -31749, 5734, 30314, 22928, -32248, 8783, -9221, -25293, 2675, + -5477, 1121, 25305, -22977, -4281, -28899, -7797, 14573, -26534, 10957, + -13343, 6459, -22816, -4170, -31937, -17759, -15487, 746, -18672, -10085, + 16241, -5661, -29114, -7207, -1672, 21320, -12868, 21089, 4304, -29204, + -15728, 5839, -1328, -19749, -17104, 18363, 7688, -23322, 14164, -6455, + -2465, 13584, -6474, -31825, -27876, 5968, -3539, 27959, -26549, -8165, + 3015, -25449, 26507, 8734, 26569, 8556, -31836, -12027, -25436, 8484, + -28789, 11403, -1479, -12744, 1070, 13568, 20553, -12071, -12367, -10160, + 10899, 23663, 17156, 24631, 24329, -21444, 22952, 30120, 17708, 24577, + -28350, 9620, -11528, 9198, 24887, -8281, 17481, -21752, 1293, 8353, + 14019, -12688, -15487, 27263, 7539, -26662, 8369, -20183, 18151, 23888, + -10906, -23894, 17398, -11887, -16228, -19656, -28245, 3402, -6304, 16392, + -840, -7551, -28744, -18764, 2875, -5856, 26278, -29079, -3702, 2478, + -23982, 2684, 23420, -19791, -22570, -28746, 10556, -31549, -13690, 31053, + 17343, -16798, 11935, -23734, 8507, 23397, 26201, -9937, -897, 11765, + 13377, -2564, -8895, -14401, -27774, -3629, -21908, -6636, 27563, 743, + 27141, -26743, 32312, -26448, -12246, 18702, 6711, -2234, -13230, -24040, + -13434, -21848, -11986, +}; + +static const int16_t mel_filterbank_16_test4_mel_log[23] = { + -4211, -4205, -4222, -4146, -3992, -3883, -4028, -4119, -4154, -4111, + -4211, -4125, -4018, -4023, -4069, -4073, -4074, -4158, -4052, -4025, + -4049, -4120, -4106, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test1.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test1.h new file mode 100644 index 000000000000..bf72abe058de --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test1.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_32_TEST1_FFT_SIZE 512 +#define MEL_FILTERBANK_32_TEST1_NUM_MEL_BINS 23 +#define MEL_FILTERBANK_32_TEST1_NORM_SLANEY 0 +#define MEL_FILTERBANK_32_TEST1_MEL_LOG MEL_DB +#define MEL_FILTERBANK_32_TEST1_SHIFT 0 + +static const int32_t mel_filterbank_32_test1_real[257] = { + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, +}; + +static const int32_t mel_filterbank_32_test1_imag[257] = { + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, +}; + +static const int16_t mel_filterbank_32_test1_mel_log[23] = { + 947, 995, 1057, 1103, 1164, 1211, 1272, 1321, 1377, 1430, + 1486, 1536, 1593, 1646, 1700, 1753, 1808, 1861, 1916, 1969, + 2023, 2077, 2131, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test2.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test2.h new file mode 100644 index 000000000000..8c24686e4ac9 --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test2.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_32_TEST2_FFT_SIZE 512 +#define MEL_FILTERBANK_32_TEST2_NUM_MEL_BINS 23 +#define MEL_FILTERBANK_32_TEST2_NORM_SLANEY 1 +#define MEL_FILTERBANK_32_TEST2_MEL_LOG MEL_LOG +#define MEL_FILTERBANK_32_TEST2_SHIFT 1 + +static const int32_t mel_filterbank_32_test2_real[257] = { + 279461323, 1390781566, -1605893308, -858491904, -2138369621, 1937491349, + 1143747056, 1079343158, -1551063714, -647167636, -1497480890, -14084580, + 1325651332, 570667122, 809178271, 599449521, 984929314, 1545525548, + 545269203, -1371849607, 314849219, -1444972356, 1743978925, -1815298915, + -693488397, 346249730, -106364189, 1311341503, 132191109, -1171193208, + 899731117, -1509111693, 679103827, 575450661, -1162620797, -1364820282, + -1433005068, -1504926082, -1276690205, 1954033604, -2079157853, 1965009171, + -2037136123, 2023404891, -869319949, 107688055, 1556235063, 1702546096, + -1335689494, 690285243, 1895072448, 2043146547, -1683905266, -1379117314, + 1058930316, -1935017962, -1841317411, -46705538, 1502782519, 2134776746, + -2128617521, 182997665, 1551978600, 1757238730, 1483269371, 1627246649, + 1057344660, -1642870602, 38750298, -1422356743, 1422113078, 1838292632, + -1419553569, 1648139240, -481625200, -504360328, -981602217, 1580046067, + 1037245156, -223884919, 900392038, 1908388329, -1399653076, -1096950608, + 605285980, 1325480637, 1517716916, -437581375, -1651441517, -1802679586, + -599287008, 1412638579, -1225741978, 1250008673, 664381250, -2035185509, + 1227399802, 1814894460, -33014851, 1434569135, -1583323865, 1115761513, + 1828522973, 1428968151, -1033364146, -1232562124, 95841258, -440847895, + -89722801, 2121299979, 448731559, 1910868086, -41050373, -266517496, + 1171046766, 1048257925, -245225163, -1919850156, -1770291699, 1279839943, + 668221204, -2008603503, 245100167, 944040490, -1673284689, -1216990252, + 1335821654, -1551935396, 1640244578, 1819159433, -2092698923, -527596991, + -1426737932, 172755592, -1710846815, -1978829964, 1860704867, 2025471714, + -597309606, 619357493, -1855652208, -1254508423, -1977386421, -131600748, + -1502823133, 2110147159, -313264831, 1955808290, 963133675, 347427259, + 172906396, 882363199, -2125884759, 1213396031, 1833347908, -2111854071, + 1394268115, 1148198810, 2135186707, -1169721149, 1801920055, 609882373, + -1695136907, -995741294, 1133200340, 1312156127, -1699720433, -129885067, + -1206619991, 1815516634, -771708419, 1535638966, -1031450708, 1623767975, + -1338880391, 1113229055, -2011379140, 611342025, 287208383, -530816960, + -1234595309, 1254804071, -1522808657, -46632820, -2092311585, -1345991104, + -63434704, 1452669938, -1541648581, 997364367, 820626155, -1999338974, + -47857688, 2024606395, -1664508651, 1044595206, 595030659, 404512531, + -5916263, 291424953, -315661837, -1820037736, -899423475, 263432022, + 572662886, 1850168227, 2052002907, -1745489544, 694646297, 441406242, + -112451421, -617374308, -104889795, 734533975, 1974161089, -1764869641, + 1278794128, 389878861, 1770371579, -1713136531, -887792748, -1925913993, + 17730401, 1152665077, -932070712, -1179568762, -724605467, -200783917, + 1019559258, 42458564, -504597704, 1741537155, 1998266816, 550904084, + -1580414091, 508102269, -502424827, 2109661082, -915569840, 885585447, + 151208178, -1317648556, 813617563, -1930781059, -1355345153, -1951382642, + 1653740659, 1459405774, -1640010734, -384765274, -1631105786, 309635025, + 1930115931, -1046317771, 2103956023, -645069552, -1251886872, +}; + +static const int32_t mel_filterbank_32_test2_imag[257] = { + 712222229, 2033000035, 526991721, -1874590477, -543272418, -1433438740, + -1154151866, -1923249275, 1725530241, 1259678259, -545399322, 1426164100, + 1090211119, 523398017, -454866325, -604396553, -1765865234, -679992092, + 209038610, -169447364, 624713187, 58071571, 1350451399, -1730084957, + -155849070, 385763180, -1343585726, 478159339, -1924394537, 325244767, + 1470359298, -1176934, -261886113, -1507288350, -2026024331, 1102388345, + 1271766600, -886671970, -1652674442, -536477360, 1412587879, 1467919242, + 709693745, 1976286148, 1903176855, -1663443014, 636889745, -82445970, + -1861779452, 1708414405, -11896506, 1165239354, -1888229847, -1020237420, + 648837998, -1573659222, 595049409, -494165644, 1141164760, 656767854, + -509000589, -858913647, -686595381, 1799275775, -187832607, -246973708, + -196770406, 1912471667, -1206374913, 1642407502, -2062119357, -679614652, + 1142579179, -675152961, 510269620, -201772572, -2103835602, 425550374, + 436232735, 641743065, -675509739, -28779478, 866612496, 1665599490, + -1911011999, -1725022287, 643312165, 1134175842, 2095767696, -1609217767, + -582066100, 756902474, -533614591, 1561042334, -893453051, -1574212929, + 741528313, -1277387780, 1582760724, 1078712484, -346261767, -2146491231, + -1505541806, -971374278, 1599553277, 434870352, -767989747, -926454191, + -277816499, 1734131920, 1825814843, 22730909, 547959698, 941731395, + -2044778605, 321832645, -1947619647, -332725154, -138580293, -2050297185, + -1867992764, 1820878597, 146642484, -572104809, -584346709, -1497338704, + -1504919610, -640800137, -704520255, 1219890311, -56954652, -151191383, + -1583758231, 1659538731, 749718434, 1439499684, 672110563, 2078407588, + 2060681809, -1073084636, 535027098, 980293743, -7858436, 1502501086, + -1327496207, -1614290142, -2135498880, -1490556417, 146719625, 45670986, + -492994042, -813482037, -2132213117, 1353955993, 594502751, -221880670, + -1099143247, 1303029022, 1391444366, 1512647321, -140652639, 2021636696, + 1465631884, -1810121671, -1127004196, 1363956549, -404462590, -144687911, + 1939333290, 1997182581, 1139389827, 320119332, 1786384382, -19617655, + -1434465918, -747334317, -874300267, 250390115, -1857672986, -1851226054, + -1431149321, 1921732705, 1336114580, 903900319, 2019689308, 2140726760, + 2093602453, -1502866704, 1969151471, 130820620, -1829284479, -808223063, + 1697245576, 1437818950, -2137395819, 602196704, 1302159245, -1094655071, + -1872080760, -1017270222, -1706303056, -69926256, -348388580, -509859828, + 1661143520, -341202876, -928366334, -1940547210, -1206172921, -1120230490, + -2021819403, 868918778, -2114689190, 476400694, -394752431, -1078265821, + 654809529, -771904028, -1702215264, 152750059, -1439371348, 1646856687, + 714927423, 1493542630, 1128120679, 1318614121, 571026397, 903778405, + 810303730, -769023081, 135929249, 1602855843, -1913237532, 1721318, + -288779795, 1736380080, 559133237, 2074624777, 365932672, 1463022703, + -133943792, 194228427, -1378237306, 577508590, 1988392800, 146087950, + -87556120, 1261286223, -1749281258, 1635521583, -2130846940, 49517074, + 766495473, 282383993, -92519408, -770891464, 436281912, +}; + +static const int16_t mel_filterbank_32_test2_mel_log[23] = { + -624, -658, -730, -737, -730, -688, -715, -676, -615, -627, + -634, -659, -654, -693, -657, -659, -673, -654, -642, -645, + -648, -651, -678, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test3.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test3.h new file mode 100644 index 000000000000..657075f827e2 --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test3.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_32_TEST3_FFT_SIZE 128 +#define MEL_FILTERBANK_32_TEST3_NUM_MEL_BINS 10 +#define MEL_FILTERBANK_32_TEST3_NORM_SLANEY 0 +#define MEL_FILTERBANK_32_TEST3_MEL_LOG MEL_LOG10 +#define MEL_FILTERBANK_32_TEST3_SHIFT 2 + +static const int32_t mel_filterbank_32_test3_real[65] = { + 1809626122, 2078831788, 2076276839, 1702121709, 1570683325, 1292617533, + 236132369, -348441473, -1601496640, 664091035, 1563217394, -968092351, + 1460992986, -1843592188, -520584074, -995704700, -1490692186, 562638912, + -788664159, 1971870392, -5695173, 1024815776, -2092698467, 452488499, + 328355925, 1320181983, 665582756, 1624478588, 1728178556, -1493648507, + -1320358473, 1249730895, -1886757211, -473188605, -859140114, 1005795040, + -1699908311, 1256602151, 1214311563, 139147033, -1059343626, -1842736026, + 540321193, -2041477541, -1881013172, -1590804423, -212110944, 740176814, + 1529484384, -6676852, -1937955799, -799583926, 608301233, 1230021268, + -905591736, -9156824, 1367666262, 408572905, 156442504, -726394330, + -379287590, 1262747189, -673415565, -160602846, -567693024, +}; + +static const int32_t mel_filterbank_32_test3_imag[65] = { + 771249939, 291108725, 651876590, -38166160, -436118560, -96704586, + -1861491985, -382129738, 2014734620, 1205687647, 983624342, 1140960708, + 1102006161, 1474334785, 1160314835, 2055833035, -1669198484, -446346139, + -34099245, -1038975703, -1988714936, 2037452268, 972492175, -1511979541, + -1512281361, 879712807, -511128929, -1819298994, -382937811, -1533343895, + 1283852142, 1847901790, -2127213645, 644419390, 766791081, -1058181837, + 1473950797, -884940326, -2032119177, -1746732435, 1279406214, 907967366, + 1217222868, 532243703, 1397648759, -1997062790, -405981903, -1075164509, + -82047440, 1635691597, -941951536, 425813835, -2034843240, -1480910452, + 1434136270, -1310423009, 1416428825, -695463185, 734939984, -1922572020, + 1006349777, -2225747, 1903958734, -902920596, -530168929, +}; + +static const int16_t mel_filterbank_32_test3_mel_log[10] = { + -135, -147, -133, -111, -90, -88, -69, -55, -46, -42, +}; diff --git a/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test4.h b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test4.h new file mode 100644 index 000000000000..dc9b0c8bfc2a --- /dev/null +++ b/test/cmocka/src/math/auditory/ref_mel_filterbank_32_test4.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 13-Sep-2022 11:32:32 with script ref_matrix.m v1.9-rc1-1767-gf95e12db0 */ + +#define MEL_FILTERBANK_32_TEST4_FFT_SIZE 1024 +#define MEL_FILTERBANK_32_TEST4_NUM_MEL_BINS 23 +#define MEL_FILTERBANK_32_TEST4_NORM_SLANEY 1 +#define MEL_FILTERBANK_32_TEST4_MEL_LOG MEL_DB +#define MEL_FILTERBANK_32_TEST4_SHIFT 3 + +static const int32_t mel_filterbank_32_test4_real[513] = { + -1675725814, 1426306934, 2025475456, -1210015671, 885096674, -1979921115, + 499483754, 727413574, -1987704281, -2133161814, -1535603906, 1556519594, + -961911973, 136114115, 95439766, 290415874, -717119722, -371873076, + -367871884, 2078428237, -1899495252, -444344922, 1251212373, 404523482, + -817920289, 1725730342, -1747506272, -777272531, 1661987480, 676163889, + 792494009, -111889804, -1540844607, 1936707619, 1643366687, -268699399, + 1438628505, -751003376, -568484878, 1266325864, -1720955960, 1940387015, + -2141153197, -878768136, -1939372930, -245928179, 1244880673, 1776057520, + 142826389, 1305998385, 269124182, 1077506157, -2107839578, -99708302, + -1072326518, -824984798, 2005531132, -1250675748, 87944836, -1178770398, + 288612670, 2139596053, -1581126339, 1952821062, -1615433787, -1347596645, + 629224351, -1597001652, -1798214748, 683874991, -2029806479, 2083831377, + 168925132, -541874907, 887919575, 1921617221, -505614937, 828535935, + 438392949, 1182222872, 394424910, -531803677, 1506026845, -1177958386, + 1275426119, 2134087672, -939262874, 903579407, 707132294, -365778600, + -7430713, 1928968706, 1946400477, 1000398006, -495295609, -1975329639, + 356197039, 277938680, -621985922, 1632950092, 534852849, 532642716, + -877283958, -1826735804, -886026007, -1139283847, -661865709, 1496754695, + -1458723872, -1469461315, 37191280, 443674417, -1454288947, 581771895, + 1477213525, 1212337034, -1011179808, -795861897, -1360664660, -225600577, + -744409673, -945681834, 1854411866, -430817806, -517873598, 398772464, + -1853249672, -1265994601, 960433191, 322756539, -1287491593, 1475236850, + -327577151, 192203921, 120118999, -1352451611, -1796628998, -154216715, + -2016251886, -279240917, 248528116, 596064707, -2000520977, 901515557, + -1420242827, 401074668, 464135294, 1169775519, -1905790309, 1523532905, + -496995037, -431133280, -749826191, 237898713, -878663966, -575010213, + -648332492, 559308060, 706273359, 2113537672, 1908517089, -642751039, + -1318563787, 1802065792, -907560733, 218439578, 1800983527, -1760728190, + -1040686458, -313326636, 333818989, 1715931325, -1210211760, 2005886670, + -283547822, 1223302993, 108378537, -724660399, -293803050, 935880250, + 1787617264, 1675157450, -1568925533, -1632462285, 1689865281, 657497395, + -1974490626, 20254909, 1694164734, -490792508, -893130384, -1142304234, + -1284417025, -514081544, 407120561, -994774663, 525887143, 1308106635, + -1700930493, 984579624, 638190326, -108857564, 1859343355, -1733261199, + 425660973, -1144330860, -2008634493, 342992926, 1469729873, 244370703, + 1459786326, -1267220335, 520785773, -1400069628, -903919595, -2068014146, + 865420406, 1941717657, 1069486950, 1102635742, 180771203, -936032834, + -1095754189, -917756266, 1989147146, -1156654683, 160294250, -1266979909, + -283290483, -1536687877, -534363618, 1260833291, 1343532990, 1734268738, + 173412458, 1365212531, 895142676, -1961903042, -1520650435, -1145314608, + -1087910573, -1416124836, -1137922229, -964387335, 1939635690, -658543113, + -870495649, -410486310, -849383789, 1105142689, -602395388, -1611044073, + 503295261, -620539221, -588676006, -1853328698, 1576948232, -180834453, + -1814128107, 1739123294, -937609053, 489101610, 695174568, -1288384550, + 1975625804, 709124803, 177381460, 1584709237, 245017005, -2055579435, + -74386463, 1322787990, 1013652509, 310545013, -2108893997, 937507453, + -217211135, 685548802, 1087521565, 1308844098, -2022261376, 1201806013, + 289268189, -1820565225, -1066776142, -1574300812, 276913386, 176013269, + -1851468284, 2097794602, -1069036943, -792537467, -856171886, -1966927354, + 119835174, -1047876097, -392087597, 1922052165, 1800798054, -1626746019, + 394900058, -602789326, 941916103, 101151168, -1027169982, -29724154, + 1528303556, 963817649, -1292311413, -1471945961, -556303407, 1555946414, + 793549445, 576375503, -1540504734, -1806883099, 1615531966, -341756126, + -52984404, -170400704, 67333274, -979276637, -1152855817, 1715985794, + 1755341652, 445142661, -578804898, 423442976, 723646783, 1694639867, + -1772380429, 167548175, -307305185, 503170427, 252869966, -1177462328, + -1698575685, -2104629942, -1893422142, -761702269, 1200342457, -706614091, + 513543280, 2116928037, 635679619, 170835847, -1149957079, 1030071572, + 1670709401, 1545361986, 416872913, 664655395, 1782471531, -286976483, + -902970678, 566430168, -878656509, 524109664, -1943325839, 2124333324, + -1259438389, 461124680, -654422768, 935173586, -2027253361, -1860400470, + 1834226518, -1770506807, -719842695, 112446090, -1088163791, 184251763, + 1206318233, 93984113, 1855210840, -1515642504, -357488589, -943634953, + 421337654, -1990825331, -1873952200, -760713848, -1724951077, -1417147539, + -553347271, -1976708779, 898683052, 607056520, -1399897946, -1880543087, + -400894737, -158643525, -1277004160, 1587204692, 420650682, -2048641259, + 1715523485, -202094894, -1898263118, -1691060151, 2140720327, 1573364218, + 494805129, -2031757968, -762259476, -155579891, -1722207871, 304891758, + -747860776, -212633795, 334336554, -1826029795, -1901198758, -854885602, + 93292053, 265773586, -1110013810, 1772619601, 1399018036, -238173615, + 2070442944, 336156617, -1140642398, 1333975793, -209275870, -1073874240, + 1956089304, -1534805073, 53959327, 2026903032, 637032218, 492508209, + -130350660, 334065553, 1766576859, -531629834, -1164946431, -328458177, + -972396827, -238087888, 547672956, 148783051, -492022176, 1603955962, + -857495654, -429369102, 76121915, -1881948522, -1153769002, -1638590189, + -1723226624, 1676220318, -2004078653, 1456144202, 31210345, -1659075253, + -41035591, 427098936, -1760008307, 2053956587, 657210624, -166936245, + 1562329188, -1018641379, 1391410245, -734545472, 1895371349, -1099047466, + 1963273210, 46492869, 277368384, 2120494639, 1163867160, -799714660, + -1898922617, -1958188154, 1344084115, -377642397, -497515402, 99327700, + 1684266988, -404067772, 448346895, -1740305473, -704455048, -1525392689, + -1095729781, -519812769, -986469755, -1221491708, 574370748, 1287268572, + -1251922722, 1701907386, 1055314141, 156275851, 2018485139, 278671094, + -1212512651, 1536581617, 1554775231, -801860967, -743097153, 1460346450, + -32071439, -1924564176, 1194079802, -314939705, -945056523, -715077644, + -571488554, 1266123761, -1981307989, +}; + +static const int32_t mel_filterbank_32_test4_imag[513] = { + 973537383, 1600667564, -919918504, 673662439, -1151538177, 523788191, + -1824829524, 2004701220, 472317367, -499439500, -2016187471, 1535732502, + 444714595, 1493963164, 19826629, -2113506859, 1799905592, -383519982, + 998003287, -1498491417, 1353916614, 1759229479, 1193753781, 1104335462, + -407173536, 867158536, 281152584, 363939860, -666086724, 877175084, + -1456579407, -2140981354, 266291632, 199647796, 218303575, 835529025, + 1836073145, 1907868749, 1732002811, 447133095, 1830556967, -1645203293, + -683752317, -1989727594, 164797253, 1018889943, -1369138926, -316768177, + -1725855483, -845156936, 1203117457, 158743781, 1155653005, 596758414, + 1688558858, -1886820419, -1392550607, -359351929, 1029898115, 1687727983, + -2036444542, -1556654940, -326041994, 1136305676, 104956922, 1092989114, + -1418204887, 741856842, 509609650, -2118079918, 1031760770, 2111987796, + -1596948911, -598792485, -1326830222, 920830942, -1383550652, 2090999459, + -2074472941, -1976559113, 1307089682, 1545296100, 284552441, 1091405654, + 83815283, 368956900, -1328291538, 14780973, -1928806966, -1906554266, + -707821778, 562231649, 1683531896, 744732840, 795715880, 840717485, + 1287766200, 689793941, 85627025, -722686613, 1864757602, -1088873216, + 48130998, 1032157463, -1055838111, 1484275236, 163871995, 1761521283, + -641211086, 1869706134, 1837041089, 376670180, -1710418609, -571763485, + -962736097, -1004603582, -1174507557, -2141810941, 1687953808, -199726686, + 336815654, -791968180, 2121786322, 2078304110, 1995218000, 714103764, + 971341971, -712781801, 97808287, -973435587, 937930785, 1194076312, + -1799315476, -1195804192, -1271484291, 533002460, 967248606, 1436083251, + -2066328601, -1279395030, -132744718, -522288718, -685503694, -1873244897, + 1122429290, -418063158, 748568631, 219368285, -1926476800, -826798653, + 1999070052, 1853171658, -523871220, 505389626, 268578870, 1419747437, + 1965801113, -1823189336, 1666552094, 268209075, -1312734740, -1196351154, + 883745568, 415587203, 370638812, 2012167045, 351085338, -1718844661, + -1431929977, -1708994138, -1519357116, 736865063, 600664842, -547885563, + -1447949585, -474513105, 1288389542, -430382782, 1095728126, -879564584, + 601320807, 1654065583, -1247072433, -84368242, -1662205775, -1578960373, + -1872596046, -1806903928, 545263982, -380817715, 595238169, 1531400494, + 1132046146, 2045092900, 1209193260, 1870815614, 1027150737, -1058195041, + 941672802, 831130355, 1173895955, 1061789298, -780036211, 44800620, + 1172811586, 312740303, 1949272346, -1410586212, 1749061415, 1083274172, + -918370387, 547223255, -159652854, -1591546323, 212105511, 2016527188, + -248504704, 390687104, -1670870066, -1289124592, -1447558155, -1989096304, + -976140135, -1159067406, -607545936, -1570486149, 2141447489, 58071629, + -481696453, -1074374224, -580883905, -433544559, 1830947821, -19443615, + 468954615, -2126831454, 376792174, 1191692031, 675096634, 121610683, + 1399185074, 1986137916, -799995827, 1275970606, -922662922, -2083510645, + -1743113532, -735629024, -835086288, -2070079176, -1450808132, -240563423, + 1145768552, 778488314, 921428231, -172739814, 1800744098, 2099995997, + 1858007643, -165255965, 1739127476, -487686434, 442452723, 259068170, + 1485370440, -924255682, 701447606, 439195524, 672003239, -816326882, + -723084343, -1339182275, -1715051707, -916700837, -623516630, 153595324, + 2108111588, -2026459703, 899933155, 1740136140, 1571225228, -1635655303, + 1955392100, -253829170, 1613877845, 1567455371, -622123542, 563269703, + 1565727107, -2057324835, -1817543165, -529507503, -1506701742, -2001038596, + 1212253263, -741976748, 1363550453, -1401795505, 756419902, 1613191781, + 1104474344, -1161248714, -605832542, -587705741, -998824232, -698779315, + -1773990505, -208049710, -194716518, -2022777083, 588848059, -1892110102, + -1420791872, 793193454, 234364823, -2121559940, -910167339, -529949294, + -1518300861, -1827364207, -168608063, -556651902, 1393963927, 161214415, + 1363721192, -170163054, -2087208874, -2126080945, -1433545048, -575788303, + 937206860, -1462764342, -950169298, 622505893, -913951220, -764800992, + -1479973596, -482483137, 1699660869, 1665446016, -456927278, 753585264, + -1064231931, 1932682492, 535505857, -1258649007, -1676518317, 282821923, + -969230683, -1841831183, -1466949086, -1934795595, 776889782, 1210132000, + 1320123466, -1009087134, 1700374963, 463796716, -2085632517, -669891423, + 144588937, 548736090, -228761552, 1336188566, -1525452170, 2039376637, + 1433488568, -686760285, 499242986, -842860838, -1764291959, 92452628, + 1397116496, 1133556212, 1922596188, -714909018, -473570041, -1501465248, + -714234075, 230548813, 216010848, -1458480506, -1644588205, -435722568, + 1423279168, -1352909521, 3374803, -1604967088, 1566067281, 1145234511, + 276396331, -474295936, -42358414, 1661740438, 1739669123, -6919384, + 125528795, 1759651190, 337577759, 1184488001, 693184660, -130321166, + -1203588908, 440619572, -1356097283, -1299185879, 1554744431, -1607824219, + 625262437, -269216237, 483635082, 1019979205, -844908341, -1962938725, + 1440993872, -561317095, 692947045, 1699604106, -970237124, 2138457676, + 1436036838, 1251311610, 672646460, 187574189, -486699983, 1383976278, + 409458619, 1209640262, 2094546270, 1238040646, 1515783666, -61792428, + 1605270108, -713621344, -1265654797, -24236209, -2013442187, 1406921398, + -1012506595, 762353828, 1262137712, 781013452, 647505994, -1128108686, + -97051318, 1874406471, -1111951953, -1249346375, -977225200, 1184626800, + -724082460, 442702472, -1357145826, -1771850747, -820702187, -1155868452, + 1757445006, 1876403978, -2010565070, 402210988, -1959288825, -322539832, + 92690887, 1461746685, 536998383, -1051387892, 1738135623, 1148047346, + 269146280, 1705761438, -566594622, -696940018, 510479867, -1774270575, + -534734030, -1342688092, 1333701978, 958843697, 750219316, 1778036648, + 1378516557, 209270720, -2080733009, -1740808839, 63386379, 1943398133, + 1473436618, 1868363370, 2033293718, -547494986, -769225676, 1216540471, + -1235998325, 1972043708, 1847836103, -576687460, -666096214, 827561293, + 930306514, 1289965495, 402311637, -1730120149, 255589923, -1962413677, + 1106519816, 685680916, 427174531, -1172548621, 917896191, 964230522, + -669078725, -2006819922, 1475818831, +}; + +static const int16_t mel_filterbank_32_test4_mel_log[23] = { + -4014, -4091, -4150, -4106, -3929, -4047, -4001, -3949, -4000, -4132, + -4143, -4095, -4126, -4095, -4077, -4088, -4077, -4086, -4031, -4096, + -4071, -4074, -4101, +}; diff --git a/test/cmocka/src/math/dct/CMakeLists.txt b/test/cmocka/src/math/dct/CMakeLists.txt new file mode 100644 index 000000000000..a50dd6ee524f --- /dev/null +++ b/test/cmocka/src/math/dct/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(dct + dct.c + ${PROJECT_SOURCE_DIR}/src/math/dct.c + ${PROJECT_SOURCE_DIR}/src/math/trig.c + ${PROJECT_SOURCE_DIR}/src/math/sqrt_int16.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c +) diff --git a/test/cmocka/src/math/dct/dct.c b/test/cmocka/src/math/dct/dct.c new file mode 100644 index 000000000000..ea35d170e66e --- /dev/null +++ b/test/cmocka/src/math/dct/dct.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <cmocka.h> +#include <math.h> +#include <sof/math/dct.h> +#include <sof/math/matrix.h> +#include "ref_dct_matrix_16_test1.h" +#include "ref_dct_matrix_16_test2.h" + +#define MATRIX_MULT_16_MAX_ERROR_ABS 2.5 +#define MATRIX_MULT_16_MAX_ERROR_RMS 1.1 + +struct processing_module dummy; + +static void dct_matrix_16_test(const int16_t *ref, int num_in, int num_out, + enum dct_type type, bool ortho) +{ + struct dct_plan_16 dct; + double delta; + double sum_squares = 0; + double error_rms; + double delta_max = 0; + int16_t x; + int rows; + int columns; + int ret; + int i, j, k; + + /* Calculate DCT matrix */ + dct.num_in = num_in; + dct.num_out = num_out; + dct.type = type; + dct.ortho = ortho; + ret = mod_dct_initialize_16(&dummy, &dct); + if (ret) { + fprintf(stderr, "Failed to initialize DCT.\n"); + exit(EXIT_FAILURE); + } + + /* Check */ + rows = dct.matrix->rows; + columns = dct.matrix->columns; + k = 0; + for (i = 0; i < rows; i++) { + for (j = 0; j < columns; j++) { + x = mat_get_scalar_16b(dct.matrix, i, j); + delta = (double)x - (double)ref[k++]; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + } + } + + error_rms = sqrt(sum_squares / (double)(rows * columns)); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, MATRIX_MULT_16_MAX_ERROR_ABS, error_rms, MATRIX_MULT_16_MAX_ERROR_RMS); + + assert_true(error_rms < MATRIX_MULT_16_MAX_ERROR_RMS); + assert_true(delta_max < MATRIX_MULT_16_MAX_ERROR_ABS); + + mod_dct_free_16(&dummy, &dct); +} + +static void test_dct_matrix_16_test1(void **state) +{ + (void)state; + + dct_matrix_16_test(dct_matrix_16_test1_matrix, + DCT_MATRIX_16_TEST1_NUM_IN, + DCT_MATRIX_16_TEST1_NUM_OUT, + DCT_MATRIX_16_TEST1_TYPE, + DCT_MATRIX_16_TEST1_ORTHO); +} + +static void test_dct_matrix_16_test2(void **state) +{ + (void)state; + + dct_matrix_16_test(dct_matrix_16_test2_matrix, + DCT_MATRIX_16_TEST2_NUM_IN, + DCT_MATRIX_16_TEST2_NUM_OUT, + DCT_MATRIX_16_TEST2_TYPE, + DCT_MATRIX_16_TEST2_ORTHO); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_dct_matrix_16_test1), + cmocka_unit_test(test_dct_matrix_16_test2), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/dct/mfcc_get_dct_matrix.m b/test/cmocka/src/math/dct/mfcc_get_dct_matrix.m new file mode 100644 index 000000000000..22d91481b7fe --- /dev/null +++ b/test/cmocka/src/math/dct/mfcc_get_dct_matrix.m @@ -0,0 +1,57 @@ +% dct_matrix = mfcc_get_dct_matrix(num_ceps, num_mels, type) +% +% Input +% num_ceps - number of cepstral coefficients +% num_mels - number of Mel band energies +% type - DCT type, currently only 2 for DCT-II is supported +% +% Output +% dct matrix coefficients + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +% Ref: pytorch kaldi.py _get_dct_matrix +function dct_matrix = mfcc_get_dct_matrix(num_ceps, num_mels, type) + +dct_matrix = create_dct(num_ceps, num_mels, type, 'ortho'); + +% TODO: Check if code below is needed +% make first cepstral to be weighted sum of factor sqrt(1 / num_mels) +%dct_matrix(:,1) = sqrt(1 / num_mels); +%dct_matrix = dct_matrix(:, 1:num_ceps); + +end + + +% Ref pytorch functional.py create_dct +function dct_matrix = create_dct(n_mfcc, n_mels, type, norm) + +debug = 0; +n = (0:(n_mels - 1))'; % Size n_mels x 1 +k = 0:(n_mfcc - 1); % Size 1 x n_mfcc +switch type + case 2, + arg = pi / n_mels * (n + 0.5) * k; + dct_matrix = cos(arg); + if debug + fprintf(1, 'Max arg = %f\n', max(max(arg))); + end + case 3, + error('not implemented'); % FIXME + otherwise + error('Unknown DCT type'); +end + +switch lower(norm) + case 'ortho', + dct_matrix(:,1) = dct_matrix(:,1) * 1 / sqrt(2); + dct_matrix = dct_matrix * sqrt(2 / n_mels); + case 'none' + dct_matrix = dct_matrix * 2; + otherwise + error('Unknown norm'); +end + +end diff --git a/test/cmocka/src/math/dct/ref_dct.m b/test/cmocka/src/math/dct/ref_dct.m new file mode 100644 index 000000000000..f015490d8c66 --- /dev/null +++ b/test/cmocka/src/math/dct/ref_dct.m @@ -0,0 +1,67 @@ +% ref_auditory - Generate C header files for auditory library unit tests + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function ref_dct() + + path(path(), '../../../m'); + opt.describe = export_get_git_describe(); + + %% Test 1, + opt.test_n = 1; + opt.num_in = 23; + opt.num_out = 13; + opt.type = 'DCT_II'; + opt.ortho = 'true'; + opt.bits = 16; + get_ref_dct_matrix(opt); + + %% Test 2, + opt.test_n = 2; + opt.num_in = 42; + opt.num_out = 42; + opt.type = 'DCT_II'; + opt.ortho = 'true'; + opt.bits = 16; + get_ref_dct_matrix(opt); + +end + +function get_ref_dct_matrix(opt) + + header_fn = sprintf('ref_dct_matrix_%d_test%d.h', opt.bits, opt.test_n); + + % TODO: type and ortho parameters are not supported + dct_matrix = mfcc_get_dct_matrix(opt.num_out, opt.num_in, 2); + + switch opt.bits + case 16 + qdm = export_quant_qxy(dct_matrix, 16, 15, false); % Q1.15 + case 32 + qdm = export_quant_qxy(dct_matrix, 32, 31, false); % Q1.31 + otherwise + error('Illegal bits value'); + end + + define_prefix = sprintf('DCT_MATRIX_%d_TEST%d_', opt.bits, opt.test_n); + vector_prefix = sprintf('dct_matrix_%d_test%d_', opt.bits, opt.test_n); + + fh = export_headerfile_open(header_fn); + comment = sprintf('Created %s with script ref_matrix.m %s', ... + datestr(now, 0), opt.describe); + export_comment(fh, comment); + export_ndefine(fh, [define_prefix 'NUM_IN'], opt.num_in); + export_ndefine(fh, [define_prefix 'NUM_OUT'], opt.num_out); + export_sdefine(fh, [define_prefix 'TYPE'], opt.type); + export_sdefine(fh, [define_prefix 'ORTHO'], opt.ortho); + export_vector(fh, opt.bits, [vector_prefix 'matrix'], mat_to_vec(qdm)); + fclose(fh); + fprintf(1, 'Exported %s.\n', header_fn); + +end + +function v = mat_to_vec(m) + v = reshape(transpose(m), prod(size(m)), 1); +end diff --git a/test/cmocka/src/math/dct/ref_dct_matrix_16_test1.h b/test/cmocka/src/math/dct/ref_dct_matrix_16_test1.h new file mode 100644 index 000000000000..ea7dbedfd541 --- /dev/null +++ b/test/cmocka/src/math/dct/ref_dct_matrix_16_test1.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 02-Sep-2022 16:36:35 with script ref_matrix.m v1.9-rc1-1720-g5b4f9f481 */ + +#define DCT_MATRIX_16_TEST1_NUM_IN 23 +#define DCT_MATRIX_16_TEST1_NUM_OUT 13 +#define DCT_MATRIX_16_TEST1_TYPE DCT_II +#define DCT_MATRIX_16_TEST1_ORTHO true + +static const int16_t dct_matrix_16_test1_matrix[299] = { + 6833, 9640, 9573, 9461, 9304, 9105, 8863, 8579, 8256, 7894, + 7496, 7062, 6595, 6833, 9461, 8863, 7894, 6595, 5021, 3236, + 1316, -659, -2607, -4445, -6098, -7496, 6833, 9105, 7496, 5021, + 1966, -1316, -4445, -7062, -8863, -9640, -9304, -7894, -5572, 6833, + 8579, 5572, 1316, -3236, -7062, -9304, -9461, -7496, -3850, 659, + 5021, 8256, 6833, 7894, 3236, -2607, -7496, -9640, -8256, -3850, + 1966, 7062, 9573, 8579, 4445, 6833, 7062, 659, -6098, -9573, + -7894, -1966, 5021, 9304, 8579, 3236, -3850, -8863, 6833, 6098, + -1966, -8579, -8863, -2607, 5572, 9640, 6595, -1316, -8256, -9105, + -3236, 6833, 5021, -4445, -9640, -5572, 3850, 9573, 6098, -3236, + -9461, -6595, 2607, 9304, 6833, 3850, -6595, -9105, -659, 8579, + 7496, -2607, -9573, -5021, 5572, 9461, 1966, 6833, 2607, -8256, + -7062, 4445, 9461, 659, -9105, -5572, 6098, 8863, -1316, -9573, + 6833, 1316, -9304, -3850, 8256, 6098, -6595, -7894, 4445, 9105, + -1966, -9640, -659, 6833, 0, -9663, 0, 9663, 0, -9663, + 0, 9663, 0, -9663, 0, 9663, 6833, -1316, -9304, 3850, + 8256, -6098, -6595, 7894, 4445, -9105, -1966, 9640, -659, 6833, + -2607, -8256, 7062, 4445, -9461, 659, 9105, -5572, -6098, 8863, + 1316, -9573, 6833, -3850, -6595, 9105, -659, -8579, 7496, 2607, + -9573, 5021, 5572, -9461, 1966, 6833, -5021, -4445, 9640, -5572, + -3850, 9573, -6098, -3236, 9461, -6595, -2607, 9304, 6833, -6098, + -1966, 8579, -8863, 2607, 5572, -9640, 6595, 1316, -8256, 9105, + -3236, 6833, -7062, 659, 6098, -9573, 7894, -1966, -5021, 9304, + -8579, 3236, 3850, -8863, 6833, -7894, 3236, 2607, -7496, 9640, + -8256, 3850, 1966, -7062, 9573, -8579, 4445, 6833, -8579, 5572, + -1316, -3236, 7062, -9304, 9461, -7496, 3850, 659, -5021, 8256, + 6833, -9105, 7496, -5021, 1966, 1316, -4445, 7062, -8863, 9640, + -9304, 7894, -5572, 6833, -9461, 8863, -7894, 6595, -5021, 3236, + -1316, -659, 2607, -4445, 6098, -7496, 6833, -9640, 9573, -9461, + 9304, -9105, 8863, -8579, 8256, -7894, 7496, -7062, 6595, +}; diff --git a/test/cmocka/src/math/dct/ref_dct_matrix_16_test2.h b/test/cmocka/src/math/dct/ref_dct_matrix_16_test2.h new file mode 100644 index 000000000000..49a2dd2ce583 --- /dev/null +++ b/test/cmocka/src/math/dct/ref_dct_matrix_16_test2.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 02-Sep-2022 16:36:35 with script ref_matrix.m v1.9-rc1-1720-g5b4f9f481 */ + +#define DCT_MATRIX_16_TEST2_NUM_IN 42 +#define DCT_MATRIX_16_TEST2_NUM_OUT 42 +#define DCT_MATRIX_16_TEST2_TYPE DCT_II +#define DCT_MATRIX_16_TEST2_ORTHO true + +static const int16_t dct_matrix_16_test2_matrix[1764] = { + 5056, 7146, 7131, 7106, 7071, 7026, 6971, 6907, 6833, 6749, + 6656, 6554, 6442, 6322, 6193, 6055, 5908, 5753, 5591, 5420, + 5242, 5056, 4864, 4664, 4458, 4246, 4028, 3804, 3575, 3341, + 3103, 2859, 2612, 2362, 2108, 1851, 1591, 1329, 1066, 801, + 534, 267, 5056, 7106, 6971, 6749, 6442, 6055, 5591, 5056, + 4458, 3804, 3103, 2362, 1591, 801, 0, -801, -1591, -2362, + -3103, -3804, -4458, -5056, -5591, -6055, -6442, -6749, -6971, -7106, + -7151, -7106, -6971, -6749, -6442, -6055, -5591, -5056, -4458, -3804, + -3103, -2362, -1591, -801, 5056, 7026, 6656, 6055, 5242, 4246, + 3103, 1851, 534, -801, -2108, -3341, -4458, -5420, -6193, -6749, + -7071, -7146, -6971, -6554, -5908, -5056, -4028, -2859, -1591, -267, + 1066, 2362, 3575, 4664, 5591, 6322, 6833, 7106, 7131, 6907, + 6442, 5753, 4864, 3804, 2612, 1329, 5056, 6907, 6193, 5056, + 3575, 1851, 0, -1851, -3575, -5056, -6193, -6907, -7151, -6907, + -6193, -5056, -3575, -1851, 0, 1851, 3575, 5056, 6193, 6907, + 7151, 6907, 6193, 5056, 3575, 1851, 0, -1851, -3575, -5056, + -6193, -6907, -7151, -6907, -6193, -5056, -3575, -1851, 5056, 6749, + 5591, 3804, 1591, -801, -3103, -5056, -6442, -7106, -6971, -6055, + -4458, -2362, 0, 2362, 4458, 6055, 6971, 7106, 6442, 5056, + 3103, 801, -1591, -3804, -5591, -6749, -7151, -6749, -5591, -3804, + -1591, 801, 3103, 5056, 6442, 7106, 6971, 6055, 4458, 2362, + 5056, 6554, 4864, 2362, -534, -3341, -5591, -6907, -7071, -6055, + -4028, -1329, 1591, 4246, 6193, 7106, 6833, 5420, 3103, 267, + -2612, -5056, -6656, -7146, -6442, -4664, -2108, 801, 3575, 5753, + 6971, 7026, 5908, 3804, 1066, -1851, -4458, -6322, -7131, -6749, + -5242, -2859, 5056, 6322, 4028, 801, -2612, -5420, -6971, -6907, + -5242, -2362, 1066, 4246, 6442, 7146, 6193, 3804, 534, -2859, + -5591, -7026, -6833, -5056, -2108, 1329, 4458, 6554, 7131, 6055, + 3575, 267, -3103, -5753, -7071, -6749, -4864, -1851, 1591, 4664, + 6656, 7106, 5908, 3341, 5056, 6055, 3103, -801, -4458, -6749, + -6971, -5056, -1591, 2362, 5591, 7106, 6442, 3804, 0, -3804, + -6442, -7106, -5591, -2362, 1591, 5056, 6971, 6749, 4458, 801, + -3103, -6055, -7151, -6055, -3103, 801, 4458, 6749, 6971, 5056, + 1591, -2362, -5591, -7106, -6442, -3804, 5056, 5753, 2108, -2362, + -5908, -7146, -5591, -1851, 2612, 6055, 7131, 5420, 1591, -2859, + -6193, -7106, -5242, -1329, 3103, 6322, 7071, 5056, 1066, -3341, + -6442, -7026, -4864, -801, 3575, 6554, 6971, 4664, 534, -3804, + -6656, -6907, -4458, -267, 4028, 6749, 6833, 4246, 5056, 5420, + 1066, -3804, -6833, -6554, -3103, 1851, 5908, 7106, 4864, 267, + -4458, -7026, -6193, -2362, 2612, 6322, 6971, 4246, -534, -5056, + -7131, -5753, -1591, 3341, 6656, 6749, 3575, -1329, -5591, -7146, + -5242, -801, 4028, 6907, 6442, 2859, -2108, -6055, -7071, -4664, + 5056, 5056, 0, -5056, -7151, -5056, 0, 5056, 7151, 5056, + 0, -5056, -7151, -5056, 0, 5056, 7151, 5056, 0, -5056, + -7151, -5056, 0, 5056, 7151, 5056, 0, -5056, -7151, -5056, + 0, 5056, 7151, 5056, 0, -5056, -7151, -5056, 0, 5056, + 7151, 5056, 5056, 4664, -1066, -6055, -6833, -2859, 3103, 6907, + 5908, 801, -4864, -7146, -4458, 1329, 6193, 6749, 2612, -3341, + -6971, -5753, -534, 5056, 7131, 4246, -1591, -6322, -6656, -2362, + 3575, 7026, 5591, 267, -5242, -7106, -4028, 1851, 6442, 6554, + 2108, -3804, -7071, -5420, 5056, 4246, -2108, -6749, -5908, -267, + 5591, 6907, 2612, -3804, -7131, -4664, 1591, 6554, 6193, 801, + -5242, -7026, -3103, 3341, 7071, 5056, -1066, -6322, -6442, -1329, + 4864, 7106, 3575, -2859, -6971, -5420, 534, 6055, 6656, 1851, + -4458, -7146, -4028, 2362, 6833, 5753, 5056, 3804, -3103, -7106, + -4458, 2362, 6971, 5056, -1591, -6749, -5591, 801, 6442, 6055, + 0, -6055, -6442, -801, 5591, 6749, 1591, -5056, -6971, -2362, + 4458, 7106, 3103, -3804, -7151, -3804, 3103, 7106, 4458, -2362, + -6971, -5056, 1591, 6749, 5591, -801, -6442, -6055, 5056, 3341, + -4028, -7106, -2612, 4664, 6971, 1851, -5242, -6749, -1066, 5753, + 6442, 267, -6193, -6055, 534, 6554, 5591, -1329, -6833, -5056, + 2108, 7026, 4458, -2859, -7131, -3804, 3575, 7146, 3103, -4246, + -7071, -2362, 4864, 6907, 1591, -5420, -6656, -801, 5908, 6322, + 5056, 2859, -4864, -6749, -534, 6322, 5591, -1851, -7071, -3804, + 4028, 7026, 1591, -5753, -6193, 801, 6833, 4664, -3103, -7146, + -2612, 5056, 6656, 267, -6442, -5420, 2108, 7106, 3575, -4246, + -6971, -1329, 5908, 6055, -1066, -6907, -4458, 3341, 7131, 2362, + -5242, -6554, 5056, 2362, -5591, -6055, 1591, 7106, 3103, -5056, + -6442, 801, 6971, 3804, -4458, -6749, 0, 6749, 4458, -3804, + -6971, -801, 6442, 5056, -3103, -7106, -1591, 6055, 5591, -2362, + -7151, -2362, 5591, 6055, -1591, -7106, -3103, 5056, 6442, -801, + -6971, -3804, 4458, 6749, 5056, 1851, -6193, -5056, 3575, 6907, + 0, -6907, -3575, 5056, 6193, -1851, -7151, -1851, 6193, 5056, + -3575, -6907, 0, 6907, 3575, -5056, -6193, 1851, 7151, 1851, + -6193, -5056, 3575, 6907, 0, -6907, -3575, 5056, 6193, -1851, + -7151, -1851, 6193, 5056, -3575, -6907, 5056, 1329, -6656, -3804, + 5242, 5753, -3103, -6907, 534, 7106, 2108, -6322, -4458, 4664, + 6193, -2362, -7071, -267, 6971, 2859, -5908, -5056, 4028, 6554, + -1591, -7146, -1066, 6749, 3575, -5420, -5591, 3341, 6833, -801, + -7131, -1851, 6442, 4246, -4864, -6055, 2612, 7026, 5056, 801, + -6971, -2362, 6442, 3804, -5591, -5056, 4458, 6055, -3103, -6749, + 1591, 7106, 0, -7106, -1591, 6749, 3103, -6055, -4458, 5056, + 5591, -3804, -6442, 2362, 6971, -801, -7151, -801, 6971, 2362, + -6442, -3804, 5591, 5056, -4458, -6055, 3103, 6749, -1591, -7106, + 5056, 267, -7131, -801, 7071, 1329, -6971, -1851, 6833, 2362, + -6656, -2859, 6442, 3341, -6193, -3804, 5908, 4246, -5591, -4664, + 5242, 5056, -4864, -5420, 4458, 5753, -4028, -6055, 3575, 6322, + -3103, -6554, 2612, 6749, -2108, -6907, 1591, 7026, -1066, -7106, + 534, 7146, 5056, -267, -7131, 801, 7071, -1329, -6971, 1851, + 6833, -2362, -6656, 2859, 6442, -3341, -6193, 3804, 5908, -4246, + -5591, 4664, 5242, -5056, -4864, 5420, 4458, -5753, -4028, 6055, + 3575, -6322, -3103, 6554, 2612, -6749, -2108, 6907, 1591, -7026, + -1066, 7106, 534, -7146, 5056, -801, -6971, 2362, 6442, -3804, + -5591, 5056, 4458, -6055, -3103, 6749, 1591, -7106, 0, 7106, + -1591, -6749, 3103, 6055, -4458, -5056, 5591, 3804, -6442, -2362, + 6971, 801, -7151, 801, 6971, -2362, -6442, 3804, 5591, -5056, + -4458, 6055, 3103, -6749, -1591, 7106, 5056, -1329, -6656, 3804, + 5242, -5753, -3103, 6907, 534, -7106, 2108, 6322, -4458, -4664, + 6193, 2362, -7071, 267, 6971, -2859, -5908, 5056, 4028, -6554, + -1591, 7146, -1066, -6749, 3575, 5420, -5591, -3341, 6833, 801, + -7131, 1851, 6442, -4246, -4864, 6055, 2612, -7026, 5056, -1851, + -6193, 5056, 3575, -6907, 0, 6907, -3575, -5056, 6193, 1851, + -7151, 1851, 6193, -5056, -3575, 6907, 0, -6907, 3575, 5056, + -6193, -1851, 7151, -1851, -6193, 5056, 3575, -6907, 0, 6907, + -3575, -5056, 6193, 1851, -7151, 1851, 6193, -5056, -3575, 6907, + 5056, -2362, -5591, 6055, 1591, -7106, 3103, 5056, -6442, -801, + 6971, -3804, -4458, 6749, 0, -6749, 4458, 3804, -6971, 801, + 6442, -5056, -3103, 7106, -1591, -6055, 5591, 2362, -7151, 2362, + 5591, -6055, -1591, 7106, -3103, -5056, 6442, 801, -6971, 3804, + 4458, -6749, 5056, -2859, -4864, 6749, -534, -6322, 5591, 1851, + -7071, 3804, 4028, -7026, 1591, 5753, -6193, -801, 6833, -4664, + -3103, 7146, -2612, -5056, 6656, -267, -6442, 5420, 2108, -7106, + 3575, 4246, -6971, 1329, 5908, -6055, -1066, 6907, -4458, -3341, + 7131, -2362, -5242, 6554, 5056, -3341, -4028, 7106, -2612, -4664, + 6971, -1851, -5242, 6749, -1066, -5753, 6442, -267, -6193, 6055, + 534, -6554, 5591, 1329, -6833, 5056, 2108, -7026, 4458, 2859, + -7131, 3804, 3575, -7146, 3103, 4246, -7071, 2362, 4864, -6907, + 1591, 5420, -6656, 801, 5908, -6322, 5056, -3804, -3103, 7106, + -4458, -2362, 6971, -5056, -1591, 6749, -5591, -801, 6442, -6055, + 0, 6055, -6442, 801, 5591, -6749, 1591, 5056, -6971, 2362, + 4458, -7106, 3103, 3804, -7151, 3804, 3103, -7106, 4458, 2362, + -6971, 5056, 1591, -6749, 5591, 801, -6442, 6055, 5056, -4246, + -2108, 6749, -5908, 267, 5591, -6907, 2612, 3804, -7131, 4664, + 1591, -6554, 6193, -801, -5242, 7026, -3103, -3341, 7071, -5056, + -1066, 6322, -6442, 1329, 4864, -7106, 3575, 2859, -6971, 5420, + 534, -6055, 6656, -1851, -4458, 7146, -4028, -2362, 6833, -5753, + 5056, -4664, -1066, 6055, -6833, 2859, 3103, -6907, 5908, -801, + -4864, 7146, -4458, -1329, 6193, -6749, 2612, 3341, -6971, 5753, + -534, -5056, 7131, -4246, -1591, 6322, -6656, 2362, 3575, -7026, + 5591, -267, -5242, 7106, -4028, -1851, 6442, -6554, 2108, 3804, + -7071, 5420, 5056, -5056, 0, 5056, -7151, 5056, 0, -5056, + 7151, -5056, 0, 5056, -7151, 5056, 0, -5056, 7151, -5056, + 0, 5056, -7151, 5056, 0, -5056, 7151, -5056, 0, 5056, + -7151, 5056, 0, -5056, 7151, -5056, 0, 5056, -7151, 5056, + 0, -5056, 7151, -5056, 5056, -5420, 1066, 3804, -6833, 6554, + -3103, -1851, 5908, -7106, 4864, -267, -4458, 7026, -6193, 2362, + 2612, -6322, 6971, -4246, -534, 5056, -7131, 5753, -1591, -3341, + 6656, -6749, 3575, 1329, -5591, 7146, -5242, 801, 4028, -6907, + 6442, -2859, -2108, 6055, -7071, 4664, 5056, -5753, 2108, 2362, + -5908, 7146, -5591, 1851, 2612, -6055, 7131, -5420, 1591, 2859, + -6193, 7106, -5242, 1329, 3103, -6322, 7071, -5056, 1066, 3341, + -6442, 7026, -4864, 801, 3575, -6554, 6971, -4664, 534, 3804, + -6656, 6907, -4458, 267, 4028, -6749, 6833, -4246, 5056, -6055, + 3103, 801, -4458, 6749, -6971, 5056, -1591, -2362, 5591, -7106, + 6442, -3804, 0, 3804, -6442, 7106, -5591, 2362, 1591, -5056, + 6971, -6749, 4458, -801, -3103, 6055, -7151, 6055, -3103, -801, + 4458, -6749, 6971, -5056, 1591, 2362, -5591, 7106, -6442, 3804, + 5056, -6322, 4028, -801, -2612, 5420, -6971, 6907, -5242, 2362, + 1066, -4246, 6442, -7146, 6193, -3804, 534, 2859, -5591, 7026, + -6833, 5056, -2108, -1329, 4458, -6554, 7131, -6055, 3575, -267, + -3103, 5753, -7071, 6749, -4864, 1851, 1591, -4664, 6656, -7106, + 5908, -3341, 5056, -6554, 4864, -2362, -534, 3341, -5591, 6907, + -7071, 6055, -4028, 1329, 1591, -4246, 6193, -7106, 6833, -5420, + 3103, -267, -2612, 5056, -6656, 7146, -6442, 4664, -2108, -801, + 3575, -5753, 6971, -7026, 5908, -3804, 1066, 1851, -4458, 6322, + -7131, 6749, -5242, 2859, 5056, -6749, 5591, -3804, 1591, 801, + -3103, 5056, -6442, 7106, -6971, 6055, -4458, 2362, 0, -2362, + 4458, -6055, 6971, -7106, 6442, -5056, 3103, -801, -1591, 3804, + -5591, 6749, -7151, 6749, -5591, 3804, -1591, -801, 3103, -5056, + 6442, -7106, 6971, -6055, 4458, -2362, 5056, -6907, 6193, -5056, + 3575, -1851, 0, 1851, -3575, 5056, -6193, 6907, -7151, 6907, + -6193, 5056, -3575, 1851, 0, -1851, 3575, -5056, 6193, -6907, + 7151, -6907, 6193, -5056, 3575, -1851, 0, 1851, -3575, 5056, + -6193, 6907, -7151, 6907, -6193, 5056, -3575, 1851, 5056, -7026, + 6656, -6055, 5242, -4246, 3103, -1851, 534, 801, -2108, 3341, + -4458, 5420, -6193, 6749, -7071, 7146, -6971, 6554, -5908, 5056, + -4028, 2859, -1591, 267, 1066, -2362, 3575, -4664, 5591, -6322, + 6833, -7106, 7131, -6907, 6442, -5753, 4864, -3804, 2612, -1329, + 5056, -7106, 6971, -6749, 6442, -6055, 5591, -5056, 4458, -3804, + 3103, -2362, 1591, -801, 0, 801, -1591, 2362, -3103, 3804, + -4458, 5056, -5591, 6055, -6442, 6749, -6971, 7106, -7151, 7106, + -6971, 6749, -6442, 6055, -5591, 5056, -4458, 3804, -3103, 2362, + -1591, 801, 5056, -7146, 7131, -7106, 7071, -7026, 6971, -6907, + 6833, -6749, 6656, -6554, 6442, -6322, 6193, -6055, 5908, -5753, + 5591, -5420, 5242, -5056, 4864, -4664, 4458, -4246, 4028, -3804, + 3575, -3341, 3103, -2859, 2612, -2362, 2108, -1851, 1591, -1329, + 1066, -801, 534, -267, +}; diff --git a/test/cmocka/src/math/fft/CMakeLists.txt b/test/cmocka/src/math/fft/CMakeLists.txt new file mode 100644 index 000000000000..97ac2ee8438f --- /dev/null +++ b/test/cmocka/src/math/fft/CMakeLists.txt @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(fft + fft.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_common.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_16.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_16_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_32.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_32_hifi3.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/comp_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/buffers/audio_buffer.c + ${PROJECT_SOURCE_DIR}/src/audio/source_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_api_helper.c + ${PROJECT_SOURCE_DIR}/src/audio/sink_source_utils.c + ${PROJECT_SOURCE_DIR}/src/audio/audio_stream.c + ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c + ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c + ${PROJECT_SOURCE_DIR}/src/ipc/ipc-helper.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-graph.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-params.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c + ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c + ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c +) + +cmocka_test(dft3 + dft3.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_multi.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_multi_generic.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_multi_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_32.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_common.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c +) + +cmocka_test(fft_multi + fft_multi.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_multi.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_multi_generic.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_multi_hifi3.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_common.c + ${PROJECT_SOURCE_DIR}/src/math/fft/fft_32.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c +) diff --git a/test/cmocka/src/math/fft/dft3.c b/test/cmocka/src/math/fft/dft3.c new file mode 100644 index 000000000000..a787d8329993 --- /dev/null +++ b/test/cmocka/src/math/fft/dft3.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/fft.h> +#include "ref_dft3_32.h" + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <cmocka.h> +#include <math.h> + +#define SOFM_DFT3_MAX_ERROR_ABS 3.1 +#define SOFM_DFT3_MAX_ERROR_RMS 1.1 +#define DFT_SIZE 3 + +static void dft3_32_test(const int32_t *in_real, const int32_t *in_imag, + const int32_t *ref_real, const int32_t *ref_imag, int num_tests) + +{ + struct icomplex32 x[DFT_SIZE]; + struct icomplex32 y[DFT_SIZE]; + double delta; + double error_rms; + double delta_max = 0; + double sum_squares = 0; + const int32_t *p_in_real = in_real; + const int32_t *p_in_imag = in_imag; + const int32_t *p_ref_real = ref_real; + const int32_t *p_ref_imag = ref_imag; + int i, j; + + for (i = 0; i < num_tests; i++) { + for (j = 0; j < DFT_SIZE; j++) { + x[j].real = *p_in_real++; + x[j].imag = *p_in_imag++; + } + + dft3_32(x, y); + + for (j = 0; j < DFT_SIZE; j++) { + delta = (double)*p_ref_real - (double)y[j].real; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + + delta = (double)*p_ref_imag - (double)y[j].imag; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + + p_ref_real++; + p_ref_imag++; + } + } + + error_rms = sqrt(sum_squares / (double)(2 * DFT_SIZE * num_tests)); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, SOFM_DFT3_MAX_ERROR_ABS, error_rms, SOFM_DFT3_MAX_ERROR_RMS); + + assert_true(error_rms < SOFM_DFT3_MAX_ERROR_RMS); + assert_true(delta_max < SOFM_DFT3_MAX_ERROR_ABS); +} + +static void dft3_32_test_1(void **state) +{ + (void)state; + + dft3_32_test(input_data_real_q31, input_data_imag_q31, + ref_data_real_q31, ref_data_imag_q31, + REF_SOFM_DFT3_NUM_TESTS); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(dft3_32_test_1), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/fft/fft.c b/test/cmocka/src/math/fft/fft.c new file mode 100644 index 000000000000..dc3dc8e70524 --- /dev/null +++ b/test/cmocka/src/math/fft/fft.c @@ -0,0 +1,841 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Keyon Jie <yang.jie@linux.intel.com> + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <math.h> +#include <cmocka.h> +#include <stdbool.h> + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/buffer.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/fft.h> + +#include "input.h" + +/* SNR DB threshold */ +#define FFT_DB_TH_16 27.0 +#define FFT_DB_TH 95.0 +#define SINE_HZ 1000 + +/* For rectangular window frequency matched sine wave test */ +#define TWO_PI 6.28318530717959 +#define SINE_SCALE_S16 32767.0 +#define SINE_SCALE_S32 2147483647.0 +#define SINE_FS 48000.0 +#define SINE_BASE (SINE_FS / 256.0) /* One perid exactly 256 samples, 187.5 Hz */ +#define SINE_FREQ (4.0 * SINE_BASE) /* Four periods, 1125 Hz */ +#define MIN_SNR_256_16 49.0 +#define MIN_SNR_512_16 42.0 +#define MIN_SNR_1024_16 38.0 +#define MIN_SNR_256 132.0 +#define MIN_SNR_512 125.0 +#define MIN_SNR_1024 119.0 + +struct processing_module dummy; + +/** + * \brief Doing Fast Fourier Transform (FFT) for mono real input buffers. + * \param[in] src - pointer to input buffer. + * \param[out] dst - pointer to output buffer, FFT output for input buffer. + * \param[in] size - input buffer sample count. + */ +static void fft_real(struct comp_buffer *src, struct comp_buffer *dst, uint32_t size) +{ + struct icomplex32 *inb; + struct icomplex32 *outb; + struct fft_plan *plan; + int i; + + if (audio_stream_get_channels(&src->stream) != 1) + return; + + if (src->stream.size < size * sizeof(int32_t) || + dst->stream.size < size * sizeof(struct icomplex32)) + return; + + inb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex32)); + if (!inb) + return; + outb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex32)); + if (!outb) + goto err_outb; + + plan = mod_fft_plan_new(&dummy, inb, outb, size, 32); + if (!plan) + goto err_plan; + + for (i = 0; i < size; i++) { + inb[i].real = *((int32_t *)src->stream.addr + i); + inb[i].imag = 0; + } + + /* perform a single FFT transform */ + fft_execute_32(plan, false); + + for (i = 0; i < size; i++) { + *((int32_t *)dst->stream.addr + 2 * i) = outb[i].real; + *((int32_t *)dst->stream.addr + 2 * i + 1) = outb[i].imag; + } + + mod_fft_plan_free(&dummy, plan); + +err_plan: + rfree(outb); +err_outb: + rfree(inb); +} + +/** + * \brief Doing Inverse Fast Fourier Transform (IFFT) for mono complex input buffers. + * \param[in] src - pointer to input buffer. + * \param[out] dst - pointer to output buffer, FFT output for input buffer. + * \param[in] size - input buffer sample count. + */ +static void ifft_complex(struct comp_buffer *src, struct comp_buffer *dst, uint32_t size) +{ + struct icomplex32 *inb; + struct icomplex32 *outb; + struct fft_plan *plan; + int i; + + if (audio_stream_get_channels(&src->stream) != 1) + return; + + if (src->stream.size < size * sizeof(struct icomplex32) || + dst->stream.size < size * sizeof(struct icomplex32)) + return; + + inb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex32)); + if (!inb) + return; + + outb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex32)); + if (!outb) + goto err_outb; + + plan = mod_fft_plan_new(&dummy, inb, outb, size, 32); + if (!plan) + goto err_plan; + + for (i = 0; i < size; i++) { + inb[i].real = *((int32_t *)src->stream.addr + 2 * i); + inb[i].imag = *((int32_t *)src->stream.addr + 2 * i + 1); + } + + /* perform a single IFFT transform */ + fft_execute_32(plan, true); + + for (i = 0; i < size; i++) { + *((int32_t *)dst->stream.addr + 2 * i) = outb[i].real; + *((int32_t *)dst->stream.addr + 2 * i + 1) = outb[i].imag; + } + + mod_fft_plan_free(&dummy, plan); + +err_plan: + rfree(outb); +err_outb: + rfree(inb); +} + +/** + * \brief Doing Fast Fourier Transform (FFT) for 2 real input buffers. + * \param[in] src - pointer to input buffer (2 channels). + * \param[out] dst1 - pointer to output buffer, FFT output for input buffer 1. + * \param[out] dst2 - pointer to output buffer, FFT output for input buffer 2. + * \param[in] size - input buffer sample count. + */ +static void fft_real_2(struct comp_buffer *src, struct comp_buffer *dst1, + struct comp_buffer *dst2, uint32_t size) +{ + struct icomplex32 *inb; + struct icomplex32 *outb; + struct fft_plan *plan; + int i; + + if (audio_stream_get_channels(&src->stream) != 2) + return; + + if (src->stream.size < size * sizeof(int32_t) * 2 || + dst1->stream.size < size * sizeof(struct icomplex32) || + dst2->stream.size < size * sizeof(struct icomplex32)) + return; + + inb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex32)); + if (!inb) + return; + + outb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex32)); + if (!outb) + goto err_outb; + + plan = mod_fft_plan_new(&dummy, inb, outb, size, 32); + if (!plan) + goto err_plan; + + /* generate complex inputs */ + for (i = 0; i < size; i++) { + inb[i].real = *((int32_t *)src->stream.addr + 2 * i); + inb[i].imag = *((int32_t *)src->stream.addr + 2 * i + 1); + } + + /* perform a single FFT transform */ + fft_execute_32(plan, false); + + /* calculate the outputs */ + *((int32_t *)dst1->stream.addr) = outb[0].real; + *((int32_t *)dst1->stream.addr + 1) = 0; + *((int32_t *)dst2->stream.addr) = 0; + *((int32_t *)dst2->stream.addr + 1) = -outb[0].imag; + for (i = 1; i < size; i++) { + *((int32_t *)dst1->stream.addr + 2 * i) = + (outb[i].real + outb[size - i].real) / 2; + *((int32_t *)dst1->stream.addr + 2 * i + 1) = + (outb[i].imag - outb[size - i].imag) / 2; + *((int32_t *)dst2->stream.addr + 2 * i) = + (outb[i].imag + outb[size - i].imag) / 2; + *((int32_t *)dst2->stream.addr + 2 * i + 1) = + (outb[size - i].real - outb[i].real) / 2; + } + + mod_fft_plan_free(&dummy, plan); + +err_plan: + rfree(outb); +err_outb: + rfree(inb); +} + +static int power_peak_index_32(struct icomplex32 *out, int fft_size) +{ + int64_t p; + int64_t peak = 0; + int i; + int r = 0; + + /* looking for the peak */ + for (i = 0; i < fft_size / 2; i++) { + p = (int64_t)out[i].real * out[i].real + (int64_t)out[i].imag * out[i].imag; + if (p > peak) { + peak = p; + r = i; + } + } + + return r; +} + +static double integrate_power_32(struct icomplex32 *s, int start_idx, int end_idx) +{ + double energy = 0; + int i; + + for (i = start_idx; i <= end_idx; i++) + energy += (double)s[i].real * s[i].real + (double)s[i].imag * s[i].imag; + + return energy; +} + +static void get_sine_32(int32_t *in, double sine_freq, double fs, int fft_size) +{ + double c = TWO_PI * sine_freq / fs; + double w; + int i; + + for (i = 0; i < fft_size; i++) { + w = c * i; + in[i] = (int32_t)round(SINE_SCALE_S32 * sin(w)); + } +} + +static void test_math_fft_256(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 256 * 2 * sizeof(int32_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex32 *out = (struct icomplex32 *)sink->stream.addr; + int32_t *in = (int32_t *)source->stream.addr; + int fft_size = 256; + int r; + int i; + double signal; + double noise; + double snr; + + (void)state; + + /* create sine wave */ + get_sine_32(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real(source, sink, fft_size); + + /* find peak */ + r = power_peak_index_32(out, fft_size); + i = (int)round((SINE_FREQ * fft_size) / SINE_FS); + printf("%s: peak at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* the min. SNR should be met */ + noise = integrate_power_32(out, 0, i - 2); + signal = integrate_power_32(out, i - 1, i + 1); + noise += integrate_power_32(out, i + 2, fft_size / 2 - 1); + snr = 10 * log10(signal / noise); + printf("%s: SNR %5.2f dB\n", __func__, snr); + assert_int_equal(snr < MIN_SNR_256, 0); + + buffer_free(source); + buffer_free(sink); +} + +static void test_math_fft_512(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 512 * 2 * sizeof(int32_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex32 *out = (struct icomplex32 *)sink->stream.addr; + int32_t *in = (int32_t *)source->stream.addr; + int fft_size = 512; + int r; + int i; + double signal; + double noise; + double snr; + + (void)state; + + /* create sine wave */ + get_sine_32(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real(source, sink, fft_size); + + /* find peak */ + r = power_peak_index_32(out, fft_size); + i = (int)round((SINE_FREQ * fft_size) / SINE_FS); + printf("%s: peak at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* the min. SNR should be met */ + noise = integrate_power_32(out, 0, i - 2); + signal = integrate_power_32(out, i - 1, i + 1); + noise += integrate_power_32(out, i + 2, fft_size / 2 - 1); + snr = 10 * log10(signal / noise); + printf("%s: SNR %5.2f dB\n", __func__, snr); + assert_int_equal(snr < MIN_SNR_512, 0); + + buffer_free(source); + buffer_free(sink); +} + +static void test_math_fft_1024(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 1024 * 2 * sizeof(int32_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex32 *out = (struct icomplex32 *)sink->stream.addr; + int32_t *in = (int32_t *)source->stream.addr; + int fft_size = 1024; + int r; + int i; + double signal; + double noise; + double snr; + + (void)state; + + /* create sine wave */ + get_sine_32(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real(source, sink, fft_size); + + /* find peak */ + r = power_peak_index_32(out, fft_size); + i = (int)round((SINE_FREQ * fft_size) / SINE_FS); + printf("%s: peak at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* the min. SNR should be met */ + noise = integrate_power_32(out, 0, i - 2); + signal = integrate_power_32(out, i - 1, i + 1); + noise += integrate_power_32(out, i + 2, fft_size / 2 - 1); + snr = 10 * log10(signal / noise); + printf("%s: SNR %5.2f dB\n", __func__, snr); + assert_int_equal(snr < MIN_SNR_1024, 0); + + buffer_free(source); + buffer_free(sink); +} + +static void test_math_fft_1024_ifft(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 1024 * 4 * 2, + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *intm = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex32 *out = (struct icomplex32 *)sink->stream.addr; + float db; + int64_t signal = 0; + int64_t noise = 0; + uint32_t fft_size = 1024; + int32_t *in = (int32_t *)source->stream.addr; + int i; + + (void)state; + + get_sine_32(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real(source, intm, fft_size); + + audio_stream_set_channels(&intm->stream, 1); + /* do ifft transform */ + ifft_complex(intm, sink, fft_size); + + /* calculate signal and noise */ + for (i = 0; i < fft_size; i++) { + signal += (int64_t)(in[i] / 32) * (in[i] / 32); + noise += (int64_t)((out[i].real - in[i]) / 32) * + ((out[i].real - in[i]) / 32) + + (int64_t)(out[i].imag / 32) * (out[i].imag / 32); + } + + db = 10 * log10((float)signal / noise); + printf("%s: SNR: %6.2f dB\n", __func__, db); + assert_int_equal(db < FFT_DB_TH, 0); + + buffer_free(source); + buffer_free(intm); + buffer_free(sink); +} + +static void test_math_fft_512_2ch(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 512 * 4 * 2, + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink1 = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink2 = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex32 *out1 = (struct icomplex32 *)sink1->stream.addr; + struct icomplex32 *out2 = (struct icomplex32 *)sink2->stream.addr; + uint32_t fft_size = 512; + int i; + int r; + + (void)state; + + for (i = 0; i < fft_size; i++) { + *((int32_t *)source->stream.addr + 2 * i) = input_samples[i]; + *((int32_t *)source->stream.addr + 2 * i + 1) = input_samples[fft_size + i]; + } + + audio_stream_set_channels(&source->stream, 2); + /* do fft transform */ + fft_real_2(source, sink1, sink2, fft_size); + + /* looking for the peak for channel 0 */ + r = power_peak_index_32(out1, fft_size); + i = (SINE_HZ * fft_size) / 48000; + printf("%s: peak for channel 0 at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* looking for the peak for channel 1 */ + r = power_peak_index_32(out2, fft_size); + i = (SINE_HZ * fft_size) / 48000; + printf("%s: peak for channel 1 at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + buffer_free(source); + buffer_free(sink1); + buffer_free(sink2); +} + +/** + * \brief Doing Fast Fourier Transform (FFT) for mono real input buffers. + * \param[in] src - pointer to input buffer. + * \param[out] dst - pointer to output buffer, FFT output for input buffer. + * \param[in] size - input buffer sample count. + */ +static void fft_real_16(struct comp_buffer *src, struct comp_buffer *dst, uint32_t size) +{ + struct icomplex16 *inb; + struct icomplex16 *outb; + struct fft_plan *plan; + int i; + + if (audio_stream_get_channels(&src->stream) != 1) + return; + + if (src->stream.size < size * sizeof(int16_t) || + dst->stream.size < size * sizeof(struct icomplex16)) + return; + + inb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex16)); + if (!inb) + return; + outb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex16)); + if (!outb) + goto err_outb; + + plan = mod_fft_plan_new(&dummy, inb, outb, size, 16); + if (!plan) + goto err_plan; + + for (i = 0; i < size; i++) { + inb[i].real = *((int16_t *)src->stream.addr + i); + inb[i].imag = 0; + } + + /* perform a single FFT transform */ + fft_execute_16(plan, false); + + for (i = 0; i < size; i++) { + *((int16_t *)dst->stream.addr + 2 * i) = outb[i].real; + *((int16_t *)dst->stream.addr + 2 * i + 1) = outb[i].imag; + } + + mod_fft_plan_free(&dummy, plan); + +err_plan: + rfree(outb); +err_outb: + rfree(inb); +} + +/** + * \brief Doing Inverse Fast Fourier Transform (IFFT) for mono complex input buffers. + * \param[in] src - pointer to input buffer. + * \param[out] dst - pointer to output buffer, FFT output for input buffer. + * \param[in] size - input buffer sample count. + */ +static void ifft_complex_16(struct comp_buffer *src, struct comp_buffer *dst, uint32_t size) +{ + struct icomplex16 *inb; + struct icomplex16 *outb; + struct fft_plan *plan; + int i; + + if (audio_stream_get_channels(&src->stream) != 1) + return; + + if (src->stream.size < size * sizeof(struct icomplex16) || + dst->stream.size < size * sizeof(struct icomplex16)) + return; + + inb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex16)); + if (!inb) + return; + + outb = rzalloc(SOF_MEM_FLAG_USER, + size * sizeof(struct icomplex16)); + if (!outb) + goto err_outb; + + plan = mod_fft_plan_new(&dummy, inb, outb, size, 16); + if (!plan) + goto err_plan; + + for (i = 0; i < size; i++) { + inb[i].real = *((int16_t *)src->stream.addr + 2 * i); + inb[i].imag = *((int16_t *)src->stream.addr + 2 * i + 1); + } + + /* perform a single IFFT transform */ + fft_execute_16(plan, true); + + for (i = 0; i < size; i++) { + *((int16_t *)dst->stream.addr + 2 * i) = outb[i].real; + *((int16_t *)dst->stream.addr + 2 * i + 1) = outb[i].imag; + } + + mod_fft_plan_free(&dummy, plan); + +err_plan: + rfree(outb); +err_outb: + rfree(inb); +} + +static int power_peak_index_16(struct icomplex16 *out, int fft_size) +{ + int32_t p; + int32_t peak = 0; + int i; + int r = 0; + + /* looking for the peak */ + for (i = 0; i < fft_size / 2; i++) { + p = (int32_t)out[i].real * out[i].real + (int32_t)out[i].imag * out[i].imag; + if (p > peak) { + peak = p; + r = i; + } + } + + return r; +} + +static double integrate_power_16(struct icomplex16 *s, int start_idx, int end_idx) +{ + double energy = 0; + int i; + + for (i = start_idx; i <= end_idx; i++) + energy += (double)s[i].real * s[i].real + (double)s[i].imag * s[i].imag; + + return energy; +} + +static void get_sine_16(int16_t *in, double sine_freq, double fs, int fft_size) +{ + double c = TWO_PI * sine_freq / fs; + double w; + int i; + + for (i = 0; i < fft_size; i++) { + w = c * i; + in[i] = (int16_t)round(SINE_SCALE_S16 * sin(w)); + } +} + +static void test_math_fft_256_16(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 256 * 2 * sizeof(int16_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex16 *out = (struct icomplex16 *)sink->stream.addr; + int16_t *in = (int16_t *)source->stream.addr; + int fft_size = 256; + int r; + int i; + double signal; + double noise; + double snr; + + (void)state; + + /* create sine wave */ + get_sine_16(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real_16(source, sink, fft_size); + + /* find peak */ + r = power_peak_index_16(out, fft_size); + i = (int)round((SINE_FREQ * fft_size) / SINE_FS); + printf("%s: peak at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* the min. SNR should be met */ + noise = integrate_power_16(out, 0, i - 2); + signal = integrate_power_16(out, i - 1, i + 1); + noise += integrate_power_16(out, i + 2, fft_size / 2 - 1); + snr = 10 * log10(signal / noise); + printf("%s: SNR %5.2f dB\n", __func__, snr); + assert_int_equal(snr < MIN_SNR_256_16, 0); + + buffer_free(source); + buffer_free(sink); +} + +static void test_math_fft_512_16(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 512 * 2 * sizeof(int16_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex16 *out = (struct icomplex16 *)sink->stream.addr; + int16_t *in = (int16_t *)source->stream.addr; + int fft_size = 512; + int r; + int i; + double signal; + double noise; + double snr; + + (void)state; + + /* create sine wave */ + get_sine_16(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real_16(source, sink, fft_size); + + /* find peak */ + r = power_peak_index_16(out, fft_size); + i = (int)round((SINE_FREQ * fft_size) / SINE_FS); + printf("%s: peak at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* the min. SNR should be met */ + noise = integrate_power_16(out, 0, i - 2); + signal = integrate_power_16(out, i - 1, i + 1); + noise += integrate_power_16(out, i + 2, fft_size / 2 - 1); + snr = 10 * log10(signal / noise); + printf("%s: SNR %5.2f dB\n", __func__, snr); + assert_int_equal(snr < MIN_SNR_512_16, 0); + + buffer_free(source); + buffer_free(sink); +} + +static void test_math_fft_1024_16(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 1024 * 2 * sizeof(int16_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex16 *out = (struct icomplex16 *)sink->stream.addr; + int16_t *in = (int16_t *)source->stream.addr; + int fft_size = 1024; + int r; + int i; + double signal; + double noise; + double snr; + + (void)state; + + /* create sine wave */ + get_sine_16(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real_16(source, sink, fft_size); + + /* find peak */ + r = power_peak_index_16(out, fft_size); + i = (int)round((SINE_FREQ * fft_size) / SINE_FS); + printf("%s: peak at point %d\n", __func__, r); + + /* the peak should be in range i +/-1 */ + assert_in_range(r, i - 1, i + 1); + + /* the min. SNR should be met */ + noise = integrate_power_16(out, 0, i - 2); + signal = integrate_power_16(out, i - 1, i + 1); + noise += integrate_power_16(out, i + 2, fft_size / 2 - 1); + snr = 10 * log10(signal / noise); + printf("%s: SNR %5.2f dB\n", __func__, snr); + assert_int_equal(snr < MIN_SNR_1024_16, 0); + + buffer_free(source); + buffer_free(sink); +} + +static void test_math_fft_1024_ifft_16(void **state) +{ + struct sof_ipc_buffer test_buf_desc = { + .size = 1024 * 2 * sizeof(int16_t), + }; + struct comp_buffer *source = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *intm = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct comp_buffer *sink = buffer_new(NULL, &test_buf_desc, BUFFER_USAGE_NOT_SHARED); + struct icomplex16 *out = (struct icomplex16 *)sink->stream.addr; + float db; + int64_t signal = 0; + int64_t noise = 0; + uint32_t fft_size = 1024; + int16_t *in = (int16_t *)source->stream.addr; + int i; + + (void)state; + + get_sine_16(in, SINE_FREQ, SINE_FS, fft_size); + audio_stream_set_channels(&source->stream, 1); + + /* do fft transform */ + fft_real_16(source, intm, fft_size); + + audio_stream_set_channels(&intm->stream, 1); + /* do ifft transform */ + ifft_complex_16(intm, sink, fft_size); + + /* calculate signal and noise */ + for (i = 0; i < fft_size; i++) { + signal += (int64_t)in[i] * in[i]; + noise += (int64_t)(out[i].real - in[i]) * (out[i].real - in[i]) + + (int64_t)out[i].imag * out[i].imag; + } + + db = 10 * log10((float)signal / noise); + printf("%s: SNR: %6.2f dB\n", __func__, db); + assert_int_equal(db < FFT_DB_TH_16, 0); + + buffer_free(source); + buffer_free(intm); + buffer_free(sink); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_fft_256_16), + cmocka_unit_test(test_math_fft_512_16), + cmocka_unit_test(test_math_fft_1024_16), + cmocka_unit_test(test_math_fft_1024_ifft_16), + cmocka_unit_test(test_math_fft_256), + cmocka_unit_test(test_math_fft_512), + cmocka_unit_test(test_math_fft_1024), + cmocka_unit_test(test_math_fft_1024_ifft), + cmocka_unit_test(test_math_fft_512_2ch), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/fft/fft_multi.c b/test/cmocka/src/math/fft/fft_multi.c new file mode 100644 index 000000000000..bf5bd49efb08 --- /dev/null +++ b/test/cmocka/src/math/fft/fft_multi.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/format.h> +#include <sof/math/icomplex16.h> +#include <sof/math/icomplex32.h> +#include <sof/math/fft.h> +#include "ref_fft_multi_96_32.h" +#include "ref_fft_multi_512_32.h" +#include "ref_fft_multi_768_32.h" +#include "ref_fft_multi_1024_32.h" +#include "ref_fft_multi_1536_32.h" +#include "ref_fft_multi_3072_32.h" + +#include "ref_ifft_multi_24_32.h" +#include "ref_ifft_multi_256_32.h" +#include "ref_ifft_multi_1024_32.h" +#include "ref_ifft_multi_1536_32.h" +#include "ref_ifft_multi_3072_32.h" + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <cmocka.h> +#include <math.h> + +#define FFT_MAX_ERROR_ABS 1050.0 /* about -126 dB */ +#define FFT_MAX_ERROR_RMS 35.0 /* about -156 dB */ +#define IFFT_MAX_ERROR_ABS 2400000.0 /* about -59 dB */ +#define IFFT_MAX_ERROR_RMS 44000.0 /* about -94 dB */ + +struct processing_module dummy; + +static void fft_multi_32_test(const int32_t *in_real, const int32_t *in_imag, + const int32_t *ref_real, const int32_t *ref_imag, + int num_bins, int num_tests, double max_error_abs, + double max_error_rms, bool do_ifft) +{ + struct icomplex32 *x; + struct icomplex32 *y; + struct fft_multi_plan *plan; + double delta; + double error_rms; + double delta_max = 0; + double sum_squares = 0; + const int32_t *p_in_real = in_real; + const int32_t *p_in_imag = in_imag; + const int32_t *p_ref_real = ref_real; + const int32_t *p_ref_imag = ref_imag; + int i, j; + FILE *fh1, *fh2; + + x = malloc(num_bins * sizeof(struct icomplex32)); + if (!x) { + fprintf(stderr, "Failed to allocate input data buffer.\n"); + assert_true(false); + } + + y = malloc(num_bins * sizeof(struct icomplex32)); + if (!y) { + fprintf(stderr, "Failed to allocate output data buffer.\n"); + assert_true(false); + } + + plan = mod_fft_multi_plan_new(&dummy, x, y, num_bins, 32); + if (!plan) { + fprintf(stderr, "Failed to allocate FFT plan.\n"); + assert_true(false); + } + + fh1 = fopen("debug_fft_multi_in.txt", "w"); + fh2 = fopen("debug_fft_multi_out.txt", "w"); + + for (i = 0; i < num_tests; i++) { + for (j = 0; j < num_bins; j++) { + x[j].real = *p_in_real++; + x[j].imag = *p_in_imag++; + fprintf(fh1, "%d %d\n", x[j].real, x[j].imag); + } + + fft_multi_execute_32(plan, do_ifft); + + for (j = 0; j < num_bins; j++) { + fprintf(fh2, "%d %d %d %d\n", + y[j].real, y[j].imag, *p_ref_real, *p_ref_imag); + delta = (double)*p_ref_real - (double)y[j].real; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + + delta = (double)*p_ref_imag - (double)y[j].imag; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + + p_ref_real++; + p_ref_imag++; + } + + } + + mod_fft_multi_plan_free(&dummy, plan); + free(y); + free(x); + fclose(fh1); fclose(fh2); + + error_rms = sqrt(sum_squares / (double)(2 * num_bins * num_tests)); + printf("Max absolute error = %5.2f (limit %5.2f), error RMS = %5.2f (limit %5.2f)\n", + delta_max, max_error_abs, error_rms, max_error_rms); + + assert_true(error_rms < max_error_rms); + assert_true(delta_max < max_error_abs); +} + +static void fft_multi_32_test_1(void **state) +{ + (void)state; + + /* Test FFT */ + fft_multi_32_test(fft_in_real_96_q31, fft_in_imag_96_q31, + fft_ref_real_96_q31, fft_ref_imag_96_q31, + 96, REF_SOFM_FFT_MULTI_96_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + fft_multi_32_test(fft_in_real_512_q31, fft_in_imag_512_q31, + fft_ref_real_512_q31, fft_ref_imag_512_q31, + 512, REF_SOFM_FFT_MULTI_512_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + fft_multi_32_test(fft_in_real_768_q31, fft_in_imag_768_q31, + fft_ref_real_768_q31, fft_ref_imag_768_q31, + 768, REF_SOFM_FFT_MULTI_768_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + fft_multi_32_test(fft_in_real_1024_q31, fft_in_imag_1024_q31, + fft_ref_real_1024_q31, fft_ref_imag_1024_q31, + 1024, REF_SOFM_FFT_MULTI_1024_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + fft_multi_32_test(fft_in_real_1536_q31, fft_in_imag_1536_q31, + fft_ref_real_1536_q31, fft_ref_imag_1536_q31, + 1536, REF_SOFM_FFT_MULTI_1536_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + fft_multi_32_test(fft_in_real_3072_q31, fft_in_imag_3072_q31, + fft_ref_real_3072_q31, fft_ref_imag_3072_q31, + 3072, REF_SOFM_FFT_MULTI_3072_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + fft_multi_32_test(fft_in_real_3072_q31, fft_in_imag_3072_q31, + fft_ref_real_3072_q31, fft_ref_imag_3072_q31, + 3072, REF_SOFM_FFT_MULTI_3072_NUM_TESTS, + FFT_MAX_ERROR_ABS, FFT_MAX_ERROR_RMS, false); + + /* Test IFFT */ + fft_multi_32_test(ifft_in_real_24_q31, ifft_in_imag_24_q31, + ifft_ref_real_24_q31, ifft_ref_imag_24_q31, + 24, REF_SOFM_IFFT_MULTI_24_NUM_TESTS, + IFFT_MAX_ERROR_ABS, IFFT_MAX_ERROR_RMS, true); + fft_multi_32_test(ifft_in_real_256_q31, ifft_in_imag_256_q31, + ifft_ref_real_256_q31, ifft_ref_imag_256_q31, + 256, REF_SOFM_IFFT_MULTI_256_NUM_TESTS, + IFFT_MAX_ERROR_ABS, IFFT_MAX_ERROR_RMS, true); + fft_multi_32_test(ifft_in_real_1024_q31, ifft_in_imag_1024_q31, + ifft_ref_real_1024_q31, ifft_ref_imag_1024_q31, + 1024, REF_SOFM_IFFT_MULTI_1024_NUM_TESTS, + IFFT_MAX_ERROR_ABS, IFFT_MAX_ERROR_RMS, true); + fft_multi_32_test(ifft_in_real_1536_q31, ifft_in_imag_1536_q31, + ifft_ref_real_1536_q31, ifft_ref_imag_1536_q31, + 1536, REF_SOFM_IFFT_MULTI_1536_NUM_TESTS, + IFFT_MAX_ERROR_ABS, IFFT_MAX_ERROR_RMS, true); + fft_multi_32_test(ifft_in_real_3072_q31, ifft_in_imag_3072_q31, + ifft_ref_real_3072_q31, ifft_ref_imag_3072_q31, + 3072, REF_SOFM_IFFT_MULTI_3072_NUM_TESTS, + IFFT_MAX_ERROR_ABS, IFFT_MAX_ERROR_RMS, true); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(fft_multi_32_test_1), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/fft/input.h b/test/cmocka/src/math/fft/input.h new file mode 100644 index 000000000000..05b050266121 --- /dev/null +++ b/test/cmocka/src/math/fft/input.h @@ -0,0 +1,1035 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + */ + +/* Input samples for FFT cmocka test */ + +/* sine wave samples, freq = 1000Hz */ +int input_samples[FFT_SIZE_MAX] = { +0, +279466742, +554180337, +819468480, +1070819172, +1303957463, +1514918156, +1700113250, +1856392962, +1981099300, +2072111269, +2127880946, +2147459804, +2130514848, +2077334276, +1988822580, +1866485157, +1712402714, +1529195871, +1319980594, +1088315199, +838139832, +573709453, +299521473, +20239257, +-259387187, +-534601995, +-800724338, +-1053228029, +-1287818508, +-1500505878, +-1687672772, +-1846135871, +-1973200047, +-2066704205, +-2125058033, +-2147269054, +-2132959506, +-2082372763, +-1996369201, +-1876411561, +-1724540073, +-1543337753, +-1335886476, +-1105714555, +-856736735, +-593187609, +-319549599, +-40476716, +239284591, +514976167, +781909071, +1035543332, +1271565160, +1485960316, +1675082385, +1835714795, +1965125524, +2061113564, +2122046360, +2146887571, +2135214701, +2087226281, +2003738493, +1886171291, +1736524248, +1557342547, +1351673697, +1123015695, +875257538, +612613075, +339549341, +60710580, +-219160741, +-495304595, +-763024350, +-1017766652, +-1255198866, +-1471282763, +-1662343208, +-1825130661, +-1956876446, +-2055339843, +-2118846195, +-2146315390, +-2137280235, +-2091894399, +-2010929801, +-1895763480, +-1748354174, +-1571209009, +-1367340855, +-1140217083, +-893700596, +-631984125, +-359518922, +-80939051, +199017424, +475589028, +744071854, +999899569, +1238721077, +1456474522, +1649456372, +1814384408, +1948453548, +2049383555, +2115457821, +2145552560, +2139155923, +2096376704, +2017942488, +1905187277, +1760028802, +1584935907, +1382886557, +1157317190, +912064270, +651299038, +379456568, +101160333, +-178856429, +-455831216, +-725053264, +-981943668, +-1222133257, +-1441536908, +-1636423021, +-1803476991, +-1939857576, +-2043245229, +-2111881541, +-2144599150, +-2140841599, +-2100672796, +-2024775928, +-1914441843, +-1771547094, +-1598522022, +-1398309424, +-1174314497, +-930346929, +-670556100, +-399360509, +-121372629, +158679547, +436032915, +705970271, +963900546, +1205436881, +1426471249, +1623244314, +1792409378, +1931089296, +2036925410, +2108117670, +2143455244, +2142337113, +2104782294, +2031429517, +1923526358, +1782908027, +1611966148, +1413608084, +1191207495, +948546950, +689753598, +419228976, +141574144, +-138488570, +-416195882, +-686824570, +-945771804, +-1188633431, +-1411278882, +-1609921421, +-1781182553, +-1922149484, +-2030424660, +-2104166545, +-2142120944, +-2143642332, +-2108704833, +-2037902662, +-1932440015, +-1794110592, +-1625267088, +-1428781180, +-1207994683, +-966662715, +-708889829, +-439060206, +-161763083, +118285292, +396321881, +667617861, +927559053, +1171724400, +1395961157, +1596455526, +1769797514, +1913038936, +2023743555, +2100028515, +2140596369, +2144757141, +2112440065, +2044194789, +1941182020, +1805153793, +1638423664, +1443827363, +1224674570, +984692615, +727963092, +458852435, +181937654, +-98071507, +-376412676, +-648351850, +-909263911, +-1154711289, +-1380519435, +-1582847824, +-1758255271, +-1903758462, +-2016882690, +-2095703949, +-2138881653, +-2145681439, +-2115987658, +-2050305338, +-1949751599, +-1816036651, +-1651434705, +-1458745297, +-1241245674, +-1002635050, +-746971693, +-478603906, +-202096064, +77849011, +356470036, +629028249, +890888003, +1137595610, +1364955087, +1569099524, +1746556849, +1894308884, +2009842674, +2091193230, +2136976950, +2146415146, +2119347297, +2056233768, +1958147990, +1826758197, +1664299056, +1473533657, +1257706524, +1020488424, +765913944, +498312865, +222236523, +-57619599, +-336495732, +-609648774, +-872432962, +-1120378883, +-1349269496, +-1555211848, +-1734703288, +-1884691043, +-2002624132, +-2086496759, +-2134882427, +-2146958196, +-2122518682, +-2061979551, +-1966370446, +-1837317480, +-1677015574, +-1488191129, +-1274055656, +-1038251153, +-784788162, +-517977561, +-242357241, +37385070, +316491539, +590215147, +853900426, +1103062638, +1333464055, +1541186029, +1722695641, +1874905792, +1995227705, +2081614954, +2132598273, +2147310541, +2125501534, +2067542177, +1974418238, +1847713562, +1689583130, +1502716412, +1290291620, +1055921658, +803592671, +537596247, +262456432, +-17147220, +-296459233, +-570729093, +-835292041, +-1085648413, +-1317540168, +-1527023313, +-1710534974, +-1864954002, +-1987654050, +-2076548247, +-2130124688, +-2147472149, +-2128295586, +-2072921152, +-1982290651, +-1857945519, +-1702000608, +-1517108214, +-1306412973, +-1073498371, +-822325799, +-557167181, +-282532310, +-3092153, +276400594, +551192344, +816609461, +1068137753, +1301499250, +1512724957, +1698222367, +1854836556, +1979903841, +2071297090, +2127461894, +2147443006, +2130900591, +2078115998, +1989986986, +1868012443, +1714266904, +1531365258, +1322418282, +1090979729, +840985884, +576688624, +302583092, +23331252, +-256317403, +-531606634, +-797854345, +-1050532216, +-1285342725, +-1498292233, +-1685758915, +-1844554352, +-1971977765, +-2065861948, +-2124610126, +-2147223115, +-2133316316, +-2083126254, +-1997506558, +-1877913439, +-1726380929, +-1545486278, +-1338306127, +-1108364180, +-859571268, +-596158842, +-322606996, +-43568278, +236211445, +511973705, +779028359, +1032833364, +1269072028, +1483726422, +1673145724, +1834108304, +1963876527, +2060243304, +2121569638, +2146812495, +2135542548, +2087951475, +2004848700, +1887647629, +1738341607, +1559470018, +1354075096, +1125650179, +878080300, +615576105, +342602245, +63801434, +-216084505, +-492295298, +-760133175, +-1015042770, +-1252688605, +-1469028818, +-1660383914, +-1823499341, +-1955600846, +-2054441657, +-2118340700, +-2146211183, +-2137579089, +-2092591232, +-2012012760, +-1897214146, +-1750147875, +-1573315237, +-1369723788, +-1142836192, +-896511335, +-634938690, +-362567062, +-84028923, +195938372, +472573164, +741170471, +997162015, +1236193911, +1454200726, +1647474619, +1812728403, +1947151456, +2048457523, +2114923598, +2145419232, +2139425758, +2097045112, +2018998101, +1906612142, +1761798685, +1587020705, +1385250813, +1159920691, +914862738, +654244876, +382499673, +104248948, +-175774834, +-452809052, +-722141933, +-979192685, +-1219589411, +-1439243464, +-1634418986, +-1801796449, +-1938529110, +-2042291433, +-2111318637, +-2144436713, +-2141082391, +-2101312721, +-2025804103, +-1915840781, +-1773293002, +-1600585205, +-1400654792, +-1176902160, +-933132876, +-673492948, +-402398309, +-124459714, +155595682, +433004720, +703049250, +961136378, +1202876580, +1424158359, +1621218174, +1790704448, +1929734573, +2035943935, +2107526136, +2143263712, +2142548840, +2105393679, +2032430162, +1924899245, +1784629804, +1614007532, +1415934356, +1193779089, +951320129, +692681197, +422261201, +144659423, +-135402710, +-413161925, +-683894118, +-942994697, +-1186056903, +-1408946753, +-1607873357, +-1779453387, +-1920768625, +-2029415593, +-2103546433, +-2141900334, +-2143824976, +-2109287624, +-2038875688, +-1933786727, +-1795808086, +-1627286493, +-1431088150, +-1210549980, +-969422880, +-711807917, +-442086586, +-164846284, +115197710, +393282431, +664678238, +924769254, +1169131873, +1393609996, +1594385719, +1768044264, +1911632063, +2022706986, +2099379881, +2140346700, +2144910685, +2112994210, +2045140110, +1942502440, +1806826853, +1640420909, +1446114825, +1227213343, +987439521, +730871411, +461872702, +185018501, +-94982478, +-373368004, +-645403318, +-906461668, +-1152102994, +-1378149450, +-1580756458, +-1756478094, +-1902325699, +-2015818711, +-2095026849, +-2138602948, +-2145805870, +-2116513108, +-2051222870, +-1951045608, +-1817685128, +-1653409614, +-1461013049, +-1243767698, +-1005368452, +-749869984, +-481617792, +-205174285, +74758809, +353420411, +626071070, +888073564, +1134971779, +1362566490, +1566986785, +1744755903, +1892850360, +2008751379, +2090487725, +2136669233, +2146510453, +2119844004, +2057123429, +1959415473, +1828381946, +1666251453, +1475781497, +1260211574, +1023208080, +768801950, +501320102, +225311843, +-54528500, +-333441426, +-606683210, +-869606577, +-1117739748, +-1346862498, +-1553077924, +-1732878733, +-1883206887, +-2001505618, +-2085762912, +-2134545727, +-2147024370, +-2122986604, +-2062841263, +-1967611292, +-1838916356, +-1678945286, +-1490418857, +-1276543511, +-1040956821, +-787665626, +-520977881, +-245429388, +34293346, +313432823, +587241461, +851062346, +1100408434, +1331038870, +1539031109, +1720847638, +1873396136, +1994082072, +2080852829, +2132232618, +2147347576, +2125940628, +2068375863, +1975632336, +1849287422, +1691489985, +1504923830, +1292762058, +1058613099, +806459337, +540589384, +265525133, +-14055147, +-293396379, +-567747550, +-832442518, +-1082979375, +-1315097011, +-1524847589, +-1708663688, +-1863418980, +-1986481400, +-2075757913, +-2129730112, +-2147480042, +-2128705814, +-2073726737, +-1983477893, +-1859494225, +-1703884437, +-1519295127, +-1308865774, +-1076175344, +-825181414, +-560152869, +-285597292, +-6184300, +273333873, +548203208, +813748749, +1065454120, +1299038338, +1510528622, +1696327964, +1853276304, +1978704277, +2070478616, +2127038431, +2147421756, +2131281915, +2078893412, +1991147266, +1869535856, +1716127539, +1533531471, +1324853229, +1093641997, +843830194, +579666598, +305644083, +26423199, +-253247089, +-528610172, +-794982697, +-1047834225, +-1282864277, +-1496075482, +-1683841563, +-1842969009, +-1970751394, +-2065015408, +-2124157814, +-2147172725, +-2133668704, +-2083875427, +-1998639773, +-1879411424, +-1728218205, +-1547631598, +-1340723004, +-1111011506, +-862404019, +-599128838, +-325663725, +-46659750, +233137810, +508970181, +776146031, +1030121255, +1266576264, +1481489452, +1671205593, +1832498011, +1962623458, +2059368772, +2121088517, +2146732968, +2135865968, +2088672340, +2005954750, +1889120053, +1740155361, +1561594255, +1356473687, +1128282329, +880901241, +618537860, +345654439, +66892157, +-213007822, +-489284981, +-757240423, +-1012316784, +-1250175747, +-1466771827, +-1658421177, +-1821864240, +-1954321190, +-2053539212, +-2117830813, +-2146102527, +-2137873512, +-2093283725, +-2013091547, +-1898660878, +-1751937947, +-1575418203, +-1372103880, +-1145452931, +-899320216, +-637891939, +-365614450, +-87118622, +192858913, +469556320, +738267552, +994422393, +1233664182, +1451923916, +1645489450, +1811068640, +1945845328, +2047527244, +2114384991, +2145281456, +2139691157, +2097709173, +2020049529, +1908033054, +1763564914, +1589102213, +1387612196, +1162521788, +917659309, +657189357, +385541985, +107337348, +-172692874, +-449785950, +-719229105, +-976439672, +-1217043036, +-1436947036, +-1632411562, +-1800112171, +-1937196625, +-2041333403, +-2110751356, +-2144269830, +-2141318743, +-2101948290, +-2026828078, +-1917235747, +-1775035232, +-1602645069, +-1402997255, +-1179487383, +-935916889, +-676428400, +-405435275, +-127546540, +152511495, +429975627, +700126771, +958370217, +1200313785, +1421842518, +1619188673, +1788995805, +1928375849, +2034958239, +2106930233, +2143067736, +2142756125, +2106000700, +2033426593, +1926268140, +1786347881, +1616045570, +1418257692, +1196348209, +954091336, +695607359, +425292551, +147744403, +-132316569, +-410127112, +-680962247, +-940215635, +-1183477915, +-1406611703, +-1605821959, +-1777720531, +-1919383783, +-2028402319, +-2102921960, +-2141675283, +-2144003175, +-2109866042, +-2039844487, +-1935129431, +-1797501857, +-1629302524, +-1433392152, +-1213102768, +-972181035, +-714724530, +-445112050, +-167929143, +112109890, +390242166, +661737237, +921977537, +1166536922, +1391255946, +1592312606, +1766287349, +1910221227, +2021666224, +2098726893, +2140092594, +2145059782, +2113543975, +2046081191, +1943818832, +1808496168, +1642414754, +1448399289, +1229749572, +990184379, +733778214, +464892012, +188098965, +-91893252, +-370322557, +-642453448, +-903657544, +-1149492310, +-1375776608, +-1578661815, +-1754697275, +-1900888993, +-2014750553, +-2094345406, +-2138319810, +-2145925852, +-2117034170, +-2052136150, +-1952335572, +-1819329837, +-1655381095, +-1463277771, +-1246287143, +-1008099770, +-752766721, +-484630679, +-208252080, +71668452, +350370054, +623112592, +885257283, +1132345594, +1360175067, +1564870798, +1742951339, +1891387912, +2007655920, +2089777886, +2136357087, +2146601309, +2120336317, +2058008826, +1960678895, +1830001904, +1668200395, +1478026276, +1262714012, +1025925615, +771688362, +504326299, +228386697, +-51437287, +-330386429, +-603716387, +-866778388, +-1115098296, +-1344452707, +-1550940780, +-1731050584, +-1881718827, +-2000382955, +-2085024740, +-2134204601, +-2147086092, +-2123450124, +-2063698698, +-1968848058, +-1840511418, +-1680871517, +-1492643495, +-1279028719, +-1043660331, +-790541457, +-523977121, +-248501027, +31201552, +310373457, +584266557, +848222501, +1097751949, +1328610925, +1536872998, +1718996067, +1871882596, +1992932305, +2080086390, +2131862543, +2147380159, +2126375315, +2069205260, +1976842337, +1850857449, +1693393333, +1507128128, +1295229815, +1061302344, +809324332, +543581401, +268593284, +-10963046, +-290332916, +-564764829, +-829591270, +-1080308093, +-1312651128, +-1522668703, +-1706788859, +-1861880094, +-1985304631, +-2074963275, +-2129331120, +-2147483482, +-2129111628, +-2074528023, +-1984661022, +-1861039075, +-1705764733, +-1521478889, +-1311315862, +-1078850085, +-828035318, +-563137397, +-288661682, +-9276435, +270266586, +545212936, +810886350, +1062768278, +1296574733, +1508329155, +1694430044, +1851712209, +1977500611, +2069655850, +2126610558, +2147396054, +}; diff --git a/test/cmocka/src/math/fft/ref_dft3.m b/test/cmocka/src/math/fft/ref_dft3.m new file mode 100644 index 000000000000..c3f55d91b3e3 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_dft3.m @@ -0,0 +1,59 @@ +% ref_dft3 - Generate C header files for DFT3 function unit tests + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2025 Intel Corporation. All rights reserved. + +function ref_dft3() + + path(path(), '../../../m'); + opt.describe = export_get_git_describe(); + + N = 3; + num_tests = 100; + scale_q31 = 2^31; + opt.bits = 32; + min_int32 = int32(-2^31); + max_int32 = int32(2^31 - 1); + + % Random values + input_data_real_q31 = int32((2 * rand(N, num_tests) - 1) * scale_q31); + input_data_imag_q31 = int32((2 * rand(N, num_tests) - 1) * scale_q31); + + % Apply max and min values to first two tests + input_data_real_q31(:,1) = [max_int32 max_int32 max_int32]; + input_data_imag_q31(:,1) = [max_int32 max_int32 max_int32]; + input_data_real_q31(:,2) = [min_int32 min_int32 min_int32]; + input_data_imag_q31(:,2) = [min_int32 min_int32 min_int32]; + + % Convert to float for reference DFT + input_data_real_f = double(input_data_real_q31) / scale_q31; + input_data_imag_f = double(input_data_imag_q31) / scale_q31; + input_data_f = complex(input_data_real_f, input_data_imag_f); + + ref_data_f = zeros(N, num_tests); + for i = 1:num_tests + ref_data_f(:,i) = fft(1/N * input_data_f(:,i)); + end + + input_data_vec_f = reshape(input_data_f, N * num_tests, 1); + input_data_real_q31 = int32(real(input_data_vec_f) * scale_q31); + input_data_imag_q31 = int32(imag(input_data_vec_f) * scale_q31); + + ref_data_vec_f = reshape(ref_data_f, N * num_tests, 1); + ref_data_real_q31 = int32(real(ref_data_vec_f) * scale_q31); + ref_data_imag_q31 = int32(imag(ref_data_vec_f) * scale_q31); + + header_fn = sprintf('ref_dft3_32.h'); + fh = export_headerfile_open(header_fn); + comment = sprintf('Created %s with script ref_dft3.m %s', ... + datestr(now, 0), opt.describe); + export_comment(fh, comment); + export_ndefine(fh, 'REF_SOFM_DFT3_NUM_TESTS', num_tests); + export_vector(fh, opt.bits, 'input_data_real_q31', input_data_real_q31); + export_vector(fh, opt.bits, 'input_data_imag_q31', input_data_imag_q31); + export_vector(fh, opt.bits, 'ref_data_real_q31', ref_data_real_q31); + export_vector(fh, opt.bits, 'ref_data_imag_q31', ref_data_imag_q31); + fclose(fh); + fprintf(1, 'Exported %s.\n', header_fn); +end diff --git a/test/cmocka/src/math/fft/ref_dft3_32.h b/test/cmocka/src/math/fft/ref_dft3_32.h new file mode 100644 index 000000000000..dc29c737e552 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_dft3_32.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 18-Nov-2025 10:04:16 with script ref_dft3.m v1.9-rc1-6866-g7082edfc2-dirty */ + +#define REF_SOFM_DFT3_NUM_TESTS 100 + +static const int32_t input_data_real_q31[300] = { + 2147483647, 2147483647, 2147483647, -2147483648, -2147483648, -2147483648, + 1162219834, 23816319, -504635601, -893753638, 2096234199, 1926797429, + -1498879994, -1344377511, -1565629944, 470700317, 1534215118, 250204116, + -1513962524, 328839298, -891150595, 1037032885, 2053083918, 214745934, + -1132393293, -684253779, 1290308737, 1492556115, 1767631432, -1476198666, + -1980706125, -152724048, 1304919915, -333340349, -945811108, 555573004, + 508704347, -91940743, -1172534471, 808237431, -864171862, -1701987975, + 667143603, 466065800, -680587634, -1210890266, -1609079348, 376693582, + -1989200673, -866348502, -1518045121, -810592170, -2014026366, 308045234, + -893653199, -71890004, 1798867597, -1165288212, -195853850, 727803849, + -827203566, -763401435, -555032730, 2049556353, -1733329582, 1857973403, + -969720479, 474304971, -118122188, -1414917124, 755553858, 512336983, + -412624469, -654030354, -673412294, -480554119, 2141467418, 982286252, + -333493549, -1792914214, -751632737, 1453631035, -567352454, -1121160722, + 1835418889, 1469373494, 1260799356, 1916321534, 1046738218, -482282675, + -1777733492, 1417780825, -1905923885, 1720942739, -1698447345, 1524731616, + -940329093, 474359626, 869280780, -1587738164, 718005895, -1275483558, + 1311357743, -1127231201, 1170568884, 351336134, 912933315, 929235364, + -1766156248, -751021719, -1575099846, -500683117, 758133192, -1000251215, + -460549792, -872077348, 1190236123, -2094039372, -97472255, 1766680277, + 1682916204, 1878420776, -1937130520, -1305433548, -2023614346, -961620965, + -1144745178, 349170968, -990207654, 2066179435, -409481891, -1640628527, + -1748672103, 1509049194, 2136386712, 749103155, 1869393346, -473447757, + 188132091, 471958830, 565514557, 24038287, 250957039, 555942787, + -1417341343, 1310588913, -1980667608, 1978973460, -1886552564, -931043047, + 240691726, 366351147, 856435514, -2100179945, 1322815981, -1993386310, + -1907183049, 1018981874, -1982669624, -392347504, 283140809, -701932511, + 827970927, 1087003102, 1539141719, 575668370, -284136687, -166908907, + 1086613743, -1578737459, 1755161659, -363056680, -972520979, 1833561918, + -691836837, 2043720743, -142353127, 1166774227, 991149245, -1806872349, + -1973652264, 1188981112, 1911685701, -968798985, 2077908949, -166982863, + 1326781679, -1986923452, -1067800528, 1854266938, 1333307796, -241964941, + -267584968, 886003675, -805272619, 1479927684, 159424368, 139369932, + -313191797, -791964593, 123256824, 1761190835, 267191061, -1066245064, + 2059356024, 983929284, -988243656, -2128354307, 1321996812, 279274571, + -958912371, 115946572, 1492522503, -1102123606, -1958076794, -1473281696, + -511493535, -162111044, -1652434912, 515681118, 1328854757, 1615582785, + 838101882, -981669826, -85699769, 826563860, -1054635732, 276608854, + -285946678, 1081455066, 1239400031, 344174895, -152045930, -1779441010, + -1443541302, -626187735, -7031089, -314268939, 575767023, -18068620, + 857747866, -1026238975, 1741588511, -825216518, -657754491, -1800153864, + 902250246, 1007864270, 1984210739, 1594306126, -365683058, -306799624, + 728125587, -1705315469, -445468326, 1860359390, 1561088340, 996962395, + 636780028, 1069385362, 49149330, -1167618105, -2051885175, 1699344213, + -450653472, 28073512, 1407413309, -1332191163, 1302508825, 589871272, + -769422448, -1945782013, -1273023036, -2144421096, -981418969, 1126299923, + -1473462655, -1468616147, 1514904515, 1873597062, 977229454, -190860952, + -1450912250, -1515509653, -1706549902, -1798566387, -1488199231, 465976855, + 1507852161, 1334015424, -1930050220, -839537711, -519449681, 1802561273, + -1686609113, -988247120, -2018183481, -1422312120, -524629977, 777771469, +}; + +static const int32_t input_data_imag_q31[300] = { + 2147483647, 2147483647, 2147483647, -2147483648, -2147483648, -2147483648, + -447071638, -710569404, -521054814, -1525984216, 1485866355, -1887906218, + 694991588, -1423316381, -526983997, 1416498079, -9059322, -1894876350, + 529729352, -1667720604, -1765426014, 1622805049, 1403298661, -56966777, + 1372247161, -989865104, 226982867, 1200666007, -1172962658, -327728731, + -1770194241, 2063801732, -1222401122, -1437089259, 7163116, -1667845557, + 699401620, -767508329, 1458191154, 2102543710, -386800992, 984597551, + -1002742709, -1568629571, -502851595, -51793840, -709663670, 1748043151, + 1096459944, 1109269442, 1991276284, 1630095127, -412134472, -1039994124, + -769839143, -2071887810, -1473927075, 143017106, 792574136, 1214806759, + -1707309285, -1546417474, 1644851668, 1369929054, -1504595449, -504861820, + 941716193, 1798841734, 1004503064, -548152154, 1433124598, 75564731, + -837059818, -1634446222, 1096996669, 760853936, 158476524, 1288109053, + -545735405, -1072909043, 1216016240, 1728999756, 1301464866, 1708661027, + 424731640, -179953738, 1829344056, -325009476, 1191455307, 1243675521, + 206426657, -785131901, 513197679, -1441381381, -1879255156, -626702268, + 1196431670, -484279907, 2027499180, 947791638, -1004082133, 1126341198, + -762028151, -776494670, -1745568389, -1969907879, 894288459, 106735650, + -272461269, -337916005, -1243196237, -395332730, 1275277656, -1472977807, + -938816844, 1834539458, 1332936891, 878083108, -45073545, -1185953597, + -717818068, -30126320, 1482293565, -1904955333, -932393894, -2110646291, + -525568699, -1934721075, -841727840, 199552072, 402812734, 545621043, + 2041424330, 636650031, 262616779, 2027512409, -1473662400, -2131440924, + 86104846, 858180945, -1162684732, -1853469689, -1511760166, -2140871371, + -16978023, 1565504329, 1807701041, 838301612, -432147051, 1812146715, + 358112650, -1258170956, 688314303, -938717727, 1479050461, -808626808, + -1801201683, -567689961, 409371332, -1131239726, -219900330, 1662293964, + -1591338732, -1898978738, -1394863666, -1673116723, -1385225905, -506268616, + 1968110246, -124595511, 1787454593, 579998873, -556710560, 1912851650, + -99737218, -2012489847, 248120965, 283176403, 1573201156, -759852424, + -1562343755, 1375885975, -1557867556, 135286679, 920363352, 1029195101, + 1429284623, 1861442578, 1690850333, -2039742677, -452522368, 94467724, + 603284320, 370872395, -1416940658, 1020409603, -181807657, -1585188066, + -131317730, 1841147202, 751515590, 1429723577, -1685642094, 1194135059, + 782914220, 1896122751, 1008900429, 937134356, 54677423, -1294082603, + -1394821557, -1413641053, -1995302037, 1412674184, -2090278821, -818075169, + 412258694, -646997248, -1371284669, -943407015, -277753547, -1009224290, + -714869328, 759608215, 1616359360, -754310245, 1178040373, -1748780178, + -283459899, 863462232, 844805157, 302181273, -1799234263, 299774378, + 902067000, 2019733716, -779964295, -1476250288, 174210071, 1848240816, + -417614345, -1449712719, -232573863, -1033791826, -1734572491, 2059952961, + 164824306, -1192574723, -794465893, -2100496663, 1966082659, 662383049, + -1724169177, 1397272869, 443158715, -1466228413, -1048441604, -721618311, + 607147167, 405920890, 1890695467, 1700845925, -861572606, -193465319, + -699440151, -1445722888, -1602829412, 2051117803, -720439151, -1947113131, + -390310420, -1650048864, 841983379, 476615869, -1467229630, 43603884, + -1704704811, -1363183779, 1599254898, 174995960, 1261823464, -2010724063, + -1013060202, 983314876, -1374232138, 2105244869, -1751771177, -2066157313, + -200819569, 997385318, 1618215010, -2057992268, 1973711259, -518966102, + 1974013954, -1632849536, -1429309305, -817476773, -724148800, -1290709464, +}; + +static const int32_t ref_data_real_q31[300] = { + 2147483647, 0, 0, -2147483648, 0, 0, + 227133517, 412835009, 522251308, 1043092663, 5501101, -1942347402, + -1469629150, -273374294, 244123449, 751706517, 403885384, -684891584, + -692091274, -382730503, -439140748, 1101620912, 389248308, -453836336, + -175446112, -829747342, -127199839, 594662960, 204948560, 692944595, + -276170086, 96377032, -1800913071, -241192818, 437459588, -529607120, + -251923622, -262190113, 1022818082, -585974135, 301217124, 1092994442, + 150873923, -49528761, 565798441, -814425344, -907711308, 511246386, + -1457864765, -520281398, -11054510, -838857767, 195380268, -167114671, + 277774798, -758330394, -413097603, -211112738, -598975796, -355199678, + -715212577, -977235544, 865244555, 724733391, 373813241, 951009721, + -204512565, -153298134, -611909779, -49008761, -291060404, -1074847959, + -580022372, -704800693, 872198596, 881066517, -1006907140, -354713496, + -959346833, -347829172, 973682456, -78294047, 648415134, 883509948, + 1521863913, -423256823, 736811799, 826925692, 529623244, 559772598, + -755292184, -886016120, -136425188, 515742337, 241019328, 964181075, + 134437104, -1262471265, 187705067, -715071942, -1051333353, 178667131, + 451565142, 709643787, 150148814, 731168271, 37430845, -417262982, + -1364092604, 60300071, -462363715, -247600380, 666811647, -919894384, + -47463672, -61742871, -351343248, -141610450, -646870758, -1305558164, + 541402153, 134159011, 1007355039, -1430222953, 402526872, -277737467, + -595260621, -590262248, 40777691, 5356339, 989186340, 1071636756, + 632254601, -1082489253, -1298437451, 715016248, 206927757, -172840850, + 408535159, 473172137, -693575205, 276979371, 55138220, -308079304, + -695806679, -430683500, -290851163, -279540717, 481385284, 1777128893, + 487826129, -685469096, 438334693, -923583425, 72097283, -1248693804, + -956956933, -757166358, -193059758, -270379735, -604326575, 482358807, + 1151371916, -307225981, -16175008, 41540925, 13330609, 520796836, + 421012648, -219160773, 884761869, 165994753, -977426920, 448375487, + 403176926, -1200089012, 105075249, 117017041, 1198373149, -148615963, + 375671516, -327760195, -2021563586, 314042367, -672837696, -610003656, + -575980767, 1000626962, 902135484, 981869931, 278296065, 594100942, + -62284637, 413447008, -618747339, 592907328, 848631206, 38389150, + -327299855, 321603581, -307495523, 320712277, -111080778, 1551559336, + 685013884, 943290093, 431052047, -175694308, -586976517, -1365683482, + 216518901, -419804573, -755626699, -1511160699, -162735014, 571772107, + -775346497, 341010250, -77157288, 1153372887, -107688469, -530003300, + -76422571, 209939474, 704584979, 16178994, 1250092749, -439707883, + 678302806, -476738909, -487510576, -529104015, -169292147, 1042571057, + -692253375, 432559237, -1183847163, 81143155, -680957097, 285545004, + 524365801, -184666690, 518048756, -1094374958, -960805926, 1229964365, + 1298108418, -312853206, -83004966, 307274481, 1019861483, 267170162, + -474219403, 876601527, 325743463, 1472803375, 99432249, 288123766, + 585104907, -402779940, 454455062, -506719689, -523315169, -137583247, + 328277783, -344112881, -434818374, 186729645, -405350128, -1113570680, + -1329409166, -439394384, 999381102, -666513381, -1175093926, -302813790, + -475724762, -1354051330, 356313437, 886655188, 1438174035, -451232161, + -1557657268, 733937711, -627192692, -940262921, -338396273, -519907193, + 303939122, 422738425, 781174615, 147857960, 225876137, -1213271808, + -1564346571, -119888274, -2374267, -389723543, -352742313, -679846265, +}; + +static const int32_t ref_data_imag_q31[300] = { + 2147483647, 0, 0, -2147483648, 0, 0, + -559565285, -96304105, 208797753, -642674693, -490566944, -392742579, + -418436263, 492843850, 620584002, -162479198, 418826590, 1160150687, + -967805755, 396586807, 1100948300, 989712311, -214136096, 847228834, + 203121641, 1154569860, 14555660, -100008461, -286075856, 1586750324, + -309597877, -309512615, -1151083749, -1032590567, 231162914, -635661607, + 463361482, -193920471, 429960609, 900113423, 359358464, 843071823, + -1024741292, -320011043, 342009626, 328861880, 382915408, -763571128, + 1399001890, -339399582, 36857636, 59322177, 1455710807, 115062143, + -1438551343, 874397302, -205685102, 716799334, -20254103, -553528124, + -536291697, -525357930, -645659658, -213176072, 1828272435, -245167310, + 1248353664, -324337725, 17700255, 320179058, -504376270, -363954942, + -458169790, -195040098, -183849930, 735813171, -322106397, 347147162, + -134209403, 94829069, -506355072, 1579708550, -85225073, 234516279, + 691373986, -193531340, -73111006, 703373784, -955581942, -72801318, + -21835855, -845339649, 1073602161, -1315779602, 867650731, -993252510, + 913216981, 255611262, 27603427, 356683568, -279916801, 871024871, + -1094697070, 829652208, -496983289, -322961257, -818767315, -828179307, + -617857837, -65192580, 410589148, -197677627, -606429407, 408774304, + 742886502, -245513054, -1436190292, -117648011, 1036000043, -40268923, + 244783059, -1582755347, 620154220, -1649331839, 178759335, -434382829, + -1100672538, -99093384, 674197223, 382661950, -446956360, 263846482, + 980230380, 711693717, 349500233, -525863638, 600368053, 1953007994, + -72799647, 106459459, 52445034, -1835367075, 78990495, -97093109, + 1118742449, -1517964155, 382243683, 739433759, 325265765, -226397912, + -70581334, 355822163, 72871822, -89431358, -1381948327, 532661958, + -653173437, -1440516273, 292488027, 103717969, -901845021, -333112674, + -1628393712, 149048666, -111993686, -1188203748, -208615742, -276297233, + 1210323109, 1341307345, -583520208, 645379988, 777355801, -842736915, + -621368700, -370249428, 891880910, 365508378, -848885248, 766553273, + -581441779, -281824144, -699077833, 694948377, -927875295, 368213597, + 1660525845, 149707323, -380948545, -799265774, -1074980521, -165496382, + -147594648, -112789928, 863668896, -248862040, 628846604, 640425039, + 820448354, -211681376, -740084708, 312738847, 173562512, 943422218, + 1229312467, -792516412, 346118166, -100756941, 217937665, 819953632, + -1601254882, 500599905, -294166579, -498559935, 1095565350, 815668770, + -535341074, 43580441, 904019327, -743461617, -17201447, -182743951, + 553699416, -375640095, -892928649, -441683350, 227983763, -540610658, + 474935830, -333603080, -424792649, -399092871, -119151422, 820425566, + 713945474, 272795891, -84674365, 182066866, -1000584161, -657732993, + -699966976, 940179287, -657826657, -236137119, -728609646, -69045061, + -607405437, 667961820, 104267923, 175989682, -1121244989, -1155241356, + 38754136, -517775113, -1245148200, -1078762776, -356581952, -30883685, + 967921175, -474903778, 114129770, 215269333, 1825674944, -340098353, + -1249330817, 673126435, -123235769, -205478160, 922577240, 1334018723, + -399458635, 198782896, -189634681, -315669959, 1004588949, -212303121, + -489544564, 253688105, -1468848352, -191301546, -154049902, 520347408, + -467992488, -327682427, -217385287, -570894540, 1902191749, 773947660, + 804926920, -1445127833, 439381345, -201082370, -258148124, -1598761774, + -362714962, 871047441, 1465681476, -944111679, 439288366, -312653460, +}; diff --git a/test/cmocka/src/math/fft/ref_fft_multi.m b/test/cmocka/src/math/fft/ref_fft_multi.m new file mode 100644 index 000000000000..57b1218f64dc --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi.m @@ -0,0 +1,138 @@ +% ref_sofm_dft3 - Generate C header files for DFT3 function unit tests + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2025 Intel Corporation. All rights reserved. + +function ref_fft_multi() + + rand('twister', 0); % Set seed to produce same test vectors every time + path(path(), '../../../m'); + opt.describe = export_get_git_describe(); + opt.bits = 32; + opt.fs = 48e3; + opt.ifft = 0; + opt.sine = 1; + opt.rand = 0; + opt.dc = 0; + opt.num_tests = 1; + + N = 96; + make_fft_multi_test_vectors(opt, N); + + N = 512; + make_fft_multi_test_vectors(opt, N); + + N = 768; + make_fft_multi_test_vectors(opt, N); + + N = 1024; + make_fft_multi_test_vectors(opt, N); + + N = 1536; + make_fft_multi_test_vectors(opt, N); + + N = 3072; + make_fft_multi_test_vectors(opt, N); + + opt.ifft = 1; + opt.dc = 0; + opt.sine = 1; + opt.rand = 0; + + N = 24; + make_fft_multi_test_vectors(opt, N); + + N = 256; + make_fft_multi_test_vectors(opt, N); + + N = 1024; + make_fft_multi_test_vectors(opt, N); + + N = 1536; + make_fft_multi_test_vectors(opt, N); + + N = 3072; + make_fft_multi_test_vectors(opt, N); + +end + +function make_fft_multi_test_vectors(opt, N) + + scale_q = 2^(opt.bits - 1); + min_int = int32(-scale_q); + max_int = int32(scale_q - 1); + n = 1; + + input_data_real_q = int32(zeros(N, opt.num_tests)); + input_data_imag_q = int32(zeros(N, opt.num_tests)); + + if opt.dc + input_data_real_q(:,n) = int32(ones(N, 1) * scale_q / N); + n = n + 1; + end + if opt.rand + input_data_real_q(:,n) = int32(2 * (rand(N, 1) - 1) * scale_q * 0.1); + input_data_imag_q(:,n) = int32(2 * (rand(N, 1) - 1) * scale_q * 0.1); + n = n + 1; + end + if opt.sine + ft = 997; + t = (0:(N - 1))'/opt.fs; + x = 10^(-1 / 20) * sin(2 * pi * ft * t) .* kaiser(N, 20); + dither = scale_q / 2^19 * (rand(N, 1) + rand(N, 1) - 1); + input_data_real_q(:,n) = int32(x * scale_q + dither); + if opt.ifft + tmp_fft = fft(double(input_data_real_q(:,n)) / scale_q) / N; + input_data_real_q(:,n) = int32(real(tmp_fft) * scale_q); + input_data_imag_q(:,n) = int32(imag(tmp_fft) * scale_q); + end + n = n + 1; + end + + if opt.ifft + N_half = N/2 + 1; + for i = 1:opt.num_tests + input_data_real_q(N_half + 1:end) = input_data_real_q(N_half - 1:-1:2); + input_data_imag_q(N_half + 1:end) = -input_data_imag_q(N_half - 1:-1:2); + end + end + + input_data_real_f = double(input_data_real_q) / scale_q; + input_data_imag_f = double(input_data_imag_q) / scale_q; + input_data_f = complex(input_data_real_f, input_data_imag_f); + + ref_data_f = zeros(N, opt.num_tests); + for i = 1:opt.num_tests + if opt.ifft + ref_data_f(:,i) = ifft(input_data_f(:,i)) * N; + test_type = 'ifft'; + else + ref_data_f(:,i) = fft(input_data_f(:,i)) / N; + test_type = 'fft'; + end + end + + input_data_vec_f = reshape(input_data_f, N * opt.num_tests, 1); + input_data_real_q = int32(real(input_data_vec_f) * scale_q); + input_data_imag_q = int32(imag(input_data_vec_f) * scale_q); + + ref_data_vec_f = reshape(ref_data_f, N * opt.num_tests, 1); + ref_data_real_q = int32(real(ref_data_vec_f) * scale_q); + ref_data_imag_q = int32(imag(ref_data_vec_f) * scale_q); + + header_fn = sprintf('ref_%s_multi_%d_%d.h', test_type, N, opt.bits); + fh = export_headerfile_open(header_fn); + comment = sprintf('Created %s with script ref_fft_multi.m %s', ... + datestr(now, 0), opt.describe); + export_comment(fh, comment); + dstr = sprintf('REF_SOFM_%s_MULTI_%d_NUM_TESTS', upper(test_type), N); + export_ndefine(fh, dstr, opt.num_tests); + qbits = opt.bits-1; + vstr = sprintf('%s_in_real_%d_q%d', test_type, N, qbits); export_vector(fh, opt.bits, vstr, input_data_real_q); + vstr = sprintf('%s_in_imag_%d_q%d', test_type, N, qbits); export_vector(fh, opt.bits, vstr, input_data_imag_q); + vstr = sprintf('%s_ref_real_%d_q%d', test_type, N, qbits); export_vector(fh, opt.bits, vstr, ref_data_real_q); + vstr = sprintf('%s_ref_imag_%d_q%d', test_type, N, qbits); export_vector(fh, opt.bits, vstr, ref_data_imag_q); + fclose(fh); + fprintf(1, 'Exported %s.\n', header_fn); +end diff --git a/test/cmocka/src/math/fft/ref_fft_multi_1024_32.h b/test/cmocka/src/math/fft/ref_fft_multi_1024_32.h new file mode 100644 index 000000000000..e9482fd88f05 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi_1024_32.h @@ -0,0 +1,704 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_FFT_MULTI_1024_NUM_TESTS 1 + +static const int32_t fft_in_real_1024_q31[1024] = { + -368, 399, 1137, -1510, 917, -915, + 1477, 4004, 26, -670, 19, -245, + 2071, 2623, -2126, 2311, 2688, 609, + -1461, 4166, -310, 1858, -248, -2221, + 2398, -796, -698, -2996, -2571, -2483, + -6926, -3796, -6581, -7667, -9040, -7126, + -9738, -14377, -11690, -11331, -14016, -14971, + -16347, -13087, -10581, -9389, -7947, -3776, + -2708, 3498, 9037, 13136, 16328, 23190, + 32849, 35886, 48147, 54704, 58656, 61210, + 72193, 75724, 79356, 83168, 79591, 79627, + 74772, 71013, 60544, 48856, 38174, 19894, + 7444, -19623, -39518, -64353, -90252, -120797, + -153590, -180846, -212338, -240701, -268837, -292589, + -315071, -330749, -341626, -350148, -349717, -341020, + -321991, -296385, -259725, -214521, -161010, -95406, + -24910, 56696, 146420, 244250, 343559, 452730, + 558328, 663250, 762184, 865981, 953691, 1033614, + 1102113, 1146873, 1184623, 1193892, 1178554, 1142859, + 1077203, 986336, 862134, 713246, 531955, 325661, + 92277, -163732, -444123, -741602, -1049074, -1363826, + -1673315, -1986171, -2284459, -2565083, -2814370, -3040133, + -3213891, -3347594, -3418856, -3434223, -3384851, -3262396, + -3066903, -2788032, -2437241, -2010678, -1507173, -933398, + -292175, 401186, 1147352, 1924628, 2732596, 3549354, + 4364626, 5154297, 5908401, 6604560, 7227639, 7762620, + 8187446, 8485952, 8644128, 8647068, 8487648, 8152221, + 7637666, 6938503, 6053636, 4993121, 3757798, 2362454, + 824586, -836731, -2601505, -4437764, -6320658, -8213153, + -10084097, -11885518, -13592349, -15153379, -16539412, -17701707, + -18614256, -19232046, -19532284, -19487537, -19071832, -18272835, + -17080871, -15486581, -13507411, -11145107, -8429888, -5384383, + -2046831, 1539831, 5322377, 9232369, 13214694, 17192520, + 21092853, 24835370, 28351421, 31545946, 34345883, 36680788, + 38470656, 39655664, 40177693, 39987331, 39049848, 37341196, + 34842396, 31562278, 27514832, 22737753, 17268732, 11184374, + 4553185, -2521582, -9942347, -17586988, -25318003, -33004376, + -40502110, -47661459, -54324353, -60352266, -65595404, -69912251, + -73185900, -75289166, -76129593, -75628186, -73725851, -70384308, + -65592931, -59374400, -51767812, -42836205, -32691229, -21454188, + -9277580, 3661148, 17155201, 30992883, 44929675, 58721466, + 72101400, 84812804, 96588363, 107172798, 116308292, 123771871, + 129349707, 132844569, 134111243, 133017754, 129482950, 123461622, + 114953182, 103996453, 90695125, 75177530, 57638338, 38301433, + 17446062, -4619599, -27538997, -50938883, -74412221, -97544926, + -119890697, -141021854, -160509246, -177915765, -192864953, -204975605, + -213910563, -219386073, -221174163, -219080029, -213000947, -202885489, + -188762284, -170723570, -148948541, -123686136, -95259386, -64055427, + -30526184, 4796392, 41356982, 78546374, 115716100, 152196811, + 187309768, 220376926, 250730546, 277732060, 300774553, 319307850, + 332839493, 340957166, 343321132, 339690110, 329923997, 313993109, + 291964388, 264026987, 230483360, 191744445, 148326011, 100855269, + 50040078, -3320582, -58361692, -114153996, -169724988, -224082501, + -276218832, -325139925, -369868955, -409475994, -443108525, -469982022, + -489407140, -500819525, -503770287, -497957407, -483219505, -459561117, + -427126685, -386245337, -337398907, -281210112, -218478327, -150122739, + -77193519, -857934, 77633280, 156947583, 235700971, 312486893, + 385900471, 454546040, 517078779, 572234396, 618846940, 655866323, + 682385018, 697661309, 701140616, 692455705, 671454559, 638191695, + 592953243, 536228161, 468740763, 391410722, 305371394, 211913742, + 112517115, 8779394, -97571576, -204721044, -310812944, -413944482, + -512242592, -603866176, -687055198, -760155313, -821656150, -870226938, + -904719195, -924232004, -928094286, -915902067, -887526961, -843128897, + -783147032, -708310751, -619625914, -518372450, -406053401, -284426943, + -155438894, -21198654, 116042557, 253946179, 390103902, 522103112, + 647549938, 764131222, 869639373, 962024696, 1039435602, 1100238386, + 1143082131, 1166889988, 1170916785, 1154742462, 1118300936, 1061877010, + 986124238, 892031533, 780943280, 654515630, 514699010, 363722438, + 204041308, 38296251, -130713333, -300089725, -466886857, -628155818, + -781011029, -922654557, -1050458538, -1161990550, -1255074187, -1327830448, + -1378699528, -1406489333, -1410401993, -1390048875, -1345442734, -1277046744, + -1185735381, -1072791871, -939913349, -789148010, -622904148, -443859970, + -254989459, -59453972, 139440960, 338268373, 533579021, 721939184, + 899993480, 1064547333, 1212580705, 1341356167, 1448429738, 1531710189, + 1589513254, 1620570159, 1624075071, 1599693216, 1547576100, 1468358349, + 1363160695, 1233557983, 1081585799, 909666978, 720606772, 517535787, + 303843415, 83155845, -140774037, -364089673, -582915806, -793434722, + -991929280, -1174879622, -1339004843, -1481331242, -1599239695, -1690521084, + -1753414617, -1786655673, -1789471827, -1761622946, -1703404590, -1615638103, + -1499681710, -1357368825, -1191014889, -1003370614, -797569666, -577065119, + -345612065, -107143552, 134247659, 374406599, 609174673, 834479923, + 1046391045, 1241200833, 1415476892, 1566138455, 1690498403, 1786340377, + 1851905391, 1885980406, 1887879581, 1857497280, 1795259750, 1702182967, + 1579787973, 1430138425, 1255747801, 1059596968, 845018463, 615693435, + 375556538, 128723997, -120541681, -367952127, -609245853, -840251626, + -1056983758, -1255713119, -1433002929, -1585806827, -1711487302, -1807896047, + -1873374729, -1906818169, -1907682853, -1875971972, -1812263992, -1717703065, + -1593954268, -1443193039, -1268056578, -1071600342, -857256745, -628746553, + -390033866, -145248896, 101367834, 345584281, 583192434, 810121403, + 1022514754, 1216749114, 1389559178, 1538036051, 1659720826, 1752625201, + 1815263564, 1846687542, 1846482241, 1814804568, 1752335291, 1660298657, + 1540415690, 1394895914, 1226369062, 1037859231, 832714547, 614553921, + 387208246, 154635241, -79138710, -310077686, -534233497, -747807910, + -947188843, -1129059176, -1290398152, -1428596523, -1541438634, -1627173606, + -1684538320, -1712767041, -1711595046, -1681286807, -1622597001, -1536771335, + -1425516195, -1290963285, -1135617456, -962344519, -774276536, -574780100, + -367390670, -155754790, 56472073, 265619298, 468138053, 660610367, + 839838555, 1002881515, 1147110243, 1270246183, 1370408966, 1446132923, + 1496387070, 1520594854, 1518642268, 1490871859, 1438060822, 1361413472, + 1262533951, 1143393613, 1006287680, 853798274, 688736004, 514105396, + 333012732, 148667398, -35733530, -217014467, -392110758, -558100965, + -712261129, -852105187, -975443549, -1080391668, -1165419174, -1229358286, + -1271414669, -1291210466, -1288731328, -1264359862, -1218860857, -1153341530, + -1069241701, -968310686, -852532664, -724155275, -585580585, -439357512, + -288125820, -134567565, 18641167, 168876530, 313606578, 450450547, + 577187923, 691823560, 792614885, 878071523, 947009493, 998553637, + 1032138861, 1047522337, 1044786400, 1024325396, 986827656, 933271381, + 864889514, 783149214, 689722654, 586443194, 475288458, 358321978, + 237687607, 115515445, -6047806, -124934122, -239156594, -346852125, + -446302911, -535987147, -614574458, -680951101, -734251225, -773853212, + -799381512, -810715674, -807980350, -791554564, -762030650, -720222509, + -667136883, -603952781, -532002178, -452725279, -367667954, -278430473, + -186653775, -93972100, -2008492, 87674367, 173587352, 254349650, + 328707091, 395532579, 453881657, 502968672, 542187532, 571122852, + 589545497, 597423743, 594906342, 582312760, 560132475, 529012045, + 489738788, 443207538, 390429237, 332480939, 270507669, 205698013, + 139248854, 72343880, 6161787, -58185019, -119638793, -177222667, + -230069141, -277392475, -318549855, -353017704, -380401245, -400449224, + -413034731, -418173539, -416007937, -406810636, -390947543, -368915371, + -341281976, -308709781, -271917570, -231677874, -188800752, -144107774, + -98436708, -52602612, -7411234, 36384414, 78073041, 117002200, + 152593715, 184344809, 211842274, 234752359, 252842032, 265962120, + 274065260, 277185824, 275449286, 269054677, 258286311, 243480550, + 225049447, 203437341, 179141946, 152679159, 124587493, 95420206, + 65717940, 36017421, 6836042, -21343530, -48068436, -72924828, + -95564270, -115673579, -133003852, -147361340, -158615881, -166696411, + -171587602, -173332374, -172021708, -167813897, -160892709, -151487639, + -139867533, -126332160, -111186743, -94771864, -77414398, -59468599, + -41264688, -23136882, -5393390, 11673173, 27787932, 42720560, + 56258677, 68224110, 78480457, 86924579, 93484306, 98135239, + 100882999, 101760369, 100841495, 98224064, 94030202, 88408482, + 81519998, 73548785, 64683174, 55119877, 45056490, 34697694, + 24240625, 13872761, 3766924, -5911143, -15005474, -23390680, + -30955991, -37604248, -43269353, -47895977, -51454249, -53937007, + -55362525, -55747797, -55145509, -53618025, -51236984, -48085430, + -44268219, -39886204, -35034027, -29836702, -24398794, -18829886, + -13230267, -7714345, -2360118, 2740293, 7512401, 11880497, + 15801966, 19227412, 22118471, 24467824, 26244407, 27468824, + 28135353, 28271925, 27906481, 27074587, 25818645, 24179863, + 22210583, 19974799, 17518427, 14905291, 12182096, 9415316, + 6650447, 3941996, 1322253, -1147115, -3452698, -5548001, + -7414029, -9030592, -10383149, -11471664, -12284872, -12825237, + -13105151, -13137584, -12935370, -12509734, -11898201, -11110368, + -10182305, -9134505, -7994237, -6789150, -5547559, -4288857, + -3040785, -1826870, -664203, 428580, 1435486, 2347513, + 3156311, 3844950, 4416372, 4868942, 5201790, 5414675, + 5520660, 5510424, 5404147, 5214941, 4938663, 4597616, + 4199190, 3756301, 3279832, 2777704, 2263902, 1749437, + 1241556, 754804, 295430, -138960, -532715, -883294, + -1191253, -1456374, -1673086, -1837247, -1953436, -2026864, + -2056034, -2045306, -1996661, -1918087, -1810768, -1676714, + -1527078, -1358080, -1181368, -994156, -808485, -625825, + -444558, -269900, -109532, 35633, 171250, 289167, + 391357, 477326, 547758, 597162, 631158, 651246, + 658747, 652056, 630488, 604961, 565338, 524089, + 468544, 414088, 361691, 302709, 245522, 189197, + 133521, 86065, 35459, -10093, -45678, -78284, + -107849, -127244, -147945, -159990, -166806, -172400, + -172766, -166698, -161371, -155608, -142927, -131151, + -117442, -103171, -87695, -73917, -59685, -43890, + -32345, -17413, -8851, 1262, 10615, 13688, + 22228, 26986, 33290, 32113, 31330, 36857, + 35941, 33027, 31131, 28558, 25825, 25129, + 20114, 20537, 15259, 10616, 7286, 6079, + 2197, 1142, 1303, 2290, -964, -3359, + -1473, -2972, -5153, -4402, -4875, -2764, + -2954, -2435, -6289, -2906, -1971, -1469, + -1069, -1732, -1718, -2575, -802, -2749, + 882, 1954, 1617, -292, -6, 2813, + 1640, -2041, -979, -122, -997, 1850, + 717, 1785, 1849, 1967, +}; + +static const int32_t fft_in_imag_1024_q31[1024] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static const int32_t fft_ref_real_1024_q31[1024] = { + 28, -16, 40, -36, -11, 23, + -2, 7, 65, 28, -27, 3, + 62, -17, 36, 122, -55154, 1535502, + -13543813, 57130836, -135763827, 195823639, -176199334, 98119761, + -32279433, 5635597, -409816, 6072, -21, -83, + -21, 67, -30, -1, 1, 3, + 42, -5, 77, 67, -11, -9, + 24, -27, -78, -11, 18, -61, + -28, 16, -7, 46, -11, 10, + -8, -47, 95, 12, -3, -22, + -8, -46, 24, 59, -6, 32, + 26, 18, 35, 8, 52, -23, + -67, -17, -26, -3, -10, -47, + 32, 35, -9, 38, 14, 30, + 36, 2, -7, 63, 32, -84, + 30, 19, -9, 6, 43, 11, + -2, -5, -47, -43, 4, 8, + -22, -6, -30, -63, -43, -14, + 20, 2, 86, -5, 39, -58, + 37, -42, -4, 27, 0, -16, + -30, 20, -67, -31, 40, -74, + 57, -62, -8, -6, 23, 13, + 3, 21, -51, 10, 64, -25, + 11, -3, 12, 38, -22, 18, + -5, 0, 41, -14, 30, -16, + -11, 11, -18, 36, -29, -54, + 20, -14, -6, -28, 21, 15, + 78, -17, 48, -23, -13, 16, + 27, -22, -12, -2, -85, -4, + -23, -43, 64, 6, 1, 31, + 35, 19, 23, -1, 22, 54, + 18, 6, -25, -42, 2, 41, + -18, -40, -43, 31, -26, 37, + -34, 13, 7, -16, 9, 72, + 38, 2, 44, -54, -28, -56, + 1, -58, 51, 59, 84, -48, + 39, -80, 6, 21, -6, 21, + -25, -24, -54, -67, -1, 11, + 4, -80, 3, -12, -24, -59, + -3, 57, -9, -36, -24, -28, + -31, -19, -40, -24, 4, -9, + 5, -64, -16, 25, 19, 53, + 2, -60, 48, -25, 55, -27, + 61, 17, 43, 36, -15, 6, + -98, -38, -4, 63, -14, 57, + 7, 19, -6, 12, -18, 51, + -48, 39, 4, -63, -3, -1, + -59, -15, 16, 61, -8, 12, + 5, 29, -38, 65, 29, -10, + -25, -19, 22, 17, -53, 12, + -29, 13, 7, -8, -27, 3, + 62, -4, -29, -35, 9, 40, + -69, 9, -23, 18, 21, -92, + -42, 20, -15, 5, 26, 20, + 32, 59, -17, 25, -3, 57, + -40, 9, 8, 90, -40, 16, + -119, -32, 26, -35, 18, 21, + -22, 45, 17, 29, -24, -14, + -44, -29, -59, -6, 17, -7, + -33, -37, 14, -53, 16, -17, + -59, -20, -24, -19, -58, -21, + 11, -12, 10, -13, 22, -18, + 4, -30, 53, -46, -6, -51, + 45, -21, 46, -1, 14, -22, + -33, -25, -28, 30, 1, 45, + 78, 6, -26, -6, 17, -27, + 52, -9, 20, -40, -3, 16, + 36, -21, -60, 2, 16, -56, + 13, 0, 20, -3, 46, -8, + -65, -2, -26, -27, 38, -41, + 32, -11, 6, 12, 55, -22, + 23, 47, 56, 25, -4, -27, + -14, -26, 17, -49, -5, 49, + -16, 29, -42, 51, -14, 56, + 18, -62, -31, -10, -38, -22, + -56, -60, -39, 42, 9, 90, + 29, 79, 27, 2, -27, -60, + -20, 7, 26, -6, 86, -94, + 0, -31, 7, -22, 46, 44, + 22, -64, 25, 47, -49, -24, + 62, 5, 7, -59, 40, -3, + -27, 16, 7, -32, -20, -41, + 84, -36, 21, -81, 96, 48, + 58, 16, -48, -16, -72, 29, + 36, 21, -30, -21, -55, 68, + -20, -40, -24, -40, -20, 68, + -55, -21, -30, 21, 36, 29, + -72, -16, -48, 16, 58, 48, + 96, -81, 21, -36, 84, -41, + -20, -32, 7, 16, -27, -3, + 40, -59, 7, 5, 62, -24, + -49, 47, 25, -64, 22, 44, + 46, -22, 7, -31, 0, -94, + 86, -6, 26, 7, -20, -60, + -27, 2, 27, 79, 29, 90, + 9, 42, -39, -60, -56, -22, + -38, -10, -31, -62, 18, 56, + -14, 51, -42, 29, -16, 49, + -5, -49, 17, -26, -14, -27, + -4, 25, 56, 47, 23, -22, + 55, 12, 6, -11, 32, -41, + 38, -27, -26, -2, -65, -8, + 46, -3, 20, 0, 13, -56, + 16, 2, -60, -21, 36, 16, + -3, -40, 20, -9, 52, -27, + 17, -6, -26, 6, 78, 45, + 1, 30, -28, -25, -33, -22, + 14, -1, 46, -21, 45, -51, + -6, -46, 53, -30, 4, -18, + 22, -13, 10, -12, 11, -21, + -58, -19, -24, -20, -59, -17, + 16, -53, 14, -37, -33, -7, + 17, -6, -59, -29, -44, -14, + -24, 29, 17, 45, -22, 21, + 18, -35, 26, -32, -119, 16, + -40, 90, 8, 9, -40, 57, + -3, 25, -17, 59, 32, 20, + 26, 5, -15, 20, -42, -92, + 21, 18, -23, 9, -69, 40, + 9, -35, -29, -4, 62, 3, + -27, -8, 7, 13, -29, 12, + -53, 17, 22, -19, -25, -10, + 29, 65, -38, 29, 5, 12, + -8, 61, 16, -15, -59, -1, + -3, -63, 4, 39, -48, 51, + -18, 12, -6, 19, 7, 57, + -14, 63, -4, -38, -98, 6, + -15, 36, 43, 17, 61, -27, + 55, -25, 48, -60, 2, 53, + 19, 25, -16, -64, 5, -9, + 4, -24, -40, -19, -31, -28, + -24, -36, -9, 57, -3, -59, + -24, -12, 3, -80, 4, 11, + -1, -67, -54, -24, -25, 21, + -6, 21, 6, -80, 39, -48, + 84, 59, 51, -58, 1, -56, + -28, -54, 44, 2, 38, 72, + 9, -16, 7, 13, -34, 37, + -26, 31, -43, -40, -18, 41, + 2, -42, -25, 6, 18, 54, + 22, -1, 23, 19, 35, 31, + 1, 6, 64, -43, -23, -4, + -85, -2, -12, -22, 27, 16, + -13, -23, 48, -17, 78, 15, + 21, -28, -6, -14, 20, -54, + -29, 36, -18, 11, -11, -16, + 30, -14, 41, 0, -5, 18, + -22, 38, 12, -3, 11, -25, + 64, 10, -51, 21, 3, 13, + 23, -6, -8, -62, 57, -74, + 40, -31, -67, 20, -30, -16, + 0, 27, -4, -42, 37, -58, + 39, -5, 86, 2, 20, -14, + -43, -63, -30, -6, -22, 8, + 4, -43, -47, -5, -2, 11, + 43, 6, -9, 19, 30, -84, + 32, 63, -7, 2, 36, 30, + 14, 38, -9, 35, 32, -47, + -10, -3, -26, -17, -67, -23, + 52, 8, 35, 18, 26, 32, + -6, 59, 24, -46, -8, -22, + -3, 12, 95, -47, -8, 10, + -11, 46, -7, 16, -28, -61, + 18, -11, -78, -27, 24, -9, + -11, 67, 77, -5, 42, 3, + 1, -1, -30, 67, -21, -83, + -21, 6072, -409816, 5635597, -32279433, 98119761, + -176199334, 195823639, -135763827, 57130836, -13543813, 1535502, + -55154, 122, 36, -17, 62, 3, + -27, 28, 65, 7, -2, 23, + -11, -36, 40, -16, +}; + +static const int32_t fft_ref_imag_1024_q31[1024] = { + 0, -7, -54, 77, 13, 24, + 39, -30, 30, -28, -25, 2, + 30, -15, 23, -34, 50485, -1395758, + 12235464, -51294594, 121144577, -173660896, 155294491, -85945123, + 28099645, -4875526, 352336, -5061, -5, 10, + -18, 14, -31, -55, 65, -37, + 34, -52, -5, 56, -13, -45, + -15, -15, 11, 44, -21, 3, + 55, 54, 61, -36, -27, -47, + -44, 19, -26, -13, 12, -45, + 35, 51, -67, -9, 11, -54, + 28, 92, 15, -32, -46, 10, + -8, -15, -6, 7, 14, 68, + -19, -68, 20, 27, -51, 92, + 4, -11, 39, -15, 36, -38, + 6, -8, 11, 45, 27, 13, + 24, 48, -2, 20, 6, 3, + -9, 4, 86, 10, 11, 8, + -45, 80, 28, -23, 7, 11, + 6, -50, -66, 34, 102, 95, + 8, 36, 2, -72, -22, 55, + -21, 24, -5, 1, 35, -3, + -68, -20, -2, -7, 49, -65, + -34, -15, 19, 108, 55, 9, + 16, -24, 2, -18, -18, 37, + 67, 16, 15, -11, -7, -23, + 25, -8, 8, -20, 10, 41, + 32, -9, -81, -12, -29, 47, + 5, -31, -17, -67, -17, -32, + 16, -47, 12, -30, 18, -23, + -20, 14, 21, 27, 2, -99, + -28, 22, -11, 8, -15, -44, + -8, -2, 1, -46, 61, -16, + 30, 18, 14, 8, 29, 16, + -69, 29, -43, -33, -2, 23, + 53, -71, -51, -10, -1, -29, + 33, -7, -43, -25, 47, -49, + 44, 17, -16, 55, 53, 48, + 32, 60, -15, -15, 34, -31, + -34, 36, -11, 22, 18, 7, + 49, 48, -19, -70, 50, -15, + -91, 75, 4, -14, 36, 14, + -1, 16, 2, -3, -49, 29, + 44, 64, -74, 11, 42, 11, + -12, -64, -76, -11, 2, -35, + 22, -48, -39, -31, -33, -18, + -33, 34, 8, 66, 43, 8, + -2, 39, 29, -16, 3, 28, + 8, -50, -54, 41, 14, -34, + -2, -33, 23, -8, 21, -29, + 13, 62, 9, -21, -30, 31, + 56, 44, 14, 20, 12, -8, + -2, -7, -1, 40, 30, -1, + 22, -43, 88, 68, 36, -51, + -75, 21, -61, -40, -12, -8, + -57, 5, -1, 28, -41, -17, + 22, 34, -63, -27, 24, 57, + -86, -4, -16, -53, 15, 26, + 14, -27, -23, -48, 16, -28, + -6, -37, 38, -39, -2, 32, + -56, 40, 15, -26, -73, -21, + 28, -62, 4, 76, 23, 49, + -1, -40, 51, -29, 4, 49, + 5, -3, -36, 41, 27, -16, + -11, -47, -12, 4, 2, 32, + -79, 67, -24, 45, 23, -15, + 66, -7, 60, -76, -17, -45, + -20, 17, -3, -13, 2, 9, + 19, 16, 6, -29, 23, -15, + 98, 3, 11, 22, 38, -10, + 2, -12, 20, 32, 30, 34, + 54, 47, -25, -15, -75, 38, + -10, 49, 28, -81, -1, 21, + 6, 39, -68, -31, -11, -45, + -19, 10, -27, -11, 29, -26, + 39, 3, -53, 17, 111, 58, + -3, -27, -26, -16, 57, 19, + 5, 34, 17, 68, -22, 31, + 28, 8, 36, 10, -52, 43, + 4, 35, -34, 2, -8, 40, + 33, -68, -35, 32, 4, 38, + -27, -24, 30, -15, 1, -35, + -19, -33, 43, 9, 15, -30, + -38, -10, -4, -48, 17, -12, + 20, -20, 40, -60, 27, 12, + 47, -13, 0, 13, -47, -12, + -27, 60, -40, 20, -20, 12, + -17, 48, 4, 10, 38, 30, + -15, -9, -43, 33, 19, 35, + -1, 15, -30, 24, 27, -38, + -4, -32, 35, 68, -33, -40, + 8, -2, 34, -35, -4, -43, + 52, -10, -36, -8, -28, -31, + 22, -68, -17, -34, -5, -19, + -57, 16, 26, 27, 3, -58, + -111, -17, 53, -3, -39, 26, + -29, 11, 27, -10, 19, 45, + 11, 31, 68, -39, -6, -21, + 1, 81, -28, -49, 10, -38, + 75, 15, 25, -47, -54, -34, + -30, -32, -20, 12, -2, 10, + -38, -22, -11, -3, -98, 15, + -23, 29, -6, -16, -19, -9, + -2, 13, 3, -17, 20, 45, + 17, 76, -60, 7, -66, 15, + -23, -45, 24, -67, 79, -32, + -2, -4, 12, 47, 11, 16, + -27, -41, 36, 3, -5, -49, + -4, 29, -51, 40, 1, -49, + -23, -76, -4, 62, -28, 21, + 73, 26, -15, -40, 56, -32, + 2, 39, -38, 37, 6, 28, + -16, 48, 23, 27, -14, -26, + -15, 53, 16, 4, 86, -57, + -24, 27, 63, -34, -22, 17, + 41, -28, 1, -5, 57, 8, + 12, 40, 61, -21, 75, 51, + -36, -68, -88, 43, -22, 1, + -30, -40, 1, 7, 2, 8, + -12, -20, -14, -44, -56, -31, + 30, 21, -9, -62, -13, 29, + -21, 8, -23, 33, 2, 34, + -14, -41, 54, 50, -8, -28, + -3, 16, -29, -39, 2, -8, + -43, -66, -8, -34, 33, 18, + 33, 31, 39, 48, -22, 35, + -2, 11, 76, 64, 12, -11, + -42, -11, 74, -64, -44, -29, + 49, 3, -2, -16, 1, -14, + -36, 14, -4, -75, 91, 15, + -50, 70, 19, -48, -49, -7, + -18, -22, 11, -36, 34, 31, + -34, 15, 15, -60, -32, -48, + -53, -55, 16, -17, -44, 49, + -47, 25, 43, 7, -33, 29, + 1, 10, 51, 71, -53, -23, + 2, 33, 43, -29, 69, -16, + -29, -8, -14, -18, -30, 16, + -61, 46, -1, 2, 8, 44, + 15, -8, 11, -22, 28, 99, + -2, -27, -21, -14, 20, 23, + -18, 30, -12, 47, -16, 32, + 17, 67, 17, 31, -5, -47, + 29, 12, 81, 9, -32, -41, + -10, 20, -8, 8, -25, 23, + 7, 11, -15, -16, -67, -37, + 18, 18, -2, 24, -16, -9, + -55, -108, -19, 15, 34, 65, + -49, 7, 2, 20, 68, 3, + -35, -1, 5, -24, 21, -55, + 22, 72, -2, -36, -8, -95, + -102, -34, 66, 50, -6, -11, + -7, 23, -28, -80, 45, -8, + -11, -10, -86, -4, 9, -3, + -6, -20, 2, -48, -24, -13, + -27, -45, -11, 8, -6, 38, + -36, 15, -39, 11, -4, -92, + 51, -27, -20, 68, 19, -68, + -14, -7, 6, 15, 8, -10, + 46, 32, -15, -92, -28, 54, + -11, 9, 67, -51, -35, 45, + -12, 13, 26, -19, 44, 47, + 27, 36, -61, -54, -55, -3, + 21, -44, -11, 15, 15, 45, + 13, -56, 5, 52, -34, 37, + -65, 55, 31, -14, 18, -10, + 5, 5061, -352336, 4875526, -28099645, 85945123, + -155294491, 173660896, -121144577, 51294594, -12235464, 1395758, + -50485, 34, -23, 15, -30, -2, + 25, 28, -30, 30, -39, -24, + -13, -77, 54, 7, +}; diff --git a/test/cmocka/src/math/fft/ref_fft_multi_1536_32.h b/test/cmocka/src/math/fft/ref_fft_multi_1536_32.h new file mode 100644 index 000000000000..3b80ddea426a --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi_1536_32.h @@ -0,0 +1,1044 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_FFT_MULTI_1536_NUM_TESTS 1 + +static const int32_t fft_in_real_1536_q31[1536] = { + -1307, -574, -1210, -1522, -1899, 1071, + 855, 2163, 1521, 2259, 1260, -2999, + 433, 1384, -1287, -2171, 1479, 1583, + -1436, 1011, 4189, 2711, -946, -195, + -2543, 1178, -1736, 772, 1522, -171, + -1454, -1564, -1958, -4470, -3253, -3927, + -4950, -5304, -4795, -3937, -4683, -5511, + -5491, -2036, -46, -2309, -4636, 183, + 1165, 889, 2769, 2573, 4187, 7141, + 10550, 8534, 13292, 12890, 13854, 14933, + 14481, 13572, 19470, 17619, 19996, 15501, + 14335, 15941, 10852, 9125, 9930, 6717, + 3435, -122, -7217, -14931, -15699, -19050, + -28226, -29840, -39221, -38444, -45330, -48565, + -53919, -51940, -56165, -59291, -56469, -54002, + -50482, -46240, -39727, -31555, -24931, -13667, + -4067, 7601, 19601, 36606, 49720, 66264, + 82262, 93798, 109492, 123549, 138328, 146587, + 153740, 163017, 163203, 163630, 160765, 157379, + 146736, 132520, 113001, 93878, 69705, 39592, + 12865, -21580, -56672, -95272, -131691, -174549, + -213209, -248628, -283486, -320449, -346051, -370771, + -392071, -407380, -415127, -415461, -403141, -387183, + -367199, -327447, -286189, -235079, -175686, -108377, + -31956, 45401, 128250, 217821, 312206, 403171, + 493176, 576281, 661962, 734196, 802037, 857666, + 899782, 931826, 947158, 943468, 922552, 883848, + 826153, 747513, 653458, 535042, 402552, 250199, + 86048, -86449, -277634, -465706, -659677, -859066, + -1050155, -1237367, -1413054, -1568939, -1705530, -1823177, + -1913070, -1972205, -1997013, -1988742, -1939559, -1853061, + -1727260, -1564661, -1362612, -1120399, -846100, -538521, + -204309, 151603, 528919, 922290, 1315125, 1706894, + 2090470, 2458389, 2799972, 3109863, 3382597, 3609505, + 3778017, 3891544, 3933694, 3912353, 3813931, 3643198, + 3393850, 3071142, 2677376, 2209600, 1677941, 1084818, + 444967, -243363, -962452, -1701393, -2442824, -3187052, + -3905129, -4595717, -5232588, -5810315, -6311599, -6728312, + -7036669, -7235070, -7315570, -7261861, -7076599, -6757898, + -6294514, -5696302, -4963545, -4110784, -3133421, -2057740, + -890886, 352251, 1643641, 2971293, 4311667, 5637297, + 6922700, 8146290, 9279509, 10298347, 11182888, 11906619, + 12445720, 12792796, 12920677, 12821426, 12487235, 11917145, + 11098463, 10047806, 8770879, 7274529, 5582694, 3712279, + 1694100, -446673, -2678418, -4957743, -7246818, -9512063, + -11705023, -13778294, -15700344, -17427663, -18912276, -20124761, + -21027320, -21598948, -21801191, -21628479, -21056400, -20085908, + -18714238, -16955159, -14813766, -12321078, -9504162, -6399966, + -3054231, 482872, 4154302, 7905278, 11666569, 15378054, + 18958123, 22345534, 25474375, 28277167, 30683302, 32642235, + 34096393, 35003550, 35319949, 35025915, 34092432, 32521600, + 30307717, 27471468, 24039684, 20045508, 15546072, 10598856, + 5269966, -350481, -6180026, -12114692, -18059248, -23906672, + -29549875, -34871747, -39782448, -44161036, -47925834, -50975328, + -53235322, -54634944, -55118776, -54647517, -53185173, -50739616, + -47302385, -42904835, -37598374, -31437470, -24504539, -16886940, + -8713803, -96592, 8822281, 17893277, 26962568, 35868287, + 44446216, 52535664, 59974374, 66609968, 72289304, 76896286, + 80294207, 82394351, 83111692, 82389627, 80191979, 76513564, + 71358551, 64784668, 56848569, 47656194, 37330198, 26009511, + 13864615, 1086171, -12123873, -25537363, -38932152, -52068869, + -64704797, -76601691, -87525849, -97258037, -105582362, -112312248, + -117278944, -120341163, -121382694, -120326971, -117128187, -111776250, + -104303150, -94772849, -83295810, -70008000, -55097092, -38780459, + -21296115, -2915789, 16048887, 35294650, 54490243, 73286361, + 91346168, 108333722, 123911975, 137767211, 149615571, 159177154, + 166229885, 170578636, 172063686, 170577539, 166068796, 158531146, + 148010324, 134608279, 118482912, 99845751, 78943021, 56093794, + 31643166, 5972435, -20501213, -47329173, -74051124, -100196883, + -125294427, -148870026, -170477108, -189679210, -206075759, -219304043, + -229055107, -235069748, -237136842, -235122812, -228956016, -218642090, + -204251958, -185931479, -163914657, -138473803, -109988389, -78864741, + -45593192, -10699983, 25253171, 61650957, 97869663, 133278383, + 167232254, 199106861, 228282653, 254196068, 276312161, 294146665, + 307294652, 315410249, 318234645, 315590297, 307394443, 293664335, + 274509339, 250133892, 220842123, 187039901, 149209960, 107922433, + 63810361, 17587760, -29985506, -78117921, -125968455, -172708192, + -217493625, -259497359, -297927725, -332031196, -361123362, -384588415, + -401886494, -412588709, -416366237, -413004376, -402403545, -384595162, + -359740975, -328120781, -290142483, -246340640, -197348989, -143910091, + -86867351, -27143103, 34285708, 96376993, 158069138, 218280055, + 275929446, 329963897, 379373709, 423197160, 460572512, 490705168, + 512948401, 526747189, 531695512, 527540747, 514177226, 491657698, + 460188457, 420160343, 372096220, 316680397, 254738394, 187222293, + 115197014, 39828687, -37626355, -115870108, -193554390, -269321025, + -341820450, -409733063, -471798151, -526831940, -573748345, -611594031, + -639544543, -656949500, -663308649, -658325717, -641880896, -614068050, + -575168915, -525665290, -466238167, -397738580, -321208417, -237834108, + -148957438, -56007249, 39465483, 135841047, 231468773, 324681365, + 413821307, 497283182, 573521157, 641095651, 698712130, 745197774, + 779567711, 801049388, 809057254, 803237808, 783489679, 749925411, + 702911733, 643063728, 571208755, 488423234, 395954144, 295275675, + 187993978, 75865718, -39236308, -155364925, -270531450, -382717564, + -489957676, -590312404, -681949986, -763163139, -832392865, -888277334, + -929664966, -955628349, -965507939, -958906225, -935713724, -896099293, + -840526616, -769729759, -684734549, -586814614, -477494414, -358504690, + -231768214, -99384696, 36447617, 173415519, 309178420, 441371753, + 567666025, 685811530, 793656966, 889216942, 970688561, 1036488980, + 1085290370, 1116036006, 1127980589, 1120686956, 1094053945, 1048302464, + 983994405, 902020613, 803589058, 690200491, 563631899, 425926519, + 279325343, 126250979, -30724886, -188948326, -345694846, -498252679, + -643944275, -780184780, -904516055, -1014670896, -1108601825, -1184506299, + -1240890909, -1276581824, -1290734322, -1282895863, -1252960854, -1201218312, + -1128343320, -1035375507, -923712972, -795088635, -651552657, -495428590, + -329277266, -155868968, 21884630, 200961971, 378296024, 550818202, + 715513308, 869463796, 1009937937, 1134384860, 1240514038, 1326341350, + 1390206244, 1430809681, 1447252889, 1439042709, 1406104903, 1348787986, + 1267878591, 1164563795, 1040427150, 897443541, 737906293, 564423186, + 379869427, 187329491, -9955718, -208626909, -405282321, -596523018, + -779023314, -949576746, -1105159690, -1242989351, -1360560433, -1455708690, + -1526631531, -1571933920, -1590652703, -1582289863, -1546784045, -1484564044, + -1396513095, -1283969795, -1148697739, -992870821, -819029807, -630048695, + -429062628, -219454929, -4764302, 211344971, 425177867, 633047097, + 831343127, 1016615527, 1185591113, 1335287179, 1463017725, 1566460527, + 1643703210, 1693272282, 1714173828, 1705879519, 1668383535, 1602171121, + 1508225260, 1388013119, 1243466543, 1076941063, 891185548, 689291733, + 474640802, 250860397, 21738447, -208811879, -436851181, -658444086, + -869778675, -1067171636, -1247182880, -1406650050, -1542754248, -1653063285, + -1735584343, -1788792418, -1811656971, -1803674070, -1764855225, -1695756123, + -1597458692, -1471529123, -1320042483, -1145495192, -950811122, -739251472, + -514387884, -280038811, -40182539, 201082127, 439625474, 671360194, + 892281969, 1098593058, 1286704310, 1453353848, 1595632929, 1711032396, + 1797519314, 1853535499, 1878057863, 1870596072, 1831203976, 1760492969, + 1659601101, 1530204850, 1374462215, 1194990025, 994815702, 777344707, + 546257874, 305494569, 59165380, -188527365, -433343031, -671080193, + -897665887, -1109212583, -1302074592, -1472935050, -1618847731, -1737293175, + -1826220505, -1884077847, -1909862809, -1903102016, -1863908084, -1792915406, + -1691338340, -1560892199, -1403810772, -1222762623, -1020844224, -801519269, + -568521705, -325842895, -77639026, 171850260, 418354109, 657652397, + 885658006, 1098483323, 1292482492, 1464354264, 1611173802, 1730447918, + 1820147456, 1878774327, 1905345015, 1899436591, 1861181614, 1791269880, + 1690931416, 1561918192, 1406474208, 1227285856, 1027453891, 810423456, + 579930851, 339935975, 94561541, -151995804, -395519520, -631846220, + -856955512, -1067023060, -1258484983, -1428107906, -1573047808, -1690881207, + -1779650546, -1837917712, -1864752691, -1859784222, -1823172826, -1755627369, + -1658388705, -1533199617, -1382280092, -1208279946, -1014241857, -803543612, + -579832950, -346972564, -108975262, 130084072, 366112543, 595091308, + 813135881, 1016560268, 1201935283, 1366175566, 1506546319, 1620740341, + 1706921440, 1763716202, 1790274256, 1786276435, 1751905466, 1687886894, + 1595436847, 1476262351, 1332506505, 1166743251, 981898453, 781224629, + 568212339, 346559921, 120100320, -107291665, -331716427, -549356988, + -756537606, -949779759, -1125851662, -1281839136, -1415194341, -1523750226, + -1605799171, -1660093788, -1685848027, -1682799447, -1651157876, -1591635572, + -1505409467, -1394110995, -1259788475, -1104878691, -932150993, -744662067, + -545708117, -338757382, -127388767, 84763881, 294067482, 496979529, + 690070737, 870117589, 1034133585, 1179439215, 1303678090, 1404887501, + 1481492441, 1532367900, 1556837967, 1554669622, 1526102357, 1471816788, + 1392929409, 1290979584, 1167883699, 1025898547, 867595552, 695801640, + 513558015, 324055197, 130580019, -63531828, -254957837, -440470852, + -616936670, -781439126, -931257387, -1063973979, -1177469886, -1269969396, + -1340089214, -1386823818, -1409580111, -1408192311, -1382898809, -1334344278, + -1263571363, -1172000225, -1061372669, -933760932, -791499808, -637157868, + -473474442, -303337763, -129705392, 44420335, 216069365, 382339648, + 540447254, 687781491, 821934079, 940760571, 1042387135, 1125252799, + 1188147208, 1230201006, 1250924236, 1250187783, 1228227566, 1185647619, + 1123398884, 1042759518, 945299898, 832870179, 707547821, 571626092, + 427527543, 277810041, 125085057, -28010600, -178853506, -324906192, + -463733638, -593048340, -710768042, -815013616, -904172591, -976908539, + -1032173782, -1069239365, -1087698933, -1087470671, -1068778489, -1032179008, + -978515150, -908919940, -824775378, -727706611, -619535673, -502243121, + -377946135, -248861178, -117246162, 14621362, 144491857, 270172298, + 389581420, 500764993, 601939427, 691515419, 768128879, 830643528, + 878195038, 910177424, 926258719, 926396266, 910805964, 879977667, + 834650965, 775805529, 704649184, 622560430, 531100567, 431974140, + 326968596, 217974337, 106897439, -4331905, -113811517, -219713043, + -320271090, -413863122, -498997138, -574345705, -638786489, -691378723, + -731416804, -758409004, -772102118, -772476516, -759734475, -734294552, + -696804594, -648094824, -589172646, -521212233, -445517032, -363502236, + -276673232, -186591246, -94842458, -3022754, 87303105, 174620285, + 257495934, 334583680, 404667701, 466682288, 519703658, 562979891, + 595946616, 618221526, 629610881, 630106942, 619907159, 599363749, + 569010853, 529543975, 481805921, 426750078, 365456250, 299075520, + 228840090, 156015660, 81893049, 7755186, -65128851, -135537978, + -202321503, -264404090, -320822061, -370714643, -413359634, -448173767, + -474696651, -492653799, -501893571, -502433588, -494432932, -478193313, + -454161674, -422891283, -385068437, -341460613, -292938082, -240419450, + -184880948, -127332930, -68805082, -10308903, 47162165, 102642618, + 155226699, 204081975, 248446611, 287663437, 321164632, 348507085, + 369349845, 383472440, 390780777, 391301244, 385159596, 372608714, + 354002348, 329792757, 300514176, 266772038, 229250923, 188660171, + 145771607, 101362438, 56230870, 11158037, -33089190, -75767489, + -116186499, -153708843, -187764622, -217840328, -243526598, -264475454, + -280442868, -291277471, -296907101, -297359175, -292750056, -283273727, + -269212330, -250907995, -228786222, -203299441, -174980678, -144370836, + -112054125, -78619334, -44674297, -10796779, 22429621, 54448874, + 84741856, 112850180, 138327885, 160816025, 180007793, 195653700, + 207572067, 215662380, 219880160, 220249673, 216865158, 209879430, + 199507426, 186012659, 169709832, 150948749, 130113527, 107611242, + 83879355, 59352318, 34467719, 9665911, -14642108, -38040824, + -60157016, -80654418, -99219264, -115589797, -129545820, -140913863, + -149571739, -155444700, -158505797, -158792334, -156363817, -151338055, + -143887461, -134194341, -122498799, -109046102, -94123508, -78025128, + -61059747, -43545883, -25796815, -8129513, 9163546, 25792880, + 41498590, 56033059, 69187641, 80767050, 90630249, 98658995, + 104762234, 108902079, 111059757, 111263586, 109562557, 106046746, + 100833173, 94061670, 85895528, 76519048, 66130807, 54934736, + 43153781, 31007416, 18709409, 6487602, -5465933, -16946274, + -27770029, -37775509, -46814982, -54771683, -61533641, -67030347, + -71205626, -74023788, -75495830, -75627969, -74470032, -72077681, + -68529180, -63937739, -58408135, -52062371, -45042063, -37490140, + -29555197, -21385211, -13122625, -4921524, 3085357, 10759723, + 17992582, 24666389, 30683196, 35971842, 40458997, 44099420, + 46855760, 48721212, 49685704, 49765688, 48994777, 47411331, + 45075651, 42054087, 38424158, 34268812, 29672938, 24740687, + 19571693, 14248378, 8884824, 3562881, -1621239, -6586647, + -11253090, -15555599, -19428913, -22821406, -25700820, -28024865, + -29783485, -30965398, -31574032, -31615670, -31114544, -30104441, + -28614173, -26690187, -24393033, -21759693, -18857738, -15751354, + -12492477, -9153261, -5783717, -2459634, 778698, 3875964, + 6776702, 9449232, 11845786, 13948370, 15720788, 17149101, + 18231430, 18949799, 19315305, 19335514, 19020327, 18395826, + 17478205, 16296941, 14893212, 13283979, 11522416, 9639711, + 7663000, 5644053, 3617443, 1615060, -332168, -2184038, + -3918720, -5508362, -6936545, -8183325, -9232830, -10074356, + -10703608, -11126458, -11331077, -11339686, -11148104, -10770979, + -10228871, -9536383, -8710109, -7770585, -6742184, -5643349, + -4500541, -3328458, -2159579, -1004392, 110110, 1173423, + 2159647, 3069460, 3876884, 4586498, 5177693, 5646960, + 5999906, 6233787, 6347370, 6346598, 6231484, 6021809, + 5711125, 5320225, 4855551, 4327752, 3755975, 3148939, + 2514295, 1870100, 1224054, 591479, -19842, -595926, + -1136695, -1623514, -2058527, -2441755, -2759699, -3009118, + -3195895, -3315318, -3372391, -3367899, -3304971, -3188264, + -3019838, -2809759, -2565867, -2288243, -1979646, -1665042, + -1328619, -993474, -657631, -327993, -16430, 284913, + 562503, 810232, 1034553, 1226932, 1381838, 1513025, + 1599447, 1662854, 1686316, 1682092, 1651127, 1587146, + 1503496, 1397927, 1269542, 1131369, 982502, 824625, + 660881, 493354, 326771, 168908, 16066, -125971, + -261297, -378974, -483268, -576163, -647622, -708224, + -748436, -777452, -785947, -779909, -768879, -735235, + -693141, -644311, -585366, -522056, -451398, -378281, + -301901, -228634, -154426, -81830, -10134, 47735, + 111082, 163294, 207447, 247956, 282325, 307949, + 324908, 333180, 335597, 335296, 325667, 311552, + 293582, 271780, 245119, 219071, 189774, 158232, + 126724, 93564, 64134, 34822, 6228, -19584, + -41721, -63726, -82340, -98638, -109326, -117337, + -126201, -127991, -132091, -130369, -124920, -119589, + -111608, -103992, -92468, -82123, -67954, -61380, + -46424, -35967, -21111, -11739, -5029, 5679, + 13330, 22276, 26343, 35218, 34648, 39078, + 41053, 41092, 46268, 44252, 41586, 40964, + 33470, 36946, 29670, 27351, 23384, 20595, + 14255, 8620, 6966, 7402, 2342, -3982, + -3662, -6609, -4254, -9826, -11984, -13311, + -11772, -11570, -11066, -9660, -9629, -8766, + -9862, -6981, -8621, -6396, -5888, -4708, + -1464, -3442, -1834, -1918, -3426, 1074, + 2306, 544, 72, 3496, 3495, -1310, + 1331, 2847, 5980, 2827, 3263, 1499, + 2773, 1854, 1693, 3452, 2877, -1854, + 724, -2026, -2173, -141, -640, 1167, + 2129, -1066, 1932, -806, -690, -1960, + -506, -1528, -1399, -333, -2033, -851, + -1057, -321, -3212, 2295, -24, -2239, +}; + +static const int32_t fft_in_imag_1536_q31[1536] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const int32_t fft_ref_real_1536_q31[1536] = { + 36, 4, -4, -16, 8, 47, + -34, 30, -82, -15, 32, -63, + -77, -44, 12, -13, 1, -15, + -7, -13, 58, -10, 19, -16, + -13, 92, -848, 92278, -1546050, 10045551, + -33641357, 65657099, -78882771, 59164075, -27128397, 7128059, + -930416, 42760, -189, 12, -18, 9, + -9, -43, -37, 25, -6, 36, + -13, -15, -64, 43, -7, 3, + 16, -4, 46, 43, 15, -30, + 46, -7, 15, -9, 8, -14, + 29, -1, -53, 49, -19, -15, + -29, -11, -10, -29, -25, -11, + -36, 36, -29, -6, 28, 8, + 49, 23, -32, -27, -28, -25, + 14, 28, -6, 8, -39, 10, + 21, -4, -22, 52, 22, -11, + -27, 17, -1, 10, 30, -40, + -5, 5, 0, -18, 28, -29, + 30, 27, -1, -16, 42, -51, + -84, -14, -24, -26, -4, -4, + -36, -57, -39, 22, -4, -36, + 1, -53, 52, -17, -45, -6, + -22, 20, -19, 21, -12, -3, + -18, 38, -43, -24, -32, 48, + 47, 17, -25, -4, 22, 9, + -25, 15, -7, -22, -33, 20, + 19, 37, 36, 42, 39, -20, + 28, 25, -5, -5, 20, 42, + 30, -15, 1, -19, 33, -48, + -4, 24, -38, -18, -30, 44, + 14, 42, 3, 44, -85, 25, + 33, 27, -16, -7, 14, -48, + 35, -12, 1, 18, -37, -82, + 4, 24, -52, -57, 21, -2, + -37, -51, 23, 35, 60, 2, + 19, 32, -23, 3, 54, 7, + -49, 26, -37, 39, 48, 19, + 29, -3, 5, -22, 6, 26, + -5, -11, 13, -16, -38, 38, + -23, 55, -4, 30, -12, 59, + -26, -25, 27, -21, 4, -18, + -24, -17, -41, -56, 39, 22, + -1, -6, -38, -18, -3, 25, + -66, 52, 3, 29, -17, -2, + -36, -23, -8, 20, 21, -41, + -22, -15, 31, -6, 11, 26, + -1, 36, -29, -4, -11, 12, + 47, -8, -5, 0, 35, 8, + -13, -3, -47, -15, 14, -38, + 40, 34, -55, -38, -51, -17, + -13, 9, -33, -10, 9, 56, + 12, 4, 12, -1, -11, 3, + 55, 31, -5, 36, -14, -26, + -4, 10, -12, 8, 5, -70, + 37, -31, -55, -17, -26, -45, + -5, -13, -1, 27, 42, 31, + -5, -39, -57, -22, 14, 9, + 4, -20, -29, 31, -45, 16, + 4, 38, 27, -39, 5, 23, + 36, 39, 36, 51, -3, -4, + -19, -44, -9, -53, -14, 46, + -46, 5, 4, -24, 13, -21, + 2, 40, -26, 31, 21, 41, + -13, 9, -39, -33, -4, -22, + 10, 18, 0, 16, 42, 20, + -8, 12, -18, 11, 8, -30, + -22, 35, -29, 8, 47, -29, + -36, 2, -10, -57, -21, 23, + 9, -91, -49, 6, 14, 3, + 50, -59, -56, -3, 4, -4, + -71, -10, -55, 13, 28, -37, + -6, -50, 17, 4, 52, 7, + -53, 19, 33, -19, 12, -8, + -52, 30, -8, -5, 53, -3, + -13, 10, 2, -25, -14, -43, + 35, -22, 5, 68, -8, -8, + 3, 46, -2, -16, -5, 40, + -14, -28, 6, 65, -22, -5, + -9, -13, -27, 11, 16, -39, + 28, 24, 54, 37, -31, 39, + -15, 68, -3, -42, 8, 40, + 11, -3, -47, 33, -19, 24, + -6, -6, -9, -61, 55, 9, + 24, 11, -35, 19, -1, 5, + 63, -10, -24, -6, -8, -12, + 20, 17, 0, 31, -34, -3, + 32, 66, -38, 0, 7, 32, + 11, 0, 2, -8, -22, -46, + 11, -3, -25, -36, -2, 41, + -19, -17, -29, 30, -1, 70, + 25, 16, -25, -15, 12, 18, + -13, 20, 13, -44, -42, -21, + 4, -39, 32, 21, 60, -11, + -31, 10, -9, 1, 19, -45, + -4, -16, -21, 26, 35, 11, + 18, 38, 1, 6, 51, 13, + -70, 7, 55, 35, -10, -13, + -14, -56, -12, 26, 18, 51, + -24, 4, -35, 16, -1, -45, + 40, 48, 50, 15, 1, -19, + 1, -21, 67, -46, -20, -8, + -7, -2, -24, 16, -39, -1, + 26, 72, 3, -16, -3, 14, + 28, 9, -40, 34, -3, 18, + -8, -41, -51, 45, 28, -37, + 4, 24, 21, -38, 90, -29, + 9, 9, 47, -10, 35, -1, + -30, -11, 11, 38, -24, 10, + -40, 43, -3, -52, 23, 3, + -9, 14, 1, 20, 44, 13, + -35, -9, 36, -39, 37, 4, + 20, -18, 42, 39, -19, 20, + 26, -3, 38, -11, 20, -2, + 29, -60, -22, -23, 37, -30, + 44, -23, 7, -30, 39, -14, + -18, -26, 13, 23, -40, -45, + 3, -2, -14, 35, -10, -33, + 3, -40, -42, -38, 3, -5, + 18, -44, -36, 24, 40, 33, + 37, 18, -13, 19, -5, -13, + -7, -8, -1, -41, -18, -14, + -46, -49, 22, 8, -1, -14, + 0, 40, -15, 65, -35, -29, + 14, 25, -19, 13, -27, -12, + -37, -42, 4, -14, -58, 0, + 62, -16, 26, 19, -29, 23, + -17, 24, -61, 30, 24, 9, + -52, 9, 24, 30, -61, 24, + -17, 23, -29, 19, 26, -16, + 62, 0, -58, -14, 4, -42, + -37, -12, -27, 13, -19, 25, + 14, -29, -35, 65, -15, 40, + 0, -14, -1, 8, 22, -49, + -46, -14, -18, -41, -1, -8, + -7, -13, -5, 19, -13, 18, + 37, 33, 40, 24, -36, -44, + 18, -5, 3, -38, -42, -40, + 3, -33, -10, 35, -14, -2, + 3, -45, -40, 23, 13, -26, + -18, -14, 39, -30, 7, -23, + 44, -30, 37, -23, -22, -60, + 29, -2, 20, -11, 38, -3, + 26, 20, -19, 39, 42, -18, + 20, 4, 37, -39, 36, -9, + -35, 13, 44, 20, 1, 14, + -9, 3, 23, -52, -3, 43, + -40, 10, -24, 38, 11, -11, + -30, -1, 35, -10, 47, 9, + 9, -29, 90, -38, 21, 24, + 4, -37, 28, 45, -51, -41, + -8, 18, -3, 34, -40, 9, + 28, 14, -3, -16, 3, 72, + 26, -1, -39, 16, -24, -2, + -7, -8, -20, -46, 67, -21, + 1, -19, 1, 15, 50, 48, + 40, -45, -1, 16, -35, 4, + -24, 51, 18, 26, -12, -56, + -14, -13, -10, 35, 55, 7, + -70, 13, 51, 6, 1, 38, + 18, 11, 35, 26, -21, -16, + -4, -45, 19, 1, -9, 10, + -31, -11, 60, 21, 32, -39, + 4, -21, -42, -44, 13, 20, + -13, 18, 12, -15, -25, 16, + 25, 70, -1, 30, -29, -17, + -19, 41, -2, -36, -25, -3, + 11, -46, -22, -8, 2, 0, + 11, 32, 7, 0, -38, 66, + 32, -3, -34, 31, 0, 17, + 20, -12, -8, -6, -24, -10, + 63, 5, -1, 19, -35, 11, + 24, 9, 55, -61, -9, -6, + -6, 24, -19, 33, -47, -3, + 11, 40, 8, -42, -3, 68, + -15, 39, -31, 37, 54, 24, + 28, -39, 16, 11, -27, -13, + -9, -5, -22, 65, 6, -28, + -14, 40, -5, -16, -2, 46, + 3, -8, -8, 68, 5, -22, + 35, -43, -14, -25, 2, 10, + -13, -3, 53, -5, -8, 30, + -52, -8, 12, -19, 33, 19, + -53, 7, 52, 4, 17, -50, + -6, -37, 28, 13, -55, -10, + -71, -4, 4, -3, -56, -59, + 50, 3, 14, 6, -49, -91, + 9, 23, -21, -57, -10, 2, + -36, -29, 47, 8, -29, 35, + -22, -30, 8, 11, -18, 12, + -8, 20, 42, 16, 0, 18, + 10, -22, -4, -33, -39, 9, + -13, 41, 21, 31, -26, 40, + 2, -21, 13, -24, 4, 5, + -46, 46, -14, -53, -9, -44, + -19, -4, -3, 51, 36, 39, + 36, 23, 5, -39, 27, 38, + 4, 16, -45, 31, -29, -20, + 4, 9, 14, -22, -57, -39, + -5, 31, 42, 27, -1, -13, + -5, -45, -26, -17, -55, -31, + 37, -70, 5, 8, -12, 10, + -4, -26, -14, 36, -5, 31, + 55, 3, -11, -1, 12, 4, + 12, 56, 9, -10, -33, 9, + -13, -17, -51, -38, -55, 34, + 40, -38, 14, -15, -47, -3, + -13, 8, 35, 0, -5, -8, + 47, 12, -11, -4, -29, 36, + -1, 26, 11, -6, 31, -15, + -22, -41, 21, 20, -8, -23, + -36, -2, -17, 29, 3, 52, + -66, 25, -3, -18, -38, -6, + -1, 22, 39, -56, -41, -17, + -24, -18, 4, -21, 27, -25, + -26, 59, -12, 30, -4, 55, + -23, 38, -38, -16, 13, -11, + -5, 26, 6, -22, 5, -3, + 29, 19, 48, 39, -37, 26, + -49, 7, 54, 3, -23, 32, + 19, 2, 60, 35, 23, -51, + -37, -2, 21, -57, -52, 24, + 4, -82, -37, 18, 1, -12, + 35, -48, 14, -7, -16, 27, + 33, 25, -85, 44, 3, 42, + 14, 44, -30, -18, -38, 24, + -4, -48, 33, -19, 1, -15, + 30, 42, 20, -5, -5, 25, + 28, -20, 39, 42, 36, 37, + 19, 20, -33, -22, -7, 15, + -25, 9, 22, -4, -25, 17, + 47, 48, -32, -24, -43, 38, + -18, -3, -12, 21, -19, 20, + -22, -6, -45, -17, 52, -53, + 1, -36, -4, 22, -39, -57, + -36, -4, -4, -26, -24, -14, + -84, -51, 42, -16, -1, 27, + 30, -29, 28, -18, 0, 5, + -5, -40, 30, 10, -1, 17, + -27, -11, 22, 52, -22, -4, + 21, 10, -39, 8, -6, 28, + 14, -25, -28, -27, -32, 23, + 49, 8, 28, -6, -29, 36, + -36, -11, -25, -29, -10, -11, + -29, -15, -19, 49, -53, -1, + 29, -14, 8, -9, 15, -7, + 46, -30, 15, 43, 46, -4, + 16, 3, -7, 43, -64, -15, + -13, 36, -6, 25, -37, -43, + -9, 9, -18, 12, -189, 42760, + -930416, 7128059, -27128397, 59164075, -78882771, 65657099, + -33641357, 10045551, -1546050, 92278, -848, 92, + -13, -16, 19, -10, 58, -13, + -7, -15, 1, -13, 12, -44, + -77, -63, 32, -15, -82, 30, + -34, 47, 8, -16, -4, 4, +}; + +static const int32_t fft_ref_imag_1536_q31[1536] = { + 0, -51, -47, -1, -37, 43, + 28, -75, -11, -5, 22, -19, + 34, 22, -2, 47, 5, -17, + -59, 34, 2, -3, -6, 15, + -23, -10, -2528, 286363, -4833320, 31628670, + -106676515, 209692355, -253750691, 191701755, -88543033, 23436068, + -3081512, 142772, -625, 11, 6, -13, + 4, -7, -42, 19, -6, -5, + 11, -28, 39, -47, 29, 60, + 39, -3, -48, 25, -47, 5, + -27, 14, -37, 42, 54, 24, + -11, -60, -22, -14, 51, -36, + 53, -48, -50, -5, -52, -23, + -18, -23, -16, -22, 23, 34, + 33, -6, -11, -62, -45, 11, + 19, -2, -39, -18, 20, 4, + 2, 24, 24, 13, -9, -2, + -4, 32, -2, 10, 15, 6, + -29, -7, 45, -29, 18, 26, + 1, -19, -20, 0, 32, 16, + -1, 32, 72, -48, -27, -4, + 69, 22, -7, 6, 22, 56, + -14, 32, -34, -39, 31, -18, + 30, 19, -4, 71, 10, 28, + -23, 22, 13, 12, -2, 21, + 38, -33, 1, -37, -32, 19, + 13, 23, -43, 10, 7, -28, + 65, 25, 4, -24, 13, 17, + 0, -23, 14, 13, -18, -16, + 21, -47, 19, -20, 15, 1, + -50, -2, -21, -33, 9, 44, + 25, 28, 20, -31, 13, 4, + -4, 83, -1, 46, 10, 16, + -14, 17, 16, 15, 32, 24, + -11, -44, 45, -68, 36, -32, + 66, 23, 12, 42, -12, -6, + 50, -68, -14, -46, -36, -9, + 71, -41, -28, -33, 5, -61, + -10, 54, 0, 40, 0, 17, + 3, 4, 6, -20, 6, -7, + 1, -17, 3, -26, -29, 23, + -4, 17, -15, 8, 6, 8, + -23, -20, -3, 38, 13, -32, + 18, -3, -45, -47, -44, -26, + -29, 23, 28, -3, 58, -40, + 53, -9, 5, 35, 8, -1, + -25, 36, -6, -56, -1, 35, + -3, -7, -23, -12, 31, -51, + 5, 77, -38, -42, 49, -1, + -23, -3, 8, 0, 2, 11, + 27, -35, 8, 58, -46, -27, + 14, -10, -15, -45, -16, 2, + 20, 8, 10, 9, 29, -30, + -15, 68, -8, 16, -63, -23, + -5, -37, 7, -31, -25, 44, + -17, -34, 14, 10, 7, 16, + 18, 26, 44, 12, -13, 4, + 25, 6, 29, -47, 24, 8, + -14, 6, 21, -39, -2, -73, + -11, -7, -7, -14, -34, 11, + 74, 43, 17, -28, 18, -49, + 27, 3, -7, -13, 39, 20, + -39, 9, -10, 38, -15, -14, + 3, -43, 12, -31, 18, 44, + -24, -22, -52, -26, 15, -20, + -52, -28, 10, -18, -13, -17, + -16, -77, 16, -59, -102, 15, + 31, -75, -24, 42, 9, 19, + -3, 10, 4, 4, -25, 33, + 18, 22, 2, 34, -32, -18, + -1, 12, -3, -12, -6, 20, + -63, 3, -4, 18, 46, 40, + -15, -30, -4, 26, -31, -1, + -15, 19, -49, -11, 20, 1, + 2, 37, 54, 13, -2, -7, + -19, 9, -5, 4, 101, -42, + -45, 17, 14, -35, -56, 30, + -19, 86, -10, -46, -50, -7, + -22, -6, 0, -15, -6, 9, + -46, 54, -14, -7, 2, 27, + -54, 74, 29, 58, -39, 2, + -78, -8, -65, 47, 17, -40, + -15, 6, 3, 13, 7, -26, + -65, -26, -37, 18, -34, -10, + 11, -44, 3, 4, -28, -16, + 8, -88, -3, 8, 27, 18, + -9, 60, 30, 45, -53, -1, + -11, -1, 31, -4, 18, -5, + -13, -5, 9, -40, 22, 6, + -20, 23, 6, 32, -13, 25, + -5, 25, 12, 29, 8, -5, + -53, 45, 7, -24, -3, -12, + 3, 31, -1, -43, -9, -47, + -14, -38, -34, 57, 22, 45, + -20, -5, -30, -18, -17, -2, + 43, -28, 2, 59, -80, -5, + -16, -51, 39, -21, -21, 24, + 47, -29, 15, -22, 71, 77, + -34, 38, -9, -24, 23, -2, + 17, 33, -23, 52, 2, -25, + -55, -2, -34, 64, 59, 1, + 17, 11, 17, 11, -41, -15, + 13, 9, 32, 21, 17, 30, + -32, -49, 10, 11, 31, -1, + -48, 41, 28, -42, -47, 6, + -6, 2, -71, -44, -27, 51, + -3, 38, -66, -36, 34, -41, + 43, 38, 15, 32, -29, 11, + 3, -20, 23, 20, -54, -10, + 6, 7, -4, -12, 26, -14, + 22, 45, -5, 64, 22, -6, + -41, -30, -14, -8, -100, -26, + 28, 57, -5, -9, 42, -20, + 39, 9, 18, 14, 52, 6, + 2, 7, -93, -29, -15, -20, + 25, 18, 2, -20, -7, 15, + 67, -29, -20, -43, 3, 38, + 16, -32, 20, 43, -2, 41, + 16, -3, -8, -21, 1, -12, + 25, 1, 63, 12, -43, -2, + -23, 8, -7, -14, 24, 24, + 32, -19, 33, 13, -9, 1, + 24, 37, -24, 9, -46, -19, + 38, 71, 32, -26, 5, -66, + -5, 8, -5, 13, -43, -24, + -24, -26, 5, -28, 26, 0, + -20, -20, 2, -14, 60, -8, + -57, -34, 13, 12, 14, -1, + 0, 1, -14, -12, -13, 34, + 57, 8, -60, 14, -2, 20, + 20, 0, -26, 28, -5, 26, + 24, 24, 43, -13, 5, -8, + 5, 66, -5, 26, -32, -71, + -38, 19, 46, -9, 24, -37, + -24, -1, 9, -13, -33, 19, + -32, -24, -24, 14, 7, -8, + 23, 2, 43, -12, -63, -1, + -25, 12, -1, 21, 8, 3, + -16, -41, 2, -43, -20, 32, + -16, -38, -3, 43, 20, 29, + -67, -15, 7, 20, -2, -18, + -25, 20, 15, 29, 93, -7, + -2, -6, -52, -14, -18, -9, + -39, 20, -42, 9, 5, -57, + -28, 26, 100, 8, 14, 30, + 41, 6, -22, -64, 5, -45, + -22, 14, -26, 12, 4, -7, + -6, 10, 54, -20, -23, 20, + -3, -11, 29, -32, -15, -38, + -43, 41, -34, 36, 66, -38, + 3, -51, 27, 44, 71, -2, + 6, -6, 47, 42, -28, -41, + 48, 1, -31, -11, -10, 49, + 32, -30, -17, -21, -32, -9, + -13, 15, 41, -11, -17, -11, + -17, -1, -59, -64, 34, 2, + 55, 25, -2, -52, 23, -33, + -17, 2, -23, 24, 9, -38, + 34, -77, -71, 22, -15, 29, + -47, -24, 21, 21, -39, 51, + 16, 5, 80, -59, -2, 28, + -43, 2, 17, 18, 30, 5, + 20, -45, -22, -57, 34, 38, + 14, 47, 9, 43, 1, -31, + -3, 12, 3, 24, -7, -45, + 53, 5, -8, -29, -12, -25, + 5, -25, 13, -32, -6, -23, + 20, -6, -22, 40, -9, 5, + 13, 5, -18, 4, -31, 1, + 11, 1, 53, -45, -30, -60, + 9, -18, -27, -8, 3, 88, + -8, 16, 28, -4, -3, 44, + -11, 10, 34, -18, 37, 26, + 65, 26, -7, -13, -3, -6, + 15, 40, -17, -47, 65, 8, + 78, -2, 39, -58, -29, -74, + 54, -27, -2, 7, 14, -54, + 46, -9, 6, 15, 0, 6, + 22, 7, 50, 46, 10, -86, + 19, -30, 56, 35, -14, -17, + 45, 42, -101, -4, 5, -9, + 19, 7, 2, -13, -54, -37, + -2, -1, -20, 11, 49, -19, + 15, 1, 31, -26, 4, 30, + 15, -40, -46, -18, 4, -3, + 63, -20, 6, 12, 3, -12, + 1, 18, 32, -34, -2, -22, + -18, -33, 25, -4, -4, -10, + 3, -19, -9, -42, 24, 75, + -31, -15, 102, 59, -16, 77, + 16, 17, 13, 18, -10, 28, + 52, 20, -15, 26, 52, 22, + 24, -44, -18, 31, -12, 43, + -3, 14, 15, -38, 10, -9, + 39, -20, -39, 13, 7, -3, + -27, 49, -18, 28, -17, -43, + -74, -11, 34, 14, 7, 7, + 11, 73, 2, 39, -21, -6, + 14, -8, -24, 47, -29, -6, + -25, -4, 13, -12, -44, -26, + -18, -16, -7, -10, -14, 34, + 17, -44, 25, 31, -7, 37, + 5, 23, 63, -16, 8, -68, + 15, 30, -29, -9, -10, -8, + -20, -2, 16, 45, 15, 10, + -14, 27, 46, -58, -8, 35, + -27, -11, -2, 0, -8, 3, + 23, 1, -49, 42, 38, -77, + -5, 51, -31, 12, 23, 7, + 3, -35, 1, 56, 6, -36, + 25, 1, -8, -35, -5, 9, + -53, 40, -58, 3, -28, -23, + 29, 26, 44, 47, 45, 3, + -18, 32, -13, -38, 3, 20, + 23, -8, -6, -8, 15, -17, + 4, -23, 29, 26, -3, 17, + -1, 7, -6, 20, -6, -4, + -3, -17, 0, -40, 0, -54, + 10, 61, -5, 33, 28, 41, + -71, 9, 36, 46, 14, 68, + -50, 6, 12, -42, -12, -23, + -66, 32, -36, 68, -45, 44, + 11, -24, -32, -15, -16, -17, + 14, -16, -10, -46, 1, -83, + 4, -4, -13, 31, -20, -28, + -25, -44, -9, 33, 21, 2, + 50, -1, -15, 20, -19, 47, + -21, 16, 18, -13, -14, 23, + 0, -17, -13, 24, -4, -25, + -65, 28, -7, -10, 43, -23, + -13, -19, 32, 37, -1, 33, + -38, -21, 2, -12, -13, -22, + 23, -28, -10, -71, 4, -19, + -30, 18, -31, 39, 34, -32, + 14, -56, -22, -6, 7, -22, + -69, 4, 27, 48, -72, -32, + 1, -16, -32, 0, 20, 19, + -1, -26, -18, 29, -45, 7, + 29, -6, -15, -10, 2, -32, + 4, 2, 9, -13, -24, -24, + -2, -4, -20, 18, 39, 2, + -19, -11, 45, 62, 11, 6, + -33, -34, -23, 22, 16, 23, + 18, 23, 52, 5, 50, 48, + -53, 36, -51, 14, 22, 60, + 11, -24, -54, -42, 37, -14, + 27, -5, 47, -25, 48, 3, + -39, -60, -29, 47, -39, 28, + -11, 5, 6, -19, 42, 7, + -4, 13, -6, -11, 625, -142772, + 3081512, -23436068, 88543033, -191701755, 253750691, -209692355, + 106676515, -31628670, 4833320, -286363, 2528, 10, + 23, -15, 6, 3, -2, -34, + 59, 17, -5, -47, 2, -22, + -34, 19, -22, 5, 11, 75, + -28, -43, 37, 1, 47, 51, +}; diff --git a/test/cmocka/src/math/fft/ref_fft_multi_3072_32.h b/test/cmocka/src/math/fft/ref_fft_multi_3072_32.h new file mode 100644 index 000000000000..25e70400ccf6 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi_3072_32.h @@ -0,0 +1,2068 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_FFT_MULTI_3072_NUM_TESTS 1 + +static const int32_t fft_in_real_3072_q31[3072] = { + 372, -3573, -1008, 217, -780, 436, + -1549, -852, -2495, 1920, -990, 2031, + -1837, -1265, 107, -2253, 2173, -458, + 3792, -194, 423, 799, 701, 1111, + -2804, -608, 1177, -1518, 168, 1765, + 705, -254, -3040, 1816, -2288, -285, + -1613, -1936, 688, -3208, -4065, -349, + -966, -1253, -1, 817, 111, -3848, + 205, 1017, -2528, 2877, 174, -1019, + 2896, 307, 1621, 520, 3704, 931, + 823, 2510, 3310, 1172, 4812, 931, + 1606, 2074, 2256, -1087, 2452, 758, + 589, 2385, 1960, -2318, -2127, -4529, + -4734, 105, -4991, -7191, -4860, -5616, + -2791, -5424, -4297, -5662, -8319, -6945, + -5017, -2177, -4699, -1601, 604, -43, + 1878, 3462, 1152, 1164, 2308, 5171, + 8093, 6337, 9436, 9868, 12643, 11458, + 11732, 12804, 8785, 10229, 11049, 12522, + 10680, 5304, 6307, 3106, 6523, 1343, + 258, -3209, -4227, -5295, -7664, -10933, + -9853, -13973, -18784, -16492, -20604, -22894, + -19663, -21716, -19330, -19486, -20742, -19535, + -16630, -15494, -14231, -10701, -8950, -5354, + -2341, 157, 6564, 11704, 18055, 14585, + 21646, 28327, 29665, 32553, 35738, 35431, + 38650, 39954, 38001, 43701, 38676, 35777, + 37697, 30835, 28715, 23077, 16120, 10116, + 1842, -2231, -12878, -19231, -23871, -33268, + -39644, -46730, -52379, -58782, -59834, -67902, + -68580, -70729, -72311, -70437, -71116, -65100, + -62389, -52520, -45857, -39326, -26646, -17904, + -5812, 7728, 15285, 31013, 43597, 56440, + 68135, 76812, 89464, 101782, 109968, 113335, + 121569, 117890, 122090, 118167, 117262, 109348, + 104021, 95523, 81365, 63317, 50309, 32668, + 13461, -7822, -28259, -51658, -72664, -91775, + -115036, -131884, -148209, -161626, -176665, -186642, + -198422, -201251, -204468, -199154, -194769, -184574, + -170630, -155814, -133647, -111067, -82874, -53815, + -23251, 8690, 45733, 77325, 109576, 147709, + 178113, 208648, 234279, 261877, 284629, 296896, + 312298, 317591, 320982, 318739, 305377, 291686, + 270019, 245901, 215298, 175604, 137830, 90294, + 41554, -10071, -62629, -117838, -169306, -223248, + -270854, -323501, -368270, -403786, -438021, -462004, + -483065, -495690, -501584, -494599, -479802, -453999, + -421113, -384132, -333536, -274847, -214043, -141020, + -68871, 9322, 93150, 174657, 257553, 338309, + 414683, 487699, 555110, 613887, 662617, 705407, + 734778, 750029, 756904, 750785, 728812, 693681, + 641368, 582598, 505227, 422816, 325847, 224093, + 111558, -5393, -128174, -253153, -371497, -497447, + -611885, -720876, -818284, -911629, -982314, -1042069, + -1089267, -1113410, -1121889, -1111498, -1080988, -1028361, + -955932, -867286, -759764, -631297, -494221, -341335, + -174492, -1266, 175797, 353877, 535388, 712596, + 885107, 1043835, 1190169, 1319079, 1429815, 1519748, + 1579473, 1619092, 1633179, 1618264, 1574576, 1499577, + 1397206, 1267140, 1106626, 928445, 727130, 507505, + 271402, 21420, -236596, -495465, -757620, -1006830, + -1249141, -1479683, -1690633, -1879331, -2034859, -2165655, + -2256619, -2315157, -2332427, -2310891, -2246487, -2143264, + -1999884, -1816213, -1596280, -1342502, -1052822, -742495, + -407978, -57316, 304579, 672838, 1038655, 1398459, + 1742918, 2065247, 2365675, 2631021, 2853345, 3036470, + 3167820, 3249898, 3281470, 3252625, 3164310, 3019310, + 2822626, 2564728, 2259683, 1900120, 1508700, 1070684, + 603408, 110951, -392666, -903614, -1414802, -1912902, + -2392206, -2845130, -3258570, -3627149, -3940690, -4191313, + -4381803, -4499619, -4541815, -4504007, -4388011, -4192289, + -3919064, -3569292, -3147477, -2658923, -2113464, -1518547, + -874826, -209524, 487728, 1191134, 1892304, 2573893, + 3234254, 3855470, 4423871, 4927377, 5359814, 5713992, + 5972621, 6140505, 6199387, 6153667, 5998277, 5738563, + 5368890, 4896998, 4329184, 3671418, 2930085, 2121158, + 1254388, 347574, -591983, -1544910, -2490043, -3420032, + -4315360, -5152121, -5921191, -6611696, -7199706, -7679390, + -8034751, -8257121, -8346135, -8290828, -8093048, -7744783, + -7254418, -6630540, -5870181, -4992728, -4006965, -2925017, + -1770290, -553992, 701532, 1972732, 3243885, 4485736, + 5676566, 6798847, 7830355, 8753293, 9542274, 10185538, + 10668092, 10977869, 11100656, 11039240, 10778861, 10326862, + 9684417, 8861605, 7863637, 6708489, 5407284, 3980889, + 2454492, 851943, -806049, -2488656, -4160522, -5801884, + -7381535, -8865301, -10234725, -11457830, -12501687, -13359571, + -14004580, -14421804, -14594932, -14515706, -14190718, -13607659, + -12780027, -11711622, -10410644, -8902247, -7209085, -5351692, + -3360190, -1266353, 892180, 3085982, 5277651, 7423286, + 9487880, 11431794, 13220058, 14818486, 16199378, 17322667, + 18173106, 18731015, 18968208, 18891463, 18480248, 17738440, + 16674383, 15296941, 13630301, 11690888, 9508065, 7111137, + 4541597, 1838855, -953433, -3788691, -6620413, -9392119, + -12060485, -14576464, -16894758, -18969314, -20757213, -22224208, + -23337383, -24068281, -24396675, -24314555, -23807617, -22876611, + -21528574, -19784004, -17663705, -15191458, -12403961, -9347173, + -6060577, -2608229, 959950, 4586727, 8204034, 11755744, + 15172504, 18397037, 21372442, 24033132, 26334534, 28221481, + 29661590, 30621139, 31064526, 30984600, 30361616, 29206481, + 27520780, 25328643, 22655207, 19532705, 16011679, 12149179, + 7998202, 3629080, -886601, -5477122, -10060474, -14562086, + -18899133, -22989928, -26765395, -30151720, -33079322, -35496765, + -37343077, -38580863, -39174876, -39103667, -38354970, -36935358, + -34846029, -32114319, -28772721, -24876871, -20476549, -15641187, + -10440364, -4966127, 700841, 6459485, 12215659, 17866676, + 23313028, 28458228, 33210198, 37478907, 41172064, 44232678, + 46576561, 48163284, 48945603, 48900048, 48012912, 46278450, + 43710721, 40344152, 36215687, 31392482, 25936258, 19939304, + 13485840, 6683808, -355573, -7517128, -14679416, -21710106, + -28499406, -34910051, -40834645, -46165701, -50790443, -54626140, + -57579532, -59598013, -60619069, -60618781, -59567039, -57473025, + -54351412, -50233342, -45186383, -39261858, -32564132, -25185248, + -17241901, -8866923, -191879, 8633665, 17460936, 26143204, + 34521609, 42447110, 49780242, 56379237, 62120194, 66881659, + 70575603, 73119678, 74443740, 74499636, 73282198, 70781179, + 67012890, 62026148, 55887344, 48687496, 40526263, 31529575, + 21836507, 11612109, 1012091, -9779981, -20582181, -31204035, + -41466004, -51182619, -60176524, -68284491, -75345078, -81225915, + -85799183, -88971434, -90663991, -90821930, -89419903, -86450743, + -81949463, -75956415, -68564796, -59875217, -50011014, -39129949, + -27400942, -15013360, -2168850, 10917793, 24023847, 36925822, + 49394121, 61211286, 72157333, 82036329, 90656560, 97852309, + 103475793, 107411172, 109549870, 109844745, 108245148, 104766008, + 99424144, 92289308, 83453912, 73051237, 61227750, 48165694, + 34079160, 19189890, 3741027, -12005929, -27789733, -43333372, + -58369825, -72626480, -85852717, -97799740, -108240568, -116984834, + -123841326, -128673829, -131365348, -131830251, -130042187, -125987529, + -119708342, -111271729, -100800507, -88439340, -74371460, -58820447, + -42024813, -24265428, -5823474, 12987814, 31851444, 50439832, + 68434255, 85515447, 101367399, 115712690, 128275627, 138809813, + 147111488, 153005021, 156352343, 157056501, 155072568, 150396562, + 143063101, 133170013, 120845814, 106268769, 89657765, 71271888, + 51399185, 30366381, 8513394, -13791446, -36175759, -58247278, + -79630509, -99940520, -118815593, -135911795, -150904974, -163518047, + -173494300, -180628604, -184757144, -185767143, -183596719, -178244443, + -169749533, -158227572, -143833336, -126769181, -107293920, -85709208, + -62364441, -37631290, -11919266, 14347827, 40716579, 66739386, + 91969993, 115952914, 138266858, 158500447, 176282916, 191272406, + 203177017, 211746908, 216794498, 218182573, 215846442, 209774794, + 200015892, 186692556, 169994049, 150152492, 127483522, 102323384, + 75084856, 46201855, 16153098, -14559068, -45419047, -75892600, + -105455486, -133589527, -159788255, -183572055, -204512930, -222207105, + -236312548, -246537938, -252661829, -254527285, -252044844, -245204000, + -234070892, -218777349, -199540150, -176640610, -150422459, -121292087, + -89721942, -56221556, -21340285, 14334216, 50205554, 85654350, + 120069924, 152846317, 183399211, 211180614, 235673463, 256424814, + 273019784, 285138036, 292514936, 294953678, 292364878, 284724191, + 272110317, 254679055, 232666741, 206401006, 176282044, 142782930, + 106435316, 67827972, 27606004, -13567407, -54989891, -95960432, + -135762579, -173703133, -209109185, -241342374, -269808493, -293980021, + -313386899, -327646179, -336453636, -339592042, -336942587, -328480069, + -314289983, -294549465, -269535128, -239608257, -205233219, -166948378, + -125366856, -81167440, -35076509, 12137668, 59676374, 106721077, + 152465978, 196107885, 236879838, 274040630, 306911433, 334892873, + 357441507, 374108431, 384553642, 388516901, 385863592, 376571435, + 360716345, 338509581, 310254184, 276376144, 237395341, 193917688, + 146647470, 96356984, 43868781, -9933526, -64145444, -117835189, + -170084338, -219972544, -266627410, -309204586, -346936289, -379122173, + -405155218, -424514827, -436810151, -441744679, -439162883, -429030505, + -411439631, -386617413, -354911037, -316798931, -272863878, -223795489, + -170394207, -113517117, -54112101, 6829649, 68271983, 129181249, + 188492354, 245177826, 298242279, 346730695, 389776661, 426578154, + 456438915, 478787617, 493156906, 499218782, 496797130, 485840086, + 466453824, 438883546, 403526720, 360909157, 311693565, 256651431, + 196672699, 132738813, 65908364, -2703538, -71935942, -140613095, + -207543775, -271573069, -331567032, -386461954, -435270224, -477095415, + -511150801, -536776982, -553457499, -560821589, -558658317, -546905800, + -525675660, -495251147, -456064122, -408695891, -353884464, -292507426, + -225550806, -154103971, -79358011, -2561945, 74990922, 151974456, + 227067781, 298963701, 366402727, 428187197, 483209074, 530460127, + 569065103, 598275256, 617513188, 626357580, 624559602, 612058838, + 588971043, 555592552, 512412748, 460076790, 399404508, 331355368, + 257033083, 177659157, 94542334, 9080697, -77291728, -163095921, + -246863323, -327129624, -402505892, -471643480, -533307653, -586384181, + -629887100, -662983451, -685030545, -695536926, -694237467, -681049278, + -656096022, -619710506, -572410016, -514922467, -448143694, -373128295, + -291109814, -203423941, -111523060, -16946439, 78702051, 173797563, + 266709385, 355818638, 439585563, 516517252, 585239763, 644525256, + 693261354, 730544741, 755634274, 768002388, 767333019, 753544351, + 726750519, 687313547, 635808270, 573021365, 499930935, 417715763, + 327699155, 231373047, 130330697, 26255704, -79077473, -183883762, + -286364208, -384749243, -477322091, -562450927, -638620614, -704458584, + -758759964, -800505747, -828885262, -843307676, -843428140, -829125298, + -800541387, -758052984, -702291149, -634095686, -554553702, -464934785, + -366695229, -261454617, -150966943, -37076378, 78289104, 193169085, + 305591559, 413616449, 515365690, 609043518, 692999321, 765716588, + 825874492, 872350263, 904253049, 920935675, 921993322, 907300938, + 876995158, 831492911, 771451746, 697804425, 611711609, 514553983, + 407924116, 293581677, 173416032, 49451086, -76220456, -201456944, + -324120836, -442096257, -553320447, -655855947, -747885861, -827768799, + -894049560, -945498889, -981150629, -1000271847, -1002432788, -987484122, + -955566735, -907106665, -842823854, -763720833, -671044190, -566294105, + -451177423, -327601471, -197612754, -63402956, 72760120, 208568511, + 341689943, 469838167, 590782890, 702408508, 802758269, 890034724, + 962657597, 1019303575, 1058896759, 1080652859, 1084088210, 1069029598, + 1035618264, 984312724, 915867520, 831363489, 732141019, 619797883, + 496179013, 363327875, 223462244, 78928184, -67831872, -214319471, + -358035612, -496500520, -627323350, -748214481, -857046183, -951889165, + -1031049603, -1093062609, -1136780159, -1161344249, -1166220616, -1151212846, + -1116462912, -1062447094, -989978191, -900185174, -794510265, -674662535, + -542611316, -400546431, -250829785, -95990652, 61366328, 218558108, + 372901738, 521744570, 662502854, 792737450, 910165194, 1012696160, + 1098503418, 1166031146, 1214025412, 1241556119, 1248038839, 1233252312, + 1197338095, 1140793802, 1064472412, 969574944, 857621750, 730435938, + 590107881, 438968868, 279545499, 114515179, -53332932, -221139123, + -386045481, -545210951, -695893623, -835474544, -961505113, -1071770327, + -1164307836, -1237438055, -1289820122, -1320452961, -1328709383, -1314332855, + -1277452999, -1218591232, -1138644358, -1038871318, -920887278, -786611045, + -638256294, -478293717, -309395514, -134403655, 43716046, 221948477, + 397235398, 566578363, 727061393, 875885710, 1010467343, 1128436049, + 1227704280, 1306480900, 1363339414, 1397194675, 1407372472, 1393581163, + 1355953850, 1295026075, 1211729278, 1107379980, 983679487, 842642384, + 686602223, 518156042, 340129235, 155518548, -32551931, -220890139, + -406278195, -585537160, -755583489, -913469206, -1056447718, -1182017615, + -1287952094, -1372373602, -1433740315, -1470904340, -1483138314, -1470125229, + -1431990546, -1369269446, -1282934208, -1174373193, -1045338593, -897949621, + -734659284, -558177505, -371469791, -177689875, 19897308, 217914039, + 413000387, 601804247, 781081356, 947739871, 1098873275, 1231848458, + 1344327873, 1434310884, 1500178253, 1540716776, 1555129431, 1543082456, + 1504676705, 1440471424, 1351471197, 1239098180, 1105185347, 951941327, + 781912112, 597936823, 403109189, 200711702, -5827201, -212996516, + -417263748, -615131936, -803202303, -978233490, -1137186723, -1277303294, + -1396118945, -1491537327, -1561856292, -1605781912, -1622476857, -1611576361, + -1573161776, -1507803264, -1416525319, -1300803759, -1162529626, -1003997711, + -827837307, -637004368, -434709124, -224359341, -9529003, 206138691, + 418964803, 625310311, 821624595, 1004540605, 1170892708, 1317790091, + 1442669662, 1543328211, 1617988707, 1665290217, 1684351248, 1674761398, + 1636600581, 1570429050, 1477314812, 1358748196, 1216694357, 1053500806, + 871896317, 674924682, 465908519, 248377622, 26015600, -197400277, + -418050818, -632173339, -836090410, -1026306638, -1199532255, -1352774350, + -1483362532, -1589011002, -1667857340, -1718486144, -1739962335, -1731840810, + -1694189001, -1627581900, -1533073579, -1412215425, -1266999164, -1099845212, + -913551939, -711244528, -496342110, -272477568, -43447743, 186853426, + 414497132, 635604535, 846382113, 1043217377, 1222716978, 1381788493, + 1517666640, 1627985742, 1710809548, 1764671488, 1788582982, 1782076477, + 1745200236, 1678510858, 1583099752, 1460517021, 1312810748, 1142441329, + 952273264, 745504463, 525629176, 296376863, 61629633, -174618632, + -408342794, -635547128, -852353972, -1055045659, -1240135324, -1404435561, + -1545115420, -1659730825, -1746277289, -1803232403, -1829574223, -1824802377, + -1788944079, -1722556598, -1626725028, -1503023090, -1353527120, -1180736052, + -987563716, -777264704, -553397694, -319761871, -80318116, 160854501, + 399645250, 631985939, 853909923, 1061611331, 1251535092, 1420412831, + 1565341387, 1683811150, 1773776008, 1833654782, 1862391453, 1859458840, + 1824851861, 1759129786, 1663371340, 1539171366, 1388613977, 1214226218, + 1018956327, 806101706, 579277790, 342327686, 99281607, -145729280, + -388524088, -624973189, -851026538, -1062835803, -1256769433, -1429499244, + -1578069680, -1699911201, -1792938289, -1855528096, -1886587771, -1885558778, + -1852429664, -1787734857, -1692550025, -1568466400, -1417586538, -1242447341, + -1046019000, -831624085, -602913005, -363765229, -118251153, 129457667, + 375134811, 614592317, 843748087, 1058698271, 1255758464, 1431568802, + 1583117023, 1707808398, 1803500889, 1868550498, 1901833106, 1902758600, + 1871299790, 1807979837, 1713850848, 1590514279, 1440046976, 1265017072, + 1068378419, 853480525, 623981978, 383772466, 136960898, -112268288, + -359659896, -601003283, -832179172, -1049261809, -1248533101, -1426603183, + -1580432180, -1707395953, -1805328349, -1872549473, -1907910206, -1910814775, + -1881202917, -1819574231, -1726982026, -1604991549, -1455688417, -1281609582, + -1085722448, -871357291, -642173873, -402075571, -155147588, 94400620, + 342321129, 584394446, 816488006, 1034659652, 1235193836, 1414674308, + 1570050564, 1698682278, 1798381561, 1867461880, 1904745928, 1909621460, + 1882002289, 1822370756, 1731752675, 1611705013, 1464279579, 1291998030, + 1097801079, 885007491, 657247751, 418407719, 172550487, -76118746, + -323372208, -565006313, -796894006, -1015107018, -1215927812, -1395948753, + -1552119395, -1681790895, -1782774050, -1853366552, -1892385206, -1899187777, + -1873679839, -1816317016, -1728099817, -1610555232, -1465702231, -1296030798, + -1104443064, -894224213, -668970217, -432524377, -188922860, 57680630, + 303083765, 543111971, 773679620, 990878213, 1191015166, 1370695312, + 1526895364, 1656961023, 1758718736, 1830458745, 1870990611, 1879657894, + 1856353863, 1801500924, 1716067064, 1601550638, 1459926812, 1293641207, + 1105551152, 898884149, 677182586, 444237696, 204031857, -39343627, + -281736298, -519024737, -747172550, -962310633, -1160791510, -1339271328, + -1494719175, -1624541086, -1726550849, -1799056437, -1840866215, -1851310975, + -1830256497, -1778117519, -1695817922, -1584815664, -1447032134, -1284862167, + -1101102449, -898911555, -681766646, -453381107, -217659996, 21366015, + 259627334, 493072531, 717731912, 929796840, 1125686578, 1302092995, + 1456042960, 1584965877, 1686703884, 1759582038, 1802411351, 1814517128, + 1795746957, 1746490037, 1667630110, 1560571974, 1427195337, 1269816814, + 1091157415, 894309346, 682655783, 459821541, 229631191, -3993204, + -237059049, -465606052, -685758770, -893780837, -1086166235, -1259671231, + -1411385009, -1538774911, -1639722862, -1712573317, -1756151511, -1769778723, + -1753291016, -1707044018, -1631880689, -1529156784, -1400686108, -1248703573, + -1075859349, -885148396, -679846603, -463496048, -239788111, -12560535, + 214318802, 436987939, 651666136, 854732389, 1042749336, 1212562328, + 1361331574, 1486573736, 1586227826, 1658651760, 1702702242, 1717695626, + 1703457825, 1660303465, 1589051490, 1490989763, 1367859974, 1221822045, + 1055420110, 871556095, 673397091, 464356944, 248014359, 28080829, + -191693218, -407572184, -615900079, -813149545, -995996567, -1161375920, + -1306531882, -1429044334, -1526907572, -1598523621, -1642761569, -1658943247, + -1646894744, -1606892066, -1539710329, -1446580159, -1329162799, -1189527590, + -1030127747, -853735167, -663407611, -462418808, -254229501, -42399820, + 169456638, 377724875, 578889840, 769552187, 946493762, 1106754813, + 1247677619, 1366914015, 1462520817, 1532951923, 1577094138, 1594286405, + 1584336159, 1547503054, 1484508014, 1396513358, 1285105867, 1152266026, + 1000323211, 831943670, 650031253, 457742924, 258379751, 55360097, + -147846433, -347791305, -541082791, -724454616, -894833732, -1049361614, + -1185484687, -1300948925, -1393867554, -1462752654, -1506521824, -1524533384, + -1516574802, -1482884630, -1424136518, -1341432851, -1236268049, -1110524433, + -966418198, -806474656, -633479500, -450427103, -260466143, -66854834, + 127098863, 318089721, 502893013, 678382955, 841619455, 989876004, + 1120697339, 1231931272, 1321770079, 1388772538, 1431906568, 1450534876, + 1444442644, 1413845056, 1359367791, 1282042512, 1183277772, 1064854075, + 928867553, 777701643, 614003268, 440609784, 260505083, 76790900, + -107401371, -288931568, -464730053, -631836635, -787442491, -928965186, + -1054051161, -1160657065, -1247066123, -1311885917, -1354123223, -1373168202, + -1368802284, -1341216760, -1290982804, -1219066595, -1126792942, -1015826842, + -888151193, -746007399, -591889851, -428465269, -258572080, -85121742, + 88920688, 260585671, 426981992, 585294900, 732878617, 867277717, + 986273316, 1087923620, 1170580702, 1232948145, 1274057596, 1293321664, + 1290530992, 1265838308, 1219781089, 1153257231, 1067495900, 964056608, + 844792140, 711809082, 567448255, 414212554, 254760785, 91832000, + -71785113, -233304073, -389994059, -539215391, -678473322, -805453139, + -918071312, -1014479841, -1093139146, -1152809828, -1192574868, -1211869926, + -1210493120, -1188564867, -1146588764, -1085378215, -1006085479, -910161450, + -799328092, -675557523, -541026496, -398078579, -249185492, -96927040, + 56100459, 207288881, 354080272, 494009592, 624733114, 744082407, + 850101449, 941069115, 1015518946, 1072290089, 1110517423, 1129670265, + 1129533115, 1110223700, 1072184544, 1016169922, 943250152, 854763597, + 752304762, 637705517, 512980046, 380314890, 242012700, 100457755, + -41929112, -182717458, -319523659, -450054681, -572124060, -683719153, + -783001820, -868369330, -938460454, -992171022, -1028698784, -1047540077, + -1048477478, -1031607491, -997345635, -946379405, -879674816, -798478560, + -704259631, -598699131, -483675841, -361200006, -233396979, -102482690, + 29303374, 159718607, 286551799, 407675562, 521064808, 624853955, + 717339406, 797022340, 862641000, 913174146, 947865519, 966232390, + 968081056, 953484359, 922809892, 876682824, 816002928, 741894612, + 655708808, 559003777, 453484070, 341012181, 223536838, 103102585, + -18231207, -138395994, -255358187, -367155417, -471922910, -567935035, + -653617482, -727595050, -788689017, -835957241, -868699728, -886469086, + -889064437, -876548172, -849255973, -807751705, -752850349, -685578717, + -607173529, -519046712, -422764499, -320025539, -212631771, -102431653, + 8679050, 118808590, 226088922, 328724742, 424998537, 513330924, + 592282938, 660578068, 717148585, 761116085, 791826700, 808868239, + 812060341, 801441718, 777312861, 740179100, 690781536, 630052357, + 559110226, 479237115, 391866261, 298532311, 200875179, 100588108, + -610935, -100984350, -198848126, -292555400, -380546365, -461371121, + -533714162, -596419791, -648495691, -689153805, -717786679, -734004557, + -737643044, -728735072, -707539194, -674510633, -630315927, -575794155, + -511962755, -439967668, -361115320, -276796807, -188485656, -97721711, + -6063325, 84929152, 173707386, 258789883, 338754416, 412300822, + 478218897, 535461035, 583136381, 620504801, 647030016, 662347093, + 666298302, 658915851, 640421042, 611217389, 571909299, 523236434, + 466118540, 401593676, 330829977, 255074713, 175659977, 93973455, + 11414720, -70601436, -150685191, -227503101, -299773173, -366307069, + -426034100, -477991736, -521372745, -555521252, -579940444, -594295661, + -598442639, -592398963, -576367295, -550703332, -515942267, -472744367, + -421927480, -364422131, -301274182, -233603649, -162596392, -89494303, + -15558951, 57945069, 129779304, 198738559, 263672984, 323523850, + 377322092, 424207594, 463456672, 494471834, 516803451, 530158177, + 534393266, 529522630, 515724338, 493304606, 462743275, 424626320, + 379680922, 328730698, 272703820, 212598528, 149477147, 84438014, + 18611869, -46890812, -110948255, -172487905, -230496546, -284018556, + -332192437, -374254634, -409548650, -437541760, -457837031, -470164722, + -474394574, -470538855, -458739378, -439284058, -412572405, -379141514, + -339620640, -294741156, -245331348, -192260455, -136472440, -78951410, + -20681431, 37338334, 94122301, 148721185, 200232600, 247810779, + 290690901, 328188337, 359735133, 384848064, 403172538, 414463652, + 418610740, 415613591, 405605607, 388825120, 365626134, 336479343, + 301938434, 262645580, 219323579, 172743491, 123741607, 73166108, + 21901695, -29183784, -79217342, -127361553, -172827260, -214863245, + -252797135, -286027063, -314046252, -336431187, -352861785, -363131190, + -367130392, -364860806, -356427781, -342050458, -322027327, -296771219, + -266766470, -232577223, -194827396, -154198752, -111414668, -67220706, + -22389838, 22307679, 66124103, 108321476, 148198106, 185107523, + 218456075, 247717969, 272443667, 292266337, 306907078, 316173250, + 319972907, 318303699, 311259083, 299016458, 281848796, 260101048, + 234203589, 204633082, 171949718, 136725579, 99604730, 61231692, + 22273999, -16596878, -54722051, -91473029, -126228497, -158429158, + -187562194, -213164905, -234846275, -252286330, -265238700, -273536116, + -277094400, -275914375, -270072015, -259723698, -245095661, -226492133, + -204280400, -178876569, -150746899, -120409997, -88411434, -55305328, + -21667576, 11918194, 44883235, 76677980, 106780616, 134691029, + 159972434, 182226557, 201111853, 216348627, 227724715, 235098889, + 238395584, 237611210, 232806177, 224118037, 211737832, 195926515, + 176998172, 155309580, 131268918, 105312714, 77901800, 49526741, + 20677629, -8152943, -36463737, -63797045, -89689774, -113724824, + -135517472, -154731255, -171066319, -184289182, -194215635, -200718014, + -203729844, -203249948, -199333372, -192088472, -181686292, -168339828, + -152317100, -133929642, -113514481, -91450898, -68133602, -43973447, + -19397877, 5181202, 29338391, 52668207, 74790435, 95343031, + 114004002, 130473256, 144509701, 155902177, 164494452, 170183422, + 172913199, 172664116, 169497118, 163505317, 154823158, 143635522, + 130168501, 114678360, 97469233, 78842181, 59141556, 38714750, + 17918761, -2890580, -23352359, -43134629, -61902442, -79359178, + -95219793, -109241655, -121213199, -130959126, -138341127, -143279885, + -145714907, -145650458, -143112905, -138187337, -130992820, -121679590, + -110437544, -97489588, -83076189, -67465699, -50939873, -33792500, + -16322159, 1168621, 18385872, 35036145, 50842116, 65557638, + 78945236, 90795089, 100928151, 109206567, 115506792, 119754384, + 121907623, 121965051, 119953463, 115936809, 110018616, 102324285, + 93009785, 82258499, 70282778, 57293087, 43527865, 29239498, + 14664699, 70861, -14299001, -28213778, -41434394, -53740906, + -64954354, -74898839, -83413372, -90382889, -95713352, -99339509, + -101224772, -101365811, -99785822, -96538276, -91706578, -85398224, + -77737953, -68883543, -59001121, -48272419, -36897641, -25072795, + -13015236, -928046, 10981346, 22514261, 33483859, 43710738, + 53031141, 61298934, 68403208, 74226528, 78703859, 81766293, + 83402166, 83593718, 82365139, 79763031, 75844981, 70710156, + 64464541, 57223854, 49132714, 40341451, 31011508, 21310849, + 11407368, 1476260, -8314581, -17806980, -26836240, -35256930, + -42939854, -49774817, -55645608, -60473208, -64195712, -66770589, + -68169750, -68386355, -67439994, -65369396, -62224639, -58081970, + -53024988, -47151459, -40577074, -33432655, -25843582, -17943272, + -9879653, -1786795, 6204057, 13943017, 21315103, 28198305, + 34483247, 40076675, 44890339, 48859763, 51930920, 54068789, + 55255655, 55479959, 54760676, 53131015, 50625910, 47308295, + 43244014, 38521353, 33230411, 27468337, 21346443, 14969441, + 8451097, 1911594, -4546380, -10811070, -16777372, -22352502, + -27448560, -31988943, -35903458, -39138144, -41648387, -43410944, + -44400727, -44621343, -44081728, -42808165, -40830393, -38198108, + -34962490, -31195794, -26971588, -22366339, -17469059, -12364939, + -7146798, -1904260, 3270688, 8291813, 13081852, 17556488, + 21651104, 25302659, 28458917, 31067904, 33104793, 34537546, + 35361975, 35568405, 35171243, 34183205, 32633364, 30558842, + 28008752, 25031682, 21689735, 18045101, 14159915, 10112948, + 5974900, 1811564, -2298588, -6289153, -10097187, -13660268, + -16919025, -19831526, -22344434, -24432003, -26066684, -27225918, + -27897027, -28086260, -27792985, -27036877, -25834713, -24221524, + -22225205, -19892344, -17274057, -14413387, -11365046, -8183432, + -4931257, -1661870, 1574892, 4716073, 7715537, 10517058, + 13094848, 15384977, 17377333, 19030984, 20328238, 21250991, + 21798830, 21964593, 21748393, 21175692, 20254116, 19005897, + 17462773, 15654865, 13621029, 11397319, 9026624, 6554408, + 4021974, 1473276, -1045124, -3494283, -5828872, -8019481, + -10025125, -11819321, -13375815, -14668543, -15689994, -16418956, + -16857296, -16995023, -16846583, -16415125, -15716033, -14759735, + -13579195, -12195213, -10628145, -8917589, -7096262, -5190286, + -3236944, -1276058, 664754, 2555441, 4356032, 6042109, + 7595282, 8978157, 10184344, 11185233, 11977764, 12548965, + 12893033, 13012020, 12907487, 12584782, 12058266, 11340230, + 10442126, 9390046, 8200237, 6899404, 5512572, 4061687, + 2576181, 1082059, -399648, -1840723, -3216302, -4503358, + -5687931, -6747557, -7663720, -8435769, -9042960, -9483154, + -9751663, -9850907, -9778461, -9539916, -9147874, -8613425, + -7936567, -7146604, -6254913, -5277446, -4230376, -3136291, + -2020988, -890678, 223543, 1308679, 2340192, 3311287, + 4208466, 5007097, 5699297, 6284284, 6744247, 7081498, + 7287208, 7366198, 7318562, 7141633, 6855926, 6457825, + 5963094, 5371511, 4712336, 3985065, 3203226, 2395092, + 1563689, 724529, -106180, -913239, -1684731, -2407744, + -3072538, -3667103, -4189285, -4623149, -4965217, -5220752, + -5374082, -5440210, -5406704, -5282249, -5070729, -4783594, + -4415459, -3989230, -3500736, -2970824, -2398253, -1803663, + -1193152, -574547, 34052, 628024, 1193352, 1723345, + 2216278, 2654349, 3031779, 3355709, 3608106, 3794901, + 3913643, 3960671, 3940274, 3855545, 3701699, 3492897, + 3230771, 2919037, 2567523, 2182907, 1769008, 1336204, + 894476, 450016, 4193, -419198, -833301, -1219488, + -1571324, -1888273, -2167536, -2401825, -2582554, -2722866, + -2806550, -2845009, -2831941, -2765462, -2661468, -2513744, + -2323485, -2105147, -1854412, -1580356, -1286629, -975301, + -656393, -339857, -25917, 279482, 571766, 848201, + 1100367, 1327317, 1524758, 1690162, 1819819, 1918854, + 1980841, 2008787, 1998777, 1955867, 1882817, 1780155, + 1648781, 1489634, 1319263, 1122357, 915235, 703731, + 481879, 255745, 35727, -179285, -387338, -576268, + -757789, -914450, -1054956, -1171327, -1261362, -1329783, + -1378263, -1393224, -1392519, -1361178, -1306723, -1240796, + -1149249, -1040253, -919112, -788188, -644100, -491012, + -342989, -186968, -35569, 111048, 254402, 388767, + 509286, 617211, 714449, 793277, 860190, 907067, + 935048, 948515, 946097, 928525, 896936, 846039, + 783146, 710400, 630008, 540362, 441121, 340845, + 239764, 133643, 30048, -71439, -166063, -251751, + -336514, -413690, -476442, -527614, -569975, -607659, + -628455, -633038, -634976, -620199, -598848, -564510, + -525244, -476398, -419249, -365706, -299017, -231986, + -163672, -92415, -26440, 38907, 105485, 163003, + 216292, 267479, 308792, 345665, 374432, 397776, + 404976, 414881, 412461, 405962, 388957, 369428, + 345535, 309636, 276555, 239076, 192795, 150978, + 104505, 65702, 20859, -25024, -65606, -102706, + -135673, -165912, -198790, -220192, -234479, -251306, + -260362, -266001, -259886, -260002, -248657, -234334, + -217503, -202297, -179055, -150768, -125468, -98832, + -72894, -42018, -16516, 10166, 39386, 62450, + 82544, 102115, 120459, 135598, 149235, 157042, + 158816, 163383, 162876, 159670, 151270, 148796, + 135741, 125439, 109131, 94537, 77595, 61876, + 45016, 28294, 13536, -6488, -22571, -33842, + -48832, -63638, -72140, -79993, -87569, -91387, + -95105, -99573, -95906, -97510, -90434, -89172, + -80757, -73767, -68179, -54591, -49098, -38081, + -30096, -17678, -7483, 5124, 12679, 18818, + 30341, 33042, 42717, 49133, 51057, 55150, + 58448, 56577, 55508, 55179, 54289, 49140, + 48421, 43652, 34986, 33365, 29958, 21943, + 13434, 9563, 6068, -2185, -7641, -11314, + -14491, -18527, -21375, -25536, -28757, -27068, + -31902, -32247, -31210, -32378, -28844, -28972, + -26917, -25630, -19653, -19191, -12051, -13582, + -4826, -5962, -4862, 33, 4819, 6114, + 9049, 8981, 14172, 14118, 15072, 15034, + 13362, 14617, 16282, 17865, 16105, 14323, + 10499, 14625, 9801, 12096, 5293, 8147, + 4763, 1429, -173, 295, 161, -2375, + -3393, -8030, -6053, -7764, -7193, -6627, + -9527, -5178, -9881, -4584, -6991, -9292, + -4680, -4957, -5201, -6648, -1473, -1584, + -1987, -2221, 2201, 2720, -1950, 3637, + 2274, 2021, -940, 2507, 2115, 4251, + 1166, 6089, 4628, 2775, 1047, 4879, + 3630, 4012, 4345, 3681, -266, 1657, + 2323, 829, 3660, 1100, -605, 876, + -165, -2762, 1204, -1477, 1170, 1144, + -1294, 1092, -473, -2287, 641, -3627, + 953, -4014, -3664, 1544, -1398, -3629, + 880, -264, 338, 1087, 1064, 578, + 1306, 2399, 218, -903, 3089, 1797, + 434, 3576, 2306, 1934, 3420, 2750, + 373, -2829, -1670, 851, 1698, 227, + 3297, -3177, -2034, 108, -559, 2858, + -1395, -1436, -3109, 2556, -1476, -899, + 232, -2557, -1521, -2150, 1048, -826, +}; + +static const int32_t fft_in_imag_3072_q31[3072] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const int32_t fft_ref_real_3072_q31[3072] = { + -45, 22, 19, -6, 19, -10, + 21, 10, -22, 11, -4, -26, + -5, -42, 5, 6, 9, -28, + -19, 5, 4, 13, -6, -24, + -4, -32, -14, -5, -21, -19, + -14, 5, 1, 12, 17, -4, + 17, 6, -31, -49, 6, -14, + -10, 43, -3, -29, -20, -4, + 1, -37, 37, -25, 21, -56, + -6, 6, -12, 10, -2790, 237344, + -3579960, 21781560, -69391869, 129763729, -149772245, 107836740, + -47262115, 11753740, -1421223, 57093, -178, -10, + 16, -20, 6, -4, -33, -18, + -22, -12, -20, -5, -33, -9, + 0, 2, -36, 15, 11, 36, + 45, 16, 26, -15, 15, -13, + -4, 17, 24, 17, -4, 0, + 13, -19, 17, -3, 20, 11, + -26, -11, 3, 0, -12, 26, + 20, 10, 42, -8, -16, -56, + 4, -8, 11, 8, 40, -9, + 5, -40, 20, -4, 19, -17, + 11, -9, -21, -16, 31, 31, + 0, 36, -14, 0, 2, -9, + -35, -37, -37, 37, -6, -2, + -35, 3, -19, -11, 11, -3, + -5, -15, -4, 34, 0, 5, + -27, 10, 28, -14, 26, -20, + -27, 2, -4, 32, 12, 13, + -4, -19, 25, 30, 0, 2, + 7, 21, -28, -10, -21, 10, + -4, -8, 8, -1, -8, 35, + -18, -8, -20, 5, -17, 3, + 2, 11, -22, -13, 3, 27, + 8, 34, 6, -17, 31, -17, + 31, -34, -8, 0, 9, 5, + -22, 2, 19, -19, 8, 5, + 16, -8, 26, 6, 4, 21, + 25, -7, 11, -34, -4, 17, + 11, -1, -20, -28, -6, -38, + -7, 17, 15, -11, 32, -1, + 8, 21, -8, 30, -55, -19, + -14, -10, 8, 8, -14, -21, + 15, 27, 5, -12, 9, -24, + -7, -3, -8, -20, -14, -7, + 6, -28, -3, 1, -6, -21, + -21, 2, -22, 44, -5, -25, + -34, 18, 19, 5, 9, 23, + 7, 6, -20, 22, 0, -13, + 51, 11, 2, -16, -6, 0, + 8, -6, 0, 18, 16, 22, + 10, -7, -54, -11, -18, -8, + 5, 27, 12, -17, -24, 13, + 11, 9, 2, -12, 23, 0, + 12, 31, -14, 12, 9, 24, + 2, -1, 32, -8, 11, -9, + 26, 6, -1, -3, 7, 57, + -20, 10, 8, 13, -24, 3, + -7, -29, 46, 30, 0, 22, + -2, -20, 39, 24, -15, -2, + -2, 7, -16, -50, 29, -7, + -22, 23, 19, -21, -29, -22, + 32, -4, 9, -14, -20, -17, + -12, 2, -19, -24, 10, 22, + 10, 14, -15, -3, -41, -20, + 3, 6, 20, 10, 8, -11, + -4, 10, 2, -19, -10, 41, + -8, -6, -36, -35, -11, 0, + -11, 1, -3, -16, 12, -14, + -28, 2, 6, -10, -14, -2, + 14, 10, -7, -13, 37, 17, + -1, 12, 9, -37, 34, -36, + 7, 8, 4, -13, 22, 24, + 19, 0, 24, 26, -33, -30, + 28, 19, -26, 20, -29, -12, + -2, -25, -26, 1, 3, 43, + -4, -12, -23, 4, -19, 21, + -34, -3, 55, -20, -29, -23, + 30, 51, 13, -15, 10, 9, + 17, -28, -23, -16, 64, -1, + 5, 10, -4, 29, 26, -7, + 18, -37, -24, 49, -18, 11, + -15, -29, 34, -2, -15, -17, + -6, 16, -15, 7, 29, -9, + 23, 18, 10, -10, 23, -33, + 28, -19, -1, 31, -13, 5, + -5, -47, -21, 29, 4, 13, + -7, -19, 2, 9, -31, 3, + 3, -3, 4, -1, -32, -34, + -11, -29, 11, -7, 44, 13, + -25, -12, -21, 6, 5, -6, + 71, -5, -4, 25, -4, -6, + -39, 16, -26, 9, -2, -14, + -3, -7, -5, -8, -21, -20, + -25, 9, 10, 2, -44, 2, + 16, 3, 31, 8, -16, -5, + 6, -7, 9, 7, 3, -15, + -13, 11, -44, 11, -4, 14, + 15, 6, -39, -2, -23, 9, + 13, -48, 19, 9, 7, -24, + 15, 43, -17, 40, 6, -26, + -36, 2, -30, 28, 8, -5, + -16, -20, 25, 48, -17, -6, + -45, 31, 7, 5, 27, 21, + 19, 36, -25, 18, 4, 3, + -20, -23, 8, -27, 27, -8, + -20, 23, -18, -13, -12, 13, + 2, 1, 15, 23, -10, 24, + -42, -46, 54, 18, -13, -11, + 5, 24, 12, 12, -19, 6, + -52, -10, 0, -2, -4, -10, + -14, 12, 12, -15, -17, 46, + 26, 20, 38, 16, -9, -12, + 0, -28, -8, -6, 4, -13, + 5, 7, 5, 0, 2, 10, + -15, 9, -2, 39, -13, 9, + 7, 11, -7, 26, 9, -11, + -20, -26, 42, 32, -22, -13, + 10, 39, 10, 6, -15, 25, + -17, -9, 14, -9, -5, -33, + 5, -23, -30, 0, 1, -6, + 3, 37, -15, 7, -4, 17, + 29, 14, 20, 11, -5, -14, + 35, 12, -13, -12, 8, -27, + 0, -8, -7, -8, 30, 23, + -41, 8, -28, 35, 53, 21, + 27, -17, -32, -5, -48, 4, + -8, 19, -2, -29, 17, 6, + -11, 2, -7, 0, 0, 1, + -34, -22, 22, -13, 10, 2, + -15, 22, 0, -47, 9, -1, + -42, -7, -10, 10, -21, -55, + 25, -27, -15, -21, -23, 10, + 2, -35, 20, -20, -3, 2, + -28, 9, 12, 40, 3, 25, + -9, -19, 15, 7, 8, -11, + 19, 10, -1, -15, -11, 32, + -32, -50, 29, -12, 13, 11, + -6, 30, 4, -26, 9, 3, + -4, 13, -32, -16, -9, 10, + 33, 26, 27, -23, -35, 10, + 15, -5, 53, 8, -25, -10, + -5, 7, 9, 11, -4, -34, + -7, 2, -5, 11, -13, -61, + -24, 18, -16, 13, 9, -45, + 10, 31, -9, 13, -3, 11, + 31, -30, 38, -14, -3, 18, + 26, 10, 10, 17, -16, -3, + -6, 37, -36, -17, -3, 30, + 14, 6, -31, -1, 8, -39, + 18, 20, 17, 22, -35, -12, + 0, -5, -6, -2, -37, 20, + -10, -16, -2, -5, 21, -8, + -5, 18, -12, -17, -5, 4, + -33, -8, -33, -23, -25, -14, + -15, 4, 53, -61, -6, 34, + -3, 11, -53, -7, -6, -11, + 28, 4, -16, -6, -13, -3, + 35, 3, -15, -16, 24, 16, + 25, 45, 5, -18, 2, 15, + 19, 42, 33, 17, 39, 8, + 3, 0, -12, -19, -9, 31, + 15, 40, 19, 8, 7, 5, + 14, -33, 8, -3, 16, -33, + -31, -13, -31, 37, -28, -19, + 6, 0, -46, 29, -22, -10, + -8, -2, -42, 29, -35, 10, + 40, 20, 8, 19, -13, 8, + 6, -2, 20, -15, 27, -42, + -11, 13, -1, 30, 31, 29, + 36, -27, 11, 36, 0, 3, + -9, 12, 1, -26, -8, 17, + -18, -9, -44, 23, -8, -36, + 2, 36, 41, 33, -28, -25, + 7, -8, 29, 43, 13, 19, + -7, 19, -19, -6, 34, -3, + 25, 40, 1, 3, -4, 5, + -16, -11, 36, 3, -17, -31, + 13, 3, -13, 3, -5, 6, + -6, -19, 1, -4, -7, 13, + -25, 26, -1, 26, -40, 0, + -1, -34, 21, 31, -22, 23, + 14, -19, 25, -7, 21, 31, + -6, 16, -16, 10, 28, 7, + -28, 7, -33, -6, 8, -31, + -16, -11, -3, -6, -7, 18, + -18, 24, 31, -24, 32, -43, + 9, -8, 12, 25, -21, 13, + -7, -5, -18, -48, -4, -33, + 15, 11, 7, 26, -10, -28, + -20, 8, 40, 15, 56, -35, + -42, 16, 3, -36, -25, 6, + 11, 24, -35, 10, -4, 5, + 17, 25, 73, -2, 72, -20, + -5, 19, 13, -8, -27, -18, + -11, 2, -15, 12, 16, -20, + -23, -12, -5, 47, 12, 9, + -14, 1, -10, 15, -4, -9, + -8, -5, -18, 28, -49, 18, + 35, 11, -8, 12, -10, -13, + 13, -4, -7, 4, 1, -13, + 13, 21, 28, 15, 19, -3, + 15, -8, 38, 31, -15, 21, + -8, -4, -10, 34, 3, -18, + -1, -20, -18, 16, -41, -3, + -10, -4, 15, -25, 2, -11, + -4, -14, 6, -14, -10, -17, + 10, -27, 51, -51, 30, 13, + -15, 4, -12, -55, -3, 17, + -7, -4, 0, -15, -28, -29, + -12, -29, 12, 6, -12, -46, + 9, 4, 9, -21, 10, 4, + 7, -9, -22, 4, -3, -8, + -15, 53, 26, 5, -19, -24, + 13, 16, -16, -26, 20, -35, + -26, 25, -15, 4, -23, 30, + -18, 11, -31, -2, -13, 24, + 3, 9, -1, 1, -1, -7, + 10, 29, -4, -1, 5, 12, + 5, 6, 3, 22, -18, 11, + -26, -4, -10, 10, -13, 7, + 13, 1, 36, -9, 35, 32, + 2, 7, -20, 19, -6, -18, + 15, -8, 33, 20, -9, -18, + 25, 29, 40, -23, -6, 34, + -21, 5, 21, -7, -2, 7, + -16, -3, 2, -18, 23, 9, + 62, 21, 32, 2, 6, -16, + 25, -9, -8, 31, 6, 37, + 14, 30, -36, -15, 4, 16, + 25, -13, 23, 26, 38, -5, + -27, 20, 27, -2, 9, -22, + 47, -3, 6, 42, 12, 17, + 8, -7, 47, 43, 2, 3, + -24, 9, -3, -11, 5, 42, + 13, 7, -23, -36, 22, 26, + -6, 18, -11, -15, -17, 18, + 2, 36, -40, -1, -18, -42, + 33, 56, 10, -1, 16, -2, + 6, -23, 16, 7, -35, -5, + -13, -11, -4, 10, 5, 5, + 33, 0, 8, 23, -19, 31, + -23, 2, -51, -30, -24, -28, + 13, -10, 8, -19, 14, -23, + -8, 3, -14, 17, -36, -21, + 12, 41, -5, 26, -4, -10, + 25, 40, -21, -4, 17, 8, + -22, -3, -38, 22, 5, 28, + 38, 0, -3, 1, 20, -11, + -3, -6, 28, -26, 9, -21, + 5, -14, -2, -42, -14, 23, + -21, -24, -13, 20, -19, -13, + -3, -7, 20, 13, -16, 18, + -14, -2, 14, 31, -1, -12, + -25, -2, 1, -9, -32, 37, + -5, -3, 30, -13, -7, 12, + 31, 12, -7, -13, 30, -3, + -5, 37, -32, -9, 1, -2, + -25, -12, -1, 31, 14, -2, + -14, 18, -16, 13, 20, -7, + -3, -13, -19, 20, -13, -24, + -21, 23, -14, -42, -2, -14, + 5, -21, 9, -26, 28, -6, + -3, -11, 20, 1, -3, 0, + 38, 28, 5, 22, -38, -3, + -22, 8, 17, -4, -21, 40, + 25, -10, -4, 26, -5, 41, + 12, -21, -36, 17, -14, 3, + -8, -23, 14, -19, 8, -10, + 13, -28, -24, -30, -51, 2, + -23, 31, -19, 23, 8, 0, + 33, 5, 5, 10, -4, -11, + -13, -5, -35, 7, 16, -23, + 6, -2, 16, -1, 10, 56, + 33, -42, -18, -1, -40, 36, + 2, 18, -17, -15, -11, 18, + -6, 26, 22, -36, -23, 7, + 13, 42, 5, -11, -3, 9, + -24, 3, 2, 43, 47, -7, + 8, 17, 12, 42, 6, -3, + 47, -22, 9, -2, 27, 20, + -27, -5, 38, 26, 23, -13, + 25, 16, 4, -15, -36, 30, + 14, 37, 6, 31, -8, -9, + 25, -16, 6, 2, 32, 21, + 62, 9, 23, -18, 2, -3, + -16, 7, -2, -7, 21, 5, + -21, 34, -6, -23, 40, 29, + 25, -18, -9, 20, 33, -8, + 15, -18, -6, 19, -20, 7, + 2, 32, 35, -9, 36, 1, + 13, 7, -13, 10, -10, -4, + -26, 11, -18, 22, 3, 6, + 5, 12, 5, -1, -4, 29, + 10, -7, -1, 1, -1, 9, + 3, 24, -13, -2, -31, 11, + -18, 30, -23, 4, -15, 25, + -26, -35, 20, -26, -16, 16, + 13, -24, -19, 5, 26, 53, + -15, -8, -3, 4, -22, -9, + 7, 4, 10, -21, 9, 4, + 9, -46, -12, 6, 12, -29, + -12, -29, -28, -15, 0, -4, + -7, 17, -3, -55, -12, 4, + -15, 13, 30, -51, 51, -27, + 10, -17, -10, -14, 6, -14, + -4, -11, 2, -25, 15, -4, + -10, -3, -41, 16, -18, -20, + -1, -18, 3, 34, -10, -4, + -8, 21, -15, 31, 38, -8, + 15, -3, 19, 15, 28, 21, + 13, -13, 1, 4, -7, -4, + 13, -13, -10, 12, -8, 11, + 35, 18, -49, 28, -18, -5, + -8, -9, -4, 15, -10, 1, + -14, 9, 12, 47, -5, -12, + -23, -20, 16, 12, -15, 2, + -11, -18, -27, -8, 13, 19, + -5, -20, 72, -2, 73, 25, + 17, 5, -4, 10, -35, 24, + 11, 6, -25, -36, 3, 16, + -42, -35, 56, 15, 40, 8, + -20, -28, -10, 26, 7, 11, + 15, -33, -4, -48, -18, -5, + -7, 13, -21, 25, 12, -8, + 9, -43, 32, -24, 31, 24, + -18, 18, -7, -6, -3, -11, + -16, -31, 8, -6, -33, 7, + -28, 7, 28, 10, -16, 16, + -6, 31, 21, -7, 25, -19, + 14, 23, -22, 31, 21, -34, + -1, 0, -40, 26, -1, 26, + -25, 13, -7, -4, 1, -19, + -6, 6, -5, 3, -13, 3, + 13, -31, -17, 3, 36, -11, + -16, 5, -4, 3, 1, 40, + 25, -3, 34, -6, -19, 19, + -7, 19, 13, 43, 29, -8, + 7, -25, -28, 33, 41, 36, + 2, -36, -8, 23, -44, -9, + -18, 17, -8, -26, 1, 12, + -9, 3, 0, 36, 11, -27, + 36, 29, 31, 30, -1, 13, + -11, -42, 27, -15, 20, -2, + 6, 8, -13, 19, 8, 20, + 40, 10, -35, 29, -42, -2, + -8, -10, -22, 29, -46, 0, + 6, -19, -28, 37, -31, -13, + -31, -33, 16, -3, 8, -33, + 14, 5, 7, 8, 19, 40, + 15, 31, -9, -19, -12, 0, + 3, 8, 39, 17, 33, 42, + 19, 15, 2, -18, 5, 45, + 25, 16, 24, -16, -15, 3, + 35, -3, -13, -6, -16, 4, + 28, -11, -6, -7, -53, 11, + -3, 34, -6, -61, 53, 4, + -15, -14, -25, -23, -33, -8, + -33, 4, -5, -17, -12, 18, + -5, -8, 21, -5, -2, -16, + -10, 20, -37, -2, -6, -5, + 0, -12, -35, 22, 17, 20, + 18, -39, 8, -1, -31, 6, + 14, 30, -3, -17, -36, 37, + -6, -3, -16, 17, 10, 10, + 26, 18, -3, -14, 38, -30, + 31, 11, -3, 13, -9, 31, + 10, -45, 9, 13, -16, 18, + -24, -61, -13, 11, -5, 2, + -7, -34, -4, 11, 9, 7, + -5, -10, -25, 8, 53, -5, + 15, 10, -35, -23, 27, 26, + 33, 10, -9, -16, -32, 13, + -4, 3, 9, -26, 4, 30, + -6, 11, 13, -12, 29, -50, + -32, 32, -11, -15, -1, 10, + 19, -11, 8, 7, 15, -19, + -9, 25, 3, 40, 12, 9, + -28, 2, -3, -20, 20, -35, + 2, 10, -23, -21, -15, -27, + 25, -55, -21, 10, -10, -7, + -42, -1, 9, -47, 0, 22, + -15, 2, 10, -13, 22, -22, + -34, 1, 0, 0, -7, 2, + -11, 6, 17, -29, -2, 19, + -8, 4, -48, -5, -32, -17, + 27, 21, 53, 35, -28, 8, + -41, 23, 30, -8, -7, -8, + 0, -27, 8, -12, -13, 12, + 35, -14, -5, 11, 20, 14, + 29, 17, -4, 7, -15, 37, + 3, -6, 1, 0, -30, -23, + 5, -33, -5, -9, 14, -9, + -17, 25, -15, 6, 10, 39, + 10, -13, -22, 32, 42, -26, + -20, -11, 9, 26, -7, 11, + 7, 9, -13, 39, -2, 9, + -15, 10, 2, 0, 5, 7, + 5, -13, 4, -6, -8, -28, + 0, -12, -9, 16, 38, 20, + 26, 46, -17, -15, 12, 12, + -14, -10, -4, -2, 0, -10, + -52, 6, -19, 12, 12, 24, + 5, -11, -13, 18, 54, -46, + -42, 24, -10, 23, 15, 1, + 2, 13, -12, -13, -18, 23, + -20, -8, 27, -27, 8, -23, + -20, 3, 4, 18, -25, 36, + 19, 21, 27, 5, 7, 31, + -45, -6, -17, 48, 25, -20, + -16, -5, 8, 28, -30, 2, + -36, -26, 6, 40, -17, 43, + 15, -24, 7, 9, 19, -48, + 13, 9, -23, -2, -39, 6, + 15, 14, -4, 11, -44, 11, + -13, -15, 3, 7, 9, -7, + 6, -5, -16, 8, 31, 3, + 16, 2, -44, 2, 10, 9, + -25, -20, -21, -8, -5, -7, + -3, -14, -2, 9, -26, 16, + -39, -6, -4, 25, -4, -5, + 71, -6, 5, 6, -21, -12, + -25, 13, 44, -7, 11, -29, + -11, -34, -32, -1, 4, -3, + 3, 3, -31, 9, 2, -19, + -7, 13, 4, 29, -21, -47, + -5, 5, -13, 31, -1, -19, + 28, -33, 23, -10, 10, 18, + 23, -9, 29, 7, -15, 16, + -6, -17, -15, -2, 34, -29, + -15, 11, -18, 49, -24, -37, + 18, -7, 26, 29, -4, 10, + 5, -1, 64, -16, -23, -28, + 17, 9, 10, -15, 13, 51, + 30, -23, -29, -20, 55, -3, + -34, 21, -19, 4, -23, -12, + -4, 43, 3, 1, -26, -25, + -2, -12, -29, 20, -26, 19, + 28, -30, -33, 26, 24, 0, + 19, 24, 22, -13, 4, 8, + 7, -36, 34, -37, 9, 12, + -1, 17, 37, -13, -7, 10, + 14, -2, -14, -10, 6, 2, + -28, -14, 12, -16, -3, 1, + -11, 0, -11, -35, -36, -6, + -8, 41, -10, -19, 2, 10, + -4, -11, 8, 10, 20, 6, + 3, -20, -41, -3, -15, 14, + 10, 22, 10, -24, -19, 2, + -12, -17, -20, -14, 9, -4, + 32, -22, -29, -21, 19, 23, + -22, -7, 29, -50, -16, 7, + -2, -2, -15, 24, 39, -20, + -2, 22, 0, 30, 46, -29, + -7, 3, -24, 13, 8, 10, + -20, 57, 7, -3, -1, 6, + 26, -9, 11, -8, 32, -1, + 2, 24, 9, 12, -14, 31, + 12, 0, 23, -12, 2, 9, + 11, 13, -24, -17, 12, 27, + 5, -8, -18, -11, -54, -7, + 10, 22, 16, 18, 0, -6, + 8, 0, -6, -16, 2, 11, + 51, -13, 0, 22, -20, 6, + 7, 23, 9, 5, 19, 18, + -34, -25, -5, 44, -22, 2, + -21, -21, -6, 1, -3, -28, + 6, -7, -14, -20, -8, -3, + -7, -24, 9, -12, 5, 27, + 15, -21, -14, 8, 8, -10, + -14, -19, -55, 30, -8, 21, + 8, -1, 32, -11, 15, 17, + -7, -38, -6, -28, -20, -1, + 11, 17, -4, -34, 11, -7, + 25, 21, 4, 6, 26, -8, + 16, 5, 8, -19, 19, 2, + -22, 5, 9, 0, -8, -34, + 31, -17, 31, -17, 6, 34, + 8, 27, 3, -13, -22, 11, + 2, 3, -17, 5, -20, -8, + -18, 35, -8, -1, 8, -8, + -4, 10, -21, -10, -28, 21, + 7, 2, 0, 30, 25, -19, + -4, 13, 12, 32, -4, 2, + -27, -20, 26, -14, 28, 10, + -27, 5, 0, 34, -4, -15, + -5, -3, 11, -11, -19, 3, + -35, -2, -6, 37, -37, -37, + -35, -9, 2, 0, -14, 36, + 0, 31, 31, -16, -21, -9, + 11, -17, 19, -4, 20, -40, + 5, -9, 40, 8, 11, -8, + 4, -56, -16, -8, 42, 10, + 20, 26, -12, 0, 3, -11, + -26, 11, 20, -3, 17, -19, + 13, 0, -4, 17, 24, 17, + -4, -13, 15, -15, 26, 16, + 45, 36, 11, 15, -36, 2, + 0, -9, -33, -5, -20, -12, + -22, -18, -33, -4, 6, -20, + 16, -10, -178, 57093, -1421223, 11753740, + -47262115, 107836740, -149772245, 129763729, -69391869, 21781560, + -3579960, 237344, -2790, 10, -12, 6, + -6, -56, 21, -25, 37, -37, + 1, -4, -20, -29, -3, 43, + -10, -14, 6, -49, -31, 6, + 17, -4, 17, 12, 1, 5, + -14, -19, -21, -5, -14, -32, + -4, -24, -6, 13, 4, 5, + -19, -28, 9, 6, 5, -42, + -5, -26, -4, 11, -22, 10, + 21, -10, 19, -6, 19, 22, +}; + +static const int32_t fft_ref_imag_3072_q31[3072] = { + 0, -1, -4, -15, -6, 19, + 1, 14, 47, -16, 15, 7, + 11, -9, -21, 4, 30, 43, + 16, 41, -11, 34, -26, 1, + 5, -11, -9, 45, -15, -18, + 18, -1, -6, 47, 25, -24, + -21, -56, 19, -1, 2, -12, + -15, 28, -26, 5, 15, 0, + 3, -17, 33, 0, -32, -16, + 10, 21, -16, -2, -3984, 340956, + -5154182, 31427830, -100341944, 188051672, -217523306, 156961255, + -68943044, 17183326, -2082337, 83868, -223, -19, + -32, -29, 1, 20, -16, 53, + 22, 26, -19, 7, -22, -18, + 4, 3, -20, 25, -23, 5, + -23, 17, -26, 23, -25, 7, + -19, -41, 14, -20, -1, 11, + 3, -12, -4, 11, 23, 8, + 15, 4, 2, 23, 26, 9, + 30, 31, -20, -17, -38, 39, + -23, 7, 10, 18, 17, 0, + 23, -15, 12, 25, -9, -28, + 34, -19, -23, 6, 11, 1, + -13, -3, 19, 23, -10, -19, + 25, 5, -3, -7, -22, 17, + 43, -32, 10, -10, -43, -34, + 25, 1, 7, -26, 4, 21, + -2, 5, 2, -15, -1, 19, + -19, -1, 37, -18, -44, 15, + -14, 1, 24, -11, -14, 6, + -20, -14, 16, -11, 31, 35, + 14, -4, 3, 17, -22, -21, + 24, -32, 26, 43, -9, -20, + -13, -21, 15, -25, 30, -11, + -14, -2, -28, -23, -21, 8, + 24, -9, -36, -29, 1, 6, + -6, 0, -11, -19, 22, 15, + 29, -28, -12, 18, 18, 4, + 10, -56, 7, -21, -32, 11, + -20, -18, -35, 19, -15, 4, + 42, -7, 43, 2, 9, -11, + 14, 9, -2, 25, 14, -4, + 0, 7, 19, 7, 21, 20, + -9, 20, 22, -22, -18, 21, + -19, 16, 0, 2, -8, -24, + 20, 13, -6, 15, -20, -19, + -35, -21, -1, 0, 22, 11, + 20, 14, -14, 41, 36, -2, + -4, 1, 35, 4, 19, -12, + 3, -5, -26, -26, -33, 12, + 13, -21, -20, 18, -23, -14, + -13, -23, -14, 20, -20, 12, + 16, 7, 7, 12, -9, 15, + -17, 20, 29, 12, -7, -11, + 17, -35, -18, 6, -3, 22, + -10, -12, -21, 21, 12, -4, + -28, 27, -8, -5, -8, 21, + -9, 16, 19, -13, -1, 0, + -40, 34, 1, -22, -7, 5, + 25, 15, -5, -38, 17, 35, + -11, 19, -8, -9, -19, 42, + 10, 10, -63, 3, -39, 18, + -7, 32, -2, 0, 7, 18, + 20, 11, -57, -22, -1, 18, + -13, 13, -11, 5, -32, 16, + -11, 40, 3, 8, -7, -62, + -5, 22, -16, -6, 15, 34, + 20, -55, 16, 36, 19, 30, + 8, 31, -2, 19, -46, -12, + -20, -7, -13, -15, -5, 6, + 9, -12, -6, 23, -7, 7, + -33, -23, -1, -17, -2, 0, + -1, 9, 11, 42, -3, -57, + -42, 3, -13, -30, 26, -13, + 26, -28, 17, -36, -32, 12, + 17, 8, -33, 27, 18, -13, + 3, 24, 3, 47, -8, 7, + 11, -17, 0, -12, -20, 12, + -15, -18, -6, -20, -6, 9, + 19, 20, -13, 4, 18, 3, + 11, -6, 37, 27, 18, -2, + -13, -8, 43, 33, -7, -11, + 7, 30, 3, 9, 17, 20, + -40, 25, 48, 8, 8, 29, + -23, 19, -13, -4, 30, -13, + 27, 18, 43, -1, 35, 28, + -38, -14, -32, 14, 14, -7, + 26, 4, -18, 37, -26, 5, + 18, 38, 6, 20, 15, 13, + 17, 27, 23, 21, 9, 7, + 37, 28, 35, -12, 11, -11, + -26, -5, 18, -56, 11, -31, + -20, 28, -21, 2, 35, -17, + -26, 30, -28, -4, 40, 6, + 19, -6, 11, 0, -1, 17, + 4, 0, -33, -4, 3, 17, + 18, 15, -15, 31, -14, -3, + -19, -8, 2, -50, 2, -5, + -12, 14, 18, -20, -2, 30, + -10, -50, -23, -7, -12, 8, + 6, -1, 39, 6, 0, -58, + 14, 20, 16, -14, -35, 0, + -19, 27, -11, -7, -19, 14, + 10, 0, 43, -18, 33, 5, + -10, 72, 4, -1, -7, -22, + -25, -24, 1, -8, 3, 1, + 45, 3, 22, 5, -12, -23, + -46, 11, 8, -19, 8, 39, + 4, 2, -31, 4, -8, 20, + 17, 33, -11, 4, -23, 8, + 10, -5, -4, 5, 25, -34, + -1, 18, -19, -8, -27, 8, + 5, -39, 48, -20, -13, 32, + 27, -31, 17, -21, 13, -9, + 11, 9, 33, -8, -26, 16, + -38, -1, -19, 6, 1, 2, + -2, 21, 42, -14, 27, 5, + -16, 22, -55, 18, -23, 74, + -14, 15, 2, 16, -8, -28, + -36, 27, 15, 1, 20, -6, + 15, 11, -56, 29, 10, 24, + 31, 13, -38, 24, -18, -16, + 16, 13, 4, -9, -6, 7, + 11, -1, -11, -28, -23, 24, + -4, -4, 22, 29, 10, -41, + -2, -24, -14, 13, -42, -20, + 26, 34, -5, -19, 15, 7, + -44, -15, -44, 21, -2, -37, + 25, 33, 8, 22, 30, -3, + 10, -13, 1, 13, 13, 26, + -26, 20, 37, 17, 22, 21, + 25, 1, 0, -17, -1, -5, + 6, -17, 5, -28, 29, 13, + 6, -32, -5, -30, 4, -3, + -13, -14, 35, 19, 31, 34, + 66, 11, -28, 31, 13, 2, + -6, 2, 52, -22, 5, -6, + 1, -21, 22, -46, -28, -10, + 42, 16, -26, 6, -21, -17, + -18, 5, 18, 11, -53, -3, + -9, 2, -3, 8, -7, 32, + 14, -26, 25, 5, 19, 1, + -3, 4, -10, 20, -12, -19, + -11, -35, 3, 11, -27, -10, + -15, -40, -10, 19, -1, -20, + -30, 2, 49, 21, 32, 16, + -43, -3, -34, -26, 4, -23, + 41, 6, 35, 25, 28, 20, + 3, 14, -12, -3, -14, -9, + 10, 26, 6, -42, 10, 21, + 18, 13, -23, 27, -5, -28, + 11, -2, -5, -19, 19, 12, + 32, -1, -12, -24, -11, -11, + -15, 8, 6, 38, 21, 29, + -17, -4, -40, 2, 11, -10, + 1, 10, -16, -12, -65, -5, + 23, 39, -40, -10, 23, -14, + 2, 38, -5, 3, 15, 19, + -1, 25, -20, -22, -24, -17, + 11, -9, -16, 4, 18, -10, + -5, -14, -24, -13, -20, 38, + -31, 17, -33, -15, -9, -25, + 9, -9, 8, -23, -5, 14, + 45, 10, -11, 9, -2, 2, + -17, -8, 11, -13, -24, -3, + 8, -4, -13, 22, 11, 28, + 4, 14, 28, 10, 16, -35, + 5, -8, -3, -24, 9, -22, + -32, 10, 24, -1, 27, 10, + 0, 13, -26, -3, 2, -13, + 24, 23, -20, -38, 13, 21, + -20, -11, -16, -24, -5, 4, + 21, 35, 9, 12, -2, 1, + 16, 15, -31, 47, 7, -3, + 18, -22, -7, 28, -7, -6, + 18, -6, -5, 6, -35, 11, + 18, 3, 9, 4, -4, 5, + -3, -26, 35, 22, 34, 42, + -24, 9, -24, 10, -23, 34, + -32, 30, -1, 32, 17, 13, + -26, 10, 0, -1, 23, 3, + -14, 59, -49, -35, 3, 1, + -17, -5, 0, 5, -5, 18, + 10, 4, -4, 18, -4, -19, + -33, -4, -5, 26, -9, -18, + 53, -30, 19, 23, 39, -9, + -6, 38, -10, 22, 13, -21, + 8, 1, 17, -21, 1, -18, + 34, 25, -4, -3, 32, 0, + -23, -2, -9, -13, 1, -5, + -2, 31, -29, -11, -16, 2, + -8, -29, -34, -44, -51, -28, + 7, -13, 9, -44, -3, 30, + -15, -33, 25, -26, 7, -21, + 40, 31, -5, 42, -18, -21, + 5, -17, 24, -7, 29, 5, + 17, 15, 3, 23, 19, -6, + -33, 12, -10, -31, 38, 6, + 26, 26, 6, 20, 18, 39, + 30, -6, -17, -13, 22, -49, + 10, -13, -16, 15, 12, 14, + -31, -17, -1, 17, 8, -32, + -28, -15, 9, -30, 23, -12, + 17, -22, -21, -60, -33, -16, + 13, -14, -7, 18, 20, -8, + -11, 3, -6, -35, -15, 27, + 24, 67, 10, -18, 8, -14, + 3, 11, -38, -1, -18, 26, + -21, 39, 3, -3, 34, -45, + 11, 0, 11, -2, -16, -7, + 34, -7, 22, 16, -22, -14, + 17, -15, -32, 9, 37, 5, + 27, -15, 24, 2, -9, -17, + -17, -11, -26, 8, 29, 9, + 21, -41, -3, 36, 8, 43, + 14, -6, 9, 5, -1, -3, + -38, -27, 9, 1, 13, 7, + -6, 54, 20, -18, 9, 0, + 10, 6, -8, 30, -17, -28, + -22, 7, 16, -42, 12, 14, + 29, -2, 21, 19, 0, -23, + 19, -16, -31, -3, -32, -45, + -52, -24, -27, 2, 15, -28, + -11, 24, -14, 9, -4, 6, + 3, 1, -22, 21, 5, 37, + 24, 33, 21, 14, -56, -20, + -12, -26, -20, -12, -42, -17, + -12, 0, 0, -7, -6, 14, + 37, -37, -6, -8, 18, -20, + 24, 12, 11, 14, 20, -24, + 6, -6, -1, -19, -7, 4, + 4, -11, -29, 6, -3, 18, + -37, -37, -26, -24, 17, -17, + -3, -21, 19, -2, 15, -5, + -14, 0, 6, 4, 9, -19, + 8, -13, 15, -14, -14, -28, + 19, -24, 40, 6, -10, -20, + -21, -38, -14, -11, 14, 12, + 31, 30, -1, 9, -5, -4, + -29, -20, 43, -7, -33, -10, + -31, 0, 9, 2, 15, 18, + -11, -11, -3, 12, 32, 31, + -9, -8, 19, -5, -2, -8, + -19, 7, 13, -10, -1, -4, + -38, -6, 6, -34, -14, -4, + -11, 6, 12, -18, 28, 73, + -21, 54, -16, 32, -17, 13, + -3, 5, -2, -5, -1, 22, + 8, 29, 15, -9, -26, -29, + 1, 28, -27, 15, 0, 26, + -28, 17, 7, -7, -4, 4, + -3, -22, -3, -25, -6, 10, + -26, -11, -19, -23, -14, 22, + 0, -10, 22, -5, -3, -11, + 27, -6, 27, -8, 19, -8, + -2, 12, 2, 53, 11, -46, + 0, 46, -11, -53, -2, -12, + 2, 8, -19, 8, -27, 6, + -27, 11, 3, 5, -22, 10, + 0, -22, 14, 23, 19, 11, + 26, -10, 6, 25, 3, 22, + 3, -4, 4, 7, -7, -17, + 28, -26, 0, -15, 27, -28, + -1, 29, 26, 9, -15, -29, + -8, -22, 1, 5, 2, -5, + 3, -13, 17, -32, 16, -54, + 21, -73, -28, 18, -12, -6, + 11, 4, 14, 34, -6, 6, + 38, 4, 1, 10, -13, -7, + 19, 8, 2, 5, -19, 8, + 9, -31, -32, -12, 3, 11, + 11, -18, -15, -2, -9, 0, + 31, 10, 33, 7, -43, 20, + 29, 4, 5, -9, 1, -30, + -31, -12, -14, 11, 14, 38, + 21, 20, 10, -6, -40, 24, + -19, 28, 14, 14, -15, 13, + -8, 19, -9, -4, -6, 0, + 14, 5, -15, 2, -19, 21, + 3, 17, -17, 24, 26, 37, + 37, -18, 3, -6, 29, 11, + -4, -4, 7, 19, 1, 6, + -6, 24, -20, -14, -11, -12, + -24, 20, -18, 8, 6, 37, + -37, -14, 6, 7, 0, 0, + 12, 17, 42, 12, 20, 26, + 12, 20, 56, -14, -21, -33, + -24, -37, -5, -21, 22, -1, + -3, -6, 4, -9, 14, -24, + 11, 28, -15, -2, 27, 24, + 52, 45, 32, 3, 31, 16, + -19, 23, 0, -19, -21, 2, + -29, -14, -12, 42, -16, -7, + 22, 28, 17, -30, 8, -6, + -10, 0, -9, 18, -20, -54, + 6, -7, -13, -1, -9, 27, + 38, 3, 1, -5, -9, 6, + -14, -43, -8, -36, 3, 41, + -21, -9, -29, -8, 26, 11, + 17, 17, 9, -2, -24, 15, + -27, -5, -37, -9, 32, 15, + -17, 14, 22, -16, -22, 7, + -34, 7, 16, 2, -11, 0, + -11, 45, -34, 3, -3, -39, + 21, -26, 18, 1, 38, -11, + -3, 14, -8, 18, -10, -67, + -24, -27, 15, 35, 6, -3, + 11, 8, -20, -18, 7, 14, + -13, 16, 33, 60, 21, 22, + -17, 12, -23, 30, -9, 15, + 28, 32, -8, -17, 1, 17, + 31, -14, -12, -15, 16, 13, + -10, 49, -22, 13, 17, 6, + -30, -39, -18, -20, -6, -26, + -26, -6, -38, 31, 10, -12, + 33, 6, -19, -23, -3, -15, + -17, -5, -29, 7, -24, 17, + -5, 21, 18, -42, 5, -31, + -40, 21, -7, 26, -25, 33, + 15, -30, 3, 44, -9, 13, + -7, 28, 51, 44, 34, 29, + 8, -2, 16, 11, 29, -31, + 2, 5, -1, 13, 9, 2, + 23, 0, -32, 3, 4, -25, + -34, 18, -1, 21, -17, -1, + -8, 21, -13, -22, 10, -38, + 6, 9, -39, -23, -19, 30, + -53, 18, 9, -26, 5, 4, + 33, 19, 4, -18, 4, -4, + -10, -18, 5, -5, 0, 5, + 17, -1, -3, 35, 49, -59, + 14, -3, -23, 1, 0, -10, + 26, -13, -17, -32, 1, -30, + 32, -34, 23, -10, 24, -9, + 24, -42, -34, -22, -35, 26, + 3, -5, 4, -4, -9, -3, + -18, -11, 35, -6, 5, 6, + -18, 6, 7, -28, 7, 22, + -18, 3, -7, -47, 31, -15, + -16, -1, 2, -12, -9, -35, + -21, -4, 5, 24, 16, 11, + 20, -21, -13, 38, 20, -23, + -24, 13, -2, 3, 26, -13, + 0, -10, -27, 1, -24, -10, + 32, 22, -9, 24, 3, 8, + -5, 35, -16, -10, -28, -14, + -4, -28, -11, -22, 13, 4, + -8, 3, 24, 13, -11, 8, + 17, -2, 2, -9, 11, -10, + -45, -14, 5, 23, -8, 9, + -9, 25, 9, 15, 33, -17, + 31, -38, 20, 13, 24, 14, + 5, 10, -18, -4, 16, 9, + -11, 17, 24, 22, 20, -25, + 1, -19, -15, -3, 5, -38, + -2, 14, -23, 10, 40, -39, + -23, 5, 65, 12, 16, -10, + -1, 10, -11, -2, 40, 4, + 17, -29, -21, -38, -6, -8, + 15, 11, 11, 24, 12, 1, + -32, -12, -19, 19, 5, 2, + -11, 28, 5, -27, 23, -13, + -18, -21, -10, 42, -6, -26, + -10, 9, 14, 3, 12, -14, + -3, -20, -28, -25, -35, -6, + -41, 23, -4, 26, 34, 3, + 43, -16, -32, -21, -49, -2, + 30, 20, 1, -19, 10, 40, + 15, 10, 27, -11, -3, 35, + 11, 19, 12, -20, 10, -4, + 3, -1, -19, -5, -25, 26, + -14, -32, 7, -8, 3, -2, + 9, 3, 53, -11, -18, -5, + 18, 17, 21, -6, 26, -16, + -42, 10, 28, 46, -22, 21, + -1, 6, -5, 22, -52, -2, + 6, -2, -13, -31, 28, -11, + -66, -34, -31, -19, -35, 14, + 13, 3, -4, 30, 5, 32, + -6, -13, -29, 28, -5, 17, + -6, 5, 1, 17, 0, -1, + -25, -21, -22, -17, -37, -20, + 26, -26, -13, -13, -1, 13, + -10, 3, -30, -22, -8, -33, + -25, 37, 2, -21, 44, 15, + 44, -7, -15, 19, 5, -34, + -26, 20, 42, -13, 14, 24, + 2, 41, -10, -29, -22, 4, + 4, -24, 23, 28, 11, 1, + -11, -7, 6, 9, -4, -13, + -16, 16, 18, -24, 38, -13, + -31, -24, -10, -29, 56, -11, + -15, 6, -20, -1, -15, -27, + 36, 28, 8, -16, -2, -15, + 14, -74, 23, -18, 55, -22, + 16, -5, -27, 14, -42, -21, + 2, -2, -1, -6, 19, 1, + 38, -16, 26, 8, -33, -9, + -11, 9, -13, 21, -17, 31, + -27, -32, 13, 20, -48, 39, + -5, -8, 27, 8, 19, -18, + 1, 34, -25, -5, 4, 5, + -10, -8, 23, -4, 11, -33, + -17, -20, 8, -4, 31, -2, + -4, -39, -8, 19, -8, -11, + 46, 23, 12, -5, -22, -3, + -45, -1, -3, 8, -1, 24, + 25, 22, 7, 1, -4, -72, + 10, -5, -33, 18, -43, 0, + -10, -14, 19, 7, 11, -27, + 19, 0, 35, 14, -16, -20, + -14, 58, 0, -6, -39, 1, + -6, -8, 12, 7, 23, 50, + 10, -30, 2, 20, -18, -14, + 12, 5, -2, 50, -2, 8, + 19, 3, 14, -31, 15, -15, + -18, -17, -3, 4, 33, 0, + -4, -17, 1, 0, -11, 6, + -19, -6, -40, 4, 28, -30, + 26, 17, -35, -2, 21, -28, + 20, 31, -11, 56, -18, 5, + 26, 11, -11, 12, -35, -28, + -37, -7, -9, -21, -23, -27, + -17, -13, -15, -20, -6, -38, + -18, -5, 26, -37, 18, -4, + -26, 7, -14, -14, 32, 14, + 38, -28, -35, 1, -43, -18, + -27, 13, -30, 4, 13, -19, + 23, -29, -8, -8, -48, -25, + 40, -20, -17, -9, -3, -30, + -7, 11, 7, -33, -43, 8, + 13, 2, -18, -27, -37, 6, + -11, -3, -18, -4, 13, -20, + -19, -9, 6, 20, 6, 18, + 15, -12, 20, 12, 0, 17, + -11, -7, 8, -47, -3, -24, + -3, 13, -18, -27, 33, -8, + -17, -12, 32, 36, -17, 28, + -26, 13, -26, 30, 13, -3, + 42, 57, 3, -42, -11, -9, + 1, 0, 2, 17, 1, 23, + 33, -7, 7, -23, 6, 12, + -9, -6, 5, 15, 13, 7, + 20, 12, 46, -19, 2, -31, + -8, -30, -19, -36, -16, 55, + -20, -34, -15, 6, 16, -22, + 5, 62, 7, -8, -3, -40, + 11, -16, 32, -5, 11, -13, + 13, -18, 1, 22, 57, -11, + -20, -18, -7, 0, 2, -32, + 7, -18, 39, -3, 63, -10, + -10, -42, 19, 9, 8, -19, + 11, -35, -17, 38, 5, -15, + -25, -5, 7, 22, -1, -34, + 40, 0, 1, 13, -19, -16, + 9, -21, 8, 5, 8, -27, + 28, 4, -12, -21, 21, 12, + 10, -22, 3, -6, 18, 35, + -17, 11, 7, -12, -29, -20, + 17, -15, 9, -12, -7, -7, + -16, -12, 20, -20, 14, 23, + 13, 14, 23, -18, 20, 21, + -13, -12, 33, 26, 26, 5, + -3, 12, -19, -4, -35, -1, + 4, 2, -36, -41, 14, -14, + -20, -11, -22, 0, 1, 21, + 35, 19, 20, -15, 6, -13, + -20, 24, 8, -2, 0, -16, + 19, -21, 18, 22, -22, -20, + 9, -20, -21, -7, -19, -7, + 0, 4, -14, -25, 2, -9, + -14, 11, -9, -2, -43, 7, + -42, -4, 15, -19, 35, 18, + 20, -11, 32, 21, -7, 56, + -10, -4, -18, -18, 12, 28, + -29, -15, -22, 19, 11, 0, + 6, -6, -1, 29, 36, 9, + -24, -8, 21, 23, 28, 2, + 14, 11, -30, 25, -15, 21, + 13, 20, 9, -43, -26, 32, + -24, 21, 22, -17, -3, 4, + -14, -35, -31, 11, -16, 14, + 20, -6, 14, 11, -24, -1, + 14, -15, 44, 18, -37, 1, + 19, -19, 1, 15, -2, -5, + 2, -21, -4, 26, -7, -1, + -25, 34, 43, 10, -10, 32, + -43, -17, 22, 7, 3, -5, + -25, 19, 10, -23, -19, 3, + 13, -1, -11, -6, 23, 19, + -34, 28, 9, -25, -12, 15, + -23, 0, -17, -18, -10, -7, + 23, -39, 38, 17, 20, -31, + -30, -9, -26, -23, -2, -4, + -15, -8, -23, -11, 4, 12, + -3, -11, 1, 20, -14, 41, + 19, -7, 25, -23, 26, -17, + 23, -5, 23, -25, 20, -3, + -4, 18, 22, -7, 19, -26, + -22, -53, 16, -20, -1, 29, + 32, 19, 223, -83868, 2082337, -17183326, + 68943044, -156961255, 217523306, -188051672, 100341944, -31427830, + 5154182, -340956, 3984, 2, 16, -21, + -10, 16, 32, 0, -33, 17, + -3, 0, -15, -5, 26, -28, + 15, 12, -2, 1, -19, 56, + 21, 24, -25, -47, 6, 1, + -18, 18, 15, -45, 9, 11, + -5, -1, 26, -34, 11, -41, + -16, -43, -30, -4, 21, 9, + -11, -7, -15, 16, -47, -14, + -1, -19, 6, 15, 4, 1, +}; diff --git a/test/cmocka/src/math/fft/ref_fft_multi_512_32.h b/test/cmocka/src/math/fft/ref_fft_multi_512_32.h new file mode 100644 index 000000000000..2f66b1943af0 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi_512_32.h @@ -0,0 +1,364 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_FFT_MULTI_512_NUM_TESTS 1 + +static const int32_t fft_in_real_512_q31[512] = { + 2377, 340, -1196, 1231, 390, -220, + 1663, -1097, 2649, 2272, 2236, 4342, + 3392, 4062, 6525, 5862, 5260, 4298, + 5946, 6952, 9757, 6742, 5507, 6233, + 2746, -6220, -7167, -15262, -27034, -37541, + -48308, -63366, -79216, -99095, -114978, -136892, + -158310, -176123, -192474, -205758, -221510, -225664, + -228096, -217668, -204746, -176198, -137635, -82142, + -9371, 74606, 179015, 298476, 439502, 594979, + 765297, 950034, 1143794, 1342066, 1544951, 1741581, + 1929492, 2099900, 2239228, 2342857, 2403695, 2406952, + 2348372, 2215760, 1999224, 1685659, 1277296, 767477, + 145652, -576843, -1412213, -2348478, -3374059, -4478609, + -5650739, -6865398, -8098727, -9324264, -10504916, -11605125, + -12596267, -13427768, -14058251, -14447678, -14546148, -14324532, + -13731373, -12741029, -11318240, -9445464, -7106292, -4298630, + -1028803, 2685749, 6812826, 11306975, 16107663, 21145964, + 26323168, 31551295, 36709825, 41672460, 46306375, 50477948, + 54028871, 56821040, 58704348, 59538514, 59202251, 57564674, + 54532854, 50034062, 44008837, 36428878, 27312638, 16697669, + 4668381, -8656667, -23115247, -38512817, -54605837, -71114797, + -87734187, -104118684, -119911490, -134714976, -148144714, -159788322, + -169256899, -176160487, -180148043, -180882561, -178086768, -171520785, + -161024629, -146479642, -127877567, -105271227, -78804161, -48731098, + -15371603, 20843417, 59393829, 99676740, 141010892, 182645196, + 223765608, 263517948, 301016662, 335366499, 365667808, 391049190, + 410689064, 423816593, 429762391, 427948384, 417924213, 399366813, + 372118999, 336184162, 291744393, 239157693, 178963703, 111897394, + 38855262, -39076188, -120670524, -204555997, -289250536, -373165551, + -454647551, -532020754, -603591727, -667697336, -722744462, -767256517, + -799860865, -819376406, -824826855, -815445853, -790753739, -750514716, + -694807177, -624005830, -538798080, -440180087, -329446119, -208181786, + -78228178, 58322457, 199177086, 341868299, 483806041, 622316802, + 754703901, 878291108, 990474654, 1088787157, 1170940744, 1234884629, + 1278855173, 1301396967, 1301443489, 1278304462, 1231723405, 1161876364, + 1069381916, 955316252, 821188818, 668927730, 500846793, 319639136, + 128281798, -69969079, -271643589, -473138138, -670788021, -860891365, + -1039840037, -1204143102, -1350521372, -1475985731, -1577855538, -1653868143, + -1702201550, -1721507212, -1710987200, -1670357852, -1599913631, -1500498908, + -1373524895, -1220918243, -1045119827, -849030441, -635951651, -409549533, + -173768611, 67236847, 309172231, 547685783, 778474962, 997324032, + 1200229451, 1383452973, 1543599999, 1677687708, 1783202582, 1858150469, + 1901102793, 1911207547, 1888235269, 1832550711, 1745137332, 1627554622, + 1481924147, 1310889170, 1117549902, 905412773, 678329960, 440406809, + 195946023, -50663943, -295003900, -532722276, -759616239, -971714214, + -1165343086, -1337202219, -1484407839, -1604573685, -1695818260, -1756812449, + -1786819343, -1785656952, -1753727278, -1692003786, -1601974636, -1485654570, + -1345493052, -1184355718, -1005445656, -812247941, -608443862, -397860620, + -184370436, 28155650, 235957789, 435414812, 623142459, 796038302, + 951331454, 1086646118, 1200032277, 1289966608, 1355409649, 1395802572, + 1411048221, 1401526273, 1368065265, 1311904927, 1234670391, 1138345134, + 1025205425, 897763065, 758730599, 610957451, 457356034, 300870453, + 144392851, -9273089, -157452086, -297686686, -427726193, -545602364, + -649633283, -738464975, -811055534, -866715451, -905106645, -926196810, + -930306878, -918048808, -890310025, -848238628, -793193671, -726739273, + -650563089, -566482249, -476362216, -382121302, -285648791, -188804509, + -93364778, -998556, 86774250, 168572629, 243214304, 309689690, + 367216509, 415201133, 453269644, 481254962, 499186921, 507293573, + 505953135, 495734458, 477315340, 451506885, 419217631, 381418708, + 339130862, 293409409, 245305078, 195852674, 146051406, 96847653, + 49123725, 3659924, -38835925, -77768267, -112648940, -143097159, + -168840927, -189723596, -205688470, -216780356, -223132535, -224963023, + -222563624, -216291546, -206547705, -193779025, -178448674, -161042676, + -142059071, -121973485, -101257674, -80361164, -59693896, -39639548, + -20528876, -2649969, 13743698, 28468278, 41381077, 52378701, + 61415428, 68489302, 73635092, 76919839, 78440949, 78342766, + 76763449, 73871913, 69846273, 64879055, 59156607, 52859212, + 46172815, 39271624, 32308042, 25436123, 18778046, 12454362, + 6550180, 1153222, -3690186, -7931022, -11549357, -14541771, + -16905259, -18670872, -19854696, -20504812, -20665306, -20388254, + -19735543, -18756855, -17510711, -16058137, -14452422, -12750215, + -10996406, -9230387, -7506048, -5841514, -4269596, -2815062, + -1498386, -320570, 699683, 1563959, 2280010, 2842827, + 3263548, 3556194, 3723649, 3782673, 3754077, 3639669, + 3463676, 3234034, 2965500, 2669406, 2362184, 2043555, + 1730398, 1426011, 1139067, 870062, 626287, 406552, + 214758, 52290, -81400, -192447, -276653, -339805, + -380854, -406690, -418638, -414054, -398956, -376437, + -345489, -315906, -280747, -249434, -213100, -176507, + -144467, -112761, -87348, -65472, -45559, -29659, + -17812, -6285, 5913, 11034, 14331, 17585, + 21840, 18597, 16523, 19606, 14800, 12216, + 13421, 8687, 9253, 5262, 7307, 4478, + 87, 917, 3655, 2959, -1190, -1801, + -2753, -174, -122, -410, -480, -795, + -1249, 1770, +}; + +static const int32_t fft_in_imag_512_q31[512] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, +}; + +static const int32_t fft_ref_real_512_q31[512] = { + -45, -91, 39, 13, 39, -12759, + 683966, -8435969, 44965977, -129224628, 221075980, -234823286, + 155575966, -62329239, 13936841, -1458185, 45393, -68, + -11, 94, 12, 28, -47, 61, + 89, -87, -33, 108, -49, -75, + -72, 76, -55, 53, 22, -71, + -24, 83, 42, -17, 71, 73, + 65, -2, 5, 63, -22, 0, + -22, 87, 31, -51, 42, -41, + -5, -51, 46, 32, -65, 92, + -3, 20, -36, -14, -131, -38, + 87, -49, 7, 6, 69, 9, + 26, -43, 11, -80, 145, -61, + 4, -4, -65, 76, 18, 25, + 118, -32, 8, 24, -76, 37, + -41, -23, 110, 126, -66, 55, + 12, -7, 119, -24, 29, -70, + 1, 42, -11, 118, 44, -5, + -28, -2, 33, -101, 36, -67, + 7, 19, -36, -15, 16, 16, + 30, 14, -41, -1, -6, -35, + -23, -50, 77, -11, 10, -28, + 102, 117, 41, 31, 39, 108, + 75, -68, -9, -6, 35, -69, + -52, 37, -81, 30, -76, -50, + 59, 0, 41, -24, 66, 61, + 6, -12, 28, 80, -68, 42, + 21, -62, 1, -103, -21, 7, + 46, 76, -48, 15, -76, 84, + 97, -35, 135, 18, 43, -20, + -22, 42, 54, 49, -48, -16, + -22, 18, -6, -76, 32, -80, + 25, 34, 8, 6, 9, 71, + -1, 97, -137, 52, -9, 0, + 2, 15, 19, -115, -40, 53, + 37, -22, -61, -72, -7, 4, + -41, 4, -44, -28, 16, -12, + -30, 17, 103, -24, 15, 41, + -25, -3, 15, -42, -73, 83, + -4, 49, 2, -96, 58, 85, + -11, -50, -24, -44, -75, -8, + 10, -23, 21, -26, 49, -50, + -40, 15, 87, -18, 58, -18, + 87, 15, -40, -50, 49, -26, + 21, -23, 10, -8, -75, -44, + -24, -50, -11, 85, 58, -96, + 2, 49, -4, 83, -73, -42, + 15, -3, -25, 41, 15, -24, + 103, 17, -30, -12, 16, -28, + -44, 4, -41, 4, -7, -72, + -61, -22, 37, 53, -40, -115, + 19, 15, 2, 0, -9, 52, + -137, 97, -1, 71, 9, 6, + 8, 34, 25, -80, 32, -76, + -6, 18, -22, -16, -48, 49, + 54, 42, -22, -20, 43, 18, + 135, -35, 97, 84, -76, 15, + -48, 76, 46, 7, -21, -103, + 1, -62, 21, 42, -68, 80, + 28, -12, 6, 61, 66, -24, + 41, 0, 59, -50, -76, 30, + -81, 37, -52, -69, 35, -6, + -9, -68, 75, 108, 39, 31, + 41, 117, 102, -28, 10, -11, + 77, -50, -23, -35, -6, -1, + -41, 14, 30, 16, 16, -15, + -36, 19, 7, -67, 36, -101, + 33, -2, -28, -5, 44, 118, + -11, 42, 1, -70, 29, -24, + 119, -7, 12, 55, -66, 126, + 110, -23, -41, 37, -76, 24, + 8, -32, 118, 25, 18, 76, + -65, -4, 4, -61, 145, -80, + 11, -43, 26, 9, 69, 6, + 7, -49, 87, -38, -131, -14, + -36, 20, -3, 92, -65, 32, + 46, -51, -5, -41, 42, -51, + 31, 87, -22, 0, -22, 63, + 5, -2, 65, 73, 71, -17, + 42, 83, -24, -71, 22, 53, + -55, 76, -72, -75, -49, 108, + -33, -87, 89, 61, -47, 28, + 12, 94, -11, -68, 45393, -1458185, + 13936841, -62329239, 155575966, -234823286, 221075980, -129224628, + 44965977, -8435969, 683966, -12759, 39, 13, + 39, -91, +}; + +static const int32_t fft_ref_imag_512_q31[512] = { + 0, 16, -60, 53, -58, -5240, + 284775, -3574190, 19378087, -56632327, 98507314, -106364728, + 71622799, -29159462, 6624575, -704027, 22181, -107, + 40, 52, 20, -56, -24, 12, + 16, -86, -125, 4, -12, 76, + -44, 24, 37, -11, 36, 32, + -10, 83, -45, 12, -22, 42, + -16, -11, 45, 41, 73, 29, + -59, 13, -10, -52, 9, -21, + -69, -51, -41, 13, -9, 102, + 4, 66, 62, -33, 113, -66, + -49, 36, -93, -52, -48, 49, + 56, 71, 1, 36, -56, -60, + -55, 36, -57, -130, 38, 51, + -69, 33, -49, -68, -10, 61, + 6, 29, 56, -41, -5, 18, + 65, 15, 71, 24, 27, -9, + 13, 19, 119, 52, -8, 26, + 60, -36, -5, 29, -25, -5, + -17, 3, 34, 21, -28, -92, + -21, -42, 28, 18, -95, 47, + 71, -4, -1, 47, -16, -27, + -25, 26, 16, 14, -92, 53, + -27, -14, 50, -23, 23, 87, + -45, 49, 156, -12, -49, 1, + 14, -22, -3, -33, -56, -39, + 24, -11, 74, -3, -36, -26, + -10, -5, 62, 48, -2, 58, + -111, 29, -20, 102, 104, -8, + -88, 41, 3, 24, 38, -40, + 79, -96, 11, 14, 23, -8, + 44, 26, -92, 14, 91, 9, + -74, -8, -40, 2, -99, -29, + -44, 10, -3, 49, -43, 11, + -66, -3, -1, 8, -2, 45, + 52, -39, 82, -32, -85, 55, + -59, -25, -58, -78, 34, 70, + -66, 104, -31, -5, 71, -56, + -25, -35, 37, 8, 18, 36, + 35, -15, 70, 86, 0, -54, + -65, -4, 45, 51, -101, 73, + 15, -27, 32, 32, 57, -22, + -3, -55, 46, -60, 0, 60, + -46, 55, 3, 22, -57, -32, + -32, 27, -15, -73, 101, -51, + -45, 4, 65, 54, 0, -86, + -70, 15, -35, -36, -18, -8, + -37, 35, 25, 56, -71, 5, + 31, -104, 66, -70, -34, 78, + 58, 25, 59, -55, 85, 32, + -82, 39, -52, -45, 2, -8, + 1, 3, 66, -11, 43, -49, + 3, -10, 44, 29, 99, -2, + 40, 8, 74, -9, -91, -14, + 92, -26, -44, 8, -23, -14, + -11, 96, -79, 40, -38, -24, + -3, -41, 88, 8, -104, -102, + 20, -29, 111, -58, 2, -48, + -62, 5, 10, 26, 36, 3, + -74, 11, -24, 39, 56, 33, + 3, 22, -14, -1, 49, 12, + -156, -49, 45, -87, -23, 23, + -50, 14, 27, -53, 92, -14, + -16, -26, 25, 27, 16, -47, + 1, 4, -71, -47, 95, -18, + -28, 42, 21, 92, 28, -21, + -34, -3, 17, 5, 25, -29, + 5, 36, -60, -26, 8, -52, + -119, -19, -13, 9, -27, -24, + -71, -15, -65, -18, 5, 41, + -56, -29, -6, -61, 10, 68, + 49, -33, 69, -51, -38, 130, + 57, -36, 55, 60, 56, -36, + -1, -71, -56, -49, 48, 52, + 93, -36, 49, 66, -113, 33, + -62, -66, -4, -102, 9, -13, + 41, 51, 69, 21, -9, 52, + 10, -13, 59, -29, -73, -41, + -45, 11, 16, -42, 22, -12, + 45, -83, 10, -32, -36, 11, + -37, -24, 44, -76, 12, -4, + 125, 86, -16, -12, 24, 56, + -20, -52, -40, 107, -22181, 704027, + -6624575, 29159462, -71622799, 106364728, -98507314, 56632327, + -19378087, 3574190, -284775, 5240, 58, -53, + 60, -16, +}; diff --git a/test/cmocka/src/math/fft/ref_fft_multi_768_32.h b/test/cmocka/src/math/fft/ref_fft_multi_768_32.h new file mode 100644 index 000000000000..e2addddba223 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi_768_32.h @@ -0,0 +1,532 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_FFT_MULTI_768_NUM_TESTS 1 + +static const int32_t fft_in_real_768_q31[768] = { + -241, 3628, 1266, -2634, 3092, 232, + -640, -2125, -647, -471, 2119, 325, + 924, 1109, 2295, 142, 2343, 4363, + 2796, 852, 2382, 3248, 59, -164, + -472, -531, -1894, -3358, -6065, -6495, + -10815, -14044, -14091, -21234, -21055, -28456, + -27657, -28889, -31938, -37655, -37301, -39941, + -37891, -34378, -35403, -25561, -19647, -12509, + -606, 7543, 27322, 43905, 60616, 82045, + 106206, 131271, 155362, 177405, 206514, 230378, + 252852, 269899, 284703, 292311, 298400, 296951, + 287396, 266368, 239466, 199332, 153113, 89801, + 17743, -67554, -159603, -263913, -379403, -500228, + -624420, -747661, -878313, -1008009, -1123947, -1235504, + -1330305, -1415140, -1469543, -1503109, -1506498, -1472749, + -1404180, -1300722, -1150891, -953777, -717782, -430319, + -101128, 266708, 676619, 1119232, 1588541, 2080078, + 2582718, 3082395, 3581368, 4053897, 4495380, 4890271, + 5223260, 5483176, 5660980, 5732018, 5692000, 5528919, + 5231518, 4798517, 4214949, 3489048, 2614503, 1598896, + 445129, -831444, -2217322, -3689401, -5234758, -6824231, + -8425955, -10013777, -11546286, -12986974, -14303728, -15452171, + -16393147, -17098221, -17516838, -17627470, -17394452, -16795021, + -15807984, -14417914, -12622002, -10422907, -7825330, -4853484, + -1537434, 2089436, 5978600, 10075995, 14311269, 18609861, + 22892297, 27073727, 31067236, 34772158, 38090534, 40934898, + 43202133, 44813294, 45679346, 45731324, 44905126, 43149410, + 40438048, 36750358, 32085432, 26463085, 19925175, 12540171, + 4381317, -4438039, -13790945, -23543065, -33528565, -43564061, + -53465445, -63029646, -72045718, -80312846, -87610680, -93744955, + -98520554, -101753835, -103280411, -102966601, -100709277, -96415613, + -90045652, -81592422, -71092553, -58618157, -44282598, -28246494, + -10713843, 8066777, 27824234, 48231529, 68946383, 89591059, + 109773996, 129088677, 147128854, 163468860, 177716203, 189481150, + 198414424, 204188194, 206522572, 205187796, 200015913, 190891669, + 177791058, 160736722, 139852452, 115319077, 87417331, 56488140, + 22961781, -12682422, -49874998, -88011035, -126426119, -164419626, + -201273383, -236244280, -268603859, -297627612, -322626893, -342948091, + -358004727, -367277860, -370342769, -366852815, -356581652, -339422399, + -315383357, -284601000, -247362998, -204058953, -155232745, -101548024, + -43766850, 17205216, 80403869, 144751837, 209130532, 272363524, + 333253552, 390604777, 443225021, 489983715, 529796603, 561679037, + 584753366, 598271174, 601626791, 594389174, 576296927, 547288978, + 507501344, 457258651, 397112676, 327797845, 250251097, 165585699, + 75093904, -19793649, -117512265, -216400732, -314702204, -410646381, + -502420161, -588236711, -666381398, -735199970, -793172141, -838922144, + -871263019, -889212884, -892024318, -879199280, -850513416, -806023413, + -746080576, -671318723, -582662836, -481304796, -368721547, -246617566, + -116917087, 18270872, 156674321, 295907377, 433516862, 567002905, + 693899018, 811767777, 918300703, 1011331647, 1088889407, 1149227101, + 1190877755, 1212675673, 1213778899, 1193712929, 1152364866, 1090009355, + 1007296111, 905266409, 785326540, 649219884, 499038860, 337158886, + 166206194, -10961531, -191342499, -371803627, -549163002, -720223486, + -881850257, -1031031431, -1164911846, -1280868241, -1376550015, -1449939386, + -1499367541, -1523583693, -1521766543, -1493533215, -1438987495, -1358687436, + -1253679050, -1125438417, -975903567, -807401765, -622633116, -424638658, + -216716665, -2389257, 214658063, 430646136, 641770661, 844277440, + 1034504073, 1208988113, 1364494665, 1498093914, 1607219524, 1689717041, + 1743869703, 1768468592, 1762801849, 1726698298, 1660522023, 1565178648, + 1442100556, 1293212702, 1120923589, 928071098, 717883328, 493909272, + 259976392, 20109529, -221543570, -460775430, -693380588, -915279395, + -1122535646, -1311465176, -1478694764, -1621202263, -1736420964, -1822228493, + -1877035711, -1899782713, -1889981357, -1847719295, -1773655476, -1669011369, + -1535556633, -1375568847, -1191799200, -987421289, -765980565, -531317241, + -287522473, -38826774, 210438051, 455926599, 693378607, 918668739, + 1127898672, 1317450221, 1484066329, 1624902389, 1737561435, 1820169914, + 1871370256, 1890370085, 1876956318, 1831481264, 1754859942, 1648550469, + 1514537726, 1355269389, 1173649163, 972947096, 756747847, 528901760, + 293423150, 54461413, -183819750, -417285653, -641919290, -853887630, + -1049609077, -1225812585, -1379604726, -1508498680, -1610479734, -1684014303, + -1728095431, -1742222985, -1726455301, -1681364668, -1608026287, -1508012075, + -1383349677, -1236465382, -1070165680, -887555137, -691989929, -487024198, + -276323896, -63620915, 147368778, 353015035, 549823704, 734499919, + 904012813, 1055637525, 1186997279, 1296126973, 1381461577, 1441882934, + 1476731983, 1485810836, 1469378480, 1428137473, 1363206291, 1276124718, + 1168776500, 1043382186, 902429921, 748648315, 584934734, 414320933, + 239889131, 64740645, -108075141, -275595744, -435033737, -583772214, + -719463613, -840011127, -943642758, -1028922523, -1094765960, -1140450717, + -1165628503, -1170317758, -1154910358, -1120124363, -1067022676, -996950501, + -911527447, -812600545, -702233328, -582607456, -456037458, -324903799, + -191587971, -58477754, 72134075, 198026348, 317140968, 427596570, + 527697948, 615989474, 691267140, 752573081, 799243835, 830886626, + 847377376, 848875628, 835788248, 808780118, 768740386, 716762333, + 654109652, 582210084, 502593426, 416905102, 326822356, 234056696, + 140318147, 47264446, -43493550, -130454209, -212221899, -287551695, + -355341753, -414661156, -464781140, -505142479, -535375283, -555326382, + -564998467, -564605784, -554520170, -535277315, -507545850, -472137486, + -429952101, -381993665, -329320813, -273037272, -214275690, -154161305, + -93793908, -34261274, 23446178, 78376049, 129678588, 176604769, + 218510346, 254869838, 285274876, 309446449, 327216576, 338561446, + 343550216, 342374595, 335330281, 322798847, 305241328, 283205569, + 257276138, 228087926, 196306163, 162614199, 127698298, 92230529, + 56859824, 22218011, -11122306, -42635429, -71849428, -98358438, + -121834503, -141999690, -158667712, -171721547, -181107624, -186849406, + -189032211, -187801396, -183357131, -175951701, -165863098, -153423152, + -138980699, -122894992, -105545878, -87314275, -68566012, -49677861, + -30984026, -12814682, 4531458, 20798958, 35753250, 49203321, + 60992344, 71008612, 79174265, 85454460, 89847498, 92383097, + 93135114, 92195760, 89684369, 85748781, 80536599, 74229321, + 67008217, 59067898, 50589678, 41764861, 32780594, 23799570, + 14993219, 6509774, -1519081, -8981737, -15771145, -21811536, + -27053959, -31440950, -34961449, -37604251, -39392286, -40339728, + -40496531, -39917823, -38657779, -36799506, -34411495, -31574572, + -28386220, -24923452, -21270576, -17508795, -13717544, -9974397, + -6333739, -2866681, 384131, 3368107, 6055198, 8416649, + 10434463, 12091696, 13399827, 14352349, 14958192, 15241456, + 15221308, 14925295, 14374955, 13608579, 12654643, 11552968, + 10327766, 9020876, 7661805, 6278839, 4907365, 3564212, + 2278189, 1064063, -56710, -1068964, -1969870, -2748235, + -3400263, -3926939, -4334024, -4613344, -4777385, -4836237, + -4799867, -4673215, -4466130, -4199935, -3874971, -3511593, + -3118446, -2704701, -2280034, -1857999, -1445532, -1048462, + -672536, -324455, -6582, 276892, 520368, 728589, + 897649, 1032019, 1126293, 1192973, 1228285, 1231327, + 1206481, 1161397, 1102233, 1026682, 938355, 843020, + 739097, 631951, 530386, 428349, 326932, 240431, + 154170, 73476, 6017, -55869, -103578, -144953, + -178246, -202681, -221485, -230703, -235306, -226956, + -222383, -208635, -196477, -178217, -164594, -144650, + -125017, -105575, -87630, -67991, -51183, -39259, + -23108, -11134, 1244, 9731, 12825, 20491, + 23334, 24167, 26047, 27043, 28682, 26990, + 26946, 22875, 20894, 17822, 18266, 15434, + 12288, 11757, 9451, 4447, 6333, 2560, + 3081, 1489, 1911, 2215, -1287, 197, + 1072, -1622, -3627, -2827, -1107, -1453, + -1069, -4722, 633, 1036, -3478, -2766, + 990, -1236, 1683, -3486, 3291, -2011, +}; + +static const int32_t fft_in_imag_768_q31[768] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const int32_t fft_ref_real_768_q31[768] = { + 45, 20, -33, 47, 30, -4, + -56, -17, 21, -19, -368, 43718, + -759260, 5010913, -16911518, 33136889, -39906332, 30002948, + -13815282, 3661837, -487124, 23450, -78, 55, + 58, 54, -44, -50, 69, 7, + -8, 3, 9, 37, -38, 92, + 6, 75, 74, -35, 16, -23, + -30, 7, 60, -2, 33, -28, + 35, 5, -27, 48, -6, 36, + 74, 49, 3, -36, -82, -71, + -17, 44, 13, 9, 1, 0, + 15, 116, 24, 13, -22, -83, + -43, -23, 52, -7, -32, 26, + 77, 12, -9, 61, -27, 64, + 14, -20, 0, 28, 38, -32, + -48, 27, -35, -15, -25, -29, + -33, -64, 12, 25, -34, -17, + -26, 62, 57, 47, -53, 45, + 36, -75, -50, -100, -53, 1, + -23, 12, -27, 126, -25, 11, + -13, -23, -54, 30, -8, -4, + 74, 33, -26, -18, 45, -4, + -28, -84, 42, 19, 2, -15, + -27, 27, 42, -49, 68, -51, + 17, 77, -46, 58, 6, 15, + -72, 32, -8, 97, 1, 21, + 47, -67, -98, 1, 6, 16, + 13, 10, 65, 83, -7, 58, + 34, 29, 33, -47, 53, 8, + -33, 25, -34, 61, -22, -34, + 37, 45, 52, 32, 36, 32, + -29, -13, 53, 46, -110, -40, + -76, 32, -18, -32, -46, -5, + 8, -22, -73, -49, -23, -39, + 6, -27, -34, -56, -42, -34, + -24, -18, 48, -19, -12, 115, + -23, 45, -22, -81, -65, 13, + 42, 28, -15, 43, 9, -18, + -98, -21, 4, 21, 37, -35, + -14, -14, 20, -37, -62, 66, + 10, -1, -26, 1, 35, 2, + -25, -91, -9, 26, 23, -39, + 9, 5, -27, 21, -24, 21, + 12, -26, -71, -17, 26, -31, + -23, 1, 107, -94, -17, 12, + -30, -53, 62, 28, 0, 55, + -109, -29, -79, -80, -53, -30, + -61, -57, -47, 59, -44, -19, + 30, 48, -43, 42, -15, 11, + 1, -23, -38, -12, -47, -30, + -50, -3, -20, -20, 68, -42, + -1, -15, 16, -33, 4, -23, + -59, -24, -39, 5, -34, 67, + -40, 14, 105, 41, -40, 38, + -12, -34, 34, 16, -21, 68, + -42, -32, -32, -12, 8, -58, + 29, 2, 39, 76, 57, 35, + -26, -18, -70, -14, 20, -37, + 23, 18, -47, -72, 69, -24, + -6, 41, -1, 8, 25, -41, + -5, 58, 71, 72, -40, 50, + 32, -28, 55, 50, -52, -27, + 44, 38, -23, 18, 38, 9, + 53, -26, 45, 79, -17, 110, + 32, 110, -17, 79, 45, -26, + 53, 9, 38, 18, -23, 38, + 44, -27, -52, 50, 55, -28, + 32, 50, -40, 72, 71, 58, + -5, -41, 25, 8, -1, 41, + -6, -24, 69, -72, -47, 18, + 23, -37, 20, -14, -70, -18, + -26, 35, 57, 76, 39, 2, + 29, -58, 8, -12, -32, -32, + -42, 68, -21, 16, 34, -34, + -12, 38, -40, 41, 105, 14, + -40, 67, -34, 5, -39, -24, + -59, -23, 4, -33, 16, -15, + -1, -42, 68, -20, -20, -3, + -50, -30, -47, -12, -38, -23, + 1, 11, -15, 42, -43, 48, + 30, -19, -44, 59, -47, -57, + -61, -30, -53, -80, -79, -29, + -109, 55, 0, 28, 62, -53, + -30, 12, -17, -94, 107, 1, + -23, -31, 26, -17, -71, -26, + 12, 21, -24, 21, -27, 5, + 9, -39, 23, 26, -9, -91, + -25, 2, 35, 1, -26, -1, + 10, 66, -62, -37, 20, -14, + -14, -35, 37, 21, 4, -21, + -98, -18, 9, 43, -15, 28, + 42, 13, -65, -81, -22, 45, + -23, 115, -12, -19, 48, -18, + -24, -34, -42, -56, -34, -27, + 6, -39, -23, -49, -73, -22, + 8, -5, -46, -32, -18, 32, + -76, -40, -110, 46, 53, -13, + -29, 32, 36, 32, 52, 45, + 37, -34, -22, 61, -34, 25, + -33, 8, 53, -47, 33, 29, + 34, 58, -7, 83, 65, 10, + 13, 16, 6, 1, -98, -67, + 47, 21, 1, 97, -8, 32, + -72, 15, 6, 58, -46, 77, + 17, -51, 68, -49, 42, 27, + -27, -15, 2, 19, 42, -84, + -28, -4, 45, -18, -26, 33, + 74, -4, -8, 30, -54, -23, + -13, 11, -25, 126, -27, 12, + -23, 1, -53, -100, -50, -75, + 36, 45, -53, 47, 57, 62, + -26, -17, -34, 25, 12, -64, + -33, -29, -25, -15, -35, 27, + -48, -32, 38, 28, 0, -20, + 14, 64, -27, 61, -9, 12, + 77, 26, -32, -7, 52, -23, + -43, -83, -22, 13, 24, 116, + 15, 0, 1, 9, 13, 44, + -17, -71, -82, -36, 3, 49, + 74, 36, -6, 48, -27, 5, + 35, -28, 33, -2, 60, 7, + -30, -23, 16, -35, 74, 75, + 6, 92, -38, 37, 9, 3, + -8, 7, 69, -50, -44, 54, + 58, 55, -78, 23450, -487124, 3661837, + -13815282, 30002948, -39906332, 33136889, -16911518, 5010913, + -759260, 43718, -368, -19, 21, -17, + -56, -4, 30, 47, -33, 20, +}; + +static const int32_t fft_ref_imag_768_q31[768] = { + 0, -32, -5, 26, 5, 43, + -33, 33, 46, -24, -1903, 252986, + -4504301, 30493677, -105611719, 212501965, -262975509, 203317701, + -96347654, 26303114, -3606843, 179333, -945, -2, + -33, -11, -91, -18, -5, -11, + -4, 11, 43, -17, 26, 49, + 13, -31, -13, 4, 27, -2, + -1, 66, -18, -35, 34, -14, + 37, -68, 47, 2, -33, 36, + -10, 44, -5, -19, 8, -19, + -26, -44, 65, -29, -73, -29, + -22, -24, 11, -29, 13, -44, + -26, 44, 76, -44, -30, 26, + 3, -45, -18, 105, -113, 82, + -11, 57, -5, -54, -10, -36, + 0, 11, -10, 40, -33, -29, + 7, 34, -19, -11, -114, 57, + 18, 26, -81, -58, 9, -19, + 0, 92, 77, -34, -14, -76, + 35, -55, -9, 43, 7, 2, + 46, -51, 39, -57, 57, -96, + 9, 36, -6, 91, 12, -133, + -27, 38, 14, 52, 16, 12, + 16, -36, 43, -9, -23, 22, + 31, -5, -90, -25, -34, 61, + -49, 22, -56, 26, 39, -25, + -23, -69, -17, -49, 33, -10, + -86, 125, 10, -22, 62, -77, + -28, -96, -11, 68, 17, -26, + 69, 29, -16, -43, 29, 16, + 71, -13, -4, 26, 51, 21, + -43, -28, -30, -55, 26, 19, + 33, -7, -21, 9, -17, -38, + -41, -34, -14, 14, 6, -43, + -27, 70, 30, -53, -31, -11, + -24, -4, -27, 0, -31, -71, + -4, -17, 44, 29, 18, -32, + -11, -15, -12, -2, 2, -24, + -43, 9, -103, 54, -39, -80, + 41, -118, 17, -16, -35, -76, + 11, -34, -9, -58, -18, -20, + 54, 28, 23, -38, -47, -15, + 7, -104, 11, 59, 29, 37, + -29, -37, 16, 0, -4, 26, + 27, -40, 38, 58, -55, 2, + 42, 21, -51, 47, -5, -77, + -1, -29, 63, 14, 30, -35, + -73, 1, 13, 8, 65, -17, + -2, -21, -66, 87, -17, -134, + 9, -66, -11, 66, -27, -28, + 12, 31, -24, 0, -61, 14, + 58, 20, -46, -17, -14, -14, + -12, -47, 12, -63, 27, -21, + 33, -78, 1, 16, -25, -48, + -41, -96, 137, -59, 4, 18, + 43, 32, -33, -21, -13, 16, + 71, -39, -46, 33, 5, -7, + -11, -19, -13, -16, -59, 45, + -26, -24, -70, -39, 2, 12, + 70, 43, -58, 32, 34, -40, + 44, -32, -28, -26, 23, -7, + 64, -63, 24, 37, -17, 7, + -1, 0, -59, -16, 5, -77, + -16, 51, 19, 44, 16, 62, + 0, -62, -16, -44, -19, -51, + 16, 77, -5, 16, 59, 0, + 1, -7, 17, -37, -24, 63, + -64, 7, -23, 26, 28, 32, + -44, 40, -34, -32, 58, -43, + -70, -12, -2, 39, 70, 24, + 26, -45, 59, 16, 13, 19, + 11, 7, -5, -33, 46, 39, + -71, -16, 13, 21, 33, -32, + -43, -18, -4, 59, -137, 96, + 41, 48, 25, -16, -1, 78, + -33, 21, -27, 63, -12, 47, + 12, 14, 14, 17, 46, -20, + -58, -14, 61, 0, 24, -31, + -12, 28, 27, -66, 11, 66, + -9, 134, 17, -87, 66, 21, + 2, 17, -65, -8, -13, -1, + 73, 35, -30, -14, -63, 29, + 1, 77, 5, -47, 51, -21, + -42, -2, 55, -58, -38, 40, + -27, -26, 4, 0, -16, 37, + 29, -37, -29, -59, -11, 104, + -7, 15, 47, 38, -23, -28, + -54, 20, 18, 58, 9, 34, + -11, 76, 35, 16, -17, 118, + -41, 80, 39, -54, 103, -9, + 43, 24, -2, 2, 12, 15, + 11, 32, -18, -29, -44, 17, + 4, 71, 31, 0, 27, 4, + 24, 11, 31, 53, -30, -70, + 27, 43, -6, -14, 14, 34, + 41, 38, 17, -9, 21, 7, + -33, -19, -26, 55, 30, 28, + 43, -21, -51, -26, 4, 13, + -71, -16, -29, 43, 16, -29, + -69, 26, -17, -68, 11, 96, + 28, 77, -62, 22, -10, -125, + 86, 10, -33, 49, 17, 69, + 23, 25, -39, -26, 56, -22, + 49, -61, 34, 25, 90, 5, + -31, -22, 23, 9, -43, 36, + -16, -12, -16, -52, -14, -38, + 27, 133, -12, -91, 6, -36, + -9, 96, -57, 57, -39, 51, + -46, -2, -7, -43, 9, 55, + -35, 76, 14, 34, -77, -92, + 0, 19, -9, 58, 81, -26, + -18, -57, 114, 11, 19, -34, + -7, 29, 33, -40, 10, -11, + 0, 36, 10, 54, 5, -57, + 11, -82, 113, -105, 18, 45, + -3, -26, 30, 44, -76, -44, + 26, 44, -13, 29, -11, 24, + 22, 29, 73, 29, -65, 44, + 26, 19, -8, 19, 5, -44, + 10, -36, 33, -2, -47, 68, + -37, 14, -34, 35, 18, -66, + 1, 2, -27, -4, 13, 31, + -13, -49, -26, 17, -43, -11, + 4, 11, 5, 18, 91, 11, + 33, 2, 945, -179333, 3606843, -26303114, + 96347654, -203317701, 262975509, -212501965, 105611719, -30493677, + 4504301, -252986, 1903, 24, -46, -33, + 33, -43, -5, -26, 5, 32, +}; diff --git a/test/cmocka/src/math/fft/ref_fft_multi_96_32.h b/test/cmocka/src/math/fft/ref_fft_multi_96_32.h new file mode 100644 index 000000000000..48ed4c1e7ae1 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_fft_multi_96_32.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_FFT_MULTI_96_NUM_TESTS 1 + +static const int32_t fft_in_real_96_q31[96] = { + 2612, -585, 740, 1771, 10242, 28387, + 67673, 150357, 305252, 583434, 1049075, 1773977, + 2866391, 4421878, 6535194, 9264176, 12595638, 16410151, + 20420570, 24132226, 26792322, 27353105, 24457934, 16442487, + 1411524, -22682595, -57886075, -106071598, -168720146, -246662584, + -339873057, -447258396, -566496507, -693969722, -824813628, -953046420, + -1071834144, -1173876250, -1251869944, -1299031192, -1309635449, -1279509181, + -1206486132, -1090677103, -934610659, -743214358, -523566965, -284489188, + -36038274, 211200645, 446740932, 660913160, 845461777, 994029750, + 1102498010, 1169119233, 1194490190, 1181384510, 1134337335, 1059242451, + 962836599, 852157942, 734074206, 614854055, 499863929, 393334033, + 298286546, 216528461, 148768326, 94769100, 53566286, 23675203, + 3333228, -9343610, -16164205, -18786637, -18606500, -16758603, + -14096842, -11214929, -8500848, -6156283, -4266830, -2826418, + -1788630, -1079523, -614752, -331493, -166234, -76988, + -33171, -13273, -4796, -1383, 2439, 1203, +}; + +static const int32_t fft_in_imag_96_q31[96] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; + +static const int32_t fft_ref_real_96_q31[96] = { + -17402140, 14269492, -5584270, -2890773, 4789231, -2333890, + 486956, -35699, 330, 13, 164, 145, + 68, -18, -52, -121, 151, 206, + -21, -66, -30, 131, 0, 78, + -307, 162, -16, -184, 174, -39, + 140, -48, 32, -31, -199, 139, + -187, 137, -72, 272, 156, -11, + -74, 3, 49, 154, -109, 172, + 81, 172, -109, 154, 49, 3, + -74, -11, 156, 272, -72, 137, + -187, 139, -199, -31, 32, -48, + 140, -39, 174, -184, -16, 162, + -307, 78, 0, 131, -30, -66, + -21, 206, 151, -121, -52, -18, + 68, 145, 164, 13, 330, -35699, + 486956, -2333890, 4789231, -2890773, -5584270, 14269492, +}; + +static const int32_t fft_ref_imag_96_q31[96] = { + 0, 179914066, -259234323, 208477801, -102275624, 29288094, + -4318694, 244372, -1937, 98, -53, 13, + -18, 191, 43, 145, 120, 116, + -14, 54, 22, -22, -73, -99, + 113, 41, 26, -65, 99, -120, + -16, 69, -52, -74, 73, -70, + 85, -46, 106, -107, 55, -3, + 13, -45, -98, 68, 77, -85, + 0, 85, -77, -68, 98, 45, + -13, 3, -55, 107, -106, 46, + -85, 70, -73, 74, 52, -69, + 16, 120, -99, 65, -26, -41, + -113, 99, 73, 22, -22, -54, + 14, -116, -120, -145, -43, -191, + 18, -13, 53, -98, 1937, -244372, + 4318694, -29288094, 102275624, -208477801, 259234323, -179914066, +}; diff --git a/test/cmocka/src/math/fft/ref_ifft_multi_1024_32.h b/test/cmocka/src/math/fft/ref_ifft_multi_1024_32.h new file mode 100644 index 000000000000..f9d39f509c2e --- /dev/null +++ b/test/cmocka/src/math/fft/ref_ifft_multi_1024_32.h @@ -0,0 +1,704 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_IFFT_MULTI_1024_NUM_TESTS 1 + +static const int32_t ifft_in_real_1024_q31[1024] = { + -25, -79, 39, 48, -13, -34, + -8, -8, -21, -23, 43, -46, + -62, -24, -39, 10, -55147, 1535442, + -13543809, 57130805, -135763817, 195823576, -176199328, 98119764, + -32279401, 5635577, -409793, 5971, 1, 4, + 86, 8, -39, -22, 43, 34, + 22, -65, -65, 9, 49, 17, + 54, 42, -41, 100, 11, -49, + 26, 19, -36, 4, -26, 25, + -30, 19, 27, -30, 78, -61, + -71, 7, 2, 33, 51, -3, + 29, 17, 7, 0, -28, 45, + 17, -31, -72, 44, 14, -9, + 38, 11, 35, 10, 68, 34, + -3, 6, 19, 16, 45, -35, + 48, 21, 28, 27, 18, 41, + 5, 35, -2, -5, -69, 14, + -6, 45, 22, 19, 55, 14, + 13, 40, 5, 4, 11, -30, + 59, 18, 94, 41, -92, 27, + -3, -2, 50, 35, -24, 27, + 44, -40, 35, -28, 49, -30, + -3, 11, -54, -28, 6, 45, + -21, 63, -10, -10, -8, -2, + 24, 10, 50, 4, 21, -29, + -10, 39, -61, 16, -28, -29, + -58, 37, 38, -34, 19, -72, + -30, 9, 45, -36, 32, 23, + 38, 59, -59, -23, -31, -60, + 23, -11, 12, -15, -32, 36, + 15, 48, -39, -33, 81, -58, + -2, -73, 50, -70, 19, 8, + 45, -18, -22, 40, -8, 23, + 18, 42, 18, 80, 38, -1, + 7, -4, 3, 23, 23, -59, + -4, 21, -45, -26, 49, -17, + 61, -16, -17, 32, -8, -13, + 32, 77, -72, 50, -6, 9, + 51, 21, -35, -95, -32, -6, + 26, 17, 4, -56, 0, -94, + 3, -5, 3, 7, -57, -44, + -29, -18, 29, -92, -25, -93, + 41, 4, 5, -38, -1, -64, + -81, -63, -21, -41, -51, 41, + -59, -1, 68, -14, 40, -62, + 47, 73, 9, 25, 57, -18, + 15, -25, -39, -49, 1, 11, + 37, -28, 42, -52, 45, 5, + 47, -40, -10, -8, 45, -1, + -28, -33, 63, -44, 38, 15, + 15, -48, 45, -51, -28, -87, + 7, 10, -63, 25, 29, 48, + -1, -36, 10, -44, 41, 33, + 9, 32, -15, -40, -86, 12, + -84, 34, 46, -12, -5, 54, + -19, -8, -46, -26, -4, -57, + -44, -11, -7, -19, 10, -30, + -1, 39, 9, -17, -22, 35, + -14, -7, 5, -41, 27, -2, + -21, 33, 47, 20, 66, 1, + 23, -54, -4, -34, 2, 33, + 56, -7, 26, 11, 20, -30, + -66, -30, -20, 18, 72, -24, + -37, -20, -70, -21, -48, 64, + -45, 15, -46, 19, -41, -8, + -38, 17, -14, -27, 5, -72, + 34, 36, 29, -5, -11, 24, + -10, 26, -16, 30, 22, -18, + 37, 31, -14, 42, -14, -17, + -10, 29, -14, -80, -2, 26, + -10, -21, -87, 20, 76, 1, + 28, -11, 81, 44, 18, -9, + 12, 53, 40, 14, 8, 18, + 4, -3, -19, -4, -15, -8, + 19, -18, -12, -34, 10, -29, + -56, -10, -18, -59, 45, 19, + 12, 25, -4, 12, 34, -27, + 0, 1, 29, -16, 14, 7, + -41, 15, 26, -21, 24, -30, + -9, -24, 26, 14, 76, 0, + 76, 4, -32, 91, -21, -31, + -6, 8, -45, 21, 69, 44, + -9, 0, -7, -27, -14, 14, + -3, -6, 44, -4, 7, -35, + -40, 32, -18, -17, -40, -21, + -17, 51, 31, 51, -17, -21, + -40, -17, -18, 32, -40, -35, + 7, -4, 44, -6, -3, 14, + -14, -27, -7, 0, -9, 44, + 69, 21, -45, 8, -6, -31, + -21, 91, -32, 4, 76, 0, + 76, 14, 26, -24, -9, -30, + 24, -21, 26, 15, -41, 7, + 14, -16, 29, 1, 0, -27, + 34, 12, -4, 25, 12, 19, + 45, -59, -18, -10, -56, -29, + 10, -34, -12, -18, 19, -8, + -15, -4, -19, -3, 4, 18, + 8, 14, 40, 53, 12, -9, + 18, 44, 81, -11, 28, 1, + 76, 20, -87, -21, -10, 26, + -2, -80, -14, 29, -10, -17, + -14, 42, -14, 31, 37, -18, + 22, 30, -16, 26, -10, 24, + -11, -5, 29, 36, 34, -72, + 5, -27, -14, 17, -38, -8, + -41, 19, -46, 15, -45, 64, + -48, -21, -70, -20, -37, -24, + 72, 18, -20, -30, -66, -30, + 20, 11, 26, -7, 56, 33, + 2, -34, -4, -54, 23, 1, + 66, 20, 47, 33, -21, -2, + 27, -41, 5, -7, -14, 35, + -22, -17, 9, 39, -1, -30, + 10, -19, -7, -11, -44, -57, + -4, -26, -46, -8, -19, 54, + -5, -12, 46, 34, -84, 12, + -86, -40, -15, 32, 9, 33, + 41, -44, 10, -36, -1, 48, + 29, 25, -63, 10, 7, -87, + -28, -51, 45, -48, 15, 15, + 38, -44, 63, -33, -28, -1, + 45, -8, -10, -40, 47, 5, + 45, -52, 42, -28, 37, 11, + 1, -49, -39, -25, 15, -18, + 57, 25, 9, 73, 47, -62, + 40, -14, 68, -1, -59, 41, + -51, -41, -21, -63, -81, -64, + -1, -38, 5, 4, 41, -93, + -25, -92, 29, -18, -29, -44, + -57, 7, 3, -5, 3, -94, + 0, -56, 4, 17, 26, -6, + -32, -95, -35, 21, 51, 9, + -6, 50, -72, 77, 32, -13, + -8, 32, -17, -16, 61, -17, + 49, -26, -45, 21, -4, -59, + 23, 23, 3, -4, 7, -1, + 38, 80, 18, 42, 18, 23, + -8, 40, -22, -18, 45, 8, + 19, -70, 50, -73, -2, -58, + 81, -33, -39, 48, 15, 36, + -32, -15, 12, -11, 23, -60, + -31, -23, -59, 59, 38, 23, + 32, -36, 45, 9, -30, -72, + 19, -34, 38, 37, -58, -29, + -28, 16, -61, 39, -10, -29, + 21, 4, 50, 10, 24, -2, + -8, -10, -10, 63, -21, 45, + 6, -28, -54, 11, -3, -30, + 49, -28, 35, -40, 44, 27, + -24, 35, 50, -2, -3, 27, + -92, 41, 94, 18, 59, -30, + 11, 4, 5, 40, 13, 14, + 55, 19, 22, 45, -6, 14, + -69, -5, -2, 35, 5, 41, + 18, 27, 28, 21, 48, -35, + 45, 16, 19, 6, -3, 34, + 68, 10, 35, 11, 38, -9, + 14, 44, -72, -31, 17, 45, + -28, 0, 7, 17, 29, -3, + 51, 33, 2, 7, -71, -61, + 78, -30, 27, 19, -30, 25, + -26, 4, -36, 19, 26, -49, + 11, 100, -41, 42, 54, 17, + 49, 9, -65, -65, 22, 34, + 43, -22, -39, 8, 86, 4, + 1, 5971, -409793, 5635577, -32279401, 98119764, + -176199328, 195823576, -135763817, 57130805, -13543809, 1535442, + -55147, 10, -39, -24, -62, -46, + 43, -23, -21, -8, -8, -34, + -13, 48, 39, -79, +}; + +static const int32_t ifft_in_imag_1024_q31[1024] = { + 0, -83, 39, 95, 15, 7, + -35, 3, -6, -13, 35, 57, + 28, 60, -67, -79, 50487, -1395762, + 12235510, -51294609, 121144602, -173660953, 155294502, -85945073, + 28099679, -4875536, 352396, -5166, 26, -2, + -73, -42, 38, 16, 22, -70, + 59, -3, -20, 45, 5, -16, + 10, 11, 20, -37, -43, -13, + 25, -25, 28, 39, -27, -7, + 46, -10, 59, 84, 14, -82, + 2, 13, 16, -54, 84, 0, + 50, -8, 13, 59, -28, -33, + 81, -5, 42, -22, -37, -7, + -40, -26, -32, -90, 2, 60, + 17, 38, 19, -58, 29, 17, + 38, 31, -21, -77, -3, 43, + -27, 23, 10, 20, -35, 3, + 13, 16, 22, 36, -42, 0, + 5, 4, -38, 51, -37, -83, + 10, -7, -9, 2, -83, -99, + 7, -10, -32, -40, 26, -8, + 16, 62, -15, 28, -21, 111, + 17, 8, 71, 64, -25, 24, + -18, -18, 36, -2, 2, 42, + -4, -32, 19, -76, 28, -83, + 57, -12, -26, -11, -3, -17, + 51, -36, 33, -66, -1, -28, + 16, -7, -62, 24, -47, -23, + -18, -22, 80, -15, -86, 46, + 59, 11, -11, -20, -23, 35, + -5, 16, 29, -15, -20, -53, + 99, 58, -10, 34, 28, -13, + 23, 10, -42, -61, 52, 31, + -5, 9, 0, -50, -56, -47, + 13, 1, -22, -1, -48, 8, + -2, 34, -26, 39, -54, -9, + -9, -30, 15, 6, 46, -36, + -55, 24, 15, 1, -33, 7, + 0, 23, -19, 35, -15, 43, + 83, -21, -32, -11, -44, -1, + 81, 16, -34, 14, -39, -11, + -65, -17, -9, 42, -10, -4, + 24, -34, -15, -9, -15, -10, + -26, 20, 28, 0, -5, -46, + 7, -71, -48, -35, 1, -4, + 120, -22, 4, 1, -37, -2, + -35, -30, 67, -55, -40, -3, + -104, -17, 24, -2, 22, 44, + -32, -34, 11, 58, 10, -21, + 25, 13, 86, 12, -70, -14, + -26, -40, 3, 28, 26, -36, + 12, 32, -15, 10, 52, 40, + -4, 59, 13, -32, -23, -21, + 2, -54, 28, -27, -12, 14, + 69, -74, 0, 42, -32, 16, + 24, -10, 32, -10, 19, -8, + -14, -3, 50, 6, -33, -56, + 40, 6, -39, -29, 18, 7, + 40, -35, -39, 96, -32, 71, + 63, -32, 1, 49, -75, 60, + -56, 7, -51, -9, -30, 11, + 4, -54, 24, 55, -1, 87, + 56, -55, -4, 27, -20, -92, + -29, 49, 15, -32, 9, -32, + 53, 16, 40, -20, 29, 19, + 31, 21, 37, 19, -40, 76, + 25, 49, -8, 10, 26, 61, + -29, 24, 59, -34, 71, -43, + 42, -16, -5, 4, 4, -56, + -18, -56, 9, 30, -26, 1, + -71, 21, 86, -3, -58, 7, + 80, -38, -10, -16, -2, 18, + -14, -3, 15, 27, -17, -67, + -15, 41, -13, 6, 13, 24, + -25, 39, -24, -12, 16, -14, + 23, 26, 10, 53, -49, -49, + -38, 6, 31, -30, -5, -16, + 16, -14, -31, 60, -42, -7, + 66, 52, 16, -12, -36, -9, + -60, -21, 63, -40, -47, -4, + -73, 16, 75, -46, -41, -12, + -19, -48, 5, -22, 19, 14, + 56, 42, -23, -11, 29, -17, + -68, -31, -19, -4, -46, 16, + 55, 23, 22, -15, -9, -7, + -31, -26, 0, 26, 31, 7, + 9, 15, -22, -23, -55, -16, + 46, 4, 19, 31, 68, 17, + -29, 11, 23, -42, -56, -14, + -19, 22, -5, 48, 19, 12, + 41, 46, -75, -16, 73, 4, + 47, 40, -63, 21, 60, 9, + 36, 12, -16, -52, -66, 7, + 42, -60, 31, 14, -16, 16, + 5, 30, -31, -6, 38, 49, + 49, -53, -10, -26, -23, 14, + -16, 12, 24, -39, 25, -24, + -13, -6, 13, -41, 15, 67, + 17, -27, -15, 3, 14, -18, + 2, 16, 10, 38, -80, -7, + 58, 3, -86, -21, 71, -1, + 26, -30, -9, 56, 18, 56, + -4, -4, 5, 16, -42, 43, + -71, 34, -59, -24, 29, -61, + -26, -10, 8, -49, -25, -76, + 40, -19, -37, -21, -31, -19, + -29, 20, -40, -16, -53, 32, + -9, 32, -15, -49, 29, 92, + 20, -27, 4, 55, -56, -87, + 1, -55, -24, 54, -4, -11, + 30, 9, 51, -7, 56, -60, + 75, -49, -1, 32, -63, -71, + 32, -96, 39, 35, -40, -7, + -18, 29, 39, -6, -40, 56, + 33, -6, -50, 3, 14, 8, + -19, 10, -32, 10, -24, -16, + 32, -42, 0, 74, -69, -14, + 12, 27, -28, 54, -2, 21, + 23, 32, -13, -59, 4, -40, + -52, -10, 15, -32, -12, 36, + -26, -28, -3, 40, 26, 14, + 70, -12, -86, -13, -25, 21, + -10, -58, -11, 34, 32, -44, + -22, 2, -24, 17, 104, 3, + 40, 55, -67, 30, 35, 2, + 37, -1, -4, 22, -120, 4, + -1, 35, 48, 71, -7, 46, + 5, 0, -28, -20, 26, 10, + 15, 9, 15, 34, -24, 4, + 10, -42, 9, 17, 65, 11, + 39, -14, 34, -16, -81, 1, + 44, 11, 32, 21, -83, -43, + 15, -35, 19, -23, 0, -7, + 33, -1, -15, -24, 55, 36, + -46, -6, -15, 30, 9, 9, + 54, -39, 26, -34, 2, -8, + 48, 1, 22, -1, -13, 47, + 56, 50, 0, -9, 5, -31, + -52, 61, 42, -10, -23, 13, + -28, -34, 10, -58, -99, 53, + 20, 15, -29, -16, 5, -35, + 23, 20, 11, -11, -59, -46, + 86, 15, -80, 22, 18, 23, + 47, -24, 62, 7, -16, 28, + 1, 66, -33, 36, -51, 17, + 3, 11, 26, 12, -57, 83, + -28, 76, -19, 32, 4, -42, + -2, 2, -36, 18, 18, -24, + 25, -64, -71, -8, -17, -111, + 21, -28, 15, -62, -16, 8, + -26, 40, 32, 10, -7, 99, + 83, -2, 9, 7, -10, 83, + 37, -51, 38, -4, -5, 0, + 42, -36, -22, -16, -13, -3, + 35, -20, -10, -23, 27, -43, + 3, 77, 21, -31, -38, -17, + -29, 58, -19, -38, -17, -60, + -2, 90, 32, 26, 40, 7, + 37, 22, -42, 5, -81, 33, + 28, -59, -13, 8, -50, 0, + -84, 54, -16, -13, -2, 82, + -14, -84, -59, 10, -46, 7, + 27, -39, -28, 25, -25, 13, + 43, 37, -20, -11, -10, 16, + -5, -45, 20, 3, -59, 70, + -22, -16, -38, 42, 73, 2, + -26, 5166, -352396, 4875536, -28099679, 85945073, + -155294502, 173660953, -121144602, 51294609, -12235510, 1395762, + -50487, 79, 67, -60, -28, -57, + -35, 13, 6, -3, 35, -7, + -15, -95, -39, 83, +}; + +static const int32_t ifft_ref_real_1024_q31[1024] = { + 326, 1146, 2786, -3072, -3316, -605, + -2901, -840, -2671, 664, 2057, 956, + -21, -662, 462, 3641, -2217, 610, + -1321, 238, 2943, 688, 1060, 846, + -3792, -1576, 2121, -1631, -211, -2712, + -2722, -3466, -8597, -7806, -10107, -8978, + -8707, -11131, -9732, -15323, -15254, -13081, + -12623, -10274, -13212, -5985, -4940, -4716, + -1004, 3307, 7423, 11870, 21908, 23159, + 29444, 38649, 46299, 51698, 58474, 61509, + 69988, 71541, 78183, 80345, 79248, 80016, + 77508, 69254, 64701, 54919, 38485, 22397, + 7619, -18671, -39738, -64092, -93406, -121566, + -151206, -181934, -213000, -241011, -269356, -295013, + -318042, -331352, -343862, -348224, -349487, -339135, + -319901, -295323, -258729, -214256, -161875, -98338, + -22320, 61463, 148883, 241596, 343430, 449953, + 553092, 660575, 765348, 863233, 956207, 1031827, + 1098053, 1152642, 1181959, 1190748, 1179948, 1146590, + 1076767, 984062, 860947, 715027, 533899, 321992, + 91170, -167866, -444979, -738889, -1046761, -1361827, + -1677156, -1987696, -2285378, -2563978, -2820773, -3038273, + -3217797, -3348348, -3421990, -3434697, -3385794, -3264787, + -3066741, -2788681, -2438638, -2011383, -1505748, -933663, + -291619, 399962, 1144061, 1925860, 2735503, 3549988, + 4362537, 5151016, 5907267, 6604092, 7230123, 7760787, + 8186022, 8488314, 8646197, 8646598, 8484987, 8152712, + 7635835, 6935136, 6051955, 4991930, 3755510, 2363819, + 826364, -834320, -2599066, -4440124, -6321571, -8216197, + -10077901, -11885570, -13588265, -15155182, -16535940, -17702619, + -18613150, -19234858, -19532980, -19487165, -19075195, -18273148, + -17078708, -15490893, -13506877, -11147624, -8430976, -5382361, + -2046368, 1542253, 5318886, 9227859, 13214381, 17188190, + 21089248, 24838424, 28350006, 31546237, 34346432, 36681320, + 38471965, 39655342, 40176918, 39988511, 39053022, 37340045, + 34844574, 31564156, 27518651, 22736319, 17272291, 11186028, + 4553529, -2522282, -9940434, -17585491, -25318423, -33006825, + -40506944, -47660215, -54327081, -60355027, -65599108, -69911020, + -73182968, -75287952, -76129493, -75629810, -73723931, -70383367, + -65595111, -59372093, -51768179, -42837441, -32692074, -21452167, + -9277743, 3657281, 17156928, 30990380, 44930749, 58723629, + 72104522, 84815781, 96588254, 107170396, 116310129, 123773406, + 129346015, 132845872, 134109268, 133017610, 129484530, 123462360, + 114949234, 103998137, 90691090, 75177605, 57635434, 38303041, + 17446134, -4620199, -27539988, -50941560, -74413943, -97543947, + -119891596, -141022922, -160505079, -177918821, -192864296, -204973947, + -213909668, -219387656, -221170208, -219080741, -212996462, -202883444, + -188761959, -170722219, -148945912, -123689848, -95255466, -64056433, + -30529263, 4794075, 41356921, 78547365, 115714160, 152194199, + 187309917, 220377731, 250731557, 277733009, 300773373, 319311844, + 332844739, 340960776, 343321097, 339692071, 329923185, 313994650, + 291963289, 264028543, 230483055, 191743888, 148332347, 100859462, + 50042902, -3319828, -58361358, -114155510, -169723973, -224083369, + -276218550, -325136386, -369863274, -409475668, -443106446, -469980132, + -489407054, -500821595, -503772467, -497957373, -483223160, -459560044, + -427130807, -386246818, -337395714, -281211712, -218478864, -150120760, + -77192341, -857360, 77633043, 156945573, 235703099, 312492496, + 385896495, 454541831, 517077914, 572237251, 618849440, 655864033, + 682381207, 697662138, 701140517, 692454437, 671455926, 638192497, + 592950953, 536228301, 468743311, 391413562, 305373081, 211917193, + 112515196, 8778457, -97574737, -204722093, -310812643, -413944496, + -512244821, -603865242, -687056465, -760154912, -821653865, -870222658, + -904720479, -924233005, -928095122, -915899426, -887528715, -843128402, + -783143163, -708310042, -619630001, -518370643, -406052045, -284427622, + -155436858, -21195452, 116047980, 253948213, 390107041, 522103241, + 647551921, 764128146, 869637593, 962029890, 1039437023, 1100241539, + 1143083583, 1166892820, 1170916692, 1154740779, 1118299769, 1061881018, + 986122536, 892029173, 780944200, 654513839, 514700066, 363723079, + 204041778, 38296711, -130712875, -300087519, -466886151, -628155008, + -781010506, -922657115, -1050458160, -1161992111, -1255074688, -1327830658, + -1378698781, -1406490452, -1410403952, -1390048744, -1345443160, -1277046282, + -1185733013, -1072792031, -939913170, -789152392, -622900774, -443861303, + -254992312, -59450927, 139443874, 338270624, 533579987, 721937713, + 899993623, 1064543298, 1212581744, 1341359152, 1448429579, 1531710980, + 1589512741, 1620569648, 1624074651, 1599696439, 1547574911, 1468356915, + 1363161501, 1233562136, 1081583751, 909664374, 720608445, 517535818, + 303845742, 83153937, -140773909, -364088220, -582915643, -793431776, + -991930383, -1174877083, -1339004161, -1481332999, -1599238488, -1690519489, + -1753417293, -1786653305, -1789473370, -1761623106, -1703406621, -1615638750, + -1499680365, -1357367601, -1191013457, -1003373006, -797566749, -577067164, + -345613976, -107144347, 134245982, 374403491, 609177711, 834477933, + 1046389454, 1241198812, 1415473145, 1566135863, 1690502316, 1786338339, + 1851906157, 1885975091, 1887878900, 1857497793, 1795262548, 1702180329, + 1579789356, 1430135802, 1255748305, 1059597591, 845017078, 615693842, + 375555802, 128728549, -120541875, -367952417, -609239266, -840247912, + -1056986532, -1255711898, -1433001718, -1585806912, -1711490644, -1807893880, + -1873372869, -1906821270, -1907681888, -1875968599, -1812268342, -1717704175, + -1593954721, -1443189071, -1268052547, -1071604372, -857256046, -628745296, + -390036133, -145250986, 101370068, 345578885, 583188397, 810124441, + 1022511584, 1216750332, 1389559157, 1538037301, 1659724323, 1752624907, + 1815261574, 1846685940, 1846484281, 1814806282, 1752336430, 1660299848, + 1540418887, 1394895267, 1226368506, 1037861164, 832714737, 614557244, + 387207300, 154634175, -79136531, -310076941, -534235098, -747807622, + -947193377, -1129055065, -1290399669, -1428593288, -1541436757, -1627178290, + -1684539978, -1712767863, -1711595900, -1681285479, -1622599120, -1536772665, + -1425517966, -1290963494, -1135616184, -962344542, -774274368, -574781562, + -367391560, -155748026, 56468987, 265617545, 468136455, 660612031, + 839839063, 1002881883, 1147108605, 1270245760, 1370406427, 1446131637, + 1496385859, 1520595225, 1518643671, 1490871745, 1438059084, 1361412752, + 1262534324, 1143392079, 1006288158, 853795822, 688738010, 514100456, + 333016242, 148666198, -35733786, -217015994, -392114684, -558100465, + -712257271, -852104103, -975444447, -1080394328, -1165418355, -1229357540, + -1271415577, -1291209572, -1288731220, -1264358312, -1218861398, -1153343168, + -1069242324, -968305532, -852531316, -724153592, -585580472, -439354359, + -288129099, -134568938, 18639437, 168876066, 313606234, 450448228, + 577184171, 691821653, 792615435, 878069759, 947011876, 998555008, + 1032137571, 1047524066, 1044787870, 1024323798, 986830822, 933272555, + 864888321, 783151052, 689717699, 586439370, 475283364, 358327327, + 237682213, 115515955, -6047289, -124936621, -239160418, -346849610, + -446305192, -535984604, -614569358, -680950643, -734254056, -773856112, + -799382239, -810716482, -807980300, -791555184, -762029195, -720221489, + -667137368, -603957468, -532003241, -452726882, -367667281, -278430831, + -186650850, -93967586, -2010105, 87670605, 173583395, 254348294, + 328705558, 395535680, 453880834, 502971400, 542184178, 571117360, + 589547079, 597424930, 594903224, 582311351, 560135788, 529013782, + 489740139, 443210310, 390428155, 332480838, 270509976, 205696632, + 139248261, 72346401, 6164976, -58182531, -119639865, -177226711, + -230066695, -277391885, -318549814, -353018304, -380398777, -400445720, + -413030907, -418170496, -416006843, -406808812, -390949602, -368911794, + -341285549, -308709477, -271916169, -231679042, -188803111, -144109017, + -98433010, -52605797, -7410253, 36387441, 78074158, 117003911, + 152593644, 184341862, 211838920, 234752163, 252840296, 265961426, + 274066892, 277186709, 275448124, 269055850, 258286481, 243481885, + 225049684, 203441735, 179143029, 152678153, 124588986, 95419225, + 65714533, 36014755, 6833670, -21342804, -48066571, -72929222, + -95564180, -115671966, -133002819, -147362366, -158618696, -166699102, + -171586889, -173327948, -172026559, -167814604, -160894287, -151489663, + -139871117, -126329356, -111186960, -94771411, -77414678, -59467657, + -41266314, -23138140, -5391564, 11671033, 27790902, 42722186, + 56256573, 68223974, 78479099, 86918806, 93483066, 98132973, + 100882481, 101761537, 100840788, 98224915, 94030256, 88408558, + 81520765, 73547285, 64681638, 55113243, 45056283, 34698342, + 24242606, 13871476, 3767927, -5908113, -15006947, -23389971, + -30957637, -37604085, -43265955, -47896929, -51453182, -53942389, + -55361586, -55748217, -55150039, -53619207, -51237913, -48086596, + -44270032, -39882417, -35035095, -29835697, -24398261, -18831626, + -13233531, -7709600, -2359060, 2741076, 7508090, 11883351, + 15802228, 19226824, 22123134, 24464432, 26249325, 27466691, + 28134399, 28273722, 27908768, 27072999, 25812506, 24173126, + 22210833, 19974234, 17521274, 14903269, 12184305, 9415050, + 6651964, 3939391, 1325486, -1151329, -3451045, -5548765, + -7411580, -9028634, -10385842, -11469809, -12283476, -12825585, + -13106189, -13133337, -12930778, -12512723, -11898955, -11114197, + -10181485, -9136535, -7996551, -6790865, -5546526, -4288121, + -3042708, -1831404, -666060, 426453, 1433672, 2346296, + 3151055, 3844528, 4418334, 4867341, 5201684, 5417090, + 5517138, 5510524, 5407103, 5212655, 4939564, 4596810, + 4201640, 3756418, 3276626, 2775443, 2263223, 1749530, + 1245083, 755616, 295067, -137266, -531108, -885778, + -1193909, -1455972, -1667698, -1836140, -1951262, -2025669, + -2058551, -2043942, -1998955, -1921219, -1810497, -1674966, + -1525317, -1355771, -1176953, -994191, -810831, -625797, + -442618, -273791, -112000, 39406, 171237, 287439, + 392918, 476625, 546027, 599266, 631420, 652492, + 661672, 651810, 635639, 603428, 568623, 520399, + 472127, 414285, 362057, 300075, 247514, 186936, + 134315, 82093, 36560, -9730, -45362, -81307, + -109537, -129710, -147427, -160759, -168481, -172912, + -172555, -167998, -163837, -153003, -142682, -133355, + -120121, -102416, -88146, -72605, -59067, -43018, + -30225, -20737, -6450, 2671, 9514, 15270, + 21544, 27571, 31312, 30051, 32554, 35022, + 29866, 33834, 34496, 30956, 25856, 24739, + 21090, 18605, 13885, 11395, 12074, 8208, + 6113, 1491, 2436, -1194, 755, -1141, + -1742, -2584, -3779, -2934, -5882, -4082, + -4822, -4378, -850, -2076, -212, 341, + -1712, -2779, -3499, 1149, -151, 92, + -3132, 333, 1147, -3681, -2353, 1598, + 1786, -536, -1080, -780, 238, -2557, + -1215, -478, 1247, 793, +}; + +static const int32_t ifft_ref_imag_1024_q31[1024] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; diff --git a/test/cmocka/src/math/fft/ref_ifft_multi_1536_32.h b/test/cmocka/src/math/fft/ref_ifft_multi_1536_32.h new file mode 100644 index 000000000000..1a1b0fc65f4a --- /dev/null +++ b/test/cmocka/src/math/fft/ref_ifft_multi_1536_32.h @@ -0,0 +1,1044 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_IFFT_MULTI_1536_NUM_TESTS 1 + +static const int32_t ifft_in_real_1536_q31[1536] = { + 99, -4, 22, -33, 37, 83, + 29, 51, 3, 13, -14, -14, + -20, -21, 39, 31, -29, -6, + -26, -52, -4, -9, -9, -9, + 29, -25, -825, 92195, -1546020, 10045581, + -33641397, 65657100, -78882664, 59164046, -27128469, 7128081, + -930292, 42792, -213, 1, 4, 7, + 58, -24, 27, -19, -58, -34, + -1, -41, -4, -16, -22, -20, + -1, 35, 2, 8, 21, -59, + 28, -17, -35, -32, 56, 7, + -45, 10, 19, 26, 13, 7, + -17, 21, -20, 18, 19, -15, + -57, -18, 3, 33, 9, 11, + 9, -17, -5, 34, 23, 55, + -3, -10, 20, -2, 23, -8, + -6, -28, -21, -10, -15, 5, + 4, -21, -58, 16, 24, 45, + -15, -42, 10, -10, -46, -23, + 7, 13, 2, 17, -12, -35, + -31, 17, 30, -5, 1, 11, + 18, -5, 41, -13, -1, 14, + -9, -10, -16, -41, 12, 8, + 21, 13, 91, -53, -38, 19, + 11, 32, 36, 29, -19, 16, + -32, 22, 47, -35, -17, 6, + -1, -2, -34, 27, -12, -7, + -18, 16, -11, 28, 8, 31, + -72, 33, -32, 2, 27, -35, + -26, 2, -35, 9, 33, 1, + -34, -29, -35, 9, 12, -22, + -8, 0, 11, 21, -14, 3, + 41, 11, 27, 8, -14, 7, + -2, -18, 39, 26, -15, 7, + -6, 15, -17, -4, 19, 2, + -33, -11, -27, 0, 37, 45, + -8, 8, 38, 43, -16, -51, + -17, -35, -19, 32, 50, 9, + 2, -23, 36, 8, 34, 41, + -22, -40, 7, 9, -4, 23, + -35, 2, 0, 49, 66, 4, + -9, 18, 2, -25, -30, -21, + 51, -65, -15, -38, 72, 16, + -7, 27, -14, 2, 2, 18, + -45, -18, -17, -10, 17, -63, + -6, 1, -58, -16, -26, -8, + 9, 44, -9, 6, -19, 15, + -48, 28, -12, 51, -17, 42, + 6, -3, 12, -31, 19, -22, + 34, -9, 20, 38, -9, 0, + 40, -14, 31, 39, 74, -19, + -38, 19, 46, -2, -2, 27, + -24, -5, -34, 15, 8, 52, + 36, 53, 20, 31, -6, -4, + 21, -10, -6, 19, 7, -11, + -49, 32, -8, -16, 29, 9, + -6, -3, -2, 20, -7, -13, + 10, -16, -12, -81, -29, -34, + -42, 36, 4, 76, -12, -24, + 40, 39, 8, 9, 33, -8, + 34, 39, 16, 18, -30, -16, + 13, -22, 25, 21, 8, 28, + -17, -18, 2, -42, 40, -44, + 20, -53, -35, 30, 2, 25, + -58, -15, -32, 43, 25, 8, + 7, 6, -34, 27, 21, 56, + -65, 52, 27, -11, 28, 43, + -14, -11, 40, -29, 71, -69, + 28, 0, -11, -57, -33, 17, + 28, -21, -29, 0, -40, 1, + -28, -44, 31, 6, -16, -38, + 1, -41, -17, 46, -10, -21, + 30, 46, 57, -30, 37, -3, + -22, -55, -15, 20, -8, -4, + -29, 13, -11, 11, 3, 5, + -2, 51, -10, -29, -28, -5, + 33, -12, 5, -20, 3, -13, + -9, 7, -25, -38, 33, -13, + -46, -18, -7, -99, -32, -56, + 28, -1, 23, -17, -61, -36, + -14, -20, 17, -14, -11, -19, + 45, -10, 12, -12, -15, 18, + 32, 11, 6, -47, 0, -19, + 49, -23, 40, -36, 35, -19, + 9, -23, -7, -14, -45, 6, + 71, -8, 8, -25, -1, 14, + 39, 39, 61, -3, -42, 20, + 10, 27, -14, 49, -36, 6, + 21, 19, 15, 5, -12, -9, + 15, 6, -45, 19, -43, -4, + 9, 37, 37, 5, -29, 34, + -1, -24, -8, -18, -8, 39, + -19, -1, -12, 54, -36, -14, + 14, -8, 23, -59, -54, -13, + 39, 1, -12, -51, 18, 15, + -14, 5, 28, -15, -30, -5, + 7, 35, 21, -25, -40, -13, + -58, 36, 42, -16, 14, -28, + -50, -17, -10, -20, 2, 7, + -49, 38, -19, -2, -16, 8, + 9, 16, -12, 20, 1, 34, + 38, -9, 43, 31, 30, 0, + -55, -2, 69, 14, -23, 39, + -31, -20, 26, 46, 22, -24, + -1, 29, -24, 24, 6, 34, + -13, 21, 25, -34, 7, 9, + -47, -3, 46, -11, 27, -23, + -13, -21, -24, 5, 9, -49, + -7, 38, -13, 46, 2, 32, + 18, 38, 17, -47, 5, 4, + 8, 5, 34, -11, 26, 14, + 1, -7, 3, 45, -31, 2, + -13, -43, 58, 11, 14, -3, + -57, -28, -23, -5, 28, 42, + -1, 2, -1, 2, 25, -49, + -57, 18, -57, 18, 50, -32, + 26, -3, -23, -6, -60, -28, + 24, -9, 3, 28, 21, -46, + -22, -57, -21, 4, -63, -39, + -46, -51, 2, 20, -35, -47, + -14, 64, -75, 1, -8, 12, + 34, 13, 48, -10, 45, 23, + 12, 12, -6, -61, -45, 3, + 3, 45, -39, 12, 10, -49, + -14, 47, 7, -8, 31, -36, + -45, 9, 5, -2, -2, -8, + 24, -35, 6, -15, -8, 67, + 28, -5, -14, -9, -8, -24, + 131, -24, -8, -9, -14, -5, + 28, 67, -8, -15, 6, -35, + 24, -8, -2, -2, 5, 9, + -45, -36, 31, -8, 7, 47, + -14, -49, 10, 12, -39, 45, + 3, 3, -45, -61, -6, 12, + 12, 23, 45, -10, 48, 13, + 34, 12, -8, 1, -75, 64, + -14, -47, -35, 20, 2, -51, + -46, -39, -63, 4, -21, -57, + -22, -46, 21, 28, 3, -9, + 24, -28, -60, -6, -23, -3, + 26, -32, 50, 18, -57, 18, + -57, -49, 25, 2, -1, 2, + -1, 42, 28, -5, -23, -28, + -57, -3, 14, 11, 58, -43, + -13, 2, -31, 45, 3, -7, + 1, 14, 26, -11, 34, 5, + 8, 4, 5, -47, 17, 38, + 18, 32, 2, 46, -13, 38, + -7, -49, 9, 5, -24, -21, + -13, -23, 27, -11, 46, -3, + -47, 9, 7, -34, 25, 21, + -13, 34, 6, 24, -24, 29, + -1, -24, 22, 46, 26, -20, + -31, 39, -23, 14, 69, -2, + -55, 0, 30, 31, 43, -9, + 38, 34, 1, 20, -12, 16, + 9, 8, -16, -2, -19, 38, + -49, 7, 2, -20, -10, -17, + -50, -28, 14, -16, 42, 36, + -58, -13, -40, -25, 21, 35, + 7, -5, -30, -15, 28, 5, + -14, 15, 18, -51, -12, 1, + 39, -13, -54, -59, 23, -8, + 14, -14, -36, 54, -12, -1, + -19, 39, -8, -18, -8, -24, + -1, 34, -29, 5, 37, 37, + 9, -4, -43, 19, -45, 6, + 15, -9, -12, 5, 15, 19, + 21, 6, -36, 49, -14, 27, + 10, 20, -42, -3, 61, 39, + 39, 14, -1, -25, 8, -8, + 71, 6, -45, -14, -7, -23, + 9, -19, 35, -36, 40, -23, + 49, -19, 0, -47, 6, 11, + 32, 18, -15, -12, 12, -10, + 45, -19, -11, -14, 17, -20, + -14, -36, -61, -17, 23, -1, + 28, -56, -32, -99, -7, -18, + -46, -13, 33, -38, -25, 7, + -9, -13, 3, -20, 5, -12, + 33, -5, -28, -29, -10, 51, + -2, 5, 3, 11, -11, 13, + -29, -4, -8, 20, -15, -55, + -22, -3, 37, -30, 57, 46, + 30, -21, -10, 46, -17, -41, + 1, -38, -16, 6, 31, -44, + -28, 1, -40, 0, -29, -21, + 28, 17, -33, -57, -11, 0, + 28, -69, 71, -29, 40, -11, + -14, 43, 28, -11, 27, 52, + -65, 56, 21, 27, -34, 6, + 7, 8, 25, 43, -32, -15, + -58, 25, 2, 30, -35, -53, + 20, -44, 40, -42, 2, -18, + -17, 28, 8, 21, 25, -22, + 13, -16, -30, 18, 16, 39, + 34, -8, 33, 9, 8, 39, + 40, -24, -12, 76, 4, 36, + -42, -34, -29, -81, -12, -16, + 10, -13, -7, 20, -2, -3, + -6, 9, 29, -16, -8, 32, + -49, -11, 7, 19, -6, -10, + 21, -4, -6, 31, 20, 53, + 36, 52, 8, 15, -34, -5, + -24, 27, -2, -2, 46, 19, + -38, -19, 74, 39, 31, -14, + 40, 0, -9, 38, 20, -9, + 34, -22, 19, -31, 12, -3, + 6, 42, -17, 51, -12, 28, + -48, 15, -19, 6, -9, 44, + 9, -8, -26, -16, -58, 1, + -6, -63, 17, -10, -17, -18, + -45, 18, 2, 2, -14, 27, + -7, 16, 72, -38, -15, -65, + 51, -21, -30, -25, 2, 18, + -9, 4, 66, 49, 0, 2, + -35, 23, -4, 9, 7, -40, + -22, 41, 34, 8, 36, -23, + 2, 9, 50, 32, -19, -35, + -17, -51, -16, 43, 38, 8, + -8, 45, 37, 0, -27, -11, + -33, 2, 19, -4, -17, 15, + -6, 7, -15, 26, 39, -18, + -2, 7, -14, 8, 27, 11, + 41, 3, -14, 21, 11, 0, + -8, -22, 12, 9, -35, -29, + -34, 1, 33, 9, -35, 2, + -26, -35, 27, 2, -32, 33, + -72, 31, 8, 28, -11, 16, + -18, -7, -12, 27, -34, -2, + -1, 6, -17, -35, 47, 22, + -32, 16, -19, 29, 36, 32, + 11, 19, -38, -53, 91, 13, + 21, 8, 12, -41, -16, -10, + -9, 14, -1, -13, 41, -5, + 18, 11, 1, -5, 30, 17, + -31, -35, -12, 17, 2, 13, + 7, -23, -46, -10, 10, -42, + -15, 45, 24, 16, -58, -21, + 4, 5, -15, -10, -21, -28, + -6, -8, 23, -2, 20, -10, + -3, 55, 23, 34, -5, -17, + 9, 11, 9, 33, 3, -18, + -57, -15, 19, 18, -20, 21, + -17, 7, 13, 26, 19, 10, + -45, 7, 56, -32, -35, -17, + 28, -59, 21, 8, 2, 35, + -1, -20, -22, -16, -4, -41, + -1, -34, -58, -19, 27, -24, + 58, 7, 4, 1, -213, 42792, + -930292, 7128081, -27128469, 59164046, -78882664, 65657100, + -33641397, 10045581, -1546020, 92195, -825, -25, + 29, -9, -9, -9, -4, -52, + -26, -6, -29, 31, 39, -21, + -20, -14, -14, 13, 3, 51, + 29, 83, 37, -33, 22, -4, +}; + +static const int32_t ifft_in_imag_1536_q31[1536] = { + 0, 0, 18, -9, 28, 19, + 4, -28, -9, -34, -6, -1, + 0, 31, 9, -9, -65, -34, + 6, 1, -49, -34, -2, 18, + -20, -61, -2523, 286383, -4833354, 31628685, + -106676469, 209692391, -253750715, 191701771, -88543013, 23436058, + -3081460, 142801, -570, -45, -20, -15, + 0, -4, -25, 28, -24, -66, + -10, 11, 37, -2, 10, 5, + 64, -2, 10, -9, 25, 32, + 34, -76, -24, 40, 11, -61, + -57, 0, -18, -22, -30, 32, + -3, -26, 9, 28, 6, -25, + -29, 18, -31, -39, -59, -23, + -14, -71, 33, 9, -12, -61, + 44, -9, 8, 38, 65, 48, + 17, -22, 16, 15, 8, -12, + 36, 16, -55, -24, 13, -22, + -38, -58, 34, -28, 52, -24, + -12, 38, -6, -16, 5, 23, + -11, 21, -21, 11, 52, 0, + -1, 29, -39, 20, 40, 47, + 34, -16, 34, 23, -19, -39, + 14, -28, -10, 5, 23, 22, + 21, 8, -10, 18, -20, 33, + -16, 19, 22, -45, -13, -21, + 6, 23, -19, -18, -15, 15, + -5, -13, 26, -19, -33, 2, + 46, 7, -1, -10, 0, 50, + -4, -34, 23, -3, -36, -76, + -58, 28, 18, 16, 0, 7, + 6, 52, 9, 10, -14, 37, + 43, 28, -21, 37, 16, 4, + -28, -7, -64, -2, 3, -35, + -52, -25, -7, -30, -3, 46, + -24, 27, 64, 17, 2, -23, + 15, -6, -26, 33, 49, 7, + 9, -39, -38, 43, -33, -37, + 58, 16, 48, 23, 34, 24, + -15, -15, 21, 17, -3, -19, + 2, -15, 37, -9, 21, -18, + 26, 89, 39, 29, 1, -17, + 38, 25, -48, -27, -16, 21, + 20, -36, 16, -3, 16, -23, + -8, -34, 29, -62, 47, -39, + -2, 8, -23, -18, -20, 24, + -4, 29, 3, 14, -15, -13, + -36, 21, -15, -29, 15, -13, + -19, 21, -2, 53, -28, 11, + -12, -70, 48, -1, -11, -62, + -18, 7, -14, -2, 22, -40, + 6, -35, 35, 8, 5, -25, + -24, 69, -21, 26, 12, 53, + 21, 17, -3, -42, 39, -7, + 64, 23, -37, 30, -35, 37, + 23, 29, 20, 72, 0, 29, + 49, 38, -76, -39, -63, 33, + -3, -5, -8, 21, -15, -36, + 25, -34, -7, -1, 0, -74, + 15, 5, -9, 59, -12, 3, + -22, 48, -11, -36, -57, 4, + -5, 45, -38, 61, -17, 9, + 67, 11, 7, 22, -10, 13, + -10, 10, 11, -20, -9, 46, + -26, 12, 12, -54, 36, -8, + 7, -27, 24, 2, -26, 9, + -34, -15, 35, 59, 40, 18, + 19, 5, 20, 11, -41, -4, + -54, 50, -30, 19, -28, 3, + 0, 3, -12, -37, -75, 6, + -25, -9, -5, 33, 32, -40, + 38, 33, 21, -11, -24, -15, + 33, -16, -13, 30, -5, 31, + 44, 26, -33, -10, 10, 27, + -14, -2, -76, -6, -12, -29, + -20, -7, 1, 28, 13, -24, + 11, 64, -29, -10, -1, -10, + -30, -61, -10, -8, 23, 16, + -28, 68, -37, -49, -7, 73, + -39, 1, 53, 54, 44, 10, + 8, 14, -19, -6, -10, -6, + 42, -2, -15, 27, -6, -41, + 7, -27, 3, -43, -15, -31, + 15, 2, -17, 18, -37, -1, + -1, 5, 11, 11, -38, 33, + 17, -24, -53, 0, 30, -17, + 39, -20, -9, -6, 26, -18, + -17, 6, 10, -3, -75, -12, + -7, -27, 13, -25, -52, 41, + -19, -1, -78, 7, 23, -15, + 24, 16, -36, -15, -40, 8, + 20, 31, 8, 8, 48, -40, + 4, -29, -2, -1, -14, -56, + -37, -26, -41, 21, -17, -38, + -34, -1, 24, 33, -31, -14, + 8, -23, 6, -51, 28, 2, + 6, 4, 38, 4, -1, -39, + 17, -24, 0, 21, -32, -4, + -22, 6, 23, -67, 11, 31, + 36, 3, 27, 16, 24, -9, + 10, -9, -53, -45, -42, 17, + -24, -1, 15, -1, -8, -11, + -4, -59, 30, -47, -30, -24, + 27, -24, 62, 7, -60, 79, + -6, 2, 47, -20, -5, 41, + -8, 4, 43, -14, 32, -8, + -2, 11, -8, 12, -33, 5, + 24, -17, 8, -44, 37, 28, + -7, 24, -5, 42, -6, -42, + -8, 49, -30, 10, 61, -3, + 23, 48, 25, 45, -43, 4, + -7, -26, -23, -13, 18, -13, + -42, 52, 39, -60, -21, 23, + -71, -35, 9, 3, 1, -8, + 19, 0, -9, 8, -39, 1, + 8, 35, 2, 67, 1, -32, + -11, -16, 32, -16, -78, 14, + 54, -32, -16, 16, 2, -10, + 31, 1, 26, -20, -20, -25, + 1, -13, -16, -64, 0, 45, + -6, -29, 21, 55, 27, 55, + -10, -34, -22, 57, -1, 7, + 2, -6, 14, -9, -28, 13, + 1, 7, 7, 11, -45, -35, + -24, -46, 32, -27, 76, -27, + 4, -14, -7, -37, 24, -8, + -2, 58, 26, 34, -24, 23, + 29, 30, 28, -18, -5, 17, + 0, -17, 5, 18, -28, -30, + -29, -23, 24, -34, -26, -58, + 2, 8, -24, 37, 7, 14, + -4, 27, -76, 27, -32, 46, + 24, 35, 45, -11, -7, -7, + -1, -13, 28, 9, -14, 6, + -2, -7, 1, -57, 22, 34, + 10, -55, -27, -55, -21, 29, + 6, -45, 0, 64, 16, 13, + -1, 25, 20, 20, -26, -1, + -31, 10, -2, -16, 16, 32, + -54, -14, 78, 16, -32, 16, + 11, 32, -1, -67, -2, -35, + -8, -1, 39, -8, 9, 0, + -19, 8, -1, -3, -9, 35, + 71, -23, 21, 60, -39, -52, + 42, 13, -18, 13, 23, 26, + 7, -4, 43, -45, -25, -48, + -23, 3, -61, -10, 30, -49, + 8, 42, 6, -42, 5, -24, + 7, -28, -37, 44, -8, 17, + -24, -5, 33, -12, 8, -11, + 2, 8, -32, 14, -43, -4, + 8, -41, 5, 20, -47, -2, + 6, -79, 60, -7, -62, 24, + -27, 24, 30, 47, -30, 59, + 4, 11, 8, 1, -15, 1, + 24, -17, 42, 45, 53, 9, + -10, 9, -24, -16, -27, -3, + -36, -31, -11, 67, -23, -6, + 22, 4, 32, -21, 0, 24, + -17, 39, 1, -4, -38, -4, + -6, -2, -28, 51, -6, 23, + -8, 14, 31, -33, -24, 1, + 34, 38, 17, -21, 41, 26, + 37, 56, 14, 1, 2, 29, + -4, 40, -48, -8, -8, -31, + -20, -8, 40, 15, 36, -16, + -24, 15, -23, -7, 78, 1, + 19, -41, 52, 25, -13, 27, + 7, 12, 75, 3, -10, -6, + 17, 18, -26, 6, 9, 20, + -39, 17, -30, 0, 53, 24, + -17, -33, 38, -11, -11, -5, + 1, 1, 37, -18, 17, -2, + -15, 31, 15, 43, -3, 27, + -7, 41, 6, -27, 15, 2, + -42, 6, 10, 6, 19, -14, + -8, -10, -44, -54, -53, -1, + 39, -73, 7, 49, 37, -68, + 28, -16, -23, 8, 10, 61, + 30, 10, 1, 10, 29, -64, + -11, 24, -13, -28, -1, 7, + 20, 29, 12, 6, 76, 2, + 14, -27, -10, 10, 33, -26, + -44, -31, 5, -30, 13, 16, + -33, 15, 24, 11, -21, -33, + -38, 40, -32, -33, 5, 9, + 25, -6, 75, 37, 12, -3, + 0, -3, 28, -19, 30, -50, + 54, 4, 41, -11, -20, -5, + -19, -18, -40, -59, -35, 15, + 34, -9, 26, -2, -24, 27, + -7, 8, -36, 54, -12, -12, + 26, -46, 9, 20, -11, -10, + 10, -13, 10, -22, -7, -11, + -67, -9, 17, -61, 38, -45, + 5, -4, 57, 36, 11, -48, + 22, -3, 12, -59, 9, -5, + -15, 74, 0, 1, 7, 34, + -25, 36, 15, -21, 8, 5, + 3, -33, 63, 39, 76, -38, + -49, -29, 0, -72, -20, -29, + -23, -37, 35, -30, 37, -23, + -64, 7, -39, 42, 3, -17, + -21, -53, -12, -26, 21, -69, + 24, 25, -5, -8, -35, 35, + -6, 40, -22, 2, 14, -7, + 18, 62, 11, 1, -48, 70, + 12, -11, 28, -53, 2, -21, + 19, 13, -15, 29, 15, -21, + 36, 13, 15, -14, -3, -29, + 4, -24, 20, 18, 23, -8, + 2, 39, -47, 62, -29, 34, + 8, 23, -16, 3, -16, 36, + -20, -21, 16, 27, 48, -25, + -38, 17, -1, -29, -39, -89, + -26, 18, -21, 9, -37, 15, + -2, 19, 3, -17, -21, 15, + 15, -24, -34, -23, -48, -16, + -58, 37, 33, -43, 38, 39, + -9, -7, -49, -33, 26, 6, + -15, 23, -2, -17, -64, -27, + 24, -46, 3, 30, 7, 25, + 52, 35, -3, 2, 64, 7, + 28, -4, -16, -37, 21, -28, + -43, -37, 14, -10, -9, -52, + -6, -7, 0, -16, -18, -28, + 58, 76, 36, 3, -23, 34, + 4, -50, 0, 10, 1, -7, + -46, -2, 33, 19, -26, 13, + 5, -15, 15, 18, 19, -23, + -6, 21, 13, 45, -22, -19, + 16, -33, 20, -18, 10, -8, + -21, -22, -23, -5, 10, 28, + -14, 39, 19, -23, -34, 16, + -34, -47, -40, -20, 39, -29, + 1, 0, -52, -11, 21, -21, + 11, -23, -5, 16, 6, -38, + 12, 24, -52, 28, -34, 58, + 38, 22, -13, 24, 55, -16, + -36, 12, -8, -15, -16, 22, + -17, -48, -65, -38, -8, 9, + -44, 61, 12, -9, -33, 71, + 14, 23, 59, 39, 31, -18, + 29, 25, -6, -28, -9, 26, + 3, -32, 30, 22, 18, 0, + 57, 61, -11, -40, 24, 76, + -34, -32, -25, 9, -10, 2, + -64, -5, -10, 2, -37, -11, + 10, 66, 24, -28, 25, 4, + 0, 15, 20, 45, 570, -142801, + 3081460, -23436058, 88543013, -191701771, 253750715, -209692391, + 106676469, -31628685, 4833354, -286383, 2523, 61, + 20, -18, 2, 34, 49, -1, + -6, 34, 65, 9, -9, -31, + 0, 1, 6, 34, 9, 28, + -4, -19, -28, 9, -18, 0, +}; + +static const int32_t ifft_ref_real_1536_q31[1536] = { + -208, 1028, -2146, -280, 776, 1608, + 1081, 637, 842, 2274, 792, -115, + 4394, -1464, 1851, 967, -191, -578, + 3180, 1263, 2142, 3402, 586, 3266, + 1202, 1888, -1120, -375, 151, -3604, + -122, 1991, -236, -3107, -2506, -2626, + -4282, -4639, -172, -4654, -4533, -2999, + -15, -5065, -155, -4063, 1261, 721, + 3129, -671, 2662, 2723, 1061, 8426, + 7675, 7229, 12234, 10576, 10304, 13036, + 14434, 17152, 14472, 17043, 18274, 13826, + 13241, 11632, 10311, 8876, 7535, 5023, + 3673, -2123, -7309, -14532, -15667, -19573, + -23310, -31847, -36355, -41917, -44643, -49330, + -54444, -56048, -54924, -55007, -57774, -56197, + -52275, -46488, -40590, -33525, -26331, -14534, + -5315, 9452, 18671, 36735, 52659, 65412, + 79725, 95877, 109849, 123652, 137540, 145200, + 153930, 156815, 164349, 165740, 158411, 156119, + 147951, 133110, 115471, 91519, 70424, 42272, + 11340, -21575, -56827, -94279, -134881, -172055, + -213360, -250037, -284627, -319512, -347581, -372634, + -392288, -406000, -415059, -413205, -406127, -386463, + -366070, -328695, -289256, -232414, -177543, -111152, + -32078, 46657, 132162, 217378, 312255, 401003, + 492486, 578105, 657728, 735235, 800967, 858345, + 901514, 933447, 945826, 945383, 923194, 881957, + 823666, 744892, 650339, 532505, 401713, 249385, + 86826, -91622, -272974, -466517, -662726, -858114, + -1051320, -1236046, -1411686, -1569633, -1705463, -1822427, + -1914305, -1971737, -1997485, -1988663, -1938185, -1857534, + -1732525, -1564796, -1360688, -1122122, -845645, -539384, + -203558, 157006, 530053, 917864, 1312502, 1707075, + 2090197, 2459433, 2801281, 3110743, 3383779, 3607114, + 3778184, 3890401, 3933792, 3914304, 3817403, 3643098, + 3399418, 3073155, 2678505, 2209822, 1678372, 1084276, + 442509, -245337, -960479, -1702598, -2445594, -3185798, + -3906204, -4592220, -5233953, -5810889, -6310512, -6724566, + -7038143, -7235970, -7314842, -7265505, -7076677, -6754784, + -6296018, -5699434, -4969654, -4108742, -3136922, -2059649, + -890244, 353243, 1648727, 2977030, 4314244, 5640043, + 6926146, 8145887, 9277320, 10297821, 11185992, 11903031, + 12448852, 12792884, 12916543, 12821770, 12484853, 11912496, + 11102716, 10052315, 8769831, 7273682, 5584355, 3711104, + 1693775, -447201, -2677090, -4958879, -7247563, -9511744, + -11703465, -13782705, -15702704, -17424542, -18916260, -20127258, + -21032184, -21595619, -21803149, -21624235, -21057140, -20087223, + -18716527, -16953659, -14810811, -12321141, -9503518, -6400778, + -3055652, 480782, 4156075, 7903631, 11669689, 15374606, + 18958814, 22346114, 25474151, 28274296, 30683080, 32639661, + 34096110, 35002560, 35321394, 35025586, 34095720, 32521541, + 30304896, 27471731, 24037163, 20047123, 15547141, 10594808, + 5269683, -351499, -6179407, -12112749, -18058849, -23905328, + -29545744, -34872979, -39781852, -44166629, -47923957, -50978111, + -53236721, -54638099, -55119176, -54643963, -53185424, -50737369, + -47298744, -42907294, -37598036, -31434040, -24498741, -16887429, + -8713123, -94741, 8820257, 17893205, 26963034, 35871054, + 44447851, 52538069, 59975530, 66609377, 72294399, 76892212, + 80292014, 82392141, 83110260, 82389572, 80193927, 76508526, + 71360649, 64780127, 56849853, 47655824, 37328004, 26008147, + 13867342, 1085333, -12120465, -25536048, -38934836, -52068253, + -64705008, -76603397, -87527796, -97258179, -105585075, -112314562, + -117280713, -120338580, -121384153, -120330545, -117127521, -111779505, + -104304143, -94771825, -83291461, -70009055, -55094819, -38774930, + -21294148, -2914662, 16054170, 35299102, 54488431, 73287116, + 91347784, 108331536, 123909356, 137766473, 149616023, 159180965, + 166233868, 170575046, 172064616, 170576428, 166068025, 158531167, + 148009147, 134610545, 118483473, 99844653, 78947786, 56095457, + 31645852, 5973079, -20500963, -47330323, -74052822, -100200161, + -125296303, -148871677, -170474655, -189679049, -206074331, -219306189, + -229059310, -235068628, -237134168, -235123748, -228956546, -218641946, + -204252159, -185934134, -163910290, -138473312, -109988245, -78863628, + -45594336, -10693457, 25250196, 61651254, 97872112, 133279643, + 167232663, 199102751, 228284556, 254194790, 276309629, 294146180, + 307294012, 315412570, 318233653, 315585456, 307396754, 293662441, + 274507454, 250130988, 220841590, 187039402, 149213225, 107920491, + 63808737, 17587427, -29987869, -78118952, -125968080, -172711586, + -217494176, -259499772, -297926602, -332032449, -361127238, -384589906, + -401888592, -412591548, -416368239, -413003605, -402401970, -384597510, + -359738491, -328121730, -290141454, -246339982, -197346613, -143913090, + -86867154, -27145840, 34282217, 96378194, 158069896, 218280353, + 275928983, 329964614, 379369503, 423194148, 460570682, 490705819, + 512949051, 526745521, 531697773, 527540589, 514173891, 491656679, + 460188620, 420159841, 372096451, 316682269, 254737793, 187222598, + 115194822, 39831891, -37626003, -115868772, -193555103, -269324053, + -341819985, -409734768, -471798949, -526832218, -573747752, -611592070, + -639544497, -656948721, -663307112, -658324851, -641879757, -614068853, + -575169661, -525665973, -466233677, -397737653, -321211140, -237834773, + -148953290, -56002184, 39464289, 135838415, 231470672, 324683029, + 413824173, 497281235, 573519966, 641099500, 698711660, 745193260, + 779570707, 801047198, 809057956, 803239996, 783490048, 749925326, + 702910625, 643062665, 571208539, 488421585, 395954303, 295274829, + 187992943, 75867686, -39234688, -155364893, -270526625, -382721173, + -489954333, -590312450, -681948840, -763162502, -832395730, -888280790, + -929662923, -955628164, -965508614, -958905396, -935714163, -896097977, + -840525812, -769729565, -684734615, -586818083, -477494634, -358505054, + -231767635, -99384991, 36447908, 173418741, 309179351, 441372486, + 567665080, 685809850, 793657618, 889220299, 970691248, 1036487321, + 1085290926, 1116036982, 1127985532, 1120690429, 1094052234, 1048304735, + 983994827, 902020022, 803586229, 690197392, 563634712, 425927856, + 279326828, 126252690, -30727602, -188948106, -345698579, -498253663, + -643943557, -780184469, -904517779, -1014672187, -1108602474, -1184506618, + -1240893623, -1276580740, -1290736320, -1282893759, -1252957322, -1201218320, + -1128344799, -1035378921, -923712736, -795091118, -651549487, -495428782, + -329278199, -155867023, 21884624, 200964166, 378296390, 550817084, + 715509842, 869465952, 1009935821, 1134382373, 1240516904, 1326342221, + 1390206083, 1430813800, 1447256973, 1439042403, 1406102963, 1348789380, + 1267880510, 1164559892, 1040430447, 897443767, 737906646, 564425518, + 379875346, 187325754, -9959043, -208628068, -405280556, -596522969, + -779024043, -949576504, -1105159555, -1242986235, -1360557688, -1455707771, + -1526630125, -1571931512, -1590656579, -1582288902, -1546785379, -1484564418, + -1396514081, -1283966465, -1148699380, -992870834, -819030265, -630046527, + -429061869, -219452221, -4767624, 211344570, 425174230, 633047815, + 831345812, 1016614742, 1185594779, 1335289737, 1463018092, 1566456589, + 1643704895, 1693273650, 1714172081, 1705882228, 1668384051, 1602168866, + 1508224931, 1388011642, 1243467936, 1076940537, 891184470, 689290793, + 474641988, 250858324, 21737861, -208816087, -436846641, -658446865, + -869777852, -1067170436, -1247183257, -1406646888, -1542751972, -1653062659, + -1735582597, -1788791763, -1811654306, -1803668814, -1764855539, -1695759994, + -1597456049, -1471530418, -1320042339, -1145497633, -950809867, -739249865, + -514385056, -280041257, -40181383, 201080379, 439624918, 671355509, + 892286064, 1098594389, 1286706868, 1453352441, 1595628823, 1711035463, + 1797521019, 1853538365, 1878059813, 1870600384, 1831206309, 1760492154, + 1659602184, 1530203408, 1374457364, 1194986427, 994818107, 777345237, + 546255918, 305492794, 59165875, -188527458, -433341422, -671079309, + -897668893, -1109214643, -1302074023, -1472937031, -1618848646, -1737290618, + -1826217726, -1884079590, -1909863238, -1903105212, -1863905400, -1792913351, + -1691333260, -1560895247, -1403806747, -1222758514, -1020847804, -801517798, + -568519036, -325840915, -77637046, 171850151, 418353964, 657652106, + 885660159, 1098481666, 1292480155, 1464355516, 1611177051, 1730444441, + 1820150539, 1878772825, 1905343502, 1899434946, 1861181237, 1791267354, + 1690932265, 1561919190, 1406470627, 1227285157, 1027454790, 810422575, + 579933199, 339937735, 94560706, -151998519, -395519648, -631847447, + -856952704, -1067020943, -1258483185, -1428108906, -1573046811, -1690880320, + -1779653406, -1837919413, -1864754559, -1859783641, -1823171173, -1755625833, + -1658386915, -1533198396, -1382281189, -1208279192, -1014238945, -803541923, + -579834919, -346970773, -108971582, 130083337, 366114057, 595094166, + 813132897, 1016558501, 1201938275, 1366176039, 1506542457, 1620740077, + 1706919479, 1763717224, 1790275640, 1786276393, 1751908357, 1687891249, + 1595438012, 1476262486, 1332509163, 1166745659, 981900242, 781222554, + 568211774, 346560641, 120100574, -107289782, -331713541, -549356216, + -756540884, -949779137, -1125851227, -1281843132, -1415192803, -1523754996, + -1605802264, -1660092492, -1685848824, -1682801752, -1651163067, -1591637338, + -1505408041, -1394110256, -1259790097, -1104882900, -932150731, -744661919, + -545709413, -338757446, -127382761, 84765707, 294067250, 496976412, + 690070929, 870113211, 1034134977, 1179439235, 1303678232, 1404885195, + 1481490379, 1532369848, 1556838111, 1554667668, 1526100288, 1471814589, + 1392935146, 1290979951, 1167883446, 1025897621, 867598300, 695803013, + 513556483, 324055689, 130579822, -63530664, -254960711, -440468393, + -616936322, -781437175, -931258704, -1063977475, -1177469159, -1269973586, + -1340088669, -1386818867, -1409579450, -1408193505, -1382898111, -1334344314, + -1263572251, -1171997342, -1061377097, -933764183, -791500540, -637158044, + -473474842, -303339128, -129708618, 44418353, 216071053, 382335233, + 540448165, 687781229, 821938681, 940758749, 1042384718, 1125252993, + 1188147956, 1230202439, 1250926083, 1250188874, 1228226406, 1185647049, + 1123399468, 1042758074, 945299018, 832869534, 707550079, 571621816, + 427526974, 277809022, 125084990, -28007635, -178856734, -324907138, + -463734021, -593052973, -710764745, -815013568, -904171247, -976904534, + -1032170687, -1069237209, -1087700273, -1087470343, -1068778111, -1032176645, + -978516872, -908919323, -824774811, -727708909, -619535342, -502245966, + -377946914, -248858753, -117245647, 14624738, 144489450, 270173067, + 389580624, 500766017, 601940765, 691518395, 768126426, 830640815, + 878191105, 910178934, 926258016, 926396556, 910805951, 879973778, + 834645350, 775805740, 704647514, 622561565, 531103763, 431972981, + 326970096, 217973439, 106899986, -4330812, -113813213, -219710289, + -320272154, -413860814, -498998744, -574348156, -638786776, -691379857, + -731412862, -758411959, -772099815, -772476020, -759732747, -734296127, + -696804018, -648095467, -589173798, -521211860, -445513712, -363500819, + -276669977, -186588833, -94839242, -3023445, 87304541, 174622298, + 257494031, 334584378, 404667892, 466682945, 519706284, 562979312, + 595951179, 618222270, 629608809, 630112956, 619904735, 599360500, + 569008486, 529544706, 481803119, 426750006, 365455529, 299075876, + 228840843, 156016605, 81889836, 7756860, -65127282, -135536293, + -202317721, -264407579, -320823972, -370715300, -413363358, -448173476, + -474700396, -492652588, -501896551, -502436599, -494431331, -478193830, + -454159830, -422893027, -385065038, -341461778, -292933893, -240416823, + -184881223, -127335687, -68805911, -10307038, 47162104, 102643156, + 155228358, 204082912, 248449560, 287665317, 321164977, 348506386, + 369349387, 383472021, 390781163, 391299046, 385158588, 372607442, + 354005897, 329793737, 300515771, 266774740, 229249182, 188658014, + 145771955, 101363895, 56228463, 11154361, -33085315, -75765867, + -116185210, -153712088, -187762879, -217843178, -243525696, -264475607, + -280445626, -291273854, -296909542, -297359668, -292750374, -283274804, + -269211393, -250910393, -228781316, -203300855, -174980799, -144372364, + -112054201, -78621969, -44668588, -10793090, 22429460, 54446787, + 84748044, 112851032, 138327117, 160818678, 180008562, 195655717, + 207575091, 215660629, 219880235, 220245999, 216864942, 209880683, + 199509818, 186014197, 169708472, 150946259, 130109644, 107612785, + 83879303, 59350962, 34464106, 9662772, -14639065, -38039657, + -60160003, -80657250, -99220426, -115593466, -129546162, -140913942, + -149573644, -155442464, -158504321, -158789018, -156361959, -151342314, + -143885404, -134196704, -122497522, -109047150, -94117870, -78022254, + -61057968, -43547261, -25804349, -8129901, 9162869, 25798240, + 41501763, 56035957, 69186490, 80772311, 90633998, 98658424, + 104762522, 108903204, 111057934, 111259018, 109562688, 106046605, + 100834254, 94063360, 85898082, 76517844, 66128784, 54935713, + 43153877, 31006516, 18711362, 6483672, -5469064, -16945311, + -27770754, -37775892, -46818615, -54771112, -61533068, -67026503, + -71200739, -74026465, -75494146, -75627807, -74467061, -72073364, + -68533189, -63937179, -58405371, -52064462, -45039931, -37490040, + -29556752, -21379814, -13124254, -4921292, 3081325, 10761369, + 17992294, 24664939, 30680797, 35969684, 40457241, 44097381, + 46861649, 48722338, 49681754, 49764898, 48992385, 47410889, + 45073356, 42055772, 38424287, 34266273, 29673244, 24744847, + 19568708, 14249149, 8882570, 3560649, -1623890, -6587324, + -11253071, -15553237, -19428909, -22822812, -25697558, -28027913, + -29781633, -30967017, -31573078, -31616950, -31116986, -30105009, + -28612194, -26690950, -24392479, -21758782, -18856741, -15747532, + -12493053, -9151192, -5784785, -2455284, 778428, 3873794, + 6780421, 9450391, 11848188, 13945439, 15721307, 17153486, + 18229833, 18951292, 19317601, 19331829, 19021991, 18391908, + 17477080, 16298631, 14892301, 13286497, 11524410, 9636999, + 7666248, 5643968, 3619164, 1614643, -329494, -2182511, + -3917053, -5510740, -6935551, -8181585, -9230774, -10069505, + -10702745, -11124460, -11330344, -11338179, -11147183, -10771893, + -10229996, -9534288, -8708260, -7772003, -6742108, -5645520, + -4499511, -3330022, -2160619, -1007517, 105958, 1168081, + 2163850, 3069108, 3879602, 4582611, 5175824, 5650631, + 6001619, 6231347, 6348767, 6345832, 6232970, 6020724, + 5711035, 5319768, 4857301, 4330983, 3759052, 3147093, + 2517341, 1869971, 1228320, 593568, -13299, -596644, + -1133926, -1626587, -2061258, -2441661, -2757956, -3009281, + -3195090, -3317069, -3371358, -3369538, -3302704, -3189124, + -3018550, -2810982, -2566460, -2287369, -1982568, -1663786, + -1330037, -993438, -655731, -327480, -11833, 285255, + 559486, 814369, 1035555, 1225864, 1383761, 1511685, + 1599628, 1660692, 1688986, 1684490, 1647570, 1589017, + 1501582, 1394429, 1269741, 1134725, 981075, 823149, + 660159, 493844, 330114, 168814, 14527, -125758, + -257464, -379420, -486743, -577185, -649186, -707958, + -749120, -773688, -786833, -783576, -765253, -738249, + -693765, -642543, -586705, -522856, -450846, -376578, + -301263, -227397, -150470, -82949, -13294, 54367, + 108632, 162347, 208816, 250661, 281292, 304919, + 322777, 332948, 337096, 334473, 326032, 313228, + 295408, 269412, 246699, 215496, 190086, 157695, + 129658, 95562, 61975, 35544, 6711, -22281, + -42869, -59780, -80439, -98610, -110030, -117739, + -124576, -125753, -129948, -128983, -126581, -120301, + -111860, -100762, -94013, -80985, -73587, -61872, + -44448, -35456, -24861, -15228, -2995, 5562, + 13149, 23916, 29909, 35440, 38197, 42010, + 41917, 45141, 44609, 43511, 37540, 35788, + 34531, 31114, 29589, 26982, 24108, 17555, + 14847, 11406, 8428, 3218, 3294, -1756, + -1478, -3498, -8358, -10181, -11537, -11814, + -13888, -11146, -12862, -10178, -12001, -9587, + -8324, -8228, -7163, -2786, -4551, -4214, + -5084, -462, -2985, -2426, -1665, 3391, + 1562, -1694, 4507, 3775, 5534, 2691, + 2039, 5411, 4536, 2785, 1536, 1316, + 3155, 784, -961, 1172, 6, 2598, + 6, -1522, -831, 2692, 3324, -1300, + -1621, -647, -107, 3253, 1955, -1892, + 328, -2424, 701, -926, 497, -2227, + -2074, 2411, -2446, -1601, 854, 603, +}; + +static const int32_t ifft_ref_imag_1536_q31[1536] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; diff --git a/test/cmocka/src/math/fft/ref_ifft_multi_24_32.h b/test/cmocka/src/math/fft/ref_ifft_multi_24_32.h new file mode 100644 index 000000000000..8bcfdd9a5674 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_ifft_multi_24_32.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_IFFT_MULTI_24_NUM_TESTS 1 + +static const int32_t ifft_in_real_24_q31[24] = { + 482922326, -394845603, 213372960, -73385945, 14855847, -1509706, + 52714, 201, 43, 63, -129, -11, + 417, -11, -129, 63, 43, 201, + 52714, -1509706, 14855847, -73385945, 213372960, -394845603, +}; + +static const int32_t ifft_in_imag_24_q31[24] = { + 0, -45964234, 50459274, -26744935, 7515901, -1010620, + 45488, -203, -258, 455, -501, -248, + 0, 248, 501, -455, 258, 203, + -45488, 1010620, -7515901, 26744935, -50459274, 45964234, +}; + +static const int32_t ifft_ref_real_24_q31[24] = { + 3611, 3470, 104050, 1303039, 8697436, 38649256, + 126241459, 320754897, 656625195, 1107910524, 1563494828, 1861834284, + 1878967615, 1607563569, 1161729935, 703464423, 352140415, 142695560, + 45325407, 10719014, 1734754, 163218, 8211, 1653, +}; + +static const int32_t ifft_ref_imag_24_q31[24] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; diff --git a/test/cmocka/src/math/fft/ref_ifft_multi_256_32.h b/test/cmocka/src/math/fft/ref_ifft_multi_256_32.h new file mode 100644 index 000000000000..edc4d0e6bcf5 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_ifft_multi_256_32.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:52 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_IFFT_MULTI_256_NUM_TESTS 1 + +static const int32_t ifft_in_real_256_q31[256] = { + -104443, 1525281, -13889136, 60179033, -146702250, 217202408, + -201034199, 115601193, -39529650, 7259750, -570251, 9887, + -10, -25, -68, -107, 25, -62, + -37, -112, 27, -50, -122, 55, + 55, -9, -19, -74, 31, 1, + -21, 24, -93, -138, 2, 128, + 31, -108, -62, -21, 153, 60, + -104, 65, 61, 63, 82, 19, + -92, -12, -63, -10, -8, 72, + 6, -41, -35, 2, 172, 109, + 7, 87, -64, -88, 4, 133, + 19, -113, 0, 93, 82, 106, + 17, 44, 38, -76, -19, -96, + 25, 37, 52, -61, -129, 25, + -116, -18, -62, -88, -142, -17, + 88, 52, 70, 8, -36, -104, + 138, 103, 24, -9, 60, 17, + -86, 24, -150, 13, -84, 138, + -114, -4, 17, 65, 0, 9, + 22, 13, -110, -64, 50, 52, + -37, 79, -79, -85, -120, -34, + 76, -81, 60, -81, 76, -34, + -120, -85, -79, 79, -37, 52, + 50, -64, -110, 13, 22, 9, + 0, 65, 17, -4, -114, 138, + -84, 13, -150, 24, -86, 17, + 60, -9, 24, 103, 138, -104, + -36, 8, 70, 52, 88, -17, + -142, -88, -62, -18, -116, 25, + -129, -61, 52, 37, 25, -96, + -19, -76, 38, 44, 17, 106, + 82, 93, 0, -113, 19, 133, + 4, -88, -64, 87, 7, 109, + 172, 2, -35, -41, 6, 72, + -8, -10, -63, -12, -92, 19, + 82, 63, 61, 65, -104, 60, + 153, -21, -62, -108, 31, 128, + 2, -138, -93, 24, -21, 1, + 31, -74, -19, -9, 55, 55, + -122, -50, 27, -112, -37, -62, + 25, -107, -68, -25, -10, 9887, + -570251, 7259750, -39529650, 115601193, -201034199, 217202408, + -146702250, 60179033, -13889136, 1525281, +}; + +static const int32_t ifft_in_imag_256_q31[256] = { + 0, -1104526, 9802224, -41374276, 98231553, -141609308, + 127580058, -71388104, 23746028, -4240611, 323629, -5337, + 32, -60, -129, -15, -27, 102, + 58, -169, -92, 19, 75, 5, + -81, 131, -54, -36, -21, -15, + 118, -72, -77, 65, -42, 118, + -9, -18, 106, 80, -7, 88, + 41, 65, 32, -107, -22, -1, + 67, 45, 7, -109, 47, -25, + -53, -44, -33, -24, 2, 179, + -68, 105, 153, 16, -75, -42, + 11, -113, -44, -22, -63, -25, + 6, 2, 26, -87, 111, 106, + -53, -51, -36, -51, -27, 235, + -114, -20, -69, 10, -97, 83, + -57, -37, -69, -148, -34, 75, + 76, -38, 60, 29, 152, 37, + 141, 35, 52, -103, 96, -39, + -4, 38, -124, 18, 162, -48, + 52, -93, 94, -33, -1, 129, + 54, -27, 16, 64, 44, -43, + -45, 22, 0, -22, 45, 43, + -44, -64, -16, 27, -54, -129, + 1, 33, -94, 93, -52, 48, + -162, -18, 124, -38, 4, 39, + -96, 103, -52, -35, -141, -37, + -152, -29, -60, 38, -76, -75, + 34, 148, 69, 37, 57, -83, + 97, -10, 69, 20, 114, -235, + 27, 51, 36, 51, 53, -106, + -111, 87, -26, -2, -6, 25, + 63, 22, 44, 113, -11, 42, + 75, -16, -153, -105, 68, -179, + -2, 24, 33, 44, 53, 25, + -47, 109, -7, -45, -67, 1, + 22, 107, -32, -65, -41, -88, + 7, -80, -106, 18, 9, -118, + 42, -65, 77, 72, -118, 15, + 21, 36, 54, -131, 81, -5, + -75, -19, 92, 169, -58, -102, + 27, 15, 129, 60, -32, 5337, + -323629, 4240611, -23746028, 71388104, -127580058, 141609308, + -98231553, 41374276, -9802224, 1104526, +}; + +static const int32_t ifft_ref_real_256_q31[256] = { + -1569, -830, -1909, -1488, 3415, 3228, + 2188, 5284, 6862, 8740, 14431, 22319, + 31495, 39307, 50570, 64256, 80688, 97686, + 111687, 123695, 129388, 123769, 106202, 69953, + 5001, -90529, -229211, -419412, -662837, -975167, + -1362616, -1829929, -2378158, -3009308, -3713257, -4488081, + -5304582, -6149738, -6981956, -7751361, -8417790, -8914691, + -9158092, -9075448, -8582552, -7568550, -5957542, -3636565, + -521174, 3464467, 8388636, 14295537, 21192186, 29060893, + 37842039, 47439021, 57690475, 68385421, 79264186, 90000101, + 100216705, 109496356, 117359992, 123303230, 126792865, 127286147, + 124251244, 117173422, 105589837, 89107796, 67418137, 40323152, + 7767654, -30165152, -73203423, -120914317, -172649439, -227578442, + -284684073, -342740508, -400372402, -456051421, -508121756, -554862914, + -594502691, -625273094, -645469812, -653507615, -647957114, -627616785, + -591570790, -539212509, -470319052, -385064318, -284054609, -168344268, + -39430444, 100735569, 249803271, 405020394, 563321689, 721358446, + 875594019, 1022376304, 1158027755, 1278948253, 1381696559, 1463114882, + 1520394842, 1551181119, 1553662138, 1526604042, 1469444535, 1382288632, + 1265978107, 1122031888, 952680234, 760801123, 549852852, 323835818, + 87168988, -155419072, -398954843, -638404904, -868755989, -1085152640, + -1283040981, -1458244948, -1607111733, -1726568155, -1814231913, -1868441101, + -1888300566, -1873720889, -1825365598, -1744688034, -1633837210, -1495617661, + -1333406076, -1151061358, -952804289, -743116848, -526638885, -308020361, + -91818428, 117599868, 316184921, 500269979, 666664268, 812707094, + 936326727, 1036037706, 1110986476, 1160919766, 1186188110, 1187665485, + 1166746402, 1125255573, 1065389168, 989631979, 900676276, 801355102, + 694539705, 583089310, 469753347, 357133296, 247607391, 143289840, + 46010628, -42730106, -121763798, -190243820, -247669626, -293855572, + -328899891, -353164563, -367242673, -371922368, -368136646, -356940054, + -339446602, -316817655, -290210974, -260754391, -229500117, -197441719, + -165470302, -134343018, -104720510, -77121551, -51962267, -29512549, + -9954815, 6654740, 20324394, 31163846, 39337881, 45058213, + 48577520, 50167506, 50120504, 48722648, 46250707, 42973219, + 39131997, 34949970, 30607270, 26272771, 22078954, 18121182, + 14480497, 11206366, 8326540, 5845185, 3759796, 2057048, + 705551, -326115, -1083775, -1602381, -1917835, -2073023, + -2101305, -2038436, -1903566, -1728329, -1527768, -1319424, + -1111624, -920902, -739460, -586382, -452219, -337529, + -243069, -171574, -119157, -73001, -40498, -22362, + -7395, -1426, 8844, 10381, 5185, 10614, + 6251, 4908, 6476, 3273, 608, 2586, + -939, 517, -2100, 59, +}; + +static const int32_t ifft_ref_imag_256_q31[256] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; diff --git a/test/cmocka/src/math/fft/ref_ifft_multi_3072_32.h b/test/cmocka/src/math/fft/ref_ifft_multi_3072_32.h new file mode 100644 index 000000000000..9fc9c64978d3 --- /dev/null +++ b/test/cmocka/src/math/fft/ref_ifft_multi_3072_32.h @@ -0,0 +1,2068 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. + */ + +/* Created 20-Nov-2025 16:11:53 with script ref_fft_multi.m v1.9-rc1-6882-ge0b90b605-dirty */ + +#define REF_SOFM_IFFT_MULTI_3072_NUM_TESTS 1 + +static const int32_t ifft_in_real_3072_q31[3072] = { + -59, -1, -55, 24, -14, 0, + -14, -29, -16, 30, -13, 24, + 23, -8, -29, -3, -6, -29, + -25, -14, -20, 1, -8, 2, + 7, -21, -15, 18, -56, 0, + -26, 43, -5, 7, 42, -26, + -13, -5, -24, -8, -11, -27, + 20, -6, -4, -1, 14, -21, + -23, 31, 4, -7, 21, 31, + 51, -20, -8, -5, -2784, 237345, + -3580001, 21781536, -69391859, 129763784, -149772281, 107836784, + -47262139, 11753785, -1421192, 57131, -155, -28, + -24, 6, -19, 20, -3, 7, + -19, -9, -52, 28, -31, 44, + -14, 8, -3, -37, 7, -25, + 13, 29, 2, 70, 13, 16, + -4, 40, -34, 7, -23, 26, + -20, 9, 21, 6, -31, -27, + -19, 12, 20, -15, 15, -3, + -34, 34, -24, 39, 62, 3, + -38, 21, -21, 39, 2, -4, + 8, 9, -25, -17, 35, 14, + -4, 13, 30, -13, 7, 18, + 22, -27, 8, -34, -15, 5, + 0, 18, -26, -22, 16, 6, + -19, -15, -12, -19, 11, 25, + -6, 6, -1, 40, 24, -17, + 0, -30, 2, -3, 15, 6, + 32, -2, -6, 8, -44, -28, + -11, -17, -16, 24, -4, 9, + 11, 22, -16, 9, 13, -10, + 11, -31, 10, -39, -9, 3, + 24, 7, -32, 31, -9, -22, + -17, 7, -17, 22, 8, -11, + 0, 6, 20, 22, -25, 18, + 1, 6, -21, -8, -1, -2, + 22, -1, -30, 13, -8, -21, + -21, -22, 15, -17, 40, -15, + -21, 7, -6, 9, 37, -3, + 13, -10, -52, 31, -8, 23, + 39, 14, -4, 5, -9, -38, + -9, -4, 10, 2, 42, -27, + 2, 28, -15, -16, -22, 17, + 0, -15, 14, -11, 4, -17, + -24, 4, 6, -15, -2, 40, + 7, 1, 22, -2, 0, -10, + -2, 31, -5, 20, -12, -6, + 0, 12, 1, -35, 7, -26, + 11, -47, 3, -34, 23, 1, + -8, 0, 11, 18, 26, -1, + -31, 23, 10, -17, -12, 7, + 5, -21, 19, 10, -14, 11, + 12, -10, 49, 0, 5, -16, + -9, 24, 11, 21, -29, -15, + -31, -21, -5, 46, -25, 1, + 62, -18, -32, -8, 4, 5, + -22, -27, 38, -15, 19, 3, + -22, 8, 16, -27, 18, -31, + -25, -22, 23, -34, 1, 39, + 1, -11, 2, 40, 19, 29, + -29, -3, 4, 33, -26, 1, + 15, 3, -8, 65, 29, 3, + -7, 26, -25, 10, -4, 14, + 40, -30, 1, 11, 5, 17, + 9, 8, -6, -13, 18, 27, + -1, -25, 15, 85, -20, 6, + -32, -29, 31, 13, -17, -4, + 9, -3, 8, 11, -11, -38, + -26, 7, -19, 13, 28, 32, + 20, 1, -8, 11, 13, 1, + 8, 20, 40, 2, -41, -7, + -13, 6, 0, 45, -8, 26, + 13, 9, 7, 31, -19, -28, + -18, -19, 10, 13, -5, -32, + 18, -26, -23, 19, -23, -3, + -7, -9, 4, 3, -12, 7, + 14, -14, 29, 22, 0, 63, + -6, 5, -24, -13, 7, 34, + -9, 9, 9, 21, 4, 7, + 3, 17, 31, -27, -38, -47, + 17, 12, -11, -14, 15, -10, + -3, 22, 11, 14, 2, -16, + 23, 5, -48, -18, -21, 38, + -23, 8, -7, -19, 31, 29, + -14, -7, 22, 6, 38, 1, + 22, 24, -9, -2, 20, -70, + 21, 20, -42, -1, -39, -7, + -7, 26, -57, -18, 28, 22, + -4, 11, -13, 12, -16, -5, + -9, -5, 9, 3, 4, -38, + -2, -2, -20, 4, -34, -21, + 15, -54, -8, -47, -17, 25, + -26, 20, 6, 12, -20, 21, + -10, -7, 32, -26, 16, -3, + -9, 1, -3, -3, 6, -9, + -11, 18, 0, -23, -17, 1, + 1, -13, -9, -1, 7, 8, + -16, -7, 19, 15, -38, 4, + 21, 20, 3, -1, 5, -2, + -7, 25, -66, 41, -9, -20, + -17, -22, 11, -16, 4, 17, + 6, 22, -20, 14, -4, -2, + 22, -5, 32, 16, 36, -1, + -6, 0, -20, 8, -2, 14, + -29, -2, 6, 14, -4, 9, + 23, -4, 4, -21, -11, -20, + -13, -22, -30, 14, -18, 39, + 27, -24, 24, -19, 24, 29, + 1, -29, 14, 22, -2, -4, + -34, -26, 7, 24, -22, 4, + 24, -19, -35, 11, -4, 10, + -12, -21, 22, 7, 14, 17, + 8, 11, 9, 23, 3, -15, + -6, 20, -11, -17, -28, 33, + -6, 2, -12, -19, -13, -18, + -7, 45, 18, -20, -1, 2, + 15, -1, 37, 9, -15, -12, + 23, 10, 0, 29, -23, 42, + -15, 7, -22, -9, 2, 6, + -30, -26, 56, -18, 2, -1, + -20, -25, 30, 25, -15, 29, + 20, -11, -25, 29, 4, -26, + 9, -8, -14, 29, 13, 4, + -29, 2, -5, -12, 3, 27, + -9, -13, 42, 10, -6, -18, + -6, -3, -26, -40, -8, -11, + 17, -3, 10, -23, -24, -8, + -30, -8, -6, 18, 30, -6, + 24, -1, 3, -1, -35, 9, + -10, -6, -20, -2, -32, 15, + -48, 14, 19, -15, -10, -22, + -19, -26, -59, 3, -3, 39, + 4, 1, 16, 38, -25, 17, + 10, 57, 28, 5, 31, 19, + 2, 18, 16, -26, -6, 28, + -54, -12, -12, -12, -20, 1, + 21, 22, -22, -4, -11, 26, + -1, 0, -2, -8, 13, 35, + 30, -28, -10, -3, -15, -45, + -4, 3, -6, 23, 42, 2, + 29, -35, 45, 0, 2, 6, + -15, 16, -5, 0, -11, 4, + 22, -20, 36, 37, -14, 10, + 6, 5, 19, 35, -3, 44, + -22, -13, -22, 5, 15, 14, + -33, 9, -23, -17, 13, -9, + -17, 9, -25, -14, -17, 31, + 3, -4, -27, -16, 25, 1, + 16, -34, 6, -21, -15, 16, + -25, 3, 23, 17, -4, 14, + 8, -10, 31, 9, 21, 5, + 6, 14, 14, 20, -25, -3, + 12, 2, 37, -25, -14, -1, + -17, -19, -14, 0, 14, 18, + 24, -42, 22, -5, -12, -13, + -21, -1, -31, 25, -17, -38, + -10, -21, -18, 33, 19, 20, + -16, -7, -27, -9, -10, -11, + 17, 9, 10, -33, 23, -23, + 13, 17, -8, 2, -19, -9, + 18, -4, 31, 11, -21, -2, + 2, -2, -11, -15, 12, -20, + 0, 11, -3, -22, -6, 6, + 12, 13, 19, -1, 16, 21, + 11, 1, 7, 9, -31, 29, + 6, -12, -27, -41, -21, 16, + 23, 17, -16, -52, 12, 63, + -6, -37, 26, -16, 52, 28, + -32, -12, -4, 10, -46, 12, + -17, -5, 72, 10, 43, -9, + -27, 43, 14, 26, -39, -16, + 13, -3, -23, -4, 11, 9, + -2, -22, 8, 26, -5, 13, + -18, -9, -18, 5, 29, -35, + 3, 23, 21, 17, -18, -40, + 43, -38, 18, -3, -7, 28, + -1, 27, -15, -31, -30, 2, + 9, -18, -3, -21, -10, -13, + -26, 5, -6, 18, 32, 41, + 11, -1, -4, 14, 22, -39, + 2, -20, -17, 22, -8, 2, + 20, 32, -1, -9, 3, 1, + -34, -8, -20, 3, -18, 12, + 13, -10, -26, -45, 15, -32, + -12, 0, -38, -2, 0, -6, + 10, 1, -17, -1, 17, 15, + -7, -29, 9, 17, -10, -6, + -33, -8, -11, -4, 37, 11, + 28, 9, 0, 3, 18, -24, + -36, -8, -9, 38, 16, 47, + -19, -9, -22, 24, 22, -22, + 10, 40, 2, -10, 1, 3, + -17, 2, -22, -7, 33, -17, + -9, 18, 37, 6, 21, -23, + 17, -30, -54, -9, 31, 13, + -7, -23, 30, 2, 47, 21, + 28, -34, 3, 32, -40, -7, + 27, 8, 33, -28, -14, 48, + -21, -57, 38, -14, -40, 1, + -9, -21, 3, 24, 6, 19, + 10, 1, 9, 12, -15, 3, + 9, 21, -2, 8, 6, -51, + 10, 16, -25, 15, 13, 18, + -8, 20, -24, -19, 10, 11, + -17, -15, -14, 47, 9, 14, + 20, -24, -10, 17, -4, 7, + -8, 9, -19, 5, 6, 27, + 7, 36, 26, -22, -4, -30, + -19, -3, -30, 33, 7, -31, + 23, 7, -34, 23, 31, -20, + 8, 33, 31, 8, -1, -1, + -39, 19, -22, -50, -27, -23, + -13, 18, -8, -5, -1, 8, + 25, 14, 7, -29, 21, 0, + 28, 35, 26, 18, 7, -1, + -18, -25, 33, -23, -5, -28, + -37, 28, -1, -13, 5, -18, + -11, -8, 1, -18, -4, 1, + 2, -20, 8, -23, -21, 31, + 20, 12, -4, -5, -4, -10, + 9, -41, -12, 32, 30, -5, + -30, 1, -23, -11, 22, -21, + 30, -14, -29, -15, 23, 0, + -6, 7, -15, -18, 26, -3, + 5, -3, -2, 0, 26, 36, + -17, -6, 14, 0, 3, -19, + 1, 23, 20, 6, 15, -8, + -33, -15, -26, -14, 10, -23, + -25, 11, 0, -18, -4, -2, + -3, -11, 21, -40, 15, 19, + -10, 21, 12, -44, -21, 16, + 22, 8, -18, -13, -12, -8, + 0, -52, -4, -9, -20, -3, + 16, 21, -16, -35, -23, 4, + 11, -18, 10, 3, -26, -34, + -24, -33, -6, -28, -21, 57, + 0, 22, 9, -31, 8, -9, + -4, 24, 22, 22, 19, -10, + 17, 38, 43, 10, 27, 21, + 7, 8, 3, -57, -9, -36, + 3, -13, 3, 18, 34, 23, + -22, -31, -8, -3, 24, 28, + -48, -24, 25, -13, 2, 9, + 6, -22, 4, -46, -30, 9, + -13, -4, 9, -24, -2, -21, + -20, 1, -36, 0, -23, -21, + -37, -21, 3, 17, 4, -34, + 5, -36, -13, -4, -25, -18, + 20, -40, -2, -26, -9, -7, + -4, -34, -16, -26, 22, -12, + -17, -24, -40, -3, -26, 37, + -14, 23, -8, 0, -35, 2, + 11, 5, -7, -11, 54, 9, + -25, 26, -59, 0, -5, 40, + -13, -6, -12, 43, 11, 9, + -25, -16, -47, -28, 6, -3, + -27, -3, 6, -28, -47, -16, + -25, 9, 11, 43, -12, -6, + -13, 40, -5, 0, -59, 26, + -25, 9, 54, -11, -7, 5, + 11, 2, -35, 0, -8, 23, + -14, 37, -26, -3, -40, -24, + -17, -12, 22, -26, -16, -34, + -4, -7, -9, -26, -2, -40, + 20, -18, -25, -4, -13, -36, + 5, -34, 4, 17, 3, -21, + -37, -21, -23, 0, -36, 1, + -20, -21, -2, -24, 9, -4, + -13, 9, -30, -46, 4, -22, + 6, 9, 2, -13, 25, -24, + -48, 28, 24, -3, -8, -31, + -22, 23, 34, 18, 3, -13, + 3, -36, -9, -57, 3, 8, + 7, 21, 27, 10, 43, 38, + 17, -10, 19, 22, 22, 24, + -4, -9, 8, -31, 9, 22, + 0, 57, -21, -28, -6, -33, + -24, -34, -26, 3, 10, -18, + 11, 4, -23, -35, -16, 21, + 16, -3, -20, -9, -4, -52, + 0, -8, -12, -13, -18, 8, + 22, 16, -21, -44, 12, 21, + -10, 19, 15, -40, 21, -11, + -3, -2, -4, -18, 0, 11, + -25, -23, 10, -14, -26, -15, + -33, -8, 15, 6, 20, 23, + 1, -19, 3, 0, 14, -6, + -17, 36, 26, 0, -2, -3, + 5, -3, 26, -18, -15, 7, + -6, 0, 23, -15, -29, -14, + 30, -21, 22, -11, -23, 1, + -30, -5, 30, 32, -12, -41, + 9, -10, -4, -5, -4, 12, + 20, 31, -21, -23, 8, -20, + 2, 1, -4, -18, 1, -8, + -11, -18, 5, -13, -1, 28, + -37, -28, -5, -23, 33, -25, + -18, -1, 7, 18, 26, 35, + 28, 0, 21, -29, 7, 14, + 25, 8, -1, -5, -8, 18, + -13, -23, -27, -50, -22, 19, + -39, -1, -1, 8, 31, 33, + 8, -20, 31, 23, -34, 7, + 23, -31, 7, 33, -30, -3, + -19, -30, -4, -22, 26, 36, + 7, 27, 6, 5, -19, 9, + -8, 7, -4, 17, -10, -24, + 20, 14, 9, 47, -14, -15, + -17, 11, 10, -19, -24, 20, + -8, 18, 13, 15, -25, 16, + 10, -51, 6, 8, -2, 21, + 9, 3, -15, 12, 9, 1, + 10, 19, 6, 24, 3, -21, + -9, 1, -40, -14, 38, -57, + -21, 48, -14, -28, 33, 8, + 27, -7, -40, 32, 3, -34, + 28, 21, 47, 2, 30, -23, + -7, 13, 31, -9, -54, -30, + 17, -23, 21, 6, 37, 18, + -9, -17, 33, -7, -22, 2, + -17, 3, 1, -10, 2, 40, + 10, -22, 22, 24, -22, -9, + -19, 47, 16, 38, -9, -8, + -36, -24, 18, 3, 0, 9, + 28, 11, 37, -4, -11, -8, + -33, -6, -10, 17, 9, -29, + -7, 15, 17, -1, -17, 1, + 10, -6, 0, -2, -38, 0, + -12, -32, 15, -45, -26, -10, + 13, 12, -18, 3, -20, -8, + -34, 1, 3, -9, -1, 32, + 20, 2, -8, 22, -17, -20, + 2, -39, 22, 14, -4, -1, + 11, 41, 32, 18, -6, 5, + -26, -13, -10, -21, -3, -18, + 9, 2, -30, -31, -15, 27, + -1, 28, -7, -3, 18, -38, + 43, -40, -18, 17, 21, 23, + 3, -35, 29, 5, -18, -9, + -18, 13, -5, 26, 8, -22, + -2, 9, 11, -4, -23, -3, + 13, -16, -39, 26, 14, 43, + -27, -9, 43, 10, 72, -5, + -17, 12, -46, 10, -4, -12, + -32, 28, 52, -16, 26, -37, + -6, 63, 12, -52, -16, 17, + 23, 16, -21, -41, -27, -12, + 6, 29, -31, 9, 7, 1, + 11, 21, 16, -1, 19, 13, + 12, 6, -6, -22, -3, 11, + 0, -20, 12, -15, -11, -2, + 2, -2, -21, 11, 31, -4, + 18, -9, -19, 2, -8, 17, + 13, -23, 23, -33, 10, 9, + 17, -11, -10, -9, -27, -7, + -16, 20, 19, 33, -18, -21, + -10, -38, -17, 25, -31, -1, + -21, -13, -12, -5, 22, -42, + 24, 18, 14, 0, -14, -19, + -17, -1, -14, -25, 37, 2, + 12, -3, -25, 20, 14, 14, + 6, 5, 21, 9, 31, -10, + 8, 14, -4, 17, 23, 3, + -25, 16, -15, -21, 6, -34, + 16, 1, 25, -16, -27, -4, + 3, 31, -17, -14, -25, 9, + -17, -9, 13, -17, -23, 9, + -33, 14, 15, 5, -22, -13, + -22, 44, -3, 35, 19, 5, + 6, 10, -14, 37, 36, -20, + 22, 4, -11, 0, -5, 16, + -15, 6, 2, 0, 45, -35, + 29, 2, 42, 23, -6, 3, + -4, -45, -15, -3, -10, -28, + 30, 35, 13, -8, -2, 0, + -1, 26, -11, -4, -22, 22, + 21, 1, -20, -12, -12, -12, + -54, 28, -6, -26, 16, 18, + 2, 19, 31, 5, 28, 57, + 10, 17, -25, 38, 16, 1, + 4, 39, -3, 3, -59, -26, + -19, -22, -10, -15, 19, 14, + -48, 15, -32, -2, -20, -6, + -10, 9, -35, -1, 3, -1, + 24, -6, 30, 18, -6, -8, + -30, -8, -24, -23, 10, -3, + 17, -11, -8, -40, -26, -3, + -6, -18, -6, 10, 42, -13, + -9, 27, 3, -12, -5, 2, + -29, 4, 13, 29, -14, -8, + 9, -26, 4, 29, -25, -11, + 20, 29, -15, 25, 30, -25, + -20, -1, 2, -18, 56, -26, + -30, 6, 2, -9, -22, 7, + -15, 42, -23, 29, 0, 10, + 23, -12, -15, 9, 37, -1, + 15, 2, -1, -20, 18, 45, + -7, -18, -13, -19, -12, 2, + -6, 33, -28, -17, -11, 20, + -6, -15, 3, 23, 9, 11, + 8, 17, 14, 7, 22, -21, + -12, 10, -4, 11, -35, -19, + 24, 4, -22, 24, 7, -26, + -34, -4, -2, 22, 14, -29, + 1, 29, 24, -19, 24, -24, + 27, 39, -18, 14, -30, -22, + -13, -20, -11, -21, 4, -4, + 23, 9, -4, 14, 6, -2, + -29, 14, -2, 8, -20, 0, + -6, -1, 36, 16, 32, -5, + 22, -2, -4, 14, -20, 22, + 6, 17, 4, -16, 11, -22, + -17, -20, -9, 41, -66, 25, + -7, -2, 5, -1, 3, 20, + 21, 4, -38, 15, 19, -7, + -16, 8, 7, -1, -9, -13, + 1, 1, -17, -23, 0, 18, + -11, -9, 6, -3, -3, 1, + -9, -3, 16, -26, 32, -7, + -10, 21, -20, 12, 6, 20, + -26, 25, -17, -47, -8, -54, + 15, -21, -34, 4, -20, -2, + -2, -38, 4, 3, 9, -5, + -9, -5, -16, 12, -13, 11, + -4, 22, 28, -18, -57, 26, + -7, -7, -39, -1, -42, 20, + 21, -70, 20, -2, -9, 24, + 22, 1, 38, 6, 22, -7, + -14, 29, 31, -19, -7, 8, + -23, 38, -21, -18, -48, 5, + 23, -16, 2, 14, 11, 22, + -3, -10, 15, -14, -11, 12, + 17, -47, -38, -27, 31, 17, + 3, 7, 4, 21, 9, 9, + -9, 34, 7, -13, -24, 5, + -6, 63, 0, 22, 29, -14, + 14, 7, -12, 3, 4, -9, + -7, -3, -23, 19, -23, -26, + 18, -32, -5, 13, 10, -19, + -18, -28, -19, 31, 7, 9, + 13, 26, -8, 45, 0, 6, + -13, -7, -41, 2, 40, 20, + 8, 1, 13, 11, -8, 1, + 20, 32, 28, 13, -19, 7, + -26, -38, -11, 11, 8, -3, + 9, -4, -17, 13, 31, -29, + -32, 6, -20, 85, 15, -25, + -1, 27, 18, -13, -6, 8, + 9, 17, 5, 11, 1, -30, + 40, 14, -4, 10, -25, 26, + -7, 3, 29, 65, -8, 3, + 15, 1, -26, 33, 4, -3, + -29, 29, 19, 40, 2, -11, + 1, 39, 1, -34, 23, -22, + -25, -31, 18, -27, 16, 8, + -22, 3, 19, -15, 38, -27, + -22, 5, 4, -8, -32, -18, + 62, 1, -25, 46, -5, -21, + -31, -15, -29, 21, 11, 24, + -9, -16, 5, 0, 49, -10, + 12, 11, -14, 10, 19, -21, + 5, 7, -12, -17, 10, 23, + -31, -1, 26, 18, 11, 0, + -8, 1, 23, -34, 3, -47, + 11, -26, 7, -35, 1, 12, + 0, -6, -12, 20, -5, 31, + -2, -10, 0, -2, 22, 1, + 7, 40, -2, -15, 6, 4, + -24, -17, 4, -11, 14, -15, + 0, 17, -22, -16, -15, 28, + 2, -27, 42, 2, 10, -4, + -9, -38, -9, 5, -4, 14, + 39, 23, -8, 31, -52, -10, + 13, -3, 37, 9, -6, 7, + -21, -15, 40, -17, 15, -22, + -21, -21, -8, 13, -30, -1, + 22, -2, -1, -8, -21, 6, + 1, 18, -25, 22, 20, 6, + 0, -11, 8, 22, -17, 7, + -17, -22, -9, 31, -32, 7, + 24, 3, -9, -39, 10, -31, + 11, -10, 13, 9, -16, 22, + 11, 9, -4, 24, -16, -17, + -11, -28, -44, 8, -6, -2, + 32, 6, 15, -3, 2, -30, + 0, -17, 24, 40, -1, 6, + -6, 25, 11, -19, -12, -15, + -19, 6, 16, -22, -26, 18, + 0, 5, -15, -34, 8, -27, + 22, 18, 7, -13, 30, 13, + -4, 14, 35, -17, -25, 9, + 8, -4, 2, 39, -21, 21, + -38, 3, 62, 39, -24, 34, + -34, -3, 15, -15, 20, 12, + -19, -27, -31, 6, 21, 9, + -20, 26, -23, 7, -34, 40, + -4, 16, 13, 70, 2, 29, + 13, -25, 7, -37, -3, 8, + -14, 44, -31, 28, -52, -9, + -19, 7, -3, 20, -19, 6, + -24, -28, -155, 57131, -1421192, 11753785, + -47262139, 107836784, -149772281, 129763784, -69391859, 21781536, + -3580001, 237345, -2784, -5, -8, -20, + 51, 31, 21, -7, 4, 31, + -23, -21, 14, -1, -4, -6, + 20, -27, -11, -8, -24, -5, + -13, -26, 42, 7, -5, 43, + -26, 0, -56, 18, -15, -21, + 7, 2, -8, 1, -20, -14, + -25, -29, -6, -3, -29, -8, + 23, 24, -13, 30, -16, -29, + -14, 0, -14, 24, -55, -1, +}; + +static const int32_t ifft_in_imag_3072_q31[3072] = { + 0, 10, -20, -15, 21, -8, + 63, -15, -9, -25, 3, -7, + -21, -6, -5, -35, 2, 43, + -21, 1, -6, 0, 13, 8, + -6, -7, 1, -1, 7, 3, + -10, 68, 17, 12, -28, -34, + 26, 4, -5, -17, -4, 11, + -21, -2, -21, -7, 13, -33, + -11, 10, 19, 6, -5, 16, + -7, 50, -5, 33, -4068, 340975, + -5154185, 31427845, -100341977, 188051721, -217523237, 156961250, + -68943059, 17183334, -2082308, 83903, -220, 19, + -10, -17, 24, 8, 30, -1, + -16, -1, -1, 7, -30, -32, + 4, 12, -10, 52, 41, 0, + -23, -1, 33, -13, -27, 33, + -23, -27, 2, -53, -7, 17, + -5, 54, 6, -1, 7, 11, + -8, 25, -10, 22, -9, 25, + 0, -26, -27, 3, -5, -19, + -24, -7, 29, -1, 15, 8, + 27, 33, 25, 16, -57, -14, + 13, 11, -22, 24, -22, 10, + -17, 8, 10, 43, 19, 15, + -19, -12, -13, -26, 2, 11, + 29, 29, -29, 24, 20, -31, + 16, 4, 5, -21, -16, -21, + -22, 5, -5, 22, -15, -2, + 29, -21, -3, -5, 9, 6, + 4, 6, 7, -3, -5, -27, + 31, 6, -2, 8, -36, -3, + 43, 2, -8, -16, -23, -44, + -17, -8, 33, -37, -8, 13, + -24, 3, -12, 35, -26, -13, + -22, -2, -5, 5, -23, 5, + -20, 2, -20, 21, 42, 17, + -19, 2, 31, -31, 10, 23, + 4, 20, -11, 9, 15, -5, + 13, -20, -45, 34, -6, -10, + -25, 5, -17, -14, 25, -27, + 9, 5, -7, 7, -24, 10, + -5, -10, -8, 3, -34, -43, + -10, 8, 23, 11, 36, 18, + -26, -11, -1, -3, -19, -4, + -31, -31, -15, 12, 15, 44, + 39, -13, 20, 45, -2, -4, + 7, 5, -7, 32, 9, -4, + -4, -1, -13, 22, 10, -35, + -1, 2, 31, 16, 36, 37, + -21, -14, -42, -34, 32, -26, + 9, 25, -9, 8, -18, -2, + 2, 13, 38, 24, -9, -17, + -4, -1, -10, 2, -1, 45, + 28, -25, 18, 10, -46, -19, + 30, 1, -46, -13, 10, -7, + -27, 22, 2, 23, -24, -13, + -22, -15, -30, 27, 16, 3, + -55, 29, 24, 5, 29, -3, + 1, 15, -18, -6, 22, 11, + 19, -8, 25, -12, 15, 14, + 31, -46, -10, 18, -38, -10, + 22, 16, -2, 8, 4, 37, + 22, 30, 42, 48, -30, -5, + 21, -15, -13, -13, -31, 27, + -4, -26, 2, -15, 33, -17, + -39, 7, -20, -1, 14, -19, + 21, 4, 22, -20, -18, 23, + -2, -9, 38, -23, 8, 35, + -9, -7, 3, 7, -5, -5, + 46, 20, 35, 21, -28, 17, + -33, 19, 22, -23, 30, 14, + 34, -12, -25, -19, -14, 21, + -20, 22, 4, 8, -9, 20, + 24, -36, 0, -24, -18, -4, + 6, 11, -4, -26, -22, -15, + -36, 16, -32, 23, -3, 14, + -51, -36, -5, 14, 8, 10, + 41, -12, -20, 25, 1, -24, + 16, 12, 43, 14, -17, 4, + -60, -28, -4, -41, 44, 6, + 1, -4, 6, -1, -1, -14, + -9, 3, -14, -38, 0, 14, + 1, 35, -9, -14, 22, 39, + -21, -29, 15, 32, 4, 23, + 19, 20, 1, -40, -29, 31, + 6, -33, -14, -15, 11, -8, + -13, -36, -35, -8, -7, 2, + 21, -17, -19, -2, 38, 19, + -5, 4, 15, -21, 51, 52, + 18, 1, 45, -7, -11, -22, + -7, 1, -49, -6, -12, 24, + -7, -46, -63, 1, -13, -15, + -25, 3, 27, 10, 9, -33, + -6, -36, 6, 1, -25, -7, + 13, -5, -4, 2, -5, 3, + -33, -36, -2, -26, -27, -16, + -6, -10, 37, -29, 18, 3, + -18, -4, -7, -1, -7, -4, + 3, 46, -12, -30, -7, -12, + -6, 5, -25, -9, 1, 12, + 31, 17, -7, 20, -36, 10, + 0, 13, 16, -16, 10, 17, + 23, -14, 10, -4, -17, -1, + -8, -8, -25, 24, 3, 7, + -16, 59, 2, 28, 25, -1, + 14, -3, -30, -27, -17, 25, + 46, -14, -22, 21, 18, -9, + 13, 23, -5, -23, -18, -5, + -35, 7, 12, -18, -17, 8, + 3, -47, 1, -16, -6, 38, + 38, 20, -3, 41, 71, 0, + 3, 31, 29, -9, 5, -20, + 23, 19, -30, 14, 30, 45, + 14, -29, -6, -9, -12, 14, + -11, 26, -6, -20, -26, 20, + -2, -5, 30, 1, 3, -2, + -36, 13, 5, -7, 30, 18, + -8, -16, 9, 24, 4, 8, + -18, -15, -7, 6, -44, 2, + 9, -18, -21, 3, 4, 1, + -13, -12, 18, -5, 7, -11, + -17, -26, 10, 12, -7, 24, + 7, -12, 39, 21, -16, 37, + -10, -12, -36, -9, -9, 17, + -29, -37, 6, -3, 28, 19, + -37, 17, -21, 7, 4, -5, + 22, 10, -2, -13, 26, -5, + -5, 6, -22, -2, 19, -5, + 15, 15, -2, 9, -15, 11, + -18, -5, -24, 21, 40, -33, + -9, -3, 40, -14, -15, 32, + 31, 13, -23, -17, 32, 10, + 14, 7, 18, -30, -13, -27, + -11, -27, -52, -15, -18, 15, + 42, -7, 17, 10, -1, -30, + -13, -21, 7, -3, 37, 19, + 8, -22, -6, -28, -7, 43, + 9, -24, -27, -33, -7, 27, + -21, 21, 28, -20, -44, 14, + 29, 6, -6, -4, 2, -18, + 13, -5, 14, 21, 15, -2, + 57, -2, 25, -4, 28, 20, + -10, -9, -29, 16, -43, 27, + 12, -9, -1, -21, 47, -45, + -15, -26, -1, 18, 22, -20, + 3, -22, 19, -55, 5, 19, + -4, -15, -11, 0, -14, -9, + -47, 15, 21, -17, -3, 3, + 6, 43, 14, 9, 10, -38, + -1, -22, 13, 6, 11, -17, + 52, -1, -7, 4, 12, -22, + 1, -13, -4, -30, -17, 7, + 6, 39, -5, -34, -15, 21, + -15, -10, -15, 6, -24, -23, + 0, -18, -23, -22, -44, 1, + -16, -3, 22, 3, -14, 4, + 18, -1, -6, 10, 3, 6, + 19, -1, -4, 11, 1, -9, + -3, 6, 22, -11, 6, 5, + -6, -9, -4, 0, -7, -43, + -29, 1, 2, 28, 9, 34, + 19, -2, 1, 7, -9, 16, + 9, 5, -2, 6, -10, 25, + -3, -28, -46, -8, 10, -10, + 0, 36, 1, 10, -2, 14, + 12, 28, -6, 22, -1, -2, + -18, -15, 15, 7, -2, -4, + 28, 17, -6, 5, 8, 22, + -12, -52, 8, 33, 7, 8, + -26, -19, -11, 8, 1, 18, + 12, -38, 25, 9, 22, -6, + 16, 9, 34, -33, 27, -22, + -6, -24, 0, -28, -5, 25, + -6, 36, -4, -38, 6, -14, + 1, -21, -17, 27, -73, -21, + 19, 20, 13, -13, -28, 21, + 2, 34, -2, -33, -8, 28, + 5, 18, 3, 16, -35, 7, + 14, 1, -20, -11, 33, -16, + 20, 15, -21, -21, 10, 9, + 3, -27, -10, -1, -2, 22, + 6, 34, -34, -25, 7, 37, + 8, -33, -16, 5, 5, 5, + 17, 5, -5, 3, 37, -18, + -9, 10, -20, 6, -5, 56, + 26, -11, -17, 5, 10, 7, + 5, -23, 51, 15, -24, -15, + -20, -24, -16, 23, -22, -5, + -18, 30, 23, -35, 2, 23, + 12, 20, -9, -3, 25, -4, + 0, 2, 47, -24, -10, 12, + 14, 22, -7, 18, -14, 10, + 20, -6, 9, 20, 0, -2, + -32, 22, -17, -12, 26, -39, + -2, -16, 29, 2, 16, 13, + 8, -14, 3, -15, 3, 3, + 2, -26, -46, 9, 14, -16, + -29, 36, 1, 49, 25, -45, + 23, 7, -1, 13, -3, 24, + -15, -23, -9, -13, -10, -7, + 28, -14, -14, 29, 1, -7, + -10, 5, 17, 4, 24, 27, + -4, 31, 8, 10, 22, -18, + 27, -12, -47, 24, 3, 8, + 8, -12, -7, -10, -50, -38, + 28, 11, 18, -6, 38, 22, + -1, 15, -15, 8, -27, 27, + -50, 10, -15, 20, 10, 1, + -15, -12, -13, 1, 6, -22, + 17, -3, 23, 13, -17, -12, + 20, -27, -23, -6, 0, -12, + 15, -23, 18, -3, -2, -37, + -32, 28, 20, 0, -33, 10, + -25, 3, -16, -6, 5, 5, + -3, -28, 5, 33, -11, -18, + 31, 34, -2, -2, -53, 15, + 12, -3, 9, 12, 11, 30, + -18, 25, 34, 3, 43, 15, + -18, 43, -5, -10, 2, -6, + 45, 19, 18, -15, -9, 26, + 3, -21, -25, -7, 17, 4, + -7, -27, 11, 5, 18, -40, + 28, 1, 0, -7, 38, -26, + 9, 15, 12, 3, 9, 15, + -34, 51, -1, -30, 4, 45, + 13, 9, 13, -15, 17, 25, + 22, -21, 30, 27, -52, -41, + 40, -37, -8, -44, 45, 26, + 1, 20, -5, 4, 13, 30, + 19, -7, 4, -6, -10, -8, + -19, -30, 4, -35, 4, 10, + -2, -6, 1, 50, -3, 2, + 14, 0, 10, 24, 3, 36, + -13, 4, -21, -15, -4, -9, + 18, -26, -4, 13, 11, -16, + 17, 1, -15, -4, 14, -14, + 4, -23, -2, 3, 12, -8, + 32, 10, -4, 6, 2, 11, + -31, 20, 7, -37, 7, 23, + -18, -30, -31, 20, -1, 10, + -18, 17, 31, -10, -12, -9, + -3, -16, -44, -16, -10, -6, + -21, -10, -13, 7, 6, -1, + -18, 10, -9, 23, -14, -31, + -21, -8, 32, 11, 35, 11, + -18, 1, -8, -29, 7, 6, + -16, -4, 9, 10, -4, 0, + -12, -7, 13, 9, -23, 7, + -18, -16, 23, 46, -39, 17, + -9, -18, 9, 11, 18, 7, + -18, 1, -20, 8, -1, -7, + 21, -2, 13, -23, -12, 8, + -28, 17, -12, -36, 33, 10, + 34, -8, -2, 44, -2, 11, + 19, -17, -11, 55, 26, 4, + -14, -41, 5, 3, 49, -44, + 0, 44, -49, -3, -5, 41, + 14, -4, -26, -55, 11, 17, + -19, -11, 2, -44, 2, 8, + -34, -10, -33, 36, 12, -17, + 28, -8, 12, 23, -13, 2, + -21, 7, 1, -8, 20, -1, + 18, -7, -18, -11, -9, 18, + 9, -17, 39, -46, -23, 16, + 18, -7, 23, -9, -13, 7, + 12, 0, 4, -10, -9, 4, + 16, -6, -7, 29, 8, -1, + 18, -11, -35, -11, -32, 8, + 21, 31, 14, -23, 9, -10, + 18, 1, -6, -7, 13, 10, + 21, 6, 10, 16, 44, 16, + 3, 9, 12, 10, -31, -17, + 18, -10, 1, -20, 31, 30, + 18, -23, -7, 37, -7, -20, + 31, -11, -2, -6, 4, -10, + -32, 8, -12, -3, 2, 23, + -4, 14, -14, 4, 15, -1, + -17, 16, -11, -13, 4, 26, + -18, 9, 4, 15, 21, -4, + 13, -36, -3, -24, -10, 0, + -14, -2, 3, -50, -1, 6, + 2, -10, -4, 35, -4, 30, + 19, 8, 10, 6, -4, 7, + -19, -30, -13, -4, 5, -20, + -1, -26, -45, 44, 8, 37, + -40, 41, 52, -27, -30, 21, + -22, -25, -17, 15, -13, -9, + -13, -45, -4, 30, 1, -51, + 34, -15, -9, -3, -12, -15, + -9, 26, -38, 7, 0, -1, + -28, 40, -18, -5, -11, 27, + 7, -4, -17, 7, 25, 21, + -3, -26, 9, 15, -18, -19, + -45, 6, -2, 10, 5, -43, + 18, -15, -43, -3, -34, -25, + 18, -30, -11, -12, -9, 3, + -12, -15, 53, 2, 2, -34, + -31, 18, 11, -33, -5, 28, + 3, -5, -5, 6, 16, -3, + 25, -10, 33, 0, -20, -28, + 32, 37, 2, 3, -18, 23, + -15, 12, 0, 6, 23, 27, + -20, 12, 17, -13, -23, 3, + -17, 22, -6, -1, 13, 12, + 15, -1, -10, -20, 15, -10, + 50, -27, 27, -8, 15, -15, + 1, -22, -38, 6, -18, -11, + -28, 38, 50, 10, 7, 12, + -8, -8, -3, -24, 47, 12, + -27, 18, -22, -10, -8, -31, + 4, -27, -24, -4, -17, -5, + 10, 7, -1, -29, 14, 14, + -28, 7, 10, 13, 9, 23, + 15, -24, 3, -13, 1, -7, + -23, 45, -25, -49, -1, -36, + 29, 16, -14, -9, 46, 26, + -2, -3, -3, 15, -3, 14, + -8, -13, -16, -2, -29, 16, + 2, 39, -26, 12, 17, -22, + 32, 2, 0, -20, -9, 6, + -20, -10, 14, -18, 7, -22, + -14, -12, 10, 24, -47, -2, + 0, 4, -25, 3, 9, -20, + -12, -23, -2, 35, -23, -30, + 18, 5, 22, -23, 16, 24, + 20, 15, 24, -15, -51, 23, + -5, -7, -10, -5, 17, 11, + -26, -56, 5, -6, 20, -10, + 9, 18, -37, -3, 5, -5, + -17, -5, -5, -5, 16, 33, + -8, -37, -7, 25, 34, -34, + -6, -22, 2, 1, 10, 27, + -3, -9, -10, 21, 21, -15, + -20, 16, -33, 11, 20, -1, + -14, -7, 35, -16, -3, -18, + -5, -28, 8, 33, 2, -34, + -2, -21, 28, 13, -13, -20, + -19, 21, 73, -27, 17, 21, + -1, 14, -6, 38, 4, -36, + 6, -25, 5, 28, 0, 24, + 6, 22, -27, 33, -34, -9, + -16, 6, -22, -9, -25, 38, + -12, -18, -1, -8, 11, 19, + 26, -8, -7, -33, -8, 52, + 12, -22, -8, -5, 6, -17, + -28, 4, 2, -7, -15, 15, + 18, 2, 1, -22, 6, -28, + -12, -14, 2, -10, -1, -36, + 0, 10, -10, 8, 46, 28, + 3, -25, 10, -6, 2, -5, + -9, -16, 9, -7, -1, 2, + -19, -34, -9, -28, -2, -1, + 29, 43, 7, 0, 4, 9, + 6, -5, -6, 11, -22, -6, + 3, 9, -1, -11, 4, 1, + -19, -6, -3, -10, 6, 1, + -18, -4, 14, -3, -22, 3, + 16, -1, 44, 22, 23, 18, + 0, 23, 24, -6, 15, 10, + 15, -21, 15, 34, 5, -39, + -6, -7, 17, 30, 4, 13, + -1, 22, -12, -4, 7, 1, + -52, 17, -11, -6, -13, 22, + 1, 38, -10, -9, -14, -43, + -6, -3, 3, 17, -21, -15, + 47, 9, 14, 0, 11, 15, + 4, -19, -5, 55, -19, 22, + -3, 20, -22, -18, 1, 26, + 15, 45, -47, 21, 1, 9, + -12, -27, 43, -16, 29, 9, + 10, -20, -28, 4, -25, 2, + -57, 2, -15, -21, -14, 5, + -13, 18, -2, 4, 6, -6, + -29, -14, 44, 20, -28, -21, + 21, -27, 7, 33, 27, 24, + -9, -43, 7, 28, 6, 22, + -8, -19, -37, 3, -7, 21, + 13, 30, 1, -10, -17, 7, + -42, -15, 18, 15, 52, 27, + 11, 27, 13, 30, -18, -7, + -14, -10, -32, 17, 23, -13, + -31, -32, 15, 14, -40, 3, + 9, 33, -40, -21, 24, 5, + 18, -11, 15, -9, 2, -15, + -15, 5, -19, 2, 22, -6, + 5, 5, -26, 13, 2, -10, + -22, 5, -4, -7, 21, -17, + 37, -19, -28, 3, -6, 37, + 29, -17, 9, 9, 36, 12, + 10, -37, 16, -21, -39, 12, + -7, -24, 7, -12, -10, 26, + 17, 11, -7, 5, -18, 12, + 13, -1, -4, -3, 21, 18, + -9, -2, 44, -6, 7, 15, + 18, -8, -4, -24, -9, 16, + 8, -18, -30, 7, -5, -13, + 36, 2, -3, -1, -30, 5, + 2, -20, 26, 20, 6, -26, + 11, -14, 12, 9, 6, 29, + -14, -45, -30, -14, 30, -19, + -23, 20, -5, 9, -29, -31, + -3, 0, -71, -41, 3, -20, + -38, -38, 6, 16, -1, 47, + -3, -8, 17, 18, -12, -7, + 35, 5, 18, 23, 5, -23, + -13, 9, -18, -21, 22, 14, + -46, -25, 17, 27, 30, 3, + -14, 1, -25, -28, -2, -59, + 16, -7, -3, -24, 25, 8, + 8, 1, 17, 4, -10, 14, + -23, -17, -10, 16, -16, -13, + 0, -10, 36, -20, 7, -17, + -31, -12, -1, 9, 25, -5, + 6, 12, 7, 30, 12, -46, + -3, 4, 7, 1, 7, 4, + 18, -3, -18, 29, -37, 10, + 6, 16, 27, 26, 2, 36, + 33, -3, 5, -2, 4, 5, + -13, 7, 25, -1, -6, 36, + 6, 33, -9, -10, -27, -3, + 25, 15, 13, -1, 63, 46, + 7, -24, 12, 6, 49, -1, + 7, 22, 11, 7, -45, -1, + -18, -52, -51, 21, -15, -4, + 5, -19, -38, 2, 19, 17, + -21, -2, 7, 8, 35, 36, + 13, 8, -11, 15, 14, 33, + -6, -31, 29, 40, -1, -20, + -19, -23, -4, -32, -15, 29, + 21, -39, -22, 14, 9, -35, + -1, -14, 0, 38, 14, -3, + 9, 14, 1, 1, -6, 4, + -1, -6, -44, 41, 4, 28, + 60, -4, 17, -14, -43, -12, + -16, 24, -1, -25, 20, 12, + -41, -10, -8, -14, 5, 36, + 51, -14, 3, -23, 32, -16, + 36, 15, 22, 26, 4, -11, + -6, 4, 18, 24, 0, 36, + -24, -20, 9, -8, -4, -22, + 20, -21, 14, 19, 25, 12, + -34, -14, -30, 23, -22, -19, + 33, -17, 28, -21, -35, -20, + -46, 5, 5, -7, -3, 7, + 9, -35, -8, 23, -38, 9, + 2, -23, 18, 20, -22, -4, + -21, 19, -14, 1, 20, -7, + 39, 17, -33, 15, -2, 26, + 4, -27, 31, 13, 13, 15, + -21, 5, 30, -48, -42, -30, + -22, -37, -4, -8, 2, -16, + -22, 10, 38, -18, 10, 46, + -31, -14, -15, 12, -25, 8, + -19, -11, -22, 6, 18, -15, + -1, 3, -29, -5, -24, -29, + 55, -3, -16, -27, 30, 15, + 22, 13, 24, -23, -2, -22, + 27, 7, -10, 13, 46, -1, + -30, 19, 46, -10, -18, 25, + -28, -45, 1, -2, 10, 1, + 4, 17, 9, -24, -38, -13, + -2, 2, 18, -8, 9, -25, + -9, 26, -32, 34, 42, 14, + 21, -37, -36, -16, -31, -2, + 1, 35, -10, -22, 13, 1, + 4, 4, -9, -32, 7, -5, + -7, 4, 2, -45, -20, 13, + -39, -44, -15, -12, 15, 31, + 31, 4, 19, 3, 1, 11, + 26, -18, -36, -11, -23, -8, + 10, 43, 34, -3, 8, 10, + 5, -10, 24, -7, 7, -5, + -9, 27, -25, 14, 17, -5, + 25, 10, 6, -34, 45, 20, + -13, 5, -15, -9, 11, -20, + -4, -23, -10, 31, -31, -2, + 19, -17, -42, -21, 20, -2, + 20, -5, 23, -5, 5, 2, + 22, 13, 26, -35, 12, -3, + 24, -13, 8, 37, -33, 8, + 17, 44, 23, 16, 8, -2, + -43, 3, 36, -8, 2, -6, + -31, 27, 5, 3, -7, -6, + -4, -6, -9, 5, 3, 21, + -29, 2, 15, -22, 5, -5, + 22, 21, 16, 21, -5, -4, + -16, 31, -20, -24, 29, -29, + -29, -11, -2, 26, 13, 12, + 19, -15, -19, -43, -10, -8, + 17, -10, 22, -24, 22, -11, + -13, 14, 57, -16, -25, -33, + -27, -8, -15, 1, -29, 7, + 24, 19, 5, -3, 27, 26, + 0, -25, 9, -22, 10, -25, + 8, -11, -7, 1, -6, -54, + 5, -17, 7, 53, -2, 27, + 23, -33, 27, 13, -33, 1, + 23, 0, -41, -52, 10, -12, + -4, 32, 30, -7, 1, 1, + 16, 1, -30, -8, -24, 17, + 10, -19, 220, -83903, 2082308, -17183334, + 68943059, -156961250, 217523237, -188051721, 100341977, -31427845, + 5154185, -340975, 4068, -33, 5, -50, + 7, -16, 5, -6, -19, -10, + 11, 33, -13, 7, 21, 2, + 21, -11, 4, 17, 5, -4, + -26, 34, 28, -12, -17, -68, + 10, -3, -7, 1, -1, 7, + 6, -8, -13, 0, 6, -1, + 21, -43, -2, 35, 5, 6, + 21, 7, -3, 25, 9, 15, + -63, 8, -21, 15, 20, -10, +}; + +static const int32_t ifft_ref_real_3072_q31[3072] = { + -1954, 1267, -1428, -189, -2328, -332, + -2139, 2088, 1120, -504, -2966, -2008, + -3174, 846, -914, 1141, -2101, -1347, + 3027, -1403, -1333, 362, 1668, -927, + 1181, -1244, -225, -358, 228, -2786, + 2981, -1883, 1268, -3378, 837, -534, + -1694, -1442, -1609, 233, 657, 23, + -1344, 662, -1927, -982, -3378, -381, + -779, 844, 2776, 2991, -1622, -1119, + 3870, 265, -548, 2619, 4851, -163, + 1724, 2204, 750, 902, 2561, 4782, + 3436, 2236, 3459, 607, -2115, 1150, + 684, 206, -433, -699, -4322, -665, + -1792, -1032, -2476, -4106, -4595, -7403, + -5622, -4960, -3025, -6094, -4879, -5786, + -6701, -500, -3185, -2761, -3410, -1888, + 2902, 3236, 1579, 1072, 6289, 5865, + 3737, 7878, 10582, 11262, 5716, 8054, + 10346, 11274, 12870, 8232, 10221, 8739, + 9892, 9425, 8387, 2936, 1194, 3767, + 3503, -909, -5905, -5029, -9175, -10882, + -13511, -12505, -18920, -17241, -21785, -18975, + -18165, -21109, -20486, -23023, -18012, -19889, + -16786, -16232, -16213, -12552, -11375, -5925, + -3013, -68, 6753, 11006, 10410, 17275, + 18657, 26177, 27511, 30865, 35720, 36178, + 40779, 42618, 39224, 37957, 35824, 38634, + 33522, 32862, 26097, 23825, 18366, 10697, + 2542, -3672, -8849, -17950, -25991, -35087, + -41498, -47572, -51102, -58015, -62956, -68385, + -70399, -70984, -75068, -68763, -72106, -66894, + -60619, -53553, -47109, -36855, -27916, -17365, + -9085, 4803, 17617, 31120, 43881, 55889, + 67189, 80156, 92141, 98698, 106521, 111873, + 119040, 120646, 121770, 119358, 115558, 112068, + 103408, 89951, 80567, 66268, 48447, 35386, + 11202, -5637, -31755, -52096, -69437, -90322, + -113541, -131335, -149125, -165772, -176375, -189568, + -193607, -198890, -199959, -201103, -193177, -183881, + -169659, -150640, -131600, -112287, -80475, -51938, + -22370, 9892, 41497, 76822, 111071, 143854, + 174132, 205505, 236130, 261930, 279611, 299838, + 309539, 319576, 321418, 317950, 307013, 292425, + 272196, 248900, 217268, 174794, 134153, 89526, + 39276, -11100, -64816, -117792, -169261, -224363, + -272702, -320621, -363995, -405013, -436618, -461801, + -484416, -498480, -498357, -493096, -476616, -455593, + -423250, -379896, -334722, -274426, -209798, -142911, + -68726, 10645, 91081, 174972, 259533, 339980, + 415872, 486041, 556745, 615719, 664094, 704463, + 734385, 750620, 754842, 747862, 725129, 692003, + 643234, 579508, 509962, 422076, 326650, 221229, + 109587, -7844, -129406, -252356, -374193, -495182, + -610853, -720845, -820495, -906599, -985383, -1044324, + -1087653, -1116727, -1119971, -1110995, -1079312, -1030261, + -955116, -868440, -755018, -634629, -491612, -340000, + -174008, -2545, 175459, 357679, 534472, 711584, + 880611, 1044734, 1187234, 1319178, 1429981, 1514941, + 1579514, 1621514, 1632752, 1615925, 1570986, 1497739, + 1396079, 1264505, 1111550, 930262, 727987, 506360, + 270114, 20615, -236580, -496428, -752595, -1006049, + -1248329, -1478414, -1689987, -1875964, -2034697, -2162770, + -2260013, -2312597, -2336506, -2314000, -2246916, -2147191, + -1999537, -1819161, -1598211, -1339436, -1053219, -741591, + -404819, -52105, 309008, 673402, 1040004, 1399854, + 1743725, 2065359, 2364137, 2627629, 2852233, 3037607, + 3171927, 3252277, 3278896, 3252821, 3166834, 3019401, + 2821154, 2565178, 2259733, 1902289, 1505911, 1071868, + 604387, 114568, -390538, -901979, -1414555, -1914667, + -2392421, -2844993, -3257702, -3627354, -3937513, -4197246, + -4382927, -4499670, -4541377, -4505222, -4388437, -4193254, + -3917142, -3572652, -3149370, -2664511, -2114061, -1520182, + -878438, -206493, 488632, 1187065, 1887697, 2573079, + 3234344, 3854568, 4423382, 4930050, 5363304, 5713011, + 5974276, 6138366, 6197414, 6153614, 6000228, 5736857, + 5367596, 4895708, 4327978, 3670697, 2930826, 2121844, + 1253041, 345643, -591645, -1542721, -2491418, -3421573, + -4314585, -5153975, -5923671, -6613787, -7199081, -7676067, + -8032673, -8261748, -8344694, -8289718, -8091735, -7743502, + -7254200, -6625856, -5868940, -4992277, -4003982, -2924878, + -1768018, -551110, 699523, 1970706, 3241390, 4481897, + 5675977, 6800856, 7836039, 8754662, 9546004, 10185660, + 10671856, 10976049, 11105194, 11035120, 10778861, 10326591, + 9683699, 8861631, 7867395, 6705779, 5405603, 3980232, + 2454384, 850530, -805109, -2486513, -4160748, -5805891, + -7382307, -8869688, -10233575, -11456331, -12505369, -13360134, + -14001774, -14417847, -14592276, -14519772, -14192650, -13609416, + -12782143, -11705217, -10409849, -8901823, -7209623, -5352473, + -3361810, -1266846, 895532, 3091918, 5277170, 7420525, + 9489624, 11432011, 13218921, 14821879, 16198902, 17320553, + 18176905, 18728063, 18968219, 18889211, 18474356, 17736672, + 16676488, 15301851, 13630777, 11691303, 9503862, 7109981, + 4543576, 1837027, -952943, -3787629, -6616674, -9389765, + -12060838, -14575923, -16896520, -18966998, -20757833, -22225876, + -23339580, -24064965, -24399452, -24313960, -23801953, -22874513, + -21529058, -19786854, -17661695, -15187331, -12403054, -9343646, + -6061675, -2608238, 960215, 4587200, 8203769, 11754426, + 15171453, 18398050, 21370217, 24031857, 26331810, 28224976, + 29662244, 30620056, 31063943, 30981748, 30362653, 29208928, + 27521429, 25329400, 22653382, 19531351, 16013837, 12153017, + 7998716, 3631447, -887872, -5478882, -10065002, -14563158, + -18898704, -22992346, -26766793, -30153622, -33084231, -35497471, + -37346046, -38578296, -39177363, -39107071, -38357663, -36931725, + -34843569, -32109203, -28776745, -24879474, -20480119, -15636363, + -10440654, -4962221, 700614, 6457439, 12213225, 17863443, + 23312919, 28460670, 33212090, 37476766, 41174535, 44229347, + 46576727, 48162205, 48947682, 48902130, 48012213, 46278804, + 43713794, 40343588, 36215821, 31390803, 25937800, 19941472, + 13486924, 6681309, -359302, -7516992, -14675702, -21708040, + -28497166, -34910721, -40834521, -46165672, -50790519, -54624928, + -57581677, -59595573, -60621295, -60618413, -59571237, -57474927, + -54349703, -50239530, -45184393, -39261870, -32559111, -25183391, + -17240783, -8864180, -195070, 8633884, 17462285, 26142836, + 34521640, 42450999, 49782997, 56376985, 62114562, 66884038, + 70577659, 73119273, 74442582, 74504938, 73280556, 70778132, + 67008877, 62027743, 55891005, 48684209, 40526777, 31524482, + 21837075, 11608676, 1013426, -9776897, -20582082, -31205608, + -41468126, -51178912, -60175566, -68283677, -75344704, -81222512, + -85802753, -88973444, -90664439, -90820751, -89418368, -86452620, + -81948797, -75958944, -68566242, -59877640, -50011282, -39132078, + -27402568, -15013504, -2168131, 10918713, 24020964, 36927546, + 49396361, 61209585, 72158752, 82038947, 90660079, 97855090, + 103473914, 107407932, 109551924, 109843422, 108249115, 104763010, + 99421497, 92289068, 83455070, 73050647, 61227870, 48169481, + 34081773, 19187156, 3739342, -12004598, -27791472, -43333230, + -58365766, -72626836, -85851549, -97795818, -108239741, -116981970, + -123840767, -128671350, -131359123, -131835146, -130042269, -125987174, + -119707501, -111272601, -100798435, -88436623, -74369612, -58823550, + -42030940, -24264150, -5826716, 12986473, 31848307, 50441973, + 68433889, 85512134, 101368634, 115713840, 128269407, 138806740, + 147108818, 153002353, 156352203, 157056990, 155072795, 150393409, + 143062822, 133169262, 120845178, 106267660, 89657885, 71273294, + 51399725, 30366288, 8514011, -13792699, -36174735, -58248196, + -79627543, -99936507, -118812766, -135906620, -150905421, -163518325, + -173495056, -180624235, -184755195, -185764212, -183594689, -178240626, + -169750794, -158228079, -143834201, -126764583, -107293151, -85713607, + -62363318, -37632655, -11918011, 14346364, 40717861, 66742307, + 91968909, 115955469, 138267475, 158501540, 176282366, 191273980, + 203176778, 211748630, 216793410, 218187466, 215847622, 209772219, + 200013871, 186692507, 169996463, 150155667, 127480051, 102325892, + 75082013, 46198998, 16151019, -14561432, -45418844, -75894680, + -105459536, -133586607, -159787579, -183572791, -204511701, -222205628, + -236312691, -246538905, -252660476, -254524141, -252042329, -245203169, + -234069735, -218776002, -199541362, -176642414, -150419791, -121291048, + -89722588, -56220440, -21344396, 14334015, 50206743, 85657746, + 120072210, 152844393, 183400551, 211180477, 235674009, 256422421, + 273023557, 285141522, 292508799, 294952686, 292362193, 284725036, + 272111181, 254677613, 232669346, 206404757, 176282500, 142783969, + 106437823, 67830506, 27604415, -13569950, -54991741, -95959498, + -135761919, -173705841, -209109551, -241337116, -269805490, -293980085, + -313391229, -327649859, -336454096, -339589981, -336941047, -328484687, + -314290618, -294554567, -269534232, -239604639, -205232447, -166945906, + -125368449, -81167635, -35075166, 12139805, 59675747, 106722917, + 152463819, 196110460, 236875290, 274037087, 306914105, 334892098, + 357442746, 374110440, 384551660, 388518382, 385864545, 376568060, + 360714253, 338512455, 310255664, 276379501, 237393220, 193922019, + 146648837, 96353228, 43872047, -9932907, -64141763, -117837085, + -170085645, -219975310, -266629410, -309200944, -346939392, -379119852, + -405153604, -424514398, -436807953, -441745719, -439164716, -429031904, + -411439319, -386617372, -354913267, -316797073, -272860523, -223800373, + -170393396, -113518291, -54112519, 6827960, 68275656, 129182673, + 188492573, 245180555, 298245210, 346732971, 389775867, 426573829, + 456438737, 478787157, 493153292, 499220637, 496795613, 485840102, + 466452793, 438881992, 403526130, 360909673, 311691302, 256650303, + 196670827, 132739707, 65907805, -2700984, -71937130, -140610726, + -207548644, -271569377, -331569987, -386464900, -435269685, -477092614, + -511151438, -536775753, -553458247, -560822864, -558660166, -546903818, + -525680344, -495253593, -456060540, -408696645, -353886403, -292506414, + -225548912, -154104305, -79357989, -2561325, 74990181, 151972303, + 227066091, 298962161, 366405218, 428188514, 483211372, 530459862, + 569062016, 598277372, 617510900, 626356585, 624560000, 612060937, + 588968499, 555591130, 512411217, 460077642, 399402792, 331356454, + 257035710, 177661517, 94544543, 9078357, -77292654, -163096706, + -246858480, -327129277, -402500612, -471640542, -533309915, -586386059, + -629889889, -662987333, -685024657, -695536650, -694236254, -681048472, + -656096749, -619709358, -572413134, -514919077, -448139426, -373131135, + -291109258, -203418830, -111520436, -16947282, 78700085, 173795497, + 266706134, 355821766, 439583391, 516516093, 585243211, 644522213, + 693263322, 730544442, 755633273, 768005415, 767338814, 753543170, + 726752740, 687313915, 635809216, 573019067, 499930312, 417713744, + 327700363, 231372022, 130329737, 26257105, -79076016, -183887358, + -286366416, -384750216, -477320353, -562449725, -638616288, -704458907, + -758758447, -800507282, -828883506, -843307951, -843426655, -829126268, + -800540682, -758051926, -702285573, -634098007, -554555308, -464934509, + -366696843, -261459008, -150968810, -37078553, 78287202, 193169274, + 305590106, 413617022, 515363932, 609041209, 692999791, 765716620, + 825874328, 872350899, 904255173, 920933942, 921991897, 907302345, + 876995606, 831491084, 771450963, 697802833, 611711188, 514553522, + 407924872, 293581426, 173412732, 49450008, -76218165, -201462064, + -324123571, -442093130, -553318187, -655856510, -747889886, -827768644, + -894047369, -945499331, -981148121, -1000271653, -1002435558, -987487658, + -955564675, -907105489, -842828582, -763719588, -671045492, -566295061, + -451176469, -327596047, -197610656, -63402519, 72763028, 208568268, + 341689279, 469837824, 590779804, 702411793, 802756107, 890031701, + 962659652, 1019302373, 1058894770, 1080652653, 1084089892, 1069029267, + 1035616997, 984310463, 915868643, 831368539, 732138036, 619797618, + 496178710, 363330656, 223463581, 78932936, -67831952, -214321056, + -358035511, -496501573, -627322734, -748210245, -857045845, -951889207, + -1031046097, -1093063589, -1136783070, -1161342438, -1166218018, -1151211372, + -1116459710, -1062446233, -989977050, -900187067, -794513962, -674664651, + -542612066, -400545709, -250835618, -95987277, 61364836, 218559073, + 372902420, 521744972, 662503466, 792739349, 910160054, 1012694129, + 1098502669, 1166028599, 1214023809, 1241553437, 1248036967, 1233254419, + 1197341171, 1140794021, 1064475666, 969571958, 857622760, 730435171, + 590108274, 438970794, 279545597, 114515489, -53334992, -221140870, + -386048025, -545211956, -695892850, -835473083, -961502732, -1071771032, + -1164306249, -1237436513, -1289821237, -1320457758, -1328710489, -1314334805, + -1277454667, -1218590303, -1138644363, -1038872942, -920883135, -786610219, + -638256404, -478293472, -309391820, -134402940, 43720522, 221947038, + 397237986, 566582584, 727057401, 875882937, 1010467192, 1128437030, + 1227705429, 1306486153, 1363337657, 1397194988, 1407374023, 1393581661, + 1355955920, 1295029129, 1211727393, 1107379233, 983675309, 842639668, + 686599942, 518157159, 340132910, 155517872, -32551047, -220888680, + -406281117, -585536670, -755581427, -913471547, -1056447125, -1182018238, + -1287955758, -1372371364, -1433739680, -1470903413, -1483138046, -1470128386, + -1431988068, -1369264203, -1282936733, -1174373434, -1045338297, -897950837, + -734656662, -558176986, -371475445, -177689527, 19892513, 217915644, + 412997957, 601805608, 781081716, 947733928, 1098870125, 1231847160, + 1344327293, 1434310121, 1500180677, 1540715667, 1555129526, 1543084250, + 1504675269, 1440471194, 1351469669, 1239099003, 1105185102, 951940796, + 781910283, 597941305, 403111530, 200712781, -5824762, -212994191, + -417261433, -615130588, -803202090, -978230008, -1137190856, -1277301705, + -1396119506, -1491538873, -1561855656, -1605779457, -1622481182, -1611573682, + -1573160731, -1507799779, -1416525935, -1300804137, -1162532566, -1003997496, + -827842473, -637007723, -434707419, -224363857, -9529147, 206141110, + 418961991, 625309440, 821625264, 1004543936, 1170892474, 1317789291, + 1442668348, 1543329576, 1617986419, 1665291150, 1684353298, 1674763544, + 1636596958, 1570432320, 1477313125, 1358749421, 1216693848, 1053501196, + 871900049, 674928292, 465909734, 248374414, 26011493, -197396416, + -418047432, -632168499, -836088206, -1026306899, -1199532237, -1352774708, + -1483362122, -1589013138, -1667859380, -1718486820, -1739959414, -1731839850, + -1694188625, -1627580629, -1533073593, -1412212813, -1266996403, -1099843876, + -913551827, -711245725, -496342808, -272475963, -43448807, 186852460, + 414501321, 635605431, 846385683, 1043217713, 1222718789, 1381788185, + 1517669181, 1627982917, 1710811456, 1764671245, 1788582254, 1782075582, + 1745195237, 1678510734, 1583094073, 1460515358, 1312808363, 1142439233, + 952272960, 745500972, 525630752, 296374628, 61627773, -174619248, + -408338841, -635548976, -852356373, -1055039545, -1240132943, -1404437242, + -1545116122, -1659725677, -1746274508, -1803234452, -1829578860, -1824800936, + -1788947477, -1722558810, -1626723784, -1503026676, -1353526848, -1180736873, + -987560877, -777264714, -553400924, -319762014, -80323054, 160850975, + 399648300, 631989745, 853911556, 1061611842, 1251535835, 1420413179, + 1565341882, 1683813544, 1773777276, 1833658423, 1862393559, 1859456468, + 1824850431, 1759130098, 1663373112, 1539169746, 1388612600, 1214226013, + 1018956148, 806102039, 579277584, 342326951, 99278560, -145730951, + -388522944, -624972370, -851028582, -1062836348, -1256765856, -1429496044, + -1578067280, -1699914608, -1792940108, -1855530759, -1886589380, -1885556536, + -1852427918, -1787733942, -1692547773, -1568470823, -1417588696, -1242446357, + -1046016840, -831625333, -602914593, -363764440, -118246447, 129457933, + 375133133, 614592525, 843753094, 1058698702, 1255759245, 1431571485, + 1583116729, 1707807432, 1803502380, 1868552397, 1901829488, 1902756563, + 1871297545, 1807976709, 1713849715, 1590510399, 1440048829, 1265014746, + 1068377633, 853481494, 623978067, 383777980, 136958703, -112263451, + -359658453, -601001951, -832182190, -1049261424, -1248533642, -1426603203, + -1580431454, -1707395036, -1805325977, -1872546489, -1907914848, -1910818076, + -1881207464, -1819578191, -1726983553, -1604994703, -1455689253, -1281612422, + -1085724274, -871362313, -642175923, -402075595, -155149216, 94400503, + 342322888, 584392163, 816484983, 1034660863, 1235192607, 1414675018, + 1570047568, 1698683993, 1798381542, 1867461297, 1904749062, 1909622838, + 1882001675, 1822371202, 1731754856, 1611708739, 1464279918, 1291998989, + 1097800233, 885005516, 657247259, 418403559, 172550621, -76116588, + -323374830, -565003771, -796896074, -1015106272, -1215927587, -1395951522, + -1552119510, -1681791215, -1782773966, -1853368131, -1892388366, -1899186924, + -1873682131, -1816320639, -1728100774, -1610554472, -1465704675, -1296028376, + -1104443620, -894227806, -668969691, -432525248, -188924505, 57679224, + 303082074, 543110898, 773680753, 990874742, 1191013320, 1370694105, + 1526894338, 1656961319, 1758722067, 1830459298, 1870994518, 1879662164, + 1856352631, 1801500505, 1716070729, 1601552060, 1459928482, 1293641204, + 1105547943, 898884127, 677184136, 444236544, 204030905, -39343464, + -281738664, -519025295, -747170062, -962310760, -1160794862, -1339268137, + -1494721598, -1624539903, -1726553534, -1799057804, -1840866292, -1851309234, + -1830258511, -1778116140, -1695821581, -1584818150, -1447033124, -1284862132, + -1101101431, -898908590, -681765683, -453380283, -217663348, 21366067, + 259626629, 493069110, 717729127, 929798100, 1125685812, 1302090661, + 1456045329, 1584967615, 1686708061, 1759581633, 1802411603, 1814515303, + 1795749950, 1746490361, 1667630949, 1560573113, 1427192494, 1269816696, + 1091161725, 894307502, 682653795, 459821740, 229630215, -3991130, + -237055717, -465609152, -685757243, -893783125, -1086168150, -1259671175, + -1411386186, -1538775234, -1639723774, -1712577604, -1756151022, -1769776508, + -1753292116, -1707041151, -1631881051, -1529159258, -1400681659, -1248706757, + -1075861775, -885147434, -679849203, -463492936, -239788150, -12560413, + 214318410, 436985739, 651670077, 854731189, 1042749355, 1212561343, + 1361329636, 1486571568, 1586224427, 1658655883, 1702702675, 1717693933, + 1703455417, 1660303044, 1589054484, 1490989879, 1367857293, 1221819477, + 1055425710, 871558841, 673398885, 464352943, 248016103, 28083145, + -191694062, -407575006, -615898089, -813149104, -995999398, -1161377159, + -1306529815, -1429044289, -1526909689, -1598526684, -1642758694, -1658946878, + -1646894078, -1606895102, -1539711606, -1446581982, -1329160129, -1189527998, + -1030131177, -853735906, -663406443, -462421125, -254228780, -42401115, + 169451502, 377727713, 578892455, 769550429, 946492399, 1106757984, + 1247674256, 1366915397, 1462519769, 1532950547, 1577092743, 1594289529, + 1584334455, 1547501541, 1484506909, 1396511141, 1285109652, 1152267535, + 1000325188, 831938878, 650030018, 457742667, 258382869, 55359579, + -147847679, -347788933, -541079146, -724454918, -894832674, -1049365889, + -1185484078, -1300945379, -1393867499, -1462752000, -1506525019, -1524534111, + -1516573574, -1482884349, -1424138055, -1341436489, -1236269034, -1110525776, + -966421500, -806481853, -633479129, -450426376, -260462875, -66851522, + 127097697, 318089971, 502889675, 678382853, 841616839, 989876013, + 1120699644, 1231929704, 1321767154, 1388773428, 1431909652, 1450532073, + 1444440429, 1413846257, 1359367356, 1282038972, 1183278349, 1064856624, + 928864074, 777700150, 614008311, 440608109, 260508254, 76791586, + -107397743, -288930379, -464730860, -631837850, -787440176, -928960132, + -1054050908, -1160662595, -1247065451, -1311883567, -1354123178, -1373165346, + -1368802620, -1341217886, -1290981329, -1219063811, -1126791045, -1015827089, + -888150371, -746008746, -591888502, -428466615, -258572737, -85123526, + 88914651, 260589405, 426977848, 585294445, 732875277, 867275801, + 986273147, 1087921573, 1170581642, 1232944255, 1274053918, 1293320897, + 1290533012, 1265841361, 1219785598, 1153259730, 1067496103, 964053892, + 844793457, 711808351, 567446758, 414212914, 254760236, 91832935, + -71784776, -233305320, -389993434, -539216020, -678471866, -805456788, + -918066920, -1014479691, -1093137391, -1152807458, -1192573206, -1211874921, + -1210490051, -1188568015, -1146583692, -1085373537, -1006089058, -910161528, + -799331029, -675561646, -541023592, -398076238, -249186890, -96927127, + 56101333, 207288357, 354082194, 494010022, 624734728, 744083114, + 850106912, 941064500, 1015518034, 1072287608, 1110518956, 1129673954, + 1129534807, 1110224999, 1072183624, 1016175030, 943253900, 854764740, + 752304975, 637704638, 512982470, 380314468, 242013120, 100454613, + -41930954, -182719906, -319522396, -450050709, -572124797, -683715081, + -783002819, -868369891, -938459121, -992172259, -1028703484, -1047537853, + -1048477454, -1031613185, -997345311, -946374992, -879676080, -798477569, + -704258873, -598700531, -483679417, -361196098, -233396476, -102482455, + 29308002, 159719299, 286554702, 407677229, 521069555, 624855049, + 717336577, 797022777, 862641869, 913174983, 947866087, 966234173, + 968080713, 953484175, 922811838, 876683918, 816003691, 741894095, + 655709798, 559004050, 453483583, 341011967, 223540020, 103099760, + -18233260, -138395689, -255355128, -367156398, -471920516, -567930301, + -653616510, -727591722, -788690875, -835956443, -868701664, -886467574, + -889061508, -876552359, -849257612, -807750695, -752853186, -685576819, + -607171911, -519042242, -422762779, -320026739, -212630774, -102428770, + 8682967, 118812009, 226087388, 328720449, 424999500, 513333030, + 592286422, 660577795, 717148715, 761115072, 791827347, 808872127, + 812061714, 801441574, 777310902, 740181390, 690785229, 630053428, + 559110814, 479238032, 391861521, 298534506, 200878658, 100590430, + -607287, -100989423, -198849315, -292555237, -380548523, -461371351, + -533713558, -596424172, -648498641, -689151697, -717782049, -734005256, + -737643908, -728733948, -707537411, -674510484, -630317318, -575800816, + -511961435, -439971506, -361118572, -276793246, -188485832, -97722445, + -6061637, 84927343, 173708384, 258790208, 338756360, 412298791, + 478220506, 535463826, 583135683, 620504631, 647031770, 662348437, + 666300618, 658915978, 640416389, 611220585, 571908297, 523234948, + 466117071, 401592604, 330825586, 255073642, 175660907, 93972958, + 11416894, -70596785, -150687862, -227501411, -299770818, -366304718, + -426033185, -477990740, -521373453, -555521652, -579935619, -594295837, + -598441014, -592403331, -576366581, -550704622, -515936356, -472738946, + -421926566, -364421956, -301273613, -233600973, -162593440, -89496920, + -15564081, 57945801, 129777276, 198735962, 263673192, 323522023, + 377324214, 424207890, 463459128, 494471178, 516806828, 530161704, + 534390205, 529525253, 515722595, 493310268, 462743131, 424629406, + 379680615, 328731908, 272704910, 212598522, 149476632, 84436692, + 18611043, -46890106, -110946726, -172490471, -230497005, -284018193, + -332193404, -374253518, -409544375, -437542950, -457836446, -470163396, + -474396436, -470538010, -458741499, -439285478, -412576250, -379140208, + -339618079, -294740527, -245328608, -192258120, -136474880, -78950323, + -20684043, 37337800, 94123822, 148719315, 200232263, 247809979, + 290690028, 328191762, 359737003, 384846037, 403167797, 414462578, + 418612328, 415616471, 405608074, 388824822, 365627908, 336478576, + 301938852, 262645553, 219323761, 172742000, 123743307, 73167648, + 21900080, -29183756, -79218352, -127364108, -172827967, -214863012, + -252796088, -286026643, -314042942, -336429977, -352864310, -363132718, + -367129059, -364863616, -356429040, -342048284, -322028244, -296774094, + -266768316, -232579633, -194825815, -154197159, -111415846, -67221548, + -22393396, 22309840, 66124542, 108316468, 148196551, 185105519, + 218455448, 247719513, 272444601, 292265988, 306909294, 316172902, + 319976012, 318306257, 311259813, 299016336, 281847408, 260104006, + 234201035, 204634435, 171943983, 136726029, 99607937, 61229245, + 22277383, -16592151, -54723400, -91468534, -126228236, -158430959, + -187562953, -213164354, -234846478, -252284778, -265235499, -273534395, + -277099121, -275918277, -270073506, -259721509, -245096765, -226492670, + -204280869, -178875510, -150747495, -120413922, -88411837, -55306424, + -21669900, 11917494, 44880837, 76678439, 106778103, 134689892, + 159972738, 182223956, 201108612, 216348810, 227726051, 235104451, + 238398771, 237610161, 232803839, 224116370, 211735335, 195925346, + 176994801, 155311385, 131268473, 105311188, 77899862, 49524551, + 20673231, -8152563, -36466660, -63795119, -89689631, -113724103, + -135516162, -154729334, -171063592, -184287496, -194214077, -200713055, + -203732664, -203253125, -199335834, -192088497, -181685639, -168336364, + -152320108, -133926606, -113516594, -91451969, -68135088, -43975393, + -19395029, 5179829, 29338263, 52667285, 74792697, 95346363, + 114000498, 130472557, 144507874, 155901496, 164498743, 170184919, + 172911765, 172668424, 169499571, 163505275, 154819428, 143630524, + 130166712, 114681138, 97470938, 78844567, 59142464, 38718237, + 17918794, -2890238, -23353533, -43135381, -61900242, -79354061, + -95218074, -109237355, -121211123, -130960785, -138345116, -143280745, + -145714419, -145646556, -143111878, -138189432, -130990829, -121678718, + -110439552, -97488855, -83077526, -67467936, -50938253, -33790970, + -16323372, 1170024, 18382855, 35032469, 50844610, 65556934, + 78945328, 90799046, 100930128, 109201569, 115507170, 119753539, + 121907093, 121964702, 119952242, 115936776, 110019754, 102325119, + 93008244, 82261389, 70284961, 57293131, 43529865, 29234651, + 14669782, 72779, -14296826, -28212097, -41430023, -53743152, + -64955789, -74894358, -83414010, -90383998, -95716201, -99336816, + -101228066, -101364256, -99783104, -96540755, -91706720, -85398404, + -77736086, -68883213, -58999854, -48272828, -36895247, -25073075, + -13017290, -929976, 10982581, 22515118, 33483816, 43708142, + 53031199, 61303563, 68404150, 74229401, 78705238, 81769841, + 83400870, 83592764, 82367919, 79764133, 75845584, 70713662, + 64463816, 57222981, 49132592, 40343881, 31010088, 21309507, + 11408987, 1476574, -8313780, -17805847, -26834606, -35257362, + -42940370, -49768901, -55642345, -60471386, -64198025, -66767863, + -68164088, -68386583, -67440978, -65373000, -62227670, -58079637, + -53020760, -47150844, -40578759, -33434938, -25844740, -17946248, + -9882139, -1783854, 6202175, 13941288, 21315238, 28196425, + 34483059, 40077359, 44886111, 48859936, 51928205, 54068948, + 55255999, 55479035, 54764175, 53128559, 50625402, 47303227, + 43241873, 38519687, 33230138, 27466783, 21346265, 14970247, + 8455675, 1911983, -4545824, -10812044, -16774603, -22355449, + -27449074, -31989201, -35898928, -39137158, -41646925, -43408685, + -44400739, -44620314, -44085374, -42807115, -40826602, -38193991, + -34964509, -31193892, -26972036, -22367527, -17466953, -12367218, + -7146262, -1904869, 3267821, 8291041, 13080466, 17561039, + 21651499, 25306067, 28460581, 31066869, 33106592, 34537018, + 35360504, 35569033, 35167687, 34177966, 32634704, 30560883, + 28009270, 25036520, 21689186, 18040253, 14161727, 10113724, + 5974160, 1812535, -2298571, -6293363, -10098147, -13659222, + -16921043, -19827946, -22345389, -24432435, -26066901, -27223379, + -27898523, -28085752, -27792084, -27035106, -25834265, -24220063, + -22225270, -19894969, -17274748, -14414396, -11365505, -8185495, + -4931060, -1659560, 1575182, 4715237, 7711549, 10523077, + 13090914, 15387506, 17376138, 19029662, 20325401, 21250905, + 21795069, 21961365, 21753118, 21177274, 20250113, 19008061, + 17460596, 15654912, 13623473, 11397730, 9025297, 6557050, + 4019253, 1474121, -1045141, -3489662, -5831327, -8019809, + -10026099, -11818538, -13371276, -14669502, -15687477, -16419232, + -16856866, -16994403, -16845308, -16412914, -15714736, -14760202, + -13578426, -12191116, -10629600, -8921647, -7092202, -5190448, + -3239217, -1275934, 663046, 2554298, 4356076, 6044040, + 7594214, 8980359, 10182478, 11188168, 11974521, 12546254, + 12895773, 13014200, 12908086, 12587362, 12058446, 11338623, + 10439693, 9387813, 8201196, 6899320, 5509481, 4064219, + 2576865, 1080047, -400703, -1839939, -3214850, -4504065, + -5687108, -6747572, -7663672, -8435009, -9043227, -9484985, + -9753642, -9849076, -9779353, -9541923, -9151368, -8610339, + -7937707, -7149141, -6254080, -5276073, -4231361, -3138920, + -2020649, -894056, 222733, 1305993, 2340866, 3311888, + 4207117, 5005958, 5703280, 6283490, 6745544, 7082468, + 7287202, 7363976, 7317850, 7144786, 6853114, 6459652, + 5959086, 5371726, 4711175, 3985262, 3204339, 2395324, + 1564483, 723119, -105777, -909733, -1683889, -2405419, + -3074924, -3671133, -4188416, -4623151, -4966669, -5217822, + -5376505, -5438699, -5406246, -5282262, -5074698, -4786421, + -4415698, -3989649, -3503458, -2971553, -2398392, -1804213, + -1193619, -576390, 32462, 628385, 1194781, 1727140, + 2213574, 2652369, 3033564, 3352595, 3609052, 3797641, + 3911246, 3962598, 3939600, 3852699, 3701594, 3492114, + 3230424, 2916926, 2563901, 2181899, 1765468, 1336348, + 897255, 451524, 10400, -423355, -833387, -1217639, + -1571274, -1889254, -2165240, -2398526, -2581778, -2722473, + -2806177, -2843650, -2829585, -2769524, -2663939, -2516691, + -2327935, -2105389, -1854132, -1579438, -1284757, -976868, + -663162, -345625, -29806, 277631, 573265, 848377, + 1098155, 1323542, 1523169, 1692667, 1820388, 1921574, + 1980041, 2009485, 2000458, 1958506, 1882804, 1781576, + 1650184, 1491210, 1315288, 1123764, 920326, 700329, + 478507, 256533, 32026, -180003, -384095, -577687, + -756750, -917410, -1053764, -1170111, -1262779, -1332577, + -1375847, -1391609, -1392675, -1362480, -1311761, -1240430, + -1148291, -1039811, -917895, -784334, -643710, -496828, + -337593, -185408, -35103, 113070, 255859, 384329, + 506227, 617511, 714746, 795605, 860777, 906972, + 935925, 948904, 945758, 926027, 895773, 846226, + 784240, 710311, 628903, 537754, 444898, 341692, + 241505, 133447, 30958, -72515, -164395, -255320, + -334239, -410321, -475067, -526756, -573940, -605247, + -622819, -637482, -631446, -619838, -596390, -563572, + -523754, -477660, -426306, -363560, -295189, -230207, + -163718, -95093, -25083, 39224, 104809, 164493, + 216339, 268715, 307770, 343381, 376591, 393894, + 409214, 415048, 414650, 407176, 388288, 370122, + 344328, 309042, 277273, 235390, 198767, 149968, + 107391, 64774, 22734, -22484, -65777, -100024, + -134431, -168338, -196571, -218070, -239916, -252287, + -260207, -264251, -263475, -255361, -249920, -233428, + -219729, -200561, -178348, -152486, -126879, -98039, + -68509, -40108, -12510, 10116, 37364, 62735, + 83265, 105535, 122744, 134992, 146756, 157803, + 160999, 161373, 164013, 160462, 154774, 144884, + 134790, 126783, 107178, 92058, 76572, 57882, + 43557, 26865, 12612, -4122, -19611, -34312, + -50182, -64020, -71989, -80713, -88451, -93341, + -97703, -97951, -98271, -96134, -93821, -85291, + -81741, -74008, -66399, -57833, -47278, -35028, + -26476, -14656, -4700, 3292, 15438, 21244, + 29516, 33116, 42333, 47158, 49673, 56057, + 53914, 56647, 58612, 53778, 50181, 53182, + 46382, 38717, 37541, 30440, 26852, 21271, + 13076, 9386, 4881, -3217, -6456, -9167, + -14339, -21479, -24043, -24056, -31348, -29829, + -29018, -30209, -31831, -31798, -28027, -29569, + -25967, -24517, -21618, -18204, -15378, -12502, + -9278, -7266, -3404, 3091, 4309, 6623, + 9973, 9739, 10030, 12920, 16929, 18390, + 15259, 16991, 14629, 15567, 17209, 11571, + 14371, 12597, 11641, 9273, 6978, 8908, + 3725, -56, 2695, -189, -624, -3726, + -4651, -5443, -6305, -5793, -8874, -6473, + -7155, -7928, -4337, -5197, -10879, -8256, + -9328, -5819, -4801, -1061, -4140, -2848, + -5058, 450, 134, -988, -2654, -529, + 1305, -1503, 1327, 2653, 2727, 3765, + 1663, 2376, 5098, 3599, 2627, 4534, + 1709, 4472, 1626, 4200, -688, 1716, + 455, 2684, -1687, -2322, 540, 278, + 2327, 931, -1176, -108, -3519, -317, + -1225, -1108, -971, -844, -2534, -1462, + -554, -41, -29, -263, -2482, 614, + -2090, 576, -2654, -2080, 656, 174, + -297, -1757, 738, -493, 1359, 229, + 934, -956, -1365, -707, 3858, 1771, + 799, -1000, -779, -93, -1114, 804, + -1730, -1932, -731, 1052, 108, -1784, + -1167, -1073, 2003, 441, -543, -445, + -1474, 253, -2753, 1985, -2835, 1736, +}; + +static const int32_t ifft_ref_imag_3072_q31[3072] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +}; diff --git a/test/cmocka/src/math/matrix/CMakeLists.txt b/test/cmocka/src/math/matrix/CMakeLists.txt new file mode 100644 index 000000000000..2c5c0420fb35 --- /dev/null +++ b/test/cmocka/src/math/matrix/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(matrix + matrix.c + ${PROJECT_SOURCE_DIR}/src/math/matrix.c + ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c +) diff --git a/test/cmocka/src/math/matrix/matrix.c b/test/cmocka/src/math/matrix/matrix.c new file mode 100644 index 000000000000..63632ba58c4b --- /dev/null +++ b/test/cmocka/src/math/matrix/matrix.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <sof/audio/module_adapter/module/generic.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <cmocka.h> +#include <math.h> +#include <sof/math/matrix.h> +#include "ref_matrix_mult_16_test1.h" +#include "ref_matrix_mult_16_test2.h" +#include "ref_matrix_mult_16_test3.h" +#include "ref_matrix_mult_16_test4.h" + +#define MATRIX_MULT_16_MAX_ERROR_ABS 1.5 +#define MATRIX_MULT_16_MAX_ERROR_RMS 0.5 + +struct processing_module dummy; + +static void matrix_mult_16_test(const int16_t *a_ref, const int16_t *b_ref, const int16_t *c_ref, + int elementwise, int a_rows, int a_columns, + int b_rows, int b_columns, int c_rows, int c_columns, + int a_frac, int b_frac, int c_frac) +{ + struct mat_matrix_16b *a_matrix; + struct mat_matrix_16b *b_matrix; + struct mat_matrix_16b *c_matrix; + float delta; + float sum_squares = 0; + float error_rms; + float delta_max = 0; + int16_t x; + int i, j, k; + + a_matrix = mod_mat_matrix_alloc_16b(&dummy, a_rows, a_columns, a_frac); + if (!a_matrix) + exit(EXIT_FAILURE); + + b_matrix = mod_mat_matrix_alloc_16b(&dummy, b_rows, b_columns, b_frac); + if (!b_matrix) { + mod_free(&dummy, a_matrix); + exit(EXIT_FAILURE); + } + + c_matrix = mod_mat_matrix_alloc_16b(&dummy, c_rows, c_columns, c_frac); + if (!c_matrix) { + mod_free(&dummy, a_matrix); + mod_free(&dummy, b_matrix); + exit(EXIT_FAILURE); + } + + /* Initialize matrices a and b from test vectors and do matrix multiply */ + mat_copy_from_linear_16b(a_matrix, a_ref); + mat_copy_from_linear_16b(b_matrix, b_ref); + if (elementwise) + mat_multiply_elementwise(a_matrix, b_matrix, c_matrix); + else + mat_multiply(a_matrix, b_matrix, c_matrix); + + /* Check */ + k = 0; + for (i = 0; i < c_matrix->rows; i++) { + for (j = 0; j < c_matrix->columns; j++) { + x = mat_get_scalar_16b(c_matrix, i, j); + delta = (float)x - (float)c_ref[k++]; + sum_squares += delta * delta; + if (delta > delta_max) + delta_max = delta; + else if (-delta > delta_max) + delta_max = -delta; + } + } + + error_rms = sqrt(sum_squares / (float)(c_matrix->rows * c_matrix->columns)); + printf("Max absolute error = %5.2f (max %5.2f), error RMS = %5.2f (max %5.2f)\n", + delta_max, MATRIX_MULT_16_MAX_ERROR_ABS, error_rms, MATRIX_MULT_16_MAX_ERROR_RMS); + + assert_true(error_rms < MATRIX_MULT_16_MAX_ERROR_RMS); + assert_true(delta_max < MATRIX_MULT_16_MAX_ERROR_ABS); + + mod_free(&dummy, a_matrix); + mod_free(&dummy, b_matrix); + mod_free(&dummy, c_matrix); +} + +static void test_matrix_mult_16_test1(void **state) +{ + (void)state; + + matrix_mult_16_test(matrix_mult_16_test1_a, + matrix_mult_16_test1_b, + matrix_mult_16_test1_c, + MATRIX_MULT_16_TEST1_ELEMENTWISE, + MATRIX_MULT_16_TEST1_A_ROWS, + MATRIX_MULT_16_TEST1_A_COLUMNS, + MATRIX_MULT_16_TEST1_B_ROWS, + MATRIX_MULT_16_TEST1_B_COLUMNS, + MATRIX_MULT_16_TEST1_C_ROWS, + MATRIX_MULT_16_TEST1_C_COLUMNS, + MATRIX_MULT_16_TEST1_A_QXY_Y, + MATRIX_MULT_16_TEST1_B_QXY_Y, + MATRIX_MULT_16_TEST1_C_QXY_Y); +} + +static void test_matrix_mult_16_test2(void **state) +{ + (void)state; + + matrix_mult_16_test(matrix_mult_16_test2_a, + matrix_mult_16_test2_b, + matrix_mult_16_test2_c, + MATRIX_MULT_16_TEST2_ELEMENTWISE, + MATRIX_MULT_16_TEST2_A_ROWS, + MATRIX_MULT_16_TEST2_A_COLUMNS, + MATRIX_MULT_16_TEST2_B_ROWS, + MATRIX_MULT_16_TEST2_B_COLUMNS, + MATRIX_MULT_16_TEST2_C_ROWS, + MATRIX_MULT_16_TEST2_C_COLUMNS, + MATRIX_MULT_16_TEST2_A_QXY_Y, + MATRIX_MULT_16_TEST2_B_QXY_Y, + MATRIX_MULT_16_TEST2_C_QXY_Y); +} + +static void test_matrix_mult_16_test3(void **state) +{ + (void)state; + + matrix_mult_16_test(matrix_mult_16_test3_a, + matrix_mult_16_test3_b, + matrix_mult_16_test3_c, + MATRIX_MULT_16_TEST3_ELEMENTWISE, + MATRIX_MULT_16_TEST3_A_ROWS, + MATRIX_MULT_16_TEST3_A_COLUMNS, + MATRIX_MULT_16_TEST3_B_ROWS, + MATRIX_MULT_16_TEST3_B_COLUMNS, + MATRIX_MULT_16_TEST3_C_ROWS, + MATRIX_MULT_16_TEST3_C_COLUMNS, + MATRIX_MULT_16_TEST3_A_QXY_Y, + MATRIX_MULT_16_TEST3_B_QXY_Y, + MATRIX_MULT_16_TEST3_C_QXY_Y); +} + +static void test_matrix_mult_16_test4(void **state) +{ + (void)state; + + matrix_mult_16_test(matrix_mult_16_test4_a, + matrix_mult_16_test4_b, + matrix_mult_16_test4_c, + MATRIX_MULT_16_TEST4_ELEMENTWISE, + MATRIX_MULT_16_TEST4_A_ROWS, + MATRIX_MULT_16_TEST4_A_COLUMNS, + MATRIX_MULT_16_TEST4_B_ROWS, + MATRIX_MULT_16_TEST4_B_COLUMNS, + MATRIX_MULT_16_TEST4_C_ROWS, + MATRIX_MULT_16_TEST4_C_COLUMNS, + MATRIX_MULT_16_TEST4_A_QXY_Y, + MATRIX_MULT_16_TEST4_B_QXY_Y, + MATRIX_MULT_16_TEST4_C_QXY_Y); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_matrix_mult_16_test1), + cmocka_unit_test(test_matrix_mult_16_test2), + cmocka_unit_test(test_matrix_mult_16_test3), + cmocka_unit_test(test_matrix_mult_16_test4), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/matrix/ref_matrix.m b/test/cmocka/src/math/matrix/ref_matrix.m new file mode 100644 index 000000000000..671295f908a9 --- /dev/null +++ b/test/cmocka/src/math/matrix/ref_matrix.m @@ -0,0 +1,238 @@ +% ref_matrix - Generate C header files for matrix library unit tests + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function ref_matrix() + opt.test_n = 1; + opt.input = 'random'; + opt.a_rows = 3; + opt.a_columns = 4; + opt.b_rows = 4; + opt.b_columns = 5; + opt.a_qxy_x = 1; + opt.a_qxy_y = 15; + opt.b_qxy_x = 1; + opt.b_qxy_y = 15; + opt.c_qxy_x = 2; + opt.c_qxy_y = 14; + opt.elementwise = 0; + get_ref_mult(opt); + + opt.test_n = 2; + opt.input = 'random'; + opt.a_rows = 6; + opt.a_columns = 7; + opt.b_rows = 7; + opt.b_columns = 8; + opt.a_qxy_x = 7; + opt.a_qxy_y = 0; + opt.b_qxy_x = 7; + opt.b_qxy_y = 0; + opt.c_qxy_x = 16; + opt.c_qxy_y = 0; + opt.elementwise = 0; + get_ref_mult(opt); + + opt.test_n = 3; + opt.input = 'random'; + opt.a_rows = 5; + opt.a_columns = 6; + opt.b_rows = 5; + opt.b_columns = 6; + opt.a_qxy_x = 1; + opt.a_qxy_y = 15; + opt.b_qxy_x = 1; + opt.b_qxy_y = 15; + opt.c_qxy_x = 1; + opt.c_qxy_y = 15; + opt.elementwise = 1; + get_ref_mult(opt); + + opt.test_n = 4; + opt.input = 'random'; + opt.a_rows = 6; + opt.a_columns = 1; + opt.b_rows = 1; + opt.b_columns = 8; + opt.a_qxy_x = 1; + opt.a_qxy_y = 15; + opt.b_qxy_x = 1; + opt.b_qxy_y = 15; + opt.c_qxy_x = 1; + opt.c_qxy_y = 15; + opt.elementwise = 0; + get_ref_mult(opt); +end + +function get_ref_mult(opt) + [a_bits, a_scale] = get_qxy_scale(opt.a_qxy_x, opt.a_qxy_y); + [b_bits, b_scale] = get_qxy_scale(opt.b_qxy_x, opt.b_qxy_y); + [c_bits, c_scale] = get_qxy_scale(opt.c_qxy_x, opt.c_qxy_y); + bits = max([a_bits b_bits c_bits]); + + % Data to process + switch lower(opt.input) + case 'ones' + a = ones(opt.a_rows, opt.a_columns); + b = ones(opt.b_rows, opt.b_columns); + case 'random' + a = (rand(opt.a_rows, opt.a_columns) * 2 - 1) * a_scale; + b = (rand(opt.b_rows, opt.b_columns) * 2 - 1) * b_scale; + otherwise + error('Illegal input'); + end + + [iqa, fqa] = quant_qxy(a, bits, opt.a_qxy_y, true); + [iqb, fqb] = quant_qxy(b, bits, opt.b_qxy_y, true); + if opt.elementwise + c = fqa .* fqb; + else + c = fqa * fqb; + end + + iqc = quant_qxy(c, bits, opt.c_qxy_y, false); + c_size = size(c); + + header_fn = sprintf('ref_matrix_mult_%d_test%d.h', bits, opt.test_n); + define_prefix = sprintf('MATRIX_MULT_%d_TEST%d_', bits, opt.test_n); + + fh = export_headerfile_open(header_fn); + comment = sprintf('Created %s with script ref_matrix.m %s', ... + datestr(now, 0), get_git_describe()); + export_comment(fh, comment); + export_ndefine(fh, [define_prefix 'ELEMENTWISE'], opt.elementwise); + export_ndefine(fh, [define_prefix 'A_ROWS'], opt.a_rows); + export_ndefine(fh, [define_prefix 'A_COLUMNS'], opt.a_columns); + export_ndefine(fh, [define_prefix 'B_ROWS'], opt.b_rows); + export_ndefine(fh, [define_prefix 'B_COLUMNS'], opt.b_columns); + export_ndefine(fh, [define_prefix 'C_ROWS'], c_size(1)); + export_ndefine(fh, [define_prefix 'C_COLUMNS'], c_size(2)); + export_ndefine(fh, [define_prefix 'A_QXY_Y'], opt.a_qxy_y); + export_ndefine(fh, [define_prefix 'B_QXY_Y'], opt.b_qxy_y); + export_ndefine(fh, [define_prefix 'C_QXY_Y'], opt.c_qxy_y); + + vector_name_a = sprintf('matrix_mult_%d_test%d_a', bits, opt.test_n); + vector_name_b = sprintf('matrix_mult_%d_test%d_b', bits, opt.test_n); + vector_name_c = sprintf('matrix_mult_%d_test%d_c', bits, opt.test_n); + export_vector(fh, bits, vector_name_a, mat_to_vec(iqa), size(iqa)); + export_vector(fh, bits, vector_name_b, mat_to_vec(iqb), size(iqb)); + export_vector(fh, bits, vector_name_c, mat_to_vec(iqc), size(iqc)); + fclose(fh); + fprintf(1, 'Exported file %s\n', header_fn); +end + +function [bits, scale] = get_qxy_scale(qxy_x, qxy_y) + bits = qxy_x + qxy_y; + scale = 2^(bits - 1) / 2^qxy_y; +end + +function v = mat_to_vec(m) + v = reshape(transpose(m), prod(size(m)), 1); +end + +function [yq,qval] = quant_qxy(val, bits, y, saturate) + intmax = 2^(bits - 1) - 1; + intmin = -intmax - 1; + scale = 2^y; + yf = round(val * scale); + if saturate == true + yf(yf > intmax) = intmax; + yf(yf < intmin) = intmin; + end + + min_y = min(min(yf)); + max_y = max(max(yf)); + if max_y > intmax || min_y < intmin + fprintf(1, 'max_y = %d (%d), min_y = %d (%d)\n', ... + max_y, intmax, min_y, intmin); + error('Overflow, use other Q format'); + end + + switch bits + case 8 + yq = int8(yf); + case 16 + yq = int16(yf); + case 32 + yq = int32(yf); + otherwise + error('Unknown bits'); + end + + qval = double(yq) / scale; +end + +function fh = export_headerfile_open(headerfn) + fh = fopen(headerfn, 'w'); + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', ... + datestr(now, 'yyyy')); + fprintf(fh, ' */\n\n'); +end + +function export_ndefine(fh, dn, dval) + fprintf(fh, '#define %s %d\n', dn, dval); +end + +function export_comment(fh, text) + fprintf(fh, '/* %s */\n\n', text); +end + +function export_vector(fh, bits, vname, data, msize) + switch bits + case 8 + vtype = 'int8_t'; + maxcol = 10; + case 16 + vtype = 'int16_t'; + maxcol = 10; + case 32 + vtype = 'int32_t'; + maxcol = 6; + otherwise + error('Unkown bits format') + end + + if nargin == 5 + columns = msize(2); + columns = min(columns, maxcol); + else + columns = maxcol; + end + + rows = ceil(length(data) / columns); + fprintf(fh, '\nstatic const %s %s[%d] = {\n', vtype, vname, length(data)); + i = 1; + for j = 1:rows + if bits > 16 + fprintf(fh, '\t%11d,', data(i)); + else + fprintf(fh, '\t%6d,', data(i)); + end + i = i + 1; + for k = 2:columns + if i <= length(data) + if bits > 16 + fprintf(fh, ' %11d,', data(i)); + else + fprintf(fh, ' %6d,', data(i)); + end + i = i + 1; + end + end + fprintf(fh, '\n'); + end + fprintf(fh, '};\n'); +end + +function description = get_git_describe() + git_cmd = 'git describe --dirty --long --always'; + [status, out] = system(git_cmd); + description = strtrim(out); + if status + description = 'Unknown' + end +end diff --git a/test/cmocka/src/math/matrix/ref_matrix_mult_16_test1.h b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test1.h new file mode 100644 index 000000000000..527b6504f9b6 --- /dev/null +++ b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test1.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 31-Aug-2022 13:19:22 with script ref_matrix.m v1.9-rc1-1687-g6be4f7333-dirty */ + +#define MATRIX_MULT_16_TEST1_ELEMENTWISE 0 +#define MATRIX_MULT_16_TEST1_A_ROWS 3 +#define MATRIX_MULT_16_TEST1_A_COLUMNS 4 +#define MATRIX_MULT_16_TEST1_B_ROWS 4 +#define MATRIX_MULT_16_TEST1_B_COLUMNS 5 +#define MATRIX_MULT_16_TEST1_C_ROWS 3 +#define MATRIX_MULT_16_TEST1_C_COLUMNS 5 +#define MATRIX_MULT_16_TEST1_A_QXY_Y 15 +#define MATRIX_MULT_16_TEST1_B_QXY_Y 15 +#define MATRIX_MULT_16_TEST1_C_QXY_Y 14 + +static const int16_t matrix_mult_16_test1_a[12] = { + 19277, -6161, -12335, -26818, + 10310, 27140, 19845, -10544, + -23131, -404, 21417, -17457, +}; + +static const int16_t matrix_mult_16_test1_b[20] = { + -9743, -26470, -14323, 15093, 28656, + -23012, -7262, 20498, -8560, 9035, + -32365, 4482, 5131, 30363, 417, + -3825, 9178, 13964, 9555, -30031, +}; + +static const int16_t matrix_mult_16_test1_c[15] = { + 6954, -11703, -12820, -4381, 19790, + -20248, -7291, 5543, 6486, 13208, + -5977, 8407, 2886, 2103, -2034, +}; diff --git a/test/cmocka/src/math/matrix/ref_matrix_mult_16_test2.h b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test2.h new file mode 100644 index 000000000000..32822e46a81a --- /dev/null +++ b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test2.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 31-Aug-2022 13:19:22 with script ref_matrix.m v1.9-rc1-1687-g6be4f7333-dirty */ + +#define MATRIX_MULT_16_TEST2_ELEMENTWISE 0 +#define MATRIX_MULT_16_TEST2_A_ROWS 6 +#define MATRIX_MULT_16_TEST2_A_COLUMNS 7 +#define MATRIX_MULT_16_TEST2_B_ROWS 7 +#define MATRIX_MULT_16_TEST2_B_COLUMNS 8 +#define MATRIX_MULT_16_TEST2_C_ROWS 6 +#define MATRIX_MULT_16_TEST2_C_COLUMNS 8 +#define MATRIX_MULT_16_TEST2_A_QXY_Y 0 +#define MATRIX_MULT_16_TEST2_B_QXY_Y 0 +#define MATRIX_MULT_16_TEST2_C_QXY_Y 0 + +static const int16_t matrix_mult_16_test2_a[42] = { + 46, -7, -40, 15, -11, -26, 36, + -30, 16, 27, 49, 41, 1, 20, + -62, -34, 1, 17, 31, 56, -37, + 61, -57, 57, -36, -60, -32, -20, + -1, 12, -54, 44, -29, 57, 37, + -1, -4, 41, 17, -61, -53, -28, +}; + +static const int16_t matrix_mult_16_test2_b[56] = { + -49, 12, 19, 38, -43, 58, -46, -34, + 15, 38, -60, -15, 10, -30, 49, -46, + -54, -29, 34, 14, 57, 16, 23, 23, + 61, 24, 33, 56, 30, 19, -39, -45, + -53, 15, 49, 24, 56, -9, -40, 30, + 61, -19, 51, -62, 10, 24, 4, -19, + -31, -63, 41, -41, 40, 38, -13, 27, +}; + +static const int16_t matrix_mult_16_test2_c[48] = { + -1403, -133, 40, 2005, -3314, 3366, -4096, -1701, + 509, -23, 3885, 1844, 7565, -442, -1022, 451, + 6431, 75, 4315, -2091, 3709, -2578, 11, 1797, + -7270, -2983, -63, 3319, -5504, 4488, -352, 1747, + 9696, -783, 1880, -4257, -1169, 2589, -1417, -4694, + -320, 911, -4664, 4518, -2216, -746, 2722, -1183, +}; diff --git a/test/cmocka/src/math/matrix/ref_matrix_mult_16_test3.h b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test3.h new file mode 100644 index 000000000000..3809dc2f0f73 --- /dev/null +++ b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test3.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 31-Aug-2022 13:19:22 with script ref_matrix.m v1.9-rc1-1687-g6be4f7333-dirty */ + +#define MATRIX_MULT_16_TEST3_ELEMENTWISE 1 +#define MATRIX_MULT_16_TEST3_A_ROWS 5 +#define MATRIX_MULT_16_TEST3_A_COLUMNS 6 +#define MATRIX_MULT_16_TEST3_B_ROWS 5 +#define MATRIX_MULT_16_TEST3_B_COLUMNS 6 +#define MATRIX_MULT_16_TEST3_C_ROWS 5 +#define MATRIX_MULT_16_TEST3_C_COLUMNS 6 +#define MATRIX_MULT_16_TEST3_A_QXY_Y 15 +#define MATRIX_MULT_16_TEST3_B_QXY_Y 15 +#define MATRIX_MULT_16_TEST3_C_QXY_Y 15 + +static const int16_t matrix_mult_16_test3_a[30] = { + 23663, -18301, 5145, 24885, 28067, 7557, + 5068, -23957, -4802, 18506, -17209, 22372, + -23746, -15777, -3153, 6782, 3516, -18088, + -3783, -9536, -22760, 21341, -5638, 2116, + 30943, -30206, -29372, 25730, 25178, -29591, +}; + +static const int16_t matrix_mult_16_test3_b[30] = { + 23845, 24708, -29283, 24416, 27463, 18332, + -4428, -16617, -12608, 21807, -30988, -1056, + 9420, 13385, -15170, -21833, 21322, -28217, + -14987, 15556, 7216, -15191, 4158, 11965, + -23855, -18550, -10367, 1097, 23384, -8219, +}; + +static const int16_t matrix_mult_16_test3_c[30] = { + 17219, -13799, -4598, 18542, 23523, 4228, + -685, 12149, 1848, 12316, 16274, -721, + -6826, -6445, 1460, -4519, 2288, 15576, + 1730, -4527, -5012, -9894, -715, 773, + -22526, 17100, 9293, 861, 17968, 7422, +}; diff --git a/test/cmocka/src/math/matrix/ref_matrix_mult_16_test4.h b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test4.h new file mode 100644 index 000000000000..c8e5b54035b7 --- /dev/null +++ b/test/cmocka/src/math/matrix/ref_matrix_mult_16_test4.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* Created 31-Aug-2022 13:19:22 with script ref_matrix.m v1.9-rc1-1687-g6be4f7333-dirty */ + +#define MATRIX_MULT_16_TEST4_ELEMENTWISE 0 +#define MATRIX_MULT_16_TEST4_A_ROWS 6 +#define MATRIX_MULT_16_TEST4_A_COLUMNS 1 +#define MATRIX_MULT_16_TEST4_B_ROWS 1 +#define MATRIX_MULT_16_TEST4_B_COLUMNS 8 +#define MATRIX_MULT_16_TEST4_C_ROWS 6 +#define MATRIX_MULT_16_TEST4_C_COLUMNS 8 +#define MATRIX_MULT_16_TEST4_A_QXY_Y 15 +#define MATRIX_MULT_16_TEST4_B_QXY_Y 15 +#define MATRIX_MULT_16_TEST4_C_QXY_Y 15 + +static const int16_t matrix_mult_16_test4_a[6] = { + 1885, + -7669, + 20092, + 28297, + 5628, + -30238, +}; + +static const int16_t matrix_mult_16_test4_b[8] = { + 1932, -16113, 10393, 11618, -354, -1301, 6828, 16450, +}; + +static const int16_t matrix_mult_16_test4_c[48] = { + 111, -927, 598, 668, -20, -75, 393, 946, + -452, 3771, -2432, -2719, 83, 304, -1598, -3850, + 1185, -9880, 6373, 7124, -217, -798, 4187, 10086, + 1668, -13914, 8975, 10033, -306, -1123, 5896, 14205, + 332, -2767, 1785, 1995, -61, -223, 1173, 2825, + -1783, 14869, -9591, -10721, 327, 1201, -6301, -15180, +}; diff --git a/test/cmocka/src/math/numbers/CMakeLists.txt b/test/cmocka/src/math/numbers/CMakeLists.txt deleted file mode 100644 index 7a8c71670daf..000000000000 --- a/test/cmocka/src/math/numbers/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmocka_test(gcd - gcd.c - ${PROJECT_SOURCE_DIR}/src/math/numbers.c -) - -cmocka_test(ceil_divide - ceil_divide.c - ${PROJECT_SOURCE_DIR}/src/math/numbers.c -) -target_link_libraries(ceil_divide PRIVATE -lm) - -cmocka_test(find_equal_int16 - find_equal_int16.c - ${PROJECT_SOURCE_DIR}/src/math/numbers.c -) - -cmocka_test(find_min_int16 - find_min_int16.c - ${PROJECT_SOURCE_DIR}/src/math/numbers.c -) - -cmocka_test(find_max_abs_int32 - find_max_abs_int32.c - ${PROJECT_SOURCE_DIR}/src/math/numbers.c -) - -cmocka_test(norm_int32 - norm_int32.c - ${PROJECT_SOURCE_DIR}/src/math/numbers.c -) diff --git a/test/cmocka/src/math/numbers/ceil_divide.c b/test/cmocka/src/math/numbers/ceil_divide.c deleted file mode 100644 index 578df9b281b3..000000000000 --- a/test/cmocka/src/math/numbers/ceil_divide.c +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/math/numbers.h> - -#include <stdio.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <math.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_math_numbers_ceil_divide(void **state) -{ - (void)state; - - int params[8] = { - -1000, - 300, - 123, - -10, - 1337, - -6, - 999, - -2 - }; - - int i, j; - - for (i = 0; i < 8; ++i) { - for (j = 0; j < 8; ++j) { - int ref = ceilf((float)params[i] / (float)params[j]); - int r = ceil_divide(params[i], params[j]); - - if (r != ref) { - printf("%s: %d / %d = %d (ref: %d)\n", __func__, - params[i], params[j], r, ref); - } - - assert_int_equal(r, ref); - } - } - -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_math_numbers_ceil_divide) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/numbers/find_equal_int16.c b/test/cmocka/src/math/numbers/find_equal_int16.c deleted file mode 100644 index fc202f50f75b..000000000000 --- a/test/cmocka/src/math/numbers/find_equal_int16.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/math/numbers.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_math_numbers_find_equal_int16_for_5_123_5_10_123_500_123_n_123_equals_1_4_and_6 - (void **state) -{ - (void)state; - - int16_t r[4]; - int16_t vec[] = {5, 123, 5, 10, 123, 500, 123}; - int16_t template[] = {1, 4, 6}; - - int r_num = find_equal_int16(r, vec, 123, 7, 4); - - assert_int_equal(r_num, 3); - assert_memory_equal(r, template, sizeof(int16_t) * 3); -} - -static void test_math_numbers_find_equal_int16_for_1_2_3_4_5_n_0_equals_nothing - (void **state) -{ - (void)state; - - int16_t r[4]; - int16_t vec[] = {1, 2, 3, 4, 5}; - - int r_num = find_equal_int16(r, vec, 0, 5, 4); - - assert_int_equal(r_num, 0); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test - (test_math_numbers_find_equal_int16_for_5_123_5_10_123_500_123_n_123_equals_1_4_and_6), - cmocka_unit_test - (test_math_numbers_find_equal_int16_for_1_2_3_4_5_n_0_equals_nothing) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/numbers/find_max_abs_int32.c b/test/cmocka/src/math/numbers/find_max_abs_int32.c deleted file mode 100644 index 7e65493aaa68..000000000000 --- a/test/cmocka/src/math/numbers/find_max_abs_int32.c +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/math/numbers.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_math_numbers_find_max_abs_int32_for_neg100_99_98_50_equals_100 - (void **state) -{ - (void)state; - - int32_t vec[] = {-100, 99, 98, 50}; - int r = find_max_abs_int32(vec, sizeof(vec) / sizeof(int32_t)); - - assert_int_equal(r, 100); -} - -static void test_math_numbers_find_max_abs_int32_for_neg100_99_98_50_101_equals_101 - (void **state) -{ - (void)state; - - int32_t vec[] = {-100, 99, 98, 50, 101}; - int r = find_max_abs_int32(vec, sizeof(vec) / sizeof(int32_t)); - - assert_int_equal(r, 101); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test - (test_math_numbers_find_max_abs_int32_for_neg100_99_98_50_equals_100), - cmocka_unit_test - (test_math_numbers_find_max_abs_int32_for_neg100_99_98_50_101_equals_101) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/numbers/find_min_int16.c b/test/cmocka/src/math/numbers/find_min_int16.c deleted file mode 100644 index 2e08b729ef50..000000000000 --- a/test/cmocka/src/math/numbers/find_min_int16.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/math/numbers.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_math_numbers_find_min_int16_for_2_equals_2(void **state) -{ - (void)state; - - int16_t vec[] = {2}; - int r = find_min_int16(vec, sizeof(vec) / sizeof(int16_t)); - - assert_int_equal(r, 2); -} - -static void test_math_numbers_find_min_int16_for_5_2_3_4_1_equals_1 - (void **state) -{ - (void)state; - - int16_t vec[] = {5, 2, 3, 4, 1}; - int r = find_min_int16(vec, sizeof(vec) / sizeof(int16_t)); - - assert_int_equal(r, 1); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test - (test_math_numbers_find_min_int16_for_2_equals_2), - cmocka_unit_test - (test_math_numbers_find_min_int16_for_5_2_3_4_1_equals_1) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/numbers/gcd.c b/test/cmocka/src/math/numbers/gcd.c deleted file mode 100644 index 8fcab94fc948..000000000000 --- a/test/cmocka/src/math/numbers/gcd.c +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Marcin Maka <marcin.maka@linux.intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include <sof/math/numbers.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_math_numbers_gcd_for_5083_and_391_equals_391(void **state) -{ - int r; - - (void) state; - - r = gcd(5083, 391); - assert_int_equal(r, 391); -} - -static void test_math_numbers_gcd_for_12_and_9_equals_3(void **state) -{ - int r; - - (void) state; - - r = gcd(12, 9); - assert_int_equal(r, 3); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test - (test_math_numbers_gcd_for_5083_and_391_equals_391), - cmocka_unit_test(test_math_numbers_gcd_for_12_and_9_equals_3), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/numbers/norm_int32.c b/test/cmocka/src/math/numbers/norm_int32.c deleted file mode 100644 index 7397d2359c7a..000000000000 --- a/test/cmocka/src/math/numbers/norm_int32.c +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <sof/math/numbers.h> - -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <stdint.h> -#include <cmocka.h> - -static void test_math_numbers_norm_int32_for_0_equals_31(void **state) -{ - (void)state; - - int r = norm_int32(0); - - assert_int_equal(r, 31); -} - -static void test_math_numbers_norm_int32_for_35_equals_10(void **state) -{ - (void)state; - - int r = norm_int32(35); - - assert_int_equal(r, 25); -} - -static void test_math_numbers_norm_int32_for_2147483647_equals_0(void **state) -{ - (void)state; - - int r = norm_int32(2147483647); - - assert_int_equal(r, 0); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_math_numbers_norm_int32_for_0_equals_31), - cmocka_unit_test - (test_math_numbers_norm_int32_for_35_equals_10), - cmocka_unit_test - (test_math_numbers_norm_int32_for_2147483647_equals_0) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/trig/CMakeLists.txt b/test/cmocka/src/math/trig/CMakeLists.txt deleted file mode 100644 index 96c893ec7c89..000000000000 --- a/test/cmocka/src/math/trig/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmocka_test(sin_fixed - sin_fixed.c - ${PROJECT_SOURCE_DIR}/src/math/trig.c -) diff --git a/test/cmocka/src/math/trig/sin_fixed.c b/test/cmocka/src/math/trig/sin_fixed.c deleted file mode 100644 index b6c1e1b2884d..000000000000 --- a/test/cmocka/src/math/trig/sin_fixed.c +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> - -#include <stdio.h> -#include <stdint.h> -#include <stdarg.h> -#include <stddef.h> -#include <setjmp.h> -#include <math.h> -#include <cmocka.h> - -#include <sof/audio/format.h> -#include <sof/math/trig.h> - -#define CMP_TOLERANCE 0.000005 - -/* Reference table generated by sin(), gcc-4.3.2 */ -static const float sin_ref_table[] = { - 0.0000000000, 0.0174524064, 0.0348994967, 0.0523359562, - 0.0697564737, 0.0871557427, 0.1045284633, 0.1218693434, - 0.1391731010, 0.1564344650, 0.1736481777, 0.1908089954, - 0.2079116908, 0.2249510543, 0.2419218956, 0.2588190451, - 0.2756373558, 0.2923717047, 0.3090169944, 0.3255681545, - 0.3420201433, 0.3583679495, 0.3746065934, 0.3907311285, - 0.4067366431, 0.4226182617, 0.4383711468, 0.4539904997, - 0.4694715628, 0.4848096202, 0.5000000000, 0.5150380749, - 0.5299192642, 0.5446390350, 0.5591929035, 0.5735764364, - 0.5877852523, 0.6018150232, 0.6156614753, 0.6293203910, - 0.6427876097, 0.6560590290, 0.6691306064, 0.6819983601, - 0.6946583705, 0.7071067812, 0.7193398003, 0.7313537016, - 0.7431448255, 0.7547095802, 0.7660444431, 0.7771459615, - 0.7880107536, 0.7986355100, 0.8090169944, 0.8191520443, - 0.8290375726, 0.8386705679, 0.8480480962, 0.8571673007, - 0.8660254038, 0.8746197071, 0.8829475929, 0.8910065242, - 0.8987940463, 0.9063077870, 0.9135454576, 0.9205048535, - 0.9271838546, 0.9335804265, 0.9396926208, 0.9455185756, - 0.9510565163, 0.9563047560, 0.9612616959, 0.9659258263, - 0.9702957263, 0.9743700648, 0.9781476007, 0.9816271834, - 0.9848077530, 0.9876883406, 0.9902680687, 0.9925461516, - 0.9945218954, 0.9961946981, 0.9975640503, 0.9986295348, - 0.9993908270, 0.9998476952, 1.0000000000, 0.9998476952, - 0.9993908270, 0.9986295348, 0.9975640503, 0.9961946981, - 0.9945218954, 0.9925461516, 0.9902680687, 0.9876883406, - 0.9848077530, 0.9816271834, 0.9781476007, 0.9743700648, - 0.9702957263, 0.9659258263, 0.9612616959, 0.9563047560, - 0.9510565163, 0.9455185756, 0.9396926208, 0.9335804265, - 0.9271838546, 0.9205048535, 0.9135454576, 0.9063077870, - 0.8987940463, 0.8910065242, 0.8829475929, 0.8746197071, - 0.8660254038, 0.8571673007, 0.8480480962, 0.8386705679, - 0.8290375726, 0.8191520443, 0.8090169944, 0.7986355100, - 0.7880107536, 0.7771459615, 0.7660444431, 0.7547095802, - 0.7431448255, 0.7313537016, 0.7193398003, 0.7071067812, - 0.6946583705, 0.6819983601, 0.6691306064, 0.6560590290, - 0.6427876097, 0.6293203910, 0.6156614753, 0.6018150232, - 0.5877852523, 0.5735764364, 0.5591929035, 0.5446390350, - 0.5299192642, 0.5150380749, 0.5000000000, 0.4848096202, - 0.4694715628, 0.4539904997, 0.4383711468, 0.4226182617, - 0.4067366431, 0.3907311285, 0.3746065934, 0.3583679495, - 0.3420201433, 0.3255681545, 0.3090169944, 0.2923717047, - 0.2756373558, 0.2588190451, 0.2419218956, 0.2249510543, - 0.2079116908, 0.1908089954, 0.1736481777, 0.1564344650, - 0.1391731010, 0.1218693434, 0.1045284633, 0.0871557427, - 0.0697564737, 0.0523359562, 0.0348994967, 0.0174524064, - 0.0000000000, -0.0174524064, -0.0348994967, -0.0523359562, - -0.0697564737, -0.0871557427, -0.1045284633, -0.1218693434, - -0.1391731010, -0.1564344650, -0.1736481777, -0.1908089954, - -0.2079116908, -0.2249510543, -0.2419218956, -0.2588190451, - -0.2756373558, -0.2923717047, -0.3090169944, -0.3255681545, - -0.3420201433, -0.3583679495, -0.3746065934, -0.3907311285, - -0.4067366431, -0.4226182617, -0.4383711468, -0.4539904997, - -0.4694715628, -0.4848096202, -0.5000000000, -0.5150380749, - -0.5299192642, -0.5446390350, -0.5591929035, -0.5735764364, - -0.5877852523, -0.6018150232, -0.6156614753, -0.6293203910, - -0.6427876097, -0.6560590290, -0.6691306064, -0.6819983601, - -0.6946583705, -0.7071067812, -0.7193398003, -0.7313537016, - -0.7431448255, -0.7547095802, -0.7660444431, -0.7771459615, - -0.7880107536, -0.7986355100, -0.8090169944, -0.8191520443, - -0.8290375726, -0.8386705679, -0.8480480962, -0.8571673007, - -0.8660254038, -0.8746197071, -0.8829475929, -0.8910065242, - -0.8987940463, -0.9063077870, -0.9135454576, -0.9205048535, - -0.9271838546, -0.9335804265, -0.9396926208, -0.9455185756, - -0.9510565163, -0.9563047560, -0.9612616959, -0.9659258263, - -0.9702957263, -0.9743700648, -0.9781476007, -0.9816271834, - -0.9848077530, -0.9876883406, -0.9902680687, -0.9925461516, - -0.9945218954, -0.9961946981, -0.9975640503, -0.9986295348, - -0.9993908270, -0.9998476952, -1.0000000000, -0.9998476952, - -0.9993908270, -0.9986295348, -0.9975640503, -0.9961946981, - -0.9945218954, -0.9925461516, -0.9902680687, -0.9876883406, - -0.9848077530, -0.9816271834, -0.9781476007, -0.9743700648, - -0.9702957263, -0.9659258263, -0.9612616959, -0.9563047560, - -0.9510565163, -0.9455185756, -0.9396926208, -0.9335804265, - -0.9271838546, -0.9205048535, -0.9135454576, -0.9063077870, - -0.8987940463, -0.8910065242, -0.8829475929, -0.8746197071, - -0.8660254038, -0.8571673007, -0.8480480962, -0.8386705679, - -0.8290375726, -0.8191520443, -0.8090169944, -0.7986355100, - -0.7880107536, -0.7771459615, -0.7660444431, -0.7547095802, - -0.7431448255, -0.7313537016, -0.7193398003, -0.7071067812, - -0.6946583705, -0.6819983601, -0.6691306064, -0.6560590290, - -0.6427876097, -0.6293203910, -0.6156614753, -0.6018150232, - -0.5877852523, -0.5735764364, -0.5591929035, -0.5446390350, - -0.5299192642, -0.5150380749, -0.5000000000, -0.4848096202, - -0.4694715628, -0.4539904997, -0.4383711468, -0.4226182617, - -0.4067366431, -0.3907311285, -0.3746065934, -0.3583679495, - -0.3420201433, -0.3255681545, -0.3090169944, -0.2923717047, - -0.2756373558, -0.2588190451, -0.2419218956, -0.2249510543, - -0.2079116908, -0.1908089954, -0.1736481777, -0.1564344650, - -0.1391731010, -0.1218693434, -0.1045284633, -0.0871557427, - -0.0697564737, -0.0523359562, -0.0348994967, -0.0174524064 -}; - -static void test_math_trig_sin_fixed(void **state) -{ - (void)state; - - int theta; - - for (theta = 0; theta < 360; ++theta) { - double rad = M_PI / (180.0 / theta); - int32_t rad_q28 = Q_CONVERT_FLOAT(rad, 28); - - float r = Q_CONVERT_QTOF(sin_fixed(rad_q28), 31); - float diff = fabsf(sin_ref_table[theta] - r); - - if (diff > CMP_TOLERANCE) { - printf("%s: diff for %d deg = %.10f\n", __func__, - theta, diff); - } - - assert_true(diff <= CMP_TOLERANCE); - } -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test(test_math_trig_sin_fixed) - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/math/window/CMakeLists.txt b/test/cmocka/src/math/window/CMakeLists.txt new file mode 100644 index 000000000000..0d4365694523 --- /dev/null +++ b/test/cmocka/src/math/window/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmocka_test(window + window.c + ${PROJECT_SOURCE_DIR}/src/math/window.c + ${PROJECT_SOURCE_DIR}/src/math/trig.c + ${PROJECT_SOURCE_DIR}/src/math/log_e.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c + ${PROJECT_SOURCE_DIR}/src/math/decibels.c +) diff --git a/test/cmocka/src/math/window/mfcc_blackman.m b/test/cmocka/src/math/window/mfcc_blackman.m new file mode 100644 index 000000000000..b3b6be62f993 --- /dev/null +++ b/test/cmocka/src/math/window/mfcc_blackman.m @@ -0,0 +1,30 @@ +% win = mfcc_blackman(length, a0) +% +% Input +% length - length of window +% a0 - optional, parameter a0 for equation +% +% Output +% window coefficients +% +% https://en.wikipedia.org/wiki/Window_function#Blackman_window + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function w = mfcc_blackman(win_length, a0) + + if nargin < 2 + a0 = 0.42; % Default in Kaldi compute-mfcc-feats + end + + alpha = 1 - 2 * a0; + a1 = 1/2; + a2 = alpha / 2; + + n = (0:(win_length - 1))'; + a = 2 * pi / (win_length -1); + w = a0 - a1 * cos(a * n ) + a2 * cos(2 * a * n / win_length); + +end diff --git a/test/cmocka/src/math/window/mfcc_povey.m b/test/cmocka/src/math/window/mfcc_povey.m new file mode 100644 index 000000000000..9c993326d719 --- /dev/null +++ b/test/cmocka/src/math/window/mfcc_povey.m @@ -0,0 +1,24 @@ +% win = mfcc_povey(length) +% +% Input +% length +% +% Output +% window coefficients +% +% https://kaldi-asr.org/doc/feature-window_8h_source.html +% +% "povey is a window I made to be similar to Hamming but to go to +% zero at the edges" + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2022, Intel Corporation. All rights reserved. + +function w = mfcc_povey(win_length) + + n = (0:(win_length - 1))'; + a = 2 * pi / (win_length - 1); + w = (0.5 - 0.5 * cos(a * n)) .^ 0.85; + +end diff --git a/test/cmocka/src/math/window/ref_window.m b/test/cmocka/src/math/window/ref_window.m new file mode 100644 index 000000000000..dacc85cc1488 --- /dev/null +++ b/test/cmocka/src/math/window/ref_window.m @@ -0,0 +1,65 @@ +%% SPDX-License-Identifier: BSD-3-Clause +%% +%% Copyright(c) 2022 Intel Corporation. All rights reserved. + +function ref_window() + + get_ref_window('rectangular', 'ref_window_rectangular.h', 16); + get_ref_window('blackman', 'ref_window_blackman.h', 160); + get_ref_window('hamming', 'ref_window_hamming.h', 256); + get_ref_window('povey', 'ref_window_povey.h', 200); + +end + +function get_ref_window(wname, headerfn, wlength) + + switch lower(wname) + case 'rectangular' + win = boxcar(wlength); + case 'blackman' + win = mfcc_blackman(wlength); + case 'hamming' + win = hamming(wlength); + case 'povey' + win = mfcc_povey(wlength); + otherwise + fprintf(1, 'Illegal window name %s. ', wname); + error('Failed.'); + end + + qwin = quant_s16(win); + vn = sprintf('ref_%s', lower(wname)); + dn = sprintf('LENGTH_%s', upper(wname)); + export_headerfile(headerfn, vn, dn, qwin); + fprintf(1, 'Exported %s\n', headerfn); + +end + +function y = quant_s16(x) + + scale = 2^15; + intmax = scale - 1; + intmin = -scale; + + y = max(min(round(x * scale), intmax), intmin); +end + +function export_headerfile(headerfn, vn, dn, win) + + fh = fopen(headerfn, 'w'); + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s Intel Corporation. All rights reserved.\n', ... + datestr(now, 'yyyy')); + fprintf(fh, ' */\n\n'); + fprintf(fh, '#define %s %d\n\n', dn, length(win)); + fprintf(fh, 'static const int16_t %s[%s] = {\n', vn, dn); + + for i = 1:length(win) + fprintf(fh, '\t%d,\n', win(i)); + end + + fprintf(fh, '};\n'); + fclose(fh); + +end diff --git a/test/cmocka/src/math/window/ref_window_blackman.h b/test/cmocka/src/math/window/ref_window_blackman.h new file mode 100644 index 000000000000..5a5a27f55ccc --- /dev/null +++ b/test/cmocka/src/math/window/ref_window_blackman.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#define LENGTH_BLACKMAN 160 + +static const int16_t ref_blackman[LENGTH_BLACKMAN] = { + 0, + 13, + 51, + 115, + 204, + 319, + 458, + 623, + 812, + 1025, + 1263, + 1524, + 1808, + 2115, + 2444, + 2795, + 3167, + 3560, + 3973, + 4405, + 4856, + 5325, + 5811, + 6314, + 6832, + 7366, + 7913, + 8474, + 9047, + 9631, + 10226, + 10831, + 11444, + 12065, + 12693, + 13326, + 13965, + 14607, + 15251, + 15898, + 16545, + 17192, + 17838, + 18482, + 19122, + 19758, + 20389, + 21013, + 21631, + 22240, + 22840, + 23429, + 24008, + 24575, + 25129, + 25670, + 26196, + 26706, + 27201, + 27678, + 28138, + 28580, + 29003, + 29406, + 29788, + 30150, + 30490, + 30808, + 31104, + 31376, + 31625, + 31851, + 32052, + 32229, + 32381, + 32508, + 32610, + 32686, + 32737, + 32763, + 32763, + 32737, + 32686, + 32609, + 32507, + 32380, + 32228, + 32051, + 31850, + 31624, + 31375, + 31102, + 30807, + 30489, + 30148, + 29787, + 29404, + 29001, + 28578, + 28137, + 27676, + 27199, + 26704, + 26193, + 25667, + 25127, + 24572, + 24005, + 23426, + 22837, + 22237, + 21627, + 21010, + 20385, + 19755, + 19118, + 18478, + 17834, + 17189, + 16541, + 15894, + 15247, + 14602, + 13960, + 13322, + 12688, + 12060, + 11439, + 10826, + 10221, + 9626, + 9041, + 8468, + 7908, + 7360, + 6827, + 6308, + 5805, + 5319, + 4850, + 4399, + 3967, + 3554, + 3161, + 2788, + 2437, + 2108, + 1801, + 1517, + 1256, + 1018, + 805, + 615, + 451, + 311, + 197, + 107, + 43, + 5, + -8, +}; diff --git a/test/cmocka/src/math/window/ref_window_hamming.h b/test/cmocka/src/math/window/ref_window_hamming.h new file mode 100644 index 000000000000..74da18a77ead --- /dev/null +++ b/test/cmocka/src/math/window/ref_window_hamming.h @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#define LENGTH_HAMMING 256 + +static const int16_t ref_hamming[LENGTH_HAMMING] = { + 2621, + 2626, + 2640, + 2663, + 2695, + 2736, + 2786, + 2845, + 2913, + 2991, + 3077, + 3172, + 3276, + 3388, + 3509, + 3639, + 3778, + 3925, + 4080, + 4243, + 4415, + 4595, + 4782, + 4978, + 5181, + 5392, + 5610, + 5836, + 6069, + 6309, + 6555, + 6809, + 7069, + 7336, + 7609, + 7888, + 8173, + 8464, + 8760, + 9062, + 9369, + 9681, + 9998, + 10319, + 10646, + 10976, + 11310, + 11649, + 11991, + 12336, + 12685, + 13037, + 13391, + 13749, + 14108, + 14470, + 14834, + 15199, + 15566, + 15935, + 16304, + 16674, + 17045, + 17416, + 17788, + 18159, + 18530, + 18900, + 19270, + 19639, + 20007, + 20373, + 20738, + 21101, + 21461, + 21820, + 22176, + 22529, + 22879, + 23226, + 23570, + 23910, + 24247, + 24579, + 24907, + 25231, + 25551, + 25865, + 26175, + 26479, + 26778, + 27072, + 27360, + 27642, + 27918, + 28188, + 28451, + 28708, + 28958, + 29202, + 29438, + 29667, + 29889, + 30104, + 30311, + 30510, + 30702, + 30886, + 31061, + 31229, + 31388, + 31539, + 31682, + 31816, + 31942, + 32059, + 32167, + 32266, + 32357, + 32439, + 32511, + 32575, + 32630, + 32675, + 32712, + 32739, + 32758, + 32767, + 32767, + 32758, + 32739, + 32712, + 32675, + 32630, + 32575, + 32511, + 32439, + 32357, + 32266, + 32167, + 32059, + 31942, + 31816, + 31682, + 31539, + 31388, + 31229, + 31061, + 30886, + 30702, + 30510, + 30311, + 30104, + 29889, + 29667, + 29438, + 29202, + 28958, + 28708, + 28451, + 28188, + 27918, + 27642, + 27360, + 27072, + 26778, + 26479, + 26175, + 25865, + 25551, + 25231, + 24907, + 24579, + 24247, + 23910, + 23570, + 23226, + 22879, + 22529, + 22176, + 21820, + 21461, + 21101, + 20738, + 20373, + 20007, + 19639, + 19270, + 18900, + 18530, + 18159, + 17788, + 17416, + 17045, + 16674, + 16304, + 15935, + 15566, + 15199, + 14834, + 14470, + 14108, + 13749, + 13391, + 13037, + 12685, + 12336, + 11991, + 11649, + 11310, + 10976, + 10646, + 10319, + 9998, + 9681, + 9369, + 9062, + 8760, + 8464, + 8173, + 7888, + 7609, + 7336, + 7069, + 6809, + 6555, + 6309, + 6069, + 5836, + 5610, + 5392, + 5181, + 4978, + 4782, + 4595, + 4415, + 4243, + 4080, + 3925, + 3778, + 3639, + 3509, + 3388, + 3276, + 3172, + 3077, + 2991, + 2913, + 2845, + 2786, + 2736, + 2695, + 2663, + 2640, + 2626, + 2621, +}; diff --git a/test/cmocka/src/math/window/ref_window_povey.h b/test/cmocka/src/math/window/ref_window_povey.h new file mode 100644 index 000000000000..40ec66f0941a --- /dev/null +++ b/test/cmocka/src/math/window/ref_window_povey.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#define LENGTH_POVEY 200 + +static const int16_t ref_povey[LENGTH_POVEY] = { + 0, + 28, + 92, + 183, + 299, + 437, + 595, + 772, + 968, + 1181, + 1411, + 1657, + 1918, + 2193, + 2483, + 2786, + 3102, + 3431, + 3772, + 4124, + 4487, + 4861, + 5245, + 5639, + 6042, + 6453, + 6873, + 7301, + 7736, + 8178, + 8627, + 9082, + 9542, + 10007, + 10478, + 10952, + 11431, + 11913, + 12398, + 12886, + 13376, + 13867, + 14360, + 14854, + 15349, + 15843, + 16337, + 16830, + 17322, + 17813, + 18301, + 18787, + 19270, + 19750, + 20227, + 20699, + 21167, + 21631, + 22089, + 22541, + 22988, + 23429, + 23863, + 24290, + 24710, + 25122, + 25527, + 25923, + 26311, + 26689, + 27059, + 27419, + 27770, + 28110, + 28440, + 28760, + 29069, + 29367, + 29654, + 29929, + 30193, + 30444, + 30684, + 30911, + 31126, + 31328, + 31518, + 31694, + 31858, + 32008, + 32145, + 32269, + 32379, + 32476, + 32558, + 32628, + 32683, + 32725, + 32752, + 32766, + 32766, + 32752, + 32725, + 32683, + 32628, + 32558, + 32476, + 32379, + 32269, + 32145, + 32008, + 31858, + 31694, + 31518, + 31328, + 31126, + 30911, + 30684, + 30444, + 30193, + 29929, + 29654, + 29367, + 29069, + 28760, + 28440, + 28110, + 27770, + 27419, + 27059, + 26689, + 26311, + 25923, + 25527, + 25122, + 24710, + 24290, + 23863, + 23429, + 22988, + 22541, + 22089, + 21631, + 21167, + 20699, + 20227, + 19750, + 19270, + 18787, + 18301, + 17813, + 17322, + 16830, + 16337, + 15843, + 15349, + 14854, + 14360, + 13867, + 13376, + 12886, + 12398, + 11913, + 11431, + 10952, + 10478, + 10007, + 9542, + 9082, + 8627, + 8178, + 7736, + 7301, + 6873, + 6453, + 6042, + 5639, + 5245, + 4861, + 4487, + 4124, + 3772, + 3431, + 3102, + 2786, + 2483, + 2193, + 1918, + 1657, + 1411, + 1181, + 968, + 772, + 595, + 437, + 299, + 183, + 92, + 28, + 0, +}; diff --git a/test/cmocka/src/math/window/ref_window_rectangular.h b/test/cmocka/src/math/window/ref_window_rectangular.h new file mode 100644 index 000000000000..74503d74e250 --- /dev/null +++ b/test/cmocka/src/math/window/ref_window_rectangular.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#define LENGTH_RECTANGULAR 16 + +static const int16_t ref_rectangular[LENGTH_RECTANGULAR] = { + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, + 32767, +}; diff --git a/test/cmocka/src/math/window/window.c b/test/cmocka/src/math/window/window.c new file mode 100644 index 000000000000..82e0f66a6bec --- /dev/null +++ b/test/cmocka/src/math/window/window.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <string.h> +#include <cmocka.h> +#include <math.h> +#include <sof/math/window.h> + +#include "ref_window_rectangular.h" +#include "ref_window_blackman.h" +#include "ref_window_hamming.h" +#include "ref_window_povey.h" + +#define MAX_ERR_RMS 1.0 +#define MAX_STR_SIZE 256 +#define MAX_WIN_LENGTH 4096 +#undef DEBUG_FILES /* Change to #define to get file output */ + +static float window_delta_rms(const int16_t *ref_win, int16_t *win, int win_length) +{ + float err_squared = 0.0; + int i; + + for (i = 0; i < win_length; i++) { + err_squared += ((float)ref_win[i] - (float)win[i]) * + ((float)ref_win[i] - (float)win[i]); + } + + return sqrt(err_squared / (float)win_length); +} + +static float test_window(char *window_name, const int16_t *ref_win, int window_length) +{ + float err_rms; + int16_t *win; + + win = malloc(window_length * sizeof(int16_t)); + if (!win) { + fprintf(stderr, "Failed to allocate reference window.\n"); + exit(EXIT_FAILURE); + } + + /* calculate window and get RMS error vs. reference */ + if (!strcmp(window_name, "rectangular")) { + win_rectangular_16b(win, window_length); + } else if (!strcmp(window_name, "blackman")) { + win_blackman_16b(win, window_length, WIN_BLACKMAN_A0_Q15); + } else if (!strcmp(window_name, "hamming")) { + win_hamming_16b(win, window_length); + } else if (!strcmp(window_name, "povey")) { + win_povey_16b(win, window_length); + } else { + fprintf(stderr, "Illegal window %s.\n", window_name); + free(win); + exit(EXIT_FAILURE); + } + +#ifdef DEBUG_FILES + FILE *fh; + int i; + + fh = fopen("window.txt", "w"); + for (i = 0; i < window_length; i++) + fprintf(fh, "%d %d\n", win[i], ref_win[i]); + + fclose(fh); +#endif + + err_rms = window_delta_rms(ref_win, win, window_length); + printf("Window %s RMS error = %5.2f LSB (max %5.2f)\n", window_name, err_rms, MAX_ERR_RMS); + free(win); + return err_rms; +} + +static void test_math_window_rectangular(void **state) +{ + float err_rms; + + (void)state; + + err_rms = test_window("rectangular", ref_rectangular, LENGTH_RECTANGULAR); + assert_true(err_rms < MAX_ERR_RMS); +} + +static void test_math_window_blackman(void **state) +{ + float err_rms; + + (void)state; + + err_rms = test_window("blackman", ref_blackman, LENGTH_BLACKMAN); + assert_true(err_rms < MAX_ERR_RMS); +} + +static void test_math_window_hamming(void **state) +{ + float err_rms; + + (void)state; + + err_rms = test_window("hamming", ref_hamming, LENGTH_HAMMING); + assert_true(err_rms < MAX_ERR_RMS); +} + +static void test_math_window_povey(void **state) +{ + float err_rms; + + (void)state; + + err_rms = test_window("povey", ref_povey, LENGTH_POVEY); + assert_true(err_rms < MAX_ERR_RMS); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_window_rectangular), + cmocka_unit_test(test_math_window_blackman), + cmocka_unit_test(test_math_window_hamming), + cmocka_unit_test(test_math_window_povey), + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/notifier_mocks.c b/test/cmocka/src/notifier_mocks.c index 07557bbca1cc..bfdb0d488ffe 100644 --- a/test/cmocka/src/notifier_mocks.c +++ b/test/cmocka/src/notifier_mocks.c @@ -6,7 +6,7 @@ #include <stdint.h> #include <stdlib.h> -#include <sof/lib/alloc.h> +#include <rtos/alloc.h> #include <sof/lib/notifier.h> #include <sof/list.h> #include <sof/common.h> @@ -50,7 +50,7 @@ void notifier_event(const void *caller, enum notify_id type, uint32_t core_mask, } int notifier_register(void *receiver, void *caller, enum notify_id type, - void (*cb)(void *arg, enum notify_id type, void *data)) + void (*cb)(void *arg, enum notify_id type, void *data), uint32_t flags) { struct notify *notify = *arch_notify_get(); struct callback_handle *handle; @@ -58,7 +58,7 @@ int notifier_register(void *receiver, void *caller, enum notify_id type, if (type >= NOTIFIER_ID_COUNT) return -EINVAL; - handle = rzalloc(0, 0, 0, sizeof(struct callback_handle)); + handle = rzalloc(SOF_MEM_FLAG_USER, sizeof(struct callback_handle)); if (!handle) return -ENOMEM; diff --git a/test/cmocka/src/util.h b/test/cmocka/src/util.h new file mode 100644 index 000000000000..38561e81e42e --- /dev/null +++ b/test/cmocka/src/util.h @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Daniel Bogdzia <danielx.bogdzia@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <rtos/sof.h> +#include <sof/audio/component.h> +#include <rtos/alloc.h> + +#include <stdlib.h> + +static inline struct comp_buffer *create_test_sink(struct comp_dev *dev, + uint32_t pipeline_id, + uint32_t frame_fmt, + uint16_t channels, + uint16_t buffer_size) +{ + struct sof_ipc_buffer desc = { + .comp = { + .pipeline_id = pipeline_id, + }, + .size = buffer_size, + }; + struct comp_buffer *buffer = buffer_new(NULL, &desc, BUFFER_USAGE_NOT_SHARED); + + memset(buffer->stream.addr, 0, buffer_size); + + /* set bsink list */ + if (dev) + list_item_append(&buffer->source_list, &dev->bsink_list); + + /* alloc sink and set default parameters */ + buffer->sink = calloc(1, sizeof(struct comp_dev)); + buffer->sink->state = COMP_STATE_PREPARE; + audio_stream_set_frm_fmt(&buffer->stream, frame_fmt); + audio_stream_set_channels(&buffer->stream, channels); + + return buffer; +} + +static inline void free_test_sink(struct comp_buffer *buffer) +{ + free(comp_buffer_get_sink_component(buffer)); + buffer_free(buffer); +} + +static inline struct comp_buffer *create_test_source(struct comp_dev *dev, + uint32_t pipeline_id, + uint32_t frame_fmt, + uint16_t channels, + uint16_t buffer_size) +{ + struct sof_ipc_buffer desc = { + .comp = { + .pipeline_id = pipeline_id, + }, + .size = buffer_size, + }; + struct comp_buffer *buffer = buffer_new(NULL, &desc, BUFFER_USAGE_NOT_SHARED); + + memset(buffer->stream.addr, 0, buffer_size); + + /*set bsource list */ + if (dev) + list_item_append(&buffer->sink_list, &dev->bsource_list); + + /* alloc source and set default parameters */ + buffer->source = calloc(1, sizeof(struct comp_dev)); + buffer->source->state = COMP_STATE_PREPARE; + audio_stream_set_frm_fmt(&buffer->stream, frame_fmt); + audio_stream_set_channels(&buffer->stream, channels); + + return buffer; +} + +static inline void free_test_source(struct comp_buffer *buffer) +{ + free(buffer->source); + buffer_free(buffer); +} diff --git a/test/test-all-defconfigs.sh b/test/test-all-defconfigs.sh new file mode 100755 index 000000000000..aaba127833b8 --- /dev/null +++ b/test/test-all-defconfigs.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +set -e + +# Absolute +SOFTOP=$(cd "$(dirname "$0")"/.. && pwd) + +# Relative +BUILDTOP=build_ut_defs + +rebuild_config() +{ + local conf="$1" + mkdir -p "$BUILDTOP" + printf '\n ========= Building native cmocka tests for %s ======\n\n' "$conf" + + ( set -x + cmake -DINIT_CONFIG="$conf" -S "$SOFTOP" -B "$BUILDTOP"/"$conf" \ + -DBUILD_UNIT_TESTS=ON \ + -DBUILD_UNIT_TESTS_HOST=ON + + cmake --build "$BUILDTOP"/"$conf" -- -j"$(nproc)" + ) +} + +main() +{ + local defconfig + + # First make sure all configurations build + for d in "$SOFTOP"/src/arch/xtensa/configs/*_defconfig; do + defconfig=$(basename "$d") + rebuild_config "$defconfig" + done + + # Now run all the tests + for d in "$BUILDTOP"/*_defconfig; do + printf '\n\n ========= Running native cmocka tests in %s ======\n\n' "$d" + ( set -x + cmake --build "$d" -- test + ) + done +} + +main "$@" diff --git a/test/ztest/unit/common/alloc.c b/test/ztest/unit/common/alloc.c new file mode 100644 index 000000000000..d00dc3c7b831 --- /dev/null +++ b/test/ztest/unit/common/alloc.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* Copyright(c) 2026 Intel Corporation. All rights reserved. */ + +#include <zephyr/ztest.h> +#include <sof/common.h> + +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +void *__wrap_rzalloc(uint32_t flags, size_t bytes) +{ + void *ret; + (void)flags; + + ret = malloc(bytes); + + zassert_not_null(ret, "Memory allocation should not fail"); + + memset(ret, 0, bytes); + + return ret; +} + +void __wrap_rfree(void *ptr) +{ + free(ptr); +} + +struct k_heap; +void *__wrap_sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, size_t alignment) +{ + void *ret; + + (void)flags; + (void)heap; + + if (alignment) + ret = aligned_alloc(alignment, ALIGN_UP(bytes, alignment)); + else + ret = malloc(bytes); + + zassert_not_null(ret, "Memory allocation should not fail"); + + return ret; +} + +void __wrap_sof_heap_free(struct k_heap *heap, void *ptr) +{ + (void)heap; + + free(ptr); +} + +struct k_heap *__wrap_sof_sys_heap_get(void) +{ + return NULL; +} diff --git a/test/ztest/unit/fast-get/CMakeLists.txt b/test/ztest/unit/fast-get/CMakeLists.txt new file mode 100644 index 000000000000..39b79142d8bd --- /dev/null +++ b/test/ztest/unit/fast-get/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_fast_get) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../..") + +# Include SOF CMake functions +include(${SOF_ROOT}/scripts/cmake/misc.cmake) + +target_include_directories(app PRIVATE + ${SOF_ROOT}/zephyr/include + ${SOF_ROOT}/src/include + ${SOF_ROOT}/src/platform/posix/include +) + +# Define SOF-specific configurations for unit testing +target_compile_definitions(app PRIVATE + -DCONFIG_ZEPHYR_POSIX=1 +) + +target_sources(app PRIVATE + test_fast_get_ztest.c + ${SOF_ROOT}/src/lib/objpool.c + ${SOF_ROOT}/zephyr/lib/fast-get.c + ${SOF_ROOT}/test/ztest/unit/common/alloc.c +) + +target_link_libraries(app PRIVATE "-Wl,--wrap=rzalloc,--wrap=rfree,--wrap=sof_heap_alloc,--wrap=sof_heap_free") + +# Add RELATIVE_FILE definitions for SOF trace functionality +sof_append_relative_path_definitions(app) diff --git a/test/ztest/unit/fast-get/prj.conf b/test/ztest/unit/fast-get/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/fast-get/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/fast-get/test_fast_get_ztest.c b/test/ztest/unit/fast-get/test_fast_get_ztest.c new file mode 100644 index 000000000000..3022d80e5ab7 --- /dev/null +++ b/test/ztest/unit/fast-get/test_fast_get_ztest.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. + +#include <zephyr/ztest.h> +#include <sof/common.h> +#include <sof/lib/fast-get.h> +#include <stdlib.h> + +static const int testdata[33][100] = { + { + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 0, + }, + { 2 }, + { 3 }, + { 4 }, + { 5 }, + { 6 }, + { 7 }, + { 8 }, + { 9 }, + { 10 }, + { 11 }, + { 12 }, + { 13 }, + { 14 }, + { 15 }, + { 16 }, + { 17 }, + { 18 }, + { 19 }, + { 20 }, + { 21 }, + { 23 }, + { 24 }, + { 25 }, + { 26 }, + { 27 }, + { 28 }, + { 29 }, + { 30 }, + { 31 }, + { 32 }, + { 33 }, +}; + +/** + * @brief Test basic fast_get and fast_put functionality + * + * Tests that fast_get can allocate memory for data and fast_put can free it. + * Verifies that the returned pointer is valid and data is correctly copied. + */ +ZTEST(fast_get_suite, test_simple_fast_get_put) +{ + const void *ret; + + ret = fast_get(NULL, testdata[0], sizeof(testdata[0])); + + zassert_not_null(ret, "fast_get should return valid pointer"); + zassert_mem_equal(ret, testdata[0], sizeof(testdata[0]), + "Returned data should match original data"); + + fast_put(NULL, NULL, ret); +} + +/** + * @brief Test fast_get size mismatch behavior + * + * Tests that fast_get returns NULL when requested size doesn't match + * previously allocated size for the same data pointer. + */ +ZTEST(fast_get_suite, test_fast_get_size_missmatch_test) +{ + const void *ret[2]; + + ret[0] = fast_get(NULL, testdata[0], sizeof(testdata[0])); + + zassert_not_null(ret[0], "First fast_get should succeed"); + zassert_mem_equal(ret[0], testdata[0], sizeof(testdata[0]), + "Returned data should match original data"); + + ret[1] = fast_get(NULL, testdata[0], sizeof(testdata[0]) + 1); + zassert_is_null(ret[1], "fast_get with different size should return NULL"); + + fast_put(NULL, NULL, ret[0]); +} + +/** + * @brief Test multiple fast_get and fast_put operations + * + * Tests that fast_get can handle more than 32 allocations and that + * all data is correctly stored and can be retrieved. + */ +ZTEST(fast_get_suite, test_over_32_fast_gets_and_puts) +{ + const void *copy[ARRAY_SIZE(testdata)]; + int i; + + for (i = 0; i < ARRAY_SIZE(copy); i++) + copy[i] = fast_get(NULL, testdata[i], sizeof(testdata[0])); + + for (i = 0; i < ARRAY_SIZE(copy); i++) + zassert_mem_equal(copy[i], testdata[i], sizeof(testdata[0]), + "Data at index %d should match original", i); + + for (i = 0; i < ARRAY_SIZE(copy); i++) + fast_put(NULL, NULL, copy[i]); +} + +/** + * @brief Test fast_get reference counting functionality + * + * Tests that fast_get implements proper reference counting - multiple + * fast_get calls for the same data should return the same pointer, + * and the data should remain valid until all references are released. + */ +ZTEST(fast_get_suite, test_fast_get_refcounting) +{ + const void *copy[2][ARRAY_SIZE(testdata)]; + int i; + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + copy[0][i] = fast_get(NULL, testdata[i], sizeof(testdata[0])); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + copy[1][i] = fast_get(NULL, testdata[i], sizeof(testdata[0])); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + zassert_equal_ptr(copy[0][i], copy[1][i], + "Same data should return same pointer (refcounting)"); + + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + zassert_mem_equal(copy[0][i], testdata[i], sizeof(testdata[0]), + "Data should match original after multiple fast_get calls"); + + /* Release first set of references */ + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + fast_put(NULL, NULL, copy[0][i]); + + /* Data should still be valid through second set of references */ + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + zassert_mem_equal(copy[1][i], testdata[i], sizeof(testdata[0]), + "Data should remain valid after partial fast_put"); + + /* Release second set of references */ + for (i = 0; i < ARRAY_SIZE(copy[0]); i++) + fast_put(NULL, NULL, copy[1][i]); +} + +/** + * @brief Define and initialize the fast_get test suite + */ +ZTEST_SUITE(fast_get_suite, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/fast-get/testcase.yaml b/test/ztest/unit/fast-get/testcase.yaml new file mode 100644 index 000000000000..e3648bfc4e5d --- /dev/null +++ b/test/ztest/unit/fast-get/testcase.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2025 Intel Corporation. All rights reserved. +# +# These contents may have been developed with support from one or more Intel-operated +# generative artificial intelligence solutions. + +tests: + sof.unit.fast_get: + tags: fast_get memory cache + platform_allow: native_sim + integration_platforms: + - native_sim + build_only: false diff --git a/test/ztest/unit/list/CMakeLists.txt b/test/ztest/unit/list/CMakeLists.txt new file mode 100644 index 000000000000..a6ecea3a7ae1 --- /dev/null +++ b/test/ztest/unit/list/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_list) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../..") + +target_include_directories(app PRIVATE ${SOF_ROOT}/src/include) + +target_sources(app PRIVATE test_list_ztest.c) diff --git a/test/ztest/unit/list/prj.conf b/test/ztest/unit/list/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/list/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/list/test_list_ztest.c b/test/ztest/unit/list/test_list_ztest.c new file mode 100644 index 000000000000..38dc72a3f9f5 --- /dev/null +++ b/test/ztest/unit/list/test_list_ztest.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. + +#include <zephyr/ztest.h> +#include <sof/list.h> + +/** + * @brief Test list_init functionality + * + * Tests that list.prev and list.next point to the list itself after initialization + */ +ZTEST(sof_list_suite, test_list_init) +{ + struct list_item list = {.prev = NULL, .next = NULL}; + + list_init(&list); + + /* Verify that prev and next pointers point to the list itself after initialization */ + zassert_equal(&list, list.prev, "list.prev should point to itself after list_init"); + zassert_equal(&list, list.next, "list.next should point to itself after list_init"); +} + +/** + * @brief Test list_is_empty functionality + * + * Tests that list_is_empty returns true for empty lists and false for non-empty lists + */ +ZTEST(sof_list_suite, test_list_is_empty) +{ + struct list_item list; + struct list_item item; + + /* Test when list is empty */ + list_init(&list); + zassert_true(list_is_empty(&list), "list_is_empty should return true for empty list"); + + /* Test when list is not empty */ + list_item_append(&item, &list); + zassert_false(list_is_empty(&list), "list_is_empty should return false for non-empty list"); +} + +/** + * @brief Test list_item_append functionality + * + * Tests that list_item_append correctly appends an item to the end of the list + */ +ZTEST(sof_list_suite, test_list_item_append) +{ + struct list_item head; + struct list_item item1; + struct list_item item2; + + /* Initialize list */ + list_init(&head); + + /* Append first item */ + list_item_append(&item1, &head); + zassert_equal(&item1, head.next, "head->next should point to item1"); + zassert_equal(&item1, head.prev, "head->prev should point to item1"); + zassert_equal(&head, item1.next, "item1->next should point to head"); + zassert_equal(&head, item1.prev, "item1->prev should point to head"); + + /* Append second item */ + list_item_append(&item2, &head); + zassert_equal(&item1, head.next, "head->next should still point to item1"); + zassert_equal(&item2, head.prev, "head->prev should now point to item2"); + zassert_equal(&item2, item1.next, "item1->next should now point to item2"); + zassert_equal(&head, item1.prev, "item1->prev should still point to head"); + zassert_equal(&head, item2.next, "item2->next should point to head"); + zassert_equal(&item1, item2.prev, "item2->prev should point to item1"); +} + +/** + * @brief Test list_item_prepend functionality + * + * Tests that list_item_prepend correctly prepends an item to the beginning of the list + */ +ZTEST(sof_list_suite, test_list_item_prepend) +{ + struct list_item head; + struct list_item item1; + struct list_item item2; + + /* Initialize list */ + list_init(&head); + + /* Prepend first item */ + list_item_prepend(&item1, &head); + zassert_equal(&item1, head.next, "head->next should point to item1"); + zassert_equal(&item1, head.prev, "head->prev should point to item1"); + zassert_equal(&head, item1.next, "item1->next should point to head"); + zassert_equal(&head, item1.prev, "item1->prev should point to head"); + + /* Prepend second item */ + list_item_prepend(&item2, &head); + zassert_equal(&item2, head.next, "head->next should now point to item2"); + zassert_equal(&item1, head.prev, "head->prev should still point to item1"); + zassert_equal(&item1, item2.next, "item2->next should point to item1"); + zassert_equal(&head, item2.prev, "item2->prev should point to head"); + zassert_equal(&head, item1.next, "item1->next should still point to head"); + zassert_equal(&item2, item1.prev, "item1->prev should now point to item2"); +} + +/** + * @brief Test list_item_del functionality + * + * Tests that list_item_del correctly removes an item from a list + */ +ZTEST(sof_list_suite, test_list_item_del) +{ + struct list_item head; + struct list_item item1; + struct list_item item2; + + /* Initialize list */ + list_init(&head); + + /* Add items to list */ + list_item_append(&item1, &head); + list_item_append(&item2, &head); + + /* Remove first item */ + list_item_del(&item1); + + /* Check that item1 is properly removed and initialized */ + zassert_equal(&item1, item1.next, "item1->next should point to itself after deletion"); + zassert_equal(&item1, item1.prev, "item1->prev should point to itself after deletion"); + + /* Check that head and item2 are properly linked */ + zassert_equal(&item2, head.next, "head->next should point to item2"); + zassert_equal(&item2, head.prev, "head->prev should point to item2"); + zassert_equal(&head, item2.next, "item2->next should point to head"); + zassert_equal(&head, item2.prev, "item2->prev should point to head"); +} + +/** + * @brief Test list_item_is_last functionality + * + * Tests that list_item_is_last correctly identifies the last item in a list + */ +ZTEST(sof_list_suite, test_list_item_is_last) +{ + struct list_item head; + struct list_item item1; + struct list_item item2; + + /* Initialize list */ + list_init(&head); + + /* Add items to list */ + list_item_append(&item1, &head); + list_item_append(&item2, &head); + + /* Check item positions */ + zassert_false(list_item_is_last(&item1, &head), + "item1 should not be the last item in the list"); + zassert_true(list_item_is_last(&item2, &head), + "item2 should be the last item in the list"); +} + +/** + * @brief Test list_relink functionality + * + * Tests that list_relink correctly updates references when a list head is moved + */ +ZTEST(sof_list_suite, test_list_relink) +{ + struct list_item old_head; + struct list_item new_head; + struct list_item item1; + struct list_item item2; + + /* Test case 1: Empty list relinking */ + list_init(&old_head); + new_head = old_head; /* Copy the old head structure */ + + list_relink(&new_head, &old_head); + + /* After relinking empty list, new_head should be properly initialized */ + zassert_equal(&new_head, new_head.next, + "Empty list: new_head->next should point to itself"); + zassert_equal(&new_head, new_head.prev, + "Empty list: new_head->prev should point to itself"); + + /* Test case 2: Non-empty list relinking */ + list_init(&old_head); + list_item_append(&item1, &old_head); + list_item_append(&item2, &old_head); + + /* Verify initial state - items point to old_head */ + zassert_equal(&old_head, item1.prev, "Initial: item1 prev should point to old_head"); + zassert_equal(&old_head, item2.next, "Initial: item2 next should point to old_head"); + + /* Simulate moving list to new location by copying head structure */ + new_head = old_head; + /* Now new_head.next points to item1, new_head.prev points to item2 */ + /* But item1.prev and item2.next still point to &old_head */ + + /* Perform the relinking */ + list_relink(&new_head, &old_head); + + /* After relinking, items should now point to new_head instead of old_head */ + zassert_equal(&new_head, item1.prev, "After relink: item1 prev should point to new_head"); + zassert_equal(&new_head, item2.next, "After relink: item2 next should point to new_head"); + zassert_equal(&item1, new_head.next, "After relink: new_head next should point to item1"); + zassert_equal(&item2, new_head.prev, "After relink: new_head prev should point to item2"); + + /* Verify list integrity - items should still be properly linked */ + zassert_equal(&item2, item1.next, "After relink: item1 next should point to item2"); + zassert_equal(&item1, item2.prev, "After relink: item2 prev should point to item1"); +} + +ZTEST_SUITE(sof_list_suite, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/list/testcase.yaml b/test/ztest/unit/list/testcase.yaml new file mode 100644 index 000000000000..38b1697f5d2c --- /dev/null +++ b/test/ztest/unit/list/testcase.yaml @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2025 Intel Corporation. All rights reserved. +# +# These contents may have been developed with support from one or more Intel-operated +# generative artificial intelligence solutions. + +tests: + sof.unit.list: + platform_allow: native_sim + harness: ztest + tags: unit diff --git a/test/ztest/unit/math/advanced/functions/CMakeLists.txt b/test/ztest/unit/math/advanced/functions/CMakeLists.txt new file mode 100644 index 000000000000..615fc86a7db6 --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_math_advanced_functions) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../../../..") + +# Set SOF top directory for UUID registry generation +set(sof_top_dir ${SOF_ROOT}) + +# Include SOF CMake utilities for proper SOF source compilation +include(${SOF_ROOT}/scripts/cmake/misc.cmake) +include(${SOF_ROOT}/scripts/cmake/uuid-registry.cmake) + +target_include_directories(app PRIVATE + ${SOF_ROOT}/zephyr/include + ${SOF_ROOT}/src/include + ${SOF_ROOT}/src/platform/posix/include + ${SOF_ROOT}/test/cmocka/include + ${PROJECT_BINARY_DIR}/include/generated # For uuid-registry.h +) + +# Define SOF-specific configurations for unit testing +target_compile_definitions(app PRIVATE + -DCONFIG_ZEPHYR_POSIX=1 + -DCONFIG_LIBRARY=1 + -DUNIT_TEST=1 +) + +target_sources(app PRIVATE + test_scalar_power_ztest.c + test_base2_logarithm_ztest.c + test_base10_logarithm_ztest.c + test_base_e_logarithm_ztest.c + test_exponential_ztest.c + test_square_root_ztest.c + ${SOF_ROOT}/src/math/power.c + ${SOF_ROOT}/src/math/base2log.c + ${SOF_ROOT}/src/math/log_10.c + ${SOF_ROOT}/src/math/log_e.c + ${SOF_ROOT}/src/math/exp_fcn.c + ${SOF_ROOT}/src/math/sqrt_int16.c + # Note: exp_fcn_hifi.c is conditionally compiled only for Xtensa HiFi platforms. + # TODO: Enable these tests on Xtensa platforms to also test HiFi-optimized code paths. + ${SOF_ROOT}/src/math/exp_fcn_hifi.c +) + +# Apply SOF relative path definitions for proper compilation +sof_append_relative_path_definitions(app) diff --git a/test/ztest/unit/math/advanced/functions/prj.conf b/test/ztest/unit/math/advanced/functions/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/math/advanced/functions/test_base10_logarithm_ztest.c b/test/ztest/unit/math/advanced/functions/test_base10_logarithm_ztest.c new file mode 100644 index 000000000000..b880cfd388a5 --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/test_base10_logarithm_ztest.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. All rights reserved. +// +// Converted from CMock to Ztest +// +// Original test from sof/test/cmocka/src/math/arithmetic/base_10_logarithm.c: +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <zephyr/ztest.h> +#include <stdint.h> +#include <math.h> + +#include <sof/math/log.h> + +/* 'Error[max] = 0.0000071279028671,THD = -102.9407645424143993 ' */ +/* 'Error[max] = rms(log10() - double(log10_int32()))' */ +/* 'THD = 20*log10(Error[max])' */ +#define CMP_TOLERANCE 0.0000071279028671 + +/* Base-10 logarithm log10(X) reference table generated by matlab/Octave */ +/* UQ4.28 */ +static const double common_log10_ref_table[] = { + 0.0000000000000000, 7.6373246662453802, 7.9383546619093615, 8.1144459209650428, + 8.2393846575733427, 8.3362946705813989, 8.4154759166290241, 8.4824227062596371, + 8.5404146532373240, 8.5915671756847054, 8.6373246662453802, 8.6787173514036056, + 8.7165059122930053, 8.7512680193222625, 8.7834527026386606, 8.8134159259684335, + 8.8414446495269665, 8.8677735882125130, 8.8925971719048302, 8.9160782677250818, + 8.9383546624098908, 8.9595439614559940, 8.9797473475226131, 8.9990525026982162, + 9.0175359083740947, 9.0352646753178405, 9.0522980146012202, 9.0686884307751292, + 9.0844826979451199, 9.0997226644895282, 9.1144459212987297, 9.1286863604025754, + 9.1424746448781171, 9.1558386064266184, 9.1688035835820649, 9.1813927108816724, + 9.1936271672907388, 9.2055263908534872, 9.2171082633890631, 9.2283892737852433, + 9.2393846580738721, 9.2501085234534361, 9.2605739571199752, 9.2707931222905753, + 9.2807773431865943, 9.2905371804656394, 9.3000824983621975, 9.3094225246070792, + 9.3185659040380759, 9.3275207466824899, 9.3362946709818218, 9.3448948427358882, + 9.3533280102652014, 9.3616005362239267, 9.3697184264391105, 9.3776873561036460, + 9.3855126936091011, 9.3931995222691196, 9.4007526601535094, 9.4081766782268659, + 9.4154759169627091, 9.4226545015843630, 9.4297163562280168, 9.4366652161756566, + 9.4435046406985137, 9.4502380233502628, 9.4568686022422757, 9.4633994693944423, + 9.4698335793932600, 9.4761737574178788, 9.4824227066886628, 9.4885830153874373, + 9.4946571630937573, 9.5006475267772306, 9.5065563863821918, 9.5123859300375031, + 9.5181382589213257, 9.5238153918078847, 9.5294192693208828, 9.5349517579159713, + 9.5404146536127215, 9.5458096854947918, 9.5511385189953373, 9.5564027589832818, + 9.5616039526647825, 9.5667435923129869, 9.5718231178381536, 9.5768439193242560, + 9.5818073388505756, 9.5867146733402073, 9.5915671761296206, 9.5963660590064990, + 9.6011124940261787, 9.6058076152298781, 9.6104525202710605, 9.6150482719557271, + 9.6195958997020572, 9.6240964009244330, 9.6285507423464711, 9.6329598611462810}; + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +ZTEST(math_advanced_functions_suite, test_math_arithmetic_base10log_fixed) +{ + double clogfxp; + double diff; + int i; + + BUILD_ASSERT(ARRAY_SIZE(uv) == ARRAY_SIZE(common_log10_ref_table), + "Test vector size must match reference table size"); + + for (i = 0; i < ARRAY_SIZE(common_log10_ref_table); i++) { + clogfxp = log10_int32(uv[i]); + diff = fabs(common_log10_ref_table[i] - (double)clogfxp / (1 << 28)); + + if (diff > CMP_TOLERANCE) { + zassert_true(diff <= CMP_TOLERANCE, + "log10_int32(%u): delta %.16f > tolerance (got %.16f)", + uv[i], diff, clogfxp / (1 << 28)); + } + } +} \ No newline at end of file diff --git a/test/ztest/unit/math/advanced/functions/test_base2_logarithm_ztest.c b/test/ztest/unit/math/advanced/functions/test_base2_logarithm_ztest.c new file mode 100644 index 000000000000..52d1eb0e6a0b --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/test_base2_logarithm_ztest.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// +// Original test from sof/test/cmocka/src/math/arithmetic/base2_logarithm.c +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/audio/format.h> +#include <sof/math/log.h> +#include <math.h> +#include <rtos/string.h> + +/* Test data tables from MATLAB-generated reference */ +#include "log2_tables.h" + +/* 'Error[max] = 0.0000236785999981,THD(-dBc) = -92.5128795787487235' */ +#define CMP_TOLERANCE 0.0000236785691029f + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +/** + * @brief Test base-2 logarithm function with fixed-point arithmetic + * + * This test validates the base2_logarithm() function against MATLAB-generated + * reference values. It tests 100 uniformly distributed input values across + * the full uint32_t range, checking that the fixed-point logarithm calculation + * stays within acceptable tolerance. + * + * Input values: Q32.0 format (unsigned 32-bit integers) + * Result: Q16.16 fixed-point format + * Reference: MATLAB log2() function results + */ +ZTEST(math_advanced_functions_suite, test_math_arithmetic_base2log_fixed) +{ + uint32_t u[100]; + int i, ret; + + BUILD_ASSERT(ARRAY_SIZE(uv) == ARRAY_SIZE(log2_lookup_table), + "Test vector size must match reference table size"); + + ret = memcpy_s((void *)&u[0], sizeof(u), (void *)&uv[0], 100U * sizeof(uint32_t)); + zassert_equal(ret, 0, "memcpy_s failed with error code %d", ret); + + for (i = 0; i < ARRAY_SIZE(u); i++) { + float y = Q_CONVERT_QTOF(base2_logarithm(u[i]), 0); + float delta = fabsf((float)(log2_lookup_table[i] - (double)y / (1 << 16))); + + zassert_true(delta <= CMP_TOLERANCE, + "base2_logarithm(%u): delta %.16f > tolerance (expected %.16f, got %.16f)", + u[i], (double)delta, log2_lookup_table[i], (double)y / (1 << 16)); + } +} diff --git a/test/ztest/unit/math/advanced/functions/test_base_e_logarithm_ztest.c b/test/ztest/unit/math/advanced/functions/test_base_e_logarithm_ztest.c new file mode 100644 index 000000000000..e400b8b76a59 --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/test_base_e_logarithm_ztest.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// +// Original test from sof/test/cmocka/src/math/arithmetic/base_e_logarithm.c +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <zephyr/ztest.h> +#include <stdint.h> +#include <math.h> + +#include <sof/math/log.h> + +/* 'Error[max] = 0.0000164133276926,THD(-dBc) = -95.6960671942683234' */ +/* 'Error[max] = rms(log() - double(log_int32()))' */ +/* 'THD = 20*log10(Error[max])' */ +#define CMP_TOLERANCE 0.0000164133276926 + +/* Natural logarithm loge(X) reference table generated by matlab/Octave */ +/* UQ5.27 */ +static const double natural_log_lookup_table[] = { + 0.0000000000000000, 17.5855899268523359, 18.2787371074122831, 18.6842022155204468, + 18.9718842879722267, 19.1950278392864391, 19.3773493960803940, 19.5315000759076511, + 19.6650314685321739, 19.7828145041885577, 19.8881750198463827, 19.9834851996507084, + 20.0704965766403376, 20.1505392860869676, 20.2246472581140395, 20.2936401294912301, + 20.3581786505327571, 20.4188032722644479, 20.4759616860290699, 20.5300289072319480, + 20.5813222015588408, 20.6301123656733907, 20.6766323812583899, 20.7210841437836706, + 20.7636437581607112, 20.8044657526425461, 20.8436864657603671, 20.8814267937103786, + 20.9177944378507625, 20.9528857576336485, 20.9867873092828354, 21.0195771320810394, + 21.0513258303723845, 21.0820974890173112, 21.1119504521464485, 21.1409379890003279, + 21.1691088659487328, 21.1965078407425196, 21.2231760877918916, 21.2491515741640455, + 21.2744693821187845, 21.2991619946810467, 21.3232595462333343, 21.3467900436180038, + 21.3697795618183370, 21.3922524176471107, 21.4142313243436178, 21.4357375295432568, + 21.4567909387206548, 21.4774102259037889, 21.4976129332024932, 21.5174155604805932, + 21.5368336463203107, 21.5558818412742781, 21.5745739742703257, 21.5929231129229997, + 21.6109416184107097, 21.6286411954956677, 21.6460329381935921, 21.6631273715394208, + 21.6799344898427790, 21.6964637917813938, 21.7127243130127638, 21.7287246543415016, + 21.7444730112924880, 21.7599771978118319, 21.7752446699265008, 21.7902825472754031, + 21.8050976330453672, 21.8196964324517815, 21.8340851698895619, 21.8482698048676056, + 21.8622560468288185, 21.8760493689479993, 21.8896550209909755, 21.9030780413106569, + 21.9163232680485471, 21.9293953496040821, 21.9422987544284780, 21.9550377801946830, + 21.9676165623906030, 21.9800390823784895, 21.9923091749598925, 22.0044305354820757, + 22.0164067265188734, 22.0282411841561903, 22.0399372239099236, 22.0514980465667030, + 22.0629267423782807, 22.0742262976204415, 22.0853995982070579, 22.0964494343823858, + 22.1073785049035614, 22.1181894209970018, 22.1288847101032040, 22.1394668194234150, + 22.1499381192805984, 22.1603009063062437, 22.1705574064637361, 22.1807097776854185}; + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +/** + * @brief Test natural (base-e) logarithm function with fixed-point arithmetic + * + * This test validates the ln_int32() function against MATLAB-generated reference + * values. It tests 100 uniformly distributed input values across the full uint32_t + * range, checking that the fixed-point logarithm calculation stays within acceptable + * tolerance. + * + * Input values: Q32.0 format (unsigned 32-bit integers) + * Result: UQ5.27 fixed-point format + * Reference: MATLAB log() function results + */ +ZTEST(math_advanced_functions_suite, test_math_arithmetic_base_e_log_fixed) +{ + int i; + + BUILD_ASSERT(ARRAY_SIZE(uv) == ARRAY_SIZE(natural_log_lookup_table), + "Test vector size must match reference table size"); + + for (i = 0; i < ARRAY_SIZE(uv); i++) { + double logefxp = ln_int32(uv[i]); + double diff = fabs(natural_log_lookup_table[i] - logefxp / (1 << 27)); + + zassert_true(diff <= CMP_TOLERANCE, + "ln_int32(%u): diff %.16f > tolerance (expected %.16f, got %.16f)", + uv[i], diff, natural_log_lookup_table[i], logefxp / (1 << 27)); + } +} diff --git a/test/ztest/unit/math/advanced/functions/test_exponential_ztest.c b/test/ztest/unit/math/advanced/functions/test_exponential_ztest.c new file mode 100644 index 000000000000..1fd03b6bb5af --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/test_exponential_ztest.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022-2026 Intel Corporation. + * + * These contents may have been developed with support from one or more Intel-operated + * generative artificial intelligence solutions. + * + * Converted from CMock to Ztest + * + * Original test from sof/test/cmocka/src/math/arithmetic/exponential.c + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + * Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + */ + +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> +#include <sof/math/exp_fcn.h> +#include <sof/audio/format.h> +#include <sof/common.h> +#include <math.h> +#include <rtos/string.h> + +LOG_MODULE_REGISTER(test_exponential, LOG_LEVEL_INF); + +#define ULP_TOLERANCE 1.0 +#define ULP_SCALE 1.9073e-06 /* For exp() output Q13.19, 1 / 2^19 */ +#define NUMTESTSAMPLES 256 + +#define NUMTESTSAMPLES_TEST2 100 +#define ABS_DELTA_TOLERANCE_TEST2 2.0e-6 +#define REL_DELTA_TOLERANCE_TEST2 1000.0 /* rel. error is large with values near zero */ +#define NUMTESTSAMPLES_TEST3 100 +#define ABS_DELTA_TOLERANCE_TEST3 2.0e-6 +#define REL_DELTA_TOLERANCE_TEST3 10.0e-2 +#define SOFM_EXP_FIXED_ARG_MIN -11.5 +#define SOFM_EXP_FIXED_ARG_MAX 7.6245 + +#define NUMTESTSAMPLES_TEST4 100 +#define ABS_DELTA_TOLERANCE_TEST4 2.5e-5 +#define REL_DELTA_TOLERANCE_TEST4 1000.0 /* rel. error is large with values near zero */ + +/** + * Saturates input to 32 bits + * @param x Input value + * @return Saturated output value + */ +static int32_t saturate32(int64_t x) +{ + if (x < INT32_MIN) + return INT32_MIN; + else if (x > INT32_MAX) + return INT32_MAX; + + return x; +} + +/** + * Generates linearly spaced values for a vector with end points and number points in + * desired fractional Q-format for 32 bit integer. If the test values exceed int32_t + * range, the values are saturated to INT32_MIN to INT32_MAX range. + * + * @param a First value of test vector + * @param b Last value of test vector + * @param step_count Number of values in vector + * @param point Calculate n-th point of vector 0 .. step_count - 1 + * @param qformat Number of fractional bits y in Qx.y format + * @param fout Pointer to calculated test vector value, double + * @param iout Pointer to calculated test vector value, int32_t + */ +static void gen_testvector_linspace_int32(double a, double b, int step_count, int point, + int qformat, double *fout, int32_t *iout) +{ + double fstep = (b - a) / (step_count - 1); + double fvalue = a + fstep * point; + int64_t itmp; + + itmp = (int64_t)round(fvalue * (double)(1 << qformat)); + *iout = saturate32(itmp); + *fout = (double)*iout / (1 << qformat); +} + +/** + * Calculate reference exponent value + * @param x Input value + * @param qformat Fractional bits y in Qx.y format + * @return Saturated exponent value to match fractional format + */ +static double ref_exp(double x, int qformat) +{ + double yf; + int64_t yi; + + yf = exp(x); + yi = yf * (1 << qformat); + + if (yi > INT32_MAX) + yi = INT32_MAX; + else if (yi < INT32_MIN) + yi = INT32_MIN; + + yf = (double)yi / (1 << qformat); + return yf; +} + +/** + * Calculates test exponent function and compares result to reference exponent. + * @param ivalue Fractional format input value Q5.27 + * @param iexp_value Fractional format output value Q12.20 + * @param abs_delta_max Calculated absolute error + * @param rel_delta_max Calculated relative error + * @param abs_delta_tolerance Tolerance for absolute error + * @param rel_delta_tolerance Tolerance for relative error + */ +static void test_exp_with_input_value(int32_t ivalue, int32_t *iexp_value, + double *abs_delta_max, double *rel_delta_max, + double abs_delta_tolerance, double rel_delta_tolerance) +{ + double fvalue, fexp_value, ref_exp_value; + double rel_delta, abs_delta; + double eps = 1e-9; + + *iexp_value = sofm_exp_fixed(ivalue); + fvalue = (double)ivalue / (1 << 27); /* Q5.27 */ + fexp_value = (double)*iexp_value / (1 << 20); /* Q12.20 */ + ref_exp_value = ref_exp(fvalue, 20); + abs_delta = fabs(ref_exp_value - fexp_value); + rel_delta = abs_delta / (ref_exp_value + eps); + + if (abs_delta > *abs_delta_max) + *abs_delta_max = abs_delta; + + if (rel_delta > *rel_delta_max) + *rel_delta_max = rel_delta; + + zassert_true(abs_delta <= abs_delta_tolerance, + "sofm_exp_fixed: Absolute error %g exceeds limit %g, input %g output %g", + abs_delta, abs_delta_tolerance, fvalue, fexp_value); + + zassert_true(rel_delta <= rel_delta_tolerance, + "sofm_exp_fixed: Relative error %g exceeds limit %g, input %g output %g", + rel_delta, rel_delta_tolerance, fvalue, fexp_value); +} + +/** + * Reference function for dB to linear conversion + * @param x Input value + * @param qformat Fractional bits y in Qx.y format for saturation + * @return Saturated linear value + */ +static double ref_db2lin(double x, int qformat) +{ + double fref; + int64_t iref; + + fref = pow(10, x / 20); + iref = fref * (1 << qformat); + return (double)saturate32(iref) / (1 << qformat); +} + +/** + * @brief Test sofm_exp_approx() function with ULP error validation + * + * This test validates the sofm_exp_approx() exponential approximation function + * against the C standard library exp() function. It tests 256 linearly spaced + * input values and checks that the ULP (Unit in the Last Place) error stays + * within acceptable tolerance. + * + * Input values: Q28 format, range -8 to 8 + * Result: Q19 format + * Validation: ULP error < 1.0 ULP + */ +ZTEST(math_advanced_functions_suite, test_function_sofm_exp_approx) +{ + int32_t accum; + int i; + double a_i; + double max_ulp = 0; + double ulp; + double a_tmp = -8; + double b_tmp = 8; + int32_t b_i; + + for (i = 0; i < NUMTESTSAMPLES; i++) { + gen_testvector_linspace_int32(a_tmp, b_tmp, NUMTESTSAMPLES, i, 28, &a_i, &b_i); + accum = sofm_exp_approx(b_i); + ulp = fabs(exp(a_i) - (double)accum / (1 << 19)) / ULP_SCALE; + if (ulp > max_ulp) + max_ulp = ulp; + + zassert_true(ulp <= ULP_TOLERANCE, + "sofm_exp_approx: ULP %.16f exceeds tolerance, value=%.16f, exp=%.16f", + ulp, (double)b_i / (1 << 28), (double)accum / (1 << 19)); + } + + LOG_INF("Worst-case ULP: %g ULP_SCALE %g", max_ulp, ULP_SCALE); +} + +/** + * @brief Test sofm_exp_fixed() function with absolute and relative error validation + * + * This test validates the sofm_exp_fixed() fixed-point exponential function + * against a reference implementation. It performs two sub-tests with different + * input ranges and tolerance requirements. + * + * Sub-test 1: Coarse grid across max range + * - Input values: Q27 format, range -16 to 16 + * - Result: Q20 format + * - Tolerances: abs 2.0e-6, rel 1000.0 + * + * Sub-test 2: Fine grid across typical range + * - Input values: Q27 format, range -11.5 to 7.6245 + * - Result: Q20 format + * - Tolerances: abs 2.0e-6, rel 10.0e-2 + */ +ZTEST(math_advanced_functions_suite, test_function_sofm_exp_fixed) +{ + double rel_delta_max, abs_delta_max; + double tmp; + int32_t ivalue, iexp_value; + int i; + + /* Test max int32_t range with coarse grid */ + rel_delta_max = 0; + abs_delta_max = 0; + for (i = 0; i < NUMTESTSAMPLES_TEST2; i++) { + gen_testvector_linspace_int32(-16, 16, NUMTESTSAMPLES_TEST2, i, 27, &tmp, &ivalue); + test_exp_with_input_value(ivalue, &iexp_value, &abs_delta_max, &rel_delta_max, + ABS_DELTA_TOLERANCE_TEST2, REL_DELTA_TOLERANCE_TEST2); + } + + LOG_INF("Absolute max error was %.6e (max range)", abs_delta_max); + LOG_INF("Relative max error was %.6e (max range)", rel_delta_max); + + /* Test max int32_t middle range with fine grid */ + rel_delta_max = 0; + abs_delta_max = 0; + for (i = 0; i < NUMTESTSAMPLES_TEST3; i++) { + gen_testvector_linspace_int32(SOFM_EXP_FIXED_ARG_MIN, SOFM_EXP_FIXED_ARG_MAX, + NUMTESTSAMPLES_TEST3, i, 27, &tmp, &ivalue); + test_exp_with_input_value(ivalue, &iexp_value, &abs_delta_max, &rel_delta_max, + ABS_DELTA_TOLERANCE_TEST3, REL_DELTA_TOLERANCE_TEST3); + } + + LOG_INF("Absolute max error was %.6e (middle)", abs_delta_max); + LOG_INF("Relative max error was %.6e (middle)", rel_delta_max); +} + +/** + * @brief Test sofm_db2lin_fixed() function for dB to linear conversion + * + * This test validates the sofm_db2lin_fixed() function that converts decibel + * values to linear scale using fixed-point arithmetic. It compares against + * a reference implementation using floating-point pow(10, x/20). + * + * Input values: Q24 format, range -128 to 128 dB + * Result: Q20 format + * Tolerances: abs 2.5e-5, rel 1000.0 + */ +ZTEST(math_advanced_functions_suite, test_function_sofm_db2lin_fixed) +{ + double abs_delta, rel_delta, abs_delta_max, rel_delta_max; + double fin, fout, fref; + double eps = 1e-9; + int32_t iin, iout; + int i; + + rel_delta_max = 0; + abs_delta_max = 0; + for (i = 0; i < NUMTESTSAMPLES_TEST4; i++) { + gen_testvector_linspace_int32(-128, 128, NUMTESTSAMPLES_TEST4, i, 24, &fin, &iin); + iout = sofm_db2lin_fixed(iin); + fout = (double)iout / (1 << 20); + fref = ref_db2lin(fin, 20); + abs_delta = fabs(fref - fout); + rel_delta = abs_delta / (fref + eps); + if (abs_delta > abs_delta_max) + abs_delta_max = abs_delta; + + if (rel_delta > rel_delta_max) + rel_delta_max = rel_delta; + + zassert_true(abs_delta <= ABS_DELTA_TOLERANCE_TEST4, + "sofm_db2lin_fixed: Absolute error %g exceeds limit %g, input %g output %g", + abs_delta, ABS_DELTA_TOLERANCE_TEST4, fin, fout); + + zassert_true(rel_delta <= REL_DELTA_TOLERANCE_TEST4, + "sofm_db2lin_fixed: Relative error %g exceeds limit %g, input %g output %g", + rel_delta, REL_DELTA_TOLERANCE_TEST4, fin, fout); + } + + LOG_INF("Absolute max error was %.6e", abs_delta_max); + LOG_INF("Relative max error was %.6e", rel_delta_max); +} diff --git a/test/ztest/unit/math/advanced/functions/test_scalar_power_ztest.c b/test/ztest/unit/math/advanced/functions/test_scalar_power_ztest.c new file mode 100644 index 000000000000..a3c2d6fe911c --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/test_scalar_power_ztest.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// +// Original test from sof/test/cmocka/src/math/arithmetic/scalar_power.c: +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> +#include <sof/audio/format.h> +#include <sof/math/power.h> +#include <sof/common.h> +#include <math.h> + +LOG_MODULE_REGISTER(test_scalar_power, LOG_LEVEL_INF); + +/* Test data tables from MATLAB-generated reference */ +#include "power_tables.h" + +/* Error tolerance: max error = 0.000034912111005, THD+N = -96.457180359025074 */ +#define CMP_TOLERANCE 0.0000150363575813f + +/** + * @brief Test scalar power function with fixed-point arithmetic + * + * This test validates the power_int32() function against MATLAB-generated + * reference values. It tests 64 base values against 6 exponent values, + * checking that the fixed-point power calculation stays within acceptable + * tolerance. + * + * Base values: Fixed-point Q6.25 format (range -1.0 to 1.0) + * Exponent values: Fixed-point Q2.29 format + * Result: Fixed-point Q16.15 format + */ +ZTEST(math_advanced_functions_suite, test_math_arithmetic_power_fixed) +{ + double p; + int i; + int j; + + for (i = 0; i < ARRAY_SIZE(b); i++) { + for (j = 0; j < ARRAY_SIZE(e); j++) { + p = power_int32(b[i], e[j]); + float delta = fabsf((float)(power_table[i][j] - (double)p / (1 << 15))); + + zassert_true(delta <= CMP_TOLERANCE, + "Power calc error: delta=%f > %f at b[%d]=%d, e[%d]=%d", + (double)delta, (double)CMP_TOLERANCE, i, b[i], j, e[j]); + } + } +} + +ZTEST_SUITE(math_advanced_functions_suite, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/math/advanced/functions/test_square_root_ztest.c b/test/ztest/unit/math/advanced/functions/test_square_root_ztest.c new file mode 100644 index 000000000000..2dcb45ffa0ff --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/test_square_root_ztest.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. All rights reserved. +// +// Converted from CMock to Ztest +// +// Original test from sof/test/cmocka/src/math/arithmetic/square_root.c: +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> + +#include <zephyr/ztest.h> +#include <stdint.h> +#include <math.h> + +#include <sof/math/sqrt.h> +#include <sof/audio/format.h> +#include <rtos/string.h> +#include <sof/common.h> + +/* 'Error[max] = 0.0003000860000000,THD(-dBc) = -87.1210823527511309' */ +#define CMP_TOLERANCE 0.0001689942 + +static const double sqrt_ref_table[] = { + 0.0000000000000000, 0.2529127196287289, 0.3580137261684250, 0.4383362543470480, + 0.5060667106469264, 0.5657458434447398, 0.6199010757774179, 0.6695089151758922, + 0.7156864056624241, 0.7590598625931949, 0.8002380017063674, 0.8392530626247365, + 0.8765332548597343, 0.9124250825410271, 0.9468285879714448, 0.9800251112854200, + 1.0121334212938529, 1.0433710015497843, 1.0735864616438677, 1.1029744939820685, + 1.1317074351394887, 1.1596234572049671, 1.1868830634270588, 1.2135304899342250, + 1.2397036881347898, 1.2652391387105444, 1.2902693214499832, 1.3148230929007141, + 1.3390178303517843, 1.3626935069009465, 1.3859648038460428, 1.4089384024417106, + 1.4314580907679415, 1.4536289448738284, 1.4754666899408471, 1.4970674458754356, + 1.5182805344369004, 1.5392012945030940, 1.5598414883410430, 1.5802893574042065, + 1.6003997303408295, 1.6202605162827983, 1.6399552204252408, 1.6593426315110451, + 1.6785061252494731, 1.6974532854396907, 1.7162624043615824, 1.7347972458979175, + 1.7531361407845656, 1.7712851751976586, 1.7893183496097054, 1.8071040368501201, + 1.8247163735084968, 1.8422265952170487, 1.8595062978852748, 1.8766268983537990, + 1.8935927121149891, 1.9104717594746068, 1.9271396388170734, 1.9436645881555799, + 1.9601125007572908, 1.9763617734046062, 1.9924785326635266, 2.0084659685628234, + 2.0243874459327196, 2.0401248429936829, 2.0557417684986605, 2.0712409474756917, + 2.0866835042418388, 2.1019545405705138, 2.1171154277400652, 2.1322257663648099, + 2.1471729232877355, 2.1620167451363552, 2.1767593459084997, 2.1914584719713490, + 2.2060043241401410, 2.2204548907543695, 2.2348120201987909, 2.2491317769308226, + 2.2633070038662453, 2.2773940013752560, 2.2914476694602910, 2.3053627188850347, + 2.3191942802134968, 2.3329438383992445, 2.3466648541067809, 2.3602543890966499, + 2.3737661268541177, 2.3872013883939496, 2.4006123079591588, 2.4138981537908761, + 2.4271112748749282, 2.4403028756693299, 2.4533737931163282, 2.4663754402969551, + 2.4793089069839604, 2.4922242356226696, 2.5050242482608827, 2.5177591878742098, + 2.5304782774210888, 2.5430857547967194, 2.5556310375326090, 2.5681150370943278, + 2.5805859466650203, 2.5929498012639969, 2.6052549809231724, 2.6175023131556161, + 2.6297390257875399, 2.6418728560436060, 2.6539512111660981, 2.6660206330081166, + 2.6779900782816579, 2.6899062628881700, 2.7017698915479462, 2.7136266381449752, + 2.7253870138018930, 2.7370968595849874, 2.7487568212739375, 2.7604117531402812, + 2.7719736453698474, 2.7834875128828940, 2.7949976241045360, 2.8064170328908711, + 2.8177901636300033, 2.8291175744390689, 2.8404427884354582, 2.8516802201728368, + 2.8628735427669523, 2.8740232715872360, 2.8851722218959477, 2.8962361080806240, + 2.9072578897476569, 2.9182798738083706, 2.9292187124939990, 2.9401168530136688, + 2.9509747462702896, 2.9618340496219568, 2.9726126187665289, 2.9833522462156559, + 2.9940941216626773, 3.0047569707257522, 3.0153821145710538, 3.0259699503836783, + 3.0365610688738007, 3.0470753139280951, 3.0575534030495688, 3.0679957066870220, + 3.0784422425351754, 3.0888139284157279, 3.0991509043809078, 3.1094927741514371, + 3.1197612338526808, 3.1299960063872287, 3.1401974211424988, 3.1504045499149789, + 3.1605400917999757, 3.1706432337342845, 3.1807142844611178, 3.1907918051402224, + 3.2007994606816590, 3.2107759235502562, 3.2207593849316032, 3.2306742112715421, + 3.2405587023112234, 3.2504131347991749, 3.2602752232365293, 3.2700702400713046, + 3.2798360048560355, 3.2895727781126838, 3.2993178153786578, 3.3089972636170311, + 3.3186484800856810, 3.3283083869662677, 3.3379037677111065, 3.3474716438306089, + 3.3570122504989461, 3.3665620793882591, 3.3760487375221642, 3.3855088128485207, + 3.3949784839156196, 3.4043859578490805, 3.4137675072784321, 3.4231233453528955, + 3.4324892457042018, 3.4417941928048226, 3.4510740515635128, 3.4603290238249023, + 3.4695944917958350, 3.4788001927748020, 3.4879815975718680, 3.4971738031409019, + 3.5063070962374359, 3.5154166604934614, 3.5245026799003858, 3.5335998818485379, + 3.5426392659640071, 3.5516556438511886, 3.5606491902811768, 3.5696542746637245, + 3.5786025882144274, 3.5875285822032135, 3.5964663647113397, 3.6053481324623839, + 3.6142080737002402, 3.6230463485511746, 3.6318967259718442, 3.6406920594682268, + 3.6494661959833250, 3.6582526566654741, 3.6669847755001657, 3.6756961500510350, + 3.6843869274616097, 3.6930903069956198, 3.7017402474207994, 3.7103700224000571, + 3.7189797723132347, 3.7276023837381045, 3.7361724230822109, 3.7447228493908598, + 3.7532863204297375, 3.7617978476886553, 3.7702901600042669, 3.7787633869263368, + 3.7872498886065071, 3.7956852559847478, 3.8041019184887777, 3.8125000000000000, + 3.8209115711273665, 3.8292727871131094, 3.8376157861196840, 3.8459724266107265, + 3.8542792776341468, 3.8625682639598748, 3.8708395003538962, 3.8791245690071618, + 3.8873605782876637, 3.8955791750874478, 3.9037804693815712, 3.9119957742180653, + 3.9201627238228260, 3.9283126944020128, 3.9364768015796816, 3.9445930655930783, + 3.9526926641056979, 3.9607756993580185, 3.9688730295891301, 3.9769231786332004, + 3.9849570653270532, 3.9930053589840071, 3.9999694823054588, 3.9999694823054588}; + +/* testvector in Q4.12 */ +static const uint32_t uv[252] = { + 0U, 262U, 525U, 787U, 1049U, 1311U, + 1574U, 1836U, 2098U, 2360U, 2623U, 2885U, + 3147U, 3410U, 3672U, 3934U, 4196U, 4459U, + 4721U, 4983U, 5246U, 5508U, 5770U, 6032U, + 6295U, 6557U, 6819U, 7081U, 7344U, 7606U, + 7868U, 8131U, 8393U, 8655U, 8917U, 9180U, + 9442U, 9704U, 9966U, 10229U, 10491U, 10753U, + 11016U, 11278U, 11540U, 11802U, 12065U, 12327U, + 12589U, 12851U, 13114U, 13376U, 13638U, 13901U, + 14163U, 14425U, 14687U, 14950U, 15212U, 15474U, + 15737U, 15999U, 16261U, 16523U, 16786U, 17048U, + 17310U, 17572U, 17835U, 18097U, 18359U, 18622U, + 18884U, 19146U, 19408U, 19671U, 19933U, 20195U, + 20457U, 20720U, 20982U, 21244U, 21507U, 21769U, + 22031U, 22293U, 22556U, 22818U, 23080U, 23342U, + 23605U, 23867U, 24129U, 24392U, 24654U, 24916U, + 25178U, 25441U, 25703U, 25965U, 26228U, 26490U, + 26752U, 27014U, 27277U, 27539U, 27801U, 28063U, + 28326U, 28588U, 28850U, 29113U, 29375U, 29637U, + 29899U, 30162U, 30424U, 30686U, 30948U, 31211U, + 31473U, 31735U, 31998U, 32260U, 32522U, 32784U, + 33047U, 33309U, 33571U, 33833U, 34096U, 34358U, + 34620U, 34883U, 35145U, 35407U, 35669U, 35932U, + 36194U, 36456U, 36719U, 36981U, 37243U, 37505U, + 37768U, 38030U, 38292U, 38554U, 38817U, 39079U, + 39341U, 39604U, 39866U, 40128U, 40390U, 40653U, + 40915U, 41177U, 41439U, 41702U, 41964U, 42226U, + 42489U, 42751U, 43013U, 43275U, 43538U, 43800U, + 44062U, 44324U, 44587U, 44849U, 45111U, 45374U, + 45636U, 45898U, 46160U, 46423U, 46685U, 46947U, + 47210U, 47472U, 47734U, 47996U, 48259U, 48521U, + 48783U, 49045U, 49308U, 49570U, 49832U, 50095U, + 50357U, 50619U, 50881U, 51144U, 51406U, 51668U, + 51930U, 52193U, 52455U, 52717U, 52980U, 53242U, + 53504U, 53766U, 54029U, 54291U, 54553U, 54816U, + 55078U, 55340U, 55602U, 55865U, 56127U, 56389U, + 56651U, 56914U, 57176U, 57438U, 57701U, 57963U, + 58225U, 58487U, 58750U, 59012U, 59274U, 59536U, + 59799U, 60061U, 60323U, 60586U, 60848U, 61110U, + 61372U, 61635U, 61897U, 62159U, 62421U, 62684U, + 62946U, 63208U, 63471U, 63733U, 63995U, 64257U, + 64520U, 64782U, 65044U, 65307U, UINT16_MAX, UINT16_MAX}; + +ZTEST(math_advanced_functions_suite, test_math_arithmetic_sqrt_fixed) +{ + uint32_t u[ARRAY_SIZE(uv)]; + int i; + double y; + double diff; + int ret; + + BUILD_ASSERT(ARRAY_SIZE(uv) == ARRAY_SIZE(sqrt_ref_table), + "Test vector size must match reference table size"); + + ret = memcpy_s(u, sizeof(u), uv, sizeof(uv)); + zassert_equal(ret, 0, "memcpy_s failed: %d", ret); + + for (i = 0; i < ARRAY_SIZE(sqrt_ref_table); i++) { + y = (double)Q_CONVERT_QTOF(sofm_sqrt_int16(u[i]), 12); + diff = fabs(sqrt_ref_table[i] - y); + + if (diff > CMP_TOLERANCE) { + zassert_true(diff <= CMP_TOLERANCE, + "sqrt delta=%f ref=%f actual=%f index=%d", + diff, sqrt_ref_table[i], y, i); + } + } +} diff --git a/test/ztest/unit/math/advanced/functions/testcase.yaml b/test/ztest/unit/math/advanced/functions/testcase.yaml new file mode 100644 index 000000000000..1d58ccae0591 --- /dev/null +++ b/test/ztest/unit/math/advanced/functions/testcase.yaml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2025 Intel Corporation. All rights reserved. +# +# Math advanced functions unit tests for Ztest framework +# +# These contents may have been developed with support from one or more Intel-operated +# generative artificial intelligence solutions. +# + +tests: + sof.unit.math.advanced.functions: + tags: math advanced functions power logarithm base2 base10 exponential exp db2lin sqrt log10 + platform_allow: native_sim + integration_platforms: + - native_sim + build_only: false diff --git a/test/ztest/unit/math/basic/arithmetic/CMakeLists.txt b/test/ztest/unit/math/basic/arithmetic/CMakeLists.txt new file mode 100644 index 000000000000..b71031491abf --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_math_arithmetic) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../../../..") + +target_include_directories(app PRIVATE + ${SOF_ROOT}/zephyr/include + ${SOF_ROOT}/src/include +) + +# Define SOF-specific configurations for unit testing +target_compile_definitions(app PRIVATE + -DCONFIG_ZEPHYR_POSIX=1 + -DCONFIG_LIBRARY=1 + -DCONFIG_NUMBERS_VECTOR_FIND=1 + -DCONFIG_NUMBERS_NORM=1 + -DUNIT_TEST=1 +) + +target_sources(app PRIVATE + test_gcd_ztest.c + test_ceil_divide_ztest.c + test_find_equal_int16_ztest.c + test_find_min_int16_ztest.c + test_find_max_abs_int32_ztest.c + test_norm_int32_ztest.c + test_crc32_ztest.c + ${SOF_ROOT}/src/math/numbers.c +) + +# Link math library for ceil_divide test +target_link_libraries(app PRIVATE m) diff --git a/test/ztest/unit/math/basic/arithmetic/prj.conf b/test/ztest/unit/math/basic/arithmetic/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/math/basic/arithmetic/test_ceil_divide_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_ceil_divide_ztest.c new file mode 100644 index 000000000000..e9ad0c7833a7 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_ceil_divide_ztest.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// Original file: sof/test/cmocka/src/math/numbers/ceil_divide.c +// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> +#include <math.h> + +/** + * @brief Test ceil_divide function with various parameter combinations + * + * Tests ceil_divide against reference ceilf implementation with multiple + * positive and negative integer combinations + */ +ZTEST(math_arithmetic_suite, test_math_numbers_ceil_divide) +{ + int params[8] = { + -1000, + 300, + 123, + -10, + 1337, + -6, + 999, + -2 + }; + + int i, j; + + for (i = 0; i < ARRAY_SIZE(params); ++i) { + for (j = 0; j < ARRAY_SIZE(params); ++j) { + int ref = ceilf((float)params[i] / (float)params[j]); + int r = ceil_divide(params[i], params[j]); + + zassert_equal(r, ref, + "ceil_divide(%d, %d) = %d, expected %d", + params[i], params[j], r, ref); + } + } +} diff --git a/test/ztest/unit/math/basic/arithmetic/test_crc32_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_crc32_ztest.c new file mode 100644 index 000000000000..7485fc13dbc8 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_crc32_ztest.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. All rights reserved. +// +// Author: Tomasz Leman <tomasz.m.leman@intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> +#include <stdint.h> + +/** + * @brief Test crc32 with an empty buffer + * + * With zero bytes the outer loop does not execute and the function returns + * ~(~base) == 0 for base == 0. + */ +ZTEST(math_arithmetic_suite, test_math_numbers_crc32_empty_buffer) +{ + uint8_t data[1] = {0}; + uint32_t result = crc32(0, data, 0); + + zassert_equal(result, 0x00000000U, + "crc32 of empty buffer with base=0 should be 0x00000000"); +} + +/** + * @brief Test crc32 with a single zero byte + * + * Exercises one iteration of the outer loop and all 8 iterations of the + * inner bit-processing loop. + */ +ZTEST(math_arithmetic_suite, test_math_numbers_crc32_single_zero_byte) +{ + uint8_t data[] = {0x00}; + uint32_t result = crc32(0, data, sizeof(data)); + + zassert_equal(result, 0xD202EF8DU, + "crc32({0x00}, base=0) should be 0xD202EF8D"); +} + +/** + * @brief Test crc32 with a single 0xFF byte + * + * Exercises the branch where (cur & 1) is false in the inner loop. + */ +ZTEST(math_arithmetic_suite, test_math_numbers_crc32_single_ff_byte) +{ + uint8_t data[] = {0xFF}; + uint32_t result = crc32(0, data, sizeof(data)); + + zassert_equal(result, 0xFF000000U, + "crc32({0xFF}, base=0) should be 0xFF000000"); +} + +/** + * @brief Test crc32 against the well-known CRC-32 check value + * + * The string "123456789" must produce 0xCBF43926 — the standard reference + * value for CRC-32 (ISO 3309 / ITU-T V.42). + */ +ZTEST(math_arithmetic_suite, test_math_numbers_crc32_known_vector_123456789) +{ + const uint8_t data[] = "123456789"; + uint32_t result = crc32(0, data, sizeof(data) - 1); /* exclude NUL */ + + zassert_equal(result, 0xCBF43926U, + "crc32(\"123456789\", base=0) should be 0xCBF43926"); +} + +/** + * @brief Test crc32 with a non-zero base + * + * A non-zero base changes the initial CRC register value (~base), allowing + * incremental / chained CRC computation. Verifies the result differs from the + * base=0 case and matches the expected precomputed value. + */ +ZTEST(math_arithmetic_suite, test_math_numbers_crc32_nonzero_base) +{ + uint8_t data[] = {0xAB, 0xCD, 0xEF}; + uint32_t result_base0 = crc32(0x00000000U, data, sizeof(data)); + uint32_t result_nonzero = crc32(0xDEADBEEFU, data, sizeof(data)); + + zassert_equal(result_base0, 0x648D3D79U, + "crc32({0xAB,0xCD,0xEF}, base=0) should be 0x648D3D79"); + zassert_equal(result_nonzero, 0x1412F659U, + "crc32({0xAB,0xCD,0xEF}, base=0xDEADBEEF) should be 0x1412F659"); + zassert_not_equal(result_base0, result_nonzero, + "Different bases must yield different CRC values"); +} + +/** + * @brief Test crc32 over a four-byte all-zeros buffer + * + * Exercises multiple iterations of the outer byte loop, producing a result + * that differs from the single-byte zero-byte case. + */ +ZTEST(math_arithmetic_suite, test_math_numbers_crc32_four_zero_bytes) +{ + uint8_t data[] = {0x00, 0x00, 0x00, 0x00}; + uint32_t result = crc32(0, data, sizeof(data)); + + zassert_equal(result, 0x2144DF1CU, + "crc32({0,0,0,0}, base=0) should be 0x2144DF1C"); +} diff --git a/test/ztest/unit/math/basic/arithmetic/test_find_equal_int16_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_find_equal_int16_ztest.c new file mode 100644 index 000000000000..268b031eb3e2 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_find_equal_int16_ztest.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// Original tests from test/cmocka/src/math/numbers/find_equal_int16.c: +// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> + +/** + * @brief Test find_equal_int16 function with array containing matches + * + * Tests that find_equal_int16 correctly finds all indices where value 123 + * appears in the array [5, 123, 5, 10, 123, 500, 123] + */ +ZTEST(math_arithmetic_suite, test_math_numbers_find_equal_int16_matches) +{ + int16_t r[4]; + int16_t vec[] = {5, 123, 5, 10, 123, 500, 123}; + int16_t template[] = {1, 4, 6}; + + int r_num = find_equal_int16(r, vec, 123, 7, 4); + + zassert_equal(r_num, 3, "Should find 3 occurrences of 123"); + zassert_mem_equal(r, template, sizeof(int16_t) * 3, + "Result indices should match expected template"); +} + +/** + * @brief Test find_equal_int16 function with no matches + * + * Tests that find_equal_int16 returns 0 when searching for value 0 + * in array [1, 2, 3, 4, 5] where it doesn't exist + */ +ZTEST(math_arithmetic_suite, test_math_numbers_find_equal_int16_no_matches) +{ + int16_t r[4]; + int16_t vec[] = {1, 2, 3, 4, 5}; + + int r_num = find_equal_int16(r, vec, 0, 5, 4); + + zassert_equal(r_num, 0, "Should find 0 occurrences of 0"); +} diff --git a/test/ztest/unit/math/basic/arithmetic/test_find_max_abs_int32_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_find_max_abs_int32_ztest.c new file mode 100644 index 000000000000..7b978188c9a7 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_find_max_abs_int32_ztest.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// Original tests from test/cmocka/src/math/numbers/find_max_abs_int32.c: +// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> +#include <sof/common.h> + +/** + * @brief Test find_max_abs_int32 function with negative maximum absolute value + * + * Tests that find_max_abs_int32 correctly finds maximum absolute value + * in array [-100, 99, 98, 50] where -100 has the largest absolute value + */ +ZTEST(math_arithmetic_suite, test_math_numbers_find_max_abs_int32_negative_max) +{ + int32_t vec[] = {-100, 99, 98, 50}; + int32_t r = find_max_abs_int32(vec, ARRAY_SIZE(vec)); + + zassert_equal(r, 100, "find_max_abs_int32([-100, 99, 98, 50]) should return 100"); +} + +/** + * @brief Test find_max_abs_int32 function with positive maximum absolute value + * + * Tests that find_max_abs_int32 correctly finds maximum absolute value + * in array [-100, 99, 98, 50, 101] where 101 has the largest absolute value + */ +ZTEST(math_arithmetic_suite, test_math_numbers_find_max_abs_int32_positive_max) +{ + int32_t vec[] = {-100, 99, 98, 50, 101}; + int32_t r = find_max_abs_int32(vec, ARRAY_SIZE(vec)); + + zassert_equal(r, 101, "find_max_abs_int32([-100, 99, 98, 50, 101]) should return 101"); +} diff --git a/test/ztest/unit/math/basic/arithmetic/test_find_min_int16_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_find_min_int16_ztest.c new file mode 100644 index 000000000000..ac9225081a43 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_find_min_int16_ztest.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// Original tests from test/cmocka/src/math/numbers/find_min_int16.c: +// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> +#include <sof/common.h> + +/** + * @brief Test find_min_int16 function with single element array + * + * Tests that find_min_int16 returns the single element when array has one item + */ +ZTEST(math_arithmetic_suite, test_math_numbers_find_min_int16_for_2_equals_2) +{ + int16_t vec[] = {2}; + int r = find_min_int16(vec, ARRAY_SIZE(vec)); + + zassert_equal(r, 2, "find_min_int16([2]) should return 2"); +} + +/** + * @brief Test find_min_int16 function with multiple elements + * + * Tests that find_min_int16 correctly finds minimum value in array [5, 2, 3, 4, 1] + */ +ZTEST(math_arithmetic_suite, test_math_numbers_find_min_int16_for_5_2_3_4_1_equals_1) +{ + int16_t vec[] = {5, 2, 3, 4, 1}; + int r = find_min_int16(vec, ARRAY_SIZE(vec)); + + zassert_equal(r, 1, "find_min_int16([5, 2, 3, 4, 1]) should return 1"); +} diff --git a/test/ztest/unit/math/basic/arithmetic/test_gcd_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_gcd_ztest.c new file mode 100644 index 000000000000..508afaecb8e1 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_gcd_ztest.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// Original tests from test/cmocka/src/math/numbers/gcd.c: +// Author: Marcin Maka <marcin.maka@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> + +/** + * @brief Test GCD function with typical case + * + * Tests that gcd(5083, 391) returns 391 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_5083_and_391_equals_391) +{ + int r; + + r = gcd(5083, 391); + zassert_equal(r, 391, "gcd(5083, 391) should equal 391"); +} + +/** + * @brief Test GCD function with small positive numbers + * + * Tests that gcd(12, 9) returns 3 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_12_and_9_equals_3) +{ + int r; + + r = gcd(12, 9); + zassert_equal(r, 3, "gcd(12, 9) should equal 3"); +} + +/** + * @brief Test GCD function with zero second argument + * + * Tests that gcd(5, 0) returns 5 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_5_and_0_equals_5) +{ + int r; + + r = gcd(5, 0); + zassert_equal(r, 5, "gcd(5, 0) should equal 5"); +} + +/** + * @brief Test GCD function with zero first argument + * + * Tests that gcd(0, 5) returns 5 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_0_and_5_equals_5) +{ + int r; + + r = gcd(0, 5); + zassert_equal(r, 5, "gcd(0, 5) should equal 5"); +} + +/** + * @brief Test GCD function with both arguments zero + * + * Tests that gcd(0, 0) returns 0 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_0_and_0_equals_0) +{ + int r; + + r = gcd(0, 0); + zassert_equal(r, 0, "gcd(0, 0) should equal 0"); +} + +/** + * @brief Test GCD function with negative first argument + * + * Tests that gcd(-4, 14) returns 2 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_neg_4_and_14_equals_2) +{ + int r; + + r = gcd(-4, 14); + zassert_equal(r, 2, "gcd(-4, 14) should equal 2"); +} + +/** + * @brief Test GCD function with negative second argument + * + * Tests that gcd(4, -14) returns 2 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_4_and_neg_14_equals_2) +{ + int r; + + r = gcd(4, -14); + zassert_equal(r, 2, "gcd(4, -14) should equal 2"); +} + +/** + * @brief Test GCD function with both arguments negative + * + * Tests that gcd(-4, -14) returns 2 + */ +ZTEST(math_arithmetic_suite, test_math_numbers_gcd_for_neg_4_and_neg_14_equals_2) +{ + int r; + + r = gcd(-4, -14); + zassert_equal(r, 2, "gcd(-4, -14) should equal 2"); +} + +/** + * @brief Define and initialize the math arithmetic test suite + */ +ZTEST_SUITE(math_arithmetic_suite, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/math/basic/arithmetic/test_norm_int32_ztest.c b/test/ztest/unit/math/basic/arithmetic/test_norm_int32_ztest.c new file mode 100644 index 000000000000..4e3d1b830817 --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/test_norm_int32_ztest.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// Original tests from test/cmocka/src/math/numbers/norm_int32.c: +// Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com> + +#include <zephyr/ztest.h> +#include <sof/math/numbers.h> + +/** + * @brief Test norm_int32 function with zero value + * + * Tests that norm_int32(0) returns 31 (number of leading zeros in 32-bit zero) + */ +ZTEST(math_arithmetic_suite, test_math_numbers_norm_int32_for_0_equals_31) +{ + int r = norm_int32(0); + + zassert_equal(r, 31, "norm_int32(0) should return 31"); +} + +/** + * @brief Test norm_int32 function with small positive value + * + * Tests that norm_int32(35) returns 25 (number of leading zeros) + */ +ZTEST(math_arithmetic_suite, test_math_numbers_norm_int32_for_35_equals_25) +{ + int r = norm_int32(35); + + zassert_equal(r, 25, "norm_int32(35) should return 25"); +} + +/** + * @brief Test norm_int32 function with maximum positive value + * + * Tests that norm_int32(INT32_MAX) returns 0 (no leading zeros in max int32) + */ +ZTEST(math_arithmetic_suite, test_math_numbers_norm_int32_for_int32_max_equals_0) +{ + int r = norm_int32(INT32_MAX); + + zassert_equal(r, 0, "norm_int32(INT32_MAX) should return 0"); +} diff --git a/test/ztest/unit/math/basic/arithmetic/testcase.yaml b/test/ztest/unit/math/basic/arithmetic/testcase.yaml new file mode 100644 index 000000000000..8afd7eca7daa --- /dev/null +++ b/test/ztest/unit/math/basic/arithmetic/testcase.yaml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2025 Intel Corporation. All rights reserved. +# +# Math basic arithmetic unit tests converted from CMock to Ztest +# +# These contents may have been developed with support from one or more Intel-operated +# generative artificial intelligence solutions. +# + +tests: + sof.unit.math.basic.arithmetic: + tags: math arithmetic numbers + platform_allow: native_sim + integration_platforms: + - native_sim + build_only: false diff --git a/test/ztest/unit/math/basic/complex/CMakeLists.txt b/test/ztest/unit/math/basic/complex/CMakeLists.txt new file mode 100644 index 000000000000..db756e341b5b --- /dev/null +++ b/test/ztest/unit/math/basic/complex/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_math_complex) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../../../..") + +target_include_directories(app PRIVATE + ${SOF_ROOT}/zephyr/include + ${SOF_ROOT}/src/include +) + +# Define SOF-specific configurations for unit testing +target_compile_definitions(app PRIVATE + -DCONFIG_ZEPHYR_POSIX=1 + -DCONFIG_LIBRARY=1 + -DUNIT_TEST=1 +) + +target_sources(app PRIVATE + test_complex_polar.c + ${SOF_ROOT}/src/math/complex.c + ${SOF_ROOT}/src/math/sqrt_int32.c + ${SOF_ROOT}/src/math/trig.c + ${SOF_ROOT}/src/math/atan2.c +) + +# Link math library for standard math functions +target_link_libraries(app PRIVATE m) diff --git a/test/ztest/unit/math/basic/complex/prj.conf b/test/ztest/unit/math/basic/complex/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/math/basic/complex/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/math/basic/complex/test_complex_polar.c b/test/ztest/unit/math/basic/complex/test_complex_polar.c new file mode 100644 index 000000000000..22d5e1d3471b --- /dev/null +++ b/test/ztest/unit/math/basic/complex/test_complex_polar.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2026 Intel Corporation. + +#include <math.h> +#include <sof/common.h> +#include <sof/math/icomplex32.h> +#include <zephyr/logging/log.h> +#include <zephyr/ztest.h> + +/* Test data tables from Octave generated reference */ +#include "test_complex_polar_tables.h" + +LOG_MODULE_REGISTER(test_complex_polar, LOG_LEVEL_INF); + +#define COMPLEX_ABS_TOL 1.2e-8 +#define MAGNITUDE_ABS_TOL 7.1e-8 +#define ANGLE_ABS_TOL 2.0e-5 + +/** + * @brief Test complex to polar conversion function + * + * This test validates the icomplex32_to_polar() function against + * Octave-generated reference values. The test includes 1000 data points. + * + * Complex number values are Q1.31 -1.0 to +1.0 + * Polar magnitude values are Q2.30 0 to +2.0 + * Polar angle values are Q3.29 from -pi to +pi + */ +ZTEST(math_complex, test_icomplex32_to_polar) +{ + struct icomplex32 complex, complex_mag_max, complex_ang_max; + struct ipolar32 polar; + double ref_magnitude, ref_angle; + double magnitude, angle; + double delta_mag, delta_ang; + double magnitude_scale_q30 = 1.0 / 1073741824.0; /* 1.0 / 2^30 */ + double angle_scale_q29 = 1.0 / 536870912.0; /* 1.0 / 2^29 */ + double delta_mag_max = 0; + double delta_ang_max = 0; + int i; + + for (i = 0; i < TEST_COMPLEX_POLAR_NUM_POINTS; i++) { + complex.real = test_real_values[i]; + complex.imag = test_imag_values[i]; + ref_magnitude = magnitude_scale_q30 * test_magnitude_values[i]; + ref_angle = angle_scale_q29 * test_angle_values[i]; + sofm_icomplex32_to_polar(&complex, &polar); + + magnitude = magnitude_scale_q30 * polar.magnitude; + delta_mag = fabs(ref_magnitude - magnitude); + if (delta_mag > delta_mag_max) { + delta_mag_max = delta_mag; + complex_mag_max = complex; + } + + angle = angle_scale_q29 * polar.angle; + delta_ang = fabs(ref_angle - angle); + if (delta_ang > delta_ang_max) { + delta_ang_max = delta_ang; + complex_ang_max = complex; + } + + zassert_true(delta_mag <= MAGNITUDE_ABS_TOL, "Magnitude calc error at (%d, %d)", + complex.real, complex.imag); + zassert_true(delta_ang <= ANGLE_ABS_TOL, "Angle calc error at (%d, %d)", + complex.real, complex.imag); + } + + /* Re-run worst cases to print info */ + sofm_icomplex32_to_polar(&complex_mag_max, &polar); + printf("delta_mag_max = %g at (%d, %d) -> (%d, %d)\n", delta_mag_max, complex_mag_max.real, + complex_mag_max.imag, polar.magnitude, polar.angle); + + sofm_icomplex32_to_polar(&complex_ang_max, &polar); + printf("delta_ang_max = %g at (%d, %d) -> (%d, %d)\n", delta_ang_max, complex_ang_max.real, + complex_ang_max.imag, polar.magnitude, polar.angle); +} + +ZTEST(math_complex, test_ipolar32_to_complex) +{ + struct icomplex32 complex; + struct ipolar32 polar, polar_real_max, polar_imag_max; + double ref_real, ref_imag; + double real, imag; + double delta_real, delta_imag; + double scale_q31 = 1.0 / 2147483648.0; + double delta_real_max = 0; + double delta_imag_max = 0; + int i; + + for (i = 0; i < TEST_COMPLEX_POLAR_NUM_POINTS; i++) { + polar.magnitude = test_magnitude_values[i]; + polar.angle = test_angle_values[i]; + ref_real = scale_q31 * test_real_values[i]; + ref_imag = scale_q31 * test_imag_values[i]; + sofm_ipolar32_to_complex(&polar, &complex); + + real = scale_q31 * complex.real; + delta_real = fabs(ref_real - real); + if (delta_real > delta_real_max) { + delta_real_max = delta_real; + polar_real_max = polar; + } + + imag = scale_q31 * complex.imag; + delta_imag = fabs(ref_imag - imag); + if (delta_imag > delta_imag_max) { + delta_imag_max = delta_imag; + polar_imag_max = polar; + } + + zassert_true(delta_real <= COMPLEX_ABS_TOL, "Real calc error at (%d, %d)", + polar.magnitude, polar.angle); + zassert_true(delta_imag <= COMPLEX_ABS_TOL, "Imag calc error at (%d, %d)", + polar.magnitude, polar.angle); + } + + /* Re-run worst cases to print info */ + sofm_ipolar32_to_complex(&polar_real_max, &complex); + printf(" INFO - delta_real_max = %g at (%d, %d) -> (%d, %d)\n", delta_real_max, + polar_real_max.magnitude, polar_real_max.angle, complex.real, complex.imag); + + sofm_ipolar32_to_complex(&polar_imag_max, &complex); + printf(" INFO - delta_imag_max = %g at (%d, %d) -> (%d, %d)\n", delta_imag_max, + polar_imag_max.magnitude, polar_imag_max.angle, complex.real, complex.imag); +} + +ZTEST_SUITE(math_complex, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/math/basic/complex/test_complex_polar_reference.m b/test/ztest/unit/math/basic/complex/test_complex_polar_reference.m new file mode 100644 index 000000000000..5f7bed37b682 --- /dev/null +++ b/test/ztest/unit/math/basic/complex/test_complex_polar_reference.m @@ -0,0 +1,78 @@ +function test_complex_polar_reference() + + % Make a box flattened spiral of (re,im) values to exercise the + % Q1.31 complex numbers range + q31_scale = 2^31; + num_points = 1000; + magnitude0 = linspace(0, sqrt(2), num_points); + angle0 = pi/4 + linspace(0, 10*2*pi, num_points); + re = max(min(magnitude0 .* cos(angle0), 1), -1); + im = max(min(magnitude0 .* sin(angle0), 1), -1); + ref_re = int32(re * q31_scale); + ref_im = int32(im * q31_scale); + re = double(ref_re)/q31_scale; + im = double(ref_im)/q31_scale; + figure(1) + plot(re, im) + grid on + + % In polar format magnitude is Q2.30 and angle Q3.29 + q29_scale = 2^29; + q30_scale = 2^30; + magnitude = sqrt(re.^2 + im.^2); + phase = angle(complex(re, im)); + ref_magnitude = int32(magnitude * q30_scale); + ref_angle = int32(phase * q29_scale); + magnitude = double(ref_magnitude)/q30_scale; + phase = double(ref_angle)/q29_scale; + + figure(2) + subplot(2,1,1); + plot(magnitude); + grid on + subplot(2,1,2); + plot(phase); + grid on + + fh = export_headerfile('test_complex_polar_tables.h'); + dn = 'TEST_COMPLEX_POLAR_NUM_POINTS'; + vl = 6; + export_define(fh, dn, num_points); + export_array(fh, 'test_real_values', dn, vl, ref_re); + export_array(fh, 'test_imag_values', dn, vl, ref_im); + export_array(fh, 'test_magnitude_values', dn, vl, ref_magnitude); + export_array(fh, 'test_angle_values', dn, vl, ref_angle); + fclose(fh); + +end + +function fh = export_headerfile(headerfn) + fh = fopen(headerfn, 'w'); + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s Intel Corporation.\n', ... + datestr(now, 'yyyy')); + fprintf(fh, ' */\n\n'); +end + +function export_define(fh, dn, val) + fprintf(fh, '#define %s %d\n', dn, val); +end + +function export_array(fh, vn, size_str, vl, data) + fprintf(fh, '\n'); + fprintf(fh, 'static const int32_t %s[%s] = {\n', vn, size_str); + + n = length(data); + k = 0; + for i = 1:vl:n + fprintf(fh, '\t'); + for j = 1:min(vl, n-k) + k = k + 1; + fprintf(fh, '%12d,', data(k)); + end + fprintf(fh, '\n'); + end + + fprintf(fh, '};\n'); +end diff --git a/test/ztest/unit/math/basic/complex/test_complex_polar_tables.h b/test/ztest/unit/math/basic/complex/test_complex_polar_tables.h new file mode 100644 index 000000000000..638768767ae6 --- /dev/null +++ b/test/ztest/unit/math/basic/complex/test_complex_polar_tables.h @@ -0,0 +1,686 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#define TEST_COMPLEX_POLAR_NUM_POINTS 1000 + +static const int32_t test_real_values[TEST_COMPLEX_POLAR_NUM_POINTS] = { + 0, 2010271, 3725920, 5124845, 6187393, 6896488, + 7237756, 7199623, 6773402, 5953363, 4736785, 3123990, + 1118360, -1273667, -4042611, -7175994, -10658392, -14471508, + -18594262, -23002899, -27671114, -32570187, -37669141, -42934909, + -48332514, -53825266, -59374967, -64942126, -70486186, -75965757, + -81338858, -86563159, -91596238, -96395831, -100920087, -105127827, + -108978795, -112433915, -115455535, -118007677, -120056267, -121569369, + -122517407, -122873369, -122613014, -121715052, -120161316, -117936927, + -115030428, -111433912, -107143132, -102157588, -96480602, -90119364, + -83084968, -75392423, -67060644, -58112422, -48574376, -38476879, + -27853971, -16743244, -5185716, 6774328, 19089497, 31709487, + 44581284, 57649387, 70856046, 84141512, 97444305, 110701494, + 123848984, 136821814, 149554472, 161981203, 174036334, 185654596, + 196771457, 207323444, 217248478, 226486192, 234978262, 242668716, + 249504251, 255434527, 260412465, 264394521, 267340956, 269216089, + 269988529, 269631397, 268122524, 265444636, 261585512, 256538120, + 250300736, 242877038, 234276169, 224512787, 213607079, 201584756, + 188477021, 174320506, 159157195, 143034304, 126004153, 108123999, + 89455850, 70066259, 50026081, 29410226, 8297371, -13230336, + -35087593, -57186288, -79435849, -101743616, -124015229, -146155020, + -168066426, -189652405, -210815858, -231460066, -251489116, -270808344, + -289324766, -306947511, -323588255, -339161636, -353585678, -366782188, + -378677155, -389201124, -398289563, -405883204, -411928378, -416377312, + -419188416, -420326545, -419763226, -417476873, -413452963, -407684185, + -400170564, -390919549, -379946071, -367272574, -352929002, -336952767, + -319388673, -300288814, -279712434, -257725762, -234401803, -209820111, + -184066521, -157232854, -129416598, -100720550, -71252444, -41124543, + -10453216, 20641515, 52036441, 83605659, 115221069, 146752903, + 178070250, 209041601, 239535398, 269420591, 298567200, 326846870, + 354133435, 380303474, 405236856, 428817285, 450932827, 471476430, + 490346422, 507446994, 522688663, 535988713, 547271612, 556469398, + 563522043, 568377780, 570993410, 571334557, 569375910, 565101409, + 558504407, 549587788, 538364050, 524855342, 509093464, 491119833, + 470985394, 448750502, 424484760, 398266816, 370184118, 340332636, + 308816539, 275747839, 241246001, 205437508, 168455409, 130438820, + 91532404, 51885823, 11653162, -29007671, -69935565, -110966841, + -151935909, -192675939, -233019531, -272799413, -311849123, -350003711, + -387100428, -422979418, -457484405, -490463364, -521769184, -551260318, + -578801413, -604263917, -627526666, -648476446, -667008521, -683027136, + -696445987, -707188646, -715188962, -720391416, -722751431, -722235644, + -718822138, -712500616, -703272542, -691151224, -676161857, -658341510, + -637739067, -614415122, -588441819, -559902651, -528892197, -495515829, + -459889360, -422138650, -382399165, -340815504, -297540866, -252736498, + -206571092, -159220151, -110865324, -61693712, -11897138, 38328592, + 88784468, 139269058, 189579315, 239511395, 288861476, 337426598, + 385005490, 431399405, 476412946, 519854889, 561538988, 601284771, + 638918316, 674273001, 707190239, 737520175, 765122358, 789866376, + 811632461, 830312042, 845808268, 858036480, 866924641, 872413711, + 874457976, 873025324, 868097468, 859670112, 847753061, 832370279, + 813559881, 791374074, 765879040, 737154758, 705294769, 670405888, + 632607856, 592032937, 548825466, 503141340, 455147462, 405021134, + 352949406, 299128380, 243762474, 187063647, 129250588, 70547873, + 11185092, -48604046, -108582637, -168511515, -228150215, -287257925, + -345594471, -402921282, -459002370, -513605298, -566502143, -617470444, + -666294131, -712764442, -756680808, -797851714, -836095524, -871241275, + -903129435, -931612608, -956556208, -977839072, -995354034, -1009008434, + -1018724582, -1024440155, -1026108541, -1023699117, -1017197463, -1006605519, + -991941664, -973240745, -950554022, -923949063, -893509556, -859335070, + -821540743, -780256901, -735628623, -687815235, -636989754, -583338260, + -527059225, -468362778, -407469927, -344611725, -280028399, -213968429, + -146687596, -78447990, -9516990, 59833783, 129329538, 198693400, + 267647516, 335914167, 403216884, 469281571, 533837615, 596618999, + 657365393, 715823231, 771746768, 824899108, 875053204, 921992824, + 965513473, 1005423279, 1041543829, 1073710959, 1101775481, 1125603867, + 1145078861, 1160100036, 1170584284, 1176466239, 1177698625, 1174252547, + 1166117690, 1153302463, 1135834055, 1113758421, 1087140193, 1056062514, + 1020626795, 980952399, 937176255, 889452389, 837951397, 782859836, + 724379560, 662726978, 598132266, 530838500, 461100754, 389185126, + 315367731, 239933637, 163175768, 85393765, 6892818, -72017533, + -151024619, -229813879, -308070111, -385478738, -461727067, -536505555, + -609509063, -680438101, -749000052, -814910383, -877893819, -937685487, + -994032034, -1046692688, -1095440283, -1140062237, -1180361463, -1216157237, + -1247285993, -1273602059, -1294978319, -1311306812, -1322499248, -1328487452, + -1329223727, -1324681139, -1314853718, -1299756576, -1279425943, -1253919113, + -1223314312, -1187710477, -1147226950, -1102003096, -1052197829, -997989064, + -939573091, -877163865, -810992232, -741305080, -668364414, -592446383, + -513840229, -432847191, -349779351, -264958429, -178714543, -91384921, + -3312582, 85155009, 173667311, 261872102, 349416872, 435950238, + 521123353, 604591309, 686014536, 765060179, 841403464, 914729020, + 984732190, 1051120287, 1113613817, 1171947650, 1225872142, 1275154193, + 1319578251, 1358947246, 1393083452, 1421829276, 1445047976, 1462624287, + 1474464972, 1480499286, 1480679346, 1474980420, 1463401119, 1445963494, + 1422713045, 1393718635, 1359072305, 1318889005, 1273306222, 1222483522, + 1166602002, 1105863652, 1040490631, 970724462, 896825138, 819070164, + 737753515, 653184524, 565686712, 475596548, 383262159, 289041982, + 193303378, 96421195, -1223696, -99245902, -197257024, -294867199, + -391686652, -487327250, -581404058, -673536888, -763351836, -850482796, + -934572954, -1015276244, -1092258774, -1165200200, -1233795059, -1297754046, + -1356805225, -1410695180, -1459190100, -1502076781, -1539163558, -1570281144, + -1595283397, -1614047983, -1626476954, -1632497230, -1632060983, -1625145921, + -1611755471, -1591918856, -1565691082, -1533152805, -1494410107, -1449594166, + -1398860823, -1342390050, -1280385322, -1213072890, -1140700959, -1063538782, + -981875656, -896019849, -806297430, -713051040, -616638580, -517431842, + -415815073, -312183493, -206941750, -100502348, 6715973, 114289887, + 221793148, 328798283, 434878288, 539608337, 642567479, 743340331, + 841518752, 936703496, 1028505836, 1116549146, 1200470449, 1279921905, + 1354572256, 1424108199, 1488235698, 1546681223, 1599192907, 1645541631, + 1685522007, 1718953282, 1745680143, 1765573419, 1778530688, 1784476774, + 1783364142, 1775173175, 1759912353, 1737618309, 1708355783, 1672217452, + 1629323661, 1579822034, 1523886975, 1461719066, 1393544352, 1319613531, + 1240201029, 1155603995, 1066141184, 972151767, 873994039, 772044064, + 666694228, 558351735, 447437031, 334382174, 219629153, 103628158, + -13164188, -130286620, -247275059, -363664447, -478990597, -592792047, + -704611899, -813999660, -920513054, -1023719807, -1123199405, -1218544801, + -1309364080, -1395282072, -1475941891, -1551006421, -1620159719, -1683108337, + -1739582565, -1789337578, -1832154489, -1867841304, -1896233769, -1917196112, + -1930621670, -1936433411, -1934584326, -1925057716, -1907867350, -1883057503, + -1850702880, -1810908409, -1763808919, -1709568693, -1648380911, -1580466964, + -1506075665, -1425482338, -1338987809, -1246917285, -1149619133, -1047463566, + -940841237, -830161746, -715852069, -598354909, -478126986, -355637260, + -231365102, -105798420, 20568260, 147235736, 273702109, 399464766, + 524022380, 646876907, 767535579, 885512881, 1000332498, 1111529244, + 1218650944, 1321260268, 1418936519, 1511277353, 1597900434, 1678445014, + 1752573434, 1819972530, 1880354956, 1933460397, 1979056689, 2016940822, + 2046939832, 2068911577, 2082745395, 2088362629, 2085717041, 2074795083, + 2055616049, 2028232093, 1992728115, 1949221519, 1897861838, 1838830236, + 1772338873, 1698630153, 1617975845, 1530676089, 1437058282, 1337475852, + 1232306929, 1121952911, 1006836935, 887402254, 764110532, 637440063, + 507883912, 375948001, 242149128, 107012950, -28928090, -165136854, + -301073636, -436198297, -569972415, -701861428, -831336767, -957877980, + -1080974821, -1200129303, -1314857719, -1424692595, -1529184604, -1627904392, + -1720444345, -1806420269, -1885472979, -1957269800, -2021505955, -2077905857, + -2126224286, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2134427233, -2087152629, + -2031478388, -1967602767, -1895757115, -1816205050, -1729241491, -1635191576, + -1534409444, -1427276909, -1314202015, -1195617484, -1071979063, -943763772, + -811468066, -675605914, -536706801, -395313667, -251980784, -107271583, + 38243559, 183989571, 329388955, 473864078, 616839468, 757744102, + 896013690, 1031092931, 1162437746, 1289517467, 1411816980, 1528838814, + 1640105159, 1745159817, 1843570071, 1934928464, 2018854482, 2094996135, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2095882397, 2018631901, 1933188085, + 1839869214, 1739025602, 1631038305, 1516317685, 1395301849, 1268454981, + 1136265566, 999244503, 857923137, 712851198, 564594663, 413733548, + 260859639, 106574173, -48514532, -203793467, -358647365, -512461128, + -664622282, -814523405, -961564559, -1105155685, -1244718977, -1379691200, + -1509525966, -1633695942, -1751694994, -1863040244, -1967274048, -2063965870, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2140959504, -2049575701, -1949855636, -1842174985, -1726941891, -1604595423, + -1475603904, -1340463117, -1199694407, -1053842666, -903474228, -749174669, + -591546527, -431206951, -268785283, -104920590, 59740851, 224548104, + 388848145, 551988449, 713319584, 872197794, 1027987568, 1180064182, + 1327816205, 1470647954, 1607981896, 1739260983, 1863950908, 1981542280, + 2091552701, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2059197392, 1944636555, + 1822117240, 1692107383, 1555105670, 1411639621, 1262263565, 1107556498, + 948119841, 784575098, 617561439, 447733201, 275757323, 102310727, + -71922343, -246253024, -419990557, -592445023, -762930082, -930765707, + -1095280893, -1255816341, -1411727102, -1562385162, -1707181977, -1845530925, + -1976869684, -2100662514, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2046407157, -1916561405, -1778850838, -1633804651, -1481982238, + -1323971036, -1160384254, -991858494, -819051274, -642638465, -463311644, + -281775385, -98744494, 85058813, 268907750, 452073843, 633829815, + 813452467, 990225566, 1163442693, 1332410066, 1496449324, 1654900245, + 1807123402, 1952502745, 2090448093, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, +}; + +static const int32_t test_imag_values[TEST_COMPLEX_POLAR_NUM_POINTS] = { + 0, 2280495, 4804675, 7544043, 10468320, 13545649, + 16742800, 20025381, 23358065, 26704813, 30029111, 33294205, + 36463340, 39499998, 42368139, 45032439, 47458523, 49613195, + 51464665, 52982763, 54139155, 54907533, 55263817, 55186324, + 54655939, 53656265, 52173763, 50197872, 47721119, 44739207, + 41251086, 37259012, 32768581, 27788749, 22331828, 16413469, + 10052626, 3271493, -3904569, -11447125, -19324782, -27503316, + -35945824, -44612882, -53462730, -62451464, -71533245, -80660524, + -89784269, -98854220, -107819134, -116627055, -125225582, -133562147, + -141584294, -149239968, -156477796, -163247376, -169499562, -175186750, + -180263151, -184685069, -188411163, -191402709, -193623847, -195041816, + -195627177, -195354030, -194200203, -192147436, -189181540, -185292545, + -180474822, -174727190, -168053001, -160460202, -151961376, -142573766, + -132319265, -121224392, -109320247, -96642432, -83230957, -69130128, + -54388396, -39058203, -23195794, -6861013, 9882924, 26969672, + 44330020, 61892171, 79582039, 97323560, 115039017, 132649379, + 150074644, 167234202, 184047196, 200432896, 216311074, 231602379, + 246228722, 260113649, 273182721, 285363882, 296587829, 306788366, + 315902751, 323872039, 330641397, 336160422, 340383425, 343269713, + 344783842, 344895851, 343581478, 340822348, 336606140, 330926726, + 323784289, 315185406, 305143109, 293676920, 280812849, 266583368, + 251027358, 234190024, 216122776, 196883092, 176534343, 155145589, + 132791360, 109551391, 85510349, 60757523, 35386492, 9494776, + -16816541, -43443203, -70278199, -97212191, -124133959, -150930858, + -177489291, -203695186, -229434484, -254593631, -279060074, -302722755, + -325472612, -347203067, -367810515, -387194804, -405259702, -421913360, + -437068750, -450644099, -462563293, -472756271, -481159391, -487715772, + -492375618, -495096503, -495843637, -494590097, -491317033, -486013829, + -478678244, -469316510, -457943399, -444582251, -429264969, -412031974, + -392932124, -372022602, -349368756, -325043912, -299129152, -271713045, + -242891359, -212766730, -181448298, -149051321, -115696746, -81510765, + -46624336, -11172682, 24705234, 60867249, 97168571, 133462352, + 169600285, 205433208, 240811719, 275586798, 309610431, 342736240, + 374820102, 405720778, 435300526, 463425704, 489967369, 514801854, + 537811332, 558884360, 577916399, 594810315, 609476843, 621835035, + 631812669, 639346627, 644383234, 646878573, 646798747, 644120109, + 638829452, 630924157, 620412291, 607312670, 591654878, 573479230, + 552836704, 529788822, 504407482, 476774755, 446982629, 415132713, + 381335905, 345712005, 308389303, 269504118, 229200302, 187628715, + 144946659, 101317283, 56908963, 11894650, -33548800, -79241326, + -125000369, -170641608, -215979698, -260829021, -305004451, -348322109, + -390600134, -431659438, -471324465, -509423935, -545791581, -580266864, + -612695679, -642931032, -670833695, -696272835, -719126612, -739282748, + -756639051, -771103915, -782596769, -791048488, -796401763, -798611419, + -797644690, -793481442, -786114351, -775549022, -761804063, -744911098, + -724914741, -701872496, -675854626, -646943948, -615235591, -580836694, + -543866053, -504453723, -462740564, -418877743, -373026195, -325356033, + -276045917, -225282393, -173259184, -120176451, -66240028, -11660620, + 43347018, 98564927, 153772807, 208748896, 263270860, 317116694, + 370065621, 421899000, 472401226, 521360624, 568570334, 613829180, + 656942528, 697723108, 735991831, 771578561, 804322866, 834074727, + 860695216, 884057126, 904045564, 920558492, 933507222, 942816860, + 948426696, 950290537, 948376986, 942669659, 933167350, 919884121, + 902849348, 882107693, 857719013, 829758219, 798315059, 763493846, + 725413129, 684205295, 640016118, 593004254, 543340674, 491208047, + 436800076, 380320774, 321983708, 262011190, 200633431, 138087661, + 74617206, 10470549, -54099646, -118837530, -183485081, -247783134, + -311472418, -374294603, -435993344, -496315331, -555011323, -611837177, + -666554862, -718933455, -768750105, -815790985, -859852197, -900740653, + -938274911, -972285972, -1002618031, -1029129172, -1051692022, -1070194342, + -1084539559, -1094647244, -1100453524, -1101911425, -1098991157, -1091680325, + -1079984072, -1063925154, -1043543944, -1018898360, -990063728, -957132573, + -920214336, -879435024, -834936792, -786877452, -735429928, -680781633, + -623133796, -562700722, -499709000, -434396656, -367012256, -297813959, + -227068533, -155050322, -82040188, -8324413, 65806424, 140058591, + 214136368, 287743222, 360582998, 432361108, 502785721, 571568950, + 638428026, 703086462, 765275191, 824733684, 881211039, 934467032, + 984273140, 1030413508, 1072685885, 1110902496, 1144890869, 1174494601, + 1199574061, 1220007038, 1235689307, 1246535140, 1252477736, 1253469580, + 1249482727, 1240509005, 1226560146, 1207667830, 1183883652, 1155279014, + 1121944928, 1083991746, 1041548804, 994764001, 943803283, 888850071, + 830104601, 767783203, 702117507, 633353587, 561751041, 487582013, + 411130162, 332689574, 252563637, 171063864, 88508687, 5222207, + -78467074, -162227550, -245725826, -328628042, -410601210, -491314552, + -570440832, -647657683, -722648920, -795105831, -864728447, -931226783, + -994322041, -1053747774, -1109251010, -1160593320, -1207551838, -1249920218, + -1287509538, -1320149123, -1347687313, -1369992150, -1386951992, -1398476047, + -1404494823, -1404960503, -1399847223, -1389151273, -1372891207, -1351107860, + -1323864282, -1291245579, -1253358666, -1210331933, -1162314819, -1109477306, + -1052009323, -990120072, -924037270, -854006320, -780289398, -703164480, + -622924289, -539875196, -454336043, -366636924, -277117911, -186127736, + -94022433, -1163946, 92081298, 185343827, 278252596, 370436457, + 461525644, 551153259, 638956742, 724579345, 807671574, 887892617, + 964911740, 1038409650, 1108079811, 1173629724, 1234782149, 1291276269, + 1342868805, 1389335049, 1430469836, 1466088443, 1496027403, 1520145244, + 1538323138, 1550465462, 1556500276, 1556379693, 1550080173, 1537602702, + 1518972892, 1494240964, 1463481650, 1426793984, 1384301002, 1336149343, + 1282508749, 1223571484, 1159551643, 1090684388, 1017225083, 939448359, + 857647080, 772131254, 683226852, 591274574, 496628537, 399654920, + 300730542, 200241404, 98581176, -3850338, -106648779, -209406823, + -311715799, -413167311, -513354874, -611875536, -708331500, -802331731, + -893493540, -981444140, -1065822168, -1146279171, -1222481036, -1294109383, + -1360862883, -1422458528, -1478632818, -1529142890, -1573767555, -1612308258, + -1644589953, -1670461882, -1689798263, -1702498883, -1708489584, -1707722653, + -1700177108, -1685858871, -1664800843, -1637062866, -1602731579, -1561920169, + -1514768007, -1461440191, -1402126973, -1337043088, -1266426988, -1190539966, + -1109665203, -1024106706, -934188176, -840251780, -742656855, -641778531, + -538006296, -431742487, -323400735, -213404354, -102184684, 9820593, + 122169183, 234415920, 346114537, 456819433, 566087456, 673479672, + 778563134, 880912619, 980112355, 1075757704, 1167456813, 1254832216, + 1337522390, 1415183239, 1487489533, 1554136256, 1614839895, 1669339637, + 1717398481, 1758804263, 1793370582, 1820937624, 1841372888, 1854571804, + 1860458238, 1858984887, 1850133564, 1833915363, 1810370710, 1779569298, + 1741609902, 1696620080, 1644755759, 1586200705, 1521165879, 1449888687, + 1372632115, 1289683769, 1201354806, 1107978767, 1009910327, 907523945, + 801212438, 691385473, 578467993, 462898573, 345127714, 225616089, + 104832744, -16746748, -138642154, -260370483, -381447896, -501391630, + -619721926, -735963941, -849649659, -960319774, -1067525541, -1170830599, + -1269812742, -1364065646, -1453200533, -1536847770, -1614658403, -1686305606, + -1751486049, -1809921176, -1861358393, -1905572145, -1942364901, -1971568024, + -1993042528, -2006679721, -2012401729, -2010161898, -1999945075, -1981767762, + -1955678145, -1921755996, -1880112455, -1830889673, -1774260348, -1710427123, + -1639621871, -1562104859, -1478163796, -1388112772, -1292291083, -1191061960, + -1084811190, -973945653, -858891760, -740093820, -618012319, -493122141, + -365910719, -236876134, -106525162, 24628712, 156067320, 287269855, + 417714940, 546882693, 674256803, 799326595, 921589072, 1040550941, + 1155730603, 1266660098, 1372887010, 1473976304, 1569512113, 1659099440, + 1742365791, 1818962720, 1888567281, 1950883387, 2005643062, 2052607583, + 2091568519, 2122348637, 2144802698, 2147483647, 2147483647, 2147483647, + 2147483647, 2129411660, 2100718805, 2063618704, 2018235083, 1964724911, + 1903277871, 1834115693, 1757491361, 1673688197, 1583018816, 1485823964, + 1382471243, 1273353720, 1158888438, 1039514824, 915692999, 787902012, + 656637981, 522412174, 385749013, 247184030, 107261763, -33466378, + -174444288, -315113364, -454914717, -593291393, -729690591, -863565873, + -994379352, -1121603851, -1244725030, -1363243461, -1476676654, -1584561022, + -1686453767, -1781934703, -1870607982, -1952103729, -2026079585, -2092222141, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2098121767, -2031804437, -1957262673, -1874770773, -1784635305, + -1687193971, -1582814348, -1471892505, -1354851496, -1232139760, -1104229395, + -971614348, -834808505, -694343705, -550767672, -404641875, -256539338, + -107042392, 43259617, 193772649, 343900318, 493046257, 640616484, + 786021771, 928679993, 1068018461, 1203476217, 1334506296, 1460577931, + 1581178701, 1695816616, 1804022117, 1905350001, 1999381249, 2085724755, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2079864332, + 1991456543, 1894942798, 1790686072, 1679080943, 1560552105, 1435552756, + 1304562862, 1168087321, 1026654016, 880811774, 731128237, 578187655, + 422588602, 264941637, 105866910, -54008284, -214051971, -373630004, + -532108568, -688856702, -843248811, -994667159, -1142504345, -1286165736, + -1425071859, -1558660737, -1686390161, -1807739892, -1922213774, -2029341764, + -2128681858, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2107545118, -2004607307, -1893491944, -1774620780, + -1648447297, -1515454979, -1376155464, -1231086572, -1080810233, -925910312, + -766990339, -604671161, -439588511, -272390527, -103735200, 65712212, + 235281808, 404301694, 572100644, 738010765, 901370158, 1061525555, + 1217834934, 1369670091, 1516419162, 1657489093, 1792308030, 1920327639, + 2041025335, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2113625473, + 1995608424, 1869430904, 1735575344, 1594555664, 1446915305, 1293225136, + 1134081244, 970102629, 801928792, 630217245, 455640938, 278885624, + 100647162, -78371218, -257461692, -435914639, -613021457, -788077372, + -960384243, -1129253349, -1294008139, -1453986944, -1608545631, -1757060198, + -1898929290, -2033576637, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, -2147483648, + -2147483648, -2147483648, -2097032362, -1963508376, -1821933528, -1672852323, + -1516840140, -1354501017, -1186465312, -1013387253, -835942395, -654824984, + -470745238, -284426564, -96602715, 91985099, 280591136, 468468072, + 654869963, 839055203, 1020289478, 1197848691, 1371021856, 1539113946, + 1701448678, 1857371236, 2006250910, 2147483647, +}; + +static const int32_t test_magnitude_values[TEST_COMPLEX_POLAR_NUM_POINTS] = { + 0, 1520020, 3040040, 4560061, 6080081, 7600101, + 9120121, 10640142, 12160162, 13680182, 15200203, 16720223, + 18240243, 19760264, 21280284, 22800304, 24320324, 25840345, + 27360365, 28880385, 30400406, 31920426, 33440446, 34960466, + 36480486, 38000507, 39520527, 41040547, 42560567, 44080588, + 45600608, 47120628, 48640648, 50160669, 51680689, 53200710, + 54720730, 56240750, 57760770, 59280791, 60800811, 62320831, + 63840852, 65360871, 66880892, 68400912, 69920932, 71440953, + 72960973, 74480993, 76001014, 77521034, 79041054, 80561074, + 82081094, 83601115, 85121135, 86641156, 88161176, 89681196, + 91201216, 92721237, 94241257, 95761277, 97281297, 98801318, + 100321338, 101841358, 103361378, 104881399, 106401419, 107921439, + 109441459, 110961479, 112481500, 114001520, 115521541, 117041561, + 118561581, 120081601, 121601622, 123121642, 124641662, 126161682, + 127681703, 129201723, 130721743, 132241764, 133761784, 135281804, + 136801824, 138321845, 139841865, 141361885, 142881905, 144401926, + 145921946, 147441966, 148961987, 150482007, 152002027, 153522047, + 155042068, 156562088, 158082108, 159602128, 161122148, 162642169, + 164162189, 165682210, 167202229, 168722250, 170242270, 171762290, + 173282311, 174802331, 176322351, 177842371, 179362392, 180882412, + 182402432, 183922453, 185442473, 186962493, 188482514, 190002534, + 191522554, 193042574, 194562595, 196082615, 197602635, 199122655, + 200642676, 202162696, 203682716, 205202736, 206722757, 208242777, + 209762797, 211282818, 212802838, 214322858, 215842878, 217362899, + 218882919, 220402939, 221922959, 223442980, 224963000, 226483020, + 228003040, 229523061, 231043081, 232563101, 234083122, 235603142, + 237123162, 238643183, 240163203, 241683223, 243203243, 244723263, + 246243284, 247763304, 249283325, 250803344, 252323365, 253843385, + 255363405, 256883426, 258403446, 259923466, 261443486, 262963507, + 264483527, 266003547, 267523568, 269043588, 270563608, 272083628, + 273603648, 275123669, 276643689, 278163709, 279683730, 281203750, + 282723771, 284243790, 285763811, 287283831, 288803851, 290323872, + 291843892, 293363912, 294883932, 296403953, 297923973, 299443993, + 300964014, 302484034, 304004054, 305524074, 307044095, 308564115, + 310084135, 311604155, 313124176, 314644196, 316164216, 317684237, + 319204257, 320724277, 322244297, 323764318, 325284338, 326804358, + 328324378, 329844399, 331364419, 332884439, 334404460, 335924480, + 337444500, 338964520, 340484540, 342004561, 343524581, 345044601, + 346564622, 348084642, 349604662, 351124682, 352644703, 354164723, + 355684743, 357204764, 358724784, 360244804, 361764825, 363284845, + 364804865, 366324885, 367844906, 369364925, 370884946, 372404966, + 373924987, 375445007, 376965027, 378485047, 380005068, 381525088, + 383045108, 384565128, 386085149, 387605169, 389125189, 390645210, + 392165230, 393685250, 395205270, 396725290, 398245311, 399765331, + 401285351, 402805372, 404325392, 405845412, 407365433, 408885452, + 410405473, 411925493, 413445514, 414965534, 416485554, 418005574, + 419525595, 421045615, 422565635, 424085655, 425605676, 427125696, + 428645716, 430165737, 431685757, 433205777, 434725797, 436245818, + 437765838, 439285858, 440805879, 442325899, 443845919, 445365939, + 446885960, 448405980, 449926000, 451446020, 452966041, 454486061, + 456006081, 457526101, 459046122, 460566142, 462086162, 463606182, + 465126203, 466646223, 468166243, 469686264, 471206284, 472726304, + 474246324, 475766344, 477286365, 478806385, 480326406, 481846426, + 483366446, 484886466, 486406487, 487926507, 489446527, 490966547, + 492486568, 494006588, 495526608, 497046628, 498566649, 500086669, + 501606689, 503126709, 504646730, 506166750, 507686770, 509206791, + 510726811, 512246831, 513766851, 515286872, 516806892, 518326912, + 519846932, 521366953, 522886973, 524406993, 525927014, 527447034, + 528967054, 530487074, 532007095, 533527115, 535047135, 536567156, + 538087176, 539607196, 541127216, 542647237, 544167257, 545687277, + 547207298, 548727318, 550247338, 551767358, 553287378, 554807399, + 556327419, 557847439, 559367459, 560887480, 562407500, 563927520, + 565447540, 566967561, 568487581, 570007601, 571527622, 573047642, + 574567662, 576087683, 577607703, 579127723, 580647743, 582167764, + 583687784, 585207804, 586727824, 588247845, 589767865, 591287885, + 592807905, 594327926, 595847946, 597367966, 598887986, 600408007, + 601928027, 603448047, 604968068, 606488088, 608008108, 609528128, + 611048149, 612568169, 614088189, 615608209, 617128230, 618648250, + 620168270, 621688291, 623208311, 624728331, 626248351, 627768372, + 629288392, 630808412, 632328432, 633848453, 635368473, 636888493, + 638408513, 639928534, 641448554, 642968574, 644488595, 646008615, + 647528635, 649048656, 650568676, 652088696, 653608716, 655128736, + 656648757, 658168777, 659688797, 661208817, 662728838, 664248858, + 665768878, 667288899, 668808919, 670328939, 671848959, 673368980, + 674889000, 676409020, 677929041, 679449061, 680969081, 682489101, + 684009122, 685529142, 687049162, 688569182, 690089203, 691609223, + 693129243, 694649264, 696169284, 697689304, 699209324, 700729345, + 702249365, 703769385, 705289406, 706809426, 708329446, 709849466, + 711369487, 712889507, 714409527, 715929547, 717449568, 718969588, + 720489608, 722009629, 723529649, 725049669, 726569689, 728089710, + 729609730, 731129750, 732649770, 734169790, 735689811, 737209831, + 738729851, 740249872, 741769892, 743289912, 744809933, 746329953, + 747849973, 749369993, 750890013, 752410034, 753930054, 755450075, + 756970095, 758490115, 760010135, 761530155, 763050176, 764570196, + 766090216, 767610237, 769130257, 770650277, 772170297, 773690318, + 775210338, 776730358, 778250379, 779770399, 781290419, 782810439, + 784330460, 785850480, 787370500, 788890520, 790410540, 791930561, + 793450581, 794970601, 796490622, 798010642, 799530662, 801050682, + 802570703, 804090723, 805610743, 807130764, 808650784, 810170804, + 811690824, 813210845, 814730865, 816250885, 817770905, 819290925, + 820810946, 822330966, 823850986, 825371007, 826891027, 828411047, + 829931068, 831451088, 832971108, 834491129, 836011148, 837531169, + 839051189, 840571210, 842091230, 843611250, 845131270, 846651290, + 848171311, 849691331, 851211351, 852731372, 854251392, 855771412, + 857291432, 858811453, 860331473, 861851493, 863371513, 864891534, + 866411554, 867931574, 869451595, 870971615, 872491635, 874011655, + 875531676, 877051696, 878571716, 880091737, 881611757, 883131777, + 884651797, 886171818, 887691838, 889211858, 890731879, 892251898, + 893771919, 895291939, 896811960, 898331980, 899852000, 901372020, + 902892040, 904412061, 905932081, 907452101, 908972122, 910492142, + 912012162, 913532182, 915052203, 916572223, 918092243, 919612263, + 921132284, 922652304, 924172324, 925692345, 927212365, 928732385, + 930252405, 931772426, 933292446, 934812466, 936332486, 937852507, + 939372527, 940892547, 942412567, 943932588, 945452608, 946972629, + 948492649, 950012669, 951532689, 953052709, 954572730, 956092750, + 957612770, 959132791, 960652811, 962172831, 963692851, 965212872, + 966732892, 968252912, 969772932, 971292953, 972812973, 974332993, + 975853013, 977373034, 978893054, 980413074, 981933095, 983453115, + 984973135, 986493155, 988013176, 989533196, 991053216, 992573236, + 994093257, 995613277, 997133297, 998653318, 1000173338, 1001693358, + 1003213378, 1004733399, 1006253419, 1007773439, 1009293459, 1010813480, + 1012333500, 1013853520, 1015373541, 1016893561, 1018413581, 1019933601, + 1021453621, 1022973642, 1024493662, 1026013682, 1027533703, 1029053723, + 1030573743, 1032093763, 1033613784, 1035133804, 1036653824, 1038173844, + 1039693865, 1041213885, 1042733905, 1044253925, 1045773946, 1047293966, + 1048813986, 1050334007, 1051854027, 1053374047, 1054894067, 1056414088, + 1057934108, 1059454128, 1060974149, 1062494169, 1064014189, 1065534210, + 1067054230, 1068574250, 1070094270, 1071614290, 1073134311, 1074654331, + 1076174351, 1077694372, 1079214392, 1075074159, 1073839239, 1076911811, + 1084242979, 1086814493, 1088334513, 1089854534, 1091374554, 1092894574, + 1094414594, 1095934615, 1097454635, 1098974655, 1100494676, 1102014696, + 1103534716, 1105054737, 1106574756, 1108094777, 1109614797, 1111134818, + 1112654838, 1105056616, 1090927165, 1080831389, 1075080358, 1073872201, + 1077278612, 1085239887, 1097569294, 1113965966, 1127855041, 1129375061, + 1130895081, 1132415101, 1133935122, 1135455142, 1136975162, 1138495183, + 1140015203, 1141535223, 1143055243, 1144575264, 1146095284, 1147615304, + 1147842154, 1125625312, 1106767840, 1091782821, 1081108266, 1075080603, + 1073912076, 1077675529, 1086299119, 1099571869, 1117159003, 1138624405, + 1163456762, 1168895588, 1170415608, 1171935628, 1173455649, 1174975669, + 1176495689, 1178015709, 1179535730, 1181055750, 1182575770, 1184095790, + 1178528792, 1152019016, 1128472330, 1108493464, 1092636841, 1081376258, + 1075074891, 1073959660, 1078104106, 1087422807, 1101678336, 1120499386, + 1143406778, 1169843210, 1199202803, 1208416115, 1209936135, 1211456155, + 1212976175, 1214496196, 1216016216, 1217536236, 1219056257, 1220576277, + 1214782434, 1184290462, 1156256689, 1131353486, 1110231186, 1093487707, + 1081634615, 1075063262, 1074015791, 1078565922, 1088613102, 1103891120, + 1123989412, 1148383036, 1176466363, 1207585929, 1241069231, 1247936642, + 1249456662, 1250976682, 1252496703, 1254016723, 1255536743, 1257056764, + 1256340945, 1222304586, 1190137018, 1160551098, 1134265678, 1111978752, + 1094333946, 1081882629, 1075045792, 1074081342, 1079062587, 1089872171, + 1106212632, 1127631320, 1153554786, 1183326749, 1216244445, 1251589821, + 1285937149, 1287457169, 1288977189, 1290497210, 1292017230, 1293537250, + 1295057270, 1265753470, 1229934215, 1196063374, 1164898247, 1137205863, + 1113733957, 1095174125, 1082119627, 1075022598, 1074157226, 1079595743, + 1091202192, 1108645262, 1131427290, 1158923532, 1190424762, 1225177282, + 1262416521, 1301392660, 1325457676, 1326977696, 1328497716, 1330017737, + 1331537757, 1314181286, 1275293091, 1237665157, 1202064555, 1169294223, + 1140171061, 1115494647, 1096006851, 1082344979, 1074993838, 1074244398, + 1080167064, 1092605358, 1111191383, 1135379441, 1164490680, 1197760673, + 1234383241, 1273546443, 1314459308, 1356369797, 1364978203, 1366498223, + 1368018243, 1367014394, 1325711098, 1284952570, 1245491401, 1208135693, + 1173735197, 1143158355, 1117258715, 1096830779, 1082558095, 1074959708, + 1074343851, 1080778257, 1094083873, 1113853348, 1139489834, 1170257537, + 1205334627, 1243860995, 1284976598, 1327849145, 1371692050, 1402978709, + 1404498730, 1406018750, 1380571240, 1337375582, 1294724866, 1253407084, + 1214272034, 1178217417, 1146164888, 1119024105, 1097644601, 1082758423, + 1074920447, 1074456615, 1081431059, 1095639949, 1116633481, 1143760460, + 1176225309, 1213146647, 1253609098, 1296703903, 1341557403, 1387348781, + 1433319440, 1442499237, 1439174558, 1394273675, 1349166748, 1304603136, + 1261406489, 1220468930, 1182737216, 1149187866, 1120788809, 1098447051, + 1082945449, 1074876329, 1074583759, 1082127233, 1097275806, 1119534083, + 1148193248, 1182395100, 1221196638, 1263625993, 1308725200, 1355579289, + 1403333621, 1451202345, 1480499743, 1454909890, 1408112903, 1361076863, + 1314580734, 1269484051, 1226721846, 1187291007, 1152224555, 1122550865, + 1099236905, 1083118701, 1074827672, 1074726392, 1082868575, 1098993670, + 1122557424, 1152790055, 1188767916, 1229484394, 1273910019, 1321037258, + 1369909999, 1419640265, 1469415592, 1518500249, +}; + +static const int32_t test_angle_values[TEST_COMPLEX_POLAR_NUM_POINTS] = { + 0, 455423907, 489190152, 522956546, 556722871, 590489235, + 624255603, 658021957, 691788319, 725554680, 759321041, 793087401, + 826853754, 860620121, 894386476, 928152832, 961919193, 995685560, + 1029451923, 1063218283, 1096984641, 1130751002, 1164517360, 1198283724, + 1232050084, 1265816445, 1299582805, 1333349167, 1367115527, 1400881883, + 1434648246, 1468414607, 1502180969, 1535947328, 1569713687, 1603480052, + 1637246411, 1671012770, -1668480294, -1634713934, -1600947572, -1567181214, + -1533414852, -1499648491, -1465882130, -1432115770, -1398349410, -1364583047, + -1330816690, -1297050328, -1263283967, -1229517604, -1195751244, -1161984884, + -1128218524, -1094452163, -1060685802, -1026919441, -993153083, -959386722, + -925620362, -891853999, -858087640, -824321279, -790554919, -756788558, + -723022197, -689255837, -655489475, -621723114, -587956754, -554190394, + -520424032, -486657673, -452891312, -419124952, -385358590, -351592230, + -317825870, -284059508, -250293147, -216526788, -182760426, -148994067, + -115227706, -81461345, -47694984, -13928624, 19837736, 53604097, + 87370458, 121136819, 154903180, 188669541, 222435900, 256202261, + 289968622, 323734982, 357501343, 391267703, 425034064, 458800425, + 492566785, 526333147, 560099507, 593865868, 627632228, 661398588, + 695164950, 728931309, 762697671, 796464031, 830230391, 863996753, + 897763113, 931529473, 965295834, 999062194, 1032828555, 1066594916, + 1100361277, 1134127638, 1167893998, 1201660359, 1235426719, 1269193079, + 1302959441, 1336725801, 1370492162, 1404258523, 1438024883, 1471791244, + 1505557604, 1539323965, 1573090326, 1606856686, 1640623046, 1674389407, + -1665103658, -1631337297, -1597570937, -1563804577, -1530038216, -1496271855, + -1462505495, -1428739134, -1394972773, -1361206413, -1327440051, -1293673691, + -1259907330, -1226140970, -1192374609, -1158608249, -1124841888, -1091075528, + -1057309167, -1023542806, -989776446, -956010085, -922243724, -888477363, + -854711003, -820944642, -787178282, -753411921, -719645561, -685879201, + -652112840, -618346479, -584580118, -550813757, -517047396, -483281036, + -449514676, -415748315, -381981955, -348215594, -314449234, -280682873, + -246916512, -213150151, -179383790, -145617431, -111851070, -78084709, + -44318349, -10551988, 23214373, 56980733, 90747094, 124513454, + 158279815, 192046176, 225812537, 259578897, 293345258, 327111619, + 360877979, 394644339, 428410700, 462177061, 495943422, 529709782, + 563476143, 597242504, 631008864, 664775225, 698541586, 732307946, + 766074307, 799840668, 833607028, 867373388, 901139749, 934906110, + 968672470, 1002438831, 1036205191, 1069971552, 1103737913, 1137504273, + 1171270634, 1205036995, 1238803355, 1272569716, 1306336077, 1340102437, + 1373868797, 1407635158, 1441401519, 1475167879, 1508934240, 1542700601, + 1576466962, 1610233322, 1643999683, 1677766044, -1661727022, -1627960661, + -1594194301, -1560427940, -1526661580, -1492895219, -1459128858, -1425362498, + -1391596137, -1357829777, -1324063416, -1290297056, -1256530695, -1222764334, + -1188997973, -1155231613, -1121465252, -1087698892, -1053932531, -1020166170, + -986399810, -952633449, -918867088, -885100728, -851334367, -817568007, + -783801646, -750035285, -716268925, -682502564, -648736204, -614969843, + -581203483, -547437121, -513670761, -479904400, -446138040, -412371679, + -378605318, -344838958, -311072598, -277306237, -243539876, -209773516, + -176007155, -142240794, -108474434, -74708073, -40941712, -7175351, + 26591009, 60357370, 94123730, 127890091, 161656451, 195422812, + 229189173, 262955533, 296721894, 330488255, 364254615, 398020976, + 431787337, 465553697, 499320058, 533086418, 566852779, 600619139, + 634385500, 668151861, 701918221, 735684582, 769450943, 803217303, + 836983664, 870750024, 904516385, 938282746, 972049107, 1005815467, + 1039581828, 1073348188, 1107114549, 1140880909, 1174647270, 1208413631, + 1242179992, 1275946352, 1309712712, 1343479073, 1377245434, 1411011795, + 1444778155, 1478544515, 1512310876, 1546077237, 1579843598, 1613609958, + 1647376319, 1681142680, -1658350386, -1624584025, -1590817665, -1557051304, + -1523284944, -1489518583, -1455752222, -1421985862, -1388219501, -1354453140, + -1320686780, -1286920419, -1253154059, -1219387698, -1185621337, -1151854977, + -1118088616, -1084322256, -1050555895, -1016789534, -983023174, -949256813, + -915490452, -881724092, -847957731, -814191371, -780425010, -746658649, + -712892289, -679125928, -645359567, -611593207, -577826846, -544060486, + -510294125, -476527764, -442761404, -408995043, -375228683, -341462322, + -307695961, -273929601, -240163240, -206396879, -172630519, -138864158, + -105097798, -71331437, -37565076, -3798716, 29967645, 63734006, + 97500366, 131266727, 165033087, 198799448, 232565809, 266332170, + 300098530, 333864891, 367631251, 401397612, 435163972, 468930333, + 502696694, 536463054, 570229415, 603995776, 637762136, 671528497, + 705294857, 739061218, 772827579, 806593940, 840360300, 874126660, + 907893021, 941659382, 975425742, 1009192103, 1042958464, 1076724824, + 1110491185, 1144257546, 1178023906, 1211790267, 1245556628, 1279322988, + 1313089349, 1346855709, 1380622070, 1414388430, 1448154791, 1481921152, + 1515687512, 1549453873, 1583220234, 1616986594, 1650752955, 1684519316, + -1654973750, -1621207390, -1587441029, -1553674668, -1519908307, -1486141947, + -1452375586, -1418609226, -1384842865, -1351076504, -1317310144, -1283543783, + -1249777423, -1216011062, -1182244701, -1148478341, -1114711980, -1080945620, + -1047179259, -1013412898, -979646538, -945880177, -912113816, -878347456, + -844581095, -810814734, -777048374, -743282013, -709515652, -675749292, + -641982931, -608216571, -574450210, -540683850, -506917489, -473151128, + -439384768, -405618407, -371852046, -338085686, -304319325, -270552965, + -236786604, -203020243, -169253882, -135487522, -101721161, -67954801, + -34188440, -422080, 33344281, 67110642, 100877002, 134643363, + 168409723, 202176084, 235942445, 269708806, 303475166, 337241527, + 371007887, 404774248, 438540609, 472306969, 506073330, 539839690, + 573606051, 607372412, 641138772, 674905133, 708671493, 742437854, + 776204215, 809970575, 843736936, 877503297, 911269657, 945036018, + 978802379, 1012568739, 1046335100, 1080101460, 1113867821, 1147634182, + 1181400542, 1215166903, 1248933264, 1282699624, 1316465985, 1350232345, + 1383998706, 1417765067, 1451531427, 1485297788, 1519064148, 1552830509, + 1586596870, 1620363230, 1654129591, -1685363475, -1651597114, -1617830753, + -1584064393, -1550298032, -1516531672, -1482765311, -1448998950, -1415232589, + -1381466229, -1347699868, -1313933508, -1280167147, -1246400786, -1212634426, + -1178868065, -1145101704, -1111335344, -1077568983, -1043802623, -1010036262, + -976269901, -942503541, -908737180, -874970820, -841204459, -807438098, + -773671738, -739905377, -706139016, -672372656, -638606295, -604839935, + -571073574, -537307213, -503540853, -469774492, -436008132, -402241771, + -368475410, -334709050, -300942689, -267176328, -233409968, -199643607, + -165877247, -132110886, -98344525, -64578165, -30811804, 2954557, + 36720917, 70487278, 104253638, 138019999, 171786360, 205552720, + 239319081, 273085441, 306851802, 340618163, 374384523, 408150884, + 441917245, 475683605, 509449966, 543216326, 576982687, 610749048, + 644515408, 678281769, 712048130, 745814490, 779580851, 813347211, + 847113572, 880879933, 914646293, 948412654, 982179014, 1015945375, + 1049711736, 1083478096, 1117244457, 1151010818, 1184777178, 1218543539, + 1252309900, 1286076260, 1319842621, 1353608981, 1387375342, 1421141703, + 1454908063, 1488674424, 1522440785, 1556207145, 1589973506, 1623739866, + 1657506227, -1681986838, -1648220478, -1614454117, -1580687756, -1546921396, + -1513155035, -1479388675, -1445622314, -1411855954, -1378089593, -1344323232, + -1310556872, -1276790511, -1243024150, -1209257790, -1175491429, -1141725069, + -1107958708, -1074192347, -1040425987, -1006659626, -972893265, -939126905, + -905360544, -871594184, -837827823, -804061462, -770295102, -736528741, + -702762380, -668996020, -635229659, -601463299, -567696938, -533930577, + -500164217, -466397856, -432631495, -398865135, -365098774, -331332414, + -297566053, -263799692, -230033332, -196266971, -162500611, -128734250, + -94967889, -61201529, -27435168, 6331193, 40097553, 73863914, + 107630275, 141396635, 175162996, 208929356, 242695717, 276462078, + 310228438, 343994799, 377761160, 411527520, 445293881, 479060241, + 512826602, 546592963, 580359323, 614125684, 647892044, 681658405, + 715424766, 749191126, 782957487, 816583731, 850546442, 884517983, + 918095853, 951789290, 985555651, 1019322011, 1053088372, 1086854732, + 1120621093, 1154387454, 1188153814, 1221920175, 1255686536, 1289452896, + 1323219257, 1356985618, 1390751978, 1424518339, 1458284699, 1492051060, + 1525817421, 1558515203, 1591210057, 1625104467, 1659836538, -1678263796, + -1643114188, -1608409583, -1574557824, -1541916605, -1509778399, -1476012039, + -1442245678, -1408479317, -1374712957, -1340946596, -1307180236, -1273413875, + -1239647514, -1205881154, -1172114793, -1138348432, -1104582072, -1070815711, + -1037277627, -1006953160, -974798160, -941049125, -906023309, -870110480, + -833754977, -797429519, -761604435, -726717287, -693147741, -661201051, + -631101277, -598086662, -564320302, -530553941, -496787581, -463021220, + -429254859, -395488499, -361722138, -327955777, -294189417, -260423056, + -228107767, -199050376, -167890154, -134786733, -99988130, -63832335, + -26738468, 10813442, 48312328, 85251237, 121161768, 155642038, + 188374348, 219131472, 247773022, 279838714, 313605074, 347371435, + 381137795, 414904156, 448670517, 482436877, 516203238, 549969599, + 582037330, 609501076, 639262763, 671246375, 705289776, 741133442, + 778417896, 816693154, 855441427, 894111101, 932156768, 969078115, + 1004450907, 1037945710, 1069333432, 1098479713, 1125331797, 1157764090, + 1191530450, 1225296811, 1259063172, 1292829532, 1326595893, 1360362254, + 1393549421, 1419174932, 1447210699, 1477661220, 1510456009, 1545431067, + 1582315409, 1620727322, 1660184395, -1673130488, -1633292893, -1594147962, + -1556228930, -1519982405, -1485748705, -1453757368, -1424135103, -1396921696, + -1371336321, -1337569960, -1303803600, -1270037239, -1236270878, -1202504518, + -1168738157, -1142902306, -1116829630, -1088239207, -1057115054, -1023521125, + -987622598, -949701839, -910163545, -869524163, -828383495, -787381090, + -747144824, -708241805, -671140908, -636192336, -603624541, -573554891, + -546008662, -520941146, -493410945, -459644584, -425878223, -392111863, + -358345502, -329925268, -305960772, -279458857, -250330735, -218547869, + -184166647, -147352692, -108399636, -67735914, -25913657, 16422928, + 58586777, 99905998, 139778742, 177714100, 213353127, 246470106, + 276958755, 304809839, 330086146, 352899001, 384514432, 418280792, + 452047153, 485034379, 506829690, 531112614, 558026402, 587675688, + 620102643, 655259517, 692981020, 732962399, 774750734, 817756500, + 861288724, 904610383, 947003720, 987831357, 1026580736, 1062885451, + 1096524280, 1127403811, 1155532370, 1180991934, 1203912500, 1228673447, + 1262439808, 1296206168, 1321710457, 1343731052, 1368315799, 1395624655, + 1425779004, 1458835741, 1494756849, 1533378191, 1574384078, 1617296344, + 1661486321, -1667045600, -1622570045, -1579111903, -1537344766, -1497802318, + -1460856986, -1426723649, -1395481024, -1367101734, -1341483576, -1318477274, + -1297908655, -1266660603, -1234499623, -1214714269, -1192483396, -1167612757, + -1139925070, -1109281313, -1075608776, -1038934618, -999420963, -957394220, + -913358561, -867983604, -822061263, -776436023, -731922866, -689232184, + -648918104, -611357492, -576756938, -545178627, -516574676, -490821684, + -467750585, -447169895, -422501587, -397647381, -377724508, -355297630, + -330156367, -302105515, -270987551, -236712861, -199296591, -158897953, + -115853835, -70695178, -24134408, 22982226, 69752633, 115310525, + 158908241, 199972059, 238122394, 273162971, 305049991, 333853246, + 359718224, 382834217, 403410102, 421657428, +}; diff --git a/test/ztest/unit/math/basic/complex/testcase.yaml b/test/ztest/unit/math/basic/complex/testcase.yaml new file mode 100644 index 000000000000..729fbd762b58 --- /dev/null +++ b/test/ztest/unit/math/basic/complex/testcase.yaml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2026 Intel Corporation. +# +# Math basic complex numbers unit tests +# + +common: + tags: + - SOF + - unit_test + - math + - complex + integration_platforms: + - native_sim + arch_exclude: xtensa # Test is for host builds only + +tests: + sof.unit.math.basic.complex: + platform_allow: + - native_sim diff --git a/test/ztest/unit/math/basic/trigonometry/CMakeLists.txt b/test/ztest/unit/math/basic/trigonometry/CMakeLists.txt new file mode 100644 index 000000000000..48d009abbee8 --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_math_trigonometry) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../../../..") + +target_include_directories(app PRIVATE + ${SOF_ROOT}/zephyr/include + ${SOF_ROOT}/src/include +) + +# Define SOF-specific configurations for unit testing +target_compile_definitions(app PRIVATE + -DCONFIG_ZEPHYR_POSIX=1 + -DCONFIG_LIBRARY=1 + -DUNIT_TEST=1 +) + +target_sources(app PRIVATE + trig_test.c + ${SOF_ROOT}/src/math/trig.c + ${SOF_ROOT}/src/math/lut_trig.c + ${SOF_ROOT}/src/math/atan2.c +) + +# Link math library for standard math functions +target_link_libraries(app PRIVATE m) diff --git a/test/ztest/unit/math/basic/trigonometry/atan2_tables.h b/test/ztest/unit/math/basic/trigonometry/atan2_tables.h new file mode 100644 index 000000000000..f7ec1e6587fa --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/atan2_tables.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2026 Intel Corporation. + */ + +#ifndef __ATAN2_TABLES_H__ +#define __ATAN2_TABLES_H__ + +#include <stdint.h> + +#define ATAN2_TEST_TABLE_SIZE 256 + +static const int32_t atan2_test_y[ATAN2_TEST_TABLE_SIZE] = { + 0, 593678131, -532114458, 826669466, 85578803, 2092045542, + -1879009088, -1576694240, 1539058893, 1401024205, -1764925184, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1002953741, 562543872, 1322188032, + -1091606067, -400921101, 2147483647, -1690120538, 2050372122, -350646912, + -1880522864, 320130202, 1583472563, 1870898586, 1777558605, 1275437645, + 2147483647, 645138560, 1016824371, 1133248230, -1409419475, -65799642, + 751321472, -554752, -481011942, -1824835690, 1120701542, 1219868109, + 1276479565, -1402484230, 1094266906, 345378458, 1388947226, 1235927757, + -67347315, -113975488, 352132070, 646445466, -175333594, 1313648794, + 498544640, 689375667, 1101318170, -1891416384, 973726336, 260722458, + 2049027200, 1619159731, 659320781, 811575142, 2062582016, 1804117709, + -556148173, 2147483647, -1581181395, -1384873248, -2147483648, 1919463322, + -715849728, 1482341555, -2106111198, 2147483647, -1581934605, -2147483648, + 2147483647, -1977711542, -1219287520, -1913594461, -1213455936, 1750786893, + -420132698, -222367974, -435172250, -2087889971, -919525235, 834603827, + -1669661664, 2147483647, 1584016051, 2082185882, 212862848, 1926648627, + -1889370525, -1133371149, 2147483647, -125891533, 629086234, -580819290, + -814994048, -940839821, -2147483648, -11732723, -499195981, 2003249459, + -1797551043, 1543991962, 703381043, -200345024, 1618129075, 1901467674, + 2147483647, 747880038, 2017725389, 1628990106, -2147483648, 2147483647, + -451489280, 486361498, -2132152282, -58571955, 157509299, -834756314, + 1251017293, 1892762010, -1455901638, 90604237, -957637261, -2147483648, + 752198656, -1829826099, -1725792499, -569240883, 42635648, -1498449850, + -437911232, -23190746, -661963034, -324850381, -2134133197, 297851418, + 980486426, -357129907, 1688064717, -819664806, 1316280909, 13885414, + -1496825299, 18689510, 1180361037, -324324774, 370182912, 2146612582, + -652058458, -259263629, 277880346, -1507396774, -1420640883, 1603635123, + 1512286899, 925569638, 64723789, 2101077862, 2046962227, -1243819526, + 1021511040, -1659139469, 1906461286, 1168691814, 1900425472, 195734528, + -689034931, 510480538, -1956886624, 965214694, -1640061773, -2146964829, + -1588224, -1125154624, 34522470, 1535756570, 692508749, 292941158, + -143428173, 715886899, 1614379853, 33759053, -1082890266, 610783923, + 1470741325, 1262575846, -53151718, 2033863603, 844302131, 19598797, + 654380390, -411747354, -1558739706, -1846029434, 1652960461, -2147483648, + -587736512, -595937408, 1554227840, 562723533, 1592959667, -46749261, + 1489178803, 582155622, -2126878934, -1168122701, -2147483648, 1081324570, + 1864094003, 1138184397, -547145984, 772395853, -41048269, 1008931123, + -844305651, 1003180570, 2147483647, 2147483647, -715760602, -2035354781, + -1371158131, 1678904832, 494394701, -1407855398, 440926182, 2082209818, + -1291104390, 1887003290, 744169114, -1480452019, 2087889126, 23236224, + -1745024160, -72790784, 523330227, -115015155, 1655730278, 923114086, + 880698086, 1312830746, 132706534, -978800064, +}; + +static const int32_t atan2_test_x[ATAN2_TEST_TABLE_SIZE] = { + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -1399816141, + -230097050, -1261376090, -2081157232, -440471258, -876176998, -1642130829, + -171532698, 104774067, -928553894, 803256115, 1159264128, -451441549, + 1477543373, -1407978810, -155422643, -1755391194, 1797471949, -2131587568, + -251177766, -2147483648, -868828787, 1321866445, -550897318, -288342067, + 158300877, 370411853, 1242460877, 560164634, 560658278, 1170291584, + -1531339462, 1861627750, 881152307, -76744870, 1266329293, -808628198, + 779498650, -1042297485, 29521254, -2147483648, -1831276832, 315334554, + 1677842637, -314975091, 1873312179, 1370099174, -853027507, 1308034816, + 1094235366, 2147483647, 268095872, 2147483647, -834663949, 838375578, + -574429504, -707173350, 1876573952, 874547379, 1613107021, -2076715221, + 1954203187, -1230503296, 1975324314, 1574426445, 150468173, -2147483648, + -2045228592, 102846515, -1659941536, 2147483647, 523171686, -919468352, + 1801804365, 25905792, -2147483648, 2100982400, -2147483648, -592549478, + 774778470, -794157056, -687915571, 1915112320, -1895780832, -651402752, + -1753523904, -2127834438, -1292520768, -72287987, 471997645, -1600389824, + 1050780826, 909749350, 1526121907, -480663181, 1690915917, 152633958, + 1151843968, -1504568947, -2135539402, 799874662, 1630831770, -643009382, + -1334604269, -2147483648, -1856544518, 1010088781, 1164046259, 914998093, + 2147483647, 560258406, 1061672550, 1741415526, 730181760, -1559917498, + 1348011034, 280000230, 247261696, 1805741133, -998184000, 2003341542, + 182103398, -343834726, -665013325, 681587456, -965692570, 773658266, + -854945766, -1014991155, -663706278, 200810086, -2147483648, 1065857690, + -1146915827, -2147483648, 1094864461, 1700262502, -1050449382, -713241830, + -1989792816, -1679438253, -2144952374, 1737513395, -76085786, -999872192, + 1268036915, 1857466829, 1334412570, 351298253, 1767924506, -206440256, + -2147483648, -1185212653, 2030329805, 2147483647, 1363327539, 848855885, + 1660833434, 1357533338, -1650400646, 991000525, 2106705357, 2147483647, + -1964598170, 1936573338, 799362995, 406677427, -395381466, 2147483647, + -1469184218, 204290944, 1538024576, 2093231642, 2147483647, -1031910246, + -2147483648, 2147483647, -172979558, 1774660941, 795639117, 1787846861, + 1848797773, 282311603, -379224384, -889636070, -1874511760, -1696152198, + -96912922, 1257014528, 1355642675, -28044262, -1442693542, -2147483648, + 586790195, 170231987, -474024038, 1662995277, -139357645, -447027750, + -774900826, 2147483647, 1843413581, 1234652954, -991492621, -2147483648, + -272780570, -1956468659, 1327163059, 1548914611, 1038220902, 2147483647, + -1708905722, 550796928, -1898930634, 1387736064, -1010688026, -1955962237, + 2147483647, 1687800013, -538678554, -2051015613, 1152012083, -1856525088, + -784337101, 361366016, 1829781043, -926315456, 584568653, -421916493, + 1094186931, 1752872986, -1590665542, -714551270, 1503289216, -2001796262, + -554735245, -1757686726, -904190426, -2083870624, -561217114, -885333222, + -314317274, 1836398643, -1568309389, 2094263142, +}; + +static const int32_t atan2_test_ref[ATAN2_TEST_TABLE_SIZE] = { + 0, 843314857, -843314857, 843314857, 843314857, 843314857, + -843314857, -843314857, 843314857, 843314857, -843314857, 1686629713, + 1686629713, 1686629713, 1686629713, 1686629713, 1686629713, 1686629713, + 1686629713, 0, 1686629713, -480774686, 242550644, 1019958505, + -341607303, -1537697774, 882102887, -1275141377, 456892678, -1599098184, + -914601725, 1607182223, 1112734724, 513084281, 1004661107, 962680342, + 803811086, 563496816, 368216934, 596849638, -640053917, -30153818, + 1441750136, -159984, -268264737, -865880079, 388944604, 1157587081, + 548989894, -1186440684, 828834606, 1601018220, 1338258195, 709198926, + -21538024, -1500229594, 99753206, 236681525, -1577795578, 422807062, + 229517388, 166764936, 715116877, -387665176, 1223768840, 161868893, + 990055806, 1064389455, 181392893, 401616028, 486983396, 1302621340, + -148853162, 1122663950, -362401539, -387315937, -805759192, 1295041388, + -1505874184, 806125749, -1201663508, 421657428, -671841804, -1060503213, + 468530021, -836282855, -1409396260, -396616142, -1410500034, 1018520658, + -266761868, -1540056775, -1383811666, -444815486, -1444175423, 1199116908, + -1278122081, 1262504863, 1210753289, 861946112, 227456622, 1215451470, + -570823003, -480185572, 511613552, -1549105769, 191218374, -705349581, + -330593881, -1386609757, -1263475094, -7874366, -159473626, 1010064033, + -1186190715, 1351971671, 1492198979, -105120786, 508515064, 602528322, + 421657428, 498137329, 583272798, 403755854, -667353222, 1180588320, + -173509607, 562873277, -781331817, -17408120, 1602606516, -211958872, + 765710697, 939789547, -1073348055, 70950927, -1267220800, -657671271, + 1299248585, -1115207171, -1040423529, -661241101, 1675972201, -511381404, + -1490815052, -1680832252, -291950578, -101352536, -1088879133, 1474249986, + 1440830194, -1574140544, 1328665659, -236647292, 874313438, 1679174565, + -465981743, 5401720, 388810509, -400234846, 110813576, 894787567, + -1528364782, -1571011137, 73024931, -328578059, -432708387, 581946141, + 396542676, 321267954, 1665586022, 606704001, 413936026, -281848594, + 1429206964, -380316068, 630163376, 663532294, 953439316, 48798797, + -1451193270, 638942546, -485695493, 231958476, -350157942, -1083853093, + -1686232657, -259102718, 1580872968, 382979880, 384511044, 87192252, + -41566736, 641651025, 967182272, 1666266823, -1405387221, 1501063583, + 878640321, 422842424, -21038732, 850717120, 1402364287, 1681730150, + 450864858, -632841657, -1001810229, -449635784, 888470538, -953498287, + -1338255336, -145327507, 376072239, 229590563, 1142214026, -1674944244, + 940578011, 1531360468, -543807078, -346902051, -601547020, 250433321, + 1241668689, 601343996, -1536018589, 272669402, -1664837116, 1430957794, + -201109884, 287908177, 975262018, 1252638885, -298470119, -1240320708, + -1122270737, 729495693, 141675968, -1155748018, 346943281, 950647349, + -465878468, 441432301, 1451702422, -1084733681, 508293499, 1680398164, + -1008559815, -1664409066, 1404948145, -1657028209, 1018764798, 1253757970, + 1027356695, 333210160, 1641308961, -234723315, +}; + +#endif /* __ATAN2_TABLES_H__ */ diff --git a/test/ztest/unit/math/basic/trigonometry/atan2_tables.m b/test/ztest/unit/math/basic/trigonometry/atan2_tables.m new file mode 100644 index 000000000000..37728a20e0d7 --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/atan2_tables.m @@ -0,0 +1,95 @@ +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2026 Intel Corporation. + +function atan2_tables() + + % Create random test points with bias to min/max values + q31_scale = 2^31; + q29_scale = 2^29; + num_points = 256; + rand('seed', 42); + x = max(min(2.2 * rand(num_points, 1) - 1.1, 1), -1); + y = max(min(2.2 * rand(num_points, 1) - 1.1, 1), -1); + + % Force 1st test point to be (0, 0) to ensure it is tested + x(1) = 0; + y(1) = 0; + + % Then force 10 test points to have x = 0, the reference values are 0 or pi + x(2:11) = 0; + + % And force 10 test points to have y = 0, the reference values are +/-pi + y(12:21) = 0; + + % Quantize input values + ref_x = int32(x * q31_scale); + ref_y = int32(y * q31_scale); + x = double(ref_x)/q31_scale; + y = double(ref_y)/q31_scale; + a = atan2(y, x); + ref_a = int32(a * q29_scale); + + figure(1) + subplot(2,1,1) + plot(x, y, 'o'); + grid on; + subplot(2,1,2) + plot(a, 'o'); + grid on; + + fn = 'atan2_tables.h'; + fh = export_headerfile(fn); + dn = 'ATAN2_TEST_TABLE_SIZE'; + vl = 6; + fu = export_ifndef(fh, fn); + export_define(fh, dn, num_points); + export_array(fh, 'atan2_test_y', dn, vl, ref_y); + export_array(fh, 'atan2_test_x', dn, vl, ref_x); + export_array(fh, 'atan2_test_ref', dn, vl, ref_a); + export_fclose(fh, fu); + +end + +function [fh] = export_headerfile(headerfn) + fh = fopen(headerfn, 'w'); + fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, ' *\n'); + fprintf(fh, ' * Copyright(c) %s Intel Corporation.\n', ... + datestr(now, 'yyyy')); + fprintf(fh, ' */\n\n'); +end + +function fu = export_ifndef(fh, fn) + fu = sprintf('__%s__', upper(strrep(fn, '.', '_'))); + fprintf(fh, '#ifndef %s\n', fu); + fprintf(fh, '#define %s\n\n', fu); + fprintf(fh, '#include <stdint.h>\n\n'); +end + +function export_define(fh, dn, val) + fprintf(fh, '#define %s %d\n', dn, val); +end + +function export_array(fh, vn, size_str, vl, data) + fprintf(fh, '\n'); + fprintf(fh, 'static const int32_t %s[%s] = {\n', vn, size_str); + + n = length(data); + k = 0; + for i = 1:vl:n + fprintf(fh, '\t'); + for j = 1:min(vl, n-k) + k = k + 1; + fprintf(fh, '%12d,', data(k)); + end + fprintf(fh, '\n'); + end + + fprintf(fh, '};\n'); +end + +function export_fclose(fh, fu) + fprintf(fh, "\n#endif /* %s */\n", fu); + fclose(fh); +end diff --git a/test/ztest/unit/math/basic/trigonometry/prj.conf b/test/ztest/unit/math/basic/trigonometry/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/math/basic/trigonometry/testcase.yaml b/test/ztest/unit/math/basic/trigonometry/testcase.yaml new file mode 100644 index 000000000000..90bb941c4a22 --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/testcase.yaml @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2025 Intel Corporation. All rights reserved. +# +# Math basic trigonometry unit tests converted from CMock to Ztest +# +# These contents may have been developed with support from one or more Intel-operated +# generative artificial intelligence solutions. +# + +common: + tags: + - SOF + - unit_test + - math + - trigonometry + integration_platforms: + - native_sim + arch_exclude: xtensa # Test is for host builds only + +tests: + sof.unit.math.basic.trigonometry: + platform_allow: + - native_sim diff --git a/test/ztest/unit/math/basic/trigonometry/trig_tables.h b/test/ztest/unit/math/basic/trigonometry/trig_tables.h new file mode 100644 index 000000000000..3e1f8a7eb94f --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/trig_tables.h @@ -0,0 +1,360 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry <malladi.sastry@linux.intel.com> + */ + +/* Reference table generated by sin(), gcc-4.3.2 */ +static const float sin_ref_table[] = { + 0.0000000000, 0.0174524064, 0.0348994967, 0.0523359562, + 0.0697564737, 0.0871557427, 0.1045284633, 0.1218693434, + 0.1391731010, 0.1564344650, 0.1736481777, 0.1908089954, + 0.2079116908, 0.2249510543, 0.2419218956, 0.2588190451, + 0.2756373558, 0.2923717047, 0.3090169944, 0.3255681545, + 0.3420201433, 0.3583679495, 0.3746065934, 0.3907311285, + 0.4067366431, 0.4226182617, 0.4383711468, 0.4539904997, + 0.4694715628, 0.4848096202, 0.5000000000, 0.5150380749, + 0.5299192642, 0.5446390350, 0.5591929035, 0.5735764364, + 0.5877852523, 0.6018150232, 0.6156614753, 0.6293203910, + 0.6427876097, 0.6560590290, 0.6691306064, 0.6819983601, + 0.6946583705, 0.7071067812, 0.7193398003, 0.7313537016, + 0.7431448255, 0.7547095802, 0.7660444431, 0.7771459615, + 0.7880107536, 0.7986355100, 0.8090169944, 0.8191520443, + 0.8290375726, 0.8386705679, 0.8480480962, 0.8571673007, + 0.8660254038, 0.8746197071, 0.8829475929, 0.8910065242, + 0.8987940463, 0.9063077870, 0.9135454576, 0.9205048535, + 0.9271838546, 0.9335804265, 0.9396926208, 0.9455185756, + 0.9510565163, 0.9563047560, 0.9612616959, 0.9659258263, + 0.9702957263, 0.9743700648, 0.9781476007, 0.9816271834, + 0.9848077530, 0.9876883406, 0.9902680687, 0.9925461516, + 0.9945218954, 0.9961946981, 0.9975640503, 0.9986295348, + 0.9993908270, 0.9998476952, 1.0000000000, 0.9998476952, + 0.9993908270, 0.9986295348, 0.9975640503, 0.9961946981, + 0.9945218954, 0.9925461516, 0.9902680687, 0.9876883406, + 0.9848077530, 0.9816271834, 0.9781476007, 0.9743700648, + 0.9702957263, 0.9659258263, 0.9612616959, 0.9563047560, + 0.9510565163, 0.9455185756, 0.9396926208, 0.9335804265, + 0.9271838546, 0.9205048535, 0.9135454576, 0.9063077870, + 0.8987940463, 0.8910065242, 0.8829475929, 0.8746197071, + 0.8660254038, 0.8571673007, 0.8480480962, 0.8386705679, + 0.8290375726, 0.8191520443, 0.8090169944, 0.7986355100, + 0.7880107536, 0.7771459615, 0.7660444431, 0.7547095802, + 0.7431448255, 0.7313537016, 0.7193398003, 0.7071067812, + 0.6946583705, 0.6819983601, 0.6691306064, 0.6560590290, + 0.6427876097, 0.6293203910, 0.6156614753, 0.6018150232, + 0.5877852523, 0.5735764364, 0.5591929035, 0.5446390350, + 0.5299192642, 0.5150380749, 0.5000000000, 0.4848096202, + 0.4694715628, 0.4539904997, 0.4383711468, 0.4226182617, + 0.4067366431, 0.3907311285, 0.3746065934, 0.3583679495, + 0.3420201433, 0.3255681545, 0.3090169944, 0.2923717047, + 0.2756373558, 0.2588190451, 0.2419218956, 0.2249510543, + 0.2079116908, 0.1908089954, 0.1736481777, 0.1564344650, + 0.1391731010, 0.1218693434, 0.1045284633, 0.0871557427, + 0.0697564737, 0.0523359562, 0.0348994967, 0.0174524064, + 0.0000000000, -0.0174524064, -0.0348994967, -0.0523359562, + -0.0697564737, -0.0871557427, -0.1045284633, -0.1218693434, + -0.1391731010, -0.1564344650, -0.1736481777, -0.1908089954, + -0.2079116908, -0.2249510543, -0.2419218956, -0.2588190451, + -0.2756373558, -0.2923717047, -0.3090169944, -0.3255681545, + -0.3420201433, -0.3583679495, -0.3746065934, -0.3907311285, + -0.4067366431, -0.4226182617, -0.4383711468, -0.4539904997, + -0.4694715628, -0.4848096202, -0.5000000000, -0.5150380749, + -0.5299192642, -0.5446390350, -0.5591929035, -0.5735764364, + -0.5877852523, -0.6018150232, -0.6156614753, -0.6293203910, + -0.6427876097, -0.6560590290, -0.6691306064, -0.6819983601, + -0.6946583705, -0.7071067812, -0.7193398003, -0.7313537016, + -0.7431448255, -0.7547095802, -0.7660444431, -0.7771459615, + -0.7880107536, -0.7986355100, -0.8090169944, -0.8191520443, + -0.8290375726, -0.8386705679, -0.8480480962, -0.8571673007, + -0.8660254038, -0.8746197071, -0.8829475929, -0.8910065242, + -0.8987940463, -0.9063077870, -0.9135454576, -0.9205048535, + -0.9271838546, -0.9335804265, -0.9396926208, -0.9455185756, + -0.9510565163, -0.9563047560, -0.9612616959, -0.9659258263, + -0.9702957263, -0.9743700648, -0.9781476007, -0.9816271834, + -0.9848077530, -0.9876883406, -0.9902680687, -0.9925461516, + -0.9945218954, -0.9961946981, -0.9975640503, -0.9986295348, + -0.9993908270, -0.9998476952, -1.0000000000, -0.9998476952, + -0.9993908270, -0.9986295348, -0.9975640503, -0.9961946981, + -0.9945218954, -0.9925461516, -0.9902680687, -0.9876883406, + -0.9848077530, -0.9816271834, -0.9781476007, -0.9743700648, + -0.9702957263, -0.9659258263, -0.9612616959, -0.9563047560, + -0.9510565163, -0.9455185756, -0.9396926208, -0.9335804265, + -0.9271838546, -0.9205048535, -0.9135454576, -0.9063077870, + -0.8987940463, -0.8910065242, -0.8829475929, -0.8746197071, + -0.8660254038, -0.8571673007, -0.8480480962, -0.8386705679, + -0.8290375726, -0.8191520443, -0.8090169944, -0.7986355100, + -0.7880107536, -0.7771459615, -0.7660444431, -0.7547095802, + -0.7431448255, -0.7313537016, -0.7193398003, -0.7071067812, + -0.6946583705, -0.6819983601, -0.6691306064, -0.6560590290, + -0.6427876097, -0.6293203910, -0.6156614753, -0.6018150232, + -0.5877852523, -0.5735764364, -0.5591929035, -0.5446390350, + -0.5299192642, -0.5150380749, -0.5000000000, -0.4848096202, + -0.4694715628, -0.4539904997, -0.4383711468, -0.4226182617, + -0.4067366431, -0.3907311285, -0.3746065934, -0.3583679495, + -0.3420201433, -0.3255681545, -0.3090169944, -0.2923717047, + -0.2756373558, -0.2588190451, -0.2419218956, -0.2249510543, + -0.2079116908, -0.1908089954, -0.1736481777, -0.1564344650, + -0.1391731010, -0.1218693434, -0.1045284633, -0.0871557427, + -0.0697564737, -0.0523359562, -0.0348994967, -0.0174524064 +}; + +/* Reference table generated by cos(), gcc-4.3.2 */ +static const float cos_ref_table[] = { + 1.000000000000000, 0.999847695156391, 0.999390827019096, 0.998629534754574, + 0.997564050259824, 0.996194698091746, 0.994521895368273, 0.992546151641322, + 0.99026806874157, 0.987688340595138, 0.984807753012208, 0.981627183447664, + 0.978147600733806, 0.974370064785235, 0.970295726275996, 0.965925826289068, + 0.961261695938319, 0.956304755963035, 0.951056516295154, 0.945518575599317, + 0.939692620785908, 0.933580426497202, 0.927183854566787, 0.92050485345244, + 0.913545457642601, 0.90630778703665, 0.898794046299167, 0.891006524188368, + 0.882947592858927, 0.874619707139396, 0.866025403784439, 0.857167300702112, + 0.848048096156426, 0.838670567945424, 0.829037572555042, 0.819152044288992, + 0.809016994374947, 0.798635510047293, 0.788010753606722, 0.777145961456971, + 0.766044443118978, 0.754709580222772, 0.743144825477394, 0.731353701619171, + 0.719339800338651, 0.707106781186548, 0.694658370458997, 0.681998360062498, + 0.669130606358858, 0.656059028990507, 0.642787609686539, 0.629320391049838, + 0.615661475325658, 0.601815023152048, 0.587785252292473, 0.573576436351046, + 0.559192903470747, 0.544639035015027, 0.529919264233205, 0.515038074910054, + 0.500000000000000, 0.484809620246337, 0.469471562785891, 0.453990499739547, + 0.438371146789077, 0.422618261740699, 0.4067366430758, 0.390731128489274, + 0.374606593415912, 0.3583679495453, 0.342020143325669, 0.325568154457157, + 0.309016994374947, 0.292371704722737, 0.275637355816999, 0.258819045102521, + 0.241921895599668, 0.224951054343865, 0.207911690817759, 0.190808995376545, + 0.17364817766693, 0.156434465040231, 0.139173100960066, 0.121869343405147, + 0.104528463267653, 0.0871557427476581, 0.0697564737441255, 0.052335956242944, + 0.0348994967025011, 0.0174524064372834, 6.12323399573677e-17, -0.0174524064372835, + -0.0348994967025007, -0.0523359562429436, -0.0697564737441253, -0.0871557427476582, + -0.104528463267653, -0.121869343405147, -0.139173100960065, -0.156434465040231, + -0.17364817766693, -0.190808995376545, -0.207911690817759, -0.224951054343865, + -0.241921895599668, -0.258819045102521, -0.275637355816999, -0.292371704722737, + -0.309016994374947, -0.325568154457156, -0.342020143325669, -0.3583679495453, + -0.374606593415912, -0.390731128489274, -0.4067366430758, -0.422618261740699, + -0.438371146789078, -0.453990499739547, -0.469471562785891, -0.484809620246337, + -0.500000000000000, -0.515038074910054, -0.529919264233205, -0.544639035015027, + -0.559192903470747, -0.573576436351046, -0.587785252292473, -0.601815023152048, + -0.615661475325658, -0.629320391049837, -0.642787609686539, -0.656059028990507, + -0.669130606358858, -0.681998360062498, -0.694658370458997, -0.707106781186547, + -0.719339800338651, -0.73135370161917, -0.743144825477394, -0.754709580222772, + -0.766044443118978, -0.777145961456971, -0.788010753606722, -0.798635510047293, + -0.809016994374947, -0.819152044288992, -0.829037572555042, -0.838670567945424, + -0.848048096156426, -0.857167300702112, -0.866025403784439, -0.874619707139396, + -0.882947592858927, -0.891006524188368, -0.898794046299167, -0.90630778703665, + -0.913545457642601, -0.92050485345244, -0.927183854566787, -0.933580426497202, + -0.939692620785908, -0.945518575599317, -0.951056516295154, -0.956304755963035, + -0.961261695938319, -0.965925826289068, -0.970295726275996, -0.974370064785235, + -0.978147600733806, -0.981627183447664, -0.984807753012208, -0.987688340595138, + -0.99026806874157, -0.992546151641322, -0.994521895368273, -0.996194698091746, + -0.997564050259824, -0.998629534754574, -0.999390827019096, -0.999847695156391, + -1.000000000000000, -0.999847695156391, -0.999390827019096, -0.998629534754574, + -0.997564050259824, -0.996194698091746, -0.994521895368273, -0.992546151641322, + -0.99026806874157, -0.987688340595138, -0.984807753012208, -0.981627183447664, + -0.978147600733806, -0.974370064785235, -0.970295726275997, -0.965925826289068, + -0.961261695938319, -0.956304755963036, -0.951056516295154, -0.945518575599317, + -0.939692620785908, -0.933580426497202, -0.927183854566787, -0.92050485345244, + -0.913545457642601, -0.90630778703665, -0.898794046299167, -0.891006524188368, + -0.882947592858927, -0.874619707139396, -0.866025403784439, -0.857167300702112, + -0.848048096156426, -0.838670567945424, -0.829037572555042, -0.819152044288992, + -0.809016994374947, -0.798635510047293, -0.788010753606722, -0.777145961456971, + -0.766044443118978, -0.754709580222772, -0.743144825477394, -0.731353701619171, + -0.719339800338651, -0.707106781186548, -0.694658370458997, -0.681998360062499, + -0.669130606358858, -0.656059028990508, -0.642787609686539, -0.629320391049837, + -0.615661475325658, -0.601815023152048, -0.587785252292473, -0.573576436351046, + -0.559192903470747, -0.544639035015027, -0.529919264233205, -0.515038074910054, + -0.500000000000000, -0.484809620246337, -0.469471562785891, -0.453990499739547, + -0.438371146789078, -0.4226182617407, -0.4067366430758, -0.390731128489274, + -0.374606593415912, -0.358367949545301, -0.342020143325669, -0.325568154457157, + -0.309016994374948, -0.292371704722737, -0.275637355816999, -0.258819045102521, + -0.241921895599668, -0.224951054343865, -0.20791169081776, -0.190808995376545, + -0.17364817766693, -0.156434465040231, -0.139173100960065, -0.121869343405147, + -0.104528463267653, -0.0871557427476582, -0.0697564737441256, -0.0523359562429443, + -0.0348994967025016, -0.0174524064372835, -1.83697019872103e-16, 0.0174524064372831, + 0.0348994967025013, 0.0523359562429439, 0.0697564737441252, 0.0871557427476579, + 0.104528463267653, 0.121869343405148, 0.139173100960065, 0.156434465040231, + 0.17364817766693, 0.190808995376544, 0.207911690817759, 0.224951054343865, + 0.241921895599667, 0.258819045102521, 0.275637355816999, 0.292371704722737, + 0.309016994374947, 0.325568154457156, 0.342020143325668, 0.3583679495453, + 0.374606593415912, 0.390731128489273, 0.406736643075801, 0.4226182617407, + 0.438371146789077, 0.453990499739547, 0.46947156278589, 0.484809620246337, + 0.500000000000000, 0.515038074910054, 0.529919264233205, 0.544639035015027, + 0.559192903470746, 0.573576436351046, 0.587785252292473, 0.601815023152048, + 0.615661475325659, 0.629320391049838, 0.642787609686539, 0.656059028990507, + 0.669130606358858, 0.681998360062498, 0.694658370458997, 0.707106781186547, + 0.719339800338651, 0.731353701619171, 0.743144825477394, 0.754709580222772, + 0.766044443118978, 0.777145961456971, 0.788010753606722, 0.798635510047293, + 0.809016994374947, 0.819152044288992, 0.829037572555041, 0.838670567945424, + 0.848048096156425, 0.857167300702112, 0.866025403784438, 0.874619707139396, + 0.882947592858927, 0.891006524188368, 0.898794046299167, 0.90630778703665, + 0.913545457642601, 0.92050485345244, 0.927183854566787, 0.933580426497202, + 0.939692620785908, 0.945518575599317, 0.951056516295154, 0.956304755963036, + 0.961261695938319, 0.965925826289068, 0.970295726275996, 0.974370064785235, + 0.978147600733806, 0.981627183447664, 0.984807753012208, 0.987688340595138, + 0.99026806874157, 0.992546151641322, 0.994521895368273, 0.996194698091746, + 0.997564050259824, 0.998629534754574, 0.999390827019096, 0.999847695156391, + 1 +}; + +/* Reference table generated by asin(), gcc-4.3.2 */ +static const float asin_ref_table[] = { + -1.5707963258028030, -1.4292567726224661, -1.3704614471644163, -1.3252307642251253, + -1.2870021797716618, -1.2532358597964048, -1.2226302791386843, -1.1944128256291151, + -1.1680804640054703, -1.1432840377092361, -1.1197695024311543, -1.0973451361060143, + -1.0758621711283922, -1.0552022922784090, -1.0352696590125561, -1.0159852746874094, + -0.9972832072526217, -0.9791076704859734, -0.9614110030233860, -0.9441520925611258, + -0.9272952042520046, -0.9108089841902256, -0.8946658074855804, -0.8788411282002926, + -0.8633130993694067, -0.8480620700865984, -0.8330703470855951, -0.8183219302445650, + -0.8038023039698601, -0.7894981894642115, -0.7753974795341492, -0.7614890411496162, + -0.7477626111358404, -0.7342087719589472, -0.7208187356591225, -0.7075844295322895, + -0.6944982521235943, -0.6815531998872757, -0.6687426939606667, -0.6560605876147747, + -0.6435010936111212, -0.6310588326305151, -0.6187286712229252, -0.6065058410167694, + -0.5943857878446579, -0.5823642127215862, -0.5704370923340321, -0.5586005486547947, + -0.5468509383499622, -0.5351847745478153, -0.5235987640917301, -0.5120897386223078, + -0.5006546974182129, -0.4892907701432705, -0.4779951833188534, -0.4667653329670429, + -0.4555986635386944, -0.4444927759468555, -0.4334453158080578, -0.4224540572613478, + -0.4115168377757072, -0.4006315693259239, -0.3897962793707848, -0.3790090084075928, + -0.3682678826153278, -0.3575710840523243, -0.3469168916344643, -0.3363035582005978, + -0.3257294744253159, -0.3151930235326290, -0.3046926259994507, -0.2942268401384354, + -0.2837941013276577, -0.2733930107206106, -0.2630221955478191, -0.2526802383363247, + -0.2423658333718777, -0.2320776768028736, -0.2218144722282887, -0.2115749418735504, + -0.2013579159975052, -0.1911621354520321, -0.1809864528477192, -0.1708296611905098, + -0.1606906354427338, -0.1505682766437531, -0.1404614131897688, -0.1303689777851105, + -0.1202898658812046, -0.1102230437099934, -0.1001674197614193, -0.0901219304651022, + -0.0800855793058872, -0.0700572803616524, -0.0600360594689846, -0.0500208474695683, + -0.0400106683373451, -0.0300045013427734, -0.0200013294816017, -0.0100001543760300, + 0.0000000000000000, 0.0100001543760300, 0.0200013294816017, 0.0300045013427734, + 0.0400106683373451, 0.0500208474695683, 0.0600360594689846, 0.0700572803616524, + 0.0800855793058872, 0.0901219304651022, 0.1001674197614193, 0.1102230437099934, + 0.1202898658812046, 0.1303689777851105, 0.1404614131897688, 0.1505682766437531, + 0.1606906354427338, 0.1708296611905098, 0.1809864528477192, 0.1911621354520321, + 0.2013579159975052, 0.2115749418735504, 0.2218144722282887, 0.2320776768028736, + 0.2423658333718777, 0.2526802383363247, 0.2630221955478191, 0.2733930107206106, + 0.2837941013276577, 0.2942268401384354, 0.3046926259994507, 0.3151930235326290, + 0.3257294744253159, 0.3363035582005978, 0.3469168916344643, 0.3575710840523243, + 0.3682678826153278, 0.3790090084075928, 0.3897962793707848, 0.4006315693259239, + 0.4115168377757072, 0.4224540572613478, 0.4334453158080578, 0.4444927759468555, + 0.4555986635386944, 0.4667653329670429, 0.4779951833188534, 0.4892907701432705, + 0.5006546974182129, 0.5120897386223078, 0.5235987640917301, 0.5351847745478153, + 0.5468509383499622, 0.5586005486547947, 0.5704370923340321, 0.5823642127215862, + 0.5943857878446579, 0.6065058410167694, 0.6187286712229252, 0.6310588326305151, + 0.6435010936111212, 0.6560605876147747, 0.6687426939606667, 0.6815531998872757, + 0.6944982521235943, 0.7075844295322895, 0.7208187356591225, 0.7342087719589472, + 0.7477626111358404, 0.7614890411496162, 0.7753974795341492, 0.7894981894642115, + 0.8038023039698601, 0.8183219302445650, 0.8330703470855951, 0.8480620700865984, + 0.8633130993694067, 0.8788411282002926, 0.8946658074855804, 0.9108089841902256, + 0.9272952042520046, 0.9441520925611258, 0.9614110030233860, 0.9791076704859734, + 0.9972832072526217, 1.0159852746874094, 1.0352696590125561, 1.0552022922784090, + 1.0758621711283922, 1.0973451361060143, 1.1197695024311543, 1.1432840377092361, + 1.1680804640054703, 1.1944128256291151, 1.2226302791386843, 1.2532358597964048, + 1.2870021797716618, 1.3252307642251253, 1.3704614471644163, 1.4292567726224661, + 1.5707963258028030, +}; + +/* Reference table generated by acos(), gcc-4.3.2 */ +static const float acos_ref_table[] = { + 3.1415926534682512, 3.0000531002879143, 2.9412577748298645, 2.8960270918905735, + 2.8577985074371099, 2.8240321874618530, 2.7934266068041325, 2.7652091532945633, + 2.7388767916709185, 2.7140803653746843, 2.6905658300966024, 2.6681414637714624, + 2.6466584987938404, 2.6259986199438572, 2.6060659866780043, 2.5867816023528576, + 2.5680795349180698, 2.5499039981514215, 2.5322073306888342, 2.5149484202265739, + 2.4980915319174528, 2.4816053118556738, 2.4654621351510286, 2.4496374558657408, + 2.4341094270348549, 2.4188583977520466, 2.4038666747510433, 2.3891182579100132, + 2.3745986316353083, 2.3602945171296597, 2.3461938071995974, 2.3322853688150644, + 2.3185589388012886, 2.3050050996243954, 2.2916150633245707, 2.2783807571977377, + 2.2652945797890425, 2.2523495275527239, 2.2395390216261148, 2.2268569152802229, + 2.2142974212765694, 2.2018551602959633, 2.1895249988883734, 2.1773021686822176, + 2.1651821155101061, 2.1531605403870344, 2.1412334199994802, 2.1293968763202429, + 2.1176472660154104, 2.1059811022132635, 2.0943950917571783, 2.0828860662877560, + 2.0714510250836611, 2.0600870978087187, 2.0487915109843016, 2.0375616606324911, + 2.0263949912041426, 2.0152891036123037, 2.0042416434735060, 1.9932503849267960, + 1.9823131654411554, 1.9714278969913721, 1.9605926070362329, 1.9498053360730410, + 1.9390642102807760, 1.9283674117177725, 1.9177132192999125, 1.9070998858660460, + 1.8965258020907640, 1.8859893511980772, 1.8754889536648989, 1.8650231678038836, + 1.8545904289931059, 1.8441893383860588, 1.8338185232132673, 1.8234765660017729, + 1.8131621610373259, 1.8028740044683218, 1.7926107998937368, 1.7823712695389986, + 1.7721542436629534, 1.7619584631174803, 1.7517827805131674, 1.7416259888559580, + 1.7314869631081820, 1.7213646043092012, 1.7112577408552170, 1.7011653054505587, + 1.6910861935466528, 1.6810193713754416, 1.6709637474268675, 1.6609182581305504, + 1.6508819069713354, 1.6408536080271006, 1.6308323871344328, 1.6208171751350164, + 1.6108069960027933, 1.6008008290082216, 1.5907976571470499, 1.5807964820414782, + 1.5707963258028030, 1.5607961714267731, 1.5507949963212013, 1.5407918244600296, + 1.5307856574654579, 1.5207754783332348, 1.5107602663338184, 1.5007390454411507, + 1.4907107464969158, 1.4806743953377008, 1.4706289060413837, 1.4605732820928097, + 1.4505064599215984, 1.4404273480176926, 1.4303349126130342, 1.4202280491590500, + 1.4101056903600693, 1.3999666646122932, 1.3898098729550838, 1.3796341903507710, + 1.3694384098052979, 1.3592213839292526, 1.3489818535745144, 1.3387186489999294, + 1.3284304924309254, 1.3181160874664783, 1.3077741302549839, 1.2974033150821924, + 1.2870022244751453, 1.2765694856643677, 1.2661036998033524, 1.2556033022701740, + 1.2450668513774872, 1.2344927676022053, 1.2238794341683388, 1.2132252417504787, + 1.2025284431874752, 1.1917872473952103, 1.1810000464320183, 1.1701647564768791, + 1.1592794880270958, 1.1483422685414553, 1.1373510099947453, 1.1263035498559475, + 1.1151976622641087, 1.1040309928357601, 1.0928011424839497, 1.0815055556595325, + 1.0701416283845901, 1.0587065871804953, 1.0471975617110729, 1.0356115512549877, + 1.0239453874528408, 1.0121957771480083, 1.0003592334687710, 0.9884321130812168, + 0.9764105379581451, 0.9642904847860336, 0.9520676545798779, 0.9397374931722879, + 0.9272952321916819, 0.9147357381880283, 0.9020536318421364, 0.8892431259155273, + 0.8762980736792088, 0.8632118962705135, 0.8499775901436806, 0.8365875538438559, + 0.8230337146669626, 0.8093072846531868, 0.7953988462686539, 0.7812981363385916, + 0.7669940218329430, 0.7524743955582380, 0.7377259787172079, 0.7227342557162046, + 0.7074832264333963, 0.6919551976025105, 0.6761305183172226, 0.6599873416125774, + 0.6435011215507984, 0.6266442332416773, 0.6093853227794170, 0.5916886553168297, + 0.5735131185501814, 0.5548110511153936, 0.5355266667902470, 0.5155940335243940, + 0.4949341546744108, 0.4734511896967888, 0.4510268233716488, 0.4275122880935669, + 0.4027158617973328, 0.3763835001736879, 0.3481660466641188, 0.3175604660063982, + 0.2837941460311413, 0.2455655615776777, 0.2003348786383867, 0.1415395531803370, + 0.0000000000000000 +}; + +/* Reference degree table generated for acos(),asin() in range of [-1:1e-2:1]*/ +static const double degree_table[] = { + -57.2957795262336731, -56.7228217124938965, -56.1498639285564423, -55.5769061148166656, + -55.0039483308792114, -54.4309905469417572, -53.8580327332019806, -53.2850749492645264, + -52.7121171653270721, -52.1391593515872955, -51.5662015676498413, -50.9932437539100647, + -50.4202859699726105, -49.8473281860351562, -49.2743703722953796, -48.7014125883579254, + -48.1284548044204712, -47.5554969906806946, -46.9825392067432404, -46.4095813930034637, + -45.8366236090660095, -45.2636658251285553, -44.6907080113887787, -44.1177502274513245, + -43.5447924435138702, -42.9718346297740936, -42.3988768458366394, -41.8259190320968628, + -41.2529612481594086, -40.6800034642219543, -40.1070456504821777, -39.5340878665447235, + -38.9611300826072693, -38.3881722688674927, -37.8152144849300385, -37.2422566711902618, + -36.6692988872528076, -36.0963411033153534, -35.5233832895755768, -34.9504255056381226, + -34.3774677217006683, -33.8045099079608917, -33.2315521240234375, -32.6585943102836609, + -32.0856365263462067, -31.5126787424087524, -30.9397209286689758, -30.3667631447315216, + -29.7938053607940674, -29.2208475470542908, -28.6478897631168365, -28.0749319493770599, + -27.5019741654396057, -26.9290163815021515, -26.3560585677623749, -25.7831007838249207, + -25.2101429998874664, -24.6371851861476898, -24.0642274022102356, -23.4912695884704590, + -22.9183118045330048, -22.3453540205955505, -21.7723962068557739, -21.1994384229183197, + -20.6264806389808655, -20.0535228252410889, -19.4805650413036346, -18.9076072275638580, + -18.3346494436264038, -17.7616916596889496, -17.1887338459491730, -16.6157760620117188, + -16.0428182780742645, -15.4698604643344879, -14.8969026803970337, -14.3239448666572571, + -13.7509870827198029, -13.1780292987823486, -12.6050714850425720, -12.0321137011051178, + -11.4591559171676636, -10.8861981034278870, -10.3132403194904327, -9.7402825057506561, + -9.1673247218132019, -8.5943669378757477, -8.0214091241359711, -7.4484513401985168, + -6.8754935562610626, -6.3025357425212860, -5.7295779585838318, -5.1566201448440552, + -4.5836623609066010, -4.0107045769691467, -3.4377467632293701, -2.8647889792919159, + -2.2918311953544617, -1.7188733816146851, -1.1459155976772308, -0.5729577839374542, + 0.0000000000000000, 0.5729577839374542, 1.1459155976772308, 1.7188733816146851, + 2.2918311953544617, 2.8647889792919159, 3.4377467632293701, 4.0107045769691467, + 4.5836623609066010, 5.1566201448440552, 5.7295779585838318, 6.3025357425212860, + 6.8754935562610626, 7.4484513401985168, 8.0214091241359711, 8.5943669378757477, + 9.1673247218132019, 9.7402825057506561, 10.3132403194904327, 10.8861981034278870, + 11.4591559171676636, 12.0321137011051178, 12.6050714850425720, 13.1780292987823486, + 13.7509870827198029, 14.3239448666572571, 14.8969026803970337, 15.4698604643344879, + 16.0428182780742645, 16.6157760620117188, 17.1887338459491730, 17.7616916596889496, + 18.3346494436264038, 18.9076072275638580, 19.4805650413036346, 20.0535228252410889, + 20.6264806389808655, 21.1994384229183197, 21.7723962068557739, 22.3453540205955505, + 22.9183118045330048, 23.4912695884704590, 24.0642274022102356, 24.6371851861476898, + 25.2101429998874664, 25.7831007838249207, 26.3560585677623749, 26.9290163815021515, + 27.5019741654396057, 28.0749319493770599, 28.6478897631168365, 29.2208475470542908, + 29.7938053607940674, 30.3667631447315216, 30.9397209286689758, 31.5126787424087524, + 32.0856365263462067, 32.6585943102836609, 33.2315521240234375, 33.8045099079608917, + 34.3774677217006683, 34.9504255056381226, 35.5233832895755768, 36.0963411033153534, + 36.6692988872528076, 37.2422566711902618, 37.8152144849300385, 38.3881722688674927, + 38.9611300826072693, 39.5340878665447235, 40.1070456504821777, 40.6800034642219543, + 41.2529612481594086, 41.8259190320968628, 42.3988768458366394, 42.9718346297740936, + 43.5447924435138702, 44.1177502274513245, 44.6907080113887787, 45.2636658251285553, + 45.8366236090660095, 46.4095813930034637, 46.9825392067432404, 47.5554969906806946, + 48.1284548044204712, 48.7014125883579254, 49.2743703722953796, 49.8473281860351562, + 50.4202859699726105, 50.9932437539100647, 51.5662015676498413, 52.1391593515872955, + 52.7121171653270721, 53.2850749492645264, 53.8580327332019806, 54.4309905469417572, + 55.0039483308792114, 55.5769061148166656, 56.1498639285564423, 56.7228217124938965, + 57.2957795262336731 +}; diff --git a/test/ztest/unit/math/basic/trigonometry/trig_test.c b/test/ztest/unit/math/basic/trigonometry/trig_test.c new file mode 100644 index 000000000000..0e9471712891 --- /dev/null +++ b/test/ztest/unit/math/basic/trigonometry/trig_test.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// These contents may have been developed with support from one or more Intel-operated +// generative artificial intelligence solutions. +// +// Converted from CMock to Ztest +// +// Original tests from sof/test/cmocka/src/math/trig/: +// - sin_32b_fixed.c (Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com>) +// - sin_16b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - cos_32b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - cos_16b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - asin_32b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - asin_16b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - acos_32b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - acos_16b_fixed.c (Author: Shriram Shastry <malladi.sastry@linux.intel.com>) +// - lut_sin_16b_fixed.c (Authors: Slawomir Blauciak <slawomir.blauciak@linux.intel.com>, +// Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>) + +#define _USE_MATH_DEFINES +#include <math.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <zephyr/ztest.h> +#include <sof/audio/format.h> +#include <sof/audio/format_generic.h> +#include <sof/math/trig.h> +#include <sof/math/cordic.h> +#include <sof/math/lut_trig.h> +#include "trig_tables.h" +#include "atan2_tables.h" + +/* Define M_PI if not available */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +/* Conversion factor from degrees to radians (PI/180) */ +#define DEGREES_TO_RADIANS 0.017453292519943295 + +#define CMP_TOLERANCE_32B 0.0000000611175871f +#define CMP_TOLERANCE_16B 0.000065f +#define CMP_TOLERANCE_ASIN_32B 0.000000068141916f +#define CMP_TOLERANCE_ACOS_32B 0.000000060077032f +#define CMP_TOLERANCE_ASIN_16B 0.0001152158f +#define CMP_TOLERANCE_ACOS_16B 0.0001196862f +#define CMP_TOLERANCE_SIN 3.1e-5f +#define CMP_TOLERANCE_ATAN2 2.0e-5 /* ~0.001 degrees in radians */ + +/* + * Helper function for rounding double values to nearest integer + * Implements custom rounding: round to 0 if absolute value < 0.5, otherwise round normally + */ +static inline int32_t round_to_nearest_int(double value) +{ + double abs_value = fabs(value); + + return (int32_t) (abs_value >= 0.5) ? floor(value + 0.5) : 0.0; +} + +/* Test sin_32b_fixed function */ +ZTEST(trigonometry, test_sin_32b_fixed) +{ + int theta; + float delta; + double rad; + int32_t sin_val; + + for (theta = 0; theta < ARRAY_SIZE(sin_ref_table); ++theta) { + rad = M_PI * ((double)theta / 180.0); + sin_val = sin_fixed_32b(Q_CONVERT_FLOAT(rad, 28)); + delta = fabsf(sin_ref_table[theta] - Q_CONVERT_QTOF(sin_val, 31)); + zassert_true(delta <= CMP_TOLERANCE_32B, + "sin_32b_fixed failed for angle %d", theta); + } +} + +/* Test sin_16b_fixed function */ +ZTEST(trigonometry, test_sin_16b_fixed) +{ + int theta; + float delta; + double rad; + int16_t sin_val; + + for (theta = 0; theta < ARRAY_SIZE(sin_ref_table); ++theta) { + rad = M_PI * ((double)theta / 180.0); + sin_val = sin_fixed_16b(Q_CONVERT_FLOAT(rad, 28)); + delta = fabsf(sin_ref_table[theta] - Q_CONVERT_QTOF(sin_val, 15)); + zassert_true(delta <= CMP_TOLERANCE_16B, + "sin_16b_fixed failed for angle %d", theta); + } +} + +/* Test cos_32b_fixed function */ +ZTEST(trigonometry, test_cos_32b_fixed) +{ + int theta; + float delta; + double rad; + int32_t cos_val; + + for (theta = 0; theta < ARRAY_SIZE(cos_ref_table); ++theta) { + rad = M_PI * ((double)theta / 180.0); + cos_val = cos_fixed_32b(Q_CONVERT_FLOAT(rad, 28)); + delta = fabsf(cos_ref_table[theta] - Q_CONVERT_QTOF(cos_val, 31)); + zassert_true(delta <= CMP_TOLERANCE_32B, + "cos_32b_fixed failed for angle %d", theta); + } +} + +/* Test cos_16b_fixed function */ +ZTEST(trigonometry, test_cos_16b_fixed) +{ + int theta; + float delta; + double rad; + int16_t cos_val; + + for (theta = 0; theta < ARRAY_SIZE(cos_ref_table); ++theta) { + rad = M_PI * ((double)theta / 180.0); + cos_val = cos_fixed_16b(Q_CONVERT_FLOAT(rad, 28)); + delta = fabsf(cos_ref_table[theta] - Q_CONVERT_QTOF(cos_val, 15)); + zassert_true(delta <= CMP_TOLERANCE_16B, + "cos_16b_fixed failed for angle %d", theta); + } +} + +/* Test asin_32b_fixed function */ +ZTEST(trigonometry, test_asin_32b_fixed) +{ + int index; + float delta; + double u; + int32_t asin_val, input_val; + + for (index = 0; index < ARRAY_SIZE(degree_table); ++index) { + /* Convert degree to input value in Q2.30 format like original test */ + /* angleInRadians = PI/180 * angleInDegrees & const Q2.30 format */ + u = (DEGREES_TO_RADIANS * degree_table[index] * 0x40000000); + input_val = round_to_nearest_int(u); + + asin_val = asin_fixed_32b(input_val); + delta = fabsf(asin_ref_table[index] - Q_CONVERT_QTOF(asin_val, 29)); + zassert_true(delta <= CMP_TOLERANCE_ASIN_32B, + "asin_32b_fixed failed for index %d", index); + } +} + +/* Test asin_16b_fixed function */ +ZTEST(trigonometry, test_asin_16b_fixed) +{ + int index; + float delta; + double u; + int16_t asin_val; + int32_t input_val; + + for (index = 0; index < ARRAY_SIZE(degree_table); ++index) { + /* Convert degree to input value in Q2.30 format like original test */ + /* angleInRadians = PI/180 * angleInDegrees & const Q2.30 format */ + u = (DEGREES_TO_RADIANS * degree_table[index] * 0x40000000); + input_val = round_to_nearest_int(u); + + asin_val = asin_fixed_16b(input_val); + delta = fabsf(asin_ref_table[index] - Q_CONVERT_QTOF(asin_val, 13)); + zassert_true(delta <= CMP_TOLERANCE_ASIN_16B, + "asin_16b_fixed failed for index %d", index); + } +} + +/* Test acos_32b_fixed function */ +ZTEST(trigonometry, test_acos_32b_fixed) +{ + int index; + float delta; + double u; + int32_t acos_val, input_val; + + for (index = 0; index < ARRAY_SIZE(degree_table); ++index) { + /* Convert degree to input value in Q2.30 format like original test */ + /* angleInRadians = PI/180 * angleInDegrees & const Q2.30 format */ + u = (DEGREES_TO_RADIANS * degree_table[index] * 0x40000000); + input_val = round_to_nearest_int(u); + + acos_val = acos_fixed_32b(input_val); + delta = fabsf(acos_ref_table[index] - Q_CONVERT_QTOF(acos_val, 29)); + zassert_true(delta <= CMP_TOLERANCE_ACOS_32B, + "acos_32b_fixed failed for index %d", index); + } +} + +/* Test acos_16b_fixed function */ +ZTEST(trigonometry, test_acos_16b_fixed) +{ + int index; + float delta; + double u; + int16_t acos_val; + int32_t input_val; + + for (index = 0; index < ARRAY_SIZE(degree_table); ++index) { + /* Convert degree to input value in Q2.30 format like original test */ + /* angleInRadians = PI/180 * angleInDegrees & const Q2.30 format */ + u = (DEGREES_TO_RADIANS * degree_table[index] * 0x40000000); + input_val = round_to_nearest_int(u); + + acos_val = acos_fixed_16b(input_val); + delta = fabsf(acos_ref_table[index] - Q_CONVERT_QTOF(acos_val, 13)); + zassert_true(delta <= CMP_TOLERANCE_ACOS_16B, + "acos_16b_fixed failed for index %d", index); + } +} + +/* Test sin lookup table function */ +ZTEST(trigonometry, test_sin_lut_16b_fixed) +{ + int theta; + float delta; + double rad; + int16_t sin_val; + + for (theta = 0; theta < ARRAY_SIZE(sin_ref_table); ++theta) { + rad = M_PI * (double)theta / 180.0; + sin_val = sofm_lut_sin_fixed_16b(Q_CONVERT_FLOAT(rad, 28)); + delta = fabsf(sin_ref_table[theta] - Q_CONVERT_QTOF(sin_val, 15)); + zassert_true(delta <= CMP_TOLERANCE_SIN, + "sin_lut_16b_fixed failed for angle %d", theta); + } +} + +/* Test sofm_atan2_32b function */ +ZTEST(trigonometry, test_atan2) +{ + double reference; + double result; + double delta; + double delta_max = 0.0; + int32_t result_q29_max = 0; + int32_t result_q29; + int i_max = 0; + int i; + + /* Note that the first atan2_test_y[], atan2_test_x[] have forced to + * zero y or x, values to test edge cases where x == 0 or y == 0. See + * script atan2_tables.m for details. + */ + for (i = 0; i < ATAN2_TEST_TABLE_SIZE; ++i) { + result_q29 = sofm_atan2_32b(atan2_test_y[i], atan2_test_x[i]); + result = Q_CONVERT_QTOD(result_q29, 29); + reference = Q_CONVERT_QTOD(atan2_test_ref[i], 29); + delta = fabs(reference - result); + if (i == 0 || delta > delta_max) { + result_q29_max = result_q29; + delta_max = delta; + i_max = i; + } + zassert_true(delta <= CMP_TOLERANCE_ATAN2, + "sofm_atan2_32b failed for input %d: (%d, %d) result %d, expected %d", + i, atan2_test_y[i], atan2_test_x[i], result_q29, atan2_test_ref[i]); + } + printf(" INFO - Maximum delta for atan2 test %d: %.6e (%d, %d) result %d\n", + i_max, delta_max, atan2_test_y[i_max], atan2_test_x[i_max], result_q29_max); +} + +ZTEST_SUITE(trigonometry, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/objpool/CMakeLists.txt b/test/ztest/unit/objpool/CMakeLists.txt new file mode 100644 index 000000000000..2ce499607463 --- /dev/null +++ b/test/ztest/unit/objpool/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_objpool) + +set(SOF_ROOT "${PROJECT_SOURCE_DIR}/../../../..") + +# Include SOF CMake functions +include(${SOF_ROOT}/scripts/cmake/misc.cmake) + +target_include_directories(app PRIVATE + ${SOF_ROOT}/zephyr/include + ${SOF_ROOT}/src/include + ${SOF_ROOT}/src/platform/posix/include +) + +# Define SOF-specific configurations for unit testing +target_compile_definitions(app PRIVATE + -DCONFIG_ZEPHYR_POSIX=1 +) + +target_sources(app PRIVATE + test_objpool_ztest.c + ${SOF_ROOT}/test/ztest/unit/common/alloc.c + ${SOF_ROOT}/src/lib/objpool.c +) + +target_link_libraries(app PRIVATE "-Wl,--wrap=rzalloc,--wrap=sof_heap_alloc,--wrap=sof_heap_free,--wrap=sof_sys_heap_get") + +# Add RELATIVE_FILE definitions for SOF trace functionality +sof_append_relative_path_definitions(app) diff --git a/test/ztest/unit/objpool/prj.conf b/test/ztest/unit/objpool/prj.conf new file mode 100644 index 000000000000..d34c7781cd0a --- /dev/null +++ b/test/ztest/unit/objpool/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_SOF_FULL_ZEPHYR_APPLICATION=n diff --git a/test/ztest/unit/objpool/test_objpool_ztest.c b/test/ztest/unit/objpool/test_objpool_ztest.c new file mode 100644 index 000000000000..596fb3accd70 --- /dev/null +++ b/test/ztest/unit/objpool/test_objpool_ztest.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#define DATA_SIZE 5 +#define ALIGNED_SIZE ALIGN_UP(DATA_SIZE, sizeof(int)) + +#include <zephyr/ztest.h> +#include <sof/objpool.h> +#include <sof/common.h> +#include <sof/list.h> + +#include <rtos/alloc.h> + +#include <stdlib.h> +#include <string.h> + +ZTEST(objpool_suite, test_objpool_wrong_size) +{ + struct objpool_head head = {.list = LIST_INIT(head.list)}; + /* new object pool of 2 blocks */ + uint8_t *block1 = objpool_alloc(&head, DATA_SIZE, 0); + /* should fail because of a different size */ + uint8_t *block2 = objpool_alloc(&head, DATA_SIZE + 1, 0); + /* second block in the first object pool */ + uint8_t *block3 = objpool_alloc(&head, DATA_SIZE, 0); + /* new object pool of 4 blocks */ + uint8_t *block4 = objpool_alloc(&head, DATA_SIZE, 0); + /* should fail because of a different size */ + uint8_t *block5 = objpool_alloc(&head, DATA_SIZE * 2, 0); + /* should fail because of different flags */ + uint8_t *block6 = objpool_alloc(&head, DATA_SIZE * 2, SOF_MEM_FLAG_COHERENT); + + zassert_not_null(block1); + zassert_is_null(block2); + zassert_not_null(block3); + zassert_not_null(block4); + zassert_is_null(block5); + zassert_is_null(block6); + + zassert_not_ok(objpool_free(&head, block1 + 1)); + zassert_ok(objpool_free(&head, block1)); + zassert_not_ok(objpool_free(&head, block3 + 1)); + zassert_ok(objpool_free(&head, block3)); + zassert_not_ok(objpool_free(&head, block4 + 1)); + zassert_ok(objpool_free(&head, block4)); +} + +ZTEST(objpool_suite, test_objpool) +{ + struct objpool_head head = {.list = LIST_INIT(head.list)}; + void *blocks[62]; /* 2 + 4 + 8 + 16 + 32 */ + unsigned int k = 0; + + /* Loop over all powers: 2^1..2^5 */ + for (unsigned int i = 1; i <= 5; i++) { + unsigned int n = 1 << i; + uint8_t *start; + + for (unsigned int j = 0; j < n; j++) { + uint8_t *block = objpool_alloc(&head, DATA_SIZE, 0); + + zassert_not_null(block, "allocation failed loop %u iter %u", i, j); + + if (!j) + start = block; + else + zassert_equal(block, start + ALIGNED_SIZE * j, "wrong pointer"); + + blocks[k++] = block; + } + } + + while (k--) + zassert_ok(objpool_free(&head, blocks[k]), "free failed"); +} + +struct test_objpool_data { + char cnt; + uint8_t reserved[DATA_SIZE - sizeof(char)]; +} __packed; + +static unsigned int test_objpool_check; + +static bool test_objpool_cb(void *data, void *arg) +{ + struct test_objpool_data *odata = data; + + zassert_equal(test_objpool_check++, odata->cnt, "Counter mismatch"); + zassert_equal((unsigned int)arg, 2, "Wrong argument"); + + return odata->cnt == (unsigned int)arg; +} + +ZTEST(objpool_suite, test_objpool_iterate) +{ + struct objpool_head head = {.list = LIST_INIT(head.list)}; + unsigned int i; + + for (i = 0; i < 4; i++) { + struct test_objpool_data *odata = objpool_alloc(&head, sizeof(*odata), 0); + + zassert_not_null(odata, "allocation failed loop %u", i); + + odata->cnt = i; + } + + int ret = objpool_iterate(&head, test_objpool_cb, (void *)2); + + zassert_equal(test_objpool_check, 3); + + zassert_ok(ret); + + /* Reset for a possible rerun */ + test_objpool_check = 0; +} + +ZTEST_SUITE(objpool_suite, NULL, NULL, NULL, NULL, NULL); diff --git a/test/ztest/unit/objpool/testcase.yaml b/test/ztest/unit/objpool/testcase.yaml new file mode 100644 index 000000000000..5558c1f50a6b --- /dev/null +++ b/test/ztest/unit/objpool/testcase.yaml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright(c) 2025 Intel Corporation. +# +# Object pool allocator unit tests for Ztest framework + +tests: + sof.unit.objpool: + tags: unit + platform_allow: native_sim + integration_platforms: + - native_sim + build_only: false diff --git a/third_party/include/DtsSofInterface.h b/third_party/include/DtsSofInterface.h new file mode 100644 index 000000000000..209ff8244d5f --- /dev/null +++ b/third_party/include/DtsSofInterface.h @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Xperi. All rights reserved. +// +// Author: Mark Barton <mark.barton@xperi.com> +#ifndef __SOF_AUDIO_DTS_SOF_INTERFACE_H__ +#define __SOF_AUDIO_DTS_SOF_INTERFACE_H__ + +#include "DtsSofInterfaceResult.h" +#include "DtsSofInterfaceVersion.h" + +#include <stddef.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef _WINDOWS +#define DTS_SOF_INTERFACE_API __declspec(dllexport) +#else +#define DTS_SOF_INTERFACE_API +#endif + +#if !defined(DTS_SOF_INTERFACE_NOEXCEPT) +#if (defined(__cplusplus) && __cplusplus >= 201103L) && (defined(_MSC_VER) && _MSC_VER >= 1900 && defined(_CPPUNWIND)) +#define DTS_SOF_INTERFACE_NOEXCEPT noexcept +#elif (defined(_MSC_VER) && defined(_CPPUNWIND)) +#define DTS_SOF_INTERFACE_NOEXCEPT throw() +#else +#define DTS_SOF_INTERFACE_NOEXCEPT +#endif +#endif + +typedef struct DtsSofInterfaceInst DtsSofInterfaceInst; + +typedef enum { + // Supported parameter ids + DTS_SOF_INTERFACE_PARAMETER_ID_SINGLE_CONFIGURATION = 1, +} DtsSofInterfaceParameterId; + +typedef enum +{ + DTS_SOF_INTERFACE_BUFFER_LAYOUT_INTERLEAVED = 0, + DTS_SOF_INTERFACE_BUFFER_LAYOUT_NONINTERLEAVED, +} DtsSofInterfaceBufferLayout; + +typedef enum +{ + DTS_SOF_INTERFACE_BUFFER_FORMAT_SINT16LE = 0, + DTS_SOF_INTERFACE_BUFFER_FORMAT_SINT24LE, + DTS_SOF_INTERFACE_BUFFER_FORMAT_SINT32LE, + DTS_SOF_INTERFACE_BUFFER_FORMAT_FLOAT32, +} DtsSofInterfaceBufferFormat; + +typedef struct DtsSofInterfaceBufferConfiguration +{ + DtsSofInterfaceBufferLayout bufferLayout; + DtsSofInterfaceBufferFormat bufferFormat; + unsigned int sampleRate; + unsigned int numChannels; + unsigned int periodInFrames; +} DtsSofInterfaceBufferConfiguration; + +typedef void* (*DtsSofInterfaceAllocateMemory)( + void *pMemoryAllocationContext, + unsigned int length, + unsigned int alignment); + +typedef void (*DtsSofInterfaceFreeMemory)(void *pMemoryAllocationContext, void *pMemory); + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceInit( + DtsSofInterfaceInst **ppInst, + DtsSofInterfaceAllocateMemory pMemoryAllocationFn, + DtsSofInterfaceFreeMemory pMemoryFreeFn, + void *MemoryAllocationContext) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfacePrepare( + DtsSofInterfaceInst* pInst, + const DtsSofInterfaceBufferConfiguration* pBufferConfiguration, + void** ppSofInputBuffer, + unsigned int* pSofInputBufferSize, + void** ppSofOutputBuffer, + unsigned int* pSofOutputBufferSize) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceInitProcess( + DtsSofInterfaceInst* pInst) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceProcess( + DtsSofInterfaceInst* pInst, + unsigned int* pNumBytesProcessed) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceApplyConfig( + DtsSofInterfaceInst* pInst, + int parameterId, + const void *pData, + unsigned int dataSize) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceReset( + DtsSofInterfaceInst* pInst) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceFree( + DtsSofInterfaceInst* pInst) DTS_SOF_INTERFACE_NOEXCEPT; + +DtsSofInterfaceResult DTS_SOF_INTERFACE_API dtsSofInterfaceGetVersion( + DtsSofInterfaceVersionInfo* pInterfaceVersion, + DtsSofInterfaceVersionInfo* pSdkVersion) DTS_SOF_INTERFACE_NOEXCEPT; + +#if defined(__cplusplus) +} +#endif + +#endif // __SOF_AUDIO_DTS_SOF_INTERFACE_H__ diff --git a/third_party/include/DtsSofInterfaceResult.h b/third_party/include/DtsSofInterfaceResult.h new file mode 100644 index 000000000000..f64fdc41adf4 --- /dev/null +++ b/third_party/include/DtsSofInterfaceResult.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Xperi. All rights reserved. +// +// Author: Mark Barton <mark.barton@xperi.com> +#ifndef __SOF_AUDIO_DTS_SOF_INTERFACE_RESULT_H__ +#define __SOF_AUDIO_DTS_SOF_INTERFACE_RESULT_H__ + + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef enum DtsSofInterfaceResult +{ + DTS_SOF_INTERFACE_RESULT_SUCCESS = 0, + + DTS_SOF_INTERFACE_RESULT_ERROR_NO_MEMORY = -1001000, + DTS_SOF_INTERFACE_RESULT_ERROR_ALREADY_INITIALIZED_MODULE = -1001001, + DTS_SOF_INTERFACE_RESULT_ERROR_DTS_INTERNAL_MODULE_ERROR = -1001002, + DTS_SOF_INTERFACE_RESULT_INVALID_SDK_VERSION = -1001003, + DTS_SOF_INTERFACE_RESULT_ERROR_PARAMETER_NULL = -1001004, + DTS_SOF_INTERFACE_RESULT_ERROR_INVALID_PARAMETER_SYSTEM_LAYOUT = -1001005, + DTS_SOF_INTERFACE_RESULT_ERROR_INVALID_PARAMETER_SYSTEM_FORMAT = -1001006, + DTS_SOF_INTERFACE_RESULT_ERROR_INVALID_PARAMETER_SYSTEM_SAMPLE_RATE = -1001007, + DTS_SOF_INTERFACE_RESULT_ERROR_INCORRECT_LIFETIME_STATE = -1001008, + DTS_SOF_INTERFACE_RESULT_ERROR_INVALID_PARAMETER_ID = -1001009, + DTS_SOF_INTERFACE_RESULT_ERROR_INVALID_CONFIGURATION_DATA = -1001010, + +} DtsSofInterfaceResult; + +#if defined(__cplusplus) +} +#endif + +#endif // __SOF_AUDIO_DTS_SOF_INTERFACE_RESULT_H__ diff --git a/third_party/include/DtsSofInterfaceVersion.h b/third_party/include/DtsSofInterfaceVersion.h new file mode 100644 index 000000000000..553537a2c8cf --- /dev/null +++ b/third_party/include/DtsSofInterfaceVersion.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Xperi. All rights reserved. +// +// Author: Mark Barton <mark.barton@xperi.com> +#ifndef __SOF_AUDIO_DTS_SOF_INTERFACE_VERSION_H__ +#define __SOF_AUDIO_DTS_SOF_INTERFACE_VERSION_H__ + +#define DTS_SOF_INTERFACE_PRODUCT_NAME "DtsSofInterface" +#define DTS_SOF_INTERFACE_PRODUCT_VERSION_MAJOR 1 +#define DTS_SOF_INTERFACE_PRODUCT_VERSION_MINOR 1 +#define DTS_SOF_INTERFACE_PRODUCT_VERSION_PATCH 3 +#define DTS_SOF_INTERFACE_PRODUCT_VERSION_BUILD 0 +#define DTS_SOF_INTERFACE_PRODUCT_VERSION_EXTRA "RC2" + +#if defined(__cplusplus) +extern "C" { +#endif + +/** Version information for the library. + */ +typedef struct DtsSofInterfaceVersionInfo +{ + /** Name of product. + */ + const char* product; + /** Major version number. + */ + int major; + /** Minor version number. + */ + int minor; + /** Patch number. + */ + int patch; + /** Build number. + */ + int build; +} DtsSofInterfaceVersionInfo; + +#if defined(__cplusplus) +} +#endif + +#endif // __SOF_AUDIO_DTS_SOF_INTERFACE_VERSION_H__ diff --git a/third_party/include/dax_inf.h b/third_party/include/dax_inf.h new file mode 100644 index 000000000000..8e25f52fc4a7 --- /dev/null +++ b/third_party/include/dax_inf.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE + * + * Copyright(c) 2025 Dolby Laboratories. All rights reserved. + * + * Author: Jun Lai <jun.lai@dolby.com> + */ + +#ifndef DAX_INF_H +#define DAX_INF_H + +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +enum dax_device { + DAX_DEVICE_UNSUPPORTED = -1, + DAX_DEVICE_SPEAKER = 0, + DAX_DEVICE_HEADPHONE = 1, +}; + +enum dax_frame_fmt { + DAX_FMT_UNSUPPORTED = -1, + DAX_FMT_SHORT_16 = 4, + DAX_FMT_INT = 5, + DAX_FMT_FLOAT = 7, +}; + +enum dax_sample_rate { + DAX_RATE_UNSUPPORTED = -1, +}; + +enum dax_channels { + DAX_CHANNLES_UNSUPPORTED = -1, +}; + +enum dax_buffer_fmt { + DAX_BUFFER_LAYOUT_UNSUPPORTED = -1, + DAX_BUFFER_LAYOUT_INTERLEAVED, + DAX_BUFFER_LAYOUT_NONINTERLEAVED, +}; + +enum dax_param_id { + DAX_PARAM_ID_ENABLE = 0x08001026, + DAX_PARAM_ID_TUNING_FILE = 0x08001027, + DAX_PARAM_ID_PROFILE = 0x08001028, + DAX_PARAM_ID_ENDPOINT = 0x08001029, + DAX_PARAM_ID_TUNING_DEVICE = 0x08001030, + DAX_PARAM_ID_CP_ENABLE = 0x08001031, + DAX_PARAM_ID_OUT_DEVICE = 0x08001032, + DAX_PARAM_ID_ABSOLUTE_VOLUME = 0x08001033, + DAX_PARAM_ID_CTC_ENABLE = 0x08001034, +}; + +struct dax_media_fmt { + enum dax_frame_fmt data_format; + uint32_t sampling_rate; + uint32_t num_channels; + enum dax_buffer_fmt layout; + uint32_t bytes_per_sample; +}; + +struct dax_buffer { + void *addr; + uint32_t size; /* Total buffer size in bytes */ + uint32_t avail; /* Available bytes for reading */ + uint32_t free; /* Free bytes for writing */ +}; + +struct sof_dax { + /* SOF module parameters */ + uint32_t sof_period_bytes; + + /* DAX state parameters */ + uint32_t period_bytes; + uint32_t period_us; + int32_t endpoint; + int32_t tuning_device; + void *blob_handler; + void *p_dax; + struct dax_media_fmt input_media_format; + struct dax_media_fmt output_media_format; + + /* DAX control parameters */ + int32_t enable; + int32_t profile; + int32_t out_device; + int32_t ctc_enable; + int32_t content_processing_enable; + int32_t volume; + uint32_t update_flags; /* Deprecated */ + + /* DAX buffers */ + struct dax_buffer persist_buffer; /* Used for dax instance */ + struct dax_buffer scratch_buffer; /* Used for dax process */ + struct dax_buffer input_buffer; + struct dax_buffer output_buffer; + struct dax_buffer tuning_file_buffer; +}; + +/** + * @brief Query the persistent memory requirements for the DAX module + * + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return Size of required persistent memory in bytes + */ +uint32_t dax_query_persist_memory(struct sof_dax *dax_ctx); + +/** + * @brief Query the scratch memory requirements for the DAX module + * + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return Size of required scratch memory in bytes + */ +uint32_t dax_query_scratch_memory(struct sof_dax *dax_ctx); + +/** + * @brief Query the number of frames in a processing period + * + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return Number of frames per period + */ +uint32_t dax_query_period_frames(struct sof_dax *dax_ctx); + +/** + * @brief Free the DAX module + * + * @param[in] dax_ctx Pointer to the DAX context structure + * + * This function free all resources built on persistent buffer. + * DO NOT USE THE INSTANCE AFTER CALLING FREE. + * + * @return 0 on success, negative error code on failure + */ +int dax_free(struct sof_dax *dax_ctx); + +/** + * @brief Initialize the DAX module + * + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return 0 on success, negative error code on failure + */ +int dax_init(struct sof_dax *dax_ctx); + +/** + * @brief Process audio data through the DAX module + * + * If DAX is disabled or the DAX instance is invalid (dax_ctx->p_dax is NULL), + * the dax_process will by default perform only copy operations, without any + * audio processing. + * + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return Bytes of processed. negative error code on failure + */ +int dax_process(struct sof_dax *dax_ctx); + +/** + * @brief Set a parameter value for the DAX module + * + * @param[in] id Parameter identifier + * @param[in] val Pointer to parameter value + * @param[in] val_sz Size of parameter value in bytes + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return 0 on success, negative error code on failure + */ +int dax_set_param(uint32_t id, const void *val, uint32_t val_sz, struct sof_dax *dax_ctx); + +/** + * @brief Enable/Disable the DAX module + * + * @param[in] enable 0:disable, 1:enable. + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return 0 on success, negative error code on failure + */ +int dax_set_enable(int32_t enable, struct sof_dax *dax_ctx); + +/** + * @brief Set the volume for the DAX module + * + * @param[in] volume Value to apply + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return 0 or positive code on success, negative error code on failure + */ +int dax_set_volume(int32_t volume, struct sof_dax *dax_ctx); + +/** + * @brief Update the output device configuration + * + * @param[in] out_device Output device identifier. Supported devices: + * 0: speaker + * 1: headphone + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return 0 on success, negative error code on failure + */ +int dax_set_device(int32_t out_device, struct sof_dax *dax_ctx); + +/** + * @brief Enable/Disable crosstalk cancellation feature + * + * @param[in] enable 0:disable, 1:enable. + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return 0 on success, negative error code on failure + */ +int dax_set_ctc_enable(int32_t enable, struct sof_dax *dax_ctx); + +/** + * @brief Get the DAX module version string + * + * @return Pointer to null-terminated version string + */ +const char *dax_get_version(void); + +/** + * @brief Find parameters in a buffer based on query criteria + * + * @param[in] query_id ID of the parameter to search for. Supported query IDs: + * - DAX_PARAM_ID_PROFILE + * - DAX_PARAM_ID_TUNING_DEVICE + * - DAX_PARAM_ID_CP_ENABLE + * @param[in] query_val Value to match when searching + * @param[out] query_sz Pointer to store the size of the found parameters + * @param[in] dax_ctx Pointer to the DAX context structure + * + * @return Pointer to the found parameters, or NULL if not found + */ +void *dax_find_params(uint32_t query_id, + int32_t query_val, + uint32_t *query_sz, + struct sof_dax *dax_ctx); + +#endif /* DAX_INF_H */ diff --git a/third_party/include/google_audio_post_processing.h b/third_party/include/google_audio_post_processing.h new file mode 100644 index 000000000000..766655973e77 --- /dev/null +++ b/third_party/include/google_audio_post_processing.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Google LLC. + * + * Author: Kehuang Li <kehuangli@google.com> + */ + +#ifndef GOOGLE_AUDIO_POST_PROCESSING_H +#define GOOGLE_AUDIO_POST_PROCESSING_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// This define ensure that the linked library matches the header file. +#define GoogleAudioPostProcessingCreate GoogleAudioPostProcessingCreate_v1 + +typedef struct GoogleAudioPostProcessingState GoogleAudioPostProcessingState; + +struct GoogleAudioPostProcessingBuffer { + uint16_t sample_size; // Bytes per sample, s16=>2, s32=>4. + uint16_t channels; // Number of interleaved channels. + uint32_t frames; // Total available frames. + void *base_addr; // Start address of the circular buffer. + void *head_ptr; // Current read/write position of the circular buffer. + void *end_addr; // End address of the circular buffer. +}; + +// Creates an instance of GoogleAudioPostProcessing with the tuning embedded in +// the library. +GoogleAudioPostProcessingState *GoogleAudioPostProcessingCreate(void); + +// Frees all allocated resources in `state` and deletes `state`. +void GoogleAudioPostProcessingDelete(GoogleAudioPostProcessingState *state); + +// Setup or reconfigure the audio processing. +// Returns 0 if success and non zero if failure. +int GoogleAudioPostProcessingSetup(GoogleAudioPostProcessingState *const state, + int channels, int frames, int volume, + const uint8_t *const config, + int config_size); + +// Pulls the current config (serialized) of the audio processing pipeline. +// If the config size is greater than `max_config_size`, following calls with +// `msg_index` > 0 can happen, and the implementation will maintain that internally. +// Returns config size if success and negative if failure. +int GoogleAudioPostProcessingGetConfig( + GoogleAudioPostProcessingState *const state, int code, int msg_index, + uint8_t *const config, int max_config_size); + +// Accepts and produces a frame of interleaved 32 bit integer audio. `src` and +// `dest` may use the same memory, if desired. +// Returns 0 if success and non zero if failure. +int GoogleAudioPostProcessingProcess( + GoogleAudioPostProcessingState *const state, + const struct GoogleAudioPostProcessingBuffer *const src, + struct GoogleAudioPostProcessingBuffer *const dest); + +// Sets system volume. +// Returns volume if success and negative if failure. +int GoogleAudioPostProcessingSetVol(GoogleAudioPostProcessingState *const state, + const int *const volume, int num_channels); + +// Gets current volume. +// Returns 0 if success and non zero if failure. +int GoogleAudioPostProcessingGetVol(GoogleAudioPostProcessingState *const state, + int *const volume, int num_channels); + +#ifdef __cplusplus +} +#endif + +#endif // GOOGLE_AUDIO_POST_PROCESSING_H diff --git a/third_party/include/google_audio_post_processing_platform.h b/third_party/include/google_audio_post_processing_platform.h new file mode 100644 index 000000000000..cb6ee7f46cf9 --- /dev/null +++ b/third_party/include/google_audio_post_processing_platform.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Google LLC. + * + * Author: Kehuang Li <kehuangli@google.com> + */ + +#ifndef GOOGLE_AUDIO_POST_PROCESSING_PLATFORM_H_ +#define GOOGLE_AUDIO_POST_PROCESSING_PLATFORM_H_ + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Allocates memory of size `size` and returns a pointer to the allocated +// memory. If no memory is available, NULL is returned. +void *GoogleAudioPostProcessingMalloc(size_t size); + +// Frees the memory pointed to by `p`. +void GoogleAudioPostProcessingFree(void *p); + +// Log "line: code". +void GoogleAudioPostProcessingLog(int line, int code); + +#ifdef __cplusplus +} +#endif + +#endif // GOOGLE_AUDIO_POST_PROCESSING_PLATFORM_H_ diff --git a/third_party/include/google_ctc_audio_processing.h b/third_party/include/google_ctc_audio_processing.h new file mode 100644 index 000000000000..6c473425c3b8 --- /dev/null +++ b/third_party/include/google_ctc_audio_processing.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2024 Google LLC. + * + * Author: Eddy Hsu <eddyhsu@google.com> + */ +#ifndef GOOGLE_CTC_AUDIO_PROCESSING_H +#define GOOGLE_CTC_AUDIO_PROCESSING_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct GoogleCtcAudioProcessingState GoogleCtcAudioProcessingState; + +// Creates an instance of GoogleCtcAudioProcessing with the tuning embedded in +// the library. If creation fails, NULL is returned. +GoogleCtcAudioProcessingState *GoogleCtcAudioProcessingCreate(void); + +GoogleCtcAudioProcessingState *GoogleCtcAudioProcessingCreateWithConfig(int chunk_frames, + int sample_rate, + const uint8_t *config, + int config_size); + +// Frees all allocated resources in `state`. +void GoogleCtcAudioProcessingFree(GoogleCtcAudioProcessingState *state); + +// Apply CTC on `src` and produce result in `dest`. +void GoogleCtcAudioProcessingProcess(GoogleCtcAudioProcessingState *state, + const float *src, float *dest, + int num_frames, int num_channels); + +// Reconfigure the audio processing. +// Returns 0 if success and non zero if failure. +int GoogleCtcAudioProcessingReconfigure(GoogleCtcAudioProcessingState *state, + const uint8_t *config, int config_size); + +#ifdef __cplusplus +} +#endif + +#endif // GOOGLE_CTC_AUDIO_PROCESSING_H diff --git a/third_party/include/google_rtc_audio_processing.h b/third_party/include/google_rtc_audio_processing.h new file mode 100644 index 000000000000..1c6f149c7ea5 --- /dev/null +++ b/third_party/include/google_rtc_audio_processing.h @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Google LLC. +// +// Author: Lionel Koenig <lionelk@google.com> +#ifndef GOOGLE_RTC_AUDIO_PROCESSING_H +#define GOOGLE_RTC_AUDIO_PROCESSING_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// This define ensure that the linked library matches the header file. +// LINT.IfChange(api_version) +#define GoogleRtcAudioProcessingCreate GoogleRtcAudioProcessingCreate_v1 +// LINT.ThenChange() + +typedef struct GoogleRtcAudioProcessingState GoogleRtcAudioProcessingState; + +// LINT.IfChange() + +// Attaches `buffer` to use for memory allocations. The ownership of `buffer` +// remains within the caller. +void GoogleRtcAudioProcessingAttachMemoryBuffer(uint8_t *const buffer, + int buffer_size); + +// Detaches any attached memory buffer used for memory allocations. Returns 0 if +// success and non zero if failure. +void GoogleRtcAudioProcessingDetachMemoryBuffer(void); + +// Creates an instance of GoogleRtcAudioProcessing with the tuning embedded in +// the library. If creation fails, NULL is returned. +GoogleRtcAudioProcessingState *GoogleRtcAudioProcessingCreate(void); + +// Creates an instance of GoogleRtcAudioProcessing based on `config` and stream +// formats, where the content of config overrides any embedded parameters and +// the stream formats overrides any content in the config. Setting `config` to +// NULL means that no config is specified. If creation fails, NULL is returned. +GoogleRtcAudioProcessingState *GoogleRtcAudioProcessingCreateWithConfig( + int capture_sample_rate_hz, int num_capture_input_channels, + int num_capture_output_channels, int render_sample_rate_hz, + int num_render_channels, const uint8_t *const config, int config_size); + +// Frees all allocated resources in `state`. +void GoogleRtcAudioProcessingFree(GoogleRtcAudioProcessingState *state); + +// Specifies the stream formats to use. Returns 0 if success and non zero if +// failure. +int GoogleRtcAudioProcessingSetStreamFormats( + GoogleRtcAudioProcessingState *const state, int capture_sample_rate_hz, + int num_capture_input_channels, int num_capture_output_channels, + int render_sample_rate_hz, int num_render_channels); + +// Specifies setup-specific parameters. Returns 0 if success and non zero if +// failure. Parameters which are NULL are ignored. +int GoogleRtcAudioProcessingParameters( + GoogleRtcAudioProcessingState *const state, float *capture_headroom_linear, + float *echo_path_delay_ms); + +// Returns the framesize used for processing. +int GoogleRtcAudioProcessingGetFramesizeInMs( + GoogleRtcAudioProcessingState *const state); + +// Reconfigure the audio processing. +// Returns 0 if success and non zero if failure. +int GoogleRtcAudioProcessingReconfigure( + GoogleRtcAudioProcessingState *const state, const uint8_t *const config, + int config_size); + +// Processes the microphone stream. +// Accepts deinterleaved float audio with the range [-1, 1]. Each element of +// |src| points to an array of samples for the channel. At output, the channels +// will be in |dest|. +// Returns 0 if success and non zero if failure. +int GoogleRtcAudioProcessingProcessCapture_float32( + GoogleRtcAudioProcessingState *const state, const float *const *src, + float *const *dest); + +// Accepts and and produces a frame of interleaved 16 bit integer audio. `src` +// and `dest` may use the same memory, if desired. +// Returns 0 if success and non zero if failure. +int GoogleRtcAudioProcessingProcessCapture_int16( + GoogleRtcAudioProcessingState *const state, const int16_t *const src, + int16_t *const dest); + +// Analyzes the playback stream. +// Accepts deinterleaved float audio with the range [-1, 1]. Each element +// of |src| points to an array of samples for the channel. +// Returns 0 if success and non zero if failure. +int GoogleRtcAudioProcessingAnalyzeRender_float32( + GoogleRtcAudioProcessingState *const state, const float *const *src); + +// Accepts interleaved int16 audio. +// Returns 0 if success and non zero if failure. +int GoogleRtcAudioProcessingAnalyzeRender_int16( + GoogleRtcAudioProcessingState *const state, const int16_t *const src); + +// LINT.ThenChange(:api_version) + +#ifdef __cplusplus +} +#endif + +#endif // GOOGLE_RTC_AUDIO_PROCESSING_H diff --git a/third_party/include/google_rtc_audio_processing_platform.h b/third_party/include/google_rtc_audio_processing_platform.h new file mode 100644 index 000000000000..f0043d97c85d --- /dev/null +++ b/third_party/include/google_rtc_audio_processing_platform.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Google LLC. +// +// Author: Lionel Koenig <lionelk@google.com> +#ifndef GOOGLE_RTC_AUDIO_PROCESSING_PLATFORM_H_ +#define GOOGLE_RTC_AUDIO_PROCESSING_PLATFORM_H_ + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Allocates memory of size `size` and returns a pointer to the allocated +// memory. If no memory is available, NULL is returned. +void *GoogleRtcMalloc(size_t size); + +// Frees the memory pointed to by `p`. +void GoogleRtcFree(void *p); + +#ifdef __cplusplus +} +#endif + +#endif // GOOGLE_RTC_AUDIO_PROCESSING_PLATFORM_H_ diff --git a/third_party/include/google_rtc_audio_processing_sof_message_reader.h b/third_party/include/google_rtc_audio_processing_sof_message_reader.h new file mode 100644 index 000000000000..6eb7c51817b0 --- /dev/null +++ b/third_party/include/google_rtc_audio_processing_sof_message_reader.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Google LLC. +// +// Author: Per Ahgren <peah@google.com> +#ifndef GOOGLE_RTC_AUDIO_PROCESSING_SOF_MESSAGE_READER_H_ +#define GOOGLE_RTC_AUDIO_PROCESSING_SOF_MESSAGE_READER_H_ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Parses the fields from a SOF config message `message` of size `message_size` +// intended for the GoogleRtcAudioProcessing component and the corresponding +// outputs parameters based on the content. Any previous content in the output +// parameters is overwritten regardless of the content in `message`. +void GoogleRtcAudioProcessingParseSofConfigMessage( + uint8_t *message, size_t message_size, + uint8_t **google_rtc_audio_processing_config, + size_t *google_rtc_audio_processing_config_size, + int *num_capture_input_channels, int *num_capture_output_channels, + float *aec_reference_delay, float *mic_gain, + bool *google_rtc_audio_processing_config_present, + bool *num_capture_input_channels_present, + bool *num_capture_output_channels_present, + bool *aec_reference_delay_present, bool *mic_gain_present); + +#ifdef __cplusplus +} +#endif + +#endif // GOOGLE_RTC_AUDIO_PROCESSING_SOF_MESSAGE_READER_H_ diff --git a/third_party/include/nxp/eap/EAP_Includes/EAP16.h b/third_party/include/nxp/eap/EAP_Includes/EAP16.h new file mode 100644 index 000000000000..4bcee38dee12 --- /dev/null +++ b/third_party/include/nxp/eap/EAP_Includes/EAP16.h @@ -0,0 +1,1033 @@ +/* Copyright 2004-2025 NXP + * + * SPDX-License-Identifier: MIT + * This license applies ONLY to this header file EAP16.h + * + * 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. + * + */ + +/***************************************************************************************** + + $Author: beq03888 $ + $Revision: 16643 $ + $Date: 2011-10-14 09:00:36 +0200 (Fri, 14 Oct 2011) $ + +*****************************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Header file for the application layer interface of Concert Sound, Bass Enhancement */ +/* and volume management bundle. */ +/* */ +/* This files includes all definitions, types, structures and function */ +/* prototypes required by the calling layer. All other types, structures and */ +/* functions are private. */ +/* */ +/****************************************************************************************/ +/* */ +/* Note: 1 */ +/* ======= */ +/* The algorithm can execute either with separate input and output buffers or with */ +/* a common buffer, i.e. the data is processed in-place. */ +/* */ +/****************************************************************************************/ +/* */ +/* Note: 2 */ +/* ======= */ +/* Three data formats are support Stereo and Mono. The input data is */ +/* interleaved as follows: ----- */ +/* */ +/* Byte Offset Stereo Input Mono Input */ +/* =========== ============ ==================== */ +/* 0 Left Sample #1 Mono Sample #1 */ +/* 2 Right Sample #1 Mono Sample #1 */ +/* 4 Left Sample #2 Mono Sample #2 */ +/* 6 Right Sample #2 Mono Sample #2 */ +/* . . . */ +/* . . . */ +/* */ +/* For output buffer there is 3 cases : */ +/* ------ */ +/* 1) CROSSOVER is DISABLE */ +/* Byte Offset Stereo Input/Output Mono Input/Output */ +/* =========== =================== ================= */ +/* 0 Left Sample #1 Mono Sample #1 */ +/* 2 Right Sample #1 Mono Sample #1 */ +/* 4 Left Sample #2 Mono Sample #2 */ +/* 6 Right Sample #2 Mono Sample #2 */ +/* . . . */ +/* . . . */ +/* */ +/* 2) CROSSOVER is ENABLE & input/output in STEREO */ +/* pOutData[0] will be the output Low band and pOutData[1] the High band */ +/* Stereo Input pOutData[0] in stereo pOutData[1] in stereo */ +/* =================== ===================== ===================== */ +/* Left Sample #1 Left Sample LB #1 Left Sample HB #1 */ +/* Right Sample #1 Right Sample LB #1 Right Sample HB #1 */ +/* Left Sample #2 Left Sample LB #2 Left Sample HB #2 */ +/* Right Sample #2 Right Sample LB #2 Right Sample HB #2 */ +/* . . . */ +/* . . . */ +/* */ +/* 3) CROSSOVER is ENABLE & input/output in MONO */ +/* pOutData[0] will be the output Low band and pOutData[1] the High band */ +/* Mono Input pOutData[0] in mono pOutData[1] in mono */ +/* =============== ===================== ===================== */ +/* MONO Sample #1 MONO Sample LB #1 MONO Sample HB #1 */ +/* MONO Sample #2 MONO Sample LB #2 MONO Sample HB #2 */ +/* MONO Sample #3 MONO Sample LB #3 MONO Sample HB #3 */ +/* MONO Sample #4 MONO Sample LB #4 MONO Sample HB #4 */ +/* . . . */ +/* . . . */ +/* */ +/****************************************************************************************/ + +#ifndef __LVM_H__ +#define __LVM_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#ifdef ALGORITHM_CS +#define ALGORITHM_VIRTUALIZER +#endif /* ALGORITHM_CS */ + +#ifdef ALGORITHM_DBE +#define ALGORITHM_BASS +#else +#ifdef ALGORITHM_PB +#define ALGORITHM_BASS +#endif /* ALGORITHM_PB */ +#endif /* ALGORITHM_DBE */ + + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVC_Types.h" + + +/****************************************************************************************/ +/* */ +/* Definitions */ +/* */ +/****************************************************************************************/ + +/* MAXIMAL VALUE LIMIT */ +#define LVM_MAX_NUM_CHANNELS 2 /* Maximum number of interleaved input channels */ +#define MAX_INTERNAL_BLOCKSIZE 1024 /* Maximum internal block size authorized (multiple of 64)*/ +#define LVM_HEADROOM_MAX_NBANDS 5 /* Headroom management */ +#define LVM_EQNB_MAX_BANDS_NBR 10 /* EQNB Maximal band number */ +#define LVM_PSA_MAX_NUMBANDS 64 /* Maximum Number of PSA Bands*/ + +/* Memory table*/ +#define LVM_NR_MEMORY_REGIONS 4 /* Number of memory regions */ + +/* Concert Sound effect level presets */ +#ifdef ALGORITHM_VIRTUALIZER +#define LVM_CS_EFFECT_NONE 0 /* 0% effect, minimum value */ +#define LVM_CS_EFFECT_LOW 16384 /* 50% effect */ +#define LVM_CS_EFFECT_MED 24576 /* 75% effect */ +#define LVM_CS_EFFECT_HIGH 32767 /* 100% effect, maximum value */ +#endif /*end ALGORITHM_VIRTUALIZER */ + +#ifdef ALGORITHM_TE +#define LVM_TE_LOW_MIPS 32767 /* Treble enhancement 6dB Mips saving mode */ +#endif /* end ALGORITHM_TE */ + +/* Bass enhancement effect level presets */ +#ifdef ALGORITHM_BASS +#define LVM_BE_0DB 0 /* 0dB boost, no effect */ +#define LVM_BE_3DB 3 /* +3dB boost */ +#define LVM_BE_6DB 6 /* +6dB boost */ +#define LVM_BE_9DB 9 /* +9dB boost */ +#define LVM_BE_12DB 12 /* +12dB boost */ +#define LVM_BE_15DB 15 /* +15dB boost */ +#endif /* end ALGORITHM_BASS */ + +/****************************************************************************************/ +/* */ +/* Types */ +/* */ +/****************************************************************************************/ + +/* Instance handle */ +typedef void *LVM_Handle_t; + + +/* Status return values */ +typedef enum +{ + LVM_SUCCESS = 0, /* Successful return from a routine */ + LVM_ALIGNMENTERROR = 1, /* Memory alignment error */ + LVM_NULLADDRESS = 2, /* NULL allocation address */ + LVM_INVALIDNUMSAMPLES = 3, /* Invalid number of samples */ + LVM_WRONGAUDIOTIME = 4, /* Wrong time value for audio time*/ + LVM_ALGORITHMDISABLED = 5, /* Algorithm is disabled*/ + LVM_NOT_INITIALIZED = 6, /* Process function was called for a non-initialized module */ + LVM_INVALIDNXPPLATFORM = 7, /* Invalid NXP platform */ + // OUT OF RANGE HANDLE Must stay at the end of the enum + LVM_OUTOFRANGE = 8, /* Out of range control parameter (without details) */ + /* OUT OF RANGE WITH DETAILS */ + LVM_OUTOFRANGE_GENERAL_PARAMS = 9, + LVM_OUTOFRANGE_SPEAKER_TYPES = 10, + LVM_OUTOFRANGE_VIRTUALIZER_OM = 11, + LVM_OUTOFRANGE_VIRTUALIZER_TYPE = 12, + LVM_OUTOFRANGE_VIRTUALIZER_REVERB = 13, + LVM_OUTOFRANGE_CS_EFFECT = 14, + LVM_OUTOFRANGE_USER_EQNB = 15, + LVM_OUTOFRANGE_USER_EQNB_BAND_DEF = 16, + LVM_OUTOFRANGE_PRODUCT_EQNB = 17, + LVM_OUTOFRANGE_PRODUCT_EQNB_BAND_DEF = 18, + LVM_OUTOFRANGE_BE = 19, + LVM_OUTOFRANGE_PB = 20, + LVM_OUTOFRANGE_VC_LEVEL = 21, + LVM_OUTOFRANGE_VC_BALANCE = 22, + LVM_OUTOFRANGE_TE = 23, + LVM_OUTOFRANGE_LM = 24, + LVM_OUTOFRANGE_LM_SPEAKER_CUTOFF = 25, + LVM_OUTOFRANGE_AVL = 26, + LVM_OUTOFRANGE_TG_OM = 27, + LVM_OUTOFRANGE_TG = 28, + LVM_OUTOFRANGE_PSA_RATE = 29, + LVM_OUTOFRANGE_PSA_ENABLE = 30, + LVM_OUTOFRANGE_PSA_NUMBAND = 31, + LVM_OUTOFRANGE_LIMP_OM = 32, + LVM_OUTOFRANGE_LIMP_THRESHOLD = 33, + LVM_OUTOFRANGE_LIMR_OM = 34, + LVM_OUTOFRANGE_LIMR_THRESHOLD = 35, + LVM_OUTOFRANGE_LIMR_REFERENCE = 36, + LVM_OUTOFRANGE_CS_AP_MODE = 37, + LVM_OUTOFRANGE_CS_AP = 38, + LVM_OUTOFRANGE_XO_OPERATINGMODE = 39, + LVM_OUTOFRANGE_XO_CUTOFFFREQUENCY = 40, + + + LVM_RETURNSTATUS_DUMMY = LVM_MAXENUM +} LVM_ReturnStatus_en; + + +/* Buffer Management mode */ +typedef enum +{ + LVM_MANAGED_BUFFERS = 0, + LVM_UNMANAGED_BUFFERS = 1, + LVM_BUFFERS_DUMMY = LVM_MAXENUM +} LVM_BufferMode_en; + + + +/* Output device type */ +typedef enum +{ + LVM_HEADPHONES = 0, + LVM_MOBILE_SPEAKERS_SMALL = 2, + LVM_MOBILE_SPEAKERS_MEDIUM = 3, + LVM_MOBILE_SPEAKERS_LARGE = 4, + LVM_SPEAKERTYPE_MAX = LVM_MAXENUM +} LVM_OutputDeviceType_en; + +typedef enum +{ + LVM_IMXRT1050 = 1, // I.MXRT1050 : EAP running on Cortex-M7 + LVM_IMXRT1060 = 2, // I.MXRT1060 : EAP running on Cortex-M7 + LVM_IMXRT1064 = 3, // I.MXRT1064 : EAP running on Cortex-M7 + LVM_IMXRT1170 = 4, // I.MXRT1170 : EAP running on Cortex-M7 + LVM_LPC55 = 5, // LPC55 : EAP running on Cortex-M33 + LVM_IMXRT500 = 6, // I.MXRT500 : EAP running on FusionF1 + LVM_IMXRT600 = 7, // I.MXRT600 : EAP running on HIFI4 + LVM_MAX_PLATFORM = LVM_MAXENUM, +}EAP_NXPPlatform_en; + +/* Virtualizer mode selection*/ +#ifdef ALGORITHM_VIRTUALIZER +typedef enum +{ + LVM_CONCERTSOUND = 0, + LVM_VIRTUALIZERTYPE_DUMMY = LVM_MAXENUM +} LVM_VirtualizerType_en; +#endif /* ALGORITHM_VIRTUALIZER */ + +/* N-Band Equaliser operating mode */ +#if (ALGORITHM_EQNB) || (ALGORITHM_PR_EQNB) +typedef enum +{ + LVM_EQNB_OFF = 0, + LVM_EQNB_ON = 1, + LVM_EQNB_DUMMY = LVM_MAXENUM +} LVM_EQNB_Mode_en; +#endif /* ALGORITHM_EQNB || ALGORITHM_PR_EQNB*/ + +/* Filter mode control */ +typedef enum +{ + LVM_EQNB_FILTER_OFF = 0, + LVM_EQNB_FILTER_ON = 1, + LVM_EQNB_FILTER_DUMMY = LVM_MAXENUM +} LVM_EQNB_FilterMode_en; + +/* Bass Enhancement operating mode */ +#ifdef ALGORITHM_BASS +typedef enum +{ + LVM_BE_OFF = 0, + LVM_BE_ON = 1, + LVM_BE_DUMMY = LVM_MAXENUM +} LVM_BE_Mode_en; + +/* Bass Enhancement centre frequency selection control */ +typedef enum +{ + LVM_BE_CENTRE_55Hz = 0, + LVM_BE_CENTRE_66Hz = 1, + LVM_BE_CENTRE_78Hz = 2, + LVM_BE_CENTRE_90Hz = 3, + LVM_BE_CENTRE_DUMMY = LVM_MAXENUM +} LVM_BE_CentreFreq_en; + +/* Bass Enhancement HPF selection control */ +typedef enum +{ + LVM_BE_HPF_OFF = 0, + LVM_BE_HPF_ON = 1, + LVM_BE_HPF_DUMMY = LVM_MAXENUM +} LVM_BE_FilterSelect_en; + + +#endif /* ALGORITHM_BASS */ + +/* Volume Control operating mode */ +typedef enum +{ + LVM_VC_OFF = 0, + LVM_VC_ON = 1, + LVM_VC_DUMMY = LVM_MAXENUM +} LVM_VC_Mode_en; + +/* Treble Enhancement operating mode */ +#ifdef ALGORITHM_TE +typedef enum +{ + LVM_TE_OFF = 0, + LVM_TE_ON = 1, + LVM_TE_DUMMY = LVM_MAXENUM +} LVM_TE_Mode_en; +#endif /* ALGORITHM_TE */ + +/* Loudness Maximiser operating mode */ +#ifdef ALGORITHM_LM +typedef enum +{ + LVM_LM_OFF = 0, + LVM_LM_ON = 1, + LVM_LM_DUMMY = LVM_MAXENUM +}LVM_LM_Mode_en; + +/* Loudness Maximiser effect setting */ +typedef enum +{ + LVM_LM_GENTLE = 0, + LVM_LM_MEDIUM = 1, + LVM_LM_EXTREME = 2, + LVM_LM_EFFECT_DUMMY = LVM_MAXENUM +}LVM_LM_Effect_en; +#endif /* ALGORITHM_LM */ + +/* AVL operating mode */ +#ifdef ALGORITHM_AVL +typedef enum +{ + LVM_AVL_OFF = 0, + LVM_AVL_ON = 1, + LVM_AVL_DUMMY = LVM_MAXENUM +} LVM_AVL_Mode_en; +#endif /* ALGORITHM_AVL */ + +/* Headroom management operating mode */ +typedef enum +{ + LVM_HEADROOM_OFF = 0, + LVM_HEADROOM_ON = 1, + LVM_Headroom_DUMMY = LVM_MAXENUM +} LVM_Headroom_Mode_en; + +/* Tone Generator operating mode */ +#ifdef ALGORITHM_TG +typedef enum +{ + LVM_TG_OFF = 0, + LVM_TG_CONTINUOUS = 1, + LVM_TG_ONESHOT = 2, + LVM_TG_DUMMY = LVM_MAXENUM +} LVM_TG_Mode_en; + +/* Tone Generator sweep mode */ +typedef enum +{ + LVM_TG_SWEEPLIN = 0, + LVM_TG_SWEEPLOG = 1, + LVM_TG_SWEEP_DUMMY = LVM_MAXENUM +} LVM_TG_SweepMode_en; +#endif /* ALGORITHM_TG */ + +#ifdef ALGORITHM_XO +typedef enum +{ + LVM_XO_MODE_OFF = 0, + LVM_XO_MODE_ON = 1 +}LVM_XO_MODE_en; +#endif /*ALGORITHM_XO*/ + + +#ifdef ALGORITHM_PSA +typedef enum +{ + LVM_PSA_SPEED_SLOW, /* Peak decaying at slow speed */ + LVM_PSA_SPEED_MEDIUM, /* Peak decaying at medium speed */ + LVM_PSA_SPEED_FAST, /* Peak decaying at fast speed */ + LVM_PSA_SPEED_DUMMY = LVM_MAXENUM +} LVM_PSA_DecaySpeed_en; + +typedef enum +{ + LVM_PSA_OFF = 0, + LVM_PSA_ON = 1, + LVM_PSA_DUMMY = LVM_MAXENUM +} LVM_PSA_Mode_en; +#endif /* ALGORITHM_PSA */ + +#ifdef ALGORITHM_LIMP +typedef enum +{ + LVM_LIMP_OFF = 0, + LVM_LIMP_ON = 1, + LVM_LIMP_DUMMY = LVM_MAXENUM +} LVM_LIMP_Mode_en; +#endif /* ALGORITHM_LIMP */ + +#ifdef ALGORITHM_LIMR +typedef enum +{ + LVM_LIMR_OFF = 0, + LVM_LIMR_ON = 1, + LVM_LIMR_DUMMY = LVM_MAXENUM +} LVM_LIMR_Mode_en; + +typedef enum +{ + LVM_LIMR_REF_INPUT = 0, + LVM_LIMR_REF_0DBFS = 1, + LVM_LIMR_REF_DUMMY = LVM_MAXENUM +} LVM_LIMR_Reference_en; +#endif /* ALGORITHM_LIMR */ + +// Adavanced parameter mode +typedef enum +{ + LVM_AP_DEFAULT = 0, + LVM_AP_MANUAL = 1, + LVM_AP_DUMMY = LVM_MAXENUM +} LVM_AP_MODE_en; + +/****************************************************************************************/ +/* */ +/* Structures */ +/* */ +/****************************************************************************************/ + +/* Version information */ +typedef struct +{ + LVM_CHAR *pVersionNumber; /* Pointer to the version number in the format X.YY.ZZ */ + LVM_CHAR *pPlatform; /* Pointer to the library platform type */ +} LVM_VersionInfo_st; + +/* Memory table containing the region definitions */ +typedef struct +{ + LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */ +} LVM_MemTab_t; + + +/* N-Band equaliser band definition */ +typedef struct +{ + LVM_INT16 Gain; /* Band gain in dB */ + LVM_UINT16 Frequency; /* Band centre frequency in Hz */ + LVM_UINT16 QFactor; /* Band quality factor (x100) */ +} LVM_EQNB_BandDef_t; + +/* Headroom band definition */ +typedef struct +{ + LVM_UINT16 Limit_Low; /* Low frequency limit of the band in Hertz */ + LVM_UINT16 Limit_High; /* High frequency limit of the band in Hertz */ + LVM_INT16 Headroom_Offset; /* Headroom = biggest band gain - Headroom_Offset */ +} LVM_HeadroomBandDef_t; + +/* Control Parameter structure */ +typedef struct +{ + /* General parameters */ + LVM_Mode_en OperatingMode; /* Bundle operating mode On/Bypass */ + LVM_Fs_en SampleRate; /* Sample rate */ + LVM_Format_en SourceFormat; /* Input data format */ + LVM_OutputDeviceType_en SpeakerType; /* Output device type */ + LVM_SpeakerType_en SpeakerTypeInternal; /* Device speaker type, mono or stereo */ + +#ifdef ALGORITHM_CS + /* Concert Sound Virtualizer parameters*/ + LVM_Mode_en VirtualizerOperatingMode; /* Virtualizer operating mode On/Off */ + LVM_VirtualizerType_en VirtualizerType; /* Virtualizer type: ConcertSound, CinemaSound Music or CinemaSound Movie */ + LVM_UINT16 VirtualizerReverbLevel; /* Virtualizer reverb level in % */ + LVM_INT16 CS_EffectLevel; /* Concert Sound effect level */ +#endif /* ALGORITHM_CS */ + +#ifdef ALGORITHM_EQNB + /* N-Band Equaliser parameters */ + LVM_EQNB_Mode_en EQNB_OperatingMode; /* N-Band Equaliser operating mode */ + LVM_EQNB_FilterMode_en EQNB_LPF_Mode; /* Low pass filter */ + LVM_INT16 EQNB_LPF_CornerFreq; + LVM_EQNB_FilterMode_en EQNB_HPF_Mode; /* High pass filter */ + LVM_INT16 EQNB_HPF_CornerFreq; + LVM_UINT16 EQNB_NBands; /* Number of bands */ + LVM_EQNB_BandDef_t *pEQNB_BandDefinition; /* Pointer to equaliser definitions */ +#endif /* ALGORITHM_EQNB */ + +#ifdef ALGORITHM_PR_EQNB + /* N-Band Equaliser parameters */ + LVM_EQNB_Mode_en PR_EQNB_OperatingMode; /* N-Band Equaliser operating mode */ + LVM_EQNB_FilterMode_en PR_EQNB_LPF_Mode; /* Low pass filter */ + LVM_INT16 PR_EQNB_LPF_CornerFreq; + LVM_EQNB_FilterMode_en PR_EQNB_HPF_Mode; /* High pass filter */ + LVM_INT16 PR_EQNB_HPF_CornerFreq; + LVM_UINT16 PR_EQNB_NBands; /* Number of bands */ + LVM_EQNB_BandDef_t *pPR_EQNB_BandDefinition; /* Pointer to equaliser definitions */ +#endif /* ALGORITHM_PR_EQNB */ + +#ifdef ALGORITHM_DBE + /* Bass Enhancement parameters */ + LVM_BE_Mode_en BE_OperatingMode; /* Bass Enhancement operating mode */ + LVM_INT16 BE_EffectLevel; /* Bass Enhancement effect level */ + LVM_BE_CentreFreq_en BE_CentreFreq; /* Bass Enhancement centre frequency */ + LVM_BE_FilterSelect_en BE_HPF; /* Bass Enhancement high pass filter selector */ + +#endif /* ALGORITHM_DBE */ +#ifdef ALGORITHM_PB + /* Bass Enhancement parameters */ + LVM_BE_Mode_en BE_OperatingMode; /* Bass Enhancement operating mode */ + LVM_INT16 BE_EffectLevel; /* Bass Enhancement effect level */ + LVM_BE_CentreFreq_en BE_CentreFreq; /* Bass Enhancement centre frequency */ + LVM_BE_FilterSelect_en BE_HPF; /* Bass Enhancement high pass filter selector */ + +#endif /* ALGORITHM_PB */ + /* Volume Control parameters */ + LVM_INT16 VC_EffectLevel; /* Volume Control setting in dBs */ + LVM_INT16 VC_Balance; /* Left Right Balance control in dB (-96 to 96 dB), -ve values reduce */ + +#ifdef ALGORITHM_TE + /* Treble Enhancement parameters */ + LVM_TE_Mode_en TE_OperatingMode; /* Treble Enhancement On/Off */ + LVM_INT16 TE_EffectLevel; /* Treble Enhancement gain dBs */ + +#endif /* ALGORITHM_TE */ +#ifdef ALGORITHM_LM + /* Loudness Maximiser parameters */ + LVM_LM_Mode_en LM_OperatingMode; /* Loudness Maximiser operating mode */ + LVM_LM_Effect_en LM_EffectLevel; /* Loudness Maximiser effect level */ + LVM_UINT16 LM_Attenuation; /* Loudness Maximiser output attenuation */ + LVM_UINT16 LM_CompressorGain; /* Loudness Maximiser output compressor gain */ + LVM_UINT16 LM_SpeakerCutOff; /* Loudness Maximiser speaker cut off frequency */ + +#endif /* ALGORITHM_LM */ + +#ifdef ALGORITHM_AVL + /* AVL parameters */ + LVM_AVL_Mode_en AVL_OperatingMode; /* AVL operating mode */ + +#endif /* ALGORITHM_AVL */ + +#ifdef ALGORITHM_TG + /* Tone Generator parameters */ + LVM_TG_Mode_en TG_OperatingMode; /* Tone generator mode */ + LVM_TG_SweepMode_en TG_SweepMode; /* Log or linear sweep */ + LVM_UINT16 TG_StartFrequency; /* Sweep start frequency in Hz */ + LVM_INT16 TG_StartAmplitude; /* Sweep start amplitude in dBr */ + LVM_UINT16 TG_StopFrequency; /* Sweep stop frequency in Hz */ + LVM_INT16 TG_StopAmplitude; /* Sweep stop amplitude in dBr */ + LVM_UINT16 TG_SweepDuration; /* Sweep duration in seconds, 0 for infinite duration tone */ + LVM_Callback pTG_CallBack; /* End of sweep callback */ + LVM_INT16 TG_CallBackID; /* Callback ID*/ + void *pTGAppMemSpace; /* Application instance handle or memory area */ +#endif /* ALGORITHM_TG */ + +#ifdef ALGORITHM_PSA + /* General Control */ + LVM_PSA_Mode_en PSA_Enable; + + /* Spectrum Analyzer parameters */ + LVM_PSA_DecaySpeed_en PSA_PeakDecayRate; /* Peak value decay rate*/ + LVM_UINT16 PSA_NumBands; /* Number of Bands*/ +#endif /* ALGORITHM_PSA */ + +#ifdef ALGORITHM_LIMP + LVM_LIMP_Mode_en LIMP_OperatingMode; /* LIMP operating mode */ + LVM_INT16 LIMP_Threshold; /* LIMP threshold in dB */ +#endif /* ALGORITHM_LIMP */ + +#ifdef ALGORITHM_LIMR + LVM_LIMR_Mode_en LIMR_OperatingMode; /* LIMR operating mode */ + LVM_LIMR_Reference_en LIMR_Reference; /* LIMR reference input */ + LVM_INT16 LIMR_Threshold; /* LIMR threshold in dB */ +#endif /* ALGORITHM_LIMR */ + +#ifdef ALGORITHM_CS + LVM_AP_MODE_en CS_AP_Mode; /* concert sound advanced paramameter mode */ + LVM_INT16 CS_AP_MidGain; /* MidChannelGain */ + LVM_UINT16 CS_AP_MidCornerFreq; /* Shelving Filter Corner Frequency */ + LVM_UINT16 CS_AP_SideHighPassCutoff; /* SideBoost HighPassFilter Corner Frequency */ + LVM_UINT16 CS_AP_SideLowPassCutoff; /* SideBoost LowPassFilter Corner Frequency */ + LVM_INT16 CS_AP_SideGain; /* Side Channel Gain */ +#endif + +#ifdef ALGORITHM_XO + LVM_Mode_en XO_OperatingMode; /* Crossover operating mode*/ + LVM_UINT16 XO_cutoffFrequency; /* Crossover cut-off frequency*/ + +#endif/*ALGORITHM_XO*/ +} LVM_ControlParams_t; + + +/* Instance Parameter structure */ +typedef struct +{ + /* General */ + LVM_BufferMode_en BufferMode; /* Buffer management mode */ + LVM_UINT16 MaxBlockSize; /* Maximum processing block size */ + + /* N-Band Equaliser */ + LVM_UINT16 EQNB_NumBands; /* Maximum number of User equaliser bands */ + LVM_UINT16 PR_EQNB_NumBands; /* Maximum number of Product equaliser bands */ + EAP_NXPPlatform_en Platform; /* NXP Platform where EAP is playing on (LVM_IMXRT1050,LVM_IMXRT1060, LVM_IMXRT1064, LVM_IMXRT1170, LVM_LPC55, LVM_IMXRT500, LVM_IMXRT600)*/ + + +#ifdef ALGORITHM_PSA + /* PSA */ + LVM_UINT16 PSA_HistorySize; /* PSA History size in ms: 200 to 5000 */ + LVM_UINT16 PSA_MaxBands; /* Maximum number of bands: 6 to 64 */ + LVM_UINT16 PSA_SpectrumUpdateRate; /* Spectrum update rate : 10 to 25*/ + LVM_PSA_Mode_en PSA_Included; /* Controls the instance memory allocation for PSA: ON/OFF */ +#endif /* ALGORITHM_PSA */ +} LVM_InstParams_t; + + +/* Headroom management parameter structure */ +typedef struct +{ + LVM_Headroom_Mode_en Headroom_OperatingMode; /* Headroom Control On/Off */ + LVM_HeadroomBandDef_t *pHeadroomDefinition; /* Pointer to headroom bands definition */ + LVM_UINT16 NHeadroomBands; /* Number of headroom bands */ +} LVM_HeadroomParams_t; + + +/****************************************************************************************/ +/* */ +/* Function Prototypes */ +/* */ +/****************************************************************************************/ + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetVersionInfo */ +/* */ +/* DESCRIPTION: */ +/* This function is used to retrieve information about the library's version. */ +/* */ +/* PARAMETERS: */ +/* pVersion Pointer to an empty version info structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS when pVersion is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st *pVersion); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetMemoryTable */ +/* */ +/* DESCRIPTION: */ +/* This function is used for memory allocation and free. It can be called in */ +/* two ways: */ +/* */ +/* hInstance = NULL Returns the memory requirements */ +/* hInstance = Instance handle Returns the memory requirements and */ +/* allocated base addresses for the instance */ +/* */ +/* When this function is called for memory allocation (hInstance=NULL) the memory */ +/* base address pointers are NULL on return. */ +/* */ +/* When the function is called for free (hInstance = Instance Handle) the memory */ +/* table returns the allocated memory and base addresses used during initialisation. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pMemoryTable Pointer to an empty memory definition table */ +/* pInstParams Pointer to the instance parameters */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When one of pMemoryTable or pInstParams is NULL */ +/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t hInstance, + LVM_MemTab_t *pMemoryTable, + LVM_InstParams_t *pInstParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetInstanceHandle */ +/* */ +/* DESCRIPTION: */ +/* This function is used to create a bundle instance. It returns the created instance */ +/* handle through phInstance. All parameters are set to their default, inactive state. */ +/* */ +/* PARAMETERS: */ +/* phInstance pointer to the instance handle */ +/* pMemoryTable Pointer to the memory definition table */ +/* pInstParams Pointer to the instance parameters */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Initialisation succeeded */ +/* LVM_ALIGNMENTERROR Instance or scratch memory on incorrect alignment */ +/* LVM_NULLADDRESS Instance or scratch memory has a NULL pointer */ +/* */ +/* NOTES: */ +/* 1. This function must not be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t *phInstance, + LVM_MemTab_t *pMemoryTable, + LVM_InstParams_t *pInstParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_ClearAudioBuffers */ +/* */ +/* DESCRIPTION: */ +/* This function is used to clear the internal audio buffers of the bundle. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Buffers Cleared */ +/* LVM_NULLADDRESS Instance is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t hInstance); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetControlParameters */ +/* */ +/* DESCRIPTION: */ +/* Request the LifeVibes module parameters. The current parameter set is returned */ +/* via the parameter pointer. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to an empty parameter structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS when any of hInstance or pParams is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t hInstance, + LVM_ControlParams_t *pParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_SetControlParameters */ +/* */ +/* DESCRIPTION: */ +/* Sets or changes the LifeVibes module parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to a parameter structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When hInstance, pParams or any control pointers are NULL */ +/* LVM_OUTOFRANGE When any of the control parameters are out of range */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance, + LVM_ControlParams_t *pParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_Process */ +/* */ +/* DESCRIPTION: */ +/* Process function for the LifeVibes module. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pInData Pointer to the input data */ +/* pOutData Pointer to the output data */ +/* NumSamples Number of samples in the input buffer */ +/* AudioTime Audio Time of the current input data in milli-seconds */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_INVALIDNUMSAMPLES When the NumSamples is not a valied multiple in unmanaged */ +/* buffer mode */ +/* LVM_ALIGNMENTERROR When either the input our output buffers are not 32-bit */ +/* aligned in unmanaged mode */ +/* LVM_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */ +/* */ +/* NOTES: */ +/* 1. The input and output buffers must be 32-bit aligned */ +/* 2. Number of samples is defined as follows: */ +/* MONO the number of samples in the block */ +/* MONOINSTEREO the number of sample pairs in the block */ +/* STEREO the number of sample pairs in the block */ +/* */ +/* 3. If Crossover Disable, pOutData[0] MUST be initialize as a non-null pointer */ +/* 4. If Crossover Enable, pOutData[0] & pOutData[1] MUST be initialize as */ +/* a non-null pointer */ +/* */ +/* */ +/* */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance, + const LVM_INT16 *pInData, + LVM_INT16 **pOutData, + LVM_UINT16 NumSamples, + LVM_UINT32 AudioTime); + + +#ifdef ALGORITHM_AVL +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetAVLGain */ +/* */ +/* DESCRIPTION: */ +/* This function is used to retrieve the AVL last generated gain in Q16.15 */ +/* linear values. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pAVL_Gain Pointer to the gain */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When hInstance or pAVL_Gain are null addresses */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetAVLGain( LVM_Handle_t hInstance, + LVM_INT32 *pAVL_Gain); + + +#endif /* ALGORITHM_AVL */ + +#ifdef ALGORITHM_EQNB +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_SetHeadroomParams */ +/* */ +/* DESCRIPTION: */ +/* This function is used to set the automatic headroom management parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pHeadroomParams Pointer to headroom parameter structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_SetHeadroomParams( LVM_Handle_t hInstance, + LVM_HeadroomParams_t *pHeadroomParams); + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetHeadroomParams */ +/* */ +/* DESCRIPTION: */ +/* This function is used to get the automatic headroom management parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pHeadroomParams Pointer to headroom parameter structure (output) */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When hInstance or pHeadroomParams are NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetHeadroomParams( LVM_Handle_t hInstance, + LVM_HeadroomParams_t *pHeadroomParams); +#endif /* ALGORITHM_EQNB */ + +#ifdef ALGORITHM_PSA +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetSpectrum */ +/* */ +/* DESCRIPTION: */ +/* This function is used to retrieve Spectral information at a given Audio time */ +/* for display usage */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pCurrentPeaks Pointer to location where currents peaks are to be saved */ +/* pPastPeaks Pointer to location where past peaks are to be saved */ +/* pCentreFreqs Pointer to location where centre frequency of each band is */ +/* to be saved */ +/* AudioTime Audio time at which the spectral information is needed */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS If any of input addresses are NULL */ +/* LVM_WRONGAUDIOTIME Failure due to audio time error */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetSpectrum( LVM_Handle_t hInstance, + LVM_INT8 *pCurrentPeaks, + LVM_INT8 *pPastPeaks, + LVM_UINT16 *pCentreFreqs, + LVM_UINT32 AudioTime); + + +#endif /* ALGORITHM_PSA */ + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_SetVolumeNoSmoothing */ +/* */ +/* DESCRIPTION: */ +/* This function is used to set output volume without any smoothing */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pParams Control Parameters, only volume value is used here */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS If any of input addresses are NULL */ +/* LVM_OUTOFRANGE When any of the control parameters are out of range */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t hInstance, + LVM_ControlParams_t *pParams); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LVM_H__ */ + diff --git a/third_party/include/nxp/eap/EAP_Includes/EAP32.h b/third_party/include/nxp/eap/EAP_Includes/EAP32.h new file mode 100644 index 000000000000..d69a335405a8 --- /dev/null +++ b/third_party/include/nxp/eap/EAP_Includes/EAP32.h @@ -0,0 +1,1016 @@ +/* Copyright 2004-2025 NXP + * + * SPDX-License-Identifier: MIT + * This license applies ONLY to this header file EAP32.h + * + * 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. + * + */ + +/****************************************************************************************/ +/* */ +/* Header file for the application layer interface of Concert Sound, Bass Enhancement */ +/* and volume management bundle. */ +/* */ +/* This files includes all definitions, types, structures and function */ +/* prototypes required by the calling layer. All other types, structures and */ +/* functions are private. */ +/* */ +/****************************************************************************************/ +/* */ +/* Note: 1 */ +/* ======= */ +/* The algorithm can execute either with separate input and output buffers or with */ +/* a common buffer, i.e. the data is processed in-place. */ +/* */ +/****************************************************************************************/ +/* */ +/* Note: 2 */ +/* ======= */ +/* Three data formats are support Stereo,Mono-In-Stereo and Mono. The data is */ +/* interleaved as follows: */ +/* */ +/* Byte Offset Stereo Input Mono Input */ +/* =========== ============ ==================== */ +/* 0 Left Sample #1 Mono Sample #1 */ +/* 2 Right Sample #1 Mono Sample #1 */ +/* 4 Left Sample #2 Mono Sample #2 */ +/* 6 Right Sample #2 Mono Sample #2 */ +/* . . . */ +/* . . . */ +/* */ +/* For output buffer there is 3 cases : */ +/* ------ */ +/* 1) CROSSOVER is DISABLE */ +/* Byte Offset Stereo Input/Output Mono Input/Output */ +/* =========== =================== ================= */ +/* 0 Left Sample #1 Mono Sample #1 */ +/* 2 Right Sample #1 Mono Sample #1 */ +/* 4 Left Sample #2 Mono Sample #2 */ +/* 6 Right Sample #2 Mono Sample #2 */ +/* . . . */ +/* . . . */ +/* */ +/* 2) CROSSOVER is ENABLE & input/output in STEREO */ +/* pOutData[0] will be the output Low band and pOutData[1] the High band */ +/* Stereo Input pOutData[0] in stereo pOutData[1] in stereo */ +/* =================== ===================== ===================== */ +/* Left Sample #1 Left Sample LB #1 Left Sample HB #1 */ +/* Right Sample #1 Right Sample LB #1 Right Sample HB #1 */ +/* Left Sample #2 Left Sample LB #2 Left Sample HB #2 */ +/* Right Sample #2 Right Sample LB #2 Right Sample HB #2 */ +/* . . . */ +/* . . . */ +/* */ +/* 3) CROSSOVER is ENABLE & input/output in MONO */ +/* pOutData[0] will be the output Low band and pOutData[1] the High band */ +/* Mono Input pOutData[0] in mono pOutData[1] in mono */ +/* =============== ===================== ===================== */ +/* MONO Sample #1 MONO Sample LB #1 MONO Sample HB #1 */ +/* MONO Sample #2 MONO Sample LB #2 MONO Sample HB #2 */ +/* MONO Sample #3 MONO Sample LB #3 MONO Sample HB #3 */ +/* MONO Sample #4 MONO Sample LB #4 MONO Sample HB #4 */ +/* . . . */ +/* . . . */ +/* */ +/****************************************************************************************/ + +#ifndef __LVM_H__ +#define __LVM_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#ifdef ALGORITHM_CS +#define ALGORITHM_VIRTUALIZER +#endif /* ALGORITHM_CS */ + +#ifdef ALGORITHM_DBE +#define ALGORITHM_BASS +#else +#ifdef ALGORITHM_PB +#define ALGORITHM_BASS +#endif /* ALGORITHM_PB */ +#endif /* ALGORITHM_DBE */ + + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVC_Types.h" + + +/****************************************************************************************/ +/* */ +/* Definitions */ +/* */ +/****************************************************************************************/ + +/* MAXIMAL VALUE LIMIT */ +#define LVM_MAX_NUM_CHANNELS 2 /* Maximum number of interleaved input channels */ +#define MAX_INTERNAL_BLOCKSIZE 1024 /* Maximum internal block size authorized (multiple of 64)*/ +#define LVM_HEADROOM_MAX_NBANDS 5 /* Headroom management */ +#define LVM_EQNB_MAX_BANDS_NBR 10 /* EQNB Maximal band number */ +#define LVM_PSA_MAX_NUMBANDS 64 /* Maximum Number of PSA Bands*/ + +/* Memory table*/ +#define LVM_NR_MEMORY_REGIONS 4 /* Number of memory regions */ + +/* Concert Sound effect level presets */ +#ifdef ALGORITHM_VIRTUALIZER +#define LVM_CS_EFFECT_NONE 0 /* 0% effect, minimum value */ +#define LVM_CS_EFFECT_LOW 16384 /* 50% effect */ +#define LVM_CS_EFFECT_MED 24576 /* 75% effect */ +#define LVM_CS_EFFECT_HIGH 32767 /* 100% effect, maximum value */ +#endif /*end ALGORITHM_VIRTUALIZER */ + +#ifdef ALGORITHM_TE +#define LVM_TE_LOW_MIPS 32767 /* Treble enhancement 6dB Mips saving mode */ +#endif /* end ALGORITHM_TE */ + +/* Bass enhancement effect level presets */ +#ifdef ALGORITHM_BASS +#define LVM_BE_0DB 0 /* 0dB boost, no effect */ +#define LVM_BE_3DB 3 /* +3dB boost */ +#define LVM_BE_6DB 6 /* +6dB boost */ +#define LVM_BE_9DB 9 /* +9dB boost */ +#define LVM_BE_12DB 12 /* +12dB boost */ +#define LVM_BE_15DB 15 /* +15dB boost */ +#endif /* end ALGORITHM_BASS */ + +/****************************************************************************************/ +/* */ +/* Types */ +/* */ +/****************************************************************************************/ + +/* Instance handle */ +typedef void *LVM_Handle_t; + + +/* Status return values */ +typedef enum +{ + LVM_SUCCESS = 0, /* Successful return from a routine */ + LVM_ALIGNMENTERROR = 1, /* Memory alignment error */ + LVM_NULLADDRESS = 2, /* NULL allocation address */ + LVM_INVALIDNUMSAMPLES = 3, /* Invalid number of samples */ + LVM_WRONGAUDIOTIME = 4, /* Wrong time value for audio time*/ + LVM_ALGORITHMDISABLED = 5, /* Algorithm is disabled*/ + LVM_NOT_INITIALIZED = 6, /* Process function was called for a non-initialized module */ + LVM_INVALIDNXPPLATFORM = 7, /* Invalid NXP platform */ + // OUT OF RANGE HANDLE Must stay at the end of the enum + LVM_OUTOFRANGE = 8, /* Out of range control parameter (without details) */ + /* OUT OF RANGE WITH DETAILS */ + LVM_OUTOFRANGE_GENERAL_PARAMS = 9, + LVM_OUTOFRANGE_SPEAKER_TYPES = 10, + LVM_OUTOFRANGE_VIRTUALIZER_OM = 11, + LVM_OUTOFRANGE_VIRTUALIZER_TYPE = 12, + LVM_OUTOFRANGE_VIRTUALIZER_REVERB = 13, + LVM_OUTOFRANGE_CS_EFFECT = 14, + LVM_OUTOFRANGE_USER_EQNB = 15, + LVM_OUTOFRANGE_USER_EQNB_BAND_DEF = 16, + LVM_OUTOFRANGE_PRODUCT_EQNB = 17, + LVM_OUTOFRANGE_PRODUCT_EQNB_BAND_DEF = 18, + LVM_OUTOFRANGE_BE = 19, + LVM_OUTOFRANGE_PB = 20, + LVM_OUTOFRANGE_VC_LEVEL = 21, + LVM_OUTOFRANGE_VC_BALANCE = 22, + LVM_OUTOFRANGE_TE = 23, + LVM_OUTOFRANGE_LM = 24, + LVM_OUTOFRANGE_LM_SPEAKER_CUTOFF = 25, + LVM_OUTOFRANGE_AVL = 26, + LVM_OUTOFRANGE_TG_OM = 27, + LVM_OUTOFRANGE_TG = 28, + LVM_OUTOFRANGE_PSA_RATE = 29, + LVM_OUTOFRANGE_PSA_ENABLE = 30, + LVM_OUTOFRANGE_PSA_NUMBAND = 31, + LVM_OUTOFRANGE_LIMP_OM = 32, + LVM_OUTOFRANGE_LIMP_THRESHOLD = 33, + LVM_OUTOFRANGE_LIMR_OM = 34, + LVM_OUTOFRANGE_LIMR_THRESHOLD = 35, + LVM_OUTOFRANGE_LIMR_REFERENCE = 36, + LVM_OUTOFRANGE_CS_AP_MODE = 37, + LVM_OUTOFRANGE_CS_AP = 38, + LVM_OUTOFRANGE_XO_OPERATINGMODE = 39, + LVM_OUTOFRANGE_XO_CUTOFFFREQUENCY = 40, + LVM_OUTOFRANGE_FBSP_OPERATINGMODE = 41, + + + LVM_RETURNSTATUS_DUMMY = LVM_MAXENUM +} LVM_ReturnStatus_en; + + +/* Buffer Management mode */ +typedef enum +{ + LVM_MANAGED_BUFFERS = 0, + LVM_UNMANAGED_BUFFERS = 1, + LVM_BUFFERS_DUMMY = LVM_MAXENUM +} LVM_BufferMode_en; + + + +/* Output device type */ +typedef enum +{ + LVM_HEADPHONES = 0, + LVM_MOBILE_SPEAKERS_SMALL = 2, + LVM_MOBILE_SPEAKERS_MEDIUM = 3, + LVM_MOBILE_SPEAKERS_LARGE = 4, + LVM_SPEAKERTYPE_MAX = LVM_MAXENUM +} LVM_OutputDeviceType_en; +typedef enum +{ + LVM_IMXRT1050 = 1, // I.MXRT1050 : EAP running on Cortex-M7 + LVM_IMXRT1060 = 2, // I.MXRT1060 : EAP running on Cortex-M7 + LVM_IMXRT1064 = 3, // I.MXRT1064 : EAP running on Cortex-M7 + LVM_IMXRT1170 = 4, // I.MXRT1170 : EAP running on Cortex-M7 + LVM_LPC55 = 5, // LPC55 : EAP running on Cortex-M33 + LVM_IMXRT500 = 6, // I.MXRT500 : EAP running on FusionF1 + LVM_IMXRT600 = 7, // I.MXRT600 : EAP running on HIFI4 + LVM_MAX_PLATFORM = LVM_MAXENUM, +}EAP_NXPPlatform_en; +/* Virtualizer mode selection*/ +#ifdef ALGORITHM_VIRTUALIZER +typedef enum +{ + LVM_CONCERTSOUND = 0, + LVM_VIRTUALIZERTYPE_DUMMY = LVM_MAXENUM +} LVM_VirtualizerType_en; +#endif /* ALGORITHM_VIRTUALIZER */ + +/* N-Band Equaliser operating mode */ +#if defined (ALGORITHM_EQNB) || defined (ALGORITHM_PR_EQNB) +typedef enum +{ LVM_EQNB_OFF = 0, + LVM_EQNB_ON = 1, + LVM_EQNB_DUMMY = LVM_MAXENUM +} LVM_EQNB_Mode_en; +#endif /* ALGORITHM_EQNB || ALGORITHM_PR_EQNB*/ + +/* Filter mode control */ +typedef enum +{ + LVM_EQNB_FILTER_OFF = 0, + LVM_EQNB_FILTER_ON = 1, + LVM_EQNB_FILTER_DUMMY = LVM_MAXENUM +} LVM_EQNB_FilterMode_en; + +/* Bass Enhancement operating mode */ +#ifdef ALGORITHM_BASS +typedef enum +{ + LVM_BE_OFF = 0, + LVM_BE_ON = 1, + LVM_BE_DUMMY = LVM_MAXENUM +} LVM_BE_Mode_en; + +/* Bass Enhancement centre frequency selection control */ +typedef enum +{ + LVM_BE_CENTRE_55Hz = 0, + LVM_BE_CENTRE_66Hz = 1, + LVM_BE_CENTRE_78Hz = 2, + LVM_BE_CENTRE_90Hz = 3, + LVM_BE_CENTRE_DUMMY = LVM_MAXENUM +} LVM_BE_CentreFreq_en; + +/* Bass Enhancement HPF selection control */ +typedef enum +{ + LVM_BE_HPF_OFF = 0, + LVM_BE_HPF_ON = 1, + LVM_BE_HPF_DUMMY = LVM_MAXENUM +} LVM_BE_FilterSelect_en; + + +#endif /* ALGORITHM_BASS */ + +/* Volume Control operating mode */ +typedef enum +{ + LVM_VC_OFF = 0, + LVM_VC_ON = 1, + LVM_VC_DUMMY = LVM_MAXENUM +} LVM_VC_Mode_en; + +/* Treble Enhancement operating mode */ +#ifdef ALGORITHM_TE +typedef enum +{ + LVM_TE_OFF = 0, + LVM_TE_ON = 1, + LVM_TE_DUMMY = LVM_MAXENUM +} LVM_TE_Mode_en; +#endif /* ALGORITHM_TE */ + +/* Loudness Maximiser operating mode */ +#ifdef ALGORITHM_LM +typedef enum +{ + LVM_LM_OFF = 0, + LVM_LM_ON = 1, + LVM_LM_DUMMY = LVM_MAXENUM +}LVM_LM_Mode_en; + +/* Loudness Maximiser effect setting */ +typedef enum +{ + LVM_LM_GENTLE = 0, + LVM_LM_MEDIUM = 1, + LVM_LM_EXTREME = 2, + LVM_LM_EFFECT_DUMMY = LVM_MAXENUM +}LVM_LM_Effect_en; +#endif /* ALGORITHM_LM */ + +/* AVL operating mode */ +#ifdef ALGORITHM_AVL +typedef enum +{ + LVM_AVL_OFF = 0, + LVM_AVL_ON = 1, + LVM_AVL_DUMMY = LVM_MAXENUM +} LVM_AVL_Mode_en; +#endif /* ALGORITHM_AVL */ + +/* Headroom management operating mode */ +typedef enum +{ + LVM_HEADROOM_OFF = 0, + LVM_HEADROOM_ON = 1, + LVM_Headroom_DUMMY = LVM_MAXENUM +} LVM_Headroom_Mode_en; + +/* Tone Generator operating mode */ +#ifdef ALGORITHM_TG +typedef enum +{ + LVM_TG_OFF = 0, + LVM_TG_CONTINUOUS = 1, + LVM_TG_ONESHOT = 2, + LVM_TG_DUMMY = LVM_MAXENUM +} LVM_TG_Mode_en; + +/* Tone Generator sweep mode */ +typedef enum +{ + LVM_TG_SWEEPLIN = 0, + LVM_TG_SWEEPLOG = 1, + LVM_TG_SWEEP_DUMMY = LVM_MAXENUM +} LVM_TG_SweepMode_en; +#endif /* ALGORITHM_TG */ + +#ifdef ALGORITHM_XO +typedef enum +{ + LVM_XO_MODE_OFF = 0, + LVM_XO_MODE_ON = 1 +}LVM_XO_MODE_en; +#endif /*ALGORITHM_XO*/ + + +#ifdef ALGORITHM_PSA +typedef enum +{ + LVM_PSA_SPEED_SLOW, /* Peak decaying at slow speed */ + LVM_PSA_SPEED_MEDIUM, /* Peak decaying at medium speed */ + LVM_PSA_SPEED_FAST, /* Peak decaying at fast speed */ + LVM_PSA_SPEED_DUMMY = LVM_MAXENUM +} LVM_PSA_DecaySpeed_en; + +typedef enum +{ + LVM_PSA_OFF = 0, + LVM_PSA_ON = 1, + LVM_PSA_DUMMY = LVM_MAXENUM +} LVM_PSA_Mode_en; +#endif /* ALGORITHM_PSA */ + +#ifdef ALGORITHM_LIMP +typedef enum +{ + LVM_LIMP_OFF = 0, + LVM_LIMP_ON = 1, + LVM_LIMP_DUMMY = LVM_MAXENUM +} LVM_LIMP_Mode_en; +#endif /* ALGORITHM_LIMP */ + +#ifdef ALGORITHM_LIMR +typedef enum +{ + LVM_LIMR_OFF = 0, + LVM_LIMR_ON = 1, + LVM_LIMR_DUMMY = LVM_MAXENUM +} LVM_LIMR_Mode_en; + +typedef enum +{ + LVM_LIMR_REF_INPUT = 0, + LVM_LIMR_REF_0DBFS = 1, + LVM_LIMR_REF_DUMMY = LVM_MAXENUM +} LVM_LIMR_Reference_en; +#endif /* ALGORITHM_LIMR */ + +// Adavanced parameter mode +typedef enum +{ + LVM_AP_DEFAULT = 0, + LVM_AP_MANUAL = 1, + LVM_AP_DUMMY = LVM_MAXENUM +} LVM_AP_MODE_en; + +/****************************************************************************************/ +/* */ +/* Structures */ +/* */ +/****************************************************************************************/ + +/* Version information */ +typedef struct +{ + LVM_CHAR *pVersionNumber; /* Pointer to the version number in the format X.YY.ZZ */ + LVM_CHAR *pPlatform; /* Pointer to the library platform type */ +} LVM_VersionInfo_st; + +/* Memory table containing the region definitions */ +typedef struct +{ + LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */ +} LVM_MemTab_t; + + +/* N-Band equaliser band definition */ +typedef struct +{ + LVM_INT16 Gain; /* Band gain in dB */ + LVM_UINT16 Frequency; /* Band centre frequency in Hz */ + LVM_UINT16 QFactor; /* Band quality factor (x100) */ +} LVM_EQNB_BandDef_t; + +/* Headroom band definition */ +typedef struct +{ + LVM_UINT16 Limit_Low; /* Low frequency limit of the band in Hertz */ + LVM_UINT16 Limit_High; /* High frequency limit of the band in Hertz */ + LVM_INT16 Headroom_Offset; /* Headroom = biggest band gain - Headroom_Offset */ +} LVM_HeadroomBandDef_t; + +/* Control Parameter structure */ +typedef struct +{ + /* General parameters */ + LVM_Mode_en OperatingMode; /* Bundle operating mode On/Bypass */ + LVM_Fs_en SampleRate; /* Sample rate */ + LVM_Format_en SourceFormat; /* Input data format */ + LVM_OutputDeviceType_en SpeakerType; /* Output device type */ + LVM_SpeakerType_en SpeakerTypeInternal; /* Device speaker type, mono or stereo */ + +#ifdef ALGORITHM_CS + /* Concert Sound Virtualizer parameters*/ + LVM_Mode_en VirtualizerOperatingMode; /* Virtualizer operating mode On/Off */ + LVM_VirtualizerType_en VirtualizerType; /* Virtualizer type: ConcertSound, CinemaSound Music or CinemaSound Movie */ + LVM_UINT16 VirtualizerReverbLevel; /* Virtualizer reverb level in % */ + LVM_INT16 CS_EffectLevel; /* Concert Sound effect level */ +#endif /* ALGORITHM_CS */ + +#ifdef ALGORITHM_EQNB + /* N-Band Equaliser parameters */ + LVM_EQNB_Mode_en EQNB_OperatingMode; /* N-Band Equaliser operating mode */ + LVM_EQNB_FilterMode_en EQNB_LPF_Mode; /* Low pass filter */ + LVM_INT16 EQNB_LPF_CornerFreq; + LVM_EQNB_FilterMode_en EQNB_HPF_Mode; /* High pass filter */ + LVM_INT16 EQNB_HPF_CornerFreq; + LVM_UINT16 EQNB_NBands; /* Number of bands */ + LVM_EQNB_BandDef_t *pEQNB_BandDefinition; /* Pointer to equaliser definitions */ +#endif /* ALGORITHM_EQNB */ + +#ifdef ALGORITHM_PR_EQNB + /* N-Band Equaliser parameters */ + LVM_EQNB_Mode_en PR_EQNB_OperatingMode; /* N-Band Equaliser operating mode */ + LVM_EQNB_FilterMode_en PR_EQNB_LPF_Mode; /* Low pass filter */ + LVM_INT16 PR_EQNB_LPF_CornerFreq; + LVM_EQNB_FilterMode_en PR_EQNB_HPF_Mode; /* High pass filter */ + LVM_INT16 PR_EQNB_HPF_CornerFreq; + LVM_UINT16 PR_EQNB_NBands; /* Number of bands */ + LVM_EQNB_BandDef_t *pPR_EQNB_BandDefinition; /* Pointer to equaliser definitions */ +#endif /* ALGORITHM_PR_EQNB */ + +#ifdef ALGORITHM_DBE + /* Bass Enhancement parameters */ + LVM_BE_Mode_en BE_OperatingMode; /* Bass Enhancement operating mode */ + LVM_INT16 BE_EffectLevel; /* Bass Enhancement effect level */ + LVM_BE_CentreFreq_en BE_CentreFreq; /* Bass Enhancement centre frequency */ + LVM_BE_FilterSelect_en BE_HPF; /* Bass Enhancement high pass filter selector */ + +#endif /* ALGORITHM_DBE */ +#ifdef ALGORITHM_PB + /* Bass Enhancement parameters */ + LVM_BE_Mode_en BE_OperatingMode; /* Bass Enhancement operating mode */ + LVM_INT16 BE_EffectLevel; /* Bass Enhancement effect level */ + LVM_BE_CentreFreq_en BE_CentreFreq; /* Bass Enhancement centre frequency */ + LVM_BE_FilterSelect_en BE_HPF; /* Bass Enhancement high pass filter selector */ + +#endif /* ALGORITHM_PB */ + /* Volume Control parameters */ + LVM_INT16 VC_EffectLevel; /* Volume Control setting in dBs */ + LVM_INT16 VC_Balance; /* Left Right Balance control in dB (-96 to 96 dB), -ve values reduce */ + +#ifdef ALGORITHM_TE + /* Treble Enhancement parameters */ + LVM_TE_Mode_en TE_OperatingMode; /* Treble Enhancement On/Off */ + LVM_INT16 TE_EffectLevel; /* Treble Enhancement gain dBs */ + +#endif /* ALGORITHM_TE */ +#ifdef ALGORITHM_LM + /* Loudness Maximiser parameters */ + LVM_LM_Mode_en LM_OperatingMode; /* Loudness Maximiser operating mode */ + LVM_LM_Effect_en LM_EffectLevel; /* Loudness Maximiser effect level */ + LVM_UINT16 LM_Attenuation; /* Loudness Maximiser output attenuation */ + LVM_UINT16 LM_CompressorGain; /* Loudness Maximiser output compressor gain */ + LVM_UINT16 LM_SpeakerCutOff; /* Loudness Maximiser speaker cut off frequency */ + +#endif /* ALGORITHM_LM */ + +#ifdef ALGORITHM_AVL + /* AVL parameters */ + LVM_AVL_Mode_en AVL_OperatingMode; /* AVL operating mode */ + +#endif /* ALGORITHM_AVL */ + +#ifdef ALGORITHM_TG + /* Tone Generator parameters */ + LVM_TG_Mode_en TG_OperatingMode; /* Tone generator mode */ + LVM_TG_SweepMode_en TG_SweepMode; /* Log or linear sweep */ + LVM_UINT16 TG_StartFrequency; /* Sweep start frequency in Hz */ + LVM_INT16 TG_StartAmplitude; /* Sweep start amplitude in dBr */ + LVM_UINT16 TG_StopFrequency; /* Sweep stop frequency in Hz */ + LVM_INT16 TG_StopAmplitude; /* Sweep stop amplitude in dBr */ + LVM_UINT16 TG_SweepDuration; /* Sweep duration in seconds, 0 for infinite duration tone */ + LVM_Callback pTG_CallBack; /* End of sweep callback */ + LVM_INT16 TG_CallBackID; /* Callback ID*/ + void *pTGAppMemSpace; /* Application instance handle or memory area */ +#endif /* ALGORITHM_TG */ + +#ifdef ALGORITHM_PSA + /* General Control */ + LVM_PSA_Mode_en PSA_Enable; + + /* Spectrum Analyzer parameters */ + LVM_PSA_DecaySpeed_en PSA_PeakDecayRate; /* Peak value decay rate*/ + LVM_UINT16 PSA_NumBands; /* Number of Bands*/ +#endif /* ALGORITHM_PSA */ + +#ifdef ALGORITHM_LIMP + LVM_LIMP_Mode_en LIMP_OperatingMode; /* LIMP operating mode */ + LVM_INT16 LIMP_Threshold; /* LIMP threshold in dB */ +#endif /* ALGORITHM_LIMP */ + +#ifdef ALGORITHM_LIMR + LVM_LIMR_Mode_en LIMR_OperatingMode; /* LIMR operating mode */ + LVM_LIMR_Reference_en LIMR_Reference; /* LIMR reference input */ + LVM_INT16 LIMR_Threshold; /* LIMR threshold in dB */ +#endif /* ALGORITHM_LIMR */ + +#ifdef ALGORITHM_CS + LVM_AP_MODE_en CS_AP_Mode; /* concert sound advanced paramameter mode */ + LVM_INT16 CS_AP_MidGain; /* MidChannelGain */ + LVM_UINT16 CS_AP_MidCornerFreq; /* Shelving Filter Corner Frequency */ + LVM_UINT16 CS_AP_SideHighPassCutoff; /* SideBoost HighPassFilter Corner Frequency */ + LVM_UINT16 CS_AP_SideLowPassCutoff; /* SideBoost LowPassFilter Corner Frequency */ + LVM_INT16 CS_AP_SideGain; /* Side Channel Gain */ +#endif + +#ifdef ALGORITHM_XO + LVM_Mode_en XO_OperatingMode; /* Crossover operating mode*/ + LVM_UINT16 XO_cutoffFrequency; /* Crossover cut-off frequency*/ + +#endif/*ALGORITHM_XO*/ + +} LVM_ControlParams_t; + + +/* Instance Parameter structure */ +typedef struct +{ + /* General */ + LVM_BufferMode_en BufferMode; /* Buffer management mode */ + LVM_UINT16 MaxBlockSize; /* Maximum processing block size */ + + /* N-Band Equaliser */ + LVM_UINT16 EQNB_NumBands; /* Maximum number of User equaliser bands */ + LVM_UINT16 PR_EQNB_NumBands; /* Maximum number of Product equaliser bands */ + EAP_NXPPlatform_en Platform; /* NXP Platform where EAP is playing on (LVM_IMXRT1050,LVM_IMXRT1060, LVM_IMXRT1064, LVM_IMXRT1170, LVM_LPC55, LVM_IMXRT500, LVM_IMXRT600)*/ +#ifdef ALGORITHM_PSA + /* PSA */ + LVM_UINT16 PSA_HistorySize; /* PSA History size in ms: 200 to 5000 */ + LVM_UINT16 PSA_MaxBands; /* Maximum number of bands: 6 to 64 */ + LVM_UINT16 PSA_SpectrumUpdateRate; /* Spectrum update rate : 10 to 25*/ + LVM_PSA_Mode_en PSA_Included; /* Controls the instance memory allocation for PSA: ON/OFF */ +#endif /* ALGORITHM_PSA */ +} LVM_InstParams_t; + + +/* Headroom management parameter structure */ +typedef struct +{ + LVM_Headroom_Mode_en Headroom_OperatingMode; /* Headroom Control On/Off */ + LVM_HeadroomBandDef_t *pHeadroomDefinition; /* Pointer to headroom bands definition */ + LVM_UINT16 NHeadroomBands; /* Number of headroom bands */ +} LVM_HeadroomParams_t; + + +/****************************************************************************************/ +/* */ +/* Function Prototypes */ +/* */ +/****************************************************************************************/ + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetVersionInfo */ +/* */ +/* DESCRIPTION: */ +/* This function is used to retrieve information about the library's version. */ +/* */ +/* PARAMETERS: */ +/* pVersion Pointer to an empty version info structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS when pVersion is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st *pVersion); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetMemoryTable */ +/* */ +/* DESCRIPTION: */ +/* This function is used for memory allocation and free. It can be called in */ +/* two ways: */ +/* */ +/* hInstance = NULL Returns the memory requirements */ +/* hInstance = Instance handle Returns the memory requirements and */ +/* allocated base addresses for the instance */ +/* */ +/* When this function is called for memory allocation (hInstance=NULL) the memory */ +/* base address pointers are NULL on return. */ +/* */ +/* When the function is called for free (hInstance = Instance Handle) the memory */ +/* table returns the allocated memory and base addresses used during initialisation. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pMemoryTable Pointer to an empty memory definition table */ +/* pInstParams Pointer to the instance parameters */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When one of pMemoryTable or pInstParams is NULL */ +/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t hInstance, + LVM_MemTab_t *pMemoryTable, + LVM_InstParams_t *pInstParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetInstanceHandle */ +/* */ +/* DESCRIPTION: */ +/* This function is used to create a bundle instance. It returns the created instance */ +/* handle through phInstance. All parameters are set to their default, inactive state. */ +/* */ +/* PARAMETERS: */ +/* phInstance pointer to the instance handle */ +/* pMemoryTable Pointer to the memory definition table */ +/* pInstParams Pointer to the instance parameters */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Initialisation succeeded */ +/* LVM_ALIGNMENTERROR Instance or scratch memory on incorrect alignment */ +/* LVM_NULLADDRESS Instance or scratch memory has a NULL pointer */ +/* */ +/* NOTES: */ +/* 1. This function must not be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t *phInstance, + LVM_MemTab_t *pMemoryTable, + LVM_InstParams_t *pInstParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_ClearAudioBuffers */ +/* */ +/* DESCRIPTION: */ +/* This function is used to clear the internal audio buffers of the bundle. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Buffers Cleared */ +/* LVM_NULLADDRESS Instance is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t hInstance); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetControlParameters */ +/* */ +/* DESCRIPTION: */ +/* Request the LifeVibes module parameters. The current parameter set is returned */ +/* via the parameter pointer. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to an empty parameter structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS when any of hInstance or pParams is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t hInstance, + LVM_ControlParams_t *pParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_SetControlParameters */ +/* */ +/* DESCRIPTION: */ +/* Sets or changes the LifeVibes module parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to a parameter structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When hInstance, pParams or any control pointers are NULL */ +/* LVM_OUTOFRANGE When any of the control parameters are out of range */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance, + LVM_ControlParams_t *pParams); + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_Process */ +/* */ +/* DESCRIPTION: */ +/* Process function for the LifeVibes module. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pInData Pointer to the input data */ +/* pOutData Pointer to the output data */ +/* NumSamples Number of samples in the input buffer */ +/* AudioTime Audio Time of the current input data in milli-seconds */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_INVALIDNUMSAMPLES When the NumSamples is not a valied multiple in unmanaged */ +/* buffer mode */ +/* LVM_ALIGNMENTERROR When either the input our output buffers are not 32-bit */ +/* aligned in unmanaged mode */ +/* LVM_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */ +/* */ +/* NOTES: */ +/* 1. The input and output buffers must be 32-bit aligned */ +/* 2. Number of samples is defined as follows: */ +/* MONO the number of samples in the block */ +/* MONOINSTEREO the number of sample pairs in the block */ +/* STEREO the number of sample pairs in the block */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance, + const LVM_INT32 *pInData, + LVM_INT32 **pOutData, + LVM_UINT16 NumSamples, + LVM_UINT32 AudioTime); + + +#ifdef ALGORITHM_AVL +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetAVLGain */ +/* */ +/* DESCRIPTION: */ +/* This function is used to retrieve the AVL last generated gain in Q16.15 */ +/* linear values. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pAVL_Gain Pointer to the gain */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When hInstance or pAVL_Gain are null addresses */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetAVLGain( LVM_Handle_t hInstance, + LVM_INT32 *pAVL_Gain); + + +#endif /* ALGORITHM_AVL */ + +#ifdef ALGORITHM_EQNB +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_SetHeadroomParams */ +/* */ +/* DESCRIPTION: */ +/* This function is used to set the automatic headroom management parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pHeadroomParams Pointer to headroom parameter structure */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_SetHeadroomParams( LVM_Handle_t hInstance, + LVM_HeadroomParams_t *pHeadroomParams); + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetHeadroomParams */ +/* */ +/* DESCRIPTION: */ +/* This function is used to get the automatic headroom management parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pHeadroomParams Pointer to headroom parameter structure (output) */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS When hInstance or pHeadroomParams are NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetHeadroomParams( LVM_Handle_t hInstance, + LVM_HeadroomParams_t *pHeadroomParams); +#endif /* ALGORITHM_EQNB */ + +#ifdef ALGORITHM_PSA +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_GetSpectrum */ +/* */ +/* DESCRIPTION: */ +/* This function is used to retrieve Spectral information at a given Audio time */ +/* for display usage */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pCurrentPeaks Pointer to location where currents peaks are to be saved */ +/* pPastPeaks Pointer to location where past peaks are to be saved */ +/* pCentreFreqs Pointer to location where centre frequency of each band is */ +/* to be saved */ +/* AudioTime Audio time at which the spectral information is needed */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS If any of input addresses are NULL */ +/* LVM_WRONGAUDIOTIME Failure due to audio time error */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_GetSpectrum( LVM_Handle_t hInstance, + LVM_INT8 *pCurrentPeaks, + LVM_INT8 *pPastPeaks, + LVM_UINT16 *pCentreFreqs, + LVM_UINT32 AudioTime); + + +#endif /* ALGORITHM_PSA */ + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVM_SetVolumeNoSmoothing */ +/* */ +/* DESCRIPTION: */ +/* This function is used to set output volume without any smoothing */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance Handle */ +/* pParams Control Parameters, only volume value is used here */ +/* */ +/* RETURNS: */ +/* LVM_SUCCESS Succeeded */ +/* LVM_NULLADDRESS If any of input addresses are NULL */ +/* LVM_OUTOFRANGE When any of the control parameters are out of range */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVM_Process function */ +/* */ +/****************************************************************************************/ +#ifdef __DLL_EXPORT +__declspec(dllexport) +#endif /* __DLL_EXPORT */ +LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t hInstance, + LVM_ControlParams_t *pParams); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LVM_H__ */ + + diff --git a/third_party/include/nxp/eap/EAP_Includes/LVC_Types.h b/third_party/include/nxp/eap/EAP_Includes/LVC_Types.h new file mode 100644 index 000000000000..6d3501daf8e6 --- /dev/null +++ b/third_party/include/nxp/eap/EAP_Includes/LVC_Types.h @@ -0,0 +1,417 @@ +/* Copyright 2004-2025 NXP + * + * SPDX-License-Identifier: MIT + * This license applies ONLY to this header file LVC_Types.h + * + * 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. + * + */ + +/**************************************************************************************** + + $Author: beq07720 $ + $Revision: 130089 $ + $Date: 2019-07-24 07:46:43 +0200 (Wed, 24 Jul 2019) $ + +*****************************************************************************************/ + +/** @file + * Header file defining the standard LifeVibes types for use in the application layer + * interface of all LifeVibes modules + */ + +#ifndef LVC_TYPES_H +#define LVC_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/****************************************************************************************/ +/* */ +/* definitions */ +/* */ +/****************************************************************************************/ + +#define LVM_NULL (void *)0 ///< NULL pointer + +#define LVM_TRUE 1 ///< Boolean True +#define LVM_FALSE 0 ///< Boolean False + +#define LVM_MAXINT_8 127 ///< Maximum positive integer size +#define LVM_MAXINT_16 32767 ///< Maximum signed int 16 bits number +#define LVM_MAXUINT_16 65535U ///< Maximum un-signed int 16 bits number +#define LVM_MAXINT_32 2147483647 ///< Maximum signed int 32 bits number +#define LVM_MAXUINT_32 4294967295U ///< Maximum un-signed int 32 bits number +#define LVM_MININT_32 0x80000000U ///< Minimum signed int 32 bit number in 2's complement form + +#define LVM_MAXENUM 2147483647 ///< Maximum value for enumerator +#define LVM_MODULEID_MASK 0xFF00 ///< Mask to extract the calling module ID from callbackId +#define LVM_EVENTID_MASK 0x00FF ///< Mask to extract the callback event from callbackId + +/* Memory table*/ +#define LVM_MEMREGION_PERSISTENT_SLOW_DATA 0 ///< Offset to the instance memory region +#define LVM_MEMREGION_PERSISTENT_FAST_DATA 1 ///< Offset to the persistent data memory region +#define LVM_MEMREGION_PERSISTENT_FAST_COEF 2 ///< Offset to the persistent coefficient memory region +#define LVM_MEMREGION_TEMPORARY_FAST 3 ///< Offset to temporary memory region + +#define LVM_NR_MEMORY_REGIONS 4 ///< Number of memory regions + +#define LVM_MODE_LVWIREFORMAT_LENGTH (4) ///< Number of bytes to encode @ref LVM_Mode_en in LVWireFormat +#define LVM_CONFIG_LVWIREFORMAT_LENGTH (4) ///< Number of bytes to encode @ref LVM_Config_en in LVWireFormat +#define LVM_FS_LVWIREFORMAT_LENGTH (4) ///< Number of bytes to encode @ref LVM_Fs_en sample Rate in LVWireFormat +#define LVM_CHANNELTYPE_LVWIREFORMAT_LENGTH (4) ///< Number of bytes to encode @ref LVM_ChannelType_en in LVWireFormat + +#define LVM_CHAR_LVWIREFORMAT_LENGTH (1) ///< Number of bytes to encode ASCII character in LVWireFormat +#define LVM_INT8_LVWIREFORMAT_LENGTH (1) ///< Number of bytes to encode Signed 8-bit word in LVWireFormat +#define LVM_UINT8_LVWIREFORMAT_LENGTH (1) ///< Number of bytes to encode Unsigned 8-bit word in LVWireFormat + +#define LVM_INT16_LVWIREFORMAT_LENGTH (2) ///< Number of bytes to encode Signed 16-bit word in LVWireFormat +#define LVM_UINT16_LVWIREFORMAT_LENGTH (2) ///< Number of bytes to encode Unsigned 16-bit word in LVWireFormat + +#define LVM_INT32_LVWIREFORMAT_LENGTH (4) ///< Number of bytes to encode Signed 32-bit word in LVWireFormat +#define LVM_UINT32_LVWIREFORMAT_LENGTH (4) ///< Number of bytes to encode Unsigned 32-bit word in LVWireFormat + + +/****************************************************************************************/ +/* */ +/* Basic types */ +/* */ +/****************************************************************************************/ + +typedef char LVM_CHAR; ///< ASCII character + +typedef char LVM_INT8; ///< Signed 8-bit word +typedef unsigned char LVM_UINT8; ///< Unsigned 8-bit word + +typedef short LVM_INT16; ///< Signed 16-bit word +typedef unsigned short LVM_UINT16; ///< Unsigned 16-bit word + +#if (defined __LP64__) && __LP64__ +typedef int LVM_INT32; ///< Signed 32-bit word +typedef unsigned int LVM_UINT32; ///< Unsigned 32-bit word +// Type macros +#define LVM_PRINTF_FORMAT_SPECIFIER_INT32 "d" +#define LVM_PRINTF_FORMAT_SPECIFIER_UINT32 "u" +#elif defined(TOOLCHAIN_ADK) // CSR ADK +typedef int LVM_INT32; ///< Signed 32-bit word +typedef unsigned int LVM_UINT32; ///< Unsigned 32-bit word +// Type macros +#define LVM_PRINTF_FORMAT_SPECIFIER_INT32 "d" +#define LVM_PRINTF_FORMAT_SPECIFIER_UINT32 "u" +#else // (defined __LP64__) && __LP64__ +typedef long LVM_INT32; ///< Signed 32-bit word +typedef unsigned long LVM_UINT32; ///< Unsigned 32-bit word +// Type macros +#define LVM_PRINTF_FORMAT_SPECIFIER_INT32 "li" +#define LVM_PRINTF_FORMAT_SPECIFIER_UINT32 "lu" +#endif // (defined __LP64__) && __LP64__ + +typedef float LVM_FLOAT; ///< Single Precision floating point type +typedef double LVM_DOUBLE; ///< Double Precision floating point type + +/****************************************************************************************/ +/* */ +/* Standard Enumerated types */ +/* */ +/****************************************************************************************/ + +/** +The @ref LVM_Mode_en enumerated type is used to set the operating mode of a particular feature inside the LifeVibes modules. +The feature can be separately set to enable the feature processing (i.e., ON) or to disable all feature processing +modules (i.e., OFF). +*/ +typedef enum +{ + LVM_MODE_OFF = 0, ///< LVM module disabled + LVM_MODE_ON = 1, ///< LVM module enabled + LVM_MODE_MUTE = 2, ///< LVM module muted + LVM_MODE_DUMMY = LVM_MAXENUM +} LVM_Mode_en; + +/** +Sets stream Format +*/ +typedef enum +{ + LVM_STEREO = 0, ///<Stereo stream + LVM_MONOINSTEREO = 1, ///<Mono in stereo stream + LVM_MONO = 2, ///<Mono stream + LVM_5DOT1 = 3, ///<stream 5.1 formatted + LVM_7DOT1 = 4, ///<stream 7.1 formatted + LVM_SOURCE_DUMMY = LVM_MAXENUM +} LVM_Format_en; + +/** +Sets Speaker type +*/ +typedef enum +{ + LVM_SPEAKER_MONO = 0, ///< Mono type speaker + LVM_SPEAKER_STEREO = 1, ///< Stereo type speaker + LVM_SPEAKER_DUMMY = LVM_MAXENUM +} LVM_SpeakerType_en; + +/** +Sets Word length +*/ +typedef enum +{ + LVM_16_BIT = 0, ///< 16 bit word length + LVM_32_BIT = 1, ///< 32 bit word length + LVM_WORDLENGTH_DUMMY = LVM_MAXENUM +} LVM_WordLength_en; + +/** +The LVM product supports the sample rates specified in @ref LVM_Fs_en. The input and output sample rates are always the same. +*/ +typedef enum +{ + LVM_FS_8000 = 0, ///< 8k sampling rate + LVM_FS_11025 = 1, ///< 11.025k sampling rate + LVM_FS_12000 = 2, ///< 12k sampling rate + LVM_FS_16000 = 3, ///< 16k sampling rate + LVM_FS_22050 = 4, ///< 22.050k sampling rate + LVM_FS_24000 = 5, ///< 24k sampling rate + LVM_FS_32000 = 6, ///< 32k sampling rate + LVM_FS_44100 = 7, ///< 44.1k sampling rate + LVM_FS_48000 = 8, ///< 48k sampling rate + LVM_FS_96000 = 9, + LVM_FS_COUNT = 10, ///< Max sampling rate count + LVM_FS_INVALID = LVM_MAXENUM-1, + LVM_FS_DUMMY = LVM_MAXENUM +} LVM_Fs_en; + +/** +The LVM product supports the sample rates specified in @ref LVM_Fs_HDAudio_en. The input and output sample rates are always the same. +*/ +typedef enum +{ + LVM_FS_HDAUDIO_8000 = 0, ///< 8k sampling rate + LVM_FS_HDAUDIO_11025 = 1, ///< 11.025k sampling rate + LVM_FS_HDAUDIO_16000 = 2, ///< 16k sampling rate + LVM_FS_HDAUDIO_22050 = 3, ///< 22.050k sampling rate + LVM_FS_HDAUDIO_32000 = 4, ///< 32k sampling rate + LVM_FS_HDAUDIO_44100 = 5, ///< 44.1k sampling rate + LVM_FS_HDAUDIO_48000 = 6, ///< 48k sampling rate + LVM_FS_HDAUDIO_88200 = 7, ///< 88.2k sampling rate + LVM_FS_HDAUDIO_96000 = 8, ///< 96k sampling rate + LVM_FS_HDAUDIO_176400 = 9, ///< 176.4k sampling rate + LVM_FS_HDAUDIO_192000 = 10, ///< 192k sampling rate + LVM_FS_HDAUDIO_COUNT = 11, ///< Max sampling rate count + LVM_FS_HDAUDIO_INVALID = LVM_MAXENUM-1, + LVM_FS_HDAUDIO_DUMMY = LVM_MAXENUM +} LVM_Fs_HDAudio_en; + +/** +The @ref LVM_PcmFormat_en enumerated type identifies the different PCM formats that can be configured +*/ +typedef enum { + LVM_PCMFORMAT_16_BIT = 0, ///< PCM signed Q0.15 + LVM_PCMFORMAT_32_BIT = 1, ///< PCM signed Q0.31 + LVM_PCMFORMAT_8_24_BIT = 2, ///< PCM signed Q7.24 + LVM_PCMFORMAT_COUNT = 3, ///< Max PCM Format count + LVM_PCMFORMAT_DUMMY = LVM_MAXENUM +} LVM_PcmFormat_en; + +/** +The enumerated type is used to select the reset mode for the module. +@ref LVM_RESET_SOFT is used to select a soft reset (or partial reset) and @ref LVM_RESET_HARD is +used to select a hard reset (full re-initialization). +*/ +typedef enum +{ +/** +<table border> + <tr> + <td><b>Name</b></td> + <td><b>MODE</b></td> + </tr> + <tr> + <td>ResetType</td> + <td>@ref LVM_RESET_SOFT</td> + </tr> + <tr> + <td></td> + <td>@ref LVM_RESET_HARD</td> + </tr> +</table> +*/ + LVM_RESET_SOFT = 0, ///< Reset type for LVM where a partial reset of the module should be performed + LVM_RESET_HARD = 1, ///< Reset type for LVM where a full reset of the module should be performed + LVM_RESET_DUMMY = LVM_MAXENUM +} LVM_ResetType_en; + +/** +The @ref LVM_MemoryTypes_en enumerated type identifies the memory region types so that they can be correctly placed in memory +by the calling application. +The module initially has no permanent memory storage and makes no use of persistent memory allocation internally. +The calling application must allocate memory for the module to use. + +Four memory regions are required: +@li @ref LVM_MEMREGION_PERSISTENT_SLOW_DATA : this type of memory is used to store all the control data that needs to be saved between two consecutive calls to the process function. +@li @ref LVM_MEMREGION_PERSISTENT_FAST_DATA : this type of memory is used to store data such as filter history +@li @ref LVM_MEMREGION_PERSISTENT_FAST_COEF : this type of memory is used to store filter coefficients. +@li @ref LVM_MEMREGION_TEMPORARY_FAST (scratch): this type of memory is used to store temporary data. This memory can be reused by the application in between calls to the process function. + +This collection of memory regions forms the module instance. + +Typically the memory is allocated by the application dynamically; however, it can be allocated statically if required. +The sizes of the memory regions can be found by running the GetMemoryTable functions on a simulator and noting +the returned values. Alternatively contact NXP who can provide the figures. +It is possible that these memory sizes will change between release versions of the library and hence the dynamic memory allocation method is preferred where possible. +On some target platforms the placement of memory regions is critical for achieving optimal performance of the module. +*/ +typedef enum +{ + LVM_PERSISTENT_SLOW_DATA = LVM_MEMREGION_PERSISTENT_SLOW_DATA, ///< Persistent slow memory region + LVM_PERSISTENT_FAST_DATA = LVM_MEMREGION_PERSISTENT_FAST_DATA, ///< Persistent fast memory region + LVM_PERSISTENT_FAST_COEF = LVM_MEMREGION_PERSISTENT_FAST_COEF, ///< Persisten fast memory for coefficient storage + LVM_TEMPORARY_FAST = LVM_MEMREGION_TEMPORARY_FAST, ///< Temporary fast memory region + LVM_MEMORYTYPE_DUMMY = LVM_MAXENUM +} LVM_MemoryTypes_en; + +/** +Sets mod of Configuration +*/ +typedef enum +{ + LVM_CONFIG_HANDSET = 0, ///< Handset configuration + LVM_CONFIG_SPEAKERPHONE = 1, ///< Speaker mod configuration + LVM_CONFIG_STEREOHEADSET = 2, ///< Stereo Headset configuration + LVM_CONFIG_HEADSET_ENDFIRE = 3, ///< Close-microphone endfire headset configuration + LVM_CONFIG_HEADSET_CALLING = 4, ///< Ear cup mics for calling + LVM_CONFIG_HEADSET_CALLING_BOOM = 5, ///< Ear cup and boom mics for calling + LVM_CONFIG_HEADSET_FRONTEND = 6, ///< Ear cup mics for frontend pre enhancement + LVM_CONFIG_HEADSET_FRONTEND_BOOM = 7, ///< Ear cup and boom mics for frontend pre enhancement + LVM_CONFIG_DUMMY = LVM_MAXENUM +} LVM_Config_en; + +/** +Sets Channel Type +*/ +typedef enum +{ + LVM_MICROPHONE_CHANNEL = 0, ///< Microphone Channel + LVM_SPEAKER_CHANNEL = 1, ///< Speaker Channel + LVM_SPEAKER_AS_MIC_CHANNEL = 2, ///< Speaker or Receiver behaving as a Microphone Channel + LVM_MICROPHONE_AS_FAREND_REFERENCE_CHANNEL = 3, ///< Microphone as Farend Reference Channel + LVM_CHANNEL_DUMMY = LVM_MAXENUM +} LVM_ChannelType_en; + +/** +Sets Tunability of tuning parameters +*/ +typedef enum +{ + LVM_TUNABILITY_BASIC = 0, ///< Basic tuning parameter, always visible + LVM_TUNABILITY_ADVANCED = 1, ///< Expert tuning parameter, only visible in advanced tuning mode + LVM_TUNABILITY_RESERVED = 2, ///< Reserved tuning parameter, not visible + LVM_TUNABILITY_DUMMY = LVM_MAXENUM +} LVM_Tunability_en; + +/** +Sets Volume Dependence +*/ +typedef enum +{ + LVM_VOLUME_DEPENDENT = 0, ///< Volume dependent + LVM_VOLUME_INDEPENDENT = 1, ///< Volume independent + LVM_VOLUMEDEPENDENCE_DUMMY = LVM_MAXENUM +} LVM_VolumeDependence_en; + +/** +The @ref LVM_MemoryRegion_st type defines a memory region by specifying its size in bytes, its region type and its base pointer. +@see LVM_MemoryTypes_en +*/ +typedef struct +{ + LVM_UINT32 Size; ///< The size of the memory region in bytes + LVM_MemoryTypes_en Type; ///< Type of memory region + void *pBaseAddress; ///< Pointer to the memory region base address +} LVM_MemoryRegion_st; + +/** +The LVM_MemoryTable_st type defines the memory requirements of the module as an array of region definitions. +The number of required memory regions is given by the constant @ref LVM_NR_MEMORY_REGIONS +@see LVM_MemoryRegion_st +*/ +typedef struct +{ + LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; ///< One definition of all memory regions +} LVM_MemoryTable_st; + +/** +The LVM_ContextTable_st type defines a memory region by specifying its size in bytes and its base pointer. +@see LVM_ContextTable_st +*/ +typedef struct +{ + LVM_UINT32 ContextTableLength; ///< its size in bytes + LVM_CHAR *pContext; ///< its base pointer +} LVM_ContextTable_st; + +/** +Beats Per Minute Structure +*/ +typedef struct +{ + LVM_INT16 ShortTermMinimum; ///< Beats per minute in Q9.6 format + LVM_INT16 ShortTermAverage; ///< Beats per minute in Q9.6 format + LVM_INT16 ShortTermMaximum; ///< Beats per minute in Q9.6 format + + LVM_INT16 Confidence; ///< Beat confidence level: 0 = no confidence, 32767 = maximum confidence + LVM_INT16 Strength; ///< Beat strength level: 0 = no beat, 32767 = maximum strength beat + LVM_INT16 LongTermMinimum; ///< Beats per minute in Q9.6 format + LVM_INT16 LongTermAverage; ///< Beats per minute in Q9.6 format + LVM_INT16 LongTermMaximum; ///< Beats per minute in Q9.6 format + +} LVM_BPMModuleStats_st; + + +/****************************************************************************************/ +/* */ +/* Standard Function Prototypes */ +/* */ +/****************************************************************************************/ +/** +@brief General purpose callback function + +@param pCallbackData Pointer to the callback data structure +@param pGeneralPurpose General purpose pointer (e.g. to a data structure needed in the callback) +@param PresetLength General purpose variable (e.g. to be used as callback ID) +@return \ref LVM_INT32 +*/ +typedef LVM_INT32 (*LVM_Callback)(void *pCallbackData, + void *pGeneralPurpose, + LVM_INT16 GeneralPurpose ); + +/****************************************************************************************/ +/* */ +/* End of file */ +/* */ +/****************************************************************************************/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LVC_TYPES_H */ diff --git a/tools/.gitignore b/tools/.gitignore deleted file mode 100644 index 72c3b4c2c564..000000000000 --- a/tools/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -*.o -*.in -*~ -autom4te* -*.Po -*.swp -Makefile -config.* -configure -depcomp -install-sh -missing -stamp-h1 -aclocal.m4 -compile -ltmain.sh -rimage/rimage -rwav/rwav -*.tplg -topology/*.conf -test/topology/*.conf -eqctl/sof-eqctl -logger/sof-logger diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 6d08afa746cd..fb16d265c070 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") message(FATAL_ERROR @@ -12,10 +12,18 @@ endif() project(SOF_TOOLS C) +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "No CMAKE_BUILD_TYPE, defaulting to Debug") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE) +endif() + set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}/..") +# Most (too) verbose, keep this one first (assuming -j1) +add_subdirectory(topology) +# Includes test/topology/ +add_subdirectory(test) + add_subdirectory(probes) add_subdirectory(logger) add_subdirectory(ctl) -add_subdirectory(topology) -add_subdirectory(test) diff --git a/tools/README.md b/tools/README.md index 3aa3be7ad051..c74f411f8560 100644 --- a/tools/README.md +++ b/tools/README.md @@ -15,15 +15,15 @@ make install ### sof-logger sof-logger is used to print logs delivered from FW dma_trace mechanism, by -searching log entries in *.ldc file generated by rimage. +searching log entries in *.ldc file generated by smex. -Every entry declared in FW is placed in elf output file (e.g. sof-apl) in +Every entry declared in FW is placed in elf output file (e.g. sof-tgl) in .static_log_entries section in a form of struct defined in sof/src/include/sof/trace.h in sof fw repo. *.ldc file contains `snd_sof_logs_header` (defined in rmbox/logger\_convert.c) following by `.static_log_entries` section -incorporated from FW elf file (e.g. sof-apl). `snd_sof_logs_header` +incorporated from FW elf file (e.g. sof-tgl). `snd_sof_logs_header` contains basic information about `.static_log_entries` section like `base_address` and `data_length`. @@ -133,7 +133,7 @@ Usage sof-coredump-reader.py [-h] [-a ARCH] [-c] [-l COLUMNCOUNT] [-v] We read from dump file into sof-coredump-reader.py, then we pipe its output to xt-gdb, which operates on given elf-file. - $ ./sof-coredump-to-gdb.sh sof-apl dump_file + $ ./sof-coredump-to-gdb.sh sof-tgl dump_file ### tests @@ -150,7 +150,7 @@ functionality and quality of processed samples. #### Compilation steps -Run the host-build-all.sh to build the required libraries for the testbench. +Run the rebuild-testbench.sh to build the required libraries for the testbench. It should also build the testbench executable. #### Running the Testbench diff --git a/tools/coredumper/sof-coredump-reader.py b/tools/coredumper/sof-coredump-reader.py index 55445a1a763c..9c1f5cceb762 100755 --- a/tools/coredumper/sof-coredump-reader.py +++ b/tools/coredumper/sof-coredump-reader.py @@ -56,7 +56,7 @@ def stdout_print(*args, **kwargs): ]] ] -# Exception casues: +# Exception causes: # CODE: [Exception cause, excvaddr loaded] EXCCAUSE_CODE = { 0: ["IllegalInstructionCause: Illegal instruction", False], @@ -718,7 +718,16 @@ def __init__(self, args): .format(stack_base, stack_dw_num)) stdoutOpen() - stdoutPrint("break *0xbefe0000\nrun\n") + + # disable confirmation request for undefined breakpoint + stdoutPrint("set confirm off\n") + + # for XTOS SOF build + stdoutPrint("break _MemErrorVector\n") + # for Zephyr SOF build + stdoutPrint("break _MemoryExceptionVector_text_start\n") + + stdoutPrint("run\n") stdoutPrint(self.core_dump.to_string(1)) #TODO: make this elegant diff --git a/tools/corpus/README.md b/tools/corpus/README.md new file mode 100644 index 000000000000..cce79445601a --- /dev/null +++ b/tools/corpus/README.md @@ -0,0 +1,21 @@ +# SOF Corpus Directory + +==================== + +The following directory is a special directory containing binary transcripts of +IPC messages from various devices. When OSS-Fuzz runs, it zips these files up +into a output directory to be used as seed material for the fuzzers. + +Feel free to add more examples to this directory, more components and state +coverage the better. + +## How to generate these files + +These files are generated by live dumping the IPC messages, the initial batch +were created by adding a hook to write binary ipc window to the /tmp directory +from the kernel every time a IPC TX occurred. These files were then +concatenated together in order sent. A single file represents a single DSP +lifecycle. If you inspect the data, you will be able to parse out each IPC at +SOF_IPC_MSG_MAX_SIZE byte intervals. + + diff --git a/tools/corpus/sof-ipc3/DELETE_ME b/tools/corpus/sof-ipc3/DELETE_ME new file mode 100644 index 000000000000..e5b9ac78ad06 --- /dev/null +++ b/tools/corpus/sof-ipc3/DELETE_ME @@ -0,0 +1 @@ +stub file until real data is added diff --git a/tools/corpus/sof-ipc4/DELETE_ME b/tools/corpus/sof-ipc4/DELETE_ME new file mode 100644 index 000000000000..e5b9ac78ad06 --- /dev/null +++ b/tools/corpus/sof-ipc4/DELETE_ME @@ -0,0 +1 @@ +stub file until real data is added diff --git a/tools/ctl/CMakeLists.txt b/tools/ctl/CMakeLists.txt index 6cf6fea5936c..5c4c2dd315b5 100644 --- a/tools/ctl/CMakeLists.txt +++ b/tools/ctl/CMakeLists.txt @@ -4,11 +4,19 @@ add_executable(sof-ctl ctl.c ) +target_link_directories(sof-ctl BEFORE + PRIVATE "${SOF_ROOT_SOURCE_DIRECTORY}/../tools/lib") + target_link_libraries(sof-ctl PRIVATE "-lasound" ) +target_compile_options(sof-ctl PRIVATE + -Wall -Werror +) + target_include_directories(sof-ctl PRIVATE + "${SOF_ROOT_SOURCE_DIRECTORY}/../tools/include" "${SOF_ROOT_SOURCE_DIRECTORY}/src/include" "${SOF_ROOT_SOURCE_DIRECTORY}" ) diff --git a/tools/ctl/ctl.c b/tools/ctl/ctl.c index 957003397ff8..c669349b68f9 100644 --- a/tools/ctl/ctl.c +++ b/tools/ctl/ctl.c @@ -20,6 +20,15 @@ #define BUFFER_SIZE_OFFSET 1 #define BUFFER_ABI_OFFSET 2 +#define BUFFER_TLV_HEADER_BYTES ((BUFFER_ABI_OFFSET) * sizeof(uint32_t)) + +/* Definitions for multiple IPCs */ +enum sof_ipc_type { + SOF_IPC_TYPE_3, + SOF_IPC_TYPE_4, + SOF_IPC_TYPE_COUNT +}; + struct ctl_data { /* the input file name */ char *input_file; @@ -30,15 +39,21 @@ struct ctl_data { int out_fd; /* cached buffer for input/output */ - unsigned int *buffer; + /* use uint32_t to ensure alignment: Warning on pointer arithmetic. */ + uint32_t *buffer; int buffer_size; int ctrl_size; + enum sof_ipc_type ipc_type; + + /* IPC type dependent magic number to use, expect */ + uint32_t magic; + /* flag for input/output format, binary or CSV */ bool binary; /* flag for input/output format, with or without abi header */ bool no_abi; - /* component specific type, default 0 */ + /* component specific type / param_id, default 0 */ uint32_t type; /* set or get control value */ bool set; @@ -67,16 +82,19 @@ static void usage(char *name) fprintf(stdout, "\t %s -h\n", name); fprintf(stdout, "\nWhere:\n"); fprintf(stdout, " -D device name (default is hw:0)\n"); - fprintf(stdout, " -g <size> generates"); - fprintf(stdout, " the current ABI header with given payload size\n"); fprintf(stdout, " -c control name e.g."); fprintf(stdout, " numid=22,name=\\\"EQIIR1.0 EQIIR\\\"\"\n"); fprintf(stdout, " -n control id e.g. 22\n"); - fprintf(stdout, " -s set data using ASCII CSV input file\n"); + fprintf(stdout, " -i {3|4} selects the IPC type to use, defaults to 3 (IPC3)\n"); + fprintf(stdout, " -g <size> generates"); + fprintf(stdout, " the current ABI header with given payload size\n"); + fprintf(stdout, " -s set data, default is using ASCII CSV input file\n"); fprintf(stdout, " -b set/get control in binary mode(e.g. for set, use binary input file, for get, dump out in hex format)\n"); fprintf(stdout, " -r no abi header for the input file, or not dumping abi header for get.\n"); fprintf(stdout, " -o specify the output file.\n"); - fprintf(stdout, " -t specify the component specified type.\n"); + fprintf(stdout, " -t specify the component specified type (IPC3 specific).\n"); + fprintf(stdout, " -p specify the param_id of the data (IPC4 specific)."); + fprintf(stdout, " Valid range: 0-255\n"); } static void header_init(struct ctl_data *ctl_data) @@ -84,22 +102,26 @@ static void header_init(struct ctl_data *ctl_data) struct sof_abi_hdr *hdr = (struct sof_abi_hdr *)&ctl_data->buffer[BUFFER_ABI_OFFSET]; - hdr->magic = SOF_ABI_MAGIC; + hdr->magic = ctl_data->magic; hdr->type = ctl_data->type; hdr->abi = SOF_ABI_VERSION; + ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY; } +/* Returns the number of bytes written to the control buffer */ static int read_setup(struct ctl_data *ctl_data) { struct sof_abi_hdr *hdr = (struct sof_abi_hdr *)&ctl_data->buffer[BUFFER_ABI_OFFSET]; - int n_max = ctl_data->ctrl_size / sizeof(unsigned int); + int n_max = ctl_data->ctrl_size; char *mode = ctl_data->binary ? "rb" : "r"; int abi_size = 0; - unsigned int x; + uint32_t x; int separator; int n = 0; FILE *fh; + int data_start_int_index = 0; + int data_int_index; /* open input file */ fh = fdopen(ctl_data->in_fd, mode); @@ -111,20 +133,21 @@ static int read_setup(struct ctl_data *ctl_data) /* create abi header*/ if (ctl_data->no_abi) { header_init(ctl_data); - abi_size = sizeof(struct sof_abi_hdr) / sizeof(int); + abi_size = sizeof(struct sof_abi_hdr); + data_start_int_index += (abi_size + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t); } if (ctl_data->binary) { - n = fread(&ctl_data->buffer[BUFFER_ABI_OFFSET + abi_size], - sizeof(int), n_max - abi_size, fh); - + n = fread(&ctl_data->buffer[data_start_int_index], + sizeof(uint8_t), n_max - abi_size, fh); goto read_done; } /* reading for ASCII CSV txt */ + data_int_index = data_start_int_index; while (fscanf(fh, "%u", &x) != EOF) { if (n < n_max) - ctl_data->buffer[BUFFER_ABI_OFFSET + abi_size + n] = x; + ctl_data->buffer[data_int_index] = x; if (n > 0) fprintf(stdout, ","); @@ -133,24 +156,31 @@ static int read_setup(struct ctl_data *ctl_data) separator = fgetc(fh); while (separator != ',' && separator != EOF) separator = fgetc(fh); - - n++; + data_int_index++; + n += sizeof(uint32_t); } fprintf(stdout, "\n"); read_done: if (ctl_data->no_abi) { - hdr->size = n * sizeof(int); + hdr->size = n; n += abi_size; + ctl_data->buffer[BUFFER_SIZE_OFFSET] = n; + n += BUFFER_TLV_HEADER_BYTES; } if (n > n_max) { fprintf(stderr, "Warning: Read of %d exceeded control size. ", - 4 * n); + n); fprintf(stderr, "Please check the data file.\n"); } + if (hdr->magic != ctl_data->magic) + fprintf(stderr, + "Info: ABI mismatch: expecting: 0x%8.8x, got: 0x%8.8x\n", + ctl_data->magic, hdr->magic); + fclose(fh); return n; } @@ -161,7 +191,10 @@ static void header_dump(struct ctl_data *ctl_data) (struct sof_abi_hdr *)&ctl_data->buffer[BUFFER_ABI_OFFSET]; fprintf(stdout, "hdr: magic 0x%8.8x\n", hdr->magic); - fprintf(stdout, "hdr: type %d\n", hdr->type); + if (ctl_data->ipc_type == SOF_IPC_TYPE_3) + fprintf(stdout, "hdr: type %u\n", hdr->type); + else + fprintf(stdout, "hdr: param_id %u\n", hdr->type); fprintf(stdout, "hdr: size %d bytes\n", hdr->size); fprintf(stdout, "hdr: abi %d:%d:%d\n", SOF_ABI_VERSION_MAJOR(hdr->abi), @@ -178,16 +211,16 @@ static void hex_data_dump(struct ctl_data *ctl_data) int i; /* calculate the dumping units */ - n = ctl_data->buffer[BUFFER_SIZE_OFFSET] / sizeof(uint16_t); + n = (ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES) / sizeof(uint16_t); /* exclude the type and size header */ - int_offset = 2; + int_offset = 0; /* exclude abi header if '-r' specified */ if (ctl_data->no_abi) { - int_offset += sizeof(struct sof_abi_hdr) / + int_offset += (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t); - n -= sizeof(struct sof_abi_hdr) / + n -= (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) / sizeof(uint16_t); } @@ -197,7 +230,7 @@ static void hex_data_dump(struct ctl_data *ctl_data) /* Print out in 16bit hex format */ for (i = 0; i < n; i++) { if (!(i % 8)) - fprintf(stdout, "%08lx ", + fprintf(stdout, "%08zx ", i * sizeof(uint16_t)); fprintf(stdout, "%04x ", config[i]); if ((i % 8) == 7) @@ -214,11 +247,11 @@ static void csv_data_dump(struct ctl_data *ctl_data, FILE *fh) int i; int s = 0; - config = &ctl_data->buffer[BUFFER_ABI_OFFSET]; - n = ctl_data->buffer[BUFFER_SIZE_OFFSET] / sizeof(uint32_t); + config = &ctl_data->buffer[0]; + n = (ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t); if (ctl_data->no_abi) - s = sizeof(struct sof_abi_hdr) / sizeof(uint32_t); + s = (sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES) / sizeof(uint32_t); /* Print out in CSV txt formal */ for (i = s; i < n; i++) { @@ -262,7 +295,7 @@ static int buffer_alloc(struct ctl_data *ctl_data) * Allocate buffer for tlv write/read. The buffer needs a two * words header with tag (SOF_CTRL_CMD_BINARY) and size in bytes. */ - buffer_size = ctl_data->ctrl_size + 2 * sizeof(unsigned int); + buffer_size = ctl_data->ctrl_size + 2 * sizeof(uint32_t); ctl_data->buffer = calloc(1, buffer_size); if (!ctl_data->buffer) { fprintf(stderr, @@ -270,10 +303,7 @@ static int buffer_alloc(struct ctl_data *ctl_data) return -EINVAL; } - ctl_data->buffer[BUFFER_TAG_OFFSET] = SOF_CTRL_CMD_BINARY; - ctl_data->buffer_size = buffer_size; - return 0; } @@ -287,11 +317,9 @@ static int ctl_setup(struct ctl_data *ctl_data) { int mode = SND_CTL_NONBLOCK; int ctrl_size; - int buffer_size; int read; int write; int type; - char opt; int ret; /* Open the device, mixer control and get read/write/type properties. @@ -355,12 +383,9 @@ static int ctl_setup(struct ctl_data *ctl_data) read = snd_ctl_elem_info_is_tlv_readable(ctl_data->info); write = snd_ctl_elem_info_is_tlv_writable(ctl_data->info); type = snd_ctl_elem_info_get_type(ctl_data->info); - if (!read) { - fprintf(stderr, "Error: No read capability.\n"); - goto value_free; - } - if (!write) { - fprintf(stderr, "Error: No write capability.\n"); + + if (!read && !write) { + fprintf(stderr, "Error: Not a read/write control\n"); goto value_free; } if (type != SND_CTL_ELEM_TYPE_BYTES) { @@ -379,8 +404,6 @@ static int ctl_setup(struct ctl_data *ctl_data) } return ret; -buff_free: - buffer_free(ctl_data); value_free: snd_ctl_elem_value_free(ctl_data->value); @@ -408,11 +431,11 @@ static int ctl_free(struct ctl_data *ctl_data) return ret; } -static void ctl_dump(struct ctl_data *ctl_data) +static void ctl_dump(struct ctl_data *ctl_data, size_t dump_size) { FILE *fh; int offset = 0; - size_t n;/* in bytes */ + size_t n = 0;/* in bytes */ if (ctl_data->out_fd > 0) { if (ctl_data->binary) { @@ -424,13 +447,16 @@ static void ctl_dump(struct ctl_data *ctl_data) return; } - offset = BUFFER_ABI_OFFSET; - n = ctl_data->buffer[BUFFER_SIZE_OFFSET]; + if (dump_size) + n = dump_size; + else + n = ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES; if (ctl_data->no_abi) { - offset += sizeof(struct sof_abi_hdr) / - sizeof(int); + offset = sizeof(struct sof_abi_hdr) / sizeof(int) + + BUFFER_ABI_OFFSET; n -= sizeof(struct sof_abi_hdr); + n -= BUFFER_ABI_OFFSET * sizeof(uint32_t); } n = fwrite(&ctl_data->buffer[offset], 1, n, fh); @@ -443,7 +469,7 @@ static void ctl_dump(struct ctl_data *ctl_data) csv_data_dump(ctl_data, fh); } - fprintf(stdout, "%ld bytes written to file.\n", n); + fprintf(stdout, "%zd bytes written to file.\n", n); fclose(fh); } else { /* dump to stdout */ @@ -455,7 +481,7 @@ static void ctl_dump(struct ctl_data *ctl_data) static int ctl_set_get(struct ctl_data *ctl_data) { int ret; - size_t n; + size_t read_size, ref_size; if (!ctl_data->buffer) { fprintf(stderr, "Error: No buffer for set/get!\n"); @@ -467,14 +493,22 @@ static int ctl_set_get(struct ctl_data *ctl_data) ctl_data->input_file); fprintf(stdout, "into device %s control %s.\n", ctl_data->dev, ctl_data->cname); - n = read_setup(ctl_data); - if (n < 1) { + read_size = read_setup(ctl_data); + if (read_size < 1) { fprintf(stderr, "Error: failed data read from %s.\n", ctl_data->input_file); return -EINVAL; } - ctl_data->buffer[BUFFER_SIZE_OFFSET] = n * sizeof(unsigned int); + ref_size = ctl_data->buffer[BUFFER_SIZE_OFFSET] + BUFFER_TLV_HEADER_BYTES; + if (read_size != ref_size) { + fprintf(stderr, + "Error: Blob TLV header size %u (plus %lu) does not match with read bytes count %zu.\n", + ctl_data->buffer[BUFFER_SIZE_OFFSET], BUFFER_TLV_HEADER_BYTES, + read_size); + return -EINVAL; + } + ret = snd_ctl_elem_tlv_write(ctl_data->ctl, ctl_data->id, ctl_data->buffer); if (ret < 0) { @@ -487,6 +521,8 @@ static int ctl_set_get(struct ctl_data *ctl_data) fprintf(stdout, "Retrieving configuration for "); fprintf(stdout, "device %s control %s.\n", ctl_data->dev, ctl_data->cname); + /* set the ABI header to pass the param ID */ + header_init(ctl_data); ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size; ret = snd_ctl_elem_tlv_read(ctl_data->ctl, ctl_data->id, ctl_data->buffer, @@ -497,6 +533,8 @@ static int ctl_set_get(struct ctl_data *ctl_data) } fprintf(stdout, "Success.\n"); } + + return 0; } int main(int argc, char *argv[]) @@ -504,13 +542,10 @@ int main(int argc, char *argv[]) char *input_file = NULL; char *output_file = NULL; struct ctl_data *ctl_data; + int ipc_type = 3; char nname[256]; int ret = 0; - int n = 0; - int read; - int write; - int type; - char opt; + int opt; struct sof_abi_hdr *hdr; ctl_data = calloc(1, sizeof(struct ctl_data)); @@ -522,7 +557,7 @@ int main(int argc, char *argv[]) ctl_data->dev = "hw:0"; - while ((opt = getopt(argc, argv, "hD:c:s:n:o:t:g:br")) != -1) { + while ((opt = getopt(argc, argv, "hD:c:s:n:i:o:t:p:g:br")) != -1) { switch (opt) { case 'D': ctl_data->dev = optarg; @@ -534,6 +569,9 @@ int main(int argc, char *argv[]) sprintf(nname, "numid=%d", atoi(optarg)); ctl_data->cname = nname; break; + case 'i': + ipc_type = atoi(optarg); + break; case 's': input_file = optarg; ctl_data->input_file = input_file; @@ -549,6 +587,7 @@ int main(int argc, char *argv[]) ctl_data->no_abi = true; break; case 't': + case 'p': ctl_data->type = atoi(optarg); break; case 'g': @@ -563,6 +602,35 @@ int main(int argc, char *argv[]) } } + /* All arguments are switches, error if something still remains in command line */ + if (optind < argc) { + fprintf(stderr, "Error: Non-supported argument %s.\n", + argv[optind]); + return -EINVAL; + } + + switch (ipc_type) { + case 3: + ctl_data->ipc_type = SOF_IPC_TYPE_3; + ctl_data->magic = SOF_ABI_MAGIC; + break; + case 4: + if (ctl_data->type > 255) { + fprintf(stderr, "error: The param_id %u is out of range\n\n", + ctl_data->type); + usage(argv[0]); + goto struct_free; + } + + ctl_data->ipc_type = SOF_IPC_TYPE_4; + ctl_data->magic = SOF_IPC4_ABI_MAGIC; + break; + default: + fprintf(stderr, "error: Unsupported IPC type: %u\n\n", ipc_type); + usage(argv[0]); + goto struct_free; + } + /* open output file */ if (output_file) { ctl_data->out_fd = open(output_file, O_CREAT | O_TRUNC | O_RDWR, @@ -581,8 +649,8 @@ int main(int argc, char *argv[]) hdr = (struct sof_abi_hdr *) &ctl_data->buffer[BUFFER_ABI_OFFSET]; hdr->size = ctl_data->print_abi_size; - ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size; - ctl_dump(ctl_data); + ctl_data->buffer[BUFFER_SIZE_OFFSET] = ctl_data->ctrl_size + hdr->size; + ctl_dump(ctl_data, sizeof(struct sof_abi_hdr) + BUFFER_TLV_HEADER_BYTES); buffer_free(ctl_data); goto out_fd_close; } @@ -620,7 +688,7 @@ int main(int argc, char *argv[]) } /* dump the tlv buffer to a file or stdout */ - ctl_dump(ctl_data); + ctl_dump(ctl_data, 0); data_free: ret = ctl_free(ctl_data); diff --git a/tools/ctl/eq_fir_flat.txt b/tools/ctl/eq_fir_flat.txt deleted file mode 100644 index 4be59009db77..000000000000 --- a/tools/ctl/eq_fir_flat.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,56,50331648,0,0,0,0,56,65538,0,0,0,0,0,4294901764,0,0,0,0,16384,0, diff --git a/tools/ctl/eq_fir_loudness.txt b/tools/ctl/eq_fir_loudness.txt deleted file mode 100644 index 1288bd2fbafe..000000000000 --- a/tools/ctl/eq_fir_loudness.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,256,50331648,0,0,0,0,256,131076,0,0,0,0,65537,65537,4294901764,0,0,0,0,16384,0,88,0,0,0,0,3535366939,119016436,49938453,30147089,30343698,30409180,29426121,27328945,25428369,23921015,22479202,20906315,19267889,17826074,16646407,15663350,14745832,13762777,12845259,11862204,10879149,10027167,9175186,8388742,7602298,6946927,6291557,5636187,5046354,4522057,3997761,3539002,3145779,2752557,2424872,2162723,1900575,1638427,1441815,1245204,1048593,917519,720909,7, diff --git a/tools/ctl/eq_fir_mid.txt b/tools/ctl/eq_fir_mid.txt deleted file mode 100644 index aac92e71de89..000000000000 --- a/tools/ctl/eq_fir_mid.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,128,50380800,0,0,0,0,128,65538,0,0,0,0,0,65576,0,0,0,0,1202154746,4222755303,3873958283,4024953600,4126012299,4176934804,4217764409,4250664050,4273864222,4288806716,2490349,6750285,8126582,7733371,6488174,4980824,3473472,2293804,1245211,1245197, diff --git a/tools/ctl/eq_fir_pass.txt b/tools/ctl/eq_fir_pass.txt deleted file mode 100644 index 5ba02fc7d7fd..000000000000 --- a/tools/ctl/eq_fir_pass.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,56,50331648,0,0,0,0,56,65538,0,0,0,0,4294967295,4294901764,0,0,0,0,16384,0, diff --git a/tools/ctl/eq_iir_bandpass.txt b/tools/ctl/eq_iir_bandpass.txt deleted file mode 100644 index 7c6e3f410a82..000000000000 --- a/tools/ctl/eq_iir_bandpass.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,116,50331648,0,0,0,0,116,2,1,0,0,0,0,0,0,2,2,0,0,0,0,3316150158,2048164275,513807534,3267352229,513807534,0,16384,3867454526,1191025347,38870735,77741469,38870735,4294967292,24197, diff --git a/tools/ctl/eq_iir_bassboost.txt b/tools/ctl/eq_iir_bassboost.txt deleted file mode 100644 index 1c874bfebba8..000000000000 --- a/tools/ctl/eq_iir_bassboost.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,116,50331648,0,0,0,0,116,2,1,0,0,0,0,0,0,2,2,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,16384,3260252783,2107733822,161646111,3961037800,172645501,4294967294,27910, diff --git a/tools/ctl/eq_iir_flat.txt b/tools/ctl/eq_iir_flat.txt deleted file mode 100644 index b62751a8d79f..000000000000 --- a/tools/ctl/eq_iir_flat.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,88,50331648,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,538145694,0,32690, diff --git a/tools/ctl/eq_iir_highpass_20hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_20hz_0db_48khz.txt deleted file mode 100644 index b8a91e11868f..000000000000 --- a/tools/ctl/eq_iir_highpass_20hz_0db_48khz.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3225193546,2143508228,537150400,3220666496,537150400,0,32690, diff --git a/tools/ctl/eq_iir_highpass_30hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_30hz_0db_48khz.txt deleted file mode 100644 index d5077e402bfd..000000000000 --- a/tools/ctl/eq_iir_highpass_30hz_0db_48khz.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,32690, diff --git a/tools/ctl/eq_iir_highpass_40hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_40hz_0db_48khz.txt deleted file mode 100644 index ebbd75c3c248..000000000000 --- a/tools/ctl/eq_iir_highpass_40hz_0db_48khz.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,0,32690, diff --git a/tools/ctl/eq_iir_highpass_50hz_0db_48khz.txt b/tools/ctl/eq_iir_highpass_50hz_0db_48khz.txt deleted file mode 100644 index 19d82f920b67..000000000000 --- a/tools/ctl/eq_iir_highpass_50hz_0db_48khz.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,88,50380800,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3231118179,2137545158,535660909,3223645479,535660909,0,32690, diff --git a/tools/ctl/eq_iir_loudness.txt b/tools/ctl/eq_iir_loudness.txt deleted file mode 100644 index 76a52301d281..000000000000 --- a/tools/ctl/eq_iir_loudness.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,204,50331648,0,0,0,0,204,4,2,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,538145694,0,32690,3,3,0,0,0,0,3237960220,2130690484,297056159,3694463533,303476880,0,16384,3302357025,2064935920,245217319,3776455865,274003881,0,16384,4106268671,4130185751,69182517,4179658584,365641401,4294967292,25468, diff --git a/tools/ctl/eq_iir_pass.txt b/tools/ctl/eq_iir_pass.txt deleted file mode 100644 index e8545206de29..000000000000 --- a/tools/ctl/eq_iir_pass.txt +++ /dev/null @@ -1 +0,0 @@ -4607827,0,88,50331648,0,0,0,0,88,2,1,0,0,0,0,4294967295,4294967295,1,1,0,0,0,0,0,0,0,0,538145694,0,32690, diff --git a/tools/ctl/ipc3/eq_fir/flat.txt b/tools/ctl/ipc3/eq_fir/flat.txt new file mode 100644 index 000000000000..ed8f327e17ee --- /dev/null +++ b/tools/ctl/ipc3/eq_fir/flat.txt @@ -0,0 +1 @@ +3,88,4607827,0,56,50450433,0,0,0,0,56,65538,0,0,0,0,0,4294901764,0,0,0,0,16384,0 diff --git a/tools/ctl/ipc3/eq_fir/loudness.txt b/tools/ctl/ipc3/eq_fir/loudness.txt new file mode 100644 index 000000000000..40cc0f19924e --- /dev/null +++ b/tools/ctl/ipc3/eq_fir/loudness.txt @@ -0,0 +1 @@ +3,616,4607827,0,584,50450433,0,0,0,0,584,131076,0,0,0,0,65537,65537,4294901764,0,0,0,0,16384,0,252,0,0,0,0,65537,65537,65537,65537,131073,131074,131074,196611,196611,262147,262148,327685,393221,393222,458759,524296,589833,655370,720907,786444,851981,983054,1048591,1179665,1245202,1376276,1507350,1638424,1769498,1966109,2162719,2359330,2621478,2818089,3080237,3407922,3670070,3997755,4325440,4718661,5046347,5505105,5963863,6422622,6815845,7274604,7733362,8192121,8781953,9568396,10420376,11272357,12058802,12976318,14155982,15335649,16056559,16515324,16711960,24117551,70844611,3920495315,3920522431,70845139,24117443,16711983,16515352,16056572,15335663,14156001,12976334,12058814,11272370,10420389,9568408,8781964,8192129,7733369,7274610,6815852,6422629,5963870,5505111,5046353,4718667,4325445,3997760,3670075,3407926,3080242,2818093,2621481,2359334,2162722,1966111,1769501,1638426,1507352,1376278,1245204,1179666,1048593,983055,851982,786445,720908,655371,589834,524297,458760,393223,393222,327685,262149,262148,196611,196611,131075,131074,131074,65537,65537,65537,65537,1,0 diff --git a/tools/ctl/ipc3/eq_fir/mid.txt b/tools/ctl/ipc3/eq_fir/mid.txt new file mode 100644 index 000000000000..3d1f8b502d51 --- /dev/null +++ b/tools/ctl/ipc3/eq_fir/mid.txt @@ -0,0 +1 @@ +3,160,4607827,0,128,50450433,0,0,0,0,128,65538,0,0,0,0,0,65576,0,0,0,0,1202154746,4222755303,3873958283,4024953600,4126012299,4176934804,4217764409,4250664050,4273864222,4288806716,2490349,6750285,8126582,7733371,6488174,4980824,3473472,2293804,1245211,1245197 diff --git a/tools/ctl/ipc3/eq_fir/pass.txt b/tools/ctl/ipc3/eq_fir/pass.txt new file mode 100644 index 000000000000..501ef2821697 --- /dev/null +++ b/tools/ctl/ipc3/eq_fir/pass.txt @@ -0,0 +1 @@ +3,88,4607827,0,56,50450433,0,0,0,0,56,65538,0,0,0,0,4294967295,4294901764,0,0,0,0,16384,0 diff --git a/tools/ctl/ipc3/eq_iir/bandpass.txt b/tools/ctl/ipc3/eq_iir/bandpass.txt new file mode 100644 index 000000000000..214dc382fd85 --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/bandpass.txt @@ -0,0 +1 @@ +3,148,4607827,0,116,50450433,0,0,0,0,116,2,1,0,0,0,0,0,0,2,2,0,0,0,0,3316150158,2048164275,513807534,3267352229,513807534,0,16384,3867454526,1191025347,38870735,77741469,38870735,4294967292,24197 diff --git a/tools/ctl/ipc3/eq_iir/bassboost.txt b/tools/ctl/ipc3/eq_iir/bassboost.txt new file mode 100644 index 000000000000..82e849f5603e --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/bassboost.txt @@ -0,0 +1 @@ +3,148,4607827,0,116,50450433,0,0,0,0,116,2,1,0,0,0,0,0,0,2,2,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,16384,3260252783,2107733822,161646111,3961037800,172645501,4294967294,27910 diff --git a/tools/ctl/ipc3/eq_iir/bundle.txt b/tools/ctl/ipc3/eq_iir/bundle.txt new file mode 100644 index 000000000000..ef8a861b777f --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/bundle.txt @@ -0,0 +1 @@ +3,440,4607827,0,408,50450433,0,0,0,0,408,2,5,0,0,0,0,2,2,1,1,0,0,0,0,0,0,0,0,538145694,0,32690,3,3,0,0,0,0,3237960220,2130690484,297056159,3694463533,303476880,0,16384,3302357025,2064935920,245217319,3776455865,274003881,0,16384,4106268671,4130185751,69182517,4179658584,365641401,4294967292,25468,2,2,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,16384,3260252783,2107733822,161646111,3961037800,172645501,4294967294,27910,2,2,0,0,0,0,3316150158,2048164275,513807534,3267352229,513807534,0,16384,3867454526,1191025347,38870735,77741469,38870735,4294967292,24197,1,1,0,0,0,0,3240919741,2127607086,533187596,3228592105,533187596,4294967292,20433 diff --git a/tools/ctl/ipc3/eq_iir/flat.txt b/tools/ctl/ipc3/eq_iir/flat.txt new file mode 100644 index 000000000000..25fc6796f600 --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/flat.txt @@ -0,0 +1 @@ +3,120,4607827,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,538145694,0,32690 diff --git a/tools/ctl/ipc3/eq_iir/highpass_20hz_0db_48khz.txt b/tools/ctl/ipc3/eq_iir/highpass_20hz_0db_48khz.txt new file mode 100644 index 000000000000..e642a5fc82b2 --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/highpass_20hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,4607827,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3225193546,2143508228,537150400,3220666496,537150400,0,32690 diff --git a/tools/ctl/ipc3/eq_iir/highpass_30hz_0db_48khz.txt b/tools/ctl/ipc3/eq_iir/highpass_30hz_0db_48khz.txt new file mode 100644 index 000000000000..4bc0d715fd96 --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/highpass_30hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,4607827,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,32690 diff --git a/tools/ctl/ipc3/eq_iir/highpass_40hz_0db_48khz.txt b/tools/ctl/ipc3/eq_iir/highpass_40hz_0db_48khz.txt new file mode 100644 index 000000000000..b132779d1ace --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/highpass_40hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,4607827,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,0,32690 diff --git a/tools/ctl/ipc3/eq_iir/highpass_50hz_0db_48khz.txt b/tools/ctl/ipc3/eq_iir/highpass_50hz_0db_48khz.txt new file mode 100644 index 000000000000..c25060036801 --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/highpass_50hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,4607827,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3231118179,2137545158,535660909,3223645479,535660909,0,32690 diff --git a/tools/ctl/ipc3/eq_iir/loudness.txt b/tools/ctl/ipc3/eq_iir/loudness.txt new file mode 100644 index 000000000000..1cf6a66fa25a --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/loudness.txt @@ -0,0 +1 @@ +3,236,4607827,0,204,50450433,0,0,0,0,204,4,2,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,538145694,0,32690,3,3,0,0,0,0,3237960220,2130690484,297056159,3694463533,303476880,0,16384,3302357025,2064935920,245217319,3776455865,274003881,0,16384,4106268671,4130185751,69182517,4179658584,365641401,4294967292,25468 diff --git a/tools/ctl/ipc3/eq_iir/pass.txt b/tools/ctl/ipc3/eq_iir/pass.txt new file mode 100644 index 000000000000..ce79acad80fd --- /dev/null +++ b/tools/ctl/ipc3/eq_iir/pass.txt @@ -0,0 +1 @@ +3,120,4607827,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,4294967295,4294967295,1,1,0,0,0,0,0,0,0,0,538145694,0,32690 diff --git a/tools/ctl/ipc4/drc/passthrough.txt b/tools/ctl/ipc4/drc/passthrough.txt new file mode 100644 index 000000000000..e650ab9a26e3 --- /dev/null +++ b/tools/ctl/ipc4/drc/passthrough.txt @@ -0,0 +1 @@ +3,140,877023059,0,108,50450433,0,0,0,0,108,0,0,0,0,0,3892314112,503316480,201326592,6442451,67748529,89478485,2030160,9723989,4285175934,33474947,575096676,24401431,7456540,4286019447,2062296,5,4423680,294359,2477728,622039,46513 diff --git a/tools/ctl/ipc4/drc/speaker_default.txt b/tools/ctl/ipc4/drc/speaker_default.txt new file mode 100644 index 000000000000..03d17e103040 --- /dev/null +++ b/tools/ctl/ipc4/drc/speaker_default.txt @@ -0,0 +1 @@ +3,140,877023059,0,108,50450433,0,0,0,0,108,0,0,0,0,1,3791650816,335544320,167772160,6442451,33954698,107374182,12228399,1969176,4292887072,5305422,137666458,81276115,7456540,4286019447,2062296,5,4423680,294359,2477728,622039,46513 diff --git a/tools/ctl/ipc4/eq_fir/flat.txt b/tools/ctl/ipc4/eq_fir/flat.txt new file mode 100644 index 000000000000..5fd026ca0c20 --- /dev/null +++ b/tools/ctl/ipc4/eq_fir/flat.txt @@ -0,0 +1 @@ +3,88,877023059,0,56,50450433,0,0,0,0,56,65538,0,0,0,0,0,4294901764,0,0,0,0,16384,0 diff --git a/tools/ctl/ipc4/eq_fir/loudness.txt b/tools/ctl/ipc4/eq_fir/loudness.txt new file mode 100644 index 000000000000..e5093f015b0e --- /dev/null +++ b/tools/ctl/ipc4/eq_fir/loudness.txt @@ -0,0 +1 @@ +3,616,877023059,0,584,50450433,0,0,0,0,584,131076,0,0,0,0,65537,65537,4294901764,0,0,0,0,16384,0,252,0,0,0,0,65537,65537,65537,65537,131073,131074,131074,196611,196611,262147,262148,327685,393221,393222,458759,524296,589833,655370,720907,786444,851981,983054,1048591,1179665,1245202,1376276,1507350,1638424,1769498,1966109,2162719,2359330,2621478,2818089,3080237,3407922,3670070,3997755,4325440,4718661,5046347,5505105,5963863,6422622,6815845,7274604,7733362,8192121,8781953,9568396,10420376,11272357,12058802,12976318,14155982,15335649,16056559,16515324,16711960,24117551,70844611,3920495315,3920522431,70845139,24117443,16711983,16515352,16056572,15335663,14156001,12976334,12058814,11272370,10420389,9568408,8781964,8192129,7733369,7274610,6815852,6422629,5963870,5505111,5046353,4718667,4325445,3997760,3670075,3407926,3080242,2818093,2621481,2359334,2162722,1966111,1769501,1638426,1507352,1376278,1245204,1179666,1048593,983055,851982,786445,720908,655371,589834,524297,458760,393223,393222,327685,262149,262148,196611,196611,131075,131074,131074,65537,65537,65537,65537,1,0 diff --git a/tools/ctl/ipc4/eq_fir/mid.txt b/tools/ctl/ipc4/eq_fir/mid.txt new file mode 100644 index 000000000000..36d74f693e46 --- /dev/null +++ b/tools/ctl/ipc4/eq_fir/mid.txt @@ -0,0 +1 @@ +3,160,877023059,0,128,50450433,0,0,0,0,128,65538,0,0,0,0,0,65576,0,0,0,0,1202154746,4222755303,3873958283,4024953600,4126012299,4176934804,4217764409,4250664050,4273864222,4288806716,2490349,6750285,8126582,7733371,6488174,4980824,3473472,2293804,1245211,1245197 diff --git a/tools/ctl/ipc4/eq_fir/pass.txt b/tools/ctl/ipc4/eq_fir/pass.txt new file mode 100644 index 000000000000..5decf09aed40 --- /dev/null +++ b/tools/ctl/ipc4/eq_fir/pass.txt @@ -0,0 +1 @@ +3,88,877023059,0,56,50450433,0,0,0,0,56,65538,0,0,0,0,4294967295,4294901764,0,0,0,0,16384,0 diff --git a/tools/ctl/ipc4/eq_iir/bandpass.txt b/tools/ctl/ipc4/eq_iir/bandpass.txt new file mode 100644 index 000000000000..3509ec8c7cf2 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/bandpass.txt @@ -0,0 +1 @@ +3,148,877023059,0,116,50450433,0,0,0,0,116,2,1,0,0,0,0,0,0,2,2,0,0,0,0,3316150158,2048164275,513807534,3267352229,513807534,0,16384,3867454526,1191025347,38870735,77741469,38870735,4294967292,24197 diff --git a/tools/ctl/ipc4/eq_iir/bassboost.txt b/tools/ctl/ipc4/eq_iir/bassboost.txt new file mode 100644 index 000000000000..8d96a8c7fc68 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/bassboost.txt @@ -0,0 +1 @@ +3,148,877023059,0,116,50450433,0,0,0,0,116,2,1,0,0,0,0,0,0,2,2,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,16384,3260252783,2107733822,161646111,3961037800,172645501,4294967294,27910 diff --git a/tools/ctl/ipc4/eq_iir/flat.txt b/tools/ctl/ipc4/eq_iir/flat.txt new file mode 100644 index 000000000000..cb78a292eda8 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/flat.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,538145694,0,32690 diff --git a/tools/ctl/ipc4/eq_iir/highpass_20hz_0db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_20hz_0db_48khz.txt new file mode 100644 index 000000000000..6d2ced3f43a3 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_20hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3225193546,2143508228,537150400,3220666496,537150400,0,32690 diff --git a/tools/ctl/ipc4/eq_iir/highpass_30hz_0db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_30hz_0db_48khz.txt new file mode 100644 index 000000000000..a87e38ddcbfa --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_30hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3227172081,2141520527,536653443,3221660410,536653443,0,32690 diff --git a/tools/ctl/ipc4/eq_iir/highpass_40hz_0db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_40hz_0db_48khz.txt new file mode 100644 index 000000000000..3aafc5060347 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_40hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,0,32690 diff --git a/tools/ctl/ipc4/eq_iir/highpass_40hz_20db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_40hz_20db_48khz.txt new file mode 100644 index 000000000000..4a4f1459a3ac --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_40hz_20db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,4294967292,20432 diff --git a/tools/ctl/ipc4/eq_iir/highpass_40hz_30db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_40hz_30db_48khz.txt new file mode 100644 index 000000000000..d997e8f3131b --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_40hz_30db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,4294967291,32305 diff --git a/tools/ctl/ipc4/eq_iir/highpass_40hz_40db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_40hz_40db_48khz.txt new file mode 100644 index 000000000000..082ed00b7e31 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_40hz_40db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3229146956,2139532835,536156946,3222653403,536156946,4294967289,25539 diff --git a/tools/ctl/ipc4/eq_iir/highpass_50hz_0db_48khz.txt b/tools/ctl/ipc4/eq_iir/highpass_50hz_0db_48khz.txt new file mode 100644 index 000000000000..b7822d4dc230 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/highpass_50hz_0db_48khz.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,0,0,1,1,0,0,0,0,3231118179,2137545158,535660909,3223645479,535660909,0,32690 diff --git a/tools/ctl/ipc4/eq_iir/loudness.txt b/tools/ctl/ipc4/eq_iir/loudness.txt new file mode 100644 index 000000000000..fed1b4f25578 --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/loudness.txt @@ -0,0 +1 @@ +3,236,877023059,0,204,50450433,0,0,0,0,204,4,2,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,538145694,0,32690,3,3,0,0,0,0,3237960220,2130690484,297056159,3694463533,303476880,0,16384,3302357025,2064935920,245217319,3776455865,274003881,0,16384,4106268671,4130185751,69182517,4179658584,365641401,4294967292,25468 diff --git a/tools/ctl/ipc4/eq_iir/pass.txt b/tools/ctl/ipc4/eq_iir/pass.txt new file mode 100644 index 000000000000..ee0d545ef39e --- /dev/null +++ b/tools/ctl/ipc4/eq_iir/pass.txt @@ -0,0 +1 @@ +3,120,877023059,0,88,50450433,0,0,0,0,88,2,1,0,0,0,0,4294967295,4294967295,1,1,0,0,0,0,0,0,0,0,538145694,0,32690 diff --git a/tools/debug_stream/debug_stream.py b/tools/debug_stream/debug_stream.py new file mode 100644 index 000000000000..39770cab4cd3 --- /dev/null +++ b/tools/debug_stream/debug_stream.py @@ -0,0 +1,628 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2024, Intel Corporation. + +""" +For receiving, decoding and printing debug-stream records over debug window slot. +""" + +import argparse +import ctypes +import time +import sys +import os + +import logging + +logging.basicConfig( + format="%(filename)s:%(lineno)s %(funcName)s: %(message)s", level=logging.WARNING +) + +DEBUG_STREAM_PAYLOAD_MAGIC = 0x1ED15EED +DEBUG_SLOT_SIZE = 4096 + +# TODO: python construct would probably be cleaner than ctypes structs + +class DebugStreamHdr(ctypes.Structure): + """ + Generic Debug-stream header + """ + + _fields_ = [ + ("magic", ctypes.c_uint), + ("hdr_size", ctypes.c_uint), + ] + + +class DebugStreamRecord(ctypes.Structure): + """ + Debug Stream record for passing debug data + """ + + _fields_ = [ + ("id", ctypes.c_uint), + ("seqno", ctypes.c_uint), + ("size_words", ctypes.c_uint), + ] + +class CPUInfo(ctypes.Structure): + """ + Thread Info record header + """ + + _pack_ = 1 + _fields_ = [ + ("hdr", DebugStreamRecord), + ("load", ctypes.c_ubyte), + ("thread_count", ctypes.c_ubyte), + ] + + +class ThreadInfo(ctypes.Structure): + """ + Thread specific data-record, the thread name string starts after name_len + """ + + _pack_ = 1 + _fields_ = [ + ("stack_usage", ctypes.c_ubyte), + ("cpu_load", ctypes.c_ubyte), + ("name_len", ctypes.c_ubyte), + ] + + +class TextMsg(ctypes.Structure): + """ + Text Msg record header + """ + + _pack_ = 1 + _fields_ = [ + ("hdr", DebugStreamRecord), + ] + + +WSIZE = ctypes.sizeof(ctypes.c_uint) + + +class RecordPrinter: + """ + Debug Stream record decoder and printer class + """ + + RECORD_ID_UNINITIALIZED = 0 + RECORD_ID_THREAD_INFO = 1 + RECORD_ID_TEXT_MSG = 2 + + def print_record(self, record, cpu): + """prints debug-stream record""" + recp = ctypes.cast(record, ctypes.POINTER(DebugStreamRecord)) + logging.debug( + "rec: %u %u %u", recp.contents.id, recp.contents.seqno, recp.contents.size_words + ) + if recp.contents.id == self.RECORD_ID_THREAD_INFO: + return self.print_thread_info(record, cpu) + if recp.contents.id == self.RECORD_ID_TEXT_MSG: + return self.print_text_msg(record, cpu) + logging.warning("cpu %u: Unsupported record type %u", cpu, recp.contents.id) + return True + + def print_thread_info(self, record, cpu): + """prints thread-info record""" + remlen = len(record) - ctypes.sizeof(CPUInfo) + if remlen < 0: + logging.info("Buffer end reached, parsing failed") + return False + cpup = ctypes.cast(record, ctypes.POINTER(CPUInfo)) + print( + "CPU %u: Load: %02.1f%% %u threads (seqno %u)" + % ( + cpu, + cpup.contents.load / 2.55, + cpup.contents.thread_count, + cpup.contents.hdr.seqno, + ) + ) + remain = (ctypes.c_ubyte * (len(record) - ctypes.sizeof(CPUInfo))).from_address( + ctypes.addressof(record) + ctypes.sizeof(CPUInfo) + ) + for i in range(cpup.contents.thread_count): + remlen = remlen - ctypes.sizeof(ThreadInfo) + if remlen < 0: + logging.info("Buffer end reached, parsing failed on %u thread field", i) + return False + threadp = ctypes.cast(remain, ctypes.POINTER(ThreadInfo)) + remain = ( + ctypes.c_ubyte * (len(remain) - ctypes.sizeof(ThreadInfo)) + ).from_address(ctypes.addressof(remain) + ctypes.sizeof(ThreadInfo)) + remlen = remlen - threadp.contents.name_len + if remlen < 0: + logging.info("Buffer end reached, parsing failed on %u thread field", i) + return False + name = bytearray(remain[: threadp.contents.name_len]).decode("utf-8") + remain = ( + ctypes.c_ubyte * (len(remain) - threadp.contents.name_len) + ).from_address(ctypes.addressof(remain) + threadp.contents.name_len) + print( + " %-20s stack %02.1f%%\tload %02.1f%%" + % ( + name, + threadp.contents.stack_usage / 2.55, + threadp.contents.cpu_load / 2.55, + ) + ) + return True + + def print_text_msg(self, record, cpu): + """prints text-msg record""" + if len(record) - ctypes.sizeof(TextMsg) < 0: + logging.info("Buffer end reached, parsing failed") + return False + buffer = ( + ctypes.c_ubyte * (len(record) - ctypes.sizeof(TextMsg)) + ).from_address(ctypes.addressof(record) + ctypes.sizeof(TextMsg)) + payload = bytes(buffer) + msg = payload.split(b"\0", 1)[0].decode("utf-8", errors="replace") + print("CPU %u:\n%s" % (cpu, msg)) + return True + +class DebugStreamSectionDescriptor(ctypes.Structure): + """ + Describes CPU specific circular buffers + """ + + _fields_ = [ + ("core_id", ctypes.c_uint), + ("buf_words", ctypes.c_uint), + ("offset", ctypes.c_uint), + ] + + +class DebugStreamSlotHdr(ctypes.Structure): + """ + Debug Slot transport specific Debug Stream header, padded to cache line + """ + + _fields_ = [ + ("hdr", DebugStreamHdr), + ("total_size", ctypes.c_uint), + ("num_sections", ctypes.c_uint), + ] + + +class CircularBufHdr(ctypes.Structure): + """ + Live data header for CPU specific circular buffer + """ + + _fields_ = [ + ("next_seqno", ctypes.c_uint), + ("w_ptr", ctypes.c_uint), + ] + + +class CircularBufferDecoder: + """ + Class for extracting records from circular buffer + """ + + desc = None + boffset = None + buf_words = None + cpu = None + printer = None + prev_w_ptr = 0 + prev_seqno = None + error_count = 0 + + def __init__(self, desc, cpu, printer): + self.desc = desc + self.boffset = desc.offset + ctypes.sizeof(CircularBufHdr) + self.buf_words = desc.buf_words + self.cpu = cpu + self.printer = printer + logging.debug( + "boffset %u buf_words %u cpu %u", self.boffset, self.buf_words, self.cpu + ) + + def get_hdr(self, slot, pos): + """ + Get record header from position (handles circular buffer wrap) + """ + if pos >= self.buf_words: + logging.warning("Bad position %u", pos) + return None + hdr_size = ctypes.sizeof(DebugStreamRecord) + hdr_words = hdr_size // WSIZE + if pos + hdr_words > self.buf_words: + hdr = (ctypes.c_ubyte * hdr_size)() + size1 = (self.buf_words - pos) * WSIZE + size2 = hdr_size - size1 + pos1 = self.boffset + pos * WSIZE + pos2 = self.boffset + logging.debug( + "Wrapped header %u %u %u %u", pos, hdr_words, self.buf_words, size1 + ) + + hdr[0:size1] = slot[pos1 : pos1 + size1] + hdr[size1:hdr_size] = slot[pos2 : pos2 + size2] + header = ctypes.cast(hdr, ctypes.POINTER(DebugStreamRecord)).contents + else: + header = ctypes.cast( + slot[self.boffset + pos * WSIZE :], ctypes.POINTER(DebugStreamRecord) + ).contents + if header.id > 100 or header.size_words >= self.buf_words: + logging.info( + "Broken record id %u seqno %u size %u", + header.id, + header.seqno, + header.size_words, + ) + return None + return header + + def get_record(self, slot, pos, seqno): + """ + Get record from position + """ + rec = self.get_hdr(slot, pos) + if rec is None or rec.size_words == 0: + return None + logging.debug( + "got header at pos %u rec %u %u %u", pos, rec.id, rec.seqno, rec.size_words + ) + if seqno is not None and rec.seqno != seqno: + logging.warning( + "Record seqno mismatch %u != %u, pos %u size %u", + rec.seqno, + seqno, + pos, + rec.size_words, + ) + self.error_count = self.error_count + 1 + return None + rwords = rec.size_words + rsize = rec.size_words * WSIZE + if pos + rwords > self.buf_words: + record = (ctypes.c_ubyte * rsize)() + size1 = (self.buf_words - pos) * WSIZE + size2 = rsize - size1 + pos1 = self.boffset + pos * WSIZE + pos2 = self.boffset + logging.debug( + "Wrapped record %u %u %u %u", pos, rsize, self.buf_words, size1 + ) + + record[0:size1] = slot[pos1 : pos1 + size1] + record[size1:rsize] = slot[pos2 : pos2 + size2] + else: + record = (ctypes.c_ubyte * rsize).from_buffer_copy( + slot, self.boffset + pos * WSIZE + ) + logging.info("got %u", rec.seqno) + self.error_count = 0 + return record + + def catch_up(self, slot): + """ + Search backwards from w_ptr for valid records + """ + circ = CircularBufHdr.from_buffer_copy(slot, self.desc.offset) + if circ.next_seqno == 0 or circ.w_ptr >= self.buf_words: + return + self.decode_past_records(slot, circ.w_ptr, circ.next_seqno) + self.prev_w_ptr = circ.w_ptr + self.prev_seqno = circ.next_seqno - 1 + logging.debug("seqno %u w_ptr %u", self.prev_seqno, self.prev_w_ptr) + + def decode_past_records(self, slot, pos, seqno): + """ + Decode records backwards from pos. Should not be called directly, use catch_up() + """ + if self.prev_seqno is not None and self.prev_seqno >= seqno - 1: + return + if pos == 0: + spos = self.buf_words - 1 + else: + spos = pos - 1 + bsize = ctypes.cast( + slot[self.boffset + spos * 4 :], ctypes.POINTER(ctypes.c_uint) + ).contents.value + bpos = pos - bsize + if bpos < 0: + bpos = self.buf_words + pos - bsize + rec = self.get_hdr(slot, bpos) + if rec == None: + return + if bsize != rec.size_words: + return + if seqno is not None: + if rec.seqno != seqno - 1: + return + else: + seqno = rec.seqno + 1 + + self.decode_past_records(slot, bpos, seqno - 1) + + record = self.get_record(slot, bpos, seqno - 1) + if record is not None: + if not self.printer.print_record(record, self.cpu): + logging.info("Parse failed on record %u", seqno - 1) + logging.info("Printing %u success", seqno - 1) + else: + logging.info("Broken record %u", seqno - 1) + + def get_next_record(self, slot): + """ + Get next record from the circular buffer and print it, returns True if a record + with expected seqno number was found and successfully decoded and printed. + """ + if self.prev_seqno is not None: + record = self.get_record(slot, self.prev_w_ptr, self.prev_seqno + 1) + else: + record = self.get_record(slot, self.prev_w_ptr, None) + if record is not None: + print_success = self.printer.print_record(record, self.cpu) + if print_success: + recp = ctypes.cast(record, ctypes.POINTER(DebugStreamRecord)) + self.prev_w_ptr = ( + self.prev_w_ptr + recp.contents.size_words + ) % self.buf_words + self.prev_seqno = recp.contents.seqno + else: + logging.info("Parse failed on record %u", self.prev_seqno + 1) + return print_success + self.error_count = self.error_count + 1 + logging.info("Record decoding failed %u", self.error_count) + return False + + def poll_buffer(self, slot): + """ + Poll for new records. If there were new records return True + """ + circ = CircularBufHdr.from_buffer_copy(slot, self.desc.offset) + if self.prev_w_ptr == circ.w_ptr: + return False + got_record = True + while self.prev_w_ptr != circ.w_ptr and got_record: + got_record = self.get_next_record(slot) + return True + + def check_error_count(self): + """ + Check if maximum error count was reached + """ + if self.error_count > 3: + return True + return False + + +class DebugStreamDecoder: + """ + Class for decoding debug-stream slot contents + """ + + file_size = DEBUG_SLOT_SIZE + file = None + slot = None + descs = [] + circdec = [] + rec_printer = RecordPrinter() + + def set_file(self, file): + """ + Ser file to read the slot contents from + """ + self.file = file + + def update_slot(self): + """ + Update slot contents + """ + self.file.seek(0) + self.slot = self.file.read(self.file_size) + + def set_slot(self, buf): + """ + Update slot contents + """ + self.slot = buf + + def get_descriptors(self): + """ + Read the core specific descriptors and initialize core + specific circular buffer decoders. + + """ + if self.slot is None: + return False + hdr = ctypes.cast(self.slot, ctypes.POINTER(DebugStreamSlotHdr)) + if hdr.contents.hdr.magic != DEBUG_STREAM_PAYLOAD_MAGIC: + logging.info("Debug Slot has bad magic 0x%08x", hdr.contents.hdr.magic) + return False + num_sections = hdr.contents.num_sections + if num_sections == len(self.descs): + return True + if num_sections > 32: + logging.info("Suspiciously many sections %u", num_sections) + return False + hsize = ctypes.sizeof(DebugStreamSlotHdr) + self.descs = (DebugStreamSectionDescriptor * num_sections).from_buffer_copy( + self.slot, hsize + ) + for i in range(len(self.descs)): + if (self.descs[i].core_id > 32 or + self.descs[i].buf_words > DEBUG_SLOT_SIZE // WSIZE or + self.descs[i].offset > DEBUG_SLOT_SIZE): + logging.info("Suspicious descriptor %u values %u %u %u", i, + self.descs[i].core_id, self.descs[i].buf_words, + self.descs[i].offset) + return False + self.circdec = [ + CircularBufferDecoder(self.descs[i], i, self.rec_printer) + for i in range(len(self.descs)) + ] + logging.info( + "Header hdr_size %u total_size %u num_sections %u", + hdr.contents.hdr.hdr_size, + hdr.contents.total_size, + hdr.contents.num_sections, + ) + return True + + def catch_up_all(self): + """ + Checks all circular buffers if there is records behind w_ptr. If there + is valid seqno number available the decoding stops when there previous + printed record is reached. + """ + if len(self.descs) == 0 or self.slot is None: + return + for i in range(len(self.descs)): + self.circdec[i].catch_up(self.slot) + + def poll(self): + """ + Poll all circular buffers for more records. Returns True if nothing new + was found and its time to go to sleep. + """ + if len(self.descs) == 0 or self.slot is None: + return False + sleep = True + for i in range(len(self.descs)): + if self.circdec[i].poll_buffer(self.slot): + sleep = False + return sleep + + def check_slot(self): + """ + Check if previously updated slot contents is valid + """ + hdr = ctypes.cast(self.slot, ctypes.POINTER(DebugStreamSlotHdr)) + if hdr.contents.hdr.magic != DEBUG_STREAM_PAYLOAD_MAGIC: + self.slot = None + return False + if hdr.contents.num_sections != len(self.descs): + self.slot = None + return False + for i in range(len(self.descs)): + if self.circdec[i].check_error_count(): + self.circdec[i] = CircularBufferDecoder( + self.descs[i], i, self.rec_printer + ) + return True + + def reset(self): + """ + Reset decoder + """ + self.file = None + self.slot = None + +def cavstool_main_loop(my_args): + import cavstool + try: + (hda, sd, dsp, hda_ostream_id) = cavstool.map_regs(True) + except Exception as e: + logging.error("Could not map device in sysfs; run as root?") + logging.error(e) + sys.exit(1) + ADSP_DW_SLOT_DEBUG_STREAM = 0x53523134 + decoder = DebugStreamDecoder() + while True: + if not cavstool.fw_is_alive(dsp): + cavstool.wait_fw_entered(dsp, timeout_s=None) + if my_args.direct_access_slot < 0: + offset = cavstool.debug_slot_offset_by_type(ADSP_DW_SLOT_DEBUG_STREAM, timeout_s=0.5) + if offset is None: + logging.error("Could not find debug_stream slot") + sys.exit(1) + logging.info("Got offset 0x%08x by type 0x%08x", offset, + ADSP_DW_SLOT_DEBUG_STREAM) + else: + offset = cavstool.debug_slot_offset(my_args.direct_access_slot) + buf = cavstool.win_read(offset, 0, DEBUG_SLOT_SIZE) + decoder.set_slot(buf) + if not decoder.get_descriptors(): + time.sleep(my_args.update_interval) + continue + decoder.catch_up_all() + while True: + if decoder.poll(): + time.sleep(my_args.update_interval) + buf = cavstool.win_read(offset, 0, DEBUG_SLOT_SIZE) + decoder.set_slot(buf) + if not decoder.check_slot(): + break + +def main_f(my_args): + """ + Open debug stream slot file and pass it to decoder + + This tool and the protocol it implements is for debugging and optimized + to interfere with SOF DSP as little as possible, but not worrying too much + about the host CPU load. That is why there where no synchronous mechanism + done and the host simply polls for new records. + """ + if my_args.direct_access_slot >= 0 or not os.path.isfile(my_args.debugstream_file): + return cavstool_main_loop(my_args) + decoder = DebugStreamDecoder() + prev_error = None + while True: + try: + with open(my_args.debugstream_file, "rb") as file: + decoder.set_file(file) + decoder.update_slot() + if not decoder.get_descriptors(): + time.sleep(my_args.update_interval) + continue + decoder.catch_up_all() + while True: + if decoder.poll(): + time.sleep(my_args.update_interval) + decoder.update_slot() + if not decoder.check_slot(): + break + + except FileNotFoundError: + print(f"File {my_args.debugstream_file} not found!") + break + except OSError as err: + if str(err) != prev_error: + print(f"Open {my_args.debugstream_file} failed '{err}'") + prev_error = str(err) + decoder.reset() + time.sleep(args.update_interval) + + +def parse_params(): + """Parses parameters""" + parser = argparse.ArgumentParser(description="SOF DebugStream thread info client. ") + parser.add_argument( + "-t", + "--update-interval", + type=float, + help="Telemetry2 window polling interval in seconds, default 1", + default=0.01, + ) + parser.add_argument( + "-f", + "--debugstream-file", + help="File to read the DebugStream data from, default /sys/kernel/debug/sof/debug_stream", + default="/sys/kernel/debug/sof/debug_stream", + ) + parser.add_argument( + "-c", + "--direct-access-slot", + help="Access specified debug window slot directly, no need for debugfs file", + type=int, + default=-1, + ) + parsed_args = parser.parse_args() + return parsed_args + + +if __name__ == "__main__": + args = parse_params() + main_f(args) diff --git a/tools/demo-gui/README-dev.md b/tools/demo-gui/README-dev.md new file mode 100644 index 000000000000..455d3bf6b582 --- /dev/null +++ b/tools/demo-gui/README-dev.md @@ -0,0 +1,40 @@ +## Developing sof-gui and tui + +The architecture of the SOF UIs is simple, and designed to make implementing new features extremely easy. + +Controller engine "sof_controller_engine.py", that handles all interaction with Linux and SOF. + +GUI "sof_demo_gui.py", links a GTK gui with the controller engine. + +TUI "sof_demo_tui.py", links a text UI to the controller engine. + +eq_configs and audios folders to contain example audios and EQ commands. + +Pipeline within topology folder, named: +```sof-<hardware-name>-gui-components-wm8960.tplg``` + +## Adding a new component to the UIs + +There are three main things that need to be edited to add a new component: + +### Controller engine + +Provide required sof_ctl calls and other necessary logic to control the component. Update execute_command to contain the desired commands. Ensure that autodetection is used for commands so that the implementation is generic. + +### GUI and TUI + +Add new buttons to the init method or gui that provide the needed functionality for the component. These should be designed to call methods in controller engine that will then interact with SOF and Linux + +### Pipeline + +See relevant documentation for pipeline development. Ensure any control needed is exposed through the pipeline. Also ensure the pipeline is set to build for your target HW within the cmakefiles. + +## Next steps for overall UI development + +Add DRC and other base level SOF components. + +Add real time EQ config generation, so the user could control low, mid, and high controls in real time. This would require a new EQ component that supports smooth real time control. + +Add graphics and other quality of life functions to the GUI. + +Create a version of sof-ctl that provides direct Python bindings to communicate with SOF components, rather than needing a Linux command. diff --git a/tools/demo-gui/README.md b/tools/demo-gui/README.md new file mode 100644 index 000000000000..279937dfa0aa --- /dev/null +++ b/tools/demo-gui/README.md @@ -0,0 +1,37 @@ +## sof-demo-gui + +### sof-demo-gui.py - sof-demo-tui.py +User input logic and display handling + +### sof-controller-engine +Controller to abstract the GUI and TUI control. + +Handles the linking of user input and sof_ctl generically of the control type. + +### How to use the interfaces + +Build sof-ctl for target and copy it to the gui folder base directory within your local repo. + +If you have audio on your local machine that you wish to demonstrate using the GUI, add it to the audios subfolder. +Also, you can specify audio paths on the target with the command line arg --audio-path "path" + +If you would like to include eq configs, they are stored in tools/ctl/ipc3. Copy them from there to the eq_configs folder. + +Copy entire GUI folder to target hardware. + +Next, ensure that the +```sof-<hardware-name>-gui-components-wm8960.tplg``` +is built and loaded as SOF's topology. Make sure this is built for your target hardware. + +After this, run either the GUI or TUI on a board with SOF loaded. This can be done using the command: +```python3 sof-demo-gui``` +or +```python3 sof-demo-tui``` + +The interfaces themselves are self-explanatory, as they are made to be plug and play on all SOF supporting systems. + +The features currently supported are: +Playback and Record with ALSA +Volume control using the SOF component +EQ component with realtime control +Generic implementation with autodetection of SOF cards and commands diff --git a/tools/demo-gui/demo-gui/sof_controller_engine.py b/tools/demo-gui/demo-gui/sof_controller_engine.py new file mode 100644 index 000000000000..c1dd6c1d9294 --- /dev/null +++ b/tools/demo-gui/demo-gui/sof_controller_engine.py @@ -0,0 +1,243 @@ +# SPDX-License-Identifier: BSD-3-Clause + +import subprocess +import os +import signal +import re +import math + +# Global variables +aplay_process = None +arecord_process = None +paused = None +current_file = None +device_string = None +volume_control = None +eq_numid = None +is_muted = False +previous_volume = 50 # Store the previous volume level +extra_audio_paths = [] + +def initialize_device(): + global device_string, volume_control, eq_numid + + try: + output = subprocess.check_output(["aplay", "-l"], text=True, stderr=subprocess.DEVNULL) + match = re.search(r"card (\d+):.*\[.*sof.*\]", output, re.IGNORECASE) + if match: + card_number = match.group(1) + device_string = f"hw:{card_number}" + print(f"Detected SOF card: {device_string}") + else: + raise RuntimeError("SOF card not found. Ensure the device is connected and recognized by the system.") + + controls_output = subprocess.check_output(["amixer", f"-D{device_string}", "controls"], text=True, stderr=subprocess.DEVNULL) + volume_match = re.search(r"numid=(\d+),iface=MIXER,name='(.*Master Playback Volume.*)'", controls_output) + if volume_match: + volume_control = volume_match.group(2) + print(f"Detected Volume Control: {volume_control}") + else: + raise RuntimeError("Volume control not found.") + + eq_match = re.search(r"numid=(\d+),iface=MIXER,name='EQIIR1\.0 eqiir_coef_1'", controls_output) + if eq_match: + eq_numid = eq_match.group(1) + print(f"Detected EQ numid: {eq_numid}") + else: + raise RuntimeError("EQ control not found.") + + except subprocess.CalledProcessError as e: + print(f"Failed to run device detection commands: {e}") + raise + except RuntimeError as e: + print(e) + raise + +def scale_volume(user_volume): + normalized_volume = user_volume / 100.0 + scaled_volume = 31 * math.sqrt(normalized_volume) + return int(round(scaled_volume)) + +def scan_for_files(directory_name: str, file_extension: str, extra_paths: list = None): + found_files = [] + dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), directory_name) + + try: + if os.path.exists(dir_path): + found_files.extend([f for f in os.listdir(dir_path) if f.endswith(file_extension)]) + else: + print(f"Error: The '{directory_name}' directory is missing. It should be located in the same folder as this script.") + + if extra_paths: + for path in extra_paths: + if os.path.exists(path): + found_files.extend([f for f in os.listdir(path) if f.endswith(file_extension)]) + else: + print(f"Warning: The directory '{path}' does not exist.") + except Exception as e: + print(f"Error scanning for files: {e}") + + return found_files + +def execute_command(command: str, data: int = 0, file_name: str = None): + if device_string is None or volume_control is None or eq_numid is None: + raise RuntimeError("Device not initialized. Call initialize_device() first.") + + command_switch = { + 'volume': lambda x: handle_volume(data), + 'eq': lambda x: handle_eq(file_name), + 'play': lambda x: handle_play(file_name), + 'pause': lambda x: handle_pause(), + 'stop': lambda x: handle_stop(), + 'mute': lambda x: handle_mute(), + 'record': lambda x: handle_record(start=data, filename=file_name) + } + + command_function = command_switch.get(command, lambda x: handle_unknown_command(data)) + try: + command_function(data) + except Exception as e: + print(f"Error executing command '{command}': {e}") + +def handle_volume(data: int): + amixer_command = f"amixer -D{device_string} cset name='{volume_control}' {data}" + try: + subprocess.run(amixer_command, shell=True, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + print(f"Failed to set volume: {e}") + +def handle_eq(eq_file_name: str): + if not eq_file_name: + print("No EQ file name provided.") + return + + ctl_command = f"./sof-ctl -D{device_string} -n {eq_numid} -s {eq_file_name}" + try: + subprocess.run(ctl_command, shell=True, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + print(f"Failed to apply EQ settings: {e}") + +def handle_play(play_file_name: str): + global aplay_process, paused, current_file + + if not play_file_name: + print("No file name provided for playback.") + return + + try: + if paused and current_file == play_file_name: + os.kill(aplay_process.pid, signal.SIGCONT) + print("Playback resumed.") + paused = False + return + + if aplay_process is not None: + if aplay_process.poll() is None: + if current_file == play_file_name: + print("Playback is already in progress.") + return + else: + os.kill(aplay_process.pid, signal.SIGKILL) + print("Stopping current playback to play a new file.") + else: + print("Previous process is not running, starting new playback.") + + default_audio_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'audios') + file_path = next((os.path.join(path, play_file_name) for path in [default_audio_dir] + extra_audio_paths if os.path.exists(os.path.join(path, play_file_name))), None) + + if file_path is None: + print(f"Error: File '{play_file_name}' not found in the default 'audios' directory or any provided paths.") + return + + aplay_command = f"aplay -D{device_string} '{file_path}'" + aplay_process = subprocess.Popen(aplay_command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + current_file = play_file_name + print(f"Playing file: {play_file_name}.") + paused = False + except subprocess.CalledProcessError as e: + print(f"Failed to play file: {e}") + except Exception as e: + print(f"Error during playback: {e}") + +def handle_pause(): + global aplay_process, paused + + if aplay_process is None: + print("No playback process to pause.") + return + + if aplay_process.poll() is not None: + print("Playback process has already finished.") + return + + try: + os.kill(aplay_process.pid, signal.SIGSTOP) + paused = True + print("Playback paused.") + except Exception as e: + print(f"Failed to pause playback: {e}") + +def handle_stop(): + global aplay_process, paused, current_file + + if aplay_process is None: + print("No playback process to stop.") + return + + if aplay_process.poll() is not None: + print("Playback process has already finished.") + return + + try: + os.kill(aplay_process.pid, signal.SIGKILL) + aplay_process = None + paused = False + current_file = None + print("Playback stopped.") + except Exception as e: + print(f"Failed to stop playback: {e}") + +def handle_mute(): + if not is_muted: + previous_volume = scale_volume(50) # Assume 50 is the current volume + handle_volume(0) + is_muted = True + print("Audio muted.") + else: + handle_volume(previous_volume) + is_muted = False + print("Audio unmuted.") + +def handle_record(start: bool, filename: str): + global arecord_process + + if start: + if arecord_process is not None and arecord_process.poll() is None: + print("Recording is already in progress.") + return + + if not filename: + print("No filename provided for recording.") + return + + record_command = f"arecord -D{device_string} -f cd -t wav {filename}" + try: + arecord_process = subprocess.Popen(record_command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + print(f"Started recording: {filename}") + except subprocess.CalledProcessError as e: + print(f"Failed to start recording: {e}") + + else: + if arecord_process is None or arecord_process.poll() is not None: + print("No recording process to stop.") + return + + try: + os.kill(arecord_process.pid, signal.SIGINT) + arecord_process = None + print("Stopped recording.") + except Exception as e: + print(f"Failed to stop recording: {e}") + +def handle_unknown_command(data: int): + print(f"Unknown command: {data}") diff --git a/tools/demo-gui/demo-gui/sof_demo_gui.py b/tools/demo-gui/demo-gui/sof_demo_gui.py new file mode 100644 index 000000000000..3f18287adf2a --- /dev/null +++ b/tools/demo-gui/demo-gui/sof_demo_gui.py @@ -0,0 +1,257 @@ +# SPDX-License-Identifier: BSD-3-Clause + +import gi +import os +import argparse +import sof_controller_engine as sof_ctl +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk, Gdk + +class MyWindow(Gtk.Window): + def __init__(self, audio_paths, config_paths): + super().__init__(title="SOF Demo Gui") + self.set_resizable(False) + self.set_border_width(10) + self.apply_css() + self.init_ui(audio_paths, config_paths) + sof_ctl.initialize_device() + self.is_muted = False + self.previous_volume = 50 # Store the previous volume level + + def apply_css(self): + css_provider = Gtk.CssProvider() + css = """ + * { + font-family: "Segoe UI", "Arial", sans-serif; + font-size: 14px; + color: #020202; + } + window { + background-color: #2C3E50; + } + frame { + border: 1px solid #34495E; + border-radius: 5px; + padding: 10px; + margin: 5px; + background-color: #34495E; + } + button, togglebutton { + background-color: #3b3b3b; + border: none; + padding: 10px; + color: #020202; + } + button:hover, togglebutton:hover { + background-color: #A9A9A9; + color: #020202; + } + togglebutton:checked { + background-color: #A9A9A9; + color: #020202; + } + scale { + background-color: #34495E; + border-radius: 5px; + color: #FFFFFF; + } + label { + color: #020202; + } + headerbar { + background-color: #2C3E50; + color: #FFFFFF; + } + headerbar.titlebar { + background-color: #2C3E50; + } + """ + css_provider.load_from_data(css.encode('utf-8')) + screen = Gdk.Screen.get_default() + Gtk.StyleContext.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) + + def init_ui(self, audio_paths, config_paths): + main_grid = Gtk.Grid() + main_grid.set_row_spacing(10) + main_grid.set_column_spacing(10) + self.add(main_grid) + + control_frame = self.create_control_frame() + main_grid.attach(control_frame, 0, 0, 1, 1) + + file_frame = self.create_file_frame() + main_grid.attach(file_frame, 0, 1, 1, 1) + + record_frame = self.create_record_frame() + main_grid.attach(record_frame, 0, 2, 1, 1) + + self.scan_and_populate_dropdowns(audio_paths, config_paths) + + def create_control_frame(self): + control_frame = Gtk.Frame(label="Playback and Volume Control") + control_grid = Gtk.Grid() + control_grid.set_row_spacing(10) + control_grid.set_column_spacing(10) + control_frame.add(control_grid) + + volume_adjustment = Gtk.Adjustment(value=100, lower=0, upper=100, step_increment=1, page_increment=5, page_size=0) + self.volume_button = Gtk.Scale(name="volume", orientation=Gtk.Orientation.HORIZONTAL, adjustment=volume_adjustment) + self.volume_button.set_digits(0) + self.volume_button.set_hexpand(True) + self.volume_button.connect("value-changed", self.on_volume_changed) + control_grid.attach(self.volume_button, 0, 0, 2, 1) + + self.play_pause_button = Gtk.ToggleButton(label="Play") + self.play_pause_button.connect("toggled", self.on_play_pause_toggled) + control_grid.attach(self.play_pause_button, 0, 1, 1, 1) + + self.stop_button = Gtk.Button(label="Stop") + self.stop_button.connect("clicked", self.on_stop_clicked) + control_grid.attach(self.stop_button, 1, 1, 1, 1) + + self.mute_button = Gtk.Button(label="Mute") + self.mute_button.connect("clicked", self.on_mute_clicked) + control_grid.attach(self.mute_button, 0, 2, 2, 1) + + return control_frame + + def create_file_frame(self): + file_frame = Gtk.Frame(label="File Selection") + file_grid = Gtk.Grid() + file_grid.set_row_spacing(10) + file_grid.set_column_spacing(10) + file_frame.add(file_grid) + + self.wav_dropdown = Gtk.ComboBoxText() + self.wav_dropdown.connect("changed", self.on_wav_file_selected) + wav_label = Gtk.Label(label="Select WAV File") + wav_label.set_margin_top(5) + wav_label.set_margin_bottom(5) + file_grid.attach(wav_label, 0, 0, 1, 1) + file_grid.attach(self.wav_dropdown, 1, 0, 1, 1) + + self.eq_dropdown = Gtk.ComboBoxText() + eq_label = Gtk.Label(label="Select EQ Config") + eq_label.set_margin_top(5) + eq_label.set_margin_bottom(5) + file_grid.attach(eq_label, 0, 1, 1, 1) + file_grid.attach(self.eq_dropdown, 1, 1, 1, 1) + + self.apply_eq_button = Gtk.Button(label="Apply EQ Config") + self.apply_eq_button.connect("clicked", self.on_apply_eq_clicked) + file_grid.attach(self.apply_eq_button, 1, 2, 1, 1) + + return file_frame + + def create_record_frame(self): + record_frame = Gtk.Frame(label="Recording Control") + record_grid = Gtk.Grid() + record_grid.set_row_spacing(10) + record_grid.set_column_spacing(10) + record_grid.set_hexpand(True) + record_grid.set_vexpand(True) + record_frame.add(record_grid) + + self.record_button = Gtk.ToggleButton(label="Record") + self.record_button.connect("toggled", self.on_record_toggled) + self.record_button.set_hexpand(True) + self.record_button.set_vexpand(True) + record_grid.attach(self.record_button, 0, 0, 1, 1) + + self.record_index = 1 + + return record_frame + + def scan_and_populate_dropdowns(self, audio_paths, config_paths): + wav_files = sof_ctl.scan_for_files('audios', '.wav', extra_paths=audio_paths) + + self.wav_dropdown.remove_all() + for wav_file in wav_files: + self.wav_dropdown.append_text(wav_file) + + if wav_files: + self.wav_dropdown.set_active(0) + self.selected_wav_file = wav_files[0] + + eq_files = sof_ctl.scan_for_files('eq_configs', '.txt', extra_paths=config_paths) + + self.eq_dropdown.remove_all() + for eq_file in eq_files: + self.eq_dropdown.append_text(eq_file) + + if eq_files: + self.eq_dropdown.set_active(0) + self.selected_eq_file = eq_files[0] + + def on_volume_changed(self, widget): + user_volume = widget.get_value() + scaled_volume = sof_ctl.scale_volume(user_volume) + sof_ctl.execute_command(command="volume", data=scaled_volume) + + def on_play_pause_toggled(self, widget): + if widget.get_active(): + widget.set_label("Pause") + sof_ctl.execute_command(command="play", file_name=self.selected_wav_file) + else: + widget.set_label("Play") + sof_ctl.execute_command(command="pause") + + def on_stop_clicked(self, widget): + self.play_pause_button.set_active(False) + sof_ctl.execute_command(command="stop") + + def on_mute_clicked(self, widget): + if not self.is_muted: + self.previous_volume = self.volume_button.get_value() + self.volume_button.set_value(0) + self.is_muted = True + widget.set_label("Unmute") + else: + self.volume_button.set_value(self.previous_volume) + self.is_muted = False + widget.set_label("Mute") + + def on_record_toggled(self, widget): + if widget.get_active(): + widget.set_label("Stop Recording") + filename = self.generate_sequential_filename() + sof_ctl.execute_command(command="record", data=True, file_name=filename) + else: + widget.set_label("Record") + sof_ctl.execute_command(command="record", data=False) + + def generate_sequential_filename(self): + recordings_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'recordings') + + if not os.path.exists(recordings_dir): + os.makedirs(recordings_dir) + + filename = os.path.join(recordings_dir, f"recording_{self.record_index}.wav") + self.record_index += 1 + + return filename + + def on_wav_file_selected(self, widget): + self.selected_wav_file = widget.get_active_text() + + def on_apply_eq_clicked(self, widget): + self.selected_eq_file = self.eq_dropdown.get_active_text() + if self.selected_eq_file: + eq_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'eq_configs', self.selected_eq_file) + sof_ctl.execute_command(command="eq", file_name=eq_file_path) + +def main(): + parser = argparse.ArgumentParser(description="SOF GUI Application") + parser.add_argument('--audio-path', action='append', help="Additional path to search for audio files (.wav)") + parser.add_argument('--config-path', action='append', help="Additional path to search for EQ config files (.txt)") + args = parser.parse_args() + + sof_ctl.extra_audio_paths = args.audio_path if args.audio_path else [] + + win = MyWindow(audio_paths=args.audio_path, config_paths=args.config_path) + win.connect("destroy", Gtk.main_quit) + win.show_all() + Gtk.main() + +if __name__ == "__main__": + main() diff --git a/tools/demo-gui/demo-gui/sof_demo_tui.py b/tools/demo-gui/demo-gui/sof_demo_tui.py new file mode 100644 index 000000000000..3fb387d684e1 --- /dev/null +++ b/tools/demo-gui/demo-gui/sof_demo_tui.py @@ -0,0 +1,184 @@ +# SPDX-License-Identifier: BSD-3-Clause + +import os +import sof_controller_engine as sof_ctl +import argparse + +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +class TextBasedUI: + def __init__(self, audio_paths, config_paths): + self.selected_wav_file = None + self.selected_eq_file = None + self.volume = 15 + self.is_playing = False + self.is_recording = False + self.scan_and_populate_files(audio_paths, config_paths) + sof_ctl.initialize_device() + self.run_ui() + + def scan_and_populate_files(self, audio_paths, config_paths): + self.wav_files = sof_ctl.scan_for_files('audios', '.wav', extra_paths=audio_paths) + + if self.wav_files: + self.selected_wav_file = self.wav_files[0] + print(f"Default WAV file selected: {self.selected_wav_file}") + + self.eq_files = sof_ctl.scan_for_files('eq_configs', '.txt', extra_paths=config_paths) + + if self.eq_files: + self.selected_eq_file = self.eq_files[0] + print(f"Default EQ config selected: {self.selected_eq_file}") + + def display_menu(self): + print("\nSOF Text-Based UI") + print("==================") + print("1. Select a WAV file") + if self.selected_wav_file: + print(f" Currently selected: {self.selected_wav_file}") + else: + print(" No WAV file selected") + + print("2. Select an EQ Config") + if self.selected_eq_file: + print(f" Currently selected: {self.selected_eq_file}") + else: + print(" No EQ file selected") + + print(f"3. Set Volume (Current: {self.volume})") + print(f"4. Play/Pause (Current: {'Playing' if self.is_playing else 'Paused'})") + print(f"5. Start/Stop Recording (Current: {'Recording' if self.is_recording else 'Not Recording'})") + print("6. Apply EQ Config") + print("7. Quit") + print("==================") + + def run_ui(self): + while True: + self.display_menu() + choice = input("Enter your choice (1-7): ").strip() + + if choice == '1': + self.select_wav_file() + elif choice == '2': + self.select_eq_file() + elif choice == '3': + self.set_volume() + elif choice == '4': + self.toggle_play_pause() + elif choice == '5': + self.toggle_record() + elif choice == '6': + self.apply_eq_config() + elif choice == '7': + print("Exiting...") + break + else: + print("Invalid choice, please try again.") + + def select_wav_file(self): + if not self.wav_files: + print("No .wav files found in the current directory.") + return + + print("\nSelect a WAV file:") + for idx, wav_file in enumerate(self.wav_files): + print(f"{idx + 1}. {wav_file}") + + file_choice = input(f"Enter the number of the file (1-{len(self.wav_files)}): ").strip() + + try: + file_index = int(file_choice) - 1 + if 0 <= file_index < len(self.wav_files): + self.selected_wav_file = self.wav_files[file_index] + print(f"Selected file: {self.selected_wav_file}") + else: + print("Invalid selection.") + except ValueError: + print("Invalid input, please enter a number.") + + def select_eq_file(self): + if not self.eq_files: + print("No EQ config files found in the eq_configs directory.") + return + + print("\nSelect an EQ Config file:") + for idx, eq_file in enumerate(self.eq_files): + print(f"{idx + 1}. {eq_file}") + + file_choice = input(f"Enter the number of the file (1-{len(self.eq_files)}): ").strip() + + try: + file_index = int(file_choice) - 1 + if 0 <= file_index < len(self.eq_files): + self.selected_eq_file = self.eq_files[file_index] + print(f"Selected EQ Config: {self.selected_eq_file}") + else: + print("Invalid selection.") + except ValueError: + print("Invalid input, please enter a number.") + + def set_volume(self): + volume_input = input("Enter volume level (0-100): ").strip() + + try: + user_volume = int(volume_input) + if 0 <= user_volume <= 100: + self.volume = user_volume + scaled_volume = sof_ctl.scale_volume(user_volume) + sof_ctl.execute_command(command="volume", data=scaled_volume) + print(f"Volume set to {self.volume}.") + else: + print("Volume must be between 0 and 100.") + except ValueError: + print("Invalid input, please enter a number.") + + def toggle_play_pause(self): + if not self.selected_wav_file: + print("No WAV file selected.") + return + + if not self.is_playing: + sof_ctl.execute_command(command="play", file_name=self.selected_wav_file) + self.is_playing = True + print("Playing...") + else: + sof_ctl.execute_command(command="pause") + self.is_playing = False + print("Paused.") + + def toggle_record(self): + recordings_dir = os.path.join(os.getcwd(), 'recordings') + + if not self.is_recording: + filename = input(f"Enter filename to save the recording (default: {recordings_dir}/record.wav): ").strip() + if not filename: + filename = "record.wav" + + full_path = os.path.join(recordings_dir, filename) + sof_ctl.execute_command(command="record", data=True, file_name=full_path) + self.is_recording = True + else: + sof_ctl.execute_command(command="record", data=False) + self.is_recording = False + + def apply_eq_config(self): + if not self.selected_eq_file: + print("No EQ config file selected.") + return + + eq_file_path = os.path.join(os.getcwd(), 'eq_configs', self.selected_eq_file) + sof_ctl.execute_command(command="eq", file_name=eq_file_path) + print(f"Applied EQ config: {self.selected_eq_file}") + +def main(): + parser = argparse.ArgumentParser(description="SOF TUI Application") + parser.add_argument('--audio-path', action='append', help="Additional path to search for audio files (.wav)") + parser.add_argument('--config-path', action='append', help="Additional path to search for EQ config files (.txt)") + args = parser.parse_args() + + sof_ctl.extra_audio_paths = args.audio_path if args.audio_path else [] + + TextBasedUI(audio_paths=args.audio_path, config_paths=args.config_path) + +if __name__ == "__main__": + main() diff --git a/tools/fuzzer/CMakeLists.txt b/tools/fuzzer/CMakeLists.txt deleted file mode 100644 index 31c0b2e45c83..000000000000 --- a/tools/fuzzer/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause - -cmake_minimum_required(VERSION 3.10) - -project(SOF_FUZZER C) - -if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") - message(FATAL_ERROR - " In-source builds are not supported.\n" - " Please remove CMakeCache.txt and the CMakeFiles directory.\n" - " Then specify a build directory. Example: cmake -Bbuild ..." - ) -endif() - -include(ExternalProject) - -set(parser_src_dir "${PROJECT_SOURCE_DIR}/../tplg_parser") -set(parser_install_dir "${PROJECT_BINARY_DIR}/sof_parser/install") - -ExternalProject_Add(sof_parser_ep - SOURCE_DIR "${parser_src_dir}" - PREFIX "${PROJECT_BINARY_DIR}/sof_parser" - BINARY_DIR "${PROJECT_BINARY_DIR}/sof_parser/build" - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${parser_install_dir} - -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} - BUILD_COMMAND ${CMAKE_COMMAND} - BUILD_ALWAYS 1 - BUILD_BYPRODUCTS "${parser_install_dir}/lib/libsof_tplg_parser.so" -) - -add_library(sof_parser SHARED IMPORTED) -set_target_properties(sof_parser PROPERTIES IMPORTED_LOCATION "${parser_install_dir}/lib/libsof_tplg_parser.so") -add_dependencies(sof_parser sof_parser_ep) - -add_executable(sof-fuzzer - main.c - qemu-bridge.c - topology.c - platform/byt-host.c - platform/hsw-host.c -) - -target_link_libraries(sof-fuzzer PRIVATE sof_parser) -target_include_directories(sof-fuzzer PRIVATE "${parser_install_dir}/include") - -add_dependencies(sof-fuzzer sof_parser) - -find_package(PkgConfig REQUIRED) -pkg_search_module(GLIB REQUIRED glib-2.0) -target_include_directories(sof-fuzzer PRIVATE ${GLIB_INCLUDE_DIRS}) -target_link_libraries(sof-fuzzer PRIVATE ${GLIB_LDFLAGS}) - -find_library(LIBRT rt) -if(LIBRT) - target_link_libraries(sof-fuzzer PRIVATE ${LIBRT}) -endif() - -set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}/../..") - -target_include_directories(sof-fuzzer PRIVATE - "${SOF_ROOT_SOURCE_DIRECTORY}/src/include" - "${SOF_ROOT_SOURCE_DIRECTORY}/src/arch/host/include" - "${SOF_ROOT_SOURCE_DIRECTORY}" -) - -install(TARGETS sof-fuzzer DESTINATION bin) diff --git a/tools/fuzzer/fuzzer.h b/tools/fuzzer/fuzzer.h deleted file mode 100644 index c515711ba357..000000000000 --- a/tools/fuzzer/fuzzer.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - * Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __FUZZER_H__ -#define __FUZZER_H__ - -#include <stdint.h> - -#define DEBUG_MSG_LEN 512 - -/* SOF Panic */ -#define SOF_IPC_PANIC_MAGIC 0x0dead000 -#define SOF_IPC_PANIC_MAGIC_MASK 0x0ffff000 - -/* SOF driver max BARs */ -#define MAX_BAR_COUNT 8 - -/* SOF driver IPC reply types */ -#define SOF_IPC_DSP_REPLY 0 -#define SOF_IPC_HOST_REPLY 1 - -/* kernel IRQ retrun values */ -#define IRQ_NONE 0 -#define IRQ_WAKE_THREAD 1 -#define IRQ_HANDLED 2 - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - -struct fuzz; -struct fuzz_platform; - -/* platform memory regions */ -struct fuzzer_mem_desc { - const char *name; - unsigned long base; - size_t size; - unsigned long alias; - void *ptr; -}; - -/* Register descriptor */ -struct fuzzer_reg_desc { - const char *name; /* register name */ - uint32_t offset; /* register offset */ - size_t size; /* register/area size */ -}; - -/* Device register space */ -struct fuzzer_reg_space { - const char *name; /* device name */ - int irq; - struct fuzzer_mem_desc desc; -}; - -struct mailbox { - unsigned int offset; - unsigned int size; -}; - -/* IPC message */ -struct ipc_msg { - uint32_t header; - void *msg_data; - unsigned int msg_size; - void *reply_data; - unsigned int reply_size; -}; - -/* platform description */ -struct fuzz_platform { - const char *name; - - /* all ops mandatory */ - int (*send_msg)(struct fuzz *f, struct ipc_msg *msg); - int (*get_reply)(struct fuzz *f, struct ipc_msg *msg); - int (*init)(struct fuzz *f, struct fuzz_platform *platform); - void (*free)(struct fuzz *f); - void (*mailbox_read)(struct fuzz *fuzzer, unsigned int offset, - void *mbox_data, unsigned int size); - void (*mailbox_write)(struct fuzz *fuzzer, unsigned int offset, - void *mbox_data, unsigned int size); - void (*fw_ready)(struct fuzz *fuzzer); - - /* registers */ - struct fuzzer_reg_space *reg_region; - int num_reg_regions; - - /* memories */ - struct fuzzer_mem_desc *mem_region; - int num_mem_regions; -}; - -/* runtime context */ -struct fuzz { - struct fuzz_platform *platform; - int boot_complete; - - /* ipc */ - struct ipc_msg msg; - - /* ipc mutex */ - pthread_mutex_t ipc_mutex; - - FILE *tplg_file; - - void *platform_data; /* core does not touch this */ -}; - -/* called by platform when it receives IPC message */ -void fuzzer_ipc_msg_rx(struct fuzz *fuzzer, struct mailbox *mailbox); - -/* called by platform when it receives IPC message reply */ -void fuzzer_ipc_msg_reply(struct fuzz *fuzzer, struct mailbox *mailbox); - -/* called by platform when FW crashses */ -void fuzzer_ipc_crash(struct fuzz *fuzzer, struct mailbox *mailbox, - unsigned int offset); - -/* called by platforms to allocate memory/register regions */ -void *fuzzer_create_memory_region(struct fuzz *fuzzer, int id, int idx); -void *fuzzer_create_io_region(struct fuzz *fuzzer, int id, int idx); -void fuzzer_free_regions(struct fuzz *fuzzer); - -/* ipc */ -int fuzzer_send_msg(struct fuzz *fuzzer); - -/* topology */ -int parse_tplg(struct fuzz *fuzzer, char *tplg_filename); - -/* Convenience platform ops */ -static inline void fuzzer_mailbox_read(struct fuzz *fuzzer, - struct mailbox *mailbox, int offset, - void *dest, size_t bytes) -{ - fuzzer->platform->mailbox_read(fuzzer, mailbox->offset + offset, - dest, bytes); -} - -static inline void fuzzer_mailbox_write(struct fuzz *fuzzer, - struct mailbox *mailbox, int offset, - void *src, size_t bytes) -{ - fuzzer->platform->mailbox_write(fuzzer, mailbox->offset + offset, - src, bytes); -} - -static inline void fuzzer_fw_ready(struct fuzz *fuzzer) -{ - fuzzer->platform->fw_ready(fuzzer); -} - - -extern struct fuzz_platform byt_platform; -extern struct fuzz_platform cht_platform; -extern struct fuzz_platform bsw_platform; -extern struct fuzz_platform hsw_platform; -extern struct fuzz_platform bdw_platform; - -extern pthread_cond_t cond; - -#endif diff --git a/tools/fuzzer/main.c b/tools/fuzzer/main.c deleted file mode 100644 index c42759362629..000000000000 --- a/tools/fuzzer/main.c +++ /dev/null @@ -1,354 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <errno.h> -#include <unistd.h> -#include <sys/time.h> -#include <pthread.h> -#include <string.h> -#include "fuzzer.h" -#include <ipc/topology.h> -#include <ipc/stream.h> -#include <ipc/control.h> -#include "qemu-bridge.h" -#include <ipc/trace.h> - -int enable_fuzzer; - -int ipc_reply_recd; -pthread_cond_t ipc_cond = PTHREAD_COND_INITIALIZER; -pthread_mutex_t ipc_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - -/* tplg message types */ -uint32_t tplg_cmd_types[] = {SOF_IPC_TPLG_COMP_NEW, - SOF_IPC_TPLG_COMP_FREE, - SOF_IPC_TPLG_COMP_CONNECT, - SOF_IPC_TPLG_PIPE_NEW, - SOF_IPC_TPLG_PIPE_FREE, - SOF_IPC_TPLG_PIPE_CONNECT, - SOF_IPC_TPLG_PIPE_COMPLETE, - SOF_IPC_TPLG_BUFFER_NEW, - SOF_IPC_TPLG_BUFFER_FREE}; - -/* PM message types */ -uint32_t pm_cmd_types[] = {SOF_IPC_PM_CTX_SAVE, - SOF_IPC_PM_CTX_RESTORE, - SOF_IPC_PM_CTX_SIZE, - SOF_IPC_PM_CLK_SET, - SOF_IPC_PM_CLK_GET, - SOF_IPC_PM_CLK_REQ, - SOF_IPC_PM_CORE_ENABLE}; - -uint32_t comp_cmd_types[] = {SOF_IPC_COMP_SET_VALUE, - SOF_IPC_COMP_GET_VALUE, - SOF_IPC_COMP_SET_DATA, - SOF_IPC_COMP_GET_DATA}; - -uint32_t dai_cmd_types[] = {SOF_IPC_DAI_CONFIG, SOF_IPC_DAI_LOOPBACK}; - -uint32_t stream_cmd_types[] = {SOF_IPC_STREAM_PCM_PARAMS, - SOF_IPC_STREAM_PCM_PARAMS_REPLY, - SOF_IPC_STREAM_PCM_FREE, - SOF_IPC_STREAM_TRIG_START, - SOF_IPC_STREAM_TRIG_STOP, - SOF_IPC_STREAM_TRIG_PAUSE, - SOF_IPC_STREAM_TRIG_RELEASE, - SOF_IPC_STREAM_TRIG_DRAIN, - SOF_IPC_STREAM_TRIG_XRUN, - SOF_IPC_STREAM_POSITION, - SOF_IPC_STREAM_VORBIS_PARAMS, - SOF_IPC_STREAM_VORBIS_FREE}; - -uint32_t trace_cmd_types[] = {SOF_IPC_TRACE_DMA_PARAMS, - SOF_IPC_TRACE_DMA_POSITION}; - -/* list of supported target platforms */ -static struct fuzz_platform *platform[] = { - &byt_platform, - &cht_platform, - &bsw_platform, - &hsw_platform, - &bdw_platform -}; - -static void usage(char *name) -{ - int i; - - fprintf(stdout, "Usage %s -p platform <option(s)>\n", name); - fprintf(stdout, " -t topology file\n"); - fprintf(stdout, " -p platform name\n"); - fprintf(stdout, " supported platforms: "); - for (i = 0; i < ARRAY_SIZE(platform); i++) - fprintf(stdout, "%s ", platform[i]->name); - fprintf(stdout, "\n"); - fprintf(stdout, "Qemu must be started before the fuzzer is run.\n"); - - exit(0); -} - -static void ipc_dump(struct ipc_msg *msg) -{ - fprintf(stdout, "ipc: header 0x%x size %d reply %d\n", - msg->header, msg->msg_size, msg->reply_size); -} - -static void ipc_dump_err(struct ipc_msg *msg) -{ - /* TODO: dump IPC payload */ - fprintf(stderr, "ipc: header 0x%x size %d reply %d\n", - msg->header, msg->msg_size, msg->reply_size); -} - -void *fuzzer_create_io_region(struct fuzz *fuzzer, int id, int idx) -{ - struct fuzz_platform *plat = fuzzer->platform; - struct fuzzer_reg_space *space; - char shm_name[32]; - int err; - void *ptr = NULL; - - space = &plat->reg_region[idx]; - - sprintf(shm_name, "%s-io", space->name); - fprintf(stdout, "registering %s\n", shm_name); - err = qemu_io_register_shm(shm_name, id, space->desc.size, &ptr); - if (err < 0) - fprintf(stderr, "error: can't allocate IO %s:%d SHM %d\n", shm_name, - id, err); - - return ptr; -} - -void *fuzzer_create_memory_region(struct fuzz *fuzzer, int id, int idx) -{ - struct fuzz_platform *plat = fuzzer->platform; - struct fuzzer_mem_desc *desc; - char shm_name[32]; - void *ptr = NULL; - int err; - - desc = &plat->mem_region[idx]; - - /* shared via SHM (not shared on real HW) */ - sprintf(shm_name, "%s-mem", desc->name); - fprintf(stdout, "registering %s\n", shm_name); - err = qemu_io_register_shm(shm_name, id, desc->size, &ptr); - if (err < 0) - fprintf(stderr, "error: can't allocate %s:%d SHM %d\n", shm_name, - id, err); - - return ptr; -} - -/* frees all SHM and message queues */ -void fuzzer_free_regions(struct fuzz *fuzzer) -{ - struct fuzz_platform *plat = fuzzer->platform; - int i; - - for (i = 0; i < plat->num_mem_regions; i++) - qemu_io_free_shm(i); - - for (i = 0; i < plat->num_reg_regions; i++) - qemu_io_free_shm(i); - - qemu_io_free(); -} - -/* called by platform when it receives IPC message */ -void fuzzer_ipc_msg_rx(struct fuzz *fuzzer, struct mailbox *mailbox) -{ - struct sof_ipc_comp_reply r; - struct sof_ipc_cmd_hdr hdr; - uint32_t cmd; - - /* read mailbox */ - fuzzer_mailbox_read(fuzzer, mailbox, 0, &hdr, sizeof(hdr)); - cmd = hdr.cmd & SOF_GLB_TYPE_MASK; - - /* check message type */ - switch (cmd) { - case SOF_IPC_GLB_REPLY: - fprintf(stderr, "error: ipc reply unknown\n"); - break; - case SOF_IPC_FW_READY: - fuzzer_fw_ready(fuzzer); - fuzzer->boot_complete = 1; - break; - case SOF_IPC_GLB_COMPOUND: - case SOF_IPC_GLB_TPLG_MSG: - case SOF_IPC_GLB_PM_MSG: - case SOF_IPC_GLB_COMP_MSG: - case SOF_IPC_GLB_STREAM_MSG: - case SOF_IPC_GLB_TRACE_MSG: - fuzzer_mailbox_read(fuzzer, mailbox, 0, &r, sizeof(r)); - break; - default: - fprintf(stderr, "error: unknown DSP message 0x%x\n", cmd); - break; - } - -} - -/* called by platform when it receives IPC message reply */ -void fuzzer_ipc_msg_reply(struct fuzz *fuzzer, struct mailbox *mailbox) -{ - int ret; - - ret = fuzzer->platform->get_reply(fuzzer, &fuzzer->msg); - if (ret < 0) - fprintf(stderr, "error: incorrect DSP reply\n"); - - ipc_dump(&fuzzer->msg); - - pthread_mutex_lock(&ipc_mutex); - ipc_reply_recd = 1; - pthread_cond_signal(&ipc_cond); - pthread_mutex_unlock(&ipc_mutex); -} - -/* called by platform when FW crashses */ -void fuzzer_ipc_crash(struct fuzz *fuzzer, struct mailbox *mailbox, - unsigned int offset) -{ - /* TODO: DSP FW has crashed. dump stack, regs, last IPC, log etc */ - fprintf(stderr, "error: DSP FW crash\n"); - exit(EXIT_FAILURE); -} - -int fuzzer_send_msg(struct fuzz *fuzzer) -{ - struct timespec timeout; - struct timeval tp; - int ret; - - ipc_dump(&fuzzer->msg); - - /* send msg */ - ret = fuzzer->platform->send_msg(fuzzer, &fuzzer->msg); - if (ret < 0) { - fprintf(stderr, "error: message tx failed\n"); - return ret; - } - - /* wait for ipc reply */ - gettimeofday(&tp, NULL); - timeout.tv_sec = tp.tv_sec; - timeout.tv_nsec = tp.tv_usec * 1000; - timeout.tv_nsec += 300000000; /* 300ms timeout */ - - /* first lock the boot wait mutex */ - pthread_mutex_lock(&ipc_mutex); - - /* reset condition for next IPC message */ - ipc_reply_recd = 0; - ret = 0; - - /* now wait for mutex unlock and ipc_reply_recd set by IPC reply */ - while (!ipc_reply_recd && !ret) - ret = pthread_cond_timedwait(&ipc_cond, &ipc_mutex, &timeout); - - if (ret == ETIMEDOUT && !ipc_reply_recd) { - ret = -EINVAL; - fprintf(stderr, "error: IPC timeout\n"); - ipc_dump_err(&fuzzer->msg); - pthread_mutex_unlock(&ipc_mutex); - exit(0); - } - - pthread_mutex_unlock(&ipc_mutex); - - /* - * sleep for 5 ms before continuing sending the next message. - * This helps with the condition signaling. Without this, - * the condition seems to always satisfy and - * the fuzzer never waits for a response from the DSP. - */ - usleep(50000); - - return ret; -} - -int main(int argc, char *argv[]) -{ - struct fuzz fuzzer; - int ret; - char opt; - char *topology_file; - char *platform_name = NULL; - int i, j; - int regions = 0; - - /* parse arguments */ - while ((opt = getopt(argc, argv, "ht:p:")) != -1) { - switch (opt) { - case 't': - topology_file = optarg; - break; - case 'p': - platform_name = optarg; - break; - case 'h': - usage(argv[0]); - exit(0); - break; - default: - usage(argv[0]); - exit(EXIT_FAILURE); - } - } - - /* initialise emulated target device */ - if (!platform_name) { - fprintf(stderr, "error: no target platform specified\n"); - usage(argv[0]); - exit(EXIT_FAILURE); - } - - /* find platform */ - for (i = 0; i < ARRAY_SIZE(platform); i++) { - if (!strcmp(platform[i]->name, platform_name)) - break; - } - - /* no platform found */ - if (i >= ARRAY_SIZE(platform)) { - fprintf(stderr, "error: platform %s not supported\n", - platform_name); - usage(argv[0]); - exit(EXIT_FAILURE); - } - - /* init plaform */ - fprintf(stdout, "initialising platform %s\n", platform[i]->name); - ret = platform[i]->init(&fuzzer, platform[i]); - if (ret == ETIMEDOUT) { - fprintf(stderr, "error: platform %s failed to initialise\n", - platform_name); - exit(EXIT_FAILURE); - } - - fprintf(stdout, "FW boot complete\n"); - - /* allocate max ipc size bytes for the msg and reply */ - fuzzer.msg.msg_data = malloc(SOF_IPC_MSG_MAX_SIZE); - fuzzer.msg.reply_data = malloc(SOF_IPC_MSG_MAX_SIZE); - - /* load topology */ - ret = parse_tplg(&fuzzer, topology_file); - if (ret < 0) - exit(EXIT_FAILURE); - - /* all done - now free platform */ - platform[i]->free(&fuzzer); - return 0; -} diff --git a/tools/fuzzer/platform/byt-host.c b/tools/fuzzer/platform/byt-host.c deleted file mode 100644 index ed22cae8480b..000000000000 --- a/tools/fuzzer/platform/byt-host.c +++ /dev/null @@ -1,543 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -/* Core IA host SHIM support for Baytrail audio DSP. */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <string.h> -#include <stdint.h> -#include <unistd.h> -#include <sys/time.h> -#include "shim.h" -#include <ipc/trace.h> -#include <ipc/info.h> -#include "../fuzzer.h" -#include "../qemu-bridge.h" - -#define MBOX_OFFSET 0x144000 - -/* Baytrail, Cherrytrail and Braswell - taken from qemu */ -#define ADSP_PCI_SIZE 0x00001000 -#define ADSP_BYT_PCI_BASE 0xF1200000 -#define ADSP_BYT_MMIO_BASE 0xF1400000 -#define ADSP_BYT_HOST_IRAM_OFFSET 0x000c0000 -#define ADSP_BYT_HOST_DRAM_OFFSET 0x00100000 -#define ADSP_BYT_HOST_IRAM_BASE \ - (ADSP_BYT_MMIO_BASE + ADSP_BYT_HOST_IRAM_OFFSET) -#define ADSP_BYT_HOST_DRAM_BASE \ - (ADSP_BYT_MMIO_BASE + ADSP_BYT_HOST_DRAM_OFFSET) -#define ADSP_BYT_HOST_SHIM_BASE \ - (ADSP_BYT_MMIO_BASE + 0x00140000) -#define ADSP_BYT_HOST_MAILBOX_BASE \ - (ADSP_BYT_MMIO_BASE + 0x00144000) - -#define ADSP_CHT_PCI_BASE 0xF1600000 -#define ADSP_CHT_MMIO_BASE 0xF1800000 -#define ADSP_CHT_HOST_IRAM_BASE \ - (ADSP_CHT_MMIO_BASE + ADSP_BYT_HOST_IRAM_OFFSET) -#define ADSP_CHT_HOST_DRAM_BASE \ - (ADSP_CHT_MMIO_BASE + ADSP_BYT_HOST_DRAM_OFFSET) -#define ADSP_CHT_HOST_SHIM_BASE \ - (ADSP_CHT_MMIO_BASE + 0x00140000) -#define ADSP_CHT_HOST_MAILBOX_BASE \ - (ADSP_CHT_MMIO_BASE + 0x00144000) - -#define ADSP_BYT_IRAM_SIZE 0x14000 -#define ADSP_BYT_DRAM_SIZE 0x28000 -#define ADSP_BYT_SHIM_SIZE 0x1000 -#define ADSP_MAILBOX_SIZE 0x1000 - -/* TODO get from driver. */ -#define BYT_PANIC_OFFSET(x) (x) - -struct byt_data { - void *bar[MAX_BAR_COUNT]; - struct mailbox host_box; - struct mailbox dsp_box; - int boot_complete; - pthread_mutex_t mutex; -}; - -/* Platform host description taken from Qemu - mapped to BAR 0, 1*/ -static struct fuzzer_mem_desc byt_mem[] = { - {.name = "iram", .base = ADSP_BYT_HOST_IRAM_BASE, - .size = ADSP_BYT_IRAM_SIZE}, - {.name = "dram", .base = ADSP_BYT_HOST_DRAM_BASE, - .size = ADSP_BYT_DRAM_SIZE}, -}; - -/* mapped to BAR 2, 3 */ -static struct fuzzer_reg_space byt_io[] = { - { .name = "shim", - .desc = {.base = ADSP_BYT_HOST_SHIM_BASE, - .size = ADSP_BYT_SHIM_SIZE},}, - { .name = "mbox", - .desc = {.base = ADSP_BYT_HOST_MAILBOX_BASE, - .size = ADSP_MAILBOX_SIZE},}, -}; - -#define BYT_DSP_BAR 2 -#define BYT_MBOX_BAR 3 - -/* - * Platform support for BYT/CHT. - * - * The IPC portions below are copied and pasted from the SOF driver with some - * modification for data structure and printing. - * - * The "driver" code below no longer writes directly to the HW but writes - * to the virtual HW as exported by qemu as Posix SHM and message queues. - * - * Register IO and mailbox IO is performed using shared memory regions between - * fuzzer and qemu. - * - * IRQs are send using message queues between fuzzer and qemu. - * - * SHM and message queues can be inspected from the cmd line by using - * "less -C" on /dev/shm/name and /dev/mqueue/name - */ - -static uint64_t dsp_read64(struct fuzz *fuzzer, unsigned int bar, - unsigned int reg) -{ - struct byt_data *data = fuzzer->platform_data; - - return *((uint64_t *)(data->bar[bar] + reg)); -} - -static void dsp_write64(struct fuzz *fuzzer, unsigned int bar, - unsigned int reg, uint64_t value) -{ - struct byt_data *data = fuzzer->platform_data; - struct qemu_io_msg_reg32 reg32; - struct qemu_io_msg_irq irq; - uint32_t active, isrd; - - /* write value to SHM */ - *((uint64_t *)(data->bar[bar] + reg)) = value; - - /* most IO is handled by SHM, but there are some exceptions */ - switch (reg) { - case SHIM_IPCX: - - /* now set/clear status bit */ - isrd = dsp_read64(fuzzer, bar, SHIM_ISRD) & - ~(SHIM_ISRD_DONE | SHIM_ISRD_BUSY); - isrd |= value & SHIM_IPCX_BUSY ? SHIM_ISRD_BUSY : 0; - isrd |= value & SHIM_IPCX_DONE ? SHIM_ISRD_DONE : 0; - dsp_write64(fuzzer, bar, SHIM_ISRD, isrd); - - /* do we need to send an IRQ ? */ - if (value & SHIM_IPCX_BUSY) { - - fprintf(stdout, "irq: send busy interrupt 0x%8.8lx\n", - value); - - /* send IRQ to child */ - irq.hdr.type = QEMU_IO_TYPE_IRQ; - irq.hdr.msg = QEMU_IO_MSG_IRQ; - irq.hdr.size = sizeof(irq); - irq.irq = 0; - - qemu_io_send_msg(&irq.hdr); - } - break; - case SHIM_IPCD: - - /* set/clear status bit */ - isrd = dsp_read64(fuzzer, bar, SHIM_ISRD) & - ~(SHIM_ISRD_DONE | SHIM_ISRD_BUSY); - isrd |= value & SHIM_IPCD_BUSY ? SHIM_ISRD_BUSY : 0; - isrd |= value & SHIM_IPCD_DONE ? SHIM_ISRD_DONE : 0; - dsp_write64(fuzzer, bar, SHIM_ISRD, isrd); - - /* do we need to send an IRQ ? */ - if (value & SHIM_IPCD_DONE) { - - fprintf(stdout, "irq: send done interrupt 0x%8.8lx\n", - value); - - /* send IRQ to child */ - irq.hdr.type = QEMU_IO_TYPE_IRQ; - irq.hdr.msg = QEMU_IO_MSG_IRQ; - irq.hdr.size = sizeof(irq); - irq.irq = 0; - - qemu_io_send_msg(&irq.hdr); - } - break; - case SHIM_IMRX: - - active = dsp_read64(fuzzer, bar, SHIM_ISRX) & - ~(dsp_read64(fuzzer, bar, SHIM_IMRX)); - - fprintf(stdout, "irq: masking %lx mask %lx active %x\n", - dsp_read64(fuzzer, bar, SHIM_ISRD), - dsp_read64(fuzzer, bar, SHIM_IMRD), active); - break; - default: - break; - } -} - -static uint64_t dsp_update_bits64_unlocked(struct fuzz *fuzzer, - unsigned int bar, uint32_t offset, - uint64_t mask, uint64_t value) -{ - struct byt_data *data = fuzzer->platform_data; - uint64_t old, new; - uint64_t ret; - - ret = dsp_read64(fuzzer, bar, offset); - old = ret; - - new = (old & ~mask) | (value & mask); - - if (old == new) - return 0; - - dsp_write64(fuzzer, bar, offset, new); - return 1; -} - -static void mailbox_read(struct fuzz *fuzzer, unsigned int offset, - void *mbox_data, unsigned int size) -{ - struct byt_data *data = fuzzer->platform_data; - - memcpy(mbox_data, (void *)(data->bar[BYT_MBOX_BAR] + offset), size); -} - -static void mailbox_write(struct fuzz *fuzzer, unsigned int offset, - void *mbox_data, unsigned int size) -{ - struct byt_data *data = fuzzer->platform_data; - - memcpy((void *)(data->bar[BYT_MBOX_BAR] + offset), mbox_data, size); -} - -static int byt_cmd_done(struct fuzz *fuzzer, int dir) -{ - if (dir == SOF_IPC_HOST_REPLY) { - /* clear BUSY bit and set DONE bit - accept new messages */ - dsp_update_bits64_unlocked(fuzzer, BYT_DSP_BAR, SHIM_IPCD, - SHIM_BYT_IPCD_BUSY | - SHIM_BYT_IPCD_DONE, - SHIM_BYT_IPCD_DONE); - - /* unmask busy interrupt */ - dsp_update_bits64_unlocked(fuzzer, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_BUSY, 0); - } else { - /* clear DONE bit - tell DSP we have completed */ - dsp_update_bits64_unlocked(fuzzer, BYT_DSP_BAR, SHIM_IPCX, - SHIM_BYT_IPCX_DONE, 0); - - /* unmask Done interrupt */ - dsp_update_bits64_unlocked(fuzzer, BYT_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); - } - - return 0; -} - -/* - * IPC Doorbell IRQ handler and thread. - */ - -static int byt_irq_handler(int irq, void *context) -{ - struct fuzz *fuzzer = (struct fuzz *)context; - uint64_t isr; - int ret = IRQ_NONE; - - /* Interrupt arrived, check src */ - isr = dsp_read64(fuzzer, BYT_DSP_BAR, SHIM_ISRX); - if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY)) - ret = IRQ_WAKE_THREAD; - - return ret; -} - -static int byt_irq_thread(int irq, void *context) -{ - struct fuzz *fuzzer = (struct fuzz *)context; - struct byt_data *data = fuzzer->platform_data; - uint64_t ipcx, ipcd; - uint64_t imrx; - - imrx = dsp_read64(fuzzer, BYT_DSP_BAR, SHIM_IMRX); - ipcx = dsp_read64(fuzzer, BYT_DSP_BAR, SHIM_IPCX); - - /* reply message from DSP */ - if ((ipcx & SHIM_BYT_IPCX_DONE) && - !(imrx & SHIM_IMRX_DONE)) { - /* Mask Done interrupt before first */ - dsp_update_bits64_unlocked(fuzzer, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_DONE, - SHIM_IMRX_DONE); - - fprintf(stdout, "ipc: reply msg from DSP\n"); - /* - * handle immediate reply from DSP core. If the msg is - * found, set done bit in cmd_done which is called at the - * end of message processing function, else set it here - * because the done bit can't be set in cmd_done function - * which is triggered by msg - */ - fuzzer_ipc_msg_reply(fuzzer, &data->host_box); - byt_cmd_done(fuzzer, SOF_IPC_DSP_REPLY); - return IRQ_HANDLED; - } - - /* new message from DSP */ - ipcd = dsp_read64(fuzzer, BYT_DSP_BAR, SHIM_IPCD); - if ((ipcd & SHIM_BYT_IPCD_BUSY) && - !(imrx & SHIM_IMRX_BUSY)) { - /* Mask Busy interrupt before return */ - dsp_update_bits64_unlocked(fuzzer, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_BUSY, - SHIM_IMRX_BUSY); - - /* read mailbox */ - if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { - fuzzer_ipc_crash(fuzzer, &data->dsp_box, - BYT_PANIC_OFFSET(ipcd) + MBOX_OFFSET); - } else { - fuzzer_ipc_msg_rx(fuzzer, &data->dsp_box); - } - - if (!data->boot_complete && fuzzer->boot_complete) { - data->boot_complete = 1; - byt_cmd_done(fuzzer, SOF_IPC_HOST_REPLY); - pthread_cond_signal(&cond); - return IRQ_HANDLED; - } - } - - return IRQ_HANDLED; -} - -static int byt_send_msg(struct fuzz *fuzzer, struct ipc_msg *msg) -{ - struct fuzz_platform *plat = fuzzer->platform; - struct byt_data *data = fuzzer->platform_data; - struct sof_ipc_cmd_hdr *hdr = (struct sof_ipc_cmd_hdr *)msg->msg_data; - uint64_t cmd = msg->header; - - /* send the message */ - fuzzer_mailbox_write(fuzzer, &data->host_box, 0, msg->msg_data, - msg->msg_size); - dsp_write64(fuzzer, BYT_DSP_BAR, SHIM_IPCX, - cmd | SHIM_BYT_IPCX_BUSY); - - return 0; -} - -static int byt_get_reply(struct fuzz *fuzzer, struct ipc_msg *msg) -{ - struct fuzz_platform *plat = fuzzer->platform; - struct byt_data *data = fuzzer->platform_data; - struct sof_ipc_reply reply; - int ret = 0; - uint32_t size; - - /* get reply */ - fuzzer_mailbox_read(fuzzer, &data->host_box, 0, &reply, sizeof(reply)); - - if (reply.error < 0) { - size = sizeof(reply); - ret = reply.error; - } else { - /* reply correct size ? */ - if (reply.hdr.size != msg->reply_size) { - fprintf(stderr, - "error: reply expected 0x%x got 0x%x bytes\n", - msg->reply_size, reply.hdr.size); - size = msg->reply_size; - ret = -EINVAL; - } else { - size = reply.hdr.size; - } - } - - /* read the message */ - if (msg->msg_data && size > 0) - fuzzer_mailbox_read(fuzzer, &data->host_box, 0, - msg->reply_data, size); - - return ret; -} - -/* called when we receive a message from qemu */ -static int bridge_cb(void *data, struct qemu_io_msg *msg) -{ - struct fuzz *fuzzer = (struct fuzz *)data; - - fprintf(stdout, "msg: id %d msg %d size %d type %d\n", - msg->id, msg->msg, msg->size, msg->type); - - switch (msg->type) { - case QEMU_IO_TYPE_IRQ: - /* IRQ from DSP */ - if (byt_irq_handler(0, fuzzer) != IRQ_NONE) - byt_irq_thread(0, fuzzer); - break; - default: - break; - } - - return 0; -} - -static int byt_platform_init(struct fuzz *fuzzer, - struct fuzz_platform *platform) -{ - struct timespec timeout; - struct byt_data *data; - struct timeval tp; - int i, bar; - int ret = 0; - - /* init private data */ - data = calloc(sizeof(*data), 1); - if (!data) - return -ENOMEM; - fuzzer->platform_data = data; - fuzzer->platform = platform; - - /* create SHM for memories and register regions */ - for (i = 0, bar = 0; i < platform->num_mem_regions; i++, bar++) { - data->bar[bar] = fuzzer_create_memory_region(fuzzer, bar, i); - if (!data->bar[bar]) { - fprintf(stderr, "error: failed to create mem region %s\n", - platform->mem_region[i].name); - return -ENOMEM; - } - } - - for (i = 0; i < platform->num_reg_regions; i++, bar++) { - data->bar[bar] = fuzzer_create_io_region(fuzzer, bar, i); - if (!data->bar[bar]) { - fprintf(stderr, "error: failed to create mem region %s\n", - platform->reg_region[i].name); - return -ENOMEM; - } - } - - /* initialise bridge to qemu */ - qemu_io_register_parent(platform->name, &bridge_cb, (void *)fuzzer); - - /* set boot wait timeout */ - gettimeofday(&tp, NULL); - timeout.tv_sec = tp.tv_sec; - timeout.tv_nsec = tp.tv_usec * 1000; - timeout.tv_sec += 5; - - /* first lock the boot wait mutex */ - pthread_mutex_lock(&data->mutex); - - /* now wait for mutex to be unlocked by boot ready message */ - while (!ret && !data->boot_complete) - ret = pthread_cond_timedwait(&cond, &data->mutex, &timeout); - - if (ret == ETIMEDOUT && !data->boot_complete) - fprintf(stderr, "error: DSP boot timeout\n"); - - pthread_mutex_unlock(&data->mutex); - - return ret; -} - -static void byt_platform_free(struct fuzz *fuzzer) -{ - struct byt_data *data = fuzzer->platform_data; - - fuzzer_free_regions(fuzzer); - free(data); -} - -static void byt_fw_ready(struct fuzz *fuzzer) -{ - struct byt_data *data = fuzzer->platform_data; - struct sof_ipc_fw_ready fw_ready; - struct sof_ipc_fw_version version; - uint32_t offset = MBOX_OFFSET; - - /* read fw_ready data from mailbox */ - fuzzer_mailbox_read(fuzzer, &data->dsp_box, 0, - &fw_ready, sizeof(fw_ready)); - - /* - * Hardcode offsets. - * TODO: read init host_box and dsp_box from fw_ready message - */ - data->host_box.offset = 0x400; - data->host_box.size = 0x400; - data->dsp_box.offset = 0; - data->dsp_box.size = 0x400; - - fprintf(stdout, - "ipc: host box 0x%x size 0x%x\n", data->host_box.offset, - data->host_box.size); - fprintf(stdout, "ipc: dsp box 0x%x size 0x%x\n", data->dsp_box.offset, - data->dsp_box.size); - - version = fw_ready.version; - fprintf(stdout, "ipc: FW version major: %d minor: %d tag: %s\n", - version.major, version.minor, version.tag); -} - -struct fuzz_platform byt_platform = { - .name = "byt", - .send_msg = byt_send_msg, - .get_reply = byt_get_reply, - .init = byt_platform_init, - .free = byt_platform_free, - .mailbox_read = mailbox_read, - .mailbox_write = mailbox_write, - .fw_ready = byt_fw_ready, - .num_mem_regions = ARRAY_SIZE(byt_mem), - .mem_region = byt_mem, - .num_reg_regions = ARRAY_SIZE(byt_io), - .reg_region = byt_io, -}; - -struct fuzz_platform cht_platform = { - .name = "cht", - .send_msg = byt_send_msg, - .get_reply = byt_get_reply, - .init = byt_platform_init, - .free = byt_platform_free, - .mailbox_read = mailbox_read, - .mailbox_write = mailbox_write, - .fw_ready = byt_fw_ready, - .num_mem_regions = ARRAY_SIZE(byt_mem), - .mem_region = byt_mem, - .num_reg_regions = ARRAY_SIZE(byt_io), - .reg_region = byt_io, -}; - -struct fuzz_platform bsw_platform = { - .name = "bsw", - .send_msg = byt_send_msg, - .get_reply = byt_get_reply, - .init = byt_platform_init, - .free = byt_platform_free, - .mailbox_read = mailbox_read, - .mailbox_write = mailbox_write, - .fw_ready = byt_fw_ready, - .num_mem_regions = ARRAY_SIZE(byt_mem), - .mem_region = byt_mem, - .num_reg_regions = ARRAY_SIZE(byt_io), - .reg_region = byt_io, -}; diff --git a/tools/fuzzer/platform/hsw-host.c b/tools/fuzzer/platform/hsw-host.c deleted file mode 100644 index c502f4371a77..000000000000 --- a/tools/fuzzer/platform/hsw-host.c +++ /dev/null @@ -1,558 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -/* Core IA host SHIM support for Haswell audio DSP. */ - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <string.h> -#include <stdint.h> -#include <unistd.h> -#include <sys/time.h> -#include "shim.h" -#include <ipc/trace.h> -#include <ipc/info.h> -#include "../fuzzer.h" -#include "../qemu-bridge.h" - -#define MBOX_OFFSET 0x144000 - -/* taken from qemu value */ -#define ADSP_PCI_SIZE 0x00001000 - -/* Haswell and Broadwell */ -#define ADSP_HSW_PCI_BASE 0xF0200000 -#define ADSP_HSW_MMIO_BASE 0xF0400000 -#define ADSP_HSW_HOST_IRAM_OFFSET 0x00080000 -#define ADSP_HSW_HOST_DRAM_OFFSET 0x00000000 -#define ADSP_HSW_HOST_IRAM_BASE \ - (ADSP_HSW_MMIO_BASE + ADSP_HSW_HOST_IRAM_OFFSET) -#define ADSP_HSW_HOST_DRAM_BASE \ - (ADSP_HSW_MMIO_BASE + ADSP_HSW_HOST_DRAM_OFFSET) -#define ADSP_HSW_HOST_SHIM_BASE \ - (ADSP_HSW_MMIO_BASE + 0x000E7000) -#define ADSP_HSW_HOST_MAILBOX_BASE \ - (ADSP_HSW_HOST_DRAM_BASE + 0x0007E000) - -#define ADSP_BDW_PCI_BASE 0xF0600000 -#define ADSP_BDW_MMIO_BASE 0xF0800000 -#define ADSP_BDW_HOST_IRAM_OFFSET 0x000A0000 -#define ADSP_BDW_HOST_DRAM_OFFSET 0x00000000 -#define ADSP_BDW_HOST_IRAM_BASE \ - (ADSP_BDW_MMIO_BASE + ADSP_BDW_HOST_IRAM_OFFSET) -#define ADSP_BDW_HOST_DRAM_BASE \ - (ADSP_BDW_MMIO_BASE + ADSP_BDW_HOST_DRAM_OFFSET) -#define ADSP_BDW_HOST_SHIM_BASE \ - (ADSP_BDW_MMIO_BASE + 0x000FB000) -#define ADSP_BDW_HOST_MAILBOX_BASE \ - (ADSP_BDW_HOST_DRAM_BASE + 0x0009E000) - -#define ADSP_HSW_DSP_SHIM_BASE 0xFFFE7000 -#define ADSP_BDW_DSP_SHIM_BASE 0xFFFFB000 -#define ADSP_HSW_SHIM_SIZE 0x00001000 - -#define ADSP_BDW_DSP_MAILBOX_BASE (0x0049E000 - ADSP_HSW_DSP_DRAM_BASE) -#define ADSP_HSW_DSP_MAILBOX_BASE (0x0047E000 - ADSP_HSW_DSP_DRAM_BASE) - -#define ADSP_HSW_DSP_IRAM_BASE 0x00000000 -#define ADSP_HSW_DSP_DRAM_BASE 0x00400000 - -#define ADSP_HSW_IRAM_SIZE 0x50000 -#define ADSP_HSW_DRAM_SIZE 0x80000 - -#define ADSP_BDW_DSP_IRAM_BASE 0x00000000 -#define ADSP_BDW_DSP_DRAM_BASE 0x00400000 -#define ADSP_BDW_IRAM_SIZE 0x50000 -#define ADSP_BDW_DRAM_SIZE 0xA0000 - -#define ADSP_MAILBOX_SIZE 0x980 - -/* TODO get from driver. */ -#define HSW_PANIC_OFFSET(x) (x) - -struct hsw_data { - void *bar[MAX_BAR_COUNT]; - struct mailbox host_box; - struct mailbox dsp_box; - int boot_complete; - pthread_mutex_t mutex; -}; - -static struct fuzzer_mem_desc hsw_mem[] = { - {.name = "iram", .base = ADSP_HSW_HOST_IRAM_BASE, - .size = ADSP_HSW_IRAM_SIZE}, - {.name = "dram", .base = ADSP_HSW_HOST_DRAM_BASE, - .size = ADSP_HSW_DRAM_SIZE}, -}; - -static struct fuzzer_reg_space hsw_io[] = { - { .name = "shim", - .desc = {.base = ADSP_HSW_DSP_SHIM_BASE, - .size = ADSP_HSW_SHIM_SIZE},}, -}; - -static struct fuzzer_mem_desc bdw_mem[] = { - {.name = "iram", .base = ADSP_BDW_HOST_IRAM_BASE, - .size = ADSP_BDW_IRAM_SIZE}, - {.name = "dram", .base = ADSP_BDW_HOST_DRAM_BASE, - .size = ADSP_BDW_DRAM_SIZE}, -}; - -static struct fuzzer_reg_space bdw_io[] = { - { .name = "shim", - .desc = {.base = ADSP_BDW_DSP_SHIM_BASE, - .size = ADSP_HSW_SHIM_SIZE},}, -}; - -#define HSW_DSP_BAR 2 -#define HSW_MBOX_BAR 1 - -/* - * Platform support for HSW/BDW. - * - * The IPC portions below are copied and pasted from the SOF driver with some - * modification for data structure and printing. - * - * The "driver" code below no longer writes directly to the HW but writes - * to the virtual HW as exported by qemu as Posix SHM and message queues. - * - * Register IO and mailbox IO is performed using shared memory regions between - * fuzzer and qemu. - * - * IRQs are send using message queues between fuzzer and qemu. - * - * SHM and message queues can be inspected from the cmd line by using - * "less -C" on /dev/shm/name and /dev/mqueue/name - */ - -static uint32_t dsp_read(struct fuzz *fuzzer, unsigned int bar, - unsigned int reg) -{ - struct hsw_data *data = fuzzer->platform_data; - - return *((uint32_t *)(data->bar[bar] + reg)); -} - -static void dsp_write(struct fuzz *fuzzer, unsigned int bar, - unsigned int reg, uint32_t value) -{ - struct hsw_data *data = fuzzer->platform_data; - struct qemu_io_msg_reg32 reg32; - struct qemu_io_msg_irq irq; - uint32_t active, isrd; - - /* write value to SHM */ - *((uint32_t *)(data->bar[bar] + reg)) = value; - - /* most IO is handled by SHM, but there are some exceptions */ - switch (reg) { - case SHIM_IPCX: - /* now set/clear status bit */ - isrd = dsp_read(fuzzer, bar, SHIM_ISRD) & - ~(SHIM_ISRD_DONE | SHIM_ISRD_BUSY); - isrd |= value & SHIM_IPCX_BUSY ? SHIM_ISRD_BUSY : 0; - isrd |= value & SHIM_IPCX_DONE ? SHIM_ISRD_DONE : 0; - dsp_write(fuzzer, bar, SHIM_ISRD, isrd); - - /* do we need to send an IRQ ? */ - if (value & SHIM_IPCX_BUSY) { - - fprintf(stdout, "irq: send busy interrupt 0x%8.8x\n", - value); - - /* send IRQ to child */ - irq.hdr.type = QEMU_IO_TYPE_IRQ; - irq.hdr.msg = QEMU_IO_MSG_IRQ; - irq.hdr.size = sizeof(irq); - irq.irq = 0; - - qemu_io_send_msg(&irq.hdr); - } - break; - case SHIM_IPCD: - /* set/clear status bit */ - isrd = dsp_read(fuzzer, bar, SHIM_ISRD) & - ~(SHIM_ISRD_DONE | SHIM_ISRD_BUSY); - isrd |= value & SHIM_IPCD_BUSY ? SHIM_ISRD_BUSY : 0; - isrd |= value & SHIM_IPCD_DONE ? SHIM_ISRD_DONE : 0; - dsp_write(fuzzer, bar, SHIM_ISRD, isrd); - - /* do we need to send an IRQ ? */ - if (value & SHIM_IPCD_DONE) { - - fprintf(stdout, "irq: send done interrupt 0x%8.8x\n", - value); - - /* send IRQ to child */ - irq.hdr.type = QEMU_IO_TYPE_IRQ; - irq.hdr.msg = QEMU_IO_MSG_IRQ; - irq.hdr.size = sizeof(irq); - irq.irq = 0; - - qemu_io_send_msg(&irq.hdr); - } - break; - case SHIM_IMRX: - active = dsp_read(fuzzer, bar, SHIM_ISRX) & - ~(dsp_read(fuzzer, bar, SHIM_IMRX)); - - fprintf(stdout, "irq: masking %x mask %x active %x\n", - dsp_read(fuzzer, bar, SHIM_ISRD), - dsp_read(fuzzer, bar, SHIM_IMRD), active); - break; - default: - break; - } -} - -static uint64_t dsp_update_bits_unlocked(struct fuzz *fuzzer, - unsigned int bar, uint32_t offset, - uint32_t mask, uint32_t value) -{ - struct hsw_data *data = fuzzer->platform_data; - uint32_t old, new; - uint32_t ret; - - ret = dsp_read(fuzzer, bar, offset); - old = ret; - - new = (old & ~mask) | (value & mask); - - if (old == new) - return 0; - - dsp_write(fuzzer, bar, offset, new); - return 1; -} - -static void mailbox_read(struct fuzz *fuzzer, unsigned int offset, - void *mbox_data, unsigned int size) -{ - struct hsw_data *data = fuzzer->platform_data; - int i, j = 1; - - memcpy(mbox_data, (void *)(data->bar[HSW_MBOX_BAR] + offset), size); -} - -static void mailbox_write(struct fuzz *fuzzer, unsigned int offset, - void *mbox_data, unsigned int size) -{ - struct hsw_data *data = fuzzer->platform_data; - - memcpy((void *)(data->bar[HSW_MBOX_BAR] + offset), mbox_data, size); -} - -static int hsw_cmd_done(struct fuzz *fuzzer, int dir) -{ - if (dir == SOF_IPC_HOST_REPLY) { - /* clear BUSY bit and set DONE bit - accept new messages */ - dsp_update_bits_unlocked(fuzzer, HSW_DSP_BAR, SHIM_IPCD, - SHIM_IPCD_BUSY | - SHIM_IPCD_DONE, - SHIM_IPCD_DONE); - - /* unmask busy interrupt */ - dsp_update_bits_unlocked(fuzzer, HSW_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_BUSY, 0); - } else { - /* clear DONE bit - tell DSP we have completed */ - dsp_update_bits_unlocked(fuzzer, HSW_DSP_BAR, SHIM_IPCX, - SHIM_IPCX_DONE, 0); - - /* unmask Done interrupt */ - dsp_update_bits_unlocked(fuzzer, HSW_DSP_BAR, SHIM_IMRX, - SHIM_IMRX_DONE, 0); - } - - return 0; -} - -/* - * IPC Doorbell IRQ handler and thread. - */ - -static int hsw_irq_handler(int irq, void *context) -{ - struct fuzz *fuzzer = (struct fuzz *)context; - uint32_t isr; - int ret = IRQ_NONE; - - /* Interrupt arrived, check src */ - isr = dsp_read(fuzzer, HSW_DSP_BAR, SHIM_ISRX); - if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY)) - ret = IRQ_WAKE_THREAD; - - return ret; -} - -static int hsw_irq_thread(int irq, void *context) -{ - struct fuzz *fuzzer = (struct fuzz *)context; - struct hsw_data *data = fuzzer->platform_data; - uint32_t ipcx, ipcd; - uint32_t imrx; - - imrx = dsp_read(fuzzer, HSW_DSP_BAR, SHIM_IMRX); - ipcx = dsp_read(fuzzer, HSW_DSP_BAR, SHIM_IPCX); - - /* reply message from DSP */ - if ((ipcx & SHIM_IPCX_DONE) && - !(imrx & SHIM_IMRX_DONE)) { - /* Mask Done interrupt before first */ - dsp_update_bits_unlocked(fuzzer, HSW_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_DONE, - SHIM_IMRX_DONE); - - fprintf(stdout, "ipc: reply msg from DSP\n"); - /* - * handle immediate reply from DSP core. If the msg is - * found, set done bit in cmd_done which is called at the - * end of message processing function, else set it here - * because the done bit can't be set in cmd_done function - * which is triggered by msg - */ - - fuzzer_ipc_msg_reply(fuzzer, &data->host_box); - hsw_cmd_done(fuzzer, SOF_IPC_DSP_REPLY); - return IRQ_HANDLED; - } - - /* new message from DSP */ - ipcd = dsp_read(fuzzer, HSW_DSP_BAR, SHIM_IPCD); - if ((ipcd & SHIM_IPCD_BUSY) && - !(imrx & SHIM_IMRX_BUSY)) { - /* Mask Busy interrupt before return */ - dsp_update_bits_unlocked(fuzzer, HSW_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_BUSY, - SHIM_IMRX_BUSY); - - /* read mailbox */ - if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { - fuzzer_ipc_crash(fuzzer, &data->dsp_box, - HSW_PANIC_OFFSET(ipcd) + MBOX_OFFSET); - } else { - fuzzer_ipc_msg_rx(fuzzer, &data->dsp_box); - } - - if (!data->boot_complete && fuzzer->boot_complete) { - data->boot_complete = 1; - hsw_cmd_done(fuzzer, SOF_IPC_HOST_REPLY); - pthread_cond_signal(&cond); - return IRQ_HANDLED; - } - } - - return IRQ_HANDLED; -} - -static int hsw_send_msg(struct fuzz *fuzzer, struct ipc_msg *msg) -{ - struct fuzz_platform *plat = fuzzer->platform; - struct hsw_data *data = fuzzer->platform_data; - struct sof_ipc_cmd_hdr *hdr = (struct sof_ipc_cmd_hdr *)msg->msg_data; - uint32_t cmd = msg->header; - - /* send the message */ - fuzzer_mailbox_write(fuzzer, &data->host_box, 0, msg->msg_data, - msg->msg_size); - - dsp_write(fuzzer, HSW_DSP_BAR, SHIM_IPCX, - cmd | SHIM_IPCX_BUSY); - - return 0; -} - -static int hsw_get_reply(struct fuzz *fuzzer, struct ipc_msg *msg) -{ - struct fuzz_platform *plat = fuzzer->platform; - struct hsw_data *data = fuzzer->platform_data; - struct sof_ipc_reply reply; - int ret = 0; - uint32_t size; - - /* get reply */ - fuzzer_mailbox_read(fuzzer, &data->host_box, 0, &reply, sizeof(reply)); - - if (reply.error < 0) { - size = sizeof(reply); - ret = reply.error; - } else { - /* reply correct size ? */ - if (reply.hdr.size != msg->reply_size) { - fprintf(stderr, - "error: reply expected 0x%x got 0x%x bytes\n", - msg->reply_size, reply.hdr.size); - size = msg->reply_size; - ret = -EINVAL; - } else { - size = reply.hdr.size; - } - } - - /* read the message */ - if (msg->msg_data && size > 0) - fuzzer_mailbox_read(fuzzer, &data->host_box, 0, - msg->reply_data, size); - - return ret; -} - -/* called when we receive a message from qemu */ -static int bridge_cb(void *data, struct qemu_io_msg *msg) -{ - struct fuzz *fuzzer = (struct fuzz *)data; - - fprintf(stdout, "msg: id %d msg %d size %d type %d\n", - msg->id, msg->msg, msg->size, msg->type); - - switch (msg->type) { - case QEMU_IO_TYPE_IRQ: - /* IRQ from DSP */ - if (hsw_irq_handler(0, fuzzer) != IRQ_NONE) - hsw_irq_thread(0, fuzzer); - break; - default: - break; - } - - return 0; -} - -static int hsw_platform_init(struct fuzz *fuzzer, - struct fuzz_platform *platform) -{ - struct timespec timeout; - struct hsw_data *data; - struct timeval tp; - int i, bar; - int ret = 0; - - /* init private data */ - data = calloc(sizeof(*data), 1); - if (!data) - return -ENOMEM; - fuzzer->platform_data = data; - fuzzer->platform = platform; - - /* - * Hardcode offsets. - * TODO: read init host_box and dsp_box from fw_ready message - */ - data->host_box.offset = ADSP_BDW_DSP_MAILBOX_BASE + 0x400; - data->host_box.size = 0x400; - data->dsp_box.offset = ADSP_BDW_DSP_MAILBOX_BASE + 0x0; - data->dsp_box.size = 0x400; - - /* create SHM for memories and register regions */ - for (i = 0, bar = 0; i < platform->num_mem_regions; i++, bar++) { - data->bar[bar] = fuzzer_create_memory_region(fuzzer, bar, i); - if (!data->bar[bar]) { - fprintf(stderr, - "error: failed to create mem region %s\n", - platform->mem_region[i].name); - return -ENOMEM; - } - } - - for (i = 0; i < platform->num_reg_regions; i++, bar++) { - data->bar[bar] = fuzzer_create_io_region(fuzzer, bar, i); - if (!data->bar[bar]) { - fprintf(stderr, - "error: failed to create mem region %s\n", - platform->reg_region[i].name); - return -ENOMEM; - } - } - - /* initialise bridge to qemu */ - qemu_io_register_parent(platform->name, &bridge_cb, (void *)fuzzer); - - /* set boot wait timeout */ - gettimeofday(&tp, NULL); - timeout.tv_sec = tp.tv_sec; - timeout.tv_nsec = tp.tv_usec * 1000; - timeout.tv_sec += 5; - - /* first lock the boot wait mutex */ - pthread_mutex_lock(&data->mutex); - - /* now wait for mutex to be unlocked by boot ready message */ - while (!ret && !data->boot_complete) - ret = pthread_cond_timedwait(&cond, &data->mutex, &timeout); - - if (ret == ETIMEDOUT && !data->boot_complete) - fprintf(stderr, "error: DSP boot timeout\n"); - - pthread_mutex_unlock(&data->mutex); - - return ret; -} - -static void hsw_platform_free(struct fuzz *fuzzer) -{ - struct hsw_data *data = fuzzer->platform_data; - - fuzzer_free_regions(fuzzer); - free(data); -} - -static void hsw_fw_ready(struct fuzz *fuzzer) -{ - struct hsw_data *data = fuzzer->platform_data; - struct sof_ipc_fw_ready fw_ready; - struct sof_ipc_fw_version version; - - /* read fw_ready data from mailbox */ - fuzzer_mailbox_read(fuzzer, &data->dsp_box, 0, - &fw_ready, sizeof(fw_ready)); - - /* TODO read from FW */ - fprintf(stdout, "ipc: host box 0x%x size 0x%x\n", - data->host_box.offset, - data->host_box.size); - fprintf(stdout, "ipc: dsp box 0x%x size 0x%x\n", - data->dsp_box.offset, - data->dsp_box.size); - - version = fw_ready.version; - fprintf(stdout, "ipc: FW version major: %d minor: %d tag: %s\n", - version.major, version.minor, version.tag); -} - -struct fuzz_platform hsw_platform = { - .name = "hsw", - .send_msg = hsw_send_msg, - .get_reply = hsw_get_reply, - .init = hsw_platform_init, - .free = hsw_platform_free, - .mailbox_read = mailbox_read, - .mailbox_write = mailbox_write, - .fw_ready = hsw_fw_ready, - .num_mem_regions = ARRAY_SIZE(hsw_mem), - .mem_region = hsw_mem, - .num_reg_regions = ARRAY_SIZE(hsw_io), - .reg_region = hsw_io, -}; - -struct fuzz_platform bdw_platform = { - .name = "bdw", - .send_msg = hsw_send_msg, - .get_reply = hsw_get_reply, - .init = hsw_platform_init, - .free = hsw_platform_free, - .mailbox_read = mailbox_read, - .mailbox_write = mailbox_write, - .fw_ready = hsw_fw_ready, - .num_mem_regions = ARRAY_SIZE(bdw_mem), - .mem_region = bdw_mem, - .num_reg_regions = ARRAY_SIZE(bdw_io), - .reg_region = bdw_io, -}; diff --git a/tools/fuzzer/platform/shim.h b/tools/fuzzer/platform/shim.h deleted file mode 100644 index fef7a002410a..000000000000 --- a/tools/fuzzer/platform/shim.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * SPDX-License-Identifier: (BSD-3-Clause) - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef __SOF_INTEL_SHIM_H -#define __SOF_INTEL_SHIM_H - -#define BIT(x) (1 << x) -#define BIT_ULL(x) (1ULL << x) - -#define SHIM_OFFSET 0 - -/* - * SHIM registers for BYT, BSW, CHT, HSW, BDW - */ - -#define SHIM_CSR (SHIM_OFFSET + 0x00) -#define SHIM_PISR (SHIM_OFFSET + 0x08) -#define SHIM_PIMR (SHIM_OFFSET + 0x10) -#define SHIM_ISRX (SHIM_OFFSET + 0x18) -#define SHIM_ISRD (SHIM_OFFSET + 0x20) -#define SHIM_IMRX (SHIM_OFFSET + 0x28) -#define SHIM_IMRD (SHIM_OFFSET + 0x30) -#define SHIM_IPCX (SHIM_OFFSET + 0x38) -#define SHIM_IPCD (SHIM_OFFSET + 0x40) -#define SHIM_ISRSC (SHIM_OFFSET + 0x48) -#define SHIM_ISRLPESC (SHIM_OFFSET + 0x50) -#define SHIM_IMRSC (SHIM_OFFSET + 0x58) -#define SHIM_IMRLPESC (SHIM_OFFSET + 0x60) -#define SHIM_IPCSC (SHIM_OFFSET + 0x68) -#define SHIM_IPCLPESC (SHIM_OFFSET + 0x70) -#define SHIM_CLKCTL (SHIM_OFFSET + 0x78) -#define SHIM_CSR2 (SHIM_OFFSET + 0x80) -#define SHIM_LTRC (SHIM_OFFSET + 0xE0) -#define SHIM_HMDC (SHIM_OFFSET + 0xE8) - -#define SHIM_PWMCTRL 0x1000 - -/* - * SST SHIM register bits for BYT, BSW, CHT HSW, BDW - * Register bit naming and functionality can differ between devices. - */ - -/* CSR / CS */ -#define SHIM_CSR_RST BIT(1) -#define SHIM_CSR_SBCS0 BIT(2) -#define SHIM_CSR_SBCS1 BIT(3) -#define SHIM_CSR_DCS(x) ((x) << 4) -#define SHIM_CSR_DCS_MASK (0x7 << 4) -#define SHIM_CSR_STALL BIT(10) -#define SHIM_CSR_S0IOCS BIT(21) -#define SHIM_CSR_S1IOCS BIT(23) -#define SHIM_CSR_LPCS BIT(31) -#define SHIM_CSR_24MHZ_LPCS \ - (SHIM_CSR_SBCS0 | SHIM_CSR_SBCS1 | SHIM_CSR_LPCS) -#define SHIM_CSR_24MHZ_NO_LPCS (SHIM_CSR_SBCS0 | SHIM_CSR_SBCS1) -#define SHIM_BYT_CSR_RST BIT(0) -#define SHIM_BYT_CSR_VECTOR_SEL BIT(1) -#define SHIM_BYT_CSR_STALL BIT(2) -#define SHIM_BYT_CSR_PWAITMODE BIT(3) - -/* ISRX / ISC */ -#define SHIM_ISRX_BUSY BIT(1) -#define SHIM_ISRX_DONE BIT(0) -#define SHIM_BYT_ISRX_REQUEST BIT(1) - -/* ISRD / ISD */ -#define SHIM_ISRD_BUSY BIT(1) -#define SHIM_ISRD_DONE BIT(0) - -/* IMRX / IMC */ -#define SHIM_IMRX_BUSY BIT(1) -#define SHIM_IMRX_DONE BIT(0) -#define SHIM_BYT_IMRX_REQUEST BIT(1) - -/* IMRD / IMD */ -#define SHIM_IMRD_DONE BIT(0) -#define SHIM_IMRD_BUSY BIT(1) -#define SHIM_IMRD_SSP0 BIT(16) -#define SHIM_IMRD_DMAC0 BIT(21) -#define SHIM_IMRD_DMAC1 BIT(22) -#define SHIM_IMRD_DMAC (SHIM_IMRD_DMAC0 | SHIM_IMRD_DMAC1) - -/* IPCX / IPCC */ -#define SHIM_IPCX_DONE BIT(30) -#define SHIM_IPCX_BUSY BIT(31) -#define SHIM_BYT_IPCX_DONE BIT_ULL(62) -#define SHIM_BYT_IPCX_BUSY BIT_ULL(63) - -/* IPCD */ -#define SHIM_IPCD_DONE BIT(30) -#define SHIM_IPCD_BUSY BIT(31) -#define SHIM_BYT_IPCD_DONE BIT_ULL(62) -#define SHIM_BYT_IPCD_BUSY BIT_ULL(63) - -/* CLKCTL */ -#define SHIM_CLKCTL_SMOS(x) ((x) << 24) -#define SHIM_CLKCTL_MASK (3 << 24) -#define SHIM_CLKCTL_DCPLCG BIT(18) -#define SHIM_CLKCTL_SCOE1 BIT(17) -#define SHIM_CLKCTL_SCOE0 BIT(16) - -/* CSR2 / CS2 */ -#define SHIM_CSR2_SDFD_SSP0 BIT(1) -#define SHIM_CSR2_SDFD_SSP1 BIT(2) - -/* LTRC */ -#define SHIM_LTRC_VAL(x) ((x) << 0) - -/* HMDC */ -#define SHIM_HMDC_HDDA0(x) ((x) << 0) -#define SHIM_HMDC_HDDA1(x) ((x) << 7) -#define SHIM_HMDC_HDDA_E0_CH0 1 -#define SHIM_HMDC_HDDA_E0_CH1 2 -#define SHIM_HMDC_HDDA_E0_CH2 4 -#define SHIM_HMDC_HDDA_E0_CH3 8 -#define SHIM_HMDC_HDDA_E1_CH0 SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH0) -#define SHIM_HMDC_HDDA_E1_CH1 SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH1) -#define SHIM_HMDC_HDDA_E1_CH2 SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH2) -#define SHIM_HMDC_HDDA_E1_CH3 SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH3) -#define SHIM_HMDC_HDDA_E0_ALLCH \ - (SHIM_HMDC_HDDA_E0_CH0 | SHIM_HMDC_HDDA_E0_CH1 | \ - SHIM_HMDC_HDDA_E0_CH2 | SHIM_HMDC_HDDA_E0_CH3) -#define SHIM_HMDC_HDDA_E1_ALLCH \ - (SHIM_HMDC_HDDA_E1_CH0 | SHIM_HMDC_HDDA_E1_CH1 | \ - SHIM_HMDC_HDDA_E1_CH2 | SHIM_HMDC_HDDA_E1_CH3) - -/* Audio DSP PCI registers */ -#define PCI_VDRTCTL0 0xa0 -#define PCI_VDRTCTL1 0xa4 -#define PCI_VDRTCTL2 0xa8 -#define PCI_VDRTCTL3 0xaC - -/* VDRTCTL0 */ -#define PCI_VDRTCL0_D3PGD BIT(0) -#define PCI_VDRTCL0_D3SRAMPGD BIT(1) -#define PCI_VDRTCL0_DSRAMPGE_SHIFT 12 -#define PCI_VDRTCL0_DSRAMPGE_MASK GENMASK(PCI_VDRTCL0_DSRAMPGE_SHIFT + 19,\ - PCI_VDRTCL0_DSRAMPGE_SHIFT) -#define PCI_VDRTCL0_ISRAMPGE_SHIFT 2 -#define PCI_VDRTCL0_ISRAMPGE_MASK GENMASK(PCI_VDRTCL0_ISRAMPGE_SHIFT + 9,\ - PCI_VDRTCL0_ISRAMPGE_SHIFT) - -/* VDRTCTL2 */ -#define PCI_VDRTCL2_DCLCGE BIT(1) -#define PCI_VDRTCL2_DTCGE BIT(10) -#define PCI_VDRTCL2_APLLSE_MASK BIT(31) - -/* PMCS */ -#define PCI_PMCS 0x84 -#define PCI_PMCS_PS_MASK 0x3 - -#endif diff --git a/tools/fuzzer/qemu-bridge.c b/tools/fuzzer/qemu-bridge.c deleted file mode 100644 index 2f2680a2f99b..000000000000 --- a/tools/fuzzer/qemu-bridge.c +++ /dev/null @@ -1,395 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -/* - * Creates an IO bridge between two QEMU instances where messages can be passed - * between the parent and child instances via messages queues and shared memory. - * - * The parent is usually the QEMU instance that runs the operating system (like - * Linux) on the application processor whilst the child is typically a smaller - * processor running an embedded firmware. The parent and child do not need to - * be the same architecture but are expected to communicate over a local bus. - */ - -#include <mqueue.h> -#include <unistd.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#include <stdint.h> -#include <stdbool.h> -#include <stdio.h> -#include <glib.h> -#include <errno.h> -#include "qemu-bridge.h" - -/* set to 1 to enable debug */ -static int io_bridge_debug;//QEMU_IO_DEBUG; - -/* we can either be parent or child */ -#define ROLE_NONE 0 -#define ROLE_PARENT 1 -#define ROLE_CHILD 2 - -static int role = ROLE_NONE; - -#define QEMU_IO_MAX_MSGS 8 -#define QEMU_IO_MAX_MSG_SIZE 128 -#define QEMU_IO_MAX_SHM_REGIONS 32 - -#define NAME_SIZE 64 - -struct io_shm { - int fd; - void *addr; - char name[NAME_SIZE]; - size_t size; -}; - -struct io_mq { - char mq_name[NAME_SIZE]; - char thread_name[NAME_SIZE]; - struct mq_attr mqattr; - mqd_t mqdes; -}; - -struct io_bridge { - struct io_mq parent; - struct io_mq child; - GThread *io_thread; - int (*cb)(void *data, struct qemu_io_msg *msg); - struct io_shm shm[QEMU_IO_MAX_SHM_REGIONS]; - void *data; -}; - -static struct io_bridge _iob; -static int _id; - -/* parent reader Q */ -static gpointer parent_reader_thread(gpointer data) -{ - struct io_bridge *io = data; - char buf[QEMU_IO_MAX_MSG_SIZE]; - int i; - - mq_getattr(io->parent.mqdes, &io->parent.mqattr); - if (io_bridge_debug) - fprintf(stdout, "bridge-io: %d messages are currently on parent queue.\n", - (int)io->parent.mqattr.mq_curmsgs); - - while (mq_receive(io->parent.mqdes, buf, QEMU_IO_MAX_MSG_SIZE, - NULL) != -1) { - struct qemu_io_msg *hdr = (struct qemu_io_msg *)buf; - - if (io_bridge_debug) - fprintf(stdout, "bridge-io: msg recv %d type %d size %d msg %d\n", - hdr->id, hdr->type, hdr->size, hdr->msg); - - if (io->cb) - io->cb(io->data, hdr); - } - - return 0; -} - -/* child reader Q */ -static gpointer child_reader_thread(gpointer data) -{ - struct io_bridge *io = data; - char buf[QEMU_IO_MAX_MSG_SIZE]; - int i; - - mq_getattr(io->child.mqdes, &io->child.mqattr); - if (io_bridge_debug) - fprintf(stdout, "bridge-io: %d messages are currently on child queue.\n", - (int)io->child.mqattr.mq_curmsgs); - - /* flush old messages here */ - for (i = 0; i < io->child.mqattr.mq_curmsgs; i++) { - mq_receive(io->child.mqdes, buf, QEMU_IO_MAX_MSG_SIZE, NULL); - struct qemu_io_msg *hdr = (struct qemu_io_msg *)buf; - - if (io_bridge_debug) - fprintf(stdout, "bridge-io: flushed %d type %d size %d msg %d\n", - hdr->id, hdr->type, hdr->size, hdr->msg); - } - - while (mq_receive(io->child.mqdes, buf, QEMU_IO_MAX_MSG_SIZE, - NULL) != -1) { - struct qemu_io_msg *hdr = (struct qemu_io_msg *)buf; - - if (io_bridge_debug) - fprintf(stdout, "bridge-io: msg recv %d type %d size %d msg %d\n", - hdr->id, hdr->type, hdr->size, hdr->msg); - - if (io->cb) - io->cb(io->data, hdr); - } - - return 0; -} - -static int mq_init(const char *name, struct io_bridge *io) -{ - int ret = 0; - - io->parent.mqattr.mq_maxmsg = QEMU_IO_MAX_MSGS; - io->parent.mqattr.mq_msgsize = QEMU_IO_MAX_MSG_SIZE; - io->parent.mqattr.mq_flags = 0; - io->parent.mqattr.mq_curmsgs = 0; - - io->child.mqattr.mq_maxmsg = QEMU_IO_MAX_MSGS; - io->child.mqattr.mq_msgsize = QEMU_IO_MAX_MSG_SIZE; - io->child.mqattr.mq_flags = 0; - io->child.mqattr.mq_curmsgs = 0; - - if (role == ROLE_PARENT) { - - /* Host */ - - sprintf(io->parent.thread_name, "io-bridge-%s", name); - io->io_thread = g_thread_new(io->parent.thread_name, - parent_reader_thread, io); - - /* parent Rx Q */ - sprintf(io->parent.mq_name, "/qemu-io-parent-%s", name); - io->parent.mqdes = mq_open(io->parent.mq_name, - O_RDONLY | O_CREAT, - 0664, &io->parent.mqattr); - if (io->parent.mqdes < 0) { - fprintf(stderr, "failed to open parent Rx queue %d\n", - -errno); - ret = -errno; - } - - /* parent Tx Q */ - sprintf(io->child.mq_name, "/qemu-io-child-%s", name); - io->child.mqdes = mq_open(io->child.mq_name, - O_WRONLY | O_CREAT, - 0664, &io->child.mqattr); - if (io->child.mqdes < 0) { - fprintf(stderr, "failed to open parent Tx queue %d\n", - -errno); - ret = -errno; - } - } else { - - /* DSP */ - - sprintf(io->child.thread_name, "io-bridge-%s", name); - io->io_thread = g_thread_new(io->child.thread_name, - child_reader_thread, io); - - /* child Rx Q */ - sprintf(io->child.mq_name, "/qemu-io-child-%s", name); - mq_unlink(io->child.mq_name); - io->child.mqdes = mq_open(io->child.mq_name, - O_RDONLY | O_CREAT, - 0664, &io->child.mqattr); - if (io->child.mqdes < 0) { - fprintf(stderr, "failed to open child Rx queue %d\n", - -errno); - ret = -errno; - } - - /* child Tx Q */ - sprintf(io->parent.mq_name, "/qemu-io-parent-%s", name); - mq_unlink(io->parent.mq_name); - io->parent.mqdes = mq_open(io->parent.mq_name, - O_WRONLY | O_CREAT, - 0664, &io->parent.mqattr); - if (io->parent.mqdes < 0) { - fprintf(stderr, "failed to open child Tx queue %d\n", - -errno); - ret = -errno; - } - } - - if (ret == 0 && io_bridge_debug) { - fprintf(stdout, "bridge-io-mq: added %s\n", - io->parent.mq_name); - fprintf(stdout, "bridge-io-mq: added %s\n", io->child.mq_name); - } - - return ret; -} - -int qemu_io_register_parent(const char *name, - int (*cb)(void *, struct qemu_io_msg *msg), - void *data) -{ - if (role != ROLE_NONE) - return -EINVAL; - - role = ROLE_PARENT; - _iob.cb = cb; - _iob.data = data; - - mq_init(name, &_iob); - - return 0; -} - -int qemu_io_register_child(const char *name, - int (*cb)(void *, struct qemu_io_msg *msg), - void *data) -{ - int ret = 0; - - if (role != ROLE_NONE) - return -EINVAL; - - role = ROLE_CHILD; - _iob.cb = cb; - _iob.data = data; - - mq_init(name, &_iob); - - return ret; -} - -int qemu_io_register_shm(const char *rname, int region, size_t size, - void **addr) -{ - char *name; - int fd, ret; - void *a; - - /* check that region is not already in use */ - if (_iob.shm[region].fd) - return -EBUSY; - - name = _iob.shm[region].name; - sprintf(name, "qemu-bridge-%s", rname); - - fd = shm_open(name, O_RDWR | O_CREAT, 0664); - if (fd < 0) { - fprintf(stderr, "bridge-io: can't open SHM %d\n", errno); - return -errno; - } - - ret = ftruncate(fd, size); - if (ret < 0) { - fprintf(stderr, "bridge-io: can't truncate %d\n", errno); - shm_unlink(name); - return -errno; - } - - a = mmap(*addr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (!a) { - fprintf(stderr, "bridge-io: can't open mmap %d\n", errno); - shm_unlink(name); - return -errno; - } - - if (io_bridge_debug) - fprintf(stdout, "bridge-io: %s fd %d region %d at %p allocated %zu bytes\n", - name, fd, region, a, size); - _iob.shm[region].fd = fd; - _iob.shm[region].addr = a; - _iob.shm[region].size = size; - *addr = a; - - return ret; -} - -#define PAGE_SIZE 4096 - -int qemu_io_sync(int region, unsigned int offset, size_t length) -{ - if (region < 0 || region > QEMU_IO_MAX_SHM_REGIONS) - return -EINVAL; - - /* check that region is in use */ - if (_iob.shm[region].fd == 0) - return -EINVAL; - - /* align offset to pagesize */ - offset -= (offset % PAGE_SIZE); - - return msync(_iob.shm[region].addr + offset, length, - MS_SYNC | MS_INVALIDATE); -} - -int qemu_io_send_msg(struct qemu_io_msg *msg) -{ - int ret; - - msg->id = _id++; - - if (role == ROLE_PARENT) - ret = mq_send(_iob.child.mqdes, (const char *)msg, msg->size, - 0); - else - ret = mq_send(_iob.parent.mqdes, (const char *)msg, msg->size, - 0); - - if (io_bridge_debug) - fprintf(stdout, "bridge-io: msg send: %d type %d msg %d size %d ret %d\n", - msg->id, msg->type, msg->msg, msg->size, ret); - if (ret < 0) - fprintf(stderr, "bridge-io: msg send failed %d\n", -errno); - - return ret; -} - -int qemu_io_send_msg_reply(struct qemu_io_msg *msg) -{ - int ret; - - if (role == ROLE_PARENT) - ret = mq_send(_iob.child.mqdes, (const char *)msg, msg->size, - 0); - else - ret = mq_send(_iob.parent.mqdes, (const char *)msg, msg->size, - 0); - - if (io_bridge_debug) - fprintf(stdout, "bridge-io: repmsg send: %d type %d msg %d size %d ret %d\n", - msg->id, msg->type, msg->msg, msg->size, ret); - if (ret < 0) - fprintf(stderr, "bridge-io: rmsg send failed %d\n", -errno); - - return ret; -} - -void qemu_io_free(void) -{ - int i; - - for (i = 0; i < QEMU_IO_MAX_SHM_REGIONS; i++) { - if (_iob.shm[i].fd) { - munmap(_iob.shm[i].addr, _iob.shm[i].size); - shm_unlink(_iob.shm[i].name); - close(_iob.shm[i].fd); - } - } - - mq_unlink(_iob.parent.mq_name); - mq_unlink(_iob.child.mq_name); - - mq_close(_iob.parent.mqdes); - mq_close(_iob.child.mqdes); -} - -void qemu_io_free_shm(int region) -{ - int err; - - if (region < QEMU_IO_MAX_SHM_REGIONS && _iob.shm[region].fd) { - err = munmap(_iob.shm[region].addr, _iob.shm[region].size); - if (err < 0) - fprintf(stderr, "bridge-io: munmap failed %d\n", - errno); - - /* client or host can unlink this, so it gets done twice */ - shm_unlink(_iob.shm[region].name); - close(_iob.shm[region].fd); - _iob.shm[region].fd = 0; - } -} diff --git a/tools/fuzzer/qemu-bridge.h b/tools/fuzzer/qemu-bridge.h deleted file mode 100644 index ebfa2704974c..000000000000 --- a/tools/fuzzer/qemu-bridge.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> - */ - -#ifndef IO_BRIDGE_H -#define IO_BRIDGE_H - -#include <stdint.h> - -#define QEMU_IO_DEBUG 0 - -/* IO type */ -#define QEMU_IO_TYPE_QEMU 0 -#define QEMU_IO_TYPE_REG 1 -#define QEMU_IO_TYPE_IRQ 2 -#define QEMU_IO_TYPE_GDB 3 -#define QEMU_IO_TYPE_PM 4 -#define QEMU_IO_TYPE_DMA 5 -#define QEMU_IO_TYPE_MEM 6 - -/* Global Message Reply */ -#define QEMU_IO_MSG_REPLY 0 - -/* Register Messages */ -#define QEMU_IO_MSG_REG32W 32 -#define QEMU_IO_MSG_REG64W 33 -#define QEMU_IO_MSG_REG32R 34 -#define QEMU_IO_MSG_REG64R 35 - -/* IRQ Messages */ -#define QEMU_IO_MSG_IRQ 64 - -/* DMA Messages */ -#define QEMU_IO_DMA_REQ_NEW 96 -#define QEMU_IO_DMA_REQ_READY 97 -#define QEMU_IO_DMA_REQ_COMPLETE 98 - -/* DMA Direction - relative to msg sender */ -#define QEMU_IO_DMA_DIR_READ 256 -#define QEMU_IO_DMA_DIR_WRITE 257 - -/* GDB Messages */ -#define QEMU_IO_GDB_STALL 128 -#define QEMU_IO_GDB_CONT 129 -#define QEMU_IO_GDB_STALL_RPLY 130 /* stall after reply */ - -/* PM Messages */ -#define QEMU_IO_PM_S0 192 -#define QEMU_IO_PM_S1 193 -#define QEMU_IO_PM_S2 194 -#define QEMU_IO_PM_S3 195 -#define QEMU_IO_PM_D0 196 -#define QEMU_IO_PM_D1 197 -#define QEMU_IO_PM_D2 198 -#define QEMU_IO_PM_D3 199 - -/* Common message header */ -struct qemu_io_msg { - uint16_t type; - uint16_t msg; - uint32_t size; - uint32_t id; -}; - -/* Generic message reply */ -struct qemu_io_msg_reply { - struct qemu_io_msg hdr; - uint32_t reply; -}; - -/* Register messages */ -struct qemu_io_msg_reg32 { - struct qemu_io_msg hdr; - uint32_t reg; - uint32_t val; -}; - -struct qemu_io_msg_reg64 { - struct qemu_io_msg hdr; - uint64_t reg; - uint64_t val; -}; - -/* IRQ Messages */ -struct qemu_io_msg_irq { - struct qemu_io_msg hdr; - uint32_t irq; -}; - -/* PM Messages */ -struct qemu_io_msg_pm_state { - struct qemu_io_msg hdr; -}; - -/* DMA Messages - same message used as reply */ -struct qemu_io_msg_dma32 { - struct qemu_io_msg hdr; - uint32_t direction; /* QEMU_IO_DMA_DIR_ */ - uint32_t reply; /* 0 or errno */ - uint32_t src; - uint32_t dest; - uint32_t size; - uint32_t dmac_id; - uint32_t chan_id; - uint64_t host_data; - uint64_t client_data; -}; - -struct qemu_io_msg_dma64 { - struct qemu_io_msg hdr; - uint32_t direction; /* QEMU_IO_DMA_DIR_ */ - uint32_t reply; /* 0 or errno */ - uint64_t src; - uint64_t dest; - uint64_t size; - uint32_t dmac_id; - uint32_t chan_id; - uint64_t host_data; - uint64_t client_data; -}; - -/* API calls for parent and child */ -int qemu_io_register_parent(const char *name, - int (*cb)(void *, struct qemu_io_msg *msg), - void *data); -int qemu_io_register_child(const char *name, - int (*cb)(void *, struct qemu_io_msg *msg), - void *data); - -int qemu_io_send_msg(struct qemu_io_msg *msg); -int qemu_io_send_msg_reply(struct qemu_io_msg *msg); - -int qemu_io_register_shm(const char *name, int region, size_t size, - void **addr); -int qemu_io_sync(int region, unsigned int offset, size_t length); - -void qemu_io_free(void); -void qemu_io_free_shm(int region); - -#endif diff --git a/tools/fuzzer/topology.c b/tools/fuzzer/topology.c deleted file mode 100644 index 83e49c6ea53b..000000000000 --- a/tools/fuzzer/topology.c +++ /dev/null @@ -1,458 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -/* Topology loader to set up components and pipeline */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <stddef.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> -#include "../fuzzer/fuzzer.h" -#include <ipc/topology.h> -#include <ipc/stream.h> -#include <sof/common.h> -#include <tplg_parser/topology.h> - -const struct sof_dai_types sof_dais[] = { - {"SSP", SOF_DAI_INTEL_SSP}, - {"HDA", SOF_DAI_INTEL_HDA}, - {"DMIC", SOF_DAI_INTEL_DMIC}, -}; - -/* find dai type */ -enum sof_ipc_dai_type find_dai(const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sof_dais); i++) { - if (strcmp(name, sof_dais[i].name) == 0) - return sof_dais[i].type; - } - - return SOF_DAI_INTEL_NONE; -} - -void register_comp(int comp_type) {} - -int find_widget(struct comp_info *temp_comp_list, int count, char *name) -{ - int i; - - for (i = 0; i < count; i++) { - if (!strcmp(temp_comp_list[i].name, name)) - return temp_comp_list[i].id; - } - - return -EINVAL; -} - -int complete_pipeline(struct fuzz *fuzzer, uint32_t comp_id) -{ - struct sof_ipc_pipe_ready ready; - struct sof_ipc_reply r; - int ret; - - fprintf(stdout, "tplg: complete pipeline id %d\n", comp_id); - - ready.hdr.size = sizeof(ready); - ready.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_COMPLETE; - ready.comp_id = comp_id; - - /* configure fuzzer msg */ - fuzzer->msg.header = ready.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &ready, ready.hdr.size); - fuzzer->msg.msg_size = sizeof(ready); - fuzzer->msg.reply_size = sizeof(r); - - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - return ret; - - return 1; -} - -/* load pipeline graph DAPM widget*/ -static int load_graph(void *dev, struct comp_info *temp_comp_list, - int count, int num_comps, int pipeline_id) -{ - struct sof_ipc_pipe_comp_connect connection; - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_reply r; - char pipeline_string[DEBUG_MSG_LEN]; - int ret = 0; - int i; - - for (i = 0; i < count; i++) { - ret = tplg_load_graph(num_comps, pipeline_id, temp_comp_list, - pipeline_string, &connection, - fuzzer->tplg_file, i, count); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = connection.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &connection, connection.hdr.size); - fuzzer->msg.msg_size = sizeof(connection); - fuzzer->msg.reply_size = sizeof(r); - - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - } - - return ret; -} - -/* load buffer DAPM widget */ -int load_buffer(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct sof_ipc_buffer buffer; - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_reply r; - int ret; - - ret = tplg_load_buffer(comp_id, pipeline_id, widget->priv.size, &buffer, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = buffer.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &buffer, buffer.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(buffer); - fuzzer->msg.reply_size = sizeof(r); - - /* load volume component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return 0; -} - -/* load pcm component */ -static int load_pcm(void *dev, int comp_id, int pipeline_id, int size, int dir) -{ - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_host host; - struct sof_ipc_comp_reply r; - int ret; - - ret = tplg_load_pcm(comp_id, pipeline_id, size, dir, &host, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = host.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &host, host.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(host); - fuzzer->msg.reply_size = sizeof(r); - - /* load volume component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - return 0; -} - -int load_aif_in_out(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, void *tp) -{ - return load_pcm(dev, comp_id, pipeline_id, widget->priv.size, dir); -} - -/* load dai component */ -static int load_dai(struct fuzz *fuzzer, int comp_id, int pipeline_id, - int size) -{ - struct sof_ipc_comp_dai comp_dai; - struct sof_ipc_comp_reply r; - int ret; - - ret = tplg_load_dai(comp_id, pipeline_id, size, &comp_dai, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = comp_dai.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &comp_dai, comp_dai.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(comp_dai); - fuzzer->msg.reply_size = sizeof(r); - - /* load volume component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return 0; -} - -int load_dai_in_out(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, void *tp) -{ - return load_dai(dev, comp_id, pipeline_id, widget->priv.size); -} - -/* load pda dapm widget */ -int load_pga(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_volume volume; - struct sof_ipc_comp_reply r; - int ret = 0; - - ret = tplg_load_pga(comp_id, pipeline_id, widget->priv.size, &volume, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = volume.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &volume, volume.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(volume); - fuzzer->msg.reply_size = sizeof(r); - - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return 0; -} - -/* load scheduler dapm widget */ -int load_pipeline(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int sched_id) -{ - struct sof_ipc_pipe_new pipeline; - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_reply r; - int ret; - - ret = tplg_load_pipeline(comp_id, pipeline_id, widget->priv.size, - &pipeline, fuzzer->tplg_file); - if (ret < 0) - return ret; - - pipeline.sched_id = sched_id; - - /* configure fuzzer msg */ - fuzzer->msg.header = pipeline.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &pipeline, pipeline.hdr.size); - fuzzer->msg.msg_size = sizeof(pipeline); - fuzzer->msg.reply_size = sizeof(r); - - /* load volume component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return 0; -} - -/* load src dapm widget */ -int load_src(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, void *params) -{ - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_src src = {0}; - struct sof_ipc_comp_reply r; - int ret = 0; - - ret = tplg_load_src(comp_id, pipeline_id, widget->priv.size, &src, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = src.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &src, src.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(src); - fuzzer->msg.reply_size = sizeof(r); - - /* load volume component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return ret; -} - -/* load asrc dapm widget */ -int load_asrc(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, void *params) -{ - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_asrc asrc = {0}; - struct sof_ipc_comp_reply r; - int ret = 0; - - ret = tplg_load_asrc(comp_id, pipeline_id, widget->priv.size, &asrc, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = asrc.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &asrc, asrc.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(asrc); - fuzzer->msg.reply_size = sizeof(r); - - /* load asrc component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return ret; -} - -/* load mixer dapm widget */ -int load_mixer(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct fuzz *fuzzer = (struct fuzz *)dev; - struct sof_ipc_comp_mixer mixer = {0}; - struct sof_ipc_comp_reply r; - int ret = 0; - - ret = tplg_load_mixer(comp_id, pipeline_id, widget->priv.size, &mixer, - fuzzer->tplg_file); - if (ret < 0) - return ret; - - /* configure fuzzer msg */ - fuzzer->msg.header = mixer.comp.hdr.cmd; - memcpy(fuzzer->msg.msg_data, &mixer, mixer.comp.hdr.size); - fuzzer->msg.msg_size = sizeof(mixer); - fuzzer->msg.reply_size = sizeof(r); - - /* load volume component */ - ret = fuzzer_send_msg(fuzzer); - if (ret < 0) - fprintf(stderr, "error: message tx failed\n"); - - return ret; -} - -/* load effect dapm widget */ -int load_process(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - return -EINVAL; /* Not implemented */ -} - -/* parse topology file and set up pipeline */ -int parse_tplg(struct fuzz *fuzzer, char *tplg_filename) -{ - struct snd_soc_tplg_hdr *hdr; - - struct comp_info *temp_comp_list = NULL; - char message[DEBUG_MSG_LEN]; - int next_comp_id = 0, num_comps = 0; - int i, ret = 0; - size_t file_size, size; - int sched_id; - - /* open topology file */ - fuzzer->tplg_file = fopen(tplg_filename, "rb"); - if (!fuzzer->tplg_file) { - fprintf(stderr, "error: opening topology file %s\n", - tplg_filename); - return -errno; - } - - /* file size */ - fseek(fuzzer->tplg_file, 0, SEEK_END); - file_size = ftell(fuzzer->tplg_file); - fseek(fuzzer->tplg_file, 0, SEEK_SET); - - /* allocate memory */ - size = sizeof(struct snd_soc_tplg_hdr); - hdr = (struct snd_soc_tplg_hdr *)malloc(size); - if (!hdr) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - fprintf(stdout, "debug: %s", "topology parsing start\n"); - - while (1) { - /* read topology header */ - ret = fread(hdr, sizeof(struct snd_soc_tplg_hdr), 1, - fuzzer->tplg_file); - if (ret != 1) - return -EINVAL; - - sprintf(message, "type: %x, size: 0x%x count: %d index: %d\n", - hdr->type, hdr->payload_size, hdr->count, hdr->index); - fprintf(stdout, "debug %s", message); - - /* parse header and load the next block based on type */ - switch (hdr->type) { - /* load dapm widget */ - case SND_SOC_TPLG_TYPE_DAPM_WIDGET: - sprintf(message, "number of DAPM widgets %d\n", - hdr->count); - fprintf(stdout, "debug %s\n", message); - - num_comps += hdr->count; - size = sizeof(struct comp_info) * num_comps; - temp_comp_list = (struct comp_info *) - realloc(temp_comp_list, size); - - for (i = (num_comps - hdr->count); i < num_comps; i++) - ret = load_widget(fuzzer, FUZZER_DEV, - temp_comp_list, - next_comp_id++, i, - hdr->index, NULL, &sched_id, - fuzzer->tplg_file); - if (ret < 0) { - fprintf(stderr, "error: loading widget\n"); - goto finish; - } - break; - - /* set up component connections from pipeline graph */ - case SND_SOC_TPLG_TYPE_DAPM_GRAPH: - if (load_graph(fuzzer, temp_comp_list, hdr->count, - num_comps, hdr->index) < 0) { - fprintf(stderr, "error: pipeline graph\n"); - return -EINVAL; - } - if (ftell(fuzzer->tplg_file) == file_size) - goto finish; - break; - default: - fseek(fuzzer->tplg_file, hdr->payload_size, SEEK_CUR); - if (ftell(fuzzer->tplg_file) == file_size) - goto finish; - break; - } - } -finish: - /* pipeline complete after pipeline connections are established */ - for (i = 0; i < num_comps; i++) - if (temp_comp_list[i].type == SND_SOC_TPLG_DAPM_SCHEDULER) - complete_pipeline(fuzzer, temp_comp_list[i].id); - - fprintf(stdout, "debug: %s", "topology parsing end\n"); - - /* free all data */ - free(hdr); - - for (i = 0; i < num_comps; i++) - free(temp_comp_list[i].name); - - free(temp_comp_list); - fclose(fuzzer->tplg_file); - return 0; -} diff --git a/tools/logger/CMakeLists.txt b/tools/logger/CMakeLists.txt index 1fdc9b2100cb..ac83f5687454 100644 --- a/tools/logger/CMakeLists.txt +++ b/tools/logger/CMakeLists.txt @@ -1,17 +1,50 @@ # SPDX-License-Identifier: BSD-3-Clause +# https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/How-To-Write-Platform-Checks +INCLUDE (CheckIncludeFiles) +CHECK_INCLUDE_FILES(sys/inotify.h HAS_INOTIFY) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + add_executable(sof-logger logger.c convert.c + filter.c + misc.c ) +include(../../scripts/cmake/misc.cmake) +include(../../scripts/cmake/uuid-registry.cmake) + +if(${CMAKE_HOST_WIN32}) + cmake_minimum_required(VERSION 3.20) + if(DEFINED ENV{MSYS_INSTALL_DIR}) + set(MSYS_INSTALL_DIR $ENV{MSYS_INSTALL_DIR}) + cmake_path(IS_ABSOLUTE MSYS_INSTALL_DIR IS_MSYS_INSTALL_DIR_ABSOLUTE) + if(NOT IS_MSYS_INSTALL_DIR_ABSOLUTE) + message(FATAL_ERROR "Please provide absolute path to MSYS2 installation + setting MSYS_INSTALL_DIR env variable") + endif() + cmake_path(APPEND MSYS_INSTALL_DIR "usr" "include" OUTPUT_VARIABLE MSYS_SYSTEM_INCLUDE_PATH) + target_include_directories(sof-logger PRIVATE "${MSYS_SYSTEM_INCLUDE_PATH}") + endif() +endif() + target_compile_options(sof-logger PRIVATE -Wall -Werror ) target_include_directories(sof-logger PRIVATE "${SOF_ROOT_SOURCE_DIRECTORY}/src/include" + "${SOF_ROOT_SOURCE_DIRECTORY}/tools/rimage/src/include" "${SOF_ROOT_SOURCE_DIRECTORY}" ) +# TODO: logger should not need to include RTOS headers. FIX. +target_include_directories(sof-logger PRIVATE + "${SOF_ROOT_SOURCE_DIRECTORY}/xtos/include" +) + install(TARGETS sof-logger DESTINATION bin) diff --git a/tools/logger/config.h.in b/tools/logger/config.h.in new file mode 100644 index 000000000000..fecbafbd274c --- /dev/null +++ b/tools/logger/config.h.in @@ -0,0 +1 @@ +#cmakedefine01 HAS_INOTIFY diff --git a/tools/logger/convert.c b/tools/logger/convert.c index 570628d9ceee..4e0a6cdc59ae 100644 --- a/tools/logger/convert.c +++ b/tools/logger/convert.c @@ -5,7 +5,9 @@ // Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> // Artur Kloniecki <arturx.kloniecki@linux.intel.com> -#include <stdarg.h> +#include <assert.h> +#include <endian.h> +#include <stdbool.h> #include <stdlib.h> #include <stdint.h> #include <string.h> @@ -13,9 +15,12 @@ #include <unistd.h> #include <math.h> #include <sof/lib/uuid.h> +#include <time.h> #include <user/abi_dbg.h> #include <user/trace.h> #include "convert.h" +#include "filter.h" +#include "misc.h" #define CEIL(a, b) ((a+b-1)/b) @@ -26,6 +31,9 @@ #define TRACE_IDS_MASK ((1 << TRACE_ID_LENGTH) - 1) #define INVALID_TRACE_ID (-1 & TRACE_IDS_MASK) +/** Dictionary entry. This MUST match the start of the linker output + * defined by _DECLARE_LOG_ENTRY(). + */ struct ldc_entry_header { uint32_t level; uint32_t component_class; @@ -35,6 +43,7 @@ struct ldc_entry_header { uint32_t text_len; }; +/** Dictionary entry + unformatted parameters */ struct ldc_entry { struct ldc_entry_header header; char *file_name; @@ -42,6 +51,7 @@ struct ldc_entry { uint32_t *params; }; +/** Dictionary entry + formatted parameters */ struct proc_ldc_entry { int subst_mask; struct ldc_entry_header header; @@ -50,96 +60,243 @@ struct proc_ldc_entry { uintptr_t params[TRACE_MAX_PARAMS_COUNT]; }; -static const char *BAD_PTR_STR = "<bad uid ptr %x>"; +#define BAD_PTR_STR "<bad uid ptr 0x%.8x>" +#define UUID_LOWER "%s%s%s<%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%s%s%s" +#define UUID_UPPER "%s%s%s<%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X>%s%s%s" -static void log_err(FILE *out_fd, const char *fmt, ...) +static const char *missing = "<missing>"; + +static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_address); + +char *format_uid_raw(const struct sof_uuid_entry *uid_entry, int use_colors, int name_first, + bool be, bool upper) { - ssize_t needed_size; - va_list args, args_alloc; - char *buff; - - va_start(args, fmt); - - va_copy(args_alloc, args); - needed_size = vsnprintf(NULL, 0, fmt, args_alloc) + 1; - buff = malloc(needed_size); - va_end(args_alloc); - - if (buff) { - vsprintf(buff, fmt, args); - fprintf(stderr, "%s", buff); - if (out_fd) { - fprintf(out_fd, "%s", buff); - fflush(out_fd); - } - free(buff); - } else { - vfprintf(stderr, fmt, args); - } + const struct sof_uuid *uid_val = &uid_entry->id; + uint32_t a = be ? htobe32(uid_val->a) : uid_val->a; + uint16_t b = be ? htobe16(uid_val->b) : uid_val->b; + uint16_t c = be ? htobe16(uid_val->c) : uid_val->c; + char *str; + + str = log_asprintf(upper ? UUID_UPPER : UUID_LOWER, + use_colors ? KBLU : "", + name_first ? uid_entry->name : "", + name_first ? " " : "", + a, b, c, + uid_val->d[0], uid_val->d[1], uid_val->d[2], + uid_val->d[3], uid_val->d[4], uid_val->d[5], + uid_val->d[6], uid_val->d[7], + name_first ? "" : " ", + name_first ? "" : uid_entry->name, + use_colors ? KNRM : ""); + return str; +} + +static const struct sof_uuid_entry *get_uuid_entry(uint32_t uid_ptr) +{ + const struct snd_sof_uids_header *uids_dict = global_config->uids_dict; - va_end(args); + return (const struct sof_uuid_entry *) + ((uint8_t *)uids_dict + uids_dict->data_offset + uid_ptr - + uids_dict->base_address); } -const char *format_uid(const struct snd_sof_uids_header *uids_dict, - uint32_t uid_ptr, - int use_colors) +/* + * Use uids dictionary content, to convert address of uuid `entry` from logger + * memory space to corresponding uuid key address used in firmware trace system + * (with base UUID_ENTRY_ELF_BASE, 0x1FFFA000 as usual). Function get_uuid_entry + * works in oppopsite direction. + */ +uint32_t get_uuid_key(const struct sof_uuid_entry *entry) { + const struct snd_sof_uids_header *uids_dict = global_config->uids_dict; + + /* + * uids_dict->data_offset and uids_dict->base_address are both constants, + * related with given ldc file. + * Uuid address used in firmware, points unusable memory region, + * so its treated as key value. + */ + return (uintptr_t)entry - (uintptr_t)uids_dict - + uids_dict->data_offset + uids_dict->base_address; +} + +static const char *format_uid(uint32_t uid_ptr, int use_colors, bool be, bool upper) +{ + const struct snd_sof_uids_header *uids_dict = global_config->uids_dict; + const struct sof_uuid_entry *uid_entry; char *str; if (uid_ptr < uids_dict->base_address || uid_ptr >= uids_dict->base_address + uids_dict->data_length) { str = calloc(1, strlen(BAD_PTR_STR) + 1 + 6); + if (!str) { + log_err("can't allocate memory\n"); + exit(EXIT_FAILURE); + } sprintf(str, BAD_PTR_STR, uid_ptr); } else { - const struct sof_uuid *uid_val = (const struct sof_uuid *) - ((uint8_t *)uids_dict + uids_dict->data_offset + - uid_ptr - uids_dict->base_address); - - str = calloc(1, (use_colors ? strlen(KBLU) : 0) + 1 + - 36 + 1 + *(uint32_t *)(uid_val + 1) + 1 + - (use_colors ? strlen(KNRM) : 0)); - sprintf(str, "%s%s <%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%s", - use_colors ? KBLU : "", - (const char *)(uid_val + 1) + 4, - uid_val->a, uid_val->b, uid_val->c, - uid_val->d[0], uid_val->d[1], uid_val->d[2], - uid_val->d[3], uid_val->d[4], uid_val->d[5], - uid_val->d[6], uid_val->d[7], - use_colors ? KNRM : ""); + uid_entry = get_uuid_entry(uid_ptr); + str = format_uid_raw(uid_entry, use_colors, 1, be, upper); } + return str; } +/* fmt should point '%pUx`, return pointer to UUID string or zero */ +static const char *asprintf_uuid(const char *fmt, uint32_t uuid_key, bool use_colors, int *fmt_len) +{ + const char *fmt_end = fmt + strlen(fmt); + int be, upper; + int len = 4; /* assure full formating, with x */ + + if (fmt + 2 >= fmt_end || fmt[1] != 'p' || fmt[2] != 'U') { + *fmt_len = 0; + return NULL; + } + /* check 'x' value */ + switch (fmt + 3 < fmt_end ? fmt[3] : 0) { + case 'b': + be = 1; + upper = 0; + break; + case 'B': + be = 1; + upper = 1; + break; + case 'l': + be = 0; + upper = 0; + break; + case 'L': + be = 0; + upper = 1; + break; + default: + be = 0; + upper = 0; + --len; + break; + } + *fmt_len = len; + return format_uid(uuid_key, use_colors, be, upper); +} + +static const char *asprintf_entry_text(uint32_t entry_address) +{ + struct ldc_entry entry; + int ret; + + ret = read_entry_from_ldc_file(&entry, entry_address); + if (ret) + return NULL; + + free(entry.file_name); + + return entry.text; +} + +/** printf-like formatting from the binary ldc_entry input to the + * formatted proc_lpc_entry output. Also copies the unmodified + * ldc_entry_header from input to output. + * + * @param[out] pe copy of the header + formatted output + * @param[in] e copy of the dictionary entry where unformatted, + uint32_t params have been inserted. + @param[in] use_colors whether to use ANSI terminal codes +*/ static void process_params(struct proc_ldc_entry *pe, const struct ldc_entry *e, - const struct snd_sof_uids_header *uids_dict, int use_colors) { - const char *p = e->text; + char *p = e->text; const char *t_end = p + strlen(e->text); - unsigned int par_bit = 1; - int i; + int uuid_fmt_len; + int i = 0; pe->subst_mask = 0; pe->header = e->header; pe->file_name = e->file_name; pe->text = e->text; - /* scan the text for possible replacements */ + /* + * Scan the text for possible replacements. We follow the Linux kernel + * that uses %pUx formats for UUID / GUID printing, where 'x' is + * optional and can be one of 'b', 'B', 'l' (default), and 'L'. + * For decoding log entry text from pointer %pQ is used. + */ while ((p = strchr(p, '%'))) { - if (p < t_end - 1 && *(p + 1) == 's') - pe->subst_mask += par_bit; - par_bit <<= 1; - ++p; - } + uint32_t raw_param; - for (i = 0; i < e->header.params_num; i++) { - pe->params[i] = e->params[i]; - if (pe->subst_mask & (1 << i)) - pe->params[i] = (uintptr_t)format_uid(uids_dict, - e->params[i], - use_colors); + if (i >= e->header.params_num) { + /* Don't read e->params[] out of bounds. */ + log_err("Too many %% conversion specifiers in '%s'\n", + e->text); + break; + } + raw_param = e->params[i]; + + /* % can't be the last char */ + if (p + 1 >= t_end) { + log_err("Invalid format string\n"); + break; + } + + /* scan format string */ + if (p[1] == '%') { + /* Skip "%%" */ + p += 2; + } else if (p[1] == 's') { + /* %s format specifier */ + /* check for string printing, because it leads to logger crash */ + log_err("String printing is not supported\n"); + pe->params[i] = (uintptr_t)log_asprintf("<String @ 0x%08x>", raw_param); + if (!pe->params[i]) + abort(); + pe->subst_mask |= 1 << i; + ++i; + p += 2; + } else if (p + 2 < t_end && p[1] == 'p' && p[2] == 'U') { + /* %pUx format specifier */ + /* substitute UUID entry address with formatted string pointer from heap */ + pe->params[i] = (uintptr_t)asprintf_uuid(p, raw_param, use_colors, + &uuid_fmt_len); + if (!pe->params[i]) + abort(); + pe->subst_mask |= 1 << i; + ++i; + /* replace uuid formatter with %s */ + p[1] = 's'; + memmove(&p[2], &p[uuid_fmt_len], (int)(t_end - &p[uuid_fmt_len]) + 1); + p += uuid_fmt_len - 2; + t_end -= uuid_fmt_len - 2; + } else if (p + 2 < t_end && p[1] == 'p' && p[2] == 'Q') { + /* %pQ format specifier */ + /* substitute log entry address with formatted entry text */ + pe->params[i] = (uintptr_t)asprintf_entry_text(raw_param); + + if (pe->params[i]) + pe->subst_mask |= 1 << i; + else + pe->params[i] = (uintptr_t)missing; + + ++i; + + /* replace entry formatter with %s */ + p[1] = 's'; + memmove(&p[2], &p[3], t_end - &p[2]); + p++; + t_end--; + } else { + /* arguments different from %pU and %pQ should be passed without + * modification + */ + pe->params[i] = raw_param; + ++i; + p += 2; + } } + if (i < e->header.params_num) + log_err("Too few %% conversion specifiers in '%s'\n", e->text); } static void free_proc_ldc_entry(struct proc_ldc_entry *pe) @@ -153,25 +310,74 @@ static void free_proc_ldc_entry(struct proc_ldc_entry *pe) } } -static double to_usecs(uint64_t time, double clk) +static double to_usecs(uint64_t time) { /* trace timestamp uses CPU system clock at default 25MHz ticks */ // TODO: support variable clock rates - return (double)time / clk; + return (double)time / global_config->clock; } +/** Justified timestamp width for printf format string */ +static uint8_t timestamp_width(uint8_t precision) +{ + /* 64bits yields less than 20 digits precision. As reported by + * gcc 9.3, this avoids a very long precision causing snprintf() + * to truncate time_fmt + */ + assert(precision < 20); + /* + * 12 digits for units is enough for 1M seconds = 11 days which + * should be enough for most test runs. + * + * Add 1 for the comma when there is one. + */ + return 12 + (precision > 0 ? 1 : 0) + precision; +} -static inline void print_table_header(FILE *out_fd) +static inline void print_table_header(void) { - fprintf(out_fd, "%18s %18s %2s %-18s %-29s %s\n", - "TIMESTAMP", "DELTA", "C#", "COMPONENT", "LOCATION", - "CONTENT"); + FILE *out_fd = global_config->out_fd; + int hide_location = global_config->hide_location; + + char date_string[64]; + const time_t epoc_secs = time(NULL); + /* See SOF_IPC_TRACE_DMA_PARAMS_EXT in the kernel sources */ + struct timespec ktime; + const int gettime_ret = clock_gettime(CLOCK_MONOTONIC, &ktime); + + if (gettime_ret) { + log_err("clock_gettime() failed: %s\n", + strerror(errno)); + exit(1); + } + + if (global_config->time_precision >= 0) { + const uint8_t ts_width = timestamp_width(global_config->time_precision); + + fprintf(out_fd, "%*s(us)%*s ", -ts_width, " TIMESTAMP", ts_width, "DELTA"); + } + + fprintf(out_fd, "%2s %-18s ", "C#", "COMPONENT"); + if (!hide_location) + fprintf(out_fd, "%-29s ", "LOCATION"); + fprintf(out_fd, "%s", "CONTENT"); + + if (global_config->time_precision >= 0) { + struct tm *ltime = localtime(&epoc_secs); + + /* e.g.: ktime=4263.487s @ 2021-04-27 14:21:13 -0700 PDT */ + fprintf(out_fd, "\tktime=%lu.%03lus", + ktime.tv_sec, ktime.tv_nsec / 1000000); + + if (ltime && strftime(date_string, sizeof(date_string), + "%F %X %z %Z", ltime)) + fprintf(out_fd, " @ %s", date_string); + } + + fprintf(out_fd, "\n"); fflush(out_fd); } -#define CASE(x) \ - case(TRACE_CLASS_##x): return #x - static const char *get_level_color(uint32_t level) { switch (level) { @@ -191,99 +397,113 @@ static const char *get_level_name(uint32_t level) return "ERROR "; case LOG_LEVEL_WARNING: return "WARN "; + case LOG_LEVEL_INFO: + return "INFO "; + case LOG_LEVEL_DEBUG: + return "DEBUG "; default: - return ""; /* info is usual, do not print anything */ + return "UNKNOWN "; } } -static -const char *get_component_name(const struct snd_sof_uids_header *uids_dict, - uint32_t trace_class, uint32_t uid_ptr) +static const char *get_component_name(uint32_t trace_class, uint32_t uid_ptr) { + const struct snd_sof_uids_header *uids_dict = global_config->uids_dict; + const struct sof_uuid_entry *uid_entry; + /* if uid_ptr is non-zero, find name in the ldc file */ if (uid_ptr) { if (uid_ptr < uids_dict->base_address || uid_ptr >= uids_dict->base_address + uids_dict->data_length) return "<uid?>"; - const struct sof_uuid *uid_val = (const struct sof_uuid *) - ((uint8_t *)uids_dict + uids_dict->data_offset + - uid_ptr - uids_dict->base_address); - - return (const char *)(uid_val + 1) + sizeof(uint32_t); - } - - /* otherwise print legacy trace class name */ - switch (trace_class) { - CASE(IRQ); - CASE(IPC); - CASE(PIPE); - CASE(DAI); - CASE(DMA); - CASE(COMP); - CASE(WAIT); - CASE(LOCK); - CASE(MEM); - CASE(BUFFER); - CASE(SA); - CASE(POWER); - CASE(IDC); - CASE(CPU); - CASE(CLK); - CASE(EDF); - CASE(SCHEDULE); - CASE(SCHEDULE_LL); - CASE(CHMAP); - CASE(NOTIFIER); - CASE(MN); - CASE(PROBE); - default: return "unknown"; + uid_entry = get_uuid_entry(uid_ptr); + return uid_entry->name; } + + /* do not resolve legacy (deprecated) trace class name */ + return "unknown"; } /* remove superfluous leading file path and shrink to last 20 chars */ static char *format_file_name(char *file_name_raw, int full_name) { - char *name; - int len; + char *name; + int len; - /* most/all string should have "src" */ - name = strstr(file_name_raw, "src"); - if (!name) - name = file_name_raw; + /* most/all string should have "src" */ + name = strstr(file_name_raw, "src"); + if (!name) + name = file_name_raw; - if (full_name) - return name; - /* keep the last 24 chars */ - len = strlen(name); - if (len > 24) { - char *sep_pos = NULL; - - name += (len - 24); - sep_pos = strchr(name, '/'); - if (!sep_pos) - return name; - while (--sep_pos >= name) - *sep_pos = '.'; - } + if (full_name) return name; + /* keep the last 24 chars */ + len = strlen(name); + if (len > 24) { + char *sep_pos = NULL; + + name += (len - 24); + sep_pos = strchr(name, '/'); + if (!sep_pos) + return name; + while (--sep_pos >= name) + *sep_pos = '.'; + } + return name; } -static void print_entry_params(FILE *out_fd, - const struct snd_sof_uids_header *uids_dict, - const struct log_entry_header *dma_log, const struct ldc_entry *entry, - uint64_t last_timestamp, double clock, int use_colors, int raw_output) +static int entry_number = 1; +/** Formats and outputs one entry from the trace + the corresponding + * ldc_entry from the dictionary passed as arguments. Expects the log + * variables to have already been copied into the ldc_entry. + */ +static void print_entry_params(const struct log_entry_header *dma_log, + const struct ldc_entry *entry, uint64_t last_timestamp) { + static uint64_t timestamp_origin; + + FILE *out_fd = global_config->out_fd; + int use_colors = global_config->use_colors; + int raw_output = global_config->raw_output; + int hide_location = global_config->hide_location; + int time_precision = global_config->time_precision; + char ids[TRACE_MAX_IDS_STR]; - float dt = to_usecs(dma_log->timestamp - last_timestamp, clock); + float dt = to_usecs(dma_log->timestamp - last_timestamp); struct proc_ldc_entry proc_entry; + int ret; if (raw_output) use_colors = 0; - if (dt < 0 || dt > 1000.0 * 1000.0 * 1000.0) + /* Something somewhere went wrong */ + if (dt > 1000.0 * 1000.0 * 1000.0) dt = NAN; + if (dma_log->timestamp < last_timestamp) { + fprintf(out_fd, + "\n\t\t --- negative DELTA = %.3f us: wrap, IPC_TRACE, other? ---\n\n", + -to_usecs(last_timestamp - dma_log->timestamp)); + entry_number = 1; + } + + /* The first entry: + * - is never shown with a relative TIMESTAMP (to itself!?) + * - shows a zero DELTA + */ + if (entry_number == 1) { + entry_number++; + /* Display absolute (and random) timestamps */ + timestamp_origin = 0; + dt = 0; + } else if (entry_number == 2) { + entry_number++; + if (global_config->relative_timestamps == 1) + /* Switch to relative timestamps from now on. */ + timestamp_origin = last_timestamp; + } /* We don't need the exact entry_number after 3 */ + if (dma_log->id_0 != INVALID_TRACE_ID && dma_log->id_1 != INVALID_TRACE_ID) sprintf(ids, "%d.%d", (dma_log->id_0 & TRACE_IDS_MASK), @@ -291,29 +511,36 @@ static void print_entry_params(FILE *out_fd, else ids[0] = '\0'; - if (raw_output) { - const char *entry_fmt = "%s%u %u %s%s%s %.6f %.6f (%s:%u) "; - - fprintf(out_fd, entry_fmt, + if (raw_output) { /* "raw" means script-friendly (not all hex) */ + fprintf(out_fd, "%s%u %u %s%s%s ", entry->header.level == use_colors ? (LOG_LEVEL_CRITICAL ? KRED : KNRM) : "", dma_log->core_id, entry->header.level, - get_component_name(uids_dict, - entry->header.component_class, - dma_log->uid), + get_component_name(entry->header.component_class, dma_log->uid), raw_output && strlen(ids) ? "-" : "", - ids, - to_usecs(dma_log->timestamp, clock), - dt, - format_file_name(entry->file_name, raw_output), - entry->header.line_idx); + ids); + + if (time_precision >= 0) + fprintf(out_fd, "%.*f %.*f ", + time_precision, to_usecs(dma_log->timestamp - timestamp_origin), + time_precision, dt); + + if (!hide_location) + fprintf(out_fd, "(%s:%u) ", + format_file_name(entry->file_name, raw_output), + entry->header.line_idx); } else { - /* timestamp */ - fprintf(out_fd, "%s[%16.6f] (%16.6f)%s ", - use_colors ? KGRN : "", - to_usecs(dma_log->timestamp, clock), dt, - use_colors ? KNRM : ""); + if (time_precision >= 0) { + const uint8_t ts_width = timestamp_width(time_precision); + + fprintf(out_fd, "%s[%*.*f] (%*.*f)%s ", + use_colors ? KGRN : "", + ts_width, time_precision, + to_usecs(dma_log->timestamp - timestamp_origin), + ts_width, time_precision, dt, + use_colors ? KNRM : ""); + } /* core id */ fprintf(out_fd, "c%d ", dma_log->core_id); @@ -321,16 +548,15 @@ static void print_entry_params(FILE *out_fd, /* component name and id */ fprintf(out_fd, "%s%-12s %-5s%s ", use_colors ? KYEL : "", - get_component_name(uids_dict, - entry->header.component_class, - dma_log->uid), + get_component_name(entry->header.component_class, dma_log->uid), ids, use_colors ? KNRM : ""); /* location */ - fprintf(out_fd, "%24s:%-4u ", - format_file_name(entry->file_name, raw_output), - entry->header.line_idx); + if (!hide_location) + fprintf(out_fd, "%24s:%-4u ", + format_file_name(entry->file_name, raw_output), + entry->header.line_idx); /* level name */ fprintf(out_fd, "%s%s", @@ -338,155 +564,210 @@ static void print_entry_params(FILE *out_fd, get_level_name(entry->header.level)); } - process_params(&proc_entry, entry, uids_dict, use_colors); + /* Minimal, printf-like formatting */ + process_params(&proc_entry, entry, use_colors); switch (proc_entry.header.params_num) { case 0: - fprintf(out_fd, "%s", proc_entry.text); + ret = fprintf(out_fd, "%s", proc_entry.text); break; case 1: - fprintf(out_fd, proc_entry.text, proc_entry.params[0]); + ret = fprintf(out_fd, proc_entry.text, proc_entry.params[0]); break; case 2: - fprintf(out_fd, proc_entry.text, proc_entry.params[0], - proc_entry.params[1]); + ret = fprintf(out_fd, proc_entry.text, proc_entry.params[0], proc_entry.params[1]); break; case 3: - fprintf(out_fd, proc_entry.text, proc_entry.params[0], - proc_entry.params[1], proc_entry.params[2]); + ret = fprintf(out_fd, proc_entry.text, proc_entry.params[0], proc_entry.params[1], + proc_entry.params[2]); break; case 4: - fprintf(out_fd, proc_entry.text, proc_entry.params[0], - proc_entry.params[1], proc_entry.params[2], - proc_entry.params[3]); + ret = fprintf(out_fd, proc_entry.text, proc_entry.params[0], proc_entry.params[1], + proc_entry.params[2], proc_entry.params[3]); + break; + default: + log_err("Unsupported number of arguments for '%s'", proc_entry.text); + ret = 0; /* don't log ferror */ break; } free_proc_ldc_entry(&proc_entry); + /* log format text comes from ldc file (may be invalid), so error check is needed here */ + if (ret < 0) + log_err("trace fprintf failed for '%s', %d '%s'", + proc_entry.text, ferror(out_fd), strerror(ferror(out_fd))); fprintf(out_fd, "%s\n", use_colors ? KNRM : ""); fflush(out_fd); } -static int fetch_entry(const struct convert_config *config, - uint32_t base_address, uint32_t data_offset, - const struct log_entry_header *dma_log, uint64_t *last_timestamp) +static int read_entry_from_ldc_file(struct ldc_entry *entry, uint32_t log_entry_address) { - struct ldc_entry entry; - uint32_t entry_offset; + uint32_t base_address = global_config->logs_header->base_address; + uint32_t data_offset = global_config->logs_header->data_offset; int ret; - entry.file_name = NULL; - entry.text = NULL; - entry.params = NULL; - /* evaluate entry offset in input file */ - entry_offset = dma_log->log_entry_address - base_address; + uint32_t entry_offset = (log_entry_address - base_address) + data_offset; + + entry->file_name = NULL; + entry->text = NULL; + entry->params = NULL; /* set file position to beginning of processed entry */ - fseek(config->ldc_fd, entry_offset + data_offset, SEEK_SET); + ret = fseek(global_config->ldc_fd, entry_offset, SEEK_SET); + if (ret) { + log_err("Failed to seek to entry header for offset 0x%x in dictionary.\n", + entry_offset); + ret = -errno; + goto out; + } /* fetching elf header params */ - ret = fread(&entry.header, sizeof(entry.header), 1, config->ldc_fd); - if (!ret) { - ret = -ferror(config->ldc_fd); + ret = fread(&entry->header, sizeof(entry->header), 1, global_config->ldc_fd); + if (ret != 1) { + log_err("Failed to read entry header for offset 0x%x in dictionary.\n", + entry_offset); + ret = -1; goto out; } - if (entry.header.file_name_len > TRACE_MAX_FILENAME_LEN) { - log_err(config->out_fd, - "Error: Invalid filename length or ldc file does not match firmware\n"); + if (entry->header.file_name_len > TRACE_MAX_FILENAME_LEN) { + log_err("Invalid filename length %d or ldc file does not match firmware\n", + entry->header.file_name_len); ret = -EINVAL; goto out; } - entry.file_name = (char *)malloc(entry.header.file_name_len); + entry->file_name = (char *)malloc(entry->header.file_name_len + 1); - if (!entry.file_name) { - log_err(config->out_fd, - "error: can't allocate %d byte for entry.file_name\n", - entry.header.file_name_len); + if (!entry->file_name) { + log_err("can't allocate %d byte for entry.file_name\n", + entry->header.file_name_len); ret = -ENOMEM; goto out; } - ret = fread(entry.file_name, sizeof(char), entry.header.file_name_len, - config->ldc_fd); - if (ret != entry.header.file_name_len) { - ret = -ferror(config->ldc_fd); + ret = fread(entry->file_name, sizeof(char), entry->header.file_name_len, + global_config->ldc_fd); + entry->file_name[entry->header.file_name_len] = '\0'; + + if (ret != entry->header.file_name_len) { + log_err("Failed to read source filename for offset 0x%x in dictionary.\n", + entry_offset); + ret = -1; goto out; } /* fetching text */ - if (entry.header.text_len > TRACE_MAX_TEXT_LEN) { - log_err(config->out_fd, - "Error: Invalid text length.\n"); + if (entry->header.text_len > TRACE_MAX_TEXT_LEN) { + log_err("Invalid text length.\n"); ret = -EINVAL; goto out; } - entry.text = (char *)malloc(entry.header.text_len); - if (entry.text == NULL) { - log_err(config->out_fd, - "error: can't allocate %d byte for entry.text\n", - entry.header.text_len); + entry->text = (char *)malloc(entry->header.text_len + 1); + if (!entry->text) { + log_err("can't allocate %d byte for entry.text\n", entry->header.text_len); ret = -ENOMEM; goto out; } - ret = fread(entry.text, sizeof(char), entry.header.text_len, config->ldc_fd); - if (ret != entry.header.text_len) { - ret = -ferror(config->ldc_fd); + ret = fread(entry->text, sizeof(char), entry->header.text_len, global_config->ldc_fd); + if (ret != entry->header.text_len) { + log_err("Failed to read log message at offset 0x%x from dictionary.\n", + entry_offset); + ret = -1; + goto out; + } + entry->text[entry->header.text_len] = '\0'; + + return 0; + +out: + free(entry->text); + entry->text = NULL; + free(entry->file_name); + entry->file_name = NULL; + + return ret; +} + +/** Gets the dictionary entry matching the log entry argument, reads + * from the log the variable number of arguments needed by this entry + * and passes everything to print_entry_params() to finish processing + * this log entry. So not just "fetch" but everything else after it too. + * + * @param[in] dma_log protocol header from any trace (not just from the + * "DMA" trace) + * @param[in,out] last_timestamp timestamp found for this entry + */ +static int fetch_entry(const struct log_entry_header *dma_log, uint64_t *last_timestamp) +{ + struct ldc_entry entry; + int ret; + + ret = read_entry_from_ldc_file(&entry, dma_log->log_entry_address); + if (ret < 0) { + log_err("read_entry_from_ldc_file(0x%x) returned %d\n", + dma_log->log_entry_address, ret); goto out; } /* fetching entry params from dma dump */ if (entry.header.params_num > TRACE_MAX_PARAMS_COUNT) { - log_err(config->out_fd, - "Error: Invalid number of parameters.\n"); + log_err("Invalid number of parameters.\n"); ret = -EINVAL; goto out; } - entry.params = (uint32_t *)malloc(sizeof(uint32_t) * - entry.header.params_num); - if (entry.params == NULL) { - log_err(config->out_fd, - "error: can't allocate %d byte for entry.params\n", + entry.params = (uint32_t *)malloc(sizeof(uint32_t) * entry.header.params_num); + if (!entry.params) { + log_err("can't allocate %d byte for entry.params\n", (int)(sizeof(uint32_t) * entry.header.params_num)); ret = -ENOMEM; goto out; } - if (config->serial_fd < 0) { - ret = fread(entry.params, sizeof(uint32_t), - entry.header.params_num, config->in_fd); + if (global_config->serial_fd < 0) { + ret = fread(entry.params, sizeof(uint32_t), entry.header.params_num, + global_config->in_fd); if (ret != entry.header.params_num) { - ret = -ferror(config->in_fd); + fprintf(global_config->out_fd, + "warn: failed to fread() %d params from the log for %s:%d\n", + entry.header.params_num, + entry.file_name, entry.header.line_idx); + + ret = ferror(global_config->in_fd) ? -1 : 0; + + if (feof(global_config->in_fd)) + fprintf(global_config->out_fd, + "warn: log's End Of File. Device suspend?\n"); + goto out; } - } else { + } else { /* serial */ size_t size = sizeof(uint32_t) * entry.header.params_num; uint8_t *n; - for (n = (uint8_t *)entry.params; size; - n += ret, size -= ret) { - ret = read(config->serial_fd, n, size); + /* Repeatedly read() how much we still miss until we got + * enough for the number of params needed by this + * particular statement. + */ + for (n = (uint8_t *)entry.params; size; n += ret, size -= ret) { + ret = read(global_config->serial_fd, n, size); if (ret < 0) { ret = -errno; + log_err("Failed to fread %d params from serial: %s\n", + entry.header.params_num, strerror(errno)); goto out; } if (ret != size) - log_err(config->out_fd, - "Partial read of %u bytes of %lu.\n", + log_err("Partial read of %u bytes of %zu, reading more\n", ret, size); } - } + } /* serial */ /* printing entry content */ - print_entry_params(config->out_fd, - config->uids_dict, - dma_log, &entry, *last_timestamp, - config->clock, config->use_colors, - config->raw_output); + print_entry_params(dma_log, &entry, *last_timestamp); *last_timestamp = dma_log->timestamp; /* set f_ldc file position to the beginning */ - rewind(config->ldc_fd); + rewind(global_config->ldc_fd); ret = 0; out: @@ -498,18 +779,15 @@ static int fetch_entry(const struct convert_config *config, return ret; } -static int serial_read(const struct convert_config *config, - struct snd_sof_logs_header *snd, uint64_t *last_timestamp) +static int serial_read(uint64_t *last_timestamp) { struct log_entry_header dma_log; size_t len; uint8_t *n; int ret; - for (len = 0, n = (uint8_t *)&dma_log; len < sizeof(dma_log); - n += sizeof(uint32_t)) { - - ret = read(config->serial_fd, n, sizeof(*n) * sizeof(uint32_t)); + for (len = 0, n = (uint8_t *)&dma_log; len < sizeof(dma_log); n += sizeof(uint32_t)) { + ret = read(global_config->serial_fd, n, sizeof(*n) * sizeof(uint32_t)); if (ret < 0) return -errno; @@ -521,8 +799,9 @@ static int serial_read(const struct convert_config *config, } /* Skip all trace_point() values, although this test isn't 100% reliable */ - while ((dma_log.log_entry_address < snd->base_address) || - dma_log.log_entry_address > snd->base_address + snd->data_length) { + while ((dma_log.log_entry_address < global_config->logs_header->base_address) || + dma_log.log_entry_address > global_config->logs_header->base_address + + global_config->logs_header->data_length) { /* * 8 characters and a '\n' come from the serial port, append a * '\0' @@ -535,191 +814,342 @@ static int serial_read(const struct convert_config *config, memcpy(s, c, sizeof(s) - 1); s[sizeof(s) - 1] = '\0'; - fprintf(config->out_fd, "Trace point %s", s); + fprintf(global_config->out_fd, "Trace point %s", s); memmove(&dma_log, c + 9, sizeof(dma_log) - 9); c = (uint8_t *)(&dma_log + 1) - 9; for (len = 9; len; len -= ret, c += ret) { - ret = read(config->serial_fd, c, len); + ret = read(global_config->serial_fd, c, len); if (ret < 0) return ret; } } - /* fetching entry from elf dump */ - return fetch_entry(config, snd->base_address, snd->data_offset, - &dma_log, last_timestamp); + /* fetching entry from elf dump and complete processing this log + * line + */ + return fetch_entry(&dma_log, last_timestamp); } -static int logger_read(const struct convert_config *config, - struct snd_sof_logs_header *snd) +/** Main logger loop */ +static int logger_read(void) { struct log_entry_header dma_log; int ret = 0; uint64_t last_timestamp = 0; - if (!config->raw_output) - print_table_header(config->out_fd); + bool ldc_address_OK = false; + unsigned int skipped_dwords = 0; + + if (!global_config->raw_output) + print_table_header(); - if (config->serial_fd >= 0) + if (global_config->serial_fd >= 0) /* Wait for CTRL-C */ for (;;) { - ret = serial_read(config, snd, &last_timestamp); + ret = serial_read(&last_timestamp); if (ret < 0) return ret; } - while (!ferror(config->in_fd)) { + /* One iteration per log statement */ + while (!ferror(global_config->in_fd)) { /* getting entry parameters from dma dump */ - ret = fread(&dma_log, sizeof(dma_log), 1, config->in_fd); - if (!ret) { - if (config->trace && !ferror(config->in_fd)) { - freopen(NULL, "r", config->in_fd); - continue; + ret = fread(&dma_log, sizeof(dma_log), 1, global_config->in_fd); + if (ret != 1) { + /* + * use ferror (not errno) to check fread fail - + * see https://www.gnu.org/software/gnulib/manual/html_node/fread.html + */ + ret = -ferror(global_config->in_fd); + if (ret) { + log_err("in %s(), fread(..., %s) failed: %s(%d)\n", + __func__, global_config->in_file, + strerror(-ret), ret); + break; + } + /* for trace mode, try to reopen */ + if (global_config->trace) { + fprintf(global_config->out_fd, + "\n ---- %s; %s -----\n\n", + "Re-opening trace input file", + "device suspend?"); + if (freopen(NULL, "rb", global_config->in_fd)) { + entry_number = 1; + continue; + } else { + log_err("in %s(), freopen(..., %s) failed: %s(%d)\n", + __func__, global_config->in_file, + strerror(errno), errno); + ret = -errno; + break; + } + } else { + /* EOF */ + if (!feof(global_config->in_fd)) + log_err("file '%s' is unaligned with trace entry size (%zu)\n", + global_config->in_file, sizeof(dma_log)); + break; } - - return -ferror(config->in_fd); } /* checking if received trace address is located in * entry section in elf file. */ - if ((dma_log.log_entry_address < snd->base_address) || - dma_log.log_entry_address > snd->base_address + snd->data_length) { - /* in case the address is not correct input fd should be - * move forward by one DWORD, not entire struct dma_log + if (dma_log.log_entry_address < global_config->logs_header->base_address || + dma_log.log_entry_address > global_config->logs_header->base_address + + global_config->logs_header->data_length) { + /* Finding uninitialized and incomplete log statements in the + * mailbox ring buffer is routine. Take note in both cases but + * report errors only for the DMA trace. + */ + if (global_config->trace && ldc_address_OK) { + log_err("log_entry_address %#10x is not in dictionary range!\n", + dma_log.log_entry_address); + fprintf(global_config->out_fd, + "warn: Seeking forward 4 bytes at a time until re-synchronize.\n"); + } + ldc_address_OK = false; + /* When the address is not correct, move forward by one DWORD (not + * entire struct dma_log) */ - fseek(config->in_fd, -(sizeof(dma_log) - sizeof(uint32_t)), SEEK_CUR); + ret = fseek(global_config->in_fd, -(sizeof(dma_log) - sizeof(uint32_t)), + SEEK_CUR); + if (ret) { + log_err("fetch_entry() failed on seek, aborting\n"); + ret = -errno; + break; + } + skipped_dwords++; continue; + + } else if (!ldc_address_OK) { + /* Just found a valid address (again) */ + + /* At this point, skipped_dwords can be == 0 + * only when we just started to run. + */ + if (skipped_dwords != 0) { + fprintf(global_config->out_fd, + "\nFound valid LDC address after skipping %zu bytes (one line uses %zu + 0 to 16 bytes)\n", + sizeof(uint32_t) * skipped_dwords, sizeof(dma_log)); + } + + ldc_address_OK = true; + skipped_dwords = 0; } - /* fetching entry from elf dump */ - ret = fetch_entry(config, snd->base_address, snd->data_offset, - &dma_log, &last_timestamp); - if (ret) + /* fetching entry from dictionary, read the number of + * arguments needed and finish the entire processing of + * this log line. + */ + ret = fetch_entry(&dma_log, &last_timestamp); + if (ret) { + log_err("fetch_entry() failed with: %d, aborting\n", ret); break; - } + } + } /* next log entry */ + + /* End of (etrace) file */ + fprintf(global_config->out_fd, + "Skipped %zu bytes after the last statement", + sizeof(uint32_t) * skipped_dwords); + + if (!global_config->trace && + /* maximum 4 arguments supported */ + skipped_dwords < sizeof(dma_log) + 4 * sizeof(uint32_t)) + fprintf(global_config->out_fd, + ". Potential mailbox wrap, check the start of the output for later logs"); + + fprintf(global_config->out_fd, ".\n"); return ret; } -/* fw verification */ -static int verify_fw_ver(const struct convert_config *config, - const struct snd_sof_logs_header *snd) +/** Compare the dictionary checksum in the firmware image (through + * /sys/kernel/debug/sof/fw_version) with the checksum in the .ldc file. + * @return 0 when the checksums match + */ +static int verify_ldc_checksum(const uint32_t ldc_sum) { struct sof_ipc_fw_version ver; - int count, ret = 0; - - if (!config->version_fd) - return 0; + int count; /* here fw verification should be exploited */ - count = fread(&ver, sizeof(ver), 1, config->version_fd); + count = fread(&ver, sizeof(ver), 1, global_config->version_fd); if (!count) { - log_err(config->out_fd, "Error while reading %s.\n", - config->version_file); - return -ferror(config->version_fd); + log_err("Error while reading %s.\n", global_config->version_file); + return -ferror(global_config->version_fd); } - ret = memcmp(&ver, &snd->version, sizeof(struct sof_ipc_fw_version)); - if (ret) { - log_err(config->out_fd, - "Error: fw version in %s file does not coincide with fw version in %s file.\n", - config->ldc_file, config->version_file); + /* compare source hash value from version file and ldc file */ + if (ver.src_hash != ldc_sum) { + log_err("src hash value from version file (0x%x) differ from src hash version saved in dictionary (0x%x).\n", + ver.src_hash, ldc_sum); return -EINVAL; } + return 0; +} - /* logger and version_file abi dbg verification */ - if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_DBG_VERSION, - ver.abi_version)) { - log_err(config->out_fd, - "Error: abi version in %s file does not coincide with abi version used by logger.\n", - config->version_file); - log_err(config->out_fd, - "logger ABI Version is %d:%d:%d\n", - SOF_ABI_VERSION_MAJOR(SOF_ABI_DBG_VERSION), - SOF_ABI_VERSION_MINOR(SOF_ABI_DBG_VERSION), - SOF_ABI_VERSION_PATCH(SOF_ABI_DBG_VERSION)); - log_err(config->out_fd, - "version_file ABI Version is %d:%d:%d\n", - SOF_ABI_VERSION_MAJOR(ver.abi_version), - SOF_ABI_VERSION_MINOR(ver.abi_version), - SOF_ABI_VERSION_PATCH(ver.abi_version)); - return -EINVAL; +static int dump_ldc_info(void) +{ + struct snd_sof_uids_header *uids_dict = global_config->uids_dict; + ssize_t remaining = uids_dict->data_length; + const struct sof_uuid_entry *uid_ptr; + FILE *out_fd = global_config->out_fd; + uintptr_t uid_addr; + int cnt = 0; + char *name; + + fprintf(out_fd, "logger ABI Version is\t%d:%d:%d\n", + SOF_ABI_VERSION_MAJOR(SOF_ABI_DBG_VERSION), + SOF_ABI_VERSION_MINOR(SOF_ABI_DBG_VERSION), + SOF_ABI_VERSION_PATCH(SOF_ABI_DBG_VERSION)); + + fprintf(out_fd, "ldc_file ABI Version is\t%d:%d:%d\n", + SOF_ABI_VERSION_MAJOR(global_config->logs_header->version.abi_version), + SOF_ABI_VERSION_MINOR(global_config->logs_header->version.abi_version), + SOF_ABI_VERSION_PATCH(global_config->logs_header->version.abi_version)); + fprintf(out_fd, "ldc_file src checksum\t\t0x%08x\n", + global_config->logs_header->version.src_hash); + + if (global_config->version_fd) { + struct sof_ipc_fw_version ver; + + if (fread(&ver, sizeof(ver), 1, global_config->version_fd) == 1) + fprintf(out_fd, "Loaded FW expects checksum\t0x%08x\n", + ver.src_hash); + } + + fprintf(out_fd, "\n"); + fprintf(out_fd, "Components uuid dictionary size:\t%zd bytes\n", + remaining); + fprintf(out_fd, "Components uuid base address: \t0x%x\n", + uids_dict->base_address); + fprintf(out_fd, "Components uuid entries:\n"); + fprintf(out_fd, "\t%10s %38s %s\n", "ADDRESS", "UUID", "NAME"); + + uid_ptr = (const struct sof_uuid_entry *) + ((uintptr_t)uids_dict + uids_dict->data_offset); + + while (remaining > 0) { + name = format_uid_raw(&uid_ptr[cnt], 0, 0, false, false); + uid_addr = get_uuid_key(&uid_ptr[cnt]); + fprintf(out_fd, "\t%p %s\n", (void *)uid_addr, name ? name : missing); + + if (name) { + free(name); + name = NULL; + } + remaining -= sizeof(struct sof_uuid_entry); + ++cnt; } + + fprintf(out_fd, "\t-------------------------------------------------- cnt: %d\n", + cnt); + return 0; } -int convert(struct convert_config *config) +int convert(void) { - struct snd_sof_logs_header snd; + struct snd_sof_logs_header * const logs_hdr = malloc(sizeof(*logs_hdr)); struct snd_sof_uids_header uids_hdr; int count, ret = 0; - count = fread(&snd, sizeof(snd), 1, config->ldc_fd); + /* const pointer initialized at build time */ + if (!global_config) + abort(); + + if (!logs_hdr) + abort(); + + /* just a shorter alias */ + struct convert_config * const config = global_config; + + config->logs_header = logs_hdr; + + count = fread(logs_hdr, sizeof(*logs_hdr), 1, config->ldc_fd); if (!count) { - log_err(config->out_fd, "Error while reading %s.\n", - config->ldc_file); + log_err("Error while reading %s.\n", config->ldc_file); return -ferror(config->ldc_fd); } - if (strncmp((char *) snd.sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE)) { - log_err(config->out_fd, - "Error: Invalid ldc file signature.\n"); + if (strncmp((char *)logs_hdr->sig, SND_SOF_LOGS_SIG, SND_SOF_LOGS_SIG_SIZE)) { + log_err("Invalid ldc file signature.\n"); return -EINVAL; } - ret = verify_fw_ver(config, &snd); - if (ret) - return ret; + if (global_config->version_fw && /* -n option */ + !global_config->dump_ldc) { + ret = verify_ldc_checksum(logs_hdr->version.src_hash); + if (ret) + return ret; + } /* default logger and ldc_file abi verification */ if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_DBG_VERSION, - snd.version.abi_version)) { - log_err(config->out_fd, - "Error: abi version in %s file does not coincide with abi version used by logger.\n", + logs_hdr->version.abi_version)) { + log_err("abi version in %s file does not coincide with abi version used by logger.\n", config->ldc_file); - log_err(config->out_fd, "logger ABI Version is %d:%d:%d\n", + log_err("logger ABI Version is %d:%d:%d\n", SOF_ABI_VERSION_MAJOR(SOF_ABI_DBG_VERSION), SOF_ABI_VERSION_MINOR(SOF_ABI_DBG_VERSION), SOF_ABI_VERSION_PATCH(SOF_ABI_DBG_VERSION)); - log_err(config->out_fd, "ldc_file ABI Version is %d:%d:%d\n", - SOF_ABI_VERSION_MAJOR(snd.version.abi_version), - SOF_ABI_VERSION_MINOR(snd.version.abi_version), - SOF_ABI_VERSION_PATCH(snd.version.abi_version)); + log_err("ldc_file ABI Version is %d:%d:%d\n", + SOF_ABI_VERSION_MAJOR(logs_hdr->version.abi_version), + SOF_ABI_VERSION_MINOR(logs_hdr->version.abi_version), + SOF_ABI_VERSION_PATCH(logs_hdr->version.abi_version)); return -EINVAL; } /* read uuid section header */ - fseek(config->ldc_fd, snd.data_offset + snd.data_length, SEEK_SET); + ret = fseek(config->ldc_fd, logs_hdr->data_offset + logs_hdr->data_length, SEEK_SET); + if (ret) { + log_err("Error while seeking to uuids header from %s.\n", config->ldc_file); + return -errno; + } + count = fread(&uids_hdr, sizeof(uids_hdr), 1, config->ldc_fd); if (!count) { - log_err(config->out_fd, - "Error while reading uuids header from %s.\n", - config->ldc_file); + log_err("Error while reading uuids header from %s.\n", config->ldc_file); return -ferror(config->ldc_fd); } if (strncmp((char *)uids_hdr.sig, SND_SOF_UIDS_SIG, SND_SOF_UIDS_SIG_SIZE)) { - log_err(config->out_fd, - "Error: invalid uuid section signature.\n"); + log_err("invalid uuid section signature.\n"); return -EINVAL; } config->uids_dict = calloc(1, sizeof(uids_hdr) + uids_hdr.data_length); if (!config->uids_dict) { - log_err(config->out_fd, - "Error: failed to alloc memory for uuids.\n"); + log_err("failed to alloc memory for uuids.\n"); return -ENOMEM; } memcpy(config->uids_dict, &uids_hdr, sizeof(uids_hdr)); count = fread(config->uids_dict + 1, uids_hdr.data_length, 1, config->ldc_fd); if (!count) { - log_err(config->out_fd, - "Error: failed to read uuid section data.\n"); - return -ferror(config->ldc_fd); + log_err("failed to read uuid section data.\n"); + ret = -ferror(config->ldc_fd); + goto out; + } + + if (config->dump_ldc) { + ret = dump_ldc_info(); + goto out; + } + + if (config->filter_config) { + ret = filter_update_firmware(); + if (ret) { + log_err("failed to apply trace filter, %d.\n", ret); + goto out; + } } - return logger_read(config, &snd); + ret = logger_read(); +out: + free(config->uids_dict); + return ret; } diff --git a/tools/logger/convert.h b/tools/logger/convert.h index bd82d5add3e9..a870c990b9e4 100644 --- a/tools/logger/convert.h +++ b/tools/logger/convert.h @@ -12,7 +12,8 @@ #include <stdio.h> #include <ipc/info.h> -#include <rimage/file_format.h> +#include <smex/ldc.h> +#include <sof/lib/uuid.h> #define KNRM "\x1B[0m" #define KRED "\x1B[31m" @@ -29,6 +30,7 @@ struct convert_config { int trace; const char *ldc_file; FILE* ldc_fd; + char *filter_config; int input_std; int version_fw; char *version_file; @@ -36,7 +38,17 @@ struct convert_config { int use_colors; int serial_fd; int raw_output; + int dump_ldc; + int hide_location; + int relative_timestamps; + int8_t time_precision; struct snd_sof_uids_header *uids_dict; + struct snd_sof_logs_header *logs_header; }; -int convert(struct convert_config *config); +uint32_t get_uuid_key(const struct sof_uuid_entry *entry); + +/* pointer to config for global context */ +extern struct convert_config * const global_config; + +int convert(void); diff --git a/tools/logger/filter.c b/tools/logger/filter.c new file mode 100644 index 000000000000..0943f68d16b2 --- /dev/null +++ b/tools/logger/filter.c @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#include <ipc/trace.h> +#include <smex/ldc.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <user/trace.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "convert.h" +#include "filter.h" +#include "misc.h" + +#define COMPONENTS_SEPARATOR ',' +#define COMPONENT_NAME_SCAN_STRING_LENGTH 32 + +/** map between log level given by user and enum value */ +static const struct { + const char name[16]; + int32_t log_level; +} log_level_dict[] = { + {"verbose", LOG_LEVEL_VERBOSE}, + {"debug", LOG_LEVEL_DEBUG}, + {"info", LOG_LEVEL_INFO}, + {"warning", LOG_LEVEL_WARNING}, + {"error", LOG_LEVEL_ERROR}, + {"critical", LOG_LEVEL_CRITICAL}, + {"v", LOG_LEVEL_VERBOSE}, + {"d", LOG_LEVEL_DEBUG}, + {"i", LOG_LEVEL_INFO}, + {"w", LOG_LEVEL_WARNING}, + {"e", LOG_LEVEL_ERROR}, + {"c", LOG_LEVEL_CRITICAL}, +}; + +struct filter_element { + struct list_item list; + int32_t uuid_id; /**< type id, or -1 when not important */ + int32_t comp_id; /**< component id or -1 when not important */ + int32_t pipe_id; /**< pipeline id or -1 when not important */ + int32_t log_level; /**< new log level value */ +}; + +/** + * Search for uuid entry with given component name in given uids dictionary + * @param name of uuid entry + * @return pointer to sof_uuid_entry with given name + */ +static struct sof_uuid_entry *get_uuid_by_name(const char *name) +{ + const struct snd_sof_uids_header *uids_dict = global_config->uids_dict; + uintptr_t beg = (uintptr_t)uids_dict + uids_dict->data_offset; + uintptr_t end = beg + uids_dict->data_length; + struct sof_uuid_entry *ptr = (struct sof_uuid_entry *)beg; + + while ((uintptr_t)ptr < end) { + if (strcmp(name, ptr->name) == 0) + return ptr; + ++ptr; + } + return NULL; +} + +/** + * Parse log level name (from log_level_dict) to enum value. + * Take care about possible whitespace at the begin. + * @param value_start pointer to the begin of range to search + * @return enum value for given log level, or -1 for invalid value + */ +static int filter_parse_log_level(const char *value_start) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(log_level_dict); ++i) { + if (!strcmp(log_level_dict[i].name, value_start)) + return log_level_dict[i].log_level; + } + return -1; +} + +static char *filter_parse_component_name(char *input_str, struct filter_element *out) +{ + static char scan_format_string[COMPONENT_NAME_SCAN_STRING_LENGTH] = ""; + char comp_name[UUID_NAME_MAX_LEN]; + struct sof_uuid_entry *uuid_entry; + int ret; + + /* if component name is not specified, stay with default out->uuid_id value */ + if (input_str[0] == '*') + return &input_str[1]; + + /* + * Take care about buffer overflows when dealing with input from + * user, so scan no more than UUID_NAME_MAX_LEN bytes to + * `comp_name` variable. Only once initialise scan_format_string. + */ + if (strlen(scan_format_string) == 0) { + ret = snprintf(scan_format_string, sizeof(scan_format_string), + "%%%d[^0-9* ]s", UUID_NAME_MAX_LEN); + if (ret <= 0) + return NULL; + } + ret = sscanf(input_str, scan_format_string, comp_name); + if (ret <= 0) + return NULL; + + /* find component uuid key */ + uuid_entry = get_uuid_by_name(comp_name); + if (!uuid_entry) { + log_err("unknown component name `%s`\n", comp_name); + return NULL; + } + out->uuid_id = get_uuid_key(uuid_entry); + return strstr(input_str, comp_name) + strlen(comp_name); +} + +/** + * Parse component definition from input_str. + * + * Possible input_str formats: + * `name pipe_id.comp_id` + * `name pipe_id.*` + * `name *` + * `name` + * `* pipe_id.comp_id` + * `* pipe_id.*` + * `*` + * Whitespace is possible at the begin, end and after `name`. + * `name` must refer to values from given UUID dictionary, + * (so name comes from SOF_DEFINE_UUID macro usage) + + * @param input_str formatted component definition + * @param out element where component definition should be saved + */ +static int filter_parse_component(char *input_str, struct filter_element *out) +{ + char *instance_info; + int ret; + + /* trim whitespaces, to easily check first and last char */ + input_str = trim(input_str); + + /* assign default values */ + out->uuid_id = 0; + out->pipe_id = -1; + out->comp_id = -1; + + /* parse component name and store pointer after component name, pointer to instance info */ + instance_info = filter_parse_component_name(input_str, out); + if (!instance_info) { + log_err("component name parsing `%s`\n", input_str); + return -EINVAL; + } + + /* if instance is not specified then stop parsing */ + instance_info = ltrim(instance_info); + if (instance_info[0] == '\0' || + (instance_info[0] == '*' && instance_info[1] == '\0')) { + return 0; + } + + /* now parse last part: `number.x` where x is a number or `*` */ + ret = sscanf(instance_info, "%d.%d", &out->pipe_id, &out->comp_id); + if (ret == 2) + return 0; + else if (ret != 1) + return -EINVAL; + + /* pipeline id parsed but component id is not a number */ + if (instance_info[strlen(instance_info) - 1] == '*') + return 0; + log_err("Use * to specify each component on particular pipeline\n"); + return -EINVAL; +} + +/** + * Convert argument from -F flag to sof_ipc_dma_trace_filter_elem struct values. + * + * Possible log_level - see filter_parse_log_level() documentation + * Possible component - list of components separated by `COMPONENTS_SEPARATOR`, + * for single component definition description look at + * filter_parse_component() documentation + * + * Examples: + * `debug="pipe1"` - set debug log level for components from pipeline1 + * `d="pipe1, dai2.3"` - as above, but also for dai2.3 + * `error="FIR*"` - for each FIR component set log level to error + * + * @param input_str log level settings in format `log_level=component` + * @param out_list output list with filter_element elements + */ +static int filter_parse_entry(char *input_str, struct list_item *out_list) +{ + struct filter_element *filter; + char *comp_fmt_end; + int32_t log_level; + char *comp_fmt; + int ret; + + /* + * split string on '=' char, left part describes log level, + * the right one is for component description. + */ + comp_fmt = strchr(input_str, '='); + if (!comp_fmt) { + log_err("unable to find `=` in `%s`\n", input_str); + return -EINVAL; + } + *comp_fmt = 0; + ++comp_fmt; + + /* find correct log level in given conf string - string before `=` */ + log_level = filter_parse_log_level(input_str); + if (log_level < 0) { + log_err("unable to parse log level from `%s`\n", input_str); + return log_level; + } + + /* + * now parse list of components name and optional instance identifier, + * split string on `COMPONENTS_SEPARATOR` + */ + while (comp_fmt) { + filter = malloc(sizeof(struct filter_element)); + if (!filter) { + log_err("unable to malloc memory\n"); + return -ENOMEM; + } + + comp_fmt_end = strchr(comp_fmt, COMPONENTS_SEPARATOR); + if (comp_fmt_end) + *comp_fmt_end = '\0'; + ret = filter_parse_component(comp_fmt, filter); + if (ret < 0) { + log_err("unable to parse component from `%s`\n", comp_fmt); + free(filter); + return ret; + } + filter->log_level = log_level; + + list_item_append(&filter->list, out_list); + comp_fmt = comp_fmt_end ? comp_fmt_end + 1 : 0; + } + + return 0; +} + +/** + * Parse `input_str` content and send it to FW via debugFS. + * + * `input_str` contain single filter definition element per line. + * Each line is parsed by `filter_parse_entry`, and saved in list. + * List of `sof_ipc_dma_trace_filter_elem` is writend to debugFS, + * and then send as IPC to FW (this action is implemented in driver). + * Each line in debugFS represents single IPC message. + */ +int filter_update_firmware(void) +{ + char *input_str = global_config->filter_config; + struct filter_element *filter; + struct list_item filter_list; + struct list_item *list_elem; + struct list_item *list_temp; + char *line_end; + FILE *out_fd = NULL; + int ret = 0; + + list_init(&filter_list); + + /* parse `input_str` line by line */ + line_end = strchr(input_str, '\n'); + while (line_end) { + line_end[0] = '\0'; + ret = filter_parse_entry(input_str, &filter_list); + if (ret < 0) + goto err; + input_str = line_end + 1; + line_end = strchr(input_str, '\n'); + } + + /* write output to debugFS */ + out_fd = fopen(FILTER_KERNEL_PATH, "w"); + if (!out_fd) { + log_err("Unable to open out file '%s'\n", FILTER_KERNEL_PATH); + ret = -errno; + goto err; + } + + list_for_item(list_elem, &filter_list) { + filter = container_of(list_elem, struct filter_element, list); + fprintf(out_fd, "%d %X %d %d;", filter->log_level, + filter->uuid_id, filter->pipe_id, filter->comp_id); + } + fprintf(out_fd, "\n"); + +err: + if (out_fd) + fclose(out_fd); + + /* free each component from parsed element list */ + list_for_item_safe(list_elem, list_temp, &filter_list) { + filter = container_of(list_elem, struct filter_element, list); + free(filter); + } + + return ret; +} diff --git a/tools/logger/filter.h b/tools/logger/filter.h new file mode 100644 index 000000000000..11246128dd10 --- /dev/null +++ b/tools/logger/filter.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#ifndef __LOGGER_FILTER_H__ +#define __LOGGER_FILTER_H__ + +#define FILTER_KERNEL_PATH "/sys/kernel/debug/sof/filter" + +int filter_update_firmware(void); + +#endif /* __LOGGER_FILTER_H__ */ diff --git a/tools/logger/logger.c b/tools/logger/logger.c index deb56618bd15..b6c2b26bd629 100644 --- a/tools/logger/logger.c +++ b/tools/logger/logger.c @@ -5,16 +5,31 @@ // Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> // Artur Kloniecki <arturx.kloniecki@linux.intel.com> +#include <assert.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> +#include <limits.h> #include <errno.h> #include <string.h> #include <ctype.h> #include <fcntl.h> #include <stdbool.h> #include <termios.h> + +#include <sys/types.h> +#include <dirent.h> + +#include "config.h" + +#if HAS_INOTIFY +#include <poll.h> +#include <sys/inotify.h> +#include <sys/stat.h> +#endif + #include "convert.h" +#include "misc.h" #define APP_NAME "sof-logger" @@ -29,27 +44,48 @@ static const char *debugfs[] = { "hda", "pp", "dsp", }; +/** See PLATFORM_DEFAULT_CLOCK in the firmware code. */ +static const float DEFAULT_CLOCK_MHZ = 19.2; + static void usage(void) { fprintf(stdout, "Usage %s <option(s)> <file(s)>\n", APP_NAME); - fprintf(stdout, "%s:\t \t\t\tDisplay mailbox contents\n", APP_NAME); + fprintf(stdout, "%s:\t \t\t\tDisplay mailbox or DMA trace contents\n", APP_NAME); fprintf(stdout, "%s:\t -i infile -o outfile\tDump infile contents " "to outfile\n", APP_NAME); - fprintf(stdout, "%s:\t -l *.ldc_file\t\t*.ldc files generated " - "by rimage\n", APP_NAME); + fprintf(stdout, "%s:\t -l *.ldc_file\t\t.ldc input file generated by smex\n", + APP_NAME); fprintf(stdout, "%s:\t -p \t\t\tInput from stdin\n", APP_NAME); - fprintf(stdout, "%s:\t -e \t\t\tEnable checking firmware version with " - "default verification file\n", APP_NAME); - fprintf(stdout, "%s:\t -v ver_file\t\tEnable checking firmware version " - "with ver_file file\n", APP_NAME); - fprintf(stdout, "%s:\t -c\t\t\tSet timestamp clock in MHz\n", APP_NAME); + fprintf(stdout, "%s:\t -v ver_file\t\tUse ver_file instead of " + "/sys/kernel/debug/sof/fw_version\n", APP_NAME); + fprintf(stdout, "%s:\t -n\t\t\tDo not compare dictionary checksums\n", + APP_NAME); + fprintf(stdout, "%s:\t -c clock\t\tSet timestamp clock in MHz, %.2f MHz by default\n", + APP_NAME, DEFAULT_CLOCK_MHZ); fprintf(stdout, "%s:\t -s state_name\t\tTake a snapshot of state\n", APP_NAME); - fprintf(stdout, "%s:\t -t\t\t\tDisplay trace data\n", APP_NAME); + fprintf(stdout, "%s:\t -t\t\t\tDMA 'trace' stream instead of 'etrace' error mailbox\n", + APP_NAME); fprintf(stdout, "%s:\t -u baud\t\tInput data from a UART\n", APP_NAME); fprintf(stdout, "%s:\t -r\t\t\tLess formatted output for " "chained log processors\n", APP_NAME); + fprintf(stdout, "%s:\t -L\t\t\tHide log location in source code\n", + APP_NAME); + fprintf(stdout, + "%s:\t -e 0/1\t\t\tTimestamps relative to first entry seen. Defaults to\n", + APP_NAME); + fprintf(stdout, "%s:\t\t\t\tabsolute when -r(aw), relative otherwise.\n", + APP_NAME); + fprintf(stdout, "%s:\t -f precision\t\tSet timestamp precision\n", + APP_NAME); + fprintf(stdout, "%s:\t -g\t\t\tHide timestamp\n", + APP_NAME); + fprintf(stdout, "%s:\t -d *.ldc_file \t\tDump ldc_file information\n", + APP_NAME); + fprintf(stdout, "%s:\t -F filter\t\tUpdate trace filter, format: " + "<level>=<comp1>[, <comp2>]\n", + APP_NAME); exit(0); } @@ -61,29 +97,29 @@ static int snapshot(const char *name) FILE *in_fd, *out_fd; int i, count; - if (name == NULL) { + if (!name) { fprintf(stderr, "error: need snapshot name\n"); return -EINVAL; } for (i = 0; i < ARRAY_SIZE(debugfs); i++) { - sprintf(pinname, "%s/%s", path, debugfs[i]); - sprintf(poutname, "%s.%s.txt", name, debugfs[i]); + snprintf(pinname, sizeof(pinname), "%s/%s", path, debugfs[i]); + snprintf(poutname, sizeof(poutname), "%s.%s.txt", name, debugfs[i]); /* open debugfs for reading */ in_fd = fopen(pinname, "rb"); - if (in_fd == NULL) { - fprintf(stderr, "error: unable to open %s for reading %d\n", - pinname, errno); + if (!in_fd) { + fprintf(stderr, "error: unable to open %s for reading: %s\n", + pinname, strerror(errno)); continue; } /* open outfile for writing */ out_fd = fopen(poutname, "wb"); - if (out_fd == NULL) { - fprintf(stderr, "error: unable to open %s for writing %d\n", - poutname, errno); + if (!out_fd) { + fprintf(stderr, "error: unable to open %s for writing: %s\n", + poutname, strerror(errno)); fclose(in_fd); continue; } @@ -96,9 +132,14 @@ static int snapshot(const char *name) if (count != 4) break; - sprintf(buffer, "0x%6.6x: 0x%8.8x\n", addr, val); + snprintf(buffer, sizeof(buffer), "0x%6.6x: 0x%8.8x\n", addr, val); - count = fwrite(buffer, 1, strlen(buffer), out_fd); + i = strlen(buffer); + count = fwrite(buffer, 1, i, out_fd); + if (count != i) { + fprintf(stderr, "error: an error occurred during write to %s: %s\n", + poutname, strerror(errno)); + } addr += 4; } @@ -128,18 +169,142 @@ static int configure_uart(const char *file, unsigned int baud) tio.c_cc[VMIN] = 1; ret = tcsetattr(fd, TCSANOW, &tio); - return ret < 0 ? -errno : fd; + if (ret < 0) { + close(fd); + return -errno; + } + + return fd; } +/* Concantenate `config->filter_config` with `input` + `\n` */ +static int append_filter_config(struct convert_config *config, const char *input) +{ + char *old_config = config->filter_config; + + /* filer_config can't be NULL for following steps */ + if (!old_config) + old_config = log_asprintf("%s", ""); + + config->filter_config = log_asprintf("%s%s\n", old_config, input); + free(old_config); + if (!config->filter_config) + return -ENOMEM; + return 0; +} + +#if !HAS_INOTIFY +static void *wait_open(const char *watched_dir, const char *expected_file) +{ + assert(HAS_INOTIFY); /* Should never be called */ +} +#else +/* + * This 5 minutes timeout is for "backward compatible safety" in case + * any user/script of an earlier, pre-inotify version of sof-logger + * (accidentally?) _expected_ the tool to quit when the driver was not + * loaded. This expectation was always wrong but an infinite wait is too + * severe of a punishment. This timeout cannot be too small otherwise it + * would defeat the new feature. + */ +#ifndef SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS +#define SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS (5 * 60) +#endif + +/* + * Using inotify, wait up to 5 minutes for 'expected_name' to appear in + * 'watched_dir'. Then return opendir/fopen(expected_name). fopen() and + * opendir() failures are NOT handled; e.g. NULL from fopen() is just + * passed through. + * + * Returns a FILE * or DIR * + */ +static void *wait_open(const char *watched_dir, const char *expected_file) +{ + if (access(watched_dir, R_OK)) { + fprintf(stderr, "error: %s() cannot read %s\n", __func__, watched_dir); + return NULL; + } + + const int iqueue = inotify_init(); + const int dwatch = inotify_add_watch(iqueue, watched_dir, IN_CREATE); + struct stat expected_stat; + void *ret_stream = NULL; + const int fpath_len = strlen(watched_dir) + 1 + strlen(expected_file) + 1; + char * const fpath = malloc(fpath_len); + + if (!fpath) { + fprintf(stderr, "error: can't allocate memory\n"); + exit(EXIT_FAILURE); + } + + snprintf(fpath, fpath_len, "%s/%s", watched_dir, expected_file); + + /* Not racy because the inotify watch was set first. */ + if (!access(fpath, F_OK)) + goto fopenit; + + fprintf(stdout, "%s: waiting in %s/ for %s\n", APP_NAME, watched_dir, expected_file); + fflush(stdout); + + while (1) { + char evlist[1 * sizeof(struct inotify_event)]; + struct pollfd pfd[1] = {{ .fd = iqueue, .events = POLLIN, .revents = 0 }}; + int pret = poll(pfd, sizeof(pfd) / sizeof(struct pollfd), + SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS * 1000); + + if (pret == 0) { + fprintf(stderr, "error: no %s after waiting %d seconds\n", + expected_file, SOF_LOGGER_WAIT_OPEN_TIMEOUT_SECS); + goto cleanup; + } + + if (pret < 0 || pfd[0].revents != POLLIN) { + fprintf(stderr, "error: in %s, poll(%s) returned %d, %d\n", + __func__, watched_dir, pret, pfd[0].revents); + goto cleanup; + } + + /* Silence __attribute__((warn_unused_result)) which is + * enabled by some Linux distros even when broken in gcc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 + */ + (void)!read(iqueue, evlist, sizeof(evlist)); + + if (!access(fpath, F_OK)) + goto fopenit; + } + +fopenit: + if (stat(fpath, &expected_stat)) + goto cleanup; + + if ((expected_stat.st_mode & S_IFMT) == S_IFDIR) + ret_stream = opendir(fpath); + else + ret_stream = fopen(fpath, "rb"); + +cleanup: + free(fpath); + inotify_rm_watch(iqueue, dwatch); + + return ret_stream; +} +#endif // HAS_INOTIFY + +static struct convert_config _global_config; +struct convert_config * const global_config = &_global_config; + int main(int argc, char *argv[]) { + static const char optstring[] = "ho:i:l:ps:c:u:tv:rd:Le:f:gF:n"; struct convert_config config; unsigned int baud = 0; const char *snapshot_file = 0; int opt, ret = 0; config.trace = 0; - config.clock = 19.2; + config.clock = DEFAULT_CLOCK_MHZ; config.in_file = NULL; config.out_file = NULL; config.out_fd = NULL; @@ -148,14 +313,19 @@ int main(int argc, char *argv[]) config.ldc_fd = NULL; config.input_std = 0; /* checking fw version is disabled by default */ - config.version_file = NULL; + config.version_file = "/sys/kernel/debug/sof/fw_version"; config.version_fd = NULL; - config.version_fw = 0; + config.version_fw = 1; config.use_colors = 1; config.serial_fd = -EINVAL; config.raw_output = 0; + config.dump_ldc = 0; + config.hide_location = 0; + config.time_precision = 6; + config.relative_timestamps = INT_MAX; /* unspecified */ + config.filter_config = NULL; - while ((opt = getopt(argc, argv, "ho:i:l:ps:c:u:tev:r")) != -1) { + while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'o': config.out_file = optarg; @@ -173,18 +343,15 @@ int main(int argc, char *argv[]) snapshot_file = optarg; break; case 'l': + if (config.ldc_file) { + fprintf(stderr, "error: Multiple ldc files\n"); + usage(); + } config.ldc_file = optarg; break; case 'p': config.input_std = 1; break; - case 'e': - /* enabling checking fw version with default verification - * file - */ - config.version_fw = 1; - config.version_file = "/sys/kernel/debug/sof/fw_version"; - break; case 'u': baud = atoi(optarg); break; @@ -193,17 +360,65 @@ int main(int argc, char *argv[]) break; case 'v': /* enabling checking fw version with ver_file file */ - config.version_fw = 1; config.version_file = optarg; break; + case 'n': + config.version_fw = 0; + break; + case 'L': + config.hide_location = 1; + break; + case 'e': { + int i = atoi(optarg); + + if (i < 0 || 1 < i) { + fprintf(stderr, "%s: invalid option: -e %s\n", + APP_NAME, optarg); + ret = -EINVAL; + goto out; + } + config.relative_timestamps = i; + break; + } + case 'f': + config.time_precision = atoi(optarg); + if (config.time_precision < 0) { + usage(); + ret = -EINVAL; + goto out; + } + break; + case 'g': + config.time_precision = -1; + break; + case 'd': + if (config.ldc_file) { + fprintf(stderr, "error: Multiple ldc files\n"); + usage(); + } + config.dump_ldc = 1; + config.ldc_file = optarg; + break; + case 'F': + ret = append_filter_config(&config, optarg); + if (ret < 0) + return ret; + break; case 'h': default: /* '?' */ usage(); } } - if (snapshot_file) - return baud ? EINVAL : -snapshot(snapshot_file); + if (argc != optind) { + fprintf(stderr, "error: Unused parameter '%s'\n", argv[optind]); + usage(); + } + + if (snapshot_file) { + ret = baud ? EINVAL : -snapshot(snapshot_file); + goto out; + } if (!config.ldc_file) { fprintf(stderr, "error: Missing ldc file\n"); @@ -212,28 +427,18 @@ int main(int argc, char *argv[]) config.ldc_fd = fopen(config.ldc_file, "rb"); if (!config.ldc_fd) { - fprintf(stderr, "error: Unable to open ldc file %s\n", - config.ldc_file); ret = errno; + fprintf(stderr, "error: Unable to open ldc file %s: %s\n", + config.ldc_file, strerror(ret)); goto out; } - if (config.version_fw) { - config.version_fd = fopen(config.version_file, "rb"); - if (!config.version_fd) { - fprintf(stderr, "error: Unable to open version file %s\n", - config.version_file); - ret = errno; - goto out; - } - } - if (config.out_file) { config.out_fd = fopen(config.out_file, "w"); if (!config.out_fd) { - fprintf(stderr, "error: Unable to open out file %s\n", - config.out_file); ret = errno; + fprintf(stderr, "error: Unable to open out file %s: %s\n", + config.out_file, strerror(ret)); goto out; } } else { @@ -244,10 +449,19 @@ int main(int argc, char *argv[]) if (config.trace) config.in_file = "/sys/kernel/debug/sof/trace"; + /* Default value when -e is not specified */ + if (config.relative_timestamps == INT_MAX) + config.relative_timestamps = config.raw_output ? 0 : 1; + /* default option with no infile is to dump errors/debug data */ - if (!config.in_file) + if (!config.in_file && !config.dump_ldc) config.in_file = "/sys/kernel/debug/sof/etrace"; + if (!config.in_file && baud) { + fprintf(stderr, "error: No UART device specified\n"); + usage(); + } + if (config.input_std) { config.in_fd = stdin; } else if (baud) { @@ -256,21 +470,58 @@ int main(int argc, char *argv[]) ret = -config.serial_fd; goto out; } - } else { - config.in_fd = fopen(config.in_file, "rb"); + } else if (config.in_file) { + static const char sys_debug[] = "/sys/kernel/debug"; + static const char sys_debug_sof[] = "/sys/kernel/debug/sof"; + /* In the future we could add an option to force waiting + * for _any_ input file, not just for /sys/kernel/debug/sof/[e]trace + */ + config.in_fd = NULL; + if (!HAS_INOTIFY || + strncmp(config.in_file, sys_debug, strlen(sys_debug))) { + config.in_fd = fopen(config.in_file, "rb"); + } else { // both inotify and /sys/kernel/debug/ + DIR *dbg_sof = (DIR *)wait_open(sys_debug, "sof"); + + if (dbg_sof) { + closedir(dbg_sof); + config.in_fd = + (FILE *)wait_open(sys_debug_sof, + config.in_file + + strlen(sys_debug_sof) + 1); + } + } + if (!config.in_fd) { - fprintf(stderr, "error: Unable to open in file %s\n", - config.in_file); ret = errno; + fprintf(stderr, + "error: Unable to open in file %s: %s\n", + config.in_file, strerror(ret)); goto out; } } if (isatty(fileno(config.out_fd)) != 1) config.use_colors = 0; - ret = -convert(&config); + if (config.version_fw) { + config.version_fd = fopen(config.version_file, "rb"); + if (!config.version_fd && !config.dump_ldc) { + ret = errno; + fprintf(stderr, + "error: Unable to open version file %s: %s\n", + config.version_file, strerror(ret)); + goto out; + } + } + + _global_config = config; + ret = -convert(); out: + /* free memory */ + if (config.filter_config) + free(config.filter_config); + /* close files */ if (config.out_fd) fclose(config.out_fd); diff --git a/tools/logger/misc.c b/tools/logger/misc.c new file mode 100644 index 000000000000..20e5db9f95b8 --- /dev/null +++ b/tools/logger/misc.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#include "convert.h" +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +char *log_vasprintf(const char *format, va_list args) +{ + va_list args_copy; + int size; + char localbuf[1]; + char *result; + + va_copy(args_copy, args); + size = vsnprintf(localbuf, 1, format, args_copy); + va_end(args_copy); + + result = malloc(size + 1); + if (result) + vsnprintf(result, size + 1, format, args); + return result; +} + +char *log_asprintf(const char *format, ...) +{ + va_list args; + char *result; + + va_start(args, format); + result = log_vasprintf(format, args); + va_end(args); + + return result; +} + +/** Prints 1. once to stderr. 2. a second time to the global out_fd if + * out_fd is neither stderr nor stdout (because the -o option was used). + */ +void log_err(const char *fmt, ...) +{ + FILE *out_fd = global_config ? global_config->out_fd : NULL; + static const char prefix[] = "error: "; + ssize_t needed_size; + va_list args, args_alloc; + char *buff; + + va_start(args, fmt); + + /* Print into buff first, then outputs buff twice */ + va_copy(args_alloc, args); + needed_size = vsnprintf(NULL, 0, fmt, args_alloc) + 1; + buff = malloc(needed_size); + va_end(args_alloc); + + if (buff) { + vsprintf(buff, fmt, args); + fprintf(stderr, "%s%s", prefix, buff); + + /* take care about out_fd validity and duplicated logging */ + if (out_fd && out_fd != stderr && out_fd != stdout) { + fprintf(out_fd, "%s%s", prefix, buff); + fflush(out_fd); + } + free(buff); + } else { + fprintf(stderr, "%s", prefix); + vfprintf(stderr, fmt, args); + } + + va_end(args); +} + +/* trim whitespaces from string begin */ +char *ltrim(char *s) +{ + while (isspace((int)*s)) + s++; + return s; +} + +/* trim whitespaces from string end */ +char *rtrim(char *s) +{ + char *ptr = s + strlen(s) - 1; + + while (ptr >= s && isspace((int)*ptr)) { + *ptr = '\0'; + --ptr; + } + return s; +} + +/* trim whitespaces from string begin and end*/ +char *trim(char *s) +{ + return ltrim(rtrim(s)); +} diff --git a/tools/logger/misc.h b/tools/logger/misc.h new file mode 100644 index 000000000000..b2beb9259ae1 --- /dev/null +++ b/tools/logger/misc.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#include <stdarg.h> +#include <stdlib.h> + +char *log_vasprintf(const char *format, va_list args); + +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif +char *log_asprintf(const char *format, ...); + +#ifdef __GNUC__ +__attribute__((format(printf, 1, 2))) +#endif +void log_err(const char *fmt, ...); + +/* trim whitespaces from string begin */ +char *ltrim(char *s); + +/* trim whitespaces from string end */ +char *rtrim(char *s); + +/* trim whitespaces from string begin and end*/ +char *trim(char *s); diff --git a/tools/mtrace/mtrace-reader.c b/tools/mtrace/mtrace-reader.c new file mode 100644 index 000000000000..ae5eb31d68a8 --- /dev/null +++ b/tools/mtrace/mtrace-reader.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. +// +// Author: Kai Vehmanen <kai.vehmanen@linux.intel.com> +// +// Compile instructions: +// gcc -o mtrace-reader mtrace-reader.c -Wall -O2 +// + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdint.h> + +#define READ_BUFFER 16384 +#define MTRACE_FILE "/sys/kernel/debug/sof/mtrace/core0" + +uint8_t buffer[READ_BUFFER]; + +int main(void) +{ + ssize_t read_bytes; + uint32_t data_len; + uint32_t header; + int fd; + + fd = open(MTRACE_FILE, O_RDONLY); + if (fd < 0) { + perror("open"); + return 1; + } + + while (1) { + read_bytes = read(fd, buffer, READ_BUFFER); + + /* handle end-of-file */ + if (read_bytes == 0) + continue; + + if (read_bytes <= 4) + continue; + + header = *(uint32_t *)buffer; + data_len = header; + if (data_len > read_bytes - 4) + continue; + + if (write(STDOUT_FILENO, buffer + 4, data_len) < 0) { + perror("write"); + return -1; + } + } + + close(fd); + + return 0; +} diff --git a/tools/mtrace/mtrace-reader.py b/tools/mtrace/mtrace-reader.py new file mode 100755 index 000000000000..d0acbd1cfce6 --- /dev/null +++ b/tools/mtrace/mtrace-reader.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# +# Copyright (c) 2022, Intel Corporation. All rights reserved. + +#pylint:disable=mixed-indentation + +# Tool to stream data from Linux SOF driver "mtrace" debugfs +# interface to standard output. Plain "cat" is not sufficient +# as each read() syscall returns log data with a 32bit binary +# header, containing the payload length. + +import struct +import os +import sys +import argparse + +READ_BUFFER = 16384 +MTRACE_FILE = "/sys/kernel/debug/sof/mtrace/core0" + +parser = argparse.ArgumentParser() +parser.add_argument('-m', '--mark-chunks', + action='store_true') + +args = parser.parse_args() + +chunk_idx = 0 + +fd = os.open(MTRACE_FILE, os.O_RDONLY) +while fd >= 0: + # direct unbuffered os.read() must be used to comply with + # debugfs protocol used. each non-zero read will return + # a buffer containing a 32bit header and a payload + read_bytes = os.read(fd, READ_BUFFER) + + # handle end-of-file + if len(read_bytes) == 0: + continue + + if len(read_bytes) <= 4: + continue + + header = struct.unpack('I', read_bytes[0:4]) + data_len = header[0] + data = read_bytes[4:4+data_len] + + if (args.mark_chunks): + chunk_msg = "\n--- Chunk #{} start (size: {}) ---\n" .format(chunk_idx, data_len) + sys.stdout.write(chunk_msg) + + sys.stdout.buffer.write(data) + sys.stdout.flush() + chunk_idx += 1 diff --git a/tools/plugin/CMakeLists.txt b/tools/plugin/CMakeLists.txt new file mode 100644 index 000000000000..a137a4b7d04c --- /dev/null +++ b/tools/plugin/CMakeLists.txt @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.13) + +project(SOF_PLUGIN C CXX) + +include(../../scripts/cmake/misc.cmake) +include(CheckCCompilerFlag) + +set(sof_source_directory "${PROJECT_SOURCE_DIR}/../..") +set(sof_install_directory "${PROJECT_BINARY_DIR}/sof_ep/install") +set(sof_binary_directory "${PROJECT_BINARY_DIR}/sof_ep/build") + +set(config_h ${sof_binary_directory}/library_autoconfig.h) + +set(parser_source_directory "${PROJECT_SOURCE_DIR}/../tplg_parser") +set(parser_install_dir "${PROJECT_BINARY_DIR}/sof_parser/install") + +message("ipc4 build") +set(tplg_ipc plugin_ipc4_defconfig) + +include(ExternalProject) + +# External project for SOF library +ExternalProject_Add(sof_ep + DOWNLOAD_COMMAND "" + SOURCE_DIR "${sof_source_directory}" + PREFIX "${PROJECT_BINARY_DIR}/sof_ep" + BINARY_DIR "${sof_binary_directory}" + CMAKE_ARGS -DCONFIG_LIBRARY=ON + -DCMAKE_INSTALL_PREFIX=${sof_install_directory} + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -DINIT_CONFIG=${tplg_ipc} + -DCONFIG_H_PATH=${config_h} + -DCONFIG_LIBRARY_STATIC=ON + -DOPTIMIZE_FOR_DEBUG=ON + BUILD_ALWAYS 1 + BUILD_BYPRODUCTS "${sof_install_directory}/lib/libsof.a" +) + +add_library(sof_library STATIC IMPORTED) +set_target_properties(sof_library PROPERTIES IMPORTED_LOCATION "${sof_install_directory}/lib/libsof.a") +add_dependencies(sof_library sof_ep) + +# External project for topology parser +ExternalProject_Add(parser_ep + SOURCE_DIR "${parser_source_directory}" + PREFIX "${PROJECT_BINARY_DIR}/sof_parser" + BINARY_DIR "${PROJECT_BINARY_DIR}/sof_parser/build" + CMAKE_ARGS -DCONFIG_LIBRARY=ON + -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/sof_parser/install + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -DCONFIG_LIBRARY_STATIC=ON + -DOPTIMIZE_FOR_DEBUG=ON + BUILD_ALWAYS 1 + BUILD_BYPRODUCTS "${parser_install_dir}/lib/libsof_tplg_parser.a" +) + +add_library(sof_parser_lib STATIC IMPORTED) +set_target_properties(sof_parser_lib PROPERTIES IMPORTED_LOCATION "${parser_install_dir}/lib/libsof_tplg_parser.a") +add_dependencies(sof_parser_lib parser_ep) + +add_subdirectory(alsaconf) +add_subdirectory(alsaplug) +add_subdirectory(modules) +add_subdirectory(pipe) + +add_dependencies(asound_module_pcm_sof sof_parser_lib) +add_dependencies(asound_module_ctl_sof sof_parser_lib) + +add_dependencies(sof-pipe sof_mod_shm) +add_dependencies(sof-pipe sof_mod_alsa) diff --git a/tools/plugin/README.md b/tools/plugin/README.md new file mode 100644 index 000000000000..e225437b404f --- /dev/null +++ b/tools/plugin/README.md @@ -0,0 +1,161 @@ +# ALSA Plugin + +The SOF ALSA plugin allows SOF topologies to be run on the host. The plugin +is still WIP with many rough edges that need refined before production +deployment, however the plugin is usable today as a rapid development +framework for SOF infrastructure and processing. + +### Features + * aplay & arecord usage working today + * alsamixer & amixer usage not working today + * modules are loaded as SO shared libraries. + * topology is parsed by the plugin and pipelines associated with the requested PCM ID are loaded + * pipelines run as individual userspace threads + * pipelines can be pinned to efficency cores + * pipelines can use realtime priority. + * alsa sink and alsa source modules available. + * pipelines can block (non blocking and mmap todo) + +### License +Code is a mixture of LGPL and BSD 3c. + +### Usage +Please build as cmake project, for IPC4 (functional) +IPC3 is not functional and not supported + +``` +cd sof +cmake -GNinja -B build-plugin/ -S tools/plugin/ +# Build external projects first to avoid build race condition +# Dropping -GNinja is another (very slow) option. +cmake --build build-plugin/ -- sof_ep parser_ep +cmake --build build-plugin/ +``` +then (use default ALSA prefix atm) + +``` +sudo cmake --install build-plugin/ + +Make sure to set the LD_LIBRARY_PATH to include directory where the SOF modules are installed +Ex: "~/work/sof/sof/build-plugin/sof_ep/install/lib:~/work/sof/sof/build-plugin/modules/" +And set the environment variable SOF_PLUGIN_TOPOLOGY_PATH to point to the directory containing the topology binary +``` + +Code can then be run by starting sof-pipe with your desired topology (Ex: sof-plugin.tplg) + +``` + ./sof-pipe -T sof-plugin.tplg +``` + +At this point the sof-pipe daemon is waiting for IPC. Audio applications can now invoke sof-pipe processing via + +``` +aplay -Dsof:plugin:1:default:default:48k2c16b -f dat some48kHz.wav +``` +The command line is parsed as follows: +- "sof" is the plugin name +- "sof-plugin" is the topology name. The "sof-" prefix and ".tplg" suffix will be appended by the plugin +- "1" is the PCM ID for render/capture +- "default": The first default is the card name +- "default": The second default is the device name +- "48k2c16b" is the config name for 48K, stereo, 16bit + +Config name is optional in the command line. When it is not provided, hw_params will be used to +configure the endpoint. In this case, the command line can be simplified to: + +``` +aplay -Dsof:plugin:1:default:default +``` + +When using the default device, the command line can be further simplified to: + +``` +aplay -Dsof:plugin:1 +``` + +This renders audio to the sof-pipe daemon using the sof-plugin topology playback PCM ID 1. +The above example needs to be 48k as example pipe has no SRC/ASRC. + +Likewise + +``` +arecord -Dsof:plugin:1:default:default:48k2c16b -f dat file.wav +``` +Will record audio using the plugin topology and PCM ID 1. + +Mixer settings can be adjusted for sof-plugin by + +``` +alsamixer -Dsof:plugin +``` +or +``` +amixer -Dsof:plugin cset numid=1 20 +``` +Bytes control data can be set using sof-ctl as follows: + +``` +./sof-ctl -Dsof:plugin -n 4 -r -i 4 -p 2 -s ~/data.txt +``` +where -n is the numid of the kcontrol, -i is the IPC version, -p is the param ID and -s specifies +the data in csv format. + +Bytes control data can be read using sof-ctl as follows: +``` +./sof-ctl -Dsof:plugin -n 4 -i 4 -p 2 +``` +where -n is the numid of the kcontrol, -i is the IPC version and -p is the param ID. + +Note: Bytes controls must have tlv_read/tlv_write and tlv_callback access. + +## Instructions for testing OpenVino noise suppression model with the SOF plugin: +1. Prepare Open Model Zoo repository: + + - Clone repo: + ``` + git clone --recurse-submodules https://github.com/openvinotoolkit/open_model_zoo.git + ``` + + - Build demo applications: + https://docs.openvino.ai/2023.3/omz_demos.html#a-name-build-demos-linux-a-build-the-demo-applications-on-linux + +2. Source OpenVino environment and get OpenCV +https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit-download.html + +3. Worth building and running the demo noise suppression application in the open model zoo +repository to make sure OpenVino and OpenCV are configured properly. +Fetch the model, e.g., `noise-suppression-poconetlike-0001.xml`, by running this demo: + + https://docs.openvino.ai/2023.3/omz_demos_noise_suppression_demo_cpp.html + +4. Set environment variable NOISE_SUPPRESSION_MODEL_NAME to point to the model file +``` +export NOISE_SUPPRESSION_MODEL_NAME=~/open_model_zoo/demos/noise_suppression_demo/cpp/intel/noise-suppression-poconetlike-0001/FP16/noise-suppression-poconetlike-0001.xml + +``` +5. Set environment variable OpenVINO_DIR to include CMake files (e.g., OpenVINOConfig.cmake) for building the plugin: +``` +export OpenVINO_DIR=~/openvino_env/lib/python3.10/site-packages/openvino/cmake + +``` +6. Update environment variable LD_LIBRARY_PATH to include necessary directories for the plugin: + +``` +export LD_LIBRARY_PATH=~/work/sof/sof/build-plugin/sof_ep/install/lib:~/work/sof/sof/build-plugin/modules/:~/work/sof/sof/build-plugin/modules/ov_noise_suppression/ +``` + +7. Enable noise suppression by setting NOISE_SUPPRESSION=true in the tplg-targets for the sof-plugin topology + +8. Rebuild the plugin: Remove the previous build-build directory and rebuild it by following the usage steps above. + +9. Start capture using the following command. This uses the 16K capture from the DMIC from +PCM hw device 0,7. Currently, only 16K capture is supported but in the future this will be expanded +to work with 48K capture. +``` +arecord -Dsof:plugin:1:0:7:16k2c16b -f dat -r 16000 --period-size=2048 file_ns_16k.wav +``` + +### TODO Items for single pipeline E2E audio +Use hw_params instead of hardcoded config +Add support for 24-bit and 16-bit audio +Remove duplication of kcontrols when alsamixer is opened/closed repeatedly \ No newline at end of file diff --git a/tools/plugin/alsaconf/50-sof.conf b/tools/plugin/alsaconf/50-sof.conf new file mode 100644 index 000000000000..91566ec28a55 --- /dev/null +++ b/tools/plugin/alsaconf/50-sof.conf @@ -0,0 +1,94 @@ +# Invoke a SOF pipeline and route it to a sound card or another plugin +# To use the PCM 0 on the SOF "volume" topology and route it to hw:1,2 then run +# aplay -Dsof:volume:0,hw,1,2 +# tplg:pipe:[pipe:card:dev:config[pipe:card:dev:config]...] +# +# TPLG SOF topology configuration (mandatory) + +pcm.sof { + @args [ TPLG ] + @args.TPLG { + type string + default "passthrough" + } + + type sof + tplg $TPLG + + hint { + show { + @func refer + name defaults.namehint.basic + } + description "SOF Topology and PCM" + } + + config.48k2c16b { + rate 48000 + channels 2 + format S16_LE + period_time 0 + period_frames 48 + buffer_time 0 + buffer_frames 192 + } + + config.16k2c16b { + rate 16000 + channels 2 + format S16_LE + period_time 0 + period_frames 2048 # based on the period size needed for Noise suppression module + buffer_time 0 + buffer_frames 8192 + } + + config.48k8c16b { + rate 48000 + channels 8 + format S16_LE + period_time 0 + period_frames 1024 + buffer_time 0 + buffer_frames 5120 + } + + config.8k8c16b { + rate 8000 + channels 8 + format S16_LE + period_time 0 + period_frames 1024 + buffer_time 0 + buffer_frames 5120 + } + + config.48k2c32b { + rate 48000 + channels 2 + format S32_LE + period_time 0 + period_frames 6000 + buffer_time 0 + buffer_frames 24000 + } +} + +ctl.sof { + @args [ TPLG ] + @args.TPLG { + type string + default "passthrough" + } + + type sof + tplg $TPLG + + hint { + show { + @func refer + name defaults.namehint.basic + } + description "SOF Topology" + } +} diff --git a/tools/plugin/alsaconf/CMakeLists.txt b/tools/plugin/alsaconf/CMakeLists.txt new file mode 100644 index 000000000000..3a58c514f522 --- /dev/null +++ b/tools/plugin/alsaconf/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +install(FILES 50-sof.conf DESTINATION /usr/share/alsa/alsa.conf.d) +# HACK needs to link to above +install(FILES 50-sof.conf DESTINATION /etc/alsa/conf.d) diff --git a/tools/plugin/alsaplug/CMakeLists.txt b/tools/plugin/alsaplug/CMakeLists.txt new file mode 100644 index 000000000000..d60104d8245d --- /dev/null +++ b/tools/plugin/alsaplug/CMakeLists.txt @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# PCM ALSA module +add_library(asound_module_pcm_sof MODULE + pcm.c + plugin.c + ../common.c + tplg.c + tplg_ctl.c +) + +sof_append_relative_path_definitions(asound_module_pcm_sof) + +target_include_directories(asound_module_pcm_sof PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${sof_source_directory}/src/audio) + +target_compile_options(asound_module_pcm_sof PRIVATE -DPIC -g -O3 -Wmissing-prototypes + -Wno-stringop-truncation -Wimplicit-fallthrough -DCONFIG_LIBRARY -imacros${config_h}) + +install(TARGETS asound_module_pcm_sof DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +target_link_options(asound_module_pcm_sof PRIVATE -Wl,--export-dynamic,--no-undefined) +target_link_libraries(asound_module_pcm_sof PRIVATE sof_library) +target_link_libraries(asound_module_pcm_sof PRIVATE sof_parser_lib) +target_link_libraries(asound_module_pcm_sof PRIVATE pthread) +target_link_libraries(asound_module_pcm_sof PRIVATE -lasound -ldl -lm -lasound -lrt) + +target_include_directories(asound_module_pcm_sof PRIVATE ${sof_install_directory}/include) +target_include_directories(asound_module_pcm_sof PRIVATE ${parser_install_dir}/include) + +set_target_properties(asound_module_pcm_sof + PROPERTIES + INSTALL_RPATH "${sof_install_directory}/alsa-lib" + INSTALL_RPATH_USE_LINK_PATH TRUE +) + +# CTL ALSA module +add_library(asound_module_ctl_sof MODULE + ctl.c + plugin.c + ../common.c +) +sof_append_relative_path_definitions(asound_module_ctl_sof) +target_include_directories(asound_module_ctl_sof PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${sof_source_directory}/src/audio) + +target_compile_options(asound_module_ctl_sof PRIVATE -DPIC -g -O3 -Wmissing-prototypes + -Wimplicit-fallthrough -Wno-stringop-truncation -Wall -Werror -DCONFIG_LIBRARY -imacros${config_h}) + +install(TARGETS asound_module_ctl_sof DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +target_link_options(asound_module_ctl_sof PRIVATE -Wl,--export-dynamic,--no-undefined) +target_link_libraries(asound_module_ctl_sof PRIVATE sof_library) +target_link_libraries(asound_module_ctl_sof PRIVATE sof_parser_lib) +target_link_libraries(asound_module_ctl_sof PRIVATE pthread) +target_link_libraries(asound_module_ctl_sof PRIVATE -lasound -ldl -lm -lasound -lrt) + +target_include_directories(asound_module_ctl_sof PRIVATE ${sof_install_directory}/include) +target_include_directories(asound_module_ctl_sof PRIVATE ${parser_install_dir}/include) + +set_target_properties(asound_module_ctl_sof + PROPERTIES + INSTALL_RPATH "${sof_install_directory}/alsa-lib" + INSTALL_RPATH_USE_LINK_PATH TRUE +) diff --git a/tools/plugin/alsaplug/conf.c b/tools/plugin/alsaplug/conf.c new file mode 100644 index 000000000000..5b259bf6885a --- /dev/null +++ b/tools/plugin/alsaplug/conf.c @@ -0,0 +1,47 @@ +/*-*- linux-c -*-*/ + +/* + * ALSA <-> SOF Config plugin + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + */ + +#include <stdio.h> +#include <alsa/asoundlib.h> +#include "plugin.h" + +/* Not actually part of the alsa api.... */ +extern int +snd_config_hook_load(snd_config_t *root, snd_config_t *config, + snd_config_t **dst, snd_config_t *private_data); + +/* manifest file could be loaded as a hook */ +int sofplug_load_hook(snd_config_t *root, snd_config_t *config, + snd_config_t **dst, snd_config_t *private_data) +{ + int ret = 0; + + *dst = NULL; + + /* TODO: load hook when SOF ready */ + return snd_config_hook_load(root, config, dst, private_data); +} + +SND_DLSYM_BUILD_VERSION(sofplug_load_hook, + SND_CONFIG_DLSYM_VERSION_HOOK); diff --git a/tools/plugin/alsaplug/ctl.c b/tools/plugin/alsaplug/ctl.c new file mode 100644 index 000000000000..85a31177cfca --- /dev/null +++ b/tools/plugin/alsaplug/ctl.c @@ -0,0 +1,845 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <mqueue.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> + +// TODO remove parsing and read ctls from sof-pipe SHM glb context +#include <ipc/control.h> + +#include <alsa/asoundlib.h> +#include <alsa/control_external.h> + +#include "plugin.h" +#include "common.h" + +typedef struct snd_sof_ctl { + struct plug_shm_glb_state *glb; + snd_ctl_ext_t ext; + struct plug_socket_desc ipc; + struct plug_shm_desc shm_ctx; + int subscribed; + int updated[MAX_CTLS]; + +} snd_sof_ctl_t; + +#define CTL_GET_TPLG_HDR(_ctl, _key) \ + (&_ctl->glb->ctl[_key].mixer_ctl.hdr) + +#define CTL_GET_TPLG_MIXER(_ctl, _key) \ + (&_ctl->glb->ctl[_key].mixer_ctl) + +#define CTL_GET_TPLG_ENUM(_ctl, _key) \ + (&_ctl->glb->ctl[_key].enum_ctl) + +#define CTL_GET_TPLG_BYTES(_ctl, _key) \ + (&_ctl->glb->ctl[_key].bytes_ctl) + +static uint32_t mixer_to_ipc(unsigned int value, uint32_t *volume_table, int size) +{ + if (value >= size) + return volume_table[size - 1]; + + return volume_table[value]; +} + +static uint32_t ipc_to_mixer(uint32_t value, uint32_t *volume_table, int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (volume_table[i] >= value) + return i; + } + + return i - 1; +} + +/* number of ctls */ +static int plug_ctl_elem_count(snd_ctl_ext_t *ext) +{ + snd_sof_ctl_t *ctl = ext->private_data; + + /* TODO: get count of elems from topology */ + return ctl->glb->num_ctls; +} + +static int plug_ctl_elem_list(snd_ctl_ext_t *ext, unsigned int offset, snd_ctl_elem_id_t *id) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_ctl_hdr *hdr; + + if (offset >= ctl->glb->num_ctls) + return -EINVAL; + + hdr = CTL_GET_TPLG_HDR(ctl, offset); + + snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); + snd_ctl_elem_id_set_name(id, hdr->name); + + return 0; +} + +static snd_ctl_ext_key_t plug_ctl_find_elem(snd_ctl_ext_t *ext, const snd_ctl_elem_id_t *id) +{ + snd_sof_ctl_t *ctl = ext->private_data; + unsigned int numid; + + numid = snd_ctl_elem_id_get_numid(id); + + if (numid > ctl->glb->num_ctls) + return SND_CTL_EXT_KEY_NOT_FOUND; + + return numid - 1; +} + +static int plug_ctl_get_attribute(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + int *type, unsigned int *acc, unsigned int *count) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_ctl_hdr *hdr = CTL_GET_TPLG_HDR(ctl, key); + struct snd_soc_tplg_mixer_control *mixer_ctl; + struct snd_soc_tplg_enum_control *enum_ctl; + struct snd_soc_tplg_bytes_control *bytes_ctl; + int err = 0; + + switch (hdr->ops.info) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + mixer_ctl = (struct snd_soc_tplg_mixer_control *)hdr; + + /* check for type - boolean should be binary values */ + if (mixer_ctl->max == 1 && mixer_ctl->min == 0) + *type = SND_CTL_ELEM_TYPE_BOOLEAN; + else + *type = SND_CTL_ELEM_TYPE_INTEGER; + *count = 2;//mixer_ctl->num_channels; ///// WRONG is 0 !!! + + //printf("mixer %d %d\n", __LINE__, mixer_ctl->num_channels); + break; + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_CTL_ENUM_VALUE: + enum_ctl = (struct snd_soc_tplg_enum_control *)hdr; + *type = SND_CTL_ELEM_TYPE_ENUMERATED; + *count = enum_ctl->items; + break; + case SND_SOC_TPLG_CTL_RANGE: + case SND_SOC_TPLG_CTL_STROBE: + // TODO: ?? + break; + case SND_SOC_TPLG_CTL_BYTES: + bytes_ctl = (struct snd_soc_tplg_bytes_control *)hdr; + *type = SND_CTL_ELEM_TYPE_BYTES; + *count = bytes_ctl->max; + break; + } + + *acc = hdr->access; + + /* access needs the callback to decode the data */ + if ((hdr->access & SND_CTL_EXT_ACCESS_TLV_READ) || + (hdr->access & SND_CTL_EXT_ACCESS_TLV_WRITE)) + *acc |= SND_CTL_EXT_ACCESS_TLV_CALLBACK; + return err; +} + +/* + * Integer ops + */ +static int plug_ctl_get_integer_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *imin, + long *imax, long *istep) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_ctl_hdr *hdr = CTL_GET_TPLG_HDR(ctl, key); + struct snd_soc_tplg_mixer_control *mixer_ctl = + CTL_GET_TPLG_MIXER(ctl, key); + int err = 0; + + switch (hdr->type) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + /* TLV uses the fields differently */ + if ((hdr->access & SND_CTL_EXT_ACCESS_TLV_READ) || + (hdr->access & SND_CTL_EXT_ACCESS_TLV_WRITE)) { + *istep = mixer_ctl->hdr.tlv.scale.step; + *imin = (int32_t)mixer_ctl->hdr.tlv.scale.min; + *imax = mixer_ctl->max; + } else { + *istep = 1; + *imin = mixer_ctl->min; + *imax = mixer_ctl->max; + } + break; + default: + SNDERR("invalid ctl type for integer using key %d", key); + err = -EINVAL; + break; + } + + return err; +} + +static int plug_ctl_read_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_mixer_control *mixer_ctl = CTL_GET_TPLG_MIXER(ctl, key); + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_peak_volume_config *volume; + struct ipc4_module_large_config_reply *reply; + char *reply_data; + void *msg; + int reply_data_size, size; + int num_data_items; + int i, err; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, IPC4_VOLUME, sizeof(volume), ctl->glb->ctl[key].module_id, + ctl->glb->ctl[key].instance_id, SOF_IPC4_MOD_LARGE_CONFIG_GET); + + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + size = sizeof(config); + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + /* reply contains both the requested data and the reply status */ + reply_data_size = sizeof(*reply) + mixer_ctl->num_channels * sizeof(*volume); + reply_data = calloc(reply_data_size, 1); + if (!reply_data_size) { + free(msg); + return -ENOMEM; + } + + /* send the IPC message */ + memcpy(msg, &config, sizeof(config)); + err = plug_ipc_cmd_tx_rx(&ctl->ipc, msg, size, reply_data, reply_data_size); + free(msg); + if (err < 0) { + SNDERR("failed to set volume for control %s\n", mixer_ctl->hdr.name); + goto out; + } + + reply = (struct ipc4_module_large_config_reply *)reply_data; + if (reply->primary.r.status != IPC4_SUCCESS) { + SNDERR("volume control %s set failed with status %d\n", + mixer_ctl->hdr.name, reply->primary.r.status); + err = -EINVAL; + goto out; + } + + /* check data sanity */ + num_data_items = reply->extension.r.data_off_size / sizeof(*volume); + if (num_data_items != mixer_ctl->num_channels) { + SNDERR("Channel count %d doesn't match the expected value %d\n", + num_data_items, mixer_ctl->num_channels); + err = -EINVAL; + goto out; + } + + /* set the mixer values based on the received data */ + volume = (struct ipc4_peak_volume_config *)(reply_data + sizeof(*reply)); + for (i = 0; i < mixer_ctl->num_channels; i++) + value[i] = ipc_to_mixer(volume[i].target_volume, ctl->glb->ctl[key].volume_table, + mixer_ctl->max + 1); +out: + free(reply_data); + return err; +} + +static int plug_ctl_write_integer(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, long *value) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_mixer_control *mixer_ctl = CTL_GET_TPLG_MIXER(ctl, key); + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_peak_volume_config volume; + struct ipc4_message_reply reply; + bool all_channels_equal = true; + uint32_t val; + void *msg; + int size, err; + int i; + + /* set data for IPC */ + val = value[0]; + for (i = 1; i < mixer_ctl->num_channels; i++) { + if (value[i] != val) { + all_channels_equal = false; + break; + } + } + + /* + * if all channels have the same volume, send a single IPC, else, send individual IPCs + * for each channel + */ + for (i = 0; i < mixer_ctl->num_channels; i++) { + if (all_channels_equal) { + volume.channel_id = IPC4_ALL_CHANNELS_MASK; + volume.target_volume = mixer_to_ipc(val, ctl->glb->ctl[key].volume_table, + mixer_ctl->max + 1); + } else { + volume.channel_id = i; + volume.target_volume = mixer_to_ipc(value[i], + ctl->glb->ctl[key].volume_table, + mixer_ctl->max + 1); + } + + /* TODO: get curve duration and type from topology */ + volume.curve_type = 1; + volume.curve_duration = 200000; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, IPC4_VOLUME, sizeof(volume), + ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + size = sizeof(config) + sizeof(volume); + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), &volume, sizeof(volume)); + + /* send the message and check status */ + err = plug_ipc_cmd_tx_rx(&ctl->ipc, msg, size, &reply, sizeof(reply)); + free(msg); + if (err < 0) { + SNDERR("failed to set volume control %s\n", mixer_ctl->hdr.name); + return err; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("volume control %s set failed with status %d\n", + mixer_ctl->hdr.name, reply.primary.r.status); + return -EINVAL; + } + + if (all_channels_equal) + break; + } + + return 0; +} + +/* + * Enum ops + */ +static int plug_ctl_get_enumerated_info(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + unsigned int *items) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_ctl_hdr *hdr = CTL_GET_TPLG_HDR(ctl, key); + struct snd_soc_tplg_enum_control *enum_ctl = + (struct snd_soc_tplg_enum_control *)hdr; + int err = 0; + + switch (hdr->ops.info) { + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_CTL_ENUM_VALUE: + *items = enum_ctl->items; + break; + default: + SNDERR("invalid ctl type for enum using key %d", key); + err = -EINVAL; + break; + } + + return err; +} + +static int plug_ctl_get_enumerated_name(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + unsigned int item, char *name, size_t name_max_len) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_ctl_hdr *hdr = CTL_GET_TPLG_HDR(ctl, key); + struct snd_soc_tplg_enum_control *enum_ctl = + (struct snd_soc_tplg_enum_control *)hdr; + + if (item >= enum_ctl->items) { + SNDERR("invalid item %d for enum using key %d\n", item, key); + return -EINVAL; + } + + strncpy(name, enum_ctl->texts[item], name_max_len); + return 0; +} + +static int plug_ctl_read_enumerated(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + unsigned int *items) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_enum_control *enum_ctl = CTL_GET_TPLG_ENUM(ctl, key); + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_module_large_config_reply *reply; + struct sof_ipc4_control_msg_payload *data; + char *reply_data; + void *msg; + int size, reply_data_size; + int i, err; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, SOF_IPC4_ENUM_CONTROL_PARAM_ID, 0, + ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_GET); + + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + size = sizeof(config); + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + /* reply contains both the requested data and the reply status */ + reply_data_size = sizeof(*reply) + sizeof(*data) + + enum_ctl->num_channels * sizeof(data->chanv[0]); + reply_data = calloc(reply_data_size, 1); + if (!reply_data_size) { + free(msg); + return -ENOMEM; + } + + /* send the IPC message */ + memcpy(msg, &config, sizeof(config)); + err = plug_ipc_cmd_tx_rx(&ctl->ipc, msg, size, reply_data, reply_data_size); + free(msg); + if (err < 0) { + SNDERR("failed to get enum items for control %s\n", enum_ctl->hdr.name); + goto out; + } + + reply = (struct ipc4_module_large_config_reply *)reply_data; + if (reply->primary.r.status != IPC4_SUCCESS) { + SNDERR("enum control %s get failed with status %d\n", + enum_ctl->hdr.name, reply->primary.r.status); + err = -EINVAL; + goto out; + } + + /* check data sanity */ + data = (struct sof_ipc4_control_msg_payload *)(reply_data + sizeof(*reply)); + if (data->num_elems != enum_ctl->num_channels) { + SNDERR("Channel count %d doesn't match the expected value %d for enum ctl %s\n", + data->num_elems, enum_ctl->num_channels, enum_ctl->hdr.name); + err = -EINVAL; + goto out; + } + + /* set the enum items based on the received data */ + for (i = 0; i < enum_ctl->num_channels; i++) + items[i] = data->chanv[i].value; +out: + free(reply_data); + return 0; +} + +static int plug_ctl_write_enumerated(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + unsigned int *items) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_enum_control *enum_ctl = CTL_GET_TPLG_ENUM(ctl, key); + struct ipc4_module_large_config config = {{ 0 }}; + struct sof_ipc4_control_msg_payload *data; + struct ipc4_message_reply reply; + void *msg; + int data_size, msg_size; + int err, i; + + /* size of control data */ + data_size = enum_ctl->num_channels * sizeof(struct sof_ipc4_ctrl_value_chan) + + sizeof(*data); + + /* allocate memory for control data */ + data = calloc(data_size, 1); + if (!data) + return -ENOMEM; + + /* set param ID and number of channels */ + data->id = ctl->glb->ctl[key].index; + data->num_elems = enum_ctl->num_channels; + + /* set the enum values */ + for (i = 0; i < data->num_elems; i++) { + data->chanv[i].channel = i; + data->chanv[i].value = items[i]; + } + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, SOF_IPC4_ENUM_CONTROL_PARAM_ID, data_size, + ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + + /* + * enum controls can have a maximum of 16 texts/values. So the entire data can be sent + * in a single IPC message + */ + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + /* allocate memory for IPC message */ + msg_size = sizeof(config) + data_size; + msg = calloc(msg_size, 1); + if (!msg) { + free(data); + return -ENOMEM; + } + + /* set the IPC message data */ + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), data, data_size); + free(data); + + /* send the message and check status */ + err = plug_ipc_cmd_tx_rx(&ctl->ipc, msg, msg_size, &reply, sizeof(reply)); + free(msg); + if (err < 0) { + SNDERR("failed to set enum control %s\n", enum_ctl->hdr.name); + return err; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("enum control %s set failed with status %d\n", + enum_ctl->hdr.name, reply.primary.r.status); + return -EINVAL; + } + + return 0; +} + +/* + * Bytes ops + */ +static int plug_ctl_get_bytes_data(snd_sof_ctl_t *ctl, snd_ctl_ext_key_t key, + struct sof_abi_hdr *abi, unsigned int max_bytes) +{ + struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key); + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_module_large_config_reply *reply; + char *reply_data, *data; + void *msg; + uint32_t data_size; + int size, reply_data_size; + int err; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, abi->type, 0, + ctl->glb->ctl[key].module_id, ctl->glb->ctl[key].instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_GET); + + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + size = sizeof(config); + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + /* + * reply contains both the requested data and the reply status. Allocate enough memory + * for max data + */ + reply_data_size = sizeof(*reply) + sizeof(*data) + bytes_ctl->max; + reply_data = calloc(reply_data_size, 1); + if (!reply_data_size) { + free(msg); + return -ENOMEM; + } + + /* send the IPC message */ + memcpy(msg, &config, sizeof(config)); + err = plug_ipc_cmd_tx_rx(&ctl->ipc, msg, size, reply_data, reply_data_size); + free(msg); + if (err < 0) { + SNDERR("failed to get bytes data for control %s\n", bytes_ctl->hdr.name); + goto out; + } + + reply = (struct ipc4_module_large_config_reply *)reply_data; + if (reply->primary.r.status != IPC4_SUCCESS) { + SNDERR("bytes control %s get failed with status %d\n", + bytes_ctl->hdr.name, reply->primary.r.status); + err = -EINVAL; + goto out; + } + + /* check data sanity */ + data = (char *)(reply_data + sizeof(*reply)); + data_size = reply->extension.r.data_off_size; + if (data_size > bytes_ctl->max) { + SNDERR("received data size %d is larger than max %d for bytes control %s\n", + data_size, bytes_ctl->max, bytes_ctl->hdr.name); + err = -EINVAL; + goto out; + } + + abi->size = data_size; + + if (data_size) + memcpy(abi->data, data, MIN(data_size, max_bytes)); + + err = data_size; +out: + free(reply_data); + return err; +} + +static int plug_ctl_read_bytes(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + unsigned char *data, size_t max_bytes) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct sof_abi_hdr *abi = (struct sof_abi_hdr *)data; + int data_size; + + data_size = plug_ctl_get_bytes_data(ctl, key, abi, max_bytes); + if (data_size < 0) + return data_size; + + return 0; +} + +static int plug_ctl_write_bytes(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, + unsigned char *data, size_t max_bytes) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key); + struct sof_abi_hdr *abi = (struct sof_abi_hdr *)data; + int err; + + /* send IPC with kcontrol data */ + err = plug_send_bytes_data(&ctl->ipc, ctl->glb->ctl[key].module_id, + ctl->glb->ctl[key].instance_id, abi); + if (err < 0) { + SNDERR("failed to set bytes data for control %s\n", bytes_ctl->hdr.name); + return err; + } + + return 0; +} + +/* TLV ops used for TLV bytes control callback */ +/* TLV ops used for TLV bytes control callback */ +static int plug_tlv_rw(snd_ctl_ext_t *ext, snd_ctl_ext_key_t key, int op_flag, + unsigned int numid, unsigned int *tlv, unsigned int tlv_size) +{ + snd_sof_ctl_t *ctl = ext->private_data; + struct snd_soc_tplg_bytes_control *bytes_ctl = CTL_GET_TPLG_BYTES(ctl, key); + struct sof_abi_hdr *abi = (struct sof_abi_hdr *)(tlv + 2); /* skip TLV header */ + int data_size; + + /* only bytes and volume controls have tlv callback set */ + if (bytes_ctl->hdr.ops.info != SND_SOC_TPLG_CTL_BYTES) { + struct snd_soc_tplg_mixer_control *mixer_ctl = CTL_GET_TPLG_MIXER(ctl, key); + struct snd_soc_tplg_ctl_hdr *hdr = &mixer_ctl->hdr; + struct snd_soc_tplg_ctl_tlv *mixer_tlv = &hdr->tlv; + + /* set the dbscale values */ + tlv[0] = SND_CTL_TLVT_DB_SCALE; + tlv[1] = sizeof(int) * 2; + tlv[2] = mixer_tlv->scale.min; + tlv[3] = mixer_tlv->scale.mute << 16 | mixer_tlv->scale.step; + + return 0; + } + + /* send IPC with kcontrol data if op_flag is > 0 else send IPC to get kcontrol data */ + if (op_flag) { + int err; + + err = plug_send_bytes_data(&ctl->ipc, ctl->glb->ctl[key].module_id, + ctl->glb->ctl[key].instance_id, abi); + if (err < 0) { + SNDERR("failed to set bytes data for control %s\n", bytes_ctl->hdr.name); + return err; + } + + return 0; + } + + /* read kcontrol data */ + data_size = plug_ctl_get_bytes_data(ctl, key, abi, tlv_size); + if (data_size < 0) + return data_size; + + /* set data size and numid */ + tlv[0] = numid; + tlv[1] = data_size + sizeof(*abi); + + return 0; +} + +static void plug_ctl_subscribe_events(snd_ctl_ext_t *ext, int subscribe) +{ + snd_sof_ctl_t *ctl = ext->private_data; + + ctl->subscribed = !!(subscribe & SND_CTL_EVENT_MASK_VALUE); +} + +static int plug_ctl_read_event(snd_ctl_ext_t *ext, snd_ctl_elem_id_t *id, + unsigned int *event_mask) +{ + snd_sof_ctl_t *ctl = ext->private_data; + int numid; + int err = 0; + + numid = snd_ctl_elem_id_get_numid(id); + + // TODO: we need a notify() or listening thread to take async/volatile ctl + // notifications from sof-pipe and notify userspace via events of the ctl change. + if (!ctl->updated[numid - 1] || !ctl->subscribed) { + err = -EAGAIN; + goto out; + } + + *event_mask = SND_CTL_EVENT_MASK_VALUE; +out: + return err; +} + +static int plug_ctl_poll_revents(snd_ctl_ext_t *ext, struct pollfd *pfd, + unsigned int nfds, unsigned short *revents) +{ + snd_sof_ctl_t *ctl = ext->private_data; + int i; + + *revents = 0; + + for (i = 0; i < ctl->glb->num_ctls; i++) { + if (ctl->updated[i]) { + *revents = POLLIN; + break; + } + } + + return 0; +} + +static void plug_ctl_close(snd_ctl_ext_t *ext) +{ + snd_sof_ctl_t *ctl = ext->private_data; + + /* TODO: munmap */ + close(ctl->ipc.socket_fd); + free(ctl); +} + +static const snd_ctl_ext_callback_t sof_ext_callback = { + .elem_count = plug_ctl_elem_count, + .elem_list = plug_ctl_elem_list, + .find_elem = plug_ctl_find_elem, + .get_attribute = plug_ctl_get_attribute, + .get_integer_info = plug_ctl_get_integer_info, + .read_integer = plug_ctl_read_integer, + .write_integer = plug_ctl_write_integer, + .get_enumerated_info = plug_ctl_get_enumerated_info, + .get_enumerated_name = plug_ctl_get_enumerated_name, + .read_enumerated = plug_ctl_read_enumerated, + .write_enumerated = plug_ctl_write_enumerated, + .read_bytes = plug_ctl_read_bytes, + .write_bytes = plug_ctl_write_bytes, + .subscribe_events = plug_ctl_subscribe_events, + .read_event = plug_ctl_read_event, + .poll_revents = plug_ctl_poll_revents, + .close = plug_ctl_close, +}; + +SND_CTL_PLUGIN_DEFINE_FUNC(sof) +{ + snd_sof_plug_t *plug; + int err; + snd_sof_ctl_t *ctl; + + /* create context */ + plug = calloc(1, sizeof(*plug)); + if (!plug) + return -ENOMEM; + + ctl = calloc(1, sizeof(*ctl)); + if (!ctl) + return -ENOMEM; + plug->module_prv = ctl; + + /* parse the ALSA configuration file for sof plugin */ + err = plug_parse_conf(plug, name, root, conf, true); + if (err < 0) { + SNDERR("failed to parse config: %s", strerror(err)); + goto error; + } + + /* init IPC socket name */ + err = plug_socket_path_init(&ctl->ipc, "sof", "ipc", 0); + if (err < 0) { + SNDERR("error: invalid name for IPC tx mq %s\n", plug->tplg_file); + goto error; + } + + err = plug_create_client_socket(&ctl->ipc); + if (err < 0) { + SNDERR("failed to connect to SOF pipe IPC socket : %s", strerror(err)); + return -errno; + } + + /* create a SHM mapping for low latency stream position */ + err = plug_shm_init(&ctl->shm_ctx, plug->tplg_file, "ctx", 0); + if (err < 0) + goto error; + + // TODO: make this open/close per operation for shared access + /* create a SHM mapping for low latency stream position */ + err = plug_shm_open(&ctl->shm_ctx); + if (err < 0) + goto error; + + /* get global context for kcontrol lookup */ + ctl->glb = ctl->shm_ctx.addr; + + /* TODO: add some flavour to the names based on the topology */ + ctl->ext.version = SND_CTL_EXT_VERSION; + ctl->ext.card_idx = 0; + strncpy(ctl->ext.id, "sof", sizeof(ctl->ext.id) - 1); + strncpy(ctl->ext.driver, "SOF plugin", + sizeof(ctl->ext.driver) - 1); + strncpy(ctl->ext.name, "SOF", sizeof(ctl->ext.name) - 1); + strncpy(ctl->ext.mixername, "SOF", + sizeof(ctl->ext.mixername) - 1); + + ctl->ext.callback = &sof_ext_callback; + ctl->ext.private_data = ctl; + ctl->ext.tlv.c = plug_tlv_rw; + + err = snd_ctl_ext_create(&ctl->ext, name, mode); + if (err < 0) + goto error; + + *handlep = ctl->ext.handle; + + return 0; + +error: + free(ctl); + + return err; +} + +SND_CTL_PLUGIN_SYMBOL(sof); diff --git a/tools/plugin/alsaplug/pcm.c b/tools/plugin/alsaplug/pcm.c new file mode 100644 index 000000000000..ed5224c829b5 --- /dev/null +++ b/tools/plugin/alsaplug/pcm.c @@ -0,0 +1,1000 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <math.h> + +#include <alsa/asoundlib.h> +#include <alsa/pcm_external.h> + +#include <rtos/sof.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component.h> +#include <ipc/stream.h> +#include <tplg_parser/topology.h> + +#include "plugin.h" +#include "common.h" + +typedef struct snd_sof_pcm { + snd_pcm_ioplug_t io; + size_t frame_size; + struct timespec wait_timeout; + int capture; + int events; + + /* PCM flow control */ + struct plug_sem_desc ready[TPLG_MAX_PCM_PIPELINES]; + struct plug_sem_desc done[TPLG_MAX_PCM_PIPELINES]; + + struct plug_shm_desc shm_pcm; + + int frame_us; +} snd_sof_pcm_t; + +static int plug_pipeline_set_state(snd_sof_plug_t *plug, int state, + struct ipc4_pipeline_set_state *pipe_state, + struct tplg_pipeline_info *pipe_info, + struct plug_socket_desc *ipc) +{ + struct ipc4_message_reply reply = {{ 0 }}; + int ret; + + pipe_state->primary.r.ppl_id = pipe_info->instance_id; + + ret = plug_ipc_cmd_tx_rx(ipc, pipe_state, sizeof(*pipe_state), + &reply, sizeof(reply)); + if (ret < 0) + SNDERR("failed pipeline %d set state %d\n", pipe_info->instance_id, state); + + return ret; +} + +static int plug_pipelines_set_state(snd_sof_plug_t *plug, int state) +{ + snd_sof_pcm_t *pcm = plug->module_prv; + struct ipc4_pipeline_set_state pipe_state = {{ 0 }}; + struct tplg_pipeline_list *pipeline_list; + int i; + + if (pcm->capture) + pipeline_list = &plug->pcm_info->capture_pipeline_list; + else + pipeline_list = &plug->pcm_info->playback_pipeline_list; + + pipe_state.primary.r.ppl_state = state; + pipe_state.primary.r.type = SOF_IPC4_GLB_SET_PIPELINE_STATE; + pipe_state.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + pipe_state.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + + /* + * pipeline list is populated starting from the host to DAI. So traverse the list in + * the reverse order for capture to start the source pipeline first. + */ + if (pcm->capture) { + for (i = pipeline_list->count - 1; i >= 0; i--) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + int ret; + + ret = plug_pipeline_set_state(plug, state, &pipe_state, pipe_info, + &plug->ipc); + if (ret < 0) + return ret; + } + + return 0; + } + + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + int ret; + + ret = plug_pipeline_set_state(plug, state, &pipe_state, pipe_info, + &plug->ipc); + if (ret < 0) + return ret; + } + + return 0; +} + +static int plug_pcm_start(snd_pcm_ioplug_t *io) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + int err; + + switch (ctx->state) { + case SOF_PLUGIN_STATE_READY: + err = plug_pipelines_set_state(plug, SOF_IPC4_PIPELINE_STATE_RUNNING); + if (err < 0) + return err; + break; + case SOF_PLUGIN_STATE_STREAM_RUNNING: + { + struct tplg_pipeline_list *pipeline_list; + int i, delay; + + if (!pcm->capture) + break; + + pipeline_list = &plug->pcm_info->capture_pipeline_list; + + /* start the first period copy for capture */ + for (i = pipeline_list->count - 1; i >= 0; i--) { + sem_post(pcm->ready[i].sem); + + /* wait for sof-pipe reader to consume data or timeout */ + err = clock_gettime(CLOCK_REALTIME, &pcm->wait_timeout); + if (err == -1) { + SNDERR("write: cant get time: %s", strerror(errno)); + return -EPIPE; + } + + /* work out delay TODO: fix ALSA reader */ + delay = pcm->frame_us * io->period_size / 500; + plug_timespec_add_ms(&pcm->wait_timeout, delay); + + /* wait for sof-pipe writer to produce data or timeout */ + err = sem_timedwait(pcm->done[i].sem, &pcm->wait_timeout); + if (err == -1) { + SNDERR("read: waited %d ms for %ld frames fatal timeout: %s", + delay, io->period_size, strerror(errno)); + return -errno; + } + } + } + break; + case SOF_PLUGIN_STATE_INIT: + case SOF_PLUGIN_STATE_STREAM_ERROR: + case SOF_PLUGIN_STATE_DEAD: + default: + /* some error */ + SNDERR("pcm start: invalid pipe state: %d", ctx->state); + return -EINVAL; + } + + return 0; +} + +static int plug_pcm_stop(snd_pcm_ioplug_t *io) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + int err; + + printf("%s %d state %ld\n", __func__, __LINE__, ctx->state); + switch (ctx->state) { + case SOF_PLUGIN_STATE_STREAM_ERROR: + case SOF_PLUGIN_STATE_STREAM_RUNNING: + { + err = plug_pipelines_set_state(plug, SOF_IPC4_PIPELINE_STATE_PAUSED); + if (err < 0) + return err; + break; + } + case SOF_PLUGIN_STATE_READY: + /* already stopped */ + break; + case SOF_PLUGIN_STATE_INIT: + case SOF_PLUGIN_STATE_DEAD: + default: + /* some error */ + SNDERR("pcm stop: invalid pipe state: %d", ctx->state); + return -EINVAL; + } + + return 0; +} + +/* buffer position up to buffer_size */ +static snd_pcm_sframes_t plug_pcm_pointer(snd_pcm_ioplug_t *io) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + snd_pcm_sframes_t ptr = 0; + int err; + + if (io->state == SND_PCM_STATE_XRUN) + return -EPIPE; + + if (io->state != SND_PCM_STATE_RUNNING) + return 0; + + switch (ctx->state) { + case SOF_PLUGIN_STATE_STREAM_RUNNING: + case SOF_PLUGIN_STATE_STREAM_ERROR: + if (pcm->capture) + ptr = ctx->wtotal / pcm->frame_size; + else + ptr = ctx->rtotal / pcm->frame_size; + break; + case SOF_PLUGIN_STATE_READY: + /* not running */ + return 0; + case SOF_PLUGIN_STATE_INIT: + case SOF_PLUGIN_STATE_DEAD: + default: + /* some error */ + SNDERR("pointer: invalid pipe state: %d", ctx->state); + ptr = -EPIPE; + } + + return ptr; +} + +/* get the delay for the running PCM; optional; since v1.0.1 */ +static int plug_pcm_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + int err = 0; + + switch (ctx->state) { + case SOF_PLUGIN_STATE_STREAM_RUNNING: + case SOF_PLUGIN_STATE_READY: + // TODO: is capture delay correct here ??? + if (pcm->capture) + *delayp = (ctx->wtotal - ctx->rtotal) / pcm->frame_size; + else + *delayp = (ctx->rtotal - ctx->wtotal) / pcm->frame_size; + /* sanitize delay */ + if (*delayp < pcm->io.period_size || *delayp > io->buffer_size) + *delayp = pcm->io.period_size; + return 0; + case SOF_PLUGIN_STATE_STREAM_ERROR: + snd_pcm_ioplug_set_state(io, SND_PCM_STATE_XRUN); + return 0; + case SOF_PLUGIN_STATE_INIT: + case SOF_PLUGIN_STATE_DEAD: + default: + /* some error */ + SNDERR("delay: invalid pipe state: %d", ctx->state); + return -EPIPE; + } +} + +/* return frames written */ +static snd_pcm_sframes_t plug_pcm_write(snd_pcm_ioplug_t *io, const snd_pcm_channel_area_t *areas, + snd_pcm_uframes_t offset, snd_pcm_uframes_t size) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + struct tplg_pipeline_list *pipeline_list; + snd_pcm_sframes_t frames = 0; + int i; + ssize_t bytes; + const char *buf; + int err, delay; + + pipeline_list = &plug->pcm_info->playback_pipeline_list; + + /* calculate the buffer position and size from application */ + buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8; + bytes = size * pcm->frame_size; + + /* now check what the pipe has free */ + bytes = MIN(plug_ep_get_free(ctx), bytes); + + frames = bytes / pcm->frame_size; + + if (frames == 0) + return frames; + + /* write audio data to the pipe */ + memcpy(plug_ep_wptr(ctx), buf, bytes); + + plug_ep_produce(ctx, bytes); + + /* tell the pipelines data is ready starting at the source pipeline */ + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + sem_post(pcm->ready[i].sem); + + /* wait for sof-pipe reader to consume data or timeout */ + err = clock_gettime(CLOCK_REALTIME, &pcm->wait_timeout); + if (err == -1) { + SNDERR("write: cant get time: %s", strerror(errno)); + return -EPIPE; + } + + /* work out delay */ + delay = pcm->frame_us * frames / 500; + plug_timespec_add_ms(&pcm->wait_timeout, delay); + + /* now block caller on pipeline IO to PCM device */ + err = sem_timedwait(pcm->done[i].sem, &pcm->wait_timeout); + if (err == -1) { + SNDERR("write: waited %d ms for %ld frames, fatal timeout: %s", + delay, frames, strerror(errno)); + return -errno; + } + } + + return frames; +} + +/* return frames read */ +static snd_pcm_sframes_t plug_pcm_read(snd_pcm_ioplug_t *io, const snd_pcm_channel_area_t *areas, + snd_pcm_uframes_t offset, snd_pcm_uframes_t size) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + snd_pcm_sframes_t frames; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + struct tplg_pipeline_list *pipeline_list; + ssize_t bytes; + char *buf; + int err, delay, i; + + pipeline_list = &plug->pcm_info->capture_pipeline_list; + + /* calculate the buffer position and size */ + buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8; + bytes = size * pcm->frame_size; + + /* check what the pipe has avail */ + bytes = MIN(plug_ep_get_avail(ctx), bytes); + frames = bytes / pcm->frame_size; + + if (!frames) + return 0; + + /* tell the pipe ready we are ready for next period */ + for (i = pipeline_list->count - 1; i >= 0; i--) { + sem_post(pcm->ready[i].sem); + + /* wait for sof-pipe reader to consume data or timeout */ + err = clock_gettime(CLOCK_REALTIME, &pcm->wait_timeout); + if (err == -1) { + SNDERR("write: cant get time: %s", strerror(errno)); + return -EPIPE; + } + + /* work out delay TODO: fix ALSA reader */ + delay = pcm->frame_us * frames / 500; + plug_timespec_add_ms(&pcm->wait_timeout, delay); + + /* wait for sof-pipe writer to produce data or timeout */ + err = sem_timedwait(pcm->done[i].sem, &pcm->wait_timeout); + if (err == -1) { + SNDERR("read: waited %d ms for %ld frames fatal timeout: %s", + delay, frames, strerror(errno)); + return -errno; + } + } + + /* copy audio data from pipe */ + memcpy(buf, plug_ep_rptr(ctx), bytes); + plug_ep_consume(ctx, bytes); + + return frames; +} + +static int plug_pcm_prepare(snd_pcm_ioplug_t *io) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + int err = 0; + + ctx->wtotal = 0; + ctx->rtotal = 0; + ctx->rpos = 0; + ctx->rwrap = 0; + ctx->wpos = 0; + ctx->wwrap = 0; + + /* start the pipeline threads + * + * We do this during prepare so that pipelines can consume/produce + * any start threshold worth of data with the pipeline in a running + * state + */ + switch (ctx->state) { + case SOF_PLUGIN_STATE_INIT: + /* set pipelines to PAUSED state to prepare them */ + err = plug_pipelines_set_state(plug, SOF_IPC4_PIPELINE_STATE_PAUSED); + if (err < 0) + return err; + + fprintf(stdout, "pipelines complete now\n"); + + /* set pipelines to RUNNING state */ + err = plug_pipelines_set_state(plug, SOF_IPC4_PIPELINE_STATE_RUNNING); + if (err < 0) + return err; + break; + case SOF_PLUGIN_STATE_STREAM_ERROR: + case SOF_PLUGIN_STATE_DEAD: + /* some error */ + SNDERR("write: invalid pipe state: %d", ctx->state); + return -EINVAL; + case SOF_PLUGIN_STATE_READY: + case SOF_PLUGIN_STATE_STREAM_RUNNING: + default: + /* do nothing */ + break; + } + + fprintf(stdout, "PCM prepare done\n"); + + return err; +} + +static int plug_init_shm_ctx(snd_sof_plug_t *plug, snd_pcm_hw_params_t *params); + +static int plug_pcm_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_endpoint *ctx; + struct tplg_pipeline_list *pipeline_list; + int i, err; + + pcm->frame_size = (snd_pcm_format_physical_width(io->format) * io->channels) / 8; + + plug->period_size = io->period_size; + + /* used for wait timeouts */ + pcm->frame_us = ceil(1000000.0 / io->rate); + + /* now send IPCs to set up widgets */ + err = plug_set_up_pipelines(plug, pcm->capture, params); + if (err < 0) { + fprintf(stderr, "error setting up pipelines\n"); + return err; + } + + if (pcm->capture) + pipeline_list = &plug->pcm_info->capture_pipeline_list; + else + pipeline_list = &plug->pcm_info->playback_pipeline_list; + + /* init and open for PCM ready lock for all pipelines */ + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + /* init name for pipeline ready lock */ + err = plug_lock_init(&pcm->ready[i], plug->tplg_file, "ready", + pipe_info->instance_id); + if (err < 0) { + SNDERR("error: invalid name for PCM ready lock %s\n", + pipe_info->instance_id); + return err; + } + + /* init name for pipeline done lock */ + err = plug_lock_init(&pcm->done[i], plug->tplg_file, "done", + pipe_info->instance_id); + if (err < 0) { + SNDERR("error: invalid name for PCM done lock %s\n", + pipe_info->instance_id); + return err; + } + + /* open lock "ready" for pipeline audio data */ + err = plug_lock_open(&pcm->ready[i]); + if (err < 0) { + SNDERR("error: failed to open sof-pipe ready lock %s: %s", + pcm->ready[i].name, strerror(err)); + return -errno; + } + + /* open lock "done" for pipeline audio data */ + err = plug_lock_open(&pcm->done[i]); + if (err < 0) { + SNDERR("error: failed to open sof-pipe done lock %s: %s", + pcm->done[i].name, strerror(err)); + return -errno; + } + } + + /* init PCM shm name */ + err = plug_shm_init(&pcm->shm_pcm, plug->tplg_file, "pcm", plug->pcm_id); + if (err < 0) { + SNDERR("error: invalid name for PCM SHM %s\n", plug->tplg_file); + return err; + } + + /* open audio PCM SHM data endpoint */ + err = plug_shm_open(&pcm->shm_pcm); + if (err < 0) { + SNDERR("error: failed to open sof-pipe PCM SHM %s: %s", + pcm->shm_pcm.name, strerror(err)); + return -errno; + } + + /* set up the endpoint configs */ + err = plug_init_shm_ctx(plug, params); + if (err < 0) { + SNDERR("error: failed to init sof-pipe ep context: %s:%s", + pcm->shm_pcm.name, strerror(err)); + return -err; + } + + ctx = pcm->shm_pcm.addr; + ctx->frame_size = pcm->frame_size; + + /* needs to be set here and NOT in SW params as SW params not + * called in capture flow ? + */ + ctx->buffer_size = io->buffer_size * ctx->frame_size; + + if (!ctx->buffer_size) { + SNDERR("Invalid buffer_size io buffer_size %d ctx->frame_size %d\n", + io->buffer_size, ctx->frame_size); + return -EINVAL; + } + + fprintf(stdout, "PCM hw_params done\n"); + + return 0; +} + +// TODO: why not called for arecord +static int plug_pcm_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + snd_pcm_uframes_t start_threshold; + struct plug_shm_endpoint *ctx = pcm->shm_pcm.addr; + int err; + + /* get the stream start threshold */ + err = snd_pcm_sw_params_get_start_threshold(params, &start_threshold); + if (err < 0) { + SNDERR("sw params: failed to get start threshold: %s", strerror(err)); + return err; + } + + /* TODO: this seems to be ignored or overridden by application params ??? */ + if (start_threshold < io->period_size) { + start_threshold = io->period_size; + err = snd_pcm_sw_params_set_start_threshold(pcm->io.pcm, + params, start_threshold); + if (err < 0) { + SNDERR("sw params: failed to set start threshold %d: %s", + start_threshold, strerror(err)); + return err; + } + } + + /* keep running as long as we can */ + err = snd_pcm_sw_params_set_avail_min(pcm->io.pcm, params, 1); + if (err < 0) { + SNDERR("sw params: failed to set avail min %d: %s", 1, strerror(err)); + return err; + } + + fprintf(stdout, "sw_params done\n"); + + return 0; +} + +static int plug_pcm_close(snd_pcm_ioplug_t *io) +{ + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_glb_state *ctx = plug->glb_ctx.addr; + int err = 0; + + printf("%s %d\n", __func__, __LINE__); + + ctx->state = SOF_PLUGIN_STATE_INIT; + + plug_free_topology(plug); + + free(plug->tplg_file); + free(plug->module_prv); + free(plug); + + return err; +} + +static int plug_pcm_hw_free(snd_pcm_ioplug_t *io) +{ + struct tplg_pipeline_list *pipeline_list; + snd_sof_plug_t *plug = io->private_data; + snd_sof_pcm_t *pcm = plug->module_prv; + int ret, i; + + /* reset all pipelines */ + ret = plug_pipelines_set_state(plug, SOF_IPC4_PIPELINE_STATE_RESET); + if (ret < 0) { + fprintf(stderr, "failed to reset pipelines\n"); + return ret; + } + + if (pcm->capture) + pipeline_list = &plug->pcm_info->capture_pipeline_list; + else + pipeline_list = &plug->pcm_info->playback_pipeline_list; + + ret = plug_free_pipelines(plug, pipeline_list, pcm->capture); + + close(pcm->shm_pcm.fd); + close(plug->glb_ctx.fd); + + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + sem_close(pcm->ready[pipe_info->instance_id].sem); + sem_close(pcm->done[pipe_info->instance_id].sem); + } + close(plug->ipc.socket_fd); + + return 0; +} + +static const snd_pcm_ioplug_callback_t sof_playback_callback = { + .start = plug_pcm_start, + .stop = plug_pcm_stop, + .pointer = plug_pcm_pointer, + .transfer = plug_pcm_write, + .delay = plug_pcm_delay, + .prepare = plug_pcm_prepare, + .hw_params = plug_pcm_hw_params, + .hw_free = plug_pcm_hw_free, + .sw_params = plug_pcm_sw_params, + .close = plug_pcm_close, +}; + +static const snd_pcm_ioplug_callback_t sof_capture_callback = { + .start = plug_pcm_start, + .stop = plug_pcm_stop, + .pointer = plug_pcm_pointer, + .transfer = plug_pcm_read, + .delay = plug_pcm_delay, + .prepare = plug_pcm_prepare, + .hw_params = plug_pcm_hw_params, + .sw_params = plug_pcm_sw_params, + .hw_free = plug_pcm_hw_free, + .close = plug_pcm_close, +}; + +static const snd_pcm_access_t access_list[] = { + SND_PCM_ACCESS_RW_INTERLEAVED +}; + +static const unsigned int formats[] = { + SND_PCM_FORMAT_S16_LE, + SND_PCM_FORMAT_FLOAT_LE, + SND_PCM_FORMAT_S32_LE, + SND_PCM_FORMAT_S24_LE, +}; + +/* + * Set HW constraints for the SOF plugin. This needs to be quite unrestrictive atm + * as we really need to parse topology before the HW constraints can be narrowed + * to a range that will work with the specified pipeline. + * TODO: Align with topology. + */ +static int plug_hw_constraint(snd_sof_plug_t *plug) +{ + snd_sof_pcm_t *pcm = plug->module_prv; + snd_pcm_ioplug_t *io = &pcm->io; + int err; + + err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, + ARRAY_SIZE(access_list), + access_list); + if (err < 0) { + SNDERR("constraints: failed to set access: %s", strerror(err)); + return err; + } + + err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, + ARRAY_SIZE(formats), formats); + if (err < 0) { + SNDERR("constraints: failed to set format: %s", strerror(err)); + return err; + } + + err = + snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, + 1, 8); + if (err < 0) { + SNDERR("constraints: failed to set channels: %s", strerror(err)); + return err; + } + + err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, + 1, 192000); + if (err < 0) { + SNDERR("constraints: failed to set rate: %s", strerror(err)); + return err; + } + + err = + snd_pcm_ioplug_set_param_minmax(io, + SND_PCM_IOPLUG_HW_BUFFER_BYTES, + 1, 4 * 1024 * 1024); + if (err < 0) { + SNDERR("constraints: failed to set buffer bytes: %s", strerror(err)); + return err; + } + + err = + snd_pcm_ioplug_set_param_minmax(io, + SND_PCM_IOPLUG_HW_PERIOD_BYTES, + 128, 2 * 1024 * 1024); + if (err < 0) { + SNDERR("constraints: failed to set period bytes: %s", strerror(err)); + return err; + } + + err = + snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 1, 4); + if (err < 0) { + SNDERR("constraints: failed to set period count: %s", strerror(err)); + return err; + } + + return 0; +} + +/* + * Register the plugin with ALSA and make available for use. + * TODO: setup all audio params + * TODO: setup polling fd for RW or mmap IOs + */ +static int plug_create(snd_sof_plug_t *plug, snd_pcm_t **pcmp, const char *name, + snd_pcm_stream_t stream, int mode) +{ + snd_sof_pcm_t *pcm = plug->module_prv; + int err; + + pcm->io.version = SND_PCM_IOPLUG_VERSION; + pcm->io.name = "ALSA <-> SOF PCM I/O Plugin"; + pcm->io.poll_fd = pcm->shm_pcm.fd; + pcm->io.poll_events = POLLIN; + pcm->io.mmap_rw = 0; + + if (stream == SND_PCM_STREAM_PLAYBACK) + pcm->io.callback = &sof_playback_callback; + else + pcm->io.callback = &sof_capture_callback; + + pcm->io.private_data = plug; + + /* create the plugin */ + err = snd_pcm_ioplug_create(&pcm->io, name, stream, mode); + if (err < 0) { + SNDERR("failed to register plugin %s: %s\n", name, strerror(err)); + return err; + } + + /* set the HW constrainst */ + err = plug_hw_constraint(plug); + if (err < 0) { + snd_pcm_ioplug_delete(&pcm->io); + return err; + } + + *pcmp = pcm->io.pcm; + return 0; +} + +static int plug_init_shm_ctx(snd_sof_plug_t *plug, snd_pcm_hw_params_t *params) +{ + struct plug_shm_glb_state *glb = plug->glb_ctx.addr; + struct endpoint_hw_config *ep; + struct plug_cmdline_item *ci; + struct plug_config *pc; + int i, j; + + glb->num_ep_configs = 0; + + for (i = 0; i < plug->num_cmdline; i++) { + bool found = false; + + if (glb->num_ep_configs >= NUM_EP_CONFIGS - 1) { + SNDERR("error: too many endpoint configs\n"); + return -EINVAL; + } + + ci = &plug->cmdline[i]; + + for (j = 0; j < plug->num_configs; j++) { + pc = &plug->config[j]; + if (strcmp(pc->name, ci->config_name)) + continue; + + ep = &glb->ep_config[glb->num_ep_configs++]; + ep->buffer_frames = pc->buffer_frames; + ep->buffer_time = pc->buffer_time; + ep->channels = pc->channels; + ep->format = pc->format; + ep->period_frames = pc->period_frames; + ep->period_time = pc->period_time; + ep->rate = pc->rate; + strncpy(ep->config_name, ci->config_name, sizeof(ep->config_name)); + found = true; + break; + } + + /* use hw_params if no matching config found or config missing in command line */ + if (!found) { + unsigned int channels, rate, dir, buffer_time, period_time; + snd_pcm_uframes_t buffer_size, period_size; + snd_pcm_format_t format; + + snd_pcm_hw_params_get_channels(params, &channels); + snd_pcm_hw_params_get_rate(params, &rate, &dir); + snd_pcm_hw_params_get_buffer_size(params, &buffer_size); + snd_pcm_hw_params_get_period_size(params, &period_size, &dir); + snd_pcm_hw_params_get_buffer_time(params, &buffer_time, &dir); + snd_pcm_hw_params_get_period_time(params, &period_time, &dir); + snd_pcm_hw_params_get_format(params, &format); + + ep = &glb->ep_config[glb->num_ep_configs++]; + ep->buffer_frames = buffer_size; + ep->buffer_time = buffer_time; + ep->channels = channels; + ep->format = format; + ep->period_frames = period_size; + ep->period_time = period_time; + ep->rate = rate; + } + + ep->pipeline = ci->pcm; + strncpy(ep->card_name, ci->card_name, sizeof(ep->card_name)); + strncpy(ep->dev_name, ci->dev_name, sizeof(ep->dev_name)); + } + + return 0; +} + +/* + * Complete parent initialisation. + * 1. Check if pipe already ready by opening SHM context and IPC. + * 2. TODO: check context state and load topology is needed for core. + */ +static int plug_init_sof_pipe(snd_sof_plug_t *plug, snd_pcm_t **pcmp, + const char *name, snd_pcm_stream_t stream, int mode) +{ + snd_sof_pcm_t *pcm = plug->module_prv; + struct plug_shm_glb_state *ctx; + struct timespec delay; + int err, i; + + /* initialize widget, route and pcm lists */ + list_init(&plug->widget_list); + list_init(&plug->route_list); + list_init(&plug->pcm_list); + + plug->tplg.tplg_file = plug->tplg_file; + + /* plugin only works with IPC4 */ + plug->tplg.ipc_major = 4; + + /* init global status hsm name */ + err = plug_shm_init(&plug->glb_ctx, plug->tplg_file, "ctx", 0); + if (err < 0) { + SNDERR("error: invalid name for global SHM %s\n", plug->tplg_file); + return err; + } + + /* open the global context via SHM */ + plug->glb_ctx.size = 128 * 1024; + err = plug_shm_open(&plug->glb_ctx); + if (err < 0) { + SNDERR("error: failed to open plugin context: %s:%s", + plug->glb_ctx.name, strerror(err)); + return err; + } + + /* parse topology file */ + err = plug_parse_topology(plug); + if (err < 0) { + fprintf(stderr, "error parsing topology %s\n", plug->tplg.tplg_file); + return err; + } + + fprintf(stdout, "topology parsing complete\n"); + + /* init IPC message queue name */ + err = plug_socket_path_init(&plug->ipc, "sof", "ipc", 0); + if (err < 0) { + SNDERR("error: invalid name for IPC socket %s\n", plug->tplg_file); + return err; + } + + err = plug_create_client_socket(&plug->ipc); + if (err < 0) { + SNDERR("failed to connect to SOF pipe IPC socket : %s", strerror(err)); + return -errno; + } + + /* now register the plugin */ + err = plug_create(plug, pcmp, name, stream, mode); + if (err < 0) { + SNDERR("failed to create plugin: %s", strerror(err)); + return -errno; + } + + return 0; +} + +/* + * ALSA PCM plugin entry point. + */ +SND_PCM_PLUGIN_DEFINE_FUNC(sof) +{ + snd_sof_plug_t *plug; + snd_sof_pcm_t *pcm; + int err; + + fprintf(stdout, "This code is WIP. Cmd args & config will possible change over time\n"); + fprintf(stdout, "\nThe 50-sonf.conf file is parsed for PCM configurations which can\n"); + fprintf(stdout, "be mapped on the cmd line to pipeline endpoints.\n"); + fprintf(stdout, "\ni.e. aplay -Dsof:<topology>:<pcm id><card>:<device>:<config> file.wav\n"); + fprintf(stdout, "\nwhich can be used as\n"); + fprintf(stdout, "\ne.g. aplay -Dsof:bdw-nocodec:1:default:default:48k2c16b -f dat ~/audiodump.wav\n\n"); + + /* create context */ + plug = calloc(1, sizeof(*plug)); + if (!plug) + return -ENOMEM; + + pcm = calloc(1, sizeof(*pcm)); + if (!pcm) { + free(plug); + return -ENOMEM; + } + plug->module_prv = pcm; + + if (stream == SND_PCM_STREAM_CAPTURE) + pcm->capture = 1; + + /* parse the ALSA configuration file for sof plugin */ + err = plug_parse_conf(plug, name, root, conf, false); + if (err < 0) { + SNDERR("failed to parse config: %s", strerror(err)); + goto parse_conf_err; + } + + /* now try and connect to the sof-pipe for this topology */ + err = plug_init_sof_pipe(plug, pcmp, name, stream, mode); + if (err < 0) { + SNDERR("failed to complete plugin init: %s", strerror(err)); + goto pipe_error; + } + + /* everything is good */ + return 0; + +pipe_error: + free(plug->tplg_file); +parse_conf_err: + free(plug->module_prv); +dev_error: + free(plug); + return err; +} + +SND_PCM_PLUGIN_SYMBOL(sof); diff --git a/tools/plugin/alsaplug/plugin.c b/tools/plugin/alsaplug/plugin.c new file mode 100644 index 000000000000..52bbdcfc70e1 --- /dev/null +++ b/tools/plugin/alsaplug/plugin.c @@ -0,0 +1,361 @@ +/*-*- linux-c -*-*/ + +/* + * ALSA <-> SOF PCM I/O plugin + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stddef.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <alsa/asoundlib.h> +#include <alsa/pcm_external.h> + +#include "plugin.h" +#include "common.h" + +/* + * Open an existing semaphore using lock object. + */ +int plug_lock_open(struct plug_sem_desc *lock) +{ + lock->sem = sem_open(lock->name, O_RDWR); + if (lock->sem == SEM_FAILED) { + SNDERR("failed to open semaphore %s: %s\n", lock->name, strerror(errno)); + return -errno; + } + + return 0; +} + +#define itemsize(type, member) sizeof(((type *)0)->member) + +static int parse_conf_long(snd_config_t *cfg, void *obj, size_t size) +{ + long val; + + if (snd_config_get_integer(cfg, &val) < 0) + return -EINVAL; + + *((long *)obj) = val; + return 0; +} + +static int parse_conf_str(snd_config_t *cfg, void *obj, size_t size) +{ + const char *id; + + if (snd_config_get_id(cfg, &id) < 0) + return -EINVAL; + strncpy(obj, id, size); + + return 0; +} + +static int parse_conf_format(snd_config_t *cfg, void *obj, size_t size) +{ + const char *id; + + if (snd_config_get_string(cfg, &id) < 0) + return -EINVAL; + + if (!strcmp("S16_LE", id)) { + *((long *)obj) = SND_PCM_FORMAT_S16_LE; + return 0; + } + if (!strcmp("S32_LE", id)) { + *((long *)obj) = SND_PCM_FORMAT_S32_LE; + return 0; + } + if (!strcmp("S24_4LE", id)) { + *((long *)obj) = SND_PCM_FORMAT_S24_LE; + return 0; + } + if (!strcmp("FLOAT", id)) { + *((long *)obj) = SND_PCM_FORMAT_FLOAT_LE; + return 0; + } + + /* not found */ + SNDERR("error: cant find format: %s", id); + return -EINVAL; +} + +struct config_item { + char *name; + size_t size; + size_t offset; + int (*copy)(snd_config_t *cfg, void *obj, size_t size); +}; + +struct config_item config_items[] = { + {"name", itemsize(struct plug_config, name), + offsetof(struct plug_config, name), parse_conf_str}, + {"rate", itemsize(struct plug_config, rate), + offsetof(struct plug_config, rate), parse_conf_long}, + {"format", itemsize(struct plug_config, format), + offsetof(struct plug_config, format), parse_conf_format}, + {"channels", itemsize(struct plug_config, channels), + offsetof(struct plug_config, channels), parse_conf_long}, + {"period_time", itemsize(struct plug_config, period_time), + offsetof(struct plug_config, period_time), parse_conf_long}, + {"period_frames", itemsize(struct plug_config, period_frames), + offsetof(struct plug_config, period_frames), parse_conf_long}, + {"buffer_time", itemsize(struct plug_config, buffer_time), + offsetof(struct plug_config, buffer_time), parse_conf_long}, + {"buffer_frames", itemsize(struct plug_config, buffer_frames), + offsetof(struct plug_config, buffer_frames), parse_conf_long}, +}; + +static int parse_item(snd_config_t *cfg, const char *id, struct plug_config *dest_cfg) +{ + void *dest = dest_cfg; + int i; + + for (i = 0; i < ARRAY_SIZE(config_items); i++) { + /* does ID match */ + if (strcmp(id, config_items[i].name)) + continue; + + /* now get the value */ + return config_items[i].copy(cfg, dest + config_items[i].offset, + config_items[i].size); + } + + /* not found - non fatal */ + return 0; +} + +static int parse_slave_configs(snd_sof_plug_t *plug, snd_config_t *n) +{ + snd_config_iterator_t si1, si2, snext1, snext2; + struct plug_config *config; + const char *id; + + fprintf(stdout, "Parsing ALSA conf for configs\n"); + + snd_config_for_each(si1, snext1, n) { + snd_config_t *sn1 = snd_config_iterator_entry(si1); + + config = &plug->config[plug->num_configs]; + + /* get config name */ + if (parse_item(sn1, "name", config) < 0) { + SNDERR("error: cant find config name"); + return -EINVAL; + } + + /* now get item values in each config */ + snd_config_for_each(si2, snext2, sn1) { + snd_config_t *sn2 = snd_config_iterator_entry(si2); + + if (snd_config_get_id(sn2, &id) < 0) + continue; + + if (parse_item(sn2, id, config) < 0) { + SNDERR("error: malformed config: %s", id); + return -EINVAL; + } + } + + fprintf(stdout, " config %d: %s\n", plug->num_configs, + config->name); + + /* next config */ + plug->num_configs++; + if (plug->num_configs >= PLUG_MAX_CONFIG) { + SNDERR("error: too many configs"); + return -EINVAL; + } + } + + return 0; +} + +/* + * Parse the client cmdline. Format is + * tplg:pcm:card:dev:config[dai_pipe:card:dev:config]...] + */ +static int parse_client_cmdline(snd_sof_plug_t *plug, char *cmdline, bool just_tplg) +{ + struct plug_cmdline_item *cmd_item; + char *tplg, *next, *card, *dev, *config, *pcm; + char *tplg_path = getenv("SOF_PLUGIN_TOPOLOGY_PATH"); + char tplg_file[128]; + int ret; + int i; + + if (!tplg_path) { + SNDERR("Invalid topology path. Please set the SOF_PLUGIN_TOPOLOGY_PATH env variable\n"); + return -EINVAL; + } + + /* get topology file */ + tplg = strtok_r(cmdline, ":", &next); + if (!tplg) { + SNDERR("invalid cmdline, cant find topology %s", cmdline); + return -EINVAL; + } + + /* now convert to filename and add the topology path */ + ret = snprintf(tplg_file, sizeof(tplg_file), "%ssof-%s.tplg", tplg_path, tplg); + if (ret < 0) { + SNDERR("invalid cmdline topology file %s", tplg); + return -EINVAL; + } + plug->tplg_file = strdup(tplg_file); + if (!plug->tplg_file) + return -ENOMEM; + + if (just_tplg) + return 0; + + /* get PCM ID */ + pcm = strtok_r(next, ":", &next); + if (!pcm) { + SNDERR("invalid cmdline, cant find PCM %s", pcm); + return -EINVAL; + } + plug->pcm_id = atoi(pcm); + + fprintf(stdout, "Parsing cmd line\n"); + + cmd_item = &plug->cmdline[plug->num_cmdline]; + card = strtok_r(next, ":", &next); + /* card/dev names and config are all optional */ + if (!card) { + strncpy(cmd_item->card_name, "default", sizeof(cmd_item->card_name)); + strncpy(cmd_item->dev_name, "default", sizeof(cmd_item->dev_name)); + fprintf(stdout, "no config name provided, will use hw_params\n"); + } else { + strncpy(cmd_item->card_name, card, sizeof(cmd_item->card_name)); + dev = strtok_r(next, ":", &next); + /* dev name must be provided along with card name */ + if (!dev) { + SNDERR("Invalid dev name\n"); + return -EINVAL; + } + strncpy(cmd_item->dev_name, dev, sizeof(cmd_item->dev_name)); + config = strtok_r(next, ":", &next); + /* config name is optional */ + if (!config) + fprintf(stdout, "no config name provided, will use hw_params\n"); + else + strncpy(cmd_item->config_name, config, sizeof(cmd_item->config_name)); + } + + cmd_item->pcm = atoi(pcm); + + /* + * dev name is special, we cant use "," in the command line + * so need to replace it with a "." and then later change it + * back to "," + */ + for (i = 0; i < sizeof(cmd_item->dev_name); i++) { + if (cmd_item->dev_name[i] != '.') + continue; + cmd_item->dev_name[i] = ','; + break; + } + + fprintf(stdout, " cmd %d: for pcm %d uses %s with PCM %s:%s\n", + plug->num_cmdline, cmd_item->pcm, cmd_item->config_name, + cmd_item->card_name, cmd_item->dev_name); + + plug->num_cmdline++; + + printf("plug: topology file %s with pipe %ld\n", plug->tplg_file, plug->tplg_pipeline); + return 0; +} + +/* + * Parse the ALSA conf for the SOF plugin and construct the command line options + * to be passed into the SOF pipe executable. + * TODO: verify all args + * TODO: validate all args. + * TODO: contruct sof pipe cmd line. + */ +int plug_parse_conf(snd_sof_plug_t *plug, const char *name, snd_config_t *root, + snd_config_t *conf, bool just_tplg) +{ + snd_config_iterator_t i, next; + const char *tplg = NULL; + + /* + * The topology filename and topology PCM need to be passed in. + * i.e. aplay -Dsof:tplg:pcm:[card:dev:config]...] + */ + snd_config_for_each(i, next, conf) { + snd_config_t *n = snd_config_iterator_entry(i); + const char *id; + + if (snd_config_get_id(n, &id) < 0) + continue; + + /* dont care */ + if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0 || + strcmp(id, "hint") == 0) + continue; + + /* client command line topology */ + if (strcmp(id, "tplg") == 0) { + if (snd_config_get_string(n, &tplg) < 0) { + SNDERR("Invalid type for %s", id); + return -EINVAL; + } else if (!*tplg) { + tplg = NULL; + } + continue; + } + + /* topology PCM configurations */ + if (strcmp(id, "config") == 0) { + if (parse_slave_configs(plug, n)) + return -EINVAL; + continue; + } + + /* not fatal - carry on and verify later */ + SNDERR("Unknown field %s", id); + } + + /* verify mandatory inputs are specified */ + if (!tplg) { + SNDERR("Missing topology topology"); + return -EINVAL; + } + + /* parse the client command line */ + if (parse_client_cmdline(plug, (char *)tplg, just_tplg)) { + SNDERR("invalid sof cmd line"); + return -EINVAL; + } + + return 0; +} diff --git a/tools/plugin/alsaplug/plugin.h b/tools/plugin/alsaplug/plugin.h new file mode 100644 index 000000000000..7f4009267d24 --- /dev/null +++ b/tools/plugin/alsaplug/plugin.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __SOF_PLUGIN_PLUGIN_H__ +#define __SOF_PLUGIN_PLUGIN_H__ + +#include <alsa/asoundlib.h> +#include <sof/list.h> +#include "common.h" + +#include <tplg_parser/topology.h> + +#define PLUG_MAX_CONFIG 128 + +typedef struct snd_sof_plug { + /* conf data */ + char *device; + + /* topology info */ + char *tplg_file; + long tplg_pipeline; // HACK, use configs + + /* number of configurations in plugin conf */ + struct plug_config config[PLUG_MAX_CONFIG]; + int num_configs; + + /* command line arguments */ + struct plug_cmdline_item cmdline[PLUG_MAX_CONFIG]; + int num_cmdline; + + /* topology */ + struct tplg_context tplg; + struct list_item widget_list; + struct list_item route_list; + struct list_item pcm_list; + struct list_item pipeline_list; + int instance_ids[SND_SOC_TPLG_DAPM_LAST]; + struct plug_socket_desc ipc; + + struct plug_shm_desc glb_ctx; + + int pcm_id; + struct tplg_pcm_info *pcm_info; + + snd_pcm_uframes_t period_size; + + void *module_prv; /* module private data */ +} snd_sof_plug_t; + +/* + * ALSA Conf + */ +int sofplug_load_hook(snd_config_t *root, snd_config_t *config, + snd_config_t **dst, snd_config_t *private_data); + +int plug_parse_conf(snd_sof_plug_t *plug, const char *name, + snd_config_t *root, snd_config_t *conf, bool just_tplg); +int plug_parse_topology(snd_sof_plug_t *plug); +int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir, snd_pcm_hw_params_t *params); +int plug_free_pipelines(snd_sof_plug_t *plug, struct tplg_pipeline_list *pipeline_list, int dir); +void plug_free_topology(snd_sof_plug_t *plug); +int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, void *arg, int index); + +#endif diff --git a/tools/plugin/alsaplug/tplg.c b/tools/plugin/alsaplug/tplg.c new file mode 100644 index 000000000000..7b05b7ead50a --- /dev/null +++ b/tools/plugin/alsaplug/tplg.c @@ -0,0 +1,1554 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> + +/* Topology loader to set up components and pipeline */ + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <dlfcn.h> +#include <kernel/header.h> + +#include <ipc4/error_status.h> + +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +#include <alsa/asoundlib.h> +#include <alsa/control_external.h> +#include <alsa/pcm_external.h> + +#include "plugin.h" + +#define FILE_READ 0 +#define FILE_WRITE 1 + +#define MAX_TPLG_OBJECT_SIZE 4096 + +//#include <sound/asound.h> + +/* temporary - current MAXLEN is not define in UAPI header - fix pending */ +#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN +#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 +#endif +#include <alsa/sound/asoc.h> + +#define SOF_IPC4_FW_PAGE(x) ((((x) + BIT(12) - 1) & ~(BIT(12) - 1)) >> 12) +#define SOF_IPC4_FW_ROUNDUP(x) (((x) + BIT(6) - 1) & (~(BIT(6) - 1))) +#define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12 +#define SOF_IPC4_PIPELINE_OBJECT_SIZE 448 +#define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128 +#define SOF_IPC4_LL_TASK_OBJECT_SIZE 72 +#define SOF_IPC4_LL_TASK_LIST_ITEM_SIZE 12 +#define SOF_IPC4_FW_MAX_QUEUE_COUNT 8 + +static const struct sof_topology_token ipc4_comp_tokens[] = { + {SOF_TKN_COMP_IS_PAGES, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct ipc4_base_module_cfg, is_pages)}, +}; + +static int plug_parse_ipc4_comp_tokens(snd_sof_plug_t *plug, struct ipc4_base_module_cfg *base_cfg) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0]; + int size = ctx->widget->priv.size; + int ret; + + ret = sof_parse_token_sets(base_cfg, ipc4_comp_tokens, ARRAY_SIZE(ipc4_comp_tokens), + array, size, 1, 0); + if (ret < 0) + return ret; + + return sof_parse_tokens(&comp_info->uuid, comp_ext_tokens, + ARRAY_SIZE(comp_ext_tokens), array, size); +} + +static void plug_setup_widget_ipc_msg(struct tplg_comp_info *comp_info) +{ + struct ipc4_module_init_instance *module_init = &comp_info->module_init; + + module_init->primary.r.type = SOF_IPC4_MOD_INIT_INSTANCE; + module_init->primary.r.module_id = comp_info->module_id; + module_init->primary.r.instance_id = comp_info->instance_id; + module_init->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + module_init->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; +} + +static int plug_aif_in_out(snd_sof_plug_t *plug, int dir) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + /* overwrite the topology UUIDs with the SHM module UUID for the host components */ + if (dir == SOF_IPC_STREAM_PLAYBACK) { + struct sof_uuid uuid = {.a = 0xe2b6031c, .b = 0x47e8, .c = 0x11ed, + .d = { 0x07, 0xa9, 0x7f, 0x80, 0x1b, 0x6e, 0xfa, 0x6c }}; + comp_info->module_id = 0x96; + plug_setup_widget_ipc_msg(comp_info); + comp_info->uuid = uuid; + } else { + struct sof_uuid uuid = {.a = 0xdabe8814, .b = 0x47e8, .c = 0x11ed, + .d = { 0xa5, 0x8b, 0xb3, 0x09, 0x97, 0x4f, 0xec, 0xce }}; + comp_info->module_id = 0x98; + plug_setup_widget_ipc_msg(comp_info); + comp_info->uuid = uuid; + } + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), &comp_info->uuid, + sizeof(struct sof_uuid)); + + return 0; +} + +static int plug_dai_in_out(snd_sof_plug_t *plug, int dir) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + /* overwrite the topology UUIDs with the ALSA module UUID for the DAI components */ + if (dir == SOF_IPC_STREAM_PLAYBACK) { + struct sof_uuid uuid = {.a = 0x72cee996, .b = 0x39f2, .c = 0x11ed, + .d = { 0xa0, 0x8f, 0x97, 0xfc, 0xc4, 0x2e, 0xaa, 0xeb }}; + + comp_info->module_id = 0x97; + plug_setup_widget_ipc_msg(comp_info); + comp_info->uuid = uuid; + } else { + struct sof_uuid uuid = {.a = 0x66def9f0, .b = 0x39f2, .c = 0x11ed, + .d = { 0xf7, 0x89, 0xaf, 0x98, 0xa6, 0x44, 0x0c, 0xc4 }}; + + comp_info->module_id = 0x99; + plug_setup_widget_ipc_msg(comp_info); + comp_info->uuid = uuid; + } + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), &comp_info->uuid, + sizeof(struct sof_uuid)); + + return 0; +} + +static int plug_new_src_ipc(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp_src *src = + (struct sof_ipc_comp_src *)tplg_object; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + int ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + ret = tplg_new_src(ctx, &src->comp, MAX_TPLG_OBJECT_SIZE, + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + SNDERR("error: failed to create src\n"); + goto out; + } + +out: + free(tplg_ctl); + return ret; +} + +static int plug_new_asrc_ipc(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp_asrc *asrc = + (struct sof_ipc_comp_asrc *)tplg_object; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + int ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + ret = tplg_new_asrc(ctx, &asrc->comp, MAX_TPLG_OBJECT_SIZE, + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + SNDERR("error: failed to create PGA\n"); + goto out; + } + +out: + free(tplg_ctl); + return ret; +} + +static int plug_new_mixer(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp_mixer *mixer = + (struct sof_ipc_comp_mixer *)tplg_object; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + int ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + comp_info->instance_id = plug->instance_ids[SND_SOC_TPLG_DAPM_MIXER]++; + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + ret = tplg_new_mixer(ctx, &mixer->comp, MAX_TPLG_OBJECT_SIZE, + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + SNDERR("error: failed to create mixer\n"); + goto out; + } + + if (strstr(comp_info->name, "mixin")) { + comp_info->module_id = 0x2; + plug_setup_widget_ipc_msg(comp_info); + } else { + comp_info->module_id = 0x3; + plug_setup_widget_ipc_msg(comp_info); + } + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), &comp_info->uuid, + sizeof(struct sof_uuid)); +out: + free(tplg_ctl); + return ret; +} + +static int plug_new_pga(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct ipc4_peak_volume_config volume; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + uint32_t uuid_offset; + int ret; + + comp_info->ipc_size = sizeof(struct ipc4_peak_volume_config); + comp_info->ipc_size += sizeof(struct ipc4_base_module_cfg); + uuid_offset = comp_info->ipc_size; + comp_info->ipc_size += sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + /* FIXME: move this to when the widget is actually set up */ + comp_info->instance_id = plug->instance_ids[SND_SOC_TPLG_DAPM_PGA]++; + comp_info->module_id = 0x6; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) { + free(comp_info->ipc_payload); + return -ENOMEM; + } + + ret = tplg_new_pga(ctx, &volume, sizeof(struct ipc4_peak_volume_config), + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + SNDERR("%s: failed to create PGA\n", __func__); + goto out; + } + + /* copy volume data to ipc_payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), + &volume, sizeof(struct ipc4_peak_volume_config)); + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + uuid_offset, &comp_info->uuid, sizeof(struct sof_uuid)); + + /* skip kcontrols for now */ + if (tplg_create_controls(ctx, ctx->widget->num_kcontrols, + tplg_ctl, ctx->hdr->payload_size, comp_info) < 0) { + SNDERR("error: loading controls\n"); + goto out; + } + + plug_setup_widget_ipc_msg(comp_info); + + free(tplg_ctl); + + return ret; + +out: + free(tplg_ctl); + free(comp_info->ipc_payload); + + return ret; +} + +static int plug_new_process(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct ipc4_base_module_cfg basecfg; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + /* only base config supported for now. extn support will be added later */ + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + /* FIXME: move this to when the widget is actually set up */ + comp_info->instance_id = plug->instance_ids[SND_SOC_TPLG_DAPM_EFFECT]++; + comp_info->module_id = 0x95; + + plug_setup_widget_ipc_msg(comp_info); + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) { + free(comp_info->ipc_payload); + return -ENOMEM; + } + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), &comp_info->uuid, + sizeof(struct sof_uuid)); + + /* set up kcontrols */ + ret = tplg_create_controls(ctx, ctx->widget->num_kcontrols, + tplg_ctl, ctx->hdr->payload_size, comp_info); + if (ret < 0) { + SNDERR("failed to create controls for process comp\n"); + free(comp_info->ipc_payload); + } + + free(tplg_ctl); + return ret; +} + +static int plug_new_pipeline(snd_sof_plug_t *plug) +{ + struct tplg_pipeline_info *pipe_info; + struct sof_ipc_pipe_new pipeline = {0}; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + struct tplg_context *ctx = &plug->tplg; + int ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + pipe_info = calloc(sizeof(struct tplg_pipeline_info), 1); + if (!pipe_info) { + ret = -ENOMEM; + goto out; + } + + pipe_info->name = strdup(ctx->widget->name); + if (!pipe_info->name) { + free(pipe_info); + goto out; + } + + pipe_info->id = ctx->pipeline_id; + + ret = tplg_new_pipeline(ctx, &pipeline, sizeof(pipeline), tplg_ctl); + if (ret < 0) { + SNDERR("error: failed to create pipeline\n"); + free(pipe_info->name); + free(pipe_info); + goto out; + } + + list_item_append(&pipe_info->item, &plug->pipeline_list); + tplg_debug("loading pipeline %s\n", pipe_info->name); +out: + free(tplg_ctl); + return ret; +} + +static int plug_new_buffer(snd_sof_plug_t *plug) +{ + struct ipc4_copier_module_cfg *copier = calloc(sizeof(struct ipc4_copier_module_cfg), 1); + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + int ret; + + if (!copier) + return -ENOMEM; + + comp_info->ipc_payload = copier; + + ret = tplg_new_buffer(ctx, copier, sizeof(copier), NULL, 0); + if (ret < 0) { + SNDERR("error: failed to create pipeline\n"); + free(copier); + } + + return ret; +} + +/* Insert new comp info into the list of widgets */ +static inline int plug_insert_comp(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + struct tplg_comp_info *comp_info; + int comp_id = ctx->comp_id; + int ret; + + if (ctx->widget->id == SND_SOC_TPLG_DAPM_SCHEDULER) + return 0; + + comp_info = calloc(sizeof(struct tplg_comp_info), 1); + if (!comp_info) + return -ENOMEM; + + comp_info->name = strdup(ctx->widget->name); + if (!comp_info->name) { + ret = -ENOMEM; + goto err; + } + + comp_info->stream_name = strdup(ctx->widget->sname); + if (!comp_info->stream_name) { + ret = -ENOMEM; + goto sname_err; + } + + comp_info->id = comp_id; + comp_info->type = ctx->widget->id; + comp_info->pipeline_id = ctx->pipeline_id; + ctx->current_comp_info = comp_info; + + ret = plug_parse_ipc4_comp_tokens(plug, &comp_info->basecfg); + if (ret < 0) + goto sname_err; + + list_item_append(&comp_info->item, &plug->widget_list); + + tplg_debug("debug: loading comp_id %d: widget %s type %d size %d at offset %ld is_pages %d\n", + comp_id, ctx->widget->name, ctx->widget->id, ctx->widget->size, + ctx->tplg_offset, comp_info->basecfg.is_pages); + + return 0; +sname_err: + free(comp_info->name); +err: + free(comp_info); + return ret; +} + +/* load dapm widget */ +static int plug_load_widget(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + int ret = 0; + + /* get next widget */ + ctx->widget = tplg_get_widget(ctx); + ctx->widget_size = ctx->widget->size; + + /* insert widget into mapping */ + ret = plug_insert_comp(plug); + if (ret < 0) { + SNDERR("plug_load_widget: invalid widget index\n"); + return ret; + } + + /* load widget based on type */ + switch (ctx->widget->id) { + /* load pga widget */ + case SND_SOC_TPLG_DAPM_PGA: + if (plug_new_pga(plug) < 0) { + SNDERR("error: load pga\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_AIF_IN: + if (plug_aif_in_out(plug, SOF_IPC_STREAM_PLAYBACK) < 0) { + SNDERR("error: load AIF IN failed\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_AIF_OUT: + if (plug_aif_in_out(plug, SOF_IPC_STREAM_CAPTURE) < 0) { + SNDERR("error: load AIF OUT failed\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_DAI_IN: + if (plug_dai_in_out(plug, SOF_IPC_STREAM_PLAYBACK) < 0) { + SNDERR("error: load filewrite\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_DAI_OUT: + if (plug_dai_in_out(plug, SOF_IPC_STREAM_CAPTURE) < 0) { + SNDERR("error: load filewrite\n"); + ret = -EINVAL; + goto exit; + } + break; + + case SND_SOC_TPLG_DAPM_BUFFER: + if (plug_new_buffer(plug) < 0) { + SNDERR("error: load pipeline\n"); + ret = -EINVAL; + goto exit; + } + break; + + case SND_SOC_TPLG_DAPM_SCHEDULER: + if (plug_new_pipeline(plug) < 0) { + SNDERR("error: load pipeline\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_SRC: + if (plug_new_src_ipc(plug) < 0) { + SNDERR("error: load src\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_ASRC: + if (plug_new_asrc_ipc(plug) < 0) { + SNDERR("error: load asrc\n"); + ret = -EINVAL; + goto exit; + } + break; + + case SND_SOC_TPLG_DAPM_MIXER: + if (plug_new_mixer(plug) < 0) { + SNDERR("error: load mixer\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_EFFECT: + if (plug_new_process(plug) < 0) { + SNDERR("error: load effect\n"); + ret = -EINVAL; + goto exit; + } + break; + + /* unsupported widgets */ + default: + tplg_debug("info: Widget %s id %d unsupported and skipped: size %d priv size %d\n", + ctx->widget->name, ctx->widget->id, + ctx->widget->size, ctx->widget->priv.size); + +#if 0 + if (fseek(ctx->file, ctx->widget->priv.size, SEEK_CUR)) { + SNDERR("error: fseek unsupported widget\n"); + ret = -errno; + goto exit; + } + ret = tplg_create_controls(ctx->widget->num_kcontrols, ctx->file, NULL, 0); + if (ret < 0) { + SNDERR("error: loading controls\n"); + //goto exit; + } +#endif + ret = 0; + break; + } + + ret = 1; + +exit: + return ret; +} + +static int plug_register_graph(snd_sof_plug_t *plug, int count) +{ + struct tplg_context *ctx = &plug->tplg; + int ret = 0; + int i; + + for (i = 0; i < count; i++) { + ret = tplg_parse_graph(ctx, &plug->widget_list, &plug->route_list); + if (ret < 0) + return ret; + } + + return ret; +} + +static int plug_parse_pcm(snd_sof_plug_t *plug, int count) +{ + struct tplg_context *ctx = &plug->tplg; + int ret, i; + + for (i = 0; i < count; i++) { + ret = tplg_parse_pcm(ctx, &plug->widget_list, &plug->pcm_list); + if (ret < 0) + return ret; + } + + return 0; +} + +static void +plug_pipeline_update_resource_usage(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info) +{ + struct ipc4_base_module_cfg *base_config = &comp_info->basecfg; + struct tplg_pipeline_info *pipe_info = comp_info->pipe_info; + int task_mem, queue_mem; + int ibs, bss, total; + + ibs = base_config->ibs; + bss = base_config->is_pages; + + task_mem = SOF_IPC4_PIPELINE_OBJECT_SIZE; + task_mem += SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE + bss; + + /* LL modules */ + task_mem += SOF_IPC4_FW_ROUNDUP(SOF_IPC4_LL_TASK_OBJECT_SIZE); + task_mem += SOF_IPC4_FW_MAX_QUEUE_COUNT * SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE; + task_mem += SOF_IPC4_LL_TASK_LIST_ITEM_SIZE; + + ibs = SOF_IPC4_FW_ROUNDUP(ibs); + queue_mem = SOF_IPC4_FW_MAX_QUEUE_COUNT * (SOF_IPC4_DATA_QUEUE_OBJECT_SIZE + ibs); + + total = SOF_IPC4_FW_PAGE(task_mem + queue_mem); + + pipe_info->mem_usage += total; +} + +static int plug_is_single_format(struct sof_ipc4_pin_format *fmts, int num_formats) +{ + struct sof_ipc4_pin_format *fmt = &fmts[0]; + uint32_t _rate, _channels, _valid_bits; + int i; + + _rate = fmt->audio_fmt.sampling_frequency; + _channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + _valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + for (i = 1; i < num_formats; i++) { + struct sof_ipc4_pin_format *fmt = &fmts[i]; + uint32_t rate, channels, valid_bits; + + rate = fmt->audio_fmt.sampling_frequency; + channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + if (rate != _rate || channels != _channels || valid_bits != _valid_bits) + return false; + } + + return true; +} + +static int plug_match_audio_format(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info, + snd_pcm_hw_params_t *params) +{ + struct sof_ipc4_available_audio_format *available_fmt = &comp_info->available_fmt; + struct ipc4_base_module_cfg *base_cfg = &comp_info->basecfg; + struct sof_ipc4_pin_format *fmt; + snd_pcm_format_t params_format; + unsigned int params_channels, params_rate, dir; + int params_valid_bits; + int i; + + snd_pcm_hw_params_get_channels(params, ¶ms_channels); + snd_pcm_hw_params_get_rate(params, ¶ms_rate, &dir); + snd_pcm_hw_params_get_format(params, ¶ms_format); + + switch (params_format) { + case SND_PCM_FORMAT_S16_LE: + params_valid_bits = 16; + break; + case SND_PCM_FORMAT_S32_LE: + params_valid_bits = 32; + break; + case SND_PCM_FORMAT_S24_LE: + params_valid_bits = 24; + break; + default: + break; + } + + if (plug_is_single_format(available_fmt->input_pin_fmts, + available_fmt->num_input_formats)) { + fmt = &available_fmt->input_pin_fmts[0]; + goto out; + } + + for (i = 0; i < available_fmt->num_input_formats; i++) { + uint32_t rate, channels, valid_bits; + + fmt = &available_fmt->input_pin_fmts[i]; + + rate = fmt->audio_fmt.sampling_frequency; + channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + + if (rate == params_rate && channels == params_channels && + valid_bits == params_valid_bits) + break; + } + + if (i == available_fmt->num_input_formats) { + SNDERR("Cannot find matching format for rate %d channels %d valid_bits %d for %s\n", + params_rate, params_channels, params_valid_bits, comp_info->name); + return -EINVAL; + } +out: + + base_cfg->audio_fmt.sampling_frequency = fmt->audio_fmt.sampling_frequency; + base_cfg->audio_fmt.depth = fmt->audio_fmt.bit_depth; + base_cfg->audio_fmt.ch_map = fmt->audio_fmt.ch_map; + base_cfg->audio_fmt.ch_cfg = fmt->audio_fmt.ch_cfg; + base_cfg->audio_fmt.interleaving_style = fmt->audio_fmt.interleaving_style; + base_cfg->audio_fmt.channels_count = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + base_cfg->audio_fmt.valid_bit_depth = + (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + base_cfg->audio_fmt.s_type = + (fmt->audio_fmt.fmt_cfg & MASK(23, 16)) >> 16; + + /* Choose ALSA period size for ibs/obs so that the buffer sizes will be set accordingly */ + base_cfg->ibs = plug->period_size * 2; + base_cfg->obs = plug->period_size * 2; + + return 0; +} + +static int plug_set_up_widget_base_config(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info, + snd_pcm_hw_params_t *params) +{ + int ret, i; + + /* match audio formats and populate base config */ + ret = plug_match_audio_format(plug, comp_info, params); + if (ret < 0) + return ret; + + /* copy the basecfg into the ipc payload */ + memcpy(comp_info->ipc_payload, &comp_info->basecfg, sizeof(struct ipc4_base_module_cfg)); + + return 0; +} + +/* parse topology file and set up pipeline */ +int plug_parse_topology(snd_sof_plug_t *plug) + +{ + struct tplg_context *ctx = &plug->tplg; + struct snd_soc_tplg_hdr *hdr; + struct list_item *item; + char pipeline_string[256] = {0}; + int i; + int ret = 0; + FILE *file; + size_t size; + + tplg_debug("parsing topology file %s\n", ctx->tplg_file); + + ctx->ctl_arg = plug; + ctx->ctl_cb = plug_kcontrol_cb_new; + + /* open topology file */ + file = fopen(ctx->tplg_file, "rb"); + if (!file) { + SNDERR("error: can't open topology %s : %s\n", ctx->tplg_file, strerror(errno)); + return -errno; + } + + /* file size */ + if (fseek(file, 0, SEEK_END)) { + SNDERR("error: can't seek to end of topology: %s\n", strerror(errno)); + fclose(file); + return -errno; + } + ctx->tplg_size = ftell(file); + if (fseek(file, 0, SEEK_SET)) { + SNDERR("error: can't seek to beginning of topology: %s\n", strerror(errno)); + fclose(file); + return -errno; + } + + /* load whole topology into memory */ + ctx->tplg_base = calloc(ctx->tplg_size, 1); + if (!ctx->tplg_base) { + SNDERR("error: can't alloc buffer for topology %zu bytes\n", ctx->tplg_size); + fclose(file); + return -ENOMEM; + } + ret = fread(ctx->tplg_base, ctx->tplg_size, 1, file); + if (ret != 1) { + SNDERR("error: can't read topology: %s\n", + strerror(errno)); + fclose(file); + return -errno; + } + fclose(file); + + /* initialize widget, route, pipeline and pcm lists */ + list_init(&plug->widget_list); + list_init(&plug->route_list); + list_init(&plug->pcm_list); + list_init(&plug->pipeline_list); + + while (ctx->tplg_offset < ctx->tplg_size) { + /* read next topology header */ + hdr = tplg_get_hdr(ctx); + + tplg_debug("type: %x, size: 0x%x count: %d index: %d\n", + hdr->type, hdr->payload_size, hdr->count, hdr->index); + + ctx->hdr = hdr; + + /* parse header and load the next block based on type */ + switch (hdr->type) { + /* load dapm widget */ + case SND_SOC_TPLG_TYPE_DAPM_WIDGET: + tplg_debug("number of DAPM widgets %d\n", hdr->count); + + /* update max pipeline_id */ + ctx->pipeline_id = hdr->index; + + for (i = 0; i < hdr->count; i++) { + ret = plug_load_widget(plug); + if (ret < 0) { + SNDERR("error: loading widget\n"); + return ret; + } + ctx->comp_id++; + } + break; + /* set up component connections from pipeline graph */ + case SND_SOC_TPLG_TYPE_DAPM_GRAPH: + if (plug_register_graph(plug, hdr->count) < 0) { + SNDERR("error: pipeline graph\n"); + return -EINVAL; + } + break; + /* parse PCM info */ + case SND_SOC_TPLG_TYPE_PCM: + ret = plug_parse_pcm(plug, hdr->count); + if (ret < 0) + goto out; + break; + default: + tplg_debug("%s %d\n", __func__, __LINE__); + tplg_skip_hdr_payload(ctx); + break; + } + } + + /* assign pipeline to every widget in the widget list */ + list_for_item(item, &plug->widget_list) { + struct tplg_comp_info *comp_info = container_of(item, struct tplg_comp_info, item); + struct list_item *pipe_item; + + list_for_item(pipe_item, &plug->pipeline_list) { + struct tplg_pipeline_info *pipe_info; + + pipe_info = container_of(pipe_item, struct tplg_pipeline_info, item); + if (pipe_info->id == comp_info->pipeline_id) { + comp_info->pipe_info = pipe_info; + break; + } + } + + if (!comp_info->pipe_info) { + SNDERR("Error assigning pipeline for %s\n", comp_info->name); + return -EINVAL; + } + } +out: + return ret; +} + +static int plug_set_up_widget_ipc(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info) +{ + struct ipc4_module_init_instance *module_init = &comp_info->module_init; + struct ipc4_message_reply reply; + void *msg; + int size, ret; + + module_init->extension.r.param_block_size = comp_info->ipc_size >> 2; + module_init->extension.r.ppl_instance_id = comp_info->pipe_info->instance_id; + + size = sizeof(*module_init) + comp_info->ipc_size; + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + memcpy(msg, module_init, sizeof(*module_init)); + memcpy(msg + sizeof(*module_init), comp_info->ipc_payload, comp_info->ipc_size); + + ret = plug_ipc_cmd_tx_rx(&plug->ipc, msg, size, &reply, sizeof(reply)); + free(msg); + if (ret < 0) { + SNDERR("error: can't set up widget %s\n", comp_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("widget %s set up failed with status %d\n", + comp_info->name, reply.primary.r.status); + return -EINVAL; + } + return 0; +} + +static int plug_set_up_pipeline(snd_sof_plug_t *plug, struct tplg_pipeline_info *pipe_info) +{ + struct ipc4_pipeline_create msg = {{ 0 }}; + struct ipc4_message_reply reply; + int ret; + + msg.primary.r.type = SOF_IPC4_GLB_CREATE_PIPELINE; + msg.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + pipe_info->instance_id = plug->instance_ids[SND_SOC_TPLG_DAPM_SCHEDULER]++; + msg.primary.r.instance_id = pipe_info->instance_id; + msg.primary.r.ppl_mem_size = pipe_info->mem_usage; + + ret = plug_ipc_cmd_tx_rx(&plug->ipc, &msg, sizeof(msg), &reply, sizeof(reply)); + if (ret < 0) { + SNDERR("error: can't set up pipeline %s\n", pipe_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("pipeline %s instance ID %d set up failed with status %d\n", + pipe_info->name, pipe_info->instance_id, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("pipeline %s instance_id %d mem_usage %d set up\n", pipe_info->name, + pipe_info->instance_id, pipe_info->mem_usage); + + return 0; +} + +static int plug_prepare_widget(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_info, + struct tplg_comp_info *comp_info, int dir, + snd_pcm_hw_params_t *params) +{ + struct tplg_pipeline_list *pipeline_list; + int ret, i; + + if (dir) + pipeline_list = &pcm_info->capture_pipeline_list; + else + pipeline_list = &pcm_info->playback_pipeline_list; + + /* populate base config */ + ret = plug_set_up_widget_base_config(plug, comp_info, params); + if (ret < 0) + return ret; + + plug_pipeline_update_resource_usage(plug, comp_info); + + /* add pipeline to pcm pipeline_list if needed */ + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + if (pipe_info == comp_info->pipe_info) + break; + } + + if (i == pipeline_list->count) { + pipeline_list->pipelines[pipeline_list->count] = comp_info->pipe_info; + pipeline_list->count++; + } + + tplg_debug("widget %s prepared\n", comp_info->name); + return 0; +} + +static int plug_prepare_widgets(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_info, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info, + snd_pcm_hw_params_t *params) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->source != current_comp_info) + continue; + + /* set up source widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = plug_prepare_widget(plug, pcm_info, current_comp_info, 0, params); + if (ret < 0) + return ret; + } + + /* set up the sink widget */ + ret = plug_prepare_widget(plug, pcm_info, route_info->sink, 0, params); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN || + route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = plug_prepare_widgets(plug, pcm_info, starting_comp_info, + route_info->sink, params); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int plug_prepare_widgets_capture(snd_sof_plug_t *plug, struct tplg_pcm_info *pcm_info, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info, + snd_pcm_hw_params_t *params) +{ + struct list_item *item; + int ret; + + /* for capture */ + list_for_item(item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->sink != current_comp_info) + continue; + + /* set up sink widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = plug_prepare_widget(plug, pcm_info, current_comp_info, 1, params); + if (ret < 0) + return ret; + } + + /* set up the source widget */ + ret = plug_prepare_widget(plug, pcm_info, route_info->source, 1, params); + if (ret < 0) + return ret; + + /* and then continue up the path */ + if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_IN && + route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = plug_prepare_widgets_capture(plug, pcm_info, starting_comp_info, + route_info->source, params); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int plug_set_up_route(snd_sof_plug_t *plug, struct tplg_route_info *route_info) +{ + struct tplg_comp_info *src_comp_info = route_info->source; + struct tplg_comp_info *sink_comp_info = route_info->sink; + struct ipc4_module_bind_unbind bu; + struct ipc4_message_reply reply; + int ret; + + bu.primary.r.module_id = src_comp_info->module_id; + bu.primary.r.instance_id = src_comp_info->instance_id; + bu.primary.r.type = SOF_IPC4_MOD_BIND; + bu.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + bu.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + + bu.extension.r.dst_module_id = sink_comp_info->module_id; + bu.extension.r.dst_instance_id = sink_comp_info->instance_id; + + /* FIXME: assign queue ID for components with multiple inputs/outputs */ + bu.extension.r.dst_queue = 0; + bu.extension.r.src_queue = 0; + + ret = plug_ipc_cmd_tx_rx(&plug->ipc, &bu, sizeof(bu), &reply, sizeof(reply)); + if (ret < 0) { + SNDERR("error: can't set up route %s -> %s\n", src_comp_info->name, + sink_comp_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("route %s -> %s ID set up failed with status %d\n", + src_comp_info->name, sink_comp_info->name, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("route %s -> %s set up\n", src_comp_info->name, sink_comp_info->name); + + return 0; +} + +static int plug_set_up_widget(snd_sof_plug_t *plug, struct tplg_comp_info *comp_info) +{ + struct tplg_pipeline_info *pipe_info = comp_info->pipe_info; + struct plug_shm_glb_state *glb = plug->glb_ctx.addr; + struct plug_shm_ctl *ctl; + int ret, i; + + pipe_info->usage_count++; + + /* first set up pipeline if needed, only done once for the first pipeline widget */ + if (pipe_info->usage_count == 1) { + ret = plug_set_up_pipeline(plug, pipe_info); + if (ret < 0) { + pipe_info->usage_count--; + return ret; + } + } + + /* now set up the widget */ + ret = plug_set_up_widget_ipc(plug, comp_info); + if (ret < 0) + return ret; + + /* send kcontrol bytes data */ + for (i = 0; i < glb->num_ctls; i++) { + struct snd_soc_tplg_bytes_control *tplg_bytes; + struct sof_abi_hdr *abi; + int priv_size; + + ctl = &glb->ctl[i]; + + /* send the bytes data from kcontrols associated with current widget */ + if (ctl->module_id != comp_info->module_id || + ctl->instance_id != comp_info->instance_id || + ctl->type != SND_SOC_TPLG_TYPE_BYTES) + continue; + + tplg_bytes = &ctl->bytes_ctl; + priv_size = tplg_bytes->priv.size; + abi = (struct sof_abi_hdr *)ctl->data; + + /* send IPC with kcontrol data */ + ret = plug_send_bytes_data(&plug->ipc, comp_info->module_id, + comp_info->instance_id, abi); + if (ret < 0) { + SNDERR("failed to set bytes data for widget %s\n", comp_info->name); + return ret; + } + } + + tplg_debug("widget %s set up\n", comp_info->name); + + return 0; +} + +static int plug_set_up_widgets(snd_sof_plug_t *plug, struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->source != current_comp_info) + continue; + + /* set up source widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = plug_set_up_widget(plug, current_comp_info); + if (ret < 0) + return ret; + } + + /* set up the sink widget */ + ret = plug_set_up_widget(plug, route_info->sink); + if (ret < 0) + return ret; + + /* source and sink widgets are up, so set up route now */ + ret = plug_set_up_route(plug, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN || + route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = plug_set_up_widgets(plug, starting_comp_info, route_info->sink); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int plug_set_up_widgets_capture(snd_sof_plug_t *plug, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->sink != current_comp_info) + continue; + + /* set up source widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = plug_set_up_widget(plug, current_comp_info); + if (ret < 0) + return ret; + } + + /* set up the sink widget */ + ret = plug_set_up_widget(plug, route_info->source); + if (ret < 0) + return ret; + + /* source and sink widgets are up, so set up route now */ + ret = plug_set_up_route(plug, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_IN && + route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = plug_set_up_widgets_capture(plug, starting_comp_info, + route_info->source); + if (ret < 0) + return ret; + } + } + + return 0; +} + +int plug_set_up_pipelines(snd_sof_plug_t *plug, int dir, snd_pcm_hw_params_t *params) +{ + struct tplg_comp_info *host = NULL; + struct tplg_pcm_info *pcm_info; + struct list_item *item; + int ret; + + list_for_item(item, &plug->pcm_list) { + pcm_info = container_of(item, struct tplg_pcm_info, item); + + if (pcm_info->id == plug->pcm_id) { + if (dir) + host = pcm_info->capture_host; + else + host = pcm_info->playback_host; + break; + } + } + + if (!host) { + SNDERR("No host component found for PCM ID: %d\n", plug->pcm_id); + return -EINVAL; + } + + plug->pcm_info = pcm_info; + + if (dir) { + ret = plug_prepare_widgets_capture(plug, pcm_info, host, host, params); + if (ret < 0) + return ret; + + ret = plug_set_up_widgets_capture(plug, host, host); + if (ret < 0) + return ret; + + tplg_debug("Setting up capture pipelines complete\n"); + + return 0; + } + + ret = plug_prepare_widgets(plug, pcm_info, host, host, params); + if (ret < 0) + return ret; + + ret = plug_set_up_widgets(plug, host, host); + if (ret < 0) + return ret; + + tplg_debug("Setting up playback pipelines complete\n"); + + return 0; +} + +static int plug_delete_pipeline(snd_sof_plug_t *plug, struct tplg_pipeline_info *pipe_info) +{ + struct ipc4_pipeline_delete msg; + struct ipc4_message_reply reply; + int ret; + + msg.primary.r.type = SOF_IPC4_GLB_DELETE_PIPELINE; + msg.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + msg.primary.r.instance_id = pipe_info->instance_id; + + ret = plug_ipc_cmd_tx_rx(&plug->ipc, &msg, sizeof(msg), &reply, sizeof(reply)); + if (ret < 0) { + SNDERR("error: can't delete pipeline %s\n", pipe_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("pipeline %s instance ID %d delete failed with status %d\n", + pipe_info->name, pipe_info->instance_id, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("pipeline %s instance_id %d freed\n", pipe_info->name, + pipe_info->instance_id); + + return 0; +} + +static int plug_free_route(snd_sof_plug_t *plug, struct tplg_route_info *route_info) +{ + struct tplg_comp_info *src_comp_info = route_info->source; + struct tplg_comp_info *sink_comp_info = route_info->sink; + struct ipc4_module_bind_unbind bu; + struct ipc4_message_reply reply; + int ret; + + /* only unbind when widgets belong to separate pipelines */ + if (src_comp_info->pipeline_id == sink_comp_info->pipeline_id) + return 0; + + bu.primary.r.module_id = src_comp_info->module_id; + bu.primary.r.instance_id = src_comp_info->instance_id; + bu.primary.r.type = SOF_IPC4_MOD_UNBIND; + bu.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + bu.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + + bu.extension.r.dst_module_id = sink_comp_info->module_id; + bu.extension.r.dst_instance_id = sink_comp_info->instance_id; + + /* FIXME: assign queue ID for components with multiple inputs/outputs */ + bu.extension.r.dst_queue = 0; + bu.extension.r.src_queue = 0; + + ret = plug_ipc_cmd_tx_rx(&plug->ipc, &bu, sizeof(bu), &reply, sizeof(reply)); + if (ret < 0) { + SNDERR("error: can't set up route %s -> %s\n", src_comp_info->name, + sink_comp_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("route %s -> %s ID set up failed with status %d\n", + src_comp_info->name, sink_comp_info->name, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("route %s -> %s freed\n", src_comp_info->name, sink_comp_info->name); + + return 0; +} + +static int plug_free_widgets(snd_sof_plug_t *plug, struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->source != current_comp_info) + continue; + + /* Widgets will be freed when the pipeline is deleted, so just unbind modules */ + ret = plug_free_route(plug, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN || + route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = plug_free_widgets(plug, starting_comp_info, route_info->sink); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int plug_free_widgets_capture(snd_sof_plug_t *plug, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->sink != current_comp_info) + continue; + + /* Widgets will be freed when the pipeline is deleted, so just unbind modules */ + ret = plug_free_route(plug, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN && + route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = plug_free_widgets_capture(plug, starting_comp_info, + route_info->source); + if (ret < 0) + return ret; + } + } + + return 0; +} + +int plug_free_pipelines(snd_sof_plug_t *plug, struct tplg_pipeline_list *pipeline_list, int dir) +{ + struct tplg_comp_info *host = NULL; + struct tplg_pcm_info *pcm_info; + struct list_item *item; + int ret, i; + + list_for_item(item, &plug->pcm_list) { + pcm_info = container_of(item, struct tplg_pcm_info, item); + + if (pcm_info->id == plug->pcm_id) { + if (dir) + host = pcm_info->capture_host; + else + host = pcm_info->playback_host; + break; + } + } + + if (!host) { + SNDERR("No host component found for PCM ID: %d\n", plug->pcm_id); + return -EINVAL; + } + + if (dir) { + ret = plug_free_widgets_capture(plug, host, host); + if (ret < 0) { + SNDERR("failed to free widgets for capture PCM %d\n", plug->pcm_id); + return ret; + } + } else { + ret = plug_free_widgets(plug, host, host); + if (ret < 0) { + SNDERR("failed to free widgets for PCM %d\n", plug->pcm_id); + return ret; + } + } + + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + ret = plug_delete_pipeline(plug, pipe_info); + if (ret < 0) + return ret; + } + + plug->instance_ids[SND_SOC_TPLG_DAPM_SCHEDULER] = 0; + return 0; +} + +void plug_free_topology(snd_sof_plug_t *plug) +{ + struct tplg_context *ctx = &plug->tplg; + struct list_item *item, *_item; + + list_for_item_safe(item, _item, &plug->pcm_list) { + struct tplg_pcm_info *pcm_info = container_of(item, struct tplg_pcm_info, item); + + free(pcm_info->name); + free(pcm_info); + } + + list_for_item_safe(item, _item, &plug->widget_list) { + struct tplg_comp_info *comp_info = container_of(item, struct tplg_comp_info, item); + struct sof_ipc4_available_audio_format *available_fmts = &comp_info->available_fmt; + + free(available_fmts->output_pin_fmts); + free(available_fmts->input_pin_fmts); + free(comp_info->name); + free(comp_info->stream_name); + free(comp_info->ipc_payload); + free(comp_info); + } + + list_for_item_safe(item, _item, &plug->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + free(route_info); + } + + list_for_item_safe(item, _item, &plug->pipeline_list) { + struct tplg_pipeline_info *pipe_info = container_of(item, struct tplg_pipeline_info, + item); + + free(pipe_info->name); + free(pipe_info); + } + + free(ctx->tplg_base); + tplg_debug("freed all pipelines, widgets, routes and pcms\n"); +} diff --git a/tools/plugin/alsaplug/tplg_ctl.c b/tools/plugin/alsaplug/tplg_ctl.c new file mode 100644 index 000000000000..ad2709153806 --- /dev/null +++ b/tools/plugin/alsaplug/tplg_ctl.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// + +/* SOF topology kcontrols */ + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <math.h> + +#include <alsa/asoundlib.h> +#include <alsa/pcm_external.h> + +#include <rtos/sof.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component.h> +#include <ipc/stream.h> +#include <tplg_parser/topology.h> + +#include "plugin.h" +#include "common.h" + +#define SOF_IPC4_VOL_ZERO_DB 0x7fffffff +#define VOLUME_FWL 16 +/* + * Constants used in the computation of linear volume gain + * from dB gain 20th root of 10 in Q1.16 fixed-point notation + */ +#define VOL_TWENTIETH_ROOT_OF_TEN 73533 +/* 40th root of 10 in Q1.16 fixed-point notation*/ +#define VOL_FORTIETH_ROOT_OF_TEN 69419 + +/* 0.5 dB step value in topology TLV */ +#define VOL_HALF_DB_STEP 50 + +/* + * Function to truncate an unsigned 64-bit number + * by x bits and return 32-bit unsigned number. This + * function also takes care of rounding while truncating + */ +static uint32_t vol_shift_64(uint64_t i, uint32_t x) +{ + if (x == 0) + return (uint32_t)i; + + /* do not truncate more than 32 bits */ + if (x > 32) + x = 32; + + return (uint32_t)(((i >> (x - 1)) + 1) >> 1); +} + +/* + * Function to compute a ** exp where, + * a is a fractional number represented by a fixed-point integer with a fractional word length + * of "fwl" + * exp is an integer + * fwl is the fractional word length + * Return value is a fractional number represented by a fixed-point integer with a fractional + * word length of "fwl" + */ +static uint32_t vol_pow32(uint32_t a, int exp, uint32_t fwl) +{ + int i, iter; + uint32_t power = 1 << fwl; + unsigned long long numerator; + + /* if exponent is 0, return 1 */ + if (exp == 0) + return power; + + /* determine the number of iterations based on the exponent */ + if (exp < 0) + iter = exp * -1; + else + iter = exp; + + /* multiply a "iter" times to compute power */ + for (i = 0; i < iter; i++) { + /* + * Product of 2 Qx.fwl fixed-point numbers yields a Q2*x.2*fwl + * Truncate product back to fwl fractional bits with rounding + */ + power = vol_shift_64((uint64_t)power * a, fwl); + } + + if (exp > 0) { + /* if exp is positive, return the result */ + return power; + } + + /* if exp is negative, return the multiplicative inverse */ + numerator = (uint64_t)1 << (fwl << 1); + numerator /= power; + + return (uint32_t)numerator; +} + +/* + * Function to calculate volume gain from TLV data. + * This function can only handle gain steps that are multiples of 0.5 dB + */ +static uint32_t vol_compute_gain(uint32_t value, struct snd_soc_tplg_tlv_dbscale *scale) +{ + int dB_gain; + uint32_t linear_gain; + int f_step; + + /* mute volume */ + if (value == 0 && scale->mute) + return 0; + + /* compute dB gain from tlv. tlv_step in topology is multiplied by 100 */ + dB_gain = (int)scale->min / 100 + (value * scale->step) / 100; + + /* compute linear gain represented by fixed-point int with VOLUME_FWL fractional bits */ + linear_gain = vol_pow32(VOL_TWENTIETH_ROOT_OF_TEN, dB_gain, VOLUME_FWL); + + /* extract the fractional part of volume step */ + f_step = scale->step - (scale->step / 100); + + /* if volume step is an odd multiple of 0.5 dB */ + if (f_step == VOL_HALF_DB_STEP && (value & 1)) + linear_gain = vol_shift_64((uint64_t)linear_gain * VOL_FORTIETH_ROOT_OF_TEN, + VOLUME_FWL); + + return linear_gain; +} + +/* helper function to add new kcontrols to the list of kcontrols in the global context */ +int plug_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, void *_comp, void *arg, int index) +{ + struct tplg_comp_info *comp_info = _comp; + snd_sof_plug_t *plug = arg; + struct plug_shm_glb_state *glb = plug->glb_ctx.addr; + struct plug_shm_ctl *ctl; + + if (glb->num_ctls >= MAX_CTLS) { + SNDERR("Failed to add a new control. Too many controls already\n"); + return -EINVAL; + } + + switch (tplg_ctl->ops.info) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + { + struct snd_soc_tplg_mixer_control *tplg_mixer = + (struct snd_soc_tplg_mixer_control *)tplg_ctl; + struct snd_soc_tplg_ctl_tlv *tlv; + struct snd_soc_tplg_tlv_dbscale *scale; + int i; + + glb->size += sizeof(struct plug_shm_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->mixer_ctl = *tplg_mixer; + ctl->index = index; + ctl->type = tplg_ctl->type; + tlv = &tplg_ctl->tlv; + scale = &tlv->scale; + + /* populate the volume table */ + for (i = 0; i < tplg_mixer->max + 1 ; i++) { + uint32_t val = vol_compute_gain(i, scale); + + /* Can be over Q1.31, need to saturate */ + uint64_t q31val = ((uint64_t)val) << 15; + + ctl->volume_table[i] = q31val > SOF_IPC4_VOL_ZERO_DB ? + SOF_IPC4_VOL_ZERO_DB : q31val; + } + break; + } + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_CTL_ENUM_VALUE: + { + struct snd_soc_tplg_enum_control *tplg_enum = + (struct snd_soc_tplg_enum_control *)tplg_ctl; + + glb->size += sizeof(struct plug_shm_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->enum_ctl = *tplg_enum; + ctl->index = index; + ctl->type = tplg_ctl->type; + break; + } + case SND_SOC_TPLG_CTL_BYTES: + { + struct snd_soc_tplg_bytes_control *tplg_bytes = + (struct snd_soc_tplg_bytes_control *)tplg_ctl; + + glb->size += sizeof(struct plug_shm_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->bytes_ctl = *tplg_bytes; + ctl->index = index; + ctl->type = tplg_ctl->type; + memcpy(ctl->data, tplg_bytes->priv.data, tplg_bytes->priv.size); + break; + } + case SND_SOC_TPLG_CTL_RANGE: + case SND_SOC_TPLG_CTL_STROBE: + default: + SNDERR("Invalid ctl type %d\n", tplg_ctl->type); + return -EINVAL; + } + + return 0; +} diff --git a/tools/plugin/common.c b/tools/plugin/common.c new file mode 100644 index 000000000000..f20cb14e0b0e --- /dev/null +++ b/tools/plugin/common.c @@ -0,0 +1,466 @@ +/*-*- linux-c -*-*/ + +/* + * ALSA <-> SOF PCM I/O plugin + * + * Copyright (c) 2022 by Liam Girdwood <liam.r.girdwood@intel.com> + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/stat.h> + +#include "common.h" + +/* + * Timing + */ +void plug_timespec_add_ms(struct timespec *ts, unsigned long ms) +{ + long ns; + long secs = ms / 1000; + + /* get ms remainder */ + ms = ms - (secs * 1000); + ns = ms * 1000000; + + ts->tv_nsec += ns; + if (ts->tv_nsec > 1000000000) { + secs++; + ts->tv_nsec -= 1000000000; + } + ts->tv_sec += (secs + DEBUG_TV_SECS); +} + +long plug_timespec_delta_ns(struct timespec *before, struct timespec *after) +{ + long ns; + + ns = (after->tv_sec - before->tv_sec) * 1000000000; + ns += after->tv_nsec - before->tv_nsec; + + return ns; +} + +static const char *suffix_name(const char *longname) +{ + size_t len = strlen(longname); + int i = len; + + /* longname name invalid */ + if (len < 1) { + SNDERR("invalid topology long name\n"); + return NULL; + } + + /* find the last '/' in the longname topology path */ + while (--i >= 0) { + if (longname[i] == '/') { + i += 1; /* skip / */ + return &longname[i]; + } + } + + /* no / in topology path, so use full path */ + return longname; +} + +/* + * IPC + * + * POSIX message queues are used for interprocess IPC messaging. + */ + +/* + * Initialise the IPC object. + */ +int plug_socket_path_init(struct plug_socket_desc *ipc, const char *tplg, const char *type, + int index) +{ + snprintf(ipc->path, NAME_SIZE, "/tmp/%s-%s", tplg, type); + return 0; +} + +/* + * Locking + * + * POSIX semaphores are used to block and synchronise audio between + * different threads and processes. + */ + +/* + * Initialise the lock object. + */ +int plug_lock_init(struct plug_sem_desc *lock, const char *tplg, const char *type, int index) +{ + const char *name = suffix_name(tplg); + + if (!name) + return -EINVAL; + + /* semaphores need the leading / */ + snprintf(lock->name, NAME_SIZE, "/lock-%s-%s-%d", name, type, index); + + return 0; +} + +/* + * SHM + * + * Shared memory is used for audio data and audio context sharing between + * threads and processes. + */ + +/* + * Initialise the SHM object. + */ +int plug_shm_init(struct plug_shm_desc *shm, const char *tplg, const char *type, int index) +{ + const char *name = suffix_name(tplg); + + if (!name) + return -EINVAL; + + snprintf(shm->name, NAME_SIZE, "/shm-%s-%s-%d", name, type, index); + shm->size = SHM_SIZE; + + return 0; +} + +/* + * Open an existing shared memory region using the SHM object. + */ +int plug_shm_open(struct plug_shm_desc *shm) +{ + struct stat status; + + /* open SHM to be used for low latency position */ + shm->fd = shm_open(shm->name, O_RDWR, + S_IRWXU | S_IRWXG); + if (shm->fd < 0) { + //SNDERR("failed to open SHM position %s: %s\n", + // shm->name, strerror(errno)); + return -errno; + } + + fstat(shm->fd, &status); + /* map it locally for context readback */ + shm->addr = mmap(NULL, status.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm->fd, 0); + if (!shm->addr) { + SNDERR("failed to mmap SHM position%s: %s\n", shm->name, strerror(errno)); + return -errno; + } + + return 0; +} + +static int plug_socket_timed_wait(struct plug_socket_desc *ipc, fd_set *fds, int timeout_ms, + bool write) +{ + struct timeval timeout; + int result; + + /* Set the timeout for select */ + timeout.tv_sec = 0; + timeout.tv_usec = timeout_ms * 1000; + + /* now wait for socket to be readable/writable */ + if (write) + result = select(ipc->socket_fd + 1, NULL, fds, NULL, &timeout); + else + result = select(ipc->socket_fd + 1, fds, NULL, NULL, &timeout); + + if (result == -1) { + SNDERR("error waiting for socket to be %s\n", write ? "writable" : "readable"); + return result; + } + + if (result == 0) { + SNDERR("IPC Socket %s timeout\n", write ? "write" : "read"); + return -ETIMEDOUT; + } + + /* socket ready for read/write */ + if (FD_ISSET(ipc->socket_fd, fds)) + return 0; + + /* socket not ready */ + return -EINVAL; +} + +static int plug_ipc_cmd_tx(struct plug_socket_desc *ipc, void *msg, size_t len) +{ + fd_set write_fds; + char mailbox[IPC3_MAX_MSG_SIZE]; + ssize_t bytes; + int err; + + if (len > IPC3_MAX_MSG_SIZE) { + SNDERR("ipc: message too big %d\n", len); + return -EINVAL; + } + memset(mailbox, 0, IPC3_MAX_MSG_SIZE); + memcpy(mailbox, msg, len); + + /* Wait for the socket to be writable */ + FD_ZERO(&write_fds); + FD_SET(ipc->socket_fd, &write_fds); + + err = plug_socket_timed_wait(ipc, &write_fds, 20, true); + if (err < 0) + return err; + + bytes = send(ipc->socket_fd, mailbox, IPC3_MAX_MSG_SIZE, 0); + if (bytes == -1) { + SNDERR("failed to send IPC message : %s\n", strerror(errno)); + return -errno; + } + + return bytes; +} + +static int plug_ipc_cmd_rx(struct plug_socket_desc *ipc, char mailbox[IPC3_MAX_MSG_SIZE]) +{ + fd_set read_fds; + int err; + + /* Wait for the socket to be readable */ + FD_ZERO(&read_fds); + FD_SET(ipc->socket_fd, &read_fds); + + err = plug_socket_timed_wait(ipc, &read_fds, 200, false); + if (err < 0) + return err; + + memset(mailbox, 0, IPC3_MAX_MSG_SIZE); + return recv(ipc->socket_fd, mailbox, IPC3_MAX_MSG_SIZE, 0); +} + +int plug_ipc_cmd_tx_rx(struct plug_socket_desc *ipc, void *msg, size_t len, void *reply, + size_t rlen) +{ + char mailbox[IPC3_MAX_MSG_SIZE]; + ssize_t bytes; + int err; + + /* send IPC message */ + bytes = plug_ipc_cmd_tx(ipc, msg, len); + if (bytes == -1) { + SNDERR("failed to send IPC message : %s\n", strerror(errno)); + return -errno; + } + + /* wait for response */ + memset(mailbox, 0, IPC3_MAX_MSG_SIZE); + bytes = plug_ipc_cmd_rx(ipc, mailbox); + if (bytes == -1) { + SNDERR("failed to read IPC message reply %s\n", strerror(errno)); + return -errno; + } + + /* no response or connection lost, try to restablish connection */ + if (bytes == 0) { + close(ipc->socket_fd); + err = plug_create_client_socket(ipc); + if (err < 0) { + SNDERR("failed to reestablish connection to SOF pipe IPC socket : %s", + strerror(err)); + return -errno; + } + + /* send IPC message again */ + bytes = plug_ipc_cmd_tx(ipc, msg, len); + if (bytes == -1) { + SNDERR("failed to send IPC message : %s\n", strerror(errno)); + return -errno; + } + + /* wait for response */ + memset(mailbox, 0, IPC3_MAX_MSG_SIZE); + bytes = plug_ipc_cmd_rx(ipc, mailbox); + if (bytes == -1) { + SNDERR("failed to read IPC message reply %s\n", strerror(errno)); + return -errno; + } + + /* connection lost again, quit now */ + if (bytes == 0) + return -errno; + } + + /* do the message work */ + if (rlen && reply) + memcpy(reply, mailbox, rlen); + + return 0; +} + +void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, + size_t size, uint32_t module_id, uint32_t instance_id, + uint32_t type) +{ + config->primary.r.type = type; + config->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + config->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + config->primary.r.module_id = module_id; + config->primary.r.instance_id = instance_id; + + config->extension.r.data_off_size = size; + config->extension.r.large_param_id = param_id; +} + +int plug_send_bytes_data(struct plug_socket_desc *ipc, uint32_t module_id, uint32_t instance_id, + struct sof_abi_hdr *abi) +{ + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_message_reply reply; + void *msg; + int msg_size; + int err; + + /* configure the IPC message */ + plug_ctl_ipc_message(&config, abi->type, abi->size, module_id, instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + /* allocate memory for IPC message */ + msg_size = sizeof(config) + abi->size; + msg = calloc(msg_size, 1); + if (!msg) + return -ENOMEM; + + /* set the IPC message data */ + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), abi->data, abi->size); + + /* send the message and check status */ + err = plug_ipc_cmd_tx_rx(ipc, msg, msg_size, &reply, sizeof(reply)); + free(msg); + if (err < 0) { + SNDERR("failed to send IPC to set bytes data\n"); + return err; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + SNDERR("IPC failed with status %d\n", reply.primary.r.status); + return -EINVAL; + } + + return 0; +} + +int plug_socket_create(struct plug_socket_desc *ipc) +{ + struct sockaddr_un addr; + int sockfd; + + /* Check if the socket path already exists */ + if (access(ipc->path, F_OK) != -1) { + /* If it exists, remove it */ + if (unlink(ipc->path) == -1) { + SNDERR("unlink previous socket file"); + return -EINVAL; + } + } + + /* Create the socket */ + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { + SNDERR("failed to create new socket"); + return sockfd; + } + + ipc->socket_fd = sockfd; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, ipc->path, sizeof(addr.sun_path) - 1); + + /* Bind the socket to the address */ + if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + SNDERR("failed to bind new socket for IPC path\n"); + close(sockfd); + return -EINVAL; + } + + if (listen(sockfd, MAX_IPC_CLIENTS) == -1) { + SNDERR("failed to listen on socket for IPC\n"); + return -EINVAL; + } + + return 0; +} + +static int set_socket_nonblocking(int sockfd) +{ + int flags = fcntl(sockfd, F_GETFL, 0); + + if (flags == -1) { + SNDERR("fcntl(F_GETFL) failed"); + return -EINVAL; + } + + flags |= O_NONBLOCK; + if (fcntl(sockfd, F_SETFL, flags) == -1) { + SNDERR("fcntl(F_SETFL) failed"); + return -EINVAL; + } + + return 0; +} + +int plug_create_client_socket(struct plug_socket_desc *ipc) +{ + struct sockaddr_un addr; + int sockfd; + + sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { + SNDERR("error: failed to create sof-pipe IPC socket\n"); + return sockfd; + } + + if (set_socket_nonblocking(sockfd) < 0) { + close(sockfd); + return -EINVAL; + } + ipc->socket_fd = sockfd; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, ipc->path, sizeof(addr.sun_path) - 1); + + /* Connect to the server (non-blocking) */ + if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + if (errno != EINPROGRESS) { + SNDERR("failed to connect to ipc socket"); + return -errno; + } + } + + return sockfd; +} diff --git a/tools/plugin/common.h b/tools/plugin/common.h new file mode 100644 index 000000000000..a64100c397cc --- /dev/null +++ b/tools/plugin/common.h @@ -0,0 +1,328 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __SOF_PLUGIN_COMMON_H__ +#define __SOF_PLUGIN_COMMON_H__ + +#include <stdint.h> +#include <semaphore.h> +#include <alsa/asoundlib.h> +#include <ipc/control.h> +#include <tplg_parser/topology.h> + +/* temporary - current MAXLEN is not define in UAPI header - fix pending */ +#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN +#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 +#endif + +#include <alsa/sound/uapi/asoc.h> + +#define IPC3_MAX_MSG_SIZE 384 +#define NAME_SIZE 256 + +#define MAX_CTLS 256 + +#define MS_TO_US(_msus) (_msus * 1000) +#define MS_TO_NS(_msns) (MS_TO_US(_msns * 1000)) + +#define MS_TO_US(_msus) (_msus * 1000) +#define MS_TO_NS(_msns) (MS_TO_US(_msns * 1000)) + +#define SEM_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) + +#define SHM_SIZE (4096 * 64) /* get from topology - and set for context */ + +#define NUM_EP_CONFIGS 8 + +#define MAX_IPC_CLIENTS 5 + +/* + * Run with valgrind + * valgrind --trace-children=yes aplay -v -Dsof:blah.tplg,1,hw:1,2 -f dat /dev/zero + */ +//#define VALGRIND +#ifdef VALGRIND +#define DEBUG_TV_SECS 10 +#define DEBUG_RETRIES 1000 +#else +#define DEBUG_RETRIES 10 +#define DEBUG_TV_SECS 0 +#endif + +#define SOF_MAGIC "sofpipe" +#define MAX_VOLUME_SIZE 120 +#define MAX_DATA_SIZE 512 + +enum plugin_state { + SOF_PLUGIN_STATE_INIT = 0, + SOF_PLUGIN_STATE_READY = 1, + SOF_PLUGIN_STATE_DEAD = 2, + SOF_PLUGIN_STATE_STREAM_RUNNING = 3, + SOF_PLUGIN_STATE_STREAM_ERROR = 5, +}; + +struct plug_shm_ctl { + unsigned int module_id; + unsigned int instance_id; + unsigned int type; + unsigned int volume_table[MAX_VOLUME_SIZE]; + unsigned int index; + char data[MAX_DATA_SIZE]; + union { + struct snd_soc_tplg_mixer_control mixer_ctl; + struct snd_soc_tplg_enum_control enum_ctl; + struct snd_soc_tplg_bytes_control bytes_ctl; + }; +}; + +/* + * config.48k2c { + * rate 48000 + * channels 2 + * period_time 0 + * period_frames 6000 + * buffer_time 0 + * buffer_frames 24000 + * } + */ +struct plug_config { + char name[44]; + unsigned long buffer_frames; + unsigned long buffer_time; + unsigned long period_frames; + unsigned long period_time; + int rate; + int channels; + unsigned long format; +}; + +/* + * :[pcm:card:dev:config[pcm:card:dev:config]...] + */ +struct plug_cmdline_item { + int pcm; + char card_name[44]; + char dev_name[44]; + char config_name[44]; +}; + +/* + * Endpoint pipeline configuration + */ +struct endpoint_hw_config { + int pipeline; + char card_name[44]; + char dev_name[44]; + char config_name[44]; + unsigned long buffer_frames; + unsigned long buffer_time; + unsigned long period_frames; + unsigned long period_time; + int rate; + int channels; + unsigned long format; +}; + +struct plug_shm_endpoint { + char magic[8]; /* SOF_MAGIC */ + uint64_t state; + uint32_t pipeline_id; + uint32_t comp_id; + uint32_t idx; + unsigned long rpos; /* current position in ring buffer */ + unsigned long rwrap; + unsigned long wpos; /* current position in ring buffer */ + unsigned long wwrap; + unsigned long buffer_size; /* buffer size */ + unsigned long wtotal; /* total frames copied */ + unsigned long rtotal; /* total frames copied */ + int frame_size; + char data[0]; // TODO: align this on SIMD/cache +}; + +struct plug_shm_glb_state { + char magic[8]; /* SOF_MAGIC */ + uint64_t size; /* size of this structure in bytes */ + uint64_t state; /* enum plugin_state */ + struct endpoint_hw_config ep_config[NUM_EP_CONFIGS]; + int num_ep_configs; + uint64_t num_ctls; /* number of ctls */ + struct plug_shm_ctl ctl[]; +}; + +struct plug_shm_desc { + /* SHM for stream context sync */ + int fd; + int size; + char name[NAME_SIZE]; + void *addr; +}; + +struct plug_socket_desc { + int socket_fd; + char path[NAME_SIZE]; +}; + +struct plug_sem_desc { + char name[NAME_SIZE]; + sem_t *sem; +}; + +struct plug_ctl_container { + struct snd_soc_tplg_ctl_hdr *tplg[MAX_CTLS]; + int updated[MAX_CTLS]; + int count; +}; + +static inline void *plug_ep_rptr(struct plug_shm_endpoint *ep) +{ + return ep->data + ep->rpos; +} + +static inline void *plug_ep_wptr(struct plug_shm_endpoint *ep) +{ + return ep->data + ep->wpos; +} + +static inline int plug_ep_wrap_rsize(struct plug_shm_endpoint *ep) +{ + return ep->buffer_size - ep->rpos; +} + +static inline int plug_ep_wrap_wsize(struct plug_shm_endpoint *ep) +{ + return ep->buffer_size - ep->wpos; +} + +static inline int plug_ep_get_free(struct plug_shm_endpoint *ep) +{ + if (ep->rwrap == ep->wwrap) { + /* calculate available bytes */ + if (ep->rpos < ep->wpos) + return ep->buffer_size - (ep->wpos - ep->rpos); + else + return ep->buffer_size; + } else { + return ep->rpos - ep->wpos; + } +} + +static inline int plug_ep_get_avail(struct plug_shm_endpoint *ep) +{ + if (ep->rwrap == ep->wwrap) { + /* calculate available bytes */ + if (ep->rpos < ep->wpos) + return ep->wpos - ep->rpos; + else + return 0; + } else { + return (ep->buffer_size - ep->rpos) + ep->wpos; + } +} + +static inline void *plug_ep_consume(struct plug_shm_endpoint *ep, unsigned int bytes) +{ + ep->rtotal += bytes; + ep->rpos += bytes; + + if (ep->rpos >= ep->buffer_size) { + ep->rpos -= ep->buffer_size; + ep->rwrap++; + } + + return ep->data + ep->rpos; +} + +static inline void *plug_ep_produce(struct plug_shm_endpoint *ep, unsigned int bytes) +{ + ep->wtotal += bytes; + ep->wpos += bytes; + + if (ep->wpos >= ep->buffer_size) { + ep->wpos -= ep->buffer_size; + ep->wwrap++; + } + + return ep->data + ep->wpos; +} + +/* + * SHM + */ +int plug_shm_init(struct plug_shm_desc *shm, const char *tplg, const char *type, int index); + +int plug_shm_create(struct plug_shm_desc *shm); + +int plug_shm_open(struct plug_shm_desc *shm); + +void plug_shm_free(struct plug_shm_desc *shm); + +/* + * IPC + */ +int plug_socket_path_init(struct plug_socket_desc *ipc, const char *tplg, const char *type, + int index); + +void plug_socket_free(struct plug_socket_desc *ipc); + +int plug_ipc_cmd_tx_rx(struct plug_socket_desc *ipc, void *msg, size_t len, void *reply, + size_t rlen); + +/* + * Locking + */ +int plug_lock_create(struct plug_sem_desc *lock); + +void plug_lock_free(struct plug_sem_desc *lock); + +int plug_lock_init(struct plug_sem_desc *lock, const char *tplg, const char *type, int index); + +int plug_lock_open(struct plug_sem_desc *lock); + +/* + * Timing. + */ +void plug_timespec_add_ms(struct timespec *ts, unsigned long ms); + +long plug_timespec_delta_ns(struct timespec *before, struct timespec *after); + +/* dump the IPC data - dont print lines of 0s */ +static inline void data_dump(void *vdata, size_t bytes) +{ + uint32_t *data = vdata; + size_t words = bytes >> 2; + int i; + + for (i = 0; i < words; i++) { + /* 4 words per line */ + if (i % 4 == 0) { + /* delete lines with all 0s */ + if (i > 0 && data[i - 3] == 0 && data[i - 2] == 0 && + data[i - 1] == 0 && data[i - 0] == 0) + printf("\r"); + else + printf("\n"); + + printf("0x%4.4x: 0x%8.8x", i, data[i]); + } else { + printf(" 0x%8.8x", data[i]); + } + } + printf("\n"); +} + +void plug_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, + size_t size, uint32_t module_id, uint32_t instance_id, + uint32_t type); +int plug_send_bytes_data(struct plug_socket_desc *ipc, uint32_t module_id, uint32_t instance_id, + struct sof_abi_hdr *abi); + +int plug_socket_create(struct plug_socket_desc *ipc); + +int plug_create_client_socket(struct plug_socket_desc *ipc); + +#endif diff --git a/tools/plugin/modules/CMakeLists.txt b/tools/plugin/modules/CMakeLists.txt new file mode 100644 index 000000000000..d737972cde7d --- /dev/null +++ b/tools/plugin/modules/CMakeLists.txt @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# File SHM pipe module +add_library(sof_mod_shm MODULE + shm.c +) +sof_append_relative_path_definitions(sof_mod_shm) +target_include_directories(sof_mod_shm PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../pipe + ${sof_source_directory}/src/audio) + +target_compile_options(sof_mod_shm PRIVATE -DPIC -g -O3 -Wall -Werror -DCONFIG_LIBRARY -imacros${config_h}) + +install(TARGETS sof_mod_shm + DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +target_link_options(sof_mod_shm PRIVATE -Wl,--export-dynamic) + +target_include_directories(sof_mod_shm PRIVATE ${sof_install_directory}/include) +target_include_directories(sof_mod_shm PRIVATE ${parser_install_dir}/include) + +set_target_properties(sof_mod_shm + PROPERTIES + INSTALL_RPATH "${sof_install_directory}/alsa-lib" + INSTALL_RPATH_USE_LINK_PATH TRUE +) + + +# ALSA SOF pipe module +add_library(sof_mod_alsa MODULE + alsa.c +) +sof_append_relative_path_definitions(sof_mod_alsa) +target_include_directories(sof_mod_alsa PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../pipe + ${sof_source_directory}/src/audio) + +target_compile_options(sof_mod_alsa PRIVATE -DPIC -g -O3 -Wmissing-prototypes + -Wimplicit-fallthrough -Wall -Werror -DCONFIG_LIBRARY -imacros${config_h}) + +install(TARGETS sof_mod_alsa + DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +target_link_options(sof_mod_alsa PRIVATE -Wl,--export-dynamic) + +target_include_directories(sof_mod_alsa PRIVATE ${sof_install_directory}/include) +target_include_directories(sof_mod_alsa PRIVATE ${parser_install_dir}/include) + +set_target_properties(sof_mod_alsa + PROPERTIES + INSTALL_RPATH "${sof_install_directory}/alsa-lib" + INSTALL_RPATH_USE_LINK_PATH TRUE +) + +add_subdirectory(ov_noise_suppression) diff --git a/tools/plugin/modules/alsa.c b/tools/plugin/modules/alsa.c new file mode 100644 index 000000000000..69442c687136 --- /dev/null +++ b/tools/plugin/modules/alsa.c @@ -0,0 +1,788 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +/* file component for reading/writing pcm samples to/from a file */ + +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <rtos/sof.h> +#include <sof/list.h> +#include <sof/audio/stream.h> +#include <sof/audio/ipc-config.h> +#include <sof/ipc/driver.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <ipc/stream.h> +#include <ipc/topology.h> +#include <ipc/dai.h> + +#include <alsa/asoundlib.h> + +#include "pipe.h" + +SOF_DEFINE_REG_UUID(arecord); +DECLARE_TR_CTX(arecord_tr, SOF_UUID(arecord_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(aplay); +DECLARE_TR_CTX(aplay_tr, SOF_UUID(aplay_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_arecord; +static const struct comp_driver comp_aplay; + +/* ALSA comp data */ +struct alsa_comp_data { + snd_pcm_t *handle; + snd_pcm_info_t *info; + snd_pcm_hw_params_t *hw_params; + snd_pcm_sw_params_t *sw_params; + snd_pcm_uframes_t period_frames; + snd_pcm_uframes_t buffer_frames; + char *pcm_name; + struct sof_ipc_stream_params params; + struct plug_shm_desc pcm; + struct plug_shm_endpoint *ctx; + struct plug_shm_desc glb; + struct plug_shm_glb_state *glb_ctx; + struct endpoint_hw_config *ep_hw; +#if CONFIG_IPC_MAJOR_4 + struct ipc4_base_module_cfg base_cfg; +#endif +}; + +static struct endpoint_hw_config *alsa_get_hw_config(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_glb_state *glb = cd->glb_ctx; + + if (!glb->num_ep_configs) + return NULL; + + return glb->ep_config; +} + +static int alsa_alloc(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + int err; + + /* get ALSA ready */ + err = snd_pcm_info_malloc(&cd->info); + if (err < 0) + goto error; + + err = snd_pcm_hw_params_malloc(&cd->hw_params); + if (err < 0) + goto error; + + err = snd_pcm_sw_params_malloc(&cd->sw_params); + if (err < 0) + goto error; + + comp_dbg(dev, "open done"); + return 0; + +error: + return err; +} + +static int alsa_close(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + int ret = 0; + + comp_dbg(dev, "close"); + if (cd->handle) { + ret = snd_pcm_hw_free(cd->handle); + if (ret < 0) + comp_err(dev, "error: failed to snd_pcm_hw_free: %s\n", snd_strerror(ret)); + + ret = snd_pcm_close(cd->handle); + if (ret < 0) + comp_err(dev, "error: failed to snd_pcm_close: %s\n", snd_strerror(ret)); + + cd->handle = NULL; + } + + return ret; +} + +static void alsa_free(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + + comp_dbg(dev, "alsa_free()"); + + snd_pcm_sw_params_free(cd->sw_params); + snd_pcm_hw_params_free(cd->hw_params); + snd_pcm_info_free(cd->info); + plug_shm_free(&cd->pcm); + free(cd); + free(dev); +} + +static struct comp_dev *alsa_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ +#if CONFIG_IPC_MAJOR_4 + const struct ipc4_base_module_cfg *base_cfg = (struct ipc4_base_module_cfg *)spec; +#endif + struct comp_dev *dev; + struct alsa_comp_data *cd; + int err; + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + /* allocate memory for file comp data */ + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) + goto error; + + comp_set_drvdata(dev, cd); + memcpy(&cd->base_cfg, base_cfg, sizeof(struct ipc4_base_module_cfg)); + + /* use PCM ID to create shm */ + err = plug_shm_init(&cd->pcm, _sp->topology_name, "pcm", 1); + if (err < 0) { + comp_err(dev, "Error initializing pcm\n"); + goto error; + } + + // TODO: get the shm size for the buffer using a better method + //cd->pcm.size = 128 * 1024; + + /* mmap the SHM PCM */ + err = plug_shm_open(&cd->pcm); + if (err < 0) { + comp_err(dev, "Error open pcm shm"); + goto error; + } + cd->ctx = cd->pcm.addr; + + err = plug_shm_init(&cd->glb, _sp->topology_name, "ctx", 0); + if (err < 0) { + comp_err(dev, "Error initializing ctx\n"); + goto error; + } + + // TODO: get the shm size for the buffer using a better method + //cd->pcm.size = 128 * 1024; + + /* mmap the GLB ctx */ + err = plug_shm_open(&cd->glb); + if (err < 0) { + comp_err(dev, "Error opening glb ctx\n"); + goto error; + } + cd->glb_ctx = cd->glb.addr; + + /* alloc alsa context */ + err = alsa_alloc(dev); + if (err < 0) { + comp_err(dev, "Error allocating alsa context\n"); + goto error; + } + + return dev; + +error: + free(cd); + free(dev); + return NULL; +} + +static struct comp_dev *arecord_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, const void *spec) +{ + struct comp_dev *dev; + struct alsa_comp_data *cd; + + comp_dbg(dev, "arecord_new()"); + + dev = alsa_new(drv, config, spec); + if (!dev) + return NULL; + + cd = comp_get_drvdata(dev); + cd->params.direction = SND_PCM_STREAM_CAPTURE; + + dev->state = COMP_STATE_READY; + return dev; +} + +static struct comp_dev *aplay_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev; + struct alsa_comp_data *cd; + + comp_dbg(dev, "aplay_new()"); + + dev = alsa_new(drv, config, spec); + if (!dev) + return NULL; + + cd = comp_get_drvdata(dev); + cd->params.direction = SND_PCM_STREAM_PLAYBACK; + + dev->state = COMP_STATE_READY; + return dev; +} + +static int set_params(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + struct sof_ipc_stream_params *params = &cd->params; + int frame_fmt; + int err; + + err = snd_pcm_open(&cd->handle, cd->pcm_name, cd->params.direction, 0); + if (err < 0) { + comp_err(dev, "error: cant open PCM %s: %s\n", cd->pcm_name, snd_strerror(err)); + return err; + } + + err = snd_pcm_info(cd->handle, cd->info); + if (err < 0) { + comp_err(dev, "error: cant get PCM info: %s\n", snd_strerror(err)); + return err; + } + + /* set sample format */ + switch (params->frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + frame_fmt = SND_PCM_FORMAT_S16_LE; + break; + case SOF_IPC_FRAME_S24_4LE: + frame_fmt = SND_PCM_FORMAT_S24_LE; + break; + case SOF_IPC_FRAME_S32_LE: + frame_fmt = SND_PCM_FORMAT_S32_LE; + break; + case SOF_IPC_FRAME_FLOAT: + frame_fmt = SND_PCM_FORMAT_FLOAT_LE; + break; + case SOF_IPC_FRAME_S24_3LE: + frame_fmt = SND_PCM_FORMAT_S24_3LE; + break; + default: + comp_err(dev, "error: invalid frame format %d for ALSA PCM\n", params->frame_fmt); + return -EINVAL; + } + + /* commit playback hw_params and sw_params. Set latency of 10ms to avoid glitches */ + if (cd->params.direction == SND_PCM_STREAM_PLAYBACK) + return snd_pcm_set_params(cd->handle, frame_fmt, SND_PCM_ACCESS_RW_INTERLEAVED, + params->channels, params->rate, 0, 10000); + + /* is sound card HW configuration valid ? */ + err = snd_pcm_hw_params_any(cd->handle, cd->hw_params); + if (err < 0) { + comp_err(dev, "error: cant get PCM hw_params: %s\n", snd_strerror(err)); + return err; + } + + /* set interleaved buffer format */ + err = snd_pcm_hw_params_set_access(cd->handle, cd->hw_params, + SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) { + comp_err(dev, "error: PCM can't set interleaved: %s\n", snd_strerror(err)); + return err; + } + + err = snd_pcm_hw_params_set_format(cd->handle, cd->hw_params, frame_fmt); + if (err < 0) { + comp_err(dev, "error: PCM can't set format %d: %s\n", + frame_fmt, snd_strerror(err)); + return err; + } + + /* set number of channels */ + err = snd_pcm_hw_params_set_channels(cd->handle, cd->hw_params, params->channels); + if (err < 0) { + comp_err(dev, "error: PCM can't set channels %d: %s\n", + params->channels, snd_strerror(err)); + return err; + } + + /* set sample rate */ + err = snd_pcm_hw_params_set_rate(cd->handle, cd->hw_params, params->rate, 0); + if (err < 0) { + comp_err(dev, "error: PCM can't set rate %d: %s\n", + params->rate, snd_strerror(err)); + return err; + } + + /* set period size TODO: get from topology */ + err = snd_pcm_hw_params_set_period_size(cd->handle, cd->hw_params, + cd->period_frames, 0); + if (err < 0) { + comp_err(dev, "error: PCM can't set period size %ld frames: %s\n", + cd->period_frames, snd_strerror(err)); + return err; + } + + /* set buffer size: TODO: get from topology */ + err = snd_pcm_hw_params_set_buffer_size_near(cd->handle, cd->hw_params, + &cd->buffer_frames); + if (err < 0) { + comp_err(dev, "error: PCM can't set buffer size %ld frames: %s\n", + cd->buffer_frames, snd_strerror(err)); + return err; + } + + /* commit the hw params */ + err = snd_pcm_hw_params(cd->handle, cd->hw_params); + if (err < 0) { + comp_err(dev, "error: PCM can't commit hw_params: %s\n", snd_strerror(err)); + snd_pcm_hw_params_dump(cd->hw_params, SND_OUTPUT_STDIO); + return err; + } + + /* get the initial SW params */ + err = snd_pcm_sw_params_current(cd->handle, cd->sw_params); + if (err < 0) { + comp_err(dev, "error: PCM can't get sw params: %s\n", snd_strerror(err)); + return err; + } + + /* set the avail min to the period size */ + err = snd_pcm_sw_params_set_avail_min(cd->handle, cd->sw_params, cd->period_frames); + if (err < 0) { + comp_err(dev, "error: PCM can't set avail min: %s\n", snd_strerror(err)); + return err; + } + + /* PCM should start after receiving first periods worth of data */ + err = snd_pcm_sw_params_set_start_threshold(cd->handle, cd->sw_params, 1); + if (err < 0) { + comp_err(dev, "error: PCM can't set start threshold: %s\n", snd_strerror(err)); + return err; + } + + /* PCM should stop if only buffer_frame worth of data is available */ + err = snd_pcm_sw_params_set_stop_threshold(cd->handle, cd->sw_params, + cd->buffer_frames); + if (err < 0) { + comp_err(dev, "error: PCM can't set stop threshold: %s\n", snd_strerror(err)); + return err; + } + + /* commit the sw params */ + if (snd_pcm_sw_params(cd->handle, cd->sw_params) < 0) { + comp_err(dev, "error: PCM can't commit sw_params: %s\n", snd_strerror(err)); + snd_pcm_sw_params_dump(cd->sw_params, SND_OUTPUT_STDIO); + return err; + } + + comp_dbg(dev, "params set"); + return 0; +} + +static int alsa_dai_get_hw_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir); + +/** + * \brief Sets file component audio stream parameters. + * \param[in,out] dev Volume base component device. + * \param[in] params Audio (PCM) stream parameters (ignored for this component) + * \return Error code. + * + * All done in prepare() since we need to know source and sink component params. + */ +static int arecord_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +{ + struct comp_buffer *buffer; + struct alsa_comp_data *cd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "arecord params"); + + ret = alsa_dai_get_hw_params(dev, params, cd->params.direction); + + if (params->direction != SND_PCM_STREAM_CAPTURE) { + comp_err(dev, "alsa_params(): pcm params invalid direction."); + return -EINVAL; + } + + /* params can be aligned to match pipeline here */ + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "alsa_params(): pcm params verification failed."); + return ret; + } + memcpy(&cd->params, params, sizeof(*params)); + + /* file component sink/source buffer period count */ + buffer = comp_dev_get_first_data_consumer(dev); + audio_buffer_reset(&buffer->audio_buffer); + + comp_dbg(dev, "prepare done ret = %d", ret); + + return 0; +} + +static int aplay_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +{ + struct comp_buffer *buffer; + struct alsa_comp_data *cd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "aplay params"); + + ret = alsa_dai_get_hw_params(dev, params, cd->params.direction); + + if (params->direction != SND_PCM_STREAM_PLAYBACK) { + comp_err(dev, "alsa_params(): pcm params invalid direction."); + return -EINVAL; + } + + /* params can be aligned to match pipeline here */ + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "alsa_params(): pcm params verification failed."); + return ret; + } + memcpy(&cd->params, params, sizeof(*params)); + + /* file component sink/source buffer period count */ + buffer = comp_dev_get_first_data_producer(dev); + audio_buffer_reset(&buffer->audio_buffer); + + comp_dbg(dev, "prepare done ret = %d", ret); + return 0; +} + +static int alsa_trigger(struct comp_dev *dev, int cmd) +{ + int err; + + /* trigger is handled automatically by ALSA start threshold */ + comp_dbg(dev, "trigger cmd %d", cmd); + + switch (cmd) { + case COMP_TRIGGER_PAUSE: + case COMP_TRIGGER_STOP: + err = alsa_close(dev); + if (err < 0) { + comp_err(dev, "error: cant stop pipeline"); + return err; + } + break; + case COMP_TRIGGER_RELEASE: + case COMP_TRIGGER_START: + err = set_params(dev); + if (err < 0) { + comp_err(dev, "error: cant stop pipeline"); + return err; + } + break; + default: + break; + } + + return comp_set_state(dev, cmd); +} + +/* used to pass standard and bespoke commands (with data) to component */ +static int alsa_cmd(struct comp_dev *dev, int cmd, void *data, + int max_data_size) +{ + return 0; +} + +/* + * copy and process stream samples + * returns the number of bytes copied + */ +static int arecord_copy(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *buffer; + struct audio_stream *sink; + snd_pcm_sframes_t frames; + snd_pcm_uframes_t free; + snd_pcm_uframes_t total = 0; + unsigned int frame_bytes; + void *pos; + + switch (dev->state) { + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + + /* file component sink buffer */ + buffer = comp_dev_get_first_data_consumer(dev); + sink = &buffer->stream; + pos = sink->w_ptr; + + //FIX: this will fill buffer and higher latency, use period size + free = MIN(audio_stream_get_free_frames(sink), cd->period_frames); + frame_bytes = audio_stream_frame_bytes(sink); + + while (free) { + frames = MIN(free, audio_stream_frames_without_wrap(sink, pos)); + + /* read PCM samples from file */ + frames = snd_pcm_readi(cd->handle, pos, frames); + if (frames < 0) { + if (frames == -EPIPE) { + snd_pcm_prepare(cd->handle); + continue; + } + comp_err(dev, "failed to read: %s: %s\n", + cd->pcm_name, snd_strerror(frames)); + return frames; + } + + free -= frames; + pos = audio_stream_wrap(sink, pos + frames * frame_bytes); + total += frames; + } + + /* update sink buffer pointers */ + comp_update_buffer_produce(buffer, total * frame_bytes); + comp_dbg(dev, "read %d frames", total); + + return 0; +} + +/* + * copy and process stream samples + * returns the number of bytes copied + */ +static int aplay_copy(struct comp_dev *dev) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + struct comp_buffer *buffer; + struct audio_stream *source; + snd_pcm_sframes_t frames; + snd_pcm_sframes_t avail; + snd_pcm_uframes_t total = 0; + unsigned int frame_bytes; + void *pos; + + switch (dev->state) { + case COMP_STATE_ACTIVE: + break; + default: + return -EINVAL; + } + + /* file component source buffer */ + buffer = comp_dev_get_first_data_producer(dev); + source = &buffer->stream; + pos = source->r_ptr; + avail = audio_stream_get_avail_frames(source); + frame_bytes = audio_stream_frame_bytes(source); + + while (avail > 0) { + frames = MIN(avail, audio_stream_frames_without_wrap(source, pos)); + + /* write PCM samples to PCM */ + frames = snd_pcm_writei(cd->handle, pos, frames); + if (frames < 0) { + if (frames == -EPIPE) { + snd_pcm_prepare(cd->handle); + continue; + } + comp_err(dev, "failed to write: %s: %s\n", + cd->pcm_name, snd_strerror(frames)); + return frames; + } + avail -= frames; + pos = audio_stream_wrap(source, pos + frames * frame_bytes); + total += frames; + } + + /* update sink buffer pointers */ + comp_update_buffer_consume(buffer, total * frame_bytes); + comp_dbg(dev, "wrote %d bytes", total * frame_bytes); + + return 0; +} + +static int alsa_prepare(struct comp_dev *dev) +{ + int ret = 0; + + comp_dbg(dev, "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 ret; +} + +static int alsa_reset(struct comp_dev *dev) +{ + comp_dbg(dev, "reset"); + + comp_set_state(dev, COMP_TRIGGER_RESET); + + return 0; +} + +/* + * TODO: we pass the DAI topology config back up the pipeline so + * that upstream/downstream can be configured. Needs to be configured + * at stream runtime instead of at topology load time. + */ +static int alsa_dai_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + struct endpoint_hw_config *ep_hw; + char pcm_name[128]; + + comp_dbg(dev, "get_hw_params"); + + /* get our hw config from cmdline and conf file */ + ep_hw = alsa_get_hw_config(dev); + if (!ep_hw) { + comp_err(dev, "error: failed to get hw config %d\n"); + return -EINVAL; + } + cd->ep_hw = ep_hw; + + /* PCM name comes from cmd line - "default" dev means dont use dev */ + if (!strncmp(cd->ep_hw->dev_name, "default", sizeof(cd->ep_hw->dev_name))) { + snprintf(pcm_name, sizeof(pcm_name), "%s", cd->ep_hw->card_name); + } else { + snprintf(pcm_name, sizeof(pcm_name), "hw:%s,%s", + cd->ep_hw->card_name, cd->ep_hw->dev_name); + } + cd->pcm_name = strdup(pcm_name); + comp_dbg(dev, "using ALSA card %s", cd->pcm_name); + + /* set default config - get from cmdline and plugin config */ + cd->params.rate = cd->ep_hw->rate; + cd->params.channels = cd->ep_hw->channels; + cd->buffer_frames = cd->ep_hw->buffer_frames; + cd->period_frames = cd->ep_hw->period_frames; + + /* ALSA API uses frames, SOF buffer uses bytes */ + switch (cd->ep_hw->format) { + case SND_PCM_FORMAT_S16_LE: + cd->params.frame_fmt = SOF_IPC_FRAME_S16_LE; + cd->params.buffer.size = cd->ep_hw->buffer_frames * 2; + break; + case SND_PCM_FORMAT_S24_LE: + cd->params.frame_fmt = SOF_IPC_FRAME_S24_4LE; + cd->params.buffer.size = cd->ep_hw->buffer_frames * 4; + break; + case SND_PCM_FORMAT_S32_LE: + cd->params.frame_fmt = SOF_IPC_FRAME_S32_LE; + cd->params.buffer.size = cd->ep_hw->buffer_frames * 4; + break; + case SND_PCM_FORMAT_FLOAT: + cd->params.frame_fmt = SOF_IPC_FRAME_FLOAT; + cd->params.buffer.size = cd->ep_hw->buffer_frames * 4; + break; + case SND_PCM_FORMAT_S24_3LE: + cd->params.frame_fmt = SOF_IPC_FRAME_S24_3LE; + cd->params.buffer.size = cd->ep_hw->buffer_frames * 3; + break; + default: + comp_err(dev, "error: invalid frame format %d for ALSA PCM\n", params->frame_fmt); + return -EINVAL; + } + + memcpy(params, &cd->params, sizeof(*params)); + + comp_dbg(dev, "rate %d", params->rate); + comp_dbg(dev, "frame format %d", params->frame_fmt); + comp_dbg(dev, "channels %d", params->channels); + comp_dbg(dev, "buffer frames %d", cd->buffer_frames); + comp_dbg(dev, "period frames %d", cd->period_frames); + comp_dbg(dev, "direction %d", params->direction); + + return 0; +} + +static int alsa_get_attribute(struct comp_dev *dev, uint32_t type, void *value) +{ + struct alsa_comp_data *cd = comp_get_drvdata(dev); + + switch (type) { + case COMP_ATTR_BASE_CONFIG: + memcpy_s(value, sizeof(struct ipc4_base_module_cfg), + &cd->base_cfg, sizeof(struct ipc4_base_module_cfg)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct comp_driver comp_arecord = { + .type = SOF_COMP_FILEREAD, + .uid = SOF_RT_UUID(arecord_uuid), + .tctx = &arecord_tr, + .ops = { + .create = arecord_new, + .free = alsa_free, + .params = arecord_params, + .cmd = alsa_cmd, + .trigger = alsa_trigger, + .copy = arecord_copy, + .prepare = alsa_prepare, + .reset = alsa_reset, + .dai_get_hw_params = alsa_dai_get_hw_params, + .get_attribute = alsa_get_attribute, + }, +}; + +static const struct comp_driver comp_aplay = { + .type = SOF_COMP_FILEWRITE, + .uid = SOF_RT_UUID(aplay_uuid), + .tctx = &aplay_tr, + .ops = { + .create = aplay_new, + .free = alsa_free, + .params = aplay_params, + .cmd = alsa_cmd, + .trigger = alsa_trigger, + .copy = aplay_copy, + .prepare = alsa_prepare, + .reset = alsa_reset, + .dai_get_hw_params = alsa_dai_get_hw_params, + .get_attribute = alsa_get_attribute, + }, +}; + +static struct comp_driver_info comp_arecord_info = { + .drv = &comp_arecord, +}; + +static struct comp_driver_info comp_aplay_info = { + .drv = &comp_aplay, +}; + +static void sys_comp_alsa_init(void) +{ + comp_register(&comp_arecord_info); + comp_register(&comp_aplay_info); +} + +DECLARE_MODULE(sys_comp_alsa_init); diff --git a/tools/plugin/modules/ov_noise_suppression/CMakeLists.txt b/tools/plugin/modules/ov_noise_suppression/CMakeLists.txt new file mode 100644 index 000000000000..039e9056ee45 --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/CMakeLists.txt @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Noise suppression module +find_package(OpenVINO COMPONENTS Runtime) + +if(OpenVINO_FOUND) +add_library(sof_ns_interface STATIC noise_suppression_interface.cpp) +target_link_libraries(sof_ns_interface PRIVATE -Wl,--export-dynamic) +target_link_libraries(sof_ns_interface PRIVATE openvino::runtime) +target_compile_options(sof_ns_interface PRIVATE -fPIC) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/src/include) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/posix/include) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/src/arch/host/include) +target_include_directories(sof_ns_interface PRIVATE ${sof_source_directory}/src/platform/posix/include) +set_target_properties(sof_ns_interface PROPERTIES LINKER_LANGUAGE CXX) +sof_append_relative_path_definitions(sof_ns_interface) +install(TARGETS sof_ns_interface DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +add_library(sof_ns MODULE noise_suppression.c) +target_link_libraries(sof_ns PRIVATE sof_ns_interface) +target_link_libraries(sof_ns PRIVATE -Wl,--export-dynamic) +sof_append_relative_path_definitions(sof_ns) +target_compile_options(sof_ns PRIVATE -DPIC -g -O3 -Wall -Werror -DCONFIG_LIBRARY -imacros${config_h}) +install(TARGETS sof_ns DESTINATION /usr/lib/x86_64-linux-gnu/alsa-lib) + +target_include_directories(sof_ns PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../pipe + ${sof_source_directory}/src/audio) + + +target_link_options(sof_ns PRIVATE -Wl,--export-dynamic) +target_include_directories(sof_ns PRIVATE ${sof_install_directory}/include) +target_include_directories(sof_ns PRIVATE ${parser_install_dir}/include) + +set_target_properties(sof_ns + PROPERTIES + INSTALL_RPATH "${sof_install_directory}/alsa-lib" + INSTALL_RPATH_USE_LINK_PATH TRUE +) +endif() diff --git a/tools/plugin/modules/ov_noise_suppression/noise_suppression.c b/tools/plugin/modules/ov_noise_suppression/noise_suppression.c new file mode 100644 index 000000000000..84ed62ab394c --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/noise_suppression.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +#include <sof/audio/buffer.h> +#include <sof/audio/format.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/pipeline.h> +#include <rtos/panic.h> +#include <sof/ipc/msg.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <rtos/init.h> +#include <sof/lib/memory.h> +#include <sof/lib/notifier.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <rtos/string.h> +#include <sof/ut.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +#include "noise_suppression_interface.h" + +LOG_MODULE_REGISTER(ns, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(ns); + +DECLARE_TR_CTX(ns_comp_tr, SOF_UUID(ns_uuid), LOG_LEVEL_INFO); + +static int ns_free(struct processing_module *mod) +{ + ns_handle handle = module_get_private_data(mod); + + ov_ns_free(handle); + return 0; +} + +static int ns_init(struct processing_module *mod) +{ + struct module_data *mod_data = &mod->priv; + + return ov_ns_init(&mod_data->private); +} + +static int +ns_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) +{ + ns_handle handle = module_get_private_data(mod); + int ret; + + ret = ov_ns_process(handle, input_buffers, num_input_buffers, + output_buffers, num_output_buffers); + if (ret < 0) + return ret; + + module_update_buffer_position(&input_buffers[0], &output_buffers[0], ret); + + return 0; +} + +static const struct module_interface ns_interface = { + .init = ns_init, + .process_audio_stream = ns_process, + .free = ns_free +}; + +DECLARE_MODULE_ADAPTER(ns_interface, ns_uuid, ns_comp_tr); +SOF_MODULE_INIT(ns, sys_comp_module_ns_interface_init); diff --git a/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.cpp b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.cpp new file mode 100644 index 000000000000..fa74736d062f --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.cpp @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + + +#include <stddef.h> +#include <module/module/interface.h> +#include <sof/audio/audio_stream.h> +#include <openvino/openvino.hpp> + +#include "noise_suppression_interface.h" +#define NS_MAX_SOURCE_CHANNELS 2 + +extern "C" { + struct ns_data { + std::shared_ptr<ov::Model> model; + std::vector<std::pair<std::string, std::string>> state_names; + ov::InferRequest infer_request[NS_MAX_SOURCE_CHANNELS]; + ov::Shape inp_shape; + int iter; + }; + + int ov_ns_init(ns_handle *handle) { + struct ns_data *nd; + ov::OutputVector inputs, outputs; + ov::Core core; + size_t state_size = 0; + const char* model_name = std::getenv("NOISE_SUPPRESSION_MODEL_NAME"); + std::string device("CPU"); + int i; + + nd = new ns_data(); + if(!nd) + return -ENOMEM; + + *handle = nd; + nd->model = core.read_model(model_name); + inputs = nd->model->inputs(); + outputs = nd->model->outputs(); + + /* get state name pairs */ + for (size_t i = 0; i < inputs.size(); i++) { + std::string inp_state_name = inputs[i].get_any_name(); + if (inp_state_name.find("inp_state_") == std::string::npos) + continue; + + std::string out_state_name(inp_state_name); + out_state_name.replace(0, 3, "out"); + + /* find corresponding output state */ + if (outputs.end() == std::find_if(outputs.begin(), outputs.end(), [&out_state_name](const ov::Output<ov::Node>& output) { + return output.get_any_name() == out_state_name; + })) + return -EINVAL; + + nd->state_names.emplace_back(inp_state_name, out_state_name); + + ov::Shape shape = inputs[i].get_shape(); + size_t tensor_size = std::accumulate(shape.begin(), shape.end(), 1, + std::multiplies<size_t>()); + + state_size += tensor_size; + } + + if (!state_size) + return -EINVAL; + + /* + * query the list of available devices and use NPU if available, otherwise use + * CPU by default + */ + std::vector<std::string> available_devices = core.get_available_devices(); + for (auto &s: available_devices) { + if (!s.compare("NPU")) { + device.assign("NPU"); + break; + } + } + + /* save the infer_request objects for each channel separately */ + ov::CompiledModel compiled_model = core.compile_model(nd->model, device, {}); + for (i = 0; i < NS_MAX_SOURCE_CHANNELS; i++) + nd->infer_request[i] = compiled_model.create_infer_request(); + + nd->inp_shape = nd->model->input("input").get_shape(); + + return 0; + } + + void ov_ns_free(ns_handle handle) { + struct ns_data *nd = (struct ns_data *)handle; + + delete nd; + } + + int ov_ns_process(ns_handle handle, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, int num_output_buffers) + { + struct audio_stream *source = (struct audio_stream *)input_buffers[0].data; + struct audio_stream *sink = (struct audio_stream *)output_buffers[0].data; + struct ns_data *nd = (struct ns_data *)handle; + std::vector<float> inp_wave_fp32, out_wave_fp32; + /* only 16-bit supported for now */ + int16_t *input_data = (int16_t *)audio_stream_get_rptr(source); + int16_t *output_data = (int16_t *)audio_stream_get_wptr(sink); + uint32_t frame_count = input_buffers[0].size; + float scale = 1.0f / std::numeric_limits<int16_t>::max(); + int i, j, ch; + + /* + * The noise suppression model only supports mono, so process each channel + * separately + */ + inp_wave_fp32.resize(frame_count, 0); + out_wave_fp32.resize(frame_count, 0); + + for (ch = 0; ch < NS_MAX_SOURCE_CHANNELS; ch++) { + /* split each channel samples and convert to floating point */ + for (i = ch, j = 0; j < frame_count; i+=2,j++) { + void *inp = &input_data[i]; + + /* wrap if needed */ + if (inp >= source->end_addr) + inp = (char *)source->addr + + ((char *)inp - (char *)source->end_addr); + + inp_wave_fp32[j] = (float)(*(int16_t *)inp) * scale; + } + + ov::Tensor input_tensor(ov::element::f32, nd->inp_shape, + &inp_wave_fp32[0]); + nd->infer_request[ch].set_tensor("input", input_tensor); + + for (auto& state_name: nd->state_names) { + const std::string& inp_state_name = state_name.first; + const std::string& out_state_name = state_name.second; + ov::Tensor state_tensor; + ov::Shape state_shape; + + state_shape = nd->model->input(inp_state_name).get_shape(); + if (nd->iter > 0) { + /* + * set input state by corresponding output state from prev + * infer + */ + state_tensor = + nd->infer_request[ch].get_tensor(out_state_name); + } else { + state_tensor = ov::Tensor(ov::element::f32, state_shape); + std::memset(state_tensor.data<float>(), 0, + state_tensor.get_byte_size()); + } + nd->infer_request[ch].set_tensor(inp_state_name, state_tensor); + } + nd->infer_request[ch].infer(); + + /* process output */ + float* src = nd->infer_request[ch].get_tensor("output").data<float>(); + float* dst = &out_wave_fp32[0]; + std::memcpy(dst, src, frame_count * sizeof(float)); + + /* convert back to int and write back to output buffer */ + for (i = 0, j = ch; i < frame_count; i++,j+=2) { + float v = out_wave_fp32[i]; + void *out = &output_data[j]; + + /* wrap if needed */ + if (out >= sink->end_addr) + out = (char *)sink->addr + + ((char *)out - (char *)sink->end_addr); + + v = std::clamp(v, -1.0f, +1.0f); + *(int16_t *)out = (int16_t)(v * std::numeric_limits<int16_t>::max()); + } + } + + nd->iter++; + + /* return frame_count so the input and output buffers can be updated accordingly */ + return frame_count; + } +} /* extern "C" */ + diff --git a/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.h b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.h new file mode 100644 index 000000000000..5005e1f58161 --- /dev/null +++ b/tools/plugin/modules/ov_noise_suppression/noise_suppression_interface.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + * + */ + +#ifndef _NOISE_SUPPRESSION_INTERFACE_H +#define _NOISE_SUPPRESSION_INTERFACE_H + +#ifdef __cplusplus +extern "C" { +#endif + typedef void *ns_handle; + int ov_ns_init(ns_handle *handle); + void ov_ns_free(ns_handle handle); + int ov_ns_process(ns_handle handle, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, int num_output_buffers); + +#ifdef __cplusplus +} +#endif + +#endif /*_NOISE_SUPPRESSION_INTERFACE_H */ diff --git a/tools/plugin/modules/shm.c b/tools/plugin/modules/shm.c new file mode 100644 index 000000000000..0ddf297adcd1 --- /dev/null +++ b/tools/plugin/modules/shm.c @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +/* shm component for reading/writing pcm samples to/from a shm */ + +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <semaphore.h> + +#include <rtos/sof.h> +#include <sof/list.h> +#include <sof/audio/stream.h> +#include <sof/audio/ipc-config.h> +#include <sof/ipc/driver.h> +#include <sof/audio/component.h> +#include <sof/audio/format.h> +#include <sof/audio/pipeline.h> +#include <ipc/stream.h> +#include <ipc/topology.h> + +#include "pipe.h" + +SOF_DEFINE_REG_UUID(shmread); +DECLARE_TR_CTX(shmread_tr, SOF_UUID(shmread_uuid), LOG_LEVEL_INFO); + +SOF_DEFINE_REG_UUID(shmwrite); +DECLARE_TR_CTX(shmwrite_tr, SOF_UUID(shmwrite_uuid), LOG_LEVEL_INFO); + +static const struct comp_driver comp_shmread; +static const struct comp_driver comp_shmwrite; + +/* shm comp data */ +struct shm_comp_data { + /* PCM data */ + struct plug_shm_desc pcm; + struct plug_shm_endpoint *ctx; +#if CONFIG_IPC_MAJOR_4 + struct ipc4_base_module_cfg base_cfg; +#endif +}; + +static int shm_process_new(struct comp_dev *dev, + const struct comp_ipc_config *config, + const void *spec) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx; + int ret; + + comp_dbg(dev, "shm new()"); + + /* FIXME: use PCM ID to create shm */ + ret = plug_shm_init(&cd->pcm, _sp->topology_name, "pcm", 1); + if (ret < 0) + return ret; + + // TODO: get the shm size for the buffer using a better method + cd->pcm.size = 128 * 1024; + + /* mmap the SHM PCM */ + ret = plug_shm_create(&cd->pcm); + if (ret < 0) + return ret; + + cd->ctx = cd->pcm.addr; + ctx = cd->ctx; + ctx->buffer_size = cd->pcm.size; + memset(ctx, 0, sizeof(*ctx)); + ctx->comp_id = config->id; + ctx->pipeline_id = config->pipeline_id; + ctx->state = SOF_PLUGIN_STATE_INIT; + dev->state = COMP_STATE_READY; + + return 0; +} + +static void shm_free(struct comp_dev *dev) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + + cd->ctx = NULL; + + plug_shm_free(&cd->pcm); + shm_unlink(cd->pcm.name); + + free(cd); + free(dev); +} + +static struct comp_dev *shm_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec, int direction) +{ + struct comp_dev *dev; +#if CONFIG_IPC_MAJOR_4 + const struct ipc4_base_module_cfg *base_cfg = (struct ipc4_base_module_cfg *)spec; +#endif + struct shm_comp_data *cd; + int err; + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + /* allocate memory for shm comp data */ + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + if (!cd) + goto error; + + comp_set_drvdata(dev, cd); + memcpy(&cd->base_cfg, base_cfg, sizeof(struct ipc4_base_module_cfg)); + + dev->direction = direction; + err = shm_process_new(dev, config, spec); + if (err < 0) { + free(cd); + free(dev); + return NULL; + } + dev->direction_set = true; + + dev->state = COMP_STATE_READY; + return dev; + +error: + free(dev); + return NULL; +} + +static struct comp_dev *shmwrite_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + return shm_new(drv, config, spec, SOF_IPC_STREAM_PLAYBACK); +} + +static struct comp_dev *shmread_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + return shm_new(drv, config, spec, SOF_IPC_STREAM_CAPTURE); +} + +/** + * \brief Sets shm component audio stream parameters. + * \param[in,out] dev Volume base component device. + * \param[in] params Audio (PCM) stream parameters (ignored for this component) + * \return Error code. + * + * All done in prepare() since we need to know source and sink component params. + */ +static int shmread_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + int ret; + +#if CONFIG_IPC_MAJOR_4 + ipc4_base_module_cfg_to_stream_params(&cd->base_cfg, params); +#endif + + comp_err(dev, "forme_fmt %d channels %d", params->frame_fmt, params->channels); + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "shm_params(): pcm params verification failed."); + return ret; + } + ctx->state = SOF_PLUGIN_STATE_READY; + + return 0; +} + +static int shmwrite_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + int ret; + + ret = comp_verify_params(dev, 0, params); + if (ret < 0) { + comp_err(dev, "shm_params(): pcm params verification failed."); + return ret; + } + ctx->state = SOF_PLUGIN_STATE_READY; + + return 0; +} + +static int shm_trigger(struct comp_dev *dev, int cmd) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + + comp_dbg(dev, "shm_trigger(%d)", cmd); + + switch (cmd) { + case COMP_TRIGGER_START: + case COMP_TRIGGER_RELEASE: + ctx->state = SOF_PLUGIN_STATE_STREAM_RUNNING; + break; + case COMP_TRIGGER_STOP: + case COMP_TRIGGER_PAUSE: + ctx->state = SOF_PLUGIN_STATE_READY; + break; + case COMP_TRIGGER_RESET: + ctx->state = SOF_PLUGIN_STATE_INIT; + break; + case COMP_TRIGGER_XRUN: + ctx->state = SOF_PLUGIN_STATE_STREAM_ERROR; + break; + default: + break; + } + + return comp_set_state(dev, cmd); +} + +static int shm_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_size) +{ + return 0; +} + +/* + * copy from local SOF buffer to remote SHM buffer + */ +static int shmread_copy(struct comp_dev *dev) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + struct comp_buffer *buffer; + struct audio_stream *source; + unsigned int copy_bytes; + unsigned int remaining; + unsigned int total = 0; + void *rptr; + void *dest; + + /* local SOF source buffer */ + buffer = comp_dev_get_first_data_producer(dev); + source = &buffer->stream; + rptr = source->r_ptr; + + /* remote SHM sink buffer */ + dest = plug_ep_wptr(ctx); + + /* maximum byte count that can be copied this iteration */ + remaining = MIN(audio_stream_get_avail_bytes(source), plug_ep_get_free(ctx)); + + while (remaining) { + /* min bytes from source pipe */ + copy_bytes = MIN(remaining, plug_ep_wrap_wsize(ctx)); + + /* min bytes from source and sink */ + copy_bytes = MIN(copy_bytes, audio_stream_bytes_without_wrap(source, rptr)); + + /* anything to copy ? */ + if (copy_bytes == 0) + break; + + /* copy to local buffer from SHM buffer */ + memcpy(dest, rptr, copy_bytes); + + /* update SHM pointer with wrap */ + dest = plug_ep_produce(ctx, copy_bytes); + + /* update local pointers */ + rptr = audio_stream_wrap(source, rptr + copy_bytes); + + /* update avail and totals */ + remaining -= copy_bytes; + total += copy_bytes; + } + + /* update sink buffer pointers */ + comp_update_buffer_consume(buffer, total); + comp_dbg(dev, "wrote %d bytes", total); + + return 0; +} + +/* + * copy to local SOF buffer from remote SHM buffer + */ +static int shmwrite_copy(struct comp_dev *dev) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + struct comp_buffer *buffer; + struct audio_stream *sink; + unsigned int copy_bytes; + unsigned int remaining; + unsigned int total = 0; + void *wptr; + void *src; + + /* local SOF sink buffer */ + buffer = comp_dev_get_first_data_consumer(dev); + sink = &buffer->stream; + wptr = sink->w_ptr; + + /* remote SHM source buffer */ + src = plug_ep_rptr(ctx); + + /* maximum byte count that can be copied this iteration */ + remaining = MIN(audio_stream_get_free_bytes(sink), plug_ep_get_avail(ctx)); + + while (remaining > 0) { + /* min bytes free bytes in local sink */ + copy_bytes = MIN(remaining, plug_ep_wrap_rsize(ctx)); + + /* min bytes to wrap */ + copy_bytes = MIN(copy_bytes, audio_stream_bytes_without_wrap(sink, wptr)); + + /* nothing to copy ? */ + if (copy_bytes == 0) + break; + + /* copy to SHM from local buffer */ + memcpy(wptr, src, copy_bytes); + + /* update local pointers */ + wptr = audio_stream_wrap(sink, wptr + copy_bytes); + + /* update SHM pointer with wrap */ + src = plug_ep_consume(ctx, copy_bytes); + + /* update avail and totals */ + remaining -= copy_bytes; + total += copy_bytes; + } + + /* update sink buffer pointers */ + comp_update_buffer_produce(buffer, total); + comp_dbg(dev, "read %d bytes", total); + + return 0; +} + +static int shm_prepare(struct comp_dev *dev) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + int ret = 0; + + comp_dbg(dev, "shm prepare_copy()"); + + ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + if (ret < 0) + return ret; + + ctx->state = SOF_PLUGIN_STATE_READY; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return ret; +} + +static int shm_reset(struct comp_dev *dev) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + struct plug_shm_endpoint *ctx = cd->ctx; + + comp_set_state(dev, COMP_TRIGGER_RESET); + ctx->state = SOF_PLUGIN_STATE_INIT; + + return 0; +} + +int shm_get_attribute(struct comp_dev *dev, uint32_t type, void *value) +{ + struct shm_comp_data *cd = comp_get_drvdata(dev); + + switch (type) { + case COMP_ATTR_BASE_CONFIG: + memcpy_s(value, sizeof(struct ipc4_base_module_cfg), + &cd->base_cfg, sizeof(struct ipc4_base_module_cfg)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct comp_driver comp_shmread = { + .type = SOF_COMP_HOST, + .uid = SOF_RT_UUID(shmread_uuid), + .tctx = &shmread_tr, + .ops = { + .create = shmread_new, + .free = shm_free, + .params = shmread_params, + .cmd = shm_cmd, + .trigger = shm_trigger, + .copy = shmread_copy, + .prepare = shm_prepare, + .reset = shm_reset, + .get_attribute = shm_get_attribute, + }, +}; + +static const struct comp_driver comp_shmwrite = { + .type = SOF_COMP_HOST, + .uid = SOF_RT_UUID(shmwrite_uuid), + .tctx = &shmwrite_tr, + .ops = { + .create = shmwrite_new, + .free = shm_free, + .params = shmwrite_params, + .cmd = shm_cmd, + .trigger = shm_trigger, + .copy = shmwrite_copy, + .prepare = shm_prepare, + .reset = shm_reset, + .get_attribute = shm_get_attribute, + }, +}; + +static struct comp_driver_info comp_shmread_info = { + .drv = &comp_shmread, +}; + +static struct comp_driver_info comp_shmwrite_info = { + .drv = &comp_shmwrite, +}; + +static void sys_comp_shm_init(void) +{ + comp_register(&comp_shmread_info); + comp_register(&comp_shmwrite_info); +} + +DECLARE_MODULE(sys_comp_shm_init); diff --git a/tools/plugin/pipe/CMakeLists.txt b/tools/plugin/pipe/CMakeLists.txt new file mode 100644 index 000000000000..244fb3199e38 --- /dev/null +++ b/tools/plugin/pipe/CMakeLists.txt @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_executable(sof-pipe + main.c + cpu.c + pipeline.c + ipc4.c + ../common.c +) + +sof_append_relative_path_definitions(sof-pipe) + +target_include_directories(sof-pipe PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${sof_source_directory}/src/audio) + +target_compile_options(sof-pipe PRIVATE -DPIC -g -O3 -Wall -Werror -Wno-stringop-truncation -DCONFIG_LIBRARY -imacros${config_h}) + +target_include_directories(sof-pipe PRIVATE ${sof_install_directory}/include) +target_include_directories(sof-pipe PRIVATE ${parser_install_dir}/include) + +target_link_libraries(sof-pipe PRIVATE -Wl,-whole-archive sof_library -Wl,-no-whole-archive) +target_link_libraries(sof-pipe PRIVATE sof_parser_lib) +target_link_libraries(sof-pipe PRIVATE pthread) +target_link_libraries(sof-pipe PRIVATE -rdynamic -lasound -ldl -lm -lasound -lrt) diff --git a/tools/plugin/pipe/cpu.c b/tools/plugin/pipe/cpu.c new file mode 100644 index 000000000000..ea7e5d0645e2 --- /dev/null +++ b/tools/plugin/pipe/cpu.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + +/* + * SOF pipeline in userspace. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <assert.h> +#include <errno.h> +#include <pthread.h> +#include <limits.h> +#include <dlfcn.h> + +#include "common.h" +#include "pipe.h" + +/* read the CPU ID register data on x86 */ +static inline void x86_cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + /* data type is passed in on eax (and sometimes ecx) */ + asm volatile("cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (*eax), "2" (*ecx)); +} + +/* + * Check core type for E cores. If non hybrid then it does not matter. + */ +static inline int use_this_core(struct sof_pipe *sp) +{ + /* CPUID - set eax to 0x1a for hybrid core types */ + unsigned int eax = 0x1a, ebx = 0, ecx = 0, edx = 0; + char core_mask; + + /* get the processor core type we are running on now */ + x86_cpuid(&eax, &ebx, &ecx, &edx); + + /* core type 0x20 is atom, 0x40 is core */ + core_mask = (eax >> 24) & 0xFF; + switch (core_mask) { + case 0x20: + fprintf(sp->log, "found E core\n"); + if (sp->use_E_core) + return 1; + return 0; + case 0x40: + fprintf(sp->log, "found P core\n"); + if (sp->use_P_core) + return 1; + return 0; + default: + /* non hybrid arch, just use first core */ + fprintf(sp->log, "found non hybrid core topology\n"); + return 1; + } +} + +/* sof-pipe needs to be sticky to the current core for low latency */ +int pipe_set_affinity(struct sof_pipe *sp) +{ + cpu_set_t cpuset; + pthread_t thread; + long core_count = sysconf(_SC_NPROCESSORS_ONLN); + int i; + int err; + + /* Set affinity mask to core */ + thread = pthread_self(); + CPU_ZERO(&cpuset); + + /* find the first E core (usually come after the P cores ?) */ + for (i = core_count - 1; i >= 0; i--) { + CPU_ZERO(&cpuset); + CPU_SET(i, &cpuset); + + /* change our core to i */ + err = pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset); + if (err != 0) { + fprintf(sp->log, "error: failed to set CPU affinity to core %d: %s\n", + i, strerror(err)); + return err; + } + + /* should we use this core ? */ + if (use_this_core(sp)) + break; + } + + return 0; +} + +/* set ipc thread to low priority */ +int pipe_set_ipc_lowpri(struct sof_pipe *sp) +{ + pthread_attr_t attr; + struct sched_param param; + int err; + + /* attempt to set thread priority - needs suid */ + fprintf(sp->log, "pipe: set IPC low priority\n"); + + err = pthread_attr_init(&attr); + if (err < 0) { + fprintf(sp->log, "error: can't create thread attr %d %s\n", err, strerror(errno)); + return err; + } + + err = pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + if (err < 0) { + fprintf(sp->log, "error: can't set thread policy %d %s\n", err, strerror(errno)); + return err; + } + param.sched_priority = 0; + err = pthread_attr_setschedparam(&attr, ¶m); + if (err < 0) { + fprintf(sp->log, "error: can't set thread sched param %d %s\n", + err, strerror(errno)); + return err; + } + + return 0; +} + +/* set pipeline to realtime priority */ +int pipe_set_rt(struct sof_pipe *sp) +{ + pthread_attr_t attr; + struct sched_param param; + int err; + uid_t uid = getuid(); + uid_t euid = geteuid(); + + /* do we have elevated privileges to attempt RT priority */ + if (uid < 0 || uid != euid) { + /* attempt to set thread priority - needs suid */ + fprintf(sp->log, "pipe: set RT priority\n"); + + err = pthread_attr_init(&attr); + if (err < 0) { + fprintf(sp->log, "error: can't create thread attr %d %s\n", + err, strerror(errno)); + return err; + } + + err = pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + if (err < 0) { + fprintf(sp->log, "error: can't set thread policy %d %s\n", + err, strerror(errno)); + return err; + } + param.sched_priority = 80; + err = pthread_attr_setschedparam(&attr, ¶m); + if (err < 0) { + fprintf(sp->log, "error: can't set thread sched param %d %s\n", + err, strerror(errno)); + return err; + } + err = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + if (err < 0) { + fprintf(sp->log, "error: can't set thread inherit %d %s\n", + err, strerror(errno)); + return err; + } + } else { + fprintf(sp->log, "error: no elevated privileges for RT. uid %d euid %d\n", + uid, euid); + } + + return 0; +} diff --git a/tools/plugin/pipe/ipc4.c b/tools/plugin/pipe/ipc4.c new file mode 100644 index 000000000000..90157971d05e --- /dev/null +++ b/tools/plugin/pipe/ipc4.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + +/* + * SOF pipeline in userspace. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <pthread.h> +#include <limits.h> +#include <getopt.h> +#include <dlfcn.h> + +#include <rtos/sof.h> +#include <rtos/task.h> +#include <sof/lib/notifier.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/topology.h> +#include <sof/lib/agent.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/schedule.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component.h> +#include <sof/audio/component_ext.h> + +#include "common.h" +#include "pipe.h" + +// TODO: take prefix from ALSA prefix +#define COMP_PREFIX "./sof_ep/install/lib/libsof_" +#define COMP_SUFFIX ".so" +#define UUID_STR_SIZE 32 + +struct sof_pipe_module_library_map { + int module_id; + const char *name; +}; + +static const struct sof_pipe_module_library_map library_map[] = { + {0x6, "libsof_volume.so"}, + {0x2, "libsof_mixer.so"}, + {0x3, "libsof_mixer.so"}, + {0x95, "libsof_ns.so"}, + /*FIXME: hack for now to set up ALSA and SHM components */ + {0x96, "libsof_mod_shm.so"}, /* host playback */ + {0x97, "libsof_mod_alsa.so"}, /* dai playback */ + {0x98, "libsof_mod_shm.so"}, /* host capture */ + {0x99, "libsof_mod_alsa.so"}, /* dai capture */ +}; + +static int pipe_register_comp(struct sof_pipe *sp, uint16_t module_id) +{ + const struct sof_pipe_module_library_map *lib; + int i; + + /* check if module already loaded */ + for (i = 0; i < sp->mod_idx; i++) { + if (sp->module[i].module_id == module_id) + return 0; /* module found and already loaded */ + } + + for (i = 0; i < ARRAY_SIZE(library_map); i++) { + lib = &library_map[i]; + + if (module_id == lib->module_id) + break; + } + + if (i == ARRAY_SIZE(library_map)) { + fprintf(stderr, "module ID: %d not supported\n", module_id); + return -ENOTSUP; + } + + /* not loaded, so load module */ + sp->module[sp->mod_idx].handle = dlopen(lib->name, RTLD_NOW); + if (!sp->module[sp->mod_idx].handle) { + fprintf(stderr, "error: cant load module %s: %s\n", + lib->name, dlerror()); + return -errno; + } + + sp->mod_idx++; + + return 0; +} + +#define iCS(x) ((x) & SOF_CMD_TYPE_MASK) +#define iGS(x) ((x) & SOF_GLB_TYPE_MASK) + +static int pipe_sof_ipc_cmd_before(struct sof_pipe *sp, void *mailbox, size_t bytes) +{ + struct ipc4_message_request *in = mailbox; + enum ipc4_message_target target = in->primary.r.msg_tgt; + int ret = 0; + + switch (target) { + case SOF_IPC4_MESSAGE_TARGET_MODULE_MSG: + { + uint32_t type = in->primary.r.type; + + switch (type) { + case SOF_IPC4_MOD_INIT_INSTANCE: + { + struct ipc4_module_init_instance *module_init = + (struct ipc4_module_init_instance *)in; + + ret = pipe_register_comp(sp, module_init->primary.r.module_id); + break; + } + default: + break; + } + break; + } + case SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG: + { + uint32_t type = in->primary.r.type; + + switch (type) { + case SOF_IPC4_GLB_SET_PIPELINE_STATE: + { + struct ipc4_pipeline_set_state *state; + struct ipc_comp_dev *ipc_pipe; + struct ipc *ipc = ipc_get(); + unsigned int pipeline_id; + + state = (struct ipc4_pipeline_set_state *)in; + pipeline_id = (unsigned int)state->primary.r.ppl_id; + + if (state->primary.r.ppl_state == SOF_IPC4_PIPELINE_STATE_PAUSED) { + ipc_pipe = ipc_get_pipeline_by_id(ipc, pipeline_id); + if (!ipc_pipe) { + fprintf(stderr, "No pipeline with instance_id = %u", + pipeline_id); + return -EINVAL; + } + + /* stop the pipeline thread */ + ret = pipe_thread_stop(sp, ipc_pipe->pipeline); + if (ret < 0) { + printf("error: can't start pipeline %d thread\n", + ipc_pipe->pipeline->comp_id); + return ret; + } + } + break; + } + default: + break; + } + break; + } + default: + fprintf(sp->log, "ipc: unknown command target %u size %ld", + target, bytes); + ret = -EINVAL; + break; + } + + return ret; +} + +static int pipe_sof_ipc_cmd_after(struct sof_pipe *sp, void *mailbox, size_t bytes) +{ + struct ipc4_message_request *in = mailbox; + enum ipc4_message_target target = in->primary.r.msg_tgt; + int ret = 0; + + switch (target) { + case SOF_IPC4_MESSAGE_TARGET_MODULE_MSG: + break; + case SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG: + { + uint32_t type = in->primary.r.type; + + switch (type) { + case SOF_IPC4_GLB_CREATE_PIPELINE: + { + struct ipc4_pipeline_create *pipe_desc = (struct ipc4_pipeline_create *)in; + struct ipc_comp_dev *ipc_pipe; + struct ipc *ipc = ipc_get(); + unsigned int pipeline_id = (unsigned int)pipe_desc->primary.r.instance_id; + + ipc_pipe = ipc_get_pipeline_by_id(ipc, pipeline_id); + if (!ipc_pipe) { + fprintf(stderr, "No pipeline with instance_id = %u\n", + pipeline_id); + return -EINVAL; + } + + /* create new pipeline thread */ + ret = pipe_thread_new(sp, ipc_pipe->pipeline); + if (ret < 0) { + printf("error: can't create pipeline %d thread\n", + ipc_pipe->pipeline->pipeline_id); + return ret; + } + break; + } + case SOF_IPC4_GLB_SET_PIPELINE_STATE: + { + struct ipc4_pipeline_set_state *state; + struct ipc_comp_dev *ipc_pipe; + struct ipc *ipc = ipc_get(); + unsigned int pipeline_id; + + state = (struct ipc4_pipeline_set_state *)in; + pipeline_id = (unsigned int)state->primary.r.ppl_id; + + if (state->primary.r.ppl_state == SOF_IPC4_PIPELINE_STATE_RUNNING) { + ipc_pipe = ipc_get_pipeline_by_id(ipc, pipeline_id); + if (!ipc_pipe) { + fprintf(stderr, "No pipeline with instance_id = %u\n", + pipeline_id); + return -EINVAL; + } + + /* start the pipeline thread */ + ret = pipe_thread_start(sp, ipc_pipe->pipeline); + if (ret < 0) { + printf("error: can't start pipeline %d thread\n", + ipc_pipe->pipeline->comp_id); + return ret; + } + } + break; + } + case SOF_IPC4_GLB_DELETE_PIPELINE: + { + struct ipc4_pipeline_create *pipe_desc = (struct ipc4_pipeline_create *)in; + unsigned int pipeline_id = (unsigned int)pipe_desc->primary.r.instance_id; + + /* free pipeline thread */ + ret = pipe_thread_free(sp, pipeline_id); + if (ret < 0) { + printf("error: can't free pipeline %d thread\n", + pipeline_id); + return ret; + } + + break; + } + default: + break; + } + break; + } + default: + fprintf(sp->log, "ipc: unknown command target %u size %ld", + target, bytes); + ret = -EINVAL; + break; + } + + return ret; +} + +int pipe_ipc_do(struct sof_pipe *sp, void *mailbox, size_t bytes) +{ + char mailbox_copy[IPC3_MAX_MSG_SIZE] = {0}; + int err = 0; + + /* preserve mailbox contents for local "after" config */ + memcpy(mailbox_copy, mailbox, bytes); + + /* some IPCs require pipe to perform actions before core */ + /* mailbox can be re-written here by local pipe if needed */ + err = pipe_sof_ipc_cmd_before(sp, mailbox, bytes); + if (err < 0) { + fprintf(sp->log, "error: local IPC processing failed\n"); + return err; + } + + /* is the IPC local only or do we need send to infra ? */ + err = pipe_ipc_message(sp, mailbox, bytes); + if (err < 0) { + fprintf(sp->log, "error: infra IPC processing failed\n"); + return err; + } + + /* some IPCs require pipe to perform actions before core */ + err = pipe_sof_ipc_cmd_after(sp, mailbox_copy, bytes); + if (err < 0) { + fprintf(sp->log, "error: local IPC processing failed\n"); + return err; + } + + return err; +} + +static void *handle_ipc_client(void *data) +{ + struct sof_pipe *sp = data; + struct plug_socket_desc *ipc_socket = &sp->ipc_socket; + struct timespec ts; + int client_id = sp->new_client_id; + int clientfd = sp->client_sock_ids[client_id]; + char mailbox[IPC3_MAX_MSG_SIZE] = {0}; + ssize_t ipc_size; + int err; + + while (1) { + memset(mailbox, 0, IPC3_MAX_MSG_SIZE); + + ipc_size = recv(clientfd, mailbox, IPC3_MAX_MSG_SIZE, 0); + if (ipc_size < 0) { + fprintf(sp->log, "error: can't read IPC socket %s : %s\n", + ipc_socket->path, strerror(errno)); + break; + } + + /* connection lost */ + if (ipc_size == 0) { + close(clientfd); + break; + } + + /* TODO: properly validate message and continue if garbage */ + if (*((uint32_t *)mailbox) == 0) { + fprintf(sp->log, "sof-pipe: IPC %s garbage read\n", ipc_socket->path); + ts.tv_sec = 0; + ts.tv_nsec = 20 * 1000 * 1000; /* 20 ms */ + nanosleep(&ts, NULL); + continue; + } + + /* do the message work */ + //data_dump(mailbox, IPC3_MAX_MSG_SIZE); + err = pipe_ipc_do(sp, mailbox, ipc_size); + if (err < 0) + fprintf(sp->log, "error: local IPC processing failed\n"); + + /* now return message completion status found in mailbox */ + err = send(clientfd, mailbox, IPC3_MAX_MSG_SIZE, 0); + if (err < 0) { + close(clientfd); + break; + } + } + + close(clientfd); + sp->client_sock_ids[client_id] = 0; + return NULL; +} + +int pipe_ipc_process(struct sof_pipe *sp, struct plug_socket_desc *ipc_socket) +{ + pthread_t thread_id; + int err; + + /* IPC thread should not preempt processing thread */ + err = pipe_set_ipc_lowpri(sp); + if (err < 0) + fprintf(sp->log, "error: cant set PCM IPC thread to low priority"); + + /* create the IPC socket */ + err = plug_socket_create(ipc_socket); + if (err < 0) { + fprintf(sp->log, "error: can't create TX IPC socket : %s\n", + strerror(errno)); + return -errno; + } + + /* let main() know we are ready */ + fprintf(sp->log, "sof-pipe: IPC %s socket ready\n", ipc_socket->path); + + /* main PCM IPC handling loop */ + while (1) { + int clientfd, i; + + /* Accept a connection from a client */ + clientfd = accept(ipc_socket->socket_fd, NULL, NULL); + if (clientfd == -1) { + fprintf(sp->log, "IPC %s socket accept failed\n", ipc_socket->path); + return -errno; + } + + for (i = 0; i < MAX_IPC_CLIENTS; i++) { + if (!sp->client_sock_ids[i]) { + sp->client_sock_ids[i] = clientfd; + sp->new_client_id = i; + break; + } + } + + /* create a new thread for each new IPC client */ + if (pthread_create(&thread_id, NULL, handle_ipc_client, sp) != 0) { + fprintf(sp->log, "Client IPC thread creation failed"); + close(clientfd); + sp->client_sock_ids[i] = 0; + continue; + } + + fprintf(sp->log, "Client IPC thread created client id %d\n", clientfd); + /* Detach the thread */ + pthread_detach(thread_id); + } + + close(ipc_socket->socket_fd); + + fprintf(sp->log, "***sof-pipe: IPC %s thread finished !!\n", ipc_socket->path); + return 0; +} diff --git a/tools/plugin/pipe/main.c b/tools/plugin/pipe/main.c new file mode 100644 index 000000000000..68861fc0af2a --- /dev/null +++ b/tools/plugin/pipe/main.c @@ -0,0 +1,345 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + +/* + * SOF pipeline in userspace. + */ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <pthread.h> +#include <limits.h> +#include <getopt.h> +#include <dlfcn.h> + +#include "common.h" +#include "pipe.h" + +#define VERSION "v0.1" + +/* global needed for signal handler */ +struct sof_pipe *_sp; + +static void shutdown(struct sof_pipe *sp) +{ + struct pipethread_data *pipeline_ctx = sp->pipeline_ctx; + int i; + + /* free everything */ + munmap(sp->shm_context.addr, sp->shm_context.size); + shm_unlink(sp->shm_context.name); + + /* cancel all threads, free locks and message queues */ + for (i = 0; i < sp->pipe_thread_count; i++) { + struct pipethread_data *pd = &pipeline_ctx[i]; + + pthread_cancel(pd->ipc_thread); + pthread_cancel(pd->pcm_thread); + plug_lock_free(&pd->ready); + plug_lock_free(&pd->done); + } + + /* free the sof-pipe IPC tx/rx message queues */ + plug_socket_free(&sp->ipc_socket); + + pthread_mutex_destroy(&sp->ipc_lock); + + fflush(sp->log); + fflush(stdout); + fflush(stderr); +} + +/* signals from the ALSA PCM plugin or something has gone wrong */ +static void signal_handler(int sig) +{ + switch (sig) { + case SIGTERM: + fprintf(_sp->log, "Pipe caught SIGTERM - shutdown\n"); + break; + case SIGINT: + fprintf(_sp->log, "Pipe caught SIGINT - shutdown\n"); + break; + default: + fprintf(_sp->log, "Pipe caught signal %d, something went wrong\n", sig); + break; + } + fprintf(_sp->log, "Pipe shutdown signal\n"); + + /* try and clean up if we can */ + shutdown(_sp); + exit(EXIT_FAILURE); +} + +static int pipe_init_signals(struct sof_pipe *sp) +{ + struct sigaction *action = &sp->action; + int err; + + /* + * signals - currently only check for SIGCHLD. TODO: handle more + */ + sigemptyset(&action->sa_mask); + action->sa_handler = signal_handler; + err = sigaction(SIGTERM, action, NULL); + if (err < 0) { + fprintf(sp->log, "failed to register signal action: %s", + strerror(errno)); + return err; + } + + err = sigaction(SIGSEGV, action, NULL); + if (err < 0) { + fprintf(sp->log, "failed to register signal action: %s", + strerror(errno)); + return err; + } + + err = sigaction(SIGINT, action, NULL); + if (err < 0) { + fprintf(sp->log, "failed to register signal action: %s", + strerror(errno)); + return err; + } + + return 0; +} + +int pipe_ipc_message(struct sof_pipe *sp, void *mailbox, size_t bytes) +{ + struct ipc *ipc = ipc_get(); + + /* reply is copied back to mailbox */ + pthread_mutex_lock(&sp->ipc_lock); + memcpy(ipc->comp_data, mailbox, bytes); + ipc_cmd(mailbox); + memcpy(mailbox, ipc->comp_data, bytes); + pthread_mutex_unlock(&sp->ipc_lock); + + return 0; +} + +/* + * Create and open a new semaphore using the lock object. + */ +int plug_lock_create(struct plug_sem_desc *lock) +{ + /* delete any old stale resources that use our resource name */ + sem_unlink(lock->name); + + /* RW blocking lock */ + lock->sem = sem_open(lock->name, O_CREAT | O_RDWR | O_EXCL, SEM_PERMS, 0); + if (lock->sem == SEM_FAILED) { + SNDERR("failed to create semaphore %s: %s", lock->name, strerror(errno)); + return -errno; + } + + return 0; +} + +/* + * Free and delete semaphore resourses in lock object. + */ +void plug_lock_free(struct plug_sem_desc *lock) +{ + sem_close(lock->sem); + sem_unlink(lock->name); +} + +/* + * Create and open a new shared memory region using the SHM object. + */ +int plug_shm_create(struct plug_shm_desc *shm) +{ + int err; + + /* delete any old stale resources that use our resource name */ + shm_unlink(shm->name); + + /* open SHM to be used for low latency position */ + shm->fd = shm_open(shm->name, O_RDWR | O_CREAT, S_IRWXU | S_IRWXG); + if (shm->fd < 0) { + SNDERR("failed to create SHM position %s: %s", shm->name, strerror(errno)); + return -errno; + } + + /* set SHM size */ + err = ftruncate(shm->fd, shm->size); + if (err < 0) { + SNDERR("failed to truncate SHM position %s: %s", shm->name, strerror(errno)); + shm_unlink(shm->name); + return -errno; + } + + /* map it locally for context readback */ + shm->addr = mmap(NULL, shm->size, PROT_READ | PROT_WRITE, MAP_SHARED, shm->fd, 0); + if (!shm->addr) { + SNDERR("failed to mmap SHM position%s: %s", shm->name, strerror(errno)); + shm_unlink(shm->name); + return -errno; + } + + return 0; +} + +/* + * Free and delete shared memory region resourses in SHM object. + */ +void plug_shm_free(struct plug_shm_desc *shm) +{ + close(shm->fd); + shm_unlink(shm->name); +} + + +/* + * Free and delete message queue resources in IPC object. + */ +void plug_socket_free(struct plug_socket_desc *ipc) +{ + unlink(ipc->path); +} + +/* + * -D ALSA device. e.g. + * -R realtime (needs parent to set uid) + * -p Force run on P core + * -e Force run on E core + * -t topology name. + * -L log file (otherwise stdout) + * -h help + */ +static void usage(char *name) +{ + fprintf(stdout, "Usage: %s -D ALSA device -T topology\n", name); +} + +int main(int argc, char *argv[], char *env[]) +{ + struct sof_pipe sp = {0}; + int option = 0; + int ret = 0; + + /* default config */ + sp.log = stdout; + sp.alsa_name = "default"; /* default sound device */ + _sp = &sp; + + /* parse all args */ + while ((option = getopt(argc, argv, "hD:RpeT:")) != -1) { + switch (option) { + /* Alsa device */ + case 'D': + sp.alsa_name = strdup(optarg); + break; + case 'R': + sp.realtime = 1; + break; + case 'p': + sp.use_P_core = 1; + sp.use_E_core = 0; + break; + case 'e': + sp.use_E_core = 1; + sp.use_P_core = 0; + break; + case 'T': + snprintf(sp.topology_name, NAME_SIZE, "%s", optarg); + break; + + /* print usage */ + default: + fprintf(sp.log, "unknown option %c\n", option); + __attribute__ ((fallthrough)); + case 'h': + usage(argv[0]); + exit(EXIT_SUCCESS); + } + } + + /* validate cmd line params */ + if (strlen(sp.topology_name) == 0) { + fprintf(sp.log, "error: no IPC topology name specified\n"); + exit(EXIT_FAILURE); + } + + /* global IPC access serialisation mutex */ + ret = pthread_mutex_init(&sp.ipc_lock, NULL); + if (ret < 0) { + fprintf(sp.log, "error: cant create mutex %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + fprintf(sp.log, "sof-pipe-%s: using topology %s\n", VERSION, sp.topology_name); + + /* set CPU affinity */ + if (sp.use_E_core || sp.use_P_core) { + ret = pipe_set_affinity(&sp); + if (ret < 0) + goto out; + } + + /* initialize ipc and scheduler */ + if (pipe_sof_setup(sof_get()) < 0) { + fprintf(stderr, "error: pipeline init\n"); + exit(EXIT_FAILURE); + } + + /* global context - plugin clients open this first */ + ret = plug_shm_init(&sp.shm_context, sp.topology_name, "ctx", 0); + if (ret < 0) + goto out; + + /* cleanup any lingering global IPC files */ + shm_unlink(sp.shm_context.name); + + /* make sure we can cleanly shutdown */ + ret = pipe_init_signals(&sp); + if (ret < 0) + goto out; + + /* mmap context on successful topology load */ + ret = plug_shm_create(&sp.shm_context); + if (ret < 0) + goto out; + + /* now prep the global context for client plugin access */ + sp.glb = sp.shm_context.addr; + memset(sp.glb, 0, sizeof(*sp.glb)); + sprintf(sp.glb->magic, "%s", SOF_MAGIC); + sp.glb->size = sizeof(*sp.glb); + sp.glb->state = SOF_PLUGIN_STATE_INIT; + sp.tplg.tplg_file = sp.topology_name; + sp.tplg.ipc_major = 4; //HACK hard code to v4 + + /* sofpipe is now ready */ + sp.glb->state = SOF_PLUGIN_STATE_INIT; + + ret = plug_socket_path_init(&sp.ipc_socket, "sof", "ipc", 0); + if (ret < 0) + goto out; + + /* now process IPCs as they arrive from plugins */ + ret = pipe_ipc_process(&sp, &sp.ipc_socket); + +out: + fprintf(sp.log, "shutdown main\n"); + shutdown(&sp); + return ret; +} diff --git a/tools/plugin/pipe/pipe.h b/tools/plugin/pipe/pipe.h new file mode 100644 index 000000000000..8f8fb26080ea --- /dev/null +++ b/tools/plugin/pipe/pipe.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022-2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __SOF_PLUGIN_PIPE_H__ +#define __SOF_PLUGIN_PIPE_H__ + +#include <stdatomic.h> +#include <stdint.h> +#include <pthread.h> +#include <signal.h> + +#include <alsa/asoundlib.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> +#include "common.h" + +struct sof_pipe; + +#define MAX_MODULE_ID 256 +#define MAX_PIPE_THREADS 128 +#define MAX_PIPELINES 32 + +struct pipethread_data { + pthread_t pcm_thread; + pthread_t ipc_thread; + struct sof_pipe *sp; + struct pipeline *pcm_pipeline; + /* PCM flow control */ + struct plug_sem_desc ready; + struct plug_sem_desc done; + atomic_int pipe_users; +}; + +struct sof_pipe_module { + void *handle; + char uuid[SOF_UUID_SIZE]; + int module_id; +}; + +struct sof_pipe { + const char *alsa_name; + char topology_name[NAME_SIZE]; + int realtime; + int use_P_core; + int use_E_core; + int capture; + int file_mode; + int pipe_thread_count; + + struct sigaction action; + + /* SHM for stream context sync */ + struct plug_shm_desc shm_context; + struct plug_shm_glb_state *glb; + + FILE *log; + pthread_mutex_t ipc_lock; + struct tplg_context tplg; + struct tplg_comp_info *comp_list; + struct list_item widget_list; /* list of widgets */ + struct list_item route_list; /* list of widget connections */ + struct list_item pcm_list; /* list of PCMs */ + int info_elems; + int info_index; + + /* IPC */ + pthread_t ipc_pcm_thread; + struct plug_socket_desc ipc_socket; /* queue used by plugin to send IPCs */ + int client_sock_ids[MAX_IPC_CLIENTS]; + int client_count; + int new_client_id; + + /* module SO handles */ + struct sof_pipe_module module[MAX_MODULE_ID]; + int mod_idx; + + /* pipeline context */ + struct pipethread_data pipeline_ctx[MAX_PIPELINES]; +}; + +/* global needed for signal handler */ +extern struct sof_pipe *_sp; + +int pipe_thread_new(struct sof_pipe *sp, struct pipeline *p); +int pipe_thread_free(struct sof_pipe *sp, int pipeline_id); +int pipe_thread_start(struct sof_pipe *sp, struct pipeline *p); +int pipe_thread_stop(struct sof_pipe *sp, struct pipeline *p); +int pipe_sof_setup(struct sof *sof); +int pipe_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, + void *comp, void *arg); + +/* set pipeline to realtime priority */ +int pipe_set_rt(struct sof_pipe *sp); + +/* set ipc thread to low priority */ +int pipe_set_ipc_lowpri(struct sof_pipe *sp); + +int pipe_ipc_process(struct sof_pipe *sp, struct plug_socket_desc *ipc_socket); + +int pipe_ipc_new(struct sof_pipe *sp, int pri, int core); +void pipe_ipc_free(struct sof_pipe *sp); + +int pipe_set_affinity(struct sof_pipe *sp); + +int pipe_ipc_message(struct sof_pipe *sp, void *mailbox, size_t bytes); + +int pipe_ipc_do(struct sof_pipe *sp, void *mailbox, size_t bytes); + +/* + * Topology + */ +int plug_parse_topology(struct sof_pipe *sp, struct tplg_context *ctx); + +int plug_load_widget(struct sof_pipe *sp, struct tplg_context *ctx); + +int plug_register_graph(struct sof_pipe *sp, struct tplg_context *ctx, + struct tplg_comp_info *temp_comp_list, + char *pipeline_string, + int count, int num_comps, int pipeline_id); + +#endif diff --git a/tools/plugin/pipe/pipeline.c b/tools/plugin/pipe/pipeline.c new file mode 100644 index 000000000000..2985e46d04ad --- /dev/null +++ b/tools/plugin/pipe/pipeline.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + +/* + * SOF pipeline in userspace. + */ + +#include <stdio.h> +#include <sys/poll.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <assert.h> +#include <errno.h> +#include <pthread.h> +#include <limits.h> +#include <dlfcn.h> + +#include <rtos/sof.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component.h> +#include <sof/audio/component_ext.h> +#include <rtos/task.h> +#include <sof/lib/notifier.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/schedule/schedule.h> +#include <stdatomic.h> + +#include "common.h" +#include "pipe.h" + +#define MAX_PIPE_USERS 8 + +static struct ll_schedule_domain domain = {0}; + +// TODO: all these steps are probably not needed - i.e we only need IPC and pipeline. +int pipe_sof_setup(struct sof *sof) +{ + /* register modules */ + + domain.next_tick = 0; + + /* init components */ + sys_comp_init(sof); + + /* other necessary initializations, todo: follow better SOF init */ + pipeline_posn_init(sof); + init_system_notify(sof); + + /* init IPC */ + if (ipc_init(sof) < 0) { + fprintf(stderr, "error: IPC init\n"); + return -EINVAL; + } + + /* init LL scheduler */ + if (scheduler_init_ll(&domain) < 0) { + fprintf(stderr, "error: edf scheduler init\n"); + return -EINVAL; + } + + /* init EDF scheduler */ + if (scheduler_init_edf() < 0) { + fprintf(stderr, "error: edf scheduler init\n"); + return -EINVAL; + } + + return 0; +} + +static inline int pipe_copy_ready(struct pipethread_data *pd) +{ + struct timespec delay; + int err; + + /* get the current time for source delay */ + err = clock_gettime(CLOCK_REALTIME, &delay); + if (err == -1) { + fprintf(_sp->log, "shm: cant get time: %s", strerror(errno)); + return -errno; + } + + // TODO get from rate + plug_timespec_add_ms(&delay, 2000); + + /* wait for data from source */ + err = sem_timedwait(pd->ready.sem, &delay); + if (err == -1) { + fprintf(_sp->log, "%s %d: fatal timeout: %s on %s\n", __FILE__, __LINE__, + strerror(errno), pd->ready.name); + return -errno; + } + + return 0; +} + +static inline void pipe_copy_done(struct pipethread_data *pd) +{ + /* tell peer we are done */ + sem_post(pd->done.sem); +} + +static void *pipe_process_thread(void *arg) +{ + struct pipethread_data *pd = arg; + int err; + + fprintf(_sp->log, "pipe thread started for pipeline %d\n", + pd->pcm_pipeline->pipeline_id); + + do { + if (pd->pcm_pipeline->status != COMP_STATE_ACTIVE) { + fprintf(_sp->log, "pipe state non active %d\n", + pd->pcm_pipeline->status); + break; + } + + if (pd->pipe_users <= 0) { + fprintf(_sp->log, "pipe no users.\n"); + break; + } + + /* wait for pipe to be ready */ + err = pipe_copy_ready(pd); + if (err < 0) { + fprintf(_sp->log, "pipe ready timeout on pipeline %d state %d users %d\n", + pd->pcm_pipeline->pipeline_id, pd->pcm_pipeline->status, + pd->pipe_users); + break; + } + + /* sink has read data so now generate more it */ + err = pipeline_copy(pd->pcm_pipeline); + + pipe_copy_done(pd); + + if (err < 0) { + fprintf(_sp->log, "pipe thread error %d\n", err); + break; + } else if (err > 0) { + fprintf(_sp->log, "pipe thread complete %d\n", err); + break; + } + + } while (1); + + fprintf(_sp->log, "pipe complete for pipeline %d\n", + pd->pcm_pipeline->pipeline_id); + return 0; +} + +static void *pipe_ipc_process_thread(void *arg) +{ + struct pipethread_data *pd = arg; + int err; + + /* initialise semaphores to default starting value */ + err = sem_init(pd->done.sem, 1, 0); + if (err < 0) { + fprintf(_sp->log, "failed to reset DONE: %s\n", + strerror(errno)); + return NULL; + } + err = sem_init(pd->ready.sem, 1, 0); + if (err < 0) { + fprintf(_sp->log, "failed to reset READY: %s\n", + strerror(errno)); + return NULL; + } + + return NULL; +} + +int pipe_thread_start(struct sof_pipe *sp, struct pipeline *p) +{ + struct pipethread_data *pipeline_ctx = sp->pipeline_ctx; + struct pipethread_data *pd; + int pipeline_id; + int ret, pipe_users; + + pipeline_id = p->pipeline_id; + + if (pipeline_id >= MAX_PIPELINES) { + fprintf(_sp->log, "error: pipeline ID %d out of range\n", pipeline_id); + return -EINVAL; + } + + if (!pipeline_ctx[pipeline_id].sp) { + fprintf(_sp->log, "error: pipeline ID %d not in use\n", pipeline_id); + return -EINVAL; + } + pd = &pipeline_ctx[pipeline_id]; + + /* only create thread if not active */ + pipe_users = atomic_fetch_add(&pd->pipe_users, 1); + if (pipe_users > 0) { + fprintf(_sp->log, "pipeline ID %d thread already running %d users\n", + pipeline_id, pipe_users); + return 0; + } + + fprintf(_sp->log, "pipeline ID %d thread not running so starting...\n", pipeline_id); + + /* first user so start the PCM pipeline thread */ + ret = pthread_create(&pd->pcm_thread, NULL, pipe_process_thread, pd); + if (ret < 0) { + fprintf(_sp->log, "failed to create PCM thread: %s\n", strerror(errno)); + return -errno; + } + + return ret; +} + +int pipe_thread_stop(struct sof_pipe *sp, struct pipeline *p) +{ + struct pipethread_data *pipeline_ctx = sp->pipeline_ctx; + struct pipethread_data *pd; + int pipeline_id; + int ret, pipe_users; + + pipeline_id = p->pipeline_id; + + /* this is called when the pipeline is PAUSED for the first time before RUNNING */ + if (p->status == COMP_STATE_INIT) + return 0; + + if (pipeline_id >= MAX_PIPELINES) { + fprintf(_sp->log, "error: pipeline ID %d out of range\n", pipeline_id); + return -EINVAL; + } + + if (!pipeline_ctx[pipeline_id].sp) { + fprintf(_sp->log, "error: pipeline ID %d not in use\n", pipeline_id); + return -EINVAL; + } + pd = &pipeline_ctx[pipeline_id]; + + /* only join thread if not active */ + pipe_users = atomic_fetch_sub(&pd->pipe_users, 1); + if (pipe_users != 1) { + fprintf(_sp->log, "pipeline ID %d thread has multiple %d users\n", + pipeline_id, pipe_users); + return 0; + } + + fprintf(_sp->log, "pipeline ID %d thread can be stopped...\n", pipeline_id); + + ret = pthread_cancel(pd->pcm_thread); + if (ret < 0) { + fprintf(_sp->log, "failed to cancel PCM thread: %s\n", strerror(errno)); + return -errno; + } + + return ret; +} + +int pipe_thread_new(struct sof_pipe *sp, struct pipeline *p) +{ + struct pipethread_data *pipeline_ctx = sp->pipeline_ctx; + struct pipethread_data *pd; + int ret; + + if (!p) { + fprintf(_sp->log, "error: invalid pipeline\n"); + return -EINVAL; + } + + if (p->pipeline_id >= MAX_PIPELINES) { + fprintf(_sp->log, "error: pipeline ID %d out of range\n", p->pipeline_id); + return -EINVAL; + } + + if (pipeline_ctx[p->pipeline_id].sp) { + fprintf(_sp->log, "error: pipeline ID %d in use\n", p->pipeline_id); + return -EINVAL; + } + pd = &pipeline_ctx[p->pipeline_id]; + pd->sp = _sp; + pd->pcm_pipeline = p; + + /* init names of shared resources */ + ret = plug_lock_init(&pd->ready, _sp->topology_name, "ready", p->pipeline_id); + if (ret < 0) + return ret; + + ret = plug_lock_init(&pd->done, _sp->topology_name, "done", p->pipeline_id); + if (ret) + return ret; + + /* open semaphores */ + ret = plug_lock_create(&pd->ready); + if (ret < 0) + return ret; + ret = plug_lock_create(&pd->done); + if (ret < 0) + goto lock_err; + + /* start IPC pipeline thread */ + ret = pthread_create(&pd->ipc_thread, NULL, pipe_ipc_process_thread, pd); + if (ret < 0) { + fprintf(_sp->log, "failed to create IPC thread: %s\n", strerror(errno)); + ret = -errno; + goto lock2_err; + } + + return 0; + +lock2_err: + plug_lock_free(&pd->done); +lock_err: + plug_lock_free(&pd->ready); + return ret; +} + +int pipe_thread_free(struct sof_pipe *sp, int pipeline_id) +{ + struct pipethread_data *pipeline_ctx = sp->pipeline_ctx; + struct pipethread_data *pd; + int err; + + if (pipeline_id >= MAX_PIPELINES) { + fprintf(_sp->log, "error: pipeline ID %d out of range\n", pipeline_id); + return -EINVAL; + } + + if (!pipeline_ctx[pipeline_id].sp) { + fprintf(_sp->log, "error: pipeline ID %d not in use\n", pipeline_id); + return -EINVAL; + } + + pd = &pipeline_ctx[pipeline_id]; + + err = pthread_cancel(pd->ipc_thread); + if (err < 0) { + fprintf(_sp->log, "failed to create IPC thread: %s\n", strerror(errno)); + return -errno; + } + + plug_lock_free(&pd->ready); + plug_lock_free(&pd->done); + + pd->sp = NULL; + return 0; +} diff --git a/tools/probes/CMakeLists.txt b/tools/probes/CMakeLists.txt index 32f89a607711..1b39e6d192db 100644 --- a/tools/probes/CMakeLists.txt +++ b/tools/probes/CMakeLists.txt @@ -1,10 +1,10 @@ # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) add_executable(sof-probes + probes_demux.c probes_main.c - ../../src/math/numbers.c ) target_compile_options(sof-probes PRIVATE @@ -15,4 +15,9 @@ target_include_directories(sof-probes PRIVATE "../../src/include" ) +# TODO: probes should not need to include RTOS headers. FIX. +target_include_directories(sof-probes PRIVATE + "../../xtos/include" +) + install(TARGETS sof-probes DESTINATION bin) diff --git a/tools/probes/probes_demux.c b/tools/probes/probes_demux.c new file mode 100644 index 000000000000..a411eef117b9 --- /dev/null +++ b/tools/probes/probes_demux.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Adrian Bonislawski <adrian.bonislawski@intel.com> +// Jyri Sarha <jyri.sarha@intel.com> (restructured and moved to this file) + +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <ipc/probe_dma_frame.h> + +#include "wave.h" + +#define APP_NAME "sof-probes" + +#define PACKET_MAX_SIZE 4096 /**< Size limit for probe data packet */ +#define DATA_READ_LIMIT 4096 /**< Data limit for file read */ +#define FILES_LIMIT 32 /**< Maximum num of probe output files */ +#define FILE_PATH_LIMIT 128 /**< Path limit for probe output files */ + +struct wave_files { + FILE *fd; + uint32_t buffer_id; + uint32_t fmt; + uint32_t size; + struct wave header; +}; + +enum p_state { + READY = 0, /**< At this stage app is looking for a SYNC word */ + SYNC, /**< SYNC received, copying data */ + CHECK /**< Check crc and save packet if valid */ +}; + +struct dma_frame_parser { + bool log_to_stdout; + enum p_state state; + struct probe_data_packet *packet; + size_t packet_size; + uint8_t *w_ptr; /* Write pointer to copy data to */ + uint32_t total_data_to_copy; /* Total bytes left to copy */ + int start; /* Start of unfilled data */ + int len; /* Data buffer fill level */ + uint8_t data[DATA_READ_LIMIT]; + struct wave_files files[FILES_LIMIT]; +}; + +static uint32_t sample_rate[] = { + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000, 128000, 176400, 192000 +}; + +int get_buffer_file(struct wave_files *files, uint32_t buffer_id) +{ + int i; + + for (i = 0; i < FILES_LIMIT; i++) { + if (files[i].fd != NULL && files[i].buffer_id == buffer_id) + return i; + } + return -1; +} + +int get_buffer_file_free(struct wave_files *files) +{ + int i; + + for (i = 0; i < FILES_LIMIT; i++) { + if (files[i].fd == NULL) + return i; + } + return -1; +} + +bool is_audio_format(uint32_t format) +{ + return (format & PROBE_MASK_FMT_TYPE) != 0 && (format & PROBE_MASK_AUDIO_FMT) == 0; +} + +int init_wave(struct dma_frame_parser *p, uint32_t buffer_id, uint32_t format) +{ + bool audio = is_audio_format(format); + char path[FILE_PATH_LIMIT]; + int i; + + i = get_buffer_file_free(p->files); + if (i == -1) { + fprintf(stderr, "error: too many buffers\n"); + exit(0); + } + + sprintf(path, "buffer_%d.%s", buffer_id, audio ? "wav" : "bin"); + + fprintf(stderr, "%s:\t Creating file %s\n", APP_NAME, path); + + if (!audio && p->log_to_stdout) { + p->files[i].fd = stdout; + } else { + p->files[i].fd = fopen(path, "wb"); + if (!p->files[i].fd) { + fprintf(stderr, "error: unable to create file %s, error %d\n", + path, errno); + exit(0); + } + } + + p->files[i].buffer_id = buffer_id; + p->files[i].fmt = format; + + if (!audio) + return i; + + p->files[i].header.riff.chunk_id = HEADER_RIFF; + p->files[i].header.riff.format = HEADER_WAVE; + p->files[i].header.fmt.subchunk_id = HEADER_FMT; + p->files[i].header.fmt.subchunk_size = 16; + p->files[i].header.fmt.audio_format = 1; + p->files[i].header.fmt.num_channels = ((format & PROBE_MASK_NB_CHANNELS) >> PROBE_SHIFT_NB_CHANNELS) + 1; + p->files[i].header.fmt.sample_rate = sample_rate[(format & PROBE_MASK_SAMPLE_RATE) >> PROBE_SHIFT_SAMPLE_RATE]; + p->files[i].header.fmt.bits_per_sample = (((format & PROBE_MASK_CONTAINER_SIZE) >> PROBE_SHIFT_CONTAINER_SIZE) + 1) * 8; + p->files[i].header.fmt.byte_rate = p->files[i].header.fmt.sample_rate * + p->files[i].header.fmt.num_channels * + p->files[i].header.fmt.bits_per_sample / 8; + p->files[i].header.fmt.block_align = p->files[i].header.fmt.num_channels * + p->files[i].header.fmt.bits_per_sample / 8; + p->files[i].header.data.subchunk_id = HEADER_DATA; + + fwrite(&p->files[i].header, sizeof(struct wave), 1, p->files[i].fd); + + return i; +} + +void finalize_wave_files(struct dma_frame_parser *p) +{ + struct wave_files *files = p->files; + uint32_t i, chunk_size; + + /* fill the header at the beginning of each file */ + /* and close all opened files */ + /* check wave struct to understand the offsets */ + for (i = 0; i < FILES_LIMIT; i++) { + if (!is_audio_format(files[i].fmt)) + continue; + + if (files[i].fd) { + chunk_size = files[i].size + sizeof(struct wave) - + offsetof(struct riff_chunk, format); + + fseek(files[i].fd, sizeof(uint32_t), SEEK_SET); + fwrite(&chunk_size, sizeof(uint32_t), 1, files[i].fd); + fseek(files[i].fd, sizeof(struct wave) - + offsetof(struct data_subchunk, subchunk_size), + SEEK_SET); + fwrite(&files[i].size, sizeof(uint32_t), 1, files[i].fd); + + fclose(files[i].fd); + } + } +} + +int validate_data_packet(struct probe_data_packet *packet) +{ + uint64_t *checksump; + uint64_t sum; + + sum = (uint32_t) (packet->sync_word + + packet->buffer_id + + packet->format + + packet->timestamp_high + + packet->timestamp_low + + packet->data_size_bytes); + + checksump = (uint64_t *) (packet->data + packet->data_size_bytes); + + if (sum != *checksump) { + fprintf(stderr, "Checksum error 0x%016" PRIx64 " != 0x%016" PRIx64 "\n", + sum, *checksump); + return -EINVAL; + } + + return 0; +} + +int process_sync(struct dma_frame_parser *p) +{ + struct probe_data_packet *temp_packet; + + /* request to copy data_size from probe packet and 64-bit checksum */ + p->total_data_to_copy = p->packet->data_size_bytes + sizeof(uint64_t); + + if (sizeof(struct probe_data_packet) + p->total_data_to_copy > + p->packet_size) { + p->packet_size = sizeof(struct probe_data_packet) + + p->total_data_to_copy; + + temp_packet = realloc(p->packet, p->packet_size); + + if (!temp_packet) + return -ENOMEM; + + p->packet = temp_packet; + } + + p->w_ptr = (uint8_t *)p->packet->data; + + return 0; +} + +struct dma_frame_parser *parser_init(void) +{ + struct dma_frame_parser *p = malloc(sizeof(*p)); + if (!p) { + fprintf(stderr, "error: allocation failed, err %d\n", + errno); + return NULL; + } + memset(p, 0, sizeof(*p)); + p->packet = malloc(PACKET_MAX_SIZE); + if (!p) { + fprintf(stderr, "error: allocation failed, err %d\n", + errno); + free(p); + return NULL; + } + memset(p->packet, 0, PACKET_MAX_SIZE); + p->packet_size = PACKET_MAX_SIZE; + return p; +} + +void parser_free(struct dma_frame_parser *p) +{ + free(p->packet); + free(p); +} + +void parser_log_to_stdout(struct dma_frame_parser *p) +{ + p->log_to_stdout = true; +} + +void parser_fetch_free_buffer(struct dma_frame_parser *p, uint8_t **d, size_t *len) +{ + *d = &p->data[p->start]; + *len = sizeof(p->data) - p->start; +} + +int parser_parse_data(struct dma_frame_parser *p, size_t d_len) +{ + uint i = 0; + + p->len = p->start + d_len; + /* processing all loaded bytes */ + while (i < p->len) { + if (p->total_data_to_copy == 0) { + switch (p->state) { + case READY: + /* check for SYNC */ + if (p->len - i < sizeof(p->packet->sync_word)) { + p->start = p->len - i; + memmove(&p->data[0], &p->data[i], p->start); + i += p->start; + } else if (*((uint32_t *)&p->data[i]) == + PROBE_EXTRACT_SYNC_WORD) { + memset(p->packet, 0, p->packet_size); + /* request to copy full data packet */ + p->total_data_to_copy = + sizeof(struct probe_data_packet); + p->w_ptr = (uint8_t *)p->packet; + p->state = SYNC; + p->start = 0; + } else { + i++; + } + break; + case SYNC: + /* SYNC -> CHECK */ + if (process_sync(p) < 0) { + fprintf(stderr, "OOM, quitting\n"); + return -ENOMEM; + } + p->state = CHECK; + break; + case CHECK: + /* CHECK -> READY */ + /* find corresponding file and save data if valid */ + if (validate_data_packet(p->packet) == 0) { + int file = get_buffer_file(p->files, + p->packet->buffer_id); + + if (file < 0) + file = init_wave(p, p->packet->buffer_id, + p->packet->format); + + if (file < 0) { + fprintf(stderr, + "unable to open file for %u\n", + p->packet->buffer_id); + return -EIO; + } + + fwrite(p->packet->data, 1, + p->packet->data_size_bytes, + p->files[file].fd); + p->files[file].size += p->packet->data_size_bytes; + } + p->state = READY; + break; + } + } + /* data copying section */ + if (p->total_data_to_copy > 0) { + uint data_to_copy; + + /* check if there is enough bytes loaded */ + /* or copy partially if not */ + if (i + p->total_data_to_copy > p->len) { + data_to_copy = p->len - i; + p->total_data_to_copy -= data_to_copy; + } else { + data_to_copy = p->total_data_to_copy; + p->total_data_to_copy = 0; + } + memcpy(p->w_ptr, &p->data[i], data_to_copy); + p->w_ptr += data_to_copy; + i += data_to_copy; + } + } + return 0; +} diff --git a/tools/probes/probes_demux.h b/tools/probes/probes_demux.h new file mode 100644 index 000000000000..93aa89119a5e --- /dev/null +++ b/tools/probes/probes_demux.h @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Jyri Sarha <jyri.sarha@intel.com> +// + +#ifndef _PROBES_DEMUX_H_ +#define _PROBES_DEMUX_H_ + +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> + +struct dma_frame_parser; + +struct dma_frame_parser *parser_init(void); + +void parser_log_to_stdout(struct dma_frame_parser *p); + +void parser_free(struct dma_frame_parser *p); + +void parser_fetch_free_buffer(struct dma_frame_parser *p, uint8_t **d, size_t *len); + +int parser_parse_data(struct dma_frame_parser *p, size_t d_len); + +void finalize_wave_files(struct dma_frame_parser *p); + +#endif diff --git a/tools/probes/probes_main.c b/tools/probes/probes_main.c index 4ff31a76beb5..cdba2c6347d5 100644 --- a/tools/probes/probes_main.c +++ b/tools/probes/probes_main.c @@ -13,303 +13,86 @@ * */ -#include <ipc/probe.h> -#include <sof/math/numbers.h> -#include "wave.h" - -#include <ctype.h> #include <errno.h> -#include <fcntl.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> -#define APP_NAME "sof-probes" - -#define PACKET_MAX_SIZE 4096 /**< Size limit for probe data packet */ -#define DATA_READ_LIMIT 1024 /**< Data limit for file read */ -#define FILES_LIMIT 32 /**< Maximum num of probe output files */ -#define FILE_PATH_LIMIT 128 /**< Path limit for probe output files */ - -struct wave_files { - FILE *fd; - uint32_t buffer_id; - uint32_t size; - struct wave header; -}; +#include "probes_demux.h" -enum p_state { - READY = 0, /**< At this stage app is looking for a SYNC word */ - SYNC, /**< SYNC received, copying data */ - CHECK /**< Check crc and save packet if valid */ -}; - -static uint32_t sample_rate[] = { - 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, - 48000, 64000, 88200, 96000, 128000, 176400, 192000 -}; +#define APP_NAME "sof-probes" static void usage(void) { fprintf(stdout, "Usage %s <option(s)> <buffer_id/file>\n\n", APP_NAME); fprintf(stdout, "%s:\t -p file\tParse extracted file\n\n", APP_NAME); + fprintf(stdout, "%s:\t -l \t\tLog to stdout\n\n", APP_NAME); fprintf(stdout, "%s:\t -h \t\tHelp, usage info\n", APP_NAME); exit(0); } -int write_data(char *path, char *data) -{ - FILE *fd; - - fd = fopen(path, "w"); - if (!fd) { - fprintf(stderr, "error: unable to open file %s, error %d\n", - path, errno); - return errno; - } - - fprintf(fd, "%s", data); - fclose(fd); - - return 0; -} - -int get_buffer_file(struct wave_files *files, uint32_t buffer_id) +void parse_data(const char *file_in, bool log_to_stdout) { - int i; - - for (i = 0; i < FILES_LIMIT; i++) { - if (files[i].buffer_id == buffer_id) - return i; - } - return -1; -} - -int init_wave(struct wave_files *files, uint32_t buffer_id, uint32_t format) -{ - char path[FILE_PATH_LIMIT]; - int i; - - i = get_buffer_file(files, 0); - if (i == -1) { - fprintf(stderr, "error: too many buffers\n"); - exit(0); - } - - fprintf(stdout, "%s:\t Creating wave file for buffer id: %d\n", - APP_NAME, buffer_id); - - sprintf(path, "buffer_%d.wav", buffer_id); + struct dma_frame_parser *p = parser_init(); + FILE *fd_in; + uint8_t *data; + size_t len; + int ret; - files[i].fd = fopen(path, "wb"); - if (!files[i].fd) { - fprintf(stderr, "error: unable to create file %s, error %d\n", - path, errno); - exit(0); + if (!p) { + fprintf(stderr, "parser_init() failed\n"); + exit(1); } - files[i].buffer_id = buffer_id; + if (log_to_stdout) + parser_log_to_stdout(p); - files[i].header.riff.chunk_id = HEADER_RIFF; - files[i].header.riff.format = HEADER_WAVE; - files[i].header.fmt.subchunk_id = HEADER_FMT; - files[i].header.fmt.subchunk_size = 16; - files[i].header.fmt.audio_format = 1; - files[i].header.fmt.num_channels = ((format & PROBE_MASK_NB_CHANNELS) >> PROBE_SHIFT_NB_CHANNELS) + 1; - files[i].header.fmt.sample_rate = sample_rate[(format & PROBE_MASK_SAMPLE_RATE) >> PROBE_SHIFT_SAMPLE_RATE]; - files[i].header.fmt.bits_per_sample = (((format & PROBE_MASK_CONTAINER_SIZE) >> PROBE_SHIFT_CONTAINER_SIZE) + 1) * 8; - files[i].header.fmt.byte_rate = files[i].header.fmt.sample_rate * - files[i].header.fmt.num_channels * - files[i].header.fmt.bits_per_sample / 8; - files[i].header.fmt.block_align = files[i].header.fmt.num_channels * - files[i].header.fmt.bits_per_sample / 8; - files[i].header.data.subchunk_id = HEADER_DATA; - - fwrite(&files[i].header, sizeof(struct wave), 1, files[i].fd); - - return i; -} - -void finalize_wave_files(struct wave_files *files) -{ - uint32_t i, chunk_size; - - /* fill the header at the beginning of each file */ - /* and close all opened files */ - /* check wave struct to understand the offsets */ - for (i = 0; i < FILES_LIMIT; i++) { - if (files[i].fd) { - chunk_size = files[i].size + sizeof(struct wave) - - offsetof(struct riff_chunk, format); - - fseek(files[i].fd, sizeof(uint32_t), SEEK_SET); - fwrite(&chunk_size, sizeof(uint32_t), 1, files[i].fd); - fseek(files[i].fd, sizeof(struct wave) - - offsetof(struct data_subchunk, subchunk_size), - SEEK_SET); - fwrite(&files[i].size, sizeof(uint32_t), 1, files[i].fd); - - fclose(files[i].fd); + if (file_in) { + fd_in = fopen(file_in, "rb"); + if (!fd_in) { + fprintf(stderr, "error: unable to open file %s, error %d\n", + file_in, errno); + exit(0); } - } -} - -int validate_data_packet(struct probe_data_packet *data_packet) -{ - uint32_t received_crc; - uint32_t calc_crc; - - received_crc = data_packet->checksum; - data_packet->checksum = 0; - calc_crc = crc32(0, (char *)data_packet, sizeof(*data_packet)); - - if (received_crc == calc_crc) { - return 0; } else { - fprintf(stderr, "error: data packet for buffer %d is not valid: crc32: %d/%d\n", - data_packet->buffer_id, calc_crc, received_crc); - return -EINVAL; - } -} - -void parse_data(char *file_in) -{ - FILE *fd_in; - struct wave_files files[FILES_LIMIT]; - struct probe_data_packet *packet; - uint32_t data[DATA_READ_LIMIT]; - uint32_t total_data_to_copy = 0; - uint32_t data_to_copy = 0; - uint32_t *w_ptr; - int i, j, file; - - enum p_state state = READY; - - fprintf(stdout, "%s:\t Parsing file: %s\n", APP_NAME, file_in); - - fd_in = fopen(file_in, "rb"); - if (!fd_in) { - fprintf(stderr, "error: unable to open file %s, error %d\n", - file_in, errno); - exit(0); + fd_in = stdin; } - packet = malloc(PACKET_MAX_SIZE); - if (!packet) { - fprintf(stderr, "error: allocation failed, err %d\n", - errno); - fclose(fd_in); - exit(0); - } - memset(&data, 0, sizeof(uint32_t) * DATA_READ_LIMIT); - memset(&files, 0, sizeof(struct wave_files) * FILES_LIMIT); - - /* data read loop to process DATA_READ_LIMIT bytes at each iteration */ do { - i = fread(&data, sizeof(uint32_t), DATA_READ_LIMIT, fd_in); - /* processing all loaded bytes */ - for (j = 0; j < i; j++) { - /* SYNC received */ - if (data[j] == PROBE_EXTRACT_SYNC_WORD) { - if (state != READY) { - fprintf(stderr, "error: wrong state %d, err %d\n", - state, errno); - free(packet); - exit(0); - } - memset(packet, 0, PACKET_MAX_SIZE); - /* request to copy full data packet */ - total_data_to_copy = sizeof(struct probe_data_packet) / - sizeof(uint32_t); - /* probe_data_packet forced to align 4 */ - w_ptr = __builtin_assume_aligned((uint32_t *)packet, 4); - state = SYNC; - } - /* data copying section */ - if (total_data_to_copy > 0) { - /* check if there is enough bytes loaded */ - /* or copy partially if not */ - if (j + total_data_to_copy > i) { - data_to_copy = i - j; - total_data_to_copy -= data_to_copy; - } else { - data_to_copy = total_data_to_copy; - total_data_to_copy = 0; - } - memcpy(w_ptr, data + j, data_to_copy * sizeof(uint32_t)); - w_ptr += data_to_copy; - j += data_to_copy - 1; - } - - if (total_data_to_copy == 0) { - switch (state) { - case READY: - break; - case SYNC: - /* SYNC -> CHECK */ - /* request to copy data_size from probe packet */ - total_data_to_copy = packet->data_size_bytes / - sizeof(uint32_t); - if (packet->data_size_bytes > PACKET_MAX_SIZE) - packet = realloc(packet, - sizeof(struct probe_data_packet) + - packet->data_size_bytes); - /* probe_data_packet forced to align 4 */ - w_ptr = __builtin_assume_aligned((uint32_t *)&packet->data, 4); - state = CHECK; - break; - case CHECK: - /* CHECK -> READY */ - /* find corresponding file and save data if valid */ - if (validate_data_packet(packet) == 0) { - file = get_buffer_file(files, - packet->buffer_id); - - if (file < 0) - file = init_wave(files, - packet->buffer_id, - packet->format); + parser_fetch_free_buffer(p, &data, &len); + len = fread(data, 1, len, fd_in); + ret = parser_parse_data(p, len); + } while (!ret && !feof(fd_in)); - fwrite(packet->data, - sizeof(uint32_t), - packet->data_size_bytes / - sizeof(uint32_t), - files[file].fd); + if (!log_to_stdout) + finalize_wave_files(p); - files[file].size += packet->data_size_bytes; - } - state = READY; - break; - } - } - } - } while (i > 0); - - /* all done, can close files */ - finalize_wave_files(files); - free(packet); - fclose(fd_in); - fprintf(stdout, "%s:\t done\n", APP_NAME); } int main(int argc, char *argv[]) { + const char *fname = NULL; + bool log_to_stdout = false; int opt; - while ((opt = getopt(argc, argv, "hp:")) != -1) { + while ((opt = getopt(argc, argv, "lhp:")) != -1) { switch (opt) { case 'p': - parse_data(optarg); + fname = optarg; + break; + case 'l': + log_to_stdout = true; break; case 'h': default: usage(); + return 0; } } + parse_data(fname, log_to_stdout); return 0; } diff --git a/tools/rimage/CMakeLists.txt b/tools/rimage/CMakeLists.txt new file mode 100644 index 000000000000..8e0a5da7d267 --- /dev/null +++ b/tools/rimage/CMakeLists.txt @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.10) + +project(SOF_RIMAGE C) + +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "No CMAKE_BUILD_TYPE, defaulting to Debug") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE) +endif() + +add_executable(rimage + src/file_simple.c + src/cse.c + src/css.c + src/plat_auth.c + src/hash.c + src/pkcs1_5.c + src/manifest.c + src/ext_manifest.c + src/rimage.c + src/toml_utils.c + src/adsp_config.c + src/misc_utils.c + src/file_utils.c + src/elf_file.c + src/module.c + tomlc99/toml.c +) + +set_property(TARGET rimage PROPERTY C_STANDARD 99) + +target_compile_options(rimage PRIVATE + -Wall -Werror -Wmissing-prototypes -Wimplicit-fallthrough +) + +if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 9.1) + target_compile_options(rimage PRIVATE -Wno-char-subscripts) +endif() + +# Windows builds use MSYS2 https://www.msys2.org/ to get linux tools and headers. +# MSYS_INSTALL_DIR variable points to MSYS2 installation directory. +# You may pass it as environmental or cmake configure variable. +if(${CMAKE_HOST_WIN32}) + cmake_minimum_required(VERSION 3.20) + if(DEFINED ENV{MSYS_INSTALL_DIR} AND NOT MSYS_INSTALL_DIR) + set(MSYS_INSTALL_DIR $ENV{MSYS_INSTALL_DIR}) + endif() + + if(MSYS_INSTALL_DIR) + cmake_path(IS_ABSOLUTE MSYS_INSTALL_DIR IS_MSYS_INSTALL_DIR_ABSOLUTE) + if(NOT IS_MSYS_INSTALL_DIR_ABSOLUTE) + message(FATAL_ERROR "Please provide absolute path to MSYS2 installation + setting MSYS_INSTALL_DIR env variable") + endif() + # Include standard posix headers. Requires pacman openssl-devel package. + cmake_path(APPEND MSYS_INSTALL_DIR "usr" "include" OUTPUT_VARIABLE MSYS_SYSTEM_INCLUDE_PATH) + target_include_directories(rimage PRIVATE "${MSYS_SYSTEM_INCLUDE_PATH}") + endif() +endif() + +target_link_libraries(rimage PRIVATE crypto) + +target_include_directories(rimage PRIVATE + src/include/ + tomlc99/ +) diff --git a/tools/rimage/LICENSE b/tools/rimage/LICENSE new file mode 100644 index 000000000000..468893dff94b --- /dev/null +++ b/tools/rimage/LICENSE @@ -0,0 +1,97 @@ +/* + * BSD 3 Clause + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +// Copyright (c) 2003-2014 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. + + +Files with 2-Clause BSD licence: + +src/include/rimage/elf.h + +/* + * Derived from: + * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $ + * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $ + * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $ + * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $ + * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $ + * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $ + * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $ + * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $ + * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $ + * + * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. + * Copyright (c) 2001 David E. O'Brien + * Portions Copyright 2009 The Go Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ diff --git a/tools/rimage/README.md b/tools/rimage/README.md new file mode 100644 index 000000000000..797bb662f6d6 --- /dev/null +++ b/tools/rimage/README.md @@ -0,0 +1,122 @@ +# rimage + +`rimage` is a DSP firmware image creation and signing tool targeting the DSP on certain Intel System-on-Chip (SoC). This is used by the [Sound Open Firmware (SOF)](https://github.com/thesofproject/sof) to generate binary image files. + +## Building + +Most SOF users never build `rimage` directly but as an ExternalProject defined by CMake in SOF. This makes sure they always use an up-to-date version of rimage and configuration files that have been fully tested. + +If needed, `rimage` can be built manually with the usual CMake commands: + +```shell +$ cmake -B build/ +$ make -C build/ help # lists all targets +$ make -C build/ +``` + +The `build/rimage` executable can then be copied to a directory in the PATH. Zephyr users can run `west config rimage.path /path/to/rimage/build/rimage`; Zephyr documentation and `west sign -h` have more details. + +## Testing tomlc99 changes with SOF Continuous Integration + +This section is about leveraging SOF validation to test tomlc99 changes _before_ submitting them to the tomlc99 repository. + +Nothing here is actually specific to SOF and tomlc99; you can apply the same test logic to any submodule and parent on GitHub. In fact the same logic applies to submodule alternatives. GitHub is the only requirement. + +### Get familiar with git submodules + +This is unfortunately not optional for SOF and tomlc99. + +For various reasons submodules seem to confuse many git users. Maybe because the versions of the submodules are not directly visible in some configuration file like with most alternatives? Either way, an unfortunate prerequisite before doing any tomlc99 work is to get familiar with git submodules in general. As submodules are built-in there are many resources about them on the Internet. One possible starting point is https://git-scm.com/book/en/v2/Git-Tools-Submodules but feel free to use any other good tutorial instead. Make sure you actually practice a tutorial; don't just read it. Practicing on a temporary and throw-away copy of SOF + tomlc99 is a great idea. + +Obviously, you also need to be familiar with regular GitHub pull requests. + +### Run SOF tests on unmerged tomlc99 commits + +First, push the tomlc99 commits you want to be tested to any branch of your tomlc99 fork on GitHub. Do _not_ submit a tomlc99 pull request yet. + +Note your tomlc99 fork must have been created using the actual "fork" button on GitHub so GitHub is aware of the connection with the upstream tomlc99 repo. In the top-left corner you should see `forked from thesofproject/tomlc99` under the name of your fork. If not then search the Internet for "re-attach detached github fork". + +Then, **pretend** these tomlc99 commits have already been accepted and merged (they have been neither) and submit to SOF a draft pull request that updates the main SOF branch with your brand new tomlc99 commits to test. The only SOF commit in this SOF TEST pull request is an SOF commit that updates the tomlc99 pointer to the SHA of your last tomlc99 commit. If you're not sure how to do this then you must go back to the previous section and practice submodules more. + +Submit this SOF pull request as a GitHub _draft_ so reviewers are _not_ notified. Starting every pull request as a draft is always a good idea but in this case this particular SOF pull request can be especially confusing because it points at commits in a different repo and commits that are not merged yet. So you _really_ don't want to bother busy reviewers (here's a secret: some of the reviewers don't like submodules either). You can freely switch back and forth between draft and ready status and should indeed switch to draft if you forgot at submission time but you can never "un-notify" reviewers. + +GitHub has very good support for submodules and will display your SOF TEST pull request better than what the git command line can show. For instance GitHub will list your tomlc99 changes directly in the SOF Pull Request. So if something looks unexpected on GitHub then it means you did something wrong. Stop immediately (except for switching to draft if you forgot) and ask the closest git guru for help. + +Search for "Submodule" in the build logs and make sure the last of your new tomlc99 commits has been checked out. + +Iterate and force-push your tomlc99 branch and your SOF TEST pull request until all the SOF tests pass. Then you can submit your tomlc99 pull request as usual. In the comments section of the tomlc99 pull request, point at your test results on the SOF side to impress the tomlc99 reviewers and get your tomlc99 changes merged faster. + +Finally, after your tomlc99 changes have been merged, you can if you want submit one final SOF pull request that points to the final tomlc99 SHA. Or, if your tomlc99 change is not urgently needed, you can just wait for someone else to do it later. If you do it, copy the tomlc99 git log --oneline in the SOF commit message. Find some good (and less good) commit message examples for submodule updates at https://github.com/thesofproject/sof/commits/main/rimage + +## Deep Dive: ELF to Image Conversion and Manifest Structure + +`rimage` is responsible for converting standard ELF libraries and executables into DSP-compatible firmware images. It parses input ELF files, extracts loadable sections, calculates cryptographic hashes and signatures, and encapsulates them with platform-specific manifests. + +### The Build Process (ELF to Image) + +```mermaid +graph TD + A[Command Line Args] --> B[Initialize ADSP Config] + C[Input ELF Files] --> D[Parse ELF Headers & Sections] + D --> E[Register Modules & Metadata] + B --> F[Allocate Manifest Memory] + E --> F + F --> G["Copy .text, .rodata to Image Buffer"] + G --> H["Hash Module Segments (SHA-256 / SHA-384)"] + H --> I["Finalize Manifest Headers (CSS/CSE/FW Desc)"] + I --> J[Sign Root Manifest with RSA Key] + J --> K[Write Output Files] + K --> L[.ri Signed Image] + K --> M[.uns Unsigned Module] + K --> N[.met Manifest Metadata] +``` + +1. **Configuration Initialization**: `rimage` parses its command-line arguments to find the ADSP machine configuration (e.g., Apollolake `apl`, Tigerlake `tgl`, Meteorlake `mtl`). This configuration defines the specific sizes, offsets, and versions the firmware image will require. +2. **Parsing ELF Files**: The `module_open()` and `module_parse_sections()` functions read the ELF headers (`.text`, `.rodata`, `.bss`). These sections are extracted to form the payload of the modules. +3. **Module Registration**: `rimage` reads either the `.module` metadata section directly from the embedded ELF, or a corresponding `TOML` configuration file, which holds instructions on module attributes (e.g., UUID, thread affinity, entry points). +4. **Manifest and Memory Allocation**: Space is pre-allocated for the firmware image. `man_init_image_xxx()` loads the ADSP template manifest into the start of the image buffer. Then, `man_copy_elf_sections()` copies `.text` and `.rodata` sections directly into the buffer, aligning properties sequentially up to `MAN_PAGE_SIZE` (4096 bytes). +5. **Cryptographic Hashing**: Using `hash_sha256()` or `hash_sha384()` (depending on the platform), `rimage` generates a cryptographic digest of each module's `.text` and `.rodata` block. These hash digests are stored in the respective `sof_man_module` entries of the manifest. +6. **Manifest Signing**: Once all modules and internal structures are mapped, the entire structure is finalized with converged security headers (`ri_css_xxx_hdr_create`, `ri_cse_create`). The root manifest signature is then signed (`ri_manifest_sign_...()`) with an RSA private key. +7. **Writing the Payload**: Finally, the newly encapsulated firmware is written to a `.ri` file (`man_write_fw_mod()`). `rimage` also outputs a stripped `.uns` (unsigned module payload) and `.met` (manifest metadata) file for debugging. + +### Manifest Structure + +```mermaid +graph TD + A[FW Image Manifest] + A --> B[1. CSS Header] + A --> C[2. CSE Header] + A --> D[3. Firmware Descriptor] + A --> E[4. Module Entries Array] + A --> F[5. ADSP Extension Metadata] + + B --> B1("RSA Signatures") + B --> B2("Public Key & Modulus") + + C --> C1("Security Partitions Directory") + + D --> D1("Versions & Build IDs") + D --> D2("num_module_entries") + + E --> E1[Module 0] + E --> E2[Module N] + E1 --> E1a("UUID, Entry Point") + E1 --> E1b("Segment Relative Offsets") + E1 --> E1c("SHA Hash of Sub-Segments") + + F --> F1("Proprietary Components") + F --> F2("Hardware Specific Hashes") +``` + +The firmware image begins with a structured Manifest. Different platforms use altered sizes and variants (e.g., v1.5, v1.8, v2.5, ace_v1.5), but they typically follow the same overarching hierarchy (note: ordering of CSS and CSE headers may be swapped depending on the manifest version - e.g., v1.8+/v2.5 places CSE first): + +1. **CSS Header** (CSS header struct, e.g. `struct css_header_v1_8`, `struct css_header_v2_5`): Cryptographic Signature Structure. Defines the fundamental size, modulus, public key, and RSA signatures used to authenticate the firmware image on the CSME/DSP side. +2. **CSE Header** (CSE partition directory header struct, e.g. `struct CsePartitionDirHeader`, `struct CsePartitionDirHeader_v2_5`): Converged Security Engine Header. A directory mapping security partitions to the ADSP firmware metadata. +3. **Firmware Descriptor** (`struct sof_man_fw_desc` and versioned variants): + - `header`: Holds the basic firmware versions, build IDs, `preload_page_count`, and the `num_module_entries`. +4. **Module Entries** (`struct sof_man_module`): An array corresponding to each module contained in the image. + - `struct_id`: Has the literal value `"$AME"`. + - `name`, `uuid`, `entry_point`, `affinity`. + - `segment`: Details on the relative position `file_offset` and memory offset `v_base_addr` of `.text`, `.rodata`, and `.bss` partitions. + - `hash`: SHA-256 or SHA-384 digest of the active segment. +5. **ADSP Extension Metadata** (e.g., `sof_man_adsp_meta_file_ext_v2_5`): Additional proprietary component descriptors attached after the base manifest, frequently hashed recursively for verification integrity. diff --git a/tools/rimage/config/acp_6_0.toml b/tools/rimage/config/acp_6_0.toml new file mode 100644 index 000000000000..f761b839399f --- /dev/null +++ b/tools/rimage/config/acp_6_0.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "acp_6_0" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x7F000000" +size = "0x40000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xE0000000" +size = "0xE0000" +host_offset = "0x0" diff --git a/tools/rimage/config/acp_6_3.toml b/tools/rimage/config/acp_6_3.toml new file mode 100644 index 000000000000..8a6286dde153 --- /dev/null +++ b/tools/rimage/config/acp_6_3.toml @@ -0,0 +1,20 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "acp_6_3" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x7F000000" +size = "0x60000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xE0000000" +size = "0x20000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x60006000" +size = "0x27A000" +host_offset = "0x0" diff --git a/tools/rimage/config/acp_7_0.toml b/tools/rimage/config/acp_7_0.toml new file mode 100644 index 000000000000..916bcb24f047 --- /dev/null +++ b/tools/rimage/config/acp_7_0.toml @@ -0,0 +1,20 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "acp_7_0" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x7F000000" +size = "0x60000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xE0000000" +size = "0x20000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x6000C000" +size = "0x274000" +host_offset = "0x0" \ No newline at end of file diff --git a/tools/rimage/config/apl.toml b/tools/rimage/config/apl.toml new file mode 100644 index 000000000000..e100c78a754c --- /dev/null +++ b/tools/rimage/config/apl.toml @@ -0,0 +1,57 @@ +version = [1, 8] + +[adsp] +name = "apl" +image_size = "0x0A0000" # (8 + 2) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xA000A000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x58" +length = "0x378" +[[cse.entry]] +name = "cavs0015.met" +offset = "0x400" +length = "0x60" +[[cse.entry]] +name = "cavs0015" +offset = "0x480" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "cavs0015.met" + +[partition_info] +name = "ADSP" +[[partition_info.module]] +name = "cavs0015.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x2000" diff --git a/tools/rimage/config/bdw.toml b/tools/rimage/config/bdw.toml new file mode 100644 index 000000000000..6b642fcd882e --- /dev/null +++ b/tools/rimage/config/bdw.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "bdw" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0" +size = "0x50000" +host_offset = "0x000A0000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x00400000" +size = "0xA0000" +host_offset = "0x0" diff --git a/tools/rimage/config/bsw.toml b/tools/rimage/config/bsw.toml new file mode 100644 index 000000000000..6746ca6cff34 --- /dev/null +++ b/tools/rimage/config/bsw.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "bsw" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0xFF2C0000" +size = "0x14000" +host_offset = "0x0C0000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xFF300000" +size = "0x28000" +host_offset = "0x100000" diff --git a/tools/rimage/config/byt.toml b/tools/rimage/config/byt.toml new file mode 100644 index 000000000000..4afd1c0dd523 --- /dev/null +++ b/tools/rimage/config/byt.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "byt" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0xFF2C0000" +size = "0x14000" +host_offset = "0x0C0000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xFF300000" +size = "0x28000" +host_offset = "0x100000" diff --git a/tools/rimage/config/cht.toml b/tools/rimage/config/cht.toml new file mode 100644 index 000000000000..2ed88370d16a --- /dev/null +++ b/tools/rimage/config/cht.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "cht" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0xFF2C0000" +size = "0x14000" +host_offset = "0x0C0000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xFF300000" +size = "0x28000" +host_offset = "0x100000" diff --git a/tools/rimage/config/cnl.toml b/tools/rimage/config/cnl.toml new file mode 100644 index 000000000000..ccf33fb68e2a --- /dev/null +++ b/tools/rimage/config/cnl.toml @@ -0,0 +1,61 @@ +version = [1, 8] + +[adsp] +name = "cnl" +image_size = "0x300000" # (47 + 1) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "IMR" +base = "0xB0038000" +size = "0x100000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xBE040000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x58" +length = "0x378" +[[cse.entry]] +name = "cavs0015.met" +offset = "0x400" +length = "0x60" +[[cse.entry]] +name = "cavs0015" +offset = "0x480" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "cavs0015.met" + +[partition_info] +name = "ADSP" +[[partition_info.module]] +name = "cavs0015.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x30000" diff --git a/tools/rimage/config/hsw.toml b/tools/rimage/config/hsw.toml new file mode 100644 index 000000000000..2f96a675b89d --- /dev/null +++ b/tools/rimage/config/hsw.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "hsw" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0" +size = "0x60000" +host_offset = "0x80000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x00400000" +size = "0x80000" +host_offset = "0x0" diff --git a/tools/rimage/config/icl.toml b/tools/rimage/config/icl.toml new file mode 100644 index 000000000000..f6e0fc9cb209 --- /dev/null +++ b/tools/rimage/config/icl.toml @@ -0,0 +1,61 @@ +version = [1, 8] + +[adsp] +name = "icl" +image_size = "0x300000" # (47 + 1) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "IMR" +base = "0xB0038000" +size = "0x100000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xBE040000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x58" +length = "0x378" +[[cse.entry]] +name = "cavs0015.met" +offset = "0x400" +length = "0x60" +[[cse.entry]] +name = "cavs0015" +offset = "0x480" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "cavs0015.met" + +[partition_info] +name = "ADSP" +[[partition_info.module]] +name = "cavs0015.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x30000" diff --git a/tools/rimage/config/imx8.toml b/tools/rimage/config/imx8.toml new file mode 100644 index 000000000000..865be902e840 --- /dev/null +++ b/tools/rimage/config/imx8.toml @@ -0,0 +1,20 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "imx8" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x596F8000" +size = "0x800" +host_offset = "0x10000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x596E8000" +size = "0x8000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x92400000" +size = "0x800000" +host_offset = "0x0" diff --git a/tools/rimage/config/imx8m.toml b/tools/rimage/config/imx8m.toml new file mode 100644 index 000000000000..5b7ba20870bd --- /dev/null +++ b/tools/rimage/config/imx8m.toml @@ -0,0 +1,20 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "imx8m" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x3b6F8000" +size = "0x800" +host_offset = "0x10000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x3B6E8000" +size = "0x8000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x92400000" +size = "0x800000" +host_offset = "0x0" diff --git a/tools/rimage/config/imx8m_cm7.toml b/tools/rimage/config/imx8m_cm7.toml new file mode 100644 index 000000000000..2ba4fb5d16f6 --- /dev/null +++ b/tools/rimage/config/imx8m_cm7.toml @@ -0,0 +1,15 @@ +version = [1, 0] + +[adsp] +name = "imx8m_cm7" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x0000000" +size = "0x2000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x80000000" +size = "0x100000" +host_offset = "0x0" diff --git a/tools/rimage/config/imx8ulp.toml b/tools/rimage/config/imx8ulp.toml new file mode 100644 index 000000000000..7fd4c16a52f3 --- /dev/null +++ b/tools/rimage/config/imx8ulp.toml @@ -0,0 +1,20 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "imx8ulp" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x21170000" +size = "0x10000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x21180000" +size = "0x10000" +host_offset = "0x10000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x1a000000" +size = "0x800000" +host_offset = "0x0" diff --git a/tools/rimage/config/imx8x.toml b/tools/rimage/config/imx8x.toml new file mode 100644 index 000000000000..ea9059c174ae --- /dev/null +++ b/tools/rimage/config/imx8x.toml @@ -0,0 +1,20 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "imx8x" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x596F8000" +size = "0x800" +host_offset = "0x10000" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x596e8000" +size = "0x8000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x92400000" +size = "0x800000" +host_offset = "0x0" diff --git a/tools/rimage/config/imx95.toml b/tools/rimage/config/imx95.toml new file mode 100644 index 000000000000..2aa395b53956 --- /dev/null +++ b/tools/rimage/config/imx95.toml @@ -0,0 +1,9 @@ +version = [1, 0] + +[adsp] +name = "imx95" + +[[adsp.mem_zone]] +type = "SRAM" +base = "0x80000000" +size = "0x100000" diff --git a/tools/rimage/config/jsl.toml b/tools/rimage/config/jsl.toml new file mode 100644 index 000000000000..bec0e6bd3a7e --- /dev/null +++ b/tools/rimage/config/jsl.toml @@ -0,0 +1,61 @@ +version = [1, 8] + +[adsp] +name = "icl" +image_size = "0x110000" # (16 + 1) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "IMR" +base = "0xB0038000" +size = "0x100000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xBE040000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x58" +length = "0x378" +[[cse.entry]] +name = "cavs0015.met" +offset = "0x400" +length = "0x60" +[[cse.entry]] +name = "cavs0015" +offset = "0x480" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "cavs0015.met" + +[partition_info] +name = "ADSP" +[[partition_info.module]] +name = "cavs0015.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x30000" diff --git a/tools/rimage/config/kbl.toml b/tools/rimage/config/kbl.toml new file mode 100644 index 000000000000..f1c83d594905 --- /dev/null +++ b/tools/rimage/config/kbl.toml @@ -0,0 +1,30 @@ +version = [1, 5] + +[adsp] +name = "kbl" +image_size = "0x200000" # (30 + 2) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xA000A000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[css] + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0" +hw_buf_base_addr = "0xBE500000" +hw_buf_length = "0x4A000" diff --git a/tools/rimage/config/lnl.toml.h b/tools/rimage/config/lnl.toml.h new file mode 100644 index 000000000000..7a574d4ae906 --- /dev/null +++ b/tools/rimage/config/lnl.toml.h @@ -0,0 +1,166 @@ +#include "platform-lnl.toml" + + [[module.entry]] + name = "BRNGUP" + uuid = UUIDREG_STR_BRNGUP + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + +#if CONFIG_COLD_STORE_EXECUTE_DRAM + [[module.entry]] + name = "COLD" + uuid = UUIDREG_STR_COLD + affinity_mask = "3" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ +#endif + + [[module.entry]] + name = "BASEFW" + uuid = UUIDREG_STR_BASEFW + affinity_mask = "3" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + +#if defined(CONFIG_COMP_TESTER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <debug/tester/tester.toml> +#endif + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_UP_DOWN_MIXER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/up_down_mixer/up_down_mixer.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_MUX) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mux/mux.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_TEMPLATE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/template/template.toml> +#endif + +#if defined(CONFIG_COMP_LEVEL_MULTIPLIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/level_multiplier/level_multiplier.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_TONE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tone/tone.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/config/mt8186.toml b/tools/rimage/config/mt8186.toml new file mode 100644 index 000000000000..80b011b4bfd4 --- /dev/null +++ b/tools/rimage/config/mt8186.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "mt8186" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x4e100000" +size = "0x00100000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x60000000" +size = "0x00600000" +host_offset = "0x0" diff --git a/tools/rimage/config/mt8188.toml b/tools/rimage/config/mt8188.toml new file mode 100644 index 000000000000..0dcc4b4b3244 --- /dev/null +++ b/tools/rimage/config/mt8188.toml @@ -0,0 +1,15 @@ +version = [1, 0] # parse_adsp_config_v1_0() + +[adsp] +name = "mt8188" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x4e100000" +size = "0x00080000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x60000000" +size = "0x00600000" +host_offset = "0x0" diff --git a/tools/rimage/config/mt8195.toml b/tools/rimage/config/mt8195.toml new file mode 100644 index 000000000000..5c8abc92557a --- /dev/null +++ b/tools/rimage/config/mt8195.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "mt8195" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x40000000" +size = "0x00040000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x60000000" +size = "0x00600000" +host_offset = "0x0" diff --git a/tools/rimage/config/mt8196.toml b/tools/rimage/config/mt8196.toml new file mode 100644 index 000000000000..1e66bab0b538 --- /dev/null +++ b/tools/rimage/config/mt8196.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "mt8196" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x4e100000" +size = "0x00080000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x90000000" +size = "0x00600000" +host_offset = "0x0" diff --git a/tools/rimage/config/mt8365.toml b/tools/rimage/config/mt8365.toml new file mode 100644 index 000000000000..1cec40f48ca5 --- /dev/null +++ b/tools/rimage/config/mt8365.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "mt8365" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x40020000" +size = "0x00040000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "SRAM" +base = "0x60000000" +size = "0x00600000" +host_offset = "0x0" diff --git a/tools/rimage/config/mtl.toml.h b/tools/rimage/config/mtl.toml.h new file mode 100644 index 000000000000..ec9436488ca3 --- /dev/null +++ b/tools/rimage/config/mtl.toml.h @@ -0,0 +1,186 @@ +#include "platform-mtl.toml" + + [[module.entry]] + name = "BRNGUP" + uuid = UUIDREG_STR_BRNGUP + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + +#if CONFIG_COLD_STORE_EXECUTE_DRAM + [[module.entry]] + name = "COLD" + uuid = UUIDREG_STR_COLD + affinity_mask = "3" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ +#endif + + [[module.entry]] + name = "BASEFW" + uuid = UUIDREG_STR_BASEFW + affinity_mask = "3" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + +#if defined(CONFIG_COMP_TESTER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <debug/tester/tester.toml> +#endif + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_UP_DOWN_MIXER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/up_down_mixer/up_down_mixer.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_MUX) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mux/mux.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/dolby/dax.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_ctc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_DTS_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/codec/dts/dts.toml> +#endif + +#if defined(CONFIG_WAVES_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/waves/waves.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_TEMPLATE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/template/template.toml> +#endif + +#if defined(CONFIG_COMP_TENSORFLOW) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tensorflow/tflmcly.toml> +#endif + +#if defined(CONFIG_COMP_LEVEL_MULTIPLIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/level_multiplier/level_multiplier.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_TONE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tone/tone.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/config/nvl.toml.h b/tools/rimage/config/nvl.toml.h new file mode 100644 index 000000000000..4fa0ca805877 --- /dev/null +++ b/tools/rimage/config/nvl.toml.h @@ -0,0 +1,158 @@ +#include "platform-nvl.toml" + +[[module.entry]] +name = "BRNGUP" +uuid = "2B79E4F3-4675-F649-89DF-3BC194A91AEB" +affinity_mask = "0x1" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ + +#if CONFIG_COLD_STORE_EXECUTE_DRAM +[[module.entry]] +name = "COLD" +uuid = UUIDREG_STR_COLD +affinity_mask = "3" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ +#endif + +[[module.entry]] +name = "BASEFW" +uuid = "0E398C32-5ADE-BA4B-93B1-C50432280EE4" +affinity_mask = "3" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ + +#if defined(CONFIG_COMP_TESTER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <debug/tester/tester.toml> +#endif + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_UP_DOWN_MIXER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/up_down_mixer/up_down_mixer.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_MUX) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mux/mux.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_TONE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tone/tone.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/config/platform-lnl.toml b/tools/rimage/config/platform-lnl.toml new file mode 100644 index 000000000000..b797cd4c525d --- /dev/null +++ b/tools/rimage/config/platform-lnl.toml @@ -0,0 +1,56 @@ +version = [3, 0] + +[adsp] +name = "lnl" +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 = "0x4b8" +[[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" +[[signed_pkg.module]] +name = "ADSP.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x40000" diff --git a/tools/rimage/config/platform-mtl.toml b/tools/rimage/config/platform-mtl.toml new file mode 100644 index 000000000000..fdce10fd4c94 --- /dev/null +++ b/tools/rimage/config/platform-mtl.toml @@ -0,0 +1,56 @@ +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 = "0x4b8" +[[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" +[[signed_pkg.module]] +name = "ADSP.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x40000" diff --git a/tools/rimage/config/platform-nvl.toml b/tools/rimage/config/platform-nvl.toml new file mode 100644 index 000000000000..89e3ce083ed2 --- /dev/null +++ b/tools/rimage/config/platform-nvl.toml @@ -0,0 +1,56 @@ +version = [3, 0] + +[adsp] +name = "nvl" +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 = "0x4b8" +[[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" +[[signed_pkg.module]] +name = "ADSP.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x40000" diff --git a/tools/rimage/config/platform-ptl.toml b/tools/rimage/config/platform-ptl.toml new file mode 100644 index 000000000000..e32b9a1776f9 --- /dev/null +++ b/tools/rimage/config/platform-ptl.toml @@ -0,0 +1,56 @@ +version = [3, 0] + +[adsp] +name = "ptl" +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 = "0x4b8" +[[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" +[[signed_pkg.module]] +name = "ADSP.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x40000" diff --git a/tools/rimage/config/platform-tgl-h.toml b/tools/rimage/config/platform-tgl-h.toml new file mode 100644 index 000000000000..8e98866d9bcb --- /dev/null +++ b/tools/rimage/config/platform-tgl-h.toml @@ -0,0 +1,60 @@ +version = [2, 5] + +[adsp] +name = "tgl" +image_size = "0x1F0000" # (30 + 1) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0x9F180000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "IMR" +base = "0xB0000000" +size = "0x1000000" +[[adsp.mem_zone]] +type = "HP-SRAM" +base = "0xBE000000" +size = "0x800000" +[[adsp.mem_zone]] +type = "LP-SRAM" +base = "0xBE800000" +size = "0x40" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x5c" +length = "0x464" +[[cse.entry]] +name = "cavs0015.met" +offset = "0x4c0" +length = "0x70" +[[cse.entry]] +name = "cavs0015" +offset = "0x540" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "cavs0015.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x30000" diff --git a/tools/rimage/config/platform-tgl.toml b/tools/rimage/config/platform-tgl.toml new file mode 100644 index 000000000000..ffbf15862ac4 --- /dev/null +++ b/tools/rimage/config/platform-tgl.toml @@ -0,0 +1,60 @@ +version = [2, 5] + +[adsp] +name = "tgl" +image_size = "0x2F0000" +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0x9F180000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "IMR" +base = "0xB0000000" +size = "0x1000000" +[[adsp.mem_zone]] +type = "HP-SRAM" +base = "0xBE000000" +size = "0x800000" +[[adsp.mem_zone]] +type = "LP-SRAM" +base = "0xBE800000" +size = "0x40" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x5c" +length = "0x464" +[[cse.entry]] +name = "cavs0015.met" +offset = "0x4c0" +length = "0x70" +[[cse.entry]] +name = "cavs0015" +offset = "0x540" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +[[signed_pkg.module]] +name = "cavs0015.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x30000" diff --git a/tools/rimage/config/platform.toml b/tools/rimage/config/platform.toml new file mode 100644 index 000000000000..978323fa4ebc --- /dev/null +++ b/tools/rimage/config/platform.toml @@ -0,0 +1,9 @@ +#if CONFIG_METEORLAKE +#include "platform-mtl.toml" +#elif CONFIG_LUNARLAKE +#include "platform-lnl.toml" +#elif CONFIG_SOC_ACE30 +#include "platform-ptl.toml" +#elif CONFIG_SOC_ACE40 +#include "platform-nvl.toml" +#endif diff --git a/tools/rimage/config/ptl.toml.h b/tools/rimage/config/ptl.toml.h new file mode 100644 index 000000000000..e622c8af968e --- /dev/null +++ b/tools/rimage/config/ptl.toml.h @@ -0,0 +1,178 @@ +#include "platform-ptl.toml" + +[[module.entry]] +name = "BRNGUP" +uuid = UUIDREG_STR_BRNGUP +affinity_mask = "0x1" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ + +#if CONFIG_COLD_STORE_EXECUTE_DRAM +[[module.entry]] +name = "COLD" +uuid = UUIDREG_STR_COLD +affinity_mask = "3" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ +#endif + +[[module.entry]] +name = "BASEFW" +uuid = UUIDREG_STR_BASEFW +affinity_mask = "3" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ + +#if defined(CONFIG_COMP_TESTER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <debug/tester/tester.toml> +#endif + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_UP_DOWN_MIXER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/up_down_mixer/up_down_mixer.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_MUX) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mux/mux.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/dolby/dax.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_CTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_ctc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_DTS_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/codec/dts/dts.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_TEMPLATE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/template/template.toml> +#endif + +#if defined(CONFIG_COMP_LEVEL_MULTIPLIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/level_multiplier/level_multiplier.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_TONE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tone/tone.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/config/rmb.toml b/tools/rimage/config/rmb.toml new file mode 100644 index 000000000000..7d43f3a3dc33 --- /dev/null +++ b/tools/rimage/config/rmb.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "rmb" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x7F000000" +size = "0x40000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xE0000000" +size = "0xE0000" +host_offset = "0x0" diff --git a/tools/rimage/config/rn.toml b/tools/rimage/config/rn.toml new file mode 100644 index 000000000000..d4e0b34b685c --- /dev/null +++ b/tools/rimage/config/rn.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "rn" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x20000000" +size = "0x40000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0x21000000" +size = "0xE0000" +host_offset = "0x0" diff --git a/tools/rimage/config/skl.toml b/tools/rimage/config/skl.toml new file mode 100644 index 000000000000..0fff3a382bbf --- /dev/null +++ b/tools/rimage/config/skl.toml @@ -0,0 +1,30 @@ +version = [1, 5] + +[adsp] +name = "skl" +image_size = "0x200000" # (30 + 2) bank * 64KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xA000A000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[css] + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0" +hw_buf_base_addr = "0xBE500000" +hw_buf_length = "0x4A000" diff --git a/tools/rimage/config/sue.toml b/tools/rimage/config/sue.toml new file mode 100644 index 000000000000..7579c7fcfb06 --- /dev/null +++ b/tools/rimage/config/sue.toml @@ -0,0 +1,31 @@ +version = [1, 5] + +[adsp] +name = "sue" +image_size = "0x300000" # (47 + 1) bank * 64KB +exec_boot_ldr = 1 +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0xBEFE0000" +size = "0x00002000" +[[adsp.mem_zone]] +type = "IMR" +base = "0xb0038000" +size = "0x100000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xbe000000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x9E000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xBE000000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x2000" diff --git a/tools/rimage/config/tgl-h.toml.h b/tools/rimage/config/tgl-h.toml.h new file mode 100644 index 000000000000..ea5dc5d4b262 --- /dev/null +++ b/tools/rimage/config/tgl-h.toml.h @@ -0,0 +1,136 @@ +#include "platform-tgl-h.toml" + + [[module.entry]] + name = "BRNGUP" + uuid = UUIDREG_STR_BRNGUP + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + + [[module.entry]] + name = "BASEFW" + uuid = UUIDREG_STR_BASEFW + affinity_mask = "3" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_TEMPLATE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/template/template.toml> +#endif + +#if defined(CONFIG_COMP_LEVEL_MULTIPLIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/level_multiplier/level_multiplier.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/config/tgl.toml.h b/tools/rimage/config/tgl.toml.h new file mode 100644 index 000000000000..2ca246880727 --- /dev/null +++ b/tools/rimage/config/tgl.toml.h @@ -0,0 +1,136 @@ +#include "platform-tgl.toml" + + [[module.entry]] + name = "BRNGUP" + uuid = UUIDREG_STR_BRNGUP + affinity_mask = "0x1" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + + [[module.entry]] + name = "BASEFW" + uuid = UUIDREG_STR_BASEFW + affinity_mask = "3" + instance_count = "1" + domain_types = "0" + load_type = "0" + module_type = "0" + auto_start = "0" + + index = __COUNTER__ + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_TEMPLATE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/template/template.toml> +#endif + +#if defined(CONFIG_COMP_LEVEL_MULTIPLIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/level_multiplier/level_multiplier.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/config/vangogh.toml b/tools/rimage/config/vangogh.toml new file mode 100644 index 000000000000..c5acdb9c9ba3 --- /dev/null +++ b/tools/rimage/config/vangogh.toml @@ -0,0 +1,15 @@ +version = [1, 0] # use simple file write + +[adsp] +name = "vangogh" + +[[adsp.mem_zone]] +type = "IRAM" +base = "0x20000000" +size = "0x40000" +host_offset = "0x0" +[[adsp.mem_zone]] +type = "DRAM" +base = "0xE0000000" +size = "0x100000" +host_offset = "0x0" diff --git a/tools/rimage/config/wcl.toml.h b/tools/rimage/config/wcl.toml.h new file mode 100644 index 000000000000..058383af6e46 --- /dev/null +++ b/tools/rimage/config/wcl.toml.h @@ -0,0 +1,162 @@ +#include "platform-ptl.toml" + +[[module.entry]] +name = "BRNGUP" +uuid = UUIDREG_STR_BRNGUP +affinity_mask = "0x1" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ + +#if CONFIG_COLD_STORE_EXECUTE_DRAM +[[module.entry]] +name = "COLD" +uuid = UUIDREG_STR_COLD +affinity_mask = "3" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ +#endif + +[[module.entry]] +name = "BASEFW" +uuid = UUIDREG_STR_BASEFW +affinity_mask = "3" +instance_count = "1" +domain_types = "0" +load_type = "0" +module_type = "0" +auto_start = "0" + +index = __COUNTER__ + +#if defined(CONFIG_COMP_TESTER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <debug/tester/tester.toml> +#endif + +#if defined(CONFIG_COMP_MIXIN_MIXOUT) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mixin_mixout/mixin_mixout.toml> +#endif + +#if defined(CONFIG_COMP_COPIER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/copier/copier.toml> +#endif + +#if defined(CONFIG_COMP_VOLUME) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/volume/volume.toml> +#endif + +#if defined(CONFIG_COMP_ASRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/asrc/asrc.toml> +#endif + +#if defined(CONFIG_COMP_SRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/src/src.toml> +#endif + +#if defined(CONFIG_CADENCE_CODEC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/module_adapter/module/cadence.toml> +#endif + +#if defined(CONFIG_COMP_SEL) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/selector/selector.toml> +#endif + +#if defined(CONFIG_COMP_UP_DOWN_MIXER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/up_down_mixer/up_down_mixer.toml> +#endif + +#ifdef CONFIG_PROBE +#include <probe/probe.toml> +#endif + +#if defined(CONFIG_COMP_MUX) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mux/mux.toml> +#endif + +#ifdef CONFIG_SAMPLE_KEYPHRASE +#include <samples/audio/detect_test.toml> +#endif + +#if defined(CONFIG_COMP_KPB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/kpb.toml> +#endif + +#if defined(CONFIG_SAMPLE_SMART_AMP) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <samples/audio/smart_amp_test.toml> +#endif + +#if defined(CONFIG_COMP_IIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_iir/eq_iir.toml> +#endif + +#if defined(CONFIG_COMP_FIR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/eq_fir/eq_fir.toml> +#endif + +#if defined(CONFIG_COMP_ARIA) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/aria/aria.toml> +#endif + +#if defined(CONFIG_COMP_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/drc/drc.toml> +#endif + +#if defined(CONFIG_COMP_CROSSOVER) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/crossover/crossover.toml> +#endif + +#if defined(CONFIG_COMP_MULTIBAND_DRC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/multiband_drc/multiband_drc.toml> +#endif + +#if defined(CONFIG_COMP_DCBLOCK) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/dcblock/dcblock.toml> +#endif + +#if defined(CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/google/google_rtc_audio_processing.toml> +#endif + +#if defined(CONFIG_COMP_TDFB) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tdfb/tdfb.toml> +#endif + +#if defined(CONFIG_COMP_RTNR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/rtnr/rtnr.toml> +#endif + +#if defined(CONFIG_COMP_IGO_NR) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/igo_nr/igo_nr.toml> +#endif + +#if defined(CONFIG_COMP_MFCC) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/mfcc/mfcc.toml> +#endif + +#if defined(CONFIG_COMP_TEMPLATE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/template/template.toml> +#endif + +#if defined(CONFIG_COMP_SOUND_DOSE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/sound_dose/sound_dose.toml> +#endif + +#if defined(CONFIG_COMP_TONE) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/tone/tone.toml> +#endif + +#if defined(CONFIG_COMP_STFT_PROCESS) || defined(LLEXT_FORCE_ALL_MODULAR) +#include <audio/stft_process/stft_process.toml> +#endif + +[module] +count = __COUNTER__ diff --git a/tools/rimage/scripts/spelling.txt b/tools/rimage/scripts/spelling.txt new file mode 100644 index 000000000000..9a058cff49d4 --- /dev/null +++ b/tools/rimage/scripts/spelling.txt @@ -0,0 +1,1254 @@ +# Originally from Debian's Lintian tool. Various false positives have been +# removed, and various additions have been made as they've been discovered +# in the kernel source. +# +# License: GPLv2 +# +# The format of each line is: +# mistake||correction +# +abandonning||abandoning +abigious||ambiguous +abitrate||arbitrate +abov||above +abreviated||abbreviated +absense||absence +absolut||absolute +absoulte||absolute +acccess||access +acceess||access +acceleratoin||acceleration +accelleration||acceleration +accesing||accessing +accesnt||accent +accessable||accessible +accesss||access +accidentaly||accidentally +accidentually||accidentally +accoding||according +accomodate||accommodate +accomodates||accommodates +accordign||according +accoring||according +accout||account +accquire||acquire +accquired||acquired +accross||across +acessable||accessible +acess||access +achitecture||architecture +acient||ancient +acitions||actions +acitve||active +acknowldegement||acknowledgment +acknowledgement||acknowledgment +ackowledge||acknowledge +ackowledged||acknowledged +acording||according +activete||activate +actived||activated +actualy||actually +acumulating||accumulating +acumulator||accumulator +adapater||adapter +addional||additional +additionaly||additionally +additonal||additional +addres||address +adddress||address +addreses||addresses +addresss||address +aditional||additional +aditionally||additionally +aditionaly||additionally +adminstrative||administrative +adress||address +adresses||addresses +adviced||advised +afecting||affecting +againt||against +agaist||against +aggreataon||aggregation +aggreation||aggregation +albumns||albums +alegorical||allegorical +algined||aligned +algorith||algorithm +algorithmical||algorithmically +algoritm||algorithm +algoritms||algorithms +algorrithm||algorithm +algorritm||algorithm +aligment||alignment +alignement||alignment +allign||align +alligned||aligned +alllocate||allocate +alloated||allocated +allocatote||allocate +allocatrd||allocated +allocte||allocate +allpication||application +alocate||allocate +alogirhtms||algorithms +alogrithm||algorithm +alot||a lot +alow||allow +alows||allows +altough||although +alue||value +ambigious||ambiguous +amoung||among +amout||amount +an union||a union +an user||a user +an userspace||a userspace +an one||a one +analysator||analyzer +ang||and +anniversery||anniversary +annoucement||announcement +anomolies||anomalies +anomoly||anomaly +anway||anyway +aplication||application +appearence||appearance +applicaion||application +appliction||application +applictions||applications +applys||applies +appplications||applications +appropiate||appropriate +appropriatly||appropriately +approriate||appropriate +approriately||appropriately +apropriate||appropriate +aquainted||acquainted +aquired||acquired +aquisition||acquisition +arbitary||arbitrary +architechture||architecture +arguement||argument +arguements||arguments +aritmetic||arithmetic +arne't||aren't +arraival||arrival +artifical||artificial +artillary||artillery +asign||assign +asser||assert +assertation||assertion +assiged||assigned +assigment||assignment +assigments||assignments +assistent||assistant +assocation||association +associcated||associated +assotiated||associated +assum||assume +assumtpion||assumption +asuming||assuming +asycronous||asynchronous +asynchnous||asynchronous +atomatically||automatically +atomicly||atomically +atempt||attempt +attachement||attachment +attched||attached +attemps||attempts +attemping||attempting +attruibutes||attributes +authentification||authentication +automaticaly||automatically +automaticly||automatically +automatize||automate +automatized||automated +automatizes||automates +autonymous||autonomous +auxillary||auxiliary +auxilliary||auxiliary +avaiable||available +avaible||available +availabe||available +availabled||available +availablity||availability +availale||available +availavility||availability +availble||available +availiable||available +availible||available +avalable||available +avaliable||available +aysnc||async +backgroud||background +backword||backward +backwords||backwards +bahavior||behavior +bakup||backup +baloon||balloon +baloons||balloons +bandwith||bandwidth +banlance||balance +batery||battery +beacuse||because +becasue||because +becomming||becoming +becuase||because +beeing||being +befor||before +begining||beginning +beter||better +betweeen||between +bianries||binaries +bitmast||bitmask +boardcast||broadcast +borad||board +boundry||boundary +brievely||briefly +broadcat||broadcast +cacluated||calculated +caculation||calculation +calender||calendar +calescing||coalescing +calle||called +callibration||calibration +calucate||calculate +calulate||calculate +cancelation||cancellation +cancle||cancel +capabilites||capabilities +capabilty||capability +capabitilies||capabilities +capatibilities||capabilities +capapbilities||capabilities +carefuly||carefully +cariage||carriage +catagory||category +cehck||check +challange||challenge +challanges||challenges +chanell||channel +changable||changeable +chanined||chained +channle||channel +channnel||channel +charachter||character +charachters||characters +charactor||character +charater||character +charaters||characters +charcter||character +chcek||check +chck||check +checksuming||checksumming +childern||children +childs||children +chiled||child +chked||checked +chnage||change +chnages||changes +chnnel||channel +choosen||chosen +chouse||chose +circumvernt||circumvent +claread||cleared +clared||cleared +closeing||closing +clustred||clustered +coexistance||coexistence +collapsable||collapsible +colorfull||colorful +comand||command +comit||commit +commerical||commercial +comming||coming +comminucation||communication +commited||committed +commiting||committing +committ||commit +commoditiy||commodity +comsume||consume +comsumer||consumer +comsuming||consuming +compability||compatibility +compaibility||compatibility +compatability||compatibility +compatable||compatible +compatibiliy||compatibility +compatibilty||compatibility +compatiblity||compatibility +competion||completion +compilant||compliant +compleatly||completely +completition||completion +completly||completely +complient||compliant +componnents||components +compoment||component +compres||compress +compresion||compression +comression||compression +comunication||communication +conbination||combination +conditionaly||conditionally +conected||connected +connecetd||connected +configuartion||configuration +configuratoin||configuration +configuraton||configuration +configuretion||configuration +configutation||configuration +conider||consider +conjuction||conjunction +connectinos||connections +connnection||connection +connnections||connections +consistancy||consistency +consistant||consistent +containes||contains +containts||contains +contaisn||contains +contant||contact +contence||contents +continious||continuous +continous||continuous +continously||continuously +continueing||continuing +contraints||constraints +contol||control +contoller||controller +controled||controlled +controler||controller +controll||control +contruction||construction +contry||country +conuntry||country +convertion||conversion +convertor||converter +convienient||convenient +convinient||convenient +corected||corrected +correponding||corresponding +correponds||corresponds +correspoding||corresponding +cotrol||control +cound||could +couter||counter +coutner||counter +cryptocraphic||cryptographic +cunter||counter +curently||currently +cylic||cyclic +dafault||default +deafult||default +deamon||daemon +decompres||decompress +decription||description +dectected||detected +defailt||default +defferred||deferred +definate||definite +definately||definitely +defintion||definition +defintions||definitions +defualt||default +defult||default +deintializing||deinitializing +deintialize||deinitialize +deintialized||deinitialized +deivce||device +delared||declared +delare||declare +delares||declares +delaring||declaring +delemiter||delimiter +demodualtor||demodulator +demension||dimension +dependancies||dependencies +dependancy||dependency +dependant||dependent +depreacted||deprecated +depreacte||deprecate +desactivate||deactivate +desciptor||descriptor +desciptors||descriptors +descripton||description +descrition||description +descritptor||descriptor +desctiptor||descriptor +desriptor||descriptor +desriptors||descriptors +destionation||destination +destory||destroy +destoryed||destroyed +destorys||destroys +destroied||destroyed +detabase||database +deteced||detected +develope||develop +developement||development +developped||developed +developpement||development +developper||developer +developpment||development +deveolpment||development +devided||divided +deviece||device +diable||disable +dictionnary||dictionary +didnt||didn't +diferent||different +differrence||difference +diffrent||different +diffrentiate||differentiate +difinition||definition +dimesions||dimensions +diplay||display +direectly||directly +disassocation||disassociation +disapear||disappear +disapeared||disappeared +disappared||disappeared +disble||disable +disbled||disabled +disconnet||disconnect +discontinous||discontinuous +dispertion||dispersion +dissapears||disappears +distiction||distinction +docuentation||documentation +documantation||documentation +documentaion||documentation +documment||document +doesnt||doesn't +dorp||drop +dosen||doesn +downlad||download +downlads||downloads +druing||during +dynmaic||dynamic +easilly||easily +ecspecially||especially +edditable||editable +editting||editing +efective||effective +efficently||efficiently +ehther||ether +eigth||eight +elementry||elementary +eletronic||electronic +embeded||embedded +enabledi||enabled +enchanced||enhanced +encorporating||incorporating +encrupted||encrypted +encrypiton||encryption +encryptio||encryption +endianess||endianness +enhaced||enhanced +enlightnment||enlightenment +entrys||entries +enocded||encoded +enterily||entirely +enviroiment||environment +enviroment||environment +environement||environment +environent||environment +eqivalent||equivalent +equiped||equipped +equivelant||equivalent +equivilant||equivalent +eror||error +errorr||error +estbalishment||establishment +etsablishment||establishment +etsbalishment||establishment +excecutable||executable +exceded||exceeded +excellant||excellent +exeed||exceed +existance||existence +existant||existent +exixt||exist +exlcude||exclude +exlcusive||exclusive +exmaple||example +expecially||especially +explicite||explicit +explicitely||explicitly +explict||explicit +explictely||explicitly +explictly||explicitly +expresion||expression +exprimental||experimental +extened||extended +extensability||extensibility +extention||extension +extracter||extractor +falied||failed +faild||failed +faill||fail +failied||failed +faillure||failure +failue||failure +failuer||failure +failng||failing +faireness||fairness +falied||failed +faliure||failure +fallbck||fallback +familar||familiar +fatser||faster +feauture||feature +feautures||features +fetaure||feature +fetaures||features +fileystem||filesystem +fimware||firmware +firware||firmware +finanize||finalize +findn||find +finilizes||finalizes +finsih||finish +flusing||flushing +folloing||following +followign||following +followings||following +follwing||following +fonud||found +forseeable||foreseeable +forse||force +fortan||fortran +forwardig||forwarding +framming||framing +framwork||framework +frequncy||frequency +frome||from +fucntion||function +fuction||function +fuctions||functions +funcion||function +functionallity||functionality +functionaly||functionally +functionnality||functionality +functonality||functionality +funtion||function +funtions||functions +furthur||further +futhermore||furthermore +futrue||future +gaurenteed||guaranteed +generiously||generously +genereate||generate +genric||generic +globel||global +grabing||grabbing +grahical||graphical +grahpical||graphical +grapic||graphic +grranted||granted +guage||gauge +guarenteed||guaranteed +guarentee||guarantee +halfs||halves +hander||handler +handfull||handful +hanled||handled +happend||happened +harware||hardware +heirarchically||hierarchically +helpfull||helpful +hybernate||hibernate +hierachy||hierarchy +hierarchie||hierarchy +howver||however +hsould||should +hypervior||hypervisor +hypter||hyper +identidier||identifier +iligal||illegal +illigal||illegal +imblance||imbalance +immeadiately||immediately +immedaite||immediate +immediatelly||immediately +immediatly||immediately +immidiate||immediate +impelentation||implementation +impementated||implemented +implemantation||implementation +implemenation||implementation +implementaiton||implementation +implementated||implemented +implemention||implementation +implementd||implemented +implemetation||implementation +implemntation||implementation +implentation||implementation +implmentation||implementation +implmenting||implementing +incative||inactive +incomming||incoming +incompatabilities||incompatibilities +incompatable||incompatible +inconsistant||inconsistent +increas||increase +incremeted||incremented +incrment||increment +indendation||indentation +indended||intended +independant||independent +independantly||independently +independed||independent +indiate||indicate +indicat||indicate +inexpect||inexpected +infomation||information +informatiom||information +informations||information +informtion||information +infromation||information +ingore||ignore +inital||initial +initalized||initialized +initalised||initialized +initalise||initialize +initalize||initialize +initation||initiation +initators||initiators +initialiazation||initialization +initializiation||initialization +initialzed||initialized +initilization||initialization +initilize||initialize +inofficial||unofficial +insititute||institute +instal||install +instanciated||instantiated +inteface||interface +integreated||integrated +integrety||integrity +integrey||integrity +intendet||intended +intented||intended +interanl||internal +interchangable||interchangeable +interferring||interfering +interger||integer +intermittant||intermittent +internel||internal +interoprability||interoperability +interuupt||interrupt +interrface||interface +interrrupt||interrupt +interrup||interrupt +interrups||interrupts +interruptted||interrupted +interupted||interrupted +interupt||interrupt +intial||initial +intialisation||initialisation +intialised||initialised +intialise||initialise +intialization||initialization +intialized||initialized +intialize||initialize +intregral||integral +intrrupt||interrupt +intterrupt||interrupt +intuative||intuitive +invaid||invalid +invald||invalid +invalde||invalid +invalide||invalid +invalidiate||invalidate +invalud||invalid +invididual||individual +invokation||invocation +invokations||invocations +irrelevent||irrelevant +isnt||isn't +isssue||issue +iternations||iterations +itertation||iteration +itslef||itself +jave||java +jeffies||jiffies +juse||just +jus||just +kown||known +langage||language +langauage||language +langauge||language +langugage||language +lauch||launch +layed||laid +leightweight||lightweight +lengh||length +lenght||length +lenth||length +lesstiff||lesstif +libaries||libraries +libary||library +librairies||libraries +libraris||libraries +licenceing||licencing +loggging||logging +loggin||login +logile||logfile +loosing||losing +losted||lost +machinary||machinery +maintainance||maintenance +maintainence||maintenance +maintan||maintain +makeing||making +malplaced||misplaced +malplace||misplace +managable||manageable +managment||management +mangement||management +manoeuvering||maneuvering +mappping||mapping +mathimatical||mathematical +mathimatic||mathematic +mathimatics||mathematics +maxium||maximum +mechamism||mechanism +meetign||meeting +ment||meant +mergable||mergeable +mesage||message +messags||messages +messgaes||messages +messsage||message +messsages||messages +micropone||microphone +microprocesspr||microprocessor +milliseonds||milliseconds +minium||minimum +minimam||minimum +minumum||minimum +misalinged||misaligned +miscelleneous||miscellaneous +misformed||malformed +mispelled||misspelled +mispelt||misspelt +mising||missing +mismactch||mismatch +missmanaged||mismanaged +missmatch||mismatch +miximum||maximum +mmnemonic||mnemonic +mnay||many +modulues||modules +momery||memory +memomry||memory +monochorome||monochrome +monochromo||monochrome +monocrome||monochrome +mopdule||module +mroe||more +mulitplied||multiplied +multidimensionnal||multidimensional +multple||multiple +mumber||number +muticast||multicast +mutilcast||multicast +mutiple||multiple +mutli||multi +nams||names +navagating||navigating +nead||need +neccecary||necessary +neccesary||necessary +neccessary||necessary +necesary||necessary +neded||needed +negaive||negative +negoitation||negotiation +negotation||negotiation +nerver||never +nescessary||necessary +nessessary||necessary +noticable||noticeable +notications||notifications +notifed||notified +numebr||number +numner||number +obtaion||obtain +occassionally||occasionally +occationally||occasionally +occurance||occurrence +occurances||occurrences +occured||occurred +occurence||occurrence +occure||occurred +occured||occurred +occuring||occurring +offet||offset +omited||omitted +omiting||omitting +omitt||omit +ommiting||omitting +ommitted||omitted +onself||oneself +ony||only +operatione||operation +opertaions||operations +optionnal||optional +optmizations||optimizations +orientatied||orientated +orientied||oriented +orignal||original +otherise||otherwise +ouput||output +oustanding||outstanding +overaall||overall +overhread||overhead +overlaping||overlapping +overide||override +overrided||overridden +overriden||overridden +overun||overrun +overwritting||overwriting +overwriten||overwritten +pacakge||package +pachage||package +packacge||package +packege||package +packge||package +packtes||packets +pakage||package +pallette||palette +paln||plan +paramameters||parameters +paramaters||parameters +paramater||parameter +parametes||parameters +parametised||parametrised +paramter||parameter +paramters||parameters +particuarly||particularly +particularily||particularly +partiton||partition +pased||passed +passin||passing +pathes||paths +pecularities||peculiarities +peformance||performance +peice||piece +pendantic||pedantic +peprocessor||preprocessor +perfoming||performing +permissons||permissions +peroid||period +persistance||persistence +persistant||persistent +plalform||platform +platfrom||platform +plattform||platform +pleaes||please +ploting||plotting +plugable||pluggable +poinnter||pointer +pointeur||pointer +poiter||pointer +posible||possible +positon||position +possibilites||possibilities +powerfull||powerful +preample||preamble +preapre||prepare +preceeded||preceded +preceeding||preceding +preceed||precede +precendence||precedence +precission||precision +preemptable||preemptible +prefered||preferred +prefferably||preferably +premption||preemption +prepaired||prepared +pressre||pressure +primative||primitive +princliple||principle +priorty||priority +privilaged||privileged +privilage||privilege +priviledge||privilege +priviledges||privileges +probaly||probably +procceed||proceed +proccesors||processors +procesed||processed +proces||process +procesing||processing +processessing||processing +processess||processes +processpr||processor +processsed||processed +processsing||processing +procteted||protected +prodecure||procedure +progams||programs +progess||progress +programers||programmers +programm||program +programms||programs +progresss||progress +promiscous||promiscuous +promps||prompts +pronnounced||pronounced +prononciation||pronunciation +pronouce||pronounce +pronunce||pronounce +propery||property +propigate||propagate +propigation||propagation +propogate||propagate +prosess||process +protable||portable +protcol||protocol +protecion||protection +protocoll||protocol +promixity||proximity +psudo||pseudo +psuedo||pseudo +psychadelic||psychedelic +pwoer||power +quering||querying +randomally||randomly +raoming||roaming +reasearcher||researcher +reasearchers||researchers +reasearch||research +recepient||recipient +receving||receiving +recieved||received +recieve||receive +reciever||receiver +recieves||receives +recogniced||recognised +recognizeable||recognizable +recommanded||recommended +recyle||recycle +redircet||redirect +redirectrion||redirection +reename||rename +refcounf||refcount +refence||reference +refered||referred +referenace||reference +refering||referring +refernces||references +refernnce||reference +refrence||reference +registerd||registered +registeresd||registered +registerred||registered +registes||registers +registraration||registration +regsiter||register +regster||register +regualar||regular +reguator||regulator +regulamentations||regulations +reigstration||registration +releated||related +relevent||relevant +remoote||remote +remore||remote +removeable||removable +repectively||respectively +replacable||replaceable +replacments||replacements +replys||replies +reponse||response +representaion||representation +reqeust||request +requestied||requested +requiere||require +requirment||requirement +requred||required +requried||required +requst||request +reseting||resetting +resizeable||resizable +resouce||resource +resouces||resources +resoures||resources +responce||response +ressizes||resizes +ressource||resource +ressources||resources +retransmited||retransmitted +retreived||retrieved +retreive||retrieve +retrive||retrieve +retuned||returned +reudce||reduce +reuest||request +reuqest||request +reutnred||returned +revsion||revision +rmeoved||removed +rmeove||remove +rmeoves||removes +rountine||routine +routins||routines +rquest||request +runing||running +runned||ran +runnning||running +runtine||runtime +sacrifying||sacrificing +safly||safely +safty||safety +savable||saveable +scaned||scanned +scaning||scanning +scarch||search +seach||search +searchs||searches +secquence||sequence +secund||second +segement||segment +senarios||scenarios +sentivite||sensitive +separatly||separately +sepcify||specify +sepc||spec +seperated||separated +seperately||separately +seperate||separate +seperatly||separately +seperator||separator +sepperate||separate +sequece||sequence +sequencial||sequential +serveral||several +setts||sets +settting||setting +shotdown||shutdown +shoud||should +shouldnt||shouldn't +shoule||should +shrinked||shrunk +siginificantly||significantly +signabl||signal +similary||similarly +similiar||similar +simlar||similar +simliar||similar +simpified||simplified +singaled||signaled +singal||signal +singed||signed +sleeped||slept +softwares||software +speach||speech +specfic||specific +speciefied||specified +specifc||specific +specifed||specified +specificatin||specification +specificaton||specification +specifing||specifying +specifiying||specifying +speficied||specified +speicify||specify +speling||spelling +spinlcok||spinlock +spinock||spinlock +splitted||split +spreaded||spread +spurrious||spurious +sructure||structure +stablilization||stabilization +staically||statically +staion||station +standardss||standards +standartization||standardization +standart||standard +staticly||statically +stoped||stopped +stoppped||stopped +straming||streaming +struc||struct +structres||structures +stuct||struct +strucuture||structure +stucture||structure +sturcture||structure +subdirectoires||subdirectories +suble||subtle +substract||subtract +submition||submission +succesfully||successfully +succesful||successful +successed||succeeded +successfull||successful +successfuly||successfully +sucessfully||successfully +sucess||success +superflous||superfluous +superseeded||superseded +suplied||supplied +suported||supported +suport||support +supportet||supported +suppored||supported +supportin||supporting +suppoted||supported +suppported||supported +suppport||support +supress||suppress +surpressed||suppressed +surpresses||suppresses +susbsystem||subsystem +suspeneded||suspended +suspicously||suspiciously +swaping||swapping +switchs||switches +swith||switch +swithable||switchable +swithc||switch +swithced||switched +swithcing||switching +swithed||switched +swithing||switching +swtich||switch +symetric||symmetric +synax||syntax +synchonized||synchronized +syncronize||synchronize +syncronized||synchronized +syncronizing||synchronizing +syncronus||synchronous +syste||system +sytem||system +sythesis||synthesis +taht||that +targetted||targeted +targetting||targeting +teh||the +temorary||temporary +temproarily||temporarily +therfore||therefore +thier||their +threds||threads +threshhold||threshold +thresold||threshold +throught||through +troughput||throughput +thses||these +tiggered||triggered +tipically||typically +timout||timeout +tmis||this +torerable||tolerable +tramsmitted||transmitted +tramsmit||transmit +tranasction||transaction +tranfer||transfer +transciever||transceiver +transferd||transferred +transfered||transferred +transfering||transferring +transision||transition +transmittd||transmitted +transormed||transformed +trasfer||transfer +trasmission||transmission +treshold||threshold +trigerring||triggering +trun||turn +tunning||tuning +ture||true +tyep||type +udpate||update +uesd||used +uncommited||uncommitted +unconditionaly||unconditionally +underun||underrun +unecessary||unnecessary +unexecpted||unexpected +unexepected||unexpected +unexpcted||unexpected +unexpectd||unexpected +unexpeted||unexpected +unexpexted||unexpected +unfortunatelly||unfortunately +unifiy||unify +unintialized||uninitialized +unkmown||unknown +unknonw||unknown +unknow||unknown +unkown||unknown +unneded||unneeded +unneccecary||unnecessary +unneccesary||unnecessary +unneccessary||unnecessary +unnecesary||unnecessary +unneedingly||unnecessarily +unnsupported||unsupported +unmached||unmatched +unregester||unregister +unresgister||unregister +unrgesiter||unregister +unsinged||unsigned +unstabel||unstable +unsolicitied||unsolicited +unsuccessfull||unsuccessful +unsuported||unsupported +untill||until +unuseful||useless +upate||update +usefule||useful +usefull||useful +usege||usage +usera||users +usualy||usually +utilites||utilities +utillities||utilities +utilties||utilities +utiltity||utility +utitity||utility +utitlty||utility +vaid||valid +vaild||valid +valide||valid +variantions||variations +varible||variable +varient||variant +vaule||value +verbse||verbose +verisons||versions +verison||version +verson||version +vicefersa||vice-versa +virtal||virtual +virtaul||virtual +virtiual||virtual +visiters||visitors +vitual||virtual +wakeus||wakeups +wating||waiting +wiat||wait +wether||whether +whataver||whatever +whcih||which +whenver||whenever +wheter||whether +whe||when +wierd||weird +wiil||will +wirte||write +withing||within +wnat||want +workarould||workaround +writeing||writing +writting||writing +zombe||zombie +zomebie||zombie diff --git a/tools/rimage/src/adsp_config.c b/tools/rimage/src/adsp_config.c new file mode 100644 index 000000000000..6cc7434e74bc --- /dev/null +++ b/tools/rimage/src/adsp_config.c @@ -0,0 +1,2376 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#include "rimage/sof/user/manifest.h" +#include "rimage/sof/user/manifest.h" +#include "rimage/adsp_config.h" +#include "rimage/ext_manifest_gen.h" +#include "rimage/plat_auth.h" +#include "rimage/manifest.h" +#include "rimage/rimage.h" +#include "rimage/cse.h" +#include "rimage/css.h" +#include "rimage/toml_utils.h" +#include "rimage/file_utils.h" +#include "toml.h" +#include <stdbool.h> +#include <stdint.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <ctype.h> + +/* map memory zone string name to enum value */ +static enum snd_sof_fw_blk_type zone_name_to_idx(const char *name) +{ + static const struct { + const char name[32]; + enum snd_sof_fw_blk_type type; + } mem_zone_name_dict[] = { + {"START", SOF_FW_BLK_TYPE_START}, + {"IRAM", SOF_FW_BLK_TYPE_IRAM}, + {"DRAM", SOF_FW_BLK_TYPE_DRAM}, + {"SRAM", SOF_FW_BLK_TYPE_SRAM}, + {"ROM", SOF_FW_BLK_TYPE_ROM}, + {"IMR", SOF_FW_BLK_TYPE_IMR}, + {"RSRVD0", SOF_FW_BLK_TYPE_RSRVD0}, + {"HP-SRAM", SOF_FW_BLK_TYPE_HPSRAM}, + {"LP-SRAM", SOF_FW_BLK_TYPE_LPSRAM}, + {"RSRVD8", SOF_FW_BLK_TYPE_RSRVD8}, + {"RSRVD9", SOF_FW_BLK_TYPE_RSRVD9}, + {"RSRVD10", SOF_FW_BLK_TYPE_RSRVD10}, + {"RSRVD11", SOF_FW_BLK_TYPE_RSRVD11}, + {"RSRVD12", SOF_FW_BLK_TYPE_RSRVD12}, + {"RSRVD13", SOF_FW_BLK_TYPE_RSRVD13}, + {"RSRVD14", SOF_FW_BLK_TYPE_RSRVD14}, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(mem_zone_name_dict); ++i) { + if (!strcmp(name, mem_zone_name_dict[i].name)) + return mem_zone_name_dict[i].type; + } + return SOF_FW_BLK_TYPE_INVALID; +} + +static void dump_adsp(const struct adsp *adsp) +{ + int i; + + DUMP("\nadsp"); + DUMP_KEY("name", "'%s'", adsp->name); + DUMP_KEY("image_size", "0x%x", adsp->image_size); + DUMP_KEY("exec_boot_ldr", "%d", adsp->exec_boot_ldr); + for (i = 0; i < ARRAY_SIZE(adsp->mem.zones); ++i) { + DUMP_KEY("mem_zone.idx", "%d", i); + DUMP_KEY("mem_zone.size", "0x%x", adsp->mem.zones[i].size); + DUMP_KEY("mem_zone.base", "0x%x", adsp->mem.zones[i].base); + DUMP_KEY("mem_zone.host_offset", "0x%x", adsp->mem.zones[i].host_offset); + } +} + +static int parse_adsp(const toml_table_t *toml, struct parse_ctx *pctx, struct adsp *out, + bool verbose) +{ + toml_array_t *mem_zone_array, *alias_array; + struct memory_zone *zone; + struct parse_ctx ctx; + toml_table_t *adsp; + toml_raw_t raw; + int zone_idx; + char a_kind; + int a_size; + bool alias_found; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + adsp = toml_table_in(toml, "adsp"); + if (!adsp) + return err_key_not_found("adsp"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + raw = toml_raw_in(adsp, "name"); + if (!raw) + return err_key_not_found("name"); + ++ctx.key_cnt; + + /* free(out->name) is called in adsp_free() */ + ret = toml_rtos(raw, (char **)&out->name); + if (ret < 0) + return err_key_parse("name", NULL); + + out->image_size = parse_uint32_hex_key(adsp, &ctx, "image_size", 0, &ret); + if (ret < 0) + return ret; + + out->exec_boot_ldr = parse_uint32_key(adsp, &ctx, "exec_boot_ldr", 0, &ret); + if (ret < 0) + return ret; + + memset(&out->mem, 0, sizeof(out->mem)); + out->mem.alias.mask = parse_uint32_hex_key(adsp, &ctx, "alias_mask", -ENODATA, &ret); + alias_found = !ret; + + /* check everything parsed, 1 or 2 tables should be present */ + ctx.array_cnt += 1 + alias_found; + ret = assert_everything_parsed(adsp, &ctx); + if (ret < 0) + return ret; + + if (alias_found) { + alias_array = toml_array_in(adsp, "mem_alias"); + if (!alias_array) + return err_key_not_found("mem_alias"); + a_kind = toml_array_kind(alias_array); + a_size = toml_array_nelem(alias_array); + if (a_kind != 't' || a_size != 2) + return err_key_parse("mem_alias", "wrong array type %c or length %d", + a_kind, a_size); + + /* retrieve "cached" and "uncached" alias base addresses */ + for (i = 0; i < a_size; ++i) { + toml_table_t *alias = toml_table_at(alias_array, i); + char alias_name[16]; + uint32_t base; + + if (!alias) + return err_key_parse("mem_alias", NULL); + + parse_str_key(alias, &ctx, "type", alias_name, sizeof(alias_name), &ret); + if (ret < 0) + return err_key_parse("mem_alias", NULL); + + base = parse_uint32_hex_key(alias, &ctx, "base", -1, &ret); + + if (!strncmp("cached", alias_name, sizeof("cached"))) + out->mem.alias.cached = base & out->mem.alias.mask; + else if (!strncmp("uncached", alias_name, sizeof("uncached"))) + out->mem.alias.uncached = base & out->mem.alias.mask; + } + } else { + /* Make uncache_to_cache() an identity transform */ + out->mem.alias.uncached = 0; + out->mem.alias.cached = 0; + out->mem.alias.mask = 0; + } + + /* look for entry array */ + mem_zone_array = toml_array_in(adsp, "mem_zone"); + if (!mem_zone_array) + return err_key_not_found("mem_zone"); + a_kind = toml_array_kind(mem_zone_array); + a_size = toml_array_nelem(mem_zone_array); + if (a_kind != 't' || a_size > SOF_FW_BLK_TYPE_NUM) + return err_key_parse("mem_zone", "wrong array type %c or length %d", + a_kind, a_size); + + /* parse entry array elements */ + for (i = 0; i < a_size; ++i) { + toml_table_t *mem_zone = toml_table_at(mem_zone_array, i); + char zone_name[32]; + + if (!mem_zone) + return err_key_parse("mem_zone", NULL); + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + parse_str_key(mem_zone, &ctx, "type", zone_name, sizeof(zone_name), &ret); + if (ret < 0) + return err_key_parse("mem_zone", NULL); + + zone_idx = zone_name_to_idx(zone_name); + if (zone_idx < 0) + return err_key_parse("mem_zone.name", "unknown zone '%s'", zone_name); + + zone = &out->mem.zones[zone_idx]; + zone->base = parse_uint32_hex_key(mem_zone, &ctx, "base", -1, &ret); + if (ret < 0) + return err_key_parse("mem_zone", NULL); + + zone->host_offset = parse_uint32_hex_key(mem_zone, &ctx, "host_offset", 0, + &ret); + if (ret < 0) + return err_key_parse("mem_zone", NULL); + + zone->size = parse_uint32_hex_key(mem_zone, &ctx, "size", -1, &ret); + if (ret < 0) + return err_key_parse("mem_zone", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(mem_zone, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_adsp(out); + + /* + * values set in other places in code: + * - write_firmware + * - write_firmware_meu + * - man_vX_Y + */ + + return 0; +} + +static void dump_cse(const struct CsePartitionDirHeader *cse_header, + const struct CsePartitionDirEntry *cse_entry) +{ + int i; + + DUMP("\ncse"); + DUMP_PRINTABLE_BYTES("partition_name", cse_header->partition_name); + DUMP_KEY("header_version", "%d", cse_header->header_version); + DUMP_KEY("entry_version", "%d", cse_header->entry_version); + DUMP_KEY("nb_entries", "%d", cse_header->nb_entries); + for (i = 0; i < cse_header->nb_entries; ++i) { + DUMP_PRINTABLE_BYTES("entry.name", cse_entry[i].entry_name); + DUMP_KEY("entry.offset", "0x%x", cse_entry[i].offset); + DUMP_KEY("entry.length", "0x%x", cse_entry[i].length); + } +} + +static int parse_cse(const toml_table_t *toml, struct parse_ctx *pctx, + struct CsePartitionDirHeader *hdr, struct CsePartitionDirEntry *out, + int entry_capacity, bool verbose) +{ + toml_array_t *cse_entry_array; + toml_table_t *cse_entry; + struct parse_ctx ctx; + toml_table_t *cse; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + cse = toml_table_in(toml, "cse"); + if (!cse) + return err_key_not_found("cse"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + hdr->header_marker = CSE_HEADER_MAKER; + hdr->header_length = sizeof(struct CsePartitionDirHeader); + + /* configurable fields */ + hdr->header_version = parse_uint8_key(cse, &ctx, "header_version", 1, &ret); + if (ret < 0) + return ret; + + hdr->entry_version = parse_uint8_key(cse, &ctx, "entry_version", 1, &ret); + if (ret < 0) + return ret; + + parse_printable_key(cse, &ctx, "partition_name", hdr->partition_name, + sizeof(hdr->partition_name), &ret); + if (ret < 0) + return ret; + + /* check everything parsed, expect 1 table */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(cse, &ctx); + if (ret < 0) + return ret; + + /* entry array */ + cse_entry_array = toml_array_in(cse, "entry"); + if (!cse_entry_array) + return err_key_not_found("entry"); + if (toml_array_kind(cse_entry_array) != 't' || + toml_array_nelem(cse_entry_array) != entry_capacity) + return err_key_parse("entry", "wrong array type or length != %d", entry_capacity); + + /* parse entry array elements */ + for (i = 0; i < toml_array_nelem(cse_entry_array); ++i) { + cse_entry = toml_table_at(cse_entry_array, i); + if (!cse_entry) + return err_key_parse("entry", NULL); + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + parse_printable_key(cse_entry, &ctx, "name", out[i].entry_name, + sizeof(out[i].entry_name), &ret); + if (ret < 0) + return err_key_parse("entry", NULL); + + out[i].offset = parse_uint32_hex_key(cse_entry, &ctx, "offset", -1, &ret); + if (ret < 0) + return err_key_parse("entry", NULL); + + out[i].length = parse_uint32_hex_key(cse_entry, &ctx, "length", -1, &ret); + if (ret < 0) + return err_key_parse("entry", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(cse_entry, &ctx); + if (ret < 0) + return ret; + } + + hdr->nb_entries = toml_array_nelem(cse_entry_array); + + if (verbose) + dump_cse(hdr, out); + + /* + * values set in other places in code: + * - checksum + */ + + return 0; +} + +static void dump_cse_v2_5(const struct CsePartitionDirHeader_v2_5 *cse_header, + const struct CsePartitionDirEntry *cse_entry) +{ + int i; + + DUMP("\ncse"); + DUMP_PRINTABLE_BYTES("partition_name", cse_header->partition_name); + DUMP_KEY("header_version", "%d", cse_header->header_version); + DUMP_KEY("entry_version", "%d", cse_header->entry_version); + DUMP_KEY("nb_entries", "%d", cse_header->nb_entries); + for (i = 0; i < cse_header->nb_entries; ++i) { + DUMP_PRINTABLE_BYTES("entry.name", cse_entry[i].entry_name); + DUMP_KEY("entry.offset", "0x%x", cse_entry[i].offset); + DUMP_KEY("entry.length", "0x%x", cse_entry[i].length); + } +} + +/* TODO: fix up constants in headers for v2.5 */ +static int parse_cse_v2_5(const toml_table_t *toml, struct parse_ctx *pctx, + struct CsePartitionDirHeader_v2_5 *hdr, struct CsePartitionDirEntry *out, + int entry_capacity, bool verbose) +{ + toml_array_t *cse_entry_array; + toml_table_t *cse_entry; + struct parse_ctx ctx; + toml_table_t *cse; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + cse = toml_table_in(toml, "cse"); + if (!cse) + return err_key_not_found("cse"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + hdr->header_marker = CSE_HEADER_MAKER; + hdr->header_length = sizeof(struct CsePartitionDirHeader_v2_5); + + /* configurable fields */ + hdr->header_version = parse_uint8_key(cse, &ctx, "header_version", 2, &ret); + if (ret < 0) + return ret; + + hdr->entry_version = parse_uint8_key(cse, &ctx, "entry_version", 1, &ret); + if (ret < 0) + return ret; + + parse_printable_key(cse, &ctx, "partition_name", hdr->partition_name, + sizeof(hdr->partition_name), &ret); + if (ret < 0) + return ret; + + /* check everything parsed, expect 1 table */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(cse, &ctx); + if (ret < 0) + return ret; + + /* entry array */ + cse_entry_array = toml_array_in(cse, "entry"); + if (!cse_entry_array) + return err_key_not_found("entry"); + if (toml_array_kind(cse_entry_array) != 't' || + toml_array_nelem(cse_entry_array) != entry_capacity) + return err_key_parse("entry", "wrong array type or length != %d", entry_capacity); + + /* parse entry array elements */ + for (i = 0; i < toml_array_nelem(cse_entry_array); ++i) { + cse_entry = toml_table_at(cse_entry_array, i); + if (!cse_entry) + return err_key_parse("entry", NULL); + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + parse_printable_key(cse_entry, &ctx, "name", out[i].entry_name, + sizeof(out[i].entry_name), &ret); + if (ret < 0) + return err_key_parse("entry", NULL); + + out[i].offset = parse_uint32_hex_key(cse_entry, &ctx, "offset", -1, &ret); + if (ret < 0) + return err_key_parse("offset", NULL); + + out[i].length = parse_uint32_hex_key(cse_entry, &ctx, "length", -1, &ret); + if (ret < 0) + return err_key_parse("length", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(cse_entry, &ctx); + if (ret < 0) + return ret; + } + + hdr->nb_entries = toml_array_nelem(cse_entry_array); + + if (verbose) + dump_cse_v2_5(hdr, out); + + /* + * values set in other places in code: + * - checksum + */ + + return 0; +} + +static void dump_css_v1_5(const struct css_header_v1_5 *css) +{ + DUMP("\ncss 1.5"); + DUMP_KEY("module_type", "%d", css->module_type); + DUMP_KEY("header_len", "%d", css->header_len); + DUMP_KEY("header_version", "0x%x", css->header_version); + DUMP_KEY("module_vendor", "0x%x", css->module_vendor); + DUMP_KEY("size", "%d", css->size); + DUMP_KEY("key_size", "%d", css->key_size); + DUMP_KEY("modulus_size", "%d", css->modulus_size); + DUMP_KEY("exponent_size", "%d", css->exponent_size); +} + +static int parse_css_v1_5(const toml_table_t *toml, struct parse_ctx *pctx, + struct css_header_v1_5 *out, bool verbose) +{ + struct parse_ctx ctx; + toml_table_t *css; + int ret; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + css = toml_table_in(toml, "css"); + if (!css) + return err_key_not_found("css"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + out->module_type = parse_uint32_key(css, &ctx, "module_type", MAN_CSS_LT_MODULE_TYPE, &ret); + if (ret < 0) + return ret; + + out->header_len = parse_uint32_key(css, &ctx, "header_len", MAN_CSS_HDR_SIZE, &ret); + if (ret < 0) + return ret; + + out->header_version = parse_uint32_hex_key(css, &ctx, "header_version", MAN_CSS_HDR_VERSION, + &ret); + if (ret < 0) + return ret; + out->module_vendor = parse_uint32_hex_key(css, &ctx, "module_vendor", MAN_CSS_MOD_VENDOR, + &ret); + if (ret < 0) + return ret; + + out->size = parse_uint32_key(css, &ctx, "size", 0x800, &ret); + if (ret < 0) + return ret; + + out->key_size = parse_uint32_key(css, &ctx, "key_size", MAN_CSS_KEY_SIZE, &ret); + if (ret < 0) + return ret; + + out->modulus_size = parse_uint32_key(css, &ctx, "modulus_size", MAN_CSS_MOD_SIZE, &ret); + if (ret < 0) + return ret; + + out->exponent_size = parse_uint32_key(css, &ctx, "exponent_size", MAN_CSS_EXP_SIZE, &ret); + if (ret < 0) + return ret; + + /* check everything parsed */ + ret = assert_everything_parsed(css, &ctx); + if (ret < 0) + return ret; + + if (verbose) + dump_css_v1_5(out); + + /* + * values set in other places in code: + * - date + * - version + * - modulus + * - exponent + * - signature + */ + + return 0; +} + +static void dump_css_v1_8(const struct css_header_v1_8 *css) +{ + DUMP("\ncss 1.8"); + DUMP_KEY("header_type", "%d", css->header_type); + DUMP_KEY("header_len", "%d", css->header_len); + DUMP_KEY("header_version", "0x%x", css->header_version); + DUMP_KEY("module_vendor", "0x%x", css->module_vendor); + DUMP_KEY("size", "%d", css->size); + DUMP_KEY("svn", "%d", css->svn); + DUMP_KEY("modulus_size", "%d", css->modulus_size); + DUMP_KEY("exponent_size", "%d", css->exponent_size); +} + +static int parse_css_v1_8(const toml_table_t *toml, struct parse_ctx *pctx, + struct css_header_v1_8 *out, bool verbose) +{ + static const uint8_t hdr_id[4] = MAN_CSS_HDR_ID; + struct parse_ctx ctx; + toml_table_t *css; + int ret; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + css = toml_table_in(toml, "css"); + if (!css) + return err_key_not_found("css"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + memcpy(out->header_id, hdr_id, sizeof(out->header_id)); + + /* configurable fields */ + out->header_type = parse_uint32_key(css, &ctx, "header_type", MAN_CSS_MOD_TYPE, &ret); + if (ret < 0) + return ret; + + out->header_len = parse_uint32_key(css, &ctx, "header_len", MAN_CSS_HDR_SIZE, &ret); + if (ret < 0) + return ret; + + out->header_version = parse_uint32_hex_key(css, &ctx, "header_version", MAN_CSS_HDR_VERSION, + &ret); + if (ret < 0) + return ret; + out->module_vendor = parse_uint32_hex_key(css, &ctx, "module_vendor", MAN_CSS_MOD_VENDOR, + &ret); + if (ret < 0) + return ret; + + out->size = parse_uint32_key(css, &ctx, "size", 222, &ret); + if (ret < 0) + return ret; + + out->svn = parse_uint32_key(css, &ctx, "svn", 0, &ret); + if (ret < 0) + return ret; + + out->modulus_size = parse_uint32_key(css, &ctx, "modulus_size", MAN_CSS_MOD_SIZE, &ret); + if (ret < 0) + return ret; + + out->exponent_size = parse_uint32_key(css, &ctx, "exponent_size", MAN_CSS_EXP_SIZE, &ret); + if (ret < 0) + return ret; + + /* check everything parsed */ + ret = assert_everything_parsed(css, &ctx); + if (ret < 0) + return ret; + + if (verbose) + dump_css_v1_8(out); + + /* + * values set in other places in code: + * - date + * - version + * - modulus + * - exponent + * - signature + */ + + return 0; +} + +static void dump_css_v2_5(const struct css_header_v2_5 *css) +{ + DUMP("\ncss 2.5"); + DUMP_KEY("header_type", "%d", css->header_type); + DUMP_KEY("header_len", "%d", css->header_len); + DUMP_KEY("header_version", "0x%x", css->header_version); + DUMP_KEY("module_vendor", "0x%x", css->module_vendor); + DUMP_KEY("size", "%d", css->size); + DUMP_KEY("svn", "%d", css->svn); + DUMP_KEY("modulus_size", "%d", css->modulus_size); + DUMP_KEY("exponent_size", "%d", css->exponent_size); +} + +static int parse_css_v2_5(const toml_table_t *toml, struct parse_ctx *pctx, + struct css_header_v2_5 *out, bool verbose) +{ + static const uint8_t hdr_id[4] = MAN_CSS_HDR_ID; + struct parse_ctx ctx; + toml_table_t *css; + int ret; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + css = toml_table_in(toml, "css"); + if (!css) + return err_key_not_found("css"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + memcpy(out->header_id, hdr_id, sizeof(out->header_id)); + + /* configurable fields */ + out->header_type = parse_uint32_key(css, &ctx, "header_type", MAN_CSS_MOD_TYPE, &ret); + if (ret < 0) + return ret; + + out->header_len = parse_uint32_key(css, &ctx, "header_len", MAN_CSS_HDR_SIZE_2_5, &ret); + if (ret < 0) + return ret; + + out->header_version = parse_uint32_hex_key(css, &ctx, "header_version", MAN_CSS_HDR_VERSION_2_5, + &ret); + if (ret < 0) + return ret; + out->module_vendor = parse_uint32_hex_key(css, &ctx, "module_vendor", MAN_CSS_MOD_VENDOR, + &ret); + if (ret < 0) + return ret; + + out->size = parse_uint32_key(css, &ctx, "size", 281, &ret); + if (ret < 0) + return ret; + + out->svn = parse_uint32_key(css, &ctx, "svn", 0, &ret); + if (ret < 0) + return ret; + + out->modulus_size = parse_uint32_key(css, &ctx, "modulus_size", MAN_CSS_MOD_SIZE_2_5, &ret); + if (ret < 0) + return ret; + + out->exponent_size = parse_uint32_key(css, &ctx, "exponent_size", MAN_CSS_EXP_SIZE, &ret); + if (ret < 0) + return ret; + + /* hardcoded to align with meu */ + out->reserved1[0] = 0xf; + out->reserved1[1] = 0x048e0000; // TODO: what is this ? + + /* check everything parsed */ + ret = assert_everything_parsed(css, &ctx); + if (ret < 0) + return ret; + + if (verbose) + dump_css_v2_5(out); + + /* + * values set in other places in code: + * - date + * - version + * - modulus + * - exponent + * - signature + */ + + return 0; +} + +static void dump_signed_pkg(const struct signed_pkg_info_ext *signed_pkg) +{ + int i; + + DUMP("\nsigned_pkg"); + DUMP_PRINTABLE_BYTES("name", signed_pkg->name); + DUMP_KEY("vcn", "%d", signed_pkg->vcn); + DUMP_KEY("svn", "%d", signed_pkg->svn); + DUMP_KEY("fw_type", "%d", signed_pkg->fw_type); + DUMP_KEY("fw_sub_type", "%d", signed_pkg->fw_sub_type); + for (i = 0; i < ARRAY_SIZE(signed_pkg->bitmap); ++i) + DUMP_KEY("bitmap", "%d", signed_pkg->bitmap[i]); + for (i = 0; i < ARRAY_SIZE(signed_pkg->module); ++i) { + DUMP_PRINTABLE_BYTES("meta.name", signed_pkg->module[i].name); + DUMP_KEY("meta.type", "0x%x", signed_pkg->module[i].type); + DUMP_KEY("meta.hash_algo", "0x%x", signed_pkg->module[i].hash_algo); + DUMP_KEY("meta.hash_size", "0x%x", signed_pkg->module[i].hash_size); + DUMP_KEY("meta.meta_size", "%d", signed_pkg->module[i].meta_size); + } +} + +static int parse_signed_pkg(const toml_table_t *toml, struct parse_ctx *pctx, + struct image *image, bool verbose) +{ + struct adsp *adsp = image->adsp; + struct signed_pkg_info_ext *out = &adsp->man_v1_8->signed_pkg; + struct signed_pkg_info_module *mod; + toml_array_t *bitmap_array; + toml_array_t *module_array; + toml_table_t *signed_pkg; + struct parse_ctx ctx; + toml_table_t *module; + toml_raw_t raw; + int64_t temp_i; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + signed_pkg = toml_table_in(toml, "signed_pkg"); + if (!signed_pkg) + return err_key_not_found("signed_pkg"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + out->ext_type = SIGN_PKG_EXT_TYPE; + out->ext_len = sizeof(struct signed_pkg_info_ext); + + /* configurable fields */ + parse_printable_key(signed_pkg, &ctx, "name", out->name, sizeof(out->name), &ret); + if (ret < 0) + return ret; + + out->vcn = parse_uint32_key(signed_pkg, &ctx, "vcn", 0, &ret); + if (ret < 0) + return ret; + + out->svn = parse_uint32_key(signed_pkg, &ctx, "svn", 0, &ret); + if (ret < 0) + return ret; + + out->fw_type = parse_uint8_hex_key(signed_pkg, &ctx, "fw_type", 0, &ret); + if (ret < 0) + return ret; + + out->fw_sub_type = parse_uint8_hex_key(signed_pkg, &ctx, "fw_sub_type", 0, &ret); + if (ret < 0) + return ret; + + /* bitmap array */ + bitmap_array = toml_array_in(signed_pkg, "bitmap"); + if (!bitmap_array) { + /* default value, depending on the IMR type */ + out->bitmap[4] = image->imr_type == 4 ? 0x10 : 0x8; + } else { + ++ctx.array_cnt; + if (toml_array_kind(bitmap_array) != 'v' || toml_array_type(bitmap_array) != 'i' || + toml_array_nelem(bitmap_array) > ARRAY_SIZE(out->bitmap)) + return err_key_parse("bitmap", "wrong array type or length > %d", + ARRAY_SIZE(out->bitmap)); + + for (i = 0; i < toml_array_nelem(bitmap_array); ++i) { + raw = toml_raw_at(bitmap_array, i); + if (!raw) + return err_key_parse("bitmap", NULL); + + ret = toml_rtoi(raw, &temp_i); + if (ret < 0 || temp_i < 0) + return err_key_parse("bitmap", "values can't be negative"); + out->bitmap[i] = temp_i; + } + } + + /* check everything parsed, expect 1 more array */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(signed_pkg, &ctx); + if (ret < 0) + return ret; + + /* modules array */ + module_array = toml_array_in(signed_pkg, "module"); + if (!module_array) + return err_key_not_found("module"); + if (toml_array_kind(module_array) != 't' || + toml_array_nelem(module_array) != ARRAY_SIZE(out->module)) + return err_key_parse("module", "wrong array type or length != %d", + ARRAY_SIZE(out->module)); + + /* parse modules array elements */ + for (i = 0; i < toml_array_nelem(module_array); ++i) { + module = toml_table_at(module_array, i); + if (!module) + return err_key_parse("module", NULL); + mod = &out->module[i]; + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + parse_printable_key(module, &ctx, "name", mod->name, sizeof(mod->name), &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->type = parse_uint8_hex_key(module, &ctx, "type", 0x03, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->hash_algo = parse_uint8_hex_key(module, &ctx, "hash_algo", 0x02, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->hash_size = parse_uint16_hex_key(module, &ctx, "hash_size", 0x20, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->meta_size = parse_uint32_key(module, &ctx, "meta_size", 96, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(module, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_signed_pkg(out); + + /* + * values set in other places in code: + * - module.hash + */ + + return 0; +} + +static void dump_signed_pkg_v2_5(const struct signed_pkg_info_ext_v2_5 *signed_pkg) +{ + int i; + + DUMP("\nsigned_pkg"); + DUMP_PRINTABLE_BYTES("name", signed_pkg->name); + DUMP_KEY("vcn", "%d", signed_pkg->vcn); + DUMP_KEY("svn", "%d", signed_pkg->svn); + DUMP_KEY("fw_type", "%d", signed_pkg->fw_type); + DUMP_KEY("fw_sub_type", "%d", signed_pkg->fw_sub_type); + for (i = 0; i < ARRAY_SIZE(signed_pkg->bitmap); ++i) + DUMP_KEY("bitmap", "%d", signed_pkg->bitmap[i]); + for (i = 0; i < ARRAY_SIZE(signed_pkg->module); ++i) { + DUMP_PRINTABLE_BYTES("meta.name", signed_pkg->module[i].name); + DUMP_KEY("meta.type", "0x%x", signed_pkg->module[i].type); + DUMP_KEY("meta.hash_algo", "0x%x", signed_pkg->module[i].hash_algo); + DUMP_KEY("meta.hash_size", "0x%x", signed_pkg->module[i].hash_size); + DUMP_KEY("meta.meta_size", "%d", signed_pkg->module[i].meta_size); + } +} + +static int parse_signed_pkg_v2_5(const toml_table_t *toml, struct parse_ctx *pctx, + struct image *image, bool verbose) +{ + struct adsp *adsp = image->adsp; + struct signed_pkg_info_ext_v2_5 *out = &adsp->man_v2_5->signed_pkg; + struct signed_pkg_info_module_v2_5 *mod; + toml_array_t *bitmap_array; + toml_array_t *module_array; + toml_table_t *signed_pkg; + struct parse_ctx ctx; + toml_table_t *module; + toml_raw_t raw; + int64_t temp_i; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + signed_pkg = toml_table_in(toml, "signed_pkg"); + if (!signed_pkg) + return err_key_not_found("signed_pkg"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + out->ext_type = SIGN_PKG_EXT_TYPE; + out->ext_len = sizeof(struct signed_pkg_info_ext_v2_5); + + /* configurable fields */ + parse_printable_key(signed_pkg, &ctx, "name", out->name, sizeof(out->name), &ret); + if (ret < 0) + return ret; + + out->vcn = parse_uint32_key(signed_pkg, &ctx, "vcn", 0, &ret); + if (ret < 0) + return ret; + + out->svn = parse_uint32_key(signed_pkg, &ctx, "svn", 0, &ret); + if (ret < 0) + return ret; + + out->fw_type = parse_uint8_hex_key(signed_pkg, &ctx, "fw_type", 0, &ret); + if (ret < 0) + return ret; + + out->fw_sub_type = parse_uint8_hex_key(signed_pkg, &ctx, "fw_sub_type", 0, &ret); + if (ret < 0) + return ret; + + /* bitmap array */ + bitmap_array = toml_array_in(signed_pkg, "bitmap"); + if (!bitmap_array) { + /* default value, depending on the IMR type */ + out->bitmap[4] = image->imr_type == 4 ? 0x10 : 0x8; + } else { + ++ctx.array_cnt; + if (toml_array_kind(bitmap_array) != 'v' || toml_array_type(bitmap_array) != 'i' || + toml_array_nelem(bitmap_array) > ARRAY_SIZE(out->bitmap)) + return err_key_parse("bitmap", "wrong array type or length > %d", + ARRAY_SIZE(out->bitmap)); + + for (i = 0; i < toml_array_nelem(bitmap_array); ++i) { + raw = toml_raw_at(bitmap_array, i); + if (!raw) + return err_key_parse("bitmap", NULL); + + ret = toml_rtoi(raw, &temp_i); + if (ret < 0 || temp_i < 0) + return err_key_parse("bitmap", "values can't be negative"); + out->bitmap[i] = temp_i; + } + } + + /* check everything parsed, expect 1 more array */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(signed_pkg, &ctx); + if (ret < 0) + return ret; + + /* modules array */ + module_array = toml_array_in(signed_pkg, "module"); + if (!module_array) + return err_key_not_found("module"); + if (toml_array_kind(module_array) != 't' || + toml_array_nelem(module_array) != ARRAY_SIZE(out->module)) + return err_key_parse("module", "wrong array type or length != %d", + ARRAY_SIZE(out->module)); + + /* parse modules array elements */ + for (i = 0; i < toml_array_nelem(module_array); ++i) { + module = toml_table_at(module_array, i); + if (!module) + return err_key_parse("module", NULL); + mod = &out->module[i]; + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + parse_printable_key(module, &ctx, "name", mod->name, sizeof(mod->name), &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->type = parse_uint8_hex_key(module, &ctx, "type", 0x03, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->hash_algo = parse_uint8_hex_key(module, &ctx, "hash_algo", 0x00, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->hash_size = parse_uint16_hex_key(module, &ctx, "hash_size", 0x30, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->meta_size = parse_uint32_key(module, &ctx, "meta_size", 112, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(module, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_signed_pkg_v2_5(out); + + /* + * values set in other places in code: + * - module.hash + */ + + return 0; +} + +static void dump_signed_pkg_ace_v1_5(const struct signed_pkg_info_ext_ace_v1_5 *signed_pkg) +{ + int i; + + DUMP("\nsigned_pkg"); + DUMP_KEY("name", "'%s'", signed_pkg->name); + DUMP_KEY("vcn", "%d", signed_pkg->vcn); + DUMP_KEY("svn", "%d", signed_pkg->svn); + DUMP_KEY("fw_type", "%d", signed_pkg->fw_type); + DUMP_KEY("fw_sub_type", "%d", signed_pkg->fw_sub_type); + for (i = 0; i < ARRAY_SIZE(signed_pkg->module); ++i) { + DUMP_KEY("meta.name", "'%s'", signed_pkg->module[i].name); + DUMP_KEY("meta.type", "0x%x", signed_pkg->module[i].type); + } +} + +static int parse_signed_pkg_ace_v1_5(const toml_table_t *toml, struct parse_ctx *pctx, + struct image *image, bool verbose) +{ + struct adsp *adsp = image->adsp; + struct signed_pkg_info_ext_ace_v1_5 *out = &adsp->man_ace_v1_5->signed_pkg; + struct signed_pkg_info_module_ace_v1_5 *mod; + toml_array_t *module_array; + toml_table_t *signed_pkg; + struct parse_ctx ctx; + toml_table_t *module; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + signed_pkg = toml_table_in(toml, "signed_pkg"); + if (!signed_pkg) + return err_key_not_found("signed_pkg"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + out->ext_type = SIGN_PKG_EXT_TYPE_ACE_V1_5; + out->ext_len = sizeof(struct signed_pkg_info_ext_ace_v1_5); + + /* configurable fields */ + parse_printable_key(signed_pkg, &ctx, "name", out->name, sizeof(out->name), &ret); + if (ret < 0) + return ret; + + out->vcn = parse_uint32_key(signed_pkg, &ctx, "vcn", 0, &ret); + if (ret < 0) + return ret; + + out->svn = parse_uint32_key(signed_pkg, &ctx, "svn", 0, &ret); + if (ret < 0) + return ret; + + out->fw_type = parse_uint8_hex_key(signed_pkg, &ctx, "fw_type", 0, &ret); + if (ret < 0) + return ret; + + out->fw_sub_type = parse_uint8_hex_key(signed_pkg, &ctx, "fw_sub_type", 0, &ret); + if (ret < 0) + return ret; + + out->partition_usage = 0x20 + image->imr_type; + + /* check everything parsed, expect 1 more array */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(signed_pkg, &ctx); + if (ret < 0) + return ret; + + /* modules array */ + module_array = toml_array_in(signed_pkg, "module"); + if (!module_array) + return err_key_not_found("module"); + if (toml_array_kind(module_array) != 't' || + toml_array_nelem(module_array) != ARRAY_SIZE(out->module)) + return err_key_parse("module", "wrong array type or length != %d", + ARRAY_SIZE(out->module)); + + /* parse modules array elements */ + for (i = 0; i < toml_array_nelem(module_array); ++i) { + module = toml_table_at(module_array, i); + if (!module) + return err_key_parse("module", NULL); + mod = &out->module[i]; + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + parse_printable_key(module, &ctx, "name", mod->name, sizeof(mod->name), &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->type = parse_uint8_hex_key(module, &ctx, "type", 0x03, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->hash_algo = parse_uint8_hex_key(module, &ctx, "hash_algo", 0x00, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->meta_size = parse_uint32_key(module, &ctx, "meta_size", 112, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(module, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_signed_pkg_ace_v1_5(out); + + /* + * values set in other places in code: + * - module.hash + */ + + return 0; +} + +static void dump_partition_info_ext(const struct partition_info_ext *part_info) +{ + int i; + + DUMP("\npartition_info"); + DUMP_PRINTABLE_BYTES("name", part_info->name); + DUMP_KEY("part_version", "0x%x", part_info->part_version); + DUMP_KEY("instance_id", "%d", part_info->instance_id); + for (i = 0; i < ARRAY_SIZE(part_info->module); ++i) { + DUMP_PRINTABLE_BYTES("module.name", part_info->module[i].name); + DUMP_KEY("module.meta_size", "0x%x", part_info->module[i].meta_size); + DUMP_KEY("module.type", "0x%x", part_info->module[i].type); + } +} + +static int parse_partition_info_ext(const toml_table_t *toml, struct parse_ctx *pctx, + struct partition_info_ext *out, bool verbose) +{ + static const uint8_t module_reserved[3] = {0x00, 0xff, 0xff}; + struct partition_info_module *mod; + toml_table_t *partition_info; + toml_array_t *module_array; + toml_table_t *module; + struct parse_ctx ctx; + int ret; + int i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + partition_info = toml_table_in(toml, "partition_info"); + if (!partition_info) + return err_key_not_found("partition_info"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non-configurable fields */ + out->ext_type = PART_INFO_EXT_TYPE; + out->ext_len = sizeof(struct partition_info_ext); + memset(out->reserved, 0xff, sizeof(out->reserved)); + + /* configurable fields */ + parse_printable_key(partition_info, &ctx, "name", out->name, sizeof(out->name), &ret); + if (ret < 0) + return ret; + + out->vcn = parse_uint32_key(partition_info, &ctx, "vcn", 0, &ret); + if (ret < 0) + return ret; + + out->part_version = + parse_uint32_hex_key(partition_info, &ctx, "part_version", 0x10000000, &ret); + if (ret < 0) + return ret; + + out->vcn = parse_uint32_hex_key(partition_info, &ctx, "part_version", 0x10000000, &ret); + if (ret < 0) + return ret; + + out->vcn = parse_uint32_hex_key(partition_info, &ctx, "fmt_version", 0, &ret); + if (ret < 0) + return ret; + + out->instance_id = parse_uint32_key(partition_info, &ctx, "instance_id", 1, &ret); + if (ret < 0) + return ret; + + out->part_flags = parse_uint32_key(partition_info, &ctx, "part_flags", 0, &ret); + if (ret < 0) + return ret; + + /* check everything parsed, expect 1 array */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(partition_info, &ctx); + if (ret < 0) + return ret; + + /* look for module array */ + module_array = toml_array_in(partition_info, "module"); + if (!module_array) + return err_key_not_found("module"); + if (toml_array_kind(module_array) != 't' || + toml_array_nelem(module_array) > ARRAY_SIZE(out->module)) + return err_key_parse("module", "wrong array type or length > %d", + ARRAY_SIZE(out->module)); + + /* parse module array elements */ + for (i = 0; i < toml_array_nelem(module_array); ++i) { + module = toml_table_at(module_array, i); + if (!module) + return err_key_parse("module", NULL); + mod = &out->module[i]; + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + memcpy(mod->reserved, module_reserved, sizeof(mod->reserved)); + + /* configurable fields */ + parse_printable_key(module, &ctx, "name", mod->name, sizeof(mod->name), &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->meta_size = parse_uint32_key(module, &ctx, "meta_size", 96, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + mod->type = parse_uint8_hex_key(module, &ctx, "type", 0x03, &ret); + if (ret < 0) + return err_key_parse("module", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(module, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_partition_info_ext(out); + + /* + * values set in other places in code: + * - length + * - hash + * - module.hash + */ + + return 0; +} + +static int parse_info_ext_0x16(const toml_table_t *toml, struct parse_ctx *pctx, + struct info_ext_0x16 *out, bool verbose) +{ + /* known */ + out->ext_type = 0x16; + out->ext_len = sizeof(*out); + out->name[0] = 'A'; + out->name[1] = 'D'; + out->name[2] = 'S'; + out->name[3] = 'P'; + + /* copied from meu - unknown */ + out->data[0] = 0x10000000; + out->data[2] = 0x1; + out->data[3] = 0x0; + out->data[4] = 0x3003; + + return 0; +} + +static void dump_adsp_file_ext_v1_8(const struct sof_man_adsp_meta_file_ext_v1_8 *adsp_file) +{ + int i; + int j; + + DUMP("\nadsp_file_ext 1.8"); + DUMP_KEY("imr_type", "0x%x", adsp_file->imr_type); + for (i = 0; i < ARRAY_SIZE(adsp_file->comp_desc); ++i) { + DUMP_KEY("comp.version", "0x%x", adsp_file->comp_desc[i].version); + DUMP_KEY("comp.base_offset", "0x%x", adsp_file->comp_desc[i].base_offset); + for (j = 0; j < ARRAY_SIZE(adsp_file->comp_desc->attributes); ++j) + DUMP_KEY("comp.atributes[]", "%d", adsp_file->comp_desc[i].attributes[j]); + } +} + +static int parse_adsp_file_ext_v1_8(const toml_table_t *toml, struct parse_ctx *pctx, + struct sof_man_adsp_meta_file_ext_v1_8 *out, bool verbose) +{ + struct sof_man_component_desc_v1_8 *desc; + toml_array_t *attributes_array; + toml_table_t *adsp_file_ext; + toml_array_t *comp_array; + struct parse_ctx ctx; + toml_raw_t attribute; + toml_table_t *comp; + int64_t temp_i; + int ret; + int i; + int j; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + adsp_file_ext = toml_table_in(toml, "adsp_file"); + if (!adsp_file_ext) + return err_key_not_found("adsp_file"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non configurable flieds */ + out->ext_type = 17; /* always 17 for ADSP extension */ + out->ext_len = sizeof(struct sof_man_adsp_meta_file_ext_v1_8); + + /* configurable fields */ + out->imr_type = parse_uint32_hex_key(adsp_file_ext, &ctx, "imr_type", + MAN_DEFAULT_IMR_TYPE, &ret); + if (ret < 0) + return ret; + + /* check everything parsed, expect 1 array */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(adsp_file_ext, &ctx); + if (ret < 0) + return ret; + + /* parse comp array */ + comp_array = toml_array_in(adsp_file_ext, "comp"); + if (!comp_array) + return err_key_not_found("comp"); + if (toml_array_nelem(comp_array) != 1 || toml_array_kind(comp_array) != 't') + return err_key_parse("comp", "wrong array type or length != 1"); + + /* parse comp array elements */ + for (i = 0; i < toml_array_nelem(comp_array); ++i) { + comp = toml_table_at(comp_array, i); + if (!comp) + return err_key_parse("comp", NULL); + desc = &out->comp_desc[i]; + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non-configurable fields */ + + /* configurable fields */ + desc->version = parse_uint32_key(comp, &ctx, "version", 0, &ret); + if (ret < 0) + return err_key_parse("comp", NULL); + + desc->base_offset = parse_uint32_hex_key(comp, &ctx, "base_offset", + MAN_DESC_OFFSET_V1_8, &ret); + if (ret < 0) + return err_key_parse("comp", NULL); + + /* parse attributes array */ + attributes_array = toml_array_in(comp, "attributes"); + if (attributes_array) { + ++ctx.array_cnt; + if (toml_array_nelem(attributes_array) > ARRAY_SIZE(desc->attributes) || + toml_array_kind(attributes_array) != 'v' || + toml_array_type(attributes_array) != 'i') + return err_key_parse("comp.attributes", + "wrong array type or length > %d", + ARRAY_SIZE(desc->attributes)); + for (j = 0; j < toml_array_nelem(attributes_array); ++j) { + attribute = toml_raw_at(attributes_array, j); + if (!attribute) + err_key_parse("comp.attributes", NULL); + ret = toml_rtoi(attribute, &temp_i); + if (ret < 0 || temp_i < 0 || temp_i > UINT32_MAX) + err_key_parse("comp.attributes", NULL); + desc->attributes[j] = (uint32_t)temp_i; + } + } + + /* check everything parsed */ + ret = assert_everything_parsed(comp, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_adsp_file_ext_v1_8(out); + + /* + * values set in other places in code: + * - imr_type + * - comp.limit_offset + */ + + return 0; +} + +static void dump_adsp_file_ext_v2_5(const struct sof_man_adsp_meta_file_ext_v2_5 *adsp_file) +{ + int i; + int j; + + DUMP("\nadsp_file 2.5"); + DUMP_KEY("imr_type", "0x%x", adsp_file->imr_type); + for (i = 0; i < ARRAY_SIZE(adsp_file->comp_desc); ++i) { + DUMP_KEY("comp.version", "0x%x", adsp_file->comp_desc[i].version); + DUMP_KEY("comp.base_offset", "0x%x", adsp_file->comp_desc[i].base_offset); + for (j = 0; j < ARRAY_SIZE(adsp_file->comp_desc->attributes); ++j) + DUMP_KEY("comp.atributes[]", "%d", adsp_file->comp_desc[i].attributes[j]); + } +} + +static int parse_adsp_file_ext_v2_5(const toml_table_t *toml, struct parse_ctx *pctx, + struct sof_man_adsp_meta_file_ext_v2_5 *out, bool verbose) +{ + struct sof_man_component_desc_v2_5 *desc; + toml_array_t *attributes_array; + toml_table_t *adsp_file_ext; + toml_array_t *comp_array; + struct parse_ctx ctx; + toml_raw_t attribute; + toml_table_t *comp; + int64_t temp_i; + int ret; + int i; + int j; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + adsp_file_ext = toml_table_in(toml, "adsp_file"); + if (!adsp_file_ext) + return err_key_not_found("adsp_file"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + /* non configurable flieds */ + out->ext_type = 17; /* always 17 for ADSP extension */ + out->ext_len = sizeof(struct sof_man_adsp_meta_file_ext_v2_5); + + /* configurable fields */ + out->imr_type = parse_uint32_hex_key(adsp_file_ext, &ctx, "imr_type", + MAN_DEFAULT_IMR_TYPE, &ret); + if (ret < 0) + return ret; + + /* check everything parsed, expect 1 array */ + ctx.array_cnt += 1; + ret = assert_everything_parsed(adsp_file_ext, &ctx); + if (ret < 0) + return ret; + + /* parse comp array */ + comp_array = toml_array_in(adsp_file_ext, "comp"); + if (!comp_array) + return err_key_not_found("comp"); + if (toml_array_nelem(comp_array) != 1 || toml_array_kind(comp_array) != 't') + return err_key_parse("comp", "wrong array type or length != 1"); + + /* parse comp array elements */ + for (i = 0; i < toml_array_nelem(comp_array); ++i) { + comp = toml_table_at(comp_array, i); + if (!comp) + return err_key_parse("comp", NULL); + desc = &out->comp_desc[i]; + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx); + + /* non configurable flieds */ + + /* configurable fields */ + desc->version = parse_uint32_key(comp, &ctx, "version", 0, &ret); + if (ret < 0) + return err_key_parse("comp", NULL); + + desc->base_offset = parse_uint32_hex_key(comp, &ctx, "base_offset", 0x2000, &ret); + if (ret < 0) + return err_key_parse("comp", NULL); + + /* parse attributes array */ + attributes_array = toml_array_in(comp, "attributes"); + if (attributes_array) { + ++ctx.array_cnt; + if (toml_array_nelem(attributes_array) > ARRAY_SIZE(desc->attributes) || + toml_array_kind(attributes_array) != 'v' || + toml_array_type(attributes_array) != 'i') + return err_key_parse("comp.attributes", + "wrong array type or length > %d", + ARRAY_SIZE(desc->attributes)); + for (j = 0; j < toml_array_nelem(attributes_array); ++j) { + attribute = toml_raw_at(attributes_array, j); + if (!attribute) + err_key_parse("comp.attributes", NULL); + ret = toml_rtoi(attribute, &temp_i); + if (ret < 0 || temp_i < 0 || temp_i > UINT32_MAX) + err_key_parse("comp.attributes", NULL); + desc->attributes[j] = (uint32_t)temp_i; + } + } + + /* check everything parsed */ + ret = assert_everything_parsed(comp, &ctx); + if (ret < 0) + return ret; + } + + if (verbose) + dump_adsp_file_ext_v2_5(out); + + /* + * values set in other places in code: + * - imr_type + * - comp.limit_offset + */ + + return 0; +} + +static void dump_fw_desc(const struct sof_man_fw_desc *fw_desc) +{ + DUMP("\nfw_desc.header"); + DUMP_KEY("header_id", "'%c%c%c%c'", fw_desc->header.header_id[0], + fw_desc->header.header_id[1], fw_desc->header.header_id[2], + fw_desc->header.header_id[3]); + DUMP_PRINTABLE_BYTES("name", fw_desc->header.name); + DUMP_KEY("preload_page_count", "%d", fw_desc->header.preload_page_count); + DUMP_KEY("fw_image_flags", "0x%x", fw_desc->header.fw_image_flags.raw); + DUMP_KEY("feature_mask", "0x%x", fw_desc->header.feature_mask); + DUMP_KEY("hw_buf_base_addr", "0x%x", fw_desc->header.fw_compat); + DUMP_KEY("hw_buf_length", "0x%x", fw_desc->header.hw_buf_length); + DUMP_KEY("load_offset", "0x%x", fw_desc->header.load_offset); +} + +static int parse_fw_desc(const toml_table_t *toml, struct parse_ctx *pctx, + struct sof_man_fw_desc *out, bool verbose) +{ + static const uint8_t header_id[4] = SOF_MAN_FW_HDR_ID; + struct parse_ctx ctx; + toml_table_t *header; + toml_table_t *desc; + int ret; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + desc = toml_table_in(toml, "fw_desc"); + if (!desc) + return err_key_not_found("fw_desc"); + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + header = toml_table_in(desc, "header"); + if (!header) + return err_key_not_found("header"); + ++ctx.table_cnt; + + /* check everything parsed */ + ret = assert_everything_parsed(desc, &ctx); + if (ret < 0) + return ret; + + /* initialize parser context for header subtable */ + parse_ctx_init(&ctx); + + /* non configurable flieds */ + memcpy(&out->header.header_id, header_id, sizeof(header_id)); + out->header.header_len = sizeof(struct sof_man_fw_header); + + /* configurable fields */ + parse_printable_key(header, &ctx, "name", out->header.name, sizeof(out->header.name), + &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + out->header.preload_page_count = + parse_uint32_key(header, &ctx, "preload_page_count", 0, &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + out->header.fw_image_flags.raw = + parse_uint32_hex_key(header, &ctx, "fw_image_flags", SOF_MAN_FW_HDR_FLAGS, &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + out->header.feature_mask = + parse_uint32_hex_key(header, &ctx, "feature_mask", SOF_MAN_FW_HDR_FEATURES, &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + out->header.fw_compat = + parse_uint32_hex_key(header, &ctx, "hw_buf_base_addr", 0, &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + out->header.hw_buf_length = parse_uint32_hex_key(header, &ctx, "hw_buf_length", 0, &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + out->header.load_offset = parse_uint32_hex_key(header, &ctx, "load_offset", -1, &ret); + if (ret < 0) + return err_key_parse("header", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(header, &ctx); + if (ret < 0) + return ret; + + if (verbose) + dump_fw_desc(out); + + /* + * values set in other places in code: + * - major_version + * - minor_version + * - build_version + * - num_module_entries + */ + + return 0; +} + +static int parse_scheduling(const toml_table_t *mod_entry, struct parse_ctx *ctx, + struct fw_image_ext_mod_config *ext_mod_config, int *ext_length) +{ + toml_array_t *arr; + toml_raw_t raw; + int64_t val; + int ret; + + /* check "sched_caps" key */ + arr = toml_array_in(mod_entry, "sched_caps"); + if (!arr) { + ext_mod_config->header.num_scheduling_capabilities = 0; + *ext_length = 0; + return 0; + } + + if (toml_array_type(arr) != 'i' || toml_array_nelem(arr) != 2 || + toml_array_kind(arr) != 'v') + return err_key_parse("sched_caps", "wrong array type or length != 2"); + + ctx->array_cnt++; + + raw = toml_raw_at(arr, 0); + if (raw == 0) + return err_key_parse("frame_length", NULL); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("frame_length", "can't convert element to integer"); + ext_mod_config->sched_caps.frame_length = val; + + raw = toml_raw_at(arr, 1); + if (raw == 0) + return err_key_parse("multiples_supported", NULL); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("multiples_supported", "can't convert element to integer"); + ext_mod_config->sched_caps.multiples_supported.ul = val; + + ext_mod_config->header.num_scheduling_capabilities = 1; + *ext_length = sizeof(struct mod_scheduling_caps); + + return 0; +} + +static int parse_pin(const toml_table_t *mod_entry, struct parse_ctx *ctx, + struct fw_image_ext_mod_config *ext_mod_config, int *ext_length) +{ + toml_array_t *arr; + toml_raw_t raw; + int64_t val; + int ret; + int i, j; + + /* check "pin" key */ + arr = toml_array_in(mod_entry, "pin"); + if (!arr) { + ext_mod_config->header.num_pin_entries = 0; + *ext_length = 0; + return 0; + } + + if (toml_array_type(arr) != 'i' || toml_array_kind(arr) != 'v') + return err_key_parse("pin", "wrong array type"); + + ctx->array_cnt++; + + /* Pin definitions contain 6 elements */ + ext_mod_config->header.num_pin_entries = toml_array_nelem(arr) / 6; + ext_mod_config->pin_desc = calloc(sizeof(struct fw_pin_description), + toml_array_nelem(arr) / 6); + + if(!ext_mod_config->pin_desc) + return err_malloc("pin"); + + j = 0; + for (i = 0; ; i += 6, j++) { + raw = toml_raw_at(arr, i); + if (raw == 0) + break; + + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("pin", "can't convert element to integer"); + ext_mod_config->pin_desc[j].caps.ul = (uint16_t)val; + + raw = toml_raw_at(arr, i + 1); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("pin", "can't convert element to integer"); + ext_mod_config->pin_desc[j].format_type = (enum mod_stream_type)val; + + raw = toml_raw_at(arr, i + 2); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("pin", "can't convert element to integer"); + ext_mod_config->pin_desc[j].sample_rate.ul = (uint32_t)val; + + raw = toml_raw_at(arr, i + 3); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("pin", "can't convert element to integer"); + ext_mod_config->pin_desc[j].sample_size.ul = (uint16_t)val; + + raw = toml_raw_at(arr, i + 4); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("pin", "can't convert element to integer"); + ext_mod_config->pin_desc[j].sample_container.ul = (uint32_t)val; + + raw = toml_raw_at(arr, i + 5); + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("pin", "can't convert element to integer"); + ext_mod_config->pin_desc[j].ch_cfg.ul = (uint32_t)val; + } + + *ext_length = ext_mod_config->header.num_pin_entries * sizeof(struct fw_pin_description); + + return 0; +} + +static int parse_mod_config(const toml_table_t *mod_entry, struct parse_ctx *ctx, + struct fw_image_manifest_module *modules, + struct sof_man_module *mod_man) +{ + toml_array_t *arr; + toml_raw_t raw; + int *cfg_data; + int64_t val; + int ret; + int i; + + /* check "mod_cfg" key */ + arr = toml_array_in(mod_entry, "mod_cfg"); + if (!arr) { + mod_man->cfg_count = 0; + return 0; + } + + if (toml_array_type(arr) != 'i' || toml_array_kind(arr) != 'v') + return err_key_parse("mod_cfg", "wrong array type"); + + ctx->array_cnt++; + + cfg_data = (int *)(modules->mod_cfg + modules->mod_cfg_count); + mod_man->cfg_offset = modules->mod_cfg_count; + /* 11 integers per configuration entry */ + mod_man->cfg_count = toml_array_nelem(arr) / 11; + modules->mod_cfg_count += mod_man->cfg_count; + + /* parse "mod_cfg" array elements: the loop runs 11 * modules->mod_cfg_count times */ + for (i = 0; ; ++i) { + raw = toml_raw_at(arr, i); + if (raw == 0) + break; + + ret = toml_rtoi(raw, &val); + if (ret < 0) + return err_key_parse("mod_cfg", "can't convert element to integer"); + cfg_data[i] = val; + } + + if (i != 11 * mod_man->cfg_count) + return err_key_parse("mod_cfg", + "can't parse configuration, only %u parsed for %u cfgs", + i, modules->mod_cfg_count); + + return 0; +} + +static void dump_module(struct fw_image_manifest_module *man_cavs) +{ + int i; + + DUMP("\nmodule"); + DUMP_KEY("moudle count", "%d", man_cavs->mod_man_count); + DUMP_KEY("module config count", "%d", man_cavs->mod_cfg_count); + + for (i = 0; i < man_cavs->mod_man_count; i++) { + DUMP_PRINTABLE_BYTES("module name", man_cavs->mod_man[i].name); + DUMP_KEY("load type", "%d", man_cavs->mod_man[i].type.load_type); + DUMP_KEY("init config", "%d", man_cavs->mod_man[i].type.init_config); + DUMP_KEY("domain ll", "%d", man_cavs->mod_man[i].type.domain_ll); + DUMP_KEY("domain dp", "%d", man_cavs->mod_man[i].type.domain_dp); + DUMP_KEY("config count", "%d", man_cavs->mod_man[i].cfg_count); + DUMP_KEY("config offset", "%d", man_cavs->mod_man[i].cfg_offset); + } +} + +static int parse_module(const toml_table_t *toml, struct parse_ctx *pctx, + struct adsp *out, bool verbose) +{ + struct fw_image_manifest_module *modules; + toml_array_t *mod_entry_array; + toml_table_t *module; + toml_table_t *mod_entry; + struct parse_ctx ctx; + int entry_count; + int type, ext_length; + int tmp_cfg_count; + int ret, i; + + /* look for subtable in toml, increment pctx parsed table cnt and initialize local ctx */ + module = toml_table_in(toml, "module"); + if (!module) + return 0; + + out->write_firmware_ext_man = ext_man_write_cavs_25; + + modules = calloc(sizeof(struct fw_image_manifest_module), 1); + if (!modules) + return err_malloc("man_cavs"); + out->modules = modules; + + ++pctx->table_cnt; + parse_ctx_init(&ctx); + + entry_count = parse_uint32_key(module, &ctx, "count", 2, &ret); + if (ret < 0) + return ret; + + ctx.array_cnt += 1; + + mod_entry_array = toml_array_in(module, "entry"); + if (!mod_entry_array) + return err_key_not_found("entry"); + if (toml_array_kind(mod_entry_array) != 't' || + toml_array_nelem(mod_entry_array) != entry_count) + return err_key_parse("entry", "wrong array type or length != %d", entry_count); + + modules->mod_ext.mod_conf_count = entry_count; + modules->mod_man = calloc(sizeof(struct sof_man_module), entry_count); + if (!modules->mod_man) + return -ENOMEM; + + modules->mod_man_count = entry_count; + + tmp_cfg_count = entry_count * MAX_MODULES; + modules->mod_cfg = calloc(sizeof(struct sof_man_mod_config), tmp_cfg_count); + + /* parse entry array elements */ + for (i = 0; i < entry_count; ++i) { + struct fw_ext_mod_config_header *header; + struct sof_man_module *mod_man; + struct parse_ctx ctx_entry; + char buf[48]; + + mod_entry = toml_table_at(mod_entry_array, i); + if (!mod_entry) + return err_key_parse("entry", NULL); + + /* initialize parse context for each array element */ + parse_ctx_init(&ctx_entry); + + mod_man = &modules->mod_man[i]; + + memcpy(mod_man->struct_id, "$AME", 4); + + /* configurable fields */ + parse_printable_key(mod_entry, &ctx_entry, "name", mod_man->name, + sizeof(mod_man->name), &ret); + if (ret < 0) + return err_key_parse("name", NULL); + + parse_str_key(mod_entry, &ctx_entry, "uuid", buf, sizeof(buf), + &ret); + if (ret < 0) + return err_key_parse("uuid", NULL); + + parse_uuid(buf, &mod_man->uuid); + + mod_man->affinity_mask = parse_uint32_hex_key(mod_entry, &ctx_entry, + "affinity_mask", 1, &ret); + if (ret < 0) + return err_key_parse("affinity_mask", NULL); + + mod_man->instance_max_count = parse_uint16_hex_key(mod_entry, &ctx_entry, + "instance_count", 1, &ret); + if (ret < 0) + return err_key_parse("instance_count", NULL); + + type = parse_uint32_hex_key(mod_entry, &ctx_entry, "domain_types", 0, &ret); + if (ret < 0) + return err_key_parse("domain_types", NULL); + if (!type) + mod_man->type.domain_ll = 1; + else + mod_man->type.domain_dp = 1; + + mod_man->type.load_type = parse_uint32_hex_key(mod_entry, &ctx_entry, + "load_type", 1, &ret); + if (ret < 0) + return err_key_parse("load_type", NULL); + + mod_man->type.init_config = parse_uint32_hex_key(mod_entry, &ctx_entry, + "init_config", 0, &ret); + if (ret < 0) + return err_key_parse("init_config", NULL); + + mod_man->type.auto_start = parse_uint32_hex_key(mod_entry, &ctx_entry, + "auto_start", 1, &ret); + if (ret < 0) + return err_key_parse("auto_start", NULL); + + parse_uint32_key(mod_entry, &ctx_entry, "index", 1, &ret); + /* Ignore if "index" is missing for backwards compatibility */ + + header = &modules->mod_ext.ext_mod_config_array[i].header; + header->version_major = 2; + header->version_minor = 5; + header->ext_module_config_length = sizeof(struct fw_ext_mod_config_header); + memcpy(header->guid, &mod_man->uuid, sizeof(mod_man->uuid)); + + type = parse_uint32_hex_key(mod_entry, &ctx_entry, "module_type", 1, &ret); + if (ret < 0) + return err_key_parse("module_type", NULL); + + header->module_type = type; + + ret = parse_scheduling(mod_entry, &ctx_entry, + modules->mod_ext.ext_mod_config_array + i, &ext_length); + if (ret < 0) + return err_key_parse("schd_caps", NULL); + header->ext_module_config_length += ext_length; + + ret = parse_pin(mod_entry, &ctx_entry, modules->mod_ext.ext_mod_config_array + i, + &ext_length); + if (ret < 0) + return err_key_parse("pin", NULL); + header->ext_module_config_length += ext_length; + + ret = parse_mod_config(mod_entry, &ctx_entry, modules, mod_man); + if (ret < 0) + return err_key_parse("mod_cfg", NULL); + + if (modules->mod_cfg_count > tmp_cfg_count) + return -ENOMEM; + + /* check everything parsed */ + ret = assert_everything_parsed(mod_entry, &ctx_entry); + if (ret < 0) + return ret; + } + + /* check everything parsed */ + ret = assert_everything_parsed(module, &ctx); + if (ret < 0) + return ret; + + if (verbose) + dump_module(modules); + + return 0; +} + +static int parse_adsp_config_v1_0(const toml_table_t *toml, struct image *image) +{ + struct adsp *out = image->adsp; + bool verbose = image->verbose; + struct parse_ctx ctx; + int ret; + + /* version array has already been parsed, so increment ctx.array_cnt */ + parse_ctx_init(&ctx); + ++ctx.array_cnt; + + /* parse each adsp subtable, sue platform has different manifest definition */ + ret = parse_adsp(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("adsp", NULL); + + /* assign correct write functions */ + out->write_firmware = simple_write_firmware; + out->write_firmware_meu = NULL; + + /* check everything parsed */ + ret = assert_everything_parsed(toml, &ctx); + if (ret < 0) + return ret; + + return 0; +} + +static int parse_adsp_config_v1_5(const toml_table_t *toml, struct image *image) +{ + struct adsp *out = image->adsp; + bool verbose = image->verbose; + struct parse_ctx ctx; + int ret; + + /* version array has already been parsed, so increment ctx.array_cnt */ + parse_ctx_init(&ctx); + ++ctx.array_cnt; + + /* parse each adsp subtable, sue platform has different manifest definition */ + ret = parse_adsp(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("adsp", NULL); + + /* suecreek has dedicated manifest file */ + if (!strcmp(out->name, "sue")) { + /* out free is done in client code */ + out->man_v1_5_sue = malloc(sizeof(struct fw_image_manifest_v1_5_sue)); + if (!out->man_v1_5_sue) + return err_malloc("man_v1_5_sue"); + + /* clear memory */ + memset(out->man_v1_5_sue, 0, sizeof(*out->man_v1_5_sue)); + + /* assign correct write functions */ + out->write_firmware = man_write_fw_v1_5_sue; + out->write_firmware_meu = man_write_fw_meu_v1_5; + out->verify_firmware = ri_manifest_verify_v1_5; + + /* parse others sibtables */ + ret = parse_fw_desc(toml, &ctx, &out->man_v1_5_sue->desc, verbose); + if (ret < 0) + return err_key_parse("fw_desc", NULL); + } else { + /* out free is done in client code */ + out->man_v1_5 = malloc(sizeof(struct fw_image_manifest_v1_5)); + if (!out->man_v1_5) + return err_malloc("man_v1_5"); + + /* clear memory */ + memset(out->man_v1_5, 0, sizeof(*out->man_v1_5)); + + /* assign correct write functions */ + out->write_firmware = man_write_fw_v1_5; + out->write_firmware_meu = man_write_fw_meu_v1_5; + out->verify_firmware = ri_manifest_verify_v1_5; + + /* parse others sibtables */ + ret = parse_css_v1_5(toml, &ctx, &out->man_v1_5->css_header, verbose); + if (ret < 0) + return err_key_parse("css", NULL); + + ret = parse_fw_desc(toml, &ctx, &out->man_v1_5->desc, verbose); + if (ret < 0) + return err_key_parse("fw_desc", NULL); + } + + /* check everything parsed */ + ret = assert_everything_parsed(toml, &ctx); + if (ret < 0) + return ret; + + return 0; +} + +static int parse_adsp_config_v1_8(const toml_table_t *toml, struct image *image) +{ + struct adsp *out = image->adsp; + bool verbose = image->verbose; + struct parse_ctx ctx; + int ret; + + /* out free is done in client code */ + out->man_v1_8 = malloc(sizeof(struct fw_image_manifest_v1_8)); + if (!out->man_v1_8) + return err_malloc("man_v1_8"); + + /* clear memory */ + memset(out->man_v1_8, 0, sizeof(*out->man_v1_8)); + + /* assign correct write functions */ + out->write_firmware = man_write_fw_v1_8; + out->write_firmware_meu = man_write_fw_meu_v1_8; + out->verify_firmware = ri_manifest_verify_v1_8; + + /* version array has already been parsed, so increment ctx.array_cnt */ + parse_ctx_init(&ctx); + ++ctx.array_cnt; + + /* parse each toml subtable */ + ret = parse_adsp(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("adsp", NULL); + + ret = parse_cse(toml, &ctx, &out->man_v1_8->cse_partition_dir_header, + out->man_v1_8->cse_partition_dir_entry, MAN_CSE_PARTS, verbose); + if (ret < 0) + return err_key_parse("cse", NULL); + + ret = parse_css_v1_8(toml, &ctx, &out->man_v1_8->css, verbose); + if (ret < 0) + return err_key_parse("css", NULL); + + ret = parse_signed_pkg(toml, &ctx, image, verbose); + if (ret < 0) + return err_key_parse("signed_pkg", NULL); + + ret = parse_partition_info_ext(toml, &ctx, &out->man_v1_8->partition_info, verbose); + if (ret < 0) + return err_key_parse("partition_info", NULL); + + ret = parse_adsp_file_ext_v1_8(toml, &ctx, &out->man_v1_8->adsp_file_ext, verbose); + if (ret < 0) + return err_key_parse("adsp_file", NULL); + + ret = parse_fw_desc(toml, &ctx, &out->man_v1_8->desc, verbose); + if (ret < 0) + return err_key_parse("fw_desc", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(toml, &ctx); + if (ret < 0) + return ret; + + return 0; +} + +static int parse_adsp_config_v2_5(const toml_table_t *toml, struct image *image) +{ + struct adsp *out = image->adsp; + bool verbose = image->verbose; + struct parse_ctx ctx; + int ret; + + /* out free is done in client code */ + out->man_v2_5 = malloc(sizeof(struct fw_image_manifest_v2_5)); + if (!out->man_v2_5) + return err_malloc("man_v2_5"); + + /* clear memory */ + memset(out->man_v2_5, 0, sizeof(*out->man_v2_5)); + + /* assign correct write functions */ + out->write_firmware = man_write_fw_v2_5; + out->write_firmware_meu = man_write_fw_meu_v2_5; + out->verify_firmware = ri_manifest_verify_v2_5; + + /* version array has already been parsed, so increment ctx.array_cnt */ + parse_ctx_init(&ctx); + ++ctx.array_cnt; + + /* parse each toml subtable */ + ret = parse_adsp(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("adsp", NULL); + + ret = parse_cse_v2_5(toml, &ctx, &out->man_v2_5->cse_partition_dir_header, + out->man_v2_5->cse_partition_dir_entry, MAN_CSE_PARTS, verbose); + if (ret < 0) + return err_key_parse("cse", NULL); + + ret = parse_css_v2_5(toml, &ctx, &out->man_v2_5->css, verbose); + if (ret < 0) + return err_key_parse("css", NULL); + + ret = parse_signed_pkg_v2_5(toml, &ctx, image, verbose); + if (ret < 0) + return err_key_parse("signed_pkg", NULL); + + ret = parse_info_ext_0x16(toml, &ctx, &out->man_v2_5->info_0x16, verbose); + if (ret < 0) + return err_key_parse("partition_info", NULL); + + ret = parse_adsp_file_ext_v2_5(toml, &ctx, &out->man_v2_5->adsp_file_ext, verbose); + if (ret < 0) + return err_key_parse("adsp_file", NULL); + + ret = parse_fw_desc(toml, &ctx, &out->man_v2_5->desc, verbose); + if (ret < 0) + return err_key_parse("fw_desc", NULL); + + ret = parse_module(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("module", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(toml, &ctx); + if (ret < 0) + return ret; + + return 0; +} + +static int parse_adsp_config_ace_v1_5(const toml_table_t *toml, struct image *image) +{ + struct adsp *out = image->adsp; + bool verbose = image->verbose; + struct parse_ctx ctx; + int ret; + + out->man_ace_v1_5 = malloc(sizeof(struct fw_image_manifest_ace_v1_5)); + if (!out->man_ace_v1_5) + return err_malloc("man_ace_v1_5"); + + /* clear memory */ + memset(out->man_ace_v1_5, 0, sizeof(*out->man_ace_v1_5)); + + /* assign correct write functions */ + out->write_firmware = man_write_fw_ace_v1_5; + out->write_firmware_meu = man_write_fw_meu_v2_5; + out->verify_firmware = ri_manifest_verify_v2_5; + + /* version array has already been parsed, so increment ctx.array_cnt */ + parse_ctx_init(&ctx); + ++ctx.array_cnt; + + /* parse each toml subtable */ + ret = parse_adsp(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("adsp", NULL); + + ret = parse_cse_v2_5(toml, &ctx, &out->man_ace_v1_5->cse_partition_dir_header, + out->man_ace_v1_5->cse_partition_dir_entry, 3, verbose); + if (ret < 0) + return err_key_parse("cse", NULL); + + ret = parse_css_v2_5(toml, &ctx, &out->man_ace_v1_5->css, verbose); + if (ret < 0) + return err_key_parse("css", NULL); + + ret = parse_signed_pkg_ace_v1_5(toml, &ctx, image, verbose); + if (ret < 0) + return err_key_parse("signed_pkg", NULL); + + ret = parse_info_ext_0x16(toml, &ctx, &out->man_ace_v1_5->info_0x16, verbose); + if (ret < 0) + return err_key_parse("partition_info", NULL); + + ret = parse_adsp_file_ext_v2_5(toml, &ctx, &out->man_ace_v1_5->adsp_file_ext, verbose); + if (ret < 0) + return err_key_parse("adsp_file", NULL); + + ret = parse_fw_desc(toml, &ctx, &out->man_ace_v1_5->desc, verbose); + if (ret < 0) + return err_key_parse("fw_desc", NULL); + + ret = parse_module(toml, &ctx, out, verbose); + if (ret < 0) + return err_key_parse("module", NULL); + + /* check everything parsed */ + ret = assert_everything_parsed(toml, &ctx); + if (ret < 0) + return ret; + + return 0; +} + +struct config_parser { + int major; + int minor; + int (*parse)(const toml_table_t *toml, struct image *image); +}; + +static const struct config_parser *find_config_parser(int64_t version[2]) +{ + /* list of supported configuration version with handler to parser */ + static const struct config_parser parsers[] = { + {1, 0, parse_adsp_config_v1_0}, + {1, 5, parse_adsp_config_v1_5}, + {1, 8, parse_adsp_config_v1_8}, + {2, 5, parse_adsp_config_v2_5}, + {3, 0, parse_adsp_config_ace_v1_5}, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(parsers); ++i) { + if (parsers[i].major == version[0] && + parsers[i].minor == version[1]) { + return &parsers[i]; + } + } + return NULL; +} + +static int adsp_parse_config_fd(FILE *fd, struct image *image) +{ + const struct config_parser *parser; + int64_t manifest_version[2]; + toml_table_t *toml; + char errbuf[256]; + int ret; + + /* whole toml file is parsed to global toml table at once */ + toml = toml_parse_file(fd, errbuf, ARRAY_SIZE(errbuf)); + if (!toml) + return log_err(-EINVAL, "error: toml file parsing, %s\n", errbuf); + + /* manifest version is in toml root */ + ret = parse_version(toml, manifest_version); + if (ret < 0) + goto error; + + /* find parser compatible with manifest version */ + parser = find_config_parser(manifest_version); + if (!parser) { + ret = log_err(-EINVAL, "error: Unsupported config version %d.%d\n", + manifest_version[0], manifest_version[1]); + goto error; + } + + /* run dedicated toml configuration parser */ + ret = parser->parse(toml, image); +error: + toml_free(toml); + return ret; +} + +/* public function, fully handle parsing process */ +int adsp_parse_config(const char *file, struct image *image) +{ + FILE *fd; + int ret; + + fd = fopen(file, "r"); + if (!fd) + return file_error("unable to open file for reading", file); + + ret = adsp_parse_config_fd(fd, image); + fclose(fd); + return ret; +} + +/* free given pointer and internally allocated memory */ +void adsp_free(struct adsp *adsp) +{ + if (!adsp) + return; + + free(adsp->man_v1_5); + free(adsp->man_v1_5_sue); + free(adsp->man_v1_8); + free(adsp->man_v2_5); + free(adsp->modules); + free((void *)adsp->name); + + free(adsp); +} diff --git a/tools/rimage/src/cse.c b/tools/rimage/src/cse.c new file mode 100644 index 000000000000..3c5e9c561856 --- /dev/null +++ b/tools/rimage/src/cse.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <stdio.h> +#include <stdbool.h> +#include <rimage/rimage.h> +#include <rimage/cse.h> +#include <rimage/manifest.h> + +void ri_cse_create(struct image *image) +{ + struct CsePartitionDirHeader *cse_hdr = image->fw_image; + struct sof_man_adsp_meta_file_ext_v1_8 *meta = image->fw_image + + MAN_META_EXT_OFFSET_V1_8; + struct CsePartitionDirEntry *cse_entry = + image->fw_image + sizeof(*cse_hdr); + uint8_t csum = 0, *val = image->fw_image; + int i, size; + + fprintf(stdout, " cse: completing CSE V1.8 manifest\n"); + + cse_entry[2].length = meta->comp_desc[0].limit_offset - + MAN_DESC_OFFSET_V1_8; + + /* calculate checksum using BSD algo */ + size = sizeof(*cse_hdr) + sizeof(*cse_entry) * MAN_CSE_PARTS; + for (i = 0; i < size; i++) { + if (i == 11) + continue; + csum += val[i]; + } + cse_hdr->checksum = 0x100 - csum; +} + +static uint32_t crc32(uint8_t *input, int size, uint32_t poly, uint32_t init, + bool rev_in, bool rev_out, uint32_t xor_out) +{ + uint32_t crc = init; + uint32_t t32; + uint8_t val; + uint8_t t8; + int i; + int j; + + for (i = 0; i < size; i++) { + val = input[i]; + if (rev_in) { + t8 = 0; + for (j = 0; j < 8; j++) { + if (val & (1 << j)) + t8 |= (uint8_t)(1 << (7 - j)); + } + val = t8; + } + crc ^= (uint32_t)(val << 24); + for (j = 0; j < 8; j++) { + if (crc & 0x80000000) + crc = (uint32_t)((crc << 1) ^ poly); + else + crc <<= 1; + } + } + + if (rev_out) { + t32 = 0; + for (i = 0; i < 32; i++) { + if (crc & (1U << i)) + t32 |= (uint32_t)(1 << (31 - i)); + } + crc = t32; + } + + return crc ^ xor_out; +} + +void ri_cse_create_v2_5(struct image *image) +{ + struct CsePartitionDirHeader_v2_5 *cse_hdr = image->fw_image; + struct sof_man_adsp_meta_file_ext_v2_5 *meta = image->fw_image + + MAN_META_EXT_OFFSET_V2_5; + struct CsePartitionDirEntry *cse_entry = + image->fw_image + sizeof(*cse_hdr); + uint8_t *val = image->fw_image; + int size; + + fprintf(stdout, " cse: completing CSE V2.5 manifest\n"); + + cse_entry[2].length = meta->comp_desc[0].limit_offset - + MAN_DESC_OFFSET_V1_8; + + /* + * calculate checksum using crc-32/iso-hdlc + * + * polynomial: 0x04c11db7 + * initial value: 0xffffffff + * reverse input: true + * reverse output: true + * xor output: 0xffffffff + */ + size = (sizeof(*cse_hdr) + (sizeof(*cse_entry) * MAN_CSE_PARTS)); + cse_hdr->checksum = crc32(val, size, 0x04c11db7, 0xffffffff, true, true, 0xffffffff); + + fprintf(stdout, " cse: cse checksum %x\n", cse_hdr->checksum); +} + +void ri_cse_create_ace_v1_5(struct image *image) +{ + struct CsePartitionDirHeader_v2_5 *cse_hdr = image->fw_image; + struct sof_man_adsp_meta_file_ext_v2_5 *meta = image->fw_image + + MAN_META_EXT_OFFSET_ACE_V1_5; + struct CsePartitionDirEntry *cse_entry = + image->fw_image + sizeof(*cse_hdr); + uint8_t *val = image->fw_image; + int size; + + fprintf(stdout, " cse: completing CSE V2.5 manifest\n"); + + cse_entry[2].length = meta->comp_desc[0].limit_offset - + MAN_DESC_OFFSET_V1_8; + + /* + * calculate checksum using crc-32/iso-hdlc + * + * polynomial: 0x04c11db7 + * initial value: 0xffffffff + * reverse input: true + * reverse output: true + * xor output: 0xffffffff + */ + size = (sizeof(*cse_hdr) + (sizeof(*cse_entry) * MAN_CSE_PARTS)); + cse_hdr->checksum = crc32(val, size, 0x04c11db7, 0xffffffff, true, true, 0xffffffff); + + fprintf(stdout, " cse: cse checksum %x\n", cse_hdr->checksum); +} diff --git a/tools/rimage/src/css.c b/tools/rimage/src/css.c new file mode 100644 index 000000000000..a69d5c80f76b --- /dev/null +++ b/tools/rimage/src/css.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <stdio.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> +#include <rimage/rimage.h> +#include <rimage/css.h> +#include <rimage/manifest.h> + +void ri_css_v2_5_hdr_create(struct image *image) +{ + struct css_header_v2_5 *css = image->fw_image + MAN_CSS_HDR_OFFSET_2_5; + struct tm *date; + struct timeval tv; + time_t seconds; + int val; + + fprintf(stdout, " cse: %s completing CSS manifest\n", __func__); + + /* get local time and date */ + gettimeofday(&tv, NULL); + seconds = tv.tv_sec; + date = localtime(&seconds); + + if (!date) { + fprintf(stderr, "error: cant get localtime %d\n", -errno); + return; + } + + date->tm_year += 1900; + fprintf(stdout, " css: set build date to %d:%2.2d:%2.2d\n", + date->tm_year, date->tm_mon, date->tm_mday); + + /* year yYyy */ + val = date->tm_year / 1000; + css->date |= val << 28; + date->tm_year -= val * 1000; + /* year yyYy */ + val = date->tm_year / 100; + css->date |= val << 24; + date->tm_year -= val * 100; + /* year yyyY */ + val = date->tm_year / 10; + css->date |= val << 20; + date->tm_year -= val * 10; + /* year Yyyy */ + val = date->tm_year; + css->date |= val << 16; + + /* month Mm - for some reason month starts at 0 */ + val = ++date->tm_mon / 10; + css->date |= val << 12; + date->tm_mon -= (val * 10); + /* month mM */ + val = date->tm_mon; + css->date |= val << 8; + + /* Day Dd */ + val = date->tm_mday / 10; + css->date |= val << 4; + date->tm_mday -= (val * 10); + /* Day dD */ + val = date->tm_mday; + css->date |= val << 0; +} + +void ri_css_v1_8_hdr_create(struct image *image) +{ + struct css_header_v1_8 *css = image->fw_image + MAN_CSS_HDR_OFFSET; + struct tm *date; + struct timeval tv; + time_t seconds; + int val; + + fprintf(stdout, " cse: %s completing CSS manifest\n", __func__); + + /* get local time and date */ + gettimeofday(&tv, NULL); + seconds = tv.tv_sec; + date = localtime(&seconds); + + if (!date) { + fprintf(stderr, "error: cant get localtime %d\n", -errno); + return; + } + + date->tm_year += 1900; + fprintf(stdout, " css: set build date to %d:%2.2d:%2.2d\n", + date->tm_year, date->tm_mon, date->tm_mday); + + /* year yYyy */ + val = date->tm_year / 1000; + css->date |= val << 28; + date->tm_year -= val * 1000; + /* year yyYy */ + val = date->tm_year / 100; + css->date |= val << 24; + date->tm_year -= val * 100; + /* year yyyY */ + val = date->tm_year / 10; + css->date |= val << 20; + date->tm_year -= val * 10; + /* year Yyyy */ + val = date->tm_year; + css->date |= val << 16; + + /* month Mm - for some reason month starts at 0 */ + val = ++date->tm_mon / 10; + css->date |= val << 12; + date->tm_mon -= (val * 10); + /* month mM */ + val = date->tm_mon; + css->date |= val << 8; + + /* Day Dd */ + val = date->tm_mday / 10; + css->date |= val << 4; + date->tm_mday -= (val * 10); + /* Day dD */ + val = date->tm_mday; + css->date |= val << 0; +} + +void ri_css_v1_5_hdr_create(struct image *image) +{ + struct css_header_v1_5 *css = image->fw_image; + struct tm *date; + struct timeval tv; + time_t seconds; + int val; + + fprintf(stdout, " cse: %s completing CSS manifest\n", __func__); + + /* get local time and date */ + gettimeofday(&tv, NULL); + seconds = tv.tv_sec; + date = localtime(&seconds); + + if (!date) { + fprintf(stderr, "error: cant get localtime %d\n", -errno); + return; + } + + date->tm_year += 1900; + fprintf(stdout, " css: set build date to %d:%2.2d:%2.2d\n", + date->tm_year, date->tm_mon, date->tm_mday); + + /* year yYyy */ + val = date->tm_year / 1000; + css->date |= val << 28; + date->tm_year -= val * 1000; + /* year yyYy */ + val = date->tm_year / 100; + css->date |= val << 24; + date->tm_year -= val * 100; + /* year yyyY */ + val = date->tm_year / 10; + css->date |= val << 20; + date->tm_year -= val * 10; + /* year Yyyy */ + val = date->tm_year; + css->date |= val << 16; + + /* month Mm - for some reason month starts at 0 */ + val = ++date->tm_mon / 10; + css->date |= val << 12; + date->tm_mon -= (val * 10); + /* month mM */ + val = date->tm_mon; + css->date |= val << 8; + + /* Day Dd */ + val = date->tm_mday / 10; + css->date |= val << 4; + date->tm_mday -= (val * 10); + /* Day dD */ + val = date->tm_mday; + css->date |= val << 0; +} diff --git a/tools/rimage/src/elf_file.c b/tools/rimage/src/elf_file.c new file mode 100644 index 000000000000..991766d45062 --- /dev/null +++ b/tools/rimage/src/elf_file.c @@ -0,0 +1,561 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <rimage/elf_file.h> +#include <rimage/file_utils.h> +#include <rimage/misc_utils.h> + + /* Values for e_type. */ +static struct name_val e_type[] = { + NAME_VAL_ENTRY(ET_NONE), /* Unknown type. */ + NAME_VAL_ENTRY(ET_REL), /* Relocatable. */ + NAME_VAL_ENTRY(ET_EXEC), /* Executable. */ + NAME_VAL_ENTRY(ET_DYN), /* Shared object. */ + NAME_VAL_ENTRY(ET_CORE), /* Core file. */ + NAME_VAL_END +}; + +static struct name_val sh_types[] = { + NAME_VAL_ENTRY(SHT_NULL), /* inactive */ + NAME_VAL_ENTRY(SHT_PROGBITS), /* program defined information */ + NAME_VAL_ENTRY(SHT_SYMTAB), /* symbol table section */ + NAME_VAL_ENTRY(SHT_STRTAB), /* string table section */ + NAME_VAL_ENTRY(SHT_RELA), /* relocation section with addends */ + NAME_VAL_ENTRY(SHT_HASH), /* symbol hash table section */ + NAME_VAL_ENTRY(SHT_DYNAMIC), /* dynamic section */ + NAME_VAL_ENTRY(SHT_NOTE), /* note section */ + NAME_VAL_ENTRY(SHT_NOBITS), /* no space section */ + NAME_VAL_ENTRY(SHT_REL), /* relocation section - no addends */ + NAME_VAL_ENTRY(SHT_SHLIB), /* reserved - purpose unknown */ + NAME_VAL_ENTRY(SHT_DYNSYM), /* dynamic symbol table section */ + NAME_VAL_ENTRY(SHT_INIT_ARRAY), /* Initialization function pointers. */ + NAME_VAL_ENTRY(SHT_FINI_ARRAY), /* Termination function pointers. */ + NAME_VAL_ENTRY(SHT_PREINIT_ARRAY), /* Pre-initialization function ptrs. */ + NAME_VAL_ENTRY(SHT_GROUP), /* Section group. */ + NAME_VAL_ENTRY(SHT_SYMTAB_SHNDX), /* Section indexes (see SHN_XINDEX). */ + NAME_VAL_ENTRY(SHT_LOOS), /* First of OS specific semantics */ + NAME_VAL_ENTRY(SHT_HIOS), /* Last of OS specific semantics */ + NAME_VAL_ENTRY(SHT_GNU_VERDEF), + NAME_VAL_ENTRY(SHT_GNU_VERNEED), + NAME_VAL_ENTRY(SHT_GNU_VERSYM), + NAME_VAL_ENTRY(SHT_LOPROC), /* reserved range for processor */ + NAME_VAL_ENTRY(SHT_HIPROC), /* specific section header types */ + NAME_VAL_ENTRY(SHT_LOUSER), /* reserved range for application */ + NAME_VAL_ENTRY(SHT_HIUSER), /* specific indexes */ + NAME_VAL_END +}; + +/* Flags for sh_flags. */ +static struct name_val sh_flags[] = { + NAME_VAL_ENTRY(SHF_WRITE), /* Section contains writable data. */ + NAME_VAL_ENTRY(SHF_ALLOC), /* Section occupies memory. */ + NAME_VAL_ENTRY(SHF_EXECINSTR), /* Section contains instructions. */ + NAME_VAL_ENTRY(SHF_MERGE), /* Section may be merged. */ + NAME_VAL_ENTRY(SHF_STRINGS), /* Section contains strings. */ + NAME_VAL_ENTRY(SHF_INFO_LINK), /* sh_info holds section index. */ + NAME_VAL_ENTRY(SHF_LINK_ORDER), /* Special ordering requirements. */ + NAME_VAL_ENTRY(SHF_OS_NONCONFORMING), /* OS-specific processing required. */ + NAME_VAL_ENTRY(SHF_GROUP), /* Member of section group. */ + NAME_VAL_ENTRY(SHF_TLS), /* Section contains TLS data. */ + NAME_VAL_END +}; + +/* Values for p_type. */ +static struct name_val p_type[] = { + NAME_VAL_ENTRY(PT_NULL), /* Unused entry. */ + NAME_VAL_ENTRY(PT_LOAD), /* Loadable segment. */ + NAME_VAL_ENTRY(PT_DYNAMIC), /* Dynamic linking information segment. */ + NAME_VAL_ENTRY(PT_INTERP), /* Pathname of interpreter. */ + NAME_VAL_ENTRY(PT_NOTE), /* Auxiliary information. */ + NAME_VAL_ENTRY(PT_SHLIB), /* Reserved (not used). */ + NAME_VAL_ENTRY(PT_PHDR), /* Location of program header itself. */ + NAME_VAL_ENTRY(PT_TLS), /* Thread local storage segment */ + NAME_VAL_END +}; + +/* Values for p_flags. */ +static struct name_val p_flags[] = { + NAME_VAL_ENTRY(PF_X), /* Executable. */ + NAME_VAL_ENTRY(PF_W), /* Writable. */ + NAME_VAL_ENTRY(PF_R), /* Readable. */ + NAME_VAL_END +}; + +/** + * Print elf related error message + * + * @param elf elf file structure + * @param msg error message + * @param error error code to return + * @return error code + */ +static int elf_error(const struct elf_file *elf, const char *msg, int error) +{ + fprintf(stderr, "Error: %s: %s\n", elf->filename, msg); + return -error; +} + +/** + * Read elf header + * + * @param elf elf file structure + * @return error code, 0 when success + */ +static int elf_header_read(struct elf_file *elf) +{ + size_t count; + + /* read in elf header */ + count = fread(&elf->header, sizeof(elf->header), 1, elf->file); + if (count != 1) { + if (!count) + return file_error("failed to read elf header", elf->filename); + else + return elf_error(elf, "Corrupted file.", ENODATA); + } + + if (strncmp((char *)elf->header.ident, "\177ELF\001\001", 5)) + return elf_error(elf, "Not a 32 bits ELF-LE file", EILSEQ); + + if (elf->header.version != EV_CURRENT) + return elf_error(elf, "Unsupported file version.", EINVAL); + + if (elf->header.ehsize < sizeof(Elf32_Ehdr)) + return elf_error(elf, "Invalid file header size.", EINVAL); + + if (elf->header.shoff >= elf->file_size) + return elf_error(elf, "Invalid section header file offset.", EINVAL); + + if (elf->header.shentsize < sizeof(Elf32_Shdr)) + return elf_error(elf, "Invalid section header size.", EINVAL); + + if (elf->header.shoff + elf->header.shnum * sizeof(Elf32_Shdr) > elf->file_size) + return elf_error(elf, "Invalid number of section header entries.", EINVAL); + + if (elf->header.shstrndx >= elf->header.shnum) + return elf_error(elf, "Invalid section name strings section index.", EINVAL); + + return 0; +} + +void elf_header_print(const struct elf_file *elf) +{ + fprintf(stdout, "\tfile type\t 0x%8.8x ", elf->header.type); + print_enum(elf->header.type, e_type); + fprintf(stdout, "\tarchitecture\t 0x%8.8x\n", elf->header.machine); + fprintf(stdout, "\tformat version\t 0x%8.8x\n", elf->header.version); + fprintf(stdout, "\tarch flags\t 0x%8.8x\n", elf->header.flags); + fprintf(stdout, "\theader size\t 0x%8.8x\n", elf->header.ehsize); + fprintf(stdout, "\tentry point\t 0x%8.8x\n", elf->header.entry); + fprintf(stdout, "\tprogram offset\t 0x%8.8x\n", elf->header.phoff); + fprintf(stdout, "\tsection offset\t 0x%8.8x\n", elf->header.shoff); + fprintf(stdout, "\tprogram size\t 0x%8.8x\n", elf->header.phentsize); + fprintf(stdout, "\tprogram count\t 0x%8.8x\n", elf->header.phnum); + fprintf(stdout, "\tsection size\t 0x%8.8x\n", elf->header.shentsize); + fprintf(stdout, "\tsection count\t 0x%8.8x\n", elf->header.shnum); + fprintf(stdout, "\tstring index\t 0x%8.8x\n\n", elf->header.shstrndx); +} + +/** + * Read sections headers from elf file + * + * @param elf elf file structure + * @return error code, 0 when success + */ +static int elf_section_headers_read(struct elf_file *elf) +{ + int i, ret; + size_t offset, count; + + elf->sections = calloc(elf->header.shnum, sizeof(struct elf_section_header)); + if (!elf->sections) + return elf_error(elf, "Cannot allocate section array.", ENOMEM); + + /* In case of error, sections memory are released in elf_open function. */ + + offset = elf->header.shoff; + for (i = 0; i < elf->header.shnum; i++, offset += elf->header.shentsize) { + ret = fseek(elf->file, offset, SEEK_SET); + if (ret) + return file_error("unable to seek to section header", elf->filename); + + count = fread(&elf->sections[i].data, sizeof(Elf32_Shdr), 1, elf->file); + if (count != 1) { + if (!count) + return file_error("failed to read section header", elf->filename); + else + return elf_error(elf, "Corrupted file.", ENODATA); + } + } + + elf->sections_count = elf->header.shnum; + return 0; +} + +/** + * Update name of a section in the section headers + * + * @param elf elf file structure + * @return error code, 0 when success + */ +static int elf_set_sections_names(struct elf_file *elf, const struct elf_strings *strings) +{ + int ret, i; + + for (i = 0; i < elf->sections_count; i++) { + ret = elf_strings_get(strings, elf->sections[i].data.name, &elf->sections[i].name); + if (ret) + return ret; + } + + return 0; +} + +void elf_print_sections(const struct elf_file *elf) +{ + int i; + + for (i = 0; i < elf->sections_count; i++) { + fprintf(stdout, "Section %d:\n", i); + elf_section_header_print(&elf->sections[i]); + } +} + +/** + * Read program headers from elf file + * + * @param elf elf file structure + * @return error code, 0 when success + */ +static int elf_program_headers_read(struct elf_file *elf) +{ + int i, ret; + size_t offset, count; + + if (!elf->header.phnum) { + elf->programs = NULL; + elf->programs_count = 0; + return 0; + } + + elf->programs = calloc(elf->header.phnum, sizeof(Elf32_Phdr)); + if (!elf->programs) + return elf_error(elf, "Cannot allocate program array.", ENOMEM); + + /* In case of error, programs memory are released in elf_open function. */ + + offset = elf->header.phoff; + for (i = 0; i < elf->header.phnum; i++, offset += elf->header.phentsize) { + ret = fseek(elf->file, offset, SEEK_SET); + if (ret) + return file_error("unable to seek to program header", elf->filename); + + count = fread(&elf->programs[i], sizeof(Elf32_Phdr), 1, elf->file); + if (count != 1) { + if (!count) + return file_error("failed to read program header", elf->filename); + else + return elf_error(elf, "Corrupted file.", ENODATA); + } + } + + elf->programs_count = elf->header.phnum; + return 0; +} + +void elf_print_programs(const struct elf_file *elf) +{ + int i; + + for (i = 0; i < elf->programs_count; i++) { + fprintf(stdout, "\nProgram %d:\n", i); + elf_program_header_print(&elf->programs[i]); + } +} + +/** + * Copy elf_header structure. Allocates a new copy of the name string. + * + * @param [in]src Source section header structure + * @param [out]dst Destination section header structure + * @return error code, 0 when success + */ +static int elf_section_header_copy(const struct elf_section_header *src, + struct elf_section_header *dst) +{ + if (src->name) { + dst->name = strdup(src->name); + if (!dst->name) + return -ENOMEM; + } else { + dst->name = NULL; + } + + memcpy(&dst->data, &src->data, sizeof(dst->data)); + return 0; +} + +int elf_section_header_get_by_index(const struct elf_file *elf, int index, + const struct elf_section_header **header) +{ + if (index >= elf->sections_count) + return elf_error(elf, "Invalid section index.", EINVAL); + + *header = &elf->sections[index]; + + return 0; +} + +int elf_section_header_get_by_name(const struct elf_file *elf, const char* name, + const struct elf_section_header **header) +{ + int i; + + *header = NULL; + + for (i = 0; i < elf->sections_count; i++) + if (strcmp(elf->sections[i].name, name) == 0) { + *header = &elf->sections[i]; + return 0; + } + + return -ENOENT; +} + +void elf_section_header_print(const struct elf_section_header *header) +{ + fprintf(stdout, "\tname\t\t0x%8.8x\n", header->data.name); + fprintf(stdout, "\tname\t\t%s\n", header->name); + fprintf(stdout, "\ttype\t\t0x%8.8x ", header->data.type); + print_enum(header->data.type, sh_types); + fprintf(stdout, "\tflags\t\t0x%8.8x ", header->data.flags); + print_flags(header->data.flags, sh_flags); + fprintf(stdout, "\taddr\t\t0x%8.8x\n", header->data.vaddr); + fprintf(stdout, "\toffset\t\t0x%8.8x\n", header->data.off); + fprintf(stdout, "\tsize\t\t0x%8.8x\n", header->data.size); + fprintf(stdout, "\tlink\t\t0x%8.8x\n", header->data.link); + fprintf(stdout, "\tinfo\t\t0x%8.8x\n", header->data.info); + fprintf(stdout, "\taddralign\t0x%8.8x\n", header->data.addralign); + fprintf(stdout, "\tentsize\t\t0x%8.8x\n\n", header->data.entsize); +} + +/** + * Release section header structure + * + * @param sec_hdr Section header structure + */ +static void elf_section_header_free(struct elf_section_header *sec_hdr) +{ + free(sec_hdr->name); + sec_hdr->name = NULL; +} + + +int elf_open(struct elf_file *elf, const char *filename) +{ + struct elf_strings names; + int ret = -ENOMEM; + + memset(elf, 0, sizeof(*elf)); + elf->filename = strdup(filename); + if (!elf->filename) { + ret = -ENOMEM; + goto err; + } + + elf->file = fopen(filename, "rb"); + if (!elf->file) { + ret = file_error("Unable to open elf file", elf->filename); + goto err; + } + + ret = get_file_size(elf->file, elf->filename, &elf->file_size); + if (ret) + goto err; + + ret = elf_header_read(elf); + if (ret) + goto err; + + ret = elf_program_headers_read(elf); + if (ret) + goto err; + + ret = elf_section_headers_read(elf); + if (ret) + goto err; + + ret = elf_strings_read_by_index(elf, elf->header.shstrndx, &names); + if (ret) + goto err; + + ret = elf_set_sections_names(elf, &names); + if (ret) { + elf_strings_free(&names); + goto err; + } + elf_strings_free(&names); + + return 0; + +err: + elf_free(elf); + + return ret; +} + +/** +* Close elf file and release resources +* @param elf elf file structure +*/ +void elf_free(struct elf_file *elf) +{ + int i; + + free(elf->filename); + free(elf->programs); + + if (elf->file) + fclose(elf->file); + + if (elf->sections) { + for (i = 0; i < elf->sections_count; i++) + elf_section_header_free(&elf->sections[i]); + + free(elf->sections); + } +} + +int elf_section_read_content(const struct elf_file *elf, const struct elf_section_header *header, + void *buffer, const size_t size) +{ + int ret; + size_t count; + + if ((header->data.type == SHT_NOBITS) || (header->data.type == SHT_NULL) || + !header->data.size) + return elf_error(elf, "Can't read section without data.", ENODATA); + + if (!header->data.off || (header->data.off + header->data.size) > elf->file_size) + return elf_error(elf, "Invalid section position in file.", ENFILE); + + if (header->data.size > size) + return elf_error(elf, "Output buffer too small.", ENOSPC); + + ret = fseek(elf->file, header->data.off, SEEK_SET); + if (ret) + return file_error("unable to seek to section data", elf->filename); + + count = fread(buffer, header->data.size, 1, elf->file); + if (count != 1) { + if (!count) + return file_error("failed to read section data", elf->filename); + else + return elf_error(elf, "Corrupted file.", ENODATA); + } + + return 0; +} + +int elf_section_read(const struct elf_file *elf, const struct elf_section_header *header, + struct elf_section *section) +{ + int ret; + + section->data = malloc(header->data.size); + if (!section->data) + return elf_error(elf, "No memory for section buffer.", ENOMEM); + + ret = elf_section_header_copy(header, §ion->header); + if (ret) + goto err; + + ret = elf_section_read_content(elf, header, section->data, header->data.size); + if (ret) + goto err; + + return 0; + +err: + elf_section_header_free(§ion->header); + free(section->data); + return ret; +} + +int elf_section_read_by_name(const struct elf_file *elf, const char *name, + struct elf_section *section) +{ + const struct elf_section_header *header; + int ret; + + ret = elf_section_header_get_by_name(elf, name, &header); + + if (ret) + return ret; + + return elf_section_read(elf, header, section); +} + +void elf_section_free(struct elf_section *section) +{ + free(section->data); +} + +int elf_strings_read_by_index(const struct elf_file *elf, int index, struct elf_strings *strings) +{ + const struct elf_section_header *header; + int ret; + + ret = elf_section_header_get_by_index(elf, index, &header); + if (ret) + return ret; + + if (header->data.type != SHT_STRTAB) + return elf_error(elf, "Invalid section type.", EINVAL); + + ret = elf_section_read(elf, header, &strings->section); + if (ret) + return elf_error(elf, "Unable to read section names section.", ret); + + return 0; +} + +int elf_strings_get(const struct elf_strings *strings, int index, char **str) +{ + if (index >= strings->section.header.data.size) + return -EINVAL; + + *str = strdup((const char *)strings->section.data + index); + if (!*str) + return -ENOMEM; + + return 0; +} + +void elf_strings_free(struct elf_strings *strings) +{ + elf_section_free(&strings->section); +} + +void elf_program_header_print(const Elf32_Phdr *header) +{ + fprintf(stdout, "\ttype\t 0x%8.8x ", header->type); + print_enum(header->type, p_type); + fprintf(stdout, "\tflags\t 0x%8.8x ", header->flags); + print_flags(header->flags, p_flags); + fprintf(stdout, "\toffset\t 0x%8.8x\n", header->off); + fprintf(stdout, "\tvaddr\t 0x%8.8x\n", header->vaddr); + fprintf(stdout, "\tpaddr\t 0x%8.8x\n", header->paddr); + fprintf(stdout, "\tfilesz\t 0x%8.8x\n", header->filesz); + fprintf(stdout, "\tmemsz\t 0x%8.8x\n", header->memsz); + fprintf(stdout, "\talign\t 0x%8.8x\n\n", header->align); +} diff --git a/tools/rimage/src/ext_manifest.c b/tools/rimage/src/ext_manifest.c new file mode 100644 index 000000000000..03a157c08397 --- /dev/null +++ b/tools/rimage/src/ext_manifest.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include <rimage/ext_manifest_gen.h> +#include <rimage/sof/kernel/ext_manifest.h> +#include <rimage/rimage.h> +#include <rimage/cavs/cavs_ext_manifest.h> +#include <rimage/manifest.h> +#include <rimage/file_utils.h> + +const struct ext_man_header ext_man_template = { + .magic = EXT_MAN_MAGIC_NUMBER, + .header_version = EXT_MAN_VERSION, + .header_size = sizeof(struct ext_man_header), + .full_size = 0, /* runtime variable */ +}; + +static int ext_man_open_file(struct image *image) +{ + int ret; + + ret = create_file_name(image->out_ext_man_file, sizeof(image->out_ext_man_file), + image->out_file, "xman"); + if (ret) + return ret; + + /* open extended manifest outfile for writing */ + image->out_ext_man_fd = fopen(image->out_ext_man_file, "wb"); + if (!image->out_ext_man_fd) + return file_error("unable to open file for writing", image->out_ext_man_file); + + return 0; +} + +static const struct elf_file *ext_man_find_module(const struct image *image, + const struct elf_section_header **section) +{ + const struct manifest_module *module; + int i; + + for (i = 0; i < image->num_modules; i++) { + module = &image->module[i]; + + if (module->is_bootloader) + continue; + + if (!elf_section_header_get_by_name(&module->file.elf, EXT_MAN_DATA_SECTION, + section)) + return &module->file.elf; + } + + return NULL; +} + +static int ext_man_validate(uint32_t section_size, const void *section_data) +{ + uint8_t *sbuf = (uint8_t *)section_data; + struct ext_man_elem_header head; + uint32_t offset = 0; + + /* copy each head to local struct to omit memory align issues */ + while (offset < section_size) { + memcpy(&head, &sbuf[offset], sizeof(head)); + fprintf(stdout, "Extended manifest found module, type: 0x%04X size: 0x%04X (%4d) offset: 0x%04X\n", + head.type, head.elem_size, head.elem_size, offset); + if (head.elem_size == 0 || head.elem_size % EXT_MAN_ALIGN) { + fprintf(stderr, + "error: invalid extended manifest element size\n"); + return -EINVAL; + } + offset += head.elem_size; + } + + /* sum of packets size != section size */ + if (offset != section_size) { + fprintf(stderr, + "error: fw_metadata section is inconsistent, section size: 0x%04X != 0x%04X sum of packets size\n", + section_size, offset); + return -EINVAL; + } else { + return 0; + } +} + +static int ext_man_build(const struct elf_file *file, const struct elf_section_header *section, + struct ext_man_header **dst_buff) +{ + struct ext_man_header *ext_man; + size_t size; + int ret; + + size = ext_man_template.header_size + section->data.size; + if (size % 4) { + fprintf(stderr, "error: extended manifest size must be aligned to 4\n"); + return -EINVAL; + } + + ext_man = calloc(1, size); + if (!ext_man) + return -ENOMEM; + + /* fill ext_man struct, size aligned to 4 to avoid unaligned accesses */ + memcpy(ext_man, &ext_man_template, ext_man_template.header_size); + ext_man->full_size = size; + + ret = elf_section_read_content(file, section, ext_man + 1, + size - ext_man_template.header_size); + if (ret < 0) { + fprintf(stderr, "error: failed to read %s section content, code %d\n", + EXT_MAN_DATA_SECTION, ret); + free(ext_man); + return ret; + } + + *dst_buff = ext_man; + return 0; +} + +int ext_man_write(struct image *image) +{ + const struct elf_file *file; + struct ext_man_header *ext_man = NULL; + const struct elf_section_header *section; + int count; + int ret; + + ret = ext_man_open_file(image); + if (ret) + goto out; + + file = ext_man_find_module(image, §ion); + if (!file) { + ret = -ECANCELED; + goto out; + } + + ret = ext_man_build(file, section, &ext_man); + if (ret) + goto out; + + /* validate metadata section */ + ret = ext_man_validate(ext_man->full_size - ext_man->header_size, + (char *)ext_man + ext_man->header_size); + if (ret) { + ret = -errno; + goto out; + } + + /* write extended metadata to file */ + count = fwrite(ext_man, 1, ext_man->full_size, image->out_ext_man_fd); + + if (count != ext_man->full_size) { + ret = file_error("can't write extended manifest", image->out_ext_man_file); + goto out; + } + + fprintf(stdout, "Extended manifest saved to file %s size 0x%04X (%d) bytes\n\n", + image->out_ext_man_file, ext_man->full_size, + ext_man->full_size); + +out: + if (ext_man) + free(ext_man); + if (image->out_ext_man_fd) + fclose(image->out_ext_man_fd); + return ret; +} + +int ext_man_write_cavs_25(struct image *image) +{ + struct fw_image_ext_module *mod_ext; + struct fw_ext_man_cavs_header header; + int pin_count; + int count, i; + int ret; + size_t write_ret; + + ret = ext_man_open_file(image); + if (ret) + goto out; + + mod_ext = &image->adsp->modules->mod_ext; + count = mod_ext->mod_conf_count; + header.version_major = EXTENDED_MANIFEST_VERSION_MAJOR; + header.version_minor = EXTENDED_MANIFEST_VERSION_MINOR; + header.num_module_entries = count; + header.id = EXTENDED_MANIFEST_MAGIC_HEADER_ID; + header.len = sizeof(const struct fw_ext_man_cavs_header); + + for (i = 0; i < count; i++) + header.len += mod_ext->ext_mod_config_array[i].header.ext_module_config_length; + write_ret = fwrite(&header, sizeof(header), 1, image->out_ext_man_fd); + if (write_ret != 1) { + ret = file_error("can't write fw_ext_man_cavs_header", + image->out_ext_man_file); + goto out; + } + + for (i = 0; i < count; i++) { + write_ret = fwrite(&mod_ext->ext_mod_config_array[i].header, + sizeof(struct fw_ext_mod_config_header), 1, + image->out_ext_man_fd); + if (write_ret != 1) { + ret = file_error("can't write fw_ext_mod_config_header", + image->out_ext_man_file); + goto out; + } + + if (mod_ext->ext_mod_config_array[i].header.num_scheduling_capabilities) { + write_ret = fwrite(&mod_ext->ext_mod_config_array[i].sched_caps, + sizeof(struct mod_scheduling_caps), 1, + image->out_ext_man_fd); + if (write_ret != 1) { + ret = file_error("can't write mod_scheduling_caps", + image->out_ext_man_file); + goto out; + } + } + + pin_count = mod_ext->ext_mod_config_array[i].header.num_pin_entries; + if (pin_count) { + write_ret = fwrite(mod_ext->ext_mod_config_array[i].pin_desc, + sizeof(struct fw_pin_description), pin_count, + image->out_ext_man_fd); + + if (write_ret != pin_count) { + ret = file_error("can't write fw_pin_description", + image->out_ext_man_file); + goto out; + } + } + } + +out: + if (image->out_ext_man_fd) + fclose(image->out_ext_man_fd); + return ret; +} diff --git a/tools/rimage/src/file_simple.c b/tools/rimage/src/file_simple.c new file mode 100644 index 000000000000..4ea597e18152 --- /dev/null +++ b/tools/rimage/src/file_simple.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2015 Intel Corporation. All rights reserved. + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> + +#include <rimage/rimage.h> +#include <rimage/manifest.h> +#include <rimage/file_utils.h> + +static int get_mem_zone_type(const struct memory_config *memory, + const struct module_section *section) +{ + uint32_t start, end, base, size; + int i; + + start = section->load_address; + end = start + section->size; + + for (i = SOF_FW_BLK_TYPE_START; i < SOF_FW_BLK_TYPE_NUM; i++) { + base = memory->zones[i].base; + size = memory->zones[i].size; + + if (start < base) + continue; + if (start >= base + size) + continue; + if (end > base + size) + continue; + return i; + } + return SOF_FW_BLK_TYPE_INVALID; +} + +static int block_idx; + +static int write_block(struct image *image, struct manifest_module *module, + const struct module_section *section) +{ + const struct adsp *adsp = image->adsp; + struct snd_sof_blk_hdr block; + uint32_t padding = 0; + size_t count; + int ret; + + block.size = section->size; + if (block.size % 4) { + /* make block.size divisible by 4 to avoid unaligned accesses */ + padding = 4 - (block.size % 4); + block.size += padding; + } + + ret = get_mem_zone_type(&adsp->mem, section); + if (ret != SOF_FW_BLK_TYPE_INVALID) { + block.type = ret; + block.offset = section->load_address - adsp->mem.zones[ret].base + + adsp->mem.zones[ret].host_offset; + } else { + fprintf(stderr, "error: invalid block address/size 0x%x/0x%zx\n", + section->load_address, section->size); + return -EINVAL; + } + + /* write header */ + count = fwrite(&block, sizeof(block), 1, image->out_fd); + if (count != 1) + return file_error("Write header failed", image->out_file); + + /* write out section data */ + ret = module_write_section(&module->file, section, padding, image->out_fd, image->out_file); + if (ret) { + fprintf(stderr, "error: cant write section data. foffset %d size 0x%zx mem addr 0x%x\n", + section->header->data.off, section->size, section->load_address); + return ret; + } + + fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8zx\t0x%8.8lx\t%s\t%s\n", block_idx++, + section->load_address, section->size, ftell(image->out_fd), + block.type == SOF_FW_BLK_TYPE_IRAM ? "TEXT" : "DATA", + section->header->name); + + /* return padding size */ + return padding; +} + +/** + * Write all linked sections + * + * @param image program global structure + * @param module modules manifest description + * @param section module section descriptor + * @return size of used padding, error code on error + */ +static int write_blocks(struct image *image, struct manifest_module *module, + const struct module_section *section) +{ + int ret, padding = 0; + + while (section) { + ret = write_block(image, module, section); + if (ret < 0) { + fprintf(stderr, "error: failed to write section %s\n", + section->header->name); + return ret; + } + + padding += ret; + section = section->next_section; + } + + return padding; +} + +static int simple_write_module(struct image *image, struct manifest_module *module) +{ + struct snd_sof_mod_hdr hdr; + size_t count; + int err; + int ptr_hdr, ptr_cur; + uint32_t padding; + + hdr.num_blocks = module->file.text.count + module->file.data.count; + hdr.size = module->file.text.size + module->file.data.size + + sizeof(struct snd_sof_blk_hdr) * hdr.num_blocks; + hdr.type = SOF_FW_BASE; + + /* Get the pointer of writing hdr */ + ptr_hdr = ftell(image->out_fd); + if (ptr_hdr < 0) + return file_error("cant get file position", image->out_file); + + count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); + if (count != 1) + return file_error("failed to write section header", image->out_file); + + module_print_zones(&module->file); + + fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\t\tType\tName\n"); + + /* Write text sections */ + err = write_blocks(image, module, module->file.text.first_section); + if (err < 0) + return err; + padding = err; + + /* Write data sections */ + err = write_blocks(image, module, module->file.data.first_section); + if (err < 0) + return err; + padding += err; + + hdr.size += padding; + /* Record current pointer, will set it back after overwriting hdr */ + ptr_cur = ftell(image->out_fd); + if (ptr_cur < 0) + return file_error("cant get file position", image->out_file); + + /* overwrite hdr */ + err = fseek(image->out_fd, ptr_hdr, SEEK_SET); + if (err) + return file_error("cant seek to header", image->out_file); + + count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); + if (count != 1) + return file_error("failed to write section header", image->out_file); + + err = fseek(image->out_fd, ptr_cur, SEEK_SET); + if (err) + return file_error("cant seek", image->out_file); + + fprintf(stdout, "\n"); + /* return padding size */ + return padding; +} + +static int write_block_reloc(struct image *image, struct manifest_module *module) +{ + struct snd_sof_blk_hdr block; + size_t count; + int ret; + + block.size = module->file.elf.file_size; + block.type = SOF_FW_BLK_TYPE_DRAM; + block.offset = 0; + + /* write header */ + count = fwrite(&block, sizeof(block), 1, image->out_fd); + if (count != 1) + return file_error("cant write header", image->out_file); + + ret = module_write_whole_elf(&module->file, image->out_fd, image->out_file); + if (ret) + return ret; + + fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8zx\t0x%8.8lx\t%s\n", block_idx++, + 0, module->file.elf.file_size, ftell(image->out_fd), + block.type == SOF_FW_BLK_TYPE_IRAM ? "TEXT" : "DATA"); + + return ret; +} + +static int simple_write_module_reloc(struct image *image, struct manifest_module *module) +{ + struct snd_sof_mod_hdr hdr; + size_t count; + int err; + + hdr.num_blocks = 1; + hdr.size = module->file.text.size + module->file.data.size; + hdr.type = SOF_FW_BASE; // module + + count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); + if (count != 1) + return file_error("failed to write section header", image->out_file); + + module_print_zones(&module->file); + + fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\t\tType\n"); + + err = write_block_reloc(image, module); + if (err < 0) { + fprintf(stderr, "error: failed to write section #%d\n", err); + return err; + } + + fprintf(stdout, "\n"); + return 0; +} + +/* used by others */ +int simple_write_firmware(struct image *image) +{ + struct snd_sof_fw_header hdr; + struct manifest_module *module; + size_t count; + int i, ret; + + memcpy(hdr.sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE); + + hdr.num_modules = image->num_modules; + hdr.abi = SND_SOF_FW_ABI; + hdr.file_size = 0; + + for (i = 0; i < image->num_modules; i++) { + module = &image->module[i]; + module->output_size = module->file.data.size + module->file.text.size; + module->output_size += sizeof(struct snd_sof_blk_hdr) * + (module->file.data.count + module->file.text.count); + module->output_size += sizeof(struct snd_sof_mod_hdr) * + hdr.num_modules; + hdr.file_size += module->output_size; + } + + count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); + if (count != 1) + return file_error("failed to write header", image->out_file); + + for (i = 0; i < image->num_modules; i++) { + module = &image->module[i]; + + fprintf(stdout, "writing module %d %s\n", i, module->file.elf.filename); + + if (image->reloc) + ret = simple_write_module_reloc(image, module); + else + ret = simple_write_module(image, module); + if (ret < 0) { + fprintf(stderr, "error: failed to write module %d\n", + i); + return ret; + } + /* add padding size */ + hdr.file_size += ret; + } + /* overwrite hdr */ + ret = fseek(image->out_fd, 0, SEEK_SET); + if (ret) + return file_error("can't seek set", image->out_file); + + + count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); + if (count != 1) + return file_error("failed to write header", image->out_file); + + fprintf(stdout, "firmware: image size %ld (0x%lx) bytes %d modules\n\n", + (long)(hdr.file_size + sizeof(hdr)), + (long)(hdr.file_size + sizeof(hdr)), + hdr.num_modules); + + return 0; +} diff --git a/tools/rimage/src/file_utils.c b/tools/rimage/src/file_utils.c new file mode 100644 index 000000000000..89a89ae40954 --- /dev/null +++ b/tools/rimage/src/file_utils.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2023 Intel Corporation. All rights reserved. +// +// Author: Adrian Warecki <adrian.warecki@intel.com> + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <assert.h> +#include <string.h> + +#include <rimage/file_utils.h> + +int file_error(const char *msg, const char *filename) +{ + int code = errno; + char sys_msg[256]; + + strerror_r(code, sys_msg, sizeof(sys_msg)); + + fprintf(stderr, "%s:\terror: %s. %s (errno = %d)\n", filename, msg, sys_msg, code); + return -code; +} + +int create_file_name(char *new_name, const size_t name_size, const char *template_name, + const char *new_ext) +{ + int len; + + assert(new_name); + + len = snprintf(new_name, name_size, "%s.%s", template_name, new_ext); + if (len >= name_size) { + fprintf(stderr, "error: output file name too long\n"); + return -ENAMETOOLONG; + } + + unlink(new_name); + + return 0; +} + +int get_file_size(FILE *f, const char* filename, size_t *size) +{ + int ret; + long pos; + assert(size); + + /* get file size */ + ret = fseek(f, 0, SEEK_END); + if (ret) + return file_error("unable to seek eof", filename); + + pos = ftell(f); + if (pos < 0) + return file_error("unable to get file size", filename); + + ret = fseek(f, 0, SEEK_SET); + if (ret) + return file_error("unable to seek set", filename); + + *size = pos; + return 0; +} diff --git a/tools/rimage/src/hash.c b/tools/rimage/src/hash.c new file mode 100644 index 000000000000..0604670e9c6e --- /dev/null +++ b/tools/rimage/src/hash.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + * Keyon Jie <yang.jie@linux.intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> + +#include <openssl/conf.h> +#include <openssl/evp.h> +#include <openssl/err.h> + +#include <rimage/rimage.h> +#include <rimage/manifest.h> +#include <rimage/hash.h> + +#define DEBUG_HASH 0 + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +EVP_MD_CTX *EVP_MD_CTX_new(void); + +static void *OPENSSL_zalloc(size_t num) +{ + void *ret = OPENSSL_malloc(num); + + if (ret) + memset(ret, 0, num); + return ret; +} + +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); +} + +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} +#endif + +static int hash_error(struct hash_context *context, int errcode, const char *msg) +{ + EVP_MD_CTX_free(context->context); + context->context = NULL; + context->state = HS_ERROR; + context->error = -errcode; + fprintf(stderr, "hash: %s\n", msg); + return context->error; +} + +int hash_init(struct hash_context *context, const EVP_MD *algo) +{ + assert(context); + assert(algo); + + context->error = 0; + context->digest_length = 0; + context->algo = algo; + + context->context = EVP_MD_CTX_new(); + if (!context->context) + return hash_error(context, ENOMEM, "Unable to allocate hash context."); + + if (!EVP_DigestInit_ex(context->context, context->algo, NULL)) { + EVP_MD_CTX_free(context->context); + return hash_error(context, ENOTRECOVERABLE, "Unable to initialize hash context."); + } + + context->state = HS_UPDATE; + return 0; +} + +int hash_sha256_init(struct hash_context *context) +{ + return hash_init(context, EVP_sha256()); +} + +int hash_sha384_init(struct hash_context *context) +{ + return hash_init(context, EVP_sha384()); +} + +int hash_update(struct hash_context *context, const void *data, size_t size) +{ + assert(context); + assert(data); + + if (context->error) + return context->error; + + assert(context->state == HS_UPDATE); + + if (!EVP_DigestUpdate(context->context, data, size)) + return hash_error(context, EINVAL, "Unable to update hash context."); + + return 0; +} + +int hash_finalize(struct hash_context *context) +{ + assert(context); + + if (context->error) + return context->error; + + assert(context->state == HS_UPDATE); + + if (!EVP_DigestFinal_ex(context->context, context->digest, &context->digest_length)) + return hash_error(context, EINVAL, "Unable to finalize hash context."); + + context->state = HS_DONE; + +#if DEBUG_HASH + fprintf(stdout, "Hash result is: "); + hash_print(context); +#endif + + EVP_MD_CTX_free(context->context); + context->context = NULL; + return 0; +} + +int hash_get_digest(struct hash_context *context, void *output, size_t output_len) +{ + assert(context); + assert(output); + + if (context->error) + return context->error; + + assert(context->state == HS_DONE); + + if (context->digest_length > output_len) + return -ENOBUFS; + + memcpy(output, context->digest, context->digest_length); + return context->digest_length; +} + +void hash_print(struct hash_context *context) +{ + unsigned int i; + + assert(context); + assert(context->state == HS_DONE); + assert(context->digest_length); + + for (i = 0; i < context->digest_length; i++) + fprintf(stdout, "%02x", context->digest[i]); + fprintf(stdout, "\n"); +} + +int hash_single(const void *data, size_t size, const EVP_MD *algo, void *output, size_t output_len) +{ + int algo_out_size; + + assert(algo); + assert(data); + assert(output); + + //algo_out_size = EVP_MD_get_size(algo); + algo_out_size = EVP_MD_size(algo); + if (algo_out_size <= 0) + return -EINVAL; + + if (output_len > algo_out_size) + return -ENOBUFS; + + if (!EVP_Digest(data, size, output, NULL, algo, NULL)) { + fprintf(stderr, "Unable to compute hash."); + return -ENOTRECOVERABLE; + } + + return 0; +} + +int hash_sha256(const void *data, size_t size, void *output, size_t output_len) +{ + return hash_single(data, size, EVP_sha256(), output, output_len); +} + +int hash_sha384(const void *data, size_t size, void *output, size_t output_len) +{ + return hash_single(data, size, EVP_sha384(), output, output_len); +} diff --git a/tools/rimage/src/include/rimage/adsp_config.h b/tools/rimage/src/include/rimage/adsp_config.h new file mode 100644 index 000000000000..e87c78c65f91 --- /dev/null +++ b/tools/rimage/src/include/rimage/adsp_config.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. + +#include <rimage/rimage.h> +#include <stdbool.h> + +int adsp_parse_config(const char *file, struct image *image); +void adsp_free(struct adsp *adsp); diff --git a/tools/rimage/src/include/rimage/cavs/cavs_ext_manifest.h b/tools/rimage/src/include/rimage/cavs/cavs_ext_manifest.h new file mode 100644 index 000000000000..e135dbbfc191 --- /dev/null +++ b/tools/rimage/src/include/rimage/cavs/cavs_ext_manifest.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Rander Wang <rander.wang@linux.intel.com> + */ + +#ifndef __RIMAGE_CAVS_EXT_MANIFEST_H__ +#define __RIMAGE_CAVS_EXT_MANIFEST_H__ + +/* Structure of ext manifest : + * ExtendedManifestHeader + * ExtendedModuleConfig[0] + * SchedulingCapability[] + * PinDescr[] + * ExtendedModuleConfig[1] + * SchedulingCapability[] + * PinDescr[] + * ... + * ExtendedModuleConfig[N] + * SchedulingCapability[] + * PinDescr[] + */ + +/* ExtendedManifestHeader id $AE1 */ +#define EXTENDED_MANIFEST_MAGIC_HEADER_ID 0x31454124 +#define EXTENDED_MANIFEST_VERSION_MAJOR 0x0001 +#define EXTENDED_MANIFEST_VERSION_MINOR 0x0000 + +#define FW_MAX_EXT_MODULE_NUM 48 + +struct uuid_t { + uint32_t d0; + uint16_t d1; + uint16_t d2; + uint8_t d3; + uint8_t d4; + uint8_t d5; + uint8_t d6; + uint8_t d7; + uint8_t d8; + uint8_t d9; + uint8_t d10; +} __attribute__((packed)); + +union mod_multiples { + uint16_t ul; + struct { + uint16_t x1 : 1; + uint16_t x2 : 1; + uint16_t x3 : 1; + uint16_t x4 : 1; + uint16_t x5 : 1; + uint16_t x6 : 1; + uint16_t x7 : 1; + uint16_t x8 : 1; + uint16_t x9 : 1; + uint16_t x10 : 1; + uint16_t x11 : 1; + uint16_t x12 : 1; + uint16_t x13 : 1; + uint16_t x14 : 1; + uint16_t x15 : 1; + uint16_t all : 1; + } r; +} __attribute__((packed)); + +struct mod_scheduling_caps { + /* scheduling period in Samples (sample groups) (note: 1 Sample = 1 sample per channel) */ + uint16_t frame_length; + union mod_multiples multiples_supported; +} __attribute__((packed)); + +enum mod_pin_direction { + pin_input = 0, + pin_output = 1 +}; + +union mod_pin_caps { + uint32_t ul; + struct { + uint16_t direction : 1; /* 0 : input; 1: output */ + uint16_t reserved0 : 15; + uint16_t reserved1 : 16; + } r; +} __attribute__((packed)); + +union mod_sample_rates { + uint32_t ul; + struct { + uint32_t freq_8000 : 1; + uint32_t freq_11025 : 1; + uint32_t freq_12000 : 1; + uint32_t freq_16000 : 1; + uint32_t freq_18900 : 1; + uint32_t freq_22050 : 1; + uint32_t freq_24000 : 1; + uint32_t freq_32000 : 1; + uint32_t freq_37800 : 1; + uint32_t freq_44100 : 1; + uint32_t freq_48000 : 1; + uint32_t freq_64000 : 1; + uint32_t freq_88200 : 1; + uint32_t freq_96000 : 1; + uint32_t freq_176400 : 1; + uint32_t freq_192000 : 1; + uint32_t reserved : 16; + } r; +} __attribute__((packed)); + +union mod_sample_sizes { + uint32_t ul; + struct { + uint16_t bits_8 : 1; + uint16_t bits_16 : 1; + uint16_t bits_24 : 1; + uint16_t bits_32 : 1; + uint16_t bits_64 : 1; + uint16_t reserved0 : 11; + uint16_t reserved1 : 16; + } r; +} __attribute__((packed)); + +union mod_sample_containers { + uint32_t ul; + struct { + uint16_t bits_8 : 1; + uint16_t bits_16 : 1; + uint16_t bits_24 : 1; + uint16_t bits_32 : 1; + uint16_t bits_64 : 1; + uint16_t reserved0 : 11; + uint16_t reserved1 : 16; + } r; +} __attribute__((packed)); + +union mod_channel_config { + uint32_t ul; + struct { + /* FRONT_CENTER */ + uint32_t channel_mono : 1; + /* FRONT_LEFT | BACK_LEFT */ + uint32_t channel_dual_mono : 1; + /* FRONT_LEFT | FRONT_RIGHT */ + uint32_t channel_stereo : 1; + /* FRONT_LEFT | FRONT_RIGHT | LOW_FREQUENCY */ + uint32_t channel_2_1 : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER */ + uint32_t channel_3_0 : 1; + /* FRONT_LEFT | FRONT_RIGHT | BACK_LEFT | BACK_RIGHT */ + uint32_t channel_quad : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | BACK_CENTER */ + uint32_t channel_surround : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY */ + uint32_t channel_3_1 : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | BACK_LEFT | BACK_RIGHT */ + uint32_t channel_5_0 : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | SIDE_LEFT | SIDE_RIGHT */ + uint32_t channel_5_0_surround : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | BACK_LEFT | + * BACK_RIGHT + */ + uint32_t channel_5_1 : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | SIDE_LEFT | + * SIDE_RIGHT + */ + uint32_t channel_5_1_surround : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | BACK_LEFT | BACK_RIGHT | + * FRONT_LEFT_OF_CENTER | FRONT_RIGHT_OF_CENTER + */ + uint32_t channel_7_0 : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | BACK_LEFT | BACK_RIGHT | + * SIDE_LEFT | SIDE_RIGHT + */ + uint32_t channel_7_0_surround : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | BACK_LEFT | + * BACK_RIGHT | FRONT_LEFT_OF_CENTER | FRONT_RIGHT_OF_CENTER + */ + uint32_t channel_7_1 : 1; + /* FRONT_LEFT | FRONT_RIGHT | FRONT_CENTER | LOW_FREQUENCY | BACK_LEFT | + * BACK_RIGHT | SIDE_LEFT | SIDE_RIGHT + */ + uint32_t channel_7_1_surround : 1; + uint32_t reserved : 16; + } r; +} __attribute__((packed)); + +enum mod_stream_type { + epcm = 0, /* PCM stream */ + emp3, /* MP3 encoded stream */ + eaac, /* AAC encoded stream */ + emax_stream_type, + estream_type_invalid = 0xFF +}; + +enum mod_type { + ebasefw = 0, + emixin, + emixout, + ecopier, + epeakvol, + eupdwmix, + emux, + esrc, + ewov, + efx, + eaec, + ekpb, + emicselect, + efxf, /*i.e.SmartAmp */ + eaudclass, + efakecopier, + eiodriver, + ewhm, + egdbstub, + esensing, + emax, + einvalid = emax +} ; + +struct fw_pin_description { + union mod_pin_caps caps; + enum mod_stream_type format_type; + union mod_sample_rates sample_rate; + union mod_sample_sizes sample_size; + union mod_sample_containers sample_container; + union mod_channel_config ch_cfg; +} __attribute__((packed)); + +struct fw_ext_man_cavs_header { + uint32_t id; + uint32_t len; /* sizeof(Extend Manifest) in bytes */ + uint16_t version_major; /* Version of Extended Manifest structure */ + uint16_t version_minor; /* Version of Extended Manifest structure */ + uint32_t num_module_entries; +} __attribute__((packed)); + +struct fw_ext_mod_config_header { + uint32_t ext_module_config_length; /* sizeof(fw_ext_mod_config_header) in bytes */ + uint32_t guid[4]; /* Module GUID */ + uint16_t version_major; /* Module version */ + uint16_t version_minor; /* Module version */ + uint16_t version_hotfix; /* Module version */ + uint16_t version_build; /* Module version */ + enum mod_type module_type; + uint32_t init_settings_min_size; /* Minimum size of initialization settings (in bytes) */ + uint16_t num_scheduling_capabilities; /* number scheduling capabilities supported by the module */ + uint16_t num_pin_entries; /* Number of Pin (inputs + ouptuts) */ +} __attribute__((packed)); + +#endif diff --git a/tools/rimage/src/include/rimage/cse.h b/tools/rimage/src/include/rimage/cse.h new file mode 100644 index 000000000000..9a14b93b99f6 --- /dev/null +++ b/tools/rimage/src/include/rimage/cse.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + */ + +#ifndef __CSE_H__ +#define __CSE_H__ + +#include <stdint.h> + +struct image; + +#define CSE_HEADER_MAKER 0x44504324 /* "DPC$" */ + +struct CsePartitionDirHeader { + uint32_t header_marker; + uint32_t nb_entries; + uint8_t header_version; + uint8_t entry_version; + uint8_t header_length; + uint8_t checksum; + uint8_t partition_name[4]; +} __attribute__((packed)); + +struct CsePartitionDirHeader_v2_5 { + uint32_t header_marker; + uint32_t nb_entries; + uint8_t header_version; + uint8_t entry_version; + uint8_t header_length; + uint8_t not_used; /* set to zero - old checksum */ + uint8_t partition_name[4]; + uint32_t checksum; /* crc32 checksum */ +} __attribute__((packed)); + +struct CsePartitionDirEntry { + uint8_t entry_name[12]; + uint32_t offset; + uint32_t length; + uint32_t reserved; +} __attribute__((packed)); + +void ri_cse_create(struct image *image); +void ri_cse_create_v2_5(struct image *image); +void ri_cse_create_ace_v1_5(struct image *image); + +#endif diff --git a/tools/rimage/src/include/rimage/css.h b/tools/rimage/src/include/rimage/css.h new file mode 100644 index 000000000000..6283cdaf9042 --- /dev/null +++ b/tools/rimage/src/include/rimage/css.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + */ + +#ifndef __CSS_H__ +#define __CSS_H__ + +#include <stdint.h> + +struct image; + +#define MAN_CSS_LT_MODULE_TYPE 0x00000006 +#define MAN_CSS_MOD_TYPE 4 +#define MAN_CSS_HDR_SIZE 161 /* in words */ +#define MAN_CSS_HDR_SIZE_2_5 225 /* in words */ +#define MAN_CSS_HDR_VERSION 0x10000 +#define MAN_CSS_HDR_VERSION_2_5 0x21000 +#define MAN_CSS_MOD_VENDOR 0x8086 +#define MAN_CSS_HDR_ID {'$', 'M', 'N', '2'} + +#define MAN_CSS_KEY_SIZE (MAN_RSA_KEY_MODULUS_LEN >> 2) +#define MAN_CSS_MOD_SIZE (MAN_RSA_KEY_MODULUS_LEN >> 2) +#define MAN_CSS_MOD_SIZE_2_5 (MAN_RSA_KEY_MODULUS_LEN_2_5 >> 2) +#define MAN_CSS_EXP_SIZE (MAN_RSA_KEY_EXPONENT_LEN >> 2) +#define MAN_CSS_MAN_SIZE_V1_8 \ + (sizeof(struct fw_image_manifest_v1_8) >> 2) +#define MAN_CSS_MAN_SIZE_V1_5 \ + (sizeof(struct fw_image_manifest_v1_5) >> 2) + +/* + * RSA Key and Crypto + */ +#define MAN_RSA_KEY_MODULUS_LEN 256 +#define MAN_RSA_KEY_MODULUS_LEN_2_5 384 +#define MAN_RSA_KEY_EXPONENT_LEN 4 +#define MAN_RSA_SIGNATURE_LEN 256 +#define MAN_RSA_SIGNATURE_LEN_2_5 384 + +struct fw_version { + uint16_t major_version; + uint16_t minor_version; + uint16_t hotfix_version; + uint16_t build_version; +} __attribute__((packed)); + +struct css_header_v2_5 { + uint32_t header_type; + uint32_t header_len; + uint32_t header_version; + uint32_t reserved0; /* must be 0x1 */ + uint32_t module_vendor; + uint32_t date; + uint32_t size; + uint8_t header_id[4]; + uint32_t padding; /* must be 0x0 */ + struct fw_version version; + uint32_t svn; + uint32_t reserved1[18]; /* must be 0x0 */ + uint32_t modulus_size; + uint32_t exponent_size; + uint8_t modulus[MAN_RSA_KEY_MODULUS_LEN_2_5]; + uint8_t exponent[MAN_RSA_KEY_EXPONENT_LEN]; + uint8_t signature[MAN_RSA_SIGNATURE_LEN_2_5]; +} __attribute__((packed)); + +struct css_header_v1_8 { + uint32_t header_type; + uint32_t header_len; + uint32_t header_version; + uint32_t reserved0; /* must be 0x0 */ + uint32_t module_vendor; + uint32_t date; + uint32_t size; + uint8_t header_id[4]; + uint32_t padding; /* must be 0x0 */ + struct fw_version version; + uint32_t svn; + uint32_t reserved1[18]; /* must be 0x0 */ + uint32_t modulus_size; + uint32_t exponent_size; + uint8_t modulus[MAN_RSA_KEY_MODULUS_LEN]; + uint8_t exponent[MAN_RSA_KEY_EXPONENT_LEN]; + uint8_t signature[MAN_RSA_SIGNATURE_LEN]; +} __attribute__((packed)); + +struct css_header_v1_5 { + uint32_t module_type; + uint32_t header_len; + uint32_t header_version; + uint32_t reserved0; /* must be 0x0 */ + uint32_t module_vendor; + uint32_t date; + uint32_t size; + uint32_t key_size; + uint32_t modulus_size; + uint32_t exponent_size; + uint32_t reserved[22]; + uint8_t modulus[MAN_RSA_KEY_MODULUS_LEN]; + uint8_t exponent[MAN_RSA_KEY_EXPONENT_LEN]; + uint8_t signature[MAN_RSA_SIGNATURE_LEN]; +} __attribute__((packed)); + +void ri_css_v1_8_hdr_create(struct image *image); +void ri_css_v1_5_hdr_create(struct image *image); +void ri_css_v2_5_hdr_create(struct image *image); + +#endif diff --git a/tools/rimage/src/include/rimage/elf.h b/tools/rimage/src/include/rimage/elf.h new file mode 100644 index 000000000000..13a4965e059e --- /dev/null +++ b/tools/rimage/src/include/rimage/elf.h @@ -0,0 +1,936 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. + * Copyright (c) 2001 David E. O'Brien + * Portions Copyright 2009 The Go Authors. All rights reserved. + */ + +#ifndef __ELF_H__ +#define __ELF_H__ + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +#include <stdint.h> + +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; + +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; + + +typedef struct { + uint32 n_namesz; /* Length of name. */ + uint32 n_descsz; /* Length of descriptor. */ + uint32 n_type; /* Type of this note. */ +} Elf_Note; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developer/gabi/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_GNU_VERDEF 0x6ffffffd +#define SHT_GNU_VERNEED 0x6ffffffe +#define SHT_GNU_VERSYM 0x6fffffff +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ +#define PT_GNU_STACK 0x6474e551 +#define PT_PAX_FLAGS 0x65041580 + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +/* String table offset of a needed shared library. */ +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +/* String table offset of shared object name. */ +#define DT_SONAME 14 +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +/* Indicates there may be relocations in non-writable segments. [sup] */ +#define DT_TEXTREL 22 +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +/* Address of the array of pointers to initialization functions */ +#define DT_INIT_ARRAY 25 +/* Address of the array of pointers to termination functions */ +#define DT_FINI_ARRAY 26 +/* Size in bytes of the array of initialization functions. */ +#define DT_INIT_ARRAYSZ 27 +/* Size in bytes of the array of terminationfunctions. */ +#define DT_FINI_ARRAYSZ 28 +/* String table offset of a null-terminated library search path string. */ +#define DT_RUNPATH 29 +#define DT_FLAGS 30 /* Object specific flag values. */ +/* Values greater than or equal to DT_ENCODING and less than + DT_LOOS follow the rules for the interpretation of the d_un + union as follows: even == 'd_ptr', even == 'd_val' or none */ +#define DT_ENCODING 32 +/* Address of the array of pointers to pre-initialization functions. */ +#define DT_PREINIT_ARRAY 32 +/* Size in bytes of the array of pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define DT_VERSYM 0x6ffffff0 + +/* Values for DT_FLAGS */ +/* Indicates that the object being loaded may make reference to + the $ORIGIN substitution string */ +#define DF_ORIGIN 0x0001 +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +/* Indicates there may be relocations in non-writable segments. */ +#define DF_TEXTREL 0x0004 +/* Indicates that the dynamic linker should process all + relocations for the object containing this entry before + transferring control to the program. */ +#define DF_BIND_NOW 0x0008 +/* Indicates that the shared object or executable contains code + using a static thread-local storage scheme. */ +#define DF_STATIC_TLS 0x0010 + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32 Elf32_Addr; +typedef uint16 Elf32_Half; +typedef uint32 Elf32_Off; +typedef int32 Elf32_Sword; +typedef uint32 Elf32_Word; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char ident[EI_NIDENT]; /* File identification. */ + Elf32_Half type; /* File type. */ + Elf32_Half machine; /* Machine architecture. */ + Elf32_Word version; /* ELF format version. */ + Elf32_Addr entry; /* Entry point. */ + Elf32_Off phoff; /* Program header file offset. */ + Elf32_Off shoff; /* Section header file offset. */ + Elf32_Word flags; /* Architecture-specific flags. */ + Elf32_Half ehsize; /* Size of ELF header in bytes. */ + Elf32_Half phentsize; /* Size of program header entry. */ + Elf32_Half phnum; /* Number of program header entries. */ + Elf32_Half shentsize; /* Size of section header entry. */ + Elf32_Half shnum; /* Number of section header entries. */ + Elf32_Half shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word name; /* Section name (index into the + section header string table). */ + Elf32_Word type; /* Section type. */ + Elf32_Word flags; /* Section flags. */ + Elf32_Addr vaddr; /* Address in memory image. */ + Elf32_Off off; /* Offset in file. */ + Elf32_Word size; /* Size in bytes. */ + Elf32_Word link; /* Index of a related section. */ + Elf32_Word info; /* Depends on section type. */ + Elf32_Word addralign; /* Alignment in bytes. */ + Elf32_Word entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word type; /* Entry type. */ + Elf32_Off off; /* File offset of contents. */ + Elf32_Addr vaddr; /* Virtual address in memory image. */ + Elf32_Addr paddr; /* Physical address (not used). */ + Elf32_Word filesz; /* Size of contents in file. */ + Elf32_Word memsz; /* Size of contents in memory. */ + Elf32_Word flags; /* Access permission flags. */ + Elf32_Word align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr off; /* Location to be relocated. */ + Elf32_Word info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr off; /* Location to be relocated. */ + Elf32_Word info; /* Relocation type and symbol index. */ + Elf32_Sword addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Relocation types. + */ + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + +#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ + + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ + +#define R_ALPHA_COUNT 28 + + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_V4BX 40 +#define R_ARM_GOT_PREL 96 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_TLS_IE32 107 +#define R_ARM_TLS_LE32 108 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +#define R_ARM_COUNT 38 /* Count of defined relocation types. */ + + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +#define R_386_COUNT 38 /* Count of defined relocation types. */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +#define R_PPC_COUNT 37 /* Count of defined relocation types. */ + +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + + /* Count of defined relocation types. */ +#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1) + + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 + + +/* + * Magic number for the elf trampoline, chosen wisely to be an immediate + * value. + */ +#define ARM_MAGIC_TRAMP_NUMBER 0x5c000003 + + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word name; /* String table index of name. */ + Elf32_Addr value; /* Symbol value. */ + Elf32_Word size; /* Size of associated object. */ + unsigned char info; /* Type and binding information. */ + unsigned char other; /* Reserved (not used). */ + Elf32_Half shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64 Elf64_Addr; +typedef uint16 Elf64_Half; +typedef uint64 Elf64_Off; +typedef int32 Elf64_Sword; +typedef int64 Elf64_Sxword; +typedef uint32 Elf64_Word; +typedef uint64 Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +#ifdef __alpha__ +typedef Elf64_Off Elf64_Hashelt; +#else +typedef Elf64_Word Elf64_Hashelt; +#endif + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char ident[EI_NIDENT]; /* File identification. */ + Elf64_Half type; /* File type. */ + Elf64_Half machine; /* Machine architecture. */ + Elf64_Word version; /* ELF format version. */ + Elf64_Addr entry; /* Entry point. */ + Elf64_Off phoff; /* Program header file offset. */ + Elf64_Off shoff; /* Section header file offset. */ + Elf64_Word flags; /* Architecture-specific flags. */ + Elf64_Half ehsize; /* Size of ELF header in bytes. */ + Elf64_Half phentsize; /* Size of program header entry. */ + Elf64_Half phnum; /* Number of program header entries. */ + Elf64_Half shentsize; /* Size of section header entry. */ + Elf64_Half shnum; /* Number of section header entries. */ + Elf64_Half shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct Elf64_Shdr Elf64_Shdr; +struct Elf64_Shdr { + Elf64_Word name; /* Section name (index into the + section header string table). */ + Elf64_Word type; /* Section type. */ + Elf64_Xword flags; /* Section flags. */ + Elf64_Addr addr; /* Address in memory image. */ + Elf64_Off off; /* Offset in file. */ + Elf64_Xword size; /* Size in bytes. */ + Elf64_Word link; /* Index of a related section. */ + Elf64_Word info; /* Depends on section type. */ + Elf64_Xword addralign; /* Alignment in bytes. */ + Elf64_Xword entsize; /* Size of each entry in section. */ +}; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word type; /* Entry type. */ + Elf64_Word flags; /* Access permission flags. */ + Elf64_Off off; /* File offset of contents. */ + Elf64_Addr vaddr; /* Virtual address in memory image. */ + Elf64_Addr paddr; /* Physical address (not used). */ + Elf64_Xword filesz; /* Size of contents in file. */ + Elf64_Xword memsz; /* Size of contents in memory. */ + Elf64_Xword align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr off; /* Location to be relocated. */ + Elf64_Xword info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr off; /* Location to be relocated. */ + Elf64_Xword info; /* Relocation type and symbol index. */ + Elf64_Sxword addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) ((((uint64)(sym)) << 32) + (((uint64)(type)) & 0xffffffffULL)) + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word name; /* String table index of name. */ + unsigned char info; /* Type and binding information. */ + unsigned char other; /* Reserved (not used). */ + Elf64_Half shndx; /* Section index of symbol. */ + Elf64_Addr value; /* Symbol value. */ + Elf64_Xword size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* + * Go linker interface + */ + +#define ELF64HDRSIZE 64 +#define ELF64PHDRSIZE 56 +#define ELF64SHDRSIZE 64 +#define ELF64RELSIZE 16 +#define ELF64RELASIZE 24 +#define ELF64SYMSIZE sizeof(Elf64_Sym) + +#define ELF32HDRSIZE sizeof(Elf32_Ehdr) +#define ELF32PHDRSIZE sizeof(Elf32_Phdr) +#define ELF32SHDRSIZE sizeof(Elf32_Shdr) +#define ELF32SYMSIZE sizeof(Elf32_Sym) +#define ELF32RELSIZE 8 + +#endif /* __ELF_H__ */ diff --git a/tools/rimage/src/include/rimage/elf_file.h b/tools/rimage/src/include/rimage/elf_file.h new file mode 100644 index 000000000000..13bfe98cf1f7 --- /dev/null +++ b/tools/rimage/src/include/rimage/elf_file.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __ELF_FILE_H__ +#define __ELF_FILE_H__ + +#include <stddef.h> + +#include "elf.h" + +struct elf_section_header { + Elf32_Shdr data; + char *name; +}; + +struct elf_section { + struct elf_section_header header; + void *data; +}; + +struct elf_strings { + struct elf_section section; +}; + +struct elf_file { + FILE *file; + char *filename; + size_t file_size; + Elf32_Ehdr header; + struct elf_section_header *sections; + Elf32_Phdr *programs; + uint16_t sections_count; + uint16_t programs_count; +}; + +/** + * Open elf file + * + * @param [out]elf elf file structure + * @param [in]filename File name to open + * @return error code, 0 when success + */ +int elf_open(struct elf_file *elf, const char *filename); + +/** + * Close elf file and release resources + * + * @param elf elf file structure + */ +void elf_free(struct elf_file *elf); + +/** + * Print elf file header + * + * @param elf elf file structure + */ +void elf_header_print(const struct elf_file *elf); + +/** + * Print program headers + * + * @param elf elf file structure + */ +void elf_print_programs(const struct elf_file *elf); + +/** + * Print single program header + * + * @param header program header structure + */ +void elf_program_header_print(const Elf32_Phdr *header); + +/** + * Print elf sections headers + * + * @param elf elf file structure + */ +void elf_print_sections(const struct elf_file *elf); + +/** + * Return section header by index + * + * @param [in]elf elf file structure + * @param [in]index section index + * @param [out]header section header data + * @return error code, 0 when success + */ +int elf_section_header_get_by_index(const struct elf_file *elf, int index, + const struct elf_section_header **header); + +/** + * Return section header by index + * + * @param [in]elf elf file structure + * @param [in]index section index + * @param [out]header section header data + * @return error code, 0 when success + */ +int elf_section_header_get_by_name(const struct elf_file *elf, const char* name, + const struct elf_section_header **header); +/** + * Print elf section header + * + * @param header section header structure + */ +void elf_section_header_print(const struct elf_section_header *header); + +/** + * Read elf section using given header + * + * @param [in]elf elf file structure + * @param [in]header section header + * @param [out]section section data + * @return error code, 0 when success + */ +int elf_section_read(const struct elf_file *elf, const struct elf_section_header *header, + struct elf_section *section); + +/** +* Read elf section using given header to specified buffer +* +* @param [in]elf elf file structure +* @param [in]header section header +* @param [out]buffer buffer for a section data +* @param [in]size buffer size +* @return error code, 0 when success +*/ +int elf_section_read_content(const struct elf_file *elf, const struct elf_section_header *header, + void *buffer, const size_t size); + +/** + * Read elf section with given name + * + * @param [in]elf elf file structure + * @param [in]name section name + * @param [out]section section data + * @return error code, 0 when success + */ +int elf_section_read_by_name(const struct elf_file *elf, const char *name, struct elf_section *section); + +/** + * Release section + * + * @param [in]section section structure + */ +void elf_section_free(struct elf_section *section); + +/** + * Read elf strings section with given index + * + * @param [in]elf elf file structure + * @param [in]index strings section index + * @param [out]strings strings section data + * @return error code, 0 when success + */ +int elf_strings_read_by_index(const struct elf_file *elf, int index, struct elf_strings *strings); + +/** + * Get string value. Allocate new copy using strdup. + * + * @param [in]strings strings section structure + * @param [in]index string index + * @param [out]str Pointer to the variable in which the pointer to the allocated string will be placed + * @return error code, 0 when success + */ +int elf_strings_get(const struct elf_strings *strings, int index, char **str); + +/** + * Release string section + * @param [in]strings strings section structure + */ +void elf_strings_free(struct elf_strings *strings); + +#endif /* __ELF_FILE_H__ */ diff --git a/tools/rimage/src/include/rimage/ext_manifest_gen.h b/tools/rimage/src/include/rimage/ext_manifest_gen.h new file mode 100644 index 000000000000..7f106834a0ca --- /dev/null +++ b/tools/rimage/src/include/rimage/ext_manifest_gen.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + * + * To add new content to ext_man, in firmware code define struct which starts + * with ext_man_elem_head followed by usage dependent content and place whole + * struct in "fw_metadata" section. Moreover kernel code should be modified to + * properly read new packet. + * + * Extended manifest designed to be extensible. In header there is a field which + * describe header length, so after appending some data to header then it can be + * easily skipped by device with older version of this header. + * From other side, unknown ext_man elements should be just skipped by host, + * to be backward compatible. Field ext_man_elem_header.elem_size should be + * used in such a situation. + */ + +#ifndef __EXT_MAN_H__ +#define __EXT_MAN_H__ + +#include <rimage/rimage.h> + +#define EXT_MAN_DATA_SECTION ".fw_metadata" + +int ext_man_write(struct image *image); +int ext_man_write_cavs_25(struct image *image); + +#endif /* __EXT_MAN_H__ */ diff --git a/tools/rimage/src/include/rimage/file_utils.h b/tools/rimage/src/include/rimage/file_utils.h new file mode 100644 index 000000000000..34ecc89f5bad --- /dev/null +++ b/tools/rimage/src/include/rimage/file_utils.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __FILE_UTILS_H__ +#define __FILE_UTILS_H__ + +#include <stddef.h> + +/** + * Print file operation error message + * @param [in]msg error message + * @param [in]filename File name used to display the error message + * @param error code + */ +int file_error(const char *msg, const char *filename); + +/** + * Create new file name using output file name as template. + * @param [out] new_name char[] destination of new file name + * @param [in] name_size new file name buffer capacity + * @param [in] template_name File name used as a template for the new name + * @param [in] new_ext extension of the new file name + * @param error code, 0 when success + */ +int create_file_name(char *new_name, const size_t name_size, const char *template_name, + const char *new_ext); + +/** + * Get file size + * @param [in] f file handle + * @param [in] filename File name used to display the error message + * @param [out] size output for file size + * @param error code, 0 when success + */ +int get_file_size(FILE *f, const char *filename, size_t *size); + +#endif /* __FILE_UTILS_H__ */ diff --git a/tools/rimage/src/include/rimage/hash.h b/tools/rimage/src/include/rimage/hash.h new file mode 100644 index 000000000000..47a00101af4f --- /dev/null +++ b/tools/rimage/src/include/rimage/hash.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __HASH_H__ +#define __HASH_H__ + +#include <openssl/conf.h> +#include <openssl/evp.h> +#include <openssl/err.h> + +#include <stdint.h> + +/* Hash context state used to detect invalid use of hash functions */ +enum hash_state { HS_INIT, HS_UPDATE, HS_DONE, HS_ERROR }; + +struct hash_context { + enum hash_state state; + EVP_MD_CTX *context; + const EVP_MD *algo; + uint8_t digest[EVP_MAX_MD_SIZE]; + unsigned int digest_length; + int error; +}; + +/** + * Initialize hash context with given algorithm + * @param [out]context structure storing the hash context + * @param [in]algo hash algorithm + * @return error code, 0 when success + */ +int hash_init(struct hash_context *context, const EVP_MD *algo); + +/** + * Initialize sha256 hash context + * @param [out]context structure storing the hash context + * @return error code, 0 when success + */ +int hash_sha256_init(struct hash_context *context); + +/** + * Initialize sha384 hash context + * @param [out]context structure storing the hash context + * @return error code, 0 when success + */ +int hash_sha384_init(struct hash_context *context); + +/** + * Add data to hash + * @param [in]context structure storing the hash context + * @param [in]data data to be added + * @param [in]size length of data in bytes + * @return error code, 0 when success + */ +int hash_update(struct hash_context *context, const void *data, size_t size); + +/** + * Completes the hash calculation. No more data can be added! + * @param [in]context structure storing the hash context + * @return error code, 0 when success + */ +int hash_finalize(struct hash_context *context); + +/** + * Read out computed digest. Must finalize first. + * @param [in]context structure storing the hash context + * @param [out]output pointer to array where place hash value + * @param [in]output_len size of the output buffer + * @return copied digest length, < 0 if error + */ +int hash_get_digest(struct hash_context *context, void *output, size_t output_len); + +/** + * Print digest value + * @param [in]context structure storing the hash context + */ +void hash_print(struct hash_context *context); + +/** + * Calculates hash of a single memory buffer + * @param [in]data pointer to the data to be processed + * @param [in]size length of the data to be processed + * @param [in]algo hash algorithm + * @param [out]output pointer to array where place hash value + * @param [in]output_len size of the output buffer + * @return error code, 0 when success + */ +int hash_single(const void* data, size_t size, const EVP_MD *algo, void *output, size_t output_len); + +/** + * Calculates sha256 hash of a memory buffer + * @param [in]data pointer to the data to be processed + * @param [in]size length of the data to be processed + * @param [out]output pointer to array where place hash value + * @param [in]output_len size of the output buffer + * @return error code, 0 when success + */ +int hash_sha256(const void* data, size_t size, void *output, size_t output_len); + +/** + * Calculates sha384 hash of a memory buffer + * @param [in]data pointer to the data to be processed + * @param [in]size length of the data to be processed + * @param [out]output pointer to array where place hash value + * @param [in]output_len size of the output buffer + * @return error code, 0 when success + */ +int hash_sha384(const void* data, size_t size, void *output, size_t output_len); + +#endif /* __HASH_H__ */ diff --git a/tools/rimage/src/include/rimage/manifest.h b/tools/rimage/src/include/rimage/manifest.h new file mode 100644 index 000000000000..840cd7d797bf --- /dev/null +++ b/tools/rimage/src/include/rimage/manifest.h @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + */ + +#ifndef __MANIFEST_H__ +#define __MANIFEST_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <rimage/sof/user/manifest.h> +#include <rimage/css.h> +#include <rimage/cse.h> +#include <rimage/plat_auth.h> +#include <rimage/module.h> + +/* + * Manifest module data + */ +struct manifest_module { + struct module file; + + /* Following fields are used in manifest creation process */ + bool is_bootloader; + + /* Size of the module in the output image. + * Includes text and data sections size + image headers*/ + size_t output_size; + + /* executable header module */ + int exec_header; + + /* module offset in image file */ + size_t foffset; + + size_t text_fixup_size; +}; + +#define MAN_PAGE_SIZE 4096 + +/* start offset for modules built using xcc */ +#define DEFAULT_XCC_MOD_OFFSET 0x8 + +/* start offset for base FW module */ +#define FILE_TEXT_OFFSET_V1_8 0x8000 +#define FILE_TEXT_OFFSET_V1_5 0x2000 +#define FILE_TEXT_OFFSET_V1_5_SUE 0xA000 + +/* + * CSE values for CNL + */ +#define MAN_CSE_PARTS 3 + + +#define MAN_CSE_HDR_OFFSET 0 +#define MAN_CSE_PADDING_SIZE 0x30 +#define MAN_EXT_PADDING 0x20 +#define MAN_DESC_OFFSET_V1_8 0x2000 +#define MAN_DESC_OFFSET_V1_5 0x284 +#define MAN_DESC_OFFSET_V1_5_SUE 0x2000 +#define MAN_DEFAULT_IMR_TYPE 3 + +#define MAN_CSS_HDR_OFFSET \ + (MAN_CSE_HDR_OFFSET + \ + sizeof(struct CsePartitionDirHeader) + \ + MAN_CSE_PARTS * sizeof(struct CsePartitionDirEntry)) + +#define MAN_CSS_HDR_OFFSET_2_5 \ + (MAN_CSE_HDR_OFFSET + \ + sizeof(struct CsePartitionDirHeader_v2_5) + \ + MAN_CSE_PARTS * sizeof(struct CsePartitionDirEntry)) + +#define MAN_FW_DESC_OFFSET_ACE_V1_5 \ + (MAN_META_EXT_OFFSET_ACE_V1_5 + \ + sizeof(struct sof_man_adsp_meta_file_ext_v2_5) + \ + MAN_EXT_PADDING) + +#define MAN_FW_DESC_OFFSET_V2_5 \ + (MAN_META_EXT_OFFSET_V2_5 + \ + sizeof(struct sof_man_adsp_meta_file_ext_v2_5) + \ + MAN_EXT_PADDING) + +#define MAN_DESC_PADDING_SIZE_ACE_V1_5 \ + (MAN_DESC_OFFSET_V1_8 - MAN_FW_DESC_OFFSET_ACE_V1_5) + +#define MAN_DESC_PADDING_SIZE_V2_5 \ + (MAN_DESC_OFFSET_V1_8 - MAN_FW_DESC_OFFSET_V2_5) + +#define MAN_SIG_PKG_OFFSET_V1_8 \ + (MAN_CSS_HDR_OFFSET + \ + sizeof(struct css_header_v1_8)) + +#define MAN_SIG_PKG_OFFSET_V2_5 \ + (MAN_CSS_HDR_OFFSET_2_5 + \ + sizeof(struct css_header_v2_5)) + +#define MAN_PART_INFO_OFFSET_V1_8 \ + (MAN_SIG_PKG_OFFSET_V1_8 + \ + sizeof(struct signed_pkg_info_ext)) + +#define MAN_PART_INFO_OFFSET_ACE_V1_5 \ + (MAN_SIG_PKG_OFFSET_V2_5 + \ + sizeof(struct signed_pkg_info_ext_ace_v1_5)) + +#define MAN_PART_INFO_OFFSET_V2_5 \ + (MAN_SIG_PKG_OFFSET_V2_5 + \ + sizeof(struct signed_pkg_info_ext_v2_5)) + +#define MAN_META_EXT_OFFSET_V1_8 \ + (MAN_SIG_PKG_OFFSET_V1_8 + \ + sizeof(struct signed_pkg_info_ext) + \ + sizeof(struct partition_info_ext) + \ + MAN_CSE_PADDING_SIZE) + +#define MAN_META_EXT_OFFSET_ACE_V1_5 \ + (MAN_SIG_PKG_OFFSET_V2_5 + \ + sizeof(struct signed_pkg_info_ext_ace_v1_5) + \ + sizeof(struct info_ext_0x16) + \ + 0) + +#define MAN_META_EXT_OFFSET_V2_5 \ + (MAN_SIG_PKG_OFFSET_V2_5 + \ + sizeof(struct signed_pkg_info_ext_v2_5) + \ + sizeof(struct info_ext_0x16) + \ + 0) + +#define MAN_FW_DESC_OFFSET_V1_8 \ + (MAN_META_EXT_OFFSET_V1_8 + \ + sizeof(struct sof_man_adsp_meta_file_ext_v1_8) + \ + MAN_EXT_PADDING) + +#define MAN_DESC_PADDING_SIZE_V1_8 \ + (MAN_DESC_OFFSET_V1_8 - MAN_FW_DESC_OFFSET_V1_8) + +#define MAN_SIG_PKG_OFFSET_V1_5 \ + (MAN_CSS_HDR_OFFSET + \ + sizeof(struct css_header_v1_5)) + +#define MAN_META_EXT_OFFSET_V1_5 \ + (MAN_SIG_PKG_OFFSET_V1_5 + \ + sizeof(struct signed_pkg_info_ext) + \ + sizeof(struct partition_info_ext) + \ + MAN_CSE_PADDING_SIZE) + +#define MAN_FW_DESC_OFFSET_V1_5 \ + (MAN_META_EXT_OFFSET_V1_5 + \ + sizeof(struct sof_man_adsp_meta_file_ext_v1_8) + \ + MAN_EXT_PADDING) + +/* + * Firmware manifest header ACE V1_5 used on MTL onwards + */ +struct fw_image_manifest_ace_v1_5 { + /* MEU tool needs these sections to be 0s */ + struct CsePartitionDirHeader_v2_5 cse_partition_dir_header; + struct CsePartitionDirEntry cse_partition_dir_entry[MAN_CSE_PARTS]; + struct css_header_v2_5 css; + struct signed_pkg_info_ext_ace_v1_5 signed_pkg; + struct info_ext_0x16 info_0x16; + + struct sof_man_adsp_meta_file_ext_v2_5 adsp_file_ext; + + /* reserved / pading at end of ext data - all 0s*/ + uint8_t reserved[MAN_EXT_PADDING]; + + /* start of the unsigned binary for MEU input must start at MAN_DESC_OFFSET */ + uint8_t padding[MAN_DESC_PADDING_SIZE_ACE_V1_5]; + + struct sof_man_fw_desc desc; /* at offset MAN_DESC_OFFSET */ +} __attribute__((packed)); + +/* + * Firmware manifest header V2.5 used on TGL onwards + */ +struct fw_image_manifest_v2_5 { + /* MEU tool needs these sections to be 0s */ + struct CsePartitionDirHeader_v2_5 cse_partition_dir_header; + struct CsePartitionDirEntry cse_partition_dir_entry[MAN_CSE_PARTS]; + struct css_header_v2_5 css; + struct signed_pkg_info_ext_v2_5 signed_pkg; + struct info_ext_0x16 info_0x16; + + struct sof_man_adsp_meta_file_ext_v2_5 adsp_file_ext; + + /* reserved / pading at end of ext data - all 0s*/ + uint8_t reserved[MAN_EXT_PADDING]; + + /* start of the unsigned binary for MEU input must start at MAN_DESC_OFFSET */ + uint8_t padding[MAN_DESC_PADDING_SIZE_V2_5]; + + struct sof_man_fw_desc desc; /* at offset MAN_DESC_OFFSET */ +} __attribute__((packed)); + +/* + * Firmware manifest header V1.8 used on APL onwards + */ +struct fw_image_manifest_v1_8 { + /* MEU tool needs these sections to be 0s */ + struct CsePartitionDirHeader cse_partition_dir_header; + struct CsePartitionDirEntry cse_partition_dir_entry[MAN_CSE_PARTS]; + struct css_header_v1_8 css; + struct signed_pkg_info_ext signed_pkg; + struct partition_info_ext partition_info; + uint8_t cse_padding[MAN_CSE_PADDING_SIZE]; + struct sof_man_adsp_meta_file_ext_v1_8 adsp_file_ext; + + /* reserved / pading at end of ext data - all 0s*/ + uint8_t reserved[MAN_EXT_PADDING]; + + /* start of the unsigned binary for MEU input must start at MAN_DESC_OFFSET */ + uint8_t padding[MAN_DESC_PADDING_SIZE_V1_8]; + + struct sof_man_fw_desc desc; /* at offset MAN_DESC_OFFSET */ +} __attribute__((packed)); + +/* + * Firmware manifest header V1.5 used on SKL and KBL + */ +struct fw_image_manifest_v1_5 { + struct css_header_v1_5 css_header; + struct sof_man_fw_desc desc; +} __attribute__((packed)); + +struct fw_image_manifest_v1_5_sue { + struct sof_man_fw_desc desc; +} __attribute__((packed)); + +struct image; +int simple_write_firmware(struct image *image); +int man_write_fw_v1_5(struct image *image); +int man_write_fw_v1_5_sue(struct image *image); +int man_write_fw_v1_8(struct image *image); +int man_write_fw_v2_5(struct image *image); +int man_write_fw_ace_v1_5(struct image *image); +int man_write_fw_meu_v1_5(struct image *image); +int man_write_fw_meu_v1_8(struct image *image); +int man_write_fw_meu_v2_5(struct image *image); + +#endif diff --git a/tools/rimage/src/include/rimage/misc_utils.h b/tools/rimage/src/include/rimage/misc_utils.h new file mode 100644 index 000000000000..c5bfc91c863a --- /dev/null +++ b/tools/rimage/src/include/rimage/misc_utils.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __MISC_UTILS_H__ +#define __MISC_UTILS_H__ + +#include <stdint.h> + +#define DIV_ROUND_UP(val, div) (((val) + (div) - 1) / (div)) +#define ALIGN_UP(val, align) (((val) + (align) - 1) & ~((align) - 1)) + +/** + * Reverses the order of bytes in the array + * @param ptr pointer to a array + * @param size of the array + */ +void bytes_swap(uint8_t *ptr, uint32_t size); + +struct name_val { + const char *name; + unsigned long value; +}; + +#define NAME_VAL_ENTRY(x) { .name = #x, .value = x } +#define NAME_VAL_END { .name = 0, .value = 0 } + +void print_enum(unsigned long value, const struct name_val *values); +void print_flags(unsigned long value, const struct name_val *flags); + +#endif /* __MISC_UTILS_H__ */ diff --git a/tools/rimage/src/include/rimage/module.h b/tools/rimage/src/include/rimage/module.h new file mode 100644 index 000000000000..bd4b93608078 --- /dev/null +++ b/tools/rimage/src/include/rimage/module.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#ifndef __MODULE_H__ +#define __MODULE_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> + +#include <rimage/elf_file.h> + +enum module_section_type { + MST_UNKNOWN, MST_DATA, MST_TEXT, MST_BSS, MST_NOTE +}; + +struct module_section { + const struct elf_section_header *header; + enum module_section_type type; + + /* The contents of the section lie in the rom memory space */ + bool rom; + /* The section is detached from the main part of the module */ + bool detached; + + /* ADSP devices have their RAM regions mapped twice. The first mapping is set in the CPU + * to bypass the L1 cache, and so access through pointers in that region is coherent between + * CPUs (but slow). The second region accesses the same memory through the L1 cache and + * requires careful flushing when used with shared data. + * + * This distinction is exposed in the linker script, where some symbols (e.g. stack regions) + * are linked into cached memory, but others (general kernel memory) are not. + * + * Addresses of sections belonging to a rom memory are not converted. */ + + /* section virtual address, converted to cached address space */ + uint32_t address; + + /* section physical load address, converted to cached address space */ + uint32_t load_address; + + size_t size; + + /* next section of this type */ + struct module_section *next_section; +}; + +struct module_sections_info { + /* start address */ + uint32_t start; + + /* end address */ + uint32_t end; + + /* size without any gaps */ + size_t size; + + /* size include gap to nearest page */ + size_t file_size; + + /* sections count */ + unsigned int count; + + /* sections list */ + struct module_section *first_section; + struct module_section *last_section; +}; + +/* + * ELF module data + */ +struct module { + struct elf_file elf; + + unsigned short first_module_idx; + unsigned short n_modules; + + /* Array of valid sections */ + struct module_section *sections; + + /* Number of valid sections */ + unsigned int num_sections; + + struct module_sections_info text; + struct module_sections_info data; + struct module_sections_info bss; +}; + +struct image; +struct memory_alias; +struct memory_config; + +/** + * Convert uncached memory address to cached + * + * @param alias alias memory configration + * @param address address to be converted + * @return cached address + */ +unsigned long uncache_to_cache(const struct memory_alias *alias, unsigned long address); + + +/** + * Load module file + * + * @param module module structure + * @param filename module file name + * @param verbose verbose logging selection + * @return error code + */ +int module_open(struct module *module, const char *filename, const bool verbose); + +/** + * Unloads module + * + * @param module module structure + */ +void module_close(struct module *module); + +/** + * Parse module sections + * + * @param module module structure + * @param mem_cfg memory configration structure + * @param verbose verbose logging selection + * @param ignore_detached do not mark detached sections + * @return error code + */ +void module_parse_sections(struct module *module, const struct memory_config *mem_cfg, + bool verbose, bool ignore_detached); + +/** + * Read module section to memory buffer + * + * @param [in]module module structure + * @param [in]section module section structure + * @param [out]buffer destination buffer + * @param [in]size destination buffer size + * @return error code + */ +int module_read_section(const struct module *module, const struct module_section *section, + void *buffer, const size_t size); + +/** + * Read module section and write it to a file + * + * @param module module structure + * @param section module section structure + * @param padding count of padding bytes to write after section content + * @param out_file destination file handle + * @param filename output file name used to print error message + * @return error code + */ +int module_write_section(const struct module *module, const struct module_section *section, + const int padding, FILE *out_file, const char *filename); + +/** + * Read whole module elf file to a memory buffer + * + * @param [in]module module structure + * @param [out]buffer destination buffer + * @param [in]size destination buffer size + * @return error code + */ +int module_read_whole_elf(const struct module *module, void *buffer, size_t size); + +/** + * Read whore module elf file and write it to a file + * + * @param module module structure + * @param out_file destination file handle + * @param filename output file name used to print error message + * @return error code + */ +int module_write_whole_elf(const struct module *module, FILE *out_file, const char *filename); + +/** + * Displays information about the occupancy of each memory zone + * + * @param module module structure + */ +void module_print_zones(const struct module *module); + +/** + * Checks all modules to make sure their sections do not overlap with each other + * + * @param module module structure + * @param image program global structure + * @return error code + */ +int modules_validate(const struct image *image); + +#endif /* __MODULE_H__ */ diff --git a/tools/rimage/src/include/rimage/plat_auth.h b/tools/rimage/src/include/rimage/plat_auth.h new file mode 100644 index 000000000000..64cdcd98db5f --- /dev/null +++ b/tools/rimage/src/include/rimage/plat_auth.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + */ + +#ifndef __PLAT_AUTH_H__ +#define __PLAT_AUTH_H__ + +#include <stdint.h> + +struct image; + +#define PLAT_AUTH_SHA256_LEN 32 +#define PLAT_AUTH_SHA384_LEN 48 +#define PLAT_AUTH_NAME_LEN 12 +#define PLAT_AUTH_PADDING 48 /* pad at end of struct */ + +#define SIGN_PKG_EXT_TYPE 15 +#define SIGN_PKG_NUM_MODULE 1 + +#define SIGN_PKG_EXT_TYPE_ACE_V1_5 0x23 + +struct signed_pkg_info_module { + uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */ + uint8_t type; + uint8_t hash_algo; + uint16_t hash_size; + uint32_t meta_size; + uint8_t hash[PLAT_AUTH_SHA256_LEN]; +} __attribute__((packed)); + +struct signed_pkg_info_module_v2_5 { + uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */ + uint8_t type; + uint8_t hash_algo; + uint16_t hash_size; + uint32_t meta_size; + uint8_t hash[PLAT_AUTH_SHA384_LEN]; +} __attribute__((packed)); + +struct signed_pkg_info_ext { + uint32_t ext_type; + uint32_t ext_len; + + uint8_t name[4]; + uint32_t vcn; + uint8_t bitmap[16]; + uint32_t svn; + uint8_t fw_type; + uint8_t fw_sub_type; + uint8_t reserved[14]; /* must be 0 */ + + /* variable length of modules */ + struct signed_pkg_info_module module[SIGN_PKG_NUM_MODULE]; +} __attribute__((packed)); + +struct signed_pkg_info_ext_v2_5 { + uint32_t ext_type; + uint32_t ext_len; + + uint8_t name[4]; + uint32_t vcn; /* 0 */ + uint8_t bitmap[16]; + uint32_t svn; + uint8_t fw_type; + uint8_t fw_sub_type; + uint8_t reserved[14]; /* must be 0 */ + + /* variable length of modules */ + struct signed_pkg_info_module_v2_5 module[SIGN_PKG_NUM_MODULE]; +} __attribute__((packed)); + +struct signed_pkg_info_module_ace_v1_5 { + uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */ + uint8_t type; + uint8_t hash_algo; + uint8_t reserved[2]; + uint32_t meta_size; + uint8_t hash[PLAT_AUTH_SHA384_LEN]; +} __attribute__((packed)); + +struct signed_pkg_info_ext_ace_v1_5 { + uint32_t ext_type; + uint32_t ext_len; + + uint8_t name[4]; + uint32_t vcn; /* 0 */ + uint32_t svn; + uint8_t partition_usage; + uint8_t reserved0; + uint8_t fw_type; + uint8_t fw_sub_type; + uint8_t number_of_modules; + uint8_t boot_strap_svn; + uint8_t reserved[14]; /* must be 0 */ + + /* variable length of modules */ + struct signed_pkg_info_module_ace_v1_5 module[SIGN_PKG_NUM_MODULE]; +} __attribute__((packed)); + +#define PART_INFO_EXT_TYPE 3 +#define PART_INFO_NUM_MODULE 1 + +struct partition_info_module { + uint8_t name[PLAT_AUTH_NAME_LEN]; /* must be padded with 0 */ + uint8_t type; + uint8_t reserved[3]; + uint32_t meta_size; + uint8_t hash[PLAT_AUTH_SHA256_LEN]; +} __attribute__((packed)); + +struct partition_info_ext { + uint32_t ext_type; + uint32_t ext_len; + + uint8_t name[4]; /* "ADSP" */ + uint32_t length; + uint8_t hash[PLAT_AUTH_SHA256_LEN]; + + uint32_t vcn; + uint32_t part_version; + uint32_t fmt_version; + uint32_t instance_id; + uint32_t part_flags; + uint8_t reserved[20]; /* must be 0 */ + + /* variable length of modules */ + struct partition_info_module module[PART_INFO_NUM_MODULE]; +} __attribute__((packed)); + +/* offset 0x458 id */ +struct info_ext_0x16 { + uint32_t ext_type; /* 0x16 */ + uint32_t ext_len; /* 0x68 */ + uint8_t name[4]; /* ADSP */ + uint32_t size; /* file size */ + uint32_t data[5]; /* 0 = 0x10000000, 0, 1, 1, 0x3003 */ + uint8_t hash[PLAT_AUTH_SHA384_LEN]; + uint32_t data1[5]; +} __attribute__((packed)); + + +#define PLAT_AUTH_SIZE \ + (sizeof(struct partition_info_ext) + \ + sizeof(struct signed_pkg_info_ext)) + +void ri_adsp_meta_data_create_v1_8(struct image *image, int meta_start_offset, + int meta_end_offset); +void ri_adsp_meta_data_create_v2_5(struct image *image, int meta_start_offset, + int meta_end_offset); +void ri_plat_ext_data_create(struct image *image); +void ri_plat_ext_data_create_v2_5(struct image *image); +void ri_plat_ext_data_create_ace_v1_5(struct image *image); + +#endif diff --git a/tools/rimage/src/include/rimage/rimage.h b/tools/rimage/src/include/rimage/rimage.h new file mode 100644 index 000000000000..139b55951fdc --- /dev/null +++ b/tools/rimage/src/include/rimage/rimage.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2015-2018 Intel Corporation. All rights reserved. + */ + +#ifndef __RIMAGE_H__ +#define __RIMAGE_H__ + +#include <stdint.h> +#include <stdio.h> + +#include <rimage/manifest.h> +#include <rimage/cavs/cavs_ext_manifest.h> +#include <rimage/sof/kernel/fw.h> + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define MAX_MODULES 32 + +struct adsp; + +/* + * Firmware image context. + */ +struct image { + + const char *out_file; + const char *in_file; + FILE *out_fd; + void *pos; + + struct adsp *adsp; + int abi; + int verbose; + int reloc; /* ELF data is relocatable */ + int num_modules; + struct manifest_module module[MAX_MODULES]; + uint32_t image_end;/* module end, equal to output image size */ + int meu_offset; + const char *verify_file; + + /* private key file name*/ + const char *key_name; + + /* file IO */ + void *fw_image; + void *rom_image; + FILE *out_rom_fd; + FILE *out_man_fd; + FILE *out_ext_man_fd; + FILE *out_unsigned_fd; + char out_rom_file[256]; + char out_man_file[256]; + char out_ext_man_file[256]; + char out_unsigned_file[256]; + + /* fw version and build id */ + char* fw_ver_string; + char* fw_ver_build_string; + uint16_t fw_ver_major; + uint16_t fw_ver_minor; + uint16_t fw_ver_micro; + uint16_t fw_ver_build; + + uint32_t imr_type; + + /* Output image is a loadable module */ + bool loadable_module; + + /* Do not mark detached sections */ + bool ignore_detached; +}; + +struct memory_zone { + uint32_t base; + uint32_t size; + uint32_t host_offset; +}; + +struct memory_alias { + uint32_t mask; + uint32_t cached; + uint32_t uncached; +}; + +struct memory_config { + struct memory_zone zones[SOF_FW_BLK_TYPE_NUM]; + struct memory_alias alias; +}; + +struct fw_image_ext_mod_config { + struct fw_ext_mod_config_header header; + struct mod_scheduling_caps sched_caps; + struct fw_pin_description *pin_desc; +}; + +struct fw_image_ext_module { + uint32_t mod_conf_count; + struct fw_image_ext_mod_config ext_mod_config_array[FW_MAX_EXT_MODULE_NUM]; +}; + +/* + * module manifest information defined in config file + */ +struct fw_image_manifest_module { + struct fw_image_ext_module mod_ext; + uint32_t mod_cfg_count; + struct sof_man_mod_config *mod_cfg; + uint32_t mod_man_count; + struct sof_man_module *mod_man; + unsigned int output_mod_cfg_count; +}; + +/* + * Audio DSP descriptor and operations. + */ +struct adsp { + const char *name; + struct memory_config mem; + + uint32_t image_size; + + int (*write_firmware_ext_man)(struct image *image); + int (*write_firmware)(struct image *image); + int (*write_firmware_meu)(struct image *image); + int (*verify_firmware)(struct image *image); + struct fw_image_manifest_ace_v1_5 *man_ace_v1_5; + struct fw_image_manifest_v2_5 *man_v2_5; + struct fw_image_manifest_v1_8 *man_v1_8; + struct fw_image_manifest_v1_5 *man_v1_5; + struct fw_image_manifest_v1_5_sue *man_v1_5_sue; + struct fw_image_manifest_module *modules; + int exec_boot_ldr; +}; + +int ri_manifest_sign_v1_5(struct image *image); +int ri_manifest_sign_v1_8(struct image *image); +int ri_manifest_sign_v2_5(struct image *image); +int ri_manifest_sign_ace_v1_5(struct image *image); + +int pkcs_v1_5_sign_man_v1_5(struct image *image, + struct fw_image_manifest_v1_5 *man, + void *ptr1, unsigned int size1); +int pkcs_v1_5_sign_man_v1_8(struct image *image, + struct fw_image_manifest_v1_8 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); +int pkcs_v1_5_sign_man_v2_5(struct image *image, + struct fw_image_manifest_v2_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); +int pkcs_v1_5_sign_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); + +int verify_image(struct image *image); +int ri_manifest_verify_v1_5(struct image *image); +int ri_manifest_verify_v1_8(struct image *image); +int ri_manifest_verify_v2_5(struct image *image); +int pkcs_v1_5_verify_man_v1_5(struct image *image, + struct fw_image_manifest_v1_5 *man, + void *ptr1, unsigned int size1); +int pkcs_v1_5_verify_man_v1_8(struct image *image, + struct fw_image_manifest_v1_8 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); +int pkcs_v1_5_verify_man_v2_5(struct image *image, + struct fw_image_manifest_v2_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); +int pkcs_v1_5_verify_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); + +int resign_image(struct image *image); +int get_key_size(struct image *image); + +#endif diff --git a/tools/rimage/src/include/rimage/sof/kernel/ext_manifest.h b/tools/rimage/src/include/rimage/sof/kernel/ext_manifest.h new file mode 100644 index 000000000000..7d9b77735a11 --- /dev/null +++ b/tools/rimage/src/include/rimage/sof/kernel/ext_manifest.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + * + * To add new content to ext_man, in firmware code define struct which starts + * with ext_man_elem_head followed by usage dependent content and place whole + * struct in "fw_metadata" section. Moreover kernel code should be modified to + * properly read new packet. + * + * Extended manifest is designed to be extensible. In header there is a field + * which describe header length, so after appending some data to header then it + * can be easily skipped by device with older version of this header. + * Unknown ext_man elements should be just skipped by host, + * to be backward compatible. Field `ext_man_elem_header.elem_size` should be + * used in such a situation. + */ + +#ifndef __RIMAGE_KERNEL_EXT_MANIFEST_H__ +#define __RIMAGE_KERNEL_EXT_MANIFEST_H__ + +#include <stdint.h> + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +/* In ASCII `XMan` */ +#define EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ( \ + ((uint32_t)(MAJOR) << 24) | \ + ((uint32_t)(MINOR) << 12) | \ + (uint32_t)(PATH)) + +/* check extended manifest version consistency */ +#define EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define EXT_MAN_VERSION EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* struct size alignment for ext_man elements */ +#define EXT_MAN_ALIGN 16 + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct ext_man_header { + uint32_t magic; /**< identification number, */ + /**< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /**< [bytes] full size of ext_man, */ + /**< (header + content + padding) */ + uint32_t header_size; /**< [bytes] makes header extensionable, */ + /**< after append new field to ext_man header */ + /**< then backward compatible won't be lost */ + uint32_t header_version; /**< value of EXT_MAN_VERSION */ + /**< not related with following content */ + + /* just after this header should be list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* extended manifest element header */ +struct ext_man_elem_header { + uint32_t type; /**< EXT_MAN_ELEM_* */ + uint32_t elem_size; /**< in bytes, including header size */ + + /* just after this header should be type dependent content */ +} __packed; + +#endif /* __RIMAGE_KERNEL_EXT_MANIFEST_H__ */ diff --git a/src/include/kernel/fw.h b/tools/rimage/src/include/rimage/sof/kernel/fw.h similarity index 93% rename from src/include/kernel/fw.h rename to tools/rimage/src/include/rimage/sof/kernel/fw.h index 2c0a123d23b7..14c8ca0c1585 100644 --- a/src/include/kernel/fw.h +++ b/tools/rimage/src/include/rimage/sof/kernel/fw.h @@ -10,8 +10,8 @@ * Firmware file format . */ -#ifndef __KERNEL_FW_H__ -#define __KERNEL_FW_H__ +#ifndef __RIMAGE_KERNEL_FW_H__ +#define __RIMAGE_KERNEL_FW_H__ #include <stdint.h> @@ -33,8 +33,8 @@ enum snd_sof_fw_blk_type { SOF_FW_BLK_TYPE_SRAM = 3, /* system RAM */ SOF_FW_BLK_TYPE_ROM = 4, SOF_FW_BLK_TYPE_IMR = 5, - SOF_FW_BLK_TYPE_RSRVD6 = 6, - SOF_FW_BLK_TYPE_RSRVD7 = 7, + SOF_FW_BLK_TYPE_HPSRAM = 6, + SOF_FW_BLK_TYPE_LPSRAM = 7, SOF_FW_BLK_TYPE_RSRVD8 = 8, SOF_FW_BLK_TYPE_RSRVD9 = 9, SOF_FW_BLK_TYPE_RSRVD10 = 10, @@ -77,4 +77,4 @@ struct snd_sof_fw_header { uint32_t abi; /* version of header format */ } __attribute__((packed)); -#endif /* __KERNEL_FW_H__ */ +#endif /* __RIMAGE_KERNEL_FW_H__ */ diff --git a/tools/rimage/src/include/rimage/sof/user/manifest.h b/tools/rimage/src/include/rimage/sof/user/manifest.h new file mode 100644 index 000000000000..3f20d89ff495 --- /dev/null +++ b/tools/rimage/src/include/rimage/sof/user/manifest.h @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +/** + * \file include/user/manifest.h + * \brief FW Image Manifest definitions. + * \author Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __RIMAGE_USER_MANIFEST_H__ +#define __RIMAGE_USER_MANIFEST_H__ + +#include <stdint.h> + +/* start offset for base FW module */ +#define SOF_MAN_ELF_TEXT_OFFSET 0x2000 + +/* FW Extended Manifest Header id = $AE1 */ +#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124 + +/* module type load type */ +#define SOF_MAN_MOD_TYPE_BUILTIN 0 +#define SOF_MAN_MOD_TYPE_MODULE 1 +#define SOF_MAN_MOD_TYPE_LLEXT 2 /* Zephyr LLEXT-style dynamically linked */ +#define SOF_MAN_MOD_TYPE_LLEXT_AUX 3 /* Zephyr LLEXT-style dynamically linked auxiliary */ + +/* module init config */ +#define SOF_MAN_MOD_INIT_CONFIG_BASE_CFG 0 /* Base config only */ +#define SOF_MAN_MOD_INIT_CONFIG_BASE_CFG_WITH_EXT 1 /* Base config with extension */ + +#define MAN_MAX_SIZE_V1_8 (38 * 1024) + + +struct sof_man_module_type { + uint32_t load_type:4; /* SOF_MAN_MOD_TYPE_ */ + uint32_t auto_start:1; + uint32_t domain_ll:1; + uint32_t domain_dp:1; + uint32_t lib_code:1; + uint32_t init_config:4; /* SOF_MAN_MOD_INIT_CONFIG_ */ + /* The init_config field overlaps with the following fields, so core_type was trimmed to + * ensure proper placement of remaining fields. + * uint32_t domain_rtos:1; + * uint32_t core_type:8; + */ + uint32_t core_type:5; + uint32_t user_mode:1; + uint32_t large_param:1; + uint32_t stack_on_bss:1; + uint32_t rsvd_:12; +}; + +/* segment flags.type */ +#define SOF_MAN_SEGMENT_TEXT 0 +#define SOF_MAN_SEGMENT_RODATA 1 +#define SOF_MAN_SEGMENT_DATA 1 +#define SOF_MAN_SEGMENT_BSS 2 +#define SOF_MAN_SEGMENT_EMPTY 15 + +union sof_man_segment_flags { + uint32_t ul; + struct { + uint32_t contents:1; + uint32_t alloc:1; + uint32_t load:1; + uint32_t readonly:1; + uint32_t code:1; + uint32_t data:1; + uint32_t _rsvd0:2; + uint32_t type:4; /* MAN_SEGMENT_ */ + uint32_t _rsvd1:4; + uint32_t length:16; /* of segment in pages */ + } r; +} __attribute__((packed)); + +/* + * Module segment descriptor. Used by ROM - Immutable. + */ +struct sof_man_segment_desc { + union sof_man_segment_flags flags; + uint32_t v_base_addr; + uint32_t file_offset; +} __attribute__((packed)); + +/* + * The firmware binary can be split into several modules. + */ + +#define SOF_MAN_MOD_ID_LEN 4 +#define SOF_MAN_MOD_NAME_LEN 8 +#define SOF_MAN_MOD_SHA256_LEN 32 +#define SOF_MAN_MOD_SHA384_LEN 48 +#define SOF_MAN_MOD_ID {'$', 'A', 'M', 'E'} + +struct sof_man_uuid { + uint32_t a; + uint16_t b; + uint16_t c; + uint8_t d[8]; +}; + +struct sof_man_runtime_info { + uint16_t module_id; + uint16_t state_flags; +}; + +/* + * Each module has an entry in the FW header. Used by ROM - Immutable. + */ +struct sof_man_module { + union { + uint8_t struct_id[SOF_MAN_MOD_ID_LEN]; /* SOF_MAN_MOD_ID */ + struct sof_man_runtime_info runtime_info; + }; + uint8_t name[SOF_MAN_MOD_NAME_LEN]; + struct sof_man_uuid uuid; + struct sof_man_module_type type; + uint8_t hash[SOF_MAN_MOD_SHA256_LEN]; + uint32_t entry_point; + uint16_t cfg_offset; + uint16_t cfg_count; + uint32_t affinity_mask; + uint16_t instance_max_count; /* max number of instances */ + uint16_t instance_bss_size; /* instance (pages) */ + struct sof_man_segment_desc segment[3]; +} __attribute__((packed)); + +/* + * Each module has a configuration in the FW header. Used by ROM - Immutable. + */ +struct sof_man_mod_config { + uint32_t par[4]; /* module parameters */ + uint32_t is_pages; /* actual size of instance .bss (pages) */ + uint32_t cps; /* cycles per second */ + uint32_t ibs; /* input buffer size (bytes) */ + uint32_t obs; /* output buffer size (bytes) */ + uint32_t module_flags; /* flags, reserved for future use */ + uint32_t cpc; /* cycles per single run */ + uint32_t obls; /* output block size, reserved for future use */ +} __attribute__((packed)); + +/* + * FW Manifest Header + */ + +union sof_man_fw_header_image_flags { + uint32_t raw; + struct { + uint32_t tp : 1; + uint32_t image_type : 2; + uint32_t relocatable_lib : 1; + uint32_t _rsvd0 : 28; + } fields; +}; + +#define SOF_MAN_FW_HDR_IMG_TYPE_ROM_EXT 0 +#define SOF_MAN_FW_HDR_IMG_TYPE_MAIN_FW 1 +#define SOF_MAN_FW_HDR_IMG_TYPE_LIB 2 + +#define SOF_MAN_FW_HDR_FW_NAME_LEN 8 +#define SOF_MAN_FW_HDR_ID {'$', 'A', 'M', '1'} +#define SOF_MAN_FW_HDR_NAME "ADSPFW" +#define SOF_MAN_FW_HDR_FLAGS 0x0 +#define SOF_MAN_FW_HDR_FEATURES 0xffff + +/* + * The firmware has a standard header that is checked by the ROM on firmware + * loading. preload_page_count is used by DMA code loader and is entire + * image size on CNL. i.e. CNL: total size of the binary’s .text and .rodata + * Used by ROM - Immutable. + */ +struct sof_man_fw_header { + uint8_t header_id[4]; + uint32_t header_len; + uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN]; + /* number of pages of preloaded image loaded by driver */ + uint32_t preload_page_count; + union sof_man_fw_header_image_flags fw_image_flags; + uint32_t feature_mask; + uint16_t major_version; + uint16_t minor_version; + uint16_t hotfix_version; + uint16_t build_version; + uint32_t num_module_entries; + uint32_t fw_compat; + uint32_t hw_buf_length; + /* target address for binary loading as offset in IMR - must be == base offset */ + uint32_t load_offset; +} __attribute__((packed)); + +/* + * Firmware manifest descriptor. This can contain N modules and N module + * configs. Used by ROM - Immutable. + */ +struct sof_man_fw_desc { + struct sof_man_fw_header header; + + /* Warning - hack for module arrays. For some unknown reason the we + * have a variable size array of struct man_module followed by a + * variable size array of struct mod_config. These should have been + * merged into a variable array of a parent structure. We have to hack + * around this in many places.... + * + * struct sof_man_module man_module[]; + * struct sof_man_mod_config mod_config[]; + */ + +} __attribute__((packed)); + +#define SOF_MAN_COMP_SHA256_LEN 32 +#define SOF_MAN_COMP_SHA384_LEN 48 + +/* + * Component Descriptor for manifest v1.8. Used by ROM - Immutable. + */ +struct sof_man_component_desc_v1_8 { + uint32_t reserved[2]; /* all 0 */ + uint32_t version; + uint8_t hash[SOF_MAN_COMP_SHA256_LEN]; + uint32_t base_offset; + uint32_t limit_offset; + uint32_t attributes[4]; +} __attribute__((packed)); + +/* + * Audio DSP extended metadata for manifest v1.8. Used by ROM - Immutable. + */ +struct sof_man_adsp_meta_file_ext_v1_8 { + uint32_t ext_type; /* always 17 for ADSP extension */ + uint32_t ext_len; + uint32_t imr_type; + uint8_t reserved[16]; /* all 0 */ + struct sof_man_component_desc_v1_8 comp_desc[1]; +} __attribute__((packed)); + +/* + * Component Descriptor for manifest v2.5. Used by ROM - Immutable. + */ +struct sof_man_component_desc_v2_5 { + uint32_t reserved[2]; /* all 0 */ + uint32_t version; + uint8_t hash[SOF_MAN_COMP_SHA384_LEN]; + uint32_t base_offset; + uint32_t limit_offset; + uint32_t attributes[4]; +} __attribute__((packed)); + +/* + * Audio DSP extended metadata for manifest v2.5. Used by ROM - Immutable. + */ +struct sof_man_adsp_meta_file_ext_v2_5 { + uint32_t ext_type; /* always 17 for ADSP extension */ + uint32_t ext_len; + uint32_t imr_type; + uint8_t reserved[16]; /* all 0 */ + struct sof_man_component_desc_v2_5 comp_desc[1]; +} __attribute__((packed)); + +/* + * Module Manifest for rimage module metadata. Not used by ROM. + */ +struct sof_man_module_manifest { + struct sof_man_module module; + uint32_t text_size; +}; + +/* + * Module offset in manifest. + */ +#define SOF_MAN_MODULE_OFFSET(index) \ + (sizeof(struct sof_man_fw_header) + \ + (index) * sizeof(struct sof_man_module)) + +/* + * LLEXT module link area for detached sections. When an LLEXT module contains + * detached sections, they will be linked with addresses in this range. The + * upper limit has no special meaning, simply assuming that 128MiB should be + * enough and that SRAM will not use these addresses. + */ +#define SOF_MODULE_DRAM_LINK_START 0 +#define SOF_MODULE_DRAM_LINK_END 0x08000000 + +#endif /* __RIMAGE_USER_MANIFEST_H__ */ diff --git a/tools/rimage/src/include/rimage/toml_utils.h b/tools/rimage/src/include/rimage/toml_utils.h new file mode 100644 index 000000000000..8bbbdaca17fa --- /dev/null +++ b/tools/rimage/src/include/rimage/toml_utils.h @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + * Marc Herbert <marc.herbert@intel.com> + */ + +#ifndef __TOML_UTILS_H__ +#define __TOML_UTILS_H__ + +#include "toml.h" + +#include <stdint.h> +#include <stdio.h> +#include <stdarg.h> + +/** parser counter, used to assert nothing left unparsed in toml data */ +struct parse_ctx { + int key_cnt; /**< number of parsed key */ + int table_cnt; /**< number of parsed tables */ + int array_cnt; /**< number of parsed arrays */ +}; + +/* macros used to dump values after parsing */ +#define DUMP_KEY_FMT " %20s: " +#define DUMP(fmt, ...) fprintf(stdout, fmt "\n", ##__VA_ARGS__) +#define DUMP_KEY(key, fmt, ...) DUMP(DUMP_KEY_FMT fmt, key, ##__VA_ARGS__) + +void print_bytes(FILE *out, const uint8_t *arr, size_t len); + +#define DUMP_PRINTABLE_BYTES(name, var) _dump_printable_bytes(name, var, sizeof(var)) + +void _dump_printable_bytes(const char *name, const uint8_t *arr, size_t len); + +/** private parser error trace function */ +void vlog_err(const char *msg, va_list vl); + +/** parser error trace function, error code is returned to shorten client code */ +int log_err(int err_code, const char *msg, ...); + +/** log malloc error message for given key */ +int err_malloc(const char *key); + +/** log key not found error */ +int err_key_not_found(const char *key); + +/** error during parsing key value, possible detailed message */ +int err_key_parse(const char *key, const char *extra_msg, ...); + +/** initialize parser context before parsing */ +void parse_ctx_init(struct parse_ctx *ctx); + +/** check nothing left unparsed in given parsing context */ +int assert_everything_parsed(const toml_table_t *table, struct parse_ctx *ctx); + +/** + * Parse hex value from key in given toml table + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT32_MAX value for error cases + */ +uint32_t parse_uint32_hex_key(const toml_table_t *table, struct parse_ctx *ctx, + const char *key, int64_t def, int *error); +uint16_t parse_uint16_hex_key(const toml_table_t *table, struct parse_ctx *ctx, + const char *key, int64_t def, int *error); +uint8_t parse_uint8_hex_key(const toml_table_t *table, struct parse_ctx *ctx, + const char *key, int64_t def, int *error); + +/** + * Parse integer value from key in given toml table + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT32_MAX value for error cases + */ +uint32_t parse_uint32_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + int64_t def, int *error); +uint8_t parse_uint8_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + int64_t def, int *error); + +/** + * Parse string value from key in given toml table to uint8_t array. The + * destination is NOT a string because it is padded with zeros if and + * only if there is some capacity left. For string destinations use + * parse_str_key(). + * + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param dst uint8_t[] destination + * @param capacity dst array size + * @param error code, 0 when success + */ +void parse_printable_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + uint8_t *dst, int capacity, int *error); + +/** + * Parse string value from key in given toml table to given + * char[]. Destination is padded with zeros. As the only difference with + * parse_printable_key(), dst is guaranteed to be null-terminated when + * there is no error because the last destination byte is reserved for + * that. + * + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param dst char[] destination + * @param capacity dst array size including null termination. + * @param error code, 0 when success + */ +void parse_str_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + char *dst, int capacity, int *error); + +/** + * Parse UUID hex string into a byte array. The endianness of the output + * is architecture-dependent: do not use in any portable code. + */ +void parse_uuid(const char *buf, void *uuid); + +/** version is stored as toml array with integer number, something like: + * "version = [1, 8]" + */ +int parse_version(toml_table_t *toml, int64_t version[2]); + +#endif /* __TOML_UTILS_H__ */ diff --git a/tools/rimage/src/manifest.c b/tools/rimage/src/manifest.c new file mode 100644 index 000000000000..6f3a161e37a7 --- /dev/null +++ b/tools/rimage/src/manifest.c @@ -0,0 +1,1788 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> + +#include <rimage/sof/user/manifest.h> + +#include <rimage/rimage.h> +#include <rimage/css.h> +#include <rimage/cse.h> +#include <rimage/plat_auth.h> +#include <rimage/manifest.h> +#include <rimage/file_utils.h> +#include <rimage/misc_utils.h> +#include <rimage/hash.h> + +static int man_open_rom_file(struct image *image) +{ + uint32_t size; + int ret; + + ret = create_file_name(image->out_rom_file, sizeof(image->out_rom_file), image->out_file, + "rom"); + if (ret) + return ret; + + size = image->adsp->mem.zones[SOF_FW_BLK_TYPE_ROM].size; + + /* allocate ROM image */ + image->rom_image = calloc(size, 1); + if (!image->rom_image) + return -ENOMEM; + + /* open ROM outfile for writing */ + image->out_rom_fd = fopen(image->out_rom_file, "wb"); + if (!image->out_rom_fd) + return file_error("unable to open file for writing", image->out_rom_file); + + return 0; +} + +static int man_open_unsigned_file(struct image *image) +{ + int ret; + + ret = create_file_name(image->out_unsigned_file, sizeof(image->out_unsigned_file), + image->out_file, "uns"); + if (ret) + return ret; + + /* open unsigned FW outfile for writing */ + image->out_unsigned_fd = fopen(image->out_unsigned_file, "wb"); + if (!image->out_unsigned_fd) + return file_error("unable to open file for writing", image->out_unsigned_file); + + return 0; +} + +static int man_open_manifest_file(struct image *image) +{ + int ret; + + ret = create_file_name(image->out_man_file, sizeof(image->out_man_file), image->out_file, + "met"); + if (ret) + return ret; + + /* open manifest outfile for writing */ + image->out_man_fd = fopen(image->out_man_file, "wb"); + if (!image->out_man_fd) + return file_error("unable to open file for writing", image->out_man_file); + + return 0; +} + +static int man_init_image_v1_5(struct image *image) +{ + /* allocate image and copy template manifest */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) + return -ENOMEM; + + memcpy(image->fw_image, image->adsp->man_v1_5, + sizeof(struct fw_image_manifest_v1_5)); + + return 0; +} + +static int man_init_image_v1_5_sue(struct image *image) +{ + /* allocate image and copy template manifest */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) + return -ENOMEM; + + /* copy 1.5 sue manifest */ + memcpy(image->fw_image + MAN_DESC_OFFSET_V1_5_SUE, + image->adsp->man_v1_5_sue, + sizeof(struct fw_image_manifest_v1_5_sue)); + + return 0; +} + +static int man_init_image_v1_8(struct image *image) +{ + /* allocate image and copy template manifest */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) + return -ENOMEM; + + memcpy(image->fw_image, image->adsp->man_v1_8, + sizeof(struct fw_image_manifest_v1_8)); + + return 0; +} + +static int man_init_image_v2_5(struct image *image) +{ + /* allocate image and copy template manifest */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) + return -ENOMEM; + + memcpy(image->fw_image, image->adsp->man_v2_5, + sizeof(struct fw_image_manifest_v2_5)); + + return 0; +} + +/* write SRAM sections */ +static int man_copy_sram(struct image *image, const struct manifest_module *module, + const struct sof_man_segment_desc *segment, + const struct module_section *section) +{ + uint32_t offset, end; + int ret; + + assert(section->load_address >= segment->v_base_addr); + offset = segment->file_offset + section->load_address - segment->v_base_addr; + end = offset + section->size; + assert((uint64_t)offset + section->size <= image->adsp->image_size); + + ret = module_read_section(&module->file, section, image->fw_image + offset, + image->adsp->image_size - offset); + if (ret) + return ret; + + /* get module end offset ? */ + if (end > image->image_end) + image->image_end = end; + + fprintf(stdout, "\t0x%x\t0x%zx\t\t0x%x\t%s\t%s\n", section->load_address, section->size, + offset, section->type == MST_TEXT ? "TEXT" : "DATA", section->header->name); + + return 0; +} + +/** + * Write all linked sections + * + * @param image program global structure + * @param module modules manifest description + * @param section module section descriptor + * @return error code on error, 0 on success + */ +static int man_copy_elf_sections(struct image *image, struct manifest_module *module, + const struct sof_man_segment_desc *segment, + const struct module_section *section) +{ + int ret; + + while (section) { + ret = man_copy_sram(image, module, segment, section); + if (ret < 0) { + fprintf(stderr, "error: failed to write section %s\n", + section->header->name); + return ret; + } + + section = section->next_section; + } + + return 0; +} + +static void man_get_section_manifest(struct image *image, + const struct sof_man_module_manifest *sof_mod, + struct sof_man_module *man_module) +{ + struct sof_man_segment_desc *segment; + + /* configure man_module with sofmod data */ + memcpy(man_module->struct_id, "$AME", 4); + man_module->entry_point = sof_mod->module.entry_point; + memcpy(man_module->name, sof_mod->module.name, SOF_MAN_MOD_NAME_LEN); + memcpy(&man_module->uuid, &sof_mod->module.uuid, sizeof(man_module->uuid)); + man_module->affinity_mask = sof_mod->module.affinity_mask; + man_module->instance_max_count = sof_mod->module.instance_max_count; + man_module->type.auto_start = sof_mod->module.type.auto_start; + man_module->type.domain_dp = sof_mod->module.type.domain_dp; + man_module->type.domain_ll = sof_mod->module.type.domain_ll; + man_module->type.load_type = sof_mod->module.type.load_type; + + /* text segment */ + segment = &man_module->segment[SOF_MAN_SEGMENT_TEXT]; + segment->flags.r.contents = 1; + segment->flags.r.alloc = 1; + segment->flags.r.load = 1; + segment->flags.r.readonly = 1; + segment->flags.r.code = 1; + segment->flags.r.type = SOF_MAN_SEGMENT_TEXT; + + /* data segment */ + segment = &man_module->segment[SOF_MAN_SEGMENT_RODATA]; + segment->flags.r.contents = 1; + segment->flags.r.alloc = 1; + segment->flags.r.load = 1; + segment->flags.r.readonly = 0; /* rodata segment contains also writtable data */ + segment->flags.r.data = 1; + segment->flags.r.type = SOF_MAN_SEGMENT_RODATA; + + /* bss segment */ + segment = &man_module->segment[SOF_MAN_SEGMENT_BSS]; + segment->flags.r.alloc = 1; + segment->flags.r.type = SOF_MAN_SEGMENT_BSS; + + fprintf(stdout, " Entry point 0x%8.8x\n", man_module->entry_point); +} + +static int man_get_module_manifest(struct image *image, struct manifest_module *module, + struct sof_man_module *man_module) +{ + struct elf_section section; + const struct sof_man_module_manifest *sof_mod; + int ret; + + fprintf(stdout, "Module Write: %s\n", module->file.elf.filename); + + /* load in module manifest data */ + ret = elf_section_read_by_name(&module->file.elf, ".module", §ion); + if (ret) { + fprintf(stderr, "error: can't read module manifest from '.module' section.\n"); + return ret; + } + + if (sizeof(*sof_mod) > section.header.data.size) { + fprintf(stderr, "error: Invalid module manifest in '.module' section.\n"); + ret = -ENODATA; + goto error; + } + + sof_mod = section.data; + man_get_section_manifest(image, sof_mod, man_module); + + /* read out text_fixup_size from memory mapping */ + module->text_fixup_size = sof_mod->text_size; + +error: + elf_section_free(§ion); + return ret; +} + +static inline const char *segment_name(int i) +{ + switch (i) { + case SOF_MAN_SEGMENT_TEXT: + return "TEXT"; + case SOF_MAN_SEGMENT_RODATA: + return "DATA"; + case SOF_MAN_SEGMENT_BSS: + return "BSS"; + default: + return "NONE"; + } +} + +/* make sure no segments collide */ +static int man_module_validate(struct sof_man_module *man_module) +{ + uint32_t istart, iend; + uint32_t jstart, jend; + int i, j; + + for (i = 0; i < 3; i++) { + istart = man_module->segment[i].v_base_addr; + iend = istart + man_module->segment[i].flags.r.length * + MAN_PAGE_SIZE; + + for (j = 0; j < 3; j++) { + /* don't validate segment against itself */ + if (i == j) + continue; + + jstart = man_module->segment[j].v_base_addr; + jend = jstart + man_module->segment[j].flags.r.length * + MAN_PAGE_SIZE; + + if (jstart > istart && jstart < iend) + goto err; + + if (jend > istart && jend < iend) + goto err; + } + } + + /* success, no overlapping segments */ + return 0; + +err: + fprintf(stderr, "error: segment %s [0x%8.8x:0x%8.8x] overlaps", + segment_name(i), istart, iend); + fprintf(stderr, " with %s [0x%8.8x:0x%8.8x]\n", + segment_name(j), jstart, jend); + return -EINVAL; +} + +static int man_module_create(struct image *image, struct manifest_module *module, + struct sof_man_module *man_module) +{ + /* create module and segments */ + int err; + unsigned int pages; + const struct elf_section_header *bss; + + image->image_end = 0; + + err = man_get_module_manifest(image, module, man_module); + if (err < 0) + return err; + + /* stack size ??? convert sizes to PAGES */ + man_module->instance_bss_size = 1; + + /* max number of instances of this module ?? */ + man_module->instance_max_count = 1; + + module_print_zones(&module->file); + + /* main module */ + fprintf(stdout, "\tAddress\t\tSize\t\tFile\tType\tName\n"); + + /* text section is first */ + man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset = module->foffset; + man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = module->file.text.start; + + /* calculates those padding 0s by the start of next segment */ + /* file_size is already aligned to MAN_PAGE_SIZE */ + pages = module->file.text.file_size / MAN_PAGE_SIZE; + + if (module->text_fixup_size == 0) + module->text_fixup_size = module->file.text.file_size; + + /* check if text_file_size is bigger then text_fixup_size */ + if (module->file.text.file_size > module->text_fixup_size) { + fprintf(stderr, "error: too small text size assigned!\n"); + return -EINVAL; + } + + man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = pages; + + /* Copy text sections content */ + err = man_copy_elf_sections(image, module, &man_module->segment[SOF_MAN_SEGMENT_TEXT], + module->file.text.first_section); + if (err) + return err; + + /* data section */ + + /* file_size is already aligned to MAN_PAGE_SIZE */ + pages = module->file.data.file_size / MAN_PAGE_SIZE; + + man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = pages; + if (pages) { + man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = module->file.data.start; + man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset = module->foffset + + module->text_fixup_size; + /* Copy data sections content */ + err = man_copy_elf_sections(image, module, + &man_module->segment[SOF_MAN_SEGMENT_RODATA], + module->file.data.first_section); + if (err) + return err; + } else { + man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = 0; + man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset = 0; + man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.ul = 0; + man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.type = SOF_MAN_SEGMENT_EMPTY; + } + + /* bss is last */ + + /* I do not understand why only the section named .bss was taken into account. Other + * sections of the same type were ignored (type = SHT_NOBITS, flags = SHF_ALLOC). I added + * the reading of the .bss section here, to not change the behavior of the program. + */ + bss = NULL; + + if (module->is_bootloader) { + /* Bootloader should not have .bss section. */ + fprintf(stdout, "info: ignore .bss section for bootloader module\n"); + } else { + err = elf_section_header_get_by_name(&module->file.elf, ".bss", &bss); + if (err && !image->loadable_module) + fprintf(stderr, "warning: can't find '.bss' section in module %s.\n", + module->file.elf.filename); + + } + + man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0; + man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = 0; + pages = 0; + + if (bss) { + man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = + uncache_to_cache(&image->adsp->mem.alias, bss->data.vaddr); + + pages = DIV_ROUND_UP(bss->data.size, MAN_PAGE_SIZE); + } + + man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = pages; + if (pages == 0) { + man_module->segment[SOF_MAN_SEGMENT_BSS].flags.ul = 0; + man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.type = SOF_MAN_SEGMENT_EMPTY; + } + + if (man_module_validate(man_module) < 0) + return -EINVAL; + + fprintf(stdout, "\n"); + + /* no need to update end for exec headers */ + if (module->exec_header) { + image->image_end = FILE_TEXT_OFFSET_V1_5_SUE; + goto out; + } + + /* round module end upto nearest page */ + image->image_end = ALIGN_UP(image->image_end, MAN_PAGE_SIZE); + +out: + fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n", + man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length, + man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length, + man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length, + image->image_end); + return 0; +} + +static void man_module_fill_reloc(const struct manifest_module *module, + struct sof_man_module *man_module) +{ + /* stack size ??? convert sizes to PAGES */ + man_module->instance_bss_size = 1; + + /* main module */ + /* text section is first */ + man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset = + module->foffset; + man_module->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr = 0; + man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length = 0; + + /* data section */ + man_module->segment[SOF_MAN_SEGMENT_RODATA].v_base_addr = 0; + man_module->segment[SOF_MAN_SEGMENT_RODATA].file_offset = module->foffset; + man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length = module->file.data.file_size / + MAN_PAGE_SIZE; + + /* bss is last */ + man_module->segment[SOF_MAN_SEGMENT_BSS].file_offset = 0; + man_module->segment[SOF_MAN_SEGMENT_BSS].v_base_addr = 0; + man_module->segment[SOF_MAN_SEGMENT_BSS].flags.r.length = 0; +} + +/* Look for a name among module TOML manifests */ +static int man_module_find_cfg(const struct fw_image_manifest_module *modules, + const struct sof_man_module *module) +{ + unsigned int i; + char name[SOF_MAN_MOD_NAME_LEN + 1]; + + strncpy(name, (const char *)module->name, SOF_MAN_MOD_NAME_LEN); + /* Ensure null termination */ + name[SOF_MAN_MOD_NAME_LEN] = '\0'; + + for (i = 0; i < modules->mod_man_count; i++) { + if (!strncmp(name, (const char *)modules->mod_man[i].name, SOF_MAN_MOD_NAME_LEN)) + return i; + } + + fprintf(stderr, "error: Module %s not found in TOML.\n", name); + + return -ENOEXEC; +} + +static int man_module_create_reloc(struct image *image, struct manifest_module *module, + struct sof_man_module **man_module) +{ + /* create module and segments */ + struct fw_image_manifest_module *modules = image->adsp->modules; + const struct sof_man_module_manifest *sof_mod; + struct elf_section section; + int err; + + /* load in module manifest data */ + err = elf_section_read_by_name(&module->file.elf, ".module", §ion); + if (err) { + fprintf(stderr, "error: can't read module manifest from '.module' section.\n"); + return err; + } + + /* + * number of manifests in .module, one module can contain several manifests + * e.g. when a module defines multiple Module Adapter interfaces like + * volume for PEAKVOL and GAIN, mixin_mixout for MIXIN and MIXOUT etc. + */ + unsigned int n_mod = section.header.data.size / sizeof(*sof_mod); + + if (!n_mod || n_mod * sizeof(*sof_mod) != section.header.data.size) { + fprintf(stderr, "error: Invalid module manifests in '.module' section.\n"); + elf_section_free(§ion); + return -ENOEXEC; + } + + unsigned int i; + + for (i = 0, sof_mod = section.data; i < n_mod; i++, sof_mod++) { + if (i) + (*man_module)++; + + if (sof_mod->module.type.load_type != SOF_MAN_MOD_TYPE_LLEXT_AUX) { + int j = man_module_find_cfg(modules, &sof_mod->module); + + if (j < 0) { + elf_section_free(§ion); + return j; + } + + /* Found a TOML manifest, matching ELF: use as a template */ + **man_module = modules->mod_man[j]; + } + /* Use .manifest to update individual fields */ + man_get_section_manifest(image, sof_mod, *man_module); + man_module_fill_reloc(module, *man_module); + } + + module->file.n_modules = n_mod; + modules->output_mod_cfg_count += n_mod; + + elf_section_free(§ion); + + module_print_zones(&module->file); + + image->image_end = module->foffset + module->file.elf.file_size; + + /* round module end up to nearest page */ + image->image_end = ALIGN_UP(image->image_end, MAN_PAGE_SIZE); + + fprintf(stdout, "\tNo\tAddress\t\tSize\t\tFile\tType\n"); + + assert((module->file.elf.file_size + module->foffset) <= image->adsp->image_size); + err = module_read_whole_elf(&module->file, image->fw_image + module->foffset, + image->image_end - module->foffset); + if (err) + return err; + + fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8zx\t0x%x\t%s\n", 0, + 0, module->file.elf.file_size, 0, "DATA"); + + fprintf(stdout, "\n"); + + fprintf(stdout, " Total pages text %d data %d bss %d module file limit: 0x%x\n\n", + (*man_module)->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length, + (*man_module)->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length, + (*man_module)->segment[SOF_MAN_SEGMENT_BSS].flags.r.length, + image->image_end); + return 0; +} + +static int man_write_unsigned_mod(struct image *image, int meta_start_offset, + int meta_end_offset, size_t ext_file_size) +{ + int count; + + /* write metadata file for unsigned FW */ + count = fwrite(image->fw_image + meta_start_offset, + ext_file_size, 1, + image->out_man_fd); + + /* did the metadata/manifest write succeed ? */ + if (count != 1) + return file_error("failed to write meta", image->out_man_file); + + fclose(image->out_man_fd); + + /* now prepare the unsigned rimage */ + count = fwrite(image->fw_image + meta_end_offset, + image->image_end - meta_end_offset, + 1, image->out_unsigned_fd); + + /* did the unsigned FW write succeed ? */ + if (count != 1) + return file_error("failed to write firmware", image->out_unsigned_file); + fclose(image->out_unsigned_fd); + + return 0; +} + +static int man_write_fw_mod(struct image *image) +{ + int count; + + /* write manifest and signed image */ + count = fwrite(image->fw_image, image->image_end, 1, image->out_fd); + + /* did the image write succeed ? */ + if (count != 1) + return file_error("failed to write signed firmware", image->out_file); + + return 0; +} + +static int man_create_modules(struct image *image, struct sof_man_fw_desc *desc, + int file_text_offset) +{ + struct manifest_module *module; + struct sof_man_module *man_module; + int err; + int i = 0, offset = 0; + + /* if first module is executable then write before manifest */ + if (image->adsp->exec_boot_ldr) { + man_module = (void *)desc + SOF_MAN_MODULE_OFFSET(0); + module = &image->module[0]; + + fprintf(stdout, "Module: %s used as executable header\n", + module->file.elf.filename); + module->exec_header = 1; + + /* set module file offset */ + module->foffset = 0; + + err = man_module_create(image, module, man_module); + if (err < 0) + return err; + + /* setup man_modules for missing exec loader module */ + i = 1; + offset = 1; + } + + image->image_end = 0; + unsigned int n_mod = 0; + + for (man_module = (struct sof_man_module *)((uint8_t *)desc + SOF_MAN_MODULE_OFFSET(i - offset)); + i < image->num_modules; + i++, man_module++) { + module = &image->module[i]; + + if (i == 0) + module->foffset = file_text_offset; + else + module->foffset = image->image_end; + + if (image->reloc) { + module->file.first_module_idx = n_mod; + err = man_module_create_reloc(image, module, &man_module); + n_mod += module->file.n_modules; + } else { + /* Some platforms don't have modules configuration in toml file */ + if (image->adsp->modules) { + /* Use manifest created using toml files as template */ + assert(i < image->adsp->modules->mod_man_count); + memcpy(man_module, &image->adsp->modules->mod_man[i], + sizeof(*man_module)); + } + + err = man_module_create(image, module, man_module); + } + + if (err < 0) + return err; + } + + return 0; +} + +/* Copy module "mod_cfg" entries from TOML to manifest */ +static int man_create_modules_in_config(struct image *image, struct sof_man_fw_desc *desc) +{ + struct fw_image_manifest_module *modules; + struct sof_man_module *man_module; + uint8_t *cfg_start; + int i; + + modules = image->adsp->modules; + if (!modules) + return 0; + + if (image->reloc) { + /* Number of struct sof_man_mod_config entries for the current module */ + unsigned int offset = 0; + + cfg_start = (uint8_t *)desc + SOF_MAN_MODULE_OFFSET(modules->output_mod_cfg_count); + + /* + * Modules in the output file don't have to follow in the same order + * as in TOML. Moreover, the TOML configuration is global, it contains + * all the modules, enabled for this platform, whereas when building + * libraries we need to select only configurations for included modules. + * This loop finds and copies each such configuration individually. + */ + for (i = 0, man_module = (struct sof_man_module *)((uint8_t *)desc + + SOF_MAN_MODULE_OFFSET(0)); + i < modules->output_mod_cfg_count; + i++, man_module++) { + if (man_module->type.load_type == SOF_MAN_MOD_TYPE_LLEXT_AUX) + continue; + + int j = man_module_find_cfg(modules, man_module); + + if (j < 0) + return j; + + man_module->cfg_offset = offset; + + /* Copy configuration for the module */ + size_t size = modules->mod_man[j].cfg_count * + sizeof(struct sof_man_mod_config); + + memcpy(cfg_start, modules->mod_cfg + modules->mod_man[j].cfg_offset, size); + + cfg_start += size; + offset += modules->mod_man[j].cfg_count; + } + + /* Update module count */ + desc->header.num_module_entries = modules->output_mod_cfg_count; + } else { + if (image->loadable_module) + i = modules->mod_man_count; + else + /* skip modules passed as parameters. Their manifests have + * already been copied by the man_create_modules function. */ + for (i = image->num_modules; i < modules->mod_man_count; i++) { + man_module = (void *)desc + SOF_MAN_MODULE_OFFSET(i); + memcpy(man_module, &modules->mod_man[i], sizeof(*man_module)); + } + + /* We need to copy the configurations for all modules. */ + cfg_start = (uint8_t *)desc + SOF_MAN_MODULE_OFFSET(i); + memcpy(cfg_start, modules->mod_cfg, + modules->mod_cfg_count * sizeof(struct sof_man_mod_config)); + + /* Update module count */ + desc->header.num_module_entries = modules->mod_man_count; + } + + return 0; +} + +static int man_hash_modules(struct image *image, struct sof_man_fw_desc *desc) +{ + struct sof_man_module *man_module, *man; + struct manifest_module *mod_file; + size_t mod_offset, mod_size; + int i, j, idx, ret = 0; + + /* + * We walk the array of input module files and calculate a hash-sum of each of + * them. Those files might contain multiple modules, so that we then have to + * find all of them and copy the hash-sum into each one. + */ + for (i = 0, mod_file = image->module; + i < image->num_modules; + i++, mod_file++) { + man_module = (struct sof_man_module *) + ((uint8_t *)desc + SOF_MAN_MODULE_OFFSET(mod_file->file.first_module_idx)); + + if (image->adsp->exec_boot_ldr && i == 0) { + fprintf(stdout, " module: no need to hash %s\n as its exec header\n", + man_module->name); + continue; + } + + mod_offset = man_module->segment[SOF_MAN_SEGMENT_TEXT].file_offset; + mod_size = (man_module->segment[SOF_MAN_SEGMENT_TEXT].flags.r.length + + man_module->segment[SOF_MAN_SEGMENT_RODATA].flags.r.length) * + MAN_PAGE_SIZE; + + assert((mod_offset + mod_size) <= image->adsp->image_size); + + ret = hash_sha256(image->fw_image + mod_offset, mod_size, man_module->hash, sizeof(man_module->hash)); + if (ret) + break; + + /* If the input file contained more than 1 module, copy to the rest */ + for (j = 1, idx = mod_file->file.first_module_idx + 1; j < mod_file->file.n_modules; + j++, idx++) { + man = (struct sof_man_module *) + ((uint8_t *)desc + SOF_MAN_MODULE_OFFSET(idx)); + memcpy(man->hash, man_module->hash, sizeof(man->hash)); + } + } + + return ret; +} + +/* used by others */ +int man_write_fw_v1_5(struct image *image) +{ + struct sof_man_fw_desc *desc; + struct fw_image_manifest_v1_5 *m; + int ret; + + /* init image */ + ret = man_init_image_v1_5(image); + if (ret < 0) + goto err; + + /* open ROM image */ + ret = man_open_rom_file(image); + if (ret < 0) + goto err; + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + m = image->fw_image; + desc = image->fw_image + MAN_DESC_OFFSET_V1_5; + + /* firmware and build version */ + m->desc.header.major_version = image->fw_ver_major; + m->desc.header.minor_version = image->fw_ver_minor; + m->desc.header.hotfix_version = image->fw_ver_micro; + m->desc.header.build_version = image->fw_ver_build; + + /* create each module */ + m->desc.header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_5); + if (ret) + goto err; + + fprintf(stdout, "Firmware completing manifest v1.5\n"); + + /* create structures from end of file to start of file */ + ri_css_v1_5_hdr_create(image); + + fprintf(stdout, "Firmware file size 0x%x page count %d\n", + FILE_TEXT_OFFSET_V1_5 - MAN_DESC_OFFSET_V1_5 + image->image_end, + desc->header.preload_page_count); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* sign manifest */ + ret = ri_manifest_sign_v1_5(image); + if (ret < 0) + goto err; + + /* write the firmware */ + ret = man_write_fw_mod(image); + if (ret < 0) + goto err; + + /* write the unsigned files*/ + ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET_V1_5, + MAN_FW_DESC_OFFSET_V1_5, + sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest and signing completed !\n"); + return 0; + +err: + free(image->rom_image); + free(image->fw_image); + unlink(image->out_file); + unlink(image->out_rom_file); + return ret; +} + +/* used by others */ +int man_write_fw_v1_5_sue(struct image *image) +{ + struct fw_image_manifest_v1_5_sue *m; + uint32_t preload_size; + int ret; + + /* init image */ + ret = man_init_image_v1_5_sue(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + m = image->fw_image + MAN_DESC_OFFSET_V1_5_SUE; + + /* firmware and build version */ + m->desc.header.major_version = image->fw_ver_major; + m->desc.header.minor_version = image->fw_ver_minor; + m->desc.header.hotfix_version = image->fw_ver_micro; + m->desc.header.build_version = image->fw_ver_build; + + /* create each module - subtract the boot loader exec header */ + m->desc.header.num_module_entries = image->num_modules - 1; + ret = man_create_modules(image, &m->desc, FILE_TEXT_OFFSET_V1_5_SUE); + if (ret) + goto err; + + fprintf(stdout, "Firmware completing manifest v1.5\n"); + + /* write preload page count */ + preload_size = image->image_end - MAN_DESC_OFFSET_V1_5_SUE; + m->desc.header.preload_page_count = DIV_ROUND_UP(preload_size, MAN_PAGE_SIZE); + + fprintf(stdout, "Firmware file size 0x%x page count %d\n", + FILE_TEXT_OFFSET_V1_5_SUE - MAN_DESC_OFFSET_V1_5_SUE + + image->image_end, m->desc.header.preload_page_count); + + /* calculate hash for each module */ + man_hash_modules(image, &m->desc); + + /* write the firmware */ + ret = man_write_fw_mod(image); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest and signing completed !\n"); + return 0; + +err: + free(image->fw_image); + unlink(image->out_file); + return ret; +} + +/* used by others */ +int man_write_fw_v1_8(struct image *image) +{ + struct sof_man_fw_desc *desc; + struct fw_image_manifest_v1_8 *m; + int ret; + + /* init image */ + ret = man_init_image_v1_8(image); + if (ret < 0) + goto err; + + /* open ROM image */ + ret = man_open_rom_file(image); + if (ret < 0) + goto err; + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + m = image->fw_image; + desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + + /* firmware and build version */ + m->css.version.major_version = image->fw_ver_major; + m->css.version.minor_version = image->fw_ver_minor; + m->css.version.build_version = image->fw_ver_build; + m->desc.header.major_version = image->fw_ver_major; + m->desc.header.minor_version = image->fw_ver_minor; + m->desc.header.hotfix_version = image->fw_ver_micro; + m->desc.header.build_version = image->fw_ver_build; + + /* create each module */ + m->desc.header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); + if (ret) + goto err; + + fprintf(stdout, "Firmware completing manifest v1.8\n"); + + /* create structures from end of file to start of file */ + ri_adsp_meta_data_create_v1_8(image, MAN_META_EXT_OFFSET_V1_8, + MAN_FW_DESC_OFFSET_V1_8); + ri_plat_ext_data_create(image); + ri_css_v1_8_hdr_create(image); + ri_cse_create(image); + + fprintf(stdout, "Firmware file size 0x%x page count %d\n", + FILE_TEXT_OFFSET_V1_8 - MAN_DESC_OFFSET_V1_8 + image->image_end, + desc->header.preload_page_count); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* calculate hash for ADSP meta data extension - 0x480 to end */ + /* image_end is updated every time a section is added */ + assert(image->image_end > MAN_FW_DESC_OFFSET_V1_8); + ret = hash_sha256(image->fw_image + MAN_FW_DESC_OFFSET_V1_8, + image->image_end - MAN_FW_DESC_OFFSET_V1_8, + m->adsp_file_ext.comp_desc[0].hash, + sizeof(m->adsp_file_ext.comp_desc[0].hash)); + if (ret) + goto err; + + /* calculate hash for platform auth data - repeated in hash 2 and 4 */ + assert(image->image_end > (MAN_FW_DESC_OFFSET_V1_8 + + sizeof(struct sof_man_adsp_meta_file_ext_v1_8))); + + ret = hash_sha256(image->fw_image + MAN_FW_DESC_OFFSET_V1_8, + image->image_end - MAN_FW_DESC_OFFSET_V1_8, + m->signed_pkg.module[0].hash, + sizeof(m->signed_pkg.module[0].hash)); + if (ret) + goto err; + + /* hash values in reverse order */ + bytes_swap(m->signed_pkg.module[0].hash, sizeof(m->signed_pkg.module[0].hash)); + + /* Copy module hash to partition_info */ + assert(sizeof(m->partition_info.module[0].hash) == sizeof(m->signed_pkg.module[0].hash)); + memcpy(m->partition_info.module[0].hash, m->signed_pkg.module[0].hash, + sizeof(m->partition_info.module[0].hash)); + + /* sign manifest */ + ret = ri_manifest_sign_v1_8(image); + if (ret < 0) + goto err; + + /* write the firmware */ + ret = man_write_fw_mod(image); + if (ret < 0) + goto err; + + /* write the unsigned files*/ + ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET_V1_8, + MAN_FW_DESC_OFFSET_V1_8, + sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest and signing completed !\n"); + return 0; + +err: + free(image->rom_image); + free(image->fw_image); + unlink(image->out_file); + unlink(image->out_rom_file); + return ret; +} + +/* used to sign with MEU */ +int man_write_fw_meu_v1_5(struct image *image) +{ + const int meta_start_offset = image->meu_offset - + sizeof(struct sof_man_adsp_meta_file_ext_v1_8) - MAN_EXT_PADDING; + struct sof_man_adsp_meta_file_ext_v1_8 *meta; + struct sof_man_fw_desc *desc; + uint32_t preload_size; + int ret; + + /* allocate image */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) { + ret = -ENOMEM; + goto err; + } + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + meta = image->fw_image + meta_start_offset; + desc = image->fw_image + MAN_DESC_OFFSET_V1_5; + + /* copy data */ + memcpy(desc, &image->adsp->man_v1_5->desc, + sizeof(struct sof_man_fw_desc)); + + /* firmware and build version */ + desc->header.major_version = image->fw_ver_major; + desc->header.minor_version = image->fw_ver_minor; + desc->header.hotfix_version = image->fw_ver_micro; + desc->header.build_version = image->fw_ver_build; + + /* create each module */ + desc->header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_5); + if (ret) + goto err; + + fprintf(stdout, "Firmware completing manifest v1.5\n"); + + /* create structures from end of file to start of file */ + ri_adsp_meta_data_create_v1_8(image, meta_start_offset, + image->meu_offset); + + /* write preload page count */ + preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_5; + desc->header.preload_page_count = DIV_ROUND_UP(preload_size, MAN_PAGE_SIZE); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* calculate hash for ADSP meta data extension */ + assert(image->meu_offset < image->image_end); + ret = hash_sha256(image->fw_image + image->meu_offset, image->image_end - image->meu_offset, + meta->comp_desc[0].hash, sizeof(meta->comp_desc[0].hash)); + if (ret) + goto err; + + /* write the unsigned files */ + ret = man_write_unsigned_mod(image, meta_start_offset, + image->meu_offset, + sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest completed!\n"); + return 0; + +err: + free(image->fw_image); + unlink(image->out_file); + return ret; +} + +/* used to sign with MEU */ +int man_write_fw_meu_v1_8(struct image *image) +{ + const int meta_start_offset = image->meu_offset - + sizeof(struct sof_man_adsp_meta_file_ext_v1_8) - MAN_EXT_PADDING; + struct sof_man_adsp_meta_file_ext_v1_8 *meta; + struct sof_man_fw_desc *desc; + uint32_t preload_size; + int ret; + + /* allocate image */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) { + ret = -ENOMEM; + goto err; + } + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + meta = image->fw_image + meta_start_offset; + desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + + /* copy data */ + memcpy(meta, &image->adsp->man_v1_8->adsp_file_ext, + sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); + memcpy(desc, &image->adsp->man_v1_8->desc, + sizeof(struct sof_man_fw_desc)); + + /* firmware and build version */ + desc->header.major_version = image->fw_ver_major; + desc->header.minor_version = image->fw_ver_minor; + desc->header.hotfix_version = image->fw_ver_micro; + desc->header.build_version = image->fw_ver_build; + + /* create each module */ + desc->header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); + if (ret) + goto err; + + fprintf(stdout, "Firmware completing manifest v1.8\n"); + + /* create structures from end of file to start of file */ + ri_adsp_meta_data_create_v1_8(image, meta_start_offset, + image->meu_offset); + + /* write preload page count */ + preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; + desc->header.preload_page_count = DIV_ROUND_UP(preload_size, MAN_PAGE_SIZE); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* calculate hash for ADSP meta data extension */ + assert(image->meu_offset < image->image_end); + ret = hash_sha256(image->fw_image + image->meu_offset, image->image_end - image->meu_offset, + meta->comp_desc[0].hash, sizeof(meta->comp_desc[0].hash)); + if (ret) + goto err; + + /* write the unsigned files */ + ret = man_write_unsigned_mod(image, meta_start_offset, + image->meu_offset, + sizeof(struct sof_man_adsp_meta_file_ext_v1_8)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest completed!\n"); + return 0; + +err: + free(image->fw_image); + unlink(image->out_file); + return ret; +} + +/* used to sign with MEU */ +int man_write_fw_meu_v2_5(struct image *image) +{ + const int meta_start_offset = image->meu_offset - + sizeof(struct sof_man_adsp_meta_file_ext_v2_5) - MAN_EXT_PADDING; + struct sof_man_adsp_meta_file_ext_v2_5 *meta; + struct sof_man_fw_desc *desc; + uint32_t preload_size; + int ret; + + /* allocate image */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) { + ret = -ENOMEM; + goto err; + } + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + meta = image->fw_image + meta_start_offset; + desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + + /* copy data */ + memcpy(meta, &image->adsp->man_v2_5->adsp_file_ext, + sizeof(struct sof_man_adsp_meta_file_ext_v2_5)); + memcpy(desc, &image->adsp->man_v2_5->desc, + sizeof(struct sof_man_fw_desc)); + + /* firmware and build version */ + desc->header.major_version = image->fw_ver_major; + desc->header.minor_version = image->fw_ver_minor; + desc->header.hotfix_version = image->fw_ver_micro; + desc->header.build_version = image->fw_ver_build; + + /* create each module */ + desc->header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); + if (ret) + goto err; + + /* platform config defines some modules except bringup & base modules */ + man_create_modules_in_config(image, desc); + + fprintf(stdout, "Firmware completing manifest v2.5\n"); + + /* create structures from end of file to start of file */ + ri_adsp_meta_data_create_v2_5(image, meta_start_offset, + image->meu_offset); + + /* write preload page count */ + preload_size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; + desc->header.preload_page_count = DIV_ROUND_UP(preload_size, MAN_PAGE_SIZE); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* calculate hash for ADSP meta data extension */ + assert(image->meu_offset < image->image_end); + ret = hash_sha384(image->fw_image + image->meu_offset, image->image_end - image->meu_offset, + meta->comp_desc[0].hash, sizeof(meta->comp_desc[0].hash)); + if (ret) + goto err; + + /* write the unsigned files */ + ret = man_write_unsigned_mod(image, meta_start_offset, + image->meu_offset, + sizeof(struct sof_man_adsp_meta_file_ext_v2_5)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest completed!\n"); + return 0; + +err: + free(image->fw_image); + unlink(image->out_file); + return ret; +} + +/* used by others */ +int man_write_fw_v2_5(struct image *image) +{ + struct sof_man_fw_desc *desc; + struct fw_image_manifest_v2_5 *m; + int ret; + + /* init image */ + ret = man_init_image_v2_5(image); + if (ret < 0) + goto err; + + /* use default meu offset for TGL if not provided */ + if (!image->meu_offset) + image->meu_offset = MAN_FW_DESC_OFFSET_V2_5 - 0x10; + + /* open ROM image */ + ret = man_open_rom_file(image); + if (ret < 0) + goto err; + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + m = image->fw_image; + desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + + /* firmware and build version */ + m->css.version.major_version = image->fw_ver_major; + m->css.version.minor_version = image->fw_ver_minor; + m->css.version.build_version = image->fw_ver_build; + m->desc.header.major_version = image->fw_ver_major; + m->desc.header.minor_version = image->fw_ver_minor; + m->desc.header.hotfix_version = image->fw_ver_micro; + m->desc.header.build_version = image->fw_ver_build; + + /* create each module */ + m->desc.header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); + if (ret) + goto err; + + /* platform config defines some modules except bringup & base modules */ + man_create_modules_in_config(image, desc); + + fprintf(stdout, "Firmware completing manifest v2.5\n"); + + /* create structures from end of file to start of file */ + ri_adsp_meta_data_create_v2_5(image, MAN_META_EXT_OFFSET_V2_5, + image->meu_offset); + ri_plat_ext_data_create_v2_5(image); + ri_css_v2_5_hdr_create(image); + ri_cse_create_v2_5(image); + + fprintf(stdout, "Firmware file size 0x%x page count %d\n", + FILE_TEXT_OFFSET_V1_8 - MAN_DESC_OFFSET_V1_8 + image->image_end, + desc->header.preload_page_count); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* calculate hash inside ADSP meta data extension for padding to end */ + assert(image->meu_offset < image->image_end); + ret = hash_sha384(image->fw_image + image->meu_offset, image->image_end - image->meu_offset, + m->adsp_file_ext.comp_desc[0].hash, + sizeof(m->adsp_file_ext.comp_desc[0].hash)); + if (ret) + goto err; + + /* mue writes 0xff to 16 bytes of padding */ + memset(m->reserved, 0xff, 16); + + /* calculate hash inside ext info 16 of sof_man_adsp_meta_file_ext_v2_5 */ + assert((MAN_META_EXT_OFFSET_V2_5 + sizeof(struct sof_man_adsp_meta_file_ext_v2_5)) < + image->image_end); + + ret = hash_sha384(image->fw_image + MAN_META_EXT_OFFSET_V2_5, + sizeof(struct sof_man_adsp_meta_file_ext_v2_5), + m->signed_pkg.module[0].hash, sizeof(m->signed_pkg.module[0].hash)); + if (ret) + goto err; + + /* hash values in reverse order */ + bytes_swap(m->signed_pkg.module[0].hash, sizeof(m->signed_pkg.module[0].hash)); + + /* sign manifest */ + ret = ri_manifest_sign_v2_5(image); + if (ret < 0) + goto err; + +#if 0 + /* calculate hash - SHA384 on CAVS2_5+ */ + module_sha384_create(image); + module_sha_update(image, image->fw_image, + sizeof(struct CsePartitionDirHeader_v2_5) + + sizeof(struct CsePartitionDirEntry) * 3); + module_sha_update(image, image->fw_image + 0x4c0, image->image_end - 0x4c0); + module_sha_complete(image, hash); + + /* hash values in reverse order */ + for (i = 0; i < SOF_MAN_MOD_SHA384_LEN; i++) { + m->info_0x16.hash[i] = + hash[SOF_MAN_MOD_SHA384_LEN - 1 - i]; + } +#endif + /* write the firmware */ + ret = man_write_fw_mod(image); + if (ret < 0) + goto err; + + /* write the unsigned files*/ + ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET_V2_5, + MAN_FW_DESC_OFFSET_V2_5, + sizeof(struct sof_man_adsp_meta_file_ext_v2_5)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest and signing completed !\n"); + return 0; + +err: + free(image->rom_image); + free(image->fw_image); + unlink(image->out_file); + unlink(image->out_rom_file); + return ret; +} + +static int man_init_image_ace_v1_5(struct image *image) +{ + /* allocate image and copy template manifest */ + image->fw_image = calloc(image->adsp->image_size, 1); + if (!image->fw_image) + return -ENOMEM; + + memcpy(image->fw_image, image->adsp->man_ace_v1_5, + sizeof(struct fw_image_manifest_ace_v1_5)); + + return 0; +} + +int man_write_fw_ace_v1_5(struct image *image) +{ + struct hash_context hash; + struct sof_man_fw_desc *desc; + struct fw_image_manifest_ace_v1_5 *m; + int ret; + + /* init image */ + ret = man_init_image_ace_v1_5(image); + if (ret < 0) + goto err; + + /* use default meu offset for TGL if not provided */ + if (!image->meu_offset) + image->meu_offset = MAN_FW_DESC_OFFSET_ACE_V1_5 - 0x10; + + /* open ROM image */ + ret = man_open_rom_file(image); + if (ret < 0) + goto err; + + /* open unsigned firmware */ + ret = man_open_unsigned_file(image); + if (ret < 0) + goto err; + + /* create the manifest */ + ret = man_open_manifest_file(image); + if (ret < 0) + goto err; + + /* create the module */ + m = image->fw_image; + desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + + /* firmware and build version */ + m->css.version.major_version = image->fw_ver_major; + m->css.version.minor_version = image->fw_ver_minor; + m->css.version.build_version = image->fw_ver_build; + m->desc.header.major_version = image->fw_ver_major; + m->desc.header.minor_version = image->fw_ver_minor; + m->desc.header.hotfix_version = image->fw_ver_micro; + m->desc.header.build_version = image->fw_ver_build; + + m->desc.header.feature_mask = 0x2; // -> should be feature mask - to fix + m->desc.header.fw_image_flags.fields.image_type = image->loadable_module ? + SOF_MAN_FW_HDR_IMG_TYPE_LIB : SOF_MAN_FW_HDR_IMG_TYPE_MAIN_FW; + m->desc.header.fw_compat = 0x100000; // -> PUT PROPER STRUCT + + /* create each module */ + m->desc.header.num_module_entries = image->num_modules; + ret = man_create_modules(image, desc, FILE_TEXT_OFFSET_V1_8); + if (ret) + goto err; + + /* platform config defines some modules except bringup & base modules */ + ret = man_create_modules_in_config(image, desc); + if (ret) + goto err; + + fprintf(stdout, "Firmware completing manifest v2.5\n"); + + /* create structures from end of file to start of file */ + ri_adsp_meta_data_create_v2_5(image, MAN_META_EXT_OFFSET_ACE_V1_5, + image->meu_offset); + ri_plat_ext_data_create_ace_v1_5(image); + ri_css_v2_5_hdr_create(image); + ri_cse_create_ace_v1_5(image); + + fprintf(stdout, "Firmware file size 0x%x page count %d\n", + FILE_TEXT_OFFSET_V1_8 - MAN_DESC_OFFSET_V1_8 + image->image_end, + desc->header.preload_page_count); + + /* calculate hash for each module */ + man_hash_modules(image, desc); + + /* calculate hash inside ADSP meta data extension for padding to end */ + assert(image->meu_offset < image->image_end); + ret = hash_sha384(image->fw_image + image->meu_offset, image->image_end - image->meu_offset, + m->adsp_file_ext.comp_desc[0].hash, + sizeof(m->adsp_file_ext.comp_desc[0].hash)); + if (ret) + goto err; + + /* mue writes 0xff to 16 bytes of padding */ + memset(m->reserved, 0xff, 16); + + /* calculate hash inside ext info 16 of sof_man_adsp_meta_file_ext_v2_5 */ + assert((MAN_META_EXT_OFFSET_ACE_V1_5 + sizeof(struct sof_man_adsp_meta_file_ext_v2_5)) < + image->image_end); + + ret = hash_sha384(image->fw_image + MAN_META_EXT_OFFSET_ACE_V1_5, + sizeof(struct sof_man_adsp_meta_file_ext_v2_5), + m->signed_pkg.module[0].hash, sizeof(m->signed_pkg.module[0].hash)); + if (ret) + goto err; + + /* hash values in reverse order */ + bytes_swap(m->signed_pkg.module[0].hash, sizeof(m->signed_pkg.module[0].hash)); + + /* calculate hash - SHA384 on CAVS2_5+ */ + hash_sha384_init(&hash); + hash_update(&hash, image->fw_image, + sizeof(struct CsePartitionDirHeader_v2_5) + + sizeof(struct CsePartitionDirEntry) * 3); + + hash_update(&hash, image->fw_image + 0x4c0, image->image_end - 0x4c0); + hash_finalize(&hash); + + /* hash values in reverse order */ + ret = hash_get_digest(&hash, m->info_0x16.hash, sizeof(m->info_0x16.hash)); + if (ret < 0) + goto err; + bytes_swap(m->info_0x16.hash, sizeof(m->info_0x16.hash)); + + /* sign manifest */ + ret = ri_manifest_sign_ace_v1_5(image); + if (ret < 0) + goto err; + + /* write the firmware */ + ret = man_write_fw_mod(image); + if (ret < 0) + goto err; + + /* write the unsigned files*/ + ret = man_write_unsigned_mod(image, MAN_META_EXT_OFFSET_ACE_V1_5, + MAN_FW_DESC_OFFSET_ACE_V1_5, + sizeof(struct sof_man_adsp_meta_file_ext_v2_5)); + if (ret < 0) + goto err; + + fprintf(stdout, "Firmware manifest and signing completed !\n"); + return 0; + +err: + free(image->rom_image); + free(image->fw_image); + unlink(image->out_file); + unlink(image->out_rom_file); + return ret; +} + +int verify_image(struct image *image) +{ + FILE *in_file; + int ret; + void *buffer; + size_t size, read, i; + + /* is verify supported for target ? */ + if (!image->adsp->verify_firmware) { + fprintf(stderr, "error: verify not supported for target\n"); + return -EINVAL; + } + + /* open image for reading */ + in_file = fopen(image->verify_file, "rb"); + if (!in_file) + return file_error("unable to open file for reading", image->verify_file); + + /* get file size */ + ret = get_file_size(in_file, image->verify_file, &size); + if (ret < 0) { + goto out; + } + + /* allocate buffer for parsing */ + buffer = malloc(size); + if (!buffer) { + ret = -ENOMEM; + goto out; + } + + /* find start of fw image and verify */ + read = fread(buffer, 1, size, in_file); + if (read != size) { + ret = file_error("unable to read whole file", image->verify_file); + goto out; + } + for (i = 0; i < size; i += sizeof(uint32_t)) { + /* find CSE header marker "$CPD" */ + if (*(uint32_t *)(buffer + i) == CSE_HEADER_MAKER) { + image->fw_image = buffer + i; + ret = image->adsp->verify_firmware(image); + goto out; + } + } + + /* no header found */ + fprintf(stderr, "error: could not find valid CSE header $CPD in %s\n", + image->verify_file); +out: + fclose(in_file); + return 0; +} + + +int resign_image(struct image *image) +{ + int key_size, key_file_size; + void *buffer = NULL; + size_t size, read; + FILE *in_file; + int ret, i; + + /* open image for reading */ + in_file = fopen(image->in_file, "rb"); + if (!in_file) + return file_error("unable to open file for reading", image->in_file); + + /* get file size */ + ret = get_file_size(in_file, image->in_file, &size); + if (ret < 0) { + goto out; + } + + /* allocate buffer for parsing */ + buffer = malloc(size); + if (!buffer) { + ret = -ENOMEM; + goto out; + } + + /* read file into buffer */ + read = fread(buffer, 1, size, in_file); + if (read != size) { + ret = file_error("unable to read whole file", image->in_file); + goto out; + } + + fclose(in_file); + + for (i = 0; i < size; i += sizeof(uint32_t)) { + /* find CSE header marker "$CPD" */ + if (*(uint32_t *)(buffer + i) == CSE_HEADER_MAKER) { + image->fw_image = buffer + i; + break; + } + } + + if (i >= size) { + fprintf(stderr, "error: didn't found header marker %d\n", i); + ret = -EINVAL; + goto out; + } + + image->image_end = size - i; + + /* check that key size matches */ + if (image->adsp->man_v2_5 || image->adsp->man_ace_v1_5) { + key_size = 384; + } else { + key_size = 256; + } + + key_file_size = get_key_size(image); + + if (key_file_size > key_size) { + fprintf(stderr, "error: key size %d is longer than original key %d\n", + key_file_size, key_size); + ret = -EINVAL; + goto out; + } + + /* resign */ + if (image->adsp->man_v1_5) + ret = ri_manifest_sign_v1_5(image); + else if (image->adsp->man_v1_8) + ret = ri_manifest_sign_v1_8(image); + else if (image->adsp->man_v2_5) + ret = ri_manifest_sign_v2_5(image); + else if (image->adsp->man_ace_v1_5) + ret = ri_manifest_sign_ace_v1_5(image); + else + ret = -EINVAL; + + if (ret < 0) { + fprintf(stderr, "error: unable to sign image\n"); + goto out; + } + + /* open outfile for writing */ + unlink(image->out_file); + image->out_fd = fopen(image->out_file, "wb"); + if (!image->out_fd) { + ret = file_error("unable to open file for writting", image->out_file); + goto out; + } + + /* Rewrite content before CSE header */ + size = fwrite(buffer, 1, i, image->out_fd); + if (size != i) { + ret = file_error("Extended manifest write error", image->out_file); + goto out; + } + + man_write_fw_mod(image); + +out: + free(buffer); + return ret; +} diff --git a/tools/rimage/src/misc_utils.c b/tools/rimage/src/misc_utils.c new file mode 100644 index 000000000000..2c0146f5bdd9 --- /dev/null +++ b/tools/rimage/src/misc_utils.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2018-2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <stdio.h> +#include <rimage/misc_utils.h> + +void bytes_swap(uint8_t *ptr, uint32_t size) +{ + uint8_t tmp; + uint32_t index; + + for (index = 0; index < (size / 2); index++) { + tmp = ptr[index]; + ptr[index] = ptr[size - 1 - index]; + ptr[size - 1 - index] = tmp; + } +} + +void print_enum(unsigned long value, const struct name_val *values) +{ + while (values->name) { + if (values->value == value) { + fprintf(stdout, "%s\n", values->name); + return; + } + + values++; + } + + printf("Unknown: 0x%lx\n", value); +} + +void print_flags(unsigned long value, const struct name_val *flags) +{ + while (flags->name) { + if (value & flags->value) { + fprintf(stdout, "%s ", flags->name); + value &= ~flags->value; + } + + flags++; + } + + if (value) + fprintf(stdout, "+ 0x%lx", value); + printf("\n"); +} diff --git a/tools/rimage/src/module.c b/tools/rimage/src/module.c new file mode 100644 index 000000000000..d35765c591ac --- /dev/null +++ b/tools/rimage/src/module.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +#include <rimage/module.h> +#include <rimage/elf_file.h> +#include <rimage/file_utils.h> +#include <rimage/rimage.h> +#include <rimage/misc_utils.h> +#include <rimage/sof/user/manifest.h> + +int module_read_section(const struct module *module, const struct module_section *section, + void *buffer, const size_t size) +{ + return elf_section_read_content(&module->elf, section->header, buffer, size); +} + +int module_write_section(const struct module *module, const struct module_section *section, + const int padding, FILE *out_file, const char *filename) +{ + int ret; + struct elf_section section_data; + size_t count; + char padding_buf[4]; + + ret = elf_section_read(&module->elf, section->header, §ion_data); + if (ret) + return ret; + + /* write out section data */ + count = fwrite(section_data.data, section->size, 1, out_file); + if (count != 1) { + ret = file_error("cant write section", filename); + goto out; + } + + /* write padding data */ + if (padding) { + assert(padding <= sizeof(padding_buf)); + + memset(padding_buf, 0, padding); + count = fwrite(padding_buf, padding, 1, out_file); + if (count != 1) { + ret = file_error("cant write padding", filename); + goto out; + } + } + +out: + elf_section_free(§ion_data); + return ret; +} + +int module_read_whole_elf(const struct module *module, void *buffer, size_t size) +{ + int ret; + size_t count; + + if (module->elf.file_size > size) { + fprintf(stderr, "error: Output buffer too small.\n"); + return -ENOSPC; + } + + /* read in file data */ + ret = fseek(module->elf.file, 0, SEEK_SET); + if (ret) + return file_error("can't seek set", module->elf.filename); + + count = fread(buffer, module->elf.file_size, 1, module->elf.file); + if (count != 1) + return file_error("can't read data", module->elf.filename); + + return ret; +} + +int module_write_whole_elf(const struct module *module, FILE *out_file, const char *filename) +{ + int ret; + char *buffer; + size_t count; + + /* alloc data data */ + buffer = calloc(1, module->elf.file_size); + if (!buffer) + return -ENOMEM; + + ret = module_read_whole_elf(module, buffer, module->elf.file_size); + if (ret) + goto out; + + /* write out section data */ + count = fwrite(buffer, module->elf.file_size, 1, out_file); + if (count != 1) { + ret = file_error("can't write data", filename); + goto out; + } + +out: + free(buffer); + return ret; +} + +void module_print_zones(const struct module *module) +{ + fprintf(stdout, "\n\tTotals\tStart\t\tEnd\t\tSize"); + + fprintf(stdout, "\n\tTEXT\t0x%8.8x\t0x%8.8x\t0x%zx\n", + module->text.start, module->text.end, module->text.file_size); + fprintf(stdout, "\tDATA\t0x%8.8x\t0x%8.8x\t0x%zx\n", + module->data.start, module->data.end, module->data.file_size); + fprintf(stdout, "\tBSS\t0x%8.8x\t0x%8.8x\t0x%zx\n\n", + module->bss.start, module->bss.end, module->bss.file_size); +} + +/** + * Print a list of valid program headers + * + * @param module pointer to a module structure + */ +static void module_print_programs(const struct module *module) +{ + const Elf32_Phdr *header; + int i; + + /* check each program */ + for (i = 0; i < module->elf.header.phnum; i++) { + header = &module->elf.programs[i]; + + if (header->filesz == 0 || header->type != PT_LOAD) + continue; + + fprintf(stdout, "%s program-%d:\n", module->elf.filename, i); + elf_program_header_print(header); + } +} + +/** + * Goes through program headers array to find the physical address based on the virtual address. + * + * @param elf elf file structure + * @param vaddr virtual address + * @return physical address when success, virtual address on error + */ +static uint32_t find_physical_address(struct elf_file *file, size_t vaddr) +{ + uint16_t i; + const Elf32_Phdr *prog; + + for (i = 0; i < file->programs_count; i++) { + prog = &file->programs[i]; + + if (prog->type != PT_LOAD) + continue; + + if (vaddr >= prog->vaddr && vaddr < (prog->vaddr + file->programs[i].memsz)) + return file->programs[i].paddr + vaddr - prog->vaddr; + } + + return vaddr; +} + +unsigned long uncache_to_cache(const struct memory_alias *alias, unsigned long address) +{ + return (address & ~alias->mask) | alias->cached; +} + +/** + * Checks if the section is placed in the rom memory address space + * + * @param config Memory configuration structure + * @param section section to be checked + * @return true if section is placed in rom memory address space + */ +static bool section_is_rom(const struct memory_config *config, + const struct elf_section_header *section) +{ + uint32_t sect_start, sect_end; + uint32_t rom_start, rom_end; + + sect_start = section->data.vaddr; + sect_end = sect_start + section->data.size; + + rom_start = config->zones[SOF_FW_BLK_TYPE_ROM].base; + rom_end = rom_start + config->zones[SOF_FW_BLK_TYPE_ROM].size; + + if (sect_end <= rom_start || sect_start >= rom_end) + return false; + if (sect_start >= rom_start && sect_end <= rom_end) + return true; + + fprintf(stderr, "Warning! Section %s partially overlaps with rom memory.\n", section->name); + return false; +} + +/** + * Checks if the section is detached from the main module + * + * Some sections can be detached from the main module, e.g. for running in DRAM + * + * @param config Memory configuration structure + * @param section section to be checked + * @return true if section is detached + */ +static bool section_is_detached(const struct memory_config *config, + const struct elf_section_header *section) +{ + uint32_t sect_start, sect_end; + const uint32_t start = SOF_MODULE_DRAM_LINK_START, end = SOF_MODULE_DRAM_LINK_END; + + sect_start = section->data.vaddr; + sect_end = sect_start + section->data.size; + + if (sect_end <= start || sect_start >= end) + return false; + if (sect_start >= start && sect_end <= end) + return true; + + fprintf(stderr, "Warning! Section %s partially overlaps with dram memory.\n", section->name); + return false; +} + +/** + * Initialize module_sections_info structure + * + * @param info Pointer to a module_sections_info structure + */ +static void sections_info_init(struct module_sections_info *info) +{ + memset(info, 0, sizeof(*info)); + + info->start = UINT32_MAX; +} + +/** + * Adds section to module_sections_info structure + * + * @param info Pointer to a module_sections_info structure + * @param section module_section structure + */ +static void sections_info_add(struct module_sections_info *info, struct module_section *section) +{ + const uint32_t end = section->load_address + section->size; + + if (section->load_address < info->start) + info->start = section->load_address; + + if (end > info->end) + info->end = end; + + info->size += section->size; + info->count++; + + /* Add section to list */ + section->next_section = NULL; + + if (info->last_section) + info->last_section->next_section = section; + + info->last_section = section; + + if (!info->first_section) + info->first_section = section; +} + +/** + * Calculates file size after adding all sections + * + * @param info Pointer to a module_sections_info structure + */ +static void sections_info_finalize(struct module_sections_info *info) +{ + size_t size = (info->end > info->start) ? info->end - info->start : 0; + + /* file sizes round up to nearest page */ + info->file_size = ALIGN_UP(size, MAN_PAGE_SIZE); +} + +/** + * Checks the section header (type and flags) to determine the section type. + * + * @param section section header + * @return enum module_section_type + */ +static enum module_section_type get_section_type(const struct elf_section_header *section) +{ + switch (section->data.type) { + case SHT_INIT_ARRAY: + /* fall through */ + case SHT_PROGBITS: + /* text or data */ + return (section->data.flags & SHF_EXECINSTR) ? MST_TEXT : MST_DATA; + + case SHT_NOBITS: + /* bss or heap */ + return MST_BSS; + + case SHT_NOTE: + return MST_NOTE; + + default: + return MST_UNKNOWN; + } +} + +void module_parse_sections(struct module *module, const struct memory_config *mem_cfg, bool verbose, + bool ignore_detached) +{ + const uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); + uint16_t i; + + struct module_section *out_section = module->sections; + size_t cold_text_size = 0, cold_data_size = 0; + + fprintf(stdout, " Found %d sections, listing valid sections...\n", + module->elf.sections_count); + + fprintf(stdout, "\tNo\tLMA\t\tVMA\t\tEnd\t\tSize\tType\tName\n"); + + /* parse each section */ + for (i = 0; i < module->elf.sections_count; i++) { + const struct elf_section_header *sect = &module->elf.sections[i]; + struct module_sections_info *info = NULL; + + /* only write valid sections */ + if (!(sect->data.flags & valid)) + continue; + + /* Comment from fix_elf_addrs.py: + * The sof-derived linker scripts currently emit some zero-length sections + * at address zero. This is benign, and the linker is happy + * + * So we gleefully skip them. */ + if (sect->data.size == 0) + continue; + + out_section->header = sect; + out_section->size = sect->data.size; + out_section->type = get_section_type(sect); + out_section->rom = section_is_rom(mem_cfg, sect); + out_section->detached = !ignore_detached && section_is_detached(mem_cfg, sect); + out_section->address = sect->data.vaddr; + out_section->load_address = find_physical_address(&module->elf, sect->data.vaddr); + + /* Don't convert ROM addresses, ROM sections aren't included in the output image */ + if (!out_section->rom && !out_section->detached) { + /* Walk the sections in the ELF file, changing the VMA/LMA of each uncached section + * to the equivalent address in the cached area of memory. */ + out_section->address = uncache_to_cache(&mem_cfg->alias, + out_section->address); + out_section->load_address = uncache_to_cache(&mem_cfg->alias, + out_section->load_address); + } + + fprintf(stdout, "\t%d\t0x%8.8x\t0x%8.8x\t0x%8.8zx\t0x%zx", i, + out_section->load_address, out_section->address, + out_section->address + out_section->size, out_section->size); + + switch (out_section->type) { + case MST_DATA: + info = &module->data; + if (out_section->detached) + cold_data_size += out_section->size; + fprintf(stdout, "\tDATA"); + break; + + case MST_TEXT: + info = &module->text; + if (out_section->detached) + cold_text_size += out_section->size; + fprintf(stdout, "\tTEXT"); + break; + + case MST_BSS: + info = &module->bss; + fprintf(stdout, "\tBSS"); + break; + + case MST_NOTE: + fprintf(stdout, "\tNOTE"); + break; + + default: + break; + } + + if (out_section->detached) { + /* Detached sections are copied as is and don't contribute to metadata */ + fprintf(stdout, " detached"); + } else if (out_section->rom) { + /* ROM sections aren't included in the output image */ + fprintf(stdout, " ROM"); + } else { + /* Add section to list */ + if (info) + sections_info_add(info, out_section); + } + + module->num_sections++; + out_section++; + + /* section name */ + fprintf(stdout, "\t%s\n", sect->name); + + if (verbose) { + fprintf(stdout, "%s section-%d:\n", module->elf.filename, i); + elf_section_header_print(sect); + } + } + + sections_info_finalize(&module->text); + sections_info_finalize(&module->data); + sections_info_finalize(&module->bss); + + size_t fw_size = module->data.size + module->text.size; + size_t rounded, start, end, size; + + fprintf(stdout, " module: input size %zd (0x%zx) bytes %d sections\n", + fw_size, fw_size, module->num_sections); + + /* MST_TEXT */ + start = module->text.start; + end = module->text.end + cold_text_size; + size = module->text.size + cold_text_size; + rounded = ALIGN_UP(end, MAN_PAGE_SIZE) - start; + fprintf(stdout, + " module: text %zu (0x%zx) bytes, including %zu (0x%zx) %zu%% efficiency bytes\n", + size, size, cold_text_size, cold_text_size, + rounded ? (cold_text_size * 100 + rounded / 2) / rounded : 0); + + /* MST_DATA */ + start = module->data.start; + end = module->data.end + cold_data_size; + size = module->data.size + cold_data_size; + rounded = ALIGN_UP(end, MAN_PAGE_SIZE) - start; + fprintf(stdout, + "\tdata %zu (0x%zx) bytes, including %zu (0x%zx) %zu%% efficiency bytes\n", + size, size, cold_data_size, cold_data_size, + rounded ? (cold_data_size * 100 + rounded / 2) / rounded : 0); + + /* MST_BSS */ + fprintf(stdout, "\tbss %zu (0x%zx) bytes\n", + module->bss.size, module->bss.size); +} + +int module_open(struct module *module, const char *filename, const bool verbose) +{ + int ret; + + memset(module, 0, sizeof(*module)); + + ret = elf_open(&module->elf, filename); + if (ret) + return ret; + + if (verbose) { + fprintf(stdout, "%s elf header:\n", module->elf.filename); + elf_header_print(&module->elf); + module_print_programs(module); + } + + module->sections = calloc(module->elf.sections_count, sizeof(struct module_section)); + if (!module->sections) { + elf_free(&module->elf); + return -ENOMEM; + } + + sections_info_init(&module->data); + sections_info_init(&module->bss); + sections_info_init(&module->text); + + return 0; +} + +void module_close(struct module *module) +{ + elf_free(&module->elf); +} + +/** + * Checks if the contents of the section overlaps + * + * @param a first section to check + * @param b second section to check + * @return true if space of a sections overlap + */ +static bool section_check_overlap(const struct module_section *a, const struct module_section *b) +{ + uint32_t a_start = a->address; + uint32_t a_end = a_start + a->size; + + uint32_t b_start = b->address; + uint32_t b_end = b_start + b->size; + + /* is section start overlapping ? */ + return (a_start >= b_start && a_start < b_end) || + /* is section end overlapping ? */ + (a_end > b_start && a_end <= b_end); +} + +/** + * Checks if the contents of the modules overlaps + * + * @param mod first module to check + * @param mod2 second module to check + * @return error code + */ +static int module_check_overlap(const struct module *mod, const struct module *mod2) +{ + unsigned int i, j; + + /* for each section from first module */ + for (i = 0; i < mod->num_sections; i++) { + /* and for each section from second module */ + for (j = 0; j < mod2->num_sections; j++) { + const struct module_section *section = &mod->sections[i]; + const struct module_section *section2 = &mod2->sections[j]; + + /* don't compare section with itself */ + if (section == section2 || section->detached || section2->detached) + continue; + + /* check section overlapping */ + if (section_check_overlap(section, section2)) { + + fprintf(stderr, "error: Detected overlapping sections:\n"); + fprintf(stderr, "\t[0x%x : 0x%zx] %s from %s\n", section->address, + section->address + section->size - 1, + section->header->name, mod->elf.filename); + fprintf(stderr, "\t[0x%x : 0x%zx] %s from %s\n", section2->address, + section2->address + section2->size - 1, + section2->header->name, mod2->elf.filename); + + return -EINVAL; + } + } + } + + return 0; +} + +int modules_validate(const struct image *image) +{ + int i, j, ret; + + for (i = 0; i < image->num_modules; i++) { + for (j = 0; j < image->num_modules; j++) { + ret = module_check_overlap(&image->module[i].file, &image->module[j].file); + if (ret) + return ret; + } + } + + return 0; +} diff --git a/tools/rimage/src/pkcs1_5.c b/tools/rimage/src/pkcs1_5.c new file mode 100644 index 000000000000..de063ee03bec --- /dev/null +++ b/tools/rimage/src/pkcs1_5.c @@ -0,0 +1,970 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <openssl/pem.h> +#include <openssl/ssl.h> +#include <openssl/rsa.h> +#include <openssl/evp.h> +#include <openssl/bio.h> +#include <openssl/sha.h> +#include <openssl/objects.h> +#include <openssl/bn.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/core_names.h> +#endif +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include <rimage/rimage.h> +#include <rimage/css.h> +#include <rimage/manifest.h> +#include <rimage/misc_utils.h> +#include <rimage/file_utils.h> +#include <rimage/hash.h> + +#define DEBUG_PKCS 0 + +enum manver { + V15 = 0, + V18 = 1, + V25 = 2, + VACE15 = 3 +}; + +static int rimage_read_key(EVP_PKEY **privkey, struct image *image) +{ + char path[256]; + FILE *fp; + + /* requires private key */ + if (!image->key_name) { + fprintf(stderr, "error: no private key set \n"); + return -EINVAL; + } + + /* create new key */ + *privkey = EVP_PKEY_new(); + if (!(*privkey)) + return -ENOMEM; + + /* load in RSA private key from PEM file */ + memset(path, 0, sizeof(path)); + strncpy(path, image->key_name, sizeof(path) - 1); + + fprintf(stdout, " %s: read key '%s'\n", __func__, path); + fp = fopen(path, "rb"); + if (!fp) + return file_error("unable to open file for reading", path); + + PEM_read_PrivateKey(fp, privkey, NULL, NULL); + fclose(fp); + + return 0; +} + +/* + * Here we have different implementations of following functionality + * (based on different openssl versions): + * + * rimage_check_key + * + * rimage_set_modexp + * + * rimage_sign + * + * rimage_verify + * + * rimage_get_key_size + * +*/ + +#if OPENSSL_VERSION_NUMBER < 0x30000000L +static int rimage_check_key(EVP_PKEY *privkey) +{ + RSA *priv_rsa = NULL; + + priv_rsa = EVP_PKEY_get1_RSA(privkey); + + return RSA_check_key(priv_rsa); +} +#else +static int rimage_check_key(EVP_PKEY *privkey) +{ + EVP_PKEY_CTX *ctx; + int ret = 0; + + ctx = EVP_PKEY_CTX_new(privkey, NULL /* no engine */); + if (!ctx) + return -EINVAL; + + ret = EVP_PKEY_private_check(ctx); + + EVP_PKEY_CTX_free(ctx); + + return ret; +} +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static void rimage_set_modexp(EVP_PKEY *privkey, unsigned char *mod, unsigned char *exp) +{ + RSA *priv_rsa = NULL; + const BIGNUM *n; + const BIGNUM *e; + + priv_rsa = EVP_PKEY_get1_RSA(privkey); + + n = priv_rsa->n; + e = priv_rsa->e; + + BN_bn2bin(n, mod); + BN_bn2bin(e, exp); +} +#elif OPENSSL_VERSION_NUMBER < 0x30000000L +static void rimage_set_modexp(EVP_PKEY *privkey, unsigned char *mod, unsigned char *exp) +{ + const BIGNUM *n; + const BIGNUM *e; + const BIGNUM *d; + RSA *priv_rsa = NULL; + + priv_rsa = EVP_PKEY_get1_RSA(privkey); + + RSA_get0_key(priv_rsa, &n, &e, &d); + + BN_bn2bin(n, mod); + BN_bn2bin(e, exp); +} +#else +static void rimage_set_modexp(EVP_PKEY *privkey, unsigned char *mod, unsigned char *exp) +{ + BIGNUM *n = NULL; + BIGNUM *e = NULL; + + EVP_PKEY_get_bn_param(privkey, OSSL_PKEY_PARAM_RSA_N, &n); + EVP_PKEY_get_bn_param(privkey, OSSL_PKEY_PARAM_RSA_E, &e); + + BN_bn2bin(n, mod); + BN_bn2bin(e, exp); +} +#endif + +#if OPENSSL_VERSION_NUMBER < 0x30000000L +static int rimage_sign(EVP_PKEY *privkey, enum manver ver, struct hash_context *digest, + unsigned char *signature) +{ + unsigned char sig[MAN_RSA_SIGNATURE_LEN_2_5]; + unsigned int siglen = MAN_RSA_SIGNATURE_LEN; + RSA *priv_rsa = NULL; + int ret; + + priv_rsa = EVP_PKEY_get1_RSA(privkey); + + switch (ver) { + case V15: + /* fallthrough */ + case V18: + ret = RSA_sign(NID_sha256, digest->digest, digest->digest_length, + signature, &siglen, priv_rsa); + break; + case V25: + /* fallthrough */ + case VACE15: + ret = RSA_padding_add_PKCS1_PSS(priv_rsa, sig, digest->digest, digest->algo, + /* salt length */ 32); + if (ret > 0) + ret = RSA_private_encrypt(RSA_size(priv_rsa), sig, signature, priv_rsa, + RSA_NO_PADDING); + break; + default: + return -EINVAL; + } + + return ret; +} +#else +static int rimage_sign(EVP_PKEY *privkey, enum manver ver, + struct hash_context *digest, unsigned char *signature) +{ + EVP_PKEY_CTX *ctx = NULL; + size_t siglen = MAN_RSA_SIGNATURE_LEN; + int ret; + + ctx = EVP_PKEY_CTX_new(privkey, NULL /* no engine */); + if (!ctx) + return -ENOMEM; + + ret = EVP_PKEY_sign_init(ctx); + if (ret <= 0) + goto out; + + if (ver == V25 || ver == VACE15) { + ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING); + if (ret <= 0) { + fprintf(stderr, "error: failed to set rsa padding\n"); + goto out; + } + + ret = EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 32); + if (ret <= 0) { + fprintf(stderr, "error: failed to set saltlen\n"); + goto out; + } + + siglen = MAN_RSA_SIGNATURE_LEN_2_5; + } + + ret = EVP_PKEY_CTX_set_signature_md(ctx, digest->algo); + if (ret <= 0) { + fprintf(stderr, "error: failed to set signature algorithm\n"); + goto out; + } + + ret = EVP_PKEY_sign(ctx, signature, &siglen, digest->digest, digest->digest_length); + if (ret <= 0) { + fprintf(stderr, "error: failed to sign manifest\n"); + goto out; + } + +out: + EVP_PKEY_CTX_free(ctx); + + return ret; +} +#endif + +#if OPENSSL_VERSION_NUMBER < 0x30000000L +static int rimage_verify(EVP_PKEY *privkey, enum manver ver, struct hash_context *digest, + unsigned char *signature) +{ + unsigned char sig[MAN_RSA_SIGNATURE_LEN_2_5]; + unsigned int siglen = MAN_RSA_SIGNATURE_LEN; + RSA *priv_rsa = NULL; + char err_buf[256]; + int ret; + + priv_rsa = EVP_PKEY_get1_RSA(privkey); + + switch (ver) { + case V15: + /* fallthrough */ + case V18: + ret = RSA_verify(NID_sha256, digest->digest, digest->digest_length, signature, + siglen, priv_rsa); + + if (ret <= 0) { + ERR_error_string(ERR_get_error(), err_buf); + fprintf(stderr, "error: verify %s\n", err_buf); + } + break; + case V25: + /* fallthrough */ + case VACE15: + /* decrypt signature */ + ret = RSA_public_decrypt(RSA_size(priv_rsa), signature, sig, priv_rsa, + RSA_NO_PADDING); + if (ret <= 0) { + ERR_error_string(ERR_get_error(), err_buf); + fprintf(stderr, "error: verify decrypt %s\n", err_buf); + return ret; + } + + ret = RSA_verify_PKCS1_PSS(priv_rsa, digest->digest, digest->algo, sig, 32); + if (ret <= 0) { + ERR_error_string(ERR_get_error(), err_buf); + fprintf(stderr, "error: verify %s\n", err_buf); + } + break; + default: + return -EINVAL; + } + + return ret; +} +#else +static int rimage_verify(EVP_PKEY *privkey, enum manver ver,struct hash_context *digest, + unsigned char *signature) +{ + EVP_PKEY_CTX *ctx = NULL; + size_t siglen = MAN_RSA_SIGNATURE_LEN; + char err_buf[256]; + int ret; + + ctx = EVP_PKEY_CTX_new(privkey, NULL /* no engine */); + if (!ctx) + return -ENOMEM; + + ret = EVP_PKEY_verify_init(ctx); + if (ret <= 0) + goto out; + + ret = EVP_PKEY_CTX_set_signature_md(ctx, digest->algo); + if (ret <= 0) { + ERR_error_string(ERR_get_error(), err_buf); + fprintf(stderr, "error: set signature %s\n", err_buf); + goto out; + } + + switch (ver) { + case V15: /* fallthrough */ + case V18: + break; + + case V25: /* fallthrough */ + case VACE15: + ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING); + if (ret <= 0) + goto out; + + ret = EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, 32); + if (ret <= 0) + goto out; + + siglen = MAN_RSA_SIGNATURE_LEN_2_5; + break; + default: + return -EINVAL; + } + + ret = EVP_PKEY_verify(ctx, signature, siglen, digest->digest, digest->digest_length); + if (ret <= 0) { + ERR_error_string(ERR_get_error(), err_buf); + fprintf(stderr, "error: verify %s\n", err_buf); + } + +out: + EVP_PKEY_CTX_free(ctx); + + return ret; +} +#endif + +#if OPENSSL_VERSION_NUMBER < 0x30000000L +static int rimage_get_key_size(EVP_PKEY *privkey) +{ + RSA *priv_rsa = NULL; + int key_length; + + priv_rsa = EVP_PKEY_get1_RSA(privkey); + key_length = RSA_size(priv_rsa); + + RSA_free(priv_rsa); + + return key_length; +} +#else +static int rimage_get_key_size(EVP_PKEY *privkey) +{ + return EVP_PKEY_get_size(privkey); +} +#endif + +/* + * RSA signature of manifest. The signature is an PKCS + * #1-v1_5 of the entire manifest structure, including all + * extensions, and excluding the last 3 fields of the + * manifest header (Public Key, Exponent and Signature). + */ + +int pkcs_v1_5_sign_man_v1_5(struct image *image, + struct fw_image_manifest_v1_5 *man, + void *ptr1, unsigned int size1) +{ + EVP_PKEY *privkey; + struct hash_context digest; + unsigned char mod[MAN_RSA_KEY_MODULUS_LEN]; + int ret = -EINVAL, i; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest */ + hash_sha256_init(&digest); + hash_update(&digest, ptr1, size1); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* sign the manifest */ + ret = rimage_sign(privkey, V15, &digest, (unsigned char *)man->css_header.signature); + if (ret <= 0) { + fprintf(stderr, "error: failed to sign manifest\n"); + goto err; + } + + /* copy public key modulus and exponent to manifest */ + rimage_set_modexp(privkey, mod, (unsigned char *)man->css_header.exponent); + + /* modulus is reveresd */ + for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN; i++) + man->css_header.modulus[i] + = mod[MAN_RSA_KEY_MODULUS_LEN - (1 + i)]; + + /* signature is reveresd, swap it */ + bytes_swap(man->css_header.signature, + sizeof(man->css_header.signature)); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +/* + * RSA signature of manifest. The signature is an PKCS + * #1-v1_5 of the entire manifest structure, including all + * extensions, and excluding the last 3 fields of the + * manifest header (Public Key, Exponent and Signature). + */ + +int pkcs_v1_5_sign_man_v1_8(struct image *image, + struct fw_image_manifest_v1_8 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + struct hash_context digest; + unsigned char mod[MAN_RSA_KEY_MODULUS_LEN]; + int ret = -EINVAL, i; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest */ + hash_sha256_init(&digest); + hash_update(&digest, ptr1, size1); + hash_update(&digest, ptr2, size2); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* sign the manifest */ + ret = rimage_sign(privkey, V18, &digest, (unsigned char *)man->css.signature); + if (ret <= 0) { + fprintf(stderr, "error: failed to sign manifest\n"); + goto err; + } + + /* copy public key modulus and exponent to manifest */ + rimage_set_modexp(privkey, mod, (unsigned char *)man->css.exponent); + + /* modulus is reveresd */ + for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN; i++) + man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN - (1 + i)]; + + /* signature is reveresd, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +int pkcs_v1_5_sign_man_v2_5(struct image *image, + struct fw_image_manifest_v2_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + struct hash_context digest; + unsigned char mod[MAN_RSA_KEY_MODULUS_LEN_2_5]; + int ret = -EINVAL, i; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest - SHA384 on CAVS2_5+ */ + hash_sha384_init(&digest); + hash_update(&digest, ptr1, size1); + hash_update(&digest, ptr2, size2); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* sign the manifest */ + ret = rimage_sign(privkey, V25, &digest, (unsigned char *)man->css.signature); + if (ret <= 0) { + fprintf(stderr, "error: failed to sign manifest\n"); + goto err; + } + + /* copy public key modulus and exponent to manifest */ + rimage_set_modexp(privkey, mod, (unsigned char *)man->css.exponent); + + /* modulus is reversed */ + for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN_2_5; i++) + man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN_2_5 - (1 + i)]; + + /* signature is reversed, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +int pkcs_v1_5_sign_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + struct hash_context digest; + unsigned char mod[MAN_RSA_KEY_MODULUS_LEN_2_5]; + int ret = -EINVAL, i; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest - SHA384 on CAVS2_5+ */ + hash_sha384_init(&digest); + hash_update(&digest, ptr1, size1); + hash_update(&digest, ptr2, size2); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* sign the manifest */ + ret = rimage_sign(privkey, VACE15, &digest, (unsigned char *)man->css.signature); + if (ret <= 0) { + fprintf(stderr, "error: failed to sign manifest\n"); + goto err; + } + + /* copy public key modulus and exponent to manifest */ + rimage_set_modexp(privkey, mod, (unsigned char *)man->css.exponent); + + /* modulus is reversed */ + for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN_2_5; i++) + man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN_2_5 - (1 + i)]; + + /* signature is reversed, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +int ri_manifest_sign_v1_5(struct image *image) +{ + struct fw_image_manifest_v1_5 *man = image->fw_image; + + /* excluding the manifest header */ + char *const data1 = (char *)man + sizeof(struct fw_image_manifest_v1_5); + unsigned const size1 = image->image_end - sizeof(*man); + + return pkcs_v1_5_sign_man_v1_5(image, man, data1, size1); +} + +int ri_manifest_sign_v1_8(struct image *image) +{ + struct fw_image_manifest_v1_8 *man = image->fw_image; + + char *const data1 = (char *)man + MAN_CSS_HDR_OFFSET; + unsigned const size1 = + sizeof(struct css_header_v1_8) - + (MAN_RSA_KEY_MODULUS_LEN + MAN_RSA_KEY_EXPONENT_LEN + + MAN_RSA_SIGNATURE_LEN); + + char *const data2 = (char *)man + MAN_SIG_PKG_OFFSET_V1_8; + unsigned const size2 = + (man->css.size - man->css.header_len) * sizeof(uint32_t); + + return pkcs_v1_5_sign_man_v1_8(image, man, data1, size1, data2, size2); +} + +int ri_manifest_sign_v2_5(struct image *image) +{ + struct fw_image_manifest_v2_5 *man = image->fw_image; + + char *const data1 = (char *)man + MAN_CSS_HDR_OFFSET_2_5; + unsigned const size1 = + sizeof(struct css_header_v2_5) - + (MAN_RSA_KEY_MODULUS_LEN_2_5 + MAN_RSA_KEY_EXPONENT_LEN + + MAN_RSA_SIGNATURE_LEN_2_5); + + char *const data2 = (char *)man + MAN_SIG_PKG_OFFSET_V2_5; + unsigned const size2 = + (man->css.size - man->css.header_len) * sizeof(uint32_t); + + return pkcs_v1_5_sign_man_v2_5(image, man, data1, size1, data2, size2); +} + +int ri_manifest_sign_ace_v1_5(struct image *image) +{ + struct fw_image_manifest_ace_v1_5 *man = image->fw_image; + + char *const data1 = (char *)man + MAN_CSS_HDR_OFFSET_2_5; + unsigned const size1 = + sizeof(struct css_header_v2_5) - + (MAN_RSA_KEY_MODULUS_LEN_2_5 + MAN_RSA_KEY_EXPONENT_LEN + + MAN_RSA_SIGNATURE_LEN_2_5); + + char *const data2 = (char *)man + MAN_SIG_PKG_OFFSET_V2_5; + unsigned const size2 = + (man->css.size - man->css.header_len) * sizeof(uint32_t); + + return pkcs_v1_5_sign_man_ace_v1_5(image, man, data1, size1, data2, size2); +} + +/* + * RSA verify of manifest. The signature is an PKCS + * #1-v1_5 of the entire manifest structure, including all + * extensions, and excluding the last 3 fields of the + * manifest header (Public Key, Exponent and Signature). + */ + +int pkcs_v1_5_verify_man_v1_5(struct image *image, + struct fw_image_manifest_v1_5 *man, + void *ptr1, unsigned int size1) +{ + EVP_PKEY *privkey; + struct hash_context digest; + int ret = -EINVAL; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest */ + hash_sha256_init(&digest); + hash_update(&digest, ptr1, size1); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* signature is reversed, swap it */ + bytes_swap(man->css_header.signature, + sizeof(man->css_header.signature)); + + /* verify */ + ret = rimage_verify(privkey, V15, &digest, (unsigned char *)man->css_header.signature); + if (ret <= 0) + fprintf(stderr, "error: failed to verify manifest\n"); + else + fprintf(stdout, "pkcs: signature is valid !\n"); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +/* + * RSA verify of manifest. The signature is an PKCS + * #1-v1_5 of the entire manifest structure, including all + * extensions, and excluding the last 3 fields of the + * manifest header (Public Key, Exponent and Signature). + */ + +int pkcs_v1_5_verify_man_v1_8(struct image *image, + struct fw_image_manifest_v1_8 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + struct hash_context digest; + int ret = -EINVAL; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest */ + hash_sha256_init(&digest); + hash_update(&digest, ptr1, size1); + hash_update(&digest, ptr2, size2); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* signature is reveresd, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + + /* verify */ + ret = rimage_verify(privkey, V18, &digest, (unsigned char *)man->css.signature); + if (ret <= 0) + fprintf(stderr, "error: failed to verify manifest\n"); + else + fprintf(stdout, "pkcs: signature is valid !\n"); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +/* + * RSA signature of manifest. The signature is an RSA PSS + * of the entire manifest structure, including all + * extensions, and excluding the last 3 fields of the + * manifest header (Public Key, Exponent and Signature). + */ + +int pkcs_v1_5_verify_man_v2_5(struct image *image, + struct fw_image_manifest_v2_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + struct hash_context digest; + int ret = -EINVAL; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest - SHA384 on CAVS2_5+ */ + hash_sha384_init(&digest); + hash_update(&digest, ptr1, size1); + hash_update(&digest, ptr2, size2); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* signature is reversed, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + + /* verify */ + ret = rimage_verify(privkey, V25, &digest, (unsigned char *)man->css.signature); + + if (ret <= 0) + fprintf(stderr, "error: failed to verify manifest\n"); + else + fprintf(stdout, "pkcs: signature is valid !\n"); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +int pkcs_v1_5_verify_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + struct hash_context digest; + int ret = -EINVAL; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest - SHA384 on CAVS2_5+ */ + hash_sha384_init(&digest); + hash_update(&digest, ptr1, size1); + hash_update(&digest, ptr2, size2); + ret = hash_finalize(&digest); + if (ret) + goto err; + + fprintf(stdout, " pkcs: digest for manifest is "); + hash_print(&digest); + + /* signature is reversed, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + + /* verify */ + ret = rimage_verify(privkey, VACE15, &digest, (unsigned char *)man->css.signature); + if (ret <= 0) + fprintf(stderr, "error: failed to verify manifest\n"); + else + fprintf(stdout, "pkcs: signature is valid !\n"); + +err: + EVP_PKEY_free(privkey); + return ret; +} + +int ri_manifest_verify_v1_5(struct image *image) +{ + struct fw_image_manifest_v1_5 *man = image->fw_image; + + char *const data1 = (char *)man + MAN_CSS_MAN_SIZE_V1_5; + unsigned const size1 = image->image_end - sizeof(*man); + + return pkcs_v1_5_verify_man_v1_5(image, man, data1, size1); +} + +int ri_manifest_verify_v1_8(struct image *image) +{ + struct fw_image_manifest_v1_8 *man = image->fw_image; + + char *const data1 = (char *)man + MAN_CSS_HDR_OFFSET; + unsigned const size1 = + sizeof(struct css_header_v1_8) - + (MAN_RSA_KEY_MODULUS_LEN + MAN_RSA_KEY_EXPONENT_LEN + + MAN_RSA_SIGNATURE_LEN); + + char *const data2 = (char *)man + MAN_SIG_PKG_OFFSET_V1_8; + unsigned const size2 = + (man->css.size - man->css.header_len) * sizeof(uint32_t); + + return pkcs_v1_5_verify_man_v1_8(image, man, data1, size1, data2, size2); +} + +int ri_manifest_verify_v2_5(struct image *image) +{ + struct fw_image_manifest_v2_5 *man = image->fw_image; + + char *const data1 = (char *)man + MAN_CSS_HDR_OFFSET_2_5; + unsigned const size1 = + sizeof(struct css_header_v2_5) - + (MAN_RSA_KEY_MODULUS_LEN_2_5 + MAN_RSA_KEY_EXPONENT_LEN + + MAN_RSA_SIGNATURE_LEN_2_5); + + char *const data2 = (char *)man + MAN_SIG_PKG_OFFSET_V2_5; + unsigned const size2 = + (man->css.size - man->css.header_len) * sizeof(uint32_t); + + return pkcs_v1_5_verify_man_v2_5(image, man, data1, size1, data2, size2); +} + +int get_key_size(struct image *image) +{ + EVP_PKEY *privkey; + int key_len; + int ret; + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + key_len = rimage_get_key_size(privkey); + + EVP_PKEY_free(privkey); + + return key_len; +} diff --git a/tools/rimage/src/plat_auth.c b/tools/rimage/src/plat_auth.c new file mode 100644 index 000000000000..5d8d888bdf05 --- /dev/null +++ b/tools/rimage/src/plat_auth.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2017 Intel Corporation. All rights reserved. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> + +#include <rimage/rimage.h> +#include <rimage/manifest.h> +#include <rimage/plat_auth.h> +#include <rimage/misc_utils.h> + +void ri_adsp_meta_data_create_v1_8(struct image *image, int meta_start_offset, + int meta_end_offset) +{ + struct sof_man_adsp_meta_file_ext_v1_8 *meta = + image->fw_image + meta_start_offset; + + fprintf(stdout, " meta: completing ADSP manifest\n"); + + meta->comp_desc[0].limit_offset = MAN_DESC_OFFSET_V1_8 + + image->image_end - meta_end_offset; + + fprintf(stdout, " meta: limit is 0x%x\n", + meta->comp_desc[0].limit_offset); + /* now hash the AdspFwBinaryDesc -> EOF */ +} + +void ri_adsp_meta_data_create_v2_5(struct image *image, int meta_start_offset, + int meta_end_offset) +{ + struct sof_man_adsp_meta_file_ext_v2_5 *meta = + image->fw_image + meta_start_offset; + + fprintf(stdout, " meta: completing ADSP manifest\n"); + + meta->comp_desc[0].limit_offset = MAN_DESC_OFFSET_V1_8 + + image->image_end - meta_end_offset; + + fprintf(stdout, " meta: limit is 0x%x\n", + meta->comp_desc[0].limit_offset); + /* now hash the AdspFwBinaryDesc -> EOF */ +} + +void ri_plat_ext_data_create(struct image *image) +{ + struct partition_info_ext *part = image->fw_image + + MAN_PART_INFO_OFFSET_V1_8; + struct sof_man_adsp_meta_file_ext_v1_8 *meta = + image->fw_image + MAN_META_EXT_OFFSET_V1_8; + struct sof_man_fw_desc *desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + + fprintf(stdout, " auth: completing authentication manifest\n"); + + part->length = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; + part->length = ALIGN_UP(part->length, MAN_PAGE_SIZE); + + /* do this here atm */ + desc->header.preload_page_count = part->length / MAN_PAGE_SIZE; +} + +void ri_plat_ext_data_create_v2_5(struct image *image) +{ + struct sof_man_adsp_meta_file_ext_v2_5 *meta = + image->fw_image + MAN_META_EXT_OFFSET_V2_5; + struct sof_man_fw_desc *desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + struct info_ext_0x16 *ext = image->fw_image + MAN_PART_INFO_OFFSET_V2_5; + uint32_t size; + + fprintf(stdout, " auth: completing authentication manifest\n"); + + size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; + + /* do this here atm */ + desc->header.preload_page_count = DIV_ROUND_UP(size, MAN_PAGE_SIZE); + ext->size = image->image_end; +} + +void ri_plat_ext_data_create_ace_v1_5(struct image *image) +{ + struct sof_man_adsp_meta_file_ext_v2_5 *meta = + image->fw_image + MAN_META_EXT_OFFSET_ACE_V1_5; + struct sof_man_fw_desc *desc = image->fw_image + MAN_DESC_OFFSET_V1_8; + struct info_ext_0x16 *ext = image->fw_image + MAN_PART_INFO_OFFSET_ACE_V1_5; + uint32_t size; + + fprintf(stdout, " auth: completing authentication manifest\n"); + + size = meta->comp_desc[0].limit_offset - MAN_DESC_OFFSET_V1_8; + + desc->header.preload_page_count = DIV_ROUND_UP(size, MAN_PAGE_SIZE); + ext->size = image->image_end; +} diff --git a/tools/rimage/src/rimage.c b/tools/rimage/src/rimage.c new file mode 100644 index 000000000000..8e50bf9f5033 --- /dev/null +++ b/tools/rimage/src/rimage.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2015 Intel Corporation. All rights reserved. + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <getopt.h> +#include <errno.h> +#include <string.h> +#include <stdbool.h> + +#include <rimage/adsp_config.h> +#include <rimage/ext_manifest_gen.h> +#include <rimage/rimage.h> +#include <rimage/manifest.h> +#include <rimage/file_utils.h> + + +static void usage(char *name) +{ + fprintf(stdout, "%s:\t -c adsp_desc -o outfile -k [key] ELF files\n", + name); + fprintf(stdout, "%s:\t -c adsp_desc -y infile -k [key]\n", + name); + fprintf(stdout, "\t -v enable verbose output\n"); + fprintf(stdout, "\t -r enable relocatable ELF files\n"); + fprintf(stdout, "\t -s MEU signing offset, disables rimage signing\n"); + fprintf(stdout, "\t -i set IMR type\n"); + fprintf(stdout, "\t -f firmware version = major.minor.micro\n"); + fprintf(stdout, "\t -b build version\n"); + fprintf(stdout, "\t -e build extended manifest\n"); + fprintf(stdout, "\t -l build loadable modules image (don't treat the first module as a bootloader)\n"); + fprintf(stdout, "\t -y verify signed file\n"); + fprintf(stdout, "\t -q resign binary\n"); + fprintf(stdout, "\t -p set PV bit\n"); + fprintf(stdout, "\t -d ignore detached sections\n"); + fprintf(stdout, "\t -Q, --quiet suppress informational stdout logs\n"); +} + +int main(int argc, char *argv[]) +{ + struct image image; + struct adsp *heap_adsp; + const char *adsp_config = NULL; + int opt, ret, i, first_non_opt; + int use_ext_man = 0; + unsigned int pv_bit = 0; + bool imr_type_override = false; + bool quiet = false; + static const struct option long_options[] = { + { "quiet", no_argument, NULL, 'Q' }, + { NULL, 0, NULL, 0 } + }; + + memset(&image, 0, sizeof(image)); + + image.imr_type = MAN_DEFAULT_IMR_TYPE; + + while ((opt = getopt_long(argc, argv, "ho:va:s:k:ri:f:b:ec:y:q:pldQ", + long_options, NULL)) != -1) { + switch (opt) { + case 'o': + image.out_file = optarg; + break; + case 'v': + image.verbose = 1; + break; + case 's': + image.meu_offset = atoi(optarg); + break; + case 'a': + image.abi = atoi(optarg); + break; + case 'k': + image.key_name = optarg; + break; + case 'r': + image.reloc = 1; + break; + case 'i': + image.imr_type = atoi(optarg); + imr_type_override = true; + break; + case 'f': + image.fw_ver_string = optarg; + break; + case 'b': + image.fw_ver_build_string = optarg; + break; + case 'e': + use_ext_man = 1; + break; + case 'c': + adsp_config = optarg; + break; + case 'y': + image.verify_file = optarg; + break; + case 'h': + usage(argv[0]); + return 0; + case 'q': + image.in_file = optarg; + break; + case 'p': + pv_bit = 1; + break; + case 'l': + image.loadable_module = true; + break; + case 'd': + /* ignore detached sections */ + image.ignore_detached = true; + break; + case 'Q': + quiet = true; + break; + default: + /* getopt's default error message is good enough */ + return 1; + } + } + + first_non_opt = optind; + + /* we must have config */ + if (!adsp_config) { + usage(argv[0]); + fprintf(stderr, "error: must have adsp desc\n"); + return -EINVAL; + } + + /* requires private key */ + if (!image.key_name) { + fprintf(stderr, "error: requires private key\n"); + return -EINVAL; + } + + /* make sure we have an outfile if not verifying */ + if ((!image.out_file && !image.verify_file)) { + usage(argv[0]); + return -EINVAL; + } + + /* firmware version: major.minor.micro */ + if (image.fw_ver_string) { + ret = sscanf(image.fw_ver_string, "%hu.%hu.%hu", + &image.fw_ver_major, + &image.fw_ver_minor, + &image.fw_ver_micro); + + if (ret != 3) { + fprintf(stderr, + "error: cannot parse firmware version major.minor.micro\n"); + return -EINVAL; + } + } + + /* firmware build id */ + if (image.fw_ver_build_string) { + ret = sscanf(image.fw_ver_build_string, "%hu", + &image.fw_ver_build); + + if (ret != 1) { + fprintf(stderr, + "error: cannot parse build version\n"); + return -EINVAL; + } + } + + if (quiet && !freopen("/dev/null", "w", stdout)) + fprintf(stderr, "error: unable to redirect stdout: %s\n", strerror(errno)); + + /* find machine */ + heap_adsp = malloc(sizeof(struct adsp)); + if (!heap_adsp) { + fprintf(stderr, "error: memory allocation for adsp struct failed\n"); + return -ENOMEM; + } + image.adsp = heap_adsp; + memset(heap_adsp, 0, sizeof(*heap_adsp)); + ret = adsp_parse_config(adsp_config, &image); + if (ret < 0) + goto out; + + /* verify mode ? */ + if (image.verify_file) { + ret = verify_image(&image); + goto out; + } + + if (image.in_file) { + fprintf(stdout, "going to re-sign\n"); + ret = resign_image(&image); + goto out; + } + + /* set IMR Type and the PV bit in found machine definition */ + if (image.adsp->man_v1_8) { + if (imr_type_override) + image.adsp->man_v1_8->adsp_file_ext.imr_type = image.imr_type; + image.adsp->man_v1_8->css.reserved0 = pv_bit; + } + + if (image.adsp->man_v2_5) { + if (imr_type_override) + image.adsp->man_v2_5->adsp_file_ext.imr_type = image.imr_type; + image.adsp->man_v2_5->css.reserved0 = pv_bit; + } + + if (image.adsp->man_ace_v1_5) { + image.adsp->man_ace_v1_5->css.reserved0 = pv_bit; + } + + /* parse input ELF files */ + image.num_modules = argc - first_non_opt; + + if (image.num_modules <= 0) { + fprintf(stderr, + "error: requires at least one ELF input module\n"); + ret = -EINVAL; + goto out; + } + + if (image.num_modules > MAX_MODULES) { + fprintf(stderr, "error: Too many input modules\n"); + ret = -EMFILE; + goto out; + } + + /* Some platforms dont have modules configuration in toml file */ + if (image.adsp->modules && image.num_modules > image.adsp->modules->mod_man_count) { + fprintf(stderr, "error: Each ELF input module requires entry in toml file.\n"); + ret = -EINVAL; + goto out; + } + + /* getopt reorders argv[] */ + for (opt = first_non_opt; opt < argc; opt++) { + i = opt - first_non_opt; + fprintf(stdout, "\nModule Reading %s\n", argv[opt]); + ret = module_open(&image.module[i].file, argv[opt], image.verbose); + if (ret < 0) + goto out; + + module_parse_sections(&image.module[i].file, &image.adsp->mem, image.verbose, + image.ignore_detached); + + /* When there is more than one module, then first one is bootloader. + * Does not apply to building a image of a loadable module. */ + image.module[i].is_bootloader = image.num_modules > 1 && i == 0 && + !image.loadable_module; + } + + /* validate all modules */ + ret = modules_validate(&image); + if (ret < 0) + goto out; + + /* open outfile for writing */ + unlink(image.out_file); + image.out_fd = fopen(image.out_file, "wb"); + if (!image.out_fd) { + ret = file_error("unable to open file for writing", image.out_file); + goto out; + } + + /* process and write output */ + if (image.meu_offset) { + assert(image.adsp->write_firmware_meu); + ret = image.adsp->write_firmware_meu(&image); + } else { + assert(image.adsp->write_firmware); + ret = image.adsp->write_firmware(&image); + } + if (ret) + goto out; + + /* build extended manifest */ + if (use_ext_man) { + if (image.adsp->write_firmware_ext_man) + ret = image.adsp->write_firmware_ext_man(&image); + else + ret = ext_man_write(&image); + + if (ret < 0) { + fprintf(stderr, "error: unable to write extended manifest, %d\n", + ret); + goto out; + } + } + +out: + /* free memory */ + adsp_free(heap_adsp); + + /* close files */ + if (image.out_fd) + fclose(image.out_fd); + + /* Free loaded modules */ + for (i = 0; i < image.num_modules; i++) { + module_close(&image.module[i].file); + } + + return ret; +} diff --git a/tools/rimage/src/toml_utils.c b/tools/rimage/src/toml_utils.c new file mode 100644 index 000000000000..40a73fa1514c --- /dev/null +++ b/tools/rimage/src/toml_utils.c @@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + * Marc Herbert <marc.herbert@intel.com> + */ + +#include "toml.h" +#include <rimage/toml_utils.h> +#include <rimage/cavs/cavs_ext_manifest.h> + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <stdarg.h> + +void print_bytes(FILE *out, const uint8_t *arr, size_t len) +{ + for (const uint8_t *pos = arr; pos < arr + len; pos++) { + char c = *pos; + + if (isprint(c)) + fputc(c, out); + else + fprintf(out, "\\x%.2x", c); + } +} + +#define DUMP_PRINTABLE_BYTES(name, var) _dump_printable_bytes(name, var, sizeof(var)) + +void _dump_printable_bytes(const char *name, const uint8_t *arr, size_t len) +{ + printf(DUMP_KEY_FMT, name); + print_bytes(stdout, arr, len); + printf("\n"); +} + +/** private parser error trace function */ +void vlog_err(const char *msg, va_list vl) +{ + vfprintf(stderr, msg, vl); +} + +/** parser error trace function, error code is returned to shorten client code */ +int log_err(int err_code, const char *msg, ...) +{ + va_list vl; + + va_start(vl, msg); + vlog_err(msg, vl); + va_end(vl); + return err_code; +} + +/** log malloc error message for given key */ +int err_malloc(const char *key) +{ + return log_err(-ENOMEM, "error: malloc failed during parsing key '%s'\n", key); +} + +/** log key not found error */ +int err_key_not_found(const char *key) +{ + return log_err(-EINVAL, "error: '%s' not found\n", key); +} + +/** error during parsing key value, possible detailed message */ +int err_key_parse(const char *key, const char *extra_msg, ...) +{ + int ret = -EINVAL; + va_list vl; + + if (extra_msg) { + log_err(ret, "error: key '%s' parsing error, ", key); + va_start(vl, extra_msg); + vlog_err(extra_msg, vl); + va_end(vl); + return log_err(ret, "\n"); + } else { + return log_err(ret, "error: key '%s' parsing error\n", key); + } +} + +/** initialize parser context before parsing */ +void parse_ctx_init(struct parse_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +/** check nothing left unparsed in given parsing context */ +int assert_everything_parsed(const toml_table_t *table, struct parse_ctx *ctx) +{ + const char *key = toml_table_key(table); + int ret = 0; + + /* toml_table_key returns NULL for global context */ + if (!key) + key = "toml"; + + /* from number of parsed fields subtract fields count in given table */ + ctx->key_cnt = toml_table_nkval(table) - ctx->key_cnt; + ctx->array_cnt = toml_table_narr(table) - ctx->array_cnt; + ctx->table_cnt = toml_table_ntab(table) - ctx->table_cnt; + + /* when any field left unparsed, then raise error */ + if (ctx->key_cnt != 0) + ret = log_err(-EINVAL, "error: %d unparsed keys left in '%s'\n", ctx->key_cnt, key); + if (ctx->array_cnt != 0) + ret = log_err(-EINVAL, "error: %d unparsed arrays left in '%s'\n", ctx->array_cnt, + key); + if (ctx->table_cnt != 0) + ret = log_err(-EINVAL, "error: %d unparsed tables left in '%s'\n", ctx->table_cnt, + key); + return ret; +} + +/** + * Parse hex value from key in given toml table + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT32_MAX value for error cases + */ +uint32_t parse_uint32_hex_key(const toml_table_t *table, struct parse_ctx *ctx, + const char *key, int64_t def, int *error) +{ + toml_raw_t raw; + char *temp_s; + uint32_t val; + int ret; + + /* look for key in given table, assign def value when key not found */ + raw = toml_raw_in(table, key); + if (!raw) { + if (def < 0 || def > UINT32_MAX) { + *error = err_key_not_found(key); + return UINT32_MAX; + } else { + *error = 0; + return (uint32_t)def; + } + } + /* there is not build-in support for hex numbers in toml, so read then as string */ + ret = toml_rtos(raw, &temp_s); + if (ret < 0) { + *error = err_key_parse(key, NULL); + return UINT32_MAX; + } + errno = 0; + val = strtoul(temp_s, 0, 0); + + free(temp_s); + /* assert parsing success and value is within uint32_t range */ + if (errno != 0) { + *error = err_key_parse(key, "can't convert hex value"); + return UINT32_MAX; + } + + /* set success error code and increment parsed key counter */ + *error = 0; + ++ctx->key_cnt; + return (uint32_t)val; +} + +/** + * Parse hex value from key in given toml table + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT16_MAX value for error cases + */ +uint16_t parse_uint16_hex_key(const toml_table_t *table, struct parse_ctx *ctx, + const char *key, int64_t def, int *error) +{ + toml_raw_t raw; + char *temp_s; + unsigned long val; /* strtoul return type */ + int ret; + + raw = toml_raw_in(table, key); + if (!raw) { + if (def < 0 || def > UINT16_MAX) { + *error = err_key_not_found(key); + return UINT16_MAX; + } + *error = 0; + return (uint16_t)def; + } + + ret = toml_rtos(raw, &temp_s); + if (ret < 0) { + *error = err_key_parse(key, NULL); + return UINT16_MAX; + } + errno = 0; + val = strtoul(temp_s, 0, 0); + free(temp_s); + + if (errno != 0) { + *error = err_key_parse(key, "can't convert hex value"); + return UINT16_MAX; + } + if (val > UINT16_MAX) { + *error = log_err(-ERANGE, "key %s out of uint16_t hex range", key); + return UINT16_MAX; + } + + *error = 0; + ++ctx->key_cnt; + return (uint16_t)val; +} + +/** + * Parse hex value from key in given toml table + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT8_MAX value for error cases + */ +uint8_t parse_uint8_hex_key(const toml_table_t *table, struct parse_ctx *ctx, + const char *key, int64_t def, int *error) +{ + toml_raw_t raw; + char *temp_s; + unsigned long val; + int ret; + + raw = toml_raw_in(table, key); + if (!raw) { + if (def < 0 || def > UINT8_MAX) { + *error = err_key_not_found(key); + return UINT8_MAX; + } + *error = 0; + return (uint8_t)def; + } + + ret = toml_rtos(raw, &temp_s); + if (ret < 0) { + *error = err_key_parse(key, NULL); + return UINT8_MAX; + } + errno = 0; + val = strtoul(temp_s, 0, 0); + free(temp_s); + + if (errno != 0) { + *error = err_key_parse(key, "can't convert hex value"); + return UINT8_MAX; + } + if (val > UINT8_MAX) { + *error = log_err(-ERANGE, "key %s out of uint8_t hex range", key); + return UINT8_MAX; + } + + *error = 0; + ++ctx->key_cnt; + return (uint8_t)val; +} + +/** + * Parse integer value from key in given toml table + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT32_MAX value for error cases + */ +uint32_t parse_uint32_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + int64_t def, int *error) +{ + toml_raw_t raw; + int64_t val; + int ret; + + /* look for key in given table, assign def value when key not found */ + raw = toml_raw_in(table, key); + if (!raw) { + if (def < 0 || def > UINT32_MAX) { + *error = err_key_not_found(key); + return UINT32_MAX; + } else { + *error = 0; + return (uint32_t)def; + } + } + /* there is build-in support for integer numbers in toml, so use lib function */ + ret = toml_rtoi(raw, &val); + if (ret < 0) { + *error = err_key_parse(key, "can't convert to integer value"); + return UINT32_MAX; + } + /* assert value is within uint32_t range */ + if (val < 0 || val > UINT32_MAX) { + *error = log_err(-ERANGE, "key %s out of uint32_t range", key); + return UINT32_MAX; + } + /* set success error code and increment parsed key counter */ + *error = 0; + ++ctx->key_cnt; + return (uint32_t)val; +} + +/** + * Parse unsigned 8-bit integer value from key in given toml table. + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param def is default value or -1 when value don't have default value + * @param error code, 0 when success + * @return default, parsed, or UINT8_MAX value for error cases + */ +uint8_t parse_uint8_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + int64_t def, int *error) +{ + toml_raw_t raw; + int64_t val; + int ret; + + raw = toml_raw_in(table, key); + if (!raw) { + if (def < 0 || def > UINT8_MAX) { + *error = err_key_not_found(key); + return UINT8_MAX; + } else { + *error = 0; + return (uint8_t)def; + } + } + + ret = toml_rtoi(raw, &val); + if (ret < 0) { + *error = err_key_parse(key, "can't convert to integer value"); + return UINT8_MAX; + } + if (val < 0 || val > UINT8_MAX) { + *error = log_err(-ERANGE, "key %s out of uint8_t range", key); + return UINT8_MAX; + } + + *error = 0; + ++ctx->key_cnt; + return (uint8_t)val; +} + +/** + * Parse string value from key in given toml table to uint8_t array. The + * destination is NOT a string because it is padded with zeros if and + * only if there is some capacity left. For string destinations use + * parse_str_key(). + * + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param dst uint8_t[] destination + * @param capacity dst array size + * @param error code, 0 when success + */ +void parse_printable_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + uint8_t *dst, int capacity, int *error) +{ + toml_raw_t raw; + char *temp_s; + int len; + int ret; + + /* look for key in given table */ + raw = toml_raw_in(table, key); + if (!raw) { + *error = err_key_not_found(key); + return; + } + /* read string from toml, theres malloc inside toml_rtos() */ + ret = toml_rtos(raw, &temp_s); + if (ret < 0) { + *error = err_key_parse(key, NULL); + return; + } + + len = strlen(temp_s); + if (len > capacity) { + if (len > 20) { + static const char ellipsis[] = "..."; + const size_t el_len = sizeof(ellipsis); + + strncpy(temp_s + 20 - el_len, ellipsis, el_len); + } + + *error = log_err(-EINVAL, "Too long input '%s' for key '%s' (%d > %d) characters\n", + temp_s, key, len, capacity); + free(temp_s); + return; + } + + /* copy string to dst, pad with zeros the space left if any */ + strncpy((char *)dst, temp_s, capacity); + free(temp_s); + /* update parsing context */ + ++ctx->key_cnt; + *error = 0; +} + +/** + * Parse string value from key in given toml table to given + * char[]. Destination is padded with zeros. As the only difference with + * parse_printable_key(), dst is guaranteed to be null-terminated when + * there is no error because the last destination byte is reserved for + * that. + * + * @param table toml table where key is specified + * @param ctx parsing context, key counter will be incremented after successful key parse + * @param key field name + * @param dst char[] destination + * @param capacity dst array size including null termination. + * @param error code, 0 when success + */ +void parse_str_key(const toml_table_t *table, struct parse_ctx *ctx, const char *key, + char *dst, int capacity, int *error) +{ + parse_printable_key(table, ctx, key, (uint8_t *)dst, capacity - 1, error); + if (*error) /* return immediately to help forensics */ + return; + dst[capacity - 1] = 0; +} + +void parse_uuid(const char *buf, void *uuid) +{ + struct uuid_t id; + uint32_t d[11]; + + const int parsed_uuid_fields = + sscanf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", &d[0], + &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], &d[8], &d[9], &d[10]); + + assert(parsed_uuid_fields == 11); + + id.d0 = d[0]; + id.d1 = (uint16_t)d[1]; + id.d2 = (uint16_t)d[2]; + id.d3 = (uint8_t)d[3]; + id.d4 = (uint8_t)d[4]; + id.d5 = (uint8_t)d[5]; + id.d6 = (uint8_t)d[6]; + id.d7 = (uint8_t)d[7]; + id.d8 = (uint8_t)d[8]; + id.d9 = (uint8_t)d[9]; + id.d10 = (uint8_t)d[10]; + + memcpy(uuid, &id, sizeof(id)); +} + +/** version is stored as toml array with integer number, something like: + * "version = [1, 8]" + */ +int parse_version(toml_table_t *toml, int64_t version[2]) +{ + toml_array_t *arr; + toml_raw_t raw; + int ret; + int i; + + /* check "version" key */ + arr = toml_array_in(toml, "version"); + if (!arr) + return err_key_not_found("version"); + if (toml_array_type(arr) != 'i' || toml_array_nelem(arr) != 2 || + toml_array_kind(arr) != 'v') + return err_key_parse("version", "wrong array type or length != 2"); + + /* parse "version" array elements */ + for (i = 0; i < 2; ++i) { + raw = toml_raw_at(arr, i); + if (raw == 0) + return err_key_parse("version", NULL); + ret = toml_rtoi(raw, &version[i]); + if (ret < 0) + return err_key_parse("version", "can't convert element to integer"); + } + return 0; +} diff --git a/tools/rimage/tomlc99 b/tools/rimage/tomlc99 new file mode 160000 index 000000000000..e3a03f5ec7d8 --- /dev/null +++ b/tools/rimage/tomlc99 @@ -0,0 +1 @@ +Subproject commit e3a03f5ec7d8d33be705c5ce8a632d998ce9b4d1 diff --git a/tools/scripts/cross-arch64.cmake b/tools/scripts/cross-arch64.cmake new file mode 100644 index 000000000000..a9721f4ec13c --- /dev/null +++ b/tools/scripts/cross-arch64.cmake @@ -0,0 +1,23 @@ +# +# CMake Toolchain file for crosscompiling on arm64 +# +# This can be used when running cmake in the following way: +# cd build/ +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../scripts/cross-arch64.cmake +# + +# Target operating system name. +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +# Name of C compiler. +set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++") + +# Adjust the default behavior of the FIND_XXX() commands: +# search programs in the host environment only. +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# Search headers and libraries in the target environment only. +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/tools/sof_ri_info/sof_ri_info.py b/tools/sof_ri_info/sof_ri_info.py old mode 100644 new mode 100755 index d3d3b120b4c3..be78d7aebf50 --- a/tools/sof_ri_info/sof_ri_info.py +++ b/tools/sof_ri_info/sof_ri_info.py @@ -12,13 +12,24 @@ # pylint: disable=too-few-public-methods # pylint: disable=too-many-arguments # pylint: disable=too-many-instance-attributes +# pylint: disable=invalid-name +# pylint: disable=missing-function-docstring import sys import argparse import struct +import io +import pathlib +import hashlib + +# Required for open(pathlib) +assert sys.version_info >= (3, 6) + +# To extend the DSP memory layout list scroll down to DSP_MEM_SPACE_EXT # Public keys signatures recognized by parse_css_manifest() # - add a new one as array of bytes and append entry to KNOWN_KEYS below. +# you can use --full_bytes to dump the bytes in below format APL_INTEL_PROD_KEY = bytes([0x1f, 0xf4, 0x58, 0x74, 0x64, 0xd4, 0xae, 0x90, 0x03, 0xb6, 0x71, 0x0d, 0xb5, 0xaf, 0x6d, 0xd6, @@ -119,6 +130,433 @@ 0x5, 0x76, 0x1b, 0x44, 0x55, 0x75, 0xd9, 0x32, 0x35, 0xf1, 0xec, 0x4d, 0x93, 0x73, 0xe6, 0xc4]) +JSL_INTEL_PROD_KEY = bytes([0x6f, 0xe4, 0xd5, 0xc9, 0x52, 0xf4, 0x01, 0xc1, + 0x89, 0xc7, 0x2b, 0x16, 0x9b, 0xe6, 0x5d, 0x8e, + 0x91, 0x28, 0x63, 0x16, 0x4f, 0x7b, 0x18, 0x6e, + 0xa7, 0x89, 0x0c, 0xea, 0x24, 0x62, 0xc7, 0x94, + 0x75, 0x43, 0xfd, 0x6d, 0xa8, 0x67, 0x47, 0x36, + 0x50, 0xaf, 0x37, 0x46, 0x15, 0x82, 0x45, 0x4a, + 0xa3, 0x2e, 0xae, 0xa4, 0x1f, 0x92, 0x67, 0x4b, + 0x5e, 0x67, 0x7e, 0x02, 0xfc, 0x18, 0x6f, 0x68, + 0x0d, 0xe3, 0xc1, 0x00, 0xdf, 0xea, 0xed, 0x9f, + 0xdc, 0x61, 0xa0, 0xfd, 0x36, 0x61, 0x84, 0xa7, + 0x8c, 0x2a, 0x4b, 0x2c, 0x2d, 0xed, 0x8d, 0x0b, + 0x35, 0xe9, 0x79, 0x59, 0x3f, 0x22, 0xdc, 0x3c, + 0xd4, 0x43, 0x32, 0x22, 0xf0, 0xda, 0x0d, 0xa1, + 0x3a, 0xec, 0x47, 0x87, 0x5e, 0xa0, 0xd2, 0xaa, + 0xf8, 0x1c, 0x61, 0x08, 0x05, 0x64, 0xb4, 0xa8, + 0x75, 0xc8, 0x20, 0x34, 0xbf, 0x04, 0x10, 0x75, + 0x8c, 0xb7, 0x6d, 0x49, 0xde, 0x3d, 0x3c, 0x66, + 0x08, 0xfe, 0x67, 0xc8, 0x77, 0x04, 0x7c, 0xa5, + 0xf0, 0x9e, 0xe7, 0x5e, 0x70, 0xbf, 0xde, 0xf1, + 0xcb, 0x1c, 0xc0, 0x84, 0x4a, 0x89, 0x76, 0x37, + 0x4f, 0xad, 0x3b, 0x8f, 0x04, 0x91, 0xd0, 0x1b, + 0x0b, 0xa8, 0x20, 0x6e, 0x1e, 0x97, 0x1e, 0xff, + 0x1f, 0xef, 0xde, 0x7a, 0xd7, 0x93, 0x3c, 0xa9, + 0x46, 0xe5, 0x74, 0x66, 0x9c, 0x85, 0xfa, 0xaa, + 0x4a, 0xe4, 0x39, 0xc5, 0x33, 0xbb, 0x8e, 0xca, + 0x1f, 0xd9, 0x4c, 0xbc, 0xcd, 0x7c, 0xa1, 0x30, + 0xdb, 0x15, 0xed, 0xa1, 0x24, 0x9d, 0xcb, 0xf0, + 0xbe, 0xeb, 0x92, 0x60, 0xb0, 0xab, 0x60, 0xa0, + 0xcc, 0xd8, 0x04, 0xf9, 0xf1, 0xa0, 0x04, 0x98, + 0x6a, 0x20, 0xd8, 0x86, 0xff, 0xd4, 0x9d, 0x09, + 0xa1, 0x22, 0xce, 0x0a, 0x3e, 0x21, 0x27, 0xcd, + 0xf8, 0x7c, 0xb0, 0x09, 0x09, 0xc2, 0xa3, 0xcc]) + +TGL_INTEL_PROD_KEY = bytes([0xd3, 0x72, 0x92, 0x99, 0x4e, 0xb9, 0xcd, 0x67, + 0x41, 0x86, 0x16, 0x77, 0x35, 0xa1, 0x34, 0x85, + 0x43, 0x96, 0xd9, 0x53, 0x76, 0x4d, 0xd0, 0x63, + 0x17, 0x72, 0x96, 0xee, 0xf6, 0xdc, 0x50, 0x53, + 0x4b, 0x4, 0xaa, 0xfe, 0x3d, 0xd7, 0x21, 0x29, + 0x79, 0x6, 0x76, 0xee, 0xb3, 0x70, 0x23, 0x8, + 0x26, 0xa8, 0x83, 0x3d, 0x70, 0x13, 0x9d, 0x65, + 0xcb, 0xd5, 0xc6, 0xf, 0x92, 0x93, 0x38, 0x29, + 0x19, 0xa6, 0x7c, 0xbf, 0xf1, 0x76, 0x75, 0x2, + 0x9e, 0x32, 0x8f, 0x1f, 0x5, 0xa6, 0x2d, 0x89, + 0x6d, 0x38, 0xba, 0x38, 0xd, 0xf1, 0xe9, 0xe8, + 0xed, 0xf7, 0x6c, 0x20, 0x8d, 0x91, 0xc, 0xf8, + 0xdd, 0x9a, 0x56, 0xd3, 0xf7, 0xbf, 0x3c, 0xda, + 0xc8, 0x5d, 0xb, 0xef, 0x20, 0x5a, 0xc1, 0x5f, + 0x91, 0x94, 0xee, 0x90, 0xb8, 0xfc, 0x2c, 0x31, + 0x75, 0xc3, 0x7e, 0x86, 0xf6, 0x4f, 0x45, 0x4c, + 0x64, 0xe1, 0xe9, 0xe5, 0xcd, 0xf0, 0xec, 0xef, + 0xa7, 0xbd, 0x31, 0x62, 0x40, 0xa8, 0x48, 0x52, + 0xd5, 0x23, 0xce, 0x4, 0x45, 0x2f, 0xb, 0x3d, + 0xe0, 0x7a, 0xcf, 0xe5, 0x2a, 0x45, 0x5e, 0x91, + 0x1d, 0x41, 0xa7, 0x40, 0x85, 0x34, 0xe, 0x50, + 0x45, 0x59, 0xbf, 0xd, 0xa6, 0x6, 0xf9, 0xf6, + 0xce, 0xa2, 0x76, 0x72, 0x0, 0x62, 0x73, 0x37, + 0x1a, 0xbe, 0xd2, 0xe3, 0x1b, 0x7b, 0x26, 0x7b, + 0x32, 0xaa, 0x79, 0xed, 0x59, 0x23, 0xb6, 0xdb, + 0x9f, 0x3c, 0x3d, 0x65, 0xf3, 0xbb, 0x4b, 0xb4, + 0x97, 0xaa, 0x2a, 0xae, 0x48, 0xf4, 0xc5, 0x59, + 0x8d, 0x82, 0x4a, 0xb, 0x15, 0x4d, 0xd5, 0x4, + 0xa6, 0xc1, 0x2d, 0x83, 0x19, 0xc4, 0xc6, 0x49, + 0xba, 0x0, 0x1b, 0x2b, 0x70, 0xb, 0x26, 0x7c, + 0xb8, 0x94, 0x18, 0xe4, 0x9a, 0xf6, 0x5a, 0x68, + 0x9d, 0x44, 0xd2, 0xed, 0xd5, 0x67, 0x42, 0x47, + 0x5f, 0x73, 0xc5, 0xa7, 0xe5, 0x87, 0xa9, 0x4d, + 0xae, 0xc1, 0xb, 0x2c, 0x46, 0x16, 0xd7, 0x4e, + 0xf0, 0xdc, 0x61, 0x58, 0x51, 0xb1, 0x2, 0xbc, + 0xca, 0x17, 0xb1, 0x1a, 0xa, 0x96, 0x3b, 0x25, + 0x1c, 0x63, 0x56, 0x65, 0x20, 0x6e, 0x1b, 0x21, + 0xb1, 0x94, 0x7a, 0xf5, 0xbf, 0x83, 0x21, 0x86, + 0x38, 0xf1, 0x66, 0x1a, 0xa, 0x75, 0x73, 0xa, + 0xe, 0xc7, 0x64, 0x68, 0xc7, 0xf9, 0xc3, 0x4a, + 0x73, 0xfb, 0x86, 0xa5, 0x7, 0xb8, 0x8b, 0xf0, + 0xa3, 0x3b, 0xa9, 0x8f, 0x33, 0xa7, 0xce, 0xfe, + 0x36, 0x60, 0xbd, 0x5, 0xf0, 0x9a, 0x30, 0xe5, + 0xe1, 0x43, 0x25, 0x1c, 0x1, 0x4a, 0xd4, 0x23, + 0x1e, 0x8f, 0xb9, 0xdd, 0xd8, 0xb2, 0x24, 0xef, + 0x36, 0x4d, 0x5b, 0x8f, 0xba, 0x4f, 0xe9, 0x48, + 0xe7, 0x51, 0x42, 0x59, 0x56, 0xa, 0x1c, 0xf, + 0x5d, 0x62, 0x4a, 0x80, 0x96, 0x31, 0xf8, 0xb5]) + +EHL_INTEL_PROD_KEY = bytes([0xb5, 0xb0, 0xe2, 0x25, 0x3d, 0xc7, 0x54, 0x10, + 0xde, 0x3c, 0xc9, 0x24, 0x97, 0x74, 0xbc, 0x02, + 0x7d, 0x0b, 0xd6, 0x61, 0x2e, 0x35, 0x65, 0xed, + 0x78, 0xf6, 0x85, 0x73, 0x1f, 0x8c, 0xda, 0x8f, + 0x50, 0x79, 0xc7, 0x0c, 0x9e, 0xb4, 0x09, 0x3b, + 0xfc, 0x2e, 0x4e, 0xf3, 0x46, 0xfe, 0x3f, 0x20, + 0x9d, 0x8d, 0xf6, 0x3e, 0xc3, 0x46, 0x92, 0xf9, + 0xce, 0xbb, 0x7d, 0x0b, 0xb3, 0x45, 0x35, 0x76, + 0xbe, 0x19, 0x87, 0x21, 0x6c, 0x79, 0xfa, 0xf4, + 0xc8, 0x8e, 0x07, 0x26, 0x03, 0x0d, 0xe9, 0xe3, + 0x1e, 0x61, 0x7c, 0xd1, 0x45, 0x10, 0x61, 0x1c, + 0x79, 0x3f, 0x10, 0xa9, 0x42, 0x60, 0x2c, 0x7a, + 0x7a, 0x89, 0x1b, 0x54, 0xda, 0x0e, 0x54, 0x08, + 0x30, 0x0f, 0x6e, 0x37, 0xea, 0xb7, 0x58, 0xa0, + 0xaf, 0x4a, 0x94, 0x2c, 0x43, 0x50, 0x74, 0xed, + 0x16, 0xdc, 0x11, 0xa1, 0xd3, 0x6e, 0x54, 0xa6, + 0x56, 0xf9, 0x40, 0x8c, 0x3f, 0xa3, 0x74, 0xae, + 0x4f, 0x48, 0xc8, 0x79, 0x30, 0x5a, 0x99, 0x79, + 0x26, 0xe1, 0x52, 0x9b, 0xfe, 0x9e, 0xaf, 0x96, + 0xcc, 0xe6, 0x9a, 0x53, 0x2e, 0xe4, 0x40, 0xcc, + 0xad, 0x19, 0x8e, 0x23, 0x53, 0x63, 0xc8, 0xfd, + 0x96, 0xeb, 0x27, 0x9b, 0x3e, 0x49, 0x0d, 0x90, + 0xb0, 0x67, 0xb4, 0x05, 0x4a, 0x55, 0x5b, 0xb0, + 0xa5, 0x68, 0xb8, 0x60, 0xa4, 0x81, 0x6a, 0x3e, + 0x8c, 0xbc, 0x29, 0xcd, 0x85, 0x45, 0x3c, 0xf4, + 0x86, 0xf8, 0x9b, 0x69, 0xb5, 0xc5, 0xb9, 0xaa, + 0xc8, 0xed, 0x7d, 0x70, 0x45, 0xb6, 0xf6, 0x5b, + 0x48, 0x62, 0xf6, 0x68, 0xe8, 0xdd, 0x79, 0xda, + 0xb0, 0xe9, 0x3c, 0x8f, 0x01, 0x92, 0x80, 0x73, + 0x89, 0x7d, 0x9a, 0xaf, 0x31, 0x85, 0x75, 0x7c, + 0x89, 0xf3, 0x6c, 0x77, 0x95, 0x5b, 0xa9, 0xc5, + 0xe1, 0x33, 0xe0, 0x44, 0x81, 0x7e, 0x72, 0xa5, + 0xbb, 0x3d, 0x40, 0xb7, 0xc9, 0x77, 0xd8, 0xc3, + 0xe3, 0xef, 0x42, 0xae, 0x57, 0x91, 0x63, 0x0c, + 0x26, 0xac, 0x5e, 0x10, 0x51, 0x28, 0xe6, 0x61, + 0xad, 0x4d, 0xc4, 0x93, 0xb2, 0xe0, 0xb4, 0x31, + 0x60, 0x5a, 0x97, 0x0e, 0x80, 0x86, 0x91, 0xc9, + 0xcd, 0xfc, 0x97, 0xc3, 0x78, 0xbd, 0xca, 0xce, + 0xd3, 0x96, 0xee, 0x75, 0x81, 0xe0, 0x8b, 0x45, + 0x8e, 0x20, 0x4b, 0x98, 0x31, 0x0f, 0xf9, 0x66, + 0xb3, 0x04, 0xb7, 0x0d, 0xde, 0x68, 0x1e, 0x2a, + 0xe4, 0xec, 0x45, 0x2a, 0x0a, 0x24, 0x81, 0x82, + 0xcb, 0x86, 0xa0, 0x61, 0x7f, 0xe7, 0x96, 0x84, + 0x4b, 0x30, 0xc4, 0x7d, 0x5c, 0x1b, 0x2c, 0x1e, + 0x66, 0x68, 0x71, 0x1d, 0x39, 0x6c, 0x23, 0x07, + 0x6d, 0xf3, 0x3e, 0x64, 0xc3, 0x03, 0x97, 0x84, + 0x14, 0xd1, 0xf6, 0x50, 0xf4, 0x32, 0x5d, 0xae, + 0xad, 0x23, 0x46, 0x0c, 0x9f, 0xfc, 0x3e, 0xb9]) + +ADL_INTEL_PROD_KEY = bytes([0xd3, 0x42, 0x11, 0x78, 0xf4, 0x4a, 0xa5, 0x85, + 0x4b, 0x78, 0x7a, 0x9b, 0xbd, 0x71, 0xc1, 0x84, + 0x0f, 0x54, 0xe4, 0x07, 0x47, 0x65, 0x9e, 0xdc, + 0x79, 0x85, 0x14, 0x52, 0x3c, 0xa1, 0xe1, 0x06, + 0x4c, 0x25, 0x31, 0x56, 0xb2, 0xba, 0x7c, 0xfd, + 0x3d, 0x2d, 0x87, 0x28, 0xf4, 0xb3, 0x19, 0xe9, + 0x38, 0xd9, 0x78, 0x3c, 0x45, 0x7d, 0xfa, 0x9c, + 0x58, 0x3a, 0xaf, 0xda, 0x4b, 0xe1, 0x94, 0xcc, + 0xb0, 0xdb, 0x41, 0x5d, 0x5f, 0xd5, 0xf9, 0xeb, + 0x53, 0xcc, 0xd7, 0x14, 0xab, 0xdb, 0x13, 0x20, + 0x26, 0x59, 0xc0, 0x7e, 0xaa, 0x14, 0x7f, 0x80, + 0x0f, 0x73, 0x9a, 0xb2, 0xc4, 0x8c, 0x8b, 0x0d, + 0x56, 0xd0, 0x7a, 0xd1, 0x52, 0xca, 0xaa, 0x96, + 0x28, 0x8e, 0x98, 0xad, 0x6e, 0xf6, 0x36, 0x1a, + 0x6e, 0xdd, 0xba, 0x4f, 0xd5, 0xb1, 0x06, 0xe6, + 0xc8, 0x5a, 0x06, 0x93, 0x06, 0x51, 0xd1, 0x44, + 0xe1, 0x87, 0x54, 0x49, 0x2f, 0xfd, 0xa5, 0x2b, + 0x86, 0xbe, 0xea, 0x59, 0xa9, 0x09, 0xf5, 0x1f, + 0x01, 0xa4, 0x7a, 0x0b, 0xd9, 0xd0, 0x73, 0x13, + 0x1a, 0x4a, 0xb3, 0xd5, 0x4d, 0x37, 0x06, 0x6b, + 0x84, 0x48, 0xce, 0xbb, 0x0b, 0x81, 0x71, 0xa1, + 0x97, 0x3f, 0x95, 0x64, 0x6b, 0xfd, 0xb0, 0x37, + 0x4e, 0xfd, 0xa5, 0x0b, 0x08, 0xb3, 0xd0, 0xbc, + 0xbe, 0x27, 0x64, 0x72, 0x89, 0xc7, 0xc8, 0x58, + 0x7e, 0x83, 0x8a, 0x0f, 0xf5, 0x56, 0xa7, 0x53, + 0x06, 0x24, 0xa1, 0x9e, 0x2c, 0xd2, 0x35, 0x86, + 0xdf, 0x6d, 0x68, 0xdd, 0x7a, 0x95, 0xbf, 0xf5, + 0x7a, 0xa4, 0x52, 0xf9, 0xc2, 0x03, 0xa8, 0xa1, + 0x63, 0x38, 0x1e, 0xc9, 0x2b, 0x1d, 0xcb, 0x55, + 0x04, 0x4b, 0xed, 0x53, 0x06, 0xb4, 0x96, 0xc8, + 0x84, 0x73, 0x66, 0x66, 0xbe, 0xb9, 0xca, 0xfc, + 0x8b, 0x81, 0xe2, 0xbd, 0x0b, 0x8e, 0xa3, 0x93, + 0x98, 0x82, 0x1d, 0x8e, 0x99, 0xf7, 0x29, 0x48, + 0x3d, 0xeb, 0x70, 0xda, 0x02, 0x6e, 0x2e, 0xc7, + 0x6c, 0x60, 0x7c, 0x3d, 0xff, 0x78, 0xdc, 0x95, + 0x4b, 0xec, 0x89, 0x7a, 0x97, 0x61, 0x32, 0x7e, + 0x00, 0x59, 0x1d, 0x1d, 0xbe, 0x3a, 0x55, 0xb8, + 0x2e, 0xa1, 0xb4, 0xf8, 0x6c, 0xad, 0x92, 0xbc, + 0x47, 0x27, 0xe8, 0x0e, 0xad, 0x80, 0xca, 0xca, + 0xb2, 0x92, 0x71, 0xaa, 0x19, 0x2b, 0x3a, 0x4e, + 0xbb, 0x01, 0x76, 0x9b, 0x6d, 0x42, 0xd3, 0xc4, + 0x2f, 0x29, 0x8f, 0x3f, 0xd2, 0xd1, 0xd9, 0xcb, + 0x48, 0xb3, 0x99, 0xce, 0x78, 0xfa, 0x29, 0x69, + 0xdc, 0x55, 0xde, 0xcf, 0xc0, 0xc9, 0x2f, 0xbe, + 0x67, 0x22, 0xb4, 0x02, 0x38, 0x18, 0xbd, 0xa6, + 0x98, 0xcf, 0xc9, 0x42, 0x8e, 0xdd, 0xbd, 0xa0, + 0xcc, 0x17, 0xb2, 0x12, 0xd3, 0x32, 0x0f, 0x1e, + 0x0c, 0x8e, 0x94, 0x8b, 0x7c, 0xbe, 0x79, 0xeb]) + +ADL_N_INTEL_PROD_KEY = bytes([0xe1, 0x71, 0x6a, 0xed, 0xfa, 0x0b, 0x75, 0xb3, + 0xd3, 0x1a, 0x7b, 0xd9, 0xb8, 0x56, 0x43, 0x90, + 0x81, 0x9e, 0x6e, 0x4f, 0xb6, 0x94, 0xa2, 0x44, + 0x3c, 0xd7, 0x80, 0x98, 0x54, 0x48, 0xa2, 0xbb, + 0x4a, 0xd2, 0xeb, 0x25, 0x8d, 0x5b, 0x5c, 0x18, + 0x5d, 0x0c, 0xa8, 0x87, 0xb7, 0xb7, 0xec, 0xeb, + 0x49, 0xf9, 0x03, 0x14, 0x81, 0x13, 0x11, 0xe0, + 0xbb, 0x41, 0x84, 0x93, 0xa1, 0x09, 0x2e, 0xbf, + 0xa3, 0xe6, 0xc5, 0x80, 0x76, 0x86, 0x08, 0xf3, + 0x37, 0x21, 0xd6, 0xce, 0x7e, 0xf2, 0x47, 0x31, + 0xd0, 0x07, 0x6c, 0x98, 0x15, 0x1f, 0x93, 0x07, + 0x31, 0x57, 0xc6, 0x90, 0x53, 0xcf, 0x27, 0x2d, + 0x01, 0x89, 0x22, 0xc0, 0xe0, 0x00, 0x86, 0xf8, + 0x8c, 0x58, 0x94, 0x97, 0x2c, 0x09, 0x6a, 0x26, + 0xda, 0x6b, 0x0d, 0x1d, 0xcd, 0x8e, 0x7f, 0x0b, + 0xed, 0xaf, 0xeb, 0x14, 0x79, 0x8c, 0x1f, 0xec, + 0xe4, 0xc6, 0xd2, 0x39, 0x20, 0x26, 0x2b, 0xec, + 0xf3, 0x07, 0x89, 0xfd, 0x13, 0x6f, 0xa7, 0x58, + 0xe0, 0xa9, 0xb2, 0xaa, 0xab, 0x7f, 0x87, 0xfd, + 0x7c, 0xcb, 0x92, 0xc0, 0x54, 0x06, 0x46, 0xef, + 0xb0, 0xab, 0xfc, 0x52, 0xd7, 0x18, 0x82, 0x18, + 0xa2, 0x4a, 0xa6, 0xe8, 0xf6, 0x1e, 0xbe, 0xcd, + 0xf3, 0x94, 0x4f, 0xd8, 0xd8, 0x94, 0xa8, 0x26, + 0xb2, 0x25, 0x28, 0x12, 0x33, 0x07, 0x69, 0xf5, + 0x55, 0x2c, 0xcd, 0x94, 0x83, 0x42, 0xe3, 0x4e, + 0xf2, 0xe8, 0x49, 0x0a, 0x40, 0xe9, 0x03, 0x1a, + 0x05, 0x34, 0x45, 0xab, 0x82, 0x1f, 0xad, 0x0d, + 0x5d, 0x24, 0x08, 0x25, 0x49, 0x7d, 0xaa, 0x06, + 0x30, 0x3e, 0x25, 0xf4, 0x47, 0x94, 0xba, 0x20, + 0xd2, 0xc2, 0x1d, 0x20, 0x83, 0x3f, 0xb1, 0xc7, + 0x9c, 0x69, 0x05, 0x82, 0xf4, 0x9e, 0x70, 0x8e, + 0x06, 0x67, 0x9d, 0xe2, 0x8a, 0x25, 0x86, 0x95, + 0xaf, 0xe0, 0x41, 0x56, 0x68, 0x84, 0xa5, 0x91, + 0xdb, 0x8e, 0xc6, 0xa7, 0xd6, 0xcb, 0xb3, 0x1f, + 0x46, 0x53, 0xe5, 0x52, 0x4d, 0xb7, 0x3f, 0x0d, + 0x98, 0x13, 0x80, 0xc0, 0xd5, 0x9f, 0x21, 0x55, + 0xcf, 0x38, 0x1e, 0xcf, 0x4f, 0x58, 0xf7, 0x68, + 0x98, 0xda, 0x15, 0xd4, 0x54, 0x89, 0xea, 0xdf, + 0x52, 0x98, 0x97, 0x92, 0xd8, 0xcc, 0x4b, 0xdc, + 0xf7, 0x1b, 0xc4, 0xe5, 0xdb, 0x5d, 0xe7, 0xae, + 0x9e, 0x00, 0x77, 0x32, 0x4c, 0x5f, 0x3b, 0x11, + 0xa0, 0xcf, 0xbe, 0xc3, 0xe6, 0x84, 0xd8, 0xa6, + 0x58, 0x36, 0x90, 0xbc, 0xc5, 0x98, 0xdc, 0xff, + 0x48, 0x2f, 0xe7, 0xdd, 0x26, 0xa6, 0x4d, 0x15, + 0xe6, 0x39, 0x7e, 0x41, 0xd2, 0x7d, 0xb6, 0x8f, + 0xf8, 0xec, 0x54, 0xb0, 0xec, 0xad, 0x0c, 0x30, + 0x7b, 0x6f, 0x9c, 0x5a, 0xe1, 0x92, 0xf7, 0x48, + 0x63, 0x32, 0xad, 0xad, 0xe3, 0x34, 0x59, 0xcc]) + +MTL_INTEL_PROD_KEY = bytes([ + 0xf3, 0x23, 0x78, 0xe7, 0xeb, 0x85, 0x31, 0xd8, + 0xa3, 0x2e, 0xf6, 0x44, 0xb8, 0x0e, 0x0f, 0xc7, + 0xbd, 0xe0, 0x6a, 0xd4, 0xb5, 0x2a, 0xbd, 0x8d, + 0x54, 0x31, 0x00, 0x26, 0xfb, 0x70, 0x09, 0x87, + 0xf9, 0x50, 0x02, 0x78, 0x2f, 0x66, 0xe4, 0x35, + 0xa3, 0xa4, 0x62, 0x12, 0x53, 0x3e, 0x46, 0xc2, + 0x03, 0xd2, 0x87, 0x45, 0x4e, 0x53, 0x89, 0x2f, + 0x65, 0x2d, 0x6e, 0x61, 0x9f, 0x1c, 0x4f, 0x0c, + 0xb7, 0x8f, 0xfc, 0xee, 0x8b, 0x36, 0x57, 0x6c, + 0x87, 0xa1, 0xee, 0x34, 0x15, 0x05, 0xed, 0x42, + 0x46, 0x3b, 0x4c, 0x1a, 0x75, 0xf7, 0xa8, 0xe9, + 0xe0, 0x0e, 0x1c, 0x70, 0x68, 0x8e, 0x1a, 0xbb, + 0xcb, 0xa7, 0xa1, 0xef, 0x75, 0xad, 0x91, 0x0b, + 0xd4, 0x23, 0xbc, 0xc3, 0x0b, 0xa7, 0x5c, 0xfe, + 0xbf, 0x71, 0x31, 0x00, 0xa9, 0xda, 0xbe, 0xaf, + 0x2d, 0x26, 0x60, 0x8a, 0x99, 0x47, 0x89, 0x94, + 0x70, 0xfe, 0xd4, 0x05, 0x0a, 0x3d, 0xe5, 0x82, + 0xa6, 0xf4, 0x16, 0x94, 0xca, 0x36, 0x0a, 0x37, + 0x5c, 0xc9, 0xef, 0xa1, 0xf0, 0x20, 0x61, 0x66, + 0xac, 0xfe, 0x60, 0x85, 0x51, 0x31, 0xad, 0x60, + 0x7a, 0x1b, 0x0a, 0x5d, 0x18, 0x04, 0x98, 0x52, + 0xa5, 0x1a, 0x13, 0x1c, 0x4b, 0x66, 0xfe, 0x5e, + 0x09, 0x03, 0x00, 0x6c, 0x7d, 0xee, 0xce, 0xb5, + 0x77, 0xe5, 0x3d, 0xcf, 0x0f, 0x45, 0xa8, 0x85, + 0x4d, 0xdb, 0x70, 0x1d, 0xc1, 0xda, 0xf4, 0x36, + 0x3e, 0x3e, 0x78, 0x9e, 0x50, 0x75, 0xf7, 0x9c, + 0x0b, 0x32, 0xe1, 0x9e, 0x29, 0x42, 0x19, 0x43, + 0x0d, 0x5b, 0xae, 0x48, 0x3f, 0x95, 0xc7, 0x5a, + 0x73, 0x30, 0xf1, 0xb5, 0xa4, 0x4f, 0x4b, 0xed, + 0x3c, 0xa3, 0xb6, 0xde, 0xab, 0x5f, 0xf5, 0xf8, + 0xd9, 0x4d, 0x5b, 0x98, 0xdf, 0x1c, 0x0c, 0xbf, + 0x4f, 0x2d, 0xd2, 0x62, 0x74, 0x66, 0xe4, 0x71, + 0x09, 0x8e, 0xcc, 0xcf, 0xde, 0x3c, 0x9b, 0x02, + 0x16, 0x26, 0xf4, 0x20, 0x25, 0x6c, 0x07, 0x16, + 0x2e, 0x2e, 0x2e, 0xa5, 0x2a, 0x69, 0x66, 0xb1, + 0x95, 0x68, 0x13, 0x5a, 0x70, 0x6f, 0xc5, 0xc1, + 0x3a, 0x29, 0x4c, 0x9c, 0xe9, 0x9e, 0x7f, 0x6c, + 0x87, 0x0a, 0x0d, 0xa2, 0xdb, 0xb8, 0x38, 0x34, + 0x16, 0x3a, 0x7c, 0x18, 0x92, 0x5c, 0x69, 0x30, + 0x81, 0xd7, 0x68, 0x55, 0xd2, 0xd1, 0xcf, 0x7d, + 0x06, 0x49, 0xaf, 0x6a, 0x41, 0x3f, 0x06, 0x3b, + 0x9d, 0x9c, 0xcd, 0x4f, 0xa1, 0x08, 0xcf, 0x17, + 0x3a, 0x46, 0x9b, 0xcd, 0xe8, 0xd3, 0xc8, 0x47, + 0xe8, 0xd5, 0xc4, 0xd6, 0x30, 0xb3, 0xe0, 0x33, + 0xcf, 0x9a, 0x9f, 0x91, 0x22, 0x1e, 0x02, 0x17, + 0xe6, 0xf9, 0x35, 0xc2, 0xac, 0xb5, 0x83, 0xf7, + 0xec, 0x0a, 0x9e, 0xd8, 0x85, 0x13, 0x06, 0x87, + 0xbf, 0x42, 0x60, 0x6b, 0x12, 0xa5, 0x1e, 0xcc, +]) + +LNL_INTEL_PROD_KEY = bytes([0x1b, 0xd4, 0xbb, 0x79, 0xc2, 0x27, 0xa0, 0x59, + 0xab, 0xaf, 0x61, 0x7e, 0x7f, 0x06, 0xe9, 0x70, + 0xe2, 0xef, 0xc8, 0x4c, 0xea, 0x10, 0x71, 0xbb, + 0xa8, 0xf2, 0x4e, 0x1f, 0x56, 0x44, 0xe1, 0x7a, + 0x46, 0x2b, 0xcb, 0x6d, 0x3d, 0xc2, 0x5d, 0x84, + 0x83, 0xd7, 0xd1, 0xe7, 0x20, 0xec, 0xf6, 0x80, + 0xfc, 0x38, 0x08, 0x78, 0xac, 0x00, 0x49, 0xea, + 0xd1, 0xce, 0x1f, 0x8d, 0x37, 0xa6, 0x63, 0x4a, + 0x54, 0x6b, 0x2f, 0xd8, 0x49, 0xb0, 0x13, 0x9b, + 0x1a, 0x29, 0xee, 0xbf, 0xaa, 0x82, 0xae, 0x69, + 0xaf, 0x8e, 0xfc, 0xa6, 0x60, 0x5d, 0xd6, 0x09, + 0xe0, 0xa4, 0x75, 0x1b, 0xb1, 0xf4, 0x54, 0xc5, + 0xae, 0x92, 0x13, 0xa5, 0x66, 0xaa, 0xad, 0x95, + 0x94, 0x4f, 0xd6, 0xfb, 0x90, 0x11, 0x5f, 0xad, + 0x89, 0x33, 0x48, 0xf1, 0x2d, 0xb3, 0xc4, 0xe4, + 0xef, 0x78, 0x25, 0x54, 0xf8, 0xda, 0xf3, 0x8f, + 0x1d, 0xf4, 0x3c, 0xc9, 0xa8, 0x49, 0x94, 0x6c, + 0xb9, 0x45, 0xe0, 0x18, 0x46, 0x62, 0xd0, 0x4f, + 0x59, 0x05, 0x2e, 0x19, 0x10, 0xba, 0xad, 0x4d, + 0xc5, 0xe4, 0xab, 0x5d, 0x08, 0x00, 0x88, 0x6e, + 0xcc, 0x5f, 0x7c, 0x42, 0x7a, 0xf7, 0x53, 0x4a, + 0xa7, 0xc2, 0x32, 0xe1, 0xa3, 0x08, 0xe7, 0xc4, + 0xef, 0x38, 0x14, 0xba, 0x86, 0x79, 0xcb, 0x99, + 0xda, 0xc3, 0xf1, 0xf8, 0xe8, 0xf6, 0x21, 0x28, + 0xb1, 0xce, 0x1a, 0xed, 0xf4, 0xa0, 0x89, 0x9e, + 0x45, 0x1c, 0x6c, 0xb8, 0x07, 0x89, 0x57, 0xaf, + 0xbc, 0x67, 0xb2, 0x52, 0x7e, 0xc4, 0x0e, 0x98, + 0x91, 0xe8, 0x94, 0x40, 0x93, 0xf2, 0x0e, 0xa4, + 0x34, 0x7a, 0x37, 0xd0, 0x25, 0x1c, 0xc9, 0x0f, + 0xe1, 0x16, 0xc0, 0xdf, 0xc1, 0xa3, 0xb4, 0x91, + 0xca, 0x6a, 0xfa, 0x3a, 0x7b, 0x19, 0x31, 0xe2, + 0x41, 0xa1, 0xf9, 0x67, 0x09, 0x79, 0xf8, 0x79, + 0x1b, 0x7e, 0x3d, 0x3e, 0x41, 0xa6, 0xfb, 0x26, + 0x24, 0xfe, 0xeb, 0x19, 0xb2, 0x7e, 0x51, 0x7b, + 0x39, 0x1e, 0x94, 0x77, 0x70, 0xe3, 0xd2, 0x43, + 0xba, 0x38, 0xbf, 0xe5, 0x9f, 0x54, 0xd8, 0xac, + 0x17, 0x82, 0x5c, 0x55, 0x21, 0x28, 0xae, 0x39, + 0xac, 0xbc, 0xf0, 0xac, 0x0a, 0xe0, 0xf2, 0xfb, + 0x92, 0x5e, 0x51, 0x04, 0xad, 0xaf, 0x7a, 0x30, + 0x65, 0xf5, 0xe3, 0xa6, 0xab, 0xfc, 0x7d, 0xc6, + 0x26, 0x7b, 0x6c, 0xf1, 0x95, 0xb4, 0x7c, 0xe6, + 0x99, 0x5c, 0xf2, 0xbb, 0x35, 0x57, 0xc4, 0xa5, + 0x20, 0xc7, 0x3b, 0xbb, 0x95, 0x1d, 0xbd, 0x9c, + 0x3e, 0x78, 0x51, 0x13, 0xa0, 0x16, 0xd5, 0xbc, + 0x32, 0xc7, 0xd5, 0xc1, 0xfa, 0x8a, 0xd1, 0xc5, + 0x59, 0x75, 0x71, 0xbe, 0x93, 0x90, 0xb1, 0x4e, + 0x6d, 0x40, 0xe4, 0x5d, 0xaf, 0xc4, 0x5f, 0xee, + 0x09, 0xbd, 0x57, 0x5b, 0x74, 0x2b, 0x19, 0xbc]) + +ARL_S_INTEL_PROD_KEY = bytes([0x99, 0x37, 0xee, 0x99, 0xe1, 0x2e, 0x33, 0x3c, + 0xbd, 0x56, 0xa5, 0x8b, 0x55, 0xb5, 0x5e, 0x1d, + 0xe6, 0x1a, 0x1a, 0x0f, 0xef, 0xb3, 0xa0, 0x21, + 0x93, 0x76, 0xab, 0xa8, 0xf3, 0xa7, 0xfa, 0x18, + 0x54, 0xa2, 0x04, 0xc1, 0x64, 0xa6, 0x2a, 0xeb, + 0x3c, 0xf9, 0x3b, 0xf0, 0x23, 0x32, 0x75, 0xd7, + 0xa7, 0x24, 0x37, 0x44, 0x8c, 0xb9, 0xdb, 0xeb, + 0xbf, 0xe5, 0x11, 0xc1, 0x3a, 0xe5, 0xae, 0xc1, + 0x15, 0xca, 0x89, 0xf7, 0x71, 0xd7, 0x5d, 0xe3, + 0x73, 0xe8, 0x64, 0x6d, 0x9f, 0xa3, 0xec, 0xc0, + 0xd6, 0xa5, 0xd1, 0x1d, 0x44, 0x3d, 0xbb, 0xcc, + 0x55, 0xcf, 0xf3, 0x91, 0x2e, 0xd1, 0xa3, 0x5a, + 0x05, 0xb8, 0x6e, 0x62, 0xba, 0xc3, 0x1c, 0x06, + 0x20, 0x7f, 0xbd, 0xf2, 0x22, 0xee, 0xaa, 0x43, + 0x79, 0xb9, 0x38, 0xeb, 0xa8, 0x22, 0xb2, 0x5c, + 0xbf, 0x67, 0x64, 0xec, 0x60, 0x60, 0xa2, 0x3c, + 0x56, 0x05, 0x46, 0x61, 0xcf, 0x24, 0x2f, 0x3e, + 0xf5, 0x36, 0x2d, 0x2f, 0xa7, 0xb7, 0x45, 0x9a, + 0xb9, 0xf8, 0xe9, 0x89, 0x27, 0x34, 0x17, 0xf8, + 0xef, 0x6f, 0x35, 0x07, 0x59, 0x77, 0xb0, 0x63, + 0x91, 0xd6, 0x29, 0xa9, 0x22, 0xd9, 0x0f, 0xa2, + 0xc6, 0xd3, 0x9f, 0x42, 0x9d, 0x91, 0x3d, 0x02, + 0x60, 0x8a, 0x5d, 0x6a, 0xfe, 0x0d, 0x7f, 0x8e, + 0xcf, 0xee, 0x9d, 0xdf, 0x39, 0x8b, 0xdc, 0x2a, + 0x68, 0x22, 0xa4, 0x98, 0x82, 0x0a, 0x00, 0x79, + 0xb8, 0x74, 0x66, 0xd1, 0xfa, 0x8e, 0xc0, 0x59, + 0x60, 0x2d, 0x27, 0x4d, 0x10, 0x26, 0xf7, 0x1e, + 0xf6, 0x69, 0x39, 0x9b, 0xa8, 0xd8, 0x00, 0x1b, + 0x38, 0x54, 0x26, 0x92, 0x2c, 0x92, 0x0f, 0xee, + 0x44, 0x3c, 0x6f, 0x63, 0x62, 0xe5, 0x8b, 0x00, + 0xe2, 0xa8, 0x3b, 0x91, 0xe5, 0xfe, 0x55, 0x3a, + 0xf3, 0x25, 0x67, 0x6b, 0x99, 0xc0, 0xdf, 0x28, + 0x2d, 0x51, 0xd2, 0xd3, 0xa9, 0xf8, 0x55, 0x20, + 0x50, 0xa3, 0x7e, 0xec, 0x8a, 0x4f, 0x72, 0x91, + 0x74, 0x4f, 0x87, 0x40, 0xeb, 0xad, 0x33, 0xdf, + 0x9e, 0xb0, 0x3f, 0xb9, 0x5b, 0x9b, 0xcf, 0xe9, + 0x8a, 0x09, 0x88, 0xd7, 0x38, 0x4c, 0xd2, 0xd2, + 0xf1, 0x6c, 0x14, 0x3d, 0xe3, 0x1c, 0x39, 0xd7, + 0xcf, 0x57, 0x1d, 0xb8, 0x92, 0x81, 0xe3, 0x67, + 0x8f, 0xc7, 0xb8, 0xe6, 0xc7, 0x7e, 0x72, 0xda, + 0x03, 0xc6, 0x29, 0x89, 0x9c, 0x47, 0xc3, 0x9d, + 0x74, 0x6e, 0x0b, 0xc3, 0x54, 0x06, 0x25, 0x06, + 0x73, 0x28, 0x97, 0x73, 0xe0, 0xbd, 0xc8, 0x7d, + 0x83, 0x25, 0x09, 0x7e, 0xa4, 0xf9, 0x9f, 0x85, + 0x54, 0xbd, 0xf3, 0x6d, 0xef, 0xa9, 0x59, 0xc4, + 0xed, 0x70, 0x92, 0x97, 0x95, 0xcc, 0xce, 0x29, + 0x6c, 0xa0, 0x50, 0x65, 0x92, 0x39, 0x96, 0x34, + 0x61, 0xa4, 0xeb, 0x6b, 0x11, 0xd9, 0xbe, 0xb8]) + +PTL_INTEL_PROD_KEY = bytes([0x89, 0xa8, 0x6a, 0xff, 0x6b, 0x1a, 0x78, 0xae, + 0x96, 0x0f, 0x50, 0x1a, 0xfb, 0xfc, 0x7b, 0x71, + 0x62, 0x00, 0x50, 0x03, 0x5b, 0x28, 0x32, 0x1c, + 0xe9, 0x99, 0x8a, 0xeb, 0xf0, 0xc0, 0xf9, 0x08, + 0xa5, 0xec, 0xc5, 0xeb, 0xc0, 0x8e, 0x99, 0x9c, + 0x31, 0x1c, 0x9e, 0xdf, 0x33, 0x5f, 0x8b, 0x27, + 0xc6, 0x82, 0x05, 0x50, 0xfb, 0xfa, 0xcb, 0x3d, + 0x96, 0x7a, 0x39, 0xcd, 0x03, 0x77, 0x69, 0xce, + 0x04, 0x1e, 0x10, 0x52, 0x01, 0x96, 0xb4, 0x1d, + 0x46, 0x28, 0x49, 0xc9, 0x43, 0x31, 0x23, 0x04, + 0xe1, 0x0f, 0x49, 0x84, 0x3f, 0xdf, 0xe8, 0xe8, + 0x69, 0x49, 0x60, 0x3a, 0x25, 0x71, 0x14, 0x2c, + 0xee, 0x06, 0x3f, 0x5b, 0x79, 0x67, 0x9a, 0xb4, + 0x5b, 0xa3, 0xf9, 0x64, 0xb9, 0xfe, 0xf6, 0x07, + 0x0c, 0x8e, 0x09, 0x79, 0xda, 0xbc, 0xb9, 0xd6, + 0x50, 0xe4, 0xef, 0x82, 0x0d, 0x6d, 0x30, 0x9c, + 0xa6, 0xa9, 0xbf, 0x9c, 0x88, 0x68, 0xe7, 0x95, + 0xa7, 0x6e, 0x09, 0xa8, 0xa7, 0x92, 0xd5, 0x2f, + 0x3f, 0x22, 0x19, 0x97, 0x0a, 0x41, 0x3f, 0x21, + 0x67, 0x1a, 0x80, 0xb4, 0x10, 0xdd, 0xaa, 0x3b, + 0xd3, 0x1b, 0x83, 0xc7, 0x02, 0x3c, 0x89, 0x88, + 0xd1, 0x3f, 0xdb, 0xdf, 0xf2, 0xaa, 0x79, 0x5f, + 0xbf, 0xf6, 0x6d, 0x3c, 0x6f, 0xbd, 0x90, 0x31, + 0xa8, 0x7d, 0x05, 0x9a, 0x7f, 0x0d, 0x51, 0x44, + 0xee, 0x0d, 0xa2, 0x26, 0x08, 0x4d, 0x39, 0x4b, + 0xd1, 0x4d, 0x7d, 0x24, 0xd1, 0xdb, 0x69, 0x42, + 0xf9, 0x81, 0x3a, 0xc7, 0xe6, 0x1f, 0x09, 0x4d, + 0x67, 0x90, 0x0e, 0xcc, 0xe6, 0x5e, 0xd0, 0x5d, + 0xc0, 0x72, 0x07, 0xb8, 0x29, 0xc5, 0x38, 0xb2, + 0x95, 0x24, 0xef, 0x92, 0xf0, 0x43, 0x06, 0x07, + 0xe5, 0xe3, 0x7c, 0x9f, 0xba, 0x68, 0x59, 0x76, + 0x41, 0xd3, 0xac, 0x8c, 0x0a, 0xe0, 0xc0, 0xd9, + 0x50, 0x21, 0xd6, 0x8f, 0xdf, 0x8d, 0x31, 0xa7, + 0x7f, 0xf9, 0x38, 0xc5, 0x4b, 0x6e, 0x32, 0xbf, + 0x73, 0x0d, 0x93, 0x3a, 0x47, 0xad, 0x3a, 0xbd, + 0xbe, 0x5b, 0x2b, 0xaf, 0xff, 0xc9, 0x7f, 0x37, + 0x30, 0x29, 0x13, 0x0e, 0x61, 0xe6, 0x93, 0xb9, + 0x2c, 0x28, 0x3e, 0x8d, 0x38, 0x3f, 0xea, 0xf4, + 0xf4, 0xf3, 0x23, 0x0c, 0xd2, 0x06, 0x05, 0x22, + 0x51, 0x64, 0x72, 0x6f, 0xfa, 0x1b, 0x7e, 0x81, + 0x22, 0x76, 0xc9, 0x8d, 0xbb, 0xa0, 0xe0, 0xa7, + 0xa4, 0xf9, 0x55, 0x24, 0x9c, 0x4c, 0xd1, 0x80, + 0x97, 0x44, 0x55, 0xe1, 0xfc, 0xa8, 0x6c, 0x8a, + 0x41, 0x67, 0x2f, 0x02, 0x32, 0x05, 0xe5, 0xb7, + 0x7f, 0x8e, 0xda, 0x4d, 0x25, 0x91, 0xf2, 0xc0, + 0x0b, 0xf2, 0x1f, 0x28, 0xeb, 0x5d, 0x05, 0xfe, + 0x70, 0x64, 0xcf, 0x7c, 0xec, 0x79, 0xf8, 0x2e, + 0x84, 0x49, 0x82, 0xa4, 0xf2, 0x20, 0xf6, 0xbd]) + COMMUNITY_KEY = bytes([0x85, 0x00, 0xe1, 0x68, 0xaa, 0xeb, 0xd2, 0x07, 0x1b, 0x7c, 0x5e, 0xed, 0xd6, 0xe7, 0xe5, 0xf9, 0xc1, 0x0e, 0x47, 0xd4, 0x4c, 0xab, 0x8c, 0xf0, @@ -152,10 +590,69 @@ 0x3f, 0x82, 0x8f, 0xe5, 0x28, 0x4d, 0xdb, 0xb5, 0x5a, 0x96, 0x28, 0x27, 0x19, 0xaf, 0x43, 0xb9]) +COMMUNITY_KEY2 = bytes([0x6b, 0x75, 0xed, 0x58, 0x20, 0x08, 0x85, 0x95, + 0xa0, 0x49, 0x8b, 0x9e, 0xbd, 0x5f, 0x34, 0x82, + 0x0a, 0x9d, 0x1e, 0x9a, 0xb6, 0x76, 0x43, 0x19, + 0xb7, 0x76, 0x45, 0x5b, 0x59, 0xab, 0xbb, 0xf3, + 0x9e, 0x72, 0xf2, 0x41, 0x24, 0x92, 0x97, 0xef, + 0x39, 0xc0, 0xed, 0xc4, 0x7a, 0x4e, 0xdb, 0xec, + 0xeb, 0xc7, 0x4c, 0xf6, 0x45, 0xbe, 0xb2, 0xe0, + 0x13, 0x6a, 0xdc, 0x06, 0x7a, 0x1c, 0xbd, 0x8d, + 0xd8, 0xd2, 0xd7, 0x82, 0x6d, 0xbe, 0x03, 0x76, + 0x3b, 0x6b, 0xb8, 0x2f, 0xcc, 0xbe, 0x30, 0x56, + 0x61, 0x87, 0x09, 0xdf, 0x44, 0x51, 0xf8, 0x82, + 0xc5, 0x78, 0x05, 0x45, 0x8c, 0xe3, 0x78, 0x0e, + 0xd3, 0x7a, 0xd4, 0xf4, 0xbe, 0x96, 0xde, 0xb8, + 0x3b, 0x78, 0x90, 0x8b, 0xd3, 0xdd, 0x0b, 0xdd, + 0xbe, 0x56, 0xf3, 0x9a, 0x34, 0xc9, 0x38, 0x47, + 0x8d, 0xc4, 0xbd, 0x5e, 0x68, 0xf8, 0x62, 0xc4, + 0x28, 0xdd, 0x00, 0x48, 0x93, 0xb5, 0xad, 0x74, + 0x52, 0xe5, 0xf3, 0xd2, 0x97, 0xde, 0xbc, 0x0a, + 0x85, 0x95, 0xe9, 0xfa, 0xd2, 0xac, 0xdc, 0xdc, + 0x59, 0x74, 0xfa, 0x57, 0xf2, 0xd3, 0x61, 0xc6, + 0x2b, 0x26, 0xde, 0x57, 0x50, 0xe2, 0x58, 0x6b, + 0x79, 0x65, 0x0b, 0x49, 0x2c, 0x59, 0x28, 0x25, + 0x64, 0x31, 0x93, 0x65, 0x9a, 0x0a, 0x88, 0x98, + 0x9a, 0x77, 0x00, 0x47, 0x8f, 0xa0, 0xc7, 0x6b, + 0x58, 0x90, 0xa9, 0xb5, 0x15, 0xff, 0x65, 0x7c, + 0x84, 0x02, 0xd4, 0xdd, 0x09, 0xf1, 0x25, 0xad, + 0xf9, 0x30, 0xaa, 0x34, 0x5b, 0x77, 0xef, 0xb2, + 0x75, 0x3d, 0x54, 0x9d, 0xcc, 0x0d, 0x11, 0xda, + 0x91, 0x01, 0x2e, 0x51, 0xdc, 0x0c, 0x8a, 0x92, + 0x71, 0x44, 0x9a, 0xd5, 0x69, 0x5d, 0x7a, 0xad, + 0xaf, 0xdf, 0x25, 0xea, 0x95, 0x21, 0xbb, 0x99, + 0x53, 0x89, 0xbc, 0x54, 0xca, 0xf3, 0x54, 0xf5, + 0xbb, 0x38, 0x27, 0x64, 0xce, 0xf2, 0x17, 0x25, + 0x75, 0x33, 0x1a, 0x2d, 0x19, 0x00, 0xff, 0x9b, + 0xd9, 0x4d, 0x0c, 0xb1, 0xa5, 0x55, 0x55, 0xa9, + 0x29, 0x8e, 0xfb, 0x82, 0x43, 0xeb, 0xfa, 0xc8, + 0x33, 0x76, 0xf3, 0x7d, 0xee, 0x95, 0xe1, 0x39, + 0xba, 0xa5, 0x4a, 0xd5, 0xb1, 0x8a, 0xa6, 0xff, + 0x8f, 0x4b, 0x45, 0x8c, 0xe9, 0x7b, 0x87, 0xae, + 0x8d, 0x32, 0x6e, 0x16, 0xe7, 0x9e, 0x85, 0x22, + 0x71, 0x3d, 0x17, 0xba, 0x54, 0xed, 0x73, 0x87, + 0xe5, 0x9d, 0xbf, 0xc0, 0xcd, 0x76, 0xfa, 0x83, + 0xd4, 0xc5, 0x30, 0xd1, 0xc7, 0x25, 0x49, 0x25, + 0x75, 0x4d, 0x0a, 0x4a, 0x2d, 0x13, 0x1c, 0x12, + 0x2e, 0x5d, 0x2a, 0xe2, 0xa9, 0xae, 0xbf, 0x8f, + 0xdf, 0x24, 0x76, 0xf5, 0x81, 0x1e, 0x09, 0x5d, + 0x63, 0x04, 0xaf, 0x24, 0x45, 0x87, 0xf4, 0x96, + 0x55, 0xd1, 0x7d, 0xc6, 0x0d, 0x79, 0x12, 0xa9]) + KNOWN_KEYS = {APL_INTEL_PROD_KEY : 'APL Intel prod key', CNL_INTEL_PROD_KEY : 'CNL Intel prod key', ICL_INTEL_PROD_KEY : 'ICL Intel prod key', - COMMUNITY_KEY : 'Community key'} + JSL_INTEL_PROD_KEY : 'JSL Intel prod key', + TGL_INTEL_PROD_KEY : 'TGL Intel prod key', + EHL_INTEL_PROD_KEY : 'EHL Intel prod key', + ADL_INTEL_PROD_KEY : 'ADL Intel prod key', + ADL_N_INTEL_PROD_KEY : 'ADL-N Intel prod key', + MTL_INTEL_PROD_KEY : 'MTL Intel prod key', + LNL_INTEL_PROD_KEY : 'LNL Intel prod key', + ARL_S_INTEL_PROD_KEY : 'ARL-S Intel prod key', + PTL_INTEL_PROD_KEY : 'PTL Intel prod key', + COMMUNITY_KEY : 'Community key', + COMMUNITY_KEY2 : 'Community 3k key'} def parse_params(): """ Parses parameters @@ -169,6 +666,17 @@ def parse_params(): action='store_true') parser.add_argument('--no_colors', help='disable colors in output', action='store_true') + parser.add_argument('--no_cse', help='disable cse manifest parsing', + action='store_true') + parser.add_argument('--no_headers', help='skip information about headers', + action='store_true') + parser.add_argument('--no_modules', help='skip information about modules', + action='store_true') + parser.add_argument('--no_memory', help='skip information about memory', + action='store_true') + parser.add_argument('--erase_vars', help=''' + Replace the variable signature and any other variable element with constants + ''', type=pathlib.Path, dest='erased_vars_image') parser.add_argument('sof_ri_path', help='path to fw binary file to parse') parsed_args = parser.parse_args() @@ -250,22 +758,12 @@ def seg_flags_to_string(flags): # Parsers -def parse_extended_manifest(reader): - """ Parses extended manifest from sof binary - """ - ext_mft = ExtendedManifest() +def parse_extended_manifest_ae1(reader): + ext_mft = ExtendedManifestAE1() hdr = Component('ext_mft_hdr', 'Header', 0) ext_mft.add_comp(hdr) - # Try to detect signature first - sig = reader.read_bytes(4).decode() - if sig != '$AE1': - reader.set_offset(0) - reader.info('info: Extended Manifest not found (sig = '+sig+')') - reader.ext_mft_length = 0 - hdr.add_a(Auint('length', reader.ext_mft_length)) - return ext_mft - + sig = reader.read_string(4) reader.info('Extended Manifest (' + sig + ')', -4) hdr.add_a(Astring('sig', sig)) @@ -279,16 +777,65 @@ def parse_extended_manifest(reader): reader.ff_data(reader.ext_mft_length-16) return ext_mft -def parse_cse_manifest(reader, add_module_entries): +def parse_extended_manifest_xman(reader): + ext_mft = ExtendedManifestXMan() + hdr = Component('ext_mft_hdr', 'Header', 0) + ext_mft.add_comp(hdr) + + sig = reader.read_string(4) + reader.info('Extended Manifest (' + sig + ')', -4) + hdr.add_a(Astring('sig', sig)) + + # Next dword is the total length of the extended manifest + # (need to use it for further parsing) + reader.ext_mft_length = reader.read_dw() + hdr_length = reader.read_dw() + hdr_ver = reader.read_dw() + + major = hdr_ver >> 24 + minor = (hdr_ver >> 12) & 0xFFF + patch = hdr_ver & 0xFFF + + hdr.add_a(Auint('length', reader.ext_mft_length)) + hdr.add_a(Astring('ver', '{}.{}.{}'.format(major, minor, patch))) + hdr.add_a(Auint('hdr_length', hdr_length)) + + reader.ff_data(reader.ext_mft_length-16) + return ext_mft + +def parse_extended_manifest(reader): + """ Parses extended manifest from sof binary + """ + + reader.info('Looking for Extended Manifest') + # Try to detect signature first + sig = reader.read_string(4) + reader.set_offset(0) + if sig == '$AE1': + ext_mft = parse_extended_manifest_ae1(reader) + elif sig == 'XMan': + ext_mft = parse_extended_manifest_xman(reader) + else: + ext_mft = ExtendedManifestAE1() + hdr = Component('ext_mft_hdr', 'Header', 0) + ext_mft.add_comp(hdr) + reader.info('info: Extended Manifest not found (sig = '+sig+')') + reader.ext_mft_length = 0 + hdr.add_a(Auint('length', reader.ext_mft_length)) + + return ext_mft + +def parse_cse_manifest(reader): """ Parses CSE manifest form sof binary """ + reader.info('Looking for CSE Manifest') cse_mft = CseManifest(reader.get_offset()) # Try to detect signature first - sig = reader.read_bytes(4).decode() + sig = reader.read_string(4) if sig != '$CPD': - reader.error('CSE Manifest NOT found ' + sig + ')', -4) - sys.exit(1) + raise Exception('CSE Manifest magic number NOT found, instead: (' + + sig + ')', -4) reader.info('CSE Manifest (' + sig + ')', -4) # Read the header @@ -297,6 +844,7 @@ def parse_cse_manifest(reader, add_module_entries): hdr.add_a(Astring('sig', sig)) # read number of entries nb_entries = reader.read_dw() + reader.info('# of entries {}'.format(nb_entries)) hdr.add_a(Adec('nb_entries', nb_entries)) # read version (1byte for header ver and 1 byte for entry ver) ver = reader.read_w() @@ -304,13 +852,14 @@ def parse_cse_manifest(reader, add_module_entries): header_length = reader.read_b() hdr.add_a(Ahex('header_length', header_length)) hdr.add_a(Ahex('checksum', reader.read_b())) - hdr.add_a(Astring('partition_name', reader.read_bytes(4).decode())) + hdr.add_a(Astring('partition_name', reader.read_string(4))) reader.set_offset(cse_mft.file_offset + header_length) # Read entries nb_index = 0 while nb_index < nb_entries: - entry_name = reader.read_bytes(12).decode() + reader.info('Reading CSE Manifest entry %d...' % nb_index) + entry_name = reader.read_string(12) entry_offset = reader.read_dw() entry_length = reader.read_dw() # reserved field @@ -322,22 +871,25 @@ def parse_cse_manifest(reader, add_module_entries): hdr_entry.add_a(Ahex('entry_length', entry_length)) hdr.add_comp(hdr_entry) + assert cse_mft.file_offset == reader.ext_mft_length + entry_file_offset = reader.ext_mft_length + entry_offset + reader.info('... CSE Entry name {} file offset 0x{:x} length {}'.format(entry_name, + entry_file_offset, entry_length)) + if '.man' in entry_name: - entry = CssManifest(entry_name, entry_offset) - cur_off = reader.set_offset(reader.ext_mft_length + entry_offset) + entry = CssManifest(entry_name, entry_file_offset) + cur_off = reader.set_offset(entry_file_offset) parse_css_manifest(entry, reader, - reader.ext_mft_length + entry_offset + entry_length) + entry_file_offset + entry_length) reader.set_offset(cur_off) elif '.met' in entry_name: - cur_off = reader.set_offset(reader.ext_mft_length + entry_offset) + cur_off = reader.set_offset(entry_file_offset) entry = parse_mft_extension(reader, 0) entry.name = '{} ({})'.format(entry_name, entry.name) reader.set_offset(cur_off) else: - # override offset with precise one - cur_off = reader.set_offset(reader.ext_mft_length + 0x2000) - entry = parse_adsp_manifest(reader, entry_name, add_module_entries) - reader.set_offset(cur_off) + # indicate the place, the entry is enumerated. mft parsed later + entry = Component('adsp_mft_cse_entry', entry_name, entry_file_offset) cse_mft.add_comp(entry) nb_index += 1 @@ -347,18 +899,19 @@ def parse_cse_manifest(reader, add_module_entries): def parse_css_manifest(css_mft, reader, limit): """ Parses CSS manifest from sof binary """ + reader.info('Parsing CSS Manifest') ver, = struct.unpack('I', reader.get_data(0, 4)) if ver == 4: reader.info('CSS Manifest type 4') return parse_css_manifest_4(css_mft, reader, limit) - reader.error('CSS Manifest NOT found or NOT recognized!') - sys.exit(1) + raise Exception('CSS Manifest NOT found or NOT recognized!') def parse_css_manifest_4(css_mft, reader, size_limit): """ Parses CSS manifest type 4 from sof binary """ + reader.info('Parsing CSS Manifest type 4') # CSS Header hdr = Component('css_mft_hdr', 'Header', reader.get_offset()) css_mft.add_comp(hdr) @@ -369,10 +922,13 @@ def parse_css_manifest_4(css_mft, reader, size_limit): hdr.add_a(Auint('header_version', reader.read_dw())) hdr.add_a(Auint('reserved0', reader.read_dw(), 'red')) hdr.add_a(Ahex('mod_vendor', reader.read_dw())) + date_start = reader.get_offset() + hdr.add_a(Auint('date_start', date_start)) hdr.add_a(Adate('date', hex(reader.read_dw()))) + hdr.add_a(Auint('date_length', reader.get_offset() - date_start)) size = reader.read_dw() hdr.add_a(Auint('size', size)) - hdr.add_a(Astring('header_id', reader.read_bytes(4).decode())) + hdr.add_a(Astring('header_id', reader.read_string(4))) hdr.add_a(Auint('padding', reader.read_dw())) hdr.add_a(Aversion('fw_version', reader.read_w(), reader.read_w(), reader.read_w(), reader.read_w())) @@ -383,9 +939,13 @@ def parse_css_manifest_4(css_mft, reader, size_limit): exponent_size = reader.read_dw() hdr.add_a(Adec('exponent_size', exponent_size)) modulus = reader.read_bytes(modulus_size * 4) - hdr.add_a(Amodulus('modulus', modulus, KNOWN_KEYS.get(modulus, 'Other'))) + hdr.add_a(Amodulus('modulus', modulus, KNOWN_KEYS.get(modulus, 'Unknown key'))) hdr.add_a(Abytes('exponent', reader.read_bytes(exponent_size * 4))) + + sig_start = reader.get_offset() + hdr.add_a(Auint('signature_start', sig_start)) hdr.add_a(Abytes('signature', reader.read_bytes(modulus_size * 4))) + hdr.add_a(Auint('signature_length', reader.get_offset() - sig_start)) # Move right after the header reader.set_offset(css_mft.file_offset + header_len_dw*4) @@ -397,32 +957,39 @@ def parse_css_manifest_4(css_mft, reader, size_limit): # that could be parsed if extension type is recognized # # or series of 0xffffffff that should be skipped + reader.info('Parsing CSS Manifest extensions, end at 0x{:x}'.format(size_limit)) ext_idx = 0 while reader.get_offset() < size_limit: ext_type = reader.read_dw() + reader.info('Reading CSS extension type 0x{:x}:'.format(ext_type)) if ext_type == 0xffffffff: continue reader.set_offset(reader.get_offset() - 4) css_mft.add_comp(parse_mft_extension(reader, ext_idx)) ext_idx += 1 + assert reader.get_offset() == size_limit # wrong extension length + + css_mft.length = reader.get_offset() - css_mft.file_offset return css_mft def parse_mft_extension(reader, ext_id): """ Parses mft extension from sof binary """ + begin_off = reader.get_offset() ext_type = reader.read_dw() ext_len = reader.read_dw() if ext_type == 15: - begin_off = reader.get_offset() + reader.info("Plat Fw Auth extension") ext = PlatFwAuthExtension(ext_id, reader.get_offset()-8) - ext.add_a(Astring('name', reader.read_bytes(4).decode())) + ext.add_a(Astring('name', reader.read_string(4))) ext.add_a(Auint('vcn', reader.read_dw())) ext.add_a(Abytes('bitmap', reader.read_bytes(16), 'red')) ext.add_a(Auint('svn', reader.read_dw())) read_len = reader.get_offset() - begin_off reader.ff_data(ext_len - read_len) elif ext_type == 17: + reader.info("ADSP metadata file extension") ext = AdspMetadataFileExt(ext_id, reader.get_offset()-8) ext.add_a(Auint('adsp_imr_type', reader.read_dw(), 'red')) # skip reserved part @@ -435,11 +1002,22 @@ def parse_mft_extension(reader, ext_id): ext.add_a(Auint('base_offset', reader.read_dw())) ext.add_a(Auint('limit_offset', reader.read_dw())) ext.add_a(Abytes('attributes', reader.read_bytes(16))) + elif ext_type == 35: + reader.info("Signed package info extension") + ext = SignedPkgInfoExtension(ext_id, reader.get_offset()-8) + ext.add_a(Astring('name', reader.read_string(4))) + ext.add_a(Auint('vcn', reader.read_dw())) + ext.add_a(Auint('svn', reader.read_dw())) + ext.add_a(Auint('partition_usage', reader.read_b(), 'red')) + read_len = reader.get_offset() - begin_off + reader.ff_data(ext_len - read_len) else: + reader.info("Other extension") ext = MftExtension(ext_id, 'Other Extension', reader.get_offset()-8) reader.ff_data(ext_len-8) ext.add_a(Auint('type', ext_type)) ext.add_a(Auint('length', ext_len)) + reader.info("... end of extension") return ext def parse_adsp_manifest_hdr(reader): @@ -447,14 +1025,12 @@ def parse_adsp_manifest_hdr(reader): """ # Verify signature try: - sig = reader.read_bytes(4).decode() + sig = reader.read_string(4) except UnicodeDecodeError: - print('\n' + reader.offset_to_string() + \ + raise Exception('\n' + reader.offset_to_string() + \ '\terror: Failed to decode signature, wrong position?') - sys.exit(1) if sig != '$AM1': - reader.error('ADSP Manifest NOT found!', -4) - sys.exit(1) + raise Exception('ADSP Manifest NOT found!', -4) reader.info('ADSP Manifest (' + sig + ')', -4) hdr = Component('adsp_mft_hdr', 'ADSP Manifest Header', @@ -481,18 +1057,16 @@ def parse_adsp_manifest_mod_entry(index, reader): """ # Verify Mod Entry signature try: - sig = reader.read_bytes(4).decode() + sig = reader.read_string(4) except UnicodeDecodeError: - print(reader.offset_to_string() + \ + raise Exception(reader.offset_to_string() + \ '\terror: Failed to decode ModuleEntry signature') - sys.exit(1) if sig != '$AME': - reader.error('ModuleEntry signature NOT found!') - sys.exit(1) + raise Exception('ModuleEntry signature NOT found!') reader.info('Module Entry signature found (' + sig + ')', -4) - mod = Component('mod_entry_'+repr(index), 'Module Entry', - reader.get_offset() -4) + mod = AdspModuleEntry('mod_entry_'+repr(index), + reader.get_offset() -4) mod.add_a(Astring('sig', sig)) mod.add_a(Astring('mod_name', @@ -510,14 +1084,15 @@ def parse_adsp_manifest_mod_entry(index, reader): mod.add_a(Auint('instance_stack_size', reader.read_w())) for i in range(0, 3): seg_flags = reader.read_dw() - mod.add_a(Astring('seg_'+repr(i)+' flags', + mod.add_a(Astring('seg_'+repr(i)+'_flags', hex(seg_flags) + ' ' + seg_flags_to_string(seg_flags))) - mod.add_a(Ahex('seg_'+repr(i)+' v_base_addr', reader.read_dw())) - mod.add_a(Ahex('seg_'+repr(i)+' file_offset', reader.read_dw())) + mod.add_a(Ahex('seg_'+repr(i)+'_v_base_addr', reader.read_dw())) + mod.add_a(Ahex('seg_'+repr(i)+'_size', ((seg_flags>>16)&0xffff)*0x1000)) + mod.add_a(Ahex('seg_'+repr(i)+'_file_offset', reader.read_dw())) return mod -def parse_adsp_manifest(reader, name, add_module_entries): +def parse_adsp_manifest(reader, name): """ Parses ADSP manifest from sof binary """ adsp_mft = AdspManifest(name, reader.get_offset()) @@ -525,12 +1100,11 @@ def parse_adsp_manifest(reader, name, add_module_entries): num_module_entries = adsp_mft.cdir['adsp_mft_hdr'].adir['num_module_entries'].val for i in range(0, num_module_entries): mod_entry = parse_adsp_manifest_mod_entry(i, reader) - if add_module_entries: - adsp_mft.add_comp(mod_entry) + adsp_mft.add_comp(mod_entry) return adsp_mft -def parse_fw_bin(path, verbose, add_module_entries): +def parse_fw_bin(path, no_cse, verbose): """ Parses sof binary """ reader = BinReader(path, verbose) @@ -539,10 +1113,12 @@ def parse_fw_bin(path, verbose, add_module_entries): parsed_bin.add_a(Astring('file_name', reader.file_name)) parsed_bin.add_a(Auint('file_size', reader.file_size)) parsed_bin.add_comp(parse_extended_manifest(reader)) - parsed_bin.add_comp(parse_cse_manifest(reader, add_module_entries)) + if not no_cse: + parsed_bin.add_comp(parse_cse_manifest(reader)) + reader.set_offset(reader.ext_mft_length + 0x2000) + parsed_bin.add_comp(parse_adsp_manifest(reader, 'cavs0015')) - if verbose: - print('Parsing finished') + reader.info('Parsing finished', show_offset = False) return parsed_bin class BinReader(): @@ -550,15 +1126,15 @@ class BinReader(): """ def __init__(self, path, verbose): self.verbose = verbose - if self.verbose: - print('Reading SOF ri image ' + path) + self.cur_offset = 0 + self.ext_mft_length = 0 + self.info(f'Reading SOF ri image {path}', show_offset=False) self.file_name = path # read the content self.data = open(path, 'rb').read() self.file_size = len(self.data) - if self.verbose: - print('File size ' + uint_to_string(self.file_size, True)) - self.cur_offset = 0 + self.info('File size ' + uint_to_string(self.file_size, True), + show_offset=False) def get_offset(self): """ Retrieve the offset, the reader is at @@ -611,6 +1187,11 @@ def read_b(self): self.ff_data(1) return byte + def read_string(self, size_in_file): + """ Reads a string from the stream, potentially padded with zeroes + """ + return self.read_bytes(size_in_file).decode().rstrip('\0') + def read_uuid(self): """ Reads a UUID from the stream and returns as string """ @@ -628,17 +1209,21 @@ def offset_to_string(self, delta=0): """ return uint_to_string(self.cur_offset+delta) - def info(self, loginfo, off_delta=0, verb_info=True): + def info(self, loginfo, off_delta=0, verb_info=True, show_offset=True): """ Prints 'info' log to the output, respects verbose mode """ if verb_info and not self.verbose: return - print(self.offset_to_string(off_delta) + '\t' + loginfo) + if show_offset: + print(self.offset_to_string(off_delta) + '\t' + loginfo) + else: + print(loginfo) def error(self, logerror, off_delta=0): """ Prints 'error' log to the output """ - print(self.offset_to_string(off_delta) + '\terror: ' + logerror) + print(self.offset_to_string(off_delta) + '\terror: ' + logerror, + file=sys.stderr) # Data Model @@ -701,8 +1286,15 @@ def __str__(self): out = '' else: out = '{}'.format(change_color(self.color)) - if Attribute.full_bytes or length <= 16: + if length <= 16: out += ' '.join(['{:02x}'.format(b) for b in self.val]) + elif Attribute.full_bytes: + """ n is bytes per line + 8 bytes per line is useful for adding more KEYs at the top + """ + n = 8 + out += '\n' + out += ',\n'.join([', '.join(['0x{:02x}'.format(b) for b in self.val[i:i + n]]) for i in range(0, length, n)]) else: out += ' '.join('{:02x}'.format(b) for b in self.val[:8]) out += ' ... ' @@ -793,14 +1385,14 @@ def get_comp(self, comp_uid): return comp return None - def dump_info(self, pref): + def dump_info(self, pref, comp_filter): """ Prints out the content (name, all attributes, and nested comps) """ print(pref + self.name) for attrib in self.attribs: print("{:} {:<{:}} {:}".format(pref, attrib.name, self.max_attr_name_len, attrib)) - self.dump_comp_info(pref) + self.dump_comp_info(pref, comp_filter) def dump_attrib_info(self, pref, attr_name): """ Prints out a single attribute @@ -809,23 +1401,27 @@ def dump_attrib_info(self, pref, attr_name): print("{:} {:<{:}} {:}".format(pref, attrib.name, self.max_attr_name_len, attrib)) - def dump_comp_info(self, pref, name_filter=''): + def dump_comp_info(self, pref, comp_filter=''): """ Prints out all nested components (filtered by name set to 'filter') """ for comp in self.components: - if comp.name == name_filter: + if comp.name in comp_filter: continue print() - comp.dump_info(pref + ' ') + comp.dump_info(pref + ' ', comp_filter) -class ExtendedManifest(Component): + def add_comp_to_mem_map(self, mem_map): + for comp in self.components: + comp.add_comp_to_mem_map(mem_map) + +class ExtendedManifestAE1(Component): """ Extended manifest """ def __init__(self): - super(ExtendedManifest, self).__init__('ext_mft', + super(ExtendedManifestAE1, self).__init__('ext_mft', 'Extended Manifest', 0) - def dump_info(self, pref): + def dump_info(self, pref, comp_filter): hdr = self.cdir['ext_mft_hdr'] if hdr.adir['length'].val == 0: return @@ -833,7 +1429,24 @@ def dump_info(self, pref): out += ' ver {}'.format(hdr.adir['ver']) out += ' entries {}'.format(hdr.adir['entries']) print(out) - self.dump_comp_info(pref, name_filter='Header') + self.dump_comp_info(pref, comp_filter + ['Header']) + +class ExtendedManifestXMan(Component): + """ Extended manifest + """ + def __init__(self): + super(ExtendedManifestXMan, self).__init__('ext_mft', + 'Extended Manifest', 0) + + def dump_info(self, pref, comp_filter): + hdr = self.cdir['ext_mft_hdr'] + if hdr.adir['length'].val == 0: + return + out = '{}{}'.format(pref, self.name) + out += ' ver {}'.format(hdr.adir['ver']) + out += ' length {}'.format(hdr.adir['length'].val) + print(out) + self.dump_comp_info(pref, comp_filter + ['Header']) class CseManifest(Component): """ CSE Manifest @@ -841,13 +1454,13 @@ class CseManifest(Component): def __init__(self, offset): super(CseManifest, self).__init__('cse_mft', 'CSE Manifest', offset) - def dump_info(self, pref): + def dump_info(self, pref, comp_filter): hdr = self.cdir['cse_mft_hdr'] print('{}{} ver {} checksum {} partition name {}'. format(pref, self.name, hdr.adir['header_version'], hdr.adir['checksum'], hdr.adir['partition_name'])) - self.dump_comp_info(pref, name_filter='Header') + self.dump_comp_info(pref, comp_filter + ['Header']) class CssManifest(Component): """ CSS Manifest @@ -855,10 +1468,13 @@ class CssManifest(Component): def __init__(self, name, offset): super(CssManifest, self).__init__('css_mft', name, offset) - def dump_info(self, pref): + def dump_info(self, pref, comp_filter): hdr = self.cdir['css_mft_hdr'] out = '{}{} (CSS Manifest)'.format(pref, self.name) out += ' type {}'.format(hdr.adir['type']) + out += ' file offset {:#x} hdr_len {}'.format( + self.file_offset, hdr.adir['header_len_dw'].val * 4 + ) out += ' ver {}'.format(hdr.adir['header_version']) out += ' date {}'.format(hdr.adir['date']) print(out) @@ -871,10 +1487,11 @@ def dump_info(self, pref): format(pref, hdr.adir['exponent_size'])) print('{} {}'.format(pref, hdr.adir['exponent'])) - print('{} Signature'.format(pref)) + print('{} Signature (file offset {}, length {})'.format( + pref, hdr.adir['signature_start'], hdr.adir['signature_length'])) print('{} {}'.format(pref, hdr.adir['signature'])) # super().dump_info(pref) - self.dump_comp_info(pref, name_filter='Header') + self.dump_comp_info(pref, comp_filter + ['Header']) class MftExtension(Component): """ Manifest Extension @@ -883,10 +1500,10 @@ def __init__(self, ext_id, name, offset): super(MftExtension, self).__init__('mft_ext'+repr(ext_id), name, offset) - def dump_info(self, pref): - print('{}{} type {} length {}'. + def dump_info(self, pref, comp_filter): + print('{}{} type {} file offset 0x{:x} length {}'. format(pref, self.name, - self.adir['type'], self.adir['length'])) + self.adir['type'], self.file_offset, self.adir['length'])) class PlatFwAuthExtension(MftExtension): """ Platform FW Auth Extension @@ -895,14 +1512,31 @@ def __init__(self, ext_id, offset): super(PlatFwAuthExtension, self).__init__(ext_id, 'Plat Fw Auth Extension', offset) - def dump_info(self, pref): - out = '{}{}'.format(pref, self.name) + def dump_info(self, pref, comp_filter): + super().dump_info(pref, comp_filter) + out = '{}'.format(pref) out += ' name {}'.format(self.adir['name']) out += ' vcn {}'.format(self.adir['vcn']) out += ' bitmap {}'.format(self.adir['bitmap']) out += ' svn {}'.format(self.adir['svn']) print(out) +class SignedPkgInfoExtension(MftExtension): + """ Signed package info Extension + """ + def __init__(self, ext_id, offset): + super(SignedPkgInfoExtension, + self).__init__(ext_id, 'Signed package info Extension', offset) + + def dump_info(self, pref, comp_filter): + super().dump_info(pref, comp_filter) + out = '{}'.format(pref) + out += ' name {}'.format(self.adir['name']) + out += ' vcn {}'.format(self.adir['vcn']) + out += ' svn {}'.format(self.adir['svn']) + out += ' partition_usage {}'.format(self.adir['partition_usage']) + print(out) + class AdspMetadataFileExt(MftExtension): """ ADSP Metadata File Extension """ @@ -911,8 +1545,9 @@ def __init__(self, ext_id, offset): self).__init__(ext_id, 'ADSP Metadata File Extension', offset) - def dump_info(self, pref): - out = '{}{}'.format(pref, self.name) + def dump_info(self, pref, comp_filter): + super().dump_info(pref, comp_filter) + out = '{}'.format(pref) out += ' ver {}'.format(self.adir['version']) out += ' base offset {}'.format(self.adir['base_offset']) out += ' limit offset {}'.format(self.adir['limit_offset']) @@ -927,9 +1562,9 @@ class AdspManifest(Component): def __init__(self, name, offset): super(AdspManifest, self).__init__('adsp_mft', name, offset) - def dump_info(self, pref): + def dump_info(self, pref, comp_filter): hdr = self.cdir['adsp_mft_hdr'] - out = '{}{} (ADSP Manifest)'.format(pref, self.name) + out = '{}{} (ADSP Manifest) file offset 0x{:x}'.format(pref, self.name, self.file_offset) out += ' name {}'.format(hdr.adir['name']) out += ' build ver {}'.format(hdr.adir['build_version']) out += ' feature mask {}'.format(hdr.adir['feature_mask']) @@ -941,7 +1576,48 @@ def dump_info(self, pref): hdr.adir['hw_buf_length'])) print('{} Load offset {}'.format(pref, hdr.adir['load_offset'])) - self.dump_comp_info(pref, 'ADSP Manifest Header') + self.dump_comp_info(pref, comp_filter + ['ADSP Manifest Header']) + +class AdspModuleEntry(Component): + """ ADSP Module Entry + """ + def __init__(self, uid, offset): + super(AdspModuleEntry, self).__init__(uid, 'Module Entry', offset) + + def dump_info(self, pref, comp_filter): + print('{}{:9} {}'.format(pref, str(self.adir['mod_name']), + self.adir['uuid'])) + print('{} entry point {} type {}'.format(pref, self.adir['entry_point'], + self.adir['type'])) + out = '{} cfg offset {} count {} affinity {}'.format(pref, + self.adir['cfg_offset'], self.adir['cfg_count'], + self.adir['affinity_mask']) + out += ' instance max count {} stack size {}'.format( + self.adir['instance_max_count'], self.adir['instance_stack_size']) + print(out) + print('{} .text {} file offset {} flags {}'.format(pref, + self.adir['seg_0_v_base_addr'], self.adir['seg_0_file_offset'], + self.adir['seg_0_flags'])) + print('{} .rodata {} file offset {} flags {}'.format(pref, + self.adir['seg_1_v_base_addr'], self.adir['seg_1_file_offset'], + self.adir['seg_1_flags'])) + print('{} .bss {} file offset {} flags {}'.format(pref, + self.adir['seg_2_v_base_addr'], self.adir['seg_2_file_offset'], + self.adir['seg_2_flags'])) + + def add_comp_to_mem_map(self, mem_map): + mem_map.insert_segment(DspMemorySegment( + self.adir['mod_name'].val + '.text', + self.adir['seg_0_v_base_addr'].val, + self.adir['seg_0_size'].val)); + mem_map.insert_segment(DspMemorySegment( + self.adir['mod_name'].val + '.rodata', + self.adir['seg_1_v_base_addr'].val, + self.adir['seg_1_size'].val)); + mem_map.insert_segment(DspMemorySegment( + self.adir['mod_name'].val + '.bss', + self.adir['seg_2_v_base_addr'].val, + self.adir['seg_2_size'].val)); class FwBin(Component): """ Parsed sof binary @@ -949,21 +1625,319 @@ class FwBin(Component): def __init__(self): super(FwBin, self).__init__('bin', 'SOF Binary', 0) - def dump_info(self, pref): + def dump_info(self, pref, comp_filter): """ Print out the content """ print('SOF Binary {} size {}'.format( self.adir['file_name'], self.adir['file_size'])) - self.dump_comp_info(pref) + self.dump_comp_info(pref, comp_filter) + + def populate_mem_map(self, mem_map): + """ Adds modules' segments to the memory map + """ + self.add_comp_to_mem_map(mem_map) + +# DSP Memory Layout +def get_mem_map(ri_path): + """ Retrieves memory map for platform determined by the file name + """ + for plat_name in DSP_MEM_SPACE_EXT: + # use full firmware name for match + if "sof-{}.ri".format(plat_name) in ri_path: + return DSP_MEM_SPACE_EXT[plat_name] + + # Widen the search and match anything in directory names like + # `___/build_tgl_xcc/sof.ri` + found = None + for plat_name in DSP_MEM_SPACE_EXT: + if plat_name in ri_path: + if found and len(found) > len(plat_name): + continue + found = plat_name + + return DSP_MEM_SPACE_EXT[found] if found else DspMemory( + 'No platform found in name "{}"'.format(ri_path) + + "; unknown memory layout.", []) + +def add_lmap_mem_info(ri_path, mem_map): + """ Optional lmap processing + """ + lmap_path = ri_path[0:ri_path.rfind('.')] + '.lmap' + try: + with open(lmap_path) as lmap: + it_lines = iter(lmap.readlines()) + for line in it_lines: + if 'Sections:' in line: + next(it_lines) + break; + for line in it_lines: + tok = line.split() + mem_map.insert_segment(DspMemorySegment(tok[1], + int(tok[3], 16), int(tok[2], 16))) + next(it_lines) + + except FileNotFoundError: + return + +class DspMemorySegment(object): + """ Single continuous memory space + """ + def __init__(self, name, base_address, size): + self.name = name + self.base_address = base_address + self.size = size + self.used_size = 0 + self.inner_segments = [] + + def is_inner(self, segment): + return self.base_address <= segment.base_address and \ + segment.base_address + segment.size <= self.base_address + self.size + + def insert_segment(self, segment): + for seg in self.inner_segments: + if seg.is_inner(segment): + seg.insert_segment(segment) + return + self.inner_segments.append(segment) + self.used_size += segment.size + + def dump_info(self, pref): + free_size = self.size - self.used_size + out = '{}{:<35} 0x{:x}'.format(pref, self.name, self.base_address) + if self.used_size > 0: + out += ' ({} + {} {:.2f}% used)'.format(self.used_size, free_size, + self.used_size*100/self.size) + else: + out += ' ({})'.format(free_size) + print(out) + for seg in self.inner_segments: + seg.dump_info(pref + ' ') + +class DspMemory(object): + """ Dsp Memory, all top-level segments + """ + def __init__(self, platform_name, segments): + self.platform_name = platform_name + self.segments = segments + + def insert_segment(self, segment): + """ Inserts segment + """ + for seg in self.segments: + if seg.is_inner(segment): + seg.insert_segment(segment) + return + + def dump_info(self): + if not self.segments: + print(self.platform_name) # "no platform found" + return + + print("Memory layout for: " + self.platform_name) + for seg in self.segments: + seg.dump_info(' ') + +# Layouts of DSP memory for known platforms + +APL_MEMORY_SPACE = DspMemory('Intel Apollolake', + [ + DspMemorySegment('imr', 0xa0000000, 4*1024*1024), + DspMemorySegment('l2 hpsram', 0xbe000000, 8*64*1024), + DspMemorySegment('l2 lpsram', 0xbe800000, 2*64*1024) + ]) + +CNL_MEMORY_SPACE = DspMemory('Intel Cannonlake', + [ + DspMemorySegment('imr', 0xb0000000, 8*1024*1024), + DspMemorySegment('l2 hpsram', 0xbe000000, 48*64*1024), + DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024) + ]) + +ICL_MEMORY_SPACE = DspMemory('Intel Icelake', + [ + DspMemorySegment('imr', 0xb0000000, 8*1024*1024), + DspMemorySegment('l2 hpsram', 0xbe000000, 47*64*1024), + DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024) + ]) + +TGL_LP_MEMORY_SPACE = DspMemory('Intel Tigerlake-LP', + [ + DspMemorySegment('imr', 0xb0000000,16*1024*1024), + DspMemorySegment('l2 hpsram', 0xbe000000, 46*64*1024), + DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024) + ]) + +JSL_MEMORY_SPACE = DspMemory('Intel Jasperlake', + [ + DspMemorySegment('imr', 0xb0000000, 8*1024*1024), + DspMemorySegment('l2 hpsram', 0xbe000000, 16*64*1024), + DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024) + ]) + +TGL_H_MEMORY_SPACE = DspMemory('Intel Tigerlake-H', + [ + DspMemorySegment('imr', 0xb0000000, 16*1024*1024), + DspMemorySegment('l2 hpsram', 0xbe000000, 30*64*1024), + DspMemorySegment('l2 lpsram', 0xbe800000, 1*64*1024) + ]) + +DSP_MEM_SPACE_EXT = { + 'apl' : APL_MEMORY_SPACE, + 'glk' : APL_MEMORY_SPACE, + + 'cnl' : CNL_MEMORY_SPACE, + 'cfl' : CNL_MEMORY_SPACE, + 'cml' : CNL_MEMORY_SPACE, + + 'icl' : ICL_MEMORY_SPACE, + + 'jsl' : JSL_MEMORY_SPACE, + + 'tgl' : TGL_LP_MEMORY_SPACE, + 'ehl' : TGL_LP_MEMORY_SPACE, + 'adl' : TGL_LP_MEMORY_SPACE, + 'rpl' : TGL_LP_MEMORY_SPACE, + + 'tgl-h' : TGL_H_MEMORY_SPACE, + 'adl-s' : TGL_H_MEMORY_SPACE, + 'rpl-s' : TGL_H_MEMORY_SPACE, +} + + +def getCssManifest(parsed_fw): + "Also known as 'ADSP.man'" + cse_mft = parsed_fw.cdir['cse_mft'] + return cse_mft.cdir['css_mft'] + + +def Erase(input_reader, start, length, padding): + + padding = padding * (length // len(padding) + 1) + output_bytes = input_reader.read(start) + + # Skip and replace with padding + input_reader.seek(length, 1) + output_bytes += padding[:length] + + output_bytes += input_reader.read() + + input_reader.seek(0) + return io.BytesIO(output_bytes) + + +def EraseSignature(signed_input, parsed_fw): + + hdr = getCssManifest(parsed_fw).cdir['css_mft_hdr'] + + return Erase(signed_input, + hdr.adir['signature_start'].val, + hdr.adir['signature_length'].val, + b'Erased signature. ') + + +def EraseCssManifestDate(dated_input, parsed_fw): + + hdr = getCssManifest(parsed_fw).cdir['css_mft_hdr'] + + return Erase(dated_input, + hdr.adir['date_start'].val, + hdr.adir['date_length'].val, + b'\x11' * 6) # = 1111/11/11 + + +def EraseCssManifest(image_input, parsed_fw): + + css_man = getCssManifest(parsed_fw) + + return Erase(image_input, css_man.file_offset, + css_man.length, b"Erased CSS manifest. ") + + +def EraseImrType(image_input, parsed_fw): + + cse_mft = parsed_fw.cdir['cse_mft'] + adsp_meta_ext = cse_mft.cdir['mft_ext0'] + + # IMR type is the very first field after extension type and length + imr_start = adsp_meta_ext.file_offset + 4 + 4 + + # Health check: re-read the imr_type to make sure the offset is + # still correct, no copy/paste/diverge. + true_imr_type = adsp_meta_ext.adir['adsp_imr_type'].val + image_input.seek(imr_start) + imr_type, = struct.unpack("<I", image_input.read(4)) + assert imr_type == true_imr_type + image_input.seek(0) + + return Erase(image_input, imr_start, 4, b'IMRt') + + +def EraseVariables(input_path, parsed_fw, output_path): + """This is not smart but it gets the current job done. This entire + script should be re-written and based on a more advanced framework + like Construct, then a hierarchical, diffoscope-like diff should be + easy to implement on top. + """ + with open(input_path, 'rb') as reader: + + if True: + # Massive erasure required to compare .ri files produced by + # different tools (e.g. rimage vs MEU) + cse_mft = parsed_fw.cdir['cse_mft'] + adsp_mft = parsed_fw.cdir['adsp_mft'] + + cse_plus_padding_len = adsp_mft.file_offset - cse_mft.file_offset + + reader = Erase(reader, cse_mft.file_offset, + cse_plus_padding_len, + b'Erased CSE manifest + padding. ') + + else: + # This is much smaller and enough to deal with date and + # random salt when signing with the same tool + reader = EraseCssManifestDate(reader, parsed_fw) + reader = EraseSignature(reader, parsed_fw) + + with open(output_path, 'wb') as output: + for chunk in reader: + output.write(chunk) + + assert input_path.stat().st_size == output_path.stat().st_size + + with open(output_path, 'rb') as output: + return hashlib.sha256(output.read()).hexdigest() + def main(args): """ main function """ - Attribute.no_colors = args.no_colors + if sys.stdout.isatty(): + Attribute.no_colors = args.no_colors + else: + Attribute.no_colors = True + Attribute.full_bytes = args.full_bytes - fw_bin = parse_fw_bin(args.sof_ri_path, args.verbose, not args.headers) - fw_bin.dump_info('') + fw_bin = parse_fw_bin(args.sof_ri_path, args.no_cse, args.verbose) + + comp_filter = [] + if args.headers or args.no_modules: + comp_filter.append('Module Entry') + if args.no_headers: + comp_filter.append('CSE Manifest') + fw_bin.dump_info('', comp_filter) + if not args.no_memory: + mem = get_mem_map(args.sof_ri_path) + fw_bin.populate_mem_map(mem) + add_lmap_mem_info(args.sof_ri_path, mem) + print() + mem.dump_info() + + if args.erased_vars_image: + chk256 = EraseVariables(pathlib.Path(args.sof_ri_path), fw_bin, + args.erased_vars_image) + print('sha256sum {0}\n{1} {0}'.format(args.erased_vars_image, chk256)) + if __name__ == "__main__": ARGS = parse_params() diff --git a/tools/test/audio/README b/tools/test/audio/README deleted file mode 100644 index 488005a190a0..000000000000 --- a/tools/test/audio/README +++ /dev/null @@ -1,64 +0,0 @@ -SOF Audio Processing Components Tests -===================================== - -This is a set of test scripts to test that performance requirements -are met. The tests are currently for measured audio objective quality -parameters. The used criteria for performance is only an initial -assumption and need to be adjusted for various applications needs. - -The scripts support currently support the next list of objective -quality parameters. The test scripts need Matlab(R) [2] or GNU Octave -scientific programming language [3]. - - - Gain - - Frequency Response - - THD+N vs. Frequency - - Dynamic Range - - Attenuation of Alias Products - - Attenuation of Image Products - -Note: The metric is an effort to follow AES17 [1] recommendation for -parameters and test procedures. This was created to help developers to -quickly check their work but has not been verified to be -compliant. Professional equipment and formal calibration process is -recommended for professional applications where both accurate absolute -and relative metric is needed. - -Note: The test bench uses by default raw binary data files. It is -possible to convert with SoX (v14.4.1) [4] the raw data to e.g. wav -format for other audio tools and subjective listening. - -$ sox -b 32 -c 2 -r 48000 -L -e signed-integer fr_test_out.raw fr_test_out.wav - -For debugging purposes it is possible to switch from test scripts the -test vectors format to txt for easy manual data creation and -inspection. - - -Tests for component SRC ------------------------ - -The top level shell script to launch tests is src_test.sh. See script -src_run.sh for assumed install location of SOF host test bench -executable and component libraries. Exit code 0 indicates success and -exit code 1 indicates failed test cases. - -The default in/out rates matrix to test is defined in the beginning of -script src_test.m. The matrix can be also passed from calling function -src_test_top.m if need. - -The key objective quality parameters requiremements are in the -beginning of script src_test.m as well under comment Generic test -pass/fail criteria. - -Test run creates plots into directory "plots". Brief text format -reports are placed to directory "reports". - - -References ----------- - -[1] AES17-1015 standard, http://www.aes.org/publications/standards/search.cfm?docID=21 -[2] Matlab(R), https://www.mathworks.com/products/matlab.html -[3] GNU Octave, https://www.gnu.org/software/octave/ -[4] SoX - Sound eXchange, http://sox.sourceforge.net/ diff --git a/tools/test/audio/README.md b/tools/test/audio/README.md new file mode 100644 index 000000000000..e136e9aecf7e --- /dev/null +++ b/tools/test/audio/README.md @@ -0,0 +1,107 @@ +# SOF Audio Processing Components Tests + +### Test for processing components + +The script process_test.m provides tests to help to check that audio +performance requirements are met with run of SOF testbench with test +topologies. The tests are currently for measured audio objective +quality parameters. The used criteria for performance is only an +initial assumption and need to be adjusted for various applications +needs. + +The scripts support currently support the next list of objective +quality parameters. The test scripts need Matlab(R) [2] or GNU Octave +scientific programming language [3]. + + - Gain + - Frequency Response + - THD+N vs. Frequency + - Dynamic Range + - Attenuation of Alias Products + - Attenuation of Image Products + - Level Dependent Logarithmic Gain + +Note: The metric is an effort to follow AES17 [1] recommendation for +parameters and test procedures. This was created to help developers to +quickly check their work but has not been verified to be +compliant. Professional equipment and formal calibration process is +recommended for professional applications where both accurate absolute +and relative metric is needed. + +The process_test.m script is started from Octave or Matlab command shell. + +``` +octave --gui & +``` + +Examples of usage for it is shown with command help + +``` +help process_test +``` + +Tests for IIR equalizer with S32_LE input and output format with 48 +kHz rate, full test, plots shown, can be run with following command + +``` +process_test('eqiir', 32, 32, 48000, 1, 1); + +``` + +The components those can be tested with process_test are shown in the +next table. For sof-testbench4 use the 2nd column names,for +sof-testbench3 use the 3rd column names. + +| Component | IPC4 ID | IPC3 ID | +|---------------------------------|---------------|---------------| +| ARIA | aria | | +| ASRC | asrc | asrc | +| DC blocker | dcblock | dcblock | +| Dynamic range control | drc | drc | +| FIR equalizer | eqfir | eq-fir | +| Gain | gain | volume | +| IIR equalizer | eqiir | eq-iir | +| Multiband dynamic range control | drc_multiband | multiband-drc | +| SRC | src | src | +| Time domain fixed beamformer | tdfb | tdfb | + + +See README.md in tools/testbench provdes more information about using +the testbench. + +### Tests for component SRC and ASRC + +The Octave or Matlab script to test sample rate conversion is +src_test.m. See the help for src_test to see the usage. + +The top level shell script to launch tests is src_test.sh. See script +src_run.sh for assumed install location of SOF host test bench +executable and component libraries. Exit code 0 indicates success and +exit code 1 indicates failed test cases. + +The default in/out rates matrix to test is defined in the beginning of +script src_test.m. The matrix can be also passed from calling function +src_test_top.m if need. + +The key objective quality parameters requiremements are in the +beginning of script src_test.m as well under comment Generic test +pass/fail criteria. + +Test run creates plots into directory "plots". Brief text format +reports are placed to directory "reports". + +### Tests for component TDFB + +Scripts for testing special features of the multi-microphone beamformer +are in tdfb_test.m and tdfb_direction_test.m. See the help texts for usage. +Running the test needs special input files those have been created in blobs +export. See directory src/audio/tdfb/tune how to rebuild the blobs are +create simulation data files. + +References +---------- + +[1] AES17-2020 standard, http://www.aes.org/publications/standards/search.cfm?docID=21 +[2] Matlab(R), https://www.mathworks.com/products/matlab.html +[3] GNU Octave, https://www.gnu.org/software/octave/ +[4] SoX - Sound eXchange, http://sox.sourceforge.net/ diff --git a/tools/test/audio/asrc_run.sh b/tools/test/audio/asrc_run.sh index 217dc58a9fd5..ff7180951db2 100755 --- a/tools/test/audio/asrc_run.sh +++ b/tools/test/audio/asrc_run.sh @@ -2,13 +2,25 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2020 Intel Corporation. All rights reserved. -if [ -z "$6" ]; then - echo "Usage: $0 <bits in> <bits out> <rate in> <rate out> <input> <output>" - echo "Example: $0 16 16 32000 48000 input.raw output.raw" - exit -fi +usage () +{ + echo "Usage: $1 <bits in> <bits out> <rate in> <rate out> <input> <output>" + echo "Example: $1 16 16 32000 48000 input.raw output.raw" +} -COMP=asrc -DIRECTION=playback +main() +{ + local COMP DIRECTION -./comp_run.sh $COMP $DIRECTION $1 $2 $3 $4 $5 $6 + if [ $# -ne 6 ]; then + usage "$0" + exit + fi + + COMP=asrc + DIRECTION=playback + + ./comp_run.sh $COMP $DIRECTION "$@" +} + +main "$@" diff --git a/tools/test/audio/comp_run.sh b/tools/test/audio/comp_run.sh index c6b8dd337f56..096ff2c341c0 100755 --- a/tools/test/audio/comp_run.sh +++ b/tools/test/audio/comp_run.sh @@ -2,46 +2,199 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018-2020 Intel Corporation. All rights reserved. -COMP=$1 -DIRECTION=$2 -BITS_IN=$3 -BITS_OUT=$4 -FS1=$5 -FS2=$6 -FN_IN=$7 -FN_OUT=$8 - -# 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 -TPLG_DIR=../../test/topology +# stop on most errors +set -e + +usage () +{ + cat <<EOFHELP +Usage: $0 <options> <comp direction bits_in bits_out fs_in fs_out input output> +Example 1: $0 volume playback 16 16 48000 48000 input.raw output.raw +Example 2: $0 -e volume_trace.txt -t volume_config.sh + +Where volume_config.sh could be e.g. next. Minimal configuration need is only +the COMP line. + +# Volume component configuration +COMP=gain +DIRECTION=playback +BITS_IN=16 +BITS_OUT=16 +CHANNELS_IN=2 +CHANNELS_OUT=2 +FS_IN=48000 +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=true +XTRUN= +TESTBENCH=sof-testbench4 +EOFHELP +} + +parse_args () +{ + # Defaults + DIRECTION=playback + BITS_IN=16 + BITS_OUT= + CHANNELS_IN=2 + CHANNELS_OUT= + FS_IN=48000 + FS_OUT= + VALGRIND=true + DEBUG= + SOURCED_CONFIG=false + FN_TRACE= + EXTRA_OPTS= + XTRUN= + TESTBENCH=sof-testbench4 + + 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 + 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" + fi + + if [[ -z $BITS_OUT ]]; then + BITS_OUT=$BITS_IN + fi + + if [[ -z $FS_OUT ]]; then + FS_OUT=$FS_IN + fi + + if [[ -z $CHANNELS_OUT ]]; then + CHANNELS_OUT=$CHANNELS_IN + fi +} + +delete_file_check () +{ + if [ -f "$1" ]; then + rm -f "$1" + fi +} + +run_testbench () +{ + delete_file_check "$FN_OUT" + delete_file_check "$FN_TRACE" + if [ -z "$FN_TRACE" ]; then + # shellcheck disable=SC2086 + $VALGRIND_CMD $CMD + else + $VALGRIND_CMD $CMD 2> "$FN_TRACE" || { + local ret=$? + echo ---------------------------------------------------------- + cat "$FN_TRACE" + echo ---------------------------------------------------------- + return $ret # "exit" would be for something unexpected and catastrophic, + # not for a "regular" test failure + } + fi +} + +parse_args "$@" + +# Path to topologies +TPLG_DIR=../../build_tools/test/topology + +# Testbench path and executable +if [[ -z $XTRUN ]]; then + PATH_TESTBENCH=../../testbench/build_testbench/install/bin/$TESTBENCH +else + BUILD_DIR=../../testbench/build_xt_testbench + PATH_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 $PATH_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_BUILD_TIP="Please run scripts/build-tools.sh -t" +PIPELINES= + +[[ $TESTBENCH == "sof-testbench4" ]] && { + # With comp benchmark topologies for playback use pipelines 1-2, for capture 3-4 + [[ $DIRECTION == "playback" ]] && PIPELINES="-p 1,2" + [[ $DIRECTION == "capture" ]] && PIPELINES="-p 3,4" + TPLGFN=sof-hda-benchmark-${COMP}${BITS_IN}.tplg + TPLG_DIR="../../build_tools/topology/topology2/development" + TPLG_BUILD_TIP="Please run scripts/build-tools.sh" +} + TPLG=${TPLG_DIR}/${TPLGFN} +[ -f "$TPLG" ] || { + echo + echo "Error: topology $TPLG does not exist." + echo "$TPLG_BUILD_TIP" + exit 1 +} # If binary test vectors -if [ ${FN_IN: -4} == ".raw" ]; then +if [ "${FN_IN: -4}" == ".raw" ]; then BINFMT="-b S${BITS_IN}_LE" else BINFMT="" fi # Run command -# There is no more need to specify the library explicitly -#LIB="-a ${COMP}=libsof_${COMP}.so" -LIB="" -ARG="-d -r $FS1 -R $FS2 -i $FN_IN -o $FN_OUT -t $TPLG $BINFMT $LIB" +OPTS="$DEBUG -r $FS_IN -R $FS_OUT -c $CHANNELS_IN -n $CHANNELS_OUT $BINFMT $PIPELINES -t $TPLG" +DATA="-i $FN_IN -o $FN_OUT" +ARG="$OPTS $EXTRA_OPTS $DATA" CMD="$HOST_EXE $ARG" -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}" -$CMD +run_testbench diff --git a/tools/test/audio/dcblock_run.sh b/tools/test/audio/dcblock_run.sh new file mode 100755 index 000000000000..4c4d5c3037f9 --- /dev/null +++ b/tools/test/audio/dcblock_run.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause + +usage () +{ + echo "Usage: $0 <bits in> <bits out> <rate> <input> <output>" + echo "Example: $0 16 16 48000 input.raw output.raw" +} + +main () +{ + local COMP DIRECTION + + if [ $# -ne 5 ]; then + usage "$0" + exit + fi + + COMP=dcblock + DIRECTION=playback + + ./comp_run.sh $COMP $DIRECTION "$1" "$2" "$3" "$3" "$4" "$5" +} + +main "$@" diff --git a/tools/test/audio/eqfir_run.sh b/tools/test/audio/eqfir_run.sh index 1360c04bb81b..923029d37980 100755 --- a/tools/test/audio/eqfir_run.sh +++ b/tools/test/audio/eqfir_run.sh @@ -2,13 +2,25 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2020 Intel Corporation. All rights reserved. -if [ -z "$5" ]; then +usage () +{ echo "Usage: $0 <bits in> <bits out> <rate> <input> <output>" echo "Example: $0 16 16 48000 input.raw output.raw" - exit -fi +} -COMP=eq-fir -DIRECTION=playback +main () +{ + local COMP DIRECTION -./comp_run.sh $COMP $DIRECTION $1 $2 $3 $3 $4 $5 + if [ $# -ne 5 ]; then + usage "$0" + exit + fi + + COMP=eq-fir + DIRECTION=playback + + ./comp_run.sh $COMP $DIRECTION "$1" "$2" "$3" "$3" "$4" "$5" +} + +main "$@" diff --git a/tools/test/audio/eqiir_run.sh b/tools/test/audio/eqiir_run.sh index 833f03202f5f..8d5737c9ec74 100755 --- a/tools/test/audio/eqiir_run.sh +++ b/tools/test/audio/eqiir_run.sh @@ -2,14 +2,28 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2020 Intel Corporation. All rights reserved. -if [ -z "$5" ]; then +# stop on most errors +set -e + +usage () +{ echo "Usage: $0 <bits in> <bits out> <rate> <input> <output>" echo "Example: $0 16 16 48000 input.raw output.raw" - exit -fi +} + +main () +{ + local COMP DIRECTION + + if [ $# -ne 5 ]; then + usage "$0" + exit 1 + fi + COMP=eq-iir + DIRECTION=playback -COMP=eq-iir -DIRECTION=playback + ./comp_run.sh $COMP $DIRECTION "$1" "$2" "$3" "$3" "$4" "$5" +} -./comp_run.sh $COMP $DIRECTION $1 $2 $3 $3 $4 $5 +main "$@" diff --git a/tools/test/audio/process_test.m b/tools/test/audio/process_test.m new file mode 100644 index 000000000000..1af293b1967a --- /dev/null +++ b/tools/test/audio/process_test.m @@ -0,0 +1,472 @@ +% process_test - test objective audio quality parameters +% +% process_test(comp, bits_in_list, bits_out_list, fs, fulltest, show_plots, 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 +% show_plots - use 1 to show, defaults to hidden with 0 +% with value 2 also temporary sound files are preserved +% xtrun - set to 'xt-run' or 'xt-run --turbo' to test with xt-testbench +% +% E.g. +% process_test('eqiir', 32, 32, 48000, 0, 0, 'xt-run --turbo'); +% process_test('eqiir', 32, 32); + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2017-2022 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function [n_fail, n_pass, n_na] = process_test(comp, bits_in_list, bits_out_list, fs, fulltest, show_plots, xtrun) + %% Defaults for call parameters + if nargin < 1 + comp = 'eqiir'; + end + + if nargin < 2 + bits_in_list = 32; + end + + if nargin < 3 + bits_out_list = 32; + end + + if nargin < 4 + fs = 48e3; + end + + if nargin < 5 + fulltest = 1; + end + + if nargin < 6 + show_plots = 0; + end + + if nargin < 7 + xtrun = ''; + end + + %% Paths + t.blobpath = '../../topology/topology1/m4'; + plots = 'plots'; + reports = 'reports'; + + %% Defaults for test + t.comp = comp; % Pass component name from func arguments + t.fmt = 'raw'; % Can be 'raw' (fast binary) or 'txt' (debug) + t.iirblob = 'eq_iir_coef_loudness.m4'; % Use loudness type response + t.firblob = 'eq_fir_coef_loudness.m4'; % Use loudness type response + t.fs = fs; % Sample rate from func arguments + t.nch = 2; % Number of channels + t.ch = [1 2]; % Test channel 1 and 2 + 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 + % 1 shows only flashing windows while the test proceeds. With + % visibility set to 0 only console text is seen. The plots are + % exported into plots directory in png format and can be viewed from + % there. + if show_plots > 0 + t.plot_close_windows = 0; % Workaround for visible windows if Octave hangs + t.plot_visible = 'on'; % Use off for batch tests and on for interactive + else + t.plot_close_windows = 1; + t.plot_visible = 'off'; + end + + if show_plots > 1 + t.files_delete = 0; % Set to 0 to inspect the audio data files + else + t.files_delete = 1; + end + + %% Prepare + process_test_paths(true); + mkdir_check(plots); + mkdir_check(reports); + 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); + r.n_fail = 0; + r.n_pass = 0; + r.n_skipped = 0; + r.n_na = 0; + + %% Loop all modes to test + for b = 1:n_bits_out + for a = 1:n_bits_in + v = -ones(n_meas,1); % Set pass/fail test verdict to not executed + tn = 1; + t.bits_in = bits_in_list(a); + t.bits_out = bits_out_list(b); + + v(1) = chirp_test(t); + if v(1) ~= -1 && t.full_test + [v(2), g] = g_test(t); + [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 + + %% Done, store pass/fail + if v(1) ~= -1 + idx = find(v > 0); + r.n_fail = r.n_fail + length(idx); + idx = find(v == 0); + r.n_pass = r.n_pass + length(idx); + idx = find(v == -1); + r.n_skipped = r.n_skipped + length(idx); + idx = find(v == -2); + r.n_na = r.n_na + length(idx); + end + end + end + + %% FIXME: get unique string to keep all the incremental logs, like datetime string. + %% For now bitspersample is differentiator. + + %% Print table with test summary: Gain + fn = sprintf('%s/g_%s_%d.txt', reports, t.comp, t.bits_in); + print_val(t.comp, 'Gain (dB)', fn, bits_in_list, bits_out_list, r.g, r.pf); + + %% Print table with test summary: DR + fn = sprintf('%s/dr_%s_%d.txt', reports, t.comp, t.bits_in); + print_val(t.comp, 'Dynamic range (dB CCIR-RMS)', fn, bits_in_list, bits_out_list, r.dr, r.pf); + + %% Print table with test summary: THD+N vs. frequency + 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/LDLG'); + + fprintf('\n'); + fprintf('============================================================\n'); + fprintf('Number of passed tests = %d\n', r.n_pass); + fprintf('Number of failed tests = %d\n', r.n_fail); + fprintf('Number of non-applicable tests = %d\n', r.n_na); + fprintf('Number of skipped tests = %d\n', r.n_skipped); + fprintf('============================================================\n'); + + n_fail = r.n_fail; + n_pass = r.n_pass; + n_na = r.n_na; + if r.n_fail < 1 && r.n_pass < 1 + fprintf('\nERROR: No test results.\n'); + n_fail = 1; + elseif r.n_fail > 0 + fprintf('\nERROR: TEST FAILED!!!\n'); + else + fprintf('\nTest passed.\n'); + end + + process_test_paths(false); +end + +%% ------------------------------------------------------------ +%% Test execution with help of common functions +%% + +function fail = chirp_test(t) + fprintf('Spectrogram test %d Hz ...\n', t.fs); + + % Create input file + test = test_defaults(t); + test = chirp_test_input(test); + + % Run test + test = test_run_process(test); + + % Analyze + test = chirp_test_analyze(test); + test_result_print(t, 'Continuous frequency sweep', 'chirpf', test); + + % Delete files unless e.g. debugging and need data to run + delete_check(t.files_delete, test.fn_in); + delete_check(t.files_delete, test.fn_out); + + fail = test.fail; +end + + +%% Reference: AES17 6.2.2 Gain +function [fail, g_db] = g_test(t) + test = test_defaults(t); + + % Create input file + test = g_test_input(test); + + % Run test + test = test_run_process(test); + + % Measure + test = g_spec(test, t); + test = g_test_measure(test); + + % Get output parameters + fail = test.fail; + g_db = test.g_db; + delete_check(t.files_delete, test.fn_in); + delete_check(t.files_delete, test.fn_out); +end + +%% Reference: AES17 6.4.1 Dynamic range +function [fail, dr_db] = dr_test(t) + test = test_defaults(t); + + % Create input file + test = dr_test_input(test); + + % Run test + test = test_run_process(test); + + % Measure + test = dr_test_measure(test); + + % Get output parameters + fail = test.fail; + dr_db = test.dr_db; + delete_check(t.files_delete, test.fn_in); + delete_check(t.files_delete, test.fn_out); +end + +%% Reference: AES17 6.3.2 THD+N ratio vs. frequency +function [fail, thdnf] = thdnf_test(t) + test = test_defaults(t); + + % Create input file + test = thdnf_test_input(test); + + % Run test + test = test_run_process(test); + + % Measure + test = thdnf_mask(test); + test = thdnf_test_measure(test); + + % For EQ use the -20dBFS result and ignore possible -1 dBFS fail + thdnf = max(test.thdnf_low); + fail = test.fail; + delete_check(t.files_delete, test.fn_in); + delete_check(t.files_delete, test.fn_out); + + % Print + test_result_print(t, 'THD+N ratio vs. frequency', 'THDNF', test); +end + +%% Reference: AES17 6.2.3 Frequency response +function fail = fr_test(t) + test = test_defaults(t); + + % Create input file + test = fr_test_input(test); + + % Run test + test = test_run_process(test); + + % Measure + test = fr_mask(test, t); + test = fr_test_measure(test); + fail = test.fail; + delete_check(t.files_delete, test.fn_in); + delete_check(t.files_delete, test.fn_out); + + % Print + 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 + +function test = thdnf_mask(test) + min_bits = min(test.bits_in, test.bits_out); + test.thdnf_mask_f = [50 400 test.f_max]; + test.thdnf_mask_hi = [-40 -50 -50]; +end + +function test = g_spec(test, prm) + switch lower(test.comp) + case {'eq-iir', 'eqiir'} + blob = fullfile(prm.blobpath, prm.iirblob); + h = sof_eq_blob_plot(blob, 'iir', test.fs, test.f, 0); + case {'eq-fir', 'eqfir'} + blob = fullfile(prm.blobpath, prm.firblob); + h = sof_eq_blob_plot(blob, 'fir', test.fs, test.f, 0); + otherwise + test.g_db_expect = zeros(1, test.nch); + return + end + + test.g_db_expect = h.m(:, test.ch); +end + +function test = fr_mask(test, prm) + switch lower(test.comp) + case {'eq-iir', 'eqiir'} + blob = fullfile(prm.blobpath, prm.iirblob); + h = sof_eq_blob_plot(blob, 'iir', test.fs, test.f, 0); + case {'eq-fir', 'eqfir'} + blob = fullfile(prm.blobpath, prm.firblob); + h = sof_eq_blob_plot(blob, 'fir', test.fs, test.f, 0); + otherwise + % Define a generic mask for frequency response, generally + % all processing at 8 kHz or above should pass, if not + % or need for tighter criteria define per component other + % target. + test.fr_mask_fhi = [20 test.f_max]; + test.fr_mask_flo = [200 400 3500 3600 ]; + for i = 1:test.nch + test.fr_mask_mhi(:,i) = [ 1 1 ]; + test.fr_mask_mlo(:,i) = [-10 -1 -1 -10]; + end + return + end + + % Create mask from theoretical frequency response calculated from decoded + % response in h and align mask to be relative to 997 Hz response + i997 = find(test.f > 997, 1, 'first')-1; + j = 1; + for channel = test.ch + m = h.m(:, channel) - h.m(i997, channel); + test.fr_mask_flo = test.f; + test.fr_mask_fhi = test.f; + test.fr_mask_mlo(:,j) = m - test.fr_rp_max_db; + test.fr_mask_mhi(:,j) = m + test.fr_rp_max_db; + j = j + 1; + end +end + +function test = test_defaults(t) + test.comp = t.comp; + test.fmt = t.fmt; + test.bits_in = t.bits_in; + test.bits_out = t.bits_out; + test.nch = t.nch; + test.ch = t.ch; + test.fs = t.fs; + test.plot_visible = t.plot_visible; + test.xtrun = t.xtrun; + + % Misc + test.quick = 0; + test.att_rec_db = 0; + + % Plotting + test.plot_channels_combine = 1; + test.plot_thdn_axis = []; + test.plot_fr_axis = []; + test.plot_passband_zoom = 0; + + % Test constraints + test.f_start = 20; + test.f_end = test.fs * 0.41667; % 20 kHz @ 48 kHz + test.fu = test.fs * 0.41667; % 20 kHz @ 48 kHz + test.f_max = 0.999*t.fs/2; % Measure up to min. Nyquist frequency + test.fs1 = test.fs; + test.fs2 = test.fs; + + % Pass criteria + test.g_db_tol = 0.1; % Allow 0.1 dB gain variation + test.thdnf_max = []; % Set per component + test.dr_db_min = 80; % Min. DR + test.fr_rp_max_db = 0.5; % Allow 0.5 dB frequency response ripple + + % No need to collect trace + test.trace = [tempname('/tmp') '.txt']; +end + +function test = test_run_process(test) + delete_check(1, test.fn_out); + test = test_run(test); + delete_check(1, test.trace); +end + +function test_result_print(t, testverbose, testacronym, test) + tstr = sprintf('%s %s %d-%d %d Hz', ... + testverbose, t.comp, t.bits_in, t.bits_out, t.fs); + + %% FIXME: get unique string to keep all the incremental logs + + for i = 1:length(test.ph) + title(test.ph(i), tstr, 'Interpreter', 'none'); + end + + for i = 1:length(test.fh) + figure(test.fh(i)); + set(test.fh(i), 'visible', test.plot_visible); + pfn = sprintf('plots/%s_%s_%d_%d_%d_%d.png', ... + testacronym, t.comp, ... + t.bits_in, t.bits_out, t.fs, i); + print(pfn, '-dpng'); + end +end + +function process_test_paths(enable) + + sof_src_audio = '../../../src/audio'; + if enable + addpath('std_utils'); + addpath('test_utils'); + addpath('../../tune/common'); + addpath([sof_src_audio '/eq_iir/tune']); + else + rmpath('std_utils'); + rmpath('test_utils'); + rmpath('../../tune/common'); + rmpath([sof_src_audio '/eq_iir/tune']); + end +end diff --git a/tools/test/audio/src_run.sh b/tools/test/audio/src_run.sh index 277388a15dd0..93676f7c3247 100755 --- a/tools/test/audio/src_run.sh +++ b/tools/test/audio/src_run.sh @@ -2,13 +2,28 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018-2020 Intel Corporation. All rights reserved. -if [ -z "$6" ]; then - echo "Usage: $0 <bits in> <bits out> <rate in> <rate out> <input> <output>" - echo "Example: $0 16 16 32000 48000 input.raw output.raw" - exit -fi +# stop on most errors +set -e -COMP=src -DIRECTION=playback +usage () +{ + echo "Usage: $1 <bits in> <bits out> <rate in> <rate out> <input> <output>" + echo "Example: $1 16 16 32000 48000 input.raw output.raw" +} -./comp_run.sh $COMP $DIRECTION $1 $2 $3 $4 $5 $6 +main() +{ + local COMP DIRECTION + + if [ $# -ne 6 ]; then + usage "$0" + exit 1 + fi + + COMP=src + DIRECTION=playback + + ./comp_run.sh $COMP $DIRECTION "$@" +} + +main "$@" diff --git a/tools/test/audio/src_test.m b/tools/test/audio/src_test.m index 5d9b95e44da4..6b28b62693d9 100644 --- a/tools/test/audio/src_test.m +++ b/tools/test/audio/src_test.m @@ -1,30 +1,39 @@ -function [n_fail, n_pass, n_na] = src_test(bits_in, bits_out, fs_in_list, fs_out_list) +function [n_fail, n_pass, n_na] = src_test(bits_in, bits_out, fs_in_list, fs_out_list, full_test, show_plots, comp, xtrun) %% % src_test - test with SRC test bench objective audio quality parameters % -% src_test(bits_in, bits_out, fs_in, fs_out) +% src_test(bits_in, bits_out, fs_in, fs_out, full_test, show_plots, comp, xtrun) % -% bits_in - input word length -% bits_out - output word length -% fs_in - vector of rates in -% fs_out - vector of rates out +% bits_in - input word length +% bits_out - output word length +% fs_in - vector of rates in, default 8 to 192 kHz +% fs_out - vector of rates out, default 8 to 192 kHz +% full_test - set to 0 for chirp only, 1 for all, default 1 +% show_plots - set to 1 to see plots, default 0 +% comp - set to 'src' or 'asrc', default 'src' +% xtrun - set to 'xt-run' or 'xt-run --turbo' to test with xt-testbench +% +% E.g. +% src_test(32, 32, 44100, 48000, 1, 1, 'src', 'xt-run --turbo'); % % A default in-out matrix with 32 bits data is tested if the -% paremeters are omitted. +% parameters are omitted. % % SPDX-License-Identifier: BSD-3-Clause -% Copyright(c) 2016 Intel Corporation. All rights reserved. +% Copyright(c) 2016-2025 Intel Corporation. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> addpath('std_utils'); addpath('test_utils'); -addpath('../../tune/src'); +addpath('../../../src/audio/src/tune'); mkdir_check('plots'); mkdir_check('reports'); %% Defaults for call parameters +default_in = [ 8 11.025 12 16 18.9 22.050 24 32 37.8 44.1 48 50 64 88.2 96 176.4 192] * 1e3; +default_out = [ 8 11.025 12 16 22.05 24 32 44.1 48 50 64 88.2 96 176.4 192] * 1e3; if nargin < 1 bits_in = 32; end @@ -32,11 +41,28 @@ bits_out = 32; end if nargin < 3 - fs_in_list = [8 11.025 12 16 22.050 24 32 44.1 48 ... - 50 64 88.2 96 176.4 192] * 1e3; + fs_in_list = default_in; end if nargin < 4 - fs_out_list = [8 11.025 12 16 22.05 24 32 44.1 48 50] * 1e3; + fs_out_list = default_out; +end +if nargin < 5 + full_test = 1; +end +if nargin < 6 + show_plots = 0; +end +if nargin < 7 + comp = 'src'; +end +if nargin < 8 + xtrun = ''; +end +if isempty(fs_in_list) + fs_in_list = default_in; +end +if isempty(fs_out_list) + fs_out_list = default_out; end %% Generic test pass/fail criteria @@ -53,12 +79,14 @@ t.aip_db_max = -60; %% Defaults for test -t.fmt = 'raw'; % Can be 'raw' (fast binary) or 'txt' (debug) -t.nch = 2; % Number of channels -t.ch = 0; % 1..nch. With value 0 test a randomly selected channel. -t.bits_in = bits_in; % Input word length -t.bits_out = bits_out; % Output word length -t.full_test = 1; % 0 is quick check only, 1 is full set +t.fmt = 'raw'; % Can be 'raw' (fast binary) or 'txt' (debug) +t.nch = 2; % Number of channels +t.ch = 0; % 1..nch. With value 0 test a randomly selected channel. +t.bits_in = bits_in; % Input word length +t.bits_out = bits_out; % Output word length +t.full_test = full_test; % 0 is quick check only, 1 is full set +t.comp = comp; % Component to 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 @@ -66,8 +94,13 @@ % visibility set to to 0 only console text is seen. The plots are % exported into plots directory in png format and can be viewed from % there. -t.plot_close_windows = 1; % Workaround for visible windows if Octave hangs -t.plot_visible = 'off'; % Use off for batch tests and on for interactive +if show_plots + t.plot_close_windows = 0; + t.plot_visible = 'on'; +else + t.plot_close_windows = 1; % Workaround for visible windows if Octave hangs + t.plot_visible = 'off'; % Use off for batch tests and on for interactive +end t.files_delete = 1; % Set to 0 to inspect the audio data files %% Init for test loop @@ -93,7 +126,6 @@ for b = 1:n_fso for a = 1:n_fsi v = -ones(n_test,1); % Set pass/fail test verdict to not executed - tn = 1; t.fs1 = fs_in_list(a); t.fs2 = fs_out_list(b); v(1) = chirp_test(t); @@ -121,43 +153,45 @@ end end +%% Scale frequencies to kHz +k = 1/1000; + %% Print table with test summary: Gain fn = 'reports/g_src.txt'; -print_val(fn, fs_in_list, fs_out_list, r.g, r.pf, 'Gain dB'); +print_val('SRC', 'Gain dB', fn, k * fs_in_list, k * fs_out_list, r.g, r.pf); %% Print table with test summary: FR fn = 'reports/fr_src.txt'; -print_fr(fn, fs_in_list, fs_out_list, r.fr_db, r.fr_hz, r.pf); +print_fr('SRC', fn, k * fs_in_list, k * fs_out_list, r.fr_db, r.fr_hz, r.pf); %% Print table with test summary: FR fn = 'reports/fr_src.txt'; -print_val(fn, fs_in_list, fs_out_list, r.fr3db_hz/1e3, r.pf, ... - 'Frequency response -3 dB 0 - X kHz'); +print_val('SRC', 'Frequency response -3 dB 0 - X kHz', ... + fn, k * fs_in_list, k * fs_out_list, r.fr3db_hz/1e3, r.pf); %% Print table with test summary: THD+N vs. frequency fn = 'reports/thdnf_src.txt'; -print_val(fn, fs_in_list, fs_out_list, r.thdnf, r.pf, ... - 'Worst-case THD+N vs. frequency'); +print_val('SRC', 'Worst-case THD+N vs. frequency', ... + fn, k * fs_in_list, k * fs_out_list, r.thdnf, r.pf); %% Print table with test summary: DR fn = 'reports/dr_src.txt'; -print_val(fn, fs_in_list, fs_out_list, r.dr, r.pf, ... - 'Dynamic range dB (CCIR-RMS)'); +print_val('SRC', 'Dynamic range dB (CCIR-RMS)', ... + fn, k * fs_in_list, k * fs_out_list, r.dr, r.pf); %% Print table with test summary: AAP fn = 'reports/aap_src.txt'; -print_val(fn, fs_in_list, fs_out_list, r.aap, r.pf, ... - 'Attenuation of alias products dB'); +print_val('SRC', 'Attenuation of alias products dB', ... + fn, k * fs_in_list, k * fs_out_list, r.aap, r.pf); %% Print table with test summary: AIP fn = 'reports/aip_src.txt'; -print_val(fn, fs_in_list, fs_out_list, r.aip, r.pf, ... - 'Attenuation of image products dB'); - +print_val('SRC', 'Attenuation of image products dB', ... + fn, k * fs_in_list, k * fs_out_list, r.aip, r.pf); %% Print table with test summary: pass/fail fn = 'reports/pf_src.txt'; -print_pf(fn, fs_in_list, fs_out_list, r.pf); +print_pf('SRC', fn, k * fs_in_list, k * fs_out_list, r.pf, 'chirp/gain/FR/THD+N/DR/AAP/AIP'); fprintf('\n'); fprintf('Number of passed tests = %d\n', r.n_pass); @@ -200,7 +234,7 @@ test = g_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Measure test.fs = t.fs2; @@ -220,16 +254,16 @@ test = test_defaults_src(t); prm = src_param(t.fs1, t.fs2, test.coef_bits); -test.fr_rp_max_db = prm.rp_tot; % Max. ripple +/- dB allowed -test.f_lo = 20; % For response reporting, measure from 20 Hz -test.f_hi = 0.99 * min(t.fs1,t.fs2)*prm.c_pb; % to designed filter upper frequency -test.f_max = 0.99 * min(t.fs1/2, t.fs2/2); % Measure up to Nyquist frequency +test.fr_rp_max_db = prm.rp_tot; % Max. ripple +/- dB allowed +test.fr_lo = 20; % Ripple measure from 20 Hz +test.fr_hi = 0.99 * min(t.fs1,t.fs2)*prm.c_pb; % up to Nyquist frequency +test.f_max = 0.99 * min(t.fs1/2, t.fs2/2); % Measure up to Nyquist frequency %% Create input file test = fr_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Measure test.fs = t.fs2; @@ -237,7 +271,7 @@ fail = test.fail; pm_range_db = test.rp; -range_hz = [test.f_lo test.f_hi]; +range_hz = [test.fr_lo test.fr_hi]; fr3db_hz = test.fr3db_hz; delete_check(t.files_delete, test.fn_in); delete_check(t.files_delete, test.fn_out); @@ -259,16 +293,14 @@ prm = src_param(t.fs1, t.fs2, test.coef_bits); test.f_start = 20; -test.f_end = prm.c_pb*min(t.fs1, t.fs2); -test.fu = prm.c_pb*min(t.fs1, t.fs2); -%test.f_end = 0.4535*min(t.fs1, t.fs2); -%test.fu = 0.4535*min(t.fs1, t.fs2); +test.f_end = min(prm.c_pb * min(t.fs1, t.fs2), 20e3); +test.fu = min(prm.c_pb * t.fs2, 20e3); % AES17 5.2.5 standard low pass as 20 kHz %% Create input file test = thdnf_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Measure test.fs = t.fs2; @@ -297,7 +329,7 @@ test = dr_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Measure test.fs = t.fs2; @@ -332,7 +364,7 @@ test = aap_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Measure test.fs = t.fs2; @@ -365,7 +397,7 @@ test = aip_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Measure test.fs = t.fs2; @@ -384,7 +416,7 @@ % in the plot as additional freqiencies than main linear up sweep. The aliasing % can be a line, few lines, or lattice pattern depending the SRC conversion % to test. The main sweep line should be steady level and extend from near -% zero freqeuncy to near Nyquist (Fs/2). +% zero frequency to near Nyquist (Fs/2). function fail = chirp_test(t) @@ -395,12 +427,14 @@ test = chirp_test_input(test); %% Run test -test = test_run_src(test, t); +test = test_run_src(test); %% Analyze test.fs = t.fs2; test = chirp_test_analyze(test); -src_test_result_print(t, 'Chirp', 'chirpf'); +if test.fail >= 0 + src_test_result_print(t, 'Chirp', 'chirpf'); +end % Delete files unless e.g. debugging and need data to run delete_check(t.files_delete, test.fn_in); @@ -414,6 +448,7 @@ %% function test = test_defaults_src(t) +test.comp = t.comp; test.fmt = t.fmt; test.bits_in = t.bits_in; test.bits_out = t.bits_out; @@ -422,9 +457,7 @@ test.fs = t.fs1; test.fs1 = t.fs1; test.fs2 = t.fs2; -test.fr_mask_f = []; -test.fr_mask_lo = []; -test.fr_mask_hi = []; +test.xtrun = t.xtrun; test.coef_bits = 24; % No need to use actual word length in test test.att_rec_db = 0; % Not used in simulation test test.quick = 0; % Test speed is no issue in simulation @@ -432,172 +465,34 @@ test.plot_channels_combine = 0; test.plot_passband_zoom = 1; test.plot_fr_axis = [10 100e3 -4 1]; -test.plot_thdn_axis = [10 100e3 -140 -60]; -end - -function test = test_run_src(test, t) -test.ex = './src_run.sh'; -test.arg = { num2str(t.bits_in), num2str(t.bits_out), num2str(t.fs1), num2str(t.fs2), test.fn_in, test.fn_out}; +test.plot_thdn_axis = [10 100e3 -140 -59]; +test.fr_mask_flo = []; +test.fr_mask_fhi = []; +test.fr_mask_mlo = []; +test.fr_mask_mhi = []; +test.thdnf_mask_f = []; +test.thdnf_mask_hi = []; +test.thdnf_max = []; +end + +function test = test_run_src(test) +test.fs_in = test.fs1; +test.fs_out = test.fs2; +test.extra_opts = '-C 300000'; % Limit to 5 min max, assume 1 ms scheduling delete_check(1, test.fn_out); test = test_run(test); end function src_test_result_print(t, testverbose, testacronym, ph) tstr = sprintf('%s SRC %d, %d', testverbose, t.fs1, t.fs2); -if nargin > 3 - title(ph, tstr); +if nargin > 3 && ~isempty(ph) + title(ph, tstr, 'Interpreter', 'none'); else - title(tstr); + title(tstr, 'Interpreter', 'none'); end pfn = sprintf('plots/%s_src_%d_%d.png', testacronym, t.fs1, t.fs2); -% The print command caused a strange error with __osmesa_print__ -% so disable it for now until solved. -%print(pfn, '-dpng'); +print(pfn, '-dpng'); if t.plot_close_windows close all; end end - -%% The next are results printing functions - -function print_val(fn, fs_in_list, fs_out_list, val, pf, valstr) -n_fsi = length(fs_in_list); -n_fso = length(fs_out_list); -fh = fopen(fn,'w'); -fprintf(fh,'\n'); -fprintf(fh,'SRC test result: %s\n', valstr); -fprintf(fh,'%8s, ', 'in \ out'); -for a = 1:n_fso-1 - fprintf(fh,'%8.1f, ', fs_out_list(a)/1e3); -end -fprintf(fh,'%8.1f', fs_out_list(n_fso)/1e3); -fprintf(fh,'\n'); -for a = 1:n_fsi - fprintf(fh,'%8.1f, ', fs_in_list(a)/1e3); - for b = 1:n_fso - if pf(a,b,1) < 0 - cstr = 'x'; - else - if isnan(val(a,b)) - cstr = '-'; - else - cstr = sprintf('%8.2f', val(a,b)); - end - end - if b < n_fso - fprintf(fh,'%8s, ', cstr); - else - fprintf(fh,'%8s', cstr); - end - end - fprintf(fh,'\n'); -end -fclose(fh); -type(fn); -end - -function print_fr(fn, fs_in_list, fs_out_list, fr_db, fr_hz, pf) -n_fsi = length(fs_in_list); -n_fso = length(fs_out_list); -fh = fopen(fn,'w'); -fprintf(fh,'\n'); -fprintf(fh,'SRC test result: Frequency response +/- X.XX dB (YY.Y kHz) \n'); -fprintf(fh,'%8s, ', 'in \ out'); -for a = 1:n_fso-1 - fprintf(fh,'%12.1f, ', fs_out_list(a)/1e3); -end -fprintf(fh,'%12.1f', fs_out_list(n_fso)/1e3); -fprintf(fh,'\n'); -for a = 1:n_fsi - fprintf(fh,'%8.1f, ', fs_in_list(a)/1e3); - for b = 1:n_fso - if pf(a,b,1) < 0 - cstr = 'x'; - else - cstr = sprintf('%4.2f (%4.1f)', fr_db(a,b), fr_hz(a,b,2)/1e3); - end - if b < n_fso - fprintf(fh,'%12s, ', cstr); - else - fprintf(fh,'%12s', cstr); - end - end - fprintf(fh,'\n'); -end -fclose(fh); -type(fn); -end - -function print_fr3db(fn, fs_in_list, fs_out_list, fr3db_hz, pf) -n_fsi = length(fs_in_list); -n_fso = length(fs_out_list); -fh = fopen(fn,'w'); -fprintf(fh,'\n'); -fprintf(fh,'SRC test result: Frequency response -3dB 0 - X.XX kHz\n'); -fprintf(fh,'%8s, ', 'in \ out'); -for a = 1:n_fso-1 - fprintf(fh,'%8.1f, ', fs_out_list(a)/1e3); -end -fprintf(fh,'%8.1f', fs_out_list(n_fso)/1e3); -fprintf(fh,'\n'); -for a = 1:n_fsi - fprintf(fh,'%8.1f, ', fs_in_list(a)/1e3); - for b = 1:n_fso - if pf(a,b,1) < 0 - cstr = 'x'; - else - cstr = sprintf('%4.1f', fr3db_hz(a,b)/1e3); - end - if b < n_fso - fprintf(fh,'%8s, ', cstr); - else - fprintf(fh,'%8s', cstr); - end - end - fprintf(fh,'\n'); -end -fclose(fh); -type(fn); -end - - -function print_pf(fn, fs_in_list, fs_out_list, pf) -n_fsi = length(fs_in_list); -n_fso = length(fs_out_list); -fh = fopen(fn,'w'); -fprintf(fh,'\n'); -fprintf(fh,'SRC test result: Fails\n'); -fprintf(fh,'%8s, ', 'in \ out'); -for a = 1:n_fso-1 - fprintf(fh,'%14.1f, ', fs_out_list(a)/1e3); -end -fprintf(fh,'%14.1f', fs_out_list(n_fso)/1e3); -fprintf(fh,'\n'); -spf = size(pf); -npf = spf(3); -for a = 1:n_fsi - fprintf(fh,'%8.1f, ', fs_in_list(a)/1e3); - for b = 1:n_fso - if pf(a,b,1) < 0 - cstr = 'x'; - else - cstr = sprintf('%d', pf(a,b,1)); - for n=2:npf - if pf(a,b,n) < 0 - cstr = sprintf('%s/x', cstr); - else - cstr = sprintf('%s/%d', cstr,pf(a,b,n)); - end - end - end - if b < n_fso - fprintf(fh,'%14s, ', cstr); - else - fprintf(fh,'%14s', cstr); - end - end - fprintf(fh,'\n'); -end -fclose(fh); -type(fn); -end diff --git a/tools/test/audio/std_utils/aap_test_measure.m b/tools/test/audio/std_utils/aap_test_measure.m index 9e171ac341e5..9da8a5bde031 100644 --- a/tools/test/audio/std_utils/aap_test_measure.m +++ b/tools/test/audio/std_utils/aap_test_measure.m @@ -7,6 +7,8 @@ %% Reference: AES17 6.6.6 Attenuation of alias products % http://www.aes.org/publications/standards/ +debug = 0; + %% Load output file [x, nx] = load_test_output(test); if nx == 0 @@ -21,7 +23,9 @@ win = hamming(nt_use); m0 = zeros(test.nf,1); for n=1:test.nf - fprintf('Measuring %.0f Hz ...\n', test.f(n)); + if debug + fprintf('Measuring %.0f Hz ...\n', test.f(n)); + end i1 = d+(n-1)*nt+nt_skip; i2 = i1+nt_use-1; m0(n) = level_dbfs(x(i1:i2).*win); diff --git a/tools/test/audio/std_utils/aip_test_measure.m b/tools/test/audio/std_utils/aip_test_measure.m index 11ab30830f83..e78d82535cd6 100644 --- a/tools/test/audio/std_utils/aip_test_measure.m +++ b/tools/test/audio/std_utils/aip_test_measure.m @@ -7,6 +7,8 @@ %% Reference: AES17 6.6.7 Attenuation of image products % http://www.aes.org/publications/standards/ +debug = 0; + %% Load output file [x, nx] = load_test_output(test); if nx == 0 @@ -25,7 +27,9 @@ b_lpf = stdlpf_get(test.fu, test.fs); % Get LPF coef b_hpf = stdhpf_get(test.fu, test.fs); % Get HPF coef for n=1:test.nf - fprintf('Measuring %.0f Hz ...\n', test.f(n)); + if debug + fprintf('Measuring %.0f Hz ...\n', test.f(n)); + end % Get notch coef for this frequency [b_notch, a_notch] = stdnotch_get(test.f(n), test.fs); i1 = d+(n-1)*nt+nt_skip; diff --git a/tools/test/audio/std_utils/fr_test_input.m b/tools/test/audio/std_utils/fr_test_input.m index fc9b1b74de80..c2ea782f701e 100644 --- a/tools/test/audio/std_utils/fr_test_input.m +++ b/tools/test/audio/std_utils/fr_test_input.m @@ -61,9 +61,9 @@ fprintf('Using parameters Fmax=%.1f kHz, Fs=%.1f, ch=%d, Nch=%d, bits_in=%d\n', ... test.f_max/1e3, test.fs/1e3, test.ch, test.nch, test.bits_in); -pid = getpid(); -test.fn_in = sprintf('fr_test_in_%d.%s', pid, test.fmt); -test.fn_out = sprintf('fr_test_out_%d.%s', pid, test.fmt); +id = floor(rand(1,1) * 1e6); +test.fn_in = sprintf('fr_test_in_%d.%s', id, test.fmt); +test.fn_out = sprintf('fr_test_out_%d.%s', id, test.fmt); test.f_ref = 997; test.f_min = 20; diff --git a/tools/test/audio/std_utils/fr_test_measure.m b/tools/test/audio/std_utils/fr_test_measure.m index 22226b49c4c0..2e2d1d478379 100644 --- a/tools/test/audio/std_utils/fr_test_measure.m +++ b/tools/test/audio/std_utils/fr_test_measure.m @@ -3,16 +3,20 @@ %% t = fr_test_measure(t) % % Measure frequency response from captured frequency sweep created by -% fr_test_input() that sets most of the input struct fiels. The output +% fr_test_input() that sets most of the input struct fields. The output % is read from file t.fn_out. % +% The test criteria is defined with first three or four latter input +% parameters. The latter has precedence if defined. +% % Input parameters -% t.f_lo - Measure ripple start frequency -% t.f_hi - Measure ripple end frequency +% t.fr_lo - Measure ripple start frequency +% t.fr_hi - Measure ripple end frequency % t.fr_rp_max_db - Max. ripple +/- dB -% t.fr_mask_f - Frequencies for mask -% t.fr_mask_lo - Upper limits of mask -% t.fr_mask_hi - Lower limits of mask +% t.fr_mask_flo - Frequencies for lower mask +% t.fr_mask_fhi - Frequencies for higher mask +% t.fr_mask_mlo - Upper limits of mask +% t.fr_mask_mhi - Lower limits of mask % % Output parameters % t.f - Frequency grid (Hz) @@ -23,16 +27,28 @@ % t.fh - Figure handle % t.ph - Plot handle % -% E.g. -% t.fs=48e3; t.f_max=20e3; t.bits_out=16; t.ch=1; t.nch=2; t=fr_test_input(t); -% t.fn_out=t.fn_in; t.f_lo=20; t.f_hi=20e3; t.rp_max=[]; t.fr_mask_f=[]; -% t=fr_test_measure(t); -% % SPDX-License-Identifier: BSD-3-Clause % Copyright(c) 2017 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +debug = 0; + +%% Check if upper and lower mask is defined +if length(test.fr_mask_flo) || length(test.fr_mask_fhi) + test.fr_lo = 0; + test.fr_hi = 0; +end +if test.fr_lo > 0 || test.fr_hi > 0 + test.fr_mask_flo = []; + test.fr_mask_fhi = []; + test.fr_mask_mlo = []; + test.fr_mask_mhi = []; +end + +test.ph = []; +test.fh = []; + %% Reference: AES17 6.2.3 Frequency response % http://www.aes.org/publications/standards/ @@ -41,6 +57,7 @@ default_result = NaN * ones(1,length(test.ch)); test.rp = default_result; test.fr3db_hz = default_result; +test.fail = 0; j = 1; for channel = test.ch @@ -59,7 +76,9 @@ win = hamming(nt_use); m0 = zeros(test.nf,1); for n=1:test.nf - fprintf('Measuring %.0f Hz ...\n', test.f(n)); + if debug + fprintf('Measuring %.0f Hz ...\n', test.f(n)); + end i1 = d+(n-1)*nt+nt_skip; i2 = i1+nt_use-1; m0(n) = level_dbfs(x(i1:i2,j).*win) -test.a_db; @@ -72,17 +91,16 @@ test.m(:,j) = m0 - m_offs; %% Check pass/fail - idx0 = find(test.f < test.f_hi); - idx1 = find(test.f(idx0) > test.f_lo); - range_db = max(test.m(idx1,j))-min(test.m(idx1,j)); - test.rp(j) = range_db/2; - test.fail = 0; - if ~isempty(test.fr_rp_max_db) - if test.rp(j) > test.fr_rp_max_db - fprintf('Failed response ch%d +/- %f dBpp (max +/- %f dB)\n', ... - test.ch(j), test.rp(j), test.fr_rp_max_db); - test.fail = 1; - end + if test.fr_lo > 0 && test.fr_hi > 0 && ~isempty(test.fr_rp_max_db) + idx0 = find(test.f < test.fr_hi); + idx1 = find(test.f(idx0) > test.fr_lo); + range_db = max(test.m(idx1,j))-min(test.m(idx1,j)); + test.rp(j) = range_db/2; + if test.rp(j) > test.fr_rp_max_db + fprintf('Failed response ch%d +/- %f dBpp (max +/- %f dB)\n', ... + test.ch(j), test.rp(j), test.fr_rp_max_db); + test.fail = 1; + end end %% Find frequency response 3 dB 0-X Hz @@ -90,23 +108,26 @@ test.fr3db_hz(j) = test.f(idx3(end)); %% Interpolate mask in logaritmic frequencies, check - if ~isempty(test.fr_mask_f) + if ~isempty(test.fr_mask_fhi) f_log = log(test.f); - mask_hi = interp1(log(test.fr_mask_f), test.fr_mask_hi(:,j), ... - f_log, 'linear'); - mask_lo = interp1(log(test.fr_mask_f), test.fr_mask_lo(:,j), ... - f_log, 'linear'); + mask_hi = interp1(log(test.fr_mask_fhi), ... + test.fr_mask_mhi(:,j), f_log, 'linear'); over_mask = test.m(:,j)-mask_hi'; - under_mask = mask_lo'-test.m(:,j); idx = find(isnan(over_mask) == 0); [m_over_mask, io] = max(over_mask(idx)); - idx = find(isnan(under_mask) == 0); - [m_under_mask, iu] = max(under_mask(idx)); if m_over_mask > 0 fprintf('Failed upper response mask around %.0f Hz\n', ... test.f(io(1))); test.fail = 1; end + end + if ~isempty(test.fr_mask_flo) + f_log = log(test.f); + mask_lo = interp1(log(test.fr_mask_flo), ... + test.fr_mask_mlo(:,j), f_log, 'linear'); + under_mask = mask_lo'-test.m(:,j); + idx = find(isnan(under_mask) == 0); + [m_under_mask, iu] = max(under_mask(idx)); if m_under_mask > 0 fprintf('Failed lower response mask around %.0f Hz\n', ... test.f(iu(1))); @@ -114,7 +135,6 @@ end end - %% Next channel to measure j=j+1; end @@ -135,13 +155,21 @@ grid on; xlabel('Frequency (Hz)'); ylabel('Magnitude (dB)'); - if ~isempty(test.fr_mask_f) + if ~isempty(test.fr_mask_fhi) hold on; - plot(test.f, mask_hi, 'r--'); - plot(test.f, mask_lo, 'r--'); + plot(test.f, mask_hi, 'k--'); hold off; end - axis(test.plot_fr_axis); + if ~isempty(test.fr_mask_flo) + hold on; + plot(test.f, mask_lo, 'k--'); + hold off; + end + + if ~isempty(test.plot_fr_axis) + axis(test.plot_fr_axis); + end + if test.plot_channels_combine && (test.nch > 1) switch test.nch case 2 @@ -158,8 +186,8 @@ if test.plot_passband_zoom axes('Position', [ 0.2 0.2 0.4 0.2]); box on; - i1 = find(test.f < test.f_lo, 1, 'last'); - i2 = find(test.f > test.f_hi, 1, 'first'); + i1 = find(test.f < test.fr_lo, 1, 'last'); + i2 = find(test.f > test.fr_hi, 1, 'first'); if isempty(i1) i1 = 1; end @@ -175,11 +203,11 @@ if ~isempty(test.fr_rp_max_db) rp = test.fr_rp_max_db; hold on; - plot([test.f_lo test.f_hi], [-rp/2 -rp/2], 'r--'); - plot([test.f_lo test.f_hi], [ rp/2 rp/2], 'r--'); + plot([test.fr_lo test.fr_hi], [-rp/2 -rp/2], 'r--'); + plot([test.fr_lo test.fr_hi], [ rp/2 rp/2], 'r--'); hold off end - axis([0 test.f_hi -rp/2-0.05 rp/2+0.05]); + axis([0 test.f_max -rp rp]); grid on; end diff --git a/tools/test/audio/std_utils/g_test_input.m b/tools/test/audio/std_utils/g_test_input.m index 822cf0e0d3c3..7a24282e9bcb 100644 --- a/tools/test/audio/std_utils/g_test_input.m +++ b/tools/test/audio/std_utils/g_test_input.m @@ -48,9 +48,9 @@ test.fs/1e3, test.bits_in, ch, test.nch); end -pid = getpid(); -test.fn_in = sprintf('g_test_in_%d.%s', pid, test.fmt); -test.fn_out = sprintf('g_test_out_%d.%s', pid, test.fmt); +id = floor(rand(1,1) * 1e6); +test.fn_in = sprintf('g_test_in_%d.%s', id, test.fmt); +test.fn_out = sprintf('g_test_out_%d.%s', id, test.fmt); test.f = 997; diff --git a/tools/test/audio/std_utils/g_test_measure.m b/tools/test/audio/std_utils/g_test_measure.m index db09bfdc5d33..96a7e7dd6662 100644 --- a/tools/test/audio/std_utils/g_test_measure.m +++ b/tools/test/audio/std_utils/g_test_measure.m @@ -38,7 +38,7 @@ level_out = level_dbfs(y); test.g_db = level_out - level_in + test.att_rec_db; for i = 1:length(test.g_db) - fprintf('Gain = %6.3f dB (expect %6.3f dB)\n', test.g_db(i), test.g_db_expect); + fprintf('Gain = %6.3f dB (expect %6.3f dB)\n', test.g_db(i), test.g_db_expect(i)); end %% Check pass/fail 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 <seppo.ingalsuo@linux.intel.com> + +%% 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 <seppo.ingalsuo@linux.intel.com> + +%% 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/std_utils/level_dbfs.m b/tools/test/audio/std_utils/level_dbfs.m index 73cddedb4ce8..8bca996648eb 100644 --- a/tools/test/audio/std_utils/level_dbfs.m +++ b/tools/test/audio/std_utils/level_dbfs.m @@ -9,38 +9,12 @@ % dbfs - sigmal level in dBFS % -%% -% Copyright (c) 2017, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2017 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% %% Reference AES 17 3.12.3 level_ms = mean(x.^2); -dbfs = 10*log10(level_ms) + 20*log10(sqrt(2)); +dbfs = 10*log10(level_ms + 1e-20) + 20*log10(sqrt(2)); end diff --git a/tools/test/audio/std_utils/stdlpf.m b/tools/test/audio/std_utils/stdlpf.m index 56fdc5a44458..657fea4faaed 100644 --- a/tools/test/audio/std_utils/stdlpf.m +++ b/tools/test/audio/std_utils/stdlpf.m @@ -1,8 +1,8 @@ function y = stdlpf(x, fu, fs) -%% y = stdhpf(x, fu, fs) +%% y = stdlpf(x, fu, fs) % -% Standard high-pass filter +% Standard low-pass filter % % Input % x - input signal diff --git a/tools/test/audio/std_utils/stdlpf_get.m b/tools/test/audio/std_utils/stdlpf_get.m index ac344d155d55..23285dfa35ad 100644 --- a/tools/test/audio/std_utils/stdlpf_get.m +++ b/tools/test/audio/std_utils/stdlpf_get.m @@ -2,7 +2,7 @@ %% b = stdlpf_get(fu, fs) % -% Standard loww-pass filter +% Standard low-pass filter % % Input % fu - upper band-edge frequency diff --git a/tools/test/audio/std_utils/stdnotch_get.m b/tools/test/audio/std_utils/stdnotch_get.m index 5213fa8eae35..c79e6fb51de6 100644 --- a/tools/test/audio/std_utils/stdnotch_get.m +++ b/tools/test/audio/std_utils/stdnotch_get.m @@ -43,7 +43,7 @@ target_q = 2.1; bw = (2*fn/fs)/target_q; -if exist('iirnotch.m') == 2 +if exist(fullfile('iirnotch.m'),'file') == 2 [b, a] = iirnotch(2*fn/fs, bw); else [b, a] = pei_tseng_notch(2*fn/fs, bw); diff --git a/tools/test/audio/std_utils/thdnf_test_input.m b/tools/test/audio/std_utils/thdnf_test_input.m index 39869d78e010..6ed1fb75447f 100644 --- a/tools/test/audio/std_utils/thdnf_test_input.m +++ b/tools/test/audio/std_utils/thdnf_test_input.m @@ -1,6 +1,6 @@ function test = thdnf_test_input(test) -%% t = dr_test_input(t) +%% t = thdnf_test_test_input(t) % % Create tone data file for playback & record on real device or % for algorithm simulation. @@ -47,11 +47,11 @@ test.f_start, test.f_end, test.fs/1e3, test.bits_in, ch, test.nch ); end -pid = getpid(); -test.fn_in = sprintf('thdnf_test_in_%d.%s', pid, test.fmt); -test.fn_out = sprintf('thdnf_test_out_%d.%s', pid, test.fmt); +id = floor(rand(1,1) * 1e6); +test.fn_in = sprintf('thdnf_test_in_%d.%s', id, test.fmt); +test.fn_out = sprintf('thdnf_test_out_%d.%s', id, test.fmt); noct = ceil(log(test.f_end/test.f_start)/log(2)); % Max 1 octave steps -test.f = logspace(log10(test.f_start),log10(test.f_end), noct); +test.f = logspace(log10(test.f_start),log10(test.f_end), noct+1); %% Tone sweep parameters test.is = 20e-3; % Ignore signal from tone start diff --git a/tools/test/audio/std_utils/thdnf_test_measure.m b/tools/test/audio/std_utils/thdnf_test_measure.m index c3816b02e897..1fb9076acfa8 100644 --- a/tools/test/audio/std_utils/thdnf_test_measure.m +++ b/tools/test/audio/std_utils/thdnf_test_measure.m @@ -4,6 +4,24 @@ % Copyright(c) 2017 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +debug = 0; +test.ph = []; +test.fh = []; + +if isempty(test.thdnf_mask_f) + if ~isempty(test.thdnf_max) + test.thdnf_mask_f = [1 test.fs/2]; % Start from 1 due to log() + test.thdnf_mask_hi = test.thdnf_max * [1 1]; + end +else + if ~isempty(test.thdnf_max) + error('Set either thdnf_max or thdnf_mask_f & thdnf_mask_hi but not both'); + end + if isempty(test.thdnf_mask_hi) + error('thdnf_mask_hi must be set when thdnf_mask_f is defined'); + end +end + %% Reference: AES17 6.3.2 THD+N ratio vs frequency % http://www.aes.org/publications/standards/ @@ -28,6 +46,14 @@ return end +%% Interpolate THD+N mask +idx = find(test.f <= test.thdnf_mask_f(end)); +idx = find(test.f(idx) >= test.thdnf_mask_f(1)); +f_mask = test.f(idx); +f_log = log(f_mask); +mask_hi = interp1(log(test.thdnf_mask_f), test.thdnf_mask_hi, f_log, 'linear'); +mask_hi = mask_hi(:); + %% Measure all test frequencies test.fail = 0; for i = 1:length(test.ch); @@ -37,7 +63,9 @@ nn = 1; for m=1:test.na for n=1:test.nf - fprintf('Measuring %.0f Hz ...\n', test.f(n)); + if debug + fprintf('Measuring %.0f Hz ...\n', test.f(n)); + end i1 = d+(nn-1)*nt+nt_skip; i2 = i1+nt_use-1; nn = nn+1; @@ -50,7 +78,24 @@ test.thdnf = mn - ml; test.thdnf_high(:,i) = test.thdnf(:,1); test.thdnf_low(:,i) = test.thdnf(:,2); - if max(max(test.thdnf)) > test.thdnf_max + + fidx = find(test.thdnf(idx, 1) > mask_hi); + if length(fidx) > 0 + fail_hi = 1; + fprintf('Failed THD+N mask with high input.\n'); + else + fail_hi = 0; + end + + fidx = find(test.thdnf(idx, 2) > mask_hi); + if length(fidx) > 0 + fail_lo = 1; + fprintf('Failed THD+N mask with low input.\n'); + else + fail_lo = 0; + end + + if fail_hi && fail_lo test.fail = 1; end end @@ -61,15 +106,22 @@ test.ph(i) = subplot(1, 1, 1); if test.plot_channels_combine - semilogx(test.f, test.thdnf_high, test.f, test.thdnf_low, '--'); + semilogx(test.f, test.thdnf_high, test.f, test.thdnf_low); else semilogx(test.f, test.thdnf_high(:,i), ... - test.f, test.thdnf_low(:,i), '--'); + test.f, test.thdnf_low(:,i)); + end + + if ~isempty(test.thdnf_mask_f) + hold on + plot(f_mask, mask_hi, 'k--'); + hold off end grid on; - if ~isempty(test.plot_thdn_axis); + if ~isempty(test.plot_thdn_axis) axis(test.plot_thdn_axis); + end xlabel('Frequency (Hz)'); ylabel('THD+N (dB)'); diff --git a/tools/test/audio/tdfb_direction_test.m b/tools/test/audio/tdfb_direction_test.m new file mode 100644 index 000000000000..9152ee28c53f --- /dev/null +++ b/tools/test/audio/tdfb_direction_test.m @@ -0,0 +1,235 @@ +function tdfb_direction_test() + +% tdfb_test() +% Inputs +% None +% +% Outputs +% None, to be added later when automatic pass/fail is possible to +% determine. So far only visual check enabled. + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2020 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +% General settings +cfg.delete_files = 1; +cfg.do_plots = 1; +cfg.tunepath = '../../tune/tdfb/data'; + +% Arrays to test. Since the two beams configurations are merge of two designs (pm90deg) +% need to specify a compatible data file identifier for a single beam design (az0el0deg) +array_data_list = {'line2_50mm_az0el0deg_48khz', 'line4_28mm_az0el0deg_48khz', 'circular8_100mm_az0el0deg_48khz'}; +tdfb_name_list = {'', 'line4_28mm_pm90deg_48khz', 'circular8_100mm_pm30deg_48khz'}; + +%% Prepare +addpath('std_utils'); +addpath('test_utils'); +addpath('../../tune/tdfb'); + +for i = 1:length(array_data_list) + + % Get configuration, this needs to match array geometry and rate + % beam direction can be any, use (0, 0) deg. + array = array_data_list{i}; + tdfb = tdfb_name_list{i}; + + % Rub beapattern test with rotated noise + config_fn = sprintf('tdfb_coef_%s.mat', array); + simcap_fn = sprintf('simcap_noiserot_%s.raw', array); + test_beampattern(cfg, config_fn, simcap_fn, tdfb); + + % Plot estimated direction + trace_fn = 'tdfb_direction.txt'; + label = 'tdfb_dint'; + comp = 'tdfb'; + inst = ''; + dataidx = [1 2 3 4]; + [data, ts, dt] = trace_parse_tb(trace_fn, comp, inst, label, dataidx); + ref = 32768^2; + offs = 20*log10(sqrt(2)); + trig = 10 * bitand(data(:,1), 1); + flev = 10*log10(data(:,2)/ref) + offs; + slev = 10*log10(data(:,3)/ref) + offs; + az_slow = data(:,4) / 2^12 * 180/pi; + + figure + plot(flev) + hold on + plot(slev) + plot(trig) + plot(az_slow) + hold off + grid on + xlabel('Time (ms)'); + ylabel('Levels, trigger, angle'); + legend('fast level', 'slow level', 'trigger', 'slow az' ); + title(sprintf('Direction angle %s', array)); +end + +end + +function test = test_defaults(bf, arrayid) + +test.comp = 'tdfb'; +test.array = ''; +test.bits = 16; +test.fs = bf.fs; +test.fmt = 'raw'; +test.nch_in = max(bf.input_channel_select) + 1; +test.nch_out = bf.num_output_channels; +test.ch_in = 1:test.nch_in; +test.ch_out = 1:test.nch_out; +test.extra_opts='-d 4'; +test.trace = 'tdfb_direction.txt'; +if length(arrayid) + test.comp = sprintf('tdfb_%s', arrayid); +end + +end + +function test = test_run_comp(test) + +delete_check(1, test.fn_out); +test = test_run(test); + +end + +function [ldb, az] = sinerot_dbfs(x, bf) + +az = bf.sinerot_az_start:bf.sinerot_az_step:bf.sinerot_az_stop; +nt = length(az); +tn = floor(bf.sinerot_t * bf.fs); +sx = size(x); +ldb = zeros(nt, sx(2)); +for i = 1:nt + ts = (i - 1) * bf.sinerot_t; + i1 = floor(ts * bf.fs + 1); + i2 = min(i1 + tn - 1, sx(1)); + ldb(i, :) = level_dbfs(x(i1:i2, :)); +end + +end + +%% Beam pattern test + +function test_beampattern(cfg, config_fn, simcap_fn, tdfb); + +fn = fullfile(cfg.tunepath, config_fn); +if exist(fn, 'file') + load(fn); +else + fprintf(1, 'Array configuration file %s does not exist.\n', config_fn); + fprintf(1, 'Please run the script example_line_array in tools/tune/tdfb directory.\n'); + error('Stopping.'); +end + +% Create input file +test = test_defaults(bf, tdfb); +test.fn_in = fullfile(cfg.tunepath, simcap_fn); +test.fn_out = 'noiserot.raw'; + +% Run test +test = test_run_comp(test); + +% Load simulation output data +test.nch = test.nch_in; +test.ch = test.ch_in; +x = load_test_input(test); +sx = size(x); +test.nch = test.nch_out; +test.ch = test.ch_out; +y = load_test_output(test); +sy = size(y); +delete_check(cfg.delete_files, test.fn_out); +[rotx_dbfs, az] = sinerot_dbfs(x, bf); +[roty_dbfs, az] = sinerot_dbfs(y, bf); + +% Do plots +if cfg.do_plots + offset = 20*log10(bf.sinerot_a); + figure + plot(az, roty_dbfs - offset, '-', az, rotx_dbfs - offset, '--'); + grid on + xlabel('Azimuth angle (deg)'); + ylabel('Magnitude (dB)'); + ch_legend_help(sy(2)); + tstr = sprintf('Beam pattern %d Hz %s', bf.sinerot_f, bf.array_id); + title(tstr, 'Interpreter','none'); + + figure + ldb = roty_dbfs - offset; + llin = 10.^(ldb/20); + az_rad = az * pi/180; + if exist('OCTAVE_VERSION', 'builtin') + polar(az_rad, llin); + else + polarplot(az_rad, llin); + end + ch_legend_help(sy(2)); + title(tstr, 'Interpreter','none'); +end + +end + + +function ch_legend_help(nch) + +switch nch + case 1 + legend('ch1 out'); + case 2 + legend('ch1 out', 'ch2 out'); + case 3 + legend('ch1 out', 'ch2 out', 'ch3 out'); + case 4 + legend('ch1 out', 'ch2 out', 'ch3 out', 'ch4 out'); +end + +end + +function [data, ts, dt] = trace_parse_tb(trace_fn, comp, inst, label, dataidx) + nmax = 1000000; % Max. more than 15 min every 1 ms + fh = fopen(trace_fn, 'r'); + dlines = 0; + nlines = 0; + ndata = length(dataidx); + ncols = ndata; + dtmp = zeros(nmax, ncols); + ltmp = zeros(1, ncols); + str = fgets(fh); + while (str ~= -1) + nlines = nlines + 1; + idx = strfind(str, label); + if isempty(idx) + str = fgets(fh); + continue; + end + + dstr = [ ' ' str(idx + length(label) + 1:end) ' ' ]; + idx = strfind(dstr, ' '); + for i = 1:ndata + j = dataidx(i); + i1 = idx(j) + 1; + i2 = idx(j+1) - 1; + nstr = dstr(i1:i2); + ltmp(i) = str2num(nstr); + end + dlines = dlines + 1; + dtmp(dlines,:) = ltmp; + str = fgets(fh); + end + + if dlines == 0 + fprintf(1, 'Read %d lines, no label "%s" found\n', nlines, label); + error('Failed.'); + end + + dtmp = dtmp(1:dlines,:); + fprintf(1, 'Found %d lines with label "%s"\n', dlines, label); + data = dtmp(1:dlines, 1:ncols); + + ts = []; + dt = []; + +end diff --git a/tools/test/audio/tdfb_enable.sh b/tools/test/audio/tdfb_enable.sh new file mode 100644 index 000000000000..ce7422be62ca --- /dev/null +++ b/tools/test/audio/tdfb_enable.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +amixer -c0 cset name='Analog Playback TDFB track' off +amixer -c0 cset name='Analog Playback TDFB angle set' 90 +amixer -c0 cset name='Analog Playback TDFB beam' on diff --git a/tools/test/audio/tdfb_run.sh b/tools/test/audio/tdfb_run.sh new file mode 100755 index 000000000000..ad0e1174d38a --- /dev/null +++ b/tools/test/audio/tdfb_run.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020 Intel Corporation. All rights reserved. + +usage () +{ + echo "Usage: $0 <bits in> <bits out> <rate> <input> <output>" + echo "Example: $0 16 16 48000 input.raw output.raw" +} + +main () +{ + local COMP DIRECTION + + if [ $# -ne 5 ]; then + usage "$0" + exit + fi + + COMP=tdfb + DIRECTION=playback + + ./comp_run.sh $COMP $DIRECTION "$1" "$2" "$3" "$3" "$4" "$5" +} + +main "$@" diff --git a/tools/test/audio/tdfb_test.m b/tools/test/audio/tdfb_test.m new file mode 100644 index 000000000000..0c75c3cf1053 --- /dev/null +++ b/tools/test/audio/tdfb_test.m @@ -0,0 +1,241 @@ +function tdfb_test(xtrun) + +% tdfb_test(xtrun) +% Inputs +% xtrun - set to 'xt-run' or 'xt-run --turbo' to test with xt-testbench +% +% Outputs +% None, to be added later when automatic pass/fail is possible to +% determine. So far only visual check enabled. + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2020-2025 Intel Corporation. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 1 + xtrun = ''; +end + +% General settings +cfg.delete_files = 1; +cfg.do_plots = 1; +cfg.tunepath = '../../../src/audio/tdfb/tune/data'; +cfg.xtrun = xtrun; + +% Arrays to test. Since the two beams configurations are merge of two designs (pm90deg) +% need to specify a compatible data file identifier for a single beam design (az0el0deg) +array_data_list = {'line2_50mm_az0el0deg_48khz'}; +tdfb_name_list = {''}; + +%% Prepare +addpath('std_utils'); +addpath('test_utils'); +addpath('../../../src/audio/tdfb/tune'); + +for i = 1:length(array_data_list) + + %% Beam pattern test + % Get configuration, this needs to match array geometry and rate + % beam direction can be any, use (0, 0) deg. + array = array_data_list{i}; + tdfb = tdfb_name_list{i}; + config_fn = sprintf('tdfb_coef_%s.mat', array); + simcap_fn = sprintf('simcap_sinerot_%s.raw', array); + test_beampattern(cfg, config_fn, simcap_fn, tdfb); + + %% Diffuse noise test + simcap_fn = sprintf('simcap_diffuse_%s.raw', array); + desc = 'Diffuse field noise'; + [dfin_dbfs, dfout_dbfs, dfd_db] = test_noise_suppression(cfg, config_fn, simcap_fn, desc, tdfb); + + %% Random noise + simcap_fn = sprintf('simcap_random_%s.raw', array); + desc = 'Random noise'; + [rnin_dbfs, rnout_dbfs, drn_db] = test_noise_suppression(cfg, config_fn, simcap_fn, desc, tdfb); + + %% Results + fprintf(1, '\n'); + print_result('Diffuse field input level ', 'dBFS', dfin_dbfs); + print_result('Diffuse field output level', 'dBFS', dfout_dbfs); + print_result('Diffuse field level delta ', 'dB', dfd_db); + print_result('Random noise input level ', 'dBFS', rnin_dbfs); + print_result('Random noise output level ', 'dBFS', rnout_dbfs); + print_result('Random noise level delta ', 'dB', drn_db); + +end + +end + +function test = test_defaults(bf, arrayid) + +test.comp = 'tdfb'; +test.array = ''; +test.bits = 16; +test.fs = bf.fs; +test.fmt = 'raw'; +test.nch_in = max(bf.input_channel_select) + 1; +test.nch_out = bf.num_output_channels; +test.ch_in = 1:test.nch_in; +test.ch_out = 1:test.nch_out; +test.extra_opts='-s tdfb_enable.sh'; +if length(arrayid) + test.comp = sprintf('tdfb_%s', arrayid); +end + +end + +function test = test_run_comp(test) + +delete_check(1, test.fn_out); +test = test_run(test); + +end + +function [ldb, az] = sinerot_dbfs(x, bf) + +az = bf.sinerot_az_start:bf.sinerot_az_step:bf.sinerot_az_stop; +nt = length(az); +tn = floor(bf.sinerot_t * bf.fs); +sx = size(x); +ldb = zeros(nt, sx(2)); +for i = 1:nt + ts = (i - 1) * bf.sinerot_t; + i1 = floor(ts * bf.fs + 1); + i2 = min(i1 + tn - 1, sx(1)); + ldb(i, :) = level_dbfs(x(i1:i2, :)); +end + +end + +%% Beam pattern test + +function test_beampattern(cfg, config_fn, simcap_fn, tdfb); + +fn = fullfile(cfg.tunepath, config_fn); +if exist(fn, 'file') + load(fn); +else + fprintf(1, 'Array configuration file %s does not exist.\n', config_fn); + fprintf(1, 'Please run the script example_line_array in tools/tune/tdfb directory.\n'); + error('Stopping.'); +end + +% Create input file +test = test_defaults(bf, tdfb); +test.fn_in = fullfile(cfg.tunepath, simcap_fn); +test.fn_out = 'sinerot.raw'; +test.xtrun = cfg.xtrun; + +% Run test +test = test_run_comp(test); + +% Load simulation output data +test.nch = test.nch_in; +test.ch = test.ch_in; +x = load_test_input(test); +sx = size(x); +test.nch = test.nch_out; +test.ch = test.ch_out; +y = load_test_output(test); +sy = size(y); +delete_check(cfg.delete_files, test.fn_out); +[rotx_dbfs, az] = sinerot_dbfs(x, bf); +[roty_dbfs, az] = sinerot_dbfs(y, bf); + +% Do plots +if cfg.do_plots + offset = 20*log10(bf.sinerot_a); + figure + plot(az, roty_dbfs - offset, '-', az, rotx_dbfs - offset, '--'); + grid on + xlabel('Azimuth angle (deg)'); + ylabel('Magnitude (dB)'); + ch_legend_help(sy(2)); + tstr = sprintf('Beam pattern %d Hz %s', bf.sinerot_f, bf.array_id); + title(tstr, 'Interpreter','none'); + + figure + ldb = roty_dbfs - offset; + llin = 10.^(ldb/20); + az_rad = az * pi/180; + if exist('OCTAVE_VERSION', 'builtin') + polar(az_rad, llin); + else + polarplot(az_rad, llin); + end + ch_legend_help(sy(2)); + title(tstr, 'Interpreter','none'); +end + +end + +%% Noise suppression test + +function [x_dbfs, y_dbfs, delta_db] = test_noise_suppression(cfg, config_fn, simcap_fn, desc, arrayid) + +load(fullfile(cfg.tunepath, config_fn)); + +% Create input file +test = test_defaults(bf, arrayid); +fn_in = fullfile(cfg.tunepath, simcap_fn); +fn_out = 'noise_out.raw'; + +% Run test +test.fn_in = fn_in; +test.fn_out = fn_out; +test = test_run_comp(test); + +% Load simulation input data +test.nch = test.nch_in; +test.ch = test.ch_in; +x = load_test_input(test); +sx = size(x); +test.nch = test.nch_out; +test.ch = test.ch_out; +y = load_test_output(test); +sy = size(y); +delete_check(cfg.delete_files, test.fn_out); +x_dbfs = level_dbfs(x); +y_dbfs = level_dbfs(y); +delta_db = mean(x_dbfs) - y_dbfs; + +if cfg.do_plots + tstr = sprintf('%s %s', desc, bf.array_id); + figure; + plot(x(:,1)); + hold on + plot(y(:,1)); + hold off + grid on; + legend('ch1 in','ch1 out'); + title(tstr, 'Interpreter', 'none'); +end + +end + +%% Print results table line + +function print_result(desc, unit, values) + +fprintf(1, "%s,", desc); +for v = values + fprintf(1, '%6.1f, ', v); +end +fprintf(1, "%s\n", unit); + +end + +function ch_legend_help(nch) + +switch nch + case 1 + legend('ch1 out'); + case 2 + legend('ch1 out', 'ch2 out'); + case 3 + legend('ch1 out', 'ch2 out', 'ch3 out'); + case 4 + legend('ch1 out', 'ch2 out', 'ch3 out', 'ch4 out'); +end + +end diff --git a/tools/test/audio/test_utils/chirp_test_analyze.m b/tools/test/audio/test_utils/chirp_test_analyze.m index ed149846f6f7..1cfcdccbd7df 100644 --- a/tools/test/audio/test_utils/chirp_test_analyze.m +++ b/tools/test/audio/test_utils/chirp_test_analyze.m @@ -1,34 +1,11 @@ function test = chirp_test_analyze(test) -%% -% Copyright (c) 2017, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2017-2020 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% + +test.ph = []; +test.fh = []; %% Load output file [x, nx] = load_test_output(test); @@ -39,6 +16,16 @@ %% Find sync [d, nt, nt_use, nt_skip] = find_test_signal(x(:,test.ch(1)), test); +if isempty(d) + t = (((1:size(x, 1)) - 1)/test.fs)'; + figure; + plot(t, x) + grid on; + xlabel('Time (s)'); + ylabel('PCM sample values'); + test.fail = -1; + return; +end %% Trim sample i1 = d+nt_skip; @@ -53,7 +40,7 @@ et = abs(test.cl-tz)/test.cl; rms_db = 10*log10(mean(z.^2)) + 20*log10(sqrt(2)); offs_db = 20*log10(abs(mean(z))); -sum_rms_db = 10*log10(mean(s.^2)) +sum_rms_db = 10*log10(mean(s.^2)); % Check for proper ratio of out/in samples, minimum level, maximum offset % and maximum of sum of channels. The input is such that the channels should % sum to zero. A phase difference in channels would cause non-zero output @@ -62,7 +49,7 @@ if et > 0.05 fail = 1; fprintf('Failed output chirp length, err=%f, t=%f.\n', et, tz); -else if (min(rms_db) < -3) && (test.fs2 + 1 > test.fs1) +else if (min(rms_db) < -6) && (test.fs2 + 1 > test.fs1) fail = 1; fprintf('Failed output chirp level.\n'); else if max(offs_db) > -40 @@ -79,6 +66,7 @@ end test.fh = figure('visible', test.plot_visible); +test.ph = subplot(1, 1, 1); ns = 1024; no = round(0.9*ns); specgram(y(:,1), ns, test.fs, kaiser(ns,27), no); diff --git a/tools/test/audio/test_utils/chirp_test_input.m b/tools/test/audio/test_utils/chirp_test_input.m index 89b2861e538b..47491d5879a5 100644 --- a/tools/test/audio/test_utils/chirp_test_input.m +++ b/tools/test/audio/test_utils/chirp_test_input.m @@ -69,8 +69,9 @@ fprintf(', ch=%d', test.ch ); fprintf(', Nch=%d\n', test.nch ); -test.fn_in = sprintf('chirp_test_in.%s', test.fmt); -test.fn_out = sprintf('chirp_test_out.%s', test.fmt); +id = floor(rand(1,1) * 1e6); +test.fn_in = sprintf('chirp_test_in_%d.%s', id, test.fmt); +test.fn_out = sprintf('chirp_test_out_%d.%s', id, test.fmt); %% Chirp parameters diff --git a/tools/test/audio/test_utils/delete_check.m b/tools/test/audio/test_utils/delete_check.m index b3e1c8219fac..766eb3dbf50e 100644 --- a/tools/test/audio/test_utils/delete_check.m +++ b/tools/test/audio/test_utils/delete_check.m @@ -29,7 +29,7 @@ % function delete_check(really, f) -if really && exist(f) == 2 +if really && exist(fullfile('.', f),'file') == 2 delete(f); end end diff --git a/tools/test/audio/test_utils/dither_and_quantize.m b/tools/test/audio/test_utils/dither_and_quantize.m index 56a2a58b71f2..83d3a7a21fb7 100644 --- a/tools/test/audio/test_utils/dither_and_quantize.m +++ b/tools/test/audio/test_utils/dither_and_quantize.m @@ -51,8 +51,7 @@ nx = sx(1); nch = sx(2); -xq = int32(floor( scale*x + randn(nx,nch) - randn(nx,nch) -0.5)); % TPDF dither -%xq = int32(round( scale*x )); % Omit dither +xq = int32(round(scale * x + rand(nx,nch) + rand(nx, nch) - 1)); % TPDF dither idx = find(xq > smax); xq(idx) = smax; idx = find(xq < smin); diff --git a/tools/test/audio/test_utils/load_test_input.m b/tools/test/audio/test_utils/load_test_input.m new file mode 100644 index 000000000000..023a07fe8bc8 --- /dev/null +++ b/tools/test/audio/test_utils/load_test_input.m @@ -0,0 +1,26 @@ +function [x, nx] = load_test_input(test) + +%% [x, n] = load_test_input(t) +% +% Input +% t.fn_in - file name to load +% t.bits_in - word length of data +% t.fmt - file format 'raw' or 'txt +% t.ch - channel to extract +% t.nch - number of channels in (interleaved) data +% +% Output +% x - samples +% n - number of samples +% + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2020 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +tmp = test; +tmp.fn_out = test.fn_in; +tmp.bits_out = test.bits_in; +[x, nx] = load_test_output(tmp); + +end diff --git a/tools/test/audio/test_utils/load_test_output.m b/tools/test/audio/test_utils/load_test_output.m index a9b10d1fa8a3..79eafd9f3466 100644 --- a/tools/test/audio/test_utils/load_test_output.m +++ b/tools/test/audio/test_utils/load_test_output.m @@ -18,8 +18,16 @@ % Copyright(c) 2017 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +if isfield(test, 'bits_out') + bits_out = test.bits_out; +elseif isfield(test, 'bits'); + bits_out = test.bits; +else + bits_out = test.bits_in; +end + %% Integer type for binary files -switch test.bits_out +switch bits_out case 16 bfmt = 'int16'; case 24 @@ -31,7 +39,7 @@ end %% Check that output file exists -if exist(test.fn_out) +if exist(fullfile('.', test.fn_out),'file') == 2 fprintf('Reading output data file %s...\n', test.fn_out); switch lower(test.fmt) case 'txt' @@ -53,8 +61,8 @@ out = []; end -%% Exctract channels to measure -scale = 1/2^(test.bits_out-1); +%% Extract channels to measure +scale = 1/2^(bits_out-1); lout = length(out); nx = floor(lout/test.nch); x = zeros(nx,length(test.ch)); diff --git a/tools/test/audio/test_utils/mix_sweep.m b/tools/test/audio/test_utils/mix_sweep.m index 51c144312b2d..9bda9e70290c 100644 --- a/tools/test/audio/test_utils/mix_sweep.m +++ b/tools/test/audio/test_utils/mix_sweep.m @@ -4,6 +4,8 @@ % Copyright(c) 2017 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> +debug = 0; + %% Adjust tone lengt to integer number of samples test.nt = round(test.tl*test.fs); % Make number of samples per tone test.tl = test.nt/test.fs; % an integer by adjusting tl. @@ -46,7 +48,7 @@ nn = 1; for m=1:test.na for n=1:test.nf - i1 = i0 + (nn-1)*test.nt+1; + i1 = i0 + (nn-1)*test.nt; i2 = i1+test.nt-1; nn = nn+1; if length(test.f) > 1 @@ -59,7 +61,9 @@ else a = test.a; end - fprintf('Mixing %.0f Hz %.1f dBFS sine ...\n', f, 20*log10(a)); + if debug + fprintf('Mixing %.0f Hz %.1f dBFS sine ...\n', f, 20*log10(a)); + end s = multitone(test.fs, f, a, test.tl); for ch=test.ch x(i1:i2, ch) = dither_and_quantize(s.*win, test.bits_in); diff --git a/tools/test/audio/test_utils/mkdir_check.m b/tools/test/audio/test_utils/mkdir_check.m index b453d0b8d898..20b46c18e093 100644 --- a/tools/test/audio/test_utils/mkdir_check.m +++ b/tools/test/audio/test_utils/mkdir_check.m @@ -29,7 +29,7 @@ % function d = mkdir_check(d) -if exist(d) ~= 7 +if ~exist(fullfile('.', d),'dir') mkdir(d); end end diff --git a/tools/test/audio/test_utils/multitone.m b/tools/test/audio/test_utils/multitone.m index 7f3faa37f9bd..15ae6c60302c 100644 --- a/tools/test/audio/test_utils/multitone.m +++ b/tools/test/audio/test_utils/multitone.m @@ -8,54 +8,29 @@ % fs - Sample rate % f - Frequency (Hz) % a - Amplitude (lin) -% t - Lenght in seconds +% t - Length in seconds % % Example: % x = multitone(48000, [997 1997], 10.^([-26 -46]/20), 1.0); % -%% -% Copyright (c) 2017, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2017 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% n = round(fs*tlength); t = (0:n-1)/fs; nf = length(f); if nf > 1 - ph = rand(nf, 1)*2*pi; + ph = rand(nf, 1)*2*pi; else - ph = 0; + ph = 0; end -x = amp(1)*sin(2*pi*f(1)*t'); +x = zeros(n, 1); +x(:,1) = amp(1)*sin(2*pi*f(1)*t); for i=2:length(f) - x = x + amp(i)*sin(2*pi*f(i)*t+ph(i)); + x(:,1) = x(:,1) + amp(i)*sin(2*pi*f(i)*t+ph(i))'; end end diff --git a/tools/test/audio/test_utils/print_fr.m b/tools/test/audio/test_utils/print_fr.m new file mode 100644 index 000000000000..7f6e4f3b717e --- /dev/null +++ b/tools/test/audio/test_utils/print_fr.m @@ -0,0 +1,64 @@ +% print_fr(comp, filename, prm_in_list, prm_out_list, fr_db, fr_hz, pf) +% +% Prints and exports in CSV format a matrix of frequency response widths in Hz + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2020 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function print_fr(comp, fn, prm_in_list, prm_out_list, fr_db, fr_hz, pf) + +n_prmi = length(prm_in_list); +n_prmo = length(prm_out_list); +fh = fopen(fn,'w'); +fprintf(fh,'\n'); +fprintf(fh,'%s test result: Frequency response +/- X.XX dB (YY.Y kHz) \n', comp); +fprintf(fh,'%8s, ', 'in \ out'); + +% Do not print decimals for all integer parameters +if isequal(floor(prm_in_list), prm_in_list) && isequal(floor(prm_out_list), prm_out_list) + int_prms = 1; +else + int_prms = 0; +end + +for a = 1:n_prmo-1 + if int_prms + fprintf(fh,'%12d, ', prm_out_list(a)); + else + fprintf(fh,'%12.1f, ', prm_out_list(a)); + end +end + +if int_prms + fprintf(fh,'%12d', prm_out_list(n_prmo)); +else + fprintf(fh,'%12.1f', prm_out_list(n_prmo)); +end + +fprintf(fh,'\n'); +for a = 1:n_prmi + if int_prms + fprintf(fh,'%8d, ', prm_in_list(a)); + else + fprintf(fh,'%8.1f, ', prm_in_list(a)); + end + + for b = 1:n_prmo + if pf(a,b,1) < 0 + cstr = 'x'; + else + cstr = sprintf('%4.2f (%4.1f)', fr_db(a,b), fr_hz(a,b,2)/1e3); + end + if b < n_prmo + fprintf(fh,'%12s, ', cstr); + else + fprintf(fh,'%12s', cstr); + end + end + fprintf(fh,'\n'); +end + +fclose(fh); +type(fn); +end diff --git a/tools/test/audio/test_utils/print_pf.m b/tools/test/audio/test_utils/print_pf.m new file mode 100644 index 000000000000..f48e95dcef74 --- /dev/null +++ b/tools/test/audio/test_utils/print_pf.m @@ -0,0 +1,72 @@ +% print_pf(comp, filename, prm_in_list, prm_out_list, pf, desc) +% +% Prints and exports in CSV format a matrix of overall pass/fail test results + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2020 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function print_pf(comp, fn, prm_in_list, prm_out_list, pf, desc) + +n_prmi = length(prm_in_list); +n_prmo = length(prm_out_list); +fh = fopen(fn,'w'); +fprintf(fh,'\n'); +fprintf(fh,'%s test result: %s\n', comp, desc); +fprintf(fh,'%8s, ', 'in \ out'); + +% Do not print decimals for all integer parameters +if isequal(floor(prm_in_list), prm_in_list) && isequal(floor(prm_out_list), prm_out_list) + int_prms = 1; +else + int_prms = 0; +end + +for a = 1:n_prmo-1 + if int_prms + fprintf(fh,'%14d, ', prm_out_list(a)); + else + fprintf(fh,'%14.1f, ', prm_out_list(a)); + end +end + +if int_prms + fprintf(fh,'%14d', prm_out_list(n_prmo)); +else + fprintf(fh,'%14.1f', prm_out_list(n_prmo)); +end + +fprintf(fh,'\n'); +spf = size(pf); +npf = spf(3); +for a = 1:n_prmi + if int_prms + fprintf(fh,'%8d, ', prm_in_list(a)); + else + fprintf(fh,'%8.1f, ', prm_in_list(a)); + end + for b = 1:n_prmo + if pf(a,b,1) < 0 + cstr = 'x'; + else + cstr = sprintf('%d', pf(a,b,1)); + for n=2:npf + if pf(a,b,n) < 0 + cstr = sprintf('%s/x', cstr); + else + cstr = sprintf('%s/%d', cstr,pf(a,b,n)); + end + end + end + if b < n_prmo + fprintf(fh,'%14s, ', cstr); + else + fprintf(fh,'%14s', cstr); + end + end + fprintf(fh,'\n'); +end + +fclose(fh); +type(fn); +end diff --git a/tools/test/audio/test_utils/print_val.m b/tools/test/audio/test_utils/print_val.m new file mode 100644 index 000000000000..d4112ce69bc5 --- /dev/null +++ b/tools/test/audio/test_utils/print_val.m @@ -0,0 +1,65 @@ +% print_val(comp, valstr, filename, prm_in_list, prm_out_list, val, pf) +% +% Prints and exports in CSV format a matrix of test results + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2020 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function print_val(comp, valstr, fn, prm_in_list, prm_out_list, val, pf) + +% Do not print decimals for all integer parameters +if isequal(floor(prm_in_list), prm_in_list) && isequal(floor(prm_out_list), prm_out_list) + int_prms = 1; +else + int_prms = 0; +end + +n_prmi = length(prm_in_list); +n_prmo = length(prm_out_list); +fh = fopen(fn,'w'); +fprintf(fh,'\n'); +fprintf(fh,'%s test result: %s\n', comp, valstr); +fprintf(fh,'%8s, ', 'in \ out'); +for a = 1:n_prmo-1 + if int_prms + fprintf(fh,'%8d, ', prm_out_list(a)); + else + fprintf(fh,'%8.1f, ', prm_out_list(a)); + end +end + +if int_prms + fprintf(fh,'%8d', prm_out_list(n_prmo)); +else + fprintf(fh,'%8.1f', prm_out_list(n_prmo)); +end + +fprintf(fh,'\n'); +for a = 1:n_prmi + if int_prms + fprintf(fh,'%8d, ', prm_in_list(a)); + else + fprintf(fh,'%8.1f, ', prm_in_list(a)); + end + for b = 1:n_prmo + if pf(a,b,1) < 0 + cstr = 'x'; + else + if isnan(val(a,b)) + cstr = '-'; + else + cstr = sprintf('%8.2f', val(a,b)); + end + end + if b < n_prmo + fprintf(fh,'%8s, ', cstr); + else + fprintf(fh,'%8s', cstr); + end + end + fprintf(fh,'\n'); +end +fclose(fh); +type(fn); +end diff --git a/tools/test/audio/test_utils/sync_chirp.m b/tools/test/audio/test_utils/sync_chirp.m index 513a426904a0..2209f9f8b105 100644 --- a/tools/test/audio/test_utils/sync_chirp.m +++ b/tools/test/audio/test_utils/sync_chirp.m @@ -3,7 +3,7 @@ %% [y, mark]= sync_chirp(fs, direction) % % Returns a chirp signal that can be used to mark end and beginning of audio -% tests to syncronize input and captured output accurately. +% tests to synchronize input and captured output accurately. % % Input % fs - sample rate diff --git a/tools/test/audio/test_utils/test_run.m b/tools/test/audio/test_utils/test_run.m index 1eb34057f48f..0456bc0af2ad 100644 --- a/tools/test/audio/test_utils/test_run.m +++ b/tools/test/audio/test_utils/test_run.m @@ -30,24 +30,78 @@ function test = test_run(test) -if exist(test.ex) == 2 - %fcmd = sprintf('file %s', test.ex); - %[status, output]=system(fcmd); - %if findstr(output, "Tensilica Xtensa") - % ex = sprintf('xt-run --turbo --summary %s', test.ex); - %else - ex = test.ex; - %end +if isfield(test, 'ex') == 0 + test.ex = './comp_run.sh'; +end + +if exist(fullfile('./', test.ex),'file') == 2 + ex = test.ex; else error('Can''t find executable %s', test.ex); end -test.narg = length(test.arg); -arg = ''; -for n=1:test.narg - arg = sprintf('%s %s', arg, char(test.arg(n))); + +fn_config = sprintf("%s_config.sh", tempname); +fh = fopen(fn_config, 'w'); + +if isfield(test, 'fs_in') == 0 + test.fs_in = test.fs; +end + +if isfield(test, 'bits_in') == 0 + test.bits_in = test.bits; +end + +if isfield(test, 'nch_in') == 0 + test.nch_in = test.nch; +end + +fprintf(fh, '#!/bin/sh\n'); +fprintf(fh, 'COMP=\"%s\"\n', test.comp); +fprintf(fh, 'DIRECTION=playback\n'); +fprintf(fh, 'BITS_IN=%d\n', test.bits_in); +if isfield(test, 'bits_out') && (test.bits_in ~= test.bits_out) + fprintf(fh, 'BITS_OUT=%d\n', test.bits_out); +end + +fprintf(fh, 'CHANNELS_IN=%d\n', test.nch_in); +if isfield(test, 'nch_out') && (test.nch_in ~= test.nch_out) + fprintf(fh, 'CHANNELS_OUT=%d\n', test.nch_out); +end + +fprintf(fh, 'FS_IN=%d\n', test.fs_in); +if isfield(test, 'fs_out') && (test.fs_in ~= test.fs_out) + fprintf(fh, 'FS_OUT=%d\n', test.fs_out); end + +fprintf(fh, 'FN_IN=\"%s\"\n', test.fn_in); +fprintf(fh, 'FN_OUT=\"%s\"\n', test.fn_out); + +if isfield(test, 'extra_opts') + fprintf(fh, 'EXTRA_OPTS=\"%s\"\n', test.extra_opts); +end + +if isfield(test, 'trace') + fprintf(fh, 'FN_TRACE=\"%s\"\n', test.trace); +else + 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 + +fclose(fh); + +arg = sprintf('-t %s', fn_config); rcmd = sprintf('%s %s', ex, arg); fprintf('Running ''%s''...\n', rcmd); -system(rcmd); +ret = system(rcmd); +if ret + error('''%s'' returned status %d\n', rcmd, ret); +end + +delete(fn_config); end diff --git a/tools/test/audio/volume_run.sh b/tools/test/audio/volume_run.sh index 084b2bbbf5a1..72daabead275 100755 --- a/tools/test/audio/volume_run.sh +++ b/tools/test/audio/volume_run.sh @@ -2,14 +2,28 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2020 Intel Corporation. All rights reserved. -if [ -z "$5" ]; then +# stop on most errors +set -e + +usage () +{ echo "Usage: $0 <bits in> <bits out> <rate> <input> <output>" echo "Example: $0 16 16 48000 input.raw output.raw" - exit -fi +} + +main () +{ + local COMP DIRECTION + + if [ $# -ne 5 ]; then + usage "$0" + exit 1 + fi + COMP=volume + DIRECTION=playback -COMP=volume -DIRECTION=playback + ./comp_run.sh $COMP $DIRECTION "$1" "$2" "$3" "$3" "$4" "$5" +} -./comp_run.sh $COMP $DIRECTION $1 $2 $3 $3 $4 $5 +main "$@" diff --git a/tools/test/topology/CMakeLists.txt b/tools/test/topology/CMakeLists.txt index 8568a6bd1724..4e96368341d5 100644 --- a/tools/test/topology/CMakeLists.txt +++ b/tools/test/topology/CMakeLists.txt @@ -9,7 +9,9 @@ file(GLOB TPLG_DEPS find_program(XARGS NAMES xargs PATHS ENV PATH NO_DEFAULT_PATH) -if(${XARGS} STREQUAL XARGS-NOTFOUND) +if(${XARGS} STREQUAL XARGS-NOTFOUND OR + (DEFINED ENV{USE_XARGS} AND NOT $ENV{USE_XARGS} STREQUAL "yes") + ) set(USE_XARGS "no") else() set(USE_XARGS "yes") diff --git a/tools/test/topology/platform/generic.m4 b/tools/test/topology/platform/generic.m4 new file mode 100644 index 000000000000..49469d6b4b9d --- /dev/null +++ b/tools/test/topology/platform/generic.m4 @@ -0,0 +1,60 @@ +# +# Generic test platform values for pipelines and components +# + +undefine(`SSP_MCLK_RATE') +define(`SSP_MCLK_RATE', `19200000') + +undefine(`SSP1_BCLK') +define(`SSP1_BCLK', `1536000') + +undefine(`SSP_BCLK') +define(`SSP_BCLK', `1920000') + +undefine(`SSP_FSYNC') +define(`SSP_FSYNC', `48000') + +define(`SSP1_VALID_BITS_STR', `s16le') + +undefine(`SSP_BITS_WIDTH') +define(`SSP_BITS_WIDTH', `20') + +undefine(`SSP1_VALID_BITS') +define(`SSP1_VALID_BITS', `16') + +undefine(`SSP_VALID_BITS') +define(`SSP_VALID_BITS', `16') + +undefine(`MCLK_ID') +define(`MCLK_ID', `1') + +include(`memory.m4') + +dnl Memory capabilities for different buffer types +define(`PLATFORM_DAI_MEM_CAP', + MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) +define(`PLATFORM_HOST_MEM_CAP', + MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) +define(`PLATFORM_PASS_MEM_CAP', + MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) + +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) + +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# Tone Signal Generator Configuration +W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) + +W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) + +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/test/topology/test-all.m4 b/tools/test/topology/test-all.m4 index ec12ec5d15b8..6ddbe1f304ce 100644 --- a/tools/test/topology/test-all.m4 +++ b/tools/test/topology/test-all.m4 @@ -3,9 +3,9 @@ # # Include topology builder +include(`utils.m4') include(`dai.m4') include(`ssp.m4') -include(`utils.m4') include(`pipeline.m4') # Include TLV library @@ -14,8 +14,8 @@ include(`common/tlv.m4') # Include Token library include(`sof/tokens.m4') -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') +# Include generic DSP configuration +include(`platform/generic.m4') DEBUG_START @@ -60,18 +60,21 @@ PIPELINE_PCM_ADD(sof/pipe-TEST_PIPE_NAME-capture.m4, # SSP port TEST_DAI_PORT is our only pipeline DAI # -# playback DAI is SSP TEST_DAI_PORT using 2 periods +# Use 3 periods for SRC DAI buffer, otherwise 2 periods +ifelse(TEST_PIPE_NAME, `src', `define(TEST_DAI_PERIODS, `3')', `define(TEST_DAI_PERIODS, `2')') + +# playback DAI is SSP TEST_DAI_PORT using TEST_DAI_PERIODS periods # schedule 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, 1, TEST_DAI_TYPE, TEST_DAI_PORT, TEST_DAI_LINK_NAME, - PIPELINE_SOURCE_1, 2, TEST_DAI_FORMAT, + PIPELINE_SOURCE_1, TEST_DAI_PERIODS, TEST_DAI_FORMAT, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) -# capture DAI is SSP TEST_DAI_PORT using 2 periods +# capture DAI is SSP TEST_DAI_PORT using TEST_DAI_PERIODS periods # schedule 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, 2, TEST_DAI_TYPE, TEST_DAI_PORT, TEST_DAI_LINK_NAME, - PIPELINE_SINK_2, 2, TEST_DAI_FORMAT, + PIPELINE_SINK_2, TEST_DAI_PERIODS, TEST_DAI_FORMAT, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) # PCM Passthrough @@ -86,12 +89,12 @@ PCM_DUPLEX_ADD(Passthrough, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) # using TEST_SSP_PHY_BITS bit sample container on SSP TEST_DAI_PORT # DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI_PORT, - ifelse(index(TEST_DAI_LINK_NAME, NoCodec), -1, 0 ,TEST_DAI_PORT), + ifelse(index(TEST_DAI_LINK_NAME, NoCodec), -1, 0, TEST_DAI_PORT), TEST_DAI_LINK_NAME, SSP_CONFIG(TEST_SSP_MODE, SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), - SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI_PORT, TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) diff --git a/tools/test/topology/test-capture.m4 b/tools/test/topology/test-capture.m4 index 50ea33753764..75fb88d45821 100644 --- a/tools/test/topology/test-capture.m4 +++ b/tools/test/topology/test-capture.m4 @@ -3,10 +3,9 @@ # # Include topology builder +include(`utils.m4') include(`dai.m4') include(`ssp.m4') -include(`dmic.m4') -include(`utils.m4') include(`pipeline.m4') # Include TLV library @@ -15,11 +14,14 @@ include(`common/tlv.m4') # Include Token library include(`sof/tokens.m4') -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') +# Include generic DSP configuration +include(`platform/generic.m4') DEBUG_START +# Define the algorithm configurations blobs to apply such as filter coefficients +include(`test_pipeline_filters.m4') + # # Machine Specific Config - !! MUST BE SET TO MATCH TEST MACHINE DRIVER !! # @@ -52,12 +54,15 @@ PIPELINE_PCM_ADD(sof/pipe-TEST_PIPE_NAME-capture.m4, # DAI configuration # # SSP port TEST_DAI_PORT is our only pipeline DAI -# -# capture DAI is SSP TEST_DAI_PORT using 2 periods + +# Use 3 periods for SRC DAI buffer, otherwise 2 periods +ifelse(TEST_PIPE_NAME, `src', `define(TEST_DAI_PERIODS, `3')', `define(TEST_DAI_PERIODS, `2')') + +# capture DAI is SSP TEST_DAI_PORT using TEST_DAI_PERIODS periods # schedule 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, 2, TEST_DAI_TYPE, TEST_DAI_PORT, TEST_DAI_LINK_NAME, - PIPELINE_SINK_2, 2, TEST_DAI_FORMAT, + PIPELINE_SINK_2, TEST_DAI_PERIODS, TEST_DAI_FORMAT, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) # PCM Passthrough @@ -75,8 +80,8 @@ DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI_PORT, 0, TEST_DAI_LINK_NAME, ifelse(TEST_DAI_TYPE, `SSP', SSP_CONFIG(TEST_SSP_MODE, SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), - SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI_PORT, TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID)), diff --git a/tools/test/topology/test-playback.m4 b/tools/test/topology/test-playback.m4 index 7f6e340aec1f..ef16d9b3d839 100644 --- a/tools/test/topology/test-playback.m4 +++ b/tools/test/topology/test-playback.m4 @@ -3,10 +3,10 @@ # # Include topology builder +include(`utils.m4') include(`pipeline.m4') include(`dai.m4') include(`ssp.m4') -include(`utils.m4') # Include TLV library include(`common/tlv.m4') @@ -14,11 +14,14 @@ include(`common/tlv.m4') # Include Token library include(`sof/tokens.m4') -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') +# Include generic DSP configuration +include(`platform/generic.m4') DEBUG_START +dnl Produce uppercase for input string +define(`upcase', `translit(`$*', `a-z', `A-Z')') + # # Machine Specific Config - !! MUST BE SET TO MATCH TEST MACHINE DRIVER !! # @@ -32,12 +35,48 @@ DEBUG_START # TEST_SSP_PHY_BITS - SSP physical slot size # TEST_SSP_DATA_BITS - SSP data slot size # TEST_SSP_MODE - SSP mode e.g. I2S, LEFT_J, DSP_A and DSP_B +# TEST_PIPE_AMOUNT - Total amount of pipelines e.g. 1, 2, 3, 4 # +# Define the algorithm configurations blobs to apply such as filter coefficients +include(`test_pipeline_filters.m4') + +# Define TEST_HAS_PIPEn flags according to TEST_PIPE_AMOUNT. Those flags will be +# used to determine whether PIPELINE_n should be added. +ifelse(TEST_PIPE_AMOUNT, `2', +` +define(TEST_HAS_PIPE2) +') + +ifelse(TEST_PIPE_AMOUNT, `3', +` +define(TEST_HAS_PIPE2) +define(TEST_HAS_PIPE3) +') + +ifelse(TEST_PIPE_AMOUNT, `4', +` +define(TEST_HAS_PIPE2) +define(TEST_HAS_PIPE3) +define(TEST_HAS_PIPE4) +') + # -# Define the pipeline +# Define the pipeline(s) # -# PCM0P --> TEST_PIPE_NAME --> SSP(TEST_DAI_PORT) +# PCM0P --> BUF1.0 --> TEST_PIPE_NAME --> BUF1.1 --> SSP(TEST_DAI_PORT) +ifdef(`TEST_HAS_PIPE2', +` +# +---> BUF2.0 --> SSP(0 or 1) +') +ifdef(`TEST_HAS_PIPE3', +` +# +---> BUF3.0 --> SSP(2 or 3) +') +ifdef(`TEST_HAS_PIPE4', +` +# +---> BUF4.0 --> SSP(4 or 5) +') # # Playback pipeline 1 on PCM 0 using max 2 channels of s32le. @@ -47,18 +86,124 @@ PIPELINE_PCM_ADD(sof/pipe-TEST_PIPE_NAME-playback.m4, 1000, 0, 0, 8000, 192000, 48000) +# Generalize the pipeline junction name as PIPELINE_JUNCTION. +# e.g. TEST_PIPE_NAME=`crossover' --> PIPELINE_JUNCTION=`PIPELINE_CROSSOVER_1' +define(PIPELINE_JUNCTION, concat(concat(`PIPELINE_', upcase(TEST_PIPE_NAME)), `_1')) + +ifdef(`TEST_HAS_PIPE2', +` +# Playback pipeline 2 on PCM 1 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, + 2, 1, 2, s32le, + 1000, 0, 0, + 8000, 192000, 48000) + +# connect pipelines together +SectionGraph."pipe-sof-second-pipe" { + index "2" + + lines [ + # connect the second sink buffer + dapm(PIPELINE_SOURCE_2, PIPELINE_JUNCTION) + ] +} +') + +ifdef(`TEST_HAS_PIPE3', +` +# Playback pipeline 3 on PCM 2 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, + 3, 2, 2, s32le, + 1000, 0, 0, + 8000, 192000, 48000) + +# connect pipelines together +SectionGraph."pipe-sof-third-pipe" { + index "3" + + lines [ + # connect the third sink buffer + dapm(PIPELINE_SOURCE_3, PIPELINE_JUNCTION) + ] +} +') + +ifdef(`TEST_HAS_PIPE4', +` +# Playback pipeline 4 on PCM 3 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, + 4, 3, 2, s32le, + 1000, 0, 0, + 8000, 192000, 48000) + +# connect pipelines together +SectionGraph."pipe-sof-fourth-pipe" { + index "4" + + lines [ + # connect the fourth sink buffer + dapm(PIPELINE_SOURCE_4, PIPELINE_JUNCTION) + ] +} +') + # DAI configuration -# -# SSP port TEST_DAI_PORT is our only pipeline DAI -# -# playback DAI is SSP TEST_DAI_PORT using 2 periods +# Use 3 periods for SRC DAI buffer, otherwise 2 periods +ifelse(TEST_PIPE_NAME, `src', `define(TEST_DAI_PERIODS, `3')', `define(TEST_DAI_PERIODS, `2')') + +# playback DAI is SSP TEST_DAI_PORT using TEST_DAI_PERIODS periods # Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, 1, TEST_DAI_TYPE, TEST_DAI_PORT, TEST_DAI_LINK_NAME, - PIPELINE_SOURCE_1, 2, TEST_DAI_FORMAT, + PIPELINE_SOURCE_1, TEST_DAI_PERIODS, TEST_DAI_FORMAT, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) +ifdef(`TEST_HAS_PIPE2', +` +define(TEST_DAI2_PORT, ifelse(TEST_DAI_PORT, `0', `1', `0')) +define(TEST_DAI2_LINK_NAME, ifelse(TEST_DAI_PORT, `0', `SSP1-Codec', `SSP0-Codec')) + +# playback DAI is SSP TEST_DAI2_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, + 2, TEST_DAI_TYPE, TEST_DAI2_PORT, TEST_DAI2_LINK_NAME, + PIPELINE_SOURCE_2, 2, TEST_DAI_FORMAT, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) +') + +ifdef(`TEST_HAS_PIPE3', +` +define(TEST_DAI3_PORT, ifelse(TEST_DAI_PORT, `2', `3', `2')) +define(TEST_DAI3_LINK_NAME, ifelse(TEST_DAI_PORT, `2', `SSP3-Codec', `SSP2-Codec')) + +# playback DAI is SSP TEST_DAI3_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, + 3, TEST_DAI_TYPE, TEST_DAI3_PORT, TEST_DAI3_LINK_NAME, + PIPELINE_SOURCE_3, 2, TEST_DAI_FORMAT, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) +') + +ifdef(`TEST_HAS_PIPE4', +` +define(TEST_DAI4_PORT, ifelse(TEST_DAI_PORT, `4', `5', `4')) +define(TEST_DAI4_LINK_NAME, ifelse(TEST_DAI_PORT, `4', `SSP5-Codec', `SSP4-Codec')) + +# playback DAI is SSP TEST_DAI4_PORT using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, + 4, TEST_DAI_TYPE, TEST_DAI4_PORT, TEST_DAI4_LINK_NAME, + PIPELINE_SOURCE_4, 2, TEST_DAI_FORMAT, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) +') + # PCM Passthrough PCM_PLAYBACK_ADD(Passthrough, 0, PIPELINE_PCM_1) @@ -68,16 +213,51 @@ PCM_PLAYBACK_ADD(Passthrough, 0, PIPELINE_PCM_1) # Clocks masters wrt codec # # TEST_SSP_DATA_BITS bit I2S -# using TEST_SSP_PHY_BITS bit sample container on SSP TEST_DAI_PORT +# using TEST_SSP_PHY_BITS bit sample container on SSP port(s) # DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI_PORT, 0, TEST_DAI_LINK_NAME, SSP_CONFIG(TEST_SSP_MODE, SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), - SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI_PORT, TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +ifdef(`TEST_HAS_PIPE2', +` +DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI2_PORT, 1, TEST_DAI2_LINK_NAME, + SSP_CONFIG(TEST_SSP_MODE, + SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), + SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI2_PORT, + TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +') + +ifdef(`TEST_HAS_PIPE3', +` +DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI3_PORT, 2, TEST_DAI3_LINK_NAME, + SSP_CONFIG(TEST_SSP_MODE, + SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), + SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI3_PORT, + TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +') + +ifdef(`TEST_HAS_PIPE4', +` +DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI4_PORT, 3, TEST_DAI4_LINK_NAME, + SSP_CONFIG(TEST_SSP_MODE, + SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), + SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI4_PORT, + TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) +') DEBUG_END diff --git a/tools/test/topology/test-tone-playback.m4 b/tools/test/topology/test-tone-playback.m4 index 5f3f8d2e02b1..6007b5381221 100644 --- a/tools/test/topology/test-tone-playback.m4 +++ b/tools/test/topology/test-tone-playback.m4 @@ -64,8 +64,8 @@ DAI_ADD(sof/pipe-dai-playback.m4, DAI_CONFIG(TEST_DAI_TYPE, TEST_DAI_PORT, TEST_DAI_PORT, TEST_DAI_LINK_NAME, SSP_CONFIG(TEST_SSP_MODE, SSP_CLOCK(mclk, TEST_SSP_MCLK, codec_mclk_in), - SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), + SSP_CLOCK(bclk, TEST_SSP_BCLK, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), SSP_TDM(2, TEST_SSP_PHY_BITS, 3, 3), SSP_CONFIG_DATA(TEST_DAI_TYPE, TEST_DAI_PORT, TEST_SSP_DATA_BITS, TEST_SSP_MCLK_ID))) diff --git a/tools/test/topology/test_pipeline_filters.m4 b/tools/test/topology/test_pipeline_filters.m4 new file mode 100644 index 000000000000..c68d7e717e91 --- /dev/null +++ b/tools/test/topology/test_pipeline_filters.m4 @@ -0,0 +1,34 @@ + +# Define the algorithm configurations blobs to apply such as filter coefficients + +# EQs +ifelse(TEST_PIPE_NAME, `eq-iir', `define(PIPELINE_FILTER1, `eq_iir_coef_loudness.m4')') +ifelse(TEST_PIPE_NAME, `eq-fir', `define(PIPELINE_FILTER2, `eq_fir_coef_loudness.m4')') + +# TDFB test pipelines with different names for different configurations + +# line array 2 mic +ifelse(TEST_PIPE_NAME, `tdfb', `define(PIPELINE_FILTER1, `tdfb/coef_line2_50mm_pm90deg_48khz.m4')') + +# line array 4 mic +ifelse(TEST_PIPE_NAME, `tdfb_line4_28mm_pm90deg_48khz', +` +define(PIPELINE_FILTER1, `tdfb/coef_line4_28mm_pm90deg_48khz.m4') +define(TEST_PIPE_NAME, `tdfb') +') + +# circular 8 mic, use 360 degree enum controls variant while line array +# is 180 degrees +ifelse(TEST_PIPE_NAME, `tdfb_circular8_100mm_az0el0deg_48khz', +` +define(PIPELINE_FILTER1, `tdfb/coef_circular8_100mm_az0el0deg_48khz.m4') +define(TEST_PIPE_NAME, `tdfb360') +') + +# circular 8 mic, use 360 degree enum controls variant while line array +# is 180 degrees +ifelse(TEST_PIPE_NAME, `tdfb_circular8_100mm_pm30deg_48khz', +` +define(PIPELINE_FILTER1, `tdfb/coef_circular8_100mm_pm30deg_48khz.m4') +define(TEST_PIPE_NAME, `tdfb360') +') diff --git a/tools/test/topology/tplg-build.sh b/tools/test/topology/tplg-build.sh index 936415352ba2..43db928d9c9b 100755 --- a/tools/test/topology/tplg-build.sh +++ b/tools/test/topology/tplg-build.sh @@ -6,21 +6,25 @@ # binaries. Currently supports simple PCM <-> component <-> SSP style tests # using simple_test() -# Remove possible old topologies -rm -f test-*.conf test-*.tplg - # fail immediately on any errors set -e +MYDIR="$(cd $(dirname "$0") && pwd)" +cd "${MYDIR}" + # M4 preprocessor flags -export M4PATH="../../topology/:../../topology/m4:../../topology/common:../../topology/platform/intel:../../topology/platform/common" +export M4PATH="../../topology/topology1:../../topology/topology1/m4:../../topology/topology1/common:../../topology/topology1/platform/intel:../../topology/topology1/platform/common" if [ -z "$SOF_TPLG_BUILD_OUTPUT" ] then - BUILD_OUTPUT="." + BUILD_OUTPUT="./build_test_topo" else BUILD_OUTPUT="$SOF_TPLG_BUILD_OUTPUT" fi +mkdir -p "$BUILD_OUTPUT" + +# Remove possible old topologies +rm -f "$BUILD_OUTPUT"/test-*.conf "$BUILD_OUTPUT"/test-*.tplg # Simple component test cases # can be used on components with 1 sink and 1 source. @@ -34,21 +38,22 @@ M4_STRINGS="" # 3) be_name - BE DAI link name in machine driver, used for matching # 4) format - PCM sample format # 5) dai_type - dai type e.g. SSP/DMIC -# 5) dai_id - SSP port number -# 6) dai_format - SSP sample format -# 7) dai_phy_bits - SSP physical number of BLKCs per slot/channel -# 8) dai_data_bits - SSP number of valid data bits per slot/channel -# 9) dai_bclk - SSP BCLK in HZ -# 10) dai_mclk - SSP MCLK in HZ -# 11) SSP mode - SSP mode e.g. I2S, LEFT_J, DSP_A and DSP_B -# 12) SSP mclk_id -# 13) Test pipelines +# 6) dai_id - SSP port number +# 7) dai_format - SSP sample format +# 8) dai_phy_bits - SSP physical number of BLKCs per slot/channel +# 9) dai_data_bits - SSP number of valid data bits per slot/channel +# 10) dai_bclk - SSP BCLK in HZ +# 11) dai_mclk - SSP MCLK in HZ +# 12) SSP mode - SSP mode e.g. I2S, LEFT_J, DSP_A and DSP_B +# 13) SSP mclk_id +# 14) total number of pipelines - range from 1 to 4 +# 15) Test pipelines # function simple_test { if [ $5 == "SSP" ] then - TESTS=("${!14}") + TESTS=("${!15}") elif [ $5 == "DMIC" ] then TESTS=("${!15}") @@ -59,6 +64,7 @@ function simple_test { then TFILE="$i-dmic$6-${14}-$2-$4-$7-$((${13} / 1000))k-$1" echo "M4 pre-processing test $i -> ${TFILE}" + (set -x m4 ${M4_FLAGS} \ -DTEST_PIPE_NAME="$2" \ -DTEST_DAI_LINK_NAME="$3" \ @@ -75,8 +81,11 @@ function simple_test { -DTEST_DMIC_PDM_CONFIG=${14} \ -DTEST_DMIC_UNMUTE_TIME=400 \ $i.m4 > "$BUILD_OUTPUT/${TFILE}.conf" + ) echo "Compiling test $i -> $BUILD_OUTPUT/${TFILE}.tplg" + (set -x alsatplg -v 1 -c "$BUILD_OUTPUT/${TFILE}.conf" -o "$BUILD_OUTPUT/${TFILE}.tplg" + ) else if [ "$USE_XARGS" == "yes" ] then @@ -87,7 +96,12 @@ function simple_test { then TFILE="test-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" else - TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + if [ ${14} == "1" ] + then + TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + else + TFILE="$i-ssp$6-mclk-${13}-${12}-${14}way-$2-$4-$7-48k-$((${11} / 1000))k-$1" + fi fi #create input string for batch m4 processing M4_STRINGS+="-DTEST_PIPE_NAME=$2,-DTEST_DAI_LINK_NAME=$3\ @@ -95,7 +109,8 @@ function simple_test { -DTEST_PIPE_FORMAT=$4,-DTEST_SSP_BCLK=${10}\ -DTEST_SSP_MCLK=${11},-DTEST_SSP_PHY_BITS=$8\ -DTEST_SSP_DATA_BITS=$9,-DTEST_SSP_MODE=${12}\ - -DTEST_SSP_MCLK_ID=${13},-DTEST_DAI_TYPE=$5\ + -DTEST_SSP_MCLK_ID=${13},-DTEST_PIPE_AMOUNT=${14}\ + -DTEST_DAI_TYPE=$5\ $i.m4,$BUILD_OUTPUT/${TFILE}," #create input string for batch processing of conf files TEST_STRINGS+="$BUILD_OUTPUT/${TFILE}," @@ -108,9 +123,15 @@ function simple_test { then TFILE="test-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" else - TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + if [ ${14} == "1" ] + then + TFILE="$i-ssp$6-mclk-${13}-${12}-$2-$4-$7-48k-$((${11} / 1000))k-$1" + else + TFILE="$i-ssp$6-mclk-${13}-${12}-${14}way-$2-$4-$7-48k-$((${11} / 1000))k-$1" + fi fi echo "M4 pre-processing test $i -> ${TFILE}" + ( set -x m4 ${M4_FLAGS} \ -DTEST_PIPE_NAME="$2" \ -DTEST_DAI_LINK_NAME="$3" \ @@ -123,10 +144,14 @@ function simple_test { -DTEST_SSP_DATA_BITS=$9 \ -DTEST_SSP_MODE=${12} \ -DTEST_SSP_MCLK_ID=${13} \ + -DTEST_PIPE_AMOUNT=${14} \ -DTEST_DAI_TYPE=$5 \ $i.m4 > "$BUILD_OUTPUT/${TFILE}.conf" + ) echo "Compiling test $i -> $BUILD_OUTPUT/${TFILE}.tplg" + (set -x alsatplg -v 1 -c "$BUILD_OUTPUT/${TFILE}.conf" -o "$BUILD_OUTPUT/${TFILE}.tplg" + ) fi fi fi @@ -136,18 +161,18 @@ function simple_test { echo "Preparing topology build input..." # Pre-process the simple tests -simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] -simple_test codec passthrough "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec passthrough "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s24le SSP 2 s16le 20 16 1920000 19200000 I2S 0 SIMPLE_TESTS[@] -simple_test codec volume "SSP2-Codec" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 SIMPLE_TESTS[@] +simple_test codec passthrough "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec passthrough "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s16le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s24le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s24le SSP 2 s16le 20 16 1920000 19200000 I2S 0 1 SIMPLE_TESTS[@] +simple_test codec volume "SSP2-Codec" s16le SSP 2 s24le 25 24 2400000 19200000 I2S 0 1 SIMPLE_TESTS[@] # for APL APL_PROTOCOL_TESTS=(I2S LEFT_J DSP_A DSP_B) @@ -166,25 +191,25 @@ do do for mclk_id in ${MCLK_IDS[@]} do - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] done done done for mclk_id in ${MCLK_IDS[@]} do - simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test nocodec passthrough "NoCodec-${ssp}" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 SIMPLE_TESTS[@] done done done @@ -197,25 +222,30 @@ do do for format in ${APL_FORMAT_TESTS[@]} do - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test nocodec $mode "NoCodec-${ssp}" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" $format SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] done done - simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test nocodec passthrough "NoCodec-${ssp}" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 SIMPLE_TESTS[@] - simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s16le SSP $ssp s16le 20 16 1920000 19200000 $protocol 0 1 SIMPLE_TESTS[@] + simple_test codec passthrough "SSP${ssp}-Codec" s24le SSP $ssp s24le 25 24 2400000 19200000 $protocol 0 1 SIMPLE_TESTS[@] done done # for processing algorithms -ALG_MODE_TESTS=(asrc eq-fir eq-iir src) -ALG_SIMPLE_TESTS=(test-capture test-playback) +ALG_SINGLE_MODE_TESTS=(asrc eq-fir eq-iir src dcblock drc multiband-drc tdfb + tdfb_line4_28mm_pm90deg_48khz tdfb_circular8_100mm_pm30deg_48khz + mfcc) +ALG_SINGLE_SIMPLE_TESTS=(test-capture test-playback) +ALG_MULTI_MODE_TESTS=(crossover) +ALG_MULTI_SIMPLE_TESTS=(test-playback) +ALG_MULTI_PIPE_AMOUNT=(2 3 4) ALG_PROTOCOL_TESTS=(I2S) ALG_SSP_TESTS=(5) ALG_MCLK_IDS=(0) @@ -224,47 +254,69 @@ for protocol in ${ALG_PROTOCOL_TESTS[@]} do for ssp in ${ALG_SSP_TESTS[@]} do - for mode in ${ALG_MODE_TESTS[@]} + for mclk_id in ${ALG_MCLK_IDS[@]} do - for mclk_id in ${ALG_MCLK_IDS[@]} + for mode in ${ALG_SINGLE_MODE_TESTS[@]} + do + simple_test codec $mode "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id 1 ALG_SINGLE_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id 1 ALG_SINGLE_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id 1 ALG_SINGLE_SIMPLE_TESTS[@] + done + + for mode in ${ALG_MULTI_MODE_TESTS[@]} do - simple_test codec $mode "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id ALG_SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id ALG_SIMPLE_TESTS[@] - simple_test codec $mode "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id ALG_SIMPLE_TESTS[@] + for pipe_num in ${ALG_MULTI_PIPE_AMOUNT[@]} + do + simple_test codec $mode "SSP${ssp}-Codec" s16le SSP $ssp s16le 16 16 1536000 24576000 $protocol $mclk_id $pipe_num ALG_MULTI_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s24le SSP $ssp s24le 32 24 3072000 24576000 $protocol $mclk_id $pipe_num ALG_MULTI_SIMPLE_TESTS[@] + simple_test codec $mode "SSP${ssp}-Codec" s32le SSP $ssp s32le 32 32 3072000 24576000 $protocol $mclk_id $pipe_num ALG_MULTI_SIMPLE_TESTS[@] + done done done done done # for CNL -simple_test nocodec passthrough "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s16le SSP 0 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-0" s24le SSP 0 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s16le SSP 0 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s16le SSP 0 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s24le SSP 0 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-0" s24le SSP 0 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec volume "NoCodec-2" s24le SSP 2 s16le 25 16 2400000 24000000 I2S 0 SIMPLE_TESTS[@] -simple_test nocodec src "NoCodec-4" s24le SSP 4 s24le 25 24 2400000 24000000 I2S 0 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec passthrough "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s16le SSP 2 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s24le SSP 2 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec volume "NoCodec-2" s24le SSP 2 s16le 25 16 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] +simple_test nocodec src "NoCodec-4" s24le SSP 4 s24le 25 24 2400000 24000000 I2S 0 1 SIMPLE_TESTS[@] # algorithms tests if [ "$USE_XARGS" == "yes" ] then - echo "Batch processing m4 files..." + printf '%s generating %s/*.conf files with m4...\n' "$0" "$BUILD_OUTPUT" M4_STRINGS=${M4_STRINGS%?} #m4 processing - echo $M4_STRINGS | tr " " "," | tr '\n' '\0' | xargs -P0 -d ',' -n14 bash -c 'm4 "${@:1:${#}-1}" > ${14}.conf' m4 + + : ${NO_PROCESSORS:=$(nproc)} + + # Each test is defined by 15 consecutive strings, the last one + # is the ${15}.conf output file. + shell_name=m4 # $0, only used in error messages + echo $M4_STRINGS | tr " " "," | tr '\n' '\0' | + xargs ${VERBOSE:+-t} -P${NO_PROCESSORS} -d ',' -n15 \ + bash ${VERBOSE:+-x} -c \ + 'm4 --fatal-warnings "${@:1:${#}-1}" > ${15}.conf || exit 255' \ + $shell_name #execute alsatplg to create topology binary + # $TEST_STRINGS is a very long line of comma-delimited filenames. + printf '%s generating %s/*.tplg files with alsatplg...\n' \ + "$0" "$BUILD_OUTPUT" TEST_STRINGS=${TEST_STRINGS%?} - echo $TEST_STRINGS | tr '\n' ',' |\ - xargs -d ',' -P0 -n1 -I string alsatplg -v 1 -c\ - string".conf" -o string".tplg" + echo $TEST_STRINGS | tr '\n' ',' | + xargs ${VERBOSE:+-t} -d ',' -P${NO_PROCESSORS} -I string \ + alsatplg ${VERBOSE:+-v 1} -c string".conf" -o string".tplg" fi - diff --git a/tools/testbench/CMakeLists.txt b/tools/testbench/CMakeLists.txt index 4ab754b039f6..100dc320debf 100644 --- a/tools/testbench/CMakeLists.txt +++ b/tools/testbench/CMakeLists.txt @@ -1,64 +1,87 @@ # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) project(SOF_TESTBENCH C) include(../../scripts/cmake/misc.cmake) +include(CheckCCompilerFlag) -add_executable(testbench - testbench.c - alloc.c - common_test.c - file.c - ipc.c - schedule.c - ll_schedule.c - edf_schedule.c - panic.c - timer.c - topology.c - trace.c -) +set(default_asoc_h "/usr/include/alsa/sound/uapi/asoc.h") -sof_append_relative_path_definitions(testbench) +file(READ "../../src/arch/host/configs/library_defconfig" library_defconfig) -target_include_directories(testbench PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +if(library_defconfig MATCHES "CONFIG_IPC_MAJOR_4=y") + message("-- Selected IPC4 build for testbench") + set(testbench "sof-testbench4") +else() + message("-- Selected IPC3 build for testbench") + set(testbench "sof-testbench3") +endif() -target_compile_options(testbench PRIVATE -g -O3 -Wall -Werror -Wl,-EL -Wmissing-prototypes -Wimplicit-fallthrough=3) +add_executable(${testbench} + testbench.c + file.c + utils.c + utils_ipc3.c + utils_ipc4.c + topology_ipc3.c + topology_ipc4.c +) -target_link_libraries(testbench PRIVATE -ldl -lm) +sof_append_relative_path_definitions(${testbench}) -install(TARGETS testbench DESTINATION bin) +target_include_directories(${testbench} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) set(sof_source_directory "${PROJECT_SOURCE_DIR}/../..") set(sof_install_directory "${PROJECT_BINARY_DIR}/sof_ep/install") set(sof_binary_directory "${PROJECT_BINARY_DIR}/sof_ep/build") +set(config_h ${sof_binary_directory}/library_autoconfig.h) + +target_include_directories(${testbench} PRIVATE "${sof_source_directory}/src/platform/library/include") +target_include_directories(${testbench} PRIVATE "${sof_source_directory}/src/audio") + +# Configuration time, make copy +configure_file(${default_asoc_h} ${CMAKE_CURRENT_BINARY_DIR}/include/alsa/sound/asoc.h) + +# Build time +target_include_directories(${testbench} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include") + +# -Wimplicit-fallthrough is preferred, check if it's supported +check_c_compiler_flag(-Wimplicit-fallthrough supports_implicit_fallthrough) +if (supports_implicit_fallthrough) + set(implicit_fallthrough -Wimplicit-fallthrough) +endif() + +target_compile_options(${testbench} PRIVATE -g -O3 -Wall -Werror -Wmissing-prototypes + ${implicit_fallthrough} -DCONFIG_LIBRARY -DCONFIG_LIBRARY_STATIC -imacros${config_h}) + +target_link_libraries(${testbench} PRIVATE -lm) + +install(TARGETS ${testbench} DESTINATION bin) + include(ExternalProject) +# Should we do this? Only for sof_ep, not for parser_ep? +# https://stackoverflow.com/questions/12021448/how-can-cmake-arguments-be-forwarded-to-externalproject ExternalProject_Add(sof_ep DOWNLOAD_COMMAND "" SOURCE_DIR "${sof_source_directory}" PREFIX "${PROJECT_BINARY_DIR}/sof_ep" BINARY_DIR "${sof_binary_directory}" - CMAKE_ARGS -DBUILD_LIBRARY=ON + CMAKE_ARGS -DCONFIG_LIBRARY=ON -DCMAKE_INSTALL_PREFIX=${sof_install_directory} -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -DINIT_CONFIG=library_defconfig + -DCONFIG_H_PATH=${config_h} + -DCONFIG_LIBRARY_STATIC=ON BUILD_ALWAYS 1 - BUILD_BYPRODUCTS "${sof_install_directory}/lib/libsof.so" -) - -ExternalProject_Add_Step( - sof_ep defconfig - COMMAND ${CMAKE_COMMAND} --build . --target library_defconfig - DEPENDEES configure - DEPENDERS build - WORKING_DIRECTORY "${sof_binary_directory}" + BUILD_BYPRODUCTS "${sof_install_directory}/lib/libsof.a" ) -add_library(sof_library SHARED IMPORTED) -set_target_properties(sof_library PROPERTIES IMPORTED_LOCATION "${sof_install_directory}/lib/libsof.so") +add_library(sof_library STATIC IMPORTED) +set_target_properties(sof_library PROPERTIES IMPORTED_LOCATION "${sof_install_directory}/lib/libsof.a") add_dependencies(sof_library sof_ep) set(parser_source_directory "${PROJECT_SOURCE_DIR}/../tplg_parser") @@ -69,25 +92,26 @@ ExternalProject_Add(parser_ep SOURCE_DIR "${parser_source_directory}" PREFIX "${PROJECT_BINARY_DIR}/sof_parser" BINARY_DIR "${PROJECT_BINARY_DIR}/sof_parser/build" - CMAKE_ARGS -DBUILD_LIBRARY=ON + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/sof_parser/install -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} - BUILD_COMMAND make + -DCONFIG_LIBRARY_STATIC=ON BUILD_ALWAYS 1 - BUILD_BYPRODUCTS "${parser_install_dir}/lib/libsof_tplg_parser.so" + BUILD_BYPRODUCTS "${parser_install_dir}/lib/libsof_tplg_parser.a" ) -add_library(sof_parser_lib SHARED IMPORTED) -set_target_properties(sof_parser_lib PROPERTIES IMPORTED_LOCATION "${parser_install_dir}/lib/libsof_tplg_parser.so") +add_library(sof_parser_lib STATIC IMPORTED) +set_target_properties(sof_parser_lib PROPERTIES IMPORTED_LOCATION "${parser_install_dir}/lib/libsof_tplg_parser.a") add_dependencies(sof_parser_lib parser_ep) -add_dependencies(testbench sof_parser_lib) -target_link_libraries(testbench PRIVATE sof_library) -target_link_libraries(testbench PRIVATE sof_parser_lib) -target_include_directories(testbench PRIVATE ${sof_install_directory}/include) -target_include_directories(testbench PRIVATE ${parser_install_dir}/include) +add_dependencies(${testbench} sof_parser_lib) +target_link_libraries(${testbench} PRIVATE sof_library) +target_link_libraries(${testbench} PRIVATE sof_parser_lib) +target_link_libraries(${testbench} PRIVATE m) +target_include_directories(${testbench} PRIVATE ${sof_install_directory}/include) +target_include_directories(${testbench} PRIVATE ${parser_install_dir}/include) -set_target_properties(testbench +set_target_properties(${testbench} PROPERTIES INSTALL_RPATH "${sof_install_directory}/lib" INSTALL_RPATH_USE_LINK_PATH TRUE diff --git a/tools/testbench/README.md b/tools/testbench/README.md new file mode 100644 index 000000000000..d4030adc426d --- /dev/null +++ b/tools/testbench/README.md @@ -0,0 +1,325 @@ +# SOF testbench + +### Features + + * Simulate IPC3 and IPC4 SOF versions with run of set of processing + components based on desired topology. + * Replaces host and dai components with file I/O with raw binary + S16_LE/S24_LE/S32_LE or text format files for audio waveforms. + * Much faster than real-time execution in native build, e.g. x86 on + Linux for efficient validation usage. + * With xtensa DSP build offers cycles accurate simulated environment + execution. And also with options for simulation speed vs. model + accuracy. + * Allows easy use of conventional debugger, profiler, leak and memory check + tools usage for DSP firmware code. + +### Prerequisites + +Before running the SOF testbench, install the required dependencies: + +``` +sudo apt install valgrind octave-signal octave # For Ubuntu/Debian +sudo dnf install valgrind octave-signal octave # For Fedora +``` + +### Quick how-to + +The simplest way to build and execute testbench is with supplied +scripts. It executes a simple chirp waveform test for a number of +processing components. Corrupted audio or failure in execution +or a memory violation results to fail of test. + +``` +cd $SOF_WORKSPACE/sof +scripts/build-tools.sh +scripts/rebuild-testbench.sh +scripts/host-testbench.sh +``` + +### Manual run of IPC4 testbench + +As an example, process a wav file and listen it. The example +processing component is IIR equalizer. The wav file is first converted +with sox to raw 32 bit 48 kHz stereo format, then processed by +testbench, converted back to wav. + +The example processes the playback direction of topology +sof-hda-benchmark-eqiir32.tplg with IIR component. The playback +direction in the component test topologies consists of host pipeline 1 +and dai pipeline 2. Therefore the command line has option -p 1,2. + +``` +cd $SOF_WORKSPACE/sof +sox --encoding signed-integer /usr/share/sounds/alsa/Front_Left.wav -L -r 48000 -c 2 -b 32 in.raw +tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -c 2 -b S32_LE \ + -p 1,2 -t tools/build_tools/topology/topology2/development/sof-hda-benchmark-eqiir32.tplg \ + -i in.raw -o out.raw +sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav +aplay out.wav +``` + +To test capture use -p 3,4 with same topologies. To run both +directions, use -p 1,2,3,4 and provide multiple input and output +files separated with comma. Use e.g. -i i1.raw,i2.raw +-o o1.raw,o2.raw. + +### Apply controls to simulation + +The testbench supports shell script like amixer and sleep commands for +the controls. Create e.g. this script file as controls.sh: + +``` +#!/bin/sh + +# Example test sequence for DRC and volume components + +amixer -c0 cset name='Post Mixer Analog Playback DRC switch' off +amixer -c0 cset name='Post Mixer Analog Playback Volume' 40,30 +sleep 1 +amixer -c0 cset name='Post Mixer Analog Playback Volume' 0 +sleep 1 +amixer -c0 cset name='Post Mixer Analog Playback Volume' 45 +``` + +Then generarate sine wave (997 Hz, -3 dB level, 3 seconds) with sox +and check the impact to processed signal with next commands: + +``` +sox -n --encoding signed-integer -L -r 48000 -c 2 -b 32 in.raw synth 3 sine 997 norm -3 + +tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -c 2 -b S32_LE -p 1,2 \ + -t tools/build_tools/topology/topology2/production/sof-hda-generic.tplg \ +-i in.raw -o out.raw -s controls.sh + +sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav +``` + +As second example apply in one second intervals bytes control blobs +for IIR equalizer. The impact is easiest to hear with pink noise +signal. Create the control script below and run the following commands +to create the input, run testbench, and convert to wav for examining +the output. + +``` +#!/bin/sh + +# Example test sequence for IIR equalizer, switch other processing off + +amixer -c0 cset name='Post Mixer Analog Playback DRC switch' off +amixer -c0 cset name='Post Mixer Analog Playback Volume' 45 +sof-ctl -c name='Post Mixer Analog Playback FIR Eq bytes' -s tools/ctl/ipc4/eq_fir/pass.txt +sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/pass.txt +sleep 1 +sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/loudness.txt +sleep 1 +sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/bandpass.txt +sleep 1 +sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/bassboost.txt +sleep 1 +sof-ctl -c name='Post Mixer Analog Playback IIR Eq bytes' -s tools/ctl/ipc4/eq_iir/highpass_50hz_0db_48khz.txt +``` + +``` +sox -n --encoding signed-integer -L -r 48000 -c 2 -b 32 in.raw synth 5 pinknoise norm -20 + +tools/testbench/build_testbench/install/bin/sof-testbench4 -r 48000 -c 2 -b S32_LE -p 1,2 \ + -t tools/build_tools/topology/topology2/production/sof-hda-generic.tplg \ + -i in.raw -o out.raw -s controls.sh + +sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav +``` + +### Run testbench with helper script + +The scripts/sof-testbench-helper.sh simplifies the task. See the help +text shown with option -h. + +``` +Usage: scripts/sof-testbench-helper.sh <options> +Options + -b <bits>, default 32 + -c <channels>, default 2 + -h shows this text + -i <input wav>, default /usr/share/sounds/alsa/Front_Center.wav + -k keep temporary files in /tmp + -m <module>, default gain + -n <pipelines>, default 1,2 + -o <output wav>, default none + -p <profiling result text>, use with -x, default none + -r <rate>, default 48000 + -t <force topology>, default none, e.g. production/sof-hda-generic.tplg + -v runs with valgrind, not available with -x + -x runs testbench with xt-run simulator + +Example: run DRC with xt-run with profiling (slow) +scripts/sof-testbench-helper.sh -x -m drc -p profile-drc32.txt + +Example: process with native build DRC file Front_Center.wav (fast) +scripts/sof-testbench-helper.sh -m drc -i /usr/share/sounds/alsa/Front_Center.wav \ + -o ~/tmp/Front_Center_with_DRC.wav + +Example: check component eqiir with valgrind +scripts/sof-testbench-helper.sh -v -m eqiir +``` + +The above manual run can be executed with single command. The -i could +be omitted as well since the ALSA clip is the default input wav. + + +``` +scripts/sof-testbench-helper.sh -m eqiir -i /usr/share/sounds/alsa/Front_Center.wav -o out.wav +``` + +To run the same example with Xtensa simulator (MTL platform), set up +the build environment, build, and execute with additional -x +option. An MCPS estimate for pipeline execution is printed in the end +of run than can be useful when checking impact of code +optimizations. Note that the cycles of testbench file component that +replaces host-copier and dai-copier are excluded. + +``` +export XTENSA_TOOLS_ROOT=~/xtensa/XtDevTools +export ZEPHYR_TOOLCHAIN_VARIANT=xt-clang +scripts/rebuild-testbench.sh -p mtl +scripts/sof-testbench-helper.sh -x -m eqiir -i /usr/share/sounds/alsa/Front_Center.wav -o out.wav +``` + +### Run Xtensa profiler with helper script + +When profiling add to above run script option -p, e.g. (can omit output wav conversion). + + +``` +scripts/sof-testbench-helper.sh -x -m eqiir -p profile-eqiir.txt +less profile-eqiir.txt +``` + +The output of xt-gprof looks like + +``` +Flat profile: + self total + cumulative self cycles cycles + % cycles cycles calls /call /call name + (K) (K) (K) (K) +56.73 10144.51 10144.51 137088 0.07 0.07 iir_df1 +12.91 12453.23 2308.72 1428 1.62 8.72 eq_iir_s32_default + 3.23 13031.59 578.36 4290 0.13 3.61 module_adapter_copy + 2.22 13429.03 397.44 2860 0.14 0.67 file_process + 2.14 13811.37 382.34 3178 0.12 0.13 memmove + +``` + +To profile a set of processing components in SOF there is example +script sof-testbench-build-profile.sh. It profiles also two +hda-generic topologies with multiple SOF components in it. The help +for the script is shown with option -h: + +``` +Usage: scripts/sof-testbench-build-profile.sh <options> + -d <directory> directory to place code profiling reports + -h shows this text + -p <platform> sets platform for scripts/rebuild-testbench.sh +``` + +It can be run for platform mtl with command +``` +scripts/sof-testbench-build-profile.sh -p mtl +``` + +The profiling reports and component run logs (with MCPS) can be found +from default directory tools/testbench/profile. + +### Perform audio processing quality checks + +This step needs Matlab or Octave tool with signal processing +package. A number of tests is performed for IIR equalizer component as +example. The script opens plot windows and outputs a text report in +the end. A simple pass/fail criteria is used to report a verdict of +the test run. + +``` +cd $SOF_WORKSPACE/sof/tools/test/audio +octave -q --eval "pkg load signal io; [n_fail]=process_test('eq-iir', 32, 32, 48000, 1, 1); input('Press ENTER'); exit(n_fail)" +``` + +See from interactive Octave shell command "help process_test" the +explanation for the test run parameters. + +### Manual run of IPC3 testbench + +The testbench build is by default IPC4. The IPC version can be changed by applying next +patch: + +``` +diff --git a/src/arch/host/configs/library_defconfig b/src/arch/host/configs/library_defconfig +index 1b9483ffe..5c944d292 100644 +--- a/src/arch/host/configs/library_defconfig ++++ b/src/arch/host/configs/library_defconfig +@@ -22,8 +22,8 @@ CONFIG_COMP_VOLUME=y + CONFIG_COMP_VOLUME_LINEAR_RAMP=y + CONFIG_COMP_VOLUME_WINDOWS_FADE=y + CONFIG_DEBUG_MEMORY_USAGE_SCAN=n +-CONFIG_IPC_MAJOR_3=n +-CONFIG_IPC_MAJOR_4=y ++CONFIG_IPC_MAJOR_3=y ++CONFIG_IPC_MAJOR_4=n + CONFIG_LIBRARY=y + CONFIG_LIBRARY_STATIC=y + CONFIG_MATH_IIR_DF2T=y +``` + +As an example, process a wav file and listen it. The example +processing component is DC block. The wav file is first converted with +sox to raw 32 bit 48 kHz stereo format, then processed by testbench, +converted back to wav. + +``` +cd $SOF_WORKSPACE/sof +scripts/rebuild-testbench.sh +scripts/build-tools.sh -t +sox --encoding signed-integer /usr/share/sounds/alsa/Front_Left.wav -L -r 48000 -c 2 -b 32 in.raw +tools/testbench/build_testbench/install/bin/sof-testbench3 -r 48000 -R 48000 -c 2 -n 2 -b S32_LE \ + -t tools/build_tools/test/topology/test-playback-ssp5-mclk-0-I2S-dcblock-s32le-s32le-48k-24576k-codec.tplg \ + -i in.raw -o out.raw +sox --encoding signed-integer -L -r 48000 -c 2 -b 32 out.raw out.wav +aplay out.wav +``` + +The testbench binary can be debugged and profiled with native +executable tools like gdb, ddd (GUI for gdb), gprof, and valgrind. + +### Manual profiling of testbench run on xtensa + +The example is with IPC3 build for Intel MTL platform. The similar commands would work with IPC4 +build also, with changed topology for IPC4. This needs access to Cadence Xplorer toolchain with +the core confiration for the platform. + +``` +cd $SOF_WORKSPACE/sof +export XTENSA_TOOLS_ROOT=~/xtensa/XtDevTools +export ZEPHYR_TOOLCHAIN_VARIANT=xt-clang +scripts/rebuild-testbench.sh -p mtl +source tools/testbench/build_xt_testbench/xtrun_env.sh +``` + +Next the testbench is run with xt-run simulator. The example component +is dynamic range processing (DRC). For proling data generate use +option --profile. Note that this is a lot slower than native run. An +1s extract of a pink noise file is used as example. + +``` +sox --encoding signed-integer /usr/share/sounds/alsa/Noise.wav -L -r 48000 -c 2 -b 32 in.raw trim 0.0 1.0 +$XTENSA_PATH/xt-run --profile=profile.out tools/testbench/build_xt_testbench/testbench \ + -r 48000 -R 48000 -c 2 -n 2 -b S32_LE \ + -t tools/build_tools/test/topology/test-playback-ssp5-mclk-0-I2S-drc-s32le-s32le-48k-24576k-codec.tplg \ + -i in.raw -o out.raw 2> trace.txt +``` + +Then convert the profiler data to readable format and check it. + +``` +$XTENSA_PATH/xt-gprof tools/testbench/build_xt_testbench/testbench profile.out > example_profile.txt +less example_profile.txt +``` diff --git a/tools/testbench/alloc.c b/tools/testbench/alloc.c deleted file mode 100644 index 7d4fdab1fd03..000000000000 --- a/tools/testbench/alloc.c +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -#include <stdlib.h> -#include <stdint.h> -#include <stdio.h> -#include <malloc.h> -#include <sof/lib/alloc.h> -#include "testbench/common_test.h" - -/* testbench mem alloc definition */ - -void *_malloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - return malloc(bytes); -} - -void *_zalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - return calloc(bytes, 1); -} - -void rfree(void *ptr) -{ - free(ptr); -} - -void *_balloc(uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment) -{ - return malloc(bytes); -} - -void *_realloc(void *ptr, enum mem_zone zone, uint32_t flags, uint32_t caps, - size_t bytes) -{ - return realloc(ptr, bytes); -} - -void *_brealloc(void *ptr, uint32_t flags, uint32_t caps, size_t bytes, - uint32_t alignment) -{ - return realloc(ptr, bytes); -} - -void heap_trace(struct mm_heap *heap, int size) -{ - malloc_info(0, stdout); -} - -void heap_trace_all(int force) -{ - heap_trace(NULL, 0); -} diff --git a/tools/testbench/common_test.c b/tools/testbench/common_test.c deleted file mode 100644 index a6714d356712..000000000000 --- a/tools/testbench/common_test.c +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. - -#include <stdint.h> -#include <stddef.h> -#include <time.h> -#include <stdio.h> -#include <stdlib.h> -#include <sof/string.h> -#include <math.h> -#include <sof/sof.h> -#include <sof/schedule/task.h> -#include <sof/lib/alloc.h> -#include <sof/lib/notifier.h> -#include <sof/drivers/ipc.h> -#include <sof/lib/dai.h> -#include <sof/lib/dma.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/schedule/schedule.h> -#include <sof/lib/wait.h> -#include <sof/audio/pipeline.h> -#include "testbench/common_test.h" -#include <tplg_parser/topology.h> - -/* testbench helper functions for pipeline setup and trigger */ - -int tb_pipeline_setup(struct sof *sof) -{ - /* init components */ - sys_comp_init(sof); - - init_system_notify(sof); - - /* init IPC */ - if (ipc_init(sof) < 0) { - fprintf(stderr, "error: IPC init\n"); - return -EINVAL; - } - - /* init scheduler */ - if (scheduler_init_edf() < 0) { - fprintf(stderr, "error: edf scheduler init\n"); - return -EINVAL; - } - - debug_print("ipc and scheduler initialized\n"); - - return 0; -} - -/* set up pcm params, prepare and trigger pipeline */ -int tb_pipeline_start(struct ipc *ipc, struct sof_ipc_pipe_new *ipc_pipe, - struct testbench_prm *tp) -{ - struct ipc_comp_dev *pcm_dev; - struct pipeline *p; - struct comp_dev *cd; - int ret; - - /* set up pipeline params */ - ret = tb_pipeline_params(ipc, ipc_pipe, tp); - if (ret < 0) { - fprintf(stderr, "error: pipeline params\n"); - return -EINVAL; - } - - /* Get IPC component device for pipeline */ - pcm_dev = ipc_get_comp_by_id(ipc, ipc_pipe->sched_id); - if (!pcm_dev) { - fprintf(stderr, "error: ipc get comp\n"); - return -EINVAL; - } - - /* Point to pipeline */ - cd = pcm_dev->cd; - p = pcm_dev->cd->pipeline; - - /* Component prepare */ - ret = pipeline_prepare(p, cd); - - /* Start the pipeline */ - ret = pipeline_trigger(p, cd, COMP_TRIGGER_START); - if (ret < 0) - printf("Warning: Failed start pipeline command.\n"); - - return ret; -} - -/* pipeline pcm params */ -int tb_pipeline_params(struct ipc *ipc, struct sof_ipc_pipe_new *ipc_pipe, - struct testbench_prm *tp) -{ - struct ipc_comp_dev *pcm_dev; - struct pipeline *p; - struct comp_dev *cd; - struct sof_ipc_pcm_params params; - char message[DEBUG_MSG_LEN]; - int fs_period; - int period = ipc_pipe->period; - int ret = 0; - - /* Compute period from sample rates */ - fs_period = (int)(0.9999 + tp->fs_in * period / 1e6); - sprintf(message, "period sample count %d\n", fs_period); - debug_print(message); - - /* set pcm params */ - params.comp_id = ipc_pipe->comp_id; - params.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; - params.params.frame_fmt = tp->frame_fmt; - params.params.direction = SOF_IPC_STREAM_PLAYBACK; - params.params.rate = tp->fs_in; - params.params.channels = tp->channels; - switch (params.params.frame_fmt) { - case(SOF_IPC_FRAME_S16_LE): - params.params.sample_container_bytes = 2; - params.params.sample_valid_bytes = 2; - params.params.host_period_bytes = fs_period * tp->channels * - params.params.sample_container_bytes; - break; - case(SOF_IPC_FRAME_S24_4LE): - params.params.sample_container_bytes = 4; - params.params.sample_valid_bytes = 3; - params.params.host_period_bytes = fs_period * tp->channels * - params.params.sample_container_bytes; - break; - case(SOF_IPC_FRAME_S32_LE): - params.params.sample_container_bytes = 4; - params.params.sample_valid_bytes = 4; - params.params.host_period_bytes = fs_period * tp->channels * - params.params.sample_container_bytes; - break; - default: - fprintf(stderr, "error: invalid frame format\n"); - return -EINVAL; - } - - /* get scheduling component device for pipeline*/ - pcm_dev = ipc_get_comp_by_id(ipc, ipc_pipe->sched_id); - if (!pcm_dev) { - fprintf(stderr, "error: ipc get comp\n"); - return -EINVAL; - } - - /* point to pipeline */ - cd = pcm_dev->cd; - p = pcm_dev->cd->pipeline; - if (!p) { - fprintf(stderr, "error: pipeline NULL\n"); - return -EINVAL; - } - - /* pipeline params */ - ret = pipeline_params(p, cd, ¶ms); - if (ret < 0) - fprintf(stderr, "error: pipeline_params\n"); - - return ret; -} - -/* getindex of shared library from table */ -int get_index_by_name(char *comp_type, struct shared_lib_table *lib_table) -{ - int i; - - for (i = 0; i < NUM_WIDGETS_SUPPORTED; i++) { - if (!strcmp(comp_type, lib_table[i].comp_name)) - return i; - } - - return -EINVAL; -} - -/* getindex of shared library from table by widget type*/ -int get_index_by_type(uint32_t comp_type, struct shared_lib_table *lib_table) -{ - int i; - - for (i = 0; i < NUM_WIDGETS_SUPPORTED; i++) { - if (comp_type == lib_table[i].widget_type) - return i; - } - - return -EINVAL; -} - -/* The following definitions are to satisfy libsof linker errors */ - -struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) -{ - return NULL; -} - -void dai_put(struct dai *dai) -{ -} - -struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags) -{ - return NULL; -} - -void dma_put(struct dma *dma) -{ -} - -int dma_sg_alloc(struct dma_sg_elem_array *elem_array, - enum mem_zone zone, - uint32_t direction, - uint32_t buffer_count, uint32_t buffer_bytes, - uintptr_t dma_buffer_addr, uintptr_t external_addr) -{ - return 0; -} - -void dma_sg_free(struct dma_sg_elem_array *elem_array) -{ -} - -void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes) -{ -} diff --git a/tools/testbench/edf_schedule.c b/tools/testbench/edf_schedule.c deleted file mode 100644 index 356ddd78fcbd..000000000000 --- a/tools/testbench/edf_schedule.c +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/schedule/task.h> -#include <stdint.h> -#include <sof/schedule/edf_schedule.h> -#include <sof/lib/wait.h> -#include <stdlib.h> - - /* scheduler testbench definition */ - -struct edf_schedule_data { - struct list_item list; /* list of tasks in priority queue */ - uint32_t clock; -}; - -struct scheduler_ops schedule_edf_ops; - -static struct edf_schedule_data *sch; - -static void schedule_edf_task_complete(struct task *task) -{ - list_item_del(&task->list); - task->state = SOF_TASK_STATE_COMPLETED; -} - -/* schedule task */ -static void schedule_edf_task(void *data, struct task *task, uint64_t start, - uint64_t period) -{ - struct edf_schedule_data *sch = data; - (void)period; - list_item_prepend(&task->list, &sch->list); - task->state = SOF_TASK_STATE_QUEUED; - - if (task->ops.run) - task->ops.run(task->data); - - schedule_edf_task_complete(task); -} - -int schedule_task_init_edf(struct task *task, uint32_t uid, - const struct task_ops *ops, void *data, - uint16_t core, uint32_t flags) -{ - struct edf_task_pdata *edf_pdata; - int ret = 0; - - ret = schedule_task_init(task, uid, SOF_SCHEDULE_EDF, 0, ops->run, - data, core, flags); - if (ret < 0) - return ret; - - edf_pdata = malloc(sizeof(*edf_pdata)); - edf_sch_set_pdata(task, edf_pdata); - - task->ops.complete = ops->complete; - - return 0; -} - -/* initialize scheduler */ -int scheduler_init_edf(void) -{ - trace_edf_sch("edf_scheduler_init()"); - sch = malloc(sizeof(*sch)); - list_init(&sch->list); - - scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, sch); - - return 0; -} - -static void edf_scheduler_free(void *data) -{ - free(data); -} - -/* The following definitions are to satisfy libsof linker errors */ -static void schedule_edf(void *data) -{ -} - -static void schedule_edf_task_cancel(void *data, struct task *task) -{ - if (task->state == SOF_TASK_STATE_QUEUED) { - /* delete task */ - task->state = SOF_TASK_STATE_CANCEL; - list_item_del(&task->list); - } -} - -static void schedule_edf_task_free(void *data, struct task *task) -{ - task->state = SOF_TASK_STATE_FREE; - task->ops.run = NULL; - task->data = NULL; - - free(edf_sch_get_pdata(task)); - edf_sch_set_pdata(task, NULL); -} - -struct scheduler_ops schedule_edf_ops = { - .schedule_task = schedule_edf_task, - .schedule_task_running = NULL, - .schedule_task_complete = NULL, - .reschedule_task = NULL, - .schedule_task_cancel = schedule_edf_task_cancel, - .schedule_task_free = schedule_edf_task_free, - .scheduler_free = edf_scheduler_free, - .scheduler_run = schedule_edf -}; diff --git a/tools/testbench/file.c b/tools/testbench/file.c index 96ce471c37ce..18fb96481564 100644 --- a/tools/testbench/file.c +++ b/tools/testbench/file.c @@ -1,398 +1,515 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2024 Intel Corporation. All rights reserved. /* file component for reading/writing pcm samples to/from a file */ -#include <stdio.h> -#include <stdint.h> -#include <stddef.h> -#include <errno.h> -#include <inttypes.h> -#include <sof/sof.h> -#include <sof/list.h> -#include <sof/audio/stream.h> -#include <sof/lib/clk.h> -#include <sof/drivers/ipc.h> +#include <sof/audio/module_adapter/module/generic.h> #include <sof/audio/component.h> #include <sof/audio/format.h> +#include <sof/audio/ipc-config.h> #include <sof/audio/pipeline.h> +#include <sof/audio/stream.h> +#include <sof/ipc/driver.h> #include <ipc/stream.h> -#include "testbench/common_test.h" +#include <rtos/init.h> +#include <rtos/clk.h> +#include <rtos/sof.h> +#include <sof/list.h> +#include <errno.h> +#include <inttypes.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include "testbench/utils.h" #include "testbench/file.h" +#include "testbench/file_ipc4.h" +#include "../../src/audio/copier/copier.h" + +SOF_DEFINE_REG_UUID(file); +DECLARE_TR_CTX(file_tr, SOF_UUID(file_uuid), LOG_LEVEL_INFO); +LOG_MODULE_REGISTER(file, CONFIG_SOF_LOG_LEVEL); -static const struct comp_driver comp_file_dai; -static const struct comp_driver comp_file_host; +/* + * Helpers for s24_4le data. To avoid an overflown 24 bit to be taken as valid 32 bit + * sample mask in file read the 8 most signing bits to zeros. In file write similarly + * shift the 24 bit word to MSB and possibly overflow it, then shift it back to LSB + * side to create sign extension. + */ + +static void mask_sink_s24(const struct audio_stream *sink, int samples) +{ + int32_t *snk = (int32_t *)sink->w_ptr; + size_t bytes = samples * sizeof(int32_t); + size_t bytes_snk; + int samples_avail; + int i; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + samples_avail = FILE_BYTES_TO_S32_SAMPLES(MIN(bytes, bytes_snk)); + for (i = 0; i < samples_avail; i++) + *snk++ &= 0x00ffffff; + + bytes -= samples * sizeof(int32_t); + snk = audio_stream_wrap(sink, snk); + } +} + +static void sign_extend_source_s24(const struct audio_stream *source, int samples) +{ + int32_t tmp; + int32_t *src = (int32_t *)source->r_ptr; + size_t bytes = samples * sizeof(int32_t); + size_t bytes_src; + int samples_avail; + int i; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + samples_avail = FILE_BYTES_TO_S32_SAMPLES(MIN(bytes, bytes_src)); + for (i = 0; i < samples_avail; i++) { + tmp = *src << 8; + *src++ = tmp >> 8; + } + + bytes -= samples * sizeof(int32_t); + src = audio_stream_wrap(source, src); + } +} -static inline void buffer_check_wrap_32(int32_t **ptr, int32_t *end, - size_t size) +/* + * Read 32-bit samples from binary file + */ +static int read_binary_s32(struct file_comp_data *cd, const struct audio_stream *sink, int samples) { - if (*ptr >= end) - *ptr = (int32_t *)((size_t)*ptr - size); + int32_t *snk = (int32_t *)sink->w_ptr; + size_t samples_avail; + size_t bytes_snk; + size_t bytes = samples * sizeof(int32_t); + int ret; + int samples_copied = 0; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + samples_avail = FILE_BYTES_TO_S32_SAMPLES(MIN(bytes, bytes_snk)); + ret = fread(snk, sizeof(int32_t), samples_avail, cd->fs.rfh); + if (!ret) { + cd->fs.reached_eof = 1; + return samples_copied; + } + + samples_copied += ret; + bytes -= ret * sizeof(int32_t); + snk = audio_stream_wrap(sink, snk + ret); + } + + return samples_copied; } -static inline void buffer_check_wrap_16(int16_t **ptr, int16_t *end, - size_t size) +/* + * Write 32-bit samples to binary file + */ +static int write_binary_s32(struct file_comp_data *cd, const struct audio_stream *source, + int samples) { - if (*ptr >= end) - *ptr = (int16_t *)((size_t)*ptr - size); + int32_t *src = (int32_t *)source->r_ptr; + size_t samples_avail; + size_t bytes_src; + size_t bytes = samples * sizeof(int32_t); + int ret; + int samples_copied = 0; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + samples_avail = FILE_BYTES_TO_S32_SAMPLES(MIN(bytes, bytes_src)); + ret = fwrite(src, sizeof(int32_t), samples_avail, cd->fs.wfh); + if (ret == 0) { + cd->fs.write_failed = true; + return samples_copied; + } + samples_copied += ret; + bytes -= ret * sizeof(int32_t); + src = audio_stream_wrap(source, src + ret); + } + + return samples_copied; } /* - * Read 32-bit samples from file - * currently only supports txt files + * Read 32-bit samples from text file */ -static int read_samples_32(struct comp_dev *dev, - const struct audio_stream *sink, - int n, int fmt, int nch) +static int read_text_s32(struct file_comp_data *cd, const struct audio_stream *sink, int samples) { - struct file_comp_data *cd = comp_get_drvdata(dev); - int32_t *dest = (int32_t *)sink->w_ptr; - int32_t sample; - int n_wrap; - int n_min; + int32_t *snk = (int32_t *)sink->w_ptr; + size_t bytes = samples * sizeof(int32_t); + size_t bytes_snk; + int ret; int i; - int n_samples = 0; - int ret = 0; + int samples_copied = 0; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + samples = FILE_BYTES_TO_S32_SAMPLES(MIN(bytes, bytes_snk)); + for (i = 0; i < samples; i++) { + ret = fscanf(cd->fs.rfh, "%d", snk++); + if (ret == EOF) { + cd->fs.reached_eof = 1; + return samples_copied; + } + samples_copied++; + bytes -= sizeof(int32_t); + } + snk = audio_stream_wrap(sink, snk); + } + + return samples_copied; +} - while (n > 0) { - n_wrap = (int32_t *)sink->end_addr - dest; - - /* check for buffer wrap and copy to the end of the buffer */ - n_min = (n < n_wrap) ? n : n_wrap; - while (n_min > 0) { - n -= nch; - n_min -= nch; - - /* copy sample per channel */ - for (i = 0; i < nch; i++) { - /* read sample from file */ - switch (cd->fs.f_format) { - /* text input file */ - case FILE_TEXT: - if (fmt == SOF_IPC_FRAME_S32_LE) - ret = fscanf(cd->fs.rfh, "%d", - dest); - - /* mask bits if 24-bit samples */ - if (fmt == SOF_IPC_FRAME_S24_4LE) { - ret = fscanf(cd->fs.rfh, "%d", - &sample); - *dest = sample & 0x00ffffff; - } - /* quit if eof is reached */ - if (ret == EOF) { - cd->fs.reached_eof = 1; - goto quit; - } - break; - - /* raw input file */ - default: - if (fmt == SOF_IPC_FRAME_S32_LE) - ret = fread(dest, - sizeof(int32_t), - 1, cd->fs.rfh); - - /* mask bits if 24-bit samples */ - if (fmt == SOF_IPC_FRAME_S24_4LE) { - ret = fread(&sample, - sizeof(int32_t), - 1, cd->fs.rfh); - *dest = sample & 0x00ffffff; - } - /* quit if eof is reached */ - if (ret != 1) { - cd->fs.reached_eof = 1; - goto quit; - } - break; - } - dest++; - n_samples++; +/* + * Write 32-bit samples to text file + */ +static int write_text_s32(struct file_comp_data *cd, const struct audio_stream *source, int samples) +{ + int32_t *src = (int32_t *)source->r_ptr; + size_t bytes = samples * sizeof(int32_t); + size_t bytes_src; + int ret; + int i; + int samples_copied = 0; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + samples = FILE_BYTES_TO_S32_SAMPLES(MIN(bytes, bytes_src)); + for (i = 0; i < samples; i++) { + ret = fprintf(cd->fs.wfh, "%d\n", *src++); + if (ret < 1) { + cd->fs.write_failed = true; + return samples_copied; } + samples_copied++; + bytes -= sizeof(int32_t); } - /* check for buffer wrap and update pointer */ - buffer_check_wrap_32(&dest, sink->end_addr, - sink->size); + src = audio_stream_wrap(source, src); + } + + return samples_copied; +} + +static int read_samples_s32(struct file_comp_data *cd, const struct audio_stream *sink, + int samples, int fmt) +{ + int n_samples = 0; + + switch (cd->fs.f_format) { + case FILE_RAW: + /* raw input file */ + n_samples = read_binary_s32(cd, sink, samples); + break; + case FILE_TEXT: + /* text input file */ + n_samples = read_text_s32(cd, sink, samples); + break; + default: + return -EINVAL; } -quit: + + if (fmt == SOF_IPC_FRAME_S24_4LE) + mask_sink_s24(sink, samples); + return n_samples; } /* - * Read 16-bit samples from file - * currently only supports txt files + * Write 32-bit samples to file */ -static int read_samples_16(struct comp_dev *dev, - const struct audio_stream *sink, - int n, int nch) +static int write_samples_s32(struct file_comp_data *cd, struct audio_stream *source, int samples, + int fmt) { - struct file_comp_data *cd = comp_get_drvdata(dev); - int16_t *dest = (int16_t *)sink->w_ptr; - int i, n_wrap, n_min, ret; - int n_samples = 0; + int samples_written; - /* copy samples */ - while (n > 0) { - n_wrap = (int16_t *)sink->end_addr - dest; - - /* check for buffer wrap and copy to the end of the buffer */ - n_min = (n < n_wrap) ? n : n_wrap; - while (n_min > 0) { - n -= nch; - n_min -= nch; - - /* copy sample per channel */ - for (i = 0; i < nch; i++) { - switch (cd->fs.f_format) { - /* text input file */ - case FILE_TEXT: - ret = fscanf(cd->fs.rfh, "%hd", dest); - if (ret == EOF) { - cd->fs.reached_eof = 1; - goto quit; - } - break; - - /* rw pcm input file */ - default: - ret = fread(dest, sizeof(int16_t), 1, - cd->fs.rfh); - if (ret != 1) { - cd->fs.reached_eof = 1; - goto quit; - } - break; - } - - dest++; - n_samples++; - } + if (fmt == SOF_IPC_FRAME_S24_4LE) + sign_extend_source_s24(source, samples); + + switch (cd->fs.f_format) { + case FILE_RAW: + /* raw input file */ + samples_written = write_binary_s32(cd, source, samples); + break; + case FILE_TEXT: + /* text input file */ + samples_written = write_text_s32(cd, source, samples); + break; + default: + return -EINVAL; + } + + return samples_written; +} + +/* + * Read 16-bit samples from binary file + */ +static int read_binary_s16(struct file_comp_data *cd, const struct audio_stream *sink, int samples) +{ + int16_t *snk = (int16_t *)sink->w_ptr; + size_t samples_avail; + size_t bytes_snk; + size_t bytes = samples * sizeof(int16_t); + int ret; + int samples_copied = 0; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + samples_avail = FILE_BYTES_TO_S16_SAMPLES(MIN(bytes, bytes_snk)); + ret = fread(snk, sizeof(int16_t), samples_avail, cd->fs.rfh); + if (!ret) { + cd->fs.reached_eof = 1; + return samples_copied; } - /* check for buffer wrap and update pointer */ - buffer_check_wrap_16(&dest, sink->end_addr, - sink->size); + + samples_copied += ret; + bytes -= ret * sizeof(int16_t); + snk = audio_stream_wrap(sink, snk + ret); } -quit: - return n_samples; + return samples_copied; } /* - * Write 16-bit samples from file - * currently only supports txt files + * Write 16-bit samples to binary file */ -static int write_samples_16(struct comp_dev *dev, struct audio_stream *source, - int n, int nch) +static int write_binary_s16(struct file_comp_data *cd, const struct audio_stream *source, + int samples) { - struct file_comp_data *cd = comp_get_drvdata(dev); int16_t *src = (int16_t *)source->r_ptr; - int i, n_wrap, n_min, ret; - int n_samples = 0; + size_t samples_avail; + size_t bytes_src; + size_t bytes = samples * sizeof(int16_t); + int ret; + int samples_copied = 0; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + samples_avail = FILE_BYTES_TO_S16_SAMPLES(MIN(bytes, bytes_src)); + ret = fwrite(src, sizeof(int16_t), samples_avail, cd->fs.wfh); + if (!ret) { + cd->fs.write_failed = true; + return samples_copied; + } + + samples_copied += ret; + bytes -= ret * sizeof(int16_t); + src = audio_stream_wrap(source, src + ret); + } + + return samples_copied; +} - /* copy samples */ - while (n > 0) { - n_wrap = (int16_t *)source->end_addr - src; - - /* check for buffer wrap and copy to the end of the buffer */ - n_min = (n < n_wrap) ? n : n_wrap; - while (n_min > 0) { - n -= nch; - n_min -= nch; - - /* copy sample per channel */ - for (i = 0; i < nch; i++) { - switch (cd->fs.f_format) { - /* text output file */ - case FILE_TEXT: - ret = fprintf(cd->fs.wfh, - "%d\n", *src); - if (ret < 0) - goto quit; - break; - - /* raw pcm output file */ - default: - ret = fwrite(src, - sizeof(int16_t), - 1, cd->fs.wfh); - if (ret != 1) - goto quit; - break; - } - - src++; - n_samples++; +/* + * Read 16-bit samples from text file + */ +static int read_text_s16(struct file_comp_data *cd, const struct audio_stream *sink, int samples) +{ + int16_t *snk = (int16_t *)sink->w_ptr; + size_t bytes = samples * sizeof(int16_t); + size_t bytes_snk; + int ret; + int i; + int samples_copied = 0; + + while (bytes) { + bytes_snk = audio_stream_bytes_without_wrap(sink, snk); + samples = FILE_BYTES_TO_S16_SAMPLES(MIN(bytes, bytes_snk)); + for (i = 0; i < samples; i++) { + ret = fscanf(cd->fs.rfh, "%hd", snk++); + if (ret == EOF) { + cd->fs.reached_eof = true; + return samples_copied; } + samples_copied++; + bytes -= sizeof(int16_t); } - /* check for buffer wrap and update pointer */ - buffer_check_wrap_16(&src, source->end_addr, - source->size); + snk = audio_stream_wrap(sink, snk); } -quit: - return n_samples; + + return samples_copied; } /* - * Write 32-bit samples from file - * currently only supports txt files + * Write 16-bit samples to text file */ -static int write_samples_32(struct comp_dev *dev, struct audio_stream *source, - int n, int fmt, int nch) +static int write_text_s16(struct file_comp_data *cd, const struct audio_stream *source, int samples) { - struct file_comp_data *cd = comp_get_drvdata(dev); - int32_t *src = (int32_t *)source->r_ptr; - int i, n_wrap, n_min, ret; - int n_samples = 0; - int32_t sample; - - /* copy samples */ - while (n > 0) { - n_wrap = (int32_t *)source->end_addr - src; - - /* check for buffer wrap and copy to the end of the buffer */ - n_min = (n < n_wrap) ? n : n_wrap; - while (n_min > 0) { - n -= nch; - n_min -= nch; - - /* copy sample per channel */ - for (i = 0; i < nch; i++) { - switch (cd->fs.f_format) { - /* text output file */ - case FILE_TEXT: - if (fmt == SOF_IPC_FRAME_S32_LE) - ret = fprintf(cd->fs.wfh, - "%d\n", *src); - if (fmt == SOF_IPC_FRAME_S24_4LE) { - sample = *src << 8; - ret = fprintf(cd->fs.wfh, - "%d\n", - sample >> 8); - } - if (ret < 0) - goto quit; - break; - - /* raw pcm output file */ - default: - if (fmt == SOF_IPC_FRAME_S32_LE) - ret = fwrite(src, - sizeof(int32_t), - 1, cd->fs.wfh); - if (fmt == SOF_IPC_FRAME_S24_4LE) { - sample = *src << 8; - sample >>= 8; - ret = fwrite(&sample, - sizeof(int32_t), - 1, cd->fs.wfh); - } - if (ret != 1) - goto quit; - break; - } - - /* increment read pointer */ - src++; - - /* increment number of samples written */ - n_samples++; + int16_t *src = (int16_t *)source->r_ptr; + size_t bytes = samples * sizeof(int16_t); + size_t bytes_src; + int ret; + int i; + int samples_copied = 0; + + while (bytes) { + bytes_src = audio_stream_bytes_without_wrap(source, src); + samples = FILE_BYTES_TO_S16_SAMPLES(MIN(bytes, bytes_src)); + for (i = 0; i < samples; i++) { + ret = fprintf(cd->fs.wfh, "%hd\n", *src++); + if (ret < 1) { + cd->fs.write_failed = true; + return samples_copied; } + samples_copied++; + bytes -= sizeof(int16_t); } - /* check for buffer wrap and update pointer */ - buffer_check_wrap_32(&src, source->end_addr, - source->size); + src = audio_stream_wrap(source, src); } -quit: + + return samples_copied; +} + +static int read_samples_s16(struct file_comp_data *cd, const struct audio_stream *sink, int samples) +{ + int n_samples = 0; + + switch (cd->fs.f_format) { + case FILE_RAW: + /* raw input file */ + n_samples = read_binary_s16(cd, sink, samples); + break; + case FILE_TEXT: + /* text input file */ + n_samples = read_text_s16(cd, sink, samples); + break; + default: + return -EINVAL; + } + return n_samples; } +/* + * Write 16-bit samples to file + */ +static int write_samples_s16(struct file_comp_data *cd, struct audio_stream *source, int samples) +{ + int samples_written; + + switch (cd->fs.f_format) { + case FILE_RAW: + /* raw input file */ + samples_written = write_binary_s16(cd, source, samples); + break; + case FILE_TEXT: + /* text input file */ + samples_written = write_text_s16(cd, source, samples); + break; + default: + return -EINVAL; + } + + return samples_written; +} + +/* Default file copy function, just return error if called */ +static int file_default(struct file_comp_data *cd, struct audio_stream *sink, + struct audio_stream *source, uint32_t frames) +{ + return -EINVAL; +} + /* function for processing 32-bit samples */ -static int file_s32_default(struct comp_dev *dev, struct audio_stream *sink, - struct audio_stream *source, uint32_t frames) +static int file_s32(struct file_comp_data *cd, struct audio_stream *sink, + struct audio_stream *source, uint32_t frames) { - struct file_comp_data *cd = comp_get_drvdata(dev); int nch; int n_samples = 0; switch (cd->fs.mode) { case FILE_READ: /* read samples */ - nch = sink->channels; - n_samples = read_samples_32(dev, sink, frames * nch, - SOF_IPC_FRAME_S32_LE, nch); + nch = audio_stream_get_channels(sink); + n_samples = read_samples_s32(cd, sink, frames * nch, SOF_IPC_FRAME_S32_LE); break; case FILE_WRITE: /* write samples */ - nch = source->channels; - n_samples = write_samples_32(dev, source, frames * nch, - SOF_IPC_FRAME_S32_LE, nch); + nch = audio_stream_get_channels(source); + n_samples = write_samples_s32(cd, source, frames * nch, SOF_IPC_FRAME_S32_LE); break; default: /* TODO: duplex mode */ - break; + fprintf(stderr, "Error: Unknown file mode %d\n", cd->fs.mode); + return -EINVAL; } + /* update sample counter and check if we have a sample limit */ cd->fs.n += n_samples; + if (cd->max_samples && cd->fs.n >= cd->max_samples) + cd->fs.reached_eof = 1; + return n_samples; } /* function for processing 16-bit samples */ -static int file_s16(struct comp_dev *dev, struct audio_stream *sink, +static int file_s16(struct file_comp_data *cd, struct audio_stream *sink, struct audio_stream *source, uint32_t frames) { - struct file_comp_data *cd = comp_get_drvdata(dev); int nch; - int n_samples = 0; + int n_samples; switch (cd->fs.mode) { case FILE_READ: /* read samples */ - nch = sink->channels; - n_samples = read_samples_16(dev, sink, frames * nch, nch); + nch = audio_stream_get_channels(sink); + n_samples = read_samples_s16(cd, sink, frames * nch); break; case FILE_WRITE: /* write samples */ - nch = source->channels; - n_samples = write_samples_16(dev, source, frames * nch, nch); + nch = audio_stream_get_channels(source); + n_samples = write_samples_s16(cd, source, frames * nch); break; default: /* TODO: duplex mode */ - break; + fprintf(stderr, "Error: Unknown file mode %d\n", cd->fs.mode); + return -EINVAL; } + /* update sample counter and check if we have a sample limit */ cd->fs.n += n_samples; + if (cd->max_samples && cd->fs.n >= cd->max_samples) + cd->fs.reached_eof = 1; + return n_samples; } /* function for processing 24-bit samples */ -static int file_s24(struct comp_dev *dev, struct audio_stream *sink, +static int file_s24(struct file_comp_data *cd, struct audio_stream *sink, struct audio_stream *source, uint32_t frames) { - struct file_comp_data *cd = comp_get_drvdata(dev); int nch; int n_samples = 0; switch (cd->fs.mode) { case FILE_READ: /* read samples */ - nch = sink->channels; - n_samples = read_samples_32(dev, sink, frames * nch, - SOF_IPC_FRAME_S24_4LE, nch); + nch = audio_stream_get_channels(sink); + n_samples = read_samples_s32(cd, sink, frames * nch, SOF_IPC_FRAME_S24_4LE); break; case FILE_WRITE: /* write samples */ - nch = source->channels; - n_samples = write_samples_32(dev, source, frames * nch, - SOF_IPC_FRAME_S24_4LE, nch); + nch = audio_stream_get_channels(source); + n_samples = write_samples_s32(cd, source, frames * nch, SOF_IPC_FRAME_S24_4LE); break; default: /* TODO: duplex mode */ - break; + fprintf(stderr, "Error: Unknown file mode %d\n", cd->fs.mode); + return -EINVAL; } + /* update sample counter and check if we have a sample limit */ cd->fs.n += n_samples; + if (cd->max_samples && cd->fs.n >= cd->max_samples) + cd->fs.reached_eof = 1; + return n_samples; } @@ -400,404 +517,371 @@ static enum file_format get_file_format(char *filename) { char *ext = strrchr(filename, '.'); + if (!ext) + return FILE_RAW; + if (!strcmp(ext, ".txt")) return FILE_TEXT; return FILE_RAW; } -static struct comp_dev *file_new(const struct comp_driver *drv, - struct sof_ipc_comp *comp) +#if CONFIG_IPC_MAJOR_4 +/* Minimal support for IPC4 pipeline_comp_trigger()'s dai_get_init_delay_ms() */ +static int file_init_set_dai_data(struct processing_module *mod) +{ + struct dai_data *dd; + struct copier_data *ccd = module_get_private_data(mod); + + dd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*dd)); + if (!dd) + return -ENOMEM; + + /* Member dd->dai remains NULL. It's sufficient for dai_get_init_delay_ms(). + * In such case the functions returns zero delay. Testbench currently has + * no use for the feature. + */ + ccd->dd[0] = dd; + return 0; +} + +static void file_free_dai_data(struct processing_module *mod) +{ + struct copier_data *ccd = module_get_private_data(mod); + + free(ccd->dd[0]); +} +#else +/* Minimal support for IPC3 pipeline_comp_trigger()'s dai_get_init_delay_ms() */ +static int file_init_set_dai_data(struct processing_module *mod) +{ + struct dai_data *dd; + struct comp_dev *dev = mod->dev; + + dd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*dd)); + if (!dd) + return -ENOMEM; + + /* Member dd->dai remains NULL. It's sufficient for dai_get_init_delay_ms(). + * In such case the functions returns zero delay. Testbench currently has + * no use for the feature. + */ + dev->priv_data = dd; + return 0; +} + +static void file_free_dai_data(struct processing_module *mod) +{ + struct dai_data *dd; + struct comp_dev *dev = mod->dev; + + dd = comp_get_drvdata(dev); + free(dd); +} +#endif + +static int file_init(struct processing_module *mod) { - struct comp_dev *dev; - struct sof_ipc_comp_file *file; - struct sof_ipc_comp_file *ipc_file = - (struct sof_ipc_comp_file *)comp; + struct comp_dev *dev = mod->dev; + struct module_data *mod_data = &mod->priv; + struct copier_data *ccd; struct file_comp_data *cd; + int ret; - debug_print("file_new()\n"); +#if CONFIG_IPC_MAJOR_4 + const struct ipc4_file_module_cfg *module_cfg = + (const struct ipc4_file_module_cfg *)mod_data->cfg.init_data; - if (IPC_IS_SIZE_INVALID(ipc_file->config)) { - fprintf(stderr, "error: file_new() Invalid IPC size.\n"); - return NULL; - } + const struct ipc4_file_config *ipc_file = &module_cfg->config; +#else + const struct ipc_comp_file *ipc_file = + (const struct ipc_comp_file *)mod_data->cfg.init_data; +#endif + + tb_debug_print("file_init()\n"); - dev = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, - COMP_SIZE(struct sof_ipc_comp_file)); - if (!dev) - return NULL; - dev->drv = drv; + ccd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*ccd)); + if (!ccd) + return -ENOMEM; - file = COMP_GET_IPC(dev, sof_ipc_comp_file); - assert(!memcpy_s(file, sizeof(*file), ipc_file, - sizeof(struct sof_ipc_comp_file))); + mod_data->private = ccd; - /* allocate memory for file comp data */ - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); + /* File component data is placed to copier's ipcgtw_data */ + cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); if (!cd) { - free(dev); - return NULL; + free(ccd); + return -ENOMEM; } - comp_set_drvdata(dev, cd); + file_set_comp_data(ccd, cd); /* default function for processing samples */ - cd->file_func = file_s32_default; + cd->file_func = file_default; /* get filename from IPC and open file */ - cd->fs.fn = strdup(ipc_file->fn); + if (ipc_file->fn) { + cd->fs.fn = strdup(ipc_file->fn); + } else { + fprintf(stderr, "error: no filename set\n"); + goto error; + } /* set file format */ cd->fs.f_format = get_file_format(cd->fs.fn); /* set file comp mode */ cd->fs.mode = ipc_file->mode; - - cd->rate = ipc_file->rate; - cd->channels = ipc_file->channels; + cd->fs.rate = ipc_file->rate; + cd->fs.channels = ipc_file->channels; cd->frame_fmt = ipc_file->frame_fmt; + dev->direction = ipc_file->direction; + dev->direction_set = true; /* open file handle(s) depending on mode */ switch (cd->fs.mode) { case FILE_READ: cd->fs.rfh = fopen(cd->fs.fn, "r"); if (!cd->fs.rfh) { - fprintf(stderr, "error: opening file %s\n", cd->fs.fn); - free(cd); - free(dev); - return NULL; + fprintf(stderr, "error: opening file %s for reading - %s\n", + cd->fs.fn, strerror(errno)); + goto error; + } + + /* Change to DAI type is needed to avoid uninitialized hw params in + * pipeline_params, A file host can be left as SOF_COMP_MODULE_ADAPTER + */ + if (dev->direction == SOF_IPC_STREAM_CAPTURE) { + dev->ipc_config.type = SOF_COMP_DAI; + ret = file_init_set_dai_data(mod); + if (ret) { + fprintf(stderr, "error: failed set dai data.\n"); + goto error; + } } break; case FILE_WRITE: - cd->fs.wfh = fopen(cd->fs.fn, "w"); + cd->fs.wfh = fopen(cd->fs.fn, "w+"); if (!cd->fs.wfh) { - fprintf(stderr, "error: opening file %s\n", cd->fs.fn); - free(cd); - free(dev); - return NULL; + fprintf(stderr, "error: opening file %s for writing - %s\n", + cd->fs.fn, strerror(errno)); + goto error; } + + /* Change to DAI type is needed to avoid uninitialized hw params in + * pipeline_params. For capture the file write is the host so set + * SOF_COMP_HOST to skip sink check in module_adapter_prepare(). + */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + dev->ipc_config.type = SOF_COMP_DAI; + ret = file_init_set_dai_data(mod); + if (ret) { + fprintf(stderr, "error: failed set dai data.\n"); + goto error; + } + } else { + dev->ipc_config.type = SOF_COMP_HOST; + } + break; default: /* TODO: duplex mode */ - break; + fprintf(stderr, "Error: Unknown file mode %d\n", cd->fs.mode); + goto error; } - cd->fs.reached_eof = 0; + cd->fs.reached_eof = false; + cd->fs.write_failed = false; + cd->fs.copy_timeout = false; cd->fs.n = 0; + cd->fs.copy_count = 0; + cd->fs.cycles_count = 0; + return 0; - dev->state = COMP_STATE_READY; - - return dev; +error: + free(cd); + free(ccd); + return -EINVAL; } -static void file_free(struct comp_dev *dev) +static int file_free(struct processing_module *mod) { - struct file_comp_data *cd = comp_get_drvdata(dev); + struct copier_data *ccd = module_get_private_data(mod); + struct file_comp_data *cd = get_file_comp_data(ccd); - comp_dbg(dev, "file_free()"); + tb_debug_print("file_free()\n"); if (cd->fs.mode == FILE_READ) fclose(cd->fs.rfh); else fclose(cd->fs.wfh); + file_free_dai_data(mod); free(cd->fs.fn); free(cd); - free(dev); -} - -static int file_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int ret; - - comp_dbg(dev, "file_verify_params()"); - - ret = comp_verify_params(dev, 0, params); - if (ret < 0) { - comp_err(dev, "file_verify_params() error: comp_verify_params() failed."); - return ret; - } - + free(ccd); return 0; } -/** - * \brief Sets file component audio stream parameters. - * \param[in,out] dev Volume base component device. - * \param[in] params Audio (PCM) stream parameters (ignored for this component) - * \return Error code. - * - * All done in prepare() since we need to know source and sink component params. - */ -static int file_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - int err; - - comp_info(dev, "file_params()"); - - err = file_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "file_params(): pcm params verification failed."); - return -EINVAL; - } - - return 0; -} - -static int fr_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) -{ - return -EINVAL; -} - -static int file_trigger(struct comp_dev *dev, int cmd) -{ - comp_info(dev, "file_trigger()"); - return comp_set_state(dev, cmd); -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int file_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = data; - int ret = 0; - - comp_info(dev, "file_cmd()"); - switch (cmd) { - case COMP_CMD_SET_DATA: - ret = fr_cmd(dev, cdata); - break; - default: - break; - } - - return ret; -} - /* * copy and process stream samples * returns the number of bytes copied */ -static int file_copy(struct comp_dev *dev) +static int file_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 comp_dev *dev = mod->dev; + struct file_comp_data *cd = get_file_comp_data(module_get_private_data(mod)); + struct audio_stream *source; + struct audio_stream *sink; struct comp_buffer *buffer; - struct file_comp_data *cd = comp_get_drvdata(dev); - int snk_frames; - int src_frames; - int bytes = cd->sample_container_bytes; + uint32_t frames; + uint64_t cycles0, cycles1; + int samples = 0; int ret = 0; + if (cd->fs.reached_eof) + return -ENODATA; + + /* Note: a SOF_COMP_DAI does not have input_buffers and output buffers set */ + tb_getcycles(&cycles0); switch (cd->fs.mode) { case FILE_READ: - /* file component sink buffer */ - buffer = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - /* test sink has enough free frames */ - snk_frames = buffer->stream.free / - audio_stream_frame_bytes(&buffer->stream); - if (snk_frames > 0 && !cd->fs.reached_eof) { - /* read PCM samples from file */ - ret = cd->file_func(dev, &buffer->stream, NULL, - snk_frames); - - /* update sink buffer pointers */ - if (ret > 0) - comp_update_buffer_produce(buffer, - ret * bytes); - } + /* read PCM samples from file */ + buffer = comp_dev_get_first_data_consumer(dev); + sink = &buffer->stream; + frames = audio_stream_get_free_frames(sink); + frames = MIN(frames, cd->max_frames); + samples = cd->file_func(cd, sink, NULL, frames); + audio_stream_produce(sink, audio_stream_sample_bytes(sink) * samples); break; case FILE_WRITE: - /* file component source buffer */ - buffer = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); - - /* test source has enough free frames */ - src_frames = buffer->stream.avail / - audio_stream_frame_bytes(&buffer->stream); - if (src_frames > 0) { - /* write PCM samples into file */ - ret = cd->file_func(dev, NULL, &buffer->stream, - src_frames); - - /* update source buffer pointers */ - if (ret > 0) - comp_update_buffer_consume(buffer, - ret * bytes); - } + /* write PCM samples into file */ + buffer = comp_dev_get_first_data_producer(dev); + source = &buffer->stream; + frames = audio_stream_get_avail_frames(source); + frames = MIN(frames, cd->max_frames); + samples = cd->file_func(cd, NULL, source, frames); + audio_stream_consume(source, audio_stream_sample_bytes(source) * samples); break; default: /* TODO: duplex mode */ + ret = -EINVAL; break; } + cd->fs.copy_count++; + if (cd->fs.reached_eof || (cd->max_copies && cd->fs.copy_count >= cd->max_copies)) { + cd->fs.reached_eof = true; + tb_debug_print("file_process(): reached EOF\n"); + } + + if (samples) { + cd->copies_timeout_count = 0; + } else { + cd->copies_timeout_count++; + if (cd->copies_timeout_count == FILE_MAX_COPIES_TIMEOUT) { + tb_debug_print("file_process(): copies_timeout reached\n"); + cd->fs.copy_timeout = true; + } + } + + tb_getcycles(&cycles1); + cd->fs.cycles_count += cycles1 - cycles0; return ret; } -static int file_prepare(struct comp_dev *dev) +static int file_prepare(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct sof_ipc_comp_config *config = dev_comp_config(dev); - struct comp_buffer *buffer = NULL; - struct file_comp_data *cd = comp_get_drvdata(dev); struct audio_stream *stream; - int periods; - int ret = 0; - - comp_info(dev, "file_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; - - /* file component source or sink buffer */ - if (cd->fs.mode == FILE_WRITE) { - stream = &list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list)->stream; - } else { - stream = &list_first_item(&dev->bsink_list, struct comp_buffer, - source_list)->stream; - } - - if (stream->frame_fmt == SOF_IPC_FRAME_S16_LE) - cd->sample_container_bytes = 2; - else - cd->sample_container_bytes = 4; + struct comp_buffer *buffer; + struct comp_dev *dev = mod->dev; + struct file_comp_data *cd = get_file_comp_data(module_get_private_data(mod)); - /* calculate period size based on config */ - cd->period_bytes = dev->frames * cd->sample_container_bytes * - stream->channels; + tb_debug_print("file_prepare()\n"); /* file component sink/source buffer period count */ + cd->max_frames = dev->frames; switch (cd->fs.mode) { case FILE_READ: - buffer = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - periods = config->periods_sink; + buffer = comp_dev_get_first_data_consumer(dev); break; case FILE_WRITE: - buffer = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); - periods = config->periods_source; + buffer = comp_dev_get_first_data_producer(dev); break; default: /* TODO: duplex mode */ - break; - } - - if (!buffer) { - fprintf(stderr, "error: no sink/source buffer\n"); + fprintf(stderr, "Error: Unknown file mode %d\n", cd->fs.mode); return -EINVAL; } - /* set downstream buffer size */ - switch (config->frame_fmt) { - case(SOF_IPC_FRAME_S16_LE): - ret = buffer_set_size(buffer, dev->frames * 2 * - periods * buffer->stream.channels); - if (ret < 0) { - fprintf(stderr, "error: file buffer size set\n"); - return ret; - } - buffer_reset_pos(buffer, NULL); - - /* set file function */ + /* set file function */ + stream = &buffer->stream; + switch (audio_stream_get_frm_fmt(stream)) { + case SOF_IPC_FRAME_S16_LE: cd->file_func = file_s16; break; - case(SOF_IPC_FRAME_S24_4LE): - ret = buffer_set_size(buffer, dev->frames * 4 * - periods * buffer->stream.channels); - if (ret < 0) { - fprintf(stderr, "error: file buffer size set\n"); - return ret; - } - buffer_reset_pos(buffer, NULL); - - /* set file function */ + case SOF_IPC_FRAME_S24_4LE: cd->file_func = file_s24; break; - case(SOF_IPC_FRAME_S32_LE): - ret = buffer_set_size(buffer, dev->frames * 4 * - periods * buffer->stream.channels); - if (ret < 0) { - fprintf(stderr, "error: file buffer size set\n"); - return ret; - } - buffer_reset_pos(buffer, NULL); + case SOF_IPC_FRAME_S32_LE: + cd->file_func = file_s32; break; default: + fprintf(stderr, "Warning: Unknown file sample format %d\n", + dev->ipc_config.frame_fmt); return -EINVAL; } - dev->state = COMP_STATE_PREPARE; - - return ret; + return 0; } -static int file_reset(struct comp_dev *dev) +static int file_reset(struct processing_module *mod) { - comp_info(dev, "file_reset()"); - comp_set_state(dev, COMP_TRIGGER_RESET); + struct file_comp_data *cd = module_get_private_data(mod); + + tb_debug_print("file_reset()\n"); + cd->copies_timeout_count = 0; return 0; } +static int file_trigger(struct comp_dev *dev, int cmd) +{ + tb_debug_print("file_trigger()\n"); + return comp_set_state(dev, cmd); +} + static int file_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, int dir) { - struct file_comp_data *cd = comp_get_drvdata(dev); + struct processing_module *mod = comp_mod(dev); + struct file_comp_data *cd = get_file_comp_data(module_get_private_data(mod)); - comp_info(dev, "file_hw_params()"); + tb_debug_print("file_hw_params()\n"); params->direction = dir; - params->rate = cd->rate; - params->channels = cd->channels; + params->rate = cd->fs.rate; + params->channels = cd->fs.channels; params->buffer_fmt = 0; params->frame_fmt = cd->frame_fmt; return 0; } -static const struct comp_driver comp_file_host = { - .type = SOF_COMP_HOST, - .ops = { - .new = file_new, - .free = file_free, - .params = file_params, - .cmd = file_cmd, - .trigger = file_trigger, - .copy = file_copy, - .prepare = file_prepare, - .reset = file_reset, - }, -}; - -static const struct comp_driver comp_file_dai = { - .type = SOF_COMP_DAI, - .ops = { - .new = file_new, - .free = file_free, - .params = file_params, - .cmd = file_cmd, - .trigger = file_trigger, - .copy = file_copy, - .prepare = file_prepare, - .reset = file_reset, - .dai_get_hw_params = file_get_hw_params, - }, +/* Needed for SOF_COMP_DAI */ +static struct module_endpoint_ops file_endpoint_ops = { + .dai_get_hw_params = file_get_hw_params, + .trigger = file_trigger, }; -static struct comp_driver_info comp_file_host_info = { - .drv = &comp_file_host, +static const struct module_interface file_interface = { + .init = file_init, + .prepare = file_prepare, + .process_audio_stream = file_process, + .reset = file_reset, + .free = file_free, + .endpoint_ops = &file_endpoint_ops, }; -static struct comp_driver_info comp_file_dai_info = { - .drv = &comp_file_dai, -}; - -void sys_comp_file_init(void) -{ - comp_register(&comp_file_host_info); - comp_register(&comp_file_dai_info); -} +DECLARE_MODULE_ADAPTER(file_interface, file_uuid, file_tr); +SOF_MODULE_INIT(file, sys_comp_module_file_interface_init); diff --git a/tools/testbench/include/linux/types.h b/tools/testbench/include/linux/types.h new file mode 100644 index 000000000000..31186b5e365e --- /dev/null +++ b/tools/testbench/include/linux/types.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef __TESTBENCH_LINUX_TYPES_H__ +#define __TESTBENCH_LINUX_TYPES_H__ + +#include <stdint.h> + +/* + * This header files allows to include asoc.h for topology parsing to + * non-gcc builds with other C library, e.g. the one that is used by + * xt-xcc compiler. The kernel linux/types.h cannot be used because + * the other definitions there are not compatible with the toolchain. + */ + +/* There are minimum types needed for alsa/sound/uapi/asoc.h */ + +typedef int64_t __le64; +typedef int32_t __le32; +typedef int16_t __le16; +typedef uint8_t __u8; + +#endif /* __TESTBENCH_LINUX_TYPES_H__ */ diff --git a/tools/testbench/include/testbench/common_test.h b/tools/testbench/include/testbench/common_test.h deleted file mode 100644 index 9ac2f435c2e5..000000000000 --- a/tools/testbench/include/testbench/common_test.h +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - */ - -#ifndef _COMMON_TEST_H -#define _COMMON_TEST_H - -#include <stdint.h> -#include <stddef.h> -#include <time.h> -#include <stdio.h> -#include <sof/sof.h> -#include <sof/audio/component_ext.h> -#include <sof/audio/format.h> - -#define DEBUG_MSG_LEN 256 -#define MAX_LIB_NAME_LEN 256 - -/* number of widgets types supported in testbench */ -#define NUM_WIDGETS_SUPPORTED 6 - -struct testbench_prm { - char *tplg_file; /* topology file to use */ - char *input_file; /* input file name */ - char *output_file; /* output file name */ - char *bits_in; /* input bit format */ - /* - * input and output sample rate parameters - * By default, these are calculated from pipeline frames_per_sched - * and period but they can also be overridden via input arguments - * to the testbench. - */ - uint32_t fs_in; - uint32_t fs_out; - uint32_t channels; - int fr_id; - int fw_id; - int sched_id; - enum sof_ipc_frame frame_fmt; -}; - -struct shared_lib_table { - char *comp_name; - char library_name[MAX_LIB_NAME_LEN]; - uint32_t widget_type; - int register_drv; - void *handle; -}; - -extern int debug; - -int edf_scheduler_init(void); - -void sys_comp_file_init(void); - -void sys_comp_filewrite_init(void); - -int tb_pipeline_setup(struct sof *sof); - -int tb_pipeline_start(struct ipc *ipc, struct sof_ipc_pipe_new *ipc_pipe, - struct testbench_prm *tp); - -int tb_pipeline_params(struct ipc *ipc, struct sof_ipc_pipe_new *ipc_pipe, - struct testbench_prm *tp); - -void debug_print(char *message); - -int get_index_by_name(char *comp_name, - struct shared_lib_table *lib_table); - -int get_index_by_type(uint32_t comp_type, - struct shared_lib_table *lib_table); - -int parse_topology(struct sof *sof, struct shared_lib_table *library_table, - struct testbench_prm *tp, char *pipeline_msg); -#endif diff --git a/tools/testbench/include/testbench/file.h b/tools/testbench/include/testbench/file.h index bce37e0f275d..c9552c5a4425 100644 --- a/tools/testbench/include/testbench/file.h +++ b/tools/testbench/include/testbench/file.h @@ -8,8 +8,21 @@ * Ranjani Sridharan <ranjani.sridharan@linux.intel.com> */ -#ifndef _FILE_H -#define _FILE_H +#ifndef _TESTBENCH_FILE_H +#define _TESTBENCH_FILE_H + +#include <stdint.h> + +#define FILE_MAX_COPIES_TIMEOUT 3 + +/**< 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) + +/* bfc7488c-75aa-4ce8-9dbed8da08a698c2 */ +static const struct sof_uuid tb_file_uuid = { + 0xbfc7488c, 0x75aa, 0x4ce8, {0x9d, 0xbe, 0xd8, 0xda, 0x08, 0xa6, 0x98, 0xc2} +}; /* file component modes */ enum file_mode { @@ -25,36 +38,51 @@ enum file_format { /* file component state */ struct file_state { - char *fn; + uint64_t cycles_count; FILE *rfh, *wfh; /* read/write file handle */ - int reached_eof; + char *fn; + int copy_count; + int channels; + int rate; int n; enum file_mode mode; enum file_format f_format; + bool reached_eof; + bool write_failed; + bool copy_timeout; }; +struct file_comp_data; + /* file comp data */ struct file_comp_data { - uint32_t period_bytes; - uint32_t channels; - uint32_t frame_bytes; - uint32_t rate; struct file_state fs; - int sample_container_bytes; enum sof_ipc_frame frame_fmt; - int (*file_func)(struct comp_dev *dev, struct audio_stream *sink, + int sample_container_bytes; + int (*file_func)(struct file_comp_data *cd, struct audio_stream *sink, struct audio_stream *source, uint32_t frames); + /* maximum limits */ + int max_samples; + int max_copies; + int max_frames; + int copies_timeout_count; }; -/* file IO ipc comp */ -struct sof_ipc_comp_file { - struct sof_ipc_comp comp; - struct sof_ipc_comp_config config; - uint32_t rate; - uint32_t channels; - char *fn; - enum file_mode mode; - enum sof_ipc_frame frame_fmt; -} __attribute__((packed)); -#endif +void sys_comp_module_file_interface_init(void); + +/* Get file comp data from copier data */ +static inline struct file_comp_data *get_file_comp_data(struct copier_data *ccd) +{ + struct file_comp_data *cd = (struct file_comp_data *)ccd->ipcgtw_data; + + return cd; +} + +/* Set file comp data to copier data */ +static inline void file_set_comp_data(struct copier_data *ccd, struct file_comp_data *cd) +{ + ccd->ipcgtw_data = (struct ipcgtw_data *)cd; +} + +#endif /* _TESTBENCH_FILE */ diff --git a/tools/testbench/include/testbench/file_ipc4.h b/tools/testbench/include/testbench/file_ipc4.h new file mode 100644 index 000000000000..c9e435b3883f --- /dev/null +++ b/tools/testbench/include/testbench/file_ipc4.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __TESTBENCH_FILE_IPC4_H_ +#define __TESTBENCH_FILE_IPC4_H_ + +#include <ipc/topology.h> +#include <ipc4/base-config.h> + +struct ipc4_file_config { + uint32_t rate; + uint32_t channels; + char *fn; + uint32_t mode; + uint32_t frame_fmt; + uint32_t direction; /**< SOF_IPC_STREAM_ */ +}; + +struct ipc4_file_module_cfg { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_file_config config; +} __packed __aligned(8); + +#endif /* __TESTBENCH_FILE_IPC4_H_ */ diff --git a/tools/testbench/include/testbench/timer.h b/tools/testbench/include/testbench/timer.h deleted file mode 100644 index 2f8ef8e21cf7..000000000000 --- a/tools/testbench/include/testbench/timer.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2018 Intel Corporation. All rights reserved. - * - * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> - */ - -#ifndef _INCLUDE_HOST_TIMER_H_ -#define _INCLUDE_HOST_TIMER_H_ - -#include <sof/audio/component.h> -#include <ipc/stream.h> - -/* get timestamp for host stream DMA position */ -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn); - -/* get timestamp for DAI stream DMA position */ -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn); - -#endif /* _INCLUDE_HOST_TIMER_H_ */ diff --git a/tools/testbench/include/testbench/topology_ipc4.h b/tools/testbench/include/testbench/topology_ipc4.h new file mode 100644 index 000000000000..0f5d0699e08f --- /dev/null +++ b/tools/testbench/include/testbench/topology_ipc4.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef _TESTBENCH_TOPOLOGY_IPC4_H +#define _TESTBENCH_TOPOLOGY_IPC4_H + +#include <module/ipc4/base-config.h> +#include "testbench/utils.h" + +#define TB_IPC4_MAX_TPLG_OBJECT_SIZE 4096 + +/* See module_set_large_config() where message fragment is + * MAILBOX_DSPBOX_SIZE. The add of header size (8) is because + * testbench and plugin have the set large config header in + * same memory as the payload. + */ +#define TB_IPC4_MAX_MSG_SIZE (MAILBOX_DSPBOX_SIZE + sizeof(struct ipc4_module_large_config)) + +#define TB_MIXIN_MODULE_ID 0x2 +#define TB_MIXOUT_MODULE_ID 0x3 +#define TB_PGA_MODULE_ID 0x6 +#define TB_SRC_MODULE_ID 0x7 +#define TB_ASRC_MODULE_ID 0x8 +#define TB_PROCESS_MODULE_ID 0x95 +#define TB_FILE_OUT_AIF_MODULE_ID 0x9a +#define TB_FILE_IN_AIF_MODULE_ID 0x9b +#define TB_FILE_OUT_DAI_MODULE_ID 0x9c +#define TB_FILE_IN_DAI_MODULE_ID 0x9d + +enum tb_pin_type { + TB_PIN_TYPE_INPUT = 0, + TB_PIN_TYPE_OUTPUT, +}; + +int tb_delete_pipeline(struct testbench_prm *tp, struct tplg_pipeline_info *pipe_info); +int tb_free_all_pipelines(struct testbench_prm *tp); +int tb_free_route(struct testbench_prm *tp, struct tplg_route_info *route_info); +int tb_get_instance_id_from_pipeline_id(struct testbench_prm *tp, int id); +int tb_is_single_format(struct sof_ipc4_pin_format *fmts, int num_formats); +int tb_match_audio_format(struct testbench_prm *tp, struct tplg_comp_info *comp_info, + struct tb_config *config); +int tb_new_aif_in_out(struct testbench_prm *tp, int dir); +int tb_new_dai_in_out(struct testbench_prm *tp, int dir); +int tb_new_pga(struct testbench_prm *tp); +int tb_new_process(struct testbench_prm *tp); +int tb_pipelines_set_state(struct testbench_prm *tp, int state, int dir); +int tb_send_bytes_data(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, + uint32_t module_id, uint32_t instance_id, struct sof_abi_hdr *abi); +int tb_send_volume_control(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, + struct tb_ctl *ctl, int *control_values, int num_values); +int tb_send_alsa_control(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, struct tb_ctl *ctl, + int *control_values, int num_values, int param_id); +int tb_set_reset_state(struct testbench_prm *tp); +int tb_set_running_state(struct testbench_prm *tp); +int tb_set_up_pipeline(struct testbench_prm *tp, struct tplg_pipeline_info *pipe_info); +int tb_set_up_route(struct testbench_prm *tp, struct tplg_route_info *route_info); +int tb_set_up_widget_base_config(struct testbench_prm *tp, + struct tplg_comp_info *comp_info); +int tb_set_up_widget_ipc(struct testbench_prm *tp, struct tplg_comp_info *comp_info); +void tb_free_topology(struct testbench_prm *tp); +void tb_pipeline_update_resource_usage(struct testbench_prm *tp, + struct tplg_comp_info *comp_info); + +#endif /* _TESTBENCH_TOPOLOGY_IPC4_H */ diff --git a/tools/testbench/include/testbench/trace.h b/tools/testbench/include/testbench/trace.h index 73c50d43853d..fadaae825742 100644 --- a/tools/testbench/include/testbench/trace.h +++ b/tools/testbench/include/testbench/trace.h @@ -8,9 +8,11 @@ #include <stdbool.h> -#ifndef _TRACE_H -#define _TRACE_H +#ifndef _TESTBENCH_TRACE_H +#define _TESTBENCH_TRACE_H -void tb_enable_trace(bool enable); +void tb_enable_trace(unsigned int log_level); -#endif +bool tb_check_trace(unsigned int log_level); + +#endif /* _TESTBENCH_TRACE_H */ diff --git a/tools/testbench/include/testbench/utils.h b/tools/testbench/include/testbench/utils.h new file mode 100644 index 000000000000..a52688cb93dc --- /dev/null +++ b/tools/testbench/include/testbench/utils.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + */ + +#ifndef _TESTBENCH_UTILS_H +#define _TESTBENCH_UTILS_H + +#include <tplg_parser/topology.h> +#include <stdint.h> +#include <stdbool.h> + + +#include <sof/lib/uuid.h> + +#define TB_DEBUG_MSG_LEN 1024 +#define TB_MAX_LIB_NAME_LEN 1024 + +#define TB_MAX_INPUT_FILE_NUM 16 +#define TB_MAX_OUTPUT_FILE_NUM 16 +#define TB_MAX_PIPELINES_NUM 16 +#define TB_MAX_CMD_CHARS 256 +#define TB_MAX_CTL_NAME_CHARS 128 +#define TB_MAX_VOLUME_SIZE 120 +#define TB_MAX_BYTES_DATA_SIZE 8192 +#define TB_MAX_BLOB_CONTENT_CHARS 32768 + +/* number of widgets types supported in testbench */ +#define TB_NUM_WIDGETS_SUPPORTED 16 + +struct tplg_context; + +struct file_comp_lookup { + int id; + int instance_id; + int pipeline_id; + struct file_state *state; +}; + +struct tb_ctl { + struct tplg_comp_info *comp_info; + unsigned int module_id; + unsigned int instance_id; + unsigned int type; + unsigned int volume_table[TB_MAX_VOLUME_SIZE]; + unsigned int index; + char *data; + char name[TB_MAX_CTL_NAME_CHARS]; + union { + struct snd_soc_tplg_mixer_control mixer_ctl; + struct snd_soc_tplg_enum_control enum_ctl; + struct snd_soc_tplg_bytes_control bytes_ctl; + }; +}; + +struct tb_glb_state { + char magic[8]; /* SOF_MAGIC */ + uint32_t num_ctls; /* number of ctls */ + size_t size; /* size of this structure in bytes */ + struct tb_ctl *ctl; +}; + +#if CONFIG_IPC_MAJOR_4 + +#define TB_NAME_SIZE 256 +#define TB_MAX_CONFIG_COUNT 2 +#define TB_MAX_CONFIG_NAME_SIZE 64 +#define TB_MAX_CTLS 32 + +struct tb_mq_desc { + char queue_name[TB_NAME_SIZE]; +}; + +struct tb_config { + char name[TB_MAX_CONFIG_NAME_SIZE]; + unsigned long buffer_frames; + unsigned long buffer_time; + unsigned long period_frames; + unsigned long period_time; + int rate; + int channels; + unsigned long format; +}; +#endif + +/* + * Global testbench data. + * + * TODO: some items are topology and pipeline specific and need moved out + * into per pipeline data and per topology data structures. + */ +struct testbench_prm { + long long total_cycles; + int pipelines[TB_MAX_PIPELINES_NUM]; + struct file_comp_lookup fr[TB_MAX_INPUT_FILE_NUM]; + struct file_comp_lookup fw[TB_MAX_OUTPUT_FILE_NUM]; + char *input_file[TB_MAX_INPUT_FILE_NUM]; /* input file names */ + char *output_file[TB_MAX_OUTPUT_FILE_NUM]; /* output file names */ + char *tplg_file; /* topology file to use */ + char *bits_in; /* input bit format */ + char *control_file; + int input_file_num; /* number of input files */ + int output_file_num; /* number of output files */ + int pipeline_num; + int copy_iterations; + bool copy_check; + int trace_level; + int dynamic_pipeline_iterations; + char *pipeline_string; + int output_file_index; + int input_file_index; + + struct tplg_comp_info *info; + int info_index; + int info_elems; + + /* + * input and output sample rate parameters + * By default, these are calculated from pipeline frames_per_sched + * and period but they can also be overridden via input arguments + * to the testbench. + */ + uint32_t fs_in; + uint32_t fs_out; + uint32_t channels_in; + uint32_t channels_out; + enum sof_ipc_frame frame_fmt; + + /* topology */ + struct tplg_context tplg; + + FILE *control_fh; + struct tb_glb_state glb_ctx; + +#if CONFIG_IPC_MAJOR_4 + struct list_item widget_list; + struct list_item route_list; + struct list_item pcm_list; + struct list_item pipeline_list; + int instance_ids[SND_SOC_TPLG_DAPM_LAST]; + struct tb_mq_desc ipc_tx; + struct tb_mq_desc ipc_rx; + int pcm_id; // TODO: This needs to be cleaned up + struct tplg_pcm_info *pcm_info; + struct tb_config config[TB_MAX_CONFIG_COUNT]; + int num_configs; + int period_frames; +#endif +}; + +/** + * @brief Record of heap memory usage for a module. + * + * Stores the maximum heap usage observed for a specific module, + * used for profiling and memory analysis in testbench. + */ +struct tb_heap_usage_record { + char *module_name; /**< Name of the module */ + size_t heap_max; /**< Maximum heap usage in bytes */ +}; + +extern int debug; + +int tb_decode_enum(struct snd_soc_tplg_enum_control *enum_ctl, char *token); +int tb_find_file_components(struct testbench_prm *tp); +int tb_free_all_pipelines(struct testbench_prm *tp); +int tb_load_topology(struct testbench_prm *tp); +int tb_parse_topology(struct testbench_prm *tp); +int tb_pipeline_params(struct testbench_prm *tp, struct ipc *ipc, struct pipeline *p); +int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p); +int tb_pipeline_start(struct ipc *ipc, struct pipeline *p); +int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p); +int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns); +int tb_set_bytes_control(struct testbench_prm *tp, struct tb_ctl *ctl, uint32_t *data); +int tb_set_enum_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params); +int tb_set_reset_state(struct testbench_prm *tp); +int tb_set_mixer_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params); +int tb_set_running_state(struct testbench_prm *tp); +int tb_set_up_all_pipelines(struct testbench_prm *tp); +int tb_setup(struct sof *sof, struct testbench_prm *tp); +bool tb_is_pipeline_enabled(struct testbench_prm *tp, int pipeline_id); +bool tb_schedule_pipeline_check_state(struct testbench_prm *tp); + +/** + * @brief Collect heap usage statistics for all modules. + * + * Iterates over the active modules in the testbench and records the maximum + * heap usage for each one into the provided array. + * + * @param tp Pointer to testbench parameters. + * @param rec Array of heap usage records to populate. + * @param count Pointer to an integer that receives the number of records written. + */ +void tb_collect_heap_usage(struct testbench_prm *tp, struct tb_heap_usage_record *rec, int *count); +void tb_debug_print(char *message); +void tb_free(struct sof *sof); +void tb_free_topology(struct testbench_prm *tp); +void tb_getcycles(uint64_t *cycles); +void tb_gettime(struct timespec *td); +void tb_show_file_stats(struct testbench_prm *tp, int pipeline_id); + +#endif /* _TESTBENCH_UTILS_H */ diff --git a/tools/testbench/ipc.c b/tools/testbench/ipc.c deleted file mode 100644 index 3c237bebd63c..000000000000 --- a/tools/testbench/ipc.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -#include <sof/lib/alloc.h> -#include <sof/drivers/ipc.h> -#include <stdlib.h> - -/* testbench ipc */ -struct ipc *_ipc; - -/* private data for IPC */ -struct ipc_data { - struct ipc_data_host_buffer dh_buffer; -}; - -enum task_state ipc_platform_do_cmd(void *data) -{ - return SOF_TASK_STATE_COMPLETED; -} - -void ipc_platform_complete_cmd(void *data) -{ -} - -int platform_ipc_init(struct ipc *ipc) -{ - struct ipc_data *iipc; - - _ipc = ipc; - - /* init ipc data */ - iipc = malloc(sizeof(struct ipc_data)); - ipc_set_drvdata(_ipc, iipc); - - /* allocate page table buffer */ - iipc->dh_buffer.page_table = malloc(HOST_PAGE_SIZE); - if (iipc->dh_buffer.page_table) - bzero(iipc->dh_buffer.page_table, HOST_PAGE_SIZE); - - return 0; -} - -/* The following definition is to satisfy libsof linker errors */ - -void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) -{ -} diff --git a/tools/testbench/ll_schedule.c b/tools/testbench/ll_schedule.c deleted file mode 100644 index f837726433a0..000000000000 --- a/tools/testbench/ll_schedule.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/schedule/ll_schedule.h> -#include <sof/schedule/schedule.h> - -int schedule_task_init_ll(struct task *task, uint32_t uid, uint16_t type, - uint16_t priority, - enum task_state (*run)(void *data), void *data, - uint16_t core, uint32_t flags) -{ - int ret; - - ret = schedule_task_init(task, uid, type, priority, run, data, core, - flags); - - return ret; -} diff --git a/tools/testbench/panic.c b/tools/testbench/panic.c deleted file mode 100644 index f8fda1aa02db..000000000000 --- a/tools/testbench/panic.c +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> - -#include <sof/debug/panic.h> - -void __panic(uint32_t p, char *filename, uint32_t linenum) { } diff --git a/tools/testbench/schedule.c b/tools/testbench/schedule.c deleted file mode 100644 index 76add1152adf..000000000000 --- a/tools/testbench/schedule.c +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -#include <sof/audio/component.h> -#include <sof/schedule/task.h> -#include <stdint.h> -#include <sof/lib/wait.h> -#include <stdlib.h> - -static struct schedulers *testbench_schedulers_ptr; /* Initialized as NULL */ - -struct schedulers **arch_schedulers_get(void) -{ - return &testbench_schedulers_ptr; -} - -int schedule_task_init(struct task *task, uint32_t uid, uint16_t type, - uint16_t priority, enum task_state (*run)(void *data), - void *data, uint16_t core, uint32_t flags) -{ - if (type >= SOF_SCHEDULE_COUNT) - return -EINVAL; - - task->uid = uid; - task->type = SOF_SCHEDULE_EDF; /* Note: Force EDF scheduler */ - task->priority = priority; - task->core = core; - task->flags = flags; - task->state = SOF_TASK_STATE_INIT; - task->ops.run = run; - task->data = data; - - return 0; -} - -static void scheduler_register(struct schedule_data *scheduler) -{ - struct schedulers **sch = arch_schedulers_get(); - - if (!*sch) { - /* init schedulers list */ - *sch = calloc(1, sizeof(**sch)); - list_init(&(*sch)->list); - } - - list_item_append(&scheduler->list, &(*sch)->list); -} - -void scheduler_init(int type, const struct scheduler_ops *ops, void *data) -{ - struct schedule_data *sch; - - sch = calloc(1, sizeof(*sch)); - list_init(&sch->list); - sch->type = SOF_SCHEDULE_EDF; /* Note: Force EDF scheduler */ - sch->ops = ops; - sch->data = data; - - scheduler_register(sch); -} diff --git a/tools/testbench/testbench.c b/tools/testbench/testbench.c index ae1db01f47cf..670f34c1ab27 100644 --- a/tools/testbench/testbench.c +++ b/tools/testbench/testbench.c @@ -1,144 +1,162 @@ // SPDX-License-Identifier: BSD-3-Clause // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2024 Intel Corporation. All rights reserved. // // Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> // Ranjani Sridharan <ranjani.sridharan@linux.intel.com> -#include <sof/drivers/ipc.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/topology.h> #include <sof/list.h> -#include <getopt.h> -#include <dlfcn.h> -#include "testbench/common_test.h" #include <tplg_parser/topology.h> + #include "testbench/trace.h" #include "testbench/file.h" +#include "testbench/utils.h" -#define TESTBENCH_NCH 2 /* Stereo */ +#include <ctype.h> +#include <getopt.h> +#include <limits.h> +#include <stdbool.h> +#include <stdlib.h> +#include <time.h> -/* shared library look up table */ -struct shared_lib_table lib_table[NUM_WIDGETS_SUPPORTED] = { - {"file", "", SOF_COMP_HOST, 0, NULL}, /* File must be first */ - {"volume", "libsof_volume.so", SOF_COMP_VOLUME, 0, NULL}, - {"src", "libsof_src.so", SOF_COMP_SRC, 0, NULL}, - {"asrc", "libsof_asrc.so", SOF_COMP_ASRC, 0, NULL}, - {"eq-fir", "libsof_eq-fir.so", SOF_COMP_EQ_FIR, 0, NULL}, - {"eq-iir", "libsof_eq-iir.so", SOF_COMP_EQ_IIR, 0, NULL}, -}; +#define TESTBENCH_NCH 2 -/* main firmware context */ -static struct sof sof; +/* + * Parse output filenames from user input + * This function takes in the output filenames as an input in the format: + * "output_file1,output_file2,..." + * The max supported output filename number is 4, min is 1. + */ +static int parse_output_files(char *outputs, struct testbench_prm *tp) +{ + char *output_token = NULL; + char *token = strtok_r(outputs, ",", &output_token); + int index; -/* compatible variables, not used */ -intptr_t _comp_init_start, _comp_init_end; + for (index = 0; index < TB_MAX_OUTPUT_FILE_NUM && token; index++) { + /* get output file name with current index */ + tp->output_file[index] = strdup(token); -struct sof *sof_get() -{ - return &sof; + /* next output */ + token = strtok_r(NULL, ",", &output_token); + } + + if (index == TB_MAX_OUTPUT_FILE_NUM && token) { + fprintf(stderr, "error: max output file number is %d\n", + TB_MAX_OUTPUT_FILE_NUM); + for (index = 0; index < TB_MAX_OUTPUT_FILE_NUM; index++) + free(tp->output_file[index]); + return -EINVAL; + } + + /* set total output file number */ + tp->output_file_num = index; + return 0; } /* - * Parse shared library from user input - * Currently only handles volume and src comp - * This function takes in the libraries to be used as an input in the format: - * "vol=libsof_volume.so,src=libsof_src.so,..." - * The function parses the above string to identify the following: - * component type and the library name and sets up the library handle - * for the component and stores it in the shared library table + * Parse inputfilenames from user input */ -static int parse_libraries(char *libs) +static int parse_input_files(char *inputs, struct testbench_prm *tp) { - char *lib_token = NULL; - char *comp_token = NULL; - char *token = strtok_r(libs, ",", &lib_token); + char *input_token = NULL; + char *token = strtok_r(inputs, ",", &input_token); int index; - while (token) { + for (index = 0; index < TB_MAX_INPUT_FILE_NUM && token; index++) { + /* get input file name with current index */ + tp->input_file[index] = strdup(token); + + /* next input */ + token = strtok_r(NULL, ",", &input_token); + } - /* get component type */ - char *token1 = strtok_r(token, "=", &comp_token); + if (index == TB_MAX_INPUT_FILE_NUM && token) { + fprintf(stderr, "error: max input file number is %d\n", + TB_MAX_INPUT_FILE_NUM); + for (index = 0; index < TB_MAX_INPUT_FILE_NUM; index++) + free(tp->input_file[index]); + return -EINVAL; + } - /* get shared library index from library table */ - index = get_index_by_name(token1, lib_table); + /* set total input file number */ + tp->input_file_num = index; + return 0; +} - if (index < 0) { - fprintf(stderr, "error: unsupported comp type\n"); - return -EINVAL; - } +static int parse_pipelines(char *pipelines, struct testbench_prm *tp) +{ + char *output_token = NULL; + char *token = strtok_r(pipelines, ",", &output_token); + int index; - /* get shared library name */ - token1 = strtok_r(NULL, "=", &comp_token); - if (!token1) - break; + for (index = 0; index < TB_MAX_OUTPUT_FILE_NUM && token; index++) { + /* get output file name with current index */ + tp->pipelines[index] = atoi(token); - /* set to new name that may be used while loading */ - strncpy(lib_table[index].library_name, token1, - MAX_LIB_NAME_LEN - 1); + /* next output */ + token = strtok_r(NULL, ",", &output_token); + } - /* next library */ - token = strtok_r(NULL, ",", &lib_token); + if (index == TB_MAX_OUTPUT_FILE_NUM && token) { + fprintf(stderr, "error: max output file number is %d\n", + TB_MAX_OUTPUT_FILE_NUM); + return -EINVAL; } + + /* set total output file number */ + tp->pipeline_num = index; return 0; } /* print usage for testbench */ static void print_usage(char *executable) { - printf("Usage: %s -i <input_file> -o <output_file> ", executable); - printf("-t <tplg_file> -b <input_format> "); - printf("-a <comp1=comp1_library,comp2=comp2_library>\n"); - printf("input_format should be S16_LE, S32_LE, S24_LE or FLOAT_LE\n"); + printf("Usage: %s <options> -i <input_file> ", executable); + printf("-o <output_file1,output_file2,...>\n\n"); + printf("Options for processing:\n"); + printf(" -t <topology file>\n\n"); + printf("Options to control test:\n"); + printf(" -d <level> Sets the traces print level:\n"); + printf(" 0 all traces are suppressed\n"); + printf(" 1 shows error traces\n"); + printf(" 2 shows warning traces and previous\n"); + printf(" 3 shows info traces and previous\n"); + printf(" 4 shows debug traces and previous, plus other testbench debug messages\n"); + printf(" -p <pipeline1,pipeline2,...>\n"); + printf(" -C <number of copy() iterations>\n"); + printf(" -P <number of dynamic pipeline iterations>\n"); + printf(" -s <script file to set controls, with amixer and sleep commands>\n\n"); + printf("Options for input and output format override:\n"); + printf(" -b <input_format>, S16_LE, S24_LE, or S32_LE\n"); + printf(" -c <input channels>\n"); + printf(" -n <output channels>\n"); + printf(" -r <input rate>\n"); + printf(" -R <output rate>\n\n"); + printf("Help:\n"); + printf(" -h\n\n"); printf("Example Usage:\n"); - printf("%s -i in.txt -o out.txt -t test.tplg ", executable); - printf("-r 48000 -R 96000 "); - printf("-b S16_LE -a vol=libsof_volume.so\n"); -} - -/* free components */ -static void free_comps(void) -{ - struct list_item *clist; - struct list_item *temp; - struct ipc_comp_dev *icd = NULL; - - list_for_item_safe(clist, temp, &sof.ipc->comp_list) { - icd = container_of(clist, struct ipc_comp_dev, list); - switch (icd->type) { - case COMP_TYPE_COMPONENT: - comp_free(icd->cd); - list_item_del(&icd->list); - rfree(icd); - break; - case COMP_TYPE_BUFFER: - rfree(icd->cb->stream.addr); - rfree(icd->cb); - list_item_del(&icd->list); - rfree(icd); - break; - default: - rfree(icd->pipeline); - list_item_del(&icd->list); - rfree(icd); - break; - } - } + printf("%s -r 48000 -c 2 -b S16_LE -i in.raw -o out.raw -t <test.tplg>\n\n", executable); } -static void parse_input_args(int argc, char **argv, struct testbench_prm *tp) +static int parse_input_args(int argc, char **argv, struct testbench_prm *tp) { int option = 0; int ret = 0; - while ((option = getopt(argc, argv, "hdi:o:t:b:a:r:R:")) != -1) { + while ((option = getopt(argc, argv, "hd:i:o:t:b:r:R:c:n:C:P:p:s:")) != -1) { switch (option) { /* input sample file */ case 'i': - tp->input_file = strdup(optarg); + ret = parse_input_files(optarg, tp); break; - /* output sample file */ + /* output sample files */ case 'o': - tp->output_file = strdup(optarg); + ret = parse_output_files(optarg, tp); break; /* topology file */ @@ -149,12 +167,7 @@ static void parse_input_args(int argc, char **argv, struct testbench_prm *tp) /* input samples bit format */ case 'b': tp->bits_in = strdup(optarg); - tp->frame_fmt = find_format(tp->bits_in); - break; - - /* override default libraries */ - case 'a': - ret = parse_libraries(optarg); + tp->frame_fmt = tplg_find_format(tp->bits_in); break; /* input sample rate */ @@ -167,144 +180,354 @@ static void parse_input_args(int argc, char **argv, struct testbench_prm *tp) tp->fs_out = atoi(optarg); break; - /* enable debug prints */ + /* input/output channels */ + case 'c': + tp->channels_in = atoi(optarg); + break; + + /* output channels */ + case 'n': + tp->channels_out = atoi(optarg); + break; + + /* set debug log level */ case 'd': - debug = 1; + if (isdigit((int)*optarg)) { + tp->trace_level = atoi(optarg); + } else { + fprintf(stderr, "Error: Debug level must be a digit.\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + break; + + /* number of pipeline copy() iterations */ + case 'C': + tp->copy_iterations = atoi(optarg); + tp->copy_check = true; + break; + + /* number of dynamic pipeline iterations */ + case 'P': + tp->dynamic_pipeline_iterations = atoi(optarg); + break; + + /* output sample files */ + case 'p': + ret = parse_pipelines(optarg, tp); + break; + + /* control script file name */ + case 's': + tp->control_file = strdup(optarg); break; /* print usage */ case 'h': + print_usage(argv[0]); + exit(EXIT_SUCCESS); + default: + fprintf(stderr, "unknown option %c\n", option); print_usage(argv[0]); - exit(EXIT_FAILURE); + ret = -EINVAL; } if (ret < 0) - exit(EXIT_FAILURE); + return ret; } + + return ret; } -int main(int argc, char **argv) +static void test_pipeline_stats(struct testbench_prm *tp, long long delta_t, + struct tb_heap_usage_record *heap_records, + int heap_records_count) { - struct testbench_prm tp; - struct ipc_comp_dev *pcm_dev; - struct pipeline *p; - struct sof_ipc_pipe_new *ipc_pipe; - struct comp_dev *cd; - struct file_comp_data *frcd, *fwcd; - char pipeline[DEBUG_MSG_LEN]; - clock_t tic, toc; - double c_realtime, t_exec; - int n_in, n_out, ret; + long long file_cycles, pipeline_cycles; + float pipeline_mcps; + int n_in, n_out, frames_out; int i; + int count = 1; - /* initialize input and output sample rates, files, etc. */ - tp.fs_in = 0; - tp.fs_out = 0; - tp.bits_in = 0; - tp.input_file = NULL; - tp.output_file = NULL; - tp.channels = TESTBENCH_NCH; + n_out = 0; + n_in = 0; + file_cycles = 0; + for (i = 0; i < tp->input_file_num; i++) { + if (tp->fr[i].id < 0) + continue; - /* command line arguments*/ - parse_input_args(argc, argv, &tp); + n_in += tp->fr[i].state->n; + file_cycles += tp->fr[i].state->cycles_count; + } - /* check args */ - if (!tp.tplg_file || !tp.input_file || !tp.output_file || !tp.bits_in) { - print_usage(argv[0]); - exit(EXIT_FAILURE); + for (i = 0; i < tp->output_file_num; i++) { + if (tp->fw[i].id < 0) + continue; + + n_out += tp->fw[i].state->n; + file_cycles += tp->fw[i].state->cycles_count; } - /* initialize ipc and scheduler */ - if (tb_pipeline_setup(&sof) < 0) { - fprintf(stderr, "error: pipeline init\n"); - exit(EXIT_FAILURE); + /* print test summary */ + printf("==========================================================\n"); + printf(" Test Summary %d\n", count); + printf("==========================================================\n"); + + for (i = 0; i < tp->pipeline_num; i++) { + printf("pipeline %d\n", tp->pipelines[i]); + tb_show_file_stats(tp, tp->pipelines[i]); + } + + printf("Input bit format: %s\n", tp->bits_in); + printf("Input sample rate: %d\n", tp->fs_in); + printf("Output sample rate: %d\n", tp->fs_out); + + 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, frames_out); + if (heap_records_count > 0) { + for (i = 0; i < heap_records_count; i++) + printf("Heap usage for module %s: %u bytes\n", + heap_records[i].module_name, (uint32_t)heap_records[i].heap_max); } - /* parse topology file and create pipeline */ - if (parse_topology(&sof, lib_table, &tp, pipeline) < 0) { - fprintf(stderr, "error: parsing topology\n"); - exit(EXIT_FAILURE); + printf("\n"); + if (tp->total_cycles) { + pipeline_cycles = tp->total_cycles - file_cycles; + pipeline_mcps = (float)pipeline_cycles * tp->fs_out / frames_out / 1e6; + if (tb_check_trace(LOG_LEVEL_DEBUG)) + printf("Warning: Use -d 3 or smaller value to avoid traces to increase MCPS.\n"); + + 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\n", pipeline_mcps); + } + + if (delta_t) + printf("Total execution time: %lld us, %.2f x realtime\n\n", delta_t, + (float)frames_out / tp->fs_out * 1000000 / delta_t); +} + +/* + * Tester thread, one for each virtual core. This is NOT the thread that will + * execute the virtual core. + */ +static int pipline_test(struct testbench_prm *tp) +{ + struct tb_heap_usage_record heap_usage_records[TB_NUM_WIDGETS_SUPPORTED]; + struct file_state *out_stat; + struct timespec td0 = {0}, td1 = {0}; + long long delta_t = 0; + int64_t next_control_ns; + int64_t time_ns; + float samples_to_ns; + int err; + int heap_usage_records_count = 0; + int dp_count = 0; + + /* build, run and teardown pipelines */ + while (dp_count < tp->dynamic_pipeline_iterations) { + fprintf(stdout, "pipeline run %d/%d\n", dp_count, + tp->dynamic_pipeline_iterations); + + /* print test summary */ + printf("==========================================================\n"); + printf(" Test Start %d\n", dp_count); + printf("==========================================================\n"); + + err = tb_load_topology(tp); + if (err < 0) { + fprintf(stderr, "error: topology load %d failed %d\n", dp_count, err); + break; + } + + err = tb_set_up_all_pipelines(tp); + if (err < 0) { + fprintf(stderr, "error: pipelines set up %d failed %d\n", dp_count, err); + break; + } + + err = tb_set_running_state(tp); + if (err < 0) { + fprintf(stderr, "error: pipelines state set %d failed %d\n", dp_count, err); + break; + } + + err = tb_find_file_components(tp); /* Track file comp status during copying */ + if (err < 0) { + fprintf(stderr, "error: file component find failed %d\n", err); + break; + } + + /* Use first file writer to create simulation time. Calculate coefficient + * to calculate current time from file write samples count + */ + out_stat = tp->fw[0].state; + samples_to_ns = 1.0e9 / ((float)out_stat->channels * out_stat->rate); + + /* Apply initial controls time to call again controls handler */ + err = tb_read_controls(tp, &next_control_ns); + if (err) { + fprintf(stderr, "error: failed to read control commands.\n"); + goto out; + } + + tb_gettime(&td0); + + while (true) { + if (tp->copy_check) { + if (tp->copy_iterations-- <= 0) + break; + } + + if (tb_schedule_pipeline_check_state(tp)) + break; + + if (next_control_ns) { + time_ns = (int64_t)(samples_to_ns * out_stat->n); + if (time_ns >= next_control_ns) { + err = tb_read_controls(tp, &next_control_ns); + if (err) { + fprintf(stderr, + "error: failed to read control commands.\n"); + goto out; + } + + if (next_control_ns) + next_control_ns += time_ns; + } + } + } + + tb_schedule_pipeline_check_state(tp); /* Once more to flush out remaining data */ + tb_gettime(&td1); + delta_t = (td1.tv_sec - td0.tv_sec) * 1000000; + delta_t += (td1.tv_nsec - td0.tv_nsec) / 1000; + tb_collect_heap_usage(tp, heap_usage_records, &heap_usage_records_count); + +out: + err = tb_set_reset_state(tp); + if (err < 0) { + fprintf(stderr, "error: pipeline reset %d failed %d\n", + dp_count, err); + break; + } + + test_pipeline_stats(tp, delta_t, heap_usage_records, heap_usage_records_count); + + err = tb_free_all_pipelines(tp); + if (err < 0) { + fprintf(stderr, "error: free pipelines %d failed %d\n", dp_count, err); + break; + } + + tb_free_topology(tp); + dp_count++; } - /* Get pointers to fileread and filewrite */ - pcm_dev = ipc_get_comp_by_id(sof.ipc, tp.fw_id); - fwcd = comp_get_drvdata(pcm_dev->cd); - pcm_dev = ipc_get_comp_by_id(sof.ipc, tp.fr_id); - frcd = comp_get_drvdata(pcm_dev->cd); + return 0; +} - /* Run pipeline until EOF from fileread */ - pcm_dev = ipc_get_comp_by_id(sof.ipc, tp.sched_id); - p = pcm_dev->cd->pipeline; - ipc_pipe = &p->ipc_pipe; +int main(int argc, char **argv) +{ + struct testbench_prm *tp; + int i, ret; - /* input and output sample rate */ - if (!tp.fs_in) - tp.fs_in = ipc_pipe->period * ipc_pipe->frames_per_sched; + tp = calloc(1, sizeof(struct testbench_prm)); + if (!tp) + return EXIT_FAILURE; - if (!tp.fs_out) - tp.fs_out = ipc_pipe->period * ipc_pipe->frames_per_sched; + /* initialize input and output sample rates, files, etc. */ + tp->channels_in = TESTBENCH_NCH; + tp->copy_check = false; + tp->dynamic_pipeline_iterations = 1; + tp->pipeline_string = calloc(1, TB_DEBUG_MSG_LEN); + tp->pipelines[0] = 1; + tp->pipeline_num = 1; + tp->copy_iterations = 1; + tp->trace_level = LOG_LEVEL_INFO; + + /* command line arguments*/ + ret = parse_input_args(argc, argv, tp); + if (ret < 0) + goto out; + + if (!tp->channels_out) + tp->channels_out = tp->channels_in; - /* set pipeline params and trigger start */ - if (tb_pipeline_start(sof.ipc, ipc_pipe, &tp) < 0) { - fprintf(stderr, "error: pipeline params\n"); - exit(EXIT_FAILURE); + if (!tp->fs_out) + tp->fs_out = tp->fs_in; + + /* check mandatory args */ + if (!tp->tplg_file) { + fprintf(stderr, "topology file not specified, use -t file.tplg\n"); + print_usage(argv[0]); + ret = EXIT_FAILURE; + goto out; } - cd = pcm_dev->cd; - tb_enable_trace(false); /* reduce trace output */ - tic = clock(); + if (!tp->input_file_num) { + fprintf(stderr, "input files not specified, use -i file1,file2\n"); + print_usage(argv[0]); + ret = EXIT_FAILURE; + goto out; + } - while (frcd->fs.reached_eof == 0) - pipeline_schedule_copy(p, 0); + if (!tp->output_file_num) { + fprintf(stderr, "output files not specified, use -o file1,file2\n"); + print_usage(argv[0]); + ret = EXIT_FAILURE; + goto out; + } - if (!frcd->fs.reached_eof) - printf("warning: possible pipeline xrun\n"); + if (!tp->bits_in) { + fprintf(stderr, "input format not specified, use -b format\n"); + print_usage(argv[0]); + ret = EXIT_FAILURE; + goto out; + } - /* reset and free pipeline */ - toc = clock(); - tb_enable_trace(true); - pipeline_trigger(p, cd, COMP_TRIGGER_STOP); - ret = pipeline_reset(p, cd); - if (ret < 0) { - fprintf(stderr, "error: pipeline reset\n"); - exit(EXIT_FAILURE); + /* initialize ipc and scheduler */ + if (tb_setup(sof_get(), tp) < 0) { + fprintf(stderr, "error: pipeline init\n"); + ret = EXIT_FAILURE; + goto out; } - n_in = frcd->fs.n; - n_out = fwcd->fs.n; - t_exec = (double)(toc - tic) / CLOCKS_PER_SEC; - c_realtime = (double)n_out / TESTBENCH_NCH / tp.fs_out / t_exec; + if (tp->control_file) { + tp->control_fh = fopen(tp->control_file, "r"); + if (!tp->control_fh) { + fprintf(stderr, "error: opening script %s (%s).\n", + tp->control_file, strerror(errno)); + ret = -errno; + goto out; + } + } - /* free all components/buffers in pipeline */ - free_comps(); + /* build, run and teardown pipelines */ + pipline_test(tp); - /* print test summary */ - printf("==========================================================\n"); - printf(" Test Summary\n"); - printf("==========================================================\n"); - printf("Test Pipeline:\n"); - printf("%s\n", pipeline); - printf("Input bit format: %s\n", tp.bits_in); - printf("Input sample rate: %d\n", tp.fs_in); - printf("Output sample rate: %d\n", tp.fs_out); - printf("Output written to file: \"%s\"\n", tp.output_file); - printf("Input sample count: %d\n", n_in); - printf("Output sample count: %d\n", n_out); - printf("Total execution time: %.2f us, %.2f x realtime\n", - 1e3 * t_exec, c_realtime); + /* free other core FW services */ + tb_free(sof_get()); + ret = EXIT_SUCCESS; +out: /* free all other data */ - free(tp.bits_in); - free(tp.input_file); - free(tp.tplg_file); - free(tp.output_file); - - /* close shared library objects */ - for (i = 0; i < NUM_WIDGETS_SUPPORTED; i++) { - if (lib_table[i].handle) - dlclose(lib_table[i].handle); - } + free(tp->bits_in); + free(tp->tplg_file); + free(tp->control_file); + if (tp->control_fh) + fclose(tp->control_fh); + + for (i = 0; i < tp->output_file_num; i++) + free(tp->output_file[i]); + + for (i = 0; i < tp->input_file_num; i++) + free(tp->input_file[i]); - return EXIT_SUCCESS; + free(tp->pipeline_string); + free(tp); + return ret; } 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/timer.c b/tools/testbench/timer.c deleted file mode 100644 index 8965a3058308..000000000000 --- a/tools/testbench/timer.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Rander Wang <rander.wang@intel.com> -// Janusz Jankowski <janusz.jankowski@linux.intel.com> - -#include "testbench/timer.h" - -void platform_host_timestamp(struct comp_dev *host, - struct sof_ipc_stream_posn *posn) -{ -} - -/* get timestamp for DAI stream DMA position */ -void platform_dai_timestamp(struct comp_dev *dai, - struct sof_ipc_stream_posn *posn) -{ -} diff --git a/tools/testbench/topology.c b/tools/testbench/topology.c deleted file mode 100644 index ab20efa39e3e..000000000000 --- a/tools/testbench/topology.c +++ /dev/null @@ -1,773 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> - -/* Topology loader to set up components and pipeline */ - -#include <math.h> -#include <sof/drivers/ipc.h> -#include <sof/common.h> -#include <stdio.h> -#include <sof/string.h> -#include <dlfcn.h> -#include <sof/audio/component.h> -#include "testbench/file.h" -#include <tplg_parser/topology.h> -#include "testbench/common_test.h" - -FILE *file; -char pipeline_string[DEBUG_MSG_LEN]; -struct shared_lib_table *lib_table; - -const struct sof_dai_types sof_dais[] = { - {"SSP", SOF_DAI_INTEL_SSP}, - {"HDA", SOF_DAI_INTEL_HDA}, - {"DMIC", SOF_DAI_INTEL_DMIC}, -}; - -/* find dai type */ -enum sof_ipc_dai_type find_dai(const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sof_dais); i++) { - if (strcmp(name, sof_dais[i].name) == 0) - return sof_dais[i].type; - } - - return SOF_DAI_INTEL_NONE; -} - -/* - * Register component driver - * Only needed once per component type - */ -void register_comp(int comp_type) -{ - int index; - char message[DEBUG_MSG_LEN + MAX_LIB_NAME_LEN]; - - /* register file comp driver (no shared library needed) */ - if (comp_type == SOF_COMP_HOST || comp_type == SOF_COMP_DAI) { - if (!lib_table[0].register_drv) { - sys_comp_file_init(); - lib_table[0].register_drv = 1; - debug_print("registered file comp driver\n"); - } - return; - } - - /* get index of comp in shared library table */ - index = get_index_by_type(comp_type, lib_table); - if (index < 0) - return; - - /* register comp driver if not already registered */ - if (!lib_table[index].register_drv) { - sprintf(message, "registered comp driver for %s\n", - lib_table[index].comp_name); - debug_print(message); - - /* open shared library object */ - sprintf(message, "opening shared lib %s\n", - lib_table[index].library_name); - debug_print(message); - - lib_table[index].handle = dlopen(lib_table[index].library_name, - RTLD_LAZY); - if (!lib_table[index].handle) { - fprintf(stderr, "error: %s\n", dlerror()); - exit(EXIT_FAILURE); - } - - /* comp init is executed on lib load */ - lib_table[index].register_drv = 1; - } - -} - -int find_widget(struct comp_info *temp_comp_list, int count, char *name) -{ - return 0; -} - -/* load pipeline graph DAPM widget*/ -static int load_graph(void *dev, struct comp_info *temp_comp_list, - int count, int num_comps, int pipeline_id) -{ - struct sof_ipc_pipe_comp_connect connection; - struct sof *sof = (struct sof *)dev; - int ret = 0; - int i; - - for (i = 0; i < count; i++) { - ret = tplg_load_graph(num_comps, pipeline_id, temp_comp_list, - pipeline_string, &connection, file, i, - count); - if (ret < 0) - return ret; - - /* connect source and sink */ - if (ipc_comp_connect(sof->ipc, &connection) < 0) { - fprintf(stderr, "error: comp connect\n"); - return -EINVAL; - } - } - - /* pipeline complete after pipeline connections are established */ - for (i = 0; i < num_comps; i++) { - if (temp_comp_list[i].pipeline_id == pipeline_id && - temp_comp_list[i].type == SND_SOC_TPLG_DAPM_SCHEDULER) - ipc_pipeline_complete(sof->ipc, temp_comp_list[i].id); - } - - return ret; -} - -/* load buffer DAPM widget */ -int load_buffer(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct sof *sof = (struct sof *)dev; - struct sof_ipc_buffer buffer; - int size = widget->priv.size; - int ret; - - ret = tplg_load_buffer(comp_id, pipeline_id, size, &buffer, file); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - /* create buffer component */ - if (ipc_buffer_new(sof->ipc, &buffer) < 0) { - fprintf(stderr, "error: buffer new\n"); - return -EINVAL; - } - - return 0; -} - -/* load fileread component */ -static int tplg_load_fileread(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_file *fileread) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0; - size_t read_size; - int ret = 0; - - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - fprintf(stderr, - "error: fread failed during load_fileread\n"); - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&fileread->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse comp tokens %d\n", - size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - } - - free(array); - - /* configure fileread */ - fileread->mode = FILE_READ; - fileread->comp.id = comp_id; - - /* use fileread comp as scheduling comp */ - fileread->comp.core = 0; - fileread->comp.hdr.size = sizeof(struct sof_ipc_comp_file); - fileread->comp.type = SOF_COMP_FILEREAD; - fileread->comp.pipeline_id = pipeline_id; - fileread->config.hdr.size = sizeof(struct sof_ipc_comp_config); - return 0; -} - -/* load filewrite component */ -static int tplg_load_filewrite(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_file *filewrite) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t read_size; - size_t total_array_size = 0; - int ret = 0; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - ret = sof_parse_tokens(&filewrite->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse filewrite tokens %d\n", - size); - free(array); - return -EINVAL; - } - total_array_size += array->size; - } - - free(array); - - /* configure filewrite */ - filewrite->comp.core = 0; - filewrite->comp.id = comp_id; - filewrite->mode = FILE_WRITE; - filewrite->comp.hdr.size = sizeof(struct sof_ipc_comp_file); - filewrite->comp.type = SOF_COMP_FILEREAD; - filewrite->comp.pipeline_id = pipeline_id; - filewrite->config.hdr.size = sizeof(struct sof_ipc_comp_config); - return 0; -} - -/* load fileread component */ -static int load_fileread(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, - struct testbench_prm *tp) -{ - struct sof *sof = (struct sof *)dev; - struct sof_ipc_comp_file fileread; - int size = widget->priv.size; - int ret; - - fileread.config.frame_fmt = find_format(tp->bits_in); - - ret = tplg_load_fileread(comp_id, pipeline_id, size, &fileread); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - /* configure fileread */ - fileread.fn = strdup(tp->input_file); - - /* use fileread comp as scheduling comp */ - tp->fr_id = comp_id; - tp->sched_id = comp_id; - - /* Set format from testbench command line*/ - fileread.rate = tp->fs_in; - fileread.channels = tp->channels; - fileread.frame_fmt = tp->frame_fmt; - - /* Set type depending on direction */ - fileread.comp.type = (dir == SOF_IPC_STREAM_PLAYBACK) ? - SOF_COMP_HOST : SOF_COMP_DAI; - - /* create fileread component */ - register_comp(fileread.comp.type); - if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&fileread) < 0) { - fprintf(stderr, "error: comp register\n"); - return -EINVAL; - } - - free(fileread.fn); - return 0; -} - -/* load filewrite component */ -static int load_filewrite(struct sof *sof, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, - struct testbench_prm *tp) -{ - struct sof_ipc_comp_file filewrite; - int size = widget->priv.size; - int ret; - - ret = tplg_load_filewrite(comp_id, pipeline_id, size, &filewrite); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - /* configure filewrite */ - filewrite.fn = strdup(tp->output_file); - tp->fw_id = comp_id; - - /* Set format from testbench command line*/ - filewrite.rate = tp->fs_out; - filewrite.channels = tp->channels; - filewrite.frame_fmt = tp->frame_fmt; - - /* Set type depending on direction */ - filewrite.comp.type = (dir == SOF_IPC_STREAM_PLAYBACK) ? - SOF_COMP_DAI : SOF_COMP_HOST; - - /* create filewrite component */ - register_comp(filewrite.comp.type); - if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&filewrite) < 0) { - fprintf(stderr, "error: comp register\n"); - return -EINVAL; - } - - free(filewrite.fn); - return 0; -} - -int load_aif_in_out(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, void *tp) -{ - if (dir == SOF_IPC_STREAM_PLAYBACK) - return load_fileread(dev, comp_id, pipeline_id, widget, dir, - (struct testbench_prm *)tp); - - return load_filewrite(dev, comp_id, pipeline_id, widget, dir, - (struct testbench_prm *)tp); -} - -int load_dai_in_out(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, void *tp) -{ - if (dir == SOF_IPC_STREAM_PLAYBACK) - return load_filewrite(dev, comp_id, pipeline_id, widget, dir, - (struct testbench_prm *)tp); - - return load_fileread(dev, comp_id, pipeline_id, widget, dir, - (struct testbench_prm *)tp); -} - -/* load pda dapm widget */ -int load_pga(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct sof *sof = (struct sof *)dev; - struct sof_ipc_comp_volume volume = {}; - struct snd_soc_tplg_ctl_hdr *ctl = NULL; - struct snd_soc_tplg_mixer_control *mixer_ctl; - char *priv_data = NULL; - int32_t vol_min = 0; - int32_t vol_step = 0; - int32_t vol_maxs = 0; - float vol_min_db; - float vol_max_db; - int channels = 0; - int size = widget->priv.size; - int ret = 0; - - ret = tplg_load_pga(comp_id, pipeline_id, size, &volume, file); - if (ret < 0) - return ret; - - /* Only one control is supported*/ - if (widget->num_kcontrols > 1) { - fprintf(stderr, "error: more than one kcontrol defined\n"); - return -EINVAL; - } - - /* Get control into ctl and priv_data */ - if (widget->num_kcontrols) { - ret = tplg_load_one_control(&ctl, &priv_data, file); - if (ret < 0) { - fprintf(stderr, "error: failed control load\n"); - return ret; - } - - /* Get volume scale */ - mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl; - vol_min = (int32_t)mixer_ctl->hdr.tlv.scale.min; - vol_step = mixer_ctl->hdr.tlv.scale.step; - vol_maxs = mixer_ctl->max; - channels = mixer_ctl->num_channels; - } - - vol_min_db = 0.01 * vol_min; - vol_max_db = 0.01 * (vol_maxs * vol_step) + vol_min_db; - volume.min_value = round(pow(10, vol_min_db / 20.0) * 65535); - volume.max_value = round(pow(10, vol_max_db / 20.0) * 65536); - volume.channels = channels; - - free(ctl); - free(priv_data); - - /* load volume component */ - register_comp(volume.comp.type); - if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&volume) < 0) { - fprintf(stderr, "error: comp register\n"); - return -EINVAL; - } - - return 0; -} - -/* load scheduler dapm widget */ -int load_pipeline(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int sched_id) -{ - struct sof *sof = (struct sof *)dev; - struct sof_ipc_pipe_new pipeline; - int size = widget->priv.size; - int ret; - - ret = tplg_load_pipeline(comp_id, pipeline_id, size, &pipeline, file); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - pipeline.sched_id = sched_id; - - /* Create pipeline */ - if (ipc_pipeline_new(sof->ipc, &pipeline) < 0) { - fprintf(stderr, "error: pipeline new\n"); - return -EINVAL; - } - - return 0; -} - -/* load src dapm widget */ -int load_src(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, - void *params) -{ - struct testbench_prm *tp = (struct testbench_prm *)params; - struct sof *sof = (struct sof *)dev; - struct sof_ipc_comp_src src = {0}; - int size = widget->priv.size; - int ret = 0; - - ret = tplg_load_src(comp_id, pipeline_id, size, &src, file); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - /* set testbench input and output sample rate from topology */ - if (!tp->fs_out) { - tp->fs_out = src.sink_rate; - - if (!tp->fs_in) - tp->fs_in = src.source_rate; - else - src.source_rate = tp->fs_in; - } else { - src.sink_rate = tp->fs_out; - } - - /* load src component */ - register_comp(src.comp.type); - if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&src) < 0) { - fprintf(stderr, "error: new src comp\n"); - return -EINVAL; - } - - return ret; -} - -/* load asrc dapm widget */ -int load_asrc(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, - void *params) -{ - struct testbench_prm *tp = (struct testbench_prm *)params; - struct sof *sof = (struct sof *)dev; - struct sof_ipc_comp_asrc asrc = {0}; - int size = widget->priv.size; - int ret = 0; - - ret = tplg_load_asrc(comp_id, pipeline_id, size, &asrc, file); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - /* set testbench input and output sample rate from topology */ - if (!tp->fs_out) { - tp->fs_out = asrc.sink_rate; - - if (!tp->fs_in) - tp->fs_in = asrc.source_rate; - else - asrc.source_rate = tp->fs_in; - } else { - asrc.sink_rate = tp->fs_out; - } - - /* load asrc component */ - register_comp(asrc.comp.type); - if (ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)&asrc) < 0) { - fprintf(stderr, "error: new asrc comp\n"); - return -EINVAL; - } - - return ret; -} - -static int process_append_data(struct sof_ipc_comp_process **process_ipc, - struct sof_ipc_comp_process *process, - struct snd_soc_tplg_ctl_hdr *ctl, - char *priv_data) -{ - int ipc_size; - int size = 0; - struct snd_soc_tplg_bytes_control *bytes_ctl; - - /* Size is process IPC plus private data minus ABI header */ - ipc_size = sizeof(struct sof_ipc_comp_process); - if (ctl->ops.info == SND_SOC_TPLG_CTL_BYTES) { - bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl; - size = bytes_ctl->priv.size - sizeof(struct sof_abi_hdr); - ipc_size += size; - } - *process_ipc = malloc(ipc_size); - if (!(*process_ipc)) { - fprintf(stderr, "error: Failed to allocate IPC\n"); - return -ENOMEM; - } - - /* Copy header */ - memcpy(*process_ipc, process, sizeof(struct sof_ipc_comp_process)); - - /* Copy configuration data, need to strip ABI header*/ - memcpy((char *)*process_ipc + sizeof(struct sof_ipc_comp_process), - priv_data + sizeof(struct sof_abi_hdr), size); - (*process_ipc)->size = size; - return 0; -} - -/* load process dapm widget */ -int load_process(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct sof *sof = (struct sof *)dev; - struct sof_ipc_comp_process process = {0}; - struct sof_ipc_comp_process *process_ipc; - struct snd_soc_tplg_ctl_hdr *ctl = NULL; - char *priv_data = NULL; - int size; - int ret = 0; - - size = widget->priv.size; - ret = tplg_load_process(comp_id, pipeline_id, size, &process, file); - if (ret < 0) - return ret; - - if (process.comp.type == SOF_COMP_NONE) { - fprintf(stderr, "Invalid process comp type SOF_COMP_NONE\n"); - return -EINVAL; - } - - /* Only one control is supported*/ - if (widget->num_kcontrols > 1) { - fprintf(stderr, "error: more than one kcontrol defined\n"); - return -EINVAL; - } - - /* Get control into ctl and priv_data */ - if (widget->num_kcontrols) { - ret = tplg_load_one_control(&ctl, &priv_data, file); - if (ret < 0) { - fprintf(stderr, "error: failed control load\n"); - return ret; - } - } - - /* Merge process and priv_data into process_ipc */ - ret = process_append_data(&process_ipc, &process, ctl, priv_data); - free(ctl); - free(priv_data); - if (ret) { - fprintf(stderr, "error: private data append failed\n"); - return ret; - } - - /* load process component */ - register_comp(process_ipc->comp.type); - - /* Instantiate */ - ret = ipc_comp_new(sof->ipc, (struct sof_ipc_comp *)process_ipc); - free(process_ipc); - - if (ret < 0) - fprintf(stderr, "error: new process comp\n"); - - return ret; -} - -/* load mixer dapm widget */ -int load_mixer(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget) -{ - struct sof_ipc_comp_mixer mixer = {0}; - int size = widget->priv.size; - int ret = 0; - - ret = tplg_load_mixer(comp_id, pipeline_id, size, &mixer, file); - if (ret < 0) - return ret; - - if (tplg_load_controls(widget->num_kcontrols, file) < 0) { - fprintf(stderr, "error: loading controls\n"); - return -EINVAL; - } - - return ret; -} - -/* parse topology file and set up pipeline */ -int parse_topology(struct sof *sof, struct shared_lib_table *library_table, - struct testbench_prm *tp, char *pipeline_msg) -{ - struct snd_soc_tplg_hdr *hdr; - - struct comp_info *temp_comp_list = NULL; - char message[DEBUG_MSG_LEN]; - int next_comp_id = 0; - int num_comps = 0; - int i; - int ret = 0; - size_t file_size; - size_t size; - - /* open topology file */ - file = fopen(tp->tplg_file, "rb"); - if (!file) { - fprintf(stderr, "error: opening file %s\n", tp->tplg_file); - return -EINVAL; - } - - lib_table = library_table; - - /* file size */ - fseek(file, 0, SEEK_END); - file_size = ftell(file); - fseek(file, 0, SEEK_SET); - - /* allocate memory */ - size = sizeof(struct snd_soc_tplg_hdr); - hdr = (struct snd_soc_tplg_hdr *)malloc(size); - if (!hdr) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - debug_print("topology parsing start\n"); - while (1) { - /* read topology header */ - ret = fread(hdr, sizeof(struct snd_soc_tplg_hdr), 1, file); - if (ret != 1) - return -EINVAL; - - sprintf(message, "type: %x, size: 0x%x count: %d index: %d\n", - hdr->type, hdr->payload_size, hdr->count, hdr->index); - - debug_print(message); - - /* parse header and load the next block based on type */ - switch (hdr->type) { - /* load dapm widget */ - case SND_SOC_TPLG_TYPE_DAPM_WIDGET: - sprintf(message, "number of DAPM widgets %d\n", - hdr->count); - - debug_print(message); - - num_comps += hdr->count; - size = sizeof(struct comp_info) * num_comps; - temp_comp_list = (struct comp_info *) - realloc(temp_comp_list, size); - - for (i = (num_comps - hdr->count); i < num_comps; i++) { - ret = load_widget(sof, SOF_DEV, - temp_comp_list, - next_comp_id++, i, - hdr->index, tp, &tp->sched_id, - file); - if (ret < 0) { - printf("error: loading widget\n"); - goto finish; - } - } - break; - - /* set up component connections from pipeline graph */ - case SND_SOC_TPLG_TYPE_DAPM_GRAPH: - if (load_graph(sof, temp_comp_list, hdr->count, - num_comps, hdr->index) < 0) { - fprintf(stderr, "error: pipeline graph\n"); - return -EINVAL; - } - if (ftell(file) == file_size) - goto finish; - break; - default: - fseek(file, hdr->payload_size, SEEK_CUR); - if (ftell(file) == file_size) - goto finish; - break; - } - } -finish: - debug_print("topology parsing end\n"); - strcpy(pipeline_msg, pipeline_string); - - /* free all data */ - free(hdr); - - for (i = 0; i < num_comps; i++) - free(temp_comp_list[i].name); - - free(temp_comp_list); - fclose(file); - return ret; -} diff --git a/tools/testbench/topology_ipc3.c b/tools/testbench/topology_ipc3.c new file mode 100644 index 000000000000..b95dc9859e68 --- /dev/null +++ b/tools/testbench/topology_ipc3.c @@ -0,0 +1,761 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2024 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> + +/* Topology loader to set up components and pipeline */ + +#if CONFIG_IPC_MAJOR_3 + +#include <sof/audio/component.h> +#include <sof/ipc/driver.h> +#include <sof/ipc/topology.h> +#include <rtos/string.h> +#include <sof/common.h> +#include <sof/lib/uuid.h> +#include <tplg_parser/tokens.h> +#include <tplg_parser/topology.h> + +#include "testbench/utils.h" +#include "testbench/file.h" +#include "testbench/trace.h" + +#include <errno.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +#define MAX_TPLG_OBJECT_SIZE 4096 + +/* load asrc dapm widget */ +static int tb_register_asrc(struct testbench_prm *tp, struct tplg_context *ctx) +{ + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp *comp = (struct sof_ipc_comp *)tplg_object; + struct sof *sof = ctx->sof; + struct sof_ipc_comp_asrc *asrc; + int ret = 0; + + ret = tplg_new_asrc(ctx, comp, MAX_TPLG_OBJECT_SIZE, NULL, 0); + if (ret < 0) + return ret; + + asrc = (struct sof_ipc_comp_asrc *)comp; + + /* set testbench input and output sample rate from topology */ + if (!tp->fs_out) + tp->fs_out = asrc->sink_rate; + else + asrc->sink_rate = tp->fs_out; + + if (!tp->fs_in) + tp->fs_in = asrc->source_rate; + else + asrc->source_rate = tp->fs_in; + + /* load asrc component */ + if (ipc_comp_new(sof->ipc, ipc_to_comp_new(asrc)) < 0) { + fprintf(stderr, "error: new asrc comp\n"); + return -EINVAL; + } + + return ret; +} + +/* load buffer DAPM widget */ +static int tb_register_buffer(struct testbench_prm *tp, struct tplg_context *ctx) +{ + struct sof *sof = ctx->sof; + struct sof_ipc_buffer buffer = {{{0}}}; + int ret; + + ret = tplg_new_buffer(ctx, &buffer, sizeof(buffer), + NULL, 0); + if (ret < 0) + return ret; + + /* create buffer component */ + if (ipc_buffer_new(sof->ipc, &buffer) < 0) { + fprintf(stderr, "error: buffer new\n"); + return -EINVAL; + } + + return 0; +} + +/* load pipeline graph DAPM widget*/ +static int tb_register_graph(struct tplg_context *ctx, struct tplg_comp_info *temp_comp_list, + char *pipeline_string, + int num_comps, int num_connections, + int pipeline_id) +{ + struct sof_ipc_pipe_comp_connect connection; + struct sof *sof = ctx->sof; + int ret = 0; + int i; + + for (i = 0; i < num_connections; i++) { + ret = tplg_create_graph(ctx, num_comps, pipeline_id, temp_comp_list, + pipeline_string, &connection, i); + if (ret < 0) + return ret; + + /* connect source and sink */ + if (ipc_comp_connect(sof->ipc, ipc_to_pipe_connect(&connection)) < 0) { + fprintf(stderr, "error: comp connect\n"); + return -EINVAL; + } + } + + /* pipeline complete after pipeline connections are established */ + for (i = 0; i < num_comps; i++) { + if (temp_comp_list[i].pipeline_id == pipeline_id && + temp_comp_list[i].type == SND_SOC_TPLG_DAPM_SCHEDULER) + ipc_pipeline_complete(sof->ipc, temp_comp_list[i].id); + } + + return ret; +} + +/* load mixer dapm widget */ +static int tb_register_mixer(struct testbench_prm *tp, struct tplg_context *ctx) +{ + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp *comp = (struct sof_ipc_comp *)tplg_object; + struct sof *sof = ctx->sof; + int ret = 0; + + ret = tplg_new_mixer(ctx, comp, MAX_TPLG_OBJECT_SIZE, NULL, 0); + if (ret < 0) + return ret; + + /* load mixer component */ + if (ipc_comp_new(sof->ipc, ipc_to_comp_new(comp)) < 0) { + fprintf(stderr, "error: new mixer comp\n"); + ret = -EINVAL; + } + + return ret; +} + +static int tb_register_pga(struct testbench_prm *tp, struct tplg_context *ctx) +{ + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp *comp = (struct sof_ipc_comp *)tplg_object; + struct sof *sof = ctx->sof; + int ret; + + ret = tplg_new_pga(ctx, comp, MAX_TPLG_OBJECT_SIZE, NULL, 0); + if (ret < 0) { + fprintf(stderr, "error: failed to create PGA\n"); + return ret; + } + + /* load volume component */ + if (ipc_comp_new(sof->ipc, ipc_to_comp_new(comp)) < 0) { + fprintf(stderr, "error: new pga comp\n"); + ret = -EINVAL; + } + + return ret; +} + +/* load scheduler dapm widget */ +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}}; + int ret; + + ret = tplg_new_pipeline(ctx, &pipeline, sizeof(pipeline), NULL); + if (ret < 0) + return ret; + + pipeline.sched_id = ctx->sched_id; + + /* Create pipeline */ + if (ipc_pipeline_new(sof->ipc, (ipc_pipe_new *)&pipeline) < 0) { + fprintf(stderr, "error: pipeline new\n"); + return -EINVAL; + } + + return 0; +} + +/* load process dapm widget */ +static int tb_register_process(struct testbench_prm *tp, struct tplg_context *ctx) +{ + struct sof *sof = ctx->sof; + struct sof_ipc_comp_process *process; + int ret = 0; + + process = calloc(1, MAX_TPLG_OBJECT_SIZE); + if (!process) + return -ENOMEM; + + ret = tplg_new_process(ctx, process, MAX_TPLG_OBJECT_SIZE, NULL, 0); + if (ret < 0) + goto out; + + /* Instantiate */ + ret = ipc_comp_new(sof->ipc, ipc_to_comp_new(process)); + +out: + free(process); + if (ret < 0) + fprintf(stderr, "error: new process comp\n"); + + return ret; +} + +/* load src dapm widget */ +static int tb_register_src(struct testbench_prm *tp, struct tplg_context *ctx) +{ + struct sof *sof = ctx->sof; + char tplg_object[MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp *comp = (struct sof_ipc_comp *)tplg_object; + struct sof_ipc_comp_src *src; + int ret = 0; + + ret = tplg_new_src(ctx, comp, MAX_TPLG_OBJECT_SIZE, NULL, 0); + if (ret < 0) + return ret; + + src = (struct sof_ipc_comp_src *)comp; + + /* set testbench input and output sample rate from topology */ + if (!tp->fs_out) + tp->fs_out = src->sink_rate; + else + src->sink_rate = tp->fs_out; + + if (!tp->fs_in) + tp->fs_in = src->source_rate; + else + src->source_rate = tp->fs_in; + + /* load src component */ + if (ipc_comp_new(sof->ipc, ipc_to_comp_new(comp)) < 0) { + fprintf(stderr, "error: new src comp\n"); + return -EINVAL; + } + + return ret; +} + +/* load fileread component */ +static int tb_new_fileread(struct tplg_context *ctx, + struct sof_ipc_comp_file *fileread) +{ + struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0]; + size_t total_array_size = 0; + int size = ctx->widget->priv.size; + int comp_id = ctx->comp_id; + char uuid[UUID_SIZE]; + int ret; + + /* read vendor tokens */ + while (total_array_size < size) { + if (!tplg_is_valid_priv_size(total_array_size, size, array)) { + fprintf(stderr, "error: filewrite array size mismatch for widget size %d\n", + size); + return -EINVAL; + } + + /* parse comp tokens */ + ret = sof_parse_tokens(&fileread->config, comp_tokens, + ARRAY_SIZE(comp_tokens), array, + array->size); + if (ret != 0) { + fprintf(stderr, "error: parse comp tokens %d\n", + size); + return -EINVAL; + } + + /* parse uuid token */ + ret = sof_parse_tokens(uuid, comp_ext_tokens, + ARRAY_SIZE(comp_ext_tokens), array, + array->size); + if (ret != 0) { + fprintf(stderr, "error: parse mixer uuid token %d\n", size); + return -EINVAL; + } + + total_array_size += array->size; + array = MOVE_POINTER_BY_BYTES(array, array->size); + } + + /* configure fileread */ + fileread->mode = FILE_READ; + fileread->comp.id = comp_id; + + /* use fileread comp as scheduling comp */ + fileread->size = sizeof(struct ipc_comp_file); + fileread->comp.core = ctx->core_id; + fileread->comp.hdr.size = sizeof(struct sof_ipc_comp_file) + UUID_SIZE; + fileread->comp.type = SOF_COMP_FILEREAD; + fileread->comp.pipeline_id = ctx->pipeline_id; + fileread->config.hdr.size = sizeof(struct sof_ipc_comp_config); + fileread->comp.ext_data_length = UUID_SIZE; + return 0; +} + +/* load filewrite component */ +static int tb_new_filewrite(struct tplg_context *ctx, + struct sof_ipc_comp_file *filewrite) +{ + struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0]; + size_t total_array_size = 0; + int size = ctx->widget->priv.size; + int comp_id = ctx->comp_id; + char uuid[UUID_SIZE]; + int ret; + + /* read vendor tokens */ + while (total_array_size < size) { + if (!tplg_is_valid_priv_size(total_array_size, size, array)) { + fprintf(stderr, "error: filewrite array size mismatch\n"); + return -EINVAL; + } + + ret = sof_parse_tokens(&filewrite->config, comp_tokens, + ARRAY_SIZE(comp_tokens), array, + array->size); + if (ret != 0) { + fprintf(stderr, "error: parse filewrite tokens %d\n", + size); + return -EINVAL; + } + + /* parse uuid token */ + ret = sof_parse_tokens(uuid, comp_ext_tokens, + ARRAY_SIZE(comp_ext_tokens), array, + array->size); + if (ret != 0) { + fprintf(stderr, "error: parse mixer uuid token %d\n", size); + return -EINVAL; + } + + total_array_size += array->size; + array = MOVE_POINTER_BY_BYTES(array, array->size); + } + + /* configure filewrite */ + filewrite->comp.core = ctx->core_id; + filewrite->comp.id = comp_id; + filewrite->mode = FILE_WRITE; + filewrite->size = sizeof(struct ipc_comp_file); + filewrite->comp.hdr.size = sizeof(struct sof_ipc_comp_file) + UUID_SIZE; + filewrite->comp.type = SOF_COMP_FILEWRITE; + filewrite->comp.pipeline_id = ctx->pipeline_id; + filewrite->config.hdr.size = sizeof(struct sof_ipc_comp_config); + filewrite->comp.ext_data_length = UUID_SIZE; + return 0; +} + +/* load fileread component */ +static int tb_register_fileread(struct testbench_prm *tp, + struct tplg_context *ctx, int dir) +{ + struct sof *sof = ctx->sof; + struct sof_ipc_comp_file *fileread; + struct sof_uuid *file_uuid; + int ret; + + fileread = calloc(MAX_TPLG_OBJECT_SIZE, 1); + if (!fileread) + return -ENOMEM; + + fileread->config.frame_fmt = tplg_find_format(tp->bits_in); + + ret = tb_new_fileread(ctx, fileread); + if (ret < 0) + return ret; + + /* configure fileread */ + fileread->fn = strdup(tp->input_file[tp->input_file_index]); + tp->fr[tp->input_file_index].id = ctx->comp_id; + tp->fr[tp->input_file_index].instance_id = ctx->comp_id; + tp->fr[tp->input_file_index].pipeline_id = ctx->pipeline_id; + tp->input_file_index++; + + /* use fileread comp as scheduling comp */ + ctx->sched_id = ctx->comp_id; + + /* Set format from testbench command line*/ + fileread->rate = tp->fs_in; + fileread->channels = tp->channels_in; + fileread->frame_fmt = tp->frame_fmt; + fileread->direction = dir; + + file_uuid = (struct sof_uuid *)((uint8_t *)fileread + sizeof(struct sof_ipc_comp_file)); + memcpy(file_uuid, &tb_file_uuid, sizeof(*file_uuid)); + + /* create fileread component */ + if (ipc_comp_new(sof->ipc, ipc_to_comp_new(fileread)) < 0) { + fprintf(stderr, "error: file read\n"); + free(fileread->fn); + return -EINVAL; + } + + free(fileread->fn); + free(fileread); + return 0; +} + +/* load filewrite component */ +static int tb_register_filewrite(struct testbench_prm *tp, + struct tplg_context *ctx, int dir) +{ + struct sof *sof = ctx->sof; + struct sof_ipc_comp_file *filewrite; + struct sof_uuid *file_uuid; + int ret; + + filewrite = calloc(MAX_TPLG_OBJECT_SIZE, 1); + if (!filewrite) + return -ENOMEM; + + ret = tb_new_filewrite(ctx, filewrite); + if (ret < 0) + return ret; + + /* configure filewrite (multiple output files are supported.) */ + if (!tp->output_file[tp->output_file_index]) { + fprintf(stderr, "error: output[%d] file name is null\n", + tp->output_file_index); + return -EINVAL; + } + filewrite->fn = strdup(tp->output_file[tp->output_file_index]); + tp->fw[tp->output_file_index].id = ctx->comp_id; + tp->fw[tp->output_file_index].instance_id = ctx->comp_id; + tp->fw[tp->output_file_index].pipeline_id = ctx->pipeline_id; + tp->output_file_index++; + + /* Set format from testbench command line*/ + filewrite->rate = tp->fs_out; + filewrite->channels = tp->channels_out; + filewrite->frame_fmt = tp->frame_fmt; + filewrite->direction = dir; + + file_uuid = (struct sof_uuid *)((uint8_t *)filewrite + sizeof(struct sof_ipc_comp_file)); + memcpy(file_uuid, &tb_file_uuid, sizeof(*file_uuid)); + + /* create filewrite component */ + if (ipc_comp_new(sof->ipc, ipc_to_comp_new(filewrite)) < 0) { + fprintf(stderr, "error: new file write\n"); + free(filewrite->fn); + return -EINVAL; + } + + free(filewrite->fn); + free(filewrite); + return 0; +} + +static int tb_register_aif_in_out(struct testbench_prm *tb, + struct tplg_context *ctx, int dir) +{ + if (dir == SOF_IPC_STREAM_PLAYBACK) + return tb_register_fileread(tb, ctx, dir); + else + return tb_register_filewrite(tb, ctx, dir); +} + +static int tb_register_dai_in_out(struct testbench_prm *tb, + struct tplg_context *ctx, int dir) +{ + if (dir == SOF_IPC_STREAM_PLAYBACK) + return tb_register_filewrite(tb, ctx, dir); + else + return tb_register_fileread(tb, ctx, dir); +} + +/* + * create a list with all widget info + * containing mapping between component names and ids + * which will be used for setting up component connections + */ +static inline int tb_insert_comp(struct testbench_prm *tb, struct tplg_context *ctx) +{ + struct tplg_comp_info *temp_comp_list = tb->info; + int comp_index = tb->info_index; + int comp_id = ctx->comp_id; + + /* mapping should be empty */ + if (temp_comp_list[comp_index].name) { + fprintf(stderr, "comp index %d already in use with %d:%s cant insert %d:%s\n", + comp_index, + temp_comp_list[comp_index].id, temp_comp_list[comp_index].name, + ctx->widget->id, ctx->widget->name); + return -EINVAL; + } + + temp_comp_list[comp_index].id = comp_id; + temp_comp_list[comp_index].name = ctx->widget->name; + temp_comp_list[comp_index].type = ctx->widget->id; + temp_comp_list[comp_index].pipeline_id = ctx->pipeline_id; + + printf("debug: loading idx %d comp_id %d: widget %s type %d size %d at offset %ld\n", + comp_index, comp_id, ctx->widget->name, ctx->widget->id, ctx->widget->size, + ctx->tplg_offset); + + return 0; +} + +/* load dapm widget */ +static int tb_load_widget(struct testbench_prm *tb, struct tplg_context *ctx) +{ + struct tplg_comp_info *temp_comp_list = tb->info; + int comp_id = ctx->comp_id; + int ret = 0; + + /* get next widget */ + ctx->widget = tplg_get_widget(ctx); + ctx->widget_size = ctx->widget->size; + + if (!temp_comp_list) { + fprintf(stderr, "load_widget: temp_comp_list argument NULL\n"); + return -EINVAL; + } + + /* insert widget into mapping */ + ret = tb_insert_comp(tb, ctx); + if (ret < 0) { + fprintf(stderr, "plug_load_widget: invalid widget index\n"); + return ret; + } + + printf("debug: loading comp_id %d: widget %s id %d\n", + comp_id, ctx->widget->name, ctx->widget->id); + + /* load widget based on type */ + switch (ctx->widget->id) { + /* load pga widget */ + case SND_SOC_TPLG_DAPM_PGA: + if (tb_register_pga(tb, ctx) < 0) { + fprintf(stderr, "error: load pga\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_AIF_IN: + if (tb_register_aif_in_out(tb, ctx, SOF_IPC_STREAM_PLAYBACK) < 0) { + fprintf(stderr, "error: load AIF IN failed\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_AIF_OUT: + if (tb_register_aif_in_out(tb, ctx, SOF_IPC_STREAM_CAPTURE) < 0) { + fprintf(stderr, "error: load AIF OUT failed\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_DAI_IN: + if (tb_register_dai_in_out(tb, ctx, SOF_IPC_STREAM_PLAYBACK) < 0) { + fprintf(stderr, "error: load filewrite\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_DAI_OUT: + if (tb_register_dai_in_out(tb, ctx, SOF_IPC_STREAM_CAPTURE) < 0) { + fprintf(stderr, "error: load filewrite\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_BUFFER: + if (tb_register_buffer(tb, ctx) < 0) { + fprintf(stderr, "error: load buffer\n"); + ret = -EINVAL; + goto exit; + } + break; + + case SND_SOC_TPLG_DAPM_SCHEDULER: + if (tb_register_pipeline(tb, ctx) < 0) { + fprintf(stderr, "error: load pipeline\n"); + ret = -EINVAL; + goto exit; + } + break; + + case SND_SOC_TPLG_DAPM_SRC: + if (tb_register_src(tb, ctx) < 0) { + fprintf(stderr, "error: load src\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_ASRC: + if (tb_register_asrc(tb, ctx) < 0) { + fprintf(stderr, "error: load src\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_MIXER: + if (tb_register_mixer(tb, ctx) < 0) { + fprintf(stderr, "error: load mixer\n"); + ret = -EINVAL; + goto exit; + } + break; + case SND_SOC_TPLG_DAPM_EFFECT: + if (tb_register_process(tb, ctx) < 0) { + fprintf(stderr, "error: load effect\n"); + ret = -EINVAL; + goto exit; + } + break; + /* unsupported widgets */ + default: + if (tb_check_trace(LOG_LEVEL_DEBUG)) + printf("debug: Widget %s id %d unsupported and skipped: size %d priv size %d\n", + ctx->widget->name, ctx->widget->id, + ctx->widget->size, ctx->widget->priv.size); + break; + } + + ret = 1; + +exit: + return ret; +} + +/* parse topology file and set up pipeline */ +int tb_parse_topology(struct testbench_prm *tb) + +{ + struct tplg_context *ctx = &tb->tplg; + struct snd_soc_tplg_hdr *hdr; + struct tplg_comp_info *comp_list_realloc = NULL; + char pipeline_string[256] = {0}; + int i; + int ret = 0; + FILE *file; + size_t size; + + ctx->ipc_major = 3; + + /* open topology file */ + file = fopen(ctx->tplg_file, "rb"); + if (!file) { + fprintf(stderr, "error: can't open topology %s : %s\n", ctx->tplg_file, + strerror(errno)); + return -errno; + } + + /* file size */ + if (fseek(file, 0, SEEK_END)) { + fprintf(stderr, "error: can't seek to end of topology: %s\n", + strerror(errno)); + fclose(file); + return -errno; + } + ctx->tplg_size = ftell(file); + if (fseek(file, 0, SEEK_SET)) { + fprintf(stderr, "error: can't seek to beginning of topology: %s\n", + strerror(errno)); + fclose(file); + return -errno; + } + + /* load whole topology into memory */ + ctx->tplg_base = calloc(ctx->tplg_size, 1); + if (!ctx->tplg_base) { + fprintf(stderr, "error: can't alloc buffer for topology %zu bytes\n", + ctx->tplg_size); + fclose(file); + return -ENOMEM; + } + ret = fread(ctx->tplg_base, ctx->tplg_size, 1, file); + if (ret != 1) { + fprintf(stderr, "error: can't read topology: %s\n", + strerror(errno)); + free(ctx->tplg_base); + fclose(file); + return -errno; + } + fclose(file); + + while (ctx->tplg_offset < ctx->tplg_size) { + + /* read next topology header */ + hdr = tplg_get_hdr(ctx); + + tplg_debug("type: %x, size: 0x%x count: %d index: %d\n", + hdr->type, hdr->payload_size, hdr->count, hdr->index); + + ctx->hdr = hdr; + + /* parse header and load the next block based on type */ + switch (hdr->type) { + /* load dapm widget */ + case SND_SOC_TPLG_TYPE_DAPM_WIDGET: + + fprintf(stdout, "number of DAPM widgets %d\n", + hdr->count); + + /* update max pipeline_id */ + ctx->pipeline_id = hdr->index; + + tb->info_elems += hdr->count; + size = sizeof(struct tplg_comp_info) * tb->info_elems; + comp_list_realloc = (struct tplg_comp_info *) + realloc(tb->info, size); + + if (!comp_list_realloc && size) { + fprintf(stderr, "error: mem realloc\n"); + ret = -errno; + goto out; + } + tb->info = comp_list_realloc; + + for (i = (tb->info_elems - hdr->count); i < tb->info_elems; i++) + tb->info[i].name = NULL; + + for (tb->info_index = (tb->info_elems - hdr->count); + tb->info_index < tb->info_elems; + tb->info_index++) { + ret = tb_load_widget(tb, ctx); + if (ret < 0) { + printf("error: loading widget\n"); + goto out; + } else if (ret > 0) + ctx->comp_id++; + } + break; + + /* set up component connections from pipeline graph */ + case SND_SOC_TPLG_TYPE_DAPM_GRAPH: + if (tb_register_graph(ctx, tb->info, + pipeline_string, + tb->info_elems, + hdr->count, + hdr->index) < 0) { + fprintf(stderr, "error: pipeline graph\n"); + ret = -EINVAL; + goto out; + } + break; + + default: + tplg_skip_hdr_payload(ctx); + break; + } + } + +out: + /* free all data */ + free(tb->info); + free(ctx->tplg_base); + return ret; +} + +#endif /* CONFIG_IPC_MAJOR_3 */ diff --git a/tools/testbench/topology_ipc4.c b/tools/testbench/topology_ipc4.c new file mode 100644 index 000000000000..9c4900f92fed --- /dev/null +++ b/tools/testbench/topology_ipc4.c @@ -0,0 +1,1911 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2024 Intel Corporation, +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> +// Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +#if CONFIG_IPC_MAJOR_4 + +#include <ipc4/header.h> +#include <kernel/header.h> +#include <tplg_parser/tokens.h> +#include <tplg_parser/topology.h> +#include <module/ipc4/base-config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "testbench/utils.h" +#include "testbench/topology_ipc4.h" +#include "testbench/file.h" +#include "testbench/file_ipc4.h" +#include "testbench/trace.h" +#include "ipc4/pipeline.h" + +#define SOF_IPC4_FW_PAGE(x) ((((x) + BIT(12) - 1) & ~(BIT(12) - 1)) >> 12) +#define SOF_IPC4_FW_ROUNDUP(x) (((x) + BIT(6) - 1) & (~(BIT(6) - 1))) +#define SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE 12 +#define SOF_IPC4_PIPELINE_OBJECT_SIZE 448 +#define SOF_IPC4_DATA_QUEUE_OBJECT_SIZE 128 +#define SOF_IPC4_LL_TASK_OBJECT_SIZE 72 +#define SOF_IPC4_LL_TASK_LIST_ITEM_SIZE 12 +#define SOF_IPC4_FW_MAX_QUEUE_COUNT 8 + +static const struct sof_topology_token ipc4_comp_tokens[] = { + {SOF_TKN_COMP_IS_PAGES, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct ipc4_base_module_cfg, is_pages)}, +}; + +/* + * IPC + */ + +static int tb_ipc_message(void *mailbox, size_t bytes) +{ + struct ipc *ipc = ipc_get(); + + /* reply is copied back to mailbox */ + memcpy(ipc->comp_data, mailbox, bytes); + ipc_cmd(mailbox); + memcpy(mailbox, ipc->comp_data, bytes); + + return 0; +} + +static int tb_mq_cmd_tx_rx(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, + void *msg, size_t len, void *reply, size_t rlen) +{ + char mailbox[TB_IPC4_MAX_MSG_SIZE]; + struct ipc4_message_reply *reply_msg = reply; + + if (len > TB_IPC4_MAX_MSG_SIZE || rlen > TB_IPC4_MAX_MSG_SIZE) { + fprintf(stderr, "ipc: message too big len=%zu rlen=%zu\n", len, rlen); + return -EINVAL; + } + + memset(mailbox, 0, TB_IPC4_MAX_MSG_SIZE); + memcpy(mailbox, msg, len); + tb_ipc_message(mailbox, len); + memcpy(reply, mailbox, rlen); + if (reply_msg->primary.r.status != IPC4_SUCCESS) + return -EINVAL; + + return 0; +} + +static int tb_parse_ipc4_comp_tokens(struct testbench_prm *tp, + struct ipc4_base_module_cfg *base_cfg) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0]; + int size = ctx->widget->priv.size; + int ret; + + ret = sof_parse_token_sets(base_cfg, ipc4_comp_tokens, ARRAY_SIZE(ipc4_comp_tokens), + array, size, 1, 0); + if (ret < 0) + return ret; + + return sof_parse_tokens(&comp_info->uuid, comp_ext_tokens, + ARRAY_SIZE(comp_ext_tokens), array, size); +} + +static void tb_setup_widget_ipc_msg(struct tplg_comp_info *comp_info) +{ + struct ipc4_module_init_instance *module_init = &comp_info->module_init; + + module_init->primary.r.type = SOF_IPC4_MOD_INIT_INSTANCE; + module_init->primary.r.module_id = comp_info->module_id; + module_init->primary.r.instance_id = comp_info->instance_id; + module_init->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + module_init->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; +} + +int tb_set_up_widget_ipc(struct testbench_prm *tp, struct tplg_comp_info *comp_info) +{ + struct ipc4_module_init_instance *module_init = &comp_info->module_init; + struct ipc4_message_reply reply; + void *msg; + int size; + int ret = 0; + + module_init->extension.r.param_block_size = comp_info->ipc_size >> 2; + module_init->extension.r.ppl_instance_id = comp_info->pipe_info->instance_id; + + size = sizeof(*module_init) + comp_info->ipc_size; + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + memcpy(msg, module_init, sizeof(*module_init)); + memcpy(msg + sizeof(*module_init), comp_info->ipc_payload, comp_info->ipc_size); + ret = tb_mq_cmd_tx_rx(&tp->ipc_tx, &tp->ipc_rx, msg, size, &reply, sizeof(reply)); + + free(msg); + if (ret < 0) { + fprintf(stderr, "error: can't set up widget %s\n", comp_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "widget %s set up failed with status %d\n", + comp_info->name, reply.primary.r.status); + return -EINVAL; + } + return 0; +} + +int tb_set_up_route(struct testbench_prm *tp, struct tplg_route_info *route_info) +{ + struct tplg_comp_info *src_comp_info = route_info->source; + struct tplg_comp_info *sink_comp_info = route_info->sink; + struct ipc4_module_bind_unbind bu = {{0}}; + struct ipc4_message_reply reply; + int ret; + + bu.primary.r.module_id = src_comp_info->module_id; + bu.primary.r.instance_id = src_comp_info->instance_id; + bu.primary.r.type = SOF_IPC4_MOD_BIND; + bu.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + bu.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + + bu.extension.r.dst_module_id = sink_comp_info->module_id; + bu.extension.r.dst_instance_id = sink_comp_info->instance_id; + + /* FIXME: assign queue ID for components with multiple inputs/outputs */ + bu.extension.r.dst_queue = 0; + bu.extension.r.src_queue = 0; + + ret = tb_mq_cmd_tx_rx(&tp->ipc_tx, &tp->ipc_rx, &bu, sizeof(bu), &reply, sizeof(reply)); + if (ret < 0) { + fprintf(stderr, "error: can't set up route %s -> %s\n", src_comp_info->name, + sink_comp_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "route %s -> %s ID set up failed with status %d\n", + src_comp_info->name, sink_comp_info->name, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("route %s -> %s set up\n", src_comp_info->name, sink_comp_info->name); + + return 0; +} + +int tb_set_up_pipeline(struct testbench_prm *tp, struct tplg_pipeline_info *pipe_info) +{ + struct ipc4_pipeline_create msg = {.primary.dat = 0, .extension.dat = 0}; + struct ipc4_message_reply reply; + int ret; + + msg.primary.r.type = SOF_IPC4_GLB_CREATE_PIPELINE; + msg.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + pipe_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_SCHEDULER]++; + msg.primary.r.instance_id = pipe_info->instance_id; + msg.primary.r.ppl_mem_size = pipe_info->mem_usage; + ret = tb_mq_cmd_tx_rx(&tp->ipc_tx, &tp->ipc_rx, &msg, sizeof(msg), &reply, sizeof(reply)); + if (ret < 0) { + fprintf(stderr, "error: can't set up pipeline %s\n", pipe_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "pipeline %s instance ID %d set up failed with status %d\n", + pipe_info->name, pipe_info->instance_id, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("pipeline %s instance_id %d mem_usage %d set up\n", pipe_info->name, + pipe_info->instance_id, pipe_info->mem_usage); + + return 0; +} + +void tb_pipeline_update_resource_usage(struct testbench_prm *tp, + struct tplg_comp_info *comp_info) +{ + struct ipc4_base_module_cfg *base_config = &comp_info->basecfg; + struct tplg_pipeline_info *pipe_info = comp_info->pipe_info; + int task_mem, queue_mem; + int ibs, bss, total; + + ibs = base_config->ibs; + bss = base_config->is_pages; + + task_mem = SOF_IPC4_PIPELINE_OBJECT_SIZE; + task_mem += SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE + bss; + + /* LL modules */ + task_mem += SOF_IPC4_FW_ROUNDUP(SOF_IPC4_LL_TASK_OBJECT_SIZE); + task_mem += SOF_IPC4_FW_MAX_QUEUE_COUNT * SOF_IPC4_MODULE_INSTANCE_LIST_ITEM_SIZE; + task_mem += SOF_IPC4_LL_TASK_LIST_ITEM_SIZE; + + ibs = SOF_IPC4_FW_ROUNDUP(ibs); + queue_mem = SOF_IPC4_FW_MAX_QUEUE_COUNT * (SOF_IPC4_DATA_QUEUE_OBJECT_SIZE + ibs); + + total = SOF_IPC4_FW_PAGE(task_mem + queue_mem); + + pipe_info->mem_usage += total; +} + +/* + * IPC + */ + +int tb_is_single_format(struct sof_ipc4_pin_format *fmts, int num_formats) +{ + struct sof_ipc4_pin_format *fmt = &fmts[0]; + uint32_t _rate, _channels, _valid_bits; + int i; + + if (!fmt) { + fprintf(stderr, "Error: Null fmt\n"); + return false; + } + + _rate = fmt->audio_fmt.sampling_frequency; + _channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + _valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + for (i = 1; i < num_formats; i++) { + struct sof_ipc4_pin_format *fmt = &fmts[i]; + uint32_t rate, channels, valid_bits; + + rate = fmt->audio_fmt.sampling_frequency; + channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + if (rate != _rate || channels != _channels || valid_bits != _valid_bits) + return false; + } + + return true; +} + +int tb_match_audio_format(struct testbench_prm *tp, struct tplg_comp_info *comp_info, + struct tb_config *config) +{ + struct sof_ipc4_available_audio_format *available_fmt = &comp_info->available_fmt; + struct ipc4_base_module_cfg *base_cfg = &comp_info->basecfg; + struct sof_ipc4_pin_format *fmt; + int config_valid_bits; + int sample_bytes; + int i; + + switch (config->format) { + case SOF_IPC_FRAME_S16_LE: + config_valid_bits = 16; + break; + case SOF_IPC_FRAME_S32_LE: + config_valid_bits = 32; + break; + case SOF_IPC_FRAME_S24_4LE: + config_valid_bits = 24; + break; + default: + return -EINVAL; + } + + if (tb_is_single_format(available_fmt->input_pin_fmts, + available_fmt->num_input_formats)) { + fmt = &available_fmt->input_pin_fmts[0]; + goto out; + } + + for (i = 0; i < available_fmt->num_input_formats; i++) { + uint32_t rate, channels, valid_bits; + + fmt = &available_fmt->input_pin_fmts[i]; + + rate = fmt->audio_fmt.sampling_frequency; + channels = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + valid_bits = (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + + if (rate == config->rate && channels == config->channels && + valid_bits == config_valid_bits) + break; + } + + if (i == available_fmt->num_input_formats) { + fprintf(stderr, + "Cannot find matching format for rate %d channels %d valid_bits %d for %s\n", + config->rate, config->channels, config_valid_bits, comp_info->name); + return -EINVAL; + } +out: + + base_cfg->audio_fmt.sampling_frequency = fmt->audio_fmt.sampling_frequency; + base_cfg->audio_fmt.depth = fmt->audio_fmt.bit_depth; + base_cfg->audio_fmt.ch_map = fmt->audio_fmt.ch_map; + base_cfg->audio_fmt.ch_cfg = fmt->audio_fmt.ch_cfg; + base_cfg->audio_fmt.interleaving_style = fmt->audio_fmt.interleaving_style; + base_cfg->audio_fmt.channels_count = fmt->audio_fmt.fmt_cfg & MASK(7, 0); + base_cfg->audio_fmt.valid_bit_depth = + (fmt->audio_fmt.fmt_cfg & MASK(15, 8)) >> 8; + base_cfg->audio_fmt.s_type = + (fmt->audio_fmt.fmt_cfg & MASK(23, 16)) >> 16; + sample_bytes = fmt->audio_fmt.bit_depth >> 3; + base_cfg->ibs = 2 * tp->period_frames * base_cfg->audio_fmt.channels_count * sample_bytes; + base_cfg->obs = base_cfg->ibs; + + return 0; +} + +static int tb_set_pin_formats(struct tplg_comp_info *comp_info, + struct ipc4_base_module_cfg *base_cfg, + struct ipc4_base_module_cfg_ext *base_cfg_ext, + enum tb_pin_type pin_type) +{ + struct sof_ipc4_pin_format *formats_array; + struct sof_ipc4_pin_format *pin_format_item; + struct sof_ipc4_pin_format *pin_format; + struct sof_ipc4_pin_format *base_cfg_ext_pin_formats = + (struct sof_ipc4_pin_format *)base_cfg_ext->pin_formats; + int format_list_count; + int num_pins; + int i, j; + int pin_format_offset = 0; + + switch (pin_type) { + case TB_PIN_TYPE_INPUT: + num_pins = base_cfg_ext->nb_input_pins; + formats_array = comp_info->available_fmt.input_pin_fmts; + format_list_count = comp_info->available_fmt.num_input_formats; + break; + case TB_PIN_TYPE_OUTPUT: + num_pins = base_cfg_ext->nb_output_pins; + pin_format_offset = base_cfg_ext->nb_input_pins; + formats_array = comp_info->available_fmt.output_pin_fmts; + format_list_count = comp_info->available_fmt.num_output_formats; + break; + default: + fprintf(stderr, "Error: Illegal pin type %d for %s\n", pin_type, comp_info->name); + } + + for (i = pin_format_offset; i < num_pins + pin_format_offset; i++) { + pin_format = &base_cfg_ext_pin_formats[i]; + + if (i == pin_format_offset) { + if (pin_type == TB_PIN_TYPE_INPUT) { + pin_format->buffer_size = base_cfg->ibs; + /* Note: Copy "struct ipc4_audio_format" to + * "struct sof_ipc4_pin_format". They are same + * but separate definitions. The last member fmt_cfg + * is defined with bitfields for channels_count, valid_bit_depth, + * s_type, reservedin ipc4_audio_format. + */ + memcpy(&pin_format->audio_fmt, &base_cfg->audio_fmt, + sizeof(pin_format->audio_fmt)); + } else { + pin_format->buffer_size = base_cfg->obs; + /* TODO: Using workaround, need to find out how to do this. This + * is copied kernel function sof_ipc4_process_set_pin_formats() + * from process->output_format. It's set in + * sof_ipc4_prepare_process_module(). + */ + memcpy(&pin_format->audio_fmt, &base_cfg->audio_fmt, + sizeof(pin_format->audio_fmt)); + } + continue; + } + + for (j = 0; j < format_list_count; j++) { + pin_format_item = &formats_array[j]; + if (pin_format_item->pin_index == i - pin_format_offset) { + *pin_format = *pin_format_item; + break; + } + } + + if (j == format_list_count) { + fprintf(stderr, "%s pin %d format not found for %s\n", + (pin_type == TB_PIN_TYPE_INPUT) ? "input" : "output", + i - pin_format_offset, comp_info->name); + return -EINVAL; + } + } + + return 0; +} + +int tb_set_up_widget_base_config(struct testbench_prm *tp, struct tplg_comp_info *comp_info) +{ + char *config_name = tp->config[0].name; + struct ipc4_base_module_cfg *base_cfg; + struct ipc4_base_module_cfg_ext *base_cfg_ext; + struct tb_config *config; + struct tplg_pins_info *pins = &comp_info->pins_info; + bool config_found = false; + int ret, i; + + for (i = 0; i < tp->num_configs; i++) { + config = &tp->config[i]; + + if (!strcmp(config->name, config_name)) { + config_found = true; + break; + } + } + + if (!config_found) { + fprintf(stderr, "unsupported config requested %s\n", config_name); + return -ENOTSUP; + } + + /* match audio formats and populate base config */ + ret = tb_match_audio_format(tp, comp_info, config); + if (ret < 0) + return ret; + + /* copy the basecfg into the ipc payload */ + memcpy(comp_info->ipc_payload, &comp_info->basecfg, sizeof(struct ipc4_base_module_cfg)); + + /* Copy ext config for process type */ + if (comp_info->module_id == TB_PROCESS_MODULE_ID) { + base_cfg = comp_info->ipc_payload; + base_cfg_ext = comp_info->ipc_payload + sizeof(*base_cfg); + base_cfg_ext->nb_input_pins = pins->num_input_pins; + base_cfg_ext->nb_output_pins = pins->num_output_pins; + ret = tb_set_pin_formats(comp_info, base_cfg, base_cfg_ext, TB_PIN_TYPE_INPUT); + if (ret) + return ret; + + ret = tb_set_pin_formats(comp_info, base_cfg, base_cfg_ext, TB_PIN_TYPE_OUTPUT); + if (ret) + return ret; + } + + return 0; +} + +static int tb_pipeline_set_state(struct testbench_prm *tp, int state, + struct ipc4_pipeline_set_state *pipe_state, + struct tplg_pipeline_info *pipe_info, + struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx) +{ + struct ipc4_message_reply reply = {{ 0 }}; + int ret; + + pipe_state->primary.r.ppl_id = pipe_info->instance_id; + + ret = tb_mq_cmd_tx_rx(ipc_tx, ipc_rx, pipe_state, sizeof(*pipe_state), + &reply, sizeof(reply)); + if (ret < 0) + fprintf(stderr, "failed pipeline %d set state %d\n", pipe_info->instance_id, state); + + return ret; +} + +int tb_pipelines_set_state(struct testbench_prm *tp, int state, int dir) +{ + struct ipc4_pipeline_set_state pipe_state = {{ 0 }}; + struct tplg_pipeline_list *pipeline_list; + struct tplg_pipeline_info *pipe_info; + int ret; + int i; + + if (dir == SOF_IPC_STREAM_CAPTURE) + pipeline_list = &tp->pcm_info->capture_pipeline_list; + else + pipeline_list = &tp->pcm_info->playback_pipeline_list; + + pipe_state.primary.r.ppl_state = state; + pipe_state.primary.r.type = SOF_IPC4_GLB_SET_PIPELINE_STATE; + pipe_state.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + pipe_state.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + + /* + * pipeline list is populated starting from the host to DAI. So traverse the list in + * the reverse order for capture to start the source pipeline first. + */ + if (dir == SOF_IPC_STREAM_CAPTURE) { + for (i = pipeline_list->count - 1; i >= 0; i--) { + pipe_info = pipeline_list->pipelines[i]; + ret = tb_pipeline_set_state(tp, state, &pipe_state, pipe_info, + &tp->ipc_tx, &tp->ipc_rx); + if (ret < 0) + return ret; + } + + return 0; + } + + for (i = 0; i < pipeline_list->count; i++) { + pipe_info = pipeline_list->pipelines[i]; + ret = tb_pipeline_set_state(tp, state, &pipe_state, pipe_info, + &tp->ipc_tx, &tp->ipc_rx); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * Topology widgets + */ + +static int tb_new_src(struct testbench_prm *tp) +{ + struct ipc4_config_src src; + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + size_t uuid_offset; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + comp_info->ipc_size = sizeof(struct ipc4_config_src); + uuid_offset = comp_info->ipc_size; + comp_info->ipc_size += sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_EFFECT]++; + comp_info->module_id = TB_SRC_MODULE_ID; + + ret = tplg_new_src(ctx, &src, sizeof(struct ipc4_config_src), + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + fprintf(stderr, "error: failed to create SRC\n"); + goto out; + } + + /* copy volume data to ipc_payload */ + memcpy(comp_info->ipc_payload, &src, sizeof(struct ipc4_config_src)); + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + uuid_offset, &comp_info->uuid, sizeof(struct sof_uuid)); + + tb_setup_widget_ipc_msg(comp_info); + +out: + free(tplg_ctl); + return ret; +} + +static int tb_new_asrc(struct testbench_prm *tp) +{ + struct ipc4_asrc_module_cfg asrc; + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + size_t uuid_offset; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + comp_info->ipc_size = sizeof(struct ipc4_asrc_module_cfg); + uuid_offset = comp_info->ipc_size; + comp_info->ipc_size += sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_EFFECT]++; + comp_info->module_id = TB_ASRC_MODULE_ID; + + ret = tplg_new_asrc(ctx, &asrc, sizeof(struct ipc4_asrc_module_cfg), + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + fprintf(stderr, "error: failed to create SRC\n"); + goto out; + } + + /* copy volume data to ipc_payload */ + memcpy(comp_info->ipc_payload, &asrc, sizeof(struct ipc4_asrc_module_cfg)); + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + uuid_offset, &comp_info->uuid, sizeof(struct sof_uuid)); + + tb_setup_widget_ipc_msg(comp_info); + +out: + free(tplg_ctl); + return ret; +} + +static int tb_new_mixer(struct testbench_prm *tp) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + char tplg_object[TB_IPC4_MAX_TPLG_OBJECT_SIZE] = {0}; + struct sof_ipc_comp_mixer *mixer = (struct sof_ipc_comp_mixer *)tplg_object; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + int ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_MIXER]++; + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + ret = tplg_new_mixer(ctx, &mixer->comp, TB_IPC4_MAX_TPLG_OBJECT_SIZE, + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + fprintf(stderr, "error: failed to create mixer\n"); + goto out; + } + + if (strstr(comp_info->name, "mixin")) { + comp_info->module_id = TB_MIXIN_MODULE_ID; + tb_setup_widget_ipc_msg(comp_info); + } else { + comp_info->module_id = TB_MIXOUT_MODULE_ID; + tb_setup_widget_ipc_msg(comp_info); + } + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), &comp_info->uuid, + sizeof(struct sof_uuid)); + +out: + free(tplg_ctl); + return ret; +} + +static int tb_new_pipeline(struct testbench_prm *tp) +{ + struct tplg_pipeline_info *pipe_info; + struct sof_ipc_pipe_new pipeline = {{0}}; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + struct tplg_context *ctx = &tp->tplg; + int ret = 0; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + pipe_info = calloc(sizeof(struct tplg_pipeline_info), 1); + if (!pipe_info) { + ret = -ENOMEM; + goto out; + } + + pipe_info->name = strdup(ctx->widget->name); + if (!pipe_info->name) { + free(pipe_info); + goto out; + } + + pipe_info->id = ctx->pipeline_id; + + ret = tplg_new_pipeline(ctx, &pipeline, sizeof(pipeline), tplg_ctl); + if (ret < 0) { + fprintf(stderr, "error: failed to create pipeline\n"); + free(pipe_info->name); + free(pipe_info); + goto out; + } + + list_item_append(&pipe_info->item, &tp->pipeline_list); + tplg_debug("loading pipeline %s\n", pipe_info->name); +out: + free(tplg_ctl); + return ret; +} + +static int tb_new_buffer(struct testbench_prm *tp) +{ + struct ipc4_copier_module_cfg *copier = calloc(sizeof(struct ipc4_copier_module_cfg), 1); + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + int ret; + + if (!copier) + return -ENOMEM; + + comp_info->ipc_payload = copier; + + ret = tplg_new_buffer(ctx, copier, sizeof(copier), NULL, 0); + if (ret < 0) { + fprintf(stderr, "error: failed to create pipeline\n"); + free(copier); + } + + return ret; +} + +int tb_new_aif_in_out(struct testbench_prm *tp, int dir) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct ipc4_file_module_cfg *file; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + comp_info->ipc_size = sizeof(struct ipc4_file_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + if (dir == SOF_IPC_STREAM_PLAYBACK) { + /* Set from testbench command line*/ + file = (struct ipc4_file_module_cfg *)comp_info->ipc_payload; + file->config.mode = FILE_READ; + file->config.rate = tp->fs_in; + file->config.channels = tp->channels_in; + file->config.frame_fmt = tp->frame_fmt; + file->config.direction = dir; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_AIF_IN]++; + comp_info->module_id = TB_FILE_OUT_AIF_MODULE_ID; + if (tb_is_pipeline_enabled(tp, ctx->pipeline_id)) { + if (tp->input_file_index >= tp->input_file_num) { + fprintf(stderr, "error: not enough input files for aif\n"); + return -EINVAL; + } + file->config.fn = tp->input_file[tp->input_file_index]; + tp->fr[tp->input_file_index].id = comp_info->module_id; + tp->fr[tp->input_file_index].instance_id = comp_info->instance_id; + tp->fr[tp->input_file_index].pipeline_id = ctx->pipeline_id; + tp->input_file_index++; + } + + tb_setup_widget_ipc_msg(comp_info); + } else { + file = (struct ipc4_file_module_cfg *)comp_info->ipc_payload; + file->config.mode = FILE_WRITE; + file->config.rate = tp->fs_out; + file->config.channels = tp->channels_out; + file->config.frame_fmt = tp->frame_fmt; + file->config.direction = dir; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_AIF_OUT]++; + comp_info->module_id = TB_FILE_IN_AIF_MODULE_ID; + if (tb_is_pipeline_enabled(tp, ctx->pipeline_id)) { + if (tp->output_file_index >= tp->output_file_num) { + fprintf(stderr, "error: not enough output files for aif\n"); + return -EINVAL; + } + file->config.fn = tp->output_file[tp->output_file_index]; + tp->fw[tp->output_file_index].id = comp_info->module_id; + tp->fw[tp->output_file_index].instance_id = comp_info->instance_id; + tp->fw[tp->output_file_index].pipeline_id = ctx->pipeline_id; + tp->output_file_index++; + } + } + + tb_setup_widget_ipc_msg(comp_info); + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_file_module_cfg), &tb_file_uuid, + sizeof(struct sof_uuid)); + return 0; +} + +int tb_new_dai_in_out(struct testbench_prm *tp, int dir) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct ipc4_file_module_cfg *file; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + comp_info->ipc_size = sizeof(struct ipc4_file_module_cfg) + sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + if (dir == SOF_IPC_STREAM_PLAYBACK) { + /* Set from testbench command line*/ + file = (struct ipc4_file_module_cfg *)comp_info->ipc_payload; + file->config.mode = FILE_WRITE; + file->config.rate = tp->fs_out; + file->config.channels = tp->channels_out; + file->config.frame_fmt = tp->frame_fmt; + file->config.direction = dir; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_DAI_OUT]++; + comp_info->module_id = TB_FILE_OUT_DAI_MODULE_ID; + if (tb_is_pipeline_enabled(tp, ctx->pipeline_id)) { + if (tp->output_file_index >= tp->output_file_num) { + fprintf(stderr, "error: not enough output files for dai\n"); + return -EINVAL; + } + file->config.fn = tp->output_file[tp->output_file_index]; + tp->fw[tp->output_file_index].id = comp_info->module_id; + tp->fw[tp->output_file_index].instance_id = comp_info->instance_id; + tp->fw[tp->output_file_index].pipeline_id = ctx->pipeline_id; + tp->output_file_index++; + } + tb_setup_widget_ipc_msg(comp_info); + } else { + file = (struct ipc4_file_module_cfg *)comp_info->ipc_payload; + file->config.mode = FILE_READ; + file->config.rate = tp->fs_in; + file->config.channels = tp->channels_in; + file->config.frame_fmt = tp->frame_fmt; + file->config.direction = dir; + + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_DAI_IN]++; + comp_info->module_id = TB_FILE_IN_DAI_MODULE_ID; + if (tb_is_pipeline_enabled(tp, ctx->pipeline_id)) { + if (tp->input_file_index >= tp->input_file_num) { + fprintf(stderr, "error: not enough input files for dai\n"); + return -EINVAL; + } + file->config.fn = tp->input_file[tp->input_file_index]; + tp->fr[tp->input_file_index].id = comp_info->module_id; + tp->fr[tp->input_file_index].instance_id = comp_info->instance_id; + tp->fr[tp->input_file_index].pipeline_id = ctx->pipeline_id; + tp->input_file_index++; + } + } + + tb_setup_widget_ipc_msg(comp_info); + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_file_module_cfg), &tb_file_uuid, + sizeof(struct sof_uuid)); + return 0; +} + +int tb_new_pga(struct testbench_prm *tp) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct ipc4_peak_volume_config volume; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + size_t uuid_offset; + int ret; + + comp_info->ipc_size = sizeof(struct ipc4_peak_volume_config); + comp_info->ipc_size += sizeof(struct ipc4_base_module_cfg); + uuid_offset = comp_info->ipc_size; + comp_info->ipc_size += sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) + return -ENOMEM; + + /* FIXME: move this to when the widget is actually set up */ + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_PGA]++; + comp_info->module_id = TB_PGA_MODULE_ID; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) { + ret = -ENOMEM; + goto out; + } + + ret = tplg_new_pga(ctx, &volume, sizeof(struct ipc4_peak_volume_config), + tplg_ctl, ctx->hdr->payload_size); + if (ret < 0) { + fprintf(stderr, "error: failed to create PGA\n"); + goto out; + } + + /* copy volume data to ipc_payload */ + memcpy(comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg), + &volume, sizeof(struct ipc4_peak_volume_config)); + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + uuid_offset, &comp_info->uuid, sizeof(struct sof_uuid)); + + /* skip kcontrols for now */ + ret = tplg_create_controls(ctx, ctx->widget->num_kcontrols, tplg_ctl, + ctx->hdr->payload_size, comp_info); + if (ret < 0) { + fprintf(stderr, "error: loading controls\n"); + goto out; + } + + tb_setup_widget_ipc_msg(comp_info); + free(tplg_ctl); + return ret; + +out: + free(tplg_ctl); + free(comp_info->ipc_payload); + return ret; +} + +int tb_new_process(struct testbench_prm *tp) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct snd_soc_tplg_ctl_hdr *tplg_ctl; + struct tplg_pins_info *pins = &comp_info->pins_info; + size_t ext_size; + size_t uuid_offset; + int ret; + + ret = tplg_parse_widget_audio_formats(ctx); + if (ret < 0) + return ret; + + tplg_ctl = calloc(ctx->hdr->payload_size, 1); + if (!tplg_ctl) + return -ENOMEM; + + /* Ext config size */ + ext_size = ipc4_calc_base_module_cfg_ext_size(pins->num_input_pins, pins->num_output_pins); + + /* use base config variant with uuid */ + comp_info->ipc_size = sizeof(struct ipc4_base_module_cfg); + comp_info->ipc_size += ext_size; + uuid_offset = comp_info->ipc_size; + comp_info->ipc_size += sizeof(struct sof_uuid); + comp_info->ipc_payload = calloc(comp_info->ipc_size, 1); + if (!comp_info->ipc_payload) { + ret = ENOMEM; + goto out; + } + + /* FIXME: move this to when the widget is actually set up */ + comp_info->instance_id = tp->instance_ids[SND_SOC_TPLG_DAPM_EFFECT]++; + comp_info->module_id = TB_PROCESS_MODULE_ID; + + /* set up kcontrols */ + ret = tplg_create_controls(ctx, ctx->widget->num_kcontrols, tplg_ctl, + ctx->hdr->payload_size, comp_info); + if (ret < 0) { + fprintf(stderr, "error: loading controls\n"); + goto out; + } + + tb_setup_widget_ipc_msg(comp_info); + + /* copy uuid to the end of the payload */ + memcpy(comp_info->ipc_payload + uuid_offset, &comp_info->uuid, sizeof(struct sof_uuid)); + + /* TODO: drop tplg_ctl to avoid memory leak. Need to store and handle this + * to support controls. + */ + free(tplg_ctl); + return 0; + +out: + free(tplg_ctl); + free(comp_info->ipc_payload); + return ret; +} + +static int tb_register_graph(struct testbench_prm *tp, int count) +{ + struct tplg_context *ctx = &tp->tplg; + int ret = 0; + int i; + + for (i = 0; i < count; i++) { + ret = tplg_parse_graph(ctx, &tp->widget_list, &tp->route_list); + if (ret < 0) + return ret; + } + + return ret; +} + +static int tb_parse_pcm(struct testbench_prm *tp, int count) +{ + struct tplg_context *ctx = &tp->tplg; + int ret, i; + + for (i = 0; i < count; i++) { + ret = tplg_parse_pcm(ctx, &tp->widget_list, &tp->pcm_list); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * create a list with all widget info + * containing mapping between component names and ids + * which will be used for setting up component connections + */ +static inline int tb_insert_comp(struct testbench_prm *tp) +{ + struct tplg_context *ctx = &tp->tplg; + struct tplg_comp_info *comp_info; + int comp_id = ctx->comp_id; + int ret; + + if (ctx->widget->id == SND_SOC_TPLG_DAPM_SCHEDULER) + return 0; + + comp_info = calloc(sizeof(struct tplg_comp_info), 1); + if (!comp_info) + return -ENOMEM; + + comp_info->name = strdup(ctx->widget->name); + if (!comp_info->name) { + ret = -ENOMEM; + goto err; + } + + comp_info->stream_name = strdup(ctx->widget->sname); + if (!comp_info->stream_name) { + ret = -ENOMEM; + goto err; + } + + comp_info->id = comp_id; + comp_info->type = ctx->widget->id; + comp_info->pipeline_id = ctx->pipeline_id; + ctx->current_comp_info = comp_info; + + ret = tb_parse_ipc4_comp_tokens(tp, &comp_info->basecfg); + if (ret < 0) + goto err; + + list_item_append(&comp_info->item, &tp->widget_list); + + printf("debug: loading comp_id %d: pipeline_id %d: widget %s type %d size %d at offset %ld is_pages %d\n", + comp_id, ctx->pipeline_id, ctx->widget->name, ctx->widget->id, ctx->widget->size, + ctx->tplg_offset, comp_info->basecfg.is_pages); + + return 0; + +err: + free(comp_info->name); + free(comp_info); + return ret; +} + +/* load dapm widget */ +static int tb_load_widget(struct testbench_prm *tp) +{ + struct tplg_context *ctx = &tp->tplg; + int ret = 0; + + /* get next widget */ + ctx->widget = tplg_get_widget(ctx); + ctx->widget_size = ctx->widget->size; + + /* insert widget into mapping */ + ret = tb_insert_comp(tp); + if (ret < 0) { + fprintf(stderr, "tb_load_widget: invalid widget index\n"); + return ret; + } + + /* load widget based on type */ + switch (tp->tplg.widget->id) { + /* load pga widget */ + case SND_SOC_TPLG_DAPM_PGA: + if (tb_new_pga(tp) < 0) { + fprintf(stderr, "error: load pga\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_AIF_IN: + if (tb_new_aif_in_out(tp, SOF_IPC_STREAM_PLAYBACK) < 0) { + fprintf(stderr, "error: load AIF IN failed\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_AIF_OUT: + if (tb_new_aif_in_out(tp, SOF_IPC_STREAM_CAPTURE) < 0) { + fprintf(stderr, "error: load AIF OUT failed\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_DAI_IN: + if (tb_new_dai_in_out(tp, SOF_IPC_STREAM_PLAYBACK) < 0) { + fprintf(stderr, "error: load filewrite\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_DAI_OUT: + if (tb_new_dai_in_out(tp, SOF_IPC_STREAM_CAPTURE) < 0) { + fprintf(stderr, "error: load filewrite\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_BUFFER: + if (tb_new_buffer(tp) < 0) { + fprintf(stderr, "error: load buffer\n"); + return -EINVAL; + } + break; + + case SND_SOC_TPLG_DAPM_SCHEDULER: + if (tb_new_pipeline(tp) < 0) { + fprintf(stderr, "error: load pipeline\n"); + return -EINVAL; + } + break; + + case SND_SOC_TPLG_DAPM_SRC: + if (tb_new_src(tp) < 0) { + fprintf(stderr, "error: load src\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_ASRC: + if (tb_new_asrc(tp) < 0) { + fprintf(stderr, "error: load src\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_MIXER: + if (tb_new_mixer(tp) < 0) { + fprintf(stderr, "error: load mixer\n"); + return -EINVAL; + } + break; + case SND_SOC_TPLG_DAPM_EFFECT: + if (tb_new_process(tp) < 0) { + fprintf(stderr, "error: load effect\n"); + return -EINVAL; + } + break; + + /* unsupported widgets */ + default: + if (tb_check_trace(LOG_LEVEL_DEBUG)) + printf("Widget %s id %d unsupported and skipped: size %d priv size %d\n", + ctx->widget->name, ctx->widget->id, + ctx->widget->size, ctx->widget->priv.size); + break; + } + + return 0; +} + +#define SOF_IPC4_VOL_ZERO_DB 0x7fffffff +#define VOLUME_FWL 16 +/* + * Constants used in the computation of linear volume gain + * from dB gain 20th root of 10 in Q1.16 fixed-point notation + */ +#define VOL_TWENTIETH_ROOT_OF_TEN 73533 +/* 40th root of 10 in Q1.16 fixed-point notation*/ +#define VOL_FORTIETH_ROOT_OF_TEN 69419 + +/* 0.5 dB step value in topology TLV */ +#define VOL_HALF_DB_STEP 50 + +/* + * Function to truncate an unsigned 64-bit number + * by x bits and return 32-bit unsigned number. This + * function also takes care of rounding while truncating + */ +static uint32_t vol_shift_64(uint64_t i, uint32_t x) +{ + if (x == 0) + return (uint32_t)i; + + /* do not truncate more than 32 bits */ + if (x > 32) + x = 32; + + return (uint32_t)(((i >> (x - 1)) + 1) >> 1); +} + +/* + * Function to compute a ** exp where, + * a is a fractional number represented by a fixed-point integer with a fractional word length + * of "fwl" + * exp is an integer + * fwl is the fractional word length + * Return value is a fractional number represented by a fixed-point integer with a fractional + * word length of "fwl" + */ +static uint32_t vol_pow32(uint32_t a, int exp, uint32_t fwl) +{ + int i, iter; + uint32_t power = 1 << fwl; + unsigned long long numerator; + + /* if exponent is 0, return 1 */ + if (exp == 0) + return power; + + /* determine the number of iterations based on the exponent */ + if (exp < 0) + iter = exp * -1; + else + iter = exp; + + /* multiply a "iter" times to compute power */ + for (i = 0; i < iter; i++) { + /* + * Product of 2 Qx.fwl fixed-point numbers yields a Q2*x.2*fwl + * Truncate product back to fwl fractional bits with rounding + */ + power = vol_shift_64((uint64_t)power * a, fwl); + } + + if (exp > 0) { + /* if exp is positive, return the result */ + return power; + } + + /* if exp is negative, return the multiplicative inverse */ + numerator = (uint64_t)1 << (fwl << 1); + numerator /= power; + + return (uint32_t)numerator; +} + +/* + * Function to calculate volume gain from TLV data. + * This function can only handle gain steps that are multiples of 0.5 dB + */ +static uint32_t vol_compute_gain(uint32_t value, struct snd_soc_tplg_tlv_dbscale *scale) +{ + int dB_gain; + uint32_t linear_gain; + int f_step; + + /* mute volume */ + if (value == 0 && scale->mute) + return 0; + + /* compute dB gain from tlv. tlv_step in topology is multiplied by 100 */ + dB_gain = (int)scale->min / 100 + (value * scale->step) / 100; + + /* compute linear gain represented by fixed-point int with VOLUME_FWL fractional bits */ + linear_gain = vol_pow32(VOL_TWENTIETH_ROOT_OF_TEN, dB_gain, VOLUME_FWL); + + /* extract the fractional part of volume step */ + f_step = scale->step - (scale->step / 100); + + /* if volume step is an odd multiple of 0.5 dB */ + if (f_step == VOL_HALF_DB_STEP && (value & 1)) + linear_gain = vol_shift_64((uint64_t)linear_gain * VOL_FORTIETH_ROOT_OF_TEN, + VOLUME_FWL); + + return linear_gain; +} + +/* helper function to add new kcontrols to the list of kcontrols */ +static int tb_kcontrol_cb_new(struct snd_soc_tplg_ctl_hdr *tplg_ctl, + void *comp, void *arg, int index) +{ + struct tplg_comp_info *comp_info = comp; + struct testbench_prm *tp = arg; + struct tb_glb_state *glb = &tp->glb_ctx; + struct tb_ctl *ctl; + struct snd_soc_tplg_mixer_control *tplg_mixer; + struct snd_soc_tplg_enum_control *tplg_enum; + struct snd_soc_tplg_bytes_control *tplg_bytes; + struct sof_abi_hdr *abi; + + if (glb->num_ctls >= TB_MAX_CTLS) { + fprintf(stderr, "Error: Too many controls already.\n"); + return -EINVAL; + } + + fprintf(stderr, "Info: Found control type %d: %s\n", tplg_ctl->type, tplg_ctl->name); + + switch (tplg_ctl->ops.info) { + case SND_SOC_TPLG_CTL_RANGE: + case SND_SOC_TPLG_CTL_STROBE: + fprintf(stderr, "Warning: Not supported ctl type %d\n", tplg_ctl->type); + return 0; + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + tplg_mixer = (struct snd_soc_tplg_mixer_control *)tplg_ctl; + struct snd_soc_tplg_ctl_tlv *tlv; + struct snd_soc_tplg_tlv_dbscale *scale; + int i; + + glb->size += sizeof(struct tb_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->mixer_ctl = *tplg_mixer; + ctl->index = index; + ctl->type = tplg_ctl->type; + tlv = &tplg_ctl->tlv; + scale = &tlv->scale; + ctl->comp_info = comp_info; + strncpy(ctl->name, tplg_ctl->name, TB_MAX_CTL_NAME_CHARS); + + /* populate the volume table */ + for (i = 0; i < tplg_mixer->max + 1 ; i++) { + uint32_t val = vol_compute_gain(i, scale); + + /* Can be over Q1.31, need to saturate */ + uint64_t q31val = ((uint64_t)val) << 15; + + ctl->volume_table[i] = q31val > SOF_IPC4_VOL_ZERO_DB ? + SOF_IPC4_VOL_ZERO_DB : q31val; + } + break; + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_CTL_ENUM_VALUE: + tplg_enum = (struct snd_soc_tplg_enum_control *)tplg_ctl; + glb->size += sizeof(struct tb_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->enum_ctl = *tplg_enum; + ctl->index = index; + ctl->type = tplg_ctl->type; + ctl->comp_info = comp_info; + strncpy(ctl->name, tplg_ctl->name, TB_MAX_CTL_NAME_CHARS); + break; + case SND_SOC_TPLG_CTL_BYTES: + { + tplg_bytes = (struct snd_soc_tplg_bytes_control *)tplg_ctl; + glb->size += sizeof(struct tb_ctl); + ctl = &glb->ctl[glb->num_ctls++]; + ctl->module_id = comp_info->module_id; + ctl->instance_id = comp_info->instance_id; + ctl->bytes_ctl = *tplg_bytes; + ctl->index = index; + ctl->type = tplg_ctl->type; + if (tplg_bytes->priv.size > TB_MAX_BYTES_DATA_SIZE) { + fprintf(stderr, "Error: Too large bytes data size %d\n", + tplg_bytes->priv.size); + return -EINVAL; + } + + if (tplg_bytes->priv.size >= sizeof(struct sof_abi_hdr)) { + abi = (struct sof_abi_hdr *)tplg_bytes->priv.data; + if (abi->size > TB_MAX_BYTES_DATA_SIZE) { + fprintf(stderr, + "Error: ABI payload size %u exceeds max %d\n", + abi->size, TB_MAX_BYTES_DATA_SIZE); + return -EINVAL; + } + if (tplg_bytes->priv.size < + sizeof(struct sof_abi_hdr) + abi->size) { + fprintf(stderr, + "Error: bytes data size %d is smaller than ABI header + payload (%zu + %u)\n", + tplg_bytes->priv.size, + sizeof(struct sof_abi_hdr), abi->size); + return -EINVAL; + } + ctl->data = tplg_bytes->priv.data; + } + + ctl->comp_info = comp_info; + strncpy(ctl->name, tplg_ctl->name, TB_MAX_CTL_NAME_CHARS); + break; + } + default: + fprintf(stderr, "Error: Invalid ctl type %d\n", tplg_ctl->type); + return -EINVAL; + } + + return 0; +} + +/* parse topology file and set up pipeline */ +int tb_parse_topology(struct testbench_prm *tp) + +{ + struct tplg_context *ctx = &tp->tplg; + struct snd_soc_tplg_hdr *hdr; + struct list_item *item; + int i; + int ret = 0; + FILE *file; + + ctx->ipc_major = 4; + ctx->ctl_arg = tp; + ctx->ctl_cb = tb_kcontrol_cb_new; + tp->glb_ctx.ctl = calloc(TB_MAX_CTLS, sizeof(struct tb_ctl)); + if (!tp->glb_ctx.ctl) { + fprintf(stderr, "error: failed to allocate for controls.\n"); + return -ENOMEM; + } + + /* open topology file */ + file = fopen(ctx->tplg_file, "rb"); + if (!file) { + fprintf(stderr, "error: can't open topology %s : %s\n", ctx->tplg_file, + strerror(errno)); + return -errno; + } + + /* file size */ + if (fseek(file, 0, SEEK_END)) { + fprintf(stderr, "error: can't seek to end of topology: %s\n", + strerror(errno)); + fclose(file); + return -errno; + } + ctx->tplg_size = ftell(file); + if (fseek(file, 0, SEEK_SET)) { + fprintf(stderr, "error: can't seek to beginning of topology: %s\n", + strerror(errno)); + fclose(file); + return -errno; + } + + /* load whole topology into memory */ + ctx->tplg_base = calloc(ctx->tplg_size, 1); + if (!ctx->tplg_base) { + fprintf(stderr, "error: can't alloc buffer for topology %zu bytes\n", + ctx->tplg_size); + fclose(file); + return -ENOMEM; + } + ret = fread(ctx->tplg_base, ctx->tplg_size, 1, file); + if (ret != 1) { + fprintf(stderr, "error: can't read topology: %s\n", strerror(errno)); + free(ctx->tplg_base); + fclose(file); + return -errno; + } + fclose(file); + + /* initialize widget, route, pipeline and pcm lists */ + list_init(&tp->widget_list); + list_init(&tp->route_list); + list_init(&tp->pcm_list); + list_init(&tp->pipeline_list); + + while (ctx->tplg_offset < ctx->tplg_size) { + /* read next topology header */ + hdr = tplg_get_hdr(ctx); + + tplg_debug("type: %x, size: 0x%x count: %d index: %d\n", + hdr->type, hdr->payload_size, hdr->count, hdr->index); + + ctx->hdr = hdr; + + /* parse header and load the next block based on type */ + switch (hdr->type) { + /* load dapm widget */ + case SND_SOC_TPLG_TYPE_DAPM_WIDGET: + + tplg_debug("number of DAPM widgets %d\n", hdr->count); + + /* update max pipeline_id */ + ctx->pipeline_id = hdr->index; + + for (i = 0; i < hdr->count; i++) { + ret = tb_load_widget(tp); + if (ret < 0) { + fprintf(stderr, "error: loading widget\n"); + goto out; + } + ctx->comp_id++; + } + break; + + /* set up component connections from pipeline graph */ + case SND_SOC_TPLG_TYPE_DAPM_GRAPH: + ret = tb_register_graph(tp, hdr->count); + if (ret < 0) { + fprintf(stderr, "error: pipeline graph\n"); + goto out; + } + break; + + case SND_SOC_TPLG_TYPE_PCM: + ret = tb_parse_pcm(tp, hdr->count); + if (ret < 0) { + fprintf(stderr, "error: parsing pcm\n"); + goto out; + } + break; + + default: + tplg_skip_hdr_payload(ctx); + break; + } + } + + /* assign pipeline to every widget in the widget list */ + list_for_item(item, &tp->widget_list) { + struct tplg_comp_info *comp_info = container_of(item, struct tplg_comp_info, item); + struct list_item *pipe_item; + + list_for_item(pipe_item, &tp->pipeline_list) { + struct tplg_pipeline_info *pipe_info; + + pipe_info = container_of(pipe_item, struct tplg_pipeline_info, item); + if (pipe_info->id == comp_info->pipeline_id) { + comp_info->pipe_info = pipe_info; + break; + } + } + + if (!comp_info->pipe_info) { + fprintf(stderr, "warning: failed assigning pipeline for %s\n", + comp_info->name); + } + } + + return 0; + +out: + /* free all data */ + free(ctx->tplg_base); + return ret; +} + +/* + * To run + */ + +int tb_set_running_state(struct testbench_prm *tp) +{ + int ret; + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_PAUSED, SOF_IPC_STREAM_PLAYBACK); + if (ret) { + fprintf(stderr, "error: failed to set state to paused\n"); + return ret; + } + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_PAUSED, SOF_IPC_STREAM_CAPTURE); + if (ret) { + fprintf(stderr, "error: failed to set state to paused\n"); + return ret; + } + + tb_debug_print("pipelines are set to paused state\n"); + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_RUNNING, SOF_IPC_STREAM_PLAYBACK); + if (ret) { + fprintf(stderr, "error: failed to set state to running\n"); + return ret; + } + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_RUNNING, SOF_IPC_STREAM_CAPTURE); + if (ret) + fprintf(stderr, "error: failed to set state to running\n"); + + tb_debug_print("pipelines are set to running state\n"); + return ret; +} + +/* + * To stop + */ + +int tb_set_reset_state(struct testbench_prm *tp) +{ + int ret; + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_PAUSED, SOF_IPC_STREAM_PLAYBACK); + if (ret) { + fprintf(stderr, "error: failed to set state to paused\n"); + return ret; + } + + tb_schedule_pipeline_check_state(tp); + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_RESET, SOF_IPC_STREAM_PLAYBACK); + if (ret) { + fprintf(stderr, "error: failed to set state to reset\n"); + return ret; + } + + tb_schedule_pipeline_check_state(tp); + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_PAUSED, SOF_IPC_STREAM_CAPTURE); + if (ret) { + fprintf(stderr, "error: failed to set state to paused\n"); + return ret; + } + + tb_schedule_pipeline_check_state(tp); + + ret = tb_pipelines_set_state(tp, SOF_IPC4_PIPELINE_STATE_RESET, SOF_IPC_STREAM_CAPTURE); + if (ret) + fprintf(stderr, "error: failed to set state to reset\n"); + + tb_schedule_pipeline_check_state(tp); + return ret; +} + +int tb_delete_pipeline(struct testbench_prm *tp, struct tplg_pipeline_info *pipe_info) +{ + struct ipc4_pipeline_delete msg = {{0}}; + struct ipc4_message_reply reply; + int ret; + + msg.primary.r.type = SOF_IPC4_GLB_DELETE_PIPELINE; + msg.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG; + msg.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + msg.primary.r.instance_id = pipe_info->instance_id; + + ret = tb_mq_cmd_tx_rx(&tp->ipc_tx, &tp->ipc_rx, &msg, sizeof(msg), &reply, sizeof(reply)); + if (ret < 0) { + fprintf(stderr, "error: can't delete pipeline %s\n", pipe_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "pipeline %s instance ID %d delete failed with status %d\n", + pipe_info->name, pipe_info->instance_id, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("pipeline %s instance_id %d freed\n", pipe_info->name, + pipe_info->instance_id); + + return 0; +} + +int tb_free_route(struct testbench_prm *tp, struct tplg_route_info *route_info) +{ + struct tplg_comp_info *src_comp_info = route_info->source; + struct tplg_comp_info *sink_comp_info = route_info->sink; + struct ipc4_module_bind_unbind bu = {{0}}; + struct ipc4_message_reply reply; + int ret; + + /* only unbind when widgets belong to separate pipelines */ + if (src_comp_info->pipeline_id == sink_comp_info->pipeline_id) + return 0; + + bu.primary.r.module_id = src_comp_info->module_id; + bu.primary.r.instance_id = src_comp_info->instance_id; + bu.primary.r.type = SOF_IPC4_MOD_UNBIND; + bu.primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + bu.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + + bu.extension.r.dst_module_id = sink_comp_info->module_id; + bu.extension.r.dst_instance_id = sink_comp_info->instance_id; + + /* FIXME: assign queue ID for components with multiple inputs/outputs */ + bu.extension.r.dst_queue = 0; + bu.extension.r.src_queue = 0; + + ret = tb_mq_cmd_tx_rx(&tp->ipc_tx, &tp->ipc_rx, &bu, sizeof(bu), &reply, sizeof(reply)); + if (ret < 0) { + fprintf(stderr, "error: can't set up route %s -> %s\n", src_comp_info->name, + sink_comp_info->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "route %s -> %s ID set up failed with status %d\n", + src_comp_info->name, sink_comp_info->name, reply.primary.r.status); + return -EINVAL; + } + + tplg_debug("route %s -> %s freed\n", src_comp_info->name, sink_comp_info->name); + + return 0; +} + +static void tb_ctl_ipc_message(struct ipc4_module_large_config *config, int param_id, + size_t offset_or_size, uint32_t module_id, uint32_t instance_id, + uint32_t type) +{ + config->primary.r.type = type; + config->primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_MODULE_MSG; + config->primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST; + config->primary.r.module_id = module_id; + config->primary.r.instance_id = instance_id; + + config->extension.r.data_off_size = offset_or_size; + config->extension.r.large_param_id = param_id; +} + +int tb_send_bytes_data(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, + uint32_t module_id, uint32_t instance_id, struct sof_abi_hdr *abi) +{ + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_message_reply reply; + void *msg; + int ret; + size_t chunk_size; + size_t msg_size; + size_t msg_size_full = sizeof(config) + abi->size; + size_t remaining = abi->size; + size_t payload_limit = TB_IPC4_MAX_MSG_SIZE - sizeof(config); + size_t offset = 0; + + /* allocate memory for IPC message */ + msg_size = MIN(msg_size_full, TB_IPC4_MAX_MSG_SIZE); + msg = calloc(msg_size, 1); + if (!msg) + return -ENOMEM; + + config.extension.r.init_block = 1; + + /* configure the IPC message */ + tb_ctl_ipc_message(&config, abi->type, remaining, module_id, instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + + do { + if (remaining > payload_limit) { + chunk_size = payload_limit; + } else { + chunk_size = remaining; + config.extension.r.final_block = 1; + } + + if (offset) { + config.extension.r.init_block = 0; + tb_ctl_ipc_message(&config, abi->type, offset, module_id, instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + } + + /* set the IPC message data */ + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), (char *)abi->data + offset, chunk_size); + + /* send the message and check status */ + ret = tb_mq_cmd_tx_rx(ipc_tx, ipc_rx, msg, chunk_size + sizeof(config), + &reply, sizeof(reply)); + if (ret < 0) { + fprintf(stderr, "Error: Failed to send IPC to set bytes data.\n"); + goto out; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "Error: Failed with status %d.\n", reply.primary.r.status); + ret = -EINVAL; + goto out; + } + + offset += chunk_size; + remaining -= chunk_size; + } while (remaining); + +out: + free(msg); + return ret; +} + +int tb_send_volume_control(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, + struct tb_ctl *ctl, int *control_values, int num_values) +{ + struct ipc4_module_large_config config = {{ 0 }}; + struct ipc4_peak_volume_config volume; + struct ipc4_message_reply reply; + struct ipc4_peak_volume_config *volume_config; + void *msg; + bool all_channels_equal = true; + int max_val; + int size; + int ret; + int val; + int i; + + volume_config = ctl->comp_info->ipc_payload + sizeof(struct ipc4_base_module_cfg); + max_val = ctl->mixer_ctl.max; + val = control_values[0]; + for (i = 0; i < num_values; i++) { + if (i > 0 && control_values[i] != val) + all_channels_equal = false; + + if (control_values[i] < 0 || control_values[i] > max_val) { + fprintf(stderr, "error: control value %d is illegal.\n", control_values[i]); + return -EINVAL; + } + } + + for (i = 0; i < num_values; i++) { + if (all_channels_equal) { + volume.channel_id = IPC4_ALL_CHANNELS_MASK; + volume.target_volume = ctl->volume_table[val]; + } else { + volume.channel_id = i; + volume.target_volume = ctl->volume_table[control_values[i]]; + } + + /* get curve duration and type from topology */ + volume.curve_type = volume_config->curve_type; + volume.curve_duration = volume_config->curve_duration; + + /* configure the IPC message */ + tb_ctl_ipc_message(&config, IPC4_VOLUME, sizeof(volume), ctl->module_id, + ctl->instance_id, SOF_IPC4_MOD_LARGE_CONFIG_SET); + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + size = sizeof(config) + sizeof(volume); + msg = calloc(size, 1); + if (!msg) + return -ENOMEM; + + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), &volume, sizeof(volume)); + + /* send the message and check status */ + ret = tb_mq_cmd_tx_rx(ipc_tx, ipc_rx, msg, size, &reply, sizeof(reply)); + free(msg); + if (ret < 0) { + fprintf(stderr, "failed to set volume control %s\n", ctl->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "volume control %s set failed with status %d\n", + ctl->name, reply.primary.r.status); + return -EINVAL; + } + + if (all_channels_equal) + break; + } + + return 0; +} + +int tb_send_alsa_control(struct tb_mq_desc *ipc_tx, struct tb_mq_desc *ipc_rx, + struct tb_ctl *ctl, int *control_values, int num_values, int param_id) +{ + struct ipc4_module_large_config config = {{ 0 }}; + struct sof_ipc4_control_msg_payload *data; + struct ipc4_message_reply reply; + void *msg; + int data_size; + int msg_size; + int ret; + int i; + + /* size of control data */ + data_size = num_values * sizeof(struct sof_ipc4_ctrl_value_chan) + sizeof(*data); + + /* allocate memory for control data */ + data = calloc(data_size, 1); + if (!data) + return -ENOMEM; + + /* set param ID and number of channels */ + data->id = ctl->index; + data->num_elems = num_values; + + /* set the enum values */ + for (i = 0; i < data->num_elems; i++) { + data->chanv[i].channel = i; + data->chanv[i].value = control_values[i]; + } + + /* configure the IPC message */ + tb_ctl_ipc_message(&config, param_id, data_size, ctl->module_id, ctl->instance_id, + SOF_IPC4_MOD_LARGE_CONFIG_SET); + config.extension.r.final_block = 1; + config.extension.r.init_block = 1; + + /* allocate memory for IPC message */ + msg_size = sizeof(config) + data_size; + msg = calloc(msg_size, 1); + if (!msg) { + free(data); + return -ENOMEM; + } + + /* set the IPC message data */ + memcpy(msg, &config, sizeof(config)); + memcpy(msg + sizeof(config), data, data_size); + free(data); + + /* send the message and check status */ + ret = tb_mq_cmd_tx_rx(ipc_tx, ipc_rx, msg, msg_size, &reply, sizeof(reply)); + free(msg); + if (ret < 0) { + fprintf(stderr, "error: failed to set control %s\n", ctl->name); + return ret; + } + + if (reply.primary.r.status != IPC4_SUCCESS) { + fprintf(stderr, "error: control %s set failed with status %d\n", + ctl->name, reply.primary.r.status); + return -EINVAL; + } + + return 0; +} + +#endif /* CONFIG_IPC_MAJOR_4 */ diff --git a/tools/testbench/trace.c b/tools/testbench/trace.c deleted file mode 100644 index 9e07432db5b4..000000000000 --- a/tools/testbench/trace.c +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -// Liam Girdwood <liam.r.girdwood@linux.intel.com> -// Keyon Jie <yang.jie@linux.intel.com> -// Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -#include <stdint.h> -#include "testbench/common_test.h" -#include "testbench/trace.h" - -/* enable trace by default in testbench */ -int test_bench_trace = 1; -int debug; - -#define CASE(x) case TRACE_CLASS_##x: return #x - -/* look up subsystem class name from table */ -char *get_trace_class(uint32_t trace_class) -{ - switch (trace_class) { - CASE(IRQ); - CASE(IPC); - CASE(PIPE); - CASE(DAI); - CASE(DMA); - CASE(COMP); - CASE(WAIT); - CASE(LOCK); - CASE(MEM); - CASE(BUFFER); - CASE(SA); - CASE(POWER); - CASE(IDC); - CASE(CPU); - CASE(CLK); - CASE(EDF); - CASE(SCHEDULE); - CASE(SCHEDULE_LL); - CASE(CHMAP); - CASE(NOTIFIER); - CASE(MN); - CASE(PROBE); - default: return "unknown"; - } -} - -/* print debug messages */ -void debug_print(char *message) -{ - if (debug) - printf("debug: %s", message); -} - -/* enable trace in testbench */ -void tb_enable_trace(bool enable) -{ - test_bench_trace = enable; - if (enable) - debug_print("trace print enabled\n"); - else - debug_print("trace print disabled\n"); -} diff --git a/tools/testbench/utils.c b/tools/testbench/utils.c new file mode 100644 index 000000000000..597e3aaa043d --- /dev/null +++ b/tools/testbench/utils.c @@ -0,0 +1,586 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2024 Intel Corporation. All rights reserved. + +#include <sof/audio/module_adapter/module/generic.h> +#include <platform/lib/ll_schedule.h> +#include <sof/audio/component.h> +#include <sof/ipc/topology.h> +#include <sof/ipc/msg.h> +#include <sof/ipc/notification_pool.h> +#include <sof/lib/notifier.h> + +#include <ctype.h> +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#include "testbench/utils.h" +#include "testbench/trace.h" +#include "testbench/file.h" + +#if defined __XCC__ +#include <xtensa/tie/xt_timer.h> +#endif + +int tb_load_topology(struct testbench_prm *tp) +{ + struct tplg_context *ctx = &tp->tplg; + int ret; + + /* setup the thread virtual core config */ + memset(ctx, 0, sizeof(*ctx)); + ctx->comp_id = 1; + ctx->core_id = 0; + ctx->sof = sof_get(); + ctx->tplg_file = tp->tplg_file; + + /* parse topology file and create pipeline */ + ret = tb_parse_topology(tp); + if (ret < 0) + fprintf(stderr, "error: parsing topology\n"); + + tb_debug_print("topology parsing complete\n"); + return ret; +} + +static int tb_find_file_helper(struct testbench_prm *tp, struct file_comp_lookup fcl[], + int num_files) +{ + struct ipc_comp_dev *icd; + struct processing_module *mod; + struct file_comp_data *fcd; + int i; + + for (i = 0; i < num_files; i++) { + if (!tb_is_pipeline_enabled(tp, fcl[i].pipeline_id)) { + fcl[i].id = -1; + continue; + } + + icd = ipc_get_comp_by_id(sof_get()->ipc, fcl[i].id); + if (!icd) { + fcl[i].state = NULL; + continue; + } + + if (!icd->cd) { + fprintf(stderr, "error: null cd.\n"); + return -EINVAL; + } + + mod = comp_mod(icd->cd); + if (!mod) { + fprintf(stderr, "error: null module.\n"); + return -EINVAL; + } + fcd = get_file_comp_data(module_get_private_data(mod)); + fcl[i].state = &fcd->fs; + } + + return 0; +} + +int tb_find_file_components(struct testbench_prm *tp) +{ + int ret; + + /* file read */ + ret = tb_find_file_helper(tp, tp->fr, tp->input_file_num); + if (ret < 0) + return ret; + + /* file write */ + ret = tb_find_file_helper(tp, tp->fw, tp->output_file_num); + return ret; +} + +static bool tb_is_file_component_at_eof(struct testbench_prm *tp) +{ + int i; + + for (i = 0; i < tp->input_file_num; i++) { + if (!tp->fr[i].state) + continue; + + if (tp->fr[i].state->reached_eof || tp->fr[i].state->copy_timeout) + return true; + } + + for (i = 0; i < tp->output_file_num; i++) { + if (!tp->fw[i].state) + continue; + + if (tp->fw[i].state->reached_eof || tp->fw[i].state->copy_timeout || + tp->fw[i].state->write_failed) + return true; + } + + return false; +} + +void tb_show_file_stats(struct testbench_prm *tp, int pipeline_id) +{ + struct ipc_comp_dev *icd; + struct comp_dev *dev; + struct processing_module *mod; + struct file_comp_data *fcd; + int i; + + for (i = 0; i < tp->input_file_num; i++) { + if (tp->fr[i].id < 0 || tp->fr[i].pipeline_id != pipeline_id) + continue; + + icd = ipc_get_comp_by_id(sof_get()->ipc, tp->fr[i].id); + if (!icd) + continue; + + dev = icd->cd; + mod = comp_mod(dev); + fcd = get_file_comp_data(module_get_private_data(mod)); + printf("file %s: id %d: type %d: samples %d copies %d\n", + fcd->fs.fn, dev->ipc_config.id, dev->drv->type, fcd->fs.n, + fcd->fs.copy_count); + } + + for (i = 0; i < tp->output_file_num; i++) { + if (tp->fw[i].id < 0 || tp->fw[i].pipeline_id != pipeline_id) + continue; + + icd = ipc_get_comp_by_id(sof_get()->ipc, tp->fw[i].id); + if (!icd) + continue; + + dev = icd->cd; + mod = comp_mod(dev); + fcd = get_file_comp_data(module_get_private_data(mod)); + printf("file %s: id %d: type %d: samples %d copies %d\n", + fcd->fs.fn, dev->ipc_config.id, dev->drv->type, fcd->fs.n, + fcd->fs.copy_count); + } +} + +bool tb_is_pipeline_enabled(struct testbench_prm *tp, int pipeline_id) +{ + int i; + + for (i = 0; i < tp->pipeline_num; i++) { + if (tp->pipelines[i] == pipeline_id) + return true; + } + + return false; +} + +bool tb_schedule_pipeline_check_state(struct testbench_prm *tp) +{ + uint64_t cycles0, cycles1; + + tb_getcycles(&cycles0); + + schedule_ll_run_tasks(); + + tb_getcycles(&cycles1); + tp->total_cycles += cycles1 - cycles0; + + /* Check if all file components are running */ + return tb_is_file_component_at_eof(tp); +} + +struct ipc_data { + struct ipc_data_host_buffer dh_buffer; +}; + +void tb_free(struct sof *sof) +{ + struct schedule_data *sch; + struct schedulers **schedulers; + struct list_item *slist, *_slist; + struct notify **notify = arch_notify_get(); + struct ipc_data *iipc; + + free(*notify); + + /* free all scheduler data */ + schedule_free(0); + schedulers = arch_schedulers_get(); + list_for_item_safe(slist, _slist, &(*schedulers)->list) { + sch = container_of(slist, struct schedule_data, list); + list_item_del(slist); + free(sch); + } + free(*arch_schedulers_get()); + + /* Drain IPC message queue to free queued notifications */ + while (!list_is_empty(&sof->ipc->msg_list)) + ipc_send_queued_msg(); + + /* Free notification pool items */ + ipc_notification_pool_free(); + + /* free IPC data */ + iipc = sof->ipc->private; + free(sof->ipc->comp_data); + free(iipc->dh_buffer.page_table); + free(iipc); + free(sof->ipc); +} + +/* print debug messages */ +void tb_debug_print(char *message) +{ + if (host_trace_level >= LOG_LEVEL_DEBUG) + printf("debug: %s", message); +} + +/* enable trace in testbench */ +void tb_enable_trace(unsigned int log_level) +{ + host_trace_level = log_level; + if (host_trace_level >= LOG_LEVEL_DEBUG) + tb_debug_print("Verbose trace print enabled\n"); +} + +/* Helper to control messages print */ +bool tb_check_trace(unsigned int log_level) +{ + return host_trace_level >= log_level; +} + +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 +} + +static void tb_trim_line(char *new, char *line) +{ + int i = 0; + int j = 0; + int n = strlen(line); + bool in_quotes = false; + + /* Trim begin */ + while (isspace((int)line[i]) && i < n) + i++; + + /* Copy line with multiple blanks removed, change single quotes to + * double quotes, don't remove blanks from inside quotes. + */ + while (i < n) { + if (!isspace((int)line[i])) { + if (line[i] == '\'') + new[j] = '\"'; + else + new[j] = line[i]; + if (new[j] == '\"') + in_quotes = !in_quotes; + j++; + i++; + } else if (in_quotes || ((i + 1) < n && !isspace((int)line[i + 1]))) { + new[j] = ' '; + j++; + i++; + } else { + i++; + } + } + new[j] = 0; +} + +static int tb_parse_sleep(char *line, int64_t *sleep_ns) +{ + char *token = strtok(line, "sleep "); + + *sleep_ns = (int64_t)(atof(token) * 1e9); + printf("Info: Next control will be applied after %lld ns.\n", (long long)*sleep_ns); + return 0; +} + +int tb_decode_enum(struct snd_soc_tplg_enum_control *enum_ctl, char *token) +{ + int enum_items = enum_ctl->items; + int i; + + for (i = 0; i < enum_items; i++) { + if (strcmp(enum_ctl->texts[i], token) == 0) + return i; + } + + return -EINVAL; +} + +static struct tb_ctl *tb_find_control_by_name(struct testbench_prm *tp, char *name) +{ + struct tb_glb_state *glb = &tp->glb_ctx; + struct tb_ctl *ctl; + int i; + + for (i = 0; i < glb->num_ctls; i++) { + ctl = &glb->ctl[i]; + if (strcmp(ctl->name, name) == 0) + return ctl; + } + + return NULL; +} + +static int tb_parse_amixer(struct testbench_prm *tp, char *line) +{ + char *line_end; + char *name_str; + char *end_str; + char control_name[TB_MAX_CTL_NAME_CHARS] = {0}; + char control_params[TB_MAX_CTL_NAME_CHARS] = {0}; + char *find_cset_name_str = "cset name=\""; + char *find_end_str = "\" "; + int find_len = strlen(find_cset_name_str); + int find_end_len = strlen(find_end_str); + int len; + struct tb_ctl *ctl; + int ret; + + name_str = strstr(line, find_cset_name_str); + if (!name_str) { + fprintf(stderr, "error: no control name in script line: %s\n", line); + return -EINVAL; + } + + end_str = strstr(&name_str[find_len], find_end_str); + if (!end_str) { + fprintf(stderr, "error: no control name end quote in script line: %s\n", line); + return -EINVAL; + } + + len = end_str - name_str - find_len; + memcpy(control_name, name_str + find_len, len); + + line_end = line + strlen(line); + len = line_end - end_str - find_end_len; + memcpy(control_params, &end_str[find_end_len], len); + + printf("Info: Setting control name '%s' to value (%s)\n", control_name, control_params); + + ctl = tb_find_control_by_name(tp, control_name); + if (!ctl) { + fprintf(stderr, "error: control %s not found in topology.\n", control_name); + return -EINVAL; + } + + switch (ctl->type) { + case SND_SOC_TPLG_TYPE_MIXER: + ret = tb_set_mixer_control(tp, ctl, control_params); + break; + case SND_SOC_TPLG_TYPE_ENUM: + ret = tb_set_enum_control(tp, ctl, control_params); + break; + default: + fprintf(stderr, "error: control %s type %d is not supported.\n", + control_name, ctl->type); + ret = -EINVAL; + } + + return ret; +} + +static int tb_parse_sofctl(struct testbench_prm *tp, char *line) +{ + struct tb_ctl *ctl; + uint32_t *blob_bin = NULL; + char *blob_name = NULL; + char *blob_str = NULL; + char *control_name = NULL; + char *end; + char *find_ctl_name_str = "-c name=\""; + char *find_end_str = "\" "; + char *find_set_switch_str = "-s"; + char *name_str; + char *rest; + char *token; + int copy_len; + int find_len = strlen(find_ctl_name_str); + int n = 0; + int ret = 0; + FILE *fh; + + name_str = strstr(line, find_ctl_name_str); + if (!name_str) { + fprintf(stderr, "error: no control name in script line: %s\n", line); + return -EINVAL; + } + + end = strstr(&name_str[find_len], find_end_str); + if (!end) { + fprintf(stderr, "error: no control name end quote in script line: %s\n", line); + return -EINVAL; + } + + copy_len = end - name_str - find_len; + control_name = strndup(name_str + find_len, copy_len); + if (!control_name) { + fprintf(stderr, "error: failed to duplicate control name.\n"); + return -errno; + } + + name_str = strstr(line, find_set_switch_str); + if (!name_str) { + fprintf(stderr, "error: no sof-ctl control set switch in command: %s.\n", + line); + ret = -EINVAL; + goto err; + } + + name_str += strlen(find_set_switch_str) + 1; + end = line + strlen(line); + copy_len = end - name_str; + blob_name = strndup(name_str, copy_len); + if (!blob_name) { + fprintf(stderr, "error: failed to duplicate blob name.\n"); + ret = -errno; + goto err; + } + + ctl = tb_find_control_by_name(tp, control_name); + if (!ctl) { + fprintf(stderr, "error: control %s not found in topology.\n", control_name); + ret = -EINVAL; + goto err; + } + + if (ctl->type != SND_SOC_TPLG_TYPE_BYTES) { + fprintf(stderr, "error: control %s type %d is not supported.\n", + control_name, ctl->type); + ret = -EINVAL; + goto err; + } + + blob_str = malloc(TB_MAX_BLOB_CONTENT_CHARS); + if (!blob_str) { + fprintf(stderr, "error: failed to allocate memory for blob file content.\n"); + ret = -ENOMEM; + goto err; + } + + blob_bin = malloc(TB_MAX_BYTES_DATA_SIZE); + if (!blob_bin) { + fprintf(stderr, "error: failed to allocate memory for blob data.\n"); + ret = -ENOMEM; + goto err; + } + + printf("Info: Setting control name '%s' to blob '%s'\n", control_name, blob_name); + fh = fopen(blob_name, "r"); + if (!fh) { + fprintf(stderr, "error: could not open file.\n"); + ret = -errno; + goto err; + } + + end = fgets(blob_str, TB_MAX_BLOB_CONTENT_CHARS, fh); + fclose(fh); + if (!end) { + fprintf(stderr, "error: failed to read data from blob file.\n"); + ret = -ENODATA; + goto err; + } + + rest = blob_str; + while ((token = strtok_r(rest, ",", &rest))) { + if (n == TB_MAX_BYTES_DATA_SIZE) { + fprintf(stderr, "error: data read exceeds max control data size.\n"); + ret = -EINVAL; + goto err; + } + + blob_bin[n] = atoi(token); + n++; + } + + if (n < 2) { + fprintf(stderr, "error: at least two values are required in the blob file.\n"); + ret = -EINVAL; + goto err; + } + + /* Ignore TLV header from beginning. */ + ret = tb_set_bytes_control(tp, ctl, &blob_bin[2]); + +err: + free(blob_str); + free(blob_bin); + free(blob_name); + free(control_name); + return ret; +} + +int tb_read_controls(struct testbench_prm *tp, int64_t *sleep_ns) +{ + char *sleep_cmd = "sleep "; + char *amixer_cmd = "amixer "; + char *sofctl_cmd = "sof-ctl "; + char *raw_line; + char *line; + int ret = 0; + + *sleep_ns = 0; + if (!tp->control_fh) + return 0; + + raw_line = malloc(TB_MAX_CMD_CHARS); + assert(raw_line); + + line = malloc(TB_MAX_CMD_CHARS); + assert(line); + + while (fgets(raw_line, TB_MAX_CMD_CHARS, tp->control_fh)) { + tb_trim_line(line, raw_line); + if (line[0] == '#' || strlen(line) == 0) + continue; + + if (strncmp(line, sleep_cmd, strlen(sleep_cmd)) == 0) { + ret = tb_parse_sleep(line, sleep_ns); + if (ret) { + fprintf(stderr, "error: failed parse of sleep command.\n"); + break; + } + break; + } + + if (strncmp(line, amixer_cmd, strlen(amixer_cmd)) == 0) { + ret = tb_parse_amixer(tp, line); + if (ret) { + fprintf(stderr, "error: failed parse of amixer command.\n"); + break; + } + continue; + } + + if (strncmp(line, sofctl_cmd, strlen(sofctl_cmd)) == 0) { + ret = tb_parse_sofctl(tp, line); + if (ret) { + fprintf(stderr, "error: failed parse of sof-ctl command.\n"); + break; + } + continue; + } + } + + free(line); + free(raw_line); + return ret; +} diff --git a/tools/testbench/utils_ipc3.c b/tools/testbench/utils_ipc3.c new file mode 100644 index 000000000000..32c368efeb9a --- /dev/null +++ b/tools/testbench/utils_ipc3.c @@ -0,0 +1,449 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2024 Intel Corporation. All rights reserved. + +#if CONFIG_IPC_MAJOR_3 + +#include <sof/audio/component_ext.h> +#include <sof/lib/notifier.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <platform/lib/ll_schedule.h> + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "testbench/utils.h" +#include "testbench/file.h" +#include "testbench/trace.h" + +/* testbench helper functions for pipeline setup and trigger */ + +int tb_setup(struct sof *sof, struct testbench_prm *tp) +{ + struct ll_schedule_domain domain = {0}; + + /* init components */ + sys_comp_init(sof); + sys_comp_selector_init(); + + /* Module adapter components */ + sys_comp_module_crossover_interface_init(); + sys_comp_module_dcblock_interface_init(); + sys_comp_module_demux_interface_init(); + sys_comp_module_dolby_dax_audio_processing_interface_init(); + sys_comp_module_drc_interface_init(); + sys_comp_module_eq_fir_interface_init(); + sys_comp_module_eq_iir_interface_init(); + sys_comp_module_file_interface_init(); + sys_comp_module_google_rtc_audio_processing_interface_init(); + sys_comp_module_igo_nr_interface_init(); + sys_comp_module_mfcc_interface_init(); + sys_comp_module_multiband_drc_interface_init(); + sys_comp_module_mux_interface_init(); + sys_comp_module_rtnr_interface_init(); + sys_comp_module_src_interface_init(); + sys_comp_module_asrc_interface_init(); + sys_comp_module_tdfb_interface_init(); + sys_comp_module_volume_interface_init(); + + /* other necessary initializations, todo: follow better SOF init */ + pipeline_posn_init(sof); + init_system_notify(sof); + tb_enable_trace(tp->trace_level); + + /* init IPC */ + if (ipc_init(sof) < 0) { + fprintf(stderr, "error: IPC init\n"); + return -EINVAL; + } + + /* init LL scheduler */ + if (scheduler_init_ll(&domain) < 0) { + fprintf(stderr, "error: edf scheduler init\n"); + return -EINVAL; + } + + /* init EDF scheduler */ + if (scheduler_init_edf() < 0) { + fprintf(stderr, "error: edf scheduler init\n"); + return -EINVAL; + } + + tb_debug_print("ipc and scheduler initialized\n"); + + return 0; +} + +/* Get pipeline host component */ +static struct comp_dev *tb_get_pipeline_host(struct pipeline *p) +{ + struct comp_dev *cd; + + cd = p->source_comp; + if (cd->direction == SOF_IPC_STREAM_CAPTURE) + cd = p->sink_comp; + + return cd; +} + +/* set up pcm params, prepare and trigger pipeline */ +int tb_pipeline_start(struct ipc *ipc, struct pipeline *p) +{ + struct comp_dev *cd; + int ret; + + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); + + /* Component prepare */ + ret = pipeline_prepare(p, cd); + if (ret < 0) { + fprintf(stderr, "error: Failed prepare pipeline command: %s\n", + strerror(ret)); + return ret; + } + + /* Start the pipeline */ + ret = pipeline_trigger(cd->pipeline, cd, COMP_TRIGGER_PRE_START); + if (ret < 0) { + fprintf(stderr, "error: Failed to start pipeline command: %s\n", + strerror(ret)); + return ret; + } + + return ret; +} + +/* set up pcm params, prepare and trigger pipeline */ +int tb_pipeline_stop(struct ipc *ipc, struct pipeline *p) +{ + struct comp_dev *cd; + int ret; + + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); + + ret = pipeline_trigger(cd->pipeline, cd, COMP_TRIGGER_STOP); + if (ret < 0) { + fprintf(stderr, "error: Failed to stop pipeline command: %s\n", + strerror(ret)); + } + + return ret; +} + +/* set up pcm params, prepare and trigger pipeline */ +int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p) +{ + struct comp_dev *cd; + int ret; + + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); + + ret = pipeline_reset(p, cd); + if (ret < 0) + fprintf(stderr, "error: pipeline reset\n"); + + return ret; +} + +/* pipeline pcm params */ +int tb_pipeline_params(struct testbench_prm *tp, struct ipc *ipc, struct pipeline *p) +{ + struct comp_dev *cd; + struct sof_ipc_pcm_params params = {{0}}; + char message[TB_DEBUG_MSG_LEN]; + int fs_period; + int period; + int ret = 0; + + if (!p) { + fprintf(stderr, "error: pipeline is NULL\n"); + return -EINVAL; + } + + period = p->period; + + /* Compute period from sample rates */ + fs_period = (int)(0.9999 + tp->fs_in * period / 1e6); + sprintf(message, "period sample count %d\n", fs_period); + tb_debug_print(message); + + /* set pcm params */ + params.comp_id = p->comp_id; + params.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + params.params.frame_fmt = tp->frame_fmt; + params.params.rate = tp->fs_in; + params.params.channels = tp->channels_in; + + switch (params.params.frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + params.params.sample_container_bytes = 2; + params.params.sample_valid_bytes = 2; + break; + case SOF_IPC_FRAME_S24_4LE: + params.params.sample_container_bytes = 4; + params.params.sample_valid_bytes = 3; + break; + case SOF_IPC_FRAME_S32_LE: + params.params.sample_container_bytes = 4; + params.params.sample_valid_bytes = 4; + break; + default: + fprintf(stderr, "error: invalid frame format\n"); + return -EINVAL; + } + + params.params.host_period_bytes = fs_period * params.params.channels * + params.params.sample_container_bytes; + + /* Get pipeline host component */ + cd = tb_get_pipeline_host(p); + + /* Set pipeline params direction from scheduling component */ + params.params.direction = cd->direction; + + printf("test params: rate %d channels %d format %d\n", + params.params.rate, params.params.channels, + params.params.frame_fmt); + + /* pipeline params */ + ret = pipeline_params(p, cd, ¶ms); + if (ret < 0) + fprintf(stderr, "error: pipeline_params\n"); + + return ret; +} + +int tb_set_running_state(struct testbench_prm *tp) +{ + return 0; +} + +static struct pipeline *tb_get_pipeline_by_id(int id) +{ + struct ipc_comp_dev *pcm_dev; + struct ipc *ipc = sof_get()->ipc; + + pcm_dev = ipc_get_ppl_src_comp(ipc, id); + return pcm_dev->cd->pipeline; +} + +int tb_set_reset_state(struct testbench_prm *tp) +{ + struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int ret = 0; + int i; + + for (i = 0; i < tp->pipeline_num; i++) { + p = tb_get_pipeline_by_id(tp->pipelines[i]); + ret = tb_pipeline_reset(ipc, p); + if (ret < 0) + break; + } + + return ret; +} + +static void test_pipeline_free_comps(int pipeline_id) +{ + struct list_item *clist; + struct list_item *temp; + struct ipc_comp_dev *icd = NULL; + int err; + + /* remove the components for this pipeline */ + list_for_item_safe(clist, temp, &sof_get()->ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + + switch (icd->type) { + case COMP_TYPE_COMPONENT: + if (icd->cd->pipeline->pipeline_id != pipeline_id) + break; + err = ipc_comp_free(sof_get()->ipc, icd->id); + if (err) + fprintf(stderr, "failed to free comp %d\n", icd->id); + break; + case COMP_TYPE_BUFFER: + if (buffer_pipeline_id(icd->cb) != pipeline_id) + break; + err = ipc_buffer_free(sof_get()->ipc, icd->id); + if (err) + fprintf(stderr, "failed to free buffer %d\n", icd->id); + break; + case COMP_TYPE_PIPELINE: + if (icd->pipeline->pipeline_id != pipeline_id) + break; + err = ipc_pipeline_free(sof_get()->ipc, icd->id); + if (err) + fprintf(stderr, "failed to free pipeline %d\n", icd->id); + break; + default: + fprintf(stderr, "Unknown icd->type %d\n", icd->type); + } + } +} + +int tb_free_all_pipelines(struct testbench_prm *tp) +{ + int i; + + for (i = 0; i < tp->pipeline_num; i++) + test_pipeline_free_comps(tp->pipelines[i]); + + return 0; +} + +void tb_free_topology(struct testbench_prm *tp) +{ +} + +static int test_pipeline_params(struct testbench_prm *tp) +{ + struct ipc_comp_dev *pcm_dev; + struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int ret = 0; + int i; + + /* Run pipeline until EOF from fileread */ + + for (i = 0; i < tp->pipeline_num; i++) { + pcm_dev = ipc_get_ppl_src_comp(ipc, tp->pipelines[i]); + if (!pcm_dev) { + fprintf(stderr, "error: pipeline %d has no source component\n", + tp->pipelines[i]); + return -EINVAL; + } + + /* set up pipeline params */ + p = pcm_dev->cd->pipeline; + + /* input and output sample rate */ + if (!tp->fs_in) + tp->fs_in = p->period * p->frames_per_sched; + + if (!tp->fs_out) + tp->fs_out = p->period * p->frames_per_sched; + + ret = tb_pipeline_params(tp, ipc, p); + if (ret < 0) { + fprintf(stderr, "error: pipeline params failed: %s\n", + strerror(ret)); + return ret; + } + } + + return 0; +} + +static void tb_test_pipeline_set_test_limits(int pipeline_id, int max_copies, + int max_samples) +{ + struct list_item *clist; + struct ipc_comp_dev *icd = NULL; + struct comp_dev *cd; + struct dai_data *dd; + struct file_comp_data *fcd; + + /* set the test limits for this pipeline */ + list_for_item(clist, &sof_get()->ipc->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + + switch (icd->type) { + case COMP_TYPE_COMPONENT: + cd = icd->cd; + if (cd->pipeline->pipeline_id != pipeline_id) + break; + + switch (cd->drv->type) { + case SOF_COMP_HOST: + case SOF_COMP_DAI: + case SOF_COMP_FILEREAD: + case SOF_COMP_FILEWRITE: + /* only file limits supported today. TODO: add others */ + dd = comp_get_drvdata(cd); + fcd = comp_get_drvdata(dd->dai); + fcd->max_samples = max_samples; + fcd->max_copies = max_copies; + break; + default: + break; + } + break; + case COMP_TYPE_BUFFER: + default: + break; + } + } +} + +static int test_pipeline_start(struct testbench_prm *tp) +{ + struct pipeline *p; + struct ipc *ipc = sof_get()->ipc; + int i; + + /* Run pipeline until EOF from fileread */ + for (i = 0; i < tp->pipeline_num; i++) { + p = tb_get_pipeline_by_id(tp->pipelines[i]); + + /* do we need to apply copy count limit ? */ + if (tp->copy_check) + tb_test_pipeline_set_test_limits(tp->pipelines[i], tp->copy_iterations, 0); + + /* set pipeline params and trigger start */ + if (tb_pipeline_start(ipc, p) < 0) { + fprintf(stderr, "error: pipeline params\n"); + return -EINVAL; + } + } + + return 0; +} + +int tb_set_up_all_pipelines(struct testbench_prm *tp) +{ + int ret; + + ret = test_pipeline_params(tp); + if (ret < 0) { + fprintf(stderr, "error: pipeline params failed %d\n", ret); + return ret; + } + + ret = test_pipeline_start(tp); + if (ret < 0) { + fprintf(stderr, "error: pipeline failed %d\n", ret); + return ret; + } + + return 0; +} + +/* No support in IPC3 version */ +int tb_set_enum_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params) +{ + return 0; +} + +int tb_set_mixer_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params) +{ + return 0; +} + +int tb_set_bytes_control(struct testbench_prm *tp, struct tb_ctl *ctl, uint32_t *data) +{ + return 0; +} + +void tb_collect_heap_usage(struct testbench_prm *tp, struct tb_heap_usage_record *rec, int *count) +{ + *count = 0; +} + +#endif /* CONFIG_IPC_MAJOR_3 */ diff --git a/tools/testbench/utils_ipc4.c b/tools/testbench/utils_ipc4.c new file mode 100644 index 000000000000..00449de3bbd3 --- /dev/null +++ b/tools/testbench/utils_ipc4.c @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2018-2024 Intel Corporation. + +#if CONFIG_IPC_MAJOR_4 + +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/component_ext.h> +#include <sof/lib/notifier.h> +#include <sof/audio/component_ext.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <ipc/stream.h> + +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "testbench/utils.h" +#include "testbench/file.h" +#include "testbench/topology_ipc4.h" +#include "testbench/trace.h" + +#if defined __XCC__ +#include <xtensa/tie/xt_timer.h> +#endif + +SOF_DEFINE_REG_UUID(testbench); +DECLARE_TR_CTX(testbench_tr, SOF_UUID(testbench_uuid), LOG_LEVEL_INFO); +LOG_MODULE_REGISTER(testbench, CONFIG_SOF_LOG_LEVEL); + +/* testbench helper functions for pipeline setup and trigger */ + +int tb_setup(struct sof *sof, struct testbench_prm *tp) +{ + struct ll_schedule_domain domain = {0}; + int bits; + int krate; + + /* init components */ + sys_comp_init(sof); + + /* Module adapter components */ + sys_comp_module_aria_interface_init(); + sys_comp_module_asrc_interface_init(); + sys_comp_module_crossover_interface_init(); + sys_comp_module_dcblock_interface_init(); + sys_comp_module_demux_interface_init(); + sys_comp_module_dolby_dax_audio_processing_interface_init(); + sys_comp_module_drc_interface_init(); + sys_comp_module_eq_fir_interface_init(); + sys_comp_module_eq_iir_interface_init(); + sys_comp_module_file_interface_init(); + sys_comp_module_gain_interface_init(); + sys_comp_module_google_rtc_audio_processing_interface_init(); + sys_comp_module_igo_nr_interface_init(); + sys_comp_module_level_multiplier_interface_init(); + sys_comp_module_mfcc_interface_init(); + sys_comp_module_mixin_interface_init(); + sys_comp_module_mixout_interface_init(); + sys_comp_module_multiband_drc_interface_init(); + sys_comp_module_mux_interface_init(); + sys_comp_module_rtnr_interface_init(); + sys_comp_module_selector_interface_init(); + sys_comp_module_sound_dose_interface_init(); + sys_comp_module_src_interface_init(); + sys_comp_module_stft_process_interface_init(); + sys_comp_module_tdfb_interface_init(); + sys_comp_module_template_interface_init(); + sys_comp_module_volume_interface_init(); + + /* other necessary initializations */ + pipeline_posn_init(sof); + init_system_notify(sof); + tb_enable_trace(tp->trace_level); + + /* init IPC */ + if (ipc_init(sof) < 0) { + fprintf(stderr, "error: IPC init\n"); + return -EINVAL; + } + + /* Trace */ + ipc_tr.level = LOG_LEVEL_INFO; + ipc_tr.uuid_p = SOF_UUID(testbench_uuid); + + /* init LL scheduler */ + if (scheduler_init_ll(&domain) < 0) { + fprintf(stderr, "error: edf scheduler init\n"); + return -EINVAL; + } + + /* init EDF scheduler */ + if (scheduler_init_edf() < 0) { + fprintf(stderr, "error: edf scheduler init\n"); + return -EINVAL; + } + + tb_debug_print("ipc and scheduler initialized\n"); + + /* setup IPC4 audio format */ + tp->num_configs = 1; + krate = tp->fs_in / 1000; + switch (tp->frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + bits = 16; + break; + case SOF_IPC_FRAME_S24_4LE: + bits = 24; + break; + case SOF_IPC_FRAME_S32_LE: + bits = 32; + break; + default: + fprintf(stderr, "error: unsupported frame format %d\n", tp->frame_fmt); + return -EINVAL; + } + + /* TODO 44.1 kHz like rates */ + snprintf(tp->config[0].name, TB_MAX_CONFIG_NAME_SIZE, "%dk%dc%db", + krate, tp->channels_in, bits); + tp->num_configs = 1; + tp->config[0].buffer_frames = 2 * krate; + tp->config[0].buffer_time = 0; + tp->config[0].period_frames = krate; + tp->config[0].period_time = 0; + tp->config[0].rate = tp->fs_in; + tp->config[0].channels = tp->channels_in; + tp->config[0].format = tp->frame_fmt; + tp->period_frames = krate; + + /* TODO: Need to set this later for larger topologies with multiple PCMs. The + * pipelines are determined based on just the PCM ID for the device that we + * want to start playback/capture on. + */ + tp->pcm_id = 0; + + return 0; +} + +static int tb_prepare_widget(struct testbench_prm *tp, struct tplg_pcm_info *pcm_info, + struct tplg_comp_info *comp_info, int dir) +{ + struct tplg_pipeline_list *pipeline_list; + int ret, i; + + if (dir) + pipeline_list = &pcm_info->capture_pipeline_list; + else + pipeline_list = &pcm_info->playback_pipeline_list; + + /* populate base config */ + ret = tb_set_up_widget_base_config(tp, comp_info); + if (ret < 0) + return ret; + + tb_pipeline_update_resource_usage(tp, comp_info); + + /* add pipeline to pcm pipeline_list if needed */ + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + if (pipe_info == comp_info->pipe_info) + break; + } + + if (i == pipeline_list->count) { + pipeline_list->pipelines[pipeline_list->count] = comp_info->pipe_info; + pipeline_list->count++; + if (pipeline_list->count == TPLG_MAX_PCM_PIPELINES) { + fprintf(stderr, "error: pipelines count exceeds %d", + TPLG_MAX_PCM_PIPELINES); + return -EINVAL; + } + } + + return 0; +} + +static int tb_prepare_widgets_playback(struct testbench_prm *tp, struct tplg_pcm_info *pcm_info, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &tp->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->source != current_comp_info) + continue; + + /* set up source widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = tb_prepare_widget(tp, pcm_info, current_comp_info, 0); + if (ret < 0) + return ret; + } + + /* set up the sink widget */ + ret = tb_prepare_widget(tp, pcm_info, route_info->sink, 0); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN) { + ret = tb_prepare_widgets_playback(tp, pcm_info, starting_comp_info, + route_info->sink); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int tb_prepare_widgets_capture(struct testbench_prm *tp, struct tplg_pcm_info *pcm_info, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for capture */ + list_for_item(item, &tp->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->sink != current_comp_info) + continue; + + /* set up sink widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = tb_prepare_widget(tp, pcm_info, current_comp_info, 1); + if (ret < 0) + return ret; + } + + /* set up the source widget */ + ret = tb_prepare_widget(tp, pcm_info, route_info->source, 1); + if (ret < 0) + return ret; + + /* and then continue up the path */ + if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = tb_prepare_widgets_capture(tp, pcm_info, starting_comp_info, + route_info->source); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int tb_set_up_widget(struct testbench_prm *tp, struct tplg_comp_info *comp_info) +{ + struct tplg_pipeline_info *pipe_info = comp_info->pipe_info; + struct tb_glb_state *glb = &tp->glb_ctx; + struct tb_ctl *ctl; + int ret; + int i; + + pipe_info->usage_count++; + + /* first set up pipeline if needed, only done once for the first pipeline widget */ + if (pipe_info->usage_count == 1) { + ret = tb_set_up_pipeline(tp, pipe_info); + if (ret < 0) { + pipe_info->usage_count--; + return ret; + } + } + + /* now set up the widget */ + ret = tb_set_up_widget_ipc(tp, comp_info); + if (ret < 0) + return ret; + + /* send kcontrol bytes data */ + for (i = 0; i < glb->num_ctls; i++) { + struct sof_abi_hdr *abi; + + ctl = &glb->ctl[i]; + + /* send the bytes data from kcontrols associated with current widget */ + if (ctl->module_id != comp_info->module_id || + ctl->instance_id != comp_info->instance_id || + ctl->type != SND_SOC_TPLG_TYPE_BYTES || + !ctl->data) + continue; + + abi = (struct sof_abi_hdr *)ctl->data; + + /* send IPC with kcontrol data */ + ret = tb_send_bytes_data(&tp->ipc_tx, &tp->ipc_rx, + comp_info->module_id, comp_info->instance_id, abi); + if (ret < 0) { + fprintf(stderr, "Error: Failed to set bytes data for widget %s.\n", + comp_info->name); + return ret; + } + } + + return 0; +} + +static int tb_set_up_widgets_playback(struct testbench_prm *tp, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &tp->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->source != current_comp_info) + continue; + + /* set up source widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = tb_set_up_widget(tp, current_comp_info); + if (ret < 0) + return ret; + } + + /* set up the sink widget */ + ret = tb_set_up_widget(tp, route_info->sink); + if (ret < 0) + return ret; + + /* source and sink widgets are up, so set up route now */ + ret = tb_set_up_route(tp, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN) { + ret = tb_set_up_widgets_playback(tp, starting_comp_info, route_info->sink); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int tb_set_up_widgets_capture(struct testbench_prm *tp, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &tp->route_list) { + struct tplg_route_info *route_info = container_of(item, struct tplg_route_info, + item); + + if (route_info->sink != current_comp_info) + continue; + + /* set up source widget if it is the starting widget */ + if (starting_comp_info == current_comp_info) { + ret = tb_set_up_widget(tp, current_comp_info); + if (ret < 0) + return ret; + } + + /* set up the sink widget */ + ret = tb_set_up_widget(tp, route_info->source); + if (ret < 0) + return ret; + + /* source and sink widgets are up, so set up route now */ + ret = tb_set_up_route(tp, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->source->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = tb_set_up_widgets_capture(tp, starting_comp_info, route_info->source); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int tb_set_up_pipelines(struct testbench_prm *tp, int dir) +{ + struct tplg_comp_info *host = NULL; + struct tplg_pcm_info *pcm_info; + struct list_item *item; + int ret; + + list_for_item(item, &tp->pcm_list) { + pcm_info = container_of(item, struct tplg_pcm_info, item); + + if (pcm_info->id == tp->pcm_id) { + if (dir) + host = pcm_info->capture_host; + else + host = pcm_info->playback_host; + break; + } + } + + if (!host) { + fprintf(stderr, "No host component found for PCM ID: %d\n", tp->pcm_id); + return -EINVAL; + } + + if (!tb_is_pipeline_enabled(tp, host->pipeline_id)) + return 0; + + tp->pcm_info = pcm_info; /* TODO must be an array for multiple PCMs */ + + if (dir) { + ret = tb_prepare_widgets_capture(tp, pcm_info, host, host); + if (ret < 0) + return ret; + + ret = tb_set_up_widgets_capture(tp, host, host); + if (ret < 0) + return ret; + + tb_debug_print("Setting up capture pipelines complete\n"); + + return 0; + } + + ret = tb_prepare_widgets_playback(tp, pcm_info, host, host); + if (ret < 0) + return ret; + + ret = tb_set_up_widgets_playback(tp, host, host); + if (ret < 0) + return ret; + + tb_debug_print("Setting up playback pipelines complete\n"); + + return 0; +} + +int tb_set_up_all_pipelines(struct testbench_prm *tp) +{ + int ret; + + ret = tb_set_up_pipelines(tp, SOF_IPC_STREAM_PLAYBACK); + if (ret) { + fprintf(stderr, "error: Failed tb_set_up_pipelines for playback\n"); + return ret; + } + + ret = tb_set_up_pipelines(tp, SOF_IPC_STREAM_CAPTURE); + if (ret) { + fprintf(stderr, "error: Failed tb_set_up_pipelines for capture\n"); + return ret; + } + + tb_debug_print("pipelines set up complete\n"); + return 0; +} + +static int tb_free_widgets_playback(struct testbench_prm *tp, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct tplg_route_info *route_info; + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &tp->route_list) { + route_info = container_of(item, struct tplg_route_info, item); + if (route_info->source != current_comp_info) + continue; + + /* Widgets will be freed when the pipeline is deleted, so just unbind modules */ + ret = tb_free_route(tp, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_IN) { + ret = tb_free_widgets_playback(tp, starting_comp_info, route_info->sink); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int tb_free_widgets_capture(struct testbench_prm *tp, + struct tplg_comp_info *starting_comp_info, + struct tplg_comp_info *current_comp_info) +{ + struct tplg_route_info *route_info; + struct list_item *item; + int ret; + + /* for playback */ + list_for_item(item, &tp->route_list) { + route_info = container_of(item, struct tplg_route_info, item); + if (route_info->sink != current_comp_info) + continue; + + /* Widgets will be freed when the pipeline is deleted, so just unbind modules */ + ret = tb_free_route(tp, route_info); + if (ret < 0) + return ret; + + /* and then continue down the path */ + if (route_info->sink->type != SND_SOC_TPLG_DAPM_DAI_OUT) { + ret = tb_free_widgets_capture(tp, starting_comp_info, route_info->source); + if (ret < 0) + return ret; + } + } + + return 0; +} + +static int tb_free_pipelines(struct testbench_prm *tp, int dir) +{ + struct tplg_pipeline_list *pipeline_list; + struct tplg_pcm_info *pcm_info; + struct list_item *item; + struct tplg_comp_info *host = NULL; + int ret, i; + + list_for_item(item, &tp->pcm_list) { + pcm_info = container_of(item, struct tplg_pcm_info, item); + if (dir) + host = pcm_info->capture_host; + else + host = pcm_info->playback_host; + + if (!host || !tb_is_pipeline_enabled(tp, host->pipeline_id)) + continue; + + if (dir) { + pipeline_list = &tp->pcm_info->capture_pipeline_list; + ret = tb_free_widgets_capture(tp, host, host); + if (ret < 0) { + fprintf(stderr, "failed to free widgets for capture PCM\n"); + return ret; + } + } else { + pipeline_list = &tp->pcm_info->playback_pipeline_list; + ret = tb_free_widgets_playback(tp, host, host); + if (ret < 0) { + fprintf(stderr, "failed to free widgets for playback PCM\n"); + return ret; + } + } + for (i = 0; i < pipeline_list->count; i++) { + struct tplg_pipeline_info *pipe_info = pipeline_list->pipelines[i]; + + ret = tb_delete_pipeline(tp, pipe_info); + if (ret < 0) + return ret; + } + } + + tp->instance_ids[SND_SOC_TPLG_DAPM_SCHEDULER] = 0; + return 0; +} + +int tb_free_all_pipelines(struct testbench_prm *tp) +{ + tb_debug_print("freeing playback direction\n"); + tb_free_pipelines(tp, SOF_IPC_STREAM_PLAYBACK); + + tb_debug_print("freeing capture direction\n"); + tb_free_pipelines(tp, SOF_IPC_STREAM_CAPTURE); + return 0; +} + +void tb_free_topology(struct testbench_prm *tp) +{ + struct tplg_pcm_info *pcm_info; + struct tplg_comp_info *comp_info; + struct tplg_route_info *route_info; + struct tplg_pipeline_info *pipe_info; + struct tplg_context *ctx = &tp->tplg; + struct sof_ipc4_available_audio_format *available_fmts; + struct list_item *item, *_item; + + list_for_item_safe(item, _item, &tp->pcm_list) { + pcm_info = container_of(item, struct tplg_pcm_info, item); + list_item_del(item); + free(pcm_info->name); + free(pcm_info); + } + + list_for_item_safe(item, _item, &tp->widget_list) { + comp_info = container_of(item, struct tplg_comp_info, item); + available_fmts = &comp_info->available_fmt; + list_item_del(item); + free(available_fmts->output_pin_fmts); + free(available_fmts->input_pin_fmts); + free(comp_info->name); + free(comp_info->stream_name); + free(comp_info->ipc_payload); + free(comp_info); + } + + list_for_item_safe(item, _item, &tp->route_list) { + route_info = container_of(item, struct tplg_route_info, item); + list_item_del(item); + free(route_info); + } + + list_for_item_safe(item, _item, &tp->pipeline_list) { + pipe_info = container_of(item, struct tplg_pipeline_info, item); + list_item_del(item); + free(pipe_info->name); + free(pipe_info); + } + + free(ctx->tplg_base); + free(tp->glb_ctx.ctl); + tb_debug_print("freed all pipelines, widgets, routes and pcms\n"); +} + +int tb_set_enum_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params) +{ + int control_values[PLATFORM_MAX_CHANNELS]; + char *token, *rest; + int ret = 0; + int n = 0; + + rest = control_params; + while ((token = strtok_r(rest, ",", &rest))) { + if (n == PLATFORM_MAX_CHANNELS) { + fprintf(stderr, + "error: number of control values exceeds max channels count.\n"); + return -EINVAL; + } + + control_values[n] = tb_decode_enum(&ctl->enum_ctl, token); + if (control_values[n] < 0) { + fprintf(stderr, + "error: not able to decode enum %s.\n", token); + return -EINVAL; + } + n++; + } + + ret = tb_send_alsa_control(&tp->ipc_tx, &tp->ipc_rx, ctl, control_values, n, + SOF_IPC4_ENUM_CONTROL_PARAM_ID); + return ret; +} + +int tb_set_mixer_control(struct testbench_prm *tp, struct tb_ctl *ctl, char *control_params) +{ + int control_values[PLATFORM_MAX_CHANNELS]; + char *token, *rest; + int n = 0; + int ret; + + rest = control_params; + while ((token = strtok_r(rest, ",", &rest))) { + if (n == PLATFORM_MAX_CHANNELS) { + fprintf(stderr, + "error: number of control values exceeds max channels count.\n"); + return -EINVAL; + } + + if (strcmp(token, "on") == 0) + control_values[n] = 1; + else if (strcmp(token, "off") == 0) + control_values[n] = 0; + else + control_values[n] = atoi(token); + + n++; + } + + if (ctl->mixer_ctl.max == 1) + ret = tb_send_alsa_control(&tp->ipc_tx, &tp->ipc_rx, ctl, control_values, n, + SOF_IPC4_SWITCH_CONTROL_PARAM_ID); + else + ret = tb_send_volume_control(&tp->ipc_tx, &tp->ipc_rx, ctl, control_values, n); + + return ret; +} + +int tb_set_bytes_control(struct testbench_prm *tp, struct tb_ctl *ctl, uint32_t *data) +{ + return tb_send_bytes_data(&tp->ipc_tx, &tp->ipc_rx, + ctl->module_id, ctl->instance_id, + (struct sof_abi_hdr *)data); +} + +void tb_collect_heap_usage(struct testbench_prm *tp, struct tb_heap_usage_record *records, + int *count_out) +{ + struct list_item *item; + size_t hwm; + int count = 0; + + list_for_item(item, &tp->widget_list) { + struct tplg_comp_info *info = container_of(item, struct tplg_comp_info, item); + uint32_t comp_id = IPC4_COMP_ID(info->module_id, info->instance_id); + struct comp_dev *dev = ipc4_get_comp_dev(comp_id); + + if (!dev || !dev->mod) + continue; + + /* In testbench environment, skip AIF/DAI because they are not real components. */ + if (info->type == SND_SOC_TPLG_DAPM_AIF_IN || + info->type == SND_SOC_TPLG_DAPM_AIF_OUT || + info->type == SND_SOC_TPLG_DAPM_DAI_IN || + info->type == SND_SOC_TPLG_DAPM_DAI_OUT) + continue; + + if (count >= TB_NUM_WIDGETS_SUPPORTED) { + fprintf(stderr, "Error: Too many components for heap records, max %d.\n", + TB_NUM_WIDGETS_SUPPORTED); + break; + } + + module_adapter_heap_usage(dev->mod, &hwm); + records[count].module_name = info->name; + records[count].heap_max = hwm; + count++; + } + + *count_out = count; +} + +#endif /* CONFIG_IPC_MAJOR_4 */ diff --git a/tools/topology/CMakeLists.txt b/tools/topology/CMakeLists.txt index c8242e903a73..92a7acf6e5a6 100644 --- a/tools/topology/CMakeLists.txt +++ b/tools/topology/CMakeLists.txt @@ -1,168 +1,109 @@ -# SPDX-License-Identifier: BSD-3-Clause - -file(GLOB TPLG_DEPS - platform/intel/*.m4 - platform/common/*.m4 - common/*.m4 - m4/*.m4 - sof/*.m4 -) - -add_custom_target(abi - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/get_abi.sh ${SOF_ROOT_SOURCE_DIRECTORY} - DEPENDS ${TPLG_DEPS} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - VERBATIM - USES_TERMINAL -) - -set(TPLGS - "sof-cht-nocodec\;sof-cht-nocodec\;-DPLATFORM=cht" - "sof-cht-nocodec\;sof-byt-nocodec\;-DPLATFORM=byt" - "sof-bdw-nocodec\;sof-bdw-nocodec" - "sof-cht-max98090\;sof-cht-max98090" - "sof-cht-rt5682\;sof-cht-rt5682" - "sof-cht-src-50khz-pcm512x\;sof-cht-src-50khz-pcm512x" - "sof-hda-generic\;sof-hda-generic\;-DCHANNELS=0" - "sof-hda-generic\;sof-hda-generic-2ch\;-DCHANNELS=2" - "sof-hda-generic\;sof-hda-generic-4ch\;-DCHANNELS=4" - "sof-hda-generic-idisp\;sof-hda-generic-idisp\;-DCHANNELS=0" - "sof-hda-generic-idisp\;sof-hda-generic-idisp-2ch\;-DCHANNELS=2" - "sof-hda-generic-idisp\;sof-hda-generic-idisp-4ch\;-DCHANNELS=4" - "sof-hda-asrc\;sof-hda-asrc-2ch\;-DCHANNELS=2" - "sof-apl-nocodec\;sof-apl-nocodec" - "sof-apl-keyword-detect\;sof-apl-keyword-detect" - "sof-bdw-codec\;sof-bdw-rt286\;-DCODEC=RT286" - "sof-bdw-codec\;sof-bdw-rt5640\;-DCODEC=RT5640" - "sof-bdw-codec\;sof-bdw-rt5677\;-DCODEC=RT5677" - "sof-byt-codec\;sof-byt-rt5640\;-DCODEC=RT5640\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-rt5645\;-DCODEC=RT5645\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-rt5651\;-DCODEC=RT5651\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-rt5670\;-DCODEC=RT5670\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-rt5682\;-DCODEC=RT5682\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-da7213\;-DCODEC=DA7213\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-cx2072x\;-DCODEC=CX2072X\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-es8316\;-DCODEC=ES8316\;-DPLATFORM=byt\;-DSSP_NUM=2" - "sof-byt-codec\;sof-byt-rt5640-ssp0\;-DCODEC=RT5640\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-rt5645-ssp0\;-DCODEC=RT5645\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-rt5651-ssp0\;-DCODEC=RT5651\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-rt5670-ssp0\;-DCODEC=RT5670\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-rt5682-ssp0\;-DCODEC=RT5682\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-da7213-ssp0\;-DCODEC=DA7213\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-cx2072x-ssp0\;-DCODEC=CX2072X\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-byt-es8316-ssp0\;-DCODEC=ES8316\;-DPLATFORM=byt\;-DSSP_NUM=0" - "sof-byt-codec\;sof-cht-rt5640\;-DCODEC=RT5640\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-byt-codec\;sof-cht-rt5645\;-DCODEC=RT5645\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-byt-codec\;sof-cht-rt5651\;-DCODEC=RT5651\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-byt-codec\;sof-cht-rt5670\;-DCODEC=RT5670\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-byt-codec\;sof-cht-da7213\;-DCODEC=DA7213\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-byt-codec\;sof-cht-cx2072x\;-DCODEC=CX2072X\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-byt-codec\;sof-cht-es8316\;-DCODEC=ES8316\;-DPLATFORM=cht\;-DSSP_NUM=2" - "sof-cnl-rt274\;sof-cnl-rt274" - "sof-apl-tdf8532\;sof-apl-tdf8532" - "sof-apl-pcm512x\;sof-apl-pcm512x" - "sof-apl-pcm512x-nohdmi\;sof-apl-pcm512x-nohdmi" - "sof-apl-demux-pcm512x\;sof-apl-demux-pcm512x" - "sof-apl-rt298\;sof-apl-rt298" - "sof-apl-wm8804\;sof-apl-wm8804" - "sof-apl-da7219\;sof-apl-da7219" - "sof-glk-da7219-kwd\;sof-glk-da7219-kwd" - "sof-glk-da7219\;sof-glk-da7219" - "sof-glk-rt5682\;sof-glk-rt5682" - "sof-icl-nocodec\;sof-icl-nocodec" - "sof-apl-eq-pcm512x\;sof-apl-eq-pcm512x" - "sof-apl-eq-dmic\;sof-apl-eq-dmic" - "sof-apl-src-dmic\;sof-apl-src-dmic" - "sof-apl-dmic-a2ch\;sof-apl-dmic-a2ch" - "sof-apl-dmic-b2ch\;sof-apl-dmic-b2ch" - "sof-apl-dmic-a2ch-b2ch\;sof-apl-dmic-a2ch-b2ch" - "sof-apl-dmic-a4ch-b2ch\;sof-apl-dmic-a4ch-b2ch" - "sof-apl-dmic-a2ch-b4ch\;sof-apl-dmic-a2ch-b4ch" - "sof-apl-dmic-a96k-b16k\;sof-apl-dmic-a96k-b16k" - "sof-apl-dmic\;sof-apl-dmic-4ch\;-DCHANNELS=4" - "sof-apl-dmic\;sof-apl-dmic-2ch\;-DCHANNELS=2" - "sof-apl-src-50khz-pcm512x\;sof-apl-src-50khz-pcm512x" - "sof-icl-dmic-4ch\;sof-icl-dmic-4ch" - "sof-icl-rt700\;sof-icl-rt700\;-DPLATFORM=icl" - "sof-cml-rt700\;sof-cml-rt700\;-DPLATFORM=cml" - "sof-icl-rt711-rt1308-rt715\;sof-icl-rt711-rt1308-rt715\;-DPLATFORM=icl" - "sof-icl-rt711-rt1308-rt715-hdmi\;sof-cml-rt711-rt1308-mono-rt715\;-DPLATFORM=cml-mono" - "sof-icl-rt711-rt1308-rt715-hdmi\;sof-cml-rt711-rt1308-rt715\;-DPLATFORM=cml" - "sof-icl-rt711-rt1308-rt715-hdmi\;sof-icl-rt711-rt1308-rt715-hdmi\;-DPLATFORM=icl" - "sof-apl-asrc-wm8804\;sof-apl-asrc-wm8804" - "sof-apl-asrc-pcm512x\;sof-apl-asrc-pcm512x" - "sof-apl-src-pcm512x\;sof-apl-src-pcm512x" - "sof-cml-rt5682\;sof-cml-rt5682\;-DPLATFORM=cml" - "sof-cml-rt5682\;sof-whl-rt5682\;-DPLATFORM=whl" - "sof-cml-rt5682\;sof-icl-rt5682\;-DPLATFORM=icl" - "sof-cml-rt5682-kwd\;sof-cml-rt5682-kwd\;-DPLATFORM=cml" - "sof-cml-rt5682-kwd\;sof-whl-rt5682-kwd\;-DPLATFORM=whl" - "sof-cml-rt5682-kwd\;sof-icl-rt5682-kwd\;-DPLATFORM=icl" - "sof-cml-src-rt5682\;sof-cml-src-rt5682" - "sof-cml-demux-rt5682\;sof-cml-demux-rt5682\;-DPLATFORM=cml" - "sof-cml-demux-rt5682\;sof-whl-demux-rt5682\;-DPLATFORM=whl" - "sof-cnl-nocodec\;sof-cnl-nocodec" - "sof-cml-rt5682-max98357a\;sof-cml-rt5682-max98357a\;-DPLATFORM=cml" - "sof-cml-demux-rt5682-max98357a\;sof-cml-demux-rt5682-max98357a\;-DPLATFORM=cml" - "sof-cml-rt1011-rt5682\;sof-cml-rt1011-rt5682\;-DPLATFORM=cml" - "sof-tgl-nocodec\;sof-tgl-nocodec" - "sof-tgl-rt711-i2s-rt1308\;sof-tgl-rt711-i2s-rt1308\;-DHDMI=1" - "sof-tgl-rt711-i2s-rt1308\;sof-tgl-rt711-i2s-rt1308-nohdmi" - "sof-tgl-rt711-rt1308\;sof-tgl-rt711-rt1308" - "sof-tgl-nocodec\;sof-ehl-nocodec" - "sof-ehl-rt5660\;sof-ehl-rt5660\;-DHDMI=1" - "sof-ehl-rt5660\;sof-ehl-rt5660-nohdmi" - "sof-imx8qxp-nocodec\;sof-imx8qxp-nocodec" - "sof-imx8qxp-cs42888\;sof-imx8qxp-cs42888" - "sof-imx8qxp-nocodec-sai\;sof-imx8qxp-nocodec-sai" - "sof-imx8qxp-wm8960\;sof-imx8qxp-wm8960" - "sof-tgl-max98357a-rt5682\;sof-tgl-max98357a-rt5682" - "sof-tgl-max98373-rt5682\;sof-tgl-max98373-rt5682" - "sof-jsl-da7219\;sof-jsl-da7219\;-DPLATFORM=jsl" - "sof-jsl-da7219\;sof-jsl-da7219-mx98360a\;-DPLATFORM=jsl-dedede" - "sof-imx8mp-wm8960\;sof-imx8mp-wm8960" -) +set(SOF_TOPOLOGY_BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") +set(SOF_ALSA_TOOLS_DIR "${SOF_ROOT_SOURCE_DIRECTORY}/../tools/bin") +set(ALSATPLG_CMD "${SOF_ALSA_TOOLS_DIR}/alsatplg") -add_custom_target(topologies ALL) +function(alsatplg_version OUT_STATUS OUT_VERSION) + execute_process(COMMAND ${ALSATPLG_CMD} --version + RESULT_VARIABLE status + OUTPUT_VARIABLE stdout + OUTPUT_STRIP_TRAILING_WHITESPACE) + message(DEBUG "${ALSATPLG_CMD} --version: status=${status}, output=${stdout}") + + set(${OUT_STATUS} "${status}" PARENT_SCOPE) + + # Some error messages have already been printed on stderr + if(NOT status EQUAL 0) + message(WARNING "${ALSATPLG_CMD} --version returned status: ${status}, +${stdout}") + return() + endif() -foreach(tplg ${TPLGS}) - list(GET tplg 0 input) - list(GET tplg 1 output) - list(LENGTH tplg tplg_len) - math(EXPR num_args "${tplg_len} - 1") - set(DEFINES "") - if (${num_args} GREATER 1) - foreach(index RANGE 2 ${num_args}) - list(GET tplg ${index} custom_define) - list(APPEND DEFINES ${custom_define}) - endforeach() + string(REPLACE "\n" ";" ALSA_VERSION_LIST ${stdout}) + list(GET ALSA_VERSION_LIST 0 ALSATPLG_VERSION) + string(REGEX MATCH "[0-9]\.[0-9]\.*[0-9]*" ALSATPLG_VERSION_NUMBER ${ALSATPLG_VERSION}) + + set(${OUT_VERSION} "${ALSATPLG_VERSION_NUMBER}" PARENT_SCOPE) +endfunction() + + +# Being written in C, `alsatplg` silently ignores some invalid inputs +# and produces an corrupt .tplg file instead of returning an error code +# that fails the build. For instance, alsatplg versions < 1.2.5 silently +# corrupt `codec_consumer` and turn it into `codec_master` instead. +# Longer story in #5192. +alsatplg_version(STATUS ALSATPLG_VERSION_NUMBER) +if(NOT STATUS EQUAL 0) + message(WARNING "${ALSATPLG_CMD} failed: ${STATUS}; all topologies skipped") + return() +else() + if(${ALSATPLG_VERSION_NUMBER} VERSION_LESS "1.2.5") + message(WARNING "All topologies skipped: minimum alsatplg version 1.2.5,\ + found ${ALSATPLG_VERSION_NUMBER}.") + return() endif() + # success +endif() + +# This use of VERBOSE relies on original CMake behavior. +# From the add_custom_command() manual: +# +# Use of VERBATIM is recommended as it enables correct behavior. +# When VERBATIM is not given the behavior is platform specific because +# there is no protection of tool-specific special characters. +# +# This is fine because: +# - We don't expect alsatplg to work on Windows any time soon. +# - CMake is too afraid to remove the original, no-VERBATIM behavior: +# https://gitlab.kitware.com/cmake/cmake/issues/18849 +# +# Also note that in alsa-utils commit v1.2.2~15-gcbabe7a3f0cc, alsatplg +# (accidentally?) started ignoring the verbosity level, now it's just +# verbose or not. +macro(add_alsatplg_command) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output}.conf - COMMAND m4 - ${DEFINES} - -I ${CMAKE_CURRENT_SOURCE_DIR}/m4 - -I ${CMAKE_CURRENT_SOURCE_DIR}/common - -I ${CMAKE_CURRENT_SOURCE_DIR}/platform/common - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/common/abi.m4 - ${CMAKE_CURRENT_SOURCE_DIR}/${input}.m4 - > ${output}.conf - DEPENDS abi - VERBATIM + MAIN_DEPENDENCY ${ARGV0} + OUTPUT ${ARGV1} + # Warning: before alsa-utils fix 8e71fba810b87c, + # permissions are hardcoded and only the user can read + # the -o(utput) file. + # See bug https://github.com/alsa-project/alsa-utils/issues/126 + COMMAND ${ALSATPLG_CMD} \$\${VERBOSE:+-v 1} -c ${ARGV0} -o ${ARGV1} USES_TERMINAL ) +endmacro() + +macro(add_alsatplg2_command conf_header conf_target input_name output_name include_path) + # command line definitions are optional + # Set defines if there is an optional argument + if (${ARGC} GREATER 5) + set (defines ${ARGV5}) + else() + set (defines "") + endif() add_custom_command( - OUTPUT ${output}.tplg - COMMAND alsatplg -v 1 -c ${output}.conf -o ${output}.tplg - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output}.conf - VERBATIM + MAIN_DEPENDENCY ${input_name}.conf + # The conf_header file is the real dependency that + # triggers a rebuild. conf_target is the target that + # avoids a race to rebuild conf_header. See the CMake FAQ + # or (better) Sam Thursfield's blog about custom + # targets. + DEPENDS ${conf_header} ${conf_target} + OUTPUT ${output_name}.tplg + + COMMAND cat ${conf_header} ${input_name}.conf > ${output_name}.conf + + # -p to pre-process Topology2.0 conf file + COMMAND ALSA_CONFIG_DIR=${CMAKE_SOURCE_DIR}/topology/topology2 ${ALSATPLG_CMD} \$\${VERBOSE:+-v 1} + -I ${include_path} -D "'${defines}'" -p -c ${output_name}.conf -o ${output_name}.tplg USES_TERMINAL - ) + ) +endmacro() + + +add_custom_target(topologies ALL) +add_dependencies(topologies topologies1) - add_custom_target(topology_${output} DEPENDS ${output}.tplg) - add_dependencies(topologies topology_${output}) -endforeach() +add_subdirectory(topology1) +add_subdirectory(topology2) diff --git a/tools/topology/README.md b/tools/topology/README.md new file mode 100644 index 000000000000..8d10954a906a --- /dev/null +++ b/tools/topology/README.md @@ -0,0 +1,22 @@ +# SOF Topology Tools (`tools/topology`) + +The `tools/topology` directory contains the build infrastructure and source files used to generate Advanced Linux Sound Architecture (ALSA) topology (`.tplg`) binaries for Sound Open Firmware. + +ALSA topology files describe the audio DSP graph (pipelines, widgets, routes, DAIs) and are loaded dynamically by the Linux kernel SOF driver during initialization. This allows a single generic driver to support a wide variety of hardware configurations and routing paths without requiring source code changes in the kernel. + +## Directory Structure + +To support the evolution of the SOF topology syntax, the configuration files are split into two main versions: + +- [`topology1/`](topology1/README.md): Contains the legacy (v1) `m4`-based ALSA topology generation scripts and configuration files. Topology v1 heavily relies on `m4` macro preprocessing to generate the final `.conf` files before being compiled by `alsatplg`. +- [`topology2/`](topology2/README.md): Contains the newer (v2) ALSA topology generation files. Topology v2 introduces a more structured, object-oriented syntax natively supported by newer versions of the `alsatplg` compiler (specifically the pre-processor `-p` flag), reducing reliance on external macro languages. + +## Build Process + +The topology build process is managed by `CMakeLists.txt` in this root directory. It performs the following key steps: + +1. **Compiler Detection**: It locates the `alsatplg` tool (usually built in `tools/bin/alsatplg` alongside the firmware) and checks its version. +2. **Feature Validation**: It ensures the `alsatplg` version is at least `1.2.5`. Older versions are known to silently corrupt certain topology structures (e.g., converting `codec_consumer` to `codec_master`). If the tool is too old, topology generation is safely skipped with a warning. +3. **Target Generation**: It provides macros (`add_alsatplg_command` and `add_alsatplg2_command`) used by the subdirectories to invoke the topology compiler on the pre-processed `.conf` files to generate the final `.tplg` binaries. + +The `topologies` CMake target is the master target that depends on the generation targets inside both `topology1` and `topology2`. diff --git a/tools/topology/get_abi.sh b/tools/topology/get_abi.sh deleted file mode 100755 index 5c48ca3b887a..000000000000 --- a/tools/topology/get_abi.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2019 Intel Corporation. All rights reserved. - -MAJOR=`grep '#define SOF_ABI_MAJOR ' $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` -MINOR=`grep '#define SOF_ABI_MINOR ' $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` -PATCH=`grep '#define SOF_ABI_PATCH ' $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` -MAJOR_SHIFT=`grep '#define SOF_ABI_MAJOR_SHIFT'\ - $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` -MINOR_SHIFT=`grep '#define SOF_ABI_MINOR_SHIFT'\ - $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` - -major_val=$(($MAJOR << $MAJOR_SHIFT)) -minor_val=$(($MINOR << $MINOR_SHIFT)) -abi_version_3_8=$((3<<$MAJOR_SHIFT | 8<<$MINOR_SHIFT)) -abi_version=$(($major_val | $minor_val)) -abi_version_3_9_or_greater=$(($abi_version > $abi_version_3_8)) - -printf "define(\`SOF_ABI_MAJOR', \`0x%02x')\n" $MAJOR > abi.h -printf "define(\`SOF_ABI_MINOR', \`0x%02x')\n" $MINOR >> abi.h -printf "define(\`SOF_ABI_PATCH', \`0x%02x')\n" $PATCH >> abi.h -printf "define(\`SOF_ABI_VERSION', \`0x%x')\n" $abi_version >> abi.h -printf "define(\`SOF_ABI_VERSION_3_9_OR_GRT', \`%d')\n"\ - $abi_version_3_9_or_greater >> abi.h diff --git a/tools/topology/m4/asrc.m4 b/tools/topology/m4/asrc.m4 deleted file mode 100644 index 5239f4ebcc6c..000000000000 --- a/tools/topology/m4/asrc.m4 +++ /dev/null @@ -1,40 +0,0 @@ -divert(-1) - -dnl Defines the macro for ASRC widget - -dnl ASRC name) -define(`N_ASRC', `ASRC'PIPELINE_ID`.'$1) - -dnl W_ASRC(name, format, periods_sink, periods_source, data) -define(`W_ASRC', -`SectionVendorTuples."'N_ASRC($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_ASRC($1)`_data_w" {' -` tuples "'N_ASRC($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_ASRC($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_ASRC($1)`_data_str" {' -` tuples "'N_ASRC($1)`_tuples_str"' -`}' -`SectionWidget."'N_ASRC($1)`" {' -` index "'PIPELINE_ID`"' -` type "asrc"' -` no_pm "true"' -` data [' -` "'N_ASRC($1)`_data_w"' -` "'N_ASRC($1)`_data_str"' -` "'$5`"' -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/buffer.m4 b/tools/topology/m4/buffer.m4 deleted file mode 100644 index dc3ca26cea00..000000000000 --- a/tools/topology/m4/buffer.m4 +++ /dev/null @@ -1,35 +0,0 @@ -divert(-1) - -dnl Define the macro for buffer widget - -dnl Buffer name) -define(`N_BUFFER', `BUF'PIPELINE_ID`.'$1) - -dnl W_BUFFER(name, size, capabilities) -define(`W_BUFFER', -`SectionVendorTuples."'N_BUFFER($1)`_tuples" {' -` tokens "sof_buffer_tokens"' -` tuples."word" {' -` SOF_TKN_BUF_SIZE' STR($2) -` SOF_TKN_BUF_CAPS' STR($3) -` }' -`}' -`SectionData."'N_BUFFER($1)`_data" {' -` tuples "'N_BUFFER($1)`_tuples"' -`}' -`SectionWidget."'N_BUFFER($1)`" {' -` index "'PIPELINE_ID`"' -` type "buffer"' -` no_pm "true"' -` data [' -` "'N_BUFFER($1)`_data"' -` ]' -`}') - -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')') - -divert(0)dnl diff --git a/tools/topology/m4/bytecontrol.m4 b/tools/topology/m4/bytecontrol.m4 deleted file mode 100644 index 22a7b6f31c5d..000000000000 --- a/tools/topology/m4/bytecontrol.m4 +++ /dev/null @@ -1,62 +0,0 @@ -divert(-1) - -dnl Define macro for byte control - -dnl CONTROLBYTES_MAX(comment, value) -define(`CONTROLBYTES_MAX', -`#$1' -` max STR($2)') - -dnl CONTROLMIXER_TLV(comment, value) -define(`CONTROLBYTES_TLV', -`#$1' -` tlv STR($2)') - -dnl CONTROLMIXER_OPS(info, comment, get, put) -define(`CONTROLBYTES_OPS', -`ops."ctl" {' -` info STR($1)' -` #$2' -` }') - -dnl CONTROLMIXER_OPS(info, comment, get, put) -define(`CONTROLBYTES_EXTOPS', -`extops."extctl" {' -` #$1' -` get STR($2)' -` put STR($3)' -` }') - -define(`CONTROLBYTES_PRIV', -`SectionData.STR($1) {' -` $2' -`}') - -dnl C_CONTROLMIXER(name, index, ops, base, num_regs, mask, max, tlv, priv) -define(`C_CONTROLBYTES', -`SectionControlBytes.STR($1) {' -`' -` # control belongs to this index group' -` index STR($2)' -`' -` # control uses bespoke driver get/put/info ID for io ops' -` $3' -` # control uses bespoke driver get/put/info ID for ext ops' -` $4' -`' -` base STR($5)' -` num_regs STR($6)' -` mask STR($7)' -` $8' -` $9' -` access [' -` tlv_write' -` tlv_read' -` tlv_callback' -` ]' -` data [' -` $10' -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/ch_sel.m4 b/tools/topology/m4/ch_sel.m4 deleted file mode 100644 index 8c0ae7edbb70..000000000000 --- a/tools/topology/m4/ch_sel.m4 +++ /dev/null @@ -1,49 +0,0 @@ -divert(-1) - -dnl Define macro for channel selector widget - -dnl Selector name) -define(`N_SELECTOR', `SELECTOR'PIPELINE_ID`.'$1) - -dnl W_SELECTOR(name, format, periods_sink, periods_source, kcontrols_list) -define(`W_SELECTOR', -`SectionVendorTuples."'N_SELECTOR($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_SELECTOR($1)`_data_w" {' -` tuples "'N_SELECTOR($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_SELECTOR($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionVendorTuples."'N_SELECTOR($1)`_process_tuples_str" {' -` tokens "sof_process_tokens"' -` tuples."string" {' -` SOF_TKN_PROCESS_TYPE' "CHAN_SELECTOR" -` }' -`}' -`SectionData."'N_SELECTOR($1)`_data_str" {' -` tuples "'N_SELECTOR($1)`_tuples_str"' -` tuples "'N_SELECTOR($1)`_process_tuples_str"' -`}' -`SectionWidget."'N_SELECTOR($1)`" {' -` index "'PIPELINE_ID`"' -` type "effect"' -` no_pm "true"' -` data [' -` "'N_SELECTOR($1)`_data_w"' -` "'N_SELECTOR($1)`_data_str"' -` ]' -` bytes [' - $5 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/dai.m4 b/tools/topology/m4/dai.m4 deleted file mode 100644 index 0d417d502003..000000000000 --- a/tools/topology/m4/dai.m4 +++ /dev/null @@ -1,213 +0,0 @@ -divert(-1) - -include(`debug.m4') - -dnl Define macros for DAI IN/OUT widgets and DAI config - -dnl DAI name) -define(`N_DAI', DAI_NAME) -define(`N_DAI_OUT', DAI_NAME`.OUT') -define(`N_DAI_IN', DAI_NAME`.IN') - -dnl W_DAI_OUT(type, index, dai_link, format, periods_sink, periods_source) -define(`W_DAI_OUT', -`SectionVendorTuples."'N_DAI_OUT($2)`_tuples_w_comp" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($5) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($6) -` }' -`}' -`SectionData."'N_DAI_OUT($2)`_data_w_comp" {' -` tuples "'N_DAI_OUT($2)`_tuples_w_comp"' -`}' -`SectionVendorTuples."'N_DAI_OUT($2)`_tuples_w" {' -` tokens "sof_dai_tokens"' -` tuples."word" {' -` SOF_TKN_DAI_INDEX' $2 -` SOF_TKN_DAI_DIRECTION' "0" -` }' -`}' -`SectionData."'N_DAI_OUT($2)`_data_w" {' -` tuples "'N_DAI_OUT($2)`_tuples_w"' -`}' -`SectionVendorTuples."'N_DAI_OUT($2)`_tuples_str" {' -` tokens "sof_dai_tokens"' -` tuples."string" {' -` SOF_TKN_DAI_TYPE' $1 -` }' -`}' -`SectionData."'N_DAI_OUT($2)`_data_str" {' -` tuples "'N_DAI_OUT($2)`_tuples_str"' -`}' -`SectionVendorTuples."'N_DAI_OUT($2)`_tuples_comp_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($4) -` }' -`}' -`SectionData."'N_DAI_OUT($2)`_data_comp_str" {' -` tuples "'N_DAI_OUT($2)`_tuples_comp_str"' -`}' -`SectionWidget."'N_DAI_OUT`" {' -` index "'PIPELINE_ID`"' -` type "dai_in"' -` stream_name' STR($3) -` no_pm "true"' -` data [' -` "'N_DAI_OUT($2)`_data_w"' -` "'N_DAI_OUT($2)`_data_w_comp"' -` "'N_DAI_OUT($2)`_data_str"' -` "'N_DAI_OUT($2)`_data_comp_str"' -` ]' -`}') - -dnl W_DAI_IN(type, index, dai_link, format, periods_sink, periods_source) -define(`W_DAI_IN', -`SectionVendorTuples."'N_DAI_IN($2)`_tuples_w_comp" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($5) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($6) -` }' -`}' -`SectionData."'N_DAI_IN($2)`_data_w_comp" {' -` tuples "'N_DAI_IN($2)`_tuples_w_comp"' -`}' -`SectionVendorTuples."'N_DAI_IN($2)`_tuples_w" {' -` tokens "sof_dai_tokens"' -` tuples."word" {' -` SOF_TKN_DAI_INDEX' $2 -` SOF_TKN_DAI_DIRECTION' "1" -` }' -`}' -`SectionData."'N_DAI_IN($2)`_data_w" {' -` tuples "'N_DAI_IN($2)`_tuples_w"' -`}' -`SectionVendorTuples."'N_DAI_IN($2)`_tuples_str" {' -` tokens "sof_dai_tokens"' -` tuples."string" {' -` SOF_TKN_DAI_TYPE' $1 -` }' -`}' -`SectionData."'N_DAI_IN($2)`_data_str" {' -` tuples "'N_DAI_IN($2)`_tuples_str"' -`}' -`SectionVendorTuples."'N_DAI_IN($2)`_tuples_comp_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($4) -` }' -`}' -`SectionData."'N_DAI_IN($2)`_data_comp_str" {' -` tuples "'N_DAI_IN($2)`_tuples_comp_str"' -`}' -`SectionWidget."'N_DAI_IN`" {' -` index "'PIPELINE_ID`"' -` type "dai_out"' -` stream_name' STR($3) -` no_pm "true"' -` data [' -` "'N_DAI_IN($2)`_data_w"' -` "'N_DAI_IN($2)`_data_w_comp"' -` "'N_DAI_IN($2)`_data_str"' -` "'N_DAI_IN($2)`_data_comp_str"' -` ]' -`}') - -dnl D_DAI(id, playback, capture, data)) -define(`D_DAI', `SectionDAI."'N_DAI`" {' -` index "'PIPELINE_ID`"' -` id "'$1`"' -` playback "'$2`"' -` capture "'$3`"' -`}') - -dnl DAI Config) -define(`N_DAI_CONFIG', `DAICONFIG.'$1) -dnl DAI_CONFIG(type, idx, link_id, name, sai_config/esai_config/ssp_config/dmic_config) -define(`DO_DAI_CONFIG', -`SectionHWConfig."'$1$2`" {' -`' -` id "'$3`"' -`' -` ifelse($1, `SSP', $5, $1, `ESAI', $5, $1, `SAI', $5, `}')' -`ifelse($1, `DMIC', $5, `')' -`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples_common" {' -` tokens "sof_dai_tokens"' -` tuples."string" {' -` SOF_TKN_DAI_TYPE' STR($1) -` }' -` tuples."word" {' -` SOF_TKN_DAI_INDEX' STR($2) -` }' -`}' -`SectionData."'N_DAI_CONFIG($1$2)`_data_common" {' -` tuples "'N_DAI_CONFIG($1$2)`_tuples_common"' -`}' -`' -`SectionBE."'$4`" {' -` id "'$3`"' -` index "0"' -` default_hw_conf_id "'$3`"' -`' -` hw_configs [' -` "'$1$2`"' -` ]' -` data [' -` ifelse($1, `HDA', `', ifelse($1, `ALH', `', "'N_DAI_CONFIG($1$2)`_data"))' -` "'N_DAI_CONFIG($1$2)`_data_common"' -`ifelse($1, `DMIC',` "'N_DAI_CONFIG($1$2)`_pdm_data"', `')' -` ]' -`}' -`DEBUG_DAI_CONFIG($1, $3)' -) - -dnl DAI_CONFIG(type, idx, link_id, name, ssp_config/dmic_config) -define(`DAI_CONFIG', -`ifelse(`$#', `5', `DO_DAI_CONFIG($1, $2, $3, $4, $5)', `$#', `4', `DO_DAI_CONFIG($1, $2, $3, $4)', `fatal_error(`Invalid parameters ($#) to DAI_CONFIG')')' -) - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl period , priority, core, time_domain) -define(`DAI_ADD', -`undefine(`PIPELINE_ID')' -`undefine(`DAI_TYPE')' -`undefine(`DAI_INDEX')' -`undefine(`DAI_BE')' -`undefine(`DAI_BUF')' -`undefine(`DAI_PERIODS')' -`undefine(`DAI_FORMAT')' -`undefine(`SCHEDULE_PERIOD')' -`undefine(`SCHEDULE_PRIORITY')' -`undefine(`SCHEDULE_CORE')' -`undefine(`SCHEDULE_TIME_DOMAIN')' -`define(`PIPELINE_ID', $2)' -`define(`DAI_TYPE', STR($3))' -`define(`DAI_INDEX', STR($4))' -`define(`DAI_BE', $5)' -`define(`DAI_BUF', $6)' -`define(`DAI_NAME', $3$4)' -`define(`DAI_PERIODS', $7)' -`define(`DAI_FORMAT', $8)' -`define(`SCHEDULE_PERIOD', $9)' -`define(`SCHEDULE_PRIORITY', $10)' -`define(`SCHEDULE_CORE', $11)' -`define(`SCHEDULE_TIME_DOMAIN', $12)' -`include($1)' -`DEBUG_DAI($3, $4)' -) - -# DAI_ADD_SCHED can be used for adding a DAI with sched_comp -dnl DAI_ADD_SCHED(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl period , priority, core, time_domain, sched_comp) -define(`DAI_ADD_SCHED', -`undefine(`SCHED_COMP')' -`define(`SCHED_COMP', $13)' -`DAI_ADD($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)' -) -divert(0)dnl diff --git a/tools/topology/m4/demux_coef_default.m4 b/tools/topology/m4/demux_coef_default.m4 deleted file mode 100644 index 503da3039f1b..000000000000 --- a/tools/topology/m4/demux_coef_default.m4 +++ /dev/null @@ -1,11 +0,0 @@ -CONTROLBYTES_PRIV(DEMUX_priv, -` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x28,0x00,0x00,0x00,0x00,0x60,0x00,0x03,' -` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' -` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' -` 0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,' -` 0x01,0x00,0x00,0x00,0x02,0x01,0x02,0x04,' -` 0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,' -` 0x05,0x00,0x00,0x00,0x02,0x01,0x02,0x04,' -` 0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00"' -) diff --git a/tools/topology/m4/detect.m4 b/tools/topology/m4/detect.m4 deleted file mode 100644 index 3a7b8d3d61d6..000000000000 --- a/tools/topology/m4/detect.m4 +++ /dev/null @@ -1,52 +0,0 @@ -divert(-1) - -dnl Define macro for generic detection widget - -dnl Detect name) -define(`N_DETECT', `DETECT'PIPELINE_ID`.'$1) - -dnl W_DETECT(name, format, periods_sink, periods_source, detect_type, stream_name, kcontrols_list) -define(`W_DETECT', -`SectionVendorTuples."'N_DETECT($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionVendorTuples."'N_DETECT($1)`_detect_process_tuples_str" {' -` tokens "sof_process_tokens"' -` tuples."string" {' -` SOF_TKN_PROCESS_TYPE' STR(concat($5, _DETECT)) -` }' -`}' -`SectionData."'N_DETECT($1)`_data_w" {' -` tuples "'N_DETECT($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_DETECT($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_DETECT($1)`_data_str" {' -` tuples "'N_DETECT($1)`_tuples_str"' -` tuples "'N_DETECT($1)`_detect_process_tuples_str"' -`}' -`SectionWidget."'N_DETECT($1)`" {' -` index "'PIPELINE_ID`"' -` type "effect"' -` stream_name' STR($6) -` no_pm "true"' -` event_flags "15"' # trapping PRE/POST_PMU/PMD events -` event_type "1"' # 1 for DAPM event for detect component -` data [' -` "'N_DETECT($1)`_data_w"' -` "'N_DETECT($1)`_data_str"' -` ]' -` bytes [' - $7 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/eq_fir.m4 b/tools/topology/m4/eq_fir.m4 deleted file mode 100644 index fa49cab5dff6..000000000000 --- a/tools/topology/m4/eq_fir.m4 +++ /dev/null @@ -1,52 +0,0 @@ -divert(-1) - -dnl Define macro for Eq effect widget - -dnl EQ name) -define(`N_EQ_FIR', `EQFIR'PIPELINE_ID`.'$1) - -dnl W_EQ(name, format, periods_sink, periods_source, kcontrols_list) -define(`W_EQ_FIR', -`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_EQ_FIR($1)`_data_w" {' -` tuples "'N_EQ_FIR($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_EQ_FIR($1)`_data_str" {' -` tuples "'N_EQ_FIR($1)`_tuples_str"' -`}' -`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_str_type" {' -` tokens "sof_process_tokens"' -` tuples."string" {' -` SOF_TKN_PROCESS_TYPE' "EQFIR" -` }' -`}' -`SectionData."'N_EQ_FIR($1)`_data_str_type" {' -` tuples "'N_EQ_FIR($1)`_tuples_str_type"' -`}' -`SectionWidget."'N_EQ_FIR($1)`" {' -` index "'PIPELINE_ID`"' -` type "effect"' -` no_pm "true"' -` data [' -` "'N_EQ_FIR($1)`_data_w"' -` "'N_EQ_FIR($1)`_data_str"' -` "'N_EQ_FIR($1)`_data_str_type"' -` ]' -` bytes [' - $5 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/eq_iir.m4 b/tools/topology/m4/eq_iir.m4 deleted file mode 100644 index 47dcf8ba0c35..000000000000 --- a/tools/topology/m4/eq_iir.m4 +++ /dev/null @@ -1,52 +0,0 @@ -divert(-1) - -dnl Define macro for Eq effect widget - -dnl EQ name) -define(`N_EQ_IIR', `EQIIR'PIPELINE_ID`.'$1) - -dnl W_EQ(name, format, periods_sink, periods_source, kcontrols_list) -define(`W_EQ_IIR', -`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_EQ_IIR($1)`_data_w" {' -` tuples "'N_EQ_IIR($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_EQ_IIR($1)`_data_str" {' -` tuples "'N_EQ_IIR($1)`_tuples_str"' -`}' -`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_str_type" {' -` tokens "sof_process_tokens"' -` tuples."string" {' -` SOF_TKN_PROCESS_TYPE' "EQIIR" -` }' -`}' -`SectionData."'N_EQ_IIR($1)`_data_str_type" {' -` tuples "'N_EQ_IIR($1)`_tuples_str_type"' -`}' -`SectionWidget."'N_EQ_IIR($1)`" {' -` index "'PIPELINE_ID`"' -` type "effect"' -` no_pm "true"' -` data [' -` "'N_EQ_IIR($1)`_data_w"' -` "'N_EQ_IIR($1)`_data_str"' -` "'N_EQ_IIR($1)`_data_str_type"' -` ]' -` bytes [' - $5 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/kpbm.m4 b/tools/topology/m4/kpbm.m4 deleted file mode 100644 index 8a3694dbcf60..000000000000 --- a/tools/topology/m4/kpbm.m4 +++ /dev/null @@ -1,49 +0,0 @@ -divert(-1) - -dnl Define macro for Key Phrase Buffer Manager(kpbm) widget - -dnl kpbm Name) -define(`N_KPBM', `KPBM'$2`.'$1) - -dnl W_KPBM(name, format, periods_sink, periods_source, pipeline_id, kcontrols_list) -define(`W_KPBM', -`SectionVendorTuples."'N_KPBM($1, $5)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_KPBM($1, $5)`_data_w" {' -` tuples "'N_KPBM($1, $5)`_tuples_w"' -`}' -`SectionVendorTuples."'N_KPBM($1, $5)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionVendorTuples."'N_KPBM($1)`_process_tuples_str" {' -` tokens "sof_process_tokens"' -` tuples."string" {' -` SOF_TKN_PROCESS_TYPE' "KPB" -` }' -`}' -`SectionData."'N_KPBM($1, $5)`_data_str" {' -` tuples "'N_KPBM($1, $5)`_tuples_str"' -` tuples "'N_KPBM($1)`_process_tuples_str"' -`}' -`SectionWidget."'N_KPBM($1, $5)`" {' -` index STR($5)' -` type "effect"' -` no_pm "true"' -` data [' -` "'N_KPBM($1, $5)`_data_w"' -` "'N_KPBM($1, $5)`_data_str"' -` ]' -` bytes [' - $6 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/mixer.m4 b/tools/topology/m4/mixer.m4 deleted file mode 100644 index 860e78166b15..000000000000 --- a/tools/topology/m4/mixer.m4 +++ /dev/null @@ -1,42 +0,0 @@ -divert(-1) - -dnl Define macro for Mixer widget - -dnl Mixer Name) -define(`N_MIXER', `MIXER'PIPELINE_ID`.'$1) - -dnl Pipe Buffer name in pipeline (pipeline, buffer) -define(`NPIPELINE_MIXER', `MIXER'$1`.'$2) - -dnl W_MIXER(name, format, periods_sink, periods_source) -define(`W_MIXER', -`SectionVendorTuples."'N_MIXER($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_MIXER($1)`_data_w" {' -` tuples "'N_MIXER($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_MIXER($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_MIXER($1)`_data_str" {' -` tuples "'N_MIXER($1)`_tuples_str"' -`}' -`SectionWidget."'N_MIXER($1)`" {' -` index "'PIPELINE_ID`"' -` type "mixer"' -` no_pm "true"' -` data [' -` "'N_MIXER($1)`_data_w"' -` "'N_MIXER($1)`_data_str"' -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/muxdemux.m4 b/tools/topology/m4/muxdemux.m4 deleted file mode 100644 index b1f7a8bd9fb9..000000000000 --- a/tools/topology/m4/muxdemux.m4 +++ /dev/null @@ -1,49 +0,0 @@ -divert(-1) - -dnl Define macro for demux widget - -dnl Mux name) -define(`N_MUXDEMUX', `MUXDEMUX'PIPELINE_ID`.'$1) - -dnl W_MUXDEMUX(name, mux/demux, format, periods_sink, periods_source, kcontrol_list) -define(`W_MUXDEMUX', -`SectionVendorTuples."'N_MUXDEMUX($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($4) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($5) -` }' -`}' -`SectionData."'N_MUXDEMUX($1)`_data_w" {' -` tuples "'N_MUXDEMUX($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_MUXDEMUX($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($3) -` }' -`}' -`SectionVendorTuples."'N_MUXDEMUX($1)`_mux_process_tuples_str" {' -` tokens "sof_process_tokens"' -` tuples."string" {' -`ifelse(`$2', `0', ` SOF_TKN_PROCESS_TYPE' "MUX", ` SOF_TKN_PROCESS_TYPE' "DEMUX")' -` }' -`}' -`SectionData."'N_MUXDEMUX($1)`_data_str" {' -` tuples "'N_MUXDEMUX($1)`_tuples_str"' -` tuples "'N_MUXDEMUX($1)`_mux_process_tuples_str"' -`}' -`SectionWidget."'N_MUXDEMUX($1)`" {' -` index "'PIPELINE_ID`"' -` type "effect"' -` no_pm "true"' -` data [' -` "'N_MUXDEMUX($1)`_data_w"' -` "'N_MUXDEMUX($1)`_data_str"' -` ]' -` bytes [' - $6 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/pcm.m4 b/tools/topology/m4/pcm.m4 deleted file mode 100644 index 48286a095bf4..000000000000 --- a/tools/topology/m4/pcm.m4 +++ /dev/null @@ -1,163 +0,0 @@ -divert(-1) - -dnl Define the macro for PCM playback/capture/capabilities - -dnl PCM name) -define(`N_PCMP', `PCM'$1`P') -define(`N_PCMC', `PCM'$1`C') - -dnl W_PCM_PLAYBACK(pcm, stream, periods_sink, periods_source) -dnl PCM platform configuration -define(`W_PCM_PLAYBACK', -`SectionVendorTuples."'N_PCMP($1)`_tuples_w_comp" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_PCMP($1)`_data_w_comp" {' -` tuples "'N_PCMP($1)`_tuples_w_comp"' -`}' -`SectionWidget."'N_PCMP($1)`" {' -` index "'PIPELINE_ID`"' -` type "aif_in"' -` no_pm "true"' -` stream_name "'$2` '$1`"' -` data [' -` "'N_PCMP($1)`_data_w_comp"' -` ]' -`}') - - -dnl W_PCM_CAPTURE(pcm, stream, periods_sink, periods_source) -define(`W_PCM_CAPTURE', -`SectionVendorTuples."'N_PCMC($1)`_tuples_w_comp" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_PCMC($1)`_data_w_comp" {' -` tuples "'N_PCMC($1)`_tuples_w_comp"' -`}' -`SectionWidget."'N_PCMC($1)`" {' -` index "'PIPELINE_ID`"' -` type "aif_out"' -` no_pm "true"' -` stream_name "'$2` '$1`"' -` data [' -` "'N_PCMC($1)`_data_w_comp"' -` ]' -`}') - -dnl PCM_CAPABILITIES(name, formats, rate_min, rate_max, channels_min, channels_max, periods_min, periods_max, period_size_min, period_size_max, buffer_size_min, buffer_size_max) -define(`PCM_CAPABILITIES', -`SectionPCMCapabilities.STR($1) {' -`' -` formats "$2"' -` rate_min STR($3)' -` rate_max STR($4)' -` channels_min STR($5)' -` channels_max STR($6)' -` periods_min STR($7)' -` periods_max STR($8)' -` period_size_min STR($9)' -` period_size_max STR($10)' -` buffer_size_min STR($11)' -` buffer_size_max STR($12)' -`}') - -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -define(`PCM_PLAYBACK_ADD', -`ifelse(`$#', `3', -`SectionPCM.STR($1) {' -`' -` # used for binding to the PCM' -` id STR($2)' -`' -` dai.STR($1 $2) {' -` id STR($2)' -` }' -`' -` pcm."playback" {' -`' -` capabilities STR($3)' -` }' -`}', `fatal_error(`Invalid parameters ($#) to PCM_PLAYBACK_ADD')')' -) - -dnl PCM_CAPTURE_ADD_COMMON(name, pcm_id, capture, lp) -define(`PCM_CAPTURE_ADD_COMMON', -`ifelse(`$4', `1', -`SectionVendorTuples."$1_tuples_w" {' -` tokens "sof_stream_tokens"' -` tuples."bool" {' -` SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 "true"' -` }' -`}' -`' -`SectionData."$1_data_w" {' -` tuples "$1_tuples_w"' -`}', `')' -`' -`SectionPCM.STR($1) {' -`' -` # used for binding to the PCM' -` id STR($2)' -`' -` dai.STR($1 $2) {' -` id STR($2)' -` }' -`' -` pcm."capture" {' -`' -` capabilities STR($3)' -` }' -`ifelse(`$4', `1', -` data [' -` "$1_data_w"' -` ]', `')' -`}' -) - -dnl PCM_CAPTURE_ADD(name, pcm_id, capture) -define(`PCM_CAPTURE_ADD', -`ifelse(`$#', `3', -PCM_CAPTURE_ADD_COMMON($1, $2, $3, 0), -`fatal_error(`Invalid parameters ($#) to PCM_CAPTURE_ADD')')' -) - -dnl PCM_CAPTURE_LP_ADD(name, pcm_id, capture) -define(`PCM_CAPTURE_LP_ADD', -`ifelse(`$#', `3', -PCM_CAPTURE_ADD_COMMON($1, $2, $3, 1), -`fatal_error(`Invalid parameters ($#) to PCM_CAPTURE_LP_ADD')')' -) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -define(`PCM_DUPLEX_ADD', -`ifelse(`$#', `4', -`SectionPCM.STR($1) {' -`' -` # used for binding to the PCM' -` id STR($2)' -`' -` dai.STR($1 $2) {' -` id STR($2)' -` }' -`' -` pcm."capture" {' -`' -` capabilities STR($4)' -` }' -`' -` pcm."playback" {' -`' -` capabilities STR($3)' -` }' -`}', `fatal_error(`Invalid parameters ($#) to PCM_DUPLEX_ADD')')' -) - -divert(0)dnl diff --git a/tools/topology/m4/pga.m4 b/tools/topology/m4/pga.m4 deleted file mode 100644 index 7233a7e6f05b..000000000000 --- a/tools/topology/m4/pga.m4 +++ /dev/null @@ -1,45 +0,0 @@ -divert(-1) - -dnl Define macro for PGA widget - -dnl PGA name) - -define(`N_PGA', `PGA'PIPELINE_ID`.'$1) - -dnl W_PGA(name, format, periods_sink, periods_source, kcontrol0. kcontrol1...etc) -define(`W_PGA', -`SectionVendorTuples."'N_PGA($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_PGA($1)`_data_w" {' -` tuples "'N_PGA($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_PGA($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_PGA($1)`_data_str" {' -` tuples "'N_PGA($1)`_tuples_str"' -`}' -`SectionWidget.ifdef(`PGA_NAME', "`PGA_NAME'", "`N_PGA($1)'") {' -` index "'PIPELINE_ID`"' -` type "pga"' -` no_pm "true"' -` data [' -` "'N_PGA($1)`_data_w"' -` "'N_PGA($1)`_data_str"' -` "'$5`"' -` ]' -` mixer [' - $6 -` ]' - -`}') - -divert(0)dnl diff --git a/tools/topology/m4/pipeline.m4 b/tools/topology/m4/pipeline.m4 deleted file mode 100644 index 37c5ca8d80ad..000000000000 --- a/tools/topology/m4/pipeline.m4 +++ /dev/null @@ -1,155 +0,0 @@ -divert(-1) - -# list of generic scheduling time domains -define(`SCHEDULE_TIME_DOMAIN_DMA', 0) -define(`SCHEDULE_TIME_DOMAIN_TIMER', 1) - -# default number of DAI periods -define(`DAI_DEFAULT_PERIODS', 2) - -dnl Define macro for pipeline widget - -dnl Pipeline name) -define(`N_PIPELINE', `PIPELINE.'PIPELINE_ID`.'$1) - -dnl W_PIPELINE(stream, period, priority, core, initiator, platform) -define(`W_PIPELINE', -`SectionVendorTuples."'N_PIPELINE($1)`_tuples" {' -` tokens "sof_sched_tokens"' -` tuples."word" {' -` SOF_TKN_SCHED_PERIOD' STR($2) -` SOF_TKN_SCHED_PRIORITY' STR($3) -` SOF_TKN_SCHED_CORE' STR($4) -` SOF_TKN_SCHED_FRAMES' "0" -` SOF_TKN_SCHED_TIME_DOMAIN' STR($5) -` }' -`}' -`SectionData."'N_PIPELINE($1)`_data" {' -` tuples "'N_PIPELINE($1)`_tuples"' -`}' -`SectionWidget."'N_PIPELINE($1)`" {' -` index "'PIPELINE_ID`"' -` type "scheduler"' -` no_pm "true"' -` stream_name "'$1`"' -` data [' -` "'N_PIPELINE($1)`_data"' -` "'$6`"' -` ]' -`}') - -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) -define(`PIPELINE_PCM_ADD', -`ifelse(eval(`$# > 10'), `1', -`undefine(`PCM_ID')' -`undefine(`PIPELINE_ID')' -`undefine(`PIPELINE_CHANNELS')' -`undefine(`PIPELINE_FORMAT')' -`undefine(`SCHEDULE_PERIOD')' -`undefine(`SCHEDULE_PRIORITY')' -`undefine(`SCHEDULE_CORE')' -`undefine(`PCM_MIN_RATE')' -`undefine(`PCM_MAX_RATE')' -`undefine(`PIPELINE_RATE')' -`undefine(`SCHEDULE_TIME_DOMAIN')' -`undefine(`DAI_FORMAT')' -`undefine(`SCHED_COMP')' -`undefine(`DAI_PERIODS')' -`define(`PIPELINE_ID', $2)' -`define(`PCM_ID', $3)' -`define(`PIPELINE_CHANNELS', $4)' -`define(`PIPELINE_FORMAT', $5)' -`define(`SCHEDULE_PERIOD', $6)' -`define(`SCHEDULE_PRIORITY', $7)' -`define(`SCHEDULE_CORE', $8)' -`define(`PCM_MIN_RATE', $9)' -`define(`PCM_MAX_RATE', $10)' -`define(`PIPELINE_RATE', $11)' -`define(`SCHEDULE_TIME_DOMAIN', $12)' -`define(`DAI_FORMAT', $5)' -`define(`SCHED_COMP', $13)' -`define(`DAI_PERIODS', DAI_DEFAULT_PERIODS)' -`include($1)' -`DEBUG_PCM_ADD($1, $3)' -,`fatal_error(`Invalid parameters ($#) to PIPELINE_PCM_ADD')')' -) - -dnl PIPELINE_PCM_DAI_ADD(pipeline, -dnl pipe id, pcm, max channels, format, -dnl period, priority, core, -dnl dai type, dai_index, dai format, -dnl periods, time_domain) -define(`PIPELINE_PCM_DAI_ADD', -`ifelse(`$#', `15', -`undefine(`PCM_ID')' -`undefine(`PIPELINE_ID')' -`undefine(`PIPELINE_CHANNELS')' -`undefine(`PIPELINE_FORMAT')' -`undefine(`SCHEDULE_PERIOD')' -`undefine(`SCHEDULE_PRIORITY')' -`undefine(`SCHEDULE_CORE')' -`undefine(`SCHEDULE_TIME_DOMAIN')' -`undefine(`DAI_TYPE')' -`undefine(`DAI_INDEX')' -`undefine(`DAI_FORMAT')' -`undefine(`DAI_PERIODS')' -`undefine(`PCM_MIN_RATE')' -`undefine(`PCM_MAX_RATE')' -`undefine(`PIPELINE_RATE')' -`define(`PIPELINE_ID', $2)' -`define(`PCM_ID', $3)' -`define(`PIPELINE_CHANNELS', $4)' -`define(`PIPELINE_FORMAT', $5)' -`define(`SCHEDULE_PERIOD', $6)' -`define(`SCHEDULE_PRIORITY', $7)' -`define(`SCHEDULE_CORE', $8)' -`define(`SCHEDULE_TIME_DOMAIN', $16)' -`define(`DAI_TYPE', STR($9))' -`define(`DAI_INDEX', STR($10))' -`define(`DAI_FORMAT', $11)' -`define(`DAI_PERIODS', $12)' -`define(`DAI_NAME', $9$10)' -`define(`PCM_MIN_RATE', $13)' -`define(`PCM_MAX_RATE', $14)' -`define(`PIPELINE_RATE', $15)' -`include($1)' -,`fatal_error(`Invalid parameters ($#) to PIPELINE_PCM_DAI_ADD')')' -) - -dnl PIPELINE_ADD(pipeline, -dnl pipe id, max channels, format, -dnl period, priority, core, -dnl sched_comp, time_domain, -dnl pcm_min_rate, pcm_max_rate, pipeline_rate) -define(`PIPELINE_ADD', -`ifelse(`$#', `12', -`undefine(`PIPELINE_ID')' -`undefine(`PIPELINE_CHANNELS')' -`undefine(`PIPELINE_FORMAT')' -`undefine(`SCHEDULE_PERIOD')' -`undefine(`SCHEDULE_PRIORITY')' -`undefine(`SCHEDULE_CORE')' -`undefine(`SCHEDULE_TIME_DOMAIN')' -`undefine(`PCM_MIN_RATE')' -`undefine(`PCM_MAX_RATE')' -`undefine(`PIPELINE_RATE')' -`define(`PIPELINE_ID', $2)' -`define(`PIPELINE_CHANNELS', $3)' -`define(`PIPELINE_FORMAT', $4)' -`define(`SCHEDULE_PERIOD', $5)' -`define(`SCHEDULE_PRIORITY', $6)' -`define(`SCHEDULE_CORE', $7)' -`define(`SCHEDULE_TIME_DOMAIN', $9)' -`define(`SCHED_COMP', $8)' -`define(`PCM_MIN_RATE', $10)' -`define(`PCM_MAX_RATE', $11)' -`define(`PIPELINE_RATE', $12)' -`include($1)' -,`fatal_error(`Invalid parameters ($#) to PIPELINE_ADD')')' -) - -divert(0)dnl diff --git a/tools/topology/m4/src.m4 b/tools/topology/m4/src.m4 deleted file mode 100644 index 90099a221e10..000000000000 --- a/tools/topology/m4/src.m4 +++ /dev/null @@ -1,40 +0,0 @@ -divert(-1) - -dnl Defines the macro for SRC widget - -dnl SRC name) -define(`N_SRC', `SRC'PIPELINE_ID`.'$1) - -dnl W_SRC(name, format, periods_sink, periods_source, data) -define(`W_SRC', -`SectionVendorTuples."'N_SRC($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionData."'N_SRC($1)`_data_w" {' -` tuples "'N_SRC($1)`_tuples_w"' -`}' -`SectionVendorTuples."'N_SRC($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_SRC($1)`_data_str" {' -` tuples "'N_SRC($1)`_tuples_str"' -`}' -`SectionWidget."'N_SRC($1)`" {' -` index "'PIPELINE_ID`"' -` type "src"' -` no_pm "true"' -` data [' -` "'N_SRC($1)`_data_w"' -` "'N_SRC($1)`_data_str"' -` "'$5`"' -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/tone.m4 b/tools/topology/m4/tone.m4 deleted file mode 100644 index dbfb88b2c333..000000000000 --- a/tools/topology/m4/tone.m4 +++ /dev/null @@ -1,49 +0,0 @@ -divert(-1) - -dnl Define macro for siggen widget - -dnl Tone name) -define(`N_TONE', `TONE'PIPELINE_ID`.'$1) - -dnl W_TONE(name, format, periods_sink, periods_source, kcontrols_list) -define(`W_TONE', -`SectionVendorTuples."'N_TONE($1)`_tuples_w" {' -` tokens "sof_comp_tokens"' -` tuples."word" {' -` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) -` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) -` }' -`}' -`SectionVendorTuples."'N_TONE($1)`_tone_tuples_w" {' -` tokens "sof_tone_tokens"' -` tuples."word" {' -` SOF_TKN_TONE_SAMPLE_RATE' ifdef(TONE_SAMPLE_RATE, STR(TONE_SAMPLE_RATE), "48000") -` }' -`}' -`SectionData."'N_TONE($1)`_data_w" {' -` tuples "'N_TONE($1)`_tuples_w"' -` tuples "'N_TONE($1)`_tone_tuples_w"' -`}' -`SectionVendorTuples."'N_TONE($1)`_tuples_str" {' -` tokens "sof_comp_tokens"' -` tuples."string" {' -` SOF_TKN_COMP_FORMAT' STR($2) -` }' -`}' -`SectionData."'N_TONE($1)`_data_str" {' -` tuples "'N_TONE($1)`_tuples_str"' -`}' -`SectionWidget."'N_TONE($1)`" {' -` index "'PIPELINE_ID`"' -` type "siggen"' -` no_pm "true"' -` data [' -` "'N_TONE($1)`_data_w"' -` "'N_TONE($1)`_data_str"' -` ]' -` mixer [' - $5 -` ]' -`}') - -divert(0)dnl diff --git a/tools/topology/m4/utils.m4 b/tools/topology/m4/utils.m4 deleted file mode 100644 index d34701335745..000000000000 --- a/tools/topology/m4/utils.m4 +++ /dev/null @@ -1,118 +0,0 @@ -divert(-1) - -include(`debug.m4') - -define(`concat',`$1$2') - -define(`STR', `"'$1`"') - -dnl Argument iterator. -define(`argn', `ifelse(`$1', 1, ``$2'', - `argn(decr(`$1'), shift(shift($@)))')') - -define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* -')m4exit(1)') - -dnl Defines a list of items from a variable number of params. -dnl Use as last argument in a macro. -dnl The first argument specifies the number of tabs to be added for formatting -define(`LIST_LOOP', `argn(j,$@) -$1ifelse(i,`2', `', `define(`i', decr(i))define(`j', incr(j))$0($@)')') - -define(`LIST', `pushdef(`i', $#)pushdef(`j', `2')LIST_LOOP($@)popdef(i)popdef(j)') - -dnl Sums a list of variable arguments. Use as last argument in macro. -define(`SUM_LOOP', `eval(argn(j,$@) - ifelse(i,`1', `', `define(`i', decr(i)) define(`j', incr(j)) + $0($@)'))') - -dnl Memory capabilities -define(`MEMCAPS', `pushdef(`i', $#) pushdef(`j', `1') SUM_LOOP($@)') - -dnl create direct DAPM/pipeline link between 2 widgets) -define(`dapm', `"$1, , $2"'`DEBUG_GRAPH($1, $2)') - -dnl COMP_SAMPLE_SIZE(FMT) -define(`COMP_SAMPLE_SIZE', -`ifelse( - $1, `s16le', `2', - $1, `s24_4le', `4', - $1, `s32le', `4', - $1, `float', `4', - `4')') - -dnl COMP_FORMAT_NAME(FMT) -define(`COMP_FORMAT_NAME', -`ifelse( - $1, `s16le', `S16_LE', - $1, `s24le', `S24_LE', - $1, `s32le', `S32_LE', - $1, `float', `FLOAT_LE', - )') - -dnl P_GRAPH(NAME, PIPELINE_ID, CONNECTIONS) -define(`P_GRAPH', -`SectionGraph.STR($1 $2) {' -` index STR($2)' -`' -` lines [' -` $3' -` ]' -`}') - -dnl W_VENDORTUPLES(name, tokens, RATE_OUT) -define(`W_VENDORTUPLES', -`SectionVendorTuples.STR($1) {' -` tokens STR($2)' -`' -` tuples."word" {' -` $3' -` }' -`}') - -dnl W_DATA(name, tuples) -define(`W_DATA', -`SectionData.STR($1) {' -` tuples STR($2)' -`}') - -dnl VIRTUAL_DAPM_ROUTE_OUT(name, dai type, dai index, direction, index) -define(`VIRTUAL_DAPM_ROUTE_OUT', -`SectionWidget.STR($1) {' -` index STR($5)' -` type "output"' -` no_pm "true"' -`}' -`SectionGraph.STR($2) {' -` index STR($5)' -`' -` lines [' -` dapm($1,$2$3.$4)' -` ]' -`}') - -dnl VIRTUAL_DAPM_ROUTE_IN(name, dai type, dai index, direction, index) -define(`VIRTUAL_DAPM_ROUTE_IN', -`SectionWidget.STR($1) {' -` index STR($5)' -` type "input"' -` no_pm "true"' -`}' -`SectionGraph.STR($2) {' -` index STR($5)' -`' -` lines [' -` dapm($2$3.$4, $1)' -` ]' -`}') - -dnl VIRTUAL_WIDGET(name, type, index) -define(`VIRTUAL_WIDGET', -`ifelse(`$#', `3', -`SectionWidget.STR($1) {' -` index STR($3)' -` type STR($2)' -` no_pm "true"' -`}', `fatal_error(`Invalid parameters ($#) to VIRTUAL_WIDGET')')') - -divert(0) dnl - diff --git a/tools/topology/platform/common/ssp.m4 b/tools/topology/platform/common/ssp.m4 deleted file mode 100644 index 22edd8578d72..000000000000 --- a/tools/topology/platform/common/ssp.m4 +++ /dev/null @@ -1,52 +0,0 @@ -divert(-1) - -dnl SSP related macros - -dnl SSP_CLOCK(clock, freq, codec_master, polarity) -dnl polarity is optional -define(`SSP_CLOCK', - $1 STR($3) - $1_freq STR($2) - `ifelse($4, `inverted', `$1_invert "true"',`')') - -dnl SSP_TDM(slots, width, tx_mask, rx_mask) -define(`SSP_TDM', -`tdm_slots 'STR($1) -` tdm_slot_width 'STR($2) -` tx_slots 'STR($3) -` rx_slots 'STR($4) -) -dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) -define(`SSP_CONFIG', -` format "'$1`"' -` '$2 -` '$3 -` '$4 -` '$5 -`}' -$6 -) - -dnl SSP_QUIRK_LBM 64 = (1 << 6) -define(`SSP_QUIRK_LBM', 64) - -dnl SSP_CONFIG_DATA(type, idx, valid bits, mclk_id, quirks, bclk_delay) -dnl mclk_id, quirks, bclk_delay are optional -define(`SSP_CONFIG_DATA', -`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' -` tokens "sof_ssp_tokens"' -` tuples."word" {' -` SOF_TKN_INTEL_SSP_SAMPLE_BITS' STR($3) -` SOF_TKN_INTEL_SSP_QUIRKS' ifelse($5, `', "0", STR($5)) -` SOF_TKN_INTEL_SSP_BCLK_DELAY' ifelse($6, `', "0", STR($6)) -` }' -` tuples."short" {' -` SOF_TKN_INTEL_SSP_MCLK_ID' ifelse($4, `', "0", STR($4)) -` }' -`}' -`SectionData."'N_DAI_CONFIG($1$2)`_data" {' -` tuples "'N_DAI_CONFIG($1$2)`_tuples"' -`}' -) - -divert(0)dnl diff --git a/tools/topology/platform/imx/imx8qxp.m4 b/tools/topology/platform/imx/imx8qxp.m4 deleted file mode 100644 index f9e475268724..000000000000 --- a/tools/topology/platform/imx/imx8qxp.m4 +++ /dev/null @@ -1,14 +0,0 @@ -# -# i.MX8QXP differentiation for pipelines and components -# - -include(`memory.m4') - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) - diff --git a/tools/topology/platform/intel/bdw.m4 b/tools/topology/platform/intel/bdw.m4 deleted file mode 100644 index 1af669996969..000000000000 --- a/tools/topology/platform/intel/bdw.m4 +++ /dev/null @@ -1,31 +0,0 @@ -# -# Broadwell differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for diferent buffer types on Broadwell -define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/platform/intel/bxt.m4 b/tools/topology/platform/intel/bxt.m4 deleted file mode 100644 index 76265130e8cb..000000000000 --- a/tools/topology/platform/intel/bxt.m4 +++ /dev/null @@ -1,34 +0,0 @@ -# -# Broxton differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for diferent buffer types on Baytrail -define(`PLATFORM_DAI_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_HOST_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_PASS_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/platform/intel/byt.m4 b/tools/topology/platform/intel/byt.m4 deleted file mode 100644 index 7d5dce743275..000000000000 --- a/tools/topology/platform/intel/byt.m4 +++ /dev/null @@ -1,42 +0,0 @@ -# -# Baytrail differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for diferent buffer types on Baytrail -define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) - -VIRTUAL_WIDGET(codec_out0, output, 1) -VIRTUAL_WIDGET(codec_out1, output, 2) -VIRTUAL_WIDGET(codec_in0, input, 3) -VIRTUAL_WIDGET(codec_in1, input, 4) -VIRTUAL_WIDGET(ssp2 Rx, input, 5) -VIRTUAL_WIDGET(ssp2 Tx, output, 6) -VIRTUAL_WIDGET(ssp0 Tx, output, 7) -VIRTUAL_WIDGET(ssp0 Rx, input, 8) -VIRTUAL_WIDGET(modem_out, output, 9) -VIRTUAL_WIDGET(modem_in, input, 10) diff --git a/tools/topology/platform/intel/cht.m4 b/tools/topology/platform/intel/cht.m4 deleted file mode 100644 index 3ea12df30c00..000000000000 --- a/tools/topology/platform/intel/cht.m4 +++ /dev/null @@ -1,42 +0,0 @@ -# -# Cherrytrail differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for diferent buffer types on Cherrytrail -define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) - -VIRTUAL_WIDGET(codec_out0, output, 1) -VIRTUAL_WIDGET(codec_out1, output, 2) -VIRTUAL_WIDGET(codec_in0, input, 3) -VIRTUAL_WIDGET(codec_in1, input, 4) -VIRTUAL_WIDGET(ssp2 Rx, input, 5) -VIRTUAL_WIDGET(ssp2 Tx, output, 6) -VIRTUAL_WIDGET(ssp0 Tx, output, 7) -VIRTUAL_WIDGET(ssp0 Rx, input, 8) -VIRTUAL_WIDGET(modem_out, output, 9) -VIRTUAL_WIDGET(modem_in, input, 10) diff --git a/tools/topology/platform/intel/cml-mono.m4 b/tools/topology/platform/intel/cml-mono.m4 deleted file mode 100644 index 2f0004374cc5..000000000000 --- a/tools/topology/platform/intel/cml-mono.m4 +++ /dev/null @@ -1,3 +0,0 @@ -include(`platform/intel/cnl.m4') - -define(`MONO', `') diff --git a/tools/topology/platform/intel/cml.m4 b/tools/topology/platform/intel/cml.m4 deleted file mode 100644 index 119aa15c9962..000000000000 --- a/tools/topology/platform/intel/cml.m4 +++ /dev/null @@ -1,13 +0,0 @@ -include(`platform/intel/cnl.m4') - -#SSP setting for CML platform -undefine(`SSP_INDEX') -define(`SSP_INDEX', 0) - -undefine(`SSP_NAME') -define(`SSP_NAME', `SSP0-Codec') - -undefine(`SSP_MCLK_RATE') -define(`SSP_MCLK_RATE', `24000000') - -include(`platform/intel/dmic.m4') diff --git a/tools/topology/platform/intel/cnl.m4 b/tools/topology/platform/intel/cnl.m4 deleted file mode 100644 index 96bf6de2462b..000000000000 --- a/tools/topology/platform/intel/cnl.m4 +++ /dev/null @@ -1,35 +0,0 @@ -# -# Broxton differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for diferent buffer types on Cannonlake -define(`PLATFORM_DAI_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_HOST_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_PASS_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/platform/intel/dmic.m4 b/tools/topology/platform/intel/dmic.m4 deleted file mode 100644 index 4291543159bc..000000000000 --- a/tools/topology/platform/intel/dmic.m4 +++ /dev/null @@ -1,71 +0,0 @@ -divert(-1) - -dnl DMIC related macros - -dnl PDM_TUPLES(pdm ctrl id, mic_a_enable, mic_b_enable, polarity_a, polarity_b, -dnl clk_egde, skew) -define(`PDM_TUPLES', -` tuples."short.pdm$1" {' -` SOF_TKN_INTEL_DMIC_PDM_CTRL_ID' STR($1) -` SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable' STR($2) -` SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable' STR($3) -` SOF_TKN_INTEL_DMIC_PDM_POLARITY_A' STR($4) -` SOF_TKN_INTEL_DMIC_PDM_POLARITY_B' STR($5) -` SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE' STR($6) -` SOF_TKN_INTEL_DMIC_PDM_SKEW' STR($7) -` }' -) - -dnl PDM_CONFIG(type, idx, num pdm active, pdm tuples list) -define(`PDM_CONFIG', -` SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE' STR($3) -` }' -`}' -`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_pdm_tuples" {' -` tokens "sof_dmic_pdm_tokens"' -$4 -`}' -) - -dnl DMIC currently only supports 16 bit or 32-bit word length -dnl DMIC_WORD_LENGTH(frame format) -define(`DMIC_WORD_LENGTH', -`ifelse($1, `s16le', 16, $1, `s32le', 32, `')') - -dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, -dnl sample_rate, fifo word length, ramp_time, -dnl type, idx, pdm controller config) -define(`DMIC_CONFIG', -`SectionVendorTuples."'N_DAI_CONFIG($9$10)`_dmic_tuples" {' -` tokens "sof_dmic_tokens"' -` tuples."word" {' -` SOF_TKN_INTEL_DMIC_DRIVER_VERSION' STR($1) -` SOF_TKN_INTEL_DMIC_CLK_MIN' STR($2) -` SOF_TKN_INTEL_DMIC_CLK_MAX' STR($3) -` SOF_TKN_INTEL_DMIC_DUTY_MIN' STR($4) -` SOF_TKN_INTEL_DMIC_DUTY_MAX' STR($5) -` SOF_TKN_INTEL_DMIC_SAMPLE_RATE' STR($6) -` SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH' STR($7) -` SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS' STR($8) - -dnl PDM config for the number of active PDM controllers -$11 -`SectionData."'N_DAI_CONFIG($9$10)`_pdm_data" {' -` tuples "'N_DAI_CONFIG($9$10)`_pdm_tuples"' -`}' -`SectionData."'N_DAI_CONFIG($9$10)`_data" {' -` tuples "'N_DAI_CONFIG($9$10)`_dmic_tuples"' - -`}' -) - -dnl DMIC PDM configurations -dnl macros to get the number of active pdm's and their config -define(`MONO_PDM0_MICA', `1, LIST(`', PDM_TUPLES(0, 1, 0, 0, 0, 0, 0))') -define(`MONO_PDM0_MICB', `1, LIST(`', PDM_TUPLES(0, 0, 1, 0, 0, 0, 0))') -define(`STEREO_PDM0', `1, LIST(`', PDM_TUPLES(0, 1, 1, 0, 0, 0, 0))') -define(`STEREO_PDM1', `1, LIST(`', PDM_TUPLES(1, 1, 1, 0, 0, 0, 0))') -define(`FOUR_CH_PDM0_PDM1', - `2, LIST(`', PDM_TUPLES(0, 1, 1, 0, 0, 0, 0), PDM_TUPLES(1, 1, 1, 0, 0, 0, 0))') - -divert(0)dnl diff --git a/tools/topology/platform/intel/ehl.m4 b/tools/topology/platform/intel/ehl.m4 deleted file mode 100644 index e914bbbaa323..000000000000 --- a/tools/topology/platform/intel/ehl.m4 +++ /dev/null @@ -1,38 +0,0 @@ -# -# ElkhartLake differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for different buffer types on ElkhartLake -define(`PLATFORM_DAI_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_HOST_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_PASS_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/platform/intel/hsw.m4 b/tools/topology/platform/intel/hsw.m4 deleted file mode 100644 index c096732a7cc5..000000000000 --- a/tools/topology/platform/intel/hsw.m4 +++ /dev/null @@ -1,31 +0,0 @@ -# -# Haswell differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for diferent buffer types on Haswell -define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/platform/intel/icl.m4 b/tools/topology/platform/intel/icl.m4 deleted file mode 100644 index 5ac76905ba87..000000000000 --- a/tools/topology/platform/intel/icl.m4 +++ /dev/null @@ -1,50 +0,0 @@ -# -# Icelake differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for different buffer types on Icelake -define(`PLATFORM_DAI_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_HOST_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_PASS_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) - -#SSP setting for ICL platform -undefine(`SSP_INDEX') -define(`SSP_INDEX', 0) - -undefine(`SSP_NAME') -define(`SSP_NAME', `SSP0-Codec') - -undefine(`SSP_MCLK_RATE') -define(`SSP_MCLK_RATE', `19200000') - -include(`platform/intel/dmic.m4') diff --git a/tools/topology/platform/intel/intel-generic-dmic.m4 b/tools/topology/platform/intel/intel-generic-dmic.m4 deleted file mode 100644 index 0e8daf7dc268..000000000000 --- a/tools/topology/platform/intel/intel-generic-dmic.m4 +++ /dev/null @@ -1,86 +0,0 @@ -# -# Topology for digital microphones array -# - -include(`platform/intel/dmic.m4') - -# defined in machine driver -define(DMIC_DAI_LINK_48k_ID, `6') -define(DMIC_DAI_LINK_16k_ID, `7') - -# -# Define the pipelines -# - -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) - -# Passthrough capture pipeline using max channels defined by CHANNELS. - -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-eq-capture.m4, - DMIC_PIPELINE_48k_ID, DMIC_DAI_LINK_48k_ID, CHANNELS, s32le, - 1000, 0, 0, 48000, 48000, 48000) - -# Passthrough capture pipeline using max channels defined by CHANNELS. - -# Schedule with 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-eq-capture-16khz.m4, - DMIC_PIPELINE_16k_ID, DMIC_DAI_LINK_16k_ID, CHANNELS, s32le, - 1000, 0, 0, 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - DMIC_PIPELINE_48k_ID, DMIC, 0, dmic01, - concat(`PIPELINE_SINK_', DMIC_PIPELINE_48k_ID), 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s32le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - DMIC_PIPELINE_16k_ID, DMIC, 1, dmic16k, - concat(`PIPELINE_SINK_', DMIC_PIPELINE_16k_ID), 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, DMIC_DAI_LINK_48k_ID, concat(`PIPELINE_PCM_', DMIC_PIPELINE_48k_ID)) -PCM_CAPTURE_ADD(DMIC16kHz, DMIC_DAI_LINK_16k_ID, concat(`PIPELINE_PCM_', DMIC_PIPELINE_16k_ID)) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -ifelse(CHANNELS, 4, -`DAI_CONFIG(DMIC, 0, DMIC_DAI_LINK_48k_ID, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 200, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1)))', -`DAI_CONFIG(DMIC, 0, DMIC_DAI_LINK_48k_ID, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 200, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0)))') - -ifelse(CHANNELS, 4, -`DAI_CONFIG(DMIC, 1, DMIC_DAI_LINK_16k_ID, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, FOUR_CH_PDM0_PDM1)))', -`DAI_CONFIG(DMIC, 1, DMIC_DAI_LINK_16k_ID, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0)))') diff --git a/tools/topology/platform/intel/tgl.m4 b/tools/topology/platform/intel/tgl.m4 deleted file mode 100644 index f058b2025bbb..000000000000 --- a/tools/topology/platform/intel/tgl.m4 +++ /dev/null @@ -1,38 +0,0 @@ -# -# Tigerlake differentiation for pipelines and components -# - -include(`memory.m4') - -dnl Memory capabilities for different buffer types on Tigerlake -define(`PLATFORM_DAI_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_HOST_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_PASS_MEM_CAP', - MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE, MEM_CAP_HP)) -define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) - -# Low Latency PCM Configuration -W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) - -W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) - -# Media PCM Configuration -W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) - -W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) - -# Tone Signal Generator Configuration -W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) - -W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) - -# DAI schedule Configuration - scheduled by IRQ -W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, - LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) - -W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/platform/intel/whl.m4 b/tools/topology/platform/intel/whl.m4 deleted file mode 100644 index 185adcdff434..000000000000 --- a/tools/topology/platform/intel/whl.m4 +++ /dev/null @@ -1,13 +0,0 @@ -include(`platform/intel/cnl.m4') - -#SSP setting for WHL platform -undefine(`SSP_INDEX') -define(`SSP_INDEX', 1) - -undefine(`SSP_NAME') -define(`SSP_NAME', `SSP1-Codec') - -undefine(`SSP_MCLK_RATE') -define(`SSP_MCLK_RATE', `24000000') - -include(`platform/intel/dmic.m4') diff --git a/tools/topology/sof-apl-asrc-pcm512x.m4 b/tools/topology/sof-apl-asrc-pcm512x.m4 deleted file mode 100644 index 08c055312099..000000000000 --- a/tools/topology/sof-apl-asrc-pcm512x.m4 +++ /dev/null @@ -1,117 +0,0 @@ -# -# Topology for Apollolake UP^2 with pcm512x codec for testing ASRC -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 --> ASRC --> Volume --> SSP5 (pcm512x) -# PCM5 <-- ASRC <-- Volume <-- DMIC0 (DMIC) -# PCM6 <-- ASRC <-- Volume <-- DMIC1 (DMIC16kHz) - -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) - -# Playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-asrc-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 8000, 192000, 48000) - -# DMIC capture pipeline 2 on PCM 5 using max 2 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-asrc-volume-capture.m4, - 2, 5, 2, s32le, - 1000, 0, 0, - 8000, 192000, 48000) - -# DMIC16kHz capture pipeline 2 on PCM 6 using max 2 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-asrc-volume-capture.m4, - 3, 6, 2, s32le, - 1000, 0, 0, - 8000, 192000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, DMIC, 0, dmic01, - PIPELINE_SINK_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16kHz using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, DMIC, 1, dmic16k, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(DMIC, 5, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC16kHz, 6, PIPELINE_PCM_3) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 5 (ID: 0) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -# DMIC (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - -# DMIC16kHz (ID: 2) -DAI_CONFIG(DMIC, 1, 2, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -DEBUG_END diff --git a/tools/topology/sof-apl-asrc-wm8804.m4 b/tools/topology/sof-apl-asrc-wm8804.m4 deleted file mode 100644 index 2589535cf238..000000000000 --- a/tools/topology/sof-apl-asrc-wm8804.m4 +++ /dev/null @@ -1,71 +0,0 @@ -# -# Topology for Apollolake UP^2 with wm8804 codec for testing ASRC -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> volume -----> SSP5 (wm8804) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-asrc-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 8000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_master), - SSP_CLOCK(fsync, 48000, codec_master), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -DEBUG_END diff --git a/tools/topology/sof-apl-da7219.m4 b/tools/topology/sof-apl-da7219.m4 deleted file mode 100644 index 0c687dea8b52..000000000000 --- a/tools/topology/sof-apl-da7219.m4 +++ /dev/null @@ -1,204 +0,0 @@ -# -# Topology for ApolloLake with Dialog7219. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume (pipe 1) -----> SSP5 (speaker - maxim98357a, BE link 0) -# PCM1 <---> volume (pipe 2,3) <----> SSP1 (headset - da7219, BE link 1) -# PCM99 <---- DMIC0 (dmic capture, BE link 2) -# PCM5 ----> volume (pipe 5) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM6 ----> Volume (pipe 6) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM7 ----> volume (pipe 7) -----> iDisp3 (HDMI/DP playback, BE link 5) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 99 using max 4 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 4, 99, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 5 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 6 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 7 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 7, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 1, SSP1-Codec, - PIPELINE_SINK_3, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 3, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 4, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 5, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -PCM_PLAYBACK_ADD(Speakers, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 99, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 5 (ID: 0) with 19.2 MHz mclk with MCLK_ID 0 (unused), 1.536 MHz blck -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 16, 0))) - -#SSP 1 (ID: 1) with 19.2 MHz mclk with MCLK_ID 0, 1.92 MHz bclk -DAI_CONFIG(SSP, 1, 1, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1920000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 20, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16, 0))) - -# dmic01 (id: 2) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - # FIXME: what is the right configuration - # PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 3, 3, iDisp1) -DAI_CONFIG(HDA, 4, 4, iDisp2) -DAI_CONFIG(HDA, 5, 5, iDisp3) - -## remove warnings with SST hard-coded routes - -VIRTUAL_WIDGET(ssp5 Tx, out_drv, 0) -VIRTUAL_WIDGET(ssp1 Rx, out_drv, 1) -VIRTUAL_WIDGET(ssp1 Tx, out_drv, 2) -VIRTUAL_WIDGET(DMIC01 Rx, out_drv, 3) -VIRTUAL_WIDGET(DMic, out_drv, 4) -VIRTUAL_WIDGET(dmic01_hifi, out_drv, 5) -VIRTUAL_WIDGET(hif5-0 Output, out_drv, 6) -VIRTUAL_WIDGET(hif6-0 Output, out_drv, 7) -VIRTUAL_WIDGET(hif7-0 Output, out_drv, 8) -VIRTUAL_WIDGET(iDisp3_out, out_drv, 9) -VIRTUAL_WIDGET(iDisp2_out, out_drv, 10) -VIRTUAL_WIDGET(iDisp1_out, out_drv, 11) -VIRTUAL_WIDGET(codec0_out, output, 12) -VIRTUAL_WIDGET(codec1_out, output, 13) -VIRTUAL_WIDGET(codec0_in, input, 14) diff --git a/tools/topology/sof-apl-demux-pcm512x.m4 b/tools/topology/sof-apl-demux-pcm512x.m4 deleted file mode 100644 index 8995ca4dea34..000000000000 --- a/tools/topology/sof-apl-demux-pcm512x.m4 +++ /dev/null @@ -1,159 +0,0 @@ -# -# Demux topology for generic Apollolake UP^2 with pcm512x codec and HDMI. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> demux -----> SSP5 (pcm512x) -# PCM1 ----> volume -----> iDisp1 -# PCM2 ----> volume -----> iDisp2 -# PCM3 ----> volume -----> iDisp3 -# PCM4 <---- demux -# - -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) - -# Demux pipeline 1 on PCM 0 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-demux-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 3 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# currently this dai is here as "virtual" capture backend -W_DAI_IN(SSP, 5, SSP5-Codec, s24le, 3, 0) - -# Capture pipeline 5 from demux on PCM 5 using max 2 channels of s32le. -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture-sched.m4, - 5, 4, 2, s32le, - 1000, 1, 0, - 48000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_TIMER, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect demux to capture -SectionGraph."PIPE_CAP" { - index "0" - - lines [ - # mux to capture - dapm(PIPELINE_SINK_5, PIPELINE_DEMUX_1) - ] -} - -# Connect virtual capture to dai -SectionGraph."PIPE_CAP_VIRT" { - index "5" - - lines [ - # mux to capture - dapm(ECHO REF 5, SSP5.IN) - ] -} - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, HDA, 0, iDisp1, - PIPELINE_SOURCE_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, HDA, 1, iDisp2, - PIPELINE_SOURCE_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, HDA, 2, iDisp3, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) -PCM_PLAYBACK_ADD(HDMI1, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(HDMI2, 2, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI3, 3, PIPELINE_PCM_4) -PCM_CAPTURE_ADD(EchoRef, 4, PIPELINE_PCM_5) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 5 (ID: 0) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -# 3 HDMI/DP outputs (ID: 1,2,3) -DAI_CONFIG(HDA, 0, 1, iDisp1) -DAI_CONFIG(HDA, 1, 2, iDisp2) -DAI_CONFIG(HDA, 2, 3, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-apl-dmic-a2ch-b2ch.m4 b/tools/topology/sof-apl-dmic-a2ch-b2ch.m4 deleted file mode 100644 index a8cafc264006..000000000000 --- a/tools/topology/sof-apl-dmic-a2ch-b2ch.m4 +++ /dev/null @@ -1,100 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 2ch 32b mic1-2 -# DAI1 2ch 32b mic3-4 - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM6 <----- DMIC6 (DMIC01) -# PCM7 <----- DMIC7 (DMIC16k) -# - -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) - -# Passthrough capture pipeline 6 on PCM 6 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 7 on PCM 7 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 7, 7, 2, s32le, - 1000, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16kHz, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM1))) diff --git a/tools/topology/sof-apl-dmic-a2ch-b4ch.m4 b/tools/topology/sof-apl-dmic-a2ch-b4ch.m4 deleted file mode 100644 index e5f0dc4b5b9c..000000000000 --- a/tools/topology/sof-apl-dmic-a2ch-b4ch.m4 +++ /dev/null @@ -1,100 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 2ch 16b mic1-2 -# DAI1 4ch 32b mic1-4 - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM6 <----- DMIC6 (DMIC01) -# PCM7 <----- DMIC7 (DMIC16k) -# - -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) - -# Passthrough capture pipeline 6 on PCM 6 using max channels 2 -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 6, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 7 on PCM 7 using max channels 4. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 7, 7, 4, s32le, - 1000, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16kHz, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, FOUR_CH_PDM0_PDM1))) diff --git a/tools/topology/sof-apl-dmic-a2ch.m4 b/tools/topology/sof-apl-dmic-a2ch.m4 deleted file mode 100644 index 2c171efaa43d..000000000000 --- a/tools/topology/sof-apl-dmic-a2ch.m4 +++ /dev/null @@ -1,76 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 2ch 32b mic1-2 -# DAI1 none - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM6 <----- DMIC6 (DMIC01) -# - -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) - -# Passthrough capture pipeline 6 on PCM 6 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_6) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - diff --git a/tools/topology/sof-apl-dmic-a4ch-b2ch.m4 b/tools/topology/sof-apl-dmic-a4ch-b2ch.m4 deleted file mode 100644 index 7a47d1cc81a8..000000000000 --- a/tools/topology/sof-apl-dmic-a4ch-b2ch.m4 +++ /dev/null @@ -1,99 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 4ch 16b mic1-2 -# DAI1 2ch 16b mic1-4 - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM6 <----- DMIC6 (DMIC01) -# PCM7 <----- DMIC7 (DMIC16k) -# - -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) - -# Passthrough capture pipeline 6 on PCM 6 using max channels 4. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 6, 4, s16le, - 1000, 0, 0, DMIC, - 48000, 48000, 48000) - -# Passthrough capture pipeline 7 on PCM 7 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 7, 7, 2, s16le, - 1000, 0, 0, DMIC, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16kHz, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) diff --git a/tools/topology/sof-apl-dmic-a96k-b16k.m4 b/tools/topology/sof-apl-dmic-a96k-b16k.m4 deleted file mode 100644 index 0c58c616dba7..000000000000 --- a/tools/topology/sof-apl-dmic-a96k-b16k.m4 +++ /dev/null @@ -1,104 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 2ch 32b mic1-2 -# DAI1 2ch 32b mic1-2 - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM6 <--- volume <--- DMIC6 (DMIC01) -# PCM7 <--- volume <--- DMIC7 (DMIC16k) -# - -dnl PIPELINE_PCM_DAI_ADD(pipeline, -dnl pipe id, pcm, max channels, format, -dnl period, priority, core, -dnl dai type, dai_index, dai format, -dnl dai periods, pcm_min_rate, pcm_max_rate, -dnl pipeline_rate, time_domain) - -# Passthrough capture pipeline 6 on PCM 6 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_DAI_ADD(sof/pipe-volume-capture.m4, - 6, 6, 2, s32le, - 1000, 0, 0, DMIC, 0, s32le, 3, - 96000, 96000, 96000) - -# Passthrough capture pipeline 7 on PCM 7 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_DAI_ADD(sof/pipe-volume-capture.m4, - 7, 7, 2, s32le, - 1000, 0, 0, DMIC, 1, s32le, 3, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 3 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 3, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 3 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 3, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC01, 6, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16k, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 96000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -DEBUG_END diff --git a/tools/topology/sof-apl-dmic-b2ch.m4 b/tools/topology/sof-apl-dmic-b2ch.m4 deleted file mode 100644 index dfc2fdc01c82..000000000000 --- a/tools/topology/sof-apl-dmic-b2ch.m4 +++ /dev/null @@ -1,76 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 none -# DAI1 2ch 32b mic3-4 - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM7 <----- DMIC7 (DMIC16k) -# - -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) - -# Passthrough capture pipeline 7 on PCM 7 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 7, 7, 2, s32le, - 1000, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC16kHz, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM1))) diff --git a/tools/topology/sof-apl-dmic.m4 b/tools/topology/sof-apl-dmic.m4 deleted file mode 100644 index 3e894cd79d75..000000000000 --- a/tools/topology/sof-apl-dmic.m4 +++ /dev/null @@ -1,99 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -define(DMIC_PDM_CONFIG, ifelse(CHANNELS, `4', ``FOUR_CH_PDM0_PDM1'', - `ifelse(CHANNELS, `2', ``STEREO_PDM0'', `')')) - -# -# Define the pipelines -# -# PCM6 <----- DMIC6 (DMIC01) -# PCM7 <----- DMIC7 (DMIC16k) -# - -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) - -# Passthrough capture pipeline 6 on PCM 6 using max channels defined by CHANNELS. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 6, CHANNELS, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 7 on PCM 7 using max channels defined by CHANNELS. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 7, 7, CHANNELS, s32le, - 1000, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16kHz, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, DMIC_PDM_CONFIG))) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, DMIC_PDM_CONFIG))) diff --git a/tools/topology/sof-apl-eq-dmic.m4 b/tools/topology/sof-apl-eq-dmic.m4 deleted file mode 100644 index 6ff543c4e949..000000000000 --- a/tools/topology/sof-apl-eq-dmic.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM6 <---- EQ IIR <----- DMIC6 (DMIC01) -# - -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) - -# Passthrough capture pipeline 13 on PCM 6 using max 4 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-eq-capture.m4, - 1, 6, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 1, DMIC, 0, NoCodec-6, - PIPELINE_SINK_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) - -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time - dnl type, dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - diff --git a/tools/topology/sof-apl-eq-pcm512x.m4 b/tools/topology/sof-apl-eq-pcm512x.m4 deleted file mode 100644 index 6ed1a52a0c1d..000000000000 --- a/tools/topology/sof-apl-eq-pcm512x.m4 +++ /dev/null @@ -1,67 +0,0 @@ -# -# Topology for generic Apollolake UP^2 with pcm512x codec with equalizer components. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -# -# Define the pipelines -# -# PCM0 ----> EQ IIR ----> EQ FIR ----> volume ----> SSP5 (pcm512x) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-eq-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) diff --git a/tools/topology/sof-apl-keyword-detect.m4 b/tools/topology/sof-apl-keyword-detect.m4 deleted file mode 100644 index b05fbd2eb529..000000000000 --- a/tools/topology/sof-apl-keyword-detect.m4 +++ /dev/null @@ -1,97 +0,0 @@ -# -# Topology for ApolloLake with direct attach digital microphones array for -# keyword detection and triggering use case. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -define(KWD_PIPE_SCH_DEADLINE_US, 20000) - -# -# Define the pipelines -# -# PCM 0 <-------+- KPBM 0 <-- B0 <-- DMIC6 (DMIC01) -# | -# Keyword <-----+ - -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) - -# Passthrough capture pipeline 1 on PCM 0 using max 2 channels. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-kfbm-capture.m4, - 1, 0, 2, s16le, - KWD_PIPE_SCH_DEADLINE_US, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s16le format, with 320 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 1, DMIC, 1, NoCodec-6, - PIPELINE_SINK_1, 2, s16le, - KWD_PIPE_SCH_DEADLINE_US, - 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# keyword detector pipe -dnl PIPELINE_ADD(pipeline, -dnl pipe id, max channels, format, -dnl period, priority, core, -dnl sched_comp, time_domain, -dnl pcm_min_rate, pcm_max_rate, pipeline_rate) -PIPELINE_ADD(sof/pipe-detect.m4, - 2, 2, s16le, - KWD_PIPE_SCH_DEADLINE_US, 1, 0, - PIPELINE_SCHED_COMP_1, - SCHEDULE_TIME_DOMAIN_TIMER, - 16000, 16000, 16000) - -# Connect pipelines together -SectionGraph."pipe-sof-apl-keyword-detect" { - index "0" - - lines [ - # keyword detect - dapm(PIPELINE_SINK_2, PIPELINE_SOURCE_1) - dapm(PIPELINE_PCM_1, PIPELINE_DETECT_2) - ] -} - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -DAI_CONFIG(DMIC, 1, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - diff --git a/tools/topology/sof-apl-nocodec.m4 b/tools/topology/sof-apl-nocodec.m4 deleted file mode 100644 index aa0f24e91c20..000000000000 --- a/tools/topology/sof-apl-nocodec.m4 +++ /dev/null @@ -1,321 +0,0 @@ -# -# Topology for generic Apollolake board with no codec and digital mic array. -# -# APL Host GW DMAC support max 6 playback and max 6 capture channels so some -# pipelines/PCMs/DAIs are commented out to keep within HW bounds. If these -# are needed then they can be used provided other PCMs/pipelines/SSPs are -# commented out in their place. - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`ssp.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP0 -# PCM1 <---> volume <----> SSP1 -# PCM2 <---> volume <----> SSP2 -# PCM3 <---> volume <----> SSP3 -# PCM4 <---> volume <----> SSP4 -# PCM5 <---> volume <----> SSP5 -# PCM6 <---- volume <----- DMIC6 (DMIC01) -# - -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 s16le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 1 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 1 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 2 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -#PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, -# 5, 2, 2, s32le, -# 1000, 0, 0, -# 48000, 48000, 48000) - -# Low Latency capture pipeline 6 on PCM 2 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -#PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, -# 6, 2, 2, s32le, -# 1000, 0, 0, -# 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 3 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 8 on PCM 3 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 8, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 9 on PCM 4 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -#PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, -# 9, 4, 2, s32le, -# 1000, 0, 0, -# 48000, 48000, 48000) - -# Low Latency capture pipeline 10 on PCM 4 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -#PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, -# 10, 4, 2, s32le, -# 1000, 0, 0, -# 48000, 48000, 48000) - -# Low Latency playback pipeline 11 on PCM 5 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 11, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 12 on PCM 5 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 12, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 13 on PCM 6 using max 2 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 13, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, NoCodec-0, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# Media playback pipeline 14 on PCM 7 using max 2 channels of s16le. -# Set 4000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 14, 7, 2, s16le, - 4000, 0, 0, - 48000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_TIMER, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."media-pipeline" { - index "0" - - lines [ - # media 0 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_14) - ] -} - -# capture DAI is SSP0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, NoCodec-0, - PIPELINE_SINK_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, SSP, 1, NoCodec-1, - PIPELINE_SOURCE_3, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, SSP, 1, NoCodec-1, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -#DAI_ADD(sof/pipe-dai-playback.m4, -# 5, SSP, 2, NoCodec-2, -# PIPELINE_SOURCE_5, 2, s16le, -# 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -#DAI_ADD(sof/pipe-dai-capture.m4, -# 6, SSP, 2, NoCodec-2, -# PIPELINE_SINK_6, 2, s16le, -# 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP3 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, SSP, 3, NoCodec-3, - PIPELINE_SOURCE_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP3 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 8, SSP, 3, NoCodec-3, - PIPELINE_SINK_8, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP4 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -#DAI_ADD(sof/pipe-dai-playback.m4, -# 9, SSP, 4, NoCodec-4, -# PIPELINE_SOURCE_9, 2, s16le, -# 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP4 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -#DAI_ADD(sof/pipe-dai-capture.m4, -# 10, SSP, 4, NoCodec-4, -# PIPELINE_SINK_10, 2, s16le, -# 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP5 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 11, SSP, 5, NoCodec-5, - PIPELINE_SOURCE_11, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP5 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 12, SSP, 5, NoCodec-5, - PIPELINE_SINK_12, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 13, DMIC, 0, NoCodec-6, - PIPELINE_SINK_13, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_DUPLEX_ADD(Port1, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) -#PCM_DUPLEX_ADD(Port2, 2, PIPELINE_PCM_5, PIPELINE_PCM_6) -PCM_DUPLEX_ADD(Port3, 3, PIPELINE_PCM_7, PIPELINE_PCM_8) -#PCM_DUPLEX_ADD(Port4, 4, PIPELINE_PCM_9, PIPELINE_PCM_10) -PCM_DUPLEX_ADD(Port5, 5, PIPELINE_PCM_11, PIPELINE_PCM_12) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_13) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -DAI_CONFIG(SSP, 0, 0, NoCodec-0, - dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - dnl SSP_CONFIG_DATA(type, dai_index, valid bits, mclk_id, quirks) - SSP_CONFIG_DATA(SSP, 0, 16, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 1, 1, NoCodec-1, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16, 0, SSP_QUIRK_LBM))) - -#DAI_CONFIG(SSP, 2, 2, NoCodec-2, -# SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), -# SSP_CLOCK(bclk, 1536000, codec_slave), -# SSP_CLOCK(fsync, 48000, codec_slave), -# SSP_TDM(2, 16, 3, 3), -# SSP_CONFIG_DATA(SSP, 2, 16, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 3, 3, NoCodec-3, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 3, 16, 0, SSP_QUIRK_LBM))) - -#DAI_CONFIG(SSP, 4, 4, NoCodec-4, -# SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), -# SSP_CLOCK(bclk, 1536000, codec_slave), -# SSP_CLOCK(fsync, 48000, codec_slave), -# SSP_TDM(2, 16, 3, 3), -# SSP_CONFIG_DATA(SSP, 4, 16, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 5, 5, NoCodec-5, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 16, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - dnl PDM_CONFIG(type, dai_index, num pdm active, pdm tuples list) - dnl STEREO_PDM0 is a pre-defined pdm config for stereo capture - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - diff --git a/tools/topology/sof-apl-pcm512x-nohdmi.m4 b/tools/topology/sof-apl-pcm512x-nohdmi.m4 deleted file mode 100644 index 42b93845d550..000000000000 --- a/tools/topology/sof-apl-pcm512x-nohdmi.m4 +++ /dev/null @@ -1,73 +0,0 @@ -# -# Topology for generic Apollolake UP^2 with pcm512x codec and no HDMI. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> volume -----> SSP5 (pcm512x) -# - -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 on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 5 (ID: 0) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -DEBUG_END diff --git a/tools/topology/sof-apl-pcm512x.m4 b/tools/topology/sof-apl-pcm512x.m4 deleted file mode 100644 index 45bda529c3f1..000000000000 --- a/tools/topology/sof-apl-pcm512x.m4 +++ /dev/null @@ -1,205 +0,0 @@ -# -# Topology for generic Apollolake UP^2 with pcm512x codec and HDMI. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP5 (pcm512x) -# PCM1 ----> volume -----> iDisp1 -# PCM2 ----> volume -----> iDisp2 -# PCM3 ----> volume -----> iDisp3 -# PCM4 ----> volume -----> Media Playback 4 -# PCM5 <------------------ DMIC0 (DMIC) -# PCM6 <------------------ DMIC1 (DMIC16kHz) -# - -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 on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 3 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# DMIC passthrough capture pipeline 7 on PCM 4 using max 2 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-eq-capture.m4, - 7, 5, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# DMIC16kHz passthrough capture pipeline 8 on PCM 5 using max 2 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-eq-capture-16khz.m4, - 8, 6, 2, s16le, - 1000, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP5 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, SSP, 5, SSP5-Codec, - PIPELINE_SINK_6, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# Media playback pipeline 5 on PCM 4 using max 2 channels of s16le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 5, 4, 2, s16le, - 1000, 0, 0, - 8000, 96000, 48000, - SCHEDULE_TIME_DOMAIN_TIMER, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."media-pipeline" { - index "0" - - lines [ - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_5) - ] -} - -# capture DAI is DMIC using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 0, dmic01, - PIPELINE_SINK_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16kHz using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 8, DMIC, 1, dmic16k, - PIPELINE_SINK_8, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, HDA, 0, iDisp1, - PIPELINE_SOURCE_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, HDA, 1, iDisp2, - PIPELINE_SOURCE_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, HDA, 2, iDisp3, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_DUPLEX_ADD(Port5, 0, PIPELINE_PCM_1, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI1, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(HDMI2, 2, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI3, 3, PIPELINE_PCM_4) -PCM_CAPTURE_ADD(DMIC, 5, PIPELINE_PCM_7) -PCM_CAPTURE_ADD(DMIC16kHz, 6, PIPELINE_PCM_8) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -#SSP 5 (ID: 0) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -# DMIC (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# DMIC16kHz (ID: 2) -DAI_CONFIG(DMIC, 1, 2, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-apl-rt298.m4 b/tools/topology/sof-apl-rt298.m4 deleted file mode 100644 index 9aed26fae18b..000000000000 --- a/tools/topology/sof-apl-rt298.m4 +++ /dev/null @@ -1,120 +0,0 @@ -# -# Topology for generic Apollolake UP^2 with pcm512x codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume -----> SSP5 (rt298) -# PCM5 ----> volume (pipe 5) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM6 ----> volume (pipe 6) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM7 ----> volume (pipe 7) -----> iDisp3 (HDMI/DP playback, BE link 5) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 5 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 5, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 6 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 6, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 7 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 7, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 3, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 4, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 5, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# -# -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -DAI_CONFIG(HDA, 3, 3, iDisp1) -DAI_CONFIG(HDA, 4, 4, iDisp2) -DAI_CONFIG(HDA, 5, 5, iDisp3) - diff --git a/tools/topology/sof-apl-src-50khz-pcm512x.m4 b/tools/topology/sof-apl-src-50khz-pcm512x.m4 deleted file mode 100644 index f5f2b25083e1..000000000000 --- a/tools/topology/sof-apl-src-50khz-pcm512x.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# -# Topology for Apollolake UP^2 with pcm512x codec with sample rate -# conversion (SRC component). -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> src -----> SSP5 (pcm512x) -# - -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) - -# Playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 50000, 50000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 5 (ID: 0) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 3200000, codec_slave), - SSP_CLOCK(fsync, 50000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -DEBUG_END diff --git a/tools/topology/sof-apl-src-dmic.m4 b/tools/topology/sof-apl-src-dmic.m4 deleted file mode 100644 index 74e5c477b406..000000000000 --- a/tools/topology/sof-apl-src-dmic.m4 +++ /dev/null @@ -1,103 +0,0 @@ -# -# Topology for Apollo Lake with direct attach digital microphones array -# - -# Capture configuration -# DAI0 2ch 32b mic1-2 -# DAI1 2ch 32b mic1-2 - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM6 <--- Volume <--- SRC <--- DMIC6 (DMIC01) -# PCM7 <--- Volume <--- SRC <--- DMIC7 (DMIC16k) -# - -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) - -# SRC capture pipeline 6 on PCM 6 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-capture.m4, - 6, 6, 2, s32le, - 1000, 0, 0, - 8000, 48000, 48000) - -# SRC capture pipeline 7 on PCM 7 using max channels 2. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-capture.m4, - 7, 7, 2, s32le, - 1000, 0, 0, - 8000, 48000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, DMIC, 0, NoCodec-6, - PIPELINE_SINK_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 1, NoCodec-7, - PIPELINE_SINK_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16kHz, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - -DAI_CONFIG(DMIC, 1, 7, NoCodec-7, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -DEBUG_END diff --git a/tools/topology/sof-apl-src-pcm512x.m4 b/tools/topology/sof-apl-src-pcm512x.m4 deleted file mode 100644 index 1c756f802f33..000000000000 --- a/tools/topology/sof-apl-src-pcm512x.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# -# Topology for Apollolake UP^2 with pcm512x codec with sample rate -# conversion (SRC component). -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> src -----> SSP5 (pcm512x) -# - -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) - -# Playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 8000, 96000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 5 (ID: 0) -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) - -DEBUG_END diff --git a/tools/topology/sof-apl-tdf8532.m4 b/tools/topology/sof-apl-tdf8532.m4 deleted file mode 100644 index 6711ae86e940..000000000000 --- a/tools/topology/sof-apl-tdf8532.m4 +++ /dev/null @@ -1,262 +0,0 @@ -# -# Topology for generic Apollolake board with TDF8532 -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -# -# Define the pipelines -# -# PCM0 -----> Volume -----> SSP4 -# PCM1 <----> Volume <----> SSP2(Dirana Pb/Cp) -# PCM2 <----> Volume <----> SSP0(BT HFP out/in) -# PCM3 <----- Volume <----- SSP1(HDMI in) -# PCM4 <----> Volume <----> SSP3(Modem out/in) -# PCM5 <----> Volume <----> SSP5(TestPin out/in) -# - -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 4 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 8 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 8, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 8 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 8, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 2 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 2, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 5 on PCM 2 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 5, 2, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 6 on PCM 3 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 3, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 4 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 4, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 8 on PCM 4 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 8, 4, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 9 on PCM 5 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 9, 5, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 10 on PCM 5 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 10, 5, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, SSP, 0, SSP0-Codec, - PIPELINE_SOURCE_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 5, SSP, 0, SSP0-Codec, - PIPELINE_SINK_5, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, SSP, 1, SSP1-Codec, - PIPELINE_SINK_6, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 2, SSP2-Codec, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP3 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, SSP, 3, SSP3-Codec, - PIPELINE_SOURCE_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP3 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 8, SSP, 3, SSP3-Codec, - PIPELINE_SINK_8, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP4 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 4, SSP4-Codec, - PIPELINE_SOURCE_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP5 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 9, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_9, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP5 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 10, SSP, 5, SSP5-Codec, - PIPELINE_SINK_10, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -PCM_DUPLEX_ADD(Port0, 2, PIPELINE_PCM_4, PIPELINE_PCM_5) -PCM_CAPTURE_ADD(Port1, 3, PIPELINE_PCM_6) -PCM_DUPLEX_ADD(Port2, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_DUPLEX_ADD(Port3, 4, PIPELINE_PCM_7, PIPELINE_PCM_8) -PCM_PLAYBACK_ADD(Port4, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Port5, 5, PIPELINE_PCM_9, PIPELINE_PCM_10) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 0, 0, SSP0-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 16))) - -DAI_CONFIG(SSP, 1, 1, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16))) - -DAI_CONFIG(SSP, 2, 2, SSP2-Codec, - SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 12288000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(8, 32, 255, 255), - SSP_CONFIG_DATA(SSP, 2, 32))) - -DAI_CONFIG(SSP, 3, 3, SSP3-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 3, 16))) - -DAI_CONFIG(SSP, 4, 4, SSP4-Codec, - SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 12288000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(8, 32, 15, 15), - SSP_CONFIG_DATA(SSP, 4, 32))) - -DAI_CONFIG(SSP, 5, 5, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 16))) - - -VIRTUAL_DAPM_ROUTE_IN(BtHfp_ssp0_in, SSP, 0, IN, 0) -VIRTUAL_DAPM_ROUTE_OUT(BtHfp_ssp0_out, SSP, 0, OUT, 1) -VIRTUAL_DAPM_ROUTE_IN(hdmi_ssp1_in, SSP, 1, IN, 2) -VIRTUAL_DAPM_ROUTE_IN(dirana_in, SSP, 2, IN, 3) -VIRTUAL_DAPM_ROUTE_IN(dirana_aux_in, SSP, 2, IN, 4) -VIRTUAL_DAPM_ROUTE_IN(dirana_tuner_in, SSP, 2, IN, 5) -VIRTUAL_DAPM_ROUTE_OUT(dirana_out, SSP, 2, OUT, 6) -VIRTUAL_DAPM_ROUTE_IN(Modem_ssp3_in, SSP, 3, IN, 7) -VIRTUAL_DAPM_ROUTE_OUT(Modem_ssp3_out, SSP, 3, OUT, 8) -VIRTUAL_DAPM_ROUTE_OUT(codec0_out, SSP, 4, OUT, 9) -VIRTUAL_DAPM_ROUTE_IN(TestPin_ssp5_in, SSP, 5, IN, 10) -VIRTUAL_DAPM_ROUTE_OUT(TestPin_ssp5_out, SSP, 5, OUT, 11) -VIRTUAL_WIDGET(ssp0 Tx, out_drv, 12) -VIRTUAL_WIDGET(ssp0 Rx, out_drv, 13) -VIRTUAL_WIDGET(ssp1 Rx, out_drv, 14) -VIRTUAL_WIDGET(ssp2 Tx, out_drv, 15) -VIRTUAL_WIDGET(ssp2 Rx, out_drv, 16) -VIRTUAL_WIDGET(ssp3 Tx, out_drv, 17) -VIRTUAL_WIDGET(ssp3 Rx, out_drv, 18) -VIRTUAL_WIDGET(ssp4 Tx, out_drv, 19) -VIRTUAL_WIDGET(ssp5 Tx, out_drv, 20) -VIRTUAL_WIDGET(ssp5 Rx, out_drv, 21) diff --git a/tools/topology/sof-apl-wm8804.m4 b/tools/topology/sof-apl-wm8804.m4 deleted file mode 100644 index 1fee993ab660..000000000000 --- a/tools/topology/sof-apl-wm8804.m4 +++ /dev/null @@ -1,67 +0,0 @@ -# -# Topology for generic Apollolake UP^2 with wm8804 codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Apollolake DSP configuration -include(`platform/intel/bxt.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume -----> SSP5 (wm8804) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP5 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 5, SSP5-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Low Latency, id 0 -PCM_PLAYBACK_ADD(Port5, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -DAI_CONFIG(SSP, 5, 0, SSP5-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), - SSP_CLOCK(bclk, 3072000, codec_master), - SSP_CLOCK(fsync, 48000, codec_master), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 5, 24))) diff --git a/tools/topology/sof-bdw-codec.m4 b/tools/topology/sof-bdw-codec.m4 deleted file mode 100644 index 18ce2fff9838..000000000000 --- a/tools/topology/sof-bdw-codec.m4 +++ /dev/null @@ -1,103 +0,0 @@ -# -`# Topology for generic bdw board with' CODEC -# - -# Include topology builder -include(`pipeline.m4') -include(`utils.m4') -include(`dai.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Broadwell DSP configuration -include(`platform/intel/bdw.m4') - - -define(PIPE_NAME, pipe-bdw-`'CODEC`') - -# -# Define the pipelines -# -# PCM0 ----> volume ---------------+ -# |--low latency mixer ----> volume ----> SSP0 -# PCM1 -----> volume -----> SRC ---+ -# -# PCM0 <---- Volume <---- SSP0 -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 1 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 0 is our only pipeline DAI -# - -# playback DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le. -# 2000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 3, 1, 2, s32le, - 2000, 0, 0, - 8000, 96000, 48000, - SCHEDULE_TIME_DOMAIN_DMA, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."PIPE_NAME" { - index "0" - - lines [ - # media 0 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_3) - ] -} - -# capture DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, Codec, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Low Latency -PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 0, 0, Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24))) - -dnl CODEC is defined and will be expanded, need to undefine it before use -undefine(`CODEC') -VIRTUAL_WIDGET(SSP0 CODEC OUT, output, 0) -VIRTUAL_WIDGET(SSP0 CODEC IN, input, 1) -VIRTUAL_WIDGET(DSP Capture, input, 2) diff --git a/tools/topology/sof-bdw-nocodec.m4 b/tools/topology/sof-bdw-nocodec.m4 deleted file mode 100644 index 58db2169bdfe..000000000000 --- a/tools/topology/sof-bdw-nocodec.m4 +++ /dev/null @@ -1,93 +0,0 @@ -# -# Topology for generic Broadwell board with no codec. -# - -# Include topology builder -include(`pipeline.m4') -include(`utils.m4') -include(`dai.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include DSP configuration -include(`platform/intel/bdw.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume ---------------+ -# |--low latency mixer ----> volume ----> SSP0 (NoCodec) -# PCM1 -----> volume ----> SRC ----+ -# -# PCM0 <---- Volume <---- SSP0 (NoCodec) -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 2 is our only pipeline DAI -# - -# playback DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, NoCodec-0, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0) - -# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 1 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 3, 1, 2, s32le, - 1000, 1, 0, - 8000, 48000, 48000, - 0, PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."media-pipe" { - index "0" - - lines [ - # media 0 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_3) - ] -} - -# capture DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, NoCodec-0, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0) - -# PCM Low Latency -PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 0, 0, NoCodec-0, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24, 0, SSP_QUIRK_LBM))) diff --git a/tools/topology/sof-byt-codec.m4 b/tools/topology/sof-byt-codec.m4 deleted file mode 100644 index 3f0ed41abe89..000000000000 --- a/tools/topology/sof-byt-codec.m4 +++ /dev/null @@ -1,95 +0,0 @@ -`# Topology for generic' PLATFORM `board with' CODEC `on SSP' SSP_NUM - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include DSP configuration -ifelse(PLATFORM, `cht', include(`platform/intel/cht.m4'), - ifelse(PLATFORM, `byt', include(`platform/intel/byt.m4'), `')) - -define(PIPE_NAME, pipe-`'PLATFORM`'-`'CODEC`') - -# -# Define the pipelines -# -# PCM0 ----> volume ---------------+ -# |--low latency mixer ----> volume ----> SSP2 -# PCM1 -----> volume ----> SRC ----+ -# -# PCM0 <---- Volume <---- SSP2 -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 1 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 1, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 2 is our only pipeline DAI -# - -# playback DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 1 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, SSP_NUM, SSP2-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 8000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_DMA, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."PIPE_NAME" { - index "0" - - lines [ - # media 0 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_3) - ] -} - -# capture DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, SSP_NUM, SSP2-Codec, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Low Latency -PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, SSP_NUM, 0, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, SSP_NUM, 24))) diff --git a/tools/topology/sof-cht-max98090.m4 b/tools/topology/sof-cht-max98090.m4 deleted file mode 100644 index 067c12aeacd7..000000000000 --- a/tools/topology/sof-cht-max98090.m4 +++ /dev/null @@ -1,96 +0,0 @@ -# -# Topology for generic CHT/BSW board with Maxim 98090 codec -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Cherrytrail DSP configuration -include(`platform/intel/cht.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume ---------------+ -# |--low latency mixer ----> volume ----> SSP2 -# PCM1 -----> volume ----> SRC ----+ -# -# PCM0 <---- Volume <---- SSP2 -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 1 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 1, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 2 is our only pipeline DAI -# - -# playback DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 1 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le. -# 4000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 3, 1, 2, s32le, - 4000, 0, 0, - 8000, 48000, 48000, - 0, PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."pipe-cht-max98090" { - index "0" - - lines [ - # media 0 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_3) - ] -} - -# capture DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 2, SSP2-Codec, - PIPELINE_SINK_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Low Latency -PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 2, 0, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1920000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 20, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 16))) - -VIRTUAL_WIDGET(ssp2 Rx, out_drv, 1) -VIRTUAL_WIDGET(ssp2 Tx, out_drv, 2) diff --git a/tools/topology/sof-cht-nocodec.m4 b/tools/topology/sof-cht-nocodec.m4 deleted file mode 100644 index 8d7758c55a66..000000000000 --- a/tools/topology/sof-cht-nocodec.m4 +++ /dev/null @@ -1,97 +0,0 @@ -# -ifelse(PLATFORM, `cht', `# Topology for generic CherryTrail board with no codec.', `') -ifelse(PLATFORM, `byt', `# Topology for generic BayTrail board with no codec.', `') -# - -# Include topology builder -include(`pipeline.m4') -include(`utils.m4') -include(`dai.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include DSP configuration -ifelse(PLATFORM, `cht', include(`platform/intel/cht.m4'), - ifelse(PLATFORM, `byt', include(`platform/intel/byt.m4'), `')) -define(PIPE_NAME, ifelse(PLATFORM, `cht', pipe-cht-nocodec, - ifelse(PLATFORM, `byt', pipe-byt-nocodec, `'))) - -# -# Define the pipelines -# -# PCM0 ----> volume ---------------+ -# |--low latency mixer ----> volume ----> SSP2 (NoCodec) -# PCM1 -----> volume ----> SRC ----+ -# -# PCM0 <---- Volume <---- SSP2 (NoCodec) -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 1 -PIPELINE_PCM_ADD(sof/pipe-low-latency-playback.m4, - 1, 0, 2, s32le, - 1000, 1, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 2 is our only pipeline DAI -# - -# playback DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 1 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 2, NoCodec-2, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Media Playback pipeline 3 on PCM 1 using max 2 channels of s32le. -# 4000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-pcm-media.m4, - 3, 1, 2, s32le, - 4000, 0, 0, - 8000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_DMA, PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."media-pipe" { - index "0" - - lines [ - # media 0 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_3) - ] -} - -# capture DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 2, NoCodec-2, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Low Latency -PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 2, 2, NoCodec-2, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 24, 0, SSP_QUIRK_LBM))) diff --git a/tools/topology/sof-cht-rt5682.m4 b/tools/topology/sof-cht-rt5682.m4 deleted file mode 100644 index 24cde320fe8c..000000000000 --- a/tools/topology/sof-cht-rt5682.m4 +++ /dev/null @@ -1,71 +0,0 @@ -# -# Topology for generic CHT board with Realtek codecs -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Cherrytrail DSP configuration -include(`platform/intel/cht.m4') - -# -# Define the pipelines -# -# PCM0 <----> Volume <----> SSP2 -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 2 is our only pipeline DAI -# - -# playback DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# capture DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 2, SSP2-Codec, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM Low Latency -PCM_DUPLEX_ADD(SSP2, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 2, 0, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 24))) diff --git a/tools/topology/sof-cht-src-50khz-pcm512x.m4 b/tools/topology/sof-cht-src-50khz-pcm512x.m4 deleted file mode 100644 index 2791dfb985eb..000000000000 --- a/tools/topology/sof-cht-src-50khz-pcm512x.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# -# Topology for Cherrytrail UP with pcm512x codec with sample rate -# conversion (SRC component). -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Cherrytrail DSP configuration -include(`platform/intel/cht.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> src -----> SSP2 (pcm512x) -# - -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) - -# Playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-src-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 50000, 50000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core) - -# playback DAI is SSP2 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# PCM, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Port2, 0, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 2 (ID: 0) -DAI_CONFIG(SSP, 2, 0, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 3200000, codec_slave), - SSP_CLOCK(fsync, 50000, codec_slave), - SSP_TDM(2, 32, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 24))) - -DEBUG_END diff --git a/tools/topology/sof-cml-demux-rt5682-max98357a.m4 b/tools/topology/sof-cml-demux-rt5682-max98357a.m4 deleted file mode 100644 index 8db4b5dae2f8..000000000000 --- a/tools/topology/sof-cml-demux-rt5682-max98357a.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# -# Topology for Cometlake with rt5682 headset on SSP0, max98357a spk on SSP1 -# -# Adding max98357a spk on SSP1 on top of sof-cml-rt5682. -# - -# Include SOF CML RT5682 Topology -# This includes topology for RT5682, DMIC and 3 HDMI Pass through pipeline -include(`sof-cml-demux-rt5682.m4') - -# Define the Speaker pipeline -# -# PCM6 ----> volume (pipe 8) ----> SSP1 (speaker - maxim98357a, BE link 5) -# - -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 8 on PCM 6 using max 2 channels of s32le. -# Schedule 1000us deadline on core 0 with priority 0 -# pipe-src pipeline is needed for older SSP config - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000)', -`PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, - 8, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000)') - -# -# Speaker DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -#With m/n divider available we can support 24 bit playback - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`DAI_ADD(sof/pipe-dai-playback.m4, - 8, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_7, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER)', -`DAI_ADD(sof/pipe-dai-playback.m4, - 8, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER)') - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Speakers, 6, PIPELINE_PCM_8) - -# -# BE configurations for Speakers - overrides config in ACPI if present -# - -#SSP 1 (ID: 6) -# Use BCLK derived using m/n divider only on later versions - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`DAI_CONFIG(SSP, 1, 6, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2304000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 24, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 24)))', -`DAI_CONFIG(SSP, 1, 6, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 1500000, codec_slave), - SSP_CLOCK(fsync, 46875, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16)))') diff --git a/tools/topology/sof-cml-demux-rt5682.m4 b/tools/topology/sof-cml-demux-rt5682.m4 deleted file mode 100644 index 64e958355a37..000000000000 --- a/tools/topology/sof-cml-demux-rt5682.m4 +++ /dev/null @@ -1,194 +0,0 @@ -# -# Topology for Cometlake with rt5682 codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include platform specific DSP configuration -include(`platform/intel/'PLATFORM`.m4') - -DEBUG_START - - -# -# Define the pipelines -# -# PCM0 ----> demux ----> SSP(SSP_INDEX) -# PCM0 <---- volume <----- SSP(SSP_INDEX) -# PCM1 ----> volume -----> DMIC01 (dmic0 capture) -# PCM2 ----> volume -----> iDisp1 -# PCM3 ----> volume -----> iDisp2 -# PCM4 ----> volume -----> iDisp3 -# PCM5 <---- demux -# - -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) - -# Demux pipeline 1 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-demux-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 3 on PCM 1 using max 4 channels. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 1, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 2 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 3 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 4 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP(SPP_INDEX) using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, SSP_INDEX, SSP_NAME, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP(SSP_INDEX) using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP,SSP_INDEX, SSP_NAME, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# Capture pipeline 5 on PCM 5 using max 2 channels of s32le. -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture-sched.m4, - 5, 5, 2, s32le, - 1000, 1, 0, - 48000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_TIMER) - -# Connect demux to capture -SectionGraph."PIPE_CAP" { - index "0" - - lines [ - # demux to capture - dapm(PIPELINE_SINK_5, PIPELINE_DEMUX_1) - ] -} - -# Connect virtual capture to dai -SectionGraph."PIPE_CAP_VIRT" { - index "5" - - lines [ - # mux to capture - dapm(ECHO REF 5, `SSP'SSP_INDEX`.IN') - ] -} - -# capture DAI is DMIC01 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, HDA, 0, iDisp1, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 1, iDisp2, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 2, iDisp3, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_DUPLEX_ADD(Port1, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(EchoRef, 5, PIPELINE_PCM_5) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP SSP_INDEX (ID: 0) -DAI_CONFIG(SSP, SSP_INDEX, 0, SSP_NAME, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, SSP_INDEX, 24))) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) - - -DEBUG_END diff --git a/tools/topology/sof-cml-rt1011-rt5682.m4 b/tools/topology/sof-cml-rt1011-rt5682.m4 deleted file mode 100644 index 0201829ef179..000000000000 --- a/tools/topology/sof-cml-rt1011-rt5682.m4 +++ /dev/null @@ -1,70 +0,0 @@ -# -# Topology for Cometlake with rt1011 spk on SSP1 -# - -# Include SOF CML RT5682 Topology -# This includes topology for RT5682, DMIC and 3 HDMI Pass through pipeline -include(`sof-cml-rt5682-kwd.m4') -include(`abi.h') -DEBUG_START -# -# Define the Speaker pipeline -# -# PCM5 ----> volume (pipe 7) ----> SSP1 (speaker - rt1011, BE link 5) -# - -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 7 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# Speaker DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_7, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Speakers, 5, PIPELINE_PCM_7) - -# -# BE configurations for Speakers - overrides config in ACPI if present -# - -#SSP 1 (ID: 6) -#Use BCLK delay in SSP_CONFIG_DATA only on supporting version - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`DAI_CONFIG(SSP, 1, 6, SSP1-Codec, - SSP_CONFIG(DSP_A, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(4, 25, 3, 15), - SSP_CONFIG_DATA(SSP, 1, 24, 0, 0, 10)))', -`DAI_CONFIG(SSP, 1, 6, SSP1-Codec, - SSP_CONFIG(DSP_A, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(4, 25, 3, 15), - SSP_CONFIG_DATA(SSP, 1, 24)))') - -DEBUG_END diff --git a/tools/topology/sof-cml-rt5682-kwd.m4 b/tools/topology/sof-cml-rt5682-kwd.m4 deleted file mode 100644 index 033a9f9dd508..000000000000 --- a/tools/topology/sof-cml-rt5682-kwd.m4 +++ /dev/null @@ -1,215 +0,0 @@ -# -# Topology for Cometlake with rt5682 codec and Keyword Detect. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Platform specific DSP configuration -include(`platform/intel/'PLATFORM`.m4') - -define(KWD_PIPE_SCH_DEADLINE_US, 20000) - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP(SSP_INDEX, BE link 0) -# PCM1 <------------------ DMIC01 (dmic0 capture, , BE link 1) -# PCM2 ----> volume -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM3 ----> volume -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM4 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 5) -# PCM8 <-------(pipe 8) <------------+- KPBM 0 <----- DMIC1 (dmic16k, BE link 2) -# | -# Detector <--- selector (pipe 9) <---+ -# - -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 s24le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 3 on PCM 1 using max 4 channels. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 1, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 2 using max 2 channels of s32le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 3 using max 2 channels of s32le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 4 using max 2 channels of s32le. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP(SPP_INDEX) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, SSP_INDEX, SSP_NAME, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP(SSP_INDEX) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP,SSP_INDEX, SSP_NAME, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 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, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 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, - 4, HDA, 0, iDisp1, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 5, HDA, 1, iDisp2, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 6, HDA, 2, iDisp3, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# -# KWD configuration -# - -# Passthrough capture pipeline 7 on PCM 7 using max 2 channels. -# Schedule 20000us deadline on core 0 with priority 0 -PIPELINE_PCM_DAI_ADD(sof/pipe-kfbm-capture.m4, - 8, 8, 2, s24le, - KWD_PIPE_SCH_DEADLINE_US, 0, 0, DMIC, 1, s32le, 3, - 16000, 16000, 16000) - -# capture DAI is DMIC 1 using 3 periods -# Buffers use s32le format, with 320 frame per 20000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 8, DMIC, 1, dmic16k, - PIPELINE_SINK_8, 3, s32le, - KWD_PIPE_SCH_DEADLINE_US, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_DUPLEX_ADD(Port1, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_6) - -# keyword detector pipe -dnl PIPELINE_ADD(pipeline, -dnl pipe id, max channels, format, -dnl period, priority, core, -dnl sched_comp, time_domain, -dnl pcm_min_rate, pcm_max_rate, pipeline_rate) -PIPELINE_ADD(sof/pipe-detect.m4, - 9, 2, s24le, - KWD_PIPE_SCH_DEADLINE_US, 1, 0, - PIPELINE_SCHED_COMP_8, - SCHEDULE_TIME_DOMAIN_TIMER, - 16000, 16000, 16000) - -# Connect pipelines together -SectionGraph."pipe-sof-cml-keyword-detect" { - index "0" - - lines [ - # keyword detect - dapm(PIPELINE_SINK_9, PIPELINE_SOURCE_8) - dapm(PIPELINE_PCM_8, PIPELINE_DETECT_9) - ] -} - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP SSP_INDEX (ID: 0) -DAI_CONFIG(SSP, SSP_INDEX, 0, SSP_NAME, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, SSP_MCLK_RATE, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, SSP_INDEX, 24))) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 2) -DAI_CONFIG(DMIC, 1, 2, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-cml-rt5682-max98357a.m4 b/tools/topology/sof-cml-rt5682-max98357a.m4 deleted file mode 100644 index ac1dab29d4ca..000000000000 --- a/tools/topology/sof-cml-rt5682-max98357a.m4 +++ /dev/null @@ -1,87 +0,0 @@ -# -# Topology for Cometlake with rt5682 headset on SSP0, max98357a spk on SSP1 -# -# Adding max98357a spk on SSP1 on top of sof-cml-rt5682. -# - -# Include SOF CML RT5682 Topology -# This includes topology for RT5682, DMIC and 3 HDMI Pass through pipeline -include(`sof-cml-rt5682-kwd.m4') -include(`abi.h') - -DEBUG_START -# -# Define the Speaker pipeline -# -# PCM5 ----> volume (pipe 7) ----> SSP1 (speaker - maxim98357a, BE link 5) -# - -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 7 on PCM 5 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -# pipe-src pipeline is needed for older SSP config - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000)', -`PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, - 7, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000)') - -# -# Speaker DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -#With m/n divider available we can support 24 bit playback - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`DAI_ADD(sof/pipe-dai-playback.m4, - 7, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_7, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER)', -`DAI_ADD(sof/pipe-dai-playback.m4, - 7, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER)') - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Speakers, 5, PIPELINE_PCM_7) - -# -# BE configurations for Speakers - overrides config in ACPI if present -# - -#SSP 1 (ID: 6) -# Use BCLK derived using m/n divider only on later versions - -ifelse(SOF_ABI_VERSION_3_9_OR_GRT, `1', -`DAI_CONFIG(SSP, 1, 6, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2304000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 24, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 24)))', -`DAI_CONFIG(SSP, 1, 6, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 1500000, codec_slave), - SSP_CLOCK(fsync, 46875, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16)))') - -DEBUG_END diff --git a/tools/topology/sof-cml-rt5682.m4 b/tools/topology/sof-cml-rt5682.m4 deleted file mode 100644 index cbab2009b68f..000000000000 --- a/tools/topology/sof-cml-rt5682.m4 +++ /dev/null @@ -1,185 +0,0 @@ -# -# Topology for Cometlake with rt5682 codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Platform specific DSP configuration -include(`platform/intel/'PLATFORM`.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP(SSP_INDEX, BE link 0) -# PCM1 <------------------ DMIC01 (dmic0 capture, , BE link 1) -# PCM2 ----> volume -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM3 ----> volume -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM4 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 5) -# PCM8 <---- volume <----- DMIC16k (dmic16k, BE link 2) -# - -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 s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 3 on PCM 1 using max 4 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 1, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 2 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 3 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 4 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 7 on PCM 5 using max 2 channels. -# Schedule 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 8, 8, 2, s24le, - 1000, 0, 0, - 16000, 16000, 16000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP(SPP_INDEX) using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, SSP_INDEX, SSP_NAME, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP(SSP_INDEX) using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP,SSP_INDEX, SSP_NAME, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, HDA, 0, iDisp1, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 1, iDisp2, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 2, iDisp3, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16k using 2 periods -# Buffers use s32le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 8, DMIC, 1, dmic16k, - PIPELINE_SINK_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_DUPLEX_ADD(Port1, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC16kHz, 8, PIPELINE_PCM_8) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP SSP_INDEX (ID: 0) -DAI_CONFIG(SSP, SSP_INDEX, 0, SSP_NAME, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, SSP_MCLK_RATE, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, SSP_INDEX, 24))) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 2) -DAI_CONFIG(DMIC, 1, 2, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-cml-rt700.m4 b/tools/topology/sof-cml-rt700.m4 deleted file mode 100644 index 55a4362ff1b5..000000000000 --- a/tools/topology/sof-cml-rt700.m4 +++ /dev/null @@ -1,184 +0,0 @@ -# -# Topology for Cometlake with rt700 codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include CML DSP configuration -include(`platform/intel/cml.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> ALH 2 BE dailink 0 -# PCM1 <--- volume <---- ALH 3 BE dailink 1 -# PCM2 <---------------- DMIC01 (dmic0 capture, BE dailink 2) -# PCM3 <---------------- DMIC16k (dmic16k, BE dailink 3) -# PCM4 ----> volume -----> iDisp1 (HDMI/DP playback, BE link 4) -# PCM5 ----> volume -----> iDisp2 (HDMI/DP playback, BE link 5) -# PCM6 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 6) -# - -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. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 3 on PCM 2 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 2, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 4 on PCM 3 using max 2 channels. -# Schedule 16 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 4, 3, 2, s16le, - 1000, 0, 0, - 16000, 16000, 16000) - -# Low Latency playback pipeline 5 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 6 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is ALH(SDW1 PIN2) 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, ALH, 0x102, SDW1-Playback, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW1 PIN3) 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, ALH, 0x103, SDW1-Capture, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 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, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16k using 2 periods -# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 1, dmic16k, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 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, - 5, HDA, 0, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 6, HDA, 1, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 7, HDA, 2, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(SDW1-speakers, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(SDW1-mics, 1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC16kHz, 3, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 4, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 5, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 6, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -#ALH dai index = ((link_id << 8) | PDI id) -#ALH SDW1 Pin2 (ID: 0) -DAI_CONFIG(ALH, 0x102, 0, SDW1-Playback) - -#ALH SDW1 Pin3 (ID: 1) -DAI_CONFIG(ALH, 0x103, 1, SDW1-Capture) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 2) -DAI_CONFIG(DMIC, 1, 3, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 4,5,6) -DAI_CONFIG(HDA, 0, 4, iDisp1) -DAI_CONFIG(HDA, 1, 5, iDisp2) -DAI_CONFIG(HDA, 2, 6, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-cml-src-rt5682.m4 b/tools/topology/sof-cml-src-rt5682.m4 deleted file mode 100644 index a3b9b5d8a44d..000000000000 --- a/tools/topology/sof-cml-src-rt5682.m4 +++ /dev/null @@ -1,164 +0,0 @@ -# -# Topology for Cometlake with rt5682 codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Cometlake DSP configuration -include(`platform/intel/cml.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ----> SRC ----> volume -----> SSP1 -# PCM0 <---- volume <----- SSP1 -# PCM1 <---- volume <----- DMIC01 (dmic0 capture) -# PCM2 ----> volume -----> iDisp1 -# PCM3 ----> volume -----> iDisp2 -# PCM4 ----> volume -----> iDisp3 -# - -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 s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 8000, 96000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 3 on PCM 1 using max 4 channels. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 1, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 2 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 3 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 3, 2, s32le, - 1000, 0, 0, - 48000 ,48000 ,48000) - -# Low Latency playback pipeline 6 on PCM 4 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 1, SSP1-Codec, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, HDA, 0, iDisp1, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 1, iDisp2, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 2, iDisp3, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_DUPLEX_ADD(Port1, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_6) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 1 (ID: 0) -DAI_CONFIG(SSP, 1, 0, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 24))) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 3 HDMI/DP outputs (ID: 2,3,4) -DAI_CONFIG(HDA, 0, 2, iDisp1) -DAI_CONFIG(HDA, 1, 3, iDisp2) -DAI_CONFIG(HDA, 2, 4, iDisp3) - - -DEBUG_END diff --git a/tools/topology/sof-cnl-nocodec.m4 b/tools/topology/sof-cnl-nocodec.m4 deleted file mode 100644 index 31e344980fe6..000000000000 --- a/tools/topology/sof-cnl-nocodec.m4 +++ /dev/null @@ -1,181 +0,0 @@ -# -# Topology for generic Cannonlake board with no codec and digital mic array. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`ssp.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Cannonlake DSP configuration -include(`platform/intel/cnl.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP0 -# PCM1 <---> Volume <----> SSP1 -# PCM2 <---> volume <----> SSP2 -# PCM3 <---- volume <----- DMIC3 (DMIC01) -# - -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 s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 1 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 1 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 2 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 2, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 6 on PCM 2 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 2, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 7 on PCM 3 using max 4 channels. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 7, 3, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, NoCodec-0, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, NoCodec-0, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, SSP, 1, NoCodec-1, - PIPELINE_SOURCE_3, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, SSP, 1, NoCodec-1, - PIPELINE_SINK_4, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, SSP, 2, NoCodec-2, - PIPELINE_SOURCE_5, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, SSP, 2, NoCodec-2, - PIPELINE_SINK_6, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 7, DMIC, 0, NoCodec-3, - PIPELINE_SINK_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_DUPLEX_ADD(Port1, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) -PCM_DUPLEX_ADD(Port2, 2, PIPELINE_PCM_5, PIPELINE_PCM_6) -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 3, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -DAI_CONFIG(SSP, 0, 0, NoCodec-0, - dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - dnl SSP_CONFIG_DATA(type, dai_index, valid bits, mclk_id, quirks) - SSP_CONFIG_DATA(SSP, 0, 24, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 1, 1, NoCodec-1, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 24, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 2, 2, NoCodec-2, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 24, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(DMIC, 0, 3, NoCodec-3, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) diff --git a/tools/topology/sof-cnl-rt274.m4 b/tools/topology/sof-cnl-rt274.m4 deleted file mode 100644 index 3b9b25da7934..000000000000 --- a/tools/topology/sof-cnl-rt274.m4 +++ /dev/null @@ -1,104 +0,0 @@ -# -# Topology for generic Cannonlake board with RT274 -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Cannonlake DSP configuration -include(`platform/intel/cnl.m4') - -# -# Define the pipelines -# -# PCM0 <---> volume <---> SSP0 -# -# - -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 s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 0 is our only pipeline DAI -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, SSP0-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, SSP0-Codec, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency -PCM_DUPLEX_ADD(Passthrough, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 0, 1, SSP0-Codec, - SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(4, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24))) - -VIRTUAL_DAPM_ROUTE_OUT(codec0_out, SSP, 0, OUT, 0) -VIRTUAL_DAPM_ROUTE_OUT(codec1_out, SSP, 0, OUT, 1) -VIRTUAL_DAPM_ROUTE_OUT(ssp0 Tx, SSP, 0, OUT, 2) -VIRTUAL_DAPM_ROUTE_OUT(Capture, SSP, 0, OUT, 3) -VIRTUAL_DAPM_ROUTE_OUT(SoC DMIC, SSP, 0, OUT, 4) -VIRTUAL_DAPM_ROUTE_IN(codec0_in, SSP, 0, IN, 5) -VIRTUAL_DAPM_ROUTE_OUT(ssp2_out, SSP, 0, OUT, 6) -VIRTUAL_DAPM_ROUTE_IN(ssp2_in, SSP, 0, IN, 7) -VIRTUAL_DAPM_ROUTE_OUT(ssp1_out, SSP, 0, OUT, 8) -VIRTUAL_WIDGET(DMIC01 Rx, out_drv, 9) -VIRTUAL_WIDGET(DMic, out_drv, 10) -VIRTUAL_WIDGET(dmic01_hifi, out_drv, 11) -VIRTUAL_WIDGET(ssp0 Rx, out_drv, 12) -VIRTUAL_WIDGET(ssp1_out, out_drv, 13) -VIRTUAL_WIDGET(ssp2_out, out_drv, 14) -VIRTUAL_WIDGET(ssp2_in, out_drv, 15) -VIRTUAL_WIDGET(ssp2 Rx, out_drv, 16) -VIRTUAL_WIDGET(ssp2 Tx, out_drv, 17) -VIRTUAL_WIDGET(Dummy Playback, out_drv, 18) -VIRTUAL_WIDGET(Dummy Capture, out_drv, 19) diff --git a/tools/topology/sof-ehl-rt5660.m4 b/tools/topology/sof-ehl-rt5660.m4 deleted file mode 100644 index 9d3ec8a37647..000000000000 --- a/tools/topology/sof-ehl-rt5660.m4 +++ /dev/null @@ -1,217 +0,0 @@ -# -# Topology for ELKHARTLAKE with rt5660 codec -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Elkhartlake DSP configuration -include(`platform/intel/ehl.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP0 BE dailink 0 -# PCM1 <---- volume <----- DMIC48k (dmic48k, BE dailink 1) - -ifelse(HDMI, `1', -` -# PCM2 ----> volume -----> iDisp1 (HDMI/DP playback, BE link 5) -# PCM3 ----> volume -----> iDisp2 (HDMI/DP playback, BE link 6) -# PCM4 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 7) -# PCM5 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 8) -') - -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) -# time_domain and sched_comp is used for a "branched" pipeline, -# which is not applicable in ehl-rt5660. - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 4 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 4 on PCM 3 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 3, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -ifelse(HDMI, `1', -` -# Low Latency playback pipeline 4 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 3 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) -') - -# -# DAIs configuration -# - -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 SSP0 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, SSP, 0, SSP0-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 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, SSP, 0, SSP0-Codec, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC48k 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, - 3, DMIC, 0, dmic48k, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16k using 2 periods -# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 1, dmic16k, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) -ifelse(HDMI, `1', -` -# playback DAI is iDisp1 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, - 5, HDA, 0, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 6, HDA, 1, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 7, HDA, 2, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp4 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, - 8, HDA, 3, iDisp4, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) -') - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_DUPLEX_ADD(Headset, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC16kHz, 2, PIPELINE_PCM_4) - -ifelse(HDMI, `1', -` -PCM_PLAYBACK_ADD(HDMI1, 3, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 4, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 5, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI4, 6, PIPELINE_PCM_8) -') - -# -# BE configurations - overrides config in ACPI if present -# -#SSP 2 (ID: 0) -DAI_CONFIG(SSP, 0, 0, SSP0-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 9600000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24))) - -# dmic48k (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic48k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 2) -DAI_CONFIG(DMIC, 1, 2, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -ifelse(HDMI, `1', -` -# 4 HDMI/DP outputs (ID: 5,6,7,8) -DAI_CONFIG(HDA, 0, 5, iDisp1) -DAI_CONFIG(HDA, 1, 6, iDisp2) -DAI_CONFIG(HDA, 2, 7, iDisp3) -DAI_CONFIG(HDA, 3, 8, iDisp4) -') - -DEBUG_END diff --git a/tools/topology/sof-glk-da7219-kwd.m4 b/tools/topology/sof-glk-da7219-kwd.m4 deleted file mode 100644 index b9ddcbf1abbb..000000000000 --- a/tools/topology/sof-glk-da7219-kwd.m4 +++ /dev/null @@ -1,255 +0,0 @@ -# -# Topology for GeminiLake with Dialog7219. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -define(KWD_PIPE_SCH_DEADLINE_US, 20000) - -# -# Define the pipelines -# -# PCM0 ----> volume (pipe 1) -----> SSP1 (speaker - maxim98357a, BE link 0) -# PCM1 <---> volume (pipe 2,3) <----> SSP2 (headset - da7219, BE link 1) -# PCM99 <---- volume (pipe 4) <----- DMIC0 (dmic01 , BE link 2) -# PCM5 ----> volume (pipe 5) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM6 ----> volume (pipe 6) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM7 ----> volume (pipe 7) -----> iDisp3 (HDMI/DP playback, BE link 5) -# PCM8 <-------(pipe 8) <------------+- KPBM 0 <----- DMIC1 (dmic16k, BE link 6) -# | -# Detector <--- selector (pipe 9) <---+ -# - -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 on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 99 using max 4 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 99, 4, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 5 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 6 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 7 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 7, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 2, SSP2-Codec, - PIPELINE_SINK_3, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 3, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 4, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 5, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# -# KWD configuration -# - -# Passthrough capture pipeline 8 on PCM 8 using max 2 channels. -# Schedule 20000us deadline on core 0 with priority 0 -PIPELINE_PCM_DAI_ADD(sof/pipe-kfbm-capture.m4, - 8, 8, 2, s16le, - KWD_PIPE_SCH_DEADLINE_US, 0, 0, DMIC, 1, s16le, 3, - 16000, 16000, 16000) - -# capture DAI is DMIC 1 using 3 periods -# Buffers use s16le format, with 320 frame per 20000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 8, DMIC, 1, dmic16k, - PIPELINE_SINK_8, 3, s16le, - KWD_PIPE_SCH_DEADLINE_US, 0, 0, - SCHEDULE_TIME_DOMAIN_TIMER) - -PCM_PLAYBACK_ADD(Speakers, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 99, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_7) - -# keyword detector pipe -dnl PIPELINE_ADD(pipeline, -dnl pipe id, max channels, format, -dnl period, priority, core, -dnl sched_comp, time_domain, -dnl pcm_min_rate, pcm_max_rate, pipeline_rate) -PIPELINE_ADD(sof/pipe-detect.m4, - 9, 2, s16le, - KWD_PIPE_SCH_DEADLINE_US, 1, 0, - PIPELINE_SCHED_COMP_8, SCHEDULE_TIME_DOMAIN_TIMER, - 16000, 16000, 16000) - -# Connect pipelines together -SectionGraph."pipe-sof-glk-keyword-detect" { - index "0" - - lines [ - # keyword detect - dapm(PIPELINE_SINK_9, PIPELINE_SOURCE_8) - dapm(PIPELINE_PCM_8, PIPELINE_DETECT_9) - ] -} - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 1 (ID: 0) with 19.2 MHz mclk with MCLK_ID 1 (unused), 1.536 MHz blck -DAI_CONFIG(SSP, 1, 0, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16, 1))) - -#SSP 2 (ID: 1) with 19.2 MHz mclk with MCLK_ID 1, 1.92 MHz bclk -DAI_CONFIG(SSP, 2, 1, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1920000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 20, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 16, 1))) - -# dmic01 (ID: 2) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 3, 3, iDisp1) -DAI_CONFIG(HDA, 4, 4, iDisp2) -DAI_CONFIG(HDA, 5, 5, iDisp3) - -# dmic16k (ID: 6) -DAI_CONFIG(DMIC, 1, 6, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -## remove warnings with SST hard-coded routes - -VIRTUAL_WIDGET(ssp1 Tx, out_drv, 0) -VIRTUAL_WIDGET(ssp2 Rx, out_drv, 1) -VIRTUAL_WIDGET(ssp2 Tx, out_drv, 2) -VIRTUAL_WIDGET(iDisp3 Tx, out_drv, 15) -VIRTUAL_WIDGET(iDisp2 Tx, out_drv, 16) -VIRTUAL_WIDGET(iDisp1 Tx, out_drv, 17) -VIRTUAL_WIDGET(DMIC01 Rx, out_drv, 3) -VIRTUAL_WIDGET(DMic, out_drv, 4) -VIRTUAL_WIDGET(dmic01_hifi, out_drv, 5) -VIRTUAL_WIDGET(hif5-0 Output, out_drv, 6) -VIRTUAL_WIDGET(hif6-0 Output, out_drv, 7) -VIRTUAL_WIDGET(hif7-0 Output, out_drv, 8) -VIRTUAL_WIDGET(iDisp3_out, out_drv, 9) -VIRTUAL_WIDGET(iDisp2_out, out_drv, 10) -VIRTUAL_WIDGET(iDisp1_out, out_drv, 11) -VIRTUAL_WIDGET(codec0_out, output, 12) -VIRTUAL_WIDGET(codec1_out, output, 13) -VIRTUAL_WIDGET(codec0_in, input, 14) diff --git a/tools/topology/sof-glk-da7219.m4 b/tools/topology/sof-glk-da7219.m4 deleted file mode 100644 index e64944b58685..000000000000 --- a/tools/topology/sof-glk-da7219.m4 +++ /dev/null @@ -1,206 +0,0 @@ -# -# Topology for GeminiLake with Dialog7219. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume (pipe 1) -----> SSP1 (speaker - maxim98357a, BE link 0) -# PCM1 <---> volume (pipe 2,3) <----> SSP2 (headset - da7219, BE link 1) -# PCM99 <---- DMIC0 (dmic capture, BE link 2) -# PCM5 ----> volume (pipe 5) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM6 ----> Volume (pipe 6) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM7 ----> volume (pipe 7) -----> iDisp3 (HDMI/DP playback, BE link 5) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 99 using max 4 channels of s32le. -# 1000us deadline on core 0 with priority 0 -#PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 99, 4, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 5 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 6 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 7 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 7, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 2, SSP2-Codec, - PIPELINE_SINK_3, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 3, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 4, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 5, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -PCM_PLAYBACK_ADD(Speakers, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 99, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 1 (ID: 0) with 19.2 MHz mclk with MCLK_ID 1 (unused), 1.536 MHz blck -DAI_CONFIG(SSP, 1, 0, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16, 1))) - -#SSP 2 (ID: 1) with 19.2 MHz mclk with MCLK_ID 1, 1.92 MHz bclk -DAI_CONFIG(SSP, 2, 1, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1920000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 20, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 16, 1))) - -# dmic01 (id: 2) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 3, 3, iDisp1) -DAI_CONFIG(HDA, 4, 4, iDisp2) -DAI_CONFIG(HDA, 5, 5, iDisp3) - -## remove warnings with SST hard-coded routes - -VIRTUAL_WIDGET(ssp1 Tx, out_drv, 0) -VIRTUAL_WIDGET(ssp2 Rx, out_drv, 1) -VIRTUAL_WIDGET(ssp2 Tx, out_drv, 2) -VIRTUAL_WIDGET(iDisp3 Tx, out_drv, 15) -VIRTUAL_WIDGET(iDisp2 Tx, out_drv, 16) -VIRTUAL_WIDGET(iDisp1 Tx, out_drv, 17) -VIRTUAL_WIDGET(DMIC01 Rx, out_drv, 3) -VIRTUAL_WIDGET(DMic, out_drv, 4) -VIRTUAL_WIDGET(dmic01_hifi, out_drv, 5) -VIRTUAL_WIDGET(hif5-0 Output, out_drv, 6) -VIRTUAL_WIDGET(hif6-0 Output, out_drv, 7) -VIRTUAL_WIDGET(hif7-0 Output, out_drv, 8) -VIRTUAL_WIDGET(iDisp3_out, out_drv, 9) -VIRTUAL_WIDGET(iDisp2_out, out_drv, 10) -VIRTUAL_WIDGET(iDisp1_out, out_drv, 11) -VIRTUAL_WIDGET(codec0_out, output, 12) -VIRTUAL_WIDGET(codec1_out, output, 13) -VIRTUAL_WIDGET(codec0_in, input, 14) diff --git a/tools/topology/sof-glk-rt5682.m4 b/tools/topology/sof-glk-rt5682.m4 deleted file mode 100644 index fcd66a9bb9de..000000000000 --- a/tools/topology/sof-glk-rt5682.m4 +++ /dev/null @@ -1,210 +0,0 @@ -# -# Topology for Geminilake with rt5682 headset on SSP2, max98357a spk on SSP1 -# -# Modified from: -# Geminilake topology for codecs da7219 headset on SSP2, max98357a spk on SSP1 -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM0 ----> volume (pipe 1) -----> SSP1 (speaker - maxim98357a, BE link 0) -# PCM1 <---> volume (pipe 2,3) <----> SSP2 (headset - rt5682, BE link 1) -# PCM99 <---- DMIC0 (dmic capture, BE link 2) -# PCM5 ----> volume (pipe 5) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM6 ----> Volume (pipe 6) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM7 ----> volume (pipe 7) -----> iDisp3 (HDMI/DP playback, BE link 5) -# - -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. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 2 channels of s32le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 99 using max 4 channels of s16le. -# 1000us deadline on core 0 with priority 0 -#PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 4, 99, 4, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 5 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 5, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 6 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 6, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 7 using max 2 channels of s16le. -# 1000us deadline on core 0 with priority 0 -# PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 7, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 2, SSP2-Codec, - PIPELINE_SINK_3, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC0 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 3, iDisp1, - PIPELINE_SOURCE_5, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 4, iDisp2, - PIPELINE_SOURCE_6, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s16le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 5, iDisp3, - PIPELINE_SOURCE_7, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -PCM_PLAYBACK_ADD(Speakers, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 99, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -#SSP 1 (ID: 0) with 19.2 MHz mclk with MCLK_ID 1 (unused), 1.536 MHz blck -DAI_CONFIG(SSP, 1, 0, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16, 1))) - -#SSP 2 (ID: 1) with 19.2 MHz mclk with MCLK_ID 1, 2.4 MHz bclk -DAI_CONFIG(SSP, 2, 1, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 20, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 16, 1))) - -# dmic01 (id: 2) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 3, 3, iDisp1) -DAI_CONFIG(HDA, 4, 4, iDisp2) -DAI_CONFIG(HDA, 5, 5, iDisp3) - -## remove warnings with SST hard-coded routes - -VIRTUAL_WIDGET(ssp1 Tx, out_drv, 0) -VIRTUAL_WIDGET(ssp2 Rx, out_drv, 1) -VIRTUAL_WIDGET(ssp2 Tx, out_drv, 2) -VIRTUAL_WIDGET(iDisp3 Tx, out_drv, 16) -VIRTUAL_WIDGET(iDisp2 Tx, out_drv, 17) -VIRTUAL_WIDGET(iDisp1 Tx, out_drv, 18) -VIRTUAL_WIDGET(DMIC01 Rx, out_drv, 3) -VIRTUAL_WIDGET(DMIC AIF, input, 15) -VIRTUAL_WIDGET(DMic, out_drv, 4) -VIRTUAL_WIDGET(dmic01_hifi, out_drv, 5) -VIRTUAL_WIDGET(hif5-0 Output, out_drv, 6) -VIRTUAL_WIDGET(hif6-0 Output, out_drv, 7) -VIRTUAL_WIDGET(hif7-0 Output, out_drv, 8) -VIRTUAL_WIDGET(iDisp3_out, out_drv, 9) -VIRTUAL_WIDGET(iDisp2_out, out_drv, 10) -VIRTUAL_WIDGET(iDisp1_out, out_drv, 11) -VIRTUAL_WIDGET(codec0_out, output, 12) -VIRTUAL_WIDGET(codec1_out, output, 13) -VIRTUAL_WIDGET(codec0_in, input, 14) diff --git a/tools/topology/sof-hda-asrc.m4 b/tools/topology/sof-hda-asrc.m4 deleted file mode 100644 index b12a30f08be9..000000000000 --- a/tools/topology/sof-hda-asrc.m4 +++ /dev/null @@ -1,188 +0,0 @@ -# -# Topology for SKL+ HDA for testing ASRC -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') - -DEBUG_START - -# Define pipeline id for intel-generic-dmic.m4 -# to generate dmic setting - -ifelse(CHANNELS, `0', , -` -define(DMIC_PIPELINE_48k_ID, `10') -define(DMIC_PIPELINE_16k_ID, `11') - -include(`platform/intel/intel-generic-dmic.m4') -' -) - -# -# Define the pipelines -# -# PCM0 <---> volume (pipe 1,2) <----> HDA Analog (HDA Analog playback/capture) -# PCM1 <---> volume (pipe 3,4) <----> HDA Digital (HDA Digital playback/capture) -# PCM3 ----> volume (pipe 7) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM4 ----> Volume (pipe 8) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM5 ----> volume (pipe 9) -----> iDisp3 (HDMI/DP playback, BE link 5) -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-asrc-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 8000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-asrc-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 1 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 1 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 3 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 3, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 8 on PCM 4 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 4, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 9 on PCM 5 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 9, 5, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -# playback DAI is HDA Analog using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, HDA, 0, Analog Playback and Capture, - PIPELINE_SOURCE_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is HDA Analog using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, HDA, 1, Analog Playback and Capture, - PIPELINE_SINK_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is HDA Digital using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, HDA, 2, Digital Playback and Capture, - PIPELINE_SOURCE_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is HDA Digital using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, HDA, 3, Digital Playback and Capture, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 4, iDisp1, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 8, HDA, 5, iDisp2, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 9, HDA, 6, iDisp3, - PIPELINE_SOURCE_9, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -PCM_DUPLEX_ADD(HDA Analog, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_DUPLEX_ADD(HDA Digital, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 3, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI2, 4, PIPELINE_PCM_8) -PCM_PLAYBACK_ADD(HDMI3, 5, PIPELINE_PCM_9) - -# -# BE configurations - overrides config in ACPI if present -# - -# HDA outputs -DAI_CONFIG(HDA, 0, 4, Analog Playback and Capture) -DAI_CONFIG(HDA, 1, 5, Digital Playback and Capture) -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 4, 1, iDisp1) -DAI_CONFIG(HDA, 5, 2, iDisp2) -DAI_CONFIG(HDA, 6, 3, iDisp3) - - -VIRTUAL_DAPM_ROUTE_IN(codec0_in, HDA, 1, IN, 1) -VIRTUAL_DAPM_ROUTE_IN(codec1_in, HDA, 3, IN, 2) -VIRTUAL_DAPM_ROUTE_OUT(codec0_out, HDA, 0, OUT, 3) -VIRTUAL_DAPM_ROUTE_OUT(codec1_out, HDA, 2, OUT, 4) - -# codec2 is not supported in dai links but it exists -# in dapm routes, so hack this one to HDA1 -VIRTUAL_DAPM_ROUTE_IN(codec2_in, HDA, 3, IN, 5) -VIRTUAL_DAPM_ROUTE_OUT(codec2_out, HDA, 2, OUT, 6) - -VIRTUAL_DAPM_ROUTE_OUT(iDisp1_out, HDA, 4, OUT, 7) -VIRTUAL_DAPM_ROUTE_OUT(iDisp2_out, HDA, 5, OUT, 8) -VIRTUAL_DAPM_ROUTE_OUT(iDisp3_out, HDA, 6, OUT, 9) - -VIRTUAL_WIDGET(iDisp3 Tx, out_drv, 0) -VIRTUAL_WIDGET(iDisp2 Tx, out_drv, 1) -VIRTUAL_WIDGET(iDisp1 Tx, out_drv, 2) -VIRTUAL_WIDGET(Analog CPU Playback, out_drv, 3) -VIRTUAL_WIDGET(Digital CPU Playback, out_drv, 4) -VIRTUAL_WIDGET(Alt Analog CPU Playback, out_drv, 5) -VIRTUAL_WIDGET(Analog CPU Capture, input, 6) -VIRTUAL_WIDGET(Digital CPU Capture, input, 7) -VIRTUAL_WIDGET(Alt Analog CPU Capture, input, 8) - -DEBUG_END diff --git a/tools/topology/sof-hda-generic-idisp.m4 b/tools/topology/sof-hda-generic-idisp.m4 deleted file mode 100644 index 5a97b253580c..000000000000 --- a/tools/topology/sof-hda-generic-idisp.m4 +++ /dev/null @@ -1,117 +0,0 @@ -# -# Topology for SKL+ HDA Generic machine w/ iDISP codec only -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') - -# Define pipeline id for intel-generic-dmic.m4 -# to generate dmic setting - -ifelse(CHANNELS, `0', , -` -define(DMIC_PIPELINE_48k_ID, `5') -define(DMIC_PIPELINE_16k_ID, `6') - -include(`platform/intel/intel-generic-dmic.m4') -' -) - -# -# Define the pipelines -# -# PCM1 ----> volume -----> iDisp1 -# PCM2 ----> volume -----> iDisp2 -# PCM3 ----> volume -----> iDisp3 -# - -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 2 on PCM 1 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 3 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, HDA, 0, iDisp1, - PIPELINE_SOURCE_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, HDA, 1, iDisp2, - PIPELINE_SOURCE_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, HDA, 2, iDisp3, - PIPELINE_SOURCE_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(HDMI1, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(HDMI2, 2, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI3, 3, PIPELINE_PCM_4) - -# -# BE configurations - overrides config in ACPI if present -# - -# 3 HDMI/DP outputs (ID: 1,2,3) -DAI_CONFIG(HDA, 0, 1, iDisp1) -DAI_CONFIG(HDA, 1, 2, iDisp2) -DAI_CONFIG(HDA, 2, 3, iDisp3) - -VIRTUAL_DAPM_ROUTE_OUT(iDisp1_out, HDA, 0, OUT, 2) -VIRTUAL_DAPM_ROUTE_OUT(iDisp2_out, HDA, 1, OUT, 3) -VIRTUAL_DAPM_ROUTE_OUT(iDisp3_out, HDA, 2, OUT, 4) - -VIRTUAL_WIDGET(iDisp3 Tx, out_drv, 0) -VIRTUAL_WIDGET(iDisp2 Tx, out_drv, 1) -VIRTUAL_WIDGET(iDisp1 Tx, out_drv, 2) diff --git a/tools/topology/sof-hda-generic.m4 b/tools/topology/sof-hda-generic.m4 deleted file mode 100644 index 9544b20348a9..000000000000 --- a/tools/topology/sof-hda-generic.m4 +++ /dev/null @@ -1,185 +0,0 @@ -# Topology for SKL+ HDA Generic machine -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include bxt DSP configuration -include(`platform/intel/bxt.m4') - -# Define pipeline id for intel-generic-dmic.m4 -# to generate dmic setting - -ifelse(CHANNELS, `0', , -` -define(DMIC_PIPELINE_48k_ID, `10') -define(DMIC_PIPELINE_16k_ID, `11') - -include(`platform/intel/intel-generic-dmic.m4') -' -) - -# -# Define the pipelines -# -# PCM0P --> volume (pipe 1) --> HDA Analog (HDA Analog playback) -# PCM0C <-- volume, EQ (pipe 2) <-- HDA Analog (HDA Analog capture) -# PCM1P --> volume (pipe 3) --> HDA Digital (HDA Digital playback) -# PCM1C <-- volume, EQ (pipe 4) <-- HDA Digital (HDA Digital capture) -# PCM3 ----> volume (pipe 7) ----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM4 ----> Volume (pipe 8) ----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM5 ----> volume (pipe 9) ----> iDisp3 (HDMI/DP playback, BE link 5) -# - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-highpass-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 1 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 1 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-highpass-capture.m4, - 4, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 3 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 3, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 8 on PCM 4 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 4, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 9 on PCM 5 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 9, 5, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -# playback DAI is HDA Analog using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, HDA, 0, Analog Playback and Capture, - PIPELINE_SOURCE_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is HDA Analog using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, HDA, 1, Analog Playback and Capture, - PIPELINE_SINK_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is HDA Digital using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, HDA, 2, Digital Playback and Capture, - PIPELINE_SOURCE_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is HDA Digital using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, HDA, 3, Digital Playback and Capture, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 4, iDisp1, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 8, HDA, 5, iDisp2, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Dai buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 9, HDA, 6, iDisp3, - PIPELINE_SOURCE_9, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -PCM_DUPLEX_ADD(HDA Analog, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_DUPLEX_ADD(HDA Digital, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 3, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI2, 4, PIPELINE_PCM_8) -PCM_PLAYBACK_ADD(HDMI3, 5, PIPELINE_PCM_9) - -# -# BE configurations - overrides config in ACPI if present -# - -# HDA outputs -DAI_CONFIG(HDA, 0, 4, Analog Playback and Capture) -DAI_CONFIG(HDA, 1, 5, Digital Playback and Capture) -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 4, 1, iDisp1) -DAI_CONFIG(HDA, 5, 2, iDisp2) -DAI_CONFIG(HDA, 6, 3, iDisp3) - - -VIRTUAL_DAPM_ROUTE_IN(codec0_in, HDA, 1, IN, 1) -VIRTUAL_DAPM_ROUTE_IN(codec1_in, HDA, 3, IN, 2) -VIRTUAL_DAPM_ROUTE_OUT(codec0_out, HDA, 0, OUT, 3) -VIRTUAL_DAPM_ROUTE_OUT(codec1_out, HDA, 2, OUT, 4) - -# codec2 is not supported in dai links but it exists -# in dapm routes, so hack this one to HDA1 -VIRTUAL_DAPM_ROUTE_IN(codec2_in, HDA, 3, IN, 5) -VIRTUAL_DAPM_ROUTE_OUT(codec2_out, HDA, 2, OUT, 6) - -VIRTUAL_DAPM_ROUTE_OUT(iDisp1_out, HDA, 4, OUT, 7) -VIRTUAL_DAPM_ROUTE_OUT(iDisp2_out, HDA, 5, OUT, 8) -VIRTUAL_DAPM_ROUTE_OUT(iDisp3_out, HDA, 6, OUT, 9) - -VIRTUAL_WIDGET(iDisp3 Tx, out_drv, 0) -VIRTUAL_WIDGET(iDisp2 Tx, out_drv, 1) -VIRTUAL_WIDGET(iDisp1 Tx, out_drv, 2) -VIRTUAL_WIDGET(Analog CPU Playback, out_drv, 3) -VIRTUAL_WIDGET(Digital CPU Playback, out_drv, 4) -VIRTUAL_WIDGET(Alt Analog CPU Playback, out_drv, 5) -VIRTUAL_WIDGET(Analog CPU Capture, input, 6) -VIRTUAL_WIDGET(Digital CPU Capture, input, 7) -VIRTUAL_WIDGET(Alt Analog CPU Capture, input, 8) diff --git a/tools/topology/sof-icl-dmic-4ch.m4 b/tools/topology/sof-icl-dmic-4ch.m4 deleted file mode 100644 index ba95b4de3f93..000000000000 --- a/tools/topology/sof-icl-dmic-4ch.m4 +++ /dev/null @@ -1,69 +0,0 @@ -# -# Topology for ICL Lake with direct attach digital microphones array -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include IceLake DSP configuration -include(`platform/intel/icl.m4') - -# -# Define the pipelines -# -# PCM6 <---- volume <----- DMIC01 (dmic0 capture) -# - -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) - -# Passthrough capture pipeline 1 on PCM 1 using max 4 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 1, 1, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 1, DMIC, 0, dmic01, - PIPELINE_SINK_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) - -dnl PCM_CAPTURE_ADD(name, pipeline, capture) -PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_1) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) - -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) diff --git a/tools/topology/sof-icl-nocodec.m4 b/tools/topology/sof-icl-nocodec.m4 deleted file mode 100644 index 1cdaa44bfad7..000000000000 --- a/tools/topology/sof-icl-nocodec.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# -# Topology for generic Icelake board with nocodec -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Icelake DSP configuration -include(`platform/intel/icl.m4') - -# -# Define the pipelines -# -# PCM0 <---> Volume <---> SSP0 (NoCodec) -# - -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 s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SSP port 0 is our only pipeline DAI -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, NoCodec-0, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s24le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, NoCodec-0, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency -PCM_DUPLEX_ADD(Passthrough, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -# -# BE configurations - overrides config in ACPI if present -# -DAI_CONFIG(SSP, 0, 0, NoCodec-0, - SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, 38400000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24, 0, SSP_QUIRK_LBM))) diff --git a/tools/topology/sof-icl-rt700.m4 b/tools/topology/sof-icl-rt700.m4 deleted file mode 100644 index 8efbb4db63eb..000000000000 --- a/tools/topology/sof-icl-rt700.m4 +++ /dev/null @@ -1,184 +0,0 @@ -# -# Topology for Icelake with rt700 codec. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Icelake DSP configuration -include(`platform/intel/icl.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> ALH 2 BE dailink 0 -# PCM1 <--- volume <---- ALH 3 BE dailink 1 -# PCM2 <---------------- DMIC01 (dmic0 capture, BE dailink 2) -# PCM3 <---------------- DMIC16k (dmic16k, BE dailink 3) -# PCM4 ----> volume -----> iDisp1 (HDMI/DP playback, BE link 4) -# PCM5 ----> volume -----> iDisp2 (HDMI/DP playback, BE link 5) -# PCM6 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 6) -# - -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. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 3 on PCM 2 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 2, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 4 on PCM 3 using max 2 channels. -# Schedule 16 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 4, 3, 2, s16le, - 1000, 0, 0, - 16000, 16000, 16000) - -# Low Latency playback pipeline 5 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 6 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is ALH(SDW0 PIN2) 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, ALH, 2, SDW0-Playback, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW0 PIN2) 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, ALH, 3, SDW0-Capture, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 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, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16k using 2 periods -# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, DMIC, 1, dmic16k, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 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, - 5, HDA, 0, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 6, HDA, 1, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 7, HDA, 2, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(SDW0-speakers, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(SDW0-mics, 1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC, 2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC16kHz, 3, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 4, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 5, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 6, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -#ALH dai index = ((link_id << 8) | PDI id) -#ALH SDW0 Pin2 (ID: 0) -DAI_CONFIG(ALH, 2, 0, SDW0-Playback) - -#ALH SDW0 Pin3 (ID: 1) -DAI_CONFIG(ALH, 3, 1, SDW0-Capture) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 2) -DAI_CONFIG(DMIC, 1, 3, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 4,5,6) -DAI_CONFIG(HDA, 0, 4, iDisp1) -DAI_CONFIG(HDA, 1, 5, iDisp2) -DAI_CONFIG(HDA, 2, 6, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-icl-rt711-rt1308-rt715-hdmi.m4 b/tools/topology/sof-icl-rt711-rt1308-rt715-hdmi.m4 deleted file mode 100644 index e8265820f2ac..000000000000 --- a/tools/topology/sof-icl-rt711-rt1308-rt715-hdmi.m4 +++ /dev/null @@ -1,207 +0,0 @@ -# -# Topology for Icelake with rt711 + rt1308 (x2) + rt715. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Platform specific DSP configuration -include(`platform/intel/'PLATFORM`.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> ALH 2 BE dailink 0 -# PCM1 <--- volume <---- ALH 3 BE dailink 1 -# PCM2 ---> volume ----> ALH 2 BE dailink 2 -ifdef(`MONO', `', -`# PCM3 ---> volume ----> ALH 2 BE dailink 3') -# PCM4 <--- volume <---- ALH 2 BE dailink 4 -# PCM5 ---> volume <---- iDisp1 -# PCM6 ---> volume <---- iDisp2 -# PCM7 ---> volume <---- iDisp3 - -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. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-demux-playback.m4, - 3, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -ifdef(`MONO', `', -`# Low Latency playback pipeline 4 on PCM 3 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-dai-endpoint.m4, - 4, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000)') - -# Low Latency capture pipeline 5 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-highpass-capture.m4, - 5, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 6 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 8 on PCM 7 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 7, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is ALH(SDW0 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, ALH, 2, SDW0-Playback, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW0 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, ALH, 3, SDW0-Capture, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is ALH(SDW1 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, ALH, 0x102, SDW1-Playback, - PIPELINE_SOURCE_3, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -ifdef(`MONO', `', -`# playback DAI is ALH(SDW2 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD_SCHED(sof/pipe-dai-sched-playback.m4, - 4, ALH, 0x202, SDW1-Playback, - PIPELINE_SOURCE_4, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER, - PIPELINE_PLAYBACK_SCHED_COMP_3) - -# Connect demux to 2nd pipeline -SectionGraph."PIPE_DEMUX" { - index "4" - - lines [ - # mux to 2nd pipeline - dapm(PIPELINE_SOURCE_4, PIPELINE_DEMUX_3) - ] -} -') - -# capture DAI is ALH(SDW3 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 5, ALH, 0x302, SDW3-Capture, - PIPELINE_SINK_5, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# # Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 0, iDisp1, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# # Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 1, iDisp2, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# # Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 8, HDA, 2, iDisp3, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Headphone, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(Headset mic, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(SDW1-speakers, 2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(Microphones, 4, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_8) - -# -# BE configurations - overrides config in ACPI if present -# - -#ALH dai index = ((link_id << 8) | PDI id) -#ALH SDW0 Pin2 (ID: 0) -DAI_CONFIG(ALH, 2, 0, SDW0-Playback) - -#ALH SDW0 Pin3 (ID: 1) -DAI_CONFIG(ALH, 3, 1, SDW0-Capture) - -#ALH SDW1 Pin2 (ID: 2) -DAI_CONFIG(ALH, 0x102, 2, SDW1-Playback) - -#ALH SDW3 Pin2 (ID: 4) -DAI_CONFIG(ALH, 0x302, 4, SDW3-Capture) - -# 3 HDMI/DP outputs (ID: 5,6,7) -DAI_CONFIG(HDA, 0, 5, iDisp1) -DAI_CONFIG(HDA, 1, 6, iDisp2) -DAI_CONFIG(HDA, 2, 7, iDisp3) - -DEBUG_END diff --git a/tools/topology/sof-icl-rt711-rt1308-rt715.m4 b/tools/topology/sof-icl-rt711-rt1308-rt715.m4 deleted file mode 100644 index 8b8fe5c65104..000000000000 --- a/tools/topology/sof-icl-rt711-rt1308-rt715.m4 +++ /dev/null @@ -1,144 +0,0 @@ -# -# Topology for Icelake with rt711 + rt1308 (x2) + rt715. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Icelake DSP configuration -include(`platform/intel/icl.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> ALH 2 BE dailink 0 -# PCM1 <--- volume <---- ALH 3 BE dailink 1 -# PCM2 ---> volume ----> ALH 2 BE dailink 2 -# PCM3 ---> volume ----> ALH 2 BE dailink 3 -# PCM4 <--- volume <---- ALH 2 BE dailink 4 - -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. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 3 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 5 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-highpass-capture.m4, - 5, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is ALH(SDW0 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, ALH, 2, SDW0-Playback, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW0 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, ALH, 3, SDW0-Capture, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is ALH(SDW1 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, ALH, 0x102, SDW1-Playback, - PIPELINE_SOURCE_3, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is ALH(SDW2 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 4, ALH, 0x202, SDW2-Playback, - PIPELINE_SOURCE_4, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW3 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 5, ALH, 0x302, SDW3-Capture, - PIPELINE_SINK_5, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Headphone, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(Headset mics, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(SDW1-speakers, 2, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(SDW2-speakers, 3, PIPELINE_PCM_4) -PCM_CAPTURE_ADD(Microphones, 4, PIPELINE_PCM_5) - -# -# BE configurations - overrides config in ACPI if present -# - -#ALH dai index = ((link_id << 8) | PDI id) -#ALH SDW0 Pin2 (ID: 0) -DAI_CONFIG(ALH, 2, 0, SDW0-Playback) - -#ALH SDW0 Pin3 (ID: 1) -DAI_CONFIG(ALH, 3, 1, SDW0-Capture) - -#ALH SDW1 Pin2 (ID: 2) -DAI_CONFIG(ALH, 0x102, 2, SDW1-Playback) - -#ALH SDW2 Pin2 (ID: 3) -DAI_CONFIG(ALH, 0x202, 3, SDW2-Playback) - -#ALH SDW3 Pin2 (ID: 4) -DAI_CONFIG(ALH, 0x302, 4, SDW3-Capture) - -DEBUG_END diff --git a/tools/topology/sof-imx8mp-wm8960.m4 b/tools/topology/sof-imx8mp-wm8960.m4 deleted file mode 100644 index fa9c09a14424..000000000000 --- a/tools/topology/sof-imx8mp-wm8960.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# -# Topology for i.MX8MP board with wm8960 codec -# - -# 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/imx8qxp.m4') - -# -# Define the pipelines -# -# PCM0 <----> volume <-----> SAI3 (wm8960) -# - -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 on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) -# -# DAIs configuration -# - -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, sai3-wm8960-hifi, - 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, sai3-wm8960-hifi, - 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, 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, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/sof-imx8qxp-cs42888.m4 b/tools/topology/sof-imx8qxp-cs42888.m4 deleted file mode 100644 index d6c7071fe67d..000000000000 --- a/tools/topology/sof-imx8qxp-cs42888.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# -# Topology for i.MX8QXP board with cs42888 codec -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`esai.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/imx8qxp.m4') - -# -# Define the pipelines -# -# PCM0 <----> volume <-----> ESAI0 (cs42888) -# - -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 s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -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 ESAI0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, ESAI, 0, esai0-cs42888, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# capture DAI is ESAI0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, ESAI, 0, esai0-cs42888, - PIPELINE_SINK_2, 2, s24le, - 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, esai_config) -DAI_CONFIG(ESAI, 0, 0, esai0-cs42888, - ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), - ESAI_CLOCK(bclk, 3072000, codec_slave), - ESAI_CLOCK(fsync, 48000, codec_slave), - ESAI_TDM(2, 32, 3, 3), - ESAI_CONFIG_DATA(ESAI, 0, 0))) diff --git a/tools/topology/sof-imx8qxp-nocodec-sai.m4 b/tools/topology/sof-imx8qxp-nocodec-sai.m4 deleted file mode 100644 index 0bb539453158..000000000000 --- a/tools/topology/sof-imx8qxp-nocodec-sai.m4 +++ /dev/null @@ -1,68 +0,0 @@ -# -# Topology for i.MX8QXP board with nocodec -# - -# 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/imx8qxp.m4') - -# -# Define the pipelines -# -# PCM0 ---> Volume ---> SAI1 (NoCodec) -# - -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 s24le -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 8000, 96000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core) - -# playback DAI is SAI1 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 1, NoCodec-0, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) - -# PCM Low Latency, id 0 -PCM_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) - -dnl DAI_CONFIG(type, dai_index, link_id, name, sai_config) -DAI_CONFIG(SAI, 1, 0, NoCodec-0, - SAI_CONFIG(I2S, SAI_CLOCK(mclk, 49152000, codec_mclk_in), - SAI_CLOCK(bclk, 3072000, codec_slave), - SAI_CLOCK(fsync, 48000, codec_slave), - SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/sof-imx8qxp-nocodec.m4 b/tools/topology/sof-imx8qxp-nocodec.m4 deleted file mode 100644 index db979a74d4c9..000000000000 --- a/tools/topology/sof-imx8qxp-nocodec.m4 +++ /dev/null @@ -1,68 +0,0 @@ -# -# Topology for i.MX8QXP board with nocodec -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`esai.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/imx8qxp.m4') - -# -# Define the pipelines -# -# PCM0 ---> Volume ---> ESAI0 (NoCodec) -# - -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 s24le -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s24le, - 1000, 0, 0, - 8000, 96000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core) - -# playback DAI is ESAI0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, ESAI, 0, NoCodec-0, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) - -# PCM Low Latency, id 0 -PCM_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) - -dnl DAI_CONFIG(type, dai_index, link_id, name, esai_config) -DAI_CONFIG(ESAI, 0, 0, NoCodec-0, - ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), - ESAI_CLOCK(bclk, 3072000, codec_slave), - ESAI_CLOCK(fsync, 48000, codec_slave), - ESAI_TDM(2, 32, 3, 3), - ESAI_CONFIG_DATA(ESAI, 0, 0))) diff --git a/tools/topology/sof-imx8qxp-wm8960.m4 b/tools/topology/sof-imx8qxp-wm8960.m4 deleted file mode 100644 index 66c964132f61..000000000000 --- a/tools/topology/sof-imx8qxp-wm8960.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# -# Topology for i.MX8QXP board with wm8960 codec -# - -# 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/imx8qxp.m4') - -# -# Define the pipelines -# -# PCM0 <----> volume <-----> SAI1 (wm8960) -# - -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 on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# Set 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) -# -# DAIs configuration -# - -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 -# 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, - PIPELINE_SOURCE_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# 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, 1, sai1-wm8960-hifi, - 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, 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, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/sof-jsl-da7219.m4 b/tools/topology/sof-jsl-da7219.m4 deleted file mode 100644 index a17f21978ced..000000000000 --- a/tools/topology/sof-jsl-da7219.m4 +++ /dev/null @@ -1,198 +0,0 @@ -# -# Topology for JasperLake with Dialog7219. -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Icelake DSP configuration -include(`platform/intel/icl.m4') -include(`platform/intel/dmic.m4') - -define(`SPK_INDEX', `1') -define(`SPK_NAME', `SSP1-Codec') - -undefine(`SPK_DATA_FORMAT') -define(`SPK_DATA_FORMAT', ifelse(PLATFORM, `jsl', `s16le', - ifelse(PLATFORM, `jsl-dedede', `s24le',`'))) - -# -# Define the pipelines -# -# PCM0 ----> volume (pipe 4) -----> SSP1 (speaker - maxim98373, BE link 0) -# PCM1 <---> volume (pipe 1,2) <----> SSP0 (headset - da7219, BE link 1) -# PCM5 <---- DMIC0 (pipe 3) <----- dmic (DMIC01 - BE link 2) -# PCM2 ----> volume (pipe 5) -----> iDisp1 (HDMI/DP playback, BE link 3) -# PCM3 ----> Volume (pipe 6) -----> iDisp2 (HDMI/DP playback, BE link 4) -# PCM4 ----> volume (pipe 7) -----> iDisp3 (HDMI/DP playback, BE link 5) - -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 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 5 using max 4 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 3, 5, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 4, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 3 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, SSP0-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, SSP0-Codec, - PIPELINE_SINK_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC0 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, - 3, DMIC, 0, dmic01, - PIPELINE_SINK_3, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -DAI_ADD(sof/pipe-dai-playback.m4, - 4, SSP, SPK_INDEX, SPK_NAME, - PIPELINE_SOURCE_4, 2, SPK_DATA_FORMAT, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, HDA, 0, iDisp1, - PIPELINE_SOURCE_5, 2, s16le, - 1000, 0, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 1, iDisp2, - PIPELINE_SOURCE_6, 2, s16le, - 1000, 0, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 2, iDisp3, - PIPELINE_SOURCE_7, 2, s16le, - 1000, 0, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# -# Bind PCM with the pipeline -# - -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Speakers, 0, PIPELINE_PCM_4) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_CAPTURE_ADD(DMIC01, 5, PIPELINE_PCM_3) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_7) - -# -# BE configurations - overrides config in ACPI if present -# - -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) -dnl SSP_CLOCK(clock, freq, codec_master, polarity) -dnl SSP_CONFIG_DATA(type, idx, valid bits, mclk_id) -dnl mclk_id is optional - -# SSP 1 (ID: 0) -DAI_CONFIG(SSP, SPK_INDEX, 0, SPK_NAME, - ifelse(PLATFORM, `jsl', - SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 4800000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(4, 25, 3, 240), - SSP_CONFIG_DATA(SSP, SPK_INDEX, 16)), - PLATFORM, `jsl-dedede', - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2304000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 24, 3, 3), - SSP_CONFIG_DATA(SSP, SPK_INDEX, 24, 0)), - `')) -# SSP 0 (ID: 1) -DAI_CONFIG(SSP, 0, 1, SSP0-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 16))) - -# dmic01 (ID: 2) -DAI_CONFIG(DMIC, 0, 2, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 3 HDMI/DP outputs (ID: 3,4,5) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) diff --git a/tools/topology/sof-tgl-max98357a-rt5682.m4 b/tools/topology/sof-tgl-max98357a-rt5682.m4 deleted file mode 100644 index e68f3b40d583..000000000000 --- a/tools/topology/sof-tgl-max98357a-rt5682.m4 +++ /dev/null @@ -1,202 +0,0 @@ -# -# Topology for Tigerlake with Max98357a amp + rt5682 codec + DMIC + 4 HDMI -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Tigerlake DSP configuration -include(`platform/intel/tgl.m4') -include(`platform/intel/dmic.m4') -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> SSP1 (Speaker - max98357a) -# PCM1 <---> volume <----> SSP0 (Headset - ALC5682) -# PCM99 <---- volume <----- DMIC01 (dmic0 capture) -# PCM2 ----> volume -----> iDisp1 -# PCM3 ----> volume -----> iDisp2 -# PCM4 ----> volume -----> iDisp3 -# PCM5 ----> volume -----> iDisp4 - -dnl PIPELINE_PCM_ADD(pipeline, -dnl pipe id, pcm, max channels, format, -dnl frames, deadline, priority, core) - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s24le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s24le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 2 channels of s24le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) -# Passthrough capture pipeline 4 on PCM 99 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 4, 99, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 3 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 4 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl frames, deadline, priority, core) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0) -# playback DAI is SSP0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 0, SSP0-Codec, - PIPELINE_SOURCE_2, 2, s24le, - 1000, 0, 0) - -# capture DAI is SSP0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 0, SSP0-Codec, - PIPELINE_SINK_3, 2, s24le, - 1000, 0, 0) - -# capture DAI is DMIC01 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, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0) - -# playback DAI is iDisp1 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, - 5, HDA, 0, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 6, HDA, 1, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 7, HDA, 2, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp4 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, - 8, HDA, 3, iDisp4, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(max357a-spk, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 99, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI4, 5, PIPELINE_PCM_8) - -# -# BE conf2igurations - overrides config in ACPI if present -# -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) -dnl SSP_CLOCK(clock, freq, codec_master, polarity) -dnl SSP_CONFIG_DATA(type, idx, valid bits, mclk_id) -dnl mclk_id is optional -dnl ssp1-maxmspk - -# SSP 1 (ID: 7) -DAI_CONFIG(SSP, 1, 7, SSP1-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 1536000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 16, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 16))) -# SSP 0 (ID: 0) -DAI_CONFIG(SSP, 0, 0, SSP0-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24))) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 4 HDMI/DP outputs (ID: 3,4,5,6) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) -DAI_CONFIG(HDA, 3, 6, iDisp4) - -DEBUG_END diff --git a/tools/topology/sof-tgl-max98373-rt5682.m4 b/tools/topology/sof-tgl-max98373-rt5682.m4 deleted file mode 100644 index c47500886621..000000000000 --- a/tools/topology/sof-tgl-max98373-rt5682.m4 +++ /dev/null @@ -1,210 +0,0 @@ -# -# Topology for Tigerlake with Max98373 amp + rt5682 codec + DMIC + 4 HDMI -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Tigerlake DSP configuration -include(`platform/intel/tgl.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> SSP1 (Speaker - max98373) -# PCM1 <---> volume <----> SSP0 (Headset - ALC5682) -# PCM99 <---- volume <---- DMIC01 (dmic0 capture) -# PCM2 ----> volume -----> iDisp1 -# PCM3 ----> volume -----> iDisp2 -# PCM4 ----> volume -----> iDisp3 -# PCM5 ----> volume -----> iDisp4 - - -dnl PIPELINE_PCM_ADD(pipeline, -dnl pipe id, pcm, max channels, format, -dnl frames, deadline, priority, core) - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 3 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 3, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 4 on PCM 99 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 4, 99, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 6 on PCM 3 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 3, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 4 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 4, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 8 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl frames, deadline, priority, core) - -# playback DAI is SSP1 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 1, SSP1-Codec, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 2, SSP, 0, SSP0-Codec, - PIPELINE_SOURCE_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 3, SSP, 0, SSP0-Codec, - PIPELINE_SINK_3, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 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, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 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, - 5, HDA, 0, iDisp1, - PIPELINE_SOURCE_5, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 6, HDA, 1, iDisp2, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 7, HDA, 2, iDisp3, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp4 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, - 8, HDA, 3, iDisp4, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# -# Bind PCM with the pipeline -# -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(max373-spk, 0, PIPELINE_PCM_1) -PCM_DUPLEX_ADD(Headset, 1, PIPELINE_PCM_2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 99, PIPELINE_PCM_4) -PCM_PLAYBACK_ADD(HDMI1, 2, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI2, 3, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI3, 4, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI4, 5, PIPELINE_PCM_8) - -# -# BE configurations - overrides config in ACPI if present -# -dnl DAI_CONFIG(type, dai_index, link_id, name, ssp_config/dmic_config) -dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) -dnl SSP_CLOCK(clock, freq, codec_master, polarity) -dnl SSP_CONFIG_DATA(type, idx, valid bits, mclk_id) -dnl mclk_id is optional -dnl ssp1-maxmspk, ssp0-RTHeadset - -#SSP 1 (ID: 7) -DAI_CONFIG(SSP, 1, 7, SSP1-Codec, - SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, 38400000, codec_mclk_in), - SSP_CLOCK(bclk, 9600000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(8, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 24))) - -#SSP 0 (ID: 0) -DAI_CONFIG(SSP, 0, 0, SSP0-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 19200000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24))) - -# dmic01 (ID: 1) -DAI_CONFIG(DMIC, 0, 1, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# 4 HDMI/DP outputs (ID: 3,4,5,6) -DAI_CONFIG(HDA, 0, 3, iDisp1) -DAI_CONFIG(HDA, 1, 4, iDisp2) -DAI_CONFIG(HDA, 2, 5, iDisp3) -DAI_CONFIG(HDA, 3, 6, iDisp4) - -DEBUG_END diff --git a/tools/topology/sof-tgl-nocodec.m4 b/tools/topology/sof-tgl-nocodec.m4 deleted file mode 100644 index df16a327c3dd..000000000000 --- a/tools/topology/sof-tgl-nocodec.m4 +++ /dev/null @@ -1,186 +0,0 @@ -# -# Topology for generic Tigerlake board with no codec and digital mic array. -# -# TGL Host GW DMAC support max 6 playback and max 6 capture channels so some -# pipelines/PCMs/DAIs are commented out to keep within HW bounds. If these -# are needed then they can be used provided other PCMs/pipelines/SSPs are -# commented out in their place. - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`ssp.m4') -include(`pipeline.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Tigerlake DSP configuration -include(`platform/intel/tgl.m4') -include(`platform/intel/dmic.m4') - -# -# Define the pipelines -# -# PCM0 <---> volume <----> SSP0 -# PCM1 <---> Volume <----> SSP1 -# PCM2 <---> volume <----> SSP2 -# PCM6 <---- volume <----- DMIC6 (DMIC01) -# - -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 s16le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s16le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 1 using max 2 channels of s16le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 1, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 4 on PCM 1 using max 2 channels of s16le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 1, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 5 on PCM 2 using max 2 channels of s16le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 5, 2, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 6 on PCM 2 using max 2 channels of s16le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 6, 2, 2, s16le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 13 on PCM 6 using max 2 channels. -# 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, - 13, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is SSP0 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SSP, 0, NoCodec-0, - PIPELINE_SOURCE_1, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP0 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SSP, 0, NoCodec-0, - PIPELINE_SINK_2, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP1 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, SSP, 1, NoCodec-1, - PIPELINE_SOURCE_3, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP1 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 4, SSP, 1, NoCodec-1, - PIPELINE_SINK_4, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 5, SSP, 2, NoCodec-2, - PIPELINE_SOURCE_5, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is SSP2 using 2 periods -# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 6, SSP, 2, NoCodec-2, - PIPELINE_SINK_6, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC 0 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 13, DMIC, 0, NoCodec-6, - PIPELINE_SINK_13, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) -PCM_DUPLEX_ADD(Port1, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) -PCM_DUPLEX_ADD(Port2, 2, PIPELINE_PCM_5, PIPELINE_PCM_6) -PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_13) - -# -# BE configurations - overrides config in ACPI if present -# - -DAI_CONFIG(SSP, 0, 0, NoCodec-0, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 0, 24, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 1, 1, NoCodec-1, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 1, 24, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(SSP, 2, 2, NoCodec-2, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 24, 0, SSP_QUIRK_LBM))) - -DAI_CONFIG(DMIC, 0, 6, NoCodec-6, - dnl DMIC_CONFIG(driver_version, clk_min, clk_mac, duty_min, duty_max, - dnl sample_rate, fifo word length, unmute time, type, - dnl dai_index, pdm controller config) - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - dnl PDM_CONFIG(type, dai_index, num pdm active, pdm tuples list) - dnl STEREO_PDM0 is a pre-defined pdm config for stereo capture - PDM_CONFIG(DMIC, 0, STEREO_PDM0))) - diff --git a/tools/topology/sof-tgl-rt711-i2s-rt1308.m4 b/tools/topology/sof-tgl-rt711-i2s-rt1308.m4 deleted file mode 100644 index 64408ed25f1f..000000000000 --- a/tools/topology/sof-tgl-rt711-i2s-rt1308.m4 +++ /dev/null @@ -1,244 +0,0 @@ -# -# Topology for Tigerlake with rt711 + rt1308 codec + DMIC + 4 HDMI -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`ssp.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include Tigerlake DSP configuration -include(`platform/intel/tgl.m4') -include(`platform/intel/dmic.m4') - -DEBUG_START - -# -# Define the pipelines -# - -# PCM0 ---> volume ----> ALH 2 BE dailink 0 -# PCM1 <--- volume <---- ALH 3 BE dailink 1 -# PCM2 ----> volume -----> SSP2 BE dailink 2 -# PCM3 <---- volume <----- DMIC01 (dmic0 capture) BE dailink 3 -# PCM4 <---------------- DMIC16k (dmic16k, BE dailink 4) - -ifelse(HDMI, `1', -` -# PCM5 ----> volume -----> iDisp1 (HDMI/DP playback, BE link 5) -# PCM6 ----> volume -----> iDisp2 (HDMI/DP playback, BE link 6) -# PCM7 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 7) -# PCM8 ----> volume -----> iDisp3 (HDMI/DP playback, BE link 8) -') - -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. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s24le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 2, 2, s24le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 4 on PCM 3 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 3, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 5 on PCM 4 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 5, 4, 4, s16le, - 1000, 0, 0, - 16000, 16000, 16000) - -ifelse(HDMI, `1', -` -# Low Latency playback pipeline 6 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 6 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 8 on PCM 7 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 7, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 9 on PCM 8 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 9, 8, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) -') - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is ALH(SDW0 PIN2) 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, ALH, 2, SDW0-Playback, - PIPELINE_SOURCE_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW0 PIN2) 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, ALH, 3, SDW0-Capture, - PIPELINE_SINK_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is SSP2 using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, SSP, 2, SSP2-Codec, - PIPELINE_SOURCE_3, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 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, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16k using 2 periods -# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 5, DMIC, 1, dmic16k, - PIPELINE_SINK_5, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -ifelse(HDMI, `1', -` -# playback DAI is iDisp1 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, - 6, HDA, 0, iDisp1, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 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, - 7, HDA, 1, iDisp2, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 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, - 8, HDA, 2, iDisp3, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp4 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, - 9, HDA, 3, iDisp4, - PIPELINE_SOURCE_9, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) -') - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(SDW0-headphone, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(SDW0-mics, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(Speaker, 2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 3, PIPELINE_PCM_4) -PCM_CAPTURE_ADD(DMIC16kHz, 4, PIPELINE_PCM_5) - -ifelse(HDMI, `1', -` -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_8) -PCM_PLAYBACK_ADD(HDMI4, 8, PIPELINE_PCM_9) -') - -# -# BE configurations - overrides config in ACPI if present -# - -#ALH dai index = ((link_id << 8) | PDI id) -#ALH SDW0 Pin2 (ID: 0) -DAI_CONFIG(ALH, 0x002, 0, SDW0-Playback) - -#ALH SDW0 Pin3 (ID: 1) -DAI_CONFIG(ALH, 0x003, 1, SDW0-Capture) - -#SSP 2 (ID: 2) -DAI_CONFIG(SSP, 2, 2, SSP2-Codec, - SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), - SSP_CLOCK(bclk, 2400000, codec_slave), - SSP_CLOCK(fsync, 48000, codec_slave), - SSP_TDM(2, 25, 3, 3), - SSP_CONFIG_DATA(SSP, 2, 24))) - -# dmic01 (ID: 3) -DAI_CONFIG(DMIC, 0, 3, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 4) -DAI_CONFIG(DMIC, 1, 4, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -ifelse(HDMI, `1', -` -# 4 HDMI/DP outputs (ID: 5,6,7,8) -DAI_CONFIG(HDA, 0, 5, iDisp1) -DAI_CONFIG(HDA, 1, 6, iDisp2) -DAI_CONFIG(HDA, 2, 7, iDisp3) -DAI_CONFIG(HDA, 3, 8, iDisp4) -') - -DEBUG_END diff --git a/tools/topology/sof-tgl-rt711-rt1308.m4 b/tools/topology/sof-tgl-rt711-rt1308.m4 deleted file mode 100644 index 1ccfa6e97fd2..000000000000 --- a/tools/topology/sof-tgl-rt711-rt1308.m4 +++ /dev/null @@ -1,218 +0,0 @@ -# -# Topology for Tigerlake with rt711 + rt1308 (x2). -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`platform/intel/dmic.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -include(`platform/intel/tgl.m4') - -DEBUG_START - -# -# Define the pipelines -# -# PCM0 ---> volume ----> ALH 2 BE dailink 0 -# PCM1 <--- volume <---- ALH 3 BE dailink 1 -# PCM2 <--- volume <---- ALH 2 BE dailink 2 -# PCM3 <----volume <---- DMIC01 -# PCM4 <----volume <---- DMIC16k -# PCM5 ---> volume <---- iDisp1 -# PCM6 ---> volume <---- iDisp2 -# PCM7 ---> volume <---- iDisp3 -# PCM8 ---> volume <---- iDisp4 - -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. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 1, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 3 on PCM 2 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 3, 2, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 4 on PCM 3 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 4, 3, 4, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Passthrough capture pipeline 5 on PCM 4 using max 4 channels. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture-16khz.m4, - 5, 4, 4, s16le, - 1000, 0, 0, - 16000, 16000, 16000) - -# Low Latency playback pipeline 6 on PCM 5 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 6, 5, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 7 on PCM 6 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 7, 6, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 8 on PCM 7 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 8, 7, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# Low Latency playback pipeline 9 on PCM 8 using max 2 channels of s32le. -# Schedule 48 frames per 1000us deadline on core 0 with priority 0 -PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, - 9, 8, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAIs configuration -# - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl deadline, priority, core, time_domain) - -# playback DAI is ALH(SDW0 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, ALH, 2, SDW0-Playback, - PIPELINE_SOURCE_1, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is ALH(SDW0 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, ALH, 3, SDW0-Capture, - PIPELINE_SINK_2, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is ALH(SDW1 PIN2) using 2 periods -# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 3, ALH, 0x102, SDW1-Playback, - PIPELINE_SOURCE_3, 2, s24le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC01 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, - 4, DMIC, 0, dmic01, - PIPELINE_SINK_4, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# capture DAI is DMIC16k using 2 periods -# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 5, DMIC, 1, dmic16k, - PIPELINE_SINK_5, 2, s16le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp1 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 6, HDA, 0, iDisp1, - PIPELINE_SOURCE_6, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp2 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 7, HDA, 1, iDisp2, - PIPELINE_SOURCE_7, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 8, HDA, 2, iDisp3, - PIPELINE_SOURCE_8, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# playback DAI is iDisp4 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, - 9, HDA, 3, iDisp4, - PIPELINE_SOURCE_9, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) - -# PCM Low Latency, id 0 -dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) -PCM_PLAYBACK_ADD(Headphone, 0, PIPELINE_PCM_1) -PCM_CAPTURE_ADD(Headset mic, 1, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(SDW1-speakers, 2, PIPELINE_PCM_3) -PCM_CAPTURE_ADD(DMIC, 3, PIPELINE_PCM_4) -PCM_CAPTURE_ADD(DMIC16kHz, 4, PIPELINE_PCM_5) -PCM_PLAYBACK_ADD(HDMI1, 5, PIPELINE_PCM_6) -PCM_PLAYBACK_ADD(HDMI2, 6, PIPELINE_PCM_7) -PCM_PLAYBACK_ADD(HDMI3, 7, PIPELINE_PCM_8) -PCM_PLAYBACK_ADD(HDMI4, 8, PIPELINE_PCM_9) -# -# BE configurations - overrides config in ACPI if present -# - -#ALH dai index = ((link_id << 8) | PDI id) -#ALH SDW0 Pin2 (ID: 0) -DAI_CONFIG(ALH, 2, 0, SDW0-Playback) - -#ALH SDW0 Pin3 (ID: 1) -DAI_CONFIG(ALH, 3, 1, SDW0-Capture) - -#ALH SDW1 Pin2 (ID: 2) -DAI_CONFIG(ALH, 0x102, 2, SDW1-Playback) - -# dmic01 (ID: 3) -DAI_CONFIG(DMIC, 0, 3, dmic01, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 48000, - DMIC_WORD_LENGTH(s32le), 400, DMIC, 0, - PDM_CONFIG(DMIC, 0, FOUR_CH_PDM0_PDM1))) - -# dmic16k (ID: 4) -DAI_CONFIG(DMIC, 1, 4, dmic16k, - DMIC_CONFIG(1, 500000, 4800000, 40, 60, 16000, - DMIC_WORD_LENGTH(s16le), 400, DMIC, 1, - PDM_CONFIG(DMIC, 1, STEREO_PDM0))) - -# 3 HDMI/DP outputs (ID: 5,6,7) -DAI_CONFIG(HDA, 0, 5, iDisp1) -DAI_CONFIG(HDA, 1, 6, iDisp2) -DAI_CONFIG(HDA, 2, 7, iDisp3) -DAI_CONFIG(HDA, 3, 8, iDisp4) - -DEBUG_END diff --git a/tools/topology/sof/pipe-demux-playback.m4 b/tools/topology/sof/pipe-demux-playback.m4 deleted file mode 100644 index 9c7795b56f52..000000000000 --- a/tools/topology/sof/pipe-demux-playback.m4 +++ /dev/null @@ -1,80 +0,0 @@ -# Demux Pipeline -# -# Low Latency Playback with demux. -# -# Pipeline Endpoints for connection are :- -# -# Playback Demux -# B1 (DAI buffer) -# -# -# host PCM_P -- B0 --> Demux(M) -- B1--> sink DAI0 -# | -# pipeline n+1 --> DAI -# - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`muxdemux.m4') -include(`mixercontrol.m4') -include(`bytecontrol.m4') - -# Use default parameters -include(`demux_coef_default.m4') - -# demux Bytes control with max value of 255 -C_CONTROLBYTES(DEMUX, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - DEMUX_priv) -# -# Components and Buffers -# - -# Host "Low latency Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0) - -# Mux 0 has 2 sink and source periods. -W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, LIST(` ', "DEMUX")) - -# Low Latency Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_COMP_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --B0--> volume(0P) --B1--> Mux(M) --B2--> volume(LL) ---B3--> sink DAI0 - -P_GRAPH(pipe-ll-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_MUXDEMUX(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_MUXDEMUX(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID) - -# -# PCM Configuration -# - - -# PCM capabilities supported by FW -PCM_CAPABILITIES(Low Latency Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/pipe-eq-capture-16khz.m4 b/tools/topology/sof/pipe-eq-capture-16khz.m4 deleted file mode 100644 index ac9b0e7d490c..000000000000 --- a/tools/topology/sof/pipe-eq-capture-16khz.m4 +++ /dev/null @@ -1,114 +0,0 @@ -# Capture EQ Pipeline and PCM, 16 kHz -# -# Pipeline Endpoints for connection are :- -# -# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`bytecontrol.m4') -include(`eq_iir.m4') - -define(`CONTROL_NAME', Capture Volume) -define(`PGA_NAME', Dmic1) - -# -# Controls -# - -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, - 256 binds the mixer control to volume get/put handlers, - 256, 256), - CONTROLMIXER_MAX(, 70), - false, - CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# Volume Configuration -W_VENDORTUPLES(capture_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(capture_pga_conf, capture_pga_tokens) - -# Use 50 Hz highpass response with +20 dB gain -include(`eq_iir_coef_highpass_50hz_20db_16khz.m4') - -# EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQIIR_C16, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - CONTROLBYTES_EXTOPS( - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - EQIIR_HP50HZ20dB16K_priv) - -# -# Components and Buffers -# - -# Host "Highpass Capture" PCM -# with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2) - -# "Volume" has 2 source and 2 sink periods -W_PGA(0, PIPELINE_FORMAT, 2, 2, - capture_pga_conf, LIST(` ', - "CONTROL_NAME")) - -# "EQ 0" has 2 sink period and x source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, LIST(` ', "EQIIR_C16")) - -# Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - eval(PCM_MAX_RATE / SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 - -P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', - `dapm(N_BUFFER(0), PGA_NAME)', - `dapm(PGA_NAME, N_BUFFER(1))', - `dapm(N_BUFFER(1), N_EQ_IIR(0))', - `dapm(N_EQ_IIR(0), N_BUFFER(2))')) - -undefine(`CONTROL_NAME') -undefine(`PGA_NAME') - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', 16000, 16000, - PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-eq-capture.m4 b/tools/topology/sof/pipe-eq-capture.m4 deleted file mode 100644 index d368cbd2d005..000000000000 --- a/tools/topology/sof/pipe-eq-capture.m4 +++ /dev/null @@ -1,132 +0,0 @@ -# Capture EQ Pipeline and PCM, 48 kHz -# -# Pipeline Endpoints for connection are :- -# -# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`bytecontrol.m4') -include(`mixercontrol.m4') -include(`eq_iir.m4') - -define(`PGA_NAME', Dmic0) -define(`CONTROL_NAME_VOLUME', Capture Volume) -define(`CONTROL_NAME_SWITCH', Capture Switch) -define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') - -# -# Controls -# - -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, - 256 binds the mixer control to volume get/put handlers, - 256, 256), - CONTROLMIXER_MAX(, 70), - false, - CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') - -# Switch type Mixer Control with max value of 1 -C_CONTROLMIXER(Master Capture Switch, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), - CONTROLMIXER_MAX(max 1 indicates switch type control, 1), - false, - , - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 2, 0), KCONTROL_CHANNEL(FR, 2, 1)), - "1", "1") - -# Volume Configuration -W_VENDORTUPLES(capture_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(capture_pga_conf, capture_pga_tokens) - -# Use 50 Hz highpass response with +20 dB gain -include(`eq_iir_coef_highpass_50hz_20db_48khz.m4') - -# EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQIIR_C48, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - CONTROLBYTES_EXTOPS( - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - EQIIR_HP50HZ20dB48K_priv) - -# -# Components and Buffers -# - -# Host "Highpass Capture" PCM -# with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2) - -# "Volume" has 2 source and 2 sink periods -W_PGA(0, PIPELINE_FORMAT, 2, 2, - capture_pga_conf, LIST(` ', - "CONTROL_NAME_VOLUME", "CONTROL_NAME_SWITCH")) - -# "EQ 0" has 2 sink period and x source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, LIST(` ', "EQIIR_C48")) - -# Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 - -P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', - `dapm(N_BUFFER(0), PGA_NAME)', - `dapm(PGA_NAME, N_BUFFER(1))', - `dapm(N_BUFFER(1), N_EQ_IIR(0))', - `dapm(N_EQ_IIR(0), N_BUFFER(2))')) - -undefine(`PGA_NAME') -undefine(`CONTROL_NAME') -undefine(`CONTROL_NAME_VOLUME') -undefine(`CONTROL_NAME_SWITCH') - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, - PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, - 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-eq-fir-capture.m4 b/tools/topology/sof/pipe-eq-fir-capture.m4 deleted file mode 100644 index 65e592c1df4f..000000000000 --- a/tools/topology/sof/pipe-eq-fir-capture.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# Capture EQ Pipeline and PCM, 48 kHz -# -# Pipeline Endpoints for connection are :- -# -# host PCM_C <-- B0 <--EQ_FIR 0 <-- B1 <-- sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`bytecontrol.m4') -include(`eq_fir.m4') - -# -# Controls -# - -# Use flat response -include(`eq_fir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -define(MY_CONTROLBYTES, concat(`EQFIR_CONTROLBYTES_', PIPELINE_ID)) -C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - CONTROLBYTES_EXTOPS( - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 4096), - , - EQFIR_priv) - -# -# Components and Buffers -# - -# Host "EQ FIR Capture" PCM -# with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, EQ FIR Capture, 0, 2) - -# "EQ 0" has 2 sink period and x source periods -W_EQ_FIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, LIST(` ', "MY_CONTROLBYTES")) - -# Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_C <-- B0 <--EQ_FIR 0 <-- B1 <-- sink DAI0 - -P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', - `dapm(N_BUFFER(0), N_EQ_FIR(0))', - `dapm(N_EQ_FIR(0), N_BUFFER(1))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), EQ FIR Capture PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(EQ FIR Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, - PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, - 2, 16, 192, 16384, 65536, 65536) - -undefine(`MY_CONTROLBYTES') diff --git a/tools/topology/sof/pipe-eq-fir-playback.m4 b/tools/topology/sof/pipe-eq-fir-playback.m4 deleted file mode 100644 index 906ca3cd05e3..000000000000 --- a/tools/topology/sof/pipe-eq-fir-playback.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> EQ_FIR 0 --> B1 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`dai.m4') -include(`bytecontrol.m4') -include(`pipeline.m4') -include(`eq_fir.m4') - -# -# Controls -# - -# Use coefficients for flat frequency response -include(`eq_fir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -define(MY_CONTROLBYTES, concat(`EQFIR_CONTROLBYTES_', PIPELINE_ID)) -C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 4096), - , - EQFIR_priv) - -# -# Components and Buffers -# - -# Host "EQ FIR Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, EQ FIR Playback, 2, 0) - -# "EQ 0" has x sink period and 2 source periods -W_EQ_FIR(0, PIPELINE_FORMAT, DAI_PERIODS, 2, LIST(` ', "MY_CONTROLBYTES")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host host PCM_P --> B0 --> EQ_FIR 0 --> B1 --> sink DAI0 - -P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_EQ_FIR(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_EQ_FIR(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), - EQ FIR Playback PCM_ID) - -# -# PCM Configuration - -# -PCM_CAPABILITIES(EQ FIR Playback PCM_ID, `S32_LE,S24_LE,S16_LE', - PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, - 2, 16, 192, 16384, 65536, 65536) - -undefine(`MY_CONTROLBYTES') diff --git a/tools/topology/sof/pipe-eq-fir-volume-playback.m4 b/tools/topology/sof/pipe-eq-fir-volume-playback.m4 deleted file mode 100644 index b85e0c3ce30d..000000000000 --- a/tools/topology/sof/pipe-eq-fir-volume-playback.m4 +++ /dev/null @@ -1,102 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`mixercontrol.m4') -include(`bytecontrol.m4') -include(`pipeline.m4') -include(`eq_fir.m4') - -# -# Controls -# -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), - CONTROLMIXER_MAX(, 32), - false, - CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# -# Volume configuration -# - -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(playback_pga_conf, playback_pga_tokens) - -# EQ initial parameters, in this case flat response -include(`eq_fir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQFIR, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - EQFIR_priv) - -# -# Components and Buffers -# - -# Host "Passthrough Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0) - -# "Volume" has 2 source and x sink periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) - -# "EQ 0" has 2 sink period and 2 source periods -W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQFIR")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 - -P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_EQ_FIR(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_EQ_FIR(0))', - `dapm(N_PGA(0), N_BUFFER(1))', - `dapm(N_BUFFER(2), N_PGA(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) - - -# -# PCM Configuration - -# -PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/pipe-eq-iir-capture.m4 b/tools/topology/sof/pipe-eq-iir-capture.m4 deleted file mode 100644 index 6fa515829647..000000000000 --- a/tools/topology/sof/pipe-eq-iir-capture.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# Capture EQ Pipeline and PCM, 48 kHz -# -# Pipeline Endpoints for connection are :- -# -# host PCM_C <-- B0 <--EQ_IIR 0 <-- B1 <-- sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`bytecontrol.m4') -include(`eq_iir.m4') - -# -# Controls -# - -# Use 40 Hz highpass response with 0 dB gain -include(`eq_iir_coef_highpass_40hz_0db_48khz.m4') - -# EQ Bytes control with max value of 255 -define(MY_CONTROLBYTES, concat(`EQIIR_CONTROLBYTES_', PIPELINE_ID)) -C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - CONTROLBYTES_EXTOPS( - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 1024), - , - EQIIR_HP40HZ0dB48K_priv) - -# -# Components and Buffers -# - -# Host "EQ IIR Capture" PCM -# with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, EQ IIR Capture, 0, 2) - -# "EQ 0" has 2 sink period and x source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, LIST(` ', "MY_CONTROLBYTES")) - -# Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_C <-- B0 <--EQ_IIR 0 <-- B1 <-- sink DAI0 - -P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', - `dapm(N_BUFFER(0), N_EQ_IIR(0))', - `dapm(N_EQ_IIR(0), N_BUFFER(1))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), EQ IIR Capture PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(EQ IIR Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, - PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, - 2, 16, 192, 16384, 65536, 65536) - -undefine(`MY_CONTROLBYTES') diff --git a/tools/topology/sof/pipe-eq-iir-playback.m4 b/tools/topology/sof/pipe-eq-iir-playback.m4 deleted file mode 100644 index 4ee35bc5f1cb..000000000000 --- a/tools/topology/sof/pipe-eq-iir-playback.m4 +++ /dev/null @@ -1,82 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`dai.m4') -include(`bytecontrol.m4') -include(`pipeline.m4') -include(`eq_iir.m4') - -# -# Controls -# - -# Use coefficients for flat frequency response -include(`eq_iir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -define(MY_CONTROLBYTES, concat(`EQIIR_CONTROLBYTES_', PIPELINE_ID)) -C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 1024), - , - EQIIR_priv) - -# -# Components and Buffers -# - -# Host "EQ IIR Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, EQ IIR Playback, 2, 0) - -# "EQ 0" has x sink period and 2 source periods -W_EQ_IIR(0, PIPELINE_FORMAT, DAI_PERIODS, 2, LIST(` ', "MY_CONTROLBYTES")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> sink DAI0 - -P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_EQ_IIR(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_EQ_IIR(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), - EQ IIR Playback PCM_ID) - -# -# PCM Configuration - -# -PCM_CAPABILITIES(EQ IIR Playback PCM_ID, `S32_LE,S24_LE,S16_LE', - PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, - 2, 16, 192, 16384, 65536, 65536) - -undefine(`MY_CONTROLBYTES') diff --git a/tools/topology/sof/pipe-eq-iir-volume-playback.m4 b/tools/topology/sof/pipe-eq-iir-volume-playback.m4 deleted file mode 100644 index f433a4bf5dde..000000000000 --- a/tools/topology/sof/pipe-eq-iir-volume-playback.m4 +++ /dev/null @@ -1,102 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`mixercontrol.m4') -include(`bytecontrol.m4') -include(`pipeline.m4') -include(`eq_iir.m4') - -# -# Controls -# -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), - CONTROLMIXER_MAX(, 32), - false, - CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# -# Volume configuration -# - -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(playback_pga_conf, playback_pga_tokens) - -# EQ initial parameters, in this case flat response -include(`eq_iir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQIIR, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - EQIIR_priv) - -# -# Components and Buffers -# - -# Host "Passthrough Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0) - -# "Volume" has 2 source and x sink periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) - -# "EQ 0" has 2 sink period and 2 source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQIIR")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 - -P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_EQ_IIR(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_EQ_IIR(0))', - `dapm(N_PGA(0), N_BUFFER(1))', - `dapm(N_BUFFER(2), N_PGA(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) - - -# -# PCM Configuration - -# -PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/pipe-eq-volume-playback.m4 b/tools/topology/sof/pipe-eq-volume-playback.m4 deleted file mode 100644 index 930c30efc316..000000000000 --- a/tools/topology/sof/pipe-eq-volume-playback.m4 +++ /dev/null @@ -1,123 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> Volume 0 --> B3 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`mixercontrol.m4') -include(`bytecontrol.m4') -include(`pipeline.m4') -include(`eq_iir.m4') -include(`eq_fir.m4') - -# -# Controls -# -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), - CONTROLMIXER_MAX(, 32), - false, - CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - - -# -# Volume configuration -# - -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(playback_pga_conf, playback_pga_tokens) - -# Use coefficients for flat frequency response -include(`eq_iir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQIIR, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - EQIIR_priv) - -# Use coefficients for flat frequency response -include(`eq_fir_coef_flat.m4') - -# EQ Bytes control with max value of 255 -C_CONTROLBYTES(EQFIR, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), - , , , - CONTROLBYTES_MAX(, 4096), - , - EQFIR_priv) - -# -# Components and Buffers -# - -# Host "Passthrough Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0) - -# "Volume" has 2 source and x sink periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) - -# "EQ 0" has 2 sink period and 2 source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQIIR")) - -# "EQ 0" has 2 sink period and 2 source periods -W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "EQFIR")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(2, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> Volume 0 --> B3 --> sink DAI0 - -P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_EQ_IIR(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_EQ_IIR(0))', - `dapm(N_EQ_FIR(0), N_BUFFER(1))', - `dapm(N_BUFFER(2), N_EQ_FIR(0))', - `dapm(N_PGA(0), N_BUFFER(2))', - `dapm(N_BUFFER(3), N_PGA(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(3)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) - -# -# PCM Configuration - -# -PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/pipe-highpass-capture.m4 b/tools/topology/sof/pipe-highpass-capture.m4 deleted file mode 100644 index ecc2a8495911..000000000000 --- a/tools/topology/sof/pipe-highpass-capture.m4 +++ /dev/null @@ -1,123 +0,0 @@ -# IIR highpass filter, volume control, and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQ_IIR <-- B2 <-- source DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`mixercontrol.m4') -include(`pipeline.m4') -include(`bytecontrol.m4') -include(`eq_iir.m4') - -# -# Controls -# -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, - 256 binds the mixer control to volume get/put handlers, - 256, 256), - CONTROLMIXER_MAX(, 80), - false, - CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# -# Volume Configuration -# - -define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) -define(MY_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) -W_VENDORTUPLES(MY_PGA_TOKENS, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "400"')) - -W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) - -# -# IIR configuration -# - -include(`eq_iir_coef_highpass_40hz_0db_48khz.m4') - -# EQ Bytes control with max value of 255 -define(MY_EQIIR_BYTES, concat(`eqiir_bytes_', PIPELINE_ID)) -C_CONTROLBYTES(MY_EQIIR_BYTES, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - CONTROLBYTES_EXTOPS( - 258 binds the mixer control to bytes get/put handlers, - 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - EQIIR_HP40HZ0dB48K_priv) - -# -# Components and Buffers -# - -# Host "Highpass Capture" PCM -# with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2) - -# "Volume" has 2 sink and 2 source periods -W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, MY_PGA_CONF, - LIST(` ', "PIPELINE_ID Master Capture Volume")) - -# "EQ_IIR 0" has 2 sink and x source periods -W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, - LIST(` ', "MY_EQIIR_BYTES")) - -# Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, - COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- EQ_IIR 0 <-- B2 <-- sink DAI0 - -P_GRAPH(pipe-pass-vol-capture-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', - `dapm(N_BUFFER(0), N_PGA(0))', - `dapm(N_PGA(0), N_BUFFER(1))', - `dapm(N_BUFFER(1), N_EQ_IIR(0))', - `dapm(N_EQ_IIR(0), N_BUFFER(2))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(Highpass Capture PCM_ID, `S32_LE,S24_LE,S16_LE', - PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, - 2, 16, 192, 16384, 65536, 65536) - -undefine(`MY_PGA_TOKENS') -undefine(`MY_PGA_CONF') -undefine(`MY_EQIIR_BYTES') diff --git a/tools/topology/sof/pipe-passthrough-capture.m4 b/tools/topology/sof/pipe-passthrough-capture.m4 deleted file mode 100644 index 0bbe422605bb..000000000000 --- a/tools/topology/sof/pipe-passthrough-capture.m4 +++ /dev/null @@ -1,46 +0,0 @@ -# Capture Passthrough Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_C <-- B0 <-- sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`dai.m4') -include(`pipeline.m4') - -# -# Components and Buffers -# - -# Host "Passthrough Capture" PCM -# with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, DAI_PERIODS) - -# Capture Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_PASS_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_C <-- B0 <-- sink DAI0 - -P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_PCMC(PCM_ID), N_BUFFER(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(Passthrough Capture PCM_ID, COMP_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-passthrough-playback.m4 b/tools/topology/sof/pipe-passthrough-playback.m4 deleted file mode 100644 index 72f785ab9d55..000000000000 --- a/tools/topology/sof/pipe-passthrough-playback.m4 +++ /dev/null @@ -1,46 +0,0 @@ -# Low Latency Passthrough Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`dai.m4') -include(`pipeline.m4') - -# -# Components and Buffers -# - -# Host "Passthrough Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_PASS_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --> B0 --> sink DAI0 - -P_GRAPH(pipe-pass-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(0)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(Passthrough Playback PCM_ID, COMP_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-src-volume-playback.m4 b/tools/topology/sof/pipe-src-volume-playback.m4 deleted file mode 100644 index 6d4d0bf691ee..000000000000 --- a/tools/topology/sof/pipe-src-volume-playback.m4 +++ /dev/null @@ -1,97 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> SRC --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`src.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`mixercontrol.m4') -include(`pipeline.m4') - -# -# Controls -# -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), - CONTROLMIXER_MAX(, 32), - false, - CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# -# Components and Buffers -# - -# Host "SRC Playback" PCM -# with 3 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, SRC Playback, 3, 0) - -# -# SRC Configuration -# - -W_VENDORTUPLES(media_src_tokens, sof_src_tokens, LIST(` ', `SOF_TKN_SRC_RATE_OUT "PIPELINE_RATE"')) - -W_DATA(media_src_conf, media_src_tokens) - -# "SRC" has 3 source and 3 sink periods -W_SRC(0, PIPELINE_FORMAT, 3, 3, media_src_conf) - -# -# Volume Configuration -# - -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - - -W_DATA(playback_pga_conf, playback_pga_tokens) - -# "Volume" has 3 source and x sink periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 3, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(3, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(3, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --> B0 --> SRC 0 --> B1 Volume 0 --> B2 --> sink DAI0 - -P_GRAPH(pipe-pass-src-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_SRC(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_SRC(0))', - `dapm(N_PGA(0), N_BUFFER(1))', - `dapm(N_BUFFER(2), N_PGA(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), SRC Playback PCM_ID) - -# -# PCM Configuration -# - -PCM_CAPABILITIES(SRC Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 8000, 192000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/pipe-volume-demux-playback.m4 b/tools/topology/sof/pipe-volume-demux-playback.m4 deleted file mode 100644 index 5b3ae308ed8f..000000000000 --- a/tools/topology/sof/pipe-volume-demux-playback.m4 +++ /dev/null @@ -1,107 +0,0 @@ -# Demux Volume Pipeline -# -# Low Latency Playback with demux and volume. -# -# Pipeline Endpoints for connection are :- -# -# Playback Demux -# B2 (DAI buffer) -# -# -# host PCM_P -- B0 --> Demux(M) -- B1 --> volume -- B2 --> sink DAI0 -# | -# pipeline n+1 --> DAI -# - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`muxdemux.m4') -include(`mixercontrol.m4') -include(`bytecontrol.m4') - -# Use default parameters -include(`demux_coef_default.m4') - -# demux Bytes control with max value of 255 -C_CONTROLBYTES(DEMUX, PIPELINE_ID, - CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), - CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), - , , , - CONTROLBYTES_MAX(, 304), - , - DEMUX_priv) - -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), - CONTROLMIXER_MAX(, 32), - false, - CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# -# Volume configuration -# - -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(playback_pga_conf, playback_pga_tokens) - -# -# Components and Buffers -# - -# Host "Low latency Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0) - -# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong -W_PGA(1, PIPELINE_FORMAT, DAI_PERIODS, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) - -# Mux 0 has 2 sink and source periods. -W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, LIST(` ', "DEMUX")) - -# Low Latency Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_COMP_MEM_CAP) -W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_COMP_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --B0--> Demux --B1--> volume ---B2--> sink DAI0 - -P_GRAPH(pipe-ll-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_MUXDEMUX(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_MUXDEMUX(0))', - `dapm(N_PGA(1), N_BUFFER(1))', - `dapm(N_BUFFER(2), N_PGA(1))')) -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) -indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID) - -# -# PCM Configuration -# - - -# PCM capabilities supported by FW -PCM_CAPABILITIES(Low Latency Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/pipe-volume-playback.m4 b/tools/topology/sof/pipe-volume-playback.m4 deleted file mode 100644 index 6bc2805cb808..000000000000 --- a/tools/topology/sof/pipe-volume-playback.m4 +++ /dev/null @@ -1,81 +0,0 @@ -# Low Latency Passthrough with volume Pipeline and PCM -# -# Pipeline Endpoints for connection are :- -# -# host PCM_P --> B0 --> Volume 0 --> B1 --> sink DAI0 - -# Include topology builder -include(`utils.m4') -include(`buffer.m4') -include(`pcm.m4') -include(`pga.m4') -include(`dai.m4') -include(`mixercontrol.m4') -include(`pipeline.m4') - -# -# Controls -# -# Volume Mixer control with max value of 32 -C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, - CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), - CONTROLMIXER_MAX(, 32), - false, - CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), - Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) - -# -# Volume configuration -# - -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) - -W_DATA(playback_pga_conf, playback_pga_tokens) - -# -# Components and Buffers -# - -# Host "Passthrough Playback" PCM -# with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0) - - -# "Volume" has 2 source and x sink periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) - -# Playback Buffers -W_BUFFER(0, COMP_BUFFER_SIZE(2, - COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_HOST_MEM_CAP) -W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, - COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), - PLATFORM_DAI_MEM_CAP) - -# -# Pipeline Graph -# -# host PCM_P --> B0 --> Volume 0 --> B1 --> sink DAI0 - -P_GRAPH(pipe-pass-vol-playback-PIPELINE_ID, PIPELINE_ID, - LIST(` ', - `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', - `dapm(N_PGA(0), N_BUFFER(0))', - `dapm(N_BUFFER(1), N_PGA(0))')) - -# -# Pipeline Source and Sinks -# -indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) -indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) - - -# -# PCM Configuration - -# -PCM_CAPABILITIES(Passthrough Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) - diff --git a/tools/topology/sof/tokens.m4 b/tools/topology/sof/tokens.m4 deleted file mode 100644 index 68e5496bf918..000000000000 --- a/tools/topology/sof/tokens.m4 +++ /dev/null @@ -1,119 +0,0 @@ - -# -# SOF Tokens for differentiation. -# -# Differentiation can be done at the platform and machine level. -# -# Tokens are GUIDs - -# TODO: pre-process this with UAPI headers GNU cpp. - - -SectionVendorTokens."sof_buffer_tokens" { - SOF_TKN_BUF_SIZE "100" - SOF_TKN_BUF_CAPS "101" -} - -SectionVendorTokens."sof_dai_tokens" { -# Token retired with ABI 3.2, do not use for new capabilities -# SOF_TKN_DAI_DMAC_CONFIG "153" - SOF_TKN_DAI_TYPE "154" - SOF_TKN_DAI_INDEX "155" - SOF_TKN_DAI_DIRECTION "156" -} - -SectionVendorTokens."sof_sched_tokens" { - SOF_TKN_SCHED_PERIOD "200" - SOF_TKN_SCHED_PRIORITY "201" - SOF_TKN_SCHED_MIPS "202" - SOF_TKN_SCHED_CORE "203" - SOF_TKN_SCHED_FRAMES "204" - SOF_TKN_SCHED_TIME_DOMAIN "205" -} - -SectionVendorTokens."sof_volume_tokens" { - SOF_TKN_VOLUME_RAMP_STEP_TYPE "250" - SOF_TKN_VOLUME_RAMP_STEP_MS "251" -} - -SectionVendorTokens."sof_src_tokens" { - SOF_TKN_SRC_RATE_IN "300" - SOF_TKN_SRC_RATE_OUT "301" -} - -SectionVendorTokens."sof_asrc_tokens" { - SOF_TKN_ASRC_RATE_IN "320" - SOF_TKN_ASRC_RATE_OUT "321" - SOF_TKN_ASRC_ASYNCHRONOUS_MODE "322" - SOF_TKN_ASRC_OPERATION_MODE "323" -} - -SectionVendorTokens."sof_pcm_tokens" { - SOF_TKN_PCM_DMAC_CONFIG "353" -} - -SectionVendorTokens."sof_comp_tokens" { - SOF_TKN_COMP_PERIOD_SINK_COUNT "400" - SOF_TKN_COMP_PERIOD_SOURCE_COUNT "401" - SOF_TKN_COMP_FORMAT "402" -# Token retired with ABI 3.2, do not use for new capabilities -# SOF_TKN_COMP_PRELOAD_COUNT "403" -} - -SectionVendorTokens."sof_ssp_tokens" { - SOF_TKN_INTEL_SSP_CLKS_CONTROL "500" - SOF_TKN_INTEL_SSP_MCLK_ID "501" - SOF_TKN_INTEL_SSP_SAMPLE_BITS "502" - SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH "503" - SOF_TKN_INTEL_SSP_QUIRKS "504" - SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT "505" - SOF_TKN_INTEL_SSP_BCLK_DELAY "506" -} - -SectionVendorTokens."sof_dmic_tokens" { - SOF_TKN_INTEL_DMIC_DRIVER_VERSION "600" - SOF_TKN_INTEL_DMIC_CLK_MIN "601" - SOF_TKN_INTEL_DMIC_CLK_MAX "602" - SOF_TKN_INTEL_DMIC_DUTY_MIN "603" - SOF_TKN_INTEL_DMIC_DUTY_MAX "604" - SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE "605" - SOF_TKN_INTEL_DMIC_SAMPLE_RATE "608" - SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH "609" - SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS "610" -} - -SectionVendorTokens."sof_dmic_pdm_tokens" { - SOF_TKN_INTEL_DMIC_PDM_CTRL_ID "700" - SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable "701" - SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable "702" - SOF_TKN_INTEL_DMIC_PDM_POLARITY_A "703" - SOF_TKN_INTEL_DMIC_PDM_POLARITY_B "704" - SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE "705" - SOF_TKN_INTEL_DMIC_PDM_SKEW "706" -} - -SectionVendorTokens."sof_tone_tokens" { - SOF_TKN_TONE_SAMPLE_RATE "800" -} - -SectionVendorTokens."sof_process_tokens" { - SOF_TKN_PROCESS_TYPE "900" -} - -SectionVendorTokens."sof_sai_tokens" { - SOF_TKN_IMX_SAI_MCLK_ID "1000" -} - -SectionVendorTokens."sof_esai_tokens" { - SOF_TKN_IMX_ESAI_MCLK_ID "1100" -} - -SectionVendorTokens."sof_stream_tokens" { - SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3 "1200" - SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 "1201" -} - -SectionVendorTokens."sof_led_tokens" { - SOF_TKN_MUTE_LED_USE "1300" - SOF_TKN_MUTE_LED_DIRECTION "1301" -} diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt new file mode 100644 index 000000000000..c6ae06d0be04 --- /dev/null +++ b/tools/topology/topology1/CMakeLists.txt @@ -0,0 +1,183 @@ +# SPDX-License-Identifier: BSD-3-Clause + +file(GLOB TPLG_DEPS + platform/common/*.m4 + common/*.m4 + m4/*.m4 + sof/*.m4 +) + +add_custom_target(abi_v1 + DEPENDS abi.h +) +add_custom_command(OUTPUT abi.h + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/get_abi.sh ${SOF_ROOT_SOURCE_DIRECTORY} + DEPENDS ${TPLG_DEPS} ${SOF_ROOT_SOURCE_DIRECTORY}/src/include/kernel/abi.h + # get_abi.h generates (a smaller) abi.h in the current directory + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + VERBATIM + USES_TERMINAL +) + +set(TPLGS + ## i.MX8 (i.MX8QM and i.MX8QXP) topologies + "sof-imx8-nocodec\;sof-imx8-nocodec" + "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\;-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\;-DCODEC=wm8960\;-DSAI_INDEX=1" + "sof-imx8-compr-wm8960-mixer\;sof-imx8-compr-wm8962-mixer\;-DCODEC=wm8962\;-DSAI_INDEX=1" + "sof-imx8-wm8960-kwd\;sof-imx8-wm8960-kwd" + "sof-imx8-cs42888-mixer\;sof-imx8-cs42888-mixer" + "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" + "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-pcm-wm8960\;sof-imx8-compr-pcm-wm8960" + "sof-imx8-compr-pcm-cap-wm8960\;sof-imx8-compr-pcm-cap-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-compr-wm8960-mixer\;sof-imx8mp-compr-wm8960-mixer\;-DCODEC=wm8960\;-DSAI_INDEX=3" + "sof-imx8-compr-wm8960-mixer\;sof-imx8mp-compr-wm8962-mixer\;-DCODEC=wm8962\;-DSAI_INDEX=3" + "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-micfil\;sof-imx8mp-micfil" + "sof-imx8mp-btsco-dual-8ch\;sof-imx8mp-btsco-dual-8ch" + "sof-imx8-wm8960\;sof-imx8mp-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-eap-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eap\;-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-gui-components-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=gui-components\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-drc-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=drc\;-DSAI_INDEX=3" + "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 + + ## i.MX8ULP topologies + "sof-imx8ulp-btsco\;sof-imx8ulp-btsco\;-DFSYNC_RATE=8000" + "sof-imx8ulp-btsco\;sof-imx8ulp-btsco-16k\;-DFSYNC_RATE=16000" + "sof-imx8ulp-9x9-btsco\;sof-imx8ulp-9x9-btsco\;-DFSYNC_RATE=8000" + "sof-imx8ulp-9x9-btsco\;sof-imx8ulp-9x9-btsco-16k\;-DFSYNC_RATE=16000" + ## end i.MX8ULP topologies + + ## i.MX93 topologies + "sof-imx93-wm8962\;sof-imx93-wm8962\;-DPPROC=volume" + ## end i.MX93 topologies + + ## i.MX95 topologies + "sof-imx95-wm8962\;sof-imx95-wm8962\;-DPPROC=volume" + "sof-imx95-wm8962\;sof-imx95-passthrough-wm8962\;-DPPROC=passthrough" + ## end i.MX95 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" + "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682-rtnr\;-DCHANNELS=2\;-DRTNR" + "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682-google-aec-rtnr\;-DGOOGLE_RTC_AUDIO_PROCESSING\;-DCHANNELS=2\;-DRTNR" + "sof-mt8186-mt6366\;sof-mt8186" + "sof-mt8186-mt6366\;sof-mt8186-dts\;-DDTS=`DTS'" + "sof-mt8186-mt6366\;sof-mt8186-mt6366-rt1019-rt5682s-waves\;-DWAVES=1" + "sof-mt8188-mt6359\;sof-mt8188" + "sof-mt8188-mt6359\;sof-mt8188-waves\;-DWAVES=1" + "sof-mt8196-mt6681\;sof-mt8196" + "sof-mt8196-mt6681\;sof-mt8196-waves\;-DWAVES=1" + "sof-mt8196-mt6681\;sof-mt8196-dts\;-DDTS=`DTS'" + "sof-mt8196-mt6681\;sof-mt8196-google-ctc\;-DGOOGLE_CTC=1" + "sof-mt8196-mt6681\;sof-mt8196-waves-google-ctc\;-DWAVES=1\;-DGOOGLE_CTC=1" + "sof-mt8365-mt6357\;sof-mt8365" + "sof-mt8365-mt6357\;sof-mt8365-waves\;-DWAVES=1" + + "sof-acp-renoir\;sof-acp" + "sof-rn-rt5682-rt1019\;sof-rn-rt5682-rt1019" + "sof-rn-rt5682-rt1019\;sof-rn-rt5682-rt1019-dts\;-DDTS=`DTS'" + "sof-rn-rt5682-max98360\;sof-rn-rt5682-max98360" + "sof-acp-vangogh\;sof-vangogh-nau8821-max" + "sof-acp-rmb\;sof-acp-rmb" + "sof-acp-rmb-dmic4ch\;sof-acp-rmb-dmic4ch" + "sof-acp-rmb-tdm8ch-dmic4ch-rt5682-rt1019\;sof-acp-rmb-tdm8ch-dmic4ch-rt5682-rt1019" + "sof-acp-rmb-tdm8ch-dmic2ch-nau8825-max98360\;sof-acp-rmb-tdm8ch-dmic2ch-nau8825-max98360" + "sof-acp-rmb\;sof-rmb-rt5682s-rt1019" + "sof-acp-rmb\;sof-rmb-nau8825-max98360" + "sof-acp_6_3\;sof-acp_6_3" + "sof-acp_6_3_sdw\;sof-acp_6_3-rt711-l0-rt1316-l0-rt714-l1" + "sof-acp_7_0\;sof-acp_7_0" + "sof-acp_7_0_sdw\;sof-acp_7_0-rt722-l0" +) + +# This empty 'production/' source subdirectory exists only to create the +# corresponding 'production/' subdirectory in the build directory and +# solve race https://github.com/thesofproject/sof/issues/5067 without +# the disruption of actually moving all *.m4 sources one directory level +# down. +add_subdirectory(production) + +# "Install" all v1 production topologies two directory levels up. +add_custom_target(topologies1 ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory production ${SOF_TOPOLOGY_BINARY_DIRECTORY} +) + +foreach(tplg ${TPLGS}) + list(GET tplg 0 input) + list(GET tplg 1 output) + list(LENGTH tplg tplg_len) + math(EXPR num_args "${tplg_len} - 1") + set(DEFINES "") + if (${num_args} GREATER 1) + foreach(index RANGE 2 ${num_args}) + list(GET tplg ${index} custom_define) + list(APPEND DEFINES ${custom_define}) + endforeach() + endif() + + # m4 + # TODO: reduce duplication with subdirectories + add_custom_command( + OUTPUT production/${output}.conf + COMMAND m4 --fatal-warnings + ${DEFINES} + -I ${CMAKE_CURRENT_SOURCE_DIR}/m4 + -I ${CMAKE_CURRENT_SOURCE_DIR}/common + -I ${CMAKE_CURRENT_SOURCE_DIR}/platform/common + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/common/abi.m4 + ${CMAKE_CURRENT_SOURCE_DIR}/${input}.m4 + > production/${output}.conf + MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${input}.m4 + # The 'abi.h' file is the real dependency that triggers + # a rebuild. 'abi_v1' is the target that avoids a race + # to rebuild abi.h. See the CMake FAQ or (better) Sam + # Thursfield's blog about custom targets. + DEPENDS abi_v1 ${CMAKE_CURRENT_BINARY_DIR}/abi.h + VERBATIM + USES_TERMINAL + ) + + # alsatplg + add_alsatplg_command(production/${output}.conf production/${output}.tplg) + + add_custom_target(topology1_${output} DEPENDS production/${output}.tplg) + add_dependencies(topologies1 topology1_${output}) +endforeach() + +add_subdirectory(development) diff --git a/tools/topology/topology1/README.md b/tools/topology/topology1/README.md new file mode 100644 index 000000000000..78253bb06ee2 --- /dev/null +++ b/tools/topology/topology1/README.md @@ -0,0 +1,86 @@ +# ALSA Topology v1 (`tools/topology/topology1`) + +This directory contains the source files and `m4` macros used to generate version 1 of the ALSA topology binary files (`.tplg`) for Sound Open Firmware. + +## Overview + +Topology v1 relies heavily on the `m4` macro processor to handle the complexity and reusability of DSP graph definitions. Because raw ALSA configuration files for complex audio routing can become extremely verbose and repetitive, SOF uses `m4` to define logical blocks (like DAIs, SSPs, pipelines, and volume controls) that can be easily instantiated and connected. + +## Structure + +The core generation components include: + +- **`m4/`**: This directory contains the foundational macro definitions. These macros define how base elements like widgets (e.g., `PGA`, `Mixer`, `SRC`), pipelines, and routing paths are constructed in the ALSA `.conf` format. +- **`common/`**: Contains shared components and standard pipeline definitions that are reused across multiple different hardware platforms. +- **`platform/`**: Contains macros and configurations specific to individual hardware architectures (e.g., Intel cAVS, IMX). +- **Platform `.m4` files**: At the root of `topology1`, there are numerous `.m4` files (e.g., `sof-cavs-nocodec.m4`, `sof-imx8-wm8960.m4`). These are the top-level files that instantiate the macros to build a complete topology graph for a specific board or hardware configuration. + +## Component Assembly + +Building a topology in v1 is essentially a process of calling nested `m4` macros to piece together the DSP pipeline. Here's how the ingredients combine: + +1. **Base Macros (`m4/`)**: Define the raw ALSA syntax for things like a single PGA volume control or a DAI link. +2. **Pipelines (`common/`)**: Define a logical sequence of base widgets. For example, a "Playback Pipeline" macro might chain together a Host PCM, a Buffer, a Volume Control (PGA), and an output Buffer. +3. **Top-Level File (`*.m4`)**: Instantiates the pipelines, defines the physical DAI hardware connections, and sets up routing lines between the pipelines and the DAIs. + +```mermaid +graph TD + subgraph "Base Ingredients (m4/)" + A[Widget: PCM] + B[Widget: PGA Volume] + C[Widget: DAI] + D[Widget: Mixer] + end + + subgraph "Recipes (common/ & platform/)" + P1[Playback Pipeline] + P1 -.->|Includes| A + P1 -.->|Includes| B + + P2[Capture Pipeline] + P2 -.->|Includes| D + P2 -.->|Includes| C + end + + subgraph "The Meal (sof-board.m4)" + Top[Top-Level Topology] + Top ==>|Instantiates| P1 + Top ==>|Instantiates| P2 + Top ==>|Defines| Routes[Audio Routes] + Routes -.->|Connects Pipeline to DAI| Top + end +``` + +## Build Flow + +### Architecture Diagram + +```mermaid +flowchart TD + m4_core(["m4/ (Core Macros)"]) -.-> m4_plat(["platform/ (Platform Macros)"]) + m4_comp(["common/ (Shared Components)"]) -.-> m4_plat + + m4_plat -.-> m4_top(["sof-*.m4 (Top-level Platform File)"]) + + m4_top -->|"m4 processor"| conf["ALSA .conf Output"] + + conf -->|"alsatplg"| tplg["ALSA .tplg Binary"] +``` + +When the SOF build system compiles a v1 topology: + +1. The `m4` processor takes a top-level platform `.m4` file. +2. It expands all the macros defined in `m4/`, `common/`, and `platform/`. +3. The output is a raw ALSA `.conf` text file. +4. The `alsatplg` compiler parses this `.conf` file and compiles it into the final `.tplg` binary format loaded by the kernel. + +### Build Instructions + +Topologies are built automatically as part of the standard SOF CMake build process. To explicitly build all topologies (including v1): + +```bash +# From your build directory: +make topologies1 +# OR +cmake --build . --target topologies1 +``` diff --git a/tools/topology/common/abi.m4 b/tools/topology/topology1/common/abi.m4 similarity index 100% rename from tools/topology/common/abi.m4 rename to tools/topology/topology1/common/abi.m4 diff --git a/tools/topology/common/memory.m4 b/tools/topology/topology1/common/memory.m4 similarity index 100% rename from tools/topology/common/memory.m4 rename to tools/topology/topology1/common/memory.m4 diff --git a/tools/topology/common/tlv.m4 b/tools/topology/topology1/common/tlv.m4 similarity index 100% rename from tools/topology/common/tlv.m4 rename to tools/topology/topology1/common/tlv.m4 diff --git a/tools/topology/topology1/development/CMakeLists.txt b/tools/topology/topology1/development/CMakeLists.txt new file mode 100644 index 000000000000..b3bbb5c72317 --- /dev/null +++ b/tools/topology/topology1/development/CMakeLists.txt @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: BSD-3-Clause + +set(TPLGS +) + + +add_custom_target(dev_topologies1 ALL) + +foreach(tplg ${TPLGS}) + list(GET tplg 0 input) + list(GET tplg 1 output) + list(LENGTH tplg tplg_len) + math(EXPR num_args "${tplg_len} - 1") + set(DEFINES "") + if (${num_args} GREATER 1) + foreach(index RANGE 2 ${num_args}) + list(GET tplg ${index} custom_define) + list(APPEND DEFINES ${custom_define}) + endforeach() + endif() + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${output}.conf + COMMAND m4 --fatal-warnings + ${DEFINES} + -I ${CMAKE_CURRENT_SOURCE_DIR}/../m4 + -I ${CMAKE_CURRENT_SOURCE_DIR}/../common + -I ${CMAKE_CURRENT_SOURCE_DIR}/../platform/common + -I ${CMAKE_CURRENT_SOURCE_DIR}/../ + -I ${CMAKE_CURRENT_BINARY_DIR}/../ + ${CMAKE_CURRENT_SOURCE_DIR}/../common/abi.m4 + ${CMAKE_CURRENT_SOURCE_DIR}/${input}.m4 + > ${output}.conf + DEPENDS abi_v1 ${CMAKE_BINARY_DIR}/topology/topology1/abi.h + VERBATIM + USES_TERMINAL + ) + + add_alsatplg_command(${output}.conf ${output}.tplg) + + add_custom_target(dev_topology_${output} DEPENDS ${output}.tplg) + add_dependencies(dev_topologies1 dev_topology_${output}) +endforeach() diff --git a/tools/topology/topology1/get_abi.sh b/tools/topology/topology1/get_abi.sh new file mode 100755 index 000000000000..424336761a4a --- /dev/null +++ b/tools/topology/topology1/get_abi.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2019 Intel Corporation. All rights reserved. + + +set -e + +MAJOR=`grep '#define SOF_ABI_MAJOR ' $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` +MINOR=`grep '#define SOF_ABI_MINOR ' $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` +PATCH=`grep '#define SOF_ABI_PATCH ' $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` +MAJOR_SHIFT=`grep '#define SOF_ABI_MAJOR_SHIFT'\ + $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` +MINOR_SHIFT=`grep '#define SOF_ABI_MINOR_SHIFT'\ + $1/src/include/kernel/abi.h | grep -E ".[[:digit:]]$" -o` + +major_val=$(($MAJOR << $MAJOR_SHIFT)) +minor_val=$(($MINOR << $MINOR_SHIFT)) +abi_version_3_8=$((3<<$MAJOR_SHIFT | 8<<$MINOR_SHIFT)) +abi_version=$(($major_val | $minor_val)) +abi_version_3_9_or_greater=$(($abi_version > $abi_version_3_8)) +abi_version_3_17=$((3<<$MAJOR_SHIFT | 17<<$MINOR_SHIFT)) +abi_version_3_17_or_greater=$(($abi_version >= $abi_version_3_17)) + +printf "define(\`SOF_ABI_MAJOR', \`0x%02x')\n" $MAJOR > abi.h +printf "define(\`SOF_ABI_MINOR', \`0x%02x')\n" $MINOR >> abi.h +printf "define(\`SOF_ABI_PATCH', \`0x%02x')\n" $PATCH >> abi.h +printf "define(\`SOF_ABI_VERSION', \`0x%x')\n" $abi_version >> abi.h +printf "define(\`SOF_ABI_VERSION_3_9_OR_GRT', \`%d')\n"\ + $abi_version_3_9_or_greater >> abi.h +printf "define(\`SOF_ABI_VERSION_3_17_OR_GRT', \`%d')\n"\ + $abi_version_3_17_or_greater >> abi.h diff --git a/tools/topology/topology1/m4/asrc.m4 b/tools/topology/topology1/m4/asrc.m4 new file mode 100644 index 000000000000..a25c327f60c4 --- /dev/null +++ b/tools/topology/topology1/m4/asrc.m4 @@ -0,0 +1,52 @@ +divert(-1) + +dnl Defines the macro for ASRC widget +DECLARE_SOF_RT_UUID("asrc", asrc_uuid, 0xc8ec72f6, 0x8526, 0x4faf, + 0x9d, 0x39, 0xa2, 0x3d, 0x0b, 0x54, 0x1d, 0xe2) + +dnl ASRC name) +define(`N_ASRC', `ASRC'PIPELINE_ID`.'$1) + +dnl W_ASRC(name, format, periods_sink, periods_source, data) +define(`W_ASRC', +`SectionVendorTuples."'N_ASRC($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(asrc_uuid) +` }' +`}' +`SectionData."'N_ASRC($1)`_data_uuid" {' +` tuples "'N_ASRC($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_ASRC($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` }' +`}' +`SectionData."'N_ASRC($1)`_data_w" {' +` tuples "'N_ASRC($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_ASRC($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_ASRC($1)`_data_str" {' +` tuples "'N_ASRC($1)`_tuples_str"' +`}' +`SectionWidget."'N_ASRC($1)`" {' +` index "'PIPELINE_ID`"' +` type "asrc"' +` no_pm "true"' +` data [' +` "'N_ASRC($1)`_data_uuid"' +` "'N_ASRC($1)`_data_w"' +` "'N_ASRC($1)`_data_str"' +` "'$5`"' +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/buffer.m4 b/tools/topology/topology1/m4/buffer.m4 new file mode 100644 index 000000000000..29a6b5f084a5 --- /dev/null +++ b/tools/topology/topology1/m4/buffer.m4 @@ -0,0 +1,54 @@ +divert(-1) + +dnl Define the macro for buffer widget + +dnl N_BUFFER(name) +define(`N_BUFFER', `BUF'PIPELINE_ID`.'$1) + +dnl W_BUFFER(name, size, capabilities, [core], [flags]) +define(`W_BUFFER', +`SectionVendorTuples."'N_BUFFER($1)`_tuples" {' +` tokens "sof_buffer_tokens"' +` tuples."word" {' +` SOF_TKN_BUF_SIZE' STR($2) +` SOF_TKN_BUF_CAPS' STR($3) +`ifelse(`$#', `5', +` SOF_TKN_BUF_FLAGS' STR($5) +,` ')' +` }' +`}' +`SectionData."'N_BUFFER($1)`_data" {' +` tuples "'N_BUFFER($1)`_tuples"' +`}' +`ifelse(`$#', `4', +`SectionVendorTuples."'N_BUFFER($1)`_comp_tuples" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_CORE_ID' 0 +` }' +`}' +`SectionData."'N_BUFFER($1)`_comp" {' +` tuples "'N_BUFFER($1)`_comp_tuples"' +`}' +,` ')' +`SectionWidget."'N_BUFFER($1)`" {' +` index "'PIPELINE_ID`"' +` type "buffer"' +` no_pm "true"' +` data [' +` "'N_BUFFER($1)`_data"' +`ifelse(`$#', `4', +` "'N_BUFFER($1)`_comp"' +,` ')' +` ]' +`}') + +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) +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/m4/bytecontrol.m4 b/tools/topology/topology1/m4/bytecontrol.m4 new file mode 100644 index 000000000000..56014f19b8bb --- /dev/null +++ b/tools/topology/topology1/m4/bytecontrol.m4 @@ -0,0 +1,193 @@ +divert(-1) + +# don't care value +define(`XX', 0x00) + +dnl Define macro for byte control + +dnl CONTROLBYTES_MAX(comment, value) +define(`CONTROLBYTES_MAX', +`#$1' +` max STR($2)') + +dnl CONTROLBYTES_TLV(comment, value) +define(`CONTROLBYTES_TLV', +`#$1' +` tlv STR($2)') + +dnl CONTROLBYTES_OPS(info, comment, get, put) +define(`CONTROLBYTES_OPS', +`ops."ctl" {' +` info STR($1)' +` #$2' +` }') + +dnl CONTROLBYTES_OPS(info, comment, get, put) +define(`CONTROLBYTES_EXTOPS', +`extops."extctl" {' +` #$1' +` get STR($2)' +` put STR($3)' +` }') + +# Readonly byte control to read the actual value from DSP +dnl CONTROLBYTES_EXTOPS_READONLY(info, comment, get) +define(`CONTROLBYTES_EXTOPS_READONLY', +`extops."extctl" {' +` #$1' +` get STR($2)' +` }') + +# Writeonly byte control +dnl CONTROLBYTES_EXTOPS_WRITEONLY(info, comment, put) +define(`CONTROLBYTES_EXTOPS_WRITEONLY', +`extops."extctl" {' +` #$1' +` put STR($2)' +` }') + +define(`CONTROLBYTES_PRIV', +`SectionData.STR($1) {' +` $2' +`}') + +dnl C_CONTROLBYTES(name, index, ops, base, num_regs, mask, max, tlv, priv) +define(`C_CONTROLBYTES', +`SectionControlBytes.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $3' +` # control uses bespoke driver get/put/info ID for ext ops' +` $4' +`' +` # default base/num_regs/mask to avoid NULL STR' +` ifelse($5, `', base STR(XX), base STR($5))' +` ifelse($6, `', num_regs STR(XX), num_regs STR($6)`')' +` ifelse($7, `', mask STR(XX), mask STR($7)`')' +` $8' +` $9' +` access [' +` tlv_write' +` tlv_read' +` tlv_callback' +` ]' +` data [' +` $10' +` ]' +`}') + +dnl C_CONTROLBYTES_READONLY(name, index, ops, base, num_regs, mask, max, tlv, priv) +define(`C_CONTROLBYTES_READONLY', +`SectionControlBytes.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $3' +` # control uses bespoke driver get/put/info ID for ext ops' +` $4' +`' +` # default base/num_regs/mask to avoid NULL STR' +` ifelse($5, `', base STR(XX), base STR($5))' +` ifelse($6, `', num_regs STR(XX), num_regs STR($6)`')' +` ifelse($7, `', mask STR(XX), mask STR($7)`')' +` $8' +` $9' +` access [' +` tlv_read' +` tlv_callback' +` ]' +` data [' +` $10' +` ]' +`}') + +# Readonly byte control to read the actual value from DSP +dnl C_CONTROLBYTES_VOLATILE_READONLY(name, index, ops, base, num_regs, mask, max, tlv, priv) +define(`C_CONTROLBYTES_VOLATILE_READONLY', +`SectionControlBytes.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $3' +` # control uses bespoke driver get/put/info ID for ext ops' +` $4' +`' +` ifelse($5, `', base STR(XX), base STR($5))' +` ifelse($6, `', num_regs STR(XX), num_regs STR($6)`')' +` ifelse($7, `', mask STR(XX), mask STR($7)`')' +` $8' +` $9' +` access [' +` tlv_read' +` tlv_callback' +` volatile' +` ]' +` data [' +` $10' +` ]' +`}') + +# Writeonly byte control +dnl C_CONTROLBYTES_WRITEONLY(name, index, ops, base, num_regs, mask, max, tlv, priv) +define(`C_CONTROLBYTES_WRITEONLY', +`SectionControlBytes.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $3' +` # control uses bespoke driver get/put/info ID for ext ops' +` $4' +`' +` ifelse($5, `', base STR(XX), base STR($5))' +` ifelse($6, `', num_regs STR(XX), num_regs STR($6)`')' +` ifelse($7, `', mask STR(XX), mask STR($7)`')' +` $8' +` $9' +` access [' +` tlv_write' +` tlv_callback' +` ]' +` data [' +` $10' +` ]' +`}') + +# Read-write volatile byte control +dnl C_CONTROLBYTES_VOLATILE_RW(name, index, ops, base, num_regs, mask, max, tlv, priv) +define(`C_CONTROLBYTES_VOLATILE_RW', +`SectionControlBytes.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $3' +` # control uses bespoke driver get/put/info ID for ext ops' +` $4' +`' +` ifelse($5, `', base STR(XX), base STR($5))' +` ifelse($6, `', num_regs STR(XX), num_regs STR($6)`')' +` ifelse($7, `', mask STR(XX), mask STR($7)`')' +` $8' +` $9' +` access [' +` tlv_read' +` tlv_write' +` tlv_callback' +` volatile' +` ]' +` data [' +` $10' +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/ch_sel.m4 b/tools/topology/topology1/m4/ch_sel.m4 new file mode 100644 index 000000000000..e34ee8e9217b --- /dev/null +++ b/tools/topology/topology1/m4/ch_sel.m4 @@ -0,0 +1,62 @@ +divert(-1) + +dnl Define macro for channel selector widget +DECLARE_SOF_RT_UUID("selector", selector_uuid, 0x55a88ed5, 0x3d18, 0x46ca, + 0x88, 0xf1, 0x0e, 0xe6, 0xea, 0xe9, 0x93, 0x0f) + +dnl N_SELECTOR(name) +define(`N_SELECTOR', `SELECTOR'PIPELINE_ID`.'$1) + +dnl W_SELECTOR(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_SELECTOR', +`SectionVendorTuples."'N_SELECTOR($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(selector_uuid) +` }' +`}' +`SectionData."'N_SELECTOR($1)`_data_uuid" {' +` tuples "'N_SELECTOR($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_SELECTOR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_SELECTOR($1)`_data_w" {' +` tuples "'N_SELECTOR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_SELECTOR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionVendorTuples."'N_SELECTOR($1)`_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "CHAN_SELECTOR" +` }' +`}' +`SectionData."'N_SELECTOR($1)`_data_str" {' +` tuples "'N_SELECTOR($1)`_tuples_str"' +` tuples "'N_SELECTOR($1)`_process_tuples_str"' +`}' +`SectionWidget."'N_SELECTOR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_SELECTOR($1)`_data_uuid"' +` "'N_SELECTOR($1)`_data_w"' +` "'N_SELECTOR($1)`_data_str"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/codec_adapter.m4 b/tools/topology/topology1/m4/codec_adapter.m4 new file mode 100644 index 000000000000..8387867e2ef5 --- /dev/null +++ b/tools/topology/topology1/m4/codec_adapter.m4 @@ -0,0 +1,58 @@ +divert(-1) + +dnl Define macro for CODEC_ADAPTER widget +DECLARE_SOF_RT_UUID("codec_adapter", ca_uuid, 0xd8218443, 0x5ff3, 0x4a4c, + 0xb3, 0x88, 0x6c, 0xfe, 0x07, 0xb9, 0x56, 0xaa); + +ifdef(`CA_UUID', `', `define(`CA_UUID', ca_uuid)'); + +dnl N_CODEC_ADAPTER(name) +define(`N_CODEC_ADAPTER', `CODEC_ADAPTER'PIPELINE_ID`.'$1) + +dnl W_CODEC_ADAPTER(name, format, periods_sink, periods_source, core, kcontrol0. kcontrol1...etc) +define(`W_CODEC_ADAPTER', +`SectionVendorTuples."'N_CODEC_ADAPTER($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(CA_UUID) +` }' +`}' +`SectionData."'N_CODEC_ADAPTER($1)`_data_uuid" {' +` tuples "'N_CODEC_ADAPTER($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_CODEC_ADAPTER($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_CODEC_ADAPTER($1)`_data_w" {' +` tuples "'N_CODEC_ADAPTER($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_CODEC_ADAPTER($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_CODEC_ADAPTER($1)`_data_str" {' +` tuples "'N_CODEC_ADAPTER($1)`_tuples_str"' +`}' +`SectionWidget.ifdef(`CODEC_ADAPTER_NAME', "`CODEC_ADAPTER_NAME'", "`N_CODEC_ADAPTER($1)'") {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_CODEC_ADAPTER($1)`_data_uuid"' +` "'N_CODEC_ADAPTER($1)`_data_w"' +` "'N_CODEC_ADAPTER($1)`_data_str"' +` ]' +` bytes [' + $6 +` ]' + +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/crossover.m4 b/tools/topology/topology1/m4/crossover.m4 new file mode 100644 index 000000000000..22deb6a6c9aa --- /dev/null +++ b/tools/topology/topology1/m4/crossover.m4 @@ -0,0 +1,61 @@ +divert(-1) + +dnl Define macro for crossover widget +DECLARE_SOF_RT_UUID("crossover", crossover_uuid, 0x948c9ad1, 0x806a, 0x4131, + 0xad, 0x6c, 0xb2, 0xbd, 0xa9, 0xe3, 0x5a, 0x9f) + +dnl N_CROSSOVER(name) +define(`N_CROSSOVER', `CROSSOVER'PIPELINE_ID`.'$1) + +dnl W_CROSSOVER(name, format, periods_sink, periods_source, kcontrol_list) +define(`W_CROSSOVER', +`SectionVendorTuples."'N_CROSSOVER($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(crossover_uuid) +` }' +`}' +`SectionData."'N_CROSSOVER($1)`_data_uuid" {' +` tuples "'N_CROSSOVER($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_CROSSOVER($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` }' +`}' +`SectionData."'N_CROSSOVER($1)`_data_w" {' +` tuples "'N_CROSSOVER($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_CROSSOVER($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionVendorTuples."'N_CROSSOVER($1)`_crossover_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "CROSSOVER" +` }' +`}' +`SectionData."'N_CROSSOVER($1)`_data_str" {' +` tuples "'N_CROSSOVER($1)`_tuples_str"' +` tuples "'N_CROSSOVER($1)`_crossover_process_tuples_str"' +`}' +`SectionWidget."'N_CROSSOVER($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_CROSSOVER($1)`_data_uuid"' +` "'N_CROSSOVER($1)`_data_w"' +` "'N_CROSSOVER($1)`_data_str"' +` ]' +` bytes [' + $5 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/crossover/coef_2way_48000_200_1_2.m4 b/tools/topology/topology1/m4/crossover/coef_2way_48000_200_1_2.m4 new file mode 100644 index 000000000000..640f22ee7e26 --- /dev/null +++ b/tools/topology/topology1/m4/crossover/coef_2way_48000_200_1_2.m4 @@ -0,0 +1,19 @@ +# Exported Control Bytes 30-Jun-2023 +CONTROLBYTES_PRIV(CROSSOVER_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x60,0x00,0x00,0x00,0x00,0xa0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x95,0xc1,0x02,0x00,0x2a,0x83,0x05,0x00,' +` 0x95,0xc1,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2,' +` 0x3e,0x77,0xa1,0x7d,0x34,0x7d,0xd3,0x3e,' +` 0x99,0x05,0x59,0x82,0x34,0x7d,0xd3,0x3e,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/crossover/coef_3way_48000_200_1000_1_2_3.m4 b/tools/topology/topology1/m4/crossover/coef_3way_48000_200_1000_1_2_3.m4 new file mode 100644 index 000000000000..3ee3d5ef0e00 --- /dev/null +++ b/tools/topology/topology1/m4/crossover/coef_3way_48000_200_1000_1_2_3.m4 @@ -0,0 +1,33 @@ +# Exported Control Bytes 30-Jun-2023 +CONTROLBYTES_PRIV(CROSSOVER_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xd0,0x00,0x00,0x00,0x00,0xa0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xd0,0x00,0x00,0x00,0x03,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x95,0xc1,0x02,0x00,0x2a,0x83,0x05,0x00,' +` 0x95,0xc1,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2,' +` 0x3e,0x77,0xa1,0x7d,0x34,0x7d,0xd3,0x3e,' +` 0x99,0x05,0x59,0x82,0x34,0x7d,0xd3,0x3e,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xef,0xcd,0xd0,0xca,0x5d,0x8c,0x2e,0x74,' +` 0x6d,0x29,0x40,0x00,0xda,0x52,0x80,0x00,' +` 0x6d,0x29,0x40,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0xef,0xcd,0xd0,0xca,' +` 0x5d,0x8c,0x2e,0x74,0x9c,0x6f,0x57,0x3a,' +` 0xc9,0x20,0x51,0x8b,0x9c,0x6f,0x57,0x3a,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xef,0xcd,0xd0,0xca,0x5d,0x8c,0x2e,0x74,' +` 0x6d,0x29,0x40,0x00,0xda,0x52,0x80,0x00,' +` 0x6d,0x29,0x40,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0xef,0xcd,0xd0,0xca,' +` 0x5d,0x8c,0x2e,0x74,0x9c,0x6f,0x57,0x3a,' +` 0xc9,0x20,0x51,0x8b,0x9c,0x6f,0x57,0x3a,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/crossover/coef_4way_48000_200_1000_3000_1_2_3_4.m4 b/tools/topology/topology1/m4/crossover/coef_4way_48000_200_1000_3000_1_2_3_4.m4 new file mode 100644 index 000000000000..fe1fd29bd60d --- /dev/null +++ b/tools/topology/topology1/m4/crossover/coef_4way_48000_200_1000_3000_1_2_3_4.m4 @@ -0,0 +1,33 @@ +# Exported Control Bytes 30-Jun-2023 +CONTROLBYTES_PRIV(CROSSOVER_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xd0,0x00,0x00,0x00,0x00,0xa0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xd0,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x95,0xc1,0x02,0x00,0x2a,0x83,0x05,0x00,' +` 0x95,0xc1,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2,' +` 0x3e,0x77,0xa1,0x7d,0x34,0x7d,0xd3,0x3e,' +` 0x99,0x05,0x59,0x82,0x34,0x7d,0xd3,0x3e,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xef,0xcd,0xd0,0xca,0x5d,0x8c,0x2e,0x74,' +` 0x6d,0x29,0x40,0x00,0xda,0x52,0x80,0x00,' +` 0x6d,0x29,0x40,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0xef,0xcd,0xd0,0xca,' +` 0x5d,0x8c,0x2e,0x74,0x9c,0x6f,0x57,0x3a,' +` 0xc9,0x20,0x51,0x8b,0x9c,0x6f,0x57,0x3a,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xd0,0x91,0x42,0xdb,0xb1,0x53,0x12,0x5d,' +` 0xa0,0xc6,0xea,0x01,0x3f,0x8d,0xd5,0x03,' +` 0xa0,0xc6,0xea,0x01,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0xd0,0x91,0x42,0xdb,' +` 0xb1,0x53,0x12,0x5d,0x78,0xf0,0x73,0x30,' +` 0x10,0x1f,0x18,0x9f,0x78,0xf0,0x73,0x30,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/crossover_coef_default.m4 b/tools/topology/topology1/m4/crossover_coef_default.m4 new file mode 100644 index 000000000000..25d86f4a5c5b --- /dev/null +++ b/tools/topology/topology1/m4/crossover_coef_default.m4 @@ -0,0 +1,19 @@ +# Exported Control Bytes 17-Apr-2020 +CONTROLBYTES_PRIV(CROSSOVER_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x60,0x00,0x00,0x00,0x00,0xf0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,' +` 0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x8e,0x6f,0xa8,0xc5,0xb3,0x81,0x14,0x7a,' +` 0xb0,0xc3,0x10,0x00,0x5f,0x87,0x21,0x00,' +` 0xb0,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x8e,0x6f,0xa8,0xc5,' +` 0xb3,0x81,0x14,0x7a,0x89,0x04,0x1b,0x3d,' +` 0xee,0xf6,0xc9,0x85,0x89,0x04,0x1b,0x3d,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/dai.m4 b/tools/topology/topology1/m4/dai.m4 new file mode 100644 index 000000000000..cd968c6c61fd --- /dev/null +++ b/tools/topology/topology1/m4/dai.m4 @@ -0,0 +1,305 @@ +divert(-1) + +include(`debug.m4') + +dnl Define macros for DAI IN/OUT widgets and DAI config +DECLARE_SOF_RT_UUID("dai", dai_comp_uuid, 0xc2b00d27, 0xffbc, 0x4150, + 0xa5, 0x1a, 0x24, 0x5c, 0x79, 0xc5, 0xe5, 0x4b) + +dnl N_DAI(name) +define(`N_DAI', DAI_NAME) +define(`N_DAI_OUT', DAI_NAME`.OUT') +define(`N_DAI_IN', DAI_NAME`.IN') + +dnl W_DAI_OUT(type, index, dai_link, format, periods_sink, periods_source, core) +define(`W_DAI_OUT', +`SectionVendorTuples."'N_DAI_OUT`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(dai_comp_uuid) +` }' +`}' +`SectionData."'N_DAI_OUT`_data_uuid" {' +` tuples "'N_DAI_OUT`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_DAI_OUT`_tuples_w_comp" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($5) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($6) +` SOF_TKN_COMP_CORE_ID' STR($7) +` }' +`}' +`SectionData."'N_DAI_OUT`_data_w_comp" {' +` tuples "'N_DAI_OUT`_tuples_w_comp"' +`}' +`SectionVendorTuples."'N_DAI_OUT`_tuples_w" {' +` tokens "sof_dai_tokens"' +` tuples."word" {' +` SOF_TKN_DAI_INDEX' $2 +` SOF_TKN_DAI_DIRECTION' "0" +` }' +`}' +`SectionData."'N_DAI_OUT`_data_w" {' +` tuples "'N_DAI_OUT`_tuples_w"' +`}' +`SectionVendorTuples."'N_DAI_OUT`_tuples_str" {' +` tokens "sof_dai_tokens"' +` tuples."string" {' +` SOF_TKN_DAI_TYPE' $1 +` }' +`}' +`SectionData."'N_DAI_OUT`_data_str" {' +` tuples "'N_DAI_OUT`_tuples_str"' +`}' +`SectionVendorTuples."'N_DAI_OUT`_tuples_comp_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($4) +` }' +`}' +`SectionData."'N_DAI_OUT`_data_comp_str" {' +` tuples "'N_DAI_OUT`_tuples_comp_str"' +`}' +`SectionWidget."'N_DAI_OUT`" {' +` index "'PIPELINE_ID`"' +` type "dai_in"' +` stream_name' STR($3) +` no_pm "true"' +` data [' +` "'N_DAI_OUT`_data_uuid"' +` "'N_DAI_OUT`_data_w"' +` "'N_DAI_OUT`_data_w_comp"' +` "'N_DAI_OUT`_data_str"' +` "'N_DAI_OUT`_data_comp_str"' +` ]' +`}') + +dnl W_DAI_IN(type, index, dai_link, format, periods_sink, periods_source, core) +define(`W_DAI_IN', +`SectionVendorTuples."'N_DAI_IN`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(dai_comp_uuid) +` }' +`}' +`SectionData."'N_DAI_IN`_data_uuid" {' +` tuples "'N_DAI_IN`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_DAI_IN`_tuples_w_comp" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($5) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($6) +` SOF_TKN_COMP_CORE_ID' STR($7) +` }' +`}' +`SectionData."'N_DAI_IN`_data_w_comp" {' +` tuples "'N_DAI_IN`_tuples_w_comp"' +`}' +`SectionVendorTuples."'N_DAI_IN`_tuples_w" {' +` tokens "sof_dai_tokens"' +` tuples."word" {' +` SOF_TKN_DAI_INDEX' $2 +` SOF_TKN_DAI_DIRECTION' "1" +` }' +`}' +`SectionData."'N_DAI_IN`_data_w" {' +` tuples "'N_DAI_IN`_tuples_w"' +`}' +`SectionVendorTuples."'N_DAI_IN`_tuples_str" {' +` tokens "sof_dai_tokens"' +` tuples."string" {' +` SOF_TKN_DAI_TYPE' $1 +` }' +`}' +`SectionData."'N_DAI_IN`_data_str" {' +` tuples "'N_DAI_IN`_tuples_str"' +`}' +`SectionVendorTuples."'N_DAI_IN`_tuples_comp_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($4) +` }' +`}' +`SectionData."'N_DAI_IN`_data_comp_str" {' +` tuples "'N_DAI_IN`_tuples_comp_str"' +`}' +`SectionWidget."'N_DAI_IN`" {' +` index "'PIPELINE_ID`"' +` type "dai_out"' +` stream_name' STR($3) +` no_pm "true"' +` data [' +` "'N_DAI_IN`_data_uuid"' +` "'N_DAI_IN`_data_w"' +` "'N_DAI_IN`_data_w_comp"' +` "'N_DAI_IN`_data_str"' +` "'N_DAI_IN`_data_comp_str"' +` ]' +`}') + +dnl D_DAI(id, playback, capture, data)) +define(`D_DAI', `SectionDAI."'N_DAI`" {' +` index "'PIPELINE_ID`"' +` id "'$1`"' +` playback "'$2`"' +` capture "'$3`"' +`}') + +dnl DAI Config) +define(`N_DAI_CONFIG', `DAICONFIG.'$1) +dnl DAI_CONFIG(type, idx, link_id, name, sai_config/esai_config/ssp_config/dmic_config/afe_config) +define(`DO_DAI_CONFIG', +`SectionHWConfig."'$1$2`" {' +`' +` id "'$3`"' +`' +` ifelse($1, `SSP', $5, $1, `HDA', $5, $1, `ALH', $5, $1, `ESAI', $5, $1, `SAI', $5, $1, `MICFIL', $5, $1, `AFE', $5, $1, `ACP', $5, $1, `ACPSP', $5, $1,`ACPSP_VIRTUAL', $5, $1, `ACPHS', $5, $1, `ACPHS_VIRTUAL', $5, $1, `ACP_SDW', $5, $1, `ACPDMIC', $5, `}')' +`ifelse($1, `DMIC', $5, `')' +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples_common" {' +` tokens "sof_dai_tokens"' +` tuples."string" {' +` SOF_TKN_DAI_TYPE' STR($1) +` }' +` tuples."word" {' +` SOF_TKN_DAI_INDEX' STR($2) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data_common" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples_common"' +`}' +`' +`SectionBE."'$4`" {' +` id "'$3`"' +` index "0"' +` default_hw_conf_id "'$3`"' +`' +` hw_configs [' +` "'$1$2`"' +` ]' +` data [' +` "'N_DAI_CONFIG($1$2)`_data"' +` "'N_DAI_CONFIG($1$2)`_data_common"' +`ifelse($1, `DMIC',` "'N_DAI_CONFIG($1$2)`_pdm_data"', `')' +` ]' +`}' +`DEBUG_DAI_CONFIG($1, $3)' +) + +dnl DAI_CONFIG(type, idx, link_id, name, ssp_config/dmic_config) +define(`DAI_CONFIG', +`ifelse(`$#', `5', `DO_DAI_CONFIG($1, $2, $3, $4, $5)', `$#', `4', `DO_DAI_CONFIG($1, $2, $3, $4)', `fatal_error(`Invalid parameters ($#) to DAI_CONFIG')')' +) + +define(`HW_CONFIG_NAMES', +` hw_configs [' +` $1' +` ]') + +define(`DAI_DATA_NAMES', +` data [' +` $1' +` "N_DAI_CONFIG_data_common"') + +dnl DO_MULTI_DAI_CONFIG(type, idx, link_id, name, sai_config/esai_config/ssp_config/dmic_config) +define(`DO_MULTI_DAI_CONFIG', +`$5' +`SectionVendorTuples."N_DAI_CONFIG_tuples_common" {' +` tokens "sof_dai_tokens"' +` tuples."string" {' +` SOF_TKN_DAI_TYPE' STR($1) +` }' +` tuples."word" {' +` SOF_TKN_DAI_INDEX' STR($2) +` }' +`}' +`SectionData."N_DAI_CONFIG_data_common" {' +` tuples "N_DAI_CONFIG_tuples_common"' +`}' +`' +`SectionBE."'$4`" {' +` id "'$3`"' +` index "0"' +` default_hw_conf_id "'$3`"' +`' +` $6' +` $7' +`ifelse($1, `DMIC',` "'N_DAI_CONFIG($1$2)`_pdm_data"', `')' +` ]' +`}' +`DEBUG_DAI_CONFIG($1, $3)' +) + +dnl MULTI_DAI_CONFIG(type, idx, link_id, name, ssp_config/dmic_config times n) + define(`MULTI_DAI_CONFIG', +`ifelse(`eval($# < 5)', `1', `fatal_error(`Invalid parameters ($#) to MULTI_DAI_CONFIG')', `DO_MULTI_DAI_CONFIG($@)')' +) + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl period , priority, core, time_domain, +dnl channels, rate, dynamic_pipe) +define(`DAI_ADD', +`undefine(`PIPELINE_ID')' +`undefine(`DAI_TYPE')' +`undefine(`DAI_INDEX')' +`undefine(`DAI_BE')' +`undefine(`DAI_BUF')' +`undefine(`DAI_PERIODS')' +`undefine(`DAI_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`DAI_CHANNELS')' +`undefine(`DAI_RATE')' +`undefine(`DYNAMIC_PIPE')' +`define(`PIPELINE_ID', $2)' +`define(`DAI_TYPE', STR($3))' +`define(`DAI_INDEX', STR($4))' +`define(`DAI_BE', $5)' +`define(`DAI_BUF', $6)' +`define(`DAI_NAME', $3$4)' +`define(`DAI_PERIODS', $7)' +`define(`DAI_FORMAT', $8)' +`define(`SCHEDULE_PERIOD', $9)' +`define(`SCHEDULE_PRIORITY', $10)' +`define(`SCHEDULE_CORE', $11)' +`define(`SCHEDULE_TIME_DOMAIN', $12)' +`define(`DAI_CHANNELS', $13)' +`define(`DAI_RATE', $14)' +`define(`DYNAMIC_PIPE', $15)' +`define(`PIPELINE_FORMAT', $8)' +`include($1)' +`DEBUG_DAI($3, $4)' +`undefine(`PIPELINE_ID')' +`undefine(`DAI_TYPE')' +`undefine(`DAI_INDEX')' +`undefine(`DAI_BE')' +`undefine(`DAI_BUF')' +`undefine(`DAI_PERIODS')' +`undefine(`DAI_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`DAI_CHANNELS')' +`undefine(`DAI_RATE')' +`undefine(`DYNAMIC_PIPE')' +`undefine(`PIPELINE_FORMAT')' +) + +# DAI_ADD_SCHED can be used for adding a DAI with sched_comp +dnl DAI_ADD_SCHED(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl period , priority, core, time_domain, sched_comp) +define(`DAI_ADD_SCHED', +`undefine(`SCHED_COMP')' +`define(`SCHED_COMP', $13)' +`DAI_ADD($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)' +`undefine(`SCHED_COMP')' +) +divert(0)dnl diff --git a/tools/topology/topology1/m4/dcblock.m4 b/tools/topology/topology1/m4/dcblock.m4 new file mode 100644 index 000000000000..02263b806abb --- /dev/null +++ b/tools/topology/topology1/m4/dcblock.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for DC Blocking Filter widget +DECLARE_SOF_RT_UUID("dcblock", dcblock_uuid, 0xb809efaf, 0x5681, 0x42b1, + 0x9e, 0xd6, 0x04, 0xbb, 0x01, 0x2d, 0xd3, 0x84) + +dnl N_DCBLOCK(name) +define(`N_DCBLOCK', `DCBLOCK'PIPELINE_ID`.'$1) + +dnl W_DCBLOCK(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_DCBLOCK', +`SectionVendorTuples."'N_DCBLOCK($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(dcblock_uuid) +` }' +`}' +`SectionData."'N_DCBLOCK($1)`_data_uuid" {' +` tuples "'N_DCBLOCK($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_DCBLOCK($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_DCBLOCK($1)`_data_w" {' +` tuples "'N_DCBLOCK($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_DCBLOCK($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_DCBLOCK($1)`_data_str" {' +` tuples "'N_DCBLOCK($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_DCBLOCK($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "DCBLOCK" +` }' +`}' +`SectionData."'N_DCBLOCK($1)`_data_str_type" {' +` tuples "'N_DCBLOCK($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_DCBLOCK($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_DCBLOCK($1)`_data_uuid"' +` "'N_DCBLOCK($1)`_data_w"' +` "'N_DCBLOCK($1)`_data_str"' +` "'N_DCBLOCK($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/dcblock_coef_default.m4 b/tools/topology/topology1/m4/dcblock_coef_default.m4 new file mode 100644 index 000000000000..b7d7f5f166e7 --- /dev/null +++ b/tools/topology/topology1/m4/dcblock_coef_default.m4 @@ -0,0 +1,11 @@ +# Exported Control Bytes 16-Mar-2020 +CONTROLBYTES_PRIV(DCBLOCK_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e,' +` 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e,' +` 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e,' +` 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e"' +) diff --git a/tools/topology/m4/debug.m4 b/tools/topology/topology1/m4/debug.m4 similarity index 100% rename from tools/topology/m4/debug.m4 rename to tools/topology/topology1/m4/debug.m4 diff --git a/tools/topology/topology1/m4/detect.m4 b/tools/topology/topology1/m4/detect.m4 new file mode 100644 index 000000000000..19c2849899c2 --- /dev/null +++ b/tools/topology/topology1/m4/detect.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for generic detection widget +DECLARE_SOF_RT_UUID("kd-test", keyword_uuid, 0xeba8d51f, 0x7827, 0x47b5, + 0x82, 0xee, 0xde, 0x6e, 0x77, 0x43, 0xaf, 0x67) + +dnl N_DETECT(name) +define(`N_DETECT', `DETECT'PIPELINE_ID`.'$1) + +dnl W_DETECT(name, format, periods_sink, periods_source, detect_type, stream_name, core, kcontrols_list) +define(`W_DETECT', +`SectionVendorTuples."'N_DETECT($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(keyword_uuid) +` }' +`}' +`SectionData."'N_DETECT($1)`_data_uuid" {' +` tuples "'N_DETECT($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_DETECT($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($7) +` }' +`}' +`SectionVendorTuples."'N_DETECT($1)`_detect_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' STR(concat($5, _DETECT)) +` }' +`}' +`SectionData."'N_DETECT($1)`_data_w" {' +` tuples "'N_DETECT($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_DETECT($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_DETECT($1)`_data_str" {' +` tuples "'N_DETECT($1)`_tuples_str"' +` tuples "'N_DETECT($1)`_detect_process_tuples_str"' +`}' +`SectionWidget."'N_DETECT($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` stream_name' STR($6) +` no_pm "true"' +` event_flags "15"' # trapping PRE/POST_PMU/PMD events +` event_type "1"' # 1 for DAPM event for detect component +` data [' +` "'N_DETECT($1)`_data_uuid"' +` "'N_DETECT($1)`_data_w"' +` "'N_DETECT($1)`_data_str"' +` ]' +` bytes [' + $8 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/m4/detect_test_coef.m4 b/tools/topology/topology1/m4/detect_test_coef.m4 similarity index 91% rename from tools/topology/m4/detect_test_coef.m4 rename to tools/topology/topology1/m4/detect_test_coef.m4 index 4ffcfe6b6960..45e98eb7276b 100644 --- a/tools/topology/m4/detect_test_coef.m4 +++ b/tools/topology/topology1/m4/detect_test_coef.m4 @@ -7,5 +7,5 @@ CONTROLBYTES_PRIV(DETECTOR_priv, ` 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x34,0x08,0x00,0x00,' ` 0x03,0x00,0x18,0x00,0x00,0x00,0x00,0x00,' -` 0x34,0x08,0x00,0x00,0x00,0x00,0x00,0x00"' +` 0xD0,0x07,0x00,0x00,0x00,0x00,0x00,0x00"' ) diff --git a/tools/topology/topology1/m4/drc.m4 b/tools/topology/topology1/m4/drc.m4 new file mode 100644 index 000000000000..5201120035a3 --- /dev/null +++ b/tools/topology/topology1/m4/drc.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for Dyanamic Range Compressor widget +DECLARE_SOF_RT_UUID("drc", drc_uuid, 0xb36ee4da, 0x006f, 0x47f9, + 0xa0, 0x6d, 0xfe, 0xcb, 0xe2, 0xd8, 0xb6, 0xce); + +dnl N_DRC(name) +define(`N_DRC', `DRC'PIPELINE_ID`.'$1) + +dnl W_DRC(name, format, periods_sink, periods_source, core, kcontrol_list) +define(`W_DRC', +`SectionVendorTuples."'N_DRC($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(drc_uuid) +` }' +`}' +`SectionData."'N_DRC($1)`_data_uuid" {' +` tuples "'N_DRC($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_DRC($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_DRC($1)`_data_w" {' +` tuples "'N_DRC($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_DRC($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_DRC($1)`_data_str" {' +` tuples "'N_DRC($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_DRC($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "DRC" +` }' +`}' +`SectionData."'N_DRC($1)`_data_str_type" {' +` tuples "'N_DRC($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_DRC($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_DRC($1)`_data_uuid"' +` "'N_DRC($1)`_data_w"' +` "'N_DRC($1)`_data_str"' +` "'N_DRC($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/drc_coef_default.m4 b/tools/topology/topology1/m4/drc_coef_default.m4 new file mode 100644 index 000000000000..cf6add6a97c0 --- /dev/null +++ b/tools/topology/topology1/m4/drc_coef_default.m4 @@ -0,0 +1,21 @@ +# Exported Control Bytes 03-Nov-2020 +CONTROLBYTES_PRIV(DRC_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x6c,0x00,0x00,0x00,0x00,0x20,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e,' +` 0x00,0x00,0x00,0x01,0xd3,0x4d,0x62,0x00,' +` 0xb1,0xc2,0x09,0x04,0x00,0x00,0x00,0x40,' +` 0xa6,0x99,0x01,0x00,0xce,0xd8,0x0f,0x0a,' +` 0x1f,0x1a,0xf0,0xf5,0x83,0xc9,0xfe,0x01,' +` 0xdf,0x30,0x61,0x3a,0xcb,0x83,0x0e,0x01,' +` 0xef,0x84,0x73,0x01,0x6d,0x64,0x6b,0xff,' +` 0x03,0x41,0x22,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x10,0xf8,0x00,0xaa,0x81,0x10,0x00,' +` 0xf4,0xf0,0x8a,0x00,0xaa,0xe1,0x22,0x00,' +` 0xb9,0x9b,0x02,0x00"' +) diff --git a/tools/topology/topology1/m4/drc_coef_speaker_default.m4 b/tools/topology/topology1/m4/drc_coef_speaker_default.m4 new file mode 100644 index 000000000000..f463c57f3a00 --- /dev/null +++ b/tools/topology/topology1/m4/drc_coef_speaker_default.m4 @@ -0,0 +1,22 @@ +# Exported with script example_drc.m 21-May-2024 +# cd tools/tune/drc; octave --no-window-system example_drc.m +CONTROLBYTES_PRIV(DRC_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x6c,0x00,0x00,0x00,0x00,0xa0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x14,' +` 0x00,0x00,0x00,0x0a,0xd3,0x4d,0x62,0x00,' +` 0x8a,0x1b,0x06,0x02,0x66,0x66,0x66,0x06,' +` 0x2f,0x97,0xba,0x00,0x18,0x0c,0x1e,0x00,' +` 0x20,0x42,0xe0,0xff,0x4e,0xf4,0x50,0x00,' +` 0x9a,0x9f,0x34,0x08,0xd3,0x2c,0xd8,0x04,' +` 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff,' +` 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x80,0x43,0x00,0xd7,0x7d,0x04,0x00,' +` 0xa0,0xce,0x25,0x00,0xd7,0x7d,0x09,0x00,' +` 0xb1,0xb5,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/dts_codec_adapter.m4 b/tools/topology/topology1/m4/dts_codec_adapter.m4 new file mode 100644 index 000000000000..49ba3d8bdec8 --- /dev/null +++ b/tools/topology/topology1/m4/dts_codec_adapter.m4 @@ -0,0 +1,34 @@ + + +# DTS codec setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +) +define(`CA_SETUP_CONTROLBYTES_MAX', 8192) +define(`CA_SETUP_CONTROLBYTES_NAME', `DTS Codec Setup ') + +DECLARE_SOF_RT_UUID("DTS codec", dts_uuid, 0xd95fc34f, 0x370f, 0x4ac7, 0xbc, 0x86, 0xbf, 0xdc, 0x5b, 0xe2, 0x41, 0xe6) +define(`CA_UUID', dts_uuid) + + +include(`codec_adapter.m4') + + +define(CA_SETUP_CONFIG, concat(`ca_setup_config_', PIPELINE_ID)) +define(CA_SETUP_CONTROLBYTES_NAME_PIPE, concat(CA_SETUP_CONTROLBYTES_NAME, PIPELINE_ID)) + + +# Codec adapter setup config +CONTROLBYTES_PRIV(CA_SETUP_CONFIG, CA_SETUP_CONTROLBYTES) + +# Codec adapter Bytes control for setup config +C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_SETUP_CONTROLBYTES_MAX), + , + CA_SETUP_CONFIG) diff --git a/tools/topology/topology1/m4/eap.m4 b/tools/topology/topology1/m4/eap.m4 new file mode 100644 index 000000000000..1d223ad2cbdf --- /dev/null +++ b/tools/topology/topology1/m4/eap.m4 @@ -0,0 +1,69 @@ +divert(-1) + +dnl Define macro for EAP (Essential Audio Processing) widget +DECLARE_SOF_RT_UUID("eap", eap_uuid, 0x127f4eec, 0x23fa, 0x11f0, + 0xa4, 0xa6, 0xbf, 0x0c, 0xd6, 0xb4, 0x58, 0x3b) + +dnl EAP(name) +define(`N_EAP', `EAP'PIPELINE_ID`.'$1) + +dnl W_EAP(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_EAP', +`SectionVendorTuples."'N_EAP($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(eap_uuid) +` }' +`}' +`SectionData."'N_EAP($1)`_data_uuid" {' +` tuples "'N_EAP($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_EAP($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_EAP($1)`_data_w" {' +` tuples "'N_EAP($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_EAP($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_EAP($1)`_data_str" {' +` tuples "'N_EAP($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_EAP($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "EAP" +` }' +`}' +`SectionData."'N_EAP($1)`_data_str_type" {' +` tuples "'N_EAP($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_EAP($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_EAP($1)`_data_uuid"' +` "'N_EAP($1)`_data_w"' +` "'N_EAP($1)`_data_str"' +` "'N_EAP($1)`_data_str_type"' +` ]' +` enum [' + $6 + $7 +` ]' +` bytes [' + $8 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/eap_controls.m4 b/tools/topology/topology1/m4/eap_controls.m4 new file mode 100644 index 000000000000..56bbb904a2a2 --- /dev/null +++ b/tools/topology/topology1/m4/eap_controls.m4 @@ -0,0 +1,12 @@ + +# EAP supported Audio Processing algorithms +CONTROLENUM_LIST(DEF_EAP_CFG_VALUES, + LIST(` ', `"Off"', `"AutoVolumeLeveler"', `"ConcertSound"', `"LoudnessMaximiser"', `"MusicEnhancerRMSLimiter"', `"VoiceEnhancer"')) + +# TDFB enum control +C_CONTROLENUM(DEF_EAP_CFG, PIPELINE_ID, + DEF_EAP_CFG_VALUES, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + CONTROLENUM_OPS(enum, + 257 binds the mixer control to enum get/put handlers, + 257, 257)) diff --git a/tools/topology/topology1/m4/enumcontrol.m4 b/tools/topology/topology1/m4/enumcontrol.m4 new file mode 100644 index 000000000000..3c046198da6c --- /dev/null +++ b/tools/topology/topology1/m4/enumcontrol.m4 @@ -0,0 +1,58 @@ +dnl ENUM_CHANNEL(name, reg, shift) +define(`ENUM_CHANNEL', +`channel.STR($1) {' +` reg STR($2)' +` shift STR($3)' +` }') + + +dnl CONTROLENUM_OPS(info, comment, get, put) +define(`CONTROLENUM_OPS', +`ops."ctl" {' +` info STR($1)' +` #$2' +` get STR($3)' +` put STR($4)' +` }') + +dnl CONTROLENUM_LIST(name, enums_list) +define(`CONTROLENUM_LIST', +`SectionText.STR($1) {' +` values [' +` $2' +` ]' +`}') + +dnl C_CONTROLENUM(name, index, ops, ops, enums) +define(`C_CONTROLENUM', +`SectionControlEnum.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # enum values as text' +` texts STR($3)' +`' +` # channel register and shift for Front Left/Right' +` $4' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $5' +`}') + +dnl C_CONTROLENUM(name, index, ops, ops, enums) +define(`C_CONTROLENUM', +`SectionControlEnum.STR($1) {' +`' +` # control belongs to this index group' +` index STR($2)' +`' +` # enum values as text' +` texts STR($3)' +`' +` # channel register and shift for Front Left/Right' +` $4' +`' +` # control uses bespoke driver get/put/info ID for io ops' +` $5' +`}') diff --git a/tools/topology/topology1/m4/eq_fir.m4 b/tools/topology/topology1/m4/eq_fir.m4 new file mode 100644 index 000000000000..c1b7f67c3739 --- /dev/null +++ b/tools/topology/topology1/m4/eq_fir.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for Eq effect widget +DECLARE_SOF_RT_UUID("eq-fir", eq_fir_uuid, 0x43a90ce7, 0xf3a5, 0x41df, + 0xac, 0x06, 0xba, 0x98, 0x65, 0x1a, 0xe6, 0xa3) + +dnl N_EQ_FIR(name) +define(`N_EQ_FIR', `EQFIR'PIPELINE_ID`.'$1) + +dnl W_EQ(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_EQ_FIR', +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(eq_fir_uuid) +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_uuid" {' +` tuples "'N_EQ_FIR($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_w" {' +` tuples "'N_EQ_FIR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_str" {' +` tuples "'N_EQ_FIR($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_EQ_FIR($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "EQFIR" +` }' +`}' +`SectionData."'N_EQ_FIR($1)`_data_str_type" {' +` tuples "'N_EQ_FIR($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_EQ_FIR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_EQ_FIR($1)`_data_uuid"' +` "'N_EQ_FIR($1)`_data_w"' +` "'N_EQ_FIR($1)`_data_str"' +` "'N_EQ_FIR($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/m4/eq_fir_coef_flat.m4 b/tools/topology/topology1/m4/eq_fir_coef_flat.m4 similarity index 94% rename from tools/topology/m4/eq_fir_coef_flat.m4 rename to tools/topology/topology1/m4/eq_fir_coef_flat.m4 index a8f4119d11af..badad66dfecb 100644 --- a/tools/topology/m4/eq_fir_coef_flat.m4 +++ b/tools/topology/topology1/m4/eq_fir_coef_flat.m4 @@ -1,5 +1,5 @@ # Flat FIR EQ 19-Dec-2018 -CONTROLBYTES_PRIV(EQFIR_priv, +CONTROLBYTES_PRIV(DEF_EQFIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/topology1/m4/eq_fir_coef_loudness.m4 b/tools/topology/topology1/m4/eq_fir_coef_loudness.m4 new file mode 100644 index 000000000000..c03fce95eefb --- /dev/null +++ b/tools/topology/topology1/m4/eq_fir_coef_loudness.m4 @@ -0,0 +1,80 @@ +# Loudness effect, created with example_fir_eq.m 09-Feb-2022 +CONTROLBYTES_PRIV(DEF_EQFIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x48,0x02,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x48,0x02,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x03,0x00,0x04,0x00,' +` 0x04,0x00,0x04,0x00,0x05,0x00,0x05,0x00,' +` 0x05,0x00,0x06,0x00,0x06,0x00,0x06,0x00,' +` 0x07,0x00,0x07,0x00,0x08,0x00,0x08,0x00,' +` 0x09,0x00,0x09,0x00,0x0a,0x00,0x0a,0x00,' +` 0x0b,0x00,0x0b,0x00,0x0c,0x00,0x0c,0x00,' +` 0x0d,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00,' +` 0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00,' +` 0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00,' +` 0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00,' +` 0x1a,0x00,0x1b,0x00,0x1d,0x00,0x1e,0x00,' +` 0x1f,0x00,0x21,0x00,0x22,0x00,0x24,0x00,' +` 0x26,0x00,0x28,0x00,0x29,0x00,0x2b,0x00,' +` 0x2d,0x00,0x2f,0x00,0x32,0x00,0x34,0x00,' +` 0x36,0x00,0x38,0x00,0x3b,0x00,0x3d,0x00,' +` 0x40,0x00,0x42,0x00,0x45,0x00,0x48,0x00,' +` 0x4b,0x00,0x4d,0x00,0x51,0x00,0x54,0x00,' +` 0x57,0x00,0x5b,0x00,0x5e,0x00,0x62,0x00,' +` 0x65,0x00,0x68,0x00,0x6c,0x00,0x6f,0x00,' +` 0x72,0x00,0x76,0x00,0x79,0x00,0x7d,0x00,' +` 0x81,0x00,0x86,0x00,0x8c,0x00,0x92,0x00,' +` 0x98,0x00,0x9f,0x00,0xa5,0x00,0xac,0x00,' +` 0xb2,0x00,0xb8,0x00,0xbe,0x00,0xc6,0x00,' +` 0xce,0x00,0xd8,0x00,0xe1,0x00,0xea,0x00,' +` 0xef,0x00,0xf5,0x00,0xfc,0x00,0xfc,0x00,' +` 0x18,0x01,0xff,0x00,0x2f,0x01,0x70,0x01,' +` 0xc3,0x00,0x39,0x04,0xd3,0x02,0xae,0xe9,' +` 0xbf,0x6c,0xae,0xe9,0xd3,0x02,0x39,0x04,' +` 0xc3,0x00,0x70,0x01,0x2f,0x01,0xff,0x00,' +` 0x18,0x01,0xfc,0x00,0xfc,0x00,0xf5,0x00,' +` 0xef,0x00,0xea,0x00,0xe1,0x00,0xd8,0x00,' +` 0xce,0x00,0xc6,0x00,0xbe,0x00,0xb8,0x00,' +` 0xb2,0x00,0xac,0x00,0xa5,0x00,0x9f,0x00,' +` 0x98,0x00,0x92,0x00,0x8c,0x00,0x86,0x00,' +` 0x81,0x00,0x7d,0x00,0x79,0x00,0x76,0x00,' +` 0x72,0x00,0x6f,0x00,0x6c,0x00,0x68,0x00,' +` 0x65,0x00,0x62,0x00,0x5e,0x00,0x5b,0x00,' +` 0x57,0x00,0x54,0x00,0x51,0x00,0x4d,0x00,' +` 0x4b,0x00,0x48,0x00,0x45,0x00,0x42,0x00,' +` 0x40,0x00,0x3d,0x00,0x3b,0x00,0x38,0x00,' +` 0x36,0x00,0x34,0x00,0x32,0x00,0x2f,0x00,' +` 0x2d,0x00,0x2b,0x00,0x29,0x00,0x28,0x00,' +` 0x26,0x00,0x24,0x00,0x22,0x00,0x21,0x00,' +` 0x1f,0x00,0x1e,0x00,0x1d,0x00,0x1b,0x00,' +` 0x1a,0x00,0x19,0x00,0x18,0x00,0x17,0x00,' +` 0x16,0x00,0x15,0x00,0x14,0x00,0x13,0x00,' +` 0x12,0x00,0x12,0x00,0x11,0x00,0x10,0x00,' +` 0x0f,0x00,0x0f,0x00,0x0e,0x00,0x0d,0x00,' +` 0x0d,0x00,0x0c,0x00,0x0c,0x00,0x0b,0x00,' +` 0x0b,0x00,0x0a,0x00,0x0a,0x00,0x09,0x00,' +` 0x09,0x00,0x08,0x00,0x08,0x00,0x07,0x00,' +` 0x07,0x00,0x06,0x00,0x06,0x00,0x06,0x00,' +` 0x05,0x00,0x05,0x00,0x05,0x00,0x04,0x00,' +` 0x04,0x00,0x04,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x03,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_fir_coef_mid.m4 b/tools/topology/topology1/m4/eq_fir_coef_mid.m4 new file mode 100644 index 000000000000..da3c7dc06be6 --- /dev/null +++ b/tools/topology/topology1/m4/eq_fir_coef_mid.m4 @@ -0,0 +1,23 @@ +# Mid boost, created with example_fir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQFIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x80,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x80,0x00,0x00,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfa,0x6c,0xa7,0x47,0xe7,0x21,0xb2,0xfb,' +` 0x8b,0xe9,0xe7,0xe6,0x00,0xeb,0xe7,0xef,' +` 0x8b,0xf3,0xed,0xf5,0x94,0xf7,0xf6,0xf8,' +` 0x39,0xfa,0x65,0xfb,0x72,0xfc,0x5b,0xfd,' +` 0x1e,0xfe,0xbd,0xfe,0x3c,0xff,0xa1,0xff,' +` 0xed,0xff,0x25,0x00,0x4d,0x00,0x67,0x00,' +` 0x76,0x00,0x7c,0x00,0x7b,0x00,0x76,0x00,' +` 0x6e,0x00,0x63,0x00,0x58,0x00,0x4c,0x00,' +` 0x40,0x00,0x35,0x00,0x2c,0x00,0x23,0x00,' +` 0x1b,0x00,0x13,0x00,0x0d,0x00,0x13,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_fir_coef_pass.m4 b/tools/topology/topology1/m4/eq_fir_coef_pass.m4 new file mode 100644 index 000000000000..2f3c62cdcebd --- /dev/null +++ b/tools/topology/topology1/m4/eq_fir_coef_pass.m4 @@ -0,0 +1,14 @@ +# Pass-through response, created with example_fir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQFIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x38,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x38,0x00,0x00,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xff,0xff,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_iir.m4 b/tools/topology/topology1/m4/eq_iir.m4 new file mode 100644 index 000000000000..dd3fbe037d8f --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for Eq effect widget +DECLARE_SOF_RT_UUID("eq-iir", eq_iir_uuid, 0x5150c0e6, 0x27f9, 0x4ec8, + 0x83, 0x51, 0xc7, 0x05, 0xb6, 0x42, 0xd1, 0x2f) + +dnl N_EQ_IIR(name) +define(`N_EQ_IIR', `EQIIR'PIPELINE_ID`.'$1) + +dnl W_EQ(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_EQ_IIR', +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(eq_iir_uuid) +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_uuid" {' +` tuples "'N_EQ_IIR($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_w" {' +` tuples "'N_EQ_IIR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_str" {' +` tuples "'N_EQ_IIR($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_EQ_IIR($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "EQIIR" +` }' +`}' +`SectionData."'N_EQ_IIR($1)`_data_str_type" {' +` tuples "'N_EQ_IIR($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_EQ_IIR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_EQ_IIR($1)`_data_uuid"' +` "'N_EQ_IIR($1)`_data_w"' +` "'N_EQ_IIR($1)`_data_str"' +` "'N_EQ_IIR($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/eq_iir_bundle.m4 b/tools/topology/topology1/m4/eq_iir_bundle.m4 new file mode 100644 index 000000000000..144d299db3ee --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_bundle.m4 @@ -0,0 +1,58 @@ +# Bundle of responses flat/loud/bass/band/high, created with example_iir_eq.m 15-May-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x98,0x01,0x00,0x00,0x00,0x00,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x98,0x01,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x9e,0x73,0x13,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00,' +` 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x5a,0xff,0xc0,0xb4,0xc1,0xff,0x7e,' +` 0x9f,0xb7,0xb4,0x11,0x2d,0x0a,0x35,0xdc,' +` 0x90,0xb0,0x16,0x12,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x21,0xf8,0xd5,0xc4,' +` 0xf0,0x6b,0x14,0x7b,0x27,0xb8,0x9d,0x0e,' +` 0xb9,0x24,0x18,0xe1,0xa9,0xf7,0x54,0x10,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xff,0xaf,0xc0,0xf4,0x17,0xa2,0x2d,0xf6,' +` 0x35,0xa4,0x1f,0x04,0x58,0x87,0x20,0xf9,' +` 0xb9,0x3e,0xcb,0x15,0xfc,0xff,0xff,0xff,' +` 0x7c,0x63,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0,' +` 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f,' +` 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x1f,0x86,0xa2,0x09,0xe8,0xa3,0x18,0xec,' +` 0x7d,0x5c,0x4a,0x0a,0xfe,0xff,0xff,0xff,' +` 0x06,0x6d,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8e,0x6f,0xa8,0xc5,' +` 0xb3,0x81,0x14,0x7a,0xae,0x14,0xa0,0x1e,' +` 0xa5,0xd6,0xbf,0xc2,0xae,0x14,0xa0,0x1e,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x3e,0xac,0x84,0xe6,0xc3,0x9a,0xfd,0x46,' +` 0xcf,0x1e,0x51,0x02,0x9d,0x3d,0xa2,0x04,' +` 0xcf,0x1e,0x51,0x02,0xfc,0xff,0xff,0xff,' +` 0x85,0x5e,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x63,0xf3,0x96,0xc0,' +` 0xc6,0x59,0x68,0x7f,0x6d,0x89,0xed,0x1f,' +` 0x27,0xed,0x24,0xc0,0x6d,0x89,0xed,0x1f,' +` 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_iir_coef_bandpass.m4 b/tools/topology/topology1/m4/eq_iir_coef_bandpass.m4 new file mode 100644 index 000000000000..ffdff07cdc44 --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_coef_bandpass.m4 @@ -0,0 +1,22 @@ +# Band-pass, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x74,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x74,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8e,0x6f,0xa8,0xc5,' +` 0xb3,0x81,0x14,0x7a,0xae,0x14,0xa0,0x1e,' +` 0xa5,0xd6,0xbf,0xc2,0xae,0x14,0xa0,0x1e,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x3e,0xac,0x84,0xe6,0xc3,0x9a,0xfd,0x46,' +` 0xcf,0x1e,0x51,0x02,0x9d,0x3d,0xa2,0x04,' +` 0xcf,0x1e,0x51,0x02,0xfc,0xff,0xff,0xff,' +` 0x85,0x5e,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_iir_coef_bandsplit.m4 b/tools/topology/topology1/m4/eq_iir_coef_bandsplit.m4 new file mode 100644 index 000000000000..808491a2ddca --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_coef_bandsplit.m4 @@ -0,0 +1,29 @@ +# Bandsplit, created with example_iir_bandsplit.m 26-Oct-2021 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xb0,0x00,0x00,0x00,0x01,0x20,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xb0,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0xda,0xf0,0xc0,' +` 0x1e,0x5d,0x0d,0x7f,0x3c,0xdf,0xd6,0x1f,' +` 0x89,0x41,0x52,0xc0,0x3c,0xdf,0xd6,0x1f,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68,' +` 0xb9,0x41,0x76,0x00,0x72,0x83,0xec,0x00,' +` 0xb9,0x41,0x76,0x00,0xff,0xff,0xff,0xff,' +` 0x99,0x7f,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x2d,0x3a,0xcd,0xd3,' +` 0xc0,0xf5,0x82,0x68,0x01,0xe1,0xa6,0x1a,' +` 0xff,0x3d,0xb2,0xca,0x01,0xe1,0xa6,0x1a,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_iir_coef_bassboost.m4 b/tools/topology/topology1/m4/eq_iir_coef_bassboost.m4 new file mode 100644 index 000000000000..c62daf0d5d39 --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_coef_bassboost.m4 @@ -0,0 +1,22 @@ +# Bass boost, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x74,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x74,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0,' +` 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f,' +` 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x1f,0x86,0xa2,0x09,0xe8,0xa3,0x18,0xec,' +` 0x7d,0x5c,0x4a,0x0a,0xfe,0xff,0xff,0xff,' +` 0x06,0x6d,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_iir_coef_drceq.m4 b/tools/topology/topology1/m4/eq_iir_coef_drceq.m4 new file mode 100644 index 000000000000..ba22c3d337ce --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_coef_drceq.m4 @@ -0,0 +1,74 @@ +# Exported Control Bytes 11-May-2021 +CONTROLBYTES_PRIV(EQIIR_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x02,0x00,0x00,0x01,0x20,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x02,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x51,0xaf,0xde,0xc0,' +` 0xe5,0x86,0x1e,0x7f,0x00,0x00,0x00,0x20,' +` 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x20,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x2a,0x07,0x27,0xf3,0x03,0x3f,0xee,0x19,' +` 0x65,0xde,0x78,0x0b,0x00,0x7b,0xab,0xf2,' +` 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x0e,0xd4,0x2c,0xc2,' +` 0x29,0xaf,0x85,0x7d,0x64,0x58,0xd4,0x1f,' +` 0x00,0x00,0x00,0xc0,0xca,0x29,0x53,0x20,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x84,0xdc,0x3e,0xc2,0x55,0x8a,0xc8,0x7c,' +` 0x6a,0xf0,0xe7,0x1f,0x00,0x00,0x00,0xc0,' +` 0x6d,0x90,0x97,0x20,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x05,0x44,0xde,0xc3,' +` 0x60,0x89,0x3f,0x77,0x12,0x68,0x7c,0x20,' +` 0x00,0x00,0x00,0xc0,0xbd,0x91,0x22,0x22,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x64,0x43,0x8b,0xdc,0x3c,0xb9,0xbd,0x19,' +` 0x97,0xcb,0x9f,0x27,0xc4,0x46,0x42,0xe6,' +` 0x05,0xf1,0xd4,0x3b,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x39,0x83,0x3c,0xcb,' +` 0x96,0xc9,0x1e,0x65,0x34,0xb0,0x48,0x22,' +` 0x00,0x00,0x00,0xc0,0xe2,0xec,0x9d,0x27,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xab,0xba,0x59,0xc3,0x82,0x51,0xb5,0x7a,' +` 0xd6,0x19,0xec,0x1f,0x00,0x00,0x00,0xc0,' +` 0x37,0x17,0x17,0x21,0xfb,0xff,0xff,0xff,' +` 0x3e,0x63,0x00,0x00,0x08,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x51,0xaf,0xde,0xc0,' +` 0xe5,0x86,0x1e,0x7f,0x00,0x00,0x00,0x20,' +` 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x20,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x2a,0x07,0x27,0xf3,0x03,0x3f,0xee,0x19,' +` 0x65,0xde,0x78,0x0b,0x00,0x7b,0xab,0xf2,' +` 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x0e,0xd4,0x2c,0xc2,' +` 0x29,0xaf,0x85,0x7d,0x64,0x58,0xd4,0x1f,' +` 0x00,0x00,0x00,0xc0,0xca,0x29,0x53,0x20,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x84,0xdc,0x3e,0xc2,0x55,0x8a,0xc8,0x7c,' +` 0x6a,0xf0,0xe7,0x1f,0x00,0x00,0x00,0xc0,' +` 0x6d,0x90,0x97,0x20,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x05,0x44,0xde,0xc3,' +` 0x60,0x89,0x3f,0x77,0x12,0x68,0x7c,0x20,' +` 0x00,0x00,0x00,0xc0,0xbd,0x91,0x22,0x22,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x64,0x43,0x8b,0xdc,0x3c,0xb9,0xbd,0x19,' +` 0x97,0xcb,0x9f,0x27,0xc4,0x46,0x42,0xe6,' +` 0x05,0xf1,0xd4,0x3b,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x39,0x83,0x3c,0xcb,' +` 0x96,0xc9,0x1e,0x65,0x34,0xb0,0x48,0x22,' +` 0x00,0x00,0x00,0xc0,0xe2,0xec,0x9d,0x27,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xab,0xba,0x59,0xc3,0x82,0x51,0xb5,0x7a,' +` 0xd6,0x19,0xec,0x1f,0x00,0x00,0x00,0xc0,' +` 0x37,0x17,0x17,0x21,0xfb,0xff,0xff,0xff,' +` 0x3e,0x63,0x00,0x00"' +) diff --git a/tools/topology/m4/eq_iir_coef_flat.m4 b/tools/topology/topology1/m4/eq_iir_coef_flat.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_flat.m4 rename to tools/topology/topology1/m4/eq_iir_coef_flat.m4 index 72e104f3d0e3..4c01a5bc39ed 100644 --- a/tools/topology/m4/eq_iir_coef_flat.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_flat.m4 @@ -1,5 +1,5 @@ # Flat IIR EQ 18-Dec-2018 -CONTROLBYTES_PRIV(EQIIR_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 index cb1fd5451898..17d5cab0d8db 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_0db_16khz.m4 @@ -1,5 +1,5 @@ # 20 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP20HZ0dB16K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 index 669c9f3483b8..176759a2f1e7 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_0db_48khz.m4 @@ -1,5 +1,5 @@ # 20 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP20HZ0dB48K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 similarity index 81% rename from tools/topology/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 index be0e3d70736e..b5b6f6e5eb86 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_20db_16khz.m4 @@ -1,7 +1,7 @@ -# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP20HZ20dB16K_priv, +# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' @@ -14,5 +14,5 @@ CONTROLBYTES_PRIV(EQIIR_HP20HZ20dB16K_priv, ` 0x00,0x00,0x00,0x00,0x3c,0xf9,0xb4,0xc0,' ` 0x79,0x05,0x4a,0x7f,0x92,0xf9,0xe5,0x1f,' ` 0xdc,0x0c,0x34,0xc0,0x92,0xf9,0xe5,0x1f,' -` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +` 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00"' ) diff --git a/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 similarity index 81% rename from tools/topology/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 index a93f8cb8e15b..5b884ce9b812 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_20hz_20db_48khz.m4 @@ -1,7 +1,7 @@ -# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP20HZ20dB48K_priv, +# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' @@ -14,5 +14,5 @@ CONTROLBYTES_PRIV(EQIIR_HP20HZ20dB48K_priv, ` 0x00,0x00,0x00,0x00,0x4a,0x8c,0x3c,0xc0,' ` 0x04,0x57,0xc3,0x7f,0xc0,0x43,0x04,0x20,' ` 0x80,0x78,0xf7,0xbf,0xc0,0x43,0x04,0x20,' -` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +` 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00"' ) diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 index 03be97e82651..ea3ab034819b 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_0db_16khz.m4 @@ -1,5 +1,5 @@ # 30 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP30HZ0dB16K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 index a77770b613ac..198fc603e805 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_0db_48khz.m4 @@ -1,5 +1,5 @@ # 30 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP30HZ0dB48K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 similarity index 81% rename from tools/topology/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 index 7f2445d82416..a343371053e4 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_20db_16khz.m4 @@ -1,7 +1,7 @@ -# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP30HZ20dB16K_priv, +# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' @@ -14,5 +14,5 @@ CONTROLBYTES_PRIV(EQIIR_HP30HZ20dB16K_priv, ` 0x00,0x00,0x00,0x00,0x98,0xb5,0x0e,0xc1,' ` 0x17,0x09,0xef,0x7e,0xbf,0x54,0xcf,0x1f,' ` 0x82,0x56,0x61,0xc0,0xbf,0x54,0xcf,0x1f,' -` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +` 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00"' ) diff --git a/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 similarity index 81% rename from tools/topology/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 index 88a62e7e12e3..f0fda06be825 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_30hz_20db_48khz.m4 @@ -1,7 +1,7 @@ -# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP30HZ20dB48K_priv, +# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' @@ -14,5 +14,5 @@ CONTROLBYTES_PRIV(EQIIR_HP30HZ20dB48K_priv, ` 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0,' ` 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f,' ` 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f,' -` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +` 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00"' ) diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 index 5242fc4bc9e9..e0fb34a92288 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_0db_16khz.m4 @@ -1,5 +1,5 @@ # 40 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP40HZ0dB16K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 index ea28ad008dcd..a333f16e81db 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_0db_48khz.m4 @@ -1,5 +1,5 @@ # 40 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP40HZ0dB48K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 similarity index 81% rename from tools/topology/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 index d2eb866d312e..45c554148392 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_20db_16khz.m4 @@ -1,7 +1,7 @@ -# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP40HZ20dB16K_priv, +# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' @@ -14,5 +14,5 @@ CONTROLBYTES_PRIV(EQIIR_HP40HZ20dB16K_priv, ` 0x00,0x00,0x00,0x00,0xba,0xf2,0x67,0xc1,' ` 0xc3,0x0d,0x94,0x7e,0xff,0xbf,0xb8,0x1f,' ` 0x03,0x80,0x8e,0xc0,0xff,0xbf,0xb8,0x1f,' -` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +` 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00"' ) diff --git a/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 similarity index 81% rename from tools/topology/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 index d1e8d5f635c4..bdc8d97bcd17 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_40hz_20db_48khz.m4 @@ -1,7 +1,7 @@ -# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP40HZ20dB48K_priv, +# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' -` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' @@ -14,5 +14,5 @@ CONTROLBYTES_PRIV(EQIIR_HP40HZ20dB48K_priv, ` 0x00,0x00,0x00,0x00,0x4c,0xdf,0x78,0xc0,' ` 0x23,0xae,0x86,0x7f,0x12,0x1b,0xf5,0x1f,' ` 0xdb,0xc9,0x15,0xc0,0x12,0x1b,0xf5,0x1f,' -` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +` 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00"' ) diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 index 4d59264b2337..fecc8d5fc7ab 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_0db_16khz.m4 @@ -1,5 +1,5 @@ # 50 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP50HZ0dB16K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 similarity index 95% rename from tools/topology/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 index 11457d497d62..031a9b7fa352 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_0db_48khz.m4 @@ -1,5 +1,5 @@ # 50 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 27-Nov-2019 -CONTROLBYTES_PRIV(EQIIR_HP50HZ0dB48K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0xc0,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 similarity index 94% rename from tools/topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 index 40aba6f8ba4d..4c7df7301c88 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_20db_16khz.m4 @@ -1,5 +1,5 @@ # 50 Hz second order high-pass and +20 dB gain 13-Aug-2019 -CONTROLBYTES_PRIV(EQIIR_HP50HZ20dB16K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 similarity index 94% rename from tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 rename to tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 index d22924ef5a55..3aced8f0a592 100644 --- a/tools/topology/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 +++ b/tools/topology/topology1/m4/eq_iir_coef_highpass_50hz_20db_48khz.m4 @@ -1,5 +1,5 @@ # 50 Hz second order high-pass and +20 dB gain 18-Dec-2018 -CONTROLBYTES_PRIV(EQIIR_HP50HZ20dB48K_priv, +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, ` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' ` 0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' ` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' diff --git a/tools/topology/topology1/m4/eq_iir_coef_loudness.m4 b/tools/topology/topology1/m4/eq_iir_coef_loudness.m4 new file mode 100644 index 000000000000..ae419f260f18 --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_coef_loudness.m4 @@ -0,0 +1,33 @@ +# Loudness effect, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xcc,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xcc,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x9e,0x73,0x13,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00,' +` 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x5a,0xff,0xc0,0xb4,0xc1,0xff,0x7e,' +` 0x9f,0xb7,0xb4,0x11,0x2d,0x0a,0x35,0xdc,' +` 0x90,0xb0,0x16,0x12,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x21,0xf8,0xd5,0xc4,' +` 0xf0,0x6b,0x14,0x7b,0x27,0xb8,0x9d,0x0e,' +` 0xb9,0x24,0x18,0xe1,0xa9,0xf7,0x54,0x10,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xff,0xaf,0xc0,0xf4,0x17,0xa2,0x2d,0xf6,' +` 0x35,0xa4,0x1f,0x04,0x58,0x87,0x20,0xf9,' +` 0xb9,0x3e,0xcb,0x15,0xfc,0xff,0xff,0xff,' +` 0x7c,0x63,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/eq_iir_coef_pass.m4 b/tools/topology/topology1/m4/eq_iir_coef_pass.m4 new file mode 100644 index 000000000000..3c8d408ca2c7 --- /dev/null +++ b/tools/topology/topology1/m4/eq_iir_coef_pass.m4 @@ -0,0 +1,18 @@ +# Pass-through, created with example_iir_eq.m 30-Mar-2020 +CONTROLBYTES_PRIV(DEF_EQIIR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x00,0xe0,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,' +` 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x9e,0x73,0x13,0x20,' +` 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/google_ctc_audio_processing.m4 b/tools/topology/topology1/m4/google_ctc_audio_processing.m4 new file mode 100644 index 000000000000..d5823814e862 --- /dev/null +++ b/tools/topology/topology1/m4/google_ctc_audio_processing.m4 @@ -0,0 +1,68 @@ +divert(-1) + +dnl Define macro for CTC Processing effect widget +DECLARE_SOF_RT_UUID("google-ctc-audio-processing", google_ctc_audio_processing_uuid, +0xbf0e1bbc, 0xdc6a, 0x45fe, 0xbc, 0x90, 0x25, 0x54, 0xcb, 0x13, 0x7a, 0xb4) + +dnl N_GOOGLE_CTC_AUDIO_PROCESSING(name) +define(`N_GOOGLE_CTC_AUDIO_PROCESSING', `GOOGLE_CTC_AUDIO_PROCESSING'PIPELINE_ID`.'$1) + +dnl W_GOOGLE_CTC_AUDIO_PROCESSING(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_GOOGLE_CTC_AUDIO_PROCESSING', +`SectionVendorTuples."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(google_ctc_audio_processing_uuid) +` }' +`}' +`SectionData."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_uuid" {' +` tuples "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_w" {' +` tuples "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_str" {' +` tuples "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "GOOGLE_CTC_AUDIO_PROCESSING" +` }' +`}' +`SectionData."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_str_type" {' +` tuples "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_uuid"' +` "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_w"' +` "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_str"' +` "'N_GOOGLE_CTC_AUDIO_PROCESSING($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +` mixer [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/google_ctc_audio_processing_coef_default.m4 b/tools/topology/topology1/m4/google_ctc_audio_processing_coef_default.m4 new file mode 100644 index 000000000000..8b8283c0a21a --- /dev/null +++ b/tools/topology/topology1/m4/google_ctc_audio_processing_coef_default.m4 @@ -0,0 +1,6 @@ +CONTROLBYTES_PRIV(DEF_CTC_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0xd0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/google_hotword_detect.m4 b/tools/topology/topology1/m4/google_hotword_detect.m4 new file mode 100644 index 000000000000..dcf498481071 --- /dev/null +++ b/tools/topology/topology1/m4/google_hotword_detect.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for Google hotword detection widget +DECLARE_SOF_RT_UUID("google-hotword-detect", ghd_uuid, 0xc3c74249, 0x058e, 0x414f, + 0x82, 0x40, 0x4d, 0xa5, 0xf3, 0xfc, 0x23, 0x89) + +dnl N_GHD(name) +define(`N_GHD', `GHD'PIPELINE_ID`.'$1) + +dnl W_GHD(name, format, periods_sink, periods_source, detect_type, stream_name, core, kcontrols_list) +define(`W_GHD', +`SectionVendorTuples."'N_GHD($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(ghd_uuid) +` }' +`}' +`SectionData."'N_GHD($1)`_data_uuid" {' +` tuples "'N_GHD($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_GHD($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($7) +` }' +`}' +`SectionVendorTuples."'N_GHD($1)`_detect_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' STR(concat($5, _DETECT)) # UUID overrides the type matching. See get_drv. +` }' +`}' +`SectionData."'N_GHD($1)`_data_w" {' +` tuples "'N_GHD($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_GHD($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_GHD($1)`_data_str" {' +` tuples "'N_GHD($1)`_tuples_str"' +` tuples "'N_GHD($1)`_detect_process_tuples_str"' +`}' +`SectionWidget."'N_GHD($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` stream_name' STR($6) +` no_pm "true"' +` event_flags "15"' # trapping PRE/POST_PMU/PMD events +` event_type "1"' # 1 for DAPM event for detect component +` data [' +` "'N_GHD($1)`_data_uuid"' +` "'N_GHD($1)`_data_w"' +` "'N_GHD($1)`_data_str"' +` ]' +` bytes [' + $8 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/google_rtc_audio_processing.m4 b/tools/topology/topology1/m4/google_rtc_audio_processing.m4 new file mode 100644 index 000000000000..8489b6717ba7 --- /dev/null +++ b/tools/topology/topology1/m4/google_rtc_audio_processing.m4 @@ -0,0 +1,68 @@ +divert(-1) + +dnl Define macro for RTC Processing effect widget +DECLARE_SOF_RT_UUID("google-rtc-audio-processing", google_rtc_audio_processing_uuid, +0xb780a0a6, 0x269f, 0x466f, 0xb4, 0x77, 0x23, 0xdf, 0xa0, 0x5a, 0xf7, 0x58) + +dnl N_GOOGLE_RTC_AUDIO_PROCESSING(name) +define(`N_GOOGLE_RTC_AUDIO_PROCESSING', `GOOGLE_RTC_AUDIO_PROCESSING'PIPELINE_ID`.'$1) + +dnl W_GOOGLE_RTC_AUDIO_PROCESSING(name, format, periods_sink, periods_source, core, mixer_kcontrols_list, byte_kcontrols_list) +define(`W_GOOGLE_RTC_AUDIO_PROCESSING', +`SectionVendorTuples."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(google_rtc_audio_processing_uuid) +` }' +`}' +`SectionData."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_uuid" {' +` tuples "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_w" {' +` tuples "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_str" {' +` tuples "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "GRTCP" +` }' +`}' +`SectionData."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_str_type" {' +` tuples "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_uuid"' +` "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_w"' +` "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_str"' +` "'N_GOOGLE_RTC_AUDIO_PROCESSING($1)`_data_str_type"' +` ]' +` mixer [' + $6 +` ]' +` bytes [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/google_rtc_audio_processing_default.m4 b/tools/topology/topology1/m4/google_rtc_audio_processing_default.m4 new file mode 100644 index 000000000000..388cc9175a05 --- /dev/null +++ b/tools/topology/topology1/m4/google_rtc_audio_processing_default.m4 @@ -0,0 +1,10 @@ +# Google RTC Audio Processing initial config. +# Empty configuration +# sof_abi_hdr.size = 0 +# sof_abi_hdr.type = 0 (BINARY_DATA) +CONTROLBYTES_PRIV(GOOGLE_RTC_AUDIO_PROCESSING_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x50,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/igo_nr.m4 b/tools/topology/topology1/m4/igo_nr.m4 new file mode 100644 index 000000000000..1db0e5f6f8df --- /dev/null +++ b/tools/topology/topology1/m4/igo_nr.m4 @@ -0,0 +1,66 @@ +divert(-1) + +dnl Define macro for IGO_NR widget +DECLARE_SOF_RT_UUID("igo-nr", igo_nr_uuid, 0x696ae2bc, 0x2877, 0x11eb, 0xad, 0xc1, + 0x02, 0x42, 0xac, 0x12, 0x00, 0x02) + +dnl N_IGO_NR(name) +define(`N_IGO_NR', `IGONR'PIPELINE_ID`.'$1) + +dnl W_IGO_NR(name, format, periods_sink, periods_source, core, kcontrol0. kcontrol1...etc) +define(`W_IGO_NR', +`SectionVendorTuples."'N_IGO_NR($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(igo_nr_uuid) +` }' +`}' +`SectionData."'N_IGO_NR($1)`_data_uuid" {' +` tuples "'N_IGO_NR($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_IGO_NR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_IGO_NR($1)`_data_w" {' +` tuples "'N_IGO_NR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_IGO_NR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_IGO_NR($1)`_data_str" {' +` tuples "'N_IGO_NR($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_IGO_NR($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "IGO_NR" +` }' +`}' +`SectionData."'N_IGO_NR($1)`_data_str_type" {' +` tuples "'N_IGO_NR($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_IGO_NR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_IGO_NR($1)`_data_uuid"' +` "'N_IGO_NR($1)`_data_w"' +` "'N_IGO_NR($1)`_data_str"' +` "'N_IGO_NR($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' + +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/kpbm.m4 b/tools/topology/topology1/m4/kpbm.m4 new file mode 100644 index 000000000000..1b9835f0ec78 --- /dev/null +++ b/tools/topology/topology1/m4/kpbm.m4 @@ -0,0 +1,62 @@ +divert(-1) + +dnl Define macro for Key Phrase Buffer Manager(kpbm) widget +DECLARE_SOF_RT_UUID("kpb", kpb_uuid, 0xd8218443, 0x5ff3, 0x4a4c, + 0xb3, 0x88, 0x6c, 0xfe, 0x07, 0xb9, 0x56, 0x2e) + +dnl N_KPBM(name) +define(`N_KPBM', `KPBM'$2`.'$1) + +dnl W_KPBM(name, format, periods_sink, periods_source, pipeline_id, core, kcontrols_list) +define(`W_KPBM', +`SectionVendorTuples."'N_KPBM($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(kpb_uuid) +` }' +`}' +`SectionData."'N_KPBM($1)`_data_uuid" {' +` tuples "'N_KPBM($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_KPBM($1, $5)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($6) +` }' +`}' +`SectionData."'N_KPBM($1, $5)`_data_w" {' +` tuples "'N_KPBM($1, $5)`_tuples_w"' +`}' +`SectionVendorTuples."'N_KPBM($1, $5)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionVendorTuples."'N_KPBM($1)`_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "KPB" +` }' +`}' +`SectionData."'N_KPBM($1, $5)`_data_str" {' +` tuples "'N_KPBM($1, $5)`_tuples_str"' +` tuples "'N_KPBM($1)`_process_tuples_str"' +`}' +`SectionWidget."'N_KPBM($1, $5)`" {' +` index STR($5)' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_KPBM($1)`_data_uuid"' +` "'N_KPBM($1, $5)`_data_w"' +` "'N_KPBM($1, $5)`_data_str"' +` ]' +` bytes [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/mfcc.m4 b/tools/topology/topology1/m4/mfcc.m4 new file mode 100644 index 000000000000..16d7674478b1 --- /dev/null +++ b/tools/topology/topology1/m4/mfcc.m4 @@ -0,0 +1,65 @@ +divert(-1) + +dnl Define macro for MFCC widget +DECLARE_SOF_RT_UUID("mfcc", mfcc_uuid, 0xdb10a773, 0x1aa4, 0x4cea, + 0xa2, 0x1f, 0x2d, 0x57, 0xa5, 0xc9, 0x82, 0xeb) + +dnl N_MFCC(name) +define(`N_MFCC', `MFCC'PIPELINE_ID`.'$1) + +dnl W_MFCC(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_MFCC', +`SectionVendorTuples."'N_MFCC($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(mfcc_uuid) +` }' +`}' +`SectionData."'N_MFCC($1)`_data_uuid" {' +` tuples "'N_MFCC($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_MFCC($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_MFCC($1)`_data_w" {' +` tuples "'N_MFCC($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_MFCC($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_MFCC($1)`_data_str" {' +` tuples "'N_MFCC($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_MFCC($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "MFCC" +` }' +`}' +`SectionData."'N_MFCC($1)`_data_str_type" {' +` tuples "'N_MFCC($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_MFCC($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_MFCC($1)`_data_uuid"' +` "'N_MFCC($1)`_data_w"' +` "'N_MFCC($1)`_data_str"' +` "'N_MFCC($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/mfcc/mfcc_config.m4 b/tools/topology/topology1/m4/mfcc/mfcc_config.m4 new file mode 100644 index 000000000000..44ab37ba7360 --- /dev/null +++ b/tools/topology/topology1/m4/mfcc/mfcc_config.m4 @@ -0,0 +1,20 @@ +# Exported MFCC configuration 30-Sep-2022 +CONTROLBYTES_PRIV(DEF_MFCC_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x68,0x00,0x00,0x00,0x00,0x80,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x80,0x3e,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0xc3,0x35,0x00,0x2c,0xff,0xff,0x00,0x00,' +` 0x90,0x01,0xa0,0x00,0x00,0x00,0x14,0x00,' +` 0x0d,0x00,0x17,0x00,0x00,0x00,0x00,0x64,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,' +` 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/mixer.m4 b/tools/topology/topology1/m4/mixer.m4 new file mode 100644 index 000000000000..8b16a377a1e8 --- /dev/null +++ b/tools/topology/topology1/m4/mixer.m4 @@ -0,0 +1,55 @@ +divert(-1) + +dnl Define macro for Mixer widget +DECLARE_SOF_RT_UUID("mixer", mixer_uuid, 0xbc06c037, 0x12aa, 0x417c, + 0x9a, 0x97, 0x89, 0x28, 0x2e, 0x32, 0x1a, 0x76) + +dnl N_MIXER(name) +define(`N_MIXER', `MIXER'PIPELINE_ID`.'$1) + +dnl Pipe Buffer name in pipeline (pipeline, buffer) +define(`NPIPELINE_MIXER', `MIXER'$1`.'$2) + +dnl W_MIXER(name, format, periods_sink, periods_source, core) +define(`W_MIXER', +`SectionVendorTuples."'N_MIXER($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(mixer_uuid) +` }' +`}' +`SectionData."'N_MIXER($1)`_data_uuid" {' +` tuples "'N_MIXER($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_MIXER($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_MIXER($1)`_data_w" {' +` tuples "'N_MIXER($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_MIXER($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_MIXER($1)`_data_str" {' +` tuples "'N_MIXER($1)`_tuples_str"' +`}' +`SectionWidget."'N_MIXER($1)`" {' +` index "'PIPELINE_ID`"' +` type "mixer"' +` no_pm "true"' +` data [' +` "'N_MIXER($1)`_data_uuid"' +` "'N_MIXER($1)`_data_w"' +` "'N_MIXER($1)`_data_str"' +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/m4/mixercontrol.m4 b/tools/topology/topology1/m4/mixercontrol.m4 similarity index 100% rename from tools/topology/m4/mixercontrol.m4 rename to tools/topology/topology1/m4/mixercontrol.m4 diff --git a/tools/topology/topology1/m4/multiband_drc.m4 b/tools/topology/topology1/m4/multiband_drc.m4 new file mode 100644 index 000000000000..d8b3915e7196 --- /dev/null +++ b/tools/topology/topology1/m4/multiband_drc.m4 @@ -0,0 +1,68 @@ +divert(-1) + +dnl Define macro for Multiband DRC widget +DECLARE_SOF_RT_UUID("multiband_drc", multiband_drc_uuid, 0x0d9f2256, 0x8e4f, 0x47b3, + 0x84, 0x48, 0x23, 0x9a, 0x33, 0x4f, 0x11, 0x91); + +dnl N_MULTIBAND_DRC(name) +define(`N_MULTIBAND_DRC', `MULTIBAND_DRC'PIPELINE_ID`.'$1) + +dnl W_MULTIBAND_DRC(name, format, periods_sink, periods_source, core, kcontrol_list) +define(`W_MULTIBAND_DRC', +`SectionVendorTuples."'N_MULTIBAND_DRC($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(multiband_drc_uuid) +` }' +`}' +`SectionData."'N_MULTIBAND_DRC($1)`_data_uuid" {' +` tuples "'N_MULTIBAND_DRC($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_MULTIBAND_DRC($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_MULTIBAND_DRC($1)`_data_w" {' +` tuples "'N_MULTIBAND_DRC($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_MULTIBAND_DRC($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_MULTIBAND_DRC($1)`_data_str" {' +` tuples "'N_MULTIBAND_DRC($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_MULTIBAND_DRC($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "MULTIBAND_DRC" +` }' +`}' +`SectionData."'N_MULTIBAND_DRC($1)`_data_str_type" {' +` tuples "'N_MULTIBAND_DRC($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_MULTIBAND_DRC($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_MULTIBAND_DRC($1)`_data_uuid"' +` "'N_MULTIBAND_DRC($1)`_data_w"' +` "'N_MULTIBAND_DRC($1)`_data_str"' +` "'N_MULTIBAND_DRC($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +` mixer [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/multiband_drc_coef_default.m4 b/tools/topology/topology1/m4/multiband_drc_coef_default.m4 new file mode 100644 index 000000000000..4c3df7838d1a --- /dev/null +++ b/tools/topology/topology1/m4/multiband_drc_coef_default.m4 @@ -0,0 +1,81 @@ +# Exported Control Bytes 16-Aug-2023 +CONTROLBYTES_PRIV(MULTIBAND_DRC_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x02,0x00,0x00,0x00,0xa0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x02,0x00,0x00,0x03,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x7b,0x8e,0x88,0xfe,' +` 0x36,0x79,0x57,0x17,0x5f,0x19,0x6f,0x06,' +` 0xe8,0x79,0x67,0xd4,0x00,0x00,0x00,0x40,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x5f,0x6d,0x19,0xe7,0x39,0xc4,0xd4,0x50,' +` 0x0c,0x9b,0x09,0x24,0xad,0x76,0x82,0x9f,' +` 0x00,0x00,0x00,0x40,0xff,0xff,0xff,0xff,' +` 0x43,0x72,0x00,0x00,0xa1,0xe6,0x90,0xf9,' +` 0x18,0x86,0x98,0x2b,0xe3,0x32,0xef,0x00,' +` 0x4b,0xf7,0x20,0xf1,0x18,0x69,0xc6,0x28,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xf4,0x64,0xf6,0xdb,0x53,0x89,0x7d,0x60,' +` 0x5c,0x14,0xf2,0x0a,0x84,0x0d,0x78,0xdc,' +` 0xda,0xef,0x21,0x1c,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2,' +` 0x3e,0x77,0xa1,0x7d,0x95,0xc1,0x02,0x00,' +` 0x2a,0x83,0x05,0x00,0x95,0xc1,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x34,0x7d,0xd3,0x3e,0x99,0x05,0x59,0x82,' +` 0x34,0x7d,0xd3,0x3e,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x2d,0x3a,0xcd,0xd3,' +` 0xc0,0xf5,0x82,0x68,0x05,0xf4,0xeb,0x00,' +` 0x0a,0xe8,0xd7,0x01,0x05,0xf4,0xeb,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68,' +` 0xe5,0x6e,0x2d,0x35,0x36,0x22,0xa5,0x95,' +` 0xe5,0x6e,0x2d,0x35,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x2d,0x3a,0xcd,0xd3,' +` 0xc0,0xf5,0x82,0x68,0x05,0xf4,0xeb,0x00,' +` 0x0a,0xe8,0xd7,0x01,0x05,0xf4,0xeb,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68,' +` 0xe5,0x6e,0x2d,0x35,0x36,0x22,0xa5,0x95,' +` 0xe5,0x6e,0x2d,0x35,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e,' +` 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00,' +` 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05,' +` 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00,' +` 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01,' +` 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01,' +` 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff,' +` 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00,' +` 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00,' +` 0x5b,0x91,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e,' +` 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00,' +` 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05,' +` 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00,' +` 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01,' +` 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01,' +` 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff,' +` 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00,' +` 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00,' +` 0x5b,0x91,0x00,0x00,0x03,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e,' +` 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00,' +` 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05,' +` 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00,' +` 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01,' +` 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01,' +` 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff,' +` 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00,' +` 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00,' +` 0x5b,0x91,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/multiband_drc_coef_passthrough.m4 b/tools/topology/topology1/m4/multiband_drc_coef_passthrough.m4 new file mode 100644 index 000000000000..e397143d7361 --- /dev/null +++ b/tools/topology/topology1/m4/multiband_drc_coef_passthrough.m4 @@ -0,0 +1,70 @@ +# Exported Control Bytes 16-Aug-2023 +CONTROLBYTES_PRIV(MULTIBAND_DRC_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xf4,0x01,0x00,0x00,0x00,0xa0,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf4,0x01,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x7b,0x8e,0x88,0xfe,' +` 0x36,0x79,0x57,0x17,0x5f,0x19,0x6f,0x06,' +` 0xe8,0x79,0x67,0xd4,0x00,0x00,0x00,0x40,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x5f,0x6d,0x19,0xe7,0x39,0xc4,0xd4,0x50,' +` 0x0c,0x9b,0x09,0x24,0xad,0x76,0x82,0x9f,' +` 0x00,0x00,0x00,0x40,0xff,0xff,0xff,0xff,' +` 0x43,0x72,0x00,0x00,0xa1,0xe6,0x90,0xf9,' +` 0x18,0x86,0x98,0x2b,0xe3,0x32,0xef,0x00,' +` 0x4b,0xf7,0x20,0xf1,0x18,0x69,0xc6,0x28,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0xf4,0x64,0xf6,0xdb,0x53,0x89,0x7d,0x60,' +` 0x5c,0x14,0xf2,0x0a,0x84,0x0d,0x78,0xdc,' +` 0xda,0xef,0x21,0x1c,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2,' +` 0x3e,0x77,0xa1,0x7d,0x95,0xc1,0x02,0x00,' +` 0x2a,0x83,0x05,0x00,0x95,0xc1,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d,' +` 0x34,0x7d,0xd3,0x3e,0x99,0x05,0x59,0x82,' +` 0x34,0x7d,0xd3,0x3e,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e,' +` 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00,' +` 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05,' +` 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00,' +` 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01,' +` 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01,' +` 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff,' +` 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00,' +` 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00,' +` 0x5b,0x91,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e,' +` 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00,' +` 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05,' +` 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00,' +` 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01,' +` 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01,' +` 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff,' +` 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00,' +` 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00,' +` 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00,' +` 0x5b,0x91,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/muxdemux.m4 b/tools/topology/topology1/m4/muxdemux.m4 new file mode 100644 index 000000000000..047e0177e783 --- /dev/null +++ b/tools/topology/topology1/m4/muxdemux.m4 @@ -0,0 +1,93 @@ +divert(-1) + +dnl Define macro for mux/demux widget +DECLARE_SOF_RT_UUID("mux", mux_uuid, 0xc607ff4d, 0x9cb6, 0x49dc, + 0xb6, 0x78, 0x7d, 0xa3, 0xc6, 0x3e, 0xa5, 0x57) +DECLARE_SOF_RT_UUID("demux", demux_uuid, 0xc4b26868, 0x1430, 0x470e, + 0xa0, 0x89, 0x15, 0xd1, 0xc7, 0x7f, 0x85, 0x1a) + +dnl Hard coded values for mux/demux config blob +define(mux_sof_magic, 0x00464F53) +define(mux_stream_struct_size, 16) +define(mux_config_struct_size, 8) + +dnl Fill bytes of struct mux_stream_config (mux.h) +dnl reserved fields in the struct are set to 0 +define(`ROUTE_MATRIX', + `PRINT_BYTES_4($1),PRINT_BYTE(0),PRINT_BYTE($2),PRINT_BYTE($3),'dnl +`PRINT_BYTE($4),' + `PRINT_BYTE($5),PRINT_BYTE($6),PRINT_BYTE($7),PRINT_BYTE($8),'dnl +`PRINT_BYTE($9),PRINT_BYTE(0),PRINT_BYTE(0),PRINT_BYTE(0)') + +dnl Fill bytes of mux/demux config binary blob +dnl blob is made of sof_abi_hdr (header.h), sof_mux_config (mux.h) and +dnl list of ROUTE_MATRIXes. +dnl reserved fields in the struct are set to 0 +define(`MUXDEMUX_CONFIG', +`SectionData.STR($1) {' +`bytes "'`PRINT_BYTES_4(mux_sof_magic),PRINT_BYTES_4(0),' + `PRINT_BYTES_4(eval(mux_config_struct_size + (mux_stream_struct_size * $2))),'dnl +`PRINT_BYTES_4(SOF_ABI_VERSION),' + `PRINT_BYTES_4(0),PRINT_BYTES_4(0),' + `PRINT_BYTES_4(0),PRINT_BYTES_4(0),' + `PRINT_BYTES_2(0),PRINT_BYTES_2(0),PRINT_BYTES_2($2),PRINT_BYTES_2(0),' + `$3'`"' + `}' +) + +dnl N_MUXDEMUX(name) +define(`N_MUXDEMUX', `MUXDEMUX'PIPELINE_ID`.'$1) + +dnl W_MUXDEMUX(name, mux/demux, format, periods_sink, periods_source, core, kcontrol_list) +define(`W_MUXDEMUX', +`SectionVendorTuples."'N_MUXDEMUX($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +`ifelse(`$2', `0',` SOF_TKN_COMP_UUID' STR(mux_uuid),` SOF_TKN_COMP_UUID' STR(demux_uuid))' +` }' +`}' +`SectionData."'N_MUXDEMUX($1)`_data_uuid" {' +` tuples "'N_MUXDEMUX($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_MUXDEMUX($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($4) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($5) +` SOF_TKN_COMP_CORE_ID' STR($6) +` }' +`}' +`SectionData."'N_MUXDEMUX($1)`_data_w" {' +` tuples "'N_MUXDEMUX($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_MUXDEMUX($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($3) +` }' +`}' +`SectionVendorTuples."'N_MUXDEMUX($1)`_mux_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +`ifelse(`$2', `0', ` SOF_TKN_PROCESS_TYPE' "MUX", ` SOF_TKN_PROCESS_TYPE' "DEMUX")' +` }' +`}' +`SectionData."'N_MUXDEMUX($1)`_data_str" {' +` tuples "'N_MUXDEMUX($1)`_tuples_str"' +` tuples "'N_MUXDEMUX($1)`_mux_process_tuples_str"' +`}' +`SectionWidget."'N_MUXDEMUX($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_MUXDEMUX($1)`_data_uuid"' +` "'N_MUXDEMUX($1)`_data_w"' +` "'N_MUXDEMUX($1)`_data_str"' +` ]' +` bytes [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/pcm.m4 b/tools/topology/topology1/m4/pcm.m4 new file mode 100644 index 000000000000..e4c6ca5caabc --- /dev/null +++ b/tools/topology/topology1/m4/pcm.m4 @@ -0,0 +1,212 @@ +divert(-1) + +dnl Define the macro for PCM playback/capture/capabilities +DECLARE_SOF_RT_UUID("host", host_uuid, 0x8b9d100c, 0x6d78, 0x418f, + 0x90, 0xa3, 0xe0, 0xe8, 0x05, 0xd0, 0x85, 0x2b) + +dnl N_PCM(name) +define(`N_PCMP', `PCM'$1`P') +define(`N_PCMC', `PCM'$1`C') + +dnl W_PCM_PLAYBACK(pcm, stream, periods_sink, periods_source, core) +dnl PCM platform configuration +define(`W_PCM_PLAYBACK', +`SectionVendorTuples."'N_PCMP($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(host_uuid) +` }' +`}' +`SectionData."'N_PCMP($1)`_data_uuid" {' +` tuples "'N_PCMP($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_PCMP($1)`_tuples_w_comp" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_PCMP($1)`_data_w_comp" {' +` tuples "'N_PCMP($1)`_tuples_w_comp"' +`}' +`SectionWidget."'N_PCMP($1)`" {' +` index "'PIPELINE_ID`"' +` type "aif_in"' +` no_pm "true"' +` stream_name "'$2` '$1`"' +` data [' +` "'N_PCMP($1)`_data_uuid"' +` "'N_PCMP($1)`_data_w_comp"' +` ]' +`}') + + +dnl W_PCM_CAPTURE(pcm, stream, periods_sink, periods_source, core) +define(`W_PCM_CAPTURE', +`SectionVendorTuples."'N_PCMC($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(host_uuid) +` }' +`}' +`SectionData."'N_PCMC($1)`_data_uuid" {' +` tuples "'N_PCMC($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_PCMC($1)`_tuples_w_comp" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_PCMC($1)`_data_w_comp" {' +` tuples "'N_PCMC($1)`_tuples_w_comp"' +`}' +`SectionWidget."'N_PCMC($1)`" {' +` index "'PIPELINE_ID`"' +` type "aif_out"' +` no_pm "true"' +` stream_name "'$2` '$1`"' +` data [' +` "'N_PCMC($1)`_data_uuid"' +` "'N_PCMC($1)`_data_w_comp"' +` ]' +`}') + +dnl PCM_CAPABILITIES(name, formats, rate_min, rate_max, channels_min, channels_max, periods_min, periods_max, period_size_min, period_size_max, buffer_size_min, buffer_size_max) +define(`PCM_CAPABILITIES', +`SectionPCMCapabilities.STR($1) {' +`' +` formats "$2"' +` rate_min STR($3)' +` rate_max STR($4)' +` channels_min STR($5)' +` channels_max STR($6)' +` periods_min STR($7)' +` periods_max STR($8)' +` period_size_min STR($9)' +` period_size_max STR($10)' +` buffer_size_min STR($11)' +` buffer_size_max STR($12)' +`}') + +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) +define(`PCM_PLAYBACK_ADD', +`ifelse(`$#', `3', +PCM_PLAYBACK_ADD_COMMON($1, $2, $3, false), +`fatal_error(`Invalid parameters ($#) to PCM_PLAYBACK_ADD')')' +) + +dnl COMPR_PLAYBACK_ADD(name, pcm_id, playback) +define(`COMPR_PLAYBACK_ADD', +`ifelse(`$#', `3', +PCM_PLAYBACK_ADD_COMMON($1, $2, $3, true), +`fatal_error(`Invalid parameters ($#) to PCM_PLAYBACK_COMPR_ADD')')' +) + +dnl PCM_PLAYBACK_ADD_COMMON(name, pcm_id, playback, compress) +define(`PCM_PLAYBACK_ADD_COMMON', +`ifelse(`$#', `4', +`SectionPCM.STR($1) {' +`' +` # used for binding to the PCM' +` id STR($2)' +`' +` dai.STR($1 $2) {' +` id STR($2)' +` }' +`' +` pcm."playback" {' +`' +` capabilities STR($3)' +` }' +`' +` compress STR($4)' +`}', `fatal_error(`Invalid parameters ($#) to PCM_PLAYBACK_ADD_COMMON')')' +) + +dnl PCM_CAPTURE_ADD_COMMON(name, pcm_id, capture, lp, compress) +define(`PCM_CAPTURE_ADD_COMMON', +`ifelse(`$4', `1', +`SectionVendorTuples."$1_tuples_w" {' +` tokens "sof_stream_tokens"' +` tuples."bool" {' +` SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 "true"' +` }' +`}' +`' +`SectionData."$1_data_w" {' +` tuples "$1_tuples_w"' +`}', `')' +`' +`SectionPCM.STR($1) {' +`' +` # used for binding to the PCM' +` id STR($2)' +`' +` dai.STR($1 $2) {' +` id STR($2)' +` }' +`' +` pcm."capture" {' +`' +` capabilities STR($3)' +` }' +`' +` compress STR($5)' +`ifelse(`$4', `1', +` data [' +` "$1_data_w"' +` ]', `')' +`}' +) + +dnl PCM_CAPTURE_ADD(name, pcm_id, capture) +define(`PCM_CAPTURE_ADD', +`ifelse(`$#', `3', +PCM_CAPTURE_ADD_COMMON($1, $2, $3, 0, false), +`fatal_error(`Invalid parameters ($#) to PCM_CAPTURE_ADD')')' +) + +dnl COMPR_CAPTURE_ADD(name, pcm_id, capture) +define(`COMPR_CAPTURE_ADD', +`ifelse(`$#', `3', +PCM_CAPTURE_ADD_COMMON($1, $2, $3, 0, true), +`fatal_error(`Invalid parameters ($#) to COMPR_CAPTURE_ADD')')' +) + +dnl PCM_CAPTURE_LP_ADD(name, pcm_id, capture) +define(`PCM_CAPTURE_LP_ADD', +`ifelse(`$#', `3', +PCM_CAPTURE_ADD_COMMON($1, $2, $3, 1, false), +`fatal_error(`Invalid parameters ($#) to PCM_CAPTURE_LP_ADD')')' +) + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +define(`PCM_DUPLEX_ADD', +`ifelse(`$#', `4', +`SectionPCM.STR($1) {' +`' +` # used for binding to the PCM' +` id STR($2)' +`' +` dai.STR($1 $2) {' +` id STR($2)' +` }' +`' +` pcm."capture" {' +`' +` capabilities STR($4)' +` }' +`' +` pcm."playback" {' +`' +` capabilities STR($3)' +` }' +`}', `fatal_error(`Invalid parameters ($#) to PCM_DUPLEX_ADD')')' +) + +divert(0)dnl diff --git a/tools/topology/topology1/m4/pga.m4 b/tools/topology/topology1/m4/pga.m4 new file mode 100644 index 000000000000..44ab473ccfcc --- /dev/null +++ b/tools/topology/topology1/m4/pga.m4 @@ -0,0 +1,57 @@ +divert(-1) + +dnl Define macro for PGA widget +DECLARE_SOF_RT_UUID("volume", volume_uuid, 0xb77e677e, 0x5ff4, 0x4188, + 0xaf, 0x14, 0xfb, 0xa8, 0xbd, 0xbf, 0x86, 0x82) + +dnl N_PGA(name) +define(`N_PGA', `PGA'PIPELINE_ID`.'$1) + +dnl W_PGA(name, format, periods_sink, periods_source, core, kcontrol0. kcontrol1...etc) +define(`W_PGA', +`SectionVendorTuples."'N_PGA($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(volume_uuid) +` }' +`}' +`SectionData."'N_PGA($1)`_data_uuid" {' +` tuples "'N_PGA($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_PGA($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($6) +` }' +`}' +`SectionData."'N_PGA($1)`_data_w" {' +` tuples "'N_PGA($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_PGA($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_PGA($1)`_data_str" {' +` tuples "'N_PGA($1)`_tuples_str"' +`}' +`SectionWidget.ifdef(`PGA_NAME', "`PGA_NAME'", "`N_PGA($1)'") {' +` index "'PIPELINE_ID`"' +` type "pga"' +` no_pm "true"' +` data [' +` "'N_PGA($1)`_data_uuid"' +` "'N_PGA($1)`_data_w"' +` "'N_PGA($1)`_data_str"' +` "'$5`"' +` ]' +` mixer [' + $7 +` ]' + +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/pipeline.m4 b/tools/topology/topology1/m4/pipeline.m4 new file mode 100644 index 000000000000..3b1b999ee0f6 --- /dev/null +++ b/tools/topology/topology1/m4/pipeline.m4 @@ -0,0 +1,208 @@ +divert(-1) + +# list of generic scheduling time domains +define(`SCHEDULE_TIME_DOMAIN_DMA', 0) +define(`SCHEDULE_TIME_DOMAIN_TIMER', 1) + +# default number of DAI periods +define(`DAI_DEFAULT_PERIODS', 2) + +# default stereo channel map +ifdef(`VOLUME_CHANNEL_MAP', , `define(`VOLUME_CHANNEL_MAP', LIST(` ', + KCONTROL_CHANNEL(FL, 1, 0), + KCONTROL_CHANNEL(FR, 1, 1)))') + +ifdef(`SWITCH_CHANNEL_MAP', , `define(`SWITCH_CHANNEL_MAP', LIST(` ', + KCONTROL_CHANNEL(FL, 2, 0), + KCONTROL_CHANNEL(FR, 2, 1)))') + +dnl Define macro for pipeline widget + +dnl Pipeline name) +define(`N_PIPELINE', `PIPELINE.'PIPELINE_ID`.'$1) + +dnl W_PIPELINE(stream, period, priority, core, initiator, platform) +define(`W_PIPELINE', +`SectionVendorTuples."'N_PIPELINE($1)`_tuples" {' +` tokens "sof_sched_tokens"' +` tuples."word" {' +` SOF_TKN_SCHED_PERIOD' STR($2) +` SOF_TKN_SCHED_PRIORITY' STR($3) +` SOF_TKN_SCHED_CORE' STR($4) +` SOF_TKN_SCHED_FRAMES' "0" +` SOF_TKN_SCHED_TIME_DOMAIN' STR($5) +` SOF_TKN_SCHED_DYNAMIC_PIPELINE' ifdef(`DYNAMIC', "1", ifelse(DYNAMIC_PIPE, `1', "1", "0")) +` }' +`}' +`SectionData."'N_PIPELINE($1)`_data" {' +` tuples "'N_PIPELINE($1)`_tuples"' +`}' +`SectionWidget."'N_PIPELINE($1)`" {' +` index "'PIPELINE_ID`"' +` type "scheduler"' +` no_pm "true"' +` stream_name "'$1`"' +` data [' +` "'N_PIPELINE($1)`_data"' +` "'$6`"' +` ]' +`}') + +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, dynamic) +define(`PIPELINE_PCM_ADD', +`ifelse(eval(`$# > 10'), `1', +`undefine(`PCM_ID')' +`undefine(`PIPELINE_ID')' +`undefine(`PIPELINE_CHANNELS')' +`undefine(`PIPELINE_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`PCM_MIN_RATE')' +`undefine(`PCM_MAX_RATE')' +`undefine(`PIPELINE_RATE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`DAI_FORMAT')' +`undefine(`SCHED_COMP')' +`undefine(`DYNAMIC_PIPE')' +`define(`PIPELINE_ID', $2)' +`define(`PCM_ID', $3)' +`define(`PIPELINE_CHANNELS', $4)' +`define(`PIPELINE_FORMAT', $5)' +`define(`SCHEDULE_PERIOD', $6)' +`define(`SCHEDULE_PRIORITY', $7)' +`define(`SCHEDULE_CORE', $8)' +`define(`PCM_MIN_RATE', $9)' +`define(`PCM_MAX_RATE', $10)' +`define(`PIPELINE_RATE', $11)' +`define(`SCHEDULE_TIME_DOMAIN', $12)' +`define(`DAI_FORMAT', $5)' +`define(`SCHED_COMP', $13)' +`define(`DYNAMIC_PIPE', $14)' +`ifdef(`DAI_PERIODS', `', `define(`DAI_PERIODS', DAI_DEFAULT_PERIODS)')' +`include($1)' +`DEBUG_PCM_ADD($1, $3)' +`undefine(`PCM_ID')' +`undefine(`PIPELINE_ID')' +`undefine(`PIPELINE_CHANNELS')' +`undefine(`PIPELINE_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`PCM_MIN_RATE')' +`undefine(`PCM_MAX_RATE')' +`undefine(`PIPELINE_RATE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`DAI_FORMAT')' +`undefine(`SCHED_COMP')' +`undefine(`DYNAMIC_PIPE')' +,`fatal_error(`Invalid parameters ($#) to PIPELINE_PCM_ADD')')' +) + +dnl PIPELINE_PCM_DAI_ADD(pipeline, +dnl pipe id, pcm, max channels, format, +dnl period, priority, core, +dnl dai type, dai_index, dai format, +dnl periods, time_domain) +define(`PIPELINE_PCM_DAI_ADD', +`ifelse(`$#', `15', +`undefine(`PCM_ID')' +`undefine(`PIPELINE_ID')' +`undefine(`PIPELINE_CHANNELS')' +`undefine(`PIPELINE_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`DAI_TYPE')' +`undefine(`DAI_INDEX')' +`undefine(`DAI_FORMAT')' +`undefine(`DAI_PERIODS')' +`undefine(`PCM_MIN_RATE')' +`undefine(`PCM_MAX_RATE')' +`undefine(`PIPELINE_RATE')' +`define(`PIPELINE_ID', $2)' +`define(`PCM_ID', $3)' +`define(`PIPELINE_CHANNELS', $4)' +`define(`PIPELINE_FORMAT', $5)' +`define(`SCHEDULE_PERIOD', $6)' +`define(`SCHEDULE_PRIORITY', $7)' +`define(`SCHEDULE_CORE', $8)' +`define(`SCHEDULE_TIME_DOMAIN', $16)' +`define(`DAI_TYPE', STR($9))' +`define(`DAI_INDEX', STR($10))' +`define(`DAI_FORMAT', $11)' +`define(`DAI_PERIODS', $12)' +`define(`DAI_NAME', $9$10)' +`define(`PCM_MIN_RATE', $13)' +`define(`PCM_MAX_RATE', $14)' +`define(`PIPELINE_RATE', $15)' +`include($1)' +`undefine(`PCM_ID')' +`undefine(`PIPELINE_ID')' +`undefine(`PIPELINE_CHANNELS')' +`undefine(`PIPELINE_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`DAI_TYPE')' +`undefine(`DAI_INDEX')' +`undefine(`DAI_FORMAT')' +`undefine(`DAI_PERIODS')' +`undefine(`PCM_MIN_RATE')' +`undefine(`PCM_MAX_RATE')' +`undefine(`PIPELINE_RATE')' +,`fatal_error(`Invalid parameters ($#) to PIPELINE_PCM_DAI_ADD')')' +) + +dnl PIPELINE_ADD(pipeline, +dnl pipe id, max channels, format, +dnl period, priority, core, +dnl sched_comp, time_domain, +dnl pcm_min_rate, pcm_max_rate, pipeline_rate, dynamic) +define(`PIPELINE_ADD', +`ifelse(`$#', `12', +`undefine(`PIPELINE_ID')' +`undefine(`PIPELINE_CHANNELS')' +`undefine(`PIPELINE_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`PCM_MIN_RATE')' +`undefine(`PCM_MAX_RATE')' +`undefine(`PIPELINE_RATE')' +`undefine(`DYNAMIC_PIPE')' +`define(`PIPELINE_ID', $2)' +`define(`PIPELINE_CHANNELS', $3)' +`define(`PIPELINE_FORMAT', $4)' +`define(`SCHEDULE_PERIOD', $5)' +`define(`SCHEDULE_PRIORITY', $6)' +`define(`SCHEDULE_CORE', $7)' +`define(`SCHEDULE_TIME_DOMAIN', $9)' +`define(`SCHED_COMP', $8)' +`define(`PCM_MIN_RATE', $10)' +`define(`PCM_MAX_RATE', $11)' +`define(`PIPELINE_RATE', $12)' +`define(`DYNAMIC_PIPE', $13)' +`include($1)' +`undefine(`PIPELINE_ID')' +`undefine(`PIPELINE_CHANNELS')' +`undefine(`PIPELINE_FORMAT')' +`undefine(`SCHEDULE_PERIOD')' +`undefine(`SCHEDULE_PRIORITY')' +`undefine(`SCHEDULE_CORE')' +`undefine(`SCHEDULE_TIME_DOMAIN')' +`undefine(`PCM_MIN_RATE')' +`undefine(`PCM_MAX_RATE')' +`undefine(`PIPELINE_RATE')' +`undefine(`DYNAMIC_PIPE')' +,`fatal_error(`Invalid parameters ($#) to PIPELINE_ADD')')' +) + +divert(0)dnl diff --git a/tools/topology/topology1/m4/rtnr.m4 b/tools/topology/topology1/m4/rtnr.m4 new file mode 100644 index 000000000000..b6c32274a23e --- /dev/null +++ b/tools/topology/topology1/m4/rtnr.m4 @@ -0,0 +1,68 @@ +divert(-1) + +dnl Define macro for RTNR effect widget +DECLARE_SOF_RT_UUID("rtnr", rtnr_uuid, 0x5c7ca334, 0xe15d, 0x11eb, 0xba, 0x80, + 0x02, 0x42, 0xac, 0x13, 0x00, 0x04) + +dnl RTNR(name) +define(`N_RTNR', `RTNR'PIPELINE_ID`.'$1) + +dnl W_RTNR(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_RTNR', +`SectionVendorTuples."'N_RTNR($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(rtnr_uuid) +` }' +`}' +`SectionData."'N_RTNR($1)`_data_uuid" {' +` tuples "'N_RTNR($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_RTNR($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_RTNR($1)`_data_w" {' +` tuples "'N_RTNR($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_RTNR($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_RTNR($1)`_data_str" {' +` tuples "'N_RTNR($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_RTNR($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "RTNR" +` }' +`}' +`SectionData."'N_RTNR($1)`_data_str_type" {' +` tuples "'N_RTNR($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_RTNR($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_RTNR($1)`_data_uuid"' +` "'N_RTNR($1)`_data_w"' +` "'N_RTNR($1)`_data_str"' +` "'N_RTNR($1)`_data_str_type"' +` ]' +` bytes [' + $6 +` ]' +` mixer [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/smart_amp.m4 b/tools/topology/topology1/m4/smart_amp.m4 new file mode 100644 index 000000000000..1eac3af9dc40 --- /dev/null +++ b/tools/topology/topology1/m4/smart_amp.m4 @@ -0,0 +1,60 @@ +divert(-1) + +dnl Define macro for smart_amp(Smart Amplifier) widget + +dnl SMART_AMP name) +define(`N_SMART_AMP', `SMART_AMP'PIPELINE_ID`.'$1) + +dnl W_SMART_AMP(name, uuid, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_SMART_AMP', +`SectionVendorTuples."'N_SMART_AMP($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR($2) +` }' +`}' +`SectionData."'N_SMART_AMP($1)`_data_uuid" {' +` tuples "'N_SMART_AMP($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_SMART_AMP($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($4) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($5) +` SOF_TKN_COMP_CORE_ID' STR($6) +` }' +`}' +`SectionData."'N_SMART_AMP($1)`_data_w" {' +` tuples "'N_SMART_AMP($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_SMART_AMP($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($3) +` }' +`}' +`SectionVendorTuples."'N_SMART_AMP($1)`_process_tuples_str" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "SMART_AMP" +` }' +`}' +`SectionData."'N_SMART_AMP($1)`_data_str" {' +` tuples "'N_SMART_AMP($1)`_tuples_str"' +` tuples "'N_SMART_AMP($1)`_process_tuples_str"' +`}' +`SectionWidget."'N_SMART_AMP($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_SMART_AMP($1)`_data_uuid"' +` "'N_SMART_AMP($1)`_data_w"' +` "'N_SMART_AMP($1)`_data_str"' +` ]' +` bytes [' + $7 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/src.m4 b/tools/topology/topology1/m4/src.m4 new file mode 100644 index 000000000000..5562a9b10cf0 --- /dev/null +++ b/tools/topology/topology1/m4/src.m4 @@ -0,0 +1,52 @@ +divert(-1) + +dnl Defines the macro for SRC widget +DECLARE_SOF_RT_UUID("src", src_uuid, 0xc1c5326d, 0x8390, 0x46b4, + 0xaa, 0x47, 0x95, 0xc3, 0xbe, 0xca, 0x65, 0x50) + +dnl SRC name) +define(`N_SRC', `SRC'PIPELINE_ID`.'$1) + +dnl W_SRC(name, format, periods_sink, periods_source, data) +define(`W_SRC', +`SectionVendorTuples."'N_SRC($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(src_uuid) +` }' +`}' +`SectionData."'N_SRC($1)`_data_uuid" {' +` tuples "'N_SRC($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_SRC($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` }' +`}' +`SectionData."'N_SRC($1)`_data_w" {' +` tuples "'N_SRC($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_SRC($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_SRC($1)`_data_str" {' +` tuples "'N_SRC($1)`_tuples_str"' +`}' +`SectionWidget."'N_SRC($1)`" {' +` index "'PIPELINE_ID`"' +` type "src"' +` no_pm "true"' +` data [' +` "'N_SRC($1)`_data_uuid"' +` "'N_SRC($1)`_data_w"' +` "'N_SRC($1)`_data_str"' +` "'$5`"' +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/tdfb.m4 b/tools/topology/topology1/m4/tdfb.m4 new file mode 100644 index 000000000000..df1fa9f56d10 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb.m4 @@ -0,0 +1,73 @@ +divert(-1) + +dnl Define macro for TDFB (time domain fixed beamformer) widget +DECLARE_SOF_RT_UUID("tdfb", tdfb_uuid, 0xdd511749, 0xd9fa, 0x455c, + 0xb3, 0xa7, 0x13, 0x58, 0x56, 0x93, 0xf1, 0xaf) + +dnl TDFB(name) +define(`N_TDFB', `TDFB'PIPELINE_ID`.'$1) + +dnl W_TDFB(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_TDFB', +`SectionVendorTuples."'N_TDFB($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(tdfb_uuid) +` }' +`}' +`SectionData."'N_TDFB($1)`_data_uuid" {' +` tuples "'N_TDFB($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_TDFB($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionData."'N_TDFB($1)`_data_w" {' +` tuples "'N_TDFB($1)`_tuples_w"' +`}' +`SectionVendorTuples."'N_TDFB($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_TDFB($1)`_data_str" {' +` tuples "'N_TDFB($1)`_tuples_str"' +`}' +`SectionVendorTuples."'N_TDFB($1)`_tuples_str_type" {' +` tokens "sof_process_tokens"' +` tuples."string" {' +` SOF_TKN_PROCESS_TYPE' "TDFB" +` }' +`}' +`SectionData."'N_TDFB($1)`_data_str_type" {' +` tuples "'N_TDFB($1)`_tuples_str_type"' +`}' +`SectionWidget."'N_TDFB($1)`" {' +` index "'PIPELINE_ID`"' +` type "effect"' +` no_pm "true"' +` data [' +` "'N_TDFB($1)`_data_uuid"' +` "'N_TDFB($1)`_data_w"' +` "'N_TDFB($1)`_data_str"' +` "'N_TDFB($1)`_data_str_type"' +` ]' +` mixer [' + $6 + $7 +` ]' +` enum [' + $8 + $9 +` ]' +` bytes [' + $10 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_azm180_150_12el0_0_12deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_azm180_150_12el0_0_12deg_16khz.m4 new file mode 100644 index 000000000000..ef0f8381fc32 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_azm180_150_12el0_0_12deg_16khz.m4 @@ -0,0 +1,979 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x5c,0x1e,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x5c,0x1e,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x08,0x00,0x0c,0x00,0x01,0x00,' +` 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xfe,0xfc,0xfe,0xdc,0xfc,0xb9,0xff,' +` 0xaa,0xf9,0xd7,0x00,0x35,0xf4,0x7d,0x05,' +` 0xd9,0xe6,0x1e,0x2c,0x5a,0x63,0x3a,0xdf,' +` 0x8d,0x08,0xb6,0xf0,0x24,0x02,0xc3,0xf6,' +` 0xe7,0xff,0x6f,0xfa,0x81,0xfe,0x40,0xfc,' +` 0x9b,0xfe,0x56,0xfe,0xb7,0xff,0xf4,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf3,0xff,0x68,0xff,' +` 0xa3,0xfe,0xd9,0xfd,0x46,0xfd,0xab,0xfc,' +` 0xd0,0xfc,0xb4,0xfb,0x6a,0xfb,0x7b,0xfa,' +` 0xd0,0xf9,0x3d,0xf9,0xfb,0xf8,0x59,0x78,' +` 0x41,0xf9,0xb6,0xf9,0x5f,0xfa,0x3d,0xfb,' +` 0x12,0xfc,0xe3,0xfc,0xb3,0xfd,0x04,0xfe,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xfe,0xfc,0xfe,0xdc,0xfc,0xb9,0xff,' +` 0xaa,0xf9,0xd7,0x00,0x35,0xf4,0x7d,0x05,' +` 0xd9,0xe6,0x1e,0x2c,0x5a,0x63,0x3a,0xdf,' +` 0x8d,0x08,0xb6,0xf0,0x24,0x02,0xc3,0xf6,' +` 0xe7,0xff,0x6f,0xfa,0x81,0xfe,0x40,0xfc,' +` 0x9b,0xfe,0x56,0xfe,0xb7,0xff,0xf4,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf3,0xff,0x68,0xff,' +` 0xa3,0xfe,0xd9,0xfd,0x46,0xfd,0xab,0xfc,' +` 0xd0,0xfc,0xb4,0xfb,0x6a,0xfb,0x7b,0xfa,' +` 0xd0,0xf9,0x3d,0xf9,0xfb,0xf8,0x59,0x78,' +` 0x41,0xf9,0xb6,0xf9,0x5f,0xfa,0x3d,0xfb,' +` 0x12,0xfc,0xe3,0xfc,0xb3,0xfd,0x04,0xfe,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf3,0xff,0x68,0xff,' +` 0xa3,0xfe,0xd9,0xfd,0x46,0xfd,0xab,0xfc,' +` 0xd0,0xfc,0xb4,0xfb,0x6a,0xfb,0x7b,0xfa,' +` 0xd0,0xf9,0x3d,0xf9,0xfb,0xf8,0x59,0x78,' +` 0x41,0xf9,0xb6,0xf9,0x5f,0xfa,0x3d,0xfb,' +` 0x12,0xfc,0xe3,0xfc,0xb3,0xfd,0x04,0xfe,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xfe,0xfc,0xfe,0xdc,0xfc,0xb9,0xff,' +` 0xaa,0xf9,0xd7,0x00,0x35,0xf4,0x7d,0x05,' +` 0xd9,0xe6,0x1e,0x2c,0x5a,0x63,0x3a,0xdf,' +` 0x8d,0x08,0xb6,0xf0,0x24,0x02,0xc3,0xf6,' +` 0xe7,0xff,0x6f,0xfa,0x81,0xfe,0x40,0xfc,' +` 0x9b,0xfe,0x56,0xfe,0xb7,0xff,0xf4,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf3,0xff,0x68,0xff,' +` 0xa3,0xfe,0xd9,0xfd,0x46,0xfd,0xab,0xfc,' +` 0xd0,0xfc,0xb4,0xfb,0x6a,0xfb,0x7b,0xfa,' +` 0xd0,0xf9,0x3d,0xf9,0xfb,0xf8,0x59,0x78,' +` 0x41,0xf9,0xb6,0xf9,0x5f,0xfa,0x3d,0xfb,' +` 0x12,0xfc,0xe3,0xfc,0xb3,0xfd,0x04,0xfe,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xb7,0xff,0x32,0x00,0x74,0xfe,0xec,0xff,' +` 0x30,0xfd,0x87,0x02,0xe8,0xfa,0x7e,0x05,' +` 0x5f,0xf6,0xf8,0x0c,0xaf,0xe8,0xe8,0x3e,' +` 0xaa,0x62,0x34,0xe6,0xc1,0x0f,0x63,0xf7,' +` 0x5f,0x07,0x4b,0xfc,0x18,0x04,0xc2,0xfe,' +` 0xef,0x02,0x36,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x64,0x00,0x48,0x00,' +` 0xba,0x01,0x66,0x01,0xd9,0x04,0xa9,0x00,' +` 0x23,0x07,0x34,0x00,0xe4,0x0b,0x29,0xfd,' +` 0x05,0x14,0x91,0xed,0x31,0x75,0xdc,0x31,' +` 0xa5,0xf4,0x60,0x0f,0x54,0xfe,0x53,0x08,' +` 0x26,0x00,0x21,0x04,0x71,0x00,0x54,0x02,' +` 0x5c,0x00,0x63,0x00,0x07,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xfe,0xfc,0xfe,0xdc,0xfc,0xb9,0xff,' +` 0xaa,0xf9,0xd7,0x00,0x35,0xf4,0x7d,0x05,' +` 0xd9,0xe6,0x1e,0x2c,0x5a,0x63,0x3a,0xdf,' +` 0x8d,0x08,0xb6,0xf0,0x24,0x02,0xc3,0xf6,' +` 0xe7,0xff,0x6f,0xfa,0x81,0xfe,0x40,0xfc,' +` 0x9b,0xfe,0x56,0xfe,0xb7,0xff,0xf4,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x62,0x00,' +` 0x10,0x01,0x0f,0x01,0x72,0x00,0xcf,0x00,' +` 0x39,0x00,0xc8,0x00,0x01,0x00,0x54,0x01,' +` 0xa9,0xfe,0x91,0x7f,0x61,0x01,0x44,0xfe,' +` 0x8a,0xff,0x76,0xfe,0x33,0xff,0xd2,0xfe,' +` 0x6b,0xff,0x94,0xfe,0x79,0xfe,0x50,0xff,' +` 0xc4,0xff,0xdd,0xff,0xf1,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0xff,0x2e,0x01,0xd9,0xfc,0x63,0x02,' +` 0xa7,0xf9,0xdf,0x04,0xb3,0xf3,0x55,0x0c,' +` 0x14,0xe2,0x95,0x56,0x0b,0x45,0xbc,0xe3,' +` 0x09,0x0b,0x20,0xf3,0xb4,0x03,0xce,0xf8,' +` 0x53,0x01,0x05,0xfc,0x8d,0xff,0x75,0xfd,' +` 0xa4,0xff,0x9a,0xff,0xf8,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x2d,0x00,' +` 0x2f,0x01,0xe0,0x00,0xe7,0x03,0xec,0x00,' +` 0x56,0x05,0x5a,0x00,0xa8,0x09,0xf6,0xfd,' +` 0x17,0x11,0x5e,0xef,0x85,0x78,0xe9,0x2a,' +` 0x0b,0xf5,0xfe,0x0d,0x5b,0xfd,0xe2,0x07,' +` 0x73,0xff,0x4b,0x04,0x7d,0xff,0x5f,0x02,' +` 0x44,0x00,0xaf,0x00,0xf0,0xff,0x0b,0x00,' +` 0x00,0x00,0x00,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xdb,0xff,0x6e,0x00,0xff,0xff,0xbc,0x00,' +` 0xca,0xfe,0x1d,0x03,0x88,0xfe,0xcb,0x05,' +` 0x8e,0xfc,0x94,0x0a,0x5d,0xf5,0x0d,0x22,' +` 0x8f,0x7a,0x85,0xf0,0x50,0x0e,0x5e,0xfd,' +` 0x86,0x07,0xc1,0xff,0x44,0x04,0xa0,0x00,' +` 0x71,0x03,0xd4,0x00,0x04,0x01,0x29,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xff,' +` 0x95,0xff,0xbe,0xfe,0x09,0xfe,0x37,0xfd,' +` 0x24,0xfd,0xf3,0xfc,0x54,0xfc,0xaf,0xfb,' +` 0x11,0xfb,0xab,0xfa,0x13,0xfa,0x14,0xfa,' +` 0x9e,0x79,0x5e,0xfa,0x8e,0xfa,0x66,0xfb,' +` 0xe8,0xfb,0xed,0xfc,0x5e,0xfd,0x61,0xfe,' +` 0x31,0xfe,0x18,0xff,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf7,0xff,0x95,0xff,0x9f,0xff,' +` 0x67,0xfd,0x8d,0xff,0xf0,0xfb,0x55,0x01,' +` 0xab,0xf8,0xd2,0x03,0xf0,0xf2,0x74,0x0b,' +` 0x0d,0xe3,0xf4,0x49,0x4c,0x52,0x84,0xe2,' +` 0x87,0x0c,0xea,0xf3,0x1b,0x05,0xd9,0xf9,' +` 0x96,0x02,0xfe,0xfc,0x71,0x01,0x69,0xff,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x10,0x00,0xf5,0xff,0xe0,0x00,0x49,0x00,' +` 0xe5,0x02,0x6f,0xff,0x4c,0x05,0x09,0xff,' +` 0xa4,0x09,0x12,0xfc,0x57,0x11,0x7d,0xf0,' +` 0x67,0x3b,0x81,0x6e,0x11,0xec,0xa3,0x13,' +` 0x8d,0xfc,0xd4,0x0a,0x9c,0xff,0xd3,0x05,' +` 0x9c,0x00,0x16,0x04,0xa6,0x00,0x3a,0x01,' +` 0x1c,0x00,0x19,0x00,0x1c,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x36,0x00,0xe8,0x00,0x06,0x01,0x08,0x03,' +` 0xdb,0x00,0x74,0x03,0x74,0x00,0xcc,0x05,' +` 0x00,0xff,0xa1,0x0a,0xb8,0xf5,0x16,0x7f,' +` 0x33,0x15,0x8e,0xf9,0x10,0x07,0xe5,0xfd,' +` 0xe9,0x03,0x05,0xff,0x12,0x02,0xe4,0xfe,' +` 0x34,0x00,0x0b,0x00,0x3f,0x00,0xdb,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xfe,0x12,0xfe,' +` 0x63,0xfe,0x2c,0xfd,0x16,0xfd,0xa3,0xfb,' +` 0xe3,0xfb,0xff,0xf9,0x04,0xfc,0xdc,0x79,' +` 0xfa,0xf8,0x27,0xfb,0xa5,0xfa,0xbd,0xfb,' +` 0xdc,0xfb,0xce,0xfc,0x23,0xfd,0x6e,0xfd,' +` 0x5a,0xfd,0x2e,0xfe,0xd0,0xfe,0xa1,0xff,' +` 0xef,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,' +` 0x06,0x00,0x07,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x4c,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x6a,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x88,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xa6,0xff,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x38,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x40,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x48,0x00,0x00,0x00,0x78,0x00,0x00,0x00,' +` 0x50,0x00,0x00,0x00,0x96,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x9a,0x01,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0x01,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x66,0xfe,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0xde,0xfe,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xfe,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0xde,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_azm180_150_12el0_0_12deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_azm180_150_12el0_0_12deg_48khz.m4 new file mode 100644 index 000000000000..f9f7638a43f4 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_azm180_150_12el0_0_12deg_48khz.m4 @@ -0,0 +1,1843 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x5c,0x39,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x5c,0x39,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x08,0x00,0x0c,0x00,0x01,0x00,' +` 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0xff,0x21,0xff,0x1b,0xff,0xe9,0xfe,' +` 0xe8,0xfe,0xaa,0xfe,0xb3,0xfe,0x66,0xfe,' +` 0x7e,0xfe,0x27,0xfe,0x59,0xfe,0xea,0xfd,' +` 0x3d,0xfe,0xb1,0xfd,0x44,0xfe,0x5f,0xfd,' +` 0x89,0xfe,0x4a,0xfc,0xa0,0x7d,0x44,0xff,' +` 0x0b,0xfd,0x55,0xfe,0x8b,0xfd,0x44,0xfe,' +` 0xd3,0xfd,0x4e,0xfe,0x05,0xfe,0x6d,0xfe,' +` 0x4b,0xfe,0xa3,0xfe,0x8f,0xfe,0xd8,0xfe,' +` 0xcf,0xfe,0x03,0xff,0xfd,0xfe,0x2b,0xff,' +` 0x2d,0xff,0x56,0xff,0x60,0xff,0x84,0xff,' +` 0x8f,0xff,0xae,0xff,0x9d,0xff,0xad,0xff,' +` 0xc3,0xff,0xd6,0xff,0xe4,0xff,0xf1,0xff,' +` 0xf7,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf7,0xff,0xef,0xff,0xe2,0xff,0xd1,0xff,' +` 0xbe,0xff,0xa4,0xff,0x96,0xff,0x9e,0xff,' +` 0x85,0xff,0x6e,0xff,0x53,0xff,0x39,0xff,' +` 0x1e,0xff,0x06,0xff,0xec,0xfe,0xd6,0xfe,' +` 0xbd,0xfe,0x9d,0xfe,0x7d,0xfe,0x5e,0xfe,' +` 0x3d,0xfe,0x1c,0xfe,0x01,0xfe,0xf0,0xfd,' +` 0xe0,0xfd,0xce,0xfd,0xba,0xfd,0xab,0xfd,' +` 0x9e,0xfd,0x97,0xfd,0x80,0x7d,0xa0,0xfd,' +` 0xac,0xfd,0xbc,0xfd,0xcb,0xfd,0xdd,0xfd,' +` 0xec,0xfd,0x06,0xfe,0x1e,0xfe,0x3a,0xfe,' +` 0x53,0xfe,0x76,0xfe,0x95,0xfe,0xb7,0xfe,' +` 0xd3,0xfe,0xf4,0xfe,0x0d,0xff,0x2b,0xff,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0xff,0x21,0xff,0x1b,0xff,0xe9,0xfe,' +` 0xe8,0xfe,0xaa,0xfe,0xb3,0xfe,0x66,0xfe,' +` 0x7e,0xfe,0x27,0xfe,0x59,0xfe,0xea,0xfd,' +` 0x3d,0xfe,0xb1,0xfd,0x44,0xfe,0x5f,0xfd,' +` 0x89,0xfe,0x4a,0xfc,0xa0,0x7d,0x44,0xff,' +` 0x0b,0xfd,0x55,0xfe,0x8b,0xfd,0x44,0xfe,' +` 0xd3,0xfd,0x4e,0xfe,0x05,0xfe,0x6d,0xfe,' +` 0x4b,0xfe,0xa3,0xfe,0x8f,0xfe,0xd8,0xfe,' +` 0xcf,0xfe,0x03,0xff,0xfd,0xfe,0x2b,0xff,' +` 0x2d,0xff,0x56,0xff,0x60,0xff,0x84,0xff,' +` 0x8f,0xff,0xae,0xff,0x9d,0xff,0xad,0xff,' +` 0xc3,0xff,0xd6,0xff,0xe4,0xff,0xf1,0xff,' +` 0xf7,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf7,0xff,0xef,0xff,0xe2,0xff,0xd1,0xff,' +` 0xbe,0xff,0xa4,0xff,0x96,0xff,0x9e,0xff,' +` 0x85,0xff,0x6e,0xff,0x53,0xff,0x39,0xff,' +` 0x1e,0xff,0x06,0xff,0xec,0xfe,0xd6,0xfe,' +` 0xbd,0xfe,0x9d,0xfe,0x7d,0xfe,0x5e,0xfe,' +` 0x3d,0xfe,0x1c,0xfe,0x01,0xfe,0xf0,0xfd,' +` 0xe0,0xfd,0xce,0xfd,0xba,0xfd,0xab,0xfd,' +` 0x9e,0xfd,0x97,0xfd,0x80,0x7d,0xa0,0xfd,' +` 0xac,0xfd,0xbc,0xfd,0xcb,0xfd,0xdd,0xfd,' +` 0xec,0xfd,0x06,0xfe,0x1e,0xfe,0x3a,0xfe,' +` 0x53,0xfe,0x76,0xfe,0x95,0xfe,0xb7,0xfe,' +` 0xd3,0xfe,0xf4,0xfe,0x0d,0xff,0x2b,0xff,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf7,0xff,0xef,0xff,0xe2,0xff,0xd1,0xff,' +` 0xbe,0xff,0xa4,0xff,0x96,0xff,0x9e,0xff,' +` 0x85,0xff,0x6e,0xff,0x53,0xff,0x39,0xff,' +` 0x1e,0xff,0x06,0xff,0xec,0xfe,0xd6,0xfe,' +` 0xbd,0xfe,0x9d,0xfe,0x7d,0xfe,0x5e,0xfe,' +` 0x3d,0xfe,0x1c,0xfe,0x01,0xfe,0xf0,0xfd,' +` 0xe0,0xfd,0xce,0xfd,0xba,0xfd,0xab,0xfd,' +` 0x9e,0xfd,0x97,0xfd,0x80,0x7d,0xa0,0xfd,' +` 0xac,0xfd,0xbc,0xfd,0xcb,0xfd,0xdd,0xfd,' +` 0xec,0xfd,0x06,0xfe,0x1e,0xfe,0x3a,0xfe,' +` 0x53,0xfe,0x76,0xfe,0x95,0xfe,0xb7,0xfe,' +` 0xd3,0xfe,0xf4,0xfe,0x0d,0xff,0x2b,0xff,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0xff,0x21,0xff,0x1b,0xff,0xe9,0xfe,' +` 0xe8,0xfe,0xaa,0xfe,0xb3,0xfe,0x66,0xfe,' +` 0x7e,0xfe,0x27,0xfe,0x59,0xfe,0xea,0xfd,' +` 0x3d,0xfe,0xb1,0xfd,0x44,0xfe,0x5f,0xfd,' +` 0x89,0xfe,0x4a,0xfc,0xa0,0x7d,0x44,0xff,' +` 0x0b,0xfd,0x55,0xfe,0x8b,0xfd,0x44,0xfe,' +` 0xd3,0xfd,0x4e,0xfe,0x05,0xfe,0x6d,0xfe,' +` 0x4b,0xfe,0xa3,0xfe,0x8f,0xfe,0xd8,0xfe,' +` 0xcf,0xfe,0x03,0xff,0xfd,0xfe,0x2b,0xff,' +` 0x2d,0xff,0x56,0xff,0x60,0xff,0x84,0xff,' +` 0x8f,0xff,0xae,0xff,0x9d,0xff,0xad,0xff,' +` 0xc3,0xff,0xd6,0xff,0xe4,0xff,0xf1,0xff,' +` 0xf7,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf7,0xff,0xef,0xff,0xe2,0xff,0xd1,0xff,' +` 0xbe,0xff,0xa4,0xff,0x96,0xff,0x9e,0xff,' +` 0x85,0xff,0x6e,0xff,0x53,0xff,0x39,0xff,' +` 0x1e,0xff,0x06,0xff,0xec,0xfe,0xd6,0xfe,' +` 0xbd,0xfe,0x9d,0xfe,0x7d,0xfe,0x5e,0xfe,' +` 0x3d,0xfe,0x1c,0xfe,0x01,0xfe,0xf0,0xfd,' +` 0xe0,0xfd,0xce,0xfd,0xba,0xfd,0xab,0xfd,' +` 0x9e,0xfd,0x97,0xfd,0x80,0x7d,0xa0,0xfd,' +` 0xac,0xfd,0xbc,0xfd,0xcb,0xfd,0xdd,0xfd,' +` 0xec,0xfd,0x06,0xfe,0x1e,0xfe,0x3a,0xfe,' +` 0x53,0xfe,0x76,0xfe,0x95,0xfe,0xb7,0xfe,' +` 0xd3,0xfe,0xf4,0xfe,0x0d,0xff,0x2b,0xff,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfb,0xff,' +` 0xea,0xff,0xf5,0xff,0xcf,0xff,0xec,0xff,' +` 0xb9,0xff,0x1b,0x00,0xb0,0xff,0x2e,0x00,' +` 0x8f,0xff,0x48,0x00,0x60,0xff,0x6b,0x00,' +` 0x28,0xff,0x9a,0x00,0xe2,0xfe,0xdf,0x00,' +` 0x91,0xfe,0x3f,0x01,0x25,0xfe,0xc9,0x01,' +` 0x8f,0xfd,0x98,0x02,0x97,0xfc,0x02,0x04,' +` 0xbd,0xfa,0x3f,0x07,0xd7,0xf4,0x15,0x19,' +` 0x24,0x7a,0x9f,0xee,0xa8,0x09,0xf1,0xf9,' +` 0x07,0x05,0x9d,0xfc,0x5a,0x03,0xcf,0xfd,' +` 0x68,0x02,0x7e,0xfe,0xcd,0x01,0xf1,0xfe,' +` 0x5a,0x01,0x3f,0xff,0x06,0x01,0x80,0xff,' +` 0xcc,0x00,0xb3,0xff,0x9c,0x00,0xd5,0xff,' +` 0x70,0x00,0xeb,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x13,0x00,' +` 0x15,0x00,0x35,0x00,0x2d,0x00,0x68,0x00,' +` 0x46,0x00,0x7a,0x00,0x43,0x00,0xbc,0x00,' +` 0x5b,0x00,0x0d,0x01,0x77,0x00,0x6b,0x01,' +` 0x8e,0x00,0xd7,0x01,0x9d,0x00,0x4f,0x02,' +` 0x94,0x00,0xd1,0x02,0x6f,0x00,0x6b,0x03,' +` 0x1a,0x00,0x29,0x04,0x65,0xff,0x4e,0x05,' +` 0xe9,0xfd,0xd6,0x07,0x42,0xf9,0x5d,0x15,' +` 0x4d,0x7e,0x80,0xf3,0xc8,0x09,0xe6,0xfc,' +` 0xd8,0x05,0xf3,0xfe,0x5c,0x04,0xd5,0xff,' +` 0x80,0x03,0x43,0x00,0xd8,0x02,0x71,0x00,' +` 0x4e,0x02,0x81,0x00,0xd6,0x01,0x79,0x00,' +` 0x67,0x01,0x66,0x00,0x09,0x01,0x4e,0x00,' +` 0xb7,0x00,0x37,0x00,0x78,0x00,0x22,0x00,' +` 0x5b,0x00,0x2b,0x00,0x31,0x00,0x13,0x00,' +` 0x12,0x00,0x05,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0xff,0x21,0xff,0x1b,0xff,0xe9,0xfe,' +` 0xe8,0xfe,0xaa,0xfe,0xb3,0xfe,0x66,0xfe,' +` 0x7e,0xfe,0x27,0xfe,0x59,0xfe,0xea,0xfd,' +` 0x3d,0xfe,0xb1,0xfd,0x44,0xfe,0x5f,0xfd,' +` 0x89,0xfe,0x4a,0xfc,0xa0,0x7d,0x44,0xff,' +` 0x0b,0xfd,0x55,0xfe,0x8b,0xfd,0x44,0xfe,' +` 0xd3,0xfd,0x4e,0xfe,0x05,0xfe,0x6d,0xfe,' +` 0x4b,0xfe,0xa3,0xfe,0x8f,0xfe,0xd8,0xfe,' +` 0xcf,0xfe,0x03,0xff,0xfd,0xfe,0x2b,0xff,' +` 0x2d,0xff,0x56,0xff,0x60,0xff,0x84,0xff,' +` 0x8f,0xff,0xae,0xff,0x9d,0xff,0xad,0xff,' +` 0xc3,0xff,0xd6,0xff,0xe4,0xff,0xf1,0xff,' +` 0xf7,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x27,0x00,0x0c,0x00,' +` 0x32,0x00,0x09,0x00,0x3f,0x00,0x00,0x00,' +` 0x49,0x00,0xef,0xff,0x53,0x00,0xdc,0xff,' +` 0x6a,0x00,0xcb,0xff,0x8b,0x00,0xaf,0xff,' +` 0xb3,0x00,0x82,0xff,0xf6,0x00,0x30,0xff,' +` 0x62,0x01,0x6b,0xfe,0xa3,0x02,0x00,0xfb,' +` 0x95,0x7f,0x7d,0x05,0x3b,0xfd,0xa1,0x01,' +` 0x84,0xfe,0xc8,0x00,0xe8,0xfe,0x67,0x00,' +` 0x22,0xff,0x31,0x00,0x44,0xff,0x0d,0x00,' +` 0x61,0xff,0xf9,0xff,0x7a,0xff,0xf0,0xff,' +` 0x96,0xff,0xee,0xff,0xad,0xff,0xef,0xff,' +` 0xc4,0xff,0xf1,0xff,0xd2,0xff,0xf4,0xff,' +` 0xc9,0xff,0xd7,0xff,0xda,0xff,0xea,0xff,' +` 0xef,0xff,0xf8,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,' +` 0x06,0x00,0x07,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x4c,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x6a,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x88,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xa6,0xff,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x38,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x40,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x48,0x00,0x00,0x00,0x78,0x00,0x00,0x00,' +` 0x50,0x00,0x00,0x00,0x96,0x00,0x00,0x00,' +` 0x58,0x00,0x00,0x00,0x9a,0x01,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0x01,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x66,0xfe,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0xde,0xfe,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xfe,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0xde,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_pm30deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_pm30deg_16khz.m4 new file mode 100644 index 000000000000..1df117e4e8f0 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_pm30deg_16khz.m4 @@ -0,0 +1,328 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0a,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0a,0x00,0x00,0x10,0x00,0x02,0x00,' +` 0x01,0x00,0x08,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xec,0xff,0xe5,0xff,' +` 0xb4,0xff,0xa2,0xff,0x52,0xff,0x74,0xff,' +` 0xfc,0xfe,0x1b,0xff,0xd4,0xfd,0x9f,0xfe,' +` 0x45,0xfd,0xb1,0xfe,0xff,0xfc,0xd8,0xfe,' +` 0x2b,0xfc,0x5c,0xff,0x92,0xfa,0x5f,0xfe,' +` 0x71,0xfa,0x95,0xfd,0xca,0xf5,0xc4,0xfe,' +` 0x7c,0xf7,0x43,0x02,0x71,0xf5,0xd7,0x04,' +` 0xfa,0xf0,0x49,0x0c,0x51,0xe2,0x28,0x4a,' +` 0x86,0x52,0xc5,0xe1,0x71,0x0d,0x19,0xf2,' +` 0x78,0x06,0x24,0xf7,0x64,0x04,0xb0,0xf9,' +` 0xf7,0x03,0xb0,0xfd,0xab,0x02,0xc5,0xfd,' +` 0xb4,0x04,0xd7,0xff,0xda,0x02,0x5d,0xff,' +` 0xbb,0x01,0x7a,0xff,0x58,0x01,0x11,0x01,' +` 0xb3,0x01,0x0d,0x01,0xe3,0x01,0xef,0x00,' +` 0x15,0x01,0x86,0x00,0x83,0x00,0x2b,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,' +` 0xef,0xff,0xdb,0xff,0xc0,0xff,0xab,0xff,' +` 0x68,0xff,0x45,0xff,0xd4,0xfe,0x46,0xfe,' +` 0x23,0xfe,0xef,0xfd,0xb5,0xfd,0x97,0xfd,' +` 0x73,0xfd,0x5d,0xfd,0xe5,0xfc,0xeb,0xfc,' +` 0x35,0xfe,0x3c,0xfc,0x7b,0xfa,0xef,0xf7,' +` 0x47,0xf8,0x55,0xf8,0x01,0xfa,0xd1,0xfa,' +` 0xb7,0xfa,0x87,0xfa,0x54,0xfa,0x48,0xfa,' +` 0xec,0xf9,0x10,0xfa,0xf4,0x79,0x3a,0xfa,' +` 0x29,0xfa,0xb5,0xfa,0xd0,0xfa,0x93,0xfb,' +` 0x86,0xfb,0x9a,0xfc,0x07,0xfb,0x71,0xfc,' +` 0x7a,0xfe,0xba,0x00,0x22,0x01,0x87,0x00,' +` 0x9f,0xff,0xe7,0xfe,0xc3,0xff,0xc9,0xff,' +` 0xff,0x00,0x1e,0x01,0x6e,0x01,0xed,0x01,' +` 0x7f,0x01,0x25,0x01,0xe8,0x00,0xa7,0x00,' +` 0x7b,0x00,0x44,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf6,0xff,0xf2,0xff,0xcd,0xff,0xad,0xff,' +` 0x75,0xff,0x88,0xff,0x43,0xff,0x84,0xff,' +` 0x36,0xff,0xcc,0xff,0x67,0xff,0x9f,0xff,' +` 0x8e,0xfe,0x00,0x00,0xcf,0xfe,0x6c,0xff,' +` 0x2a,0xfd,0xb4,0x00,0x17,0xfe,0xc1,0x02,' +` 0xfd,0xff,0x04,0x02,0x75,0xfd,0x49,0x05,' +` 0xe3,0xfd,0x57,0x07,0x09,0xfc,0x59,0x0b,' +` 0x18,0xf5,0x25,0x22,0xe6,0x7a,0x20,0xf0,' +` 0x5a,0x0f,0xf9,0xfc,0x89,0x09,0xa6,0xff,' +` 0x3e,0x07,0x4f,0x01,0x79,0x09,0x43,0x03,' +` 0x80,0x06,0x24,0x02,0x59,0x03,0x43,0x01,' +` 0xe0,0x04,0x09,0x02,0x26,0x03,0x65,0x01,' +` 0xf2,0x01,0x5b,0x00,0x0e,0x01,0x73,0x00,' +` 0xaf,0x00,0x74,0x00,0x7b,0x00,0x4d,0x00,' +` 0x66,0x00,0x29,0x00,0x1b,0x00,0x07,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x08,0x00,' +` 0x18,0x00,0x09,0x00,0x2d,0x00,0x2c,0x00,' +` 0x7d,0x00,0x10,0x00,0xb5,0x00,0x13,0x00,' +` 0x0b,0x01,0xb0,0x00,0x3f,0x02,0x9f,0x01,' +` 0xa3,0x03,0x50,0x02,0xfd,0x03,0x03,0x01,' +` 0xaa,0x04,0x52,0x02,0x97,0x07,0x72,0x03,' +` 0xbe,0x0a,0xef,0x01,0x0f,0x09,0x81,0x00,' +` 0x3d,0x0c,0xa8,0xfd,0x55,0x12,0xf2,0xee,' +` 0xda,0x78,0x07,0x2b,0xc4,0xf4,0x03,0x0f,' +` 0xf5,0xfc,0xfd,0x09,0x35,0xff,0x4a,0x07,' +` 0xee,0xfe,0x85,0x06,0x0c,0x01,0x63,0x04,' +` 0x30,0xff,0x16,0x02,0x28,0xfe,0x67,0x00,' +` 0x8a,0xff,0xa8,0x00,0x16,0x00,0xef,0x00,' +` 0x7d,0xff,0x16,0x00,0x4d,0xff,0xad,0xff,' +` 0x51,0xff,0x99,0xff,0x8a,0xff,0xf8,0xff,' +` 0xe0,0xff,0xf4,0xff,0xf6,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x27,0x00,0x7c,0x00,0x7c,0x00,0x07,0x01,' +` 0xde,0x00,0xc8,0x01,0xe3,0x00,0x96,0x01,' +` 0xdf,0x00,0x1d,0x01,0x51,0xff,0x7b,0x01,' +` 0x2c,0xff,0x7f,0x02,0x9a,0xff,0x61,0x04,' +` 0x7b,0xfd,0x5a,0x02,0x6e,0xfd,0x40,0x03,' +` 0x64,0xf9,0x0e,0x04,0xdc,0xf6,0x2c,0x06,' +` 0xda,0xf1,0x3a,0x0d,0x52,0xe1,0xd2,0x56,' +` 0x3c,0x45,0x04,0xe3,0xd7,0x0b,0x31,0xf1,' +` 0xb1,0x04,0xa3,0xf5,0x40,0x02,0xa8,0xf7,' +` 0xc4,0xfe,0x01,0xf6,0xb5,0xfd,0xb1,0xfa,' +` 0x74,0xfe,0xf6,0xfa,0xad,0xff,0x4e,0xfc,' +` 0x0a,0xff,0x25,0xfd,0xd7,0xfe,0x67,0xfd,' +` 0xbd,0xfe,0xef,0xfd,0x3c,0xff,0x0c,0xff,' +` 0x82,0xff,0x5b,0xff,0xaa,0xff,0xba,0xff,' +` 0xe7,0xff,0xee,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3a,0x00,0x69,0x00,' +` 0x91,0x00,0xc7,0x00,0xff,0x00,0x4b,0x01,' +` 0xb4,0x01,0x18,0x01,0xdf,0x00,0x93,0x00,' +` 0x69,0xff,0x63,0xff,0x73,0xfe,0x3c,0xff,' +` 0x3d,0x00,0xbd,0x00,0x6a,0x00,0x04,0xfe,' +` 0x00,0xfc,0xb0,0xfa,0x9f,0xfc,0x32,0xfb,' +` 0xce,0xfb,0x79,0xfa,0x44,0xfb,0x8f,0xf9,' +` 0xea,0xfb,0x33,0x7a,0xf5,0xf8,0x07,0xfb,' +` 0x41,0xfa,0x1a,0xfb,0xc0,0xfa,0x66,0xfb,' +` 0x23,0xfb,0x9c,0xfa,0xb6,0xf8,0xd7,0xf8,' +` 0x64,0xf8,0x0e,0xfb,0xca,0xfc,0xce,0xfe,' +` 0x2e,0xfd,0x55,0xfd,0x9e,0xfd,0xca,0xfd,' +` 0xcd,0xfd,0xf6,0xfd,0x17,0xfe,0x4f,0xfe,' +` 0x60,0xfe,0xfc,0xfe,0x54,0xff,0x7c,0xff,' +` 0xb6,0xff,0xc7,0xff,0xde,0xff,0xf1,0xff,' +` 0xfc,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0a,0x00,0x1e,0x00,0x35,0x00,0x6c,0x00,' +` 0x62,0x00,0x86,0x00,0x9e,0x00,0xbd,0x00,' +` 0xb3,0x00,0x1a,0x01,0xb0,0x00,0xf8,0x01,' +` 0xca,0x01,0x0c,0x03,0x85,0x02,0xbd,0x04,' +` 0xc3,0x01,0xf6,0x02,0xcb,0x02,0xce,0x05,' +` 0x06,0x04,0x57,0x08,0xcb,0x01,0xde,0x05,' +` 0xa7,0x00,0x59,0x07,0xda,0xfe,0x67,0x0b,' +` 0x75,0xf5,0x70,0x7f,0x42,0x15,0x64,0xf9,' +` 0x93,0x07,0x94,0xfd,0xf4,0x04,0x97,0xfe,' +` 0x84,0x03,0xac,0xfd,0x8f,0x00,0x2a,0x00,' +` 0x93,0x01,0x1b,0xfe,0xd9,0xff,0x15,0xfd,' +` 0xf9,0xfe,0xcd,0xfe,0x8a,0xff,0x86,0xfe,' +` 0x4f,0xff,0x64,0xff,0x91,0xff,0x32,0xff,' +` 0x60,0xff,0x42,0xff,0x74,0xff,0x76,0xff,' +` 0xa2,0xff,0xcf,0xff,0xf0,0xff,0xf7,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xf7,0xff,0xf9,0xff,0xe5,0xff,' +` 0x07,0x00,0x90,0xff,0xb9,0xff,0x62,0xff,' +` 0xe3,0xff,0x6a,0xff,0x68,0x00,0xa6,0xff,' +` 0x68,0x01,0x44,0x00,0x3e,0x01,0xb6,0xff,' +` 0x0f,0x01,0x7d,0xfe,0x02,0x03,0x6d,0xff,' +` 0x99,0x05,0x1f,0x01,0xf6,0x07,0xcf,0xfe,' +` 0xff,0x08,0x9d,0xfe,0x37,0x0c,0x7b,0xfb,' +` 0x9a,0x12,0x18,0xf0,0x91,0x3b,0xcf,0x6e,' +` 0x90,0xeb,0x11,0x15,0x09,0xfc,0xb9,0x0d,' +` 0x70,0xff,0xe5,0x09,0x47,0x01,0x3d,0x0b,' +` 0x8b,0x02,0xda,0x07,0x79,0x01,0xbb,0x04,' +` 0x51,0x00,0xd7,0x03,0xaf,0x01,0x86,0x03,' +` 0x1b,0x01,0x13,0x02,0x45,0x00,0xe2,0x00,' +` 0xc7,0xff,0x95,0x00,0xdd,0xff,0x68,0x00,' +` 0x0e,0x00,0x21,0x00,0xfd,0xff,0x14,0x00,' +` 0x05,0x00,0x02,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xec,0xff,0xe5,0xff,' +` 0xb4,0xff,0xa2,0xff,0x52,0xff,0x74,0xff,' +` 0xfc,0xfe,0x1b,0xff,0xd4,0xfd,0x9f,0xfe,' +` 0x45,0xfd,0xb1,0xfe,0xff,0xfc,0xd8,0xfe,' +` 0x2b,0xfc,0x5c,0xff,0x92,0xfa,0x5f,0xfe,' +` 0x71,0xfa,0x95,0xfd,0xca,0xf5,0xc4,0xfe,' +` 0x7c,0xf7,0x43,0x02,0x71,0xf5,0xd7,0x04,' +` 0xfa,0xf0,0x49,0x0c,0x51,0xe2,0x28,0x4a,' +` 0x86,0x52,0xc5,0xe1,0x71,0x0d,0x19,0xf2,' +` 0x78,0x06,0x24,0xf7,0x64,0x04,0xb0,0xf9,' +` 0xf7,0x03,0xb0,0xfd,0xab,0x02,0xc5,0xfd,' +` 0xb4,0x04,0xd7,0xff,0xda,0x02,0x5d,0xff,' +` 0xbb,0x01,0x7a,0xff,0x58,0x01,0x11,0x01,' +` 0xb3,0x01,0x0d,0x01,0xe3,0x01,0xef,0x00,' +` 0x15,0x01,0x86,0x00,0x83,0x00,0x2b,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xf7,0xff,0xf9,0xff,0xe5,0xff,' +` 0x07,0x00,0x90,0xff,0xb9,0xff,0x62,0xff,' +` 0xe3,0xff,0x6a,0xff,0x68,0x00,0xa6,0xff,' +` 0x68,0x01,0x44,0x00,0x3e,0x01,0xb6,0xff,' +` 0x0f,0x01,0x7d,0xfe,0x02,0x03,0x6d,0xff,' +` 0x99,0x05,0x1f,0x01,0xf6,0x07,0xcf,0xfe,' +` 0xff,0x08,0x9d,0xfe,0x37,0x0c,0x7b,0xfb,' +` 0x9a,0x12,0x18,0xf0,0x91,0x3b,0xcf,0x6e,' +` 0x90,0xeb,0x11,0x15,0x09,0xfc,0xb9,0x0d,' +` 0x70,0xff,0xe5,0x09,0x47,0x01,0x3d,0x0b,' +` 0x8b,0x02,0xda,0x07,0x79,0x01,0xbb,0x04,' +` 0x51,0x00,0xd7,0x03,0xaf,0x01,0x86,0x03,' +` 0x1b,0x01,0x13,0x02,0x45,0x00,0xe2,0x00,' +` 0xc7,0xff,0x95,0x00,0xdd,0xff,0x68,0x00,' +` 0x0e,0x00,0x21,0x00,0xfd,0xff,0x14,0x00,' +` 0x05,0x00,0x02,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0a,0x00,0x1e,0x00,0x35,0x00,0x6c,0x00,' +` 0x62,0x00,0x86,0x00,0x9e,0x00,0xbd,0x00,' +` 0xb3,0x00,0x1a,0x01,0xb0,0x00,0xf8,0x01,' +` 0xca,0x01,0x0c,0x03,0x85,0x02,0xbd,0x04,' +` 0xc3,0x01,0xf6,0x02,0xcb,0x02,0xce,0x05,' +` 0x06,0x04,0x57,0x08,0xcb,0x01,0xde,0x05,' +` 0xa7,0x00,0x59,0x07,0xda,0xfe,0x67,0x0b,' +` 0x75,0xf5,0x70,0x7f,0x42,0x15,0x64,0xf9,' +` 0x93,0x07,0x94,0xfd,0xf4,0x04,0x97,0xfe,' +` 0x84,0x03,0xac,0xfd,0x8f,0x00,0x2a,0x00,' +` 0x93,0x01,0x1b,0xfe,0xd9,0xff,0x15,0xfd,' +` 0xf9,0xfe,0xcd,0xfe,0x8a,0xff,0x86,0xfe,' +` 0x4f,0xff,0x64,0xff,0x91,0xff,0x32,0xff,' +` 0x60,0xff,0x42,0xff,0x74,0xff,0x76,0xff,' +` 0xa2,0xff,0xcf,0xff,0xf0,0xff,0xf7,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3a,0x00,0x69,0x00,' +` 0x91,0x00,0xc7,0x00,0xff,0x00,0x4b,0x01,' +` 0xb4,0x01,0x18,0x01,0xdf,0x00,0x93,0x00,' +` 0x69,0xff,0x63,0xff,0x73,0xfe,0x3c,0xff,' +` 0x3d,0x00,0xbd,0x00,0x6a,0x00,0x04,0xfe,' +` 0x00,0xfc,0xb0,0xfa,0x9f,0xfc,0x32,0xfb,' +` 0xce,0xfb,0x79,0xfa,0x44,0xfb,0x8f,0xf9,' +` 0xea,0xfb,0x33,0x7a,0xf5,0xf8,0x07,0xfb,' +` 0x41,0xfa,0x1a,0xfb,0xc0,0xfa,0x66,0xfb,' +` 0x23,0xfb,0x9c,0xfa,0xb6,0xf8,0xd7,0xf8,' +` 0x64,0xf8,0x0e,0xfb,0xca,0xfc,0xce,0xfe,' +` 0x2e,0xfd,0x55,0xfd,0x9e,0xfd,0xca,0xfd,' +` 0xcd,0xfd,0xf6,0xfd,0x17,0xfe,0x4f,0xfe,' +` 0x60,0xfe,0xfc,0xfe,0x54,0xff,0x7c,0xff,' +` 0xb6,0xff,0xc7,0xff,0xde,0xff,0xf1,0xff,' +` 0xfc,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x27,0x00,0x7c,0x00,0x7c,0x00,0x07,0x01,' +` 0xde,0x00,0xc8,0x01,0xe3,0x00,0x96,0x01,' +` 0xdf,0x00,0x1d,0x01,0x51,0xff,0x7b,0x01,' +` 0x2c,0xff,0x7f,0x02,0x9a,0xff,0x61,0x04,' +` 0x7b,0xfd,0x5a,0x02,0x6e,0xfd,0x40,0x03,' +` 0x64,0xf9,0x0e,0x04,0xdc,0xf6,0x2c,0x06,' +` 0xda,0xf1,0x3a,0x0d,0x52,0xe1,0xd2,0x56,' +` 0x3c,0x45,0x04,0xe3,0xd7,0x0b,0x31,0xf1,' +` 0xb1,0x04,0xa3,0xf5,0x40,0x02,0xa8,0xf7,' +` 0xc4,0xfe,0x01,0xf6,0xb5,0xfd,0xb1,0xfa,' +` 0x74,0xfe,0xf6,0xfa,0xad,0xff,0x4e,0xfc,' +` 0x0a,0xff,0x25,0xfd,0xd7,0xfe,0x67,0xfd,' +` 0xbd,0xfe,0xef,0xfd,0x3c,0xff,0x0c,0xff,' +` 0x82,0xff,0x5b,0xff,0xaa,0xff,0xba,0xff,' +` 0xe7,0xff,0xee,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x08,0x00,' +` 0x18,0x00,0x09,0x00,0x2d,0x00,0x2c,0x00,' +` 0x7d,0x00,0x10,0x00,0xb5,0x00,0x13,0x00,' +` 0x0b,0x01,0xb0,0x00,0x3f,0x02,0x9f,0x01,' +` 0xa3,0x03,0x50,0x02,0xfd,0x03,0x03,0x01,' +` 0xaa,0x04,0x52,0x02,0x97,0x07,0x72,0x03,' +` 0xbe,0x0a,0xef,0x01,0x0f,0x09,0x81,0x00,' +` 0x3d,0x0c,0xa8,0xfd,0x55,0x12,0xf2,0xee,' +` 0xda,0x78,0x07,0x2b,0xc4,0xf4,0x03,0x0f,' +` 0xf5,0xfc,0xfd,0x09,0x35,0xff,0x4a,0x07,' +` 0xee,0xfe,0x85,0x06,0x0c,0x01,0x63,0x04,' +` 0x30,0xff,0x16,0x02,0x28,0xfe,0x67,0x00,' +` 0x8a,0xff,0xa8,0x00,0x16,0x00,0xef,0x00,' +` 0x7d,0xff,0x16,0x00,0x4d,0xff,0xad,0xff,' +` 0x51,0xff,0x99,0xff,0x8a,0xff,0xf8,0xff,' +` 0xe0,0xff,0xf4,0xff,0xf6,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf6,0xff,0xf2,0xff,0xcd,0xff,0xad,0xff,' +` 0x75,0xff,0x88,0xff,0x43,0xff,0x84,0xff,' +` 0x36,0xff,0xcc,0xff,0x67,0xff,0x9f,0xff,' +` 0x8e,0xfe,0x00,0x00,0xcf,0xfe,0x6c,0xff,' +` 0x2a,0xfd,0xb4,0x00,0x17,0xfe,0xc1,0x02,' +` 0xfd,0xff,0x04,0x02,0x75,0xfd,0x49,0x05,' +` 0xe3,0xfd,0x57,0x07,0x09,0xfc,0x59,0x0b,' +` 0x18,0xf5,0x25,0x22,0xe6,0x7a,0x20,0xf0,' +` 0x5a,0x0f,0xf9,0xfc,0x89,0x09,0xa6,0xff,' +` 0x3e,0x07,0x4f,0x01,0x79,0x09,0x43,0x03,' +` 0x80,0x06,0x24,0x02,0x59,0x03,0x43,0x01,' +` 0xe0,0x04,0x09,0x02,0x26,0x03,0x65,0x01,' +` 0xf2,0x01,0x5b,0x00,0x0e,0x01,0x73,0x00,' +` 0xaf,0x00,0x74,0x00,0x7b,0x00,0x4d,0x00,' +` 0x66,0x00,0x29,0x00,0x1b,0x00,0x07,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,' +` 0xef,0xff,0xdb,0xff,0xc0,0xff,0xab,0xff,' +` 0x68,0xff,0x45,0xff,0xd4,0xfe,0x46,0xfe,' +` 0x23,0xfe,0xef,0xfd,0xb5,0xfd,0x97,0xfd,' +` 0x73,0xfd,0x5d,0xfd,0xe5,0xfc,0xeb,0xfc,' +` 0x35,0xfe,0x3c,0xfc,0x7b,0xfa,0xef,0xf7,' +` 0x47,0xf8,0x55,0xf8,0x01,0xfa,0xd1,0xfa,' +` 0xb7,0xfa,0x87,0xfa,0x54,0xfa,0x48,0xfa,' +` 0xec,0xf9,0x10,0xfa,0xf4,0x79,0x3a,0xfa,' +` 0x29,0xfa,0xb5,0xfa,0xd0,0xfa,0x93,0xfb,' +` 0x86,0xfb,0x9a,0xfc,0x07,0xfb,0x71,0xfc,' +` 0x7a,0xfe,0xba,0x00,0x22,0x01,0x87,0x00,' +` 0x9f,0xff,0xe7,0xfe,0xc3,0xff,0xc9,0xff,' +` 0xff,0x00,0x1e,0x01,0x6e,0x01,0xed,0x01,' +` 0x7f,0x01,0x25,0x01,0xe8,0x00,0xa7,0x00,' +` 0x7b,0x00,0x44,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,' +` 0x06,0x00,0x07,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,' +` 0x06,0x00,0x07,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x9a,0x01,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0x01,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x66,0xfe,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0xde,0xfe,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xfe,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0xde,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_pm30deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_pm30deg_48khz.m4 new file mode 100644 index 000000000000..b41b74a59c2b --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_circular8_100mm_pm30deg_48khz.m4 @@ -0,0 +1,328 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0a,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0a,0x00,0x00,0x10,0x00,0x02,0x00,' +` 0x01,0x00,0x08,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xf8,0xff,0xd7,0xff,0xf4,0xff,0xad,0xff,' +` 0xfc,0xff,0x7c,0xff,0x15,0x00,0x4a,0xff,' +` 0x2e,0x00,0xf5,0xfe,0x52,0x00,0x88,0xfe,' +` 0x81,0x00,0x06,0xfe,0xcc,0x00,0x6a,0xfd,' +` 0x39,0x01,0xab,0xfc,0xd7,0x01,0xb3,0xfb,' +` 0xcd,0x02,0x6a,0xfa,0x61,0x04,0x67,0xf8,' +` 0x39,0x07,0x3a,0xf4,0x1b,0x0e,0xf9,0xe5,' +` 0xad,0x43,0x45,0x5c,0x5e,0xe3,0x1a,0x0f,' +` 0xdc,0xf3,0x94,0x07,0x5c,0xf8,0xad,0x04,' +` 0x93,0xfa,0x1f,0x03,0xf6,0xfb,0x2c,0x02,' +` 0xf6,0xfc,0x8c,0x01,0xb8,0xfd,0x19,0x01,' +` 0x50,0xfe,0xc8,0x00,0xcb,0xfe,0x8d,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x10,0x00,' +` 0x19,0x00,0x18,0x00,0x0c,0x00,0x20,0x00,' +` 0x26,0x00,0x36,0x00,0x38,0x00,0x4e,0x00,' +` 0x4e,0x00,0x6b,0x00,0x66,0x00,0x85,0x00,' +` 0x79,0x00,0x9f,0x00,0x8b,0x00,0xba,0x00,' +` 0x9c,0x00,0xd7,0x00,0xab,0x00,0xf8,0x00,' +` 0xb0,0x00,0x17,0x01,0xa3,0x00,0x48,0x01,' +` 0x63,0x00,0x0f,0x02,0xe3,0x40,0xe6,0xff,' +` 0x80,0x01,0x9d,0x00,0x36,0x01,0xbd,0x00,' +` 0x15,0x01,0xc4,0x00,0xfe,0x00,0xc3,0x00,' +` 0xe6,0x00,0xb2,0x00,0xc4,0x00,0x99,0x00,' +` 0x9f,0x00,0x7c,0x00,0x7d,0x00,0x60,0x00,' +` 0x5e,0x00,0x48,0x00,0x43,0x00,0x34,0x00,' +` 0x2c,0x00,0x2d,0x00,0x35,0x00,0x20,0x00,' +` 0x17,0x00,0x0d,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x89,0x00,0x24,0x00,0x95,0x00,' +` 0xe8,0xff,0xe0,0x00,0xcb,0xff,0x3c,0x01,' +` 0x9f,0xff,0xac,0x01,0x60,0xff,0x36,0x02,' +` 0x06,0xff,0xe2,0x02,0x88,0xfe,0xbe,0x03,' +` 0xce,0xfd,0xe8,0x04,0xa9,0xfc,0x98,0x06,' +` 0xa1,0xfa,0x89,0x09,0x36,0xf6,0xf7,0x10,' +` 0xab,0xe5,0x1c,0x63,0x00,0x40,0x2f,0xe9,' +` 0x52,0x0f,0x75,0xf6,0x9f,0x08,0x53,0xfa,' +` 0xd7,0x05,0x38,0xfc,0x3e,0x04,0x58,0xfd,' +` 0x2e,0x03,0x1c,0xfe,0x69,0x02,0xa8,0xfe,' +` 0xce,0x01,0x08,0xff,0x4f,0x01,0x4f,0xff,' +` 0xed,0x00,0x88,0xff,0x9d,0x00,0xb0,0xff,' +` 0x5f,0x00,0xbb,0xff,0x26,0x00,0xd0,0xff,' +` 0x0a,0x00,0xf6,0xff,0x0b,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8f,0xff,0x51,0xff,' +` 0x6a,0xff,0x19,0xff,0x46,0xff,0xda,0xfe,' +` 0x21,0xff,0x96,0xfe,0x00,0xff,0x4a,0xfe,' +` 0xea,0xfe,0xfe,0xfd,0xe6,0xfe,0x9f,0xfd,' +` 0x08,0xff,0x21,0xfd,0x96,0xff,0xf1,0xfb,' +` 0xa1,0x02,0xcc,0x7d,0xe3,0xf9,0x46,0x00,' +` 0xb5,0xfc,0x37,0xff,0x5c,0xfd,0xef,0xfe,' +` 0xc4,0xfd,0xe2,0xfe,0x1a,0xfe,0xf3,0xfe,' +` 0x5d,0xfe,0x01,0xff,0x9a,0xfe,0x1e,0xff,' +` 0xd9,0xfe,0x44,0xff,0x17,0xff,0x66,0xff,' +` 0x48,0xff,0x88,0xff,0x78,0xff,0xaa,0xff,' +` 0x98,0xff,0xb3,0xff,0xb5,0xff,0xc9,0xff,' +` 0xd3,0xff,0xe2,0xff,0xee,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4c,0x00,0x36,0xff,0x6e,0x00,0xd8,0xfe,' +` 0x9f,0x00,0x64,0xfe,0xe4,0x00,0xd6,0xfd,' +` 0x48,0x01,0x20,0xfd,0xd5,0x01,0x34,0xfc,' +` 0xb1,0x02,0xee,0xfa,0x1e,0x04,0xe0,0xf8,' +` 0xcf,0x06,0xab,0xf4,0xf4,0x0d,0x81,0xe4,' +` 0x0d,0x68,0xbe,0x34,0x99,0xe9,0x1e,0x0c,' +` 0x81,0xf5,0x3d,0x06,0x1f,0xf9,0xbf,0x03,' +` 0xe5,0xfa,0x5d,0x02,0x0b,0xfc,0x89,0x01,' +` 0xed,0xfc,0x01,0x01,0x9c,0xfd,0xa4,0x00,' +` 0x2c,0xfe,0x66,0x00,0xa5,0xfe,0x40,0x00,' +` 0x09,0xff,0x21,0x00,0x58,0xff,0x0c,0x00,' +` 0x84,0xff,0xf7,0xff,0xb1,0xff,0xf2,0xff,' +` 0xd8,0xff,0xf8,0xff,0xf6,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x08,0x00,' +` 0x27,0x00,0x1b,0x00,0x62,0x00,0x40,0x00,' +` 0x88,0x00,0x15,0x00,0xc3,0x00,0x18,0x00,' +` 0x1b,0x01,0x16,0x00,0x89,0x01,0x09,0x00,' +` 0x10,0x02,0xee,0xff,0xb2,0x02,0xb7,0xff,' +` 0x71,0x03,0x4d,0xff,0x58,0x04,0x82,0xfe,' +` 0x8b,0x05,0x1c,0xfd,0x96,0x07,0x45,0xfa,' +` 0x52,0x0c,0x08,0xf1,0xa6,0x29,0xfa,0x73,' +` 0x36,0xea,0xc4,0x0e,0xb9,0xf8,0x66,0x08,' +` 0x3d,0xfc,0xf0,0x05,0xd2,0xfd,0x83,0x04,' +` 0xa7,0xfe,0x85,0x03,0x2d,0xff,0xc4,0x02,' +` 0x83,0xff,0x2c,0x02,0xbe,0xff,0xae,0x01,' +` 0xdf,0xff,0x3b,0x01,0xeb,0xff,0xdc,0x00,' +` 0xf3,0xff,0x91,0x00,0xeb,0xff,0x41,0x00,' +` 0x03,0x00,0x48,0x00,0x07,0x00,0x19,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0xfd,0xff,0x16,0x00,' +` 0xf4,0xff,0x12,0x00,0xc8,0xff,0x3b,0x00,' +` 0xb8,0xff,0x85,0x00,0xaf,0xff,0xcd,0x00,' +` 0x8b,0xff,0x28,0x01,0x54,0xff,0x95,0x01,' +` 0x0f,0xff,0x20,0x02,0xaf,0xfe,0xc4,0x02,' +` 0x22,0xfe,0x95,0x03,0x5b,0xfd,0xb3,0x04,' +` 0x30,0xfc,0x60,0x06,0x2f,0xfa,0x5c,0x09,' +` 0xef,0xf5,0xf0,0x10,0xa8,0xe5,0x5f,0x64,' +` 0x97,0x3e,0x24,0xea,0x70,0x0f,0x5c,0xf7,' +` 0x02,0x09,0x45,0xfb,0x4b,0x06,0x1c,0xfd,' +` 0xb0,0x04,0x24,0xfe,0x8f,0x03,0xca,0xfe,' +` 0xb7,0x02,0x39,0xff,0x0e,0x02,0x85,0xff,' +` 0x87,0x01,0xb9,0xff,0x1a,0x01,0xdb,0xff,' +` 0xc2,0x00,0xef,0xff,0x83,0x00,0x28,0x00,' +` 0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xee,0xff,' +` 0xdf,0xff,0xd3,0xff,0xc1,0xff,0xb5,0xff,' +` 0xa5,0xff,0x99,0xff,0x94,0xff,0x7a,0xff,' +` 0x68,0xff,0x4e,0xff,0x3b,0xff,0x21,0xff,' +` 0x09,0xff,0xeb,0xfe,0xd4,0xfe,0xb8,0xfe,' +` 0xa3,0xfe,0x8d,0xfe,0x7c,0xfe,0x61,0xfe,' +` 0x49,0xfe,0x34,0xfe,0x23,0xfe,0x12,0xfe,' +` 0x0c,0xfe,0x05,0xfe,0x07,0xfe,0x05,0xfe,' +` 0xf3,0x7d,0x08,0xfe,0x10,0xfe,0x16,0xfe,' +` 0x1f,0xfe,0x2a,0xfe,0x3e,0xfe,0x52,0xfe,' +` 0x6c,0xfe,0x81,0xfe,0x9b,0xfe,0xb6,0xfe,' +` 0xd3,0xfe,0xed,0xfe,0x09,0xff,0x22,0xff,' +` 0x3c,0xff,0x52,0xff,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,' +` 0x06,0x00,0x07,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x05,0x00,' +` 0x06,0x00,0x07,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x9a,0x01,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0x01,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0x22,0x01,' +` 0x00,0x00,0x00,0x00,0x66,0xfe,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xde,0xfe,0xde,0xfe,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0xfe,' +` 0x00,0x00,0x00,0x00,0x22,0x01,0xde,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_50mm_azm90_90_13el0_0_13deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_azm90_90_13el0_0_13deg_16khz.m4 new file mode 100644 index 000000000000..b8f366cb99d8 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_azm90_90_13el0_0_13deg_16khz.m4 @@ -0,0 +1,360 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0b,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0b,0x00,0x00,0x02,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0a,0x00,0x42,0x00,0x59,0x00,' +` 0x12,0x01,0xef,0x00,0x6b,0x02,0xa9,0x01,' +` 0x1c,0x04,0x02,0x03,0xa7,0x08,0x38,0x04,' +` 0x30,0x0b,0x40,0x03,0x58,0x0b,0x31,0xfb,' +` 0x52,0x0f,0x92,0xed,0xe6,0x34,0x51,0x69,' +` 0x07,0xe4,0x0b,0x0c,0x08,0xf2,0xc7,0x02,' +` 0x01,0xf2,0x51,0xfb,0xe9,0xf3,0x75,0xfa,' +` 0xc7,0xf6,0x63,0xfd,0xdb,0xfa,0xee,0xfd,' +` 0xce,0xfc,0xb5,0xfe,0x61,0xfe,0x68,0xff,' +` 0x70,0xff,0xdb,0xff,0xf1,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf4,0xff,0xcd,0xff,0x8e,0xff,0x2d,0xff,' +` 0xbd,0xfe,0x24,0xfe,0x99,0xfd,0xd3,0xfc,' +` 0x61,0xfc,0x29,0xfb,0x9b,0xf8,0xda,0xf7,' +` 0x9b,0xf7,0xe7,0xf6,0x19,0xf9,0xf1,0xfb,' +` 0x5e,0xfc,0xad,0xfd,0xbb,0xfe,0xcb,0x7f,' +` 0x41,0x01,0x43,0x02,0x7e,0x03,0xd9,0x03,' +` 0x71,0x06,0x5c,0x08,0x95,0x07,0x38,0x07,' +` 0x69,0x06,0x17,0x04,0xf9,0x02,0x83,0x02,' +` 0xd1,0x01,0x53,0x01,0xd3,0x00,0x79,0x00,' +` 0x33,0x00,0x0d,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0a,0x00,0x3e,0x00,0x5c,0x00,' +` 0x02,0x01,0xfa,0x00,0x47,0x02,0xc4,0x01,' +` 0xdc,0x03,0xf2,0x02,0x2a,0x08,0xb0,0x04,' +` 0x73,0x0a,0x16,0x04,0x24,0x0a,0xde,0xfc,' +` 0xec,0x0c,0xf9,0xf1,0x4e,0x27,0x6c,0x72,' +` 0x53,0xe7,0x10,0x0a,0xa3,0xf3,0xec,0x01,' +` 0xa0,0xf3,0x9e,0xfa,0xb2,0xf4,0x13,0xfa,' +` 0x4b,0xf7,0x29,0xfd,0x2b,0xfb,0xce,0xfd,' +` 0xfc,0xfc,0xa6,0xfe,0x78,0xfe,0x63,0xff,' +` 0x78,0xff,0xda,0xff,0xf2,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf4,0xff,0xcf,0xff,0x90,0xff,0x32,0xff,' +` 0xc3,0xfe,0x2f,0xfe,0xa2,0xfd,0xe7,0xfc,' +` 0x68,0xfc,0x63,0xfb,0xcb,0xf8,0xea,0xf7,' +` 0xb9,0xf7,0xff,0xf6,0x81,0xf9,0xf9,0xfb,' +` 0x6b,0xfc,0xb2,0xfd,0xbf,0xfe,0xcb,0x7f,' +` 0x3d,0x01,0x3e,0x02,0x71,0x03,0xd1,0x03,' +` 0x11,0x06,0x46,0x08,0x79,0x07,0x2a,0x07,' +` 0x40,0x06,0xe7,0x03,0xf3,0x02,0x74,0x02,' +` 0xca,0x01,0x4b,0x01,0xcf,0x00,0x76,0x00,' +` 0x32,0x00,0x0c,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0b,0x00,0x30,0x00,0x6a,0x00,' +` 0xc7,0x00,0x29,0x01,0xbe,0x01,0x32,0x02,' +` 0xf1,0x02,0x48,0x03,0xd9,0x05,0xbd,0x06,' +` 0x6e,0x07,0x7c,0x07,0x52,0x05,0x34,0x03,' +` 0x00,0x04,0xf1,0x00,0xb2,0x03,0xb1,0x7f,' +` 0x4e,0xfc,0xfa,0xfe,0xcb,0xfb,0x9b,0xfc,' +` 0x2a,0xfa,0xc5,0xf7,0xcb,0xf7,0x58,0xf8,' +` 0x57,0xf9,0x26,0xfc,0x68,0xfc,0x3b,0xfd,' +` 0xb2,0xfd,0x5f,0xfe,0xcf,0xfe,0x47,0xff,' +` 0x95,0xff,0xd4,0xff,0xf5,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf5,0xff,0xd3,0xff,0x97,0xff,0x43,0xff,' +` 0xd6,0xfe,0x54,0xfe,0xc0,0xfd,0x27,0xfd,' +` 0x84,0xfc,0x01,0xfc,0x77,0xf9,0x28,0xf8,' +` 0x0e,0xf8,0x77,0xf7,0xae,0xfa,0x06,0xfc,' +` 0xa1,0xfc,0xc1,0xfd,0xd2,0xfe,0xcb,0x7f,' +` 0x2a,0x01,0x31,0x02,0x3e,0x03,0xc4,0x03,' +` 0xf8,0x04,0xd8,0x07,0x2d,0x07,0xf3,0x06,' +` 0xaa,0x05,0x61,0x03,0xdc,0x02,0x41,0x02,' +` 0xb3,0x01,0x30,0x01,0xc3,0x00,0x6c,0x00,' +` 0x2f,0x00,0x0b,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0d,0x00,0x1a,0x00,0x7b,0x00,' +` 0x6a,0x00,0x67,0x01,0xe3,0x00,0xca,0x02,' +` 0x5f,0x01,0x71,0x04,0xb4,0x01,0xf4,0x08,' +` 0x70,0x03,0x9b,0x0b,0x08,0xff,0xb7,0x0a,' +` 0x50,0xf9,0x18,0x11,0x01,0xe7,0xb4,0x67,' +` 0x58,0x37,0x6b,0xe8,0xaf,0x0a,0x2c,0xf3,' +` 0x73,0x03,0xfd,0xf4,0x8f,0xfc,0xd5,0xf5,' +` 0x90,0xfc,0xba,0xfa,0x6e,0xfe,0x6d,0xfc,' +` 0xd5,0xfe,0xfd,0xfd,0x5b,0xff,0x22,0xff,' +` 0xc5,0xff,0xcc,0xff,0xfa,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xff,0xda,0xff,0xa6,0xff,0x61,0xff,' +` 0xfb,0xfe,0x96,0xfe,0x01,0xfe,0x95,0xfd,' +` 0xd9,0xfc,0xc7,0xfc,0xd9,0xfa,0xcf,0xf8,' +` 0x7e,0xf8,0xe5,0xf8,0x30,0xfc,0x45,0xfc,' +` 0x12,0xfd,0xe1,0xfd,0xf7,0xfe,0xcb,0x7f,' +` 0x05,0x01,0x11,0x02,0xd0,0x02,0x89,0x03,' +` 0x90,0x03,0x87,0x06,0xc8,0x06,0x5f,0x06,' +` 0x77,0x04,0xb9,0x02,0x96,0x02,0xea,0x01,' +` 0x83,0x01,0x02,0x01,0xab,0x00,0x5b,0x00,' +` 0x29,0x00,0x09,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x26,0x00,0x31,0x00,' +` 0xa3,0x00,0x8a,0x00,0x7d,0x01,0xf8,0x00,' +` 0x97,0x02,0x2c,0x01,0x24,0x04,0xc0,0x03,' +` 0xd3,0x07,0xe4,0x00,0xf9,0x05,0xf7,0xfd,' +` 0xad,0x08,0xf6,0xf6,0xb1,0x18,0xf1,0x79,' +` 0x96,0xed,0x60,0x07,0x7e,0xf7,0x9d,0x01,' +` 0xbc,0xf9,0xcf,0xfd,0xea,0xf6,0x58,0xfc,' +` 0xb7,0xfb,0x70,0xfe,0xe8,0xfc,0xba,0xfe,' +` 0x12,0xfe,0x3c,0xff,0x0c,0xff,0xaa,0xff,' +` 0xad,0xff,0xeb,0xff,0xf7,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf9,0xff,' +` 0xe4,0xff,0xbe,0xff,0x8a,0xff,0x3e,0xff,' +` 0xed,0xfe,0x7f,0xfe,0x25,0xfe,0xaf,0xfd,' +` 0x79,0xfd,0xdb,0xfc,0x4f,0xfa,0x40,0xf9,' +` 0xae,0xfb,0x41,0xfd,0x2c,0xfd,0xc3,0xfd,' +` 0x3d,0xfe,0x26,0xff,0xcb,0x7f,0xd7,0x00,' +` 0xb8,0x01,0x27,0x02,0xae,0x02,0x91,0x02,' +` 0xf8,0x03,0x19,0x06,0x0b,0x05,0xba,0x02,' +` 0x23,0x02,0xe7,0x01,0x78,0x01,0x23,0x01,' +` 0xc3,0x00,0x7f,0x00,0x43,0x00,0x1e,0x00,' +` 0x07,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x07,0x00,0x01,0x00,0x46,0x00,' +` 0x00,0x00,0xd5,0x00,0xfd,0xff,0xb5,0x01,' +` 0xc9,0xff,0xda,0x02,0x39,0xff,0x7d,0x04,' +` 0xf2,0x00,0xda,0x06,0x8c,0xfb,0x4e,0x09,' +` 0xb1,0xf6,0xa6,0x10,0x6b,0xe5,0x9e,0x61,' +` 0x55,0x3f,0x91,0xe7,0xf2,0x0c,0xf4,0xf4,' +` 0x8b,0x05,0x22,0xf9,0x4a,0x01,0x4f,0xf8,' +` 0x52,0x01,0x67,0xfc,0x74,0x00,0xbd,0xfd,' +` 0x17,0x00,0xc2,0xfe,0x01,0x00,0x7f,0xff,' +` 0xff,0xff,0xe2,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,' +` 0xf0,0xff,0xde,0xff,0xbe,0xff,0x9f,0xff,' +` 0x5e,0xff,0x3b,0xff,0xe8,0xfe,0xe2,0xfe,' +` 0x68,0xfe,0xc2,0xfe,0xd6,0xfc,0x87,0xfb,' +` 0x8f,0xfe,0x32,0xfe,0xa8,0xfe,0xae,0xfe,' +` 0x11,0xff,0x5f,0xff,0xcb,0x7f,0x9f,0x00,' +` 0xe9,0x00,0x45,0x01,0x46,0x01,0xaf,0x01,' +` 0x53,0x01,0x0a,0x04,0xcd,0x02,0x13,0x01,' +` 0x59,0x01,0xeb,0x00,0xde,0x00,0x95,0x00,' +` 0x73,0x00,0x3f,0x00,0x26,0x00,0x0f,0x00,' +` 0x04,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xcb,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xcb,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfc,0xff,0xf0,0xff,0xde,0xff,' +` 0xbe,0xff,0x9f,0xff,0x5e,0xff,0x3b,0xff,' +` 0xe8,0xfe,0xe2,0xfe,0x68,0xfe,0xc2,0xfe,' +` 0xd6,0xfc,0x87,0xfb,0x8f,0xfe,0x32,0xfe,' +` 0xa8,0xfe,0xae,0xfe,0x11,0xff,0x5f,0xff,' +` 0xcb,0x7f,0x9f,0x00,0xe9,0x00,0x45,0x01,' +` 0x46,0x01,0xaf,0x01,0x53,0x01,0x0a,0x04,' +` 0xcd,0x02,0x13,0x01,0x59,0x01,0xeb,0x00,' +` 0xde,0x00,0x95,0x00,0x73,0x00,0x3f,0x00,' +` 0x26,0x00,0x0f,0x00,0x04,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,' +` 0x01,0x00,0x46,0x00,0x00,0x00,0xd5,0x00,' +` 0xfd,0xff,0xb5,0x01,0xc9,0xff,0xda,0x02,' +` 0x39,0xff,0x7d,0x04,0xf2,0x00,0xda,0x06,' +` 0x8c,0xfb,0x4e,0x09,0xb1,0xf6,0xa6,0x10,' +` 0x6b,0xe5,0x9e,0x61,0x55,0x3f,0x91,0xe7,' +` 0xf2,0x0c,0xf4,0xf4,0x8b,0x05,0x22,0xf9,' +` 0x4a,0x01,0x4f,0xf8,0x52,0x01,0x67,0xfc,' +` 0x74,0x00,0xbd,0xfd,0x17,0x00,0xc2,0xfe,' +` 0x01,0x00,0x7f,0xff,0xff,0xff,0xe2,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf9,0xff,0xe4,0xff,0xbe,0xff,' +` 0x8a,0xff,0x3e,0xff,0xed,0xfe,0x7f,0xfe,' +` 0x25,0xfe,0xaf,0xfd,0x79,0xfd,0xdb,0xfc,' +` 0x4f,0xfa,0x40,0xf9,0xae,0xfb,0x41,0xfd,' +` 0x2c,0xfd,0xc3,0xfd,0x3d,0xfe,0x26,0xff,' +` 0xcb,0x7f,0xd7,0x00,0xb8,0x01,0x27,0x02,' +` 0xae,0x02,0x91,0x02,0xf8,0x03,0x19,0x06,' +` 0x0b,0x05,0xba,0x02,0x23,0x02,0xe7,0x01,' +` 0x78,0x01,0x23,0x01,0xc3,0x00,0x7f,0x00,' +` 0x43,0x00,0x1e,0x00,0x07,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x26,0x00,0x31,0x00,0xa3,0x00,0x8a,0x00,' +` 0x7d,0x01,0xf8,0x00,0x97,0x02,0x2c,0x01,' +` 0x24,0x04,0xc0,0x03,0xd3,0x07,0xe4,0x00,' +` 0xf9,0x05,0xf7,0xfd,0xad,0x08,0xf6,0xf6,' +` 0xb1,0x18,0xf1,0x79,0x96,0xed,0x60,0x07,' +` 0x7e,0xf7,0x9d,0x01,0xbc,0xf9,0xcf,0xfd,' +` 0xea,0xf6,0x58,0xfc,0xb7,0xfb,0x70,0xfe,' +` 0xe8,0xfc,0xba,0xfe,0x12,0xfe,0x3c,0xff,' +` 0x0c,0xff,0xaa,0xff,0xad,0xff,0xeb,0xff,' +` 0xf7,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf6,0xff,0xda,0xff,' +` 0xa6,0xff,0x61,0xff,0xfb,0xfe,0x96,0xfe,' +` 0x01,0xfe,0x95,0xfd,0xd9,0xfc,0xc7,0xfc,' +` 0xd9,0xfa,0xcf,0xf8,0x7e,0xf8,0xe5,0xf8,' +` 0x30,0xfc,0x45,0xfc,0x12,0xfd,0xe1,0xfd,' +` 0xf7,0xfe,0xcb,0x7f,0x05,0x01,0x11,0x02,' +` 0xd0,0x02,0x89,0x03,0x90,0x03,0x87,0x06,' +` 0xc8,0x06,0x5f,0x06,0x77,0x04,0xb9,0x02,' +` 0x96,0x02,0xea,0x01,0x83,0x01,0x02,0x01,' +` 0xab,0x00,0x5b,0x00,0x29,0x00,0x09,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,' +` 0x1a,0x00,0x7b,0x00,0x6a,0x00,0x67,0x01,' +` 0xe3,0x00,0xca,0x02,0x5f,0x01,0x71,0x04,' +` 0xb4,0x01,0xf4,0x08,0x70,0x03,0x9b,0x0b,' +` 0x08,0xff,0xb7,0x0a,0x50,0xf9,0x18,0x11,' +` 0x01,0xe7,0xb4,0x67,0x58,0x37,0x6b,0xe8,' +` 0xaf,0x0a,0x2c,0xf3,0x73,0x03,0xfd,0xf4,' +` 0x8f,0xfc,0xd5,0xf5,0x90,0xfc,0xba,0xfa,' +` 0x6e,0xfe,0x6d,0xfc,0xd5,0xfe,0xfd,0xfd,' +` 0x5b,0xff,0x22,0xff,0xc5,0xff,0xcc,0xff,' +` 0xfa,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf5,0xff,0xd3,0xff,' +` 0x97,0xff,0x43,0xff,0xd6,0xfe,0x54,0xfe,' +` 0xc0,0xfd,0x27,0xfd,0x84,0xfc,0x01,0xfc,' +` 0x77,0xf9,0x28,0xf8,0x0e,0xf8,0x77,0xf7,' +` 0xae,0xfa,0x06,0xfc,0xa1,0xfc,0xc1,0xfd,' +` 0xd2,0xfe,0xcb,0x7f,0x2a,0x01,0x31,0x02,' +` 0x3e,0x03,0xc4,0x03,0xf8,0x04,0xd8,0x07,' +` 0x2d,0x07,0xf3,0x06,0xaa,0x05,0x61,0x03,' +` 0xdc,0x02,0x41,0x02,0xb3,0x01,0x30,0x01,' +` 0xc3,0x00,0x6c,0x00,0x2f,0x00,0x0b,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,' +` 0x30,0x00,0x6a,0x00,0xc7,0x00,0x29,0x01,' +` 0xbe,0x01,0x32,0x02,0xf1,0x02,0x48,0x03,' +` 0xd9,0x05,0xbd,0x06,0x6e,0x07,0x7c,0x07,' +` 0x52,0x05,0x34,0x03,0x00,0x04,0xf1,0x00,' +` 0xb2,0x03,0xb1,0x7f,0x4e,0xfc,0xfa,0xfe,' +` 0xcb,0xfb,0x9b,0xfc,0x2a,0xfa,0xc5,0xf7,' +` 0xcb,0xf7,0x58,0xf8,0x57,0xf9,0x26,0xfc,' +` 0x68,0xfc,0x3b,0xfd,0xb2,0xfd,0x5f,0xfe,' +` 0xcf,0xfe,0x47,0xff,0x95,0xff,0xd4,0xff,' +` 0xf5,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf4,0xff,0xcf,0xff,' +` 0x90,0xff,0x32,0xff,0xc3,0xfe,0x2f,0xfe,' +` 0xa2,0xfd,0xe7,0xfc,0x68,0xfc,0x63,0xfb,' +` 0xcb,0xf8,0xea,0xf7,0xb9,0xf7,0xff,0xf6,' +` 0x81,0xf9,0xf9,0xfb,0x6b,0xfc,0xb2,0xfd,' +` 0xbf,0xfe,0xcb,0x7f,0x3d,0x01,0x3e,0x02,' +` 0x71,0x03,0xd1,0x03,0x11,0x06,0x46,0x08,' +` 0x79,0x07,0x2a,0x07,0x40,0x06,0xe7,0x03,' +` 0xf3,0x02,0x74,0x02,0xca,0x01,0x4b,0x01,' +` 0xcf,0x00,0x76,0x00,0x32,0x00,0x0c,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,' +` 0x3e,0x00,0x5c,0x00,0x02,0x01,0xfa,0x00,' +` 0x47,0x02,0xc4,0x01,0xdc,0x03,0xf2,0x02,' +` 0x2a,0x08,0xb0,0x04,0x73,0x0a,0x16,0x04,' +` 0x24,0x0a,0xde,0xfc,0xec,0x0c,0xf9,0xf1,' +` 0x4e,0x27,0x6c,0x72,0x53,0xe7,0x10,0x0a,' +` 0xa3,0xf3,0xec,0x01,0xa0,0xf3,0x9e,0xfa,' +` 0xb2,0xf4,0x13,0xfa,0x4b,0xf7,0x29,0xfd,' +` 0x2b,0xfb,0xce,0xfd,0xfc,0xfc,0xa6,0xfe,' +` 0x78,0xfe,0x63,0xff,0x78,0xff,0xda,0xff,' +` 0xf2,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf4,0xff,0xcd,0xff,' +` 0x8e,0xff,0x2d,0xff,0xbd,0xfe,0x24,0xfe,' +` 0x99,0xfd,0xd3,0xfc,0x61,0xfc,0x29,0xfb,' +` 0x9b,0xf8,0xda,0xf7,0x9b,0xf7,0xe7,0xf6,' +` 0x19,0xf9,0xf1,0xfb,0x5e,0xfc,0xad,0xfd,' +` 0xbb,0xfe,0xcb,0x7f,0x41,0x01,0x43,0x02,' +` 0x7e,0x03,0xd9,0x03,0x71,0x06,0x5c,0x08,' +` 0x95,0x07,0x38,0x07,0x69,0x06,0x17,0x04,' +` 0xf9,0x02,0x83,0x02,0xd1,0x01,0x53,0x01,' +` 0xd3,0x00,0x79,0x00,0x33,0x00,0x0d,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,' +` 0x42,0x00,0x59,0x00,0x12,0x01,0xef,0x00,' +` 0x6b,0x02,0xa9,0x01,0x1c,0x04,0x02,0x03,' +` 0xa7,0x08,0x38,0x04,0x30,0x0b,0x40,0x03,' +` 0x58,0x0b,0x31,0xfb,0x52,0x0f,0x92,0xed,' +` 0xe6,0x34,0x51,0x69,0x07,0xe4,0x0b,0x0c,' +` 0x08,0xf2,0xc7,0x02,0x01,0xf2,0x51,0xfb,' +` 0xe9,0xf3,0x75,0xfa,0xc7,0xf6,0x63,0xfd,' +` 0xdb,0xfa,0xee,0xfd,0xce,0xfc,0xb5,0xfe,' +` 0x61,0xfe,0x68,0xff,0x70,0xff,0xdb,0xff,' +` 0xf1,0xff,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x06,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x12,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x16,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x00,0x66,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_50mm_azm90_90_13el0_0_13deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_azm90_90_13el0_0_13deg_48khz.m4 new file mode 100644 index 000000000000..7267c0a58d1c --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_azm90_90_13el0_0_13deg_48khz.m4 @@ -0,0 +1,516 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xe4,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xe4,0x0f,0x00,0x00,0x02,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x19,0x00,0x29,0x00,0x41,0x00,0x58,0x00,' +` 0x79,0x00,0x95,0x00,0xbd,0x00,0xdb,0x00,' +` 0x08,0x01,0x24,0x01,0x56,0x01,0x68,0x01,' +` 0xaa,0x01,0x58,0x01,0xf9,0x00,0x10,0x01,' +` 0x0a,0x01,0x06,0x01,0x04,0x01,0xef,0x00,' +` 0xed,0x00,0xc8,0x00,0xc8,0x00,0x91,0x00,' +` 0x9b,0x00,0x48,0x00,0x74,0x00,0xc5,0xff,' +` 0xeb,0x7f,0x3c,0x00,0x8b,0xff,0xb7,0xff,' +` 0x62,0xff,0x6b,0xff,0x32,0xff,0x30,0xff,' +` 0x09,0xff,0x05,0xff,0xee,0xfe,0xe9,0xfe,' +` 0xe3,0xfe,0xdb,0xfe,0xf1,0xfe,0x88,0xfe,' +` 0x28,0xfe,0x6d,0xfe,0x7c,0xfe,0xb1,0xfe,' +` 0xcc,0xfe,0xfc,0xfe,0x1b,0xff,0x46,0xff,' +` 0x64,0xff,0x89,0xff,0xa4,0xff,0xc1,0xff,' +` 0xd5,0xff,0xec,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xec,0xff,0xd5,0xff,0xc1,0xff,0xa4,0xff,' +` 0x89,0xff,0x65,0xff,0x45,0xff,0x1c,0xff,' +` 0xfb,0xfe,0xcd,0xfe,0xaf,0xfe,0x7e,0xfe,' +` 0x6a,0xfe,0x2b,0xfe,0x84,0xfe,0xf6,0xfe,' +` 0xd6,0xfe,0xe9,0xfe,0xe3,0xfe,0xf6,0xfe,' +` 0xfc,0xfe,0x14,0xff,0x24,0xff,0x40,0xff,' +` 0x59,0xff,0x79,0xff,0x98,0xff,0xba,0xff,' +` 0xdd,0xff,0xec,0x7f,0x23,0x00,0x45,0x00,' +` 0x67,0x00,0x84,0x00,0xa3,0x00,0xba,0x00,' +` 0xd4,0x00,0xe3,0x00,0xf8,0x00,0xfc,0x00,' +` 0x0c,0x01,0x05,0x01,0x14,0x01,0xf5,0x00,' +` 0x5a,0x01,0xa7,0x01,0x6a,0x01,0x55,0x01,' +` 0x25,0x01,0x07,0x01,0xdc,0x00,0xbc,0x00,' +` 0x96,0x00,0x78,0x00,0x58,0x00,0x41,0x00,' +` 0x29,0x00,0x19,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1d,0x00,0x1f,0x00,0x50,0x00,0x40,0x00,' +` 0x99,0x00,0x67,0x00,0xf6,0x00,0x8e,0x00,' +` 0x64,0x01,0xae,0x00,0xe0,0x01,0xbe,0x00,' +` 0x6f,0x02,0x69,0x00,0x0c,0x02,0xcd,0xff,' +` 0x86,0x02,0x4f,0xff,0x0a,0x03,0x97,0xfe,' +` 0xb7,0x03,0x81,0xfd,0xc5,0x04,0xb8,0xfb,' +` 0xce,0x06,0x0f,0xf8,0x97,0x0c,0xbd,0xe9,' +` 0x08,0x74,0xd1,0x24,0xe9,0xef,0xa4,0x09,' +` 0x44,0xf8,0xff,0x04,0xc4,0xfa,0xec,0x02,' +` 0xf7,0xfb,0xb3,0x01,0xb3,0xfc,0xe6,0x00,' +` 0x3b,0xfd,0x5b,0x00,0xaf,0xfd,0xf7,0xff,' +` 0x62,0xfd,0x2e,0xff,0xe2,0xfd,0x3d,0xff,' +` 0x61,0xfe,0x5b,0xff,0xd5,0xfe,0x83,0xff,' +` 0x3a,0xff,0xac,0xff,0x8d,0xff,0xd2,0xff,' +` 0xcb,0xff,0xf2,0xff,0xf7,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xef,0xff,0xd6,0xff,0xc1,0xff,0xa5,0xff,' +` 0x8a,0xff,0x67,0xff,0x47,0xff,0x1f,0xff,' +` 0xfd,0xfe,0xd2,0xfe,0xb2,0xfe,0x84,0xfe,' +` 0x6c,0xfe,0x36,0xfe,0xb9,0xfe,0xf6,0xfe,' +` 0xdc,0xfe,0xeb,0xfe,0xe7,0xfe,0xf8,0xfe,' +` 0x00,0xff,0x16,0xff,0x27,0xff,0x42,0xff,' +` 0x5b,0xff,0x7b,0xff,0x99,0xff,0xbb,0xff,' +` 0xdd,0xff,0xec,0x7f,0x23,0x00,0x44,0x00,' +` 0x66,0x00,0x83,0x00,0xa1,0x00,0xb8,0x00,' +` 0xd1,0x00,0xe1,0x00,0xf4,0x00,0xfa,0x00,' +` 0x08,0x01,0x03,0x01,0x0f,0x01,0xf4,0x00,' +` 0x2a,0x01,0x9d,0x01,0x69,0x01,0x4f,0x01,' +` 0x23,0x01,0x03,0x01,0xda,0x00,0xb9,0x00,' +` 0x94,0x00,0x77,0x00,0x58,0x00,0x3f,0x00,' +` 0x28,0x00,0x18,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x07,0x00,0x12,0x00,0x2b,0x00,0x36,0x00,' +` 0x5d,0x00,0x66,0x00,0x9e,0x00,0x9d,0x00,' +` 0xeb,0x00,0xd8,0x00,0x40,0x01,0x0f,0x01,' +` 0x9f,0x01,0xf6,0x00,0x18,0x01,0xaa,0x00,' +` 0x4e,0x01,0x95,0x00,0x73,0x01,0x62,0x00,' +` 0x90,0x01,0x0f,0x00,0xb6,0x01,0x8c,0xff,' +` 0x02,0x02,0xa9,0xfe,0xdf,0x02,0x66,0xfc,' +` 0x25,0x08,0x2b,0x7f,0xb5,0xf8,0x66,0x03,' +` 0x2b,0xfd,0x4d,0x01,0xf5,0xfd,0x6f,0x00,' +` 0x3a,0xfe,0xeb,0xff,0x5b,0xfe,0x94,0xff,' +` 0x74,0xfe,0x5d,0xff,0x96,0xfe,0x46,0xff,' +` 0xca,0xfe,0xd8,0xfe,0x30,0xfe,0xcc,0xfe,' +` 0x90,0xfe,0x03,0xff,0xe9,0xfe,0x40,0xff,' +` 0x3b,0xff,0x7d,0xff,0x83,0xff,0xb2,0xff,' +` 0xbd,0xff,0xe3,0xff,0xf1,0xff,0xfa,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xf2,0xff,0xdf,0xff,0xc1,0xff,0xac,0xff,' +` 0x8c,0xff,0x71,0xff,0x4a,0xff,0x2c,0xff,' +` 0x02,0xff,0xe5,0xfe,0xb5,0xfe,0xa0,0xfe,' +` 0x64,0xfe,0xa5,0xfe,0x14,0xff,0xf2,0xfe,' +` 0xfa,0xfe,0xec,0xfe,0xf9,0xfe,0xfd,0xfe,' +` 0x0f,0xff,0x1b,0xff,0x33,0xff,0x47,0xff,' +` 0x64,0xff,0x7f,0xff,0x9f,0xff,0xbe,0xff,' +` 0xdf,0xff,0xec,0x7f,0x21,0x00,0x42,0x00,' +` 0x60,0x00,0x7f,0x00,0x98,0x00,0xb3,0x00,' +` 0xc6,0x00,0xdb,0x00,0xe6,0x00,0xf6,0x00,' +` 0xf7,0x00,0x01,0x01,0xf3,0x00,0xf8,0x00,' +` 0xd7,0x00,0x39,0x01,0x70,0x01,0x36,0x01,' +` 0x20,0x01,0xf3,0x00,0xd6,0x00,0xae,0x00,' +` 0x91,0x00,0x6f,0x00,0x56,0x00,0x3b,0x00,' +` 0x29,0x00,0x13,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x05,0x00,0x0d,0x00,0x18,0x00,0x3d,0x00,' +` 0x46,0x00,0x72,0x00,0x77,0x00,0xb4,0x00,' +` 0xad,0x00,0xff,0x00,0xe2,0x00,0x56,0x01,' +` 0xd3,0x00,0xdf,0x00,0x95,0x00,0x10,0x01,' +` 0x8c,0x00,0x37,0x01,0x74,0x00,0x5b,0x01,' +` 0x41,0x00,0x76,0x01,0xe6,0xff,0x9f,0x01,' +` 0x54,0xff,0x03,0x02,0x3b,0xfe,0x6f,0x03,' +` 0xd2,0xf9,0x5a,0x7f,0xec,0x06,0x5e,0xfc,' +` 0xe3,0x01,0xea,0xfd,0xba,0x00,0x52,0xfe,' +` 0x21,0x00,0x7a,0xfe,0xc0,0xff,0x92,0xfe,' +` 0x88,0xff,0xb4,0xfe,0x6b,0xff,0xd9,0xfe,' +` 0x5f,0xff,0x08,0xff,0x27,0xff,0x7d,0xfe,' +` 0xfe,0xfe,0xd6,0xfe,0x33,0xff,0x26,0xff,' +` 0x6c,0xff,0x6d,0xff,0xa2,0xff,0xa8,0xff,' +` 0xd8,0xff,0xe9,0xff,0xf4,0xff,0xfa,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfa,0xff,0xf3,0xff,' +` 0xeb,0xff,0xd5,0xff,0xae,0xff,0x9a,0xff,' +` 0x78,0xff,0x5e,0xff,0x37,0xff,0x1d,0xff,' +` 0xf1,0xfe,0xdd,0xfe,0xa3,0xfe,0xef,0xfe,' +` 0x3f,0xff,0x1e,0xff,0x23,0xff,0x14,0xff,' +` 0x18,0xff,0x12,0xff,0x19,0xff,0x20,0xff,' +` 0x33,0xff,0x43,0xff,0x5b,0xff,0x71,0xff,' +` 0x8c,0xff,0xa7,0xff,0xc4,0xff,0xe2,0xff,' +` 0xec,0x7f,0x1e,0x00,0x3b,0x00,0x58,0x00,' +` 0x72,0x00,0x8c,0x00,0xa0,0x00,0xb6,0x00,' +` 0xc4,0x00,0xd5,0x00,0xdb,0x00,0xe0,0x00,' +` 0xd9,0x00,0xdb,0x00,0xcb,0x00,0xce,0x00,' +` 0xae,0x00,0xf4,0x00,0x34,0x01,0xfe,0x00,' +` 0xe8,0x00,0xbf,0x00,0xa5,0x00,0x82,0x00,' +` 0x6a,0x00,0x4c,0x00,0x39,0x00,0x1c,0x00,' +` 0x0c,0x00,0x06,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x08,0x00,0x01,0x00,0x1e,0x00,' +` 0x0b,0x00,0x6a,0x00,0x23,0x00,0xb7,0x00,' +` 0x30,0x00,0x19,0x01,0x39,0x00,0x5c,0x01,' +` 0x8f,0xff,0x90,0x01,0x4b,0xff,0x0a,0x02,' +` 0xe0,0xfe,0xa2,0x02,0x44,0xfe,0x64,0x03,' +` 0x62,0xfd,0x6e,0x04,0x0d,0xfc,0x00,0x06,' +` 0xcc,0xf9,0xd2,0x08,0x3d,0xf5,0x0f,0x10,' +` 0x67,0xe5,0xde,0x50,0x9a,0x51,0xb6,0xe4,' +` 0xf2,0x0f,0x3a,0xf4,0x55,0x08,0x7b,0xf8,' +` 0x33,0x05,0x83,0xfa,0x76,0x03,0xc7,0xfb,' +` 0x57,0x02,0xa9,0xfc,0x8f,0x01,0x58,0xfd,' +` 0x00,0x01,0xe8,0xfd,0x97,0x00,0x69,0xfe,' +` 0x0c,0x00,0x2f,0xfe,0xbd,0xff,0xb3,0xfe,' +` 0xbe,0xff,0x21,0xff,0xc9,0xff,0x8c,0xff,' +` 0x02,0x00,0xce,0xff,0xfe,0xff,0xee,0xff,' +` 0xff,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfc,0xff,0xf7,0xff,0xf0,0xff,' +` 0xe7,0xff,0xdb,0xff,0xa9,0xff,0x8c,0xff,' +` 0x73,0xff,0x56,0xff,0x39,0xff,0x1a,0xff,' +` 0x04,0xff,0x6c,0xff,0x6f,0xff,0x62,0xff,' +` 0x5c,0xff,0x55,0xff,0x52,0xff,0x4f,0xff,' +` 0x50,0xff,0x51,0xff,0x56,0xff,0x5c,0xff,' +` 0x65,0xff,0x76,0xff,0x8a,0xff,0x9f,0xff,' +` 0xb7,0xff,0xce,0xff,0xe7,0xff,0xec,0x7f,' +` 0x19,0x00,0x31,0x00,0x48,0x00,0x5f,0x00,' +` 0x73,0x00,0x86,0x00,0x95,0x00,0x9d,0x00,' +` 0xa2,0x00,0xa5,0x00,0xa6,0x00,0xa5,0x00,' +` 0xa1,0x00,0x9d,0x00,0x95,0x00,0x8f,0x00,' +` 0x81,0x00,0x83,0x00,0xdb,0x00,0xc5,0x00,' +` 0xa7,0x00,0x8c,0x00,0x71,0x00,0x5a,0x00,' +` 0x40,0x00,0x1a,0x00,0x10,0x00,0x09,0x00,' +` 0x04,0x00,0x01,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x00,0x00,0x0a,0x00,' +` 0x00,0x00,0x1b,0x00,0xfe,0xff,0x3a,0x00,' +` 0x33,0x00,0x9a,0x00,0x4b,0x00,0xb7,0x00,' +` 0xd1,0xff,0xbd,0x00,0xb7,0xff,0xf8,0x00,' +` 0x8a,0xff,0x40,0x01,0x47,0xff,0x98,0x01,' +` 0xe8,0xfe,0x0a,0x02,0x5f,0xfe,0xa9,0x02,' +` 0x90,0xfd,0x9f,0x03,0x33,0xfc,0x70,0x05,' +` 0x45,0xf9,0x69,0x0a,0x01,0xed,0x8e,0x78,' +` 0x09,0x1c,0x5e,0xf3,0xca,0x07,0xf6,0xf9,' +` 0x39,0x04,0x12,0xfc,0xae,0x02,0x23,0xfd,' +` 0xca,0x01,0xce,0xfd,0x35,0x01,0x46,0xfe,' +` 0xce,0x00,0xa3,0xfe,0x84,0x00,0xef,0xfe,' +` 0x51,0x00,0x2e,0xff,0x30,0x00,0x56,0xff,' +` 0xad,0xff,0x46,0xff,0xbc,0xff,0xa1,0xff,' +` 0x06,0x00,0xd8,0xff,0x00,0x00,0xef,0xff,' +` 0x00,0x00,0xfc,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xfb,0xff,0xf7,0xff,' +` 0xf3,0xff,0xec,0xff,0xe9,0xff,0xd0,0xff,' +` 0x8d,0xff,0x84,0xff,0x5c,0xff,0x9e,0xff,' +` 0xc4,0xff,0xb1,0xff,0xb3,0xff,0xa9,0xff,' +` 0xa8,0xff,0xa2,0xff,0xa3,0xff,0xa0,0xff,' +` 0xa2,0xff,0xa1,0xff,0xa5,0xff,0xa7,0xff,' +` 0xad,0xff,0xb1,0xff,0xb9,0xff,0xbf,0xff,' +` 0xcc,0xff,0xdd,0xff,0xef,0xff,0xec,0x7f,' +` 0x11,0x00,0x22,0x00,0x33,0x00,0x40,0x00,' +` 0x46,0x00,0x4c,0x00,0x50,0x00,0x55,0x00,' +` 0x57,0x00,0x5a,0x00,0x59,0x00,0x5a,0x00,' +` 0x56,0x00,0x56,0x00,0x50,0x00,0x4f,0x00,' +` 0x45,0x00,0x46,0x00,0x34,0x00,0x54,0x00,' +` 0x8a,0x00,0x66,0x00,0x5c,0x00,0x25,0x00,' +` 0x11,0x00,0x0e,0x00,0x09,0x00,0x05,0x00,' +` 0x02,0x00,0x01,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xfb,0xff,0xf7,0xff,0xf3,0xff,0xec,0xff,' +` 0xe9,0xff,0xd0,0xff,0x8d,0xff,0x84,0xff,' +` 0x5c,0xff,0x9e,0xff,0xc4,0xff,0xb1,0xff,' +` 0xb3,0xff,0xa9,0xff,0xa8,0xff,0xa2,0xff,' +` 0xa3,0xff,0xa0,0xff,0xa2,0xff,0xa1,0xff,' +` 0xa5,0xff,0xa7,0xff,0xad,0xff,0xb1,0xff,' +` 0xb9,0xff,0xbf,0xff,0xcc,0xff,0xdd,0xff,' +` 0xef,0xff,0xec,0x7f,0x11,0x00,0x22,0x00,' +` 0x33,0x00,0x40,0x00,0x46,0x00,0x4c,0x00,' +` 0x50,0x00,0x55,0x00,0x57,0x00,0x5a,0x00,' +` 0x59,0x00,0x5a,0x00,0x56,0x00,0x56,0x00,' +` 0x50,0x00,0x4f,0x00,0x45,0x00,0x46,0x00,' +` 0x34,0x00,0x54,0x00,0x8a,0x00,0x66,0x00,' +` 0x5c,0x00,0x25,0x00,0x11,0x00,0x0e,0x00,' +` 0x09,0x00,0x05,0x00,0x02,0x00,0x01,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x0a,0x00,0x00,0x00,0x1b,0x00,' +` 0xfe,0xff,0x3a,0x00,0x33,0x00,0x9a,0x00,' +` 0x4b,0x00,0xb7,0x00,0xd1,0xff,0xbd,0x00,' +` 0xb7,0xff,0xf8,0x00,0x8a,0xff,0x40,0x01,' +` 0x47,0xff,0x98,0x01,0xe8,0xfe,0x0a,0x02,' +` 0x5f,0xfe,0xa9,0x02,0x90,0xfd,0x9f,0x03,' +` 0x33,0xfc,0x70,0x05,0x45,0xf9,0x69,0x0a,' +` 0x01,0xed,0x8e,0x78,0x09,0x1c,0x5e,0xf3,' +` 0xca,0x07,0xf6,0xf9,0x39,0x04,0x12,0xfc,' +` 0xae,0x02,0x23,0xfd,0xca,0x01,0xce,0xfd,' +` 0x35,0x01,0x46,0xfe,0xce,0x00,0xa3,0xfe,' +` 0x84,0x00,0xef,0xfe,0x51,0x00,0x2e,0xff,' +` 0x30,0x00,0x56,0xff,0xad,0xff,0x46,0xff,' +` 0xbc,0xff,0xa1,0xff,0x06,0x00,0xd8,0xff,' +` 0x00,0x00,0xef,0xff,0x00,0x00,0xfc,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff,' +` 0xf7,0xff,0xf0,0xff,0xe7,0xff,0xdb,0xff,' +` 0xa9,0xff,0x8c,0xff,0x73,0xff,0x56,0xff,' +` 0x39,0xff,0x1a,0xff,0x04,0xff,0x6c,0xff,' +` 0x6f,0xff,0x62,0xff,0x5c,0xff,0x55,0xff,' +` 0x52,0xff,0x4f,0xff,0x50,0xff,0x51,0xff,' +` 0x56,0xff,0x5c,0xff,0x65,0xff,0x76,0xff,' +` 0x8a,0xff,0x9f,0xff,0xb7,0xff,0xce,0xff,' +` 0xe7,0xff,0xec,0x7f,0x19,0x00,0x31,0x00,' +` 0x48,0x00,0x5f,0x00,0x73,0x00,0x86,0x00,' +` 0x95,0x00,0x9d,0x00,0xa2,0x00,0xa5,0x00,' +` 0xa6,0x00,0xa5,0x00,0xa1,0x00,0x9d,0x00,' +` 0x95,0x00,0x8f,0x00,0x81,0x00,0x83,0x00,' +` 0xdb,0x00,0xc5,0x00,0xa7,0x00,0x8c,0x00,' +` 0x71,0x00,0x5a,0x00,0x40,0x00,0x1a,0x00,' +` 0x10,0x00,0x09,0x00,0x04,0x00,0x01,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,' +` 0x01,0x00,0x1e,0x00,0x0b,0x00,0x6a,0x00,' +` 0x23,0x00,0xb7,0x00,0x30,0x00,0x19,0x01,' +` 0x39,0x00,0x5c,0x01,0x8f,0xff,0x90,0x01,' +` 0x4b,0xff,0x0a,0x02,0xe0,0xfe,0xa2,0x02,' +` 0x44,0xfe,0x64,0x03,0x62,0xfd,0x6e,0x04,' +` 0x0d,0xfc,0x00,0x06,0xcc,0xf9,0xd2,0x08,' +` 0x3d,0xf5,0x0f,0x10,0x67,0xe5,0xde,0x50,' +` 0x9a,0x51,0xb6,0xe4,0xf2,0x0f,0x3a,0xf4,' +` 0x55,0x08,0x7b,0xf8,0x33,0x05,0x83,0xfa,' +` 0x76,0x03,0xc7,0xfb,0x57,0x02,0xa9,0xfc,' +` 0x8f,0x01,0x58,0xfd,0x00,0x01,0xe8,0xfd,' +` 0x97,0x00,0x69,0xfe,0x0c,0x00,0x2f,0xfe,' +` 0xbd,0xff,0xb3,0xfe,0xbe,0xff,0x21,0xff,' +` 0xc9,0xff,0x8c,0xff,0x02,0x00,0xce,0xff,' +` 0xfe,0xff,0xee,0xff,0xff,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfa,0xff,0xf3,0xff,0xeb,0xff,0xd5,0xff,' +` 0xae,0xff,0x9a,0xff,0x78,0xff,0x5e,0xff,' +` 0x37,0xff,0x1d,0xff,0xf1,0xfe,0xdd,0xfe,' +` 0xa3,0xfe,0xef,0xfe,0x3f,0xff,0x1e,0xff,' +` 0x23,0xff,0x14,0xff,0x18,0xff,0x12,0xff,' +` 0x19,0xff,0x20,0xff,0x33,0xff,0x43,0xff,' +` 0x5b,0xff,0x71,0xff,0x8c,0xff,0xa7,0xff,' +` 0xc4,0xff,0xe2,0xff,0xec,0x7f,0x1e,0x00,' +` 0x3b,0x00,0x58,0x00,0x72,0x00,0x8c,0x00,' +` 0xa0,0x00,0xb6,0x00,0xc4,0x00,0xd5,0x00,' +` 0xdb,0x00,0xe0,0x00,0xd9,0x00,0xdb,0x00,' +` 0xcb,0x00,0xce,0x00,0xae,0x00,0xf4,0x00,' +` 0x34,0x01,0xfe,0x00,0xe8,0x00,0xbf,0x00,' +` 0xa5,0x00,0x82,0x00,0x6a,0x00,0x4c,0x00,' +` 0x39,0x00,0x1c,0x00,0x0c,0x00,0x06,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x05,0x00,0x0d,0x00,' +` 0x18,0x00,0x3d,0x00,0x46,0x00,0x72,0x00,' +` 0x77,0x00,0xb4,0x00,0xad,0x00,0xff,0x00,' +` 0xe2,0x00,0x56,0x01,0xd3,0x00,0xdf,0x00,' +` 0x95,0x00,0x10,0x01,0x8c,0x00,0x37,0x01,' +` 0x74,0x00,0x5b,0x01,0x41,0x00,0x76,0x01,' +` 0xe6,0xff,0x9f,0x01,0x54,0xff,0x03,0x02,' +` 0x3b,0xfe,0x6f,0x03,0xd2,0xf9,0x5a,0x7f,' +` 0xec,0x06,0x5e,0xfc,0xe3,0x01,0xea,0xfd,' +` 0xba,0x00,0x52,0xfe,0x21,0x00,0x7a,0xfe,' +` 0xc0,0xff,0x92,0xfe,0x88,0xff,0xb4,0xfe,' +` 0x6b,0xff,0xd9,0xfe,0x5f,0xff,0x08,0xff,' +` 0x27,0xff,0x7d,0xfe,0xfe,0xfe,0xd6,0xfe,' +` 0x33,0xff,0x26,0xff,0x6c,0xff,0x6d,0xff,' +` 0xa2,0xff,0xa8,0xff,0xd8,0xff,0xe9,0xff,' +` 0xf4,0xff,0xfa,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xf2,0xff,0xdf,0xff,' +` 0xc1,0xff,0xac,0xff,0x8c,0xff,0x71,0xff,' +` 0x4a,0xff,0x2c,0xff,0x02,0xff,0xe5,0xfe,' +` 0xb5,0xfe,0xa0,0xfe,0x64,0xfe,0xa5,0xfe,' +` 0x14,0xff,0xf2,0xfe,0xfa,0xfe,0xec,0xfe,' +` 0xf9,0xfe,0xfd,0xfe,0x0f,0xff,0x1b,0xff,' +` 0x33,0xff,0x47,0xff,0x64,0xff,0x7f,0xff,' +` 0x9f,0xff,0xbe,0xff,0xdf,0xff,0xec,0x7f,' +` 0x21,0x00,0x42,0x00,0x60,0x00,0x7f,0x00,' +` 0x98,0x00,0xb3,0x00,0xc6,0x00,0xdb,0x00,' +` 0xe6,0x00,0xf6,0x00,0xf7,0x00,0x01,0x01,' +` 0xf3,0x00,0xf8,0x00,0xd7,0x00,0x39,0x01,' +` 0x70,0x01,0x36,0x01,0x20,0x01,0xf3,0x00,' +` 0xd6,0x00,0xae,0x00,0x91,0x00,0x6f,0x00,' +` 0x56,0x00,0x3b,0x00,0x29,0x00,0x13,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x07,0x00,0x12,0x00,' +` 0x2b,0x00,0x36,0x00,0x5d,0x00,0x66,0x00,' +` 0x9e,0x00,0x9d,0x00,0xeb,0x00,0xd8,0x00,' +` 0x40,0x01,0x0f,0x01,0x9f,0x01,0xf6,0x00,' +` 0x18,0x01,0xaa,0x00,0x4e,0x01,0x95,0x00,' +` 0x73,0x01,0x62,0x00,0x90,0x01,0x0f,0x00,' +` 0xb6,0x01,0x8c,0xff,0x02,0x02,0xa9,0xfe,' +` 0xdf,0x02,0x66,0xfc,0x25,0x08,0x2b,0x7f,' +` 0xb5,0xf8,0x66,0x03,0x2b,0xfd,0x4d,0x01,' +` 0xf5,0xfd,0x6f,0x00,0x3a,0xfe,0xeb,0xff,' +` 0x5b,0xfe,0x94,0xff,0x74,0xfe,0x5d,0xff,' +` 0x96,0xfe,0x46,0xff,0xca,0xfe,0xd8,0xfe,' +` 0x30,0xfe,0xcc,0xfe,0x90,0xfe,0x03,0xff,' +` 0xe9,0xfe,0x40,0xff,0x3b,0xff,0x7d,0xff,' +` 0x83,0xff,0xb2,0xff,0xbd,0xff,0xe3,0xff,' +` 0xf1,0xff,0xfa,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xef,0xff,0xd6,0xff,' +` 0xc1,0xff,0xa5,0xff,0x8a,0xff,0x67,0xff,' +` 0x47,0xff,0x1f,0xff,0xfd,0xfe,0xd2,0xfe,' +` 0xb2,0xfe,0x84,0xfe,0x6c,0xfe,0x36,0xfe,' +` 0xb9,0xfe,0xf6,0xfe,0xdc,0xfe,0xeb,0xfe,' +` 0xe7,0xfe,0xf8,0xfe,0x00,0xff,0x16,0xff,' +` 0x27,0xff,0x42,0xff,0x5b,0xff,0x7b,0xff,' +` 0x99,0xff,0xbb,0xff,0xdd,0xff,0xec,0x7f,' +` 0x23,0x00,0x44,0x00,0x66,0x00,0x83,0x00,' +` 0xa1,0x00,0xb8,0x00,0xd1,0x00,0xe1,0x00,' +` 0xf4,0x00,0xfa,0x00,0x08,0x01,0x03,0x01,' +` 0x0f,0x01,0xf4,0x00,0x2a,0x01,0x9d,0x01,' +` 0x69,0x01,0x4f,0x01,0x23,0x01,0x03,0x01,' +` 0xda,0x00,0xb9,0x00,0x94,0x00,0x77,0x00,' +` 0x58,0x00,0x3f,0x00,0x28,0x00,0x18,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1d,0x00,0x1f,0x00,' +` 0x50,0x00,0x40,0x00,0x99,0x00,0x67,0x00,' +` 0xf6,0x00,0x8e,0x00,0x64,0x01,0xae,0x00,' +` 0xe0,0x01,0xbe,0x00,0x6f,0x02,0x69,0x00,' +` 0x0c,0x02,0xcd,0xff,0x86,0x02,0x4f,0xff,' +` 0x0a,0x03,0x97,0xfe,0xb7,0x03,0x81,0xfd,' +` 0xc5,0x04,0xb8,0xfb,0xce,0x06,0x0f,0xf8,' +` 0x97,0x0c,0xbd,0xe9,0x08,0x74,0xd1,0x24,' +` 0xe9,0xef,0xa4,0x09,0x44,0xf8,0xff,0x04,' +` 0xc4,0xfa,0xec,0x02,0xf7,0xfb,0xb3,0x01,' +` 0xb3,0xfc,0xe6,0x00,0x3b,0xfd,0x5b,0x00,' +` 0xaf,0xfd,0xf7,0xff,0x62,0xfd,0x2e,0xff,' +` 0xe2,0xfd,0x3d,0xff,0x61,0xfe,0x5b,0xff,' +` 0xd5,0xfe,0x83,0xff,0x3a,0xff,0xac,0xff,' +` 0x8d,0xff,0xd2,0xff,0xcb,0xff,0xf2,0xff,' +` 0xf7,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd5,0xff,' +` 0xc1,0xff,0xa4,0xff,0x89,0xff,0x65,0xff,' +` 0x45,0xff,0x1c,0xff,0xfb,0xfe,0xcd,0xfe,' +` 0xaf,0xfe,0x7e,0xfe,0x6a,0xfe,0x2b,0xfe,' +` 0x84,0xfe,0xf6,0xfe,0xd6,0xfe,0xe9,0xfe,' +` 0xe3,0xfe,0xf6,0xfe,0xfc,0xfe,0x14,0xff,' +` 0x24,0xff,0x40,0xff,0x59,0xff,0x79,0xff,' +` 0x98,0xff,0xba,0xff,0xdd,0xff,0xec,0x7f,' +` 0x23,0x00,0x45,0x00,0x67,0x00,0x84,0x00,' +` 0xa3,0x00,0xba,0x00,0xd4,0x00,0xe3,0x00,' +` 0xf8,0x00,0xfc,0x00,0x0c,0x01,0x05,0x01,' +` 0x14,0x01,0xf5,0x00,0x5a,0x01,0xa7,0x01,' +` 0x6a,0x01,0x55,0x01,0x25,0x01,0x07,0x01,' +` 0xdc,0x00,0xbc,0x00,0x96,0x00,0x78,0x00,' +` 0x58,0x00,0x41,0x00,0x29,0x00,0x19,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x29,0x00,' +` 0x41,0x00,0x58,0x00,0x79,0x00,0x95,0x00,' +` 0xbd,0x00,0xdb,0x00,0x08,0x01,0x24,0x01,' +` 0x56,0x01,0x68,0x01,0xaa,0x01,0x58,0x01,' +` 0xf9,0x00,0x10,0x01,0x0a,0x01,0x06,0x01,' +` 0x04,0x01,0xef,0x00,0xed,0x00,0xc8,0x00,' +` 0xc8,0x00,0x91,0x00,0x9b,0x00,0x48,0x00,' +` 0x74,0x00,0xc5,0xff,0xeb,0x7f,0x3c,0x00,' +` 0x8b,0xff,0xb7,0xff,0x62,0xff,0x6b,0xff,' +` 0x32,0xff,0x30,0xff,0x09,0xff,0x05,0xff,' +` 0xee,0xfe,0xe9,0xfe,0xe3,0xfe,0xdb,0xfe,' +` 0xf1,0xfe,0x88,0xfe,0x28,0xfe,0x6d,0xfe,' +` 0x7c,0xfe,0xb1,0xfe,0xcc,0xfe,0xfc,0xfe,' +` 0x1b,0xff,0x46,0xff,0x64,0xff,0x89,0xff,' +` 0xa4,0xff,0xc1,0xff,0xd5,0xff,0xec,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x06,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x12,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x16,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x00,0x66,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm0_30_90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm0_30_90deg_16khz.m4 new file mode 100644 index 000000000000..554372e308ec --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm0_30_90deg_16khz.m4 @@ -0,0 +1,256 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf9,0xff,0xee,0xff,' +` 0xe1,0xff,0xcd,0xff,0xb6,0xff,0x97,0xff,' +` 0x77,0xff,0x4b,0xff,0x22,0xff,0xe9,0xfe,' +` 0xb7,0xfe,0x72,0xfe,0x3b,0xfe,0xea,0xfd,' +` 0xa4,0xfd,0x3a,0xfd,0xf7,0xfc,0x87,0xfc,' +` 0x5f,0xfc,0x0c,0xfc,0x27,0xfc,0xa5,0xfb,' +` 0xb7,0xf8,0xe9,0xf7,0x18,0xfb,0x03,0xfd,' +` 0x07,0xfd,0xb4,0xfd,0x39,0xfe,0x26,0xff,' +` 0xec,0x7f,0xd9,0x00,0xc3,0x01,0x43,0x02,' +` 0xea,0x02,0xe9,0x02,0xc2,0x04,0xcd,0x07,' +` 0xfc,0x06,0x26,0x04,0xa5,0x03,0xb8,0x03,' +` 0x64,0x03,0x38,0x03,0xcb,0x02,0x87,0x02,' +` 0x21,0x02,0xdd,0x01,0x90,0x01,0x5a,0x01,' +` 0x1a,0x01,0xea,0x00,0xb7,0x00,0x91,0x00,' +` 0x6a,0x00,0x4e,0x00,0x34,0x00,0x21,0x00,' +` 0x12,0x00,0x08,0x00,0x02,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x0a,0x00,0x0e,0x00,0x29,0x00,0x28,0x00,' +` 0x61,0x00,0x52,0x00,0xb4,0x00,0x8b,0x00,' +` 0x25,0x01,0xd4,0x00,0xb4,0x01,0x27,0x01,' +` 0x60,0x02,0x8d,0x01,0x40,0x03,0xfa,0x01,' +` 0x36,0x04,0x3d,0x02,0x10,0x05,0xff,0x01,' +` 0x4e,0x06,0x31,0x05,0x03,0x0a,0x11,0x01,' +` 0xc8,0x06,0xc9,0xfd,0x1f,0x09,0xbb,0xf6,' +` 0xeb,0x18,0x10,0x7a,0x91,0xed,0x71,0x07,' +` 0x47,0xf7,0xb2,0x01,0x30,0xf9,0x83,0xfd,' +` 0x1e,0xf5,0x52,0xfb,0x11,0xfa,0x9e,0xfd,' +` 0xb9,0xfa,0x83,0xfd,0x8d,0xfb,0xd6,0xfd,' +` 0x82,0xfc,0x4b,0xfe,0x64,0xfd,0xb1,0xfe,' +` 0x13,0xfe,0x09,0xff,0xa9,0xfe,0x58,0xff,' +` 0x23,0xff,0x97,0xff,0x80,0xff,0xc7,0xff,' +` 0xc1,0xff,0xe8,0xff,0xeb,0xff,0xfa,0xff,' +` 0xfe,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x0a,0x00,0x0e,0x00,' +` 0x29,0x00,0x28,0x00,0x61,0x00,0x52,0x00,' +` 0xb4,0x00,0x8b,0x00,0x25,0x01,0xd4,0x00,' +` 0xb4,0x01,0x27,0x01,0x60,0x02,0x8d,0x01,' +` 0x40,0x03,0xfa,0x01,0x36,0x04,0x3d,0x02,' +` 0x10,0x05,0xff,0x01,0x4e,0x06,0x31,0x05,' +` 0x03,0x0a,0x11,0x01,0xc8,0x06,0xc9,0xfd,' +` 0x1f,0x09,0xbb,0xf6,0xeb,0x18,0x10,0x7a,' +` 0x91,0xed,0x71,0x07,0x47,0xf7,0xb2,0x01,' +` 0x30,0xf9,0x83,0xfd,0x1e,0xf5,0x52,0xfb,' +` 0x11,0xfa,0x9e,0xfd,0xb9,0xfa,0x83,0xfd,' +` 0x8d,0xfb,0xd6,0xfd,0x82,0xfc,0x4b,0xfe,' +` 0x64,0xfd,0xb1,0xfe,0x13,0xfe,0x09,0xff,' +` 0xa9,0xfe,0x58,0xff,0x23,0xff,0x97,0xff,' +` 0x80,0xff,0xc7,0xff,0xc1,0xff,0xe8,0xff,' +` 0xeb,0xff,0xfa,0xff,0xfe,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf9,0xff,0xee,0xff,0xe1,0xff,0xcd,0xff,' +` 0xb6,0xff,0x97,0xff,0x77,0xff,0x4b,0xff,' +` 0x22,0xff,0xe9,0xfe,0xb7,0xfe,0x72,0xfe,' +` 0x3b,0xfe,0xea,0xfd,0xa4,0xfd,0x3a,0xfd,' +` 0xf7,0xfc,0x87,0xfc,0x5f,0xfc,0x0c,0xfc,' +` 0x27,0xfc,0xa5,0xfb,0xb7,0xf8,0xe9,0xf7,' +` 0x18,0xfb,0x03,0xfd,0x07,0xfd,0xb4,0xfd,' +` 0x39,0xfe,0x26,0xff,0xec,0x7f,0xd9,0x00,' +` 0xc3,0x01,0x43,0x02,0xea,0x02,0xe9,0x02,' +` 0xc2,0x04,0xcd,0x07,0xfc,0x06,0x26,0x04,' +` 0xa5,0x03,0xb8,0x03,0x64,0x03,0x38,0x03,' +` 0xcb,0x02,0x87,0x02,0x21,0x02,0xdd,0x01,' +` 0x90,0x01,0x5a,0x01,0x1a,0x01,0xea,0x00,' +` 0xb7,0x00,0x91,0x00,0x6a,0x00,0x4e,0x00,' +` 0x34,0x00,0x21,0x00,0x12,0x00,0x08,0x00,' +` 0x02,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xf2,0xff,' +` 0xe1,0xff,0xc7,0xff,0xa6,0xff,0x7a,0xff,' +` 0x49,0xff,0x08,0xff,0xc8,0xfe,0x72,0xfe,' +` 0x23,0xfe,0xba,0xfd,0x5d,0xfd,0xd1,0xfc,' +` 0x66,0xfc,0xc9,0xfb,0x63,0xfb,0xbc,0xfa,' +` 0x74,0xfa,0xca,0xf9,0xd3,0xf9,0xa2,0xf8,' +` 0xc2,0xf5,0x93,0xf5,0xf1,0xf5,0xac,0xf5,' +` 0x7f,0xf8,0xbc,0xfb,0x46,0xfc,0xa8,0xfd,' +` 0xba,0xfe,0xec,0x7f,0x44,0x01,0x52,0x02,' +` 0xab,0x03,0x2f,0x04,0x51,0x07,0x04,0x0a,' +` 0xb3,0x09,0xff,0x09,0xc3,0x09,0xfb,0x06,' +` 0xd0,0x05,0xcd,0x05,0x25,0x05,0xd8,0x04,' +` 0x35,0x04,0xce,0x03,0x38,0x03,0xcf,0x02,' +` 0x4c,0x02,0xf3,0x01,0x91,0x01,0x48,0x01,' +` 0xfa,0x00,0xc0,0x00,0x88,0x00,0x5e,0x00,' +` 0x3a,0x00,0x20,0x00,0x0e,0x00,0x03,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x11,0x00,0x19,0x00,0x48,0x00,0x4a,0x00,' +` 0xa9,0x00,0x95,0x00,0x39,0x01,0xfc,0x00,' +` 0xf9,0x01,0x7a,0x01,0xee,0x02,0x1c,0x02,' +` 0x21,0x04,0xcc,0x02,0x78,0x05,0x6b,0x03,' +` 0xd8,0x06,0xd5,0x03,0x09,0x08,0x21,0x05,' +` 0x2c,0x0d,0xd7,0x05,0x50,0x0e,0xe5,0x03,' +` 0xe1,0x0c,0xc6,0xfa,0x1b,0x10,0x19,0xed,' +` 0x61,0x35,0x6c,0x69,0x00,0xe4,0x27,0x0c,' +` 0xad,0xf1,0xeb,0x02,0xc9,0xf0,0xaf,0xfa,' +` 0x84,0xf1,0xe8,0xf8,0x3b,0xf3,0x06,0xfc,' +` 0x3a,0xf7,0xf3,0xfb,0xa0,0xf8,0x57,0xfc,' +` 0x13,0xfa,0xf9,0xfc,0x76,0xfb,0xae,0xfd,' +` 0xb5,0xfc,0x4f,0xfe,0xb1,0xfd,0xd5,0xfe,' +` 0x80,0xfe,0x44,0xff,0x20,0xff,0x99,0xff,' +` 0x92,0xff,0xd4,0xff,0xda,0xff,0xf6,0xff,' +` 0xfc,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x11,0x00,0x19,0x00,' +` 0x48,0x00,0x4a,0x00,0xa9,0x00,0x95,0x00,' +` 0x39,0x01,0xfc,0x00,0xf9,0x01,0x7a,0x01,' +` 0xee,0x02,0x1c,0x02,0x21,0x04,0xcc,0x02,' +` 0x78,0x05,0x6b,0x03,0xd8,0x06,0xd5,0x03,' +` 0x09,0x08,0x21,0x05,0x2c,0x0d,0xd7,0x05,' +` 0x50,0x0e,0xe5,0x03,0xe1,0x0c,0xc6,0xfa,' +` 0x1b,0x10,0x19,0xed,0x61,0x35,0x6c,0x69,' +` 0x00,0xe4,0x27,0x0c,0xad,0xf1,0xeb,0x02,' +` 0xc9,0xf0,0xaf,0xfa,0x84,0xf1,0xe8,0xf8,' +` 0x3b,0xf3,0x06,0xfc,0x3a,0xf7,0xf3,0xfb,' +` 0xa0,0xf8,0x57,0xfc,0x13,0xfa,0xf9,0xfc,' +` 0x76,0xfb,0xae,0xfd,0xb5,0xfc,0x4f,0xfe,' +` 0xb1,0xfd,0xd5,0xfe,0x80,0xfe,0x44,0xff,' +` 0x20,0xff,0x99,0xff,0x92,0xff,0xd4,0xff,' +` 0xda,0xff,0xf6,0xff,0xfc,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xf2,0xff,0xe1,0xff,0xc7,0xff,' +` 0xa6,0xff,0x7a,0xff,0x49,0xff,0x08,0xff,' +` 0xc8,0xfe,0x72,0xfe,0x23,0xfe,0xba,0xfd,' +` 0x5d,0xfd,0xd1,0xfc,0x66,0xfc,0xc9,0xfb,' +` 0x63,0xfb,0xbc,0xfa,0x74,0xfa,0xca,0xf9,' +` 0xd3,0xf9,0xa2,0xf8,0xc2,0xf5,0x93,0xf5,' +` 0xf1,0xf5,0xac,0xf5,0x7f,0xf8,0xbc,0xfb,' +` 0x46,0xfc,0xa8,0xfd,0xba,0xfe,0xec,0x7f,' +` 0x44,0x01,0x52,0x02,0xab,0x03,0x2f,0x04,' +` 0x51,0x07,0x04,0x0a,0xb3,0x09,0xff,0x09,' +` 0xc3,0x09,0xfb,0x06,0xd0,0x05,0xcd,0x05,' +` 0x25,0x05,0xd8,0x04,0x35,0x04,0xce,0x03,' +` 0x38,0x03,0xcf,0x02,0x4c,0x02,0xf3,0x01,' +` 0x91,0x01,0x48,0x01,0xfa,0x00,0xc0,0x00,' +` 0x88,0x00,0x5e,0x00,0x3a,0x00,0x20,0x00,' +` 0x0e,0x00,0x03,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x66,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm0_30_90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm0_30_90deg_48khz.m4 new file mode 100644 index 000000000000..a367efa64ad2 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm0_30_90deg_48khz.m4 @@ -0,0 +1,256 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff,' +` 0xf7,0xff,0xf0,0xff,0xe7,0xff,0xdb,0xff,' +` 0xa9,0xff,0x8c,0xff,0x73,0xff,0x56,0xff,' +` 0x39,0xff,0x1a,0xff,0x04,0xff,0x6c,0xff,' +` 0x6f,0xff,0x62,0xff,0x5c,0xff,0x55,0xff,' +` 0x52,0xff,0x4f,0xff,0x50,0xff,0x51,0xff,' +` 0x56,0xff,0x5c,0xff,0x65,0xff,0x76,0xff,' +` 0x8a,0xff,0x9f,0xff,0xb7,0xff,0xce,0xff,' +` 0xe7,0xff,0xec,0x7f,0x19,0x00,0x31,0x00,' +` 0x48,0x00,0x5f,0x00,0x73,0x00,0x86,0x00,' +` 0x95,0x00,0x9d,0x00,0xa2,0x00,0xa5,0x00,' +` 0xa6,0x00,0xa5,0x00,0xa1,0x00,0x9d,0x00,' +` 0x95,0x00,0x8f,0x00,0x81,0x00,0x83,0x00,' +` 0xdb,0x00,0xc5,0x00,0xa7,0x00,0x8c,0x00,' +` 0x71,0x00,0x5a,0x00,0x40,0x00,0x1a,0x00,' +` 0x10,0x00,0x09,0x00,0x04,0x00,0x01,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,' +` 0x01,0x00,0x1e,0x00,0x0b,0x00,0x6a,0x00,' +` 0x23,0x00,0xb7,0x00,0x30,0x00,0x19,0x01,' +` 0x39,0x00,0x5c,0x01,0x8f,0xff,0x90,0x01,' +` 0x4b,0xff,0x0a,0x02,0xe0,0xfe,0xa2,0x02,' +` 0x44,0xfe,0x64,0x03,0x62,0xfd,0x6e,0x04,' +` 0x0d,0xfc,0x00,0x06,0xcc,0xf9,0xd2,0x08,' +` 0x3d,0xf5,0x0f,0x10,0x67,0xe5,0xde,0x50,' +` 0x9a,0x51,0xb6,0xe4,0xf2,0x0f,0x3a,0xf4,' +` 0x55,0x08,0x7b,0xf8,0x33,0x05,0x83,0xfa,' +` 0x76,0x03,0xc7,0xfb,0x57,0x02,0xa9,0xfc,' +` 0x8f,0x01,0x58,0xfd,0x00,0x01,0xe8,0xfd,' +` 0x97,0x00,0x69,0xfe,0x0c,0x00,0x2f,0xfe,' +` 0xbd,0xff,0xb3,0xfe,0xbe,0xff,0x21,0xff,' +` 0xc9,0xff,0x8c,0xff,0x02,0x00,0xce,0xff,' +` 0xfe,0xff,0xee,0xff,0xff,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x08,0x00,0x01,0x00,0x1e,0x00,' +` 0x0b,0x00,0x6a,0x00,0x23,0x00,0xb7,0x00,' +` 0x30,0x00,0x19,0x01,0x39,0x00,0x5c,0x01,' +` 0x8f,0xff,0x90,0x01,0x4b,0xff,0x0a,0x02,' +` 0xe0,0xfe,0xa2,0x02,0x44,0xfe,0x64,0x03,' +` 0x62,0xfd,0x6e,0x04,0x0d,0xfc,0x00,0x06,' +` 0xcc,0xf9,0xd2,0x08,0x3d,0xf5,0x0f,0x10,' +` 0x67,0xe5,0xde,0x50,0x9a,0x51,0xb6,0xe4,' +` 0xf2,0x0f,0x3a,0xf4,0x55,0x08,0x7b,0xf8,' +` 0x33,0x05,0x83,0xfa,0x76,0x03,0xc7,0xfb,' +` 0x57,0x02,0xa9,0xfc,0x8f,0x01,0x58,0xfd,' +` 0x00,0x01,0xe8,0xfd,0x97,0x00,0x69,0xfe,' +` 0x0c,0x00,0x2f,0xfe,0xbd,0xff,0xb3,0xfe,' +` 0xbe,0xff,0x21,0xff,0xc9,0xff,0x8c,0xff,' +` 0x02,0x00,0xce,0xff,0xfe,0xff,0xee,0xff,' +` 0xff,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfc,0xff,0xf7,0xff,0xf0,0xff,' +` 0xe7,0xff,0xdb,0xff,0xa9,0xff,0x8c,0xff,' +` 0x73,0xff,0x56,0xff,0x39,0xff,0x1a,0xff,' +` 0x04,0xff,0x6c,0xff,0x6f,0xff,0x62,0xff,' +` 0x5c,0xff,0x55,0xff,0x52,0xff,0x4f,0xff,' +` 0x50,0xff,0x51,0xff,0x56,0xff,0x5c,0xff,' +` 0x65,0xff,0x76,0xff,0x8a,0xff,0x9f,0xff,' +` 0xb7,0xff,0xce,0xff,0xe7,0xff,0xec,0x7f,' +` 0x19,0x00,0x31,0x00,0x48,0x00,0x5f,0x00,' +` 0x73,0x00,0x86,0x00,0x95,0x00,0x9d,0x00,' +` 0xa2,0x00,0xa5,0x00,0xa6,0x00,0xa5,0x00,' +` 0xa1,0x00,0x9d,0x00,0x95,0x00,0x8f,0x00,' +` 0x81,0x00,0x83,0x00,0xdb,0x00,0xc5,0x00,' +` 0xa7,0x00,0x8c,0x00,0x71,0x00,0x5a,0x00,' +` 0x40,0x00,0x1a,0x00,0x10,0x00,0x09,0x00,' +` 0x04,0x00,0x01,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd5,0xff,' +` 0xc1,0xff,0xa4,0xff,0x89,0xff,0x65,0xff,' +` 0x45,0xff,0x1c,0xff,0xfb,0xfe,0xcd,0xfe,' +` 0xaf,0xfe,0x7e,0xfe,0x6a,0xfe,0x2b,0xfe,' +` 0x84,0xfe,0xf6,0xfe,0xd6,0xfe,0xe9,0xfe,' +` 0xe3,0xfe,0xf6,0xfe,0xfc,0xfe,0x14,0xff,' +` 0x24,0xff,0x40,0xff,0x59,0xff,0x79,0xff,' +` 0x98,0xff,0xba,0xff,0xdd,0xff,0xec,0x7f,' +` 0x23,0x00,0x45,0x00,0x67,0x00,0x84,0x00,' +` 0xa3,0x00,0xba,0x00,0xd4,0x00,0xe3,0x00,' +` 0xf8,0x00,0xfc,0x00,0x0c,0x01,0x05,0x01,' +` 0x14,0x01,0xf5,0x00,0x5a,0x01,0xa7,0x01,' +` 0x6a,0x01,0x55,0x01,0x25,0x01,0x07,0x01,' +` 0xdc,0x00,0xbc,0x00,0x96,0x00,0x78,0x00,' +` 0x58,0x00,0x41,0x00,0x29,0x00,0x19,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x29,0x00,' +` 0x41,0x00,0x58,0x00,0x79,0x00,0x95,0x00,' +` 0xbd,0x00,0xdb,0x00,0x08,0x01,0x24,0x01,' +` 0x56,0x01,0x68,0x01,0xaa,0x01,0x58,0x01,' +` 0xf9,0x00,0x10,0x01,0x0a,0x01,0x06,0x01,' +` 0x04,0x01,0xef,0x00,0xed,0x00,0xc8,0x00,' +` 0xc8,0x00,0x91,0x00,0x9b,0x00,0x48,0x00,' +` 0x74,0x00,0xc5,0xff,0xeb,0x7f,0x3c,0x00,' +` 0x8b,0xff,0xb7,0xff,0x62,0xff,0x6b,0xff,' +` 0x32,0xff,0x30,0xff,0x09,0xff,0x05,0xff,' +` 0xee,0xfe,0xe9,0xfe,0xe3,0xfe,0xdb,0xfe,' +` 0xf1,0xfe,0x88,0xfe,0x28,0xfe,0x6d,0xfe,' +` 0x7c,0xfe,0xb1,0xfe,0xcc,0xfe,0xfc,0xfe,' +` 0x1b,0xff,0x46,0xff,0x64,0xff,0x89,0xff,' +` 0xa4,0xff,0xc1,0xff,0xd5,0xff,0xec,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x19,0x00,0x29,0x00,0x41,0x00,0x58,0x00,' +` 0x79,0x00,0x95,0x00,0xbd,0x00,0xdb,0x00,' +` 0x08,0x01,0x24,0x01,0x56,0x01,0x68,0x01,' +` 0xaa,0x01,0x58,0x01,0xf9,0x00,0x10,0x01,' +` 0x0a,0x01,0x06,0x01,0x04,0x01,0xef,0x00,' +` 0xed,0x00,0xc8,0x00,0xc8,0x00,0x91,0x00,' +` 0x9b,0x00,0x48,0x00,0x74,0x00,0xc5,0xff,' +` 0xeb,0x7f,0x3c,0x00,0x8b,0xff,0xb7,0xff,' +` 0x62,0xff,0x6b,0xff,0x32,0xff,0x30,0xff,' +` 0x09,0xff,0x05,0xff,0xee,0xfe,0xe9,0xfe,' +` 0xe3,0xfe,0xdb,0xfe,0xf1,0xfe,0x88,0xfe,' +` 0x28,0xfe,0x6d,0xfe,0x7c,0xfe,0xb1,0xfe,' +` 0xcc,0xfe,0xfc,0xfe,0x1b,0xff,0x46,0xff,' +` 0x64,0xff,0x89,0xff,0xa4,0xff,0xc1,0xff,' +` 0xd5,0xff,0xec,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xec,0xff,0xd5,0xff,0xc1,0xff,0xa4,0xff,' +` 0x89,0xff,0x65,0xff,0x45,0xff,0x1c,0xff,' +` 0xfb,0xfe,0xcd,0xfe,0xaf,0xfe,0x7e,0xfe,' +` 0x6a,0xfe,0x2b,0xfe,0x84,0xfe,0xf6,0xfe,' +` 0xd6,0xfe,0xe9,0xfe,0xe3,0xfe,0xf6,0xfe,' +` 0xfc,0xfe,0x14,0xff,0x24,0xff,0x40,0xff,' +` 0x59,0xff,0x79,0xff,0x98,0xff,0xba,0xff,' +` 0xdd,0xff,0xec,0x7f,0x23,0x00,0x45,0x00,' +` 0x67,0x00,0x84,0x00,0xa3,0x00,0xba,0x00,' +` 0xd4,0x00,0xe3,0x00,0xf8,0x00,0xfc,0x00,' +` 0x0c,0x01,0x05,0x01,0x14,0x01,0xf5,0x00,' +` 0x5a,0x01,0xa7,0x01,0x6a,0x01,0x55,0x01,' +` 0x25,0x01,0x07,0x01,0xdc,0x00,0xbc,0x00,' +` 0x96,0x00,0x78,0x00,0x58,0x00,0x41,0x00,' +` 0x29,0x00,0x19,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x66,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm90deg_16khz.m4 new file mode 100644 index 000000000000..a4c259802e65 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm90deg_16khz.m4 @@ -0,0 +1,91 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x9c,0x02,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x9c,0x02,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xf2,0xff,' +` 0xe1,0xff,0xc7,0xff,0xa6,0xff,0x7a,0xff,' +` 0x49,0xff,0x08,0xff,0xc8,0xfe,0x72,0xfe,' +` 0x23,0xfe,0xba,0xfd,0x5d,0xfd,0xd1,0xfc,' +` 0x66,0xfc,0xc9,0xfb,0x63,0xfb,0xbc,0xfa,' +` 0x74,0xfa,0xca,0xf9,0xd3,0xf9,0xa2,0xf8,' +` 0xc2,0xf5,0x93,0xf5,0xf1,0xf5,0xac,0xf5,' +` 0x7f,0xf8,0xbc,0xfb,0x46,0xfc,0xa8,0xfd,' +` 0xba,0xfe,0xec,0x7f,0x44,0x01,0x52,0x02,' +` 0xab,0x03,0x2f,0x04,0x51,0x07,0x04,0x0a,' +` 0xb3,0x09,0xff,0x09,0xc3,0x09,0xfb,0x06,' +` 0xd0,0x05,0xcd,0x05,0x25,0x05,0xd8,0x04,' +` 0x35,0x04,0xce,0x03,0x38,0x03,0xcf,0x02,' +` 0x4c,0x02,0xf3,0x01,0x91,0x01,0x48,0x01,' +` 0xfa,0x00,0xc0,0x00,0x88,0x00,0x5e,0x00,' +` 0x3a,0x00,0x20,0x00,0x0e,0x00,0x03,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x11,0x00,0x19,0x00,0x48,0x00,0x4a,0x00,' +` 0xa9,0x00,0x95,0x00,0x39,0x01,0xfc,0x00,' +` 0xf9,0x01,0x7a,0x01,0xee,0x02,0x1c,0x02,' +` 0x21,0x04,0xcc,0x02,0x78,0x05,0x6b,0x03,' +` 0xd8,0x06,0xd5,0x03,0x09,0x08,0x21,0x05,' +` 0x2c,0x0d,0xd7,0x05,0x50,0x0e,0xe5,0x03,' +` 0xe1,0x0c,0xc6,0xfa,0x1b,0x10,0x19,0xed,' +` 0x61,0x35,0x6c,0x69,0x00,0xe4,0x27,0x0c,' +` 0xad,0xf1,0xeb,0x02,0xc9,0xf0,0xaf,0xfa,' +` 0x84,0xf1,0xe8,0xf8,0x3b,0xf3,0x06,0xfc,' +` 0x3a,0xf7,0xf3,0xfb,0xa0,0xf8,0x57,0xfc,' +` 0x13,0xfa,0xf9,0xfc,0x76,0xfb,0xae,0xfd,' +` 0xb5,0xfc,0x4f,0xfe,0xb1,0xfd,0xd5,0xfe,' +` 0x80,0xfe,0x44,0xff,0x20,0xff,0x99,0xff,' +` 0x92,0xff,0xd4,0xff,0xda,0xff,0xf6,0xff,' +` 0xfc,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x11,0x00,0x19,0x00,' +` 0x48,0x00,0x4a,0x00,0xa9,0x00,0x95,0x00,' +` 0x39,0x01,0xfc,0x00,0xf9,0x01,0x7a,0x01,' +` 0xee,0x02,0x1c,0x02,0x21,0x04,0xcc,0x02,' +` 0x78,0x05,0x6b,0x03,0xd8,0x06,0xd5,0x03,' +` 0x09,0x08,0x21,0x05,0x2c,0x0d,0xd7,0x05,' +` 0x50,0x0e,0xe5,0x03,0xe1,0x0c,0xc6,0xfa,' +` 0x1b,0x10,0x19,0xed,0x61,0x35,0x6c,0x69,' +` 0x00,0xe4,0x27,0x0c,0xad,0xf1,0xeb,0x02,' +` 0xc9,0xf0,0xaf,0xfa,0x84,0xf1,0xe8,0xf8,' +` 0x3b,0xf3,0x06,0xfc,0x3a,0xf7,0xf3,0xfb,' +` 0xa0,0xf8,0x57,0xfc,0x13,0xfa,0xf9,0xfc,' +` 0x76,0xfb,0xae,0xfd,0xb5,0xfc,0x4f,0xfe,' +` 0xb1,0xfd,0xd5,0xfe,0x80,0xfe,0x44,0xff,' +` 0x20,0xff,0x99,0xff,0x92,0xff,0xd4,0xff,' +` 0xda,0xff,0xf6,0xff,0xfc,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xf2,0xff,0xe1,0xff,0xc7,0xff,' +` 0xa6,0xff,0x7a,0xff,0x49,0xff,0x08,0xff,' +` 0xc8,0xfe,0x72,0xfe,0x23,0xfe,0xba,0xfd,' +` 0x5d,0xfd,0xd1,0xfc,0x66,0xfc,0xc9,0xfb,' +` 0x63,0xfb,0xbc,0xfa,0x74,0xfa,0xca,0xf9,' +` 0xd3,0xf9,0xa2,0xf8,0xc2,0xf5,0x93,0xf5,' +` 0xf1,0xf5,0xac,0xf5,0x7f,0xf8,0xbc,0xfb,' +` 0x46,0xfc,0xa8,0xfd,0xba,0xfe,0xec,0x7f,' +` 0x44,0x01,0x52,0x02,0xab,0x03,0x2f,0x04,' +` 0x51,0x07,0x04,0x0a,0xb3,0x09,0xff,0x09,' +` 0xc3,0x09,0xfb,0x06,0xd0,0x05,0xcd,0x05,' +` 0x25,0x05,0xd8,0x04,0x35,0x04,0xce,0x03,' +` 0x38,0x03,0xcf,0x02,0x4c,0x02,0xf3,0x01,' +` 0x91,0x01,0x48,0x01,0xfa,0x00,0xc0,0x00,' +` 0x88,0x00,0x5e,0x00,0x3a,0x00,0x20,0x00,' +` 0x0e,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm90deg_48khz.m4 new file mode 100644 index 000000000000..2b2f92f1c242 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_50mm_pm90deg_48khz.m4 @@ -0,0 +1,91 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x9c,0x02,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x9c,0x02,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd5,0xff,' +` 0xc1,0xff,0xa4,0xff,0x89,0xff,0x65,0xff,' +` 0x45,0xff,0x1c,0xff,0xfb,0xfe,0xcd,0xfe,' +` 0xaf,0xfe,0x7e,0xfe,0x6a,0xfe,0x2b,0xfe,' +` 0x84,0xfe,0xf6,0xfe,0xd6,0xfe,0xe9,0xfe,' +` 0xe3,0xfe,0xf6,0xfe,0xfc,0xfe,0x14,0xff,' +` 0x24,0xff,0x40,0xff,0x59,0xff,0x79,0xff,' +` 0x98,0xff,0xba,0xff,0xdd,0xff,0xec,0x7f,' +` 0x23,0x00,0x45,0x00,0x67,0x00,0x84,0x00,' +` 0xa3,0x00,0xba,0x00,0xd4,0x00,0xe3,0x00,' +` 0xf8,0x00,0xfc,0x00,0x0c,0x01,0x05,0x01,' +` 0x14,0x01,0xf5,0x00,0x5a,0x01,0xa7,0x01,' +` 0x6a,0x01,0x55,0x01,0x25,0x01,0x07,0x01,' +` 0xdc,0x00,0xbc,0x00,0x96,0x00,0x78,0x00,' +` 0x58,0x00,0x41,0x00,0x29,0x00,0x19,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x19,0x00,0x29,0x00,' +` 0x41,0x00,0x58,0x00,0x79,0x00,0x95,0x00,' +` 0xbd,0x00,0xdb,0x00,0x08,0x01,0x24,0x01,' +` 0x56,0x01,0x68,0x01,0xaa,0x01,0x58,0x01,' +` 0xf9,0x00,0x10,0x01,0x0a,0x01,0x06,0x01,' +` 0x04,0x01,0xef,0x00,0xed,0x00,0xc8,0x00,' +` 0xc8,0x00,0x91,0x00,0x9b,0x00,0x48,0x00,' +` 0x74,0x00,0xc5,0xff,0xeb,0x7f,0x3c,0x00,' +` 0x8b,0xff,0xb7,0xff,0x62,0xff,0x6b,0xff,' +` 0x32,0xff,0x30,0xff,0x09,0xff,0x05,0xff,' +` 0xee,0xfe,0xe9,0xfe,0xe3,0xfe,0xdb,0xfe,' +` 0xf1,0xfe,0x88,0xfe,0x28,0xfe,0x6d,0xfe,' +` 0x7c,0xfe,0xb1,0xfe,0xcc,0xfe,0xfc,0xfe,' +` 0x1b,0xff,0x46,0xff,0x64,0xff,0x89,0xff,' +` 0xa4,0xff,0xc1,0xff,0xd5,0xff,0xec,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x19,0x00,0x29,0x00,0x41,0x00,0x58,0x00,' +` 0x79,0x00,0x95,0x00,0xbd,0x00,0xdb,0x00,' +` 0x08,0x01,0x24,0x01,0x56,0x01,0x68,0x01,' +` 0xaa,0x01,0x58,0x01,0xf9,0x00,0x10,0x01,' +` 0x0a,0x01,0x06,0x01,0x04,0x01,0xef,0x00,' +` 0xed,0x00,0xc8,0x00,0xc8,0x00,0x91,0x00,' +` 0x9b,0x00,0x48,0x00,0x74,0x00,0xc5,0xff,' +` 0xeb,0x7f,0x3c,0x00,0x8b,0xff,0xb7,0xff,' +` 0x62,0xff,0x6b,0xff,0x32,0xff,0x30,0xff,' +` 0x09,0xff,0x05,0xff,0xee,0xfe,0xe9,0xfe,' +` 0xe3,0xfe,0xdb,0xfe,0xf1,0xfe,0x88,0xfe,' +` 0x28,0xfe,0x6d,0xfe,0x7c,0xfe,0xb1,0xfe,' +` 0xcc,0xfe,0xfc,0xfe,0x1b,0xff,0x46,0xff,' +` 0x64,0xff,0x89,0xff,0xa4,0xff,0xc1,0xff,' +` 0xd5,0xff,0xec,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xec,0xff,0xd5,0xff,0xc1,0xff,0xa4,0xff,' +` 0x89,0xff,0x65,0xff,0x45,0xff,0x1c,0xff,' +` 0xfb,0xfe,0xcd,0xfe,0xaf,0xfe,0x7e,0xfe,' +` 0x6a,0xfe,0x2b,0xfe,0x84,0xfe,0xf6,0xfe,' +` 0xd6,0xfe,0xe9,0xfe,0xe3,0xfe,0xf6,0xfe,' +` 0xfc,0xfe,0x14,0xff,0x24,0xff,0x40,0xff,' +` 0x59,0xff,0x79,0xff,0x98,0xff,0xba,0xff,' +` 0xdd,0xff,0xec,0x7f,0x23,0x00,0x45,0x00,' +` 0x67,0x00,0x84,0x00,0xa3,0x00,0xba,0x00,' +` 0xd4,0x00,0xe3,0x00,0xf8,0x00,0xfc,0x00,' +` 0x0c,0x01,0x05,0x01,0x14,0x01,0xf5,0x00,' +` 0x5a,0x01,0xa7,0x01,0x6a,0x01,0x55,0x01,' +` 0x25,0x01,0x07,0x01,0xdc,0x00,0xbc,0x00,' +` 0x96,0x00,0x78,0x00,0x58,0x00,0x41,0x00,' +` 0x29,0x00,0x19,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_68mm_azm90_90_13el0_0_13deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_azm90_90_13el0_0_13deg_16khz.m4 new file mode 100644 index 000000000000..f5ac91ca142e --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_azm90_90_13el0_0_13deg_16khz.m4 @@ -0,0 +1,360 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0b,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x0b,0x00,0x00,0x02,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x08,0x00,0x32,0x00,0x49,0x00,0xc6,0x00,' +` 0xb6,0x00,0x32,0x02,0x22,0x02,0xcd,0x03,' +` 0xdb,0x02,0x60,0x05,0x41,0x03,0x14,0x06,' +` 0xe6,0xff,0x34,0x06,0x52,0xfd,0xa0,0x08,' +` 0x1b,0xf6,0x8a,0x19,0x82,0x79,0x66,0xed,' +` 0x0f,0x08,0xae,0xf7,0x1b,0x02,0x90,0xf9,' +` 0x89,0xff,0x8f,0xf8,0x3e,0xfc,0xc4,0xf9,' +` 0x88,0xfc,0x5f,0xfb,0x3a,0xfd,0x63,0xfd,' +` 0x07,0xff,0xcd,0xfe,0x81,0xff,0x91,0xff,' +` 0xde,0xff,0xf4,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xff,0xd7,0xff,0xa3,0xff,0x60,0xff,' +` 0x05,0xff,0xb4,0xfe,0xb3,0xfd,0x9f,0xfc,' +` 0x38,0xfc,0x79,0xfb,0x32,0xfb,0x7d,0xfa,' +` 0x25,0xfb,0x03,0xfd,0x1d,0xfd,0xa1,0xfd,' +` 0x14,0xfe,0xb4,0xfe,0x53,0xff,0xcb,0x7f,' +` 0xaa,0x00,0x43,0x01,0xd9,0x01,0x3f,0x02,' +` 0xb2,0x02,0xbf,0x02,0x63,0x04,0xe2,0x04,' +` 0x2a,0x04,0xd4,0x03,0x1b,0x03,0xac,0x02,' +` 0xbe,0x01,0xec,0x00,0xa4,0x00,0x5c,0x00,' +` 0x2a,0x00,0x0a,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x09,0x00,0x2c,0x00,0x52,0x00,0xaf,0x00,' +` 0xd0,0x00,0xd1,0x01,0x73,0x02,0x51,0x03,' +` 0x6d,0x03,0x8f,0x04,0x3d,0x04,0xbe,0x04,' +` 0x9a,0x01,0x01,0x04,0x5d,0x00,0x5b,0x04,' +` 0x2b,0xfd,0x2e,0x09,0xe3,0x7e,0xab,0xf7,' +` 0x8e,0x02,0x84,0xfb,0x78,0xff,0xb3,0xfb,' +` 0x24,0xfe,0x6f,0xfa,0x32,0xfb,0xb7,0xfa,' +` 0xed,0xfb,0xf2,0xfb,0xe4,0xfc,0xb5,0xfd,' +` 0xdb,0xfe,0xf3,0xfe,0x70,0xff,0x9d,0xff,' +` 0xdb,0xff,0xf5,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xff,0xd8,0xff,0xa4,0xff,0x63,0xff,' +` 0x09,0xff,0xbb,0xfe,0xd5,0xfd,0xa6,0xfc,' +` 0x47,0xfc,0x83,0xfb,0x46,0xfb,0x84,0xfa,' +` 0x76,0xfb,0x19,0xfd,0x20,0xfd,0xab,0xfd,' +` 0x17,0xfe,0xb9,0xfe,0x55,0xff,0xcb,0x7f,' +` 0xa9,0x00,0x3e,0x01,0xd6,0x01,0x35,0x02,' +` 0xaf,0x02,0xab,0x02,0x19,0x04,0xdc,0x04,' +` 0x19,0x04,0xcb,0x03,0x0e,0x03,0xa7,0x02,' +` 0xa4,0x01,0xe7,0x00,0xa1,0x00,0x5a,0x00,' +` 0x29,0x00,0x0a,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x1b,0x00,0x70,0x00,0x64,0x00,' +` 0x34,0x01,0xc1,0x00,0x12,0x03,0x19,0x02,' +` 0xdc,0x04,0x65,0x02,0xcd,0x06,0x2d,0x01,' +` 0xff,0x05,0x3e,0xfe,0x2a,0x08,0xb8,0xf9,' +` 0xab,0x0d,0xfc,0xe9,0xda,0x72,0x74,0x26,' +` 0x75,0xee,0x90,0x08,0xa6,0xf6,0xd6,0x02,' +` 0x0c,0xf9,0x38,0x00,0x7f,0xf8,0x6a,0xfd,' +` 0x37,0xfa,0xa0,0xfd,0xed,0xfb,0xa8,0xfe,' +` 0x5f,0xfe,0x64,0xff,0x3e,0xff,0xc3,0xff,' +` 0xcf,0xff,0xf9,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf7,0xff,0xda,0xff,0xab,0xff,0x6c,0xff,' +` 0x19,0xff,0xcb,0xfe,0x38,0xfe,0xd7,0xfc,' +` 0x66,0xfc,0xb8,0xfb,0x6d,0xfb,0xc6,0xfa,' +` 0x66,0xfc,0x40,0xfd,0x3e,0xfd,0xc3,0xfd,' +` 0x2b,0xfe,0xc7,0xfe,0x5d,0xff,0xcb,0x7f,' +` 0xa1,0x00,0x31,0x01,0xc2,0x01,0x1f,0x02,' +` 0x93,0x02,0x87,0x02,0x41,0x03,0xa1,0x04,' +` 0xf7,0x03,0x9f,0x03,0xf4,0x02,0x80,0x02,' +` 0x59,0x01,0xdc,0x00,0x97,0x00,0x55,0x00,' +` 0x26,0x00,0x0a,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x06,0x00,0x2d,0x00,0x30,0x00,' +` 0xb3,0x00,0x6f,0x00,0x8c,0x01,0x71,0x01,' +` 0xc0,0x03,0xe7,0x01,0x87,0x05,0x08,0x01,' +` 0xe2,0x04,0xb1,0xfe,0xe1,0x06,0x64,0xfb,' +` 0xcb,0x0a,0xa6,0xf1,0x04,0x25,0xac,0x73,' +` 0x9a,0xe8,0x2e,0x0b,0xd4,0xf5,0xfe,0x03,' +` 0xc5,0xf8,0x36,0x01,0x39,0xfa,0xc4,0xfd,' +` 0xbb,0xf9,0x9f,0xfd,0x60,0xfb,0x9a,0xfe,' +` 0x15,0xfe,0x52,0xff,0xf3,0xfe,0xa8,0xff,' +` 0x9f,0xff,0xe9,0xff,0xf6,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf8,0xff,0xdf,0xff,0xb6,0xff,0x7c,0xff,' +` 0x3b,0xff,0xe9,0xfe,0xab,0xfe,0x87,0xfd,' +` 0x80,0xfc,0x3f,0xfc,0x86,0xfb,0xdf,0xfb,' +` 0x82,0xfd,0x75,0xfd,0xa5,0xfd,0xe6,0xfd,' +` 0x60,0xfe,0xde,0xfe,0x6f,0xff,0xcb,0x7f,' +` 0x90,0x00,0x1a,0x01,0x90,0x01,0xfe,0x01,' +` 0x33,0x02,0x56,0x02,0x40,0x02,0xa8,0x03,' +` 0xe2,0x03,0x2c,0x03,0xdf,0x02,0xf5,0x01,' +` 0x02,0x01,0xc6,0x00,0x81,0x00,0x4b,0x00,' +` 0x21,0x00,0x08,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0a,0x00,0x0b,0x00,0x5a,0x00,' +` 0x23,0x00,0xfa,0x00,0x33,0x00,0xd6,0x01,' +` 0xc3,0x00,0x90,0x04,0x2a,0x01,0xa4,0x05,' +` 0xf6,0xfd,0x97,0x06,0xae,0xfb,0x8b,0x09,' +` 0xb3,0xf6,0xd7,0x10,0x2b,0xe5,0x02,0x5f,' +` 0x80,0x42,0xfd,0xe6,0x47,0x0d,0x88,0xf4,' +` 0xaf,0x05,0x9d,0xf8,0x75,0x02,0xe0,0xfa,' +` 0x8e,0xff,0x8f,0xfa,0xb0,0xfe,0xf8,0xfc,' +` 0xf5,0xff,0x8a,0xfe,0xda,0xff,0x5b,0xff,' +` 0xeb,0xff,0xd8,0xff,0xfd,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfa,0xff,0xe7,0xff,0xc7,0xff,0x9d,0xff,' +` 0x6b,0xff,0x31,0xff,0xfa,0xfe,0xa0,0xfe,' +` 0x24,0xfd,0xb0,0xfc,0x43,0xfc,0xc8,0xfd,' +` 0x27,0xfe,0x12,0xfe,0x41,0xfe,0x5f,0xfe,' +` 0xa9,0xfe,0x10,0xff,0x88,0xff,0xcb,0x7f,' +` 0x77,0x00,0xea,0x00,0x49,0x01,0x8b,0x01,' +` 0xa2,0x01,0xc6,0x01,0xab,0x01,0xf7,0x01,' +` 0x3e,0x03,0xcd,0x02,0x58,0x02,0x16,0x01,' +` 0xc6,0x00,0x93,0x00,0x61,0x00,0x38,0x00,' +` 0x19,0x00,0x06,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x05,0x00,0x32,0x00,' +` 0x10,0x00,0x8d,0x00,0x12,0x00,0x0f,0x01,' +` 0x14,0x00,0x3d,0x03,0x83,0x00,0x5f,0x02,' +` 0x01,0xff,0x86,0x03,0x8d,0xfd,0x58,0x05,' +` 0x7a,0xfa,0x26,0x0a,0x44,0xee,0x2f,0x79,' +` 0x2f,0x1a,0xa5,0xf3,0xb6,0x06,0xe3,0xf9,' +` 0x08,0x03,0xf0,0xfb,0x5e,0x01,0x20,0xfd,' +` 0x3a,0x00,0x16,0xfc,0x76,0xff,0xba,0xfe,' +` 0xe5,0xff,0x3d,0xff,0xe8,0xff,0xa8,0xff,' +` 0xf4,0xff,0xea,0xff,0xfe,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf2,0xff,0xe1,0xff,0xcb,0xff,0xaf,0xff,' +` 0x92,0xff,0x6c,0xff,0x5a,0xff,0xd7,0xfe,' +` 0x31,0xfd,0x66,0xfe,0x14,0xff,0xe6,0xfe,' +` 0x03,0xff,0x05,0xff,0x26,0xff,0x40,0xff,' +` 0x68,0xff,0xa9,0xff,0xcb,0x7f,0x55,0x00,' +` 0x94,0x00,0xb9,0x00,0xcf,0x00,0xea,0x00,' +` 0xe8,0x00,0xfe,0x00,0xd1,0x00,0x64,0x01,' +` 0x60,0x02,0xf3,0x00,0x83,0x00,0x70,0x00,' +` 0x4e,0x00,0x35,0x00,0x1e,0x00,0x0e,0x00,' +` 0x03,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xcb,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xcb,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf2,0xff,0xe1,0xff,' +` 0xcb,0xff,0xaf,0xff,0x92,0xff,0x6c,0xff,' +` 0x5a,0xff,0xd7,0xfe,0x31,0xfd,0x66,0xfe,' +` 0x14,0xff,0xe6,0xfe,0x03,0xff,0x05,0xff,' +` 0x26,0xff,0x40,0xff,0x68,0xff,0xa9,0xff,' +` 0xcb,0x7f,0x55,0x00,0x94,0x00,0xb9,0x00,' +` 0xcf,0x00,0xea,0x00,0xe8,0x00,0xfe,0x00,' +` 0xd1,0x00,0x64,0x01,0x60,0x02,0xf3,0x00,' +` 0x83,0x00,0x70,0x00,0x4e,0x00,0x35,0x00,' +` 0x1e,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x05,0x00,0x32,0x00,0x10,0x00,0x8d,0x00,' +` 0x12,0x00,0x0f,0x01,0x14,0x00,0x3d,0x03,' +` 0x83,0x00,0x5f,0x02,0x01,0xff,0x86,0x03,' +` 0x8d,0xfd,0x58,0x05,0x7a,0xfa,0x26,0x0a,' +` 0x44,0xee,0x2f,0x79,0x2f,0x1a,0xa5,0xf3,' +` 0xb6,0x06,0xe3,0xf9,0x08,0x03,0xf0,0xfb,' +` 0x5e,0x01,0x20,0xfd,0x3a,0x00,0x16,0xfc,' +` 0x76,0xff,0xba,0xfe,0xe5,0xff,0x3d,0xff,' +` 0xe8,0xff,0xa8,0xff,0xf4,0xff,0xea,0xff,' +` 0xfe,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfa,0xff,0xe7,0xff,' +` 0xc7,0xff,0x9d,0xff,0x6b,0xff,0x31,0xff,' +` 0xfa,0xfe,0xa0,0xfe,0x24,0xfd,0xb0,0xfc,' +` 0x43,0xfc,0xc8,0xfd,0x27,0xfe,0x12,0xfe,' +` 0x41,0xfe,0x5f,0xfe,0xa9,0xfe,0x10,0xff,' +` 0x88,0xff,0xcb,0x7f,0x77,0x00,0xea,0x00,' +` 0x49,0x01,0x8b,0x01,0xa2,0x01,0xc6,0x01,' +` 0xab,0x01,0xf7,0x01,0x3e,0x03,0xcd,0x02,' +` 0x58,0x02,0x16,0x01,0xc6,0x00,0x93,0x00,' +` 0x61,0x00,0x38,0x00,0x19,0x00,0x06,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,' +` 0x0b,0x00,0x5a,0x00,0x23,0x00,0xfa,0x00,' +` 0x33,0x00,0xd6,0x01,0xc3,0x00,0x90,0x04,' +` 0x2a,0x01,0xa4,0x05,0xf6,0xfd,0x97,0x06,' +` 0xae,0xfb,0x8b,0x09,0xb3,0xf6,0xd7,0x10,' +` 0x2b,0xe5,0x02,0x5f,0x80,0x42,0xfd,0xe6,' +` 0x47,0x0d,0x88,0xf4,0xaf,0x05,0x9d,0xf8,' +` 0x75,0x02,0xe0,0xfa,0x8e,0xff,0x8f,0xfa,' +` 0xb0,0xfe,0xf8,0xfc,0xf5,0xff,0x8a,0xfe,' +` 0xda,0xff,0x5b,0xff,0xeb,0xff,0xd8,0xff,' +` 0xfd,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf8,0xff,0xdf,0xff,' +` 0xb6,0xff,0x7c,0xff,0x3b,0xff,0xe9,0xfe,' +` 0xab,0xfe,0x87,0xfd,0x80,0xfc,0x3f,0xfc,' +` 0x86,0xfb,0xdf,0xfb,0x82,0xfd,0x75,0xfd,' +` 0xa5,0xfd,0xe6,0xfd,0x60,0xfe,0xde,0xfe,' +` 0x6f,0xff,0xcb,0x7f,0x90,0x00,0x1a,0x01,' +` 0x90,0x01,0xfe,0x01,0x33,0x02,0x56,0x02,' +` 0x40,0x02,0xa8,0x03,0xe2,0x03,0x2c,0x03,' +` 0xdf,0x02,0xf5,0x01,0x02,0x01,0xc6,0x00,' +` 0x81,0x00,0x4b,0x00,0x21,0x00,0x08,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,' +` 0x2d,0x00,0x30,0x00,0xb3,0x00,0x6f,0x00,' +` 0x8c,0x01,0x71,0x01,0xc0,0x03,0xe7,0x01,' +` 0x87,0x05,0x08,0x01,0xe2,0x04,0xb1,0xfe,' +` 0xe1,0x06,0x64,0xfb,0xcb,0x0a,0xa6,0xf1,' +` 0x04,0x25,0xac,0x73,0x9a,0xe8,0x2e,0x0b,' +` 0xd4,0xf5,0xfe,0x03,0xc5,0xf8,0x36,0x01,' +` 0x39,0xfa,0xc4,0xfd,0xbb,0xf9,0x9f,0xfd,' +` 0x60,0xfb,0x9a,0xfe,0x15,0xfe,0x52,0xff,' +` 0xf3,0xfe,0xa8,0xff,0x9f,0xff,0xe9,0xff,' +` 0xf6,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf7,0xff,0xda,0xff,' +` 0xab,0xff,0x6c,0xff,0x19,0xff,0xcb,0xfe,' +` 0x38,0xfe,0xd7,0xfc,0x66,0xfc,0xb8,0xfb,' +` 0x6d,0xfb,0xc6,0xfa,0x66,0xfc,0x40,0xfd,' +` 0x3e,0xfd,0xc3,0xfd,0x2b,0xfe,0xc7,0xfe,' +` 0x5d,0xff,0xcb,0x7f,0xa1,0x00,0x31,0x01,' +` 0xc2,0x01,0x1f,0x02,0x93,0x02,0x87,0x02,' +` 0x41,0x03,0xa1,0x04,0xf7,0x03,0x9f,0x03,' +` 0xf4,0x02,0x80,0x02,0x59,0x01,0xdc,0x00,' +` 0x97,0x00,0x55,0x00,0x26,0x00,0x0a,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x0c,0x00,0x1b,0x00,' +` 0x70,0x00,0x64,0x00,0x34,0x01,0xc1,0x00,' +` 0x12,0x03,0x19,0x02,0xdc,0x04,0x65,0x02,' +` 0xcd,0x06,0x2d,0x01,0xff,0x05,0x3e,0xfe,' +` 0x2a,0x08,0xb8,0xf9,0xab,0x0d,0xfc,0xe9,' +` 0xda,0x72,0x74,0x26,0x75,0xee,0x90,0x08,' +` 0xa6,0xf6,0xd6,0x02,0x0c,0xf9,0x38,0x00,' +` 0x7f,0xf8,0x6a,0xfd,0x37,0xfa,0xa0,0xfd,' +` 0xed,0xfb,0xa8,0xfe,0x5f,0xfe,0x64,0xff,' +` 0x3e,0xff,0xc3,0xff,0xcf,0xff,0xf9,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf6,0xff,0xd8,0xff,' +` 0xa4,0xff,0x63,0xff,0x09,0xff,0xbb,0xfe,' +` 0xd5,0xfd,0xa6,0xfc,0x47,0xfc,0x83,0xfb,' +` 0x46,0xfb,0x84,0xfa,0x76,0xfb,0x19,0xfd,' +` 0x20,0xfd,0xab,0xfd,0x17,0xfe,0xb9,0xfe,' +` 0x55,0xff,0xcb,0x7f,0xa9,0x00,0x3e,0x01,' +` 0xd6,0x01,0x35,0x02,0xaf,0x02,0xab,0x02,' +` 0x19,0x04,0xdc,0x04,0x19,0x04,0xcb,0x03,' +` 0x0e,0x03,0xa7,0x02,0xa4,0x01,0xe7,0x00,' +` 0xa1,0x00,0x5a,0x00,0x29,0x00,0x0a,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x2c,0x00,' +` 0x52,0x00,0xaf,0x00,0xd0,0x00,0xd1,0x01,' +` 0x73,0x02,0x51,0x03,0x6d,0x03,0x8f,0x04,' +` 0x3d,0x04,0xbe,0x04,0x9a,0x01,0x01,0x04,' +` 0x5d,0x00,0x5b,0x04,0x2b,0xfd,0x2e,0x09,' +` 0xe3,0x7e,0xab,0xf7,0x8e,0x02,0x84,0xfb,' +` 0x78,0xff,0xb3,0xfb,0x24,0xfe,0x6f,0xfa,' +` 0x32,0xfb,0xb7,0xfa,0xed,0xfb,0xf2,0xfb,' +` 0xe4,0xfc,0xb5,0xfd,0xdb,0xfe,0xf3,0xfe,' +` 0x70,0xff,0x9d,0xff,0xdb,0xff,0xf5,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf6,0xff,0xd7,0xff,' +` 0xa3,0xff,0x60,0xff,0x05,0xff,0xb4,0xfe,' +` 0xb3,0xfd,0x9f,0xfc,0x38,0xfc,0x79,0xfb,' +` 0x32,0xfb,0x7d,0xfa,0x25,0xfb,0x03,0xfd,' +` 0x1d,0xfd,0xa1,0xfd,0x14,0xfe,0xb4,0xfe,' +` 0x53,0xff,0xcb,0x7f,0xaa,0x00,0x43,0x01,' +` 0xd9,0x01,0x3f,0x02,0xb2,0x02,0xbf,0x02,' +` 0x63,0x04,0xe2,0x04,0x2a,0x04,0xd4,0x03,' +` 0x1b,0x03,0xac,0x02,0xbe,0x01,0xec,0x00,' +` 0xa4,0x00,0x5c,0x00,0x2a,0x00,0x0a,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x08,0x00,0x32,0x00,' +` 0x49,0x00,0xc6,0x00,0xb6,0x00,0x32,0x02,' +` 0x22,0x02,0xcd,0x03,0xdb,0x02,0x60,0x05,' +` 0x41,0x03,0x14,0x06,0xe6,0xff,0x34,0x06,' +` 0x52,0xfd,0xa0,0x08,0x1b,0xf6,0x8a,0x19,' +` 0x82,0x79,0x66,0xed,0x0f,0x08,0xae,0xf7,' +` 0x1b,0x02,0x90,0xf9,0x89,0xff,0x8f,0xf8,' +` 0x3e,0xfc,0xc4,0xf9,0x88,0xfc,0x5f,0xfb,' +` 0x3a,0xfd,0x63,0xfd,0x07,0xff,0xcd,0xfe,' +` 0x81,0xff,0x91,0xff,0xde,0xff,0xf4,0xff,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x06,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x12,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x16,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_68mm_azm90_90_13el0_0_13deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_azm90_90_13el0_0_13deg_48khz.m4 new file mode 100644 index 000000000000..570249cbf3fa --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_azm90_90_13el0_0_13deg_48khz.m4 @@ -0,0 +1,516 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xe4,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xe4,0x0f,0x00,0x00,0x02,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0d,0x00,0x42,0x00,0x18,0x00,0x80,0x00,' +` 0x22,0x00,0xd0,0x00,0x29,0x00,0x19,0x01,' +` 0xbd,0xff,0x4c,0x01,0x89,0xff,0xb3,0x01,' +` 0x35,0xff,0x2d,0x02,0xbd,0xfe,0xc2,0x02,' +` 0x13,0xfe,0x7f,0x03,0x23,0xfd,0x84,0x04,' +` 0xc0,0xfb,0x15,0x06,0x7c,0xf9,0xf5,0x08,' +` 0xe9,0xf4,0x53,0x10,0xd4,0xe4,0x14,0x54,' +` 0xc1,0x4e,0x36,0xe5,0xb9,0x0f,0x8a,0xf4,' +` 0x3b,0x08,0xcd,0xf8,0x2a,0x05,0xd8,0xfa,' +` 0x70,0x03,0x14,0xfc,0x50,0x02,0xee,0xfc,' +` 0x88,0x01,0x94,0xfd,0xfa,0x00,0x1a,0xfe,' +` 0x94,0x00,0x8c,0xfe,0x4e,0x00,0xf0,0xfe,' +` 0xf8,0xff,0xfa,0xfe,0xde,0xff,0x58,0xff,' +` 0xe3,0xff,0xa1,0xff,0xee,0xff,0xd5,0xff,' +` 0xf8,0xff,0xf5,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xf0,0xff,0xe4,0xff,' +` 0xd5,0xff,0xc4,0xff,0xb0,0xff,0x9b,0xff,' +` 0x83,0xff,0x6c,0xff,0x53,0xff,0x83,0xff,' +` 0x87,0xff,0x77,0xff,0x73,0xff,0x69,0xff,' +` 0x66,0xff,0x61,0xff,0x62,0xff,0x62,0xff,' +` 0x67,0xff,0x6b,0xff,0x74,0xff,0x7d,0xff,' +` 0x8a,0xff,0x97,0xff,0xa6,0xff,0xb6,0xff,' +` 0xc8,0xff,0xda,0xff,0xed,0xff,0xec,0x7f,' +` 0x13,0x00,0x26,0x00,0x37,0x00,0x48,0x00,' +` 0x57,0x00,0x66,0x00,0x72,0x00,0x7d,0x00,' +` 0x85,0x00,0x8d,0x00,0x90,0x00,0x94,0x00,' +` 0x92,0x00,0x92,0x00,0x8c,0x00,0x88,0x00,' +` 0x7e,0x00,0x79,0x00,0x69,0x00,0x6b,0x00,' +` 0x92,0x00,0x79,0x00,0x64,0x00,0x4e,0x00,' +` 0x3b,0x00,0x2a,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x24,0x00,0x1c,0x00,0x4e,0x00,0x31,0x00,' +` 0x87,0x00,0x4a,0x00,0xb8,0x00,0x07,0x00,' +` 0xd1,0x00,0xf9,0xff,0x11,0x01,0xd5,0xff,' +` 0x58,0x01,0x9b,0xff,0xab,0x01,0x43,0xff,' +` 0x10,0x02,0xc2,0xfe,0x96,0x02,0x02,0xfe,' +` 0x60,0x03,0xce,0xfc,0xc8,0x04,0x7f,0xfa,' +` 0x2e,0x08,0x8e,0xf3,0x79,0x1c,0x4d,0x78,' +` 0x8f,0xec,0x4f,0x0a,0xa7,0xf8,0x0a,0x05,' +` 0x6b,0xfb,0x08,0x03,0xa6,0xfc,0xec,0x01,' +` 0x5e,0xfd,0x35,0x01,0xdb,0xfd,0xb7,0x00,' +` 0x3b,0xfe,0x60,0x00,0x8c,0xfe,0x24,0x00,' +` 0xd3,0xfe,0xff,0xff,0x16,0xff,0xe8,0xff,' +` 0x0e,0xff,0xa8,0xff,0x56,0xff,0xc0,0xff,' +` 0x96,0xff,0xd8,0xff,0xc9,0xff,0xed,0xff,' +` 0xec,0xff,0xfb,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf9,0xff,0xf0,0xff,0xe4,0xff,0xd6,0xff,' +` 0xc4,0xff,0xb2,0xff,0x9b,0xff,0x87,0xff,' +` 0x6a,0xff,0x65,0xff,0x95,0xff,0x83,0xff,' +` 0x7c,0xff,0x71,0xff,0x6d,0xff,0x66,0xff,' +` 0x65,0xff,0x63,0xff,0x65,0xff,0x68,0xff,' +` 0x6e,0xff,0x75,0xff,0x7f,0xff,0x8a,0xff,' +` 0x98,0xff,0xa7,0xff,0xb7,0xff,0xc8,0xff,' +` 0xdb,0xff,0xed,0xff,0xec,0x7f,0x13,0x00,' +` 0x25,0x00,0x37,0x00,0x47,0x00,0x57,0x00,' +` 0x64,0x00,0x71,0x00,0x7b,0x00,0x84,0x00,' +` 0x8a,0x00,0x8f,0x00,0x91,0x00,0x92,0x00,' +` 0x8f,0x00,0x8c,0x00,0x85,0x00,0x7f,0x00,' +` 0x74,0x00,0x6c,0x00,0x5c,0x00,0x82,0x00,' +` 0x7c,0x00,0x61,0x00,0x4e,0x00,0x3a,0x00,' +` 0x2a,0x00,0x1b,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x09,0x00,0x25,0x00,0x16,0x00,0x52,0x00,' +` 0x26,0x00,0x91,0x00,0x22,0x00,0x96,0x00,' +` 0xf8,0xff,0xd9,0x00,0xdd,0xff,0x26,0x01,' +` 0xaf,0xff,0x7a,0x01,0x65,0xff,0xde,0x01,' +` 0xf9,0xfe,0x5a,0x02,0x5d,0xfe,0x01,0x03,' +` 0x76,0xfd,0xfd,0x03,0x01,0xfc,0xc0,0x05,' +` 0x2e,0xf9,0x05,0x0a,0x76,0xf0,0xb9,0x24,' +` 0x07,0x74,0x5e,0xe9,0x46,0x0c,0x44,0xf7,' +` 0x1f,0x06,0x91,0xfa,0xc2,0x03,0x11,0xfc,' +` 0x74,0x02,0xf2,0xfc,0x9c,0x01,0x8b,0xfd,' +` 0x07,0x01,0x01,0xfe,0x9d,0x00,0x61,0xfe,' +` 0x53,0x00,0xb6,0xfe,0x26,0x00,0x03,0xff,' +` 0x0c,0x00,0x3f,0xff,0xbd,0xff,0x4f,0xff,' +` 0xcc,0xff,0x93,0xff,0xdf,0xff,0xc7,0xff,' +` 0xef,0xff,0xeb,0xff,0xfc,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf9,0xff,0xf1,0xff,0xe6,0xff,0xd7,0xff,' +` 0xc7,0xff,0xb4,0xff,0xa1,0xff,0x87,0xff,' +` 0x7e,0xff,0xa6,0xff,0x98,0xff,0x8e,0xff,' +` 0x82,0xff,0x7a,0xff,0x71,0xff,0x6e,0xff,' +` 0x6a,0xff,0x6a,0xff,0x6a,0xff,0x6e,0xff,' +` 0x73,0xff,0x7b,0xff,0x84,0xff,0x90,0xff,' +` 0x9c,0xff,0xab,0xff,0xba,0xff,0xcb,0xff,' +` 0xdc,0xff,0xee,0xff,0xec,0x7f,0x12,0x00,' +` 0x23,0x00,0x34,0x00,0x44,0x00,0x53,0x00,' +` 0x61,0x00,0x6c,0x00,0x77,0x00,0x7f,0x00,' +` 0x85,0x00,0x89,0x00,0x8c,0x00,0x8b,0x00,' +` 0x8a,0x00,0x85,0x00,0x81,0x00,0x78,0x00,' +` 0x6f,0x00,0x63,0x00,0x59,0x00,0x4c,0x00,' +` 0x6b,0x00,0x61,0x00,0x4a,0x00,0x39,0x00,' +` 0x28,0x00,0x1a,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x00,0x0d,0x00,0x38,0x00,0x18,0x00,' +` 0x6d,0x00,0x15,0x00,0x77,0x00,0xf2,0xff,' +` 0xb4,0x00,0xd8,0xff,0xfb,0x00,0xb0,0xff,' +` 0x4e,0x01,0x73,0xff,0xb1,0x01,0x1a,0xff,' +` 0x25,0x02,0x97,0xfe,0xb7,0x02,0xda,0xfd,' +` 0x81,0x03,0xc1,0xfc,0xbe,0x04,0xed,0xfa,' +` 0x13,0x07,0x1e,0xf7,0x6d,0x0d,0x1a,0xe8,' +` 0x01,0x71,0x03,0x2a,0x3f,0xee,0xe6,0x0a,' +` 0xca,0xf7,0xe2,0x05,0xb3,0xfa,0xb8,0x03,' +` 0x22,0xfc,0x77,0x02,0x04,0xfd,0xa4,0x01,' +` 0xa2,0xfd,0x11,0x01,0x1d,0xfe,0xac,0x00,' +` 0x85,0xfe,0x66,0x00,0xde,0xfe,0x37,0x00,' +` 0x29,0xff,0x18,0x00,0x6a,0xff,0x02,0x00,' +` 0x76,0xff,0xe0,0xff,0xb1,0xff,0xed,0xff,' +` 0xdc,0xff,0xf8,0xff,0xf7,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfa,0xff,' +` 0xf2,0xff,0xe7,0xff,0xdb,0xff,0xcb,0xff,' +` 0xbc,0xff,0xa4,0xff,0xb5,0xff,0xc0,0xff,' +` 0xae,0xff,0xa9,0xff,0x9b,0xff,0x95,0xff,' +` 0x8a,0xff,0x85,0xff,0x7d,0xff,0x7a,0xff,' +` 0x76,0xff,0x79,0xff,0x7a,0xff,0x81,0xff,' +` 0x86,0xff,0x90,0xff,0x9a,0xff,0xa6,0xff,' +` 0xb2,0xff,0xc1,0xff,0xd0,0xff,0xe0,0xff,' +` 0xf0,0xff,0xec,0x7f,0x10,0x00,0x20,0x00,' +` 0x30,0x00,0x3e,0x00,0x4c,0x00,0x57,0x00,' +` 0x63,0x00,0x6b,0x00,0x74,0x00,0x78,0x00,' +` 0x7e,0x00,0x7e,0x00,0x80,0x00,0x7b,0x00,' +` 0x78,0x00,0x6f,0x00,0x69,0x00,0x5e,0x00,' +` 0x58,0x00,0x4b,0x00,0x45,0x00,0x35,0x00,' +` 0x3c,0x00,0x47,0x00,0x33,0x00,0x25,0x00,' +` 0x18,0x00,0x0e,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x12,0x00,0x0a,0x00,0x32,0x00,' +` 0x0b,0x00,0x3c,0x00,0xf7,0xff,0x66,0x00,' +` 0xe7,0xff,0x99,0x00,0xcd,0xff,0xd6,0x00,' +` 0xa5,0xff,0x20,0x01,0x6a,0xff,0x78,0x01,' +` 0x17,0xff,0xe4,0x01,0xa3,0xfe,0x71,0x02,' +` 0xfc,0xfd,0x2f,0x03,0xfa,0xfc,0x54,0x04,' +` 0x4c,0xfb,0x7f,0x06,0xc6,0xf7,0x71,0x0c,' +` 0x96,0xe9,0xf3,0x73,0xff,0x24,0x04,0xf0,' +` 0xe3,0x09,0x8e,0xf8,0x61,0x05,0x32,0xfb,' +` 0x6b,0x03,0x82,0xfc,0x49,0x02,0x51,0xfd,' +` 0x8f,0x01,0xe9,0xfd,0x0e,0x01,0x5c,0xfe,' +` 0xb2,0x00,0xba,0xfe,0x70,0x00,0x08,0xff,' +` 0x42,0x00,0x4a,0xff,0x23,0x00,0x81,0xff,' +` 0x0f,0x00,0xb0,0xff,0x01,0x00,0xba,0xff,' +` 0xf1,0xff,0xe1,0xff,0xfa,0xff,0xf8,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfb,0xff,0xf4,0xff,' +` 0xeb,0xff,0xe1,0xff,0xd0,0xff,0xd8,0xff,' +` 0xdf,0xff,0xd2,0xff,0xce,0xff,0xc3,0xff,' +` 0xbe,0xff,0xb4,0xff,0xb0,0xff,0xa7,0xff,' +` 0xa4,0xff,0x9e,0xff,0x9c,0xff,0x98,0xff,' +` 0x98,0xff,0x96,0xff,0x98,0xff,0x9b,0xff,' +` 0xa4,0xff,0xab,0xff,0xb6,0xff,0xc0,0xff,' +` 0xcc,0xff,0xd8,0xff,0xe5,0xff,0xf2,0xff,' +` 0xec,0x7f,0x0d,0x00,0x1a,0x00,0x27,0x00,' +` 0x33,0x00,0x3f,0x00,0x48,0x00,0x52,0x00,' +` 0x59,0x00,0x60,0x00,0x62,0x00,0x63,0x00,' +` 0x61,0x00,0x61,0x00,0x5c,0x00,0x5a,0x00,' +` 0x53,0x00,0x4f,0x00,0x47,0x00,0x42,0x00,' +` 0x39,0x00,0x33,0x00,0x29,0x00,0x25,0x00,' +` 0x1a,0x00,0x1e,0x00,0x21,0x00,0x14,0x00,' +` 0x0c,0x00,0x05,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x08,0x00,0xff,0xff,' +` 0x14,0x00,0xf1,0xff,0x2f,0x00,0xdd,0xff,' +` 0x57,0x00,0xbe,0xff,0x8c,0x00,0x90,0xff,' +` 0xd2,0x00,0x51,0xff,0x2a,0x01,0xfa,0xfe,' +` 0x9a,0x01,0x85,0xfe,0x29,0x02,0xe6,0xfd,' +` 0xe6,0x02,0x08,0xfd,0xf0,0x03,0xbe,0xfb,' +` 0x89,0x05,0x9f,0xf9,0x68,0x08,0x43,0xf5,' +` 0x8c,0x0f,0x26,0xe6,0xed,0x4a,0x5e,0x57,' +` 0x4a,0xe4,0x43,0x10,0x5b,0xf4,0xa6,0x08,' +` 0xc4,0xf8,0x9f,0x05,0xe9,0xfa,0xf1,0x03,' +` 0x37,0xfc,0xd9,0x02,0x1d,0xfd,0x13,0x02,' +` 0xc9,0xfd,0x81,0x01,0x4f,0xfe,0x12,0x01,' +` 0xbb,0xfe,0xbd,0x00,0x13,0xff,0x7e,0x00,' +` 0x5a,0xff,0x4f,0x00,0x93,0xff,0x2e,0x00,' +` 0xbf,0xff,0x18,0x00,0xd7,0xff,0xfd,0xff,' +` 0xef,0xff,0xff,0xff,0xfe,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfc,0xff,0xf7,0xff,0xf0,0xff,' +` 0xf5,0xff,0xf5,0xff,0xf0,0xff,0xed,0xff,' +` 0xe8,0xff,0xe4,0xff,0xdf,0xff,0xdc,0xff,' +` 0xd7,0xff,0xd4,0xff,0xd0,0xff,0xce,0xff,' +` 0xcb,0xff,0xca,0xff,0xc8,0xff,0xc8,0xff,' +` 0xc7,0xff,0xc8,0xff,0xc9,0xff,0xcb,0xff,' +` 0xcd,0xff,0xd0,0xff,0xd4,0xff,0xdb,0xff,' +` 0xe4,0xff,0xed,0xff,0xf7,0xff,0xec,0x7f,' +` 0x09,0x00,0x13,0x00,0x1c,0x00,0x24,0x00,' +` 0x2b,0x00,0x2e,0x00,0x31,0x00,0x33,0x00,' +` 0x35,0x00,0x35,0x00,0x36,0x00,0x34,0x00,' +` 0x34,0x00,0x32,0x00,0x30,0x00,0x2d,0x00,' +` 0x2b,0x00,0x26,0x00,0x24,0x00,0x1f,0x00,' +` 0x1c,0x00,0x17,0x00,0x14,0x00,0x0f,0x00,' +` 0x0c,0x00,0x08,0x00,0x07,0x00,0x09,0x00,' +` 0x04,0x00,0x01,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff,' +` 0xf7,0xff,0xf0,0xff,0xf5,0xff,0xf5,0xff,' +` 0xf0,0xff,0xed,0xff,0xe8,0xff,0xe4,0xff,' +` 0xdf,0xff,0xdc,0xff,0xd7,0xff,0xd4,0xff,' +` 0xd0,0xff,0xce,0xff,0xcb,0xff,0xca,0xff,' +` 0xc8,0xff,0xc8,0xff,0xc7,0xff,0xc8,0xff,' +` 0xc9,0xff,0xcb,0xff,0xcd,0xff,0xd0,0xff,' +` 0xd4,0xff,0xdb,0xff,0xe4,0xff,0xed,0xff,' +` 0xf7,0xff,0xec,0x7f,0x09,0x00,0x13,0x00,' +` 0x1c,0x00,0x24,0x00,0x2b,0x00,0x2e,0x00,' +` 0x31,0x00,0x33,0x00,0x35,0x00,0x35,0x00,' +` 0x36,0x00,0x34,0x00,0x34,0x00,0x32,0x00,' +` 0x30,0x00,0x2d,0x00,0x2b,0x00,0x26,0x00,' +` 0x24,0x00,0x1f,0x00,0x1c,0x00,0x17,0x00,' +` 0x14,0x00,0x0f,0x00,0x0c,0x00,0x08,0x00,' +` 0x07,0x00,0x09,0x00,0x04,0x00,0x01,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x08,0x00,0xff,0xff,0x14,0x00,0xf1,0xff,' +` 0x2f,0x00,0xdd,0xff,0x57,0x00,0xbe,0xff,' +` 0x8c,0x00,0x90,0xff,0xd2,0x00,0x51,0xff,' +` 0x2a,0x01,0xfa,0xfe,0x9a,0x01,0x85,0xfe,' +` 0x29,0x02,0xe6,0xfd,0xe6,0x02,0x08,0xfd,' +` 0xf0,0x03,0xbe,0xfb,0x89,0x05,0x9f,0xf9,' +` 0x68,0x08,0x43,0xf5,0x8c,0x0f,0x26,0xe6,' +` 0xed,0x4a,0x5e,0x57,0x4a,0xe4,0x43,0x10,' +` 0x5b,0xf4,0xa6,0x08,0xc4,0xf8,0x9f,0x05,' +` 0xe9,0xfa,0xf1,0x03,0x37,0xfc,0xd9,0x02,' +` 0x1d,0xfd,0x13,0x02,0xc9,0xfd,0x81,0x01,' +` 0x4f,0xfe,0x12,0x01,0xbb,0xfe,0xbd,0x00,' +` 0x13,0xff,0x7e,0x00,0x5a,0xff,0x4f,0x00,' +` 0x93,0xff,0x2e,0x00,0xbf,0xff,0x18,0x00,' +` 0xd7,0xff,0xfd,0xff,0xef,0xff,0xff,0xff,' +` 0xfe,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfb,0xff,0xf4,0xff,0xeb,0xff,0xe1,0xff,' +` 0xd0,0xff,0xd8,0xff,0xdf,0xff,0xd2,0xff,' +` 0xce,0xff,0xc3,0xff,0xbe,0xff,0xb4,0xff,' +` 0xb0,0xff,0xa7,0xff,0xa4,0xff,0x9e,0xff,' +` 0x9c,0xff,0x98,0xff,0x98,0xff,0x96,0xff,' +` 0x98,0xff,0x9b,0xff,0xa4,0xff,0xab,0xff,' +` 0xb6,0xff,0xc0,0xff,0xcc,0xff,0xd8,0xff,' +` 0xe5,0xff,0xf2,0xff,0xec,0x7f,0x0d,0x00,' +` 0x1a,0x00,0x27,0x00,0x33,0x00,0x3f,0x00,' +` 0x48,0x00,0x52,0x00,0x59,0x00,0x60,0x00,' +` 0x62,0x00,0x63,0x00,0x61,0x00,0x61,0x00,' +` 0x5c,0x00,0x5a,0x00,0x53,0x00,0x4f,0x00,' +` 0x47,0x00,0x42,0x00,0x39,0x00,0x33,0x00,' +` 0x29,0x00,0x25,0x00,0x1a,0x00,0x1e,0x00,' +` 0x21,0x00,0x14,0x00,0x0c,0x00,0x05,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x12,0x00,' +` 0x0a,0x00,0x32,0x00,0x0b,0x00,0x3c,0x00,' +` 0xf7,0xff,0x66,0x00,0xe7,0xff,0x99,0x00,' +` 0xcd,0xff,0xd6,0x00,0xa5,0xff,0x20,0x01,' +` 0x6a,0xff,0x78,0x01,0x17,0xff,0xe4,0x01,' +` 0xa3,0xfe,0x71,0x02,0xfc,0xfd,0x2f,0x03,' +` 0xfa,0xfc,0x54,0x04,0x4c,0xfb,0x7f,0x06,' +` 0xc6,0xf7,0x71,0x0c,0x96,0xe9,0xf3,0x73,' +` 0xff,0x24,0x04,0xf0,0xe3,0x09,0x8e,0xf8,' +` 0x61,0x05,0x32,0xfb,0x6b,0x03,0x82,0xfc,' +` 0x49,0x02,0x51,0xfd,0x8f,0x01,0xe9,0xfd,' +` 0x0e,0x01,0x5c,0xfe,0xb2,0x00,0xba,0xfe,' +` 0x70,0x00,0x08,0xff,0x42,0x00,0x4a,0xff,' +` 0x23,0x00,0x81,0xff,0x0f,0x00,0xb0,0xff,' +` 0x01,0x00,0xba,0xff,0xf1,0xff,0xe1,0xff,' +` 0xfa,0xff,0xf8,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfa,0xff,0xf2,0xff,0xe7,0xff,' +` 0xdb,0xff,0xcb,0xff,0xbc,0xff,0xa4,0xff,' +` 0xb5,0xff,0xc0,0xff,0xae,0xff,0xa9,0xff,' +` 0x9b,0xff,0x95,0xff,0x8a,0xff,0x85,0xff,' +` 0x7d,0xff,0x7a,0xff,0x76,0xff,0x79,0xff,' +` 0x7a,0xff,0x81,0xff,0x86,0xff,0x90,0xff,' +` 0x9a,0xff,0xa6,0xff,0xb2,0xff,0xc1,0xff,' +` 0xd0,0xff,0xe0,0xff,0xf0,0xff,0xec,0x7f,' +` 0x10,0x00,0x20,0x00,0x30,0x00,0x3e,0x00,' +` 0x4c,0x00,0x57,0x00,0x63,0x00,0x6b,0x00,' +` 0x74,0x00,0x78,0x00,0x7e,0x00,0x7e,0x00,' +` 0x80,0x00,0x7b,0x00,0x78,0x00,0x6f,0x00,' +` 0x69,0x00,0x5e,0x00,0x58,0x00,0x4b,0x00,' +` 0x45,0x00,0x35,0x00,0x3c,0x00,0x47,0x00,' +` 0x33,0x00,0x25,0x00,0x18,0x00,0x0e,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x14,0x00,0x0d,0x00,' +` 0x38,0x00,0x18,0x00,0x6d,0x00,0x15,0x00,' +` 0x77,0x00,0xf2,0xff,0xb4,0x00,0xd8,0xff,' +` 0xfb,0x00,0xb0,0xff,0x4e,0x01,0x73,0xff,' +` 0xb1,0x01,0x1a,0xff,0x25,0x02,0x97,0xfe,' +` 0xb7,0x02,0xda,0xfd,0x81,0x03,0xc1,0xfc,' +` 0xbe,0x04,0xed,0xfa,0x13,0x07,0x1e,0xf7,' +` 0x6d,0x0d,0x1a,0xe8,0x01,0x71,0x03,0x2a,' +` 0x3f,0xee,0xe6,0x0a,0xca,0xf7,0xe2,0x05,' +` 0xb3,0xfa,0xb8,0x03,0x22,0xfc,0x77,0x02,' +` 0x04,0xfd,0xa4,0x01,0xa2,0xfd,0x11,0x01,' +` 0x1d,0xfe,0xac,0x00,0x85,0xfe,0x66,0x00,' +` 0xde,0xfe,0x37,0x00,0x29,0xff,0x18,0x00,' +` 0x6a,0xff,0x02,0x00,0x76,0xff,0xe0,0xff,' +` 0xb1,0xff,0xed,0xff,0xdc,0xff,0xf8,0xff,' +` 0xf7,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf9,0xff,0xf1,0xff,' +` 0xe6,0xff,0xd7,0xff,0xc7,0xff,0xb4,0xff,' +` 0xa1,0xff,0x87,0xff,0x7e,0xff,0xa6,0xff,' +` 0x98,0xff,0x8e,0xff,0x82,0xff,0x7a,0xff,' +` 0x71,0xff,0x6e,0xff,0x6a,0xff,0x6a,0xff,' +` 0x6a,0xff,0x6e,0xff,0x73,0xff,0x7b,0xff,' +` 0x84,0xff,0x90,0xff,0x9c,0xff,0xab,0xff,' +` 0xba,0xff,0xcb,0xff,0xdc,0xff,0xee,0xff,' +` 0xec,0x7f,0x12,0x00,0x23,0x00,0x34,0x00,' +` 0x44,0x00,0x53,0x00,0x61,0x00,0x6c,0x00,' +` 0x77,0x00,0x7f,0x00,0x85,0x00,0x89,0x00,' +` 0x8c,0x00,0x8b,0x00,0x8a,0x00,0x85,0x00,' +` 0x81,0x00,0x78,0x00,0x6f,0x00,0x63,0x00,' +` 0x59,0x00,0x4c,0x00,0x6b,0x00,0x61,0x00,' +` 0x4a,0x00,0x39,0x00,0x28,0x00,0x1a,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x25,0x00,' +` 0x16,0x00,0x52,0x00,0x26,0x00,0x91,0x00,' +` 0x22,0x00,0x96,0x00,0xf8,0xff,0xd9,0x00,' +` 0xdd,0xff,0x26,0x01,0xaf,0xff,0x7a,0x01,' +` 0x65,0xff,0xde,0x01,0xf9,0xfe,0x5a,0x02,' +` 0x5d,0xfe,0x01,0x03,0x76,0xfd,0xfd,0x03,' +` 0x01,0xfc,0xc0,0x05,0x2e,0xf9,0x05,0x0a,' +` 0x76,0xf0,0xb9,0x24,0x07,0x74,0x5e,0xe9,' +` 0x46,0x0c,0x44,0xf7,0x1f,0x06,0x91,0xfa,' +` 0xc2,0x03,0x11,0xfc,0x74,0x02,0xf2,0xfc,' +` 0x9c,0x01,0x8b,0xfd,0x07,0x01,0x01,0xfe,' +` 0x9d,0x00,0x61,0xfe,0x53,0x00,0xb6,0xfe,' +` 0x26,0x00,0x03,0xff,0x0c,0x00,0x3f,0xff,' +` 0xbd,0xff,0x4f,0xff,0xcc,0xff,0x93,0xff,' +` 0xdf,0xff,0xc7,0xff,0xef,0xff,0xeb,0xff,' +` 0xfc,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf9,0xff,0xf0,0xff,' +` 0xe4,0xff,0xd6,0xff,0xc4,0xff,0xb2,0xff,' +` 0x9b,0xff,0x87,0xff,0x6a,0xff,0x65,0xff,' +` 0x95,0xff,0x83,0xff,0x7c,0xff,0x71,0xff,' +` 0x6d,0xff,0x66,0xff,0x65,0xff,0x63,0xff,' +` 0x65,0xff,0x68,0xff,0x6e,0xff,0x75,0xff,' +` 0x7f,0xff,0x8a,0xff,0x98,0xff,0xa7,0xff,' +` 0xb7,0xff,0xc8,0xff,0xdb,0xff,0xed,0xff,' +` 0xec,0x7f,0x13,0x00,0x25,0x00,0x37,0x00,' +` 0x47,0x00,0x57,0x00,0x64,0x00,0x71,0x00,' +` 0x7b,0x00,0x84,0x00,0x8a,0x00,0x8f,0x00,' +` 0x91,0x00,0x92,0x00,0x8f,0x00,0x8c,0x00,' +` 0x85,0x00,0x7f,0x00,0x74,0x00,0x6c,0x00,' +` 0x5c,0x00,0x82,0x00,0x7c,0x00,0x61,0x00,' +` 0x4e,0x00,0x3a,0x00,0x2a,0x00,0x1b,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x24,0x00,0x1c,0x00,' +` 0x4e,0x00,0x31,0x00,0x87,0x00,0x4a,0x00,' +` 0xb8,0x00,0x07,0x00,0xd1,0x00,0xf9,0xff,' +` 0x11,0x01,0xd5,0xff,0x58,0x01,0x9b,0xff,' +` 0xab,0x01,0x43,0xff,0x10,0x02,0xc2,0xfe,' +` 0x96,0x02,0x02,0xfe,0x60,0x03,0xce,0xfc,' +` 0xc8,0x04,0x7f,0xfa,0x2e,0x08,0x8e,0xf3,' +` 0x79,0x1c,0x4d,0x78,0x8f,0xec,0x4f,0x0a,' +` 0xa7,0xf8,0x0a,0x05,0x6b,0xfb,0x08,0x03,' +` 0xa6,0xfc,0xec,0x01,0x5e,0xfd,0x35,0x01,' +` 0xdb,0xfd,0xb7,0x00,0x3b,0xfe,0x60,0x00,' +` 0x8c,0xfe,0x24,0x00,0xd3,0xfe,0xff,0xff,' +` 0x16,0xff,0xe8,0xff,0x0e,0xff,0xa8,0xff,' +` 0x56,0xff,0xc0,0xff,0x96,0xff,0xd8,0xff,' +` 0xc9,0xff,0xed,0xff,0xec,0xff,0xfb,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xf0,0xff,0xe4,0xff,0xd5,0xff,0xc4,0xff,' +` 0xb0,0xff,0x9b,0xff,0x83,0xff,0x6c,0xff,' +` 0x53,0xff,0x83,0xff,0x87,0xff,0x77,0xff,' +` 0x73,0xff,0x69,0xff,0x66,0xff,0x61,0xff,' +` 0x62,0xff,0x62,0xff,0x67,0xff,0x6b,0xff,' +` 0x74,0xff,0x7d,0xff,0x8a,0xff,0x97,0xff,' +` 0xa6,0xff,0xb6,0xff,0xc8,0xff,0xda,0xff,' +` 0xed,0xff,0xec,0x7f,0x13,0x00,0x26,0x00,' +` 0x37,0x00,0x48,0x00,0x57,0x00,0x66,0x00,' +` 0x72,0x00,0x7d,0x00,0x85,0x00,0x8d,0x00,' +` 0x90,0x00,0x94,0x00,0x92,0x00,0x92,0x00,' +` 0x8c,0x00,0x88,0x00,0x7e,0x00,0x79,0x00,' +` 0x69,0x00,0x6b,0x00,0x92,0x00,0x79,0x00,' +` 0x64,0x00,0x4e,0x00,0x3b,0x00,0x2a,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x0d,0x00,0x42,0x00,' +` 0x18,0x00,0x80,0x00,0x22,0x00,0xd0,0x00,' +` 0x29,0x00,0x19,0x01,0xbd,0xff,0x4c,0x01,' +` 0x89,0xff,0xb3,0x01,0x35,0xff,0x2d,0x02,' +` 0xbd,0xfe,0xc2,0x02,0x13,0xfe,0x7f,0x03,' +` 0x23,0xfd,0x84,0x04,0xc0,0xfb,0x15,0x06,' +` 0x7c,0xf9,0xf5,0x08,0xe9,0xf4,0x53,0x10,' +` 0xd4,0xe4,0x14,0x54,0xc1,0x4e,0x36,0xe5,' +` 0xb9,0x0f,0x8a,0xf4,0x3b,0x08,0xcd,0xf8,' +` 0x2a,0x05,0xd8,0xfa,0x70,0x03,0x14,0xfc,' +` 0x50,0x02,0xee,0xfc,0x88,0x01,0x94,0xfd,' +` 0xfa,0x00,0x1a,0xfe,0x94,0x00,0x8c,0xfe,' +` 0x4e,0x00,0xf0,0xfe,0xf8,0xff,0xfa,0xfe,' +` 0xde,0xff,0x58,0xff,0xe3,0xff,0xa1,0xff,' +` 0xee,0xff,0xd5,0xff,0xf8,0xff,0xf5,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x06,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x12,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x16,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_68mm_pm0_30_90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_pm0_30_90deg_16khz.m4 new file mode 100644 index 000000000000..b62c79ace612 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_pm0_30_90deg_16khz.m4 @@ -0,0 +1,256 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xf0,0xff,0xe2,0xff,0xd1,0xff,0xbb,0xff,' +` 0xa1,0xff,0x84,0xff,0x62,0xff,0x39,0xff,' +` 0x0b,0xff,0xda,0xfe,0xa5,0xfe,0x70,0xfe,' +` 0x38,0xfe,0x08,0xfe,0xdf,0xfd,0xb7,0xfd,' +` 0xa2,0xfd,0x50,0xfd,0x20,0xfb,0xf5,0xfa,' +` 0xd2,0xfa,0x29,0xfd,0xca,0xfd,0xcf,0xfd,' +` 0x1a,0xfe,0x4a,0xfe,0xa1,0xfe,0x0d,0xff,' +` 0x88,0xff,0xec,0x7f,0x78,0x00,0xf0,0x00,' +` 0x5a,0x01,0xad,0x01,0xda,0x01,0x20,0x02,' +` 0x22,0x02,0xb9,0x02,0xef,0x04,0xc6,0x04,' +` 0x96,0x04,0x83,0x02,0x32,0x02,0x1a,0x02,' +` 0xf1,0x01,0xc7,0x01,0x98,0x01,0x61,0x01,' +` 0x2e,0x01,0xfc,0x00,0xce,0x00,0xa4,0x00,' +` 0x7f,0x00,0x60,0x00,0x46,0x00,0x30,0x00,' +` 0x1e,0x00,0x11,0x00,0x07,0x00,0x02,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x04,0x00,0x18,0x00,0x10,0x00,0x47,0x00,' +` 0x24,0x00,0x8f,0x00,0x3e,0x00,0xf4,0x00,' +` 0x62,0x00,0x7c,0x01,0x8a,0x00,0x20,0x02,' +` 0xae,0x00,0xdb,0x02,0xb3,0x00,0x92,0x03,' +` 0x91,0x00,0x3d,0x04,0x7d,0x01,0xc8,0x07,' +` 0xc6,0x01,0xcf,0x07,0x65,0xfd,0xe6,0x07,' +` 0x18,0xfb,0x60,0x0a,0x39,0xf6,0x45,0x11,' +` 0xed,0xe4,0x1a,0x5f,0x91,0x42,0xc2,0xe6,' +` 0x9e,0x0d,0xf1,0xf3,0x2e,0x06,0x9d,0xf7,' +` 0xf2,0x02,0x71,0xf9,0x62,0xff,0xb7,0xf7,' +` 0xc3,0xfd,0x14,0xfa,0xe6,0xff,0xde,0xfb,' +` 0x77,0xff,0xb4,0xfc,0x58,0xff,0x7a,0xfd,' +` 0x6c,0xff,0x31,0xfe,0x8f,0xff,0xca,0xfe,' +` 0xb5,0xff,0x42,0xff,0xd1,0xff,0x98,0xff,' +` 0xe8,0xff,0xd4,0xff,0xf7,0xff,0xf5,0xff,' +` 0xff,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x04,0x00,0x18,0x00,' +` 0x10,0x00,0x47,0x00,0x24,0x00,0x8f,0x00,' +` 0x3e,0x00,0xf4,0x00,0x62,0x00,0x7c,0x01,' +` 0x8a,0x00,0x20,0x02,0xae,0x00,0xdb,0x02,' +` 0xb3,0x00,0x92,0x03,0x91,0x00,0x3d,0x04,' +` 0x7d,0x01,0xc8,0x07,0xc6,0x01,0xcf,0x07,' +` 0x65,0xfd,0xe6,0x07,0x18,0xfb,0x60,0x0a,' +` 0x39,0xf6,0x45,0x11,0xed,0xe4,0x1a,0x5f,' +` 0x91,0x42,0xc2,0xe6,0x9e,0x0d,0xf1,0xf3,' +` 0x2e,0x06,0x9d,0xf7,0xf2,0x02,0x71,0xf9,' +` 0x62,0xff,0xb7,0xf7,0xc3,0xfd,0x14,0xfa,' +` 0xe6,0xff,0xde,0xfb,0x77,0xff,0xb4,0xfc,' +` 0x58,0xff,0x7a,0xfd,0x6c,0xff,0x31,0xfe,' +` 0x8f,0xff,0xca,0xfe,0xb5,0xff,0x42,0xff,' +` 0xd1,0xff,0x98,0xff,0xe8,0xff,0xd4,0xff,' +` 0xf7,0xff,0xf5,0xff,0xff,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xf0,0xff,0xe2,0xff,' +` 0xd1,0xff,0xbb,0xff,0xa1,0xff,0x84,0xff,' +` 0x62,0xff,0x39,0xff,0x0b,0xff,0xda,0xfe,' +` 0xa5,0xfe,0x70,0xfe,0x38,0xfe,0x08,0xfe,' +` 0xdf,0xfd,0xb7,0xfd,0xa2,0xfd,0x50,0xfd,' +` 0x20,0xfb,0xf5,0xfa,0xd2,0xfa,0x29,0xfd,' +` 0xca,0xfd,0xcf,0xfd,0x1a,0xfe,0x4a,0xfe,' +` 0xa1,0xfe,0x0d,0xff,0x88,0xff,0xec,0x7f,' +` 0x78,0x00,0xf0,0x00,0x5a,0x01,0xad,0x01,' +` 0xda,0x01,0x20,0x02,0x22,0x02,0xb9,0x02,' +` 0xef,0x04,0xc6,0x04,0x96,0x04,0x83,0x02,' +` 0x32,0x02,0x1a,0x02,0xf1,0x01,0xc7,0x01,' +` 0x98,0x01,0x61,0x01,0x2e,0x01,0xfc,0x00,' +` 0xce,0x00,0xa4,0x00,0x7f,0x00,0x60,0x00,' +` 0x46,0x00,0x30,0x00,0x1e,0x00,0x11,0x00,' +` 0x07,0x00,0x02,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xf3,0xff,' +` 0xe3,0xff,0xcc,0xff,0xae,0xff,0x89,0xff,' +` 0x5a,0xff,0x25,0xff,0xe7,0xfe,0xa5,0xfe,' +` 0x59,0xfe,0x0d,0xfe,0xb7,0xfd,0x6a,0xfd,' +` 0x0e,0xfd,0xcc,0xfc,0x69,0xfc,0x54,0xfc,' +` 0xb0,0xfa,0x66,0xf9,0x8d,0xf9,0x1c,0xf9,' +` 0x59,0xf9,0xf3,0xf8,0x2e,0xfa,0x9c,0xfc,' +` 0xdc,0xfc,0x82,0xfd,0x07,0xfe,0xb1,0xfe,' +` 0x53,0xff,0xec,0x7f,0xac,0x00,0x4b,0x01,' +` 0xf1,0x01,0x71,0x02,0x0f,0x03,0x4a,0x03,' +` 0x9c,0x05,0xc3,0x06,0x57,0x06,0x87,0x06,' +` 0x12,0x06,0x2b,0x06,0xed,0x04,0x61,0x03,' +` 0x46,0x03,0xe4,0x02,0xa1,0x02,0x48,0x02,' +` 0xfd,0x01,0xab,0x01,0x64,0x01,0x1e,0x01,' +` 0xe1,0x00,0xa9,0x00,0x7b,0x00,0x53,0x00,' +` 0x35,0x00,0x1d,0x00,0x0d,0x00,0x03,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x0f,0x00,' +` 0x19,0x00,0x3d,0x00,0x47,0x00,0x8e,0x00,' +` 0x90,0x00,0x05,0x01,0xf1,0x00,0x9f,0x01,' +` 0x64,0x01,0x57,0x02,0xdd,0x01,0x22,0x03,' +` 0x4c,0x02,0xf6,0x03,0x99,0x02,0x36,0x06,' +` 0xeb,0x04,0x6f,0x07,0xdf,0x04,0x2e,0x08,' +` 0x81,0x04,0xc6,0x07,0xe1,0xff,0x0b,0x07,' +` 0x17,0xfd,0x11,0x09,0xdb,0xf5,0xc6,0x19,' +` 0xa1,0x79,0x61,0xed,0x22,0x08,0x77,0xf7,' +` 0x37,0x02,0x00,0xf9,0x79,0xff,0x16,0xf7,' +` 0x32,0xfb,0x5d,0xf7,0xb8,0xfa,0x1a,0xf8,' +` 0x94,0xfa,0xf7,0xf9,0x40,0xfd,0x9d,0xfb,' +` 0x78,0xfd,0x7c,0xfc,0xe6,0xfd,0x52,0xfd,' +` 0x64,0xfe,0x15,0xfe,0xde,0xfe,0xbd,0xfe,' +` 0x48,0xff,0x42,0xff,0x9c,0xff,0xa2,0xff,' +` 0xd4,0xff,0xdf,0xff,0xf5,0xff,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x0f,0x00,0x19,0x00,0x3d,0x00,' +` 0x47,0x00,0x8e,0x00,0x90,0x00,0x05,0x01,' +` 0xf1,0x00,0x9f,0x01,0x64,0x01,0x57,0x02,' +` 0xdd,0x01,0x22,0x03,0x4c,0x02,0xf6,0x03,' +` 0x99,0x02,0x36,0x06,0xeb,0x04,0x6f,0x07,' +` 0xdf,0x04,0x2e,0x08,0x81,0x04,0xc6,0x07,' +` 0xe1,0xff,0x0b,0x07,0x17,0xfd,0x11,0x09,' +` 0xdb,0xf5,0xc6,0x19,0xa1,0x79,0x61,0xed,' +` 0x22,0x08,0x77,0xf7,0x37,0x02,0x00,0xf9,' +` 0x79,0xff,0x16,0xf7,0x32,0xfb,0x5d,0xf7,' +` 0xb8,0xfa,0x1a,0xf8,0x94,0xfa,0xf7,0xf9,' +` 0x40,0xfd,0x9d,0xfb,0x78,0xfd,0x7c,0xfc,' +` 0xe6,0xfd,0x52,0xfd,0x64,0xfe,0x15,0xfe,' +` 0xde,0xfe,0xbd,0xfe,0x48,0xff,0x42,0xff,' +` 0x9c,0xff,0xa2,0xff,0xd4,0xff,0xdf,0xff,' +` 0xf5,0xff,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xf3,0xff,0xe3,0xff,0xcc,0xff,' +` 0xae,0xff,0x89,0xff,0x5a,0xff,0x25,0xff,' +` 0xe7,0xfe,0xa5,0xfe,0x59,0xfe,0x0d,0xfe,' +` 0xb7,0xfd,0x6a,0xfd,0x0e,0xfd,0xcc,0xfc,' +` 0x69,0xfc,0x54,0xfc,0xb0,0xfa,0x66,0xf9,' +` 0x8d,0xf9,0x1c,0xf9,0x59,0xf9,0xf3,0xf8,' +` 0x2e,0xfa,0x9c,0xfc,0xdc,0xfc,0x82,0xfd,' +` 0x07,0xfe,0xb1,0xfe,0x53,0xff,0xec,0x7f,' +` 0xac,0x00,0x4b,0x01,0xf1,0x01,0x71,0x02,' +` 0x0f,0x03,0x4a,0x03,0x9c,0x05,0xc3,0x06,' +` 0x57,0x06,0x87,0x06,0x12,0x06,0x2b,0x06,' +` 0xed,0x04,0x61,0x03,0x46,0x03,0xe4,0x02,' +` 0xa1,0x02,0x48,0x02,0xfd,0x01,0xab,0x01,' +` 0x64,0x01,0x1e,0x01,0xe1,0x00,0xa9,0x00,' +` 0x7b,0x00,0x53,0x00,0x35,0x00,0x1d,0x00,' +` 0x0d,0x00,0x03,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_68mm_pm0_30_90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_pm0_30_90deg_48khz.m4 new file mode 100644 index 000000000000..d5efb804082d --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_68mm_pm0_30_90deg_48khz.m4 @@ -0,0 +1,256 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x07,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x02,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfb,0xff,0xf4,0xff,0xeb,0xff,0xe1,0xff,' +` 0xd0,0xff,0xd8,0xff,0xdf,0xff,0xd2,0xff,' +` 0xce,0xff,0xc3,0xff,0xbe,0xff,0xb4,0xff,' +` 0xb0,0xff,0xa7,0xff,0xa4,0xff,0x9e,0xff,' +` 0x9c,0xff,0x98,0xff,0x98,0xff,0x96,0xff,' +` 0x98,0xff,0x9b,0xff,0xa4,0xff,0xab,0xff,' +` 0xb6,0xff,0xc0,0xff,0xcc,0xff,0xd8,0xff,' +` 0xe5,0xff,0xf2,0xff,0xec,0x7f,0x0d,0x00,' +` 0x1a,0x00,0x27,0x00,0x33,0x00,0x3f,0x00,' +` 0x48,0x00,0x52,0x00,0x59,0x00,0x60,0x00,' +` 0x62,0x00,0x63,0x00,0x61,0x00,0x61,0x00,' +` 0x5c,0x00,0x5a,0x00,0x53,0x00,0x4f,0x00,' +` 0x47,0x00,0x42,0x00,0x39,0x00,0x33,0x00,' +` 0x29,0x00,0x25,0x00,0x1a,0x00,0x1e,0x00,' +` 0x21,0x00,0x14,0x00,0x0c,0x00,0x05,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x12,0x00,' +` 0x0a,0x00,0x32,0x00,0x0b,0x00,0x3c,0x00,' +` 0xf7,0xff,0x66,0x00,0xe7,0xff,0x99,0x00,' +` 0xcd,0xff,0xd6,0x00,0xa5,0xff,0x20,0x01,' +` 0x6a,0xff,0x78,0x01,0x17,0xff,0xe4,0x01,' +` 0xa3,0xfe,0x71,0x02,0xfc,0xfd,0x2f,0x03,' +` 0xfa,0xfc,0x54,0x04,0x4c,0xfb,0x7f,0x06,' +` 0xc6,0xf7,0x71,0x0c,0x96,0xe9,0xf3,0x73,' +` 0xff,0x24,0x04,0xf0,0xe3,0x09,0x8e,0xf8,' +` 0x61,0x05,0x32,0xfb,0x6b,0x03,0x82,0xfc,' +` 0x49,0x02,0x51,0xfd,0x8f,0x01,0xe9,0xfd,' +` 0x0e,0x01,0x5c,0xfe,0xb2,0x00,0xba,0xfe,' +` 0x70,0x00,0x08,0xff,0x42,0x00,0x4a,0xff,' +` 0x23,0x00,0x81,0xff,0x0f,0x00,0xb0,0xff,' +` 0x01,0x00,0xba,0xff,0xf1,0xff,0xe1,0xff,' +` 0xfa,0xff,0xf8,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x12,0x00,0x0a,0x00,0x32,0x00,' +` 0x0b,0x00,0x3c,0x00,0xf7,0xff,0x66,0x00,' +` 0xe7,0xff,0x99,0x00,0xcd,0xff,0xd6,0x00,' +` 0xa5,0xff,0x20,0x01,0x6a,0xff,0x78,0x01,' +` 0x17,0xff,0xe4,0x01,0xa3,0xfe,0x71,0x02,' +` 0xfc,0xfd,0x2f,0x03,0xfa,0xfc,0x54,0x04,' +` 0x4c,0xfb,0x7f,0x06,0xc6,0xf7,0x71,0x0c,' +` 0x96,0xe9,0xf3,0x73,0xff,0x24,0x04,0xf0,' +` 0xe3,0x09,0x8e,0xf8,0x61,0x05,0x32,0xfb,' +` 0x6b,0x03,0x82,0xfc,0x49,0x02,0x51,0xfd,' +` 0x8f,0x01,0xe9,0xfd,0x0e,0x01,0x5c,0xfe,' +` 0xb2,0x00,0xba,0xfe,0x70,0x00,0x08,0xff,' +` 0x42,0x00,0x4a,0xff,0x23,0x00,0x81,0xff,' +` 0x0f,0x00,0xb0,0xff,0x01,0x00,0xba,0xff,' +` 0xf1,0xff,0xe1,0xff,0xfa,0xff,0xf8,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfb,0xff,0xf4,0xff,' +` 0xeb,0xff,0xe1,0xff,0xd0,0xff,0xd8,0xff,' +` 0xdf,0xff,0xd2,0xff,0xce,0xff,0xc3,0xff,' +` 0xbe,0xff,0xb4,0xff,0xb0,0xff,0xa7,0xff,' +` 0xa4,0xff,0x9e,0xff,0x9c,0xff,0x98,0xff,' +` 0x98,0xff,0x96,0xff,0x98,0xff,0x9b,0xff,' +` 0xa4,0xff,0xab,0xff,0xb6,0xff,0xc0,0xff,' +` 0xcc,0xff,0xd8,0xff,0xe5,0xff,0xf2,0xff,' +` 0xec,0x7f,0x0d,0x00,0x1a,0x00,0x27,0x00,' +` 0x33,0x00,0x3f,0x00,0x48,0x00,0x52,0x00,' +` 0x59,0x00,0x60,0x00,0x62,0x00,0x63,0x00,' +` 0x61,0x00,0x61,0x00,0x5c,0x00,0x5a,0x00,' +` 0x53,0x00,0x4f,0x00,0x47,0x00,0x42,0x00,' +` 0x39,0x00,0x33,0x00,0x29,0x00,0x25,0x00,' +` 0x1a,0x00,0x1e,0x00,0x21,0x00,0x14,0x00,' +` 0x0c,0x00,0x05,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xf0,0xff,0xe4,0xff,0xd5,0xff,0xc4,0xff,' +` 0xb0,0xff,0x9b,0xff,0x83,0xff,0x6c,0xff,' +` 0x53,0xff,0x83,0xff,0x87,0xff,0x77,0xff,' +` 0x73,0xff,0x69,0xff,0x66,0xff,0x61,0xff,' +` 0x62,0xff,0x62,0xff,0x67,0xff,0x6b,0xff,' +` 0x74,0xff,0x7d,0xff,0x8a,0xff,0x97,0xff,' +` 0xa6,0xff,0xb6,0xff,0xc8,0xff,0xda,0xff,' +` 0xed,0xff,0xec,0x7f,0x13,0x00,0x26,0x00,' +` 0x37,0x00,0x48,0x00,0x57,0x00,0x66,0x00,' +` 0x72,0x00,0x7d,0x00,0x85,0x00,0x8d,0x00,' +` 0x90,0x00,0x94,0x00,0x92,0x00,0x92,0x00,' +` 0x8c,0x00,0x88,0x00,0x7e,0x00,0x79,0x00,' +` 0x69,0x00,0x6b,0x00,0x92,0x00,0x79,0x00,' +` 0x64,0x00,0x4e,0x00,0x3b,0x00,0x2a,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x0d,0x00,0x42,0x00,' +` 0x18,0x00,0x80,0x00,0x22,0x00,0xd0,0x00,' +` 0x29,0x00,0x19,0x01,0xbd,0xff,0x4c,0x01,' +` 0x89,0xff,0xb3,0x01,0x35,0xff,0x2d,0x02,' +` 0xbd,0xfe,0xc2,0x02,0x13,0xfe,0x7f,0x03,' +` 0x23,0xfd,0x84,0x04,0xc0,0xfb,0x15,0x06,' +` 0x7c,0xf9,0xf5,0x08,0xe9,0xf4,0x53,0x10,' +` 0xd4,0xe4,0x14,0x54,0xc1,0x4e,0x36,0xe5,' +` 0xb9,0x0f,0x8a,0xf4,0x3b,0x08,0xcd,0xf8,' +` 0x2a,0x05,0xd8,0xfa,0x70,0x03,0x14,0xfc,' +` 0x50,0x02,0xee,0xfc,0x88,0x01,0x94,0xfd,' +` 0xfa,0x00,0x1a,0xfe,0x94,0x00,0x8c,0xfe,' +` 0x4e,0x00,0xf0,0xfe,0xf8,0xff,0xfa,0xfe,' +` 0xde,0xff,0x58,0xff,0xe3,0xff,0xa1,0xff,' +` 0xee,0xff,0xd5,0xff,0xf8,0xff,0xf5,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0d,0x00,0x42,0x00,0x18,0x00,0x80,0x00,' +` 0x22,0x00,0xd0,0x00,0x29,0x00,0x19,0x01,' +` 0xbd,0xff,0x4c,0x01,0x89,0xff,0xb3,0x01,' +` 0x35,0xff,0x2d,0x02,0xbd,0xfe,0xc2,0x02,' +` 0x13,0xfe,0x7f,0x03,0x23,0xfd,0x84,0x04,' +` 0xc0,0xfb,0x15,0x06,0x7c,0xf9,0xf5,0x08,' +` 0xe9,0xf4,0x53,0x10,0xd4,0xe4,0x14,0x54,' +` 0xc1,0x4e,0x36,0xe5,0xb9,0x0f,0x8a,0xf4,' +` 0x3b,0x08,0xcd,0xf8,0x2a,0x05,0xd8,0xfa,' +` 0x70,0x03,0x14,0xfc,0x50,0x02,0xee,0xfc,' +` 0x88,0x01,0x94,0xfd,0xfa,0x00,0x1a,0xfe,' +` 0x94,0x00,0x8c,0xfe,0x4e,0x00,0xf0,0xfe,' +` 0xf8,0xff,0xfa,0xfe,0xde,0xff,0x58,0xff,' +` 0xe3,0xff,0xa1,0xff,0xee,0xff,0xd5,0xff,' +` 0xf8,0xff,0xf5,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xf0,0xff,0xe4,0xff,' +` 0xd5,0xff,0xc4,0xff,0xb0,0xff,0x9b,0xff,' +` 0x83,0xff,0x6c,0xff,0x53,0xff,0x83,0xff,' +` 0x87,0xff,0x77,0xff,0x73,0xff,0x69,0xff,' +` 0x66,0xff,0x61,0xff,0x62,0xff,0x62,0xff,' +` 0x67,0xff,0x6b,0xff,0x74,0xff,0x7d,0xff,' +` 0x8a,0xff,0x97,0xff,0xa6,0xff,0xb6,0xff,' +` 0xc8,0xff,0xda,0xff,0xed,0xff,0xec,0x7f,' +` 0x13,0x00,0x26,0x00,0x37,0x00,0x48,0x00,' +` 0x57,0x00,0x66,0x00,0x72,0x00,0x7d,0x00,' +` 0x85,0x00,0x8d,0x00,0x90,0x00,0x94,0x00,' +` 0x92,0x00,0x92,0x00,0x8c,0x00,0x88,0x00,' +` 0x7e,0x00,0x79,0x00,0x69,0x00,0x6b,0x00,' +` 0x92,0x00,0x79,0x00,0x64,0x00,0x4e,0x00,' +` 0x3b,0x00,0x2a,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line2_pass.m4 b/tools/topology/topology1/m4/tdfb/coef_line2_pass.m4 new file mode 100644 index 000000000000..925ccfe362a6 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line2_pass.m4 @@ -0,0 +1,12 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x02,0x00,0x02,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_azm90_90_13el0_0_13deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_azm90_90_13el0_0_13deg_16khz.m4 new file mode 100644 index 000000000000..2221c01aecc8 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_azm90_90_13el0_0_13deg_16khz.m4 @@ -0,0 +1,696 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x84,0x15,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x84,0x15,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x00,0xd5,0x00,0xad,0x00,0x08,0x03,' +` 0xe6,0x02,0xe2,0x07,0x55,0x07,0xf0,0x0e,' +` 0x84,0x0c,0xc5,0x1a,0x4c,0x14,0x24,0x24,' +` 0x02,0x11,0x46,0x27,0x67,0xfe,0x6e,0x64,' +` 0xff,0x66,0x16,0xf5,0x52,0x1e,0xe7,0xfc,' +` 0x64,0x0a,0x07,0xfa,0x34,0x04,0xe9,0xfd,' +` 0x25,0x04,0x94,0xfd,0x7c,0x01,0x53,0xfd,' +` 0xee,0xff,0x16,0xfe,0x88,0xff,0x9b,0xfe,' +` 0x96,0xff,0x7a,0xff,0xdf,0xff,0xf0,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0x01,0x00,' +` 0x6b,0xff,0xff,0xfe,0x08,0xfd,0x59,0xfc,' +` 0x53,0xf8,0x50,0xf6,0x81,0xf0,0x2b,0xf0,' +` 0x91,0xe7,0x05,0xe6,0x84,0xdd,0x0f,0xe4,' +` 0xf6,0xdc,0xa0,0xef,0x5b,0xd4,0xe7,0x62,' +` 0xb2,0x09,0x5f,0xe5,0xaf,0xfc,0x5f,0xf7,' +` 0x4c,0x05,0x30,0x00,0xcc,0x05,0x46,0xff,' +` 0x35,0x04,0x8a,0x01,0xbf,0x03,0x80,0x01,' +` 0x7d,0x02,0x21,0x01,0x33,0x01,0x66,0x00,' +` 0x67,0x00,0x17,0x00,0x08,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x28,0x00,0x31,0x00,0xc3,0x00,0x8b,0x00,' +` 0xf1,0x01,0x4b,0x01,0x51,0x03,0x6f,0x01,' +` 0xd0,0x04,0xca,0x00,0xdc,0x04,0x4f,0xfe,' +` 0xbf,0x08,0x7d,0xfc,0x4b,0x07,0x8b,0xee,' +` 0x7b,0x01,0xe0,0xd5,0xfe,0x56,0x5c,0x1b,' +` 0x99,0xd2,0xcb,0xf1,0x9b,0xd9,0xf7,0xe6,' +` 0xc3,0xde,0xd3,0xea,0x2a,0xeb,0x33,0xf3,' +` 0x18,0xf3,0x23,0xf9,0x76,0xfa,0xa9,0xfd,' +` 0x10,0xfe,0x9a,0xff,0xba,0xff,0x0c,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0xff,' +` 0xe9,0xff,0xce,0xff,0xad,0xff,0x89,0xff,' +` 0x92,0xff,0x77,0xff,0x79,0xff,0x8c,0xff,' +` 0xff,0xff,0x18,0x00,0xec,0x00,0x43,0x00,' +` 0xa3,0xff,0xa7,0x00,0x02,0x02,0xe2,0x05,' +` 0x82,0x07,0x1a,0x09,0x6b,0x4a,0xa4,0x0b,' +` 0x82,0x0c,0xd0,0x0c,0xee,0x0e,0x2b,0x0e,' +` 0xfb,0x0c,0x20,0x0a,0x5f,0x07,0xef,0x05,' +` 0x44,0x04,0xe5,0x02,0xb6,0x01,0x02,0x01,' +` 0x77,0x00,0x40,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0e,0x00,0x57,0x00,0x62,0x00,0x51,0x01,' +` 0x8f,0x01,0x90,0x03,0xee,0x03,0xeb,0x06,' +` 0xac,0x06,0xd4,0x0b,0x84,0x0b,0x6e,0x10,' +` 0x9f,0x0b,0x73,0x10,0x1b,0x06,0x28,0x1a,' +` 0x2a,0x46,0xd0,0xfe,0xcb,0x0c,0xd0,0x01,' +` 0x57,0x04,0x94,0xfe,0x46,0x01,0x92,0xff,' +` 0xdc,0x01,0x66,0xff,0xa4,0x00,0x27,0xff,' +` 0xe1,0xff,0x46,0xff,0xcb,0xff,0x73,0xff,' +` 0xc5,0xff,0xc8,0xff,0xef,0xff,0xf9,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfb,0xff,0x15,0x00,' +` 0x5d,0xff,0x39,0xff,0xec,0xfc,0xd6,0xfc,' +` 0x1c,0xf8,0x23,0xf7,0xf1,0xef,0x3f,0xf1,' +` 0x2c,0xe7,0x6e,0xe8,0xf4,0xda,0xb5,0xe6,' +` 0x85,0xd7,0xe6,0xf4,0xe8,0xca,0x1c,0x47,' +` 0xf5,0x30,0x35,0xd8,0x71,0x02,0x33,0xf0,' +` 0xe1,0x07,0x97,0xfc,0xbe,0x07,0x4b,0xfd,' +` 0xcb,0x04,0x2c,0x00,0x31,0x04,0xcb,0x00,' +` 0xa3,0x02,0xc0,0x00,0x61,0x01,0x42,0x00,' +` 0x6e,0x00,0x10,0x00,0x0a,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x27,0x00,0x27,0x00,0xbb,0x00,0x71,0x00,' +` 0xed,0x01,0x05,0x01,0x34,0x03,0x0c,0x01,' +` 0xbb,0x04,0x2b,0x00,0xe6,0x04,0x43,0xfd,' +` 0x88,0x08,0xca,0xfb,0x98,0x07,0x9f,0xed,' +` 0x78,0x02,0x82,0xd4,0x58,0x4f,0x8f,0x25,' +` 0xe3,0xcf,0x45,0xf3,0x47,0xd9,0x9b,0xe7,' +` 0x3f,0xde,0x1b,0xeb,0xc4,0xea,0x32,0xf3,' +` 0xd5,0xf2,0xee,0xf8,0x2b,0xfa,0xad,0xfd,' +` 0xf6,0xfd,0x8e,0xff,0xb2,0xff,0x0b,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0xff,' +` 0xeb,0xff,0xd2,0xff,0xb3,0xff,0x99,0xff,' +` 0xa5,0xff,0x89,0xff,0x94,0xff,0xb0,0xff,' +` 0x21,0x00,0x38,0x00,0x10,0x01,0x86,0x00,' +` 0xd1,0xff,0xbe,0x00,0x47,0x02,0x0f,0x06,' +` 0x94,0x07,0x32,0x09,0x7f,0x4a,0xb6,0x0b,' +` 0x9b,0x0c,0xd3,0x0c,0xdb,0x0e,0x4d,0x0e,' +` 0x06,0x0d,0x1c,0x0a,0x77,0x07,0x0b,0x06,' +` 0x55,0x04,0xff,0x02,0xbf,0x01,0x0b,0x01,' +` 0x78,0x00,0x3f,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x16,0x00,0xca,0x00,0xdd,0x00,0x14,0x03,' +` 0x6d,0x03,0x2e,0x08,0xf4,0x07,0x53,0x0f,' +` 0xf9,0x0c,0x5f,0x19,0xd0,0x15,0x6f,0x23,' +` 0x98,0x12,0xad,0x25,0xd8,0x03,0xf9,0x4d,' +` 0x16,0x7c,0x86,0xf6,0x30,0x1e,0x88,0x00,' +` 0xce,0x0b,0x52,0xfb,0x81,0x05,0x76,0xff,' +` 0x0c,0x05,0xcf,0xfe,0x6d,0x02,0x97,0xfe,' +` 0x9b,0x00,0xb5,0xfe,0x13,0x00,0x1d,0xff,' +` 0xbe,0xff,0x98,0xff,0xea,0xff,0xf4,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xeb,0xff,' +` 0x40,0xff,0xae,0xfe,0x06,0xfd,0xb5,0xfb,' +` 0x82,0xf7,0x89,0xf5,0x79,0xf0,0x1b,0xef,' +` 0x8c,0xe8,0x48,0xe5,0x88,0xde,0x80,0xe3,' +` 0x70,0xe0,0x78,0xeb,0x54,0xdb,0xa9,0x67,' +` 0x98,0xfc,0x55,0xea,0xbc,0xf8,0xe6,0xf7,' +` 0x84,0x02,0x0d,0x00,0x28,0x02,0xb6,0xfe,' +` 0x58,0x02,0xbd,0x00,0x83,0x02,0x00,0x01,' +` 0x95,0x01,0xc5,0x00,0xf3,0x00,0x4c,0x00,' +` 0x42,0x00,0x0f,0x00,0x06,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,' +` 0x06,0x00,0x58,0x00,0x29,0x00,0x35,0x01,' +` 0x47,0x00,0x1a,0x02,0x25,0x00,0x66,0x03,' +` 0xfa,0xfe,0xc8,0x03,0xce,0xfb,0xed,0x05,' +` 0x4b,0xfb,0x83,0x06,0xc1,0xed,0x1c,0x02,' +` 0x91,0xd6,0xa9,0x34,0xd3,0x42,0xac,0xca,' +` 0x91,0xf4,0xfd,0xd7,0x2f,0xe7,0xa7,0xda,' +` 0x46,0xe9,0x7f,0xe7,0x00,0xf1,0xd7,0xef,' +` 0xed,0xf6,0x86,0xf7,0xc2,0xfc,0xe5,0xfc,' +` 0x21,0xff,0x42,0xff,0x14,0x00,0xfa,0xff,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xf0,0xff,' +` 0xdc,0xff,0xca,0xff,0xc9,0xff,0xd0,0xff,' +` 0xc4,0xff,0xe5,0xff,0x1c,0x00,0x79,0x00,' +` 0xa8,0x00,0x6b,0x01,0x50,0x01,0x5d,0x00,' +` 0x04,0x01,0x1d,0x03,0x83,0x06,0xc3,0x07,' +` 0x6e,0x09,0xa8,0x4a,0xdc,0x0b,0xcb,0x0c,' +` 0xd6,0x0c,0x7d,0x0e,0x99,0x0e,0x0e,0x0d,' +` 0x00,0x0a,0xb1,0x07,0x4c,0x06,0x86,0x04,' +` 0x3c,0x03,0xe7,0x01,0x1a,0x01,0x87,0x00,' +` 0x3a,0x00,0x16,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x07,0x00,0x15,0x00,0x4a,0x00,0xa4,0x00,' +` 0x46,0x01,0x3b,0x02,0x80,0x03,0xd9,0x04,' +` 0x83,0x06,0xfa,0x07,0xc4,0x09,0xd3,0x0c,' +` 0xc2,0x0e,0xb4,0x0d,0xd4,0x0c,0xb7,0x0c,' +` 0x16,0x0c,0xbe,0x4a,0x6c,0x09,0x14,0x08,' +` 0xdf,0x06,0x6f,0x04,0x67,0x01,0x3e,0x01,' +` 0x4c,0x02,0xeb,0x01,0x40,0x01,0xf9,0x00,' +` 0x9b,0x00,0x6d,0x00,0x1d,0x00,0x0b,0x00,' +` 0xf9,0xff,0xf6,0xff,0xec,0xff,0xf5,0xff,' +` 0xfd,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x06,0x00,0xf6,0xff,' +` 0xd9,0xff,0x1e,0xff,0xb5,0xfe,0xd1,0xfc,' +` 0x4a,0xfb,0x0e,0xf7,0xee,0xf5,0x19,0xf0,' +` 0xe7,0xef,0xd1,0xe8,0x23,0xe8,0x06,0xdd,' +` 0x27,0xe7,0x28,0xde,0xae,0xef,0xbc,0xd3,' +` 0xb9,0x61,0x04,0x0a,0x84,0xe3,0xff,0xfa,' +` 0xde,0xf1,0x68,0x02,0x74,0xfc,0x4b,0x00,' +` 0x17,0xfc,0x1a,0x01,0xa8,0xfe,0x5a,0x01,' +` 0xd5,0xff,0xe7,0x00,0xfc,0xff,0x98,0x00,' +` 0x1f,0x00,0x2c,0x00,0xfe,0xff,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0xfe,0xff,0x26,0x00,0x1d,0x00,0x87,0x00,' +` 0xf8,0xff,0xc1,0x00,0xca,0xff,0x19,0x01,' +` 0x98,0xfe,0xb1,0x00,0x0c,0xfc,0xa1,0xff,' +` 0x6d,0xfc,0x95,0x01,0xf5,0xf1,0xd5,0xf9,' +` 0x96,0xe4,0x27,0x06,0x23,0x63,0x2e,0xd5,' +` 0xa3,0xee,0xc1,0xde,0xce,0xe6,0x62,0xdd,' +` 0x08,0xe8,0x28,0xe9,0xd1,0xef,0x57,0xf0,' +` 0xee,0xf5,0x3b,0xf7,0x4e,0xfb,0xec,0xfc,' +` 0xbe,0xfe,0x2c,0xff,0xdd,0xff,0xfa,0xff,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xf6,0xff,' +` 0xee,0xff,0xf9,0xff,0xff,0xff,0x12,0x00,' +` 0x2a,0x00,0x7a,0x00,0xb1,0x00,0x0e,0x01,' +` 0x63,0x01,0x02,0x02,0x83,0x02,0x6f,0x01,' +` 0x8d,0x01,0x8d,0x04,0x0a,0x07,0x18,0x08,' +` 0xa9,0x09,0xca,0x4a,0xed,0x0b,0xc9,0x0c,' +` 0xbf,0x0c,0x92,0x0d,0xa7,0x0e,0xc7,0x0c,' +` 0xa9,0x09,0xea,0x07,0x6d,0x06,0xc9,0x04,' +` 0x6e,0x03,0x2f,0x02,0x3a,0x01,0x9d,0x00,' +` 0x44,0x00,0x12,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0x0d,0x00,0x19,0x00,0x7a,0x00,' +` 0xb1,0x00,0xd0,0x01,0x2e,0x02,0x22,0x04,' +` 0x6c,0x04,0x4f,0x07,0xed,0x06,0xaa,0x0a,' +` 0x9e,0x0a,0xfc,0x0f,0x9c,0x08,0x15,0x11,' +` 0x59,0x04,0x0c,0x1e,0x51,0x44,0x24,0xfe,' +` 0x6d,0x0e,0x3a,0x03,0x81,0x08,0xd6,0xff,' +` 0x35,0x05,0x27,0x02,0xdb,0x03,0x52,0x01,' +` 0x70,0x02,0xd2,0x00,0x6d,0x01,0x60,0x00,' +` 0x8c,0x00,0x0f,0x00,0x2b,0x00,0xfd,0xff,' +` 0x02,0x00,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfb,0xff,' +` 0xf6,0xff,0x7c,0xff,0x58,0xff,0x83,0xfd,' +` 0xbc,0xfc,0x2c,0xf9,0xd1,0xf8,0xf5,0xf2,' +` 0xfa,0xf3,0xe8,0xeb,0xe3,0xef,0x45,0xe0,' +` 0x9b,0xeb,0x81,0xde,0x36,0xf4,0x22,0xd1,' +` 0x52,0x26,0x3f,0x4e,0x39,0xd2,0x7b,0x00,' +` 0x64,0xe7,0xac,0xff,0xc3,0xf6,0xd3,0xfe,' +` 0x81,0xf6,0x3e,0xff,0xab,0xfa,0xe6,0xff,' +` 0x00,0xfd,0x2e,0x00,0x91,0xfe,0x27,0x00,' +` 0x69,0xff,0x29,0x00,0xd8,0xff,0x09,0x00,' +` 0xff,0xff,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,' +` 0xe3,0xff,0x03,0x00,0x80,0xff,0xce,0xff,' +` 0xc8,0xfe,0x7d,0xff,0x5b,0xfd,0xc7,0xfe,' +` 0x34,0xfb,0x74,0xfd,0x47,0xf7,0x24,0xfd,' +` 0x72,0xf8,0xf7,0xf9,0x04,0xeb,0x77,0xf9,' +` 0x7d,0xda,0xd2,0x63,0x63,0x02,0xcb,0xdb,' +` 0xa1,0xed,0x59,0xe2,0x68,0xe7,0xc9,0xe3,' +` 0xe3,0xee,0x5c,0xed,0x60,0xf3,0x0d,0xf4,' +` 0xa3,0xf8,0xdc,0xf9,0xba,0xfc,0xf5,0xfd,' +` 0x59,0xff,0x9e,0xff,0xf8,0xff,0xff,0xff,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x00,0x00,0x0d,0x00,' +` 0x1c,0x00,0x3e,0x00,0x67,0x00,0xcc,0x00,' +` 0x1a,0x01,0x86,0x01,0xde,0x01,0x78,0x02,' +` 0xe9,0x02,0xf7,0x03,0x2d,0x03,0xc9,0x02,' +` 0x5f,0x06,0xa2,0x07,0xa8,0x08,0xcb,0x09,' +` 0xc8,0x4a,0xca,0x0b,0x46,0x0c,0x4f,0x0c,' +` 0x1a,0x0c,0xd8,0x0d,0xc3,0x0b,0xf4,0x08,' +` 0xd9,0x07,0x38,0x06,0xd9,0x04,0x72,0x03,' +` 0x5d,0x02,0x6c,0x01,0xbd,0x00,0x51,0x00,' +` 0x1d,0x00,0x03,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x11,0x00,0x24,0x00,' +` 0x89,0x00,0xd5,0x00,0xbe,0x01,0x22,0x02,' +` 0xc2,0x03,0x2b,0x04,0x79,0x06,0x56,0x06,' +` 0x23,0x09,0xea,0x08,0xa1,0x0d,0xc4,0x07,' +` 0x49,0x0f,0xe4,0x04,0xc5,0x19,0x60,0x46,' +` 0x0c,0x00,0x7b,0x0e,0xe5,0x04,0x2e,0x0a,' +` 0xb2,0x02,0x15,0x07,0x00,0x04,0x2d,0x05,' +` 0xce,0x02,0x6e,0x03,0xdf,0x01,0x12,0x02,' +` 0xfb,0x00,0xf7,0x00,0x4c,0x00,0x47,0x00,' +` 0x0c,0x00,0x08,0x00,0xff,0xff,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xe2,0xff,0xd4,0xff,0x0f,0xff,0x64,0xfe,' +` 0x41,0xfc,0xb9,0xfb,0x17,0xf8,0xce,0xf7,' +` 0x70,0xf2,0xa0,0xf3,0x83,0xec,0x0c,0xf0,' +` 0x96,0xe2,0xab,0xef,0xc1,0xe0,0x4e,0xf5,' +` 0xf9,0xd1,0x07,0x5c,0x4c,0x14,0x47,0xdc,' +` 0xe6,0xf9,0xc5,0xe8,0xf2,0xfa,0x00,0xf3,' +` 0xd3,0xf8,0x87,0xf5,0x1a,0xfb,0x4d,0xf9,' +` 0xfc,0xfc,0x19,0xfc,0x7d,0xfe,0x36,0xfe,' +` 0x69,0xff,0x4f,0xff,0xde,0xff,0xf1,0xff,' +` 0x04,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xe6,0xff,' +` 0xdc,0xff,0x2f,0xff,0x70,0xff,0xe8,0xfd,' +` 0x88,0xfe,0x85,0xfb,0x24,0xfd,0x53,0xf8,' +` 0x67,0xfb,0x04,0xf4,0x91,0xf9,0x57,0xf1,' +` 0x16,0xfb,0x86,0xe5,0x59,0xfd,0x41,0xd4,' +` 0x24,0x2e,0x8b,0x48,0xcd,0xcd,0x08,0xf8,' +` 0xeb,0xde,0xbf,0xf0,0xf5,0xe1,0x0f,0xf2,' +` 0xc6,0xeb,0xcb,0xf4,0x2e,0xf2,0xa0,0xf8,' +` 0x0c,0xf8,0x3a,0xfc,0x47,0xfc,0xb5,0xfe,' +` 0x20,0xff,0xec,0xff,0xe4,0xff,0x03,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x06,0x00,0x1d,0x00,0x3c,0x00,' +` 0x7e,0x00,0xdd,0x00,0x59,0x01,0xd7,0x01,' +` 0x80,0x02,0xfd,0x02,0xd5,0x03,0x68,0x04,' +` 0x99,0x05,0x89,0x05,0x4c,0x05,0x1d,0x08,' +` 0x99,0x08,0x84,0x09,0x0a,0x0a,0xa0,0x4a,' +` 0x47,0x0b,0x3e,0x0b,0x46,0x0b,0x78,0x0a,' +` 0x9a,0x0b,0xda,0x09,0xd1,0x07,0x06,0x07,' +` 0x96,0x05,0x7f,0x04,0x31,0x03,0x47,0x02,' +` 0x6f,0x01,0xe1,0x00,0x63,0x00,0x27,0x00,' +` 0x08,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x06,0x00,0x1b,0x00,' +` 0x52,0x00,0xb9,0x00,0x22,0x01,0xd2,0x01,' +` 0x7b,0x02,0x7c,0x03,0x46,0x04,0x74,0x05,' +` 0x35,0x06,0x78,0x07,0x07,0x08,0x65,0x09,' +` 0x41,0x09,0xb2,0x0a,0xb4,0x09,0x4b,0x0c,' +` 0x77,0x4a,0xf5,0x08,0xda,0x0a,0x24,0x09,' +` 0x52,0x09,0xdc,0x07,0x7e,0x07,0x48,0x06,' +` 0x89,0x05,0x65,0x04,0x9a,0x03,0xa7,0x02,' +` 0xf2,0x01,0x42,0x01,0xc9,0x00,0x6b,0x00,' +` 0x2c,0x00,0x08,0x00,0x01,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf3,0xff,0xce,0xff,0x59,0xff,0x97,0xfe,' +` 0xb3,0xfd,0x70,0xfc,0xf6,0xfa,0x2c,0xf9,' +` 0x4d,0xf7,0x51,0xf5,0x55,0xf3,0x68,0xf1,' +` 0x89,0xef,0xc3,0xed,0xc4,0xec,0xa1,0xeb,' +` 0x09,0xeb,0x9f,0xea,0x87,0x6a,0x11,0xeb,' +` 0xc6,0xeb,0xc3,0xec,0x08,0xee,0xc3,0xef,' +` 0x67,0xf1,0x1f,0xf3,0x26,0xf5,0x03,0xf7,' +` 0xec,0xf8,0x95,0xfa,0x2d,0xfc,0x6c,0xfd,' +` 0x74,0xfe,0x23,0xff,0xaa,0xff,0xee,0xff,' +` 0xfe,0xff,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf3,0xff,0xce,0xff,' +` 0x59,0xff,0x97,0xfe,0xb3,0xfd,0x70,0xfc,' +` 0xf6,0xfa,0x2c,0xf9,0x4d,0xf7,0x51,0xf5,' +` 0x55,0xf3,0x68,0xf1,0x89,0xef,0xc3,0xed,' +` 0xc4,0xec,0xa1,0xeb,0x09,0xeb,0x9f,0xea,' +` 0x87,0x6a,0x11,0xeb,0xc6,0xeb,0xc3,0xec,' +` 0x08,0xee,0xc3,0xef,0x67,0xf1,0x1f,0xf3,' +` 0x26,0xf5,0x03,0xf7,0xec,0xf8,0x95,0xfa,' +` 0x2d,0xfc,0x6c,0xfd,0x74,0xfe,0x23,0xff,' +` 0xaa,0xff,0xee,0xff,0xfe,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x06,0x00,0x1b,0x00,0x52,0x00,0xb9,0x00,' +` 0x22,0x01,0xd2,0x01,0x7b,0x02,0x7c,0x03,' +` 0x46,0x04,0x74,0x05,0x35,0x06,0x78,0x07,' +` 0x07,0x08,0x65,0x09,0x41,0x09,0xb2,0x0a,' +` 0xb4,0x09,0x4b,0x0c,0x77,0x4a,0xf5,0x08,' +` 0xda,0x0a,0x24,0x09,0x52,0x09,0xdc,0x07,' +` 0x7e,0x07,0x48,0x06,0x89,0x05,0x65,0x04,' +` 0x9a,0x03,0xa7,0x02,0xf2,0x01,0x42,0x01,' +` 0xc9,0x00,0x6b,0x00,0x2c,0x00,0x08,0x00,' +` 0x01,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x06,0x00,' +` 0x1d,0x00,0x3c,0x00,0x7e,0x00,0xdd,0x00,' +` 0x59,0x01,0xd7,0x01,0x80,0x02,0xfd,0x02,' +` 0xd5,0x03,0x68,0x04,0x99,0x05,0x89,0x05,' +` 0x4c,0x05,0x1d,0x08,0x99,0x08,0x84,0x09,' +` 0x0a,0x0a,0xa0,0x4a,0x47,0x0b,0x3e,0x0b,' +` 0x46,0x0b,0x78,0x0a,0x9a,0x0b,0xda,0x09,' +` 0xd1,0x07,0x06,0x07,0x96,0x05,0x7f,0x04,' +` 0x31,0x03,0x47,0x02,0x6f,0x01,0xe1,0x00,' +` 0x63,0x00,0x27,0x00,0x08,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xe6,0xff,0xdc,0xff,0x2f,0xff,' +` 0x70,0xff,0xe8,0xfd,0x88,0xfe,0x85,0xfb,' +` 0x24,0xfd,0x53,0xf8,0x67,0xfb,0x04,0xf4,' +` 0x91,0xf9,0x57,0xf1,0x16,0xfb,0x86,0xe5,' +` 0x59,0xfd,0x41,0xd4,0x24,0x2e,0x8b,0x48,' +` 0xcd,0xcd,0x08,0xf8,0xeb,0xde,0xbf,0xf0,' +` 0xf5,0xe1,0x0f,0xf2,0xc6,0xeb,0xcb,0xf4,' +` 0x2e,0xf2,0xa0,0xf8,0x0c,0xf8,0x3a,0xfc,' +` 0x47,0xfc,0xb5,0xfe,0x20,0xff,0xec,0xff,' +` 0xe4,0xff,0x03,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xe2,0xff,0xd4,0xff,' +` 0x0f,0xff,0x64,0xfe,0x41,0xfc,0xb9,0xfb,' +` 0x17,0xf8,0xce,0xf7,0x70,0xf2,0xa0,0xf3,' +` 0x83,0xec,0x0c,0xf0,0x96,0xe2,0xab,0xef,' +` 0xc1,0xe0,0x4e,0xf5,0xf9,0xd1,0x07,0x5c,' +` 0x4c,0x14,0x47,0xdc,0xe6,0xf9,0xc5,0xe8,' +` 0xf2,0xfa,0x00,0xf3,0xd3,0xf8,0x87,0xf5,' +` 0x1a,0xfb,0x4d,0xf9,0xfc,0xfc,0x19,0xfc,' +` 0x7d,0xfe,0x36,0xfe,0x69,0xff,0x4f,0xff,' +` 0xde,0xff,0xf1,0xff,0x04,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x11,0x00,0x24,0x00,0x89,0x00,0xd5,0x00,' +` 0xbe,0x01,0x22,0x02,0xc2,0x03,0x2b,0x04,' +` 0x79,0x06,0x56,0x06,0x23,0x09,0xea,0x08,' +` 0xa1,0x0d,0xc4,0x07,0x49,0x0f,0xe4,0x04,' +` 0xc5,0x19,0x60,0x46,0x0c,0x00,0x7b,0x0e,' +` 0xe5,0x04,0x2e,0x0a,0xb2,0x02,0x15,0x07,' +` 0x00,0x04,0x2d,0x05,0xce,0x02,0x6e,0x03,' +` 0xdf,0x01,0x12,0x02,0xfb,0x00,0xf7,0x00,' +` 0x4c,0x00,0x47,0x00,0x0c,0x00,0x08,0x00,' +` 0xff,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0x00,0x00,0x0d,0x00,0x1c,0x00,0x3e,0x00,' +` 0x67,0x00,0xcc,0x00,0x1a,0x01,0x86,0x01,' +` 0xde,0x01,0x78,0x02,0xe9,0x02,0xf7,0x03,' +` 0x2d,0x03,0xc9,0x02,0x5f,0x06,0xa2,0x07,' +` 0xa8,0x08,0xcb,0x09,0xc8,0x4a,0xca,0x0b,' +` 0x46,0x0c,0x4f,0x0c,0x1a,0x0c,0xd8,0x0d,' +` 0xc3,0x0b,0xf4,0x08,0xd9,0x07,0x38,0x06,' +` 0xd9,0x04,0x72,0x03,0x5d,0x02,0x6c,0x01,' +` 0xbd,0x00,0x51,0x00,0x1d,0x00,0x03,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0x00,0x00,0xe3,0xff,0x03,0x00,' +` 0x80,0xff,0xce,0xff,0xc8,0xfe,0x7d,0xff,' +` 0x5b,0xfd,0xc7,0xfe,0x34,0xfb,0x74,0xfd,' +` 0x47,0xf7,0x24,0xfd,0x72,0xf8,0xf7,0xf9,' +` 0x04,0xeb,0x77,0xf9,0x7d,0xda,0xd2,0x63,' +` 0x63,0x02,0xcb,0xdb,0xa1,0xed,0x59,0xe2,' +` 0x68,0xe7,0xc9,0xe3,0xe3,0xee,0x5c,0xed,' +` 0x60,0xf3,0x0d,0xf4,0xa3,0xf8,0xdc,0xf9,' +` 0xba,0xfc,0xf5,0xfd,0x59,0xff,0x9e,0xff,' +` 0xf8,0xff,0xff,0xff,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfb,0xff,0xf6,0xff,0x7c,0xff,' +` 0x58,0xff,0x83,0xfd,0xbc,0xfc,0x2c,0xf9,' +` 0xd1,0xf8,0xf5,0xf2,0xfa,0xf3,0xe8,0xeb,' +` 0xe3,0xef,0x45,0xe0,0x9b,0xeb,0x81,0xde,' +` 0x36,0xf4,0x22,0xd1,0x52,0x26,0x3f,0x4e,' +` 0x39,0xd2,0x7b,0x00,0x64,0xe7,0xac,0xff,' +` 0xc3,0xf6,0xd3,0xfe,0x81,0xf6,0x3e,0xff,' +` 0xab,0xfa,0xe6,0xff,0x00,0xfd,0x2e,0x00,' +` 0x91,0xfe,0x27,0x00,0x69,0xff,0x29,0x00,' +` 0xd8,0xff,0x09,0x00,0xff,0xff,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x00,' +` 0x19,0x00,0x7a,0x00,0xb1,0x00,0xd0,0x01,' +` 0x2e,0x02,0x22,0x04,0x6c,0x04,0x4f,0x07,' +` 0xed,0x06,0xaa,0x0a,0x9e,0x0a,0xfc,0x0f,' +` 0x9c,0x08,0x15,0x11,0x59,0x04,0x0c,0x1e,' +` 0x51,0x44,0x24,0xfe,0x6d,0x0e,0x3a,0x03,' +` 0x81,0x08,0xd6,0xff,0x35,0x05,0x27,0x02,' +` 0xdb,0x03,0x52,0x01,0x70,0x02,0xd2,0x00,' +` 0x6d,0x01,0x60,0x00,0x8c,0x00,0x0f,0x00,' +` 0x2b,0x00,0xfd,0xff,0x02,0x00,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xf6,0xff,0xee,0xff,0xf9,0xff,' +` 0xff,0xff,0x12,0x00,0x2a,0x00,0x7a,0x00,' +` 0xb1,0x00,0x0e,0x01,0x63,0x01,0x02,0x02,' +` 0x83,0x02,0x6f,0x01,0x8d,0x01,0x8d,0x04,' +` 0x0a,0x07,0x18,0x08,0xa9,0x09,0xca,0x4a,' +` 0xed,0x0b,0xc9,0x0c,0xbf,0x0c,0x92,0x0d,' +` 0xa7,0x0e,0xc7,0x0c,0xa9,0x09,0xea,0x07,' +` 0x6d,0x06,0xc9,0x04,0x6e,0x03,0x2f,0x02,' +` 0x3a,0x01,0x9d,0x00,0x44,0x00,0x12,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0xfe,0xff,0x26,0x00,' +` 0x1d,0x00,0x87,0x00,0xf8,0xff,0xc1,0x00,' +` 0xca,0xff,0x19,0x01,0x98,0xfe,0xb1,0x00,' +` 0x0c,0xfc,0xa1,0xff,0x6d,0xfc,0x95,0x01,' +` 0xf5,0xf1,0xd5,0xf9,0x96,0xe4,0x27,0x06,' +` 0x23,0x63,0x2e,0xd5,0xa3,0xee,0xc1,0xde,' +` 0xce,0xe6,0x62,0xdd,0x08,0xe8,0x28,0xe9,' +` 0xd1,0xef,0x57,0xf0,0xee,0xf5,0x3b,0xf7,' +` 0x4e,0xfb,0xec,0xfc,0xbe,0xfe,0x2c,0xff,' +` 0xdd,0xff,0xfa,0xff,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x06,0x00,0xf6,0xff,0xd9,0xff,0x1e,0xff,' +` 0xb5,0xfe,0xd1,0xfc,0x4a,0xfb,0x0e,0xf7,' +` 0xee,0xf5,0x19,0xf0,0xe7,0xef,0xd1,0xe8,' +` 0x23,0xe8,0x06,0xdd,0x27,0xe7,0x28,0xde,' +` 0xae,0xef,0xbc,0xd3,0xb9,0x61,0x04,0x0a,' +` 0x84,0xe3,0xff,0xfa,0xde,0xf1,0x68,0x02,' +` 0x74,0xfc,0x4b,0x00,0x17,0xfc,0x1a,0x01,' +` 0xa8,0xfe,0x5a,0x01,0xd5,0xff,0xe7,0x00,' +` 0xfc,0xff,0x98,0x00,0x1f,0x00,0x2c,0x00,' +` 0xfe,0xff,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x07,0x00,0x15,0x00,' +` 0x4a,0x00,0xa4,0x00,0x46,0x01,0x3b,0x02,' +` 0x80,0x03,0xd9,0x04,0x83,0x06,0xfa,0x07,' +` 0xc4,0x09,0xd3,0x0c,0xc2,0x0e,0xb4,0x0d,' +` 0xd4,0x0c,0xb7,0x0c,0x16,0x0c,0xbe,0x4a,' +` 0x6c,0x09,0x14,0x08,0xdf,0x06,0x6f,0x04,' +` 0x67,0x01,0x3e,0x01,0x4c,0x02,0xeb,0x01,' +` 0x40,0x01,0xf9,0x00,0x9b,0x00,0x6d,0x00,' +` 0x1d,0x00,0x0b,0x00,0xf9,0xff,0xf6,0xff,' +` 0xec,0xff,0xf5,0xff,0xfd,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfc,0xff,0xf0,0xff,0xdc,0xff,0xca,0xff,' +` 0xc9,0xff,0xd0,0xff,0xc4,0xff,0xe5,0xff,' +` 0x1c,0x00,0x79,0x00,0xa8,0x00,0x6b,0x01,' +` 0x50,0x01,0x5d,0x00,0x04,0x01,0x1d,0x03,' +` 0x83,0x06,0xc3,0x07,0x6e,0x09,0xa8,0x4a,' +` 0xdc,0x0b,0xcb,0x0c,0xd6,0x0c,0x7d,0x0e,' +` 0x99,0x0e,0x0e,0x0d,0x00,0x0a,0xb1,0x07,' +` 0x4c,0x06,0x86,0x04,0x3c,0x03,0xe7,0x01,' +` 0x1a,0x01,0x87,0x00,0x3a,0x00,0x16,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x08,0x00,0x06,0x00,0x58,0x00,' +` 0x29,0x00,0x35,0x01,0x47,0x00,0x1a,0x02,' +` 0x25,0x00,0x66,0x03,0xfa,0xfe,0xc8,0x03,' +` 0xce,0xfb,0xed,0x05,0x4b,0xfb,0x83,0x06,' +` 0xc1,0xed,0x1c,0x02,0x91,0xd6,0xa9,0x34,' +` 0xd3,0x42,0xac,0xca,0x91,0xf4,0xfd,0xd7,' +` 0x2f,0xe7,0xa7,0xda,0x46,0xe9,0x7f,0xe7,' +` 0x00,0xf1,0xd7,0xef,0xed,0xf6,0x86,0xf7,' +` 0xc2,0xfc,0xe5,0xfc,0x21,0xff,0x42,0xff,' +` 0x14,0x00,0xfa,0xff,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfc,0xff,0xeb,0xff,0x40,0xff,0xae,0xfe,' +` 0x06,0xfd,0xb5,0xfb,0x82,0xf7,0x89,0xf5,' +` 0x79,0xf0,0x1b,0xef,0x8c,0xe8,0x48,0xe5,' +` 0x88,0xde,0x80,0xe3,0x70,0xe0,0x78,0xeb,' +` 0x54,0xdb,0xa9,0x67,0x98,0xfc,0x55,0xea,' +` 0xbc,0xf8,0xe6,0xf7,0x84,0x02,0x0d,0x00,' +` 0x28,0x02,0xb6,0xfe,0x58,0x02,0xbd,0x00,' +` 0x83,0x02,0x00,0x01,0x95,0x01,0xc5,0x00,' +` 0xf3,0x00,0x4c,0x00,0x42,0x00,0x0f,0x00,' +` 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x16,0x00,0xca,0x00,' +` 0xdd,0x00,0x14,0x03,0x6d,0x03,0x2e,0x08,' +` 0xf4,0x07,0x53,0x0f,0xf9,0x0c,0x5f,0x19,' +` 0xd0,0x15,0x6f,0x23,0x98,0x12,0xad,0x25,' +` 0xd8,0x03,0xf9,0x4d,0x16,0x7c,0x86,0xf6,' +` 0x30,0x1e,0x88,0x00,0xce,0x0b,0x52,0xfb,' +` 0x81,0x05,0x76,0xff,0x0c,0x05,0xcf,0xfe,' +` 0x6d,0x02,0x97,0xfe,0x9b,0x00,0xb5,0xfe,' +` 0x13,0x00,0x1d,0xff,0xbe,0xff,0x98,0xff,' +` 0xea,0xff,0xf4,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfa,0xff,0xeb,0xff,0xd2,0xff,' +` 0xb3,0xff,0x99,0xff,0xa5,0xff,0x89,0xff,' +` 0x94,0xff,0xb0,0xff,0x21,0x00,0x38,0x00,' +` 0x10,0x01,0x86,0x00,0xd1,0xff,0xbe,0x00,' +` 0x47,0x02,0x0f,0x06,0x94,0x07,0x32,0x09,' +` 0x7f,0x4a,0xb6,0x0b,0x9b,0x0c,0xd3,0x0c,' +` 0xdb,0x0e,0x4d,0x0e,0x06,0x0d,0x1c,0x0a,' +` 0x77,0x07,0x0b,0x06,0x55,0x04,0xff,0x02,' +` 0xbf,0x01,0x0b,0x01,0x78,0x00,0x3f,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x27,0x00,0x27,0x00,' +` 0xbb,0x00,0x71,0x00,0xed,0x01,0x05,0x01,' +` 0x34,0x03,0x0c,0x01,0xbb,0x04,0x2b,0x00,' +` 0xe6,0x04,0x43,0xfd,0x88,0x08,0xca,0xfb,' +` 0x98,0x07,0x9f,0xed,0x78,0x02,0x82,0xd4,' +` 0x58,0x4f,0x8f,0x25,0xe3,0xcf,0x45,0xf3,' +` 0x47,0xd9,0x9b,0xe7,0x3f,0xde,0x1b,0xeb,' +` 0xc4,0xea,0x32,0xf3,0xd5,0xf2,0xee,0xf8,' +` 0x2b,0xfa,0xad,0xfd,0xf6,0xfd,0x8e,0xff,' +` 0xb2,0xff,0x0b,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfb,0xff,0x15,0x00,0x5d,0xff,0x39,0xff,' +` 0xec,0xfc,0xd6,0xfc,0x1c,0xf8,0x23,0xf7,' +` 0xf1,0xef,0x3f,0xf1,0x2c,0xe7,0x6e,0xe8,' +` 0xf4,0xda,0xb5,0xe6,0x85,0xd7,0xe6,0xf4,' +` 0xe8,0xca,0x1c,0x47,0xf5,0x30,0x35,0xd8,' +` 0x71,0x02,0x33,0xf0,0xe1,0x07,0x97,0xfc,' +` 0xbe,0x07,0x4b,0xfd,0xcb,0x04,0x2c,0x00,' +` 0x31,0x04,0xcb,0x00,0xa3,0x02,0xc0,0x00,' +` 0x61,0x01,0x42,0x00,0x6e,0x00,0x10,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x0e,0x00,0x57,0x00,' +` 0x62,0x00,0x51,0x01,0x8f,0x01,0x90,0x03,' +` 0xee,0x03,0xeb,0x06,0xac,0x06,0xd4,0x0b,' +` 0x84,0x0b,0x6e,0x10,0x9f,0x0b,0x73,0x10,' +` 0x1b,0x06,0x28,0x1a,0x2a,0x46,0xd0,0xfe,' +` 0xcb,0x0c,0xd0,0x01,0x57,0x04,0x94,0xfe,' +` 0x46,0x01,0x92,0xff,0xdc,0x01,0x66,0xff,' +` 0xa4,0x00,0x27,0xff,0xe1,0xff,0x46,0xff,' +` 0xcb,0xff,0x73,0xff,0xc5,0xff,0xc8,0xff,' +` 0xef,0xff,0xf9,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfa,0xff,0xe9,0xff,0xce,0xff,' +` 0xad,0xff,0x89,0xff,0x92,0xff,0x77,0xff,' +` 0x79,0xff,0x8c,0xff,0xff,0xff,0x18,0x00,' +` 0xec,0x00,0x43,0x00,0xa3,0xff,0xa7,0x00,' +` 0x02,0x02,0xe2,0x05,0x82,0x07,0x1a,0x09,' +` 0x6b,0x4a,0xa4,0x0b,0x82,0x0c,0xd0,0x0c,' +` 0xee,0x0e,0x2b,0x0e,0xfb,0x0c,0x20,0x0a,' +` 0x5f,0x07,0xef,0x05,0x44,0x04,0xe5,0x02,' +` 0xb6,0x01,0x02,0x01,0x77,0x00,0x40,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x28,0x00,0x31,0x00,' +` 0xc3,0x00,0x8b,0x00,0xf1,0x01,0x4b,0x01,' +` 0x51,0x03,0x6f,0x01,0xd0,0x04,0xca,0x00,' +` 0xdc,0x04,0x4f,0xfe,0xbf,0x08,0x7d,0xfc,' +` 0x4b,0x07,0x8b,0xee,0x7b,0x01,0xe0,0xd5,' +` 0xfe,0x56,0x5c,0x1b,0x99,0xd2,0xcb,0xf1,' +` 0x9b,0xd9,0xf7,0xe6,0xc3,0xde,0xd3,0xea,' +` 0x2a,0xeb,0x33,0xf3,0x18,0xf3,0x23,0xf9,' +` 0x76,0xfa,0xa9,0xfd,0x10,0xfe,0x9a,0xff,' +` 0xba,0xff,0x0c,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0x01,0x00,0x6b,0xff,0xff,0xfe,' +` 0x08,0xfd,0x59,0xfc,0x53,0xf8,0x50,0xf6,' +` 0x81,0xf0,0x2b,0xf0,0x91,0xe7,0x05,0xe6,' +` 0x84,0xdd,0x0f,0xe4,0xf6,0xdc,0xa0,0xef,' +` 0x5b,0xd4,0xe7,0x62,0xb2,0x09,0x5f,0xe5,' +` 0xaf,0xfc,0x5f,0xf7,0x4c,0x05,0x30,0x00,' +` 0xcc,0x05,0x46,0xff,0x35,0x04,0x8a,0x01,' +` 0xbf,0x03,0x80,0x01,0x7d,0x02,0x21,0x01,' +` 0x33,0x01,0x66,0x00,0x67,0x00,0x17,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x14,0x00,0xd5,0x00,' +` 0xad,0x00,0x08,0x03,0xe6,0x02,0xe2,0x07,' +` 0x55,0x07,0xf0,0x0e,0x84,0x0c,0xc5,0x1a,' +` 0x4c,0x14,0x24,0x24,0x02,0x11,0x46,0x27,' +` 0x67,0xfe,0x6e,0x64,0xff,0x66,0x16,0xf5,' +` 0x52,0x1e,0xe7,0xfc,0x64,0x0a,0x07,0xfa,' +` 0x34,0x04,0xe9,0xfd,0x25,0x04,0x94,0xfd,' +` 0x7c,0x01,0x53,0xfd,0xee,0xff,0x16,0xfe,' +` 0x88,0xff,0x9b,0xfe,0x96,0xff,0x7a,0xff,' +` 0xdf,0xff,0xf0,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0x75,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_azm90_90_13el0_0_13deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_azm90_90_13el0_0_13deg_48khz.m4 new file mode 100644 index 000000000000..973b2ece3a33 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_azm90_90_13el0_0_13deg_48khz.m4 @@ -0,0 +1,1216 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x25,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x25,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xee,0x01,0x8c,0x01,0xc2,0x02,0x20,0x02,' +` 0xba,0x03,0xbe,0x02,0x74,0x05,0x59,0x04,' +` 0xdc,0x06,0x0a,0x05,0x31,0x08,0xa5,0x05,' +` 0x8a,0x09,0x16,0x06,0xe5,0x0a,0x4c,0x06,' +` 0x21,0x0b,0x29,0x04,0x15,0x0c,0x29,0x03,' +` 0xb5,0x0d,0x1a,0x01,0x73,0x10,0xa3,0xfc,' +` 0x58,0x17,0x26,0xed,0x53,0x53,0x38,0x5d,' +` 0xfc,0xea,0x92,0x16,0x4f,0xfa,0x5f,0x0e,' +` 0xf2,0xfd,0xa7,0x0a,0x43,0xff,0x3b,0x08,' +` 0xc8,0xff,0x25,0x06,0x23,0xfe,0x8e,0x03,' +` 0x51,0xfe,0x8f,0x02,0x6a,0xfe,0xc5,0x01,' +` 0x7c,0xfe,0x29,0x01,0x8c,0xfe,0xce,0x00,' +` 0xa1,0xff,0x2e,0x01,0xa3,0xff,0xce,0x00,' +` 0xa7,0xff,0x85,0x00,0xb1,0xff,0x51,0x00,' +` 0xbf,0xff,0x2d,0x00,0xcf,0xff,0x15,0x00,' +` 0xda,0xff,0x04,0x00,0xeb,0xff,0x01,0x00,' +` 0xf8,0xff,0x00,0x00,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x51,0xff,0x56,0xff,' +` 0xcd,0xfe,0xe5,0xfe,0x1e,0xfe,0x58,0xfe,' +` 0x47,0xfd,0xb2,0xfd,0x4b,0xfc,0xfa,0xfc,' +` 0x38,0xfb,0xa1,0xfb,0x0e,0xf9,0xac,0xfa,' +` 0xbe,0xf7,0xf7,0xf9,0x67,0xf6,0x71,0xf9,' +` 0x11,0xf5,0x31,0xf9,0xb2,0xf3,0x5a,0xfa,' +` 0x42,0xf4,0x81,0xfb,0xe3,0xf2,0x10,0xfd,' +` 0xfd,0xf0,0x0f,0x00,0x2f,0xed,0x61,0x07,' +` 0x5e,0xdf,0x8c,0x3e,0x61,0x55,0xb9,0xdd,' +` 0x45,0x0a,0xde,0xee,0xa3,0x03,0x25,0xf4,' +` 0xa3,0x01,0x24,0xf7,0xfb,0x00,0x3d,0xf9,' +` 0x10,0x01,0xa0,0xfc,0x57,0x02,0xca,0xfd,' +` 0x50,0x02,0xb5,0xfe,0x46,0x02,0x69,0xff,' +` 0x31,0x02,0xf0,0xff,0xf8,0x01,0x56,0xff,' +` 0x07,0x01,0xa8,0xff,0xef,0x00,0xe3,0xff,' +` 0xcf,0x00,0x06,0x00,0xa8,0x00,0x17,0x00,' +` 0x7e,0x00,0x1a,0x00,0x55,0x00,0x10,0x00,' +` 0x2e,0x00,0x0a,0x00,0x15,0x00,0x04,0x00,' +` 0x05,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x09,0x00,0x0d,0x00,' +` 0x17,0x00,0x1a,0x00,0x2b,0x00,0x32,0x00,' +` 0x45,0x00,0x43,0x00,0x5a,0x00,0x4e,0x00,' +` 0x68,0x00,0x4e,0x00,0x6d,0x00,0x3d,0x00,' +` 0x65,0x00,0x10,0x00,0x9b,0x00,0x00,0x01,' +` 0x09,0x01,0xc2,0x00,0xdf,0x00,0x6e,0x00,' +` 0x92,0x00,0xfd,0xff,0x24,0x00,0x7b,0xff,' +` 0x2f,0xff,0xce,0xfc,0x71,0xfd,0xdd,0xfb,' +` 0xad,0xfc,0xbf,0xfa,0x0a,0xfc,0x6b,0xf9,' +` 0xd0,0xfb,0x4b,0xf7,0x63,0xfe,0x9f,0x78,' +` 0xfb,0xf3,0xa9,0xfa,0x79,0xf6,0xfa,0xf8,' +` 0xb7,0xf6,0x45,0xf8,0xcb,0xf6,0xfa,0xf7,' +` 0xf2,0xf6,0x04,0xf8,0x31,0xf6,0x9b,0xf6,' +` 0x8e,0xf6,0x55,0xf7,0x67,0xf7,0x2d,0xf8,' +` 0x65,0xf8,0x21,0xf9,0x7a,0xf9,0x1f,0xfa,' +` 0x1c,0xfb,0x14,0xfc,0x4e,0xfc,0xed,0xfc,' +` 0x38,0xfd,0xbb,0xfd,0x05,0xfe,0x6e,0xfe,' +` 0xaf,0xfe,0x00,0xff,0x36,0xff,0x6f,0xff,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xfd,0xff,0xfc,0xff,' +` 0xfa,0xff,0xfa,0xff,0xfc,0xff,0xfc,0xff,' +` 0xfe,0xff,0x00,0x00,0x04,0x00,0x08,0x00,' +` 0x0f,0x00,0x15,0x00,0x22,0x00,0x27,0x00,' +` 0x41,0x00,0x1d,0x00,0xce,0xff,0xec,0xff,' +` 0xed,0xff,0x0a,0x00,0x11,0x00,0x34,0x00,' +` 0x3f,0x00,0x6b,0x00,0x6e,0x00,0xe0,0x00,' +` 0xad,0x01,0xcc,0x01,0x0a,0x02,0x37,0x02,' +` 0x6f,0x02,0x9f,0x02,0xd3,0x02,0x01,0x03,' +` 0x30,0x03,0x5a,0x03,0x7b,0x43,0xa5,0x03,' +` 0xc4,0x03,0xdf,0x03,0xf2,0x03,0x03,0x04,' +` 0x09,0x04,0x0f,0x04,0x06,0x04,0x06,0x04,' +` 0xe4,0x03,0x64,0x04,0x89,0x04,0x3f,0x04,' +` 0x1b,0x04,0xd4,0x03,0xa4,0x03,0x5b,0x03,' +` 0x27,0x03,0xd9,0x02,0xaa,0x02,0x18,0x02,' +` 0xb3,0x01,0x88,0x01,0x50,0x01,0x22,0x01,' +` 0xf3,0x00,0xca,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x47,0x01,0x45,0x02,0xd4,0x01,0x28,0x03,' +` 0x74,0x02,0x2a,0x04,0x14,0x03,0xf2,0x05,' +` 0xcf,0x04,0x68,0x07,0x7f,0x05,0xbe,0x08,' +` 0x16,0x06,0x15,0x0a,0x7c,0x06,0x70,0x0b,' +` 0x75,0x06,0x1a,0x0b,0x91,0x04,0x49,0x0c,' +` 0x78,0x03,0xdb,0x0d,0x57,0x01,0x8e,0x10,' +` 0xbd,0xfc,0xa8,0x17,0xe6,0xeb,0x30,0x68,' +` 0x38,0x47,0x74,0xee,0xed,0x14,0x46,0xfb,' +` 0x93,0x0d,0x72,0xfe,0x1a,0x0a,0x93,0xff,' +` 0xcc,0x07,0xfe,0xff,0xde,0x05,0x6a,0xfe,' +` 0x51,0x03,0x8a,0xfe,0x62,0x02,0x9d,0xfe,' +` 0xa6,0x01,0xaa,0xfe,0x17,0x01,0xb2,0xfe,' +` 0xfb,0x00,0xd0,0xff,0x0b,0x01,0xc0,0xff,' +` 0xb7,0x00,0xc0,0xff,0x75,0x00,0xc6,0xff,' +` 0x46,0x00,0xd1,0xff,0x27,0x00,0xde,0xff,' +` 0x13,0x00,0xe8,0xff,0x03,0x00,0xf4,0xff,' +` 0x01,0x00,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x7e,0xff,0x22,0xff,' +` 0x1a,0xff,0x8e,0xfe,0x96,0xfe,0xd3,0xfd,' +` 0xf5,0xfd,0xf2,0xfc,0x3c,0xfd,0xf1,0xfb,' +` 0x77,0xfc,0xd9,0xfa,0xe2,0xfa,0xb8,0xf8,' +` 0xf1,0xf9,0x78,0xf7,0x30,0xf9,0x3d,0xf6,' +` 0x9b,0xf8,0x13,0xf5,0x39,0xf8,0x39,0xf4,' +` 0x08,0xfa,0x7b,0xf4,0xa7,0xfa,0x7b,0xf3,' +` 0xfd,0xfb,0xfe,0xf1,0xa6,0xfe,0xc0,0xee,' +` 0x87,0x05,0x86,0xe0,0x07,0x6a,0x08,0x23,' +` 0x09,0xe8,0x1f,0x05,0x74,0xf2,0x31,0x01,' +` 0x4e,0xf6,0x1b,0x00,0xab,0xf8,0xea,0xff,' +` 0x60,0xfa,0x64,0x00,0x8b,0xfd,0x8d,0x01,' +` 0x72,0xfe,0xa7,0x01,0x33,0xff,0xb2,0x01,' +` 0xc7,0xff,0xab,0x01,0x3a,0x00,0x24,0x01,' +` 0x75,0xff,0xc2,0x00,0xc7,0xff,0xaf,0x00,' +` 0xf6,0xff,0x97,0x00,0x10,0x00,0x79,0x00,' +` 0x19,0x00,0x58,0x00,0x18,0x00,0x3a,0x00,' +` 0x0e,0x00,0x1b,0x00,0x07,0x00,0x0a,0x00,' +` 0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x04,0x00,0x06,0x00,0x10,0x00,' +` 0x0e,0x00,0x21,0x00,0x1c,0x00,0x3f,0x00,' +` 0x28,0x00,0x58,0x00,0x2d,0x00,0x6f,0x00,' +` 0x29,0x00,0x80,0x00,0x15,0x00,0x85,0x00,' +` 0xf0,0xff,0x7b,0x00,0xc4,0xff,0x5f,0x01,' +` 0x61,0x00,0x5d,0x01,0x03,0x00,0x3e,0x01,' +` 0x7d,0xff,0x0d,0x01,0xc8,0xfe,0xdf,0x00,' +` 0x77,0xfd,0xa1,0xfe,0x46,0xfb,0x51,0xfe,' +` 0xc3,0xf9,0x2b,0xfe,0xda,0xf7,0xae,0xfe,' +` 0xc5,0xf4,0xc4,0x01,0x43,0xea,0xe9,0x74,' +` 0x8d,0x0c,0x2b,0xef,0xf2,0xfd,0x83,0xf3,' +` 0x02,0xfb,0xca,0xf4,0xb5,0xf9,0x82,0xf5,' +` 0x10,0xf9,0x35,0xf6,0x5f,0xf8,0x24,0xf5,' +` 0xd6,0xf7,0x35,0xf6,0x64,0xf8,0x4b,0xf7,' +` 0x27,0xf9,0x70,0xf8,0x0e,0xfa,0x95,0xf9,' +` 0x8c,0xfb,0xa9,0xfb,0x9d,0xfc,0x9b,0xfc,' +` 0x6f,0xfd,0x80,0xfd,0x2a,0xfe,0x45,0xfe,' +` 0xc7,0xfe,0xe6,0xfe,0x43,0xff,0x60,0xff,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xfd,0xff,0xfc,0xff,' +` 0xfb,0xff,0xfd,0xff,0xfe,0xff,0xff,0xff,' +` 0x01,0x00,0x04,0x00,0x08,0x00,0x0d,0x00,' +` 0x14,0x00,0x1b,0x00,0x27,0x00,0x30,0x00,' +` 0x44,0x00,0x3a,0x00,0xdc,0xff,0xf2,0xff,' +` 0xf7,0xff,0x12,0x00,0x1b,0x00,0x3d,0x00,' +` 0x47,0x00,0x76,0x00,0x75,0x00,0x0e,0x01,' +` 0xbc,0x01,0xd1,0x01,0x14,0x02,0x3d,0x02,' +` 0x78,0x02,0xa5,0x02,0xdb,0x02,0x08,0x03,' +` 0x37,0x03,0x60,0x03,0x82,0x43,0xac,0x03,' +` 0xca,0x03,0xe6,0x03,0xf8,0x03,0x0a,0x04,' +` 0x0e,0x04,0x18,0x04,0x0a,0x04,0x10,0x04,' +` 0xe4,0x03,0x45,0x04,0x91,0x04,0x43,0x04,' +` 0x21,0x04,0xda,0x03,0xaa,0x03,0x61,0x03,' +` 0x2b,0x03,0xe0,0x02,0xaa,0x02,0x0a,0x02,' +` 0xbb,0x01,0x8c,0x01,0x56,0x01,0x25,0x01,' +` 0xf7,0x00,0xcd,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x91,0x00,0xab,0x00,0xde,0x00,0xfb,0x00,' +` 0x3a,0x01,0x58,0x01,0xa2,0x01,0xbe,0x01,' +` 0x0d,0x02,0x7c,0x02,0x12,0x03,0x13,0x03,' +` 0x97,0x03,0x8c,0x03,0x19,0x04,0xf6,0x03,' +` 0x90,0x04,0x40,0x04,0x34,0x04,0xac,0x03,' +` 0x6c,0x04,0xb5,0x03,0x99,0x04,0x8c,0x03,' +` 0xc4,0x04,0x24,0x03,0x20,0x05,0x03,0x02,' +` 0x7d,0x07,0x38,0x43,0x07,0x00,0xff,0x04,' +` 0xea,0x01,0xc5,0x03,0x03,0x02,0x15,0x03,' +` 0xd3,0x01,0x88,0x02,0x8d,0x01,0x18,0x02,' +` 0x34,0x01,0xe1,0x00,0x4a,0x00,0x96,0x00,' +` 0x1f,0x00,0x5e,0x00,0xfc,0xff,0x34,0x00,' +` 0xdd,0xff,0x37,0x00,0x58,0x00,0x5e,0x00,' +` 0x35,0x00,0x40,0x00,0x20,0x00,0x29,0x00,' +` 0x11,0x00,0x18,0x00,0x08,0x00,0x0d,0x00,' +` 0x02,0x00,0x06,0x00,0x00,0x00,0x02,0x00,' +` 0xfe,0xff,0xff,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x88,0xff,0x7e,0xff,' +` 0x1a,0xff,0x19,0xff,0x83,0xfe,0x95,0xfe,' +` 0xc4,0xfd,0xf5,0xfd,0xe0,0xfc,0x3f,0xfd,' +` 0xdf,0xfb,0x7d,0xfc,0xda,0xfa,0x6f,0xfb,' +` 0x8d,0xf8,0x1a,0xfa,0x50,0xf7,0x60,0xf9,' +` 0x10,0xf6,0xd4,0xf8,0xdc,0xf4,0x78,0xf8,' +` 0x9e,0xf4,0x78,0xfa,0x09,0xf4,0x11,0xfb,' +` 0xe5,0xf2,0x8a,0xfc,0x34,0xf1,0x75,0xff,' +` 0x90,0xed,0xf0,0x06,0x3f,0xde,0xa9,0x63,' +` 0x78,0x2c,0xe0,0xe4,0xb7,0x06,0x1a,0xf1,' +` 0xeb,0x01,0x6d,0xf5,0x7a,0x00,0x06,0xf8,' +` 0x0b,0x00,0xe5,0xf9,0xe4,0xff,0x71,0xfc,' +` 0xb3,0x01,0xd2,0xfd,0xa1,0x01,0xa7,0xfe,' +` 0xa1,0x01,0x4b,0xff,0x9b,0x01,0xb4,0xff,' +` 0xa4,0x00,0x33,0xff,0x9a,0x00,0x8c,0xff,' +` 0x8e,0x00,0xc4,0xff,0x7a,0x00,0xe8,0xff,' +` 0x62,0x00,0xfd,0xff,0x49,0x00,0x05,0x00,' +` 0x2f,0x00,0x07,0x00,0x19,0x00,0x02,0x00,' +` 0x08,0x00,0x01,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x08,0x00,0x02,0x00,' +` 0x19,0x00,0x05,0x00,0x2f,0x00,0x03,0x00,' +` 0x48,0x00,0xf8,0xff,0x61,0x00,0xe1,0xff,' +` 0x78,0x00,0xba,0xff,0x8c,0x00,0x7f,0xff,' +` 0x98,0x00,0x22,0xff,0xa4,0x00,0xa2,0xff,' +` 0x98,0x01,0x32,0xff,0xa0,0x01,0x89,0xfe,' +` 0xa2,0x01,0xad,0xfd,0xbb,0x01,0x24,0xfc,' +` 0xe2,0xff,0xb8,0xf9,0x17,0x00,0xcc,0xf7,' +` 0x94,0x00,0x20,0xf5,0x1f,0x02,0xa6,0xf0,' +` 0x31,0x07,0xd2,0xe3,0xce,0x2f,0x27,0x61,' +` 0xa5,0xdd,0x49,0x07,0x34,0xed,0xa7,0xff,' +` 0xf6,0xf0,0xab,0xfc,0xb8,0xf2,0x29,0xfb,' +` 0xe8,0xf3,0x8c,0xfa,0x7e,0xf4,0x87,0xf8,' +` 0xca,0xf4,0xe1,0xf8,0x03,0xf6,0x6b,0xf9,' +` 0x48,0xf7,0x23,0xfa,0x8b,0xf8,0x8e,0xfb,' +` 0xd3,0xfa,0x87,0xfc,0xdd,0xfb,0x47,0xfd,' +` 0xdf,0xfc,0xfb,0xfd,0xc3,0xfd,0x9a,0xfe,' +` 0x83,0xfe,0x1c,0xff,0x1a,0xff,0x80,0xff,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xff,0xff,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x04,0x00,0x07,0x00,0x0a,0x00,' +` 0x0f,0x00,0x14,0x00,0x1c,0x00,0x22,0x00,' +` 0x2e,0x00,0x36,0x00,0x48,0x00,0x50,0x00,' +` 0x71,0x00,0x27,0x00,0xfb,0xff,0x1c,0x00,' +` 0x22,0x00,0x3e,0x00,0x4f,0x00,0x6e,0x00,' +` 0x84,0x00,0xb1,0x00,0x89,0x01,0xce,0x01,' +` 0xef,0x01,0x26,0x02,0x54,0x02,0x8b,0x02,' +` 0xb9,0x02,0xed,0x02,0x19,0x03,0x48,0x03,' +` 0x70,0x03,0x91,0x43,0xb9,0x03,0xd9,0x03,' +` 0xf2,0x03,0x06,0x04,0x15,0x04,0x1d,0x04,' +` 0x21,0x04,0x1c,0x04,0x13,0x04,0xf8,0x03,' +` 0xee,0x03,0x78,0x04,0x5b,0x04,0x21,0x04,' +` 0xef,0x03,0xad,0x03,0x75,0x03,0x2c,0x03,' +` 0xf8,0x02,0x88,0x02,0xf6,0x01,0xcc,0x01,' +` 0x91,0x01,0x62,0x01,0x2d,0x01,0x02,0x01,' +` 0xd5,0x00,0xaf,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x59,0x00,0x73,0x00,0x95,0x00,0xb6,0x00,' +` 0xe0,0x00,0x08,0x01,0x3b,0x01,0x67,0x01,' +` 0x9f,0x01,0xcc,0x01,0x0b,0x02,0x39,0x02,' +` 0xea,0x02,0x36,0x03,0x7b,0x03,0xab,0x03,' +` 0xf5,0x03,0x15,0x04,0x67,0x04,0xef,0x03,' +` 0xd4,0x03,0xf2,0x03,0x10,0x04,0x10,0x04,' +` 0x30,0x04,0x0f,0x04,0x2e,0x04,0xeb,0x03,' +` 0x20,0x04,0x9d,0x03,0x45,0x04,0x97,0x43,' +` 0xf6,0x02,0x95,0x03,0xfd,0x02,0x1b,0x03,' +` 0xb3,0x02,0xaf,0x02,0x5b,0x02,0x4b,0x02,' +` 0x0c,0x02,0xf0,0x01,0xc4,0x01,0x6f,0x01,' +` 0x9b,0x00,0x9e,0x00,0x6d,0x00,0x67,0x00,' +` 0x44,0x00,0x3b,0x00,0x30,0x00,0x9e,0x00,' +` 0x84,0x00,0x78,0x00,0x5e,0x00,0x54,0x00,' +` 0x41,0x00,0x3a,0x00,0x2c,0x00,0x27,0x00,' +` 0x1c,0x00,0x18,0x00,0x11,0x00,0x0e,0x00,' +` 0x09,0x00,0x07,0x00,0x04,0x00,0x03,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xd9,0xff,0xaa,0xff,' +` 0xa1,0xff,0x4b,0xff,0x4c,0xff,0xc3,0xfe,' +` 0xda,0xfe,0x13,0xfe,0x4d,0xfe,0x3d,0xfd,' +` 0xac,0xfd,0x48,0xfc,0x07,0xfd,0x3a,0xfb,' +` 0x6c,0xfc,0xd0,0xf9,0xa2,0xfa,0xf8,0xf7,' +` 0x03,0xfa,0xa1,0xf6,0x86,0xf9,0x46,0xf5,' +` 0x81,0xf9,0xa4,0xf5,0xdd,0xfa,0x6e,0xf4,' +` 0x87,0xfb,0x06,0xf3,0xed,0xfc,0x21,0xf1,' +` 0xce,0xff,0x64,0xed,0xdb,0x06,0x09,0xe0,' +` 0x93,0x3a,0x6f,0x58,0x7c,0xdd,0xd9,0x09,' +` 0x9a,0xee,0x27,0x03,0xc3,0xf3,0x19,0x01,' +` 0xa2,0xf6,0x4c,0x00,0x90,0xf8,0x07,0x00,' +` 0x06,0xfa,0x13,0x01,0x08,0xfd,0x6a,0x01,' +` 0xd7,0xfd,0x6a,0x01,0x7f,0xfe,0x6f,0x01,' +` 0x88,0xfe,0x2a,0x00,0xa1,0xfe,0x4b,0x00,' +` 0x0f,0xff,0x56,0x00,0x61,0xff,0x50,0x00,' +` 0x9b,0xff,0x43,0x00,0xc4,0xff,0x34,0x00,' +` 0xe0,0xff,0x25,0x00,0xf1,0xff,0x17,0x00,' +` 0xfa,0xff,0x0b,0x00,0xfe,0xff,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0xfe,0xff,0x0a,0x00,0xf9,0xff,0x16,0x00,' +` 0xee,0xff,0x23,0x00,0xda,0xff,0x31,0x00,' +` 0xbc,0xff,0x3f,0x00,0x90,0xff,0x4a,0x00,' +` 0x52,0xff,0x4f,0x00,0xfb,0xfe,0x43,0x00,' +` 0x88,0xfe,0x21,0x00,0x59,0xfe,0x64,0x01,' +` 0x5e,0xfe,0x5f,0x01,0xb0,0xfd,0x5f,0x01,' +` 0xdf,0xfc,0xed,0x00,0xcb,0xf9,0x09,0x00,' +` 0x54,0xf8,0x53,0x00,0x60,0xf6,0x2a,0x01,' +` 0x78,0xf3,0x43,0x03,0x49,0xee,0xf0,0x09,' +` 0x9a,0xdd,0x5f,0x4e,0x98,0x45,0xf3,0xdd,' +` 0xc3,0x07,0xbb,0xec,0x30,0x00,0xc2,0xf0,' +` 0x26,0xfd,0xc9,0xf2,0xaf,0xfb,0x45,0xf4,' +` 0xf9,0xfa,0x8e,0xf5,0xb0,0xf9,0x2b,0xf5,' +` 0x9e,0xf9,0x8f,0xf6,0x17,0xfa,0xec,0xf7,' +` 0xb6,0xfa,0xdc,0xf9,0x76,0xfc,0x38,0xfb,' +` 0x11,0xfd,0x47,0xfc,0xb4,0xfd,0x3d,0xfd,' +` 0x54,0xfe,0x14,0xfe,0xdf,0xfe,0xc4,0xfe,' +` 0x4f,0xff,0x4b,0xff,0xa3,0xff,0xaa,0xff,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x05,0x00,0x07,0x00,0x0a,0x00,0x0f,0x00,' +` 0x13,0x00,0x1a,0x00,0x20,0x00,0x29,0x00,' +` 0x31,0x00,0x3e,0x00,0x47,0x00,0x59,0x00,' +` 0x66,0x00,0x7d,0x00,0x8b,0x00,0xab,0x00,' +` 0x4b,0x00,0x3b,0x00,0x55,0x00,0x69,0x00,' +` 0x7f,0x00,0x9f,0x00,0xae,0x00,0x70,0x01,' +` 0xd9,0x01,0xed,0x01,0x24,0x02,0x44,0x02,' +` 0x76,0x02,0xa1,0x02,0xd5,0x02,0x00,0x03,' +` 0x2f,0x03,0x57,0x03,0x80,0x03,0x9c,0x43,' +` 0xc3,0x03,0xdf,0x03,0xf6,0x03,0x0a,0x04,' +` 0x16,0x04,0x21,0x04,0x1f,0x04,0x1a,0x04,' +` 0x03,0x04,0xf7,0x03,0xcc,0x03,0xdb,0x03,' +` 0x53,0x04,0x1a,0x04,0xe8,0x03,0xad,0x03,' +` 0x70,0x03,0x37,0x03,0xe1,0x02,0x38,0x02,' +` 0x04,0x02,0xcb,0x01,0x99,0x01,0x65,0x01,' +` 0x36,0x01,0x06,0x01,0xdc,0x00,0xb5,0x00,' +` 0x92,0x00,0x72,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x4f,0x00,0x95,0x00,0x98,0x00,0x07,0x01,' +` 0xfc,0x00,0x9c,0x01,0x79,0x01,0x53,0x02,' +` 0x09,0x02,0x26,0x03,0xa5,0x02,0x12,0x04,' +` 0x43,0x03,0x10,0x05,0xce,0x03,0xaa,0x06,' +` 0xb5,0x05,0x43,0x08,0x35,0x06,0x88,0x09,' +` 0x0a,0x06,0xdb,0x08,0x4f,0x05,0xf3,0x09,' +` 0xfe,0x04,0x13,0x0b,0x39,0x04,0x7f,0x0c,' +` 0x9f,0x02,0xd1,0x0e,0xd2,0xfe,0xe9,0x14,' +` 0xbe,0xef,0xbe,0x78,0x67,0x30,0x54,0xf5,' +` 0x81,0x11,0x2f,0xfe,0x15,0x0c,0x79,0x00,' +` 0x7f,0x09,0x58,0x01,0xc8,0x07,0xa1,0x01,' +` 0x73,0x06,0xa5,0x01,0x4c,0x05,0x36,0x00,' +` 0xf0,0x02,0x02,0x00,0x4f,0x02,0xe8,0xff,' +` 0x91,0x02,0xfd,0x00,0x2c,0x02,0xbf,0x00,' +` 0xab,0x01,0x90,0x00,0x3e,0x01,0x68,0x00,' +` 0xe4,0x00,0x4a,0x00,0x9e,0x00,0x32,0x00,' +` 0x65,0x00,0x1f,0x00,0x3b,0x00,0x11,0x00,' +` 0x1d,0x00,0x07,0x00,0x0a,0x00,0x02,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xe6,0xff,0xd7,0xff,' +` 0xb2,0xff,0x9d,0xff,0x5d,0xff,0x46,0xff,' +` 0xe5,0xfe,0xd1,0xfe,0x4b,0xfe,0x40,0xfe,' +` 0x93,0xfd,0x9f,0xfd,0xc5,0xfc,0xf1,0xfc,' +` 0xe5,0xfb,0x3a,0xfc,0xfd,0xfa,0x6a,0xfb,' +` 0xe6,0xf8,0xc2,0xf9,0xce,0xf7,0x11,0xf9,' +` 0xd4,0xf6,0xe8,0xf9,0x5e,0xf7,0xdf,0xf9,' +` 0x8e,0xf6,0x02,0xfa,0xbd,0xf5,0x8b,0xfa,' +` 0xbb,0xf4,0xca,0xfb,0x12,0xf3,0xf7,0xfe,' +` 0xd0,0xed,0xd7,0x0f,0x7a,0x73,0x46,0xe8,' +` 0x6f,0x02,0xa6,0xf3,0xae,0xfe,0xce,0xf6,' +` 0xbd,0xfd,0x8e,0xf8,0x86,0xfd,0xdd,0xf9,' +` 0x9c,0xfd,0xf9,0xfa,0xc4,0xfd,0x86,0xfc,' +` 0xd3,0xff,0xf3,0xfd,0xdf,0xff,0x95,0xfe,' +` 0xab,0xff,0xc3,0xfd,0x2a,0xff,0x53,0xfe,' +` 0x5f,0xff,0xc5,0xfe,0x91,0xff,0x22,0xff,' +` 0xb9,0xff,0x69,0xff,0xd3,0xff,0x9c,0xff,' +` 0xe5,0xff,0xc2,0xff,0xf1,0xff,0xdd,0xff,' +` 0xf9,0xff,0xf0,0xff,0xfd,0xff,0xfb,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0x00,0x00,' +` 0xf1,0xff,0xff,0xff,0xdc,0xff,0xfe,0xff,' +` 0xbb,0xff,0xfa,0xff,0x8d,0xff,0xf3,0xff,' +` 0x4e,0xff,0xe9,0xff,0xf9,0xfe,0xd4,0xff,' +` 0x8a,0xfe,0xba,0xff,0x00,0xfe,0xa1,0xff,' +` 0x52,0xfd,0xcf,0xff,0xe8,0xfd,0x91,0x00,' +` 0x1d,0xfd,0xb6,0x00,0xba,0xfb,0x04,0xff,' +` 0xaa,0xf9,0x32,0xff,0x27,0xf8,0x95,0xff,' +` 0x41,0xf6,0x83,0x00,0x8e,0xf3,0xb9,0x02,' +` 0x9a,0xee,0x31,0x09,0xee,0xde,0x26,0x44,' +` 0xf6,0x4f,0xb9,0xdc,0x70,0x08,0x71,0xec,' +` 0xa3,0x00,0xa3,0xf0,0xa8,0xfd,0xc8,0xf2,' +` 0x30,0xfc,0x3c,0xf4,0x77,0xfb,0x6c,0xf5,' +` 0x41,0xfb,0xa8,0xf5,0xab,0xf9,0x76,0xf6,' +` 0x30,0xfa,0xa9,0xf7,0x8c,0xfb,0x17,0xfa,' +` 0x5d,0xfc,0x1b,0xfb,0xfb,0xfc,0x19,0xfc,' +` 0x98,0xfd,0x05,0xfd,0x2d,0xfe,0xd8,0xfd,' +` 0xb8,0xfe,0x8d,0xfe,0x2d,0xff,0x1d,0xff,' +` 0x87,0xff,0x88,0xff,0xc7,0xff,0xce,0xff,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x00,' +` 0x07,0x00,0x0b,0x00,0x10,0x00,0x16,0x00,' +` 0x1d,0x00,0x26,0x00,0x2f,0x00,0x3b,0x00,' +` 0x46,0x00,0x55,0x00,0x62,0x00,0x76,0x00,' +` 0x85,0x00,0x9d,0x00,0xae,0x00,0xce,0x00,' +` 0xdd,0x00,0x0a,0x01,0xac,0x00,0x92,0x00,' +` 0xb4,0x00,0xc9,0x00,0xe0,0x00,0x98,0x01,' +` 0xf6,0x01,0x07,0x02,0x3b,0x02,0x57,0x02,' +` 0x85,0x02,0xa3,0x02,0xcd,0x02,0xec,0x02,' +` 0x18,0x03,0x3c,0x03,0x63,0x03,0x83,0x03,' +` 0x9c,0x43,0xbc,0x03,0xd5,0x03,0xe7,0x03,' +` 0xf6,0x03,0xff,0x03,0xfc,0x03,0xf5,0x03,' +` 0xe7,0x03,0xd8,0x03,0xbe,0x03,0xa9,0x03,' +` 0x80,0x03,0x7b,0x03,0xef,0x03,0xbf,0x03,' +` 0x85,0x03,0x54,0x03,0xfb,0x02,0x51,0x02,' +` 0x25,0x02,0xed,0x01,0xbf,0x01,0x8a,0x01,' +` 0x5c,0x01,0x2c,0x01,0x03,0x01,0xd9,0x00,' +` 0xb4,0x00,0x90,0x00,0x72,0x00,0x57,0x00,' +` 0x41,0x00,0x2e,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x1d,0x00,0x45,0x00,0x46,0x00,' +` 0x91,0x00,0x85,0x00,0xfd,0x00,0xdb,0x00,' +` 0x89,0x01,0x43,0x01,0x31,0x02,0xb7,0x01,' +` 0xf2,0x02,0x34,0x02,0xc8,0x03,0xb4,0x02,' +` 0xae,0x04,0x32,0x03,0x99,0x05,0xdc,0x03,' +` 0xf4,0x07,0x45,0x05,0x85,0x08,0xd0,0x03,' +` 0xf0,0x08,0xcd,0x03,0x10,0x0a,0x65,0x03,' +` 0x64,0x0b,0x75,0x02,0x2c,0x0d,0x8e,0x00,' +` 0x27,0x10,0x3d,0xfc,0x99,0x17,0xaf,0xeb,' +` 0xcb,0x66,0x21,0x49,0x69,0xee,0x89,0x15,' +` 0xd2,0xfb,0x77,0x0e,0x6f,0xff,0x52,0x0b,' +` 0xed,0x00,0x53,0x09,0x99,0x01,0xcf,0x07,' +` 0xe1,0x01,0x8b,0x06,0xff,0x01,0xbf,0x04,' +` 0x5a,0x00,0x64,0x03,0x5a,0x01,0xe3,0x03,' +` 0x5b,0x01,0x19,0x03,0x27,0x01,0x6d,0x02,' +` 0xef,0x00,0xd7,0x01,0xb8,0x00,0x58,0x01,' +` 0x86,0x00,0xef,0x00,0x5d,0x00,0x9c,0x00,' +` 0x3c,0x00,0x5c,0x00,0x21,0x00,0x2e,0x00,' +` 0x0e,0x00,0x10,0x00,0x03,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xf8,0xff,' +` 0xe8,0xff,0xdd,0xff,0xb8,0xff,0xac,0xff,' +` 0x6a,0xff,0x62,0xff,0xfe,0xfe,0x02,0xff,' +` 0x75,0xfe,0x8f,0xfe,0xd2,0xfd,0x0d,0xfe,' +` 0x17,0xfd,0x80,0xfd,0x48,0xfc,0xf0,0xfc,' +` 0x6a,0xfb,0x67,0xfc,0x76,0xfa,0xd1,0xfa,' +` 0x45,0xf8,0x7f,0xfa,0xc8,0xf8,0x32,0xfb,' +` 0xd8,0xf7,0x2b,0xfb,0xe5,0xf6,0x69,0xfb,' +` 0xd3,0xf5,0x17,0xfc,0x68,0xf4,0xa2,0xfd,' +` 0xe7,0xf1,0x9a,0x01,0x46,0xea,0xb3,0x19,' +` 0x11,0x6f,0xe1,0xe3,0xf9,0x04,0x88,0xf1,' +` 0xc2,0xff,0x14,0xf5,0x25,0xfe,0xfb,0xf6,' +` 0x8c,0xfd,0x54,0xf8,0x67,0xfd,0x6b,0xf9,' +` 0x82,0xfd,0x4e,0xfa,0x22,0xfe,0xca,0xfc,' +` 0x3b,0xff,0xa7,0xfc,0x01,0xfe,0xde,0xfc,' +` 0x60,0xfe,0x75,0xfd,0xb0,0xfe,0x00,0xfe,' +` 0xf9,0xfe,0x7b,0xfe,0x3a,0xff,0xe5,0xfe,' +` 0x74,0xff,0x3e,0xff,0xa2,0xff,0x82,0xff,' +` 0xc6,0xff,0xb7,0xff,0xe0,0xff,0xdc,0xff,' +` 0xf3,0xff,0xf4,0xff,0xfd,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfb,0xff,0xf8,0xff,0xe8,0xff,0xe9,0xff,' +` 0xc7,0xff,0xd1,0xff,0x97,0xff,0xb0,0xff,' +` 0x56,0xff,0x85,0xff,0x01,0xff,0x4e,0xff,' +` 0x98,0xfe,0x0e,0xff,0x1e,0xfe,0xc9,0xfe,' +` 0x91,0xfd,0x7e,0xfe,0xf1,0xfc,0x30,0xfe,' +` 0x43,0xfc,0xe7,0xfe,0xf7,0xfc,0x7b,0xfe,' +` 0x7b,0xfa,0x83,0xfd,0x96,0xf9,0x63,0xfd,' +` 0x7f,0xf8,0x7f,0xfd,0x2d,0xf7,0xfe,0xfd,' +` 0x66,0xf5,0x53,0xff,0x5f,0xf2,0x2f,0x03,' +` 0xa4,0xe9,0xc5,0x1c,0x64,0x6d,0x85,0xe2,' +` 0x9b,0x04,0x27,0xf0,0xad,0xfe,0x80,0xf3,' +` 0x9a,0xfc,0x31,0xf5,0xac,0xfb,0x61,0xf6,' +` 0x47,0xfb,0x64,0xf7,0x31,0xfb,0x61,0xf8,' +` 0x13,0xfb,0xda,0xf7,0x76,0xfa,0xc8,0xf9,' +` 0x51,0xfc,0xf9,0xfa,0xc7,0xfc,0xe2,0xfb,' +` 0x51,0xfd,0xbb,0xfc,0xdd,0xfd,0x81,0xfd,' +` 0x61,0xfe,0x2f,0xfe,0xd8,0xfe,0xc3,0xfe,' +` 0x3e,0xff,0x3d,0xff,0x90,0xff,0x98,0xff,' +` 0xcb,0xff,0xd5,0xff,0xee,0xff,0xf6,0xff,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x06,0x00,0x0b,0x00,0x12,0x00,0x1a,0x00,' +` 0x24,0x00,0x30,0x00,0x3c,0x00,0x4b,0x00,' +` 0x5b,0x00,0x6e,0x00,0x82,0x00,0x99,0x00,' +` 0xaf,0x00,0xcb,0x00,0xe4,0x00,0x04,0x01,' +` 0x1c,0x01,0x43,0x01,0x57,0x01,0x8d,0x01,' +` 0x52,0x01,0x04,0x01,0x47,0x01,0xf6,0x01,' +` 0x30,0x02,0x47,0x02,0x72,0x02,0x8d,0x02,' +` 0xb4,0x02,0xcf,0x02,0xf2,0x02,0x0a,0x03,' +` 0x28,0x03,0x3c,0x03,0x55,0x03,0x68,0x03,' +` 0x83,0x03,0x8d,0x43,0xa7,0x03,0xb4,0x03,' +` 0xbd,0x03,0xb9,0x03,0xb6,0x03,0xab,0x03,' +` 0xa0,0x03,0x8e,0x03,0x7b,0x03,0x62,0x03,' +` 0x47,0x03,0x27,0x03,0x07,0x03,0xe0,0x02,' +` 0x41,0x03,0x46,0x03,0xc2,0x02,0x31,0x02,' +` 0x12,0x02,0xde,0x01,0xb7,0x01,0x87,0x01,' +` 0x5f,0x01,0x34,0x01,0x0e,0x01,0xe7,0x00,' +` 0xc5,0x00,0xa3,0x00,0x85,0x00,0x69,0x00,' +` 0x51,0x00,0x3c,0x00,0x2b,0x00,0x1c,0x00,' +` 0x12,0x00,0x09,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x09,0x00,' +` 0x0e,0x00,0x1a,0x00,0x22,0x00,0x35,0x00,' +` 0x3f,0x00,0x5a,0x00,0x65,0x00,0x8a,0x00,' +` 0x94,0x00,0xc4,0x00,0xcb,0x00,0x07,0x01,' +` 0x09,0x01,0x51,0x01,0x4b,0x01,0xa1,0x01,' +` 0x8f,0x01,0xf5,0x01,0xd3,0x01,0x49,0x02,' +` 0x2c,0x02,0xa4,0x02,0x4c,0x02,0xf7,0x02,' +` 0x7e,0x02,0x49,0x03,0xa2,0x02,0x9b,0x03,' +` 0xb2,0x02,0xf2,0x03,0xa3,0x02,0x5d,0x04,' +` 0x54,0x02,0x1b,0x05,0x23,0x01,0x98,0x08,' +` 0xf6,0x42,0x34,0xff,0xbd,0x05,0xfb,0x01,' +` 0x88,0x04,0x7a,0x02,0x01,0x04,0x98,0x02,' +` 0x9f,0x03,0x8e,0x02,0x48,0x03,0x6d,0x02,' +` 0xf3,0x02,0x3d,0x02,0x9e,0x02,0xff,0x01,' +` 0x30,0x02,0xcc,0x01,0xed,0x01,0x87,0x01,' +` 0x9b,0x01,0x44,0x01,0x4c,0x01,0x04,0x01,' +` 0x03,0x01,0xc7,0x00,0xc2,0x00,0x92,0x00,' +` 0x88,0x00,0x64,0x00,0x59,0x00,0x3e,0x00,' +` 0x34,0x00,0x22,0x00,0x19,0x00,0x0e,0x00,' +` 0x09,0x00,0x03,0x00,0x01,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf9,0xff,0xf0,0xff,0xe2,0xff,0xd0,0xff,' +` 0xb8,0xff,0x9c,0xff,0x7b,0xff,0x55,0xff,' +` 0x2a,0xff,0xfa,0xfe,0xc5,0xfe,0x8d,0xfe,' +` 0x50,0xfe,0x11,0xfe,0xcc,0xfd,0x87,0xfd,' +` 0x3c,0xfd,0xf4,0xfc,0xa5,0xfc,0x5d,0xfc,' +` 0x0a,0xfc,0xc9,0xfb,0x47,0xfb,0x24,0xfb,' +` 0xec,0xfa,0xa0,0xfa,0x65,0xfa,0x24,0xfa,' +` 0xee,0xf9,0xb7,0xf9,0x8a,0xf9,0x5e,0xf9,' +` 0x3b,0xf9,0x1c,0xf9,0x04,0xf9,0xf1,0xf8,' +` 0xe7,0xf8,0xe1,0xf8,0xd8,0x78,0xef,0xf8,' +` 0xfc,0xf8,0x10,0xf9,0x29,0xf9,0x4a,0xf9,' +` 0x6e,0xf9,0x9a,0xf9,0xc9,0xf9,0x00,0xfa,' +` 0x37,0xfa,0x77,0xfa,0xb4,0xfa,0xfd,0xfa,' +` 0x3c,0xfb,0x93,0xfb,0x00,0xfc,0x17,0xfc,' +` 0x6c,0xfc,0xb2,0xfc,0x00,0xfd,0x47,0xfd,' +` 0x91,0xfd,0xd4,0xfd,0x18,0xfe,0x56,0xfe,' +` 0x93,0xfe,0xca,0xfe,0xfe,0xfe,0x2c,0xff,' +` 0x57,0xff,0x7c,0xff,0x9d,0xff,0xb9,0xff,' +` 0xd0,0xff,0xe2,0xff,0xf0,0xff,0xf9,0xff,' +` 0xfe,0xff,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf9,0xff,0xf0,0xff,' +` 0xe2,0xff,0xd0,0xff,0xb8,0xff,0x9c,0xff,' +` 0x7b,0xff,0x55,0xff,0x2a,0xff,0xfa,0xfe,' +` 0xc5,0xfe,0x8d,0xfe,0x50,0xfe,0x11,0xfe,' +` 0xcc,0xfd,0x87,0xfd,0x3c,0xfd,0xf4,0xfc,' +` 0xa5,0xfc,0x5d,0xfc,0x0a,0xfc,0xc9,0xfb,' +` 0x47,0xfb,0x24,0xfb,0xec,0xfa,0xa0,0xfa,' +` 0x65,0xfa,0x24,0xfa,0xee,0xf9,0xb7,0xf9,' +` 0x8a,0xf9,0x5e,0xf9,0x3b,0xf9,0x1c,0xf9,' +` 0x04,0xf9,0xf1,0xf8,0xe7,0xf8,0xe1,0xf8,' +` 0xd8,0x78,0xef,0xf8,0xfc,0xf8,0x10,0xf9,' +` 0x29,0xf9,0x4a,0xf9,0x6e,0xf9,0x9a,0xf9,' +` 0xc9,0xf9,0x00,0xfa,0x37,0xfa,0x77,0xfa,' +` 0xb4,0xfa,0xfd,0xfa,0x3c,0xfb,0x93,0xfb,' +` 0x00,0xfc,0x17,0xfc,0x6c,0xfc,0xb2,0xfc,' +` 0x00,0xfd,0x47,0xfd,0x91,0xfd,0xd4,0xfd,' +` 0x18,0xfe,0x56,0xfe,0x93,0xfe,0xca,0xfe,' +` 0xfe,0xfe,0x2c,0xff,0x57,0xff,0x7c,0xff,' +` 0x9d,0xff,0xb9,0xff,0xd0,0xff,0xe2,0xff,' +` 0xf0,0xff,0xf9,0xff,0xfe,0xff,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x09,0x00,0x0e,0x00,0x1a,0x00,' +` 0x22,0x00,0x35,0x00,0x3f,0x00,0x5a,0x00,' +` 0x65,0x00,0x8a,0x00,0x94,0x00,0xc4,0x00,' +` 0xcb,0x00,0x07,0x01,0x09,0x01,0x51,0x01,' +` 0x4b,0x01,0xa1,0x01,0x8f,0x01,0xf5,0x01,' +` 0xd3,0x01,0x49,0x02,0x2c,0x02,0xa4,0x02,' +` 0x4c,0x02,0xf7,0x02,0x7e,0x02,0x49,0x03,' +` 0xa2,0x02,0x9b,0x03,0xb2,0x02,0xf2,0x03,' +` 0xa3,0x02,0x5d,0x04,0x54,0x02,0x1b,0x05,' +` 0x23,0x01,0x98,0x08,0xf6,0x42,0x34,0xff,' +` 0xbd,0x05,0xfb,0x01,0x88,0x04,0x7a,0x02,' +` 0x01,0x04,0x98,0x02,0x9f,0x03,0x8e,0x02,' +` 0x48,0x03,0x6d,0x02,0xf3,0x02,0x3d,0x02,' +` 0x9e,0x02,0xff,0x01,0x30,0x02,0xcc,0x01,' +` 0xed,0x01,0x87,0x01,0x9b,0x01,0x44,0x01,' +` 0x4c,0x01,0x04,0x01,0x03,0x01,0xc7,0x00,' +` 0xc2,0x00,0x92,0x00,0x88,0x00,0x64,0x00,' +` 0x59,0x00,0x3e,0x00,0x34,0x00,0x22,0x00,' +` 0x19,0x00,0x0e,0x00,0x09,0x00,0x03,0x00,' +` 0x01,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x06,0x00,0x0b,0x00,' +` 0x12,0x00,0x1a,0x00,0x24,0x00,0x30,0x00,' +` 0x3c,0x00,0x4b,0x00,0x5b,0x00,0x6e,0x00,' +` 0x82,0x00,0x99,0x00,0xaf,0x00,0xcb,0x00,' +` 0xe4,0x00,0x04,0x01,0x1c,0x01,0x43,0x01,' +` 0x57,0x01,0x8d,0x01,0x52,0x01,0x04,0x01,' +` 0x47,0x01,0xf6,0x01,0x30,0x02,0x47,0x02,' +` 0x72,0x02,0x8d,0x02,0xb4,0x02,0xcf,0x02,' +` 0xf2,0x02,0x0a,0x03,0x28,0x03,0x3c,0x03,' +` 0x55,0x03,0x68,0x03,0x83,0x03,0x8d,0x43,' +` 0xa7,0x03,0xb4,0x03,0xbd,0x03,0xb9,0x03,' +` 0xb6,0x03,0xab,0x03,0xa0,0x03,0x8e,0x03,' +` 0x7b,0x03,0x62,0x03,0x47,0x03,0x27,0x03,' +` 0x07,0x03,0xe0,0x02,0x41,0x03,0x46,0x03,' +` 0xc2,0x02,0x31,0x02,0x12,0x02,0xde,0x01,' +` 0xb7,0x01,0x87,0x01,0x5f,0x01,0x34,0x01,' +` 0x0e,0x01,0xe7,0x00,0xc5,0x00,0xa3,0x00,' +` 0x85,0x00,0x69,0x00,0x51,0x00,0x3c,0x00,' +` 0x2b,0x00,0x1c,0x00,0x12,0x00,0x09,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfb,0xff,0xf8,0xff,' +` 0xe8,0xff,0xe9,0xff,0xc7,0xff,0xd1,0xff,' +` 0x97,0xff,0xb0,0xff,0x56,0xff,0x85,0xff,' +` 0x01,0xff,0x4e,0xff,0x98,0xfe,0x0e,0xff,' +` 0x1e,0xfe,0xc9,0xfe,0x91,0xfd,0x7e,0xfe,' +` 0xf1,0xfc,0x30,0xfe,0x43,0xfc,0xe7,0xfe,' +` 0xf7,0xfc,0x7b,0xfe,0x7b,0xfa,0x83,0xfd,' +` 0x96,0xf9,0x63,0xfd,0x7f,0xf8,0x7f,0xfd,' +` 0x2d,0xf7,0xfe,0xfd,0x66,0xf5,0x53,0xff,' +` 0x5f,0xf2,0x2f,0x03,0xa4,0xe9,0xc5,0x1c,' +` 0x64,0x6d,0x85,0xe2,0x9b,0x04,0x27,0xf0,' +` 0xad,0xfe,0x80,0xf3,0x9a,0xfc,0x31,0xf5,' +` 0xac,0xfb,0x61,0xf6,0x47,0xfb,0x64,0xf7,' +` 0x31,0xfb,0x61,0xf8,0x13,0xfb,0xda,0xf7,' +` 0x76,0xfa,0xc8,0xf9,0x51,0xfc,0xf9,0xfa,' +` 0xc7,0xfc,0xe2,0xfb,0x51,0xfd,0xbb,0xfc,' +` 0xdd,0xfd,0x81,0xfd,0x61,0xfe,0x2f,0xfe,' +` 0xd8,0xfe,0xc3,0xfe,0x3e,0xff,0x3d,0xff,' +` 0x90,0xff,0x98,0xff,0xcb,0xff,0xd5,0xff,' +` 0xee,0xff,0xf6,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xf8,0xff,0xe8,0xff,0xdd,0xff,' +` 0xb8,0xff,0xac,0xff,0x6a,0xff,0x62,0xff,' +` 0xfe,0xfe,0x02,0xff,0x75,0xfe,0x8f,0xfe,' +` 0xd2,0xfd,0x0d,0xfe,0x17,0xfd,0x80,0xfd,' +` 0x48,0xfc,0xf0,0xfc,0x6a,0xfb,0x67,0xfc,' +` 0x76,0xfa,0xd1,0xfa,0x45,0xf8,0x7f,0xfa,' +` 0xc8,0xf8,0x32,0xfb,0xd8,0xf7,0x2b,0xfb,' +` 0xe5,0xf6,0x69,0xfb,0xd3,0xf5,0x17,0xfc,' +` 0x68,0xf4,0xa2,0xfd,0xe7,0xf1,0x9a,0x01,' +` 0x46,0xea,0xb3,0x19,0x11,0x6f,0xe1,0xe3,' +` 0xf9,0x04,0x88,0xf1,0xc2,0xff,0x14,0xf5,' +` 0x25,0xfe,0xfb,0xf6,0x8c,0xfd,0x54,0xf8,' +` 0x67,0xfd,0x6b,0xf9,0x82,0xfd,0x4e,0xfa,' +` 0x22,0xfe,0xca,0xfc,0x3b,0xff,0xa7,0xfc,' +` 0x01,0xfe,0xde,0xfc,0x60,0xfe,0x75,0xfd,' +` 0xb0,0xfe,0x00,0xfe,0xf9,0xfe,0x7b,0xfe,' +` 0x3a,0xff,0xe5,0xfe,0x74,0xff,0x3e,0xff,' +` 0xa2,0xff,0x82,0xff,0xc6,0xff,0xb7,0xff,' +` 0xe0,0xff,0xdc,0xff,0xf3,0xff,0xf4,0xff,' +` 0xfd,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x17,0x00,0x1d,0x00,' +` 0x45,0x00,0x46,0x00,0x91,0x00,0x85,0x00,' +` 0xfd,0x00,0xdb,0x00,0x89,0x01,0x43,0x01,' +` 0x31,0x02,0xb7,0x01,0xf2,0x02,0x34,0x02,' +` 0xc8,0x03,0xb4,0x02,0xae,0x04,0x32,0x03,' +` 0x99,0x05,0xdc,0x03,0xf4,0x07,0x45,0x05,' +` 0x85,0x08,0xd0,0x03,0xf0,0x08,0xcd,0x03,' +` 0x10,0x0a,0x65,0x03,0x64,0x0b,0x75,0x02,' +` 0x2c,0x0d,0x8e,0x00,0x27,0x10,0x3d,0xfc,' +` 0x99,0x17,0xaf,0xeb,0xcb,0x66,0x21,0x49,' +` 0x69,0xee,0x89,0x15,0xd2,0xfb,0x77,0x0e,' +` 0x6f,0xff,0x52,0x0b,0xed,0x00,0x53,0x09,' +` 0x99,0x01,0xcf,0x07,0xe1,0x01,0x8b,0x06,' +` 0xff,0x01,0xbf,0x04,0x5a,0x00,0x64,0x03,' +` 0x5a,0x01,0xe3,0x03,0x5b,0x01,0x19,0x03,' +` 0x27,0x01,0x6d,0x02,0xef,0x00,0xd7,0x01,' +` 0xb8,0x00,0x58,0x01,0x86,0x00,0xef,0x00,' +` 0x5d,0x00,0x9c,0x00,0x3c,0x00,0x5c,0x00,' +` 0x21,0x00,0x2e,0x00,0x0e,0x00,0x10,0x00,' +` 0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x04,0x00,0x07,0x00,0x0b,0x00,' +` 0x10,0x00,0x16,0x00,0x1d,0x00,0x26,0x00,' +` 0x2f,0x00,0x3b,0x00,0x46,0x00,0x55,0x00,' +` 0x62,0x00,0x76,0x00,0x85,0x00,0x9d,0x00,' +` 0xae,0x00,0xce,0x00,0xdd,0x00,0x0a,0x01,' +` 0xac,0x00,0x92,0x00,0xb4,0x00,0xc9,0x00,' +` 0xe0,0x00,0x98,0x01,0xf6,0x01,0x07,0x02,' +` 0x3b,0x02,0x57,0x02,0x85,0x02,0xa3,0x02,' +` 0xcd,0x02,0xec,0x02,0x18,0x03,0x3c,0x03,' +` 0x63,0x03,0x83,0x03,0x9c,0x43,0xbc,0x03,' +` 0xd5,0x03,0xe7,0x03,0xf6,0x03,0xff,0x03,' +` 0xfc,0x03,0xf5,0x03,0xe7,0x03,0xd8,0x03,' +` 0xbe,0x03,0xa9,0x03,0x80,0x03,0x7b,0x03,' +` 0xef,0x03,0xbf,0x03,0x85,0x03,0x54,0x03,' +` 0xfb,0x02,0x51,0x02,0x25,0x02,0xed,0x01,' +` 0xbf,0x01,0x8a,0x01,0x5c,0x01,0x2c,0x01,' +` 0x03,0x01,0xd9,0x00,0xb4,0x00,0x90,0x00,' +` 0x72,0x00,0x57,0x00,0x41,0x00,0x2e,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0x00,0x00,0xf1,0xff,0xff,0xff,' +` 0xdc,0xff,0xfe,0xff,0xbb,0xff,0xfa,0xff,' +` 0x8d,0xff,0xf3,0xff,0x4e,0xff,0xe9,0xff,' +` 0xf9,0xfe,0xd4,0xff,0x8a,0xfe,0xba,0xff,' +` 0x00,0xfe,0xa1,0xff,0x52,0xfd,0xcf,0xff,' +` 0xe8,0xfd,0x91,0x00,0x1d,0xfd,0xb6,0x00,' +` 0xba,0xfb,0x04,0xff,0xaa,0xf9,0x32,0xff,' +` 0x27,0xf8,0x95,0xff,0x41,0xf6,0x83,0x00,' +` 0x8e,0xf3,0xb9,0x02,0x9a,0xee,0x31,0x09,' +` 0xee,0xde,0x26,0x44,0xf6,0x4f,0xb9,0xdc,' +` 0x70,0x08,0x71,0xec,0xa3,0x00,0xa3,0xf0,' +` 0xa8,0xfd,0xc8,0xf2,0x30,0xfc,0x3c,0xf4,' +` 0x77,0xfb,0x6c,0xf5,0x41,0xfb,0xa8,0xf5,' +` 0xab,0xf9,0x76,0xf6,0x30,0xfa,0xa9,0xf7,' +` 0x8c,0xfb,0x17,0xfa,0x5d,0xfc,0x1b,0xfb,' +` 0xfb,0xfc,0x19,0xfc,0x98,0xfd,0x05,0xfd,' +` 0x2d,0xfe,0xd8,0xfd,0xb8,0xfe,0x8d,0xfe,' +` 0x2d,0xff,0x1d,0xff,0x87,0xff,0x88,0xff,' +` 0xc7,0xff,0xce,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xe6,0xff,0xd7,0xff,0xb2,0xff,0x9d,0xff,' +` 0x5d,0xff,0x46,0xff,0xe5,0xfe,0xd1,0xfe,' +` 0x4b,0xfe,0x40,0xfe,0x93,0xfd,0x9f,0xfd,' +` 0xc5,0xfc,0xf1,0xfc,0xe5,0xfb,0x3a,0xfc,' +` 0xfd,0xfa,0x6a,0xfb,0xe6,0xf8,0xc2,0xf9,' +` 0xce,0xf7,0x11,0xf9,0xd4,0xf6,0xe8,0xf9,' +` 0x5e,0xf7,0xdf,0xf9,0x8e,0xf6,0x02,0xfa,' +` 0xbd,0xf5,0x8b,0xfa,0xbb,0xf4,0xca,0xfb,' +` 0x12,0xf3,0xf7,0xfe,0xd0,0xed,0xd7,0x0f,' +` 0x7a,0x73,0x46,0xe8,0x6f,0x02,0xa6,0xf3,' +` 0xae,0xfe,0xce,0xf6,0xbd,0xfd,0x8e,0xf8,' +` 0x86,0xfd,0xdd,0xf9,0x9c,0xfd,0xf9,0xfa,' +` 0xc4,0xfd,0x86,0xfc,0xd3,0xff,0xf3,0xfd,' +` 0xdf,0xff,0x95,0xfe,0xab,0xff,0xc3,0xfd,' +` 0x2a,0xff,0x53,0xfe,0x5f,0xff,0xc5,0xfe,' +` 0x91,0xff,0x22,0xff,0xb9,0xff,0x69,0xff,' +` 0xd3,0xff,0x9c,0xff,0xe5,0xff,0xc2,0xff,' +` 0xf1,0xff,0xdd,0xff,0xf9,0xff,0xf0,0xff,' +` 0xfd,0xff,0xfb,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x4f,0x00,0x95,0x00,' +` 0x98,0x00,0x07,0x01,0xfc,0x00,0x9c,0x01,' +` 0x79,0x01,0x53,0x02,0x09,0x02,0x26,0x03,' +` 0xa5,0x02,0x12,0x04,0x43,0x03,0x10,0x05,' +` 0xce,0x03,0xaa,0x06,0xb5,0x05,0x43,0x08,' +` 0x35,0x06,0x88,0x09,0x0a,0x06,0xdb,0x08,' +` 0x4f,0x05,0xf3,0x09,0xfe,0x04,0x13,0x0b,' +` 0x39,0x04,0x7f,0x0c,0x9f,0x02,0xd1,0x0e,' +` 0xd2,0xfe,0xe9,0x14,0xbe,0xef,0xbe,0x78,' +` 0x67,0x30,0x54,0xf5,0x81,0x11,0x2f,0xfe,' +` 0x15,0x0c,0x79,0x00,0x7f,0x09,0x58,0x01,' +` 0xc8,0x07,0xa1,0x01,0x73,0x06,0xa5,0x01,' +` 0x4c,0x05,0x36,0x00,0xf0,0x02,0x02,0x00,' +` 0x4f,0x02,0xe8,0xff,0x91,0x02,0xfd,0x00,' +` 0x2c,0x02,0xbf,0x00,0xab,0x01,0x90,0x00,' +` 0x3e,0x01,0x68,0x00,0xe4,0x00,0x4a,0x00,' +` 0x9e,0x00,0x32,0x00,0x65,0x00,0x1f,0x00,' +` 0x3b,0x00,0x11,0x00,0x1d,0x00,0x07,0x00,' +` 0x0a,0x00,0x02,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x05,0x00,0x07,0x00,' +` 0x0a,0x00,0x0f,0x00,0x13,0x00,0x1a,0x00,' +` 0x20,0x00,0x29,0x00,0x31,0x00,0x3e,0x00,' +` 0x47,0x00,0x59,0x00,0x66,0x00,0x7d,0x00,' +` 0x8b,0x00,0xab,0x00,0x4b,0x00,0x3b,0x00,' +` 0x55,0x00,0x69,0x00,0x7f,0x00,0x9f,0x00,' +` 0xae,0x00,0x70,0x01,0xd9,0x01,0xed,0x01,' +` 0x24,0x02,0x44,0x02,0x76,0x02,0xa1,0x02,' +` 0xd5,0x02,0x00,0x03,0x2f,0x03,0x57,0x03,' +` 0x80,0x03,0x9c,0x43,0xc3,0x03,0xdf,0x03,' +` 0xf6,0x03,0x0a,0x04,0x16,0x04,0x21,0x04,' +` 0x1f,0x04,0x1a,0x04,0x03,0x04,0xf7,0x03,' +` 0xcc,0x03,0xdb,0x03,0x53,0x04,0x1a,0x04,' +` 0xe8,0x03,0xad,0x03,0x70,0x03,0x37,0x03,' +` 0xe1,0x02,0x38,0x02,0x04,0x02,0xcb,0x01,' +` 0x99,0x01,0x65,0x01,0x36,0x01,0x06,0x01,' +` 0xdc,0x00,0xb5,0x00,0x92,0x00,0x72,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xfe,0xff,0x0a,0x00,' +` 0xf9,0xff,0x16,0x00,0xee,0xff,0x23,0x00,' +` 0xda,0xff,0x31,0x00,0xbc,0xff,0x3f,0x00,' +` 0x90,0xff,0x4a,0x00,0x52,0xff,0x4f,0x00,' +` 0xfb,0xfe,0x43,0x00,0x88,0xfe,0x21,0x00,' +` 0x59,0xfe,0x64,0x01,0x5e,0xfe,0x5f,0x01,' +` 0xb0,0xfd,0x5f,0x01,0xdf,0xfc,0xed,0x00,' +` 0xcb,0xf9,0x09,0x00,0x54,0xf8,0x53,0x00,' +` 0x60,0xf6,0x2a,0x01,0x78,0xf3,0x43,0x03,' +` 0x49,0xee,0xf0,0x09,0x9a,0xdd,0x5f,0x4e,' +` 0x98,0x45,0xf3,0xdd,0xc3,0x07,0xbb,0xec,' +` 0x30,0x00,0xc2,0xf0,0x26,0xfd,0xc9,0xf2,' +` 0xaf,0xfb,0x45,0xf4,0xf9,0xfa,0x8e,0xf5,' +` 0xb0,0xf9,0x2b,0xf5,0x9e,0xf9,0x8f,0xf6,' +` 0x17,0xfa,0xec,0xf7,0xb6,0xfa,0xdc,0xf9,' +` 0x76,0xfc,0x38,0xfb,0x11,0xfd,0x47,0xfc,' +` 0xb4,0xfd,0x3d,0xfd,0x54,0xfe,0x14,0xfe,' +` 0xdf,0xfe,0xc4,0xfe,0x4f,0xff,0x4b,0xff,' +` 0xa3,0xff,0xaa,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xd9,0xff,0xaa,0xff,0xa1,0xff,0x4b,0xff,' +` 0x4c,0xff,0xc3,0xfe,0xda,0xfe,0x13,0xfe,' +` 0x4d,0xfe,0x3d,0xfd,0xac,0xfd,0x48,0xfc,' +` 0x07,0xfd,0x3a,0xfb,0x6c,0xfc,0xd0,0xf9,' +` 0xa2,0xfa,0xf8,0xf7,0x03,0xfa,0xa1,0xf6,' +` 0x86,0xf9,0x46,0xf5,0x81,0xf9,0xa4,0xf5,' +` 0xdd,0xfa,0x6e,0xf4,0x87,0xfb,0x06,0xf3,' +` 0xed,0xfc,0x21,0xf1,0xce,0xff,0x64,0xed,' +` 0xdb,0x06,0x09,0xe0,0x93,0x3a,0x6f,0x58,' +` 0x7c,0xdd,0xd9,0x09,0x9a,0xee,0x27,0x03,' +` 0xc3,0xf3,0x19,0x01,0xa2,0xf6,0x4c,0x00,' +` 0x90,0xf8,0x07,0x00,0x06,0xfa,0x13,0x01,' +` 0x08,0xfd,0x6a,0x01,0xd7,0xfd,0x6a,0x01,' +` 0x7f,0xfe,0x6f,0x01,0x88,0xfe,0x2a,0x00,' +` 0xa1,0xfe,0x4b,0x00,0x0f,0xff,0x56,0x00,' +` 0x61,0xff,0x50,0x00,0x9b,0xff,0x43,0x00,' +` 0xc4,0xff,0x34,0x00,0xe0,0xff,0x25,0x00,' +` 0xf1,0xff,0x17,0x00,0xfa,0xff,0x0b,0x00,' +` 0xfe,0xff,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x59,0x00,0x73,0x00,' +` 0x95,0x00,0xb6,0x00,0xe0,0x00,0x08,0x01,' +` 0x3b,0x01,0x67,0x01,0x9f,0x01,0xcc,0x01,' +` 0x0b,0x02,0x39,0x02,0xea,0x02,0x36,0x03,' +` 0x7b,0x03,0xab,0x03,0xf5,0x03,0x15,0x04,' +` 0x67,0x04,0xef,0x03,0xd4,0x03,0xf2,0x03,' +` 0x10,0x04,0x10,0x04,0x30,0x04,0x0f,0x04,' +` 0x2e,0x04,0xeb,0x03,0x20,0x04,0x9d,0x03,' +` 0x45,0x04,0x97,0x43,0xf6,0x02,0x95,0x03,' +` 0xfd,0x02,0x1b,0x03,0xb3,0x02,0xaf,0x02,' +` 0x5b,0x02,0x4b,0x02,0x0c,0x02,0xf0,0x01,' +` 0xc4,0x01,0x6f,0x01,0x9b,0x00,0x9e,0x00,' +` 0x6d,0x00,0x67,0x00,0x44,0x00,0x3b,0x00,' +` 0x30,0x00,0x9e,0x00,0x84,0x00,0x78,0x00,' +` 0x5e,0x00,0x54,0x00,0x41,0x00,0x3a,0x00,' +` 0x2c,0x00,0x27,0x00,0x1c,0x00,0x18,0x00,' +` 0x11,0x00,0x0e,0x00,0x09,0x00,0x07,0x00,' +` 0x04,0x00,0x03,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,' +` 0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,' +` 0x07,0x00,0x0a,0x00,0x0f,0x00,0x14,0x00,' +` 0x1c,0x00,0x22,0x00,0x2e,0x00,0x36,0x00,' +` 0x48,0x00,0x50,0x00,0x71,0x00,0x27,0x00,' +` 0xfb,0xff,0x1c,0x00,0x22,0x00,0x3e,0x00,' +` 0x4f,0x00,0x6e,0x00,0x84,0x00,0xb1,0x00,' +` 0x89,0x01,0xce,0x01,0xef,0x01,0x26,0x02,' +` 0x54,0x02,0x8b,0x02,0xb9,0x02,0xed,0x02,' +` 0x19,0x03,0x48,0x03,0x70,0x03,0x91,0x43,' +` 0xb9,0x03,0xd9,0x03,0xf2,0x03,0x06,0x04,' +` 0x15,0x04,0x1d,0x04,0x21,0x04,0x1c,0x04,' +` 0x13,0x04,0xf8,0x03,0xee,0x03,0x78,0x04,' +` 0x5b,0x04,0x21,0x04,0xef,0x03,0xad,0x03,' +` 0x75,0x03,0x2c,0x03,0xf8,0x02,0x88,0x02,' +` 0xf6,0x01,0xcc,0x01,0x91,0x01,0x62,0x01,' +` 0x2d,0x01,0x02,0x01,0xd5,0x00,0xaf,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,' +` 0x08,0x00,0x02,0x00,0x19,0x00,0x05,0x00,' +` 0x2f,0x00,0x03,0x00,0x48,0x00,0xf8,0xff,' +` 0x61,0x00,0xe1,0xff,0x78,0x00,0xba,0xff,' +` 0x8c,0x00,0x7f,0xff,0x98,0x00,0x22,0xff,' +` 0xa4,0x00,0xa2,0xff,0x98,0x01,0x32,0xff,' +` 0xa0,0x01,0x89,0xfe,0xa2,0x01,0xad,0xfd,' +` 0xbb,0x01,0x24,0xfc,0xe2,0xff,0xb8,0xf9,' +` 0x17,0x00,0xcc,0xf7,0x94,0x00,0x20,0xf5,' +` 0x1f,0x02,0xa6,0xf0,0x31,0x07,0xd2,0xe3,' +` 0xce,0x2f,0x27,0x61,0xa5,0xdd,0x49,0x07,' +` 0x34,0xed,0xa7,0xff,0xf6,0xf0,0xab,0xfc,' +` 0xb8,0xf2,0x29,0xfb,0xe8,0xf3,0x8c,0xfa,' +` 0x7e,0xf4,0x87,0xf8,0xca,0xf4,0xe1,0xf8,' +` 0x03,0xf6,0x6b,0xf9,0x48,0xf7,0x23,0xfa,' +` 0x8b,0xf8,0x8e,0xfb,0xd3,0xfa,0x87,0xfc,' +` 0xdd,0xfb,0x47,0xfd,0xdf,0xfc,0xfb,0xfd,' +` 0xc3,0xfd,0x9a,0xfe,0x83,0xfe,0x1c,0xff,' +` 0x1a,0xff,0x80,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x88,0xff,0x7e,0xff,0x1a,0xff,0x19,0xff,' +` 0x83,0xfe,0x95,0xfe,0xc4,0xfd,0xf5,0xfd,' +` 0xe0,0xfc,0x3f,0xfd,0xdf,0xfb,0x7d,0xfc,' +` 0xda,0xfa,0x6f,0xfb,0x8d,0xf8,0x1a,0xfa,' +` 0x50,0xf7,0x60,0xf9,0x10,0xf6,0xd4,0xf8,' +` 0xdc,0xf4,0x78,0xf8,0x9e,0xf4,0x78,0xfa,' +` 0x09,0xf4,0x11,0xfb,0xe5,0xf2,0x8a,0xfc,' +` 0x34,0xf1,0x75,0xff,0x90,0xed,0xf0,0x06,' +` 0x3f,0xde,0xa9,0x63,0x78,0x2c,0xe0,0xe4,' +` 0xb7,0x06,0x1a,0xf1,0xeb,0x01,0x6d,0xf5,' +` 0x7a,0x00,0x06,0xf8,0x0b,0x00,0xe5,0xf9,' +` 0xe4,0xff,0x71,0xfc,0xb3,0x01,0xd2,0xfd,' +` 0xa1,0x01,0xa7,0xfe,0xa1,0x01,0x4b,0xff,' +` 0x9b,0x01,0xb4,0xff,0xa4,0x00,0x33,0xff,' +` 0x9a,0x00,0x8c,0xff,0x8e,0x00,0xc4,0xff,' +` 0x7a,0x00,0xe8,0xff,0x62,0x00,0xfd,0xff,' +` 0x49,0x00,0x05,0x00,0x2f,0x00,0x07,0x00,' +` 0x19,0x00,0x02,0x00,0x08,0x00,0x01,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x91,0x00,0xab,0x00,' +` 0xde,0x00,0xfb,0x00,0x3a,0x01,0x58,0x01,' +` 0xa2,0x01,0xbe,0x01,0x0d,0x02,0x7c,0x02,' +` 0x12,0x03,0x13,0x03,0x97,0x03,0x8c,0x03,' +` 0x19,0x04,0xf6,0x03,0x90,0x04,0x40,0x04,' +` 0x34,0x04,0xac,0x03,0x6c,0x04,0xb5,0x03,' +` 0x99,0x04,0x8c,0x03,0xc4,0x04,0x24,0x03,' +` 0x20,0x05,0x03,0x02,0x7d,0x07,0x38,0x43,' +` 0x07,0x00,0xff,0x04,0xea,0x01,0xc5,0x03,' +` 0x03,0x02,0x15,0x03,0xd3,0x01,0x88,0x02,' +` 0x8d,0x01,0x18,0x02,0x34,0x01,0xe1,0x00,' +` 0x4a,0x00,0x96,0x00,0x1f,0x00,0x5e,0x00,' +` 0xfc,0xff,0x34,0x00,0xdd,0xff,0x37,0x00,' +` 0x58,0x00,0x5e,0x00,0x35,0x00,0x40,0x00,' +` 0x20,0x00,0x29,0x00,0x11,0x00,0x18,0x00,' +` 0x08,0x00,0x0d,0x00,0x02,0x00,0x06,0x00,' +` 0x00,0x00,0x02,0x00,0xfe,0xff,0xff,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xfd,0xff,0xfc,0xff,0xfb,0xff,0xfd,0xff,' +` 0xfe,0xff,0xff,0xff,0x01,0x00,0x04,0x00,' +` 0x08,0x00,0x0d,0x00,0x14,0x00,0x1b,0x00,' +` 0x27,0x00,0x30,0x00,0x44,0x00,0x3a,0x00,' +` 0xdc,0xff,0xf2,0xff,0xf7,0xff,0x12,0x00,' +` 0x1b,0x00,0x3d,0x00,0x47,0x00,0x76,0x00,' +` 0x75,0x00,0x0e,0x01,0xbc,0x01,0xd1,0x01,' +` 0x14,0x02,0x3d,0x02,0x78,0x02,0xa5,0x02,' +` 0xdb,0x02,0x08,0x03,0x37,0x03,0x60,0x03,' +` 0x82,0x43,0xac,0x03,0xca,0x03,0xe6,0x03,' +` 0xf8,0x03,0x0a,0x04,0x0e,0x04,0x18,0x04,' +` 0x0a,0x04,0x10,0x04,0xe4,0x03,0x45,0x04,' +` 0x91,0x04,0x43,0x04,0x21,0x04,0xda,0x03,' +` 0xaa,0x03,0x61,0x03,0x2b,0x03,0xe0,0x02,' +` 0xaa,0x02,0x0a,0x02,0xbb,0x01,0x8c,0x01,' +` 0x56,0x01,0x25,0x01,0xf7,0x00,0xcd,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,' +` 0x06,0x00,0x10,0x00,0x0e,0x00,0x21,0x00,' +` 0x1c,0x00,0x3f,0x00,0x28,0x00,0x58,0x00,' +` 0x2d,0x00,0x6f,0x00,0x29,0x00,0x80,0x00,' +` 0x15,0x00,0x85,0x00,0xf0,0xff,0x7b,0x00,' +` 0xc4,0xff,0x5f,0x01,0x61,0x00,0x5d,0x01,' +` 0x03,0x00,0x3e,0x01,0x7d,0xff,0x0d,0x01,' +` 0xc8,0xfe,0xdf,0x00,0x77,0xfd,0xa1,0xfe,' +` 0x46,0xfb,0x51,0xfe,0xc3,0xf9,0x2b,0xfe,' +` 0xda,0xf7,0xae,0xfe,0xc5,0xf4,0xc4,0x01,' +` 0x43,0xea,0xe9,0x74,0x8d,0x0c,0x2b,0xef,' +` 0xf2,0xfd,0x83,0xf3,0x02,0xfb,0xca,0xf4,' +` 0xb5,0xf9,0x82,0xf5,0x10,0xf9,0x35,0xf6,' +` 0x5f,0xf8,0x24,0xf5,0xd6,0xf7,0x35,0xf6,' +` 0x64,0xf8,0x4b,0xf7,0x27,0xf9,0x70,0xf8,' +` 0x0e,0xfa,0x95,0xf9,0x8c,0xfb,0xa9,0xfb,' +` 0x9d,0xfc,0x9b,0xfc,0x6f,0xfd,0x80,0xfd,' +` 0x2a,0xfe,0x45,0xfe,0xc7,0xfe,0xe6,0xfe,' +` 0x43,0xff,0x60,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x7e,0xff,0x22,0xff,0x1a,0xff,0x8e,0xfe,' +` 0x96,0xfe,0xd3,0xfd,0xf5,0xfd,0xf2,0xfc,' +` 0x3c,0xfd,0xf1,0xfb,0x77,0xfc,0xd9,0xfa,' +` 0xe2,0xfa,0xb8,0xf8,0xf1,0xf9,0x78,0xf7,' +` 0x30,0xf9,0x3d,0xf6,0x9b,0xf8,0x13,0xf5,' +` 0x39,0xf8,0x39,0xf4,0x08,0xfa,0x7b,0xf4,' +` 0xa7,0xfa,0x7b,0xf3,0xfd,0xfb,0xfe,0xf1,' +` 0xa6,0xfe,0xc0,0xee,0x87,0x05,0x86,0xe0,' +` 0x07,0x6a,0x08,0x23,0x09,0xe8,0x1f,0x05,' +` 0x74,0xf2,0x31,0x01,0x4e,0xf6,0x1b,0x00,' +` 0xab,0xf8,0xea,0xff,0x60,0xfa,0x64,0x00,' +` 0x8b,0xfd,0x8d,0x01,0x72,0xfe,0xa7,0x01,' +` 0x33,0xff,0xb2,0x01,0xc7,0xff,0xab,0x01,' +` 0x3a,0x00,0x24,0x01,0x75,0xff,0xc2,0x00,' +` 0xc7,0xff,0xaf,0x00,0xf6,0xff,0x97,0x00,' +` 0x10,0x00,0x79,0x00,0x19,0x00,0x58,0x00,' +` 0x18,0x00,0x3a,0x00,0x0e,0x00,0x1b,0x00,' +` 0x07,0x00,0x0a,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x47,0x01,0x45,0x02,' +` 0xd4,0x01,0x28,0x03,0x74,0x02,0x2a,0x04,' +` 0x14,0x03,0xf2,0x05,0xcf,0x04,0x68,0x07,' +` 0x7f,0x05,0xbe,0x08,0x16,0x06,0x15,0x0a,' +` 0x7c,0x06,0x70,0x0b,0x75,0x06,0x1a,0x0b,' +` 0x91,0x04,0x49,0x0c,0x78,0x03,0xdb,0x0d,' +` 0x57,0x01,0x8e,0x10,0xbd,0xfc,0xa8,0x17,' +` 0xe6,0xeb,0x30,0x68,0x38,0x47,0x74,0xee,' +` 0xed,0x14,0x46,0xfb,0x93,0x0d,0x72,0xfe,' +` 0x1a,0x0a,0x93,0xff,0xcc,0x07,0xfe,0xff,' +` 0xde,0x05,0x6a,0xfe,0x51,0x03,0x8a,0xfe,' +` 0x62,0x02,0x9d,0xfe,0xa6,0x01,0xaa,0xfe,' +` 0x17,0x01,0xb2,0xfe,0xfb,0x00,0xd0,0xff,' +` 0x0b,0x01,0xc0,0xff,0xb7,0x00,0xc0,0xff,' +` 0x75,0x00,0xc6,0xff,0x46,0x00,0xd1,0xff,' +` 0x27,0x00,0xde,0xff,0x13,0x00,0xe8,0xff,' +` 0x03,0x00,0xf4,0xff,0x01,0x00,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xfd,0xff,0xfc,0xff,0xfa,0xff,0xfa,0xff,' +` 0xfc,0xff,0xfc,0xff,0xfe,0xff,0x00,0x00,' +` 0x04,0x00,0x08,0x00,0x0f,0x00,0x15,0x00,' +` 0x22,0x00,0x27,0x00,0x41,0x00,0x1d,0x00,' +` 0xce,0xff,0xec,0xff,0xed,0xff,0x0a,0x00,' +` 0x11,0x00,0x34,0x00,0x3f,0x00,0x6b,0x00,' +` 0x6e,0x00,0xe0,0x00,0xad,0x01,0xcc,0x01,' +` 0x0a,0x02,0x37,0x02,0x6f,0x02,0x9f,0x02,' +` 0xd3,0x02,0x01,0x03,0x30,0x03,0x5a,0x03,' +` 0x7b,0x43,0xa5,0x03,0xc4,0x03,0xdf,0x03,' +` 0xf2,0x03,0x03,0x04,0x09,0x04,0x0f,0x04,' +` 0x06,0x04,0x06,0x04,0xe4,0x03,0x64,0x04,' +` 0x89,0x04,0x3f,0x04,0x1b,0x04,0xd4,0x03,' +` 0xa4,0x03,0x5b,0x03,0x27,0x03,0xd9,0x02,' +` 0xaa,0x02,0x18,0x02,0xb3,0x01,0x88,0x01,' +` 0x50,0x01,0x22,0x01,0xf3,0x00,0xca,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x09,0x00,0x0d,0x00,0x17,0x00,0x1a,0x00,' +` 0x2b,0x00,0x32,0x00,0x45,0x00,0x43,0x00,' +` 0x5a,0x00,0x4e,0x00,0x68,0x00,0x4e,0x00,' +` 0x6d,0x00,0x3d,0x00,0x65,0x00,0x10,0x00,' +` 0x9b,0x00,0x00,0x01,0x09,0x01,0xc2,0x00,' +` 0xdf,0x00,0x6e,0x00,0x92,0x00,0xfd,0xff,' +` 0x24,0x00,0x7b,0xff,0x2f,0xff,0xce,0xfc,' +` 0x71,0xfd,0xdd,0xfb,0xad,0xfc,0xbf,0xfa,' +` 0x0a,0xfc,0x6b,0xf9,0xd0,0xfb,0x4b,0xf7,' +` 0x63,0xfe,0x9f,0x78,0xfb,0xf3,0xa9,0xfa,' +` 0x79,0xf6,0xfa,0xf8,0xb7,0xf6,0x45,0xf8,' +` 0xcb,0xf6,0xfa,0xf7,0xf2,0xf6,0x04,0xf8,' +` 0x31,0xf6,0x9b,0xf6,0x8e,0xf6,0x55,0xf7,' +` 0x67,0xf7,0x2d,0xf8,0x65,0xf8,0x21,0xf9,' +` 0x7a,0xf9,0x1f,0xfa,0x1c,0xfb,0x14,0xfc,' +` 0x4e,0xfc,0xed,0xfc,0x38,0xfd,0xbb,0xfd,' +` 0x05,0xfe,0x6e,0xfe,0xaf,0xfe,0x00,0xff,' +` 0x36,0xff,0x6f,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x51,0xff,0x56,0xff,0xcd,0xfe,0xe5,0xfe,' +` 0x1e,0xfe,0x58,0xfe,0x47,0xfd,0xb2,0xfd,' +` 0x4b,0xfc,0xfa,0xfc,0x38,0xfb,0xa1,0xfb,' +` 0x0e,0xf9,0xac,0xfa,0xbe,0xf7,0xf7,0xf9,' +` 0x67,0xf6,0x71,0xf9,0x11,0xf5,0x31,0xf9,' +` 0xb2,0xf3,0x5a,0xfa,0x42,0xf4,0x81,0xfb,' +` 0xe3,0xf2,0x10,0xfd,0xfd,0xf0,0x0f,0x00,' +` 0x2f,0xed,0x61,0x07,0x5e,0xdf,0x8c,0x3e,' +` 0x61,0x55,0xb9,0xdd,0x45,0x0a,0xde,0xee,' +` 0xa3,0x03,0x25,0xf4,0xa3,0x01,0x24,0xf7,' +` 0xfb,0x00,0x3d,0xf9,0x10,0x01,0xa0,0xfc,' +` 0x57,0x02,0xca,0xfd,0x50,0x02,0xb5,0xfe,' +` 0x46,0x02,0x69,0xff,0x31,0x02,0xf0,0xff,' +` 0xf8,0x01,0x56,0xff,0x07,0x01,0xa8,0xff,' +` 0xef,0x00,0xe3,0xff,0xcf,0x00,0x06,0x00,' +` 0xa8,0x00,0x17,0x00,0x7e,0x00,0x1a,0x00,' +` 0x55,0x00,0x10,0x00,0x2e,0x00,0x0a,0x00,' +` 0x15,0x00,0x04,0x00,0x05,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xee,0x01,0x8c,0x01,' +` 0xc2,0x02,0x20,0x02,0xba,0x03,0xbe,0x02,' +` 0x74,0x05,0x59,0x04,0xdc,0x06,0x0a,0x05,' +` 0x31,0x08,0xa5,0x05,0x8a,0x09,0x16,0x06,' +` 0xe5,0x0a,0x4c,0x06,0x21,0x0b,0x29,0x04,' +` 0x15,0x0c,0x29,0x03,0xb5,0x0d,0x1a,0x01,' +` 0x73,0x10,0xa3,0xfc,0x58,0x17,0x26,0xed,' +` 0x53,0x53,0x38,0x5d,0xfc,0xea,0x92,0x16,' +` 0x4f,0xfa,0x5f,0x0e,0xf2,0xfd,0xa7,0x0a,' +` 0x43,0xff,0x3b,0x08,0xc8,0xff,0x25,0x06,' +` 0x23,0xfe,0x8e,0x03,0x51,0xfe,0x8f,0x02,' +` 0x6a,0xfe,0xc5,0x01,0x7c,0xfe,0x29,0x01,' +` 0x8c,0xfe,0xce,0x00,0xa1,0xff,0x2e,0x01,' +` 0xa3,0xff,0xce,0x00,0xa7,0xff,0x85,0x00,' +` 0xb1,0xff,0x51,0x00,0xbf,0xff,0x2d,0x00,' +` 0xcf,0xff,0x15,0x00,0xda,0xff,0x04,0x00,' +` 0xeb,0xff,0x01,0x00,0xf8,0xff,0x00,0x00,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0x75,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_pm0_30_90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_pm0_30_90deg_16khz.m4 new file mode 100644 index 000000000000..b5bb66f90fa5 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_pm0_30_90deg_16khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xf0,0xff,' +` 0xe5,0xff,0xd7,0xff,0xbc,0xff,0xaf,0xff,' +` 0x9d,0xff,0x9b,0xff,0x96,0xff,0xb0,0xff,' +` 0xcd,0xff,0x16,0x00,0x61,0x00,0xd8,0x00,' +` 0xa4,0x01,0xa7,0x02,0x33,0x03,0x34,0x04,' +` 0xd9,0x04,0xf1,0x05,0x82,0x06,0x8d,0x07,' +` 0xf1,0x07,0xf3,0x08,0x1d,0x09,0x37,0x0a,' +` 0xbb,0x09,0xf8,0x0a,0xca,0x09,0x4e,0x0c,' +` 0x8a,0x4a,0x0a,0x09,0x21,0x0b,0x9c,0x09,' +` 0x22,0x0a,0xec,0x08,0xfa,0x08,0x09,0x08,' +` 0xab,0x07,0xb1,0x06,0x25,0x06,0x2f,0x05,' +` 0x7c,0x04,0x90,0x03,0xe1,0x02,0x24,0x02,' +` 0x62,0x01,0x86,0x00,0x42,0x00,0xe6,0xff,' +` 0xc4,0xff,0x99,0xff,0x9a,0xff,0x9b,0xff,' +` 0xab,0xff,0xb9,0xff,0xcd,0xff,0xe1,0xff,' +` 0xef,0xff,0xf8,0xff,0xfe,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0x0f,0x00,0x20,0x00,0x36,0x00,0x54,0x00,' +` 0x85,0x00,0xa6,0x00,0xc1,0x00,0xd2,0x00,' +` 0xcd,0x00,0xad,0x00,0x5c,0x00,0xe7,0xff,' +` 0x2f,0xff,0x6b,0xfe,0xaa,0xfc,0xd6,0xfa,' +` 0x7d,0xf9,0xc7,0xf7,0x26,0xf6,0x5b,0xf4,' +` 0xc2,0xf2,0x35,0xf1,0xcb,0xef,0x84,0xee,' +` 0x4f,0xed,0x2c,0xec,0xc8,0xeb,0x1b,0xeb,' +` 0xd8,0xea,0x9a,0xea,0xa2,0x6a,0xe0,0xea,' +` 0x42,0xeb,0xc6,0xeb,0x77,0xec,0x91,0xed,' +` 0x83,0xee,0x86,0xef,0xfa,0xf0,0x52,0xf2,' +` 0xed,0xf3,0x68,0xf5,0x2c,0xf7,0xb4,0xf8,' +` 0x59,0xfa,0x97,0xfb,0x48,0xfd,0xdc,0xfe,' +` 0x88,0xff,0x24,0x00,0x80,0x00,0xc3,0x00,' +` 0xd1,0x00,0xc4,0x00,0xad,0x00,0x8b,0x00,' +` 0x69,0x00,0x3c,0x00,0x22,0x00,0x10,0x00,' +` 0x04,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x04,0x00,0x0f,0x00,0x20,0x00,' +` 0x36,0x00,0x54,0x00,0x85,0x00,0xa6,0x00,' +` 0xc1,0x00,0xd2,0x00,0xcd,0x00,0xad,0x00,' +` 0x5c,0x00,0xe7,0xff,0x2f,0xff,0x6b,0xfe,' +` 0xaa,0xfc,0xd6,0xfa,0x7d,0xf9,0xc7,0xf7,' +` 0x26,0xf6,0x5b,0xf4,0xc2,0xf2,0x35,0xf1,' +` 0xcb,0xef,0x84,0xee,0x4f,0xed,0x2c,0xec,' +` 0xc8,0xeb,0x1b,0xeb,0xd8,0xea,0x9a,0xea,' +` 0xa2,0x6a,0xe0,0xea,0x42,0xeb,0xc6,0xeb,' +` 0x77,0xec,0x91,0xed,0x83,0xee,0x86,0xef,' +` 0xfa,0xf0,0x52,0xf2,0xed,0xf3,0x68,0xf5,' +` 0x2c,0xf7,0xb4,0xf8,0x59,0xfa,0x97,0xfb,' +` 0x48,0xfd,0xdc,0xfe,0x88,0xff,0x24,0x00,' +` 0x80,0x00,0xc3,0x00,0xd1,0x00,0xc4,0x00,' +` 0xad,0x00,0x8b,0x00,0x69,0x00,0x3c,0x00,' +` 0x22,0x00,0x10,0x00,0x04,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf8,0xff,0xf0,0xff,0xe5,0xff,0xd7,0xff,' +` 0xbc,0xff,0xaf,0xff,0x9d,0xff,0x9b,0xff,' +` 0x96,0xff,0xb0,0xff,0xcd,0xff,0x16,0x00,' +` 0x61,0x00,0xd8,0x00,0xa4,0x01,0xa7,0x02,' +` 0x33,0x03,0x34,0x04,0xd9,0x04,0xf1,0x05,' +` 0x82,0x06,0x8d,0x07,0xf1,0x07,0xf3,0x08,' +` 0x1d,0x09,0x37,0x0a,0xbb,0x09,0xf8,0x0a,' +` 0xca,0x09,0x4e,0x0c,0x8a,0x4a,0x0a,0x09,' +` 0x21,0x0b,0x9c,0x09,0x22,0x0a,0xec,0x08,' +` 0xfa,0x08,0x09,0x08,0xab,0x07,0xb1,0x06,' +` 0x25,0x06,0x2f,0x05,0x7c,0x04,0x90,0x03,' +` 0xe1,0x02,0x24,0x02,0x62,0x01,0x86,0x00,' +` 0x42,0x00,0xe6,0xff,0xc4,0xff,0x99,0xff,' +` 0x9a,0xff,0x9b,0xff,0xab,0xff,0xb9,0xff,' +` 0xcd,0xff,0xe1,0xff,0xef,0xff,0xf8,0xff,' +` 0xfe,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf8,0xff,0xf0,0xff,' +` 0xe5,0xff,0xd7,0xff,0xbc,0xff,0xaf,0xff,' +` 0x9d,0xff,0x9b,0xff,0x96,0xff,0xb0,0xff,' +` 0xcd,0xff,0x16,0x00,0x61,0x00,0xd8,0x00,' +` 0xa4,0x01,0xa7,0x02,0x33,0x03,0x34,0x04,' +` 0xd9,0x04,0xf1,0x05,0x82,0x06,0x8d,0x07,' +` 0xf1,0x07,0xf3,0x08,0x1d,0x09,0x37,0x0a,' +` 0xbb,0x09,0xf8,0x0a,0xca,0x09,0x4e,0x0c,' +` 0x8a,0x4a,0x0a,0x09,0x21,0x0b,0x9c,0x09,' +` 0x22,0x0a,0xec,0x08,0xfa,0x08,0x09,0x08,' +` 0xab,0x07,0xb1,0x06,0x25,0x06,0x2f,0x05,' +` 0x7c,0x04,0x90,0x03,0xe1,0x02,0x24,0x02,' +` 0x62,0x01,0x86,0x00,0x42,0x00,0xe6,0xff,' +` 0xc4,0xff,0x99,0xff,0x9a,0xff,0x9b,0xff,' +` 0xab,0xff,0xb9,0xff,0xcd,0xff,0xe1,0xff,' +` 0xef,0xff,0xf8,0xff,0xfe,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0x0f,0x00,0x20,0x00,0x36,0x00,0x54,0x00,' +` 0x85,0x00,0xa6,0x00,0xc1,0x00,0xd2,0x00,' +` 0xcd,0x00,0xad,0x00,0x5c,0x00,0xe7,0xff,' +` 0x2f,0xff,0x6b,0xfe,0xaa,0xfc,0xd6,0xfa,' +` 0x7d,0xf9,0xc7,0xf7,0x26,0xf6,0x5b,0xf4,' +` 0xc2,0xf2,0x35,0xf1,0xcb,0xef,0x84,0xee,' +` 0x4f,0xed,0x2c,0xec,0xc8,0xeb,0x1b,0xeb,' +` 0xd8,0xea,0x9a,0xea,0xa2,0x6a,0xe0,0xea,' +` 0x42,0xeb,0xc6,0xeb,0x77,0xec,0x91,0xed,' +` 0x83,0xee,0x86,0xef,0xfa,0xf0,0x52,0xf2,' +` 0xed,0xf3,0x68,0xf5,0x2c,0xf7,0xb4,0xf8,' +` 0x59,0xfa,0x97,0xfb,0x48,0xfd,0xdc,0xfe,' +` 0x88,0xff,0x24,0x00,0x80,0x00,0xc3,0x00,' +` 0xd1,0x00,0xc4,0x00,0xad,0x00,0x8b,0x00,' +` 0x69,0x00,0x3c,0x00,0x22,0x00,0x10,0x00,' +` 0x04,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x04,0x00,0x0f,0x00,0x20,0x00,' +` 0x36,0x00,0x54,0x00,0x85,0x00,0xa6,0x00,' +` 0xc1,0x00,0xd2,0x00,0xcd,0x00,0xad,0x00,' +` 0x5c,0x00,0xe7,0xff,0x2f,0xff,0x6b,0xfe,' +` 0xaa,0xfc,0xd6,0xfa,0x7d,0xf9,0xc7,0xf7,' +` 0x26,0xf6,0x5b,0xf4,0xc2,0xf2,0x35,0xf1,' +` 0xcb,0xef,0x84,0xee,0x4f,0xed,0x2c,0xec,' +` 0xc8,0xeb,0x1b,0xeb,0xd8,0xea,0x9a,0xea,' +` 0xa2,0x6a,0xe0,0xea,0x42,0xeb,0xc6,0xeb,' +` 0x77,0xec,0x91,0xed,0x83,0xee,0x86,0xef,' +` 0xfa,0xf0,0x52,0xf2,0xed,0xf3,0x68,0xf5,' +` 0x2c,0xf7,0xb4,0xf8,0x59,0xfa,0x97,0xfb,' +` 0x48,0xfd,0xdc,0xfe,0x88,0xff,0x24,0x00,' +` 0x80,0x00,0xc3,0x00,0xd1,0x00,0xc4,0x00,' +` 0xad,0x00,0x8b,0x00,0x69,0x00,0x3c,0x00,' +` 0x22,0x00,0x10,0x00,0x04,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf8,0xff,0xf0,0xff,0xe5,0xff,0xd7,0xff,' +` 0xbc,0xff,0xaf,0xff,0x9d,0xff,0x9b,0xff,' +` 0x96,0xff,0xb0,0xff,0xcd,0xff,0x16,0x00,' +` 0x61,0x00,0xd8,0x00,0xa4,0x01,0xa7,0x02,' +` 0x33,0x03,0x34,0x04,0xd9,0x04,0xf1,0x05,' +` 0x82,0x06,0x8d,0x07,0xf1,0x07,0xf3,0x08,' +` 0x1d,0x09,0x37,0x0a,0xbb,0x09,0xf8,0x0a,' +` 0xca,0x09,0x4e,0x0c,0x8a,0x4a,0x0a,0x09,' +` 0x21,0x0b,0x9c,0x09,0x22,0x0a,0xec,0x08,' +` 0xfa,0x08,0x09,0x08,0xab,0x07,0xb1,0x06,' +` 0x25,0x06,0x2f,0x05,0x7c,0x04,0x90,0x03,' +` 0xe1,0x02,0x24,0x02,0x62,0x01,0x86,0x00,' +` 0x42,0x00,0xe6,0xff,0xc4,0xff,0x99,0xff,' +` 0x9a,0xff,0x9b,0xff,0xab,0xff,0xb9,0xff,' +` 0xcd,0xff,0xe1,0xff,0xef,0xff,0xf8,0xff,' +` 0xfe,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf9,0xff,0xf2,0xff,0xe9,0xff,0xde,0xff,' +` 0xd5,0xff,0xc5,0xff,0xa3,0xff,0x9b,0xff,' +` 0x9b,0xff,0xa1,0xff,0x9c,0xff,0xa8,0xff,' +` 0x08,0x00,0x6d,0x00,0x90,0x00,0xe4,0x00,' +` 0x24,0x01,0xd8,0x01,0x27,0x02,0x99,0x02,' +` 0xd8,0x02,0x6b,0x03,0xb9,0x03,0xc0,0x04,' +` 0x9b,0x03,0x07,0x03,0xb2,0x06,0xd4,0x07,' +` 0xbc,0x08,0xcd,0x09,0xdb,0x4a,0xe6,0x0b,' +` 0x97,0x0c,0xf1,0x0c,0x28,0x0d,0xb7,0x0f,' +` 0x17,0x0e,0x74,0x0b,0xde,0x0a,0x78,0x09,' +` 0x44,0x08,0xbc,0x06,0x74,0x05,0x05,0x04,' +` 0xb3,0x02,0xa0,0x01,0xec,0x00,0x38,0x00,' +` 0xfd,0xff,0xaf,0xff,0x80,0xff,0x71,0xff,' +` 0x7b,0xff,0xa7,0xff,0xba,0xff,0xbd,0xff,' +` 0xcc,0xff,0xdf,0xff,0xed,0xff,0xf8,0xff,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x04,0x00,0xfe,0xff,0x0e,0x00,' +` 0xfc,0xff,0x28,0x00,0xfa,0xff,0x1d,0x00,' +` 0xd4,0xff,0x68,0x00,0xf5,0xff,0xaf,0x00,' +` 0xdc,0xff,0x00,0x00,0x12,0xff,0x0f,0x00,' +` 0x2b,0xfe,0x73,0xff,0x2f,0xfd,0xff,0xfe,' +` 0x7d,0xfb,0x24,0xfe,0x5b,0xf9,0xbe,0xfc,' +` 0x8c,0xf5,0xc0,0xfc,0xca,0xf7,0xa8,0xf9,' +` 0x7a,0xea,0x68,0xf9,0x73,0xda,0xec,0x63,' +` 0x68,0x02,0xde,0xda,0xb0,0xec,0xc3,0xdf,' +` 0x15,0xe4,0x32,0xde,0x1b,0xea,0x30,0xe6,' +` 0xc8,0xec,0x9e,0xeb,0x9a,0xf1,0xd4,0xf1,' +` 0xbc,0xf6,0x87,0xf8,0xaa,0xfc,0xe7,0xfc,' +` 0x78,0xff,0xc2,0xff,0x71,0x01,0xf7,0x00,' +` 0xc1,0x01,0x4d,0x01,0x75,0x01,0x01,0x01,' +` 0xec,0x00,0x86,0x00,0x70,0x00,0x38,0x00,' +` 0x1e,0x00,0x07,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x06,0x00,0x1e,0x00,0x31,0x00,' +` 0x6f,0x00,0x71,0x00,0xef,0x00,0xd2,0x00,' +` 0x71,0x01,0xfb,0x00,0xae,0x01,0x74,0x00,' +` 0x5c,0x01,0xd9,0xfe,0x65,0xff,0xd2,0xfb,' +` 0xa7,0xfc,0xe4,0xf6,0xc1,0xf6,0x3e,0xf0,' +` 0xf4,0xf1,0xc1,0xe9,0xb1,0xed,0x2d,0xe4,' +` 0x63,0xeb,0xfc,0xd9,0xd9,0xe8,0x96,0xdb,' +` 0x9b,0xf3,0xf0,0xcf,0xac,0x26,0x54,0x4e,' +` 0x2d,0xd2,0x7c,0x00,0xc3,0xe6,0xa8,0xff,' +` 0xf5,0xf5,0xab,0xfe,0xa0,0xf4,0x08,0xff,' +` 0x9e,0xf8,0xd9,0xff,0xe2,0xfa,0x5a,0x00,' +` 0xb1,0xfc,0x6f,0x00,0xd8,0xfd,0xd4,0x00,' +` 0xbf,0xfe,0x94,0x00,0xd0,0xff,0xfc,0x00,' +` 0xdf,0xff,0x9b,0x00,0xc0,0xff,0x49,0x00,' +` 0xfa,0xff,0x39,0x00,0xfa,0xff,0x16,0x00,' +` 0xfe,0xff,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xec,0xff,0xe7,0xff,0xc8,0xff,0xd4,0xff,' +` 0xb4,0xff,0xc7,0xff,0x6a,0xff,0xb7,0xff,' +` 0x6e,0xff,0x21,0x00,0xdf,0xff,0xd3,0x00,' +` 0xcc,0x00,0x70,0x02,0x87,0x02,0x20,0x05,' +` 0x09,0x05,0x14,0x08,0x8a,0x07,0x21,0x0b,' +` 0x97,0x09,0xa4,0x0d,0xb9,0x0c,0x25,0x12,' +` 0x5c,0x09,0xf5,0x11,0x75,0x04,0x51,0x1e,' +` 0x62,0x44,0x23,0xfe,0x8f,0x0e,0x4f,0x03,' +` 0xf1,0x08,0xd2,0xff,0xe9,0x05,0x94,0x02,' +` 0xef,0x04,0xd3,0x01,0xb6,0x03,0x66,0x01,' +` 0xc9,0x02,0xdd,0x00,0x8b,0x01,0x36,0x00,' +` 0xde,0x00,0xe9,0xff,0x25,0x00,0x45,0xff,' +` 0xc3,0xff,0x5f,0xff,0xae,0xff,0x6e,0xff,' +` 0xb3,0xff,0xaf,0xff,0xdb,0xff,0xd2,0xff,' +` 0xeb,0xff,0xee,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xec,0xff,0xe7,0xff,' +` 0xc8,0xff,0xd4,0xff,0xb4,0xff,0xc7,0xff,' +` 0x6a,0xff,0xb7,0xff,0x6e,0xff,0x21,0x00,' +` 0xdf,0xff,0xd3,0x00,0xcc,0x00,0x70,0x02,' +` 0x87,0x02,0x20,0x05,0x09,0x05,0x14,0x08,' +` 0x8a,0x07,0x21,0x0b,0x97,0x09,0xa4,0x0d,' +` 0xb9,0x0c,0x25,0x12,0x5c,0x09,0xf5,0x11,' +` 0x75,0x04,0x51,0x1e,0x62,0x44,0x23,0xfe,' +` 0x8f,0x0e,0x4f,0x03,0xf1,0x08,0xd2,0xff,' +` 0xe9,0x05,0x94,0x02,0xef,0x04,0xd3,0x01,' +` 0xb6,0x03,0x66,0x01,0xc9,0x02,0xdd,0x00,' +` 0x8b,0x01,0x36,0x00,0xde,0x00,0xe9,0xff,' +` 0x25,0x00,0x45,0xff,0xc3,0xff,0x5f,0xff,' +` 0xae,0xff,0x6e,0xff,0xb3,0xff,0xaf,0xff,' +` 0xdb,0xff,0xd2,0xff,0xeb,0xff,0xee,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,' +` 0x1e,0x00,0x31,0x00,0x6f,0x00,0x71,0x00,' +` 0xef,0x00,0xd2,0x00,0x71,0x01,0xfb,0x00,' +` 0xae,0x01,0x74,0x00,0x5c,0x01,0xd9,0xfe,' +` 0x65,0xff,0xd2,0xfb,0xa7,0xfc,0xe4,0xf6,' +` 0xc1,0xf6,0x3e,0xf0,0xf4,0xf1,0xc1,0xe9,' +` 0xb1,0xed,0x2d,0xe4,0x63,0xeb,0xfc,0xd9,' +` 0xd9,0xe8,0x96,0xdb,0x9b,0xf3,0xf0,0xcf,' +` 0xac,0x26,0x54,0x4e,0x2d,0xd2,0x7c,0x00,' +` 0xc3,0xe6,0xa8,0xff,0xf5,0xf5,0xab,0xfe,' +` 0xa0,0xf4,0x08,0xff,0x9e,0xf8,0xd9,0xff,' +` 0xe2,0xfa,0x5a,0x00,0xb1,0xfc,0x6f,0x00,' +` 0xd8,0xfd,0xd4,0x00,0xbf,0xfe,0x94,0x00,' +` 0xd0,0xff,0xfc,0x00,0xdf,0xff,0x9b,0x00,' +` 0xc0,0xff,0x49,0x00,0xfa,0xff,0x39,0x00,' +` 0xfa,0xff,0x16,0x00,0xfe,0xff,0x06,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0xfe,0xff,0x0e,0x00,0xfc,0xff,0x28,0x00,' +` 0xfa,0xff,0x1d,0x00,0xd4,0xff,0x68,0x00,' +` 0xf5,0xff,0xaf,0x00,0xdc,0xff,0x00,0x00,' +` 0x12,0xff,0x0f,0x00,0x2b,0xfe,0x73,0xff,' +` 0x2f,0xfd,0xff,0xfe,0x7d,0xfb,0x24,0xfe,' +` 0x5b,0xf9,0xbe,0xfc,0x8c,0xf5,0xc0,0xfc,' +` 0xca,0xf7,0xa8,0xf9,0x7a,0xea,0x68,0xf9,' +` 0x73,0xda,0xec,0x63,0x68,0x02,0xde,0xda,' +` 0xb0,0xec,0xc3,0xdf,0x15,0xe4,0x32,0xde,' +` 0x1b,0xea,0x30,0xe6,0xc8,0xec,0x9e,0xeb,' +` 0x9a,0xf1,0xd4,0xf1,0xbc,0xf6,0x87,0xf8,' +` 0xaa,0xfc,0xe7,0xfc,0x78,0xff,0xc2,0xff,' +` 0x71,0x01,0xf7,0x00,0xc1,0x01,0x4d,0x01,' +` 0x75,0x01,0x01,0x01,0xec,0x00,0x86,0x00,' +` 0x70,0x00,0x38,0x00,0x1e,0x00,0x07,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf9,0xff,0xf2,0xff,' +` 0xe9,0xff,0xde,0xff,0xd5,0xff,0xc5,0xff,' +` 0xa3,0xff,0x9b,0xff,0x9b,0xff,0xa1,0xff,' +` 0x9c,0xff,0xa8,0xff,0x08,0x00,0x6d,0x00,' +` 0x90,0x00,0xe4,0x00,0x24,0x01,0xd8,0x01,' +` 0x27,0x02,0x99,0x02,0xd8,0x02,0x6b,0x03,' +` 0xb9,0x03,0xc0,0x04,0x9b,0x03,0x07,0x03,' +` 0xb2,0x06,0xd4,0x07,0xbc,0x08,0xcd,0x09,' +` 0xdb,0x4a,0xe6,0x0b,0x97,0x0c,0xf1,0x0c,' +` 0x28,0x0d,0xb7,0x0f,0x17,0x0e,0x74,0x0b,' +` 0xde,0x0a,0x78,0x09,0x44,0x08,0xbc,0x06,' +` 0x74,0x05,0x05,0x04,0xb3,0x02,0xa0,0x01,' +` 0xec,0x00,0x38,0x00,0xfd,0xff,0xaf,0xff,' +` 0x80,0xff,0x71,0xff,0x7b,0xff,0xa7,0xff,' +` 0xba,0xff,0xbd,0xff,0xcc,0xff,0xdf,0xff,' +` 0xed,0xff,0xf8,0xff,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf8,0xff,' +` 0xeb,0xff,0xda,0xff,0xc9,0xff,0xae,0xff,' +` 0x8d,0xff,0x5c,0xff,0x29,0xff,0x03,0xff,' +` 0xe0,0xfe,0x9f,0xfe,0x93,0xfe,0x6f,0xfe,' +` 0x57,0xfe,0x4e,0xfe,0xc8,0xfe,0xc5,0xfe,' +` 0xf8,0xfe,0x3a,0xff,0xfe,0xff,0x21,0x00,' +` 0x2e,0x01,0x50,0x00,0x96,0xff,0xb6,0x00,' +` 0x1c,0x02,0x08,0x06,0x94,0x07,0x1d,0x09,' +` 0x7e,0x4a,0xbf,0x0b,0xd4,0x0c,0x78,0x0d,' +` 0x3b,0x10,0x15,0x10,0x8d,0x0f,0xf4,0x0c,' +` 0x34,0x0a,0x08,0x09,0x46,0x07,0xa9,0x05,' +` 0xf4,0x03,0xda,0x02,0xb5,0x01,0x47,0x01,' +` 0xa6,0x00,0x23,0x00,0xe5,0xff,0xf2,0xff,' +` 0xc9,0xff,0xbb,0xff,0xa0,0xff,0xb0,0xff,' +` 0xb8,0xff,0xcb,0xff,0xd8,0xff,0xe8,0xff,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfc,0xff,0xf8,0xff,0xe3,0xff,' +` 0xe6,0xff,0xae,0xff,0xe2,0xff,0xa8,0xff,' +` 0x36,0x00,0xf0,0xff,0x0a,0x01,0x56,0x00,' +` 0x2f,0x01,0x92,0x00,0x7f,0x02,0x90,0x01,' +` 0xe5,0x03,0xfc,0x01,0x7f,0x05,0xfb,0x02,' +` 0x7b,0x06,0x72,0x02,0x53,0x07,0x18,0x01,' +` 0x37,0x06,0xfa,0xfd,0xee,0x09,0x2e,0xfc,' +` 0xab,0x07,0x18,0xee,0x7f,0x01,0xd6,0xd5,' +` 0x14,0x57,0x9b,0x1b,0x70,0xd1,0x10,0xf1,' +` 0x42,0xd6,0x94,0xe3,0x2e,0xd8,0xe8,0xe4,' +` 0x25,0xe3,0x82,0xec,0xfd,0xe9,0x95,0xf2,' +` 0x36,0xf3,0x62,0xf9,0xe8,0xf8,0xf7,0xfd,' +` 0xcc,0xfd,0xb9,0x00,0x28,0x00,0xc7,0x01,' +` 0x13,0x01,0xfe,0x01,0x28,0x01,0x8f,0x01,' +` 0x04,0x01,0x13,0x01,0xa8,0x00,0x8e,0x00,' +` 0x46,0x00,0x23,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1e,0x00,0x50,0x00,0x7e,0x00,0xd0,0x00,' +` 0xec,0x00,0x59,0x01,0x4a,0x01,0xbe,0x01,' +` 0x6f,0x01,0x1c,0x02,0x14,0x01,0xa4,0x01,' +` 0xe2,0xff,0x0b,0x00,0x07,0xfd,0x54,0xfc,' +` 0x99,0xf7,0x93,0xf7,0xfe,0xf0,0x7a,0xef,' +` 0x69,0xe8,0x14,0xea,0xbd,0xe0,0xe0,0xe0,' +` 0xda,0xd8,0x9f,0xe1,0x2a,0xdb,0x35,0xef,' +` 0xf5,0xd3,0x00,0x63,0xb4,0x09,0x22,0xe5,' +` 0x99,0xfc,0xee,0xf6,0xc2,0x05,0x36,0x00,' +` 0xf2,0x06,0x12,0xff,0xd3,0x05,0x58,0x02,' +` 0x63,0x06,0xee,0x02,0xbf,0x05,0x32,0x03,' +` 0x64,0x04,0x0b,0x02,0x3d,0x03,0x6c,0x01,' +` 0xd8,0x01,0x75,0x00,0xe3,0x00,0x84,0x00,' +` 0x96,0x00,0xf0,0xff,0x06,0x00,0xbd,0xff,' +` 0xda,0xff,0xce,0xff,0xf0,0xff,0xf3,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xdd,0xff,0xdd,0xff,' +` 0x9b,0xff,0xb9,0xff,0x47,0xff,0xa4,0xff,' +` 0x09,0xff,0x04,0x00,0x2c,0xff,0x98,0x00,' +` 0x0c,0xff,0xba,0x01,0x9e,0x00,0x42,0x04,' +` 0x79,0x02,0x96,0x08,0xb0,0x06,0x69,0x0f,' +` 0x81,0x0c,0xbe,0x16,0x55,0x11,0x3f,0x22,' +` 0x51,0x18,0x08,0x29,0x7d,0x12,0x49,0x29,' +` 0x5c,0xfe,0x58,0x65,0x1a,0x67,0x13,0xf5,' +` 0x98,0x1e,0xd2,0xfc,0xec,0x0a,0x82,0xf9,' +` 0xc5,0x04,0x7f,0xfd,0x4e,0x05,0xa5,0xfc,' +` 0x43,0x02,0x70,0xfb,0xdd,0xff,0x96,0xfb,' +` 0xad,0xfe,0xe6,0xfa,0xe2,0xfd,0xc7,0xfb,' +` 0xe9,0xfd,0x87,0xfc,0x67,0xfe,0x77,0xfd,' +` 0xc9,0xfe,0x78,0xfe,0x64,0xff,0x34,0xff,' +` 0xb6,0xff,0xa0,0xff,0xec,0xff,0xe8,0xff,' +` 0xfb,0xff,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xdd,0xff,0xdd,0xff,0x9b,0xff,0xb9,0xff,' +` 0x47,0xff,0xa4,0xff,0x09,0xff,0x04,0x00,' +` 0x2c,0xff,0x98,0x00,0x0c,0xff,0xba,0x01,' +` 0x9e,0x00,0x42,0x04,0x79,0x02,0x96,0x08,' +` 0xb0,0x06,0x69,0x0f,0x81,0x0c,0xbe,0x16,' +` 0x55,0x11,0x3f,0x22,0x51,0x18,0x08,0x29,' +` 0x7d,0x12,0x49,0x29,0x5c,0xfe,0x58,0x65,' +` 0x1a,0x67,0x13,0xf5,0x98,0x1e,0xd2,0xfc,' +` 0xec,0x0a,0x82,0xf9,0xc5,0x04,0x7f,0xfd,' +` 0x4e,0x05,0xa5,0xfc,0x43,0x02,0x70,0xfb,' +` 0xdd,0xff,0x96,0xfb,0xad,0xfe,0xe6,0xfa,' +` 0xe2,0xfd,0xc7,0xfb,0xe9,0xfd,0x87,0xfc,' +` 0x67,0xfe,0x77,0xfd,0xc9,0xfe,0x78,0xfe,' +` 0x64,0xff,0x34,0xff,0xb6,0xff,0xa0,0xff,' +` 0xec,0xff,0xe8,0xff,0xfb,0xff,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x50,0x00,' +` 0x7e,0x00,0xd0,0x00,0xec,0x00,0x59,0x01,' +` 0x4a,0x01,0xbe,0x01,0x6f,0x01,0x1c,0x02,' +` 0x14,0x01,0xa4,0x01,0xe2,0xff,0x0b,0x00,' +` 0x07,0xfd,0x54,0xfc,0x99,0xf7,0x93,0xf7,' +` 0xfe,0xf0,0x7a,0xef,0x69,0xe8,0x14,0xea,' +` 0xbd,0xe0,0xe0,0xe0,0xda,0xd8,0x9f,0xe1,' +` 0x2a,0xdb,0x35,0xef,0xf5,0xd3,0x00,0x63,' +` 0xb4,0x09,0x22,0xe5,0x99,0xfc,0xee,0xf6,' +` 0xc2,0x05,0x36,0x00,0xf2,0x06,0x12,0xff,' +` 0xd3,0x05,0x58,0x02,0x63,0x06,0xee,0x02,' +` 0xbf,0x05,0x32,0x03,0x64,0x04,0x0b,0x02,' +` 0x3d,0x03,0x6c,0x01,0xd8,0x01,0x75,0x00,' +` 0xe3,0x00,0x84,0x00,0x96,0x00,0xf0,0xff,' +` 0x06,0x00,0xbd,0xff,0xda,0xff,0xce,0xff,' +` 0xf0,0xff,0xf3,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,' +` 0xf8,0xff,0xe3,0xff,0xe6,0xff,0xae,0xff,' +` 0xe2,0xff,0xa8,0xff,0x36,0x00,0xf0,0xff,' +` 0x0a,0x01,0x56,0x00,0x2f,0x01,0x92,0x00,' +` 0x7f,0x02,0x90,0x01,0xe5,0x03,0xfc,0x01,' +` 0x7f,0x05,0xfb,0x02,0x7b,0x06,0x72,0x02,' +` 0x53,0x07,0x18,0x01,0x37,0x06,0xfa,0xfd,' +` 0xee,0x09,0x2e,0xfc,0xab,0x07,0x18,0xee,' +` 0x7f,0x01,0xd6,0xd5,0x14,0x57,0x9b,0x1b,' +` 0x70,0xd1,0x10,0xf1,0x42,0xd6,0x94,0xe3,' +` 0x2e,0xd8,0xe8,0xe4,0x25,0xe3,0x82,0xec,' +` 0xfd,0xe9,0x95,0xf2,0x36,0xf3,0x62,0xf9,' +` 0xe8,0xf8,0xf7,0xfd,0xcc,0xfd,0xb9,0x00,' +` 0x28,0x00,0xc7,0x01,0x13,0x01,0xfe,0x01,' +` 0x28,0x01,0x8f,0x01,0x04,0x01,0x13,0x01,' +` 0xa8,0x00,0x8e,0x00,0x46,0x00,0x23,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf8,0xff,0xeb,0xff,0xda,0xff,' +` 0xc9,0xff,0xae,0xff,0x8d,0xff,0x5c,0xff,' +` 0x29,0xff,0x03,0xff,0xe0,0xfe,0x9f,0xfe,' +` 0x93,0xfe,0x6f,0xfe,0x57,0xfe,0x4e,0xfe,' +` 0xc8,0xfe,0xc5,0xfe,0xf8,0xfe,0x3a,0xff,' +` 0xfe,0xff,0x21,0x00,0x2e,0x01,0x50,0x00,' +` 0x96,0xff,0xb6,0x00,0x1c,0x02,0x08,0x06,' +` 0x94,0x07,0x1d,0x09,0x7e,0x4a,0xbf,0x0b,' +` 0xd4,0x0c,0x78,0x0d,0x3b,0x10,0x15,0x10,' +` 0x8d,0x0f,0xf4,0x0c,0x34,0x0a,0x08,0x09,' +` 0x46,0x07,0xa9,0x05,0xf4,0x03,0xda,0x02,' +` 0xb5,0x01,0x47,0x01,0xa6,0x00,0x23,0x00,' +` 0xe5,0xff,0xf2,0xff,0xc9,0xff,0xbb,0xff,' +` 0xa0,0xff,0xb0,0xff,0xb8,0xff,0xcb,0xff,' +` 0xd8,0xff,0xe8,0xff,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0x75,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_pm0_30deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_pm0_30deg_48khz.m4 new file mode 100644 index 000000000000..52dbec9f69e7 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_0mm36mm146mm182mm_pm0_30deg_48khz.m4 @@ -0,0 +1,493 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x2c,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x2c,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x64,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x05,0x00,0x0a,0x00,0x0e,0x00,0x16,0x00,' +` 0x1b,0x00,0x29,0x00,0x2f,0x00,0x42,0x00,' +` 0x48,0x00,0x62,0x00,0x69,0x00,0x89,0x00,' +` 0x90,0x00,0xb8,0x00,0xbc,0x00,0xed,0x00,' +` 0xee,0x00,0x27,0x01,0x23,0x01,0x65,0x01,' +` 0x5b,0x01,0xa8,0x01,0x95,0x01,0xec,0x01,' +` 0xcf,0x01,0x32,0x02,0x07,0x02,0x78,0x02,' +` 0x3d,0x02,0xbb,0x02,0x89,0x02,0x04,0x03,' +` 0x93,0x02,0x43,0x03,0xb3,0x02,0x83,0x03,' +` 0xc7,0x02,0xc4,0x03,0xc9,0x02,0x0b,0x04,' +` 0xaf,0x02,0x6a,0x04,0x58,0x02,0x20,0x05,' +` 0x24,0x01,0x98,0x08,0xf8,0x42,0x33,0xff,' +` 0xc2,0x05,0xfe,0x01,0x95,0x04,0x86,0x02,' +` 0x1b,0x04,0xae,0x02,0xc8,0x03,0xb2,0x02,' +` 0x82,0x03,0xa1,0x02,0x3f,0x03,0x82,0x02,' +` 0xfe,0x02,0x54,0x02,0x9c,0x02,0x34,0x02,' +` 0x6e,0x02,0xfd,0x01,0x2a,0x02,0xc5,0x01,' +` 0xe5,0x01,0x8d,0x01,0xa1,0x01,0x54,0x01,' +` 0x60,0x01,0x1d,0x01,0x23,0x01,0xe9,0x00,' +` 0xea,0x00,0xb9,0x00,0xb7,0x00,0x8e,0x00,' +` 0x88,0x00,0x68,0x00,0x61,0x00,0x48,0x00,' +` 0x41,0x00,0x2e,0x00,0x28,0x00,0x1b,0x00,' +` 0x16,0x00,0x0e,0x00,0x0a,0x00,0x05,0x00,' +` 0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x64,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfa,0xff,0xf5,0xff,0xed,0xff,' +` 0xe3,0xff,0xd6,0xff,0xc6,0xff,0xb3,0xff,' +` 0x9d,0xff,0x84,0xff,0x67,0xff,0x47,0xff,' +` 0x23,0xff,0xfc,0xfe,0xd1,0xfe,0xa3,0xfe,' +` 0x72,0xfe,0x3f,0xfe,0x09,0xfe,0xd3,0xfd,' +` 0x98,0xfd,0x5e,0xfd,0x1f,0xfd,0xe3,0xfc,' +` 0xa2,0xfc,0x64,0xfc,0x22,0xfc,0xe5,0xfb,' +` 0xa3,0xfb,0x6a,0xfb,0x26,0xfb,0xf7,0xfa,' +` 0x7d,0xfa,0x72,0xfa,0x4f,0xfa,0x15,0xfa,' +` 0xec,0xf9,0xbc,0xf9,0x98,0xf9,0x71,0xf9,' +` 0x52,0xf9,0x34,0xf9,0x1d,0xf9,0x07,0xf9,' +` 0xf8,0xf8,0xeb,0xf8,0xe4,0xf8,0xe0,0xf8,' +` 0xdd,0x78,0xed,0xf8,0xf5,0xf8,0x03,0xf9,' +` 0x14,0xf9,0x2b,0xf9,0x44,0xf9,0x63,0xf9,' +` 0x83,0xf9,0xab,0xf9,0xd1,0xf9,0x00,0xfa,' +` 0x2b,0xfa,0x62,0xfa,0x8e,0xfa,0xd5,0xfa,' +` 0x39,0xfb,0x35,0xfb,0x7d,0xfb,0xb3,0xfb,' +` 0xf6,0xfb,0x31,0xfc,0x72,0xfc,0xae,0xfc,' +` 0xee,0xfc,0x2a,0xfd,0x67,0xfd,0xa0,0xfd,' +` 0xda,0xfd,0x10,0xfe,0x45,0xfe,0x76,0xfe,' +` 0xa6,0xfe,0xd2,0xfe,0xfd,0xfe,0x24,0xff,' +` 0x48,0xff,0x67,0xff,0x84,0xff,0x9d,0xff,' +` 0xb4,0xff,0xc6,0xff,0xd6,0xff,0xe3,0xff,' +` 0xed,0xff,0xf4,0xff,0xfa,0xff,0xfd,0xff,' +` 0xff,0xff,0x00,0x00,0x64,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfa,0xff,' +` 0xf5,0xff,0xed,0xff,0xe3,0xff,0xd6,0xff,' +` 0xc6,0xff,0xb3,0xff,0x9d,0xff,0x84,0xff,' +` 0x67,0xff,0x47,0xff,0x23,0xff,0xfc,0xfe,' +` 0xd1,0xfe,0xa3,0xfe,0x72,0xfe,0x3f,0xfe,' +` 0x09,0xfe,0xd3,0xfd,0x98,0xfd,0x5e,0xfd,' +` 0x1f,0xfd,0xe3,0xfc,0xa2,0xfc,0x64,0xfc,' +` 0x22,0xfc,0xe5,0xfb,0xa3,0xfb,0x6a,0xfb,' +` 0x26,0xfb,0xf7,0xfa,0x7d,0xfa,0x72,0xfa,' +` 0x4f,0xfa,0x15,0xfa,0xec,0xf9,0xbc,0xf9,' +` 0x98,0xf9,0x71,0xf9,0x52,0xf9,0x34,0xf9,' +` 0x1d,0xf9,0x07,0xf9,0xf8,0xf8,0xeb,0xf8,' +` 0xe4,0xf8,0xe0,0xf8,0xdd,0x78,0xed,0xf8,' +` 0xf5,0xf8,0x03,0xf9,0x14,0xf9,0x2b,0xf9,' +` 0x44,0xf9,0x63,0xf9,0x83,0xf9,0xab,0xf9,' +` 0xd1,0xf9,0x00,0xfa,0x2b,0xfa,0x62,0xfa,' +` 0x8e,0xfa,0xd5,0xfa,0x39,0xfb,0x35,0xfb,' +` 0x7d,0xfb,0xb3,0xfb,0xf6,0xfb,0x31,0xfc,' +` 0x72,0xfc,0xae,0xfc,0xee,0xfc,0x2a,0xfd,' +` 0x67,0xfd,0xa0,0xfd,0xda,0xfd,0x10,0xfe,' +` 0x45,0xfe,0x76,0xfe,0xa6,0xfe,0xd2,0xfe,' +` 0xfd,0xfe,0x24,0xff,0x48,0xff,0x67,0xff,' +` 0x84,0xff,0x9d,0xff,0xb4,0xff,0xc6,0xff,' +` 0xd6,0xff,0xe3,0xff,0xed,0xff,0xf4,0xff,' +` 0xfa,0xff,0xfd,0xff,0xff,0xff,0x00,0x00,' +` 0x64,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x05,0x00,0x0a,0x00,' +` 0x0e,0x00,0x16,0x00,0x1b,0x00,0x29,0x00,' +` 0x2f,0x00,0x42,0x00,0x48,0x00,0x62,0x00,' +` 0x69,0x00,0x89,0x00,0x90,0x00,0xb8,0x00,' +` 0xbc,0x00,0xed,0x00,0xee,0x00,0x27,0x01,' +` 0x23,0x01,0x65,0x01,0x5b,0x01,0xa8,0x01,' +` 0x95,0x01,0xec,0x01,0xcf,0x01,0x32,0x02,' +` 0x07,0x02,0x78,0x02,0x3d,0x02,0xbb,0x02,' +` 0x89,0x02,0x04,0x03,0x93,0x02,0x43,0x03,' +` 0xb3,0x02,0x83,0x03,0xc7,0x02,0xc4,0x03,' +` 0xc9,0x02,0x0b,0x04,0xaf,0x02,0x6a,0x04,' +` 0x58,0x02,0x20,0x05,0x24,0x01,0x98,0x08,' +` 0xf8,0x42,0x33,0xff,0xc2,0x05,0xfe,0x01,' +` 0x95,0x04,0x86,0x02,0x1b,0x04,0xae,0x02,' +` 0xc8,0x03,0xb2,0x02,0x82,0x03,0xa1,0x02,' +` 0x3f,0x03,0x82,0x02,0xfe,0x02,0x54,0x02,' +` 0x9c,0x02,0x34,0x02,0x6e,0x02,0xfd,0x01,' +` 0x2a,0x02,0xc5,0x01,0xe5,0x01,0x8d,0x01,' +` 0xa1,0x01,0x54,0x01,0x60,0x01,0x1d,0x01,' +` 0x23,0x01,0xe9,0x00,0xea,0x00,0xb9,0x00,' +` 0xb7,0x00,0x8e,0x00,0x88,0x00,0x68,0x00,' +` 0x61,0x00,0x48,0x00,0x41,0x00,0x2e,0x00,' +` 0x28,0x00,0x1b,0x00,0x16,0x00,0x0e,0x00,' +` 0x0a,0x00,0x05,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x64,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x05,0x00,0x0a,0x00,0x0e,0x00,0x16,0x00,' +` 0x1b,0x00,0x29,0x00,0x2f,0x00,0x42,0x00,' +` 0x48,0x00,0x62,0x00,0x69,0x00,0x89,0x00,' +` 0x90,0x00,0xb8,0x00,0xbc,0x00,0xed,0x00,' +` 0xee,0x00,0x27,0x01,0x23,0x01,0x65,0x01,' +` 0x5b,0x01,0xa8,0x01,0x95,0x01,0xec,0x01,' +` 0xcf,0x01,0x32,0x02,0x07,0x02,0x78,0x02,' +` 0x3d,0x02,0xbb,0x02,0x89,0x02,0x04,0x03,' +` 0x93,0x02,0x43,0x03,0xb3,0x02,0x83,0x03,' +` 0xc7,0x02,0xc4,0x03,0xc9,0x02,0x0b,0x04,' +` 0xaf,0x02,0x6a,0x04,0x58,0x02,0x20,0x05,' +` 0x24,0x01,0x98,0x08,0xf8,0x42,0x33,0xff,' +` 0xc2,0x05,0xfe,0x01,0x95,0x04,0x86,0x02,' +` 0x1b,0x04,0xae,0x02,0xc8,0x03,0xb2,0x02,' +` 0x82,0x03,0xa1,0x02,0x3f,0x03,0x82,0x02,' +` 0xfe,0x02,0x54,0x02,0x9c,0x02,0x34,0x02,' +` 0x6e,0x02,0xfd,0x01,0x2a,0x02,0xc5,0x01,' +` 0xe5,0x01,0x8d,0x01,0xa1,0x01,0x54,0x01,' +` 0x60,0x01,0x1d,0x01,0x23,0x01,0xe9,0x00,' +` 0xea,0x00,0xb9,0x00,0xb7,0x00,0x8e,0x00,' +` 0x88,0x00,0x68,0x00,0x61,0x00,0x48,0x00,' +` 0x41,0x00,0x2e,0x00,0x28,0x00,0x1b,0x00,' +` 0x16,0x00,0x0e,0x00,0x0a,0x00,0x05,0x00,' +` 0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x64,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfa,0xff,0xf5,0xff,0xed,0xff,' +` 0xe3,0xff,0xd6,0xff,0xc6,0xff,0xb3,0xff,' +` 0x9d,0xff,0x84,0xff,0x67,0xff,0x47,0xff,' +` 0x23,0xff,0xfc,0xfe,0xd1,0xfe,0xa3,0xfe,' +` 0x72,0xfe,0x3f,0xfe,0x09,0xfe,0xd3,0xfd,' +` 0x98,0xfd,0x5e,0xfd,0x1f,0xfd,0xe3,0xfc,' +` 0xa2,0xfc,0x64,0xfc,0x22,0xfc,0xe5,0xfb,' +` 0xa3,0xfb,0x6a,0xfb,0x26,0xfb,0xf7,0xfa,' +` 0x7d,0xfa,0x72,0xfa,0x4f,0xfa,0x15,0xfa,' +` 0xec,0xf9,0xbc,0xf9,0x98,0xf9,0x71,0xf9,' +` 0x52,0xf9,0x34,0xf9,0x1d,0xf9,0x07,0xf9,' +` 0xf8,0xf8,0xeb,0xf8,0xe4,0xf8,0xe0,0xf8,' +` 0xdd,0x78,0xed,0xf8,0xf5,0xf8,0x03,0xf9,' +` 0x14,0xf9,0x2b,0xf9,0x44,0xf9,0x63,0xf9,' +` 0x83,0xf9,0xab,0xf9,0xd1,0xf9,0x00,0xfa,' +` 0x2b,0xfa,0x62,0xfa,0x8e,0xfa,0xd5,0xfa,' +` 0x39,0xfb,0x35,0xfb,0x7d,0xfb,0xb3,0xfb,' +` 0xf6,0xfb,0x31,0xfc,0x72,0xfc,0xae,0xfc,' +` 0xee,0xfc,0x2a,0xfd,0x67,0xfd,0xa0,0xfd,' +` 0xda,0xfd,0x10,0xfe,0x45,0xfe,0x76,0xfe,' +` 0xa6,0xfe,0xd2,0xfe,0xfd,0xfe,0x24,0xff,' +` 0x48,0xff,0x67,0xff,0x84,0xff,0x9d,0xff,' +` 0xb4,0xff,0xc6,0xff,0xd6,0xff,0xe3,0xff,' +` 0xed,0xff,0xf4,0xff,0xfa,0xff,0xfd,0xff,' +` 0xff,0xff,0x00,0x00,0x64,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfa,0xff,' +` 0xf5,0xff,0xed,0xff,0xe3,0xff,0xd6,0xff,' +` 0xc6,0xff,0xb3,0xff,0x9d,0xff,0x84,0xff,' +` 0x67,0xff,0x47,0xff,0x23,0xff,0xfc,0xfe,' +` 0xd1,0xfe,0xa3,0xfe,0x72,0xfe,0x3f,0xfe,' +` 0x09,0xfe,0xd3,0xfd,0x98,0xfd,0x5e,0xfd,' +` 0x1f,0xfd,0xe3,0xfc,0xa2,0xfc,0x64,0xfc,' +` 0x22,0xfc,0xe5,0xfb,0xa3,0xfb,0x6a,0xfb,' +` 0x26,0xfb,0xf7,0xfa,0x7d,0xfa,0x72,0xfa,' +` 0x4f,0xfa,0x15,0xfa,0xec,0xf9,0xbc,0xf9,' +` 0x98,0xf9,0x71,0xf9,0x52,0xf9,0x34,0xf9,' +` 0x1d,0xf9,0x07,0xf9,0xf8,0xf8,0xeb,0xf8,' +` 0xe4,0xf8,0xe0,0xf8,0xdd,0x78,0xed,0xf8,' +` 0xf5,0xf8,0x03,0xf9,0x14,0xf9,0x2b,0xf9,' +` 0x44,0xf9,0x63,0xf9,0x83,0xf9,0xab,0xf9,' +` 0xd1,0xf9,0x00,0xfa,0x2b,0xfa,0x62,0xfa,' +` 0x8e,0xfa,0xd5,0xfa,0x39,0xfb,0x35,0xfb,' +` 0x7d,0xfb,0xb3,0xfb,0xf6,0xfb,0x31,0xfc,' +` 0x72,0xfc,0xae,0xfc,0xee,0xfc,0x2a,0xfd,' +` 0x67,0xfd,0xa0,0xfd,0xda,0xfd,0x10,0xfe,' +` 0x45,0xfe,0x76,0xfe,0xa6,0xfe,0xd2,0xfe,' +` 0xfd,0xfe,0x24,0xff,0x48,0xff,0x67,0xff,' +` 0x84,0xff,0x9d,0xff,0xb4,0xff,0xc6,0xff,' +` 0xd6,0xff,0xe3,0xff,0xed,0xff,0xf4,0xff,' +` 0xfa,0xff,0xfd,0xff,0xff,0xff,0x00,0x00,' +` 0x64,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x05,0x00,0x0a,0x00,' +` 0x0e,0x00,0x16,0x00,0x1b,0x00,0x29,0x00,' +` 0x2f,0x00,0x42,0x00,0x48,0x00,0x62,0x00,' +` 0x69,0x00,0x89,0x00,0x90,0x00,0xb8,0x00,' +` 0xbc,0x00,0xed,0x00,0xee,0x00,0x27,0x01,' +` 0x23,0x01,0x65,0x01,0x5b,0x01,0xa8,0x01,' +` 0x95,0x01,0xec,0x01,0xcf,0x01,0x32,0x02,' +` 0x07,0x02,0x78,0x02,0x3d,0x02,0xbb,0x02,' +` 0x89,0x02,0x04,0x03,0x93,0x02,0x43,0x03,' +` 0xb3,0x02,0x83,0x03,0xc7,0x02,0xc4,0x03,' +` 0xc9,0x02,0x0b,0x04,0xaf,0x02,0x6a,0x04,' +` 0x58,0x02,0x20,0x05,0x24,0x01,0x98,0x08,' +` 0xf8,0x42,0x33,0xff,0xc2,0x05,0xfe,0x01,' +` 0x95,0x04,0x86,0x02,0x1b,0x04,0xae,0x02,' +` 0xc8,0x03,0xb2,0x02,0x82,0x03,0xa1,0x02,' +` 0x3f,0x03,0x82,0x02,0xfe,0x02,0x54,0x02,' +` 0x9c,0x02,0x34,0x02,0x6e,0x02,0xfd,0x01,' +` 0x2a,0x02,0xc5,0x01,0xe5,0x01,0x8d,0x01,' +` 0xa1,0x01,0x54,0x01,0x60,0x01,0x1d,0x01,' +` 0x23,0x01,0xe9,0x00,0xea,0x00,0xb9,0x00,' +` 0xb7,0x00,0x8e,0x00,0x88,0x00,0x68,0x00,' +` 0x61,0x00,0x48,0x00,0x41,0x00,0x2e,0x00,' +` 0x28,0x00,0x1b,0x00,0x16,0x00,0x0e,0x00,' +` 0x0a,0x00,0x05,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x64,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,' +` 0x05,0x00,0x08,0x00,0x0a,0x00,0x0e,0x00,' +` 0x16,0x00,0x1c,0x00,0x22,0x00,0x2a,0x00,' +` 0x31,0x00,0x3a,0x00,0x42,0x00,0x4d,0x00,' +` 0x56,0x00,0x64,0x00,0x6e,0x00,0x7d,0x00,' +` 0x88,0x00,0x9a,0x00,0xa7,0x00,0xbd,0x00,' +` 0xcb,0x00,0xe6,0x00,0xf4,0x00,0x15,0x01,' +` 0x20,0x01,0x4f,0x01,0xd3,0x00,0xae,0x00,' +` 0xd2,0x00,0xe6,0x00,0xfa,0x00,0xc1,0x01,' +` 0x20,0x02,0x2b,0x02,0x5a,0x02,0x71,0x02,' +` 0x9a,0x02,0xb4,0x02,0xda,0x02,0xf5,0x02,' +` 0x1e,0x03,0x3f,0x03,0x64,0x03,0x83,0x03,' +` 0x9f,0x43,0xbe,0x03,0xd9,0x03,0xee,0x03,' +` 0x02,0x04,0x11,0x04,0x15,0x04,0x18,0x04,' +` 0x12,0x04,0x0f,0x04,0x00,0x04,0xf8,0x03,' +` 0xdb,0x03,0xe6,0x03,0x7e,0x04,0x5f,0x04,' +` 0x35,0x04,0x14,0x04,0xc2,0x03,0x04,0x03,' +` 0xe3,0x02,0xb2,0x02,0x8c,0x02,0x5b,0x02,' +` 0x31,0x02,0x00,0x02,0xd7,0x01,0xa8,0x01,' +` 0x7e,0x01,0x52,0x01,0x2c,0x01,0x05,0x01,' +` 0xe3,0x00,0xc1,0x00,0xa4,0x00,0x88,0x00,' +` 0x70,0x00,0x5a,0x00,0x48,0x00,0x37,0x00,' +` 0x2a,0x00,0x1c,0x00,0x13,0x00,0x0d,0x00,' +` 0x64,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0x01,0x00,0xfa,0xff,0x02,0x00,' +` 0xf1,0xff,0x02,0x00,0xe1,0xff,0x04,0x00,' +` 0xd3,0xff,0x04,0x00,0xb6,0xff,0x00,0x00,' +` 0x92,0xff,0xfd,0xff,0x67,0xff,0xf8,0xff,' +` 0x33,0xff,0xf0,0xff,0xf2,0xfe,0xe5,0xff,' +` 0xa4,0xfe,0xd6,0xff,0x3f,0xfe,0xba,0xff,' +` 0xc4,0xfd,0x9a,0xff,0x34,0xfd,0x80,0xff,' +` 0x83,0xfc,0xc3,0xff,0x6e,0xfd,0xad,0x00,' +` 0xa2,0xfc,0xd0,0x00,0x36,0xfb,0xeb,0xfe,' +` 0x22,0xf9,0x24,0xff,0xb8,0xf7,0x90,0xff,' +` 0xed,0xf5,0x86,0x00,0x55,0xf3,0xc1,0x02,' +` 0x7b,0xee,0x39,0x09,0xe3,0xde,0x28,0x44,' +` 0xf9,0x4f,0xae,0xdc,0x77,0x08,0x4d,0xec,' +` 0xa5,0x00,0x5d,0xf0,0x99,0xfd,0x56,0xf2,' +` 0x06,0xfc,0x95,0xf3,0x28,0xfb,0x89,0xf4,' +` 0xc6,0xfa,0x69,0xf4,0xc4,0xf8,0xde,0xf4,' +` 0x0e,0xf9,0xc7,0xf5,0x63,0xfa,0x4f,0xf8,' +` 0x1a,0xfb,0x27,0xf9,0x99,0xfb,0x0a,0xfa,' +` 0x20,0xfc,0xea,0xfa,0xaf,0xfc,0xc6,0xfb,' +` 0x45,0xfd,0x9b,0xfc,0xd6,0xfd,0x5b,0xfd,' +` 0x5a,0xfe,0x04,0xfe,0xcd,0xfe,0x93,0xfe,' +` 0x2d,0xff,0x08,0xff,0x78,0xff,0x61,0xff,' +` 0xb5,0xff,0xb6,0xff,0xe1,0xff,0xdc,0xff,' +` 0xf4,0xff,0xf3,0xff,0x64,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf9,0xff,0xf6,0xff,0xe9,0xff,0xe4,0xff,' +` 0xcd,0xff,0xc1,0xff,0x88,0xff,0x81,0xff,' +` 0x3d,0xff,0x35,0xff,0xd9,0xfe,0xd3,0xfe,' +` 0x5c,0xfe,0x5d,0xfe,0xc6,0xfd,0xd3,0xfd,' +` 0x1b,0xfd,0x39,0xfd,0x5c,0xfc,0x94,0xfc,' +` 0x96,0xfb,0xf2,0xfb,0xcd,0xfa,0x53,0xfb,' +` 0x03,0xfa,0xb9,0xfa,0x41,0xf9,0x08,0xfa,' +` 0x0c,0xf7,0x59,0xf8,0x36,0xf6,0xe8,0xf7,' +` 0x86,0xf5,0x2c,0xf9,0x7e,0xf6,0x5b,0xf9,' +` 0xe7,0xf5,0xad,0xf9,0x4a,0xf5,0x5c,0xfa,' +` 0x73,0xf4,0xb7,0xfb,0xeb,0xf2,0xf5,0xfe,' +` 0xbf,0xed,0xdc,0x0f,0x7e,0x73,0x45,0xe8,' +` 0x70,0x02,0x9b,0xf3,0xac,0xfe,0xb3,0xf6,' +` 0xb3,0xfd,0x5f,0xf8,0x70,0xfd,0x98,0xf9,' +` 0x7a,0xfd,0xa0,0xfa,0x94,0xfd,0x2c,0xfc,' +` 0xce,0xff,0xa9,0xfd,0xd9,0xff,0x4e,0xfe,' +` 0x98,0xff,0x2d,0xfd,0xe9,0xfe,0xbe,0xfd,' +` 0x1f,0xff,0x34,0xfe,0x56,0xff,0x9a,0xfe,' +` 0x86,0xff,0xed,0xfe,0xa7,0xff,0x2b,0xff,' +` 0xc0,0xff,0x5e,0xff,0xd2,0xff,0x87,0xff,' +` 0xe1,0xff,0xa9,0xff,0xec,0xff,0xc5,0xff,' +` 0xf7,0xff,0xdc,0xff,0xfe,0xff,0xe6,0xff,' +` 0xfc,0xff,0xf2,0xff,0xff,0xff,0xfa,0xff,' +` 0x00,0x00,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x64,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x14,0x00,0x31,0x00,' +` 0x2d,0x00,0x63,0x00,0x5e,0x00,0xa9,0x00,' +` 0x9a,0x00,0x06,0x01,0xec,0x00,0x7c,0x01,' +` 0x50,0x01,0x0a,0x02,0xc7,0x01,0xb0,0x02,' +` 0x4e,0x02,0x6d,0x03,0xe2,0x02,0x3b,0x04,' +` 0x78,0x03,0x11,0x05,0x0a,0x04,0xf0,0x05,' +` 0x90,0x04,0xd2,0x06,0xf3,0x04,0x67,0x08,' +` 0xff,0x06,0xde,0x09,0x3e,0x07,0xe3,0x0a,' +` 0xc4,0x06,0xc0,0x09,0xc1,0x05,0xa2,0x0a,' +` 0x44,0x05,0x8f,0x0b,0x5d,0x04,0xcf,0x0c,' +` 0xaa,0x02,0xfe,0x0e,0xd0,0xfe,0xfc,0x14,' +` 0xb8,0xef,0xc3,0x78,0x69,0x30,0x50,0xf5,' +` 0x91,0x11,0x2c,0xfe,0x39,0x0c,0x7b,0x00,' +` 0xbc,0x09,0x63,0x01,0x1f,0x08,0xb9,0x01,' +` 0xe5,0x06,0xc8,0x01,0xd5,0x05,0x3d,0x00,' +` 0x5b,0x03,0x03,0x00,0xc2,0x02,0xe3,0xff,' +` 0x3c,0x03,0x4a,0x01,0xed,0x02,0x0b,0x01,' +` 0x6f,0x02,0xdc,0x00,0x01,0x02,0xb2,0x00,' +` 0x9f,0x01,0x91,0x00,0x4f,0x01,0x75,0x00,' +` 0x0a,0x01,0x5d,0x00,0xce,0x00,0x47,0x00,' +` 0x9b,0x00,0x35,0x00,0x70,0x00,0x24,0x00,' +` 0x4b,0x00,0x16,0x00,0x2b,0x00,0x06,0x00,' +` 0x17,0x00,0x03,0x00,0x0a,0x00,0x01,0x00,' +` 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x64,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x00,0x31,0x00,0x2d,0x00,0x63,0x00,' +` 0x5e,0x00,0xa9,0x00,0x9a,0x00,0x06,0x01,' +` 0xec,0x00,0x7c,0x01,0x50,0x01,0x0a,0x02,' +` 0xc7,0x01,0xb0,0x02,0x4e,0x02,0x6d,0x03,' +` 0xe2,0x02,0x3b,0x04,0x78,0x03,0x11,0x05,' +` 0x0a,0x04,0xf0,0x05,0x90,0x04,0xd2,0x06,' +` 0xf3,0x04,0x67,0x08,0xff,0x06,0xde,0x09,' +` 0x3e,0x07,0xe3,0x0a,0xc4,0x06,0xc0,0x09,' +` 0xc1,0x05,0xa2,0x0a,0x44,0x05,0x8f,0x0b,' +` 0x5d,0x04,0xcf,0x0c,0xaa,0x02,0xfe,0x0e,' +` 0xd0,0xfe,0xfc,0x14,0xb8,0xef,0xc3,0x78,' +` 0x69,0x30,0x50,0xf5,0x91,0x11,0x2c,0xfe,' +` 0x39,0x0c,0x7b,0x00,0xbc,0x09,0x63,0x01,' +` 0x1f,0x08,0xb9,0x01,0xe5,0x06,0xc8,0x01,' +` 0xd5,0x05,0x3d,0x00,0x5b,0x03,0x03,0x00,' +` 0xc2,0x02,0xe3,0xff,0x3c,0x03,0x4a,0x01,' +` 0xed,0x02,0x0b,0x01,0x6f,0x02,0xdc,0x00,' +` 0x01,0x02,0xb2,0x00,0x9f,0x01,0x91,0x00,' +` 0x4f,0x01,0x75,0x00,0x0a,0x01,0x5d,0x00,' +` 0xce,0x00,0x47,0x00,0x9b,0x00,0x35,0x00,' +` 0x70,0x00,0x24,0x00,0x4b,0x00,0x16,0x00,' +` 0x2b,0x00,0x06,0x00,0x17,0x00,0x03,0x00,' +` 0x0a,0x00,0x01,0x00,0x03,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x64,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf9,0xff,0xf6,0xff,' +` 0xe9,0xff,0xe4,0xff,0xcd,0xff,0xc1,0xff,' +` 0x88,0xff,0x81,0xff,0x3d,0xff,0x35,0xff,' +` 0xd9,0xfe,0xd3,0xfe,0x5c,0xfe,0x5d,0xfe,' +` 0xc6,0xfd,0xd3,0xfd,0x1b,0xfd,0x39,0xfd,' +` 0x5c,0xfc,0x94,0xfc,0x96,0xfb,0xf2,0xfb,' +` 0xcd,0xfa,0x53,0xfb,0x03,0xfa,0xb9,0xfa,' +` 0x41,0xf9,0x08,0xfa,0x0c,0xf7,0x59,0xf8,' +` 0x36,0xf6,0xe8,0xf7,0x86,0xf5,0x2c,0xf9,' +` 0x7e,0xf6,0x5b,0xf9,0xe7,0xf5,0xad,0xf9,' +` 0x4a,0xf5,0x5c,0xfa,0x73,0xf4,0xb7,0xfb,' +` 0xeb,0xf2,0xf5,0xfe,0xbf,0xed,0xdc,0x0f,' +` 0x7e,0x73,0x45,0xe8,0x70,0x02,0x9b,0xf3,' +` 0xac,0xfe,0xb3,0xf6,0xb3,0xfd,0x5f,0xf8,' +` 0x70,0xfd,0x98,0xf9,0x7a,0xfd,0xa0,0xfa,' +` 0x94,0xfd,0x2c,0xfc,0xce,0xff,0xa9,0xfd,' +` 0xd9,0xff,0x4e,0xfe,0x98,0xff,0x2d,0xfd,' +` 0xe9,0xfe,0xbe,0xfd,0x1f,0xff,0x34,0xfe,' +` 0x56,0xff,0x9a,0xfe,0x86,0xff,0xed,0xfe,' +` 0xa7,0xff,0x2b,0xff,0xc0,0xff,0x5e,0xff,' +` 0xd2,0xff,0x87,0xff,0xe1,0xff,0xa9,0xff,' +` 0xec,0xff,0xc5,0xff,0xf7,0xff,0xdc,0xff,' +` 0xfe,0xff,0xe6,0xff,0xfc,0xff,0xf2,0xff,' +` 0xff,0xff,0xfa,0xff,0x00,0x00,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x64,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x00,' +` 0xfa,0xff,0x02,0x00,0xf1,0xff,0x02,0x00,' +` 0xe1,0xff,0x04,0x00,0xd3,0xff,0x04,0x00,' +` 0xb6,0xff,0x00,0x00,0x92,0xff,0xfd,0xff,' +` 0x67,0xff,0xf8,0xff,0x33,0xff,0xf0,0xff,' +` 0xf2,0xfe,0xe5,0xff,0xa4,0xfe,0xd6,0xff,' +` 0x3f,0xfe,0xba,0xff,0xc4,0xfd,0x9a,0xff,' +` 0x34,0xfd,0x80,0xff,0x83,0xfc,0xc3,0xff,' +` 0x6e,0xfd,0xad,0x00,0xa2,0xfc,0xd0,0x00,' +` 0x36,0xfb,0xeb,0xfe,0x22,0xf9,0x24,0xff,' +` 0xb8,0xf7,0x90,0xff,0xed,0xf5,0x86,0x00,' +` 0x55,0xf3,0xc1,0x02,0x7b,0xee,0x39,0x09,' +` 0xe3,0xde,0x28,0x44,0xf9,0x4f,0xae,0xdc,' +` 0x77,0x08,0x4d,0xec,0xa5,0x00,0x5d,0xf0,' +` 0x99,0xfd,0x56,0xf2,0x06,0xfc,0x95,0xf3,' +` 0x28,0xfb,0x89,0xf4,0xc6,0xfa,0x69,0xf4,' +` 0xc4,0xf8,0xde,0xf4,0x0e,0xf9,0xc7,0xf5,' +` 0x63,0xfa,0x4f,0xf8,0x1a,0xfb,0x27,0xf9,' +` 0x99,0xfb,0x0a,0xfa,0x20,0xfc,0xea,0xfa,' +` 0xaf,0xfc,0xc6,0xfb,0x45,0xfd,0x9b,0xfc,' +` 0xd6,0xfd,0x5b,0xfd,0x5a,0xfe,0x04,0xfe,' +` 0xcd,0xfe,0x93,0xfe,0x2d,0xff,0x08,0xff,' +` 0x78,0xff,0x61,0xff,0xb5,0xff,0xb6,0xff,' +` 0xe1,0xff,0xdc,0xff,0xf4,0xff,0xf3,0xff,' +` 0x64,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x05,0x00,0x08,0x00,' +` 0x0a,0x00,0x0e,0x00,0x16,0x00,0x1c,0x00,' +` 0x22,0x00,0x2a,0x00,0x31,0x00,0x3a,0x00,' +` 0x42,0x00,0x4d,0x00,0x56,0x00,0x64,0x00,' +` 0x6e,0x00,0x7d,0x00,0x88,0x00,0x9a,0x00,' +` 0xa7,0x00,0xbd,0x00,0xcb,0x00,0xe6,0x00,' +` 0xf4,0x00,0x15,0x01,0x20,0x01,0x4f,0x01,' +` 0xd3,0x00,0xae,0x00,0xd2,0x00,0xe6,0x00,' +` 0xfa,0x00,0xc1,0x01,0x20,0x02,0x2b,0x02,' +` 0x5a,0x02,0x71,0x02,0x9a,0x02,0xb4,0x02,' +` 0xda,0x02,0xf5,0x02,0x1e,0x03,0x3f,0x03,' +` 0x64,0x03,0x83,0x03,0x9f,0x43,0xbe,0x03,' +` 0xd9,0x03,0xee,0x03,0x02,0x04,0x11,0x04,' +` 0x15,0x04,0x18,0x04,0x12,0x04,0x0f,0x04,' +` 0x00,0x04,0xf8,0x03,0xdb,0x03,0xe6,0x03,' +` 0x7e,0x04,0x5f,0x04,0x35,0x04,0x14,0x04,' +` 0xc2,0x03,0x04,0x03,0xe3,0x02,0xb2,0x02,' +` 0x8c,0x02,0x5b,0x02,0x31,0x02,0x00,0x02,' +` 0xd7,0x01,0xa8,0x01,0x7e,0x01,0x52,0x01,' +` 0x2c,0x01,0x05,0x01,0xe3,0x00,0xc1,0x00,' +` 0xa4,0x00,0x88,0x00,0x70,0x00,0x5a,0x00,' +` 0x48,0x00,0x37,0x00,0x2a,0x00,0x1c,0x00,' +` 0x13,0x00,0x0d,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x00,0x00,0x75,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_16khz.m4 new file mode 100644 index 000000000000..2a087d70b898 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_16khz.m4 @@ -0,0 +1,696 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x84,0x15,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x84,0x15,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xf6,0xff,0xee,0xff,0xc8,0xff,' +` 0xae,0xff,0x51,0xff,0x2a,0xff,0xf8,0xfe,' +` 0x36,0x00,0xa3,0x00,0x23,0x02,0x96,0x03,' +` 0xf7,0x07,0xde,0x0c,0xaa,0x14,0xbf,0x14,' +` 0x1f,0x1a,0x77,0x13,0x9a,0x56,0x9e,0x19,' +` 0x26,0x0e,0x39,0x0a,0xbf,0x00,0xc2,0x00,' +` 0x04,0xfd,0xa4,0xfd,0x96,0xfc,0x7b,0xfd,' +` 0x20,0xfd,0xa5,0xfe,0xda,0xfe,0x14,0xff,' +` 0xf5,0xfe,0x21,0xff,0x42,0xff,0xa1,0xff,' +` 0xca,0xff,0xf2,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,' +` 0x7b,0x00,0x7e,0x01,0x62,0x02,0x8b,0x04,' +` 0x14,0x05,0xda,0x07,0x03,0x06,0xd5,0x08,' +` 0x11,0x01,0x3d,0xff,0xfd,0xee,0x34,0xeb,' +` 0x39,0xd0,0xd4,0xce,0x02,0xb6,0x00,0xca,' +` 0x60,0xa5,0x39,0x2e,0xe2,0x1a,0x1f,0xd6,' +` 0x64,0x0d,0x5f,0x03,0x8a,0x1a,0x90,0x0f,' +` 0x6b,0x15,0xed,0x07,0x7c,0x07,0x85,0xfd,' +` 0xaa,0xfe,0x90,0xfb,0x53,0xfd,0x99,0xfc,' +` 0x99,0xfe,0xe4,0xfe,0xc4,0xff,0xdb,0xff,' +` 0x03,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0xdf,0xff,' +` 0xc2,0xff,0xf2,0xfe,0x93,0xfe,0xb1,0xfc,' +` 0x28,0xfd,0xa1,0xfb,0x59,0xfe,0x74,0xfd,' +` 0xad,0x06,0xf6,0x07,0x85,0x14,0x4e,0x10,' +` 0xfa,0x19,0x89,0x05,0xb5,0x0c,0x60,0xdb,' +` 0x14,0x0e,0xea,0x39,0x3c,0xa8,0xb9,0xc8,' +` 0xb7,0xb6,0x99,0xcd,0x98,0xcf,0xcd,0xe9,' +` 0x96,0xee,0x4e,0xfe,0xcb,0x00,0x66,0x08,' +` 0x10,0x06,0xa6,0x07,0x25,0x05,0x7d,0x04,' +` 0x6d,0x02,0x7d,0x01,0x7e,0x00,0x23,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf1,0xff,0xcb,0xff,0x9c,0xff,' +` 0x4b,0xff,0x0d,0xff,0x04,0xff,0xf1,0xfe,' +` 0xff,0xfe,0x7f,0xfe,0x6c,0xfd,0x1b,0xfd,' +` 0x02,0xfd,0x0b,0xfd,0x9a,0xfd,0xa8,0xff,' +` 0xba,0x01,0xc7,0x07,0x60,0x10,0xc7,0x13,' +` 0x0d,0x57,0x2d,0x18,0xb7,0x17,0x63,0x16,' +` 0xc2,0x13,0x37,0x0e,0xa6,0x07,0x45,0x04,' +` 0xdc,0x01,0xf9,0x00,0x13,0x00,0x32,0xff,' +` 0x0a,0xff,0x64,0xff,0x9e,0xff,0xd0,0xff,' +` 0xe9,0xff,0xf7,0xff,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf2,0xff,0xf0,0xff,0xb8,0xff,' +` 0xbd,0xff,0x2c,0xff,0x55,0xff,0x90,0xfe,' +` 0x55,0x00,0x27,0x00,0x76,0x02,0xd5,0x02,' +` 0x7e,0x08,0xd7,0x0a,0x35,0x16,0xbe,0x12,' +` 0x9d,0x1d,0x2b,0x0e,0x25,0x53,0xda,0x24,' +` 0x9f,0x0a,0xb3,0x0e,0x9d,0xff,0xdb,0x02,' +` 0xc0,0xfc,0xe5,0xfe,0x55,0xfc,0x51,0xfe,' +` 0xdc,0xfc,0x07,0xff,0xae,0xfe,0x48,0xff,' +` 0xda,0xfe,0x37,0xff,0x36,0xff,0xa7,0xff,' +` 0xc7,0xff,0xf2,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,' +` 0x79,0x00,0x7a,0x01,0x58,0x02,0x92,0x04,' +` 0x07,0x05,0xfa,0x07,0xed,0x05,0xf0,0x08,' +` 0x7e,0x01,0xf9,0xff,0x8d,0xef,0x1c,0xec,' +` 0x1d,0xd1,0xb1,0xcf,0xe9,0xb5,0xf8,0xc9,' +` 0x0f,0xa4,0x25,0x1f,0xf8,0x27,0x01,0xd1,' +` 0x00,0x0c,0x56,0x00,0x66,0x19,0x50,0x0e,' +` 0x1b,0x15,0x3e,0x07,0xc4,0x07,0x65,0xfd,' +` 0xf3,0xfe,0x9d,0xfb,0x87,0xfd,0xa8,0xfc,' +` 0xb6,0xfe,0xec,0xfe,0xcd,0xff,0xdd,0xff,' +` 0x04,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0xe6,0xff,' +` 0xc9,0xff,0x0d,0xff,0xac,0xfe,0xdf,0xfc,' +` 0x24,0xfd,0xb8,0xfb,0x36,0xfe,0x2e,0xfd,' +` 0xc1,0x05,0x49,0x07,0xd6,0x12,0x09,0x10,' +` 0x49,0x18,0x8d,0x05,0xb7,0x0a,0xbd,0xdd,' +` 0x65,0x06,0x02,0x3f,0x41,0xaa,0x41,0xc7,' +` 0x3a,0xb7,0xca,0xcc,0x43,0xcf,0xa9,0xe8,' +` 0x5a,0xee,0xab,0xfd,0xbb,0x00,0xf5,0x07,' +` 0xfe,0x05,0x7f,0x07,0x2f,0x05,0x73,0x04,' +` 0x75,0x02,0x7b,0x01,0x81,0x00,0x23,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf1,0xff,0xca,0xff,0x9a,0xff,' +` 0x4d,0xff,0x06,0xff,0x01,0xff,0xf1,0xfe,' +` 0x08,0xff,0xac,0xfe,0x9e,0xfd,0x59,0xfd,' +` 0x6a,0xfd,0x64,0xfd,0x2b,0xfe,0x2d,0x00,' +` 0xff,0x01,0x54,0x08,0xb7,0x10,0x03,0x14,' +` 0x51,0x57,0x79,0x18,0x10,0x18,0x9d,0x16,' +` 0x22,0x14,0x47,0x0e,0xa3,0x07,0x89,0x04,' +` 0xd2,0x01,0xf0,0x00,0x0c,0x00,0x18,0xff,' +` 0x05,0xff,0x5b,0xff,0x96,0xff,0xca,0xff,' +` 0xe4,0xff,0xf5,0xff,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfb,0xff,0xf7,0xff,0xc6,0xff,0xd8,0xff,' +` 0x48,0xff,0x99,0xff,0x87,0xfe,0xe5,0xff,' +` 0x96,0xff,0x16,0x02,0x93,0x01,0xee,0x07,' +` 0xc2,0x06,0xad,0x14,0x06,0x11,0x69,0x1e,' +` 0x68,0x0d,0x21,0x38,0x8b,0x47,0xd3,0x05,' +` 0x43,0x17,0xf0,0x00,0x0e,0x06,0xf8,0xfd,' +` 0x70,0x01,0x54,0xfc,0xd7,0xff,0x8e,0xfc,' +` 0x6f,0xff,0x69,0xfe,0x6d,0xff,0x6d,0xfe,' +` 0x0a,0xff,0xbf,0xfe,0x70,0xff,0x7a,0xff,' +` 0xcc,0xff,0xee,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,' +` 0x9f,0x00,0x4f,0x01,0xe0,0x02,0xaa,0x03,' +` 0xde,0x05,0x1c,0x05,0xb4,0x06,0xe1,0x02,' +` 0xde,0x00,0x5e,0xf4,0xcd,0xee,0xb7,0xd9,' +` 0x10,0xd3,0x28,0xbe,0x26,0xc7,0x1c,0xad,' +` 0x74,0xee,0x4d,0x46,0x5b,0xcd,0x47,0x01,' +` 0x78,0xfb,0x21,0x13,0x25,0x0d,0x12,0x14,' +` 0xea,0x06,0xf1,0x07,0xbc,0xfd,0xb2,0xfe,' +` 0x89,0xfb,0x18,0xfd,0x33,0xfc,0x64,0xfe,' +` 0xac,0xfe,0xba,0xff,0xcf,0xff,0x14,0x00,' +` 0x04,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x06,0x00,0xfc,0xff,0xe1,0xff,' +` 0x59,0xff,0xf3,0xfe,0x7e,0xfd,0x26,0xfd,' +` 0x13,0xfc,0xbf,0xfd,0xe5,0xfc,0xce,0x02,' +` 0xaa,0x05,0x61,0x0d,0x47,0x0f,0xac,0x12,' +` 0xf4,0x05,0xb0,0x03,0x76,0xe5,0xe9,0xf0,' +` 0x36,0x4a,0x18,0xb4,0xf4,0xc1,0x18,0xba,' +` 0x1b,0xca,0xa2,0xcf,0xda,0xe4,0x2b,0xee,' +` 0x68,0xfb,0xd6,0x00,0x6b,0x06,0xd9,0x05,' +` 0xe4,0x06,0x48,0x05,0x43,0x04,0x89,0x02,' +` 0x6c,0x01,0x89,0x00,0x22,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf1,0xff,0xc7,0xff,0x94,0xff,0x54,0xff,' +` 0xfa,0xfe,0xf1,0xfe,0xf4,0xfe,0x17,0xff,' +` 0x25,0xff,0x32,0xfe,0x13,0xfe,0x7b,0xfe,' +` 0x6f,0xfe,0xdc,0xff,0xa2,0x01,0xdb,0x02,' +` 0xe6,0x09,0x98,0x11,0xab,0x14,0xeb,0x57,' +` 0x34,0x19,0xeb,0x18,0x2c,0x17,0x15,0x15,' +` 0x6a,0x0e,0x9f,0x07,0x3a,0x05,0xe6,0x01,' +` 0xc9,0x00,0xf2,0xff,0xde,0xfe,0xfc,0xfe,' +` 0x42,0xff,0x82,0xff,0xb8,0xff,0xd7,0xff,' +` 0xf1,0xff,0xfd,0xff,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xe7,0xff,0xd7,0xff,0x86,0xff,' +` 0x95,0xff,0xfb,0xfe,0x4c,0xff,0x5e,0xfe,' +` 0xf6,0xff,0xc3,0xff,0x09,0x03,0x33,0x04,' +` 0x33,0x09,0x8c,0x0a,0x29,0x18,0x07,0x14,' +` 0x65,0x1f,0x72,0x0f,0x89,0x53,0xbe,0x27,' +` 0xc4,0x0b,0xc3,0x12,0x47,0x02,0xe8,0x05,' +` 0xfe,0x00,0xf7,0x01,0x8d,0xfe,0x34,0x00,' +` 0x50,0xfe,0x1c,0x00,0xd2,0xfe,0x4c,0xff,' +` 0xa7,0xfe,0x23,0xff,0x43,0xff,0x99,0xff,' +` 0xc1,0xff,0xf1,0xff,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,' +` 0x83,0x00,0x5d,0x01,0x4c,0x02,0x1b,0x04,' +` 0xd2,0x04,0x81,0x06,0xf0,0x04,0x53,0x05,' +` 0x96,0x00,0x40,0xfb,0xf1,0xed,0xa2,0xe4,' +` 0x0d,0xd1,0x7d,0xcc,0x87,0xba,0x42,0xc4,' +` 0x79,0xb1,0xa6,0x47,0x4c,0xf2,0x40,0xdf,' +` 0xb9,0xfd,0x32,0xfe,0xaf,0x0c,0xda,0x09,' +` 0x03,0x09,0xbb,0x01,0x1e,0x01,0x98,0xfc,' +` 0x31,0xfe,0x6e,0xfc,0xf6,0xfd,0x31,0xfe,' +` 0x8d,0xff,0xa5,0xff,0x1c,0x00,0x10,0x00,' +` 0x0c,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0a,0x00,0x1d,0x00,0x09,0x00,' +` 0xde,0xff,0x47,0xff,0xc0,0xfe,0x4b,0xfd,' +` 0x27,0xfd,0xaa,0xfc,0xe9,0xfd,0x22,0xfe,' +` 0x97,0x03,0x8c,0x04,0x1d,0x0d,0xd0,0x08,' +` 0x77,0x06,0xe0,0xf6,0xd2,0xf0,0x46,0xd5,' +` 0x21,0x4e,0x2b,0xcf,0x72,0xb7,0x62,0xc2,' +` 0xef,0xc4,0xd4,0xd3,0x9a,0xde,0xb7,0xee,' +` 0x75,0xf7,0x12,0x01,0xd7,0x03,0x88,0x05,' +` 0xa9,0x05,0x48,0x05,0xd3,0x03,0x92,0x02,' +` 0x4b,0x01,0x93,0x00,0x20,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf0,0xff,0xc5,0xff,0x8b,0xff,0x58,0xff,' +` 0x07,0xff,0xca,0xfe,0xf6,0xfe,0x23,0xff,' +` 0x9d,0xff,0x35,0xff,0x30,0xff,0xc2,0xff,' +` 0x3d,0x00,0x7f,0x02,0xc3,0x03,0x8e,0x04,' +` 0x48,0x0c,0xb8,0x12,0x9e,0x15,0x83,0x58,' +` 0xdb,0x19,0xcb,0x19,0xb3,0x17,0x15,0x16,' +` 0x64,0x0e,0xc9,0x07,0xd7,0x05,0x82,0x02,' +` 0x9f,0x00,0x91,0xff,0xd1,0xfe,0xee,0xfe,' +` 0x2b,0xff,0x6a,0xff,0x9b,0xff,0xc7,0xff,' +` 0xeb,0xff,0xfb,0xff,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf9,0xff,0xe2,0xff,0xbe,0xff,' +` 0x7f,0xff,0x5d,0xff,0x24,0xff,0x0e,0xff,' +` 0x0a,0xff,0x25,0xff,0xd5,0x00,0xb1,0x03,' +` 0xd1,0x05,0xc1,0x08,0x72,0x0d,0xb1,0x16,' +` 0x27,0x17,0x2a,0x1b,0x9d,0x17,0xbc,0x58,' +` 0x7f,0x19,0x70,0x12,0x59,0x10,0xf3,0x06,' +` 0x8b,0x06,0xff,0x04,0xdb,0x02,0xb1,0x00,' +` 0x60,0x00,0x32,0x00,0xb5,0xff,0x12,0xff,' +` 0xcf,0xfe,0xb0,0xfe,0x23,0xff,0x42,0xff,' +` 0x89,0xff,0xc3,0xff,0xf0,0xff,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,' +` 0x71,0x00,0x43,0x01,0xe3,0x01,0x9e,0x03,' +` 0x37,0x04,0x4d,0x06,0xb3,0x04,0xc2,0x05,' +` 0xad,0x00,0x1c,0x00,0x6b,0xf2,0x9e,0xec,' +` 0x28,0xd8,0xbf,0xd7,0x38,0xbe,0xda,0xcb,' +` 0xf3,0xac,0x44,0xf6,0x3f,0x3f,0xe1,0xc4,' +` 0xe5,0xf5,0xf2,0xe9,0x1f,0x03,0x20,0xfd,' +` 0xdb,0x06,0xe6,0xfc,0x2e,0x00,0x00,0xfc,' +` 0xcb,0xff,0xe9,0xfc,0x53,0xff,0xbd,0xfe,' +` 0x32,0x00,0xe2,0xff,0x58,0x00,0x1c,0x00,' +` 0x11,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x0e,0x00,0x44,0x00,0x38,0x00,' +` 0x98,0x00,0xbd,0xff,0x41,0x00,0x2d,0xfe,' +` 0x20,0xff,0xf0,0xfb,0xb2,0xff,0xfd,0xfa,' +` 0x2d,0x00,0xd2,0xfb,0x73,0x07,0x44,0xfc,' +` 0xe2,0x03,0x20,0xe8,0xc2,0xf6,0x94,0xc2,' +` 0xfd,0x38,0x7f,0xff,0x9c,0xac,0x3e,0xcf,' +` 0x93,0xc0,0x15,0xdb,0xe7,0xda,0xd7,0xee,' +` 0xb7,0xf3,0x6c,0x00,0x9e,0x00,0x02,0x05,' +` 0xc3,0x03,0xed,0x04,0x0a,0x03,0x72,0x02,' +` 0x18,0x01,0x96,0x00,0x1d,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf0,0xff,0xc5,0xff,0x89,0xff,0x4b,0xff,' +` 0x24,0xff,0xc9,0xfe,0xca,0xfe,0x38,0xff,' +` 0xac,0xff,0x75,0x00,0x5b,0x00,0x02,0x01,' +` 0xab,0x02,0x69,0x05,0x5e,0x06,0x8a,0x07,' +` 0x58,0x0f,0xcc,0x13,0xb6,0x16,0xe9,0x58,' +` 0xf6,0x19,0xed,0x19,0xbe,0x17,0x0f,0x16,' +` 0x01,0x0e,0x49,0x08,0xed,0x05,0x61,0x03,' +` 0xed,0x00,0xed,0xfe,0x05,0xff,0xed,0xfe,' +` 0x20,0xff,0x4d,0xff,0x7d,0xff,0xb9,0xff,' +` 0xe2,0xff,0xf9,0xff,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf6,0xff,0xdb,0xff,0xad,0xff,' +` 0x7b,0xff,0x36,0xff,0x34,0xff,0x30,0xff,' +` 0x0d,0xff,0x6c,0xff,0x79,0x01,0x0a,0x04,' +` 0xeb,0x05,0x0a,0x09,0x41,0x0d,0x4b,0x14,' +` 0x41,0x17,0x51,0x18,0x8b,0x1a,0xea,0x58,' +` 0xd6,0x16,0x65,0x15,0x52,0x12,0xce,0x0b,' +` 0x02,0x09,0x71,0x07,0xdb,0x04,0x10,0x02,' +` 0x1e,0x01,0xae,0x00,0x80,0xff,0xdc,0xfe,' +` 0x93,0xfe,0xf8,0xfe,0x02,0xff,0x49,0xff,' +` 0x88,0xff,0xc8,0xff,0xf1,0xff,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,' +` 0x64,0x00,0x1b,0x01,0x81,0x01,0xe5,0x02,' +` 0xcf,0x02,0x99,0x04,0x77,0x02,0xa0,0x03,' +` 0xd6,0xfc,0x19,0xfe,0x57,0xef,0x46,0xed,' +` 0xb4,0xdb,0xc7,0xdd,0x0e,0xc2,0xd6,0xd6,' +` 0x23,0xae,0x9f,0x35,0xfb,0x06,0xeb,0xc4,' +` 0x8d,0xed,0x32,0xe0,0x19,0xfa,0x68,0xf2,' +` 0xe1,0xfe,0x5f,0xf7,0xf6,0xfd,0xad,0xfc,' +` 0xab,0x00,0xb4,0xfe,0x29,0x01,0x2b,0x00,' +` 0x27,0x01,0x90,0x00,0xab,0x00,0x3e,0x00,' +` 0x18,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x17,0x00,0x3a,0x00,0xa2,0x00,' +` 0x81,0x00,0x0f,0x01,0x0a,0x00,0xfd,0x00,' +` 0x7d,0xfe,0x6e,0x00,0x61,0xfc,0x98,0xfd,' +` 0x0a,0xf7,0x7a,0xfe,0xff,0xf1,0xa2,0xf9,' +` 0x8a,0xdf,0x1d,0xed,0x7a,0xc4,0xb1,0x06,' +` 0x4f,0x35,0x0d,0xae,0xeb,0xd6,0x44,0xc2,' +` 0x54,0xde,0x30,0xdc,0xc4,0xed,0xf2,0xef,' +` 0x9e,0xfe,0x44,0xfd,0xff,0x03,0xc1,0x02,' +` 0xd1,0x04,0xf6,0x02,0xff,0x02,0x91,0x01,' +` 0x24,0x01,0x67,0x00,0x1f,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0xff,' +` 0xca,0xff,0x8d,0xff,0x4f,0xff,0x12,0xff,' +` 0x06,0xff,0xb0,0xfe,0xf7,0xfe,0xb1,0xff,' +` 0xd0,0x00,0x64,0x01,0x39,0x02,0x34,0x05,' +` 0x8d,0x07,0x6d,0x09,0xf0,0x0b,0xd0,0x12,' +` 0x1c,0x15,0xd6,0x17,0xf9,0x58,0x9a,0x19,' +` 0xa6,0x18,0xcc,0x16,0x26,0x14,0xd2,0x0c,' +` 0xe3,0x08,0x8c,0x05,0xd9,0x03,0x32,0x01,' +` 0x48,0xff,0xe3,0xfe,0x1c,0xff,0x1c,0xff,' +` 0x2c,0xff,0x71,0xff,0xa9,0xff,0xd9,0xff,' +` 0xf6,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf4,0xff,0xd1,0xff,0x9c,0xff,' +` 0x5b,0xff,0x1d,0xff,0xee,0xfe,0xf0,0xfe,' +` 0xcf,0xfe,0x45,0xff,0x4e,0x00,0xbf,0x01,' +` 0xc5,0x03,0x4c,0x06,0x45,0x09,0x13,0x0c,' +` 0x42,0x11,0xe6,0x15,0x03,0x17,0x76,0x19,' +` 0xf4,0x58,0x21,0x18,0xba,0x16,0x96,0x14,' +` 0x31,0x10,0xd9,0x0a,0x61,0x08,0x57,0x05,' +` 0x25,0x03,0x3d,0x01,0x20,0x00,0x38,0xff,' +` 0xf9,0xfe,0x1a,0xff,0x32,0xff,0x61,0xff,' +` 0x9e,0xff,0xd1,0xff,0xf4,0xff,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,' +` 0x5f,0x00,0xc9,0x00,0x49,0x01,0xc9,0x01,' +` 0x21,0x02,0x25,0x02,0x5c,0x02,0x84,0x01,' +` 0x5b,0xff,0x99,0xfc,0x69,0xf8,0x8a,0xf3,' +` 0x5d,0xed,0x0f,0xe8,0x58,0xdd,0x87,0xd4,' +` 0x89,0xd1,0x09,0xce,0xaa,0x4d,0xcf,0xce,' +` 0xfa,0xd2,0x85,0xd6,0xbf,0xdf,0x1d,0xea,' +` 0x54,0xef,0x33,0xf5,0xc3,0xf9,0x73,0xfd,' +` 0xc7,0xff,0x86,0x01,0x14,0x02,0xc7,0x01,' +` 0x9f,0x01,0x3b,0x01,0xc5,0x00,0x5e,0x00,' +` 0x19,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x18,0x00,0x5f,0x00,0xc9,0x00,' +` 0x49,0x01,0xc9,0x01,0x21,0x02,0x25,0x02,' +` 0x5c,0x02,0x84,0x01,0x5b,0xff,0x99,0xfc,' +` 0x69,0xf8,0x8a,0xf3,0x5d,0xed,0x0f,0xe8,' +` 0x58,0xdd,0x87,0xd4,0x89,0xd1,0x09,0xce,' +` 0xaa,0x4d,0xcf,0xce,0xfa,0xd2,0x85,0xd6,' +` 0xbf,0xdf,0x1d,0xea,0x54,0xef,0x33,0xf5,' +` 0xc3,0xf9,0x73,0xfd,0xc7,0xff,0x86,0x01,' +` 0x14,0x02,0xc7,0x01,0x9f,0x01,0x3b,0x01,' +` 0xc5,0x00,0x5e,0x00,0x19,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf4,0xff,' +` 0xd1,0xff,0x9c,0xff,0x5b,0xff,0x1d,0xff,' +` 0xee,0xfe,0xf0,0xfe,0xcf,0xfe,0x45,0xff,' +` 0x4e,0x00,0xbf,0x01,0xc5,0x03,0x4c,0x06,' +` 0x45,0x09,0x13,0x0c,0x42,0x11,0xe6,0x15,' +` 0x03,0x17,0x76,0x19,0xf4,0x58,0x21,0x18,' +` 0xba,0x16,0x96,0x14,0x31,0x10,0xd9,0x0a,' +` 0x61,0x08,0x57,0x05,0x25,0x03,0x3d,0x01,' +` 0x20,0x00,0x38,0xff,0xf9,0xfe,0x1a,0xff,' +` 0x32,0xff,0x61,0xff,0x9e,0xff,0xd1,0xff,' +` 0xf4,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xf1,0xff,0xca,0xff,0x8d,0xff,' +` 0x4f,0xff,0x12,0xff,0x06,0xff,0xb0,0xfe,' +` 0xf7,0xfe,0xb1,0xff,0xd0,0x00,0x64,0x01,' +` 0x39,0x02,0x34,0x05,0x8d,0x07,0x6d,0x09,' +` 0xf0,0x0b,0xd0,0x12,0x1c,0x15,0xd6,0x17,' +` 0xf9,0x58,0x9a,0x19,0xa6,0x18,0xcc,0x16,' +` 0x26,0x14,0xd2,0x0c,0xe3,0x08,0x8c,0x05,' +` 0xd9,0x03,0x32,0x01,0x48,0xff,0xe3,0xfe,' +` 0x1c,0xff,0x1c,0xff,0x2c,0xff,0x71,0xff,' +` 0xa9,0xff,0xd9,0xff,0xf6,0xff,0x00,0x00,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,' +` 0x3a,0x00,0xa2,0x00,0x81,0x00,0x0f,0x01,' +` 0x0a,0x00,0xfd,0x00,0x7d,0xfe,0x6e,0x00,' +` 0x61,0xfc,0x98,0xfd,0x0a,0xf7,0x7a,0xfe,' +` 0xff,0xf1,0xa2,0xf9,0x8a,0xdf,0x1d,0xed,' +` 0x7a,0xc4,0xb1,0x06,0x4f,0x35,0x0d,0xae,' +` 0xeb,0xd6,0x44,0xc2,0x54,0xde,0x30,0xdc,' +` 0xc4,0xed,0xf2,0xef,0x9e,0xfe,0x44,0xfd,' +` 0xff,0x03,0xc1,0x02,0xd1,0x04,0xf6,0x02,' +` 0xff,0x02,0x91,0x01,0x24,0x01,0x67,0x00,' +` 0x1f,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x1e,0x00,0x64,0x00,0x1b,0x01,' +` 0x81,0x01,0xe5,0x02,0xcf,0x02,0x99,0x04,' +` 0x77,0x02,0xa0,0x03,0xd6,0xfc,0x19,0xfe,' +` 0x57,0xef,0x46,0xed,0xb4,0xdb,0xc7,0xdd,' +` 0x0e,0xc2,0xd6,0xd6,0x23,0xae,0x9f,0x35,' +` 0xfb,0x06,0xeb,0xc4,0x8d,0xed,0x32,0xe0,' +` 0x19,0xfa,0x68,0xf2,0xe1,0xfe,0x5f,0xf7,' +` 0xf6,0xfd,0xad,0xfc,0xab,0x00,0xb4,0xfe,' +` 0x29,0x01,0x2b,0x00,0x27,0x01,0x90,0x00,' +` 0xab,0x00,0x3e,0x00,0x18,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf6,0xff,' +` 0xdb,0xff,0xad,0xff,0x7b,0xff,0x36,0xff,' +` 0x34,0xff,0x30,0xff,0x0d,0xff,0x6c,0xff,' +` 0x79,0x01,0x0a,0x04,0xeb,0x05,0x0a,0x09,' +` 0x41,0x0d,0x4b,0x14,0x41,0x17,0x51,0x18,' +` 0x8b,0x1a,0xea,0x58,0xd6,0x16,0x65,0x15,' +` 0x52,0x12,0xce,0x0b,0x02,0x09,0x71,0x07,' +` 0xdb,0x04,0x10,0x02,0x1e,0x01,0xae,0x00,' +` 0x80,0xff,0xdc,0xfe,0x93,0xfe,0xf8,0xfe,' +` 0x02,0xff,0x49,0xff,0x88,0xff,0xc8,0xff,' +` 0xf1,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf0,0xff,0xc5,0xff,' +` 0x89,0xff,0x4b,0xff,0x24,0xff,0xc9,0xfe,' +` 0xca,0xfe,0x38,0xff,0xac,0xff,0x75,0x00,' +` 0x5b,0x00,0x02,0x01,0xab,0x02,0x69,0x05,' +` 0x5e,0x06,0x8a,0x07,0x58,0x0f,0xcc,0x13,' +` 0xb6,0x16,0xe9,0x58,0xf6,0x19,0xed,0x19,' +` 0xbe,0x17,0x0f,0x16,0x01,0x0e,0x49,0x08,' +` 0xed,0x05,0x61,0x03,0xed,0x00,0xed,0xfe,' +` 0x05,0xff,0xed,0xfe,0x20,0xff,0x4d,0xff,' +` 0x7d,0xff,0xb9,0xff,0xe2,0xff,0xf9,0xff,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,' +` 0x44,0x00,0x38,0x00,0x98,0x00,0xbd,0xff,' +` 0x41,0x00,0x2d,0xfe,0x20,0xff,0xf0,0xfb,' +` 0xb2,0xff,0xfd,0xfa,0x2d,0x00,0xd2,0xfb,' +` 0x73,0x07,0x44,0xfc,0xe2,0x03,0x20,0xe8,' +` 0xc2,0xf6,0x94,0xc2,0xfd,0x38,0x7f,0xff,' +` 0x9c,0xac,0x3e,0xcf,0x93,0xc0,0x15,0xdb,' +` 0xe7,0xda,0xd7,0xee,0xb7,0xf3,0x6c,0x00,' +` 0x9e,0x00,0x02,0x05,0xc3,0x03,0xed,0x04,' +` 0x0a,0x03,0x72,0x02,0x18,0x01,0x96,0x00,' +` 0x1d,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x20,0x00,0x71,0x00,0x43,0x01,' +` 0xe3,0x01,0x9e,0x03,0x37,0x04,0x4d,0x06,' +` 0xb3,0x04,0xc2,0x05,0xad,0x00,0x1c,0x00,' +` 0x6b,0xf2,0x9e,0xec,0x28,0xd8,0xbf,0xd7,' +` 0x38,0xbe,0xda,0xcb,0xf3,0xac,0x44,0xf6,' +` 0x3f,0x3f,0xe1,0xc4,0xe5,0xf5,0xf2,0xe9,' +` 0x1f,0x03,0x20,0xfd,0xdb,0x06,0xe6,0xfc,' +` 0x2e,0x00,0x00,0xfc,0xcb,0xff,0xe9,0xfc,' +` 0x53,0xff,0xbd,0xfe,0x32,0x00,0xe2,0xff,' +` 0x58,0x00,0x1c,0x00,0x11,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf9,0xff,' +` 0xe2,0xff,0xbe,0xff,0x7f,0xff,0x5d,0xff,' +` 0x24,0xff,0x0e,0xff,0x0a,0xff,0x25,0xff,' +` 0xd5,0x00,0xb1,0x03,0xd1,0x05,0xc1,0x08,' +` 0x72,0x0d,0xb1,0x16,0x27,0x17,0x2a,0x1b,' +` 0x9d,0x17,0xbc,0x58,0x7f,0x19,0x70,0x12,' +` 0x59,0x10,0xf3,0x06,0x8b,0x06,0xff,0x04,' +` 0xdb,0x02,0xb1,0x00,0x60,0x00,0x32,0x00,' +` 0xb5,0xff,0x12,0xff,0xcf,0xfe,0xb0,0xfe,' +` 0x23,0xff,0x42,0xff,0x89,0xff,0xc3,0xff,' +` 0xf0,0xff,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf0,0xff,0xc5,0xff,' +` 0x8b,0xff,0x58,0xff,0x07,0xff,0xca,0xfe,' +` 0xf6,0xfe,0x23,0xff,0x9d,0xff,0x35,0xff,' +` 0x30,0xff,0xc2,0xff,0x3d,0x00,0x7f,0x02,' +` 0xc3,0x03,0x8e,0x04,0x48,0x0c,0xb8,0x12,' +` 0x9e,0x15,0x83,0x58,0xdb,0x19,0xcb,0x19,' +` 0xb3,0x17,0x15,0x16,0x64,0x0e,0xc9,0x07,' +` 0xd7,0x05,0x82,0x02,0x9f,0x00,0x91,0xff,' +` 0xd1,0xfe,0xee,0xfe,0x2b,0xff,0x6a,0xff,' +` 0x9b,0xff,0xc7,0xff,0xeb,0xff,0xfb,0xff,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,' +` 0x1d,0x00,0x09,0x00,0xde,0xff,0x47,0xff,' +` 0xc0,0xfe,0x4b,0xfd,0x27,0xfd,0xaa,0xfc,' +` 0xe9,0xfd,0x22,0xfe,0x97,0x03,0x8c,0x04,' +` 0x1d,0x0d,0xd0,0x08,0x77,0x06,0xe0,0xf6,' +` 0xd2,0xf0,0x46,0xd5,0x21,0x4e,0x2b,0xcf,' +` 0x72,0xb7,0x62,0xc2,0xef,0xc4,0xd4,0xd3,' +` 0x9a,0xde,0xb7,0xee,0x75,0xf7,0x12,0x01,' +` 0xd7,0x03,0x88,0x05,0xa9,0x05,0x48,0x05,' +` 0xd3,0x03,0x92,0x02,0x4b,0x01,0x93,0x00,' +` 0x20,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x22,0x00,0x83,0x00,0x5d,0x01,' +` 0x4c,0x02,0x1b,0x04,0xd2,0x04,0x81,0x06,' +` 0xf0,0x04,0x53,0x05,0x96,0x00,0x40,0xfb,' +` 0xf1,0xed,0xa2,0xe4,0x0d,0xd1,0x7d,0xcc,' +` 0x87,0xba,0x42,0xc4,0x79,0xb1,0xa6,0x47,' +` 0x4c,0xf2,0x40,0xdf,0xb9,0xfd,0x32,0xfe,' +` 0xaf,0x0c,0xda,0x09,0x03,0x09,0xbb,0x01,' +` 0x1e,0x01,0x98,0xfc,0x31,0xfe,0x6e,0xfc,' +` 0xf6,0xfd,0x31,0xfe,0x8d,0xff,0xa5,0xff,' +` 0x1c,0x00,0x10,0x00,0x0c,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xe7,0xff,' +` 0xd7,0xff,0x86,0xff,0x95,0xff,0xfb,0xfe,' +` 0x4c,0xff,0x5e,0xfe,0xf6,0xff,0xc3,0xff,' +` 0x09,0x03,0x33,0x04,0x33,0x09,0x8c,0x0a,' +` 0x29,0x18,0x07,0x14,0x65,0x1f,0x72,0x0f,' +` 0x89,0x53,0xbe,0x27,0xc4,0x0b,0xc3,0x12,' +` 0x47,0x02,0xe8,0x05,0xfe,0x00,0xf7,0x01,' +` 0x8d,0xfe,0x34,0x00,0x50,0xfe,0x1c,0x00,' +` 0xd2,0xfe,0x4c,0xff,0xa7,0xfe,0x23,0xff,' +` 0x43,0xff,0x99,0xff,0xc1,0xff,0xf1,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf1,0xff,0xc7,0xff,' +` 0x94,0xff,0x54,0xff,0xfa,0xfe,0xf1,0xfe,' +` 0xf4,0xfe,0x17,0xff,0x25,0xff,0x32,0xfe,' +` 0x13,0xfe,0x7b,0xfe,0x6f,0xfe,0xdc,0xff,' +` 0xa2,0x01,0xdb,0x02,0xe6,0x09,0x98,0x11,' +` 0xab,0x14,0xeb,0x57,0x34,0x19,0xeb,0x18,' +` 0x2c,0x17,0x15,0x15,0x6a,0x0e,0x9f,0x07,' +` 0x3a,0x05,0xe6,0x01,0xc9,0x00,0xf2,0xff,' +` 0xde,0xfe,0xfc,0xfe,0x42,0xff,0x82,0xff,' +` 0xb8,0xff,0xd7,0xff,0xf1,0xff,0xfd,0xff,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,' +` 0xfc,0xff,0xe1,0xff,0x59,0xff,0xf3,0xfe,' +` 0x7e,0xfd,0x26,0xfd,0x13,0xfc,0xbf,0xfd,' +` 0xe5,0xfc,0xce,0x02,0xaa,0x05,0x61,0x0d,' +` 0x47,0x0f,0xac,0x12,0xf4,0x05,0xb0,0x03,' +` 0x76,0xe5,0xe9,0xf0,0x36,0x4a,0x18,0xb4,' +` 0xf4,0xc1,0x18,0xba,0x1b,0xca,0xa2,0xcf,' +` 0xda,0xe4,0x2b,0xee,0x68,0xfb,0xd6,0x00,' +` 0x6b,0x06,0xd9,0x05,0xe4,0x06,0x48,0x05,' +` 0x43,0x04,0x89,0x02,0x6c,0x01,0x89,0x00,' +` 0x22,0x00,0x00,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x1f,0x00,0x9f,0x00,0x4f,0x01,' +` 0xe0,0x02,0xaa,0x03,0xde,0x05,0x1c,0x05,' +` 0xb4,0x06,0xe1,0x02,0xde,0x00,0x5e,0xf4,' +` 0xcd,0xee,0xb7,0xd9,0x10,0xd3,0x28,0xbe,' +` 0x26,0xc7,0x1c,0xad,0x74,0xee,0x4d,0x46,' +` 0x5b,0xcd,0x47,0x01,0x78,0xfb,0x21,0x13,' +` 0x25,0x0d,0x12,0x14,0xea,0x06,0xf1,0x07,' +` 0xbc,0xfd,0xb2,0xfe,0x89,0xfb,0x18,0xfd,' +` 0x33,0xfc,0x64,0xfe,0xac,0xfe,0xba,0xff,' +` 0xcf,0xff,0x14,0x00,0x04,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfb,0xff,0xf7,0xff,' +` 0xc6,0xff,0xd8,0xff,0x48,0xff,0x99,0xff,' +` 0x87,0xfe,0xe5,0xff,0x96,0xff,0x16,0x02,' +` 0x93,0x01,0xee,0x07,0xc2,0x06,0xad,0x14,' +` 0x06,0x11,0x69,0x1e,0x68,0x0d,0x21,0x38,' +` 0x8b,0x47,0xd3,0x05,0x43,0x17,0xf0,0x00,' +` 0x0e,0x06,0xf8,0xfd,0x70,0x01,0x54,0xfc,' +` 0xd7,0xff,0x8e,0xfc,0x6f,0xff,0x69,0xfe,' +` 0x6d,0xff,0x6d,0xfe,0x0a,0xff,0xbf,0xfe,' +` 0x70,0xff,0x7a,0xff,0xcc,0xff,0xee,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0xff,' +` 0xca,0xff,0x9a,0xff,0x4d,0xff,0x06,0xff,' +` 0x01,0xff,0xf1,0xfe,0x08,0xff,0xac,0xfe,' +` 0x9e,0xfd,0x59,0xfd,0x6a,0xfd,0x64,0xfd,' +` 0x2b,0xfe,0x2d,0x00,0xff,0x01,0x54,0x08,' +` 0xb7,0x10,0x03,0x14,0x51,0x57,0x79,0x18,' +` 0x10,0x18,0x9d,0x16,0x22,0x14,0x47,0x0e,' +` 0xa3,0x07,0x89,0x04,0xd2,0x01,0xf0,0x00,' +` 0x0c,0x00,0x18,0xff,0x05,0xff,0x5b,0xff,' +` 0x96,0xff,0xca,0xff,0xe4,0xff,0xf5,0xff,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0xe6,0xff,0xc9,0xff,0x0d,0xff,' +` 0xac,0xfe,0xdf,0xfc,0x24,0xfd,0xb8,0xfb,' +` 0x36,0xfe,0x2e,0xfd,0xc1,0x05,0x49,0x07,' +` 0xd6,0x12,0x09,0x10,0x49,0x18,0x8d,0x05,' +` 0xb7,0x0a,0xbd,0xdd,0x65,0x06,0x02,0x3f,' +` 0x41,0xaa,0x41,0xc7,0x3a,0xb7,0xca,0xcc,' +` 0x43,0xcf,0xa9,0xe8,0x5a,0xee,0xab,0xfd,' +` 0xbb,0x00,0xf5,0x07,0xfe,0x05,0x7f,0x07,' +` 0x2f,0x05,0x73,0x04,0x75,0x02,0x7b,0x01,' +` 0x81,0x00,0x23,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x23,0x00,0x79,0x00,0x7a,0x01,' +` 0x58,0x02,0x92,0x04,0x07,0x05,0xfa,0x07,' +` 0xed,0x05,0xf0,0x08,0x7e,0x01,0xf9,0xff,' +` 0x8d,0xef,0x1c,0xec,0x1d,0xd1,0xb1,0xcf,' +` 0xe9,0xb5,0xf8,0xc9,0x0f,0xa4,0x25,0x1f,' +` 0xf8,0x27,0x01,0xd1,0x00,0x0c,0x56,0x00,' +` 0x66,0x19,0x50,0x0e,0x1b,0x15,0x3e,0x07,' +` 0xc4,0x07,0x65,0xfd,0xf3,0xfe,0x9d,0xfb,' +` 0x87,0xfd,0xa8,0xfc,0xb6,0xfe,0xec,0xfe,' +` 0xcd,0xff,0xdd,0xff,0x04,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf2,0xff,' +` 0xf0,0xff,0xb8,0xff,0xbd,0xff,0x2c,0xff,' +` 0x55,0xff,0x90,0xfe,0x55,0x00,0x27,0x00,' +` 0x76,0x02,0xd5,0x02,0x7e,0x08,0xd7,0x0a,' +` 0x35,0x16,0xbe,0x12,0x9d,0x1d,0x2b,0x0e,' +` 0x25,0x53,0xda,0x24,0x9f,0x0a,0xb3,0x0e,' +` 0x9d,0xff,0xdb,0x02,0xc0,0xfc,0xe5,0xfe,' +` 0x55,0xfc,0x51,0xfe,0xdc,0xfc,0x07,0xff,' +` 0xae,0xfe,0x48,0xff,0xda,0xfe,0x37,0xff,' +` 0x36,0xff,0xa7,0xff,0xc7,0xff,0xf2,0xff,' +` 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0xff,' +` 0xcb,0xff,0x9c,0xff,0x4b,0xff,0x0d,0xff,' +` 0x04,0xff,0xf1,0xfe,0xff,0xfe,0x7f,0xfe,' +` 0x6c,0xfd,0x1b,0xfd,0x02,0xfd,0x0b,0xfd,' +` 0x9a,0xfd,0xa8,0xff,0xba,0x01,0xc7,0x07,' +` 0x60,0x10,0xc7,0x13,0x0d,0x57,0x2d,0x18,' +` 0xb7,0x17,0x63,0x16,0xc2,0x13,0x37,0x0e,' +` 0xa6,0x07,0x45,0x04,0xdc,0x01,0xf9,0x00,' +` 0x13,0x00,0x32,0xff,0x0a,0xff,0x64,0xff,' +` 0x9e,0xff,0xd0,0xff,0xe9,0xff,0xf7,0xff,' +` 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0xdf,0xff,0xc2,0xff,0xf2,0xfe,' +` 0x93,0xfe,0xb1,0xfc,0x28,0xfd,0xa1,0xfb,' +` 0x59,0xfe,0x74,0xfd,0xad,0x06,0xf6,0x07,' +` 0x85,0x14,0x4e,0x10,0xfa,0x19,0x89,0x05,' +` 0xb5,0x0c,0x60,0xdb,0x14,0x0e,0xea,0x39,' +` 0x3c,0xa8,0xb9,0xc8,0xb7,0xb6,0x99,0xcd,' +` 0x98,0xcf,0xcd,0xe9,0x96,0xee,0x4e,0xfe,' +` 0xcb,0x00,0x66,0x08,0x10,0x06,0xa6,0x07,' +` 0x25,0x05,0x7d,0x04,0x6d,0x02,0x7d,0x01,' +` 0x7e,0x00,0x23,0x00,0x28,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x23,0x00,0x7b,0x00,0x7e,0x01,' +` 0x62,0x02,0x8b,0x04,0x14,0x05,0xda,0x07,' +` 0x03,0x06,0xd5,0x08,0x11,0x01,0x3d,0xff,' +` 0xfd,0xee,0x34,0xeb,0x39,0xd0,0xd4,0xce,' +` 0x02,0xb6,0x00,0xca,0x60,0xa5,0x39,0x2e,' +` 0xe2,0x1a,0x1f,0xd6,0x64,0x0d,0x5f,0x03,' +` 0x8a,0x1a,0x90,0x0f,0x6b,0x15,0xed,0x07,' +` 0x7c,0x07,0x85,0xfd,0xaa,0xfe,0x90,0xfb,' +` 0x53,0xfd,0x99,0xfc,0x99,0xfe,0xe4,0xfe,' +` 0xc4,0xff,0xdb,0xff,0x03,0x00,0x00,0x00,' +` 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff,' +` 0xee,0xff,0xc8,0xff,0xae,0xff,0x51,0xff,' +` 0x2a,0xff,0xf8,0xfe,0x36,0x00,0xa3,0x00,' +` 0x23,0x02,0x96,0x03,0xf7,0x07,0xde,0x0c,' +` 0xaa,0x14,0xbf,0x14,0x1f,0x1a,0x77,0x13,' +` 0x9a,0x56,0x9e,0x19,0x26,0x0e,0x39,0x0a,' +` 0xbf,0x00,0xc2,0x00,0x04,0xfd,0xa4,0xfd,' +` 0x96,0xfc,0x7b,0xfd,0x20,0xfd,0xa5,0xfe,' +` 0xda,0xfe,0x14,0xff,0xf5,0xfe,0x21,0xff,' +` 0x42,0xff,0xa1,0xff,0xca,0xff,0xf2,0xff,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0xac,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_48khz.m4 new file mode 100644 index 000000000000..64f8ad44e828 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_azm90_90_13el0_0_13deg_48khz.m4 @@ -0,0 +1,1216 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x25,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x25,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfa,0xff,0xeb,0xff,0x00,0x00,0xf1,0xff,' +` 0x0e,0x00,0xf3,0xff,0x28,0x00,0x01,0x00,' +` 0x5b,0x00,0x15,0x00,0x71,0x00,0x38,0x00,' +` 0xe2,0x00,0x92,0x00,0x7d,0x01,0x0f,0x01,' +` 0x4c,0x02,0x99,0x01,0x60,0x03,0x7d,0x03,' +` 0x28,0x05,0x5b,0x04,0x7b,0x06,0x35,0x05,' +` 0xc9,0x07,0xe6,0x05,0xba,0x08,0x90,0x05,' +` 0xca,0x09,0x4c,0x05,0x3e,0x0b,0xc9,0x03,' +` 0x4b,0x0e,0x9a,0xfc,0x99,0x41,0x38,0x1a,' +` 0x11,0xff,0xca,0x0b,0x8f,0x02,0xa4,0x08,' +` 0xef,0x02,0xaf,0x06,0x93,0x02,0xb1,0x03,' +` 0x32,0x00,0x3b,0x02,0xba,0xff,0x40,0x01,' +` 0x55,0xff,0x84,0x00,0x20,0xff,0x44,0x00,' +` 0xed,0xfe,0xd5,0xff,0xfc,0xfe,0xb7,0xff,' +` 0x1d,0xff,0xb4,0xff,0x49,0xff,0xbc,0xff,' +` 0x61,0xff,0xbc,0xff,0x8b,0xff,0xce,0xff,' +` 0xaf,0xff,0xde,0xff,0xcc,0xff,0xf4,0xff,' +` 0xed,0xff,0xfb,0xff,0xf7,0xff,0xfe,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0x0c,0x00,' +` 0x1e,0x00,0x2b,0x00,0x49,0x00,0x4d,0x00,' +` 0x84,0x00,0x7d,0x00,0xa0,0x00,0x68,0x00,' +` 0x7e,0x00,0x02,0x00,0x01,0x00,0x3d,0xff,' +` 0x35,0xff,0xf0,0xfd,0xc3,0xfd,0x0e,0xfc,' +` 0xd6,0xfb,0xac,0xf9,0x84,0xf9,0xda,0xf6,' +` 0xb5,0xf5,0x26,0xf2,0x9e,0xf2,0x0f,0xef,' +` 0x27,0xf0,0x47,0xec,0x54,0xee,0x14,0xea,' +` 0xae,0xec,0x49,0xe7,0x28,0xed,0xba,0xe6,' +` 0xd6,0xef,0xdc,0xe5,0x78,0xf6,0x8b,0xdd,' +` 0xc8,0x6a,0x09,0x0a,0x49,0xe9,0x0e,0xfd,' +` 0x03,0xf3,0x0d,0xfe,0xbb,0xf8,0x78,0x00,' +` 0x22,0xfd,0xc9,0x03,0x52,0x01,0x6c,0x05,' +` 0x50,0x03,0x47,0x06,0x6a,0x04,0x67,0x06,' +` 0xdb,0x04,0x62,0x06,0x2a,0x04,0x08,0x05,' +` 0x58,0x03,0xc7,0x03,0x56,0x02,0x88,0x02,' +` 0x5d,0x01,0x72,0x01,0x7c,0x00,0x96,0x00,' +` 0x00,0x00,0x19,0x00,0xbe,0xff,0xdb,0xff,' +` 0xaf,0xff,0xe1,0xff,0xd3,0xff,0xe7,0xff,' +` 0xe6,0xff,0xf4,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xfa,0xff,0xf1,0xff,0xeb,0xff,0xde,0xff,' +` 0xdd,0xff,0xd1,0xff,0xc7,0xff,0xb5,0xff,' +` 0xde,0xff,0xdf,0xff,0x2e,0x00,0x42,0x00,' +` 0xbe,0x00,0xf7,0x00,0xbd,0x01,0xee,0x01,' +` 0xdb,0x02,0x06,0x03,0x0e,0x04,0x1b,0x04,' +` 0x20,0x05,0x24,0x05,0x4e,0x06,0x09,0x05,' +` 0x22,0x06,0x9f,0x04,0x87,0x05,0x5b,0x03,' +` 0x2d,0x04,0x37,0x01,0x33,0x01,0xb9,0xfc,' +` 0x14,0xfe,0x83,0xf8,0x17,0xfb,0x38,0xf3,' +` 0x8f,0xf9,0x0e,0xe9,0x5c,0x6f,0x48,0xfa,' +` 0x57,0xe8,0xdd,0xef,0xe5,0xe8,0xad,0xec,' +` 0xa4,0xe8,0x65,0xeb,0x28,0xe9,0xd5,0xec,' +` 0xce,0xeb,0x60,0xee,0x1a,0xee,0xa0,0xf0,' +` 0xec,0xf0,0x57,0xf3,0x19,0xf4,0x7b,0xf7,' +` 0x75,0xf8,0x41,0xfa,0xf9,0xfa,0x7c,0xfc,' +` 0x16,0xfd,0x40,0xfe,0xb1,0xfe,0x7c,0xff,' +` 0xa6,0xff,0x2a,0x00,0x40,0x00,0x82,0x00,' +` 0x7a,0x00,0x8d,0x00,0x73,0x00,0x59,0x00,' +` 0x3e,0x00,0x30,0x00,0x1b,0x00,0x0d,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfc,0xff,' +` 0xfa,0xff,0xf7,0xff,0xf3,0xff,0xee,0xff,' +` 0xda,0xff,0xce,0xff,0xc2,0xff,0xb6,0xff,' +` 0xa7,0xff,0x9b,0xff,0x88,0xff,0x89,0xff,' +` 0x81,0xff,0x74,0xff,0x65,0xff,0x61,0xff,' +` 0x58,0xff,0x64,0xff,0x60,0xff,0xa2,0xff,' +` 0xc5,0xff,0xc0,0xff,0x10,0x00,0x48,0x00,' +` 0xa9,0x00,0xfc,0x00,0x72,0x01,0xde,0x01,' +` 0xe0,0x03,0xb5,0x04,0x20,0x05,0xb1,0x05,' +` 0x22,0x06,0xa0,0x06,0x02,0x07,0x66,0x07,' +` 0xa5,0x47,0xea,0x07,0x00,0x08,0x10,0x08,' +` 0xfe,0x07,0xe5,0x07,0xac,0x07,0x69,0x07,' +` 0x1f,0x07,0x3c,0x07,0xb5,0x06,0x47,0x06,' +` 0xab,0x05,0x37,0x05,0x8b,0x04,0x2c,0x04,' +` 0x28,0x03,0x19,0x02,0xef,0x01,0x7d,0x01,' +` 0x37,0x01,0xe6,0x00,0xac,0x00,0x76,0x00,' +` 0x4a,0x00,0x37,0x00,0x3d,0x00,0x21,0x00,' +` 0x14,0x00,0x07,0x00,0x01,0x00,0xfd,0xff,' +` 0xfb,0xff,0xf2,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf9,0xff,0xe0,0xff,0xf6,0xff,0xe0,0xff,' +` 0x1a,0x00,0xdd,0xff,0x47,0x00,0xef,0xff,' +` 0xa1,0x00,0x09,0x00,0xce,0x00,0x42,0x00,' +` 0xa1,0x01,0xe1,0x00,0xc6,0x02,0xc7,0x01,' +` 0x46,0x04,0xea,0x02,0x8f,0x05,0xb3,0x05,' +` 0x39,0x0a,0xb7,0x07,0xdd,0x0c,0x67,0x09,' +` 0x9a,0x0f,0xc5,0x0a,0x0b,0x12,0x1e,0x0a,' +` 0x38,0x14,0x88,0x09,0x88,0x17,0x72,0x06,' +` 0xd3,0x1d,0x16,0xfa,0x4b,0x48,0x5c,0x76,' +` 0xc2,0xf3,0x5f,0x1d,0x60,0x02,0x5a,0x14,' +` 0xb2,0x04,0x8c,0x0f,0xcd,0x04,0xf0,0x0a,' +` 0xde,0xff,0xf7,0x05,0x24,0xff,0xb8,0x03,' +` 0x68,0xfe,0x0f,0x02,0xe0,0xfd,0x86,0x01,' +` 0xf7,0xfd,0x16,0x00,0xda,0xfd,0xc5,0xff,' +` 0x13,0xfe,0xa7,0xff,0x69,0xfe,0xa9,0xff,' +` 0xb1,0xfe,0x8b,0xff,0xef,0xfe,0xa4,0xff,' +` 0x3b,0xff,0xbd,0xff,0x7a,0xff,0xe7,0xff,' +` 0xcc,0xff,0xf5,0xff,0xe4,0xff,0xfa,0xff,' +` 0xf5,0xff,0xfe,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0x0b,0x00,' +` 0x20,0x00,0x28,0x00,0x4f,0x00,0x45,0x00,' +` 0x86,0x00,0x73,0x00,0xbc,0x00,0x59,0x00,' +` 0xab,0x00,0xed,0xff,0x44,0x00,0x23,0xff,' +` 0x90,0xff,0xc4,0xfd,0x3c,0xfe,0xd0,0xfb,' +` 0x72,0xfc,0x54,0xf9,0x47,0xfa,0x59,0xf6,' +` 0xec,0xf6,0x90,0xf1,0xb4,0xf3,0x2e,0xee,' +` 0x75,0xf1,0x0b,0xeb,0xe5,0xef,0x60,0xe8,' +` 0xc9,0xee,0xbc,0xe4,0x9b,0xef,0x1b,0xe3,' +` 0x74,0xf3,0x3c,0xe0,0xfa,0xfc,0x68,0xd2,' +` 0xe5,0x4b,0x90,0x37,0x1a,0xda,0xbd,0x04,' +` 0x64,0xec,0xc7,0x01,0x5c,0xf4,0xba,0x02,' +` 0xc1,0xf9,0xd2,0x04,0xdc,0xfe,0x65,0x06,' +` 0x50,0x01,0x02,0x07,0xcc,0x02,0x00,0x07,' +` 0x7a,0x03,0x28,0x07,0x61,0x03,0x60,0x05,' +` 0xaf,0x02,0x16,0x04,0xd8,0x01,0xcc,0x02,' +` 0x01,0x01,0xb2,0x01,0x52,0x00,0xc0,0x00,' +` 0xdc,0xff,0x3a,0x00,0xa8,0xff,0xf2,0xff,' +` 0xa3,0xff,0xef,0xff,0xcd,0xff,0xee,0xff,' +` 0xe4,0xff,0xf6,0xff,0xf8,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xfa,0xff,0xf0,0xff,0xed,0xff,0xd9,0xff,' +` 0xe2,0xff,0xc8,0xff,0xdb,0xff,0x9d,0xff,' +` 0xe9,0xff,0xb9,0xff,0x3a,0x00,0x07,0x00,' +` 0xcd,0x00,0xac,0x00,0xc9,0x01,0x78,0x01,' +` 0xea,0x02,0x71,0x02,0x29,0x04,0x66,0x03,' +` 0x4d,0x05,0x62,0x04,0xdf,0x06,0x02,0x04,' +` 0x9d,0x06,0x6d,0x03,0x3e,0x06,0xf4,0x01,' +` 0x36,0x05,0x86,0xff,0xae,0x02,0xa6,0xfa,' +` 0x4d,0x00,0xad,0xf5,0x8a,0xfe,0xa9,0xee,' +` 0x28,0x00,0x9a,0xdd,0x2d,0x67,0xc0,0x0f,' +` 0x74,0xdf,0x79,0xf5,0xe3,0xe4,0xd1,0xef,' +` 0x16,0xe6,0x84,0xed,0x35,0xe7,0x1c,0xee,' +` 0x83,0xea,0x71,0xef,0x0b,0xed,0x6a,0xf1,' +` 0x0e,0xf0,0xe9,0xf3,0x62,0xf3,0x98,0xf7,' +` 0xd2,0xf7,0x8d,0xfa,0x78,0xfa,0xb0,0xfc,' +` 0xb0,0xfc,0x65,0xfe,0x62,0xfe,0x9e,0xff,' +` 0x7b,0xff,0x3b,0x00,0x1e,0x00,0x8f,0x00,' +` 0x64,0x00,0x96,0x00,0x64,0x00,0x5c,0x00,' +` 0x38,0x00,0x31,0x00,0x19,0x00,0x0e,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfc,0xff,' +` 0xfa,0xff,0xf7,0xff,0xf3,0xff,0xf1,0xff,' +` 0xdf,0xff,0xd0,0xff,0xc7,0xff,0xbb,0xff,' +` 0xaf,0xff,0xa2,0xff,0x96,0xff,0x9a,0xff,' +` 0x8f,0xff,0x87,0xff,0x78,0xff,0x78,0xff,' +` 0x6d,0xff,0x7f,0xff,0x75,0xff,0xdc,0xff,' +` 0xf0,0xff,0xd9,0xff,0x2a,0x00,0x64,0x00,' +` 0xbf,0x00,0x1a,0x01,0x80,0x01,0x16,0x02,' +` 0x22,0x04,0xc1,0x04,0x40,0x05,0xc2,0x05,' +` 0x3d,0x06,0xb2,0x06,0x1a,0x07,0x78,0x07,' +` 0xba,0x47,0x00,0x08,0x1b,0x08,0x2a,0x08,' +` 0x19,0x08,0x01,0x08,0xc7,0x07,0x89,0x07,' +` 0x2d,0x07,0x4b,0x07,0xd2,0x06,0x5d,0x06,' +` 0xc3,0x05,0x4d,0x05,0x9e,0x04,0x43,0x04,' +` 0x11,0x03,0x06,0x02,0x03,0x02,0x84,0x01,' +` 0x45,0x01,0xec,0x00,0xb7,0x00,0x79,0x00,' +` 0x53,0x00,0x2b,0x00,0x37,0x00,0x23,0x00,' +` 0x13,0x00,0x07,0x00,0x00,0x00,0xfd,0xff,' +` 0xf7,0xff,0xf1,0xff,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfb,0xff,0xf2,0xff,0xf6,0xff,0xea,0xff,' +` 0x05,0x00,0xf7,0xff,0x17,0x00,0x09,0x00,' +` 0x31,0x00,0x02,0x00,0x60,0x00,0x42,0x00,' +` 0xc4,0x00,0xa3,0x00,0x52,0x01,0x28,0x01,' +` 0x0d,0x02,0xad,0x01,0x71,0x02,0xb0,0x02,' +` 0xfb,0x04,0x62,0x04,0x34,0x06,0x62,0x05,' +` 0x76,0x07,0x45,0x06,0x69,0x08,0x2e,0x06,' +` 0x54,0x09,0x4d,0x06,0x73,0x0a,0x95,0x05,' +` 0x35,0x0c,0x5d,0x02,0x6c,0x15,0x80,0x44,' +` 0x5a,0xfe,0x3e,0x0c,0x70,0x03,0xf8,0x08,' +` 0xde,0x03,0x26,0x07,0x76,0x03,0xa8,0x05,' +` 0x7f,0x01,0x81,0x02,0x8e,0x00,0xa0,0x01,' +` 0x0a,0x00,0xea,0x00,0xb6,0xff,0xcf,0x00,' +` 0xe8,0xff,0x2c,0x00,0x68,0xff,0xf5,0xff,' +` 0x72,0xff,0xe5,0xff,0x86,0xff,0xdd,0xff,' +` 0x99,0xff,0xda,0xff,0xa1,0xff,0xd3,0xff,' +` 0xb9,0xff,0xdc,0xff,0xd4,0xff,0xf9,0xff,' +` 0xed,0xff,0xfb,0xff,0xf5,0xff,0xfc,0xff,' +` 0xfb,0xff,0xff,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0x0c,0x00,' +` 0x1d,0x00,0x28,0x00,0x46,0x00,0x46,0x00,' +` 0x6d,0x00,0x67,0x00,0xa5,0x00,0x56,0x00,' +` 0x84,0x00,0xee,0xff,0x24,0x00,0x28,0xff,' +` 0x36,0xff,0xc5,0xfd,0xca,0xfd,0xdb,0xfb,' +` 0xe7,0xfb,0x77,0xf9,0x8b,0xf9,0xe6,0xf5,' +` 0x5c,0xf6,0x05,0xf2,0xf8,0xf2,0xd4,0xee,' +` 0xa8,0xf0,0xef,0xeb,0xff,0xee,0x54,0xe9,' +` 0xfc,0xec,0x88,0xe6,0x9d,0xed,0x6b,0xe5,' +` 0xaa,0xf0,0xc3,0xe3,0x46,0xf8,0x0d,0xd9,' +` 0xe1,0x65,0x92,0x12,0xd1,0xe4,0x61,0xfe,' +` 0x55,0xf0,0x2e,0xfe,0x6f,0xf6,0x07,0x00,' +` 0xc5,0xfa,0x44,0x02,0x44,0xff,0x4b,0x04,' +` 0x58,0x01,0x1b,0x05,0x98,0x02,0x49,0x05,' +` 0x8a,0x03,0xef,0x05,0x52,0x03,0x19,0x04,' +` 0x4f,0x02,0x0a,0x03,0x80,0x01,0xfa,0x01,' +` 0xc9,0x00,0x1f,0x01,0x3f,0x00,0x71,0x00,' +` 0xc7,0xff,0x02,0x00,0xa3,0xff,0xd4,0xff,' +` 0xc0,0xff,0xe8,0xff,0xd0,0xff,0xea,0xff,' +` 0xe6,0xff,0xf6,0xff,0xf9,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xf8,0xff,0xf7,0xff,0xe4,0xff,0xee,0xff,' +` 0xcb,0xff,0xf2,0xff,0xb3,0xff,0xe2,0xff,' +` 0x98,0xff,0x1b,0x00,0xb6,0xff,0x99,0x00,' +` 0x24,0x00,0x51,0x01,0xa1,0x00,0x3b,0x02,' +` 0x48,0x01,0x5d,0x03,0xfe,0x01,0x80,0x04,' +` 0x01,0x03,0x5b,0x06,0xcb,0x02,0xcc,0x05,' +` 0xc7,0x01,0xbe,0x05,0x44,0x00,0x1b,0x05,' +` 0xcf,0xfd,0x17,0x03,0xf4,0xf8,0x82,0x01,' +` 0xd9,0xf3,0x94,0x00,0x46,0xec,0x46,0x03,' +` 0x43,0xdb,0x93,0x2f,0xf8,0x51,0x61,0xd2,' +` 0x4e,0xfc,0x4e,0xe0,0xf4,0xf2,0x2e,0xe3,' +` 0x33,0xef,0xfd,0xe4,0x4f,0xee,0x69,0xe8,' +` 0xf4,0xef,0x36,0xeb,0x79,0xf1,0x58,0xee,' +` 0xa5,0xf3,0xd2,0xf1,0x0b,0xf7,0xb8,0xf5,' +` 0x30,0xfa,0x48,0xf9,0x5e,0xfc,0xc0,0xfb,' +` 0x27,0xfe,0xb6,0xfd,0x7d,0xff,0x20,0xff,' +` 0x55,0x00,0xe5,0xff,0xa8,0x00,0x51,0x00,' +` 0xbc,0x00,0x5e,0x00,0x78,0x00,0x44,0x00,' +` 0x4c,0x00,0x27,0x00,0x1f,0x00,0x0b,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xfd,0xff,0xfa,0xff,' +` 0xf9,0xff,0xf6,0xff,0xf4,0xff,0xf1,0xff,' +` 0xdd,0xff,0xd0,0xff,0xcb,0xff,0xc0,0xff,' +` 0xbe,0xff,0xc0,0xff,0xbd,0xff,0xb7,0xff,' +` 0xb8,0xff,0xb3,0xff,0xb3,0xff,0xb4,0xff,' +` 0xbc,0xff,0xe7,0xff,0x60,0x00,0x58,0x00,' +` 0x3e,0x00,0x67,0x00,0xbf,0x00,0xf7,0x00,' +` 0x77,0x01,0x9f,0x01,0xee,0x02,0x9b,0x04,' +` 0xf1,0x04,0x94,0x05,0xfa,0x05,0x81,0x06,' +` 0xe7,0x06,0x56,0x07,0xa6,0x07,0xee,0x47,' +` 0x2e,0x08,0x5b,0x08,0x69,0x08,0x5e,0x08,' +` 0x45,0x08,0x0c,0x08,0xd1,0x07,0x64,0x07,' +` 0x59,0x07,0x27,0x07,0x90,0x06,0x0b,0x06,' +` 0x7a,0x05,0xe4,0x04,0x5a,0x04,0xd9,0x02,' +` 0x06,0x02,0xfd,0x01,0xb3,0x01,0x5c,0x01,' +` 0x0c,0x01,0xca,0x00,0x8f,0x00,0x5f,0x00,' +` 0x38,0x00,0x18,0x00,0x1c,0x00,0x17,0x00,' +` 0x06,0x00,0x01,0x00,0xf9,0xff,0xee,0xff,' +` 0xf1,0xff,0xf5,0xff,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf4,0xff,0xf7,0xff,0xe1,0xff,0xf3,0xff,' +` 0xcc,0xff,0xfa,0xff,0xe8,0xff,0x3a,0x00,' +` 0xcd,0xff,0x7b,0x00,0x16,0x00,0x19,0x01,' +` 0x99,0x00,0x06,0x02,0x60,0x01,0x4b,0x03,' +` 0x6a,0x02,0x5e,0x04,0xfd,0x02,0x2f,0x06,' +` 0x78,0x04,0x93,0x0a,0xe2,0x08,0xaf,0x0d,' +` 0xaa,0x0a,0x9b,0x10,0xcb,0x0b,0x16,0x12,' +` 0xbd,0x0b,0xcd,0x14,0x38,0x0b,0xea,0x17,' +` 0x62,0x08,0x77,0x1d,0x25,0xfd,0x91,0x41,' +` 0x9a,0x7c,0xbf,0xf5,0x8f,0x1d,0x07,0x04,' +` 0x26,0x15,0x43,0x06,0xb4,0x10,0xfa,0x05,' +` 0x58,0x0d,0x2a,0x04,0xba,0x06,0xff,0x00,' +` 0xde,0x04,0x4f,0x00,0x5c,0x03,0x5f,0x00,' +` 0x3d,0x03,0x32,0x00,0x54,0x02,0x7f,0xff,' +` 0xf8,0x00,0x55,0xff,0x99,0x00,0x56,0xff,' +` 0x55,0x00,0x64,0xff,0x24,0x00,0x7a,0xff,' +` 0x04,0x00,0x7c,0xff,0x06,0x00,0xd0,0xff,' +` 0x07,0x00,0xdd,0xff,0xfe,0xff,0xe9,0xff,' +` 0xfb,0xff,0xf5,0xff,0xfd,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0x0a,0x00,' +` 0x1d,0x00,0x22,0x00,0x47,0x00,0x39,0x00,' +` 0x71,0x00,0x3b,0x00,0x8e,0x00,0x43,0x00,' +` 0xa7,0x00,0xea,0xff,0x47,0x00,0x09,0xff,' +` 0x74,0xff,0xa5,0xfd,0x2e,0xfe,0xb7,0xfb,' +` 0x79,0xfc,0x35,0xf9,0xb0,0xf9,0xc9,0xf5,' +` 0x67,0xf7,0x93,0xf2,0x30,0xf4,0xa8,0xee,' +` 0x23,0xf2,0x97,0xeb,0xc5,0xf0,0x47,0xe8,' +` 0xea,0xee,0x5e,0xe5,0xce,0xef,0xfc,0xe2,' +` 0x41,0xf3,0xdb,0xdf,0x9d,0xfc,0x24,0xd2,' +` 0x5c,0x45,0x06,0x3d,0xc5,0xd7,0xb9,0x03,' +` 0x48,0xea,0xe9,0xff,0xee,0xf1,0x29,0x00,' +` 0xe0,0xf6,0x24,0x01,0x06,0xfb,0x73,0x03,' +` 0xfa,0xfd,0x02,0x04,0xa9,0xff,0x37,0x04,' +` 0x59,0x01,0xb8,0x04,0x99,0x01,0xf0,0x03,' +` 0xbf,0x00,0x59,0x02,0x4e,0x00,0x8c,0x01,' +` 0xf6,0xff,0xde,0x00,0xb4,0xff,0x5f,0x00,' +` 0x93,0xff,0x09,0x00,0x7c,0xff,0xff,0xff,' +` 0xb7,0xff,0xf1,0xff,0xce,0xff,0xf2,0xff,' +` 0xe7,0xff,0xfa,0xff,0xfa,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff,' +` 0xf3,0xff,0xf2,0xff,0xdd,0xff,0xe7,0xff,' +` 0xc4,0xff,0xe3,0xff,0xb6,0xff,0xe2,0xff,' +` 0x76,0xff,0x01,0x00,0xa3,0xff,0x55,0x00,' +` 0xd9,0xff,0xd4,0x00,0x34,0x00,0x7f,0x01,' +` 0xa4,0x00,0x3e,0x02,0x53,0x01,0xe6,0x03,' +` 0x06,0x02,0x7b,0x04,0x9a,0x01,0x88,0x03,' +` 0x25,0x00,0x17,0x03,0x7d,0xfe,0x24,0x02,' +` 0x28,0xfb,0x80,0xff,0x94,0xf7,0xfd,0xfd,' +` 0x0f,0xf3,0xf8,0xfc,0x50,0xec,0x93,0xff,' +` 0x0a,0xdb,0x20,0x64,0x2d,0x13,0x84,0xdd,' +` 0x02,0xf6,0xf6,0xe3,0x17,0xf0,0xb3,0xe5,' +` 0x23,0xee,0x98,0xe7,0x1b,0xee,0x95,0xea,' +` 0x6e,0xf0,0x6d,0xed,0x36,0xf2,0x54,0xf0,' +` 0xb0,0xf4,0x4b,0xf4,0xb6,0xf7,0x23,0xf7,' +` 0x30,0xfa,0x74,0xfa,0xb6,0xfc,0x9c,0xfc,' +` 0x5c,0xfe,0x48,0xfe,0x8a,0xff,0x70,0xff,' +` 0x43,0x00,0x1e,0x00,0x8c,0x00,0x4f,0x00,' +` 0x6b,0x00,0x40,0x00,0x53,0x00,0x30,0x00,' +` 0x2d,0x00,0x16,0x00,0x0d,0x00,0x03,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfe,0xff,0xfd,0xff,0xfb,0xff,0xfa,0xff,' +` 0xf9,0xff,0xfa,0xff,0xf8,0xff,0xfb,0xff,' +` 0xe9,0xff,0xdd,0xff,0xe9,0xff,0xe6,0xff,' +` 0xeb,0xff,0xed,0xff,0xf3,0xff,0xf9,0xff,' +` 0x03,0x00,0x12,0x00,0x1a,0x00,0x5e,0x00,' +` 0xb4,0x00,0xbf,0x00,0x08,0x01,0xea,0x00,' +` 0xec,0x00,0x33,0x01,0x7e,0x01,0xc7,0x01,' +` 0x55,0x02,0x42,0x04,0xdd,0x04,0x60,0x05,' +` 0xe9,0x05,0x64,0x06,0xd4,0x06,0x38,0x07,' +` 0x95,0x07,0xe2,0x07,0x23,0x48,0x5f,0x08,' +` 0x8b,0x08,0x9d,0x08,0xa4,0x08,0x83,0x08,' +` 0x59,0x08,0x0b,0x08,0xbe,0x07,0x50,0x07,' +` 0x5e,0x07,0xe0,0x06,0x5a,0x06,0xae,0x05,' +` 0x3d,0x05,0x07,0x04,0xab,0x02,0x6c,0x02,' +` 0xdd,0x01,0xb6,0x01,0x86,0x01,0x34,0x01,' +` 0xe8,0x00,0xad,0x00,0x75,0x00,0x4e,0x00,' +` 0x28,0x00,0x11,0x00,0xfb,0xff,0x09,0x00,' +` 0xfb,0xff,0xeb,0xff,0xee,0xff,0xf0,0xff,' +` 0xf5,0xff,0xf8,0xff,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfd,0xff,0xf8,0xff,0xf9,0xff,' +` 0xf0,0xff,0xf9,0xff,0xe6,0xff,0xeb,0xff,' +` 0xe0,0xff,0x19,0x00,0x19,0x00,0x56,0x00,' +` 0x55,0x00,0xb3,0x00,0xb2,0x00,0x37,0x01,' +` 0x2e,0x01,0x98,0x01,0x89,0x01,0x63,0x02,' +` 0x44,0x02,0x57,0x03,0x0c,0x03,0x33,0x05,' +` 0x99,0x05,0xdd,0x06,0x8c,0x06,0xc2,0x07,' +` 0xb2,0x06,0xa9,0x08,0x31,0x07,0x92,0x09,' +` 0x28,0x07,0x71,0x0a,0x46,0x06,0x2c,0x0c,' +` 0xb8,0x01,0xb9,0x46,0xd8,0x10,0xc8,0x03,' +` 0x32,0x0a,0x42,0x05,0x4f,0x08,0x13,0x05,' +` 0xea,0x06,0x7a,0x04,0xb8,0x05,0xa8,0x03,' +` 0x19,0x03,0x99,0x01,0x4b,0x02,0x39,0x01,' +` 0x2a,0x02,0x48,0x01,0xaf,0x01,0xf9,0x00,' +` 0x41,0x01,0xb1,0x00,0xb2,0x00,0x25,0x00,' +` 0x62,0x00,0x0c,0x00,0x38,0x00,0xf9,0xff,' +` 0x19,0x00,0xec,0xff,0x1b,0x00,0x04,0x00,' +` 0x0b,0x00,0xf5,0xff,0xff,0xff,0xf6,0xff,' +` 0xfc,0xff,0xf9,0xff,0xfd,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x09,0x00,0x16,0x00,0x1f,0x00,0x32,0x00,' +` 0x35,0x00,0x48,0x00,0x3c,0x00,0x51,0x00,' +` 0x1b,0x00,0x4a,0x00,0xeb,0xff,0xd0,0xff,' +` 0x24,0xff,0xec,0xfe,0xf0,0xfd,0xa0,0xfd,' +` 0x34,0xfc,0x44,0xfb,0x9b,0xf9,0x20,0xf9,' +` 0x32,0xf7,0xd4,0xf6,0xb1,0xf4,0xeb,0xf3,' +` 0x1d,0xf1,0x83,0xf1,0xcf,0xee,0x03,0xef,' +` 0x97,0xeb,0xa0,0xed,0x16,0xea,0x69,0xed,' +` 0x23,0xe9,0xa7,0xee,0x5c,0xe8,0x09,0xf3,' +` 0xed,0xe2,0x4b,0x6d,0x41,0xfe,0x71,0xeb,' +` 0x74,0xf7,0x8f,0xf1,0x52,0xf8,0x30,0xf5,' +` 0xfe,0xf9,0x22,0xf8,0xc4,0xfb,0xb3,0xfa,' +` 0x72,0xfe,0x67,0xfd,0x7a,0xff,0xbf,0xfe,' +` 0x0f,0x01,0x23,0x00,0x30,0x01,0x58,0x00,' +` 0x0e,0x01,0x67,0x00,0x72,0x00,0x9b,0xff,' +` 0x09,0x00,0x87,0xff,0xd4,0xff,0x7d,0xff,' +` 0xba,0xff,0x85,0xff,0xe8,0xff,0xcf,0xff,' +` 0xe5,0xff,0xcc,0xff,0xe6,0xff,0xe1,0xff,' +` 0xf1,0xff,0xf2,0xff,0xfb,0xff,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xf9,0xff,0xf5,0xff,0xeb,0xff,0xe7,0xff,' +` 0xd8,0xff,0xd8,0xff,0xcc,0xff,0xe2,0xff,' +` 0xc6,0xff,0xa7,0xff,0x82,0xff,0xaa,0xff,' +` 0x88,0xff,0xc5,0xff,0xa2,0xff,0xf1,0xff,' +` 0xdc,0xff,0xce,0x00,0x71,0x00,0xe6,0x00,' +` 0x68,0x00,0xdc,0x00,0x21,0x00,0xda,0xff,' +` 0x3c,0xfe,0xb2,0xfe,0xea,0xfc,0x68,0xfc,' +` 0xc9,0xf9,0x62,0xfa,0x57,0xf7,0x57,0xf8,' +` 0x7d,0xf4,0x74,0xf6,0xe5,0xf0,0x7d,0xf5,' +` 0xae,0xe9,0xab,0x6e,0xed,0xf5,0x87,0xe9,' +` 0xc6,0xee,0xf7,0xe9,0xe2,0xec,0x5f,0xea,' +` 0xa7,0xec,0x6e,0xeb,0x80,0xed,0x3c,0xed,' +` 0x2e,0xf0,0x47,0xf0,0x37,0xf2,0xed,0xf2,' +` 0x8c,0xf5,0x12,0xf6,0xdf,0xf7,0x88,0xf8,' +` 0x23,0xfa,0xcc,0xfa,0x91,0xfc,0x4e,0xfd,' +` 0x3d,0xfe,0xb0,0xfe,0x5d,0xff,0xa6,0xff,' +` 0x13,0x00,0x34,0x00,0x3e,0x00,0x3e,0x00,' +` 0x51,0x00,0x3f,0x00,0x40,0x00,0x2e,0x00,' +` 0x24,0x00,0x15,0x00,0x0b,0x00,0x03,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xfd,0xff,0xfb,0xff,0xfb,0xff,0xfa,0xff,' +` 0xfc,0xff,0xfc,0xff,0x05,0x00,0x0f,0x00,' +` 0x15,0x00,0x02,0x00,0x09,0x00,0x13,0x00,' +` 0x22,0x00,0x30,0x00,0x45,0x00,0x54,0x00,' +` 0x83,0x00,0xe8,0x00,0x10,0x01,0x40,0x01,' +` 0x6e,0x01,0x9f,0x01,0xdd,0x01,0xc5,0x01,' +` 0xcf,0x01,0x30,0x02,0x6a,0x02,0x31,0x04,' +` 0xfe,0x04,0x58,0x05,0xe2,0x05,0x4d,0x06,' +` 0xca,0x06,0x2e,0x07,0x90,0x07,0xd5,0x07,' +` 0x1f,0x08,0x46,0x48,0x7f,0x08,0x94,0x08,' +` 0xa8,0x08,0x9d,0x08,0x8f,0x08,0x5f,0x08,' +` 0x29,0x08,0xca,0x07,0x6d,0x07,0xff,0x06,' +` 0x08,0x07,0x64,0x06,0xfa,0x05,0xf6,0x04,' +` 0x66,0x03,0x02,0x03,0x85,0x02,0x20,0x02,' +` 0xbc,0x01,0x5f,0x01,0x46,0x01,0x12,0x01,' +` 0xca,0x00,0x96,0x00,0x66,0x00,0x41,0x00,' +` 0x23,0x00,0x0c,0x00,0xe9,0xff,0xe0,0xff,' +` 0xe9,0xff,0xf3,0xff,0xf2,0xff,0xf6,0xff,' +` 0xf8,0xff,0xfc,0xff,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xfc,0xff,' +` 0xf6,0xff,0xf1,0xff,0xef,0xff,0xf3,0xff,' +` 0xf4,0xff,0x03,0x00,0x08,0x00,0x2c,0x00,' +` 0x5f,0x00,0x91,0x00,0xb5,0x00,0xf4,0x00,' +` 0xe9,0x00,0x46,0x01,0x78,0x01,0xf3,0x01,' +` 0x2b,0x02,0xbe,0x02,0xf4,0x02,0x9e,0x03,' +` 0xc9,0x03,0xb1,0x05,0x3c,0x06,0x96,0x06,' +` 0x86,0x06,0x6a,0x07,0x34,0x07,0x24,0x08,' +` 0xa3,0x07,0xc3,0x08,0xc1,0x07,0x5e,0x09,' +` 0x28,0x07,0x44,0x0b,0x2d,0x48,0xa4,0x05,' +` 0x68,0x09,0xe8,0x06,0x2b,0x08,0x9f,0x06,' +` 0x43,0x07,0x0e,0x06,0x68,0x06,0x59,0x05,' +` 0x99,0x05,0x3f,0x04,0x01,0x03,0x9a,0x02,' +` 0xf5,0x02,0x72,0x02,0x5f,0x02,0xe5,0x01,' +` 0xce,0x01,0x6a,0x01,0x54,0x01,0x02,0x01,' +` 0xe9,0x00,0x70,0x00,0x5e,0x00,0x35,0x00,' +` 0x2a,0x00,0x2e,0x00,0x2e,0x00,0x13,0x00,' +` 0x10,0x00,0x01,0x00,0x00,0x00,0xf9,0xff,' +` 0xf9,0xff,0xf6,0xff,0xfa,0xff,0xfb,0xff,' +` 0xfe,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x07,0x00,0x0f,0x00,0x17,0x00,0x21,0x00,' +` 0x2c,0x00,0x2b,0x00,0x29,0x00,0x18,0x00,' +` 0x03,0x00,0xd4,0xff,0xb0,0xff,0xa6,0xff,' +` 0x4c,0xff,0xe1,0xfe,0x4c,0xfe,0x3e,0xfd,' +` 0x91,0xfc,0xb7,0xfb,0xe7,0xfa,0xec,0xf9,' +` 0x04,0xf9,0xf4,0xf7,0x04,0xf7,0xf1,0xf5,' +` 0x39,0xf4,0x00,0xf3,0x6c,0xf1,0x05,0xf0,' +` 0x8f,0xef,0xaa,0xee,0x83,0xee,0xd2,0xed,' +` 0x07,0xee,0x78,0xed,0x24,0xee,0x7c,0xed,' +` 0x9b,0xef,0x31,0x6f,0x1d,0xef,0x5e,0xf1,' +` 0x69,0xf1,0xc1,0xf2,0x49,0xf3,0x79,0xf4,' +` 0x2f,0xf5,0x3a,0xf6,0x03,0xf7,0xdf,0xf7,' +` 0xff,0xf8,0x91,0xfa,0x3a,0xfb,0xba,0xfc,' +` 0xf9,0xfc,0x89,0xfd,0xd0,0xfd,0x41,0xfe,' +` 0x78,0xfe,0xcc,0xfe,0xf5,0xfe,0x2e,0xff,' +` 0xd9,0xfe,0xf1,0xfe,0x15,0xff,0x3b,0xff,' +` 0x9f,0xff,0xc3,0xff,0xce,0xff,0xdf,0xff,' +` 0xe9,0xff,0xf3,0xff,0xfa,0xff,0xfb,0xff,' +` 0xfc,0xff,0x00,0x00,0x01,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfa,0xff,0xf8,0xff,0xf6,0xff,' +` 0xef,0xff,0xe3,0xff,0xd8,0xff,0xc5,0xff,' +` 0xba,0xff,0x8f,0xff,0x2b,0xff,0x0a,0xff,' +` 0xe0,0xfe,0xca,0xfe,0x19,0xff,0xe2,0xfe,' +` 0xb3,0xfe,0x63,0xfe,0x23,0xfe,0xb8,0xfd,' +` 0x67,0xfd,0xe0,0xfc,0x93,0xfc,0x23,0xfb,' +` 0x5c,0xfa,0xb7,0xf8,0xbe,0xf7,0xde,0xf6,' +` 0x12,0xf6,0x0e,0xf5,0x4f,0xf4,0x2d,0xf3,' +` 0x95,0xf2,0x58,0xf1,0x28,0xf1,0x2a,0xef,' +` 0x19,0x6f,0x57,0xef,0x83,0xed,0x0b,0xee,' +` 0x7c,0xed,0xfc,0xed,0xda,0xed,0x84,0xee,' +` 0xb7,0xee,0x9b,0xef,0x18,0xf0,0x82,0xf1,' +` 0x15,0xf3,0x71,0xf4,0x20,0xf6,0x18,0xf7,' +` 0x18,0xf8,0x1e,0xf9,0x0f,0xfa,0x01,0xfb,' +` 0xd8,0xfb,0xa8,0xfc,0x5f,0xfd,0x6a,0xfe,' +` 0xf7,0xfe,0x60,0xff,0xb7,0xff,0xbf,0xff,' +` 0xe2,0xff,0x0d,0x00,0x21,0x00,0x30,0x00,' +` 0x31,0x00,0x2f,0x00,0x23,0x00,0x19,0x00,' +` 0x0f,0x00,0x08,0x00,0x02,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xfc,0xff,0xfa,0xff,' +` 0xf8,0xff,0xf9,0xff,0xfd,0xff,0x01,0x00,' +` 0x08,0x00,0x11,0x00,0x1d,0x00,0x2e,0x00,' +` 0x3c,0x00,0x2c,0x00,0x46,0x00,0x5e,0x00,' +` 0x88,0x00,0xea,0x00,0x1c,0x01,0x51,0x01,' +` 0x8a,0x01,0xc8,0x01,0x0c,0x02,0x55,0x02,' +` 0x9f,0x02,0xe8,0x02,0xde,0x02,0xe6,0x02,' +` 0x95,0x04,0x69,0x05,0xaf,0x05,0x27,0x06,' +` 0x79,0x06,0xe2,0x06,0x31,0x07,0x8d,0x07,' +` 0xd2,0x07,0x1e,0x08,0x42,0x08,0x61,0x48,' +` 0x75,0x08,0x85,0x08,0x75,0x08,0x65,0x08,' +` 0x36,0x08,0x08,0x08,0xbd,0x07,0x77,0x07,' +` 0x17,0x07,0xb5,0x06,0x43,0x06,0x54,0x06,' +` 0x6e,0x05,0xd2,0x03,0x71,0x03,0xfb,0x02,' +` 0x97,0x02,0x2d,0x02,0xd1,0x01,0x77,0x01,' +` 0x2b,0x01,0xe6,0x00,0xdc,0x00,0xb3,0x00,' +` 0x80,0x00,0x5c,0x00,0x1f,0x00,0x06,0x00,' +` 0xfa,0xff,0xf2,0xff,0xee,0xff,0xee,0xff,' +` 0xee,0xff,0xf6,0xff,0xfb,0xff,0xfc,0xff,' +` 0xfe,0xff,0xff,0xff,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfe,0xff,0xfc,0xff,' +` 0xf8,0xff,0xf7,0xff,0xf4,0xff,0xf7,0xff,' +` 0xf7,0xff,0x00,0x00,0x05,0x00,0x17,0x00,' +` 0x23,0x00,0x41,0x00,0x55,0x00,0x82,0x00,' +` 0xa2,0x00,0xdf,0x00,0x0b,0x01,0x5a,0x01,' +` 0x90,0x01,0xf0,0x01,0x2c,0x02,0x9b,0x02,' +` 0xdb,0x02,0x57,0x03,0x97,0x03,0x1f,0x04,' +` 0x32,0x05,0x02,0x06,0x18,0x06,0xc6,0x06,' +` 0xc8,0x06,0x7b,0x07,0x53,0x07,0x1a,0x08,' +` 0xab,0x07,0xae,0x08,0x9b,0x07,0xdb,0x09,' +` 0x58,0x48,0x04,0x07,0xed,0x08,0xa8,0x07,' +` 0x37,0x08,0x68,0x07,0x93,0x07,0xe8,0x06,' +` 0xdb,0x06,0x42,0x06,0x0d,0x06,0x8c,0x05,' +` 0xfe,0x04,0xa9,0x03,0x82,0x03,0xf6,0x02,' +` 0xbe,0x02,0x47,0x02,0x0d,0x02,0xa8,0x01,' +` 0x73,0x01,0x20,0x01,0xf3,0x00,0xb2,0x00,' +` 0x8d,0x00,0x5e,0x00,0x4a,0x00,0x2a,0x00,' +` 0x1d,0x00,0x0a,0x00,0x03,0x00,0xfa,0xff,' +` 0xf8,0xff,0xf6,0xff,0xf7,0xff,0xf9,0xff,' +` 0xfb,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x08,0x00,0x10,0x00,0x13,0x00,' +` 0x16,0x00,0x15,0x00,0x10,0x00,0x04,0x00,' +` 0xf3,0xff,0xd7,0xff,0xb5,0xff,0x86,0xff,' +` 0x4f,0xff,0x06,0xff,0xb3,0xfe,0x51,0xfe,' +` 0xdd,0xfd,0x5e,0xfd,0xd0,0xfc,0x38,0xfc,' +` 0x92,0xfb,0xe8,0xfa,0x2d,0xfa,0x77,0xf9,' +` 0xac,0xf8,0xf4,0xf7,0x76,0xf5,0x32,0xf4,' +` 0x95,0xf3,0xbc,0xf2,0x21,0xf2,0x6b,0xf1,' +` 0xe9,0xf0,0x58,0xf0,0xfb,0xef,0x94,0xef,' +` 0x62,0xef,0x28,0xef,0x1c,0x6f,0x3b,0xef,' +` 0x85,0xef,0xc6,0xef,0x3e,0xf0,0xa7,0xf0,' +` 0x48,0xf1,0xd2,0xf1,0x97,0xf2,0x35,0xf3,' +` 0x1e,0xf4,0xb3,0xf4,0x26,0xf6,0x7f,0xf8,' +` 0x20,0xf9,0xf2,0xf9,0x9e,0xfa,0x58,0xfb,' +` 0xfa,0xfb,0x9a,0xfc,0x29,0xfd,0xaf,0xfd,' +` 0x26,0xfe,0x8f,0xfe,0xee,0xfe,0x3b,0xff,' +` 0x73,0xff,0xa5,0xff,0xcb,0xff,0xe8,0xff,' +` 0xfd,0xff,0x0a,0x00,0x11,0x00,0x13,0x00,' +` 0x12,0x00,0x0e,0x00,0x0a,0x00,0x04,0x00,' +` 0x01,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x08,0x00,' +` 0x10,0x00,0x13,0x00,0x16,0x00,0x15,0x00,' +` 0x10,0x00,0x04,0x00,0xf3,0xff,0xd7,0xff,' +` 0xb5,0xff,0x86,0xff,0x4f,0xff,0x06,0xff,' +` 0xb3,0xfe,0x51,0xfe,0xdd,0xfd,0x5e,0xfd,' +` 0xd0,0xfc,0x38,0xfc,0x92,0xfb,0xe8,0xfa,' +` 0x2d,0xfa,0x77,0xf9,0xac,0xf8,0xf4,0xf7,' +` 0x76,0xf5,0x32,0xf4,0x95,0xf3,0xbc,0xf2,' +` 0x21,0xf2,0x6b,0xf1,0xe9,0xf0,0x58,0xf0,' +` 0xfb,0xef,0x94,0xef,0x62,0xef,0x28,0xef,' +` 0x1c,0x6f,0x3b,0xef,0x85,0xef,0xc6,0xef,' +` 0x3e,0xf0,0xa7,0xf0,0x48,0xf1,0xd2,0xf1,' +` 0x97,0xf2,0x35,0xf3,0x1e,0xf4,0xb3,0xf4,' +` 0x26,0xf6,0x7f,0xf8,0x20,0xf9,0xf2,0xf9,' +` 0x9e,0xfa,0x58,0xfb,0xfa,0xfb,0x9a,0xfc,' +` 0x29,0xfd,0xaf,0xfd,0x26,0xfe,0x8f,0xfe,' +` 0xee,0xfe,0x3b,0xff,0x73,0xff,0xa5,0xff,' +` 0xcb,0xff,0xe8,0xff,0xfd,0xff,0x0a,0x00,' +` 0x11,0x00,0x13,0x00,0x12,0x00,0x0e,0x00,' +` 0x0a,0x00,0x04,0x00,0x01,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfe,0xff,0xfc,0xff,0xf8,0xff,0xf7,0xff,' +` 0xf4,0xff,0xf7,0xff,0xf7,0xff,0x00,0x00,' +` 0x05,0x00,0x17,0x00,0x23,0x00,0x41,0x00,' +` 0x55,0x00,0x82,0x00,0xa2,0x00,0xdf,0x00,' +` 0x0b,0x01,0x5a,0x01,0x90,0x01,0xf0,0x01,' +` 0x2c,0x02,0x9b,0x02,0xdb,0x02,0x57,0x03,' +` 0x97,0x03,0x1f,0x04,0x32,0x05,0x02,0x06,' +` 0x18,0x06,0xc6,0x06,0xc8,0x06,0x7b,0x07,' +` 0x53,0x07,0x1a,0x08,0xab,0x07,0xae,0x08,' +` 0x9b,0x07,0xdb,0x09,0x58,0x48,0x04,0x07,' +` 0xed,0x08,0xa8,0x07,0x37,0x08,0x68,0x07,' +` 0x93,0x07,0xe8,0x06,0xdb,0x06,0x42,0x06,' +` 0x0d,0x06,0x8c,0x05,0xfe,0x04,0xa9,0x03,' +` 0x82,0x03,0xf6,0x02,0xbe,0x02,0x47,0x02,' +` 0x0d,0x02,0xa8,0x01,0x73,0x01,0x20,0x01,' +` 0xf3,0x00,0xb2,0x00,0x8d,0x00,0x5e,0x00,' +` 0x4a,0x00,0x2a,0x00,0x1d,0x00,0x0a,0x00,' +` 0x03,0x00,0xfa,0xff,0xf8,0xff,0xf6,0xff,' +` 0xf7,0xff,0xf9,0xff,0xfb,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xfc,0xff,0xfa,0xff,0xf8,0xff,0xf9,0xff,' +` 0xfd,0xff,0x01,0x00,0x08,0x00,0x11,0x00,' +` 0x1d,0x00,0x2e,0x00,0x3c,0x00,0x2c,0x00,' +` 0x46,0x00,0x5e,0x00,0x88,0x00,0xea,0x00,' +` 0x1c,0x01,0x51,0x01,0x8a,0x01,0xc8,0x01,' +` 0x0c,0x02,0x55,0x02,0x9f,0x02,0xe8,0x02,' +` 0xde,0x02,0xe6,0x02,0x95,0x04,0x69,0x05,' +` 0xaf,0x05,0x27,0x06,0x79,0x06,0xe2,0x06,' +` 0x31,0x07,0x8d,0x07,0xd2,0x07,0x1e,0x08,' +` 0x42,0x08,0x61,0x48,0x75,0x08,0x85,0x08,' +` 0x75,0x08,0x65,0x08,0x36,0x08,0x08,0x08,' +` 0xbd,0x07,0x77,0x07,0x17,0x07,0xb5,0x06,' +` 0x43,0x06,0x54,0x06,0x6e,0x05,0xd2,0x03,' +` 0x71,0x03,0xfb,0x02,0x97,0x02,0x2d,0x02,' +` 0xd1,0x01,0x77,0x01,0x2b,0x01,0xe6,0x00,' +` 0xdc,0x00,0xb3,0x00,0x80,0x00,0x5c,0x00,' +` 0x1f,0x00,0x06,0x00,0xfa,0xff,0xf2,0xff,' +` 0xee,0xff,0xee,0xff,0xee,0xff,0xf6,0xff,' +` 0xfb,0xff,0xfc,0xff,0xfe,0xff,0xff,0xff,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfa,0xff,' +` 0xf8,0xff,0xf6,0xff,0xef,0xff,0xe3,0xff,' +` 0xd8,0xff,0xc5,0xff,0xba,0xff,0x8f,0xff,' +` 0x2b,0xff,0x0a,0xff,0xe0,0xfe,0xca,0xfe,' +` 0x19,0xff,0xe2,0xfe,0xb3,0xfe,0x63,0xfe,' +` 0x23,0xfe,0xb8,0xfd,0x67,0xfd,0xe0,0xfc,' +` 0x93,0xfc,0x23,0xfb,0x5c,0xfa,0xb7,0xf8,' +` 0xbe,0xf7,0xde,0xf6,0x12,0xf6,0x0e,0xf5,' +` 0x4f,0xf4,0x2d,0xf3,0x95,0xf2,0x58,0xf1,' +` 0x28,0xf1,0x2a,0xef,0x19,0x6f,0x57,0xef,' +` 0x83,0xed,0x0b,0xee,0x7c,0xed,0xfc,0xed,' +` 0xda,0xed,0x84,0xee,0xb7,0xee,0x9b,0xef,' +` 0x18,0xf0,0x82,0xf1,0x15,0xf3,0x71,0xf4,' +` 0x20,0xf6,0x18,0xf7,0x18,0xf8,0x1e,0xf9,' +` 0x0f,0xfa,0x01,0xfb,0xd8,0xfb,0xa8,0xfc,' +` 0x5f,0xfd,0x6a,0xfe,0xf7,0xfe,0x60,0xff,' +` 0xb7,0xff,0xbf,0xff,0xe2,0xff,0x0d,0x00,' +` 0x21,0x00,0x30,0x00,0x31,0x00,0x2f,0x00,' +` 0x23,0x00,0x19,0x00,0x0f,0x00,0x08,0x00,' +` 0x02,0x00,0x00,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x07,0x00,0x0f,0x00,' +` 0x17,0x00,0x21,0x00,0x2c,0x00,0x2b,0x00,' +` 0x29,0x00,0x18,0x00,0x03,0x00,0xd4,0xff,' +` 0xb0,0xff,0xa6,0xff,0x4c,0xff,0xe1,0xfe,' +` 0x4c,0xfe,0x3e,0xfd,0x91,0xfc,0xb7,0xfb,' +` 0xe7,0xfa,0xec,0xf9,0x04,0xf9,0xf4,0xf7,' +` 0x04,0xf7,0xf1,0xf5,0x39,0xf4,0x00,0xf3,' +` 0x6c,0xf1,0x05,0xf0,0x8f,0xef,0xaa,0xee,' +` 0x83,0xee,0xd2,0xed,0x07,0xee,0x78,0xed,' +` 0x24,0xee,0x7c,0xed,0x9b,0xef,0x31,0x6f,' +` 0x1d,0xef,0x5e,0xf1,0x69,0xf1,0xc1,0xf2,' +` 0x49,0xf3,0x79,0xf4,0x2f,0xf5,0x3a,0xf6,' +` 0x03,0xf7,0xdf,0xf7,0xff,0xf8,0x91,0xfa,' +` 0x3a,0xfb,0xba,0xfc,0xf9,0xfc,0x89,0xfd,' +` 0xd0,0xfd,0x41,0xfe,0x78,0xfe,0xcc,0xfe,' +` 0xf5,0xfe,0x2e,0xff,0xd9,0xfe,0xf1,0xfe,' +` 0x15,0xff,0x3b,0xff,0x9f,0xff,0xc3,0xff,' +` 0xce,0xff,0xdf,0xff,0xe9,0xff,0xf3,0xff,' +` 0xfa,0xff,0xfb,0xff,0xfc,0xff,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xfc,0xff,0xf6,0xff,0xf1,0xff,' +` 0xef,0xff,0xf3,0xff,0xf4,0xff,0x03,0x00,' +` 0x08,0x00,0x2c,0x00,0x5f,0x00,0x91,0x00,' +` 0xb5,0x00,0xf4,0x00,0xe9,0x00,0x46,0x01,' +` 0x78,0x01,0xf3,0x01,0x2b,0x02,0xbe,0x02,' +` 0xf4,0x02,0x9e,0x03,0xc9,0x03,0xb1,0x05,' +` 0x3c,0x06,0x96,0x06,0x86,0x06,0x6a,0x07,' +` 0x34,0x07,0x24,0x08,0xa3,0x07,0xc3,0x08,' +` 0xc1,0x07,0x5e,0x09,0x28,0x07,0x44,0x0b,' +` 0x2d,0x48,0xa4,0x05,0x68,0x09,0xe8,0x06,' +` 0x2b,0x08,0x9f,0x06,0x43,0x07,0x0e,0x06,' +` 0x68,0x06,0x59,0x05,0x99,0x05,0x3f,0x04,' +` 0x01,0x03,0x9a,0x02,0xf5,0x02,0x72,0x02,' +` 0x5f,0x02,0xe5,0x01,0xce,0x01,0x6a,0x01,' +` 0x54,0x01,0x02,0x01,0xe9,0x00,0x70,0x00,' +` 0x5e,0x00,0x35,0x00,0x2a,0x00,0x2e,0x00,' +` 0x2e,0x00,0x13,0x00,0x10,0x00,0x01,0x00,' +` 0x00,0x00,0xf9,0xff,0xf9,0xff,0xf6,0xff,' +` 0xfa,0xff,0xfb,0xff,0xfe,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xfd,0xff,0xfb,0xff,' +` 0xfb,0xff,0xfa,0xff,0xfc,0xff,0xfc,0xff,' +` 0x05,0x00,0x0f,0x00,0x15,0x00,0x02,0x00,' +` 0x09,0x00,0x13,0x00,0x22,0x00,0x30,0x00,' +` 0x45,0x00,0x54,0x00,0x83,0x00,0xe8,0x00,' +` 0x10,0x01,0x40,0x01,0x6e,0x01,0x9f,0x01,' +` 0xdd,0x01,0xc5,0x01,0xcf,0x01,0x30,0x02,' +` 0x6a,0x02,0x31,0x04,0xfe,0x04,0x58,0x05,' +` 0xe2,0x05,0x4d,0x06,0xca,0x06,0x2e,0x07,' +` 0x90,0x07,0xd5,0x07,0x1f,0x08,0x46,0x48,' +` 0x7f,0x08,0x94,0x08,0xa8,0x08,0x9d,0x08,' +` 0x8f,0x08,0x5f,0x08,0x29,0x08,0xca,0x07,' +` 0x6d,0x07,0xff,0x06,0x08,0x07,0x64,0x06,' +` 0xfa,0x05,0xf6,0x04,0x66,0x03,0x02,0x03,' +` 0x85,0x02,0x20,0x02,0xbc,0x01,0x5f,0x01,' +` 0x46,0x01,0x12,0x01,0xca,0x00,0x96,0x00,' +` 0x66,0x00,0x41,0x00,0x23,0x00,0x0c,0x00,' +` 0xe9,0xff,0xe0,0xff,0xe9,0xff,0xf3,0xff,' +` 0xf2,0xff,0xf6,0xff,0xf8,0xff,0xfc,0xff,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xf9,0xff,0xf5,0xff,' +` 0xeb,0xff,0xe7,0xff,0xd8,0xff,0xd8,0xff,' +` 0xcc,0xff,0xe2,0xff,0xc6,0xff,0xa7,0xff,' +` 0x82,0xff,0xaa,0xff,0x88,0xff,0xc5,0xff,' +` 0xa2,0xff,0xf1,0xff,0xdc,0xff,0xce,0x00,' +` 0x71,0x00,0xe6,0x00,0x68,0x00,0xdc,0x00,' +` 0x21,0x00,0xda,0xff,0x3c,0xfe,0xb2,0xfe,' +` 0xea,0xfc,0x68,0xfc,0xc9,0xf9,0x62,0xfa,' +` 0x57,0xf7,0x57,0xf8,0x7d,0xf4,0x74,0xf6,' +` 0xe5,0xf0,0x7d,0xf5,0xae,0xe9,0xab,0x6e,' +` 0xed,0xf5,0x87,0xe9,0xc6,0xee,0xf7,0xe9,' +` 0xe2,0xec,0x5f,0xea,0xa7,0xec,0x6e,0xeb,' +` 0x80,0xed,0x3c,0xed,0x2e,0xf0,0x47,0xf0,' +` 0x37,0xf2,0xed,0xf2,0x8c,0xf5,0x12,0xf6,' +` 0xdf,0xf7,0x88,0xf8,0x23,0xfa,0xcc,0xfa,' +` 0x91,0xfc,0x4e,0xfd,0x3d,0xfe,0xb0,0xfe,' +` 0x5d,0xff,0xa6,0xff,0x13,0x00,0x34,0x00,' +` 0x3e,0x00,0x3e,0x00,0x51,0x00,0x3f,0x00,' +` 0x40,0x00,0x2e,0x00,0x24,0x00,0x15,0x00,' +` 0x0b,0x00,0x03,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x09,0x00,0x16,0x00,' +` 0x1f,0x00,0x32,0x00,0x35,0x00,0x48,0x00,' +` 0x3c,0x00,0x51,0x00,0x1b,0x00,0x4a,0x00,' +` 0xeb,0xff,0xd0,0xff,0x24,0xff,0xec,0xfe,' +` 0xf0,0xfd,0xa0,0xfd,0x34,0xfc,0x44,0xfb,' +` 0x9b,0xf9,0x20,0xf9,0x32,0xf7,0xd4,0xf6,' +` 0xb1,0xf4,0xeb,0xf3,0x1d,0xf1,0x83,0xf1,' +` 0xcf,0xee,0x03,0xef,0x97,0xeb,0xa0,0xed,' +` 0x16,0xea,0x69,0xed,0x23,0xe9,0xa7,0xee,' +` 0x5c,0xe8,0x09,0xf3,0xed,0xe2,0x4b,0x6d,' +` 0x41,0xfe,0x71,0xeb,0x74,0xf7,0x8f,0xf1,' +` 0x52,0xf8,0x30,0xf5,0xfe,0xf9,0x22,0xf8,' +` 0xc4,0xfb,0xb3,0xfa,0x72,0xfe,0x67,0xfd,' +` 0x7a,0xff,0xbf,0xfe,0x0f,0x01,0x23,0x00,' +` 0x30,0x01,0x58,0x00,0x0e,0x01,0x67,0x00,' +` 0x72,0x00,0x9b,0xff,0x09,0x00,0x87,0xff,' +` 0xd4,0xff,0x7d,0xff,0xba,0xff,0x85,0xff,' +` 0xe8,0xff,0xcf,0xff,0xe5,0xff,0xcc,0xff,' +` 0xe6,0xff,0xe1,0xff,0xf1,0xff,0xf2,0xff,' +` 0xfb,0xff,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfd,0xff,' +` 0xf8,0xff,0xf9,0xff,0xf0,0xff,0xf9,0xff,' +` 0xe6,0xff,0xeb,0xff,0xe0,0xff,0x19,0x00,' +` 0x19,0x00,0x56,0x00,0x55,0x00,0xb3,0x00,' +` 0xb2,0x00,0x37,0x01,0x2e,0x01,0x98,0x01,' +` 0x89,0x01,0x63,0x02,0x44,0x02,0x57,0x03,' +` 0x0c,0x03,0x33,0x05,0x99,0x05,0xdd,0x06,' +` 0x8c,0x06,0xc2,0x07,0xb2,0x06,0xa9,0x08,' +` 0x31,0x07,0x92,0x09,0x28,0x07,0x71,0x0a,' +` 0x46,0x06,0x2c,0x0c,0xb8,0x01,0xb9,0x46,' +` 0xd8,0x10,0xc8,0x03,0x32,0x0a,0x42,0x05,' +` 0x4f,0x08,0x13,0x05,0xea,0x06,0x7a,0x04,' +` 0xb8,0x05,0xa8,0x03,0x19,0x03,0x99,0x01,' +` 0x4b,0x02,0x39,0x01,0x2a,0x02,0x48,0x01,' +` 0xaf,0x01,0xf9,0x00,0x41,0x01,0xb1,0x00,' +` 0xb2,0x00,0x25,0x00,0x62,0x00,0x0c,0x00,' +` 0x38,0x00,0xf9,0xff,0x19,0x00,0xec,0xff,' +` 0x1b,0x00,0x04,0x00,0x0b,0x00,0xf5,0xff,' +` 0xff,0xff,0xf6,0xff,0xfc,0xff,0xf9,0xff,' +` 0xfd,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfe,0xff,0xfd,0xff,' +` 0xfb,0xff,0xfa,0xff,0xf9,0xff,0xfa,0xff,' +` 0xf8,0xff,0xfb,0xff,0xe9,0xff,0xdd,0xff,' +` 0xe9,0xff,0xe6,0xff,0xeb,0xff,0xed,0xff,' +` 0xf3,0xff,0xf9,0xff,0x03,0x00,0x12,0x00,' +` 0x1a,0x00,0x5e,0x00,0xb4,0x00,0xbf,0x00,' +` 0x08,0x01,0xea,0x00,0xec,0x00,0x33,0x01,' +` 0x7e,0x01,0xc7,0x01,0x55,0x02,0x42,0x04,' +` 0xdd,0x04,0x60,0x05,0xe9,0x05,0x64,0x06,' +` 0xd4,0x06,0x38,0x07,0x95,0x07,0xe2,0x07,' +` 0x23,0x48,0x5f,0x08,0x8b,0x08,0x9d,0x08,' +` 0xa4,0x08,0x83,0x08,0x59,0x08,0x0b,0x08,' +` 0xbe,0x07,0x50,0x07,0x5e,0x07,0xe0,0x06,' +` 0x5a,0x06,0xae,0x05,0x3d,0x05,0x07,0x04,' +` 0xab,0x02,0x6c,0x02,0xdd,0x01,0xb6,0x01,' +` 0x86,0x01,0x34,0x01,0xe8,0x00,0xad,0x00,' +` 0x75,0x00,0x4e,0x00,0x28,0x00,0x11,0x00,' +` 0xfb,0xff,0x09,0x00,0xfb,0xff,0xeb,0xff,' +` 0xee,0xff,0xf0,0xff,0xf5,0xff,0xf8,0xff,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfc,0xff,0xf3,0xff,0xf2,0xff,' +` 0xdd,0xff,0xe7,0xff,0xc4,0xff,0xe3,0xff,' +` 0xb6,0xff,0xe2,0xff,0x76,0xff,0x01,0x00,' +` 0xa3,0xff,0x55,0x00,0xd9,0xff,0xd4,0x00,' +` 0x34,0x00,0x7f,0x01,0xa4,0x00,0x3e,0x02,' +` 0x53,0x01,0xe6,0x03,0x06,0x02,0x7b,0x04,' +` 0x9a,0x01,0x88,0x03,0x25,0x00,0x17,0x03,' +` 0x7d,0xfe,0x24,0x02,0x28,0xfb,0x80,0xff,' +` 0x94,0xf7,0xfd,0xfd,0x0f,0xf3,0xf8,0xfc,' +` 0x50,0xec,0x93,0xff,0x0a,0xdb,0x20,0x64,' +` 0x2d,0x13,0x84,0xdd,0x02,0xf6,0xf6,0xe3,' +` 0x17,0xf0,0xb3,0xe5,0x23,0xee,0x98,0xe7,' +` 0x1b,0xee,0x95,0xea,0x6e,0xf0,0x6d,0xed,' +` 0x36,0xf2,0x54,0xf0,0xb0,0xf4,0x4b,0xf4,' +` 0xb6,0xf7,0x23,0xf7,0x30,0xfa,0x74,0xfa,' +` 0xb6,0xfc,0x9c,0xfc,0x5c,0xfe,0x48,0xfe,' +` 0x8a,0xff,0x70,0xff,0x43,0x00,0x1e,0x00,' +` 0x8c,0x00,0x4f,0x00,0x6b,0x00,0x40,0x00,' +` 0x53,0x00,0x30,0x00,0x2d,0x00,0x16,0x00,' +` 0x0d,0x00,0x03,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0x0a,0x00,0x1d,0x00,0x22,0x00,' +` 0x47,0x00,0x39,0x00,0x71,0x00,0x3b,0x00,' +` 0x8e,0x00,0x43,0x00,0xa7,0x00,0xea,0xff,' +` 0x47,0x00,0x09,0xff,0x74,0xff,0xa5,0xfd,' +` 0x2e,0xfe,0xb7,0xfb,0x79,0xfc,0x35,0xf9,' +` 0xb0,0xf9,0xc9,0xf5,0x67,0xf7,0x93,0xf2,' +` 0x30,0xf4,0xa8,0xee,0x23,0xf2,0x97,0xeb,' +` 0xc5,0xf0,0x47,0xe8,0xea,0xee,0x5e,0xe5,' +` 0xce,0xef,0xfc,0xe2,0x41,0xf3,0xdb,0xdf,' +` 0x9d,0xfc,0x24,0xd2,0x5c,0x45,0x06,0x3d,' +` 0xc5,0xd7,0xb9,0x03,0x48,0xea,0xe9,0xff,' +` 0xee,0xf1,0x29,0x00,0xe0,0xf6,0x24,0x01,' +` 0x06,0xfb,0x73,0x03,0xfa,0xfd,0x02,0x04,' +` 0xa9,0xff,0x37,0x04,0x59,0x01,0xb8,0x04,' +` 0x99,0x01,0xf0,0x03,0xbf,0x00,0x59,0x02,' +` 0x4e,0x00,0x8c,0x01,0xf6,0xff,0xde,0x00,' +` 0xb4,0xff,0x5f,0x00,0x93,0xff,0x09,0x00,' +` 0x7c,0xff,0xff,0xff,0xb7,0xff,0xf1,0xff,' +` 0xce,0xff,0xf2,0xff,0xe7,0xff,0xfa,0xff,' +` 0xfa,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf4,0xff,0xf7,0xff,' +` 0xe1,0xff,0xf3,0xff,0xcc,0xff,0xfa,0xff,' +` 0xe8,0xff,0x3a,0x00,0xcd,0xff,0x7b,0x00,' +` 0x16,0x00,0x19,0x01,0x99,0x00,0x06,0x02,' +` 0x60,0x01,0x4b,0x03,0x6a,0x02,0x5e,0x04,' +` 0xfd,0x02,0x2f,0x06,0x78,0x04,0x93,0x0a,' +` 0xe2,0x08,0xaf,0x0d,0xaa,0x0a,0x9b,0x10,' +` 0xcb,0x0b,0x16,0x12,0xbd,0x0b,0xcd,0x14,' +` 0x38,0x0b,0xea,0x17,0x62,0x08,0x77,0x1d,' +` 0x25,0xfd,0x91,0x41,0x9a,0x7c,0xbf,0xf5,' +` 0x8f,0x1d,0x07,0x04,0x26,0x15,0x43,0x06,' +` 0xb4,0x10,0xfa,0x05,0x58,0x0d,0x2a,0x04,' +` 0xba,0x06,0xff,0x00,0xde,0x04,0x4f,0x00,' +` 0x5c,0x03,0x5f,0x00,0x3d,0x03,0x32,0x00,' +` 0x54,0x02,0x7f,0xff,0xf8,0x00,0x55,0xff,' +` 0x99,0x00,0x56,0xff,0x55,0x00,0x64,0xff,' +` 0x24,0x00,0x7a,0xff,0x04,0x00,0x7c,0xff,' +` 0x06,0x00,0xd0,0xff,0x07,0x00,0xdd,0xff,' +` 0xfe,0xff,0xe9,0xff,0xfb,0xff,0xf5,0xff,' +` 0xfd,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xfd,0xff,0xfa,0xff,0xf9,0xff,0xf6,0xff,' +` 0xf4,0xff,0xf1,0xff,0xdd,0xff,0xd0,0xff,' +` 0xcb,0xff,0xc0,0xff,0xbe,0xff,0xc0,0xff,' +` 0xbd,0xff,0xb7,0xff,0xb8,0xff,0xb3,0xff,' +` 0xb3,0xff,0xb4,0xff,0xbc,0xff,0xe7,0xff,' +` 0x60,0x00,0x58,0x00,0x3e,0x00,0x67,0x00,' +` 0xbf,0x00,0xf7,0x00,0x77,0x01,0x9f,0x01,' +` 0xee,0x02,0x9b,0x04,0xf1,0x04,0x94,0x05,' +` 0xfa,0x05,0x81,0x06,0xe7,0x06,0x56,0x07,' +` 0xa6,0x07,0xee,0x47,0x2e,0x08,0x5b,0x08,' +` 0x69,0x08,0x5e,0x08,0x45,0x08,0x0c,0x08,' +` 0xd1,0x07,0x64,0x07,0x59,0x07,0x27,0x07,' +` 0x90,0x06,0x0b,0x06,0x7a,0x05,0xe4,0x04,' +` 0x5a,0x04,0xd9,0x02,0x06,0x02,0xfd,0x01,' +` 0xb3,0x01,0x5c,0x01,0x0c,0x01,0xca,0x00,' +` 0x8f,0x00,0x5f,0x00,0x38,0x00,0x18,0x00,' +` 0x1c,0x00,0x17,0x00,0x06,0x00,0x01,0x00,' +` 0xf9,0xff,0xee,0xff,0xf1,0xff,0xf5,0xff,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xf8,0xff,0xf7,0xff,' +` 0xe4,0xff,0xee,0xff,0xcb,0xff,0xf2,0xff,' +` 0xb3,0xff,0xe2,0xff,0x98,0xff,0x1b,0x00,' +` 0xb6,0xff,0x99,0x00,0x24,0x00,0x51,0x01,' +` 0xa1,0x00,0x3b,0x02,0x48,0x01,0x5d,0x03,' +` 0xfe,0x01,0x80,0x04,0x01,0x03,0x5b,0x06,' +` 0xcb,0x02,0xcc,0x05,0xc7,0x01,0xbe,0x05,' +` 0x44,0x00,0x1b,0x05,0xcf,0xfd,0x17,0x03,' +` 0xf4,0xf8,0x82,0x01,0xd9,0xf3,0x94,0x00,' +` 0x46,0xec,0x46,0x03,0x43,0xdb,0x93,0x2f,' +` 0xf8,0x51,0x61,0xd2,0x4e,0xfc,0x4e,0xe0,' +` 0xf4,0xf2,0x2e,0xe3,0x33,0xef,0xfd,0xe4,' +` 0x4f,0xee,0x69,0xe8,0xf4,0xef,0x36,0xeb,' +` 0x79,0xf1,0x58,0xee,0xa5,0xf3,0xd2,0xf1,' +` 0x0b,0xf7,0xb8,0xf5,0x30,0xfa,0x48,0xf9,' +` 0x5e,0xfc,0xc0,0xfb,0x27,0xfe,0xb6,0xfd,' +` 0x7d,0xff,0x20,0xff,0x55,0x00,0xe5,0xff,' +` 0xa8,0x00,0x51,0x00,0xbc,0x00,0x5e,0x00,' +` 0x78,0x00,0x44,0x00,0x4c,0x00,0x27,0x00,' +` 0x1f,0x00,0x0b,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0x0c,0x00,0x1d,0x00,0x28,0x00,' +` 0x46,0x00,0x46,0x00,0x6d,0x00,0x67,0x00,' +` 0xa5,0x00,0x56,0x00,0x84,0x00,0xee,0xff,' +` 0x24,0x00,0x28,0xff,0x36,0xff,0xc5,0xfd,' +` 0xca,0xfd,0xdb,0xfb,0xe7,0xfb,0x77,0xf9,' +` 0x8b,0xf9,0xe6,0xf5,0x5c,0xf6,0x05,0xf2,' +` 0xf8,0xf2,0xd4,0xee,0xa8,0xf0,0xef,0xeb,' +` 0xff,0xee,0x54,0xe9,0xfc,0xec,0x88,0xe6,' +` 0x9d,0xed,0x6b,0xe5,0xaa,0xf0,0xc3,0xe3,' +` 0x46,0xf8,0x0d,0xd9,0xe1,0x65,0x92,0x12,' +` 0xd1,0xe4,0x61,0xfe,0x55,0xf0,0x2e,0xfe,' +` 0x6f,0xf6,0x07,0x00,0xc5,0xfa,0x44,0x02,' +` 0x44,0xff,0x4b,0x04,0x58,0x01,0x1b,0x05,' +` 0x98,0x02,0x49,0x05,0x8a,0x03,0xef,0x05,' +` 0x52,0x03,0x19,0x04,0x4f,0x02,0x0a,0x03,' +` 0x80,0x01,0xfa,0x01,0xc9,0x00,0x1f,0x01,' +` 0x3f,0x00,0x71,0x00,0xc7,0xff,0x02,0x00,' +` 0xa3,0xff,0xd4,0xff,0xc0,0xff,0xe8,0xff,' +` 0xd0,0xff,0xea,0xff,0xe6,0xff,0xf6,0xff,' +` 0xf9,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfb,0xff,0xf2,0xff,' +` 0xf6,0xff,0xea,0xff,0x05,0x00,0xf7,0xff,' +` 0x17,0x00,0x09,0x00,0x31,0x00,0x02,0x00,' +` 0x60,0x00,0x42,0x00,0xc4,0x00,0xa3,0x00,' +` 0x52,0x01,0x28,0x01,0x0d,0x02,0xad,0x01,' +` 0x71,0x02,0xb0,0x02,0xfb,0x04,0x62,0x04,' +` 0x34,0x06,0x62,0x05,0x76,0x07,0x45,0x06,' +` 0x69,0x08,0x2e,0x06,0x54,0x09,0x4d,0x06,' +` 0x73,0x0a,0x95,0x05,0x35,0x0c,0x5d,0x02,' +` 0x6c,0x15,0x80,0x44,0x5a,0xfe,0x3e,0x0c,' +` 0x70,0x03,0xf8,0x08,0xde,0x03,0x26,0x07,' +` 0x76,0x03,0xa8,0x05,0x7f,0x01,0x81,0x02,' +` 0x8e,0x00,0xa0,0x01,0x0a,0x00,0xea,0x00,' +` 0xb6,0xff,0xcf,0x00,0xe8,0xff,0x2c,0x00,' +` 0x68,0xff,0xf5,0xff,0x72,0xff,0xe5,0xff,' +` 0x86,0xff,0xdd,0xff,0x99,0xff,0xda,0xff,' +` 0xa1,0xff,0xd3,0xff,0xb9,0xff,0xdc,0xff,' +` 0xd4,0xff,0xf9,0xff,0xed,0xff,0xfb,0xff,' +` 0xf5,0xff,0xfc,0xff,0xfb,0xff,0xff,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfc,0xff,0xfa,0xff,0xf7,0xff,' +` 0xf3,0xff,0xf1,0xff,0xdf,0xff,0xd0,0xff,' +` 0xc7,0xff,0xbb,0xff,0xaf,0xff,0xa2,0xff,' +` 0x96,0xff,0x9a,0xff,0x8f,0xff,0x87,0xff,' +` 0x78,0xff,0x78,0xff,0x6d,0xff,0x7f,0xff,' +` 0x75,0xff,0xdc,0xff,0xf0,0xff,0xd9,0xff,' +` 0x2a,0x00,0x64,0x00,0xbf,0x00,0x1a,0x01,' +` 0x80,0x01,0x16,0x02,0x22,0x04,0xc1,0x04,' +` 0x40,0x05,0xc2,0x05,0x3d,0x06,0xb2,0x06,' +` 0x1a,0x07,0x78,0x07,0xba,0x47,0x00,0x08,' +` 0x1b,0x08,0x2a,0x08,0x19,0x08,0x01,0x08,' +` 0xc7,0x07,0x89,0x07,0x2d,0x07,0x4b,0x07,' +` 0xd2,0x06,0x5d,0x06,0xc3,0x05,0x4d,0x05,' +` 0x9e,0x04,0x43,0x04,0x11,0x03,0x06,0x02,' +` 0x03,0x02,0x84,0x01,0x45,0x01,0xec,0x00,' +` 0xb7,0x00,0x79,0x00,0x53,0x00,0x2b,0x00,' +` 0x37,0x00,0x23,0x00,0x13,0x00,0x07,0x00,' +` 0x00,0x00,0xfd,0xff,0xf7,0xff,0xf1,0xff,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xfa,0xff,0xf0,0xff,' +` 0xed,0xff,0xd9,0xff,0xe2,0xff,0xc8,0xff,' +` 0xdb,0xff,0x9d,0xff,0xe9,0xff,0xb9,0xff,' +` 0x3a,0x00,0x07,0x00,0xcd,0x00,0xac,0x00,' +` 0xc9,0x01,0x78,0x01,0xea,0x02,0x71,0x02,' +` 0x29,0x04,0x66,0x03,0x4d,0x05,0x62,0x04,' +` 0xdf,0x06,0x02,0x04,0x9d,0x06,0x6d,0x03,' +` 0x3e,0x06,0xf4,0x01,0x36,0x05,0x86,0xff,' +` 0xae,0x02,0xa6,0xfa,0x4d,0x00,0xad,0xf5,' +` 0x8a,0xfe,0xa9,0xee,0x28,0x00,0x9a,0xdd,' +` 0x2d,0x67,0xc0,0x0f,0x74,0xdf,0x79,0xf5,' +` 0xe3,0xe4,0xd1,0xef,0x16,0xe6,0x84,0xed,' +` 0x35,0xe7,0x1c,0xee,0x83,0xea,0x71,0xef,' +` 0x0b,0xed,0x6a,0xf1,0x0e,0xf0,0xe9,0xf3,' +` 0x62,0xf3,0x98,0xf7,0xd2,0xf7,0x8d,0xfa,' +` 0x78,0xfa,0xb0,0xfc,0xb0,0xfc,0x65,0xfe,' +` 0x62,0xfe,0x9e,0xff,0x7b,0xff,0x3b,0x00,' +` 0x1e,0x00,0x8f,0x00,0x64,0x00,0x96,0x00,' +` 0x64,0x00,0x5c,0x00,0x38,0x00,0x31,0x00,' +` 0x19,0x00,0x0e,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0x0b,0x00,0x20,0x00,0x28,0x00,' +` 0x4f,0x00,0x45,0x00,0x86,0x00,0x73,0x00,' +` 0xbc,0x00,0x59,0x00,0xab,0x00,0xed,0xff,' +` 0x44,0x00,0x23,0xff,0x90,0xff,0xc4,0xfd,' +` 0x3c,0xfe,0xd0,0xfb,0x72,0xfc,0x54,0xf9,' +` 0x47,0xfa,0x59,0xf6,0xec,0xf6,0x90,0xf1,' +` 0xb4,0xf3,0x2e,0xee,0x75,0xf1,0x0b,0xeb,' +` 0xe5,0xef,0x60,0xe8,0xc9,0xee,0xbc,0xe4,' +` 0x9b,0xef,0x1b,0xe3,0x74,0xf3,0x3c,0xe0,' +` 0xfa,0xfc,0x68,0xd2,0xe5,0x4b,0x90,0x37,' +` 0x1a,0xda,0xbd,0x04,0x64,0xec,0xc7,0x01,' +` 0x5c,0xf4,0xba,0x02,0xc1,0xf9,0xd2,0x04,' +` 0xdc,0xfe,0x65,0x06,0x50,0x01,0x02,0x07,' +` 0xcc,0x02,0x00,0x07,0x7a,0x03,0x28,0x07,' +` 0x61,0x03,0x60,0x05,0xaf,0x02,0x16,0x04,' +` 0xd8,0x01,0xcc,0x02,0x01,0x01,0xb2,0x01,' +` 0x52,0x00,0xc0,0x00,0xdc,0xff,0x3a,0x00,' +` 0xa8,0xff,0xf2,0xff,0xa3,0xff,0xef,0xff,' +` 0xcd,0xff,0xee,0xff,0xe4,0xff,0xf6,0xff,' +` 0xf8,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf9,0xff,0xe0,0xff,' +` 0xf6,0xff,0xe0,0xff,0x1a,0x00,0xdd,0xff,' +` 0x47,0x00,0xef,0xff,0xa1,0x00,0x09,0x00,' +` 0xce,0x00,0x42,0x00,0xa1,0x01,0xe1,0x00,' +` 0xc6,0x02,0xc7,0x01,0x46,0x04,0xea,0x02,' +` 0x8f,0x05,0xb3,0x05,0x39,0x0a,0xb7,0x07,' +` 0xdd,0x0c,0x67,0x09,0x9a,0x0f,0xc5,0x0a,' +` 0x0b,0x12,0x1e,0x0a,0x38,0x14,0x88,0x09,' +` 0x88,0x17,0x72,0x06,0xd3,0x1d,0x16,0xfa,' +` 0x4b,0x48,0x5c,0x76,0xc2,0xf3,0x5f,0x1d,' +` 0x60,0x02,0x5a,0x14,0xb2,0x04,0x8c,0x0f,' +` 0xcd,0x04,0xf0,0x0a,0xde,0xff,0xf7,0x05,' +` 0x24,0xff,0xb8,0x03,0x68,0xfe,0x0f,0x02,' +` 0xe0,0xfd,0x86,0x01,0xf7,0xfd,0x16,0x00,' +` 0xda,0xfd,0xc5,0xff,0x13,0xfe,0xa7,0xff,' +` 0x69,0xfe,0xa9,0xff,0xb1,0xfe,0x8b,0xff,' +` 0xef,0xfe,0xa4,0xff,0x3b,0xff,0xbd,0xff,' +` 0x7a,0xff,0xe7,0xff,0xcc,0xff,0xf5,0xff,' +` 0xe4,0xff,0xfa,0xff,0xf5,0xff,0xfe,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfc,0xff,0xfa,0xff,0xf7,0xff,' +` 0xf3,0xff,0xee,0xff,0xda,0xff,0xce,0xff,' +` 0xc2,0xff,0xb6,0xff,0xa7,0xff,0x9b,0xff,' +` 0x88,0xff,0x89,0xff,0x81,0xff,0x74,0xff,' +` 0x65,0xff,0x61,0xff,0x58,0xff,0x64,0xff,' +` 0x60,0xff,0xa2,0xff,0xc5,0xff,0xc0,0xff,' +` 0x10,0x00,0x48,0x00,0xa9,0x00,0xfc,0x00,' +` 0x72,0x01,0xde,0x01,0xe0,0x03,0xb5,0x04,' +` 0x20,0x05,0xb1,0x05,0x22,0x06,0xa0,0x06,' +` 0x02,0x07,0x66,0x07,0xa5,0x47,0xea,0x07,' +` 0x00,0x08,0x10,0x08,0xfe,0x07,0xe5,0x07,' +` 0xac,0x07,0x69,0x07,0x1f,0x07,0x3c,0x07,' +` 0xb5,0x06,0x47,0x06,0xab,0x05,0x37,0x05,' +` 0x8b,0x04,0x2c,0x04,0x28,0x03,0x19,0x02,' +` 0xef,0x01,0x7d,0x01,0x37,0x01,0xe6,0x00,' +` 0xac,0x00,0x76,0x00,0x4a,0x00,0x37,0x00,' +` 0x3d,0x00,0x21,0x00,0x14,0x00,0x07,0x00,' +` 0x01,0x00,0xfd,0xff,0xfb,0xff,0xf2,0xff,' +` 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xfa,0xff,0xf1,0xff,' +` 0xeb,0xff,0xde,0xff,0xdd,0xff,0xd1,0xff,' +` 0xc7,0xff,0xb5,0xff,0xde,0xff,0xdf,0xff,' +` 0x2e,0x00,0x42,0x00,0xbe,0x00,0xf7,0x00,' +` 0xbd,0x01,0xee,0x01,0xdb,0x02,0x06,0x03,' +` 0x0e,0x04,0x1b,0x04,0x20,0x05,0x24,0x05,' +` 0x4e,0x06,0x09,0x05,0x22,0x06,0x9f,0x04,' +` 0x87,0x05,0x5b,0x03,0x2d,0x04,0x37,0x01,' +` 0x33,0x01,0xb9,0xfc,0x14,0xfe,0x83,0xf8,' +` 0x17,0xfb,0x38,0xf3,0x8f,0xf9,0x0e,0xe9,' +` 0x5c,0x6f,0x48,0xfa,0x57,0xe8,0xdd,0xef,' +` 0xe5,0xe8,0xad,0xec,0xa4,0xe8,0x65,0xeb,' +` 0x28,0xe9,0xd5,0xec,0xce,0xeb,0x60,0xee,' +` 0x1a,0xee,0xa0,0xf0,0xec,0xf0,0x57,0xf3,' +` 0x19,0xf4,0x7b,0xf7,0x75,0xf8,0x41,0xfa,' +` 0xf9,0xfa,0x7c,0xfc,0x16,0xfd,0x40,0xfe,' +` 0xb1,0xfe,0x7c,0xff,0xa6,0xff,0x2a,0x00,' +` 0x40,0x00,0x82,0x00,0x7a,0x00,0x8d,0x00,' +` 0x73,0x00,0x59,0x00,0x3e,0x00,0x30,0x00,' +` 0x1b,0x00,0x0d,0x00,0x50,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0x0c,0x00,0x1e,0x00,0x2b,0x00,' +` 0x49,0x00,0x4d,0x00,0x84,0x00,0x7d,0x00,' +` 0xa0,0x00,0x68,0x00,0x7e,0x00,0x02,0x00,' +` 0x01,0x00,0x3d,0xff,0x35,0xff,0xf0,0xfd,' +` 0xc3,0xfd,0x0e,0xfc,0xd6,0xfb,0xac,0xf9,' +` 0x84,0xf9,0xda,0xf6,0xb5,0xf5,0x26,0xf2,' +` 0x9e,0xf2,0x0f,0xef,0x27,0xf0,0x47,0xec,' +` 0x54,0xee,0x14,0xea,0xae,0xec,0x49,0xe7,' +` 0x28,0xed,0xba,0xe6,0xd6,0xef,0xdc,0xe5,' +` 0x78,0xf6,0x8b,0xdd,0xc8,0x6a,0x09,0x0a,' +` 0x49,0xe9,0x0e,0xfd,0x03,0xf3,0x0d,0xfe,' +` 0xbb,0xf8,0x78,0x00,0x22,0xfd,0xc9,0x03,' +` 0x52,0x01,0x6c,0x05,0x50,0x03,0x47,0x06,' +` 0x6a,0x04,0x67,0x06,0xdb,0x04,0x62,0x06,' +` 0x2a,0x04,0x08,0x05,0x58,0x03,0xc7,0x03,' +` 0x56,0x02,0x88,0x02,0x5d,0x01,0x72,0x01,' +` 0x7c,0x00,0x96,0x00,0x00,0x00,0x19,0x00,' +` 0xbe,0xff,0xdb,0xff,0xaf,0xff,0xe1,0xff,' +` 0xd3,0xff,0xe7,0xff,0xe6,0xff,0xf4,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfa,0xff,0xeb,0xff,' +` 0x00,0x00,0xf1,0xff,0x0e,0x00,0xf3,0xff,' +` 0x28,0x00,0x01,0x00,0x5b,0x00,0x15,0x00,' +` 0x71,0x00,0x38,0x00,0xe2,0x00,0x92,0x00,' +` 0x7d,0x01,0x0f,0x01,0x4c,0x02,0x99,0x01,' +` 0x60,0x03,0x7d,0x03,0x28,0x05,0x5b,0x04,' +` 0x7b,0x06,0x35,0x05,0xc9,0x07,0xe6,0x05,' +` 0xba,0x08,0x90,0x05,0xca,0x09,0x4c,0x05,' +` 0x3e,0x0b,0xc9,0x03,0x4b,0x0e,0x9a,0xfc,' +` 0x99,0x41,0x38,0x1a,0x11,0xff,0xca,0x0b,' +` 0x8f,0x02,0xa4,0x08,0xef,0x02,0xaf,0x06,' +` 0x93,0x02,0xb1,0x03,0x32,0x00,0x3b,0x02,' +` 0xba,0xff,0x40,0x01,0x55,0xff,0x84,0x00,' +` 0x20,0xff,0x44,0x00,0xed,0xfe,0xd5,0xff,' +` 0xfc,0xfe,0xb7,0xff,0x1d,0xff,0xb4,0xff,' +` 0x49,0xff,0xbc,0xff,0x61,0xff,0xbc,0xff,' +` 0x8b,0xff,0xce,0xff,0xaf,0xff,0xde,0xff,' +` 0xcc,0xff,0xf4,0xff,0xed,0xff,0xfb,0xff,' +` 0xf7,0xff,0xfe,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0xac,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm0_30_90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm0_30_90deg_16khz.m4 new file mode 100644 index 000000000000..46dd623a5b1a --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm0_30_90deg_16khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf4,0xff,0xe4,0xff,' +` 0xca,0xff,0xa8,0xff,0x79,0xff,0x41,0xff,' +` 0xfd,0xfe,0xb3,0xfe,0x5e,0xfe,0x09,0xfe,' +` 0xab,0xfd,0x56,0xfd,0x05,0xfd,0xd7,0xfc,' +` 0xb3,0xfc,0xc2,0xfc,0xf9,0xfc,0x8d,0xfd,' +` 0xac,0xfd,0xc1,0xfe,0x77,0x00,0x6a,0x02,' +` 0xd2,0x04,0x8c,0x07,0x86,0x0a,0x20,0x0d,' +` 0x25,0x12,0x75,0x16,0x38,0x17,0x7c,0x19,' +` 0x0b,0x59,0x5a,0x18,0x4f,0x17,0xa4,0x15,' +` 0x9a,0x11,0x51,0x0c,0x0a,0x0a,0xd5,0x06,' +` 0x5a,0x04,0xe3,0x01,0x37,0x00,0x78,0xfe,' +` 0xa0,0xfd,0x75,0xfd,0x0d,0xfd,0xd6,0xfc,' +` 0xe7,0xfc,0x07,0xfd,0x4a,0xfd,0x95,0xfd,' +` 0xf3,0xfd,0x49,0xfe,0xa0,0xfe,0xed,0xfe,' +` 0x34,0xff,0x6e,0xff,0xa0,0xff,0xc6,0xff,' +` 0xe1,0xff,0xf3,0xff,0xfd,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x17,0x00,0x38,0x00,0x6b,0x00,0xb1,0x00,' +` 0x0d,0x01,0x7e,0x01,0x03,0x02,0x9b,0x02,' +` 0x42,0x03,0xf1,0x03,0xa7,0x04,0x58,0x05,' +` 0xf0,0x05,0x5a,0x06,0x92,0x06,0x86,0x06,' +` 0x07,0x06,0xf4,0x04,0x9c,0x04,0x96,0x02,' +` 0x05,0xff,0x4a,0xfb,0x4a,0xf6,0x12,0xf1,' +` 0xd7,0xea,0xf8,0xe5,0x92,0xdb,0x6a,0xd3,' +` 0x1d,0xd1,0xfc,0xcd,0xbe,0x4d,0x5d,0xce,' +` 0xd3,0xd1,0x65,0xd4,0xef,0xdc,0x26,0xe7,' +` 0x07,0xec,0x2f,0xf2,0x5c,0xf7,0x1e,0xfc,' +` 0x9f,0xff,0xfa,0x02,0xcb,0x04,0x09,0x05,' +` 0xee,0x05,0x4b,0x06,0x39,0x06,0xeb,0x05,' +` 0x71,0x05,0xd1,0x04,0x1d,0x04,0x6b,0x03,' +` 0xc1,0x02,0x25,0x02,0x99,0x01,0x22,0x01,' +` 0xc0,0x00,0x75,0x00,0x3e,0x00,0x19,0x00,' +` 0x06,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x17,0x00,0x38,0x00,' +` 0x6b,0x00,0xb1,0x00,0x0d,0x01,0x7e,0x01,' +` 0x03,0x02,0x9b,0x02,0x42,0x03,0xf1,0x03,' +` 0xa7,0x04,0x58,0x05,0xf0,0x05,0x5a,0x06,' +` 0x92,0x06,0x86,0x06,0x07,0x06,0xf4,0x04,' +` 0x9c,0x04,0x96,0x02,0x05,0xff,0x4a,0xfb,' +` 0x4a,0xf6,0x12,0xf1,0xd7,0xea,0xf8,0xe5,' +` 0x92,0xdb,0x6a,0xd3,0x1d,0xd1,0xfc,0xcd,' +` 0xbe,0x4d,0x5d,0xce,0xd3,0xd1,0x65,0xd4,' +` 0xef,0xdc,0x26,0xe7,0x07,0xec,0x2f,0xf2,' +` 0x5c,0xf7,0x1e,0xfc,0x9f,0xff,0xfa,0x02,' +` 0xcb,0x04,0x09,0x05,0xee,0x05,0x4b,0x06,' +` 0x39,0x06,0xeb,0x05,0x71,0x05,0xd1,0x04,' +` 0x1d,0x04,0x6b,0x03,0xc1,0x02,0x25,0x02,' +` 0x99,0x01,0x22,0x01,0xc0,0x00,0x75,0x00,' +` 0x3e,0x00,0x19,0x00,0x06,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf4,0xff,0xe4,0xff,0xca,0xff,0xa8,0xff,' +` 0x79,0xff,0x41,0xff,0xfd,0xfe,0xb3,0xfe,' +` 0x5e,0xfe,0x09,0xfe,0xab,0xfd,0x56,0xfd,' +` 0x05,0xfd,0xd7,0xfc,0xb3,0xfc,0xc2,0xfc,' +` 0xf9,0xfc,0x8d,0xfd,0xac,0xfd,0xc1,0xfe,' +` 0x77,0x00,0x6a,0x02,0xd2,0x04,0x8c,0x07,' +` 0x86,0x0a,0x20,0x0d,0x25,0x12,0x75,0x16,' +` 0x38,0x17,0x7c,0x19,0x0b,0x59,0x5a,0x18,' +` 0x4f,0x17,0xa4,0x15,0x9a,0x11,0x51,0x0c,' +` 0x0a,0x0a,0xd5,0x06,0x5a,0x04,0xe3,0x01,' +` 0x37,0x00,0x78,0xfe,0xa0,0xfd,0x75,0xfd,' +` 0x0d,0xfd,0xd6,0xfc,0xe7,0xfc,0x07,0xfd,' +` 0x4a,0xfd,0x95,0xfd,0xf3,0xfd,0x49,0xfe,' +` 0xa0,0xfe,0xed,0xfe,0x34,0xff,0x6e,0xff,' +` 0xa0,0xff,0xc6,0xff,0xe1,0xff,0xf3,0xff,' +` 0xfd,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf4,0xff,0xe4,0xff,' +` 0xca,0xff,0xa8,0xff,0x79,0xff,0x41,0xff,' +` 0xfd,0xfe,0xb3,0xfe,0x5e,0xfe,0x09,0xfe,' +` 0xab,0xfd,0x56,0xfd,0x05,0xfd,0xd7,0xfc,' +` 0xb3,0xfc,0xc2,0xfc,0xf9,0xfc,0x8d,0xfd,' +` 0xac,0xfd,0xc1,0xfe,0x77,0x00,0x6a,0x02,' +` 0xd2,0x04,0x8c,0x07,0x86,0x0a,0x20,0x0d,' +` 0x25,0x12,0x75,0x16,0x38,0x17,0x7c,0x19,' +` 0x0b,0x59,0x5a,0x18,0x4f,0x17,0xa4,0x15,' +` 0x9a,0x11,0x51,0x0c,0x0a,0x0a,0xd5,0x06,' +` 0x5a,0x04,0xe3,0x01,0x37,0x00,0x78,0xfe,' +` 0xa0,0xfd,0x75,0xfd,0x0d,0xfd,0xd6,0xfc,' +` 0xe7,0xfc,0x07,0xfd,0x4a,0xfd,0x95,0xfd,' +` 0xf3,0xfd,0x49,0xfe,0xa0,0xfe,0xed,0xfe,' +` 0x34,0xff,0x6e,0xff,0xa0,0xff,0xc6,0xff,' +` 0xe1,0xff,0xf3,0xff,0xfd,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x17,0x00,0x38,0x00,0x6b,0x00,0xb1,0x00,' +` 0x0d,0x01,0x7e,0x01,0x03,0x02,0x9b,0x02,' +` 0x42,0x03,0xf1,0x03,0xa7,0x04,0x58,0x05,' +` 0xf0,0x05,0x5a,0x06,0x92,0x06,0x86,0x06,' +` 0x07,0x06,0xf4,0x04,0x9c,0x04,0x96,0x02,' +` 0x05,0xff,0x4a,0xfb,0x4a,0xf6,0x12,0xf1,' +` 0xd7,0xea,0xf8,0xe5,0x92,0xdb,0x6a,0xd3,' +` 0x1d,0xd1,0xfc,0xcd,0xbe,0x4d,0x5d,0xce,' +` 0xd3,0xd1,0x65,0xd4,0xef,0xdc,0x26,0xe7,' +` 0x07,0xec,0x2f,0xf2,0x5c,0xf7,0x1e,0xfc,' +` 0x9f,0xff,0xfa,0x02,0xcb,0x04,0x09,0x05,' +` 0xee,0x05,0x4b,0x06,0x39,0x06,0xeb,0x05,' +` 0x71,0x05,0xd1,0x04,0x1d,0x04,0x6b,0x03,' +` 0xc1,0x02,0x25,0x02,0x99,0x01,0x22,0x01,' +` 0xc0,0x00,0x75,0x00,0x3e,0x00,0x19,0x00,' +` 0x06,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x17,0x00,0x38,0x00,' +` 0x6b,0x00,0xb1,0x00,0x0d,0x01,0x7e,0x01,' +` 0x03,0x02,0x9b,0x02,0x42,0x03,0xf1,0x03,' +` 0xa7,0x04,0x58,0x05,0xf0,0x05,0x5a,0x06,' +` 0x92,0x06,0x86,0x06,0x07,0x06,0xf4,0x04,' +` 0x9c,0x04,0x96,0x02,0x05,0xff,0x4a,0xfb,' +` 0x4a,0xf6,0x12,0xf1,0xd7,0xea,0xf8,0xe5,' +` 0x92,0xdb,0x6a,0xd3,0x1d,0xd1,0xfc,0xcd,' +` 0xbe,0x4d,0x5d,0xce,0xd3,0xd1,0x65,0xd4,' +` 0xef,0xdc,0x26,0xe7,0x07,0xec,0x2f,0xf2,' +` 0x5c,0xf7,0x1e,0xfc,0x9f,0xff,0xfa,0x02,' +` 0xcb,0x04,0x09,0x05,0xee,0x05,0x4b,0x06,' +` 0x39,0x06,0xeb,0x05,0x71,0x05,0xd1,0x04,' +` 0x1d,0x04,0x6b,0x03,0xc1,0x02,0x25,0x02,' +` 0x99,0x01,0x22,0x01,0xc0,0x00,0x75,0x00,' +` 0x3e,0x00,0x19,0x00,0x06,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf4,0xff,0xe4,0xff,0xca,0xff,0xa8,0xff,' +` 0x79,0xff,0x41,0xff,0xfd,0xfe,0xb3,0xfe,' +` 0x5e,0xfe,0x09,0xfe,0xab,0xfd,0x56,0xfd,' +` 0x05,0xfd,0xd7,0xfc,0xb3,0xfc,0xc2,0xfc,' +` 0xf9,0xfc,0x8d,0xfd,0xac,0xfd,0xc1,0xfe,' +` 0x77,0x00,0x6a,0x02,0xd2,0x04,0x8c,0x07,' +` 0x86,0x0a,0x20,0x0d,0x25,0x12,0x75,0x16,' +` 0x38,0x17,0x7c,0x19,0x0b,0x59,0x5a,0x18,' +` 0x4f,0x17,0xa4,0x15,0x9a,0x11,0x51,0x0c,' +` 0x0a,0x0a,0xd5,0x06,0x5a,0x04,0xe3,0x01,' +` 0x37,0x00,0x78,0xfe,0xa0,0xfd,0x75,0xfd,' +` 0x0d,0xfd,0xd6,0xfc,0xe7,0xfc,0x07,0xfd,' +` 0x4a,0xfd,0x95,0xfd,0xf3,0xfd,0x49,0xfe,' +` 0xa0,0xfe,0xed,0xfe,0x34,0xff,0x6e,0xff,' +` 0xa0,0xff,0xc6,0xff,0xe1,0xff,0xf3,0xff,' +` 0xfd,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xee,0xff,' +` 0xd6,0xff,0xb1,0xff,0x7e,0xff,0x3c,0xff,' +` 0xec,0xfe,0x90,0xfe,0x28,0xfe,0xb8,0xfd,' +` 0x4b,0xfd,0xe5,0xfc,0x93,0xfc,0x4b,0xfc,' +` 0x40,0xfc,0x62,0xfc,0xdb,0xfc,0x8e,0xfc,' +` 0x35,0xfd,0x7a,0xfe,0x70,0xff,0xb3,0x00,' +` 0x7e,0x00,0x4a,0x01,0x32,0x03,0x24,0x06,' +` 0xec,0x06,0xec,0x07,0xbc,0x0f,0xfa,0x13,' +` 0xbc,0x16,0x00,0x59,0x32,0x1a,0x97,0x1a,' +` 0xf5,0x18,0xfc,0x17,0xe7,0x0f,0xed,0x09,' +` 0x95,0x07,0xad,0x04,0x69,0x01,0x2b,0xfe,' +` 0x15,0xfe,0x84,0xfd,0x85,0xfd,0x71,0xfd,' +` 0x65,0xfd,0xbf,0xfd,0x20,0xfe,0x71,0xfe,' +` 0xb2,0xfe,0xf5,0xfe,0x34,0xff,0x64,0xff,' +` 0x8c,0xff,0xad,0xff,0xc8,0xff,0xdd,0xff,' +` 0xec,0xff,0xf6,0xff,0xfc,0xff,0xff,0xff,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x13,0x00,0x23,0x00,0x62,0x00,0x7e,0x00,' +` 0x07,0x01,0x27,0x01,0x0a,0x02,0x08,0x02,' +` 0x3b,0x03,0xd5,0x02,0x30,0x04,0xfa,0x02,' +` 0x44,0x04,0xc4,0x01,0x07,0x03,0x0b,0xff,' +` 0xb7,0x00,0xcb,0xfb,0x4a,0xfe,0x12,0xf9,' +` 0x89,0xff,0x0f,0xf9,0x3a,0x00,0xff,0xfa,' +` 0x75,0x08,0xf1,0xfb,0x15,0x04,0x84,0xe7,' +` 0xac,0xf6,0x84,0xc2,0x0c,0x39,0x7e,0xff,' +` 0x7a,0xaa,0xbf,0xcc,0x0c,0xbb,0x17,0xd6,' +` 0x8e,0xd3,0x0c,0xea,0xfd,0xee,0xa4,0x00,' +` 0x0e,0x01,0xca,0x09,0xae,0x08,0xf1,0x0d,' +` 0x20,0x0b,0x7d,0x0c,0xd2,0x08,0x67,0x09,' +` 0x57,0x06,0x56,0x06,0x09,0x04,0xed,0x03,' +` 0x61,0x02,0x45,0x02,0x4e,0x01,0x2e,0x01,' +` 0x9f,0x00,0x7d,0x00,0x35,0x00,0x1d,0x00,' +` 0x05,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x06,0x00,0x15,0x00,0x3f,0x00,' +` 0x5e,0x00,0xbe,0x00,0xe1,0x00,0x8c,0x01,' +` 0xab,0x01,0xc0,0x02,0xdc,0x02,0x87,0x04,' +` 0xa7,0x04,0x0f,0x07,0x16,0x07,0x35,0x0a,' +` 0xa4,0x09,0x3d,0x0d,0xed,0x0b,0x8a,0x0e,' +` 0x30,0x09,0xd2,0x09,0x08,0x01,0x27,0x00,' +` 0x9f,0xee,0xc7,0xe8,0xc4,0xd2,0x3c,0xd4,' +` 0xd9,0xba,0x85,0xca,0x32,0xac,0x41,0xf6,' +` 0x4f,0x3f,0x58,0xc4,0xa3,0xf5,0xd1,0xe8,' +` 0x64,0x03,0xbc,0xfc,0x37,0x08,0x08,0xfc,' +` 0x3f,0x00,0xe9,0xf9,0xa5,0xff,0xf6,0xf9,' +` 0x71,0xfe,0x6f,0xfc,0xb6,0x00,0x65,0xff,' +` 0xc7,0x02,0xca,0x01,0xcf,0x03,0xbf,0x02,' +` 0xa0,0x03,0x7e,0x02,0xaf,0x02,0xb1,0x01,' +` 0x98,0x01,0xe3,0x00,0xba,0x00,0x55,0x00,' +` 0x38,0x00,0x10,0x00,0x05,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf7,0xff,0xec,0xff,0xe0,0xff,' +` 0xc8,0xff,0xb3,0xff,0x8c,0xff,0x70,0xff,' +` 0x35,0xff,0x0a,0xff,0xb5,0xfe,0x90,0xfe,' +` 0x26,0xfe,0xed,0xfd,0x6c,0xfd,0xaa,0xfd,' +` 0x91,0xfd,0xd1,0xfd,0x1f,0xfe,0x8b,0xfe,' +` 0x44,0x01,0x1c,0x05,0x72,0x07,0x7d,0x0a,' +` 0x44,0x0f,0xab,0x18,0x57,0x18,0xdc,0x1b,' +` 0xd4,0x17,0xd3,0x58,0x85,0x19,0x9b,0x12,' +` 0xc4,0x10,0x4e,0x07,0x1d,0x07,0xab,0x05,' +` 0x6b,0x03,0xe3,0x00,0x84,0x00,0x4d,0x00,' +` 0x80,0xff,0x2f,0xfe,0x3f,0xfd,0x4a,0xfc,' +` 0xd6,0xfc,0x36,0xfc,0x3b,0xfc,0x27,0xfc,' +` 0x8e,0xfc,0xcc,0xfc,0x47,0xfd,0xa7,0xfd,' +` 0x26,0xfe,0x86,0xfe,0xec,0xfe,0x37,0xff,' +` 0x7e,0xff,0xaf,0xff,0xd6,0xff,0xee,0xff,' +` 0xfc,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf7,0xff,' +` 0xec,0xff,0xe0,0xff,0xc8,0xff,0xb3,0xff,' +` 0x8c,0xff,0x70,0xff,0x35,0xff,0x0a,0xff,' +` 0xb5,0xfe,0x90,0xfe,0x26,0xfe,0xed,0xfd,' +` 0x6c,0xfd,0xaa,0xfd,0x91,0xfd,0xd1,0xfd,' +` 0x1f,0xfe,0x8b,0xfe,0x44,0x01,0x1c,0x05,' +` 0x72,0x07,0x7d,0x0a,0x44,0x0f,0xab,0x18,' +` 0x57,0x18,0xdc,0x1b,0xd4,0x17,0xd3,0x58,' +` 0x85,0x19,0x9b,0x12,0xc4,0x10,0x4e,0x07,' +` 0x1d,0x07,0xab,0x05,0x6b,0x03,0xe3,0x00,' +` 0x84,0x00,0x4d,0x00,0x80,0xff,0x2f,0xfe,' +` 0x3f,0xfd,0x4a,0xfc,0xd6,0xfc,0x36,0xfc,' +` 0x3b,0xfc,0x27,0xfc,0x8e,0xfc,0xcc,0xfc,' +` 0x47,0xfd,0xa7,0xfd,0x26,0xfe,0x86,0xfe,' +` 0xec,0xfe,0x37,0xff,0x7e,0xff,0xaf,0xff,' +` 0xd6,0xff,0xee,0xff,0xfc,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,' +` 0x15,0x00,0x3f,0x00,0x5e,0x00,0xbe,0x00,' +` 0xe1,0x00,0x8c,0x01,0xab,0x01,0xc0,0x02,' +` 0xdc,0x02,0x87,0x04,0xa7,0x04,0x0f,0x07,' +` 0x16,0x07,0x35,0x0a,0xa4,0x09,0x3d,0x0d,' +` 0xed,0x0b,0x8a,0x0e,0x30,0x09,0xd2,0x09,' +` 0x08,0x01,0x27,0x00,0x9f,0xee,0xc7,0xe8,' +` 0xc4,0xd2,0x3c,0xd4,0xd9,0xba,0x85,0xca,' +` 0x32,0xac,0x41,0xf6,0x4f,0x3f,0x58,0xc4,' +` 0xa3,0xf5,0xd1,0xe8,0x64,0x03,0xbc,0xfc,' +` 0x37,0x08,0x08,0xfc,0x3f,0x00,0xe9,0xf9,' +` 0xa5,0xff,0xf6,0xf9,0x71,0xfe,0x6f,0xfc,' +` 0xb6,0x00,0x65,0xff,0xc7,0x02,0xca,0x01,' +` 0xcf,0x03,0xbf,0x02,0xa0,0x03,0x7e,0x02,' +` 0xaf,0x02,0xb1,0x01,0x98,0x01,0xe3,0x00,' +` 0xba,0x00,0x55,0x00,0x38,0x00,0x10,0x00,' +` 0x05,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x13,0x00,0x23,0x00,' +` 0x62,0x00,0x7e,0x00,0x07,0x01,0x27,0x01,' +` 0x0a,0x02,0x08,0x02,0x3b,0x03,0xd5,0x02,' +` 0x30,0x04,0xfa,0x02,0x44,0x04,0xc4,0x01,' +` 0x07,0x03,0x0b,0xff,0xb7,0x00,0xcb,0xfb,' +` 0x4a,0xfe,0x12,0xf9,0x89,0xff,0x0f,0xf9,' +` 0x3a,0x00,0xff,0xfa,0x75,0x08,0xf1,0xfb,' +` 0x15,0x04,0x84,0xe7,0xac,0xf6,0x84,0xc2,' +` 0x0c,0x39,0x7e,0xff,0x7a,0xaa,0xbf,0xcc,' +` 0x0c,0xbb,0x17,0xd6,0x8e,0xd3,0x0c,0xea,' +` 0xfd,0xee,0xa4,0x00,0x0e,0x01,0xca,0x09,' +` 0xae,0x08,0xf1,0x0d,0x20,0x0b,0x7d,0x0c,' +` 0xd2,0x08,0x67,0x09,0x57,0x06,0x56,0x06,' +` 0x09,0x04,0xed,0x03,0x61,0x02,0x45,0x02,' +` 0x4e,0x01,0x2e,0x01,0x9f,0x00,0x7d,0x00,' +` 0x35,0x00,0x1d,0x00,0x05,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfc,0xff,0xee,0xff,0xd6,0xff,0xb1,0xff,' +` 0x7e,0xff,0x3c,0xff,0xec,0xfe,0x90,0xfe,' +` 0x28,0xfe,0xb8,0xfd,0x4b,0xfd,0xe5,0xfc,' +` 0x93,0xfc,0x4b,0xfc,0x40,0xfc,0x62,0xfc,' +` 0xdb,0xfc,0x8e,0xfc,0x35,0xfd,0x7a,0xfe,' +` 0x70,0xff,0xb3,0x00,0x7e,0x00,0x4a,0x01,' +` 0x32,0x03,0x24,0x06,0xec,0x06,0xec,0x07,' +` 0xbc,0x0f,0xfa,0x13,0xbc,0x16,0x00,0x59,' +` 0x32,0x1a,0x97,0x1a,0xf5,0x18,0xfc,0x17,' +` 0xe7,0x0f,0xed,0x09,0x95,0x07,0xad,0x04,' +` 0x69,0x01,0x2b,0xfe,0x15,0xfe,0x84,0xfd,' +` 0x85,0xfd,0x71,0xfd,0x65,0xfd,0xbf,0xfd,' +` 0x20,0xfe,0x71,0xfe,0xb2,0xfe,0xf5,0xfe,' +` 0x34,0xff,0x64,0xff,0x8c,0xff,0xad,0xff,' +` 0xc8,0xff,0xdd,0xff,0xec,0xff,0xf6,0xff,' +` 0xfc,0xff,0xff,0xff,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfb,0xff,' +` 0xec,0xff,0xd1,0xff,0xa9,0xff,0x72,0xff,' +` 0x2b,0xff,0xd8,0xfe,0x79,0xfe,0x16,0xfe,' +` 0xb0,0xfd,0x4f,0xfd,0xf5,0xfc,0xc5,0xfc,' +` 0xac,0xfc,0xd6,0xfc,0x64,0xfc,0x87,0xfc,' +` 0x38,0xfd,0x90,0xfd,0x09,0xfe,0x70,0xfd,' +` 0x14,0xfc,0xfe,0xfb,0x2c,0xfc,0x75,0xfc,' +` 0x47,0xfd,0xa0,0xff,0xd1,0x01,0xfa,0x07,' +` 0x86,0x10,0xcc,0x13,0x24,0x57,0x65,0x18,' +` 0x52,0x18,0x89,0x17,0x7b,0x15,0x23,0x10,' +` 0x2a,0x09,0x76,0x05,0x94,0x02,0x7b,0x01,' +` 0x21,0x00,0x6c,0xfe,0xc9,0xfd,0x48,0xfe,' +` 0x9b,0xfe,0x09,0xff,0x45,0xff,0x72,0xff,' +` 0xc4,0xff,0xf9,0xff,0x17,0x00,0x27,0x00,' +` 0x2f,0x00,0x31,0x00,0x2c,0x00,0x24,0x00,' +` 0x1b,0x00,0x13,0x00,0x0b,0x00,0x05,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x08,0x00,0x24,0x00,0x32,0x00,' +` 0x81,0x00,0x8e,0x00,0x19,0x01,0xfe,0x00,' +` 0xb0,0x01,0x24,0x01,0xbf,0x01,0x3e,0x00,' +` 0x89,0x00,0xe7,0xfd,0x09,0xfe,0x9e,0xfa,' +` 0xc9,0xfa,0xa2,0xf6,0x6f,0xf9,0x75,0xf7,' +` 0x2e,0xfd,0x20,0xfc,0x3f,0x09,0x2f,0x0a,' +` 0x96,0x18,0x83,0x12,0x3e,0x1c,0xd1,0x05,' +` 0x08,0x0d,0x0b,0xdb,0x17,0x0e,0xf9,0x39,' +` 0x70,0xa7,0x4f,0xc7,0xf7,0xb2,0x34,0xc9,' +` 0x0b,0xc9,0x67,0xe5,0xb8,0xe9,0xa7,0xfd,' +` 0x35,0x01,0x53,0x0e,0xda,0x0b,0xa7,0x11,' +` 0x8f,0x0e,0x6c,0x10,0x67,0x0c,0x08,0x0c,' +` 0xe5,0x07,0x97,0x07,0xbf,0x04,0x69,0x04,' +` 0x7e,0x02,0x58,0x02,0x43,0x01,0x38,0x01,' +` 0x9e,0x00,0x90,0x00,0x40,0x00,0x31,0x00,' +` 0x10,0x00,0x05,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x0f,0x00,0x32,0x00,' +` 0x3e,0x00,0x93,0x00,0x99,0x00,0x3d,0x01,' +` 0x38,0x01,0x5d,0x02,0x67,0x02,0x6e,0x04,' +` 0x9b,0x04,0xa0,0x07,0xb3,0x07,0x0d,0x0c,' +` 0x2d,0x0c,0xa0,0x10,0x60,0x0e,0x20,0x12,' +` 0xc0,0x0b,0x10,0x0f,0x9f,0x01,0xf2,0xfe,' +` 0x3d,0xea,0x16,0xe7,0xc2,0xc9,0x8b,0xca,' +` 0x38,0xb2,0x9e,0xc8,0x8e,0xa4,0x45,0x2e,' +` 0xe9,0x1a,0xbe,0xd5,0xbb,0x0d,0x8c,0x03,' +` 0xdb,0x1c,0xab,0x11,0xa9,0x19,0x24,0x0a,' +` 0x5d,0x0a,0x39,0xfc,0xb9,0xfd,0x54,0xf7,' +` 0xd2,0xf9,0x5f,0xf6,0xe0,0xfa,0x53,0xfa,' +` 0x19,0xfe,0xaa,0xfd,0x90,0x00,0x16,0x00,' +` 0xc6,0x01,0x0f,0x01,0xb9,0x01,0xf4,0x00,' +` 0x20,0x01,0x8b,0x00,0x85,0x00,0x30,0x00,' +` 0x25,0x00,0x07,0x00,0x03,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x05,0x00,' +` 0x0c,0x00,0x11,0x00,0x1e,0x00,0x20,0x00,' +` 0x33,0x00,0x2a,0x00,0x3b,0x00,0x1a,0x00,' +` 0x2b,0x00,0xe7,0xff,0xe3,0xff,0x58,0xff,' +` 0x6b,0xff,0xe4,0xfe,0xd3,0xfe,0x12,0xfe,' +` 0x11,0xfe,0xfb,0xfd,0x5c,0x00,0xf8,0x00,' +` 0xf5,0x02,0x96,0x04,0x8b,0x09,0x9c,0x0e,' +` 0x78,0x16,0xcf,0x15,0xca,0x1a,0xa4,0x13,' +` 0xb0,0x56,0xa4,0x19,0x47,0x0e,0x7c,0x0a,' +` 0xc9,0x00,0xd3,0x00,0x9d,0xfc,0x2d,0xfd,' +` 0xa1,0xfb,0x83,0xfc,0x9f,0xfb,0xb0,0xfd,' +` 0xc1,0xfd,0xe0,0xfd,0x0b,0xfd,0xcf,0xfc,' +` 0x38,0xfc,0xff,0xfc,0x98,0xfc,0xe3,0xfc,' +` 0xe5,0xfc,0x61,0xfd,0xa4,0xfd,0x20,0xfe,' +` 0x70,0xfe,0xdd,0xfe,0x26,0xff,0x74,0xff,' +` 0xa7,0xff,0xd2,0xff,0xec,0xff,0xfb,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x05,0x00,0x0c,0x00,0x11,0x00,' +` 0x1e,0x00,0x20,0x00,0x33,0x00,0x2a,0x00,' +` 0x3b,0x00,0x1a,0x00,0x2b,0x00,0xe7,0xff,' +` 0xe3,0xff,0x58,0xff,0x6b,0xff,0xe4,0xfe,' +` 0xd3,0xfe,0x12,0xfe,0x11,0xfe,0xfb,0xfd,' +` 0x5c,0x00,0xf8,0x00,0xf5,0x02,0x96,0x04,' +` 0x8b,0x09,0x9c,0x0e,0x78,0x16,0xcf,0x15,' +` 0xca,0x1a,0xa4,0x13,0xb0,0x56,0xa4,0x19,' +` 0x47,0x0e,0x7c,0x0a,0xc9,0x00,0xd3,0x00,' +` 0x9d,0xfc,0x2d,0xfd,0xa1,0xfb,0x83,0xfc,' +` 0x9f,0xfb,0xb0,0xfd,0xc1,0xfd,0xe0,0xfd,' +` 0x0b,0xfd,0xcf,0xfc,0x38,0xfc,0xff,0xfc,' +` 0x98,0xfc,0xe3,0xfc,0xe5,0xfc,0x61,0xfd,' +` 0xa4,0xfd,0x20,0xfe,0x70,0xfe,0xdd,0xfe,' +` 0x26,0xff,0x74,0xff,0xa7,0xff,0xd2,0xff,' +` 0xec,0xff,0xfb,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x0f,0x00,0x32,0x00,0x3e,0x00,0x93,0x00,' +` 0x99,0x00,0x3d,0x01,0x38,0x01,0x5d,0x02,' +` 0x67,0x02,0x6e,0x04,0x9b,0x04,0xa0,0x07,' +` 0xb3,0x07,0x0d,0x0c,0x2d,0x0c,0xa0,0x10,' +` 0x60,0x0e,0x20,0x12,0xc0,0x0b,0x10,0x0f,' +` 0x9f,0x01,0xf2,0xfe,0x3d,0xea,0x16,0xe7,' +` 0xc2,0xc9,0x8b,0xca,0x38,0xb2,0x9e,0xc8,' +` 0x8e,0xa4,0x45,0x2e,0xe9,0x1a,0xbe,0xd5,' +` 0xbb,0x0d,0x8c,0x03,0xdb,0x1c,0xab,0x11,' +` 0xa9,0x19,0x24,0x0a,0x5d,0x0a,0x39,0xfc,' +` 0xb9,0xfd,0x54,0xf7,0xd2,0xf9,0x5f,0xf6,' +` 0xe0,0xfa,0x53,0xfa,0x19,0xfe,0xaa,0xfd,' +` 0x90,0x00,0x16,0x00,0xc6,0x01,0x0f,0x01,' +` 0xb9,0x01,0xf4,0x00,0x20,0x01,0x8b,0x00,' +` 0x85,0x00,0x30,0x00,0x25,0x00,0x07,0x00,' +` 0x03,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x08,0x00,' +` 0x24,0x00,0x32,0x00,0x81,0x00,0x8e,0x00,' +` 0x19,0x01,0xfe,0x00,0xb0,0x01,0x24,0x01,' +` 0xbf,0x01,0x3e,0x00,0x89,0x00,0xe7,0xfd,' +` 0x09,0xfe,0x9e,0xfa,0xc9,0xfa,0xa2,0xf6,' +` 0x6f,0xf9,0x75,0xf7,0x2e,0xfd,0x20,0xfc,' +` 0x3f,0x09,0x2f,0x0a,0x96,0x18,0x83,0x12,' +` 0x3e,0x1c,0xd1,0x05,0x08,0x0d,0x0b,0xdb,' +` 0x17,0x0e,0xf9,0x39,0x70,0xa7,0x4f,0xc7,' +` 0xf7,0xb2,0x34,0xc9,0x0b,0xc9,0x67,0xe5,' +` 0xb8,0xe9,0xa7,0xfd,0x35,0x01,0x53,0x0e,' +` 0xda,0x0b,0xa7,0x11,0x8f,0x0e,0x6c,0x10,' +` 0x67,0x0c,0x08,0x0c,0xe5,0x07,0x97,0x07,' +` 0xbf,0x04,0x69,0x04,0x7e,0x02,0x58,0x02,' +` 0x43,0x01,0x38,0x01,0x9e,0x00,0x90,0x00,' +` 0x40,0x00,0x31,0x00,0x10,0x00,0x05,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfb,0xff,0xec,0xff,0xd1,0xff,' +` 0xa9,0xff,0x72,0xff,0x2b,0xff,0xd8,0xfe,' +` 0x79,0xfe,0x16,0xfe,0xb0,0xfd,0x4f,0xfd,' +` 0xf5,0xfc,0xc5,0xfc,0xac,0xfc,0xd6,0xfc,' +` 0x64,0xfc,0x87,0xfc,0x38,0xfd,0x90,0xfd,' +` 0x09,0xfe,0x70,0xfd,0x14,0xfc,0xfe,0xfb,' +` 0x2c,0xfc,0x75,0xfc,0x47,0xfd,0xa0,0xff,' +` 0xd1,0x01,0xfa,0x07,0x86,0x10,0xcc,0x13,' +` 0x24,0x57,0x65,0x18,0x52,0x18,0x89,0x17,' +` 0x7b,0x15,0x23,0x10,0x2a,0x09,0x76,0x05,' +` 0x94,0x02,0x7b,0x01,0x21,0x00,0x6c,0xfe,' +` 0xc9,0xfd,0x48,0xfe,0x9b,0xfe,0x09,0xff,' +` 0x45,0xff,0x72,0xff,0xc4,0xff,0xf9,0xff,' +` 0x17,0x00,0x27,0x00,0x2f,0x00,0x31,0x00,' +` 0x2c,0x00,0x24,0x00,0x1b,0x00,0x13,0x00,' +` 0x0b,0x00,0x05,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xac,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm0_30_90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm0_30_90deg_48khz.m4 new file mode 100644 index 000000000000..6d666e2b3004 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm0_30_90deg_48khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x07,0x00,0x10,0x00,0x1a,0x00,0x30,0x00,' +` 0x45,0x00,0x6b,0x00,0x8e,0x00,0xc8,0x00,' +` 0xf9,0x00,0x49,0x01,0x86,0x01,0xeb,0x01,' +` 0x33,0x02,0xac,0x02,0xf9,0x02,0x84,0x03,' +` 0x8e,0x04,0x65,0x05,0x96,0x05,0x53,0x06,' +` 0x6e,0x06,0x31,0x07,0x1f,0x07,0xf4,0x07,' +` 0x95,0x07,0xa1,0x08,0x97,0x07,0xdb,0x09,' +` 0x54,0x48,0x00,0x07,0xe0,0x08,0x92,0x07,' +` 0x10,0x08,0x33,0x07,0x48,0x07,0x8c,0x06,' +` 0x66,0x06,0xbd,0x05,0x6f,0x05,0xdd,0x04,' +` 0x42,0x04,0x08,0x03,0xce,0x02,0x47,0x02,' +` 0x05,0x02,0x99,0x01,0x5c,0x01,0x08,0x01,' +` 0xd7,0x00,0x99,0x00,0x75,0x00,0x4c,0x00,' +` 0x34,0x00,0x1d,0x00,0x12,0x00,0x08,0x00,' +` 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfb,0xff,0xf2,0xff,0xe2,0xff,' +` 0xc9,0xff,0xa3,0xff,0x72,0xff,0x31,0xff,' +` 0xdd,0xfe,0x7a,0xfe,0x04,0xfe,0x7e,0xfd,' +` 0xe5,0xfc,0x3f,0xfc,0x85,0xfb,0xc6,0xfa,' +` 0xef,0xf9,0x23,0xf9,0xc3,0xf6,0x67,0xf5,' +` 0x9f,0xf4,0x9e,0xf3,0xd8,0xf2,0xfb,0xf1,' +` 0x54,0xf1,0xa2,0xf0,0x29,0xf0,0xac,0xef,' +` 0x6b,0xef,0x29,0xef,0x16,0x6f,0x44,0xef,' +` 0x9d,0xef,0xf4,0xef,0x88,0xf0,0x14,0xf1,' +` 0xda,0xf1,0x8d,0xf2,0x7b,0xf3,0x46,0xf4,' +` 0x56,0xf5,0x18,0xf6,0x98,0xf7,0xca,0xf9,' +` 0x80,0xfa,0x57,0xfb,0x09,0xfc,0xbc,0xfc,' +` 0x55,0xfd,0xe3,0xfd,0x5c,0xfe,0xc5,0xfe,' +` 0x1c,0xff,0x62,0xff,0x9a,0xff,0xc3,0xff,' +` 0xdd,0xff,0xef,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfb,0xff,' +` 0xf2,0xff,0xe2,0xff,0xc9,0xff,0xa3,0xff,' +` 0x72,0xff,0x31,0xff,0xdd,0xfe,0x7a,0xfe,' +` 0x04,0xfe,0x7e,0xfd,0xe5,0xfc,0x3f,0xfc,' +` 0x85,0xfb,0xc6,0xfa,0xef,0xf9,0x23,0xf9,' +` 0xc3,0xf6,0x67,0xf5,0x9f,0xf4,0x9e,0xf3,' +` 0xd8,0xf2,0xfb,0xf1,0x54,0xf1,0xa2,0xf0,' +` 0x29,0xf0,0xac,0xef,0x6b,0xef,0x29,0xef,' +` 0x16,0x6f,0x44,0xef,0x9d,0xef,0xf4,0xef,' +` 0x88,0xf0,0x14,0xf1,0xda,0xf1,0x8d,0xf2,' +` 0x7b,0xf3,0x46,0xf4,0x56,0xf5,0x18,0xf6,' +` 0x98,0xf7,0xca,0xf9,0x80,0xfa,0x57,0xfb,' +` 0x09,0xfc,0xbc,0xfc,0x55,0xfd,0xe3,0xfd,' +` 0x5c,0xfe,0xc5,0xfe,0x1c,0xff,0x62,0xff,' +` 0x9a,0xff,0xc3,0xff,0xdd,0xff,0xef,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x07,0x00,0x10,0x00,' +` 0x1a,0x00,0x30,0x00,0x45,0x00,0x6b,0x00,' +` 0x8e,0x00,0xc8,0x00,0xf9,0x00,0x49,0x01,' +` 0x86,0x01,0xeb,0x01,0x33,0x02,0xac,0x02,' +` 0xf9,0x02,0x84,0x03,0x8e,0x04,0x65,0x05,' +` 0x96,0x05,0x53,0x06,0x6e,0x06,0x31,0x07,' +` 0x1f,0x07,0xf4,0x07,0x95,0x07,0xa1,0x08,' +` 0x97,0x07,0xdb,0x09,0x54,0x48,0x00,0x07,' +` 0xe0,0x08,0x92,0x07,0x10,0x08,0x33,0x07,' +` 0x48,0x07,0x8c,0x06,0x66,0x06,0xbd,0x05,' +` 0x6f,0x05,0xdd,0x04,0x42,0x04,0x08,0x03,' +` 0xce,0x02,0x47,0x02,0x05,0x02,0x99,0x01,' +` 0x5c,0x01,0x08,0x01,0xd7,0x00,0x99,0x00,' +` 0x75,0x00,0x4c,0x00,0x34,0x00,0x1d,0x00,' +` 0x12,0x00,0x08,0x00,0x04,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x07,0x00,0x10,0x00,0x1a,0x00,0x30,0x00,' +` 0x45,0x00,0x6b,0x00,0x8e,0x00,0xc8,0x00,' +` 0xf9,0x00,0x49,0x01,0x86,0x01,0xeb,0x01,' +` 0x33,0x02,0xac,0x02,0xf9,0x02,0x84,0x03,' +` 0x8e,0x04,0x65,0x05,0x96,0x05,0x53,0x06,' +` 0x6e,0x06,0x31,0x07,0x1f,0x07,0xf4,0x07,' +` 0x95,0x07,0xa1,0x08,0x97,0x07,0xdb,0x09,' +` 0x54,0x48,0x00,0x07,0xe0,0x08,0x92,0x07,' +` 0x10,0x08,0x33,0x07,0x48,0x07,0x8c,0x06,' +` 0x66,0x06,0xbd,0x05,0x6f,0x05,0xdd,0x04,' +` 0x42,0x04,0x08,0x03,0xce,0x02,0x47,0x02,' +` 0x05,0x02,0x99,0x01,0x5c,0x01,0x08,0x01,' +` 0xd7,0x00,0x99,0x00,0x75,0x00,0x4c,0x00,' +` 0x34,0x00,0x1d,0x00,0x12,0x00,0x08,0x00,' +` 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfb,0xff,0xf2,0xff,0xe2,0xff,' +` 0xc9,0xff,0xa3,0xff,0x72,0xff,0x31,0xff,' +` 0xdd,0xfe,0x7a,0xfe,0x04,0xfe,0x7e,0xfd,' +` 0xe5,0xfc,0x3f,0xfc,0x85,0xfb,0xc6,0xfa,' +` 0xef,0xf9,0x23,0xf9,0xc3,0xf6,0x67,0xf5,' +` 0x9f,0xf4,0x9e,0xf3,0xd8,0xf2,0xfb,0xf1,' +` 0x54,0xf1,0xa2,0xf0,0x29,0xf0,0xac,0xef,' +` 0x6b,0xef,0x29,0xef,0x16,0x6f,0x44,0xef,' +` 0x9d,0xef,0xf4,0xef,0x88,0xf0,0x14,0xf1,' +` 0xda,0xf1,0x8d,0xf2,0x7b,0xf3,0x46,0xf4,' +` 0x56,0xf5,0x18,0xf6,0x98,0xf7,0xca,0xf9,' +` 0x80,0xfa,0x57,0xfb,0x09,0xfc,0xbc,0xfc,' +` 0x55,0xfd,0xe3,0xfd,0x5c,0xfe,0xc5,0xfe,' +` 0x1c,0xff,0x62,0xff,0x9a,0xff,0xc3,0xff,' +` 0xdd,0xff,0xef,0xff,0xf9,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfb,0xff,' +` 0xf2,0xff,0xe2,0xff,0xc9,0xff,0xa3,0xff,' +` 0x72,0xff,0x31,0xff,0xdd,0xfe,0x7a,0xfe,' +` 0x04,0xfe,0x7e,0xfd,0xe5,0xfc,0x3f,0xfc,' +` 0x85,0xfb,0xc6,0xfa,0xef,0xf9,0x23,0xf9,' +` 0xc3,0xf6,0x67,0xf5,0x9f,0xf4,0x9e,0xf3,' +` 0xd8,0xf2,0xfb,0xf1,0x54,0xf1,0xa2,0xf0,' +` 0x29,0xf0,0xac,0xef,0x6b,0xef,0x29,0xef,' +` 0x16,0x6f,0x44,0xef,0x9d,0xef,0xf4,0xef,' +` 0x88,0xf0,0x14,0xf1,0xda,0xf1,0x8d,0xf2,' +` 0x7b,0xf3,0x46,0xf4,0x56,0xf5,0x18,0xf6,' +` 0x98,0xf7,0xca,0xf9,0x80,0xfa,0x57,0xfb,' +` 0x09,0xfc,0xbc,0xfc,0x55,0xfd,0xe3,0xfd,' +` 0x5c,0xfe,0xc5,0xfe,0x1c,0xff,0x62,0xff,' +` 0x9a,0xff,0xc3,0xff,0xdd,0xff,0xef,0xff,' +` 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x07,0x00,0x10,0x00,' +` 0x1a,0x00,0x30,0x00,0x45,0x00,0x6b,0x00,' +` 0x8e,0x00,0xc8,0x00,0xf9,0x00,0x49,0x01,' +` 0x86,0x01,0xeb,0x01,0x33,0x02,0xac,0x02,' +` 0xf9,0x02,0x84,0x03,0x8e,0x04,0x65,0x05,' +` 0x96,0x05,0x53,0x06,0x6e,0x06,0x31,0x07,' +` 0x1f,0x07,0xf4,0x07,0x95,0x07,0xa1,0x08,' +` 0x97,0x07,0xdb,0x09,0x54,0x48,0x00,0x07,' +` 0xe0,0x08,0x92,0x07,0x10,0x08,0x33,0x07,' +` 0x48,0x07,0x8c,0x06,0x66,0x06,0xbd,0x05,' +` 0x6f,0x05,0xdd,0x04,0x42,0x04,0x08,0x03,' +` 0xce,0x02,0x47,0x02,0x05,0x02,0x99,0x01,' +` 0x5c,0x01,0x08,0x01,0xd7,0x00,0x99,0x00,' +` 0x75,0x00,0x4c,0x00,0x34,0x00,0x1d,0x00,' +` 0x12,0x00,0x08,0x00,0x04,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,' +` 0x02,0x00,0x06,0x00,0x0d,0x00,0x14,0x00,' +` 0x21,0x00,0x2d,0x00,0x4c,0x00,0x90,0x00,' +` 0xb4,0x00,0xe1,0x00,0x0e,0x01,0x3f,0x01,' +` 0x7e,0x01,0x77,0x01,0x8b,0x01,0xeb,0x01,' +` 0x2a,0x02,0xd8,0x03,0xa9,0x04,0x11,0x05,' +` 0xa8,0x05,0x20,0x06,0xaa,0x06,0x1a,0x07,' +` 0x85,0x07,0xd1,0x07,0x1e,0x08,0x42,0x48,' +` 0x7b,0x08,0x87,0x08,0x90,0x08,0x75,0x08,' +` 0x53,0x08,0x0c,0x08,0xbd,0x07,0x46,0x07,' +` 0xce,0x06,0x47,0x06,0x29,0x06,0x74,0x05,' +` 0xf3,0x04,0xf8,0x03,0x9e,0x02,0x38,0x02,' +` 0xc4,0x01,0x69,0x01,0x14,0x01,0xcb,0x00,' +` 0xad,0x00,0x84,0x00,0x56,0x00,0x38,0x00,' +` 0x20,0x00,0x10,0x00,0x07,0x00,0x01,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xf9,0xff,0xef,0xff,' +` 0xe1,0xff,0xe5,0xff,0xd3,0xff,0xe7,0xff,' +` 0xd3,0xff,0xf8,0xff,0xeb,0xff,0x80,0x00,' +` 0x4b,0x00,0xa2,0x00,0x4d,0x00,0xaa,0x00,' +` 0x1a,0x00,0xe1,0xff,0x7f,0xfe,0xdb,0xfe,' +` 0x3b,0xfd,0xb5,0xfc,0x32,0xfa,0xad,0xfa,' +` 0xad,0xf7,0x8d,0xf8,0xb3,0xf4,0x8f,0xf6,' +` 0xfb,0xf0,0x83,0xf5,0xaf,0xe9,0xa4,0x6e,' +` 0xf2,0xf5,0xa8,0xe9,0xf7,0xee,0x5f,0xea,' +` 0x69,0xed,0x35,0xeb,0xa6,0xed,0xcc,0xec,' +` 0x0b,0xef,0x28,0xef,0x22,0xf2,0x95,0xf2,' +` 0x97,0xf4,0x8a,0xf5,0xf5,0xf7,0xaf,0xf8,' +` 0x4c,0xfa,0x0c,0xfb,0x5a,0xfc,0xfe,0xfc,' +` 0x2d,0xfe,0xb4,0xfe,0x3f,0xff,0x84,0xff,' +` 0xcd,0xff,0xea,0xff,0x04,0x00,0x06,0x00,' +` 0x04,0x00,0x01,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x02,0x00,0x09,0x00,' +` 0xfc,0xff,0xf4,0xff,0xbc,0xff,0x9a,0xff,' +` 0x1e,0xff,0xdc,0xfe,0xfc,0xfd,0x43,0xfd,' +` 0x05,0xfc,0x70,0xfb,0xd3,0xf9,0x3e,0xf9,' +` 0x4c,0xf7,0x55,0xf6,0xad,0xf3,0xa3,0xf3,' +` 0xee,0xf0,0xc0,0xf0,0x4b,0xed,0xd9,0xee,' +` 0x37,0xeb,0x20,0xee,0xc5,0xe9,0xf9,0xee,' +` 0x9f,0xe8,0x1c,0xf3,0xfc,0xe2,0x45,0x6d,' +` 0x41,0xfe,0x7b,0xeb,0x80,0xf7,0xb8,0xf1,' +` 0x77,0xf8,0x7d,0xf5,0x39,0xfa,0x89,0xf8,' +` 0x0c,0xfc,0x24,0xfb,0x9b,0xfe,0xb9,0xfd,' +` 0x8e,0xff,0xf6,0xfe,0xd9,0x00,0x1b,0x00,' +` 0xe0,0x00,0x3e,0x00,0xb3,0x00,0x40,0x00,' +` 0x42,0x00,0xca,0xff,0x04,0x00,0xcc,0xff,' +` 0xf0,0xff,0xd7,0xff,0xef,0xff,0xe9,0xff,' +` 0xfd,0xff,0xfd,0xff,0xff,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0x03,0x00,' +` 0x05,0x00,0x15,0x00,0x1a,0x00,0x42,0x00,' +` 0x4c,0x00,0x96,0x00,0xa0,0x00,0xec,0x00,' +` 0xf5,0x00,0x95,0x01,0x97,0x01,0x76,0x02,' +` 0x58,0x02,0x29,0x04,0xa2,0x04,0xdb,0x05,' +` 0xbd,0x05,0xf6,0x06,0x23,0x06,0x16,0x08,' +` 0xd2,0x06,0x33,0x09,0xf5,0x06,0x40,0x0a,' +` 0x35,0x06,0x1b,0x0c,0xb7,0x01,0xb5,0x46,' +` 0xd7,0x10,0xc6,0x03,0x23,0x0a,0x33,0x05,' +` 0x28,0x08,0xef,0x04,0xa5,0x06,0x3f,0x04,' +` 0x57,0x05,0x5a,0x03,0xc8,0x02,0x66,0x01,' +` 0xf4,0x01,0x03,0x01,0xbb,0x01,0xfc,0x00,' +` 0x3d,0x01,0xaf,0x00,0xd5,0x00,0x6e,0x00,' +` 0x67,0x00,0x14,0x00,0x2f,0x00,0x05,0x00,' +` 0x15,0x00,0xfe,0xff,0x06,0x00,0xfc,0xff,' +` 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0x03,0x00,0x05,0x00,0x15,0x00,' +` 0x1a,0x00,0x42,0x00,0x4c,0x00,0x96,0x00,' +` 0xa0,0x00,0xec,0x00,0xf5,0x00,0x95,0x01,' +` 0x97,0x01,0x76,0x02,0x58,0x02,0x29,0x04,' +` 0xa2,0x04,0xdb,0x05,0xbd,0x05,0xf6,0x06,' +` 0x23,0x06,0x16,0x08,0xd2,0x06,0x33,0x09,' +` 0xf5,0x06,0x40,0x0a,0x35,0x06,0x1b,0x0c,' +` 0xb7,0x01,0xb5,0x46,0xd7,0x10,0xc6,0x03,' +` 0x23,0x0a,0x33,0x05,0x28,0x08,0xef,0x04,' +` 0xa5,0x06,0x3f,0x04,0x57,0x05,0x5a,0x03,' +` 0xc8,0x02,0x66,0x01,0xf4,0x01,0x03,0x01,' +` 0xbb,0x01,0xfc,0x00,0x3d,0x01,0xaf,0x00,' +` 0xd5,0x00,0x6e,0x00,0x67,0x00,0x14,0x00,' +` 0x2f,0x00,0x05,0x00,0x15,0x00,0xfe,0xff,' +` 0x06,0x00,0xfc,0xff,0x03,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x02,0x00,0x09,0x00,0xfc,0xff,0xf4,0xff,' +` 0xbc,0xff,0x9a,0xff,0x1e,0xff,0xdc,0xfe,' +` 0xfc,0xfd,0x43,0xfd,0x05,0xfc,0x70,0xfb,' +` 0xd3,0xf9,0x3e,0xf9,0x4c,0xf7,0x55,0xf6,' +` 0xad,0xf3,0xa3,0xf3,0xee,0xf0,0xc0,0xf0,' +` 0x4b,0xed,0xd9,0xee,0x37,0xeb,0x20,0xee,' +` 0xc5,0xe9,0xf9,0xee,0x9f,0xe8,0x1c,0xf3,' +` 0xfc,0xe2,0x45,0x6d,0x41,0xfe,0x7b,0xeb,' +` 0x80,0xf7,0xb8,0xf1,0x77,0xf8,0x7d,0xf5,' +` 0x39,0xfa,0x89,0xf8,0x0c,0xfc,0x24,0xfb,' +` 0x9b,0xfe,0xb9,0xfd,0x8e,0xff,0xf6,0xfe,' +` 0xd9,0x00,0x1b,0x00,0xe0,0x00,0x3e,0x00,' +` 0xb3,0x00,0x40,0x00,0x42,0x00,0xca,0xff,' +` 0x04,0x00,0xcc,0xff,0xf0,0xff,0xd7,0xff,' +` 0xef,0xff,0xe9,0xff,0xfd,0xff,0xfd,0xff,' +` 0xff,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xf9,0xff,0xef,0xff,0xe1,0xff,0xe5,0xff,' +` 0xd3,0xff,0xe7,0xff,0xd3,0xff,0xf8,0xff,' +` 0xeb,0xff,0x80,0x00,0x4b,0x00,0xa2,0x00,' +` 0x4d,0x00,0xaa,0x00,0x1a,0x00,0xe1,0xff,' +` 0x7f,0xfe,0xdb,0xfe,0x3b,0xfd,0xb5,0xfc,' +` 0x32,0xfa,0xad,0xfa,0xad,0xf7,0x8d,0xf8,' +` 0xb3,0xf4,0x8f,0xf6,0xfb,0xf0,0x83,0xf5,' +` 0xaf,0xe9,0xa4,0x6e,0xf2,0xf5,0xa8,0xe9,' +` 0xf7,0xee,0x5f,0xea,0x69,0xed,0x35,0xeb,' +` 0xa6,0xed,0xcc,0xec,0x0b,0xef,0x28,0xef,' +` 0x22,0xf2,0x95,0xf2,0x97,0xf4,0x8a,0xf5,' +` 0xf5,0xf7,0xaf,0xf8,0x4c,0xfa,0x0c,0xfb,' +` 0x5a,0xfc,0xfe,0xfc,0x2d,0xfe,0xb4,0xfe,' +` 0x3f,0xff,0x84,0xff,0xcd,0xff,0xea,0xff,' +` 0x04,0x00,0x06,0x00,0x04,0x00,0x01,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x00,0x00,0x02,0x00,0x06,0x00,' +` 0x0d,0x00,0x14,0x00,0x21,0x00,0x2d,0x00,' +` 0x4c,0x00,0x90,0x00,0xb4,0x00,0xe1,0x00,' +` 0x0e,0x01,0x3f,0x01,0x7e,0x01,0x77,0x01,' +` 0x8b,0x01,0xeb,0x01,0x2a,0x02,0xd8,0x03,' +` 0xa9,0x04,0x11,0x05,0xa8,0x05,0x20,0x06,' +` 0xaa,0x06,0x1a,0x07,0x85,0x07,0xd1,0x07,' +` 0x1e,0x08,0x42,0x48,0x7b,0x08,0x87,0x08,' +` 0x90,0x08,0x75,0x08,0x53,0x08,0x0c,0x08,' +` 0xbd,0x07,0x46,0x07,0xce,0x06,0x47,0x06,' +` 0x29,0x06,0x74,0x05,0xf3,0x04,0xf8,0x03,' +` 0x9e,0x02,0x38,0x02,0xc4,0x01,0x69,0x01,' +` 0x14,0x01,0xcb,0x00,0xad,0x00,0x84,0x00,' +` 0x56,0x00,0x38,0x00,0x20,0x00,0x10,0x00,' +` 0x07,0x00,0x01,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf7,0xff,0xef,0xff,0xe7,0xff,' +` 0xdb,0xff,0xd4,0xff,0xca,0xff,0xbc,0xff,' +` 0xae,0xff,0xa4,0xff,0x98,0xff,0x99,0xff,' +` 0x90,0xff,0xbb,0xff,0xd3,0xff,0xcd,0xff,' +` 0x0e,0x00,0x3e,0x00,0x94,0x00,0xe2,0x00,' +` 0x53,0x01,0xbf,0x01,0xad,0x03,0x87,0x04,' +` 0xfc,0x04,0x96,0x05,0x11,0x06,0x96,0x06,' +` 0xfe,0x06,0x65,0x07,0xa1,0x47,0xe6,0x07,' +` 0xf4,0x07,0xf9,0x07,0xd8,0x07,0xad,0x07,' +` 0x60,0x07,0x07,0x07,0xa5,0x06,0xa1,0x06,' +` 0x05,0x06,0x81,0x05,0xd6,0x04,0x51,0x04,' +` 0xa2,0x03,0x36,0x03,0x53,0x02,0x79,0x01,' +` 0x49,0x01,0xed,0x00,0xb4,0x00,0x7a,0x00,' +` 0x53,0x00,0x33,0x00,0x1b,0x00,0x11,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xfe,0xff,0xfc,0xff,' +` 0x09,0x00,0x11,0x00,0x3b,0x00,0x5c,0x00,' +` 0xbe,0x00,0xee,0x00,0x84,0x01,0xc0,0x01,' +` 0x86,0x02,0xb9,0x02,0x98,0x03,0xca,0x03,' +` 0xda,0x04,0x07,0x04,0x13,0x05,0xf1,0x03,' +` 0xd9,0x04,0x03,0x03,0xd4,0x03,0x22,0x01,' +` 0x23,0x01,0xd9,0xfc,0x22,0xfe,0xa6,0xf8,' +` 0x25,0xfb,0x4a,0xf3,0x92,0xf9,0x0f,0xe9,' +` 0x56,0x6f,0x4b,0xfa,0x79,0xe8,0x0b,0xf0,' +` 0x52,0xe9,0x35,0xed,0x8b,0xe9,0x75,0xec,' +` 0xad,0xea,0x6f,0xee,0xe0,0xed,0x8d,0xf0,' +` 0xba,0xf0,0x46,0xf3,0xf0,0xf3,0x41,0xf6,' +` 0x3b,0xf7,0x06,0xfa,0xff,0xfa,0x6d,0xfc,' +` 0x18,0xfd,0x22,0xfe,0x99,0xfe,0x40,0xff,' +` 0x84,0xff,0xd7,0xff,0xea,0xff,0x08,0x00,' +` 0x08,0x00,0x09,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x07,0x00,0x10,0x00,0x00,0x00,' +` 0x00,0x00,0xc3,0xff,0xb5,0xff,0x1e,0xff,' +` 0xed,0xfe,0xe8,0xfd,0x98,0xfd,0x10,0xfc,' +` 0xb3,0xfb,0x95,0xf9,0x6a,0xf8,0x57,0xf5,' +` 0x4c,0xf5,0xfa,0xf1,0x7a,0xf2,0xb6,0xee,' +` 0x23,0xf0,0xe8,0xeb,0xf7,0xed,0x8f,0xe8,' +` 0xe2,0xed,0x6d,0xe7,0x22,0xf0,0x26,0xe6,' +` 0x86,0xf6,0x9d,0xdd,0xc1,0x6a,0x08,0x0a,' +` 0x55,0xe9,0x13,0xfd,0x28,0xf3,0x16,0xfe,' +` 0xee,0xf8,0x73,0x00,0x48,0xfd,0x88,0x03,' +` 0x36,0x01,0xde,0x04,0xe7,0x02,0x5b,0x05,' +` 0xa8,0x03,0x1f,0x05,0xbd,0x03,0xb4,0x04,' +` 0xec,0x02,0x57,0x03,0x15,0x02,0x2f,0x02,' +` 0x3e,0x01,0x38,0x01,0x95,0x00,0x89,0x00,' +` 0x27,0x00,0x25,0x00,0x00,0x00,0x03,0x00,' +` 0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x17,0x00,0x06,0x00,' +` 0x2a,0x00,0x18,0x00,0x6c,0x00,0x4e,0x00,' +` 0xdd,0x00,0xa9,0x00,0x86,0x01,0x1f,0x01,' +` 0x7d,0x02,0xaf,0x02,0x20,0x04,0x9b,0x03,' +` 0x87,0x05,0x90,0x04,0xfd,0x06,0x68,0x05,' +` 0x25,0x08,0x47,0x05,0x69,0x09,0x27,0x05,' +` 0x09,0x0b,0xbf,0x03,0x37,0x0e,0x9c,0xfc,' +` 0x95,0x41,0x37,0x1a,0x11,0xff,0xb9,0x0b,' +` 0x88,0x02,0x7c,0x08,0xdb,0x02,0x6d,0x06,' +` 0x71,0x02,0x72,0x03,0x2d,0x00,0x00,0x02,' +` 0xc3,0xff,0x11,0x01,0x73,0xff,0x6a,0x00,' +` 0x54,0xff,0x32,0x00,0x3f,0xff,0xe3,0xff,' +` 0x5e,0xff,0xd6,0xff,0x87,0xff,0xdb,0xff,' +` 0xb2,0xff,0xe7,0xff,0xcf,0xff,0xef,0xff,' +` 0xea,0xff,0xfa,0xff,0xfb,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x06,0x00,0x2a,0x00,0x18,0x00,' +` 0x6c,0x00,0x4e,0x00,0xdd,0x00,0xa9,0x00,' +` 0x86,0x01,0x1f,0x01,0x7d,0x02,0xaf,0x02,' +` 0x20,0x04,0x9b,0x03,0x87,0x05,0x90,0x04,' +` 0xfd,0x06,0x68,0x05,0x25,0x08,0x47,0x05,' +` 0x69,0x09,0x27,0x05,0x09,0x0b,0xbf,0x03,' +` 0x37,0x0e,0x9c,0xfc,0x95,0x41,0x37,0x1a,' +` 0x11,0xff,0xb9,0x0b,0x88,0x02,0x7c,0x08,' +` 0xdb,0x02,0x6d,0x06,0x71,0x02,0x72,0x03,' +` 0x2d,0x00,0x00,0x02,0xc3,0xff,0x11,0x01,' +` 0x73,0xff,0x6a,0x00,0x54,0xff,0x32,0x00,' +` 0x3f,0xff,0xe3,0xff,0x5e,0xff,0xd6,0xff,' +` 0x87,0xff,0xdb,0xff,0xb2,0xff,0xe7,0xff,' +` 0xcf,0xff,0xef,0xff,0xea,0xff,0xfa,0xff,' +` 0xfb,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xc3,0xff,' +` 0xb5,0xff,0x1e,0xff,0xed,0xfe,0xe8,0xfd,' +` 0x98,0xfd,0x10,0xfc,0xb3,0xfb,0x95,0xf9,' +` 0x6a,0xf8,0x57,0xf5,0x4c,0xf5,0xfa,0xf1,' +` 0x7a,0xf2,0xb6,0xee,0x23,0xf0,0xe8,0xeb,' +` 0xf7,0xed,0x8f,0xe8,0xe2,0xed,0x6d,0xe7,' +` 0x22,0xf0,0x26,0xe6,0x86,0xf6,0x9d,0xdd,' +` 0xc1,0x6a,0x08,0x0a,0x55,0xe9,0x13,0xfd,' +` 0x28,0xf3,0x16,0xfe,0xee,0xf8,0x73,0x00,' +` 0x48,0xfd,0x88,0x03,0x36,0x01,0xde,0x04,' +` 0xe7,0x02,0x5b,0x05,0xa8,0x03,0x1f,0x05,' +` 0xbd,0x03,0xb4,0x04,0xec,0x02,0x57,0x03,' +` 0x15,0x02,0x2f,0x02,0x3e,0x01,0x38,0x01,' +` 0x95,0x00,0x89,0x00,0x27,0x00,0x25,0x00,' +` 0x00,0x00,0x03,0x00,0xfc,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xfe,0xff,0xfc,0xff,0x09,0x00,0x11,0x00,' +` 0x3b,0x00,0x5c,0x00,0xbe,0x00,0xee,0x00,' +` 0x84,0x01,0xc0,0x01,0x86,0x02,0xb9,0x02,' +` 0x98,0x03,0xca,0x03,0xda,0x04,0x07,0x04,' +` 0x13,0x05,0xf1,0x03,0xd9,0x04,0x03,0x03,' +` 0xd4,0x03,0x22,0x01,0x23,0x01,0xd9,0xfc,' +` 0x22,0xfe,0xa6,0xf8,0x25,0xfb,0x4a,0xf3,' +` 0x92,0xf9,0x0f,0xe9,0x56,0x6f,0x4b,0xfa,' +` 0x79,0xe8,0x0b,0xf0,0x52,0xe9,0x35,0xed,' +` 0x8b,0xe9,0x75,0xec,0xad,0xea,0x6f,0xee,' +` 0xe0,0xed,0x8d,0xf0,0xba,0xf0,0x46,0xf3,' +` 0xf0,0xf3,0x41,0xf6,0x3b,0xf7,0x06,0xfa,' +` 0xff,0xfa,0x6d,0xfc,0x18,0xfd,0x22,0xfe,' +` 0x99,0xfe,0x40,0xff,0x84,0xff,0xd7,0xff,' +` 0xea,0xff,0x08,0x00,0x08,0x00,0x09,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf7,0xff,' +` 0xef,0xff,0xe7,0xff,0xdb,0xff,0xd4,0xff,' +` 0xca,0xff,0xbc,0xff,0xae,0xff,0xa4,0xff,' +` 0x98,0xff,0x99,0xff,0x90,0xff,0xbb,0xff,' +` 0xd3,0xff,0xcd,0xff,0x0e,0x00,0x3e,0x00,' +` 0x94,0x00,0xe2,0x00,0x53,0x01,0xbf,0x01,' +` 0xad,0x03,0x87,0x04,0xfc,0x04,0x96,0x05,' +` 0x11,0x06,0x96,0x06,0xfe,0x06,0x65,0x07,' +` 0xa1,0x47,0xe6,0x07,0xf4,0x07,0xf9,0x07,' +` 0xd8,0x07,0xad,0x07,0x60,0x07,0x07,0x07,' +` 0xa5,0x06,0xa1,0x06,0x05,0x06,0x81,0x05,' +` 0xd6,0x04,0x51,0x04,0xa2,0x03,0x36,0x03,' +` 0x53,0x02,0x79,0x01,0x49,0x01,0xed,0x00,' +` 0xb4,0x00,0x7a,0x00,0x53,0x00,0x33,0x00,' +` 0x1b,0x00,0x11,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xac,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm90deg_16khz.m4 new file mode 100644 index 000000000000..bf664af09037 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm90deg_16khz.m4 @@ -0,0 +1,170 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x05,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x05,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfb,0xff,' +` 0xec,0xff,0xd1,0xff,0xa9,0xff,0x72,0xff,' +` 0x2b,0xff,0xd8,0xfe,0x79,0xfe,0x16,0xfe,' +` 0xb0,0xfd,0x4f,0xfd,0xf5,0xfc,0xc5,0xfc,' +` 0xac,0xfc,0xd6,0xfc,0x64,0xfc,0x87,0xfc,' +` 0x38,0xfd,0x90,0xfd,0x09,0xfe,0x70,0xfd,' +` 0x14,0xfc,0xfe,0xfb,0x2c,0xfc,0x75,0xfc,' +` 0x47,0xfd,0xa0,0xff,0xd1,0x01,0xfa,0x07,' +` 0x86,0x10,0xcc,0x13,0x24,0x57,0x65,0x18,' +` 0x52,0x18,0x89,0x17,0x7b,0x15,0x23,0x10,' +` 0x2a,0x09,0x76,0x05,0x94,0x02,0x7b,0x01,' +` 0x21,0x00,0x6c,0xfe,0xc9,0xfd,0x48,0xfe,' +` 0x9b,0xfe,0x09,0xff,0x45,0xff,0x72,0xff,' +` 0xc4,0xff,0xf9,0xff,0x17,0x00,0x27,0x00,' +` 0x2f,0x00,0x31,0x00,0x2c,0x00,0x24,0x00,' +` 0x1b,0x00,0x13,0x00,0x0b,0x00,0x05,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x08,0x00,0x24,0x00,0x32,0x00,' +` 0x81,0x00,0x8e,0x00,0x19,0x01,0xfe,0x00,' +` 0xb0,0x01,0x24,0x01,0xbf,0x01,0x3e,0x00,' +` 0x89,0x00,0xe7,0xfd,0x09,0xfe,0x9e,0xfa,' +` 0xc9,0xfa,0xa2,0xf6,0x6f,0xf9,0x75,0xf7,' +` 0x2e,0xfd,0x20,0xfc,0x3f,0x09,0x2f,0x0a,' +` 0x96,0x18,0x83,0x12,0x3e,0x1c,0xd1,0x05,' +` 0x08,0x0d,0x0b,0xdb,0x17,0x0e,0xf9,0x39,' +` 0x70,0xa7,0x4f,0xc7,0xf7,0xb2,0x34,0xc9,' +` 0x0b,0xc9,0x67,0xe5,0xb8,0xe9,0xa7,0xfd,' +` 0x35,0x01,0x53,0x0e,0xda,0x0b,0xa7,0x11,' +` 0x8f,0x0e,0x6c,0x10,0x67,0x0c,0x08,0x0c,' +` 0xe5,0x07,0x97,0x07,0xbf,0x04,0x69,0x04,' +` 0x7e,0x02,0x58,0x02,0x43,0x01,0x38,0x01,' +` 0x9e,0x00,0x90,0x00,0x40,0x00,0x31,0x00,' +` 0x10,0x00,0x05,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x0f,0x00,0x32,0x00,' +` 0x3e,0x00,0x93,0x00,0x99,0x00,0x3d,0x01,' +` 0x38,0x01,0x5d,0x02,0x67,0x02,0x6e,0x04,' +` 0x9b,0x04,0xa0,0x07,0xb3,0x07,0x0d,0x0c,' +` 0x2d,0x0c,0xa0,0x10,0x60,0x0e,0x20,0x12,' +` 0xc0,0x0b,0x10,0x0f,0x9f,0x01,0xf2,0xfe,' +` 0x3d,0xea,0x16,0xe7,0xc2,0xc9,0x8b,0xca,' +` 0x38,0xb2,0x9e,0xc8,0x8e,0xa4,0x45,0x2e,' +` 0xe9,0x1a,0xbe,0xd5,0xbb,0x0d,0x8c,0x03,' +` 0xdb,0x1c,0xab,0x11,0xa9,0x19,0x24,0x0a,' +` 0x5d,0x0a,0x39,0xfc,0xb9,0xfd,0x54,0xf7,' +` 0xd2,0xf9,0x5f,0xf6,0xe0,0xfa,0x53,0xfa,' +` 0x19,0xfe,0xaa,0xfd,0x90,0x00,0x16,0x00,' +` 0xc6,0x01,0x0f,0x01,0xb9,0x01,0xf4,0x00,' +` 0x20,0x01,0x8b,0x00,0x85,0x00,0x30,0x00,' +` 0x25,0x00,0x07,0x00,0x03,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x05,0x00,' +` 0x0c,0x00,0x11,0x00,0x1e,0x00,0x20,0x00,' +` 0x33,0x00,0x2a,0x00,0x3b,0x00,0x1a,0x00,' +` 0x2b,0x00,0xe7,0xff,0xe3,0xff,0x58,0xff,' +` 0x6b,0xff,0xe4,0xfe,0xd3,0xfe,0x12,0xfe,' +` 0x11,0xfe,0xfb,0xfd,0x5c,0x00,0xf8,0x00,' +` 0xf5,0x02,0x96,0x04,0x8b,0x09,0x9c,0x0e,' +` 0x78,0x16,0xcf,0x15,0xca,0x1a,0xa4,0x13,' +` 0xb0,0x56,0xa4,0x19,0x47,0x0e,0x7c,0x0a,' +` 0xc9,0x00,0xd3,0x00,0x9d,0xfc,0x2d,0xfd,' +` 0xa1,0xfb,0x83,0xfc,0x9f,0xfb,0xb0,0xfd,' +` 0xc1,0xfd,0xe0,0xfd,0x0b,0xfd,0xcf,0xfc,' +` 0x38,0xfc,0xff,0xfc,0x98,0xfc,0xe3,0xfc,' +` 0xe5,0xfc,0x61,0xfd,0xa4,0xfd,0x20,0xfe,' +` 0x70,0xfe,0xdd,0xfe,0x26,0xff,0x74,0xff,' +` 0xa7,0xff,0xd2,0xff,0xec,0xff,0xfb,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x05,0x00,0x0c,0x00,0x11,0x00,' +` 0x1e,0x00,0x20,0x00,0x33,0x00,0x2a,0x00,' +` 0x3b,0x00,0x1a,0x00,0x2b,0x00,0xe7,0xff,' +` 0xe3,0xff,0x58,0xff,0x6b,0xff,0xe4,0xfe,' +` 0xd3,0xfe,0x12,0xfe,0x11,0xfe,0xfb,0xfd,' +` 0x5c,0x00,0xf8,0x00,0xf5,0x02,0x96,0x04,' +` 0x8b,0x09,0x9c,0x0e,0x78,0x16,0xcf,0x15,' +` 0xca,0x1a,0xa4,0x13,0xb0,0x56,0xa4,0x19,' +` 0x47,0x0e,0x7c,0x0a,0xc9,0x00,0xd3,0x00,' +` 0x9d,0xfc,0x2d,0xfd,0xa1,0xfb,0x83,0xfc,' +` 0x9f,0xfb,0xb0,0xfd,0xc1,0xfd,0xe0,0xfd,' +` 0x0b,0xfd,0xcf,0xfc,0x38,0xfc,0xff,0xfc,' +` 0x98,0xfc,0xe3,0xfc,0xe5,0xfc,0x61,0xfd,' +` 0xa4,0xfd,0x20,0xfe,0x70,0xfe,0xdd,0xfe,' +` 0x26,0xff,0x74,0xff,0xa7,0xff,0xd2,0xff,' +` 0xec,0xff,0xfb,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x0f,0x00,0x32,0x00,0x3e,0x00,0x93,0x00,' +` 0x99,0x00,0x3d,0x01,0x38,0x01,0x5d,0x02,' +` 0x67,0x02,0x6e,0x04,0x9b,0x04,0xa0,0x07,' +` 0xb3,0x07,0x0d,0x0c,0x2d,0x0c,0xa0,0x10,' +` 0x60,0x0e,0x20,0x12,0xc0,0x0b,0x10,0x0f,' +` 0x9f,0x01,0xf2,0xfe,0x3d,0xea,0x16,0xe7,' +` 0xc2,0xc9,0x8b,0xca,0x38,0xb2,0x9e,0xc8,' +` 0x8e,0xa4,0x45,0x2e,0xe9,0x1a,0xbe,0xd5,' +` 0xbb,0x0d,0x8c,0x03,0xdb,0x1c,0xab,0x11,' +` 0xa9,0x19,0x24,0x0a,0x5d,0x0a,0x39,0xfc,' +` 0xb9,0xfd,0x54,0xf7,0xd2,0xf9,0x5f,0xf6,' +` 0xe0,0xfa,0x53,0xfa,0x19,0xfe,0xaa,0xfd,' +` 0x90,0x00,0x16,0x00,0xc6,0x01,0x0f,0x01,' +` 0xb9,0x01,0xf4,0x00,0x20,0x01,0x8b,0x00,' +` 0x85,0x00,0x30,0x00,0x25,0x00,0x07,0x00,' +` 0x03,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x08,0x00,' +` 0x24,0x00,0x32,0x00,0x81,0x00,0x8e,0x00,' +` 0x19,0x01,0xfe,0x00,0xb0,0x01,0x24,0x01,' +` 0xbf,0x01,0x3e,0x00,0x89,0x00,0xe7,0xfd,' +` 0x09,0xfe,0x9e,0xfa,0xc9,0xfa,0xa2,0xf6,' +` 0x6f,0xf9,0x75,0xf7,0x2e,0xfd,0x20,0xfc,' +` 0x3f,0x09,0x2f,0x0a,0x96,0x18,0x83,0x12,' +` 0x3e,0x1c,0xd1,0x05,0x08,0x0d,0x0b,0xdb,' +` 0x17,0x0e,0xf9,0x39,0x70,0xa7,0x4f,0xc7,' +` 0xf7,0xb2,0x34,0xc9,0x0b,0xc9,0x67,0xe5,' +` 0xb8,0xe9,0xa7,0xfd,0x35,0x01,0x53,0x0e,' +` 0xda,0x0b,0xa7,0x11,0x8f,0x0e,0x6c,0x10,' +` 0x67,0x0c,0x08,0x0c,0xe5,0x07,0x97,0x07,' +` 0xbf,0x04,0x69,0x04,0x7e,0x02,0x58,0x02,' +` 0x43,0x01,0x38,0x01,0x9e,0x00,0x90,0x00,' +` 0x40,0x00,0x31,0x00,0x10,0x00,0x05,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfb,0xff,0xec,0xff,0xd1,0xff,' +` 0xa9,0xff,0x72,0xff,0x2b,0xff,0xd8,0xfe,' +` 0x79,0xfe,0x16,0xfe,0xb0,0xfd,0x4f,0xfd,' +` 0xf5,0xfc,0xc5,0xfc,0xac,0xfc,0xd6,0xfc,' +` 0x64,0xfc,0x87,0xfc,0x38,0xfd,0x90,0xfd,' +` 0x09,0xfe,0x70,0xfd,0x14,0xfc,0xfe,0xfb,' +` 0x2c,0xfc,0x75,0xfc,0x47,0xfd,0xa0,0xff,' +` 0xd1,0x01,0xfa,0x07,0x86,0x10,0xcc,0x13,' +` 0x24,0x57,0x65,0x18,0x52,0x18,0x89,0x17,' +` 0x7b,0x15,0x23,0x10,0x2a,0x09,0x76,0x05,' +` 0x94,0x02,0x7b,0x01,0x21,0x00,0x6c,0xfe,' +` 0xc9,0xfd,0x48,0xfe,0x9b,0xfe,0x09,0xff,' +` 0x45,0xff,0x72,0xff,0xc4,0xff,0xf9,0xff,' +` 0x17,0x00,0x27,0x00,0x2f,0x00,0x31,0x00,' +` 0x2c,0x00,0x24,0x00,0x1b,0x00,0x13,0x00,' +` 0x0b,0x00,0x05,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm90deg_48khz.m4 new file mode 100644 index 000000000000..fa7f771f3368 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_28mm_pm90deg_48khz.m4 @@ -0,0 +1,170 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x05,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x14,0x05,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf7,0xff,0xef,0xff,0xe7,0xff,' +` 0xdb,0xff,0xd4,0xff,0xca,0xff,0xbc,0xff,' +` 0xae,0xff,0xa4,0xff,0x98,0xff,0x99,0xff,' +` 0x90,0xff,0xbb,0xff,0xd3,0xff,0xcd,0xff,' +` 0x0e,0x00,0x3e,0x00,0x94,0x00,0xe2,0x00,' +` 0x53,0x01,0xbf,0x01,0xad,0x03,0x87,0x04,' +` 0xfc,0x04,0x96,0x05,0x11,0x06,0x96,0x06,' +` 0xfe,0x06,0x65,0x07,0xa1,0x47,0xe6,0x07,' +` 0xf4,0x07,0xf9,0x07,0xd8,0x07,0xad,0x07,' +` 0x60,0x07,0x07,0x07,0xa5,0x06,0xa1,0x06,' +` 0x05,0x06,0x81,0x05,0xd6,0x04,0x51,0x04,' +` 0xa2,0x03,0x36,0x03,0x53,0x02,0x79,0x01,' +` 0x49,0x01,0xed,0x00,0xb4,0x00,0x7a,0x00,' +` 0x53,0x00,0x33,0x00,0x1b,0x00,0x11,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xfe,0xff,0xfc,0xff,' +` 0x09,0x00,0x11,0x00,0x3b,0x00,0x5c,0x00,' +` 0xbe,0x00,0xee,0x00,0x84,0x01,0xc0,0x01,' +` 0x86,0x02,0xb9,0x02,0x98,0x03,0xca,0x03,' +` 0xda,0x04,0x07,0x04,0x13,0x05,0xf1,0x03,' +` 0xd9,0x04,0x03,0x03,0xd4,0x03,0x22,0x01,' +` 0x23,0x01,0xd9,0xfc,0x22,0xfe,0xa6,0xf8,' +` 0x25,0xfb,0x4a,0xf3,0x92,0xf9,0x0f,0xe9,' +` 0x56,0x6f,0x4b,0xfa,0x79,0xe8,0x0b,0xf0,' +` 0x52,0xe9,0x35,0xed,0x8b,0xe9,0x75,0xec,' +` 0xad,0xea,0x6f,0xee,0xe0,0xed,0x8d,0xf0,' +` 0xba,0xf0,0x46,0xf3,0xf0,0xf3,0x41,0xf6,' +` 0x3b,0xf7,0x06,0xfa,0xff,0xfa,0x6d,0xfc,' +` 0x18,0xfd,0x22,0xfe,0x99,0xfe,0x40,0xff,' +` 0x84,0xff,0xd7,0xff,0xea,0xff,0x08,0x00,' +` 0x08,0x00,0x09,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x07,0x00,0x10,0x00,0x00,0x00,' +` 0x00,0x00,0xc3,0xff,0xb5,0xff,0x1e,0xff,' +` 0xed,0xfe,0xe8,0xfd,0x98,0xfd,0x10,0xfc,' +` 0xb3,0xfb,0x95,0xf9,0x6a,0xf8,0x57,0xf5,' +` 0x4c,0xf5,0xfa,0xf1,0x7a,0xf2,0xb6,0xee,' +` 0x23,0xf0,0xe8,0xeb,0xf7,0xed,0x8f,0xe8,' +` 0xe2,0xed,0x6d,0xe7,0x22,0xf0,0x26,0xe6,' +` 0x86,0xf6,0x9d,0xdd,0xc1,0x6a,0x08,0x0a,' +` 0x55,0xe9,0x13,0xfd,0x28,0xf3,0x16,0xfe,' +` 0xee,0xf8,0x73,0x00,0x48,0xfd,0x88,0x03,' +` 0x36,0x01,0xde,0x04,0xe7,0x02,0x5b,0x05,' +` 0xa8,0x03,0x1f,0x05,0xbd,0x03,0xb4,0x04,' +` 0xec,0x02,0x57,0x03,0x15,0x02,0x2f,0x02,' +` 0x3e,0x01,0x38,0x01,0x95,0x00,0x89,0x00,' +` 0x27,0x00,0x25,0x00,0x00,0x00,0x03,0x00,' +` 0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x17,0x00,0x06,0x00,' +` 0x2a,0x00,0x18,0x00,0x6c,0x00,0x4e,0x00,' +` 0xdd,0x00,0xa9,0x00,0x86,0x01,0x1f,0x01,' +` 0x7d,0x02,0xaf,0x02,0x20,0x04,0x9b,0x03,' +` 0x87,0x05,0x90,0x04,0xfd,0x06,0x68,0x05,' +` 0x25,0x08,0x47,0x05,0x69,0x09,0x27,0x05,' +` 0x09,0x0b,0xbf,0x03,0x37,0x0e,0x9c,0xfc,' +` 0x95,0x41,0x37,0x1a,0x11,0xff,0xb9,0x0b,' +` 0x88,0x02,0x7c,0x08,0xdb,0x02,0x6d,0x06,' +` 0x71,0x02,0x72,0x03,0x2d,0x00,0x00,0x02,' +` 0xc3,0xff,0x11,0x01,0x73,0xff,0x6a,0x00,' +` 0x54,0xff,0x32,0x00,0x3f,0xff,0xe3,0xff,' +` 0x5e,0xff,0xd6,0xff,0x87,0xff,0xdb,0xff,' +` 0xb2,0xff,0xe7,0xff,0xcf,0xff,0xef,0xff,' +` 0xea,0xff,0xfa,0xff,0xfb,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x06,0x00,0x2a,0x00,0x18,0x00,' +` 0x6c,0x00,0x4e,0x00,0xdd,0x00,0xa9,0x00,' +` 0x86,0x01,0x1f,0x01,0x7d,0x02,0xaf,0x02,' +` 0x20,0x04,0x9b,0x03,0x87,0x05,0x90,0x04,' +` 0xfd,0x06,0x68,0x05,0x25,0x08,0x47,0x05,' +` 0x69,0x09,0x27,0x05,0x09,0x0b,0xbf,0x03,' +` 0x37,0x0e,0x9c,0xfc,0x95,0x41,0x37,0x1a,' +` 0x11,0xff,0xb9,0x0b,0x88,0x02,0x7c,0x08,' +` 0xdb,0x02,0x6d,0x06,0x71,0x02,0x72,0x03,' +` 0x2d,0x00,0x00,0x02,0xc3,0xff,0x11,0x01,' +` 0x73,0xff,0x6a,0x00,0x54,0xff,0x32,0x00,' +` 0x3f,0xff,0xe3,0xff,0x5e,0xff,0xd6,0xff,' +` 0x87,0xff,0xdb,0xff,0xb2,0xff,0xe7,0xff,' +` 0xcf,0xff,0xef,0xff,0xea,0xff,0xfa,0xff,' +` 0xfb,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xc3,0xff,' +` 0xb5,0xff,0x1e,0xff,0xed,0xfe,0xe8,0xfd,' +` 0x98,0xfd,0x10,0xfc,0xb3,0xfb,0x95,0xf9,' +` 0x6a,0xf8,0x57,0xf5,0x4c,0xf5,0xfa,0xf1,' +` 0x7a,0xf2,0xb6,0xee,0x23,0xf0,0xe8,0xeb,' +` 0xf7,0xed,0x8f,0xe8,0xe2,0xed,0x6d,0xe7,' +` 0x22,0xf0,0x26,0xe6,0x86,0xf6,0x9d,0xdd,' +` 0xc1,0x6a,0x08,0x0a,0x55,0xe9,0x13,0xfd,' +` 0x28,0xf3,0x16,0xfe,0xee,0xf8,0x73,0x00,' +` 0x48,0xfd,0x88,0x03,0x36,0x01,0xde,0x04,' +` 0xe7,0x02,0x5b,0x05,0xa8,0x03,0x1f,0x05,' +` 0xbd,0x03,0xb4,0x04,0xec,0x02,0x57,0x03,' +` 0x15,0x02,0x2f,0x02,0x3e,0x01,0x38,0x01,' +` 0x95,0x00,0x89,0x00,0x27,0x00,0x25,0x00,' +` 0x00,0x00,0x03,0x00,0xfc,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xfe,0xff,0xfc,0xff,0x09,0x00,0x11,0x00,' +` 0x3b,0x00,0x5c,0x00,0xbe,0x00,0xee,0x00,' +` 0x84,0x01,0xc0,0x01,0x86,0x02,0xb9,0x02,' +` 0x98,0x03,0xca,0x03,0xda,0x04,0x07,0x04,' +` 0x13,0x05,0xf1,0x03,0xd9,0x04,0x03,0x03,' +` 0xd4,0x03,0x22,0x01,0x23,0x01,0xd9,0xfc,' +` 0x22,0xfe,0xa6,0xf8,0x25,0xfb,0x4a,0xf3,' +` 0x92,0xf9,0x0f,0xe9,0x56,0x6f,0x4b,0xfa,' +` 0x79,0xe8,0x0b,0xf0,0x52,0xe9,0x35,0xed,' +` 0x8b,0xe9,0x75,0xec,0xad,0xea,0x6f,0xee,' +` 0xe0,0xed,0x8d,0xf0,0xba,0xf0,0x46,0xf3,' +` 0xf0,0xf3,0x41,0xf6,0x3b,0xf7,0x06,0xfa,' +` 0xff,0xfa,0x6d,0xfc,0x18,0xfd,0x22,0xfe,' +` 0x99,0xfe,0x40,0xff,0x84,0xff,0xd7,0xff,' +` 0xea,0xff,0x08,0x00,0x08,0x00,0x09,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf7,0xff,' +` 0xef,0xff,0xe7,0xff,0xdb,0xff,0xd4,0xff,' +` 0xca,0xff,0xbc,0xff,0xae,0xff,0xa4,0xff,' +` 0x98,0xff,0x99,0xff,0x90,0xff,0xbb,0xff,' +` 0xd3,0xff,0xcd,0xff,0x0e,0x00,0x3e,0x00,' +` 0x94,0x00,0xe2,0x00,0x53,0x01,0xbf,0x01,' +` 0xad,0x03,0x87,0x04,0xfc,0x04,0x96,0x05,' +` 0x11,0x06,0x96,0x06,0xfe,0x06,0x65,0x07,' +` 0xa1,0x47,0xe6,0x07,0xf4,0x07,0xf9,0x07,' +` 0xd8,0x07,0xad,0x07,0x60,0x07,0x07,0x07,' +` 0xa5,0x06,0xa1,0x06,0x05,0x06,0x81,0x05,' +` 0xd6,0x04,0x51,0x04,0xa2,0x03,0x36,0x03,' +` 0x53,0x02,0x79,0x01,0x49,0x01,0xed,0x00,' +` 0xb4,0x00,0x7a,0x00,0x53,0x00,0x33,0x00,' +` 0x1b,0x00,0x11,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_68mm_azm90_90_13el0_0_13deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_azm90_90_13el0_0_13deg_16khz.m4 new file mode 100644 index 000000000000..b3a9ee6d81e3 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_azm90_90_13el0_0_13deg_16khz.m4 @@ -0,0 +1,852 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x64,0x1a,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x64,0x1a,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x61,0x00,0x02,0x00,0xfd,0x00,' +` 0x82,0x00,0x52,0x02,0x8a,0x01,0x72,0x04,' +` 0x12,0x03,0x2c,0x09,0x2d,0x07,0x84,0x0d,' +` 0xe3,0x09,0x46,0x12,0x0d,0x0c,0x41,0x16,' +` 0x2f,0x0b,0x54,0x1b,0x4c,0x08,0xdf,0x23,' +` 0x84,0xf8,0x6a,0x67,0x39,0x61,0xd6,0xf6,' +` 0xb4,0x1f,0x85,0x03,0xfd,0x14,0xcd,0x04,' +` 0xbe,0x0d,0x63,0xff,0x50,0x06,0x7a,0xfe,' +` 0x29,0x03,0xda,0xfd,0x3a,0x01,0x18,0xfe,' +` 0x20,0x00,0x2c,0xfe,0xca,0xff,0xb9,0xfe,' +` 0xc6,0xff,0x47,0xff,0xd4,0xff,0xa4,0xff,' +` 0xed,0xff,0xea,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x0f,0x00,0xf3,0xff,0xfe,0xff,0x7a,0xff,' +` 0x6b,0xff,0x18,0xfe,0xf3,0xfd,0x8c,0xfb,' +` 0x82,0xfb,0x8c,0xf7,0xb4,0xf6,0x92,0xf1,' +` 0xa4,0xf2,0x24,0xec,0x23,0xef,0x15,0xe7,' +` 0x7b,0xec,0x53,0xe1,0x7e,0xed,0xd1,0xdd,' +` 0xd3,0xf4,0x34,0xd4,0xc8,0x21,0x61,0x56,' +` 0x21,0xd6,0x1b,0x03,0x77,0xec,0xe2,0x01,' +` 0x85,0xf6,0x75,0x04,0x67,0xfe,0x7e,0x07,' +` 0x2b,0x02,0x10,0x08,0xd8,0x03,0x6b,0x07,' +` 0x50,0x04,0xd3,0x05,0xf4,0x02,0xcc,0x03,' +` 0xb4,0x01,0x05,0x02,0xaf,0x00,0xc7,0x00,' +` 0x12,0x00,0x2b,0x00,0xf0,0xff,0x00,0x00,' +` 0xfc,0xff,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xf9,0xff,0x0c,0x00,0x0e,0x00,0x65,0x00,' +` 0x88,0x00,0x50,0x01,0x78,0x01,0xbf,0x02,' +` 0xc8,0x02,0x79,0x04,0x40,0x04,0x4f,0x06,' +` 0x72,0x04,0xce,0x06,0xae,0x03,0x32,0x06,' +` 0x2b,0x01,0xa9,0x03,0xb7,0xfa,0x90,0xff,' +` 0x39,0xf3,0xcc,0xfc,0xef,0xe6,0xb9,0x08,' +` 0x3c,0x66,0x83,0xd8,0xaa,0xf1,0xb7,0xe0,' +` 0xc4,0xea,0x7c,0xe2,0x49,0xe9,0x7a,0xe6,' +` 0x83,0xec,0x03,0xeb,0x0e,0xf0,0x23,0xf0,' +` 0x56,0xf4,0xa5,0xf5,0xe8,0xf9,0x8f,0xfa,' +` 0xe7,0xfc,0x78,0xfd,0xe0,0xfe,0x32,0xff,' +` 0xd7,0xff,0xe3,0xff,0x13,0x00,0x09,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf8,0xff,0xee,0xff,0xe1,0xff,' +` 0xd0,0xff,0xc5,0xff,0xb2,0xff,0x9d,0xff,' +` 0x8a,0xff,0x7f,0xff,0x76,0xff,0x94,0xff,' +` 0xc9,0xff,0xc7,0xff,0x32,0x00,0x80,0x00,' +` 0x26,0x01,0x89,0x01,0xfc,0x02,0x64,0x05,' +` 0x05,0x06,0xfd,0x06,0xaa,0x07,0x76,0x08,' +` 0xfc,0x08,0x75,0x49,0xbc,0x09,0xdc,0x09,' +` 0xb6,0x09,0x79,0x09,0x01,0x09,0x6c,0x08,' +` 0x1e,0x08,0x97,0x07,0x8d,0x06,0xc6,0x05,' +` 0xba,0x04,0x0d,0x04,0xbc,0x02,0xb4,0x01,' +` 0x5a,0x01,0xe3,0x00,0x99,0x00,0x58,0x00,' +` 0x2f,0x00,0x16,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x08,0x00,0x4d,0x00,0x43,0x00,' +` 0xd0,0x00,0xbf,0x00,0xb7,0x01,0x61,0x01,' +` 0x55,0x03,0xb2,0x03,0x82,0x05,0x33,0x05,' +` 0xa4,0x07,0xab,0x06,0x7d,0x09,0xe5,0x06,' +` 0x50,0x0b,0xcb,0x06,0xc1,0x0d,0xb5,0x03,' +` 0xf5,0x17,0xa8,0x45,0x54,0xff,0xa7,0x0d,' +` 0x23,0x04,0x93,0x09,0xfb,0x03,0xfa,0x06,' +` 0x73,0x01,0xaf,0x02,0x34,0x00,0x50,0x01,' +` 0x91,0xff,0x60,0x00,0x83,0xff,0x04,0x00,' +` 0x38,0xff,0xcc,0xff,0x67,0xff,0xce,0xff,' +` 0xa0,0xff,0xde,0xff,0xc7,0xff,0xec,0xff,' +` 0xeb,0xff,0xfb,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0x0d,0x00,' +` 0xfe,0xff,0xf6,0xff,0x9c,0xff,0x53,0xff,' +` 0x5e,0xfe,0xc3,0xfd,0x07,0xfc,0x26,0xfb,' +` 0x58,0xf8,0x50,0xf6,0x95,0xf2,0xb7,0xf1,' +` 0x98,0xed,0x96,0xed,0x20,0xe9,0x19,0xea,' +` 0x29,0xe4,0x27,0xe9,0xb2,0xe2,0x94,0xec,' +` 0x9b,0xe0,0x6f,0xfc,0xc9,0x69,0x3b,0xe2,' +` 0x39,0xfa,0x41,0xf1,0x97,0xfc,0x24,0xf9,' +` 0x8c,0x00,0x99,0xff,0xe2,0x04,0x1b,0x03,' +` 0x1d,0x06,0x83,0x04,0xfa,0x05,0xe6,0x04,' +` 0x29,0x05,0x3b,0x03,0x4c,0x03,0xea,0x01,' +` 0xbd,0x01,0xd1,0x00,0xac,0x00,0x29,0x00,' +` 0x1d,0x00,0xf8,0xff,0xfd,0xff,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfb,0xff,' +` 0x03,0x00,0x11,0x00,0x4b,0x00,0x8e,0x00,' +` 0x10,0x01,0x7f,0x01,0x54,0x02,0xdd,0x02,' +` 0xd7,0x03,0x87,0x04,0xa6,0x05,0xbe,0x04,' +` 0xb6,0x05,0x4a,0x04,0xc3,0x04,0x3e,0x02,' +` 0xbc,0x01,0x95,0xfc,0xe3,0xfc,0x81,0xf6,' +` 0x1d,0xf8,0x5b,0xee,0xbb,0xf7,0xac,0x6b,' +` 0x07,0xe3,0xf1,0xeb,0x9e,0xe4,0xe1,0xe7,' +` 0xb9,0xe4,0x61,0xe7,0xa5,0xe7,0x58,0xeb,' +` 0xe4,0xeb,0x34,0xef,0xac,0xf0,0xbe,0xf3,' +` 0xdb,0xf5,0x4c,0xf9,0xc7,0xfa,0x94,0xfc,' +` 0x92,0xfd,0xb1,0xfe,0x3d,0xff,0xc3,0xff,' +` 0xeb,0xff,0x0c,0x00,0x0b,0x00,0x05,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xf9,0xff,0xf0,0xff,0xe4,0xff,0xd5,0xff,' +` 0xcd,0xff,0xbb,0xff,0xab,0xff,0x98,0xff,' +` 0x94,0xff,0x88,0xff,0xbe,0xff,0xf9,0xff,' +` 0xdd,0xff,0x53,0x00,0x98,0x00,0x48,0x01,' +` 0x9d,0x01,0x4e,0x03,0x8c,0x05,0x1f,0x06,' +` 0x1c,0x07,0xc5,0x07,0x92,0x08,0x16,0x09,' +` 0x8e,0x49,0xda,0x09,0xfb,0x09,0xd6,0x09,' +` 0x99,0x09,0x23,0x09,0x8a,0x08,0x29,0x08,' +` 0xb6,0x07,0xa4,0x06,0xdf,0x05,0xcb,0x04,' +` 0x23,0x04,0xa6,0x02,0xad,0x01,0x68,0x01,' +` 0xe7,0x00,0xa0,0x00,0x59,0x00,0x34,0x00,' +` 0x13,0x00,0x10,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x15,0x00,0x0f,0x00,0x5a,0x00,' +` 0x50,0x00,0xeb,0x00,0xd6,0x00,0xd7,0x01,' +` 0x4c,0x01,0x5e,0x03,0xd0,0x03,0xe8,0x05,' +` 0x4f,0x05,0x2a,0x08,0xb6,0x06,0xee,0x09,' +` 0xe8,0x06,0x18,0x0c,0x83,0x06,0xf5,0x0e,' +` 0x7f,0x02,0x41,0x1c,0xc2,0x43,0xef,0xfd,' +` 0xe2,0x0e,0xaa,0x03,0x65,0x0a,0xcb,0x03,' +` 0xac,0x07,0xeb,0x01,0x1d,0x03,0x4e,0x00,' +` 0xbe,0x01,0xb6,0xff,0xd0,0x00,0xd9,0xff,' +` 0x84,0x00,0x63,0xff,0x09,0x00,0x89,0xff,' +` 0xf7,0xff,0xb2,0xff,0xf3,0xff,0xd5,0xff,' +` 0xf3,0xff,0xee,0xff,0xfc,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x0d,0x00,0xef,0xff,0xfc,0xff,0x60,0xff,' +` 0x59,0xff,0xea,0xfd,0xd7,0xfd,0x53,0xfb,' +` 0x28,0xfb,0xd8,0xf6,0x03,0xf7,0x16,0xf1,' +` 0x05,0xf3,0xa4,0xeb,0xce,0xef,0x31,0xe6,' +` 0xcc,0xec,0x70,0xe0,0x79,0xee,0x13,0xdc,' +` 0x2c,0xf7,0x01,0xcf,0x64,0x39,0xdf,0x41,' +` 0x12,0xd5,0x84,0x03,0xda,0xea,0xa9,0x01,' +` 0xdd,0xf4,0x69,0x03,0x3d,0xfc,0x68,0x06,' +` 0x45,0x00,0xd9,0x06,0x1e,0x02,0x7b,0x06,' +` 0x7e,0x03,0x2d,0x05,0xe1,0x01,0x1c,0x03,' +` 0xfc,0x00,0x95,0x01,0x4d,0x00,0x9d,0x00,' +` 0xf5,0xff,0x19,0x00,0xe7,0xff,0xfd,0xff,' +` 0xfc,0xff,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xfc,0xff,' +` 0xec,0xff,0x16,0x00,0x07,0x00,0x92,0x00,' +` 0x6c,0x00,0x7e,0x01,0x2e,0x01,0xee,0x02,' +` 0x23,0x02,0x00,0x05,0xb0,0x03,0xb2,0x05,' +` 0x77,0x02,0xdd,0x05,0xa7,0x00,0x06,0x05,' +` 0x64,0xfc,0x59,0x01,0xbf,0xf5,0xdc,0xfe,' +` 0x74,0xec,0x88,0xff,0xea,0xd7,0x9c,0x5e,' +` 0x17,0x13,0x9a,0xd7,0xb4,0xf1,0xda,0xde,' +` 0xcb,0xeb,0x02,0xe2,0x7b,0xeb,0x90,0xe7,' +` 0xf1,0xee,0x98,0xec,0x9b,0xf2,0xd5,0xf1,' +` 0x0c,0xf7,0x78,0xf7,0x41,0xfb,0xb8,0xfb,' +` 0xdf,0xfd,0x2a,0xfe,0x61,0xff,0x80,0xff,' +` 0x00,0x00,0xf9,0xff,0x0e,0x00,0x03,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfa,0xff,0xf4,0xff,0xeb,0xff,0xe7,0xff,' +` 0xde,0xff,0xd7,0xff,0xcf,0xff,0xc9,0xff,' +` 0xc7,0xff,0xd1,0xff,0x38,0x00,0x66,0x00,' +` 0x3b,0x00,0x9e,0x00,0xf1,0x00,0x93,0x01,' +` 0xf8,0x01,0x39,0x04,0xd8,0x05,0x7a,0x06,' +` 0x6a,0x07,0x13,0x08,0xd8,0x08,0x58,0x09,' +` 0xc8,0x49,0x1b,0x0a,0x49,0x0a,0x26,0x0a,' +` 0xe9,0x09,0x73,0x09,0xd9,0x08,0x41,0x08,' +` 0xf7,0x07,0xea,0x06,0x13,0x06,0x09,0x05,' +` 0x3e,0x04,0x7b,0x02,0xa7,0x01,0x75,0x01,' +` 0x01,0x01,0xac,0x00,0x67,0x00,0x38,0x00,' +` 0x19,0x00,0x07,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x08,0x00,0x02,0x00,0x34,0x00,0x2a,0x00,' +` 0xa1,0x00,0x8e,0x00,0x6b,0x01,0x13,0x01,' +` 0x47,0x02,0xdc,0x01,0x4c,0x04,0xa8,0x04,' +` 0x23,0x07,0x32,0x06,0x8c,0x09,0xef,0x06,' +` 0x2b,0x0b,0x4a,0x07,0x82,0x0d,0x21,0x06,' +` 0x1c,0x11,0x8e,0xfe,0x89,0x42,0xe5,0x1e,' +` 0x55,0x00,0x30,0x0e,0xe1,0x03,0x38,0x0a,' +` 0xb5,0x03,0x81,0x07,0xf0,0x01,0x33,0x03,' +` 0x79,0x00,0xfe,0x01,0x0a,0x00,0x7e,0x01,' +` 0x2b,0x00,0xe6,0x00,0xd3,0xff,0x46,0x00,' +` 0xcd,0xff,0x1b,0x00,0xdc,0xff,0x07,0x00,' +` 0xed,0xff,0x00,0x00,0xf9,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x0d,0x00,0xed,0xff,0xf5,0xff,0x5a,0xff,' +` 0x54,0xff,0xe5,0xfd,0xe2,0xfd,0x26,0xfb,' +` 0xe5,0xfa,0x21,0xf7,0x85,0xf7,0x83,0xf1,' +` 0x5f,0xf3,0x3b,0xec,0x53,0xf0,0x55,0xe6,' +` 0x42,0xed,0x1c,0xe1,0x7e,0xee,0x41,0xdc,' +` 0xe3,0xf6,0x6c,0xcf,0xd2,0x35,0x5b,0x44,' +` 0xe7,0xd3,0x6d,0x02,0x50,0xe9,0xf9,0xff,' +` 0xc0,0xf2,0x2a,0x01,0x3b,0xf9,0x27,0x04,' +` 0xe2,0xfd,0xbd,0x04,0x02,0x00,0x23,0x05,' +` 0xab,0x01,0x32,0x04,0x08,0x01,0x14,0x02,' +` 0x45,0x00,0x0d,0x01,0xef,0xff,0x60,0x00,' +` 0xd3,0xff,0x11,0x00,0xdf,0xff,0xff,0xff,' +` 0xfd,0xff,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf2,0xff,' +` 0xff,0xff,0xe8,0xff,0x29,0x00,0xff,0xff,' +` 0x9c,0x00,0x4f,0x00,0x62,0x01,0xe8,0x00,' +` 0x17,0x03,0xd9,0x01,0x0c,0x04,0xe3,0x00,' +` 0x54,0x03,0x3c,0xff,0x8c,0x02,0x99,0xfb,' +` 0x26,0xff,0x16,0xf6,0xd3,0xfc,0xc0,0xee,' +` 0xc5,0xfb,0x80,0xe1,0xe9,0x0e,0x09,0x61,' +` 0xef,0xd3,0xec,0xf2,0x88,0xde,0x75,0xeb,' +` 0x9c,0xe1,0x91,0xea,0x96,0xe5,0xb5,0xed,' +` 0x5d,0xeb,0x23,0xf1,0x59,0xf0,0x98,0xf5,' +` 0x23,0xf6,0x88,0xf9,0x43,0xfa,0x12,0xfd,' +` 0x6f,0xfd,0xef,0xfe,0x26,0xff,0xdc,0xff,' +` 0xe5,0xff,0x18,0x00,0x09,0x00,0x05,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xfa,0xff,0xfa,0xff,0xf8,0xff,0xf9,0xff,' +` 0xfc,0xff,0x03,0x00,0x0f,0x00,0x20,0x00,' +` 0x7c,0x00,0xb4,0x00,0xf5,0x00,0xfc,0x00,' +` 0x0a,0x01,0x97,0x01,0xe0,0x01,0x08,0x03,' +` 0x5e,0x05,0x18,0x06,0x10,0x07,0xcd,0x07,' +` 0x90,0x08,0x21,0x09,0xb2,0x09,0xff,0x49,' +` 0x62,0x0a,0x7b,0x0a,0x7b,0x0a,0x32,0x0a,' +` 0xc7,0x09,0x28,0x09,0x6f,0x08,0xfd,0x07,' +` 0x60,0x07,0x36,0x06,0x6f,0x05,0x00,0x04,' +` 0x65,0x02,0xde,0x01,0x55,0x01,0x1f,0x01,' +` 0xc1,0x00,0x79,0x00,0x44,0x00,0x20,0x00,' +` 0x0c,0x00,0x01,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0x0d,0x00,0x0b,0x00,0x3f,0x00,' +` 0x40,0x00,0xb3,0x00,0xb1,0x00,0x4e,0x01,' +` 0x33,0x01,0x68,0x02,0x33,0x02,0xe6,0x03,' +` 0x80,0x04,0x67,0x07,0x5f,0x06,0x61,0x09,' +` 0xee,0x06,0x4b,0x0b,0x75,0x07,0x6b,0x0d,' +` 0x5a,0x06,0xc9,0x10,0x46,0xff,0x49,0x44,' +` 0x82,0x1c,0xa5,0x01,0xf1,0x0d,0xcc,0x04,' +` 0x3f,0x0a,0xa2,0x04,0xaa,0x07,0xc4,0x03,' +` 0x1e,0x04,0x2a,0x01,0x90,0x02,0xf9,0x00,' +` 0x1e,0x02,0xbd,0x00,0x54,0x01,0x6e,0x00,' +` 0xa6,0x00,0xfe,0xff,0x41,0x00,0xf6,0xff,' +` 0x17,0x00,0xf6,0xff,0x05,0x00,0xff,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x07,0x00,0xf8,0xff,0xe8,0xff,0x87,0xff,' +` 0x45,0xff,0x60,0xfe,0xb3,0xfd,0xbc,0xfb,' +` 0x12,0xfb,0x7f,0xf8,0xe9,0xf7,0x54,0xf4,' +` 0x4e,0xf3,0x5e,0xef,0xc1,0xef,0x03,0xea,' +` 0xfc,0xeb,0x46,0xe6,0x15,0xeb,0x84,0xe3,' +` 0xa5,0xed,0xdc,0xdf,0x1d,0xfe,0xd5,0x67,' +` 0xb8,0xde,0x04,0xf8,0xbb,0xec,0x2a,0xf8,' +` 0xf1,0xf2,0x87,0xfa,0x85,0xf7,0x62,0xfd,' +` 0x59,0xfc,0xa4,0xff,0x63,0xfe,0x5f,0x01,' +` 0x10,0x00,0x4a,0x01,0x39,0x00,0xef,0x00,' +` 0xca,0xff,0x1c,0x00,0xb7,0xff,0xf1,0xff,' +` 0xc8,0xff,0xeb,0xff,0xed,0xff,0xff,0xff,' +` 0xfe,0xff,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfc,0xff,0x01,0x00,0xe4,0xff,' +` 0xf5,0xff,0xa4,0xff,0x0a,0x00,0x6c,0xff,' +` 0x4f,0x00,0x3a,0xff,0x29,0x01,0x8b,0xff,' +` 0xd1,0x01,0x07,0xff,0x4f,0x02,0x4d,0xfd,' +` 0xec,0x00,0x88,0xfa,0x6f,0xff,0xfb,0xf4,' +` 0x81,0xfd,0x43,0xef,0xc9,0xfc,0xce,0xe6,' +` 0x58,0x00,0x41,0xd2,0xef,0x45,0x6e,0x32,' +` 0xcc,0xcf,0x19,0xf7,0x37,0xdd,0xdf,0xef,' +` 0x96,0xe2,0xf5,0xee,0x7f,0xe7,0x65,0xf1,' +` 0xdc,0xed,0x8e,0xf4,0x41,0xf3,0xc2,0xf8,' +` 0xd3,0xf7,0x9d,0xfb,0x54,0xfb,0xf7,0xfd,' +` 0x26,0xfe,0x74,0xff,0x6d,0xff,0xfd,0xff,' +` 0xef,0xff,0x0e,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,' +` 0x02,0x00,0x0b,0x00,0x14,0x00,0x26,0x00,' +` 0x37,0x00,0x67,0x00,0xc7,0x00,0xff,0x00,' +` 0x4a,0x01,0x91,0x01,0xf0,0x01,0xde,0x01,' +` 0x3f,0x02,0xba,0x02,0xe8,0x04,0x0c,0x06,' +` 0xb3,0x06,0x94,0x07,0x44,0x08,0x03,0x09,' +` 0x80,0x09,0xfb,0x09,0x31,0x4a,0x7e,0x0a,' +` 0x86,0x0a,0x7b,0x0a,0x36,0x0a,0xd9,0x09,' +` 0x3e,0x09,0x8a,0x08,0xbb,0x07,0x5e,0x07,' +` 0x6d,0x06,0x6c,0x05,0x6c,0x03,0x99,0x02,' +` 0xfe,0x01,0x78,0x01,0x01,0x01,0xc9,0x00,' +` 0x8e,0x00,0x51,0x00,0x2c,0x00,0x12,0x00,' +` 0x06,0x00,0xff,0xff,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0x0a,0x00,0x09,0x00,' +` 0x66,0x00,0x57,0x00,0x27,0x01,0xb7,0x00,' +` 0x4e,0x02,0xc2,0x01,0x67,0x04,0x4d,0x03,' +` 0x47,0x07,0x1d,0x05,0xb9,0x0c,0x80,0x0a,' +` 0xf9,0x10,0x59,0x0b,0x9e,0x15,0xd1,0x0b,' +` 0xe8,0x1a,0x55,0x09,0x9b,0x23,0x15,0xfb,' +` 0x52,0x5f,0xf2,0x6b,0x5f,0xf8,0x99,0x23,' +` 0xc5,0x06,0xce,0x19,0xf0,0x08,0x2e,0x14,' +` 0x77,0x08,0xb1,0x0f,0x49,0x04,0x66,0x08,' +` 0xbb,0x03,0xcf,0x06,0x93,0x02,0x7d,0x04,' +` 0x8e,0x01,0xb9,0x02,0xd1,0x00,0x3a,0x01,' +` 0x02,0x00,0x73,0x00,0xf1,0xff,0x39,0x00,' +` 0xfa,0xff,0x09,0x00,0xfe,0xff,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0xf9,0xff,0xff,0xff,0xc7,0xff,0xe6,0xff,' +` 0x23,0xff,0x25,0xff,0x55,0xfd,0x9f,0xfd,' +` 0xee,0xfa,0x96,0xfb,0xae,0xf7,0x1d,0xf9,' +` 0xbd,0xf3,0x9d,0xf5,0x3e,0xee,0xf4,0xf1,' +` 0xd2,0xe8,0xda,0xf0,0x69,0xe4,0x39,0xf2,' +` 0xe1,0xde,0x63,0xf9,0x94,0xce,0xf5,0x4b,' +` 0x74,0x2c,0x90,0xd5,0x67,0xfd,0x11,0xe6,' +` 0xac,0xf9,0x43,0xed,0xf5,0xf9,0x44,0xf2,' +` 0x5d,0xfb,0x4e,0xf7,0xc5,0xfd,0x17,0xfb,' +` 0x11,0xff,0xdf,0xfc,0x98,0xff,0x2b,0xfe,' +` 0xe0,0xff,0x05,0xff,0xc5,0xff,0x49,0xff,' +` 0xda,0xff,0xc3,0xff,0x04,0x00,0xf5,0xff,' +` 0x01,0x00,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xff,0xff,0xe7,0xff,' +` 0xf4,0xff,0x8d,0xff,0xa9,0xff,0x08,0xff,' +` 0x93,0xff,0xcc,0xfe,0x65,0xff,0xd9,0xfd,' +` 0xde,0xfe,0x75,0xfc,0x15,0xfe,0x84,0xfa,' +` 0x09,0xfc,0x49,0xf6,0xe6,0xf8,0x27,0xf2,' +` 0x40,0xf7,0x97,0xed,0x67,0xf6,0x5a,0xe7,' +` 0x5c,0xf9,0x61,0xd7,0x50,0x61,0x6c,0x0b,' +` 0x91,0xdb,0xd9,0xf2,0xd4,0xe3,0xc3,0xef,' +` 0xef,0xe7,0x26,0xf0,0xdc,0xeb,0x81,0xf2,' +` 0x44,0xf1,0xcc,0xf6,0x4a,0xf6,0xd1,0xf9,' +` 0xae,0xf9,0x4c,0xfc,0x6b,0xfc,0x29,0xfe,' +` 0x5a,0xfe,0x8b,0xff,0x94,0xff,0xfc,0xff,' +` 0xeb,0xff,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x09,0x00,0x14,0x00,' +` 0x16,0x00,0x29,0x00,0x44,0x00,0x8d,0x00,' +` 0xd9,0x00,0x1a,0x01,0x75,0x01,0xce,0x01,' +` 0x47,0x02,0xb3,0x02,0x31,0x03,0x07,0x03,' +` 0xd6,0x04,0x53,0x06,0xcc,0x06,0xa0,0x07,' +` 0x2b,0x08,0xde,0x08,0x56,0x09,0xe5,0x09,' +` 0x29,0x0a,0x55,0x4a,0x68,0x0a,0x69,0x0a,' +` 0x28,0x0a,0xdf,0x09,0x5b,0x09,0xd6,0x08,' +` 0x23,0x08,0x6c,0x07,0x9e,0x06,0x5a,0x06,' +` 0x56,0x04,0x32,0x03,0xa7,0x02,0x05,0x02,' +` 0x86,0x01,0x13,0x01,0xb9,0x00,0x79,0x00,' +` 0x5f,0x00,0x35,0x00,0x1a,0x00,0x04,0x00,' +` 0x00,0x00,0xff,0xff,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x08,0x00,' +` 0x12,0x00,0x2a,0x00,0x45,0x00,0x7a,0x00,' +` 0xaa,0x00,0x08,0x01,0x4f,0x01,0xd9,0x01,' +` 0x34,0x02,0xe8,0x02,0x52,0x03,0x1d,0x04,' +` 0x26,0x05,0xdc,0x06,0xe3,0x06,0x49,0x08,' +` 0x13,0x08,0xa1,0x09,0xdc,0x08,0xdf,0x0a,' +` 0xc9,0x08,0x47,0x0d,0x20,0x4a,0xab,0x07,' +` 0x47,0x0b,0xc9,0x08,0xc1,0x09,0x26,0x08,' +` 0x56,0x08,0x0b,0x07,0xce,0x06,0xc1,0x05,' +` 0xa4,0x04,0x46,0x03,0x0b,0x03,0x38,0x02,' +` 0xee,0x01,0x54,0x01,0x15,0x01,0xad,0x00,' +` 0x81,0x00,0x44,0x00,0x2a,0x00,0x11,0x00,' +` 0x09,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfc,0xff,0xf2,0xff,0xd9,0xff,0xb3,0xff,' +` 0x6f,0xff,0x1b,0xff,0x9e,0xfe,0x0a,0xfe,' +` 0x48,0xfd,0x77,0xfc,0x6e,0xfb,0x6e,0xfa,' +` 0x1d,0xf9,0x20,0xf8,0x70,0xf5,0xc2,0xf2,' +` 0xb4,0xf1,0x1e,0xf0,0x0e,0xef,0xc9,0xed,' +` 0xfa,0xec,0x15,0xec,0xa6,0xeb,0x31,0xeb,' +` 0x1e,0x6b,0x6c,0xeb,0x11,0xec,0xb0,0xec,' +` 0xbe,0xed,0xb5,0xee,0x16,0xf0,0x44,0xf1,' +` 0xe4,0xf2,0x08,0xf4,0xf6,0xf6,0x27,0xf9,' +` 0x20,0xfa,0x5a,0xfb,0x47,0xfc,0x35,0xfd,' +` 0xec,0xfd,0x91,0xfe,0x0a,0xff,0x6d,0xff,' +` 0xb1,0xff,0xd9,0xff,0xf1,0xff,0xfc,0xff,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfc,0xff,0xf2,0xff,' +` 0xd9,0xff,0xb3,0xff,0x6f,0xff,0x1b,0xff,' +` 0x9e,0xfe,0x0a,0xfe,0x48,0xfd,0x77,0xfc,' +` 0x6e,0xfb,0x6e,0xfa,0x1d,0xf9,0x20,0xf8,' +` 0x70,0xf5,0xc2,0xf2,0xb4,0xf1,0x1e,0xf0,' +` 0x0e,0xef,0xc9,0xed,0xfa,0xec,0x15,0xec,' +` 0xa6,0xeb,0x31,0xeb,0x1e,0x6b,0x6c,0xeb,' +` 0x11,0xec,0xb0,0xec,0xbe,0xed,0xb5,0xee,' +` 0x16,0xf0,0x44,0xf1,0xe4,0xf2,0x08,0xf4,' +` 0xf6,0xf6,0x27,0xf9,0x20,0xfa,0x5a,0xfb,' +` 0x47,0xfc,0x35,0xfd,0xec,0xfd,0x91,0xfe,' +` 0x0a,0xff,0x6d,0xff,0xb1,0xff,0xd9,0xff,' +` 0xf1,0xff,0xfc,0xff,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x08,0x00,0x12,0x00,0x2a,0x00,' +` 0x45,0x00,0x7a,0x00,0xaa,0x00,0x08,0x01,' +` 0x4f,0x01,0xd9,0x01,0x34,0x02,0xe8,0x02,' +` 0x52,0x03,0x1d,0x04,0x26,0x05,0xdc,0x06,' +` 0xe3,0x06,0x49,0x08,0x13,0x08,0xa1,0x09,' +` 0xdc,0x08,0xdf,0x0a,0xc9,0x08,0x47,0x0d,' +` 0x20,0x4a,0xab,0x07,0x47,0x0b,0xc9,0x08,' +` 0xc1,0x09,0x26,0x08,0x56,0x08,0x0b,0x07,' +` 0xce,0x06,0xc1,0x05,0xa4,0x04,0x46,0x03,' +` 0x0b,0x03,0x38,0x02,0xee,0x01,0x54,0x01,' +` 0x15,0x01,0xad,0x00,0x81,0x00,0x44,0x00,' +` 0x2a,0x00,0x11,0x00,0x09,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x09,0x00,0x14,0x00,0x16,0x00,0x29,0x00,' +` 0x44,0x00,0x8d,0x00,0xd9,0x00,0x1a,0x01,' +` 0x75,0x01,0xce,0x01,0x47,0x02,0xb3,0x02,' +` 0x31,0x03,0x07,0x03,0xd6,0x04,0x53,0x06,' +` 0xcc,0x06,0xa0,0x07,0x2b,0x08,0xde,0x08,' +` 0x56,0x09,0xe5,0x09,0x29,0x0a,0x55,0x4a,' +` 0x68,0x0a,0x69,0x0a,0x28,0x0a,0xdf,0x09,' +` 0x5b,0x09,0xd6,0x08,0x23,0x08,0x6c,0x07,' +` 0x9e,0x06,0x5a,0x06,0x56,0x04,0x32,0x03,' +` 0xa7,0x02,0x05,0x02,0x86,0x01,0x13,0x01,' +` 0xb9,0x00,0x79,0x00,0x5f,0x00,0x35,0x00,' +` 0x1a,0x00,0x04,0x00,0x00,0x00,0xff,0xff,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xff,0xff,0xe7,0xff,0xf4,0xff,0x8d,0xff,' +` 0xa9,0xff,0x08,0xff,0x93,0xff,0xcc,0xfe,' +` 0x65,0xff,0xd9,0xfd,0xde,0xfe,0x75,0xfc,' +` 0x15,0xfe,0x84,0xfa,0x09,0xfc,0x49,0xf6,' +` 0xe6,0xf8,0x27,0xf2,0x40,0xf7,0x97,0xed,' +` 0x67,0xf6,0x5a,0xe7,0x5c,0xf9,0x61,0xd7,' +` 0x50,0x61,0x6c,0x0b,0x91,0xdb,0xd9,0xf2,' +` 0xd4,0xe3,0xc3,0xef,0xef,0xe7,0x26,0xf0,' +` 0xdc,0xeb,0x81,0xf2,0x44,0xf1,0xcc,0xf6,' +` 0x4a,0xf6,0xd1,0xf9,0xae,0xf9,0x4c,0xfc,' +` 0x6b,0xfc,0x29,0xfe,0x5a,0xfe,0x8b,0xff,' +` 0x94,0xff,0xfc,0xff,0xeb,0xff,0x03,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xf9,0xff,0xff,0xff,' +` 0xc7,0xff,0xe6,0xff,0x23,0xff,0x25,0xff,' +` 0x55,0xfd,0x9f,0xfd,0xee,0xfa,0x96,0xfb,' +` 0xae,0xf7,0x1d,0xf9,0xbd,0xf3,0x9d,0xf5,' +` 0x3e,0xee,0xf4,0xf1,0xd2,0xe8,0xda,0xf0,' +` 0x69,0xe4,0x39,0xf2,0xe1,0xde,0x63,0xf9,' +` 0x94,0xce,0xf5,0x4b,0x74,0x2c,0x90,0xd5,' +` 0x67,0xfd,0x11,0xe6,0xac,0xf9,0x43,0xed,' +` 0xf5,0xf9,0x44,0xf2,0x5d,0xfb,0x4e,0xf7,' +` 0xc5,0xfd,0x17,0xfb,0x11,0xff,0xdf,0xfc,' +` 0x98,0xff,0x2b,0xfe,0xe0,0xff,0x05,0xff,' +` 0xc5,0xff,0x49,0xff,0xda,0xff,0xc3,0xff,' +` 0x04,0x00,0xf5,0xff,0x01,0x00,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0x0a,0x00,0x09,0x00,0x66,0x00,0x57,0x00,' +` 0x27,0x01,0xb7,0x00,0x4e,0x02,0xc2,0x01,' +` 0x67,0x04,0x4d,0x03,0x47,0x07,0x1d,0x05,' +` 0xb9,0x0c,0x80,0x0a,0xf9,0x10,0x59,0x0b,' +` 0x9e,0x15,0xd1,0x0b,0xe8,0x1a,0x55,0x09,' +` 0x9b,0x23,0x15,0xfb,0x52,0x5f,0xf2,0x6b,' +` 0x5f,0xf8,0x99,0x23,0xc5,0x06,0xce,0x19,' +` 0xf0,0x08,0x2e,0x14,0x77,0x08,0xb1,0x0f,' +` 0x49,0x04,0x66,0x08,0xbb,0x03,0xcf,0x06,' +` 0x93,0x02,0x7d,0x04,0x8e,0x01,0xb9,0x02,' +` 0xd1,0x00,0x3a,0x01,0x02,0x00,0x73,0x00,' +` 0xf1,0xff,0x39,0x00,0xfa,0xff,0x09,0x00,' +` 0xfe,0xff,0x00,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x03,0x00,0x02,0x00,0x0b,0x00,' +` 0x14,0x00,0x26,0x00,0x37,0x00,0x67,0x00,' +` 0xc7,0x00,0xff,0x00,0x4a,0x01,0x91,0x01,' +` 0xf0,0x01,0xde,0x01,0x3f,0x02,0xba,0x02,' +` 0xe8,0x04,0x0c,0x06,0xb3,0x06,0x94,0x07,' +` 0x44,0x08,0x03,0x09,0x80,0x09,0xfb,0x09,' +` 0x31,0x4a,0x7e,0x0a,0x86,0x0a,0x7b,0x0a,' +` 0x36,0x0a,0xd9,0x09,0x3e,0x09,0x8a,0x08,' +` 0xbb,0x07,0x5e,0x07,0x6d,0x06,0x6c,0x05,' +` 0x6c,0x03,0x99,0x02,0xfe,0x01,0x78,0x01,' +` 0x01,0x01,0xc9,0x00,0x8e,0x00,0x51,0x00,' +` 0x2c,0x00,0x12,0x00,0x06,0x00,0xff,0xff,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,' +` 0x01,0x00,0xe4,0xff,0xf5,0xff,0xa4,0xff,' +` 0x0a,0x00,0x6c,0xff,0x4f,0x00,0x3a,0xff,' +` 0x29,0x01,0x8b,0xff,0xd1,0x01,0x07,0xff,' +` 0x4f,0x02,0x4d,0xfd,0xec,0x00,0x88,0xfa,' +` 0x6f,0xff,0xfb,0xf4,0x81,0xfd,0x43,0xef,' +` 0xc9,0xfc,0xce,0xe6,0x58,0x00,0x41,0xd2,' +` 0xef,0x45,0x6e,0x32,0xcc,0xcf,0x19,0xf7,' +` 0x37,0xdd,0xdf,0xef,0x96,0xe2,0xf5,0xee,' +` 0x7f,0xe7,0x65,0xf1,0xdc,0xed,0x8e,0xf4,' +` 0x41,0xf3,0xc2,0xf8,0xd3,0xf7,0x9d,0xfb,' +` 0x54,0xfb,0xf7,0xfd,0x26,0xfe,0x74,0xff,' +` 0x6d,0xff,0xfd,0xff,0xef,0xff,0x0e,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x07,0x00,0xf8,0xff,' +` 0xe8,0xff,0x87,0xff,0x45,0xff,0x60,0xfe,' +` 0xb3,0xfd,0xbc,0xfb,0x12,0xfb,0x7f,0xf8,' +` 0xe9,0xf7,0x54,0xf4,0x4e,0xf3,0x5e,0xef,' +` 0xc1,0xef,0x03,0xea,0xfc,0xeb,0x46,0xe6,' +` 0x15,0xeb,0x84,0xe3,0xa5,0xed,0xdc,0xdf,' +` 0x1d,0xfe,0xd5,0x67,0xb8,0xde,0x04,0xf8,' +` 0xbb,0xec,0x2a,0xf8,0xf1,0xf2,0x87,0xfa,' +` 0x85,0xf7,0x62,0xfd,0x59,0xfc,0xa4,0xff,' +` 0x63,0xfe,0x5f,0x01,0x10,0x00,0x4a,0x01,' +` 0x39,0x00,0xef,0x00,0xca,0xff,0x1c,0x00,' +` 0xb7,0xff,0xf1,0xff,0xc8,0xff,0xeb,0xff,' +` 0xed,0xff,0xff,0xff,0xfe,0xff,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0x0d,0x00,' +` 0x0b,0x00,0x3f,0x00,0x40,0x00,0xb3,0x00,' +` 0xb1,0x00,0x4e,0x01,0x33,0x01,0x68,0x02,' +` 0x33,0x02,0xe6,0x03,0x80,0x04,0x67,0x07,' +` 0x5f,0x06,0x61,0x09,0xee,0x06,0x4b,0x0b,' +` 0x75,0x07,0x6b,0x0d,0x5a,0x06,0xc9,0x10,' +` 0x46,0xff,0x49,0x44,0x82,0x1c,0xa5,0x01,' +` 0xf1,0x0d,0xcc,0x04,0x3f,0x0a,0xa2,0x04,' +` 0xaa,0x07,0xc4,0x03,0x1e,0x04,0x2a,0x01,' +` 0x90,0x02,0xf9,0x00,0x1e,0x02,0xbd,0x00,' +` 0x54,0x01,0x6e,0x00,0xa6,0x00,0xfe,0xff,' +` 0x41,0x00,0xf6,0xff,0x17,0x00,0xf6,0xff,' +` 0x05,0x00,0xff,0xff,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xfa,0xff,0xfa,0xff,' +` 0xf8,0xff,0xf9,0xff,0xfc,0xff,0x03,0x00,' +` 0x0f,0x00,0x20,0x00,0x7c,0x00,0xb4,0x00,' +` 0xf5,0x00,0xfc,0x00,0x0a,0x01,0x97,0x01,' +` 0xe0,0x01,0x08,0x03,0x5e,0x05,0x18,0x06,' +` 0x10,0x07,0xcd,0x07,0x90,0x08,0x21,0x09,' +` 0xb2,0x09,0xff,0x49,0x62,0x0a,0x7b,0x0a,' +` 0x7b,0x0a,0x32,0x0a,0xc7,0x09,0x28,0x09,' +` 0x6f,0x08,0xfd,0x07,0x60,0x07,0x36,0x06,' +` 0x6f,0x05,0x00,0x04,0x65,0x02,0xde,0x01,' +` 0x55,0x01,0x1f,0x01,0xc1,0x00,0x79,0x00,' +` 0x44,0x00,0x20,0x00,0x0c,0x00,0x01,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xf2,0xff,0xff,0xff,0xe8,0xff,' +` 0x29,0x00,0xff,0xff,0x9c,0x00,0x4f,0x00,' +` 0x62,0x01,0xe8,0x00,0x17,0x03,0xd9,0x01,' +` 0x0c,0x04,0xe3,0x00,0x54,0x03,0x3c,0xff,' +` 0x8c,0x02,0x99,0xfb,0x26,0xff,0x16,0xf6,' +` 0xd3,0xfc,0xc0,0xee,0xc5,0xfb,0x80,0xe1,' +` 0xe9,0x0e,0x09,0x61,0xef,0xd3,0xec,0xf2,' +` 0x88,0xde,0x75,0xeb,0x9c,0xe1,0x91,0xea,' +` 0x96,0xe5,0xb5,0xed,0x5d,0xeb,0x23,0xf1,' +` 0x59,0xf0,0x98,0xf5,0x23,0xf6,0x88,0xf9,' +` 0x43,0xfa,0x12,0xfd,0x6f,0xfd,0xef,0xfe,' +` 0x26,0xff,0xdc,0xff,0xe5,0xff,0x18,0x00,' +` 0x09,0x00,0x05,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x0d,0x00,0xed,0xff,' +` 0xf5,0xff,0x5a,0xff,0x54,0xff,0xe5,0xfd,' +` 0xe2,0xfd,0x26,0xfb,0xe5,0xfa,0x21,0xf7,' +` 0x85,0xf7,0x83,0xf1,0x5f,0xf3,0x3b,0xec,' +` 0x53,0xf0,0x55,0xe6,0x42,0xed,0x1c,0xe1,' +` 0x7e,0xee,0x41,0xdc,0xe3,0xf6,0x6c,0xcf,' +` 0xd2,0x35,0x5b,0x44,0xe7,0xd3,0x6d,0x02,' +` 0x50,0xe9,0xf9,0xff,0xc0,0xf2,0x2a,0x01,' +` 0x3b,0xf9,0x27,0x04,0xe2,0xfd,0xbd,0x04,' +` 0x02,0x00,0x23,0x05,0xab,0x01,0x32,0x04,' +` 0x08,0x01,0x14,0x02,0x45,0x00,0x0d,0x01,' +` 0xef,0xff,0x60,0x00,0xd3,0xff,0x11,0x00,' +` 0xdf,0xff,0xff,0xff,0xfd,0xff,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x34,0x00,0x2a,0x00,0xa1,0x00,0x8e,0x00,' +` 0x6b,0x01,0x13,0x01,0x47,0x02,0xdc,0x01,' +` 0x4c,0x04,0xa8,0x04,0x23,0x07,0x32,0x06,' +` 0x8c,0x09,0xef,0x06,0x2b,0x0b,0x4a,0x07,' +` 0x82,0x0d,0x21,0x06,0x1c,0x11,0x8e,0xfe,' +` 0x89,0x42,0xe5,0x1e,0x55,0x00,0x30,0x0e,' +` 0xe1,0x03,0x38,0x0a,0xb5,0x03,0x81,0x07,' +` 0xf0,0x01,0x33,0x03,0x79,0x00,0xfe,0x01,' +` 0x0a,0x00,0x7e,0x01,0x2b,0x00,0xe6,0x00,' +` 0xd3,0xff,0x46,0x00,0xcd,0xff,0x1b,0x00,' +` 0xdc,0xff,0x07,0x00,0xed,0xff,0x00,0x00,' +` 0xf9,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfa,0xff,0xf4,0xff,' +` 0xeb,0xff,0xe7,0xff,0xde,0xff,0xd7,0xff,' +` 0xcf,0xff,0xc9,0xff,0xc7,0xff,0xd1,0xff,' +` 0x38,0x00,0x66,0x00,0x3b,0x00,0x9e,0x00,' +` 0xf1,0x00,0x93,0x01,0xf8,0x01,0x39,0x04,' +` 0xd8,0x05,0x7a,0x06,0x6a,0x07,0x13,0x08,' +` 0xd8,0x08,0x58,0x09,0xc8,0x49,0x1b,0x0a,' +` 0x49,0x0a,0x26,0x0a,0xe9,0x09,0x73,0x09,' +` 0xd9,0x08,0x41,0x08,0xf7,0x07,0xea,0x06,' +` 0x13,0x06,0x09,0x05,0x3e,0x04,0x7b,0x02,' +` 0xa7,0x01,0x75,0x01,0x01,0x01,0xac,0x00,' +` 0x67,0x00,0x38,0x00,0x19,0x00,0x07,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfc,0xff,0xfc,0xff,0xec,0xff,0x16,0x00,' +` 0x07,0x00,0x92,0x00,0x6c,0x00,0x7e,0x01,' +` 0x2e,0x01,0xee,0x02,0x23,0x02,0x00,0x05,' +` 0xb0,0x03,0xb2,0x05,0x77,0x02,0xdd,0x05,' +` 0xa7,0x00,0x06,0x05,0x64,0xfc,0x59,0x01,' +` 0xbf,0xf5,0xdc,0xfe,0x74,0xec,0x88,0xff,' +` 0xea,0xd7,0x9c,0x5e,0x17,0x13,0x9a,0xd7,' +` 0xb4,0xf1,0xda,0xde,0xcb,0xeb,0x02,0xe2,' +` 0x7b,0xeb,0x90,0xe7,0xf1,0xee,0x98,0xec,' +` 0x9b,0xf2,0xd5,0xf1,0x0c,0xf7,0x78,0xf7,' +` 0x41,0xfb,0xb8,0xfb,0xdf,0xfd,0x2a,0xfe,' +` 0x61,0xff,0x80,0xff,0x00,0x00,0xf9,0xff,' +` 0x0e,0x00,0x03,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x0d,0x00,0xef,0xff,' +` 0xfc,0xff,0x60,0xff,0x59,0xff,0xea,0xfd,' +` 0xd7,0xfd,0x53,0xfb,0x28,0xfb,0xd8,0xf6,' +` 0x03,0xf7,0x16,0xf1,0x05,0xf3,0xa4,0xeb,' +` 0xce,0xef,0x31,0xe6,0xcc,0xec,0x70,0xe0,' +` 0x79,0xee,0x13,0xdc,0x2c,0xf7,0x01,0xcf,' +` 0x64,0x39,0xdf,0x41,0x12,0xd5,0x84,0x03,' +` 0xda,0xea,0xa9,0x01,0xdd,0xf4,0x69,0x03,' +` 0x3d,0xfc,0x68,0x06,0x45,0x00,0xd9,0x06,' +` 0x1e,0x02,0x7b,0x06,0x7e,0x03,0x2d,0x05,' +` 0xe1,0x01,0x1c,0x03,0xfc,0x00,0x95,0x01,' +` 0x4d,0x00,0x9d,0x00,0xf5,0xff,0x19,0x00,' +` 0xe7,0xff,0xfd,0xff,0xfc,0xff,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,' +` 0x0f,0x00,0x5a,0x00,0x50,0x00,0xeb,0x00,' +` 0xd6,0x00,0xd7,0x01,0x4c,0x01,0x5e,0x03,' +` 0xd0,0x03,0xe8,0x05,0x4f,0x05,0x2a,0x08,' +` 0xb6,0x06,0xee,0x09,0xe8,0x06,0x18,0x0c,' +` 0x83,0x06,0xf5,0x0e,0x7f,0x02,0x41,0x1c,' +` 0xc2,0x43,0xef,0xfd,0xe2,0x0e,0xaa,0x03,' +` 0x65,0x0a,0xcb,0x03,0xac,0x07,0xeb,0x01,' +` 0x1d,0x03,0x4e,0x00,0xbe,0x01,0xb6,0xff,' +` 0xd0,0x00,0xd9,0xff,0x84,0x00,0x63,0xff,' +` 0x09,0x00,0x89,0xff,0xf7,0xff,0xb2,0xff,' +` 0xf3,0xff,0xd5,0xff,0xf3,0xff,0xee,0xff,' +` 0xfc,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xf9,0xff,0xf0,0xff,' +` 0xe4,0xff,0xd5,0xff,0xcd,0xff,0xbb,0xff,' +` 0xab,0xff,0x98,0xff,0x94,0xff,0x88,0xff,' +` 0xbe,0xff,0xf9,0xff,0xdd,0xff,0x53,0x00,' +` 0x98,0x00,0x48,0x01,0x9d,0x01,0x4e,0x03,' +` 0x8c,0x05,0x1f,0x06,0x1c,0x07,0xc5,0x07,' +` 0x92,0x08,0x16,0x09,0x8e,0x49,0xda,0x09,' +` 0xfb,0x09,0xd6,0x09,0x99,0x09,0x23,0x09,' +` 0x8a,0x08,0x29,0x08,0xb6,0x07,0xa4,0x06,' +` 0xdf,0x05,0xcb,0x04,0x23,0x04,0xa6,0x02,' +` 0xad,0x01,0x68,0x01,0xe7,0x00,0xa0,0x00,' +` 0x59,0x00,0x34,0x00,0x13,0x00,0x10,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfb,0xff,0x03,0x00,0x11,0x00,' +` 0x4b,0x00,0x8e,0x00,0x10,0x01,0x7f,0x01,' +` 0x54,0x02,0xdd,0x02,0xd7,0x03,0x87,0x04,' +` 0xa6,0x05,0xbe,0x04,0xb6,0x05,0x4a,0x04,' +` 0xc3,0x04,0x3e,0x02,0xbc,0x01,0x95,0xfc,' +` 0xe3,0xfc,0x81,0xf6,0x1d,0xf8,0x5b,0xee,' +` 0xbb,0xf7,0xac,0x6b,0x07,0xe3,0xf1,0xeb,' +` 0x9e,0xe4,0xe1,0xe7,0xb9,0xe4,0x61,0xe7,' +` 0xa5,0xe7,0x58,0xeb,0xe4,0xeb,0x34,0xef,' +` 0xac,0xf0,0xbe,0xf3,0xdb,0xf5,0x4c,0xf9,' +` 0xc7,0xfa,0x94,0xfc,0x92,0xfd,0xb1,0xfe,' +` 0x3d,0xff,0xc3,0xff,0xeb,0xff,0x0c,0x00,' +` 0x0b,0x00,0x05,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0x0d,0x00,0xfe,0xff,0xf6,0xff,' +` 0x9c,0xff,0x53,0xff,0x5e,0xfe,0xc3,0xfd,' +` 0x07,0xfc,0x26,0xfb,0x58,0xf8,0x50,0xf6,' +` 0x95,0xf2,0xb7,0xf1,0x98,0xed,0x96,0xed,' +` 0x20,0xe9,0x19,0xea,0x29,0xe4,0x27,0xe9,' +` 0xb2,0xe2,0x94,0xec,0x9b,0xe0,0x6f,0xfc,' +` 0xc9,0x69,0x3b,0xe2,0x39,0xfa,0x41,0xf1,' +` 0x97,0xfc,0x24,0xf9,0x8c,0x00,0x99,0xff,' +` 0xe2,0x04,0x1b,0x03,0x1d,0x06,0x83,0x04,' +` 0xfa,0x05,0xe6,0x04,0x29,0x05,0x3b,0x03,' +` 0x4c,0x03,0xea,0x01,0xbd,0x01,0xd1,0x00,' +` 0xac,0x00,0x29,0x00,0x1d,0x00,0xf8,0xff,' +` 0xfd,0xff,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x18,0x00,0x08,0x00,' +` 0x4d,0x00,0x43,0x00,0xd0,0x00,0xbf,0x00,' +` 0xb7,0x01,0x61,0x01,0x55,0x03,0xb2,0x03,' +` 0x82,0x05,0x33,0x05,0xa4,0x07,0xab,0x06,' +` 0x7d,0x09,0xe5,0x06,0x50,0x0b,0xcb,0x06,' +` 0xc1,0x0d,0xb5,0x03,0xf5,0x17,0xa8,0x45,' +` 0x54,0xff,0xa7,0x0d,0x23,0x04,0x93,0x09,' +` 0xfb,0x03,0xfa,0x06,0x73,0x01,0xaf,0x02,' +` 0x34,0x00,0x50,0x01,0x91,0xff,0x60,0x00,' +` 0x83,0xff,0x04,0x00,0x38,0xff,0xcc,0xff,' +` 0x67,0xff,0xce,0xff,0xa0,0xff,0xde,0xff,' +` 0xc7,0xff,0xec,0xff,0xeb,0xff,0xfb,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x34,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf8,0xff,' +` 0xee,0xff,0xe1,0xff,0xd0,0xff,0xc5,0xff,' +` 0xb2,0xff,0x9d,0xff,0x8a,0xff,0x7f,0xff,' +` 0x76,0xff,0x94,0xff,0xc9,0xff,0xc7,0xff,' +` 0x32,0x00,0x80,0x00,0x26,0x01,0x89,0x01,' +` 0xfc,0x02,0x64,0x05,0x05,0x06,0xfd,0x06,' +` 0xaa,0x07,0x76,0x08,0xfc,0x08,0x75,0x49,' +` 0xbc,0x09,0xdc,0x09,0xb6,0x09,0x79,0x09,' +` 0x01,0x09,0x6c,0x08,0x1e,0x08,0x97,0x07,' +` 0x8d,0x06,0xc6,0x05,0xba,0x04,0x0d,0x04,' +` 0xbc,0x02,0xb4,0x01,0x5a,0x01,0xe3,0x00,' +` 0x99,0x00,0x58,0x00,0x2f,0x00,0x16,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xf9,0xff,0x0c,0x00,' +` 0x0e,0x00,0x65,0x00,0x88,0x00,0x50,0x01,' +` 0x78,0x01,0xbf,0x02,0xc8,0x02,0x79,0x04,' +` 0x40,0x04,0x4f,0x06,0x72,0x04,0xce,0x06,' +` 0xae,0x03,0x32,0x06,0x2b,0x01,0xa9,0x03,' +` 0xb7,0xfa,0x90,0xff,0x39,0xf3,0xcc,0xfc,' +` 0xef,0xe6,0xb9,0x08,0x3c,0x66,0x83,0xd8,' +` 0xaa,0xf1,0xb7,0xe0,0xc4,0xea,0x7c,0xe2,' +` 0x49,0xe9,0x7a,0xe6,0x83,0xec,0x03,0xeb,' +` 0x0e,0xf0,0x23,0xf0,0x56,0xf4,0xa5,0xf5,' +` 0xe8,0xf9,0x8f,0xfa,0xe7,0xfc,0x78,0xfd,' +` 0xe0,0xfe,0x32,0xff,0xd7,0xff,0xe3,0xff,' +` 0x13,0x00,0x09,0x00,0x34,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x0f,0x00,0xf3,0xff,' +` 0xfe,0xff,0x7a,0xff,0x6b,0xff,0x18,0xfe,' +` 0xf3,0xfd,0x8c,0xfb,0x82,0xfb,0x8c,0xf7,' +` 0xb4,0xf6,0x92,0xf1,0xa4,0xf2,0x24,0xec,' +` 0x23,0xef,0x15,0xe7,0x7b,0xec,0x53,0xe1,' +` 0x7e,0xed,0xd1,0xdd,0xd3,0xf4,0x34,0xd4,' +` 0xc8,0x21,0x61,0x56,0x21,0xd6,0x1b,0x03,' +` 0x77,0xec,0xe2,0x01,0x85,0xf6,0x75,0x04,' +` 0x67,0xfe,0x7e,0x07,0x2b,0x02,0x10,0x08,' +` 0xd8,0x03,0x6b,0x07,0x50,0x04,0xd3,0x05,' +` 0xf4,0x02,0xcc,0x03,0xb4,0x01,0x05,0x02,' +` 0xaf,0x00,0xc7,0x00,0x12,0x00,0x2b,0x00,' +` 0xf0,0xff,0x00,0x00,0xfc,0xff,0x00,0x00,' +` 0x34,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x61,0x00,' +` 0x02,0x00,0xfd,0x00,0x82,0x00,0x52,0x02,' +` 0x8a,0x01,0x72,0x04,0x12,0x03,0x2c,0x09,' +` 0x2d,0x07,0x84,0x0d,0xe3,0x09,0x46,0x12,' +` 0x0d,0x0c,0x41,0x16,0x2f,0x0b,0x54,0x1b,' +` 0x4c,0x08,0xdf,0x23,0x84,0xf8,0x6a,0x67,' +` 0x39,0x61,0xd6,0xf6,0xb4,0x1f,0x85,0x03,' +` 0xfd,0x14,0xcd,0x04,0xbe,0x0d,0x63,0xff,' +` 0x50,0x06,0x7a,0xfe,0x29,0x03,0xda,0xfd,' +` 0x3a,0x01,0x18,0xfe,0x20,0x00,0x2c,0xfe,' +` 0xca,0xff,0xb9,0xfe,0xc6,0xff,0x47,0xff,' +` 0xd4,0xff,0xa4,0xff,0xed,0xff,0xea,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0xa2,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_68mm_azm90_90_13el0_0_13deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_azm90_90_13el0_0_13deg_48khz.m4 new file mode 100644 index 000000000000..b5df9df56096 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_azm90_90_13el0_0_13deg_48khz.m4 @@ -0,0 +1,1632 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x32,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc4,0x32,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x55,0x00,0xa0,0x00,0x7e,0x00,0x41,0x01,' +` 0xdf,0x00,0x9c,0x01,0x24,0x01,0x09,0x02,' +` 0x6f,0x01,0x85,0x02,0xc1,0x01,0x0c,0x03,' +` 0x16,0x02,0x9f,0x03,0x6e,0x02,0x3c,0x04,' +` 0xc4,0x02,0xe0,0x04,0x16,0x03,0x8a,0x05,' +` 0x64,0x03,0x19,0x06,0x2e,0x03,0x99,0x06,' +` 0x54,0x03,0x4c,0x07,0x5b,0x03,0x09,0x08,' +` 0x3d,0x03,0xd6,0x08,0xee,0x02,0xc0,0x09,' +` 0x56,0x02,0xe6,0x0a,0x45,0x01,0x8a,0x0c,' +` 0x4b,0xff,0x71,0x0f,0xf2,0xfa,0xd9,0x16,' +` 0xbc,0xea,0x7e,0x5f,0xba,0x4f,0x34,0xec,' +` 0xbf,0x15,0xab,0xfa,0x71,0x0e,0x82,0xfe,' +` 0x55,0x0b,0x23,0x00,0x74,0x09,0xec,0x00,' +` 0x17,0x08,0x4c,0x01,0xff,0x06,0x71,0x01,' +` 0x0f,0x06,0x72,0x01,0x3b,0x05,0x60,0x01,' +` 0x79,0x04,0x49,0x01,0x19,0x03,0xdf,0xff,' +` 0x40,0x02,0xd6,0xff,0xc5,0x01,0xc5,0xff,' +` 0x5f,0x01,0xb5,0xff,0x09,0x01,0xaa,0xff,' +` 0xc3,0x00,0xa3,0xff,0x89,0x00,0xa2,0xff,' +` 0x5c,0x00,0xa5,0xff,0x3a,0x00,0xad,0xff,' +` 0x1f,0x00,0xc8,0xff,0x24,0x00,0xc0,0xff,' +` 0x09,0x00,0xcf,0xff,0x02,0x00,0xdc,0xff,' +` 0xff,0xff,0xe8,0xff,0xfe,0xff,0xf2,0xff,' +` 0xff,0xff,0xfa,0xff,0xff,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf5,0xff,0xec,0xff,' +` 0xe3,0xff,0xd4,0xff,0xc6,0xff,0xb0,0xff,' +` 0x9c,0xff,0x7e,0xff,0x63,0xff,0x3d,0xff,' +` 0x17,0xff,0xd2,0xfe,0x97,0xfe,0x4f,0xfe,' +` 0x23,0xfe,0xd4,0xfd,0xa3,0xfd,0x4b,0xfd,' +` 0x18,0xfd,0xb7,0xfc,0x85,0xfc,0x1b,0xfc,' +` 0xed,0xfb,0x7c,0xfb,0x54,0xfb,0xdc,0xfa,' +` 0xbf,0xfa,0x42,0xfa,0x31,0xfa,0xaf,0xf9,' +` 0xae,0xf9,0xd6,0xf8,0xd7,0xf8,0x57,0xf8,' +` 0x85,0xf8,0xff,0xf7,0x4e,0xf8,0xbf,0xf7,' +` 0x34,0xf8,0x9a,0xf7,0x3b,0xf8,0x8c,0xf7,' +` 0x67,0xf8,0x94,0xf7,0xbc,0xf8,0xa7,0xf7,' +` 0x49,0xf9,0xa8,0xf7,0x41,0xfa,0x0f,0xf7,' +` 0x9f,0xfd,0x73,0x79,0x07,0xf6,0x56,0xfc,' +` 0x50,0xf9,0x03,0xfc,0x8e,0xfa,0x61,0xfc,' +` 0x83,0xfb,0xed,0xfc,0x5d,0xfc,0x87,0xfd,' +` 0x26,0xfd,0x23,0xfe,0xe0,0xfd,0xba,0xfe,' +` 0x8a,0xfe,0x46,0xff,0x21,0xff,0xc4,0xff,' +` 0xa1,0xff,0x39,0x00,0x6d,0x00,0xd1,0x00,' +` 0xb5,0x00,0x05,0x01,0xe8,0x00,0x27,0x01,' +` 0x09,0x01,0x38,0x01,0x19,0x01,0x39,0x01,' +` 0x19,0x01,0x2e,0x01,0x0c,0x01,0x17,0x01,' +` 0xf6,0x00,0xf8,0x00,0xd9,0x00,0xd4,0x00,' +` 0xbb,0x00,0xcb,0x00,0x98,0x00,0x87,0x00,' +` 0x70,0x00,0x63,0x00,0x4f,0x00,0x44,0x00,' +` 0x33,0x00,0x2a,0x00,0x1e,0x00,0x16,0x00,' +` 0x0e,0x00,0x09,0x00,0x05,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,' +` 0x0b,0x00,0x0a,0x00,0x1b,0x00,0x16,0x00,' +` 0x33,0x00,0x26,0x00,0x53,0x00,0x3b,0x00,' +` 0x7b,0x00,0x52,0x00,0xaa,0x00,0x6b,0x00,' +` 0xf2,0x00,0x98,0x00,0x0c,0x01,0x9c,0x00,' +` 0x42,0x01,0xa9,0x00,0x75,0x01,0xac,0x00,' +` 0xa3,0x01,0xa4,0x00,0xca,0x01,0x8b,0x00,' +` 0xe7,0x01,0x60,0x00,0xf9,0x01,0x20,0x00,' +` 0xff,0x01,0xc7,0xff,0xf7,0x01,0x58,0xff,' +` 0xc2,0x01,0x4f,0xfe,0x66,0x01,0x92,0xfd,' +` 0x33,0x01,0xad,0xfc,0x04,0x01,0xa0,0xfb,' +` 0xe3,0x00,0x63,0xfa,0xe4,0x00,0xe3,0xf8,' +` 0x29,0x01,0xf7,0xf6,0xfc,0x01,0x34,0xf4,' +` 0x23,0x04,0x2f,0xef,0xd1,0x0a,0xb9,0xde,' +` 0xe4,0x4d,0x3f,0x48,0x8c,0xde,0x07,0x09,' +` 0x67,0xed,0x63,0x01,0x4a,0xf1,0x3e,0xfe,' +` 0x0c,0xf3,0x82,0xfc,0x18,0xf4,0x73,0xfb,' +` 0xdc,0xf4,0xcc,0xfa,0x84,0xf5,0x6f,0xfa,' +` 0x25,0xf6,0x4a,0xfa,0xc9,0xf6,0x53,0xfa,' +` 0x74,0xf7,0xc1,0xfa,0x9d,0xf8,0x2d,0xfb,' +` 0x57,0xf9,0x91,0xfb,0x16,0xfa,0x01,0xfc,' +` 0xd6,0xfa,0x7a,0xfc,0x91,0xfb,0xf7,0xfc,' +` 0x45,0xfc,0x73,0xfd,0xee,0xfc,0xea,0xfd,' +` 0x8a,0xfd,0x59,0xfe,0x17,0xfe,0xbb,0xfe,' +` 0x9d,0xfe,0x2e,0xff,0x1c,0xff,0x79,0xff,' +` 0x67,0xff,0xaa,0xff,0xa1,0xff,0xcf,0xff,' +` 0xcc,0xff,0xe8,0xff,0xe8,0xff,0xf7,0xff,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfe,0xff,0xfd,0xff,0xfc,0xff,0xfb,0xff,' +` 0xfa,0xff,0xf8,0xff,0xf7,0xff,0xf6,0xff,' +` 0xf4,0xff,0xf4,0xff,0xf2,0xff,0xf6,0xff,' +` 0x00,0x00,0xf5,0xff,0xf5,0xff,0xf7,0xff,' +` 0xfa,0xff,0xfe,0xff,0x03,0x00,0x08,0x00,' +` 0x0f,0x00,0x17,0x00,0x20,0x00,0x2a,0x00,' +` 0x36,0x00,0x42,0x00,0x51,0x00,0x5f,0x00,' +` 0x71,0x00,0x80,0x00,0x96,0x00,0xa7,0x00,' +` 0x3b,0x01,0x72,0x01,0x84,0x01,0xa4,0x01,' +` 0xbc,0x01,0xdb,0x01,0xf5,0x01,0x12,0x02,' +` 0x2c,0x02,0x48,0x02,0x62,0x02,0x7c,0x02,' +` 0x94,0x02,0xad,0x02,0xc3,0x02,0xd9,0x02,' +` 0xec,0x02,0xfe,0x02,0x0e,0x03,0x1d,0x03,' +` 0x25,0x43,0x34,0x03,0x3a,0x03,0x3f,0x03,' +` 0x40,0x03,0x40,0x03,0x3d,0x03,0x38,0x03,' +` 0x31,0x03,0x27,0x03,0x1b,0x03,0x0d,0x03,' +` 0xfd,0x02,0xeb,0x02,0xd8,0x02,0xc2,0x02,' +` 0xac,0x02,0x93,0x02,0x7b,0x02,0x5d,0x02,' +` 0x4a,0x02,0x54,0x02,0x35,0x02,0x17,0x02,' +` 0xf7,0x01,0xd8,0x01,0xb9,0x01,0x9a,0x01,' +` 0x7c,0x01,0x5e,0x01,0x41,0x01,0x25,0x01,' +` 0x0a,0x01,0xf0,0x00,0xd7,0x00,0xc0,0x00,' +` 0xaa,0x00,0x95,0x00,0x83,0x00,0x6b,0x00,' +` 0x3d,0x00,0x3a,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x85,0x00,0x4e,0x00,0xa0,0x00,0x71,0x00,' +` 0x3e,0x01,0xeb,0x00,0x9f,0x01,0x30,0x01,' +` 0x0f,0x02,0x7d,0x01,0x8b,0x02,0xd0,0x01,' +` 0x15,0x03,0x27,0x02,0xa9,0x03,0x80,0x02,' +` 0x47,0x04,0xd9,0x02,0xec,0x04,0x2c,0x03,' +` 0x98,0x05,0x7b,0x03,0x09,0x06,0x4b,0x03,' +` 0xa5,0x06,0x72,0x03,0x58,0x07,0x7b,0x03,' +` 0x15,0x08,0x5f,0x03,0xe0,0x08,0x12,0x03,' +` 0xc8,0x09,0x7b,0x02,0xeb,0x0a,0x6e,0x01,' +` 0x8b,0x0c,0x77,0xff,0x6d,0x0f,0x22,0xfb,' +` 0xd4,0x16,0xbe,0xea,0xa0,0x63,0x36,0x4b,' +` 0x1e,0xed,0x65,0x15,0xfe,0xfa,0x50,0x0e,' +` 0xb7,0xfe,0x47,0x0b,0x4b,0x00,0x6e,0x09,' +` 0x0e,0x01,0x17,0x08,0x69,0x01,0x02,0x07,' +` 0x8b,0x01,0x15,0x06,0x8a,0x01,0x42,0x05,' +` 0x77,0x01,0x81,0x04,0x5d,0x01,0x74,0x03,' +` 0xee,0xff,0x48,0x02,0xe5,0xff,0xce,0x01,' +` 0xd2,0xff,0x68,0x01,0xc2,0xff,0x13,0x01,' +` 0xb5,0xff,0xcc,0x00,0xad,0xff,0x92,0x00,' +` 0xab,0xff,0x65,0x00,0xac,0xff,0x42,0x00,' +` 0xb2,0xff,0x2a,0x00,0xd3,0xff,0x30,0x00,' +` 0xce,0xff,0x0a,0x00,0xd4,0xff,0x04,0x00,' +` 0xe0,0xff,0x01,0x00,0xeb,0xff,0xff,0xff,' +` 0xf4,0xff,0xff,0xff,0xfa,0xff,0x00,0x00,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf8,0xff,0xf6,0xff,' +` 0xe8,0xff,0xe7,0xff,0xcc,0xff,0xce,0xff,' +` 0xa2,0xff,0xa9,0xff,0x68,0xff,0x78,0xff,' +` 0x18,0xff,0x23,0xff,0xab,0xfe,0xba,0xfe,' +` 0x1b,0xfe,0x54,0xfe,0x91,0xfd,0xe4,0xfd,' +` 0xf7,0xfc,0x6b,0xfd,0x4f,0xfc,0xed,0xfc,' +` 0x9d,0xfb,0x6e,0xfc,0xe5,0xfa,0xf1,0xfb,' +` 0x28,0xfa,0x7d,0xfb,0x6c,0xf9,0x15,0xfb,' +` 0xb6,0xf8,0x90,0xfa,0x90,0xf7,0x2b,0xfa,' +` 0xe3,0xf6,0x18,0xfa,0x46,0xf6,0x32,0xfa,' +` 0xad,0xf5,0x82,0xfa,0x10,0xf5,0x18,0xfb,' +` 0x5e,0xf4,0x0e,0xfc,0x6e,0xf3,0xa1,0xfd,' +` 0xe1,0xf1,0x73,0x00,0x7e,0xee,0x1d,0x07,' +` 0x23,0xe2,0x84,0x35,0x25,0x5e,0xae,0xde,' +` 0x2f,0x0a,0x9b,0xef,0x90,0x03,0x81,0xf4,' +` 0x82,0x01,0x2b,0xf7,0xc1,0x00,0x06,0xf9,' +` 0x88,0x00,0x79,0xfa,0x90,0x00,0xad,0xfb,' +` 0xb8,0x00,0xb2,0xfc,0xee,0x00,0x92,0xfd,' +` 0x25,0x01,0x49,0xfe,0x61,0x01,0x49,0xff,' +` 0xc2,0x01,0xba,0xff,0xcf,0x01,0x11,0x00,' +` 0xce,0x01,0x52,0x00,0xc1,0x01,0x7d,0x00,' +` 0xa8,0x01,0x96,0x00,0x87,0x01,0xa0,0x00,' +` 0x5d,0x01,0x9d,0x00,0x2f,0x01,0x91,0x00,' +` 0xff,0x00,0x94,0x00,0xec,0x00,0x74,0x00,' +` 0x9d,0x00,0x50,0x00,0x73,0x00,0x38,0x00,' +` 0x4e,0x00,0x25,0x00,0x30,0x00,0x15,0x00,' +` 0x1a,0x00,0x0a,0x00,0x0b,0x00,0x03,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x05,0x00,0x07,0x00,0x10,0x00,0x11,0x00,' +` 0x21,0x00,0x21,0x00,0x39,0x00,0x35,0x00,' +` 0x58,0x00,0x4e,0x00,0x7c,0x00,0x6c,0x00,' +` 0xbc,0x00,0xa0,0x00,0xd7,0x00,0x9c,0x00,' +` 0xfa,0x00,0xb1,0x00,0x20,0x01,0xbf,0x00,' +` 0x41,0x01,0xc2,0x00,0x5b,0x01,0xb9,0x00,' +` 0x6a,0x01,0xa0,0x00,0x6d,0x01,0x74,0x00,' +` 0x62,0x01,0x34,0x00,0x47,0x01,0xe2,0xff,' +` 0xfb,0x00,0xfd,0xfe,0x8a,0x00,0x6d,0xfe,' +` 0x37,0x00,0xb9,0xfd,0xdc,0xff,0xe7,0xfc,' +` 0x81,0xff,0xf5,0xfb,0x31,0xff,0xdc,0xfa,' +` 0xfe,0xfe,0x8b,0xf9,0x0c,0xff,0xd2,0xf7,' +` 0xb9,0xff,0x17,0xf5,0x54,0x02,0xff,0xed,' +` 0xf6,0x14,0x97,0x72,0x95,0xe6,0x14,0x03,' +` 0xdf,0xf1,0xbf,0xfd,0x31,0xf4,0xa6,0xfb,' +` 0x1f,0xf5,0x80,0xfa,0xa4,0xf5,0xcf,0xf9,' +` 0x0a,0xf6,0x69,0xf9,0x6b,0xf6,0x3a,0xf9,' +` 0xd4,0xf6,0x39,0xf9,0x4b,0xf7,0x5d,0xf9,' +` 0xd7,0xf7,0xb4,0xf9,0xd1,0xf8,0x73,0xfa,' +` 0x7e,0xf9,0xe6,0xfa,0x2a,0xfa,0x67,0xfb,' +` 0xda,0xfa,0xef,0xfb,0x89,0xfb,0x7b,0xfc,' +` 0x34,0xfc,0x05,0xfd,0xd7,0xfc,0x8a,0xfd,' +` 0x70,0xfd,0x06,0xfe,0xfc,0xfd,0x75,0xfe,' +` 0x86,0xfe,0xf2,0xfe,0xf7,0xfe,0x53,0xff,' +` 0x53,0xff,0x8d,0xff,0x91,0xff,0xba,0xff,' +` 0xbf,0xff,0xda,0xff,0xdf,0xff,0xef,0xff,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfe,0xff,0xfe,0xff,0xfd,0xff,0xfc,0xff,' +` 0xfb,0xff,0xf9,0xff,0xf8,0xff,0xf7,0xff,' +` 0xf7,0xff,0xf6,0xff,0xf6,0xff,0xff,0xff,' +` 0x05,0x00,0xfe,0xff,0xf8,0xff,0xfc,0xff,' +` 0xfe,0xff,0x03,0x00,0x07,0x00,0x0e,0x00,' +` 0x14,0x00,0x1e,0x00,0x25,0x00,0x31,0x00,' +` 0x3b,0x00,0x4a,0x00,0x56,0x00,0x69,0x00,' +` 0x75,0x00,0x8d,0x00,0x94,0x00,0xce,0x00,' +` 0x5e,0x01,0x71,0x01,0x94,0x01,0xa9,0x01,' +` 0xc9,0x01,0xe1,0x01,0x00,0x02,0x19,0x02,' +` 0x37,0x02,0x50,0x02,0x6c,0x02,0x84,0x02,' +` 0x9f,0x02,0xb4,0x02,0xcd,0x02,0xe0,0x02,' +` 0xf6,0x02,0x06,0x03,0x18,0x03,0x24,0x03,' +` 0x2f,0x43,0x3b,0x03,0x45,0x03,0x48,0x03,' +` 0x4b,0x03,0x4a,0x03,0x48,0x03,0x42,0x03,' +` 0x3c,0x03,0x31,0x03,0x26,0x03,0x17,0x03,' +` 0x08,0x03,0xf5,0x02,0xe2,0x02,0xcc,0x02,' +` 0xb6,0x02,0x9d,0x02,0x83,0x02,0x69,0x02,' +` 0x4b,0x02,0x51,0x02,0x41,0x02,0x1b,0x02,' +` 0x00,0x02,0xdd,0x01,0xc1,0x01,0x9f,0x01,' +` 0x83,0x01,0x62,0x01,0x47,0x01,0x29,0x01,' +` 0x10,0x01,0xf3,0x00,0xdc,0x00,0xc2,0x00,' +` 0xae,0x00,0x95,0x00,0x88,0x00,0x62,0x00,' +` 0x3b,0x00,0x36,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3e,0x00,0x75,0x00,0x54,0x00,0xac,0x00,' +` 0x75,0x00,0x09,0x01,0x13,0x01,0x9e,0x01,' +` 0x5c,0x01,0x0f,0x02,0xb0,0x01,0x8d,0x02,' +` 0x0c,0x02,0x15,0x03,0x6d,0x02,0xa8,0x03,' +` 0xd0,0x02,0x43,0x04,0x33,0x03,0xe7,0x04,' +` 0x93,0x03,0x92,0x05,0xaa,0x03,0xd1,0x05,' +` 0xdb,0x03,0x7a,0x06,0x0d,0x04,0x22,0x07,' +` 0x27,0x04,0xcc,0x07,0x21,0x04,0x7f,0x08,' +` 0xf0,0x03,0x46,0x09,0x7f,0x03,0x39,0x0a,' +` 0xa8,0x02,0x92,0x0b,0x0b,0x01,0xf4,0x0d,' +` 0x58,0xfd,0x55,0x14,0x45,0xee,0xdf,0x76,' +` 0xb6,0x31,0x3e,0xf4,0xaa,0x11,0xc7,0xfd,' +` 0x79,0x0c,0x73,0x00,0x1f,0x0a,0x8d,0x01,' +` 0xa2,0x08,0x0a,0x02,0x84,0x07,0x37,0x02,' +` 0x98,0x06,0x38,0x02,0xca,0x05,0x1e,0x02,' +` 0x11,0x05,0xec,0x01,0x63,0x04,0xaa,0x01,' +` 0xcf,0x03,0xde,0x00,0x07,0x02,0x51,0x00,' +` 0xad,0x01,0x2b,0x00,0x55,0x01,0x0e,0x00,' +` 0x08,0x01,0xf7,0xff,0xc7,0x00,0xe7,0xff,' +` 0x92,0x00,0xdc,0xff,0x68,0x00,0xd7,0xff,' +` 0x47,0x00,0xd7,0xff,0x4a,0x00,0xf3,0xff,' +` 0x34,0x00,0xf2,0xff,0x22,0x00,0xe6,0xff,' +` 0x08,0x00,0xeb,0xff,0x04,0x00,0xf2,0xff,' +` 0x02,0x00,0xf8,0xff,0x00,0x00,0xfc,0xff,' +` 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf8,0xff,0xf6,0xff,' +` 0xe7,0xff,0xe7,0xff,0xcb,0xff,0xcd,0xff,' +` 0x9f,0xff,0xa9,0xff,0x61,0xff,0x66,0xff,' +` 0x09,0xff,0x24,0xff,0xa8,0xfe,0xcf,0xfe,' +` 0x15,0xfe,0x59,0xfe,0x8b,0xfd,0xeb,0xfd,' +` 0xf1,0xfc,0x76,0xfd,0x49,0xfc,0xfb,0xfc,' +` 0x96,0xfb,0x7f,0xfc,0xdc,0xfa,0x07,0xfc,' +` 0x1c,0xfa,0x98,0xfb,0x5b,0xf9,0x3b,0xfb,' +` 0x6c,0xf8,0x80,0xfa,0x8a,0xf7,0x46,0xfa,' +` 0xca,0xf6,0x2b,0xfa,0x19,0xf6,0x4c,0xfa,' +` 0x76,0xf5,0xa4,0xfa,0xcc,0xf4,0x44,0xfb,' +` 0x07,0xf4,0x4b,0xfc,0xfc,0xf2,0xfa,0xfd,' +` 0x3f,0xf1,0x0a,0x01,0x7a,0xed,0x74,0x08,' +` 0x48,0xdf,0x40,0x42,0x29,0x53,0x2b,0xde,' +` 0xa0,0x0a,0xf0,0xee,0xd2,0x03,0xf0,0xf3,' +` 0xa1,0x01,0xaa,0xf6,0xc7,0x00,0x8d,0xf8,' +` 0x7b,0x00,0x06,0xfa,0x75,0x00,0x3e,0xfb,' +` 0x91,0x00,0x47,0xfc,0xbb,0x00,0x26,0xfd,' +` 0xe2,0x00,0xe2,0xfd,0x01,0x01,0xa1,0xfe,' +` 0x8c,0x01,0x4c,0xff,0x91,0x01,0xae,0xff,' +` 0x90,0x01,0xf7,0xff,0x86,0x01,0x2b,0x00,' +` 0x71,0x01,0x4c,0x00,0x54,0x01,0x5f,0x00,' +` 0x31,0x01,0x65,0x00,0x0a,0x01,0x62,0x00,' +` 0xf9,0x00,0x77,0x00,0xce,0x00,0x61,0x00,' +` 0xa0,0x00,0x40,0x00,0x63,0x00,0x29,0x00,' +` 0x43,0x00,0x1a,0x00,0x29,0x00,0x0f,0x00,' +` 0x16,0x00,0x07,0x00,0x09,0x00,0x02,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x00,' +` 0x05,0x00,0x0d,0x00,0x0d,0x00,0x1c,0x00,' +` 0x18,0x00,0x31,0x00,0x28,0x00,0x4b,0x00,' +` 0x3b,0x00,0x7b,0x00,0x62,0x00,0xa4,0x00,' +` 0x7b,0x00,0xce,0x00,0x77,0x00,0xd1,0x00,' +` 0x7d,0x00,0xf1,0x00,0x80,0x00,0x0b,0x01,' +` 0x79,0x00,0x1f,0x01,0x65,0x00,0x29,0x01,' +` 0x41,0x00,0x28,0x01,0x0b,0x00,0x1b,0x01,' +` 0xbf,0xff,0x05,0x01,0x36,0xff,0x6c,0x00,' +` 0x8d,0xfe,0x34,0x00,0xf2,0xfd,0xf1,0xff,' +` 0x3b,0xfd,0xa0,0xff,0x63,0xfc,0x51,0xff,' +` 0x6b,0xfb,0x10,0xff,0x49,0xfa,0xf2,0xfe,' +` 0xea,0xf8,0x20,0xff,0x16,0xf7,0x01,0x00,' +` 0x1e,0xf4,0x18,0x03,0x26,0xec,0xf1,0x18,' +` 0x6a,0x70,0x9c,0xe4,0x01,0x04,0xf2,0xf0,' +` 0x2d,0xfe,0x8c,0xf3,0xe6,0xfb,0xa1,0xf4,' +` 0xab,0xfa,0x41,0xf5,0xef,0xf9,0xb8,0xf5,' +` 0x82,0xf9,0x27,0xf6,0x4e,0xf9,0x9c,0xf6,' +` 0x49,0xf9,0x23,0xf7,0x7b,0xf9,0xc3,0xf7,' +` 0xcb,0xf9,0x76,0xf8,0x8c,0xfa,0x73,0xf9,' +` 0x00,0xfb,0x22,0xfa,0x7f,0xfb,0xd4,0xfa,' +` 0x04,0xfc,0x85,0xfb,0x8d,0xfc,0x31,0xfc,' +` 0x15,0xfd,0xd4,0xfc,0x97,0xfd,0x6c,0xfd,' +` 0x11,0xfe,0xf6,0xfd,0x92,0xfe,0x8f,0xfe,' +` 0xf4,0xfe,0xf2,0xfe,0x40,0xff,0x4a,0xff,' +` 0x8f,0xff,0x90,0xff,0xbb,0xff,0xbe,0xff,' +` 0xdb,0xff,0xdf,0xff,0xef,0xff,0xf3,0xff,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,' +` 0xfe,0xff,0xfe,0xff,0xfd,0xff,0xfd,0xff,' +` 0xfd,0xff,0xfd,0xff,0xfc,0xff,0x04,0x00,' +` 0x08,0x00,0x0a,0x00,0x0d,0x00,0x12,0x00,' +` 0x0d,0x00,0x06,0x00,0x0e,0x00,0x10,0x00,' +` 0x18,0x00,0x1c,0x00,0x26,0x00,0x2d,0x00,' +` 0x39,0x00,0x42,0x00,0x51,0x00,0x5b,0x00,' +` 0x6d,0x00,0x78,0x00,0x8f,0x00,0x97,0x00,' +` 0xc8,0x00,0x55,0x01,0x6c,0x01,0x8d,0x01,' +` 0xa6,0x01,0xc6,0x01,0xe1,0x01,0xfe,0x01,' +` 0x18,0x02,0x35,0x02,0x4e,0x02,0x6a,0x02,' +` 0x83,0x02,0x9e,0x02,0xb5,0x02,0xce,0x02,' +` 0xe3,0x02,0xf9,0x02,0x0b,0x03,0x1d,0x03,' +` 0x2b,0x03,0x3a,0x03,0x42,0x43,0x50,0x03,' +` 0x58,0x03,0x5f,0x03,0x62,0x03,0x64,0x03,' +` 0x61,0x03,0x5d,0x03,0x55,0x03,0x4c,0x03,' +` 0x3f,0x03,0x32,0x03,0x21,0x03,0x10,0x03,' +` 0xfb,0x02,0xe6,0x02,0xce,0x02,0xb5,0x02,' +` 0x9b,0x02,0x7e,0x02,0x63,0x02,0x43,0x02,' +` 0x45,0x02,0x36,0x02,0x0f,0x02,0xf3,0x01,' +` 0xcf,0x01,0xb2,0x01,0x8f,0x01,0x73,0x01,' +` 0x52,0x01,0x38,0x01,0x18,0x01,0x00,0x01,' +` 0xe3,0x00,0xce,0x00,0xb2,0x00,0xa2,0x00,' +` 0x7a,0x00,0x4d,0x00,0x45,0x00,0x38,0x00,' +` 0x2e,0x00,0x26,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x24,0x00,0x41,0x00,0x3a,0x00,0x67,0x00,' +` 0x5a,0x00,0x98,0x00,0x81,0x00,0xd5,0x00,' +` 0xaf,0x00,0x38,0x01,0x62,0x01,0xdf,0x01,' +` 0xb9,0x01,0x57,0x02,0x1c,0x02,0xdb,0x02,' +` 0x86,0x02,0x69,0x03,0xf6,0x02,0xfe,0x03,' +` 0x67,0x03,0x96,0x04,0xdc,0x03,0x04,0x05,' +` 0xd9,0x03,0x81,0x05,0x35,0x04,0x16,0x06,' +` 0x80,0x04,0xac,0x06,0xb8,0x04,0x42,0x07,' +` 0xd8,0x04,0xd9,0x07,0xd6,0x04,0x77,0x08,' +` 0xa6,0x04,0x25,0x09,0x2b,0x04,0x05,0x0a,' +` 0x37,0x03,0x70,0x0b,0x2a,0x01,0xb8,0x0e,' +` 0x9c,0xfa,0x12,0x22,0x9f,0x7f,0xc1,0xf3,' +` 0xb1,0x10,0x65,0xff,0x87,0x0b,0xdc,0x01,' +` 0x7b,0x09,0xc7,0x02,0x3b,0x08,0x23,0x03,' +` 0x4b,0x07,0x37,0x03,0x80,0x06,0x23,0x03,' +` 0xc9,0x05,0xf0,0x02,0x1a,0x05,0xac,0x02,' +` 0x79,0x04,0x61,0x02,0xe5,0x03,0x0f,0x02,' +` 0x68,0x03,0x4a,0x01,0xc0,0x01,0xaa,0x00,' +` 0x77,0x01,0x7d,0x00,0x2e,0x01,0x5b,0x00,' +` 0xef,0x00,0x3f,0x00,0xba,0x00,0x29,0x00,' +` 0x8d,0x00,0x19,0x00,0x66,0x00,0x29,0x00,' +` 0x6e,0x00,0x1f,0x00,0x4f,0x00,0x15,0x00,' +` 0x38,0x00,0x0d,0x00,0x26,0x00,0x09,0x00,' +` 0x15,0x00,0xfb,0xff,0x08,0x00,0xfd,0xff,' +` 0x04,0x00,0xfe,0xff,0x02,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf8,0xff,' +` 0xf6,0xff,0xe8,0xff,0xe6,0xff,0xcc,0xff,' +` 0xcb,0xff,0x98,0xff,0x9f,0xff,0x5b,0xff,' +` 0x6a,0xff,0x0e,0xff,0x28,0xff,0xb0,0xfe,' +` 0xda,0xfe,0x42,0xfe,0x69,0xfe,0x99,0xfd,' +` 0xf9,0xfd,0x06,0xfd,0x86,0xfd,0x64,0xfc,' +` 0x0f,0xfd,0xb8,0xfb,0x97,0xfc,0x05,0xfb,' +` 0x23,0xfc,0x4d,0xfa,0xb6,0xfb,0x8c,0xf9,' +` 0x01,0xfb,0x82,0xf8,0xa5,0xfa,0xc3,0xf7,' +` 0x64,0xfa,0x09,0xf7,0x43,0xfa,0x52,0xf6,' +` 0x49,0xfa,0x9e,0xf5,0x8a,0xfa,0xf4,0xf4,' +` 0x1b,0xfb,0x35,0xf4,0x11,0xfc,0x3b,0xf3,' +` 0xa8,0xfd,0x9b,0xf1,0x85,0x00,0x14,0xee,' +` 0x57,0x07,0x32,0xe1,0x45,0x38,0x76,0x5b,' +` 0x21,0xde,0x05,0x0a,0x03,0xef,0x3b,0x03,' +` 0xde,0xf3,0x0b,0x01,0x79,0xf6,0x2d,0x00,' +` 0x44,0xf8,0xdd,0xff,0xaa,0xf9,0xd3,0xff,' +` 0xd2,0xfa,0xe7,0xff,0xc6,0xfb,0x08,0x00,' +` 0x98,0xfc,0x30,0x00,0x4e,0xfd,0x57,0x00,' +` 0xe9,0xfd,0x7d,0x00,0xbf,0xfe,0xec,0x00,' +` 0x26,0xff,0xf5,0x00,0x76,0xff,0xf7,0x00,' +` 0xb4,0xff,0xf0,0x00,0xe2,0xff,0xe3,0x00,' +` 0x00,0x00,0xcf,0x00,0x12,0x00,0xbf,0x00,' +` 0x44,0x00,0xb7,0x00,0x3e,0x00,0x94,0x00,' +` 0x35,0x00,0x72,0x00,0x2a,0x00,0x53,0x00,' +` 0x1f,0x00,0x33,0x00,0x0a,0x00,0x1c,0x00,' +` 0x05,0x00,0x0f,0x00,0x02,0x00,0x06,0x00,' +` 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x06,0x00,' +` 0x02,0x00,0x0e,0x00,0x05,0x00,0x1b,0x00,' +` 0x0a,0x00,0x31,0x00,0x1f,0x00,0x4f,0x00,' +` 0x29,0x00,0x6d,0x00,0x34,0x00,0x8d,0x00,' +` 0x3c,0x00,0xad,0x00,0x41,0x00,0xb0,0x00,' +` 0x10,0x00,0xbe,0x00,0xfd,0xff,0xce,0x00,' +` 0xdd,0xff,0xd8,0x00,0xaf,0xff,0xda,0x00,' +` 0x70,0xff,0xd4,0x00,0x1e,0xff,0xca,0x00,' +` 0x8c,0xfe,0x41,0x00,0xeb,0xfd,0x1d,0x00,' +` 0x4e,0xfd,0xf0,0xff,0x9a,0xfc,0xc1,0xff,' +` 0xcc,0xfb,0x98,0xff,0xdc,0xfa,0x78,0xff,' +` 0xbb,0xf9,0x76,0xff,0x62,0xf8,0xb6,0xff,' +` 0xaa,0xf6,0x7c,0x00,0x2d,0xf4,0x84,0x02,' +` 0x8a,0xef,0x00,0x09,0x04,0xdf,0xb1,0x62,' +` 0x87,0x2e,0x96,0xe3,0xd6,0x05,0xe4,0xee,' +` 0xb3,0xff,0x0d,0xf2,0x17,0xfd,0x85,0xf3,' +` 0xa3,0xfb,0x6a,0xf4,0xc5,0xfa,0x1e,0xf5,' +` 0x45,0xfa,0xc1,0xf5,0x13,0xfa,0x71,0xf6,' +` 0x18,0xfa,0x24,0xf7,0x43,0xfa,0xdb,0xf7,' +` 0x8b,0xfa,0x97,0xf8,0xef,0xfa,0xa5,0xf9,' +` 0xa7,0xfb,0x62,0xfa,0x19,0xfc,0x19,0xfb,' +` 0x91,0xfc,0xca,0xfb,0x0c,0xfd,0x75,0xfc,' +` 0x85,0xfd,0x15,0xfd,0xfa,0xfd,0xa7,0xfd,' +` 0x7d,0xfe,0x4d,0xfe,0xdc,0xfe,0xb8,0xfe,' +` 0x2a,0xff,0x15,0xff,0x6c,0xff,0x61,0xff,' +` 0xa0,0xff,0x9d,0xff,0xce,0xff,0xce,0xff,' +` 0xe7,0xff,0xe9,0xff,0xf7,0xff,0xf9,0xff,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x02,0x00,0x07,0x00,0x0b,0x00,' +` 0x0d,0x00,0x11,0x00,0x14,0x00,0x18,0x00,' +` 0x1c,0x00,0x22,0x00,0x27,0x00,0x30,0x00,' +` 0x24,0x00,0x28,0x00,0x30,0x00,0x38,0x00,' +` 0x40,0x00,0x4b,0x00,0x54,0x00,0x62,0x00,' +` 0x6b,0x00,0x7d,0x00,0x86,0x00,0x9e,0x00,' +` 0xa1,0x00,0x14,0x01,0x65,0x01,0x6f,0x01,' +` 0x95,0x01,0xa9,0x01,0xcc,0x01,0xe4,0x01,' +` 0x06,0x02,0x1f,0x02,0x40,0x02,0x59,0x02,' +` 0x77,0x02,0x8e,0x02,0xa9,0x02,0xbf,0x02,' +` 0xd8,0x02,0xeb,0x02,0x02,0x03,0x13,0x03,' +` 0x26,0x03,0x35,0x03,0x45,0x03,0x50,0x03,' +` 0x5a,0x43,0x64,0x03,0x6e,0x03,0x72,0x03,' +` 0x77,0x03,0x76,0x03,0x76,0x03,0x72,0x03,' +` 0x6d,0x03,0x64,0x03,0x5b,0x03,0x4b,0x03,' +` 0x3c,0x03,0x29,0x03,0x15,0x03,0xfe,0x02,' +` 0xe7,0x02,0xcd,0x02,0xb2,0x02,0x96,0x02,' +` 0x79,0x02,0x5c,0x02,0x3c,0x02,0x22,0x02,' +` 0x29,0x02,0x05,0x02,0xe6,0x01,0xc3,0x01,' +` 0xa4,0x01,0x82,0x01,0x64,0x01,0x44,0x01,' +` 0x28,0x01,0x09,0x01,0xf0,0x00,0xd5,0x00,' +` 0xbe,0x00,0x7e,0x00,0x65,0x00,0x58,0x00,' +` 0x4a,0x00,0x3e,0x00,0x33,0x00,0x2a,0x00,' +` 0x21,0x00,0x1a,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x17,0x00,0x14,0x00,0x2d,0x00,0x25,0x00,' +` 0x4c,0x00,0x3e,0x00,0x76,0x00,0x5e,0x00,' +` 0xab,0x00,0x86,0x00,0xee,0x00,0xb6,0x00,' +` 0x3e,0x01,0xea,0x00,0xc5,0x01,0xbf,0x01,' +` 0x7e,0x02,0x19,0x02,0x09,0x03,0x7e,0x02,' +` 0x9d,0x03,0xe7,0x02,0x36,0x04,0x58,0x03,' +` 0xb2,0x04,0x56,0x03,0x37,0x05,0xb1,0x03,' +` 0xd8,0x05,0xfd,0x03,0x7d,0x06,0x37,0x04,' +` 0x23,0x07,0x5b,0x04,0xca,0x07,0x5c,0x04,' +` 0x75,0x08,0x36,0x04,0x31,0x09,0xd8,0x03,' +` 0x13,0x0a,0x20,0x03,0x47,0x0b,0xc6,0x01,' +` 0x4e,0x0d,0xde,0xfe,0x19,0x12,0x3e,0xf5,' +` 0xfa,0x30,0xcb,0x77,0x96,0xee,0x27,0x14,' +` 0x35,0xfd,0x91,0x0d,0x94,0x00,0xf7,0x0a,' +` 0xf1,0x01,0x6e,0x09,0x94,0x02,0x4e,0x08,' +` 0xd2,0x02,0x5e,0x07,0xdc,0x02,0x8e,0x06,' +` 0xc7,0x02,0xd1,0x05,0x9d,0x02,0x23,0x05,' +` 0x67,0x02,0x84,0x04,0x2a,0x02,0xf2,0x03,' +` 0xe7,0x01,0x74,0x03,0x1c,0x01,0xee,0x01,' +` 0xab,0x00,0xa3,0x01,0x88,0x00,0x59,0x01,' +` 0x6c,0x00,0x18,0x01,0x55,0x00,0xda,0x00,' +` 0x61,0x00,0xda,0x00,0x51,0x00,0xa9,0x00,' +` 0x3e,0x00,0x80,0x00,0x2e,0x00,0x5e,0x00,' +` 0x21,0x00,0x42,0x00,0x16,0x00,0x2b,0x00,' +` 0x0d,0x00,0x1a,0x00,0x07,0x00,0x0c,0x00,' +` 0x00,0x00,0x04,0x00,0x00,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff,' +` 0xf9,0xff,0xf6,0xff,0xe6,0xff,0xe5,0xff,' +` 0xc9,0xff,0xcb,0xff,0x9e,0xff,0xa7,0xff,' +` 0x65,0xff,0x77,0xff,0x1d,0xff,0x3c,0xff,' +` 0xc4,0xfe,0xf6,0xfe,0x5d,0xfe,0xa6,0xfe,' +` 0xe8,0xfd,0x29,0xfe,0x35,0xfd,0xc1,0xfd,' +` 0x9f,0xfc,0x55,0xfd,0xfd,0xfb,0xe9,0xfc,' +` 0x54,0xfb,0x81,0xfc,0xa0,0xfa,0xd2,0xfb,' +` 0xa4,0xf9,0x70,0xfb,0xe9,0xf8,0x20,0xfb,' +` 0x30,0xf8,0xe7,0xfa,0x77,0xf7,0xc9,0xfa,' +` 0xbf,0xf6,0xd4,0xfa,0x0a,0xf6,0x10,0xfb,' +` 0x48,0xf5,0x8d,0xfb,0x68,0xf4,0x73,0xfc,' +` 0x52,0xf3,0x02,0xfe,0x8e,0xf1,0xe0,0x00,' +` 0xcb,0xed,0xdf,0x07,0x28,0xe0,0xa9,0x3c,' +` 0x96,0x57,0xc1,0xdd,0x04,0x0a,0x86,0xee,' +` 0x10,0x03,0x56,0xf3,0xbc,0x00,0xe1,0xf5,' +` 0xc0,0xff,0x99,0xf7,0x4e,0xff,0xe3,0xf8,' +` 0x22,0xff,0xf2,0xf9,0x1f,0xff,0xdb,0xfa,' +` 0x33,0xff,0xa7,0xfb,0x54,0xff,0x5b,0xfc,' +` 0x7a,0xff,0xfa,0xfc,0xa2,0xff,0x84,0xfd,' +` 0xcc,0xff,0x57,0xfe,0x2c,0x00,0xad,0xfe,' +` 0x3c,0x00,0xfa,0xfe,0x45,0x00,0x38,0xff,' +` 0x4a,0x00,0x69,0xff,0x53,0x00,0xc1,0xff,' +` 0x67,0x00,0xd6,0xff,0x58,0x00,0xe5,0xff,' +` 0x48,0x00,0xef,0xff,0x38,0x00,0xf5,0xff,' +` 0x29,0x00,0xfa,0xff,0x1c,0x00,0xfd,0xff,' +` 0x12,0x00,0xfe,0xff,0x07,0x00,0xfc,0xff,' +` 0x02,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0x02,0x00,0xfc,0xff,' +` 0x06,0x00,0xfe,0xff,0x0f,0x00,0xfc,0xff,' +` 0x18,0x00,0xf8,0xff,0x23,0x00,0xf3,0xff,' +` 0x30,0x00,0xec,0xff,0x3d,0x00,0xe1,0xff,' +` 0x4a,0x00,0xd1,0xff,0x55,0x00,0xbb,0xff,' +` 0x3a,0x00,0x64,0xff,0x30,0x00,0x32,0xff,' +` 0x27,0x00,0xf2,0xfe,0x19,0x00,0xa2,0xfe,' +` 0x0a,0x00,0x13,0xfe,0x83,0xff,0x88,0xfd,' +` 0x60,0xff,0xfb,0xfc,0x33,0xff,0x5d,0xfc,' +` 0x05,0xff,0xad,0xfb,0xdc,0xfe,0xe6,0xfa,' +` 0xbe,0xfe,0x05,0xfa,0xb6,0xfe,0x00,0xf9,' +` 0xd3,0xfe,0xc4,0xf7,0x2d,0xff,0x21,0xf6,' +` 0x0e,0x00,0xbb,0xf3,0x32,0x02,0x2e,0xef,' +` 0xce,0x08,0xb9,0xde,0x20,0x62,0xfe,0x2e,' +` 0x60,0xe3,0xed,0x05,0xe0,0xee,0xd8,0xff,' +` 0x27,0xf2,0x4e,0xfd,0xb8,0xf3,0xec,0xfb,' +` 0xb4,0xf4,0x27,0xfb,0x85,0xf5,0xc0,0xfa,' +` 0x3c,0xf6,0x93,0xfa,0xea,0xf6,0x97,0xfa,' +` 0x9e,0xf7,0xc0,0xfa,0x53,0xf8,0x03,0xfb,' +` 0x09,0xf9,0x5b,0xfb,0xc1,0xf9,0xc7,0xfb,' +` 0xc0,0xfa,0x77,0xfc,0x6f,0xfb,0xe4,0xfc,' +` 0x16,0xfc,0x54,0xfd,0xb5,0xfc,0xc2,0xfd,' +` 0x48,0xfd,0x4c,0xfe,0xfa,0xfd,0xa8,0xfe,' +` 0x6c,0xfe,0xf9,0xfe,0xd1,0xfe,0x3f,0xff,' +` 0x26,0xff,0x7a,0xff,0x6c,0xff,0xa9,0xff,' +` 0xa3,0xff,0xcd,0xff,0xcc,0xff,0xe6,0xff,' +` 0xe8,0xff,0xf8,0xff,0xf9,0xff,0xfe,0xff,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x05,0x00,' +` 0x08,0x00,0x0a,0x00,0x0d,0x00,0x10,0x00,' +` 0x15,0x00,0x19,0x00,0x1f,0x00,0x24,0x00,' +` 0x2b,0x00,0x31,0x00,0x39,0x00,0x40,0x00,' +` 0x4a,0x00,0x51,0x00,0x60,0x00,0x54,0x00,' +` 0x5a,0x00,0x65,0x00,0x71,0x00,0x7c,0x00,' +` 0x8c,0x00,0x95,0x00,0xab,0x00,0xae,0x00,' +` 0x13,0x01,0x62,0x01,0x6b,0x01,0x8e,0x01,' +` 0xa1,0x01,0xc2,0x01,0xd8,0x01,0xf8,0x01,' +` 0x10,0x02,0x30,0x02,0x48,0x02,0x66,0x02,' +` 0x7e,0x02,0x9c,0x02,0xb3,0x02,0xcf,0x02,' +` 0xe4,0x02,0xfb,0x02,0x0d,0x03,0x21,0x03,' +` 0x30,0x03,0x41,0x03,0x4d,0x03,0x5b,0x03,' +` 0x64,0x03,0x6a,0x43,0x73,0x03,0x7a,0x03,' +` 0x7b,0x03,0x7e,0x03,0x7c,0x03,0x7a,0x03,' +` 0x74,0x03,0x6f,0x03,0x64,0x03,0x5b,0x03,' +` 0x4c,0x03,0x3e,0x03,0x2b,0x03,0x19,0x03,' +` 0x04,0x03,0xee,0x02,0xd3,0x02,0xba,0x02,' +` 0x9d,0x02,0x81,0x02,0x62,0x02,0x44,0x02,' +` 0x25,0x02,0x06,0x02,0xe6,0x01,0xed,0x01,' +` 0xca,0x01,0xac,0x01,0x89,0x01,0x6c,0x01,' +` 0x4b,0x01,0x30,0x01,0x11,0x01,0xf8,0x00,' +` 0xac,0x00,0x8d,0x00,0x7e,0x00,0x6c,0x00,' +` 0x5e,0x00,0x4f,0x00,0x43,0x00,0x38,0x00,' +` 0x2e,0x00,0x25,0x00,0x1d,0x00,0x16,0x00,' +` 0x11,0x00,0x0c,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x0a,0x00,0x09,0x00,0x1a,0x00,' +` 0x14,0x00,0x31,0x00,0x25,0x00,0x53,0x00,' +` 0x3d,0x00,0x7f,0x00,0x5c,0x00,0xb6,0x00,' +` 0x81,0x00,0xf9,0x00,0xae,0x00,0x48,0x01,' +` 0xe0,0x00,0xa4,0x01,0x14,0x01,0x29,0x02,' +` 0xf6,0x01,0x13,0x03,0x4e,0x02,0xa8,0x03,' +` 0xb0,0x02,0x04,0x04,0xb9,0x02,0x9d,0x04,' +` 0x08,0x03,0x40,0x05,0x4c,0x03,0xe3,0x05,' +` 0x81,0x03,0x8c,0x06,0xa6,0x03,0x3c,0x07,' +` 0xb4,0x03,0xf6,0x07,0xa4,0x03,0xbf,0x08,' +` 0x67,0x03,0xa6,0x09,0xea,0x02,0xc2,0x0a,' +` 0x01,0x02,0x52,0x0c,0x4a,0x00,0xfc,0x0e,' +` 0x88,0xfc,0x6b,0x15,0x5d,0xef,0x2e,0x45,' +` 0x89,0x69,0x49,0xeb,0xc5,0x16,0x79,0xfb,' +` 0x43,0x0f,0x89,0xff,0x3f,0x0c,0x40,0x01,' +` 0x79,0x0a,0x1a,0x02,0x37,0x09,0x8a,0x02,' +` 0x39,0x08,0xbc,0x02,0x5e,0x07,0xc7,0x02,' +` 0x9c,0x06,0xb9,0x02,0xea,0x05,0x98,0x02,' +` 0x43,0x05,0x6b,0x02,0xa8,0x04,0x34,0x02,' +` 0x17,0x04,0xf5,0x01,0x99,0x03,0x60,0x01,' +` 0x28,0x02,0xd1,0x00,0xd9,0x01,0xaa,0x00,' +` 0x8a,0x01,0xc7,0x00,0x6b,0x01,0xa1,0x00,' +` 0x26,0x01,0x80,0x00,0xe6,0x00,0x62,0x00,' +` 0xaf,0x00,0x48,0x00,0x80,0x00,0x33,0x00,' +` 0x5a,0x00,0x22,0x00,0x3b,0x00,0x15,0x00,' +` 0x24,0x00,0x0c,0x00,0x13,0x00,0x05,0x00,' +` 0x08,0x00,0x02,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfd,0xff,' +` 0xfb,0xff,0xf4,0xff,0xf0,0xff,0xe2,0xff,' +` 0xde,0xff,0xc6,0xff,0xc4,0xff,0x9f,0xff,' +` 0xa0,0xff,0x6c,0xff,0x72,0xff,0x2d,0xff,' +` 0x3b,0xff,0xe1,0xfe,0xf9,0xfe,0x89,0xfe,' +` 0xb0,0xfe,0x26,0xfe,0x5f,0xfe,0xb7,0xfd,' +` 0xd0,0xfd,0x0b,0xfd,0x73,0xfd,0x83,0xfc,' +` 0x10,0xfd,0xc6,0xfb,0x57,0xfc,0x1e,0xfb,' +` 0xf0,0xfb,0x82,0xfa,0x8f,0xfb,0xeb,0xf9,' +` 0x3e,0xfb,0x58,0xf9,0xfc,0xfa,0xc9,0xf8,' +` 0xcf,0xfa,0x3b,0xf8,0xba,0xfa,0xad,0xf7,' +` 0xc6,0xfa,0x19,0xf7,0xfd,0xfa,0x71,0xf6,' +` 0x73,0xfb,0x98,0xf5,0x58,0xfc,0x45,0xf4,' +` 0x3a,0xfe,0x86,0xf1,0x88,0x03,0x63,0xe5,' +` 0x2f,0x71,0x76,0x16,0x66,0xec,0xe5,0x01,' +` 0x9a,0xf3,0xb6,0xfe,0x1a,0xf6,0x93,0xfd,' +` 0x88,0xf7,0x1f,0xfd,0x90,0xf8,0xfd,0xfc,' +` 0x69,0xf9,0x08,0xfd,0x26,0xfa,0x2b,0xfd,' +` 0xd1,0xfa,0x5e,0xfd,0x6d,0xfb,0x99,0xfd,' +` 0xfc,0xfb,0xd8,0xfd,0x81,0xfc,0x19,0xfe,' +` 0xfc,0xfc,0x5a,0xfe,0x69,0xfd,0xa5,0xfe,' +` 0x28,0xfe,0x08,0xff,0x6f,0xfe,0x36,0xff,' +` 0xb8,0xfe,0x8a,0xff,0x25,0xff,0xa6,0xff,' +` 0x52,0xff,0xbb,0xff,0x7a,0xff,0xce,0xff,' +` 0x9d,0xff,0xdd,0xff,0xb9,0xff,0xe8,0xff,' +` 0xcf,0xff,0xf1,0xff,0xe0,0xff,0xf7,0xff,' +` 0xed,0xff,0xfb,0xff,0xf6,0xff,0xfe,0xff,' +` 0xfc,0xff,0xff,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xff,0xff,0xfb,0xff,0xfe,0xff,0xf3,0xff,' +` 0xfc,0xff,0xe7,0xff,0xf9,0xff,0xd7,0xff,' +` 0xf3,0xff,0xc2,0xff,0xec,0xff,0xa6,0xff,' +` 0xe2,0xff,0x84,0xff,0xd6,0xff,0x5b,0xff,' +` 0xc6,0xff,0x2b,0xff,0xb5,0xff,0xf5,0xfe,' +` 0x99,0xff,0x77,0xfe,0x54,0xff,0x22,0xfe,' +` 0x35,0xff,0x95,0xfd,0xaf,0xfe,0x15,0xfd,' +` 0x83,0xfe,0x91,0xfc,0x51,0xfe,0x03,0xfc,' +` 0x20,0xfe,0x6a,0xfb,0xf4,0xfd,0xc1,0xfa,' +` 0xd1,0xfd,0x08,0xfa,0xbd,0xfd,0x3a,0xf9,' +` 0xc1,0xfd,0x4f,0xf8,0xec,0xfd,0x37,0xf7,' +` 0x5c,0xfe,0xd0,0xf5,0x4a,0xff,0xc2,0xf3,' +` 0x4f,0x01,0xe4,0xef,0xcf,0x06,0xb8,0xe3,' +` 0x79,0x2f,0xce,0x61,0x41,0xde,0x00,0x08,' +` 0x19,0xee,0xc0,0x00,0x13,0xf2,0x17,0xfe,' +` 0x01,0xf4,0xc3,0xfc,0x38,0xf5,0x07,0xfc,' +` 0x20,0xf6,0x9f,0xfb,0xe4,0xf6,0x71,0xfb,' +` 0x97,0xf7,0x6b,0xfb,0x42,0xf8,0x83,0xfb,' +` 0xeb,0xf8,0xb3,0xfb,0x92,0xf9,0xf6,0xfb,' +` 0x3b,0xfa,0x4a,0xfc,0xe7,0xfa,0xa5,0xfc,' +` 0xa4,0xfb,0x58,0xfd,0x60,0xfc,0xb1,0xfd,' +` 0xee,0xfc,0x39,0xfe,0xaa,0xfd,0x88,0xfe,' +` 0x1a,0xfe,0xd2,0xfe,0x81,0xfe,0x16,0xff,' +` 0xdc,0xfe,0x51,0xff,0x2a,0xff,0x84,0xff,' +` 0x6b,0xff,0xad,0xff,0x9e,0xff,0xcc,0xff,' +` 0xc6,0xff,0xe4,0xff,0xe2,0xff,0xf3,0xff,' +` 0xf4,0xff,0xfc,0xff,0xfd,0xff,0x00,0x00,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x05,0x00,0x08,0x00,' +` 0x0b,0x00,0x0e,0x00,0x13,0x00,0x18,0x00,' +` 0x1e,0x00,0x24,0x00,0x2b,0x00,0x33,0x00,' +` 0x3c,0x00,0x45,0x00,0x51,0x00,0x5b,0x00,' +` 0x68,0x00,0x73,0x00,0x83,0x00,0x8d,0x00,' +` 0xa3,0x00,0xa1,0x00,0x9d,0x00,0xb2,0x00,' +` 0xbd,0x00,0xd4,0x00,0x40,0x01,0x6a,0x01,' +` 0x7c,0x01,0x9a,0x01,0xb0,0x01,0xcd,0x01,' +` 0xe3,0x01,0x00,0x02,0x17,0x02,0x33,0x02,' +` 0x4b,0x02,0x66,0x02,0x7d,0x02,0x97,0x02,' +` 0xad,0x02,0xc6,0x02,0xda,0x02,0xf1,0x02,' +` 0x04,0x03,0x19,0x03,0x2b,0x03,0x3d,0x03,' +` 0x4b,0x03,0x59,0x03,0x61,0x03,0x6b,0x03,' +` 0x70,0x03,0x72,0x43,0x77,0x03,0x7a,0x03,' +` 0x79,0x03,0x78,0x03,0x72,0x03,0x6d,0x03,' +` 0x64,0x03,0x5b,0x03,0x4e,0x03,0x41,0x03,' +` 0x30,0x03,0x1f,0x03,0x0b,0x03,0xf7,0x02,' +` 0xe1,0x02,0xca,0x02,0xb1,0x02,0x99,0x02,' +` 0x7e,0x02,0x64,0x02,0x48,0x02,0x2d,0x02,' +` 0x0f,0x02,0xf3,0x01,0xd3,0x01,0xb8,0x01,' +` 0x92,0x01,0x91,0x01,0x82,0x01,0x5d,0x01,' +` 0x47,0x01,0x19,0x01,0xc7,0x00,0xb3,0x00,' +` 0x9f,0x00,0x8e,0x00,0x7d,0x00,0x6d,0x00,' +` 0x5e,0x00,0x51,0x00,0x44,0x00,0x39,0x00,' +` 0x2f,0x00,0x26,0x00,0x1e,0x00,0x17,0x00,' +` 0x12,0x00,0x0d,0x00,0x09,0x00,0x06,0x00,' +` 0x04,0x00,0x02,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x03,0x00,0x07,0x00,0x08,0x00,0x0f,0x00,' +` 0x0f,0x00,0x1a,0x00,0x1a,0x00,0x29,0x00,' +` 0x27,0x00,0x3c,0x00,0x39,0x00,0x53,0x00,' +` 0x4d,0x00,0x6f,0x00,0x66,0x00,0x8f,0x00,' +` 0x81,0x00,0xb4,0x00,0xa0,0x00,0xdc,0x00,' +` 0xc3,0x00,0x06,0x01,0x14,0x01,0x81,0x01,' +` 0x4b,0x01,0xb8,0x01,0x79,0x01,0xf4,0x01,' +` 0xa6,0x01,0x33,0x02,0xd1,0x01,0x72,0x02,' +` 0xfa,0x01,0xb3,0x02,0x1f,0x02,0xf4,0x02,' +` 0x3e,0x02,0x35,0x03,0x56,0x02,0x79,0x03,' +` 0x62,0x02,0xc0,0x03,0x60,0x02,0x0f,0x04,' +` 0x46,0x02,0x71,0x04,0x02,0x02,0x04,0x05,' +` 0x5b,0x01,0x3d,0x06,0x2a,0xff,0xba,0x0c,' +` 0xb6,0x41,0x58,0xfc,0x34,0x07,0xde,0x00,' +` 0x4d,0x05,0xd0,0x01,0x91,0x04,0x2b,0x02,' +` 0x1f,0x04,0x4e,0x02,0xc8,0x03,0x55,0x02,' +` 0x7c,0x03,0x4b,0x02,0x36,0x03,0x35,0x02,' +` 0xf2,0x02,0x17,0x02,0xb0,0x02,0xf3,0x01,' +` 0x6e,0x02,0xcb,0x01,0x2e,0x02,0xa0,0x01,' +` 0xef,0x01,0x74,0x01,0xb2,0x01,0x48,0x01,' +` 0x77,0x01,0x1b,0x01,0x09,0x01,0xba,0x00,' +` 0xda,0x00,0x9a,0x00,0xb1,0x00,0x7c,0x00,' +` 0x8d,0x00,0x61,0x00,0x6d,0x00,0x4a,0x00,' +` 0x51,0x00,0x36,0x00,0x3a,0x00,0x25,0x00,' +` 0x27,0x00,0x18,0x00,0x19,0x00,0x0e,0x00,' +` 0x0e,0x00,0x07,0x00,0x07,0x00,0x03,0x00,' +` 0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfc,0xff,0xf9,0xff,0xf4,0xff,' +` 0xee,0xff,0xe6,0xff,0xdd,0xff,0xd2,0xff,' +` 0xc6,0xff,0xb8,0xff,0xa7,0xff,0x95,0xff,' +` 0x81,0xff,0x6b,0xff,0x52,0xff,0x39,0xff,' +` 0x1c,0xff,0x00,0xff,0xdd,0xfe,0xbf,0xfe,' +` 0x96,0xfe,0x77,0xfe,0x47,0xfe,0x30,0xfe,' +` 0xab,0xfd,0x3f,0xfd,0x24,0xfd,0xe1,0xfc,' +` 0xb7,0xfc,0x79,0xfc,0x4c,0xfc,0x10,0xfc,' +` 0xe1,0xfb,0xa6,0xfb,0x78,0xfb,0x3f,0xfb,' +` 0x12,0xfb,0xdc,0xfa,0xb1,0xfa,0x7f,0xfa,' +` 0x57,0xfa,0x29,0xfa,0x05,0xfa,0xdc,0xf9,' +` 0xbd,0xf9,0x99,0xf9,0x80,0xf9,0x62,0xf9,' +` 0x4f,0xf9,0x38,0xf9,0x2b,0xf9,0x1b,0xf9,' +` 0x15,0xf9,0x0c,0xf9,0x08,0x79,0x12,0xf9,' +` 0x1f,0xf9,0x29,0xf9,0x3d,0xf9,0x4e,0xf9,' +` 0x69,0xf9,0x80,0xf9,0xa1,0xf9,0xbe,0xf9,' +` 0xe4,0xf9,0x07,0xfa,0x32,0xfa,0x5a,0xfa,' +` 0x89,0xfa,0xb4,0xfa,0xe7,0xfa,0x15,0xfb,' +` 0x4b,0xfb,0x7b,0xfb,0xb3,0xfb,0xe4,0xfb,' +` 0x1d,0xfc,0x4f,0xfc,0x88,0xfc,0xb8,0xfc,' +` 0xf2,0xfc,0x20,0xfd,0x5a,0xfd,0x81,0xfd,' +` 0x1b,0xfe,0x5a,0xfe,0x77,0xfe,0xa2,0xfe,' +` 0xc1,0xfe,0xe5,0xfe,0x03,0xff,0x22,0xff,' +` 0x3d,0xff,0x58,0xff,0x6f,0xff,0x85,0xff,' +` 0x98,0xff,0xaa,0xff,0xba,0xff,0xc8,0xff,' +` 0xd4,0xff,0xdf,0xff,0xe7,0xff,0xef,0xff,' +` 0xf4,0xff,0xf9,0xff,0xfc,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfc,0xff,' +` 0xf9,0xff,0xf4,0xff,0xee,0xff,0xe6,0xff,' +` 0xdd,0xff,0xd2,0xff,0xc6,0xff,0xb8,0xff,' +` 0xa7,0xff,0x95,0xff,0x81,0xff,0x6b,0xff,' +` 0x52,0xff,0x39,0xff,0x1c,0xff,0x00,0xff,' +` 0xdd,0xfe,0xbf,0xfe,0x96,0xfe,0x77,0xfe,' +` 0x47,0xfe,0x30,0xfe,0xab,0xfd,0x3f,0xfd,' +` 0x24,0xfd,0xe1,0xfc,0xb7,0xfc,0x79,0xfc,' +` 0x4c,0xfc,0x10,0xfc,0xe1,0xfb,0xa6,0xfb,' +` 0x78,0xfb,0x3f,0xfb,0x12,0xfb,0xdc,0xfa,' +` 0xb1,0xfa,0x7f,0xfa,0x57,0xfa,0x29,0xfa,' +` 0x05,0xfa,0xdc,0xf9,0xbd,0xf9,0x99,0xf9,' +` 0x80,0xf9,0x62,0xf9,0x4f,0xf9,0x38,0xf9,' +` 0x2b,0xf9,0x1b,0xf9,0x15,0xf9,0x0c,0xf9,' +` 0x08,0x79,0x12,0xf9,0x1f,0xf9,0x29,0xf9,' +` 0x3d,0xf9,0x4e,0xf9,0x69,0xf9,0x80,0xf9,' +` 0xa1,0xf9,0xbe,0xf9,0xe4,0xf9,0x07,0xfa,' +` 0x32,0xfa,0x5a,0xfa,0x89,0xfa,0xb4,0xfa,' +` 0xe7,0xfa,0x15,0xfb,0x4b,0xfb,0x7b,0xfb,' +` 0xb3,0xfb,0xe4,0xfb,0x1d,0xfc,0x4f,0xfc,' +` 0x88,0xfc,0xb8,0xfc,0xf2,0xfc,0x20,0xfd,' +` 0x5a,0xfd,0x81,0xfd,0x1b,0xfe,0x5a,0xfe,' +` 0x77,0xfe,0xa2,0xfe,0xc1,0xfe,0xe5,0xfe,' +` 0x03,0xff,0x22,0xff,0x3d,0xff,0x58,0xff,' +` 0x6f,0xff,0x85,0xff,0x98,0xff,0xaa,0xff,' +` 0xba,0xff,0xc8,0xff,0xd4,0xff,0xdf,0xff,' +` 0xe7,0xff,0xef,0xff,0xf4,0xff,0xf9,0xff,' +` 0xfc,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0x03,0x00,0x07,0x00,' +` 0x08,0x00,0x0f,0x00,0x0f,0x00,0x1a,0x00,' +` 0x1a,0x00,0x29,0x00,0x27,0x00,0x3c,0x00,' +` 0x39,0x00,0x53,0x00,0x4d,0x00,0x6f,0x00,' +` 0x66,0x00,0x8f,0x00,0x81,0x00,0xb4,0x00,' +` 0xa0,0x00,0xdc,0x00,0xc3,0x00,0x06,0x01,' +` 0x14,0x01,0x81,0x01,0x4b,0x01,0xb8,0x01,' +` 0x79,0x01,0xf4,0x01,0xa6,0x01,0x33,0x02,' +` 0xd1,0x01,0x72,0x02,0xfa,0x01,0xb3,0x02,' +` 0x1f,0x02,0xf4,0x02,0x3e,0x02,0x35,0x03,' +` 0x56,0x02,0x79,0x03,0x62,0x02,0xc0,0x03,' +` 0x60,0x02,0x0f,0x04,0x46,0x02,0x71,0x04,' +` 0x02,0x02,0x04,0x05,0x5b,0x01,0x3d,0x06,' +` 0x2a,0xff,0xba,0x0c,0xb6,0x41,0x58,0xfc,' +` 0x34,0x07,0xde,0x00,0x4d,0x05,0xd0,0x01,' +` 0x91,0x04,0x2b,0x02,0x1f,0x04,0x4e,0x02,' +` 0xc8,0x03,0x55,0x02,0x7c,0x03,0x4b,0x02,' +` 0x36,0x03,0x35,0x02,0xf2,0x02,0x17,0x02,' +` 0xb0,0x02,0xf3,0x01,0x6e,0x02,0xcb,0x01,' +` 0x2e,0x02,0xa0,0x01,0xef,0x01,0x74,0x01,' +` 0xb2,0x01,0x48,0x01,0x77,0x01,0x1b,0x01,' +` 0x09,0x01,0xba,0x00,0xda,0x00,0x9a,0x00,' +` 0xb1,0x00,0x7c,0x00,0x8d,0x00,0x61,0x00,' +` 0x6d,0x00,0x4a,0x00,0x51,0x00,0x36,0x00,' +` 0x3a,0x00,0x25,0x00,0x27,0x00,0x18,0x00,' +` 0x19,0x00,0x0e,0x00,0x0e,0x00,0x07,0x00,' +` 0x07,0x00,0x03,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,' +` 0x05,0x00,0x08,0x00,0x0b,0x00,0x0e,0x00,' +` 0x13,0x00,0x18,0x00,0x1e,0x00,0x24,0x00,' +` 0x2b,0x00,0x33,0x00,0x3c,0x00,0x45,0x00,' +` 0x51,0x00,0x5b,0x00,0x68,0x00,0x73,0x00,' +` 0x83,0x00,0x8d,0x00,0xa3,0x00,0xa1,0x00,' +` 0x9d,0x00,0xb2,0x00,0xbd,0x00,0xd4,0x00,' +` 0x40,0x01,0x6a,0x01,0x7c,0x01,0x9a,0x01,' +` 0xb0,0x01,0xcd,0x01,0xe3,0x01,0x00,0x02,' +` 0x17,0x02,0x33,0x02,0x4b,0x02,0x66,0x02,' +` 0x7d,0x02,0x97,0x02,0xad,0x02,0xc6,0x02,' +` 0xda,0x02,0xf1,0x02,0x04,0x03,0x19,0x03,' +` 0x2b,0x03,0x3d,0x03,0x4b,0x03,0x59,0x03,' +` 0x61,0x03,0x6b,0x03,0x70,0x03,0x72,0x43,' +` 0x77,0x03,0x7a,0x03,0x79,0x03,0x78,0x03,' +` 0x72,0x03,0x6d,0x03,0x64,0x03,0x5b,0x03,' +` 0x4e,0x03,0x41,0x03,0x30,0x03,0x1f,0x03,' +` 0x0b,0x03,0xf7,0x02,0xe1,0x02,0xca,0x02,' +` 0xb1,0x02,0x99,0x02,0x7e,0x02,0x64,0x02,' +` 0x48,0x02,0x2d,0x02,0x0f,0x02,0xf3,0x01,' +` 0xd3,0x01,0xb8,0x01,0x92,0x01,0x91,0x01,' +` 0x82,0x01,0x5d,0x01,0x47,0x01,0x19,0x01,' +` 0xc7,0x00,0xb3,0x00,0x9f,0x00,0x8e,0x00,' +` 0x7d,0x00,0x6d,0x00,0x5e,0x00,0x51,0x00,' +` 0x44,0x00,0x39,0x00,0x2f,0x00,0x26,0x00,' +` 0x1e,0x00,0x17,0x00,0x12,0x00,0x0d,0x00,' +` 0x09,0x00,0x06,0x00,0x04,0x00,0x02,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xff,0xff,0xfb,0xff,' +` 0xfe,0xff,0xf3,0xff,0xfc,0xff,0xe7,0xff,' +` 0xf9,0xff,0xd7,0xff,0xf3,0xff,0xc2,0xff,' +` 0xec,0xff,0xa6,0xff,0xe2,0xff,0x84,0xff,' +` 0xd6,0xff,0x5b,0xff,0xc6,0xff,0x2b,0xff,' +` 0xb5,0xff,0xf5,0xfe,0x99,0xff,0x77,0xfe,' +` 0x54,0xff,0x22,0xfe,0x35,0xff,0x95,0xfd,' +` 0xaf,0xfe,0x15,0xfd,0x83,0xfe,0x91,0xfc,' +` 0x51,0xfe,0x03,0xfc,0x20,0xfe,0x6a,0xfb,' +` 0xf4,0xfd,0xc1,0xfa,0xd1,0xfd,0x08,0xfa,' +` 0xbd,0xfd,0x3a,0xf9,0xc1,0xfd,0x4f,0xf8,' +` 0xec,0xfd,0x37,0xf7,0x5c,0xfe,0xd0,0xf5,' +` 0x4a,0xff,0xc2,0xf3,0x4f,0x01,0xe4,0xef,' +` 0xcf,0x06,0xb8,0xe3,0x79,0x2f,0xce,0x61,' +` 0x41,0xde,0x00,0x08,0x19,0xee,0xc0,0x00,' +` 0x13,0xf2,0x17,0xfe,0x01,0xf4,0xc3,0xfc,' +` 0x38,0xf5,0x07,0xfc,0x20,0xf6,0x9f,0xfb,' +` 0xe4,0xf6,0x71,0xfb,0x97,0xf7,0x6b,0xfb,' +` 0x42,0xf8,0x83,0xfb,0xeb,0xf8,0xb3,0xfb,' +` 0x92,0xf9,0xf6,0xfb,0x3b,0xfa,0x4a,0xfc,' +` 0xe7,0xfa,0xa5,0xfc,0xa4,0xfb,0x58,0xfd,' +` 0x60,0xfc,0xb1,0xfd,0xee,0xfc,0x39,0xfe,' +` 0xaa,0xfd,0x88,0xfe,0x1a,0xfe,0xd2,0xfe,' +` 0x81,0xfe,0x16,0xff,0xdc,0xfe,0x51,0xff,' +` 0x2a,0xff,0x84,0xff,0x6b,0xff,0xad,0xff,' +` 0x9e,0xff,0xcc,0xff,0xc6,0xff,0xe4,0xff,' +` 0xe2,0xff,0xf3,0xff,0xf4,0xff,0xfc,0xff,' +` 0xfd,0xff,0x00,0x00,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfd,0xff,0xfb,0xff,0xf4,0xff,' +` 0xf0,0xff,0xe2,0xff,0xde,0xff,0xc6,0xff,' +` 0xc4,0xff,0x9f,0xff,0xa0,0xff,0x6c,0xff,' +` 0x72,0xff,0x2d,0xff,0x3b,0xff,0xe1,0xfe,' +` 0xf9,0xfe,0x89,0xfe,0xb0,0xfe,0x26,0xfe,' +` 0x5f,0xfe,0xb7,0xfd,0xd0,0xfd,0x0b,0xfd,' +` 0x73,0xfd,0x83,0xfc,0x10,0xfd,0xc6,0xfb,' +` 0x57,0xfc,0x1e,0xfb,0xf0,0xfb,0x82,0xfa,' +` 0x8f,0xfb,0xeb,0xf9,0x3e,0xfb,0x58,0xf9,' +` 0xfc,0xfa,0xc9,0xf8,0xcf,0xfa,0x3b,0xf8,' +` 0xba,0xfa,0xad,0xf7,0xc6,0xfa,0x19,0xf7,' +` 0xfd,0xfa,0x71,0xf6,0x73,0xfb,0x98,0xf5,' +` 0x58,0xfc,0x45,0xf4,0x3a,0xfe,0x86,0xf1,' +` 0x88,0x03,0x63,0xe5,0x2f,0x71,0x76,0x16,' +` 0x66,0xec,0xe5,0x01,0x9a,0xf3,0xb6,0xfe,' +` 0x1a,0xf6,0x93,0xfd,0x88,0xf7,0x1f,0xfd,' +` 0x90,0xf8,0xfd,0xfc,0x69,0xf9,0x08,0xfd,' +` 0x26,0xfa,0x2b,0xfd,0xd1,0xfa,0x5e,0xfd,' +` 0x6d,0xfb,0x99,0xfd,0xfc,0xfb,0xd8,0xfd,' +` 0x81,0xfc,0x19,0xfe,0xfc,0xfc,0x5a,0xfe,' +` 0x69,0xfd,0xa5,0xfe,0x28,0xfe,0x08,0xff,' +` 0x6f,0xfe,0x36,0xff,0xb8,0xfe,0x8a,0xff,' +` 0x25,0xff,0xa6,0xff,0x52,0xff,0xbb,0xff,' +` 0x7a,0xff,0xce,0xff,0x9d,0xff,0xdd,0xff,' +` 0xb9,0xff,0xe8,0xff,0xcf,0xff,0xf1,0xff,' +` 0xe0,0xff,0xf7,0xff,0xed,0xff,0xfb,0xff,' +` 0xf6,0xff,0xfe,0xff,0xfc,0xff,0xff,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x0a,0x00,' +` 0x09,0x00,0x1a,0x00,0x14,0x00,0x31,0x00,' +` 0x25,0x00,0x53,0x00,0x3d,0x00,0x7f,0x00,' +` 0x5c,0x00,0xb6,0x00,0x81,0x00,0xf9,0x00,' +` 0xae,0x00,0x48,0x01,0xe0,0x00,0xa4,0x01,' +` 0x14,0x01,0x29,0x02,0xf6,0x01,0x13,0x03,' +` 0x4e,0x02,0xa8,0x03,0xb0,0x02,0x04,0x04,' +` 0xb9,0x02,0x9d,0x04,0x08,0x03,0x40,0x05,' +` 0x4c,0x03,0xe3,0x05,0x81,0x03,0x8c,0x06,' +` 0xa6,0x03,0x3c,0x07,0xb4,0x03,0xf6,0x07,' +` 0xa4,0x03,0xbf,0x08,0x67,0x03,0xa6,0x09,' +` 0xea,0x02,0xc2,0x0a,0x01,0x02,0x52,0x0c,' +` 0x4a,0x00,0xfc,0x0e,0x88,0xfc,0x6b,0x15,' +` 0x5d,0xef,0x2e,0x45,0x89,0x69,0x49,0xeb,' +` 0xc5,0x16,0x79,0xfb,0x43,0x0f,0x89,0xff,' +` 0x3f,0x0c,0x40,0x01,0x79,0x0a,0x1a,0x02,' +` 0x37,0x09,0x8a,0x02,0x39,0x08,0xbc,0x02,' +` 0x5e,0x07,0xc7,0x02,0x9c,0x06,0xb9,0x02,' +` 0xea,0x05,0x98,0x02,0x43,0x05,0x6b,0x02,' +` 0xa8,0x04,0x34,0x02,0x17,0x04,0xf5,0x01,' +` 0x99,0x03,0x60,0x01,0x28,0x02,0xd1,0x00,' +` 0xd9,0x01,0xaa,0x00,0x8a,0x01,0xc7,0x00,' +` 0x6b,0x01,0xa1,0x00,0x26,0x01,0x80,0x00,' +` 0xe6,0x00,0x62,0x00,0xaf,0x00,0x48,0x00,' +` 0x80,0x00,0x33,0x00,0x5a,0x00,0x22,0x00,' +` 0x3b,0x00,0x15,0x00,0x24,0x00,0x0c,0x00,' +` 0x13,0x00,0x05,0x00,0x08,0x00,0x02,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,' +` 0x02,0x00,0x05,0x00,0x08,0x00,0x0a,0x00,' +` 0x0d,0x00,0x10,0x00,0x15,0x00,0x19,0x00,' +` 0x1f,0x00,0x24,0x00,0x2b,0x00,0x31,0x00,' +` 0x39,0x00,0x40,0x00,0x4a,0x00,0x51,0x00,' +` 0x60,0x00,0x54,0x00,0x5a,0x00,0x65,0x00,' +` 0x71,0x00,0x7c,0x00,0x8c,0x00,0x95,0x00,' +` 0xab,0x00,0xae,0x00,0x13,0x01,0x62,0x01,' +` 0x6b,0x01,0x8e,0x01,0xa1,0x01,0xc2,0x01,' +` 0xd8,0x01,0xf8,0x01,0x10,0x02,0x30,0x02,' +` 0x48,0x02,0x66,0x02,0x7e,0x02,0x9c,0x02,' +` 0xb3,0x02,0xcf,0x02,0xe4,0x02,0xfb,0x02,' +` 0x0d,0x03,0x21,0x03,0x30,0x03,0x41,0x03,' +` 0x4d,0x03,0x5b,0x03,0x64,0x03,0x6a,0x43,' +` 0x73,0x03,0x7a,0x03,0x7b,0x03,0x7e,0x03,' +` 0x7c,0x03,0x7a,0x03,0x74,0x03,0x6f,0x03,' +` 0x64,0x03,0x5b,0x03,0x4c,0x03,0x3e,0x03,' +` 0x2b,0x03,0x19,0x03,0x04,0x03,0xee,0x02,' +` 0xd3,0x02,0xba,0x02,0x9d,0x02,0x81,0x02,' +` 0x62,0x02,0x44,0x02,0x25,0x02,0x06,0x02,' +` 0xe6,0x01,0xed,0x01,0xca,0x01,0xac,0x01,' +` 0x89,0x01,0x6c,0x01,0x4b,0x01,0x30,0x01,' +` 0x11,0x01,0xf8,0x00,0xac,0x00,0x8d,0x00,' +` 0x7e,0x00,0x6c,0x00,0x5e,0x00,0x4f,0x00,' +` 0x43,0x00,0x38,0x00,0x2e,0x00,0x25,0x00,' +` 0x1d,0x00,0x16,0x00,0x11,0x00,0x0c,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0x02,0x00,0xfc,0xff,0x06,0x00,0xfe,0xff,' +` 0x0f,0x00,0xfc,0xff,0x18,0x00,0xf8,0xff,' +` 0x23,0x00,0xf3,0xff,0x30,0x00,0xec,0xff,' +` 0x3d,0x00,0xe1,0xff,0x4a,0x00,0xd1,0xff,' +` 0x55,0x00,0xbb,0xff,0x3a,0x00,0x64,0xff,' +` 0x30,0x00,0x32,0xff,0x27,0x00,0xf2,0xfe,' +` 0x19,0x00,0xa2,0xfe,0x0a,0x00,0x13,0xfe,' +` 0x83,0xff,0x88,0xfd,0x60,0xff,0xfb,0xfc,' +` 0x33,0xff,0x5d,0xfc,0x05,0xff,0xad,0xfb,' +` 0xdc,0xfe,0xe6,0xfa,0xbe,0xfe,0x05,0xfa,' +` 0xb6,0xfe,0x00,0xf9,0xd3,0xfe,0xc4,0xf7,' +` 0x2d,0xff,0x21,0xf6,0x0e,0x00,0xbb,0xf3,' +` 0x32,0x02,0x2e,0xef,0xce,0x08,0xb9,0xde,' +` 0x20,0x62,0xfe,0x2e,0x60,0xe3,0xed,0x05,' +` 0xe0,0xee,0xd8,0xff,0x27,0xf2,0x4e,0xfd,' +` 0xb8,0xf3,0xec,0xfb,0xb4,0xf4,0x27,0xfb,' +` 0x85,0xf5,0xc0,0xfa,0x3c,0xf6,0x93,0xfa,' +` 0xea,0xf6,0x97,0xfa,0x9e,0xf7,0xc0,0xfa,' +` 0x53,0xf8,0x03,0xfb,0x09,0xf9,0x5b,0xfb,' +` 0xc1,0xf9,0xc7,0xfb,0xc0,0xfa,0x77,0xfc,' +` 0x6f,0xfb,0xe4,0xfc,0x16,0xfc,0x54,0xfd,' +` 0xb5,0xfc,0xc2,0xfd,0x48,0xfd,0x4c,0xfe,' +` 0xfa,0xfd,0xa8,0xfe,0x6c,0xfe,0xf9,0xfe,' +` 0xd1,0xfe,0x3f,0xff,0x26,0xff,0x7a,0xff,' +` 0x6c,0xff,0xa9,0xff,0xa3,0xff,0xcd,0xff,' +` 0xcc,0xff,0xe6,0xff,0xe8,0xff,0xf8,0xff,' +` 0xf9,0xff,0xfe,0xff,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfe,0xff,0xf9,0xff,0xf6,0xff,' +` 0xe6,0xff,0xe5,0xff,0xc9,0xff,0xcb,0xff,' +` 0x9e,0xff,0xa7,0xff,0x65,0xff,0x77,0xff,' +` 0x1d,0xff,0x3c,0xff,0xc4,0xfe,0xf6,0xfe,' +` 0x5d,0xfe,0xa6,0xfe,0xe8,0xfd,0x29,0xfe,' +` 0x35,0xfd,0xc1,0xfd,0x9f,0xfc,0x55,0xfd,' +` 0xfd,0xfb,0xe9,0xfc,0x54,0xfb,0x81,0xfc,' +` 0xa0,0xfa,0xd2,0xfb,0xa4,0xf9,0x70,0xfb,' +` 0xe9,0xf8,0x20,0xfb,0x30,0xf8,0xe7,0xfa,' +` 0x77,0xf7,0xc9,0xfa,0xbf,0xf6,0xd4,0xfa,' +` 0x0a,0xf6,0x10,0xfb,0x48,0xf5,0x8d,0xfb,' +` 0x68,0xf4,0x73,0xfc,0x52,0xf3,0x02,0xfe,' +` 0x8e,0xf1,0xe0,0x00,0xcb,0xed,0xdf,0x07,' +` 0x28,0xe0,0xa9,0x3c,0x96,0x57,0xc1,0xdd,' +` 0x04,0x0a,0x86,0xee,0x10,0x03,0x56,0xf3,' +` 0xbc,0x00,0xe1,0xf5,0xc0,0xff,0x99,0xf7,' +` 0x4e,0xff,0xe3,0xf8,0x22,0xff,0xf2,0xf9,' +` 0x1f,0xff,0xdb,0xfa,0x33,0xff,0xa7,0xfb,' +` 0x54,0xff,0x5b,0xfc,0x7a,0xff,0xfa,0xfc,' +` 0xa2,0xff,0x84,0xfd,0xcc,0xff,0x57,0xfe,' +` 0x2c,0x00,0xad,0xfe,0x3c,0x00,0xfa,0xfe,' +` 0x45,0x00,0x38,0xff,0x4a,0x00,0x69,0xff,' +` 0x53,0x00,0xc1,0xff,0x67,0x00,0xd6,0xff,' +` 0x58,0x00,0xe5,0xff,0x48,0x00,0xef,0xff,' +` 0x38,0x00,0xf5,0xff,0x29,0x00,0xfa,0xff,' +` 0x1c,0x00,0xfd,0xff,0x12,0x00,0xfe,0xff,' +` 0x07,0x00,0xfc,0xff,0x02,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x17,0x00,0x14,0x00,' +` 0x2d,0x00,0x25,0x00,0x4c,0x00,0x3e,0x00,' +` 0x76,0x00,0x5e,0x00,0xab,0x00,0x86,0x00,' +` 0xee,0x00,0xb6,0x00,0x3e,0x01,0xea,0x00,' +` 0xc5,0x01,0xbf,0x01,0x7e,0x02,0x19,0x02,' +` 0x09,0x03,0x7e,0x02,0x9d,0x03,0xe7,0x02,' +` 0x36,0x04,0x58,0x03,0xb2,0x04,0x56,0x03,' +` 0x37,0x05,0xb1,0x03,0xd8,0x05,0xfd,0x03,' +` 0x7d,0x06,0x37,0x04,0x23,0x07,0x5b,0x04,' +` 0xca,0x07,0x5c,0x04,0x75,0x08,0x36,0x04,' +` 0x31,0x09,0xd8,0x03,0x13,0x0a,0x20,0x03,' +` 0x47,0x0b,0xc6,0x01,0x4e,0x0d,0xde,0xfe,' +` 0x19,0x12,0x3e,0xf5,0xfa,0x30,0xcb,0x77,' +` 0x96,0xee,0x27,0x14,0x35,0xfd,0x91,0x0d,' +` 0x94,0x00,0xf7,0x0a,0xf1,0x01,0x6e,0x09,' +` 0x94,0x02,0x4e,0x08,0xd2,0x02,0x5e,0x07,' +` 0xdc,0x02,0x8e,0x06,0xc7,0x02,0xd1,0x05,' +` 0x9d,0x02,0x23,0x05,0x67,0x02,0x84,0x04,' +` 0x2a,0x02,0xf2,0x03,0xe7,0x01,0x74,0x03,' +` 0x1c,0x01,0xee,0x01,0xab,0x00,0xa3,0x01,' +` 0x88,0x00,0x59,0x01,0x6c,0x00,0x18,0x01,' +` 0x55,0x00,0xda,0x00,0x61,0x00,0xda,0x00,' +` 0x51,0x00,0xa9,0x00,0x3e,0x00,0x80,0x00,' +` 0x2e,0x00,0x5e,0x00,0x21,0x00,0x42,0x00,' +` 0x16,0x00,0x2b,0x00,0x0d,0x00,0x1a,0x00,' +` 0x07,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,' +` 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x07,0x00,0x0b,0x00,0x0d,0x00,0x11,0x00,' +` 0x14,0x00,0x18,0x00,0x1c,0x00,0x22,0x00,' +` 0x27,0x00,0x30,0x00,0x24,0x00,0x28,0x00,' +` 0x30,0x00,0x38,0x00,0x40,0x00,0x4b,0x00,' +` 0x54,0x00,0x62,0x00,0x6b,0x00,0x7d,0x00,' +` 0x86,0x00,0x9e,0x00,0xa1,0x00,0x14,0x01,' +` 0x65,0x01,0x6f,0x01,0x95,0x01,0xa9,0x01,' +` 0xcc,0x01,0xe4,0x01,0x06,0x02,0x1f,0x02,' +` 0x40,0x02,0x59,0x02,0x77,0x02,0x8e,0x02,' +` 0xa9,0x02,0xbf,0x02,0xd8,0x02,0xeb,0x02,' +` 0x02,0x03,0x13,0x03,0x26,0x03,0x35,0x03,' +` 0x45,0x03,0x50,0x03,0x5a,0x43,0x64,0x03,' +` 0x6e,0x03,0x72,0x03,0x77,0x03,0x76,0x03,' +` 0x76,0x03,0x72,0x03,0x6d,0x03,0x64,0x03,' +` 0x5b,0x03,0x4b,0x03,0x3c,0x03,0x29,0x03,' +` 0x15,0x03,0xfe,0x02,0xe7,0x02,0xcd,0x02,' +` 0xb2,0x02,0x96,0x02,0x79,0x02,0x5c,0x02,' +` 0x3c,0x02,0x22,0x02,0x29,0x02,0x05,0x02,' +` 0xe6,0x01,0xc3,0x01,0xa4,0x01,0x82,0x01,' +` 0x64,0x01,0x44,0x01,0x28,0x01,0x09,0x01,' +` 0xf0,0x00,0xd5,0x00,0xbe,0x00,0x7e,0x00,' +` 0x65,0x00,0x58,0x00,0x4a,0x00,0x3e,0x00,' +` 0x33,0x00,0x2a,0x00,0x21,0x00,0x1a,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x01,0x00,0x06,0x00,0x02,0x00,0x0e,0x00,' +` 0x05,0x00,0x1b,0x00,0x0a,0x00,0x31,0x00,' +` 0x1f,0x00,0x4f,0x00,0x29,0x00,0x6d,0x00,' +` 0x34,0x00,0x8d,0x00,0x3c,0x00,0xad,0x00,' +` 0x41,0x00,0xb0,0x00,0x10,0x00,0xbe,0x00,' +` 0xfd,0xff,0xce,0x00,0xdd,0xff,0xd8,0x00,' +` 0xaf,0xff,0xda,0x00,0x70,0xff,0xd4,0x00,' +` 0x1e,0xff,0xca,0x00,0x8c,0xfe,0x41,0x00,' +` 0xeb,0xfd,0x1d,0x00,0x4e,0xfd,0xf0,0xff,' +` 0x9a,0xfc,0xc1,0xff,0xcc,0xfb,0x98,0xff,' +` 0xdc,0xfa,0x78,0xff,0xbb,0xf9,0x76,0xff,' +` 0x62,0xf8,0xb6,0xff,0xaa,0xf6,0x7c,0x00,' +` 0x2d,0xf4,0x84,0x02,0x8a,0xef,0x00,0x09,' +` 0x04,0xdf,0xb1,0x62,0x87,0x2e,0x96,0xe3,' +` 0xd6,0x05,0xe4,0xee,0xb3,0xff,0x0d,0xf2,' +` 0x17,0xfd,0x85,0xf3,0xa3,0xfb,0x6a,0xf4,' +` 0xc5,0xfa,0x1e,0xf5,0x45,0xfa,0xc1,0xf5,' +` 0x13,0xfa,0x71,0xf6,0x18,0xfa,0x24,0xf7,' +` 0x43,0xfa,0xdb,0xf7,0x8b,0xfa,0x97,0xf8,' +` 0xef,0xfa,0xa5,0xf9,0xa7,0xfb,0x62,0xfa,' +` 0x19,0xfc,0x19,0xfb,0x91,0xfc,0xca,0xfb,' +` 0x0c,0xfd,0x75,0xfc,0x85,0xfd,0x15,0xfd,' +` 0xfa,0xfd,0xa7,0xfd,0x7d,0xfe,0x4d,0xfe,' +` 0xdc,0xfe,0xb8,0xfe,0x2a,0xff,0x15,0xff,' +` 0x6c,0xff,0x61,0xff,0xa0,0xff,0x9d,0xff,' +` 0xce,0xff,0xce,0xff,0xe7,0xff,0xe9,0xff,' +` 0xf7,0xff,0xf9,0xff,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf8,0xff,0xf6,0xff,0xe8,0xff,' +` 0xe6,0xff,0xcc,0xff,0xcb,0xff,0x98,0xff,' +` 0x9f,0xff,0x5b,0xff,0x6a,0xff,0x0e,0xff,' +` 0x28,0xff,0xb0,0xfe,0xda,0xfe,0x42,0xfe,' +` 0x69,0xfe,0x99,0xfd,0xf9,0xfd,0x06,0xfd,' +` 0x86,0xfd,0x64,0xfc,0x0f,0xfd,0xb8,0xfb,' +` 0x97,0xfc,0x05,0xfb,0x23,0xfc,0x4d,0xfa,' +` 0xb6,0xfb,0x8c,0xf9,0x01,0xfb,0x82,0xf8,' +` 0xa5,0xfa,0xc3,0xf7,0x64,0xfa,0x09,0xf7,' +` 0x43,0xfa,0x52,0xf6,0x49,0xfa,0x9e,0xf5,' +` 0x8a,0xfa,0xf4,0xf4,0x1b,0xfb,0x35,0xf4,' +` 0x11,0xfc,0x3b,0xf3,0xa8,0xfd,0x9b,0xf1,' +` 0x85,0x00,0x14,0xee,0x57,0x07,0x32,0xe1,' +` 0x45,0x38,0x76,0x5b,0x21,0xde,0x05,0x0a,' +` 0x03,0xef,0x3b,0x03,0xde,0xf3,0x0b,0x01,' +` 0x79,0xf6,0x2d,0x00,0x44,0xf8,0xdd,0xff,' +` 0xaa,0xf9,0xd3,0xff,0xd2,0xfa,0xe7,0xff,' +` 0xc6,0xfb,0x08,0x00,0x98,0xfc,0x30,0x00,' +` 0x4e,0xfd,0x57,0x00,0xe9,0xfd,0x7d,0x00,' +` 0xbf,0xfe,0xec,0x00,0x26,0xff,0xf5,0x00,' +` 0x76,0xff,0xf7,0x00,0xb4,0xff,0xf0,0x00,' +` 0xe2,0xff,0xe3,0x00,0x00,0x00,0xcf,0x00,' +` 0x12,0x00,0xbf,0x00,0x44,0x00,0xb7,0x00,' +` 0x3e,0x00,0x94,0x00,0x35,0x00,0x72,0x00,' +` 0x2a,0x00,0x53,0x00,0x1f,0x00,0x33,0x00,' +` 0x0a,0x00,0x1c,0x00,0x05,0x00,0x0f,0x00,' +` 0x02,0x00,0x06,0x00,0x01,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x24,0x00,0x41,0x00,' +` 0x3a,0x00,0x67,0x00,0x5a,0x00,0x98,0x00,' +` 0x81,0x00,0xd5,0x00,0xaf,0x00,0x38,0x01,' +` 0x62,0x01,0xdf,0x01,0xb9,0x01,0x57,0x02,' +` 0x1c,0x02,0xdb,0x02,0x86,0x02,0x69,0x03,' +` 0xf6,0x02,0xfe,0x03,0x67,0x03,0x96,0x04,' +` 0xdc,0x03,0x04,0x05,0xd9,0x03,0x81,0x05,' +` 0x35,0x04,0x16,0x06,0x80,0x04,0xac,0x06,' +` 0xb8,0x04,0x42,0x07,0xd8,0x04,0xd9,0x07,' +` 0xd6,0x04,0x77,0x08,0xa6,0x04,0x25,0x09,' +` 0x2b,0x04,0x05,0x0a,0x37,0x03,0x70,0x0b,' +` 0x2a,0x01,0xb8,0x0e,0x9c,0xfa,0x12,0x22,' +` 0x9f,0x7f,0xc1,0xf3,0xb1,0x10,0x65,0xff,' +` 0x87,0x0b,0xdc,0x01,0x7b,0x09,0xc7,0x02,' +` 0x3b,0x08,0x23,0x03,0x4b,0x07,0x37,0x03,' +` 0x80,0x06,0x23,0x03,0xc9,0x05,0xf0,0x02,' +` 0x1a,0x05,0xac,0x02,0x79,0x04,0x61,0x02,' +` 0xe5,0x03,0x0f,0x02,0x68,0x03,0x4a,0x01,' +` 0xc0,0x01,0xaa,0x00,0x77,0x01,0x7d,0x00,' +` 0x2e,0x01,0x5b,0x00,0xef,0x00,0x3f,0x00,' +` 0xba,0x00,0x29,0x00,0x8d,0x00,0x19,0x00,' +` 0x66,0x00,0x29,0x00,0x6e,0x00,0x1f,0x00,' +` 0x4f,0x00,0x15,0x00,0x38,0x00,0x0d,0x00,' +` 0x26,0x00,0x09,0x00,0x15,0x00,0xfb,0xff,' +` 0x08,0x00,0xfd,0xff,0x04,0x00,0xfe,0xff,' +` 0x02,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xff,0xff,0xfe,0xff,0xfe,0xff,' +` 0xfd,0xff,0xfd,0xff,0xfd,0xff,0xfd,0xff,' +` 0xfc,0xff,0x04,0x00,0x08,0x00,0x0a,0x00,' +` 0x0d,0x00,0x12,0x00,0x0d,0x00,0x06,0x00,' +` 0x0e,0x00,0x10,0x00,0x18,0x00,0x1c,0x00,' +` 0x26,0x00,0x2d,0x00,0x39,0x00,0x42,0x00,' +` 0x51,0x00,0x5b,0x00,0x6d,0x00,0x78,0x00,' +` 0x8f,0x00,0x97,0x00,0xc8,0x00,0x55,0x01,' +` 0x6c,0x01,0x8d,0x01,0xa6,0x01,0xc6,0x01,' +` 0xe1,0x01,0xfe,0x01,0x18,0x02,0x35,0x02,' +` 0x4e,0x02,0x6a,0x02,0x83,0x02,0x9e,0x02,' +` 0xb5,0x02,0xce,0x02,0xe3,0x02,0xf9,0x02,' +` 0x0b,0x03,0x1d,0x03,0x2b,0x03,0x3a,0x03,' +` 0x42,0x43,0x50,0x03,0x58,0x03,0x5f,0x03,' +` 0x62,0x03,0x64,0x03,0x61,0x03,0x5d,0x03,' +` 0x55,0x03,0x4c,0x03,0x3f,0x03,0x32,0x03,' +` 0x21,0x03,0x10,0x03,0xfb,0x02,0xe6,0x02,' +` 0xce,0x02,0xb5,0x02,0x9b,0x02,0x7e,0x02,' +` 0x63,0x02,0x43,0x02,0x45,0x02,0x36,0x02,' +` 0x0f,0x02,0xf3,0x01,0xcf,0x01,0xb2,0x01,' +` 0x8f,0x01,0x73,0x01,0x52,0x01,0x38,0x01,' +` 0x18,0x01,0x00,0x01,0xe3,0x00,0xce,0x00,' +` 0xb2,0x00,0xa2,0x00,0x7a,0x00,0x4d,0x00,' +` 0x45,0x00,0x38,0x00,0x2e,0x00,0x26,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x04,0x00,0x05,0x00,0x0d,0x00,' +` 0x0d,0x00,0x1c,0x00,0x18,0x00,0x31,0x00,' +` 0x28,0x00,0x4b,0x00,0x3b,0x00,0x7b,0x00,' +` 0x62,0x00,0xa4,0x00,0x7b,0x00,0xce,0x00,' +` 0x77,0x00,0xd1,0x00,0x7d,0x00,0xf1,0x00,' +` 0x80,0x00,0x0b,0x01,0x79,0x00,0x1f,0x01,' +` 0x65,0x00,0x29,0x01,0x41,0x00,0x28,0x01,' +` 0x0b,0x00,0x1b,0x01,0xbf,0xff,0x05,0x01,' +` 0x36,0xff,0x6c,0x00,0x8d,0xfe,0x34,0x00,' +` 0xf2,0xfd,0xf1,0xff,0x3b,0xfd,0xa0,0xff,' +` 0x63,0xfc,0x51,0xff,0x6b,0xfb,0x10,0xff,' +` 0x49,0xfa,0xf2,0xfe,0xea,0xf8,0x20,0xff,' +` 0x16,0xf7,0x01,0x00,0x1e,0xf4,0x18,0x03,' +` 0x26,0xec,0xf1,0x18,0x6a,0x70,0x9c,0xe4,' +` 0x01,0x04,0xf2,0xf0,0x2d,0xfe,0x8c,0xf3,' +` 0xe6,0xfb,0xa1,0xf4,0xab,0xfa,0x41,0xf5,' +` 0xef,0xf9,0xb8,0xf5,0x82,0xf9,0x27,0xf6,' +` 0x4e,0xf9,0x9c,0xf6,0x49,0xf9,0x23,0xf7,' +` 0x7b,0xf9,0xc3,0xf7,0xcb,0xf9,0x76,0xf8,' +` 0x8c,0xfa,0x73,0xf9,0x00,0xfb,0x22,0xfa,' +` 0x7f,0xfb,0xd4,0xfa,0x04,0xfc,0x85,0xfb,' +` 0x8d,0xfc,0x31,0xfc,0x15,0xfd,0xd4,0xfc,' +` 0x97,0xfd,0x6c,0xfd,0x11,0xfe,0xf6,0xfd,' +` 0x92,0xfe,0x8f,0xfe,0xf4,0xfe,0xf2,0xfe,' +` 0x40,0xff,0x4a,0xff,0x8f,0xff,0x90,0xff,' +` 0xbb,0xff,0xbe,0xff,0xdb,0xff,0xdf,0xff,' +` 0xef,0xff,0xf3,0xff,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf8,0xff,0xf6,0xff,0xe7,0xff,0xe7,0xff,' +` 0xcb,0xff,0xcd,0xff,0x9f,0xff,0xa9,0xff,' +` 0x61,0xff,0x66,0xff,0x09,0xff,0x24,0xff,' +` 0xa8,0xfe,0xcf,0xfe,0x15,0xfe,0x59,0xfe,' +` 0x8b,0xfd,0xeb,0xfd,0xf1,0xfc,0x76,0xfd,' +` 0x49,0xfc,0xfb,0xfc,0x96,0xfb,0x7f,0xfc,' +` 0xdc,0xfa,0x07,0xfc,0x1c,0xfa,0x98,0xfb,' +` 0x5b,0xf9,0x3b,0xfb,0x6c,0xf8,0x80,0xfa,' +` 0x8a,0xf7,0x46,0xfa,0xca,0xf6,0x2b,0xfa,' +` 0x19,0xf6,0x4c,0xfa,0x76,0xf5,0xa4,0xfa,' +` 0xcc,0xf4,0x44,0xfb,0x07,0xf4,0x4b,0xfc,' +` 0xfc,0xf2,0xfa,0xfd,0x3f,0xf1,0x0a,0x01,' +` 0x7a,0xed,0x74,0x08,0x48,0xdf,0x40,0x42,' +` 0x29,0x53,0x2b,0xde,0xa0,0x0a,0xf0,0xee,' +` 0xd2,0x03,0xf0,0xf3,0xa1,0x01,0xaa,0xf6,' +` 0xc7,0x00,0x8d,0xf8,0x7b,0x00,0x06,0xfa,' +` 0x75,0x00,0x3e,0xfb,0x91,0x00,0x47,0xfc,' +` 0xbb,0x00,0x26,0xfd,0xe2,0x00,0xe2,0xfd,' +` 0x01,0x01,0xa1,0xfe,0x8c,0x01,0x4c,0xff,' +` 0x91,0x01,0xae,0xff,0x90,0x01,0xf7,0xff,' +` 0x86,0x01,0x2b,0x00,0x71,0x01,0x4c,0x00,' +` 0x54,0x01,0x5f,0x00,0x31,0x01,0x65,0x00,' +` 0x0a,0x01,0x62,0x00,0xf9,0x00,0x77,0x00,' +` 0xce,0x00,0x61,0x00,0xa0,0x00,0x40,0x00,' +` 0x63,0x00,0x29,0x00,0x43,0x00,0x1a,0x00,' +` 0x29,0x00,0x0f,0x00,0x16,0x00,0x07,0x00,' +` 0x09,0x00,0x02,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3e,0x00,0x75,0x00,' +` 0x54,0x00,0xac,0x00,0x75,0x00,0x09,0x01,' +` 0x13,0x01,0x9e,0x01,0x5c,0x01,0x0f,0x02,' +` 0xb0,0x01,0x8d,0x02,0x0c,0x02,0x15,0x03,' +` 0x6d,0x02,0xa8,0x03,0xd0,0x02,0x43,0x04,' +` 0x33,0x03,0xe7,0x04,0x93,0x03,0x92,0x05,' +` 0xaa,0x03,0xd1,0x05,0xdb,0x03,0x7a,0x06,' +` 0x0d,0x04,0x22,0x07,0x27,0x04,0xcc,0x07,' +` 0x21,0x04,0x7f,0x08,0xf0,0x03,0x46,0x09,' +` 0x7f,0x03,0x39,0x0a,0xa8,0x02,0x92,0x0b,' +` 0x0b,0x01,0xf4,0x0d,0x58,0xfd,0x55,0x14,' +` 0x45,0xee,0xdf,0x76,0xb6,0x31,0x3e,0xf4,' +` 0xaa,0x11,0xc7,0xfd,0x79,0x0c,0x73,0x00,' +` 0x1f,0x0a,0x8d,0x01,0xa2,0x08,0x0a,0x02,' +` 0x84,0x07,0x37,0x02,0x98,0x06,0x38,0x02,' +` 0xca,0x05,0x1e,0x02,0x11,0x05,0xec,0x01,' +` 0x63,0x04,0xaa,0x01,0xcf,0x03,0xde,0x00,' +` 0x07,0x02,0x51,0x00,0xad,0x01,0x2b,0x00,' +` 0x55,0x01,0x0e,0x00,0x08,0x01,0xf7,0xff,' +` 0xc7,0x00,0xe7,0xff,0x92,0x00,0xdc,0xff,' +` 0x68,0x00,0xd7,0xff,0x47,0x00,0xd7,0xff,' +` 0x4a,0x00,0xf3,0xff,0x34,0x00,0xf2,0xff,' +` 0x22,0x00,0xe6,0xff,0x08,0x00,0xeb,0xff,' +` 0x04,0x00,0xf2,0xff,0x02,0x00,0xf8,0xff,' +` 0x00,0x00,0xfc,0xff,0x00,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfe,0xff,0xfe,0xff,' +` 0xfd,0xff,0xfc,0xff,0xfb,0xff,0xf9,0xff,' +` 0xf8,0xff,0xf7,0xff,0xf7,0xff,0xf6,0xff,' +` 0xf6,0xff,0xff,0xff,0x05,0x00,0xfe,0xff,' +` 0xf8,0xff,0xfc,0xff,0xfe,0xff,0x03,0x00,' +` 0x07,0x00,0x0e,0x00,0x14,0x00,0x1e,0x00,' +` 0x25,0x00,0x31,0x00,0x3b,0x00,0x4a,0x00,' +` 0x56,0x00,0x69,0x00,0x75,0x00,0x8d,0x00,' +` 0x94,0x00,0xce,0x00,0x5e,0x01,0x71,0x01,' +` 0x94,0x01,0xa9,0x01,0xc9,0x01,0xe1,0x01,' +` 0x00,0x02,0x19,0x02,0x37,0x02,0x50,0x02,' +` 0x6c,0x02,0x84,0x02,0x9f,0x02,0xb4,0x02,' +` 0xcd,0x02,0xe0,0x02,0xf6,0x02,0x06,0x03,' +` 0x18,0x03,0x24,0x03,0x2f,0x43,0x3b,0x03,' +` 0x45,0x03,0x48,0x03,0x4b,0x03,0x4a,0x03,' +` 0x48,0x03,0x42,0x03,0x3c,0x03,0x31,0x03,' +` 0x26,0x03,0x17,0x03,0x08,0x03,0xf5,0x02,' +` 0xe2,0x02,0xcc,0x02,0xb6,0x02,0x9d,0x02,' +` 0x83,0x02,0x69,0x02,0x4b,0x02,0x51,0x02,' +` 0x41,0x02,0x1b,0x02,0x00,0x02,0xdd,0x01,' +` 0xc1,0x01,0x9f,0x01,0x83,0x01,0x62,0x01,' +` 0x47,0x01,0x29,0x01,0x10,0x01,0xf3,0x00,' +` 0xdc,0x00,0xc2,0x00,0xae,0x00,0x95,0x00,' +` 0x88,0x00,0x62,0x00,0x3b,0x00,0x36,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0x05,0x00,0x07,0x00,' +` 0x10,0x00,0x11,0x00,0x21,0x00,0x21,0x00,' +` 0x39,0x00,0x35,0x00,0x58,0x00,0x4e,0x00,' +` 0x7c,0x00,0x6c,0x00,0xbc,0x00,0xa0,0x00,' +` 0xd7,0x00,0x9c,0x00,0xfa,0x00,0xb1,0x00,' +` 0x20,0x01,0xbf,0x00,0x41,0x01,0xc2,0x00,' +` 0x5b,0x01,0xb9,0x00,0x6a,0x01,0xa0,0x00,' +` 0x6d,0x01,0x74,0x00,0x62,0x01,0x34,0x00,' +` 0x47,0x01,0xe2,0xff,0xfb,0x00,0xfd,0xfe,' +` 0x8a,0x00,0x6d,0xfe,0x37,0x00,0xb9,0xfd,' +` 0xdc,0xff,0xe7,0xfc,0x81,0xff,0xf5,0xfb,' +` 0x31,0xff,0xdc,0xfa,0xfe,0xfe,0x8b,0xf9,' +` 0x0c,0xff,0xd2,0xf7,0xb9,0xff,0x17,0xf5,' +` 0x54,0x02,0xff,0xed,0xf6,0x14,0x97,0x72,' +` 0x95,0xe6,0x14,0x03,0xdf,0xf1,0xbf,0xfd,' +` 0x31,0xf4,0xa6,0xfb,0x1f,0xf5,0x80,0xfa,' +` 0xa4,0xf5,0xcf,0xf9,0x0a,0xf6,0x69,0xf9,' +` 0x6b,0xf6,0x3a,0xf9,0xd4,0xf6,0x39,0xf9,' +` 0x4b,0xf7,0x5d,0xf9,0xd7,0xf7,0xb4,0xf9,' +` 0xd1,0xf8,0x73,0xfa,0x7e,0xf9,0xe6,0xfa,' +` 0x2a,0xfa,0x67,0xfb,0xda,0xfa,0xef,0xfb,' +` 0x89,0xfb,0x7b,0xfc,0x34,0xfc,0x05,0xfd,' +` 0xd7,0xfc,0x8a,0xfd,0x70,0xfd,0x06,0xfe,' +` 0xfc,0xfd,0x75,0xfe,0x86,0xfe,0xf2,0xfe,' +` 0xf7,0xfe,0x53,0xff,0x53,0xff,0x8d,0xff,' +` 0x91,0xff,0xba,0xff,0xbf,0xff,0xda,0xff,' +` 0xdf,0xff,0xef,0xff,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf8,0xff,0xf6,0xff,0xe8,0xff,0xe7,0xff,' +` 0xcc,0xff,0xce,0xff,0xa2,0xff,0xa9,0xff,' +` 0x68,0xff,0x78,0xff,0x18,0xff,0x23,0xff,' +` 0xab,0xfe,0xba,0xfe,0x1b,0xfe,0x54,0xfe,' +` 0x91,0xfd,0xe4,0xfd,0xf7,0xfc,0x6b,0xfd,' +` 0x4f,0xfc,0xed,0xfc,0x9d,0xfb,0x6e,0xfc,' +` 0xe5,0xfa,0xf1,0xfb,0x28,0xfa,0x7d,0xfb,' +` 0x6c,0xf9,0x15,0xfb,0xb6,0xf8,0x90,0xfa,' +` 0x90,0xf7,0x2b,0xfa,0xe3,0xf6,0x18,0xfa,' +` 0x46,0xf6,0x32,0xfa,0xad,0xf5,0x82,0xfa,' +` 0x10,0xf5,0x18,0xfb,0x5e,0xf4,0x0e,0xfc,' +` 0x6e,0xf3,0xa1,0xfd,0xe1,0xf1,0x73,0x00,' +` 0x7e,0xee,0x1d,0x07,0x23,0xe2,0x84,0x35,' +` 0x25,0x5e,0xae,0xde,0x2f,0x0a,0x9b,0xef,' +` 0x90,0x03,0x81,0xf4,0x82,0x01,0x2b,0xf7,' +` 0xc1,0x00,0x06,0xf9,0x88,0x00,0x79,0xfa,' +` 0x90,0x00,0xad,0xfb,0xb8,0x00,0xb2,0xfc,' +` 0xee,0x00,0x92,0xfd,0x25,0x01,0x49,0xfe,' +` 0x61,0x01,0x49,0xff,0xc2,0x01,0xba,0xff,' +` 0xcf,0x01,0x11,0x00,0xce,0x01,0x52,0x00,' +` 0xc1,0x01,0x7d,0x00,0xa8,0x01,0x96,0x00,' +` 0x87,0x01,0xa0,0x00,0x5d,0x01,0x9d,0x00,' +` 0x2f,0x01,0x91,0x00,0xff,0x00,0x94,0x00,' +` 0xec,0x00,0x74,0x00,0x9d,0x00,0x50,0x00,' +` 0x73,0x00,0x38,0x00,0x4e,0x00,0x25,0x00,' +` 0x30,0x00,0x15,0x00,0x1a,0x00,0x0a,0x00,' +` 0x0b,0x00,0x03,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x85,0x00,0x4e,0x00,' +` 0xa0,0x00,0x71,0x00,0x3e,0x01,0xeb,0x00,' +` 0x9f,0x01,0x30,0x01,0x0f,0x02,0x7d,0x01,' +` 0x8b,0x02,0xd0,0x01,0x15,0x03,0x27,0x02,' +` 0xa9,0x03,0x80,0x02,0x47,0x04,0xd9,0x02,' +` 0xec,0x04,0x2c,0x03,0x98,0x05,0x7b,0x03,' +` 0x09,0x06,0x4b,0x03,0xa5,0x06,0x72,0x03,' +` 0x58,0x07,0x7b,0x03,0x15,0x08,0x5f,0x03,' +` 0xe0,0x08,0x12,0x03,0xc8,0x09,0x7b,0x02,' +` 0xeb,0x0a,0x6e,0x01,0x8b,0x0c,0x77,0xff,' +` 0x6d,0x0f,0x22,0xfb,0xd4,0x16,0xbe,0xea,' +` 0xa0,0x63,0x36,0x4b,0x1e,0xed,0x65,0x15,' +` 0xfe,0xfa,0x50,0x0e,0xb7,0xfe,0x47,0x0b,' +` 0x4b,0x00,0x6e,0x09,0x0e,0x01,0x17,0x08,' +` 0x69,0x01,0x02,0x07,0x8b,0x01,0x15,0x06,' +` 0x8a,0x01,0x42,0x05,0x77,0x01,0x81,0x04,' +` 0x5d,0x01,0x74,0x03,0xee,0xff,0x48,0x02,' +` 0xe5,0xff,0xce,0x01,0xd2,0xff,0x68,0x01,' +` 0xc2,0xff,0x13,0x01,0xb5,0xff,0xcc,0x00,' +` 0xad,0xff,0x92,0x00,0xab,0xff,0x65,0x00,' +` 0xac,0xff,0x42,0x00,0xb2,0xff,0x2a,0x00,' +` 0xd3,0xff,0x30,0x00,0xce,0xff,0x0a,0x00,' +` 0xd4,0xff,0x04,0x00,0xe0,0xff,0x01,0x00,' +` 0xeb,0xff,0xff,0xff,0xf4,0xff,0xff,0xff,' +` 0xfa,0xff,0x00,0x00,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x70,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfe,0xff,0xfd,0xff,' +` 0xfc,0xff,0xfb,0xff,0xfa,0xff,0xf8,0xff,' +` 0xf7,0xff,0xf6,0xff,0xf4,0xff,0xf4,0xff,' +` 0xf2,0xff,0xf6,0xff,0x00,0x00,0xf5,0xff,' +` 0xf5,0xff,0xf7,0xff,0xfa,0xff,0xfe,0xff,' +` 0x03,0x00,0x08,0x00,0x0f,0x00,0x17,0x00,' +` 0x20,0x00,0x2a,0x00,0x36,0x00,0x42,0x00,' +` 0x51,0x00,0x5f,0x00,0x71,0x00,0x80,0x00,' +` 0x96,0x00,0xa7,0x00,0x3b,0x01,0x72,0x01,' +` 0x84,0x01,0xa4,0x01,0xbc,0x01,0xdb,0x01,' +` 0xf5,0x01,0x12,0x02,0x2c,0x02,0x48,0x02,' +` 0x62,0x02,0x7c,0x02,0x94,0x02,0xad,0x02,' +` 0xc3,0x02,0xd9,0x02,0xec,0x02,0xfe,0x02,' +` 0x0e,0x03,0x1d,0x03,0x25,0x43,0x34,0x03,' +` 0x3a,0x03,0x3f,0x03,0x40,0x03,0x40,0x03,' +` 0x3d,0x03,0x38,0x03,0x31,0x03,0x27,0x03,' +` 0x1b,0x03,0x0d,0x03,0xfd,0x02,0xeb,0x02,' +` 0xd8,0x02,0xc2,0x02,0xac,0x02,0x93,0x02,' +` 0x7b,0x02,0x5d,0x02,0x4a,0x02,0x54,0x02,' +` 0x35,0x02,0x17,0x02,0xf7,0x01,0xd8,0x01,' +` 0xb9,0x01,0x9a,0x01,0x7c,0x01,0x5e,0x01,' +` 0x41,0x01,0x25,0x01,0x0a,0x01,0xf0,0x00,' +` 0xd7,0x00,0xc0,0x00,0xaa,0x00,0x95,0x00,' +` 0x83,0x00,0x6b,0x00,0x3d,0x00,0x3a,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x03,0x00,0x0b,0x00,0x0a,0x00,' +` 0x1b,0x00,0x16,0x00,0x33,0x00,0x26,0x00,' +` 0x53,0x00,0x3b,0x00,0x7b,0x00,0x52,0x00,' +` 0xaa,0x00,0x6b,0x00,0xf2,0x00,0x98,0x00,' +` 0x0c,0x01,0x9c,0x00,0x42,0x01,0xa9,0x00,' +` 0x75,0x01,0xac,0x00,0xa3,0x01,0xa4,0x00,' +` 0xca,0x01,0x8b,0x00,0xe7,0x01,0x60,0x00,' +` 0xf9,0x01,0x20,0x00,0xff,0x01,0xc7,0xff,' +` 0xf7,0x01,0x58,0xff,0xc2,0x01,0x4f,0xfe,' +` 0x66,0x01,0x92,0xfd,0x33,0x01,0xad,0xfc,' +` 0x04,0x01,0xa0,0xfb,0xe3,0x00,0x63,0xfa,' +` 0xe4,0x00,0xe3,0xf8,0x29,0x01,0xf7,0xf6,' +` 0xfc,0x01,0x34,0xf4,0x23,0x04,0x2f,0xef,' +` 0xd1,0x0a,0xb9,0xde,0xe4,0x4d,0x3f,0x48,' +` 0x8c,0xde,0x07,0x09,0x67,0xed,0x63,0x01,' +` 0x4a,0xf1,0x3e,0xfe,0x0c,0xf3,0x82,0xfc,' +` 0x18,0xf4,0x73,0xfb,0xdc,0xf4,0xcc,0xfa,' +` 0x84,0xf5,0x6f,0xfa,0x25,0xf6,0x4a,0xfa,' +` 0xc9,0xf6,0x53,0xfa,0x74,0xf7,0xc1,0xfa,' +` 0x9d,0xf8,0x2d,0xfb,0x57,0xf9,0x91,0xfb,' +` 0x16,0xfa,0x01,0xfc,0xd6,0xfa,0x7a,0xfc,' +` 0x91,0xfb,0xf7,0xfc,0x45,0xfc,0x73,0xfd,' +` 0xee,0xfc,0xea,0xfd,0x8a,0xfd,0x59,0xfe,' +` 0x17,0xfe,0xbb,0xfe,0x9d,0xfe,0x2e,0xff,' +` 0x1c,0xff,0x79,0xff,0x67,0xff,0xaa,0xff,' +` 0xa1,0xff,0xcf,0xff,0xcc,0xff,0xe8,0xff,' +` 0xe8,0xff,0xf7,0xff,0x70,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf5,0xff,0xec,0xff,0xe3,0xff,0xd4,0xff,' +` 0xc6,0xff,0xb0,0xff,0x9c,0xff,0x7e,0xff,' +` 0x63,0xff,0x3d,0xff,0x17,0xff,0xd2,0xfe,' +` 0x97,0xfe,0x4f,0xfe,0x23,0xfe,0xd4,0xfd,' +` 0xa3,0xfd,0x4b,0xfd,0x18,0xfd,0xb7,0xfc,' +` 0x85,0xfc,0x1b,0xfc,0xed,0xfb,0x7c,0xfb,' +` 0x54,0xfb,0xdc,0xfa,0xbf,0xfa,0x42,0xfa,' +` 0x31,0xfa,0xaf,0xf9,0xae,0xf9,0xd6,0xf8,' +` 0xd7,0xf8,0x57,0xf8,0x85,0xf8,0xff,0xf7,' +` 0x4e,0xf8,0xbf,0xf7,0x34,0xf8,0x9a,0xf7,' +` 0x3b,0xf8,0x8c,0xf7,0x67,0xf8,0x94,0xf7,' +` 0xbc,0xf8,0xa7,0xf7,0x49,0xf9,0xa8,0xf7,' +` 0x41,0xfa,0x0f,0xf7,0x9f,0xfd,0x73,0x79,' +` 0x07,0xf6,0x56,0xfc,0x50,0xf9,0x03,0xfc,' +` 0x8e,0xfa,0x61,0xfc,0x83,0xfb,0xed,0xfc,' +` 0x5d,0xfc,0x87,0xfd,0x26,0xfd,0x23,0xfe,' +` 0xe0,0xfd,0xba,0xfe,0x8a,0xfe,0x46,0xff,' +` 0x21,0xff,0xc4,0xff,0xa1,0xff,0x39,0x00,' +` 0x6d,0x00,0xd1,0x00,0xb5,0x00,0x05,0x01,' +` 0xe8,0x00,0x27,0x01,0x09,0x01,0x38,0x01,' +` 0x19,0x01,0x39,0x01,0x19,0x01,0x2e,0x01,' +` 0x0c,0x01,0x17,0x01,0xf6,0x00,0xf8,0x00,' +` 0xd9,0x00,0xd4,0x00,0xbb,0x00,0xcb,0x00,' +` 0x98,0x00,0x87,0x00,0x70,0x00,0x63,0x00,' +` 0x4f,0x00,0x44,0x00,0x33,0x00,0x2a,0x00,' +` 0x1e,0x00,0x16,0x00,0x0e,0x00,0x09,0x00,' +` 0x05,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x70,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x55,0x00,0xa0,0x00,' +` 0x7e,0x00,0x41,0x01,0xdf,0x00,0x9c,0x01,' +` 0x24,0x01,0x09,0x02,0x6f,0x01,0x85,0x02,' +` 0xc1,0x01,0x0c,0x03,0x16,0x02,0x9f,0x03,' +` 0x6e,0x02,0x3c,0x04,0xc4,0x02,0xe0,0x04,' +` 0x16,0x03,0x8a,0x05,0x64,0x03,0x19,0x06,' +` 0x2e,0x03,0x99,0x06,0x54,0x03,0x4c,0x07,' +` 0x5b,0x03,0x09,0x08,0x3d,0x03,0xd6,0x08,' +` 0xee,0x02,0xc0,0x09,0x56,0x02,0xe6,0x0a,' +` 0x45,0x01,0x8a,0x0c,0x4b,0xff,0x71,0x0f,' +` 0xf2,0xfa,0xd9,0x16,0xbc,0xea,0x7e,0x5f,' +` 0xba,0x4f,0x34,0xec,0xbf,0x15,0xab,0xfa,' +` 0x71,0x0e,0x82,0xfe,0x55,0x0b,0x23,0x00,' +` 0x74,0x09,0xec,0x00,0x17,0x08,0x4c,0x01,' +` 0xff,0x06,0x71,0x01,0x0f,0x06,0x72,0x01,' +` 0x3b,0x05,0x60,0x01,0x79,0x04,0x49,0x01,' +` 0x19,0x03,0xdf,0xff,0x40,0x02,0xd6,0xff,' +` 0xc5,0x01,0xc5,0xff,0x5f,0x01,0xb5,0xff,' +` 0x09,0x01,0xaa,0xff,0xc3,0x00,0xa3,0xff,' +` 0x89,0x00,0xa2,0xff,0x5c,0x00,0xa5,0xff,' +` 0x3a,0x00,0xad,0xff,0x1f,0x00,0xc8,0xff,' +` 0x24,0x00,0xc0,0xff,0x09,0x00,0xcf,0xff,' +` 0x02,0x00,0xdc,0xff,0xff,0xff,0xe8,0xff,' +` 0xfe,0xff,0xf2,0xff,0xff,0xff,0xfa,0xff,' +` 0xff,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0xa2,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_68mm_pm0_30_90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_pm0_30_90deg_16khz.m4 new file mode 100644 index 000000000000..5c0aba6abbb2 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_pm0_30_90deg_16khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf9,0xff,' +` 0xf5,0xff,0xf7,0xff,0xf8,0xff,0x05,0x00,' +` 0x0e,0x00,0x2e,0x00,0x44,0x00,0x7d,0x00,' +` 0xa7,0x00,0xff,0x00,0x39,0x01,0xb9,0x01,' +` 0x02,0x02,0xa4,0x02,0xf8,0x02,0xb7,0x03,' +` 0x10,0x04,0xd8,0x04,0xde,0x05,0x99,0x07,' +` 0x72,0x07,0xc7,0x08,0x69,0x08,0xe4,0x09,' +` 0x01,0x09,0xf6,0x0a,0xd0,0x08,0x48,0x0d,' +` 0x26,0x4a,0xb1,0x07,0x5f,0x0b,0xed,0x08,' +` 0x05,0x0a,0x7d,0x08,0xd5,0x08,0x9d,0x07,' +` 0x8a,0x07,0x8f,0x06,0x77,0x05,0x02,0x04,' +` 0xe5,0x03,0xfd,0x02,0xc2,0x02,0x0a,0x02,' +` 0xce,0x01,0x3f,0x01,0x0d,0x01,0xa5,0x00,' +` 0x7d,0x00,0x43,0x00,0x30,0x00,0x0c,0x00,' +` 0x05,0x00,0xf6,0xff,0xf7,0xff,0xf4,0xff,' +` 0xf9,0xff,0xfb,0xff,0xff,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x06,0x00,0x0f,0x00,0x13,0x00,0x15,0x00,' +` 0x0d,0x00,0xfd,0xff,0xdc,0xff,0xb1,0xff,' +` 0x6c,0xff,0x1c,0xff,0x9e,0xfe,0x21,0xfe,' +` 0x73,0xfd,0xb9,0xfc,0xd3,0xfb,0xf2,0xfa,' +` 0xd9,0xf9,0xe0,0xf8,0x92,0xf7,0xba,0xf6,' +` 0xf7,0xf3,0x55,0xf1,0x8a,0xf0,0x2c,0xef,' +` 0x59,0xee,0x49,0xed,0xaa,0xec,0xeb,0xeb,' +` 0x97,0xeb,0x30,0xeb,0x27,0x6b,0x5c,0xeb,' +` 0xe7,0xeb,0x5f,0xec,0x3d,0xed,0xfd,0xed,' +` 0x24,0xef,0x11,0xf0,0x7a,0xf1,0x5d,0xf2,' +` 0x5b,0xf5,0x9f,0xf7,0x7c,0xf8,0xbe,0xf9,' +` 0xad,0xfa,0xb6,0xfb,0x88,0xfc,0x5b,0xfd,' +` 0xff,0xfd,0x9b,0xfe,0x16,0xff,0x69,0xff,' +` 0xaa,0xff,0xdd,0xff,0xfb,0xff,0x0f,0x00,' +` 0x15,0x00,0x15,0x00,0x0f,0x00,0x09,0x00,' +` 0x02,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x06,0x00,0x0f,0x00,' +` 0x13,0x00,0x15,0x00,0x0d,0x00,0xfd,0xff,' +` 0xdc,0xff,0xb1,0xff,0x6c,0xff,0x1c,0xff,' +` 0x9e,0xfe,0x21,0xfe,0x73,0xfd,0xb9,0xfc,' +` 0xd3,0xfb,0xf2,0xfa,0xd9,0xf9,0xe0,0xf8,' +` 0x92,0xf7,0xba,0xf6,0xf7,0xf3,0x55,0xf1,' +` 0x8a,0xf0,0x2c,0xef,0x59,0xee,0x49,0xed,' +` 0xaa,0xec,0xeb,0xeb,0x97,0xeb,0x30,0xeb,' +` 0x27,0x6b,0x5c,0xeb,0xe7,0xeb,0x5f,0xec,' +` 0x3d,0xed,0xfd,0xed,0x24,0xef,0x11,0xf0,' +` 0x7a,0xf1,0x5d,0xf2,0x5b,0xf5,0x9f,0xf7,' +` 0x7c,0xf8,0xbe,0xf9,0xad,0xfa,0xb6,0xfb,' +` 0x88,0xfc,0x5b,0xfd,0xff,0xfd,0x9b,0xfe,' +` 0x16,0xff,0x69,0xff,0xaa,0xff,0xdd,0xff,' +` 0xfb,0xff,0x0f,0x00,0x15,0x00,0x15,0x00,' +` 0x0f,0x00,0x09,0x00,0x02,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf9,0xff,0xf5,0xff,0xf7,0xff,' +` 0xf8,0xff,0x05,0x00,0x0e,0x00,0x2e,0x00,' +` 0x44,0x00,0x7d,0x00,0xa7,0x00,0xff,0x00,' +` 0x39,0x01,0xb9,0x01,0x02,0x02,0xa4,0x02,' +` 0xf8,0x02,0xb7,0x03,0x10,0x04,0xd8,0x04,' +` 0xde,0x05,0x99,0x07,0x72,0x07,0xc7,0x08,' +` 0x69,0x08,0xe4,0x09,0x01,0x09,0xf6,0x0a,' +` 0xd0,0x08,0x48,0x0d,0x26,0x4a,0xb1,0x07,' +` 0x5f,0x0b,0xed,0x08,0x05,0x0a,0x7d,0x08,' +` 0xd5,0x08,0x9d,0x07,0x8a,0x07,0x8f,0x06,' +` 0x77,0x05,0x02,0x04,0xe5,0x03,0xfd,0x02,' +` 0xc2,0x02,0x0a,0x02,0xce,0x01,0x3f,0x01,' +` 0x0d,0x01,0xa5,0x00,0x7d,0x00,0x43,0x00,' +` 0x30,0x00,0x0c,0x00,0x05,0x00,0xf6,0xff,' +` 0xf7,0xff,0xf4,0xff,0xf9,0xff,0xfb,0xff,' +` 0xff,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf9,0xff,' +` 0xf5,0xff,0xf7,0xff,0xf8,0xff,0x05,0x00,' +` 0x0e,0x00,0x2e,0x00,0x44,0x00,0x7d,0x00,' +` 0xa7,0x00,0xff,0x00,0x39,0x01,0xb9,0x01,' +` 0x02,0x02,0xa4,0x02,0xf8,0x02,0xb7,0x03,' +` 0x10,0x04,0xd8,0x04,0xde,0x05,0x99,0x07,' +` 0x72,0x07,0xc7,0x08,0x69,0x08,0xe4,0x09,' +` 0x01,0x09,0xf6,0x0a,0xd0,0x08,0x48,0x0d,' +` 0x26,0x4a,0xb1,0x07,0x5f,0x0b,0xed,0x08,' +` 0x05,0x0a,0x7d,0x08,0xd5,0x08,0x9d,0x07,' +` 0x8a,0x07,0x8f,0x06,0x77,0x05,0x02,0x04,' +` 0xe5,0x03,0xfd,0x02,0xc2,0x02,0x0a,0x02,' +` 0xce,0x01,0x3f,0x01,0x0d,0x01,0xa5,0x00,' +` 0x7d,0x00,0x43,0x00,0x30,0x00,0x0c,0x00,' +` 0x05,0x00,0xf6,0xff,0xf7,0xff,0xf4,0xff,' +` 0xf9,0xff,0xfb,0xff,0xff,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x06,0x00,0x0f,0x00,0x13,0x00,0x15,0x00,' +` 0x0d,0x00,0xfd,0xff,0xdc,0xff,0xb1,0xff,' +` 0x6c,0xff,0x1c,0xff,0x9e,0xfe,0x21,0xfe,' +` 0x73,0xfd,0xb9,0xfc,0xd3,0xfb,0xf2,0xfa,' +` 0xd9,0xf9,0xe0,0xf8,0x92,0xf7,0xba,0xf6,' +` 0xf7,0xf3,0x55,0xf1,0x8a,0xf0,0x2c,0xef,' +` 0x59,0xee,0x49,0xed,0xaa,0xec,0xeb,0xeb,' +` 0x97,0xeb,0x30,0xeb,0x27,0x6b,0x5c,0xeb,' +` 0xe7,0xeb,0x5f,0xec,0x3d,0xed,0xfd,0xed,' +` 0x24,0xef,0x11,0xf0,0x7a,0xf1,0x5d,0xf2,' +` 0x5b,0xf5,0x9f,0xf7,0x7c,0xf8,0xbe,0xf9,' +` 0xad,0xfa,0xb6,0xfb,0x88,0xfc,0x5b,0xfd,' +` 0xff,0xfd,0x9b,0xfe,0x16,0xff,0x69,0xff,' +` 0xaa,0xff,0xdd,0xff,0xfb,0xff,0x0f,0x00,' +` 0x15,0x00,0x15,0x00,0x0f,0x00,0x09,0x00,' +` 0x02,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x06,0x00,0x0f,0x00,' +` 0x13,0x00,0x15,0x00,0x0d,0x00,0xfd,0xff,' +` 0xdc,0xff,0xb1,0xff,0x6c,0xff,0x1c,0xff,' +` 0x9e,0xfe,0x21,0xfe,0x73,0xfd,0xb9,0xfc,' +` 0xd3,0xfb,0xf2,0xfa,0xd9,0xf9,0xe0,0xf8,' +` 0x92,0xf7,0xba,0xf6,0xf7,0xf3,0x55,0xf1,' +` 0x8a,0xf0,0x2c,0xef,0x59,0xee,0x49,0xed,' +` 0xaa,0xec,0xeb,0xeb,0x97,0xeb,0x30,0xeb,' +` 0x27,0x6b,0x5c,0xeb,0xe7,0xeb,0x5f,0xec,' +` 0x3d,0xed,0xfd,0xed,0x24,0xef,0x11,0xf0,' +` 0x7a,0xf1,0x5d,0xf2,0x5b,0xf5,0x9f,0xf7,' +` 0x7c,0xf8,0xbe,0xf9,0xad,0xfa,0xb6,0xfb,' +` 0x88,0xfc,0x5b,0xfd,0xff,0xfd,0x9b,0xfe,' +` 0x16,0xff,0x69,0xff,0xaa,0xff,0xdd,0xff,' +` 0xfb,0xff,0x0f,0x00,0x15,0x00,0x15,0x00,' +` 0x0f,0x00,0x09,0x00,0x02,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf9,0xff,0xf5,0xff,0xf7,0xff,' +` 0xf8,0xff,0x05,0x00,0x0e,0x00,0x2e,0x00,' +` 0x44,0x00,0x7d,0x00,0xa7,0x00,0xff,0x00,' +` 0x39,0x01,0xb9,0x01,0x02,0x02,0xa4,0x02,' +` 0xf8,0x02,0xb7,0x03,0x10,0x04,0xd8,0x04,' +` 0xde,0x05,0x99,0x07,0x72,0x07,0xc7,0x08,' +` 0x69,0x08,0xe4,0x09,0x01,0x09,0xf6,0x0a,' +` 0xd0,0x08,0x48,0x0d,0x26,0x4a,0xb1,0x07,' +` 0x5f,0x0b,0xed,0x08,0x05,0x0a,0x7d,0x08,' +` 0xd5,0x08,0x9d,0x07,0x8a,0x07,0x8f,0x06,' +` 0x77,0x05,0x02,0x04,0xe5,0x03,0xfd,0x02,' +` 0xc2,0x02,0x0a,0x02,0xce,0x01,0x3f,0x01,' +` 0x0d,0x01,0xa5,0x00,0x7d,0x00,0x43,0x00,' +` 0x30,0x00,0x0c,0x00,0x05,0x00,0xf6,0xff,' +` 0xf7,0xff,0xf4,0xff,0xf9,0xff,0xfb,0xff,' +` 0xff,0xff,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfd,0xff,0xfb,0xff,0xfb,0xff,0xfb,0xff,' +` 0xfe,0xff,0x08,0x00,0x1a,0x00,0x11,0x00,' +` 0x08,0x00,0x20,0x00,0x30,0x00,0x50,0x00,' +` 0x65,0x00,0xac,0x00,0x31,0x01,0x6d,0x01,' +` 0xbc,0x01,0x01,0x02,0x5e,0x02,0x33,0x02,' +` 0x90,0x02,0x06,0x03,0x4f,0x05,0x68,0x06,' +` 0xfa,0x06,0xc9,0x07,0x67,0x08,0x16,0x09,' +` 0x87,0x09,0xfc,0x09,0x37,0x4a,0x86,0x0a,' +` 0x9c,0x0a,0xa7,0x0a,0x7d,0x0a,0x42,0x0a,' +` 0xcb,0x09,0x3c,0x09,0x91,0x08,0x65,0x08,' +` 0x91,0x07,0xa2,0x06,0x61,0x04,0x80,0x03,' +` 0xda,0x02,0x41,0x02,0xad,0x01,0x72,0x01,' +` 0x28,0x01,0xc4,0x00,0x82,0x00,0x45,0x00,' +` 0x21,0x00,0xf8,0xff,0xda,0xff,0xe4,0xff,' +` 0xf0,0xff,0xf3,0xff,0xf8,0xff,0xfc,0xff,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,' +` 0xfe,0xff,0xea,0xff,0xf5,0xff,0xc2,0xff,' +` 0xed,0xff,0x91,0xff,0x0c,0x00,0x62,0xff,' +` 0xd6,0xff,0xf0,0xfe,0x18,0x00,0xcb,0xfe,' +` 0x91,0x00,0xb5,0xfe,0xc8,0x01,0x59,0xff,' +` 0x73,0x02,0xc2,0xfe,0xd4,0x02,0xd2,0xfc,' +` 0x0d,0x01,0xf1,0xf9,0x63,0xff,0x53,0xf4,' +` 0x67,0xfd,0xcd,0xee,0xbc,0xfc,0x99,0xe6,' +` 0x59,0x00,0x3d,0xd2,0xf4,0x45,0x94,0x32,' +` 0x66,0xcf,0xf4,0xf6,0x43,0xdc,0x32,0xef,' +` 0xd5,0xe0,0x91,0xed,0xdb,0xe4,0x5b,0xef,' +` 0xa2,0xea,0xff,0xf1,0xb2,0xef,0x40,0xf6,' +` 0x4e,0xf4,0x44,0xf9,0x34,0xf8,0x3e,0xfc,' +` 0x23,0xfc,0xab,0xfe,0x4e,0xfe,0xf3,0xff,' +` 0xa1,0xff,0x88,0x00,0x0c,0x00,0x6f,0x00,' +` 0x2b,0x00,0x44,0x00,0x1b,0x00,0x15,0x00,' +` 0x04,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x04,0x00,0x12,0x00,0x1d,0x00,' +` 0x38,0x00,0x31,0x00,0x53,0x00,0x1a,0x00,' +` 0x48,0x00,0xd2,0xff,0xa5,0xff,0x9b,0xfe,' +` 0x39,0xfe,0x9b,0xfc,0xc0,0xfb,0xe2,0xf8,' +` 0x6e,0xf8,0x44,0xf5,0x1b,0xf5,0x12,0xf1,' +` 0x77,0xf0,0x69,0xec,0x7d,0xed,0xa4,0xe7,' +` 0x5b,0xea,0xbe,0xe4,0x35,0xea,0xbc,0xe2,' +` 0x58,0xed,0x98,0xdf,0x1c,0xfe,0xdd,0x67,' +` 0xb6,0xde,0xfe,0xf7,0x92,0xec,0x09,0xf8,' +` 0x95,0xf2,0x4c,0xfa,0x04,0xf7,0x2b,0xfd,' +` 0xf4,0xfb,0x97,0xff,0x19,0xfe,0xad,0x01,' +` 0x14,0x00,0xbc,0x01,0x52,0x00,0x6f,0x01,' +` 0xa6,0xff,0x33,0x00,0x68,0xff,0xdc,0xff,' +` 0x5b,0xff,0xaf,0xff,0x97,0xff,0xfa,0xff,' +` 0xbb,0xff,0xe2,0xff,0xd5,0xff,0xf0,0xff,' +` 0xf1,0xff,0xfd,0xff,0xff,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfb,0xff,0xfc,0xff,' +` 0xf0,0xff,0xfc,0xff,0xe2,0xff,0xf1,0xff,' +` 0xe2,0xff,0x47,0x00,0x2a,0x00,0xba,0x00,' +` 0x9b,0x00,0x76,0x01,0x47,0x01,0x2d,0x02,' +` 0xd7,0x01,0x72,0x03,0xf7,0x02,0xfd,0x04,' +` 0x81,0x05,0xb7,0x08,0x43,0x07,0x64,0x0a,' +` 0x7e,0x07,0xf7,0x0b,0xc4,0x07,0xc9,0x0d,' +` 0x74,0x06,0xec,0x10,0x45,0xff,0x4f,0x44,' +` 0x85,0x1c,0xa7,0x01,0x0f,0x0e,0xe0,0x04,' +` 0x87,0x0a,0xd4,0x04,0x1f,0x08,0x13,0x04,' +` 0x90,0x04,0x53,0x01,0x05,0x03,0x31,0x01,' +` 0xb5,0x02,0xff,0x00,0xe6,0x01,0xa9,0x00,' +` 0x15,0x01,0xfc,0xff,0x87,0x00,0xe7,0xff,' +` 0x43,0x00,0xd9,0xff,0x1b,0x00,0xf8,0xff,' +` 0x16,0x00,0xed,0xff,0x01,0x00,0xf4,0xff,' +` 0xfd,0xff,0xfc,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfb,0xff,0xfc,0xff,0xf0,0xff,0xfc,0xff,' +` 0xe2,0xff,0xf1,0xff,0xe2,0xff,0x47,0x00,' +` 0x2a,0x00,0xba,0x00,0x9b,0x00,0x76,0x01,' +` 0x47,0x01,0x2d,0x02,0xd7,0x01,0x72,0x03,' +` 0xf7,0x02,0xfd,0x04,0x81,0x05,0xb7,0x08,' +` 0x43,0x07,0x64,0x0a,0x7e,0x07,0xf7,0x0b,' +` 0xc4,0x07,0xc9,0x0d,0x74,0x06,0xec,0x10,' +` 0x45,0xff,0x4f,0x44,0x85,0x1c,0xa7,0x01,' +` 0x0f,0x0e,0xe0,0x04,0x87,0x0a,0xd4,0x04,' +` 0x1f,0x08,0x13,0x04,0x90,0x04,0x53,0x01,' +` 0x05,0x03,0x31,0x01,0xb5,0x02,0xff,0x00,' +` 0xe6,0x01,0xa9,0x00,0x15,0x01,0xfc,0xff,' +` 0x87,0x00,0xe7,0xff,0x43,0x00,0xd9,0xff,' +` 0x1b,0x00,0xf8,0xff,0x16,0x00,0xed,0xff,' +` 0x01,0x00,0xf4,0xff,0xfd,0xff,0xfc,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0x12,0x00,0x1d,0x00,0x38,0x00,0x31,0x00,' +` 0x53,0x00,0x1a,0x00,0x48,0x00,0xd2,0xff,' +` 0xa5,0xff,0x9b,0xfe,0x39,0xfe,0x9b,0xfc,' +` 0xc0,0xfb,0xe2,0xf8,0x6e,0xf8,0x44,0xf5,' +` 0x1b,0xf5,0x12,0xf1,0x77,0xf0,0x69,0xec,' +` 0x7d,0xed,0xa4,0xe7,0x5b,0xea,0xbe,0xe4,' +` 0x35,0xea,0xbc,0xe2,0x58,0xed,0x98,0xdf,' +` 0x1c,0xfe,0xdd,0x67,0xb6,0xde,0xfe,0xf7,' +` 0x92,0xec,0x09,0xf8,0x95,0xf2,0x4c,0xfa,' +` 0x04,0xf7,0x2b,0xfd,0xf4,0xfb,0x97,0xff,' +` 0x19,0xfe,0xad,0x01,0x14,0x00,0xbc,0x01,' +` 0x52,0x00,0x6f,0x01,0xa6,0xff,0x33,0x00,' +` 0x68,0xff,0xdc,0xff,0x5b,0xff,0xaf,0xff,' +` 0x97,0xff,0xfa,0xff,0xbb,0xff,0xe2,0xff,' +` 0xd5,0xff,0xf0,0xff,0xf1,0xff,0xfd,0xff,' +` 0xff,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfe,0xff,0xfe,0xff,0xea,0xff,' +` 0xf5,0xff,0xc2,0xff,0xed,0xff,0x91,0xff,' +` 0x0c,0x00,0x62,0xff,0xd6,0xff,0xf0,0xfe,' +` 0x18,0x00,0xcb,0xfe,0x91,0x00,0xb5,0xfe,' +` 0xc8,0x01,0x59,0xff,0x73,0x02,0xc2,0xfe,' +` 0xd4,0x02,0xd2,0xfc,0x0d,0x01,0xf1,0xf9,' +` 0x63,0xff,0x53,0xf4,0x67,0xfd,0xcd,0xee,' +` 0xbc,0xfc,0x99,0xe6,0x59,0x00,0x3d,0xd2,' +` 0xf4,0x45,0x94,0x32,0x66,0xcf,0xf4,0xf6,' +` 0x43,0xdc,0x32,0xef,0xd5,0xe0,0x91,0xed,' +` 0xdb,0xe4,0x5b,0xef,0xa2,0xea,0xff,0xf1,' +` 0xb2,0xef,0x40,0xf6,0x4e,0xf4,0x44,0xf9,' +` 0x34,0xf8,0x3e,0xfc,0x23,0xfc,0xab,0xfe,' +` 0x4e,0xfe,0xf3,0xff,0xa1,0xff,0x88,0x00,' +` 0x0c,0x00,0x6f,0x00,0x2b,0x00,0x44,0x00,' +` 0x1b,0x00,0x15,0x00,0x04,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfd,0xff,0xfb,0xff,' +` 0xfb,0xff,0xfb,0xff,0xfe,0xff,0x08,0x00,' +` 0x1a,0x00,0x11,0x00,0x08,0x00,0x20,0x00,' +` 0x30,0x00,0x50,0x00,0x65,0x00,0xac,0x00,' +` 0x31,0x01,0x6d,0x01,0xbc,0x01,0x01,0x02,' +` 0x5e,0x02,0x33,0x02,0x90,0x02,0x06,0x03,' +` 0x4f,0x05,0x68,0x06,0xfa,0x06,0xc9,0x07,' +` 0x67,0x08,0x16,0x09,0x87,0x09,0xfc,0x09,' +` 0x37,0x4a,0x86,0x0a,0x9c,0x0a,0xa7,0x0a,' +` 0x7d,0x0a,0x42,0x0a,0xcb,0x09,0x3c,0x09,' +` 0x91,0x08,0x65,0x08,0x91,0x07,0xa2,0x06,' +` 0x61,0x04,0x80,0x03,0xda,0x02,0x41,0x02,' +` 0xad,0x01,0x72,0x01,0x28,0x01,0xc4,0x00,' +` 0x82,0x00,0x45,0x00,0x21,0x00,0xf8,0xff,' +` 0xda,0xff,0xe4,0xff,0xf0,0xff,0xf3,0xff,' +` 0xf8,0xff,0xfc,0xff,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfd,0xff,' +` 0xf9,0xff,0xf4,0xff,0xef,0xff,0xd9,0xff,' +` 0xc4,0xff,0xb4,0xff,0x9e,0xff,0x8a,0xff,' +` 0x71,0xff,0x70,0xff,0x5e,0xff,0x4a,0xff,' +` 0x3a,0xff,0x3a,0xff,0x3a,0xff,0x6e,0xff,' +` 0xb9,0xff,0xbb,0xff,0x3b,0x00,0x91,0x00,' +` 0x46,0x01,0xa9,0x01,0x29,0x03,0x9e,0x05,' +` 0x2f,0x06,0x1a,0x07,0xbb,0x07,0x7c,0x08,' +` 0xfd,0x08,0x7b,0x49,0xc4,0x09,0xf1,0x09,' +` 0xdf,0x09,0xbb,0x09,0x61,0x09,0xed,0x08,' +` 0xc8,0x08,0x69,0x08,0x78,0x07,0xcd,0x06,' +` 0xc9,0x05,0x2e,0x05,0xaf,0x03,0x6f,0x02,' +` 0x13,0x02,0x7b,0x01,0x1a,0x01,0xb7,0x00,' +` 0x73,0x00,0x41,0x00,0x45,0x00,0x22,0x00,' +` 0x11,0x00,0x02,0x00,0xfe,0xff,0xf8,0xff,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf2,0xff,0xec,0xff,' +` 0xd5,0xff,0xe1,0xff,0xa9,0xff,0xd9,0xff,' +` 0xbf,0xff,0x43,0x00,0x37,0x00,0x29,0x01,' +` 0x4a,0x01,0xbc,0x02,0xb7,0x02,0x96,0x04,' +` 0x45,0x04,0x66,0x06,0xba,0x05,0x11,0x08,' +` 0x71,0x05,0x04,0x08,0x31,0x04,0xdd,0x06,' +` 0x43,0x01,0xe1,0x03,0x7f,0xfa,0x8d,0xff,' +` 0x03,0xf3,0xc5,0xfc,0xdc,0xe6,0xba,0x08,' +` 0x45,0x66,0x65,0xd8,0x8b,0xf1,0x33,0xe0,' +` 0x2f,0xea,0x41,0xe1,0xef,0xe7,0x66,0xe4,' +` 0x6a,0xea,0x15,0xe8,0x38,0xed,0x97,0xec,' +` 0x15,0xf1,0x0e,0xf2,0x49,0xf7,0xa6,0xf7,' +` 0xd4,0xfa,0x55,0xfb,0xa7,0xfd,0x0b,0xfe,' +` 0x85,0xff,0x92,0xff,0x6c,0x00,0x5d,0x00,' +` 0xb2,0x00,0x87,0x00,0x83,0x00,0x45,0x00,' +` 0x36,0x00,0x16,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x1a,0x00,0x27,0x00,' +` 0x58,0x00,0x5f,0x00,0xa5,0x00,0x51,0x00,' +` 0x96,0x00,0xb8,0xff,0xf6,0xff,0x72,0xfe,' +` 0x95,0xfe,0x06,0xfc,0x37,0xfc,0x91,0xf8,' +` 0x1b,0xf9,0xe8,0xf3,0x7a,0xf3,0x8b,0xed,' +` 0xa7,0xef,0x9d,0xe8,0xc8,0xec,0x66,0xe4,' +` 0xe4,0xea,0x7f,0xdf,0xb8,0xec,0xe1,0xdc,' +` 0xa4,0xf4,0xd8,0xd3,0xe2,0x21,0x69,0x56,' +` 0x1e,0xd6,0x1d,0x03,0x4e,0xec,0xea,0x01,' +` 0x43,0xf6,0xa4,0x04,0x4e,0xfe,0x1a,0x08,' +` 0x67,0x02,0x30,0x09,0x87,0x04,0x13,0x09,' +` 0x84,0x05,0xd7,0x07,0x39,0x04,0xd4,0x05,' +` 0xd8,0x02,0xba,0x03,0x6c,0x01,0xe5,0x01,' +` 0x36,0x00,0xa6,0x00,0xa9,0xff,0x02,0x00,' +` 0x80,0xff,0xde,0xff,0xbc,0xff,0xe5,0xff,' +` 0xe0,0xff,0xf6,0xff,0xfc,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xd7,0xff,0xfb,0xff,' +` 0xd5,0xff,0x2e,0x00,0xd3,0xff,0x89,0x00,' +` 0x0a,0x00,0x1e,0x01,0x05,0x00,0x10,0x02,' +` 0xf0,0x00,0xdf,0x03,0x5d,0x02,0x5b,0x06,' +` 0x22,0x04,0xbb,0x0b,0xc8,0x08,0xeb,0x0f,' +` 0x44,0x0b,0x3f,0x14,0x08,0x0d,0x95,0x17,' +` 0xa6,0x0b,0x13,0x1c,0x6f,0x08,0x2b,0x24,' +` 0x7f,0xf8,0x73,0x67,0x41,0x61,0xcf,0xf6,' +` 0xf7,0x1f,0x94,0x03,0x90,0x15,0x00,0x05,' +` 0x8f,0x0e,0x56,0xff,0xfe,0x06,0x44,0xfe,' +` 0xb9,0x03,0x5f,0xfd,0x92,0x01,0x6f,0xfd,' +` 0x2e,0x00,0x31,0xfd,0xa6,0xff,0xa4,0xfd,' +` 0x87,0xff,0x3f,0xfe,0x7e,0xff,0xa0,0xfe,' +` 0x97,0xff,0x21,0xff,0xbd,0xff,0x83,0xff,' +` 0xed,0xff,0xdb,0xff,0xfa,0xff,0xf6,0xff,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xd7,0xff,0xfb,0xff,0xd5,0xff,0x2e,0x00,' +` 0xd3,0xff,0x89,0x00,0x0a,0x00,0x1e,0x01,' +` 0x05,0x00,0x10,0x02,0xf0,0x00,0xdf,0x03,' +` 0x5d,0x02,0x5b,0x06,0x22,0x04,0xbb,0x0b,' +` 0xc8,0x08,0xeb,0x0f,0x44,0x0b,0x3f,0x14,' +` 0x08,0x0d,0x95,0x17,0xa6,0x0b,0x13,0x1c,' +` 0x6f,0x08,0x2b,0x24,0x7f,0xf8,0x73,0x67,' +` 0x41,0x61,0xcf,0xf6,0xf7,0x1f,0x94,0x03,' +` 0x90,0x15,0x00,0x05,0x8f,0x0e,0x56,0xff,' +` 0xfe,0x06,0x44,0xfe,0xb9,0x03,0x5f,0xfd,' +` 0x92,0x01,0x6f,0xfd,0x2e,0x00,0x31,0xfd,' +` 0xa6,0xff,0xa4,0xfd,0x87,0xff,0x3f,0xfe,' +` 0x7e,0xff,0xa0,0xfe,0x97,0xff,0x21,0xff,' +` 0xbd,0xff,0x83,0xff,0xed,0xff,0xdb,0xff,' +` 0xfa,0xff,0xf6,0xff,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x1a,0x00,0x27,0x00,0x58,0x00,0x5f,0x00,' +` 0xa5,0x00,0x51,0x00,0x96,0x00,0xb8,0xff,' +` 0xf6,0xff,0x72,0xfe,0x95,0xfe,0x06,0xfc,' +` 0x37,0xfc,0x91,0xf8,0x1b,0xf9,0xe8,0xf3,' +` 0x7a,0xf3,0x8b,0xed,0xa7,0xef,0x9d,0xe8,' +` 0xc8,0xec,0x66,0xe4,0xe4,0xea,0x7f,0xdf,' +` 0xb8,0xec,0xe1,0xdc,0xa4,0xf4,0xd8,0xd3,' +` 0xe2,0x21,0x69,0x56,0x1e,0xd6,0x1d,0x03,' +` 0x4e,0xec,0xea,0x01,0x43,0xf6,0xa4,0x04,' +` 0x4e,0xfe,0x1a,0x08,0x67,0x02,0x30,0x09,' +` 0x87,0x04,0x13,0x09,0x84,0x05,0xd7,0x07,' +` 0x39,0x04,0xd4,0x05,0xd8,0x02,0xba,0x03,' +` 0x6c,0x01,0xe5,0x01,0x36,0x00,0xa6,0x00,' +` 0xa9,0xff,0x02,0x00,0x80,0xff,0xde,0xff,' +` 0xbc,0xff,0xe5,0xff,0xe0,0xff,0xf6,0xff,' +` 0xfc,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf2,0xff,0xec,0xff,0xd5,0xff,0xe1,0xff,' +` 0xa9,0xff,0xd9,0xff,0xbf,0xff,0x43,0x00,' +` 0x37,0x00,0x29,0x01,0x4a,0x01,0xbc,0x02,' +` 0xb7,0x02,0x96,0x04,0x45,0x04,0x66,0x06,' +` 0xba,0x05,0x11,0x08,0x71,0x05,0x04,0x08,' +` 0x31,0x04,0xdd,0x06,0x43,0x01,0xe1,0x03,' +` 0x7f,0xfa,0x8d,0xff,0x03,0xf3,0xc5,0xfc,' +` 0xdc,0xe6,0xba,0x08,0x45,0x66,0x65,0xd8,' +` 0x8b,0xf1,0x33,0xe0,0x2f,0xea,0x41,0xe1,' +` 0xef,0xe7,0x66,0xe4,0x6a,0xea,0x15,0xe8,' +` 0x38,0xed,0x97,0xec,0x15,0xf1,0x0e,0xf2,' +` 0x49,0xf7,0xa6,0xf7,0xd4,0xfa,0x55,0xfb,' +` 0xa7,0xfd,0x0b,0xfe,0x85,0xff,0x92,0xff,' +` 0x6c,0x00,0x5d,0x00,0xb2,0x00,0x87,0x00,' +` 0x83,0x00,0x45,0x00,0x36,0x00,0x16,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfd,0xff,0xf9,0xff,0xf4,0xff,' +` 0xef,0xff,0xd9,0xff,0xc4,0xff,0xb4,0xff,' +` 0x9e,0xff,0x8a,0xff,0x71,0xff,0x70,0xff,' +` 0x5e,0xff,0x4a,0xff,0x3a,0xff,0x3a,0xff,' +` 0x3a,0xff,0x6e,0xff,0xb9,0xff,0xbb,0xff,' +` 0x3b,0x00,0x91,0x00,0x46,0x01,0xa9,0x01,' +` 0x29,0x03,0x9e,0x05,0x2f,0x06,0x1a,0x07,' +` 0xbb,0x07,0x7c,0x08,0xfd,0x08,0x7b,0x49,' +` 0xc4,0x09,0xf1,0x09,0xdf,0x09,0xbb,0x09,' +` 0x61,0x09,0xed,0x08,0xc8,0x08,0x69,0x08,' +` 0x78,0x07,0xcd,0x06,0xc9,0x05,0x2e,0x05,' +` 0xaf,0x03,0x6f,0x02,0x13,0x02,0x7b,0x01,' +` 0x1a,0x01,0xb7,0x00,0x73,0x00,0x41,0x00,' +` 0x45,0x00,0x22,0x00,0x11,0x00,0x02,0x00,' +` 0xfe,0xff,0xf8,0xff,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xa2,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_68mm_pm0_30_90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_pm0_30_90deg_48khz.m4 new file mode 100644 index 000000000000..35abb4e2f0d1 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_68mm_pm0_30_90deg_48khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x06,0x00,0x12,0x00,' +` 0x1a,0x00,0x32,0x00,0x3a,0x00,0x63,0x00,' +` 0x67,0x00,0xa4,0x00,0x9e,0x00,0xf3,0x00,' +` 0xde,0x00,0x50,0x01,0x22,0x01,0xb6,0x01,' +` 0x67,0x01,0x25,0x02,0xa8,0x01,0x9a,0x02,' +` 0xe0,0x01,0x13,0x03,0x06,0x02,0x93,0x03,' +` 0x10,0x02,0x21,0x04,0xe8,0x01,0xd9,0x04,' +` 0x54,0x01,0x2c,0x06,0x2a,0xff,0xb9,0x0c,' +` 0xaf,0x41,0x5b,0xfc,0x21,0x07,0xd9,0x00,' +` 0x1f,0x05,0xb8,0x01,0x3f,0x04,0xf7,0x01,' +` 0xa1,0x03,0xf7,0x01,0x1a,0x03,0xd5,0x01,' +` 0x9c,0x02,0xa1,0x01,0x26,0x02,0x61,0x01,' +` 0xb6,0x01,0x1e,0x01,0x4e,0x01,0xda,0x00,' +` 0xf2,0x00,0x9c,0x00,0xa2,0x00,0x65,0x00,' +` 0x62,0x00,0x39,0x00,0x31,0x00,0x19,0x00,' +` 0x11,0x00,0x06,0x00,0x02,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf3,0xff,0xdf,0xff,0xc7,0xff,0xa5,0xff,' +` 0x7e,0xff,0x4e,0xff,0x19,0xff,0xda,0xfe,' +` 0x9a,0xfe,0x4f,0xfe,0x04,0xfe,0xb0,0xfd,' +` 0x5e,0xfd,0x04,0xfd,0xae,0xfc,0x52,0xfc,' +` 0xfb,0xfb,0xa0,0xfb,0x4d,0xfb,0xf6,0xfa,' +` 0xaa,0xfa,0x5d,0xfa,0x1b,0xfa,0xda,0xf9,' +` 0xa6,0xf9,0x73,0xf9,0x4f,0xf9,0x2e,0xf9,' +` 0x1c,0xf9,0x0d,0xf9,0xfb,0x78,0x19,0xf9,' +` 0x32,0xf9,0x4d,0xf9,0x78,0xf9,0xa5,0xf9,' +` 0xdf,0xf9,0x1b,0xfa,0x63,0xfa,0xab,0xfa,' +` 0xfd,0xfa,0x4e,0xfb,0xa7,0xfb,0xfd,0xfb,' +` 0x59,0xfc,0xb0,0xfc,0x0b,0xfd,0x60,0xfd,' +` 0xb6,0xfd,0x06,0xfe,0x54,0xfe,0x9b,0xfe,' +` 0xde,0xfe,0x1a,0xff,0x50,0xff,0x7f,0xff,' +` 0xa7,0xff,0xc7,0xff,0xe1,0xff,0xf2,0xff,' +` 0xfd,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf3,0xff,0xdf,0xff,' +` 0xc7,0xff,0xa5,0xff,0x7e,0xff,0x4e,0xff,' +` 0x19,0xff,0xda,0xfe,0x9a,0xfe,0x4f,0xfe,' +` 0x04,0xfe,0xb0,0xfd,0x5e,0xfd,0x04,0xfd,' +` 0xae,0xfc,0x52,0xfc,0xfb,0xfb,0xa0,0xfb,' +` 0x4d,0xfb,0xf6,0xfa,0xaa,0xfa,0x5d,0xfa,' +` 0x1b,0xfa,0xda,0xf9,0xa6,0xf9,0x73,0xf9,' +` 0x4f,0xf9,0x2e,0xf9,0x1c,0xf9,0x0d,0xf9,' +` 0xfb,0x78,0x19,0xf9,0x32,0xf9,0x4d,0xf9,' +` 0x78,0xf9,0xa5,0xf9,0xdf,0xf9,0x1b,0xfa,' +` 0x63,0xfa,0xab,0xfa,0xfd,0xfa,0x4e,0xfb,' +` 0xa7,0xfb,0xfd,0xfb,0x59,0xfc,0xb0,0xfc,' +` 0x0b,0xfd,0x60,0xfd,0xb6,0xfd,0x06,0xfe,' +` 0x54,0xfe,0x9b,0xfe,0xde,0xfe,0x1a,0xff,' +` 0x50,0xff,0x7f,0xff,0xa7,0xff,0xc7,0xff,' +` 0xe1,0xff,0xf2,0xff,0xfd,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x06,0x00,0x12,0x00,0x1a,0x00,0x32,0x00,' +` 0x3a,0x00,0x63,0x00,0x67,0x00,0xa4,0x00,' +` 0x9e,0x00,0xf3,0x00,0xde,0x00,0x50,0x01,' +` 0x22,0x01,0xb6,0x01,0x67,0x01,0x25,0x02,' +` 0xa8,0x01,0x9a,0x02,0xe0,0x01,0x13,0x03,' +` 0x06,0x02,0x93,0x03,0x10,0x02,0x21,0x04,' +` 0xe8,0x01,0xd9,0x04,0x54,0x01,0x2c,0x06,' +` 0x2a,0xff,0xb9,0x0c,0xaf,0x41,0x5b,0xfc,' +` 0x21,0x07,0xd9,0x00,0x1f,0x05,0xb8,0x01,' +` 0x3f,0x04,0xf7,0x01,0xa1,0x03,0xf7,0x01,' +` 0x1a,0x03,0xd5,0x01,0x9c,0x02,0xa1,0x01,' +` 0x26,0x02,0x61,0x01,0xb6,0x01,0x1e,0x01,' +` 0x4e,0x01,0xda,0x00,0xf2,0x00,0x9c,0x00,' +` 0xa2,0x00,0x65,0x00,0x62,0x00,0x39,0x00,' +` 0x31,0x00,0x19,0x00,0x11,0x00,0x06,0x00,' +` 0x02,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x06,0x00,0x12,0x00,' +` 0x1a,0x00,0x32,0x00,0x3a,0x00,0x63,0x00,' +` 0x67,0x00,0xa4,0x00,0x9e,0x00,0xf3,0x00,' +` 0xde,0x00,0x50,0x01,0x22,0x01,0xb6,0x01,' +` 0x67,0x01,0x25,0x02,0xa8,0x01,0x9a,0x02,' +` 0xe0,0x01,0x13,0x03,0x06,0x02,0x93,0x03,' +` 0x10,0x02,0x21,0x04,0xe8,0x01,0xd9,0x04,' +` 0x54,0x01,0x2c,0x06,0x2a,0xff,0xb9,0x0c,' +` 0xaf,0x41,0x5b,0xfc,0x21,0x07,0xd9,0x00,' +` 0x1f,0x05,0xb8,0x01,0x3f,0x04,0xf7,0x01,' +` 0xa1,0x03,0xf7,0x01,0x1a,0x03,0xd5,0x01,' +` 0x9c,0x02,0xa1,0x01,0x26,0x02,0x61,0x01,' +` 0xb6,0x01,0x1e,0x01,0x4e,0x01,0xda,0x00,' +` 0xf2,0x00,0x9c,0x00,0xa2,0x00,0x65,0x00,' +` 0x62,0x00,0x39,0x00,0x31,0x00,0x19,0x00,' +` 0x11,0x00,0x06,0x00,0x02,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf3,0xff,0xdf,0xff,0xc7,0xff,0xa5,0xff,' +` 0x7e,0xff,0x4e,0xff,0x19,0xff,0xda,0xfe,' +` 0x9a,0xfe,0x4f,0xfe,0x04,0xfe,0xb0,0xfd,' +` 0x5e,0xfd,0x04,0xfd,0xae,0xfc,0x52,0xfc,' +` 0xfb,0xfb,0xa0,0xfb,0x4d,0xfb,0xf6,0xfa,' +` 0xaa,0xfa,0x5d,0xfa,0x1b,0xfa,0xda,0xf9,' +` 0xa6,0xf9,0x73,0xf9,0x4f,0xf9,0x2e,0xf9,' +` 0x1c,0xf9,0x0d,0xf9,0xfb,0x78,0x19,0xf9,' +` 0x32,0xf9,0x4d,0xf9,0x78,0xf9,0xa5,0xf9,' +` 0xdf,0xf9,0x1b,0xfa,0x63,0xfa,0xab,0xfa,' +` 0xfd,0xfa,0x4e,0xfb,0xa7,0xfb,0xfd,0xfb,' +` 0x59,0xfc,0xb0,0xfc,0x0b,0xfd,0x60,0xfd,' +` 0xb6,0xfd,0x06,0xfe,0x54,0xfe,0x9b,0xfe,' +` 0xde,0xfe,0x1a,0xff,0x50,0xff,0x7f,0xff,' +` 0xa7,0xff,0xc7,0xff,0xe1,0xff,0xf2,0xff,' +` 0xfd,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf3,0xff,0xdf,0xff,' +` 0xc7,0xff,0xa5,0xff,0x7e,0xff,0x4e,0xff,' +` 0x19,0xff,0xda,0xfe,0x9a,0xfe,0x4f,0xfe,' +` 0x04,0xfe,0xb0,0xfd,0x5e,0xfd,0x04,0xfd,' +` 0xae,0xfc,0x52,0xfc,0xfb,0xfb,0xa0,0xfb,' +` 0x4d,0xfb,0xf6,0xfa,0xaa,0xfa,0x5d,0xfa,' +` 0x1b,0xfa,0xda,0xf9,0xa6,0xf9,0x73,0xf9,' +` 0x4f,0xf9,0x2e,0xf9,0x1c,0xf9,0x0d,0xf9,' +` 0xfb,0x78,0x19,0xf9,0x32,0xf9,0x4d,0xf9,' +` 0x78,0xf9,0xa5,0xf9,0xdf,0xf9,0x1b,0xfa,' +` 0x63,0xfa,0xab,0xfa,0xfd,0xfa,0x4e,0xfb,' +` 0xa7,0xfb,0xfd,0xfb,0x59,0xfc,0xb0,0xfc,' +` 0x0b,0xfd,0x60,0xfd,0xb6,0xfd,0x06,0xfe,' +` 0x54,0xfe,0x9b,0xfe,0xde,0xfe,0x1a,0xff,' +` 0x50,0xff,0x7f,0xff,0xa7,0xff,0xc7,0xff,' +` 0xe1,0xff,0xf2,0xff,0xfd,0xff,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x06,0x00,0x12,0x00,0x1a,0x00,0x32,0x00,' +` 0x3a,0x00,0x63,0x00,0x67,0x00,0xa4,0x00,' +` 0x9e,0x00,0xf3,0x00,0xde,0x00,0x50,0x01,' +` 0x22,0x01,0xb6,0x01,0x67,0x01,0x25,0x02,' +` 0xa8,0x01,0x9a,0x02,0xe0,0x01,0x13,0x03,' +` 0x06,0x02,0x93,0x03,0x10,0x02,0x21,0x04,' +` 0xe8,0x01,0xd9,0x04,0x54,0x01,0x2c,0x06,' +` 0x2a,0xff,0xb9,0x0c,0xaf,0x41,0x5b,0xfc,' +` 0x21,0x07,0xd9,0x00,0x1f,0x05,0xb8,0x01,' +` 0x3f,0x04,0xf7,0x01,0xa1,0x03,0xf7,0x01,' +` 0x1a,0x03,0xd5,0x01,0x9c,0x02,0xa1,0x01,' +` 0x26,0x02,0x61,0x01,0xb6,0x01,0x1e,0x01,' +` 0x4e,0x01,0xda,0x00,0xf2,0x00,0x9c,0x00,' +` 0xa2,0x00,0x65,0x00,0x62,0x00,0x39,0x00,' +` 0x31,0x00,0x19,0x00,0x11,0x00,0x06,0x00,' +` 0x02,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x06,0x00,0x0c,0x00,' +` 0x13,0x00,0x1b,0x00,0x36,0x00,0x56,0x00,' +` 0x6a,0x00,0x87,0x00,0xa2,0x00,0xc5,0x00,' +` 0xe5,0x00,0x0d,0x01,0x32,0x01,0x5e,0x01,' +` 0x86,0x01,0xb4,0x01,0xde,0x01,0x0d,0x02,' +` 0x37,0x02,0x65,0x02,0x8c,0x02,0xb4,0x02,' +` 0xd6,0x02,0xf9,0x02,0x14,0x03,0x30,0x03,' +` 0x44,0x03,0x58,0x03,0x63,0x03,0x63,0x43,' +` 0x6f,0x03,0x71,0x03,0x69,0x03,0x60,0x03,' +` 0x4f,0x03,0x3c,0x03,0x22,0x03,0x06,0x03,' +` 0xe4,0x02,0xc0,0x02,0x97,0x02,0x6e,0x02,' +` 0x40,0x02,0x12,0x02,0xe3,0x01,0xb3,0x01,' +` 0x82,0x01,0x53,0x01,0x25,0x01,0xf9,0x00,' +` 0xcf,0x00,0xa9,0x00,0x86,0x00,0x66,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0x01,0x00,0xf3,0xff,' +` 0x02,0x00,0xd8,0xff,0x02,0x00,0x9f,0xff,' +` 0xe2,0xff,0x48,0xff,0xca,0xff,0xd4,0xfe,' +` 0xa6,0xff,0x3c,0xfe,0x7a,0xff,0x7d,0xfd,' +` 0x49,0xff,0x97,0xfc,0x1c,0xff,0x85,0xfb,' +` 0xfc,0xfe,0x42,0xfa,0x00,0xff,0xbf,0xf8,' +` 0x41,0xff,0xd3,0xf6,0x0d,0x00,0x26,0xf4,' +` 0x26,0x02,0x5b,0xef,0xc6,0x08,0xbd,0xde,' +` 0x15,0x62,0xd0,0x2e,0xad,0xe3,0xcd,0x05,' +` 0x75,0xef,0xda,0xff,0x21,0xf3,0x8f,0xfd,' +` 0x2f,0xf5,0x86,0xfc,0xbb,0xf6,0x31,0xfc,' +` 0x26,0xf8,0x46,0xfc,0x79,0xf9,0x9c,0xfc,' +` 0xbb,0xfa,0x1d,0xfd,0xed,0xfb,0xb4,0xfd,' +` 0x04,0xfd,0x4e,0xfe,0xf9,0xfd,0xde,0xfe,' +` 0xc4,0xfe,0x59,0xff,0x67,0xff,0xba,0xff,' +` 0xca,0xff,0xee,0xff,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfa,0xff,0xef,0xff,0xc8,0xff,0xbb,0xff,' +` 0x63,0xff,0x5b,0xff,0xbe,0xfe,0xe3,0xfe,' +` 0xef,0xfd,0x58,0xfe,0xf6,0xfc,0xc5,0xfd,' +` 0xda,0xfb,0x37,0xfd,0xa1,0xfa,0xc4,0xfc,' +` 0x57,0xf9,0x7f,0xfc,0xf9,0xf7,0x81,0xfc,' +` 0x7d,0xf6,0xf9,0xfc,0xd5,0xf4,0x32,0xfe,' +` 0x92,0xf2,0xd5,0x00,0x69,0xee,0xb6,0x07,' +` 0x7e,0xe0,0x6e,0x3c,0x8c,0x57,0xc5,0xdd,' +` 0xfb,0x09,0xb5,0xee,0x00,0x03,0xc4,0xf3,' +` 0xb3,0x00,0x97,0xf6,0xc6,0xff,0x9a,0xf8,' +` 0x68,0xff,0x2a,0xfa,0x51,0xff,0x77,0xfb,' +` 0x60,0xff,0x8f,0xfc,0x80,0xff,0x7a,0xfd,' +` 0xa4,0xff,0x3b,0xfe,0xc6,0xff,0xd3,0xfe,' +` 0xe0,0xff,0x47,0xff,0xf3,0xff,0xac,0xff,' +` 0x07,0x00,0xd9,0xff,0x05,0x00,0xf4,0xff,' +` 0x02,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb9,0x00,0xa9,0x00,' +` 0x45,0x01,0x13,0x01,0xfc,0x01,0x8d,0x01,' +` 0xd7,0x02,0x0d,0x02,0xcf,0x03,0x87,0x02,' +` 0xdf,0x04,0xea,0x02,0x01,0x06,0x28,0x03,' +` 0x3a,0x07,0x27,0x03,0x95,0x08,0xc1,0x02,' +` 0x3a,0x0a,0xa6,0x01,0xa2,0x0c,0xe8,0xfe,' +` 0xba,0x11,0x5b,0xf5,0xcb,0x30,0xbe,0x77,' +` 0x98,0xee,0x13,0x14,0x3c,0xfd,0x49,0x0d,' +` 0x8f,0x00,0x69,0x0a,0xce,0x01,0x8d,0x08,' +` 0x45,0x02,0x14,0x07,0x50,0x02,0xcb,0x05,' +` 0x25,0x02,0xa7,0x04,0xdc,0x01,0xa3,0x03,' +` 0x84,0x01,0xbe,0x02,0x2b,0x01,0xfa,0x01,' +` 0xd7,0x00,0x57,0x01,0x8e,0x00,0xd8,0x00,' +` 0x38,0x00,0x4c,0x00,0x13,0x00,0x20,0x00,' +` 0x06,0x00,0x08,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xb9,0x00,0xa9,0x00,0x45,0x01,0x13,0x01,' +` 0xfc,0x01,0x8d,0x01,0xd7,0x02,0x0d,0x02,' +` 0xcf,0x03,0x87,0x02,0xdf,0x04,0xea,0x02,' +` 0x01,0x06,0x28,0x03,0x3a,0x07,0x27,0x03,' +` 0x95,0x08,0xc1,0x02,0x3a,0x0a,0xa6,0x01,' +` 0xa2,0x0c,0xe8,0xfe,0xba,0x11,0x5b,0xf5,' +` 0xcb,0x30,0xbe,0x77,0x98,0xee,0x13,0x14,' +` 0x3c,0xfd,0x49,0x0d,0x8f,0x00,0x69,0x0a,' +` 0xce,0x01,0x8d,0x08,0x45,0x02,0x14,0x07,' +` 0x50,0x02,0xcb,0x05,0x25,0x02,0xa7,0x04,' +` 0xdc,0x01,0xa3,0x03,0x84,0x01,0xbe,0x02,' +` 0x2b,0x01,0xfa,0x01,0xd7,0x00,0x57,0x01,' +` 0x8e,0x00,0xd8,0x00,0x38,0x00,0x4c,0x00,' +` 0x13,0x00,0x20,0x00,0x06,0x00,0x08,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfa,0xff,0xef,0xff,' +` 0xc8,0xff,0xbb,0xff,0x63,0xff,0x5b,0xff,' +` 0xbe,0xfe,0xe3,0xfe,0xef,0xfd,0x58,0xfe,' +` 0xf6,0xfc,0xc5,0xfd,0xda,0xfb,0x37,0xfd,' +` 0xa1,0xfa,0xc4,0xfc,0x57,0xf9,0x7f,0xfc,' +` 0xf9,0xf7,0x81,0xfc,0x7d,0xf6,0xf9,0xfc,' +` 0xd5,0xf4,0x32,0xfe,0x92,0xf2,0xd5,0x00,' +` 0x69,0xee,0xb6,0x07,0x7e,0xe0,0x6e,0x3c,' +` 0x8c,0x57,0xc5,0xdd,0xfb,0x09,0xb5,0xee,' +` 0x00,0x03,0xc4,0xf3,0xb3,0x00,0x97,0xf6,' +` 0xc6,0xff,0x9a,0xf8,0x68,0xff,0x2a,0xfa,' +` 0x51,0xff,0x77,0xfb,0x60,0xff,0x8f,0xfc,' +` 0x80,0xff,0x7a,0xfd,0xa4,0xff,0x3b,0xfe,' +` 0xc6,0xff,0xd3,0xfe,0xe0,0xff,0x47,0xff,' +` 0xf3,0xff,0xac,0xff,0x07,0x00,0xd9,0xff,' +` 0x05,0x00,0xf4,0xff,0x02,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0x01,0x00,0xf3,0xff,0x02,0x00,0xd8,0xff,' +` 0x02,0x00,0x9f,0xff,0xe2,0xff,0x48,0xff,' +` 0xca,0xff,0xd4,0xfe,0xa6,0xff,0x3c,0xfe,' +` 0x7a,0xff,0x7d,0xfd,0x49,0xff,0x97,0xfc,' +` 0x1c,0xff,0x85,0xfb,0xfc,0xfe,0x42,0xfa,' +` 0x00,0xff,0xbf,0xf8,0x41,0xff,0xd3,0xf6,' +` 0x0d,0x00,0x26,0xf4,0x26,0x02,0x5b,0xef,' +` 0xc6,0x08,0xbd,0xde,0x15,0x62,0xd0,0x2e,' +` 0xad,0xe3,0xcd,0x05,0x75,0xef,0xda,0xff,' +` 0x21,0xf3,0x8f,0xfd,0x2f,0xf5,0x86,0xfc,' +` 0xbb,0xf6,0x31,0xfc,0x26,0xf8,0x46,0xfc,' +` 0x79,0xf9,0x9c,0xfc,0xbb,0xfa,0x1d,0xfd,' +` 0xed,0xfb,0xb4,0xfd,0x04,0xfd,0x4e,0xfe,' +` 0xf9,0xfd,0xde,0xfe,0xc4,0xfe,0x59,0xff,' +` 0x67,0xff,0xba,0xff,0xca,0xff,0xee,0xff,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x06,0x00,0x0c,0x00,0x13,0x00,0x1b,0x00,' +` 0x36,0x00,0x56,0x00,0x6a,0x00,0x87,0x00,' +` 0xa2,0x00,0xc5,0x00,0xe5,0x00,0x0d,0x01,' +` 0x32,0x01,0x5e,0x01,0x86,0x01,0xb4,0x01,' +` 0xde,0x01,0x0d,0x02,0x37,0x02,0x65,0x02,' +` 0x8c,0x02,0xb4,0x02,0xd6,0x02,0xf9,0x02,' +` 0x14,0x03,0x30,0x03,0x44,0x03,0x58,0x03,' +` 0x63,0x03,0x63,0x43,0x6f,0x03,0x71,0x03,' +` 0x69,0x03,0x60,0x03,0x4f,0x03,0x3c,0x03,' +` 0x22,0x03,0x06,0x03,0xe4,0x02,0xc0,0x02,' +` 0x97,0x02,0x6e,0x02,0x40,0x02,0x12,0x02,' +` 0xe3,0x01,0xb3,0x01,0x82,0x01,0x53,0x01,' +` 0x25,0x01,0xf9,0x00,0xcf,0x00,0xa9,0x00,' +` 0x86,0x00,0x66,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0x04,0x00,0x07,0x00,' +` 0x0d,0x00,0x13,0x00,0x1c,0x00,0x25,0x00,' +` 0x33,0x00,0x41,0x00,0x8a,0x00,0xb4,0x00,' +` 0xcf,0x00,0xf4,0x00,0x16,0x01,0x3e,0x01,' +` 0x63,0x01,0x8d,0x01,0xb5,0x01,0xdf,0x01,' +` 0x07,0x02,0x31,0x02,0x57,0x02,0x7d,0x02,' +` 0x9f,0x02,0xc0,0x02,0xdc,0x02,0xf6,0x02,' +` 0x0b,0x03,0x1d,0x03,0x1e,0x43,0x31,0x03,' +` 0x32,0x03,0x2e,0x03,0x24,0x03,0x16,0x03,' +` 0x03,0x03,0xeb,0x02,0xcf,0x02,0xaf,0x02,' +` 0x8c,0x02,0x66,0x02,0x3d,0x02,0x13,0x02,' +` 0xe7,0x01,0xba,0x01,0x8d,0x01,0x60,0x01,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x0a,0x00,0x06,0x00,0x26,0x00,0x0b,0x00,' +` 0x4e,0x00,0x06,0x00,0x7c,0x00,0xef,0xff,' +` 0xab,0x00,0xbf,0xff,0xc5,0x00,0x2d,0xff,' +` 0xbf,0x00,0x97,0xfe,0xc0,0x00,0xc7,0xfd,' +` 0xb9,0x00,0xb9,0xfc,0xb3,0x00,0x65,0xfb,' +` 0xc2,0x00,0xbc,0xf9,0x0e,0x01,0x9a,0xf7,' +` 0xe3,0x01,0x9b,0xf4,0x0d,0x04,0x5c,0xef,' +` 0xc7,0x0a,0xbd,0xde,0xdc,0x4d,0xf9,0x47,' +` 0xe6,0xde,0xd7,0x08,0x08,0xee,0x51,0x01,' +` 0x53,0xf2,0x68,0xfe,0x97,0xf4,0x07,0xfd,' +` 0x3c,0xf6,0x6c,0xfc,0xa7,0xf7,0x4e,0xfc,' +` 0xfd,0xf8,0x85,0xfc,0x48,0xfa,0xf4,0xfc,' +` 0x85,0xfb,0x84,0xfd,0xae,0xfc,0x38,0xfe,' +` 0xd9,0xfd,0xd3,0xfe,0xaf,0xfe,0x51,0xff,' +` 0x54,0xff,0xb1,0xff,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xa3,0xff,0x6a,0xff,0x31,0xff,0xdd,0xfe,' +` 0x96,0xfe,0x29,0xfe,0xda,0xfd,0x37,0xfd,' +` 0xde,0xfc,0x47,0xfc,0x02,0xfc,0x5b,0xfb,' +` 0x30,0xfb,0x7c,0xfa,0x77,0xfa,0xb5,0xf9,' +` 0xe5,0xf9,0x11,0xf9,0x87,0xf9,0x95,0xf8,' +` 0x69,0xf9,0x3d,0xf8,0xa0,0xf9,0xf1,0xf7,' +` 0x60,0xfa,0x27,0xf7,0xa1,0xfd,0x66,0x79,' +` 0x08,0xf6,0x5a,0xfc,0x62,0xf9,0x18,0xfc,' +` 0xbd,0xfa,0x90,0xfc,0xd3,0xfb,0x36,0xfd,' +` 0xcc,0xfc,0xe5,0xfd,0xa9,0xfd,0x89,0xfe,' +` 0x69,0xfe,0x19,0xff,0x06,0xff,0x8c,0xff,' +` 0x7f,0xff,0xe0,0xff,0xd2,0xff,0x19,0x00,' +` 0x2a,0x00,0x47,0x00,0x35,0x00,0x40,0x00,' +` 0x2e,0x00,0x2e,0x00,0x1e,0x00,0x18,0x00,' +` 0x0d,0x00,0x07,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xc7,0x01,0x3c,0x04,' +` 0x19,0x02,0x5f,0x05,0x4d,0x02,0x9f,0x06,' +` 0x4e,0x02,0x00,0x08,0xfd,0x01,0x99,0x09,' +` 0x27,0x01,0xa9,0x0b,0x55,0xff,0xeb,0x0e,' +` 0x0d,0xfb,0x9b,0x16,0xd0,0xea,0x74,0x5f,' +` 0xb1,0x4f,0x47,0xec,0x85,0x15,0xc8,0xfa,' +` 0xf3,0x0d,0x96,0xfe,0x89,0x0a,0x20,0x00,' +` 0x53,0x08,0xc9,0x00,0xa3,0x06,0x05,0x01,' +` 0x3e,0x05,0x06,0x01,0x0d,0x04,0xe8,0x00,' +` 0x09,0x03,0xbc,0x00,0x2d,0x02,0x90,0x00,' +` 0x34,0x01,0xf5,0xff,0xa8,0x00,0xf6,0xff,' +` 0x5a,0x00,0xf7,0xff,0x28,0x00,0xfa,0xff,' +` 0x0c,0x00,0xfe,0xff,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xc7,0x01,0x3c,0x04,0x19,0x02,0x5f,0x05,' +` 0x4d,0x02,0x9f,0x06,0x4e,0x02,0x00,0x08,' +` 0xfd,0x01,0x99,0x09,0x27,0x01,0xa9,0x0b,' +` 0x55,0xff,0xeb,0x0e,0x0d,0xfb,0x9b,0x16,' +` 0xd0,0xea,0x74,0x5f,0xb1,0x4f,0x47,0xec,' +` 0x85,0x15,0xc8,0xfa,0xf3,0x0d,0x96,0xfe,' +` 0x89,0x0a,0x20,0x00,0x53,0x08,0xc9,0x00,' +` 0xa3,0x06,0x05,0x01,0x3e,0x05,0x06,0x01,' +` 0x0d,0x04,0xe8,0x00,0x09,0x03,0xbc,0x00,' +` 0x2d,0x02,0x90,0x00,0x34,0x01,0xf5,0xff,' +` 0xa8,0x00,0xf6,0xff,0x5a,0x00,0xf7,0xff,' +` 0x28,0x00,0xfa,0xff,0x0c,0x00,0xfe,0xff,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xa3,0xff,0x6a,0xff,' +` 0x31,0xff,0xdd,0xfe,0x96,0xfe,0x29,0xfe,' +` 0xda,0xfd,0x37,0xfd,0xde,0xfc,0x47,0xfc,' +` 0x02,0xfc,0x5b,0xfb,0x30,0xfb,0x7c,0xfa,' +` 0x77,0xfa,0xb5,0xf9,0xe5,0xf9,0x11,0xf9,' +` 0x87,0xf9,0x95,0xf8,0x69,0xf9,0x3d,0xf8,' +` 0xa0,0xf9,0xf1,0xf7,0x60,0xfa,0x27,0xf7,' +` 0xa1,0xfd,0x66,0x79,0x08,0xf6,0x5a,0xfc,' +` 0x62,0xf9,0x18,0xfc,0xbd,0xfa,0x90,0xfc,' +` 0xd3,0xfb,0x36,0xfd,0xcc,0xfc,0xe5,0xfd,' +` 0xa9,0xfd,0x89,0xfe,0x69,0xfe,0x19,0xff,' +` 0x06,0xff,0x8c,0xff,0x7f,0xff,0xe0,0xff,' +` 0xd2,0xff,0x19,0x00,0x2a,0x00,0x47,0x00,' +` 0x35,0x00,0x40,0x00,0x2e,0x00,0x2e,0x00,' +` 0x1e,0x00,0x18,0x00,0x0d,0x00,0x07,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x0a,0x00,0x06,0x00,' +` 0x26,0x00,0x0b,0x00,0x4e,0x00,0x06,0x00,' +` 0x7c,0x00,0xef,0xff,0xab,0x00,0xbf,0xff,' +` 0xc5,0x00,0x2d,0xff,0xbf,0x00,0x97,0xfe,' +` 0xc0,0x00,0xc7,0xfd,0xb9,0x00,0xb9,0xfc,' +` 0xb3,0x00,0x65,0xfb,0xc2,0x00,0xbc,0xf9,' +` 0x0e,0x01,0x9a,0xf7,0xe3,0x01,0x9b,0xf4,' +` 0x0d,0x04,0x5c,0xef,0xc7,0x0a,0xbd,0xde,' +` 0xdc,0x4d,0xf9,0x47,0xe6,0xde,0xd7,0x08,' +` 0x08,0xee,0x51,0x01,0x53,0xf2,0x68,0xfe,' +` 0x97,0xf4,0x07,0xfd,0x3c,0xf6,0x6c,0xfc,' +` 0xa7,0xf7,0x4e,0xfc,0xfd,0xf8,0x85,0xfc,' +` 0x48,0xfa,0xf4,0xfc,0x85,0xfb,0x84,0xfd,' +` 0xae,0xfc,0x38,0xfe,0xd9,0xfd,0xd3,0xfe,' +` 0xaf,0xfe,0x51,0xff,0x54,0xff,0xb1,0xff,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x04,0x00,0x07,0x00,0x0d,0x00,0x13,0x00,' +` 0x1c,0x00,0x25,0x00,0x33,0x00,0x41,0x00,' +` 0x8a,0x00,0xb4,0x00,0xcf,0x00,0xf4,0x00,' +` 0x16,0x01,0x3e,0x01,0x63,0x01,0x8d,0x01,' +` 0xb5,0x01,0xdf,0x01,0x07,0x02,0x31,0x02,' +` 0x57,0x02,0x7d,0x02,0x9f,0x02,0xc0,0x02,' +` 0xdc,0x02,0xf6,0x02,0x0b,0x03,0x1d,0x03,' +` 0x1e,0x43,0x31,0x03,0x32,0x03,0x2e,0x03,' +` 0x24,0x03,0x16,0x03,0x03,0x03,0xeb,0x02,' +` 0xcf,0x02,0xaf,0x02,0x8c,0x02,0x66,0x02,' +` 0x3d,0x02,0x13,0x02,0xe7,0x01,0xba,0x01,' +` 0x8d,0x01,0x60,0x01,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xa2,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x8b,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x75,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_78mm_azm90_90_13el0_0_13deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_azm90_90_13el0_0_13deg_16khz.m4 new file mode 100644 index 000000000000..38c0f229a85d --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_azm90_90_13el0_0_13deg_16khz.m4 @@ -0,0 +1,956 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0xa4,0x1d,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xa4,0x1d,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x15,0x00,0x10,0x00,0x2b,0x00,0x3b,0x00,' +` 0x77,0x00,0x97,0x00,0xf9,0x00,0x2e,0x01,' +` 0xa9,0x01,0x19,0x02,0x9a,0x03,0xb5,0x03,' +` 0xf4,0x04,0x03,0x05,0x6b,0x06,0x45,0x06,' +` 0xc0,0x07,0xa7,0x06,0x93,0x08,0x2d,0x07,' +` 0xa6,0x09,0xe3,0x06,0x1c,0x0b,0xa0,0x03,' +` 0x7d,0x47,0xcf,0x0d,0xb8,0x04,0xd6,0x08,' +` 0x12,0x05,0xe7,0x06,0x45,0x04,0x61,0x05,' +` 0x38,0x02,0xf0,0x01,0xc3,0x00,0x01,0x01,' +` 0x0e,0x00,0x4d,0x00,0x99,0xff,0xf9,0xff,' +` 0x88,0xff,0xa3,0xff,0x77,0xff,0xa5,0xff,' +` 0x90,0xff,0xb9,0xff,0xb5,0xff,0xd2,0xff,' +` 0xcf,0xff,0xe4,0xff,0xea,0xff,0xf6,0xff,' +` 0xfb,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x0c,0x00,' +` 0x02,0x00,0x0e,0x00,0xcb,0xff,0xd6,0xff,' +` 0x26,0xff,0x18,0xff,0xcd,0xfd,0xb6,0xfd,' +` 0xa9,0xfb,0xae,0xfb,0x95,0xf8,0xd8,0xf7,' +` 0xdb,0xf3,0xa1,0xf4,0xcb,0xef,0xba,0xf1,' +` 0xdb,0xeb,0xad,0xef,0xd8,0xe7,0xb3,0xed,' +` 0xe3,0xe4,0xc2,0xef,0x72,0xe2,0x39,0xf6,' +` 0xc3,0xda,0xde,0x18,0x6f,0x60,0xd0,0xd9,' +` 0x1d,0x02,0x7e,0xed,0x38,0x00,0xd4,0xf5,' +` 0x0d,0x02,0xa4,0xfb,0x2f,0x05,0x81,0x00,' +` 0x67,0x06,0xaf,0x02,0xb2,0x06,0x9e,0x03,' +` 0x2d,0x06,0xef,0x03,0x0f,0x05,0xce,0x02,' +` 0x90,0x03,0xd4,0x01,0x2c,0x02,0xf1,0x00,' +` 0x17,0x01,0x50,0x00,0x5e,0x00,0x02,0x00,' +` 0x12,0x00,0xf4,0xff,0xff,0xff,0xfd,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xff,0xff,' +` 0xf2,0xff,0x13,0x00,0xfd,0xff,0x61,0x00,' +` 0x44,0x00,0x1e,0x01,0xde,0x00,0x39,0x02,' +` 0xb9,0x01,0xa6,0x03,0xab,0x02,0x2f,0x05,' +` 0xc0,0x03,0x74,0x06,0x5f,0x03,0x11,0x07,' +` 0x60,0x02,0xea,0x06,0x19,0x00,0xed,0x05,' +` 0x31,0xfb,0xf9,0x02,0x13,0xf5,0x8c,0x01,' +` 0x38,0xec,0x42,0x04,0x41,0xd7,0x60,0x56,' +` 0xbb,0x27,0x84,0xd6,0xd4,0xf8,0xde,0xe0,' +` 0x1b,0xf1,0xf8,0xe3,0x8b,0xee,0x1e,0xe7,' +` 0x31,0xf0,0x65,0xeb,0x10,0xf2,0x70,0xef,' +` 0xd6,0xf4,0x98,0xf3,0xee,0xf7,0x4e,0xf8,' +` 0xc4,0xfb,0x81,0xfb,0xc2,0xfd,0xb3,0xfd,' +` 0x1e,0xff,0x17,0xff,0xd9,0xff,0xc5,0xff,' +` 0x0f,0x00,0x00,0x00,0x0d,0x00,0x02,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfb,0xff,0xf4,0xff,0xec,0xff,' +` 0xe0,0xff,0xd4,0xff,0xca,0xff,0xc0,0xff,' +` 0xab,0xff,0xa2,0xff,0x8e,0xff,0x91,0xff,' +` 0x82,0xff,0xa9,0xff,0xcb,0xff,0xcd,0xff,' +` 0x06,0x00,0x54,0x00,0xa0,0x00,0x22,0x01,' +` 0x6f,0x01,0x9d,0x02,0x9f,0x04,0x14,0x05,' +` 0xd3,0x05,0x5c,0x06,0xfd,0x06,0x77,0x07,' +` 0xef,0x07,0x38,0x48,0x80,0x08,0x96,0x08,' +` 0x8c,0x08,0x6c,0x08,0x22,0x08,0xd2,0x07,' +` 0x4a,0x07,0x32,0x07,0xbf,0x06,0x0f,0x06,' +` 0x5c,0x05,0xb5,0x04,0xf5,0x03,0x6f,0x03,' +` 0x59,0x02,0x87,0x01,0x4f,0x01,0xe5,0x00,' +` 0xac,0x00,0x6b,0x00,0x48,0x00,0x24,0x00,' +` 0x16,0x00,0x11,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3f,0x00,0xfa,0xff,0x80,0x00,0x30,0x00,' +` 0x3c,0x01,0xb6,0x00,0x71,0x02,0x9e,0x01,' +` 0x2f,0x04,0x7b,0x02,0xd2,0x07,0x41,0x06,' +` 0x39,0x0b,0x56,0x08,0xce,0x0e,0x2f,0x0a,' +` 0x83,0x12,0x4c,0x0a,0x30,0x15,0xc2,0x09,' +` 0x90,0x19,0x2c,0x06,0x9d,0x21,0xe8,0xf5,' +` 0x47,0x69,0xa0,0x5a,0x77,0xf5,0x26,0x1e,' +` 0x50,0x02,0xa0,0x14,0x1e,0x04,0x3f,0x0f,' +` 0x30,0x03,0x79,0x07,0x75,0xff,0x8b,0x04,' +` 0xb6,0xfe,0x74,0x02,0x3f,0xfe,0x2c,0x01,' +` 0xb4,0xfe,0x41,0x00,0x75,0xfe,0xef,0xff,' +` 0xd3,0xfe,0xda,0xff,0x3a,0xff,0xe1,0xff,' +` 0x8c,0xff,0xe2,0xff,0xc9,0xff,0xf4,0xff,' +` 0xf3,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x0a,0x00,' +` 0x0b,0x00,0x05,0x00,0xe7,0xff,0xc0,0xff,' +` 0x5d,0xff,0xec,0xfe,0x2d,0xfe,0x6a,0xfd,' +` 0x40,0xfc,0x31,0xfb,0x77,0xf9,0x54,0xf7,' +` 0x03,0xf5,0x8c,0xf3,0x60,0xf1,0x18,0xf0,' +` 0xfa,0xed,0x41,0xed,0xe2,0xea,0xfb,0xe9,' +` 0xeb,0xe8,0xf7,0xe9,0x21,0xe9,0xbc,0xeb,' +` 0x58,0xea,0xba,0xf0,0x2c,0x6f,0x59,0xee,' +` 0x56,0xf5,0x02,0xf5,0x2c,0xf9,0xfd,0xf9,' +` 0x40,0xfd,0x22,0xfe,0x3b,0x01,0x63,0x02,' +` 0xa7,0x03,0xfd,0x03,0xa1,0x04,0x94,0x04,' +` 0x9c,0x04,0xb5,0x04,0x48,0x04,0x41,0x03,' +` 0xeb,0x02,0x2c,0x02,0xc2,0x01,0x2d,0x01,' +` 0xd8,0x00,0x7c,0x00,0x44,0x00,0x15,0x00,' +` 0x06,0x00,0xfb,0xff,0xfc,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xfe,0xff,' +` 0xf0,0xff,0x10,0x00,0xf4,0xff,0x59,0x00,' +` 0x34,0x00,0x0c,0x01,0xb8,0x00,0x1b,0x02,' +` 0x80,0x01,0x7f,0x03,0x60,0x02,0x04,0x05,' +` 0x94,0x03,0x61,0x06,0xe6,0x02,0xf4,0x06,' +` 0xdf,0x01,0xdf,0x06,0x90,0xff,0xfc,0x05,' +` 0x9c,0xfa,0x43,0x03,0x7c,0xf4,0x0e,0x02,' +` 0x89,0xeb,0xf5,0x04,0x18,0xd7,0x71,0x43,' +` 0x8d,0x3d,0x2f,0xd2,0x03,0xfb,0x7c,0xdf,' +` 0x1c,0xf2,0x2c,0xe3,0x29,0xef,0x5e,0xe6,' +` 0x7a,0xf0,0x0f,0xeb,0x45,0xf2,0x26,0xef,' +` 0xf4,0xf4,0x58,0xf3,0xff,0xf7,0xea,0xf7,' +` 0xbc,0xfb,0x5e,0xfb,0xbc,0xfd,0x9a,0xfd,' +` 0x19,0xff,0x07,0xff,0xd6,0xff,0xc2,0xff,' +` 0x0f,0x00,0xfe,0xff,0x0c,0x00,0x02,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfc,0xff,0xf5,0xff,0xee,0xff,' +` 0xe2,0xff,0xda,0xff,0xd1,0xff,0xc8,0xff,' +` 0xb6,0xff,0xaf,0xff,0x9c,0xff,0xa4,0xff,' +` 0x92,0xff,0xd0,0xff,0xf7,0xff,0xe2,0xff,' +` 0x1f,0x00,0x6d,0x00,0xb8,0x00,0x3e,0x01,' +` 0x82,0x01,0xea,0x02,0xc4,0x04,0x2a,0x05,' +` 0xef,0x05,0x73,0x06,0x17,0x07,0x8e,0x07,' +` 0x06,0x08,0x4d,0x48,0x9a,0x08,0xb2,0x08,' +` 0xa7,0x08,0x89,0x08,0x3d,0x08,0xf1,0x07,' +` 0x62,0x07,0x3b,0x07,0xd7,0x06,0x26,0x06,' +` 0x6f,0x05,0xc9,0x04,0x04,0x04,0x82,0x03,' +` 0x3f,0x02,0x82,0x01,0x5a,0x01,0xeb,0x00,' +` 0xb2,0x00,0x6f,0x00,0x4a,0x00,0x27,0x00,' +` 0x14,0x00,0x0e,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1e,0x00,0xfb,0xff,0x6d,0x00,0x31,0x00,' +` 0x17,0x01,0xaf,0x00,0x38,0x02,0x8d,0x01,' +` 0xb7,0x03,0x0f,0x02,0x97,0x06,0x18,0x06,' +` 0x93,0x0a,0x28,0x08,0x2d,0x0e,0x21,0x0a,' +` 0xd8,0x11,0x3c,0x0a,0xe0,0x14,0x09,0x0a,' +` 0x4a,0x19,0xd5,0x06,0x17,0x21,0x1a,0xf8,' +` 0x7d,0x5a,0xbd,0x69,0x6a,0xf4,0x76,0x1f,' +` 0xc4,0x02,0xad,0x15,0xfa,0x04,0x26,0x10,' +` 0xb4,0x04,0x97,0x09,0xae,0xff,0x94,0x05,' +` 0x18,0xff,0x4b,0x03,0x9c,0xfe,0xf9,0x01,' +` 0x53,0xff,0x2c,0x01,0x96,0xfe,0x55,0x00,' +` 0xe7,0xfe,0x1c,0x00,0x3d,0xff,0xff,0xff,' +` 0x85,0xff,0xf5,0xff,0xb7,0xff,0xf3,0xff,' +` 0xe5,0xff,0xfc,0xff,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0x0b,0x00,' +` 0x00,0x00,0x0d,0x00,0xcc,0xff,0xc9,0xff,' +` 0x19,0xff,0x02,0xff,0xbc,0xfd,0x98,0xfd,' +` 0x9f,0xfb,0x5a,0xfb,0x20,0xf8,0x22,0xf8,' +` 0xbe,0xf3,0xb9,0xf4,0xc8,0xef,0xd8,0xf1,' +` 0xeb,0xeb,0xa7,0xef,0x59,0xe7,0xd9,0xed,' +` 0x6a,0xe4,0xc0,0xef,0xd6,0xe1,0x3f,0xf6,' +` 0xb8,0xd9,0x59,0x1a,0xc9,0x5e,0xc4,0xd8,' +` 0xa6,0x01,0x67,0xec,0x65,0xff,0x91,0xf4,' +` 0xfc,0x00,0xfd,0xf9,0x5b,0x03,0x12,0xff,' +` 0xf2,0x04,0x40,0x01,0x58,0x05,0x4c,0x02,' +` 0x27,0x05,0x48,0x03,0x90,0x04,0xfe,0x01,' +` 0xdb,0x02,0x3e,0x01,0xae,0x01,0x93,0x00,' +` 0xd1,0x00,0x29,0x00,0x4a,0x00,0xf1,0xff,' +` 0x07,0x00,0xf0,0xff,0xfd,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xf9,0xff,' +` 0xfe,0xff,0xf6,0xff,0x1c,0x00,0x21,0x00,' +` 0x79,0x00,0x7e,0x00,0x1d,0x01,0x1f,0x01,' +` 0x12,0x02,0xec,0x01,0x42,0x03,0x5b,0x03,' +` 0x89,0x04,0xd9,0x02,0x52,0x04,0x4c,0x02,' +` 0xe6,0x03,0xc1,0x00,0x91,0x02,0xec,0xfc,' +` 0x40,0xff,0xa9,0xf8,0x7d,0xfc,0xd8,0xf2,' +` 0x9e,0xfa,0x9a,0xe9,0x12,0x04,0x91,0x6a,' +` 0xdd,0xdd,0x03,0xf3,0xd5,0xe4,0x41,0xed,' +` 0xe9,0xe5,0x89,0xeb,0x86,0xe7,0xc8,0xec,' +` 0xa7,0xeb,0xa1,0xef,0x0b,0xef,0xab,0xf2,' +` 0xd2,0xf2,0x17,0xf6,0x34,0xf7,0xc9,0xf9,' +` 0xde,0xfa,0xb3,0xfc,0x38,0xfd,0x76,0xfe,' +` 0xce,0xfe,0x88,0xff,0xaf,0xff,0x02,0x00,' +` 0x01,0x00,0x12,0x00,0x09,0x00,0x04,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfc,0xff,0xf8,0xff,0xf2,0xff,0xec,0xff,' +` 0xe9,0xff,0xe2,0xff,0xdd,0xff,0xd7,0xff,' +` 0xd2,0xff,0xce,0xff,0xd0,0xff,0xdd,0xff,' +` 0x3c,0x00,0x58,0x00,0x39,0x00,0x63,0x00,' +` 0xb7,0x00,0x02,0x01,0x80,0x01,0xd6,0x01,' +` 0xcd,0x03,0xfd,0x04,0x7e,0x05,0x34,0x06,' +` 0xba,0x06,0x56,0x07,0xcc,0x07,0x3e,0x08,' +` 0x81,0x48,0xd2,0x08,0xf2,0x08,0xf0,0x08,' +` 0xcb,0x08,0x88,0x08,0x2f,0x08,0xaf,0x07,' +` 0x41,0x07,0x16,0x07,0x5c,0x06,0xab,0x05,' +` 0xf1,0x04,0x3e,0x04,0x87,0x03,0x17,0x02,' +` 0x7e,0x01,0x5e,0x01,0x06,0x01,0xbd,0x00,' +` 0x7e,0x00,0x51,0x00,0x2d,0x00,0x17,0x00,' +` 0x07,0x00,0x06,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x05,0x00,0xfd,0xff,0x1a,0x00,0x0e,0x00,' +` 0x54,0x00,0x40,0x00,0xc1,0x00,0x9e,0x00,' +` 0x6e,0x01,0xfa,0x00,0x1b,0x02,0xa1,0x01,' +` 0x7e,0x03,0xd0,0x03,0xee,0x05,0x02,0x05,' +` 0xc1,0x07,0x0f,0x06,0x09,0x09,0x29,0x06,' +` 0xb4,0x0a,0x1c,0x06,0x9a,0x0c,0x96,0x04,' +` 0x06,0x10,0xd6,0xfc,0xbd,0x40,0x8a,0x1e,' +` 0x06,0xff,0x64,0x0d,0x1d,0x03,0xc1,0x09,' +` 0x84,0x03,0x55,0x07,0x11,0x03,0xe6,0x04,' +` 0x82,0x00,0x9a,0x02,0x32,0x00,0xa5,0x01,' +` 0xfb,0xff,0x5b,0x01,0x19,0x00,0xde,0x00,' +` 0xe3,0xff,0x4a,0x00,0xce,0xff,0x24,0x00,' +` 0xd8,0xff,0x0d,0x00,0xe6,0xff,0x02,0x00,' +` 0xf3,0xff,0xfe,0xff,0xfc,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x0a,0x00,0x06,0x00,0x06,0x00,0xd5,0xff,' +` 0xb8,0xff,0x33,0xff,0xea,0xfe,0xef,0xfd,' +` 0x7d,0xfd,0xd0,0xfb,0xd6,0xfa,0xcf,0xf8,' +` 0x24,0xf8,0x10,0xf5,0x3b,0xf4,0x4b,0xf1,' +` 0x2e,0xf1,0xe9,0xed,0x3d,0xee,0xa7,0xe9,' +` 0x20,0xec,0x6c,0xe7,0x30,0xec,0x40,0xe6,' +` 0x80,0xef,0x26,0xe4,0x9c,0xfd,0xea,0x6b,' +` 0x96,0xe3,0x6f,0xf9,0xf7,0xef,0x02,0xfa,' +` 0xd7,0xf5,0x75,0xfc,0x0b,0xfa,0xcc,0xfe,' +` 0x1c,0xfe,0xac,0x01,0x37,0x00,0x92,0x02,' +` 0x3e,0x01,0x33,0x03,0x5a,0x02,0xef,0x02,' +` 0xe3,0x01,0xb1,0x01,0xc2,0x00,0xe9,0x00,' +` 0x53,0x00,0x65,0x00,0x0c,0x00,0x19,0x00,' +` 0xf0,0xff,0xfc,0xff,0xef,0xff,0xfd,0xff,' +` 0xff,0xff,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,' +` 0xe7,0xff,0x01,0x00,0xd9,0xff,0x29,0x00,' +` 0xdc,0xff,0x84,0x00,0x01,0x00,0x20,0x01,' +` 0x46,0x00,0xf7,0x01,0x05,0x01,0x95,0x03,' +` 0x52,0x01,0x56,0x04,0x16,0x00,0xd5,0x03,' +` 0x9f,0xfe,0x78,0x03,0x10,0xfc,0x6e,0x01,' +` 0x1c,0xf7,0x1c,0x00,0xaa,0xf1,0x82,0xff,' +` 0x42,0xe9,0x1c,0x03,0x23,0xd5,0x7c,0x47,' +` 0x22,0x37,0x51,0xd2,0x21,0xfa,0x3e,0xdf,' +` 0xb1,0xf1,0x38,0xe3,0x87,0xef,0xd7,0xe6,' +` 0x36,0xf0,0xd6,0xeb,0xd3,0xf2,0xd3,0xef,' +` 0x61,0xf5,0xf3,0xf3,0xe4,0xf8,0x18,0xf8,' +` 0x5a,0xfb,0x3d,0xfb,0xd2,0xfd,0xa3,0xfd,' +` 0x1d,0xff,0x09,0xff,0xd3,0xff,0xc1,0xff,' +` 0x12,0x00,0x00,0x00,0x0d,0x00,0x02,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfb,0xff,0xfb,0xff,0xf9,0xff,' +` 0xf9,0xff,0xfa,0xff,0xfc,0xff,0x01,0x00,' +` 0x08,0x00,0x13,0x00,0x2b,0x00,0x83,0x00,' +` 0x97,0x00,0xde,0x00,0xdb,0x00,0xe1,0x00,' +` 0x22,0x01,0x8c,0x01,0xc1,0x01,0xf0,0x02,' +` 0xc5,0x04,0x35,0x05,0xff,0x05,0x8d,0x06,' +` 0x2d,0x07,0xa3,0x07,0x1e,0x08,0x7a,0x08,' +` 0xbf,0x48,0x05,0x09,0x24,0x09,0x2f,0x09,' +` 0x0d,0x09,0xd5,0x08,0x6a,0x08,0x04,0x08,' +` 0x5c,0x07,0x1e,0x07,0xac,0x06,0xed,0x05,' +` 0x20,0x05,0x83,0x04,0x38,0x03,0x0a,0x02,' +` 0xbb,0x01,0x39,0x01,0x18,0x01,0xd3,0x00,' +` 0x92,0x00,0x5d,0x00,0x39,0x00,0x1d,0x00,' +` 0x0d,0x00,0x03,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0x04,0x00,0x00,0x00,0x2c,0x00,' +` 0x1b,0x00,0x95,0x00,0x6f,0x00,0x60,0x01,' +` 0x0b,0x01,0x49,0x02,0xb5,0x01,0xfc,0x03,' +` 0x04,0x03,0x2e,0x06,0x05,0x05,0x8c,0x0b,' +` 0xd2,0x08,0x38,0x0f,0x7b,0x0a,0xc0,0x11,' +` 0x1b,0x0b,0x9c,0x15,0xcb,0x0a,0xe2,0x19,' +` 0x6c,0x07,0x96,0x21,0x99,0xf8,0xce,0x5b,' +` 0x01,0x6a,0x5b,0xf5,0xc7,0x20,0x0f,0x04,' +` 0x5f,0x17,0x5e,0x06,0x14,0x12,0x1b,0x06,' +` 0x2f,0x0e,0x23,0x04,0x39,0x07,0x73,0x01,' +` 0x2e,0x05,0x46,0x01,0x8e,0x04,0x15,0x01,' +` 0x2b,0x03,0xa9,0x00,0x11,0x02,0x05,0x00,' +` 0xda,0x00,0xd8,0xff,0x71,0x00,0xd7,0xff,' +` 0x2f,0x00,0xe0,0xff,0x12,0x00,0xfc,0xff,' +` 0x05,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x00,0x00,0x10,0x00,0xf1,0xff,0x05,0x00,' +` 0x8d,0xff,0xa6,0xff,0xa7,0xfe,0xd2,0xfe,' +` 0xf9,0xfc,0xef,0xfc,0x69,0xfa,0xea,0xfa,' +` 0x67,0xf7,0x9a,0xf8,0x9f,0xf3,0x28,0xf5,' +` 0x80,0xef,0x02,0xf3,0x1d,0xeb,0x4f,0xf0,' +` 0x4b,0xe7,0x37,0xf0,0xeb,0xe3,0xa7,0xf2,' +` 0xa2,0xdf,0x4b,0xfb,0xf3,0xd0,0xda,0x4d,' +` 0x8f,0x30,0x7e,0xd8,0x28,0x01,0x9c,0xe9,' +` 0x9c,0xfd,0xc0,0xf0,0xc3,0xfd,0x9b,0xf5,' +` 0xbb,0xfe,0xce,0xf9,0xdb,0x00,0x7b,0xfc,' +` 0x3a,0x01,0xa3,0xfe,0x04,0x02,0x70,0xff,' +` 0x96,0x01,0xba,0xff,0x22,0x01,0x89,0xff,' +` 0x59,0x00,0x98,0xff,0x1e,0x00,0xb7,0xff,' +` 0x02,0x00,0xd9,0xff,0x02,0x00,0xfa,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,' +` 0xf3,0xff,0xf4,0xff,0xc9,0xff,0xf1,0xff,' +` 0xaa,0xff,0x04,0x00,0x95,0xff,0x31,0x00,' +` 0xb4,0xff,0xfd,0x00,0xca,0xff,0x46,0x01,' +` 0x83,0xff,0x77,0x01,0x64,0xfe,0x22,0x00,' +` 0x82,0xfc,0x3b,0xff,0x01,0xf9,0xd1,0xfc,' +` 0x90,0xf5,0x44,0xfb,0x26,0xf1,0x71,0xfa,' +` 0xc9,0xea,0xf6,0xfc,0x1b,0xda,0xd6,0x63,' +` 0xab,0x0e,0x4d,0xdd,0x33,0xf4,0x00,0xe4,' +` 0xad,0xef,0xf5,0xe6,0xf6,0xee,0xf4,0xe9,' +` 0x15,0xf0,0xf0,0xed,0x66,0xf3,0xb8,0xf1,' +` 0x1b,0xf6,0x12,0xf6,0x49,0xf9,0x27,0xf9,' +` 0xa7,0xfb,0xc2,0xfb,0x9f,0xfd,0x0d,0xfe,' +` 0x24,0xff,0x3a,0xff,0xce,0xff,0xd2,0xff,' +` 0x0c,0x00,0x04,0x00,0x08,0x00,0x01,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x04,0x00,0x02,0x00,0x04,0x00,0x0a,0x00,' +` 0x12,0x00,0x1f,0x00,0x2e,0x00,0x41,0x00,' +` 0x81,0x00,0xc5,0x00,0xe8,0x00,0x2b,0x01,' +` 0x54,0x01,0xb1,0x01,0xa5,0x01,0xc9,0x01,' +` 0x17,0x02,0xbc,0x02,0xa4,0x04,0x34,0x05,' +` 0xd4,0x05,0x69,0x06,0x01,0x07,0x8d,0x07,' +` 0x07,0x08,0x69,0x08,0xb9,0x08,0xeb,0x48,' +` 0x1d,0x09,0x35,0x09,0x2b,0x09,0x14,0x09,' +` 0xd1,0x08,0x88,0x08,0x05,0x08,0x8b,0x07,' +` 0xd5,0x06,0xa1,0x06,0x03,0x06,0x58,0x05,' +` 0x45,0x04,0xbc,0x02,0x53,0x02,0xc6,0x01,' +` 0x6b,0x01,0x01,0x01,0xc7,0x00,0xa3,0x00,' +` 0x6f,0x00,0x44,0x00,0x28,0x00,0x13,0x00,' +` 0x08,0x00,0x01,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0x05,0x00,0x04,0x00,' +` 0x28,0x00,0x2c,0x00,0x6c,0x00,0x69,0x00,' +` 0xb6,0x00,0xb5,0x00,0x57,0x01,0x4b,0x01,' +` 0x35,0x02,0x0d,0x02,0x4c,0x03,0xe2,0x02,' +` 0x5b,0x05,0x70,0x05,0xfc,0x06,0xd4,0x05,' +` 0x54,0x08,0x82,0x06,0xb6,0x09,0xac,0x06,' +` 0x3d,0x0b,0xca,0x05,0xf1,0x0d,0x1e,0x00,' +` 0xcc,0x45,0xd5,0x15,0xd8,0x02,0x07,0x0c,' +` 0x33,0x05,0x88,0x09,0x48,0x05,0xd5,0x07,' +` 0xc7,0x04,0x5b,0x06,0x08,0x04,0xd8,0x03,' +` 0xc0,0x01,0xff,0x02,0xc4,0x01,0x3a,0x02,' +` 0x37,0x01,0x81,0x01,0xc7,0x00,0xf2,0x00,' +` 0x74,0x00,0x7d,0x00,0x15,0x00,0x2e,0x00,' +` 0x00,0x00,0x13,0x00,0x04,0x00,0x06,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0xfe,0xff,0xff,0xff,0xe1,0xff,0xf0,0xff,' +` 0x9c,0xff,0x94,0xff,0xcd,0xfe,0x79,0xfe,' +` 0x5a,0xfd,0x25,0xfd,0x7b,0xfb,0x5e,0xfb,' +` 0x21,0xf9,0x43,0xf9,0x73,0xf6,0x51,0xf6,' +` 0xa1,0xf2,0x46,0xf3,0x85,0xee,0x4d,0xf1,' +` 0xd5,0xeb,0x95,0xf0,0x5d,0xe9,0x6f,0xf1,' +` 0x44,0xe6,0x0d,0xf6,0x88,0xdb,0xe1,0x67,' +` 0xd0,0x07,0xa2,0xe4,0x0f,0xf8,0xbb,0xec,' +` 0x23,0xf7,0x04,0xf1,0x1a,0xf8,0x54,0xf4,' +` 0x88,0xf9,0x2e,0xf7,0x05,0xfc,0x51,0xfa,' +` 0xeb,0xfd,0xae,0xfc,0xae,0xfe,0xce,0xfd,' +` 0x3e,0xff,0xa3,0xfe,0x99,0xff,0x38,0xff,' +` 0xb9,0xff,0x49,0xff,0xbc,0xff,0x9e,0xff,' +` 0xf0,0xff,0xeb,0xff,0xfe,0xff,0xfc,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfe,0xff,0xf3,0xff,' +` 0xf4,0xff,0xd0,0xff,0xb7,0xff,0x79,0xff,' +` 0x79,0xff,0x31,0xff,0x8d,0xff,0xe8,0xfe,' +` 0x2c,0xff,0x3f,0xfe,0x9e,0xfe,0x4f,0xfd,' +` 0xd7,0xfd,0x23,0xfc,0x44,0xfc,0x5e,0xf9,' +` 0x94,0xf9,0x2b,0xf6,0xd5,0xf7,0x77,0xf3,' +` 0x31,0xf6,0x52,0xf0,0x17,0xf5,0x4d,0xec,' +` 0x5a,0xf6,0x2b,0xe2,0x35,0x6b,0xcb,0xfc,' +` 0x5e,0xe5,0x3f,0xf1,0x5c,0xe9,0xb6,0xef,' +` 0x8f,0xeb,0x1b,0xf0,0xe3,0xed,0x98,0xf1,' +` 0xb9,0xf0,0xaf,0xf4,0xd2,0xf4,0x1c,0xf8,' +` 0x24,0xf8,0x51,0xfa,0xa0,0xfa,0x52,0xfc,' +` 0xad,0xfc,0xeb,0xfd,0x33,0xfe,0x23,0xff,' +` 0x70,0xff,0xcc,0xff,0xe2,0xff,0xfb,0xff,' +` 0xf9,0xff,0x03,0x00,0x01,0x00,0x00,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x05,0x00,0x0c,0x00,' +` 0x15,0x00,0x13,0x00,0x26,0x00,0x36,0x00,' +` 0x68,0x00,0xa8,0x00,0xd8,0x00,0x12,0x01,' +` 0x56,0x01,0x9e,0x01,0xf8,0x01,0x49,0x02,' +` 0xb6,0x02,0xb7,0x02,0xff,0x02,0xdb,0x04,' +` 0x80,0x05,0x05,0x06,0x8a,0x06,0x09,0x07,' +` 0x82,0x07,0xf1,0x07,0x59,0x08,0xaf,0x08,' +` 0xeb,0x08,0xfc,0x48,0x1c,0x09,0x13,0x09,' +` 0xfc,0x08,0xc2,0x08,0x7e,0x08,0x16,0x08,' +` 0xb0,0x07,0x26,0x07,0xa8,0x06,0xee,0x05,' +` 0xc9,0x05,0xf3,0x04,0x46,0x03,0xcc,0x02,' +` 0x47,0x02,0xd9,0x01,0x6e,0x01,0x16,0x01,' +` 0xc9,0x00,0x89,0x00,0x67,0x00,0x53,0x00,' +` 0x2f,0x00,0x1c,0x00,0x06,0x00,0x00,0x00,' +` 0xff,0xff,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,' +` 0x09,0x00,0x18,0x00,0x23,0x00,0x46,0x00,' +` 0x5a,0x00,0x96,0x00,0xb8,0x00,0x13,0x01,' +` 0x40,0x01,0xbc,0x01,0xef,0x01,0x8f,0x02,' +` 0xc2,0x02,0x7f,0x03,0xc3,0x03,0x90,0x05,' +` 0x97,0x05,0xbc,0x06,0x86,0x06,0xd8,0x07,' +` 0x41,0x07,0xe1,0x08,0xa0,0x07,0xf7,0x09,' +` 0x1a,0x07,0xe1,0x0c,0xb3,0x48,0x90,0x05,' +` 0x85,0x0a,0x62,0x07,0x11,0x09,0x2b,0x07,' +` 0xf4,0x07,0x7b,0x06,0xd1,0x06,0x8e,0x05,' +` 0xab,0x05,0x5a,0x04,0x83,0x03,0xc7,0x02,' +` 0x93,0x02,0xf1,0x01,0xbe,0x01,0x40,0x01,' +` 0x13,0x01,0xb8,0x00,0x95,0x00,0x59,0x00,' +` 0x42,0x00,0x1f,0x00,0x17,0x00,0x07,0x00,' +` 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd6,0xff,' +` 0xb4,0xff,0x7f,0xff,0x3f,0xff,0xea,0xfe,' +` 0x7b,0xfe,0xfc,0xfd,0x60,0xfd,0xb8,0xfc,' +` 0xf2,0xfb,0x26,0xfb,0x39,0xfa,0x5a,0xf9,' +` 0x2c,0xf8,0x6f,0xf5,0x43,0xf4,0x39,0xf3,' +` 0x32,0xf2,0x43,0xf1,0x63,0xf0,0xa5,0xef,' +` 0xfd,0xee,0x7f,0xee,0x1b,0xee,0xe7,0xed,' +` 0xbd,0x6d,0x12,0xee,0x66,0xee,0xf1,0xee,' +` 0x88,0xef,0x55,0xf0,0x22,0xf1,0x24,0xf2,' +` 0x14,0xf3,0x3e,0xf4,0x2d,0xf5,0xbf,0xf6,' +` 0x49,0xf9,0x21,0xfa,0x17,0xfb,0xe2,0xfb,' +` 0xad,0xfc,0x56,0xfd,0xf5,0xfd,0x75,0xfe,' +` 0xe6,0xfe,0x3d,0xff,0x85,0xff,0xba,0xff,' +` 0xd7,0xff,0xed,0xff,0xf9,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff,' +` 0xec,0xff,0xd6,0xff,0xb4,0xff,0x7f,0xff,' +` 0x3f,0xff,0xea,0xfe,0x7b,0xfe,0xfc,0xfd,' +` 0x60,0xfd,0xb8,0xfc,0xf2,0xfb,0x26,0xfb,' +` 0x39,0xfa,0x5a,0xf9,0x2c,0xf8,0x6f,0xf5,' +` 0x43,0xf4,0x39,0xf3,0x32,0xf2,0x43,0xf1,' +` 0x63,0xf0,0xa5,0xef,0xfd,0xee,0x7f,0xee,' +` 0x1b,0xee,0xe7,0xed,0xbd,0x6d,0x12,0xee,' +` 0x66,0xee,0xf1,0xee,0x88,0xef,0x55,0xf0,' +` 0x22,0xf1,0x24,0xf2,0x14,0xf3,0x3e,0xf4,' +` 0x2d,0xf5,0xbf,0xf6,0x49,0xf9,0x21,0xfa,' +` 0x17,0xfb,0xe2,0xfb,0xad,0xfc,0x56,0xfd,' +` 0xf5,0xfd,0x75,0xfe,0xe6,0xfe,0x3d,0xff,' +` 0x85,0xff,0xba,0xff,0xd7,0xff,0xed,0xff,' +` 0xf9,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x05,0x00,0x09,0x00,0x18,0x00,' +` 0x23,0x00,0x46,0x00,0x5a,0x00,0x96,0x00,' +` 0xb8,0x00,0x13,0x01,0x40,0x01,0xbc,0x01,' +` 0xef,0x01,0x8f,0x02,0xc2,0x02,0x7f,0x03,' +` 0xc3,0x03,0x90,0x05,0x97,0x05,0xbc,0x06,' +` 0x86,0x06,0xd8,0x07,0x41,0x07,0xe1,0x08,' +` 0xa0,0x07,0xf7,0x09,0x1a,0x07,0xe1,0x0c,' +` 0xb3,0x48,0x90,0x05,0x85,0x0a,0x62,0x07,' +` 0x11,0x09,0x2b,0x07,0xf4,0x07,0x7b,0x06,' +` 0xd1,0x06,0x8e,0x05,0xab,0x05,0x5a,0x04,' +` 0x83,0x03,0xc7,0x02,0x93,0x02,0xf1,0x01,' +` 0xbe,0x01,0x40,0x01,0x13,0x01,0xb8,0x00,' +` 0x95,0x00,0x59,0x00,0x42,0x00,0x1f,0x00,' +` 0x17,0x00,0x07,0x00,0x04,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x05,0x00,0x0c,0x00,0x15,0x00,0x13,0x00,' +` 0x26,0x00,0x36,0x00,0x68,0x00,0xa8,0x00,' +` 0xd8,0x00,0x12,0x01,0x56,0x01,0x9e,0x01,' +` 0xf8,0x01,0x49,0x02,0xb6,0x02,0xb7,0x02,' +` 0xff,0x02,0xdb,0x04,0x80,0x05,0x05,0x06,' +` 0x8a,0x06,0x09,0x07,0x82,0x07,0xf1,0x07,' +` 0x59,0x08,0xaf,0x08,0xeb,0x08,0xfc,0x48,' +` 0x1c,0x09,0x13,0x09,0xfc,0x08,0xc2,0x08,' +` 0x7e,0x08,0x16,0x08,0xb0,0x07,0x26,0x07,' +` 0xa8,0x06,0xee,0x05,0xc9,0x05,0xf3,0x04,' +` 0x46,0x03,0xcc,0x02,0x47,0x02,0xd9,0x01,' +` 0x6e,0x01,0x16,0x01,0xc9,0x00,0x89,0x00,' +` 0x67,0x00,0x53,0x00,0x2f,0x00,0x1c,0x00,' +` 0x06,0x00,0x00,0x00,0xff,0xff,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfe,0xff,0xf3,0xff,0xf4,0xff,0xd0,0xff,' +` 0xb7,0xff,0x79,0xff,0x79,0xff,0x31,0xff,' +` 0x8d,0xff,0xe8,0xfe,0x2c,0xff,0x3f,0xfe,' +` 0x9e,0xfe,0x4f,0xfd,0xd7,0xfd,0x23,0xfc,' +` 0x44,0xfc,0x5e,0xf9,0x94,0xf9,0x2b,0xf6,' +` 0xd5,0xf7,0x77,0xf3,0x31,0xf6,0x52,0xf0,' +` 0x17,0xf5,0x4d,0xec,0x5a,0xf6,0x2b,0xe2,' +` 0x35,0x6b,0xcb,0xfc,0x5e,0xe5,0x3f,0xf1,' +` 0x5c,0xe9,0xb6,0xef,0x8f,0xeb,0x1b,0xf0,' +` 0xe3,0xed,0x98,0xf1,0xb9,0xf0,0xaf,0xf4,' +` 0xd2,0xf4,0x1c,0xf8,0x24,0xf8,0x51,0xfa,' +` 0xa0,0xfa,0x52,0xfc,0xad,0xfc,0xeb,0xfd,' +` 0x33,0xfe,0x23,0xff,0x70,0xff,0xcc,0xff,' +` 0xe2,0xff,0xfb,0xff,0xf9,0xff,0x03,0x00,' +` 0x01,0x00,0x00,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0xfe,0xff,0xff,0xff,' +` 0xe1,0xff,0xf0,0xff,0x9c,0xff,0x94,0xff,' +` 0xcd,0xfe,0x79,0xfe,0x5a,0xfd,0x25,0xfd,' +` 0x7b,0xfb,0x5e,0xfb,0x21,0xf9,0x43,0xf9,' +` 0x73,0xf6,0x51,0xf6,0xa1,0xf2,0x46,0xf3,' +` 0x85,0xee,0x4d,0xf1,0xd5,0xeb,0x95,0xf0,' +` 0x5d,0xe9,0x6f,0xf1,0x44,0xe6,0x0d,0xf6,' +` 0x88,0xdb,0xe1,0x67,0xd0,0x07,0xa2,0xe4,' +` 0x0f,0xf8,0xbb,0xec,0x23,0xf7,0x04,0xf1,' +` 0x1a,0xf8,0x54,0xf4,0x88,0xf9,0x2e,0xf7,' +` 0x05,0xfc,0x51,0xfa,0xeb,0xfd,0xae,0xfc,' +` 0xae,0xfe,0xce,0xfd,0x3e,0xff,0xa3,0xfe,' +` 0x99,0xff,0x38,0xff,0xb9,0xff,0x49,0xff,' +` 0xbc,0xff,0x9e,0xff,0xf0,0xff,0xeb,0xff,' +` 0xfe,0xff,0xfc,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0x05,0x00,0x04,0x00,0x28,0x00,0x2c,0x00,' +` 0x6c,0x00,0x69,0x00,0xb6,0x00,0xb5,0x00,' +` 0x57,0x01,0x4b,0x01,0x35,0x02,0x0d,0x02,' +` 0x4c,0x03,0xe2,0x02,0x5b,0x05,0x70,0x05,' +` 0xfc,0x06,0xd4,0x05,0x54,0x08,0x82,0x06,' +` 0xb6,0x09,0xac,0x06,0x3d,0x0b,0xca,0x05,' +` 0xf1,0x0d,0x1e,0x00,0xcc,0x45,0xd5,0x15,' +` 0xd8,0x02,0x07,0x0c,0x33,0x05,0x88,0x09,' +` 0x48,0x05,0xd5,0x07,0xc7,0x04,0x5b,0x06,' +` 0x08,0x04,0xd8,0x03,0xc0,0x01,0xff,0x02,' +` 0xc4,0x01,0x3a,0x02,0x37,0x01,0x81,0x01,' +` 0xc7,0x00,0xf2,0x00,0x74,0x00,0x7d,0x00,' +` 0x15,0x00,0x2e,0x00,0x00,0x00,0x13,0x00,' +` 0x04,0x00,0x06,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x04,0x00,0x02,0x00,' +` 0x04,0x00,0x0a,0x00,0x12,0x00,0x1f,0x00,' +` 0x2e,0x00,0x41,0x00,0x81,0x00,0xc5,0x00,' +` 0xe8,0x00,0x2b,0x01,0x54,0x01,0xb1,0x01,' +` 0xa5,0x01,0xc9,0x01,0x17,0x02,0xbc,0x02,' +` 0xa4,0x04,0x34,0x05,0xd4,0x05,0x69,0x06,' +` 0x01,0x07,0x8d,0x07,0x07,0x08,0x69,0x08,' +` 0xb9,0x08,0xeb,0x48,0x1d,0x09,0x35,0x09,' +` 0x2b,0x09,0x14,0x09,0xd1,0x08,0x88,0x08,' +` 0x05,0x08,0x8b,0x07,0xd5,0x06,0xa1,0x06,' +` 0x03,0x06,0x58,0x05,0x45,0x04,0xbc,0x02,' +` 0x53,0x02,0xc6,0x01,0x6b,0x01,0x01,0x01,' +` 0xc7,0x00,0xa3,0x00,0x6f,0x00,0x44,0x00,' +` 0x28,0x00,0x13,0x00,0x08,0x00,0x01,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xff,0xff,0xf3,0xff,0xf4,0xff,' +` 0xc9,0xff,0xf1,0xff,0xaa,0xff,0x04,0x00,' +` 0x95,0xff,0x31,0x00,0xb4,0xff,0xfd,0x00,' +` 0xca,0xff,0x46,0x01,0x83,0xff,0x77,0x01,' +` 0x64,0xfe,0x22,0x00,0x82,0xfc,0x3b,0xff,' +` 0x01,0xf9,0xd1,0xfc,0x90,0xf5,0x44,0xfb,' +` 0x26,0xf1,0x71,0xfa,0xc9,0xea,0xf6,0xfc,' +` 0x1b,0xda,0xd6,0x63,0xab,0x0e,0x4d,0xdd,' +` 0x33,0xf4,0x00,0xe4,0xad,0xef,0xf5,0xe6,' +` 0xf6,0xee,0xf4,0xe9,0x15,0xf0,0xf0,0xed,' +` 0x66,0xf3,0xb8,0xf1,0x1b,0xf6,0x12,0xf6,' +` 0x49,0xf9,0x27,0xf9,0xa7,0xfb,0xc2,0xfb,' +` 0x9f,0xfd,0x0d,0xfe,0x24,0xff,0x3a,0xff,' +` 0xce,0xff,0xd2,0xff,0x0c,0x00,0x04,0x00,' +` 0x08,0x00,0x01,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x00,0x00,0x10,0x00,' +` 0xf1,0xff,0x05,0x00,0x8d,0xff,0xa6,0xff,' +` 0xa7,0xfe,0xd2,0xfe,0xf9,0xfc,0xef,0xfc,' +` 0x69,0xfa,0xea,0xfa,0x67,0xf7,0x9a,0xf8,' +` 0x9f,0xf3,0x28,0xf5,0x80,0xef,0x02,0xf3,' +` 0x1d,0xeb,0x4f,0xf0,0x4b,0xe7,0x37,0xf0,' +` 0xeb,0xe3,0xa7,0xf2,0xa2,0xdf,0x4b,0xfb,' +` 0xf3,0xd0,0xda,0x4d,0x8f,0x30,0x7e,0xd8,' +` 0x28,0x01,0x9c,0xe9,0x9c,0xfd,0xc0,0xf0,' +` 0xc3,0xfd,0x9b,0xf5,0xbb,0xfe,0xce,0xf9,' +` 0xdb,0x00,0x7b,0xfc,0x3a,0x01,0xa3,0xfe,' +` 0x04,0x02,0x70,0xff,0x96,0x01,0xba,0xff,' +` 0x22,0x01,0x89,0xff,0x59,0x00,0x98,0xff,' +` 0x1e,0x00,0xb7,0xff,0x02,0x00,0xd9,0xff,' +` 0x02,0x00,0xfa,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0x04,0x00,' +` 0x00,0x00,0x2c,0x00,0x1b,0x00,0x95,0x00,' +` 0x6f,0x00,0x60,0x01,0x0b,0x01,0x49,0x02,' +` 0xb5,0x01,0xfc,0x03,0x04,0x03,0x2e,0x06,' +` 0x05,0x05,0x8c,0x0b,0xd2,0x08,0x38,0x0f,' +` 0x7b,0x0a,0xc0,0x11,0x1b,0x0b,0x9c,0x15,' +` 0xcb,0x0a,0xe2,0x19,0x6c,0x07,0x96,0x21,' +` 0x99,0xf8,0xce,0x5b,0x01,0x6a,0x5b,0xf5,' +` 0xc7,0x20,0x0f,0x04,0x5f,0x17,0x5e,0x06,' +` 0x14,0x12,0x1b,0x06,0x2f,0x0e,0x23,0x04,' +` 0x39,0x07,0x73,0x01,0x2e,0x05,0x46,0x01,' +` 0x8e,0x04,0x15,0x01,0x2b,0x03,0xa9,0x00,' +` 0x11,0x02,0x05,0x00,0xda,0x00,0xd8,0xff,' +` 0x71,0x00,0xd7,0xff,0x2f,0x00,0xe0,0xff,' +` 0x12,0x00,0xfc,0xff,0x05,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfb,0xff,' +` 0xfb,0xff,0xf9,0xff,0xf9,0xff,0xfa,0xff,' +` 0xfc,0xff,0x01,0x00,0x08,0x00,0x13,0x00,' +` 0x2b,0x00,0x83,0x00,0x97,0x00,0xde,0x00,' +` 0xdb,0x00,0xe1,0x00,0x22,0x01,0x8c,0x01,' +` 0xc1,0x01,0xf0,0x02,0xc5,0x04,0x35,0x05,' +` 0xff,0x05,0x8d,0x06,0x2d,0x07,0xa3,0x07,' +` 0x1e,0x08,0x7a,0x08,0xbf,0x48,0x05,0x09,' +` 0x24,0x09,0x2f,0x09,0x0d,0x09,0xd5,0x08,' +` 0x6a,0x08,0x04,0x08,0x5c,0x07,0x1e,0x07,' +` 0xac,0x06,0xed,0x05,0x20,0x05,0x83,0x04,' +` 0x38,0x03,0x0a,0x02,0xbb,0x01,0x39,0x01,' +` 0x18,0x01,0xd3,0x00,0x92,0x00,0x5d,0x00,' +` 0x39,0x00,0x1d,0x00,0x0d,0x00,0x03,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xff,0xff,0xe7,0xff,0x01,0x00,' +` 0xd9,0xff,0x29,0x00,0xdc,0xff,0x84,0x00,' +` 0x01,0x00,0x20,0x01,0x46,0x00,0xf7,0x01,' +` 0x05,0x01,0x95,0x03,0x52,0x01,0x56,0x04,' +` 0x16,0x00,0xd5,0x03,0x9f,0xfe,0x78,0x03,' +` 0x10,0xfc,0x6e,0x01,0x1c,0xf7,0x1c,0x00,' +` 0xaa,0xf1,0x82,0xff,0x42,0xe9,0x1c,0x03,' +` 0x23,0xd5,0x7c,0x47,0x22,0x37,0x51,0xd2,' +` 0x21,0xfa,0x3e,0xdf,0xb1,0xf1,0x38,0xe3,' +` 0x87,0xef,0xd7,0xe6,0x36,0xf0,0xd6,0xeb,' +` 0xd3,0xf2,0xd3,0xef,0x61,0xf5,0xf3,0xf3,' +` 0xe4,0xf8,0x18,0xf8,0x5a,0xfb,0x3d,0xfb,' +` 0xd2,0xfd,0xa3,0xfd,0x1d,0xff,0x09,0xff,' +` 0xd3,0xff,0xc1,0xff,0x12,0x00,0x00,0x00,' +` 0x0d,0x00,0x02,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x0a,0x00,0x06,0x00,' +` 0x06,0x00,0xd5,0xff,0xb8,0xff,0x33,0xff,' +` 0xea,0xfe,0xef,0xfd,0x7d,0xfd,0xd0,0xfb,' +` 0xd6,0xfa,0xcf,0xf8,0x24,0xf8,0x10,0xf5,' +` 0x3b,0xf4,0x4b,0xf1,0x2e,0xf1,0xe9,0xed,' +` 0x3d,0xee,0xa7,0xe9,0x20,0xec,0x6c,0xe7,' +` 0x30,0xec,0x40,0xe6,0x80,0xef,0x26,0xe4,' +` 0x9c,0xfd,0xea,0x6b,0x96,0xe3,0x6f,0xf9,' +` 0xf7,0xef,0x02,0xfa,0xd7,0xf5,0x75,0xfc,' +` 0x0b,0xfa,0xcc,0xfe,0x1c,0xfe,0xac,0x01,' +` 0x37,0x00,0x92,0x02,0x3e,0x01,0x33,0x03,' +` 0x5a,0x02,0xef,0x02,0xe3,0x01,0xb1,0x01,' +` 0xc2,0x00,0xe9,0x00,0x53,0x00,0x65,0x00,' +` 0x0c,0x00,0x19,0x00,0xf0,0xff,0xfc,0xff,' +` 0xef,0xff,0xfd,0xff,0xff,0xff,0x00,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x05,0x00,0xfd,0xff,' +` 0x1a,0x00,0x0e,0x00,0x54,0x00,0x40,0x00,' +` 0xc1,0x00,0x9e,0x00,0x6e,0x01,0xfa,0x00,' +` 0x1b,0x02,0xa1,0x01,0x7e,0x03,0xd0,0x03,' +` 0xee,0x05,0x02,0x05,0xc1,0x07,0x0f,0x06,' +` 0x09,0x09,0x29,0x06,0xb4,0x0a,0x1c,0x06,' +` 0x9a,0x0c,0x96,0x04,0x06,0x10,0xd6,0xfc,' +` 0xbd,0x40,0x8a,0x1e,0x06,0xff,0x64,0x0d,' +` 0x1d,0x03,0xc1,0x09,0x84,0x03,0x55,0x07,' +` 0x11,0x03,0xe6,0x04,0x82,0x00,0x9a,0x02,' +` 0x32,0x00,0xa5,0x01,0xfb,0xff,0x5b,0x01,' +` 0x19,0x00,0xde,0x00,0xe3,0xff,0x4a,0x00,' +` 0xce,0xff,0x24,0x00,0xd8,0xff,0x0d,0x00,' +` 0xe6,0xff,0x02,0x00,0xf3,0xff,0xfe,0xff,' +` 0xfc,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfc,0xff,0xf8,0xff,' +` 0xf2,0xff,0xec,0xff,0xe9,0xff,0xe2,0xff,' +` 0xdd,0xff,0xd7,0xff,0xd2,0xff,0xce,0xff,' +` 0xd0,0xff,0xdd,0xff,0x3c,0x00,0x58,0x00,' +` 0x39,0x00,0x63,0x00,0xb7,0x00,0x02,0x01,' +` 0x80,0x01,0xd6,0x01,0xcd,0x03,0xfd,0x04,' +` 0x7e,0x05,0x34,0x06,0xba,0x06,0x56,0x07,' +` 0xcc,0x07,0x3e,0x08,0x81,0x48,0xd2,0x08,' +` 0xf2,0x08,0xf0,0x08,0xcb,0x08,0x88,0x08,' +` 0x2f,0x08,0xaf,0x07,0x41,0x07,0x16,0x07,' +` 0x5c,0x06,0xab,0x05,0xf1,0x04,0x3e,0x04,' +` 0x87,0x03,0x17,0x02,0x7e,0x01,0x5e,0x01,' +` 0x06,0x01,0xbd,0x00,0x7e,0x00,0x51,0x00,' +` 0x2d,0x00,0x17,0x00,0x07,0x00,0x06,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xf9,0xff,0xfe,0xff,0xf6,0xff,' +` 0x1c,0x00,0x21,0x00,0x79,0x00,0x7e,0x00,' +` 0x1d,0x01,0x1f,0x01,0x12,0x02,0xec,0x01,' +` 0x42,0x03,0x5b,0x03,0x89,0x04,0xd9,0x02,' +` 0x52,0x04,0x4c,0x02,0xe6,0x03,0xc1,0x00,' +` 0x91,0x02,0xec,0xfc,0x40,0xff,0xa9,0xf8,' +` 0x7d,0xfc,0xd8,0xf2,0x9e,0xfa,0x9a,0xe9,' +` 0x12,0x04,0x91,0x6a,0xdd,0xdd,0x03,0xf3,' +` 0xd5,0xe4,0x41,0xed,0xe9,0xe5,0x89,0xeb,' +` 0x86,0xe7,0xc8,0xec,0xa7,0xeb,0xa1,0xef,' +` 0x0b,0xef,0xab,0xf2,0xd2,0xf2,0x17,0xf6,' +` 0x34,0xf7,0xc9,0xf9,0xde,0xfa,0xb3,0xfc,' +` 0x38,0xfd,0x76,0xfe,0xce,0xfe,0x88,0xff,' +` 0xaf,0xff,0x02,0x00,0x01,0x00,0x12,0x00,' +` 0x09,0x00,0x04,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x0b,0x00,0x00,0x00,0x0d,0x00,' +` 0xcc,0xff,0xc9,0xff,0x19,0xff,0x02,0xff,' +` 0xbc,0xfd,0x98,0xfd,0x9f,0xfb,0x5a,0xfb,' +` 0x20,0xf8,0x22,0xf8,0xbe,0xf3,0xb9,0xf4,' +` 0xc8,0xef,0xd8,0xf1,0xeb,0xeb,0xa7,0xef,' +` 0x59,0xe7,0xd9,0xed,0x6a,0xe4,0xc0,0xef,' +` 0xd6,0xe1,0x3f,0xf6,0xb8,0xd9,0x59,0x1a,' +` 0xc9,0x5e,0xc4,0xd8,0xa6,0x01,0x67,0xec,' +` 0x65,0xff,0x91,0xf4,0xfc,0x00,0xfd,0xf9,' +` 0x5b,0x03,0x12,0xff,0xf2,0x04,0x40,0x01,' +` 0x58,0x05,0x4c,0x02,0x27,0x05,0x48,0x03,' +` 0x90,0x04,0xfe,0x01,0xdb,0x02,0x3e,0x01,' +` 0xae,0x01,0x93,0x00,0xd1,0x00,0x29,0x00,' +` 0x4a,0x00,0xf1,0xff,0x07,0x00,0xf0,0xff,' +` 0xfd,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0xfb,0xff,' +` 0x6d,0x00,0x31,0x00,0x17,0x01,0xaf,0x00,' +` 0x38,0x02,0x8d,0x01,0xb7,0x03,0x0f,0x02,' +` 0x97,0x06,0x18,0x06,0x93,0x0a,0x28,0x08,' +` 0x2d,0x0e,0x21,0x0a,0xd8,0x11,0x3c,0x0a,' +` 0xe0,0x14,0x09,0x0a,0x4a,0x19,0xd5,0x06,' +` 0x17,0x21,0x1a,0xf8,0x7d,0x5a,0xbd,0x69,' +` 0x6a,0xf4,0x76,0x1f,0xc4,0x02,0xad,0x15,' +` 0xfa,0x04,0x26,0x10,0xb4,0x04,0x97,0x09,' +` 0xae,0xff,0x94,0x05,0x18,0xff,0x4b,0x03,' +` 0x9c,0xfe,0xf9,0x01,0x53,0xff,0x2c,0x01,' +` 0x96,0xfe,0x55,0x00,0xe7,0xfe,0x1c,0x00,' +` 0x3d,0xff,0xff,0xff,0x85,0xff,0xf5,0xff,' +` 0xb7,0xff,0xf3,0xff,0xe5,0xff,0xfc,0xff,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff,' +` 0xf5,0xff,0xee,0xff,0xe2,0xff,0xda,0xff,' +` 0xd1,0xff,0xc8,0xff,0xb6,0xff,0xaf,0xff,' +` 0x9c,0xff,0xa4,0xff,0x92,0xff,0xd0,0xff,' +` 0xf7,0xff,0xe2,0xff,0x1f,0x00,0x6d,0x00,' +` 0xb8,0x00,0x3e,0x01,0x82,0x01,0xea,0x02,' +` 0xc4,0x04,0x2a,0x05,0xef,0x05,0x73,0x06,' +` 0x17,0x07,0x8e,0x07,0x06,0x08,0x4d,0x48,' +` 0x9a,0x08,0xb2,0x08,0xa7,0x08,0x89,0x08,' +` 0x3d,0x08,0xf1,0x07,0x62,0x07,0x3b,0x07,' +` 0xd7,0x06,0x26,0x06,0x6f,0x05,0xc9,0x04,' +` 0x04,0x04,0x82,0x03,0x3f,0x02,0x82,0x01,' +` 0x5a,0x01,0xeb,0x00,0xb2,0x00,0x6f,0x00,' +` 0x4a,0x00,0x27,0x00,0x14,0x00,0x0e,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xfe,0xff,0xf0,0xff,0x10,0x00,' +` 0xf4,0xff,0x59,0x00,0x34,0x00,0x0c,0x01,' +` 0xb8,0x00,0x1b,0x02,0x80,0x01,0x7f,0x03,' +` 0x60,0x02,0x04,0x05,0x94,0x03,0x61,0x06,' +` 0xe6,0x02,0xf4,0x06,0xdf,0x01,0xdf,0x06,' +` 0x90,0xff,0xfc,0x05,0x9c,0xfa,0x43,0x03,' +` 0x7c,0xf4,0x0e,0x02,0x89,0xeb,0xf5,0x04,' +` 0x18,0xd7,0x71,0x43,0x8d,0x3d,0x2f,0xd2,' +` 0x03,0xfb,0x7c,0xdf,0x1c,0xf2,0x2c,0xe3,' +` 0x29,0xef,0x5e,0xe6,0x7a,0xf0,0x0f,0xeb,' +` 0x45,0xf2,0x26,0xef,0xf4,0xf4,0x58,0xf3,' +` 0xff,0xf7,0xea,0xf7,0xbc,0xfb,0x5e,0xfb,' +` 0xbc,0xfd,0x9a,0xfd,0x19,0xff,0x07,0xff,' +` 0xd6,0xff,0xc2,0xff,0x0f,0x00,0xfe,0xff,' +` 0x0c,0x00,0x02,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x0a,0x00,0x0b,0x00,0x05,0x00,' +` 0xe7,0xff,0xc0,0xff,0x5d,0xff,0xec,0xfe,' +` 0x2d,0xfe,0x6a,0xfd,0x40,0xfc,0x31,0xfb,' +` 0x77,0xf9,0x54,0xf7,0x03,0xf5,0x8c,0xf3,' +` 0x60,0xf1,0x18,0xf0,0xfa,0xed,0x41,0xed,' +` 0xe2,0xea,0xfb,0xe9,0xeb,0xe8,0xf7,0xe9,' +` 0x21,0xe9,0xbc,0xeb,0x58,0xea,0xba,0xf0,' +` 0x2c,0x6f,0x59,0xee,0x56,0xf5,0x02,0xf5,' +` 0x2c,0xf9,0xfd,0xf9,0x40,0xfd,0x22,0xfe,' +` 0x3b,0x01,0x63,0x02,0xa7,0x03,0xfd,0x03,' +` 0xa1,0x04,0x94,0x04,0x9c,0x04,0xb5,0x04,' +` 0x48,0x04,0x41,0x03,0xeb,0x02,0x2c,0x02,' +` 0xc2,0x01,0x2d,0x01,0xd8,0x00,0x7c,0x00,' +` 0x44,0x00,0x15,0x00,0x06,0x00,0xfb,0xff,' +` 0xfc,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3f,0x00,0xfa,0xff,' +` 0x80,0x00,0x30,0x00,0x3c,0x01,0xb6,0x00,' +` 0x71,0x02,0x9e,0x01,0x2f,0x04,0x7b,0x02,' +` 0xd2,0x07,0x41,0x06,0x39,0x0b,0x56,0x08,' +` 0xce,0x0e,0x2f,0x0a,0x83,0x12,0x4c,0x0a,' +` 0x30,0x15,0xc2,0x09,0x90,0x19,0x2c,0x06,' +` 0x9d,0x21,0xe8,0xf5,0x47,0x69,0xa0,0x5a,' +` 0x77,0xf5,0x26,0x1e,0x50,0x02,0xa0,0x14,' +` 0x1e,0x04,0x3f,0x0f,0x30,0x03,0x79,0x07,' +` 0x75,0xff,0x8b,0x04,0xb6,0xfe,0x74,0x02,' +` 0x3f,0xfe,0x2c,0x01,0xb4,0xfe,0x41,0x00,' +` 0x75,0xfe,0xef,0xff,0xd3,0xfe,0xda,0xff,' +` 0x3a,0xff,0xe1,0xff,0x8c,0xff,0xe2,0xff,' +` 0xc9,0xff,0xf4,0xff,0xf3,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfb,0xff,' +` 0xf4,0xff,0xec,0xff,0xe0,0xff,0xd4,0xff,' +` 0xca,0xff,0xc0,0xff,0xab,0xff,0xa2,0xff,' +` 0x8e,0xff,0x91,0xff,0x82,0xff,0xa9,0xff,' +` 0xcb,0xff,0xcd,0xff,0x06,0x00,0x54,0x00,' +` 0xa0,0x00,0x22,0x01,0x6f,0x01,0x9d,0x02,' +` 0x9f,0x04,0x14,0x05,0xd3,0x05,0x5c,0x06,' +` 0xfd,0x06,0x77,0x07,0xef,0x07,0x38,0x48,' +` 0x80,0x08,0x96,0x08,0x8c,0x08,0x6c,0x08,' +` 0x22,0x08,0xd2,0x07,0x4a,0x07,0x32,0x07,' +` 0xbf,0x06,0x0f,0x06,0x5c,0x05,0xb5,0x04,' +` 0xf5,0x03,0x6f,0x03,0x59,0x02,0x87,0x01,' +` 0x4f,0x01,0xe5,0x00,0xac,0x00,0x6b,0x00,' +` 0x48,0x00,0x24,0x00,0x16,0x00,0x11,0x00,' +` 0x3c,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xff,0xff,0xf2,0xff,0x13,0x00,' +` 0xfd,0xff,0x61,0x00,0x44,0x00,0x1e,0x01,' +` 0xde,0x00,0x39,0x02,0xb9,0x01,0xa6,0x03,' +` 0xab,0x02,0x2f,0x05,0xc0,0x03,0x74,0x06,' +` 0x5f,0x03,0x11,0x07,0x60,0x02,0xea,0x06,' +` 0x19,0x00,0xed,0x05,0x31,0xfb,0xf9,0x02,' +` 0x13,0xf5,0x8c,0x01,0x38,0xec,0x42,0x04,' +` 0x41,0xd7,0x60,0x56,0xbb,0x27,0x84,0xd6,' +` 0xd4,0xf8,0xde,0xe0,0x1b,0xf1,0xf8,0xe3,' +` 0x8b,0xee,0x1e,0xe7,0x31,0xf0,0x65,0xeb,' +` 0x10,0xf2,0x70,0xef,0xd6,0xf4,0x98,0xf3,' +` 0xee,0xf7,0x4e,0xf8,0xc4,0xfb,0x81,0xfb,' +` 0xc2,0xfd,0xb3,0xfd,0x1e,0xff,0x17,0xff,' +` 0xd9,0xff,0xc5,0xff,0x0f,0x00,0x00,0x00,' +` 0x0d,0x00,0x02,0x00,0x3c,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x0c,0x00,0x02,0x00,0x0e,0x00,' +` 0xcb,0xff,0xd6,0xff,0x26,0xff,0x18,0xff,' +` 0xcd,0xfd,0xb6,0xfd,0xa9,0xfb,0xae,0xfb,' +` 0x95,0xf8,0xd8,0xf7,0xdb,0xf3,0xa1,0xf4,' +` 0xcb,0xef,0xba,0xf1,0xdb,0xeb,0xad,0xef,' +` 0xd8,0xe7,0xb3,0xed,0xe3,0xe4,0xc2,0xef,' +` 0x72,0xe2,0x39,0xf6,0xc3,0xda,0xde,0x18,' +` 0x6f,0x60,0xd0,0xd9,0x1d,0x02,0x7e,0xed,' +` 0x38,0x00,0xd4,0xf5,0x0d,0x02,0xa4,0xfb,' +` 0x2f,0x05,0x81,0x00,0x67,0x06,0xaf,0x02,' +` 0xb2,0x06,0x9e,0x03,0x2d,0x06,0xef,0x03,' +` 0x0f,0x05,0xce,0x02,0x90,0x03,0xd4,0x01,' +` 0x2c,0x02,0xf1,0x00,0x17,0x01,0x50,0x00,' +` 0x5e,0x00,0x02,0x00,0x12,0x00,0xf4,0xff,' +` 0xff,0xff,0xfd,0xff,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x15,0x00,0x10,0x00,' +` 0x2b,0x00,0x3b,0x00,0x77,0x00,0x97,0x00,' +` 0xf9,0x00,0x2e,0x01,0xa9,0x01,0x19,0x02,' +` 0x9a,0x03,0xb5,0x03,0xf4,0x04,0x03,0x05,' +` 0x6b,0x06,0x45,0x06,0xc0,0x07,0xa7,0x06,' +` 0x93,0x08,0x2d,0x07,0xa6,0x09,0xe3,0x06,' +` 0x1c,0x0b,0xa0,0x03,0x7d,0x47,0xcf,0x0d,' +` 0xb8,0x04,0xd6,0x08,0x12,0x05,0xe7,0x06,' +` 0x45,0x04,0x61,0x05,0x38,0x02,0xf0,0x01,' +` 0xc3,0x00,0x01,0x01,0x0e,0x00,0x4d,0x00,' +` 0x99,0xff,0xf9,0xff,0x88,0xff,0xa3,0xff,' +` 0x77,0xff,0xa5,0xff,0x90,0xff,0xb9,0xff,' +` 0xb5,0xff,0xd2,0xff,0xcf,0xff,0xe4,0xff,' +` 0xea,0xff,0xf6,0xff,0xfb,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0xdf,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_78mm_azm90_90_13el0_0_13deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_azm90_90_13el0_0_13deg_48khz.m4 new file mode 100644 index 000000000000..31496418a643 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_azm90_90_13el0_0_13deg_48khz.m4 @@ -0,0 +1,1736 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x36,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x36,0x00,0x00,0x04,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x93,0x00,0xf1,0x00,0xc4,0x00,0x38,0x01,' +` 0xfb,0x00,0x88,0x01,0x39,0x01,0xe3,0x01,' +` 0x7c,0x01,0x46,0x02,0xc4,0x01,0xb1,0x02,' +` 0x0e,0x02,0x24,0x03,0x59,0x02,0x9c,0x03,' +` 0xa3,0x02,0x1a,0x04,0xea,0x02,0x9f,0x04,' +` 0x00,0x03,0xc5,0x04,0x1b,0x03,0x49,0x05,' +` 0x41,0x03,0xcb,0x05,0x59,0x03,0x4f,0x06,' +` 0x5d,0x03,0xd8,0x06,0x45,0x03,0x6d,0x07,' +` 0x08,0x03,0x18,0x08,0x93,0x02,0xf0,0x08,' +` 0xc3,0x01,0x2c,0x0a,0x3c,0x00,0x6b,0x0c,' +` 0xc6,0xfc,0x80,0x12,0x61,0xee,0x62,0x78,' +` 0x7d,0x2c,0xb7,0xf4,0xd7,0x0f,0x76,0xfd,' +` 0x1c,0x0b,0xf8,0xff,0xff,0x08,0x0c,0x01,' +` 0xaf,0x07,0x8f,0x01,0xb7,0x06,0xc9,0x01,' +` 0xed,0x05,0xd9,0x01,0x3f,0x05,0xd0,0x01,' +` 0xa2,0x04,0xb5,0x01,0x13,0x04,0x91,0x01,' +` 0x90,0x03,0x66,0x01,0x14,0x03,0x72,0x00,' +` 0xb5,0x01,0x37,0x00,0x66,0x01,0x1a,0x00,' +` 0x1e,0x01,0x03,0x00,0xde,0x00,0xf0,0xff,' +` 0xa8,0x00,0xe2,0xff,0x7b,0x00,0xd8,0xff,' +` 0x57,0x00,0xd3,0xff,0x3a,0x00,0xd1,0xff,' +` 0x24,0x00,0xd2,0xff,0x14,0x00,0xd6,0xff,' +` 0x0b,0x00,0xec,0xff,0x0a,0x00,0xe2,0xff,' +` 0x00,0x00,0xea,0xff,0xfe,0xff,0xf1,0xff,' +` 0xfe,0xff,0xf7,0xff,0xff,0xff,0xfc,0xff,' +` 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf0,0xff,0xe3,0xff,' +` 0xde,0xff,0xc8,0xff,0xc3,0xff,0xa3,0xff,' +` 0x9f,0xff,0x71,0xff,0x64,0xff,0x1f,0xff,' +` 0x12,0xff,0xc7,0xfe,0xc6,0xfe,0x68,0xfe,' +` 0x70,0xfe,0xfe,0xfd,0x10,0xfe,0x89,0xfd,' +` 0xaa,0xfd,0x0c,0xfd,0x3e,0xfd,0x88,0xfc,' +` 0xd0,0xfc,0x00,0xfc,0x63,0xfc,0x76,0xfb,' +` 0xf9,0xfb,0xeb,0xfa,0x95,0xfb,0x63,0xfa,' +` 0x3e,0xfb,0xac,0xf9,0x93,0xfa,0x1a,0xf9,' +` 0x5d,0xfa,0xad,0xf8,0x3c,0xfa,0x4c,0xf8,' +` 0x35,0xfa,0xf5,0xf7,0x4b,0xfa,0xa6,0xf7,' +` 0x86,0xfa,0x59,0xf7,0xee,0xfa,0x01,0xf7,' +` 0x95,0xfb,0x84,0xf6,0xa3,0xfc,0x9f,0xf5,' +` 0x8e,0xfe,0x64,0xf3,0x7f,0x03,0x9b,0xe8,' +` 0x7f,0x74,0x87,0x13,0xac,0xef,0x73,0x02,' +` 0x1b,0xf6,0xef,0xff,0x86,0xf8,0x33,0xff,' +` 0x02,0xfa,0x0b,0xff,0x20,0xfb,0x22,0xff,' +` 0x0d,0xfc,0x58,0xff,0xd9,0xfc,0x9b,0xff,' +` 0x8d,0xfd,0xe2,0xff,0x2b,0xfe,0x28,0x00,' +` 0xb5,0xfe,0x68,0x00,0x2c,0xff,0x9f,0x00,' +` 0xd3,0xff,0x10,0x01,0x20,0x00,0x24,0x01,' +` 0x56,0x00,0x2f,0x01,0x7d,0x00,0x2f,0x01,' +` 0x95,0x00,0x27,0x01,0xa2,0x00,0x16,0x01,' +` 0xa4,0x00,0xff,0x00,0x9e,0x00,0xe4,0x00,' +` 0x92,0x00,0xc5,0x00,0x80,0x00,0xa4,0x00,' +` 0x6c,0x00,0x86,0x00,0x67,0x00,0x6b,0x00,' +` 0x40,0x00,0x49,0x00,0x2d,0x00,0x30,0x00,' +` 0x1c,0x00,0x1c,0x00,0x10,0x00,0x0e,0x00,' +` 0x07,0x00,0x05,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x04,0x00,0x08,0x00,0x0b,0x00,0x13,0x00,' +` 0x17,0x00,0x23,0x00,0x27,0x00,0x38,0x00,' +` 0x3b,0x00,0x51,0x00,0x54,0x00,0x7e,0x00,' +` 0x70,0x00,0x89,0x00,0x83,0x00,0xa8,0x00,' +` 0x99,0x00,0xc5,0x00,0xac,0x00,0xdf,0x00,' +` 0xbb,0x00,0xf5,0x00,0xc3,0x00,0x04,0x01,' +` 0xc2,0x00,0x0b,0x01,0xb7,0x00,0x09,0x01,' +` 0xa0,0x00,0xfd,0x00,0x7b,0x00,0xe5,0x00,' +` 0x47,0x00,0xc3,0x00,0xc7,0xff,0x35,0x00,' +` 0x5c,0xff,0xef,0xff,0xeb,0xfe,0x9c,0xff,' +` 0x6b,0xfe,0x41,0xff,0xdb,0xfd,0xe0,0xfe,' +` 0x3b,0xfd,0x7f,0xfe,0x8a,0xfc,0x26,0xfe,' +` 0xc4,0xfb,0xdf,0xfd,0xde,0xfa,0xc5,0xfd,' +` 0xb5,0xf9,0x1a,0xfe,0xcd,0xf7,0x1c,0x00,' +` 0xe4,0xf0,0xfd,0x78,0xf5,0x05,0x84,0xf4,' +` 0x89,0xfd,0x08,0xf7,0xb5,0xfb,0xae,0xf7,' +` 0xd1,0xfa,0xf1,0xf7,0x48,0xfa,0x18,0xf8,' +` 0xf4,0xf9,0x3d,0xf8,0xc8,0xf9,0x69,0xf8,' +` 0xba,0xf9,0xa1,0xf8,0xc8,0xf9,0xe8,0xf8,' +` 0xee,0xf9,0x3d,0xf9,0x29,0xfa,0x9f,0xf9,' +` 0x82,0xfa,0x62,0xfa,0x29,0xfb,0xdf,0xfa,' +` 0x91,0xfb,0x5f,0xfb,0x00,0xfc,0xe1,0xfb,' +` 0x74,0xfc,0x63,0xfc,0xe8,0xfc,0xe4,0xfc,' +` 0x5a,0xfd,0x5f,0xfd,0xc8,0xfd,0xd4,0xfd,' +` 0x30,0xfe,0x40,0xfe,0x8f,0xfe,0xa1,0xfe,' +` 0xe4,0xfe,0xf6,0xfe,0x31,0xff,0x4d,0xff,' +` 0x7e,0xff,0x91,0xff,0xad,0xff,0xba,0xff,' +` 0xcf,0xff,0xd8,0xff,0xe7,0xff,0xed,0xff,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0xff,' +` 0xfd,0xff,0xfd,0xff,0xfc,0xff,0xfb,0xff,' +` 0xfa,0xff,0xfa,0xff,0xf9,0xff,0xfa,0xff,' +` 0x01,0x00,0xfb,0xff,0xf8,0xff,0xfa,0xff,' +` 0xfb,0xff,0xfd,0xff,0xff,0xff,0x02,0x00,' +` 0x06,0x00,0x0a,0x00,0x0f,0x00,0x15,0x00,' +` 0x1b,0x00,0x23,0x00,0x2b,0x00,0x34,0x00,' +` 0x3e,0x00,0x49,0x00,0x54,0x00,0x62,0x00,' +` 0x6e,0x00,0x7e,0x00,0x8b,0x00,0x03,0x01,' +` 0x30,0x01,0x3e,0x01,0x57,0x01,0x69,0x01,' +` 0x82,0x01,0x95,0x01,0xad,0x01,0xc1,0x01,' +` 0xd9,0x01,0xed,0x01,0x03,0x02,0x17,0x02,' +` 0x2c,0x02,0x3e,0x02,0x52,0x02,0x63,0x02,' +` 0x75,0x02,0x84,0x02,0x94,0x02,0xa0,0x02,' +` 0xae,0x02,0xb7,0x02,0xbe,0x42,0xc8,0x02,' +` 0xcf,0x02,0xd2,0x02,0xd4,0x02,0xd3,0x02,' +` 0xd2,0x02,0xce,0x02,0xca,0x02,0xc3,0x02,' +` 0xbb,0x02,0xb1,0x02,0xa7,0x02,0x99,0x02,' +` 0x8c,0x02,0x7c,0x02,0x6c,0x02,0x5a,0x02,' +` 0x47,0x02,0x34,0x02,0x1f,0x02,0x0a,0x02,' +` 0xf3,0x01,0xe2,0x01,0xec,0x01,0xd1,0x01,' +` 0xba,0x01,0xa0,0x01,0x89,0x01,0x6f,0x01,' +` 0x58,0x01,0x3f,0x01,0x28,0x01,0x10,0x01,' +` 0xfb,0x00,0xe5,0x00,0xd1,0x00,0xbc,0x00,' +` 0xaa,0x00,0x97,0x00,0x87,0x00,0x76,0x00,' +` 0x69,0x00,0x59,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xb7,0x00,0x93,0x00,0xfb,0x00,0xc1,0x00,' +` 0x46,0x01,0xf6,0x00,0x9b,0x01,0x31,0x01,' +` 0xfa,0x01,0x71,0x01,0x62,0x02,0xb6,0x01,' +` 0xd3,0x02,0xfc,0x01,0x4c,0x03,0x43,0x02,' +` 0xcc,0x03,0x88,0x02,0x51,0x04,0xca,0x02,' +` 0xdd,0x04,0xc7,0x02,0x15,0x05,0xe7,0x02,' +` 0xa3,0x05,0x03,0x03,0x33,0x06,0x0e,0x03,' +` 0xc7,0x06,0x01,0x03,0x64,0x07,0xd4,0x02,' +` 0x12,0x08,0x7a,0x02,0xde,0x08,0xdf,0x01,' +` 0xe5,0x09,0xd5,0x00,0x6a,0x0b,0xef,0xfe,' +` 0x2b,0x0e,0xbd,0xfa,0x66,0x15,0x68,0xea,' +` 0x9e,0x6a,0xdf,0x40,0x85,0xee,0x82,0x13,' +` 0x04,0xfb,0x19,0x0d,0x7d,0xfe,0x5b,0x0a,' +` 0x02,0x00,0xb6,0x08,0xc6,0x00,0x8a,0x07,' +` 0x2c,0x01,0x9c,0x06,0x5b,0x01,0xd2,0x05,' +` 0x68,0x01,0x21,0x05,0x5f,0x01,0x82,0x04,' +` 0x48,0x01,0xf4,0x03,0x24,0x01,0x76,0x03,' +` 0xae,0x00,0xf0,0x01,0x14,0x00,0xa0,0x01,' +` 0xfc,0xff,0x50,0x01,0xea,0xff,0x0a,0x01,' +` 0xdc,0xff,0xce,0x00,0xd1,0xff,0x9c,0x00,' +` 0xcb,0xff,0x73,0x00,0xc8,0xff,0x51,0x00,' +` 0xc9,0xff,0x37,0x00,0xcc,0xff,0x24,0x00,' +` 0xd1,0xff,0x1a,0x00,0xe9,0xff,0x1a,0x00,' +` 0xe6,0xff,0x05,0x00,0xea,0xff,0x02,0x00,' +` 0xf1,0xff,0x00,0x00,0xf7,0xff,0x00,0x00,' +` 0xfc,0xff,0x00,0x00,0xff,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf6,0xff,0xed,0xff,' +` 0xe6,0xff,0xd8,0xff,0xce,0xff,0xb9,0xff,' +` 0xad,0xff,0x8f,0xff,0x75,0xff,0x4f,0xff,' +` 0x34,0xff,0xf6,0xfe,0xe2,0xfe,0xa2,0xfe,' +` 0x8d,0xfe,0x41,0xfe,0x2d,0xfe,0xd5,0xfd,' +` 0xc5,0xfd,0x61,0xfd,0x57,0xfd,0xe6,0xfc,' +` 0xe4,0xfc,0x67,0xfc,0x6f,0xfc,0xe5,0xfb,' +` 0xfc,0xfb,0x63,0xfb,0x8c,0xfb,0xe3,0xfa,' +` 0x26,0xfb,0x54,0xfa,0x6b,0xfa,0xab,0xf9,' +` 0x15,0xfa,0x44,0xf9,0xd9,0xf9,0xf0,0xf8,' +` 0xb1,0xf9,0xab,0xf8,0xa0,0xf9,0x74,0xf8,' +` 0xa9,0xf9,0x4b,0xf8,0xd1,0xf9,0x2b,0xf8,' +` 0x1d,0xfa,0x0a,0xf8,0x9a,0xfa,0xd4,0xf7,' +` 0x6c,0xfb,0x47,0xf7,0x14,0xfd,0x18,0xf5,' +` 0x8e,0x04,0x41,0x79,0xd1,0xf1,0x89,0xff,' +` 0x19,0xf8,0xc6,0xfd,0xdc,0xf9,0x87,0xfd,' +` 0xf2,0xfa,0xac,0xfd,0xce,0xfb,0xf9,0xfd,' +` 0x8d,0xfc,0x56,0xfe,0x39,0xfd,0xba,0xfe,' +` 0xd4,0xfd,0x1d,0xff,0x61,0xfe,0x7b,0xff,' +` 0xde,0xfe,0xd1,0xff,0x4b,0xff,0x19,0x00,' +` 0xa5,0xff,0x94,0x00,0x3c,0x00,0xc5,0x00,' +` 0x6d,0x00,0xe0,0x00,0x91,0x00,0xf0,0x00,' +` 0xa9,0x00,0xf4,0x00,0xb5,0x00,0xef,0x00,' +` 0xb7,0x00,0xe3,0x00,0xb0,0x00,0xd0,0x00,' +` 0xa3,0x00,0xb8,0x00,0x90,0x00,0x9d,0x00,' +` 0x7c,0x00,0x81,0x00,0x71,0x00,0x78,0x00,' +` 0x59,0x00,0x4d,0x00,0x38,0x00,0x35,0x00,' +` 0x25,0x00,0x21,0x00,0x16,0x00,0x12,0x00,' +` 0x0b,0x00,0x08,0x00,0x04,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,' +` 0x03,0x00,0x09,0x00,0x08,0x00,0x15,0x00,' +` 0x11,0x00,0x27,0x00,0x1d,0x00,0x3f,0x00,' +` 0x2b,0x00,0x5b,0x00,0x42,0x00,0x8d,0x00,' +` 0x5b,0x00,0xa4,0x00,0x57,0x00,0xc6,0x00,' +` 0x64,0x00,0xeb,0x00,0x6b,0x00,0x10,0x01,' +` 0x6c,0x00,0x31,0x01,0x64,0x00,0x4f,0x01,' +` 0x52,0x00,0x67,0x01,0x33,0x00,0x79,0x01,' +` 0x06,0x00,0x83,0x01,0xc9,0xff,0x85,0x01,' +` 0x79,0xff,0x80,0x01,0xd7,0xfe,0x17,0x01,' +` 0x4b,0xfe,0xfe,0x00,0xb1,0xfd,0xdd,0x00,' +` 0xfd,0xfc,0xbd,0x00,0x2e,0xfc,0xa6,0x00,' +` 0x3f,0xfb,0xa4,0x00,0x26,0xfa,0xc8,0x00,' +` 0xce,0xf8,0x34,0x01,0x0f,0xf7,0x31,0x02,' +` 0x7a,0xf4,0x84,0x04,0x9f,0xef,0x68,0x0b,' +` 0x28,0xdf,0x1d,0x51,0x6c,0x46,0xc1,0xdf,' +` 0xc7,0x09,0x6b,0xee,0x57,0x02,0x56,0xf2,' +` 0x4c,0xff,0x1f,0xf4,0x9d,0xfd,0x2b,0xf5,' +` 0x90,0xfc,0xe7,0xf5,0xe3,0xfb,0x80,0xf6,' +` 0x76,0xfb,0x0b,0xf7,0x3a,0xfb,0x92,0xf7,' +` 0x24,0xfb,0x1c,0xf8,0x2c,0xfb,0xae,0xf8,' +` 0x55,0xfb,0x5f,0xf9,0xea,0xfb,0x2c,0xfa,' +` 0x32,0xfc,0xc8,0xfa,0x87,0xfc,0x62,0xfb,' +` 0xe3,0xfc,0xf9,0xfb,0x43,0xfd,0x8b,0xfc,' +` 0xa4,0xfd,0x16,0xfd,0x04,0xfe,0x99,0xfd,' +` 0x5f,0xfe,0x10,0xfe,0xb3,0xfe,0x7c,0xfe,' +` 0xff,0xfe,0xda,0xfe,0x45,0xff,0x3a,0xff,' +` 0x83,0xff,0x7d,0xff,0xb8,0xff,0xb0,0xff,' +` 0xd5,0xff,0xd3,0xff,0xea,0xff,0xeb,0xff,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0xff,' +` 0xfe,0xff,0xfd,0xff,0xfd,0xff,0xfc,0xff,' +` 0xfb,0xff,0xfb,0xff,0xfb,0xff,0x00,0x00,' +` 0x03,0x00,0x01,0x00,0xfb,0xff,0xfd,0xff,' +` 0xfe,0xff,0x00,0x00,0x03,0x00,0x06,0x00,' +` 0x0a,0x00,0x0e,0x00,0x14,0x00,0x19,0x00,' +` 0x21,0x00,0x27,0x00,0x31,0x00,0x39,0x00,' +` 0x45,0x00,0x4d,0x00,0x5c,0x00,0x65,0x00,' +` 0x79,0x00,0x7c,0x00,0xb0,0x00,0x23,0x01,' +` 0x2e,0x01,0x4b,0x01,0x5b,0x01,0x74,0x01,' +` 0x87,0x01,0xa0,0x01,0xb3,0x01,0xcb,0x01,' +` 0xdf,0x01,0xf6,0x01,0x0a,0x02,0x20,0x02,' +` 0x33,0x02,0x47,0x02,0x59,0x02,0x6c,0x02,' +` 0x7c,0x02,0x8d,0x02,0x9b,0x02,0xa9,0x02,' +` 0xb4,0x02,0xbf,0x02,0xc5,0x42,0xd0,0x02,' +` 0xd7,0x02,0xdb,0x02,0xdd,0x02,0xdd,0x02,' +` 0xdb,0x02,0xd8,0x02,0xd3,0x02,0xcc,0x02,' +` 0xc4,0x02,0xba,0x02,0xb0,0x02,0xa2,0x02,' +` 0x95,0x02,0x85,0x02,0x75,0x02,0x62,0x02,' +` 0x50,0x02,0x3b,0x02,0x28,0x02,0x10,0x02,' +` 0xfd,0x01,0xe1,0x01,0xe7,0x01,0xdc,0x01,' +` 0xbf,0x01,0xa7,0x01,0x8d,0x01,0x75,0x01,' +` 0x5c,0x01,0x44,0x01,0x2c,0x01,0x15,0x01,' +` 0xff,0x00,0xe8,0x00,0xd4,0x00,0xbf,0x00,' +` 0xad,0x00,0x9a,0x00,0x89,0x00,0x78,0x00,' +` 0x6a,0x00,0x5a,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x3c,0x00,0x78,0x00,0x74,0x00,0xed,0x00,' +` 0xb5,0x00,0x34,0x01,0xec,0x00,0x87,0x01,' +` 0x28,0x01,0xe5,0x01,0x6a,0x01,0x4c,0x02,' +` 0xb0,0x01,0xbc,0x02,0xf9,0x01,0x35,0x03,' +` 0x44,0x02,0xb5,0x03,0x90,0x02,0x39,0x04,' +` 0xdb,0x02,0xa2,0x04,0xc1,0x02,0x0e,0x05,' +` 0xf6,0x02,0x98,0x05,0x1b,0x03,0x28,0x06,' +` 0x2e,0x03,0xbc,0x06,0x29,0x03,0x59,0x07,' +` 0x07,0x03,0x04,0x08,0xba,0x02,0xca,0x08,' +` 0x2f,0x02,0xc4,0x09,0x40,0x01,0x2d,0x0b,' +` 0x8e,0xff,0x9f,0x0d,0xea,0xfb,0x9b,0x13,' +` 0x87,0xef,0xc4,0x3e,0x6a,0x6c,0x8e,0xea,' +` 0x0f,0x15,0x89,0xfa,0xaa,0x0d,0x74,0xfe,' +` 0xbb,0x0a,0x1c,0x00,0x07,0x09,0xf0,0x00,' +` 0xd5,0x07,0x5e,0x01,0xe4,0x06,0x93,0x01,' +` 0x1a,0x06,0xa5,0x01,0x68,0x05,0x9f,0x01,' +` 0xc8,0x04,0x8a,0x01,0x30,0x04,0x66,0x01,' +` 0xa2,0x03,0x40,0x01,0x11,0x03,0x3c,0x00,' +` 0xd5,0x01,0x1c,0x00,0x82,0x01,0x09,0x00,' +` 0x39,0x01,0xf9,0xff,0xf8,0x00,0xec,0xff,' +` 0xc1,0x00,0xe2,0xff,0x93,0x00,0xdc,0xff,' +` 0x6e,0x00,0xda,0xff,0x50,0x00,0xda,0xff,' +` 0x38,0x00,0xdd,0xff,0x38,0x00,0xf3,0xff,' +` 0x28,0x00,0xf4,0xff,0x1b,0x00,0xf4,0xff,' +` 0x08,0x00,0xf2,0xff,0x04,0x00,0xf7,0xff,' +` 0x02,0x00,0xfb,0xff,0x01,0x00,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf4,0xff,0xef,0xff,' +` 0xe3,0xff,0xdc,0xff,0xc9,0xff,0xc0,0xff,' +` 0x9b,0xff,0x92,0xff,0x68,0xff,0x5e,0xff,' +` 0x29,0xff,0x1c,0xff,0xc6,0xfe,0xc3,0xfe,' +` 0x6b,0xfe,0x6c,0xfe,0x03,0xfe,0x0c,0xfe,' +` 0x91,0xfd,0xa5,0xfd,0x17,0xfd,0x38,0xfd,' +` 0x96,0xfc,0xc9,0xfc,0x11,0xfc,0x5a,0xfc,' +` 0x89,0xfb,0xee,0xfb,0x02,0xfb,0x89,0xfb,' +` 0x71,0xfa,0xd8,0xfa,0xb4,0xf9,0x80,0xfa,' +` 0x35,0xf9,0x36,0xfa,0xc0,0xf8,0x05,0xfa,' +` 0x62,0xf8,0xf4,0xf9,0x12,0xf8,0x00,0xfa,' +` 0xcb,0xf7,0x2c,0xfa,0x88,0xf7,0x81,0xfa,' +` 0x3f,0xf7,0x0e,0xfb,0xdb,0xf6,0xf4,0xfb,' +` 0x24,0xf6,0x9b,0xfd,0x53,0xf4,0xd7,0x01,' +` 0x21,0xeb,0x58,0x76,0x4d,0x0e,0x9e,0xf1,' +` 0xef,0x00,0xde,0xf6,0xf5,0xfe,0xe8,0xf8,' +` 0x6f,0xfe,0x33,0xfa,0x61,0xfe,0x31,0xfb,' +` 0x88,0xfe,0x07,0xfc,0xc8,0xfe,0xc2,0xfc,' +` 0x12,0xff,0x68,0xfd,0x60,0xff,0xfc,0xfd,' +` 0xaa,0xff,0x7b,0xfe,0xea,0xff,0xe7,0xfe,' +` 0x23,0x00,0x40,0xff,0x81,0x00,0xe1,0xff,' +` 0xb2,0x00,0x14,0x00,0xc7,0x00,0x3c,0x00,' +` 0xd1,0x00,0x59,0x00,0xd2,0x00,0x6a,0x00,' +` 0xcb,0x00,0x71,0x00,0xbd,0x00,0x71,0x00,' +` 0xab,0x00,0x6b,0x00,0x95,0x00,0x60,0x00,' +` 0x7d,0x00,0x5d,0x00,0x79,0x00,0x50,0x00,' +` 0x5c,0x00,0x3c,0x00,0x43,0x00,0x25,0x00,' +` 0x25,0x00,0x16,0x00,0x16,0x00,0x0c,0x00,' +` 0x0b,0x00,0x05,0x00,0x04,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x04,0x00,0x04,0x00,0x0c,0x00,0x09,0x00,' +` 0x19,0x00,0x11,0x00,0x2b,0x00,0x1f,0x00,' +` 0x4c,0x00,0x30,0x00,0x69,0x00,0x3e,0x00,' +` 0x8a,0x00,0x3f,0x00,0x93,0x00,0x40,0x00,' +` 0xb1,0x00,0x41,0x00,0xce,0x00,0x3d,0x00,' +` 0xe9,0x00,0x31,0x00,0x00,0x01,0x1b,0x00,' +` 0x12,0x01,0xfa,0xff,0x1d,0x01,0xcc,0xff,' +` 0x22,0x01,0x8e,0xff,0x20,0x01,0x40,0xff,' +` 0xd4,0x00,0x8e,0xfe,0xb6,0x00,0x14,0xfe,' +` 0x9a,0x00,0x85,0xfd,0x7c,0x00,0xda,0xfc,' +` 0x5a,0x00,0x13,0xfc,0x42,0x00,0x2e,0xfb,' +` 0x3c,0x00,0x20,0xfa,0x5a,0x00,0xd8,0xf8,' +` 0xbc,0x00,0x30,0xf7,0xa2,0x01,0xc3,0xf4,' +` 0xc1,0x03,0x4d,0xf0,0xe4,0x09,0x11,0xe2,' +` 0x9e,0x3c,0xa8,0x59,0x44,0xde,0xee,0x09,' +` 0x38,0xee,0x2b,0x02,0x32,0xf2,0x12,0xff,' +` 0xfa,0xf3,0x63,0xfd,0x02,0xf5,0x56,0xfc,' +` 0xb9,0xf5,0xa9,0xfb,0x4d,0xf6,0x3b,0xfb,' +` 0xd3,0xf6,0xfe,0xfa,0x56,0xf7,0xe7,0xfa,' +` 0xdf,0xf7,0xfb,0xfa,0x77,0xf8,0x2a,0xfb,' +` 0x11,0xf9,0x74,0xfb,0xf9,0xf9,0x01,0xfc,' +` 0x95,0xfa,0x56,0xfc,0x2e,0xfb,0xb4,0xfc,' +` 0xc5,0xfb,0x16,0xfd,0x59,0xfc,0x79,0xfd,' +` 0xe6,0xfc,0xda,0xfd,0x6b,0xfd,0x38,0xfe,' +` 0xe6,0xfd,0x8f,0xfe,0x55,0xfe,0xdd,0xfe,' +` 0xbd,0xfe,0x38,0xff,0x1b,0xff,0x6f,0xff,' +` 0x5f,0xff,0x9d,0xff,0x98,0xff,0xc9,0xff,' +` 0xc5,0xff,0xe1,0xff,0xe1,0xff,0xf2,0xff,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,' +` 0xff,0xff,0xfe,0xff,0xff,0xff,0x04,0x00,' +` 0x04,0x00,0x06,0x00,0x08,0x00,0x0b,0x00,' +` 0x0b,0x00,0x05,0x00,0x07,0x00,0x0a,0x00,' +` 0x0c,0x00,0x11,0x00,0x14,0x00,0x1b,0x00,' +` 0x1f,0x00,0x27,0x00,0x2d,0x00,0x37,0x00,' +` 0x3e,0x00,0x4a,0x00,0x52,0x00,0x61,0x00,' +` 0x68,0x00,0x7c,0x00,0x7d,0x00,0xbb,0x00,' +` 0x22,0x01,0x2a,0x01,0x48,0x01,0x58,0x01,' +` 0x74,0x01,0x87,0x01,0xa0,0x01,0xb3,0x01,' +` 0xcc,0x01,0xdf,0x01,0xf7,0x01,0x0a,0x02,' +` 0x21,0x02,0x34,0x02,0x49,0x02,0x5b,0x02,' +` 0x6f,0x02,0x80,0x02,0x91,0x02,0xa0,0x02,' +` 0xaf,0x02,0xbb,0x02,0xc7,0x02,0xd1,0x02,' +` 0xd7,0x42,0xe2,0x02,0xe8,0x02,0xed,0x02,' +` 0xf0,0x02,0xf2,0x02,0xf2,0x02,0xef,0x02,' +` 0xe9,0x02,0xe3,0x02,0xda,0x02,0xd1,0x02,' +` 0xc5,0x02,0xb9,0x02,0xaa,0x02,0x9b,0x02,' +` 0x89,0x02,0x78,0x02,0x64,0x02,0x51,0x02,' +` 0x3a,0x02,0x26,0x02,0x0c,0x02,0xf9,0x01,' +` 0xdb,0x01,0xd8,0x01,0xd4,0x01,0xb5,0x01,' +` 0x9e,0x01,0x82,0x01,0x6a,0x01,0x50,0x01,' +` 0x38,0x01,0x20,0x01,0x09,0x01,0xf2,0x00,' +` 0xdc,0x00,0xc8,0x00,0xb4,0x00,0xa1,0x00,' +` 0x8e,0x00,0x7f,0x00,0x6d,0x00,0x61,0x00,' +` 0x3f,0x00,0x2d,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x1a,0x00,0x2a,0x00,0x27,0x00,0x3c,0x00,' +` 0x38,0x00,0x51,0x00,0x61,0x00,0x97,0x00,' +` 0x8a,0x00,0xbd,0x00,0xae,0x00,0xea,0x00,' +` 0xd5,0x00,0x1b,0x01,0xff,0x00,0x51,0x01,' +` 0x2b,0x01,0x8a,0x01,0x58,0x01,0xc4,0x01,' +` 0x86,0x01,0x03,0x02,0x92,0x01,0x1a,0x02,' +` 0xb7,0x01,0x55,0x02,0xdb,0x01,0x90,0x02,' +` 0xfb,0x01,0xca,0x02,0x15,0x02,0x04,0x03,' +` 0x27,0x02,0x3d,0x03,0x2f,0x02,0x76,0x03,' +` 0x2a,0x02,0xb3,0x03,0x10,0x02,0xf7,0x03,' +` 0xdb,0x01,0x51,0x04,0x74,0x01,0xe6,0x04,' +` 0x9a,0x00,0x40,0x06,0xed,0xfd,0xf8,0x0d,' +` 0x80,0x40,0xc1,0xfa,0x2f,0x07,0xd7,0xff,' +` 0xfc,0x04,0xe7,0x00,0x20,0x04,0x4e,0x01,' +` 0x9d,0x03,0x79,0x01,0x3d,0x03,0x86,0x01,' +` 0xec,0x02,0x81,0x01,0xa3,0x02,0x72,0x01,' +` 0x60,0x02,0x59,0x01,0x1e,0x02,0x3c,0x01,' +` 0xe0,0x01,0x1d,0x01,0xa5,0x01,0xfd,0x00,' +` 0x6e,0x01,0xe0,0x00,0x30,0x01,0x59,0x00,' +` 0xad,0x00,0x44,0x00,0x8e,0x00,0x35,0x00,' +` 0x73,0x00,0x28,0x00,0x5c,0x00,0x1d,0x00,' +` 0x48,0x00,0x14,0x00,0x38,0x00,0x0d,0x00,' +` 0x2a,0x00,0x07,0x00,0x22,0x00,0x11,0x00,' +` 0x1f,0x00,0x0b,0x00,0x16,0x00,0x07,0x00,' +` 0x0f,0x00,0x04,0x00,0x0a,0x00,0x02,0x00,' +` 0x06,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xf9,0xff,0xf7,0xff,' +` 0xea,0xff,0xe6,0xff,0xcf,0xff,0xce,0xff,' +` 0xab,0xff,0xae,0xff,0x7b,0xff,0x84,0xff,' +` 0x3f,0xff,0x51,0xff,0xf6,0xfe,0x12,0xff,' +` 0x88,0xfe,0xb7,0xfe,0x23,0xfe,0x65,0xfe,' +` 0xb2,0xfd,0x0d,0xfe,0x36,0xfd,0xb0,0xfd,' +` 0xb2,0xfc,0x50,0xfd,0x28,0xfc,0xf1,0xfc,' +` 0x9a,0xfb,0x94,0xfc,0x0b,0xfb,0x25,0xfc,' +` 0x26,0xfa,0xaf,0xfb,0x90,0xf9,0x67,0xfb,' +` 0xf9,0xf8,0x31,0xfb,0x65,0xf8,0x11,0xfb,' +` 0xd4,0xf7,0x0b,0xfb,0x45,0xf7,0x2e,0xfb,' +` 0xc0,0xf6,0x86,0xfb,0x32,0xf6,0x18,0xfc,' +` 0x8b,0xf5,0x03,0xfd,0xa2,0xf4,0x7a,0xfe,' +` 0x1a,0xf3,0x1a,0x01,0xca,0xef,0x54,0x07,' +` 0x02,0xe4,0xda,0x31,0xff,0x61,0x99,0xdf,' +` 0x1e,0x0a,0x1e,0xf0,0x69,0x03,0xac,0xf4,' +` 0x32,0x01,0x0a,0xf7,0x42,0x00,0xa1,0xf8,' +` 0xdb,0xff,0xd8,0xf9,0xba,0xff,0xd9,0xfa,' +` 0xbe,0xff,0xb4,0xfb,0xd2,0xff,0x6c,0xfc,' +` 0xee,0xff,0x0d,0xfd,0x0e,0x00,0x9a,0xfd,' +` 0x2e,0x00,0x15,0xfe,0x4e,0x00,0x7a,0xfe,' +` 0x8c,0x00,0x2c,0xff,0xaf,0x00,0x69,0xff,' +` 0xb7,0x00,0x9e,0xff,0xb7,0x00,0xc9,0xff,' +` 0xb1,0x00,0xe8,0xff,0xa7,0x00,0xfe,0xff,' +` 0x98,0x00,0x0c,0x00,0x86,0x00,0x14,0x00,' +` 0x86,0x00,0x2e,0x00,0x70,0x00,0x28,0x00,' +` 0x57,0x00,0x20,0x00,0x41,0x00,0x18,0x00,' +` 0x2d,0x00,0x10,0x00,0x1c,0x00,0x07,0x00,' +` 0x0c,0x00,0x03,0x00,0x05,0x00,0x01,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x05,0x00,' +` 0x02,0x00,0x0c,0x00,0x06,0x00,0x1c,0x00,' +` 0x0e,0x00,0x2c,0x00,0x15,0x00,0x3f,0x00,' +` 0x1c,0x00,0x55,0x00,0x23,0x00,0x6d,0x00,' +` 0x28,0x00,0x82,0x00,0x0c,0x00,0x81,0x00,' +` 0x03,0x00,0x92,0x00,0xf2,0xff,0x9f,0x00,' +` 0xda,0xff,0xa9,0x00,0xb7,0xff,0xad,0x00,' +` 0x89,0xff,0xad,0x00,0x50,0xff,0xa7,0x00,' +` 0x07,0xff,0x50,0x00,0x65,0xfe,0x38,0x00,' +` 0xf8,0xfd,0x1a,0x00,0x79,0xfd,0xfa,0xff,' +` 0xe8,0xfc,0xda,0xff,0x43,0xfc,0xbf,0xff,' +` 0x86,0xfb,0xaa,0xff,0xa6,0xfa,0xa8,0xff,' +` 0xa1,0xf9,0xcd,0xff,0x65,0xf8,0x39,0x00,' +` 0xc8,0xf6,0x32,0x01,0x5f,0xf4,0x77,0x03,' +` 0xbf,0xef,0x49,0x0a,0x18,0xdf,0x6f,0x5f,' +` 0xf0,0x34,0x09,0xe3,0xb1,0x07,0x5c,0xef,' +` 0x3d,0x01,0xcf,0xf2,0x8b,0xfe,0x69,0xf4,' +` 0x0b,0xfd,0x5d,0xf5,0x1c,0xfc,0x0c,0xf6,' +` 0x88,0xfb,0xa1,0xf6,0x30,0xfb,0x2c,0xf7,' +` 0x0f,0xfb,0xc1,0xf7,0x14,0xfb,0x56,0xf8,' +` 0x35,0xfb,0xee,0xf8,0x6c,0xfb,0x88,0xf9,' +` 0xb5,0xfb,0x21,0xfa,0x2b,0xfc,0x09,0xfb,' +` 0x9b,0xfc,0x9a,0xfb,0xf9,0xfc,0x2a,0xfc,' +` 0x58,0xfd,0xb5,0xfc,0xb7,0xfd,0x3a,0xfd,' +` 0x13,0xfe,0xb6,0xfd,0x6b,0xfe,0x29,0xfe,' +` 0xbb,0xfe,0x97,0xfe,0x1d,0xff,0xf7,0xfe,' +` 0x56,0xff,0x40,0xff,0x88,0xff,0x7d,0xff,' +` 0xb1,0xff,0xac,0xff,0xd1,0xff,0xd0,0xff,' +` 0xe8,0xff,0xeb,0xff,0xf7,0xff,0xf9,0xff,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,' +` 0x03,0x00,0x05,0x00,0x06,0x00,0x08,0x00,' +` 0x09,0x00,0x0c,0x00,0x0e,0x00,0x11,0x00,' +` 0x15,0x00,0x18,0x00,0x1e,0x00,0x1f,0x00,' +` 0x18,0x00,0x1e,0x00,0x22,0x00,0x28,0x00,' +` 0x2e,0x00,0x35,0x00,0x3c,0x00,0x44,0x00,' +` 0x4d,0x00,0x56,0x00,0x61,0x00,0x6b,0x00,' +` 0x78,0x00,0x81,0x00,0x9d,0x00,0x0a,0x01,' +` 0x20,0x01,0x36,0x01,0x4a,0x01,0x61,0x01,' +` 0x77,0x01,0x8e,0x01,0xa5,0x01,0xbd,0x01,' +` 0xd3,0x01,0xeb,0x01,0x01,0x02,0x17,0x02,' +` 0x2b,0x02,0x40,0x02,0x53,0x02,0x66,0x02,' +` 0x78,0x02,0x89,0x02,0x9a,0x02,0xa9,0x02,' +` 0xb8,0x02,0xc5,0x02,0xd1,0x02,0xdc,0x02,' +` 0xe6,0x02,0xea,0x42,0xf5,0x02,0xfa,0x02,' +` 0xff,0x02,0x01,0x03,0x03,0x03,0x02,0x03,' +` 0x01,0x03,0xfc,0x02,0xf8,0x02,0xef,0x02,' +` 0xe8,0x02,0xdb,0x02,0xd0,0x02,0xc0,0x02,' +` 0xb2,0x02,0x9e,0x02,0x8e,0x02,0x78,0x02,' +` 0x65,0x02,0x4d,0x02,0x3a,0x02,0x20,0x02,' +` 0x0b,0x02,0xef,0x01,0xdc,0x01,0xba,0x01,' +` 0xbd,0x01,0xb1,0x01,0x93,0x01,0x7a,0x01,' +` 0x60,0x01,0x46,0x01,0x2e,0x01,0x15,0x01,' +` 0xfe,0x00,0xe6,0x00,0xd2,0x00,0xbb,0x00,' +` 0xaa,0x00,0x94,0x00,0x87,0x00,0x64,0x00,' +` 0x44,0x00,0x3e,0x00,0x32,0x00,0x2b,0x00,' +` 0x23,0x00,0x1d,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x11,0x00,0x28,0x00,0x1f,0x00,0x42,0x00,' +` 0x32,0x00,0x64,0x00,0x4b,0x00,0x8f,0x00,' +` 0x6a,0x00,0xc3,0x00,0x90,0x00,0xfe,0x00,' +` 0xea,0x00,0xad,0x01,0x46,0x01,0x0c,0x02,' +` 0x8f,0x01,0x77,0x02,0xda,0x01,0xec,0x02,' +` 0x29,0x02,0x66,0x03,0x7d,0x02,0xe2,0x03,' +` 0x78,0x02,0x3b,0x04,0xbf,0x02,0xc0,0x04,' +` 0xfb,0x02,0x4b,0x05,0x2d,0x03,0xd9,0x05,' +` 0x51,0x03,0x6b,0x06,0x62,0x03,0xfe,0x06,' +` 0x58,0x03,0x99,0x07,0x2f,0x03,0x43,0x08,' +` 0xdd,0x02,0x09,0x09,0x4c,0x02,0x06,0x0a,' +` 0x55,0x01,0x74,0x0b,0x99,0xff,0xf8,0x0d,' +` 0xe6,0xfb,0x24,0x14,0x2e,0xef,0x37,0x41,' +` 0xfe,0x6a,0x98,0xea,0x8e,0x15,0xb2,0xfa,' +` 0x21,0x0e,0xb3,0xfe,0x32,0x0b,0x6c,0x00,' +` 0x83,0x09,0x4f,0x01,0x58,0x08,0xc9,0x01,' +` 0x69,0x07,0x01,0x02,0x9d,0x06,0x14,0x02,' +` 0xea,0x05,0x10,0x02,0x47,0x05,0xfa,0x01,' +` 0xb1,0x04,0xda,0x01,0x25,0x04,0xb4,0x01,' +` 0xa5,0x03,0x8b,0x01,0x2d,0x03,0x63,0x01,' +` 0xaf,0x02,0x80,0x00,0xaa,0x01,0x62,0x00,' +` 0x65,0x01,0x50,0x00,0x27,0x01,0x3f,0x00,' +` 0xf2,0x00,0x31,0x00,0xc4,0x00,0x1f,0x00,' +` 0xaf,0x00,0x3a,0x00,0x8e,0x00,0x2b,0x00,' +` 0x6c,0x00,0x20,0x00,0x50,0x00,0x17,0x00,' +` 0x39,0x00,0x10,0x00,0x26,0x00,0x0a,0x00,' +` 0x17,0x00,0x05,0x00,0x0c,0x00,0x02,0x00,' +` 0x05,0x00,0x01,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfd,0xff,0xfb,0xff,' +` 0xf3,0xff,0xef,0xff,0xe1,0xff,0xdd,0xff,' +` 0xc6,0xff,0xc3,0xff,0xa1,0xff,0xa0,0xff,' +` 0x71,0xff,0x74,0xff,0x36,0xff,0x3f,0xff,' +` 0xf0,0xfe,0x01,0xff,0xa2,0xfe,0xb1,0xfe,' +` 0x1f,0xfe,0x53,0xfe,0xb9,0xfd,0xfa,0xfd,' +` 0x48,0xfd,0x9e,0xfd,0xcf,0xfc,0x41,0xfd,' +` 0x51,0xfc,0xe5,0xfc,0xca,0xfb,0x47,0xfc,' +` 0x0e,0xfb,0xeb,0xfb,0x85,0xfa,0x97,0xfb,' +` 0xfe,0xf9,0x4e,0xfb,0x7a,0xf9,0x12,0xfb,' +` 0xfa,0xf8,0xe9,0xfa,0x81,0xf8,0xda,0xfa,' +` 0x0e,0xf8,0xe7,0xfa,0x9a,0xf7,0x16,0xfb,' +` 0x1f,0xf7,0x7a,0xfb,0x9d,0xf6,0x2c,0xfc,' +` 0xe8,0xf5,0x53,0xfd,0xad,0xf4,0x7b,0xff,' +` 0xd3,0xf1,0x32,0x05,0x0d,0xe5,0xa0,0x70,' +` 0x84,0x1a,0x38,0xec,0xa7,0x03,0x20,0xf4,' +` 0x30,0x00,0xde,0xf6,0xfe,0xfe,0x70,0xf8,' +` 0x86,0xfe,0x8f,0xf9,0x60,0xfe,0x6f,0xfa,' +` 0x5d,0xfe,0x2b,0xfb,0x74,0xfe,0xd0,0xfb,' +` 0x98,0xfe,0x63,0xfc,0xc3,0xfe,0xe9,0xfc,' +` 0xf2,0xfe,0x61,0xfd,0x21,0xff,0xcd,0xfd,' +` 0x4f,0xff,0x2d,0xfe,0x79,0xff,0x7e,0xfe,' +` 0xd5,0xff,0x0e,0xff,0xeb,0xff,0x42,0xff,' +` 0xfe,0xff,0x6f,0xff,0x0a,0x00,0x94,0xff,' +` 0x12,0x00,0xb2,0xff,0x14,0x00,0xd7,0xff,' +` 0x37,0x00,0xef,0xff,0x2e,0x00,0xf7,0xff,' +` 0x26,0x00,0xfc,0xff,0x1d,0x00,0xff,0xff,' +` 0x15,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,' +` 0x09,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x02,0x00,0xff,0xff,' +` 0x05,0x00,0xfe,0xff,0x09,0x00,0xfd,0xff,' +` 0x0f,0x00,0xfa,0xff,0x17,0x00,0xf6,0xff,' +` 0x1f,0x00,0xf0,0xff,0x29,0x00,0xe8,0xff,' +` 0x32,0x00,0xda,0xff,0x3c,0x00,0xb9,0xff,' +` 0x1c,0x00,0x91,0xff,0x1b,0x00,0x6c,0xff,' +` 0x16,0x00,0x3f,0xff,0x0d,0x00,0x08,0xff,' +` 0x00,0x00,0xc4,0xfe,0xa5,0xff,0x37,0xfe,' +` 0x90,0xff,0xd6,0xfd,0x6e,0xff,0x69,0xfd,' +` 0x4a,0xff,0xee,0xfc,0x26,0xff,0x65,0xfc,' +` 0x05,0xff,0xcc,0xfb,0xeb,0xfe,0x21,0xfb,' +` 0xdd,0xfe,0x60,0xfa,0xe4,0xfe,0x80,0xf9,' +` 0x0d,0xff,0x6a,0xf8,0x6d,0xff,0x01,0xf7,' +` 0x44,0x00,0xf1,0xf4,0x29,0x02,0x25,0xf1,' +` 0x70,0x07,0x59,0xe5,0x1f,0x2e,0x5e,0x64,' +` 0x7e,0xdf,0x96,0x08,0x1a,0xef,0x5e,0x01,' +` 0xe4,0xf2,0x99,0xfe,0x97,0xf4,0x1d,0xfd,' +` 0x95,0xf5,0x36,0xfc,0x4c,0xf6,0xb2,0xfb,' +` 0xee,0xf6,0x69,0xfb,0x7f,0xf7,0x48,0xfb,' +` 0x0a,0xf8,0x48,0xfb,0x99,0xf8,0x66,0xfb,' +` 0x2a,0xf9,0x97,0xfb,0xbc,0xf9,0xd8,0xfb,' +` 0x4f,0xfa,0x25,0xfc,0xe3,0xfa,0x7e,0xfc,' +` 0xaf,0xfb,0x10,0xfd,0x3a,0xfc,0x67,0xfd,' +` 0xbf,0xfc,0xbf,0xfd,0x3d,0xfd,0x16,0xfe,' +` 0xb5,0xfd,0x66,0xfe,0x2f,0xfe,0xda,0xfe,' +` 0x98,0xfe,0x16,0xff,0xec,0xfe,0x4e,0xff,' +` 0x34,0xff,0x80,0xff,0x70,0xff,0xa8,0xff,' +` 0xa1,0xff,0xc8,0xff,0xc6,0xff,0xe1,0xff,' +` 0xe2,0xff,0xf1,0xff,0xf3,0xff,0xfb,0xff,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x02,0x00,0x03,0x00,' +` 0x04,0x00,0x06,0x00,0x08,0x00,0x0b,0x00,' +` 0x0e,0x00,0x11,0x00,0x15,0x00,0x19,0x00,' +` 0x1d,0x00,0x22,0x00,0x27,0x00,0x2e,0x00,' +` 0x34,0x00,0x3b,0x00,0x44,0x00,0x3c,0x00,' +` 0x3f,0x00,0x4a,0x00,0x50,0x00,0x5b,0x00,' +` 0x61,0x00,0x6f,0x00,0x75,0x00,0x87,0x00,' +` 0x88,0x00,0xbc,0x00,0x13,0x01,0x1c,0x01,' +` 0x36,0x01,0x46,0x01,0x5e,0x01,0x70,0x01,' +` 0x88,0x01,0x9c,0x01,0xb4,0x01,0xc8,0x01,' +` 0xe0,0x01,0xf5,0x01,0x0c,0x02,0x21,0x02,' +` 0x37,0x02,0x4b,0x02,0x60,0x02,0x74,0x02,' +` 0x86,0x02,0x97,0x02,0xa7,0x02,0xb5,0x02,' +` 0xc3,0x02,0xd0,0x02,0xdb,0x02,0xe6,0x02,' +` 0xef,0x02,0xf7,0x02,0xf9,0x42,0x02,0x03,' +` 0x05,0x03,0x08,0x03,0x09,0x03,0x09,0x03,' +` 0x07,0x03,0x04,0x03,0xfe,0x02,0xf9,0x02,' +` 0xf0,0x02,0xe8,0x02,0xdc,0x02,0xd1,0x02,' +` 0xc2,0x02,0xb4,0x02,0xa2,0x02,0x92,0x02,' +` 0x7e,0x02,0x6b,0x02,0x54,0x02,0x3f,0x02,' +` 0x26,0x02,0x10,0x02,0xf6,0x01,0xe0,0x01,' +` 0xc4,0x01,0xb0,0x01,0x8f,0x01,0x81,0x01,' +` 0x82,0x01,0x64,0x01,0x4d,0x01,0x33,0x01,' +` 0x1b,0x01,0x03,0x01,0xec,0x00,0xd7,0x00,' +` 0xc0,0x00,0xaf,0x00,0x7d,0x00,0x61,0x00,' +` 0x59,0x00,0x4b,0x00,0x41,0x00,0x36,0x00,' +` 0x2e,0x00,0x26,0x00,0x1f,0x00,0x18,0x00,' +` 0x13,0x00,0x0e,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x03,0x00,0x09,0x00,0x08,0x00,0x16,0x00,' +` 0x12,0x00,0x2a,0x00,0x20,0x00,0x45,0x00,' +` 0x32,0x00,0x69,0x00,0x4a,0x00,0x95,0x00,' +` 0x67,0x00,0xc9,0x00,0x8a,0x00,0x06,0x01,' +` 0xb1,0x00,0x4b,0x01,0xe7,0x00,0x05,0x02,' +` 0x7d,0x01,0x73,0x02,0xc1,0x01,0xe8,0x02,' +` 0x11,0x02,0x2b,0x03,0x17,0x02,0xa6,0x03,' +` 0x55,0x02,0x28,0x04,0x8e,0x02,0xac,0x04,' +` 0xbe,0x02,0x34,0x05,0xe3,0x02,0xc1,0x05,' +` 0xfc,0x02,0x54,0x06,0x04,0x03,0xf0,0x06,' +` 0xf6,0x02,0x97,0x07,0xc8,0x02,0x53,0x08,' +` 0x6f,0x02,0x31,0x09,0xd2,0x01,0x4e,0x0a,' +` 0xc6,0x00,0xef,0x0b,0xdd,0xfe,0xcd,0x0e,' +` 0xb1,0xfa,0xfa,0x15,0x91,0xeb,0xf9,0x52,' +` 0xc6,0x5b,0x68,0xea,0x4f,0x16,0x3a,0xfa,' +` 0xcd,0x0e,0x6b,0xfe,0xc8,0x0b,0x43,0x00,' +` 0x07,0x0a,0x3b,0x01,0xd0,0x08,0xc5,0x01,' +` 0xdf,0x07,0x12,0x02,0x16,0x07,0x37,0x02,' +` 0x65,0x06,0x41,0x02,0xc5,0x05,0x38,0x02,' +` 0x31,0x05,0x22,0x02,0xa6,0x04,0x02,0x02,' +` 0x25,0x04,0xdc,0x01,0xaa,0x03,0xb0,0x01,' +` 0x38,0x03,0x7f,0x01,0xd4,0x02,0x04,0x01,' +` 0xb4,0x01,0x9f,0x00,0x74,0x01,0x87,0x00,' +` 0x2e,0x01,0x77,0x00,0x2a,0x01,0x75,0x00,' +` 0xee,0x00,0x5f,0x00,0xbc,0x00,0x4b,0x00,' +` 0x8f,0x00,0x38,0x00,0x6a,0x00,0x28,0x00,' +` 0x4a,0x00,0x1b,0x00,0x32,0x00,0x11,0x00,' +` 0x1e,0x00,0x0a,0x00,0x10,0x00,0x05,0x00,' +` 0x07,0x00,0x02,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xfe,0xff,0xf9,0xff,0xf8,0xff,0xed,0xff,' +` 0xed,0xff,0xd8,0xff,0xdc,0xff,0xba,0xff,' +` 0xc5,0xff,0x93,0xff,0xa8,0xff,0x62,0xff,' +` 0x84,0xff,0x27,0xff,0x59,0xff,0xe2,0xfe,' +` 0x2a,0xff,0x92,0xfe,0xf8,0xfe,0x27,0xfe,' +` 0x8c,0xfe,0xb9,0xfd,0x50,0xfe,0x46,0xfd,' +` 0x10,0xfe,0xbb,0xfc,0x8a,0xfd,0x20,0xfc,' +` 0x45,0xfd,0x96,0xfb,0x00,0xfd,0x0a,0xfb,' +` 0xc6,0xfc,0x7e,0xfa,0x97,0xfc,0xf0,0xf9,' +` 0x76,0xfc,0x60,0xf9,0x67,0xfc,0xcc,0xf8,' +` 0x6f,0xfc,0x30,0xf8,0x93,0xfc,0x88,0xf7,' +` 0xdf,0xfc,0xc7,0xf6,0x63,0xfd,0xd9,0xf5,' +` 0x3c,0xfe,0x91,0xf4,0xb2,0xff,0x84,0xf2,' +` 0x8f,0x02,0x55,0xee,0xea,0x09,0x0c,0xdf,' +` 0xc0,0x49,0x23,0x4d,0xdc,0xde,0xa0,0x0a,' +` 0xcb,0xee,0x89,0x03,0x5b,0xf3,0xf1,0x00,' +` 0xa6,0xf5,0xae,0xff,0x22,0xf7,0x01,0xff,' +` 0x3c,0xf8,0xa4,0xfe,0x22,0xf9,0x77,0xfe,' +` 0xe7,0xf9,0x68,0xfe,0x95,0xfa,0x6c,0xfe,' +` 0x32,0xfb,0x7d,0xfe,0xc2,0xfb,0x96,0xfe,' +` 0x45,0xfc,0xb4,0xfe,0xbe,0xfc,0xd6,0xfe,' +` 0x2e,0xfd,0xf8,0xfe,0x95,0xfd,0x1a,0xff,' +` 0x31,0xfe,0x75,0xff,0x73,0xfe,0x8a,0xff,' +` 0xb9,0xfe,0x9e,0xff,0x15,0xff,0xd7,0xff,' +` 0x47,0xff,0xe0,0xff,0x6f,0xff,0xe8,0xff,' +` 0x91,0xff,0xef,0xff,0xae,0xff,0xf5,0xff,' +` 0xc6,0xff,0xf9,0xff,0xd8,0xff,0xfc,0xff,' +` 0xe7,0xff,0xfe,0xff,0xf2,0xff,0xff,0xff,' +` 0xf9,0xff,0x00,0x00,0xfe,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xff,0xff,0xf9,0xff,0xfe,0xff,' +` 0xf1,0xff,0xfb,0xff,0xe6,0xff,0xf7,0xff,' +` 0xd7,0xff,0xf2,0xff,0xc4,0xff,0xeb,0xff,' +` 0xac,0xff,0xe2,0xff,0x8e,0xff,0xd8,0xff,' +` 0x6c,0xff,0xcc,0xff,0x44,0xff,0xc0,0xff,' +` 0x0d,0xff,0x7e,0xff,0xb8,0xfe,0x66,0xff,' +` 0x74,0xfe,0x48,0xff,0xe2,0xfd,0xee,0xfe,' +` 0x93,0xfd,0xc5,0xfe,0x2f,0xfd,0x9c,0xfe,' +` 0xc2,0xfc,0x73,0xfe,0x4d,0xfc,0x4e,0xfe,' +` 0xce,0xfb,0x2c,0xfe,0x45,0xfb,0x12,0xfe,' +` 0xb0,0xfa,0x03,0xfe,0x0b,0xfa,0x06,0xfe,' +` 0x53,0xf9,0x25,0xfe,0x7e,0xf8,0x6f,0xfe,' +` 0x7a,0xf7,0x03,0xff,0x1e,0xf6,0x22,0x00,' +` 0xff,0xf3,0x7d,0x02,0xb7,0xef,0x49,0x09,' +` 0x8f,0xdf,0x9d,0x63,0xfa,0x2e,0xa5,0xe4,' +` 0xe5,0x06,0x29,0xf0,0x10,0x01,0x8d,0xf3,' +` 0xbd,0xfe,0x47,0xf5,0x8b,0xfd,0x61,0xf6,' +` 0xdb,0xfc,0x33,0xf7,0x75,0xfc,0xe0,0xf7,' +` 0x3f,0xfc,0x7b,0xf8,0x2b,0xfc,0x0c,0xf9,' +` 0x32,0xfc,0x98,0xf9,0x4d,0xfc,0x22,0xfa,' +` 0x78,0xfc,0xab,0xfa,0xaf,0xfc,0x31,0xfb,' +` 0xf1,0xfc,0xba,0xfb,0x3b,0xfd,0x3f,0xfc,' +` 0x87,0xfd,0xe0,0xfc,0x0f,0xfe,0x5e,0xfd,' +` 0x55,0xfe,0xc7,0xfd,0xaa,0xfe,0x5b,0xfe,' +` 0xf1,0xfe,0xa8,0xfe,0x29,0xff,0xf3,0xfe,' +` 0x5b,0xff,0x34,0xff,0x86,0xff,0x6c,0xff,' +` 0xaa,0xff,0x9b,0xff,0xc7,0xff,0xbf,0xff,' +` 0xde,0xff,0xdb,0xff,0xee,0xff,0xee,0xff,' +` 0xf9,0xff,0xfa,0xff,0xfe,0xff,0xff,0xff,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x03,0x00,0x04,0x00,' +` 0x06,0x00,0x09,0x00,0x0c,0x00,0x0f,0x00,' +` 0x14,0x00,0x18,0x00,0x1e,0x00,0x23,0x00,' +` 0x2a,0x00,0x30,0x00,0x39,0x00,0x40,0x00,' +` 0x49,0x00,0x52,0x00,0x5d,0x00,0x65,0x00,' +` 0x74,0x00,0x7c,0x00,0x71,0x00,0x80,0x00,' +` 0x89,0x00,0x96,0x00,0xa7,0x00,0xfd,0x00,' +` 0x1a,0x01,0x2b,0x01,0x40,0x01,0x53,0x01,' +` 0x68,0x01,0x7c,0x01,0x91,0x01,0xa6,0x01,' +` 0xbb,0x01,0xcf,0x01,0xe5,0x01,0xf9,0x01,' +` 0x0e,0x02,0x21,0x02,0x35,0x02,0x48,0x02,' +` 0x5c,0x02,0x6d,0x02,0x80,0x02,0x90,0x02,' +` 0xa2,0x02,0xb1,0x02,0xc0,0x02,0xcd,0x02,' +` 0xdb,0x02,0xe5,0x02,0xef,0x02,0xf5,0x02,' +` 0xfc,0x02,0x00,0x03,0x01,0x43,0x05,0x03,' +` 0x07,0x03,0x06,0x03,0x06,0x03,0x02,0x03,' +` 0xff,0x02,0xf7,0x02,0xf1,0x02,0xe7,0x02,' +` 0xde,0x02,0xd1,0x02,0xc6,0x02,0xb6,0x02,' +` 0xa9,0x02,0x97,0x02,0x87,0x02,0x73,0x02,' +` 0x62,0x02,0x4c,0x02,0x3a,0x02,0x22,0x02,' +` 0x0f,0x02,0xf6,0x01,0xe3,0x01,0xc9,0x01,' +` 0xb6,0x01,0x9a,0x01,0x87,0x01,0x6a,0x01,' +` 0x59,0x01,0x35,0x01,0x37,0x01,0x2b,0x01,' +` 0x12,0x01,0xfa,0x00,0xe9,0x00,0xbd,0x00,' +` 0x88,0x00,0x80,0x00,0x6e,0x00,0x64,0x00,' +` 0x56,0x00,0x4c,0x00,0x40,0x00,0x38,0x00,' +` 0x2e,0x00,0x27,0x00,0x1f,0x00,0x19,0x00,' +` 0x14,0x00,0x0f,0x00,0x0b,0x00,0x08,0x00,' +` 0x05,0x00,0x03,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00,' +` 0x03,0x00,0x06,0x00,0x07,0x00,0x0d,0x00,' +` 0x0d,0x00,0x16,0x00,0x15,0x00,0x23,0x00,' +` 0x1f,0x00,0x32,0x00,0x2c,0x00,0x45,0x00,' +` 0x3c,0x00,0x5c,0x00,0x4d,0x00,0x76,0x00,' +` 0x62,0x00,0x94,0x00,0x78,0x00,0xb6,0x00,' +` 0x8f,0x00,0xe3,0x00,0xe2,0x00,0x2f,0x01,' +` 0xfe,0x00,0x5f,0x01,0x20,0x01,0x91,0x01,' +` 0x42,0x01,0xc5,0x01,0x63,0x01,0xfa,0x01,' +` 0x83,0x01,0x31,0x02,0xa0,0x01,0x68,0x02,' +` 0xba,0x01,0xa1,0x02,0xd0,0x01,0xdb,0x02,' +` 0xdf,0x01,0x17,0x03,0xe5,0x01,0x57,0x03,' +` 0xe0,0x01,0x9e,0x03,0xca,0x01,0xf2,0x03,' +` 0x98,0x01,0x62,0x04,0x32,0x01,0x16,0x05,' +` 0x4d,0x00,0xa9,0x06,0x5b,0xfd,0x8b,0x0f,' +` 0x02,0x40,0x29,0xfa,0xc4,0x07,0xbd,0xff,' +` 0x69,0x05,0xf7,0x00,0x87,0x04,0x77,0x01,' +` 0x05,0x04,0xb4,0x01,0xa8,0x03,0xd0,0x01,' +` 0x5c,0x03,0xd8,0x01,0x19,0x03,0xd3,0x01,' +` 0xda,0x02,0xc5,0x01,0x9e,0x02,0xb1,0x01,' +` 0x64,0x02,0x97,0x01,0x2c,0x02,0x7a,0x01,' +` 0xf5,0x01,0x5b,0x01,0xbf,0x01,0x3a,0x01,' +` 0x8b,0x01,0x19,0x01,0x59,0x01,0xf8,0x00,' +` 0x29,0x01,0xdb,0x00,0xe0,0x00,0x87,0x00,' +` 0xb2,0x00,0x72,0x00,0x90,0x00,0x5d,0x00,' +` 0x73,0x00,0x4a,0x00,0x59,0x00,0x38,0x00,' +` 0x43,0x00,0x2a,0x00,0x30,0x00,0x1d,0x00,' +` 0x21,0x00,0x13,0x00,0x15,0x00,0x0c,0x00,' +` 0x0c,0x00,0x06,0x00,0x06,0x00,0x03,0x00,' +` 0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfc,0xff,0xf9,0xff,0xf5,0xff,' +` 0xf0,0xff,0xea,0xff,0xe3,0xff,0xda,0xff,' +` 0xd0,0xff,0xc4,0xff,0xb7,0xff,0xa9,0xff,' +` 0x99,0xff,0x88,0xff,0x75,0xff,0x60,0xff,' +` 0x4b,0xff,0x33,0xff,0x1b,0xff,0x00,0xff,' +` 0xe5,0xfe,0xc7,0xfe,0xac,0xfe,0x83,0xfe,' +` 0x05,0xfe,0xe5,0xfd,0xbc,0xfd,0x94,0xfd,' +` 0x6a,0xfd,0x40,0xfd,0x15,0xfd,0xea,0xfc,' +` 0xbf,0xfc,0x94,0xfc,0x6a,0xfc,0x3f,0xfc,' +` 0x15,0xfc,0xeb,0xfb,0xc3,0xfb,0x9b,0xfb,' +` 0x74,0xfb,0x4e,0xfb,0x2a,0xfb,0x06,0xfb,' +` 0xe6,0xfa,0xc5,0xfa,0xa8,0xfa,0x8b,0xfa,' +` 0x73,0xfa,0x59,0xfa,0x45,0xfa,0x30,0xfa,' +` 0x21,0xfa,0x11,0xfa,0x07,0xfa,0xfc,0xf9,' +` 0xf7,0xf9,0xf0,0xf9,0xed,0x79,0xf6,0xf9,' +` 0xff,0xf9,0x07,0xfa,0x16,0xfa,0x23,0xfa,' +` 0x37,0xfa,0x48,0xfa,0x61,0xfa,0x76,0xfa,' +` 0x94,0xfa,0xad,0xfa,0xcf,0xfa,0xec,0xfa,' +` 0x11,0xfb,0x31,0xfb,0x59,0xfb,0x7c,0xfb,' +` 0xa6,0xfb,0xcb,0xfb,0xf7,0xfb,0x1d,0xfc,' +` 0x4b,0xfc,0x72,0xfc,0xa1,0xfc,0xc7,0xfc,' +` 0xf7,0xfc,0x1c,0xfd,0x4d,0xfd,0x70,0xfd,' +` 0xa1,0xfd,0xc0,0xfd,0xf4,0xfd,0x09,0xfe,' +` 0x68,0xfe,0xbf,0xfe,0xca,0xfe,0xf0,0xfe,' +` 0x05,0xff,0x23,0xff,0x38,0xff,0x51,0xff,' +` 0x65,0xff,0x7a,0xff,0x8b,0xff,0x9d,0xff,' +` 0xac,0xff,0xba,0xff,0xc7,0xff,0xd2,0xff,' +` 0xdc,0xff,0xe4,0xff,0xeb,0xff,0xf1,0xff,' +` 0xf6,0xff,0xfa,0xff,0xfd,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfc,0xff,' +` 0xf9,0xff,0xf5,0xff,0xf0,0xff,0xea,0xff,' +` 0xe3,0xff,0xda,0xff,0xd0,0xff,0xc4,0xff,' +` 0xb7,0xff,0xa9,0xff,0x99,0xff,0x88,0xff,' +` 0x75,0xff,0x60,0xff,0x4b,0xff,0x33,0xff,' +` 0x1b,0xff,0x00,0xff,0xe5,0xfe,0xc7,0xfe,' +` 0xac,0xfe,0x83,0xfe,0x05,0xfe,0xe5,0xfd,' +` 0xbc,0xfd,0x94,0xfd,0x6a,0xfd,0x40,0xfd,' +` 0x15,0xfd,0xea,0xfc,0xbf,0xfc,0x94,0xfc,' +` 0x6a,0xfc,0x3f,0xfc,0x15,0xfc,0xeb,0xfb,' +` 0xc3,0xfb,0x9b,0xfb,0x74,0xfb,0x4e,0xfb,' +` 0x2a,0xfb,0x06,0xfb,0xe6,0xfa,0xc5,0xfa,' +` 0xa8,0xfa,0x8b,0xfa,0x73,0xfa,0x59,0xfa,' +` 0x45,0xfa,0x30,0xfa,0x21,0xfa,0x11,0xfa,' +` 0x07,0xfa,0xfc,0xf9,0xf7,0xf9,0xf0,0xf9,' +` 0xed,0x79,0xf6,0xf9,0xff,0xf9,0x07,0xfa,' +` 0x16,0xfa,0x23,0xfa,0x37,0xfa,0x48,0xfa,' +` 0x61,0xfa,0x76,0xfa,0x94,0xfa,0xad,0xfa,' +` 0xcf,0xfa,0xec,0xfa,0x11,0xfb,0x31,0xfb,' +` 0x59,0xfb,0x7c,0xfb,0xa6,0xfb,0xcb,0xfb,' +` 0xf7,0xfb,0x1d,0xfc,0x4b,0xfc,0x72,0xfc,' +` 0xa1,0xfc,0xc7,0xfc,0xf7,0xfc,0x1c,0xfd,' +` 0x4d,0xfd,0x70,0xfd,0xa1,0xfd,0xc0,0xfd,' +` 0xf4,0xfd,0x09,0xfe,0x68,0xfe,0xbf,0xfe,' +` 0xca,0xfe,0xf0,0xfe,0x05,0xff,0x23,0xff,' +` 0x38,0xff,0x51,0xff,0x65,0xff,0x7a,0xff,' +` 0x8b,0xff,0x9d,0xff,0xac,0xff,0xba,0xff,' +` 0xc7,0xff,0xd2,0xff,0xdc,0xff,0xe4,0xff,' +` 0xeb,0xff,0xf1,0xff,0xf6,0xff,0xfa,0xff,' +` 0xfd,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x02,0x00,0x03,0x00,0x06,0x00,' +` 0x07,0x00,0x0d,0x00,0x0d,0x00,0x16,0x00,' +` 0x15,0x00,0x23,0x00,0x1f,0x00,0x32,0x00,' +` 0x2c,0x00,0x45,0x00,0x3c,0x00,0x5c,0x00,' +` 0x4d,0x00,0x76,0x00,0x62,0x00,0x94,0x00,' +` 0x78,0x00,0xb6,0x00,0x8f,0x00,0xe3,0x00,' +` 0xe2,0x00,0x2f,0x01,0xfe,0x00,0x5f,0x01,' +` 0x20,0x01,0x91,0x01,0x42,0x01,0xc5,0x01,' +` 0x63,0x01,0xfa,0x01,0x83,0x01,0x31,0x02,' +` 0xa0,0x01,0x68,0x02,0xba,0x01,0xa1,0x02,' +` 0xd0,0x01,0xdb,0x02,0xdf,0x01,0x17,0x03,' +` 0xe5,0x01,0x57,0x03,0xe0,0x01,0x9e,0x03,' +` 0xca,0x01,0xf2,0x03,0x98,0x01,0x62,0x04,' +` 0x32,0x01,0x16,0x05,0x4d,0x00,0xa9,0x06,' +` 0x5b,0xfd,0x8b,0x0f,0x02,0x40,0x29,0xfa,' +` 0xc4,0x07,0xbd,0xff,0x69,0x05,0xf7,0x00,' +` 0x87,0x04,0x77,0x01,0x05,0x04,0xb4,0x01,' +` 0xa8,0x03,0xd0,0x01,0x5c,0x03,0xd8,0x01,' +` 0x19,0x03,0xd3,0x01,0xda,0x02,0xc5,0x01,' +` 0x9e,0x02,0xb1,0x01,0x64,0x02,0x97,0x01,' +` 0x2c,0x02,0x7a,0x01,0xf5,0x01,0x5b,0x01,' +` 0xbf,0x01,0x3a,0x01,0x8b,0x01,0x19,0x01,' +` 0x59,0x01,0xf8,0x00,0x29,0x01,0xdb,0x00,' +` 0xe0,0x00,0x87,0x00,0xb2,0x00,0x72,0x00,' +` 0x90,0x00,0x5d,0x00,0x73,0x00,0x4a,0x00,' +` 0x59,0x00,0x38,0x00,0x43,0x00,0x2a,0x00,' +` 0x30,0x00,0x1d,0x00,0x21,0x00,0x13,0x00,' +` 0x15,0x00,0x0c,0x00,0x0c,0x00,0x06,0x00,' +` 0x06,0x00,0x03,0x00,0x02,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,' +` 0x03,0x00,0x04,0x00,0x06,0x00,0x09,0x00,' +` 0x0c,0x00,0x0f,0x00,0x14,0x00,0x18,0x00,' +` 0x1e,0x00,0x23,0x00,0x2a,0x00,0x30,0x00,' +` 0x39,0x00,0x40,0x00,0x49,0x00,0x52,0x00,' +` 0x5d,0x00,0x65,0x00,0x74,0x00,0x7c,0x00,' +` 0x71,0x00,0x80,0x00,0x89,0x00,0x96,0x00,' +` 0xa7,0x00,0xfd,0x00,0x1a,0x01,0x2b,0x01,' +` 0x40,0x01,0x53,0x01,0x68,0x01,0x7c,0x01,' +` 0x91,0x01,0xa6,0x01,0xbb,0x01,0xcf,0x01,' +` 0xe5,0x01,0xf9,0x01,0x0e,0x02,0x21,0x02,' +` 0x35,0x02,0x48,0x02,0x5c,0x02,0x6d,0x02,' +` 0x80,0x02,0x90,0x02,0xa2,0x02,0xb1,0x02,' +` 0xc0,0x02,0xcd,0x02,0xdb,0x02,0xe5,0x02,' +` 0xef,0x02,0xf5,0x02,0xfc,0x02,0x00,0x03,' +` 0x01,0x43,0x05,0x03,0x07,0x03,0x06,0x03,' +` 0x06,0x03,0x02,0x03,0xff,0x02,0xf7,0x02,' +` 0xf1,0x02,0xe7,0x02,0xde,0x02,0xd1,0x02,' +` 0xc6,0x02,0xb6,0x02,0xa9,0x02,0x97,0x02,' +` 0x87,0x02,0x73,0x02,0x62,0x02,0x4c,0x02,' +` 0x3a,0x02,0x22,0x02,0x0f,0x02,0xf6,0x01,' +` 0xe3,0x01,0xc9,0x01,0xb6,0x01,0x9a,0x01,' +` 0x87,0x01,0x6a,0x01,0x59,0x01,0x35,0x01,' +` 0x37,0x01,0x2b,0x01,0x12,0x01,0xfa,0x00,' +` 0xe9,0x00,0xbd,0x00,0x88,0x00,0x80,0x00,' +` 0x6e,0x00,0x64,0x00,0x56,0x00,0x4c,0x00,' +` 0x40,0x00,0x38,0x00,0x2e,0x00,0x27,0x00,' +` 0x1f,0x00,0x19,0x00,0x14,0x00,0x0f,0x00,' +` 0x0b,0x00,0x08,0x00,0x05,0x00,0x03,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,' +` 0xf9,0xff,0xfe,0xff,0xf1,0xff,0xfb,0xff,' +` 0xe6,0xff,0xf7,0xff,0xd7,0xff,0xf2,0xff,' +` 0xc4,0xff,0xeb,0xff,0xac,0xff,0xe2,0xff,' +` 0x8e,0xff,0xd8,0xff,0x6c,0xff,0xcc,0xff,' +` 0x44,0xff,0xc0,0xff,0x0d,0xff,0x7e,0xff,' +` 0xb8,0xfe,0x66,0xff,0x74,0xfe,0x48,0xff,' +` 0xe2,0xfd,0xee,0xfe,0x93,0xfd,0xc5,0xfe,' +` 0x2f,0xfd,0x9c,0xfe,0xc2,0xfc,0x73,0xfe,' +` 0x4d,0xfc,0x4e,0xfe,0xce,0xfb,0x2c,0xfe,' +` 0x45,0xfb,0x12,0xfe,0xb0,0xfa,0x03,0xfe,' +` 0x0b,0xfa,0x06,0xfe,0x53,0xf9,0x25,0xfe,' +` 0x7e,0xf8,0x6f,0xfe,0x7a,0xf7,0x03,0xff,' +` 0x1e,0xf6,0x22,0x00,0xff,0xf3,0x7d,0x02,' +` 0xb7,0xef,0x49,0x09,0x8f,0xdf,0x9d,0x63,' +` 0xfa,0x2e,0xa5,0xe4,0xe5,0x06,0x29,0xf0,' +` 0x10,0x01,0x8d,0xf3,0xbd,0xfe,0x47,0xf5,' +` 0x8b,0xfd,0x61,0xf6,0xdb,0xfc,0x33,0xf7,' +` 0x75,0xfc,0xe0,0xf7,0x3f,0xfc,0x7b,0xf8,' +` 0x2b,0xfc,0x0c,0xf9,0x32,0xfc,0x98,0xf9,' +` 0x4d,0xfc,0x22,0xfa,0x78,0xfc,0xab,0xfa,' +` 0xaf,0xfc,0x31,0xfb,0xf1,0xfc,0xba,0xfb,' +` 0x3b,0xfd,0x3f,0xfc,0x87,0xfd,0xe0,0xfc,' +` 0x0f,0xfe,0x5e,0xfd,0x55,0xfe,0xc7,0xfd,' +` 0xaa,0xfe,0x5b,0xfe,0xf1,0xfe,0xa8,0xfe,' +` 0x29,0xff,0xf3,0xfe,0x5b,0xff,0x34,0xff,' +` 0x86,0xff,0x6c,0xff,0xaa,0xff,0x9b,0xff,' +` 0xc7,0xff,0xbf,0xff,0xde,0xff,0xdb,0xff,' +` 0xee,0xff,0xee,0xff,0xf9,0xff,0xfa,0xff,' +` 0xfe,0xff,0xff,0xff,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0xfe,0xff,0xf9,0xff,' +` 0xf8,0xff,0xed,0xff,0xed,0xff,0xd8,0xff,' +` 0xdc,0xff,0xba,0xff,0xc5,0xff,0x93,0xff,' +` 0xa8,0xff,0x62,0xff,0x84,0xff,0x27,0xff,' +` 0x59,0xff,0xe2,0xfe,0x2a,0xff,0x92,0xfe,' +` 0xf8,0xfe,0x27,0xfe,0x8c,0xfe,0xb9,0xfd,' +` 0x50,0xfe,0x46,0xfd,0x10,0xfe,0xbb,0xfc,' +` 0x8a,0xfd,0x20,0xfc,0x45,0xfd,0x96,0xfb,' +` 0x00,0xfd,0x0a,0xfb,0xc6,0xfc,0x7e,0xfa,' +` 0x97,0xfc,0xf0,0xf9,0x76,0xfc,0x60,0xf9,' +` 0x67,0xfc,0xcc,0xf8,0x6f,0xfc,0x30,0xf8,' +` 0x93,0xfc,0x88,0xf7,0xdf,0xfc,0xc7,0xf6,' +` 0x63,0xfd,0xd9,0xf5,0x3c,0xfe,0x91,0xf4,' +` 0xb2,0xff,0x84,0xf2,0x8f,0x02,0x55,0xee,' +` 0xea,0x09,0x0c,0xdf,0xc0,0x49,0x23,0x4d,' +` 0xdc,0xde,0xa0,0x0a,0xcb,0xee,0x89,0x03,' +` 0x5b,0xf3,0xf1,0x00,0xa6,0xf5,0xae,0xff,' +` 0x22,0xf7,0x01,0xff,0x3c,0xf8,0xa4,0xfe,' +` 0x22,0xf9,0x77,0xfe,0xe7,0xf9,0x68,0xfe,' +` 0x95,0xfa,0x6c,0xfe,0x32,0xfb,0x7d,0xfe,' +` 0xc2,0xfb,0x96,0xfe,0x45,0xfc,0xb4,0xfe,' +` 0xbe,0xfc,0xd6,0xfe,0x2e,0xfd,0xf8,0xfe,' +` 0x95,0xfd,0x1a,0xff,0x31,0xfe,0x75,0xff,' +` 0x73,0xfe,0x8a,0xff,0xb9,0xfe,0x9e,0xff,' +` 0x15,0xff,0xd7,0xff,0x47,0xff,0xe0,0xff,' +` 0x6f,0xff,0xe8,0xff,0x91,0xff,0xef,0xff,' +` 0xae,0xff,0xf5,0xff,0xc6,0xff,0xf9,0xff,' +` 0xd8,0xff,0xfc,0xff,0xe7,0xff,0xfe,0xff,' +` 0xf2,0xff,0xff,0xff,0xf9,0xff,0x00,0x00,' +` 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x03,0x00,0x09,0x00,' +` 0x08,0x00,0x16,0x00,0x12,0x00,0x2a,0x00,' +` 0x20,0x00,0x45,0x00,0x32,0x00,0x69,0x00,' +` 0x4a,0x00,0x95,0x00,0x67,0x00,0xc9,0x00,' +` 0x8a,0x00,0x06,0x01,0xb1,0x00,0x4b,0x01,' +` 0xe7,0x00,0x05,0x02,0x7d,0x01,0x73,0x02,' +` 0xc1,0x01,0xe8,0x02,0x11,0x02,0x2b,0x03,' +` 0x17,0x02,0xa6,0x03,0x55,0x02,0x28,0x04,' +` 0x8e,0x02,0xac,0x04,0xbe,0x02,0x34,0x05,' +` 0xe3,0x02,0xc1,0x05,0xfc,0x02,0x54,0x06,' +` 0x04,0x03,0xf0,0x06,0xf6,0x02,0x97,0x07,' +` 0xc8,0x02,0x53,0x08,0x6f,0x02,0x31,0x09,' +` 0xd2,0x01,0x4e,0x0a,0xc6,0x00,0xef,0x0b,' +` 0xdd,0xfe,0xcd,0x0e,0xb1,0xfa,0xfa,0x15,' +` 0x91,0xeb,0xf9,0x52,0xc6,0x5b,0x68,0xea,' +` 0x4f,0x16,0x3a,0xfa,0xcd,0x0e,0x6b,0xfe,' +` 0xc8,0x0b,0x43,0x00,0x07,0x0a,0x3b,0x01,' +` 0xd0,0x08,0xc5,0x01,0xdf,0x07,0x12,0x02,' +` 0x16,0x07,0x37,0x02,0x65,0x06,0x41,0x02,' +` 0xc5,0x05,0x38,0x02,0x31,0x05,0x22,0x02,' +` 0xa6,0x04,0x02,0x02,0x25,0x04,0xdc,0x01,' +` 0xaa,0x03,0xb0,0x01,0x38,0x03,0x7f,0x01,' +` 0xd4,0x02,0x04,0x01,0xb4,0x01,0x9f,0x00,' +` 0x74,0x01,0x87,0x00,0x2e,0x01,0x77,0x00,' +` 0x2a,0x01,0x75,0x00,0xee,0x00,0x5f,0x00,' +` 0xbc,0x00,0x4b,0x00,0x8f,0x00,0x38,0x00,' +` 0x6a,0x00,0x28,0x00,0x4a,0x00,0x1b,0x00,' +` 0x32,0x00,0x11,0x00,0x1e,0x00,0x0a,0x00,' +` 0x10,0x00,0x05,0x00,0x07,0x00,0x02,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x04,0x00,0x06,0x00,' +` 0x08,0x00,0x0b,0x00,0x0e,0x00,0x11,0x00,' +` 0x15,0x00,0x19,0x00,0x1d,0x00,0x22,0x00,' +` 0x27,0x00,0x2e,0x00,0x34,0x00,0x3b,0x00,' +` 0x44,0x00,0x3c,0x00,0x3f,0x00,0x4a,0x00,' +` 0x50,0x00,0x5b,0x00,0x61,0x00,0x6f,0x00,' +` 0x75,0x00,0x87,0x00,0x88,0x00,0xbc,0x00,' +` 0x13,0x01,0x1c,0x01,0x36,0x01,0x46,0x01,' +` 0x5e,0x01,0x70,0x01,0x88,0x01,0x9c,0x01,' +` 0xb4,0x01,0xc8,0x01,0xe0,0x01,0xf5,0x01,' +` 0x0c,0x02,0x21,0x02,0x37,0x02,0x4b,0x02,' +` 0x60,0x02,0x74,0x02,0x86,0x02,0x97,0x02,' +` 0xa7,0x02,0xb5,0x02,0xc3,0x02,0xd0,0x02,' +` 0xdb,0x02,0xe6,0x02,0xef,0x02,0xf7,0x02,' +` 0xf9,0x42,0x02,0x03,0x05,0x03,0x08,0x03,' +` 0x09,0x03,0x09,0x03,0x07,0x03,0x04,0x03,' +` 0xfe,0x02,0xf9,0x02,0xf0,0x02,0xe8,0x02,' +` 0xdc,0x02,0xd1,0x02,0xc2,0x02,0xb4,0x02,' +` 0xa2,0x02,0x92,0x02,0x7e,0x02,0x6b,0x02,' +` 0x54,0x02,0x3f,0x02,0x26,0x02,0x10,0x02,' +` 0xf6,0x01,0xe0,0x01,0xc4,0x01,0xb0,0x01,' +` 0x8f,0x01,0x81,0x01,0x82,0x01,0x64,0x01,' +` 0x4d,0x01,0x33,0x01,0x1b,0x01,0x03,0x01,' +` 0xec,0x00,0xd7,0x00,0xc0,0x00,0xaf,0x00,' +` 0x7d,0x00,0x61,0x00,0x59,0x00,0x4b,0x00,' +` 0x41,0x00,0x36,0x00,0x2e,0x00,0x26,0x00,' +` 0x1f,0x00,0x18,0x00,0x13,0x00,0x0e,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0xff,0xff,0x05,0x00,0xfe,0xff,' +` 0x09,0x00,0xfd,0xff,0x0f,0x00,0xfa,0xff,' +` 0x17,0x00,0xf6,0xff,0x1f,0x00,0xf0,0xff,' +` 0x29,0x00,0xe8,0xff,0x32,0x00,0xda,0xff,' +` 0x3c,0x00,0xb9,0xff,0x1c,0x00,0x91,0xff,' +` 0x1b,0x00,0x6c,0xff,0x16,0x00,0x3f,0xff,' +` 0x0d,0x00,0x08,0xff,0x00,0x00,0xc4,0xfe,' +` 0xa5,0xff,0x37,0xfe,0x90,0xff,0xd6,0xfd,' +` 0x6e,0xff,0x69,0xfd,0x4a,0xff,0xee,0xfc,' +` 0x26,0xff,0x65,0xfc,0x05,0xff,0xcc,0xfb,' +` 0xeb,0xfe,0x21,0xfb,0xdd,0xfe,0x60,0xfa,' +` 0xe4,0xfe,0x80,0xf9,0x0d,0xff,0x6a,0xf8,' +` 0x6d,0xff,0x01,0xf7,0x44,0x00,0xf1,0xf4,' +` 0x29,0x02,0x25,0xf1,0x70,0x07,0x59,0xe5,' +` 0x1f,0x2e,0x5e,0x64,0x7e,0xdf,0x96,0x08,' +` 0x1a,0xef,0x5e,0x01,0xe4,0xf2,0x99,0xfe,' +` 0x97,0xf4,0x1d,0xfd,0x95,0xf5,0x36,0xfc,' +` 0x4c,0xf6,0xb2,0xfb,0xee,0xf6,0x69,0xfb,' +` 0x7f,0xf7,0x48,0xfb,0x0a,0xf8,0x48,0xfb,' +` 0x99,0xf8,0x66,0xfb,0x2a,0xf9,0x97,0xfb,' +` 0xbc,0xf9,0xd8,0xfb,0x4f,0xfa,0x25,0xfc,' +` 0xe3,0xfa,0x7e,0xfc,0xaf,0xfb,0x10,0xfd,' +` 0x3a,0xfc,0x67,0xfd,0xbf,0xfc,0xbf,0xfd,' +` 0x3d,0xfd,0x16,0xfe,0xb5,0xfd,0x66,0xfe,' +` 0x2f,0xfe,0xda,0xfe,0x98,0xfe,0x16,0xff,' +` 0xec,0xfe,0x4e,0xff,0x34,0xff,0x80,0xff,' +` 0x70,0xff,0xa8,0xff,0xa1,0xff,0xc8,0xff,' +` 0xc6,0xff,0xe1,0xff,0xe2,0xff,0xf1,0xff,' +` 0xf3,0xff,0xfb,0xff,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfd,0xff,0xfb,0xff,0xf3,0xff,0xef,0xff,' +` 0xe1,0xff,0xdd,0xff,0xc6,0xff,0xc3,0xff,' +` 0xa1,0xff,0xa0,0xff,0x71,0xff,0x74,0xff,' +` 0x36,0xff,0x3f,0xff,0xf0,0xfe,0x01,0xff,' +` 0xa2,0xfe,0xb1,0xfe,0x1f,0xfe,0x53,0xfe,' +` 0xb9,0xfd,0xfa,0xfd,0x48,0xfd,0x9e,0xfd,' +` 0xcf,0xfc,0x41,0xfd,0x51,0xfc,0xe5,0xfc,' +` 0xca,0xfb,0x47,0xfc,0x0e,0xfb,0xeb,0xfb,' +` 0x85,0xfa,0x97,0xfb,0xfe,0xf9,0x4e,0xfb,' +` 0x7a,0xf9,0x12,0xfb,0xfa,0xf8,0xe9,0xfa,' +` 0x81,0xf8,0xda,0xfa,0x0e,0xf8,0xe7,0xfa,' +` 0x9a,0xf7,0x16,0xfb,0x1f,0xf7,0x7a,0xfb,' +` 0x9d,0xf6,0x2c,0xfc,0xe8,0xf5,0x53,0xfd,' +` 0xad,0xf4,0x7b,0xff,0xd3,0xf1,0x32,0x05,' +` 0x0d,0xe5,0xa0,0x70,0x84,0x1a,0x38,0xec,' +` 0xa7,0x03,0x20,0xf4,0x30,0x00,0xde,0xf6,' +` 0xfe,0xfe,0x70,0xf8,0x86,0xfe,0x8f,0xf9,' +` 0x60,0xfe,0x6f,0xfa,0x5d,0xfe,0x2b,0xfb,' +` 0x74,0xfe,0xd0,0xfb,0x98,0xfe,0x63,0xfc,' +` 0xc3,0xfe,0xe9,0xfc,0xf2,0xfe,0x61,0xfd,' +` 0x21,0xff,0xcd,0xfd,0x4f,0xff,0x2d,0xfe,' +` 0x79,0xff,0x7e,0xfe,0xd5,0xff,0x0e,0xff,' +` 0xeb,0xff,0x42,0xff,0xfe,0xff,0x6f,0xff,' +` 0x0a,0x00,0x94,0xff,0x12,0x00,0xb2,0xff,' +` 0x14,0x00,0xd7,0xff,0x37,0x00,0xef,0xff,' +` 0x2e,0x00,0xf7,0xff,0x26,0x00,0xfc,0xff,' +` 0x1d,0x00,0xff,0xff,0x15,0x00,0x00,0x00,' +` 0x0e,0x00,0x00,0x00,0x09,0x00,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x11,0x00,0x28,0x00,' +` 0x1f,0x00,0x42,0x00,0x32,0x00,0x64,0x00,' +` 0x4b,0x00,0x8f,0x00,0x6a,0x00,0xc3,0x00,' +` 0x90,0x00,0xfe,0x00,0xea,0x00,0xad,0x01,' +` 0x46,0x01,0x0c,0x02,0x8f,0x01,0x77,0x02,' +` 0xda,0x01,0xec,0x02,0x29,0x02,0x66,0x03,' +` 0x7d,0x02,0xe2,0x03,0x78,0x02,0x3b,0x04,' +` 0xbf,0x02,0xc0,0x04,0xfb,0x02,0x4b,0x05,' +` 0x2d,0x03,0xd9,0x05,0x51,0x03,0x6b,0x06,' +` 0x62,0x03,0xfe,0x06,0x58,0x03,0x99,0x07,' +` 0x2f,0x03,0x43,0x08,0xdd,0x02,0x09,0x09,' +` 0x4c,0x02,0x06,0x0a,0x55,0x01,0x74,0x0b,' +` 0x99,0xff,0xf8,0x0d,0xe6,0xfb,0x24,0x14,' +` 0x2e,0xef,0x37,0x41,0xfe,0x6a,0x98,0xea,' +` 0x8e,0x15,0xb2,0xfa,0x21,0x0e,0xb3,0xfe,' +` 0x32,0x0b,0x6c,0x00,0x83,0x09,0x4f,0x01,' +` 0x58,0x08,0xc9,0x01,0x69,0x07,0x01,0x02,' +` 0x9d,0x06,0x14,0x02,0xea,0x05,0x10,0x02,' +` 0x47,0x05,0xfa,0x01,0xb1,0x04,0xda,0x01,' +` 0x25,0x04,0xb4,0x01,0xa5,0x03,0x8b,0x01,' +` 0x2d,0x03,0x63,0x01,0xaf,0x02,0x80,0x00,' +` 0xaa,0x01,0x62,0x00,0x65,0x01,0x50,0x00,' +` 0x27,0x01,0x3f,0x00,0xf2,0x00,0x31,0x00,' +` 0xc4,0x00,0x1f,0x00,0xaf,0x00,0x3a,0x00,' +` 0x8e,0x00,0x2b,0x00,0x6c,0x00,0x20,0x00,' +` 0x50,0x00,0x17,0x00,0x39,0x00,0x10,0x00,' +` 0x26,0x00,0x0a,0x00,0x17,0x00,0x05,0x00,' +` 0x0c,0x00,0x02,0x00,0x05,0x00,0x01,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x01,0x00,0x03,0x00,0x05,0x00,' +` 0x06,0x00,0x08,0x00,0x09,0x00,0x0c,0x00,' +` 0x0e,0x00,0x11,0x00,0x15,0x00,0x18,0x00,' +` 0x1e,0x00,0x1f,0x00,0x18,0x00,0x1e,0x00,' +` 0x22,0x00,0x28,0x00,0x2e,0x00,0x35,0x00,' +` 0x3c,0x00,0x44,0x00,0x4d,0x00,0x56,0x00,' +` 0x61,0x00,0x6b,0x00,0x78,0x00,0x81,0x00,' +` 0x9d,0x00,0x0a,0x01,0x20,0x01,0x36,0x01,' +` 0x4a,0x01,0x61,0x01,0x77,0x01,0x8e,0x01,' +` 0xa5,0x01,0xbd,0x01,0xd3,0x01,0xeb,0x01,' +` 0x01,0x02,0x17,0x02,0x2b,0x02,0x40,0x02,' +` 0x53,0x02,0x66,0x02,0x78,0x02,0x89,0x02,' +` 0x9a,0x02,0xa9,0x02,0xb8,0x02,0xc5,0x02,' +` 0xd1,0x02,0xdc,0x02,0xe6,0x02,0xea,0x42,' +` 0xf5,0x02,0xfa,0x02,0xff,0x02,0x01,0x03,' +` 0x03,0x03,0x02,0x03,0x01,0x03,0xfc,0x02,' +` 0xf8,0x02,0xef,0x02,0xe8,0x02,0xdb,0x02,' +` 0xd0,0x02,0xc0,0x02,0xb2,0x02,0x9e,0x02,' +` 0x8e,0x02,0x78,0x02,0x65,0x02,0x4d,0x02,' +` 0x3a,0x02,0x20,0x02,0x0b,0x02,0xef,0x01,' +` 0xdc,0x01,0xba,0x01,0xbd,0x01,0xb1,0x01,' +` 0x93,0x01,0x7a,0x01,0x60,0x01,0x46,0x01,' +` 0x2e,0x01,0x15,0x01,0xfe,0x00,0xe6,0x00,' +` 0xd2,0x00,0xbb,0x00,0xaa,0x00,0x94,0x00,' +` 0x87,0x00,0x64,0x00,0x44,0x00,0x3e,0x00,' +` 0x32,0x00,0x2b,0x00,0x23,0x00,0x1d,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x01,0x00,0x05,0x00,0x02,0x00,0x0c,0x00,' +` 0x06,0x00,0x1c,0x00,0x0e,0x00,0x2c,0x00,' +` 0x15,0x00,0x3f,0x00,0x1c,0x00,0x55,0x00,' +` 0x23,0x00,0x6d,0x00,0x28,0x00,0x82,0x00,' +` 0x0c,0x00,0x81,0x00,0x03,0x00,0x92,0x00,' +` 0xf2,0xff,0x9f,0x00,0xda,0xff,0xa9,0x00,' +` 0xb7,0xff,0xad,0x00,0x89,0xff,0xad,0x00,' +` 0x50,0xff,0xa7,0x00,0x07,0xff,0x50,0x00,' +` 0x65,0xfe,0x38,0x00,0xf8,0xfd,0x1a,0x00,' +` 0x79,0xfd,0xfa,0xff,0xe8,0xfc,0xda,0xff,' +` 0x43,0xfc,0xbf,0xff,0x86,0xfb,0xaa,0xff,' +` 0xa6,0xfa,0xa8,0xff,0xa1,0xf9,0xcd,0xff,' +` 0x65,0xf8,0x39,0x00,0xc8,0xf6,0x32,0x01,' +` 0x5f,0xf4,0x77,0x03,0xbf,0xef,0x49,0x0a,' +` 0x18,0xdf,0x6f,0x5f,0xf0,0x34,0x09,0xe3,' +` 0xb1,0x07,0x5c,0xef,0x3d,0x01,0xcf,0xf2,' +` 0x8b,0xfe,0x69,0xf4,0x0b,0xfd,0x5d,0xf5,' +` 0x1c,0xfc,0x0c,0xf6,0x88,0xfb,0xa1,0xf6,' +` 0x30,0xfb,0x2c,0xf7,0x0f,0xfb,0xc1,0xf7,' +` 0x14,0xfb,0x56,0xf8,0x35,0xfb,0xee,0xf8,' +` 0x6c,0xfb,0x88,0xf9,0xb5,0xfb,0x21,0xfa,' +` 0x2b,0xfc,0x09,0xfb,0x9b,0xfc,0x9a,0xfb,' +` 0xf9,0xfc,0x2a,0xfc,0x58,0xfd,0xb5,0xfc,' +` 0xb7,0xfd,0x3a,0xfd,0x13,0xfe,0xb6,0xfd,' +` 0x6b,0xfe,0x29,0xfe,0xbb,0xfe,0x97,0xfe,' +` 0x1d,0xff,0xf7,0xfe,0x56,0xff,0x40,0xff,' +` 0x88,0xff,0x7d,0xff,0xb1,0xff,0xac,0xff,' +` 0xd1,0xff,0xd0,0xff,0xe8,0xff,0xeb,0xff,' +` 0xf7,0xff,0xf9,0xff,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf9,0xff,0xf7,0xff,0xea,0xff,0xe6,0xff,' +` 0xcf,0xff,0xce,0xff,0xab,0xff,0xae,0xff,' +` 0x7b,0xff,0x84,0xff,0x3f,0xff,0x51,0xff,' +` 0xf6,0xfe,0x12,0xff,0x88,0xfe,0xb7,0xfe,' +` 0x23,0xfe,0x65,0xfe,0xb2,0xfd,0x0d,0xfe,' +` 0x36,0xfd,0xb0,0xfd,0xb2,0xfc,0x50,0xfd,' +` 0x28,0xfc,0xf1,0xfc,0x9a,0xfb,0x94,0xfc,' +` 0x0b,0xfb,0x25,0xfc,0x26,0xfa,0xaf,0xfb,' +` 0x90,0xf9,0x67,0xfb,0xf9,0xf8,0x31,0xfb,' +` 0x65,0xf8,0x11,0xfb,0xd4,0xf7,0x0b,0xfb,' +` 0x45,0xf7,0x2e,0xfb,0xc0,0xf6,0x86,0xfb,' +` 0x32,0xf6,0x18,0xfc,0x8b,0xf5,0x03,0xfd,' +` 0xa2,0xf4,0x7a,0xfe,0x1a,0xf3,0x1a,0x01,' +` 0xca,0xef,0x54,0x07,0x02,0xe4,0xda,0x31,' +` 0xff,0x61,0x99,0xdf,0x1e,0x0a,0x1e,0xf0,' +` 0x69,0x03,0xac,0xf4,0x32,0x01,0x0a,0xf7,' +` 0x42,0x00,0xa1,0xf8,0xdb,0xff,0xd8,0xf9,' +` 0xba,0xff,0xd9,0xfa,0xbe,0xff,0xb4,0xfb,' +` 0xd2,0xff,0x6c,0xfc,0xee,0xff,0x0d,0xfd,' +` 0x0e,0x00,0x9a,0xfd,0x2e,0x00,0x15,0xfe,' +` 0x4e,0x00,0x7a,0xfe,0x8c,0x00,0x2c,0xff,' +` 0xaf,0x00,0x69,0xff,0xb7,0x00,0x9e,0xff,' +` 0xb7,0x00,0xc9,0xff,0xb1,0x00,0xe8,0xff,' +` 0xa7,0x00,0xfe,0xff,0x98,0x00,0x0c,0x00,' +` 0x86,0x00,0x14,0x00,0x86,0x00,0x2e,0x00,' +` 0x70,0x00,0x28,0x00,0x57,0x00,0x20,0x00,' +` 0x41,0x00,0x18,0x00,0x2d,0x00,0x10,0x00,' +` 0x1c,0x00,0x07,0x00,0x0c,0x00,0x03,0x00,' +` 0x05,0x00,0x01,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1a,0x00,0x2a,0x00,' +` 0x27,0x00,0x3c,0x00,0x38,0x00,0x51,0x00,' +` 0x61,0x00,0x97,0x00,0x8a,0x00,0xbd,0x00,' +` 0xae,0x00,0xea,0x00,0xd5,0x00,0x1b,0x01,' +` 0xff,0x00,0x51,0x01,0x2b,0x01,0x8a,0x01,' +` 0x58,0x01,0xc4,0x01,0x86,0x01,0x03,0x02,' +` 0x92,0x01,0x1a,0x02,0xb7,0x01,0x55,0x02,' +` 0xdb,0x01,0x90,0x02,0xfb,0x01,0xca,0x02,' +` 0x15,0x02,0x04,0x03,0x27,0x02,0x3d,0x03,' +` 0x2f,0x02,0x76,0x03,0x2a,0x02,0xb3,0x03,' +` 0x10,0x02,0xf7,0x03,0xdb,0x01,0x51,0x04,' +` 0x74,0x01,0xe6,0x04,0x9a,0x00,0x40,0x06,' +` 0xed,0xfd,0xf8,0x0d,0x80,0x40,0xc1,0xfa,' +` 0x2f,0x07,0xd7,0xff,0xfc,0x04,0xe7,0x00,' +` 0x20,0x04,0x4e,0x01,0x9d,0x03,0x79,0x01,' +` 0x3d,0x03,0x86,0x01,0xec,0x02,0x81,0x01,' +` 0xa3,0x02,0x72,0x01,0x60,0x02,0x59,0x01,' +` 0x1e,0x02,0x3c,0x01,0xe0,0x01,0x1d,0x01,' +` 0xa5,0x01,0xfd,0x00,0x6e,0x01,0xe0,0x00,' +` 0x30,0x01,0x59,0x00,0xad,0x00,0x44,0x00,' +` 0x8e,0x00,0x35,0x00,0x73,0x00,0x28,0x00,' +` 0x5c,0x00,0x1d,0x00,0x48,0x00,0x14,0x00,' +` 0x38,0x00,0x0d,0x00,0x2a,0x00,0x07,0x00,' +` 0x22,0x00,0x11,0x00,0x1f,0x00,0x0b,0x00,' +` 0x16,0x00,0x07,0x00,0x0f,0x00,0x04,0x00,' +` 0x0a,0x00,0x02,0x00,0x06,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,' +` 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,' +` 0xff,0xff,0x04,0x00,0x04,0x00,0x06,0x00,' +` 0x08,0x00,0x0b,0x00,0x0b,0x00,0x05,0x00,' +` 0x07,0x00,0x0a,0x00,0x0c,0x00,0x11,0x00,' +` 0x14,0x00,0x1b,0x00,0x1f,0x00,0x27,0x00,' +` 0x2d,0x00,0x37,0x00,0x3e,0x00,0x4a,0x00,' +` 0x52,0x00,0x61,0x00,0x68,0x00,0x7c,0x00,' +` 0x7d,0x00,0xbb,0x00,0x22,0x01,0x2a,0x01,' +` 0x48,0x01,0x58,0x01,0x74,0x01,0x87,0x01,' +` 0xa0,0x01,0xb3,0x01,0xcc,0x01,0xdf,0x01,' +` 0xf7,0x01,0x0a,0x02,0x21,0x02,0x34,0x02,' +` 0x49,0x02,0x5b,0x02,0x6f,0x02,0x80,0x02,' +` 0x91,0x02,0xa0,0x02,0xaf,0x02,0xbb,0x02,' +` 0xc7,0x02,0xd1,0x02,0xd7,0x42,0xe2,0x02,' +` 0xe8,0x02,0xed,0x02,0xf0,0x02,0xf2,0x02,' +` 0xf2,0x02,0xef,0x02,0xe9,0x02,0xe3,0x02,' +` 0xda,0x02,0xd1,0x02,0xc5,0x02,0xb9,0x02,' +` 0xaa,0x02,0x9b,0x02,0x89,0x02,0x78,0x02,' +` 0x64,0x02,0x51,0x02,0x3a,0x02,0x26,0x02,' +` 0x0c,0x02,0xf9,0x01,0xdb,0x01,0xd8,0x01,' +` 0xd4,0x01,0xb5,0x01,0x9e,0x01,0x82,0x01,' +` 0x6a,0x01,0x50,0x01,0x38,0x01,0x20,0x01,' +` 0x09,0x01,0xf2,0x00,0xdc,0x00,0xc8,0x00,' +` 0xb4,0x00,0xa1,0x00,0x8e,0x00,0x7f,0x00,' +` 0x6d,0x00,0x61,0x00,0x3f,0x00,0x2d,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x04,0x00,0x04,0x00,' +` 0x0c,0x00,0x09,0x00,0x19,0x00,0x11,0x00,' +` 0x2b,0x00,0x1f,0x00,0x4c,0x00,0x30,0x00,' +` 0x69,0x00,0x3e,0x00,0x8a,0x00,0x3f,0x00,' +` 0x93,0x00,0x40,0x00,0xb1,0x00,0x41,0x00,' +` 0xce,0x00,0x3d,0x00,0xe9,0x00,0x31,0x00,' +` 0x00,0x01,0x1b,0x00,0x12,0x01,0xfa,0xff,' +` 0x1d,0x01,0xcc,0xff,0x22,0x01,0x8e,0xff,' +` 0x20,0x01,0x40,0xff,0xd4,0x00,0x8e,0xfe,' +` 0xb6,0x00,0x14,0xfe,0x9a,0x00,0x85,0xfd,' +` 0x7c,0x00,0xda,0xfc,0x5a,0x00,0x13,0xfc,' +` 0x42,0x00,0x2e,0xfb,0x3c,0x00,0x20,0xfa,' +` 0x5a,0x00,0xd8,0xf8,0xbc,0x00,0x30,0xf7,' +` 0xa2,0x01,0xc3,0xf4,0xc1,0x03,0x4d,0xf0,' +` 0xe4,0x09,0x11,0xe2,0x9e,0x3c,0xa8,0x59,' +` 0x44,0xde,0xee,0x09,0x38,0xee,0x2b,0x02,' +` 0x32,0xf2,0x12,0xff,0xfa,0xf3,0x63,0xfd,' +` 0x02,0xf5,0x56,0xfc,0xb9,0xf5,0xa9,0xfb,' +` 0x4d,0xf6,0x3b,0xfb,0xd3,0xf6,0xfe,0xfa,' +` 0x56,0xf7,0xe7,0xfa,0xdf,0xf7,0xfb,0xfa,' +` 0x77,0xf8,0x2a,0xfb,0x11,0xf9,0x74,0xfb,' +` 0xf9,0xf9,0x01,0xfc,0x95,0xfa,0x56,0xfc,' +` 0x2e,0xfb,0xb4,0xfc,0xc5,0xfb,0x16,0xfd,' +` 0x59,0xfc,0x79,0xfd,0xe6,0xfc,0xda,0xfd,' +` 0x6b,0xfd,0x38,0xfe,0xe6,0xfd,0x8f,0xfe,' +` 0x55,0xfe,0xdd,0xfe,0xbd,0xfe,0x38,0xff,' +` 0x1b,0xff,0x6f,0xff,0x5f,0xff,0x9d,0xff,' +` 0x98,0xff,0xc9,0xff,0xc5,0xff,0xe1,0xff,' +` 0xe1,0xff,0xf2,0xff,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf4,0xff,0xef,0xff,0xe3,0xff,0xdc,0xff,' +` 0xc9,0xff,0xc0,0xff,0x9b,0xff,0x92,0xff,' +` 0x68,0xff,0x5e,0xff,0x29,0xff,0x1c,0xff,' +` 0xc6,0xfe,0xc3,0xfe,0x6b,0xfe,0x6c,0xfe,' +` 0x03,0xfe,0x0c,0xfe,0x91,0xfd,0xa5,0xfd,' +` 0x17,0xfd,0x38,0xfd,0x96,0xfc,0xc9,0xfc,' +` 0x11,0xfc,0x5a,0xfc,0x89,0xfb,0xee,0xfb,' +` 0x02,0xfb,0x89,0xfb,0x71,0xfa,0xd8,0xfa,' +` 0xb4,0xf9,0x80,0xfa,0x35,0xf9,0x36,0xfa,' +` 0xc0,0xf8,0x05,0xfa,0x62,0xf8,0xf4,0xf9,' +` 0x12,0xf8,0x00,0xfa,0xcb,0xf7,0x2c,0xfa,' +` 0x88,0xf7,0x81,0xfa,0x3f,0xf7,0x0e,0xfb,' +` 0xdb,0xf6,0xf4,0xfb,0x24,0xf6,0x9b,0xfd,' +` 0x53,0xf4,0xd7,0x01,0x21,0xeb,0x58,0x76,' +` 0x4d,0x0e,0x9e,0xf1,0xef,0x00,0xde,0xf6,' +` 0xf5,0xfe,0xe8,0xf8,0x6f,0xfe,0x33,0xfa,' +` 0x61,0xfe,0x31,0xfb,0x88,0xfe,0x07,0xfc,' +` 0xc8,0xfe,0xc2,0xfc,0x12,0xff,0x68,0xfd,' +` 0x60,0xff,0xfc,0xfd,0xaa,0xff,0x7b,0xfe,' +` 0xea,0xff,0xe7,0xfe,0x23,0x00,0x40,0xff,' +` 0x81,0x00,0xe1,0xff,0xb2,0x00,0x14,0x00,' +` 0xc7,0x00,0x3c,0x00,0xd1,0x00,0x59,0x00,' +` 0xd2,0x00,0x6a,0x00,0xcb,0x00,0x71,0x00,' +` 0xbd,0x00,0x71,0x00,0xab,0x00,0x6b,0x00,' +` 0x95,0x00,0x60,0x00,0x7d,0x00,0x5d,0x00,' +` 0x79,0x00,0x50,0x00,0x5c,0x00,0x3c,0x00,' +` 0x43,0x00,0x25,0x00,0x25,0x00,0x16,0x00,' +` 0x16,0x00,0x0c,0x00,0x0b,0x00,0x05,0x00,' +` 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x3c,0x00,0x78,0x00,' +` 0x74,0x00,0xed,0x00,0xb5,0x00,0x34,0x01,' +` 0xec,0x00,0x87,0x01,0x28,0x01,0xe5,0x01,' +` 0x6a,0x01,0x4c,0x02,0xb0,0x01,0xbc,0x02,' +` 0xf9,0x01,0x35,0x03,0x44,0x02,0xb5,0x03,' +` 0x90,0x02,0x39,0x04,0xdb,0x02,0xa2,0x04,' +` 0xc1,0x02,0x0e,0x05,0xf6,0x02,0x98,0x05,' +` 0x1b,0x03,0x28,0x06,0x2e,0x03,0xbc,0x06,' +` 0x29,0x03,0x59,0x07,0x07,0x03,0x04,0x08,' +` 0xba,0x02,0xca,0x08,0x2f,0x02,0xc4,0x09,' +` 0x40,0x01,0x2d,0x0b,0x8e,0xff,0x9f,0x0d,' +` 0xea,0xfb,0x9b,0x13,0x87,0xef,0xc4,0x3e,' +` 0x6a,0x6c,0x8e,0xea,0x0f,0x15,0x89,0xfa,' +` 0xaa,0x0d,0x74,0xfe,0xbb,0x0a,0x1c,0x00,' +` 0x07,0x09,0xf0,0x00,0xd5,0x07,0x5e,0x01,' +` 0xe4,0x06,0x93,0x01,0x1a,0x06,0xa5,0x01,' +` 0x68,0x05,0x9f,0x01,0xc8,0x04,0x8a,0x01,' +` 0x30,0x04,0x66,0x01,0xa2,0x03,0x40,0x01,' +` 0x11,0x03,0x3c,0x00,0xd5,0x01,0x1c,0x00,' +` 0x82,0x01,0x09,0x00,0x39,0x01,0xf9,0xff,' +` 0xf8,0x00,0xec,0xff,0xc1,0x00,0xe2,0xff,' +` 0x93,0x00,0xdc,0xff,0x6e,0x00,0xda,0xff,' +` 0x50,0x00,0xda,0xff,0x38,0x00,0xdd,0xff,' +` 0x38,0x00,0xf3,0xff,0x28,0x00,0xf4,0xff,' +` 0x1b,0x00,0xf4,0xff,0x08,0x00,0xf2,0xff,' +` 0x04,0x00,0xf7,0xff,0x02,0x00,0xfb,0xff,' +` 0x01,0x00,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xff,0xff,0xfe,0xff,0xfe,0xff,0xfd,0xff,' +` 0xfd,0xff,0xfc,0xff,0xfb,0xff,0xfb,0xff,' +` 0xfb,0xff,0x00,0x00,0x03,0x00,0x01,0x00,' +` 0xfb,0xff,0xfd,0xff,0xfe,0xff,0x00,0x00,' +` 0x03,0x00,0x06,0x00,0x0a,0x00,0x0e,0x00,' +` 0x14,0x00,0x19,0x00,0x21,0x00,0x27,0x00,' +` 0x31,0x00,0x39,0x00,0x45,0x00,0x4d,0x00,' +` 0x5c,0x00,0x65,0x00,0x79,0x00,0x7c,0x00,' +` 0xb0,0x00,0x23,0x01,0x2e,0x01,0x4b,0x01,' +` 0x5b,0x01,0x74,0x01,0x87,0x01,0xa0,0x01,' +` 0xb3,0x01,0xcb,0x01,0xdf,0x01,0xf6,0x01,' +` 0x0a,0x02,0x20,0x02,0x33,0x02,0x47,0x02,' +` 0x59,0x02,0x6c,0x02,0x7c,0x02,0x8d,0x02,' +` 0x9b,0x02,0xa9,0x02,0xb4,0x02,0xbf,0x02,' +` 0xc5,0x42,0xd0,0x02,0xd7,0x02,0xdb,0x02,' +` 0xdd,0x02,0xdd,0x02,0xdb,0x02,0xd8,0x02,' +` 0xd3,0x02,0xcc,0x02,0xc4,0x02,0xba,0x02,' +` 0xb0,0x02,0xa2,0x02,0x95,0x02,0x85,0x02,' +` 0x75,0x02,0x62,0x02,0x50,0x02,0x3b,0x02,' +` 0x28,0x02,0x10,0x02,0xfd,0x01,0xe1,0x01,' +` 0xe7,0x01,0xdc,0x01,0xbf,0x01,0xa7,0x01,' +` 0x8d,0x01,0x75,0x01,0x5c,0x01,0x44,0x01,' +` 0x2c,0x01,0x15,0x01,0xff,0x00,0xe8,0x00,' +` 0xd4,0x00,0xbf,0x00,0xad,0x00,0x9a,0x00,' +` 0x89,0x00,0x78,0x00,0x6a,0x00,0x5a,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x03,0x00,0x09,0x00,' +` 0x08,0x00,0x15,0x00,0x11,0x00,0x27,0x00,' +` 0x1d,0x00,0x3f,0x00,0x2b,0x00,0x5b,0x00,' +` 0x42,0x00,0x8d,0x00,0x5b,0x00,0xa4,0x00,' +` 0x57,0x00,0xc6,0x00,0x64,0x00,0xeb,0x00,' +` 0x6b,0x00,0x10,0x01,0x6c,0x00,0x31,0x01,' +` 0x64,0x00,0x4f,0x01,0x52,0x00,0x67,0x01,' +` 0x33,0x00,0x79,0x01,0x06,0x00,0x83,0x01,' +` 0xc9,0xff,0x85,0x01,0x79,0xff,0x80,0x01,' +` 0xd7,0xfe,0x17,0x01,0x4b,0xfe,0xfe,0x00,' +` 0xb1,0xfd,0xdd,0x00,0xfd,0xfc,0xbd,0x00,' +` 0x2e,0xfc,0xa6,0x00,0x3f,0xfb,0xa4,0x00,' +` 0x26,0xfa,0xc8,0x00,0xce,0xf8,0x34,0x01,' +` 0x0f,0xf7,0x31,0x02,0x7a,0xf4,0x84,0x04,' +` 0x9f,0xef,0x68,0x0b,0x28,0xdf,0x1d,0x51,' +` 0x6c,0x46,0xc1,0xdf,0xc7,0x09,0x6b,0xee,' +` 0x57,0x02,0x56,0xf2,0x4c,0xff,0x1f,0xf4,' +` 0x9d,0xfd,0x2b,0xf5,0x90,0xfc,0xe7,0xf5,' +` 0xe3,0xfb,0x80,0xf6,0x76,0xfb,0x0b,0xf7,' +` 0x3a,0xfb,0x92,0xf7,0x24,0xfb,0x1c,0xf8,' +` 0x2c,0xfb,0xae,0xf8,0x55,0xfb,0x5f,0xf9,' +` 0xea,0xfb,0x2c,0xfa,0x32,0xfc,0xc8,0xfa,' +` 0x87,0xfc,0x62,0xfb,0xe3,0xfc,0xf9,0xfb,' +` 0x43,0xfd,0x8b,0xfc,0xa4,0xfd,0x16,0xfd,' +` 0x04,0xfe,0x99,0xfd,0x5f,0xfe,0x10,0xfe,' +` 0xb3,0xfe,0x7c,0xfe,0xff,0xfe,0xda,0xfe,' +` 0x45,0xff,0x3a,0xff,0x83,0xff,0x7d,0xff,' +` 0xb8,0xff,0xb0,0xff,0xd5,0xff,0xd3,0xff,' +` 0xea,0xff,0xeb,0xff,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf6,0xff,0xed,0xff,0xe6,0xff,0xd8,0xff,' +` 0xce,0xff,0xb9,0xff,0xad,0xff,0x8f,0xff,' +` 0x75,0xff,0x4f,0xff,0x34,0xff,0xf6,0xfe,' +` 0xe2,0xfe,0xa2,0xfe,0x8d,0xfe,0x41,0xfe,' +` 0x2d,0xfe,0xd5,0xfd,0xc5,0xfd,0x61,0xfd,' +` 0x57,0xfd,0xe6,0xfc,0xe4,0xfc,0x67,0xfc,' +` 0x6f,0xfc,0xe5,0xfb,0xfc,0xfb,0x63,0xfb,' +` 0x8c,0xfb,0xe3,0xfa,0x26,0xfb,0x54,0xfa,' +` 0x6b,0xfa,0xab,0xf9,0x15,0xfa,0x44,0xf9,' +` 0xd9,0xf9,0xf0,0xf8,0xb1,0xf9,0xab,0xf8,' +` 0xa0,0xf9,0x74,0xf8,0xa9,0xf9,0x4b,0xf8,' +` 0xd1,0xf9,0x2b,0xf8,0x1d,0xfa,0x0a,0xf8,' +` 0x9a,0xfa,0xd4,0xf7,0x6c,0xfb,0x47,0xf7,' +` 0x14,0xfd,0x18,0xf5,0x8e,0x04,0x41,0x79,' +` 0xd1,0xf1,0x89,0xff,0x19,0xf8,0xc6,0xfd,' +` 0xdc,0xf9,0x87,0xfd,0xf2,0xfa,0xac,0xfd,' +` 0xce,0xfb,0xf9,0xfd,0x8d,0xfc,0x56,0xfe,' +` 0x39,0xfd,0xba,0xfe,0xd4,0xfd,0x1d,0xff,' +` 0x61,0xfe,0x7b,0xff,0xde,0xfe,0xd1,0xff,' +` 0x4b,0xff,0x19,0x00,0xa5,0xff,0x94,0x00,' +` 0x3c,0x00,0xc5,0x00,0x6d,0x00,0xe0,0x00,' +` 0x91,0x00,0xf0,0x00,0xa9,0x00,0xf4,0x00,' +` 0xb5,0x00,0xef,0x00,0xb7,0x00,0xe3,0x00,' +` 0xb0,0x00,0xd0,0x00,0xa3,0x00,0xb8,0x00,' +` 0x90,0x00,0x9d,0x00,0x7c,0x00,0x81,0x00,' +` 0x71,0x00,0x78,0x00,0x59,0x00,0x4d,0x00,' +` 0x38,0x00,0x35,0x00,0x25,0x00,0x21,0x00,' +` 0x16,0x00,0x12,0x00,0x0b,0x00,0x08,0x00,' +` 0x04,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb7,0x00,0x93,0x00,' +` 0xfb,0x00,0xc1,0x00,0x46,0x01,0xf6,0x00,' +` 0x9b,0x01,0x31,0x01,0xfa,0x01,0x71,0x01,' +` 0x62,0x02,0xb6,0x01,0xd3,0x02,0xfc,0x01,' +` 0x4c,0x03,0x43,0x02,0xcc,0x03,0x88,0x02,' +` 0x51,0x04,0xca,0x02,0xdd,0x04,0xc7,0x02,' +` 0x15,0x05,0xe7,0x02,0xa3,0x05,0x03,0x03,' +` 0x33,0x06,0x0e,0x03,0xc7,0x06,0x01,0x03,' +` 0x64,0x07,0xd4,0x02,0x12,0x08,0x7a,0x02,' +` 0xde,0x08,0xdf,0x01,0xe5,0x09,0xd5,0x00,' +` 0x6a,0x0b,0xef,0xfe,0x2b,0x0e,0xbd,0xfa,' +` 0x66,0x15,0x68,0xea,0x9e,0x6a,0xdf,0x40,' +` 0x85,0xee,0x82,0x13,0x04,0xfb,0x19,0x0d,' +` 0x7d,0xfe,0x5b,0x0a,0x02,0x00,0xb6,0x08,' +` 0xc6,0x00,0x8a,0x07,0x2c,0x01,0x9c,0x06,' +` 0x5b,0x01,0xd2,0x05,0x68,0x01,0x21,0x05,' +` 0x5f,0x01,0x82,0x04,0x48,0x01,0xf4,0x03,' +` 0x24,0x01,0x76,0x03,0xae,0x00,0xf0,0x01,' +` 0x14,0x00,0xa0,0x01,0xfc,0xff,0x50,0x01,' +` 0xea,0xff,0x0a,0x01,0xdc,0xff,0xce,0x00,' +` 0xd1,0xff,0x9c,0x00,0xcb,0xff,0x73,0x00,' +` 0xc8,0xff,0x51,0x00,0xc9,0xff,0x37,0x00,' +` 0xcc,0xff,0x24,0x00,0xd1,0xff,0x1a,0x00,' +` 0xe9,0xff,0x1a,0x00,0xe6,0xff,0x05,0x00,' +` 0xea,0xff,0x02,0x00,0xf1,0xff,0x00,0x00,' +` 0xf7,0xff,0x00,0x00,0xfc,0xff,0x00,0x00,' +` 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x78,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0xff,0xff,0xfe,0xff,0xfd,0xff,0xfd,0xff,' +` 0xfc,0xff,0xfb,0xff,0xfa,0xff,0xfa,0xff,' +` 0xf9,0xff,0xfa,0xff,0x01,0x00,0xfb,0xff,' +` 0xf8,0xff,0xfa,0xff,0xfb,0xff,0xfd,0xff,' +` 0xff,0xff,0x02,0x00,0x06,0x00,0x0a,0x00,' +` 0x0f,0x00,0x15,0x00,0x1b,0x00,0x23,0x00,' +` 0x2b,0x00,0x34,0x00,0x3e,0x00,0x49,0x00,' +` 0x54,0x00,0x62,0x00,0x6e,0x00,0x7e,0x00,' +` 0x8b,0x00,0x03,0x01,0x30,0x01,0x3e,0x01,' +` 0x57,0x01,0x69,0x01,0x82,0x01,0x95,0x01,' +` 0xad,0x01,0xc1,0x01,0xd9,0x01,0xed,0x01,' +` 0x03,0x02,0x17,0x02,0x2c,0x02,0x3e,0x02,' +` 0x52,0x02,0x63,0x02,0x75,0x02,0x84,0x02,' +` 0x94,0x02,0xa0,0x02,0xae,0x02,0xb7,0x02,' +` 0xbe,0x42,0xc8,0x02,0xcf,0x02,0xd2,0x02,' +` 0xd4,0x02,0xd3,0x02,0xd2,0x02,0xce,0x02,' +` 0xca,0x02,0xc3,0x02,0xbb,0x02,0xb1,0x02,' +` 0xa7,0x02,0x99,0x02,0x8c,0x02,0x7c,0x02,' +` 0x6c,0x02,0x5a,0x02,0x47,0x02,0x34,0x02,' +` 0x1f,0x02,0x0a,0x02,0xf3,0x01,0xe2,0x01,' +` 0xec,0x01,0xd1,0x01,0xba,0x01,0xa0,0x01,' +` 0x89,0x01,0x6f,0x01,0x58,0x01,0x3f,0x01,' +` 0x28,0x01,0x10,0x01,0xfb,0x00,0xe5,0x00,' +` 0xd1,0x00,0xbc,0x00,0xaa,0x00,0x97,0x00,' +` 0x87,0x00,0x76,0x00,0x69,0x00,0x59,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x04,0x00,0x08,0x00,' +` 0x0b,0x00,0x13,0x00,0x17,0x00,0x23,0x00,' +` 0x27,0x00,0x38,0x00,0x3b,0x00,0x51,0x00,' +` 0x54,0x00,0x7e,0x00,0x70,0x00,0x89,0x00,' +` 0x83,0x00,0xa8,0x00,0x99,0x00,0xc5,0x00,' +` 0xac,0x00,0xdf,0x00,0xbb,0x00,0xf5,0x00,' +` 0xc3,0x00,0x04,0x01,0xc2,0x00,0x0b,0x01,' +` 0xb7,0x00,0x09,0x01,0xa0,0x00,0xfd,0x00,' +` 0x7b,0x00,0xe5,0x00,0x47,0x00,0xc3,0x00,' +` 0xc7,0xff,0x35,0x00,0x5c,0xff,0xef,0xff,' +` 0xeb,0xfe,0x9c,0xff,0x6b,0xfe,0x41,0xff,' +` 0xdb,0xfd,0xe0,0xfe,0x3b,0xfd,0x7f,0xfe,' +` 0x8a,0xfc,0x26,0xfe,0xc4,0xfb,0xdf,0xfd,' +` 0xde,0xfa,0xc5,0xfd,0xb5,0xf9,0x1a,0xfe,' +` 0xcd,0xf7,0x1c,0x00,0xe4,0xf0,0xfd,0x78,' +` 0xf5,0x05,0x84,0xf4,0x89,0xfd,0x08,0xf7,' +` 0xb5,0xfb,0xae,0xf7,0xd1,0xfa,0xf1,0xf7,' +` 0x48,0xfa,0x18,0xf8,0xf4,0xf9,0x3d,0xf8,' +` 0xc8,0xf9,0x69,0xf8,0xba,0xf9,0xa1,0xf8,' +` 0xc8,0xf9,0xe8,0xf8,0xee,0xf9,0x3d,0xf9,' +` 0x29,0xfa,0x9f,0xf9,0x82,0xfa,0x62,0xfa,' +` 0x29,0xfb,0xdf,0xfa,0x91,0xfb,0x5f,0xfb,' +` 0x00,0xfc,0xe1,0xfb,0x74,0xfc,0x63,0xfc,' +` 0xe8,0xfc,0xe4,0xfc,0x5a,0xfd,0x5f,0xfd,' +` 0xc8,0xfd,0xd4,0xfd,0x30,0xfe,0x40,0xfe,' +` 0x8f,0xfe,0xa1,0xfe,0xe4,0xfe,0xf6,0xfe,' +` 0x31,0xff,0x4d,0xff,0x7e,0xff,0x91,0xff,' +` 0xad,0xff,0xba,0xff,0xcf,0xff,0xd8,0xff,' +` 0xe7,0xff,0xed,0xff,0x78,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xf0,0xff,0xe3,0xff,0xde,0xff,0xc8,0xff,' +` 0xc3,0xff,0xa3,0xff,0x9f,0xff,0x71,0xff,' +` 0x64,0xff,0x1f,0xff,0x12,0xff,0xc7,0xfe,' +` 0xc6,0xfe,0x68,0xfe,0x70,0xfe,0xfe,0xfd,' +` 0x10,0xfe,0x89,0xfd,0xaa,0xfd,0x0c,0xfd,' +` 0x3e,0xfd,0x88,0xfc,0xd0,0xfc,0x00,0xfc,' +` 0x63,0xfc,0x76,0xfb,0xf9,0xfb,0xeb,0xfa,' +` 0x95,0xfb,0x63,0xfa,0x3e,0xfb,0xac,0xf9,' +` 0x93,0xfa,0x1a,0xf9,0x5d,0xfa,0xad,0xf8,' +` 0x3c,0xfa,0x4c,0xf8,0x35,0xfa,0xf5,0xf7,' +` 0x4b,0xfa,0xa6,0xf7,0x86,0xfa,0x59,0xf7,' +` 0xee,0xfa,0x01,0xf7,0x95,0xfb,0x84,0xf6,' +` 0xa3,0xfc,0x9f,0xf5,0x8e,0xfe,0x64,0xf3,' +` 0x7f,0x03,0x9b,0xe8,0x7f,0x74,0x87,0x13,' +` 0xac,0xef,0x73,0x02,0x1b,0xf6,0xef,0xff,' +` 0x86,0xf8,0x33,0xff,0x02,0xfa,0x0b,0xff,' +` 0x20,0xfb,0x22,0xff,0x0d,0xfc,0x58,0xff,' +` 0xd9,0xfc,0x9b,0xff,0x8d,0xfd,0xe2,0xff,' +` 0x2b,0xfe,0x28,0x00,0xb5,0xfe,0x68,0x00,' +` 0x2c,0xff,0x9f,0x00,0xd3,0xff,0x10,0x01,' +` 0x20,0x00,0x24,0x01,0x56,0x00,0x2f,0x01,' +` 0x7d,0x00,0x2f,0x01,0x95,0x00,0x27,0x01,' +` 0xa2,0x00,0x16,0x01,0xa4,0x00,0xff,0x00,' +` 0x9e,0x00,0xe4,0x00,0x92,0x00,0xc5,0x00,' +` 0x80,0x00,0xa4,0x00,0x6c,0x00,0x86,0x00,' +` 0x67,0x00,0x6b,0x00,0x40,0x00,0x49,0x00,' +` 0x2d,0x00,0x30,0x00,0x1c,0x00,0x1c,0x00,' +` 0x10,0x00,0x0e,0x00,0x07,0x00,0x05,0x00,' +` 0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x78,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x93,0x00,0xf1,0x00,' +` 0xc4,0x00,0x38,0x01,0xfb,0x00,0x88,0x01,' +` 0x39,0x01,0xe3,0x01,0x7c,0x01,0x46,0x02,' +` 0xc4,0x01,0xb1,0x02,0x0e,0x02,0x24,0x03,' +` 0x59,0x02,0x9c,0x03,0xa3,0x02,0x1a,0x04,' +` 0xea,0x02,0x9f,0x04,0x00,0x03,0xc5,0x04,' +` 0x1b,0x03,0x49,0x05,0x41,0x03,0xcb,0x05,' +` 0x59,0x03,0x4f,0x06,0x5d,0x03,0xd8,0x06,' +` 0x45,0x03,0x6d,0x07,0x08,0x03,0x18,0x08,' +` 0x93,0x02,0xf0,0x08,0xc3,0x01,0x2c,0x0a,' +` 0x3c,0x00,0x6b,0x0c,0xc6,0xfc,0x80,0x12,' +` 0x61,0xee,0x62,0x78,0x7d,0x2c,0xb7,0xf4,' +` 0xd7,0x0f,0x76,0xfd,0x1c,0x0b,0xf8,0xff,' +` 0xff,0x08,0x0c,0x01,0xaf,0x07,0x8f,0x01,' +` 0xb7,0x06,0xc9,0x01,0xed,0x05,0xd9,0x01,' +` 0x3f,0x05,0xd0,0x01,0xa2,0x04,0xb5,0x01,' +` 0x13,0x04,0x91,0x01,0x90,0x03,0x66,0x01,' +` 0x14,0x03,0x72,0x00,0xb5,0x01,0x37,0x00,' +` 0x66,0x01,0x1a,0x00,0x1e,0x01,0x03,0x00,' +` 0xde,0x00,0xf0,0xff,0xa8,0x00,0xe2,0xff,' +` 0x7b,0x00,0xd8,0xff,0x57,0x00,0xd3,0xff,' +` 0x3a,0x00,0xd1,0xff,0x24,0x00,0xd2,0xff,' +` 0x14,0x00,0xd6,0xff,0x0b,0x00,0xec,0xff,' +` 0x0a,0x00,0xe2,0xff,0x00,0x00,0xea,0xff,' +` 0xfe,0xff,0xf1,0xff,0xfe,0xff,0xf7,0xff,' +` 0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,' +` 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00,' +` 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00,' +` 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,' +` 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,' +` 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x30,0x00,0x00,0x00,0x00,0x00,0xdf,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_78mm_pm0_30_90deg_16khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_pm0_30_90deg_16khz.m4 new file mode 100644 index 000000000000..a7635cd64f66 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_pm0_30_90deg_16khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x00,' +` 0x02,0x00,0x0b,0x00,0x11,0x00,0x28,0x00,' +` 0x35,0x00,0x64,0x00,0x79,0x00,0xbf,0x00,' +` 0xe3,0x00,0x48,0x01,0x73,0x01,0xf8,0x01,' +` 0x28,0x02,0xcd,0x02,0xfa,0x02,0xba,0x03,' +` 0xf7,0x03,0xce,0x05,0xc9,0x05,0xeb,0x06,' +` 0xa8,0x06,0xf7,0x07,0x55,0x07,0xf1,0x08,' +` 0xa9,0x07,0xfd,0x09,0x1c,0x07,0xe2,0x0c,' +` 0xb5,0x48,0x91,0x05,0x8b,0x0a,0x6a,0x07,' +` 0x22,0x09,0x3f,0x07,0x13,0x08,0x9e,0x06,' +` 0x01,0x07,0xc0,0x05,0xeb,0x05,0x96,0x04,' +` 0xbe,0x03,0xff,0x02,0xd1,0x02,0x2a,0x02,' +` 0xfb,0x01,0x74,0x01,0x48,0x01,0xe2,0x00,' +` 0xbf,0x00,0x78,0x00,0x5e,0x00,0x2f,0x00,' +` 0x26,0x00,0x0f,0x00,0x0a,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x01,0x00,0x00,0x00,0xfa,0xff,0xee,0xff,' +` 0xd9,0xff,0xb9,0xff,0x8c,0xff,0x49,0xff,' +` 0xfd,0xfe,0x9c,0xfe,0x20,0xfe,0x98,0xfd,' +` 0xf4,0xfc,0x46,0xfc,0x7c,0xfb,0xaf,0xfa,' +` 0xc4,0xf9,0xea,0xf8,0xc0,0xf7,0xf9,0xf4,' +` 0xdb,0xf3,0xdf,0xf2,0xe8,0xf1,0x09,0xf1,' +` 0x38,0xf0,0x87,0xef,0xea,0xee,0x75,0xee,' +` 0x17,0xee,0xe6,0xed,0xbf,0x6d,0x0f,0xee,' +` 0x5c,0xee,0xde,0xee,0x6a,0xef,0x29,0xf0,' +` 0xe8,0xf0,0xda,0xf1,0xb9,0xf2,0xd6,0xf3,' +` 0xb4,0xf4,0x3f,0xf6,0xd9,0xf8,0xaa,0xf9,' +` 0x9f,0xfa,0x6a,0xfb,0x39,0xfc,0xe8,0xfc,' +` 0x8f,0xfd,0x1a,0xfe,0x98,0xfe,0xfb,0xfe,' +` 0x51,0xff,0x94,0xff,0xbb,0xff,0xdc,0xff,' +` 0xf0,0xff,0xfc,0xff,0x01,0x00,0x02,0x00,' +` 0x01,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,' +` 0xfa,0xff,0xee,0xff,0xd9,0xff,0xb9,0xff,' +` 0x8c,0xff,0x49,0xff,0xfd,0xfe,0x9c,0xfe,' +` 0x20,0xfe,0x98,0xfd,0xf4,0xfc,0x46,0xfc,' +` 0x7c,0xfb,0xaf,0xfa,0xc4,0xf9,0xea,0xf8,' +` 0xc0,0xf7,0xf9,0xf4,0xdb,0xf3,0xdf,0xf2,' +` 0xe8,0xf1,0x09,0xf1,0x38,0xf0,0x87,0xef,' +` 0xea,0xee,0x75,0xee,0x17,0xee,0xe6,0xed,' +` 0xbf,0x6d,0x0f,0xee,0x5c,0xee,0xde,0xee,' +` 0x6a,0xef,0x29,0xf0,0xe8,0xf0,0xda,0xf1,' +` 0xb9,0xf2,0xd6,0xf3,0xb4,0xf4,0x3f,0xf6,' +` 0xd9,0xf8,0xaa,0xf9,0x9f,0xfa,0x6a,0xfb,' +` 0x39,0xfc,0xe8,0xfc,0x8f,0xfd,0x1a,0xfe,' +` 0x98,0xfe,0xfb,0xfe,0x51,0xff,0x94,0xff,' +` 0xbb,0xff,0xdc,0xff,0xf0,0xff,0xfc,0xff,' +` 0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0x01,0x00,0x02,0x00,0x0b,0x00,' +` 0x11,0x00,0x28,0x00,0x35,0x00,0x64,0x00,' +` 0x79,0x00,0xbf,0x00,0xe3,0x00,0x48,0x01,' +` 0x73,0x01,0xf8,0x01,0x28,0x02,0xcd,0x02,' +` 0xfa,0x02,0xba,0x03,0xf7,0x03,0xce,0x05,' +` 0xc9,0x05,0xeb,0x06,0xa8,0x06,0xf7,0x07,' +` 0x55,0x07,0xf1,0x08,0xa9,0x07,0xfd,0x09,' +` 0x1c,0x07,0xe2,0x0c,0xb5,0x48,0x91,0x05,' +` 0x8b,0x0a,0x6a,0x07,0x22,0x09,0x3f,0x07,' +` 0x13,0x08,0x9e,0x06,0x01,0x07,0xc0,0x05,' +` 0xeb,0x05,0x96,0x04,0xbe,0x03,0xff,0x02,' +` 0xd1,0x02,0x2a,0x02,0xfb,0x01,0x74,0x01,' +` 0x48,0x01,0xe2,0x00,0xbf,0x00,0x78,0x00,' +` 0x5e,0x00,0x2f,0x00,0x26,0x00,0x0f,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x00,' +` 0x02,0x00,0x0b,0x00,0x11,0x00,0x28,0x00,' +` 0x35,0x00,0x64,0x00,0x79,0x00,0xbf,0x00,' +` 0xe3,0x00,0x48,0x01,0x73,0x01,0xf8,0x01,' +` 0x28,0x02,0xcd,0x02,0xfa,0x02,0xba,0x03,' +` 0xf7,0x03,0xce,0x05,0xc9,0x05,0xeb,0x06,' +` 0xa8,0x06,0xf7,0x07,0x55,0x07,0xf1,0x08,' +` 0xa9,0x07,0xfd,0x09,0x1c,0x07,0xe2,0x0c,' +` 0xb5,0x48,0x91,0x05,0x8b,0x0a,0x6a,0x07,' +` 0x22,0x09,0x3f,0x07,0x13,0x08,0x9e,0x06,' +` 0x01,0x07,0xc0,0x05,0xeb,0x05,0x96,0x04,' +` 0xbe,0x03,0xff,0x02,0xd1,0x02,0x2a,0x02,' +` 0xfb,0x01,0x74,0x01,0x48,0x01,0xe2,0x00,' +` 0xbf,0x00,0x78,0x00,0x5e,0x00,0x2f,0x00,' +` 0x26,0x00,0x0f,0x00,0x0a,0x00,0x00,0x00,' +` 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x01,0x00,0x00,0x00,0xfa,0xff,0xee,0xff,' +` 0xd9,0xff,0xb9,0xff,0x8c,0xff,0x49,0xff,' +` 0xfd,0xfe,0x9c,0xfe,0x20,0xfe,0x98,0xfd,' +` 0xf4,0xfc,0x46,0xfc,0x7c,0xfb,0xaf,0xfa,' +` 0xc4,0xf9,0xea,0xf8,0xc0,0xf7,0xf9,0xf4,' +` 0xdb,0xf3,0xdf,0xf2,0xe8,0xf1,0x09,0xf1,' +` 0x38,0xf0,0x87,0xef,0xea,0xee,0x75,0xee,' +` 0x17,0xee,0xe6,0xed,0xbf,0x6d,0x0f,0xee,' +` 0x5c,0xee,0xde,0xee,0x6a,0xef,0x29,0xf0,' +` 0xe8,0xf0,0xda,0xf1,0xb9,0xf2,0xd6,0xf3,' +` 0xb4,0xf4,0x3f,0xf6,0xd9,0xf8,0xaa,0xf9,' +` 0x9f,0xfa,0x6a,0xfb,0x39,0xfc,0xe8,0xfc,' +` 0x8f,0xfd,0x1a,0xfe,0x98,0xfe,0xfb,0xfe,' +` 0x51,0xff,0x94,0xff,0xbb,0xff,0xdc,0xff,' +` 0xf0,0xff,0xfc,0xff,0x01,0x00,0x02,0x00,' +` 0x01,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,' +` 0xfa,0xff,0xee,0xff,0xd9,0xff,0xb9,0xff,' +` 0x8c,0xff,0x49,0xff,0xfd,0xfe,0x9c,0xfe,' +` 0x20,0xfe,0x98,0xfd,0xf4,0xfc,0x46,0xfc,' +` 0x7c,0xfb,0xaf,0xfa,0xc4,0xf9,0xea,0xf8,' +` 0xc0,0xf7,0xf9,0xf4,0xdb,0xf3,0xdf,0xf2,' +` 0xe8,0xf1,0x09,0xf1,0x38,0xf0,0x87,0xef,' +` 0xea,0xee,0x75,0xee,0x17,0xee,0xe6,0xed,' +` 0xbf,0x6d,0x0f,0xee,0x5c,0xee,0xde,0xee,' +` 0x6a,0xef,0x29,0xf0,0xe8,0xf0,0xda,0xf1,' +` 0xb9,0xf2,0xd6,0xf3,0xb4,0xf4,0x3f,0xf6,' +` 0xd9,0xf8,0xaa,0xf9,0x9f,0xfa,0x6a,0xfb,' +` 0x39,0xfc,0xe8,0xfc,0x8f,0xfd,0x1a,0xfe,' +` 0x98,0xfe,0xfb,0xfe,0x51,0xff,0x94,0xff,' +` 0xbb,0xff,0xdc,0xff,0xf0,0xff,0xfc,0xff,' +` 0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0x01,0x00,0x02,0x00,0x0b,0x00,' +` 0x11,0x00,0x28,0x00,0x35,0x00,0x64,0x00,' +` 0x79,0x00,0xbf,0x00,0xe3,0x00,0x48,0x01,' +` 0x73,0x01,0xf8,0x01,0x28,0x02,0xcd,0x02,' +` 0xfa,0x02,0xba,0x03,0xf7,0x03,0xce,0x05,' +` 0xc9,0x05,0xeb,0x06,0xa8,0x06,0xf7,0x07,' +` 0x55,0x07,0xf1,0x08,0xa9,0x07,0xfd,0x09,' +` 0x1c,0x07,0xe2,0x0c,0xb5,0x48,0x91,0x05,' +` 0x8b,0x0a,0x6a,0x07,0x22,0x09,0x3f,0x07,' +` 0x13,0x08,0x9e,0x06,0x01,0x07,0xc0,0x05,' +` 0xeb,0x05,0x96,0x04,0xbe,0x03,0xff,0x02,' +` 0xd1,0x02,0x2a,0x02,0xfb,0x01,0x74,0x01,' +` 0x48,0x01,0xe2,0x00,0xbf,0x00,0x78,0x00,' +` 0x5e,0x00,0x2f,0x00,0x26,0x00,0x0f,0x00,' +` 0x0a,0x00,0x00,0x00,0x00,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,' +` 0x09,0x00,0x04,0x00,0x06,0x00,0x10,0x00,' +` 0x1a,0x00,0x2a,0x00,0x3a,0x00,0x51,0x00,' +` 0x9a,0x00,0xe5,0x00,0x08,0x01,0x4e,0x01,' +` 0x75,0x01,0xd3,0x01,0xc1,0x01,0xe2,0x01,' +` 0x2f,0x02,0xd5,0x02,0xc5,0x04,0x50,0x05,' +` 0xeb,0x05,0x7b,0x06,0x0e,0x07,0x96,0x07,' +` 0x0c,0x08,0x6b,0x08,0xb9,0x08,0xed,0x48,' +` 0x1f,0x09,0x3a,0x09,0x35,0x09,0x24,0x09,' +` 0xea,0x08,0xaa,0x08,0x30,0x08,0xc0,0x07,' +` 0x12,0x07,0xeb,0x06,0x55,0x06,0xb1,0x05,' +` 0x9c,0x04,0xff,0x02,0x97,0x02,0x04,0x02,' +` 0xa5,0x01,0x33,0x01,0xf5,0x00,0xd1,0x00,' +` 0x94,0x00,0x60,0x00,0x3d,0x00,0x1f,0x00,' +` 0x0f,0x00,0x02,0x00,0xf8,0xff,0xf9,0xff,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfd,0xff,0xf0,0xff,0xfc,0xff,' +` 0xe0,0xff,0xe9,0xff,0xa3,0xff,0xe9,0xff,' +` 0x86,0xff,0x06,0x00,0x77,0xff,0x3c,0x00,' +` 0xa6,0xff,0x26,0x01,0xc3,0xff,0x6b,0x01,' +` 0x77,0xff,0x95,0x01,0x49,0xfe,0x23,0x00,' +` 0x5b,0xfc,0x34,0xff,0xd1,0xf8,0xc0,0xfc,' +` 0x67,0xf5,0x37,0xfb,0x0b,0xf1,0x6b,0xfa,' +` 0xbd,0xea,0xf6,0xfc,0x1a,0xda,0xd8,0x63,' +` 0xae,0x0e,0x3a,0xdd,0x25,0xf4,0xcd,0xe3,' +` 0x7f,0xef,0x92,0xe6,0x9b,0xee,0x5a,0xe9,' +` 0x87,0xef,0x26,0xed,0xb9,0xf2,0xc8,0xf0,' +` 0x53,0xf5,0x20,0xf5,0x86,0xf8,0x39,0xf8,' +` 0xf3,0xfa,0xf0,0xfa,0x12,0xfd,0x82,0xfd,' +` 0xd9,0xfe,0xe7,0xfe,0xb4,0xff,0xb3,0xff,' +` 0x17,0x00,0x09,0x00,0x1b,0x00,0x09,0x00,' +` 0x0b,0x00,0x02,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x03,0x00,0x04,0x00,0x16,0x00,' +` 0xff,0xff,0x27,0x00,0xe3,0xff,0x08,0x00,' +` 0x51,0xff,0x80,0xff,0x32,0xfe,0x7e,0xfe,' +` 0x46,0xfc,0x57,0xfc,0x81,0xf9,0x3a,0xfa,' +` 0x6d,0xf6,0xe6,0xf7,0xa4,0xf2,0x72,0xf4,' +` 0x9d,0xee,0x71,0xf2,0x62,0xea,0xe2,0xef,' +` 0xc7,0xe6,0xf8,0xef,0x9d,0xe3,0x8e,0xf2,' +` 0x7e,0xdf,0x48,0xfb,0xea,0xd0,0xdc,0x4d,' +` 0x90,0x30,0x76,0xd8,0x28,0x01,0x83,0xe9,' +` 0x98,0xfd,0x95,0xf0,0xbb,0xfd,0x63,0xf5,' +` 0xb2,0xfe,0x97,0xf9,0xe5,0x00,0x4a,0xfc,' +` 0x4f,0x01,0x87,0xfe,0x35,0x02,0x5f,0xff,' +` 0xcd,0x01,0xaf,0xff,0x59,0x01,0x6d,0xff,' +` 0x72,0x00,0x75,0xff,0x2a,0x00,0x90,0xff,' +` 0x04,0x00,0xb4,0xff,0x05,0x00,0xea,0xff,' +` 0x01,0x00,0xf8,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,' +` 0xee,0xff,0x0e,0x00,0xff,0xff,0x56,0x00,' +` 0x2e,0x00,0xe4,0x00,0x9d,0x00,0xd8,0x01,' +` 0x55,0x01,0xd1,0x02,0x0a,0x02,0xa1,0x04,' +` 0x6c,0x03,0xe3,0x06,0x80,0x05,0x76,0x0c,' +` 0x66,0x09,0x09,0x10,0xf0,0x0a,0x5e,0x12,' +` 0x68,0x0b,0x0f,0x16,0xf6,0x0a,0x2a,0x1a,' +` 0x7a,0x07,0xbc,0x21,0x95,0xf8,0xe1,0x5b,' +` 0x03,0x6a,0x5a,0xf5,0xcd,0x20,0x11,0x04,' +` 0x79,0x17,0x6a,0x06,0x47,0x12,0x33,0x06,' +` 0x7b,0x0e,0x3f,0x04,0x79,0x07,0x83,0x01,' +` 0x75,0x05,0x5b,0x01,0xeb,0x04,0x2f,0x01,' +` 0x87,0x03,0xc0,0x00,0x66,0x02,0x07,0x00,' +` 0x0c,0x01,0xcd,0xff,0x98,0x00,0xc6,0xff,' +` 0x48,0x00,0xca,0xff,0x22,0x00,0xf5,0xff,' +` 0x10,0x00,0xf6,0xff,0x01,0x00,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xff,0xff,0xee,0xff,0x0e,0x00,' +` 0xff,0xff,0x56,0x00,0x2e,0x00,0xe4,0x00,' +` 0x9d,0x00,0xd8,0x01,0x55,0x01,0xd1,0x02,' +` 0x0a,0x02,0xa1,0x04,0x6c,0x03,0xe3,0x06,' +` 0x80,0x05,0x76,0x0c,0x66,0x09,0x09,0x10,' +` 0xf0,0x0a,0x5e,0x12,0x68,0x0b,0x0f,0x16,' +` 0xf6,0x0a,0x2a,0x1a,0x7a,0x07,0xbc,0x21,' +` 0x95,0xf8,0xe1,0x5b,0x03,0x6a,0x5a,0xf5,' +` 0xcd,0x20,0x11,0x04,0x79,0x17,0x6a,0x06,' +` 0x47,0x12,0x33,0x06,0x7b,0x0e,0x3f,0x04,' +` 0x79,0x07,0x83,0x01,0x75,0x05,0x5b,0x01,' +` 0xeb,0x04,0x2f,0x01,0x87,0x03,0xc0,0x00,' +` 0x66,0x02,0x07,0x00,0x0c,0x01,0xcd,0xff,' +` 0x98,0x00,0xc6,0xff,0x48,0x00,0xca,0xff,' +` 0x22,0x00,0xf5,0xff,0x10,0x00,0xf6,0xff,' +` 0x01,0x00,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,' +` 0x04,0x00,0x16,0x00,0xff,0xff,0x27,0x00,' +` 0xe3,0xff,0x08,0x00,0x51,0xff,0x80,0xff,' +` 0x32,0xfe,0x7e,0xfe,0x46,0xfc,0x57,0xfc,' +` 0x81,0xf9,0x3a,0xfa,0x6d,0xf6,0xe6,0xf7,' +` 0xa4,0xf2,0x72,0xf4,0x9d,0xee,0x71,0xf2,' +` 0x62,0xea,0xe2,0xef,0xc7,0xe6,0xf8,0xef,' +` 0x9d,0xe3,0x8e,0xf2,0x7e,0xdf,0x48,0xfb,' +` 0xea,0xd0,0xdc,0x4d,0x90,0x30,0x76,0xd8,' +` 0x28,0x01,0x83,0xe9,0x98,0xfd,0x95,0xf0,' +` 0xbb,0xfd,0x63,0xf5,0xb2,0xfe,0x97,0xf9,' +` 0xe5,0x00,0x4a,0xfc,0x4f,0x01,0x87,0xfe,' +` 0x35,0x02,0x5f,0xff,0xcd,0x01,0xaf,0xff,' +` 0x59,0x01,0x6d,0xff,0x72,0x00,0x75,0xff,' +` 0x2a,0x00,0x90,0xff,0x04,0x00,0xb4,0xff,' +` 0x05,0x00,0xea,0xff,0x01,0x00,0xf8,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfd,0xff,' +` 0xf0,0xff,0xfc,0xff,0xe0,0xff,0xe9,0xff,' +` 0xa3,0xff,0xe9,0xff,0x86,0xff,0x06,0x00,' +` 0x77,0xff,0x3c,0x00,0xa6,0xff,0x26,0x01,' +` 0xc3,0xff,0x6b,0x01,0x77,0xff,0x95,0x01,' +` 0x49,0xfe,0x23,0x00,0x5b,0xfc,0x34,0xff,' +` 0xd1,0xf8,0xc0,0xfc,0x67,0xf5,0x37,0xfb,' +` 0x0b,0xf1,0x6b,0xfa,0xbd,0xea,0xf6,0xfc,' +` 0x1a,0xda,0xd8,0x63,0xae,0x0e,0x3a,0xdd,' +` 0x25,0xf4,0xcd,0xe3,0x7f,0xef,0x92,0xe6,' +` 0x9b,0xee,0x5a,0xe9,0x87,0xef,0x26,0xed,' +` 0xb9,0xf2,0xc8,0xf0,0x53,0xf5,0x20,0xf5,' +` 0x86,0xf8,0x39,0xf8,0xf3,0xfa,0xf0,0xfa,' +` 0x12,0xfd,0x82,0xfd,0xd9,0xfe,0xe7,0xfe,' +` 0xb4,0xff,0xb3,0xff,0x17,0x00,0x09,0x00,' +` 0x1b,0x00,0x09,0x00,0x0b,0x00,0x02,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x05,0x00,0x09,0x00,0x04,0x00,' +` 0x06,0x00,0x10,0x00,0x1a,0x00,0x2a,0x00,' +` 0x3a,0x00,0x51,0x00,0x9a,0x00,0xe5,0x00,' +` 0x08,0x01,0x4e,0x01,0x75,0x01,0xd3,0x01,' +` 0xc1,0x01,0xe2,0x01,0x2f,0x02,0xd5,0x02,' +` 0xc5,0x04,0x50,0x05,0xeb,0x05,0x7b,0x06,' +` 0x0e,0x07,0x96,0x07,0x0c,0x08,0x6b,0x08,' +` 0xb9,0x08,0xed,0x48,0x1f,0x09,0x3a,0x09,' +` 0x35,0x09,0x24,0x09,0xea,0x08,0xaa,0x08,' +` 0x30,0x08,0xc0,0x07,0x12,0x07,0xeb,0x06,' +` 0x55,0x06,0xb1,0x05,0x9c,0x04,0xff,0x02,' +` 0x97,0x02,0x04,0x02,0xa5,0x01,0x33,0x01,' +` 0xf5,0x00,0xd1,0x00,0x94,0x00,0x60,0x00,' +` 0x3d,0x00,0x1f,0x00,0x0f,0x00,0x02,0x00,' +` 0xf8,0xff,0xf9,0xff,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff,' +` 0xf6,0xff,0xef,0xff,0xe4,0xff,0xda,0xff,' +` 0xca,0xff,0xbd,0xff,0xb3,0xff,0xaa,0xff,' +` 0x93,0xff,0x8c,0xff,0x78,0xff,0x7f,0xff,' +` 0x71,0xff,0x9f,0xff,0xc6,0xff,0xc9,0xff,' +` 0x06,0x00,0x59,0x00,0xa7,0x00,0x2d,0x01,' +` 0x79,0x01,0xab,0x02,0xb1,0x04,0x22,0x05,' +` 0xdd,0x05,0x63,0x06,0x01,0x07,0x78,0x07,' +` 0xef,0x07,0x3a,0x48,0x82,0x08,0x9b,0x08,' +` 0x96,0x08,0x7b,0x08,0x39,0x08,0xf0,0x07,' +` 0x71,0x07,0x65,0x07,0xfb,0x06,0x53,0x06,' +` 0xa6,0x05,0x04,0x05,0x46,0x04,0xc3,0x03,' +` 0x9d,0x02,0xbd,0x01,0x85,0x01,0x11,0x01,' +` 0xd4,0x00,0x89,0x00,0x60,0x00,0x33,0x00,' +` 0x21,0x00,0x1e,0x00,0x11,0x00,0x06,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xfe,0xff,0xfd,0xff,0xe9,0xff,0xfc,0xff,' +` 0xdf,0xff,0x25,0x00,0xfb,0xff,0x94,0x00,' +` 0x61,0x00,0x7f,0x01,0x1c,0x01,0xbd,0x02,' +` 0x0f,0x02,0x3d,0x04,0x08,0x03,0xc6,0x05,' +` 0x1b,0x04,0xf7,0x06,0x97,0x03,0x72,0x07,' +` 0x7b,0x02,0x28,0x07,0x1a,0x00,0x0c,0x06,' +` 0x1e,0xfb,0x01,0x03,0xff,0xf4,0x8d,0x01,' +` 0x2d,0xec,0x42,0x04,0x40,0xd7,0x62,0x56,' +` 0xc3,0x27,0x6c,0xd6,0xcc,0xf8,0xa4,0xe0,' +` 0xf2,0xf0,0x8a,0xe3,0x2e,0xee,0x70,0xe6,' +` 0xa4,0xef,0x7f,0xea,0x50,0xf1,0x5a,0xee,' +` 0xf3,0xf3,0x69,0xf2,0x03,0xf7,0x43,0xf7,' +` 0x15,0xfb,0xa3,0xfa,0x3d,0xfd,0x0f,0xfd,' +` 0xd1,0xfe,0xb5,0xfe,0xc4,0xff,0x9c,0xff,' +` 0x1d,0x00,0x00,0x00,0x2c,0x00,0x11,0x00,' +` 0x12,0x00,0x03,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0x11,0x00,0x13,0x00,0x2b,0x00,' +` 0x06,0x00,0x1b,0x00,0xa7,0xff,0xbf,0xff,' +` 0xca,0xfe,0xc9,0xfe,0x30,0xfd,0x2f,0xfd,' +` 0xd2,0xfa,0xfb,0xfa,0x93,0xf7,0xeb,0xf6,' +` 0xb3,0xf2,0xbb,0xf3,0xbb,0xee,0xf5,0xf0,' +` 0xfb,0xea,0x1b,0xef,0x30,0xe7,0x51,0xed,' +` 0x78,0xe4,0x95,0xef,0x3b,0xe2,0x2e,0xf6,' +` 0xaf,0xda,0xe3,0x18,0x71,0x60,0xcf,0xd9,' +` 0x1d,0x02,0x74,0xed,0x38,0x00,0xc1,0xf5,' +` 0x13,0x02,0x93,0xfb,0x4b,0x05,0x84,0x00,' +` 0xa1,0x06,0xcc,0x02,0x0f,0x07,0xdb,0x03,' +` 0xaa,0x06,0x4f,0x04,0xa3,0x05,0x2f,0x03,' +` 0x23,0x04,0x2f,0x02,0xad,0x02,0x34,0x01,' +` 0x75,0x01,0x72,0x00,0x8f,0x00,0x04,0x00,' +` 0x23,0x00,0xe3,0xff,0xfb,0xff,0xeb,0xff,' +` 0xfc,0xff,0xfe,0xff,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x09,0x00,0x0b,0x00,' +` 0x24,0x00,0x19,0x00,0x3c,0x00,0x4f,0x00,' +` 0x98,0x00,0xba,0x00,0x29,0x01,0x5f,0x01,' +` 0xe3,0x01,0x56,0x02,0xf2,0x03,0x00,0x04,' +` 0x47,0x05,0x48,0x05,0xb2,0x06,0x7d,0x06,' +` 0xf6,0x07,0xcb,0x06,0xb5,0x08,0x41,0x07,' +` 0xb8,0x09,0xeb,0x06,0x23,0x0b,0xa1,0x03,' +` 0x7f,0x47,0xcf,0x0d,0xb9,0x04,0xdb,0x08,' +` 0x18,0x05,0xf4,0x06,0x51,0x04,0x76,0x05,' +` 0x44,0x02,0xfe,0x01,0xca,0x00,0x0c,0x01,' +` 0x0f,0x00,0x52,0x00,0x91,0xff,0xf9,0xff,' +` 0x7b,0xff,0x97,0xff,0x61,0xff,0x93,0xff,' +` 0x77,0xff,0xa5,0xff,0x9c,0xff,0xbf,0xff,' +` 0xb5,0xff,0xd0,0xff,0xd5,0xff,0xe7,0xff,' +` 0xed,0xff,0xf7,0xff,0xfc,0xff,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x09,0x00,0x0b,0x00,0x24,0x00,0x19,0x00,' +` 0x3c,0x00,0x4f,0x00,0x98,0x00,0xba,0x00,' +` 0x29,0x01,0x5f,0x01,0xe3,0x01,0x56,0x02,' +` 0xf2,0x03,0x00,0x04,0x47,0x05,0x48,0x05,' +` 0xb2,0x06,0x7d,0x06,0xf6,0x07,0xcb,0x06,' +` 0xb5,0x08,0x41,0x07,0xb8,0x09,0xeb,0x06,' +` 0x23,0x0b,0xa1,0x03,0x7f,0x47,0xcf,0x0d,' +` 0xb9,0x04,0xdb,0x08,0x18,0x05,0xf4,0x06,' +` 0x51,0x04,0x76,0x05,0x44,0x02,0xfe,0x01,' +` 0xca,0x00,0x0c,0x01,0x0f,0x00,0x52,0x00,' +` 0x91,0xff,0xf9,0xff,0x7b,0xff,0x97,0xff,' +` 0x61,0xff,0x93,0xff,0x77,0xff,0xa5,0xff,' +` 0x9c,0xff,0xbf,0xff,0xb5,0xff,0xd0,0xff,' +` 0xd5,0xff,0xe7,0xff,0xed,0xff,0xf7,0xff,' +` 0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0x11,0x00,' +` 0x13,0x00,0x2b,0x00,0x06,0x00,0x1b,0x00,' +` 0xa7,0xff,0xbf,0xff,0xca,0xfe,0xc9,0xfe,' +` 0x30,0xfd,0x2f,0xfd,0xd2,0xfa,0xfb,0xfa,' +` 0x93,0xf7,0xeb,0xf6,0xb3,0xf2,0xbb,0xf3,' +` 0xbb,0xee,0xf5,0xf0,0xfb,0xea,0x1b,0xef,' +` 0x30,0xe7,0x51,0xed,0x78,0xe4,0x95,0xef,' +` 0x3b,0xe2,0x2e,0xf6,0xaf,0xda,0xe3,0x18,' +` 0x71,0x60,0xcf,0xd9,0x1d,0x02,0x74,0xed,' +` 0x38,0x00,0xc1,0xf5,0x13,0x02,0x93,0xfb,' +` 0x4b,0x05,0x84,0x00,0xa1,0x06,0xcc,0x02,' +` 0x0f,0x07,0xdb,0x03,0xaa,0x06,0x4f,0x04,' +` 0xa3,0x05,0x2f,0x03,0x23,0x04,0x2f,0x02,' +` 0xad,0x02,0x34,0x01,0x75,0x01,0x72,0x00,' +` 0x8f,0x00,0x04,0x00,0x23,0x00,0xe3,0xff,' +` 0xfb,0xff,0xeb,0xff,0xfc,0xff,0xfe,0xff,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xfe,0xff,0xfd,0xff,' +` 0xe9,0xff,0xfc,0xff,0xdf,0xff,0x25,0x00,' +` 0xfb,0xff,0x94,0x00,0x61,0x00,0x7f,0x01,' +` 0x1c,0x01,0xbd,0x02,0x0f,0x02,0x3d,0x04,' +` 0x08,0x03,0xc6,0x05,0x1b,0x04,0xf7,0x06,' +` 0x97,0x03,0x72,0x07,0x7b,0x02,0x28,0x07,' +` 0x1a,0x00,0x0c,0x06,0x1e,0xfb,0x01,0x03,' +` 0xff,0xf4,0x8d,0x01,0x2d,0xec,0x42,0x04,' +` 0x40,0xd7,0x62,0x56,0xc3,0x27,0x6c,0xd6,' +` 0xcc,0xf8,0xa4,0xe0,0xf2,0xf0,0x8a,0xe3,' +` 0x2e,0xee,0x70,0xe6,0xa4,0xef,0x7f,0xea,' +` 0x50,0xf1,0x5a,0xee,0xf3,0xf3,0x69,0xf2,' +` 0x03,0xf7,0x43,0xf7,0x15,0xfb,0xa3,0xfa,' +` 0x3d,0xfd,0x0f,0xfd,0xd1,0xfe,0xb5,0xfe,' +` 0xc4,0xff,0x9c,0xff,0x1d,0x00,0x00,0x00,' +` 0x2c,0x00,0x11,0x00,0x12,0x00,0x03,0x00,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xff,0xff,0xfc,0xff,0xf6,0xff,0xef,0xff,' +` 0xe4,0xff,0xda,0xff,0xca,0xff,0xbd,0xff,' +` 0xb3,0xff,0xaa,0xff,0x93,0xff,0x8c,0xff,' +` 0x78,0xff,0x7f,0xff,0x71,0xff,0x9f,0xff,' +` 0xc6,0xff,0xc9,0xff,0x06,0x00,0x59,0x00,' +` 0xa7,0x00,0x2d,0x01,0x79,0x01,0xab,0x02,' +` 0xb1,0x04,0x22,0x05,0xdd,0x05,0x63,0x06,' +` 0x01,0x07,0x78,0x07,0xef,0x07,0x3a,0x48,' +` 0x82,0x08,0x9b,0x08,0x96,0x08,0x7b,0x08,' +` 0x39,0x08,0xf0,0x07,0x71,0x07,0x65,0x07,' +` 0xfb,0x06,0x53,0x06,0xa6,0x05,0x04,0x05,' +` 0x46,0x04,0xc3,0x03,0x9d,0x02,0xbd,0x01,' +` 0x85,0x01,0x11,0x01,0xd4,0x00,0x89,0x00,' +` 0x60,0x00,0x33,0x00,0x21,0x00,0x1e,0x00,' +` 0x11,0x00,0x06,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xdf,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_78mm_pm0_30_90deg_48khz.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_pm0_30_90deg_48khz.m4 new file mode 100644 index 000000000000..39c6f8410f7c --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_78mm_pm0_30_90deg_48khz.m4 @@ -0,0 +1,498 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x54,0x0f,0x00,0x00,0x08,0x00,0x02,0x00,' +` 0x01,0x00,0x04,0x00,0x03,0x00,0x01,0x00,' +` 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x04,0x00,0x0b,0x00,0x21,0x00,' +` 0x2d,0x00,0x5e,0x00,0x65,0x00,0xba,0x00,' +` 0xb0,0x00,0x33,0x01,0x0c,0x01,0xc8,0x01,' +` 0x72,0x01,0x75,0x02,0xde,0x01,0x37,0x03,' +` 0x47,0x02,0x0a,0x04,0xa3,0x02,0xeb,0x04,' +` 0xe8,0x02,0xdd,0x05,0x05,0x03,0xe5,0x06,' +` 0xdf,0x02,0x1c,0x08,0x43,0x02,0xcf,0x09,' +` 0x97,0x00,0x2d,0x0d,0xbb,0xfa,0x12,0x1f,' +` 0xf6,0x7f,0x5d,0xf4,0x5c,0x0f,0x7c,0xff,' +` 0x6f,0x0a,0xd3,0x01,0x61,0x08,0xa4,0x02,' +` 0x06,0x07,0xe0,0x02,0xed,0x05,0xcf,0x02,' +` 0xf2,0x04,0x91,0x02,0x0c,0x04,0x39,0x02,' +` 0x36,0x03,0xd4,0x01,0x73,0x02,0x6b,0x01,' +` 0xc5,0x01,0x06,0x01,0x31,0x01,0xad,0x00,' +` 0xb8,0x00,0x63,0x00,0x5d,0x00,0x2c,0x00,' +` 0x21,0x00,0x0b,0x00,0x04,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf3,0xff,0xe3,0xff,0xcc,0xff,0xae,0xff,' +` 0x8a,0xff,0x5f,0xff,0x2f,0xff,0xf9,0xfe,' +` 0xbd,0xfe,0x7d,0xfe,0x3a,0xfe,0xf2,0xfd,' +` 0xa8,0xfd,0x5b,0xfd,0x0e,0xfd,0xc0,0xfc,' +` 0x73,0xfc,0x26,0xfc,0xdc,0xfb,0x94,0xfb,' +` 0x51,0xfb,0x10,0xfb,0xd6,0xfa,0x9f,0xfa,' +` 0x72,0xfa,0x48,0xfa,0x28,0xfa,0x0d,0xfa,' +` 0xfd,0xf9,0xf1,0xf9,0xdf,0x79,0xfc,0xf9,' +` 0x10,0xfa,0x28,0xfa,0x4c,0xfa,0x73,0xfa,' +` 0xa5,0xfa,0xd8,0xfa,0x16,0xfb,0x54,0xfb,' +` 0x9a,0xfb,0xe0,0xfb,0x2d,0xfc,0x77,0xfc,' +` 0xc7,0xfc,0x12,0xfd,0x62,0xfd,0xac,0xfd,' +` 0xf7,0xfd,0x3d,0xfe,0x82,0xfe,0xc0,0xfe,' +` 0xfc,0xfe,0x31,0xff,0x61,0xff,0x8b,0xff,' +` 0xaf,0xff,0xcc,0xff,0xe3,0xff,0xf3,0xff,' +` 0xfd,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf3,0xff,0xe3,0xff,' +` 0xcc,0xff,0xae,0xff,0x8a,0xff,0x5f,0xff,' +` 0x2f,0xff,0xf9,0xfe,0xbd,0xfe,0x7d,0xfe,' +` 0x3a,0xfe,0xf2,0xfd,0xa8,0xfd,0x5b,0xfd,' +` 0x0e,0xfd,0xc0,0xfc,0x73,0xfc,0x26,0xfc,' +` 0xdc,0xfb,0x94,0xfb,0x51,0xfb,0x10,0xfb,' +` 0xd6,0xfa,0x9f,0xfa,0x72,0xfa,0x48,0xfa,' +` 0x28,0xfa,0x0d,0xfa,0xfd,0xf9,0xf1,0xf9,' +` 0xdf,0x79,0xfc,0xf9,0x10,0xfa,0x28,0xfa,' +` 0x4c,0xfa,0x73,0xfa,0xa5,0xfa,0xd8,0xfa,' +` 0x16,0xfb,0x54,0xfb,0x9a,0xfb,0xe0,0xfb,' +` 0x2d,0xfc,0x77,0xfc,0xc7,0xfc,0x12,0xfd,' +` 0x62,0xfd,0xac,0xfd,0xf7,0xfd,0x3d,0xfe,' +` 0x82,0xfe,0xc0,0xfe,0xfc,0xfe,0x31,0xff,' +` 0x61,0xff,0x8b,0xff,0xaf,0xff,0xcc,0xff,' +` 0xe3,0xff,0xf3,0xff,0xfd,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0x0b,0x00,0x21,0x00,0x2d,0x00,0x5e,0x00,' +` 0x65,0x00,0xba,0x00,0xb0,0x00,0x33,0x01,' +` 0x0c,0x01,0xc8,0x01,0x72,0x01,0x75,0x02,' +` 0xde,0x01,0x37,0x03,0x47,0x02,0x0a,0x04,' +` 0xa3,0x02,0xeb,0x04,0xe8,0x02,0xdd,0x05,' +` 0x05,0x03,0xe5,0x06,0xdf,0x02,0x1c,0x08,' +` 0x43,0x02,0xcf,0x09,0x97,0x00,0x2d,0x0d,' +` 0xbb,0xfa,0x12,0x1f,0xf6,0x7f,0x5d,0xf4,' +` 0x5c,0x0f,0x7c,0xff,0x6f,0x0a,0xd3,0x01,' +` 0x61,0x08,0xa4,0x02,0x06,0x07,0xe0,0x02,' +` 0xed,0x05,0xcf,0x02,0xf2,0x04,0x91,0x02,' +` 0x0c,0x04,0x39,0x02,0x36,0x03,0xd4,0x01,' +` 0x73,0x02,0x6b,0x01,0xc5,0x01,0x06,0x01,' +` 0x31,0x01,0xad,0x00,0xb8,0x00,0x63,0x00,' +` 0x5d,0x00,0x2c,0x00,0x21,0x00,0x0b,0x00,' +` 0x04,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x04,0x00,0x0b,0x00,0x21,0x00,' +` 0x2d,0x00,0x5e,0x00,0x65,0x00,0xba,0x00,' +` 0xb0,0x00,0x33,0x01,0x0c,0x01,0xc8,0x01,' +` 0x72,0x01,0x75,0x02,0xde,0x01,0x37,0x03,' +` 0x47,0x02,0x0a,0x04,0xa3,0x02,0xeb,0x04,' +` 0xe8,0x02,0xdd,0x05,0x05,0x03,0xe5,0x06,' +` 0xdf,0x02,0x1c,0x08,0x43,0x02,0xcf,0x09,' +` 0x97,0x00,0x2d,0x0d,0xbb,0xfa,0x12,0x1f,' +` 0xf6,0x7f,0x5d,0xf4,0x5c,0x0f,0x7c,0xff,' +` 0x6f,0x0a,0xd3,0x01,0x61,0x08,0xa4,0x02,' +` 0x06,0x07,0xe0,0x02,0xed,0x05,0xcf,0x02,' +` 0xf2,0x04,0x91,0x02,0x0c,0x04,0x39,0x02,' +` 0x36,0x03,0xd4,0x01,0x73,0x02,0x6b,0x01,' +` 0xc5,0x01,0x06,0x01,0x31,0x01,0xad,0x00,' +` 0xb8,0x00,0x63,0x00,0x5d,0x00,0x2c,0x00,' +` 0x21,0x00,0x0b,0x00,0x04,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0xff,' +` 0xf3,0xff,0xe3,0xff,0xcc,0xff,0xae,0xff,' +` 0x8a,0xff,0x5f,0xff,0x2f,0xff,0xf9,0xfe,' +` 0xbd,0xfe,0x7d,0xfe,0x3a,0xfe,0xf2,0xfd,' +` 0xa8,0xfd,0x5b,0xfd,0x0e,0xfd,0xc0,0xfc,' +` 0x73,0xfc,0x26,0xfc,0xdc,0xfb,0x94,0xfb,' +` 0x51,0xfb,0x10,0xfb,0xd6,0xfa,0x9f,0xfa,' +` 0x72,0xfa,0x48,0xfa,0x28,0xfa,0x0d,0xfa,' +` 0xfd,0xf9,0xf1,0xf9,0xdf,0x79,0xfc,0xf9,' +` 0x10,0xfa,0x28,0xfa,0x4c,0xfa,0x73,0xfa,' +` 0xa5,0xfa,0xd8,0xfa,0x16,0xfb,0x54,0xfb,' +` 0x9a,0xfb,0xe0,0xfb,0x2d,0xfc,0x77,0xfc,' +` 0xc7,0xfc,0x12,0xfd,0x62,0xfd,0xac,0xfd,' +` 0xf7,0xfd,0x3d,0xfe,0x82,0xfe,0xc0,0xfe,' +` 0xfc,0xfe,0x31,0xff,0x61,0xff,0x8b,0xff,' +` 0xaf,0xff,0xcc,0xff,0xe3,0xff,0xf3,0xff,' +` 0xfd,0xff,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfd,0xff,0xf3,0xff,0xe3,0xff,' +` 0xcc,0xff,0xae,0xff,0x8a,0xff,0x5f,0xff,' +` 0x2f,0xff,0xf9,0xfe,0xbd,0xfe,0x7d,0xfe,' +` 0x3a,0xfe,0xf2,0xfd,0xa8,0xfd,0x5b,0xfd,' +` 0x0e,0xfd,0xc0,0xfc,0x73,0xfc,0x26,0xfc,' +` 0xdc,0xfb,0x94,0xfb,0x51,0xfb,0x10,0xfb,' +` 0xd6,0xfa,0x9f,0xfa,0x72,0xfa,0x48,0xfa,' +` 0x28,0xfa,0x0d,0xfa,0xfd,0xf9,0xf1,0xf9,' +` 0xdf,0x79,0xfc,0xf9,0x10,0xfa,0x28,0xfa,' +` 0x4c,0xfa,0x73,0xfa,0xa5,0xfa,0xd8,0xfa,' +` 0x16,0xfb,0x54,0xfb,0x9a,0xfb,0xe0,0xfb,' +` 0x2d,0xfc,0x77,0xfc,0xc7,0xfc,0x12,0xfd,' +` 0x62,0xfd,0xac,0xfd,0xf7,0xfd,0x3d,0xfe,' +` 0x82,0xfe,0xc0,0xfe,0xfc,0xfe,0x31,0xff,' +` 0x61,0xff,0x8b,0xff,0xaf,0xff,0xcc,0xff,' +` 0xe3,0xff,0xf3,0xff,0xfd,0xff,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,' +` 0x0b,0x00,0x21,0x00,0x2d,0x00,0x5e,0x00,' +` 0x65,0x00,0xba,0x00,0xb0,0x00,0x33,0x01,' +` 0x0c,0x01,0xc8,0x01,0x72,0x01,0x75,0x02,' +` 0xde,0x01,0x37,0x03,0x47,0x02,0x0a,0x04,' +` 0xa3,0x02,0xeb,0x04,0xe8,0x02,0xdd,0x05,' +` 0x05,0x03,0xe5,0x06,0xdf,0x02,0x1c,0x08,' +` 0x43,0x02,0xcf,0x09,0x97,0x00,0x2d,0x0d,' +` 0xbb,0xfa,0x12,0x1f,0xf6,0x7f,0x5d,0xf4,' +` 0x5c,0x0f,0x7c,0xff,0x6f,0x0a,0xd3,0x01,' +` 0x61,0x08,0xa4,0x02,0x06,0x07,0xe0,0x02,' +` 0xed,0x05,0xcf,0x02,0xf2,0x04,0x91,0x02,' +` 0x0c,0x04,0x39,0x02,0x36,0x03,0xd4,0x01,' +` 0x73,0x02,0x6b,0x01,0xc5,0x01,0x06,0x01,' +` 0x31,0x01,0xad,0x00,0xb8,0x00,0x63,0x00,' +` 0x5d,0x00,0x2c,0x00,0x21,0x00,0x0b,0x00,' +` 0x04,0x00,0x00,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x01,0x00,0x03,0x00,0x08,0x00,' +` 0x13,0x00,0x1e,0x00,0x2c,0x00,0x3c,0x00,' +` 0x50,0x00,0x65,0x00,0x7e,0x00,0x98,0x00,' +` 0xb6,0x00,0xd5,0x00,0xf8,0x00,0x1a,0x01,' +` 0x3f,0x01,0x64,0x01,0x8b,0x01,0xb1,0x01,' +` 0xd7,0x01,0xfd,0x01,0x21,0x02,0x43,0x02,' +` 0x64,0x02,0x82,0x02,0x9d,0x02,0xb6,0x02,' +` 0xcb,0x02,0xdd,0x02,0xec,0x02,0xf6,0x02,' +` 0xf2,0x42,0xff,0x02,0xfd,0x02,0xf8,0x02,' +` 0xed,0x02,0xe0,0x02,0xcd,0x02,0xb8,0x02,' +` 0x9e,0x02,0x82,0x02,0x62,0x02,0x40,0x02,' +` 0x1b,0x02,0xf5,0x01,0xcd,0x01,0xa5,0x01,' +` 0x7b,0x01,0x53,0x01,0x2a,0x01,0x03,0x01,' +` 0xdc,0x00,0xb9,0x00,0x97,0x00,0x78,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xfa,0xff,' +` 0xfc,0xff,0xe0,0xff,0xf4,0xff,0xb1,0xff,' +` 0xe5,0xff,0x69,0xff,0xce,0xff,0x03,0xff,' +` 0xaf,0xff,0x7d,0xfe,0x8b,0xff,0xd5,0xfd,' +` 0x64,0xff,0x09,0xfd,0x42,0xff,0x16,0xfc,' +` 0x2f,0xff,0xf7,0xfa,0x3b,0xff,0x99,0xf9,' +` 0x80,0xff,0xe4,0xf7,0x3f,0x00,0x88,0xf5,' +` 0x15,0x02,0x78,0xf1,0x5b,0x07,0x74,0xe5,' +` 0x19,0x2e,0x53,0x64,0xa0,0xdf,0x7d,0x08,' +` 0x78,0xef,0x52,0x01,0x98,0xf3,0xb3,0xfe,' +` 0xb7,0xf5,0x7a,0xfd,0x36,0xf7,0xee,0xfc,' +` 0x7b,0xf8,0xd4,0xfc,0xb0,0xf9,0x00,0xfd,' +` 0xd3,0xfa,0x58,0xfd,0xe5,0xfb,0xcb,0xfd,' +` 0xe6,0xfc,0x4c,0xfe,0xcd,0xfd,0xcb,0xfe,' +` 0x92,0xfe,0x3c,0xff,0x31,0xff,0x99,0xff,' +` 0xa4,0xff,0xdb,0xff,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0xeb,0xff,0xd8,0xff,0xa7,0xff,0x93,0xff,' +` 0x39,0xff,0x31,0xff,0xa1,0xfe,0xb6,0xfe,' +` 0xe7,0xfd,0x2d,0xfe,0x0f,0xfd,0x9f,0xfd,' +` 0x22,0xfc,0x1a,0xfd,0x29,0xfb,0xac,0xfc,' +` 0x28,0xfa,0x62,0xfc,0x1e,0xf9,0x55,0xfc,' +` 0x14,0xf8,0xa7,0xfc,0xe7,0xf6,0x86,0xfd,' +` 0x48,0xf5,0x7f,0xff,0x22,0xf2,0x23,0x05,' +` 0x28,0xe5,0x94,0x70,0x81,0x1a,0x4d,0xec,' +` 0x9c,0x03,0x62,0xf4,0x2e,0x00,0x5b,0xf7,' +` 0x11,0xff,0x2f,0xf9,0xb5,0xfe,0x90,0xfa,' +` 0xae,0xfe,0xb0,0xfb,0xcc,0xfe,0xa3,0xfc,' +` 0xfd,0xfe,0x73,0xfd,0x35,0xff,0x23,0xfe,' +` 0x6c,0xff,0xb5,0xfe,0x9c,0xff,0x28,0xff,' +` 0xc3,0xff,0x80,0xff,0xdf,0xff,0xbe,0xff,' +` 0xf2,0xff,0xe5,0xff,0xfe,0xff,0xfb,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8c,0x00,0x35,0x01,' +` 0xdf,0x00,0xe2,0x01,0x3a,0x01,0xb0,0x02,' +` 0x95,0x01,0x9b,0x03,0xe2,0x01,0xa0,0x04,' +` 0x15,0x02,0xc0,0x05,0x1c,0x02,0x01,0x07,' +` 0xdd,0x01,0x75,0x08,0x2a,0x01,0x53,0x0a,' +` 0xa1,0xff,0x39,0x0d,0x0c,0xfc,0xb4,0x13,' +` 0x5e,0xef,0xf4,0x40,0xf2,0x6a,0x9b,0xea,' +` 0x78,0x15,0xc1,0xfa,0xd2,0x0d,0xbf,0xfe,' +` 0x99,0x0a,0x64,0x00,0x93,0x08,0x25,0x01,' +` 0x0a,0x07,0x73,0x01,0xbe,0x05,0x7a,0x01,' +` 0x9b,0x04,0x5c,0x01,0x9a,0x03,0x29,0x01,' +` 0xb9,0x02,0xed,0x00,0xf7,0x01,0xb0,0x00,' +` 0x55,0x01,0x78,0x00,0xd5,0x00,0x49,0x00,' +` 0x74,0x00,0x25,0x00,0x30,0x00,0x05,0x00,' +` 0x08,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x8c,0x00,0x35,0x01,0xdf,0x00,0xe2,0x01,' +` 0x3a,0x01,0xb0,0x02,0x95,0x01,0x9b,0x03,' +` 0xe2,0x01,0xa0,0x04,0x15,0x02,0xc0,0x05,' +` 0x1c,0x02,0x01,0x07,0xdd,0x01,0x75,0x08,' +` 0x2a,0x01,0x53,0x0a,0xa1,0xff,0x39,0x0d,' +` 0x0c,0xfc,0xb4,0x13,0x5e,0xef,0xf4,0x40,' +` 0xf2,0x6a,0x9b,0xea,0x78,0x15,0xc1,0xfa,' +` 0xd2,0x0d,0xbf,0xfe,0x99,0x0a,0x64,0x00,' +` 0x93,0x08,0x25,0x01,0x0a,0x07,0x73,0x01,' +` 0xbe,0x05,0x7a,0x01,0x9b,0x04,0x5c,0x01,' +` 0x9a,0x03,0x29,0x01,0xb9,0x02,0xed,0x00,' +` 0xf7,0x01,0xb0,0x00,0x55,0x01,0x78,0x00,' +` 0xd5,0x00,0x49,0x00,0x74,0x00,0x25,0x00,' +` 0x30,0x00,0x05,0x00,0x08,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0xeb,0xff,0xd8,0xff,' +` 0xa7,0xff,0x93,0xff,0x39,0xff,0x31,0xff,' +` 0xa1,0xfe,0xb6,0xfe,0xe7,0xfd,0x2d,0xfe,' +` 0x0f,0xfd,0x9f,0xfd,0x22,0xfc,0x1a,0xfd,' +` 0x29,0xfb,0xac,0xfc,0x28,0xfa,0x62,0xfc,' +` 0x1e,0xf9,0x55,0xfc,0x14,0xf8,0xa7,0xfc,' +` 0xe7,0xf6,0x86,0xfd,0x48,0xf5,0x7f,0xff,' +` 0x22,0xf2,0x23,0x05,0x28,0xe5,0x94,0x70,' +` 0x81,0x1a,0x4d,0xec,0x9c,0x03,0x62,0xf4,' +` 0x2e,0x00,0x5b,0xf7,0x11,0xff,0x2f,0xf9,' +` 0xb5,0xfe,0x90,0xfa,0xae,0xfe,0xb0,0xfb,' +` 0xcc,0xfe,0xa3,0xfc,0xfd,0xfe,0x73,0xfd,' +` 0x35,0xff,0x23,0xfe,0x6c,0xff,0xb5,0xfe,' +` 0x9c,0xff,0x28,0xff,0xc3,0xff,0x80,0xff,' +` 0xdf,0xff,0xbe,0xff,0xf2,0xff,0xe5,0xff,' +` 0xfe,0xff,0xfb,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0xfa,0xff,0xfc,0xff,0xe0,0xff,' +` 0xf4,0xff,0xb1,0xff,0xe5,0xff,0x69,0xff,' +` 0xce,0xff,0x03,0xff,0xaf,0xff,0x7d,0xfe,' +` 0x8b,0xff,0xd5,0xfd,0x64,0xff,0x09,0xfd,' +` 0x42,0xff,0x16,0xfc,0x2f,0xff,0xf7,0xfa,' +` 0x3b,0xff,0x99,0xf9,0x80,0xff,0xe4,0xf7,' +` 0x3f,0x00,0x88,0xf5,0x15,0x02,0x78,0xf1,' +` 0x5b,0x07,0x74,0xe5,0x19,0x2e,0x53,0x64,' +` 0xa0,0xdf,0x7d,0x08,0x78,0xef,0x52,0x01,' +` 0x98,0xf3,0xb3,0xfe,0xb7,0xf5,0x7a,0xfd,' +` 0x36,0xf7,0xee,0xfc,0x7b,0xf8,0xd4,0xfc,' +` 0xb0,0xf9,0x00,0xfd,0xd3,0xfa,0x58,0xfd,' +` 0xe5,0xfb,0xcb,0xfd,0xe6,0xfc,0x4c,0xfe,' +` 0xcd,0xfd,0xcb,0xfe,0x92,0xfe,0x3c,0xff,' +` 0x31,0xff,0x99,0xff,0xa4,0xff,0xdb,0xff,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x03,0x00,0x08,0x00,0x13,0x00,0x1e,0x00,' +` 0x2c,0x00,0x3c,0x00,0x50,0x00,0x65,0x00,' +` 0x7e,0x00,0x98,0x00,0xb6,0x00,0xd5,0x00,' +` 0xf8,0x00,0x1a,0x01,0x3f,0x01,0x64,0x01,' +` 0x8b,0x01,0xb1,0x01,0xd7,0x01,0xfd,0x01,' +` 0x21,0x02,0x43,0x02,0x64,0x02,0x82,0x02,' +` 0x9d,0x02,0xb6,0x02,0xcb,0x02,0xdd,0x02,' +` 0xec,0x02,0xf6,0x02,0xf2,0x42,0xff,0x02,' +` 0xfd,0x02,0xf8,0x02,0xed,0x02,0xe0,0x02,' +` 0xcd,0x02,0xb8,0x02,0x9e,0x02,0x82,0x02,' +` 0x62,0x02,0x40,0x02,0x1b,0x02,0xf5,0x01,' +` 0xcd,0x01,0xa5,0x01,0x7b,0x01,0x53,0x01,' +` 0x2a,0x01,0x03,0x01,0xdc,0x00,0xb9,0x00,' +` 0x97,0x00,0x78,0x00,0x40,0x00,0x01,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,' +` 0x06,0x00,0x0a,0x00,0x10,0x00,0x17,0x00,' +` 0x20,0x00,0x47,0x00,0x62,0x00,0x76,0x00,' +` 0x90,0x00,0xa9,0x00,0xc7,0x00,0xe4,0x00,' +` 0x05,0x01,0x26,0x01,0x49,0x01,0x6b,0x01,' +` 0x8f,0x01,0xb2,0x01,0xd5,0x01,0xf6,0x01,' +` 0x18,0x02,0x36,0x02,0x53,0x02,0x6d,0x02,' +` 0x85,0x02,0x99,0x02,0xab,0x02,0xb7,0x02,' +` 0xb7,0x42,0xc6,0x02,0xc7,0x02,0xc2,0x02,' +` 0xba,0x02,0xad,0x02,0x9d,0x02,0x88,0x02,' +` 0x70,0x02,0x55,0x02,0x37,0x02,0x16,0x02,' +` 0xf4,0x01,0xcf,0x01,0xaa,0x01,0x83,0x01,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x05,0x00,0x07,0x00,0x12,0x00,' +` 0x0d,0x00,0x21,0x00,0x0d,0x00,0x2c,0x00,' +` 0xf0,0xff,0x11,0x00,0xc3,0xff,0xf9,0xff,' +` 0x7f,0xff,0xcd,0xff,0x1c,0xff,0x8b,0xff,' +` 0x99,0xfe,0x38,0xff,0xf6,0xfd,0xd6,0xfe,' +` 0x32,0xfd,0x70,0xfe,0x4d,0xfc,0x15,0xfe,' +` 0x40,0xfb,0xe3,0xfd,0xef,0xf9,0x25,0xfe,' +` 0xe4,0xf7,0x1c,0x00,0xe6,0xf0,0xef,0x78,' +` 0xef,0x05,0xa5,0xf4,0x97,0xfd,0x5a,0xf7,' +` 0xf0,0xfb,0x4d,0xf8,0x53,0xfb,0xf4,0xf8,' +` 0x2c,0xfb,0x97,0xf9,0x51,0xfb,0x48,0xfa,' +` 0xac,0xfb,0x0b,0xfb,0x2e,0xfc,0xda,0xfb,' +` 0xcb,0xfc,0xaf,0xfc,0x75,0xfd,0x7f,0xfd,' +` 0x1f,0xfe,0x40,0xfe,0xc0,0xfe,0xf8,0xfe,' +` 0x50,0xff,0x77,0xff,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x8a,0xff,0x34,0xff,0x20,0xff,0x8f,0xfe,' +` 0x83,0xfe,0xc8,0xfd,0xea,0xfd,0xef,0xfc,' +` 0x4e,0xfd,0x07,0xfc,0xbd,0xfc,0x1a,0xfb,' +` 0x46,0xfc,0x30,0xfa,0xf7,0xfb,0x4b,0xf9,' +` 0xe4,0xfb,0x69,0xf8,0x24,0xfc,0x74,0xf7,' +` 0xe3,0xfc,0x2d,0xf6,0x9b,0xfe,0xaa,0xf3,' +` 0x75,0x03,0xb3,0xe8,0x71,0x74,0x85,0x13,' +` 0xbd,0xef,0x6c,0x02,0x52,0xf6,0xef,0xff,' +` 0xec,0xf8,0x43,0xff,0x99,0xfa,0x2a,0xff,' +` 0xe3,0xfb,0x4c,0xff,0xf0,0xfc,0x84,0xff,' +` 0xce,0xfd,0xbe,0xff,0x82,0xfe,0xef,0xff,' +` 0x0e,0xff,0x13,0x00,0x76,0xff,0x27,0x00,' +` 0xbc,0xff,0x2c,0x00,0xf6,0xff,0x32,0x00,' +` 0x04,0x00,0x1e,0x00,0x06,0x00,0x0d,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x0c,0x02,0x79,0x04,' +` 0x47,0x02,0x78,0x05,0x59,0x02,0x90,0x06,' +` 0x2c,0x02,0xd0,0x07,0x96,0x01,0x6a,0x09,' +` 0x39,0x00,0xf9,0x0b,0xd8,0xfc,0x4b,0x12,' +` 0x74,0xee,0x54,0x78,0x78,0x2c,0xc2,0xf4,' +` 0xaa,0x0f,0x84,0xfd,0xb6,0x0a,0xf9,0xff,' +` 0x53,0x08,0xf1,0x00,0xb7,0x06,0x51,0x01,' +` 0x72,0x05,0x62,0x01,0x5e,0x04,0x49,0x01,' +` 0x6d,0x03,0x1a,0x01,0x9b,0x02,0xe2,0x00,' +` 0xe8,0x01,0xa8,0x00,0x52,0x01,0x73,0x00,' +` 0xd8,0x00,0x1a,0x00,0x50,0x00,0x08,0x00,' +` 0x25,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x02,0x79,0x04,0x47,0x02,0x78,0x05,' +` 0x59,0x02,0x90,0x06,0x2c,0x02,0xd0,0x07,' +` 0x96,0x01,0x6a,0x09,0x39,0x00,0xf9,0x0b,' +` 0xd8,0xfc,0x4b,0x12,0x74,0xee,0x54,0x78,' +` 0x78,0x2c,0xc2,0xf4,0xaa,0x0f,0x84,0xfd,' +` 0xb6,0x0a,0xf9,0xff,0x53,0x08,0xf1,0x00,' +` 0xb7,0x06,0x51,0x01,0x72,0x05,0x62,0x01,' +` 0x5e,0x04,0x49,0x01,0x6d,0x03,0x1a,0x01,' +` 0x9b,0x02,0xe2,0x00,0xe8,0x01,0xa8,0x00,' +` 0x52,0x01,0x73,0x00,0xd8,0x00,0x1a,0x00,' +` 0x50,0x00,0x08,0x00,0x25,0x00,0x02,0x00,' +` 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x8a,0xff,0x34,0xff,' +` 0x20,0xff,0x8f,0xfe,0x83,0xfe,0xc8,0xfd,' +` 0xea,0xfd,0xef,0xfc,0x4e,0xfd,0x07,0xfc,' +` 0xbd,0xfc,0x1a,0xfb,0x46,0xfc,0x30,0xfa,' +` 0xf7,0xfb,0x4b,0xf9,0xe4,0xfb,0x69,0xf8,' +` 0x24,0xfc,0x74,0xf7,0xe3,0xfc,0x2d,0xf6,' +` 0x9b,0xfe,0xaa,0xf3,0x75,0x03,0xb3,0xe8,' +` 0x71,0x74,0x85,0x13,0xbd,0xef,0x6c,0x02,' +` 0x52,0xf6,0xef,0xff,0xec,0xf8,0x43,0xff,' +` 0x99,0xfa,0x2a,0xff,0xe3,0xfb,0x4c,0xff,' +` 0xf0,0xfc,0x84,0xff,0xce,0xfd,0xbe,0xff,' +` 0x82,0xfe,0xef,0xff,0x0e,0xff,0x13,0x00,' +` 0x76,0xff,0x27,0x00,0xbc,0xff,0x2c,0x00,' +` 0xf6,0xff,0x32,0x00,0x04,0x00,0x1e,0x00,' +` 0x06,0x00,0x0d,0x00,0x02,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,' +` 0x07,0x00,0x12,0x00,0x0d,0x00,0x21,0x00,' +` 0x0d,0x00,0x2c,0x00,0xf0,0xff,0x11,0x00,' +` 0xc3,0xff,0xf9,0xff,0x7f,0xff,0xcd,0xff,' +` 0x1c,0xff,0x8b,0xff,0x99,0xfe,0x38,0xff,' +` 0xf6,0xfd,0xd6,0xfe,0x32,0xfd,0x70,0xfe,' +` 0x4d,0xfc,0x15,0xfe,0x40,0xfb,0xe3,0xfd,' +` 0xef,0xf9,0x25,0xfe,0xe4,0xf7,0x1c,0x00,' +` 0xe6,0xf0,0xef,0x78,0xef,0x05,0xa5,0xf4,' +` 0x97,0xfd,0x5a,0xf7,0xf0,0xfb,0x4d,0xf8,' +` 0x53,0xfb,0xf4,0xf8,0x2c,0xfb,0x97,0xf9,' +` 0x51,0xfb,0x48,0xfa,0xac,0xfb,0x0b,0xfb,' +` 0x2e,0xfc,0xda,0xfb,0xcb,0xfc,0xaf,0xfc,' +` 0x75,0xfd,0x7f,0xfd,0x1f,0xfe,0x40,0xfe,' +` 0xc0,0xfe,0xf8,0xfe,0x50,0xff,0x77,0xff,' +` 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x03,0x00,0x06,0x00,0x0a,0x00,' +` 0x10,0x00,0x17,0x00,0x20,0x00,0x47,0x00,' +` 0x62,0x00,0x76,0x00,0x90,0x00,0xa9,0x00,' +` 0xc7,0x00,0xe4,0x00,0x05,0x01,0x26,0x01,' +` 0x49,0x01,0x6b,0x01,0x8f,0x01,0xb2,0x01,' +` 0xd5,0x01,0xf6,0x01,0x18,0x02,0x36,0x02,' +` 0x53,0x02,0x6d,0x02,0x85,0x02,0x99,0x02,' +` 0xab,0x02,0xb7,0x02,0xb7,0x42,0xc6,0x02,' +` 0xc7,0x02,0xc2,0x02,0xba,0x02,0xad,0x02,' +` 0x9d,0x02,0x88,0x02,0x70,0x02,0x55,0x02,' +` 0x37,0x02,0x16,0x02,0xf4,0x01,0xcf,0x01,' +` 0xaa,0x01,0x83,0x01,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00,' +` 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,' +` 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,' +` 0x08,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,' +` 0x10,0x00,0x00,0x00,0x00,0x00,0xdf,0x01,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xff,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xfe,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb/coef_line4_pass.m4 b/tools/topology/topology1/m4/tdfb/coef_line4_pass.m4 new file mode 100644 index 000000000000..67849cf757d1 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb/coef_line4_pass.m4 @@ -0,0 +1,14 @@ +# Exported EQ 28-Jan-2022 +CONTROLBYTES_PRIV(DEF_TDFB_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x00,0x00,0x00,0x40,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x34,0x00,0x00,0x00,0x04,0x00,0x04,0x00,' +` 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,' +` 0x02,0x00,0x03,0x00,0x01,0x00,0x02,0x00,' +` 0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00"' +) diff --git a/tools/topology/topology1/m4/tdfb_controls.m4 b/tools/topology/topology1/m4/tdfb_controls.m4 new file mode 100644 index 000000000000..09bc559ad97d --- /dev/null +++ b/tools/topology/topology1/m4/tdfb_controls.m4 @@ -0,0 +1,53 @@ +# TDFB Bytes control with max value of 255 +C_CONTROLBYTES(DEF_TDFB_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 8192), + , + DEF_TDFB_PRIV) + +# TDFB switch control with max value of 1 +define(`CONTROL_NAME', `DEF_TDFB_BEAM') +C_CONTROLMIXER(TDFB Process, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +define(`CONTROL_NAME', `DEF_TDFB_DIRECTION') +C_CONTROLMIXER(TDFB Direction, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# TDFB enum list +CONTROLENUM_LIST(DEF_TDFB_AZIMUTH_VALUES, + LIST(` ', `"-90"', `"-75"', `"-60"', `"-45"', `"-30"', `"-15"', `"0"', `"15"', `"30"', `"45"', `"60"', `"75"', `"90"')) + +# TDFB enum control +C_CONTROLENUM(DEF_TDFB_AZIMUTH, PIPELINE_ID, + DEF_TDFB_AZIMUTH_VALUES, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + CONTROLENUM_OPS(enum, + 257 binds the mixer control to enum get/put handlers, + 257, 257)) + +C_CONTROLENUM(DEF_TDFB_AZIMUTH_ESTIMATE, PIPELINE_ID, + DEF_TDFB_AZIMUTH_VALUES, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + CONTROLENUM_OPS(enum, + 257 binds the mixer control to enum get/put handlers, + 257, 257)) diff --git a/tools/topology/topology1/m4/tdfb_controls_360.m4 b/tools/topology/topology1/m4/tdfb_controls_360.m4 new file mode 100644 index 000000000000..14456aa8b50e --- /dev/null +++ b/tools/topology/topology1/m4/tdfb_controls_360.m4 @@ -0,0 +1,53 @@ +# TDFB Bytes control with max value of 255 +C_CONTROLBYTES(DEF_TDFB_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 8192), + , + DEF_TDFB_PRIV) + +# TDFB switch control with max value of 1 +define(`CONTROL_NAME', `DEF_TDFB_BEAM') +C_CONTROLMIXER(TDFB Process, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +define(`CONTROL_NAME', `DEF_TDFB_DIRECTION') +C_CONTROLMIXER(TDFB Direction, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# TDFB enum list +CONTROLENUM_LIST(DEF_TDFB_AZIMUTH_VALUES, + LIST(` ', `"0"', `"30"', `"60"', `"90"', `"120"', `"150"', `"180"', `"210"', `"240"', `"270"', `"300"', `"330"')) + +# TDFB enum control +C_CONTROLENUM(DEF_TDFB_AZIMUTH, PIPELINE_ID, + DEF_TDFB_AZIMUTH_VALUES, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + CONTROLENUM_OPS(enum, + 257 binds the mixer control to enum get/put handlers, + 257, 257)) + +C_CONTROLENUM(DEF_TDFB_AZIMUTH_ESTIMATE, PIPELINE_ID, + DEF_TDFB_AZIMUTH_VALUES, + LIST(` ', ENUM_CHANNEL(FC, 3, 0)), + CONTROLENUM_OPS(enum, + 257 binds the mixer control to enum get/put handlers, + 257, 257)) diff --git a/tools/topology/topology1/m4/tdfb_defines.m4 b/tools/topology/topology1/m4/tdfb_defines.m4 new file mode 100644 index 000000000000..dfd39f5ff463 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb_defines.m4 @@ -0,0 +1,7 @@ +define(DEF_TDFB_PRIV, concat(`tdfb_priv_', PIPELINE_ID)) +define(DEF_TDFB_BYTES, concat(`tdfb_bytes_', PIPELINE_ID)) +define(DEF_TDFB_BEAM, concat(`tdfb_beam_', PIPELINE_ID)) +define(DEF_TDFB_DIRECTION, concat(`tdfb_track_', PIPELINE_ID)) +define(DEF_TDFB_AZIMUTH, concat(`tdfb_az_set_', PIPELINE_ID)) +define(DEF_TDFB_AZIMUTH_ESTIMATE, concat(`tdfb_az_est_', PIPELINE_ID)) +define(DEF_TDFB_AZIMUTH_VALUES, concat(`tdfb_azimuth_values_', PIPELINE_ID)) diff --git a/tools/topology/topology1/m4/tdfb_undefines.m4 b/tools/topology/topology1/m4/tdfb_undefines.m4 new file mode 100644 index 000000000000..6f722f7bbda5 --- /dev/null +++ b/tools/topology/topology1/m4/tdfb_undefines.m4 @@ -0,0 +1,7 @@ +undefine(`DEF_TDFB_PRIV') +undefine(`DEF_TDFB_BYTES') +undefine(`DEF_TDFB_BEAM') +undefine(`DEF_TDFB_DIRECTION') +undefine(`DEF_TDFB_AZIMUTH') +undefine(`DEF_TDFB_AZIMUTH_ESTIMATE') +undefine(`DEF_TDFB_AZIMUTH_VALUES') diff --git a/tools/topology/topology1/m4/tone.m4 b/tools/topology/topology1/m4/tone.m4 new file mode 100644 index 000000000000..53c1354c1765 --- /dev/null +++ b/tools/topology/topology1/m4/tone.m4 @@ -0,0 +1,62 @@ +divert(-1) + +dnl Define macro for siggen widget +DECLARE_SOF_RT_UUID("tone", tone_uuid, 0x04e3f894, 0x2c5c, 0x4f2e, + 0x8d, 0xc1, 0x69, 0x4e, 0xea, 0xab, 0x53, 0xfa) + +dnl N_TONE(name) +define(`N_TONE', `TONE'PIPELINE_ID`.'$1) + +dnl W_TONE(name, format, periods_sink, periods_source, core, kcontrols_list) +define(`W_TONE', +`SectionVendorTuples."'N_TONE($1)`_tuples_uuid" {' +` tokens "sof_comp_tokens"' +` tuples."uuid" {' +` SOF_TKN_COMP_UUID' STR(tone_uuid) +` }' +`}' +`SectionData."'N_TONE($1)`_data_uuid" {' +` tuples "'N_TONE($1)`_tuples_uuid"' +`}' +`SectionVendorTuples."'N_TONE($1)`_tuples_w" {' +` tokens "sof_comp_tokens"' +` tuples."word" {' +` SOF_TKN_COMP_PERIOD_SINK_COUNT' STR($3) +` SOF_TKN_COMP_PERIOD_SOURCE_COUNT' STR($4) +` SOF_TKN_COMP_CORE_ID' STR($5) +` }' +`}' +`SectionVendorTuples."'N_TONE($1)`_tone_tuples_w" {' +` tokens "sof_tone_tokens"' +` tuples."word" {' +` SOF_TKN_TONE_SAMPLE_RATE' ifdef(TONE_SAMPLE_RATE, STR(TONE_SAMPLE_RATE), "48000") +` }' +`}' +`SectionData."'N_TONE($1)`_data_w" {' +` tuples "'N_TONE($1)`_tuples_w"' +` tuples "'N_TONE($1)`_tone_tuples_w"' +`}' +`SectionVendorTuples."'N_TONE($1)`_tuples_str" {' +` tokens "sof_comp_tokens"' +` tuples."string" {' +` SOF_TKN_COMP_FORMAT' STR($2) +` }' +`}' +`SectionData."'N_TONE($1)`_data_str" {' +` tuples "'N_TONE($1)`_tuples_str"' +`}' +`SectionWidget."'N_TONE($1)`" {' +` index "'PIPELINE_ID`"' +` type "siggen"' +` no_pm "true"' +` data [' +` "'N_TONE($1)`_data_uuid"' +` "'N_TONE($1)`_data_w"' +` "'N_TONE($1)`_data_str"' +` ]' +` mixer [' + $6 +` ]' +`}') + +divert(0)dnl diff --git a/tools/topology/topology1/m4/utils.m4 b/tools/topology/topology1/m4/utils.m4 new file mode 100644 index 000000000000..7dd05ce659ec --- /dev/null +++ b/tools/topology/topology1/m4/utils.m4 @@ -0,0 +1,188 @@ +divert(-1) + +include(`debug.m4') + +define(`concat',`$1$2') + +define(`STR', `"'$1`"') + +dnl Argument iterator. +define(`argn', `ifelse(`$1', 1, ``$2'', + `argn(decr(`$1'), shift(shift($@)))')') + +define(`fatal_error', `errprint(`m4: '__file__: __line__`: fatal error: $* +')m4exit(1)') + +dnl Defines a list of items from a variable number of params. +dnl Use as last argument in a macro. +dnl The first argument specifies the number of tabs to be added for formatting +define(`LIST_LOOP', `argn(j,$@) +$1ifelse(i,`2', `', `define(`i', decr(i))define(`j', incr(j))$0($@)')') + +define(`LIST_LOOP_NONEWLINE', `argn(j,$@)$1ifelse(i,`2', `', `define(`i', decr(i))define(`j', incr(j))$0($@)')') + +define(`LIST', `pushdef(`i', $#)pushdef(`j', `2')LIST_LOOP($@)popdef(i)popdef(j)') + +define(`LIST_NONEWLINE', `pushdef(`i', $#)pushdef(`j', `2')LIST_LOOP_NONEWLINE($@)popdef(i)popdef(j)') + +dnl Sums a list of variable arguments. Use as last argument in macro. +define(`SUM_LOOP', `eval(argn(j,$@) + ifelse(i,`1', `', `define(`i', decr(i)) define(`j', incr(j)) + $0($@)'))') + +dnl Memory capabilities +define(`MEMCAPS', `pushdef(`i', $#) pushdef(`j', `1') SUM_LOOP($@)') + +dnl create direct DAPM/pipeline link between 2 widgets) +define(`dapm', `"$1, , $2"'`DEBUG_GRAPH($1, $2)') + +dnl COMP_SAMPLE_SIZE(FMT) +define(`COMP_SAMPLE_SIZE', +`ifelse( + $1, `s16le', `2', + $1, `s24le', `4', + $1, `s32le', `4', + $1, `float', `4', + `4')') + +dnl COMP_FORMAT_NAME(FMT) +define(`COMP_FORMAT_NAME', +`ifelse( + $1, `s16le', `S16_LE', + $1, `s24le', `S24_LE', + $1, `s32le', `S32_LE', + $1, `float', `FLOAT_LE', + )') + +dnl COMP_FORMAT_VALUE(FMT) +define(`COMP_FORMAT_VALUE', +`ifelse( + $1, `s16le', `0x00', + $1, `s24le', `0x01', + $1, `s32le', `0x02', + )') + +dnl CAPABILITY_FORMAT_NAME(BUF_FMT) +define(`CAPABILITY_FORMAT_NAME', +`ifelse( + $1, `s16le', `S16_LE', + $1, `s24le', ``S24_LE,S16_LE'', + $1, `s32le', ``S32_LE,S24_LE,S16_LE'', + $1, `float', `FLOAT_LE', + )') + +# note: only support number < 256 at the moment +dnl DEC2HEX(dec_num) +define(`DEC2HEX', +`ifelse( + eval(`$1 < 16'), `1', concat(`0x0',eval($1, 16)), + eval(`$1 < 256'), `1', concat(`0x',eval($1, 16)), + )') + +dnl P_GRAPH(NAME, PIPELINE_ID, CONNECTIONS) +define(`P_GRAPH', +`SectionGraph.STR($1 $2) {' +` index STR($2)' +`' +` lines [' +` $3' +` ]' +`}') + +dnl W_VENDORTUPLES(name, tokens, RATE_OUT) +define(`W_VENDORTUPLES', +`SectionVendorTuples.STR($1) {' +` tokens STR($2)' +`' +` tuples."word" {' +` $3' +` }' +`}') + +dnl W_DATA(name, tuples) +define(`W_DATA', +`SectionData.STR($1) {' +` tuples STR($2)' +`}') + +dnl VIRTUAL_DAPM_ROUTE_OUT(name, dai type, dai index, direction, index) +dnl No routes needed. Macro retained for simplicity +define(`VIRTUAL_DAPM_ROUTE_OUT', +`SectionWidget.STR($1) {' +` index STR($5)' +` type "output"' +` no_pm "true"' +`}') + +dnl VIRTUAL_DAPM_ROUTE_IN(name, dai type, dai index, direction, index) +dnl No routes needed. Macro retained for simplicity +define(`VIRTUAL_DAPM_ROUTE_IN', +`SectionWidget.STR($1) {' +` index STR($5)' +` type "input"' +` no_pm "true"' +`}') + +dnl VIRTUAL_WIDGET(name, type, index) +define(`VIRTUAL_WIDGET', +`ifelse(`$#', `3', +`SectionWidget.STR($1) {' +` index STR($3)' +` type STR($2)' +` no_pm "true"' +`}', `fatal_error(`Invalid parameters ($#) to VIRTUAL_WIDGET')')') + +dnl create SOF_ABI_VERSION if not defined +dnl you can give the abi.h with -DSOF_ABI_FILE=(full path to abi.h) +dnl otherwise this will be empty macro +ifdef(`SOF_ABI_VERSION', `', +ifdef(`SOF_ABI_FILE', +`define(`SOF_MAJOR',' +`esyscmd(`grep "#define SOF_ABI_MAJOR "' SOF_ABI_FILE `| grep -E ".[[:digit:]]$" -o'))dnl' +`define(`SOF_MINOR',' +`esyscmd(`grep "#define SOF_ABI_MINOR "' SOF_ABI_FILE `| grep -E ".[[:digit:]]$" -o'))dnl' +`define(`SOF_PATCH',' +`esyscmd(`grep "#define SOF_ABI_PATCH "' SOF_ABI_FILE `| grep -E ".[[:digit:]]$" -o'))dnl' +`define(`SOF_MAJOR_SHIFT',' +`esyscmd(`grep "#define SOF_ABI_MAJOR_SHIFT"' SOF_ABI_FILE `| grep -E ".[[:digit:]]$" -o'))dnl' +`define(`SOF_MINOR_SHIFT',' +`esyscmd(`grep "#define SOF_ABI_MINOR_SHIFT"' SOF_ABI_FILE `| grep -E ".[[:digit:]]$" -o'))dnl' +`define(`SOF_ABI_VERSION',' +`eval(eval((SOF_MAJOR) << (SOF_MAJOR_SHIFT))dnl' +`| eval((SOF_MINOR) << (SOF_MINOR_SHIFT))))dnl' + `')) + +dnl print number's 4 bytes from right to left as hex values +define(`PRINT_BYTES_4', +`format(`0x%02x', eval(($1)&0xFF)),'dnl +`format(`0x%02x', eval(($1>>8)&0xFF)),'dnl +`format(`0x%02x', eval(($1>>16)&0xFF)),'dnl +`format(`0x%02x', eval(($1>>24)&0xFF))')dnl + +dnl print number's 2 bytes from right to left as hex values +define(`PRINT_BYTES_2', +`format(`0x%02x', eval(($1)&0xFF)),'dnl +`format(`0x%02x', eval(($1>>8)&0xFF))')dnl + +dnl print a number's right most byte as hex values +define(`PRINT_BYTE', +`format(`0x%02x', eval(($1)&0xFF))')dnl + +dnl make a byte from 8 binary values, right to left in increasing argument order +define(`BITS_TO_BYTE', +`eval(eval($1 << 0) | eval($2 << 1) | eval($3 << 2) | eval($4 << 3)dnl +| eval($5 << 4) | eval($6 << 5) | eval($7 << 6) | eval($8 << 7))')dnl + +dnl macro for component UUID declare, support copying from the FW source directly. +dnl DECLARE_SOF_RT_UUID(name, macro, a, b, c, +dnl d0, d1, d2, d3, d4, d5, d6, d7) +define(`DECLARE_SOF_RT_UUID', +`define(`$2', + `format(`%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s:%2s', + substr($3, 8, 2), substr($3, 6, 2), substr($3, 4, 2), substr($3, 2, 2), + substr($4, 4, 2), substr($4, 2, 2), substr($5, 4, 2), substr($5, 2, 2), + substr($6, 2, 2), substr($7, 2, 2), substr($8, 2, 2), substr($9, 2, 2), + substr($10, 2, 2), substr($11, 2, 2), substr($12, 2, 2), substr($13, 2, 2) +)')') + +divert(0) dnl + diff --git a/tools/topology/topology1/platform/amd/acp.m4 b/tools/topology/topology1/platform/amd/acp.m4 new file mode 100644 index 000000000000..42ff58b78467 --- /dev/null +++ b/tools/topology/topology1/platform/amd/acp.m4 @@ -0,0 +1,36 @@ +# +# ACPX differentiation for pipelines and components +# + +include(`memory.m4') + +# PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) + +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_dmic_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) + +W_DATA(pipe_media_schedule_plat_dmic, pipe_media_schedule_plat_dmic_tokens) + + +# Tone Signal Generator Configuration +W_VENDORTUPLES(pipe_tone_schedule_plat_tokens, sof_sched_tokens, + LIST(` ', `SOF_TKN_SCHED_MIPS "200000"')) + +W_DATA(pipe_tone_schedule_plat, pipe_tone_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, + LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) + +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) diff --git a/tools/topology/topology1/platform/common/acp-dmic.m4 b/tools/topology/topology1/platform/common/acp-dmic.m4 new file mode 100644 index 000000000000..542c79b782f0 --- /dev/null +++ b/tools/topology/topology1/platform/common/acp-dmic.m4 @@ -0,0 +1,24 @@ +divert(-1) + +dnl ACPDMIC related macros + +define(`ACPDMIC_CONFIG', +`}' +$1 +) +dnl ACPDMIC_CONFIG_DATA(type, idx, rate, channel) +define(`ACPDMIC_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_acpdmic_tokens"' +` tuples."word" {' +` SOF_TKN_AMD_ACPDMIC_RATE' STR($3) +` SOF_TKN_AMD_ACPDMIC_CH' STR($4) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl + diff --git a/tools/topology/topology1/platform/common/acp-hs.m4 b/tools/topology/topology1/platform/common/acp-hs.m4 new file mode 100644 index 000000000000..2dc74df3eabc --- /dev/null +++ b/tools/topology/topology1/platform/common/acp-hs.m4 @@ -0,0 +1,73 @@ +divert(-1) + +dnl ACPHS related macros + +dnl ACP_CLOCK(clock, freq, codec_provider, polarity) +dnl polarity is optional +define(`ACP_CLOCK', + $1 STR($3) + $1_freq STR($2)) + `ifelse($4, `inverted', `$1_invert "true"',`')') + +dnl ACP_TDM(slots, width, tx_mask, rx_mask) +define(`ACP_TDM', +` tdm_slots 'STR($1) +` tdm_slot_width 'STR($2) +` tx_slots 'STR($3) +` rx_slots 'STR($4) +) + +dnl ACP_CONFIG(format, mclk, bclk, fsync, tdm, hs_config_data) +define(`ACPHS_CONFIG', +` format "'$1`"' +` '$2 +` '$3 +` '$4 +` '$5 +`}' +$6 +) + +dnl ACPHS_VIRTUAL_CONFIG(format, mclk, bclk, fsync, tdm, hs_config_data) +define(`ACPHS_VIRTUAL_CONFIG', +` format "'$1`"' +` '$2 +` '$3 +` '$4 +` '$5 +`}' +$6 +) +dnl ACPHS_CONFIG_DATA(type, idx, rate, channel, i2s_tdm_mode) +#i2s_tdm_mode 1-> tdm mode, 0->i2s mode +define(`ACPHS_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_acp_tokens"' +` tuples."word" {' +` SOF_TKN_AMD_ACP_RATE' STR($3) +` SOF_TKN_AMD_ACP_CH' STR($4) +` SOF_TKN_AMD_ACP_I2S_TDM_MODE' STR($5) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +dnl ACPHS_VIRTUAL_CONFIG_DATA(type, idx, rate, channel, i2s_tdm_mode) +#i2s_tdm_mode 1-> tdm mode, 0->i2s mode +define(`ACPHS_VIRTUAL_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_acp_tokens"' +` tuples."word" {' +` SOF_TKN_AMD_ACP_RATE' STR($3) +` SOF_TKN_AMD_ACP_CH' STR($4) +` SOF_TKN_AMD_ACP_I2S_TDM_MODE' STR($5) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/topology1/platform/common/acp-sdw.m4 b/tools/topology/topology1/platform/common/acp-sdw.m4 new file mode 100644 index 000000000000..9fff69e40750 --- /dev/null +++ b/tools/topology/topology1/platform/common/acp-sdw.m4 @@ -0,0 +1,24 @@ +divert(-1) + +dnl ACP_SDW related macros + +dnl ACP_CONFIG(format, mclk, bclk, fsync, tdm, sdw_config_data) +define(`ACP_SDW_CONFIG', +`}' +$1 +) +dnl ACP_SDW_CONFIG_DATA(type, idx, rate, channel) +define(`ACP_SDW_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_acp_sdw_tokens"' +` tuples."word" {' +` SOF_TKN_AMD_ACP_SDW_SAMPLERATE' STR($3) +` SOF_TKN_AMD_ACP_SDW_CH' STR($4) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/topology1/platform/common/acp-sp.m4 b/tools/topology/topology1/platform/common/acp-sp.m4 new file mode 100644 index 000000000000..e76ec1432c7d --- /dev/null +++ b/tools/topology/topology1/platform/common/acp-sp.m4 @@ -0,0 +1,74 @@ +divert(-1) + +dnl ACPSP related macros + +dnl ACP_CLOCK(clock, freq, codec_provider, polarity) +dnl polarity is optional +define(`ACP_CLOCK', + $1 STR($3) + $1_freq STR($2)) + `ifelse($4, `inverted', `$1_invert "true"',`')') + +dnl ACP_TDM(slots, width, tx_mask, rx_mask) +define(`ACP_TDM', +` tdm_slots 'STR($1) +` tdm_slot_width 'STR($2) +` tx_slots 'STR($3) +` rx_slots 'STR($4) +) + +dnl ACP_CONFIG(format, mclk, bclk, fsync, tdm, esai_config_data) +define(`ACPSP_CONFIG', +` format "'$1`"' +` '$2 +` '$3 +` '$4 +` '$5 +`}' +$6 +) + +dnl ACPSP_VIRTUAL_CONFIG(format, mclk, bclk, fsync, tdm, esai_config_data) +define(`ACPSP_VIRTUAL_CONFIG', +` format "'$1`"' +` '$2 +` '$3 +` '$4 +` '$5 +`}' +$6 +) + +dnl ACPSP_CONFIG_DATA(type, idx, rate, channel,i2s_tdm_mode) +#i2s_tdm_mode 1-> tdm mode, 0->i2s mode +define(`ACPSP_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_acp_tokens"' +` tuples."word" {' +` SOF_TKN_AMD_ACP_RATE' STR($3) +` SOF_TKN_AMD_ACP_CH' STR($4) +` SOF_TKN_AMD_ACP_I2S_TDM_MODE' STR($5) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +dnl ACPSP_VIRTUAL_CONFIG_DATA(type, idx, rate, channel,i2s_tdm_mode) +#i2s_tdm_mode 1-> tdm mode, 0->i2s mode +define(`ACPSP_VIRTUAL_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_acp_tokens"' +` tuples."word" {' +` SOF_TKN_AMD_ACP_RATE' STR($3) +` SOF_TKN_AMD_ACP_CH' STR($4) +` SOF_TKN_AMD_ACP_I2S_TDM_MODE' STR($5) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) +divert(0)dnl + diff --git a/tools/topology/topology1/platform/common/afe.m4 b/tools/topology/topology1/platform/common/afe.m4 new file mode 100644 index 000000000000..47a790361ff4 --- /dev/null +++ b/tools/topology/topology1/platform/common/afe.m4 @@ -0,0 +1,28 @@ +divert(-1) + +dnl AFE related macros + +dnl AFE_CONFIG(afe_config_data) +define(`AFE_CONFIG', +`}' +$1 +) + +dnl AFE_CONFIG_DATA(type, idx, rate, channels, format) +define(`AFE_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_afe_tokens"' +` tuples."word" {' +` SOF_TKN_MEDIATEK_AFE_RATE' STR($3) +` SOF_TKN_MEDIATEK_AFE_CH' STR($4) +` }' +` tuples."string" {' +` SOF_TKN_MEDIATEK_AFE_FORMAT' STR($5) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/topology1/platform/common/alh.m4 b/tools/topology/topology1/platform/common/alh.m4 new file mode 100644 index 000000000000..2876775f6cf6 --- /dev/null +++ b/tools/topology/topology1/platform/common/alh.m4 @@ -0,0 +1,25 @@ +divert(-1) + +dnl ALH related macros + +dnl ALH_CONFIG(alh_config_data) +define(`ALH_CONFIG', +`}' +$1 +) + +dnl ALH_CONFIG_DATA(type, idx, rate, channels) +define(`ALH_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_alh_tokens"' +` tuples."word" {' +` SOF_TKN_INTEL_ALH_RATE' STR($3) +` SOF_TKN_INTEL_ALH_CH' STR($4) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/platform/common/esai.m4 b/tools/topology/topology1/platform/common/esai.m4 similarity index 93% rename from tools/topology/platform/common/esai.m4 rename to tools/topology/topology1/platform/common/esai.m4 index 9dd1b4c845cd..7b44caf5d8fb 100644 --- a/tools/topology/platform/common/esai.m4 +++ b/tools/topology/topology1/platform/common/esai.m4 @@ -2,7 +2,7 @@ divert(-1) dnl ESAI related macros -dnl ESAI_CLOCK(clock, freq, codec_master, polarity) +dnl ESAI_CLOCK(clock, freq, codec_provider, polarity) dnl polarity is optional define(`ESAI_CLOCK', $1 STR($3) diff --git a/tools/topology/topology1/platform/common/hda.m4 b/tools/topology/topology1/platform/common/hda.m4 new file mode 100644 index 000000000000..cfdd30b990af --- /dev/null +++ b/tools/topology/topology1/platform/common/hda.m4 @@ -0,0 +1,25 @@ +divert(-1) + +dnl HDA related macros + +dnl HDA_CONFIG(hda_config_data) +define(`HDA_CONFIG', +`}' +$1 +) + +dnl HDA_CONFIG_DATA(type, idx, rate, channels) +define(`HDA_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_hda_tokens"' +` tuples."word" {' +` SOF_TKN_INTEL_HDA_RATE' STR($3) +` SOF_TKN_INTEL_HDA_CH' STR($4) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/topology1/platform/common/micfil.m4 b/tools/topology/topology1/platform/common/micfil.m4 new file mode 100644 index 000000000000..0adad8446afb --- /dev/null +++ b/tools/topology/topology1/platform/common/micfil.m4 @@ -0,0 +1,24 @@ +divert(-1) + +dnl MICFIL related macros + +define(`MICFIL_CONFIG', +`}' +$1 +) +dnl MICFIL_CONFIG_DATA(type, idx, rate, channel) +define(`MICFIL_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_micfil_tokens"' +` tuples."word" {' +` SOF_TKN_IMX_MICFIL_RATE' STR($3) +` SOF_TKN_IMX_MICFIL_CH' STR($4) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl + diff --git a/tools/topology/platform/common/sai.m4 b/tools/topology/topology1/platform/common/sai.m4 similarity index 91% rename from tools/topology/platform/common/sai.m4 rename to tools/topology/topology1/platform/common/sai.m4 index 9697aa374bd6..888308c714d4 100644 --- a/tools/topology/platform/common/sai.m4 +++ b/tools/topology/topology1/platform/common/sai.m4 @@ -2,11 +2,11 @@ divert(-1) dnl SAI related macros -dnl SAI_CLOCK(clock, freq, codec_master, polarity) +dnl SAI_CLOCK(clock, freq, codec_provider, polarity) dnl polarity is optional define(`SAI_CLOCK', $1 STR($3) - $1_freq STR($2)) + $1_freq STR($2) `ifelse($4, `inverted', `$1_invert "true"',`')') dnl SAI_TDM(slots, width, tx_mask, rx_mask) diff --git a/tools/topology/topology1/platform/common/ssp.m4 b/tools/topology/topology1/platform/common/ssp.m4 new file mode 100644 index 000000000000..d3f5b19afad3 --- /dev/null +++ b/tools/topology/topology1/platform/common/ssp.m4 @@ -0,0 +1,101 @@ +divert(-1) + +dnl SSP related macros + +dnl SSP_CLOCK(clock, freq, codec_provider, polarity) +dnl polarity is optional +define(`SSP_CLOCK', + $1 STR($3) + $1_freq STR($2) + `ifelse($4, `inverted', `$1_invert "true"',`')') + +dnl SSP_TDM(slots, width, tx_mask, rx_mask) +define(`SSP_TDM', +`tdm_slots 'STR($1) +` tdm_slot_width 'STR($2) +` tx_slots 'STR($3) +` rx_slots 'STR($4) +) +dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) +define(`SSP_CONFIG', +` format "'$1`"' +` '$2 +` '$3 +` '$4 +` '$5 +`}' +$6 +) + +dnl SSP_QUIRK_LBM 64 = (1 << 6) +define(`SSP_QUIRK_LBM', 64) + +dnl SSP_CC_MCLK_ES 64 = (1 << 6) +define(`SSP_CC_MCLK_ES', 64) +dnl SSP_CC_BCLK_ES 128 = (1 << 7) +define(`SSP_CC_BCLK_ES', 128) +dnl SSP_CC_BCLK_ES 256 = (1 << 8) +define(`SSP_CC_MCLK_AON', 256) + +dnl SSP_CONFIG_DATA(type, idx, valid bits, mclk_id, quirks, bclk_delay, +dnl clks_control, pulse_width, padding) +dnl mclk_id, quirks, bclk_delay clks_control, pulse_width and padding are optional +define(`SSP_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_ssp_tokens"' +` tuples."word" {' +` SOF_TKN_INTEL_SSP_SAMPLE_BITS' STR($3) +` SOF_TKN_INTEL_SSP_QUIRKS' `ifelse(`$5', `', "0", STR($5))' +` SOF_TKN_INTEL_SSP_BCLK_DELAY' `ifelse(`$6', `', "0", STR($6))' +` SOF_TKN_INTEL_SSP_CLKS_CONTROL' `ifelse(`$7', `', "0", STR($7))' +` }' +` tuples."short" {' +` SOF_TKN_INTEL_SSP_MCLK_ID' `ifelse(`$4', `', "0", STR($4))' +` SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH' `ifelse(`$8', `', "0", STR($8))' +` }' +` tuples."bool" {' +` SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT' `ifelse(`$9', `', "false", STR($9))' +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +define(`MULTI_SSP_CONFIG', +`SectionHWConfig."'$1`" {' +`' +` id "'$2`"' +`' +` format "'$3`"' +` '$4 +` '$5 +` '$6 +` '$7 +`}' +$8 +) + +define(`SSP_MULTI_CONFIG_DATA', +`SectionVendorTuples."'$1`_tuples" {' +` tokens "sof_ssp_tokens"' +` tuples."word" {' +` SOF_TKN_INTEL_SSP_SAMPLE_BITS' STR($2) +` SOF_TKN_INTEL_SSP_QUIRKS' `ifelse(`$4', `', "0", STR($4))' +` SOF_TKN_INTEL_SSP_BCLK_DELAY' `ifelse(`$5', `', "0", STR($5))' +` SOF_TKN_INTEL_SSP_CLKS_CONTROL' `ifelse(`$6', `', "0", STR($6))' +` }' +` tuples."short" {' +` SOF_TKN_INTEL_SSP_MCLK_ID' `ifelse(`$3', `', "0", STR($3))' +` SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH' `ifelse(`$7', `', "0", STR($7))' +` }' +` tuples."bool" {' +` SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT' `ifelse(`$8', `', "false", STR($8))' +` }' +`}' +`SectionData."'$1`" {' +` tuples "'$1`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/topology1/platform/imx/imx8.m4 b/tools/topology/topology1/platform/imx/imx8.m4 new file mode 100644 index 000000000000..d2444dfdc2f7 --- /dev/null +++ b/tools/topology/topology1/platform/imx/imx8.m4 @@ -0,0 +1,24 @@ +# +# i.MX8QXP differentiation for pipelines and components +# + +include(`memory.m4') + +dnl Memory capabilities for different buffer types on i.MX8 +define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + diff --git a/tools/topology/topology1/platform/mediatek/mt8186.m4 b/tools/topology/topology1/platform/mediatek/mt8186.m4 new file mode 100644 index 000000000000..6c1ee496e22f --- /dev/null +++ b/tools/topology/topology1/platform/mediatek/mt8186.m4 @@ -0,0 +1,23 @@ +# +# MT8186 differentiation for pipelines and components +# + +include(`memory.m4') + +define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + diff --git a/tools/topology/topology1/platform/mediatek/mt8188.m4 b/tools/topology/topology1/platform/mediatek/mt8188.m4 new file mode 100644 index 000000000000..01bf80f26df1 --- /dev/null +++ b/tools/topology/topology1/platform/mediatek/mt8188.m4 @@ -0,0 +1,23 @@ +# +# MT8188 differentiation for pipelines and components +# + +include(`memory.m4') + +define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + diff --git a/tools/topology/topology1/platform/mediatek/mt8195.m4 b/tools/topology/topology1/platform/mediatek/mt8195.m4 new file mode 100644 index 000000000000..dff17dc3d7e0 --- /dev/null +++ b/tools/topology/topology1/platform/mediatek/mt8195.m4 @@ -0,0 +1,23 @@ +# +# MT8195 differentiation for pipelines and components +# + +include(`memory.m4') + +define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + diff --git a/tools/topology/topology1/platform/mediatek/mt8196.m4 b/tools/topology/topology1/platform/mediatek/mt8196.m4 new file mode 100644 index 000000000000..74cdd252f024 --- /dev/null +++ b/tools/topology/topology1/platform/mediatek/mt8196.m4 @@ -0,0 +1,23 @@ +# +# MT8196 differentiation for pipelines and components +# + +include(`memory.m4') + +define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + diff --git a/tools/topology/topology1/platform/mediatek/mt8365.m4 b/tools/topology/topology1/platform/mediatek/mt8365.m4 new file mode 100644 index 000000000000..fa7eca700d68 --- /dev/null +++ b/tools/topology/topology1/platform/mediatek/mt8365.m4 @@ -0,0 +1,23 @@ +# +# MT8365 differentiation for pipelines and components +# + +include(`memory.m4') + +define(`PLATFORM_DAI_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_HOST_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_PASS_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_DMA, MEM_CAP_CACHE)) +define(`PLATFORM_COMP_MEM_CAP', MEMCAPS(MEM_CAP_RAM, MEM_CAP_CACHE)) + +# Low Latency PCM Configuration +W_VENDORTUPLES(pipe_ll_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "50000"')) +W_DATA(pipe_ll_schedule_plat, pipe_ll_schedule_plat_tokens) + +# Media PCM Configuration +W_VENDORTUPLES(pipe_media_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "100000"')) +W_DATA(pipe_media_schedule_plat, pipe_media_schedule_plat_tokens) + +# DAI schedule Configuration - scheduled by IRQ +W_VENDORTUPLES(pipe_dai_schedule_plat_tokens, sof_sched_tokens, LIST(` ', `SOF_TKN_SCHED_MIPS "5000"')) +W_DATA(pipe_dai_schedule_plat, pipe_dai_schedule_plat_tokens) + diff --git a/tools/topology/topology1/production/CMakeLists.txt b/tools/topology/topology1/production/CMakeLists.txt new file mode 100644 index 000000000000..ebc7892be086 --- /dev/null +++ b/tools/topology/topology1/production/CMakeLists.txt @@ -0,0 +1,4 @@ +# Empty source directory, exists only to create the corresponding +# 'production' subdirectory in the build directory and solve race +# https://github.com/thesofproject/sof/issues/5067 without actually +# moving all *.m4 sources one level down. diff --git a/tools/topology/topology1/sof-acp-renoir.m4 b/tools/topology/topology1/sof-acp-renoir.m4 new file mode 100644 index 000000000000..2debdfa0f8a4 --- /dev/null +++ b/tools/topology/topology1/sof-acp-renoir.m4 @@ -0,0 +1,65 @@ +# +# Topology for Renoir with I2S SP and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-sp.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 1, ACPSP, 0, acp-headset-codec, +PIPELINE_SOURCE_1, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPSP, 0, 0, acp-headset-codec, + ACPSP_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPSP_CONFIG_DATA(ACPSP, 0, 48000, 2, 0))) + +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 2, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 2, ACPSP, 0, acp-headset-codec, +PIPELINE_SINK_2, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# PCM id 0 +PCM_DUPLEX_ADD(I2SSP, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) + +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 1, 2, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, 3, ACPDMIC, 0, acp-dmic-codec, +PIPELINE_SINK_3, 2, s32le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 2))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) diff --git a/tools/topology/topology1/sof-acp-rmb-dmic4ch.m4 b/tools/topology/topology1/sof-acp-rmb-dmic4ch.m4 new file mode 100644 index 000000000000..4bf45dccbae4 --- /dev/null +++ b/tools/topology/topology1/sof-acp-rmb-dmic4ch.m4 @@ -0,0 +1,85 @@ +# +# Topology for Renoir with I2S SP and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-dmic.m4') +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 1, ACPHS, 0, acp-headset-codec, +PIPELINE_SOURCE_1, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 0, 0, acp-headset-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 0, 48000, 2, 0))) + +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 2, 1, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 2, ACPHS, 1, acp-amp-codec, +PIPELINE_SOURCE_2, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 1, 1, acp-amp-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 1, 48000, 2, 0))) + + +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 3, ACPHS, 0, acp-headset-codec, +PIPELINE_SINK_3, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# PCM id 0 +PCM_DUPLEX_ADD(I2SHS, 0, PIPELINE_PCM_1, PIPELINE_PCM_3) + +# PCM id 0 +PCM_PLAYBACK_ADD(I2SHS_VIRTUAL, 1, PIPELINE_PCM_2) +#/**********************************************************************************/ +#DMIC +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 2, 4, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, 4, ACPDMIC, 0, acp-dmic-codec, +PIPELINE_SINK_4, 2, s32le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 4))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 2, PIPELINE_PCM_4) +#/**********************************************************************************/ diff --git a/tools/topology/topology1/sof-acp-rmb-tdm8ch-dmic2ch-nau8825-max98360.m4 b/tools/topology/topology1/sof-acp-rmb-tdm8ch-dmic2ch-nau8825-max98360.m4 new file mode 100644 index 000000000000..2c6b89e9c672 --- /dev/null +++ b/tools/topology/topology1/sof-acp-rmb-tdm8ch-dmic2ch-nau8825-max98360.m4 @@ -0,0 +1,197 @@ +# +# Topology for Rembrandt with I2S HS and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-dmic.m4') +include(`m4/debug.m4') +include(`muxdemux.m4') +include(`bytecontrol.m4') + +# Include TLV library +include(`common/tlv.m4') +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + + +DEBUG_START + +define(PIPE_NAME, pipe-acp-mux) + +VIRTUAL_WIDGET(ACPHS0 OUT, output, 0) +VIRTUAL_WIDGET(ACPHS0 IN, input, 1) +VIRTUAL_WIDGET(DMIC0 Capture, input, 2) +VIRTUAL_WIDGET(ACPHS1 OUT, output, 3) +# +# Define the pipelines +# +# +# |-------------->virtual_playback_passthrough --->ACPHS1 +# | +# PCM3 ----> buffer ------+ +# | +# |----> muxdemux ----> buffer ----> ACPHS +# PCM4 ----> buffer -----> +# +# PCM2 <---- muxdemux <---- buffer <---- ACPHS_Capture +# +# PCM5 <---- buffer <---- ACPDMIC + +#/**********************************************************************************/ +define(matrix1, `ROUTE_MATRIX(3, + `BITS_TO_BYTE(0, 0, 0 ,0 ,1 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,1 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,1 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,1)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)')') + +define(matrix2, `ROUTE_MATRIX(4, + `BITS_TO_BYTE(0, 0, 1 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,1 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(1, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 1, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)')') + +dnl name, num_streams, route_matrix list +MUXDEMUX_CONFIG(demux_priv_1, 2, LIST_NONEWLINE(`', `matrix1,', `matrix2')) + +# playback DAI is ACPHS using 2 periods +# Buffers use s16le format, 2000us 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-mux-dai-playback.m4, + 1, ACPHS, 0, acp-headset-codec, + NOT_USED_IGNORED, 2, s16le, + 2000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA, + 8, 48000) + +# PCM Playback pipeline 3 on PCM 0 using max 2 channels of s16le. +# 2000us deadline with priority 0 on core 0 +# this is connected to pipeline DAI 1 +PIPELINE_PCM_ADD(sof/pipe-host-playback.m4, + 3, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_DMA, + PIPELINE_PLAYBACK_SCHED_COMP_1) +#/**********************************************************************************/ +DAI_ADD(sof/pipe-virtual-playback-passthrough.m4, + 9, ACPHS, 1, acp-amp-codec, + PIPELINE_SOURCE_1, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 1, 1, acp-amp-codec, + ACPHS_CONFIG(DSP_A, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(8, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 1, 48000, 8, 1))) +#/**********************************************************************************/ +# PCM Playback pipeline 4 on PCM 1 using max 2 channels of s16le. +# 2000us deadline with priority 0 on core 0 +# this is connected to pipeline DAI 1 +PIPELINE_PCM_ADD(sof/pipe-virtual-passthrough-playback-sched.m4, + 4, 1, 2, s16le, + 2000, 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_MUX_1, PIPELINE_SOURCE_3) + # PCM pipeline 4 to DAI pipeline 1 + dapm(PIPELINE_MUX_1, PIPELINE_SOURCE_4) + ] +} + +PCM_PLAYBACK_ADD(Media Playback MUX 1, 1, PIPELINE_PCM_4) + + +# Connect playback to virtual dai +SectionGraph."PIPE_PLAYBACK_VIRT" { + index "1" + + lines [ + #playback to virtual dai + dapm(ACPHS1.OUT, VIRTUAL PLAYBACK PASSTHROUGH 4) + ] +} + +#/**********************************************************************************/ + +#/**********************************************************************************/ +define(matrix3, `ROUTE_MATRIX(2, + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,1 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,1)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)')') + +dnl name, num_streams, route_matrix list +MUXDEMUX_CONFIG(demux_priv_2, 1, LIST_NONEWLINE(`', `matrix3')) +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s16le. +# 2000us deadline with priority 0 on core 0 +#PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-low-latency-capture-demux.m4, + 2, 0, 8, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPHS using 2 periods +# Buffers use s16le format, 2000us deadline with priority 0 on core 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ACPHS, 0, acp-headset-codec, + PIPELINE_SINK_2, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_3, PIPELINE_PCM_2) + +# BE configurations - +DAI_CONFIG(ACPHS, 0, 0, acp-headset-codec, + ACPHS_CONFIG(DSP_A, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(8, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 0, 48000, 8, 1))) +#/**********************************************************************************/ + +#/**********************************************************************************/ +#DMIC + +# Capture pipeline 3-->5 on PCM 1-->6 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 5, 6, 2, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, 5, ACPDMIC, 0, acp-dmic-codec, +PIPELINE_SINK_5, 2, s32le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 5, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 5, 48000, 2))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_5) +#/**********************************************************************************/ + + +DEBUG_END diff --git a/tools/topology/topology1/sof-acp-rmb-tdm8ch-dmic4ch-rt5682-rt1019.m4 b/tools/topology/topology1/sof-acp-rmb-tdm8ch-dmic4ch-rt5682-rt1019.m4 new file mode 100644 index 000000000000..c4e484f6a0d2 --- /dev/null +++ b/tools/topology/topology1/sof-acp-rmb-tdm8ch-dmic4ch-rt5682-rt1019.m4 @@ -0,0 +1,198 @@ +# +# Topology for Rembrandt with I2S HS and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-dmic.m4') +include(`m4/debug.m4') +include(`muxdemux.m4') +include(`bytecontrol.m4') + +# Include TLV library +include(`common/tlv.m4') +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + + +DEBUG_START + +define(PIPE_NAME, pipe-acp-mux) + +VIRTUAL_WIDGET(ACPHS0 OUT, output, 0) +VIRTUAL_WIDGET(ACPHS0 IN, input, 1) +VIRTUAL_WIDGET(DMIC0 Capture, input, 2) +VIRTUAL_WIDGET(ACPHS1 OUT, output, 3) +# +# Define the pipelines +# +# +# |-------------->virtual_playback_passthrough --->ACPHS1 +# | +# PCM3 ----> buffer ------+ +# | +# |----> muxdemux ----> buffer ----> ACPHS +# PCM4 ----> buffer -----> +# +# PCM2 <---- muxdemux <---- buffer <---- ACPHS_Capture +# +# PCM5 <---- buffer <---- ACPDMIC + +#/**********************************************************************************/ +define(matrix1, `ROUTE_MATRIX(3, + `BITS_TO_BYTE(1, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 1, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,1 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,1 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,1 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,1)')') + +define(matrix2, `ROUTE_MATRIX(4, + `BITS_TO_BYTE(0, 0, 1 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,1 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)')') + +dnl name, num_streams, route_matrix list +MUXDEMUX_CONFIG(demux_priv_1, 2, LIST_NONEWLINE(`', `matrix1,', `matrix2')) + +# playback DAI is ACPHS using 2 periods +# Buffers use s16le format, 2000us 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-mux-dai-playback.m4, + 1, ACPHS, 0, acp-headset-codec, + NOT_USED_IGNORED, 2, s16le, + 2000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA, + 8, 48000) + +# PCM Playback pipeline 3 on PCM 0 using max 2 channels of s16le. +# 2000us deadline with priority 0 on core 0 +# this is connected to pipeline DAI 1 +PIPELINE_PCM_ADD(sof/pipe-host-playback.m4, + 3, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_DMA, + PIPELINE_PLAYBACK_SCHED_COMP_1) +#/**********************************************************************************/ +DAI_ADD(sof/pipe-virtual-playback-passthrough.m4, + 9, ACPHS, 1, acp-amp-codec, + PIPELINE_SOURCE_1, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 1, 1, acp-amp-codec, + ACPHS_CONFIG(DSP_A, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(8, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 1, 48000, 8, 1))) +#/**********************************************************************************/ + +# PCM Media Playback pipeline 4 on PCM 1 using max 2 channels of s16le. +# 2000us deadline with priority 0 on core 0 +# this is connected to pipeline DAI 1 +PIPELINE_PCM_ADD(sof/pipe-virtual-passthrough-playback-sched.m4, + 4, 1, 2, s16le, + 2000, 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_MUX_1, PIPELINE_SOURCE_3) + # PCM pipeline 4 to DAI pipeline 1 + dapm(PIPELINE_MUX_1, PIPELINE_SOURCE_4) + ] +} + +PCM_PLAYBACK_ADD(Media Playback MUX 1, 1, PIPELINE_PCM_4) + + +# Connect playback to virtual dai +SectionGraph."PIPE_PLAYBACK_VIRT" { + index "1" + + lines [ + #playback to virtual dai + dapm(ACPHS1.OUT, VIRTUAL PLAYBACK PASSTHROUGH 4) + ] +} + +#/**********************************************************************************/ + +#/**********************************************************************************/ +define(matrix3, `ROUTE_MATRIX(2, + `BITS_TO_BYTE(1, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 1, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,0)')') + +dnl name, num_streams, route_matrix list +MUXDEMUX_CONFIG(demux_priv_2, 1, LIST_NONEWLINE(`', `matrix3')) +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s16le. +# 2000us deadline with priority 0 on core 0 +#PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-low-latency-capture-demux.m4, + 2, 0, 8, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPHS using 2 periods +# Buffers use s16le format, 2000us deadline with priority 0 on core 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ACPHS, 0, acp-headset-codec, + PIPELINE_SINK_2, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +PCM_DUPLEX_ADD(Low Latency, 0, PIPELINE_PCM_3, PIPELINE_PCM_2) + +# BE configurations - +DAI_CONFIG(ACPHS, 0, 0, acp-headset-codec, + ACPHS_CONFIG(DSP_A, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(8, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 0, 48000, 8, 1))) +#/**********************************************************************************/ + +#/**********************************************************************************/ +#DMIC + +# Capture pipeline 3-->5 on PCM 1-->6 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 5, 6, 4, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, 5, ACPDMIC, 0, acp-dmic-codec, +PIPELINE_SINK_5, 2, s32le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 5, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 5, 48000, 4))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 6, PIPELINE_PCM_5) +#/**********************************************************************************/ + + +DEBUG_END diff --git a/tools/topology/topology1/sof-acp-rmb.m4 b/tools/topology/topology1/sof-acp-rmb.m4 new file mode 100644 index 000000000000..d5945f9ee778 --- /dev/null +++ b/tools/topology/topology1/sof-acp-rmb.m4 @@ -0,0 +1,84 @@ +# +# Topology for Renoir with I2S SP and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 1, ACPHS, 0, acp-headset-codec, +PIPELINE_SOURCE_1, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 0, 0, acp-headset-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 0, 48000, 2, 0))) + +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 2, 1, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 2, ACPHS, 1, acp-amp-codec, +PIPELINE_SOURCE_2, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 1, 1, acp-amp-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 1, 48000, 2, 0))) + + +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 3, ACPHS, 0, acp-headset-codec, +PIPELINE_SINK_3, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# PCM id 0 +PCM_DUPLEX_ADD(I2SHS, 0, PIPELINE_PCM_1, PIPELINE_PCM_3) + +# PCM id 0 +PCM_PLAYBACK_ADD(I2SHS_VIRTUAL, 1, PIPELINE_PCM_2) + +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 2, 2, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, 4, ACPDMIC, 0, acp-dmic-codec, +PIPELINE_SINK_4, 2, s32le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +#dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 2))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 2, PIPELINE_PCM_4) diff --git a/tools/topology/topology1/sof-acp-vangogh.m4 b/tools/topology/topology1/sof-acp-vangogh.m4 new file mode 100644 index 000000000000..4c313ec608c2 --- /dev/null +++ b/tools/topology/topology1/sof-acp-vangogh.m4 @@ -0,0 +1,68 @@ +# +# Topology for Vangogh with I2S SP and I2S HS. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-sp.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 1, ACPSP, 0, acp-headset-codec, +PIPELINE_SOURCE_1, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPSP, 0, 0, acp-headset-codec, + ACPSP_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPSP_CONFIG_DATA(ACPSP, 0, 48000, 2, 0))) + +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 2, 1, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 2, ACPHS, 1, acp-amp-codec, +PIPELINE_SOURCE_2, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPHS, 1, 1, acp-amp-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 1, 48000, 2, 0))) + + +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 3, ACPSP, 0, acp-headset-codec, +PIPELINE_SINK_3, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# PCM id 0 +PCM_DUPLEX_ADD(I2SSP, 0, PIPELINE_PCM_1, PIPELINE_PCM_3) + +# PCM id 1 +PCM_PLAYBACK_ADD(I2SHS, 1, PIPELINE_PCM_2) diff --git a/tools/topology/topology1/sof-acp_6_3.m4 b/tools/topology/topology1/sof-acp_6_3.m4 new file mode 100644 index 000000000000..1923d93acf8e --- /dev/null +++ b/tools/topology/topology1/sof-acp_6_3.m4 @@ -0,0 +1,98 @@ +# +# Topology for ACP_6_3 with I2SHS and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +DEBUG_START +#====================================================================== +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. + +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) + +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +# playback DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ACPHS, 0, acp-headset-codec, + PIPELINE_SOURCE_1, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acphs_config/acpdmic_config) +dnl ACPHS_CONFIG(format, mclk, bclk, fsync, tdm, acphs_config_data) +dnl ACP_CLOCK(clock, freq, codec_provider, polarity) +dnl ACPHS_CONFIG_DATA(type, idx, valid bits, mclk_id) +dnl mclk_id is optional + +DAI_CONFIG(ACPHS, 0, 0, acp-headset-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 0, 48000, 2, 0))) + +#=========================================================================== +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 2, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ACPHS, 0, acp-headset-codec, + PIPELINE_SINK_2, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +#=========================================================================== +# PCM id 0 +PCM_DUPLEX_ADD(I2SHS, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) + +#========================================================================== +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 2, 2, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, + 4, ACPDMIC, 0, acp-dmic-codec, + PIPELINE_SINK_4, 2, s32le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +#dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 2))) + +#========================================================================== +# PCM id 2 +PCM_CAPTURE_ADD(DMIC, 2, PIPELINE_PCM_4) + +#========================================================================== + +DEBUG_END diff --git a/tools/topology/topology1/sof-acp_6_3_sdw.m4 b/tools/topology/topology1/sof-acp_6_3_sdw.m4 new file mode 100644 index 000000000000..b8b6f4dc7b8e --- /dev/null +++ b/tools/topology/topology1/sof-acp_6_3_sdw.m4 @@ -0,0 +1,136 @@ +#Required Topology for RTK Monolithic Aggregated with ACP DMIC Card +# PCM Description DAI LINK DAI BE +# 0       HS Playback 0 SDW0-PIN0-Playback-SimpleJack       AUDIO_TX +# 1       HS Capture 1 SDW0-PIN3-Capture-SimpleJack    AUDIO_RX +# 2       Speaker playback 2 SDW0-PIN1-Playback-SmartAmp    BT_TX +# 4       SDW DMIC 4 SDW1-PIN1-Capture-SmartMic    P1_SW_BT RX +# +# Topology for Phoenix with soundwire and DMIC. +# + +# +# Define the pipelines +# +# PCM0 ----> buffer ----> AUDIO_TX +# PCM1 <---- buffer <---- AUDIO_RX +# PCM2 ----> buffer ----> BT_TX +# PCM4 <---- buffer <---- P1_SW_BT RX + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-sdw.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +#/**********************************************************************************/ +# PCM 0, HS Playback, DAI link id 0, Dai index 0(Audio_Tx), BE SW0-PIN0-PLAYBACK + +#Driver dai index and dai BE +#DAI Index(Instance * 64 + base_index) DAI_BE +#0(AUDIO_TX) SDW0-PIN0-PLAYBACK-SimpleJack +#1(BT_TX) SDW0-PIN1-PLAYBACK-SmartAmp +#2(HS_TX) SDW0-PIN2-PLAYBACK +#3(AUDIO_RX) SDW0-PIN3-CAPTURE-SimpleJack +#4(BT_RX) SDW0-PIN4-CAPTURE-SmartAmp +#5(HS_RX) SDW0-PIN5-CAPTURE +# +#65(P1_BT_TX) SDW1-PIN1-PLAYBACK +#68(P1_BT_RX) SDW1-PIN1-CAPTURE-SmartMic + +define(DI_SDW0_ACP_SW_Audio_TX, 0) +define(DI_SDW0_ACP_SW_BT_TX, 1) +define(DI_SDW0_ACP_SW_HS_TX, 2) +define(DI_SDW0_ACP_SW_Audio_RX, 3) +define(DI_SDW0_ACP_SW_BT_RX, 4) +define(DI_SDW0_ACP_SW_HS_RX, 5) +define(DI_SDW1_ACP_P1_SW_BT_RX, 68) +define(DI_SDW1_ACP_P1_SW_BT_TX, 65) + +define(DAI_BE_SDW0_ACP_SW_HS_RX, SDW0-PIN5-CAPTURE) +define(DAI_BE_SDW0_ACP_SW_HS_TX, SDW0-PIN2-PLAYBACK) +define(DAI_BE_SDW1_ACP_P1_SW_BT_RX, SDW1-PIN1-CAPTURE-SmartMic) +define(DAI_BE_SDW1_ACP_P1_SW_BT_TX, SDW1-PIN1-PLAYBACK) +define(DAI_BE_ACP_SW_Audio_RX, SDW0-PIN3-CAPTURE-SimpleJack) +define(DAI_BE_SDW0_ACP_SW_Audio_TX, SDW0-PIN0-PLAYBACK-SimpleJack) +define(DAI_BE_SDW0_ACP_SW_BT_RX, SDW0-PIN4-CAPTURE-SmartAmp) +define(DAI_BE_SDW0_ACP_SW_BT_TX, SDW0-PIN1-PLAYBACK-SmartAmp) + +#pipeline: name of the predefined pipeline +#pipe id: pipeline ID. This should be a unique ID identifying the pipeline +#pcm: PCM ID. This will be used to bind to the correct front end DAI link +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 0, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +#DAI_ADD(pipeline, pipe id, dai type, firmware dai_index, dai_be, buffer) +DAI_ADD(sof/pipe-dai-playback.m4, 0, ACP_SDW, DI_SDW0_ACP_SW_Audio_TX, DAI_BE_SDW0_ACP_SW_Audio_TX, +PIPELINE_SOURCE_0, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +#DAI_CONFIG(type, driver dai_index, link_id, Dai BE name, config) +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_Audio_TX, 0, DAI_BE_SDW0_ACP_SW_Audio_TX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_Audio_TX, 48000, 2))) +PCM_PLAYBACK_ADD(ACP-SW0-PIN0-Playback-HS, 0, PIPELINE_PCM_0) +#/**********************************************************************************/ + + +#/**********************************************************************************/ +#PCM 1, HS Capture, DAI link id 1, Dai index 3(Audio_RX), BE SW0-PIN0-CAPTURE +# Capture pipeline 1 on PCM 1 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 1, 1, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACP soundwire using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 1, ACP_SDW, DI_SDW0_ACP_SW_Audio_RX, DAI_BE_ACP_SW_Audio_RX, +PIPELINE_SINK_1, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_Audio_RX, 1, DAI_BE_ACP_SW_Audio_RX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_Audio_RX, 48000, 2))) +PCM_CAPTURE_ADD(ACP-SW0-PIN0-Capture-HS, 1, PIPELINE_PCM_1) +#/**********************************************************************************/ + +#/**********************************************************************************/ +#PCM 2, Speaker Playback, DAI link id 2, Dai index 1(BT_TX), BE SW0-PIN1-PLAYBACK +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 2, 2, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACP soundwire using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 2, ACP_SDW, DI_SDW0_ACP_SW_BT_TX, DAI_BE_SDW0_ACP_SW_BT_TX, +PIPELINE_SOURCE_2, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_BT_TX, 2, DAI_BE_SDW0_ACP_SW_BT_TX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_BT_TX, 48000, 2))) +PCM_PLAYBACK_ADD(ACP-SW0-PIN2-Playback-SPK, 2, PIPELINE_PCM_2) +#/**********************************************************************************/ + +#/**********************************************************************************/ +#PCM 4, SDW Capture, DAI link id 4, Dai index 68(P1_BT_RX), BE SW1-PIN1-CAPTURE +# Capture pipeline 1 on PCM 1 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 4, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACP soundwire using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 4, ACP_SDW, DI_SDW1_ACP_P1_SW_BT_RX, DAI_BE_SDW1_ACP_P1_SW_BT_RX, +PIPELINE_SINK_4, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACP_SDW, DI_SDW1_ACP_P1_SW_BT_RX, 4, DAI_BE_SDW1_ACP_P1_SW_BT_RX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW1_ACP_P1_SW_BT_RX, 48000, 2))) +PCM_CAPTURE_ADD(ACP-SW1-PIN1-CAPTURE-DMIC, 4, PIPELINE_PCM_4) +#/**********************************************************************************/ + diff --git a/tools/topology/topology1/sof-acp_7_0.m4 b/tools/topology/topology1/sof-acp_7_0.m4 new file mode 100644 index 000000000000..60f643adbd62 --- /dev/null +++ b/tools/topology/topology1/sof-acp_7_0.m4 @@ -0,0 +1,98 @@ +# +# Topology for ACP_7_0 with I2SHS and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-hs.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +DEBUG_START +#====================================================================== +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. + +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) + +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +# playback DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ACPHS, 0, acp-headset-codec, + PIPELINE_SOURCE_1, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acphs_config/acpdmic_config) +dnl ACPHS_CONFIG(format, mclk, bclk, fsync, tdm, acphs_config_data) +dnl ACP_CLOCK(clock, freq, codec_provider, polarity) +dnl ACPHS_CONFIG_DATA(type, idx, valid bits, mclk_id) +dnl mclk_id is optional + +DAI_CONFIG(ACPHS, 0, 0, acp-headset-codec, + ACPHS_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3),ACPHS_CONFIG_DATA(ACPHS, 0, 48000, 2, 0))) + +#=========================================================================== +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 2, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPHS using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ACPHS, 0, acp-headset-codec, + PIPELINE_SINK_2, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +#=========================================================================== +# PCM id 0 +PCM_DUPLEX_ADD(I2SHS, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) + +#========================================================================== +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 2, 2, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, + 4, ACPDMIC, 0, acp-dmic-codec, + PIPELINE_SINK_4, 2, s32le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +#dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 2))) + +#========================================================================== +# PCM id 2 +PCM_CAPTURE_ADD(DMIC, 2, PIPELINE_PCM_4) + +#========================================================================== + +DEBUG_END diff --git a/tools/topology/topology1/sof-acp_7_0_sdw.m4 b/tools/topology/topology1/sof-acp_7_0_sdw.m4 new file mode 100644 index 000000000000..ca03f0cd2749 --- /dev/null +++ b/tools/topology/topology1/sof-acp_7_0_sdw.m4 @@ -0,0 +1,150 @@ +#Required Topology for rt722 with ACP DMIC Card for ACP_7_0 +# +# PCM Description DAI LINK DAI BE +# 0       HS Playback 0 SDW0-PIN0-Playback-SimpleJack       AUDIO_TX +# 1       HS Capture 1 SDW0-PIN3-Capture-SimpleJack    AUDIO_RX +# 2       Speaker playback 2 SDW0-PIN1-Playback-SmartAmp    BT_TX +# 4       SDW DMIC 4 SDW0-PIN5-Capture-SmartMic    HS_RX + +# +# Define the pipelines +# +# PCM0 ----> buffer ----> AUDIO_TX +# PCM1 <---- buffer <---- AUDIO_RX +# PCM2 ----> buffer ----> BT_TX +# PCM4 <---- buffer <---- HS_RX + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-sdw.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +DEBUG_START + +#/**********************************************************************************/ +# PCM 0, HS Playback, DAI link id 0, Dai index 0(Audio_Tx), BE SW0-PIN0-PLAYBACK + +#Driver dai index and dai BE +#DAI Index(Instance * 64 + base_index) DAI_BE +#0(AUDIO_TX) SDW0-PIN0-PLAYBACK-SimpleJack +#1(BT_TX) SDW0-PIN1-PLAYBACK-SmartAmp +#2(HS_TX) SDW0-PIN2-PLAYBACK +#3(AUDIO_RX) SDW0-PIN3-CAPTURE-SimpleJack +#4(BT_RX) SDW0-PIN4-CAPTURE-SmartAmp +#5(HS_RX) SDW0-PIN5-CAPTURE + +define(DI_SDW0_ACP_SW_Audio_TX, 0) +define(DI_SDW0_ACP_SW_BT_TX, 1) +define(DI_SDW0_ACP_SW_HS_TX, 2) +define(DI_SDW0_ACP_SW_Audio_RX, 3) +define(DI_SDW0_ACP_SW_BT_RX, 4) +define(DI_SDW0_ACP_SW_HS_RX, 5) +define(DI_SDW1_ACP_P1_SW_BT_RX, 68) +define(DI_SDW1_ACP_P1_SW_BT_TX, 65) + +define(DAI_BE_SDW0_ACP_SW_HS_TX, SDW0-PIN2-PLAYBACK) +define(DAI_BE_SDW1_ACP_P1_SW_BT_RX, SDW1-PIN1-CAPTURE-SmartMic) +define(DAI_BE_SDW1_ACP_P1_SW_BT_TX, SDW1-PIN1-PLAYBACK) +define(DAI_BE_ACP_SW_Audio_RX, SDW0-PIN3-CAPTURE-SimpleJack) +define(DAI_BE_SDW0_ACP_SW_Audio_TX, SDW0-PIN0-PLAYBACK-SimpleJack) +define(DAI_BE_SDW0_ACP_SW_BT_RX, SDW0-PIN4-CAPTURE-SmartAmp) +define(DAI_BE_SDW0_ACP_SW_BT_TX, SDW0-PIN1-PLAYBACK-SmartAmp) +define(DAI_BE_SDW0_ACP_SW_HS_RX, SDW0-PIN5-CAPTURE-SmartMic) + +#pipeline: name of the predefined pipeline +#pipe id: pipeline ID. This should be a unique ID identifying the pipeline +#pcm: PCM ID. This will be used to bind to the correct front end DAI link + +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) +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 0, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) +DAI_ADD(sof/pipe-dai-playback.m4, 0, ACP_SDW, DI_SDW0_ACP_SW_Audio_TX, DAI_BE_SDW0_ACP_SW_Audio_TX, + PIPELINE_SOURCE_0, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acphs_config/acpdmic_config) +dnl ACPHS_CONFIG(format, mclk, bclk, fsync, tdm, acphs_config_data) +dnl ACP_CLOCK(clock, freq, codec_provider, polarity) +dnl ACPHS_CONFIG_DATA(type, idx, valid bits, mclk_id) +dnl mclk_id is optional +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_Audio_TX, 0, DAI_BE_SDW0_ACP_SW_Audio_TX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_Audio_TX, 48000, 2))) + +PCM_PLAYBACK_ADD(ACP-SW0-PIN0-Playback-HS, 0, PIPELINE_PCM_0) +#/**********************************************************************************/ + + +#/**********************************************************************************/ +#PCM 1, HS Capture, DAI link id 1, Dai index 3(Audio_RX), BE SW0-PIN0-CAPTURE +# Capture pipeline 1 on PCM 1 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 1, 1, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACP soundwire using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 1, ACP_SDW, DI_SDW0_ACP_SW_Audio_RX, DAI_BE_ACP_SW_Audio_RX, + PIPELINE_SINK_1, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_Audio_RX, 1, DAI_BE_ACP_SW_Audio_RX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_Audio_RX, 48000, 2))) + +PCM_CAPTURE_ADD(ACP-SW0-PIN0-Capture-HS, 1, PIPELINE_PCM_1) +#/**********************************************************************************/ + +#/**********************************************************************************/ +#PCM 2, Speaker Playback, DAI link id 2, Dai index 1(BT_TX), BE SW0-PIN1-PLAYBACK +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 2, 2, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACP soundwire using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, 2, ACP_SDW, DI_SDW0_ACP_SW_BT_TX, DAI_BE_SDW0_ACP_SW_BT_TX, + PIPELINE_SOURCE_2, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_BT_TX, 2, DAI_BE_SDW0_ACP_SW_BT_TX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_BT_TX, 48000, 2))) + +PCM_PLAYBACK_ADD(ACP-SW0-PIN2-Playback-SPK, 2, PIPELINE_PCM_2) +#/**********************************************************************************/ + +#/**********************************************************************************/ +#PCM 4, SDW Capture, DAI link id 4, Dai index 5(HS_RX), BE SDW0-PIN5-CAPTURE-SmartMic +# Capture pipeline 1 on PCM 1 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 4, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACP soundwire using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, 4, ACP_SDW, DI_SDW0_ACP_SW_HS_RX, DAI_BE_SDW0_ACP_SW_HS_RX, + PIPELINE_SINK_4, 2, s16le, 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACP_SDW, DI_SDW0_ACP_SW_HS_RX, 4, DAI_BE_SDW0_ACP_SW_HS_RX, + ACP_SDW_CONFIG(ACP_SDW_CONFIG_DATA(ACP_SDW, DI_SDW0_ACP_SW_HS_RX, 48000, 2))) + +PCM_CAPTURE_ADD(ACP-SW0-PIN5-CAPTURE-DMIC, 4, PIPELINE_PCM_4) +#/**********************************************************************************/ + +DEBUG_END diff --git a/tools/topology/topology1/sof-cavs-nocodec.m4 b/tools/topology/topology1/sof-cavs-nocodec.m4 new file mode 100644 index 000000000000..0b913fc68f82 --- /dev/null +++ b/tools/topology/topology1/sof-cavs-nocodec.m4 @@ -0,0 +1,330 @@ +# +# Topology for generic Cannonlake board with no codec and digital mic array. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`ssp.m4') +include(`pipeline.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include DSP configuration +include(`platform/intel/'PLATFORM`.m4') + +ifelse(PLATFORM, `tgl', `define(NCORES, 4)') +ifelse(PLATFORM, `ehl', `define(NCORES, 4)') +ifelse(PLATFORM, `adl', `define(NCORES, 4)') + +define(CHANNELS, `4') + +define(DMIC_PCM_48k_ID, `10') +define(DMIC_PCM_16k_ID, `11') + +define(DMIC_PIPELINE_48k_ID, `20') +define(DMIC_PIPELINE_16k_ID, `21') + +define(DMIC_DAI_LINK_48k_NAME, `NoCodec-3') +define(DMIC_DAI_LINK_16k_NAME, `NoCodec-4') + +define(DMIC_DAI_LINK_48k_ID, `3') +define(DMIC_DAI_LINK_16k_ID, `4') + +define(DMICPROC, `eq-iir-volume') +define(DMIC16KPROC, `eq-iir-volume') + +define(DMICPROC_FILTER1, `eq_iir_coef_highpass_40hz_20db_48khz.m4') +define(DMIC16KPROC_FILTER1, `eq_iir_coef_highpass_40hz_20db_16khz.m4') + +ifelse(NCORES, `4', +` +define(DMIC_48k_CORE_ID, `0') +define(DMIC_16k_CORE_ID, `0') +define(SSP0_CORE_ID, `0') +define(SSP1_CORE_ID, `0') +define(SSP2_CORE_ID, `0') +') + +ifelse(NCORES, `2', +` +define(DMIC_48k_CORE_ID, `0') +define(DMIC_16k_CORE_ID, `0') +define(SSP0_CORE_ID, `0') +define(SSP1_CORE_ID, `0') +define(SSP2_CORE_ID, `0') +') + +ifelse(NCORES, `1', +` +define(DMIC_48k_CORE_ID, `0') +define(DMIC_16k_CORE_ID, `0') +define(SSP0_CORE_ID, `0') +define(SSP1_CORE_ID, `0') +define(SSP2_CORE_ID, `0') +') + +include(`platform/intel/intel-generic-dmic.m4') + +define(SSP0_IDX, `0') +define(SSP1_IDX, `1') +define(SSP2_IDX, `2') + +define(PIPE_BITS, `s32le') +define(DAI_BITS, `s24le') + +# +# Define the pipelines +# +# PCM0 ---> Volume -----\ +# Mixer ----> SSP0 +# PCM3 ---> Volume -----/ +# PCM1 ---> Volume ----> Mixer ----> SSP1 +# PCM2 ---> volume ----> Mixer ----> SSP2 +# +# SSP0 ---> Volume ----> PCM0 +# SSP1 ---> Volume ----> PCM1 +# SSP2 ---> Volume ----> PCM2 +# DMIC0 --> IIR -------> PCM10 +# DMIC1 --> IIR -------> PCM11 +# + +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) + +# Volume switch capture pipeline 2 on PCM 0 using max 2 channels of PIPE_BITS. +# Set 1000us deadline on core SSP0_CORE_ID with priority 0 +ifdef(`DISABLE_SSP0',, + `PIPELINE_PCM_ADD(sof/pipe-volume-switch-capture.m4, + 2, 0, 2, PIPE_BITS, + 1000, 0, SSP0_CORE_ID, + 48000, 48000, 48000)') + +# Volume switch capture pipeline 4 on PCM 1 using max 2 channels of PIPE_BITS. +# Set 1000us deadline on core SSP1_CORE_ID with priority 0 +ifdef(`DISABLE_SSP1',, + `PIPELINE_PCM_ADD(sof/pipe-volume-switch-capture.m4, + 4, 1, 2, PIPE_BITS, + 1000, 0, SSP1_CORE_ID, + 48000, 48000, 48000)') + +# Volume switch capture pipeline 6 on PCM 2 using max 2 channels of PIPE_BITS. +# Set 1000us deadline with priority 0 on core SSP2_CORE_ID +PIPELINE_PCM_ADD(sof/pipe-volume-switch-capture.m4, + 6, 2, 2, PIPE_BITS, + 1000, 0, SSP2_CORE_ID, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +# playback DAI is SSP0 using 2 periods +# Buffers use DAI_BITS format, 1000us deadline with priority 0 on core SSP0_CORE_ID +# The 'NOT_USED_IGNORED' is due to dependencies and is adjusted later with an explicit dapm line. +ifdef(`DISABLE_SSP0',, + `DAI_ADD(sof/pipe-mixer-volume-dai-playback.m4, + 1, SSP, SSP0_IDX, NoCodec-0, + NOT_USED_IGNORED, 2, DAI_BITS, + 1000, 0, SSP0_CORE_ID, SCHEDULE_TIME_DOMAIN_TIMER, 2, 48000)') + +# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of PIPE_BITS. +# Set 1000us deadline on core SSP0_CORE_ID with priority 0 +ifdef(`DISABLE_SSP0',, + `PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, + 7, 0, 2, PIPE_BITS, + 1000, 0, SSP0_CORE_ID, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1)') + +# Deep buffer playback pipeline 11 on PCM 3 using max 2 channels of PIPE_BITS. +# Set 1000us deadline on core SSP0_CORE_ID with priority 0. +# TODO: Modify pipeline deadline to account for deep buffering +PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, + 11, 3, 2, PIPE_BITS, + 1000, 0, SSP0_CORE_ID, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) + +# capture DAI is SSP0 using 2 periods +# Buffers use DAI_BITS format, 1000us deadline with priority 0 on core SSP0_IDX +ifdef(`DISABLE_SSP0',, + `DAI_ADD(sof/pipe-dai-capture.m4, + 2, SSP, SSP0_IDX, NoCodec-0, + PIPELINE_SINK_2, 2, DAI_BITS, + 1000, 0, SSP0_CORE_ID, SCHEDULE_TIME_DOMAIN_TIMER)') + +# playback DAI is SSP1 using 2 periods +# Buffers use DAI_BITS format, 1000us deadline with priority 0 on core SSP1_CORE_ID +ifdef(`DISABLE_SSP1',, + `DAI_ADD(sof/pipe-mixer-volume-dai-playback.m4, + 3, SSP, SSP1_IDX, NoCodec-1, + NOT_USED_IGNORED, 2, DAI_BITS, + 1000, 0, SSP1_CORE_ID, SCHEDULE_TIME_DOMAIN_TIMER, 2, 48000)') + +# Low Latency playback pipeline 8 on PCM 1 using max 2 channels of PIPE_BITS. +# Set 1000us deadline on core SSP1_CORE_ID with priority 0 +ifdef(`DISABLE_SSP1',, + `PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, + 8, 1, 2, PIPE_BITS, + 1000, 0, SSP1_CORE_ID, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_3)') + +# capture DAI is SSP1 using 2 periods +# Buffers use DAI_BITS format, 1000us deadline with priority 0 on core SSP1_CORE_ID +ifdef(`DISABLE_SSP1',, + `DAI_ADD(sof/pipe-dai-capture.m4, + 4, SSP, SSP1_IDX, NoCodec-1, + PIPELINE_SINK_4, 2, DAI_BITS, + 1000, 0, SSP1_CORE_ID, SCHEDULE_TIME_DOMAIN_TIMER)') + +# playback DAI is SSP2 using 2 periods +# Buffers use DAI_BITS format, 1000us deadline with priority 0 on core SSP2_CORE_ID +DAI_ADD(sof/pipe-mixer-volume-dai-playback.m4, + 5, SSP, SSP2_IDX, NoCodec-2, + NOT_USED_IGNORED, 2, DAI_BITS, + 1000, 0, SSP2_CORE_ID, SCHEDULE_TIME_DOMAIN_TIMER, 2, 48000) + +# Low Latency playback pipeline 9 on PCM 2 using max 2 channels of PIPE_BITS. +# Set 1000us deadline on core SSP2_CORE_ID with priority 0 +PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, + 9, 2, 2, PIPE_BITS, + 1000, 0, SSP2_CORE_ID, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_5) + +# capture DAI is SSP2 using 2 periods +# Buffers use DAI_BITS format, 1000us deadline with priority 0 on core SSP2_CORE_ID +DAI_ADD(sof/pipe-dai-capture.m4, + 6, SSP, SSP2_IDX, NoCodec-2, + PIPELINE_SINK_6, 2, DAI_BITS, + 1000, 0, SSP2_CORE_ID, SCHEDULE_TIME_DOMAIN_TIMER) + +SectionGraph."mixer-host" { + index "0" + + lines [ + # connect mixer dai pipelines to PCM pipelines + ifdef(`DISABLE_SSP0',,`dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_7)') + ifdef(`DISABLE_SSP1',, `dapm(PIPELINE_MIXER_3, PIPELINE_SOURCE_8)') + dapm(PIPELINE_MIXER_5, PIPELINE_SOURCE_9) + ] +} + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +ifdef(`DISABLE_SSP0',, +PCM_DUPLEX_ADD(`Port'SSP0_IDX, 0, PIPELINE_PCM_7, PIPELINE_PCM_2) +) +ifdef(`DISABLE_SSP1',, +PCM_DUPLEX_ADD(`Port'SSP1_IDX, 1, PIPELINE_PCM_8, PIPELINE_PCM_4) +) +PCM_DUPLEX_ADD(`Port'SSP2_IDX, 2, PIPELINE_PCM_9, PIPELINE_PCM_6) + +# +# BE configurations - overrides config in ACPI if present +# + +ifelse(PLATFORM, `tgl', `define(ROOT_CLK, 38_4)') +ifelse(PLATFORM, `ehl', `define(ROOT_CLK, 38_4)') +ifelse(PLATFORM, `adl', `define(ROOT_CLK, 38_4)') + +ifelse(ROOT_CLK, `19_2', +` +DAI_CONFIG(SSP, SSP0_IDX, 0, NoCodec-0, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), + SSP_CLOCK(bclk, 3072000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 32, 3, 3), + dnl SSP_CONFIG_DATA(type, idx, valid bits, mclk_id, quirks, bclk_delay, + dnl clks_control, pulse_width, padding) + SSP_CONFIG_DATA(SSP, SSP0_IDX, 32, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) + +DAI_CONFIG(SSP, SSP1_IDX, 1, NoCodec-1, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), + SSP_CLOCK(bclk, 3072000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 32, 3, 3), + SSP_CONFIG_DATA(SSP, SSP1_IDX, 32, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) + +DAI_CONFIG(SSP, SSP2_IDX, 2, NoCodec-2, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24576000, codec_mclk_in), + SSP_CLOCK(bclk, 3072000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 32, 3, 3), + SSP_CONFIG_DATA(SSP, SSP2_IDX, 32, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) +') + +ifelse(ROOT_CLK, `24', +` +DAI_CONFIG(SSP, SSP0_IDX, 0, NoCodec-0, + dnl SSP_CONFIG(format, mclk, bclk, fsync, tdm, ssp_config_data) + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), + SSP_CLOCK(bclk, 4800000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 25, 3, 3), + SSP_CONFIG_DATA(SSP, SSP0_IDX, 24, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) + +DAI_CONFIG(SSP, SSP1_IDX, 1, NoCodec-1, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), + SSP_CLOCK(bclk, 4800000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 25, 3, 3), + SSP_CONFIG_DATA(SSP, SSP1_IDX, 24, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) + +DAI_CONFIG(SSP, SSP2_IDX, 2, NoCodec-2, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 24000000, codec_mclk_in), + SSP_CLOCK(bclk, 4800000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 25, 3, 3), + SSP_CONFIG_DATA(SSP, SSP2_IDX, 24, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) +') + +ifelse(ROOT_CLK, `38_4', +` +DAI_CONFIG(SSP, SSP0_IDX, 0, NoCodec-0, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), + SSP_CLOCK(bclk, 2400000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 25, 3, 3), + SSP_CONFIG_DATA(SSP, SSP0_IDX, 24, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) + +DAI_CONFIG(SSP, SSP1_IDX, 1, NoCodec-1, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), + SSP_CLOCK(bclk, 2400000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 25, 3, 3), + SSP_CONFIG_DATA(SSP, SSP1_IDX, 24, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) + +DAI_CONFIG(SSP, SSP2_IDX, 2, NoCodec-2, + SSP_CONFIG(I2S, SSP_CLOCK(mclk, 38400000, codec_mclk_in), + SSP_CLOCK(bclk, 2400000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(2, 25, 3, 3), + SSP_CONFIG_DATA(SSP, SSP2_IDX, 24, 0, SSP_QUIRK_LBM, 0, + eval(SSP_CC_MCLK_ES | SSP_CC_BCLK_ES)))) +') diff --git a/tools/topology/topology1/sof-eq-iir-dts-codec-smart-amplifier.m4 b/tools/topology/topology1/sof-eq-iir-dts-codec-smart-amplifier.m4 new file mode 100644 index 000000000000..a9040132688a --- /dev/null +++ b/tools/topology/topology1/sof-eq-iir-dts-codec-smart-amplifier.m4 @@ -0,0 +1,238 @@ +# +# Unified topology for smart amplifier implementation. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +ifelse(SDW, `1', +`include(`alh.m4')', +`include(`ssp.m4')') + +# Include Token library +include(`sof/tokens.m4') + +DEBUG_START + +# define the default macros. +# define them in your specific platform .m4 if needed. + +#undefine the DYNAMIC flag (if enabled, save it) for smart amplifier as it uses volatile kcontrols +ifdef(`DYNAMIC', `define(`SAVED_DYNAMIC', DYNAMIC)',`') +undefine(`DYNAMIC') + + +ifelse(SDW, `1', +` +# ALH related +# define(`SMART_ALH_INDEX', 1) define smart amplifier ALH index +ifdef(`SMART_ALH_INDEX',`',`errprint(note: Need to define ALH index for sof-smart-amplifier +)') +ifdef(`SMART_ALH_PLAYBACK_NAME',`',`errprint(note: Need to define ALH BE dai_link name for sof-smart-amplifier +)') +ifdef(`SMART_ALH_CAPTURE_NAME',`',`errprint(note: Need to define ALH BE dai_link name for sof-smart-amplifier +)') +', +` +# SSP related +# define(`SMART_SSP_INDEX', 1) define smart amplifier SSP index +ifdef(`SMART_SSP_INDEX',`',`errprint(note: Need to define SSP index for sof-smart-amplifier +)') +# define(`SMART_SSP_NAME', `SSP1-Codec') define SSP BE dai_link name +ifdef(`SMART_SSP_NAME',`',`errprint(note: Need to define SSP BE dai_link name for sof-smart-amplifier +)') +# define(`SMART_SSP_QUIRK', 0) define SSP quirk for special use, e.g. set SSP_QUIRK_LBM to verify +# smart_amp nocodec mode. Set it to 0 by default for normal mode. +ifdef(`SMART_SSP_QUIRK',`',`define(`SMART_SSP_QUIRK', 0)') +# define(`SSP_MCLK', ) define SSP mclk if not done yet +ifdef(`SSP_MCLK',`',`define(`SSP_MCLK', 19200000)') +') + +# define(`SMART_BE_ID', 7) define BE dai_link ID +ifdef(`SMART_BE_ID',`',`errprint(note: Need to define SSP BE dai_link ID for sof-smart-amplifier +)') +# Playback related +# define(`SMART_PB_PPL_ID', 1) +ifdef(`SMART_PB_PPL_ID',`',`errprint(note: Need to define playback pipeline ID for sof-smart-amplifier +)') +# define(`SMART_PB_CH_NUM', 2) +ifdef(`SMART_PB_CH_NUM',`',`errprint(note: Need to define playback channel number for sof-smart-amplifier +)') +define(`SMART_PIPE_SOURCE', concat(`PIPELINE_SOURCE_', SMART_PB_PPL_ID)) +# define(`SMART_TX_CHANNELS', 4) +ifdef(`SMART_TX_CHANNELS',`',`errprint(note: Need to define DAI TX channel number for sof-smart-amplifier +)') +# define(`SMART_RX_CHANNELS', 8) +ifdef(`SMART_RX_CHANNELS',`',`errprint(note: Need to define DAI RX channel number for sof-smart-amplifier +)') +# define(`SMART_FB_CHANNELS', 4) +ifdef(`SMART_FB_CHANNELS',`',`errprint(note: Need to define feedback channel number for sof-smart-amplifier +)') +define(`SMART_PB_PPL_NAME', concat(`PIPELINE_PCM_', SMART_PB_PPL_ID)) +# Ref capture related +# define(`SMART_REF_PPL_ID', 11) +ifdef(`SMART_REF_PPL_ID',`',`errprint(note: Need to define Echo Ref pipeline ID for sof-smart-amplifier +)') +# define(`SMART_REF_CH_NUM', 4) +ifdef(`SMART_REF_CH_NUM',`',`errprint(note: Need to define Echo Ref channel number for sof-smart-amplifier +)') +define(`SMART_PIPE_SINK', concat(`PIPELINE_SINK_', SMART_REF_PPL_ID)) +# define(`N_SMART_DEMUX', `MUXDEMUX'SMART_REF_PPL_ID`.'$1) +define(`SMART_REF_PPL_NAME', concat(`PIPELINE_PCM_', SMART_REF_PPL_ID)) +# PCM related +# define(`SMART_PCM_ID', 0) +ifdef(`SMART_PCM_ID',`',`errprint(note: Need to define PCM ID for sof-smart-amplifier +)') +# define(`SMART_PCM_NAME', `smart373-spk') +ifdef(`SMART_PCM_NAME',`',`errprint(note: Need to define Echo Ref pipeline ID for sof-smart-amplifier +)') + +ifelse(SDW, `1', +` +# +# Define the pipelines +# +# PCM2 ----> smart_amp ----> ALH(ALH_INDEX) +# ^ +# | +# | +# PCM3 <---- demux <----- ALH(ALH_INDEX + 1) +# +' +,` +# +# Define the pipelines +# +# PCM0 ----> smart_amp ----> SSP(SSP_INDEX) +# ^ +# | +# | +# PCM0 <---- demux <----- SSP(SSP_INDEX) +# +') + +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) + +# Demux pipeline 1 on PCM 0 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-eq-iir-dts-codec-smart-amp-playback.m4, + SMART_PB_PPL_ID, SMART_PCM_ID, SMART_PB_CH_NUM, s32le, + 1000, 0, SMART_AMP_CORE, + 48000, 48000, 48000) + +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. +# Set 1000us deadline on core 0 with priority 0 +ifelse(SDW, `1', +` +PIPELINE_PCM_ADD(sof/pipe-amp-ref-capture.m4, + SMART_REF_PPL_ID, eval(SMART_PCM_ID + 1), SMART_REF_CH_NUM, s32le, + 1000, 0, SMART_AMP_CORE, + 48000, 48000, 48000) +', +` +PIPELINE_PCM_ADD(sof/pipe-amp-ref-capture.m4, + SMART_REF_PPL_ID, SMART_PCM_ID, SMART_REF_CH_NUM, s32le, + 1000, 0, SMART_AMP_CORE, + 48000, 48000, 48000) +') + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +ifelse(SDW, `1', +` +# playback DAI is ALH(ALH_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + SMART_PB_PPL_ID, ALH, SMART_ALH_INDEX, SMART_ALH_PLAYBACK_NAME, + SMART_PIPE_SOURCE, 2, s24le, + 1000, 0, SMART_AMP_CORE, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is ALH(ALH_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + SMART_REF_PPL_ID, ALH, eval(SMART_ALH_INDEX + 1), SMART_ALH_CAPTURE_NAME, + SMART_PIPE_SINK, 2, s24le, + 1000, 0, SMART_AMP_CORE, SCHEDULE_TIME_DOMAIN_TIMER) +', +` +# playback DAI is SSP(SPP_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + SMART_PB_PPL_ID, SSP, SMART_SSP_INDEX, SMART_SSP_NAME, + SMART_PIPE_SOURCE, 2, s32le, + 1000, 0, SMART_AMP_CORE, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is SSP(SSP_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + SMART_REF_PPL_ID, SSP, SMART_SSP_INDEX, SMART_SSP_NAME, + SMART_PIPE_SINK, 2, s32le, + 1000, 0, SMART_AMP_CORE, SCHEDULE_TIME_DOMAIN_TIMER) +') + +# Connect demux to smart_amp +ifdef(`N_SMART_REF_BUF',`',`errprint(note: Need to define ref buffer name for connection +)') +ifdef(`N_SMART_DEMUX',`',`errprint(note: Need to define demux widget name for connection +)') +SectionGraph."PIPE_SMART_AMP" { + index "0" + + lines [ + # demux to smart_amp + dapm(N_SMART_REF_BUF, N_SMART_DEMUX) + ] +} + +# PCM for SMART_AMP Playback and EchoRef. +ifelse(SDW, `1', +` +PCM_PLAYBACK_ADD(SMART_PCM_NAME, SMART_PCM_ID, SMART_PB_PPL_NAME) +PCM_CAPTURE_ADD(echo, eval(SMART_PCM_ID + 1), SMART_REF_PPL_NAME) +', +` +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +PCM_DUPLEX_ADD(SMART_PCM_NAME, SMART_PCM_ID, SMART_PB_PPL_NAME, SMART_REF_PPL_NAME) +') + +# +# BE configurations - overrides config in ACPI if present +# + +ifelse(SDW, `1', +` +#ALH ALH Pin2 (ID: SMART_BE_ID) +DAI_CONFIG(ALH, SMART_ALH_INDEX, SMART_BE_ID, SMART_ALH_PLAYBACK_NAME, + ALH_CONFIG(ALH_CONFIG_DATA(ALH, SMART_ALH_INDEX, 48000, SMART_TX_CHANNELS))) + +#ALH ALH Pin3 (ID: SMART_BE_ID + 1) +DAI_CONFIG(ALH, eval(SMART_ALH_INDEX + 1), eval(SMART_BE_ID + 1), SMART_ALH_CAPTURE_NAME, + ALH_CONFIG(ALH_CONFIG_DATA(ALH, eval(SMART_ALH_INDEX + 1), 48000, SMART_RX_CHANNELS))) +', +` +#SSP SSP_INDEX (ID: SMART_BE_ID) +DAI_CONFIG(SSP, SMART_SSP_INDEX, SMART_BE_ID, SMART_SSP_NAME, + SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, 12288000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(8, 32, 15, 255), + SSP_CONFIG_DATA(SSP, SMART_SSP_INDEX, 32, 0, SMART_SSP_QUIRK))) +') + +#Re-enable DYNAMIC flag if it was enabled for other pipelines +ifdef(`SAVED_DYNAMIC', `define(`DYNAMIC', 1)',`') + +DEBUG_END diff --git a/tools/topology/topology1/sof-imx8-compr-pcm-cap-wm8960.m4 b/tools/topology/topology1/sof-imx8-compr-pcm-cap-wm8960.m4 new file mode 100644 index 000000000000..9136f44712e6 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-compr-pcm-cap-wm8960.m4 @@ -0,0 +1,91 @@ +# +# Topology with codec_adapter processing component for i.MX8QM/i.MX8QXP +# +# This is just a passthrough for capture. + +# 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') + + +# Post process setup config + + #codec Post Process setup config +# +# Define the pipelines +# +# PCM0 <---- Codec_Adapter <----- SAI1 (wm8960) +# + +DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, + 0x4ec2, 0xbc, 0x83, 0x10, 0xea, 0x10, 0x1a, 0xf8, 0x8f); + +define(`CA_UUID', passthrough_uuid) + +# Post process setup config for playback +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 2) + +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 capture 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-codec-adapter-capture.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl period, priority, core, time_domain) + +# 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, + 1, SAI, 1, sai1-wm8960-hifi, + PIPELINE_SINK_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# PCM Low Latency, id 0 + +dnl COMPR_CAPTURE_ADD(name, pcm_id, capture) +COMPR_CAPTURE_ADD(Port0, 0, PIPELINE_PCM_1) + +dnl DAI_CONFIG(type, idx, link_id, name, sai_config) +DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/topology1/sof-imx8-compr-pcm-wm8960.m4 b/tools/topology/topology1/sof-imx8-compr-pcm-wm8960.m4 new file mode 100644 index 000000000000..121d178ecbdc --- /dev/null +++ b/tools/topology/topology1/sof-imx8-compr-pcm-wm8960.m4 @@ -0,0 +1,91 @@ +# +# Topology with codec_adapter processing component for i.MX8QM/i.MX8QXP +# +# This is just a passthrough for playback. + +# 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') + + +# Post process setup config + + #codec Post Process setup config +# +# Define the pipelines +# +# PCM0 ----> Codec_Adapter -----> SAI1 (wm8960) +# + +DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, + 0x4ec2, 0xbc, 0x83, 0x10, 0xea, 0x10, 0x1a, 0xf8, 0x8f); + +define(`CA_UUID', passthrough_uuid) + +# Post process setup config for playback +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 2) + +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-codec-adapter-playback.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +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, 1, sai1-wm8960-hifi, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# PCM Low Latency, id 0 + +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, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/topology1/sof-imx8-compr-wm8960-mixer.m4 b/tools/topology/topology1/sof-imx8-compr-wm8960-mixer.m4 new file mode 100644 index 000000000000..e7c8aa17622a --- /dev/null +++ b/tools/topology/topology1/sof-imx8-compr-wm8960-mixer.m4 @@ -0,0 +1,140 @@ +# +# Topology for i.MX8QXP/i.MX8QM/i.MX8MP boards mixing PCM and Compress streams +# +# CODEC: wm8960, wm8962 +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`pcm.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') + +DECLARE_SOF_RT_UUID("Cadence Codec", cadence_codec_uuid, 0xd8218443, 0x5ff3, + 0x4a4c, 0xb3, 0x88, 0x6c, 0xfe, 0x07, 0xb9, 0x56, 0xaa); + +define(`CA_UUID', cadence_codec_uuid) + +# Post process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 8) + +# +# Define the pipelines +# +# PCM0 -----> volume -----------------v +# low latency mixer ----> volume ----> `SAI_INDEX' +# Compr1 -----> Codec Adapter -------^ +# PCM0 <---- Volume <---- `SAI_INDEX' +# + +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. +# 1000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, + 2, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +ifdef(`DMA_DOMAIN', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_DMA)', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_TIMER)') + +# +# DAI configuration +# +# SAI port `SAI_INDEX' is our only pipeline DAI +# + +# 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, SAI_INDEX, DAI_BE_NAME, + NOT_USED_IGNORED, 2, s32le, + 1000, 1, 0, SCHEDULE_DOMAIN, + 2, 48000) + +# PCM Playback pipeline 3 on PCM 0 using max 2 channels of s32le. +# 1000us deadline on core 0 with priority 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_DOMAIN, + PIPELINE_PLAYBACK_SCHED_COMP_1) + +# Compress Playback pipeline 4 on Compr 1 using max 2 channels of s32le. +# 5ms deadline on core 0 with priority 0 +# this is connected to pipeline DAI 1 +PIPELINE_PCM_ADD(sof/pipe-host-codec-adapter-playback.m4, + 4, 1, 2, s32le, + 5000, 0, 0, + 48000, 48000, 48000, + SCHEDULE_DOMAIN, + 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 SAI`SAI_INDEX' using 2 periods +# Buffers use s32le format, 1000us deadline on core 0 with priority 0 +# this is part of pipeline 2 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, SAI, SAI_INDEX, DAI_BE_NAME, + PIPELINE_SINK_2, 2, s32le, + 1000, 0, 0, SCHEDULE_DOMAIN) + + +# PCM definitions +PCM_DUPLEX_ADD(PCM, 0, PIPELINE_PCM_3, PIPELINE_PCM_2) +COMPR_PLAYBACK_ADD(PCM Deep Buffer, 1, PIPELINE_PCM_4) + +# +# BE configurations +# +DAI_CONFIG(SAI, SAI_INDEX, 0, DAI_BE_NAME, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0))) diff --git a/tools/topology/topology1/sof-imx8-compr-wm8960.m4 b/tools/topology/topology1/sof-imx8-compr-wm8960.m4 new file mode 100644 index 000000000000..597bb143feac --- /dev/null +++ b/tools/topology/topology1/sof-imx8-compr-wm8960.m4 @@ -0,0 +1,116 @@ +# +# 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') +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') + + +# Post process setup config + +#codec Post Process setup config +# +# Define the pipelines +# +# 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); + +define(`CA_UUID', cadence_codec_uuid) + +# Post process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x07,0x00,0x02,0x00,0x0C,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x03,0x00,0x02,0x00,' +` 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,' +` 0x20,0x00,0x0,0x0"'') + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 8) + +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-codec-adapter-playback.m4, + 1, 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, `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, +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, DAI_BE_NAME, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +# PCM Low Latency, id 0 + +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, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, `RATE', codec_provider), + 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_provider), + SAI_CLOCK(fsync, `RATE', codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0)))', + ) diff --git a/tools/topology/topology1/sof-imx8-cs42888-mixer.m4 b/tools/topology/topology1/sof-imx8-cs42888-mixer.m4 new file mode 100644 index 000000000000..d896ef2819b4 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-cs42888-mixer.m4 @@ -0,0 +1,106 @@ +# +# Topology for i.MX8QM / i.MX8QXP boards with cs42888 codec demonstrating mixer component +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`esai.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 ----> ESAI0 +# PCM1 -----> volume -------^ +# PCM0 <---- Volume <---- ESAI0 +# + +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. +# 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, + 2, 0, 2, s24le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAI configuration +# +# ESAI port 0 is our only pipeline DAI +# + +# playback DAI is ESAI0 using 2 periods +# Buffers use s24le 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, ESAI, 0, esai0-cs42888, + NOT_USED_IGNORED, 2, s24le, + 1000, 1, 0, SCHEDULE_TIME_DOMAIN_TIMER, + 2, 48000) + +# PCM Playback pipeline 3 on PCM 0 using max 2 channels of s24le. +# 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, s24le, + 1000, 0, 0, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_PLAYBACK_SCHED_COMP_1) + +# PCM Playback pipeline 4 on PCM 1 using max 2 channels of s24le. +# 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, s24le, + 5000, 0, 0, + 48000, 48000, 48000, + SCHEDULE_TIME_DOMAIN_TIMER, + 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 ESAI0 using 2 periods +# Buffers use s24le format, 1000us deadline with priority 0 on core 0 +# this is part of pipeline 2 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ESAI, 0, esai0-cs42888, + PIPELINE_SINK_2, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +# 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(ESAI, 0, 0, esai0-cs42888, + ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), + ESAI_CLOCK(bclk, 3072000, codec_consumer), + ESAI_CLOCK(fsync, 48000, codec_consumer), + ESAI_TDM(2, 32, 3, 3), + ESAI_CONFIG_DATA(ESAI, 0, 0))) diff --git a/tools/topology/topology1/sof-imx8-cs42888.m4 b/tools/topology/topology1/sof-imx8-cs42888.m4 new file mode 100644 index 000000000000..1bf89135ab05 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-cs42888.m4 @@ -0,0 +1,82 @@ +# +# Topology for i.MX8QXP board with cs42888 codec +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`esai.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 <-----> ESAI0 (cs42888) +# + +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 s24le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 2, s24le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 2, 0, 2, s24le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +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 ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ESAI, 0, esai0-cs42888, + PIPELINE_SOURCE_1, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ESAI, 0, esai0-cs42888, + PIPELINE_SINK_2, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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, esai_config) +DAI_CONFIG(ESAI, 0, 0, esai0-cs42888, + ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), + ESAI_CLOCK(bclk, 3072000, codec_consumer), + ESAI_CLOCK(fsync, 48000, codec_consumer), + ESAI_TDM(2, 32, 3, 3), + ESAI_CONFIG_DATA(ESAI, 0, 0))) diff --git a/tools/topology/topology1/sof-imx8-nocodec-sai.m4 b/tools/topology/topology1/sof-imx8-nocodec-sai.m4 new file mode 100644 index 000000000000..150610477251 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-nocodec-sai.m4 @@ -0,0 +1,68 @@ +# +# Topology for i.MX8QXP board with nocodec +# + +# 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 ---> SAI1 (NoCodec) +# + +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 s24le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 2, s24le, + 1000, 0, 0, + 8000, 96000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + +# playback DAI is SAI1 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SAI, 1, NoCodec-0, + PIPELINE_SOURCE_1, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) + +dnl DAI_CONFIG(type, dai_index, link_id, name, sai_config) +DAI_CONFIG(SAI, 1, 0, NoCodec-0, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 49152000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_consumer), + SAI_CLOCK(fsync, 48000, codec_consumer), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/topology1/sof-imx8-nocodec.m4 b/tools/topology/topology1/sof-imx8-nocodec.m4 new file mode 100644 index 000000000000..caf52acdf0e1 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-nocodec.m4 @@ -0,0 +1,68 @@ +# +# Topology for i.MX8QXP board with nocodec +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`esai.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 ---> ESAI0 (NoCodec) +# + +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 s24le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 2, s24le, + 1000, 0, 0, + 8000, 96000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + +# playback DAI is ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ESAI, 0, NoCodec-0, + PIPELINE_SOURCE_1, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) + +dnl DAI_CONFIG(type, dai_index, link_id, name, esai_config) +DAI_CONFIG(ESAI, 0, 0, NoCodec-0, + ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), + ESAI_CLOCK(bclk, 3072000, codec_consumer), + ESAI_CLOCK(fsync, 48000, codec_consumer), + ESAI_TDM(2, 32, 3, 3), + ESAI_CONFIG_DATA(ESAI, 0, 0))) diff --git a/tools/topology/topology1/sof-imx8-src-cs42888.m4 b/tools/topology/topology1/sof-imx8-src-cs42888.m4 new file mode 100644 index 000000000000..f972da802a52 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-src-cs42888.m4 @@ -0,0 +1,82 @@ +# +# Topology for i.MX8QXP and i.MX8QM boards with cs42888 codec +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`esai.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 <----> SRC <----> volume <-----> ESAI0 (cs42888) +# + +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 s24le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, + 1, 0, 2, s24le, + 1000, 0, 0, + 8000, 96000, 48000) + +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-src-volume-capture.m4, + 2, 0, 2, s24le, + 1000, 0, 0, + 8000, 96000, 48000) + +# +# DAIs configuration +# + +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 ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ESAI, 0, esai0-cs42888, + PIPELINE_SOURCE_1, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ESAI, 0, esai0-cs42888, + PIPELINE_SINK_2, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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, esai_config) +DAI_CONFIG(ESAI, 0, 0, esai0-cs42888, + ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), + ESAI_CLOCK(bclk, 3072000, codec_consumer), + ESAI_CLOCK(fsync, 48000, codec_consumer), + ESAI_TDM(2, 32, 3, 3), + ESAI_CONFIG_DATA(ESAI, 0, 0))) diff --git a/tools/topology/topology1/sof-imx8-src-wm8960.m4 b/tools/topology/topology1/sof-imx8-src-wm8960.m4 new file mode 100644 index 000000000000..ebf81588dd10 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-src-wm8960.m4 @@ -0,0 +1,104 @@ +# +# Topology for i.MX8QXP/i.MX8QM/i.MX8MP boards with `CODEC' codec +# +# CODEC: wm8960, 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 <----> SRC <----> volume <-----> `SAI_INDEX' (`CODEC') +# + +ifdef(`DMA_DOMAIN', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_DMA)', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_TIMER)') + +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'-volume-playback.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 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-`PPROC'-volume-capture.m4, + 2, 0, 2, s32le, + 1000, 0, 0, + 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 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, SAI_INDEX, DAI_BE_NAME, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_DOMAIN) + +# 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, SAI_INDEX, DAI_BE_NAME, + PIPELINE_SINK_2, 2, s32le, + 1000, 0, 0, SCHEDULE_DOMAIN) + + +# 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, SAI_INDEX, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, 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_provider), + SAI_CLOCK(fsync, `RATE', codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + ) diff --git a/tools/topology/topology1/sof-imx8-wm8960-cs42888.m4 b/tools/topology/topology1/sof-imx8-wm8960-cs42888.m4 new file mode 100644 index 000000000000..8034dbefde8a --- /dev/null +++ b/tools/topology/topology1/sof-imx8-wm8960-cs42888.m4 @@ -0,0 +1,118 @@ +# +# Topology for i.MX8QXP/i.MX8QM with wm8960 (cpu board) + cs42888 (base board) +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`esai.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 <-----> ESAI0 (cs42888) +# PCM1 <----> volume <-----> SAI1 (wm8960) + +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 s24le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 2, s24le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s24le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 2, 0, 2, s24le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Low Latency playback pipeline 1 on PCM 1 using max 2 channels of s32le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 3, 1, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 2 on PCM 1 using max 2 channels of s32le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 4, 1, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) +# +# DAIs configuration +# + +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 ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ESAI, 0, esai0-cs42888, + PIPELINE_SOURCE_1, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is ESAI0 using 2 periods +# Buffers use s24le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ESAI, 0, esai0-cs42888, + PIPELINE_SINK_2, 2, s24le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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, + 3, SAI, 1, sai1-wm8960-hifi, + PIPELINE_SOURCE_3, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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, + 4, SAI, 1, sai1-wm8960-hifi, + PIPELINE_SINK_4, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) +PCM_DUPLEX_ADD(Port1, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, idx, link_id, name, esai_config) +DAI_CONFIG(ESAI, 0, 0, esai0-cs42888, + ESAI_CONFIG(I2S, ESAI_CLOCK(mclk, 49152000, codec_mclk_in), + ESAI_CLOCK(bclk, 3072000, codec_consumer), + ESAI_CLOCK(fsync, 48000, codec_consumer), + ESAI_TDM(2, 32, 3, 3), + ESAI_CONFIG_DATA(ESAI, 0, 0))) + +dnl DAI_CONFIG(type, idx, link_id, name, sai_config) +DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/topology1/sof-imx8-wm8960-kwd.m4 b/tools/topology/topology1/sof-imx8-wm8960-kwd.m4 new file mode 100644 index 000000000000..2203b5504ddf --- /dev/null +++ b/tools/topology/topology1/sof-imx8-wm8960-kwd.m4 @@ -0,0 +1,90 @@ +# +# Topology for i.MX8 with wm8960 codec for +# keyword detection and triggering use case. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +include(`sai.m4') +# Include i.MX8 DSP configuration +include(`platform/imx/imx8.m4') + +define(KWD_PIPE_SCH_DEADLINE_US, 20000) + +define(DMIC_16k_PCM_NAME, `SAI1') + +# This is for iMX8QM/QXP +# +# PCM 0 <-------+- KPBM 0 <-- B0 <-- SAI1 (wm8960) +# | +# Keyword <-----+ +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) + +# Passthrough capture pipeline 1 on PCM 0 using max 2 channels. +# Schedule 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-kfbm-no-lp-capture.m4, + 1, 0, 2, s32le, + KWD_PIPE_SCH_DEADLINE_US, 0, 0, + 16000, 16000, 16000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +# This is for iMX8QM/QXP +# capture DAI is SAI1 using 2 periods +# Buffers use s32le format, with 320 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 1, SAI, 1, sai1-wm8960-hifi, + PIPELINE_SINK_1, 2, s32le, + KWD_PIPE_SCH_DEADLINE_US, + 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# keyword detector pipe +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, dynamic) +PIPELINE_PCM_ADD(sof/pipe-detect.m4, + 2, 0, 2, s32le, + KWD_PIPE_SCH_DEADLINE_US, 1, 0, + 16000, 16000, 16000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_SCHED_COMP_1) + +# Connect pipelines together +SectionGraph."pipe-sof-imx8-keyword-detect" { + index "0" + lines [ + # keyword detect + dapm(PIPELINE_SINK_2, PIPELINE_SOURCE_1) + dapm(PIPELINE_PCM_1, PIPELINE_DETECT_2) + ] +} + +dnl DAI_CONFIG(type, dai_index, link_id, name, sai_config) +DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 16000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0))) diff --git a/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 b/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 new file mode 100644 index 000000000000..4c551a7bc848 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 @@ -0,0 +1,128 @@ +# +# Topology for i.MX8QM/i.MX8QXP/i.MX8MP boards with `CODEC' codec demonstrating mixer component +# +# CODEC: wm8960, wm8962 +# + +# 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 ----> `SAI_INDEX' (`CODEC') +# PCM1 -----> volume -------^ +# PCM0 <---- Volume <---- `SAI_INDEX' +# + +# 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, + `RATE', `RATE', `RATE') + +# +# DAI configuration +# +# SAI port SAI_INDEX is our only pipeline DAI +# + +# 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)) + +ifdef(`DMA_DOMAIN', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_DMA)', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_TIMER)') + +# 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, SAI_INDEX, DAI_BE_NAME, + NOT_USED_IGNORED, 2, s32le, + 1000, 1, 0, SCHEDULE_DOMAIN, + 2, `RATE') + +# 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, + `RATE', `RATE', `RATE', + SCHEDULE_DOMAIN, + 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, + `RATE', `RATE', `RATE', + SCHEDULE_DOMAIN, + 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 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, SAI_INDEX, DAI_BE_NAME, + PIPELINE_SINK_2, 2, s32le, + 1000, 0, 0, SCHEDULE_DOMAIN) + + +# 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, SAI_INDEX, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, 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_provider), + SAI_CLOCK(fsync, RATE, codec_provider), + SAI_TDM(2, 32, 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 new file mode 100644 index 000000000000..289493cf7bda --- /dev/null +++ b/tools/topology/topology1/sof-imx8-wm8960.m4 @@ -0,0 +1,111 @@ +# +# Topology for i.MX8QM/i.MX8QXP/i.MX8MP board with 'CODEC' codec +# +# CODEC: wm8960, 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 <----> `PPROC' <-----> `SAI_INDEX' (`CODEC') +# + +ifdef(`DMA_DOMAIN', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_DMA)', `define(`SCHEDULE_DOMAIN', SCHEDULE_TIME_DOMAIN_TIMER)') + +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(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 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, SAI_INDEX, DAI_BE_NAME, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_DOMAIN) + +# 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, SAI_INDEX, DAI_BE_NAME, + PIPELINE_SINK_2, 2, s32le, + 1000, 0, 0, SCHEDULE_DOMAIN) + + +# 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, SAI_INDEX, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, RATE, codec_provider), + SAI_TDM(2, 32, 3, 3), + 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_provider), + SAI_CLOCK(fsync, RATE, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + ) diff --git a/tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 b/tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 new file mode 100644 index 000000000000..207a4a2e6eb5 --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-btsco-dual-8ch.m4 @@ -0,0 +1,124 @@ +# +# Topology for imx8mp using SAI2 and SAI3, 8 channels each, playback and capture +# + +# +# necessary device tree configuration: +# simple-audio-card with dai-link@0 (cpu <&dsp 1>) and dai-link@1 (cpu <&dsp 2>) +# + +# 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(`CHANNELS', 8) +define(`DEADLINE', 1000) + +# +# Define the pipelines +# +# PCM0 <---> Volume <---> SAI2 +# PCM1 <---> Volume <---> SAI3 + +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 CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + + +# Low Latency capture pipeline 2 on PCM 0 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 2, 0, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + + +# Low Latency playback pipeline 3 on PCM 1 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 3, 1, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + + +# Low Latency capture pipeline 4 on PCM 1 using max CHANNELS, s16le +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 4, 1, CHANNELS, s16le, + DEADLINE, 0, 0, + 48000, 48000, 48000) + +# +# DAI configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + +# playback DAI SAI2 using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SAI, 2, sai2-bt-sco-pcm-wb, + PIPELINE_SOURCE_1, 2, s16le, + DEADLINE, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI SAI2 using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 2, SAI, 2, sai2-bt-sco-pcm-wb, + PIPELINE_SINK_2, 2, s16le, + DEADLINE, 0, 0) + +# playback DAI SAI3 using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 3, SAI, 3, sai3-bt-sco-pcm-wb, + PIPELINE_SOURCE_3, 2, s16le, + DEADLINE, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI SAI3 using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 4, SAI, 3, sai3-bt-sco-pcm-wb, + PIPELINE_SINK_4, 2, s16le, + DEADLINE, 0, 0) + +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) +PCM_DUPLEX_ADD(Port1, 1, PIPELINE_PCM_3, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, dai_index, link_id, name, sai_config) +dnl SAI_CLOCK: clock, freq, codec_provider, polarity (optional) +dnl SAI_TDM: number of channels, word width, tx mask, rx mask: decimal channel enable bits +dnl SAI_CONFIG_DATA: index, mclk_id (optional) + +DAI_CONFIG(SAI, 2, 0, sai2-bt-sco-pcm-wb, + SAI_CONFIG(DSP_A, SAI_CLOCK(mclk, 12288000, codec_mclk_out), + SAI_CLOCK(bclk, 6144000, codec_consumer), + SAI_CLOCK(fsync, 48000, codec_consumer), + SAI_TDM(CHANNELS, 16, 255, 255), + SAI_CONFIG_DATA(SAI, 2, 0))) + +DAI_CONFIG(SAI, 3, 0, sai3-bt-sco-pcm-wb, + SAI_CONFIG(DSP_A, SAI_CLOCK(mclk, 12288000, codec_mclk_out), + SAI_CLOCK(bclk, 6144000, codec_consumer, inverted), + SAI_CLOCK(fsync, 48000, codec_consumer), + SAI_TDM(CHANNELS, 16, 255, 255), + SAI_CONFIG_DATA(SAI, 3, 0))) + diff --git a/tools/topology/topology1/sof-imx8mp-compr-pcm-cap-wm8960.m4 b/tools/topology/topology1/sof-imx8mp-compr-pcm-cap-wm8960.m4 new file mode 100644 index 000000000000..c86876be902d --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-compr-pcm-cap-wm8960.m4 @@ -0,0 +1,92 @@ +# +# Topology with codec_adapter processing component for i.MX8MP +# +# This is just a passthrough for capture. + +# 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') + + +# Post process setup config + + #codec Post Process setup config +# +# Define the pipelines +# +# PCM0 <---- Codec_Adapter <----- SAI3 (wm8960) +# + +DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, 0x4ec2, + 0xbc, 0x83, 0x10, 0xea, 0x10, 0x1a, 0xf8, 0x8f); + +define(`CA_UUID', passthrough_uuid) + +# Post process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 2) + +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 capture 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-codec-adapter-capture.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl period, priority, core, time_domain) + +# 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, + 1, SAI, 3, sai3-wm8960-hifi, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +# PCM Low Latency, id 0 + +dnl COMPR_CAPTURE_ADD(name, pcm_id, capture) +COMPR_CAPTURE_ADD(Port0, 0, PIPELINE_PCM_1) + +dnl DAI_CONFIG(type, idx, link_id, name, sai_config) +DAI_CONFIG(SAI, 3, 0, sai3-wm8960-hifi, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/topology1/sof-imx8mp-compr-pcm-wm8960.m4 b/tools/topology/topology1/sof-imx8mp-compr-pcm-wm8960.m4 new file mode 100644 index 000000000000..73f787e6900c --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-compr-pcm-wm8960.m4 @@ -0,0 +1,92 @@ +# +# Topology with codec_adapter processing component for i.MX8MP +# +# This is just a passthrough for playback. + +# 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') + + +# Post process setup config + + #codec Post Process setup config +# +# Define the pipelines +# +# PCM0 ----> Codec_Adapter -----> SAI3 (wm8960) +# + +DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, 0x4ec2, + 0xbc, 0x83, 0x10, 0xea, 0x10, 0x1a, 0xf8, 0x8f); + +define(`CA_UUID', passthrough_uuid) + +# Post process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 2) + +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-codec-adapter-playback.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +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, sai3-wm8960-hifi, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +# PCM Low Latency, id 0 + +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, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/topology1/sof-imx8mp-compr-wm8960.m4 b/tools/topology/topology1/sof-imx8mp-compr-wm8960.m4 new file mode 100644 index 000000000000..de620e1e3644 --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-compr-wm8960.m4 @@ -0,0 +1,117 @@ +# +# 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') +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') + + +# Post process setup config + +# codec Post Process setup config +# +# Define the pipelines +# +# 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); + +define(`CA_UUID', cadence_codec_uuid) + +# Post process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x24,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x07,0x00,0x02,0x00,0x0C,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x03,0x00,0x02,0x00,' +` 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x00,0x00,0x06,0x00,0x0C,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00"'' +) + +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 8) + +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-codec-adapter-playback.m4, + 1, 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, `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_TIMER) + + +# PCM Low Latency, id 0 + +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, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, 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_provider), + SAI_CLOCK(fsync, `RATE', codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0)))', + ) diff --git a/tools/topology/topology1/sof-imx8mp-micfil.m4 b/tools/topology/topology1/sof-imx8mp-micfil.m4 new file mode 100644 index 000000000000..ccbc060fddc5 --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-micfil.m4 @@ -0,0 +1,35 @@ +# +# Topology for i.MX8M with MICFIL found on IMX-AUD-HAT +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`micfil.m4') +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +#Include DSP configuration +include(`platform/imx/imx8.m4') + +#DMIC +# Capture pipeline 3 on PCM 1 using max 4 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 1, 0, 4, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, 1, MICFIL, 2, micfil-dmic-hifi, +PIPELINE_SINK_1, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(MICFIL, 0, 0, micfil-dmic-hifi, + MICFIL_CONFIG(MICFIL_CONFIG_DATA(MICFIL, 0, 48000, 4))) + +# PCM id 1 +PCM_CAPTURE_ADD(MICFIL, 0, PIPELINE_PCM_1) +#/**********************************************************************************/ diff --git a/tools/topology/topology1/sof-imx8mp-wm8960-kwd.m4 b/tools/topology/topology1/sof-imx8mp-wm8960-kwd.m4 new file mode 100644 index 000000000000..61bb1ce513b0 --- /dev/null +++ b/tools/topology/topology1/sof-imx8mp-wm8960-kwd.m4 @@ -0,0 +1,96 @@ +# +# Topology for i.MX8 with wm8960 codec for +# keyword detection and triggering use case. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +include(`sai.m4') +# Include i.MX8 DSP configuration +include(`platform/imx/imx8.m4') + +define(KWD_PIPE_SCH_DEADLINE_US, 20000) + +define(DMIC_16k_PCM_NAME, `SAI3') + +# This is for iMX8M PLUS +# +# PCM 0 <-------+- KPBM 0 <-- B0 <-- SAI3 (wm8960) +# | +# Keyword <-----+ +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) + +# Passthrough capture pipeline 1 on PCM 0 using max 2 channels. +# Schedule 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-kfbm-no-lp-capture.m4, + 1, 0, 2, s16le, + KWD_PIPE_SCH_DEADLINE_US, 0, 0, + 16000, 16000, 16000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +# This is for iMX8M PLUS +# capture DAI is SAI3 using 2 periods +# Buffers use s16le format, with 320 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 1, SAI, 3, sai3-wm8960-hifi, + PIPELINE_SINK_1, 2, s16le, + KWD_PIPE_SCH_DEADLINE_US, + 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# keyword detector pipe +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, dynamic) +PIPELINE_PCM_ADD(sof/pipe-detect.m4, + 2, 0, 2, s16le, + KWD_PIPE_SCH_DEADLINE_US, 1, 0, + 16000, 16000, 16000, + SCHEDULE_TIME_DOMAIN_TIMER, + PIPELINE_SCHED_COMP_1) + +# Connect pipelines together +SectionGraph."pipe-sof-apl-keyword-detect" { + index "0" + + lines [ + # keyword detect + dapm(PIPELINE_SINK_2, PIPELINE_SOURCE_1) + dapm(PIPELINE_PCM_1, PIPELINE_DETECT_2) + ] +} + +# This is for iMX8M PLUS +# +# BE configurations - overrides config in ACPI if present +# + +dnl DAI_CONFIG(type, dai_index, link_id, name, sai_config/ssp_config/dmic_config) +DAI_CONFIG(SAI, 3, 0, sai3-wm8960-hifi, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 16000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/topology1/sof-imx8ulp-9x9-btsco.m4 b/tools/topology/topology1/sof-imx8ulp-9x9-btsco.m4 new file mode 100644 index 000000000000..918048dd5d4a --- /dev/null +++ b/tools/topology/topology1/sof-imx8ulp-9x9-btsco.m4 @@ -0,0 +1,95 @@ +# +# Topology for i.MX8ULP 9x9 board with bluetooth codec +# + +# 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 <-----> SAI6 (connect to BT) +# + +# SAI6 is connected to BT which supports only 1 channel for playback and record +ifdef(`CHANNELS_MIN', `', `define(CHANNELS_MIN, 1)') + +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 1 channels of s16le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 1, s16le, + 1000, 0, 0, + `FSYNC_RATE', `FSYNC_RATE', `FSYNC_RATE') + +# Low Latency capture pipeline 2 on PCM 0 using max 1 channels of s16le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 2, 0, 1, s16le, + 1000, 0, 0, + `FSYNC_RATE', `FSYNC_RATE', `FSYNC_RATE') +# +# DAIs configuration +# + +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 SAI6 using 2 periods +# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SAI, 6, sai6-bt-sco-pcm-wb, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is SAI6 using 2 periods +# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, SAI, 6, sai6-bt-sco-pcm-wb, + PIPELINE_SINK_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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) + +# BCLK frequency is computed using the following formula: +# Freq(BCLK) = Freq(FSYNC) * TDM_SLOTS * TDM_SLOT_WIDTH +# +# For 8ULP this yields the following frequencies +# (based on supported BT HFP configurations): +# +# 1) NBS (Freq(FSYNC) = 8k) +# Freq(BCLK) = 8k * 16 * 1 = 128000 +# +# 2) WBS (Freq(FSYNC) = 16k) +# Freq(BCLK) = 16k * 16 * 1 = 256000 +dnl DAI_CONFIG(type, idx, link_id, name, sai_config) +DAI_CONFIG(SAI, 6, 0, sai6-bt-sco-pcm-wb, + SAI_CONFIG(DSP_A, SAI_CLOCK(mclk, 12288000, codec_mclk_out), + SAI_CLOCK(bclk, `eval(FSYNC_RATE * 16)', codec_consumer, inverted), + SAI_CLOCK(fsync, `FSYNC_RATE', codec_consumer), + SAI_TDM(1, 16, 1, 1), + SAI_CONFIG_DATA(SAI, 6, 0))) diff --git a/tools/topology/topology1/sof-imx8ulp-btsco.m4 b/tools/topology/topology1/sof-imx8ulp-btsco.m4 new file mode 100644 index 000000000000..05f5e71b1b04 --- /dev/null +++ b/tools/topology/topology1/sof-imx8ulp-btsco.m4 @@ -0,0 +1,96 @@ +# +# Topology for i.MX8ULP board with bluetooth codec +# + +# 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 <-----> SAI5 (connect to BT) +# + +# SAI5 is connected to BT which supports only 1 channel for playback and record +ifdef(`CHANNELS_MIN', `', `define(CHANNELS_MIN, 1)') + +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 1 channels of s16le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 1, s16le, + 1000, 0, 0, + `FSYNC_RATE', `FSYNC_RATE', `FSYNC_RATE') + +# Low Latency capture pipeline 2 on PCM 0 using max 1 channels of s16le. +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, + 2, 0, 1, s16le, + 1000, 0, 0, + `FSYNC_RATE', `FSYNC_RATE', `FSYNC_RATE') + +# +# DAIs configuration +# + +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 SAI5 using 2 periods +# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, SAI, 5, sai5-bt-sco-pcm-wb, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is SAI5 using 2 periods +# Buffers use s16le format, with 16 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 2, SAI, 5, sai5-bt-sco-pcm-wb, + PIPELINE_SINK_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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) + +# BCLK frequency is computed using the following formula: +# Freq(BCLK) = Freq(SYNC) * TDM_SLOTS * TDM_SLOT_WIDTH +# +# For 8ULP this yields the following frequencies (based on +# supported BT HFP configurations): +# +# 1) NBS (Freq(FSYNC) = 8k) +# Freq(BCLK) = 8k * 16 * 1 = 128000 +# +# 2) WBS (Freq(FSYNC) = 16k) +# Freq(BCLK) = 16k * 16 * 1 = 256000 +dnl DAI_CONFIG(type, idx, link_id, name, sai_config) +DAI_CONFIG(SAI, 5, 0, sai5-bt-sco-pcm-wb, + SAI_CONFIG(DSP_A, SAI_CLOCK(mclk, 12288000, codec_mclk_out), + SAI_CLOCK(bclk, `eval(FSYNC_RATE * 16)', codec_consumer, inverted), + SAI_CLOCK(fsync, `FSYNC_RATE', codec_consumer), + SAI_TDM(1, 16, 1, 1), + SAI_CONFIG_DATA(SAI, 5, 0))) diff --git a/tools/topology/topology1/sof-imx93-wm8962.m4 b/tools/topology/topology1/sof-imx93-wm8962.m4 new file mode 100644 index 000000000000..f9ffe7f38e0a --- /dev/null +++ b/tools/topology/topology1/sof-imx93-wm8962.m4 @@ -0,0 +1,82 @@ +# +# Topology for i.MX93 board with WM8962 codec +# + +# 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 (WM8962) +# + +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, + 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-`PPROC'-capture.m4, + 2, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) +# +# DAIs configuration +# + +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 +# 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-wm8962, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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-wm8962, + PIPELINE_SINK_2, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +# 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, sai3-wm8962, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/topology1/sof-imx95-wm8962.m4 b/tools/topology/topology1/sof-imx95-wm8962.m4 new file mode 100644 index 000000000000..c920c6e9c99e --- /dev/null +++ b/tools/topology/topology1/sof-imx95-wm8962.m4 @@ -0,0 +1,82 @@ +# +# Topology for i.MX95 with WM8962 codec +# + +# 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 <----> PPROC <-----> SAI3 +# + +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, + 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-`PPROC'-capture.m4, + 2, 0, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) +# +# DAIs configuration +# + +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 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, 3, sai3-wm8962, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# 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, 3, sai3-wm8962, + PIPELINE_SINK_2, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + + +# 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, sai3-wm8962, + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_provider), + SAI_CLOCK(fsync, 48000, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/topology1/sof-mt8186-mt6366.m4 b/tools/topology/topology1/sof-mt8186-mt6366.m4 new file mode 100644 index 000000000000..f6742a8a7623 --- /dev/null +++ b/tools/topology/topology1/sof-mt8186-mt6366.m4 @@ -0,0 +1,128 @@ +# +# Topology for MT8186 board with mt6366/rt1019/rt5682s/da7219/max98357 +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`afe.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/mediatek/mt8186.m4') + +# +# Define the pipelines +# +# PCM25 ---> AFE (Speaker - max98357/rt1019) +# PCM26 ---> AFE (Headset playback - da7219/rt5682s) +# PCM27 <--- AFE (DMIC - MT6366) +# PCM28 <--- AFE (Headset record - da7219/rt5682s) + + +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) + +define(`ENDPOINT_NAME', `Speakers') +# Low Latency playback pipeline 1 on PCM 25 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`DTS',sof/pipe-eq-iir-dts-codec-playback.m4, ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4)), + 1, 25, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +define(`ENDPOINT_NAME', `Headphones') +# Low Latency playback pipeline 2 on PCM 26 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`DTS',sof/pipe-eq-iir-dts-codec-playback.m4, ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4)), + 2, 26, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +# Low Latency capture pipeline 3 on PCM 27 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 27, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 4 on PCM 28 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 28, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, AFE, 0, AFE_SOF_DL1, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 2, AFE, 1, AFE_SOF_DL2, + PIPELINE_SOURCE_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 3, AFE, 2, AFE_SOF_UL1, + PIPELINE_SINK_3, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 4, AFE, 3, AFE_SOF_UL2, + PIPELINE_SINK_4, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +#SCHEDULE_TIME_DOMAIN_DMA +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(SOF_DL1, 25, PIPELINE_PCM_1) +PCM_PLAYBACK_ADD(SOF_DL2, 26, PIPELINE_PCM_2) +PCM_CAPTURE_ADD(SOF_UL1, 27, PIPELINE_PCM_3) +PCM_CAPTURE_ADD(SOF_UL2, 28, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, dai_index, link_id, name, afe_config) + +DAI_CONFIG(AFE, 0, 0, AFE_SOF_DL1, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 0, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 1, 0, AFE_SOF_DL2, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 1, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 2, 0, AFE_SOF_UL1, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 2, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 3, 0, AFE_SOF_UL2, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 3, 48000, 2, s16le))) diff --git a/tools/topology/topology1/sof-mt8188-mt6359.m4 b/tools/topology/topology1/sof-mt8188-mt6359.m4 new file mode 100644 index 000000000000..4244964561db --- /dev/null +++ b/tools/topology/topology1/sof-mt8188-mt6359.m4 @@ -0,0 +1,128 @@ +# +# Topology for MT8188 board with mt6359 +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`afe.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/mediatek/mt8188.m4') + +# +# Define the pipelines +# +# PCM16 ---> AFE (Speaker - rt1019) +# PCM17 ---> AFE (Headset playback - rt5682) +# PCM18 <--- AFE (DMIC - MT6365) +# PCM19 <--- AFE (Headset record - rt5682) + + +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) + +define(`ENDPOINT_NAME', `Speakers') +# Low Latency playback pipeline 1 on PCM 16 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), + 1, 16, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +define(`ENDPOINT_NAME', `Headphones') +# Low Latency playback pipeline 2 on PCM 17 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), + 2, 17, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +# Low Latency capture pipeline 3 on PCM 18 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 18, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 4 on PCM 19 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 19, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, AFE, 0, AFE_SOF_DL2, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 2, AFE, 1, AFE_SOF_DL3, + PIPELINE_SOURCE_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 3, AFE, 2, AFE_SOF_UL4, + PIPELINE_SINK_3, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 4, AFE, 3, AFE_SOF_UL5, + PIPELINE_SINK_4, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +#SCHEDULE_TIME_DOMAIN_DMA +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(SOF_DL2, 16, PIPELINE_PCM_1) +PCM_PLAYBACK_ADD(SOF_DL3, 17, PIPELINE_PCM_2) +PCM_CAPTURE_ADD(SOF_UL4, 18, PIPELINE_PCM_3) +PCM_CAPTURE_ADD(SOF_UL5, 19, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, dai_index, link_id, name, afe_config) + +DAI_CONFIG(AFE, 0, 0, AFE_SOF_DL2, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 0, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 1, 0, AFE_SOF_DL3, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 1, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 2, 0, AFE_SOF_UL4, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 2, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 3, 0, AFE_SOF_UL5, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 3, 48000, 2, s16le))) diff --git a/tools/topology/topology1/sof-mt8195-mt6359-rt1019-rt5682.m4 b/tools/topology/topology1/sof-mt8195-mt6359-rt1019-rt5682.m4 new file mode 100644 index 000000000000..a171e83c3988 --- /dev/null +++ b/tools/topology/topology1/sof-mt8195-mt6359-rt1019-rt5682.m4 @@ -0,0 +1,193 @@ +# +# Topology for MT8195 board with mt6359/rt5682/rt1019 +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`afe.m4') +include(`pcm.m4') +include(`buffer.m4') +include(`muxdemux.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include DSP configuration +include(`platform/mediatek/mt8195.m4') + +DEBUG_START + +# +# Define the demux configure +# +dnl Configure demux +dnl name, pipeline_id, routing_matrix_rows +dnl Diagonal 1's in routing matrix mean that every input channel is +dnl copied to corresponding output channels in all output streams. +dnl I.e. row index is the input channel, 1 means it is copied to +dnl corresponding output channel (column index), 0 means it is discarded. +dnl There's a separate matrix for all outputs. +define(matrix1, `ROUTE_MATRIX(1, + `BITS_TO_BYTE(1, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 1, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 1 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,1 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,1 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,1 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,1 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,1)')') + +define(matrix2, `ROUTE_MATRIX(3, + `BITS_TO_BYTE(1, 0, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 1, 0 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 1 ,0 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,1 ,0 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,1 ,0 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,1 ,0 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,1 ,0)', + `BITS_TO_BYTE(0, 0, 0 ,0 ,0 ,0 ,0 ,1)')') + + +ifdef(`GOOGLE_RTC_AUDIO_PROCESSING', `MUXDEMUX_CONFIG(demux_priv_1, 2, LIST_NONEWLINE(`', `matrix1,', `matrix2'))') +ifdef(`GOOGLE_RTC_AUDIO_PROCESSING', `define(`SPK_PERIOD_US', 10000)', `define(`SPK_PERIOD_US', 1000)') + +ifdef(`GOOGLE_RTC_AUDIO_PROCESSING', + `define(`MIC_PERIOD_US', 10000)' + , + `ifdef(`RTNR', +# 5ms period is required for RTNR build 20220728 and later versions + `define(`MIC_PERIOD_US', 5000)', + `define(`MIC_PERIOD_US', 2000)')' +) + +# +# Define the pipelines +# +# PCM16 ---> AFE (Speaker - rt1019) +# PCM17 ---> AFE (Headset playback - rt5682) +# PCM18 <--- AFE (DMIC - MT6365) +# PCM19 <--- AFE (Headset record - rt5682) + + +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 16 using max 2 channels of s16le +# Set 10000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD( + ifdef(`DTS', sof/pipe-eq-iir-dts-codec-playback.m4, + ifdef(`GOOGLE_RTC_AUDIO_PROCESSING', sof/pipe-volume-demux-playback.m4, sof/pipe-passthrough-playback.m4)), + 1, 16, 2, s16le, + SPK_PERIOD_US, 0, 0, + 48000, 48000, 48000) + +# Low Latency playback pipeline 2 on PCM 17 using max 2 channels of s16le +# Set 10000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD( + ifdef(`DTS', sof/pipe-eq-iir-dts-codec-playback.m4, sof/pipe-passthrough-playback.m4), + 2, 17, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 3 on PCM 18 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD( + ifdef(`RTNR', + ifdef(`GOOGLE_RTC_AUDIO_PROCESSING', + sof/pipe-rtnr-google-rtc-audio-processing-capture.m4, + sof/pipe-rtnr-capture.m4), + sof/pipe-passthrough-capture.m4), + 3, 18, 2, s16le, + MIC_PERIOD_US, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 4 on PCM 19 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 19, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl if using Google AEC +ifdef(`GOOGLE_RTC_AUDIO_PROCESSING', +`# Connect demux to capture' +`SectionGraph."PIPE_GOOGLE_RTC_AUDIO_PROCESSING_REF_AEC" {' +` index "0"' +` lines [' +` # mux to capture' +` dapm(N_AEC_REF_BUF, PIPELINE_DEMUX_1)' +` ]' +`}' +dnl else +, `') + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, AFE, 0, AFE_SOF_DL2, + PIPELINE_SOURCE_1, 2, s16le, + SPK_PERIOD_US, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 2, AFE, 1, AFE_SOF_DL3, + PIPELINE_SOURCE_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 3, AFE, 2, AFE_SOF_UL4, + PIPELINE_SINK_3, 2, s16le, + MIC_PERIOD_US, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 4, AFE, 3, AFE_SOF_UL5, + PIPELINE_SINK_4, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +#SCHEDULE_TIME_DOMAIN_DMA +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(SOF_DL2, 16, PIPELINE_PCM_1) +PCM_PLAYBACK_ADD(SOF_DL3, 17, PIPELINE_PCM_2) +PCM_CAPTURE_ADD(SOF_UL4, 18, PIPELINE_PCM_3) +PCM_CAPTURE_ADD(SOF_UL5, 19, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, dai_index, link_id, name, afe_config) + +DAI_CONFIG(AFE, 0, 0, AFE_SOF_DL2, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 0, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 1, 0, AFE_SOF_DL3, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 1, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 2, 0, AFE_SOF_UL4, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 2, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 3, 0, AFE_SOF_UL5, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 3, 48000, 2, s16le))) + +DEBUG_END diff --git a/tools/topology/topology1/sof-mt8196-mt6681.m4 b/tools/topology/topology1/sof-mt8196-mt6681.m4 new file mode 100644 index 000000000000..c406c6d387c8 --- /dev/null +++ b/tools/topology/topology1/sof-mt8196-mt6681.m4 @@ -0,0 +1,153 @@ +# +# Topology for MT8196 board with mt6681 +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`afe.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/mediatek/mt8196.m4') + +# +# Define the pipelines +# +# PCM0 ---> AFE (Speaker - nau8318) +# PCM1 ---> AFE (Headset playback - nau88l25) +# PCM2 <--- AFE (DMIC0 - AP) +# PCM3 <--- AFE (Headset record - nau88l25) +# PCM4 <--- AFE (DMIC1 - AP) + +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) + +define(`ENDPOINT_NAME', `Speakers') +# Low Latency playback pipeline 1 on PCM 16 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD( + ifdef(`DTS', sof/pipe-eq-iir-dts-codec-playback.m4, + ifdef(`WAVES', ifdef(`GOOGLE_CTC', sof/pipe-waves-codec-ctc-playback.m4, + sof/pipe-waves-codec-playback.m4), + ifdef(`GOOGLE_CTC', sof/pipe-ctc-playback.m4, + sof/pipe-passthrough-playback.m4))), + 1, 0, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +define(`ENDPOINT_NAME', `Headphones') +# Low Latency playback pipeline 2 on PCM 17 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`DTS', sof/pipe-eq-iir-dts-codec-playback.m4, ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4)), + 2, 1, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') +# Low Latency capture pipeline 3 on PCM 18 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 2, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 4 on PCM 19 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 3, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 4 on PCM 20 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 5, 4, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + + + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, AFE, 0, AFE_SOF_DL_24CH, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 2, AFE, 1, AFE_SOF_DL1, + PIPELINE_SOURCE_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 3, AFE, 2, AFE_SOF_UL0, + PIPELINE_SINK_3, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 4, AFE, 3, AFE_SOF_UL1, + PIPELINE_SINK_4, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 5, AFE, 4, AFE_SOF_UL2, + PIPELINE_SINK_5, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +#SCHEDULE_TIME_DOMAIN_DMA +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(SOF_DL_24CH, 0, PIPELINE_PCM_1) +PCM_PLAYBACK_ADD(SOF_DL1, 1, PIPELINE_PCM_2) +PCM_CAPTURE_ADD(SOF_UL0, 2, PIPELINE_PCM_3) +PCM_CAPTURE_ADD(SOF_UL1, 3, PIPELINE_PCM_4) +PCM_CAPTURE_ADD(SOF_UL2, 4, PIPELINE_PCM_5) + + +dnl DAI_CONFIG(type, dai_index, link_id, name, afe_config) + +DAI_CONFIG(AFE, 0, 0, AFE_SOF_DL_24CH, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 0, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 1, 0, AFE_SOF_DL1, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 1, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 2, 0, AFE_SOF_UL0, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 2, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 3, 0, AFE_SOF_UL1, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 3, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 4, 0, AFE_SOF_UL2, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 4, 48000, 2, s16le))) + diff --git a/tools/topology/topology1/sof-mt8365-mt6357.m4 b/tools/topology/topology1/sof-mt8365-mt6357.m4 new file mode 100644 index 000000000000..7ba3420d57f9 --- /dev/null +++ b/tools/topology/topology1/sof-mt8365-mt6357.m4 @@ -0,0 +1,128 @@ +# +# Topology for MT8365 board with mt6357 +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`afe.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/mediatek/mt8365.m4') + +# +# Define the pipelines +# +# PCM16 ---> AFE (Speaker - rt1019) +# PCM17 ---> AFE (Headset playback - rt5682) +# PCM18 <--- AFE (DMIC - MT6365) +# PCM19 <--- AFE (Headset record - rt5682) + + +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) + +define(`ENDPOINT_NAME', `Speakers') +# Low Latency playback pipeline 1 on PCM 16 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), + 1, 16, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +define(`ENDPOINT_NAME', `Headphones') +# Low Latency playback pipeline 2 on PCM 17 using max 2 channels of s16le +# Set 1000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(ifdef(`WAVES', sof/pipe-waves-codec-playback.m4, sof/pipe-passthrough-playback.m4), + 2, 17, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) +undefine(`ENDPOINT_NAME') + +# Low Latency capture pipeline 3 on PCM 18 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 18, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Low Latency capture pipeline 4 on PCM 19 using max 2 channels of s16le +# Set 2000us deadline with priority 0 on core 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 4, 19, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core) + + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 1, AFE, 0, AFE_SOF_DL1, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# playback DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 1000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-playback.m4, + 2, AFE, 1, AFE_SOF_DL2, + PIPELINE_SOURCE_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 3, AFE, 2, AFE_SOF_AWB, + PIPELINE_SINK_3, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is AFE using 2 periods +# Buffers use s16le format, with 48 frame per 2000us on core 0 with priority 0 +DAI_ADD(sof/pipe-dai-capture.m4, + 4, AFE, 3, AFE_SOF_VUL, + PIPELINE_SINK_4, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +#SCHEDULE_TIME_DOMAIN_DMA +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) + +# PCM Low Latency, id 0 +PCM_PLAYBACK_ADD(SOF_DL1, 16, PIPELINE_PCM_1) +PCM_PLAYBACK_ADD(SOF_DL2, 17, PIPELINE_PCM_2) +PCM_CAPTURE_ADD(SOF_AWB, 18, PIPELINE_PCM_3) +PCM_CAPTURE_ADD(SOF_VUL, 19, PIPELINE_PCM_4) + +dnl DAI_CONFIG(type, dai_index, link_id, name, afe_config) + +DAI_CONFIG(AFE, 0, 0, AFE_SOF_DL1, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 0, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 1, 0, AFE_SOF_DL2, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 1, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 2, 0, AFE_SOF_AWB, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 2, 48000, 2, s16le))) + +DAI_CONFIG(AFE, 3, 0, AFE_SOF_VUL, + AFE_CONFIG(AFE_CONFIG_DATA(AFE, 3, 48000, 2, s16le))) diff --git a/tools/topology/topology1/sof-rn-rt5682-max98360.m4 b/tools/topology/topology1/sof-rn-rt5682-max98360.m4 new file mode 100644 index 000000000000..103412db299e --- /dev/null +++ b/tools/topology/topology1/sof-rn-rt5682-max98360.m4 @@ -0,0 +1,72 @@ +# +# Topology for generic Renoir with I2S SP and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-sp.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD(sof/pipe-passthrough-playback.m4, + 1, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ACPSP, 0, acp-headset-codec, + PIPELINE_SOURCE_1, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPSP, 0, 0, acp-headset-codec, + ACPSP_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3), + ACPSP_CONFIG_DATA(ACPSP, 0, 48000, 2, 0))) + +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 2, 0, 2, s16le, + 2000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ACPSP, 0, acp-headset-codec, + PIPELINE_SINK_2, 2, s16le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# PCM id 0 +PCM_DUPLEX_ADD(I2SSP, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) + +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 1, 2, s32le, + 2000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, + 3, ACPDMIC, 0, acp-dmic-codec, + PIPELINE_SINK_3, 2, s32le, + 2000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 2))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) diff --git a/tools/topology/topology1/sof-rn-rt5682-rt1019.m4 b/tools/topology/topology1/sof-rn-rt5682-rt1019.m4 new file mode 100644 index 000000000000..5d87210b4fe9 --- /dev/null +++ b/tools/topology/topology1/sof-rn-rt5682-rt1019.m4 @@ -0,0 +1,73 @@ +# +# Topology for generic Renoir with I2S SP and DMIC. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`acp-sp.m4') +include(`acp-dmic.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include ACP DSP configuration +include(`platform/amd/acp.m4') + +# Playback pipeline 1 on PCM 0 using max 2 channels of s16le. +# Schedule 96 frames per 2000us deadline on core 0 with priority 0 +PIPELINE_PCM_ADD( +ifdef(`DTS', sof/pipe-dts-codec-eq-iir-playback.m4, sof/pipe-passthrough-playback.m4), + 1, 0, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) + +# playback DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-playback.m4, + 1, ACPSP, 0, acp-headset-codec, + PIPELINE_SOURCE_1, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +DAI_CONFIG(ACPSP, 0, 0, acp-headset-codec, + ACPSP_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), + ACP_CLOCK(bclk, 3072000, codec_consumer), + ACP_CLOCK(fsync, 48000, codec_consumer), + ACP_TDM(2, 32, 3, 3), + ACPSP_CONFIG_DATA(ACPSP, 0, 48000, 2, 0))) + +# Capture pipeline 2 on PCM 0 using max 2 channels of s16le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 2, 0, 2, s16le, + 1000, 0, 0, + 48000, 48000, 48000) + +# Capture DAI is ACPSP using 2 periods +DAI_ADD(sof/pipe-dai-capture.m4, + 2, ACPSP, 0, acp-headset-codec, + PIPELINE_SINK_2, 2, s16le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +# PCM id 0 +PCM_DUPLEX_ADD(I2SSP, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) + +# Capture pipeline 3 on PCM 1 using max 2 channels of s32le. +PIPELINE_PCM_ADD(sof/pipe-passthrough-capture.m4, + 3, 1, 2, s32le, + 1000, 0, 0, + 48000, 48000, 48000) + +DAI_ADD(sof/pipe-dai-capture.m4, + 3, ACPDMIC, 0, acp-dmic-codec, + PIPELINE_SINK_3, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) + +dnl DAI_CONFIG(type, dai_index, link_id, name, acpdmic_config) +DAI_CONFIG(ACPDMIC, 3, 2, acp-dmic-codec, + ACPDMIC_CONFIG(ACPDMIC_CONFIG_DATA(ACPDMIC, 3, 48000, 2))) + +# PCM id 1 +PCM_CAPTURE_ADD(DMIC, 1, PIPELINE_PCM_3) diff --git a/tools/topology/topology1/sof-smart-amplifier.m4 b/tools/topology/topology1/sof-smart-amplifier.m4 new file mode 100644 index 000000000000..38d4b5872d78 --- /dev/null +++ b/tools/topology/topology1/sof-smart-amplifier.m4 @@ -0,0 +1,246 @@ +# +# Unified topology for smart amplifier implementation. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +ifelse(SDW, `1', +`include(`alh.m4')', +`include(`ssp.m4')') + +# Include Token library +include(`sof/tokens.m4') + +DEBUG_START + +# define the default macros. +# define them in your specific platform .m4 if needed. + +#undefine the DYNAMIC flag (if enabled, save it) for smart amplifier as it uses volatile kcontrols +ifdef(`DYNAMIC', `define(`SAVED_DYNAMIC', DYNAMIC)',`') +undefine(`DYNAMIC') + + +# define(`SMART_AMP_CORE', 1) define the DSP core that the DSM pipeline will be run on, if not done yet +ifdef(`SMART_AMP_CORE',`',`define(`SMART_AMP_CORE', 0)') + +dnl define smart amplifier ALH index + +ifelse(SDW, `1', +` +# ALH related +# define(`SMART_ALH_INDEX', 1) define smart amplifier ALH index +ifdef(`SMART_ALH_INDEX',`',`fatal_error(note: Need to define ALH index for sof-smart-amplifier +)') +ifdef(`SMART_ALH_PLAYBACK_NAME',`',`fatal_error(note: Need to define ALH BE dai_link name for sof-smart-amplifier +)') +ifdef(`SMART_ALH_CAPTURE_NAME',`',`fatal_error(note: Need to define ALH BE dai_link name for sof-smart-amplifier +)') +', +` +# SSP related +# define(`SMART_SSP_INDEX', 1) define smart amplifier SSP index +ifdef(`SMART_SSP_INDEX',`',`fatal_error(note: Need to define SSP index for sof-smart-amplifier +)') +# define(`SMART_SSP_NAME', `SSP1-Codec') define SSP BE dai_link name +ifdef(`SMART_SSP_NAME',`',`fatal_error(note: Need to define SSP BE dai_link name for sof-smart-amplifier +)') +# define(`SMART_SSP_QUIRK', 0) define SSP quirk for special use, e.g. set SSP_QUIRK_LBM to verify +# smart_amp nocodec mode. Set it to 0 by default for normal mode. +ifdef(`SMART_SSP_QUIRK',`',`define(`SMART_SSP_QUIRK', 0)') +# define(`SSP_MCLK', ) define SSP mclk if not done yet +ifdef(`SSP_MCLK',`',`define(`SSP_MCLK', 19200000)') +') + +# define(`SMART_BE_ID', 7) define BE dai_link ID +ifdef(`SMART_BE_ID',`',`fatal_error(note: Need to define SSP BE dai_link ID for sof-smart-amplifier +)') +# Playback related +# define(`SMART_PB_PPL_ID', 1) +ifdef(`SMART_PB_PPL_ID',`',`fatal_error(note: Need to define playback pipeline ID for sof-smart-amplifier +)') +# define(`SMART_PB_CH_NUM', 2) +ifdef(`SMART_PB_CH_NUM',`',`fatal_error(note: Need to define playback channel number for sof-smart-amplifier +)') +define(`SMART_PIPE_SOURCE', concat(`PIPELINE_SOURCE_', SMART_PB_PPL_ID)) +# define(`SMART_TX_CHANNELS', 4) +ifdef(`SMART_TX_CHANNELS',`',`fatal_error(note: Need to define DAI TX channel number for sof-smart-amplifier +)') +# define(`SMART_RX_CHANNELS', 8) +ifdef(`SMART_RX_CHANNELS',`',`fatal_error(note: Need to define DAI RX channel number for sof-smart-amplifier +)') +# define(`SMART_FB_CHANNELS', 4) +ifdef(`SMART_FB_CHANNELS',`',`fatal_error(note: Need to define feedback channel number for sof-smart-amplifier +)') +define(`SMART_PB_PPL_NAME', concat(`PIPELINE_PCM_', SMART_PB_PPL_ID)) +# Ref capture related +# define(`SMART_REF_PPL_ID', 11) +ifdef(`SMART_REF_PPL_ID',`',`fatal_error(note: Need to define Echo Ref pipeline ID for sof-smart-amplifier +)') +# define(`SMART_REF_CH_NUM', 4) +ifdef(`SMART_REF_CH_NUM',`',`fatal_error(note: Need to define Echo Ref channel number for sof-smart-amplifier +)') +define(`SMART_PIPE_SINK', concat(`PIPELINE_SINK_', SMART_REF_PPL_ID)) +# define(`N_SMART_DEMUX', `MUXDEMUX'SMART_REF_PPL_ID`.'$1) +define(`SMART_REF_PPL_NAME', concat(`PIPELINE_PCM_', SMART_REF_PPL_ID)) +# PCM related +# define(`SMART_PCM_ID', 0) +ifdef(`SMART_PCM_ID',`',`fatal_error(note: Need to define PCM ID for sof-smart-amplifier +)') +ifdef(`SMART_PCM_NAME',`',`fatal_error(note: Need to define Speaker PCM name for sof-smart-amplifier +)') + +#The long process time (aprox. 8ms) and process length (16ms in 16k sample rate) of igo_nr starve +#the scheduler and results in SMART_AMP underflow, ending up with smart_amp component reset and close. +#So increase the buffer size of SMART_AMP is necessary. +ifdef(`IGO', `define(`SMART_AMP_PERIOD', 16000)', `define(`SMART_AMP_PERIOD', 1000)') + +ifelse(SDW, `1', +` +# +# Define the pipelines +# +# PCM2 ----> smart_amp ----> ALH(ALH_INDEX) +# ^ +# | +# | +# PCM3 <---- demux <----- ALH(ALH_INDEX + 1) +# +' +,` +# +# Define the pipelines +# +# PCM0 ----> smart_amp ----> SSP(SSP_INDEX) +# ^ +# | +# | +# PCM0 <---- demux <----- SSP(SSP_INDEX) +# +') + +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) + +# Demux 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-smart-amplifier-playback.m4, + SMART_PB_PPL_ID, SMART_PCM_ID, SMART_PB_CH_NUM, s32le, + SMART_AMP_PERIOD, 0, SMART_AMP_CORE, + 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 +ifelse(SDW, `1', +` +PIPELINE_PCM_ADD(sof/pipe-amp-ref-capture.m4, + SMART_REF_PPL_ID, eval(SMART_PCM_ID + 1), SMART_REF_CH_NUM, s32le, + SMART_AMP_PERIOD, 0, 0, + 48000, 48000, 48000) +', +` +PIPELINE_PCM_ADD(sof/pipe-amp-ref-capture.m4, + SMART_REF_PPL_ID, SMART_PCM_ID, SMART_REF_CH_NUM, s32le, + SMART_AMP_PERIOD, 0, SMART_AMP_CORE, + 48000, 48000, 48000) +') + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +ifelse(SDW, `1', +` +# playback DAI is ALH(ALH_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline with priority 0 on core 0 +DAI_ADD(sof/pipe-dai-playback.m4, + SMART_PB_PPL_ID, ALH, SMART_ALH_INDEX, SMART_ALH_PLAYBACK_NAME, + SMART_PIPE_SOURCE, 2, s24le, + SMART_AMP_PERIOD, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is ALH(ALH_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline with priority 0 on core 0 +DAI_ADD(sof/pipe-dai-capture.m4, + SMART_REF_PPL_ID, ALH, eval(SMART_ALH_INDEX + 1), SMART_ALH_CAPTURE_NAME, + SMART_PIPE_SINK, 2, s24le, + SMART_AMP_PERIOD, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) +', +` +# playback DAI is SSP(SPP_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline with priority 0 on core 0 +DAI_ADD(sof/pipe-dai-playback.m4, + SMART_PB_PPL_ID, SSP, SMART_SSP_INDEX, SMART_SSP_NAME, + SMART_PIPE_SOURCE, 2, s32le, + SMART_AMP_PERIOD, 0, SMART_AMP_CORE, SCHEDULE_TIME_DOMAIN_TIMER) + +# capture DAI is SSP(SSP_INDEX) using 2 periods +# Buffers use s32le format, 1000us deadline with priority 0 on core 0 +DAI_ADD(sof/pipe-dai-capture.m4, + SMART_REF_PPL_ID, SSP, SMART_SSP_INDEX, SMART_SSP_NAME, + SMART_PIPE_SINK, 2, s32le, + SMART_AMP_PERIOD, 0, SMART_AMP_CORE, SCHEDULE_TIME_DOMAIN_TIMER) +') + +# Connect demux to smart_amp +ifdef(`N_SMART_REF_BUF',`',`fatal_error(note: Need to define ref buffer name for connection +)') +ifdef(`N_SMART_DEMUX',`',`fatal_error(note: Need to define demux widget name for connection +)') +SectionGraph."PIPE_SMART_AMP" { + index "0" + + lines [ + # demux to smart_amp + dapm(N_SMART_REF_BUF, N_SMART_DEMUX) + ] +} + +# PCM for SMART_AMP Playback and EchoRef. +ifelse(SDW, `1', +` +PCM_PLAYBACK_ADD(SMART_PCM_NAME, SMART_PCM_ID, SMART_PB_PPL_NAME) +PCM_CAPTURE_ADD(Amplifier Reference, eval(SMART_PCM_ID + 1), SMART_REF_PPL_NAME) +', +` +dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +PCM_DUPLEX_ADD(SMART_PCM_NAME, SMART_PCM_ID, SMART_PB_PPL_NAME, SMART_REF_PPL_NAME) +') + +# +# BE configurations - overrides config in ACPI if present +# + +ifelse(SDW, `1', +` +#ALH ALH Pin2 (ID: SMART_BE_ID) +DAI_CONFIG(ALH, SMART_ALH_INDEX, SMART_BE_ID, SMART_ALH_PLAYBACK_NAME, + ALH_CONFIG(ALH_CONFIG_DATA(ALH, SMART_ALH_INDEX, 48000, SMART_TX_CHANNELS))) + +#ALH ALH Pin3 (ID: SMART_BE_ID + 1) +DAI_CONFIG(ALH, eval(SMART_ALH_INDEX + 1), eval(SMART_BE_ID + 1), SMART_ALH_CAPTURE_NAME, + ALH_CONFIG(ALH_CONFIG_DATA(ALH, eval(SMART_ALH_INDEX + 1), 48000, SMART_RX_CHANNELS))) +', +` +#SSP SSP_INDEX (ID: SMART_BE_ID) +DAI_CONFIG(SSP, SMART_SSP_INDEX, SMART_BE_ID, SMART_SSP_NAME, + SSP_CONFIG(DSP_B, SSP_CLOCK(mclk, SSP_MCLK, codec_mclk_in), + SSP_CLOCK(bclk, 12288000, codec_consumer), + SSP_CLOCK(fsync, 48000, codec_consumer), + SSP_TDM(8, 32, 15, 255), + SSP_CONFIG_DATA(SSP, SMART_SSP_INDEX, 32, 0, SMART_SSP_QUIRK))) +') + +#Re-enable DYNAMIC flag if it was enabled for other pipelines +ifdef(`SAVED_DYNAMIC', `define(`DYNAMIC', 1)',`') + +DEBUG_END diff --git a/tools/topology/topology1/sof/pipe-amp-ref-capture.m4 b/tools/topology/topology1/sof/pipe-amp-ref-capture.m4 new file mode 100644 index 000000000000..f605496144bf --- /dev/null +++ b/tools/topology/topology1/sof/pipe-amp-ref-capture.m4 @@ -0,0 +1,125 @@ +# Amplifier feedback reference Demux Pipeline +# +# capture with demux for both echo reference to user space and the feedback to smart amplifier FW algorithm. +# +# Pipeline Endpoints for connection are :- +# +# Capture Demux +# B1 (DAI buffer) +# +# +# | +# host PCM_C <-- B0 <-- Demux(M) <-- B1 <-- DAI +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`muxdemux.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') + +ifdef(`SMART_TX_CHANNELS',`',`fatal_error(note: Need to define DAI TX channel number for sof-smart-amplifier +)') +ifdef(`SMART_RX_CHANNELS',`',`fatal_error(note: Need to define DAI RX channel number for sof-smart-amplifier +)') +ifdef(`SMART_FB_CHANNELS',`',`fatal_error(note: Need to define feedback channel number for sof-smart-amplifier +)') + +ifdef(`SMART_PB_PPL_ID',`',`fatal_error(note: Need to define playback pipeline ID for sof-smart-amplifier +)') +ifdef(`SMART_PB_CH_NUM',`',`fatal_error(note: Need to define playback channel number for sof-smart-amplifier +)') + +ifdef(`SMART_REF_PPL_ID',`',`fatal_error(note: Need to define Echo Ref pipeline ID for sof-smart-amplifier +)') +ifdef(`SMART_REF_CH_NUM',`',`fatal_error(note: Need to define Echo Ref channel number for sof-smart-amplifier +)') + +ifelse(SMART_FB_CHANNELS, `8', +`define(`FB_CHMAP',`0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80')', +`define(`FB_CHMAP',`0x01,0x02,0x04,0x08,0x00,0x00,0x00,0x00')' +) + +ifelse(SMART_REF_CH_NUM, `4', +`define(`REF_CHMAP',`0x01,0x02,0x04,0x08,0x00,0x00,0x00,0x00')', +`define(`REF_CHMAP',`0x01,0x04,0x00,0x00,0x00,0x00,0x00,0x00')' +) + + +# should be aligned with struct sof_mux_config, used for mux input/output configuration. +CONTROLBYTES_PRIV(DEMUX_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x28,0x00,0x00,0x00,0x00,0x60,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` COMP_FORMAT_VALUE(PIPELINE_FORMAT),0x00,DEC2HEX(SMART_RX_CHANNELS),0x00,0x02,0x00,0x00,0x00,' +` DEC2HEX(SMART_PB_PPL_ID),0x00,0x00,0x00,DEC2HEX(SMART_FB_CHANNELS),FB_CHMAP,0x00,0x00,0x00,' +` DEC2HEX(SMART_REF_PPL_ID),0x00,0x00,0x00,DEC2HEX(SMART_REF_CH_NUM),REF_CHMAP,0x00,0x00,0x00"' +) + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(DEMUX, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + DEMUX_priv) +# +# Components and Buffers +# + +# Host "Echo Reference Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Echo Reference Capture, 0, 2, SCHEDULE_CORE) + +# Mux 0 has 2 sink and source periods. +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, LIST(` ', "DEMUX")) + +# define demux widget name for up layer connection +define(`N_SMART_DEMUX',N_MUXDEMUX(0)) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), SMART_RX_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <--B0-- Mux(M) <--B1-- sink DAI0 +# + +P_GRAPH(pipe-amp-ref-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_MUXDEMUX(0))', + `dapm(N_MUXDEMUX(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Echo Reference Capture PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Echo Reference Capture PCM_ID, + CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + 48000, 48000, dnl rate_min, rate_max + SMART_REF_CH_NUM, SMART_REF_CH_NUM, dnl channels_min, channels_max + 2, 16, dnl periods_min, periods_max + 192, 16384, dnl period_size_min, period_size_max + 65536, 65536) + diff --git a/tools/topology/sof/pipe-asrc-capture.m4 b/tools/topology/topology1/sof/pipe-asrc-capture.m4 similarity index 90% rename from tools/topology/sof/pipe-asrc-capture.m4 rename to tools/topology/topology1/sof/pipe-asrc-capture.m4 index 2071c8075627..83360cdb311c 100644 --- a/tools/topology/sof/pipe-asrc-capture.m4 +++ b/tools/topology/topology1/sof/pipe-asrc-capture.m4 @@ -18,7 +18,7 @@ include(`pipeline.m4') # Host "ASRC Capture" PCM # with 0 sink and 3 source periods -W_PCM_CAPTURE(PCM_ID, ASRC Capture, 0, 3) +W_PCM_CAPTURE(PCM_ID, ASRC Capture, 0, 3, SCHEDULE_CORE) # # ASRC Configuration @@ -51,7 +51,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_P <-- B0 <-- ASRC <-- B1 <-- sink DAI -P_GRAPH(pipe-pass-asrc-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-asrc-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_ASRC(0))', @@ -67,7 +67,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), ASRC Capture PCM_ID) # PCM Configuration # -PCM_CAPABILITIES(ASRC Capture PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(ASRC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-asrc-playback.m4 b/tools/topology/topology1/sof/pipe-asrc-playback.m4 similarity index 87% rename from tools/topology/sof/pipe-asrc-playback.m4 rename to tools/topology/topology1/sof/pipe-asrc-playback.m4 index efad075f3f37..9d2ad8b3820d 100644 --- a/tools/topology/sof/pipe-asrc-playback.m4 +++ b/tools/topology/topology1/sof/pipe-asrc-playback.m4 @@ -22,7 +22,7 @@ include(`pipeline.m4') # Host "ASRC Playback" PCM # with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, ASRC Playback, 2, 0) +W_PCM_PLAYBACK(PCM_ID, ASRC Playback, 2, 0, SCHEDULE_CORE) # # ASRC Configuration @@ -32,7 +32,7 @@ define(MY_ASRC_TOKENS, concat(`asrc_tokens_', PIPELINE_ID)) define(MY_ASRC_CONF, concat(`asrc_conf_', PIPELINE_ID)) W_VENDORTUPLES(MY_ASRC_TOKENS, sof_asrc_tokens, LIST(` ', `SOF_TKN_ASRC_RATE_OUT "PIPELINE_RATE"' - ` ', `SOF_TKN_ASRC_ASYNCHRONOUS_MODE "1"' + ` ', `SOF_TKN_ASRC_ASYNCHRONOUS_MODE "0"' ` ', `SOF_TKN_ASRC_OPERATION_MODE "0"')) W_DATA(MY_ASRC_CONF, MY_ASRC_TOKENS) @@ -55,7 +55,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_P --> B0 --> ASRC --> B1 --> sink DAI0 -P_GRAPH(pipe-asrc-playback-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-asrc-playback, PIPELINE_ID, LIST(` ', `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', `dapm(N_ASRC(0), N_BUFFER(0))', @@ -71,7 +71,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), ASRC Playback PCM_ID) # PCM Configuration # -PCM_CAPABILITIES(ASRC Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, +PCM_CAPABILITIES(ASRC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) undefine(`MY_ASRC_TOKENS') diff --git a/tools/topology/sof/pipe-asrc-volume-capture.m4 b/tools/topology/topology1/sof/pipe-asrc-volume-capture.m4 similarity index 91% rename from tools/topology/sof/pipe-asrc-volume-capture.m4 rename to tools/topology/topology1/sof/pipe-asrc-volume-capture.m4 index 129cdb182fc6..4c591d7e10c5 100644 --- a/tools/topology/sof/pipe-asrc-volume-capture.m4 +++ b/tools/topology/topology1/sof/pipe-asrc-volume-capture.m4 @@ -27,7 +27,7 @@ C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # Volume Configuration define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) @@ -45,7 +45,7 @@ W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) # Host "Passthrough Capture" PCM # with 0 sink and 3 source periods -W_PCM_CAPTURE(PCM_ID, ASRC Capture, 0, 3) +W_PCM_CAPTURE(PCM_ID, ASRC Capture, 0, 3, SCHEDULE_CORE) # # ASRC Configuration @@ -68,7 +68,7 @@ W_DATA(MY_ASRC_CONF, MY_ASRC_TOKENS) W_ASRC(0, PIPELINE_FORMAT, 3, 3, MY_ASRC_CONF) # "Volume" has 3 sink and x source periods -W_PGA(0, PIPELINE_FORMAT, 3, DAI_PERIODS, MY_PGA_CONF, +W_PGA(0, PIPELINE_FORMAT, 3, DAI_PERIODS, MY_PGA_CONF, SCHEDULE_CORE, LIST(` ', "PIPELINE_ID Master Capture Volume")) # Capture Buffers @@ -90,7 +90,7 @@ W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_C <-- B0 <-- ASRC <-- B1 <-- PGA <-- B2 <-- sink DAI0 -P_GRAPH(pipe-pass-src-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-asrc-volume-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_ASRC(0))', @@ -109,7 +109,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), # PCM Configuration # -PCM_CAPABILITIES(ASRC Capture PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(ASRC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-asrc-volume-playback.m4 b/tools/topology/topology1/sof/pipe-asrc-volume-playback.m4 similarity index 85% rename from tools/topology/sof/pipe-asrc-volume-playback.m4 rename to tools/topology/topology1/sof/pipe-asrc-volume-playback.m4 index 141e7c5ff63a..a0439a79a772 100644 --- a/tools/topology/sof/pipe-asrc-volume-playback.m4 +++ b/tools/topology/topology1/sof/pipe-asrc-volume-playback.m4 @@ -26,7 +26,7 @@ C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # # Components and Buffers @@ -34,7 +34,7 @@ C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, # Host "ASRC Playback" PCM # with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, ASRC Playback, 2, 0) +W_PCM_PLAYBACK(PCM_ID, ASRC Playback, 2, 0, SCHEDULE_CORE) # # ASRC Configuration @@ -57,13 +57,13 @@ W_ASRC(0, PIPELINE_FORMAT, 2, 2, MY_ASRC_CONF) define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) define(MY_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) W_VENDORTUPLES(MY_PGA_TOKENS, sof_volume_tokens, -LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) # "Volume" has x sink and 2 source periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, MY_PGA_CONF, - LIST(` ', "PIPELINE_ID Master Playback Volume")) +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, MY_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) # Playback Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, @@ -84,7 +84,7 @@ W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_P --> B0 --> ASRC --> B1 --> PGA --> B2 --> sink DAI0 -P_GRAPH(pipe-asrc-volume-playback-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-asrc-volume-playback, PIPELINE_ID, LIST(` ', `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', `dapm(N_ASRC(0), N_BUFFER(0))', @@ -102,7 +102,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), ASRC Playback PCM_ID) # PCM Configuration # -PCM_CAPABILITIES(ASRC Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, +PCM_CAPABILITIES(ASRC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) undefine(`MY_ASRC_TOKENS') diff --git a/tools/topology/topology1/sof/pipe-codec-adapter-capture.m4 b/tools/topology/topology1/sof/pipe-codec-adapter-capture.m4 new file mode 100644 index 000000000000..e5e5c4cda3a0 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-codec-adapter-capture.m4 @@ -0,0 +1,115 @@ +# Low Latency Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- CODEC_ADAPTER <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') + +# +# Controls +# + +# For codec developers, please define the following control bytes of setup config and runtime params +# and the corresponding max bytenum on your own. + +# Codec Adapter setup config control bytes (little endian) +# : bytes "abi_header, [codec_param0, codec_param1...]" +# - 32 bytes abi_header: you could get by command "sof-ctl -t 0 -g <payload_size> -b" +# - [0:3]: magic number 0x00464f53 +# - [4:7]: type 0 +# - [8:11]: payload size in bytes (not including abi header bytes) +# - [12:15]: abi 3.1.0 +# - [16:31]: reserved 0s +# - (optional) 12+ bytes codec_param: codec TLV parameters container, for more details please refer +# struct codec_param under audio/codec_adapter/codec/generic.h +# - [0:1]: param ID +# - [2:3]: codec ID (when supporting multiple codecs, 0 otherwise) +# - [4:7]: size in bytes (ID + size + data) +# - [8:n-1]: data[], the param data +ifdef(`CA_SETUP_CONTROLBYTES',`', `define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +)') +ifdef(`CA_SETUP_CONTROLBYTES_MAX',`', `define(`CA_SETUP_CONTROLBYTES_MAX', 176)') + +# For codec developers, rename bytes control names if necessary. +ifdef(`CA_SETUP_CONTROLBYTES_NAME',`', + `define(`CA_SETUP_CONTROLBYTES_NAME', `CA Setup Config')') + +define(CA_SETUP_CONFIG, concat(`ca_setup_config_', PIPELINE_ID)) +define(CA_SETUP_CONTROLBYTES_NAME_PIPE, concat(CA_SETUP_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter setup config +CONTROLBYTES_PRIV(CA_SETUP_CONFIG, CA_SETUP_CONTROLBYTES) + +# Codec adapter Bytes control for setup config +C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_SETUP_CONTROLBYTES_MAX), + , + CA_SETUP_CONFIG) + +# +# Components and Buffers +# + +# For codec developers, please define the schedule core of codec adapter if it you would like it to +# be different from SCHEDULE_CORE. +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Capture with codec adapter" PCM +# with 0 sink and DAI_PERIODS source periods +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, DAI_PERIODS, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- CODEC_ADAPTER <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-codec-adapter-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_CODEC_ADAPTER(0))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') diff --git a/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 b/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 new file mode 100644 index 000000000000..dcfe4d75dbe6 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 @@ -0,0 +1,116 @@ +# Low Latency Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> CODEC_ADAPTER -> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') + +# +# Controls +# + +# For codec developers, please define the following control bytes of setup config and runtime params +# and the corresponding max bytenum on your own. + +# Codec Adapter setup config control bytes (little endian) +# : bytes "abi_header, [codec_param0, codec_param1...]" +# - 32 bytes abi_header: you could get by command "sof-ctl -t 0 -g <payload_size> -b" +# - [0:3]: magic number 0x00464f53 +# - [4:7]: type 0 +# - [8:11]: payload size in bytes (not including abi header bytes) +# - [12:15]: abi 3.1.0 +# - [16:31]: reserved 0s +# - (optional) 12+ bytes codec_param: codec TLV parameters container, for more details please refer +# struct codec_param under audio/codec_adapter/codec/generic.h +# - [0:1]: param ID +# - [2:3]: codec ID (when supporting multiple codecs, 0 otherwise) +# - [4:7]: size in bytes (ID + size + data) +# - [8:n-1]: data[], the param data +ifdef(`CA_SETUP_CONTROLBYTES',`', `define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +)') +ifdef(`CA_SETUP_CONTROLBYTES_MAX',`', `define(`CA_SETUP_CONTROLBYTES_MAX', 176)') + +# For codec developers, rename bytes control names if necessary. +ifdef(`CA_SETUP_CONTROLBYTES_NAME',`', + `define(`CA_SETUP_CONTROLBYTES_NAME', `CA Setup Config')') + +define(CA_SETUP_CONFIG, concat(`ca_setup_config_', PIPELINE_ID)) +define(CA_SETUP_CONTROLBYTES_NAME_PIPE, concat(CA_SETUP_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter setup config +CONTROLBYTES_PRIV(CA_SETUP_CONFIG, CA_SETUP_CONTROLBYTES) + +# Codec adapter Bytes control for setup config +C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_SETUP_CONTROLBYTES_MAX), + , + CA_SETUP_CONFIG) + +# +# Components and Buffers +# + +# For codec developers, please define the schedule core of codec adapter if it you would like it to +# be different from SCHEDULE_CORE. +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> CODEC_ADAPTER -> B1 --> sink DAI0 + +P_GRAPH(pipe-codec-adapter-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') diff --git a/tools/topology/topology1/sof/pipe-crossover-playback.m4 b/tools/topology/topology1/sof/pipe-crossover-playback.m4 new file mode 100644 index 000000000000..006201eac4ae --- /dev/null +++ b/tools/topology/topology1/sof/pipe-crossover-playback.m4 @@ -0,0 +1,87 @@ +# Crossover Volume Pipeline +# +# Low Latency Playback with demux and volume. +# +# Pipeline Endpoints for connection are : +# +# B2 (DAI buffer) +# Playback Crossover +# +# host PCM_P -- B0 --> Crossover 0 --> B1 ---> DAI0 +# | +# pipeline n+1 --> DAI + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`crossover.m4') +include(`bytecontrol.m4') + +# +# Controls for Crossover +# + +define(CROSSOVER_priv, concat(`crossover_bytes_', PIPELINE_ID)) +define(MY_CROSSOVER_CTRL, concat(`crossover_control_', PIPELINE_ID)) + +# define filter, default is crossover_coef_default.m4 +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, crossover_coef_default.m4)') +include(PIPELINE_FILTER1) + +C_CONTROLBYTES(MY_CROSSOVER_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + CROSSOVER_priv) + +# +# Components and Buffers +# + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0) + +# Crossover filter has 2 sink and source periods. TODO for controls +W_CROSSOVER(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "MY_CROSSOVER_CTRL")) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + + +# +# Pipeline Graph +# host PCM_P -- B0 --> Crossover 0 --> B1 ---> DAI +# | +# pipeline n+1 --> DAI + +P_GRAPH(pipe-crossover-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CROSSOVER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CROSSOVER(0))')) +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_CROSSOVER_', PIPELINE_ID), N_CROSSOVER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Low Latency Playback PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_CROSSOVER_CTRL') +undefine(`CROSSOVER_priv') diff --git a/tools/topology/topology1/sof/pipe-ctc-playback.m4 b/tools/topology/topology1/sof/pipe-ctc-playback.m4 new file mode 100644 index 000000000000..ae34f7fb200f --- /dev/null +++ b/tools/topology/topology1/sof/pipe-ctc-playback.m4 @@ -0,0 +1,94 @@ +# CTC Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> CTC --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`google_ctc_audio_processing.m4') + +# +# Controls +# + +# Host "Playback with codec adapter" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, CTC Processing Playback, 2, 0, SCHEDULE_CORE) + +define(DEF_CTC_PRIV, concat(`ctc_priv_', PIPELINE_ID)) +define(DEF_CTC_BYTES, concat(`ctc_bytes_', PIPELINE_ID)) +include(`google_ctc_audio_processing_coef_default.m4') + +# CTC Bytes control +C_CONTROLBYTES(DEF_CTC_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(void, 4244), + , + DEF_CTC_PRIV) + +define(DEF_CTC_SWITCH, concat(`ctc_enable_', PIPELINE_ID)) +define(`CONTROL_NAME', `DEF_CTC_SWITCH') +C_CONTROLMIXER(DEF_CTC_SWITCH, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# +# Components and Buffers +# + +W_GOOGLE_CTC_AUDIO_PROCESSING(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_CTC_BYTES"), + LIST(` ', "DEF_CTC_SWITCH")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> CTC -> B1 --> sink DAI0 + +P_GRAPH(pipe-ctc-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_GOOGLE_CTC_AUDIO_PROCESSING(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_GOOGLE_CTC_AUDIO_PROCESSING(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), CTC Processing Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(CTC Processing Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_CTC_PRIV') +undefine(`DEF_CTC_BYTES') +undefine(`DEF_CTC_SWITCH') diff --git a/tools/topology/sof/pipe-dai-capture.m4 b/tools/topology/topology1/sof/pipe-dai-capture.m4 similarity index 96% rename from tools/topology/sof/pipe-dai-capture.m4 rename to tools/topology/topology1/sof/pipe-dai-capture.m4 index 40d2daf47437..39813f8b968f 100644 --- a/tools/topology/sof/pipe-dai-capture.m4 +++ b/tools/topology/topology1/sof/pipe-dai-capture.m4 @@ -8,7 +8,7 @@ include(`pipeline.m4') # # DAI definitions # -W_DAI_IN(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, DAI_PERIODS, 0) +W_DAI_IN(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, DAI_PERIODS, 0, SCHEDULE_CORE) # # DAI pipeline - always use 0 for DAIs diff --git a/tools/topology/sof/pipe-dai-endpoint.m4 b/tools/topology/topology1/sof/pipe-dai-endpoint.m4 similarity index 100% rename from tools/topology/sof/pipe-dai-endpoint.m4 rename to tools/topology/topology1/sof/pipe-dai-endpoint.m4 diff --git a/tools/topology/sof/pipe-dai-playback.m4 b/tools/topology/topology1/sof/pipe-dai-playback.m4 similarity index 96% rename from tools/topology/sof/pipe-dai-playback.m4 rename to tools/topology/topology1/sof/pipe-dai-playback.m4 index 47098bdaef2e..7618ede8dfe9 100644 --- a/tools/topology/sof/pipe-dai-playback.m4 +++ b/tools/topology/topology1/sof/pipe-dai-playback.m4 @@ -8,7 +8,7 @@ include(`pipeline.m4') # # DAI definitions # -W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS) +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) # # DAI pipeline - always use 0 for DAIs diff --git a/tools/topology/sof/pipe-dai-sched-playback.m4 b/tools/topology/topology1/sof/pipe-dai-sched-playback.m4 similarity index 100% rename from tools/topology/sof/pipe-dai-sched-playback.m4 rename to tools/topology/topology1/sof/pipe-dai-sched-playback.m4 diff --git a/tools/topology/topology1/sof/pipe-dcblock-capture.m4 b/tools/topology/topology1/sof/pipe-dcblock-capture.m4 new file mode 100644 index 000000000000..cdcec7eaa94a --- /dev/null +++ b/tools/topology/topology1/sof/pipe-dcblock-capture.m4 @@ -0,0 +1,81 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- DC Block <-- sink DAI + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`dcblock.m4') + +# +# Components and Buffers +# + +# Host "DC Block Capture" PCM +# with 0 sink and 3 source periods +W_PCM_CAPTURE(PCM_ID, DC Block Capture, 0, 3, SCHEDULE_CORE) + +define(DCBLOCK_priv, concat(`dcblock_bytes_', PIPELINE_ID)) +define(MY_DCBLOCK_CTRL, concat(`dcblock_control_', PIPELINE_ID)) +include(`dcblock_coef_default.m4') +# DC Block Bytes control with max value of 156 +# The max size needs to also take into account the space required to hold the control data IPC message +# struct sof_ipc_ctrl_data requires 92 bytes +# DCBLOCK priv in dcblock_coef_default.m4 (ABI header (32 bytes) + 8 dwords) requires 64 bytes +# Therefore at least 156 bytes are required for this kcontrol +# Any value lower than that would end up in a topology load error + C_CONTROLBYTES(MY_DCBLOCK_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 156), + , + DCBLOCK_priv) + +# "DC Block" has 2 sink periods and 2 source periods +W_DCBLOCK(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_DCBLOCK_CTRL")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- DC Block <-- B1 <-- sink DAI + +P_GRAPH(pipe-dcblock-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_DCBLOCK(0))', + `dapm(N_DCBLOCK(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), DC Block Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(DC Block Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, + 16384, 65536, 65536) + +undefine(`MY_DCBLOCK_CTRL') +undefine(`DCBLOCK_priv') diff --git a/tools/topology/topology1/sof/pipe-dcblock-playback.m4 b/tools/topology/topology1/sof/pipe-dcblock-playback.m4 new file mode 100644 index 000000000000..e7ad2cfd0021 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-dcblock-playback.m4 @@ -0,0 +1,88 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> DC Block --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`dcblock.m4') + +# +# Controls +# + +# +# Components and Buffers +# + +# Host "DC Block Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, DC Block Playback, 2, 0, SCHEDULE_CORE) + +# +# DC Block Configuration +# + +define(DCBLOCK_priv, concat(`dcblock_bytes_', PIPELINE_ID)) +define(MY_DCBLOCK_CTRL, concat(`dcblock_control_', PIPELINE_ID)) +include(`dcblock_coef_default.m4') +# DC Block Bytes control with max value of 156 +# The max size needs to also take into account the space required to hold the control data IPC message +# struct sof_ipc_ctrl_data requires 92 bytes +# DCBLOCK priv in dcblock_coef_default.m4 (ABI header (32 bytes) + 8 dwords) requires 64 bytes +# Therefore at least 156 bytes are required for this kcontrol +# Any value lower than that would end up in a topology load error + C_CONTROLBYTES(MY_DCBLOCK_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 156), + , + DCBLOCK_priv) + +# "DC Block" has 2 sink periods and 2 source periods +W_DCBLOCK(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_DCBLOCK_CTRL")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> DC Block --> B1 --> sink DAI0 + +P_GRAPH(pipe-dcblock-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_DCBLOCK(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_DCBLOCK(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), DC Block Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(DC Block Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_DCBLOCK_CTRL') +undefine(`DCBLOCK_priv') diff --git a/tools/topology/topology1/sof/pipe-dcblock-volume-playback.m4 b/tools/topology/topology1/sof/pipe-dcblock-volume-playback.m4 new file mode 100644 index 000000000000..300f7f031c39 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-dcblock-volume-playback.m4 @@ -0,0 +1,113 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> DCBLOCK 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`dcblock.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# +define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(MY_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) +W_VENDORTUPLES(MY_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) + +define(DCBLOCK_priv, concat(`dcblock_bytes_', PIPELINE_ID)) +define(MY_DCBLOCK_CTRL, concat(`dcblock_control_', PIPELINE_ID)) +include(`dcblock_coef_default.m4') +# DC Block Bytes control with max value of 156 +# The max size needs to also take into account the space required to hold the control data IPC message +# struct sof_ipc_ctrl_data requires 92 bytes +# DCBLOCK priv in dcblock_coef_default.m4 (ABI header (32 bytes) + 8 dwords) requires 64 bytes +# Therefore at least 156 bytes are required for this kcontrol +# Any value lower than that would end up in a topology load error + C_CONTROLBYTES(MY_DCBLOCK_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 156), + , + DCBLOCK_priv) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, SCHEDULE_CORE) + + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, MY_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# "DC Block" has 2 sink periods and 2 source periods +W_DCBLOCK(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_DCBLOCK_CTRL")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> DCBLOCK 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 +P_GRAPH(pipe-dcblock-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_DCBLOCK(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_DCBLOCK(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_DCBLOCK_CTRL') +undefine(`DCBLOCK_priv') +undefine(`MY_PGA_CONF') +undefine(`MY_PGA_TOKENS') diff --git a/tools/topology/topology1/sof/pipe-demux-eq-iir-playback.m4 b/tools/topology/topology1/sof/pipe-demux-eq-iir-playback.m4 new file mode 100644 index 000000000000..951c6cc115d7 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-demux-eq-iir-playback.m4 @@ -0,0 +1,93 @@ +# Demux EQ band split pipeline +# +# host PCM_P --B0--> demux(M) --B1--> eq_iir --B2--> sink DAI0 +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`muxdemux.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + +# EQ IIR Bytes control +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_bandsplit.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_bandsplit.m4)') +include(PIPELINE_FILTER1) + +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Speaker Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Speaker Playback, 2, 0, SCHEDULE_CORE) + +# "EQ IIR" has x sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Mux 0 has 2 sink and source periods. +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), 4, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --B0--> Demux(M) --B1--> eq_iir --B2--> sink DAI0 + +P_GRAPH(pipe-demux-eq-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_MUXDEMUX(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_MUXDEMUX(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_EQ_IIR(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Speaker Playback PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Speaker Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/sof/pipe-detect.m4 b/tools/topology/topology1/sof/pipe-detect.m4 similarity index 93% rename from tools/topology/sof/pipe-detect.m4 rename to tools/topology/topology1/sof/pipe-detect.m4 index 01e755927867..8dc11366713e 100644 --- a/tools/topology/sof/pipe-detect.m4 +++ b/tools/topology/topology1/sof/pipe-detect.m4 @@ -75,9 +75,11 @@ C_CONTROLBYTES(Hotword Model, PIPELINE_ID, # # "Detect 0" has 2 sink period and 0 source periods -W_DETECT(0, PIPELINE_FORMAT, 0, 2, KEYWORD, N_STS(PCM_ID), LIST(` ', "Detector Config", "Hotword Model")) +W_DETECT(0, PIPELINE_FORMAT, 0, 2, KEYWORD, N_STS(PCM_ID), SCHEDULE_CORE, + LIST(` ', "Detector Config", "Hotword Model")) -W_SELECTOR(0, PIPELINE_FORMAT, 2, 2, LIST(` ', "SELECTOR")) +W_SELECTOR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "SELECTOR")) # Capture Buffers W_BUFFER(1, COMP_BUFFER_SIZE(2, @@ -99,7 +101,7 @@ W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDU # # Detect 0 <-- B2 <-- Channel Selector 0 <-- B1 -P_GRAPH(pipe-detect-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-detect, PIPELINE_ID, LIST(` ', `dapm(DETECT SINK PIPELINE_ID, N_DETECT(0))', `dapm(N_DETECT(0), N_BUFFER(2))', diff --git a/tools/topology/topology1/sof/pipe-drc-capture.m4 b/tools/topology/topology1/sof/pipe-drc-capture.m4 new file mode 100644 index 000000000000..34bbabbf08a1 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-drc-capture.m4 @@ -0,0 +1,75 @@ +# Dynamic Range Compressor with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P <-- B0 <-- DRC <-- B1 <-- sink DAI + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`drc.m4') + +# +# Components and Buffers +# + +# Host "DRC Capture" PCM +# with 0 sink and 3 source periods +W_PCM_CAPTURE(PCM_ID, DRC Capture, 0, 3, SCHEDULE_CORE) + +define(DRC_priv, concat(`drc_bytes_', PIPELINE_ID)) +define(MY_DRC_CTRL, concat(`drc_control_', PIPELINE_ID)) +include(`drc_coef_default.m4') +C_CONTROLBYTES(MY_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DRC_priv) + +# "DRC" has 2 sink periods and 2 source periods +W_DRC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_DRC_CTRL")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- DRC <-- B1 <-- sink DAI + +P_GRAPH(pipe-drc-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_DRC(0))', + `dapm(N_DRC(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), DRC Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(DRC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, + 16384, 65536, 65536) + +undefine(`MY_DRC_CTRL') +undefine(`DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-drc-eq-volume-demux-playback.m4 b/tools/topology/topology1/sof/pipe-drc-eq-volume-demux-playback.m4 new file mode 100644 index 000000000000..ecd3954c68f9 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-drc-eq-volume-demux-playback.m4 @@ -0,0 +1,173 @@ +# Demux DRC/EQ Volume Pipeline +# +# DRC EQ Playback with demux and 3-band drc, eq-iir, and volume. +# +# Pipeline Endpoints for connection are :- +# +# Playback Demux +# B4 (DAI buffer) +# +# +# host PCM_P --B0--> multiband_drc --B1--> eq_iir --B2--> volume --B3--> Demux(M) --B4--> sink DAI0 +# | +# pipeline n+1 --> DAI +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`muxdemux.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`multiband_drc.m4') +include(`eq_iir.m4') + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + +# 3-band DRC Bytes control +define(MULTIBAND_DRC_priv, concat(`multiband_drc_bytes_', PIPELINE_ID)) +define(MY_MULTIBAND_DRC_CTRL, concat(`multiband_drc_control_', PIPELINE_ID)) +include(`multiband_drc_coef_default.m4') +C_CONTROLBYTES(MY_MULTIBAND_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + MULTIBAND_DRC_priv) + +# DRC Enable switch +define(MY_MULTIBAND_DRC_ENABLE, concat(`multiband_drc_enable_', PIPELINE_ID)) +define(`CONTROL_NAME', `MY_MULTIBAND_DRC_ENABLE') +C_CONTROLMIXER(MY_MULTIBAND_DRC_ENABLE, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# EQ IIR Bytes control +define(DEF_EQIIR_PRIV, concat(`eq_iir_bytes_', PIPELINE_ID)) +define(MY_EQIIR_CTRL, concat(`eq_iir_control_', PIPELINE_ID)) +include(`eq_iir_coef_pass.m4') +C_CONTROLBYTES(MY_EQIIR_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "DRC EQ Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, DRC EQ Playback, 2, 0, SCHEDULE_CORE) + +# "MULTIBAND_DRC" has 2 sink periods and 2 source periods +W_MULTIBAND_DRC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_MULTIBAND_DRC_CTRL"), + LIST(` ', "MY_MULTIBAND_DRC_ENABLE")) + +# "EQ IIR" has x sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_EQIIR_CTRL")) + +# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong +W_PGA(1, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# Mux 0 has 2 sink and source periods. +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(4, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --B0--> multiband_drc --B1--> eq_iir --B2--> volume --B3--> Demux(M) --B4--> sink DAI0 + +P_GRAPH(pipe-drc-eq-volume-demux-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_MULTIBAND_DRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_MULTIBAND_DRC(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_EQ_IIR(0))', + `dapm(N_PGA(1), N_BUFFER(2))', + `dapm(N_BUFFER(3), N_PGA(1))', + `dapm(N_MUXDEMUX(0), N_BUFFER(3))', + `dapm(N_BUFFER(4), N_MUXDEMUX(0))')) +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(4)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), DRC EQ Playback PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(DRC EQ Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`MY_EQIIR_CTRL') +undefine(`DEF_EQIIR_PRIV') +undefine(`MY_MULTIBAND_DRC_ENABLE') +undefine(`MY_MULTIBAND_DRC_CTRL') +undefine(`MULTIBAND_DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-drc-playback.m4 b/tools/topology/topology1/sof/pipe-drc-playback.m4 new file mode 100644 index 000000000000..3c96e32326b6 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-drc-playback.m4 @@ -0,0 +1,82 @@ +# Dynamic Range Compressor with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> DRC --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`drc.m4') + +# +# Controls +# + +# +# Components and Buffers +# + +# Host "DRC Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, DRC Playback, 2, 0, SCHEDULE_CORE) + +# +# DRC Configuration +# + +define(DRC_priv, concat(`drc_bytes_', PIPELINE_ID)) +define(MY_DRC_CTRL, concat(`drc_control_', PIPELINE_ID)) +include(`drc_coef_speaker_default.m4') +C_CONTROLBYTES(MY_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DRC_priv) + +# "DRC" has 2 sink periods and 2 source periods +W_DRC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_DRC_CTRL")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> DRC --> B1 --> sink DAI0 + +P_GRAPH(pipe-drc-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_DRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_DRC(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), DRC Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(DRC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_DRC_CTRL') +undefine(`DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-dts-codec-eq-iir-playback.m4 b/tools/topology/topology1/sof/pipe-dts-codec-eq-iir-playback.m4 new file mode 100644 index 000000000000..a38aa9e782cd --- /dev/null +++ b/tools/topology/topology1/sof/pipe-dts-codec-eq-iir-playback.m4 @@ -0,0 +1,108 @@ +# Low Latency Passthrough with DTS codec Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> DTS Codec --> B1 --> EQ 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# + +# +# DTS Codec +# + +include(`dts_codec_adapter.m4') + +# +# IIR EQ +# +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_flat.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_flat.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> DTS Codec --> B1 --> EQ 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-pass-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_EQ_IIR(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-dts-codec-playback.m4 b/tools/topology/topology1/sof/pipe-dts-codec-playback.m4 new file mode 100644 index 000000000000..39a42099fab3 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-dts-codec-playback.m4 @@ -0,0 +1,76 @@ +# Low Latency Passthrough with DTS codec Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> DTS codec --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') + +# +# Controls +# + +# +# DTS Codec +# + +include(`dts_codec_adapter.m4') + +# +# Components and Buffers +# + +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> CODEC_ADAPTER -> B1 --> sink DAI0 + +P_GRAPH(pipe-pass-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') diff --git a/tools/topology/topology1/sof/pipe-eap-playback.m4 b/tools/topology/topology1/sof/pipe-eap-playback.m4 new file mode 100644 index 000000000000..fe71aba97652 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eap-playback.m4 @@ -0,0 +1,70 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EAP 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`pipeline.m4') +include(`eap.m4') + +# +# Controls +# +# Include defines for EAP controls +include(`eap_controls.m4') + +# +# Components and Buffers +# +# Host "EAP Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, EAP Playback, 2, 0) + +# "EAP 0" has x sink period and 2 source periods +W_EAP(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EAP_CFG")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EAP --> B1 --> sink DAI0 +P_GRAPH(pipe-eap-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EAP(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EAP(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + EAP Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(EAP Playback PCM_ID, `S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DAI_EAP_CFG') diff --git a/tools/topology/topology1/sof/pipe-echo-ref-dai-capture.m4 b/tools/topology/topology1/sof/pipe-echo-ref-dai-capture.m4 new file mode 100644 index 000000000000..1a28ca547b29 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-echo-ref-dai-capture.m4 @@ -0,0 +1,23 @@ +# +# The pipeline for echo reference feature, it is used +# for the capture DAI to dock. +# +# No connections in this pipeline. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# DAI definitions +# +W_DAI_IN(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, DAI_PERIODS, 0, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs +# +W_PIPELINE(N_DAI_IN, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +indir(`define', concat(`PIPELINE_SCHED_COMP_', PIPELINE_ID), N_DAI_IN) diff --git a/tools/topology/topology1/sof/pipe-eq-fir-capture.m4 b/tools/topology/topology1/sof/pipe-eq-fir-capture.m4 new file mode 100644 index 000000000000..6404f29546ad --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-fir-capture.m4 @@ -0,0 +1,89 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <--EQ_FIR 0 <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_fir.m4') + +# +# Controls +# + +define(DEF_EQFIR_COEF, concat(`eqfir_coef_', PIPELINE_ID)) +define(DEF_EQFIR_PRIV, concat(`eqfir_priv_', PIPELINE_ID)) + +# define filter. eq_fir_coef_pass.m4 is set by default +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_fir_coef_pass.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +define(MY_CONTROLBYTES, concat(`EQFIR_CONTROLBYTES_', PIPELINE_ID)) +C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 4096), + , + DEF_EQFIR_PRIV) + +# +# Components and Buffers +# + +# Host "EQ FIR Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, EQ FIR Capture, 0, 2, SCHEDULE_CORE) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "MY_CONTROLBYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <--EQ_FIR 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-eq-fir-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_EQ_FIR(0))', + `dapm(N_EQ_FIR(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), EQ FIR Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(EQ FIR Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_CONTROLBYTES') +undefine(`MY_EQFIR_COEF') +undefine(`MY_EQFIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-fir-playback.m4 b/tools/topology/topology1/sof/pipe-eq-fir-playback.m4 new file mode 100644 index 000000000000..6d8c4bb0bf7a --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-fir-playback.m4 @@ -0,0 +1,89 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ_FIR 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_fir.m4') + +# +# Controls +# + +define(DEF_EQFIR_COEF, concat(`eqfir_coef_', PIPELINE_ID)) +define(DEF_EQFIR_PRIV, concat(`eqfir_priv_', PIPELINE_ID)) + +# define filter. eq_fir_coef_pass.m4 is set by default +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_fir_coef_pass.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +define(MY_CONTROLBYTES, concat(`EQFIR_CONTROLBYTES_', PIPELINE_ID)) +C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 4096), + , + DEF_EQFIR_PRIV) + +# +# Components and Buffers +# + +# Host "EQ FIR Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, EQ FIR Playback, 2, 0, SCHEDULE_CORE) + +# "EQ 0" has x sink period and 2 source periods +W_EQ_FIR(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "MY_CONTROLBYTES")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host host PCM_P --> B0 --> EQ_FIR 0 --> B1 --> sink DAI0 + +P_GRAPH(pipe-eq-fir-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_FIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_FIR(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + EQ FIR Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(EQ FIR Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_CONTROLBYTES') +undefine(`MY_EQFIR_COEF') +undefine(`MY_EQFIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-fir-volume-capture.m4 b/tools/topology/topology1/sof/pipe-eq-fir-volume-capture.m4 new file mode 100644 index 000000000000..350b90af0673 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-fir-volume-capture.m4 @@ -0,0 +1,129 @@ +# Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- EQ-FIR <-- B2 <-- source DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_fir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume Configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# FIR EQ +# + +define(DEF_EQFIR_COEF, concat(`eqfir_coef_', PIPELINE_ID)) +define(DEF_EQFIR_PRIV, concat(`eqfir_priv_', PIPELINE_ID)) + +# define filter. eq_fir_coef_pass.m4 is set by default +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_fir_coef_pass.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQFIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 4096), + , + DEF_EQFIR_PRIV) + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 sink and 2 source periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume")) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQFIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- EQ-FIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-eq-fir-volume-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_FIR(0))', + `dapm(N_EQ_FIR(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQFIR_COEF') +undefine(`DEF_EQFIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-fir-volume-playback.m4 b/tools/topology/topology1/sof/pipe-eq-fir-volume-playback.m4 new file mode 100644 index 000000000000..17592986b758 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-fir-volume-playback.m4 @@ -0,0 +1,115 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_fir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +define(DEF_EQFIR_COEF, concat(`eqfir_coef_', PIPELINE_ID)) +define(DEF_EQFIR_PRIV, concat(`eqfir_priv_', PIPELINE_ID)) + +# define filter. eq_fir_coef_pass.m4 is set by default +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_fir_coef_pass.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQFIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 4096), + , + DEF_EQFIR_PRIV) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, SCHEDULE_CORE) + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQFIR_COEF")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-eq-fir-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_FIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_FIR(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQFIR_COEF') +undefine(`DEF_EQFIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-capture.m4 b/tools/topology/topology1/sof/pipe-eq-iir-capture.m4 new file mode 100644 index 000000000000..c9ca12117c36 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-capture.m4 @@ -0,0 +1,88 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <--EQ_IIR 0 <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use 40 Hz highpass response with 0 dB gain +# TODO: need to implement middle level macro handler per pipeline +ifdef(`DMICPROC_FILTER1', , `define(DMICPROC_FILTER1, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +include(DMICPROC_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "EQ IIR Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, EQ IIR Capture, 0, 2, SCHEDULE_CORE) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <--EQ_IIR 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-eq-iir-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), EQ IIR Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(EQ IIR Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-codec-adapter-playback.m4 b/tools/topology/topology1/sof/pipe-eq-iir-codec-adapter-playback.m4 new file mode 100644 index 000000000000..c93d599819a7 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-codec-adapter-playback.m4 @@ -0,0 +1,189 @@ +# Low Latency Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> CODEC_ADAPTER -> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# + +# For codec developers, please define the following control bytes of setup config and runtime params +# and the corresponding max bytenum on your own. + +# Codec Adapter setup config control bytes (little endian) +# : bytes "abi_header, [codec_param0, codec_param1...]" +# - 32 bytes abi_header: you could get by command "sof-ctl -t 0 -g <payload_size> -b" +# - [0:3]: magic number 0x00464f53 +# - [4:7]: type 0 +# - [8:11]: payload size in bytes (not including abi header bytes) +# - [12:15]: abi 3.1.0 +# - [16:31]: reserved 0s +# - (optional) 12+ bytes codec_param: codec TLV parameters container, for more details please refer +# struct codec_param under audio/codec_adapter/codec/generic.h +# - [0:1]: param ID +# - [2:3]: codec ID (when supporting multiple codecs, 0 otherwise) +# - [4:7]: size in bytes (ID + size + data) +# - [8:n-1]: data[], the param data +ifdef(`CA_SETUP_CONTROLBYTES',`', `define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +)') +ifdef(`CA_SETUP_CONTROLBYTES_MAX',`', `define(`CA_SETUP_CONTROLBYTES_MAX', 176)') + +# Codec Adapter runtime param control bytes (little endian) +# : bytes "abi_header, [codec_param_0, codec_param_1...]" +# - 32 bytes abi_header: you could get by command "sof-ctl -t 1 -g <payload_size> -b" +ifdef(`CA_RUNTIME_CONTROLBYTES',`', `define(`CA_RUNTIME_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +)') +ifdef(`CA_RUNTIME_CONTROLBYTES_MAX',`', `define(`CA_RUNTIME_CONTROLBYTES_MAX', 157)') + +# For codec developers, rename bytes control names if necessary. +ifdef(`CA_SETUP_CONTROLBYTES_NAME',`', + `define(`CA_SETUP_CONTROLBYTES_NAME', `CA Setup Config')') +ifdef(`CA_RUNTIME_CONTROLBYTES_NAME',`', + `define(`CA_RUNTIME_CONTROLBYTES_NAME', `CA Runtime Params')') + +define(CA_SETUP_CONFIG, concat(`ca_setup_config_', PIPELINE_ID)) +define(CA_SETUP_CONTROLBYTES_NAME_PIPE, concat(CA_SETUP_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter setup config +CONTROLBYTES_PRIV(CA_SETUP_CONFIG, CA_SETUP_CONTROLBYTES) + +# Codec adapter Bytes control for setup config +C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_SETUP_CONTROLBYTES_MAX), + , + CA_SETUP_CONFIG) + +define(CA_RUNTIME_PARAMS, concat(`ca_runtime_params_', PIPELINE_ID)) +define(CA_RUNTIME_CONTROLBYTES_NAME_PIPE, concat(CA_RUNTIME_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter runtime params +CONTROLBYTES_PRIV(CA_RUNTIME_PARAMS, CA_RUNTIME_CONTROLBYTES) + +# Codec adapter Bytes control for runtime config +C_CONTROLBYTES(CA_RUNTIME_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_RUNTIME_CONTROLBYTES_MAX), + , + CA_RUNTIME_PARAMS) + +# +# IIR EQ +# +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_flat.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_flat.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# For codec developers, please define the schedule core of codec adapter if it you would like it to +# be different from SCHEDULE_CORE. +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE", "CA_RUNTIME_CONTROLBYTES_NAME_PIPE")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Playback Buffers +#W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, +# COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), +# PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +#W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, +# COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), +# PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> CODEC_ADAPTER -> B2 --> sink DAI0 + +P_GRAPH(pipe-pass-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_CODEC_ADAPTER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_RUNTIME_CONTROLBYTES_NAME_PIPE') +undefine(`CA_RUNTIME_PARAMS') +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_RUNTIME_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_RUNTIME_CONTROLBYTES_MAX') +undefine(`CA_RUNTIME_CONTROLBYTES') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-dts-codec-playback.m4 b/tools/topology/topology1/sof/pipe-eq-iir-dts-codec-playback.m4 new file mode 100644 index 000000000000..fc9d54d9f344 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-dts-codec-playback.m4 @@ -0,0 +1,108 @@ +# Low Latency Passthrough with DTS codec Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> DTS codec --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# + +# +# DTS Codec +# + +include(`dts_codec_adapter.m4') + +# +# IIR EQ +# +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_flat.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_flat.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> CODEC_ADAPTER -> B2 --> sink DAI0 + +P_GRAPH(pipe-pass-playback-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_CODEC_ADAPTER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-dts-codec-smart-amp-playback.m4 b/tools/topology/topology1/sof/pipe-eq-iir-dts-codec-smart-amp-playback.m4 new file mode 100644 index 000000000000..ad39972c0c66 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-dts-codec-smart-amp-playback.m4 @@ -0,0 +1,208 @@ +# Smart amplifier playback Pipeline +# +# Playback with smart_amp(Smart Amplifier), it will take the feedback(B2) from capture pipeline. +# +# Pipeline Endpoints for connection are :- +# +# Playback smart_amp +# B1 (DAI buffer) +# +# +# host PCM_P -- B3 --> eq iir --> B4 --> Codec Adapter --> B0 --> smart_amp -- B1--> sink DAI0 +# ^ +# | +# B2 +# | + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`smart_amp.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +ifdef(`SMART_TX_CHANNELS',`',`fatal_error(note: Need to define DAI TX channel number for sof-smart-amplifier +)') +ifdef(`SMART_FB_CHANNELS',`',`fatal_error(note: Need to define feedback channel number for sof-smart-amplifier +)') + +DECLARE_SOF_RT_UUID("smart_amp-test", smart_amp_comp_uuid, 0x167a961e, 0x8ae4, + 0x11ea, 0x89, 0xf1, 0x00, 0x0c, 0x29, 0xce, 0x16, 0x35) +ifdef(`SMART_UUID',`', `define(`SMART_UUID', smart_amp_comp_uuid)'); + +# +# Controls +# + +# initial config params for smart_amp, aligned with struct sof_smart_amp_config +ifelse(SMART_FB_CHANNELS, `8', +`define(`FB_CHMAP',`0xff,0xff,0x00,0x01,0xff,0xff,0xff,0xff')', +`define(`FB_CHMAP',`0x00,0x01,0x02,0x03,0xff,0xff,0xff,0xff')' +) + +CONTROLBYTES_PRIV(SMART_AMP_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,DEC2HEX(SMART_FB_CHANNELS),0x00,0x00,0x00,' +` 0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,' +` FB_CHMAP"') + +# Smart_amp Bytes control for config +C_CONTROLBYTES(Smart_amp Config, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + SMART_AMP_priv) + +# Algorithm Model initial parameters, just empty one at this moment. +CONTROLBYTES_PRIV(MODEL_priv, +` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# Detector Bytes control for Hotword Model blob +C_CONTROLBYTES(Smart_amp Model, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 300000), + , + MODEL_priv) + + +ifelse(SOF_ABI_VERSION_3_17_OR_GRT, `1', +C_CONTROLBYTES_VOLATILE_READONLY(Smart_amp Model_Get_params, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get handlers, 258, 258), + CONTROLBYTES_EXTOPS_READONLY(260 binds the mixer control to bytes get handlers, 260), + , , , + CONTROLBYTES_MAX(, 300000), + , + MODEL_priv)) + +# +# DTS Codec +# + +include(`dts_codec_adapter.m4') + +# +# IIR EQ +# + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use coefficients for pass frequency response +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_pass.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Smart Amplifier Playback, 2, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Mux 0 has 2 sink and source periods. +W_SMART_AMP(0, SMART_UUID, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "Smart_amp Config", "Smart_amp Model", + ifelse(SOF_ABI_VERSION_3_17_OR_GRT, `1', "Smart_amp Model_Get_params"))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), SMART_TX_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), SMART_FB_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(4, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +#define REF buffer name for up layer connection +define(`N_SMART_REF_BUF',`BUF'PIPELINE_ID`.'2) + +# +# Pipeline Graph +# +# host PCM_P --B3--> EQ_IIR 0 --> B4 --> Codec Adapter --> B0--> smart_amp --B1--> sink DAI0 +# ^ +# |--B2-- + +P_GRAPH(pipe-smart-amplifier-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(3), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(3))', + `dapm(N_BUFFER(4), N_EQ_IIR(0))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(4))', + `dapm(N_BUFFER(0), N_CODEC_ADAPTER(0))', + `dapm(N_SMART_AMP(0), N_BUFFER(0))', + `dapm(N_SMART_AMP(0), N_BUFFER(2))', + `dapm(N_BUFFER(1), N_SMART_AMP(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Smart Amplifier Playback PCM_ID) + +# +# PCM Configuration +# + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Smart Amplifier Playback PCM_ID, + CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + 48000, 48000, dnl rate_min, rate_max + SMART_PB_CH_NUM, SMART_PB_CH_NUM, dnl channels_min, channels_max + 2, 16, dnl periods_min, periods_max + 192, 16384, dnl period_size_min, period_size_max + 65536, 65536) + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +undefine(`PIPELINE_FILTER1') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-eq-fir-volume-playback.m4 b/tools/topology/topology1/sof/pipe-eq-iir-eq-fir-volume-playback.m4 new file mode 100644 index 000000000000..6fed74842913 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-eq-fir-volume-playback.m4 @@ -0,0 +1,149 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> Volume 0 --> B3 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_iir.m4') +include(`eq_fir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# IIR EQ +# + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use coefficients for pass frequency response +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_pass.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# FIR EQ +# + +define(DEF_EQFIR_COEF, concat(`eqfir_coef_', PIPELINE_ID)) +define(DEF_EQFIR_PRIV, concat(`eqfir_priv_', PIPELINE_ID)) + +# By default, use coefficients for pass frequency response +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_fir_coef_pass.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQFIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 4096), + , + DEF_EQFIR_PRIV) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, SCHEDULE_CORE) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQFIR_COEF")) + +# "Volume" has x sink and 2 source periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> Volume 0 --> B3 --> sink DAI0 + +P_GRAPH(pipe-eq-iir-eq-fir-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_FIR(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_EQ_FIR(0))', + `dapm(N_PGA(0), N_BUFFER(2))', + `dapm(N_BUFFER(3), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-mfcc-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-eq-iir-mfcc-capture-16khz.m4 new file mode 100644 index 000000000000..8fc4b35c9a74 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-mfcc-capture-16khz.m4 @@ -0,0 +1,119 @@ +# Capture EQ MFCC Pipeline and PCM, 16 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- MFCC 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') +include(`mfcc.m4') + +# +# Controls +# + +define(DEF_MFCC_CONFIG, concat(`mfcc_config_', PIPELINE_ID)) +define(DEF_MFCC_PRIV, concat(`mfcc_priv_', PIPELINE_ID)) + +# define filter. mfcc_config.m4 is set by default +ifdef(`DMIC16KPROC_FILTER2', , `define(DMIC16KPROC_FILTER2, `mfcc/mfcc_config.m4')') +include(DMIC16KPROC_FILTER2) + +# MFCC Bytes control with max value of 255 +define(DEF_MFCC_PARAM, concat(`mfcc_param_', PIPELINE_ID)) +C_CONTROLBYTES(DEF_MFCC_PARAM, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_MFCC_PRIV) + +# By default, use 40 Hz highpass response with +0 dB gain for 16khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`DMIC16KPROC_FILTER1', , `define(DMIC16KPROC_FILTER1, eq_iir_coef_highpass_40hz_0db_16khz.m4)') +define(DEF_EQIIR_PRIV, DMIC16KPROC_FILTER1) +include(DMIC16KPROC_FILTER1) +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE) + +# "MFCC 0" has 2 source period and 2 sink periods +W_MFCC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_MFCC_PARAM")) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- MFCC 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-eq-iir-mfcc-capture-16khz, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_MFCC(0))', + `dapm(N_MFCC(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000, + PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +undefine(`DEF_MFCC_PARAM') +undefine(`DEF_MFCC_CONFIG') +undefine(`DEF_MFCC_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-playback.m4 b/tools/topology/topology1/sof/pipe-eq-iir-playback.m4 new file mode 100644 index 000000000000..25c6fa9d11af --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-playback.m4 @@ -0,0 +1,89 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_iir.m4') + +# +# Controls +# + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_flat.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_flat.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +define(MY_CONTROLBYTES, concat(`EQIIR_CONTROLBYTES_', PIPELINE_ID)) +C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "EQ IIR Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, EQ IIR Playback, 2, 0, SCHEDULE_CORE) + +# "EQ 0" has x sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "MY_CONTROLBYTES")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host host PCM_P --> B0 --> EQ_IIR 0 --> B1 --> sink DAI0 + +P_GRAPH(pipe-eq-iir-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + EQ IIR Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(EQ IIR Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_CONTROLBYTES') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-volume-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-eq-iir-volume-capture-16khz.m4 new file mode 100644 index 000000000000..828e46581647 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-volume-capture-16khz.m4 @@ -0,0 +1,129 @@ +# Capture EQ Pipeline and PCM, 16 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`eq_iir.m4') + +define(`CONTROL_NAME', 2nd Capture Volume) +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') + +# +# Controls +# + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# By default, use 40 Hz highpass response with +0 dB gain for 16khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`DMIC16KPROC_FILTER1', , `define(DMIC16KPROC_FILTER1, eq_iir_coef_highpass_40hz_0db_16khz.m4)') +define(DEF_EQIIR_PRIV, DMIC16KPROC_FILTER1) +include(DMIC16KPROC_FILTER1) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) + + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME")) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-eq-iir-volume-capture-16khz, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +undefine(`CONTROL_NAME') +undefine(`PGA_NAME') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000, + PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-volume-capture.m4 b/tools/topology/topology1/sof/pipe-eq-iir-volume-capture.m4 new file mode 100644 index 000000000000..59b90e9990af --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-volume-capture.m4 @@ -0,0 +1,147 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`eq_iir.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', Capture Volume) +define(`CONTROL_NAME_SWITCH', Capture Switch) +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') + +# +# Controls +# + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +undefine(`CONTROL_NAME') +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') + +# Switch type Mixer Control with max value of 1 +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# By default, use 40 Hz highpass response with +0 dB gain for 48khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`DMICPROC_FILTER1', , `define(DMICPROC_FILTER1, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +define(DEF_EQIIR_PRIV, DMICPROC_FILTER1) +include(DMICPROC_FILTER1) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-eq-iir-volume-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-eq-iir-volume-playback.m4 b/tools/topology/topology1/sof/pipe-eq-iir-volume-playback.m4 new file mode 100644 index 000000000000..a55aee14010b --- /dev/null +++ b/tools/topology/topology1/sof/pipe-eq-iir-volume-playback.m4 @@ -0,0 +1,118 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# IIR EQ +# +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_flat.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_flat.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, SCHEDULE_CORE) + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-eq-iir-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-google-hotword-detect.m4 b/tools/topology/topology1/sof/pipe-google-hotword-detect.m4 new file mode 100644 index 000000000000..86c67077abba --- /dev/null +++ b/tools/topology/topology1/sof/pipe-google-hotword-detect.m4 @@ -0,0 +1,106 @@ +# Google Hotword Detector +# +# This pipeline uses the Google hotword library for detection +# +# Pipeline Endpoints for connection are :- +# +# (Google Hotword Detector <-- Channel Selector) <-- Key Phrase Buffer Manager <--- Source Pipeline +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pga.m4') +include(`ch_sel.m4') +include(`google_hotword_detect.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') + +# +# Controls +# + +# Selector initial parameters +# in_channels_count = 2, out_channels_count = 1, sel_channel = 0 +CONTROLBYTES_PRIV(SELECTOR_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00"' +) + +# Selector Bytes control with max value of 255 +C_CONTROLBYTES(SELECTOR, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + SELECTOR_priv) + +# Hotword Model initial parameters +# Empty model +# sof_abi_hdr.size = 0 +# sof_abi_hdr.type = 0 (GOOGLE_HOTWORD_DETECT_MODEL) +CONTROLBYTES_PRIV(GOOGLE_HOTWORD_DETECT_MODEL_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# Detector Bytes control for Hotword Model blob +C_CONTROLBYTES(Hotword Model, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 300000), + , + GOOGLE_HOTWORD_DETECT_MODEL_priv) + +# +# Components and Buffers +# + +# "GHD 0" has 2 sink period and 0 source periods +W_GHD(0, PIPELINE_FORMAT, 0, 2, KEYWORD, N_STS(PCM_ID), SCHEDULE_CORE, + LIST(` ', "Hotword Model")) + +W_SELECTOR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "SELECTOR")) + +# Capture Buffers +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +# Capture Buffers +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +# Virtual output widget +VIRTUAL_WIDGET(DETECT SINK PIPELINE_ID, out_drv, PIPELINE_ID) + +# Pipeline +dnl W_PIPELINE(stream, deadline, priority, core, timer, platform) +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + +# +# Pipeline Graph +# +# DETECT SINK <-- Google Hotword Detect 0 <-- B2 <-- Channel Selector 0 <-- B1 + +P_GRAPH(pipe-detect-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(DETECT SINK PIPELINE_ID, N_GHD(0))', + `dapm(N_GHD(0), N_BUFFER(2))', + `dapm(N_BUFFER(2), N_SELECTOR(0))', + `dapm(N_SELECTOR(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_DETECT_', PIPELINE_ID), DETECT SINK PIPELINE_ID) diff --git a/tools/topology/topology1/sof/pipe-google-rtc-audio-processing-capture.m4 b/tools/topology/topology1/sof/pipe-google-rtc-audio-processing-capture.m4 new file mode 100644 index 000000000000..13a8a82c5de9 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-google-rtc-audio-processing-capture.m4 @@ -0,0 +1,83 @@ +# Acoustic echo cancelling Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- AEC <-- B1 <-- source DAI0 +# ^----- B2 <-- AEC reference + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`google_rtc_audio_processing.m4') + +# +# Controls +# + +include(`google_rtc_audio_processing_default.m4') + +# Byte control for AEC tuning data +C_CONTROLBYTES(`Config', PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 2048), + , + GOOGLE_RTC_AUDIO_PROCESSING_priv) + +# +# Components and Buffers +# + +# Host "Google RTC Audio Processing Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Google RTC Audio Processing, 0, DAI_PERIODS, SCHEDULE_CORE) + +W_GOOGLE_RTC_AUDIO_PROCESSING(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + `', + LIST(` ', "Config")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +define(`N_AEC_REF_BUF',`BUF'PIPELINE_ID`.'2) +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- AEC 0 <-- B1 <-- sink DAI0 +# ^------- B2 <-- AEC ref + +P_GRAPH(pipe-google-aec-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_GOOGLE_RTC_AUDIO_PROCESSING(0))', + `dapm(N_GOOGLE_RTC_AUDIO_PROCESSING(0), N_BUFFER(1))', + `dapm(N_GOOGLE_RTC_AUDIO_PROCESSING(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Google RTC Audio Processing PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Google RTC Audio Processing PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/topology1/sof/pipe-gui-components-capture.m4 b/tools/topology/topology1/sof/pipe-gui-components-capture.m4 new file mode 100644 index 000000000000..ee8a66f6efd4 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-gui-components-capture.m4 @@ -0,0 +1,146 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`eq_iir.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', Capture Volume) +define(`CONTROL_NAME_SWITCH', Capture Switch) +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') + +# +# Controls +# + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +undefine(`CONTROL_NAME') +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') + +# Switch type Mixer Control with max value of 1 +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# By default, use 40 Hz highpass response with +0 dB gain for 48khz +ifdef(`DMICPROC_FILTER1', , `define(DMICPROC_FILTER1, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +define(DEF_EQIIR_PRIV, DMICPROC_FILTER1) +include(DMICPROC_FILTER1) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "EQ 0" has 2 sink period and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <--EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-eq-iir-volume-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-gui-components-playback.m4 b/tools/topology/topology1/sof/pipe-gui-components-playback.m4 new file mode 100644 index 000000000000..c54b168e1245 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-gui-components-playback.m4 @@ -0,0 +1,114 @@ +# Pipeline to include all relevant components for the SOF GUI + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# IIR EQ +# +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_flat.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_flat.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, SCHEDULE_CORE) + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> EQ 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-eq-iir-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-highpass-capture.m4 b/tools/topology/topology1/sof/pipe-highpass-capture.m4 new file mode 100644 index 000000000000..58f1075e3c36 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-highpass-capture.m4 @@ -0,0 +1,127 @@ +# IIR highpass filter, volume control, and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQ_IIR <-- B2 <-- source DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume Configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "400"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# IIR configuration +# + +# By default, use 40 Hz highpass response with 0 dB gain +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +define(DEF_EQIIR_PRIV, PIPELINE_FILTER1) +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +define(DEF_EQIIR_COEF, concat(`eqiir_bytes_', PIPELINE_ID)) +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 sink and 2 source periods +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume")) + +# "EQ_IIR 0" has 2 sink and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-highpass-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-highpass-switch-capture.m4 b/tools/topology/topology1/sof/pipe-highpass-switch-capture.m4 new file mode 100644 index 000000000000..e34b454d662c --- /dev/null +++ b/tools/topology/topology1/sof/pipe-highpass-switch-capture.m4 @@ -0,0 +1,140 @@ +# IIR highpass filter, volume/switch control, and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQ_IIR <-- B2 <-- source DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +C_CONTROLMIXER(Master Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 259 binds the mixer control to switch get/put handlers, + 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 2, 0), KCONTROL_CHANNEL(FR, 2, 1)), + "1", "1") +# +# Volume Configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "400"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# IIR configuration +# + + +# By default, use 40 Hz highpass response with 0 dB gain +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +define(DEF_EQIIR_PRIV, PIPELINE_FILTER1) +include(PIPELINE_FILTER1) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Highpass Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Highpass Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 sink and 2 source periods +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume", + "PIPELINE_ID Master Capture Switch")) + +# "EQ_IIR 0" has 2 sink and x source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- EQ_IIR 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-highpass-switch-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Highpass Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Highpass Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/pipe-host-codec-adapter-playback.m4 b/tools/topology/topology1/sof/pipe-host-codec-adapter-playback.m4 new file mode 100644 index 000000000000..2ee73c6ac32c --- /dev/null +++ b/tools/topology/topology1/sof/pipe-host-codec-adapter-playback.m4 @@ -0,0 +1,151 @@ +# Low Latency Host Pipeline and Codec Adapter +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> CODEC_ADAPTER -> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') +include(`bytecontrol.m4') + +# +# Controls +# + +# For codec developers, please define the following control bytes of setup config and runtime params +# and the corresponding max bytenum on your own. + +# Codec Adapter setup config control bytes (little endian) +# : bytes "abi_header, [codec_param0, codec_param1...]" +# - 32 bytes abi_header: you could get by command "sof-ctl -t 0 -g <payload_size> -b" +# - [0:3]: magic number 0x00464f53 +# - [4:7]: type 0 +# - [8:11]: payload size in bytes (not including abi header bytes) +# - [12:15]: abi 3.1.0 +# - [16:31]: reserved 0s +# - (optional) 12+ bytes codec_param: codec TLV parameters container, for more details please refer +# struct codec_param under audio/codec_adapter/codec/generic.h +# - [0:1]: param ID +# - [2:3]: codec ID, when supporting multiple codecs, 0 otherwise +# - [4:7]: size in bytes (ID + size + data) +# - [8:n-1]: data[], the param data +ifdef(`CA_SETUP_CONTROLBYTES',`', `define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +)') +ifdef(`CA_SETUP_CONTROLBYTES_MAX',`', `define(`CA_SETUP_CONTROLBYTES_MAX', 176)') + +# Codec Adapter runtime param control bytes (little endian) +# : bytes "abi_header, [codec_param_0, codec_param_1...]" +# - 32 bytes abi_header: you could get by command "sof-ctl -t 1 -g <payload_size> -b" +ifdef(`CA_RUNTIME_CONTROLBYTES',`', `define(`CA_RUNTIME_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +)') +ifdef(`CA_RUNTIME_CONTROLBYTES_MAX',`', `define(`CA_RUNTIME_CONTROLBYTES_MAX', 157)') + +# For codec developers, rename bytes control names if necessary. +ifdef(`CA_SETUP_CONTROLBYTES_NAME',`', + `define(`CA_SETUP_CONTROLBYTES_NAME', `CA Setup Config')') +ifdef(`CA_RUNTIME_CONTROLBYTES_NAME',`', + `define(`CA_RUNTIME_CONTROLBYTES_NAME', `CA Runtime Params')') + +define(CA_SETUP_CONFIG, concat(`ca_setup_config_', PIPELINE_ID)) +define(CA_SETUP_CONTROLBYTES_NAME_PIPE, concat(CA_SETUP_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter setup config +CONTROLBYTES_PRIV(CA_SETUP_CONFIG, CA_SETUP_CONTROLBYTES) + +# Codec adapter Bytes control for setup config +C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_SETUP_CONTROLBYTES_MAX), + , + CA_SETUP_CONFIG) + +define(CA_RUNTIME_PARAMS, concat(`ca_runtime_params_', PIPELINE_ID)) +define(CA_RUNTIME_CONTROLBYTES_NAME_PIPE, concat(CA_RUNTIME_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter runtime params +CONTROLBYTES_PRIV(CA_RUNTIME_PARAMS, CA_RUNTIME_CONTROLBYTES) + +# Codec adapter Bytes control for runtime config +C_CONTROLBYTES(CA_RUNTIME_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_RUNTIME_CONTROLBYTES_MAX), + , + CA_RUNTIME_PARAMS) + +# +# Components and Buffers +# + +# For codec developers, please define the schedule core of codec adapter if it you would like it to +# be different from SCHEDULE_CORE. +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE", "CA_RUNTIME_CONTROLBYTES_NAME_PIPE")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> CODEC_ADAPTER -> B1 --> sink DAI0 + +P_GRAPH(pipe-codec-adapter-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Playback PCM_ID) + +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`CA_RUNTIME_CONTROLBYTES_NAME_PIPE') +undefine(`CA_RUNTIME_PARAMS') +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_RUNTIME_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_RUNTIME_CONTROLBYTES_MAX') +undefine(`CA_RUNTIME_CONTROLBYTES') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') diff --git a/tools/topology/topology1/sof/pipe-host-playback.m4 b/tools/topology/topology1/sof/pipe-host-playback.m4 new file mode 100644 index 000000000000..bf2c31dfb9aa --- /dev/null +++ b/tools/topology/topology1/sof/pipe-host-playback.m4 @@ -0,0 +1,56 @@ +# Host PCM Volume playback pipeline +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> [other pipeline] + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') + + +# +# Components and Buffers +# + +# Host "Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Playback, 2, 0, SCHEDULE_CORE) + + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) + + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> Volume 0 --> B1 --> sink DAI0 + +P_GRAPH(pipe-host-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Playback PCM_ID) + +# +# Pipeline Configuration. +# + +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + diff --git a/tools/topology/topology1/sof/pipe-host-src-volume-playback.m4 b/tools/topology/topology1/sof/pipe-host-src-volume-playback.m4 new file mode 100644 index 000000000000..c6571fbef166 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-host-src-volume-playback.m4 @@ -0,0 +1,110 @@ +# Host PCM Volume playback pipeline +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> SRC 0 --> B1 --> Volume 0 --> B2 --> [other pipeline] + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`src.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +define(DEF_SRC_TOKENS, concat(`src_tokens_', PIPELINE_ID)) +define(DEF_SRC_CONF, concat(`src_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_SRC_TOKENS, sof_src_tokens, +LIST(` ', `SOF_TKN_SRC_RATE_OUT "PIPELINE_RATE"')) + +W_DATA(DEF_SRC_CONF, DEF_SRC_TOKENS) + +# +# Components and Buffers +# + +# Host "Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Playback, 2, 0, SCHEDULE_CORE) + +# "SRC" has 2 source and 2 sink periods +W_SRC(0, PIPELINE_FORMAT, 2, 2, DEF_SRC_CONF) + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Playback Volume")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# +# Pipeline Graph +# +# host PCM_P --> B0 -- SRC 0 --> B1 --> Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-host-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_SRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_SRC(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Playback PCM_ID) + +# +# Pipeline Configuration. +# + +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 8000, 192000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_SRC_TOKENS') +undefine(`DEF_SRC_CONF') diff --git a/tools/topology/topology1/sof/pipe-host-volume-playback.m4 b/tools/topology/topology1/sof/pipe-host-volume-playback.m4 new file mode 100644 index 000000000000..cc76e939b27f --- /dev/null +++ b/tools/topology/topology1/sof/pipe-host-volume-playback.m4 @@ -0,0 +1,91 @@ +# Host PCM Volume playback pipeline +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> Volume 0 --> B1 --> [other pipeline] + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Playback, 2, 0, SCHEDULE_CORE) + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Playback Volume")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> Volume 0 --> B1 --> sink DAI0 + +P_GRAPH(pipe-host-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_PGA(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Playback PCM_ID) + +# +# Pipeline Configuration. +# + +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-igonr-capture.m4 b/tools/topology/topology1/sof/pipe-igonr-capture.m4 new file mode 100644 index 000000000000..8249d170cdef --- /dev/null +++ b/tools/topology/topology1/sof/pipe-igonr-capture.m4 @@ -0,0 +1,91 @@ +# Capture Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`igo_nr.m4') + +CONTROLBYTES_PRIV(IGO_NR_priv, +` bytes "0x53,0x4f,0x46,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x44,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x03,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x20,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,' +` 0x3d,0x00,0x00,0x00,' +` 0x09,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x20,0x00,0x00,' +` 0x34,0x03,0x00,0x00,' +` 0x00,0x00,0x00,0x00"' +) + +C_CONTROLBYTES(IGO_NR, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 196), + , + IGO_NR_priv) + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, DAI_PERIODS, SCHEDULE_CORE) + +W_IGO_NR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, LIST(` ', "IGO_NR")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- NR0 <-- B1<-- sink DAI0 + +P_GRAPH(pipe-igonr-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_IGO_NR(0))', + `dapm(N_IGO_NR(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Capture PCM_ID, COMP_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-kfbm-capture.m4 b/tools/topology/topology1/sof/pipe-kfbm-capture.m4 similarity index 83% rename from tools/topology/sof/pipe-kfbm-capture.m4 rename to tools/topology/topology1/sof/pipe-kfbm-capture.m4 index 99853a306096..725cabdb8583 100644 --- a/tools/topology/sof/pipe-kfbm-capture.m4 +++ b/tools/topology/topology1/sof/pipe-kfbm-capture.m4 @@ -2,7 +2,7 @@ # # Pipeline Endpoints for connection are :- # -# host PCM_C <-+- KPBM 0 <-- B1 <-- Volume 0 <-- B0 <-- source DAI0 +# host PCM_C <-- B1 <--+- KPBM 0 <-- B0 <-- source DAI0 # | # Others <--+ @@ -50,10 +50,11 @@ C_CONTROLBYTES(KPB, PIPELINE_ID, # Host "Passthrough Capture" PCM # with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Sound Trigger Capture, 0, 2, 2) +W_PCM_CAPTURE(PCM_ID, Sound Trigger Capture, 0, 2, SCHEDULE_CORE) # "KPBM" has 2 source and 2 sink periods -W_KPBM(0, PIPELINE_FORMAT, 2, 2, PIPELINE_ID, LIST(` ', "KPB")) +W_KPBM(0, PIPELINE_FORMAT, 2, 2, PIPELINE_ID, SCHEDULE_CORE, + LIST(` ', "KPB")) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, @@ -71,7 +72,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(2, # | # Others <-- -P_GRAPH(pipe-kpbm-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-kfbm-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(1))', `dapm(N_BUFFER(1), N_KPBM(0, PIPELINE_ID))', @@ -88,7 +89,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), N_PCMC(PCM_ID)) # PCM Configuration # dnl PCM_CAPTURE_LP_ADD(name, pipeline, capture) -PCM_CAPTURE_LP_ADD(DMIC16k, PIPELINE_ID, N_STS(PCM_ID)) +PCM_CAPTURE_LP_ADD(DMIC_16k_PCM_NAME, PCM_ID, N_STS(PCM_ID)) -PCM_CAPABILITIES(N_STS(PCM_ID), `S32_LE,S24_LE,S16_LE', 16000, 16000, 2, PIPELINE_CHANNELS, 2, 160, 192, 256000, 256000, 1280000) +PCM_CAPABILITIES(N_STS(PCM_ID), CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000, 2, PIPELINE_CHANNELS, 2, 160, 192, 256000, 537600, 1280000) diff --git a/tools/topology/topology1/sof/pipe-kfbm-no-lp-capture.m4 b/tools/topology/topology1/sof/pipe-kfbm-no-lp-capture.m4 new file mode 100644 index 000000000000..b86f349cfcdd --- /dev/null +++ b/tools/topology/topology1/sof/pipe-kfbm-no-lp-capture.m4 @@ -0,0 +1,95 @@ +# Passthrough Capture Pipeline with KPBM and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B1 <--+- KPBM 0 <-- B0 <-- source DAI0 +# | +# Others <--+ + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`kpbm.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') + +dnl Soun Trigger Stream Name) +define(`N_STS', `Sound Trigger Capture '$1) + +# +# Controls +# + +# kpbm initial parameters, aligned with struct sof_kpb_config +CONTROLBYTES_PRIV(KPB_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x80,0x3e,0x00,0x00,0x10,0x00,0x00,0x00"' +) + +# KPB Bytes control with max value of 255 +C_CONTROLBYTES(KPB, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + KPB_priv) + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Sound Trigger Capture, 0, 2, SCHEDULE_CORE) + +# "KPBM" has 2 source and 2 sink periods +W_KPBM(0, PIPELINE_FORMAT, 2, 2, PIPELINE_ID, SCHEDULE_CORE, + LIST(` ', "KPB")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) +# Capture Buffers +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B1 <--+- KPBM 0 <-- B0 <-- source DAI0 +# | +# Others <-- + +P_GRAPH(pipe-kfbm-no-lp-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_KPBM(0, PIPELINE_ID))', + `dapm(N_KPBM(0, PIPELINE_ID), N_BUFFER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_KPBM(0, PIPELINE_ID)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), N_PCMC(PCM_ID)) + +# +# PCM Configuration +# +dnl PCM_CAPTURE_ADD(name, pipeline, capture) +PCM_CAPTURE_ADD(DMIC_16k_PCM_NAME, PCM_ID, N_STS(PCM_ID)) + +PCM_CAPABILITIES(N_STS(PCM_ID), CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000, 2, PIPELINE_CHANNELS, 2, 160, 192, 256000, 537600, 1280000) + diff --git a/tools/topology/topology1/sof/pipe-low-latency-capture-demux.m4 b/tools/topology/topology1/sof/pipe-low-latency-capture-demux.m4 new file mode 100644 index 000000000000..66fe72860a40 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-low-latency-capture-demux.m4 @@ -0,0 +1,107 @@ +# Low Latency Pipeline +# +# Low latency Capture PCM. +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Capture Volume B4 (DAI buffer) +# LL Playback Volume B3 (DAI buffer) +# +# +# host PCM_P --B0--> volume(0P) --B1--+ +# |--ll mixer(M) --B2--> volume(LL) ---B3--> sink DAI0 +# pipeline n+1 >---+ +# | +# pipeline n+2 >---+ +# | +# pipeline n+3 >---+ .....etc....more pipes can be mixed here +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pcm.m4') +#include(`pga.m4') +include(`muxdemux.m4') +include(`bytecontrol.m4') + +# +# Controls +# + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + + +# +# Components and Buffers +# + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2, SCHEDULE_CORE) + + +# Mux 0 in MUX mode, has 2 sink and source periods. +#W_MUXDEMUX(name, mux0/demux1, format, periods_sink, periods_source, core, kcontrol_list) +#W_MUXDEMUX_AMD(0, 1, PIPELINE_FORMAT, 2, 4, SCHEDULE_CORE, +# LIST(` ', concat(`DEMUX', PIPELINE_ID)),SCHEDULE_TIME_DOMAIN,SCHED_COMP) +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 4, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +#dnl W_BUFFER(name, Bufsize, capabilities) +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), 4,COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + + +# +# Pipeline Graph +# +# host PCM_P --B0--> volume(0P) --B1--+ +# |--ll mixer(M) --B2--> volume(LL) ---B3--> sink DAI0 +# pipeline n+1 >---+ +# | +# pipeline n+2 >---+ +# | +# pipeline n+3 >---+ .....etc....more pipes can be mixed here +# + +P_GRAPH(pipe-low-latency-capture-demux, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_MUXDEMUX(0))', + `dapm(N_MUXDEMUX(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) + +#W_PIPELINE(N_PCMC(PCM_ID), SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) +#W_PIPELINE(N_PCMC(PCM_ID), SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat_dmic) + + +# +# PCM Configuration +# + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Passthrough Capture PCM_ID, COMP_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/sof/pipe-low-latency-capture.m4 b/tools/topology/topology1/sof/pipe-low-latency-capture.m4 similarity index 81% rename from tools/topology/sof/pipe-low-latency-capture.m4 rename to tools/topology/topology1/sof/pipe-low-latency-capture.m4 index f83fbcb70e7e..546b9fc6ffe0 100644 --- a/tools/topology/sof/pipe-low-latency-capture.m4 +++ b/tools/topology/topology1/sof/pipe-low-latency-capture.m4 @@ -39,10 +39,11 @@ W_DATA(capture_pga_conf, capture_pga_tokens) # Host "Low Latency Capture" PCM # with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Low Latency Capture, 0, 2) +W_PCM_CAPTURE(PCM_ID, Low Latency Capture, 0, 2, SCHEDULE_CORE) # "Capture Volume" has 2 sink and x source periods for host and DAI ping-pong -W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, capture_pga_conf, LIST(` ', "PIPELINE_ID PCM PCM_ID Capture Volume")) +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, capture_pga_conf, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID PCM PCM_ID Capture Volume")) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, @@ -57,7 +58,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(2, # # host PCM <--B1-- volume <--B0-- source DAI0 -P_GRAPH(pipe-ll-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-low-latency-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(1))', `dapm(N_BUFFER(1), N_PGA(0))', @@ -73,4 +74,4 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Capture PCM_ID # PCM Configuration # -PCM_CAPABILITIES(Low Latency Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 4, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(Low Latency Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 4, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-low-latency-playback.m4 b/tools/topology/topology1/sof/pipe-low-latency-playback.m4 similarity index 80% rename from tools/topology/sof/pipe-low-latency-playback.m4 rename to tools/topology/topology1/sof/pipe-low-latency-playback.m4 index f6b12a4825d5..73ec028cf68e 100644 --- a/tools/topology/sof/pipe-low-latency-playback.m4 +++ b/tools/topology/topology1/sof/pipe-low-latency-playback.m4 @@ -46,17 +46,20 @@ C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # # Volume configuration # -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) -W_DATA(playback_pga_conf, playback_pga_tokens) +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) # # Components and Buffers @@ -64,16 +67,18 @@ W_DATA(playback_pga_conf, playback_pga_tokens) # Host "Low latency Playback" PCM # with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0) +W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0, SCHEDULE_CORE) # "Playback Volume" has 2 sink periods and 2 source periods for host ping-pong -W_PGA(0, PIPELINE_FORMAT, 2, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID PCM PCM_ID Playback Volume")) +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID PCM PCM_ID Playback Volume")) # "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong -W_PGA(1, PIPELINE_FORMAT, DAI_PERIODS, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Playback Volume")) +W_PGA(1, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) # Mixer 0 has 2 sink and source periods. -W_MIXER(0, PIPELINE_FORMAT, 2, 2) +W_MIXER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE) # Low Latency Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, @@ -101,7 +106,7 @@ W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, # pipeline n+3 >---+ .....etc....more pipes can be mixed here # -P_GRAPH(pipe-ll-playback-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-low-latency-playback, PIPELINE_ID, LIST(` ', `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', `dapm(N_PGA(0), N_BUFFER(0))', @@ -122,7 +127,8 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_I # PCM Configuration # - # PCM capabilities supported by FW -PCM_CAPABILITIES(Low Latency Playback PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(Low Latency Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-low-latency-playback_mux_tdm4ch.m4 b/tools/topology/topology1/sof/pipe-low-latency-playback_mux_tdm4ch.m4 new file mode 100644 index 000000000000..97a44d6eaf7e --- /dev/null +++ b/tools/topology/topology1/sof/pipe-low-latency-playback_mux_tdm4ch.m4 @@ -0,0 +1,116 @@ +# Low Latency Pipeline +# +# Low Latency Playback PCM mixed into single sink pipe. +# Low latency Capture PCM. +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Capture Volume B4 (DAI buffer) +# LL Playback Volume B3 (DAI buffer) +# +# +# host PCM_P --B0--> volume(0P) --B1--+ +# |--ll mixer(M) --B2--> volume(LL) ---B3--> sink DAI0 +# pipeline n+1 >---+ +# | +# pipeline n+2 >---+ +# | +# pipeline n+3 >---+ .....etc....more pipes can be mixed here +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pcm.m4') +#include(`pga.m4') +include(`muxdemux.m4') +include(`bytecontrol.m4') + +# +# Controls +# + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + + +# +# Components and Buffers +# + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0, SCHEDULE_CORE) + + +# Mux 0 in MUX mode, has 2 sink and source periods. +#W_MUXDEMUX(name, mux0/demux1, format, periods_sink, periods_source, core, kcontrol_list) +W_MUXDEMUX(0, 0, PIPELINE_FORMAT, 4, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +#dnl W_BUFFER(name, Bufsize, capabilities) +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +#W_BUFFER(1, COMP_BUFFER_SIZE(4, +# COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS,COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), +# PLATFORM_COMP_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), 4,COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + + +#W_DAI_OUT(ACPSP1, 1, 1, PIPELINE_FORMAT, 2, 2, 0) +##W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +#DAI_CONFIG(ACPSP1, 1, 1, acp-amp-codec, +# ACPSP1_CONFIG(I2S, ACP_CLOCK(mclk, 49152000, codec_mclk_in), +# ACP_CLOCK(bclk, 3072000, codec_consumer), +# ACP_CLOCK(fsync, 48000, codec_consumer), +# ACP_TDM(4, 32, 3, 3),ACPSP1_CONFIG_DATA(ACPSP1, 1, 48000, 4))) + +# +# Pipeline Graph +# +# host PCM_P --B0--> volume(0P) --B1--+ +# |--ll mixer(M) --B2--> volume(LL) ---B3--> sink DAI0 +# pipeline n+1 >---+ +# | +# pipeline n+2 >---+ +# | +# pipeline n+3 >---+ .....etc....more pipes can be mixed here +# + +P_GRAPH(pipe-low-latency-playback_mux_NewAMD, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_MUXDEMUX(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_MUXDEMUX(0))')) + #`dapm(N_DAI_OUT, N_BUFFER(1))')) + + + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID) + +# +# PCM Configuration +# + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Low Latency Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-mfcc-capture.m4 b/tools/topology/topology1/sof/pipe-mfcc-capture.m4 new file mode 100644 index 000000000000..9789794717a0 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mfcc-capture.m4 @@ -0,0 +1,88 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- MFCC 0 <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mfcc.m4') + +# +# Controls +# + +define(DEF_MFCC_CONFIG, concat(`mfcc_config_', PIPELINE_ID)) +define(DEF_MFCC_PRIV, concat(`mfcc_priv_', PIPELINE_ID)) + +# By default, use 40 Hz highpass response with 0 dB gain +# TODO: need to implement middle level macro handler per pipeline +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `mfcc/mfcc_config.m4')') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_MFCC_CONFIG, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_MFCC_PRIV) + +# +# Components and Buffers +# + +# Host "MFCC Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, MFCC Capture, 0, 2, SCHEDULE_CORE) + +# "EQ 0" has 2 sink period and x source periods +W_MFCC(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_MFCC_CONFIG")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <--MFCC 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-eq-iir-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_MFCC(0))', + `dapm(N_MFCC(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), MFCC Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(MFCC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_MFCC_CONFIG') +undefine(`DEF_MFCC_PRIV') diff --git a/tools/topology/topology1/sof/pipe-mfcc-playback.m4 b/tools/topology/topology1/sof/pipe-mfcc-playback.m4 new file mode 100644 index 000000000000..e87df38e6118 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mfcc-playback.m4 @@ -0,0 +1,88 @@ +# Low Latency mfcc pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> MFCC 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`mfcc.m4') + +# +# Controls +# + +define(DEF_MFCC_CONFIG, concat(`mfcc_config_', PIPELINE_ID)) +define(DEF_MFCC_PRIV, concat(`mfcc_priv_', PIPELINE_ID)) + +# define filter. mfcc_config.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `mfcc/mfcc_config.m4')') +include(PIPELINE_FILTER1) + +# MFCC Bytes control with max value of 255 +define(MY_CONTROLBYTES, concat(`MFCC_CONTROLBYTES_', PIPELINE_ID)) +C_CONTROLBYTES(MY_CONTROLBYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_MFCC_PRIV) + +# +# Components and Buffers +# + +# Host "MFCC Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, MFCC Playback, 2, 0, SCHEDULE_CORE) + +# "MFCC 0" has x sink period and 2 source periods +W_MFCC(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "MY_CONTROLBYTES")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> MFCC 0 --> B1 --> sink DAI0 + +P_GRAPH(pipe-mfcc-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_MFCC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_MFCC(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), MFCC Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(MFCC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_CONTROLBYTES') +undefine(`DEF_MFCC_CONFIG') +undefine(`DEF_MFCC_PRIV') diff --git a/tools/topology/topology1/sof/pipe-mixer-drc-dai-playback.m4 b/tools/topology/topology1/sof/pipe-mixer-drc-dai-playback.m4 new file mode 100644 index 000000000000..08edefef0c4c --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mixer-drc-dai-playback.m4 @@ -0,0 +1,83 @@ +# Mixer DAI Playback connector +# +# DAI playback starting with a LL mixer +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Playback Volume B1 (DAI buffer) +# +# DAI_BUF --> ll mixer(M) --> B0 --> DRC(LL) --> B1 --> sink DAI +# +# the ll mixer is connected to one DAI_BUF by default. Additional ones can be added later + +# Include topology builder +include(`utils.m4') +include(`mixer.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`drc.m4') + +# +# Controls +# + +# +# DRC Configuration +# + +define(DRC_priv, concat(`drc_bytes_', PIPELINE_ID)) +define(MY_DRC_CTRL, concat(`drc_control_', PIPELINE_ID)) +include(`drc_coef_default.m4') +C_CONTROLBYTES(MY_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DRC_priv) + + +# Mixer 0 has 2 sink and source periods. +W_MIXER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE) + +# "DRC" has 2 sink periods and 2 source periods +W_DRC(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "MY_DRC_CTRL")) + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs - FIXME WHY 0? +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS, COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Graph connections to pipelines +# we don't connect `dapm(N_MIXER(0), DAI_BUF)' due to forward dependencies +# +P_GRAPH(DAI_NAME, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_MIXER(0))', + `dapm(N_DRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_DRC(0))' + `dapm(N_DAI_OUT, N_BUFFER(1))')) + +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) +indir(`define', concat(`PIPELINE_MIXER_', PIPELINE_ID), N_MIXER(0)) + +undefine(`MY_DRC_CTRL') +undefine(`DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-mixer-eq-iir-eq-fir-volume-dai-playback.m4 b/tools/topology/topology1/sof/pipe-mixer-eq-iir-eq-fir-volume-dai-playback.m4 new file mode 100644 index 000000000000..6773eea06500 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mixer-eq-iir-eq-fir-volume-dai-playback.m4 @@ -0,0 +1,153 @@ +# Mixer DAI Playback connector +# +# DAI playback starting with a LL mixer +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Playback Volume B3 (DAI buffer) +# +# DAI_BUF --> ll mixer(M) --> B0 --> EQ_IIR 0 --> B1 --> EQ_FIR 0 --> B2 --> volume(LL) --> B3--> sink DAI +# +# the ll mixer is connected to one DAI_BUF by default. Additional ones can be added later + +# Include topology builder +include(`utils.m4') +include(`mixer.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pga.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`eq_iir.m4') +include(`eq_fir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# Mixer 0 has 2 sink and source periods. +W_MIXER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE) + +# +# IIR EQ +# + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use coefficients for pass frequency response +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_pass.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# FIR EQ +# + +define(DEF_EQFIR_COEF, concat(`eqfir_coef_', PIPELINE_ID)) +define(DEF_EQFIR_PRIV, concat(`eqfir_priv_', PIPELINE_ID)) + +# By default, use coefficients for pass frequency response +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_fir_coef_pass.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQFIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 4096), + , + DEF_EQFIR_PRIV) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_FIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQFIR_COEF")) + +# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs - FIXME WHY 0? +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS, COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Graph connections to pipelines +# we don't connect `dapm(N_MIXER(0), DAI_BUF)' due to forward dependencies +# +P_GRAPH(DAI_NAME, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_MIXER(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_FIR(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_EQ_FIR(0))', + `dapm(N_PGA(0), N_BUFFER(2))', + `dapm(N_BUFFER(3), N_PGA(0))' + `dapm(N_DAI_OUT, N_BUFFER(3))')) + +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) +indir(`define', concat(`PIPELINE_MIXER_', PIPELINE_ID), N_MIXER(0)) + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +undefine(`DEF_EQFIR_COEF') +undefine(`DEF_EQFIR_PRIV') +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-mixer-eq-iir-volume-dai-playback.m4 b/tools/topology/topology1/sof/pipe-mixer-eq-iir-volume-dai-playback.m4 new file mode 100644 index 000000000000..118d16871b35 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mixer-eq-iir-volume-dai-playback.m4 @@ -0,0 +1,121 @@ +# Mixer DAI Playback connector +# +# DAI playback starting with a LL mixer +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Playback Volume B3 (DAI buffer) +# +# DAI_BUF --> ll mixer(M) --> B0 --> EQ_IIR 0 --> B1 --> volume(LL) --> B2 --> sink DAI +# +# the ll mixer is connected to one DAI_BUF by default. Additional ones can be added later + +# Include topology builder +include(`utils.m4') +include(`mixer.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pga.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`eq_iir.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# Mixer 0 has 2 sink and source periods. +W_MIXER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE) + +# +# IIR EQ +# + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use coefficients for pass frequency response +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_pass.m4)') +include(PIPELINE_FILTER1) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs - FIXME WHY 0? +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS, COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Graph connections to pipelines +# we don't connect `dapm(N_MIXER(0), DAI_BUF)' due to forward dependencies +# +P_GRAPH(DAI_NAME, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_MIXER(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))' + `dapm(N_DAI_OUT, N_BUFFER(2))')) + +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) +indir(`define', concat(`PIPELINE_MIXER_', PIPELINE_ID), N_MIXER(0)) + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-mixer-multiband-drc-dai-playback.m4 b/tools/topology/topology1/sof/pipe-mixer-multiband-drc-dai-playback.m4 new file mode 100644 index 000000000000..f35272a6ed7f --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mixer-multiband-drc-dai-playback.m4 @@ -0,0 +1,82 @@ +# Mixer DAI Playback connector +# +# DAI playback starting with a LL mixer +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Playback Volume B1 (DAI buffer) +# +# DAI_BUF --> ll mixer(M) --> B0 --> multiband-DRC(LL) --> B1 --> sink DAI +# +# the ll mixer is connected to one DAI_BUF by default. Additional ones can be added later + +# Include topology builder +include(`utils.m4') +include(`mixer.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`multiband_drc.m4') + +# +# Controls +# + +# +# Multiband DRC Configuration +# + +define(MULTIBAND_DRC_priv, concat(`multiband_drc_bytes_', PIPELINE_ID)) +define(MY_MULTIBAND_DRC_CTRL, concat(`multiband_drc_control_', PIPELINE_ID)) +include(`multiband_drc_coef_default.m4') +C_CONTROLBYTES(MY_MULTIBAND_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + MULTIBAND_DRC_priv) + +# Mixer 0 has 2 sink and source periods. +W_MIXER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE) + +# "MULTIBAND_DRC" has 2 sink periods and 2 source periods +W_MULTIBAND_DRC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_MULTIBAND_DRC_CTRL")) + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs - FIXME WHY 0? +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS, COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Graph connections to pipelines +# we don't connect `dapm(N_MIXER(0), DAI_BUF)' due to forward dependencies +# +P_GRAPH(DAI_NAME, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_MIXER(0))', + `dapm(N_MULTIBAND_DRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_MULTIBAND_DRC(0))' + `dapm(N_DAI_OUT, N_BUFFER(1))')) + +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) +indir(`define', concat(`PIPELINE_MIXER_', PIPELINE_ID), N_MIXER(0)) + +undefine(`MY_MULTIBAND_DRC_CTRL') +undefine(`MULTIBAND_DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-mixer-volume-dai-playback.m4 b/tools/topology/topology1/sof/pipe-mixer-volume-dai-playback.m4 new file mode 100644 index 000000000000..0ddc581c6173 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mixer-volume-dai-playback.m4 @@ -0,0 +1,88 @@ +# Mixer DAI Playback connector +# +# DAI playback starting with a LL mixer +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Playback Volume B1 (DAI buffer) +# +# DAI_BUF --> ll mixer(M) --> B0 --> volume(LL) --> B1 --> sink DAI +# +# the ll mixer is connected to one DAI_BUF by default. Additional ones can be added later + +# Include topology builder +include(`utils.m4') +include(`mixer.m4') +include(`mixercontrol.m4') +include(`pga.m4') +include(`buffer.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# Mixer 0 has 2 sink and source periods. +W_MIXER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE) + +# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs - FIXME WHY 0? +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS, COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS,COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Graph connections to pipelines +# we don't connect `dapm(N_MIXER(0), DAI_BUF)' due to forward dependencies +# +P_GRAPH(DAI_NAME, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_MIXER(0))', + `dapm(N_PGA(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_PGA(0))' + `dapm(N_DAI_OUT, N_BUFFER(1))')) + +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) +indir(`define', concat(`PIPELINE_MIXER_', PIPELINE_ID), N_MIXER(0)) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-multiband-drc-capture.m4 b/tools/topology/topology1/sof/pipe-multiband-drc-capture.m4 new file mode 100644 index 000000000000..0034fc4b747f --- /dev/null +++ b/tools/topology/topology1/sof/pipe-multiband-drc-capture.m4 @@ -0,0 +1,75 @@ +# Multiband DRC with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P <-- B0 <-- MULTIBAND_DRC <-- B1 <-- sink DAI + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`multiband_drc.m4') + +# +# Components and Buffers +# + +# Host "Multiband DRC Capture" PCM +# with 0 sink and 3 source periods +W_PCM_CAPTURE(PCM_ID, Multiband DRC Capture, 0, 3, SCHEDULE_CORE) + +define(MULTIBAND_DRC_priv, concat(`multiband_drc_bytes_', PIPELINE_ID)) +define(MY_MULTIBAND_DRC_CTRL, concat(`multiband_drc_control_', PIPELINE_ID)) +include(`multiband_drc_coef_default.m4') +C_CONTROLBYTES(MY_MULTIBAND_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + MULTIBAND_DRC_priv) + +# "MULTIBAND_DRC" has 2 sink periods and 2 source periods +W_MULTIBAND_DRC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_MULTIBAND_DRC_CTRL")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- MULTIBAND_DRC <-- B1 <-- sink DAI + +P_GRAPH(pipe-multiband-drc-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_MULTIBAND_DRC(0))', + `dapm(N_MULTIBAND_DRC(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Multiband DRC Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Multiband DRC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, + 16384, 65536, 65536) + +undefine(`MY_MULTIBAND_DRC_CTRL') +undefine(`MULTIBAND_DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-multiband-drc-playback.m4 b/tools/topology/topology1/sof/pipe-multiband-drc-playback.m4 new file mode 100644 index 000000000000..d7a2fef21a8e --- /dev/null +++ b/tools/topology/topology1/sof/pipe-multiband-drc-playback.m4 @@ -0,0 +1,82 @@ +# Multiband DRC with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> MULTIBAND_DRC --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') +include(`multiband_drc.m4') + +# +# Controls +# + +# +# Components and Buffers +# + +# Host "Multiband DRC Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Multiband DRC Playback, 2, 0, SCHEDULE_CORE) + +# +# Multiband DRC Configuration +# + +define(MULTIBAND_DRC_priv, concat(`multiband_drc_bytes_', PIPELINE_ID)) +define(MY_MULTIBAND_DRC_CTRL, concat(`multiband_drc_control_', PIPELINE_ID)) +include(`multiband_drc_coef_default.m4') +C_CONTROLBYTES(MY_MULTIBAND_DRC_CTRL, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + MULTIBAND_DRC_priv) + +# "MULTIBAND_DRC" has 2 sink periods and 2 source periods +W_MULTIBAND_DRC(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "MY_MULTIBAND_DRC_CTRL")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> MULTIBAND_DRC --> B1 --> sink DAI0 + +P_GRAPH(pipe-multiband-drc-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_MULTIBAND_DRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_MULTIBAND_DRC(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Multiband DRC Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Multiband DRC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`MY_MULTIBAND_DRC_CTRL') +undefine(`MULTIBAND_DRC_priv') diff --git a/tools/topology/topology1/sof/pipe-mux-dai-playback.m4 b/tools/topology/topology1/sof/pipe-mux-dai-playback.m4 new file mode 100644 index 000000000000..43ad0949a3cd --- /dev/null +++ b/tools/topology/topology1/sof/pipe-mux-dai-playback.m4 @@ -0,0 +1,70 @@ +# Mixer DAI Playback connector +# +# DAI playback starting with a LL mixer +# +# Pipeline Endpoints for connection are :- +# +# LL Playback Mixer (Mixer) +# LL Playback Volume B1 (DAI buffer) +# +# DAI_BUF --> ll mux(M) --> B0 --> sink DAI +# +# the ll mixer is connected to one DAI_BUF by default. Additional ones can be added later + +# Include topology builder +include(`utils.m4') +include(`muxdemux.m4') + +include(`buffer.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# Controls +# + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + + + + +# Mux 0 in MUX mode, has 2 sink and source periods. +#W_MUXDEMUX(name, mux0/demux1, format, periods_sink, periods_source, core, kcontrol_list) +W_MUXDEMUX(0, 0, PIPELINE_FORMAT, 4, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs - FIXME WHY 0? +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(DAI_FORMAT), DAI_CHANNELS, COMP_PERIOD_FRAMES(DAI_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Graph connections to pipelines +# we don't connect `dapm(N_MIXER(0), DAI_BUF)' due to forward dependencies +# +P_GRAPH(DAI_NAME, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_MUXDEMUX(0))', + `dapm(N_DAI_OUT, N_BUFFER(0))')) + +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) +indir(`define', concat(`PIPELINE_MUX_', PIPELINE_ID), N_MUXDEMUX(0)) + diff --git a/tools/topology/sof/pipe-passthrough-capture-sched.m4 b/tools/topology/topology1/sof/pipe-passthrough-capture-sched.m4 similarity index 78% rename from tools/topology/sof/pipe-passthrough-capture-sched.m4 rename to tools/topology/topology1/sof/pipe-passthrough-capture-sched.m4 index 948583f6c5a1..af139226d9f5 100644 --- a/tools/topology/sof/pipe-passthrough-capture-sched.m4 +++ b/tools/topology/topology1/sof/pipe-passthrough-capture-sched.m4 @@ -17,7 +17,7 @@ include(`pipeline.m4') # Host "Passthrough Capture" PCM # with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, DAI_PERIODS) +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, DAI_PERIODS, SCHEDULE_CORE) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, @@ -32,7 +32,7 @@ VIRTUAL_WIDGET(ECHO REF PIPELINE_ID, out_drv, PIPELINE_ID) # # host PCM_C <-- B0 <-- sink DAI0 -P_GRAPH(pipe-pass-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-passthrough-capture-sched, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), ECHO REF PIPELINE_ID)')) @@ -47,4 +47,4 @@ W_PIPELINE(N_PCMC(PCM_ID), SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SC # PCM Configuration # -PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/topology1/sof/pipe-passthrough-capture.m4 b/tools/topology/topology1/sof/pipe-passthrough-capture.m4 new file mode 100644 index 000000000000..5dffa6dcd17f --- /dev/null +++ b/tools/topology/topology1/sof/pipe-passthrough-capture.m4 @@ -0,0 +1,51 @@ +# Capture Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, DAI_PERIODS, SCHEDULE_CORE) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- sink DAI0 + +P_GRAPH(pipe-passthrough-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) + +ifdef(`CHANNELS_MIN',`define(`LOCAL_CHANNELS_MIN', `CHANNELS_MIN')', +`define(`LOCAL_CHANNELS_MIN', `PIPELINE_CHANNELS')') + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Capture PCM_ID, COMP_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, LOCAL_CHANNELS_MIN, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`LOCAL_CHANNELS_MIN') diff --git a/tools/topology/topology1/sof/pipe-passthrough-playback.m4 b/tools/topology/topology1/sof/pipe-passthrough-playback.m4 new file mode 100644 index 000000000000..b505a128b77a --- /dev/null +++ b/tools/topology/topology1/sof/pipe-passthrough-playback.m4 @@ -0,0 +1,51 @@ +# Low Latency Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> sink DAI0 + +P_GRAPH(pipe-passthrough-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +ifdef(`CHANNELS_MIN',`define(`LOCAL_CHANNELS_MIN', `CHANNELS_MIN')', +`define(`LOCAL_CHANNELS_MIN', `2')') + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, COMP_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, LOCAL_CHANNELS_MIN, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`LOCAL_CHANNELS_MIN') diff --git a/tools/topology/sof/pipe-pcm-media.m4 b/tools/topology/topology1/sof/pipe-pcm-media.m4 similarity index 81% rename from tools/topology/sof/pipe-pcm-media.m4 rename to tools/topology/topology1/sof/pipe-pcm-media.m4 index 3a3157b24472..3df302af8599 100644 --- a/tools/topology/sof/pipe-pcm-media.m4 +++ b/tools/topology/topology1/sof/pipe-pcm-media.m4 @@ -26,7 +26,7 @@ C_CONTROLMIXER(PCM PCM_ID Playback Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # # SRC Configuration @@ -40,11 +40,14 @@ W_DATA(media_src_conf, media_src_tokens) # Volume Configuration # -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' - ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) -W_DATA(playback_pga_conf, playback_pga_tokens) +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) # # Components and Buffers @@ -52,10 +55,11 @@ W_DATA(playback_pga_conf, playback_pga_tokens) # Host "Media Playback" PCM # with 2 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, Media Playback, 2, 0) +W_PCM_PLAYBACK(PCM_ID, Media Playback, 2, 0, SCHEDULE_CORE) # "Playback Volume" has 3 sink period and 2 source periods for host ping-pong -W_PGA(0, PIPELINE_FORMAT, 3, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID PCM PCM_ID Playback Volume")) +W_PGA(0, PIPELINE_FORMAT, 3, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID PCM PCM_ID Playback Volume")) # "SRC 0" has 3 sink and source periods. W_SRC(0, PIPELINE_FORMAT, 3, 3, media_src_conf) @@ -79,7 +83,7 @@ W_BUFFER(2, COMP_BUFFER_SIZE(3, # PCM --B0--> volume --B1--> SRC --> B2 --> Endpoint Pipeline # -P_GRAPH(pipe-media-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-pcm-media, PIPELINE_ID, LIST(` ', `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', `dapm(N_PGA(0), N_BUFFER(0))', @@ -104,7 +108,7 @@ W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDU # PCM capabilities supported by FW -PCM_CAPABILITIES(Media Playback PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(Media Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) @@ -126,3 +130,6 @@ SectionPCM.STR(Media Playback PCM_ID) { capabilities STR(Media Playback PCM_ID) } } + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-pcm-mux.m4 b/tools/topology/topology1/sof/pipe-pcm-mux.m4 new file mode 100644 index 000000000000..9f95c11d421a --- /dev/null +++ b/tools/topology/topology1/sof/pipe-pcm-mux.m4 @@ -0,0 +1,87 @@ +# Low Power PCM Media Pipeline +# +# Low power PCM media playback with volume. +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --B0--> volume(0P) --B1--> Endpoint Pipeline +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`muxdemux.m4') +include(`pipeline.m4') +include(`pcm.m4') +include(`bytecontrol.m4') + +# +# Controls +# + + + +# +# Components and Buffers +# + +# Host "Media Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Media Playback MUX, 8, 0, SCHEDULE_CORE) + +# Media Source Buffers to SRC +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) + +# +# Pipeline Graph +# +# PCM --B0 --> Endpoint Pipeline + + +P_GRAPH(pipe-pcm-mux, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))')) + + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(0)) + + +# +# Pipeline Configuration. +# +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + + +# +# PCM Configuration +# + +# PCM capabilities supported by FW + +PCM_CAPABILITIES(Media Playback MUX PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +# PCM Media Playback +SectionPCM.STR(Media Playback MUX PCM_ID) { + + index STR(PIPELINE_ID) + + # used for binding to the PCM + id STR(PCM_ID) + + dai.STR(Media Playback MUX PCM_ID) { + id STR(PCM_ID) + } + + # Playback Configuration + pcm."playback" { + + capabilities STR(Media Playback MUX PCM_ID) + } +} diff --git a/tools/topology/topology1/sof/pipe-processing-playback.m4 b/tools/topology/topology1/sof/pipe-processing-playback.m4 new file mode 100644 index 000000000000..2af9d7fcf0fc --- /dev/null +++ b/tools/topology/topology1/sof/pipe-processing-playback.m4 @@ -0,0 +1,46 @@ +# Low Latency Passthrough Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> CODEC_ADAPTER(PP) --> B1 --> sink DAI0 + +# codec Post Process setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x5C,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x01,0x01,0xDE,0xCA,0x00,0x00,0x00,0x00,' +` 0x80,0xBB,0x00,0x00,0x20,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,0x40,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,' +` 0x80,0xBB,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,0x20,0x00,0x00,0x00,' +` 0x03,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,' +` 0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,0x02,0x00,0x00,0x00,' +` 0x05,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00"'' +) +define(`CA_SETUP_CONTROLBYTES_MAX', 300) + +# codec Post Process runtime params +define(`CA_RUNTIME_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"'' +) +define(`CA_RUNTIME_CONTROLBYTES_MAX', 157) + +define(`CA_SCHEDULE_CORE', 1) + +define(`CA_SETUP_CONTROLBYTES_NAME', `Post Process Setup Config') +define(`CA_RUNTIME_CONTROLBYTES_NAME', `Post Process Runtime Config') + +undefine(`DAI_PERIODS') +define(`DAI_PERIODS', 8) + +# Include codec adapter playback topology +include(`sof/pipe-codec-adapter-playback.m4') diff --git a/tools/topology/topology1/sof/pipe-rtnr-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-rtnr-capture-16khz.m4 new file mode 100644 index 000000000000..eafb348b5e26 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-rtnr-capture-16khz.m4 @@ -0,0 +1,127 @@ +# Capture RTNR Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <--- B1 <--- RTNR 0 <-- B0 <-- sink DAI0 +# +# +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`rtnr.m4') + +ifdef(`RTNR_BUFFER_SIZE_MIN',`', define(RTNR_BUFFER_SIZE_MIN, `65536')) +ifdef(`RTNR_BUFFER_SIZE_MAX',`', define(RTNR_BUFFER_SIZE_MAX, `65536')) +# +# Controls +# + +define(DEF_RTNR_PRIV, concat(`rtnr_priv_', PIPELINE_ID)) +define(DEF_RTNR_BYTES, concat(`rtnr_bytes_', PIPELINE_ID)) +define(DEF_RTNR_DATA, concat(`rtnr_data', PIPELINE_ID)) +define(DEF_RTNR_DATA_BYTES, concat(`rtnr_data_', PIPELINE_ID)) + +CONTROLBYTES_PRIV(DEF_RTNR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x30,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x80,0x3e,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# RTNR Bytes control with max value of 255 +C_CONTROLBYTES(DEF_RTNR_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 256), + , + DEF_RTNR_PRIV) + +CONTROLBYTES_PRIV(DEF_RTNR_DATA, +` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x30,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# Bytes control for RTNR Data blob +C_CONTROLBYTES(DEF_RTNR_DATA_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 10240), + , + DEF_RTNR_DATA) + +# RTNR Enable switch +define(DEF_RTNR_ENABLE, concat(`rtnr_enable_', PIPELINE_ID)) +define(`CONTROL_NAME', `DEF_RTNR_ENABLE') + +C_CONTROLMIXER(DEF_RTNR_ENABLE, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# +# Components and Buffers +# + +# Host "Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Capture, 0, 2, DMIC_PIPELINE_16k_CORE_ID) + +# "RTNR 0" has 2 sink period and 2 source periods +W_RTNR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_RTNR_BYTES", "DEF_RTNR_DATA_BYTES"), + LIST(` ', "DEF_RTNR_ENABLE")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(4, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(4, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +P_GRAPH(pipe-rtnr-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_RTNR(0))', + `dapm(N_RTNR(0), N_BUFFER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, RTNR_BUFFER_SIZE_MIN, RTNR_BUFFER_SIZE_MAX) + +undefine(`DEF_RTNR_ENABLE') +undefine(`DEF_RTNR_PRIV') +undefine(`DEF_RTNR_BYTES') +undefine(`DEF_RTNR_DATA') +undefine(`DEF_RTNR_DATA_BYTES') diff --git a/tools/topology/topology1/sof/pipe-rtnr-capture.m4 b/tools/topology/topology1/sof/pipe-rtnr-capture.m4 new file mode 100644 index 000000000000..b40f6bc6d286 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-rtnr-capture.m4 @@ -0,0 +1,127 @@ +# Capture RTNR Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <--- B1 <--- RTNR 0 <-- B0 <-- sink DAI0 +# +# +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`rtnr.m4') + +ifdef(`RTNR_BUFFER_SIZE_MIN',`', define(RTNR_BUFFER_SIZE_MIN, `65536')) +ifdef(`RTNR_BUFFER_SIZE_MAX',`', define(RTNR_BUFFER_SIZE_MAX, `65536')) +# +# Controls +# + +define(DEF_RTNR_PRIV, concat(`rtnr_priv_', PIPELINE_ID)) +define(DEF_RTNR_BYTES, concat(`rtnr_bytes_', PIPELINE_ID)) +define(DEF_RTNR_DATA, concat(`rtnr_data', PIPELINE_ID)) +define(DEF_RTNR_DATA_BYTES, concat(`rtnr_data_', PIPELINE_ID)) + +CONTROLBYTES_PRIV(DEF_RTNR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x30,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x80,0xbb,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# RTNR Bytes control with max value of 255 +C_CONTROLBYTES_READONLY(DEF_RTNR_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get handlers, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 256), + , + DEF_RTNR_PRIV) + +CONTROLBYTES_PRIV(DEF_RTNR_DATA, +` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x30,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# Bytes control for RTNR Data blob +C_CONTROLBYTES(DEF_RTNR_DATA_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 10240), + , + DEF_RTNR_DATA) + +# RTNR Enable switch +define(DEF_RTNR_ENABLE, concat(`rtnr_enable_', PIPELINE_ID)) +define(`CONTROL_NAME', `DEF_RTNR_ENABLE') + +C_CONTROLMIXER(DEF_RTNR_ENABLE, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# +# Components and Buffers +# + +# Host "Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Capture, 0, 2, SCHEDULE_CORE) + +# "RTNR 0" has 2 sink period and 2 source periods +W_RTNR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_RTNR_BYTES", "DEF_RTNR_DATA_BYTES"), + LIST(` ', "DEF_RTNR_ENABLE")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(4, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(4, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +P_GRAPH(pipe-rtnr-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_RTNR(0))', + `dapm(N_RTNR(0), N_BUFFER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, RTNR_BUFFER_SIZE_MIN, RTNR_BUFFER_SIZE_MAX) + +undefine(`DEF_RTNR_ENABLE') +undefine(`DEF_RTNR_PRIV') +undefine(`DEF_RTNR_BYTES') +undefine(`DEF_RTNR_DATA') +undefine(`DEF_RTNR_DATA_BYTES') diff --git a/tools/topology/topology1/sof/pipe-rtnr-google-rtc-audio-processing-capture.m4 b/tools/topology/topology1/sof/pipe-rtnr-google-rtc-audio-processing-capture.m4 new file mode 100644 index 000000000000..6e5f3cd7aacc --- /dev/null +++ b/tools/topology/topology1/sof/pipe-rtnr-google-rtc-audio-processing-capture.m4 @@ -0,0 +1,156 @@ +# Acoustic echo cancelling Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <- NC <-- B1 <-- AEC <-- B2 <-- source DAI0 +# ^----- B3 <-- AEC reference + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`google_rtc_audio_processing.m4') +include(`rtnr.m4') + +define(GOOGLE_RTC_AUDIO_PROCESSING_priv, concat(`google_rtc_audio_processing_bytes_', PIPELINE_ID)) +define(GOOGLE_RTC_AUDIO_PROCESSING_CTRL, concat(`google_rtc_audio_processing_control_', PIPELINE_ID)) + +include(`google_rtc_audio_processing_default.m4') + +define(DEF_RTNR_PRIV, concat(`rtnr_priv_', PIPELINE_ID)) +define(DEF_RTNR_BYTES, concat(`rtnr_bytes_', PIPELINE_ID)) +define(DEF_RTNR_DATA, concat(`rtnr_data', PIPELINE_ID)) +define(DEF_RTNR_DATA_BYTES, concat(`rtnr_data_', PIPELINE_ID)) + +ifdef(`RTNR_BUFFER_SIZE_MIN',`', define(RTNR_BUFFER_SIZE_MIN, `65536')) +ifdef(`RTNR_BUFFER_SIZE_MAX',`', define(RTNR_BUFFER_SIZE_MAX, `65536')) + +CONTROLBYTES_PRIV(DEF_RTNR_PRIV, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x30,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,' +` 0x80,0xbb,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# RTNR Bytes control with max value of 255 +C_CONTROLBYTES_READONLY(DEF_RTNR_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 256), + , + DEF_RTNR_PRIV) + +CONTROLBYTES_PRIV(DEF_RTNR_DATA, +` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x30,0x01,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# Bytes control for RTNR Data blob +C_CONTROLBYTES(DEF_RTNR_DATA_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 10240), + , + DEF_RTNR_DATA) + +# RTNR Enable switch +define(DEF_RTNR_ENABLE, concat(`rtnr_enable_', PIPELINE_ID)) +define(`CONTROL_NAME', `DEF_RTNR_ENABLE') + +C_CONTROLMIXER(DEF_RTNR_ENABLE, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +C_CONTROLBYTES(`Config', PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 2048), + , + GOOGLE_RTC_AUDIO_PROCESSING_priv) + +# +# Components and Buffers +# + +# Host "Google RTC Audio Processing Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Google RTC Audio Processing, 0, DAI_PERIODS, SCHEDULE_CORE) + +W_GOOGLE_RTC_AUDIO_PROCESSING(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + `', + LIST(` ', "Config")) + +# "RTNR 0" has 2 sink period and 2 source periods +W_RTNR(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_RTNR_BYTES", "DEF_RTNR_DATA_BYTES"), + LIST(` ', "DEF_RTNR_ENABLE")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +define(`N_AEC_REF_BUF',`BUF'PIPELINE_ID`.'3) +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- RTNR0 <-- B1 <-- AEC0 <-- B2 <-- sink DAI0 +# ^------- B3 <-- AEC ref + +P_GRAPH(pipe-google-aec-capture-PIPELINE_ID, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_RTNR(0))', + `dapm(N_RTNR(0), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_GOOGLE_RTC_AUDIO_PROCESSING(0))', + `dapm(N_GOOGLE_RTC_AUDIO_PROCESSING(0), N_BUFFER(2))', + `dapm(N_GOOGLE_RTC_AUDIO_PROCESSING(0), N_BUFFER(3))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Google RTC Audio Processing PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Google RTC Audio Processing PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_RTNR_ENABLE') +undefine(`DEF_RTNR_PRIV') +undefine(`DEF_RTNR_BYTES') +undefine(`DEF_RTNR_DATA') +undefine(`DEF_RTNR_DATA_BYTES') diff --git a/tools/topology/topology1/sof/pipe-smart-amplifier-playback.m4 b/tools/topology/topology1/sof/pipe-smart-amplifier-playback.m4 new file mode 100644 index 000000000000..ecef178f553c --- /dev/null +++ b/tools/topology/topology1/sof/pipe-smart-amplifier-playback.m4 @@ -0,0 +1,148 @@ +# Smart amplifier playback Pipeline +# +# Playback with smart_amp(Smart Amplifier), it will take the feedback(B2) from capture pipeline. +# +# Pipeline Endpoints for connection are :- +# +# Playback smart_amp +# B1 (DAI buffer) +# +# +# host PCM_P -- B0 --> smart_amp -- B1--> sink DAI0 +# ^ +# | +# B2 +# | + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`smart_amp.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') + +ifdef(`SMART_TX_CHANNELS',`',`fatal_error(note: Need to define DAI TX channel number for sof-smart-amplifier +)') +ifdef(`SMART_FB_CHANNELS',`',`fatal_error(note: Need to define feedback channel number for sof-smart-amplifier +)') + +DECLARE_SOF_RT_UUID("smart_amp-test", smart_amp_comp_uuid, 0x167a961e, 0x8ae4, + 0x11ea, 0x89, 0xf1, 0x00, 0x0c, 0x29, 0xce, 0x16, 0x35) +ifdef(`SMART_UUID',`', `define(`SMART_UUID', smart_amp_comp_uuid)'); +# +# Controls +# + +# initial config params for smart_amp, aligned with struct sof_smart_amp_config +ifelse(SMART_FB_CHANNELS, `8', +`define(`FB_CHMAP',`0xff,0xff,0x00,0x01,0xff,0xff,0xff,0xff')', +`define(`FB_CHMAP',`0x00,0x01,0x02,0x03,0xff,0xff,0xff,0xff')' +) + +CONTROLBYTES_PRIV(SMART_AMP_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,DEC2HEX(SMART_FB_CHANNELS),0x00,0x00,0x00,' +` 0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,' +` FB_CHMAP"') + +# Smart_amp Bytes control for config +C_CONTROLBYTES(Smart_amp Config, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + SMART_AMP_priv) + +# Algorithm Model initial parameters, just empty one at this moment. +CONTROLBYTES_PRIV(MODEL_priv, +` bytes "0x53,0x4f,0x46,0x00,0x01,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"' +) + +# Detector Bytes control for Hotword Model blob +C_CONTROLBYTES(Smart_amp Model, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 300000), + , + MODEL_priv) + + +ifelse(SOF_ABI_VERSION_3_17_OR_GRT, `1', +C_CONTROLBYTES_VOLATILE_READONLY(Smart_amp Model_Get_params, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get handlers, 258, 258), + CONTROLBYTES_EXTOPS_READONLY(260 binds the mixer control to bytes get handlers, 260), + , , , + CONTROLBYTES_MAX(, 300000), + , + MODEL_priv)) + +# +# Components and Buffers +# + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Smart Amplifier Playback, 2, 0, SCHEDULE_CORE) + +# Mux 0 has 2 sink and source periods. +W_SMART_AMP(0, SMART_UUID, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "Smart_amp Config", "Smart_amp Model", + ifelse(SOF_ABI_VERSION_3_17_OR_GRT, `1', "Smart_amp Model_Get_params"))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), SMART_TX_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), SMART_FB_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +#define REF buffer name for up layer connection +define(`N_SMART_REF_BUF',`BUF'PIPELINE_ID`.'2) + +# +# Pipeline Graph +# +# host PCM_P --B0--> smart_amp --B1--> sink DAI0 +# ^ +# |--B2-- + +P_GRAPH(pipe-smart-amplifier-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_SMART_AMP(0), N_BUFFER(0))', + `dapm(N_SMART_AMP(0), N_BUFFER(2))', + `dapm(N_BUFFER(1), N_SMART_AMP(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Smart Amplifier Playback PCM_ID) + +# +# PCM Configuration +# + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Smart Amplifier Playback PCM_ID, + CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + 48000, 48000, dnl rate_min, rate_max + SMART_PB_CH_NUM, SMART_PB_CH_NUM, dnl channels_min, channels_max + 2, 16, dnl periods_min, periods_max + 192, 16384, dnl period_size_min, period_size_max + 65536, 65536) + diff --git a/tools/topology/sof/pipe-src-capture.m4 b/tools/topology/topology1/sof/pipe-src-capture.m4 similarity index 90% rename from tools/topology/sof/pipe-src-capture.m4 rename to tools/topology/topology1/sof/pipe-src-capture.m4 index 0fe98915baee..fdf4c3ac3deb 100644 --- a/tools/topology/sof/pipe-src-capture.m4 +++ b/tools/topology/topology1/sof/pipe-src-capture.m4 @@ -18,7 +18,7 @@ include(`dai.m4') # Host "SRC Capture" PCM # with 0 sink and 3 source periods -W_PCM_CAPTURE(PCM_ID, SRC Capture, 0, 3) +W_PCM_CAPTURE(PCM_ID, SRC Capture, 0, 3, SCHEDULE_CORE) # # SRC Configuration @@ -50,7 +50,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_C <-- B0 <-- SRC <-- B1 <-- source DAI0 -P_GRAPH(pipe-pass-src-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-src-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_SRC(0))', @@ -66,7 +66,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), SRC Capture PCM_ID) # PCM Configuration # -PCM_CAPABILITIES(SRC Capture PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(SRC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-src-playback.m4 b/tools/topology/topology1/sof/pipe-src-playback.m4 similarity index 90% rename from tools/topology/sof/pipe-src-playback.m4 rename to tools/topology/topology1/sof/pipe-src-playback.m4 index 855d11816e29..2e0707f76229 100644 --- a/tools/topology/sof/pipe-src-playback.m4 +++ b/tools/topology/topology1/sof/pipe-src-playback.m4 @@ -18,7 +18,7 @@ include(`pipeline.m4') # Host "SRC Playback" PCM # with 3 sink and 0 source periods -W_PCM_PLAYBACK(PCM_ID, SRC Playback, 3, 0) +W_PCM_PLAYBACK(PCM_ID, SRC Playback, 3, 0, SCHEDULE_CORE) # # SRC Configuration @@ -50,7 +50,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_P --> B0 --> SRC 0 --> B1 --> sink DAI0 -P_GRAPH(pipe-pass-src-playback-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-src-playback, PIPELINE_ID, LIST(` ', `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', `dapm(N_SRC(0), N_BUFFER(0))', @@ -66,7 +66,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), SRC Playback PCM_ID) # PCM Configuration # -PCM_CAPABILITIES(SRC Playback PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(SRC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-src-volume-capture.m4 b/tools/topology/topology1/sof/pipe-src-volume-capture.m4 similarity index 90% rename from tools/topology/sof/pipe-src-volume-capture.m4 rename to tools/topology/topology1/sof/pipe-src-volume-capture.m4 index 9be2d22d6aec..94a25280c465 100644 --- a/tools/topology/sof/pipe-src-volume-capture.m4 +++ b/tools/topology/topology1/sof/pipe-src-volume-capture.m4 @@ -27,7 +27,7 @@ C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # Volume Configuration define(MY_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) @@ -44,7 +44,7 @@ W_DATA(MY_PGA_CONF, MY_PGA_TOKENS) # Host "Passthrough Capture" PCM # with 0 sink and 3 source periods -W_PCM_CAPTURE(PCM_ID, SRC Capture, 0, 3) +W_PCM_CAPTURE(PCM_ID, SRC Capture, 0, 3, SCHEDULE_CORE) # # SRC Configuration @@ -63,7 +63,7 @@ W_DATA(MY_SRC_CONF, MY_SRC_TOKENS) W_SRC(0, PIPELINE_FORMAT, 3, 3, MY_SRC_CONF) # "Volume" has x source and 3 sink periods -W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 3, MY_PGA_CONF, +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 3, MY_PGA_CONF, SCHEDULE_CORE, LIST(` ', "PIPELINE_ID Master Capture Volume")) # Capture Buffers @@ -85,7 +85,7 @@ W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_C <-- B0 <-- SRC <-- B1 <-- PGA <-- B2 <-- sink DAI0 -P_GRAPH(pipe-pass-src-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-src-volume-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_SRC(0))', @@ -104,7 +104,7 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), # PCM Configuration # -PCM_CAPABILITIES(SRC Capture PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(SRC Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/topology1/sof/pipe-src-volume-playback.m4 b/tools/topology/topology1/sof/pipe-src-volume-playback.m4 new file mode 100644 index 000000000000..13378f9f404e --- /dev/null +++ b/tools/topology/topology1/sof/pipe-src-volume-playback.m4 @@ -0,0 +1,102 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> SRC --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`src.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Components and Buffers +# + +# Host "SRC Playback" PCM +# with 3 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, SRC Playback, 3, 0, SCHEDULE_CORE) + +# +# SRC Configuration +# + +W_VENDORTUPLES(media_src_tokens, sof_src_tokens, LIST(` ', `SOF_TKN_SRC_RATE_OUT "PIPELINE_RATE"')) + +W_DATA(media_src_conf, media_src_tokens) + +# "SRC" has 3 source and 3 sink periods +W_SRC(0, PIPELINE_FORMAT, 3, 3, media_src_conf) + +# +# Volume Configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# "Volume" has 3 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 3, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(3, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> SRC 0 --> B1 Volume 0 --> B2 --> sink DAI0 + +P_GRAPH(pipe-src-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_SRC(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_SRC(0))', + `dapm(N_PGA(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), SRC Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(SRC Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 8000, 192000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-tdfb-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-tdfb-capture-16khz.m4 new file mode 100644 index 000000000000..1de43636f36b --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-capture-16khz.m4 @@ -0,0 +1,84 @@ +# Capture TDFB Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- TDFB 0 <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls.m4') + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- TDFB 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-capture-16khz, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb-capture.m4 b/tools/topology/topology1/sof/pipe-tdfb-capture.m4 new file mode 100644 index 000000000000..2a7fc4d98e7e --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-capture.m4 @@ -0,0 +1,84 @@ +# Capture TDFB Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- TDFB 0 <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough configuration is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls.m4') + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- TDFB 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb-eq-iir-volume-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-tdfb-eq-iir-volume-capture-16khz.m4 new file mode 100644 index 000000000000..ca075498e68d --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-eq-iir-volume-capture-16khz.m4 @@ -0,0 +1,176 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') +include(`eq_iir.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', 2nd Capture Volume) +define(`CONTROL_NAME_SWITCH', 2nd Capture Switch) + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include controls: binary, enums +# byte control in DEF_TDFB_BYTES +# enum controls in DEF_TDFB_ONOFF_ENUM, DEF_TDFB_DIRECTION_ENUM +include(`tdfb_controls.m4') + +# Volume Mixer control with max value of 32 +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +undefine(`CONTROL_NAME') + +# Switch type Mixer Control with max value of 1 +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") +undefine(`CONTROL_NAME') + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use 40 Hz highpass response with +0 dB gain for 48khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_iir_coef_highpass_40hz_0db_16khz.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-eq-iir-volume-capture-16khz, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))', + `dapm(N_BUFFER(2), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(3))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb-eq-iir-volume-capture.m4 b/tools/topology/topology1/sof/pipe-tdfb-eq-iir-volume-capture.m4 new file mode 100644 index 000000000000..008df8f8f07e --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-eq-iir-volume-capture.m4 @@ -0,0 +1,175 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') +include(`eq_iir.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', Capture Volume) +define(`CONTROL_NAME_SWITCH', Capture Switch) + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls.m4') + +# Volume Mixer control with max value of 32 +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +undefine(`CONTROL_NAME') + +# Switch type Mixer Control with max value of 1 +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") +undefine(`CONTROL_NAME') + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use 40 Hz highpass response with +0 dB gain for 48khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "TDFB 0" has 2 sink period and x source periods +# Note that the controls will receive index values 0, 1, 2 in the order below +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-eq-iir-volume-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))', + `dapm(N_BUFFER(2), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(3))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb-playback.m4 b/tools/topology/topology1/sof/pipe-tdfb-playback.m4 new file mode 100644 index 000000000000..19fbd8006ee7 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-playback.m4 @@ -0,0 +1,84 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> TDFB 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`pipeline.m4') +include(`tdfb.m4') + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls.m4') + +# +# Components and Buffers +# + +# Host "TDFB Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, TDFB Playback, 2, 0) + +# "TDFB 0" has x sink period and 2 source periods +W_TDFB(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host host PCM_P --> B0 --> TDFB --> B3 --> sink DAI0 + +P_GRAPH(pipe-tdfb-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_TDFB(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_TDFB(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + TDFB Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(TDFB Playback PCM_ID, `S32_LE,S24_LE,S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb-volume-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-tdfb-volume-capture-16khz.m4 new file mode 100644 index 000000000000..c0f8cafd113c --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-volume-capture-16khz.m4 @@ -0,0 +1,139 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- TDFB 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', 2nd Capture Volume) +define(`CONTROL_NAME_SWITCH', 2nd Capture Switch) + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls.m4') + +# Volume Mixer control with max value of 32 +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) +undefine(`CONTROL_NAME') + +# Switch type Mixer Control with max value of 1 +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") +undefine(`CONTROL_NAME') + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- TDFB 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-volume-capture-16khz, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(2))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb-volume-capture.m4 b/tools/topology/topology1/sof/pipe-tdfb-volume-capture.m4 new file mode 100644 index 000000000000..c4158251d543 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb-volume-capture.m4 @@ -0,0 +1,139 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- TDFB 0 <-- B2 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', Capture Volume) +define(`CONTROL_NAME_SWITCH', Capture Switch) + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls.m4') + +# Volume Mixer control with max value of 32 +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) +undefine(`CONTROL_NAME') + +# Switch type Mixer Control with max value of 1 +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") +undefine(`CONTROL_NAME') + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- TDFB 0 <-- B2 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-volume-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(2))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb360-capture.m4 b/tools/topology/topology1/sof/pipe-tdfb360-capture.m4 new file mode 100644 index 000000000000..66d04b8f0abc --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb360-capture.m4 @@ -0,0 +1,84 @@ +# Capture TDFB Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- TDFB 0 <-- B1 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough configuration is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls_360.m4') + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- TDFB 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, `S32_LE,S24_LE,S16_LE', PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb360-eq-iir-volume-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-tdfb360-eq-iir-volume-capture-16khz.m4 new file mode 100644 index 000000000000..124241efdc00 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb360-eq-iir-volume-capture-16khz.m4 @@ -0,0 +1,176 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') +include(`eq_iir.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', 2nd Capture Volume) +define(`CONTROL_NAME_SWITCH', 2nd Capture Switch) + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include controls: binary, enums +# byte control in DEF_TDFB_BYTES +# enum controls in DEF_TDFB_ONOFF_ENUM, DEF_TDFB_DIRECTION_ENUM +include(`tdfb_controls_360.m4') + +# Volume Mixer control with max value of 32 +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +undefine(`CONTROL_NAME') + +# Switch type Mixer Control with max value of 1 +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") +undefine(`CONTROL_NAME') + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use 40 Hz highpass response with +0 dB gain for 48khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_iir_coef_highpass_40hz_0db_16khz.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "TDFB 0" has 2 sink period and x source periods +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-eq-iir-volume-capture-16khz, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))', + `dapm(N_BUFFER(2), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(3))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb360-eq-iir-volume-capture.m4 b/tools/topology/topology1/sof/pipe-tdfb360-eq-iir-volume-capture.m4 new file mode 100644 index 000000000000..43ec9f99bcc4 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb360-eq-iir-volume-capture.m4 @@ -0,0 +1,175 @@ +# Capture EQ Pipeline and PCM, 48 kHz +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`enumcontrol.m4') +include(`tdfb.m4') +include(`eq_iir.m4') + +ifdef(`PGA_NAME', `', `define(PGA_NAME, N_PGA(0))') +define(`CONTROL_NAME_VOLUME', Capture Volume) +define(`CONTROL_NAME_SWITCH', Capture Switch) + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls, -90 to +90 limited for line array +include(`tdfb_controls_360.m4') + +# Volume Mixer control with max value of 32 +define(`CONTROL_NAME', `CONTROL_NAME_VOLUME') +C_CONTROLMIXER(Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, + 256 binds the mixer control to volume get/put handlers, + 256, 256), + CONTROLMIXER_MAX(, 70), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +20dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +undefine(`CONTROL_NAME') + +# Switch type Mixer Control with max value of 1 +define(`CONTROL_NAME', `CONTROL_NAME_SWITCH') +C_CONTROLMIXER(Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + SWITCH_CHANNEL_MAP, + "1", "1") +undefine(`CONTROL_NAME') + +# Volume Configuration +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# By default, use 40 Hz highpass response with +0 dB gain for 48khz +# TODO: need to implement middle level macro handler per pipeline +ifdef(`PIPELINE_FILTER2', , `define(PIPELINE_FILTER2, eq_iir_coef_highpass_40hz_0db_48khz.m4)') +include(PIPELINE_FILTER2) + +# EQ Bytes control with max value of 255 +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS( + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "TDFB Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, TDFB Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has 2 source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "CONTROL_NAME_VOLUME", + "CONTROL_NAME_SWITCH")) + +# "EQ 0" has 2 sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# "TDFB 0" has 2 sink period and x source periods +# Note that the controls will receive index values 0, 1, 2 in the order below +W_TDFB(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), PLATFORM_PASS_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B0 <-- Volume <-- B1 <-- EQIIR <-- B2 <-- TDFB <-- B3 <-- sink DAI0 + +P_GRAPH(pipe-tdfb-eq-iir-volume-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), PGA_NAME)', + `dapm(PGA_NAME, N_BUFFER(1))', + `dapm(N_BUFFER(1), N_EQ_IIR(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))', + `dapm(N_BUFFER(2), N_TDFB(0))', + `dapm(N_TDFB(0), N_BUFFER(3))')) + +undefine(`PGA_NAME') +undefine(`CONTROL_NAME_VOLUME') +undefine(`CONTROL_NAME_SWITCH') + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), TDFB Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(TDFB Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, + PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') +include(`tdfb_undefines.m4') diff --git a/tools/topology/topology1/sof/pipe-tdfb360-playback.m4 b/tools/topology/topology1/sof/pipe-tdfb360-playback.m4 new file mode 100644 index 000000000000..1517dd655c4a --- /dev/null +++ b/tools/topology/topology1/sof/pipe-tdfb360-playback.m4 @@ -0,0 +1,84 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> TDFB 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`enumcontrol.m4') +include(`pipeline.m4') +include(`tdfb.m4') + +# +# Controls +# + +# defines with pipeline ID appended for unique names +include(`tdfb_defines.m4') + +# Define filter. A passthrough is set by default. +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, `tdfb/coef_line2_pass.m4')') +include(PIPELINE_FILTER1) + +# Include defines for TDBF controls +include(`tdfb_controls_360.m4') + +# +# Components and Buffers +# + +# Host "TDFB Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, TDFB Playback, 2, 0) + +# "TDFB 0" has x sink period and 2 source periods +W_TDFB(0, PIPELINE_FORMAT, DAI_PERIODS, 2, SCHEDULE_CORE, + LIST(` ', "DEF_TDFB_BEAM"), + LIST(` ', "DEF_TDFB_DIRECTION"), + LIST(` ', "DEF_TDFB_AZIMUTH"), + LIST(` ', "DEF_TDFB_AZIMUTH_ESTIMATE"), + LIST(` ', "DEF_TDFB_BYTES")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, + COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host host PCM_P --> B0 --> TDFB --> B3 --> sink DAI0 + +P_GRAPH(pipe-tdfb-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_TDFB(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_TDFB(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), + TDFB Playback PCM_ID) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(TDFB Playback PCM_ID, `S32_LE,S24_LE,S16_LE', + PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) + +include(`tdfb_undefines.m4') diff --git a/tools/topology/sof/pipe-tone.m4 b/tools/topology/topology1/sof/pipe-tone.m4 similarity index 80% rename from tools/topology/sof/pipe-tone.m4 rename to tools/topology/topology1/sof/pipe-tone.m4 index 5fa22de6abdd..030923fa6695 100644 --- a/tools/topology/sof/pipe-tone.m4 +++ b/tools/topology/topology1/sof/pipe-tone.m4 @@ -26,7 +26,7 @@ C_CONTROLMIXER(Tone Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # Switch type Mixer Control with max value of 1 C_CONTROLMIXER(Tone Switch, PIPELINE_ID, @@ -41,21 +41,26 @@ C_CONTROLMIXER(Tone Switch, PIPELINE_ID, # Volume configuration # -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) -W_DATA(playback_pga_conf, playback_pga_tokens) +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) # # Components and Buffers # # "Tone 0" has 2 sink period and 0 source periods -W_TONE(0, PIPELINE_FORMAT, 2, 0, LIST(` ', "PIPELINE_ID Tone Switch")) +W_TONE(0, PIPELINE_FORMAT, 2, 0, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Tone Switch")) # "Tone Volume" has 2 sink period and 2 source periods -W_PGA(0, PIPELINE_FORMAT, 2, 2, playback_pga_conf, LIST(` ', "PIPELINE_ID Tone Volume")) +W_PGA(0, PIPELINE_FORMAT, 2, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Tone Volume")) # Low Latency Buffers W_BUFFER(0,COMP_BUFFER_SIZE(2, @@ -72,7 +77,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(2, # Tone --B0--> volume --B1--> Endpoint Pipeline # -P_GRAPH(pipe-tone-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-tone, PIPELINE_ID, LIST(` ', `dapm(N_BUFFER(0), N_TONE(0))', `dapm(N_PGA(0), N_BUFFER(0))', @@ -88,3 +93,6 @@ indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) # W_PIPELINE(N_TONE(0), SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_tone_schedule_plat) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-virtual-passthrough-playback-sched.m4 b/tools/topology/topology1/sof/pipe-virtual-passthrough-playback-sched.m4 new file mode 100644 index 000000000000..be604675eaba --- /dev/null +++ b/tools/topology/topology1/sof/pipe-virtual-passthrough-playback-sched.m4 @@ -0,0 +1,57 @@ +# virtual playback passthrough pipeline and dai +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> virtual-playback-passthrough + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# Components and Buffers +# + +# Host "Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) + +# Virtual input widget +VIRTUAL_WIDGET(VIRTUAL PLAYBACK PASSTHROUGH PIPELINE_ID, input, PIPELINE_ID) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> virtual-playback-passthrough + +P_GRAPH(pipe-virtual-passthrough-playback-sched, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(VIRTUAL PLAYBACK PASSTHROUGH PIPELINE_ID, N_BUFFER(0))' )) +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Playback PCM_ID) + +# +# Pipeline Configuration. +# + +W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_media_schedule_plat) + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + diff --git a/tools/topology/topology1/sof/pipe-virtual-playback-passthrough.m4 b/tools/topology/topology1/sof/pipe-virtual-playback-passthrough.m4 new file mode 100644 index 000000000000..6e32944b3589 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-virtual-playback-passthrough.m4 @@ -0,0 +1,23 @@ +# +# The pipeline for virtual playback passthrough feature, it is used +# for the playback DAI to dock. +# +# No connections in this pipeline. +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') + +# +# DAI definitions +# +W_DAI_OUT(DAI_TYPE, DAI_INDEX, DAI_BE, DAI_FORMAT, 0, DAI_PERIODS, SCHEDULE_CORE) + +# +# DAI pipeline - always use 0 for DAIs +# +W_PIPELINE(N_DAI_OUT, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDULE_TIME_DOMAIN, pipe_dai_schedule_plat) + +indir(`define', concat(`PIPELINE_PLAYBACK_SCHED_COMP_', PIPELINE_ID), N_DAI_OUT) diff --git a/tools/topology/topology1/sof/pipe-vol-kfbm-capture.m4 b/tools/topology/topology1/sof/pipe-vol-kfbm-capture.m4 new file mode 100644 index 000000000000..2f91a27ac06b --- /dev/null +++ b/tools/topology/topology1/sof/pipe-vol-kfbm-capture.m4 @@ -0,0 +1,124 @@ +# Passthrough Capture Pipeline with KPBM and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-+- KPBM 0 <-- B1 <-- Volume 0 <-- B0 <-- source DAI0 +# | +# Others <--+ + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`kpbm.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`pipeline.m4') + +dnl Soun Trigger Stream Name) +define(`N_STS', `Sound Trigger Capture '$1) + +# +# Controls +# + +# kpbm initial parameters, aligned with struct sof_kpb_config +CONTROLBYTES_PRIV(KPB_priv, +` bytes "0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00,' +` 0x18,0x00,0x00,0x00,0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,' +` 0x80,0x3e,0x00,0x00,0x10,0x00,0x00,0x00"' +) + +# KPB Bytes control with max value of 255 +C_CONTROLBYTES(KPB, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , + KPB_priv) + +# Volume Mixer control with max value of 80 +C_CONTROLMIXER(KWD Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +W_VENDORTUPLES(capture_pga_tokens, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(capture_pga_conf, capture_pga_tokens) + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Sound Trigger Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has x source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, capture_pga_conf, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID KWD Capture Volume")) + +# "KPBM" has 2 source and 2 sink periods +W_KPBM(0, PIPELINE_FORMAT, 2, 2, PIPELINE_ID, SCHEDULE_CORE, + LIST(` ', "KPB")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) +# Capture Buffers +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +# Capture Buffers +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_C <-- B2 <--+- KPBM 0 <-- B1 <-- volume 0 <-- B0 <-- source DAI0 +# | +# Others <-- + +P_GRAPH(pipe-vol-kfbm-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(2))', + `dapm(N_BUFFER(2), N_KPBM(0, PIPELINE_ID))', + `dapm(N_KPBM(0, PIPELINE_ID), N_BUFFER(1))', + `dapm(N_BUFFER(1), N_PGA(0, PIPELINE_ID))', + `dapm(N_PGA(0, PIPELINE_ID), N_BUFFER(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(0)) +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_KPBM(0, PIPELINE_ID)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), N_PCMC(PCM_ID)) + +# +# PCM Configuration +# +dnl PCM_CAPTURE_LP_ADD(name, pipeline, capture) +PCM_CAPTURE_LP_ADD(DMIC_16k_PCM_NAME, PCM_ID, N_STS(PCM_ID)) + +PCM_CAPABILITIES(N_STS(PCM_ID), CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000, 2, PIPELINE_CHANNELS, 2, 160, 192, 256000, 256000, 1280000) + diff --git a/tools/topology/sof/pipe-volume-capture-16khz.m4 b/tools/topology/topology1/sof/pipe-volume-capture-16khz.m4 similarity index 76% rename from tools/topology/sof/pipe-volume-capture-16khz.m4 rename to tools/topology/topology1/sof/pipe-volume-capture-16khz.m4 index 23f88732ac9e..ce28e9c068d1 100644 --- a/tools/topology/sof/pipe-volume-capture-16khz.m4 +++ b/tools/topology/topology1/sof/pipe-volume-capture-16khz.m4 @@ -26,17 +26,20 @@ C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # # Volume configuration # -W_VENDORTUPLES(playback_pga_tokens, sof_volume_tokens, +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) -W_DATA(playback_pga_conf, playback_pga_tokens) +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) # # Components and Buffers @@ -44,10 +47,11 @@ W_DATA(playback_pga_conf, playback_pga_tokens) # Host "Passthrough Capture" PCM # with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2) +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2, SCHEDULE_CORE) # "Volume" has x source and 2 sink periods -W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, playback_pga_conf, LIST(` ', "PIPELINE_ID Master Capture Volume")) +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume")) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, @@ -62,7 +66,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- sink DAI0 -P_GRAPH(pipe-pass-vol-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-volume-capture-16khz, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_PGA(0))', @@ -78,6 +82,9 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID # PCM Configuration # -PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 16000, 16000, PIPELINE_CHANNELS, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/sof/pipe-volume-capture-sched.m4 b/tools/topology/topology1/sof/pipe-volume-capture-sched.m4 similarity index 81% rename from tools/topology/sof/pipe-volume-capture-sched.m4 rename to tools/topology/topology1/sof/pipe-volume-capture-sched.m4 index 955f96d1ccc6..e0f526149209 100644 --- a/tools/topology/sof/pipe-volume-capture-sched.m4 +++ b/tools/topology/topology1/sof/pipe-volume-capture-sched.m4 @@ -23,7 +23,7 @@ C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # # Components and Buffers @@ -31,10 +31,11 @@ C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, # Host "Passthrough Capture" PCM # with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2) +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2, SCHEDULE_CORE) # "Volume" has x source and 2 sink periods -W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, LIST(` ', "PIPELINE_ID Master Capture Volume")) +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume")) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, @@ -52,7 +53,7 @@ VIRTUAL_WIDGET(ECHO REF PIPELINE_ID, out_drv, PIPELINE_ID) # # host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- sink DAI0 -P_GRAPH(pipe-pass-vol-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-volume-capture-sched, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_PGA(0))', @@ -70,5 +71,5 @@ W_PIPELINE(SCHED_COMP, SCHEDULE_PERIOD, SCHEDULE_PRIORITY, SCHEDULE_CORE, SCHEDU # PCM Configuration # -PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/sof/pipe-volume-capture.m4 b/tools/topology/topology1/sof/pipe-volume-capture.m4 similarity index 78% rename from tools/topology/sof/pipe-volume-capture.m4 rename to tools/topology/topology1/sof/pipe-volume-capture.m4 index 4815df58e2ca..e208425bd55e 100644 --- a/tools/topology/sof/pipe-volume-capture.m4 +++ b/tools/topology/topology1/sof/pipe-volume-capture.m4 @@ -23,7 +23,7 @@ C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, false, CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), Channel register and shift for Front Left/Right, - LIST(` ', KCONTROL_CHANNEL(FL, 1, 0), KCONTROL_CHANNEL(FR, 1, 1))) + VOLUME_CHANNEL_MAP) # # Volume Configuration @@ -41,10 +41,11 @@ W_DATA(capture_pga_conf, capture_pga_tokens) # Host "Passthrough Capture" PCM # with 0 sink and 2 source periods -W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2) +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2, SCHEDULE_CORE) # "Volume" has x source and 2 sink periods -W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, capture_pga_conf, LIST(` ', "PIPELINE_ID Master Capture Volume")) +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, capture_pga_conf, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume")) # Capture Buffers W_BUFFER(0, COMP_BUFFER_SIZE(2, @@ -59,7 +60,7 @@ W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, # # host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- sink DAI0 -P_GRAPH(pipe-pass-vol-capture-PIPELINE_ID, PIPELINE_ID, +P_GRAPH(pipe-volume-capture, PIPELINE_ID, LIST(` ', `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', `dapm(N_BUFFER(0), N_PGA(0))', @@ -71,10 +72,13 @@ P_GRAPH(pipe-pass-vol-capture-PIPELINE_ID, PIPELINE_ID, indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) +ifdef(`CHANNELS_MIN', `define(`LOCAL_CHANNELS_MIN', `CHANNELS_MIN')', +`define(`LOCAL_CHANNELS_MIN', `2')') + # # PCM Configuration # -PCM_CAPABILITIES(Passthrough Capture PCM_ID, `S32_LE,S24_LE,S16_LE', - PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, LOCAL_CHANNELS_MIN, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/topology1/sof/pipe-volume-demux-playback.m4 b/tools/topology/topology1/sof/pipe-volume-demux-playback.m4 new file mode 100644 index 000000000000..b3c096ed4772 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-volume-demux-playback.m4 @@ -0,0 +1,110 @@ +# Demux Volume Pipeline +# +# Low Latency Playback with demux and volume. +# +# Pipeline Endpoints for connection are :- +# +# Playback Demux +# B2 (DAI buffer) +# +# +# host PCM_P -- B0 --> volume -- B1 --> Demux(M) -- B2 --> sink DAI0 +# | +# pipeline n+1 --> DAI +# + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`muxdemux.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0, SCHEDULE_CORE) + +# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong +W_PGA(1, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# Mux 0 has 2 sink and source periods. +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P -- B0 --> volume -- B1 --> Demux -- B2 --> sink DAI0 + +P_GRAPH(pipe-volume-demux-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_PGA(1), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_PGA(1))', + `dapm(N_MUXDEMUX(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_MUXDEMUX(0))')) +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Low Latency Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-volume-playback.m4 b/tools/topology/topology1/sof/pipe-volume-playback.m4 new file mode 100644 index 000000000000..93c515e4abe7 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-volume-playback.m4 @@ -0,0 +1,89 @@ +# Low Latency Passthrough with volume Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> Volume 0 --> B1 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "Passthrough Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, 2, 0, SCHEDULE_CORE) + +# "Volume" has 2 source and x sink periods +W_PGA(0, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> Volume 0 --> B1 --> sink DAI0 + +P_GRAPH(pipe-volume-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_PGA(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_PGA(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +ifdef(`CHANNELS_MIN',`define(`LOCAL_CHANNELS_MIN', `CHANNELS_MIN')', +`define(`LOCAL_CHANNELS_MIN', `2')') + +# +# PCM Configuration + +# +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, LOCAL_CHANNELS_MIN, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`LOCAL_CHANNELS_MIN') +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-volume-switch-capture.m4 b/tools/topology/topology1/sof/pipe-volume-switch-capture.m4 new file mode 100644 index 000000000000..e61cd45afc4b --- /dev/null +++ b/tools/topology/topology1/sof/pipe-volume-switch-capture.m4 @@ -0,0 +1,90 @@ +# Passthrough with volume/switch Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_C <-- B0 <-- Volume 0 <-- B1 <-- source DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`dai.m4') +include(`mixercontrol.m4') +include(`pipeline.m4') + +# +# Controls +# +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Capture Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 80), + false, + CONTROLMIXER_TLV(TLV 80 steps from -50dB to +30dB for 1dB, vtlv_m50s1), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +C_CONTROLMIXER(Master Capture Switch, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Left/Right, + LIST(` ', KCONTROL_CHANNEL(FL, 2, 0), KCONTROL_CHANNEL(FR, 2, 1)), + "1", "1") + +# +# Volume Configuration +# + +W_VENDORTUPLES(capture_pga_tokens, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "0"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "250"')) + +W_DATA(capture_pga_conf, capture_pga_tokens) + +# +# Components and Buffers +# + +# Host "Passthrough Capture" PCM +# with 0 sink and 2 source periods +W_PCM_CAPTURE(PCM_ID, Passthrough Capture, 0, 2, SCHEDULE_CORE) + +# "Volume" has x source and 2 sink periods +W_PGA(0, PIPELINE_FORMAT, 2, DAI_PERIODS, capture_pga_conf, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Capture Volume", "PIPELINE_ID Master Capture Switch")) + +# Capture Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P <-- B0 <-- Volume 0 <-- B1 <-- sink DAI0 + +P_GRAPH(pipe-volume-switch-capture, PIPELINE_ID, + LIST(` ', + `dapm(N_PCMC(PCM_ID), N_BUFFER(0))', + `dapm(N_BUFFER(0), N_PGA(0))', + `dapm(N_PGA(0), N_BUFFER(1))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SINK_', PIPELINE_ID), N_BUFFER(1)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Capture PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Capture PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), + PCM_MIN_RATE, PCM_MAX_RATE, PIPELINE_CHANNELS, PIPELINE_CHANNELS, + 2, 16, 192, 16384, 65536, 65536) diff --git a/tools/topology/topology1/sof/pipe-waves-codec-ctc-playback.m4 b/tools/topology/topology1/sof/pipe-waves-codec-ctc-playback.m4 new file mode 100644 index 000000000000..b885fcd10a94 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-waves-codec-ctc-playback.m4 @@ -0,0 +1,155 @@ +# Low Latency Waves codec and CTC Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> Waves codec --> B1 --> CTC --> B2 --> sink DAI0 + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`bytecontrol.m4') +include(`mixercontrol.m4') +include(`google_ctc_audio_processing.m4') + +ifdef(`ENDPOINT_NAME',`',`fatal_error(`Pipe requires ENDPOINT_NAME to be defined: Speakers, Headphones, etc.')') + +# Waves codec setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,' +` 0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' + +` 0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00"'' +) +define(`CA_SETUP_CONTROLBYTES_MAX', 8192) +define(`CA_SETUP_CONTROLBYTES_NAME', `Waves' `ENDPOINT_NAME' `Setup ') + +define(`CA_SCHEDULE_CORE', 0) + +DECLARE_SOF_RT_UUID("Waves codec", waves_codec_uuid, 0xd944281a, 0xafe9, + 0x4695, 0xa0, 0x43, 0xd7, 0xf6, 0x2b, 0x89, 0x53, 0x8e); +define(`CA_UUID', waves_codec_uuid) + +# Include codec_adapter after CA_UUID definition +include(`codec_adapter.m4') + +define(CA_SETUP_CONFIG, concat(`ca_setup_config_', PIPELINE_ID)) +define(CA_SETUP_CONTROLBYTES_NAME_PIPE, concat(CA_SETUP_CONTROLBYTES_NAME, PIPELINE_ID)) + +# Codec adapter setup config +CONTROLBYTES_PRIV(CA_SETUP_CONFIG, CA_SETUP_CONTROLBYTES) + +# Codec adapter Bytes control for setup config +C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(void, CA_SETUP_CONTROLBYTES_MAX), + , + CA_SETUP_CONFIG) + +define(DEF_CTC_PRIV, concat(`ctc_priv_', PIPELINE_ID)) +define(DEF_CTC_BYTES, concat(`ctc_bytes_', PIPELINE_ID)) +include(`google_ctc_audio_processing_coef_default.m4') + +# CTC Bytes control +C_CONTROLBYTES(DEF_CTC_BYTES, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, + 258 binds the mixer control to bytes get/put handlers, + 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, + 258, 258), + , , , + CONTROLBYTES_MAX(void, 4244), + , + DEF_CTC_PRIV) + +define(DEF_CTC_SWITCH, concat(`ctc_enable_', PIPELINE_ID)) +define(`CONTROL_NAME', `DEF_CTC_SWITCH') +C_CONTROLMIXER(DEF_CTC_SWITCH, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + +# +# Components and Buffers +# + +# For codec developers, please define the schedule core of codec adapter if it you would like it to +# be different from SCHEDULE_CORE. +ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') + +# Host "Playback with codec adapter" PCM +# with DAI_PERIODS sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + +W_GOOGLE_CTC_AUDIO_PROCESSING(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "DEF_CTC_BYTES"), + LIST(` ', "DEF_CTC_SWITCH")) + +# Playback Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(1, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(DAI_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_DAI_MEM_CAP, SCHEDULE_CORE) + +# +# Pipeline Graph +# +# host PCM_P --> B0 --> Waves codec --> B1 --> CTC --> B2 --> sink DAI0 + +P_GRAPH(pipe-codec-adapter-ctc-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))', + `dapm(N_GOOGLE_CTC_AUDIO_PROCESSING(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_GOOGLE_CTC_AUDIO_PROCESSING(0))', +)) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(2)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_ID) + +# +# PCM Configuration +# + +PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_CTC_PRIV') +undefine(`DEF_CTC_BYTES') +undefine(`DEF_CTC_SWITCH') + +undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') +undefine(`CA_SETUP_PARAMS') + +undefine(`CA_SCHEDULE_CORE') +undefine(`CA_SETUP_CONTROLBYTES_NAME') +undefine(`CA_SETUP_CONTROLBYTES_MAX') +undefine(`CA_SETUP_CONTROLBYTES') diff --git a/tools/topology/topology1/sof/pipe-waves-codec-demux-playback.m4 b/tools/topology/topology1/sof/pipe-waves-codec-demux-playback.m4 new file mode 100644 index 000000000000..ada3a749d6ce --- /dev/null +++ b/tools/topology/topology1/sof/pipe-waves-codec-demux-playback.m4 @@ -0,0 +1,152 @@ +# Demux Volume Pipeline with Waves codec +# +# Low Latency Playback with demux and volume. +# +# Pipeline Endpoints for connection are :- +# +# Playback Demux +# B3 (DAI buffer) +# +# +# host PCM_P -- B0 --> Waves -> B1 --> volume -- B2 --> Demux(M) -- B3 --> sink DAI0 +# | +# pipeline n+1 --> DAI +# + +DECLARE_SOF_RT_UUID("Waves codec", waves_codec_uuid, 0xd944281a, 0xafe9, + 0x4695, 0xa0, 0x43, 0xd7, 0xf6, 0x2b, 0x89, 0x53, 0x8e); +define(`CA_UUID', waves_codec_uuid) + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`pga.m4') +include(`muxdemux.m4') +include(`mixercontrol.m4') +include(`bytecontrol.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`codec_adapter.m4') + +ifdef(`ENDPOINT_NAME',`',`fatal_error(`Pipe requires ENDPOINT_NAME to be defined: Speakers, Headphones, etc.')') + +define(`SETUP_PARAMS_NAME', `Waves' `ENDPOINT_NAME' `Setup' PIPELINE_ID) + +CONTROLBYTES_PRIV(PP_SETUP_CONFIG, +` bytes "0x53,0x4f,0x46,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,' +` 0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00"' +) + +# Post process Bytes control for setup config +C_CONTROLBYTES(SETUP_PARAMS_NAME, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(, 8192), + , + PP_SETUP_CONFIG) + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + +# Volume Mixer control with max value of 32 +C_CONTROLMIXER(Master Playback Volume, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 256 binds the mixer control to volume get/put handlers, 256, 256), + CONTROLMIXER_MAX(, 32), + false, + CONTROLMIXER_TLV(TLV 32 steps from -64dB to 0dB for 2dB, vtlv_m64s2), + Channel register and shift for Front Left/Right, + VOLUME_CHANNEL_MAP) + +# +# Volume configuration +# + +define(DEF_PGA_TOKENS, concat(`pga_tokens_', PIPELINE_ID)) +define(DEF_PGA_CONF, concat(`pga_conf_', PIPELINE_ID)) + +W_VENDORTUPLES(DEF_PGA_TOKENS, sof_volume_tokens, +LIST(` ', `SOF_TKN_VOLUME_RAMP_STEP_TYPE "2"' + ` ', `SOF_TKN_VOLUME_RAMP_STEP_MS "20"')) + +W_DATA(DEF_PGA_CONF, DEF_PGA_TOKENS) + +# +# Components and Buffers +# + +# Host "Low latency Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Low Latency Playback, 2, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, SCHEDULE_CORE, + LIST(` ', "SETUP_PARAMS_NAME")) + +# "Master Playback Volume" has 2 source and x sink periods for DAI ping-pong +W_PGA(1, PIPELINE_FORMAT, DAI_PERIODS, 2, DEF_PGA_CONF, SCHEDULE_CORE, + LIST(` ', "PIPELINE_ID Master Playback Volume")) + +# Mux 0 has 2 sink and source periods. +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --B0--> Waves --B1--> Demux --B2--> volume ---B3--> sink DAI0 + +P_GRAPH(pipe-waves-codec-demux-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))', + `dapm(N_PGA(1), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_PGA(1))', + `dapm(N_MUXDEMUX(0), N_BUFFER(2))', + `dapm(N_BUFFER(3), N_MUXDEMUX(0))')) +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_DEMUX_', PIPELINE_ID), N_MUXDEMUX(0)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Low Latency Playback PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Low Latency Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_PGA_TOKENS') +undefine(`DEF_PGA_CONF') diff --git a/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 b/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 new file mode 100644 index 000000000000..2c19ec0f19a2 --- /dev/null +++ b/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 @@ -0,0 +1,34 @@ +# Low Latency Passthrough with Waves codec Pipeline and PCM +# +# Pipeline Endpoints for connection are :- +# +# host PCM_P --> B0 --> Waves codec --> B1 --> sink DAI0 + +ifdef(`ENDPOINT_NAME',`',`fatal_error(`Pipe requires ENDPOINT_NAME to be defined: Speakers, Headphones, etc.')') + +# Waves codec setup config +define(`CA_SETUP_CONTROLBYTES', +`` bytes "0x53,0x4f,0x46,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x0C,0x00,0x00,0x00,' +` 0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' + +` 0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00"'' +) +define(`CA_SETUP_CONTROLBYTES_MAX', 8192) +define(`CA_SETUP_CONTROLBYTES_NAME', `Waves' `ENDPOINT_NAME' `Setup ') + +define(`CA_SCHEDULE_CORE', 0) + +DECLARE_SOF_RT_UUID("Waves codec", waves_codec_uuid, 0xd944281a, 0xafe9, + 0x4695, 0xa0, 0x43, 0xd7, 0xf6, 0x2b, 0x89, 0x53, 0x8e); +define(`CA_UUID', waves_codec_uuid) + +# Include codec adapter playback topology +include(`sof/pipe-codec-adapter-playback.m4') diff --git a/tools/topology/topology1/sof/pipe-waves-demux-eq-iir-playback.m4 b/tools/topology/topology1/sof/pipe-waves-demux-eq-iir-playback.m4 new file mode 100644 index 000000000000..6615912ff82e --- /dev/null +++ b/tools/topology/topology1/sof/pipe-waves-demux-eq-iir-playback.m4 @@ -0,0 +1,133 @@ +# Demux EQ band split pipeline with Waves codec +# +# host PCM_P --B0--> Waves --B1--> demux(M) --B2--> eq_iir --B3--> sink DAI0 +# + +DECLARE_SOF_RT_UUID("Waves codec", waves_codec_uuid, 0xd944281a, 0xafe9, + 0x4695, 0xa0, 0x43, 0xd7, 0xf6, 0x2b, 0x89, 0x53, 0x8e); +define(`CA_UUID', waves_codec_uuid) + +# Include topology builder +include(`utils.m4') +include(`buffer.m4') +include(`pcm.m4') +include(`muxdemux.m4') +include(`bytecontrol.m4') +include(`eq_iir.m4') +include(`codec_adapter.m4') + +ifdef(`ENDPOINT_NAME',`',`fatal_error(`Pipe requires ENDPOINT_NAME to be defined: Speakers, Headphones, etc.')') + +define(`SETUP_PARAMS_NAME', `Waves' `ENDPOINT_NAME' `Setup' PIPELINE_ID) + +CONTROLBYTES_PRIV(PP_SETUP_CONFIG, +` bytes "0x53,0x4f,0x46,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,' +` 0x00,0x10,0x00,0x03,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00,' +` 0x0c,0x00,0x00,0x00,' +` 0x00,0x00,0x00,0x00"' +) + +# Post process Bytes control for setup config +C_CONTROLBYTES(SETUP_PARAMS_NAME, PIPELINE_ID, + CONTROLBYTES_OPS(bytes), + CONTROLBYTES_EXTOPS(void, 258, 258), + , , , + CONTROLBYTES_MAX(, 8192), + , + PP_SETUP_CONFIG) + +# demux Bytes control with max value of 255 +C_CONTROLBYTES(concat(`DEMUX', PIPELINE_ID), PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the mixer control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the mixer control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 304), + , concat(`demux_priv_', PIPELINE_ID)) + +# EQ IIR Bytes control +define(DEF_EQIIR_COEF, concat(`eqiir_coef_', PIPELINE_ID)) +define(DEF_EQIIR_PRIV, concat(`eqiir_priv_', PIPELINE_ID)) + +# define filter. eq_iir_coef_bandsplit.m4 is set by default +ifdef(`PIPELINE_FILTER1', , `define(PIPELINE_FILTER1, eq_iir_coef_bandsplit.m4)') +include(PIPELINE_FILTER1) + +C_CONTROLBYTES(DEF_EQIIR_COEF, PIPELINE_ID, + CONTROLBYTES_OPS(bytes, 258 binds the control to bytes get/put handlers, 258, 258), + CONTROLBYTES_EXTOPS(258 binds the control to bytes get/put handlers, 258, 258), + , , , + CONTROLBYTES_MAX(, 1024), + , + DEF_EQIIR_PRIV) + +# +# Components and Buffers +# + +# Host "Speaker Playback" PCM +# with 2 sink and 0 source periods +W_PCM_PLAYBACK(PCM_ID, Speaker Playback, 2, 0, SCHEDULE_CORE) + +W_CODEC_ADAPTER(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "SETUP_PARAMS_NAME")) + +# "EQ IIR" has x sink period and 2 source periods +W_EQ_IIR(0, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', "DEF_EQIIR_COEF")) + +# Mux 0 has 2 sink and source periods. +W_MUXDEMUX(0, 1, PIPELINE_FORMAT, 2, 2, SCHEDULE_CORE, + LIST(` ', concat(`DEMUX', PIPELINE_ID))) + +# Low Latency Buffers +W_BUFFER(0, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_HOST_MEM_CAP) +W_BUFFER(1, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(2, COMP_BUFFER_SIZE(2, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), PIPELINE_CHANNELS, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) +W_BUFFER(3, COMP_BUFFER_SIZE(DAI_PERIODS, + COMP_SAMPLE_SIZE(PIPELINE_FORMAT), 4, COMP_PERIOD_FRAMES(PCM_MAX_RATE, SCHEDULE_PERIOD)), + PLATFORM_COMP_MEM_CAP) + +# +# Pipeline Graph +# +# host PCM_P --B0--> Waves --B1--> demux(M) --B2--> eq_iir --B3--> sink DAI0 + +P_GRAPH(pipe-demux-eq-playback, PIPELINE_ID, + LIST(` ', + `dapm(N_BUFFER(0), N_PCMP(PCM_ID))', + `dapm(N_CODEC_ADAPTER(0), N_BUFFER(0))', + `dapm(N_BUFFER(1), N_CODEC_ADAPTER(0))', + `dapm(N_MUXDEMUX(0), N_BUFFER(1))', + `dapm(N_BUFFER(2), N_MUXDEMUX(0))', + `dapm(N_EQ_IIR(0), N_BUFFER(2))', + `dapm(N_BUFFER(3), N_EQ_IIR(0))')) + +# +# Pipeline Source and Sinks +# +indir(`define', concat(`PIPELINE_SOURCE_', PIPELINE_ID), N_BUFFER(3)) +indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Speaker Playback PCM_ID) + +# +# PCM Configuration +# + + +# PCM capabilities supported by FW +PCM_CAPABILITIES(Speaker Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), 48000, 48000, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) + +undefine(`DEF_EQIIR_COEF') +undefine(`DEF_EQIIR_PRIV') diff --git a/tools/topology/topology1/sof/tokens.m4 b/tools/topology/topology1/sof/tokens.m4 new file mode 100644 index 000000000000..b9748bb52fbc --- /dev/null +++ b/tools/topology/topology1/sof/tokens.m4 @@ -0,0 +1,159 @@ + +# +# SOF Tokens for differentiation. +# +# Differentiation can be done at the platform and machine level. +# +# Tokens are GUIDs + +# TODO: pre-process this with UAPI headers GNU cpp. + + +SectionVendorTokens."sof_buffer_tokens" { + SOF_TKN_BUF_SIZE "100" + SOF_TKN_BUF_CAPS "101" +} + +SectionVendorTokens."sof_dai_tokens" { +# Token retired with ABI 3.2, do not use for new capabilities +# SOF_TKN_DAI_DMAC_CONFIG "153" + SOF_TKN_DAI_TYPE "154" + SOF_TKN_DAI_INDEX "155" + SOF_TKN_DAI_DIRECTION "156" +} + +SectionVendorTokens."sof_sched_tokens" { + SOF_TKN_SCHED_PERIOD "200" + SOF_TKN_SCHED_PRIORITY "201" + SOF_TKN_SCHED_MIPS "202" + SOF_TKN_SCHED_CORE "203" + SOF_TKN_SCHED_FRAMES "204" + SOF_TKN_SCHED_TIME_DOMAIN "205" + SOF_TKN_SCHED_DYNAMIC_PIPELINE "206" +} + +SectionVendorTokens."sof_volume_tokens" { + SOF_TKN_VOLUME_RAMP_STEP_TYPE "250" + SOF_TKN_VOLUME_RAMP_STEP_MS "251" +} + +SectionVendorTokens."sof_src_tokens" { + SOF_TKN_SRC_RATE_IN "300" + SOF_TKN_SRC_RATE_OUT "301" +} + +SectionVendorTokens."sof_asrc_tokens" { + SOF_TKN_ASRC_RATE_IN "320" + SOF_TKN_ASRC_RATE_OUT "321" + SOF_TKN_ASRC_ASYNCHRONOUS_MODE "322" + SOF_TKN_ASRC_OPERATION_MODE "323" +} + +SectionVendorTokens."sof_pcm_tokens" { + SOF_TKN_PCM_DMAC_CONFIG "353" +} + +SectionVendorTokens."sof_comp_tokens" { + SOF_TKN_COMP_PERIOD_SINK_COUNT "400" + SOF_TKN_COMP_PERIOD_SOURCE_COUNT "401" + SOF_TKN_COMP_FORMAT "402" +# Token retired with ABI 3.2, do not use for new capabilities +# SOF_TKN_COMP_PRELOAD_COUNT "403" + SOF_TKN_COMP_CORE_ID "404" + SOF_TKN_COMP_UUID "405" +} + +SectionVendorTokens."sof_ssp_tokens" { + SOF_TKN_INTEL_SSP_CLKS_CONTROL "500" + SOF_TKN_INTEL_SSP_MCLK_ID "501" + SOF_TKN_INTEL_SSP_SAMPLE_BITS "502" + SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH "503" + SOF_TKN_INTEL_SSP_QUIRKS "504" + SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT "505" + SOF_TKN_INTEL_SSP_BCLK_DELAY "506" +} + +SectionVendorTokens."sof_dmic_tokens" { + SOF_TKN_INTEL_DMIC_DRIVER_VERSION "600" + SOF_TKN_INTEL_DMIC_CLK_MIN "601" + SOF_TKN_INTEL_DMIC_CLK_MAX "602" + SOF_TKN_INTEL_DMIC_DUTY_MIN "603" + SOF_TKN_INTEL_DMIC_DUTY_MAX "604" + SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE "605" + SOF_TKN_INTEL_DMIC_SAMPLE_RATE "608" + SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH "609" + SOF_TKN_INTEL_DMIC_UNMUTE_RAMP_TIME_MS "610" +} + +SectionVendorTokens."sof_dmic_pdm_tokens" { + SOF_TKN_INTEL_DMIC_PDM_CTRL_ID "700" + SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable "701" + SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable "702" + SOF_TKN_INTEL_DMIC_PDM_POLARITY_A "703" + SOF_TKN_INTEL_DMIC_PDM_POLARITY_B "704" + SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE "705" + SOF_TKN_INTEL_DMIC_PDM_SKEW "706" +} + +SectionVendorTokens."sof_tone_tokens" { + SOF_TKN_TONE_SAMPLE_RATE "800" +} + +SectionVendorTokens."sof_process_tokens" { + SOF_TKN_PROCESS_TYPE "900" +} + +SectionVendorTokens."sof_sai_tokens" { + SOF_TKN_IMX_SAI_MCLK_ID "1000" +} + +SectionVendorTokens."sof_esai_tokens" { + SOF_TKN_IMX_ESAI_MCLK_ID "1100" +} + +SectionVendorTokens."sof_stream_tokens" { + SOF_TKN_STREAM_PLAYBACK_COMPATIBLE_D0I3 "1200" + SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 "1201" +} + +SectionVendorTokens."sof_led_tokens" { + SOF_TKN_MUTE_LED_USE "1300" + SOF_TKN_MUTE_LED_DIRECTION "1301" +} + +SectionVendorTokens."sof_alh_tokens" { + SOF_TKN_INTEL_ALH_RATE "1400" + SOF_TKN_INTEL_ALH_CH "1401" +} + +SectionVendorTokens."sof_hda_tokens" { + SOF_TKN_INTEL_HDA_RATE "1500" + SOF_TKN_INTEL_HDA_CH "1501" +} + +SectionVendorTokens."sof_afe_tokens" { + SOF_TKN_MEDIATEK_AFE_RATE "1600" + SOF_TKN_MEDIATEK_AFE_CH "1601" + SOF_TKN_MEDIATEK_AFE_FORMAT "1602" +} + +SectionVendorTokens."sof_acp_tokens" { + SOF_TKN_AMD_ACP_RATE "1700" + SOF_TKN_AMD_ACP_CH "1701" + SOF_TKN_AMD_ACP_I2S_TDM_MODE "1702" +} + +SectionVendorTokens."sof_acpdmic_tokens" { + SOF_TKN_AMD_ACPDMIC_RATE "1800" + SOF_TKN_AMD_ACPDMIC_CH "1801" +} + +SectionVendorTokens."sof_micfil_tokens" { + SOF_TKN_IMX_MICFIL_RATE "2000" + SOF_TKN_IMX_MICFIL_CH "2001" +} + +SectionVendorTokens."sof_acp_sdw_tokens" { + SOF_TKN_AMD_ACP_SDW_SAMPLERATE "2100" + SOF_TKN_AMD_ACP_SDW_CH "2101" +} diff --git a/tools/topology/topology2/CMakeLists.txt b/tools/topology/topology2/CMakeLists.txt new file mode 100644 index 000000000000..2a1ee5483e7e --- /dev/null +++ b/tools/topology/topology2/CMakeLists.txt @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# 3.17 required: foreach(<loop_var>... IN ZIP_LISTS <lists>) +cmake_minimum_required(VERSION 3.17) + +add_custom_target(topologies2 ALL + # Create directory structure to be provided for deployment + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/target/sof-ipc4-tplg + COMMAND ${CMAKE_COMMAND} -E create_symlink sof-ipc4-tplg ${CMAKE_CURRENT_BINARY_DIR}/target/sof-ace-tplg + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/target/development + # copy the topology files only to target + COMMAND ${CMAKE_COMMAND} -E copy_if_different production/*.tplg ${CMAKE_CURRENT_BINARY_DIR}/target/sof-ipc4-tplg/ + COMMAND ${CMAKE_COMMAND} -E copy_if_different development/*.tplg ${CMAKE_CURRENT_BINARY_DIR}/target/development/ +) + +# Check alsatplg version and build topology2 if alsatplg version is +# 1.2.7 or greater, see https://github.com/thesofproject/sof/issues/5323 +alsatplg_version(STATUS ALSATPLG_VERSION_NUMBER) + +if(NOT STATUS EQUAL 0) + message(WARNING "alsatplg error: ${STATUS}; topology2 will be skipped") +else() + if(${ALSATPLG_VERSION_NUMBER} VERSION_LESS "1.2.7") + message(WARNING "topology2 skipped. Minimum alsatplg version 1.2.7,\ + found ${ALSATPLG_VERSION_NUMBER}.") + else() + add_dependencies(topologies topologies2) + endif() +endif() + +# generate ABI for IPC4 +add_custom_command(OUTPUT abi.conf + COMMAND > abi.conf ${CMAKE_CURRENT_SOURCE_DIR}/get_abi.sh ${SOF_ROOT_SOURCE_DIRECTORY} "ipc4" + DEPENDS ${SOF_ROOT_SOURCE_DIRECTORY}/src/include/kernel/abi.h +) +add_custom_target(abi_target + DEPENDS abi.conf +) + +add_dependencies(topologies2 topology2_dev topology2_prod) +add_subdirectory(development) +add_subdirectory(production) diff --git a/tools/topology/topology2/README.md b/tools/topology/topology2/README.md new file mode 100644 index 000000000000..bea7ffcfdcde --- /dev/null +++ b/tools/topology/topology2/README.md @@ -0,0 +1,401 @@ +# ALSA Topology v2 (`tools/topology/topology2`) + +This directory contains the ALSA Topology v2 source files for Sound Open Firmware. + +This readme is a quick intro to the topic. Please refer to full documentation +at https://thesofproject.github.io/latest/developer_guides/topology2/topology2.html + +## Overview + +Topology v2 is a modernization of the ALSA topology infrastructure. It aims to solve the verbosity and complexity issues of Topology v1 without relying as heavily on external macro processors like `m4`. + +Topology v2 introduces an object-oriented pre-processing layer directly into the newer `alsatplg` compiler (invoked via the `-p` flag). This allows the configuration files to define classes, objects, and attributes natively within the ALSA configuration syntax. + +Building topologies requires `alsatplg` version 1.2.7 or later. The version check is +enforced in `CMakeLists.txt` at configure time. + +## Key Advantages + +- **Object-Oriented Syntax**: Topology v2 allows for the definition of classes (`Class.Widget`, `Class.Pipeline`) and object instantiation, making the topology files much easier to read, maintain, and extend. +- **Reduced Pre-Processing**: By handling templating and instantiation inside the `alsatplg` tool itself, the build process is cleaner and errors are easier to trace back to the source files, as opposed to deciphering expanded `m4` output. +- **Dynamic Variables**: Attributes can be parameterized and passed down to nested objects, allowing for highly flexible definitions of audio pipelines. + +Topology2 uses a class-based object model built on four core concepts: + +* **Classes** (`Class.Pipeline`, `Class.Widget`, `Class.PCM`) define reusable templates + with default attribute values +* **Objects** (`Object.Pipeline`, `Object.Widget`, `Object.PCM`) instantiate classes with + specific parameter values +* **Define blocks** provide variable substitution using `$VARIABLE` syntax, enabling + parameterized topologies +* **IncludeByKey** enables conditional includes based on variable values, used primarily + for platform-specific overrides + +## Structure and Component Assembly + +Topology v2 shifts the source code layout from macro definitions to class definitions, leveraging the structured nature of the newer compiler. + +The directory is built around these core parts: + +- **`include/`**: Contains the base ALSA topology class definitions. + - `components/`: Base classes for individual processing nodes (e.g., PGA, Mixer, SRC). + - `pipelines/`: Reusable pipeline class definitions that instantiate and connect several base components. + - `dais/`: Definitions for Digital Audio Interfaces (hardware endpoints). + - `controls/`: Definitions for volume, enum, and byte controls. +- **`platform/`**: Hardware-specific configurations and overrides (e.g., Intel-specific IPC attributes). +- **Top-Level `.conf` files**: The board-specific configurations (e.g., `cavs-rt5682.conf`). These behave like standard ALSA `.conf` files but utilize the `@include` directive to import classes and instantiate them dynamically. + +### Detailed Directory Layout + +```text +tools/topology/topology2/ +├── CMakeLists.txt # Build system entry point +├── get_abi.sh # ABI version extraction script +├── cavs-sdw.conf # SoundWire topology entry point +├── sof-hda-generic.conf # HDA generic topology entry point +├── cavs-mixin-mixout-hda.conf # HDA with mixer pipelines +├── cavs-nocodec.conf # SSP nocodec topology +├── ... # Other top-level .conf entry points +├── include/ +│ ├── common/ # Core class definitions (PCM, route, audio formats) +│ ├── components/ # Widget/component classes (gain, mixin, EQ, DRC) +│ ├── controls/ # Control classes (mixer, enum, bytes) +│ ├── dais/ # DAI classes (SSP, DMIC, HDA, ALH) +│ └── pipelines/ # Pipeline template classes +│ └── cavs/ # CAVS-architecture pipeline classes +├── platform/ +│ └── intel/ # Platform-specific overrides (tgl, mtl, lnl, ptl) +├── production/ # CMake targets for production topologies +│ ├── tplg-targets-ace1.cmake # Intel ACE1 (MTL) targets +│ ├── tplg-targets-ace2.cmake # Intel ACE2 (LNL) targets +│ ├── tplg-targets-ace3.cmake # Intel ACE3 (PTL) targets +│ └── ... # Additional platform target files +├── development/ # CMake targets for development/testing +└── doc/ # Doxygen documentation source +``` + +```mermaid +graph TD + subgraph "Class Definitions (include/)" + C_Comp[Class: components/pga.conf] + C_Pipe[Class: pipelines/volume-playback.conf] + C_DAI[Class: dais/ssp.conf] + end + + subgraph "Pipeline Object" + C_Pipe -.->|Instantiates| C_Comp + end + + subgraph "Top-Level Topology (board.conf)" + Board[cavs-board.conf] + Board -->|"@include"| C_Pipe + Board -->|"@include"| C_DAI + + Obj_Pipe[Object.Pipeline.volume-playback.1] + Obj_DAI[Object.Dai.SSP.1] + + Board -.->|Instantiates| Obj_Pipe + Board -.->|Instantiates| Obj_DAI + + Routes[Object.Base.route] + Board -.->|Connects Objects| Routes + end +``` + +## Architecture and Build Flow + +Unlike v1, Topology v2 processes objects and classes within the `alsatplg` compiler itself. + +### Diagram + +```mermaid +flowchart TD + conf_classes(["Class Definitions (.conf)"]) -.-> conf_objs(["Object Instantiations (.conf)"]) + + conf_objs -->|"alsatplg -p (Pre-processor Engine)"| tplg["ALSA .tplg Binary"] + + subgraph alsatplg_internal [alsatplg Internal Processing] + direction TB + parse["Parse Classes & Objects"] --> resolve["Resolve Attributes"] + resolve --> validate["Validate Topologies"] + end + + conf_objs -.-> alsatplg_internal + alsatplg_internal -.-> tplg +``` + +When building a v2 topology, the `CMakeLists.txt` in `tools/topology/` provides the `add_alsatplg2_command` macro. This macro specifically passes the `-p` flag to `alsatplg`, instructing it to use the new pre-processor engine to resolve the classes and objects defined in the `.conf` files before compiling them into the `.tplg` binary. + +### Build Instructions + +Topologies are built automatically as part of the standard SOF CMake build process. To explicitly build Topology v2 configurations: + +```bash +# From your build directory: +make topologies2 +# OR +cmake --build . --target topologies2 +``` + +To build a specific topology target: + +```bash +make sof-lnl-sdw-cs42l43-l0-cs35l56-l12 +``` + +## Best Practices for Adding New Topology Definitions + +### Topology Structure + +A top-level topology `.conf` file follows a layered configuration pattern: + +```conf +# 1. Search directories +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines/cavs> +<searchdir:platform/intel> + +# 2. Include class files +<vendor-token.conf> +<tokens.conf> +<pcm.conf> +<host-copier-gain-mixin-playback.conf> +<mixout-gain-alh-dai-copier-playback.conf> + +# 3. Define block (default variable values) +Define { + PLATFORM "" + NUM_HDMIS 3 + DEEP_BUFFER_PCM_ID 31 +} + +# 4. Platform overrides (conditional includes) +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +# 5. Conditional feature includes +IncludeByKey.NUM_HDMIS { + "3" "platform/intel/hdmi-generic.conf" +} + +# 6. DAI, Pipeline, PCM objects +# 7. Route definitions +``` + +### Reusing Existing Bases + +The most common way to add a new topology is to reuse an existing base `.conf` file and +override variables through a cmake target entry. Targets are defined in +`production/tplg-targets-*.cmake` files using a tuple format: + +```text +"input-conf;output-name;variables" +``` + +For example, to add a new SoundWire topology variant for ACE2 (Lunar Lake): + +```text +"cavs-sdw\;sof-lnl-sdw-cs42l43-l0-cs35l56-l12\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=2" +``` + +The first element is the base `.conf` file (without extension), the second is the output +`.tplg` filename, and the third is a comma-separated list of variable overrides. + +### Creating a New Base Topology + +When existing bases do not cover a new use case, create a new top-level `.conf` file: + +1. Create a new `.conf` file in `tools/topology/topology2/` following the layered + structure described above +2. Include the required class files from `include/` directories via search directives +3. Define default variables in a `Define` block +4. Add `IncludeByKey.PLATFORM` entries for platform-specific overrides +5. Instantiate DAI, Pipeline, and PCM objects with appropriate IDs +6. Define routes connecting FE mixin outputs to BE mixout inputs +7. Register the topology as a cmake target in the appropriate + `production/tplg-targets-*.cmake` file + +### PCM ID Conventions + +PCM IDs identify audio streams exposed to userspace via ALSA. Each PCM ID must be unique +within a single topology. Different topology families (Intel SoundWire vs HDA) use different +default ID ranges for the same endpoint types. + +**Intel SoundWire PCM IDs:** + +| Endpoint | Default PCM ID | Override Variable | +|---|---|---| +| Jack (playback/capture) | 0 | — | +| Speaker amplifier | 2 | — | +| SDW DMIC | 4 | — | +| HDMI 1 | 5 | `HDMI1_PCM_ID` | +| HDMI 2 | 6 | `HDMI2_PCM_ID` | +| HDMI 3 | 7 | `HDMI3_PCM_ID` | +| PCH DMIC0 | 10 | `DMIC0_PCM_ID` | +| PCH DMIC1 | 11 | `DMIC1_PCM_ID` | +| Jack Echo Ref | 11 | `SDW_JACK_ECHO_REF_PCM_ID` | +| Speaker Echo Ref | 12 | `SDW_SPK_ECHO_REF_PCM_ID` | +| Bluetooth | 2 or 20 | `BT_PCM_ID` | +| Deep Buffer (Jack) | 31 | `DEEP_BUFFER_PCM_ID` | +| Deep Buffer (Speaker) | 35 | `DEEP_BUFFER_PCM_ID_2` | +| DMIC Deep Buffer | 46 | `DMIC0_DEEP_BUFFER_PCM_ID` | +| Compress Jack Out | 50 | `COMPR_PCM_ID` | +| Compress Speaker | 52 | `COMPR_2_PCM_ID` | + +> **Note:** Bluetooth defaults to PCM ID 2 in some topologies and 20 in others. Use the +> `BT_PCM_ID` override variable to set the correct value when BT coexists with a speaker +> amplifier (which also uses PCM ID 2 by default). + +**Intel HDA PCM IDs:** + +| Endpoint | Default PCM ID | Override Variable | +|---|---|---| +| HDA Analog | 0 | — | +| HDMI 1 | 3 | `HDMI1_PCM_ID` | +| HDMI 2 | 4 | `HDMI2_PCM_ID` | +| HDMI 3 | 5 | `HDMI3_PCM_ID` | +| DMIC0 | 6 | `DMIC0_PCM_ID` | +| Deep Buffer | 31 | `DEEP_BUFFER_PCM_ID` | +| Compress HDA Analog | 50 | `COMPR_PCM_ID` | + +Key rules: + +* PCM ID 0 is always the primary playback endpoint +* PCM IDs must be unique within a single topology +* When features coexist (SDW + PCH DMIC + HDMI), adjust IDs via `Define` overrides in + cmake targets to avoid conflicts +* Different topology families (SDW vs HDA) use different default ID ranges for the same + endpoint types + +### Pipeline ID Conventions + +Pipeline IDs are set via the `index` attribute on pipeline objects. Front-end (FE) and +back-end (BE) pipelines are paired, with the FE pipeline at index N and the BE pipeline +at index N+1. + +In SoundWire topologies, pipeline indexes follow the convention documented in +`sdw-amp-generic.conf` and `sdw-dmic-generic.conf`: pipeline index = PCM ID × 10. HDMI +pipelines use a stride-10 pattern where the host pipeline is at N0 and the DAI pipeline +is at N1 (50/51, 60/61, 70/71, 80/81). + +**Intel SoundWire Pipeline IDs:** + +| Pipeline | Default Index | Override Variable | +|---|---|---| +| Jack Playback FE / BE | 0 / 1 | — | +| Jack Capture FE / BE | 10 / 11 | — | +| Deep Buffer (Jack) | 15 | `DEEP_BUFFER_PIPELINE_ID` | +| Deep Buffer (Speaker) | 16 | `DEEP_BUFFER_PIPELINE_ID_2` | +| Speaker FE / BE | 20 / 21 | — | +| Speaker Echo Ref FE / BE | 22 / 23 | — | +| SDW DMIC FE / BE | 40 / 41 | `SDW_DMIC_HOST_PIPELINE_ID` | +| HDMI 1 Host / DAI | 50 / 51 | `HDMI1_HOST_PIPELINE_ID` / `HDMI1_DAI_PIPELINE_ID` | +| HDMI 2 Host / DAI | 60 / 61 | `HDMI2_HOST_PIPELINE_ID` / `HDMI2_DAI_PIPELINE_ID` | +| HDMI 3 Host / DAI | 70 / 71 | `HDMI3_HOST_PIPELINE_ID` / `HDMI3_DAI_PIPELINE_ID` | +| HDMI 4 Host / DAI | 80 / 81 | `HDMI4_HOST_PIPELINE_ID` / `HDMI4_DAI_PIPELINE_ID` | +| Compress Jack / Speaker | 90 / 92 | `COMPR_PIPELINE_ID` / `COMPR_2_PIPELINE_ID` | +| PCH DMIC0 Host / DAI | 100 / 101 | `DMIC0_HOST_PIPELINE_ID` / `DMIC0_DAI_PIPELINE_ID` | + +**Intel HDA Pipeline IDs:** + +| Pipeline | Default Index | Override Variable | +|---|---|---| +| Analog Playback FE / BE | 1 / 2 | — | +| Analog Capture FE / BE | 3 / 4 | — | +| DMIC0 Host / DAI | 11 / 12 | `DMIC0_HOST_PIPELINE_ID` / `DMIC0_DAI_PIPELINE_ID` | +| Deep Buffer | 15 | `DEEP_BUFFER_PIPELINE_ID` | +| HDMI 1 Host / DAI | 50 / 51 | `HDMI1_HOST_PIPELINE_ID` / `HDMI1_DAI_PIPELINE_ID` | +| HDMI 2 Host / DAI | 60 / 61 | `HDMI2_HOST_PIPELINE_ID` / `HDMI2_DAI_PIPELINE_ID` | +| HDMI 3 Host / DAI | 70 / 71 | `HDMI3_HOST_PIPELINE_ID` / `HDMI3_DAI_PIPELINE_ID` | +| HDMI 4 Host / DAI | 80 / 81 | `HDMI4_HOST_PIPELINE_ID` / `HDMI4_DAI_PIPELINE_ID` | +| Compress HDA Analog Host / DAI | 90 / 91 | `COMPR_PIPELINE_ID` | + +Key rules: + +* FE and BE pipelines are paired: FE = N, BE = N+1 +* SDW convention: pipeline index = PCM ID × 10 (documented in `sdw-amp-generic.conf` and + `sdw-dmic-generic.conf`) +* HDMI uses stride-10: Host = N0, DAI = N1 +* Pipeline IDs must be unique within a single topology +* When adding new endpoints, select IDs in unused ranges that do not conflict with + existing assignments + +### Widget Naming + +Widget names follow the convention `<type>.<pipeline-index>.<instance>`. Examples: + +* `gain.1.1` — gain widget in pipeline 1, instance 1 +* `mixin.15.1` — mixin widget in pipeline 15, instance 1 +* `host-copier.0.playback` — host copier in pipeline 0, playback direction +* `dai-copier.1.ALH` — DAI copier in pipeline 1, ALH type + +### Route Definitions + +Routes connect FE pipeline mixin outputs to BE pipeline mixout inputs. This is the +primary mechanism for linking front-end and back-end pipelines: + +```conf +Object.Base.route [ + { + source "mixin.15.1" + sink "mixout.2.1" + } +] +``` + +Multiple FE pipelines can feed into a single BE mixout. For example, both a normal +playback pipeline and a deep buffer pipeline can route to the same DAI output: + +```text +host-copier.0 -> gain.0 -> mixin.0 ─┐ + ├─> mixout.1 -> gain.1 -> dai-copier.1 -> DAI +host-copier.15 -> gain.15 -> mixin.15┘ +``` + +### Platform Overrides + +Platform-specific configurations are applied using the `IncludeByKey.PLATFORM` mechanism. +Each platform `.conf` file under `platform/intel/` contains `Define` blocks that override +variables such as `DMIC_DRIVER_VERSION`, `SSP_BLOB_VERSION`, and `NUM_HDMIS`. + +Supported platforms: + +* `tgl` — Intel Tiger Lake / Alder Lake (CAVS 2.5) +* `mtl` — Intel Meteor Lake (ACE 1.x) +* `lnl` — Intel Lunar Lake (ACE 2.x) +* `ptl` — Intel Panther Lake (ACE 3.x) + +```conf +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} +``` + +### Registering CMake Targets + +Production topologies are registered in `production/tplg-targets-*.cmake` files. Each +target is a semicolon-separated tuple: + +```text +"input-conf;output-name;variable1=value1,variable2=value2" +``` + +Select the cmake file matching the target platform generation: + +| Platform | CMake Target File | +|---|---| +| Tiger Lake / Alder Lake | `tplg-targets-cavs25.cmake` | +| Meteor Lake | `tplg-targets-ace1.cmake` | +| Lunar Lake | `tplg-targets-ace2.cmake` | +| Panther Lake | `tplg-targets-ace3.cmake` | +| HDA generic | `tplg-targets-hda-generic.cmake` | + +Development and testing topologies go in `development/tplg-targets.cmake`. diff --git a/tools/topology/topology2/cavs-benchmark-hda.conf b/tools/topology/topology2/cavs-benchmark-hda.conf new file mode 100644 index 000000000000..95ab67431812 --- /dev/null +++ b/tools/topology/topology2/cavs-benchmark-hda.conf @@ -0,0 +1,1012 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<dai-copier.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<mixout-dai-copier-playback.conf> +<mixout-aria-gain-mixin-playback.conf> +<host-copier-gain-mixin-playback.conf> +<highpass-capture-be.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<hda.conf> +<hw_config_simple.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<module-copier.conf> + +<aria.conf> +<asrc.conf> +<dcblock.conf> +<dolby-dax.conf> +<drc.conf> +<eqiir.conf> +<eqfir.conf> +<gain.conf> +<igo_nr.conf> +<level_multiplier.conf> +<mfcc.conf> +<micsel.conf> +<mixin.conf> +<mixout.conf> +<multiband_drc.conf> +<rtnr.conf> +<sound_dose.conf> +<src.conf> +<src_lite.conf> +<stft_process.conf> +<tdfb.conf> +<template_comp.conf> + +Define { + HDA_CONFIG "none" + PLATFORM "none" + ANALOG_PLAYBACK_PCM 'Analog Playback' + ANALOG_CAPTURE_PCM 'Analog Capture' + HDA_ANALOG_DAI_NAME 'Analog' + HDA_ANALOG_CAPTURE_RATE 48000 + HDA_ANALOG_PLAYBACK_RATE 48000 + BENCH_PLAYBACK_HOST_PIPELINE 1 + BENCH_PLAYBACK_DAI_PIPELINE 2 + BENCH_CAPTURE_HOST_PIPELINE 3 + BENCH_CAPTURE_DAI_PIPELINE 4 + BENCH_PLAYBACK_DAI_COPIER "dai-copier.HDA.Analog.playback" + BENCH_CAPTURE_DAI_COPIER "dai-copier.HDA.Analog.capture" + BENCH_PCM_CHANNELS_MIN 2 + BENCH_PCM_CHANNELS_MAX 2 +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +Object.Widget.virtual [ + { + name 'codec0_in' + type input + index 1 + } + { + name 'codec1_in' + type input + index 2 + } + { + name 'codec0_out' + type output + index 3 + } + { + name 'codec1_out' + type output + index 4 + } + { + name 'codec2_in' + type input + index 5 + } + { + name 'codec2_out' + type output + index 6 + } + { + name 'iDisp1_out' + type output + index 7 + } + { + name 'iDisp2_out' + type output + index 8 + } + { + name 'iDisp3_out' + type output + index 9 + } + { + name 'iDisp3 Tx' + type out_drv + index 0 + } + { + name 'iDisp2 Tx' + type out_drv + index 1 + } + { + name 'iDisp1 Tx' + type out_drv + index 2 + } + { + name 'Analog CPU Playback' + type out_drv + index 3 + } + { + name 'Digital CPU Playback' + type out_drv + index 4 + } + { + name 'Alt Analog CPU Playback' + type out_drv + index 5 + } + { + name 'Analog CPU Capture' + type input + index 6 + } + { + name 'Digital CPU Capture' + type input + index 7 + } + { + name 'Alt Analog CPU Capture' + type input + index 8 + } +] + +Object.Dai.HDA [ + { + name $HDA_ANALOG_DAI_NAME + dai_index 0 + id 4 + default_hw_conf_id 4 + Object.Base.hw_config.1 { + name "HDA0" + } + direction duplex + } +] + +Object.PCM.pcm [ + { + id 0 + name 'HDA Analog' + Object.Base.fe_dai.1 { + name "HDA Analog" + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $ANALOG_PLAYBACK_PCM + formats 'S32_LE,S24_LE,S16_LE' + rates "8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,176400,192000" + channels_min $BENCH_PCM_CHANNELS_MIN + channels_max $BENCH_PCM_CHANNELS_MAX + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $ANALOG_CAPTURE_PCM + formats 'S32_LE,S24_LE,S16_LE' + rates "8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,176400,192000" + channels_min $BENCH_PCM_CHANNELS_MIN + channels_max $BENCH_PCM_CHANNELS_MAX + } + direction duplex + } +] + +Object.Pipeline { + io-gateway [ + { + index $BENCH_PLAYBACK_DAI_PIPELINE + direction playback + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + num_input_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.BENCH_MODULE_FORMAT { + "s16" { + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + } + "s24" { + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + } + "s32" { + 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 [ + { + index $BENCH_CAPTURE_DAI_PIPELINE + direction capture + Object.Widget.dai-copier.1 { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + IncludeByKey.BENCH_MODULE_FORMAT { + "s16" { + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + "s24" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + "s32" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + } + ] +} + +IncludeByKey.BENCH_CONFIG { + "benchmark" { + Object.Pipeline { + mixout-dai-copier-playback [ + { + index 3 + + Object.Widget.mixout.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + mixout-aria-gain-mixin-playback [ + { + index 2 + + Object.Widget.mixin.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + Object.Widget.gain.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + Object.Control.mixer.1 { + name 'Post Mixer $ANALOG_PLAYBACK_PCM Volume' + } + } + Object.Widget.aria.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + Object.Control.bytes."1" { + name '$ANALOG_PLAYBACK_PCM ARIA bytes' + IncludeByKey.BENCH_ARIA_PARAMS { + "passthrough" "include/components/aria/passthrough.conf" + "param_1" "include/components/aria/param_1.conf" + "param_2" "include/components/aria/param_2.conf" + "param_3" "include/components/aria/param_3.conf" + } + } + } + Object.Widget.mixout.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + } + ] + + host-copier-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + + Object.Widget.gain.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + Object.Control.mixer.1 { + name 'Pre Mixer $ANALOG_PLAYBACK_PCM Volume' + } + } + Object.Widget.mixin.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + } + ] + + host-gateway-capture [ + { + index 4 + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + highpass-capture-be [ + { + index 5 + direction capture + + Object.Widget.dai-copier.1 { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.eqiir.1 { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM IIR Eq' + } + } + } + ] + } + + # top-level pipeline connections + Object.Base.route [ + { + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + source 'mixout.3.1' + } + { + source 'mixin.2.1' + sink 'mixout.3.1' + } + { + source 'mixin.1.1' + sink 'mixout.2.1' + } + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'eqiir.5.1' + } + { + source 'eqiir.5.1' + sink 'host-copier.0.capture' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } + ] + } + + # + # Aria component + # + + "aria24" { + <include/bench/aria_s24.conf> + } + + # + # ASRC component + # + + # '^' indicates the start of the string and '$' means the end of string + # manually adding '^' and '$' for whole string precise matching + + "^asrc16$" { + <include/bench/asrc_s16.conf> + } + + "^asrc24$" { + <include/bench/asrc_s24.conf> + } + + "^asrc32$" { + <include/bench/asrc_s32.conf> + } + + # + # DCblock component + # + + "dcblock16" { + <include/bench/dcblock_s16.conf> + } + + "dcblock24" { + <include/bench/dcblock_s24.conf> + } + + "dcblock32" { + <include/bench/dcblock_s32.conf> + } + + # + # DOLBY_DAX component + # + + "dolby-dax16" { + <include/bench/dolby-dax_s16.conf> + } + + "dolby-dax24" { + <include/bench/dolby-dax_s24.conf> + } + + "dolby-dax32" { + <include/bench/dolby-dax_s32.conf> + } + + # + # DRC component + # + + "drc16" { + <include/bench/drc_s16.conf> + } + + "drc24" { + <include/bench/drc_s24.conf> + } + + "drc32" { + <include/bench/drc_s32.conf> + } + + # Multiband-DRC component + # Note: Due to alsatplg regexp match feature in IncludeByKey call it e.g. drc_multiband16 + # to not match multiband_drc16 with drc16 and get error "No variable defined + # for BENCH_DRC_PARAMS" when building these. + + "drc_multiband16" { + <include/bench/multiband_drc_s16.conf> + } + + "drc_multiband24" { + <include/bench/multiband_drc_s24.conf> + } + + "drc_multiband32" { + <include/bench/multiband_drc_s32.conf> + } + + # + # EQFIR component + # + + "eqfir16" { + <include/bench/eqfir_s16.conf> + } + + "eqfir24" { + <include/bench/eqfir_s24.conf> + } + + "eqfir32" { + <include/bench/eqfir_s32.conf> + } + + # + # EQIIR component + # + + "eqiir16" { + <include/bench/eqiir_s16.conf> + } + + "eqiir24" { + <include/bench/eqiir_s24.conf> + } + + "eqiir32" { + <include/bench/eqiir_s32.conf> + } + + # + # Gain component + # + + "gain16" { + <include/bench/gain_s16.conf> + } + + "gain24" { + <include/bench/gain_s24.conf> + } + + "gain32" { + <include/bench/gain_s32.conf> + } + + # + # IGO NR component + # + + "igo_nr16" { + <include/bench/igo_nr_s16.conf> + } + + "igo_nr24" { + <include/bench/igo_nr_s24.conf> + } + + "igo_nr32" { + <include/bench/igo_nr_s32.conf> + } + + # + # Level Multiplier component + # + + "level_multiplier16" { + <include/bench/level_multiplier_s16.conf> + } + + "level_multiplier24" { + <include/bench/level_multiplier_s24.conf> + } + + "level_multiplier32" { + <include/bench/level_multiplier_s32.conf> + } + + # + # MFCC component + # + + "mfcc16" { + <include/bench/mfcc_s16.conf> + } + + "mfcc24" { + <include/bench/mfcc_s24.conf> + } + + "mfcc32" { + <include/bench/mfcc_s32.conf> + } + + "mfccmel16" { + <include/bench/mfccmel_s16.conf> + } + "mfccmel24" { + <include/bench/mfccmel_s24.conf> + } + "mfccmel32" { + <include/bench/mfccmel_s32.conf> + } + + # + # Micsel component + # + + "^micsel16$" { + <include/bench/micsel_s16.conf> + } + + "^micsel24$" { + <include/bench/micsel_s24.conf> + } + + "^micsel32$" { + <include/bench/micsel_s32.conf> + } + + "^micsel_multich32$" { + <include/bench/micsel_multich_s32.conf> + } + + # + # RTNR component + # + + "rtnr16" { + <include/bench/rtnr_s16.conf> + } + + "rtnr24" { + <include/bench/rtnr_s24.conf> + } + + "rtnr32" { + <include/bench/rtnr_s32.conf> + } + + # + # Sound Dose component + # + + "sound_dose16" { + <include/bench/sound_dose_s16.conf> + } + + "sound_dose24" { + <include/bench/sound_dose_s24.conf> + } + + "sound_dose32" { + <include/bench/sound_dose_s32.conf> + } + + # + # SRC component + # + + "^src16$" { + <include/bench/src_s16.conf> + } + + "^src24$" { + <include/bench/src_s24.conf> + } + + "^src32$" { + <include/bench/src_s32.conf> + } + + # + # src_lite component + # + + "src_lite16" { + <include/bench/src_lite_s16.conf> + } + + "src_lite24" { + <include/bench/src_lite_s24.conf> + } + + "src_lite32" { + <include/bench/src_lite_s32.conf> + } + + # + # stft_process component, with five different blob configurations. + # + + "stft_process_192_48_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_192_48_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_192_48_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_512_128_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_512_128_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_512_128_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_768_120_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_768_120_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_768_120_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_1024_256_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_1024_256_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_1024_256_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_1536_240_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_1536_240_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_1536_240_32" { + <include/bench/stft_process_s32.conf> + } + + # + # tdfb component + # + + "tdfb16" { + <include/bench/tdfb_s16.conf> + } + + "tdfb24" { + <include/bench/tdfb_s24.conf> + } + + "tdfb32" { + <include/bench/tdfb_s32.conf> + } + + # + # template_comp component + # + + "template_comp16" { + <include/bench/template_comp_s16.conf> + } + + "template_comp24" { + <include/bench/template_comp_s24.conf> + } + + "template_comp32" { + <include/bench/template_comp_s32.conf> + } +} diff --git a/tools/topology/topology2/cavs-benchmark-sdw.conf b/tools/topology/topology2/cavs-benchmark-sdw.conf new file mode 100644 index 000000000000..1705facb4cc0 --- /dev/null +++ b/tools/topology/topology2/cavs-benchmark-sdw.conf @@ -0,0 +1,615 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<pipeline.conf> +<alh.conf> +<dai.conf> +<host.conf> +<input_audio_format.conf> +<output_audio_format.conf> +<alh-dai-copier.conf> +<controls/bytes.conf> +<controls/mixer.conf> + +<aria.conf> +<asrc.conf> +<dcblock.conf> +<drc.conf> +<eqiir.conf> +<eqfir.conf> +<gain.conf> +<igo_nr.conf> +<level_multiplier.conf> +<mfcc.conf> +<micsel.conf> +<multiband_drc.conf> +<rtnr.conf> +<sound_dose.conf> +<src.conf> +<src_lite.conf> +<stft_process.conf> +<tdfb.conf> +<template_comp.conf> + +Define { + PLATFORM "none" + SDW_JACK_OUT_STREAM 'SDW0-Playback' + SDW_JACK_IN_STREAM 'SDW0-Capture' + SDW_JACK_OUT_BE_ID 0 + SDW_JACK_IN_BE_ID 1 + NUM_SDW_AMP_LINKS 0 + SDW_DMIC 0 + SDW_JACK true + PASSTHROUGH false + SDW_ANALOG_CAPTURE_CH 2 + SDW_LINK_VALID_BITS 24 + ANALOG_PLAYBACK_PCM "Jack Out" + ANALOG_CAPTURE_PCM "Jack In" + JACK_RATE 48000 + BENCH_PLAYBACK_HOST_PIPELINE 1 + BENCH_PLAYBACK_DAI_PIPELINE 2 + BENCH_CAPTURE_HOST_PIPELINE 3 + BENCH_CAPTURE_DAI_PIPELINE 4 + BENCH_PLAYBACK_DAI_COPIER "alh-copier.SDW0-Playback.0" + BENCH_CAPTURE_DAI_COPIER "alh-copier.SDW0-Capture.0" + BENCH_PCM_CHANNELS_MIN 2 + BENCH_PCM_CHANNELS_MAX 2 +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +IncludeByKey.SDW_JACK_OUT_STREAM { + "Playback-SimpleJack" { + Define { + BENCH_PLAYBACK_DAI_COPIER "alh-copier.Playback-SimpleJack.0" + BENCH_CAPTURE_DAI_COPIER "alh-copier.Capture-SimpleJack.0" + } + } +} + +# +# 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 $JACK_RATE + 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 $JACK_RATE + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH3" + } + } +] + +Object.PCM.pcm [ + { + name "$ANALOG_PLAYBACK_PCM" + id 0 + direction "playback" + Object.Base.fe_dai.1 { + name "$ANALOG_PLAYBACK_PCM" + } + + Object.PCM.pcm_caps.1 { + name $ANALOG_PLAYBACK_PCM + formats 'S16_LE,S24_LE,S32_LE' + rates "8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,176400,192000" + channels_min $BENCH_PCM_CHANNELS_MIN + channels_max $BENCH_PCM_CHANNELS_MAX + } + } + { + name "$ANALOG_CAPTURE_PCM" + id 1 + direction "capture" + Object.Base.fe_dai.1 { + name "$ANALOG_CAPTURE_PCM" + } + + Object.PCM.pcm_caps.1 { + name $ANALOG_CAPTURE_PCM + formats 'S16_LE,S24_LE,S32_LE' + rates "8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,176400,192000" + channels_min $BENCH_PCM_CHANNELS_MIN + channels_max $BENCH_PCM_CHANNELS_MAX + } + } +] + +Object.Widget { + alh-copier [ + { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + index $BENCH_PLAYBACK_DAI_PIPELINE + type dai_in + direction playback + num_input_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.BENCH_MODULE_FORMAT { + "s16" { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + } + "s24" { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + } + "s32" { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + } + } + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + pipeline [ + { + index $BENCH_PLAYBACK_DAI_PIPELINE + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] +} + +Object.Widget { + alh-copier [ + { + stream_name $SDW_JACK_IN_STREAM + direction "capture" + type "dai_out" + index $BENCH_CAPTURE_DAI_PIPELINE + 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_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + IncludeByKey.BENCH_MODULE_FORMAT { + "s16" { + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + "s24" { + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + "s32" { + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + ] + + pipeline [ + { + index $BENCH_CAPTURE_DAI_PIPELINE + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] +} + +IncludeByKey.BENCH_CONFIG { + # + # Aria component + # + + "aria24" { + <include/bench/aria_s24.conf> + } + + # + # ASRC component + # + + # '^' indicates the start of the string and '$' means the end of string + # manually adding '^' and '$' for whole string precise matching + + "^asrc16$" { + <include/bench/asrc_s16.conf> + } + + "^asrc24$" { + <include/bench/asrc_s24.conf> + } + + "^asrc32$" { + <include/bench/asrc_s32.conf> + } + + # + # DCblock component + # + + "dcblock16" { + <include/bench/dcblock_s16.conf> + } + + "dcblock24" { + <include/bench/dcblock_s24.conf> + } + + "dcblock32" { + <include/bench/dcblock_s32.conf> + } + + # + # DRC component + # + + "drc16" { + <include/bench/drc_s16.conf> + } + + "drc24" { + <include/bench/drc_s24.conf> + } + + "drc32" { + <include/bench/drc_s32.conf> + } + + # Multiband-DRC component + # Note: Due to alsatplg regexp match feature in IncludeByKey call it e.g. drc_multiband16 + # to not match multiband_drc16 with drc16 and get error "No variable defined + # for BENCH_DRC_PARAMS" when building these. + + "drc_multiband16" { + <include/bench/multiband_drc_s16.conf> + } + + "drc_multiband24" { + <include/bench/multiband_drc_s24.conf> + } + + "drc_multiband32" { + <include/bench/multiband_drc_s32.conf> + } + + # + # EQFIR component + # + + "eqfir16" { + <include/bench/eqfir_s16.conf> + } + + "eqfir24" { + <include/bench/eqfir_s24.conf> + } + + "eqfir32" { + <include/bench/eqfir_s32.conf> + } + + # + # EQIIR component + # + + "eqiir16" { + <include/bench/eqiir_s16.conf> + } + + "eqiir24" { + <include/bench/eqiir_s24.conf> + } + + "eqiir32" { + <include/bench/eqiir_s32.conf> + } + + # + # Gain component + # + + "gain16" { + <include/bench/gain_s16.conf> + } + + "gain24" { + <include/bench/gain_s24.conf> + } + + "gain32" { + <include/bench/gain_s32.conf> + } + + # + # IGO NR component + # + + "igo_nr16" { + <include/bench/igo_nr_s16.conf> + } + + "igo_nr24" { + <include/bench/igo_nr_s24.conf> + } + + "igo_nr32" { + <include/bench/igo_nr_s32.conf> + } + + # + # Level Multiplier component + # + + "level_multiplier16" { + <include/bench/level_multiplier_s16.conf> + } + + "level_multiplier24" { + <include/bench/level_multiplier_s24.conf> + } + + "level_multiplier32" { + <include/bench/level_multiplier_s32.conf> + } + + # MFCC benchmark configs are intentionally not enabled in the SDW + # benchmark topology because the SDW ALH DAI/coprocessor side is + # constrained to $JACK_RATE while MFCC bench configs operate in a + # different rate domain. Re-enable only after adding a matching rate + # override or explicit sample-rate conversion. + + # + # Micsel component + # + + "^micsel16$" { + <include/bench/micsel_s16.conf> + } + + "^micsel24$" { + <include/bench/micsel_s24.conf> + } + + "^micsel32$" { + <include/bench/micsel_s32.conf> + } + + "^micsel_multich32$" { + <include/bench/micsel_multich_s32.conf> + } + + # + # RTNR component + # + + "rtnr16" { + <include/bench/rtnr_s16.conf> + } + + "rtnr24" { + <include/bench/rtnr_s24.conf> + } + + "rtnr32" { + <include/bench/rtnr_s32.conf> + } + + # + # Sound Dose component + # + + "sound_dose16" { + <include/bench/sound_dose_s16.conf> + } + + "sound_dose24" { + <include/bench/sound_dose_s24.conf> + } + + "sound_dose32" { + <include/bench/sound_dose_s32.conf> + } + + # + # SRC component + # + + "^src16$" { + <include/bench/src_s16.conf> + } + + "^src24$" { + <include/bench/src_s24.conf> + } + + "^src32$" { + <include/bench/src_s32.conf> + } + + # + # src_lite component + # + + "src_lite16" { + <include/bench/src_lite_s16.conf> + } + + "src_lite24" { + <include/bench/src_lite_s24.conf> + } + + "src_lite32" { + <include/bench/src_lite_s32.conf> + } + + # + # stft_process component, with five different blob configurations. + # + + "stft_process_192_48_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_192_48_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_192_48_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_512_128_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_512_128_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_512_128_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_768_120_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_768_120_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_768_120_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_1024_256_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_1024_256_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_1024_256_32" { + <include/bench/stft_process_s32.conf> + } + "stft_process_1536_240_16" { + <include/bench/stft_process_s16.conf> + } + "stft_process_1536_240_24" { + <include/bench/stft_process_s24.conf> + } + "stft_process_1536_240_32" { + <include/bench/stft_process_s32.conf> + } + + # + # tdfb component + # + + "tdfb16" { + <include/bench/tdfb_s16.conf> + } + + "tdfb24" { + <include/bench/tdfb_s24.conf> + } + + "tdfb32" { + <include/bench/tdfb_s32.conf> + } + + # + # template_comp component + # + + "template_comp16" { + <include/bench/template_comp_s16.conf> + } + + "template_comp24" { + <include/bench/template_comp_s24.conf> + } + + "template_comp32" { + <include/bench/template_comp_s32.conf> + } +} \ No newline at end of file diff --git a/tools/topology/topology2/cavs-cs35l56.conf b/tools/topology/topology2/cavs-cs35l56.conf new file mode 100644 index 000000000000..9b5eb8e91fc4 --- /dev/null +++ b/tools/topology/topology2/cavs-cs35l56.conf @@ -0,0 +1,423 @@ +# Topology for CDB35L56-FOUR board with 4x CS35L56 using TDM +# @48000 sample rate, 16 bits per sample, 8 TDM slots per frame. +# Stereo playback, 8 channel feedback capture. +# +# This setup has only speaker playback and speaker feedback devices. +# No headset, DMICs or HDMI. +# +# Based on cavs-es83x6.conf and cavs-rt5682.conf + +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<pdm_config.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<host-copier-gain-mixin-playback.conf> +<mixout-gain-dai-copier-playback.conf> +<deepbuffer-playback.conf> +<dai-copier-be.conf> +<gain-capture.conf> +<gain-module-copier.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<hda.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<dmic-default.conf> +<input_pin_binding.conf> +<output_pin_binding.conf> +<input_audio_format.conf> +<output_audio_format.conf> +<ctc.conf> + +Define { + MCLK 24576000 + # override DMIC default definitions + NUM_DMICS 0 + # override BE link ids + NUM_HDMIS 0 + + SPK_ID 0 + PLATFORM "none" + SPEAKER_CODEC_NAME 'SSP2-Codec' + SPEAKER_PLAYBACK_PCM_STREAM_NAME 'Speaker Playback' + SPEAKER_FEEDBACK_PCM_STREAM_NAME 'Speaker Feedback' + SPEAKER_SSP_DAI_INDEX 2 + SPEAKER_HW_CONFIG_NAME 'SPEAKER HWCFG' + SPEAKER_HOST_PIPELINE_ID 3 + SPEAKER_DAI_PIPELINE_ID 4 + SPEAKER_PCM_CORE_ID 0 + SPEAKER_PCM_NAME "Speakers" + SPEAKER_FEEDBACK_PCM_NAME "Feedback" + SPEAKER_PCM_ID 2 + SPEAKER_FEEDBACK_PCM_ID 3 + PLAYBACK_PIPELINE_SRC "volume" + SSP_SPK_FMT_24 false + SSP_HS_FMT_24 false +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "tgl" "platform/intel/tgl.conf" +} + +# +# Define bidirectional DAI for SSP +# +Object.Dai.SSP [ + { + id $SPK_ID + dai_index $SPEAKER_SSP_DAI_INDEX + direction "duplex" + name $SPEAKER_CODEC_NAME + default_hw_conf_id 0 + sample_bits 16 + io_clk $MCLK + + # + # TDM configuration is 48kHz, 16 bit slots, DSP_A. + # There are 8 slots: + # TX to amp on slots 0 and 1 + # RX from amp on slots 0..7 + # + Object.Base.hw_config.1 { + name $SPEAKER_HW_CONFIG_NAME + id 0 + + bclk_freq 6144000 + fsync_freq 48000 + tdm_slot_width 16 + tdm_slots 8 + tx_slots 3 # bitmask of active slots + rx_slots 255 # bitmask of active slots + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } +] + +Object.Pipeline { + # + # Playback volume control pipeline + # + host-copier-gain-mixin-playback [ + { + index $SPEAKER_HOST_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name '$SPEAKER_PLAYBACK_PCM_STREAM_NAME' + pcm_id $SPEAKER_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] + + # + # Playback pipeline towards SSP + # + mixout-gain-dai-copier-playback [ + { + index $SPEAKER_DAI_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + + # + # Define widget to send audio to SSP + # + Object.Widget.dai-copier.1 { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + + # + # Playback audio format on SSP is fixed at 48kHz, + # 2 channels, 16 bits. + # Override default dai-copier audio format. + # + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate 48000 + out_channels 2 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] + + # + # Capture pipeline for BE DAI + # + host-gateway-capture [ + { + index 5 + + # + # Define host-copier to output audio to BE DAI + # + Object.Widget.host-copier.1 { + stream_name '$SPEAKER_FEEDBACK_PCM_STREAM_NAME' + pcm_id $SPEAKER_FEEDBACK_PCM_ID + + # + # Capture is fixed at 48kHz with 8 channels, + # but allow for different sample widths on + # BE DAI. + # Default host-copier audio format is + # stereo so need to override for 8 channels. + # + num_input_audio_formats 3 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 24 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_channels 8 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + ] + + # + # Capture pipeline from SSP + # + io-gateway-capture [ + { + index 6 + + # + # Define dai-copier to receive audio from SSP + # + Object.Widget.dai-copier."1" { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_INPUT_CLASS + + # + # Capture audio format on SSP is fixed at 48kHz, + # 8 channels, 16 bits. + # Override default dai-copier audio format. + # + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate 48000 + in_channels 8 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + # + # Capture is fixed at 48kHz with 8 channels, + # but allow for different sample widths + # towards BE DAI. + # Default dai-copier audio format is + # stereo so need to override for 8 channels. + # + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + ] +} + +# +# FE DAIs +# +Object.PCM.pcm [ + # Playback FE DAI + { + name "$SPEAKER_PCM_NAME" + id $SPEAKER_PCM_ID + direction "playback" + Object.Base.fe_dai.1 { + name "$SPEAKER_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "$SPEAKER_PLAYBACK_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + channels_min 2 + channels_max 2 + periods_max 16 + period_size_min 192 + period_size_max 16384 + buffer_size_min 65536 + buffer_size_max 65536 + } + } + + # Capture FE DAI + { + name "$SPEAKER_FEEDBACK_PCM_NAME" + id $SPEAKER_FEEDBACK_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$SPEAKER_FEEDBACK_PCM_STREAM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "$SPEAKER_FEEDBACK_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + channels_min 8 + channels_max 8 + periods_max 16 + period_size_min 192 + period_size_max 16384 + buffer_size_min 65536 + buffer_size_max 65536 + } + } +] + +# +# Pipeline routing +# +Object.Base.route [ + # + # Playback: + # FE DAI -> host-copier -> gain -> dai-copier -> SSP + # + { + source "gain.$SPEAKER_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$SPEAKER_CODEC_NAME.playback" + } + { + source "mixin.$SPEAKER_HOST_PIPELINE_ID.1" + sink "mixout.$SPEAKER_DAI_PIPELINE_ID.1" + } + { + source "host-copier.$SPEAKER_PCM_ID.playback" + sink "gain.$SPEAKER_DAI_PIPELINE_ID.1" + } + + # + # Capture: + # FE DAI <- host-copier <- dai-copier <- SSP + # + { + source "dai-copier.SSP.$SPEAKER_CODEC_NAME.capture" + sink "host-copier.$SPEAKER_FEEDBACK_PCM_ID.capture" + } +] diff --git a/tools/topology/topology2/cavs-es83x6.conf b/tools/topology/topology2/cavs-es83x6.conf new file mode 100644 index 000000000000..6a5fc31054b7 --- /dev/null +++ b/tools/topology/topology2/cavs-es83x6.conf @@ -0,0 +1,240 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<pdm_config.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<host-copier-gain-mixin-playback.conf> +<mixout-gain-dai-copier-playback.conf> +<deepbuffer-playback.conf> +<dai-copier-be.conf> +<gain-capture.conf> +<gain-module-copier.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<dmic.conf> +<hda.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<bt-default.conf> +<dmic-default.conf> +<hdmi-default.conf> +<hdmi-in-default.conf> +IncludeByKey.HDMI_IN_CAPTURE { + "true" "platform/intel/hdmi-in-capture.conf" +} +<input_pin_binding.conf> +<output_pin_binding.conf> +<input_audio_format.conf> +<output_audio_format.conf> + +Define { + MCLK 24576000 + # override BE link ids + NUM_HDMIS 3 + PLATFORM "none" + HEADSET_CODEC_NAME 'SSP1-Codec' + HEADSET_PLAYBACK_PCM_STREAM_NAME 'Headset Playback' + HEADSET_CAPTURE_PCM_STREAM_NAME 'Headset Capture' + HEADSET_SSP_DAI_INDEX 1 + HEADSET_HW_CONFIG_NAME 'HEADSET HWCFG' + HEADSET_PCM_NAME "Headset" + HEADSET_PCM_ID 0 + INCLUDE_BT_OFFLOAD false +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +# include HDMI config if needed. +IncludeByKey.NUM_HDMIS { + "[3-4]" "platform/intel/hdmi-generic.conf" +} + +IncludeByKey.INCLUDE_BT_OFFLOAD { + "true" "platform/intel/bt-generic.conf" +} + +IncludeByKey.HEADSET_CODEC { +"true" { +# +# List of all DAIs +# +#SSP Index: 0, Direction: duplex + Object.Dai.SSP [ + { + id 0 + dai_index $HEADSET_SSP_DAI_INDEX + direction "duplex" + name $HEADSET_CODEC_NAME + default_hw_conf_id 0 + sample_bits 32 + io_clk $MCLK + + Object.Base.hw_config.1 { + name $HEADSET_HW_CONFIG_NAME + 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 ----> SSP1 +# +# SSP1 ----> PCM0 + +# Pipeline ID:1 PCM ID: 0 + Object.Pipeline { + # playback pipelines + host-copier-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_PLAYBACK_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Playback Volume 1' + } + } + } + ] + + mixout-gain-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Main Playback Volume 2' + } + } + } + ] + + host-gateway-capture [ + { + index 5 + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_CAPTURE_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + } + ] + + io-gateway-capture [ + { + index 6 + + Object.Widget.dai-copier."1" { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_INPUT_CLASS + 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 + } + ] + } + } + ] + } + + Object.PCM.pcm [ + { + name "$HEADSET_PCM_NAME" + id $HEADSET_PCM_ID + direction "duplex" + Object.Base.fe_dai.1 { + name "$HEADSET_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "$HEADSET_PLAYBACK_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "$HEADSET_CAPTURE_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + } + } + ] + + Object.Base.route [ + { + source "gain.2.1" + sink "dai-copier.SSP.$HEADSET_CODEC_NAME.playback" + } + { + source "mixin.1.1" + sink "mixout.2.1" + } + { + source "dai-copier.SSP.$HEADSET_CODEC_NAME.capture" + sink "host-copier.$HEADSET_PCM_ID.capture" + } + { + source "host-copier.$HEADSET_PCM_ID.playback" + sink "gain.1.1" + } + ] + } +} diff --git a/tools/topology/topology2/cavs-mixin-mixout-ctc-ssp.conf b/tools/topology/topology2/cavs-mixin-mixout-ctc-ssp.conf new file mode 100644 index 000000000000..ff8f27102d74 --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-ctc-ssp.conf @@ -0,0 +1,106 @@ +# +# Pipeline definitions +# +# PCM0 ---> gain ----> Mixin ----> Mixout ----> gain ----> CTC ----> SSP0 +# PCM1 ---> gain ----> Mixin ----> Mixout ----> gain ----> CTC ----> SSP1 +# +# The gain before mixin is for the different routes(e.g., deepbuffer, headset). + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline { + # playback pipelines + host-copier-gain-mixin-playback [ + { + index $HEADSET_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_PLAYBACK_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + { + index $SPEAKER_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name '$SPEAKER_PLAYBACK_PCM_STREAM_NAME' + pcm_id $SPEAKER_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + } + ] + + mixout-gain-ctc-dai-copier-playback [ + { + index $HEADSET_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + { + index $SPEAKER_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + Object.Widget.ctc.1 { + Object.Control { + mixer."1" { + name 'CTC Switch' + } + bytes."1" { + name 'CTC.0' + max 4160 + } + } + } + } + ] +} + +Object.Base.route [ + { + source "gain.$HEADSET_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$HEADSET_CODEC_NAME.playback" + } + { + source "mixin.$HEADSET_HOST_PIPELINE_ID.1" + sink "mixout.$HEADSET_DAI_PIPELINE_ID.1" + } + { + source "ctc.$SPEAKER_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$SPEAKER_CODEC_NAME.playback" + } + { + source "mixin.$SPEAKER_HOST_PIPELINE_ID.1" + sink "mixout.$SPEAKER_DAI_PIPELINE_ID.1" + } +] diff --git a/tools/topology/topology2/cavs-mixin-mixout-dax-hda.conf b/tools/topology/topology2/cavs-mixin-mixout-dax-hda.conf new file mode 100644 index 000000000000..bed5549d36bd --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-dax-hda.conf @@ -0,0 +1,446 @@ +<include/components/tdfb.conf> + +Define { + ANALOG_PLAYBACK_PCM 'Analog Playback' + ANALOG_CAPTURE_PCM 'Analog Capture' + HDA_ANALOG_DAI_NAME 'Analog' + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.2.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer HDA Analog' + HDA_ANALOG_CAPTURE_RATE 48000 + HDA_ANALOG_PLAYBACK_RATE 48000 + EFX_FIR_PARAMS 'passthrough' + EFX_IIR_PARAMS 'passthrough' + EFX_DRC_PARAMS 'passthrough' + HDA_MIC_ENHANCED_CAPTURE 'false' + DOLBY_DAX_CORE_ID 0 +} + +# include deep buffer config if buffer size is in 1 - 1000 ms. +IncludeByKey.DEEPBUFFER_FW_DMA_MS{ + "[1-1000]" "platform/intel/deep-buffer.conf" +} + +Object.Dai.HDA [ + { + name $HDA_ANALOG_DAI_NAME + dai_index 0 + id 4 + default_hw_conf_id 4 + Object.Base.hw_config.1 { + name "HDA0" + } + direction duplex + } +] + +Object.Pipeline { + mixout-gain-dax-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $ANALOG_PLAYBACK_PCM Volume' + } + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.dolby-dax.1 { + core_id $DOLBY_DAX_CORE_ID + Object.Control { + mixer."1" { + name 'DAX $ANALOG_PLAYBACK_PCM Switch' + } + mixer."2" { + name 'DAX $ANALOG_PLAYBACK_PCM Switch CP' + } + mixer."3" { + name 'DAX $ANALOG_PLAYBACK_PCM Switch CTC' + } + mixer."4" { + name 'DAX $ANALOG_PLAYBACK_PCM Volume' + } + enum."1" { + name 'DAX $ANALOG_PLAYBACK_PCM Profile' + } + enum."2" { + name 'DAX $ANALOG_PLAYBACK_PCM Device' + } + bytes."1" { + name 'DAX $ANALOG_PLAYBACK_PCM Tuning' + max 8192 + } + } + } + } + ] + + host-copier-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $ANALOG_PLAYBACK_PCM Volume' + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + ] + + host-gateway-capture [ + { + index 3 + + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + dai-copier-eqiir-module-copier-capture [ + { + index 4 + + Object.Widget.dai-copier."1" { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM IIR Eq' + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + } + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.module-copier."2" { + stream_name $HDA_ANALOG_DAI_NAME + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] +} + +IncludeByKey.HDA_MIC_ENHANCED_CAPTURE { + "true" { + Object.Widget.tdfb.1 { + index 3 + + Object.Control { + bytes."1" { + name 'Analog Capture TDFB bytes' + max 16384 + IncludeByKey.EFX_HDA_MIC_TDFB_PARAMS { + "line2_pass" "include/components/tdfb/line2_pass.conf" + "line2_generic_pm10deg" "include/components/tdfb/line2_generic_pm10deg_48khz.conf" + "line2_50mm" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + "line2_68mm" "include/components/tdfb/line2_68mm_pm0_30_90deg_48khz.conf" + "line2_74mm" "include/components/tdfb/line2_74mm_pm0_30_90deg_48khz.conf" + } + } + mixer."1" { + name 'Analog Capture TDFB beam switch' + } + enum."1" { + name 'Analog Capture TDFB angle set enum' + } + # Tracking is disabled from this topology, causes high MCPS + #mixer."2" { + # name 'Analog Capture TDFB track switch' + #} + #enum."2" { + # name 'Analog Capture TDFB angle estimate enum' + #} + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_channels 2 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels 2 + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.drc.1 { + index 3 + + Object.Control { + bytes."1" { + name 'Analog Capture DRC bytes' + IncludeByKey.EFX_HDA_MIC_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "amic_default" "include/components/drc/amic_default.conf" + } + } + mixer."1" { + name 'Analog Capture DRC switch' + } + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } +} + +Object.PCM.pcm [ + { + id 0 + name 'HDA Analog' + Object.Base.fe_dai.1 { + name "HDA Analog" + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $ANALOG_PLAYBACK_PCM + formats 'S32_LE,S24_LE,S16_LE' + rate_min $HDA_ANALOG_PLAYBACK_RATE + rate_max $HDA_ANALOG_PLAYBACK_RATE + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $ANALOG_CAPTURE_PCM + formats 'S32_LE,S24_LE,S16_LE' + rate_min $HDA_ANALOG_CAPTURE_RATE + rate_max $HDA_ANALOG_CAPTURE_RATE + } + direction duplex + } +] + +# top-level pipeline connections +Object.Base.route [ + { + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + source 'dolby-dax.2.1' + } + { + source 'mixin.1.1' + sink 'mixout.2.1' + } + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'eqiir.4.1' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } +] + +IncludeByKey.HDA_MIC_ENHANCED_CAPTURE { + "true" { + Object.Base.route [ + { + source 'module-copier.4.2' + sink 'tdfb.3.1' + } + { + source 'tdfb.3.1' + sink 'drc.3.1' + } + { + source 'drc.3.1' + sink 'host-copier.0.capture' + } + ] + } + "false" { + Object.Base.route [ + { + source 'module-copier.4.2' + sink 'host-copier.0.capture' + } + ] + } +} diff --git a/tools/topology/topology2/cavs-mixin-mixout-dax-ssp.conf b/tools/topology/topology2/cavs-mixin-mixout-dax-ssp.conf new file mode 100644 index 000000000000..23440bc5d163 --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-dax-ssp.conf @@ -0,0 +1,371 @@ +# +# Pipeline definitions +# +# PCM0 ---> gain ----> Mixin ----> Mixout ----> gain ----> DAX ----> CTC ----> SSP0 +# PCM1 ---> gain ----> Mixin ----> Mixout ----> gain ----> DAX ----> CTC ----> SSP1 +# +# The gain before mixin is for the different routes(e.g., deepbuffer, headset). + +Define { + DOLBY_DAX_CORE_ID 0 + SSP_HEADSET_DAX "false" + USE_CTC_SPK "false" +} + + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline { + # playback pipelines + host-copier-gain-mixin-playback [ + { + index $HEADSET_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_PLAYBACK_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + { + index $SPEAKER_HOST_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name '$SPEAKER_PLAYBACK_PCM_STREAM_NAME' + pcm_id $SPEAKER_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] + + IncludeByKey.SSP_HEADSET_DAX { + "true" { + mixout-gain-dax-dai-copier-playback [ + { + index $HEADSET_DAI_PIPELINE_ID + stream_name "$HEADSET_CODEC_NAME" + + Object.Widget.dai-copier.1 { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + + IncludeByKey.SSP_HS_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + + Object.Widget.dolby-dax.1 { + core_id $DOLBY_DAX_CORE_ID + Object.Control { + mixer."1" { + name 'DAX Headphone Switch' + } + mixer."2" { + name 'DAX Headphone Switch CP' + } + mixer."3" { + name 'DAX Headphone Switch CTC' + } + mixer."4" { + name 'DAX Headphone Volume' + } + enum."1" { + name 'DAX Headphone Profile' + } + enum."2" { + name 'DAX Headphone Device' + } + bytes."1" { + name 'DAX Headphone Tuning' + max 8192 + } + } + } + } + ] + } + "false" { + mixout-gain-dai-copier-playback [ + { + index $HEADSET_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + + IncludeByKey.SSP_HS_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + ] + } + } + + IncludeByKey.USE_CTC_SPK { + "true" { + mixout-gain-dax-ctc-dai-copier-playback [ + { + index $SPEAKER_DAI_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + stream_name "$SPEAKER_CODEC_NAME" + + Object.Widget.dai-copier.1 { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + + IncludeByKey.SSP_SPK_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + + Object.Widget.dolby-dax.1 { + core_id $DOLBY_DAX_CORE_ID + Object.Control { + mixer."1" { + name 'DAX Speaker Switch' + } + mixer."2" { + name 'DAX Speaker Switch CP' + } + mixer."3" { + name 'DAX Speaker Switch CTC' + } + mixer."4" { + name 'DAX Speaker Volume' + } + enum."1" { + name 'DAX Speaker Profile' + } + enum."2" { + name 'DAX Speaker Device' + } + bytes."1" { + name 'DAX Speaker Tuning' + max 8192 + } + } + } + + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] + } + "false" { + mixout-gain-dax-dai-copier-playback [ + { + index $SPEAKER_DAI_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + stream_name "$SPEAKER_CODEC_NAME" + + Object.Widget.dai-copier.1 { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + + IncludeByKey.SSP_SPK_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + + Object.Widget.dolby-dax.1 { + core_id $DOLBY_DAX_CORE_ID + Object.Control { + mixer."1" { + name 'DAX Speaker Switch' + } + mixer."2" { + name 'DAX Speaker Switch CP' + } + mixer."3" { + name 'DAX Speaker Switch CTC' + } + mixer."4" { + name 'DAX Speaker Volume' + } + enum."1" { + name 'DAX Speaker Profile' + } + enum."2" { + name 'DAX Speaker Device' + } + bytes."1" { + name 'DAX Speaker Tuning' + max 8192 + } + } + } + + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] + } + } +} + +Object.Base.route [ + { + source "mixin.$HEADSET_HOST_PIPELINE_ID.1" + sink "mixout.$HEADSET_DAI_PIPELINE_ID.1" + } + { + source "mixin.$SPEAKER_HOST_PIPELINE_ID.1" + sink "mixout.$SPEAKER_DAI_PIPELINE_ID.1" + } +] + +IncludeByKey.SSP_HEADSET_DAX { + "true" { + Object.Base.route [ + { + source "dolby-dax.$HEADSET_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$HEADSET_CODEC_NAME.playback" + } + ] + } + "false" { + Object.Base.route [ + { + source "gain.$HEADSET_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$HEADSET_CODEC_NAME.playback" + } + ] + } +} + +IncludeByKey.USE_CTC_SPK { + "true" { + Object.Base.route [ + { + source "ctc.$SPEAKER_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$SPEAKER_CODEC_NAME.playback" + } + ] + } + "false" { + Object.Base.route [ + { + source "dolby-dax.$SPEAKER_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$SPEAKER_CODEC_NAME.playback" + } + ] + } +} diff --git a/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf b/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf new file mode 100644 index 000000000000..7fb10e059678 --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf @@ -0,0 +1,419 @@ +<include/components/tdfb.conf> + +Define { + ANALOG_PLAYBACK_PCM 'Analog Playback' + ANALOG_CAPTURE_PCM 'Analog Capture' + HDA_ANALOG_DAI_NAME 'Analog' + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.2.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer HDA Analog' + HDA_ANALOG_CAPTURE_RATE 48000 + HDA_ANALOG_PLAYBACK_RATE 48000 + HDA_MIC_ENHANCED_CAPTURE 'false' +} + +# 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" +} + +Object.Dai.HDA [ + { + name $HDA_ANALOG_DAI_NAME + dai_index 0 + id 4 + default_hw_conf_id 4 + Object.Base.hw_config.1 { + name "HDA0" + } + direction duplex + } +] + +Object.Pipeline { + IncludeByKey.EFX_DRC_COMPONENT { + "singleband" { + mixout-gain-efx-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $ANALOG_PLAYBACK_PCM Volume' + } + } + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM IIR Eq bytes' + } + } + Object.Widget.eqfir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM FIR Eq bytes' + } + } + Object.Widget.drc.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM DRC bytes' + } + mixer."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM DRC switch' + } + } + } + } + ] + } + "multiband" { + mixout-gain-efx-mbdrc-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $ANALOG_PLAYBACK_PCM Volume' + } + } + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM IIR Eq bytes' + } + } + Object.Widget.eqfir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM FIR Eq bytes' + } + } + Object.Widget.multiband_drc.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM MBDRC bytes' + } + mixer."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM MBDRC switch' + } + } + } + } + ] + } + } + + host-copier-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $ANALOG_PLAYBACK_PCM Volume' + } + } + } + ] + + host-gateway-capture [ + { + index 3 + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + dai-copier-eqiir-module-copier-capture [ + { + index 4 + + Object.Widget.dai-copier."1" { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM IIR Eq' + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + } + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.module-copier."2" { + stream_name $HDA_ANALOG_DAI_NAME + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] +} + +IncludeByKey.HDA_MIC_ENHANCED_CAPTURE { + "true" { + Object.Widget.tdfb.1 { + index 3 + Object.Control { + bytes."1" { + name 'Analog Capture TDFB bytes' + max 16384 + IncludeByKey.EFX_HDA_MIC_TDFB_PARAMS { + "line2_pass" "include/components/tdfb/line2_pass.conf" + "line2_generic_pm10deg" "include/components/tdfb/line2_generic_pm10deg_48khz.conf" + "line2_50mm" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + "line2_68mm" "include/components/tdfb/line2_68mm_pm0_30_90deg_48khz.conf" + "line2_74mm" "include/components/tdfb/line2_74mm_pm0_30_90deg_48khz.conf" + } + } + mixer."1" { + name 'Analog Capture TDFB beam switch' + } + enum."1" { + name 'Analog Capture TDFB angle set enum' + } + # Tracking is disabled from this topology, causes high MCPS + #mixer."2" { + # name 'Analog Capture TDFB track switch' + #} + #enum."2" { + # name 'Analog Capture TDFB angle estimate enum' + #} + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_channels 2 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels 2 + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.drc.1 { + index 3 + Object.Control { + bytes."1" { + name 'Analog Capture DRC bytes' + IncludeByKey.EFX_HDA_MIC_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "amic_default" "include/components/drc/amic_default.conf" + } + } + mixer."1" { + name 'Analog Capture DRC switch' + } + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } +} + +Object.PCM.pcm [ + { + id 0 + name 'HDA Analog' + Object.Base.fe_dai.1 { + name "HDA Analog" + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $ANALOG_PLAYBACK_PCM + formats 'S32_LE,S24_LE,S16_LE' + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $ANALOG_CAPTURE_PCM + formats 'S32_LE,S24_LE,S16_LE' + } + direction duplex + } +] + +# top-level pipeline connections + +IncludeByKey.EFX_DRC_COMPONENT { + "singleband" { + Object.Base.route [ + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } + { + source 'mixin.1.1' + sink 'mixout.2.1' + } + { + source 'drc.2.1' + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + } + ] + } + "multiband" { + Object.Base.route [ + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } + { + source 'mixin.1.1' + sink 'mixout.2.1' + } + { + source 'multiband_drc.2.1' + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + } + ] + } +} + +IncludeByKey.HDA_MIC_ENHANCED_CAPTURE { + "true" { + Object.Base.route [ + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'eqiir.4.1' + } + { + source 'module-copier.4.2' + sink 'tdfb.3.1' + } + { + source 'tdfb.3.1' + sink 'drc.3.1' + } + { + source 'drc.3.1' + sink 'host-copier.0.capture' + } + ] + } + "false" { + Object.Base.route [ + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'eqiir.4.1' + } + { + source 'module-copier.4.2' + sink 'host-copier.0.capture' + } + ] + } + +} diff --git a/tools/topology/topology2/cavs-mixin-mixout-eqiir-dts-ssp.conf b/tools/topology/topology2/cavs-mixin-mixout-eqiir-dts-ssp.conf new file mode 100644 index 000000000000..94fd5257d8cf --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-eqiir-dts-ssp.conf @@ -0,0 +1,168 @@ +# +# Pipeline definitions +# +# PCM0 ---> gain ----> Mixin ----> Mixout ----> gain ----> EQ IIR ----> DTS ----> SSP0 +# PCM1 ---> gain ----> Mixin ----> Mixout ----> gain ----> EQ IIR ----> DTS ----> SSP1 + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline { + # playback pipelines + host-copier-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_PLAYBACK_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + { + index 3 + + Object.Widget.host-copier.1 { + stream_name '$SPEAKER_PLAYBACK_PCM_STREAM_NAME' + pcm_id $SPEAKER_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + } + ] + + mixout-gain-eqiir-dts-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + IncludeByKey.SSP_HS_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'EQIIR2.0 eqiir_coef_2' + } + } + + Object.Widget.dts.1 { + Object.Control.bytes."1" { + max 2048 + name 'CODEC_ADAPTER2.0 DTS Codec Setup 2' + } + } + } + { + index 4 + + Object.Widget.dai-copier.1 { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + IncludeByKey.SSP_SPK_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'EQIIR1.0 eqiir_coef_1' + } + } + + Object.Widget.dts.1 { + Object.Control.bytes."1" { + max 2048 + name 'CODEC_ADAPTER1.0 DTS Codec Setup 1' + } + } + } + ] +} + +Object.Base.route [ + { + source "gain.2.1" + sink "eqiir.2.1" + } + { + source "dts.2.1" + sink "dai-copier.SSP.$HEADSET_CODEC_NAME.playback" + } + { + source "mixin.1.1" + sink "mixout.2.1" + } + { + source "gain.4.1" + sink "eqiir.4.1" + } + { + source "dts.4.1" + sink "dai-copier.SSP.$SPEAKER_CODEC_NAME.playback" + } + { + source "mixin.3.1" + sink "mixout.4.1" + } +] diff --git a/tools/topology/topology2/cavs-mixin-mixout-hda.conf b/tools/topology/topology2/cavs-mixin-mixout-hda.conf new file mode 100644 index 000000000000..e83499754107 --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-hda.conf @@ -0,0 +1,437 @@ +<include/components/tdfb.conf> + +Define { + ANALOG_PLAYBACK_PCM 'Analog Playback' + ANALOG_CAPTURE_PCM 'Analog Capture' + HDA_ANALOG_DAI_NAME 'Analog' + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.2.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer HDA Analog' + COMPR_PIPELINE_SINK 'mixout.2.1' + COMPR_PCM_NAME 'Compress HDA Analog' + HDA_ANALOG_CAPTURE_RATE 48000 + HDA_ANALOG_PLAYBACK_RATE 48000 + EFX_FIR_PARAMS 'passthrough' + EFX_IIR_PARAMS 'passthrough' + EFX_DRC_PARAMS 'passthrough' + HDA_MIC_ENHANCED_CAPTURE 'false' +} + +# 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.COMPRESSED { + "true" "platform/intel/compr.conf" +} + +Object.Dai.HDA [ + { + name $HDA_ANALOG_DAI_NAME + dai_index 0 + id 4 + default_hw_conf_id 4 + Object.Base.hw_config.1 { + name "HDA0" + } + direction duplex + } +] + +Object.Pipeline { + mixout-gain-efx-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $ANALOG_PLAYBACK_PCM Volume' + } + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM IIR Eq bytes' + } + } + Object.Widget.eqfir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM FIR Eq bytes' + } + } + Object.Widget.drc.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM DRC bytes' + } + mixer."1" { + name 'Post Mixer $ANALOG_PLAYBACK_PCM DRC switch' + } + } + } + } + ] + + host-copier-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $ANALOG_PLAYBACK_PCM Volume' + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_PLAYBACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_PLAYBACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + ] + + host-gateway-capture [ + { + index 3 + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + dai-copier-eqiir-module-copier-capture [ + { + index 4 + + Object.Widget.dai-copier."1" { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM IIR Eq' + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + } + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.module-copier."2" { + stream_name $HDA_ANALOG_DAI_NAME + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] +} + +IncludeByKey.HDA_MIC_ENHANCED_CAPTURE { + "true" { + Object.Widget.tdfb.1 { + index 3 + Object.Control { + bytes."1" { + name 'Analog Capture TDFB bytes' + max 16384 + IncludeByKey.EFX_HDA_MIC_TDFB_PARAMS { + "line2_pass" "include/components/tdfb/line2_pass.conf" + "line2_generic_pm10deg" "include/components/tdfb/line2_generic_pm10deg_48khz.conf" + "line2_50mm" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + "line2_68mm" "include/components/tdfb/line2_68mm_pm0_30_90deg_48khz.conf" + "line2_74mm" "include/components/tdfb/line2_74mm_pm0_30_90deg_48khz.conf" + } + } + mixer."1" { + name 'Analog Capture TDFB beam switch' + } + enum."1" { + name 'Analog Capture TDFB angle set enum' + } + # Tracking is disabled from this topology, causes high MCPS + #mixer."2" { + # name 'Analog Capture TDFB track switch' + #} + #enum."2" { + # name 'Analog Capture TDFB angle estimate enum' + #} + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_channels 2 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels 2 + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.drc.1 { + index 3 + Object.Control { + bytes."1" { + name 'Analog Capture DRC bytes' + IncludeByKey.EFX_HDA_MIC_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "amic_default" "include/components/drc/amic_default.conf" + } + } + mixer."1" { + name 'Analog Capture DRC switch' + } + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $HDA_ANALOG_CAPTURE_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $HDA_ANALOG_CAPTURE_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } +} + +Object.PCM.pcm [ + { + id 0 + name 'HDA Analog' + Object.Base.fe_dai.1 { + name "HDA Analog" + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $ANALOG_PLAYBACK_PCM + formats 'S32_LE,S24_LE,S16_LE' + rate_min $HDA_ANALOG_PLAYBACK_RATE + rate_max $HDA_ANALOG_PLAYBACK_RATE + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $ANALOG_CAPTURE_PCM + formats 'S32_LE,S24_LE,S16_LE' + rate_min $HDA_ANALOG_CAPTURE_RATE + rate_max $HDA_ANALOG_CAPTURE_RATE + } + direction duplex + } +] + +# top-level pipeline connections +Object.Base.route [ + { + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + source 'drc.2.1' + } + { + source 'mixin.1.1' + sink 'mixout.2.1' + } + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'eqiir.4.1' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } +] + +IncludeByKey.HDA_MIC_ENHANCED_CAPTURE { + "true" { + Object.Base.route [ + { + source 'module-copier.4.2' + sink 'tdfb.3.1' + } + { + source 'tdfb.3.1' + sink 'drc.3.1' + } + { + source 'drc.3.1' + sink 'host-copier.0.capture' + } + ] + } + "false" { + Object.Base.route [ + { + source 'module-copier.4.2' + sink 'host-copier.0.capture' + } + ] + } +} diff --git a/tools/topology/topology2/cavs-mixin-mixout-ssp.conf b/tools/topology/topology2/cavs-mixin-mixout-ssp.conf new file mode 100644 index 000000000000..50564ab3b291 --- /dev/null +++ b/tools/topology/topology2/cavs-mixin-mixout-ssp.conf @@ -0,0 +1,144 @@ +# +# Pipeline definitions +# +# PCM0 ---> gain ----> Mixin ----> Mixout ----> gain ----> SSP0 +# PCM1 ---> gain ----> Mixin ----> Mixout ----> gain ----> SSP1 +# + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline { + # playback pipelines + host-copier-gain-mixin-playback [ + { + index $HEADSET_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_PLAYBACK_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + { + index $SPEAKER_HOST_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name '$SPEAKER_PLAYBACK_PCM_STREAM_NAME' + pcm_id $SPEAKER_PCM_ID + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] + + mixout-gain-dai-copier-playback [ + { + index $HEADSET_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + IncludeByKey.SSP_HS_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $HEADSET_PCM_NAME Playback Volume' + } + } + } + { + index $SPEAKER_DAI_PIPELINE_ID + core_id $SPEAKER_PCM_CORE_ID + + Object.Widget.dai-copier.1 { + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name "$SPEAKER_CODEC_NAME" + node_type $I2S_LINK_OUTPUT_CLASS + IncludeByKey.SSP_SPK_FMT_24 { + "true" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + "false" { + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $SPEAKER_PCM_NAME Playback Volume' + } + } + + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } + ] +} + +Object.Base.route [ + { + source "gain.$HEADSET_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$HEADSET_CODEC_NAME.playback" + } + { + source "mixin.$HEADSET_HOST_PIPELINE_ID.1" + sink "mixout.$HEADSET_DAI_PIPELINE_ID.1" + } + { + source "gain.$SPEAKER_DAI_PIPELINE_ID.1" + sink "dai-copier.SSP.$SPEAKER_CODEC_NAME.playback" + } + { + source "mixin.$SPEAKER_HOST_PIPELINE_ID.1" + sink "mixout.$SPEAKER_DAI_PIPELINE_ID.1" + } +] diff --git a/tools/topology/topology2/cavs-nocodec-bt.conf b/tools/topology/topology2/cavs-nocodec-bt.conf new file mode 100644 index 000000000000..fe69a352f075 --- /dev/null +++ b/tools/topology/topology2/cavs-nocodec-bt.conf @@ -0,0 +1,684 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<pdm_config.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<input_audio_format.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<data.conf> +<output_audio_format.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<dmic.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<dmic-default.conf> + +<bt-default.conf> +<bt-generic.conf> + +Define { + MCLK 24576000 + NUM_DMICS 0 + # override DMIC default definitions + DMIC0_HOST_PIPELINE_ID 13 + DMIC0_DAI_PIPELINE_ID 14 + DMIC0_HOST_PIPELINE_SINK 'copier.host.13.1' + DMIC0_DAI_PIPELINE_SRC 'dai-copier.DMIC.NoCodec-6.capture' + DMIC0_NAME 'NoCodec-6' + DMIC1_NAME 'NoCodec-7' + DMIC0_PCM_CAPS 'Passthrough Capture 13' + DMIC0_PIPELINE_STREAM_NAME 'dai-copier.DMIC.14.1' + + # override BT configuration + BT_NAME "NoCodec-2" + BT_PB_PCM_CAPS "SSP2 Playback" + BT_CP_PCM_CAPS "SSP2 Capture" + + PLATFORM "none" +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "tgl" "platform/intel/tgl.conf" + "adl" "platform/intel/tgl.conf" + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +# include DMIC config if needed. +IncludeByKey.NUM_DMICS { + "[1-4]" "platform/intel/dmic-generic.conf" +} + +# +# List of all DAIs +# +#SSP Index: 0, Direction: duplex +Object.Dai.SSP [ + { + id 0 + dai_index 0 + direction "duplex" + name NoCodec-0 + default_hw_conf_id 0 + sample_bits 16 + quirks "lbm_mode" + io_clk $BT_MCLK + Object.Base.hw_config.1 { + id 0 + name "BT-SCO-WB" + mclk_freq $BT_MCLK + bclk_freq 256000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 16000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.2 { + id 1 + name "BT-SCO-NB" + mclk_freq $BT_MCLK + bclk_freq 128000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 8000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.3 { + id 2 + name "BT-A2DP" + mclk_freq $BT_MCLK + bclk_freq 1536000 + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 3 + Object.Base.link_config.1 { + clock_source 1 + } + } + } + { + id 1 + dai_index 1 + direction "duplex" + name NoCodec-1 + default_hw_conf_id 0 + sample_bits 16 + quirks "lbm_mode" + io_clk $BT_MCLK + Object.Base.hw_config.1 { + id 0 + name "BT-SCO-WB" + mclk_freq $BT_MCLK + bclk_freq 256000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 16000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.2 { + id 1 + name "BT-SCO-NB" + mclk_freq $BT_MCLK + bclk_freq 128000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 8000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.3 { + id 2 + name "BT-A2DP" + mclk_freq $BT_MCLK + bclk_freq 1536000 + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 3 + Object.Base.link_config.1 { + clock_source 1 + } + } + } +] + +# +# Pipeline definitions +# + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline { + # playback pipelines + io-gateway [ + { + index 2 + direction playback + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-0.playback" + } + + Object.Widget.dai-copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + num_input_audio_formats 3 + num_output_audio_formats 3 + num_input_pins 1 + + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + { + index 4 + direction playback + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-1.playback" + } + + Object.Widget.dai-copier.1 { + dai_index 1 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + num_input_audio_formats 3 + num_output_audio_formats 3 + num_input_pins 1 + + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] + + host-gateway-playback [ + { + index 1 + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-0.playback" + } + Object.Widget.host-copier.1 { + stream_name 'SSP0 Playback' + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + { + index 3 + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-1.playback" + } + Object.Widget.host-copier.1 { + stream_name 'SSP1 Playback' + pcm_id 1 + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] + + # capture pipelines + host-gateway-capture [ + { + index 5 + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-0.capture" + } + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + { + index 9 + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-1.capture" + } + Object.Widget.host-copier.1 { + stream_name 'SSP1 Capture' + pcm_id 1 + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] + + io-gateway-capture [ + { + index 6 + direction capture + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-0.capture" + } + + Object.Widget.dai-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 3 + num_output_audio_formats 3 + num_input_pins 1 + + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + { + index 10 + direction capture + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.NoCodec-1.capture" + } + + Object.Widget.dai-copier."1" { + dai_index 1 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_INPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 3 + num_input_pins 1 + + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] +} + +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' + rates '8000,16000,48000' + channels_min 1 + channels_max 2 + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP0 Capture" + formats 'S16_LE' + rates '8000,16000,48000' + channels_min 1 + channels_max 2 + } + } + { + 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' + rates '8000,16000,48000' + channels_min 1 + channels_max 2 + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP1 Capture" + formats 'S16_LE' + rates '8000,16000,48000' + channels_min 1 + channels_max 2 + } + } +] + +Object.Base.route [ + { + source "host-copier.0.playback" + sink "dai-copier.SSP.NoCodec-0.playback" + } + { + source "host-copier.1.playback" + sink "dai-copier.SSP.NoCodec-1.playback" + } + { + source "dai-copier.SSP.NoCodec-0.capture" + sink "host-copier.0.capture" + } + { + source "dai-copier.SSP.NoCodec-1.capture" + sink "host-copier.1.capture" + } +] diff --git a/tools/topology/topology2/cavs-nocodec.conf b/tools/topology/topology2/cavs-nocodec.conf new file mode 100644 index 000000000000..fea906f98741 --- /dev/null +++ b/tools/topology/topology2/cavs-nocodec.conf @@ -0,0 +1,2178 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<pdm_config.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-capture.conf> +<host-gateway-playback.conf> +<io-gateway-capture.conf> +<io-gateway.conf> +<dai-kpb-be.conf> +<wov-detect.conf> +<host-copier-gain-mixin-playback.conf> +<host-copier-micsel-gain-mixin-playback.conf> +<host-copier-gain-src-mixin-playback.conf> +<mixout-gain-dai-copier-playback.conf> +<mixout-gain-smart-amp-dai-copier-playback.conf> +<dai-copier-gain-module-copier-capture.conf> +<dai-copier-gain-eqiir-module-copier-capture.conf> +<gain-module-copier.conf> +<gain-capture.conf> +<gain-copier-capture.conf> +<deepbuffer-playback.conf> +<mixout-mixin.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<dmic.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<kpb.conf> +<input_pin_binding.conf> +<output_pin_binding.conf> +<input_audio_format.conf> +<output_audio_format.conf> +<dmic-default.conf> +<ssp-default.conf> +<deep-buffer-default.conf> + +Define { + MCLK 24576000 + NUM_DMICS 0 + # override DMIC default definitions + DMIC0_HOST_PIPELINE_ID 13 + DMIC0_DAI_PIPELINE_ID 14 + DMIC0_HOST_PIPELINE_SINK 'host-copier.10.capture' + DMIC0_DAI_PIPELINE_SRC 'module-copier.14.2' + DMIC0_DAI_COPIER 'dai-copier.DMIC.NoCodec-6.capture' + DMIC0_NAME 'NoCodec-6' + DMIC1_NAME 'NoCodec-7' + DMIC0_PCM_CAPS 'Gain Capture 13' + DMIC1_PCM_CAPS 'DMIC1 WOV Capture' + PLATFORM "none" + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.2.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer Port0' + SMART_AMP_UUID "1e:96:7a:16:e4:8a:ea:11:89:f1:00:0c:29:ce:16:35" + # SSP0 stream has two versions: with 3 and with 5 pipelines + SSP0_MIXER_2LEVEL 0 + SSP0_MIXER_PCM_ID_1 41 + SSP0_MIXER_PIPELINE_ID_1 16 + SSP0_MIXER_PIPELINE_ID_2 21 + SSP0_MIXER_SOURCE_1 'mixin.1.1' + SSP0_MIXER_SINK_1 'mixout.2.1' + SSP0_MIXER_SOURCE_2 'mixin.16.1' + SSP0_MIXER_SINK_2 'mixout.16.1' + SSP0_MIXER_SOURCE_3 'mixin.21.1' + SSP1_ENABLED "true" + PASSTHROUGH "false" + SSP0_PCM_NAME "Port0" + SSP0_CAPTURE_PCM "Port0 2nd Capture" + SSP0_CAPTURE_PCM_ID 12 + SSP0_PCM_ID 0 + SSP1_PCM_NAME "Port1" + SSP1_PCM_CORE_ID 1 + SSP2_PCM_NAME "Port2" + SSP2_PCM_CORE_ID 2 + DMIC0_PCM_0_NAME "DMIC SFX1" + DMIC0_PCM_1_NAME "DMIC SFX2" + SRC_DOMAIN "default" + # Keep DP_SRC_CORE_ID == SSP2_PCM_CORE_ID, no nested define resolvation ATM + DP_SRC_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" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" + "nvl" "platform/intel/ptl.conf" # Note: Assume same configuration as PTL +} + +# include DMIC config if needed. +IncludeByKey.NUM_DMICS { + "[1-4]" "platform/intel/dmic-generic.conf" +} + +# include deep buffer config if buffer size is in 1 - 1000 ms. +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" + } + } +} + +# +# 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 + IncludeByKey.SSP0_RATE { + "48000" { + fsync_freq 48000 + bclk_freq 3072000 + tdm_slot_width 32 + } + "96000" { + fsync_freq 96000 + bclk_freq 6144000 + tdm_slot_width 32 + } + "192000" { + fsync_freq 192000 + bclk_freq 12288000 + 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 + IncludeByKey.SSP2_RATE { + "48000" { + fsync_freq 48000 + bclk_freq 3072000 + tdm_slot_width 32 + } + "96000" { + fsync_freq 96000 + bclk_freq 6144000 + tdm_slot_width 32 + } + "192000" { + fsync_freq 192000 + bclk_freq 12288000 + tdm_slot_width 32 + } + } + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } +] + +# +# Pipeline definitions +# +# PCM1 ---> gain ---> Mixin ---> Mixout ---> gain ---> SSP1 +# PCM2 ---> gain ---> SRC ---> Mixin ---> Mixout ---> gain ---> SSP2 +# PCM4 ---> gain ---> Mixin -------------------------->\ +# PCM3 ---> gain ---> Mixin ---->\ \ +# PCM0 ---> micsel ---> gain ---> Mixin ---> Mixout ---> Mixin ---> Mixout ---> gain ---> smart_amp ---> SSP0 +# / +# /---------------------------------------------------------------------------------->/ +# SSP0 ---> gain ---> module-copier ---> module-copier ---> gain ---> PCM0 +# \----> module-copier ---> gain ---> PCM0.1 +# SSP1 ---> PCM1 +# SSP2 ---> SRC ---> PCM2 + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline.host-copier-micsel-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name 'SSP0 Playback' + pcm_id 0 + num_input_audio_formats 49 + num_output_audio_formats 7 + + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + in_sample_type $SAMPLE_TYPE_A_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + in_sample_type $SAMPLE_TYPE_MU_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + in_sample_type $SAMPLE_TYPE_MU_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + in_sample_type $SAMPLE_TYPE_MU_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + in_sample_type $SAMPLE_TYPE_MU_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + in_sample_type $SAMPLE_TYPE_MU_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + in_sample_type $SAMPLE_TYPE_MU_LAW + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + in_sample_type $SAMPLE_TYPE_MU_LAW + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + } + ] + } + Object.Widget.micsel.1 { + Object.Control.bytes.1 { + name 'Pre Mixer $SSP0_PCM_NAME Playback Micsel Bytes' + <include/components/micsel/downmix_71_to_stereo_with_lfe.conf> + } + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Pre Mixer $SSP0_PCM_NAME Playback Volume' + } + } + } + ] + + Object.Pipeline.host-copier-gain-src-mixin-playback [ + { + index 5 + core_id $SSP2_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name 'SSP2 Playback' + pcm_id 2 + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Pre Mixer $SSP2_PCM_NAME Playback Volume' + } + } + Object.Widget.src.1 { + scheduler_domain "$SRC_DOMAIN" + IncludeByKey.SRC_DOMAIN { + "DP" { + core_id $DP_SRC_CORE_ID + domain_id 123 + stack_bytes_requirement 4096 + heap_bytes_requirement 8192 + } + } + } + Object.Widget.pipeline.1 { + core $SSP2_PCM_CORE_ID + } + } + ] + + Object.Pipeline.mixout-gain-smart-amp-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Post Mixer $SSP0_PCM_NAME Playback Volume' + } + } + + Object.Widget.smart_amp.1 { + + Object.Base.input_pin_binding.1 { + input_pin_binding_name "gain.2.1" + } + + Object.Base.input_pin_binding.2 { + input_pin_binding_name "dai-copier.SSP.NoCodec-0.capture" + } + + Object.Control.bytes."1" { + name "Main Playback and $SSP0_PCM_NAME smart_amp_init" + } + } + } + ] + + Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 6 + core_id $SSP2_PCM_CORE_ID + + Object.Widget.dai-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 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Post Mixer $SSP2_PCM_NAME Playback Volume' + } + } + + Object.Widget.pipeline."1" { + core $SSP2_PCM_CORE_ID + } + } + ] + + Object.Pipeline.gain-copier-capture [ + { + index 7 + + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id $SSP0_PCM_ID + num_input_audio_formats 1 + num_output_audio_formats 7 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + { + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_A_LAW + } + { + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_MU_LAW + } + { + 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 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + } + ] + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Post Demux $SSP0_PCM_NAME Capture Volume' + } + + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + # 32-bit 48KHz 2ch + { + 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.Widget.module-copier.2 { + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + # 32-bit 48KHz 2ch + { + 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 + } + ] + } + } + + { + index 17 + format s32le + Object.Widget.host-copier.1 { + stream_name 'SSP0-1 Capture' + pcm_id $SSP0_CAPTURE_PCM_ID + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Post Demux $SSP0_CAPTURE_PCM Volume' + } + + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + # 32-bit 48KHz 2ch + { + 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.Widget.module-copier.2 { + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + # 32-bit 48KHz 2ch + { + 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 + } + ] + } + } + ] + + IncludeByKey.NUM_DMICS { + "[1-4]" { + 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 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.Widget.gain.1 { + curve_type "windows_fade" + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.mixer.1 { + name 'Pre Demux $DMIC0_PCM_0_NAME Capture Volume' + } + } + } + ] + } + } + + Object.Pipeline.dai-copier-gain-module-copier-capture [ + { + index 8 + Object.Widget.dai-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 + } + ] + + num_output_pins 2 + 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" + + 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.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Pre Demux $SSP0_PCM_NAME Capture Volume' + } + } + } + ] + } +"true" { + Object.Pipeline.io-gateway [ + { + index 2 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + { + index 6 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 2 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP2_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP2_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + 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_rate $SSP0_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $SSP0_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $SSP0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP0_RATE + 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_rate $SSP2_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $SSP2_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $SSP2_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP2_RATE + 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 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $SSP0_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $SSP0_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $SSP0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + { + index 11 + core_id $SSP2_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name 'SSP2 Capture' + pcm_id 2 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP2_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $SSP2_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $SSP2_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $SSP2_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.pipeline."1" { + core $SSP2_PCM_CORE_ID + } + } + ] + + Object.Pipeline.io-gateway-capture [ + { + index 8 + direction capture + + Object.Widget.dai-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_output_pins 2 + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + { + in_rate $SSP0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + } +} + +Object.Pipeline.io-gateway-capture [ + { + index 12 + direction capture + core_id $SSP2_PCM_CORE_ID + + Object.Widget.dai-copier."1" { + dai_index 2 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_INPUT_CLASS + + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP2_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP2_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.pipeline."1" { + core $SSP2_PCM_CORE_ID + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline.host-gateway-capture [ + { + index 11 + core_id $SSP2_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name 'SSP2 Capture' + pcm_id 2 + + <include/components/src_format_s32_to_sxx_convert.conf> + } + + Object.Widget.pipeline."1" { + core $SSP2_PCM_CORE_ID + } + + + Object.Widget.src.1 { + index 11 + rate_in 48000 + scheduler_domain "$SRC_DOMAIN" + IncludeByKey.SRC_DOMAIN { + "DP" { + core_id $DP_SRC_CORE_ID + domain_id 123 + stack_bytes_requirement 4096 + heap_bytes_requirement 8192 + } + } + + <include/components/src_format_s32_convert_from_48k.conf> + } + } + ] + + IncludeByKey.NUM_DMICS { + "[1-4]" { + Object.Pipeline.gain-capture [ + { + format $FORMAT + index 18 + Object.Widget.pipeline.1 { + stream_name "$DMIC0_PCM_0_NAME" + } + Object.Widget.host-copier.1 { + stream_name "Gain Capture 18" + pcm_id 27 + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.Widget.gain.1 { + curve_type "windows_fade" + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.mixer.1 { + name 'Post Demux $DMIC0_PCM_0_NAME Capture Volume' + } + } + } + { + format $FORMAT + index 20 + Object.Widget.pipeline.1 { + stream_name "$DMIC0_PCM_1_NAME" + } + Object.Widget.host-copier.1 { + stream_name "Gain Capture 20" + pcm_id 28 + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.Widget.gain.1 { + curve_type "windows_fade" + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.mixer.1 { + name 'Post Demux $DMIC0_PCM_1_NAME Capture Volume' + } + } + } + ] + } + } + } +} + +Object.PCM.pcm [ + { + name "$SSP0_PCM_NAME" + id $SSP0_PCM_ID + direction "duplex" + Object.Base.fe_dai.1 { + name "$SSP0_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP0 Playback" + formats 'S16_LE,S24_LE,S32_LE,U8,A_LAW,MU_LAW,FLOAT_LE' + IncludeByKey.SSP0_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + IncludeByKey.PASSTHROUGH { + "false" { + channels_min 1 + channels_max 8 + } + } + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP0 Capture" + formats 'S16_LE,S24_LE,S32_LE,U8,A_LAW,MU_LAW,FLOAT_LE' + IncludeByKey.SSP0_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + Object.PCM.pcm [ + { + name "$SSP0_CAPTURE_PCM" + id $SSP0_CAPTURE_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$SSP0_CAPTURE_PCM" + } + Object.PCM.pcm_caps.1 { + name "SSP0-1 Capture" + formats 'S16_LE,S24_LE,S32_LE' + } + } + { + name "$DMIC0_PCM_0_NAME" + id 27 + direction "capture" + Object.Base.fe_dai."$DMIC0_PCM_0_NAME" {} + + 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 + IncludeByKey.DMIC0_RATE { + "16000" { + rates '16000' + } + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + } + } + } + { + name "$DMIC0_PCM_1_NAME" + id 28 + direction "capture" + Object.Base.fe_dai."$DMIC0_PCM_1_NAME" {} + + 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 + IncludeByKey.DMIC0_RATE { + "16000" { + rates '16000' + } + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + } + } + } + { + name "$SSP2_PCM_NAME" + id 2 + direction "duplex" + Object.Base.fe_dai.1 { + name "$SSP2_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP2 Playback" + formats 'S16_LE,S24_LE,S32_LE' + rates "8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,176400,192000" + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP2 Capture" + formats 'S16_LE,S24_LE,S32_LE' + rates "8000,11025,16000,22050,32000,44100,48000,64000,88200,96000,176400,192000" + } + } + ] + } +} + +IncludeByKey.PASSTHROUGH { +"true" { + Object.PCM.pcm [ + { + name "$SSP2_PCM_NAME" + id 2 + direction "duplex" + Object.Base.fe_dai.1 { + name "$SSP2_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP2 Playback" + formats 'S16_LE,S24_LE,S32_LE' + IncludeByKey.SSP2_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP2 Capture" + formats 'S16_LE,S24_LE,S32_LE' + IncludeByKey.SSP2_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } + ] + } +} + +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.NUM_DMICS { + "[1-4]" { + Object.Base.route [ + { + 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 "gain.18.1" + sink "host-copier.27.capture" + } + { + source "gain.20.1" + sink "host-copier.28.capture" + } + ] + } + } + + Object.Base.route [ + { + source "smart_amp.2.1" + sink "dai-copier.SSP.NoCodec-0.playback" + } + { + source "gain.6.1" + sink "dai-copier.SSP.NoCodec-2.playback" + } + { + source "mixin.5.1" + sink "mixout.6.1" + } + { + source "dai-copier.SSP.NoCodec-0.capture" + 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 "dai-copier.SSP.NoCodec-0.capture" + sink "smart_amp.2.1" + } + { + source 'host-copier.0.playback' + sink 'micsel.1.1' + } + { + source 'host-copier.2.playback' + sink 'gain.5.1' + } + { + source "gain.7.1" + sink "host-copier.$SSP0_PCM_ID.capture" + } + { + source "gain.17.1" + sink "host-copier.$SSP0_CAPTURE_PCM_ID.capture" + } + { + source "dai-copier.SSP.NoCodec-2.capture" + sink "src.11.1" + } + { + source "src.11.1" + sink "host-copier.2.capture" + } + ] + } +"true" { + Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-0.capture" + sink "host-copier.0.capture" + } + { + source "host-copier.0.playback" + sink "dai-copier.SSP.NoCodec-0.playback" + } + { + source "host-copier.2.playback" + sink "dai-copier.SSP.NoCodec-2.playback" + } + { + source "dai-copier.SSP.NoCodec-2.capture" + sink "host-copier.2.capture" + } + ] + } +} + +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" + } + } +} + +# 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 + IncludeByKey.SSP1_RATE { + "48000" { + fsync_freq 48000 + tdm_slot_width 32 + bclk_freq 3072000 + } + "96000" { + fsync_freq 96000 + tdm_slot_width 32 + bclk_freq 6144000 + } + "192000" { + fsync_freq 192000 + tdm_slot_width 32 + bclk_freq 12288000 + } + } + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } + ] + + Object.Pipeline.io-gateway-capture [ + { + index 10 + direction capture + core_id $SSP1_PCM_CORE_ID + + Object.Widget.dai-copier."1" { + dai_index 1 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_INPUT_CLASS + + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.pipeline."1" { + core $SSP1_PCM_CORE_ID + } + } + ] + + Object.Pipeline.host-gateway-capture [ + { + index 9 + core_id $SSP1_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name 'SSP1 Capture' + pcm_id 1 + } + + Object.Widget.pipeline."1" { + core $SSP1_PCM_CORE_ID + } + } + ] + + IncludeByKey.PASSTHROUGH { + "false" { + Object.Pipeline.host-copier-gain-mixin-playback [ + { + index 3 + core_id $SSP1_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name 'SSP1 Playback' + pcm_id 1 + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Pre Mixer $SSP1_PCM_NAME Playback Volume' + } + } + Object.Widget.pipeline."1" { + core $SSP1_PCM_CORE_ID + } + } + ] + + Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 4 + core_id $SSP1_PCM_CORE_ID + + Object.Widget.dai-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 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Post Mixer $SSP1_PCM_NAME Playback Volume' + } + } + Object.Widget.pipeline."1" { + core $SSP1_PCM_CORE_ID + } + } + ] + } + "true" { + Object.Pipeline.io-gateway [ + { + index 4 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 1 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $SSP1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP1_RATE + 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_rate $SSP1_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $SSP1_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $SSP1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $SSP1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + } + } + + Object.PCM.pcm [ + { + name "$SSP1_PCM_NAME" + id 1 + direction "duplex" + Object.Base.fe_dai.1 { + name "$SSP1_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP1 Playback" + formats 'S16_LE,S24_LE,S32_LE' + IncludeByKey.SSP1_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP1 Capture" + formats 'S16_LE,S24_LE,S32_LE' + IncludeByKey.SSP1_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } + ] + + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "mixin.3.1" + sink "mixout.4.1" + } + { + source "gain.4.1" + sink "dai-copier.SSP.NoCodec-1.playback" + } + { + source 'host-copier.1.playback' + sink 'gain.3.1' + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.1.playback" + sink "dai-copier.SSP.NoCodec-1.playback" + } + ] + } + } + Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-1.capture" + sink "host-copier.1.capture" + } + ] + } +} diff --git a/tools/topology/topology2/cavs-passthrough-hda.conf b/tools/topology/topology2/cavs-passthrough-hda.conf new file mode 100644 index 000000000000..42cae891632a --- /dev/null +++ b/tools/topology/topology2/cavs-passthrough-hda.conf @@ -0,0 +1,362 @@ +Define { + ANALOG_PLAYBACK_PCM 'Analog Playback' + ANALOG_CAPTURE_PCM 'Analog Capture' + HDA_ANALOG_DAI_NAME 'Analog' + CODEC_HDA_CHAIN_DMA 'false' +} + +Object.Dai.HDA [ + { + name $HDA_ANALOG_DAI_NAME + dai_index 0 + id 4 + default_hw_conf_id 4 + Object.Base.hw_config.1 { + name "HDA0" + } + direction duplex + } +] + +Object.Pipeline { + + host-gateway-playback [ + { + index 0 + use_chain_dma $CODEC_HDA_CHAIN_DMA + + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_output_pins 1 + IncludeByKey.CODEC_HDA_CHAIN_DMA { + "false" { + num_input_audio_formats 3 + num_output_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 + } + ] + 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 + } + ] + } + "true" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + } + } + } + } + ] + io-gateway [ + { + direction "playback" + index 1 + use_chain_dma $CODEC_HDA_CHAIN_DMA + + Object.Widget.dai-copier.1 { + dai_type "HDA" + type "dai_in" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_OUTPUT_CLASS + direction playback + num_input_pins 1 + IncludeByKey.CODEC_HDA_CHAIN_DMA { + "false" { + num_input_audio_formats 3 + num_output_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 + } + ] + 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 + } + ] + } + "true" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + } + } + } + } + { + direction "capture" + index 2 + use_chain_dma $CODEC_HDA_CHAIN_DMA + + Object.Widget.dai-copier.1 { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + direction capture + num_output_pins 1 + IncludeByKey.CODEC_HDA_CHAIN_DMA { + "false" { + num_input_audio_formats 3 + num_output_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 + } + ] + 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 + } + ] + } + "true" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + } + } + } + } + ] + host-gateway-capture [ + { + index 3 + use_chain_dma $CODEC_HDA_CHAIN_DMA + + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_pins 1 + IncludeByKey.CODEC_HDA_CHAIN_DMA { + "false" { + num_input_audio_formats 3 + num_output_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 + } + ] + 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 + } + ] + } + "true" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + } + } + } + } + ] +} + +Object.PCM.pcm [ + { + id 0 + name 'HDA Analog' + Object.Base.fe_dai.1 { + name "HDA Analog" + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $ANALOG_PLAYBACK_PCM + IncludeByKey.CODEC_HDA_CHAIN_DMA { + "true" { + formats 'S32_LE,S16_LE' + } + "false" { + formats 'S32_LE,S24_LE,S16_LE' + } + } + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $ANALOG_CAPTURE_PCM + IncludeByKey.CODEC_HDA_CHAIN_DMA { + "true" { + formats 'S32_LE,S16_LE' + } + "false" { + formats 'S32_LE,S24_LE,S16_LE' + } + } + } + direction duplex + } +] + +# top-level pipeline connections +Object.Base.route [ + { + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + source 'host-copier.0.playback' + } + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'host-copier.0.capture' + } +] diff --git a/tools/topology/topology2/cavs-rt5682.conf b/tools/topology/topology2/cavs-rt5682.conf new file mode 100644 index 000000000000..99ccfbfbef56 --- /dev/null +++ b/tools/topology/topology2/cavs-rt5682.conf @@ -0,0 +1,357 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<pdm_config.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<host-copier-gain-mixin-playback.conf> +<mixout-gain-dai-copier-playback.conf> +<mixout-gain-eqiir-dts-dai-copier-playback.conf> +<mixout-gain-ctc-dai-copier-playback.conf> +<mixout-gain-dax-dai-copier-playback.conf> +<mixout-gain-dax-ctc-dai-copier-playback.conf> +<deepbuffer-playback.conf> +<dai-copier-be.conf> +<dai-copier-gain-eqiir-module-copier-capture.conf> +<gain-capture.conf> +<gain-module-copier.conf> +<google-rtc-aec-capture.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<dmic.conf> +<hda.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<dmic-default.conf> +<hdmi-default.conf> +<bt-default.conf> +<deep-buffer-default.conf> +<input_pin_binding.conf> +<output_pin_binding.conf> +<input_audio_format.conf> +<output_audio_format.conf> +<ctc.conf> + +Define { + MCLK 24576000 + # override DMIC default definitions + NUM_DMICS 0 + DMIC0_ID 1 + DMIC1_ID 2 + DMIC0_HOST_PIPELINE_ID 13 + DMIC0_DAI_PIPELINE_ID 14 + DMIC0_HOST_PIPELINE_SINK 'host-copier.99.capture' + DMIC0_DAI_PIPELINE_SRC 'module-copier.14.2' + DMIC0_DAI_COPIER 'dai-copier.DMIC.dmic01.capture' + DMIC0_NAME 'dmic01' + DMIC0_PCM_CAPS 'Gain Capture 13' + # override BE link ids + NUM_HDMIS 3 + HDMI1_ID 3 + HDMI2_ID 4 + HDMI3_ID 5 + HDMI4_ID 6 + SPK_ID 7 + PLATFORM "none" + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.2.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer Jack Out' + DEEP_BUFFER_PIPELINE_ID_2 16 + DEEP_BUFFER_PCM_ID_2 35 + DEEP_BUFFER_PIPELINE_SRC_2 'mixin.16.1' + DEEP_BUFFER_PIPELINE_SINK_2 'mixout.4.1' + DEEP_BUFFER_PCM_NAME_2 'Deepbuffer Amps' + HEADSET_CODEC_NAME 'SSP0-Codec' + HEADSET_PLAYBACK_PCM_STREAM_NAME 'Headset Playback' + HEADSET_CAPTURE_PCM_STREAM_NAME 'Headset Capture' + HEADSET_SSP_DAI_INDEX 0 + HEADSET_HW_CONFIG_NAME 'HEADSET HWCFG' + SPEAKER_CODEC_NAME 'SSP1-Codec' + SPEAKER_PLAYBACK_PCM_STREAM_NAME 'Speaker Playback' + SPEAKER_SSP_DAI_INDEX 1 + SPEAKER_HW_CONFIG_NAME 'SPEAKER HWCFG' + HEADSET_HOST_PIPELINE_ID 1 + HEADSET_DAI_PIPELINE_ID 2 + SPEAKER_HOST_PIPELINE_ID 3 + SPEAKER_DAI_PIPELINE_ID 4 + SPEAKER_PCM_CORE_ID 0 + INCLUDE_ECHO_REF false + ECHO_REF_HOST_PIPELINE_ID 7 + ECHO_REF_DAI_PIPELINE_ID 8 + ECHO_REF_PCM_ID 29 + ECHO_REF_CORE_ID 0 + # override BT default definitions + BT_PB_HOST_PIPELINE_ID 9 + BT_PB_DAI_PIPELINE_ID 10 + BT_PB_DAI_PIPELINE_SRC "copier.host.9.1" + BT_PB_PIPELINE_STREAM_NAME "dai-copier.SSP.10.1" + GOOGLE_RTC_AEC_SUPPORT 0 + # assign core for AEC LL pipelines + GOOGLE_AEC_CORE_ID 0 + # assign core for RTC_AE DP task + GOOGLE_AEC_DP_CORE_ID 0 + HEADSET_PCM_NAME "Headset" + HEADSET_PCM_ID 0 + SPEAKER_PCM_NAME "Speakers" + SPEAKER_PCM_ID 1 + INCLUDE_BT_OFFLOAD true + GOOGLE_AEC_HOST_PIPELINE_PRIORITY 3 + GOOGLE_AEC_PIPELINE_PRIORITY 2 + DMIC_PIPELINE_PRIORITY 1 + ECHO_REF_PIPELINE_PRIORITY 0 + PLAYBACK_PIPELINE_SRC "volume" + USE_CTC_SPK "false" + DOLBY_DAX_CORE_ID 0 + SSP_HEADSET_DAX "false" + SSP_SPK_FMT_24 false + SSP_HS_FMT_24 false +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "adl" "platform/intel/tgl.conf" + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +# include DMIC config if needed. +IncludeByKey.NUM_DMICS { + "[1-4]" "platform/intel/dmic-generic.conf" +} + +# include HDMI config if needed. +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-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" +} + +IncludeByKey.INCLUDE_BT_OFFLOAD { + "true" "platform/intel/bt-generic.conf" +} + +IncludeByKey.PLAYBACK_PIPELINE_SRC { + "volume" "cavs-mixin-mixout-ssp.conf" + "dts" "cavs-mixin-mixout-eqiir-dts-ssp.conf" + "ctc" "cavs-mixin-mixout-ctc-ssp.conf" + "dax" "cavs-mixin-mixout-dax-ssp.conf" +} + + +# +# List of all DAIs +# +#SSP Index: 0, Direction: duplex +Object.Dai.SSP [ + { + id 0 + dai_index $HEADSET_SSP_DAI_INDEX + direction "duplex" + name $HEADSET_CODEC_NAME + default_hw_conf_id 0 + sample_bits 32 + io_clk $MCLK + + Object.Base.hw_config.1 { + name $HEADSET_HW_CONFIG_NAME + id 0 + bclk_freq 3072000 + tdm_slot_width 32 + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } + { + id $SPK_ID + dai_index $SPEAKER_SSP_DAI_INDEX + IncludeByKey.INCLUDE_ECHO_REF { + "false" { + direction "playback" + } + "true" { + direction "duplex" + quirks "lbm_mode" + } + } + name $SPEAKER_CODEC_NAME + default_hw_conf_id 0 + sample_bits 32 + io_clk $MCLK + + Object.Base.hw_config.1 { + name $SPEAKER_HW_CONFIG_NAME + 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 +# +# SSP0 ----> PCM0 +# SSP1 ----> PCM1 + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline { + host-gateway-capture [ + { + index 5 + + Object.Widget.host-copier.1 { + stream_name '$HEADSET_CAPTURE_PCM_STREAM_NAME' + pcm_id $HEADSET_PCM_ID + } + } + ] + + io-gateway-capture [ + { + index 6 + direction capture + + Object.Widget.dai-copier."1" { + dai_index $HEADSET_SSP_DAI_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "$HEADSET_CODEC_NAME" + node_type $I2S_LINK_INPUT_CLASS + + IncludeByKey.SSP_HS_FMT_24 { + "true" { + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_LSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "false" { + 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 + } + ] + } + } + } + } + ] +} + +Object.PCM.pcm [ + { + name "$HEADSET_PCM_NAME" + id $HEADSET_PCM_ID + direction "duplex" + Object.Base.fe_dai.1 { + name "$HEADSET_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "$HEADSET_PLAYBACK_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "$HEADSET_CAPTURE_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + } + } + { + name "$SPEAKER_PCM_NAME" + id $SPEAKER_PCM_ID + direction "playback" + Object.Base.fe_dai.1 { + name "$SPEAKER_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "$SPEAKER_PLAYBACK_PCM_STREAM_NAME" + formats 'S16_LE,S24_LE,S32_LE' + periods_max 16 + period_size_min 192 + period_size_max 16384 + buffer_size_min 65536 + buffer_size_max 65536 + } + } +] + +Object.Base.route [ + { + source "dai-copier.SSP.$HEADSET_CODEC_NAME.capture" + sink "host-copier.$HEADSET_PCM_ID.capture" + } + { + source "host-copier.$HEADSET_PCM_ID.playback" + sink "gain.1.1" + } + { + source "host-copier.$SPEAKER_PCM_ID.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 new file mode 100644 index 000000000000..57f2fcc2a489 --- /dev/null +++ b/tools/topology/topology2/cavs-sdw-src-gain-mixin.conf @@ -0,0 +1,218 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/controls> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<tokens.conf> +<virtual.conf> +<src-gain-mixin-playback.conf> +<mixout-gain-alh-dai-copier-playback.conf> +<host-gateway-capture.conf> +<io-gateway-capture.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<alh.conf> +<hw_config_simple.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> + +Define { + SDW_PLAYBACK_PCM 'SDW0-Playback' + SDW_CAPTURE_PCM 'SDW0-Capture' + PLAYBACK_LINK_ID 0 + CAPTURE_LINK_ID 1 + JACK_OUT_PCM_NAME "Jack Out" + JACK_IN_PCM_NAME "Jack In" +} + +# +# List of all DAIs +# +#ALH Index: 0, Direction: duplex +Object.Dai.ALH [ + { + dai_index 0 + id $PLAYBACK_LINK_ID + direction "playback" + name $SDW_PLAYBACK_PCM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH2" + } + } + { + dai_index 10 + id $CAPTURE_LINK_ID + direction "capture" + name $SDW_CAPTURE_PCM + 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 { + src-gain-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name "Gain Playback 0" + pcm_id 0 + } + Object.Widget.gain.1{ + Object.Control.mixer.1 { + name 'Pre Mixer $JACK_OUT_PCM_NAME Playback Volume' + } + } + + } + ] + + mixout-gain-alh-dai-copier-playback [ + { + index 2 + + Object.Widget.alh-copier.1 { + stream_name $SDW_PLAYBACK_PCM + type "dai_in" + node_type $ALH_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $JACK_OUT_PCM_NAME Playback Volume' + } + } + } + ] + + host-gateway-capture [ + { + index 4 + + Object.Widget.host-copier.1 { + stream_name "Passthrough Capture 0" + pcm_id 1 + } + } + ] +} + +# Capture pipeline widgets +Object.Widget { + alh-copier [ + { + stream_name $SDW_CAPTURE_PCM + direction "capture" + 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 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + + pipeline [ + { + index 3 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] +} + +Object.PCM.pcm [ + { + name "$JACK_OUT_PCM_NAME" + id 0 + direction "playback" + Object.Base.fe_dai.1 { + name "$JACK_OUT_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "Gain Playback 0" + formats 'S16_LE,S32_LE' + rate_min 16000 + rate_max 48000 + } + } + { + name "$JACK_IN_PCM_NAME" + id 1 + direction "capture" + Object.Base.fe_dai.1 { + name "$JACK_IN_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "Passthrough Capture 0" + formats 'S16_LE,S32_LE' + } + } +] + +Object.Base.route [ + { + source "mixin.1.1" + sink "mixout.2.1" + } + { + source 'gain.2.1' + sink 'alh-copier.$SDW_PLAYBACK_PCM.0' + } + { + 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 new file mode 100644 index 000000000000..6932543c06e5 --- /dev/null +++ b/tools/topology/topology2/cavs-sdw.conf @@ -0,0 +1,259 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<pdm_config.conf> +<tokens.conf> +<virtual.conf> +<host-copier-gain-mixin-playback.conf> +<mixout-gain-alh-dai-copier-playback.conf> +<mixout-gain-dax-alh-dai-copier-playback.conf> +<mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback.conf> +<mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback.conf> +<mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback.conf> +<mixout-gain-eqiir-dts-alh-dai-copier-playback.conf> +<dai-copier-gain-eqiir-module-copier-capture.conf> +<gain-capture.conf> +<gain-copier-capture.conf> +<deepbuffer-playback.conf> +<deepbuffer-capture.conf> +<compr-playback.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<host-gateway-tdfb-drc-capture.conf> +<host-gateway-src-mfcc-capture.conf> +<src.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<highpass-capture-be.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<alh.conf> +<hda.conf> +<dmic.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<alh-dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<input_audio_format.conf> +<output_audio_format.conf> +<dmic-default.conf> +<hdmi-default.conf> +<intel/ssp_aux_config.conf> +<ssp.conf> +<bt-default.conf> +<deep-buffer-default.conf> +<compr-default.conf> +<siggen-host-copier-capture.conf> + +Define { + PLATFORM "none" + DMIC_IO_CLK 38400000 + NUM_DMICS 0 + # override DMIC default definitions + PDM1_MIC_A_ENABLE 1 + PDM1_MIC_B_ENABLE 1 + DMIC0_HOST_PIPELINE_ID 100 + DMIC0_DAI_PIPELINE_ID 101 + DMIC0_HOST_PIPELINE_SINK 'host-copier.10.capture' + DMIC0_DAI_PIPELINE_SRC 'module-copier.101.2' + DMIC0_DAI_COPIER 'dai-copier.DMIC.dmic01.capture' + DMIC0_NAME 'dmic01' + DMIC0_ID 4 + DMIC1_ID 5 + DMIC0_PCM_CAPS 'Gain Capture 13' + + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.1.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer Jack Out' + DEEP_BUFFER_PIPELINE_ID_2 16 + DEEP_BUFFER_PCM_ID_2 35 + DEEP_BUFFER_PIPELINE_SRC_2 'mixin.16.1' + DEEP_BUFFER_PIPELINE_SINK_2 'mixout.21.1' + DEEP_BUFFER_PCM_NAME_2 'Deepbuffer Speaker' + + COMPR_PIPELINE_SINK 'mixout.1.1' + COMPR_PCM_NAME 'Compress Jack Out' + COMPR_2_PIPELINE_SINK 'mixout.21.1' + COMPR_2_PCM_NAME 'Compress Speaker' + + SDW_JACK_OUT_STREAM 'SDW0-Playback' + SDW_JACK_IN_STREAM 'SDW0-Capture' + SDW_JACK_OUT_BE_ID 0 + SDW_JACK_IN_BE_ID 1 + NUM_SDW_AMP_LINKS 0 + NUM_SDW_AMP_CTC_LINKS 0 + SDW_DMIC 0 + SDW_JACK true + PASSTHROUGH false + SDW_JACK_CAPTURE_CH 2 + ADD_BT false + SDW_LINK_VALID_BITS 24 + # Used when NUM_SDW_AMP_LINKS is 1 or more + SDW_SPK_ENHANCED_PLAYBACK true + # Used when SDW_DMIC is 1 + SDW_DMIC_ENHANCED_CAPTURE true + EFX_SPK_IIR_PARAMS "highpass_100hz_0db_48khz" + EFX_SPK_FIR_PARAMS "passthrough" + EFX_SPK_DRC_PARAMS "speaker_default" + EFX_MIC_IIR_PARAMS "highpass_40hz_0db_48khz" + EFX_MIC_TDFB_PARAMS "line2_generic_pm10deg" + EFX_MIC_DRC_PARAMS "dmic_default" + DMIC0_DAI_EQIIR "highpass_40hz_20db" + SDW_AMP_NUM_CHANNELS 2 + SDW_AMP_XOVER false + SDW_AMP_XOVER_SELECTOR_PARAMS default + SDW_AMP_XOVER_EQIIR_PARAMS default + SDW_AMP_XOVER_EQFIR_PARAMS default + DOLBY_DAX_CORE_ID 0 + SDW_AMP_PIPELINE_SRC "generic" + SDW_JACK_PIPELINE_SRC "generic" + SDW_ECHO_REF_DAI "false" +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" + "nvl" "platform/intel/ptl.conf" # Note: Assume same configuration as PTL +} + +IncludeByKey.ADD_BT { + "true" "platform/intel/bt-generic.conf" +} + +# include DMIC config if needed. +IncludeByKey.NUM_DMICS { +"[1-4]" "platform/intel/dmic-generic.conf" +} + +Define { + NUM_HDMIS 3 +} + +# include HDMI config if needed. +IncludeByKey.NUM_HDMIS { +"[3-4]" "platform/intel/hdmi-generic.conf" +} + +IncludeByKey.SDW_ECHO_REF_DAI { + "true" { + Object.Widget.alh-copier [ + { + stream_name "Loopback_Virtual" + direction "capture" + type "dai_out" + IncludeByKey.SDW_SPK_ECHO_REF { + "true" {index $SDW_SPK_ECHO_REF_PIPELINE_ID} + "false" {index $SDW_JACK_ECHO_REF_PIPELINE_ID} + } + dai_index 25 + node_type $ALH_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + } +} + +IncludeByKey.SDW_AMP_XOVER { + "false" { + IncludeByKey.NUM_SDW_AMP_LINKS { + "[1-3]" { + IncludeByKey.SDW_AMP_PIPELINE_SRC { + "dax" "platform/intel/sdw-amp-dax.conf" + "dts" "platform/intel/sdw-amp-dts.conf" + "generic" "platform/intel/sdw-amp-generic.conf" + } + } + } + IncludeByKey.NUM_SDW_AMP_CTC_LINKS { + "[1-3]" "platform/intel/sdw-amp-generic-ctc.conf" + } + } + "true" { + IncludeByKey.NUM_SDW_AMP_LINKS { + "[1-3]" "platform/intel/sdw-amp-xover.conf" + } + } +} + +IncludeByKey.SDW_DMIC { +"1" "platform/intel/sdw-dmic-generic.conf" +} + +IncludeByKey.SDW_JACK { +"true" { + IncludeByKey.SDW_JACK_PIPELINE_SRC { + "dax" "platform/intel/sdw-jack-dax.conf" + "dts" "platform/intel/sdw-jack-dts.conf" + "generic" "platform/intel/sdw-jack-generic.conf" + } +} +"false" { + Define { + # disable compressed audio for Jack + COMPRESSED_1 false + } + } +} + +IncludeByKey.NUM_SDW_AMP_LINKS { + "[1-3]" { + Define { + # Enable compressed audio for Speaker + COMPRESSED_2 true + } + } +} + +IncludeByKey.COMPRESSED { + "true" "platform/intel/compr.conf" +} + +IncludeByKey.SDW_JACK_ECHO_REF { + "true" "platform/intel/sdw-jack-echo-ref.conf" +} + +IncludeByKey.SDW_SPK_ECHO_REF { + "true" "platform/intel/sdw-amp-echo-ref.conf" +} + +IncludeByKey.SDW_JACK_AUDIO_FEATURE_CAPTURE { + "true" "platform/intel/sdw-jack-audio-feature.conf" +} + +IncludeByKey.SDW_DMIC_AUDIO_FEATURE_CAPTURE { + "true" "platform/intel/sdw-dmic-audio-feature.conf" +} diff --git a/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf b/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf new file mode 100644 index 000000000000..b567e5f810bb --- /dev/null +++ b/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf @@ -0,0 +1,150 @@ +Define { + ANALOG_PLAYBACK_PCM 'Analog Playback' + ANALOG_CAPTURE_PCM 'Analog Capture' + HDA_ANALOG_DAI_NAME 'Analog' + DEEP_BUFFER_PIPELINE_ID 15 + DEEP_BUFFER_PCM_ID 31 + DEEP_BUFFER_PIPELINE_SRC 'mixin.15.1' + DEEP_BUFFER_PIPELINE_SINK 'mixout.2.1' + DEEP_BUFFER_PCM_NAME 'Deepbuffer HDA Analog' +} + +# 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" +} + +Object.Dai.HDA [ + { + name $HDA_ANALOG_DAI_NAME + dai_index 0 + id 4 + default_hw_conf_id 4 + Object.Base.hw_config.1 { + name "HDA0" + } + direction duplex + } +] + +Object.Pipeline { + mixout-gain-dai-copier-playback [ + { + index 2 + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name $HDA_ANALOG_DAI_NAME + dai_type "HDA" + copier_type "HDA" + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name '2 Main Playback Volume' + } + } + } + ] + + host-copier-gain-src-mixin-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + } + + Object.Widget.src.1 { + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name '1 2nd Playback Volume' + } + } + } + ] + + host-gateway-capture [ + { + index 3 + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + } + } + ] + + io-gateway [ + { + index 4 + direction capture + + Object.Widget.dai-copier."1" { + dai_type "HDA" + type "dai_out" + copier_type "HDA" + stream_name $HDA_ANALOG_DAI_NAME + node_type $HDA_LINK_INPUT_CLASS + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + } + ] +} +Object.PCM.pcm [ + { + id 0 + name 'HDA Analog' + Object.Base.fe_dai.1 { + name "HDA Analog" + } + Object.PCM.pcm_caps.1 { + direction "playback" + name $ANALOG_PLAYBACK_PCM + formats 'S32_LE,S24_LE,S16_LE' + rate_min 8000 + rate_max 192000 + } + Object.PCM.pcm_caps.2 { + direction "capture" + name $ANALOG_CAPTURE_PCM + formats 'S32_LE,S24_LE,S16_LE' + } + direction duplex + } +] + +# top-level pipeline connections +Object.Base.route [ + { + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + source 'gain.2.1' + } + { + source 'mixin.1.1' + sink 'mixout.2.1' + } + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'host-copier.0.capture' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } +] diff --git a/tools/topology/topology2/development/CMakeLists.txt b/tools/topology/topology2/development/CMakeLists.txt new file mode 100644 index 000000000000..89737c734f4d --- /dev/null +++ b/tools/topology/topology2/development/CMakeLists.txt @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-3-Clause + +include(tplg-targets.cmake) +include(tplg-targets-bench.cmake) + +add_custom_target(topology2_dev) + +foreach(tplg ${TPLGS}) + set(defines "") + list(LENGTH tplg length) + list(GET tplg 0 input) + list(GET tplg 1 output) + + math(EXPR last_index "${length}-1") + + # Get the pre-processor definitions from the 3rd item in the list for each topology + # ex: "hda-generic\;hda-generic-2ch\;HDA_CONFIG=gain,DMIC_CH=2", "defines" would contain "HDA_CONFIG=gain,DMIC_CH=2" + if (${last_index} EQUAL 2) + list(GET tplg ${last_index} defines) + endif() + + add_alsatplg2_command("${CMAKE_CURRENT_BINARY_DIR}/../abi.conf" abi_target + "${CMAKE_CURRENT_SOURCE_DIR}/../${input}" "${output}" + "${CMAKE_CURRENT_SOURCE_DIR}/../" "${defines}") + + add_custom_target(topology2_dev_${output} DEPENDS ${output}.tplg) + add_dependencies(topology2_dev topology2_dev_${output}) +endforeach() diff --git a/tools/topology/topology2/development/cavs-nocodec-crossover.conf b/tools/topology/topology2/development/cavs-nocodec-crossover.conf new file mode 100644 index 000000000000..d282c39269b1 --- /dev/null +++ b/tools/topology/topology2/development/cavs-nocodec-crossover.conf @@ -0,0 +1,382 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-capture.conf> +<host-gateway-playback.conf> +<io-gateway-capture.conf> +<io-gateway.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<kpb.conf> +<input_pin_binding.conf> +<output_pin_binding.conf> +<input_audio_format.conf> +<output_audio_format.conf> + +<controls/bytes.conf> +<platform/intel/efx-default.conf> +<crossover.conf> + +Define { + MCLK 24576000 + PLATFORM "none" + SSP0_PCM_ID 0 + SSP0_PCM_NAME "Port0" + SSP1_PCM_NAME "Port1" + SSP2_PCM_NAME "Port2" +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "tgl" "platform/intel/tgl.conf" + "adl" "platform/intel/tgl.conf" + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.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 ---> Crossover ---> SSP0 +# | +# +--------> SSP2 +# +# SSP0 ---> PCM0 +# SSP2 ---> PCM2 + +Object.Pipeline.io-gateway [ + { + index 101 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + 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 + } + ] + } + } + { + index 102 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 2 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + 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-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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } +] + +Object.Widget.crossover [ + { + index 1 + name "crossover.1.1" + + num_input_audio_formats 1 + Object.Base.input_audio_format.1 { + input_pin_index 0 + in_bit_depth 32 + in_valid_bit_depth 32 + } + + num_output_pins 2 + num_output_audio_formats 2 + Object.Base.output_audio_format { + 1 { + output_pin_index 0 + out_bit_depth 32 + out_valid_bit_depth 32 + } + 2 { + output_pin_index 1 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + + Object.Base.output_pin_binding.1 { + output_pin_binding_name "dai-copier.SSP.NoCodec-0.playback" + } + + Object.Base.output_pin_binding.2 { + output_pin_binding_name "dai-copier.SSP.NoCodec-2.playback" + } + + Object.Control.bytes."1" { + name "crossover.1.1_bytes_control" + IncludeByKey.EFX_CROSSOVER_PARAMS { + "2way" "include/components/crossover/coef_2way_48000_200_0_1.conf" + "3way" "include/components/crossover/coef_3way_48000_200_1000_0_1_2.conf" + "4way" "include/components/crossover/coef_4way_48000_200_1000_3000_0_1_2_3.conf" + } + } + } +] + + +Object.Pipeline.host-gateway-capture [ + { + index 7 + + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id 0 + } + } +] + +Object.Pipeline.io-gateway-capture [ + { + index 8 + direction capture + + Object.Widget.dai-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_output_pins 2 + 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.host-copier.1 { + stream_name 'SSP2 Capture' + pcm_id 2 + } + } +] + +Object.Pipeline.io-gateway-capture [ + { + index 12 + direction capture + + Object.Widget.dai-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.PCM.pcm [ + { + name "$SSP0_PCM_NAME" + id $SSP0_PCM_ID + direction "duplex" + Object.Base.fe_dai.1 { + name "$SSP0_PCM_NAME" + } + + 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 'S32_LE' + } + } + { + name "$SSP2_PCM_NAME" + id 2 + direction "capture" + Object.Base.fe_dai.1 { + name "$SSP2_PCM_NAME" + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP2 Capture" + formats 'S32_LE' + } + } +] + +Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-0.capture" + sink "host-copier.0.capture" + } + { + source "host-copier.0.playback" + sink "crossover.1.1" + } + { + source "crossover.1.1" + sink "dai-copier.SSP.NoCodec-0.playback" + } + + { + source "dai-copier.SSP.NoCodec-2.capture" + sink "host-copier.2.capture" + } + { + source "crossover.1.1" + sink "dai-copier.SSP.NoCodec-2.playback" + } +] + diff --git a/tools/topology/topology2/development/cavs-nocodec-rtcaec.conf b/tools/topology/topology2/development/cavs-nocodec-rtcaec.conf new file mode 100644 index 000000000000..a35d9ba1de7c --- /dev/null +++ b/tools/topology/topology2/development/cavs-nocodec-rtcaec.conf @@ -0,0 +1,373 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-capture.conf> +<host-gateway-playback.conf> +<io-gateway-capture.conf> +<io-gateway.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<intel/hw_config_cardinal_clk.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<pipeline.conf> +<dai.conf> +<host.conf> +<input_pin_binding.conf> +<output_pin_binding.conf> +<input_audio_format.conf> +<output_audio_format.conf> + +<controls/bytes.conf> +<google-rtc-aec.conf> + +Define { + MCLK 24576000 + PLATFORM "none" + SSP0_PCM_ID 0 + SSP0_PCM_NAME "Port0" + SSP1_PCM_NAME "Port1" + SSP2_PCM_NAME "Port2" +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "tgl" "platform/intel/tgl.conf" + "adl" "platform/intel/tgl.conf" + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.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 --(1)----------------(2)--> SSP0 +# +# PCM2 --(5)----------------(6)--> SSP2 +# +# SSP0 --(8)---> RTCAEC ----(7)--> PCM0 +# ^ +# | +# SSP2 --(12)------+ + +Object.Pipeline.io-gateway [ + { + index 2 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + { + index 6 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 2 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_pins 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } +] + +Object.Pipeline.host-gateway-playback [ + { + index 1 + Object.Widget.host-copier.1 { + stream_name 'SSP0 Playback' + pcm_id 0 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } + { + index 5 + Object.Widget.host-copier.1 { + stream_name 'SSP2 Playback' + pcm_id 2 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } +] + +Object.Pipeline.host-gateway-capture [ + { + index 7 + + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id 0 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } +] + +Object.Pipeline.io-gateway-capture [ + { + index 8 + direction capture + + Object.Widget.dai-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 16 + out_valid_bit_depth 16 + } + ] + } + } + { + index 12 + direction capture + + Object.Widget.dai-copier.1 { + dai_index 2 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-2" + 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 16 + out_valid_bit_depth 16 + } + ] + } + } +] + +Object.PCM.pcm [ + { + name "$SSP0_PCM_NAME" + id $SSP0_PCM_ID + direction "duplex" + Object.Base.fe_dai.1 { + name "$SSP0_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP0 Playback" + formats 'S16_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP0 Capture" + formats 'S16_LE' + } + } + { + name "$SSP2_PCM_NAME" + id 2 + direction "playback" + Object.Base.fe_dai.1 { + name "$SSP2_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP2 Playback" + formats 'S16_LE' + } + } +] + +Object.Widget.google-rtc-aec [ + { + index 7 + name "google-rtc-aec.7.1" + + Object.Base.input_pin_binding.1 { + input_pin_binding_name "dai-copier.SSP.NoCodec-0.capture" + } + + Object.Base.input_pin_binding.2 { + input_pin_binding_name "dai-copier.SSP.NoCodec-2.capture" + } + } +] + +Object.Base.route [ + { + source "host-copier.0.playback" + sink "dai-copier.SSP.NoCodec-0.playback" + } + { + source "host-copier.2.playback" + sink "dai-copier.SSP.NoCodec-2.playback" + } + { + source "dai-copier.SSP.NoCodec-0.capture" + sink "google-rtc-aec.7.1" + } + { + source "dai-copier.SSP.NoCodec-2.capture" + sink "google-rtc-aec.7.1" + } + { + source "google-rtc-aec.7.1" + sink "host-copier.0.capture" + } +] diff --git a/tools/topology/topology2/development/sof-plugin.conf b/tools/topology/topology2/development/sof-plugin.conf new file mode 100644 index 000000000000..dcbe68b056de --- /dev/null +++ b/tools/topology/topology2/development/sof-plugin.conf @@ -0,0 +1,347 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<manifest.conf> +<tokens.conf> +<host-gateway-capture.conf> +<host-gateway-playback.conf> +<mixout-gain-dai-copier-playback.conf> +<host-copier-gain-mixin-playback.conf> +<io-gateway-capture.conf> +<io-gateway.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<ssp.conf> +<route.conf> +<common_definitions.conf> +<dai-copier.conf> +<module-copier.conf> +<gain.conf> +<pipeline.conf> +<input_audio_format.conf> +<output_audio_format.conf> +<ov_noise_suppression.conf> + +Object.Pipeline.io-gateway-capture [ + { + index 10 + direction capture + + Object.Widget.dai-copier."1" { + dai_index 1 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_INPUT_CLASS + + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 16000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate 16000 + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } +] + +Object.Pipeline.host-gateway-capture [ + { + index 9 + + Object.Widget.host-copier.1 { + stream_name 'SSP1 Capture' + pcm_id 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 16000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate 16000 + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } +] + +IncludeByKey.PLAYBACK_PROCESS { +"passthrough" { + Object.Pipeline.io-gateway [ + { + index 4 + direction playback + + Object.Widget.dai-copier.1 { + dai_index 1 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } + ] + Object.Pipeline.host-gateway-playback [ + { + index 3 + Object.Widget.host-copier.1 { + stream_name 'SSP1 Playback' + pcm_id 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } + ] + } +"mix" { + Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 4 + + Object.Widget.dai-copier.1 { + dai_index 1 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Post Mixer PlugPCM Playback Volume' + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + Object.Widget.mixout.1 { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } + ] + Object.Pipeline.host-copier-gain-mixin-playback [ + { + index 3 + Object.Widget.host-copier.1 { + stream_name 'SSP1 Playback' + pcm_id 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Pre Mixer PlugPCM Playback Volume' + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + Object.Widget.mixin.1 { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } + ] + } +} + +Object.PCM.pcm [ + { + name "PluginPCM" + id 1 + direction "duplex" + Object.Base.fe_dai.1 { + name "PluginPlayback" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP1 Playback" + formats 'S16_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP1 Capture" + formats 'S16_LE' + } + } +] + +IncludeByKey.NOISE_SUPPRESSION { +"true" { + Object.Widget.ov_ns.1 { + index 9 + } + Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-1.capture" + sink "ov_ns.9.1" + } + { + source "ov_ns.9.1" + sink "host-copier.1.capture" + } + ] + } +"false" { + Object.Base.route [ + { + source "dai-copier.SSP.NoCodec-1.capture" + sink "host-copier.1.capture" + } + ] + } +} + +IncludeByKey.PLAYBACK_PROCESS { +"passthrough" { + Object.Base.route [ + { + source "host-copier.1.playback" + sink "dai-copier.SSP.NoCodec-1.playback" + } + ] + } +"mix" { + Object.Base.route [ + { + source "host-copier.1.playback" + sink "gain.3.1" + } + { + source "mixin.3.1" + sink "mixout.4.1" + } + { + source "gain.4.1" + sink "dai-copier.SSP.NoCodec-1.playback" + } + ] + } +} diff --git a/tools/topology/topology2/development/tplg-targets-bench.cmake b/tools/topology/topology2/development/tplg-targets-bench.cmake new file mode 100644 index 000000000000..5c0f82dc7dfc --- /dev/null +++ b/tools/topology/topology2/development/tplg-targets-bench.cmake @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# +# Append test topologies for multiple formats +# to TPLGS array. +# + +set(sampleformats "16" "24" "32") + +set(components + "asrc" + "dcblock" + "dolby-dax" + "drc" + "drc_multiband" + "eqiir" + "eqfir" + "gain" + "igo_nr" + "level_multiplier" + "mfcc" + "mfccmel" + "micsel" + "rtnr" + "sound_dose" + "src" + "src_lite" + "stft_process_192_48_" + "stft_process_512_128_" + "stft_process_768_120_" + "stft_process_1024_256_" + "stft_process_1536_240_" + "tdfb" + "template_comp" +) + +set(component_parameters + "BENCH_ASRC_PARAMS=default" + "BENCH_DCBLOCK_PARAMS=default" + "BENCH_DOLBY-DAX_PARAMS=default" + "BENCH_DRC_PARAMS=default_speaker_mic" + "BENCH_DRC_MULTIBAND_PARAMS=default" + "BENCH_EQIIR_PARAMS=loudness" + "BENCH_EQFIR_PARAMS=loudness" + "BENCH_GAIN_PARAMS=default" + "BENCH_IGO_NR_PARAMS=default" + "BENCH_LEVEL_MULTIPLIER_PARAMS=default" + "BENCH_MFCC_PARAMS=default" + "BENCH_MFCC_PARAMS=mel80" + "BENCH_MICSEL_PARAMS=passthrough" + "BENCH_RTNR_PARAMS=default" + "BENCH_SOUND_DOSE_PARAMS=default" + "BENCH_SRC_PARAMS=default" + "BENCH_SRC_LITE_PARAMS=default" + "BENCH_STFT_PROCESS_PARAMS=hann_192_48" + "BENCH_STFT_PROCESS_PARAMS=hann_512_128" + "BENCH_STFT_PROCESS_PARAMS=hann_768_120" + "BENCH_STFT_PROCESS_PARAMS=hann_1024_256" + "BENCH_STFT_PROCESS_PARAMS=hann_1536_240" + "BENCH_TDFB_PARAMS=default" + "BENCH_TEMPLATE_COMP_PARAMS=default" +) + +set(components_s24 + "aria" +) + +set(component_parameters_s24 + "BENCH_ARIA_PARAMS=param_2" +) + +set(components_s32 + "micsel_multich" +) + +set(component_parameters_s32 + "BENCH_MICSEL_PARAMS=default" +) + +set (plat "mtl") + +# Add components with all sample formats +foreach(sf ${sampleformats}) + foreach(comp bench_param IN ZIP_LISTS components component_parameters) + set(item "cavs-benchmark-hda\;sof-hda-benchmark-${comp}${sf}\;PLATFORM=${plat},BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + set(item "cavs-benchmark-sdw\;sof-${plat}-sdw-benchmark-${comp}${sf}-sdw0\;PLATFORM=${plat},BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + set(item "cavs-benchmark-sdw\;sof-${plat}-sdw-benchmark-${comp}${sf}-simplejack\;PLATFORM=${plat},SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + #message(STATUS "Item=" ${item}) + endforeach() +endforeach() + +# Add components with single format +set (sf "24") +foreach(comp bench_param IN ZIP_LISTS components_s24 component_parameters_s24) + set(item "cavs-benchmark-hda\;sof-hda-benchmark-${comp}${sf}\;PLATFORM=${plat},BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + set(item "cavs-benchmark-sdw\;sof-${plat}-sdw-benchmark-${comp}${sf}-sdw0\;PLATFORM=${plat},BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + set(item "cavs-benchmark-sdw\;sof-${plat}-sdw-benchmark-${comp}${sf}-simplejack\;PLATFORM=${plat},SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") +endforeach() + +set (sf "32") +foreach(comp bench_param IN ZIP_LISTS components_s32 component_parameters_s32) + #message(STATUS "Bench_param=" ${bench_param}) + set(item "cavs-benchmark-hda\;sof-hda-benchmark-${comp}${sf}\;PLATFORM=${plat},BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + set(item "cavs-benchmark-sdw\;sof-${plat}-sdw-benchmark-${comp}${sf}-sdw0\;PLATFORM=${plat},BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") + set(item "cavs-benchmark-sdw\;sof-${plat}-sdw-benchmark-${comp}${sf}-simplejack\;PLATFORM=${plat},SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,BENCH_MODULE_FORMAT=s${sf},BENCH_CONFIG=${comp}${sf},${bench_param}") + list(APPEND TPLGS "${item}") +endforeach() diff --git a/tools/topology/topology2/development/tplg-targets.cmake b/tools/topology/topology2/development/tplg-targets.cmake new file mode 100644 index 000000000000..a906852d04f0 --- /dev/null +++ b/tools/topology/topology2/development/tplg-targets.cmake @@ -0,0 +1,489 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +set(TPLGS +# CAVS SDW topology with passthrough pipelines +"cavs-sdw\;cavs-sdw\;" + +# CAVS SDW with SRC gain and mixer support +"cavs-sdw-src-gain-mixin\;cavs-sdw-src-gain-mixin" + +# SDW + HDMI topology with passthrough pipelines +"cavs-sdw\;cavs-sdw-hdmi\;" + +# CAVS SSP topology for TGL +# multicore disabled due to SOF issue #8942 +"cavs-nocodec\;sof-tgl-nocodec\;NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-nocodec.bin,\ +SSP1_PCM_CORE_ID=0,SSP2_PCM_CORE_ID=0,\ +SSP0_MIXER_2LEVEL=1,PLATFORM=tgl" + +# multicore disabled due to SOF issue #8942 +"cavs-nocodec\;sof-adl-nocodec\;NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +SSP1_PCM_CORE_ID=0,SSP2_PCM_CORE_ID=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-adl-nocodec.bin,PLATFORM=adl" + +# SDW topology for MTL +"cavs-sdw\;mtl-sdw\;NUM_HDMIS=0" + +# SDW + HDMI topology for MTL +"cavs-sdw\;mtl-sdw-hdmi\;PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-mtl-sdw-hdmi.bin" + +# 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" +"cavs-nocodec\;sof-mtl-nocodec-ssp0-ssp2\;PLATFORM=mtl,NUM_DMICS=2,SSP1_ENABLED=false,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-nocodec-ssp0-ssp2.bin" + +# SSP topology for LNL +"cavs-nocodec\;sof-lnl-nocodec\;PLATFORM=lnl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-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-sdw\;sof-lnl-fpga-rt711-l0\;PLATFORM=lnl,NUM_HDMIS=0,PASSTHROUGH=true" + +# HDA topology with passthrough analog codec pipelines +"sof-hda-generic\;sof-hda-passthrough\;HDA_CONFIG=passthrough" +# HDA topology with passthrough analog codec pipelines using CHAIN_DMA +"sof-hda-generic\;sof-hda-passthrough-chain-dma\;HDA_CONFIG=passthrough,CODEC_HDA_CHAIN_DMA=true" + +# SSP topology for PTL, includes Data Processing SRC +"cavs-nocodec\;sof-ptl-nocodec\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-nocodec.bin,SRC_DOMAIN=DP" + +# SSP topology for PTL with 96 kHz DMIC +"cavs-nocodec\;sof-ptl-nocodec-dmic-4ch-96k\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_RATE=96000,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-nocodec-dmic-4ch-96k.bin" + +# SSP topology for PTL with 96 kHz DMIC and 96 kHz SSP0 +"cavs-nocodec\;sof-ptl-nocodec-dmic-4ch-96k-ssp0-96k\;PLATFORM=ptl,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_RATE=96000,SSP0_RATE=96000,PASSTHROUGH=true,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-nocodec-dmic-4ch-96k-ssp0-96k.bin" + +# SSP topology for PTL with 96 kHz DMIC and 192 kHz SSP0 +"cavs-nocodec\;sof-ptl-nocodec-dmic-4ch-96k-ssp0-192k\;PLATFORM=ptl,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_RATE=96000,SSP0_RATE=192000,PASSTHROUGH=true,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-nocodec-dmic-4ch-96k-ssp0-192k.bin" + +# SSP topology for PTL FPGA with lower DMIC IO clock of 19.2MHz, 2ch PDM0 enabled +"cavs-nocodec\;sof-ptl-nocodec-fpga-2ch-pdm0\;PLATFORM=ptl,NUM_DMICS=2,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-nocodec-fpga-2ch-pdm0.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" + +# SSP topology for PTL FPGA with lower DMIC IO clock of 19.2MHz, 4ch both PDM0 and PDM1 enabled +"cavs-nocodec\;sof-ptl-nocodec-fpga-4ch\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-nocodec-fpga-4ch.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" + +# SSP topology for PTL FPGA with lower DMIC IO clock of 19.2MHz, 4ch both PDM0 and PDM1 enabled, with 96 kHz DMIC +"cavs-nocodec\;sof-ptl-nocodec-fpga-dmic-4ch-96k\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_RATE=96000,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-nocodec-fpga-dmic-4ch-96k.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" + +# SSP topology for PTL FPGA, same as previous but with 96 kHz SSP0 +"cavs-nocodec\;sof-ptl-nocodec-fpga-dmic-4ch-96k-ssp0-96k\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_RATE=96000,SSP0_RATE=96000,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-nocodec-fpga-dmic-4ch-96k-ssp0-96k.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" + +# SSP topology for NVL (limit to DSP cores 0/1) +"cavs-nocodec\;sof-nvl-nocodec\;PLATFORM=nvl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,SSP2_PCM_CORE_ID=0,DP_SRC_CORE_ID=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nvl-nocodec.bin" + +# Topology for PTL with max98357a and rt5682 +"cavs-rt5682\;sof-ptl-max98357a-rt5682-ssp2-ssp0\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-max98357a-rt5682-ssp2-ssp0.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,DEEP_BUF_SPK=true" + +# Topology for PTL with rt5682 (SSP 0), max98360a (SSP 1), BT (SSP 2) and PDM0, PDM1 enabled +"cavs-rt5682\;sof-ptl-max98360a-rt5682\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-max98360a-rt5682.bin,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +BT_NAME=SSP2-BT,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true" + +# 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,HDA_MIC_ENHANCED_CAPTURE=true,\ +EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough,EFX_DRC_PARAMS=passthrough,\ +EFX_HDA_MIC_TDFB_PARAMS=line2_pass,EFX_HDA_MIC_DRC_PARAMS=passthrough" + +"sof-hda-generic\;sof-hda-efx-generic-2ch\;\ +HDA_CONFIG=efx,NUM_DMICS=2,\ +EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough,EFX_DRC_PARAMS=passthrough,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-efx-generic-4ch\;\ +HDA_CONFIG=efx,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough,EFX_DRC_PARAMS=passthrough,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DMIC0_PCM_CHANNELS=4" + +"sof-hda-generic\;sof-hda-efx-generic-4to2ch\;\ +HDA_CONFIG=efx,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough,EFX_DRC_PARAMS=passthrough,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DMIC0_PCM_CHANNELS=2" + +"sof-hda-generic\;sof-hda-efx-mbdrc-generic\;HDA_CONFIG=efx,HDA_MIC_ENHANCED_CAPTURE=true,\ +EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough,EFX_DRC_COMPONENT=multiband,\ +EFX_MBDRC_PARAMS=passthrough,EFX_HDA_MIC_TDFB_PARAMS=line2_pass,EFX_HDA_MIC_DRC_PARAMS=passthrough" + +"sof-hda-generic\;sof-hda-efx-mbdrc-generic-2ch\;\ +HDA_CONFIG=efx,NUM_DMICS=2,EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough,\ +EFX_DRC_COMPONENT=multiband,EFX_MBDRC_PARAMS=passthrough,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-efx-mbdrc-generic-4ch\;\ +HDA_CONFIG=efx,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,EFX_FIR_PARAMS=passthrough,\ +EFX_IIR_PARAMS=passthrough,EFX_DRC_COMPONENT=multiband,EFX_MBDRC_PARAMS=passthrough,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DMIC0_PCM_CHANNELS=4" + +"sof-hda-generic\;sof-hda-efx-mbdrc-generic-4to2ch\;\ +HDA_CONFIG=efx,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,EFX_FIR_PARAMS=passthrough,\ +EFX_IIR_PARAMS=passthrough,EFX_DRC_COMPONENT=multiband,EFX_MBDRC_PARAMS=passthrough,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DMIC0_PCM_CHANNELS=2" + +# With 16 kHz DMIC1 +"sof-hda-generic\;sof-hda-generic-cavs25-4ch-48k-16k\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-4ch-48k-16k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC1_ENABLE=passthrough,DMIC1_RATE=16000" + +"sof-hda-generic\;sof-hda-generic-ace1-4ch-48k-16k\;HDA_CONFIG=mix,PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-4ch-48k-16k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC1_ENABLE=passthrough,DMIC1_RATE=16000" + +# With 4ch 96 kHz DMIC1 and HDA +"sof-hda-generic\;sof-hda-generic-cavs25-4ch-48k-96k\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-4ch-48k-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC1_ENABLE=passthrough,\ +DMIC1_RATE=96000,DMIC1_PCM_ID=22" + +"sof-hda-generic\;sof-hda-generic-ace1-4ch-48k-96k\;HDA_CONFIG=mix,PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-4ch-48k-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC1_ENABLE=passthrough,\ +DMIC1_RATE=96000,DMIC1_PCM_ID=22" + +# With 2ch 96 kHz DMIC1 and HDA +"sof-hda-generic\;sof-hda-generic-cavs25-2ch-48k-96k\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-2ch-48k-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC1_ENABLE=passthrough,\ +DMIC1_RATE=96000,DMIC1_PCM_ID=22" + +"sof-hda-generic\;sof-hda-generic-ace1-2ch-48k-96k\;HDA_CONFIG=mix,PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-2ch-48k-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC1_ENABLE=passthrough,\ +DMIC1_RATE=96000,DMIC1_PCM_ID=22" + +# With 4ch 96 kHz DMIC0 and HDA +"sof-hda-generic\;sof-hda-generic-cavs25-4ch-96k\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-4ch-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_RATE=96000" + +"sof-hda-generic\;sof-hda-generic-ace1-4ch-96k\;HDA_CONFIG=mix,PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-4ch-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_RATE=96000" + +# With 2ch 96 kHz DMIC0 and HDA +"sof-hda-generic\;sof-hda-generic-cavs25-2ch-96k\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-2ch-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_RATE=96000" + +"sof-hda-generic\;sof-hda-generic-ace1-2ch-96k\;HDA_CONFIG=mix,PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-2ch-96k.bin,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_RATE=96000" + +# With 96 kHz HDA +"sof-hda-generic\;sof-hda-generic-96k\;HDA_CONFIG=mix,\ +DEEPBUFFER_FW_DMA_MS=false,HDA_ANALOG_CAPTURE_RATE=96000,HDA_ANALOG_PLAYBACK_RATE=96000,NUM_DMICS=0" + +# SDW + DMIC + HDMI, with 16 kHz DMIC1 +"cavs-sdw\;sof-mtl-sdw-cs42l42-l0-max98363-l2-4ch-48k-16k\;PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-sdw-cs42l42-l0-max98363-l2-4ch-48k-16k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +DMIC1_ENABLE=passthrough,DMIC1_RATE=16000,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +NUM_SDW_AMP_LINKS=1,SDW_SPK_STREAM=SDW2-Playback,SDW_AMP_FEEDBACK=false,\ +SDW_JACK_CAPTURE_CH=1,DEEPBUFFER_FW_DMA_MS=100,DEEPBUFFER_D0I3_COMPATIBLE=true,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +# SDW + DMIC + HDMI, with 96 kHz DMIC1 +"cavs-sdw\;sof-mtl-sdw-cs42l42-l0-max98363-l2-4ch-48k-96k\;PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-sdw-cs42l42-l0-max98363-l2-4ch-48k-96k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +DMIC1_ENABLE=passthrough,DMIC1_RATE=96000,DMIC1_PCM_ID=22,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +NUM_SDW_AMP_LINKS=1,SDW_SPK_STREAM=SDW2-Playback,SDW_AMP_FEEDBACK=false,\ +SDW_JACK_CAPTURE_CH=1,DEEPBUFFER_FW_DMA_MS=100,DEEPBUFFER_D0I3_COMPATIBLE=true,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +# SDW + DMIC + HDMI, with 96 kHz DMIC0 +"cavs-sdw\;sof-mtl-sdw-cs42l42-l0-max98363-l2-4ch-96k\;PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-sdw-cs42l42-l0-max98363-l2-4ch-96k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,DMIC0_RATE=96000,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +NUM_SDW_AMP_LINKS=1,SDW_SPK_STREAM=SDW2-Playback,SDW_AMP_FEEDBACK=false,\ +SDW_JACK_CAPTURE_CH=1,DEEPBUFFER_FW_DMA_MS=100,DEEPBUFFER_D0I3_COMPATIBLE=true,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +# SDW + DMIC + HDMI, with 16 kHz DMIC1 +"cavs-rt5682\;sof-mtl-max98360a-rt5682-4ch-48k-16k\;PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-max98360a-rt5682-4ch-48k-16k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,\ +DMIC1_ENABLE=passthrough,DMIC1_RATE=16000,DMIC1_PCM_ID=100,\ +DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true,GOOGLE_AEC_DP_CORE_ID=2" + +# SDW + DMIC + HDMI, with 96 kHz DMIC1 +"cavs-rt5682\;sof-mtl-max98360a-rt5682-4ch-48k-96k\;PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-max98360a-rt5682-4ch-48k-96k.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,\ +DMIC1_ENABLE=passthrough,DMIC1_RATE=96000,DMIC1_PCM_ID=100,\ +DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true,GOOGLE_AEC_DP_CORE_ID=2" + +# 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" + +# 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" + +# BT offload for ptl +"cavs-nocodec-bt\;sof-nocodec-bt-ptl\;PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-ptl.bin,\ +PLATFORM=ptl" +# BT offload loopback test topology (lbm) for ptl +"cavs-nocodec-bt\;sof-nocodec-bt-ptl-lbm\;BT_LOOPBACK_MODE=true,PLATFORM=ptl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-ptl-lbm.bin" + +# CAVS HDA topology for benchmarking performance +# Copier - peak volume - mixin - mixout - aria - peak volume - mixin - mixout - copier +"cavs-benchmark-hda\;sof-hda-benchmark-generic\;HDA_CONFIG=benchmark,BENCH_CONFIG=benchmark,\ +BENCH_ARIA_PARAMS=param_1,BENCH_MODULE_FORMAT=s24" + +# Topology to test IPC4 Crossover +"development/cavs-nocodec-crossover\;sof-tgl-nocodec-crossover-2way\;PLATFORM=tgl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-nocodec-crossover.bin,EFX_CROSSOVER_PARAMS=2way" + +# Topology to test RTC AEC +"development/cavs-nocodec-rtcaec\;sof-tgl-nocodec-rtcaec\;PLATFORM=tgl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-nocodec-rtcaec.bin" + +# SSP test topology for Data Processing SRC on MTL +"cavs-nocodec\;sof-mtl-nocodec-dp-test\;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,SRC_DOMAIN=DP" +# SSP test topology for Data Processing SRC on LNL +"cavs-nocodec\;sof-lnl-nocodec-dp-test\;PLATFORM=lnl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-nocodec.bin,SRC_DOMAIN=DP" +# SSP test topology for PTL with no DP +"cavs-nocodec\;sof-ptl-nocodec-dp-test\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-nocodec.bin" + +# SSP test topology for Data Processing on core 1 SRC for MTL +"cavs-nocodec\;sof-mtl-nocodec-dp-core-test\;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,SRC_DOMAIN=DP,DP_SRC_CORE_ID=1" +# SSP test topology for Data Processing on core 1 SRC for LNL +"cavs-nocodec\;sof-lnl-nocodec-dp-core-test\;PLATFORM=lnl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-nocodec.bin,SRC_DOMAIN=DP,DP_SRC_CORE_ID=1" +# SSP test topology for Data Processing on core 1 SRC for PTL +"cavs-nocodec\;sof-ptl-nocodec-dp-core-test\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-nocodec.bin,SRC_DOMAIN=DP,DP_SRC_CORE_ID=1" + +# Add MFCC to 16 kHz DMIC1, 2ch with NHLT - cAVS +"sof-hda-generic\;sof-hda-generic-cavs25-2ch-mfcc\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-2ch-mfcc.bin,\ +NUM_DMICS=2,DMIC1_RATE=16000,DMIC1_ENABLE=MFCC,DMIC1_MFCC_PARAMS=default" + +# Add MFCC to 16 kHz DMIC1, 2ch with NHLT - ACE1 +"sof-hda-generic\;sof-hda-generic-ace1-2ch-mfcc\;PLATFORM=mtl,HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-2ch-mfcc.bin,\ +NUM_DMICS=2,DMIC1_RATE=16000,DMIC1_ENABLE=MFCC,DMIC1_MFCC_PARAMS=default" + +# Add MFCC to 16 kHz DMIC1, 4ch with NHLT - cAVS +"sof-hda-generic\;sof-hda-generic-cavs25-4ch-mfcc\;HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-4ch-mfcc.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC1_RATE=16000,\ +DMIC1_ENABLE=MFCC,DMIC1_MFCC_PARAMS=default" + +# Add MFCC to 16 kHz DMIC1, 4ch with NHLT - ACE1 +"sof-hda-generic\;sof-hda-generic-ace1-4ch-mfcc\;PLATFORM=mtl,HDA_CONFIG=mix,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-4ch-mfcc.bin,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC1_RATE=16000,\ +DMIC1_ENABLE=MFCC,DMIC1_MFCC_PARAMS=default" + +# Topology for SOF plugin +"development/sof-plugin\;sof-plugin\;NOISE_SUPPRESSION=false,PLAYBACK_PROCESS=passthrough" + +# mtl-rt5650 with AEC but not DTS +"cavs-rt5682\;sof-mtl-rt5650-google-aec\;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-rt5650-google-aec.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true,PLAYBACK_PIPELINE_SRC=volume,\ +SSP_SPK_FMT_24=true,SSP_HS_FMT_24=true" + +# mtl-rt1019 with CTC +"cavs-rt5682\;sof-mtl-rt1019-rt5682-ctc\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,SPK_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-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,\ +INCLUDE_ECHO_REF=true,INCLUDE_BT_OFFLOAD=false,PLAYBACK_PIPELINE_SRC=ctc" + +# mtl-rt5650 with CTC +"cavs-rt5682\;sof-mtl-rt5650-ctc\;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-rt5650-dts.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +DEEP_BUF_SPK=true,PLAYBACK_PIPELINE_SRC=ctc,SSP_SPK_FMT_24=true,SSP_HS_FMT_24=true" + +# mtl-rt1019-rt5650 with DAX +"cavs-rt5682\;sof-mtl-rt1019-rt5682-dax\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,SPK_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-rt1019-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,\ +INCLUDE_ECHO_REF=true,PLAYBACK_PIPELINE_SRC=dax,DOLBY_DAX_CORE_ID=2,SSP_HEADSET_DAX=true,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true" + +# CS35L56 SSP2 +"cavs-cs35l56\;sof-tgl-cs35l56-ssp2\;PLATFORM=tgl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-tgl-cs35l56-ssp2.bin" + +# Topology for Google Brya +"cavs-rt5682\;sof-adl-max98357a-rt5682\;PLATFORM=adl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,NUM_HDMIS=4,\ +NHLT_BIN=nhlt-sof-adl-max98357a-rt5682.bin,SPK_ID=7,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +INCLUDE_BT_OFFLOAD=false,DEEP_BUF_SPK=true,SPEAKER_CODEC_NAME=SSP2-Codec,SPEAKER_SSP_DAI_INDEX=2" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC +# Enable FLOAT_LE and U8 PCM formats +"cavs-sdw\;sof-ptl-rt721-4ch-allfmt\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch-allfmt.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,PCM_FORMAT_ALL=true" + +# Deep buffer DMIC0 +"sof-hda-generic\;sof-hda-generic-2ch-dmicdeepbuf\;HDA_CONFIG=mix,\ +NUM_DMICS=2,DMIC0_DEEP_BUFFER=true,DEEPBUFFER_FW_DMA_MS=10,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-4ch-dmicdeepbuf\;HDA_CONFIG=mix,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_DEEP_BUFFER=true,DEEPBUFFER_FW_DMA_MS=10,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# Deep buffer DMIC0 with tplg NHLT for PTL, 2ch and 4ch +"sof-hda-generic\;sof-hda-generic-ace3-2ch-dmicdeepbuf\;PLATFORM=ptl,HDA_CONFIG=mix,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace3-2ch-dmicdeepbuf.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DMIC0_DEEP_BUFFER=true,DEEPBUFFER_FW_DMA_MS=10" + +"sof-hda-generic\;sof-hda-generic-ace3-4ch-dmicdeepbuf\;PLATFORM=ptl,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-ace3-4ch-dmicdeepbuf.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DMIC0_DEEP_BUFFER=true,DEEPBUFFER_FW_DMA_MS=10" + +# Deep buffer DMIC0 with RT721 eval board with PCH-DMIC +"cavs-sdw\;sof-ptl-rt721-4ch-dmicdeepbuf\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch-dmicdeepbuf.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,DMIC0_DEEP_BUFFER=true" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC +# Enable echo reference capture from jack and speaker output +"cavs-sdw\;sof-ptl-rt721-4ch-echoref\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch-echoref.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,SDW_JACK_ECHO_REF=true,SDW_SPK_ECHO_REF=true,SDW_ECHO_REF_DAI=true" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC +# Enable echo reference capture from jack and speaker output +# Enable SSP2 BT +"cavs-sdw\;sof-ptl-rt721-4ch-ssp2bt-echoref\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch-echoref.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +BT_NAME=SSP2-BT,BT_PCM_ID=20,BT_ID=10,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,SDW_JACK_ECHO_REF=true,SDW_SPK_ECHO_REF=true,SDW_ECHO_REF_DAI=true" + +# RT722 with PCH-DMIC and echo reference capture from jack and speaker output +"cavs-sdw\;sof-ptl-rt722-4ch-echoref\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt722-4ch-echoref.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +SDW_JACK_ECHO_REF=true,SDW_SPK_ECHO_REF=true,SDW_ECHO_REF_DAI=true" + +# Soundwire topologies with compressed support +"cavs-sdw\;sof-arl-cs42l43-l0-compr\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,COMPRESSED=true" + +"cavs-sdw\;sof-mtl-rt713-l0-rt1316-l12-compr\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,COMPRESSED=true" + +"cavs-sdw\;sof-ptl-rt721-compr\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,COMPRESSED=true" + +"cavs-sdw\;sof-ptl-rt722-compr\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,COMPRESSED=true" + +# Soundwire topologies with MFCC audio features capture +"cavs-sdw\;sof-mtl-rt713-l0-rt1316-l12-mfcc\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,SDW_JACK_AUDIO_FEATURE_CAPTURE=true" + +"cavs-sdw\;sof-arl-cs42l43-l0-cs35l56-l23-mfcc\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +SDW_JACK_AUDIO_FEATURE_CAPTURE=true,SDW_DMIC_AUDIO_FEATURE_CAPTURE=true" +) diff --git a/tools/topology/topology2/doc/CMakeLists.txt b/tools/topology/topology2/doc/CMakeLists.txt new file mode 100644 index 000000000000..303d06da3d15 --- /dev/null +++ b/tools/topology/topology2/doc/CMakeLists.txt @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.13) + +project(SOF_TOPOLOGY2_DOC NONE) + +set(SOF_ROOT_SOURCE_DIRECTORY "${PROJECT_SOURCE_DIR}/..") + +set(top_srcdir "${SOF_ROOT_SOURCE_DIRECTORY}") +set(top_bindir "${PROJECT_BINARY_DIR}") + +configure_file( + "${PROJECT_SOURCE_DIR}/sof.doxygen.in" + "${PROJECT_BINARY_DIR}/sof.doxygen" +) + +file(GLOB_RECURSE topology2_sources "${SOF_ROOT_SOURCE_DIRECTORY}/*.conf") +file(GLOB_RECURSE extra_sources "${PROJECT_SOURCE_DIR}/extra-contents/*.doxy") + +add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/contents.doxy + COMMAND ${PROJECT_SOURCE_DIR}/topology2-generate-contents.sh > ${PROJECT_BINARY_DIR}/contents.doxy + DEPENDS ${PROJECT_SOURCE_DIR}/topology2-generate-contents.sh + DEPENDS ${topology2_sources} + VERBATIM +) + +add_custom_target(doc-contents + DEPENDS ${PROJECT_BINARY_DIR}/contents.doxy +) + +add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/doxygen/html/index.html + COMMAND doxygen sof.doxygen + DEPENDS ${PROJECT_BINARY_DIR}/sof.doxygen + DEPENDS ${PROJECT_SOURCE_DIR}/topology2-filter.py + DEPENDS doc-contents + DEPENDS ${extra_sources} + DEPENDS ${topology2_sources} + VERBATIM + USES_TERMINAL +) + +add_custom_target(doc ALL + DEPENDS ${PROJECT_BINARY_DIR}/doxygen/html/index.html + VERBATIM +) diff --git a/tools/topology/topology2/doc/README b/tools/topology/topology2/doc/README new file mode 100644 index 000000000000..a412e1d2d707 --- /dev/null +++ b/tools/topology/topology2/doc/README @@ -0,0 +1,7 @@ +To build the topology2 source documentation do following steps: + +cd tools/topology/topology2/doc +cmake -B build/ +cmake --build build/ -v + +After the last command you should find the html documentation under: sof/tools/topology/topology2/doc/build/doxygen/html diff --git a/tools/topology/topology2/doc/extra-contents/mainpage.doxy b/tools/topology/topology2/doc/extra-contents/mainpage.doxy new file mode 100644 index 000000000000..4b2a2bfcabc8 --- /dev/null +++ b/tools/topology/topology2/doc/extra-contents/mainpage.doxy @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2023 Intel Corporation. All rights reserved. */ +/*! \mainpage Sound Open Firmware Topology2 + * + * \section this_document This Document + * + * This document is generated from SOF topology2 sources and its + * purpose is provide examples of how SOF ALSA topologies are built + * through instantiating toppology2 classes. + * + * The documentation is provided using Doxygen package and a Doxygen + * filter that translates the topology2 classes into C-structures. The + * filter is implemented in python and can be found from + * tools/topology/topology2/doc/topology2-filter.py + * + * The topology2 language syntax is described in detail <a + * href="https://thesofproject.github.io/latest/developer_guides/topology2/topology2.html">here</a>. + * + * \subsection doc_reading Reading the document + * + * The purpose of the translated C code is not to document actual + * topology2 code, but only to provide anchors for Doxygen to form a + * network of links through which to navigate the topology sources and + * find the pieces of related Doxygen documentation. The filter also + * creates separate pages of the original code and add links next to + * the pages in the C struct definition and instance documentation. + * + * The most essential part of the documentation is the documentation of + * classes that shown as C structs in this Doxygen documentation. + * + * \copydoc doc_contents + */ diff --git a/tools/topology/topology2/doc/sof.doxygen.in b/tools/topology/topology2/doc/sof.doxygen.in new file mode 100644 index 000000000000..8e278f79bfa3 --- /dev/null +++ b/tools/topology/topology2/doc/sof.doxygen.in @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: BSD-3-Clause +PROJECT_NAME = "Sound Open Firmware Topology2" +OUTPUT_DIRECTORY = doxygen +GENERATE_LATEX = NO +GENERATE_RTF = NO +GENERATE_MAN = NO +GENERATE_XML = YES + +CASE_SENSE_NAMES = NO +INPUT = @top_srcdir@ \ + @top_srcdir@/doc/extra-contents/ \ + @top_bindir@/contents.doxy + +RECURSIVE = YES +FILE_PATTERNS = *.conf,*.doxy +IMAGE_PATH = +QUIET = YES +WARN_LOGFILE = doxygen_warnings.txt + +EXTRACT_ALL = YES +EXTRACT_STATIC = YES +WARN_IF_UNDOCUMENTED = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +INHERIT_DOCS = YES + +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +OPTIMIZE_OUTPUT_FOR_C = YES + +HTML_TIMESTAMP = NO + +EXTENSION_MAPPING = conf=C,doxy=C +FILTER_PATTERNS = *.conf=@top_srcdir@/doc/topology2-filter.py diff --git a/tools/topology/topology2/doc/topology2-filter.py b/tools/topology/topology2/doc/topology2-filter.py new file mode 100755 index 000000000000..7ff465c66be7 --- /dev/null +++ b/tools/topology/topology2/doc/topology2-filter.py @@ -0,0 +1,745 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation. All rights reserved. +# +# The usage of this command is simple. It takes one argument, a path +# to a SOF topology2 source file, and it produces to stdout something +# that can be parsed by Doxygen as C source. Produced output contains +# C struct definitions and instantiations analogous to the topology2 +# classes and object instances. +# +# The purpose of the translated C code is not to document actual +# topology2 code, but only to provide anchors for Doxygen to form a +# network of links through which to navigate the topology sources and +# find the pieces of related Doxygen documentation. The filter also +# creates separate pages of the original code and adds links next to the +# pages in the C struct definition, instance documentation and their +# possible Doxygen documentation. + +import sys +import os +import re +import io +import logging + +logging.basicConfig(filename='filter_debug.txt', filemode='a', encoding='utf-8', + level=logging.DEBUG) + +def fname(): + try: + name = sys._getframe(1).f_code.co_name + except (IndexError, TypeError, AttributeError): + name = "<unknown>" + return name + +def cbracket_count(line): + val = line.count("{") - line.count("}") + return val + +def sbracket_count(line): + val = line.count("[") - line.count("]") + return val + +def doxy_check_add(doxy, line): + if line.find("##") >= 0: + doxy = doxy + line[line.find("##"):].replace("##", "//!", 1) + if line.find("#") >= 0: + line = line[0:line.find("#")] + return (doxy, line) + +def print_doxy(doxy, file = sys.stdout): + if len(doxy): + print(doxy, file=file) + return "" + return doxy + +def parse_include_str(line): + if re.search(r"^\s*\<[A-Za-z0-9\/_\-\.]+\>\s*", line): + tok = line.split() + return "#include " + tok[0] + "\n" + return None + +def parse_include(line): + str = parse_include_str(line) + if str: + print(str) + return True + return False + +def parse_define_block(fline, instream): + """Parses topology2 Define { } block and outputs C-preprocessor #define macros + + Parameters: + fline (string): First input line that was read by the caller + instream (stream): Input stream of topology2 file we are decoding + + Returns: + string: The original code that was translated + """ + if re.search(r"^\s*Define\s+\{", fline): + logging.debug("fline: %s", fline) + doxy = "" + for line in instream: + if cbracket_count(line) < 0: + break + (doxy, line) = doxy_check_add(doxy, line) + doxy = print_doxy(doxy) + tok = line.split(maxsplit = 2) + if len(tok) < 2: + continue + val = trim_value(line[line.find(tok[0]) + len(tok[0]):]) + print("#define %s\t%s" % (trim_c_id(tok[0]), val)) + return True + return False + +def parse_include_by_key(fline, instream, file): # For now just skip + """Handles IncludeByKey { } blocks, currently handles only actual + includes, not nested {} blocks but everything is included into + raw_code return value. + + Parameters: + fline (string): First input line that was read by the caller + instream (stream): Input stream of topology2 file we are decoding + file (stream): Output stream for the translated output + + Returns: + string: The original code that was translated + + """ + if re.search(r"^\s*IncludeByKey\.", fline): + logging.debug("fline: %s", fline) + bsum = cbracket_count(fline) + if bsum == 1: + # Assume IncludeByKey.<variable> { + tok = fline.split() + tok = tok[0].split(".") + name = tok[1] + raw_code = "" + ifstr = "if" + for line in instream: + raw_code = raw_code + line + bsum = bsum + cbracket_count(line) + tok = line.split("\"") + if len(tok) >= 4: + print("#%s %s == \"%s\"\n#include <%s>" % + (ifstr, name, tok[1], tok[3]), file = file) + if ifstr == "if": + ifstr = "elif" + if bsum < 1: + if ifstr != "if": + print("#endif", file = file) + return raw_code + return None + +def trim_value(val): + val = val.strip(" \t\n$") + end = len(val) - 1 + if val[0:1] == "\"" and val[end:] == "\"": + return val + if val.isidentifier() or val.isnumeric(): + return val + if val[0:1] == "\'" and val[end:] == "\'": + val = val.strip("\'") + return "\"" + val + "\"" + +def trim_c_id(name): + name = name.strip(" \t\n\"\'") + name = name.replace("-", "_") + name = name.replace(" ", "_") + return name + + +def parse_attribute_constraints(instream, name): + """Parses a Constraints { } block and produces a C enum definition if possible + + Parameters: + instream (stream): Input stream of topology2 file we are decoding + name (string): Attribute name of this constraints block belongs to + + Returns: + string: C enum definition or an empty string + + """ + logging.debug("name: %s", name) + valid_values = [] + tuple_values = [] + doxy = "" # This is thrown away since there is no C anchror to connect it- + raw_code = "" + enum = "" + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if cbracket_count(line) < 0: + break + if re.search(r"^\s*\!valid_values\s+\[", line): + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if sbracket_count(line) < 0: + break + valid_values.append(trim_c_id(line)) + if re.search(r"^\s*\!tuple_values\s+\[", line): + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if sbracket_count(line) < 0: + break + tuple_values.append(trim_value(line)) + if len(valid_values) > 1 and len(valid_values) == len(tuple_values): + enum = "enum " + name + " {\n" + for i in range(len(valid_values)): + enum = enum + "\t\t" + valid_values[i] + " =\t" + tuple_values[i] + ",\n" + enum = enum + "\t}" + elif len(valid_values) > 1 and len(tuple_values) == 0: + enum = "enum " + name + " {\n" + for i in range(len(valid_values)): + enum = enum + "\t\t" + valid_values[i] + "," + if valid_values[i][0:1] == "$": # If its a variable add a reference to it + enum = enum + " //!< \\ref " + valid_values[i][1:] + enum = enum + "\n" + enum = enum + "\t}" + return (raw_code, enum) + +def parse_class_attribute(attributes, doxy, instream, fline): + """Parses a DefineAttribute { } block and collects the information into + attributes dict. Any already accumulated Doxygen documentation is + also stored there under the attribute name- + + Parameters: + attributes (dict): A dictionary where data about the attribute is stored + doxy (strung): Doxygen documentation collected just before the attribute + instream (stream): Input stream of topology2 file we are decoding + fline (string): First input line that was read by the caller + + Returns: + string: The original code that was translated + """ + logging.debug("fline: %s", fline) + tok = fline.split("\"") + if len(tok) > 1: + name = tok[1] + else: + tok = fline.split(".") + tok = tok[1].split(" ") + name = tok[0] + (doxy, fline) = doxy_check_add(doxy, fline) + bsum = cbracket_count(fline) + typestr = "" + token_ref = "" + ref_type = "" + enum = "" + raw_code = "" + if bsum < 1: + # Assume: DefineAttribute.name {} + typestr = "int" + else: + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + bsum = bsum + cbracket_count(line) + if bsum < 1: + break + if re.search(r"^\s*constraints\s+\{", line) and bsum == 2: + (code, enum) = parse_attribute_constraints(instream, name) + raw_code = raw_code + code + bsum = 1 + elif re.search(r"^\s*type\s", line): + tok = line.split() + typestr = tok[1].strip(" \t\n\"\'") + elif re.search(r"^\s*token_ref\s", line): + tok = line.split() + token_ref = tok[1].strip(" \t\n\"\'") + tok = token_ref.split(".") + ref_type = tok[1] + logging.debug("type %s token_ref %s ref_type %s enum %s", + typestr, token_ref, ref_type, enum) + if enum != "" and ref_type != "bool": + typestr = enum + if ref_type == "string": + doxy = doxy + "//! \\em string type\n" + elif typestr == "" or ref_type == "bool": + typestr = ref_type + attributes[name] = { "type": typestr, "doxy": doxy, "token_ref": token_ref } + return raw_code + +def print_attributes(attributes): + """Print out struct members and their doxygen documentation from attributes dict. + + Parameters: + attributes (dict): A dictionary where data about the attributes was stored + """ + for name in attributes: + doxy = "" + if attributes[name].get("doxy"): + doxy = attributes[name]["doxy"] + "\n" + if attributes[name].get("type"): + typestr = attributes[name]["type"] + print("%s\t%s %s;\n" % (doxy, typestr, name)) + +def set_attribute_flag(attributes, attribute, flag): + if not attributes.get(attribute): + attributes[attribute] = {} + attributes[attribute][flag] = True + +def parse_attributes_block(instream, attributes, attrib_doxy): + """Parse attributes block inside class definition and store the flags in attributes dict + + Parameters: + instream (stream): Input stream of topology2 file we are decoding + attributes (dict): Dict where data about the attributes is stored + attrib_doxy (dict): Dict to store doxygen docs associated with the attributes block + + Returns: + string: The original code that was translated + """ + logging.debug("called") + raw_code = "" + doxy = "" + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if cbracket_count(line) < 0: + break + if re.search(r"^\s*\!constructor\s+\[", line): + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if sbracket_count(line) < 0: + break + set_attribute_flag(attributes, trim_c_id(line), "constructor") + attrib_doxy["constructor"] = doxy + doxy = "" + elif re.search(r"^\s*\!mandatory\s+\[", line): + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if sbracket_count(line) < 0: + break + set_attribute_flag(attributes, trim_c_id(line), "mandatory") + attrib_doxy["mandatory"] = doxy + doxy = "" + elif re.search(r"^\s*\!immutable\s+\[", line): + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if sbracket_count(line) < 0: + break + set_attribute_flag(attributes, trim_c_id(line), "immutable") + attrib_doxy["immutable"] = doxy + doxy = "" + elif re.search(r"^\s*\!deprecated\s+\[", line): + attrib_doxy["deprecated"] = doxy + doxy = "" + for line in instream: + raw_code = raw_code + line + (doxy, line) = doxy_check_add(doxy, line) + if sbracket_count(line) < 0: + break + set_attribute_flag(attributes, trim_c_id(line), "deprecated") + elif re.search(r"^\s*unique\s+", line): + tok = line.split() + attrib_doxy["unique"] = doxy + doxy = "" + set_attribute_flag(attributes, trim_c_id(tok[1]), "unique") + return raw_code + +def attribute_block_print(class_name, attributes, attrib_doxy): + """Generates a Doxygen documentation section from attribute flags + and doxygen docs stored to attrib_doxy + + Parameters: + class_name (string): Name of the class we are processing + attributes (dict): Dict where data about the attributes was stored + attrib_doxy (dict): Dict where doxygen docs of the attributes block was stored + + """ + logging.debug("class_name \'%s\'", class_name) + for field in attrib_doxy: + # Only add attribute paragraph if there are doxygen comment for it + if attrib_doxy[field] != "": + print("//! \\par %s attributes:\n//!" % field.capitalize()) + for attr in attributes: + if attributes[attr].get(field): + print("//! \\link %s::%s \\endlink \\n" % (class_name, attr)) + print("//! \\n\n%s" % attrib_doxy[field]) + +def attribute_block_info_add(attributes, attrib_doxy): + """Add simple bullets in the attribute (= struct members) documentation if + the attribute has constructor, mandatory, immutable, deprecated, or unique + property. + + Parameters: + attributes (dict): Dict where data about the attributes was stored + attrib_doxy (dict): Dict where doxygen docs of the attributes block was stored + + """ + # TODO: Add short documentation about the attribute properties and link to it. + for field in attrib_doxy: + for attr in attributes: + if attributes[attr].get(field): + if not attributes[attr].get("doxy"): + attributes[attr]["doxy"] = "" + attributes[attr]["doxy"] = "//! - \\em " + field + " attribute.\\n\n" + attributes[attr]["doxy"] + +def parse_class_contents(class_name, attributes, attrib_doxy, objs, defaults, + instream, includef = ""): + """Translates the contents inside a class definition { } block + + Parameters: + class_name (string): Class name + attributes (dict): Dict where data about the attributes is stored + attrib_doxy (dict): Dict to store doxygen docs associated with the attributes block + objs (dict): Dict to store fist level contained objects with Docxyge docs + defaults (streaM): Stream where the instances of the objects are printed + instream (stream): Input stream of topology2 file we are decoding + includef (string): Include file from where the attributes and objects inline included from + + Returns: + string: The original code that was translated + """ + bsum = 1 + doxy_addition = "" + if includef != "": + doxy_addition = "//! - Included from <" + includef + ">\\n\n" + doxy = "" + raw_code = "" + for line in instream: + raw_code = raw_code + line + if parse_include_str(line): + # Inline files that are included from within a class definition + filename = line[line.find("<") + 1:line.find(">")] + logging.debug("try to inline include \'%s\' from \'%s\'", + filename, os.getcwd()) + # NOTE: The path is relative to when the script exists so + # two levels up and we are at topology2 root + with open("../../" + filename, "r+", encoding="ascii") as ifile: + parse_class_contents(class_name, attributes, attrib_doxy, objs, + defaults, ifile, filename) + continue + if (code := parse_include_by_key(line, instream, sys.stdout)): + raw_code = raw_code + code + continue + if re.search(r"^\s*DefineAttribute\.", line): + doxy = doxy_addition + doxy + raw_code = raw_code + parse_class_attribute(attributes, doxy, instream, line) + doxy = "" + elif re.search(r"^\s*DefineArgument\.", line): + for line in instream: # Just skip, this is only used in bytes.conf + if cbracket_count(line) < 0: + break + elif re.search(r"^\s*attributes\s+\{", line): + doxy = "" # Doxy comments before attributes block end in weird places + raw_code = raw_code + parse_attributes_block(instream, attributes, attrib_doxy) + elif re.search(r"^\s*Object\.", line): + # TODO: Pass collected doxy comments to parse_object and store in objs + doxy = "" + raw_code = raw_code + parse_object(instream, line, file = defaults, + objects = objs, tabs = "\t", ending = ",") + else: # If nothing else matched, assume a default value definition for an attribute + (doxy, line) = doxy_check_add(doxy, line) + tok = line.split() + if len(tok) == 2 and tok[0].isidentifier(): + if doxy != "": + print(doxy, file = defaults) + doxy = "" + val = trim_value(line[line.find(tok[0]) + len(tok[0]):]) + print("\t.%s =\t%s," % (trim_c_id(tok[0]), val), + file = defaults) + bsum = bsum + cbracket_count(line) + if bsum < 1: + break + return raw_code + +def parse_class(instream, fline): + """Parse class definition and print out C struct definition + + Parameters: + fline (string): First input line that was read by the caller + instream (stream): Input stream of topology2 file we are decoding + """ + logging.debug("fline: %s", fline) + tok = fline.split(maxsplit = 2) + cdef = tok[0].split(".") + # base = cdef[1] # Just in case we go back to C++ tralation + class_name = cdef[2] + class_name = trim_c_id(class_name) + attributes = {} + attrib_doxy = {} + defaults = io.StringIO() + objs = {} + raw_code = fline + parse_class_contents(class_name, attributes, attrib_doxy, + objs, defaults, instream) + attribute_block_print(class_name, attributes, attrib_doxy) + attribute_block_info_add(attributes, attrib_doxy) + print("//! \\ref %s_rawcode" % class_name) + print("struct %s {" % class_name) + print_attributes(attributes) + for obj in objs: + if objs[obj]["count"] > 1: + for i in range(objs[obj]["count"]): + print(objs[obj]["doxy"][i]) + print("\tstruct %s %s%d;" % (obj, obj, i)) + else: + print(objs[obj]["doxy"][0]) + print("\tstruct %s %s;" % (obj, obj)) + print("};\n") + print("/*! \\page %s_rawcode The %s class definition in topology2 code\n\t\\code{.unparsed}" % + (class_name, class_name)) + print(raw_code) + print("\t\\endcode\n*/") + print("//! \\var struct %s %s_defaults" % (class_name, class_name)) + print("//! \\brief %s class default values" % class_name) + print("struct %s %s_defaults = {\n" % (class_name, class_name)) + print(defaults.getvalue()) + print("};\n") + defaults.close() + +def parse_members(instream, cbsum, tabs, file): + """Parse attribute initializations from object instantiation + + Parameters: + instream (stream): Input stream of topology2 file we are decoding + cbsum (int): The amount of curly brackets "{" WE HAVE OPEN + tabs (string): Current level of indentation + + Returns: + string: The original code that was translated + """ + doxy = "" + raw_code = "" + for line in instream: + raw_code = raw_code + line + if (code := parse_include_by_key(line, instream, file)): + raw_code = raw_code + code + continue + cbsum = cbsum + cbracket_count(line) + (doxy, line) = doxy_check_add(doxy, line) + # Assume ending } to be alone on its own line + if cbsum < 1: + break + if re.search(r"^\s*Object\.", line): + logging.debug("object-line: %s", line) + obj = line.split(".") + if cbsum == 2: + # Assume Object.Base.name.1 { + doxy = print_doxy(doxy, file = file) + raw_code = raw_code + parse_object(instream, line, file = file, tabs = tabs, ending = ",") + cbsum = 1 + elif cbsum == 1: + # Assume Object.Base.name.1 {} + doxy = print_doxy(doxy, file = file) + print("%s.%s = {}," % (tabs, obj[2]), file = file) + else: + tok = line.split(maxsplit = 1) + if len(tok) >=2: + name = tok[0] + val = trim_value(tok[1]) + doxy = print_doxy(doxy, file = file) + print("%s.%s = %s," % (tabs, name, val), file = file) + return raw_code + +# +def object_instance_prefix(name, ending): + """Decide "struct name name =" or ".name =" based on instantiation ending in ',' or ';' + + Parameters: + name (string): Name of the object instance + ending (string): Either ',' or ';' indication if this is an instance or a definition + + """ + if ending == ";": + return "struct " + name + " " + return "." + +def parse_object(instream, fline, file = sys.stdout, objects = {}, tabs = "", ending = ";"): + """Translates all Object instatiation into initialized C structs + Note that dict arguments in python are passed as reference + + Parameters: + instream (stream): Input stream of topology2 file we are decoding + fline (string): First input line that was read by the caller + file (stream): Where the C struct instance or definition is printed + objects (dict): Dict to store fist level contained objects with Docxyge docs + ending (string): Either ',' or ';' indication if this is an instance or a definition + tabs (string): Current level of indentation + + Returns: + string: The original code that was translated + """ + logging.debug("fline: %s", fline) + tok = fline.split(maxsplit = 2) + obj = tok[0].split(".") + cbsum = cbracket_count(fline) + sbsum = sbracket_count(fline) + name = "" + doxy = "" + raw_code = "" + if len(obj) == 4 and sbsum == 0 and cbsum == 0: + # Assume Object.Base.name.1 { } + name = obj[2] + name = trim_c_id(name) + doxy = print_doxy(doxy, file = file) + prefix = object_instance_prefix(name, ending) + print("%s%s = {}%s" % (prefix, name, ending), file = file) + objects[name] = { "count": 1, "doxy": [doxy] } + elif len(obj) == 4 and sbsum == 0 and cbsum == 1: + # Assume Object.Base.name.1 { + name = obj[2] + name = trim_c_id(name) + doxy = print_doxy(doxy, file = file) + prefix = object_instance_prefix(name, ending) + print("%s%s%s = {" % (tabs, prefix, name), file = file) + raw_code = raw_code + parse_members(instream, cbsum, tabs + "\t", file) + print("%s}%s" % (tabs, ending), file = file) + objects[name] = { "count": 1, "doxy": [doxy] } + elif len(obj) == 3 and sbsum == 1 and cbsum == 0: + # Assume Object.Base.name [ + name = obj[2] + name = trim_c_id(name) + doxy = print_doxy(doxy, file = file) + prefix = object_instance_prefix(name, ending) + print("%s%s%s[] = {" % (tabs, prefix, name), file = file) + objects[name] = { "count": 0, "doxy": [] } + for line in instream: + raw_code = raw_code + line + if parse_include(line): + continue + if (code := parse_include_by_key(line, instream, sys.stdout)): + raw_code = raw_code + code + continue + sbsum = sbsum + sbracket_count(line) + cbsum = cbsum + cbracket_count(line) + (doxy, line) = doxy_check_add(doxy, line) + if sbsum < 1: + print("%s}%s" % (tabs, ending), file = file) + break + if cbsum == 1: # Assume starting { on its own line + objects[name]["count"] = objects[name]["count"] + 1 + objects[name]["doxy"].append(doxy) + doxy = print_doxy(doxy, file = file) + print("%s\t{" % tabs, file = file) + raw_code = raw_code + parse_members(instream, cbsum, tabs + "\t\t", file) + cbsum = 0 + print("%s\t}," % tabs, file = file) + elif len(obj) == 2 and sbsum == 0 and cbsum == 1: + # Assume Object.Base { + for line in instream: + raw_code = raw_code + line + if parse_include(line): + continue + if (code := parse_include_by_key(line, instream, file)): + raw_code = raw_code + code + continue + sbsum = sbsum + sbracket_count(line) + cbsum = cbsum + cbracket_count(line) + (doxy, line) = doxy_check_add(doxy, line) + if cbsum < 1: # Ending } found + break + if sbsum == 1 and cbsum == 1 and sbracket_count(line) > 0: + # Assume Class_name [ + tok = line.split() + name = trim_c_id(tok[0]) + objects[name] = { "count": 0, "doxy": [] } + doxy = print_doxy(doxy, file = file) + prefix = object_instance_prefix(name, ending) + print("%s%s%s[] = {" % (tabs, prefix, name), file = file) + elif sbsum == 1 and cbsum == 2: + # Assume class_name [ \n { \n + objects[name]["count"] = objects[name]["count"] + 1 + objects[name]["doxy"].append(doxy) + doxy = print_doxy(doxy, file = file) + print("%s\t{" % tabs, file = file) + raw_code = raw_code + parse_members(instream, 1, tabs + "\t\t", file) + print("%s\t}," % tabs, file = file) + cbsum = 1 + elif sbsum == 0 and cbsum == 1 and sbracket_count(line) < 0: + # Assume ending ] of class table alone one its own line + print("%s}%s" % (tabs, ending), file = file) + elif sbsum == 0 and cbsum == 1 and line.count("}") == 1: + # Assume name."1" {} + # No init values, so no instantiation code needed, but we still need + # to store the object into objexts dict. + tok = line.split() + tok = tok[0].split(".") + name = trim_c_id(tok[0]) + if not objects.get(name): + objects[name] = { "count": 0, "doxy": [] } + objects[name]["count"] = objects[name]["count"] + 1 + objects[name]["doxy"].append(doxy) + doxy = print_doxy(doxy, file = file) + elif sbsum == 0 and cbsum == 2 and cbracket_count(line) == 1: + # Assume name."1" { + tok = line.split() + tok = tok[0].split(".") + name = trim_c_id(tok[0]) + mname = name + if len(tok) > 1: + idx = tok[1].strip(" \"\'") + if idx.isidentifier() or idx.isnumeric(): + mname = mname + "_" + idx + if not objects.get(name): + objects[name] = { "count": 0, "doxy": [] } + objects[name]["count"] = objects[name]["count"] + 1 + objects[name]["doxy"].append(doxy) + doxy = print_doxy(doxy, file = file) + prefix = object_instance_prefix(name, ending) + print("%s%s%s = {" % (tabs, prefix, mname), file = file) + raw_code = raw_code + parse_members(instream, 1, tabs + "\t", file) + cbsum = 1 + print("%s}%s" % (tabs, ending), file = file) + return raw_code + +def parse_object_and_make_raw_code_page(filename, index, instream, fline): + """Parses an object instance outputs its C equivalent, and creates a raw code page of + of it and prints a reference to it. Handles an "Object.... {}" instance completely + and produces possibly multiple initialized C structs, but always just one raw code + block containing the "Object.... {}" block completely. + + Parameters: + filename (stream): Name of the file we are paring + index (int): The index of the decoded Object block in this file we are handling + instream (stream): Input stream of topology2 file we are decoding + fline (string): First input line that was read by the caller + + """ + tok = filename.split("/") + filename = fname = tok[len(tok)-1] + fname = fname.replace("-", "_") + fname = fname.replace(".", "_") + c_instances = io.StringIO() + raw_code = fline + parse_object(instream, fline, c_instances) + print("/*! \\page %s_%d_rawcode The %s instances #%d in topology2 code\n\t\\code{.unparsed}" % + (fname, index, filename, index)) + print(raw_code) + print("\t\\endcode\n*/") + print("//! \\brief \\ref %s_%d_rawcode" % (fname, index)) + print(c_instances.getvalue()) + c_instances.close() + +# Main starts here, apart from debug file opening +filename = sys.argv[1] +logging.info("file: %s", filename) +with open(filename, "r+", encoding="ascii") as instream: + block_idx = 0 + + shortfname = filename[filename.find("/topology2/"):] + print("//! \\file %s" % shortfname[11:]) + print("//! Source file can be found " + + "<a href=\"https://github.com/thesofproject/sof/tree/main/tools/topology%s\">here</a>." + % shortfname) + for line in instream: + if parse_include(line): + continue + if parse_define_block(line, instream): + continue + if parse_include_by_key(line, instream, sys.stdout): + continue + if re.search(r"^\s*Class\.", line): + parse_class(instream, line) + elif re.search(r"^\s*Object\.", line): + parse_object_and_make_raw_code_page(filename, block_idx, instream, line) + block_idx = block_idx + 1 + elif line.find("##") >= 0: + sys.stdout.write(line.replace("##", "//!", 1)) + else: + sys.stdout.write("\n") diff --git a/tools/topology/topology2/doc/topology2-generate-contents.sh b/tools/topology/topology2/doc/topology2-generate-contents.sh new file mode 100755 index 000000000000..ea5b4ed059cb --- /dev/null +++ b/tools/topology/topology2/doc/topology2-generate-contents.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation. All rights reserved. +# This script generates the contents page and stores it in extra-contents/contents.doxy + +set -e +cd "$(dirname "$0")" + +generate_contents () +{ + cat <<EOF +# This contents list is automatically generated by $0. +/*! \page doc_contents + \section doc_classes Classes +EOF + for ctype in Base Widget Control Dai Pipeline + do + echo " \subsection doc_${ctype,}_classes $ctype Classes" + find .. -name \*.conf -print0 | + xargs -0 awk "/^Class\.$ctype\./ "'{ + split($1, a, "\\."); + name = a[3]; gsub("\"", "", name); gsub("-", "_", name); + print "\t\\li \\ref " name + }' | sort -u + echo + done + + echo '*/' +} + +generate_contents diff --git a/tools/topology/topology2/get_abi.sh b/tools/topology/topology2/get_abi.sh new file mode 100755 index 000000000000..a029846c9ea6 --- /dev/null +++ b/tools/topology/topology2/get_abi.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2019 Intel Corporation. All rights reserved. +set -e + +ABI_MAJOR=$(awk '/^ *# *define *SOF_ABI_MAJOR / { print $3 }' $1/src/include/kernel/abi.h) +ABI_MINOR=$(awk '/^ *# *define *SOF_ABI_MINOR / { print $3 }' $1/src/include/kernel/abi.h) +ABI_PATCH=$(awk '/^ *# *define *SOF_ABI_PATCH / { print $3 }' $1/src/include/kernel/abi.h) + +cat <<EOF_HEADER +Object.Base.manifest.1 { + name "sof_manifest" + Object.Base.data.1 { + name "SOF ABI" +EOF_HEADER + +print_1byte() +{ + printf '0x%02x' "$(("$1" & 0xff))" +} + +print_2bytes() +{ + printf '0x%02x,0x%02x' "$(("$1" & 0xff))" "$((("$1" & 0xff00) >> 8))" +} + +printf '\t\tbytes\t\"' +for vers in $ABI_MAJOR $ABI_MINOR; do + case "$2" in + ipc3) print_1byte "$vers" ;; + ipc4) print_2bytes "$vers" ;; + esac + printf ',' +done + +case "$2" in + ipc3) print_1byte "$ABI_PATCH" ;; + ipc4) print_2bytes "$ABI_PATCH" ;; +esac + +printf '\"\n\t}\n}\n' diff --git a/tools/topology/topology2/imx8-wm8960.conf b/tools/topology/topology2/imx8-wm8960.conf new file mode 100644 index 000000000000..ea6ccf92853b --- /dev/null +++ b/tools/topology/topology2/imx8-wm8960.conf @@ -0,0 +1,127 @@ +## +## Example topology for i.MX8MP board with 'CODEC' codec +## +## (source) host-copier.N.playback -> gain.N.1 -> dai-copier.SAI_DAI_INDEX(sink endpoint) +## + +# Include paths +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/controls> +<searchdir:include/dais> +<searchdir:include/pipelines> + +# Include class definitions +<vendor-token.conf> +<hw_config_simple.conf> +<tokens.conf> +<dai.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<sai.conf> +<manifest.conf> +<route.conf> +<pipeline.conf> +<gain-playback.conf> +<dai-copier.conf> +<host-copier.conf> +<common_definitions.conf> + +Define { + HEADSET_PLAYBACK_PCM_STREAM_NAME "Headset Playback" + HEADSET_PCM_NAME "Headset" + HEADSET_PCM_ID 0 +} + +# +# Pipeline definitions +# +# (source) host.N.playback -> gain.N.1 +# +Object.Pipeline { + gain-playback [ + { + index 1 + + Object.Widget.host-copier.1 { + stream_name $HEADSET_PLAYBACK_PCM_STREAM_NAME + pcm_id $HEADSET_PCM_ID + } + + Object.Widget.gain.1 { + curve_type "windows_fade" + Object.Control.mixer.1 { + name 'Playback Volume' + } + } + + time_domain "dma" + format "s32le" + num_input_audio_formats 3 + num_output_audio_formats 1 + } + ] +} + +Object.Widget { + dai-copier."1" { + dai_index $SAI_DAI_INDEX + dai_type "SAI" + copier_type "SAI" + stream_name $STREAM_CODEC_NAME + node_type $I2S_LINK_OUTPUT_CLASS + type dai_in + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + direction "playback" + + # 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 + } + ] + } +} + +# PCM Definitions +Object.PCM.pcm [ + { + name $HEADSET_PCM_NAME + direction "playback" + id $HEADSET_PCM_ID + + Object.Base.fe_dai.1 { + name "$HEADSET_PCM_NAME" + } + + Object.PCM.pcm_caps.playback { + name $HEADSET_PLAYBACK_PCM_STREAM_NAME + formats 'S32_LE,S24_LE,S16_LE' + } + } +] + +# Top-level pipeline connection +# gain.1. -> dai.SAI.1.playback +Object.Base.route [ + { + source "host-copier.$HEADSET_PCM_ID.playback" + sink "gain.1.1" + } + { + source "gain.1.1" + sink "dai-copier.SAI.$STREAM_CODEC_NAME.playback" + } +] diff --git a/tools/topology/topology2/include/bench/aria_controls_capture.conf b/tools/topology/topology2/include/bench/aria_controls_capture.conf new file mode 100644 index 000000000000..1b064a64667c --- /dev/null +++ b/tools/topology/topology2/include/bench/aria_controls_capture.conf @@ -0,0 +1,19 @@ + # Created initially with script "./bench_comp_generate.sh aria" + # may need edits to modify controls + Object.Control { + bytes."1" { + name '$ANALOG_CAPTURE_PCM ARIA bytes' + IncludeByKey.BENCH_ARIA_PARAMS { + "passthrough" "include/components/aria/passthrough.conf" + "param_1" "include/components/aria/param_1.conf" + "param_2" "include/components/aria/param_2.conf" + "param_3" "include/components/aria/param_3.conf" + } + } + #mixer."1" { + # name '$ANALOG_CAPTURE_PCM ARIA switch or volume' + #} + #enum."1" { + # name '$ANALOG_CAPTURE_PCM ARIA enum' + #} + } diff --git a/tools/topology/topology2/include/bench/aria_controls_playback.conf b/tools/topology/topology2/include/bench/aria_controls_playback.conf new file mode 100644 index 000000000000..809e4a65c530 --- /dev/null +++ b/tools/topology/topology2/include/bench/aria_controls_playback.conf @@ -0,0 +1,19 @@ + # Created initially with script "./bench_comp_generate.sh aria" + # may need edits to modify controls + Object.Control { + bytes."1" { + name '$ANALOG_PLAYBACK_PCM ARIA bytes' + IncludeByKey.BENCH_ARIA_PARAMS { + "passthrough" "include/components/aria/passthrough.conf" + "param_1" "include/components/aria/param_1.conf" + "param_2" "include/components/aria/param_2.conf" + "param_3" "include/components/aria/param_3.conf" + } + } + #mixer."1" { + # name '$ANALOG_PLAYBACK_PCM ARIA switch or volume' + #} + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM ARIA enum' + #} + } diff --git a/tools/topology/topology2/include/bench/aria_route.conf b/tools/topology/topology2/include/bench/aria_route.conf new file mode 100644 index 000000000000..441523691a51 --- /dev/null +++ b/tools/topology/topology2/include/bench/aria_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh aria" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'aria.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'aria.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'aria.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'aria.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/aria_s24.conf b/tools/topology/topology2/include/bench/aria_s24.conf new file mode 100644 index 000000000000..eaaa34b18bf3 --- /dev/null +++ b/tools/topology/topology2/include/bench/aria_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh aria" + Object.Widget.aria.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/aria_controls_playback.conf> + } + Object.Widget.aria.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/aria_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/aria_route.conf> diff --git a/tools/topology/topology2/include/bench/asrc_route.conf b/tools/topology/topology2/include/bench/asrc_route.conf new file mode 100644 index 000000000000..24985bff6176 --- /dev/null +++ b/tools/topology/topology2/include/bench/asrc_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh asrc" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'asrc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'asrc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'asrc.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'asrc.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/asrc_s16.conf b/tools/topology/topology2/include/bench/asrc_s16.conf new file mode 100644 index 000000000000..a87d2a601c71 --- /dev/null +++ b/tools/topology/topology2/include/bench/asrc_s16.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh asrc" + # Edited/added: + # - operation mode 1 for push for playback, 2 for pull for playback + # - rate_out 48000 for the fixed playback sink rate + # - rate_out 0 for the capture PCM defined sink rate + Object.Widget.asrc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + operation_mode 1 + rate_out 48000 + <include/components/src_format_s16_convert_to_48k.conf> + } + Object.Widget.asrc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + operation_mode 2 + rate_out 0 + <include/components/src_format_s16_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s16.conf> + <include/bench/asrc_route.conf> diff --git a/tools/topology/topology2/include/bench/asrc_s24.conf b/tools/topology/topology2/include/bench/asrc_s24.conf new file mode 100644 index 000000000000..ef06b0e8e10b --- /dev/null +++ b/tools/topology/topology2/include/bench/asrc_s24.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh asrc" + # Edited/added: + # - operation mode 1 for push for playback, 2 for pull for playback + # - rate_out 48000 for the fixed playback sink rate + # - rate_out 0 for the capture PCM defined sink rate + Object.Widget.asrc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + operation_mode 1 + rate_out 48000 + <include/components/src_format_s24_convert_to_48k.conf> + } + Object.Widget.asrc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + operation_mode 2 + rate_out 0 + <include/components/src_format_s24_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s24.conf> + <include/bench/asrc_route.conf> diff --git a/tools/topology/topology2/include/bench/asrc_s32.conf b/tools/topology/topology2/include/bench/asrc_s32.conf new file mode 100644 index 000000000000..9671f717a3d9 --- /dev/null +++ b/tools/topology/topology2/include/bench/asrc_s32.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh asrc" + # Edited/added: + # - operation mode 1 for push for playback, 2 for pull for playback + # - rate_out 48000 for the fixed playback sink rate + # - rate_out 0 for the capture PCM defined sink rate + Object.Widget.asrc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + operation_mode 1 + rate_out 48000 + <include/components/src_format_s32_convert_to_48k.conf> + } + Object.Widget.asrc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + operation_mode 2 + rate_out 0 + <include/components/src_format_s32_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s32.conf> + <include/bench/asrc_route.conf> diff --git a/tools/topology/topology2/include/bench/bench_comp_generate.sh b/tools/topology/topology2/include/bench/bench_comp_generate.sh new file mode 100755 index 000000000000..3a9c5aa9c229 --- /dev/null +++ b/tools/topology/topology2/include/bench/bench_comp_generate.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation. All rights reserved. + +set -e + +main () { + if [ "$#" -ne 1 ]; then + echo "Usage: $0 <component>" + exit 1 + fi + comp=$1 + FULL_CMD=( "$0" "$@" ) + generate_comp "s16" + generate_comp "s24" + generate_comp "s32" + generate_route + generate_playback_controls + generate_capture_controls +} + +generate_comp () +{ + format=$1 + fn=${comp}_${format}.conf + echo Creating file "$fn" + cat > "$fn" <<EOF_COMP + # Created with script "${FULL_CMD[@]}" + Object.Widget.${comp}.1 { + index \$BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_${format}.conf> + <include/bench/${comp}_controls_playback.conf> + } + Object.Widget.${comp}.2 { + index \$BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_${format}.conf> + <include/bench/${comp}_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_${format}.conf> + <include/bench/${comp}_route.conf> +EOF_COMP +} + +generate_route () +{ + fn=${comp}_route.conf + echo Creating file "$fn" + cat > "$fn" <<EOF_ROUTE + # Created with script "${FULL_CMD[@]}" + Object.Base.route [ + { + sink '\$BENCH_PLAYBACK_DAI_COPIER' + source '${comp}.\$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink '${comp}.\$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '\$BENCH_CAPTURE_DAI_COPIER' + sink '${comp}.\$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source '${comp}.\$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] +EOF_ROUTE +} + +generate_playback_controls () +{ + fn=${comp}_controls_playback.conf + echo Creating file "$fn" + cat > "$fn" <<EOF_PLAYBACK_BYTES + # Created initially with script "${FULL_CMD[@]}" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in ${comp^^} + #bytes."1" { + # name '\$ANALOG_PLAYBACK_PCM ${comp^^} bytes' + # IncludeByKey.BENCH_${comp^^}_PARAMS { + # "default" "include/components/${comp}/default.conf" + # } + #} + #mixer."1" { + # name '\$ANALOG_PLAYBACK_PCM ${comp^^} switch or volume' + #} + #enum."1" { + # name '\$ANALOG_PLAYBACK_PCM ${comp^^} enum' + #} + } +EOF_PLAYBACK_BYTES +} + +generate_capture_controls () +{ + fn=${comp}_controls_capture.conf + echo Creating file "$fn" + cat > "$fn" <<EOF_CAPTURE_BYTES + # Created initially with script "${FULL_CMD[@]}" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in ${comp^^} + #bytes."1" { + # name '\$ANALOG_CAPTURE_PCM ${comp^^} bytes' + # IncludeByKey.BENCH_${comp^^}_PARAMS { + # "default" "include/components/${comp}/default.conf" + # } + #} + #mixer."1" { + # name '\$ANALOG_CAPTURE_PCM ${comp^^} switch or volume' + #} + #enum."1" { + # name '\$ANALOG_CAPTURE_PCM ${comp^^} enum' + #} + } +EOF_CAPTURE_BYTES +} + +main "$@" diff --git a/tools/topology/topology2/include/bench/dcblock_control_bytes_capture.conf b/tools/topology/topology2/include/bench/dcblock_control_bytes_capture.conf new file mode 100644 index 000000000000..3d39d5cc8874 --- /dev/null +++ b/tools/topology/topology2/include/bench/dcblock_control_bytes_capture.conf @@ -0,0 +1,8 @@ + # Created initially with script "./bench_comp_generate.sh dcblock" + # may need edits to modify controls + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM DCBLOCK bytes' + IncludeByKey.BENCH_DCBLOCK_PARAMS { + "default" "include/components/dcblock/default.conf" + } + } diff --git a/tools/topology/topology2/include/bench/dcblock_control_bytes_playback.conf b/tools/topology/topology2/include/bench/dcblock_control_bytes_playback.conf new file mode 100644 index 000000000000..09885bcf561f --- /dev/null +++ b/tools/topology/topology2/include/bench/dcblock_control_bytes_playback.conf @@ -0,0 +1,8 @@ + # Created initially with script "./bench_comp_generate.sh dcblock" + # may need edits to modify controls + Object.Control.bytes."1" { + name '$ANALOG_PLAYBACK_PCM DCBLOCK bytes' + IncludeByKey.BENCH_DCBLOCK_PARAMS { + "default" "include/components/dcblock/default.conf" + } + } diff --git a/tools/topology/topology2/include/bench/dcblock_route.conf b/tools/topology/topology2/include/bench/dcblock_route.conf new file mode 100644 index 000000000000..16a1674cbf53 --- /dev/null +++ b/tools/topology/topology2/include/bench/dcblock_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh dcblock" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'dcblock.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'dcblock.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'dcblock.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'dcblock.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/dcblock_s16.conf b/tools/topology/topology2/include/bench/dcblock_s16.conf new file mode 100644 index 000000000000..6e825a2a03ac --- /dev/null +++ b/tools/topology/topology2/include/bench/dcblock_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh dcblock" + Object.Widget.dcblock.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/dcblock_control_bytes_playback.conf> + } + Object.Widget.dcblock.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/dcblock_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/dcblock_route.conf> diff --git a/tools/topology/topology2/include/bench/dcblock_s24.conf b/tools/topology/topology2/include/bench/dcblock_s24.conf new file mode 100644 index 000000000000..7f8d04082a03 --- /dev/null +++ b/tools/topology/topology2/include/bench/dcblock_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh dcblock" + Object.Widget.dcblock.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/dcblock_control_bytes_playback.conf> + } + Object.Widget.dcblock.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/dcblock_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/dcblock_route.conf> diff --git a/tools/topology/topology2/include/bench/dcblock_s32.conf b/tools/topology/topology2/include/bench/dcblock_s32.conf new file mode 100644 index 000000000000..8b2996a981cf --- /dev/null +++ b/tools/topology/topology2/include/bench/dcblock_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh dcblock" + Object.Widget.dcblock.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/dcblock_control_bytes_playback.conf> + } + Object.Widget.dcblock.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/dcblock_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/dcblock_route.conf> diff --git a/tools/topology/topology2/include/bench/dolby-dax_controls_capture.conf b/tools/topology/topology2/include/bench/dolby-dax_controls_capture.conf new file mode 100644 index 000000000000..dde79828ea06 --- /dev/null +++ b/tools/topology/topology2/include/bench/dolby-dax_controls_capture.conf @@ -0,0 +1,28 @@ + # Created initially with script "./bench_comp_generate.sh dolby-dax" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in DOLBY-DAX + mixer."1" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Switch' + } + mixer."2" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Switch CP' + } + mixer."3" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Switch CTC' + } + mixer."4" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Volume' + } + enum."1" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Profile' + } + enum."2" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Device' + } + bytes."1" { + name 'DAX $ANALOG_CAPTURE_PCM Playback Tuning' + max 8192 + <include/components/dax/default.conf> + } + } diff --git a/tools/topology/topology2/include/bench/dolby-dax_controls_playback.conf b/tools/topology/topology2/include/bench/dolby-dax_controls_playback.conf new file mode 100644 index 000000000000..9c56043a2ed0 --- /dev/null +++ b/tools/topology/topology2/include/bench/dolby-dax_controls_playback.conf @@ -0,0 +1,28 @@ + # Created initially with script "./bench_comp_generate.sh dolby-dax" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in DOLBY-DAX + mixer."1" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Switch' + } + mixer."2" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Switch CP' + } + mixer."3" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Switch CTC' + } + mixer."4" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Volume' + } + enum."1" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Profile' + } + enum."2" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Device' + } + bytes."1" { + name 'DAX $ANALOG_PLAYBACK_PCM Playback Tuning' + max 8192 + <include/components/dax/default.conf> + } + } diff --git a/tools/topology/topology2/include/bench/dolby-dax_route.conf b/tools/topology/topology2/include/bench/dolby-dax_route.conf new file mode 100644 index 000000000000..1f5e0dc0dc80 --- /dev/null +++ b/tools/topology/topology2/include/bench/dolby-dax_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh dolby-dax" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'dolby-dax.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'dolby-dax.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'dolby-dax.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'dolby-dax.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/dolby-dax_s16.conf b/tools/topology/topology2/include/bench/dolby-dax_s16.conf new file mode 100644 index 000000000000..a4f622cebad3 --- /dev/null +++ b/tools/topology/topology2/include/bench/dolby-dax_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh dolby-dax" + Object.Widget.dolby-dax.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/dolby-dax_controls_playback.conf> + } + Object.Widget.dolby-dax.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/dolby-dax_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/dolby-dax_route.conf> diff --git a/tools/topology/topology2/include/bench/dolby-dax_s24.conf b/tools/topology/topology2/include/bench/dolby-dax_s24.conf new file mode 100644 index 000000000000..b74c5d32af75 --- /dev/null +++ b/tools/topology/topology2/include/bench/dolby-dax_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh dolby-dax" + Object.Widget.dolby-dax.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/dolby-dax_controls_playback.conf> + } + Object.Widget.dolby-dax.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/dolby-dax_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/dolby-dax_route.conf> diff --git a/tools/topology/topology2/include/bench/dolby-dax_s32.conf b/tools/topology/topology2/include/bench/dolby-dax_s32.conf new file mode 100644 index 000000000000..b239e4d5dab6 --- /dev/null +++ b/tools/topology/topology2/include/bench/dolby-dax_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh dolby-dax" + Object.Widget.dolby-dax.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/dolby-dax_controls_playback.conf> + } + Object.Widget.dolby-dax.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/dolby-dax_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/dolby-dax_route.conf> diff --git a/tools/topology/topology2/include/bench/drc_controls_capture.conf b/tools/topology/topology2/include/bench/drc_controls_capture.conf new file mode 100644 index 000000000000..42d8044a6398 --- /dev/null +++ b/tools/topology/topology2/include/bench/drc_controls_capture.conf @@ -0,0 +1,20 @@ + # Created initially with script "./bench_comp_generate.sh drc" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in DRC + bytes."1" { + name '$ANALOG_CAPTURE_PCM DRC bytes' + IncludeByKey.BENCH_DRC_PARAMS { + "default" "include/components/drc/default.conf" + "enabled" "include/components/drc/enabled.conf" + "passthrough" "include/components/drc/passthrough.conf" + "default_speaker_mic" "include/components/drc/dmic_default.conf" + } + } + mixer."1" { + name '$ANALOG_CAPTURE_PCM DRC switch' + } + #enum."1" { + # name '$ANALOG_CAPTURE_PCM DRC enum' + #} + } diff --git a/tools/topology/topology2/include/bench/drc_controls_playback.conf b/tools/topology/topology2/include/bench/drc_controls_playback.conf new file mode 100644 index 000000000000..2cab24d5325d --- /dev/null +++ b/tools/topology/topology2/include/bench/drc_controls_playback.conf @@ -0,0 +1,20 @@ + # Created initially with script "./bench_comp_generate.sh drc" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in DRC + bytes."1" { + name '$ANALOG_PLAYBACK_PCM DRC bytes' + IncludeByKey.BENCH_DRC_PARAMS { + "default" "include/components/drc/default.conf" + "enabled" "include/components/drc/enabled.conf" + "passthrough" "include/components/drc/passthrough.conf" + "default_speaker_mic" "include/components/drc/speaker_default.conf" + } + } + mixer."1" { + name '$ANALOG_PLAYBACK_PCM DRC switch' + } + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM DRC enum' + #} + } diff --git a/tools/topology/topology2/include/bench/drc_route.conf b/tools/topology/topology2/include/bench/drc_route.conf new file mode 100644 index 000000000000..7814bbd3c663 --- /dev/null +++ b/tools/topology/topology2/include/bench/drc_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh drc" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'drc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'drc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'drc.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'drc.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/drc_s16.conf b/tools/topology/topology2/include/bench/drc_s16.conf new file mode 100644 index 000000000000..cce34d391e14 --- /dev/null +++ b/tools/topology/topology2/include/bench/drc_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh drc" + Object.Widget.drc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/drc_controls_playback.conf> + } + Object.Widget.drc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/drc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/drc_route.conf> diff --git a/tools/topology/topology2/include/bench/drc_s24.conf b/tools/topology/topology2/include/bench/drc_s24.conf new file mode 100644 index 000000000000..325916d4bd34 --- /dev/null +++ b/tools/topology/topology2/include/bench/drc_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh drc" + Object.Widget.drc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/drc_controls_playback.conf> + } + Object.Widget.drc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/drc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/drc_route.conf> diff --git a/tools/topology/topology2/include/bench/drc_s32.conf b/tools/topology/topology2/include/bench/drc_s32.conf new file mode 100644 index 000000000000..3c1cedddf439 --- /dev/null +++ b/tools/topology/topology2/include/bench/drc_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh drc" + Object.Widget.drc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/drc_controls_playback.conf> + } + Object.Widget.drc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/drc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/drc_route.conf> diff --git a/tools/topology/topology2/include/bench/eqfir_control_bytes_capture.conf b/tools/topology/topology2/include/bench/eqfir_control_bytes_capture.conf new file mode 100644 index 000000000000..ecde34e399e2 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqfir_control_bytes_capture.conf @@ -0,0 +1,12 @@ + # Created initially with script "./bench_comp_generate.sh eqfir" + # may need edits to modify controls + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM EQFIR bytes' + IncludeByKey.BENCH_EQFIR_PARAMS { + "default" "include/components/eqfir/passthrough.conf" + "flat" "include/components/eqfir/flat.conf" + "loudness" "include/components/eqfir/loudness.conf" + "midboost" "include/components/eqfir/midboost.conf" + "passthrough" "include/components/eqfir/passthrough.conf" + } + } diff --git a/tools/topology/topology2/include/bench/eqfir_control_bytes_playback.conf b/tools/topology/topology2/include/bench/eqfir_control_bytes_playback.conf new file mode 100644 index 000000000000..d65fd4606b7b --- /dev/null +++ b/tools/topology/topology2/include/bench/eqfir_control_bytes_playback.conf @@ -0,0 +1,12 @@ + # Created initially with script "./bench_comp_generate.sh eqfir" + # may need edits to modify controls + Object.Control.bytes."1" { + name '$ANALOG_PLAYBACK_PCM EQFIR bytes' + IncludeByKey.BENCH_EQFIR_PARAMS { + "default" "include/components/eqfir/passthrough.conf" + "flat" "include/components/eqfir/flat.conf" + "loudness" "include/components/eqfir/loudness.conf" + "midboost" "include/components/eqfir/midboost.conf" + "passthrough" "include/components/eqfir/passthrough.conf" + } + } diff --git a/tools/topology/topology2/include/bench/eqfir_route.conf b/tools/topology/topology2/include/bench/eqfir_route.conf new file mode 100644 index 000000000000..345eb6f7e803 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqfir_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh eqfir" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'eqfir.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'eqfir.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'eqfir.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'eqfir.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/eqfir_s16.conf b/tools/topology/topology2/include/bench/eqfir_s16.conf new file mode 100644 index 000000000000..06c60c2e6541 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqfir_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh eqfir" + Object.Widget.eqfir.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/eqfir_control_bytes_playback.conf> + } + Object.Widget.eqfir.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/eqfir_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/eqfir_route.conf> diff --git a/tools/topology/topology2/include/bench/eqfir_s24.conf b/tools/topology/topology2/include/bench/eqfir_s24.conf new file mode 100644 index 000000000000..c90264d29607 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqfir_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh eqfir" + Object.Widget.eqfir.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/eqfir_control_bytes_playback.conf> + } + Object.Widget.eqfir.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/eqfir_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/eqfir_route.conf> diff --git a/tools/topology/topology2/include/bench/eqfir_s32.conf b/tools/topology/topology2/include/bench/eqfir_s32.conf new file mode 100644 index 000000000000..2ad841cda0f5 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqfir_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh eqfir" + Object.Widget.eqfir.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/eqfir_control_bytes_playback.conf> + } + Object.Widget.eqfir.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/eqfir_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/eqfir_route.conf> diff --git a/tools/topology/topology2/include/bench/eqiir_control_bytes_capture.conf b/tools/topology/topology2/include/bench/eqiir_control_bytes_capture.conf new file mode 100644 index 000000000000..f5f0b4ba968f --- /dev/null +++ b/tools/topology/topology2/include/bench/eqiir_control_bytes_capture.conf @@ -0,0 +1,16 @@ + # Created initially with script "./bench_comp_generate.sh eqiir" + # may need edits to modify controls + Object.Control.bytes."1" { + name '$ANALOG_CAPTURE_PCM EQIIR bytes' + IncludeByKey.BENCH_EQIIR_PARAMS { + "default" "include/components/eqiir/passthrough.conf" + "bandpass" "include/components/eqiir/bandpass.conf" + "bassboost" "include/components/eqiir/bassboost.conf" + "flat" "include/components/eqiir/flat.conf" + "loudness" "include/components/eqiir/loudness.conf" + "passthrough" "include/components/eqiir/passthrough.conf" + "highpass_20hz_0db_48khz" "include/components/eqiir/highpass_20hz_0db_48khz.conf" + "highpass_50hz_0db_48khz" "include/components/eqiir/highpass_50hz_0db_48khz.conf" + "highpass_100hz_0db_48khz" "include/components/eqiir/highpass_100hz_0db_48khz.conf" + } + } diff --git a/tools/topology/topology2/include/bench/eqiir_control_bytes_playback.conf b/tools/topology/topology2/include/bench/eqiir_control_bytes_playback.conf new file mode 100644 index 000000000000..8164586ae8aa --- /dev/null +++ b/tools/topology/topology2/include/bench/eqiir_control_bytes_playback.conf @@ -0,0 +1,16 @@ + # Created initially with script "./bench_comp_generate.sh eqiir" + # may need edits to modify controls + Object.Control.bytes."1" { + name '$ANALOG_PLAYBACK_PCM EQIIR bytes' + IncludeByKey.BENCH_EQIIR_PARAMS { + "default" "include/components/eqiir/passthrough.conf" + "bandpass" "include/components/eqiir/bandpass.conf" + "bassboost" "include/components/eqiir/bassboost.conf" + "flat" "include/components/eqiir/flat.conf" + "loudness" "include/components/eqiir/loudness.conf" + "passthrough" "include/components/eqiir/passthrough.conf" + "highpass_20hz_0db_48khz" "include/components/eqiir/highpass_20hz_0db_48khz.conf" + "highpass_50hz_0db_48khz" "include/components/eqiir/highpass_50hz_0db_48khz.conf" + "highpass_100hz_0db_48khz" "include/components/eqiir/highpass_100hz_0db_48khz.conf" + } + } diff --git a/tools/topology/topology2/include/bench/eqiir_route.conf b/tools/topology/topology2/include/bench/eqiir_route.conf new file mode 100644 index 000000000000..c08418ff51da --- /dev/null +++ b/tools/topology/topology2/include/bench/eqiir_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh eqiir" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'eqiir.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'eqiir.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'eqiir.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'eqiir.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/eqiir_s16.conf b/tools/topology/topology2/include/bench/eqiir_s16.conf new file mode 100644 index 000000000000..a343fdae4d0d --- /dev/null +++ b/tools/topology/topology2/include/bench/eqiir_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh eqiir" + Object.Widget.eqiir.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/eqiir_control_bytes_playback.conf> + } + Object.Widget.eqiir.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/eqiir_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/eqiir_route.conf> diff --git a/tools/topology/topology2/include/bench/eqiir_s24.conf b/tools/topology/topology2/include/bench/eqiir_s24.conf new file mode 100644 index 000000000000..00eb91a9c426 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqiir_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh eqiir" + Object.Widget.eqiir.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/eqiir_control_bytes_playback.conf> + } + Object.Widget.eqiir.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/eqiir_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/eqiir_route.conf> diff --git a/tools/topology/topology2/include/bench/eqiir_s32.conf b/tools/topology/topology2/include/bench/eqiir_s32.conf new file mode 100644 index 000000000000..9e6d19bcecb0 --- /dev/null +++ b/tools/topology/topology2/include/bench/eqiir_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh eqiir" + Object.Widget.eqiir.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/eqiir_control_bytes_playback.conf> + } + Object.Widget.eqiir.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/eqiir_control_bytes_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/eqiir_route.conf> diff --git a/tools/topology/topology2/include/bench/gain_controls_capture.conf b/tools/topology/topology2/include/bench/gain_controls_capture.conf new file mode 100644 index 000000000000..421223b2a58c --- /dev/null +++ b/tools/topology/topology2/include/bench/gain_controls_capture.conf @@ -0,0 +1,16 @@ + # Created initially with script "./bench_comp_generate.sh gain" + # may need edits to modify controls + Object.Control { + #bytes."1" { + # name '$ANALOG_CAPTURE_PCM GAIN bytes' + # IncludeByKey.BENCH_GAIN_PARAMS { + # "default" "include/components/gain/default.conf" + # } + #} + mixer."1" { + name '$ANALOG_CAPTURE_PCM GAIN volume' + } + #enum."1" { + # name '$ANALOG_CAPTURE_PCM GAIN enum' + #} + } diff --git a/tools/topology/topology2/include/bench/gain_controls_playback.conf b/tools/topology/topology2/include/bench/gain_controls_playback.conf new file mode 100644 index 000000000000..95f034a4cd52 --- /dev/null +++ b/tools/topology/topology2/include/bench/gain_controls_playback.conf @@ -0,0 +1,16 @@ + # Created initially with script "./bench_comp_generate.sh gain" + # may need edits to modify controls + Object.Control { + #bytes."1" { + # name '$ANALOG_PLAYBACK_PCM GAIN bytes' + # IncludeByKey.BENCH_GAIN_PARAMS { + # "default" "include/components/gain/default.conf" + # } + #} + mixer."1" { + name '$ANALOG_PLAYBACK_PCM GAIN volume' + } + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM GAIN enum' + #} + } diff --git a/tools/topology/topology2/include/bench/gain_route.conf b/tools/topology/topology2/include/bench/gain_route.conf new file mode 100644 index 000000000000..6c22cb63fbfb --- /dev/null +++ b/tools/topology/topology2/include/bench/gain_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh gain" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'gain.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'gain.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'gain.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'gain.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/gain_s16.conf b/tools/topology/topology2/include/bench/gain_s16.conf new file mode 100644 index 000000000000..0d736ece9d9e --- /dev/null +++ b/tools/topology/topology2/include/bench/gain_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh gain" + Object.Widget.gain.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/gain_controls_playback.conf> + } + Object.Widget.gain.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/gain_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/gain_route.conf> diff --git a/tools/topology/topology2/include/bench/gain_s24.conf b/tools/topology/topology2/include/bench/gain_s24.conf new file mode 100644 index 000000000000..cd2d1809aea1 --- /dev/null +++ b/tools/topology/topology2/include/bench/gain_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh gain" + Object.Widget.gain.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/gain_controls_playback.conf> + } + Object.Widget.gain.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/gain_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/gain_route.conf> diff --git a/tools/topology/topology2/include/bench/gain_s32.conf b/tools/topology/topology2/include/bench/gain_s32.conf new file mode 100644 index 000000000000..afac93e97f1b --- /dev/null +++ b/tools/topology/topology2/include/bench/gain_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh gain" + Object.Widget.gain.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/gain_controls_playback.conf> + } + Object.Widget.gain.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/gain_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/gain_route.conf> diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_multich_s32.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_multich_s32.conf new file mode 100644 index 000000000000..95c57c8a48af --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_multich_s32.conf @@ -0,0 +1,438 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 21 + num_output_audio_formats 7 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_output_audio_formats 21 + num_input_audio_formats 7 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + } + + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + } + + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_s16.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_s16.conf new file mode 100644 index 000000000000..317c42ce824b --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_s16.conf @@ -0,0 +1,66 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + 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 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + 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 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_s16_16k.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_s16_16k.conf new file mode 100644 index 000000000000..483a087a885f --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_s16_16k.conf @@ -0,0 +1,74 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + 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 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_rate 16000 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_rate 16000 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_rate 16000 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_s24.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_s24.conf new file mode 100644 index 000000000000..4f2a17a5f0e5 --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_s24.conf @@ -0,0 +1,66 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + 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 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + 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 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_s24_16k.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_s24_16k.conf new file mode 100644 index 000000000000..4fc5b1eaf715 --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_s24_16k.conf @@ -0,0 +1,74 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + 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 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_rate 16000 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_rate 16000 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_rate 16000 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_s32.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_s32.conf new file mode 100644 index 000000000000..4ee80bf7c0a9 --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_s32.conf @@ -0,0 +1,66 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + 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 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + 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 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_s32_16k.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_s32_16k.conf new file mode 100644 index 000000000000..229e686feeba --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_s32_16k.conf @@ -0,0 +1,74 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + 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 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_rate 16000 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_rate 16000 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s16.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s16.conf new file mode 100644 index 000000000000..88526649833e --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s16.conf @@ -0,0 +1,24 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + <include/components/src_format_sxx_to_s16_convert.conf> + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + <include/components/src_format_s16_to_sxx_convert.conf> + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s24.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s24.conf new file mode 100644 index 000000000000..c8b259281c4e --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s24.conf @@ -0,0 +1,24 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + <include/components/src_format_sxx_to_s24_convert.conf> + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + <include/components/src_format_s24_to_sxx_convert.conf> + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s32.conf b/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s32.conf new file mode 100644 index 000000000000..bd6c82c6b479 --- /dev/null +++ b/tools/topology/topology2/include/bench/host_gateway_pipelines_src_s32.conf @@ -0,0 +1,24 @@ + Object.Pipeline { + host-gateway-playback [ + { + index $BENCH_PLAYBACK_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 + <include/components/src_format_sxx_to_s32_convert.conf> + } + } + ] + + host-gateway-capture [ + { + index $BENCH_CAPTURE_HOST_PIPELINE + Object.Widget.host-copier.1 { + stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 + <include/components/src_format_s32_to_sxx_convert.conf> + } + } + ] + } + diff --git a/tools/topology/topology2/include/bench/igo_nr_controls_capture.conf b/tools/topology/topology2/include/bench/igo_nr_controls_capture.conf new file mode 100644 index 000000000000..a2006c17a9d7 --- /dev/null +++ b/tools/topology/topology2/include/bench/igo_nr_controls_capture.conf @@ -0,0 +1,43 @@ + # Created initially with script "./bench_comp_generate.sh igo_nr" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in IGO_NR + bytes."1" { + name '$ANALOG_CAPTURE_PCM IGO_NR bytes' + Object.Base.data.1 { + # Data is ipc4 header modified copy from + # tools/topology/topology1/sof/pipe-igonr-capture.m4 + bytes "0x53,0x4f,0x46,0x34, + 0x00,0x00,0x00,0x00, + 0x44,0x00,0x00,0x00, + 0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x3d,0x00,0x00,0x00, + 0x09,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x20,0x00,0x00, + 0x34,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00" + } + } + mixer."1" { + name '$ANALOG_CAPTURE_PCM IGO_NR enable' + } + #enum."1" { + # name '$ANALOG_CAPTURE_PCM IGO_NR enum' + #} + } diff --git a/tools/topology/topology2/include/bench/igo_nr_controls_playback.conf b/tools/topology/topology2/include/bench/igo_nr_controls_playback.conf new file mode 100644 index 000000000000..184593f8e5df --- /dev/null +++ b/tools/topology/topology2/include/bench/igo_nr_controls_playback.conf @@ -0,0 +1,43 @@ + # Created initially with script "./bench_comp_generate.sh igo_nr" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in IGO_NR + bytes."1" { + name '$ANALOG_PLAYBACK_PCM IGO_NR bytes' + Object.Base.data.1 { + # Data is ipc4 header modified copy from + # tools/topology/topology1/sof/pipe-igonr-capture.m4 + bytes "0x53,0x4f,0x46,0x34, + 0x00,0x00,0x00,0x00, + 0x44,0x00,0x00,0x00, + 0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00, + 0x3d,0x00,0x00,0x00, + 0x09,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x20,0x00,0x00, + 0x34,0x03,0x00,0x00, + 0x00,0x00,0x00,0x00" + } + } + mixer."1" { + name '$ANALOG_PLAYBACK_PCM IGO_NR enable' + } + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM IGO_NR enum' + #} + } diff --git a/tools/topology/topology2/include/bench/igo_nr_route.conf b/tools/topology/topology2/include/bench/igo_nr_route.conf new file mode 100644 index 000000000000..be977194fe9e --- /dev/null +++ b/tools/topology/topology2/include/bench/igo_nr_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh igo_nr" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'igo_nr.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'igo_nr.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'igo_nr.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'igo_nr.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/igo_nr_s16.conf b/tools/topology/topology2/include/bench/igo_nr_s16.conf new file mode 100644 index 000000000000..6704a9803abc --- /dev/null +++ b/tools/topology/topology2/include/bench/igo_nr_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh igo_nr" + Object.Widget.igo_nr.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/igo_nr_controls_playback.conf> + } + Object.Widget.igo_nr.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/igo_nr_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/igo_nr_route.conf> diff --git a/tools/topology/topology2/include/bench/igo_nr_s24.conf b/tools/topology/topology2/include/bench/igo_nr_s24.conf new file mode 100644 index 000000000000..84ef21346784 --- /dev/null +++ b/tools/topology/topology2/include/bench/igo_nr_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh igo_nr" + Object.Widget.igo_nr.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/igo_nr_controls_playback.conf> + } + Object.Widget.igo_nr.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/igo_nr_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/igo_nr_route.conf> diff --git a/tools/topology/topology2/include/bench/igo_nr_s32.conf b/tools/topology/topology2/include/bench/igo_nr_s32.conf new file mode 100644 index 000000000000..5582b7349462 --- /dev/null +++ b/tools/topology/topology2/include/bench/igo_nr_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh igo_nr" + Object.Widget.igo_nr.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/igo_nr_controls_playback.conf> + } + Object.Widget.igo_nr.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/igo_nr_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/igo_nr_route.conf> diff --git a/tools/topology/topology2/include/bench/level_multiplier_controls_capture.conf b/tools/topology/topology2/include/bench/level_multiplier_controls_capture.conf new file mode 100644 index 000000000000..3a9a85dbf545 --- /dev/null +++ b/tools/topology/topology2/include/bench/level_multiplier_controls_capture.conf @@ -0,0 +1,17 @@ + # Created initially with script "./bench_comp_generate.sh level_multiplier" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in LEVEL_MULTIPLIER + bytes."1" { + name '$ANALOG_CAPTURE_PCM Level Multiplier bytes' + IncludeByKey.BENCH_LEVEL_MULTIPLIER_PARAMS { + "default" "include/components/level_multiplier/gain_0_db.conf" + } + } + #mixer."1" { + # name '$ANALOG_CAPTURE_PCM LEVEL_MULTIPLIER switch or volume' + #} + #enum."1" { + # name '$ANALOG_CAPTURE_PCM LEVEL_MULTIPLIER enum' + #} + } diff --git a/tools/topology/topology2/include/bench/level_multiplier_controls_playback.conf b/tools/topology/topology2/include/bench/level_multiplier_controls_playback.conf new file mode 100644 index 000000000000..59371f0eed4b --- /dev/null +++ b/tools/topology/topology2/include/bench/level_multiplier_controls_playback.conf @@ -0,0 +1,17 @@ + # Created initially with script "./bench_comp_generate.sh level_multiplier" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in LEVEL_MULTIPLIER + bytes."1" { + name '$ANALOG_PLAYBACK_PCM Level Multiplier bytes' + IncludeByKey.BENCH_LEVEL_MULTIPLIER_PARAMS { + "default" "include/components/level_multiplier/gain_0_db.conf" + } + } + #mixer."1" { + # name '$ANALOG_PLAYBACK_PCM LEVEL_MULTIPLIER switch or volume' + #} + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM LEVEL_MULTIPLIER enum' + #} + } diff --git a/tools/topology/topology2/include/bench/level_multiplier_route.conf b/tools/topology/topology2/include/bench/level_multiplier_route.conf new file mode 100644 index 000000000000..f63ab98782c4 --- /dev/null +++ b/tools/topology/topology2/include/bench/level_multiplier_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh level_multiplier" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'level_multiplier.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'level_multiplier.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'level_multiplier.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'level_multiplier.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/level_multiplier_s16.conf b/tools/topology/topology2/include/bench/level_multiplier_s16.conf new file mode 100644 index 000000000000..33b9d56ad278 --- /dev/null +++ b/tools/topology/topology2/include/bench/level_multiplier_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh level_multiplier" + Object.Widget.level_multiplier.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/level_multiplier_controls_playback.conf> + } + Object.Widget.level_multiplier.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/level_multiplier_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/level_multiplier_route.conf> diff --git a/tools/topology/topology2/include/bench/level_multiplier_s24.conf b/tools/topology/topology2/include/bench/level_multiplier_s24.conf new file mode 100644 index 000000000000..bd4b245a0bf3 --- /dev/null +++ b/tools/topology/topology2/include/bench/level_multiplier_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh level_multiplier" + Object.Widget.level_multiplier.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/level_multiplier_controls_playback.conf> + } + Object.Widget.level_multiplier.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/level_multiplier_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/level_multiplier_route.conf> diff --git a/tools/topology/topology2/include/bench/level_multiplier_s32.conf b/tools/topology/topology2/include/bench/level_multiplier_s32.conf new file mode 100644 index 000000000000..58b6f06d22a5 --- /dev/null +++ b/tools/topology/topology2/include/bench/level_multiplier_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh level_multiplier" + Object.Widget.level_multiplier.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/level_multiplier_controls_playback.conf> + } + Object.Widget.level_multiplier.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/level_multiplier_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/level_multiplier_route.conf> diff --git a/tools/topology/topology2/include/bench/mfcc_controls_capture.conf b/tools/topology/topology2/include/bench/mfcc_controls_capture.conf new file mode 100644 index 000000000000..d45baec1ee8f --- /dev/null +++ b/tools/topology/topology2/include/bench/mfcc_controls_capture.conf @@ -0,0 +1,18 @@ + # Created initially with script "./bench_comp_generate.sh mfcc" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in MFCC + bytes."1" { + name '$ANALOG_CAPTURE_PCM MFCC bytes' + IncludeByKey.BENCH_MFCC_PARAMS { + "default" "include/components/mfcc/default.conf" + "mel80" "include/components/mfcc/mel80.conf" + } + } + #mixer."1" { + # name '$ANALOG_CAPTURE_PCM MFCC switch or volume' + #} + #enum."1" { + # name '$ANALOG_CAPTURE_PCM MFCC enum' + #} + } diff --git a/tools/topology/topology2/include/bench/mfcc_controls_playback.conf b/tools/topology/topology2/include/bench/mfcc_controls_playback.conf new file mode 100644 index 000000000000..cc2ada04b8d7 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfcc_controls_playback.conf @@ -0,0 +1,18 @@ + # Created initially with script "./bench_comp_generate.sh mfcc" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in MFCC + bytes."1" { + name '$ANALOG_PLAYBACK_PCM MFCC bytes' + IncludeByKey.BENCH_MFCC_PARAMS { + "default" "include/components/mfcc/default.conf" + "mel80" "include/components/mfcc/mel80.conf" + } + } + #mixer."1" { + # name '$ANALOG_PLAYBACK_PCM MFCC switch or volume' + #} + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM MFCC enum' + #} + } diff --git a/tools/topology/topology2/include/bench/mfcc_route.conf b/tools/topology/topology2/include/bench/mfcc_route.conf new file mode 100644 index 000000000000..d4ce9af5f85d --- /dev/null +++ b/tools/topology/topology2/include/bench/mfcc_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'mfcc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'mfcc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'mfcc.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'mfcc.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/mfcc_s16.conf b/tools/topology/topology2/include/bench/mfcc_s16.conf new file mode 100644 index 000000000000..ec89bffb90a1 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfcc_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Widget.mfcc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16_16k.conf> + <include/bench/mfcc_controls_playback.conf> + } + Object.Widget.mfcc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16_16k.conf> + <include/bench/mfcc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16_16k.conf> + <include/bench/mfcc_route.conf> diff --git a/tools/topology/topology2/include/bench/mfcc_s24.conf b/tools/topology/topology2/include/bench/mfcc_s24.conf new file mode 100644 index 000000000000..73571fabe5f2 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfcc_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Widget.mfcc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24_16k.conf> + <include/bench/mfcc_controls_playback.conf> + } + Object.Widget.mfcc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24_16k.conf> + <include/bench/mfcc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24_16k.conf> + <include/bench/mfcc_route.conf> diff --git a/tools/topology/topology2/include/bench/mfcc_s32.conf b/tools/topology/topology2/include/bench/mfcc_s32.conf new file mode 100644 index 000000000000..75c01eaf4a43 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfcc_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Widget.mfcc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32_16k.conf> + <include/bench/mfcc_controls_playback.conf> + } + Object.Widget.mfcc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32_16k.conf> + <include/bench/mfcc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32_16k.conf> + <include/bench/mfcc_route.conf> diff --git a/tools/topology/topology2/include/bench/mfccmel_s16.conf b/tools/topology/topology2/include/bench/mfccmel_s16.conf new file mode 100644 index 000000000000..ec89bffb90a1 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfccmel_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Widget.mfcc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16_16k.conf> + <include/bench/mfcc_controls_playback.conf> + } + Object.Widget.mfcc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16_16k.conf> + <include/bench/mfcc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16_16k.conf> + <include/bench/mfcc_route.conf> diff --git a/tools/topology/topology2/include/bench/mfccmel_s24.conf b/tools/topology/topology2/include/bench/mfccmel_s24.conf new file mode 100644 index 000000000000..73571fabe5f2 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfccmel_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Widget.mfcc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24_16k.conf> + <include/bench/mfcc_controls_playback.conf> + } + Object.Widget.mfcc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24_16k.conf> + <include/bench/mfcc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24_16k.conf> + <include/bench/mfcc_route.conf> diff --git a/tools/topology/topology2/include/bench/mfccmel_s32.conf b/tools/topology/topology2/include/bench/mfccmel_s32.conf new file mode 100644 index 000000000000..75c01eaf4a43 --- /dev/null +++ b/tools/topology/topology2/include/bench/mfccmel_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh mfcc" + Object.Widget.mfcc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32_16k.conf> + <include/bench/mfcc_controls_playback.conf> + } + Object.Widget.mfcc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32_16k.conf> + <include/bench/mfcc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32_16k.conf> + <include/bench/mfcc_route.conf> diff --git a/tools/topology/topology2/include/bench/micsel_controls_capture.conf b/tools/topology/topology2/include/bench/micsel_controls_capture.conf new file mode 100644 index 000000000000..b51669298b90 --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_controls_capture.conf @@ -0,0 +1,18 @@ + # Created initially with script "./bench_comp_generate.sh micsel" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in MICSEL + bytes."1" { + name '$ANALOG_CAPTURE_PCM MICSEL bytes' + IncludeByKey.BENCH_MICSEL_PARAMS { + "passthrough" "include/components/micsel/passthrough.conf" + "default" "include/components/micsel/upmix_stereo_to_71.conf" + } + } + #mixer."1" { + # name '$ANALOG_CAPTURE_PCM MICSEL switch or volume' + #} + #enum."1" { + # name '$ANALOG_CAPTURE_PCM MICSEL enum' + #} + } diff --git a/tools/topology/topology2/include/bench/micsel_controls_playback.conf b/tools/topology/topology2/include/bench/micsel_controls_playback.conf new file mode 100644 index 000000000000..69dc0270d926 --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_controls_playback.conf @@ -0,0 +1,18 @@ + # Created initially with script "./bench_comp_generate.sh micsel" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in MICSEL + bytes."1" { + name '$ANALOG_PLAYBACK_PCM MICSEL bytes' + IncludeByKey.BENCH_MICSEL_PARAMS { + "passthrough" "include/components/micsel/passthrough.conf" + "default" "include/components/micsel/downmix_71_to_stereo_with_lfe.conf" + } + } + #mixer."1" { + # name '$ANALOG_PLAYBACK_PCM MICSEL switch or volume' + #} + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM MICSEL enum' + #} + } diff --git a/tools/topology/topology2/include/bench/micsel_hda_route.conf b/tools/topology/topology2/include/bench/micsel_hda_route.conf new file mode 100644 index 000000000000..1ab5115e710f --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_hda_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh micsel" + Object.Base.route [ + { + sink 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.playback' + source 'micsel.1.1' + } + { + sink 'micsel.1.1' + source 'host-copier.0.playback' + } + { + source 'dai-copier.HDA.$HDA_ANALOG_DAI_NAME.capture' + sink 'micsel.3.2' + } + { + source 'micsel.3.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/micsel_multich_s32.conf b/tools/topology/topology2/include/bench/micsel_multich_s32.conf new file mode 100644 index 000000000000..30ad60ccb76e --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_multich_s32.conf @@ -0,0 +1,138 @@ + # Created with script "./bench_comp_generate.sh micsel" + Object.Widget.micsel.1 { + index 1 + num_input_audio_formats 7 + num_output_audio_formats 1 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + ] + <include/bench/micsel_controls_playback.conf> + } + Object.Widget.micsel.2 { + index 3 + num_input_audio_formats 1 + num_output_audio_formats 7 + + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + <include/bench/micsel_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_multich_s32.conf> + <include/bench/micsel_route.conf> diff --git a/tools/topology/topology2/include/bench/micsel_route.conf b/tools/topology/topology2/include/bench/micsel_route.conf new file mode 100644 index 000000000000..1164ddb2e694 --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh micsel" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'micsel.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'micsel.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'micsel.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'micsel.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/micsel_s16.conf b/tools/topology/topology2/include/bench/micsel_s16.conf new file mode 100644 index 000000000000..a807f8695ad8 --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh micsel" + Object.Widget.micsel.1 { + index 1 + <include/bench/one_input_output_format_s16.conf> + <include/bench/micsel_controls_playback.conf> + } + Object.Widget.micsel.2 { + index 3 + <include/bench/one_input_output_format_s16.conf> + <include/bench/micsel_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/micsel_route.conf> diff --git a/tools/topology/topology2/include/bench/micsel_s24.conf b/tools/topology/topology2/include/bench/micsel_s24.conf new file mode 100644 index 000000000000..3823935c1db3 --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh micsel" + Object.Widget.micsel.1 { + index 1 + <include/bench/one_input_output_format_s24.conf> + <include/bench/micsel_controls_playback.conf> + } + Object.Widget.micsel.2 { + index 3 + <include/bench/one_input_output_format_s24.conf> + <include/bench/micsel_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/micsel_route.conf> diff --git a/tools/topology/topology2/include/bench/micsel_s32.conf b/tools/topology/topology2/include/bench/micsel_s32.conf new file mode 100644 index 000000000000..fe1e8cc556e6 --- /dev/null +++ b/tools/topology/topology2/include/bench/micsel_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh micsel" + Object.Widget.micsel.1 { + index 1 + <include/bench/one_input_output_format_s32.conf> + <include/bench/micsel_controls_playback.conf> + } + Object.Widget.micsel.2 { + index 3 + <include/bench/one_input_output_format_s32.conf> + <include/bench/micsel_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/micsel_route.conf> diff --git a/tools/topology/topology2/include/bench/multiband_drc_controls_capture.conf b/tools/topology/topology2/include/bench/multiband_drc_controls_capture.conf new file mode 100644 index 000000000000..ba1c6d87b9a1 --- /dev/null +++ b/tools/topology/topology2/include/bench/multiband_drc_controls_capture.conf @@ -0,0 +1,16 @@ + # Created initially with script "./bench_comp_generate.sh multiband_drc" + # may need edits to modify controls + Object.Control { + bytes."1" { + name '$ANALOG_CAPTURE_PCM MULTIBAND_DRC bytes' + IncludeByKey.BENCH_DRC_MULTIBAND_PARAMS { + "default" "include/components/multiband_drc/default.conf" + } + } + mixer."1" { + name '$ANALOG_CAPTURE_PCM MULTIBAND_DRC enable' + } + #enum."1" { + # name '$ANALOG_CAPTURE_PCM MULTIBAND_DRC enum' + #} + } diff --git a/tools/topology/topology2/include/bench/multiband_drc_controls_playback.conf b/tools/topology/topology2/include/bench/multiband_drc_controls_playback.conf new file mode 100644 index 000000000000..5b0357ee4e87 --- /dev/null +++ b/tools/topology/topology2/include/bench/multiband_drc_controls_playback.conf @@ -0,0 +1,16 @@ + # Created initially with script "./bench_comp_generate.sh multiband_drc" + # may need edits to modify controls + Object.Control { + bytes."1" { + name '$ANALOG_PLAYBACK_PCM MULTIBAND_DRC bytes' + IncludeByKey.BENCH_DRC_MULTIBAND_PARAMS { + "default" "include/components/multiband_drc/default.conf" + } + } + mixer."1" { + name '$ANALOG_PLAYBACK_PCM MULTIBAND_DRC enable' + } + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM MULTIBAND_DRC enum' + #} + } diff --git a/tools/topology/topology2/include/bench/multiband_drc_route.conf b/tools/topology/topology2/include/bench/multiband_drc_route.conf new file mode 100644 index 000000000000..1a59ed86f982 --- /dev/null +++ b/tools/topology/topology2/include/bench/multiband_drc_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh multiband_drc" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'multiband_drc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'multiband_drc.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'multiband_drc.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'multiband_drc.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/multiband_drc_s16.conf b/tools/topology/topology2/include/bench/multiband_drc_s16.conf new file mode 100644 index 000000000000..f29665f35799 --- /dev/null +++ b/tools/topology/topology2/include/bench/multiband_drc_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh multiband_drc" + Object.Widget.multiband_drc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/multiband_drc_controls_playback.conf> + } + Object.Widget.multiband_drc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/multiband_drc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/multiband_drc_route.conf> diff --git a/tools/topology/topology2/include/bench/multiband_drc_s24.conf b/tools/topology/topology2/include/bench/multiband_drc_s24.conf new file mode 100644 index 000000000000..110258f4c866 --- /dev/null +++ b/tools/topology/topology2/include/bench/multiband_drc_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh multiband_drc" + Object.Widget.multiband_drc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/multiband_drc_controls_playback.conf> + } + Object.Widget.multiband_drc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/multiband_drc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/multiband_drc_route.conf> diff --git a/tools/topology/topology2/include/bench/multiband_drc_s32.conf b/tools/topology/topology2/include/bench/multiband_drc_s32.conf new file mode 100644 index 000000000000..8bf433fbe94f --- /dev/null +++ b/tools/topology/topology2/include/bench/multiband_drc_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh multiband_drc" + Object.Widget.multiband_drc.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/multiband_drc_controls_playback.conf> + } + Object.Widget.multiband_drc.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/multiband_drc_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/multiband_drc_route.conf> diff --git a/tools/topology/topology2/include/bench/one_input_output_format_s16.conf b/tools/topology/topology2/include/bench/one_input_output_format_s16.conf new file mode 100644 index 000000000000..a309ceed07b4 --- /dev/null +++ b/tools/topology/topology2/include/bench/one_input_output_format_s16.conf @@ -0,0 +1,17 @@ + num_input_audio_formats 1 + num_output_audio_formats 1 + + # 16-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + diff --git a/tools/topology/topology2/include/bench/one_input_output_format_s16_16k.conf b/tools/topology/topology2/include/bench/one_input_output_format_s16_16k.conf new file mode 100644 index 000000000000..eca8c45d8bc9 --- /dev/null +++ b/tools/topology/topology2/include/bench/one_input_output_format_s16_16k.conf @@ -0,0 +1,19 @@ + num_input_audio_formats 1 + num_output_audio_formats 1 + + # 16-bit 16kHz + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_rate 16000 + } + ] + diff --git a/tools/topology/topology2/include/bench/one_input_output_format_s24.conf b/tools/topology/topology2/include/bench/one_input_output_format_s24.conf new file mode 100644 index 000000000000..081373a4b405 --- /dev/null +++ b/tools/topology/topology2/include/bench/one_input_output_format_s24.conf @@ -0,0 +1,17 @@ + num_input_audio_formats 1 + num_output_audio_formats 1 + + # 24-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + diff --git a/tools/topology/topology2/include/bench/one_input_output_format_s24_16k.conf b/tools/topology/topology2/include/bench/one_input_output_format_s24_16k.conf new file mode 100644 index 000000000000..742151e6948d --- /dev/null +++ b/tools/topology/topology2/include/bench/one_input_output_format_s24_16k.conf @@ -0,0 +1,19 @@ + num_input_audio_formats 1 + num_output_audio_formats 1 + + # 24-bit 16kHz + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_rate 16000 + } + ] + diff --git a/tools/topology/topology2/include/bench/one_input_output_format_s32.conf b/tools/topology/topology2/include/bench/one_input_output_format_s32.conf new file mode 100644 index 000000000000..adc4d2f47d40 --- /dev/null +++ b/tools/topology/topology2/include/bench/one_input_output_format_s32.conf @@ -0,0 +1,17 @@ + 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 + } + ] + diff --git a/tools/topology/topology2/include/bench/one_input_output_format_s32_16k.conf b/tools/topology/topology2/include/bench/one_input_output_format_s32_16k.conf new file mode 100644 index 000000000000..ae4608b5ab76 --- /dev/null +++ b/tools/topology/topology2/include/bench/one_input_output_format_s32_16k.conf @@ -0,0 +1,19 @@ + num_input_audio_formats 1 + num_output_audio_formats 1 + + # 32-bit 16kHz + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + diff --git a/tools/topology/topology2/include/bench/rtnr_controls_capture.conf b/tools/topology/topology2/include/bench/rtnr_controls_capture.conf new file mode 100644 index 000000000000..122f73674bc7 --- /dev/null +++ b/tools/topology/topology2/include/bench/rtnr_controls_capture.conf @@ -0,0 +1,23 @@ + # Created initially with script "./bench_comp_generate.sh rtnr" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in RTNR + bytes."1" { + name '$ANALOG_CAPTURE_PCM RTNR bytes' + IncludeByKey.BENCH_RTNR_PARAMS { + "default" "include/components/rtnr/default_bytes.conf" + } + } + bytes."2" { + name '$ANALOG_CAPTURE_PCM RTNR data' + IncludeByKey.BENCH_RTNR_PARAMS { + "default" "include/components/rtnr/default_data.conf" + } + } + mixer."1" { + name '$ANALOG_CAPTURE_PCM RTNR enable' + } + #enum."1" { + # name '$ANALOG_CAPTURE_PCM RTNR enum' + #} + } diff --git a/tools/topology/topology2/include/bench/rtnr_controls_playback.conf b/tools/topology/topology2/include/bench/rtnr_controls_playback.conf new file mode 100644 index 000000000000..21280af41cea --- /dev/null +++ b/tools/topology/topology2/include/bench/rtnr_controls_playback.conf @@ -0,0 +1,23 @@ + # Created initially with script "./bench_comp_generate.sh rtnr" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in RTNR + bytes."1" { + name '$ANALOG_PLAYBACK_PCM RTNR bytes' + IncludeByKey.BENCH_RTNR_PARAMS { + "default" "include/components/rtnr/default_bytes.conf" + } + } + bytes."2" { + name '$ANALOG_PLAYBACK_PCM RTNR data' + IncludeByKey.BENCH_RTNR_PARAMS { + "default" "include/components/rtnr/default_data.conf" + } + } + mixer."1" { + name '$ANALOG_PLAYBACK_PCM RTNR enable' + } + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM RTNR enum' + #} + } diff --git a/tools/topology/topology2/include/bench/rtnr_route.conf b/tools/topology/topology2/include/bench/rtnr_route.conf new file mode 100644 index 000000000000..9238049baf79 --- /dev/null +++ b/tools/topology/topology2/include/bench/rtnr_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh rtnr" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'rtnr.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'rtnr.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'rtnr.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'rtnr.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/rtnr_s16.conf b/tools/topology/topology2/include/bench/rtnr_s16.conf new file mode 100644 index 000000000000..e30c3843bf08 --- /dev/null +++ b/tools/topology/topology2/include/bench/rtnr_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh rtnr" + Object.Widget.rtnr.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/rtnr_controls_playback.conf> + } + Object.Widget.rtnr.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/rtnr_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/rtnr_route.conf> diff --git a/tools/topology/topology2/include/bench/rtnr_s24.conf b/tools/topology/topology2/include/bench/rtnr_s24.conf new file mode 100644 index 000000000000..bcd9d2443e53 --- /dev/null +++ b/tools/topology/topology2/include/bench/rtnr_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh rtnr" + Object.Widget.rtnr.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/rtnr_controls_playback.conf> + } + Object.Widget.rtnr.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/rtnr_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/rtnr_route.conf> diff --git a/tools/topology/topology2/include/bench/rtnr_s32.conf b/tools/topology/topology2/include/bench/rtnr_s32.conf new file mode 100644 index 000000000000..239294c41afd --- /dev/null +++ b/tools/topology/topology2/include/bench/rtnr_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh rtnr" + Object.Widget.rtnr.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/rtnr_controls_playback.conf> + } + Object.Widget.rtnr.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/rtnr_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/rtnr_route.conf> diff --git a/tools/topology/topology2/include/bench/sound_dose_controls_capture.conf b/tools/topology/topology2/include/bench/sound_dose_controls_capture.conf new file mode 100644 index 000000000000..38cbbc70b615 --- /dev/null +++ b/tools/topology/topology2/include/bench/sound_dose_controls_capture.conf @@ -0,0 +1,33 @@ + # Created initially with script "./bench_comp_generate.sh sound_dose" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in SOUND_DOSE + bytes."1" { + name '$ANALOG_CAPTURE_PCM Sound Dose setup bytes' + max 44 + IncludeByKey.BENCH_SOUND_DOSE_PARAMS { + "default" "include/components/sound_dose/setup_sens_100db.conf" + } + } + bytes."2" { + name '$ANALOG_CAPTURE_PCM Sound Dose volume bytes' + max 44 + <include/components/sound_dose/setup_vol_0db.conf> + } + bytes."3" { + name '$ANALOG_CAPTURE_PCM Sound Dose gain bytes' + max 44 + <include/components/sound_dose/setup_gain_0db.conf> + } + bytes."4" { + name '$ANALOG_CAPTURE_PCM Sound Dose data bytes' + max 256 + <include/components/sound_dose/setup_data_init.conf> + } + #mixer."1" { + # name '$ANALOG_CAPTURE_PCM SOUND_DOSE switch or volume' + #} + #enum."1" { + # name '$ANALOG_CAPTURE_PCM SOUND_DOSE enum' + #} + } diff --git a/tools/topology/topology2/include/bench/sound_dose_controls_playback.conf b/tools/topology/topology2/include/bench/sound_dose_controls_playback.conf new file mode 100644 index 000000000000..e0d83ffc0c2b --- /dev/null +++ b/tools/topology/topology2/include/bench/sound_dose_controls_playback.conf @@ -0,0 +1,33 @@ + # Created initially with script "./bench_comp_generate.sh sound_dose" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in SOUND_DOSE + bytes."1" { + name '$ANALOG_PLAYBACK_PCM Sound Dose setup bytes' + max 44 + IncludeByKey.BENCH_SOUND_DOSE_PARAMS { + "default" "include/components/sound_dose/setup_sens_100db.conf" + } + } + bytes."2" { + name '$ANALOG_PLAYBACK_PCM Sound Dose volume bytes' + max 44 + <include/components/sound_dose/setup_vol_0db.conf> + } + bytes."3" { + name '$ANALOG_PLAYBACK_PCM Sound Dose gain bytes' + max 44 + <include/components/sound_dose/setup_gain_0db.conf> + } + bytes."4" { + name '$ANALOG_PLAYBACK_PCM Sound Dose data bytes' + max 256 + <include/components/sound_dose/setup_data_init.conf> + } + #mixer."1" { + # name '$ANALOG_PLAYBACK_PCM SOUND_DOSE switch or volume' + #} + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM SOUND_DOSE enum' + #} + } diff --git a/tools/topology/topology2/include/bench/sound_dose_route.conf b/tools/topology/topology2/include/bench/sound_dose_route.conf new file mode 100644 index 000000000000..20f4b164e14d --- /dev/null +++ b/tools/topology/topology2/include/bench/sound_dose_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh sound_dose" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'sound_dose.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'sound_dose.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'sound_dose.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'sound_dose.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/sound_dose_s16.conf b/tools/topology/topology2/include/bench/sound_dose_s16.conf new file mode 100644 index 000000000000..3aec94858e08 --- /dev/null +++ b/tools/topology/topology2/include/bench/sound_dose_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh sound_dose" + Object.Widget.sound_dose.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/sound_dose_controls_playback.conf> + } + Object.Widget.sound_dose.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/sound_dose_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/sound_dose_route.conf> diff --git a/tools/topology/topology2/include/bench/sound_dose_s24.conf b/tools/topology/topology2/include/bench/sound_dose_s24.conf new file mode 100644 index 000000000000..fe59e8e2fb4c --- /dev/null +++ b/tools/topology/topology2/include/bench/sound_dose_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh sound_dose" + Object.Widget.sound_dose.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/sound_dose_controls_playback.conf> + } + Object.Widget.sound_dose.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/sound_dose_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/sound_dose_route.conf> diff --git a/tools/topology/topology2/include/bench/sound_dose_s32.conf b/tools/topology/topology2/include/bench/sound_dose_s32.conf new file mode 100644 index 000000000000..5e3146a8076f --- /dev/null +++ b/tools/topology/topology2/include/bench/sound_dose_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh sound_dose" + Object.Widget.sound_dose.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/sound_dose_controls_playback.conf> + } + Object.Widget.sound_dose.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/sound_dose_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/sound_dose_route.conf> diff --git a/tools/topology/topology2/include/bench/src_lite_route.conf b/tools/topology/topology2/include/bench/src_lite_route.conf new file mode 100644 index 000000000000..65713b5e62be --- /dev/null +++ b/tools/topology/topology2/include/bench/src_lite_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh src_lite" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'src_lite.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'src_lite.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'src_lite.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'src_lite.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/src_lite_s16.conf b/tools/topology/topology2/include/bench/src_lite_s16.conf new file mode 100644 index 000000000000..559d47a1af4b --- /dev/null +++ b/tools/topology/topology2/include/bench/src_lite_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh src_lite" + Object.Widget.src_lite.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + rate_out 48000 + <include/components/src_format_s16_convert_to_48k.conf> + } + Object.Widget.src_lite.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + rate_in 48000 + <include/components/src_format_s16_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s16.conf> + <include/bench/src_lite_route.conf> diff --git a/tools/topology/topology2/include/bench/src_lite_s24.conf b/tools/topology/topology2/include/bench/src_lite_s24.conf new file mode 100644 index 000000000000..319a5e8d3475 --- /dev/null +++ b/tools/topology/topology2/include/bench/src_lite_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh src_lite" + Object.Widget.src_lite.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + rate_out 48000 + <include/components/src_format_s24_convert_to_48k.conf> + } + Object.Widget.src_lite.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + rate_in 48000 + <include/components/src_format_s24_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s24.conf> + <include/bench/src_lite_route.conf> diff --git a/tools/topology/topology2/include/bench/src_lite_s32.conf b/tools/topology/topology2/include/bench/src_lite_s32.conf new file mode 100644 index 000000000000..8339d191e39a --- /dev/null +++ b/tools/topology/topology2/include/bench/src_lite_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh src_lite" + Object.Widget.src_lite.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + rate_out 48000 + <include/components/src_format_s32_convert_to_48k.conf> + } + Object.Widget.src_lite.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + rate_in 48000 + <include/components/src_format_s32_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s32.conf> + <include/bench/src_lite_route.conf> diff --git a/tools/topology/topology2/include/bench/src_route.conf b/tools/topology/topology2/include/bench/src_route.conf new file mode 100644 index 000000000000..aac36eb913df --- /dev/null +++ b/tools/topology/topology2/include/bench/src_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh src" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'src.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'src.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'src.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'src.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/src_s16.conf b/tools/topology/topology2/include/bench/src_s16.conf new file mode 100644 index 000000000000..73a84b407be4 --- /dev/null +++ b/tools/topology/topology2/include/bench/src_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh src" + Object.Widget.src.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + rate_out 48000 + <include/components/src_format_s16_convert_to_48k.conf> + } + Object.Widget.src.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + rate_in 48000 + <include/components/src_format_s16_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s16.conf> + <include/bench/src_route.conf> diff --git a/tools/topology/topology2/include/bench/src_s24.conf b/tools/topology/topology2/include/bench/src_s24.conf new file mode 100644 index 000000000000..355411b644eb --- /dev/null +++ b/tools/topology/topology2/include/bench/src_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh src" + Object.Widget.src.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + rate_out 48000 + <include/components/src_format_s24_convert_to_48k.conf> + } + Object.Widget.src.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + rate_in 48000 + <include/components/src_format_s24_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s24.conf> + <include/bench/src_route.conf> diff --git a/tools/topology/topology2/include/bench/src_s32.conf b/tools/topology/topology2/include/bench/src_s32.conf new file mode 100644 index 000000000000..4262fa535d2b --- /dev/null +++ b/tools/topology/topology2/include/bench/src_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh src" + Object.Widget.src.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + rate_out 48000 + <include/components/src_format_s32_convert_to_48k.conf> + } + Object.Widget.src.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + rate_in 48000 + <include/components/src_format_s32_convert_from_48k.conf> + } + <include/bench/host_gateway_pipelines_src_s32.conf> + <include/bench/src_route.conf> diff --git a/tools/topology/topology2/include/bench/stft_process_controls_capture.conf b/tools/topology/topology2/include/bench/stft_process_controls_capture.conf new file mode 100644 index 000000000000..67acf222d764 --- /dev/null +++ b/tools/topology/topology2/include/bench/stft_process_controls_capture.conf @@ -0,0 +1,21 @@ + # Created initially with script "./bench_comp_generate.sh stft_process" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in STFT_PROCESS + bytes."1" { + name '$ANALOG_CAPTURE_PCM STFT_PROCESS bytes' + IncludeByKey.BENCH_STFT_PROCESS_PARAMS { + "hann_192_48" "include/components/stft_process/hann_192_48.conf" + "hann_512_128" "include/components/stft_process/hann_512_128.conf" + "hann_768_120" "include/components/stft_process/hann_768_120.conf" + "hann_1024_256" "include/components/stft_process/hann_1024_256.conf" + "hann_1536_240" "include/components/stft_process/hann_1536_240.conf" + } + } + #mixer."1" { + # name '$ANALOG_CAPTURE_PCM STFT_PROCESS switch or volume' + #} + #enum."1" { + # name '$ANALOG_CAPTURE_PCM STFT_PROCESS enum' + #} + } diff --git a/tools/topology/topology2/include/bench/stft_process_controls_playback.conf b/tools/topology/topology2/include/bench/stft_process_controls_playback.conf new file mode 100644 index 000000000000..82c702555e40 --- /dev/null +++ b/tools/topology/topology2/include/bench/stft_process_controls_playback.conf @@ -0,0 +1,21 @@ + # Created initially with script "./bench_comp_generate.sh stft_process" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in STFT_PROCESS + bytes."1" { + name '$ANALOG_PLAYBACK_PCM STFT_PROCESS bytes' + IncludeByKey.BENCH_STFT_PROCESS_PARAMS { + "hann_192_48" "include/components/stft_process/hann_192_48.conf" + "hann_512_128" "include/components/stft_process/hann_512_128.conf" + "hann_768_120" "include/components/stft_process/hann_768_120.conf" + "hann_1024_256" "include/components/stft_process/hann_1024_256.conf" + "hann_1536_240" "include/components/stft_process/hann_1536_240.conf" + } + } + #mixer."1" { + # name '$ANALOG_PLAYBACK_PCM STFT_PROCESS switch or volume' + #} + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM STFT_PROCESS enum' + #} + } diff --git a/tools/topology/topology2/include/bench/stft_process_route.conf b/tools/topology/topology2/include/bench/stft_process_route.conf new file mode 100644 index 000000000000..dcc4dc3feebc --- /dev/null +++ b/tools/topology/topology2/include/bench/stft_process_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh stft_process" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'stft_process.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'stft_process.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'stft_process.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'stft_process.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/stft_process_s16.conf b/tools/topology/topology2/include/bench/stft_process_s16.conf new file mode 100644 index 000000000000..ebe14bcd0c21 --- /dev/null +++ b/tools/topology/topology2/include/bench/stft_process_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh stft_process" + Object.Widget.stft_process.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/stft_process_controls_playback.conf> + } + Object.Widget.stft_process.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/stft_process_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/stft_process_route.conf> diff --git a/tools/topology/topology2/include/bench/stft_process_s24.conf b/tools/topology/topology2/include/bench/stft_process_s24.conf new file mode 100644 index 000000000000..b75f35a3a486 --- /dev/null +++ b/tools/topology/topology2/include/bench/stft_process_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh stft_process" + Object.Widget.stft_process.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/stft_process_controls_playback.conf> + } + Object.Widget.stft_process.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/stft_process_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/stft_process_route.conf> diff --git a/tools/topology/topology2/include/bench/stft_process_s32.conf b/tools/topology/topology2/include/bench/stft_process_s32.conf new file mode 100644 index 000000000000..d0d16557bbee --- /dev/null +++ b/tools/topology/topology2/include/bench/stft_process_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh stft_process" + Object.Widget.stft_process.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/stft_process_controls_playback.conf> + } + Object.Widget.stft_process.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/stft_process_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/stft_process_route.conf> diff --git a/tools/topology/topology2/include/bench/tdfb_controls_capture.conf b/tools/topology/topology2/include/bench/tdfb_controls_capture.conf new file mode 100644 index 000000000000..d2128cc9ba2b --- /dev/null +++ b/tools/topology/topology2/include/bench/tdfb_controls_capture.conf @@ -0,0 +1,23 @@ + # Created initially with script "./bench_comp_generate.sh tdfb" + # may need edits to modify controls + Object.Control { + bytes."1" { + name '$ANALOG_CAPTURE_PCM TDFB bytes' + max 4096 + IncludeByKey.BENCH_TDFB_PARAMS { + "default" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + } + } + mixer."1" { + name '$ANALOG_CAPTURE_PCM TDFB beam' + } + mixer."2" { + name '$ANALOG_CAPTURE_PCM TDFB track' + } + enum."1" { + name '$ANALOG_CAPTURE_PCM TDFB angle set' + } + enum."2" { + name '$ANALOG_CAPTURE_PCM TDFB angle estimate' + } + } diff --git a/tools/topology/topology2/include/bench/tdfb_controls_playback.conf b/tools/topology/topology2/include/bench/tdfb_controls_playback.conf new file mode 100644 index 000000000000..27a09918e4ff --- /dev/null +++ b/tools/topology/topology2/include/bench/tdfb_controls_playback.conf @@ -0,0 +1,23 @@ + # Created initially with script "./bench_comp_generate.sh tdfb" + # may need edits to modify controls + Object.Control { + bytes."1" { + name '$ANALOG_PLAYBACK_PCM TDFB bytes' + max 4096 + IncludeByKey.BENCH_TDFB_PARAMS { + "default" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + } + } + mixer."1" { + name '$ANALOG_PLAYBACK_PCM TDFB beam' + } + mixer."2" { + name '$ANALOG_PLAYBACK_PCM TDFB track' + } + enum."1" { + name '$ANALOG_PLAYBACK_PCM TDFB angle set' + } + enum."2" { + name '$ANALOG_PLAYBACK_PCM TDFB angle estimate' + } + } diff --git a/tools/topology/topology2/include/bench/tdfb_route.conf b/tools/topology/topology2/include/bench/tdfb_route.conf new file mode 100644 index 000000000000..809dd627d6de --- /dev/null +++ b/tools/topology/topology2/include/bench/tdfb_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh tdfb" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'tdfb.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'tdfb.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'tdfb.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'tdfb.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/tdfb_s16.conf b/tools/topology/topology2/include/bench/tdfb_s16.conf new file mode 100644 index 000000000000..d08eea403981 --- /dev/null +++ b/tools/topology/topology2/include/bench/tdfb_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh tdfb" + Object.Widget.tdfb.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/tdfb_controls_playback.conf> + } + Object.Widget.tdfb.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/tdfb_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/tdfb_route.conf> diff --git a/tools/topology/topology2/include/bench/tdfb_s24.conf b/tools/topology/topology2/include/bench/tdfb_s24.conf new file mode 100644 index 000000000000..418e48b53c04 --- /dev/null +++ b/tools/topology/topology2/include/bench/tdfb_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh tdfb" + Object.Widget.tdfb.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/tdfb_controls_playback.conf> + } + Object.Widget.tdfb.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/tdfb_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/tdfb_route.conf> diff --git a/tools/topology/topology2/include/bench/tdfb_s32.conf b/tools/topology/topology2/include/bench/tdfb_s32.conf new file mode 100644 index 000000000000..95e36dfdff34 --- /dev/null +++ b/tools/topology/topology2/include/bench/tdfb_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh tdfb" + Object.Widget.tdfb.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/tdfb_controls_playback.conf> + } + Object.Widget.tdfb.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/tdfb_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/tdfb_route.conf> diff --git a/tools/topology/topology2/include/bench/template_comp_controls_capture.conf b/tools/topology/topology2/include/bench/template_comp_controls_capture.conf new file mode 100644 index 000000000000..b05f70fa5899 --- /dev/null +++ b/tools/topology/topology2/include/bench/template_comp_controls_capture.conf @@ -0,0 +1,17 @@ + # Created initially with script "./bench_comp_generate.sh template_comp" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in TEMPLATE_COMP + #bytes."1" { + # name '$ANALOG_CAPTURE_PCM TEMPLATE_COMP bytes' + # IncludeByKey.BENCH_TEMPLATE_COMP_PARAMS { + # "default" "include/components/template_comp/default.conf" + # } + #} + mixer."1" { + name '$ANALOG_CAPTURE_PCM TEMPLATE_COMP switch' + } + #enum."1" { + # name '$ANALOG_CAPTURE_PCM TEMPLATE_COMP enum' + #} + } diff --git a/tools/topology/topology2/include/bench/template_comp_controls_playback.conf b/tools/topology/topology2/include/bench/template_comp_controls_playback.conf new file mode 100644 index 000000000000..5e86efe6aa42 --- /dev/null +++ b/tools/topology/topology2/include/bench/template_comp_controls_playback.conf @@ -0,0 +1,17 @@ + # Created initially with script "./bench_comp_generate.sh template_comp" + # may need edits to modify controls + Object.Control { + # Un-comment the supported controls in TEMPLATE_COMP + #bytes."1" { + # name '$ANALOG_PLAYBACK_PCM TEMPLATE_COMP bytes' + # IncludeByKey.BENCH_TEMPLATE_COMP_PARAMS { + # "default" "include/components/template_comp/default.conf" + # } + #} + mixer."1" { + name '$ANALOG_PLAYBACK_PCM TEMPLATE_COMP switch' + } + #enum."1" { + # name '$ANALOG_PLAYBACK_PCM TEMPLATE_COMP enum' + #} + } diff --git a/tools/topology/topology2/include/bench/template_comp_route.conf b/tools/topology/topology2/include/bench/template_comp_route.conf new file mode 100644 index 000000000000..9fe72d672489 --- /dev/null +++ b/tools/topology/topology2/include/bench/template_comp_route.conf @@ -0,0 +1,19 @@ + # Created with script "./bench_comp_generate.sh template_comp" + Object.Base.route [ + { + sink '$BENCH_PLAYBACK_DAI_COPIER' + source 'template_comp.$BENCH_PLAYBACK_HOST_PIPELINE.1' + } + { + sink 'template_comp.$BENCH_PLAYBACK_HOST_PIPELINE.1' + source 'host-copier.0.playback' + } + { + source '$BENCH_CAPTURE_DAI_COPIER' + sink 'template_comp.$BENCH_CAPTURE_HOST_PIPELINE.2' + } + { + source 'template_comp.$BENCH_CAPTURE_HOST_PIPELINE.2' + sink 'host-copier.0.capture' + } + ] diff --git a/tools/topology/topology2/include/bench/template_comp_s16.conf b/tools/topology/topology2/include/bench/template_comp_s16.conf new file mode 100644 index 000000000000..57ab83eca6fa --- /dev/null +++ b/tools/topology/topology2/include/bench/template_comp_s16.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh template_comp" + Object.Widget.template_comp.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/template_comp_controls_playback.conf> + } + Object.Widget.template_comp.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s16.conf> + <include/bench/template_comp_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s16.conf> + <include/bench/template_comp_route.conf> diff --git a/tools/topology/topology2/include/bench/template_comp_s24.conf b/tools/topology/topology2/include/bench/template_comp_s24.conf new file mode 100644 index 000000000000..83573abf19fe --- /dev/null +++ b/tools/topology/topology2/include/bench/template_comp_s24.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh template_comp" + Object.Widget.template_comp.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/template_comp_controls_playback.conf> + } + Object.Widget.template_comp.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s24.conf> + <include/bench/template_comp_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s24.conf> + <include/bench/template_comp_route.conf> diff --git a/tools/topology/topology2/include/bench/template_comp_s32.conf b/tools/topology/topology2/include/bench/template_comp_s32.conf new file mode 100644 index 000000000000..e05a346b82d7 --- /dev/null +++ b/tools/topology/topology2/include/bench/template_comp_s32.conf @@ -0,0 +1,13 @@ + # Created with script "./bench_comp_generate.sh template_comp" + Object.Widget.template_comp.1 { + index $BENCH_PLAYBACK_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/template_comp_controls_playback.conf> + } + Object.Widget.template_comp.2 { + index $BENCH_CAPTURE_HOST_PIPELINE + <include/bench/one_input_output_format_s32.conf> + <include/bench/template_comp_controls_capture.conf> + } + <include/bench/host_gateway_pipelines_s32.conf> + <include/bench/template_comp_route.conf> diff --git a/tools/topology/topology2/include/common/common_definitions.conf b/tools/topology/topology2/include/common/common_definitions.conf new file mode 100644 index 000000000000..87c69dd41e41 --- /dev/null +++ b/tools/topology/topology2/include/common/common_definitions.conf @@ -0,0 +1,76 @@ +# Commonly used definitions in topologies +Define { + # Channel configuration + CHANNEL_CONFIG_MONO 0 # one channel only + CHANNEL_CONFIG_STEREO 1 # L & R. + CHANNEL_CONFIG_2_POINT_1 2 # L, R & LFE; PCM only. + CHANNEL_CONFIG_3_POINT_0 3 # L, C & R; MP3 & AAC only. + CHANNEL_CONFIG_3_POINT_1 4 # L, C, R & LFE; PCM only. + CHANNEL_CONFIG_QUATRO 5 # L, R, Ls & Rs; PCM only. + CHANNEL_CONFIG_4_POINT_0 6 # L, C, R & Cs; MP3 & AAC only. + CHANNEL_CONFIG_5_POINT_0 7 # L, C, R, Ls & Rs. + CHANNEL_CONFIG_5_POINT_1 8 # L, C, R, Ls, Rs & LFE. + CHANNEL_CONFIG_DUAL_MONO 9 # one channel replicated in two. + CHANNEL_CONFIG_I2S_DUAL_STEREO_0 10 # Stereo (L,R) in 4 slots, 1st stream: [ L, R, -, - ] + CHANNEL_CONFIG_I2S_DUAL_STEREO_1 11 # Stereo (L,R) in 4 slots, 2nd stream: [ -, -, L, R ] + CHANNEL_CONFIG_7_POINT_1 12 # L, C, R, Ls, Rs & LFE, LS, RS + CHANNEL_CONFIG_INVALID 13 # invalid + + # Channel map + CHANNEL_MAP_MONO 0xFFFFFFF0 + CHANNEL_MAP_STEREO 0xFFFFFF10 + CHANNEL_MAP_2_POINT_1 0xFFFFF210 + CHANNEL_MAP_3_POINT_1 0xFFFF3210 + CHANNEL_MAP_5_POINT_0 0xFFF43210 + CHANNEL_MAP_5_POINT_1 0xFF543210 + CHANNEL_MAP_7_POINT_1 0x76543210 + CHANNEL_MAP_INVALID 0xFFFFFFFF + + # Sample types + SAMPLE_TYPE_MSB_INTEGER 0 # integer with valid samples in most significant + # bits, aka left aligned (not endianness!) + SAMPLE_TYPE_LSB_INTEGER 1 # integer with valid samples in least significant + # bits, aka right aligned (not endianness!) + SAMPLE_TYPE_SIGNED_INTEGER 2 # Signed Integer + SAMPLE_TYPE_UNSIGNED_INTEGER 3 # Unsigned Integer + SAMPLE_TYPE_FLOAT 4 # Float + SAMPLE_TYPE_A_LAW 5 # A-law + SAMPLE_TYPE_MU_LAW 6 # mu-law + + # Copier type + HDA_HOST_OUTPUT_CLASS 0 # HD/A host output (-> DSP) + HDA_HOST_INPUT_CLASS 1 # HD/A host input (<- DSP) + HDA_HOST_INOUT_CLASS 2 # HD/A host input/output (rsvd for future use) + HDA_LINK_OUTPUT_CLASS 8 # HD/A link output (DSP ->) + HDA_LINK_INPUT_CLASS 9 # HD/A link input (DSP <-) + HDA_LINK_INOUT_CLASS 10 # HD/A link input/output (rsvd for future use) + DMIC_LINK_INPUT_CLASS 11 # DMIC link input (DSP <-) + I2S_LINK_OUTPUT_CLASS 12 # I2S link output (DSP ->) + I2S_LINK_INPUT_CLASS 13 # I2S link input (DSP <-) + ALH_LINK_OUTPUT_CLASS 16 # ALH link output, legacy for SNDW (DSP ->) + ALH_LINK_INPUT_CLASS 17 # ALH link input, legacy for SNDW (DSP <-) + ALH_SNDWIRE_STREAM_LINK_OUTPUT_CLASS 16 # SNDW link output (DSP ->) + ALH_SNDWIRE_STREAM_LINK_INPUT_CLASS 17 # SNDW link input (DSP <-) + ALH_UAOL_STREAM_LINK_OUTPUT_CLASS 18 # UAOL link output (DSP ->) + ALH_UAOL_STREAM_LINK_INPUT_CLASS 19 # UAOL link input (DSP <-) + IPC_OUTPUT_CLASS 20 # IPC output (DSP ->) + IPC_INPUT_CLASS 21 # IPC input (DSP <-) + I2S_MULTILINK_OUTPUT_CLASS 22 # I2S Multi gtw output (DSP ->) + I2S_MULTILINKI_NPUT_CLASS 23 # I2S Multi gtw input (DSP <-) + GPIO_CLASS 24 # GPIO + SPI_OUTPUT_CLASS 25 # SPI Output (DSP ->) + SPI_INPUT_CLASS 26 # SPI Input (DSP <-) + + DEEPBUFFER_FW_DMA_MS 100 # 100 ms copier dma size + DEEPBUFFER_D0I3_COMPATIBLE true # Deep buffer PCM is D0I3 compatible + + SSP_BLOB_VERSION_1_0 0x100 + SSP_BLOB_VERSION_1_5 0x105 + SSP_BLOB_VERSION_3_0 0x300 + + PCM_FORMAT_ALL false # Basic s16/s24/s32, no float, 8-bit etc. + SDW_JACK_ECHO_REF false # No echo reference for 3.5mm jack + SDW_SPK_ECHO_REF false # No echo reference for speaker + SDW_JACK_AUDIO_FEATURE_CAPTURE false # No audio features capture for jack + SDW_DMIC_AUDIO_FEATURE_CAPTURE false # No audio features capture for microphone +} diff --git a/tools/topology/topology2/include/common/data.conf b/tools/topology/topology2/include/common/data.conf new file mode 100644 index 000000000000..02900ee192a4 --- /dev/null +++ b/tools/topology/topology2/include/common/data.conf @@ -0,0 +1,32 @@ +## \struct data +## \brief Class definition for data object +## +## Data objects can be instantiated as: +## +## Object.Base.data."SOF ABI" { +## bytes "0x3, 0x12,0x1" +## } +## +Class.Base."data" { + + DefineAttribute."instance" {} + + DefineAttribute."name" { + type "string" + } + + DefineAttribute."bytes" { + type "string" + } + + attributes { + !constructor [ + "name" + ] + # + # data objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } +} diff --git a/tools/topology/topology2/include/common/fe_dai.conf b/tools/topology/topology2/include/common/fe_dai.conf new file mode 100644 index 000000000000..e67d8aa4d22b --- /dev/null +++ b/tools/topology/topology2/include/common/fe_dai.conf @@ -0,0 +1,40 @@ +## \struct fe_dai +## \brief FE DAI Class definition +## +## All attributes defined herein are namespaced by alsatplg to +## "Object.Base.fe_dai.instance.attribute_name". +## +## Usage: FE DAI objects can be instantiated as +## +## Object.Base.fe_dai.1 { +## id 0 +## } +## +## where NAME is the unique instance name for the FE DAI object within the +## same alsaconf node. + +Class.Base."fe_dai" { + + DefineAttribute."instance" {} + + DefineAttribute."name" { + type "string" + } + + DefineAttribute."id" {} + + attributes { + !constructor [ + "name" + ] + + !mandatory [ + "id" + ] + # + # instance attribute values for fe_dai objects must be unique in the + # same alsaconf node + # + unique "instance" + } +} diff --git a/tools/topology/topology2/include/common/input_audio_format.conf b/tools/topology/topology2/include/common/input_audio_format.conf new file mode 100644 index 000000000000..7c220516ed48 --- /dev/null +++ b/tools/topology/topology2/include/common/input_audio_format.conf @@ -0,0 +1,142 @@ +## \struct input_audio_format +## \brief Volume playback pipeline +## +## Class definition for input pin audio format object +## audio_format objects can be instantiated as: +## +## Object.Base.input_audio_format."0" { +## in_rate 48000 +## in_sample_container_size 16 +## in_valid_bit_depth 16 +## in_interleaving_style "interleaved" +## } +## + +Class.Base."input_audio_format" { + + DefineAttribute."instance" { + } + + DefineAttribute."input_pin_index" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## input sampling rate + DefineAttribute."in_rate" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## input bit depth + DefineAttribute."in_bit_depth" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## input valid bit depth + DefineAttribute."in_valid_bit_depth" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## input channel count + DefineAttribute."in_channels" { + # Token set reference name + token_ref "cavs_audio_format.word" + constraints { + min 1 + max 8 + } + } + + ## input channel map + DefineAttribute."in_ch_map" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## input channel config + DefineAttribute."in_ch_cfg" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## input interleaving style + DefineAttribute."in_interleaving_style" { + type "string" + # Token set reference name + token_ref "cavs_audio_format.word" + constraints { + !valid_values [ + "interleaved" + "non-interleaved" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + ## input format config + DefineAttribute."in_fmt_cfg" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + ## Input sample_type. + ## Valid values for sample type are defined in common_definitions.conf. + DefineAttribute."in_sample_type" { + type string + # Token set reference name + token_ref "cavs_audio_format.word" + constraints { + !valid_values [ + $SAMPLE_TYPE_MSB_INTEGER + $SAMPLE_TYPE_LSB_INTEGER + $SAMPLE_TYPE_SIGNED_INTEGER + $SAMPLE_TYPE_UNSIGNED_INTEGER + $SAMPLE_TYPE_FLOAT + $SAMPLE_TYPE_A_LAW + $SAMPLE_TYPE_MU_LAW + ] + } + } + + # + ## input buffer size + # + DefineAttribute."ibs" { + # Token set reference name and type + token_ref "cavs_audio_format.word" + } + + attributes { + !constructor [ + "instance" + ] + + # + # audio_format objects instantiated within the same alsaconf node must have unique + # instance attribute values + # + unique "instance" + } + + in_rate 48000 + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 2 + in_interleaving_style "interleaved" + in_sample_type $SAMPLE_TYPE_LSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + + # math expression for computing input/output fmt_cfg + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256)) | ($in_sample_type * 65536)]" + + # math expression for computing input/put buffer sizes + # for 11.025 22.05, 44.1, 88.2 and 176.4khz, we need to round it to ceiling value + ibs "$[($in_channels * ($[($in_rate + 999)] / 1000)) * ($in_bit_depth / 8)]" +} diff --git a/tools/topology/topology2/include/common/input_pin_binding.conf b/tools/topology/topology2/include/common/input_pin_binding.conf new file mode 100644 index 000000000000..f72d81c2a7ea --- /dev/null +++ b/tools/topology/topology2/include/common/input_pin_binding.conf @@ -0,0 +1,34 @@ +# +# The intput pin binding class definition. All attributes defined herein are +# namespaced by alsatplg to "Object.Base.input_pin_binding.instance.attribute_name". +# +# Usage: Input pin binding objects can be instantiated as +# +# Object.Base.input_pin_binding."0" { +# input_pin_binding_name "copier.host.1.0" +# } +# +# where 0 is the unique instance name for the input_pin_binding object within the +# same alsaconf node. + +Class.Base."input_pin_binding" { + + DefineAttribute."instance" {} + + # The widget name that the intput pin should be bound with. + DefineAttribute."input_pin_binding_name" { + token_ref "comp.string" + } + + attributes { + !constructor [ + "instance" + ] + + !mandatory [ + "input_pin_binding_name" + ] + + unique "instance" + } +} diff --git a/tools/topology/topology2/include/common/manifest.conf b/tools/topology/topology2/include/common/manifest.conf new file mode 100644 index 000000000000..808d9645bb8e --- /dev/null +++ b/tools/topology/topology2/include/common/manifest.conf @@ -0,0 +1,36 @@ +# +# Manifest Class definition. +# + +Class.Base."manifest" { + DefineAttribute."instance" {} + + DefineAttribute."name" { + type "string" + } + + # generate nhlt from dai definitions + DefineAttribute."nhlt" { + type "string" + constraints { + !valid_values [ + "true" + "false" + ] + } + } + + attributes { + !constructor [ + "name" + ] + # + # instance attribute values for manifest objects must be unique + # in the same alsaconf node + # + unique "instance" + } + + # as default don't generate nhlt + nhlt "false" +} diff --git a/tools/topology/topology2/include/common/output_audio_format.conf b/tools/topology/topology2/include/common/output_audio_format.conf new file mode 100644 index 000000000000..7930402a26f2 --- /dev/null +++ b/tools/topology/topology2/include/common/output_audio_format.conf @@ -0,0 +1,139 @@ +# Class definition for output pin audio format object +# audio_format objects can be instantiated as: +# +# Object.Base.output_audio_format."0" { +# out_rate 48000 +# out_sample_container_size 16 +# out_valid_bit_depth 16 +# out_interleaving_style "interleaved" + +# } +# + +Class.Base."output_audio_format" { + + DefineAttribute."instance" { + } + + DefineAttribute."output_pin_index" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # output sampling rate + DefineAttribute."out_rate" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # output bit depth + DefineAttribute."out_bit_depth" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # output valid bit depth + DefineAttribute."out_valid_bit_depth" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # output channel count + DefineAttribute."out_channels" { + # Token set reference name + token_ref "cavs_audio_format.word" + constraints { + min 1 + max 8 + } + } + + # output channel map + DefineAttribute."out_ch_map" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # output channel config + DefineAttribute."out_ch_cfg" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # output interleaving style + DefineAttribute."out_interleaving_style" { + type "string" + # Token set reference name + token_ref "cavs_audio_format.word" + constraints { + !valid_values [ + "interleaved" + "non-interleaved" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + # output format config + DefineAttribute."out_fmt_cfg" { + # Token set reference name + token_ref "cavs_audio_format.word" + } + + # + # output buffer size + # + DefineAttribute."obs" { + # Token set reference name and type + token_ref "cavs_audio_format.word" + } + + #output sample_type + DefineAttribute."out_sample_type" { + type string + # Token set reference name + token_ref "cavs_audio_format.word" + constraints { + !valid_values [ + $SAMPLE_TYPE_MSB_INTEGER + $SAMPLE_TYPE_LSB_INTEGER + $SAMPLE_TYPE_SIGNED_INTEGER + $SAMPLE_TYPE_UNSIGNED_INTEGER + $SAMPLE_TYPE_FLOAT + $SAMPLE_TYPE_A_LAW + $SAMPLE_TYPE_MU_LAW + ] + } + } + + attributes { + !constructor [ + "instance" + ] + + # + # output_audio_format objects instantiated within the same alsaconf node must have + # unique instance attribute values + # + unique "instance" + } + + out_rate 48000 + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 2 + out_interleaving_style "interleaved" + out_sample_type $SAMPLE_TYPE_LSB_INTEGER + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + + # math expression for computing output fmt_cfg + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256)) | ($out_sample_type * 65536)]" + + # math expression for computing input/put buffer sizes + # for 11.025 22.05, 44.1, 88.2 and 176.4khz, we need to round it to ceiling value + obs "$[($out_channels * ($[($out_rate + 999)] / 1000)) * ($out_bit_depth / 8)]" +} diff --git a/tools/topology/topology2/include/common/output_pin_binding.conf b/tools/topology/topology2/include/common/output_pin_binding.conf new file mode 100644 index 000000000000..27bc678c60b1 --- /dev/null +++ b/tools/topology/topology2/include/common/output_pin_binding.conf @@ -0,0 +1,37 @@ +# +# The output pin binding class definition. All attributes defined herein are +# namespaced by alsatplg to "Object.Base.output_pin_binding.instance.attribute_name". +# +# Usage: Source pin binding objects can be instantiated as +# +# Object.Base.output_pin_binding."0" { +# output_pin_binding_name "copier.host.1.0" +# } +# +# where 0 is the unique instance name for the output_pin_binding object within the +# same alsaconf node. + +Class.Base."output_pin_binding" { + + DefineAttribute."instance" {} + + # The widget name that the output pin should be bound with. + DefineAttribute."output_pin_binding_name" { + token_ref "comp.string" + } + + attributes { + !constructor [ + "instance" + ] + + !mandatory [ + "output_pin_binding_name" + ] + # + # id attribute values for pin_binding_widget objects must be unique in the + # same alsaconf node + # + unique "instance" + } +} diff --git a/tools/topology/topology2/include/common/pcm.conf b/tools/topology/topology2/include/common/pcm.conf new file mode 100644 index 000000000000..ba014d084bee --- /dev/null +++ b/tools/topology/topology2/include/common/pcm.conf @@ -0,0 +1,75 @@ +# +# PCM Class definition. All attributes defined herein are namespaced +# by alsatplg to "Object.PCM.pcm.N.attribute_name". +# +# Usage: PCM object can be instantiated as: +# +# Object.PCM.pcm."N" { +# id 2 +# pcm_name "Headset" +# direction "playback" +# } +# +# where N is the unique instance number for the PCM object within the same alsaconf node. + +Class.PCM."pcm" { + + # PCM name + DefineAttribute."name" {} + + DefineAttribute."instance" {} + + # PCM id + DefineAttribute."id" {} + + DefineAttribute."direction" { + constraints { + !valid_values [ + "playback" + "capture" + "duplex" + ] + } + } + + DefineAttribute."compress" {} + + DefineAttribute."playback_compatible_d0i3" { + # Token reference and type + token_ref "stream.bool" + } + + DefineAttribute."capture_compatible_d0i3" { + # Token reference and type + token_ref "stream.bool" + } + + DefineAttribute."playback_pause_supported" { + # Token reference and type + token_ref "stream.bool" + } + + DefineAttribute."capture_pause_supported" { + # Token reference and type + token_ref "stream.bool" + } + + attributes { + !constructor [ + "name" + "id" + "direction" + ] + + # + # pcm objects instantiated within the same alsaconf node must have unique + # id attribute + # + unique "instance" + } + + # Default values for PCM attributes + compress "false" + playback_pause_supported "false" + capture_pause_supported "false" +} diff --git a/tools/topology/topology2/include/common/pcm_caps.conf b/tools/topology/topology2/include/common/pcm_caps.conf new file mode 100644 index 000000000000..b59f875df547 --- /dev/null +++ b/tools/topology/topology2/include/common/pcm_caps.conf @@ -0,0 +1,94 @@ +# +# PCM Capabilities Class definition. All attributes defined herein are +# namespaced by alsatplg to "Object.PCM.pcm_caps.instance.attribute_name". +# +# Usage: PCM object can be instantiated as: +# +# Object.PCM.pcm_caps.1 { +# name "Headset" +# direction "playback" +# formats "S32_LE,S24_LE,S16_LE" +# rate_min 48000 +# rate_max 48000 +# channels_min 2 +# channels_max 2 +# periods_min 2 +# } +# +# where DIRECTION is the unique stream direction for the pcm_caps object within +# the same alsaconf node (normally, pcm object). + +Class.PCM."pcm_caps" { + + DefineAttribute."instance" {} + + # + # Argument used to construct PCM Capabilities + # + DefineAttribute."name" { + type "string" + } + + DefineAttribute."direction" { + type "string" + !valid_values [ + playback + capture + ] + } + + DefineAttribute."formats" { + type "string" + } + + DefineAttribute."rates" { + type "string" + } + + DefineAttribute."sigbits" {} + + DefineAttribute."rate_min" {} + + DefineAttribute."rate_max" {} + + DefineAttribute."channels_min" {} + + DefineAttribute."channels_max" {} + + DefineAttribute."periods_min" {} + + DefineAttribute."periods_max" {} + + DefineAttribute."period_size_min" {} + + DefineAttribute."period_size_max" {} + + DefineAttribute."buffer_size_min" {} + + DefineAttribute."buffer_size_max" {} + + attributes { + !constructor [ + "name" + "direction" + ] + + # + # pcm_caps objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for PCM capabilities + formats "S32_LE,S24_LE,S16_LE" + rates "48000" + periods_min 2 + periods_max 256 + channels_min 2 + channels_max 2 + period_size_min 192 # "$[((2 * $channels_min) * 48000) / 1000]" (48K, S16_LE, 1ms) + period_size_max 2097152 # Large enough to cover user's needs + buffer_size_min 384 # "$[$period_size_min * $periods_min]" + buffer_size_max 4194304 # "$[2 * $period_size_max]" +} diff --git a/tools/topology/topology2/include/common/route.conf b/tools/topology/topology2/include/common/route.conf new file mode 100644 index 000000000000..efd8adf0a516 --- /dev/null +++ b/tools/topology/topology2/include/common/route.conf @@ -0,0 +1,51 @@ +# Class definition for DAPM graph route objects +# These are instantiated as follows: +# Example: +# Object.Base.route."N" { +# source "Object.SSP.1.dai.capture" +# sink "Object.Widget.buffer.2.0" +# } +# +# The above object specifies a DAPM graph route: +# "SSP.1 capture DAI widget -> buffer.2.0 " +# where N is the unique instance of the route object in the same alsaconf node +# +Class.Base."route" { + # sink widget name + DefineAttribute."sink" { + type "string" + } + + # source widget name for route + DefineAttribute."source" { + type "string" + } + + # control name for the route + DefineAttribute."control" { + type "string" + } + + # + # Pipeline ID of the pipeline the route object belongs to + # + DefineAttribute."index" {} + + # unique instance for route object in the same alsaconf node + DefineAttribute."instance" {} + + attributes { + !constructor [ + "instance" + ] + !mandatory [ + "source" + "sink" + ] + # + # route objects instantiated within the same alsaconf node must have unique + # index attribute + # + unique "instance" + } +} diff --git a/tools/topology/topology2/include/common/tokens.conf b/tools/topology/topology2/include/common/tokens.conf new file mode 100644 index 000000000000..48b498280130 --- /dev/null +++ b/tools/topology/topology2/include/common/tokens.conf @@ -0,0 +1,197 @@ +# +# Vendor token objects with token values used for adding tuple pairs to an object's private data +# + +Object.Base.VendorToken { + "1" { + name "comp" + 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 + core_id 404 + uuid 405 + # Tokens added with ABI 4.0 + cpc 406 + is_pages 409 + num_audio_formats 410 #deprecated + num_input_pins 411 + num_output_pins 412 + # The token for input/output pin binding, it specifies + # the widget name that the queue is connected from/to. + input_pin_binding_name 413 + output_pin_binding_name 414 + num_input_audio_formats 415 + num_output_audio_formats 416 + no_wname_in_kcontrol_name 417 + scheduler_domain 418 + domain_id 419 + stack_bytes_requirement 420 + interim_heap_bytes_requirement 421 + lifetime_heap_bytes_requirement 422 + shared_bytes_requirement 423 + } + + "2" { + name "dai" + # Token retired with ABI 3.2, do not use for new capabilities + dmac_config 153 + dai_type 154 + dai_index 155 + direction 156 + } + + "3" { + name "buffer" + size 100 + caps 101 + } + + "4" { + name "volume" + ramp_step_type 250 + ramp_step_ms 251 + } + + "5" { + name "gain" + curve_type 260 + curve_duration 261 + init_value 262 + } + + "6" { + name "src" + rate_in 300 + rate_out 301 + } + + "7" { + name "asrc" + rate_out 321 + operation_mode 323 + } + + "8" { + name "scheduler" + period 200 + priority 201 + mips 202 + core 203 + frames 204 + time_domain 205 + dynamic_pipeline 206 + # ABI 4.0 onwards + lp_mode 207 + use_chain_dma 209 + kcps 210 + direction 211 + direction_valid 212 + } + + "9" { + name "intel_ssp" + clks_control 500 + mclk_id 501 + sample_bits 502 + frame_pulse_width 503 + quirks 504 + tdm_padding_per_slot 505 + bclk_delay 506 + } + + "10" { + name "intel_dmic" + driver_version 600 + clk_min 601 + clk_max 602 + duty_min 603 + duty_max 604 + num_pdm_active 605 + sample_rate 608 + fifo_word_length 609 + unmute_ramp_time_ms 610 + + + } + + "11" { + name "intel_dmic_pdm" + ctrl_id 700 + mic_a_enable 701 + mic_b_enable 702 + polarity_a 703 + polarity_b 704 + clk_edge 705 + skew 706 + + } + + "12" { + name "nxp_sai" + mclk_id 1000 + } + + "13" { + name "stream" + playback_compatible_d0i3 1200 + capture_compatible_d0i3 1201 + playback_pause_supported 1202 + capture_pause_supported 1203 + } + + "14" { + name "mute_led" + mute_led_use 1300 + mute_led_direction 1301 + } + + "15" { + name "alh" + rate 1400 + channels 1401 + } + + "16" { + name "mixinout" + mix_type 1700 + } + + # ABI 4.0 onwards + "17" { + name "cavs_audio_format" + in_rate 1900 + in_bit_depth 1901 + in_valid_bit_depth 1902 + in_channels 1903 + in_ch_map 1904 + in_ch_cfg 1905 + in_interleaving_style 1906 + in_fmt_cfg 1907 + in_sample_type 1908 + input_pin_index 1909 + # tokens up to 1929 reserved for future use + out_rate 1930 + out_bit_depth 1931 + out_valid_bit_depth 1932 + out_channels 1933 + out_ch_map 1934 + out_ch_cfg 1935 + 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 + dma_buffer_size 1972 #deprecated + } + + # ABI 4.0 onwards + "18" { + name "copier" + node_type 1980 + deep_buffer_dma_ms 1981 + } +} diff --git a/tools/topology/topology2/include/common/vendor-token.conf b/tools/topology/topology2/include/common/vendor-token.conf new file mode 100644 index 000000000000..65ac4ab940c2 --- /dev/null +++ b/tools/topology/topology2/include/common/vendor-token.conf @@ -0,0 +1,39 @@ +# +# vendortoken class definition component. All attributes defined herein are namespaced +# by alsatplg to "Object.Base.VendorTokem.name.token_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Base.VendorToken. "comp" { +# # Token retired with ABI 3.2, do not use for new capabilities +# preload_count 403 +# core_id 404 +# uuid 405 +# } +# + +Class.Base.VendorToken { + DefineAttribute."instance" {} + + # + # name for the vendortoken object + # + DefineAttribute."name" { + type "string" + } + + attributes { + # + # VendorToken object names are constructed as VendorToken.<name> + # + !constructor [ + "name" + ] + + # + # instance attribute values for VendorToken objects must be unique in the same alsaconf + # node + # + unique "instance" + } +} 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..7dddafe8d024 --- /dev/null +++ b/tools/topology/topology2/include/components/alh-dai-copier.conf @@ -0,0 +1,133 @@ +# +# 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 "dai.word" + } + + # + # alh-copier object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke Attribute Definitions for alh-copier + # + + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + } + + DefineAttribute."direction" { + type "string" + token_ref "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 "comp.word" + } + + DefineAttribute."bss_size" {} + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."node_type" { + # Token set reference name and type + token_ref "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" + 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/aria.conf b/tools/topology/topology2/include/components/aria.conf new file mode 100644 index 000000000000..fe34b5cd5070 --- /dev/null +++ b/tools/topology/topology2/include/components/aria.conf @@ -0,0 +1,99 @@ +# +# Aria widget +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Widget.aria.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.aria."N" { +# index 1 +# type "effect" +# } +# +# Where N is the unique instance number for the aria object within the same alsaconf node. + +Class.Widget."aria" { + # + # Pipeline ID for the aria widget object + # + DefineAttribute."index" {} + + #include common component definition + <include/components/widget-common.conf> + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + Object.Control.bytes."1" { + !access [ + tlv_read + tlv_callback + ] + Object.Base.extops.1 { + name "extctl" + get 258 + put 0 + } + max 4096 + } + + # Attribute categories + attributes { + # + # The aria widget name would be constructed using the index and instance attributes. + # For ex: "aria.1.1" or "aria.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "type" + "uuid" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + # + # aria widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for aria widget + + uuid "6d:16:f7:99:2c:37:ef:43:81:f6:22:00:7a:a1:5f:03" + type "effect" + no_pm "true" + cpc 5000 + is_pages 1 + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/aria/param_1.conf b/tools/topology/topology2/include/components/aria/param_1.conf new file mode 100644 index 000000000000..bfec76526ca6 --- /dev/null +++ b/tools/topology/topology2/include/components/aria/param_1.conf @@ -0,0 +1,10 @@ +# Exported with script sof_aria_blobs.m 24-Oct-2024 +# cd tools/tune/aria; octave sof_aria_blobs.m +Object.Base.data."aria_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/aria/param_2.conf b/tools/topology/topology2/include/components/aria/param_2.conf new file mode 100644 index 000000000000..8cb11358a44b --- /dev/null +++ b/tools/topology/topology2/include/components/aria/param_2.conf @@ -0,0 +1,10 @@ +# Exported with script sof_aria_blobs.m 24-Oct-2024 +# cd tools/tune/aria; octave sof_aria_blobs.m +Object.Base.data."aria_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/aria/param_3.conf b/tools/topology/topology2/include/components/aria/param_3.conf new file mode 100644 index 000000000000..c5cbfa30cb93 --- /dev/null +++ b/tools/topology/topology2/include/components/aria/param_3.conf @@ -0,0 +1,10 @@ +# Exported with script sof_aria_blobs.m 24-Oct-2024 +# cd tools/tune/aria; octave sof_aria_blobs.m +Object.Base.data."aria_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/aria/passthrough.conf b/tools/topology/topology2/include/components/aria/passthrough.conf new file mode 100644 index 000000000000..1fe0ff71adf0 --- /dev/null +++ b/tools/topology/topology2/include/components/aria/passthrough.conf @@ -0,0 +1,10 @@ +# Exported with script sof_aria_blobs.m 24-Oct-2024 +# cd tools/tune/aria; octave sof_aria_blobs.m +Object.Base.data."aria_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/asrc.conf b/tools/topology/topology2/include/components/asrc.conf new file mode 100644 index 000000000000..5ea82b0e7882 --- /dev/null +++ b/tools/topology/topology2/include/components/asrc.conf @@ -0,0 +1,89 @@ +# +# +# A generic ASRC component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.asrc.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.asrc."N" { +# format "s24le" +# rate_out 48000 +# operation_mode 0 +# } +# +# Where N is the unique instance number for the src widget within the same alsaconf node. + +Class.Widget."asrc" { + # + # Pipeline ID for the src widget object + # + DefineAttribute."index" {} + + # + # ASRC object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke attributes for ASRC + # + + # Target sample rate + DefineAttribute."rate_out" { + # Token set reference name and type + token_ref "asrc.word" + } + + DefineAttribute."operation_mode" { + # Token set reference name and type + token_ref "asrc.word" + } + + attributes { + # + # The ASRC widget name would be constructed using the index and instance attributes. + # For ex: "asrc.1.1" or "asrc.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + !mandatory [ + "operation_mode" + "num_input_audio_formats" + "num_output_audio_formats" + "num_input_pins" + "num_output_pins" + ] + + # + # 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" + ] + + unique "instance" + } + + # + # Default attributes for asrc + # + type "asrc" + uuid "2d:40:b4:66:68:b4:f2:42:81:a7:b3:71:21:86:3d:d4" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/buffer.conf b/tools/topology/topology2/include/components/buffer.conf new file mode 100644 index 000000000000..32dfcebd29f8 --- /dev/null +++ b/tools/topology/topology2/include/components/buffer.conf @@ -0,0 +1,128 @@ +# Common pipeline buffer +# +# A generic buffer component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.buffer.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.buffer."N" { +# index 1 +# caps "host" +# periods 2 +# } +# +# Where N is the unique instance number for the buffer object within the same alsaconf node. + +Class.Widget."buffer" { + # + # Pipeline ID for the buffer object + # + DefineAttribute."index" {} + + # + # Buffer object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke Attribute Definitions for Buffers + # + + # + # Buffer size in bytes. Will be calculated based on pipeline parameters in which the + # buffer object belongs + # + DefineAttribute."size" { + # Token reference and type + token_ref "buffer.word" + } + + # Number of periods + DefineAttribute."periods" {} + + # Number of channels + DefineAttribute."channels" {} + + # + # Buffer memory capabilities. The values provided will be translated to integer values + # specified in the tuple_values array + # For example: "dai" will be translated to 113 and added to the buffer widget's private data. + DefineAttribute."caps" { + type "string" + # Token reference and type + token_ref "buffer.word" + constraints { + !valid_values [ + "dai" + "host" + "pass" + "comp" + ] + !tuple_values [ + 113 + 113 + 113 + 65 + ] + } + } + + # Attribute categories + attributes { + # + # The buffer widget name would be constructed using the index and instance attributes. + # For ex: "buffer.1.1" or "buffer.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the buffer class is instantiated + # + !mandatory [ + "periods" + "caps" + "channels" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + "type" + ] + + # + # size attribute value for buffer objects is computed in the compiler + # + !automatic [ + "size" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + # + # buffer widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # + # Default attribute values for buffer objects + # + type "buffer" + uuid "92:4c:54:42:92:8e:41:4e:b6:79:34:51:9f:1c:1d:28" + no_pm "true" +} diff --git a/tools/topology/topology2/include/components/crossover.conf b/tools/topology/topology2/include/components/crossover.conf new file mode 100644 index 000000000000..e3e02ec83152 --- /dev/null +++ b/tools/topology/topology2/include/components/crossover.conf @@ -0,0 +1,63 @@ +# +# +# A generic crossover component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.crossover.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.crossover."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."crossover" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for CROSSOVER widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for crossover + # + uuid "d1:9a:8c:94:6a:80:31:41:ad:6c:b2:bd:a9:e3:5a:9f" + type "effect" + no_pm "true" + num_input_pins 1 +} diff --git a/tools/topology/topology2/include/components/crossover/coef_2way_48000_200_0_1.conf b/tools/topology/topology2/include/components/crossover/coef_2way_48000_200_0_1.conf new file mode 100644 index 000000000000..ed944f1b56d5 --- /dev/null +++ b/tools/topology/topology2/include/components/crossover/coef_2way_48000_200_0_1.conf @@ -0,0 +1,20 @@ +# Exported Control Bytes 28-Jul-2023 +Object.Base.data."crossover_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x60,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d, + 0x95,0xc1,0x02,0x00,0x2a,0x83,0x05,0x00, + 0x95,0xc1,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2, + 0x3e,0x77,0xa1,0x7d,0x34,0x7d,0xd3,0x3e, + 0x99,0x05,0x59,0x82,0x34,0x7d,0xd3,0x3e, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/crossover/coef_3way_48000_200_1000_0_1_2.conf b/tools/topology/topology2/include/components/crossover/coef_3way_48000_200_1000_0_1_2.conf new file mode 100644 index 000000000000..5d2058643f44 --- /dev/null +++ b/tools/topology/topology2/include/components/crossover/coef_3way_48000_200_1000_0_1_2.conf @@ -0,0 +1,34 @@ +# Exported Control Bytes 28-Jul-2023 +Object.Base.data."crossover_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xd0,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd0,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d, + 0x95,0xc1,0x02,0x00,0x2a,0x83,0x05,0x00, + 0x95,0xc1,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2, + 0x3e,0x77,0xa1,0x7d,0x34,0x7d,0xd3,0x3e, + 0x99,0x05,0x59,0x82,0x34,0x7d,0xd3,0x3e, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xef,0xcd,0xd0,0xca,0x5d,0x8c,0x2e,0x74, + 0x6d,0x29,0x40,0x00,0xda,0x52,0x80,0x00, + 0x6d,0x29,0x40,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0xef,0xcd,0xd0,0xca, + 0x5d,0x8c,0x2e,0x74,0x9c,0x6f,0x57,0x3a, + 0xc9,0x20,0x51,0x8b,0x9c,0x6f,0x57,0x3a, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xef,0xcd,0xd0,0xca,0x5d,0x8c,0x2e,0x74, + 0x6d,0x29,0x40,0x00,0xda,0x52,0x80,0x00, + 0x6d,0x29,0x40,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0xef,0xcd,0xd0,0xca, + 0x5d,0x8c,0x2e,0x74,0x9c,0x6f,0x57,0x3a, + 0xc9,0x20,0x51,0x8b,0x9c,0x6f,0x57,0x3a, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/crossover/coef_4way_48000_200_1000_3000_0_1_2_3.conf b/tools/topology/topology2/include/components/crossover/coef_4way_48000_200_1000_3000_0_1_2_3.conf new file mode 100644 index 000000000000..abe3519464ac --- /dev/null +++ b/tools/topology/topology2/include/components/crossover/coef_4way_48000_200_1000_3000_0_1_2_3.conf @@ -0,0 +1,34 @@ +# Exported Control Bytes 28-Jul-2023 +Object.Base.data."crossover_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xd0,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd0,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d, + 0x95,0xc1,0x02,0x00,0x2a,0x83,0x05,0x00, + 0x95,0xc1,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2, + 0x3e,0x77,0xa1,0x7d,0x34,0x7d,0xd3,0x3e, + 0x99,0x05,0x59,0x82,0x34,0x7d,0xd3,0x3e, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xef,0xcd,0xd0,0xca,0x5d,0x8c,0x2e,0x74, + 0x6d,0x29,0x40,0x00,0xda,0x52,0x80,0x00, + 0x6d,0x29,0x40,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0xef,0xcd,0xd0,0xca, + 0x5d,0x8c,0x2e,0x74,0x9c,0x6f,0x57,0x3a, + 0xc9,0x20,0x51,0x8b,0x9c,0x6f,0x57,0x3a, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xd0,0x91,0x42,0xdb,0xb1,0x53,0x12,0x5d, + 0xa0,0xc6,0xea,0x01,0x3f,0x8d,0xd5,0x03, + 0xa0,0xc6,0xea,0x01,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0xd0,0x91,0x42,0xdb, + 0xb1,0x53,0x12,0x5d,0x78,0xf0,0x73,0x30, + 0x10,0x1f,0x18,0x9f,0x78,0xf0,0x73,0x30, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/ctc.conf b/tools/topology/topology2/include/components/ctc.conf new file mode 100644 index 000000000000..7c62d525da35 --- /dev/null +++ b/tools/topology/topology2/include/components/ctc.conf @@ -0,0 +1,101 @@ +# +# Common widget ctc +# +# A generic ctc widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.ctc.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.ctc."N" { +# index 1 +# type "effect" +# } +# +# Where N is the unique instance number for the parent object. + +Class.Widget."ctc" { + # + # Pipeline ID for the CTC widget object + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for CTC widget + # + DefineAttribute."instance" { + type "integer" + } + + #include common component definition + <include/components/widget-common.conf> + + # Attribute categories + attributes { + # + # The CTC widget name would be constructed using the index and instance attributes. + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "uuid" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # 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" + ] + + # + # DTS widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # + # ctc widget switch control + # + Object.Control { + mixer."1" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + } + + # Default attribute values for CTC widget + uuid "bc:1b:0e:bf:6a:dc:fe:45:bc:90:25:54:cb:13:7a:b4" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/dai-copier.conf b/tools/topology/topology2/include/components/dai-copier.conf new file mode 100644 index 000000000000..e5508ada3df5 --- /dev/null +++ b/tools/topology/topology2/include/components/dai-copier.conf @@ -0,0 +1,171 @@ +# +# DAI gateway copier +# +# A DAI copier widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.dai-copier.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.dai-copier."N" { +# copier_type "DMIC" +# cpc 100000 +# } +# +# Where N is the unique instance number for the dai-copier object within the same alsaconf node. + +Class.Widget."dai-copier" { + # + # Pipeline ID for the dai-copier object + # + DefineAttribute."index" {} + + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + # + # dai-copier object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke Attribute Definitions for dai-copier + # + + # + # dai-copier type in pipeline. + # + DefineAttribute."copier_type" { + constraints { + !valid_values [ + "HDA" + "SSP" + "DMIC" + "SAI" + ] + } + } + + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + constraints { + !valid_values [ + "SSP" + "DMIC" + "HDA" + "SAI" + ] + } + } + + DefineAttribute."direction" { + type "string" + token_ref "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 "comp.word" + } + + DefineAttribute."bss_size" {} + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."node_type" { + # Token set reference name and type + token_ref "copier.word" + constraints { + !valid_values [ + $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 <-) + $IPC_OUTPUT_CLASS # IPC output (DSP ->) + $IPC_INPUT_CLASS # IPC input (DSP <-) + $I2S_MULTILINK_OUTPUT_CLASS # I2S Multi gtw output (DSP ->) + $I2S_MULTILINKI_NPUT_CLASS # I2S Multi gtw input (DSP <-) + $GPIO_CLASS # GPIO + $SPI_OUTPUT_CLASS # SPI Output (DSP ->) + $SPI_INPUT_CLASS # SPI Input (DSP <-) + ] + } + } + + attributes { + # + # The dai-copier widget name would be constructed using the dai-copier type, index + # and instance attributes. For ex: "dai-copier.SSP.0.1". + # + !constructor [ + "copier_type" + "stream_name" + "direction" + ] + + # + # mandatory attributes that must be provided when the buffer class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "copier_type" + "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" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + unique "instance" + } + + # + # Default attributes for dai-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" + 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/dai.conf b/tools/topology/topology2/include/components/dai.conf new file mode 100644 index 000000000000..4a34594b5eb0 --- /dev/null +++ b/tools/topology/topology2/include/components/dai.conf @@ -0,0 +1,125 @@ +# +# A generic dai widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.dai.N.attribute_name" +# +# For playback +# Object.Widget.dai."playback" { +# dai_type SSP +# index 1 +# type dai_in +# } +# +# For Capture +# Object.Widget.dai."capture" { +# dai_type SSP +# index 2 +# type dai_out +# } +# + +Class.Widget."dai" { + # Type of DAI + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + constraints { + !valid_values [ + "SSP" + "DMIC" + "HDA" + "ALH" + "SAI" + "ESAI" + ] + } + } + + DefineAttribute."instance" {} + + # DAI Index in the firmware + DefineAttribute."dai_index" { + # Token reference and type + token_ref "dai.word" + } + + # + # DAI direction. The string values will be converted to 0/1 and added as tuple data + # + DefineAttribute."direction" { + type "string" + token_ref "dai.word" + constraints { + !valid_values [ + "playback" + "capture" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + # include common widget attribute definitions + <include/components/widget-common.conf> + + # + # Pipeline ID that the dai widget belongs to + # + DefineAttribute."index" {} + + # Bespoke attributes for DAI + DefineAttribute."format" { + type "string" + # Token reference and type + token_ref "comp.string" + } + + # Attribute categories + attributes { + # + # The DAI widget name would be constructed using the dai_type, index and direction + # attributes. For ex: "dai.SSP.1.capture" or "dai.ALH.2.playback" etc. + # + !constructor [ + "dai_type" + "dai_index" + "direction" + ] + + # + # mandatory attributes that must be provided when the dai widget class is instantiated + # + !mandatory [ + "type" + "stream_name" + "format" + "index" + "format" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + # + # dai widget objects instantiated within the same alsaconf node must have unique + # direction attribute + # + unique "instance" + } + + # Default attribute values for DAI widget + uuid "27:0d:b0:c2:bc:ff:50:41:a5:1a:24:5c:79:c5:e5:4b" + no_pm "true" +} diff --git a/tools/topology/topology2/include/components/dax/default.conf b/tools/topology/topology2/include/components/dax/default.conf new file mode 100644 index 000000000000..944157bb59c1 --- /dev/null +++ b/tools/topology/topology2/include/components/dax/default.conf @@ -0,0 +1,830 @@ +Object.Base.data."dolby_data" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0xb4,0x19,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x27,0x10,0x00,0x08,0x78,0x19,0x00,0x00, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x28,0x10,0x00,0x08,0x54,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0xeb,0x08,0x01,0x00, + 0xac,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe6,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0xe5,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xe8,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0xe9,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x40,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x42,0x07,0x01,0x00, + 0x28,0x00,0x00,0x00,0x67,0x00,0x00,0x00, + 0x38,0x7f,0x00,0x00,0x9c,0x2b,0x00,0x00, + 0xe2,0x13,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x4c,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x4b,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x2d,0x00,0x00,0x00,0x29,0x10,0x00,0x08, + 0x90,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0xea,0x08,0x01,0x00,0xac,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x9d,0x00,0x00,0x00, + 0xa7,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xcb,0x00,0x00,0x00, + 0xbc,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xcd,0x00,0x00,0x00, + 0xd5,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xd1,0x00,0x00,0x00,0xc1,0x00,0x00,0x00, + 0x9f,0x00,0x00,0x00,0x86,0x00,0x00,0x00, + 0x61,0x00,0x00,0x00,0x47,0x00,0x00,0x00, + 0x16,0x00,0x00,0x00,0xa6,0xff,0xff,0xff, + 0xe5,0xfe,0xff,0xff,0x43,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x6a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x68,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe7,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x38,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x39,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x3a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x01,0x00,0x00,0x36,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xe4,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x3c,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x3d,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3e,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x3f,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x48,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x76,0x74,0x6c,0x65, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x44,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x29,0x10,0x00,0x08, + 0x90,0x01,0x00,0x00,0x01,0x00,0x00,0x00, + 0xea,0x08,0x01,0x00,0xac,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x9d,0x00,0x00,0x00, + 0xa7,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xcb,0x00,0x00,0x00, + 0xbc,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xcd,0x00,0x00,0x00, + 0xd5,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xd1,0x00,0x00,0x00,0xc1,0x00,0x00,0x00, + 0x9f,0x00,0x00,0x00,0x86,0x00,0x00,0x00, + 0x61,0x00,0x00,0x00,0x47,0x00,0x00,0x00, + 0x16,0x00,0x00,0x00,0xa6,0xff,0xff,0xff, + 0xe5,0xfe,0xff,0xff,0x43,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x6a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x68,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe7,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x38,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x39,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x3a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x01,0x00,0x00,0x36,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xe4,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x3c,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x3d,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3e,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x3f,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x48,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x76,0x74,0x6c,0x65, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x44,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x28,0x10,0x00,0x08, + 0x54,0x04,0x00,0x00,0x01,0x00,0x00,0x00, + 0xeb,0x08,0x01,0x00,0xac,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe6,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe5,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe8,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x42,0x07,0x01,0x00,0x28,0x00,0x00,0x00, + 0x67,0x00,0x00,0x00,0x38,0x7f,0x00,0x00, + 0x9c,0x2b,0x00,0x00,0xe2,0x13,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x4c,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4b,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x2d,0x00,0x00,0x00, + 0x29,0x10,0x00,0x08,0x90,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0xea,0x08,0x01,0x00, + 0xac,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x9d,0x00,0x00,0x00,0xa7,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xcb,0x00,0x00,0x00,0xbc,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xcd,0x00,0x00,0x00,0xd5,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xd1,0x00,0x00,0x00, + 0xc1,0x00,0x00,0x00,0x9f,0x00,0x00,0x00, + 0x86,0x00,0x00,0x00,0x61,0x00,0x00,0x00, + 0x47,0x00,0x00,0x00,0x16,0x00,0x00,0x00, + 0xa6,0xff,0xff,0xff,0xe5,0xfe,0xff,0xff, + 0x43,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x06,0x00,0x00,0x00, + 0x68,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe7,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x38,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x39,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x3a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x01,0x00,0x00, + 0x36,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0xe4,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x57,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x3c,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x3d,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3e,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x3f,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x48,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x76,0x74,0x6c,0x65,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x44,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x29,0x10,0x00,0x08,0x90,0x01,0x00,0x00, + 0x01,0x00,0x00,0x00,0xea,0x08,0x01,0x00, + 0xac,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x9d,0x00,0x00,0x00,0xa7,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xcb,0x00,0x00,0x00,0xbc,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xcd,0x00,0x00,0x00,0xd5,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xd1,0x00,0x00,0x00, + 0xc1,0x00,0x00,0x00,0x9f,0x00,0x00,0x00, + 0x86,0x00,0x00,0x00,0x61,0x00,0x00,0x00, + 0x47,0x00,0x00,0x00,0x16,0x00,0x00,0x00, + 0xa6,0xff,0xff,0xff,0xe5,0xfe,0xff,0xff, + 0x43,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x06,0x00,0x00,0x00, + 0x68,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe7,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x38,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x39,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x3a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x01,0x00,0x00, + 0x36,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0xe4,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x57,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x3c,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x3d,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3e,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x3f,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x48,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x76,0x74,0x6c,0x65,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x44,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x28,0x10,0x00,0x08,0x54,0x04,0x00,0x00, + 0x02,0x00,0x00,0x00,0xeb,0x08,0x01,0x00, + 0xac,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe6,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe5,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe8,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe9,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x42,0x07,0x01,0x00, + 0x28,0x00,0x00,0x00,0x67,0x00,0x00,0x00, + 0x38,0x7f,0x00,0x00,0x9c,0x2b,0x00,0x00, + 0xe2,0x13,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x4c,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x4b,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x2d,0x00,0x00,0x00,0x29,0x10,0x00,0x08, + 0x90,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0xea,0x08,0x01,0x00,0xac,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x9d,0x00,0x00,0x00, + 0xa7,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xcb,0x00,0x00,0x00, + 0xbc,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xcd,0x00,0x00,0x00, + 0xd5,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xd1,0x00,0x00,0x00,0xc1,0x00,0x00,0x00, + 0x9f,0x00,0x00,0x00,0x86,0x00,0x00,0x00, + 0x61,0x00,0x00,0x00,0x47,0x00,0x00,0x00, + 0x16,0x00,0x00,0x00,0xa6,0xff,0xff,0xff, + 0xe5,0xfe,0xff,0xff,0x43,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x6a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x68,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe7,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x38,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x39,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x3a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x01,0x00,0x00,0x36,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xe4,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x3c,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x3d,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3e,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x3f,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x48,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x76,0x74,0x6c,0x65, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x44,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x29,0x10,0x00,0x08, + 0x90,0x01,0x00,0x00,0x01,0x00,0x00,0x00, + 0xea,0x08,0x01,0x00,0xac,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x9d,0x00,0x00,0x00, + 0xa7,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xcb,0x00,0x00,0x00, + 0xbc,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xcd,0x00,0x00,0x00, + 0xd5,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xd1,0x00,0x00,0x00,0xc1,0x00,0x00,0x00, + 0x9f,0x00,0x00,0x00,0x86,0x00,0x00,0x00, + 0x61,0x00,0x00,0x00,0x47,0x00,0x00,0x00, + 0x16,0x00,0x00,0x00,0xa6,0xff,0xff,0xff, + 0xe5,0xfe,0xff,0xff,0x43,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x6a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x68,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe7,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x38,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x39,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x3a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x01,0x00,0x00,0x36,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xe4,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x3c,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x3d,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3e,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x3f,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x48,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x76,0x74,0x6c,0x65, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x44,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x28,0x10,0x00,0x08, + 0x54,0x04,0x00,0x00,0x03,0x00,0x00,0x00, + 0xeb,0x08,0x01,0x00,0xac,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe6,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe5,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe8,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe9,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x42,0x07,0x01,0x00,0x28,0x00,0x00,0x00, + 0x23,0x00,0x00,0x00,0xff,0x7f,0x00,0x00, + 0xff,0x7f,0x00,0x00,0xff,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x4c,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4b,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x2d,0x00,0x00,0x00, + 0x29,0x10,0x00,0x08,0x90,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0xea,0x08,0x01,0x00, + 0xac,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x9d,0x00,0x00,0x00,0xa7,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xcb,0x00,0x00,0x00,0xbc,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xcd,0x00,0x00,0x00,0xd5,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xd1,0x00,0x00,0x00, + 0xc1,0x00,0x00,0x00,0x9f,0x00,0x00,0x00, + 0x86,0x00,0x00,0x00,0x61,0x00,0x00,0x00, + 0x47,0x00,0x00,0x00,0x16,0x00,0x00,0x00, + 0xa6,0xff,0xff,0xff,0xe5,0xfe,0xff,0xff, + 0x43,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x06,0x00,0x00,0x00, + 0x68,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe7,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x38,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x39,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x08,0x00,0x00,0x00, + 0x3a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x01,0x00,0x00, + 0x36,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0xe4,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x57,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x3c,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x3d,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3e,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x3f,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x48,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x76,0x74,0x6c,0x65,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x44,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x29,0x10,0x00,0x08,0x90,0x01,0x00,0x00, + 0x01,0x00,0x00,0x00,0xea,0x08,0x01,0x00, + 0xac,0x00,0x00,0x00,0x14,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x9d,0x00,0x00,0x00,0xa7,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0xcb,0x00,0x00,0x00,0xbc,0x00,0x00,0x00, + 0xc0,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, + 0xcd,0x00,0x00,0x00,0xd5,0x00,0x00,0x00, + 0xda,0x00,0x00,0x00,0xd1,0x00,0x00,0x00, + 0xc1,0x00,0x00,0x00,0x9f,0x00,0x00,0x00, + 0x86,0x00,0x00,0x00,0x61,0x00,0x00,0x00, + 0x47,0x00,0x00,0x00,0x16,0x00,0x00,0x00, + 0xa6,0xff,0xff,0xff,0xe5,0xfe,0xff,0xff, + 0x43,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x06,0x00,0x00,0x00, + 0x68,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe7,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x38,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x39,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x08,0x00,0x00,0x00, + 0x3a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x01,0x00,0x00, + 0x36,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0xe4,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x57,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x3c,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x3d,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3e,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0x3f,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0x48,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x76,0x74,0x6c,0x65,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x44,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x30,0x10,0x00,0x08,0xb0,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x08,0x01,0x00,0x00,0x01,0x00,0x00, + 0x14,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf5,0x08,0x01,0x00,0x4c,0x01,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xed,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x4a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x49,0x07,0x01,0x00, + 0x28,0x00,0x00,0x00,0x67,0x00,0x00,0x00, + 0x38,0x7f,0x00,0x00,0x2a,0x1a,0x00,0x00, + 0xe2,0x13,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x64,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x65,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x0c,0x00,0x00,0x00,0xf6,0x08,0x01,0x00, + 0x1c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00, + 0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00, + 0x63,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x10,0x00,0x00,0x00,0x5b,0x07,0x01,0x00, + 0x48,0x01,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc0,0xf9,0xff,0xff,0x00,0x00,0x00,0x00, + 0xa0,0xfb,0xff,0xff,0x70,0xfe,0xff,0xff, + 0x10,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xe1,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0xe3,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x0a,0x00,0x00,0x00,0xe2,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x41,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x59,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x3b,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf4,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xf7,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x5a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x30,0x10,0x00,0x08,0x68,0x03,0x00,0x00, + 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xec,0x08,0x01,0x00,0x00,0x01,0x00,0x00, + 0x14,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x2f,0x00,0x00,0x00,0x8d,0x00,0x00,0x00, + 0xea,0x00,0x00,0x00,0x48,0x01,0x00,0x00, + 0xd5,0x01,0x00,0x00,0x90,0x02,0x00,0x00, + 0x4c,0x03,0x00,0x00,0x07,0x04,0x00,0x00, + 0x21,0x05,0x00,0x00,0x98,0x06,0x00,0x00, + 0xca,0x08,0x00,0x00,0xb8,0x0b,0x00,0x00, + 0xa6,0x0e,0x00,0x00,0x50,0x12,0x00,0x00, + 0xb5,0x16,0x00,0x00,0xd5,0x1b,0x00,0x00, + 0x28,0x23,0x00,0x00,0xf2,0x2b,0x00,0x00, + 0x33,0x36,0x00,0x00,0xe8,0x4c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf5,0x08,0x01,0x00,0x4c,0x01,0x00,0x00, + 0x14,0x00,0x00,0x00,0x2f,0x00,0x00,0x00, + 0x8d,0x00,0x00,0x00,0xea,0x00,0x00,0x00, + 0x48,0x01,0x00,0x00,0xd5,0x01,0x00,0x00, + 0x90,0x02,0x00,0x00,0x4c,0x03,0x00,0x00, + 0x07,0x04,0x00,0x00,0x21,0x05,0x00,0x00, + 0x98,0x06,0x00,0x00,0xca,0x08,0x00,0x00, + 0xb8,0x0b,0x00,0x00,0xa6,0x0e,0x00,0x00, + 0x50,0x12,0x00,0x00,0xb5,0x16,0x00,0x00, + 0xd5,0x1b,0x00,0x00,0x28,0x23,0x00,0x00, + 0xf2,0x2b,0x00,0x00,0x33,0x36,0x00,0x00, + 0xe8,0x4c,0x00,0x00,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x40,0xff,0xff,0xff, + 0x40,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xed,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x4a,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x06,0x00,0x00,0x00,0x49,0x07,0x01,0x00, + 0x28,0x00,0x00,0x00,0x67,0x00,0x00,0x00, + 0x38,0x7f,0x00,0x00,0x2a,0x1a,0x00,0x00, + 0xe2,0x13,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x64,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x65,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x0c,0x00,0x00,0x00,0xf6,0x08,0x01,0x00, + 0x1c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00, + 0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00, + 0x63,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x10,0x00,0x00,0x00,0xe1,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0xe3,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x0a,0x00,0x00,0x00,0xe2,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x41,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0xa0,0x00,0x00,0x00,0x59,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3b,0x07,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf4,0x08,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xf7,0x08,0x01,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5a,0x07,0x01,0x00, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x26,0x10,0x00,0x08,0x0c,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x28,0x10,0x00,0x08, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x32,0x10,0x00,0x08,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x31,0x10,0x00,0x08, + 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x34,0x10,0x00,0x08,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} \ No newline at end of file diff --git a/tools/topology/topology2/include/components/dcblock.conf b/tools/topology/topology2/include/components/dcblock.conf new file mode 100644 index 000000000000..4b0815173db3 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock.conf @@ -0,0 +1,65 @@ +# +# +# A generic dcblock component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.dcblock.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.dcblock."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."dcblock" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for EQ IIR widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for dcblock + # + # b809efaf-5681-42b1-9ed6-04bb012dd384 + uuid "af:ef:09:b8:81:56:b1:42:9e:d6:04:bb:01:2d:d3:84" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/dcblock/100hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/100hz_16khz.conf new file mode 100644 index 000000000000..9bda1ed41447 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/100hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x41,0xe3,0x6f,0x3d,0x41,0xe3,0x6f,0x3d, + 0x41,0xe3,0x6f,0x3d,0x41,0xe3,0x6f,0x3d, + 0x41,0xe3,0x6f,0x3d,0x41,0xe3,0x6f,0x3d, + 0x41,0xe3,0x6f,0x3d,0x41,0xe3,0x6f,0x3d" +} diff --git a/tools/topology/topology2/include/components/dcblock/100hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/100hz_48khz.conf new file mode 100644 index 000000000000..82c09e90b9c3 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/100hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x92,0x20,0x28,0x3f,0x92,0x20,0x28,0x3f, + 0x92,0x20,0x28,0x3f,0x92,0x20,0x28,0x3f, + 0x92,0x20,0x28,0x3f,0x92,0x20,0x28,0x3f, + 0x92,0x20,0x28,0x3f,0x92,0x20,0x28,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/200hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/200hz_16khz.conf new file mode 100644 index 000000000000..cc869bb12fd5 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/200hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x73,0x09,0xc6,0x3a,0x73,0x09,0xc6,0x3a, + 0x73,0x09,0xc6,0x3a,0x73,0x09,0xc6,0x3a, + 0x73,0x09,0xc6,0x3a,0x73,0x09,0xc6,0x3a, + 0x73,0x09,0xc6,0x3a,0x73,0x09,0xc6,0x3a" +} diff --git a/tools/topology/topology2/include/components/dcblock/200hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/200hz_48khz.conf new file mode 100644 index 000000000000..c4c9046f82ea --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/200hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd4,0x6d,0x4d,0x3e,0xd4,0x6d,0x4d,0x3e, + 0xd4,0x6d,0x4d,0x3e,0xd4,0x6d,0x4d,0x3e, + 0xd4,0x6d,0x4d,0x3e,0xd4,0x6d,0x4d,0x3e, + 0xd4,0x6d,0x4d,0x3e,0xd4,0x6d,0x4d,0x3e" +} diff --git a/tools/topology/topology2/include/components/dcblock/20hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/20hz_16khz.conf new file mode 100644 index 000000000000..165ae2968d23 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/20hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7c,0xd0,0x7e,0x3f,0x7c,0xd0,0x7e,0x3f, + 0x7c,0xd0,0x7e,0x3f,0x7c,0xd0,0x7e,0x3f, + 0x7c,0xd0,0x7e,0x3f,0x7c,0xd0,0x7e,0x3f, + 0x7c,0xd0,0x7e,0x3f,0x7c,0xd0,0x7e,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/20hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/20hz_48khz.conf new file mode 100644 index 000000000000..d7b8198218ad --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/20hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf6,0x0c,0xd5,0x3f,0xf6,0x0c,0xd5,0x3f, + 0xf6,0x0c,0xd5,0x3f,0xf6,0x0c,0xd5,0x3f, + 0xf6,0x0c,0xd5,0x3f,0xf6,0x0c,0xd5,0x3f, + 0xf6,0x0c,0xd5,0x3f,0xf6,0x0c,0xd5,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/30hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/30hz_16khz.conf new file mode 100644 index 000000000000..bc5013ac9acd --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/30hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x63,0xd7,0x3d,0x3f,0x63,0xd7,0x3d,0x3f, + 0x63,0xd7,0x3d,0x3f,0x63,0xd7,0x3d,0x3f, + 0x63,0xd7,0x3d,0x3f,0x63,0xd7,0x3d,0x3f, + 0x63,0xd7,0x3d,0x3f,0x63,0xd7,0x3d,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/30hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/30hz_48khz.conf new file mode 100644 index 000000000000..c4a21f83a10c --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/30hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xa6,0x88,0xbf,0x3f,0xa6,0x88,0xbf,0x3f, + 0xa6,0x88,0xbf,0x3f,0xa6,0x88,0xbf,0x3f, + 0xa6,0x88,0xbf,0x3f,0xa6,0x88,0xbf,0x3f, + 0xa6,0x88,0xbf,0x3f,0xa6,0x88,0xbf,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/40hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/40hz_16khz.conf new file mode 100644 index 000000000000..5552350b9da3 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/40hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3c,0x9d,0xfc,0x3e,0x3c,0x9d,0xfc,0x3e, + 0x3c,0x9d,0xfc,0x3e,0x3c,0x9d,0xfc,0x3e, + 0x3c,0x9d,0xfc,0x3e,0x3c,0x9d,0xfc,0x3e, + 0x3c,0x9d,0xfc,0x3e,0x3c,0x9d,0xfc,0x3e" +} diff --git a/tools/topology/topology2/include/components/dcblock/40hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/40hz_48khz.conf new file mode 100644 index 000000000000..77b497ba73a1 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/40hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x22,0xfd,0xa9,0x3f,0x22,0xfd,0xa9,0x3f, + 0x22,0xfd,0xa9,0x3f,0x22,0xfd,0xa9,0x3f, + 0x22,0xfd,0xa9,0x3f,0x22,0xfd,0xa9,0x3f, + 0x22,0xfd,0xa9,0x3f,0x22,0xfd,0xa9,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/50hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/50hz_16khz.conf new file mode 100644 index 000000000000..81e6cf5db9ea --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/50hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe6,0x21,0xbb,0x3e,0xe6,0x21,0xbb,0x3e, + 0xe6,0x21,0xbb,0x3e,0xe6,0x21,0xbb,0x3e, + 0xe6,0x21,0xbb,0x3e,0xe6,0x21,0xbb,0x3e, + 0xe6,0x21,0xbb,0x3e,0xe6,0x21,0xbb,0x3e" +} diff --git a/tools/topology/topology2/include/components/dcblock/50hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/50hz_48khz.conf new file mode 100644 index 000000000000..ced86dd64d0e --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/50hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6a,0x6a,0x94,0x3f,0x6a,0x6a,0x94,0x3f, + 0x6a,0x6a,0x94,0x3f,0x6a,0x6a,0x94,0x3f, + 0x6a,0x6a,0x94,0x3f,0x6a,0x6a,0x94,0x3f, + 0x6a,0x6a,0x94,0x3f,0x6a,0x6a,0x94,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/80hz_16khz.conf b/tools/topology/topology2/include/components/dcblock/80hz_16khz.conf new file mode 100644 index 000000000000..0bb539df5288 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/80hz_16khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x96,0x27,0xf5,0x3d,0x96,0x27,0xf5,0x3d, + 0x96,0x27,0xf5,0x3d,0x96,0x27,0xf5,0x3d, + 0x96,0x27,0xf5,0x3d,0x96,0x27,0xf5,0x3d, + 0x96,0x27,0xf5,0x3d,0x96,0x27,0xf5,0x3d" +} diff --git a/tools/topology/topology2/include/components/dcblock/80hz_48khz.conf b/tools/topology/topology2/include/components/dcblock/80hz_48khz.conf new file mode 100644 index 000000000000..7be93fe17c22 --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/80hz_48khz.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfa,0x86,0x53,0x3f,0xfa,0x86,0x53,0x3f, + 0xfa,0x86,0x53,0x3f,0xfa,0x86,0x53,0x3f, + 0xfa,0x86,0x53,0x3f,0xfa,0x86,0x53,0x3f, + 0xfa,0x86,0x53,0x3f,0xfa,0x86,0x53,0x3f" +} diff --git a/tools/topology/topology2/include/components/dcblock/default.conf b/tools/topology/topology2/include/components/dcblock/default.conf new file mode 100644 index 000000000000..cbadfc6c6cbd --- /dev/null +++ b/tools/topology/topology2/include/components/dcblock/default.conf @@ -0,0 +1,13 @@ +# Exported with script example_dcblock.m 04-Oct-2023 +# cd tools/tune/dcblock; octave example_dcblock.m +Object.Base.data."dcblock_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e, + 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e, + 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e, + 0xec,0x51,0xb8,0x3e,0xec,0x51,0xb8,0x3e" +} diff --git a/tools/topology/topology2/include/components/decoder.conf b/tools/topology/topology2/include/components/decoder.conf new file mode 100644 index 000000000000..b01a1c56d050 --- /dev/null +++ b/tools/topology/topology2/include/components/decoder.conf @@ -0,0 +1,63 @@ +# +# Decoder widget component definition +# +# A generic decoder widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.decoder.N.attribute_name" +# +# Usage: this component can be used by declaring in a parent object. i.e. +# +# Object.Widget.decoder."N" { +# index 1 +# no_pm "true" +# } +# +# Where N is the unique instance number for decoder widget in the same alsaconf node. + +Class.Widget."decoder" { + # + # Pipeline ID for the decoder widget object + # + DefineAttribute."index" {} + + # + # decoder object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # Attribute categories + attributes { + # + # The decoder widget name would be constructed using the index and instance attributes. + # For ex: "decoder.1.1" or "decoder.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "type" + ] + + # + # decoder widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for decoder widget + type "decoder" + + # cadence codec UUID + uuid "43:84:21:d8:f3:5f:4c:4a:b3:88:6c:fe:07:b9:56:aa" + no_pm "true" + num_output_pins 1 + num_input_pins 1 +} diff --git a/tools/topology/topology2/include/components/dolby-dax.conf b/tools/topology/topology2/include/components/dolby-dax.conf new file mode 100644 index 000000000000..87b317da0261 --- /dev/null +++ b/tools/topology/topology2/include/components/dolby-dax.conf @@ -0,0 +1,164 @@ +<include/controls/mixer.conf> +<include/controls/enum.conf> + +Class.Widget."dolby-dax" { + DefineAttribute."index" { + type "integer" + } + + DefineAttribute."instance" { + type "integer" + } + + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + Object.Control { + # Enable/Disable DAX module + mixer."1" { + Object.Base.channel.1 { + name "fc" + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + ## get = 259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + + #max 1 indicates switch type control + max 1 + } + # Enable/Disable DAX content processing feature + mixer."2" { + Object.Base.channel.1 { + name "fc" + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + ## get = 259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + + #max 1 indicates switch type control + max 1 + } + # Enable/Disable DAX crosstalk cancellation feature + mixer."3" { + Object.Base.channel.1 { + name "fc" + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + ## get = 259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + + #max 1 indicates switch type control + max 1 + } + # Set volume to DAX module, range from 0 to 25 + mixer."4" { + Object.Base.channel.1 { + name "fc" + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + get 256 + put 256 + } + max 25 + + Object.Base.tlv.1 { + name "vtlv_m50s200" + Object.Base.scale.1 { + name m0s131072 + min -5000 + step 200 + } + } + } + # Set profile to DAX module + enum."1" { + Object.Base { + channel.1 { + name "fc" + } + text.0 { + name "profiles" + !values [ + "0" # dynamic + "1" # movie + "2" # music + "3" # voice + ] + } + ops.1 { + name "ctl" + info "enum" + #257 binds the mixer control to enum get/put handlers + get 257 + put 257 + } + } + } + # Set output device to DAX module + enum."2" { + Object.Base { + channel.1 { + name "fc" + } + text.0 { + name "devices" + !values [ + "0" # speaker + "1" # 3.5mm wired headphone + ] + } + ops.1 { + name "ctl" + info "enum" + #257 binds the mixer control to enum get/put handlers + get 257 + put 257 + } + } + } + # Set binary effect parameters to DAX module + bytes."1" {} + } + + uuid "8b:6c:f6:40:a5:5a:45:43:89:19:53:ec:43:1a:aa:98" + type "effect" + no_pm "true" + cpc 675000 + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/drc.conf b/tools/topology/topology2/include/components/drc.conf new file mode 100644 index 000000000000..2db857f421a4 --- /dev/null +++ b/tools/topology/topology2/include/components/drc.conf @@ -0,0 +1,84 @@ +# +# +# A generic DRC component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.drc.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.drc."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."drc" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for DRC widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # drc widget switch control + # + Object.Control { + mixer."1" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + } + + # + # Default attributes for drc + # + uuid "da:e4:6e:b3:6f:00:f9:47:a0:6d:fe:cb:e2:d8:b6:ce" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/drc/default.conf b/tools/topology/topology2/include/components/drc/default.conf new file mode 100644 index 000000000000..bf858625aa69 --- /dev/null +++ b/tools/topology/topology2/include/components/drc/default.conf @@ -0,0 +1,22 @@ +# Exported Control Bytes 03-Nov-2020 (edited for tplg2 from m4) +Object.Base.data."drc_config" { + bytes " + 0x53,0x4f,0x46,0x00,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0x20,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e, + 0x00,0x00,0x00,0x01,0xd3,0x4d,0x62,0x00, + 0xb1,0xc2,0x09,0x04,0x00,0x00,0x00,0x40, + 0xa6,0x99,0x01,0x00,0xce,0xd8,0x0f,0x0a, + 0x1f,0x1a,0xf0,0xf5,0x83,0xc9,0xfe,0x01, + 0xdf,0x30,0x61,0x3a,0xcb,0x83,0x0e,0x01, + 0xef,0x84,0x73,0x01,0x6d,0x64,0x6b,0xff, + 0x03,0x41,0x22,0x00,0x05,0x00,0x00,0x00, + 0x00,0x10,0xf8,0x00,0xaa,0x81,0x10,0x00, + 0xf4,0xf0,0x8a,0x00,0xaa,0xe1,0x22,0x00, + 0xb9,0x9b,0x02,0x00" +} diff --git a/tools/topology/topology2/include/components/drc/dmic_default.conf b/tools/topology/topology2/include/components/drc/dmic_default.conf new file mode 100644 index 000000000000..af2cbc73e3cc --- /dev/null +++ b/tools/topology/topology2/include/components/drc/dmic_default.conf @@ -0,0 +1,23 @@ +# Exported with script example_drc.m 17-May-2024 +# cd tools/tune/drc; octave --no-window-system example_drc.m +Object.Base.data."drc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0xdd,0x00,0x00,0x00,0x19, + 0x00,0x00,0x00,0x0a,0xd3,0x4d,0x62,0x00, + 0x72,0x5a,0x23,0x01,0x66,0x66,0x66,0x06, + 0xd7,0x18,0xb8,0x00,0x31,0xcd,0x1a,0x00, + 0x04,0xb3,0xe4,0xff,0x4e,0xf4,0x50,0x00, + 0xf1,0x0d,0x51,0x07,0x9a,0x81,0xac,0x03, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x80,0x43,0x00,0xd7,0x7d,0x04,0x00, + 0xa0,0xce,0x25,0x00,0xd7,0x7d,0x09,0x00, + 0xb1,0xb5,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/drc/enabled.conf b/tools/topology/topology2/include/components/drc/enabled.conf new file mode 100644 index 000000000000..30dd92bbd626 --- /dev/null +++ b/tools/topology/topology2/include/components/drc/enabled.conf @@ -0,0 +1,23 @@ +# Exported with script example_drc.m 18-Dec-2023 +# cd tools/tune/drc; octave --no-window-system example_drc.m +Object.Base.data."drc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e, + 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00, + 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05, + 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00, + 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01, + 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x80,0x43,0x00,0xd7,0x7d,0x04,0x00, + 0xa0,0xce,0x25,0x00,0xd7,0x7d,0x09,0x00, + 0xb1,0xb5,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/drc/passthrough.conf b/tools/topology/topology2/include/components/drc/passthrough.conf new file mode 100644 index 000000000000..14a00abb84cf --- /dev/null +++ b/tools/topology/topology2/include/components/drc/passthrough.conf @@ -0,0 +1,23 @@ +# Exported with script example_drc.m 18-Dec-2023 +# cd tools/tune/drc; octave --no-window-system example_drc.m +Object.Base.data."drc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e, + 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00, + 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05, + 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00, + 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01, + 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x80,0x43,0x00,0xd7,0x7d,0x04,0x00, + 0xa0,0xce,0x25,0x00,0xd7,0x7d,0x09,0x00, + 0xb1,0xb5,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/drc/speaker_default.conf b/tools/topology/topology2/include/components/drc/speaker_default.conf new file mode 100644 index 000000000000..abd9d47a5680 --- /dev/null +++ b/tools/topology/topology2/include/components/drc/speaker_default.conf @@ -0,0 +1,23 @@ +# Exported with script example_drc.m 17-May-2024 +# cd tools/tune/drc; octave --no-window-system example_drc.m +Object.Base.data."drc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x14, + 0x00,0x00,0x00,0x0a,0xd3,0x4d,0x62,0x00, + 0x8a,0x1b,0x06,0x02,0x66,0x66,0x66,0x06, + 0x2f,0x97,0xba,0x00,0x18,0x0c,0x1e,0x00, + 0x20,0x42,0xe0,0xff,0x4e,0xf4,0x50,0x00, + 0x9a,0x9f,0x34,0x08,0xd3,0x2c,0xd8,0x04, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x80,0x43,0x00,0xd7,0x7d,0x04,0x00, + 0xa0,0xce,0x25,0x00,0xd7,0x7d,0x09,0x00, + 0xb1,0xb5,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/dts.conf b/tools/topology/topology2/include/components/dts.conf new file mode 100644 index 000000000000..071ee058de0a --- /dev/null +++ b/tools/topology/topology2/include/components/dts.conf @@ -0,0 +1,107 @@ +# +# Common widget dts +# +# A generic dts widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.dts.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.dts."N" { +# index 1 +# type "effect" +# } +# +# Where N is the unique instance number for the smart_amp object within the same alsaconf node. + +Class.Widget."dts" { + # + # Pipeline ID for the DTS widget object + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for DTS widget + # + DefineAttribute."instance" { + type "integer" + } + + #include common component definition + <include/components/widget-common.conf> + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + Object.Control.bytes."1" { + !access [ + tlv_read + tlv_write + tlv_callback + ] + Object.Base.extops.1 { + name "extctl" + get 258 + put 258 + } + max 2048 + Object.Base.data.1 { + <include/components/dts/dts_spk.conf> + } + } + + # Attribute categories + attributes { + # + # The DTS widget name would be constructed using the index and instance attributes. + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "type" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + # + # DTS widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for smart_amp widget + + # UUID can be overridden in the top-level topology file + uuid "4f:c3:5f:d9:0f:37:c7:4a:bc:86:bf:dc:5b:e2:41:e6" + type "effect" + no_pm "true" + core_id 0 + cpc 5000 + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/dts/dts_spk.conf b/tools/topology/topology2/include/components/dts/dts_spk.conf new file mode 100644 index 000000000000..ae4f5fb67cc4 --- /dev/null +++ b/tools/topology/topology2/include/components/dts/dts_spk.conf @@ -0,0 +1,9 @@ +Object.Base.data."dts_spk" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x0c,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/encoder.conf b/tools/topology/topology2/include/components/encoder.conf new file mode 100644 index 000000000000..cde2346e3885 --- /dev/null +++ b/tools/topology/topology2/include/components/encoder.conf @@ -0,0 +1,63 @@ +# +# Encoder widget component definition +# +# A generic encoder widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.encoder.N.attribute_name" +# +# Usage: this component can be used by declaring in a parent object. i.e. +# +# Object.Widget.encoder."N" { +# index 1 +# no_pm "true" +# } +# +# Where N is the unique instance number for encoder widget in the same alsaconf node. + +Class.Widget."encoder" { + # + # Pipeline ID for the encoder widget object + # + DefineAttribute."index" {} + + # + # encoder object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # Attribute categories + attributes { + # + # The encoder widget name would be constructed using the index and instance attributes. + # For ex: "encoder.1.1" or "encoder.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "type" + ] + + # + # encoder widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for encoder widget + type "encoder" + + # cadence codec UUID + uuid "43:84:21:d8:f3:5f:4c:4a:b3:88:6c:fe:07:b9:56:aa" + no_pm "true" + num_output_pins 1 + num_input_pins 1 +} diff --git a/tools/topology/topology2/include/components/eqfir.conf b/tools/topology/topology2/include/components/eqfir.conf new file mode 100644 index 000000000000..42e45fc85699 --- /dev/null +++ b/tools/topology/topology2/include/components/eqfir.conf @@ -0,0 +1,64 @@ +# +# +# A generic EQ FIR component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.eqfir.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.eqfir."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."eqfir" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for EQ FIR widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for eqfir + # + uuid "e7:0c:a9:43:a5:f3:df:41:ac:06:ba:98:65:1a:e6:a3" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/eqfir/flat.conf b/tools/topology/topology2/include/components/eqfir/flat.conf new file mode 100644 index 000000000000..88554eaae809 --- /dev/null +++ b/tools/topology/topology2/include/components/eqfir/flat.conf @@ -0,0 +1,15 @@ +# Flat response, created with example_fir_eq.m 02-Feb-2023 +Object.Base.data."fir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x38,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x38,0x00,0x00,0x00,0x02,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqfir/loudness.conf b/tools/topology/topology2/include/components/eqfir/loudness.conf new file mode 100644 index 000000000000..3aeb6ff31ad4 --- /dev/null +++ b/tools/topology/topology2/include/components/eqfir/loudness.conf @@ -0,0 +1,81 @@ +# Loudness effect, created with example_fir_eq.m 02-Feb-2023 +Object.Base.data."fir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x48,0x02,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x48,0x02,0x00,0x00,0x04,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00, + 0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00, + 0x03,0x00,0x03,0x00,0x03,0x00,0x04,0x00, + 0x04,0x00,0x04,0x00,0x05,0x00,0x05,0x00, + 0x05,0x00,0x06,0x00,0x06,0x00,0x06,0x00, + 0x07,0x00,0x07,0x00,0x08,0x00,0x08,0x00, + 0x09,0x00,0x09,0x00,0x0a,0x00,0x0a,0x00, + 0x0b,0x00,0x0b,0x00,0x0c,0x00,0x0c,0x00, + 0x0d,0x00,0x0d,0x00,0x0e,0x00,0x0f,0x00, + 0x0f,0x00,0x10,0x00,0x11,0x00,0x12,0x00, + 0x12,0x00,0x13,0x00,0x14,0x00,0x15,0x00, + 0x16,0x00,0x17,0x00,0x18,0x00,0x19,0x00, + 0x1a,0x00,0x1b,0x00,0x1d,0x00,0x1e,0x00, + 0x1f,0x00,0x21,0x00,0x22,0x00,0x24,0x00, + 0x26,0x00,0x28,0x00,0x29,0x00,0x2b,0x00, + 0x2d,0x00,0x2f,0x00,0x32,0x00,0x34,0x00, + 0x36,0x00,0x38,0x00,0x3b,0x00,0x3d,0x00, + 0x40,0x00,0x42,0x00,0x45,0x00,0x48,0x00, + 0x4b,0x00,0x4d,0x00,0x51,0x00,0x54,0x00, + 0x57,0x00,0x5b,0x00,0x5e,0x00,0x62,0x00, + 0x65,0x00,0x68,0x00,0x6c,0x00,0x6f,0x00, + 0x72,0x00,0x76,0x00,0x79,0x00,0x7d,0x00, + 0x81,0x00,0x86,0x00,0x8c,0x00,0x92,0x00, + 0x98,0x00,0x9f,0x00,0xa5,0x00,0xac,0x00, + 0xb2,0x00,0xb8,0x00,0xbe,0x00,0xc6,0x00, + 0xce,0x00,0xd8,0x00,0xe1,0x00,0xea,0x00, + 0xef,0x00,0xf5,0x00,0xfc,0x00,0xfc,0x00, + 0x18,0x01,0xff,0x00,0x2f,0x01,0x70,0x01, + 0xc3,0x00,0x39,0x04,0xd3,0x02,0xae,0xe9, + 0xbf,0x6c,0xae,0xe9,0xd3,0x02,0x39,0x04, + 0xc3,0x00,0x70,0x01,0x2f,0x01,0xff,0x00, + 0x18,0x01,0xfc,0x00,0xfc,0x00,0xf5,0x00, + 0xef,0x00,0xea,0x00,0xe1,0x00,0xd8,0x00, + 0xce,0x00,0xc6,0x00,0xbe,0x00,0xb8,0x00, + 0xb2,0x00,0xac,0x00,0xa5,0x00,0x9f,0x00, + 0x98,0x00,0x92,0x00,0x8c,0x00,0x86,0x00, + 0x81,0x00,0x7d,0x00,0x79,0x00,0x76,0x00, + 0x72,0x00,0x6f,0x00,0x6c,0x00,0x68,0x00, + 0x65,0x00,0x62,0x00,0x5e,0x00,0x5b,0x00, + 0x57,0x00,0x54,0x00,0x51,0x00,0x4d,0x00, + 0x4b,0x00,0x48,0x00,0x45,0x00,0x42,0x00, + 0x40,0x00,0x3d,0x00,0x3b,0x00,0x38,0x00, + 0x36,0x00,0x34,0x00,0x32,0x00,0x2f,0x00, + 0x2d,0x00,0x2b,0x00,0x29,0x00,0x28,0x00, + 0x26,0x00,0x24,0x00,0x22,0x00,0x21,0x00, + 0x1f,0x00,0x1e,0x00,0x1d,0x00,0x1b,0x00, + 0x1a,0x00,0x19,0x00,0x18,0x00,0x17,0x00, + 0x16,0x00,0x15,0x00,0x14,0x00,0x13,0x00, + 0x12,0x00,0x12,0x00,0x11,0x00,0x10,0x00, + 0x0f,0x00,0x0f,0x00,0x0e,0x00,0x0d,0x00, + 0x0d,0x00,0x0c,0x00,0x0c,0x00,0x0b,0x00, + 0x0b,0x00,0x0a,0x00,0x0a,0x00,0x09,0x00, + 0x09,0x00,0x08,0x00,0x08,0x00,0x07,0x00, + 0x07,0x00,0x06,0x00,0x06,0x00,0x06,0x00, + 0x05,0x00,0x05,0x00,0x05,0x00,0x04,0x00, + 0x04,0x00,0x04,0x00,0x03,0x00,0x03,0x00, + 0x03,0x00,0x03,0x00,0x03,0x00,0x02,0x00, + 0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqfir/midboost.conf b/tools/topology/topology2/include/components/eqfir/midboost.conf new file mode 100644 index 000000000000..f4a7ea947eab --- /dev/null +++ b/tools/topology/topology2/include/components/eqfir/midboost.conf @@ -0,0 +1,24 @@ +# Mid boost, created with example_fir_eq.m 02-Feb-2023 +Object.Base.data."fir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x02,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfa,0x6c,0xa7,0x47,0xe7,0x21,0xb2,0xfb, + 0x8b,0xe9,0xe7,0xe6,0x00,0xeb,0xe7,0xef, + 0x8b,0xf3,0xed,0xf5,0x94,0xf7,0xf6,0xf8, + 0x39,0xfa,0x65,0xfb,0x72,0xfc,0x5b,0xfd, + 0x1e,0xfe,0xbd,0xfe,0x3c,0xff,0xa1,0xff, + 0xed,0xff,0x25,0x00,0x4d,0x00,0x67,0x00, + 0x76,0x00,0x7c,0x00,0x7b,0x00,0x76,0x00, + 0x6e,0x00,0x63,0x00,0x58,0x00,0x4c,0x00, + 0x40,0x00,0x35,0x00,0x2c,0x00,0x23,0x00, + 0x1b,0x00,0x13,0x00,0x0d,0x00,0x13,0x00" +} diff --git a/tools/topology/topology2/include/components/eqfir/passthrough.conf b/tools/topology/topology2/include/components/eqfir/passthrough.conf new file mode 100644 index 000000000000..eecc17f1278e --- /dev/null +++ b/tools/topology/topology2/include/components/eqfir/passthrough.conf @@ -0,0 +1,15 @@ +# Pass-through response, created with example_fir_eq.m 02-Feb-2023 +Object.Base.data."fir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x38,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x38,0x00,0x00,0x00,0x02,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir.conf b/tools/topology/topology2/include/components/eqiir.conf new file mode 100644 index 000000000000..8d4f5bb37fad --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir.conf @@ -0,0 +1,64 @@ +# +# +# A generic EQ IIR component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.eqiir.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.eqiir."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."eqiir" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for EQ IIR widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for eqiir + # + uuid "e6:c0:50:51:f9:27:c8:4e:83:51:c7:05:b6:42:d1:2f" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/eqiir/bandpass.conf b/tools/topology/topology2/include/components/eqiir/bandpass.conf new file mode 100644 index 000000000000..087cca49eaba --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/bandpass.conf @@ -0,0 +1,23 @@ +# Band-pass, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x74,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x74,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x8e,0x6f,0xa8,0xc5, + 0xb3,0x81,0x14,0x7a,0xae,0x14,0xa0,0x1e, + 0xa5,0xd6,0xbf,0xc2,0xae,0x14,0xa0,0x1e, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x3e,0xac,0x84,0xe6,0xc3,0x9a,0xfd,0x46, + 0xcf,0x1e,0x51,0x02,0x9d,0x3d,0xa2,0x04, + 0xcf,0x1e,0x51,0x02,0xfc,0xff,0xff,0xff, + 0x85,0x5e,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/bassboost.conf b/tools/topology/topology2/include/components/eqiir/bassboost.conf new file mode 100644 index 000000000000..dd008db00335 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/bassboost.conf @@ -0,0 +1,23 @@ +# Bass boost, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x74,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x74,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0, + 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f, + 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d, + 0x1f,0x86,0xa2,0x09,0xe8,0xa3,0x18,0xec, + 0x7d,0x5c,0x4a,0x0a,0xfe,0xff,0xff,0xff, + 0x06,0x6d,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/flat.conf b/tools/topology/topology2/include/components/eqiir/flat.conf new file mode 100644 index 000000000000..ec36b278191a --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/flat.conf @@ -0,0 +1,19 @@ +# Flat response, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9e,0x73,0x13,0x20, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_100hz_0db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_100hz_0db_16khz.conf new file mode 100644 index 000000000000..0d9710dbd105 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_100hz_0db_16khz.conf @@ -0,0 +1,19 @@ +# 100 Hz second order high-pass, gain 0 dB, created with sof_example_iir_eq.m 03-Jun-2024 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf5,0x18,0x75,0xc3, + 0x6b,0x52,0x72,0x7c,0x6e,0x92,0x32,0x1f, + 0x24,0xdb,0x9a,0xc1,0x6e,0x92,0x32,0x1f, + 0x00,0x00,0x00,0x00,0xb4,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_100hz_0db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_100hz_0db_48khz.conf new file mode 100644 index 000000000000..dc71c14913cb --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_100hz_0db_48khz.conf @@ -0,0 +1,19 @@ +# 100 Hz second order high-pass, gain 0 dB, created with sof_example_iir_eq.m 03-Jun-2024 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xbd,0x82,0x2c,0xc1, + 0x2e,0xb5,0xd0,0x7e,0x0c,0xcc,0xc7,0x1f, + 0xe9,0x67,0x70,0xc0,0x0c,0xcc,0xc7,0x1f, + 0x00,0x00,0x00,0x00,0xb4,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_100hz_16db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_100hz_16db_16khz.conf new file mode 100644 index 000000000000..264bf3f13431 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_100hz_16db_16khz.conf @@ -0,0 +1,20 @@ +# 100 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf5,0x18,0x75,0xc3, + 0x6b,0x52,0x72,0x7c,0x6e,0x92,0x32,0x1f, + 0x24,0xdb,0x9a,0xc1,0x6e,0x92,0x32,0x1f, + 0xfd,0xff,0xff,0xff,0xb8,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_100hz_16db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_100hz_16db_48khz.conf new file mode 100644 index 000000000000..856f1cd6328c --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_100hz_16db_48khz.conf @@ -0,0 +1,20 @@ +# 100 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xbd,0x82,0x2c,0xc1, + 0x2e,0xb5,0xd0,0x7e,0x0c,0xcc,0xc7,0x1f, + 0xe9,0x67,0x70,0xc0,0x0c,0xcc,0xc7,0x1f, + 0xfd,0xff,0xff,0xff,0xb8,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_100hz_20db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_100hz_20db_16khz.conf new file mode 100644 index 000000000000..fb3d9abf0d6f --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_100hz_20db_16khz.conf @@ -0,0 +1,19 @@ +# 100 Hz second order high-pass, gain 20 dB, created with sof_example_iir_eq.m 03-Jun-2024 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf5,0x18,0x75,0xc3, + 0x6b,0x52,0x72,0x7c,0x6e,0x92,0x32,0x1f, + 0x24,0xdb,0x9a,0xc1,0x6e,0x92,0x32,0x1f, + 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_100hz_20db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_100hz_20db_48khz.conf new file mode 100644 index 000000000000..85d70b3e5322 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_100hz_20db_48khz.conf @@ -0,0 +1,19 @@ +# 100 Hz second order high-pass, gain 20 dB, created with sof_example_iir_eq.m 03-Jun-2024 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xbd,0x82,0x2c,0xc1, + 0x2e,0xb5,0xd0,0x7e,0x0c,0xcc,0xc7,0x1f, + 0xe9,0x67,0x70,0xc0,0x0c,0xcc,0xc7,0x1f, + 0xfc,0xff,0xff,0xff,0xd1,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_20hz_0db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_20hz_0db_16khz.conf new file mode 100644 index 000000000000..bf24703f7769 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_20hz_0db_16khz.conf @@ -0,0 +1,19 @@ +# 20 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0xf9,0xb4,0xc0, + 0x79,0x05,0x4a,0x7f,0x92,0xf9,0xe5,0x1f, + 0xdc,0x0c,0x34,0xc0,0x92,0xf9,0xe5,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_20hz_0db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_20hz_0db_48khz.conf new file mode 100644 index 000000000000..cab785b269d0 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_20hz_0db_48khz.conf @@ -0,0 +1,19 @@ +# 20 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4a,0x8c,0x3c,0xc0, + 0x04,0x57,0xc3,0x7f,0xc0,0x43,0x04,0x20, + 0x80,0x78,0xf7,0xbf,0xc0,0x43,0x04,0x20, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_20hz_16db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_20hz_16db_16khz.conf new file mode 100644 index 000000000000..0f84b2c22601 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_20hz_16db_16khz.conf @@ -0,0 +1,20 @@ +# 20 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0xf9,0xb4,0xc0, + 0x79,0x05,0x4a,0x7f,0x92,0xf9,0xe5,0x1f, + 0xdc,0x0c,0x34,0xc0,0x92,0xf9,0xe5,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_20hz_16db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_20hz_16db_48khz.conf new file mode 100644 index 000000000000..5a57e789c335 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_20hz_16db_48khz.conf @@ -0,0 +1,20 @@ +# 20 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4a,0x8c,0x3c,0xc0, + 0x04,0x57,0xc3,0x7f,0xc0,0x43,0x04,0x20, + 0x80,0x78,0xf7,0xbf,0xc0,0x43,0x04,0x20, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_20hz_20db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_20hz_20db_16khz.conf new file mode 100644 index 000000000000..cea770adec4b --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_20hz_20db_16khz.conf @@ -0,0 +1,19 @@ +# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0xf9,0xb4,0xc0, + 0x79,0x05,0x4a,0x7f,0x92,0xf9,0xe5,0x1f, + 0xdc,0x0c,0x34,0xc0,0x92,0xf9,0xe5,0x1f, + 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_20hz_20db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_20hz_20db_48khz.conf new file mode 100644 index 000000000000..f4bd0b52c714 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_20hz_20db_48khz.conf @@ -0,0 +1,19 @@ +# 20 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4a,0x8c,0x3c,0xc0, + 0x04,0x57,0xc3,0x7f,0xc0,0x43,0x04,0x20, + 0x80,0x78,0xf7,0xbf,0xc0,0x43,0x04,0x20, + 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_30hz_0db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_30hz_0db_16khz.conf new file mode 100644 index 000000000000..37a0d0968fee --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_30hz_0db_16khz.conf @@ -0,0 +1,19 @@ +# 30 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0xb5,0x0e,0xc1, + 0x17,0x09,0xef,0x7e,0xbf,0x54,0xcf,0x1f, + 0x82,0x56,0x61,0xc0,0xbf,0x54,0xcf,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_30hz_0db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_30hz_0db_48khz.conf new file mode 100644 index 000000000000..8ebaec6035a1 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_30hz_0db_48khz.conf @@ -0,0 +1,19 @@ +# 30 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0, + 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f, + 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_30hz_16db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_30hz_16db_16khz.conf new file mode 100644 index 000000000000..f1e2369164d4 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_30hz_16db_16khz.conf @@ -0,0 +1,20 @@ +# 30 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0xb5,0x0e,0xc1, + 0x17,0x09,0xef,0x7e,0xbf,0x54,0xcf,0x1f, + 0x82,0x56,0x61,0xc0,0xbf,0x54,0xcf,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_30hz_16db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_30hz_16db_48khz.conf new file mode 100644 index 000000000000..490ac534dec7 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_30hz_16db_48khz.conf @@ -0,0 +1,20 @@ +# 30 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0, + 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f, + 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_30hz_20db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_30hz_20db_16khz.conf new file mode 100644 index 000000000000..4378cde9f74f --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_30hz_20db_16khz.conf @@ -0,0 +1,19 @@ +# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x98,0xb5,0x0e,0xc1, + 0x17,0x09,0xef,0x7e,0xbf,0x54,0xcf,0x1f, + 0x82,0x56,0x61,0xc0,0xbf,0x54,0xcf,0x1f, + 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_30hz_20db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_30hz_20db_48khz.conf new file mode 100644 index 000000000000..e0b44636768b --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_30hz_20db_48khz.conf @@ -0,0 +1,19 @@ +# 30 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf1,0xbc,0x5a,0xc0, + 0x8f,0x02,0xa5,0x7f,0x83,0xae,0xfc,0x1f, + 0xfa,0xa2,0x06,0xc0,0x83,0xae,0xfc,0x1f, + 0xfc,0xff,0xff,0xff,0xcf,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_40hz_0db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_40hz_0db_16khz.conf new file mode 100644 index 000000000000..ddba11b5ac2e --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_40hz_0db_16khz.conf @@ -0,0 +1,19 @@ +# 40 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xba,0xf2,0x67,0xc1, + 0xc3,0x0d,0x94,0x7e,0xff,0xbf,0xb8,0x1f, + 0x03,0x80,0x8e,0xc0,0xff,0xbf,0xb8,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_40hz_0db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_40hz_0db_48khz.conf new file mode 100644 index 000000000000..916b45b40acc --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_40hz_0db_48khz.conf @@ -0,0 +1,19 @@ +# 40 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4c,0xdf,0x78,0xc0, + 0x23,0xae,0x86,0x7f,0x12,0x1b,0xf5,0x1f, + 0xdb,0xc9,0x15,0xc0,0x12,0x1b,0xf5,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_40hz_16db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_40hz_16db_16khz.conf new file mode 100644 index 000000000000..54e8d8b37839 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_40hz_16db_16khz.conf @@ -0,0 +1,20 @@ +# 40 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xba,0xf2,0x67,0xc1, + 0xc3,0x0d,0x94,0x7e,0xff,0xbf,0xb8,0x1f, + 0x03,0x80,0x8e,0xc0,0xff,0xbf,0xb8,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_40hz_16db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_40hz_16db_48khz.conf new file mode 100644 index 000000000000..1fbc3f74740a --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_40hz_16db_48khz.conf @@ -0,0 +1,20 @@ +# 40 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4c,0xdf,0x78,0xc0, + 0x23,0xae,0x86,0x7f,0x12,0x1b,0xf5,0x1f, + 0xdb,0xc9,0x15,0xc0,0x12,0x1b,0xf5,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_40hz_20db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_40hz_20db_16khz.conf new file mode 100644 index 000000000000..9761d9efb598 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_40hz_20db_16khz.conf @@ -0,0 +1,19 @@ +# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xba,0xf2,0x67,0xc1, + 0xc3,0x0d,0x94,0x7e,0xff,0xbf,0xb8,0x1f, + 0x03,0x80,0x8e,0xc0,0xff,0xbf,0xb8,0x1f, + 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_40hz_20db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_40hz_20db_48khz.conf new file mode 100644 index 000000000000..8e6ee27c2ffb --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_40hz_20db_48khz.conf @@ -0,0 +1,19 @@ +# 40 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4c,0xdf,0x78,0xc0, + 0x23,0xae,0x86,0x7f,0x12,0x1b,0xf5,0x1f, + 0xdb,0xc9,0x15,0xc0,0x12,0x1b,0xf5,0x1f, + 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_50hz_0db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_50hz_0db_16khz.conf new file mode 100644 index 000000000000..ddc387c7963e --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_50hz_0db_16khz.conf @@ -0,0 +1,19 @@ +# 50 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0xb1,0xc0,0xc1, + 0xd2,0x13,0x39,0x7e,0x45,0x3b,0xa2,0x1f, + 0x76,0x89,0xbb,0xc0,0x45,0x3b,0xa2,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_50hz_0db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_50hz_0db_48khz.conf new file mode 100644 index 000000000000..fc68feddd3a7 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_50hz_0db_48khz.conf @@ -0,0 +1,19 @@ +# 50 Hz second order high-pass, gain 0 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x63,0xf3,0x96,0xc0, + 0xc6,0x59,0x68,0x7f,0x6d,0x89,0xed,0x1f, + 0x27,0xed,0x24,0xc0,0x6d,0x89,0xed,0x1f, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_50hz_16db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_50hz_16db_16khz.conf new file mode 100644 index 000000000000..431a8f1c9335 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_50hz_16db_16khz.conf @@ -0,0 +1,20 @@ +# 50 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0xb1,0xc0,0xc1, + 0xd2,0x13,0x39,0x7e,0x45,0x3b,0xa2,0x1f, + 0x76,0x89,0xbb,0xc0,0x45,0x3b,0xa2,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_50hz_16db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_50hz_16db_48khz.conf new file mode 100644 index 000000000000..29e57256981f --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_50hz_16db_48khz.conf @@ -0,0 +1,20 @@ +# 50 Hz second order high-pass, gain 16 dB, created with sof_example_iir_eq.m 04-Feb-2026 +# cd src/audio/eq_iir/tune; octave --no-window-system sof_example_iir_eq.m +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x63,0xf3,0x96,0xc0, + 0xc6,0x59,0x68,0x7f,0x6d,0x89,0xed,0x1f, + 0x27,0xed,0x24,0xc0,0x6d,0x89,0xed,0x1f, + 0xfd,0xff,0xff,0xff,0xb7,0x64,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_50hz_20db_16khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_50hz_20db_16khz.conf new file mode 100644 index 000000000000..b05eb5fd765c --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_50hz_20db_16khz.conf @@ -0,0 +1,19 @@ +# 50 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x57,0xb1,0xc0,0xc1, + 0xd2,0x13,0x39,0x7e,0x45,0x3b,0xa2,0x1f, + 0x76,0x89,0xbb,0xc0,0x45,0x3b,0xa2,0x1f, + 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/highpass_50hz_20db_48khz.conf b/tools/topology/topology2/include/components/eqiir/highpass_50hz_20db_48khz.conf new file mode 100644 index 000000000000..c24972671075 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/highpass_50hz_20db_48khz.conf @@ -0,0 +1,19 @@ +# 50 Hz second order high-pass, gain 20 dB, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x63,0xf3,0x96,0xc0, + 0xc6,0x59,0x68,0x7f,0x6d,0x89,0xed,0x1f, + 0x27,0xed,0x24,0xc0,0x6d,0x89,0xed,0x1f, + 0xfc,0xff,0xff,0xff,0xd0,0x4f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/loudness.conf b/tools/topology/topology2/include/components/eqiir/loudness.conf new file mode 100644 index 000000000000..cb1db6ed43fb --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/loudness.conf @@ -0,0 +1,34 @@ +# Loudness effect, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9e,0x73,0x13,0x20, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00, + 0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1c,0x5a,0xff,0xc0,0xb4,0xc1,0xff,0x7e, + 0x9f,0xb7,0xb4,0x11,0x2d,0x0a,0x35,0xdc, + 0x90,0xb0,0x16,0x12,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x21,0xf8,0xd5,0xc4, + 0xf0,0x6b,0x14,0x7b,0x27,0xb8,0x9d,0x0e, + 0xb9,0x24,0x18,0xe1,0xa9,0xf7,0x54,0x10, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xff,0xaf,0xc0,0xf4,0x17,0xa2,0x2d,0xf6, + 0x35,0xa4,0x1f,0x04,0x58,0x87,0x20,0xf9, + 0xb9,0x3e,0xcb,0x15,0xfc,0xff,0xff,0xff, + 0x7c,0x63,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/passthrough.conf b/tools/topology/topology2/include/components/eqiir/passthrough.conf new file mode 100644 index 000000000000..87c6915931fd --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/passthrough.conf @@ -0,0 +1,19 @@ +# Pass-through, created with example_iir_eq.m 02-Feb-2023 +Object.Base.data."iir_eq" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x58,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x9e,0x73,0x13,0x20, + 0x00,0x00,0x00,0x00,0xb2,0x7f,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_hhll_48khz.conf b/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_hhll_48khz.conf new file mode 100644 index 000000000000..8338a33decb2 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_hhll_48khz.conf @@ -0,0 +1,35 @@ +# LR4 filter bank coefficients 08-Sep-2025 +# cd src/audio/eq_iir/tune; octave sof_example_lr4.m +Object.Base.data."IIR" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x2d,0x3a,0xcd,0xd3, + 0xc0,0xf5,0x82,0x68,0xb9,0x41,0x76,0x00, + 0x72,0x83,0xec,0x00,0xb9,0x41,0x76,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68, + 0xb9,0x41,0x76,0x00,0x72,0x83,0xec,0x00, + 0xb9,0x41,0x76,0x00,0xff,0xff,0xff,0xff, + 0x65,0x7f,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7e,0x70,0xdd,0xd6, + 0xc0,0xf5,0x82,0x68,0xb6,0x9e,0x44,0x1a, + 0x94,0xc2,0x76,0xcb,0xb6,0x9e,0x44,0x1a, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x7e,0x70,0xdd,0xd6,0xc0,0xf5,0x82,0x68, + 0xb6,0x9e,0x44,0x1a,0x94,0xc2,0x76,0xcb, + 0xb6,0x9e,0x44,0x1a,0xfe,0xff,0xff,0xff, + 0x92,0x41,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_lhlh_48khz.conf b/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_lhlh_48khz.conf new file mode 100644 index 000000000000..a7c04f3372a7 --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_lhlh_48khz.conf @@ -0,0 +1,35 @@ +# LR4 filter bank coefficients 08-Sep-2025 +# cd src/audio/eq_iir/tune; octave sof_example_lr4.m +Object.Base.data."IIR" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x2d,0x3a,0xcd,0xd3, + 0xc0,0xf5,0x82,0x68,0xb9,0x41,0x76,0x00, + 0x72,0x83,0xec,0x00,0xb9,0x41,0x76,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68, + 0xb9,0x41,0x76,0x00,0x72,0x83,0xec,0x00, + 0xb9,0x41,0x76,0x00,0xff,0xff,0xff,0xff, + 0x65,0x7f,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7e,0x70,0xdd,0xd6, + 0xc0,0xf5,0x82,0x68,0xb6,0x9e,0x44,0x1a, + 0x94,0xc2,0x76,0xcb,0xb6,0x9e,0x44,0x1a, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x7e,0x70,0xdd,0xd6,0xc0,0xf5,0x82,0x68, + 0xb6,0x9e,0x44,0x1a,0x94,0xc2,0x76,0xcb, + 0xb6,0x9e,0x44,0x1a,0xfe,0xff,0xff,0xff, + 0x92,0x41,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_llhh_48khz.conf b/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_llhh_48khz.conf new file mode 100644 index 000000000000..8612f617c9be --- /dev/null +++ b/tools/topology/topology2/include/components/eqiir/xover_lr4_2000hz_llhh_48khz.conf @@ -0,0 +1,35 @@ +# LR4 filter bank coefficients 08-Sep-2025 +# cd src/audio/eq_iir/tune; octave sof_example_lr4.m +Object.Base.data."IIR" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcc,0x00,0x00,0x00,0x04,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x2d,0x3a,0xcd,0xd3, + 0xc0,0xf5,0x82,0x68,0xb9,0x41,0x76,0x00, + 0x72,0x83,0xec,0x00,0xb9,0x41,0x76,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68, + 0xb9,0x41,0x76,0x00,0x72,0x83,0xec,0x00, + 0xb9,0x41,0x76,0x00,0xff,0xff,0xff,0xff, + 0x65,0x7f,0x00,0x00,0x02,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7e,0x70,0xdd,0xd6, + 0xc0,0xf5,0x82,0x68,0xb6,0x9e,0x44,0x1a, + 0x94,0xc2,0x76,0xcb,0xb6,0x9e,0x44,0x1a, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x7e,0x70,0xdd,0xd6,0xc0,0xf5,0x82,0x68, + 0xb6,0x9e,0x44,0x1a,0x94,0xc2,0x76,0xcb, + 0xb6,0x9e,0x44,0x1a,0xfe,0xff,0xff,0xff, + 0x92,0x41,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/gain.conf b/tools/topology/topology2/include/components/gain.conf new file mode 100644 index 000000000000..757bcb24ff72 --- /dev/null +++ b/tools/topology/topology2/include/components/gain.conf @@ -0,0 +1,202 @@ +## \struct gain +## \brief Common pipeline gain (volume) +## +## A generic gain (volume) widget. All attributes defined herein are namespaced +## by alsatplg to "Object.Widget.gain.N.attribute_name" +## +## Usage: this component can be used by declaring int a parent object. i.e. +## +## Object.Widget.gain."N" { +## index 1 +## format s24le +## no_pm "true" +## } +## +## Where N is the unique instance number for gain widget in the same alsaconf node. + +<include/controls/mixer.conf> + +Class.Widget."gain" { + # + ## Pipeline ID for the gain widget object + # + DefineAttribute."index" {} + + # + ## gain object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke attributes for PGA + # + + # + ## Gain curve type. The values provided will be translated to integer values + ## as specified in the tuple_values array. + ## For example: "linear" is translated to 0, "log" to 1 etc. + # + DefineAttribute."curve_type" { + type "string" + # Token set reference name + token_ref "gain.word" + constraints { + !valid_values [ + "windows_no_fade" + "windows_fade" + "linear" + "log" + "linear_zc" + "log_zc" + ] + !tuple_values [ + 0 + 1 + 2 + 3 + 4 + 5 + ] + } + } + + # + ## Gain curve in milliseconds + # + DefineAttribute."curve_duration" { + # Token set reference name + token_ref "gain.word" + } + + DefineAttribute."init_value" { + # Token set reference name + token_ref "gain.word" + } + + # Attribute categories + attributes { + # + ## The PGA widget name would be constructed using the index and instance attributes. + ## For ex: "gain.1.1" or "gain.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + # + # mandatory attributes that must be provided when the gain class is instantiated + # + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # 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" + ] + + # + # gain widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # + # gain widget mixer controls + # + Object.Control { + ## gain mixer control + mixer."1" { + ## Channel register and shift for Front Left/Right + Object.Base.channel.1 { + name "fl" + shift 0 + } + Object.Base.channel.2 { + name "fr" + } + + Object.Base.ops.1 { + name "ctl" + info "volsw" + ## get = 256 binds the mixer control to volume get/put handlers + get 256 + put 256 + } + max 45 + + Object.Base.tlv.1 { + name "vtlv_m90s2" + Object.Base.scale.1 { + name m90s2 + min -9000 + step 200 + mute 1 + } + } + } + + # mute switch control + mixer."2" { + Object.Base.channel.1 { + name "flw" + reg 2 + shift 0 + } + Object.Base.channel.2 { + name "fl" + reg 2 + shift 1 + } + Object.Base.channel.3 { + name "fr" + reg 2 + shift 2 + } + Object.Base.channel.4 { + name "frw" + reg 2 + shift 3 + } + + Object.Base.ops.1 { + name "ctl" + info "volsw" + ## get = 259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + + #max 1 indicates switch type control + max 1 + } + } + + # Default attribute values for gain widget + type "pga" + uuid "A8:A9:BC:61:D0:18:18:4A:8E:7B:26:39:21:98:04:B7" + no_pm "true" + cpc 10183 + curve_type "linear" + curve_duration 200000 # 20 ms + init_value 0x7fffffff + num_input_pins 1 + num_output_pins 1 +} 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..063807923d8d --- /dev/null +++ b/tools/topology/topology2/include/components/google-rtc-aec.conf @@ -0,0 +1,159 @@ +# +# 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" + # AEC requires 10ms buffers for processing + BUFFER_PERIOD_MS 10 +} + +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 + <include/components/widget-common.conf> + + DefineAttribute."num_audio_formats" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + Object.Control.bytes."1" { + access [ + tlv_write + tlv_callback + ] + name 'Config' + max 2048 + } + + # 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_input_audio_formats 3 + num_output_audio_formats 2 + # pin0 is the data captured by DMIC and pin1 is the ref data from playback stream + Object.Base.input_audio_format [ + # 2ch 16-bit on Pin 0 + { + input_pin_index 0 + in_bit_depth 16 + in_valid_bit_depth 16 + ibs "$[(($in_channels * ($[($in_rate + 999)] / 1000)) * ($in_bit_depth / 8)) * $BUFFER_PERIOD_MS ]" + } + # 4ch 16-bit on Pin 0 + { + input_pin_index 0 + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + ibs "$[(($in_channels * ($[($in_rate + 999)] / 1000)) * ($in_bit_depth / 8)) * $BUFFER_PERIOD_MS]" + } + # 2ch 16-bit on Pin 1 + { + input_pin_index 1 + in_bit_depth 16 + in_valid_bit_depth 16 + ibs "$[(($in_channels * ($[($in_rate + 999)] / 1000)) * ($in_bit_depth / 8)) * $BUFFER_PERIOD_MS]" + } + ] + + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + obs "$[(($out_channels * ($[($out_rate + 999)] / 1000)) * ($out_bit_depth / 8)) * $BUFFER_PERIOD_MS]" + + } + # 4ch 16-bit + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + obs "$[(($out_channels * ($[($out_rate + 999)] / 1000)) * ($out_bit_depth / 8)) * $BUFFER_PERIOD_MS]" + + } + ] + + # Default attribute values for google-rtc-aec widget + # UUID: B780A0A6-269F-466F-B477-23DFA05AF758 + uuid $AEC_UUID + type "effect" + no_pm "true" + cpc 5000 + is_pages 1 + num_input_pins 2 + num_output_pins 1 +} 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..73911ef6e128 --- /dev/null +++ b/tools/topology/topology2/include/components/host-copier.conf @@ -0,0 +1,128 @@ +# +# 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 + <include/components/widget-common.conf> + + # + # Bespoke Attribute Definitions for host copiers + # + + DefineAttribute."direction" { + type "string" + token_ref "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 "comp.word" + } + + DefineAttribute."bss_size" {} + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."node_type" { + # Token set reference name and type + token_ref "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 "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" + 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 new file mode 100644 index 000000000000..2316d0120363 --- /dev/null +++ b/tools/topology/topology2/include/components/host.conf @@ -0,0 +1,105 @@ +# A generic AIF_IN/AIF_OUT widget. All attributes defined herein are namespaced +# by alsatplg to "Object.host.direction.attribute_name" in the parent object +# +# Usage: host widget can be instantiated by declaring in a parent object as: +# +# For playback: +# Object.Widget.host."playback" { +# index 3 +# type aif_in +# } +# +# For Capture: +# Object.Widget.host."capture" { +# index 4 +# type aif_out +# } + +# +# "host" class belongs to the "Widget" group of classes. +# +Class.Widget."host" { + # + # Attributes for host widget + # + + # + # Pipeline ID that the host widget belongs to + # + DefineAttribute."index" {} + + # + # Host direction + # + DefineAttribute."direction" { + type "string" + constraints { + !valid_values [ + "playback" + "capture" + ] + + } + } + + # + # Host widget type + # + DefineAttribute."type" { + type "string" + constraints { + !valid_values [ + "aif_in" + "aif_out" + ] + + } + } + + #include common widget attributes + <include/components/widget-common.conf> + + # Attribute categories + attributes { + # + # host objects instantiated within the same alsaconf node must have unique value for + # direction attribute + # + unique "direction" + + # + # The host object name is constructed using the index and direction arguments. + # E.g. "host.0.capture" or "host.2.playback" etc + # + !constructor [ + "index" + "direction" + ] + + # + # mandatory attributes that must be provided when the host class is instantiated + # + !mandatory [ + "type" + "stream_name" + ] + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + } + + # + # Default attribute values for host + # + uuid "0c:10:9d:8b:78:6d:8f:41:90:a3:e0:e8:05:d0:85:2b" + no_pm "true" +} diff --git a/tools/topology/topology2/include/components/igo_nr.conf b/tools/topology/topology2/include/components/igo_nr.conf new file mode 100644 index 000000000000..cd85ccb2a3d8 --- /dev/null +++ b/tools/topology/topology2/include/components/igo_nr.conf @@ -0,0 +1,100 @@ +# +# +# This widget class definition is for the Intelligo Noise Reduction +# component. It is a proprietary processing component by Intelligo +# Technology, Inc. Please find the LICENCE from the component source +# directory. The stub version of the library can be freely used to test +# basic functionality of the library with pass-through processing. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.igo_nr.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.igo_nr."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +<include/controls/mixer.conf> + +Class.Widget."igo_nr" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for IGO_NR widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # IGO_NR widget switch control + # + Object.Control { + # Switch controls + mixer."1" { + Object.Base.channel.1 { + name "fl" + shift 0 + } + Object.Base.channel.2 { + name "fr" + } + # Operation volsw is used for single or double mixer + # control. See section control operations in + # https://www.alsa-project.org/alsa-doc/alsa-lib/group__topology.html + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + } + + # + # Default attributes for igo_nr + # + # 696ae2bc-2877-11eb-adc1-0242ac120002 + uuid "bc:e2:6a:69:77:28:eb:11:ad:c1:02:42:ac:12:00:02" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/kpb.conf b/tools/topology/topology2/include/components/kpb.conf new file mode 100644 index 000000000000..03f7989be8ac --- /dev/null +++ b/tools/topology/topology2/include/components/kpb.conf @@ -0,0 +1,76 @@ +# +# Widget kpb +# +# A kpb widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.kpb.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.kpb."N" { +# +# } +# +# Where N is the unique instance number for the kpb object within the same alsaconf node. + +Class.Widget."kpb" { + # + # Pipeline ID for the kpb object + # + DefineAttribute."index" {} + + # + # Kpb object instance + # + DefineAttribute."instance" {} + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + #include common component definition + <include/components/widget-common.conf> + + attributes { + # + # The kpb widget name would be constructed using the index and + # instance attributes. For example: "kpb.0.1". + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + + unique "instance" + } + + # + # Default attributes for kpb + # + type "effect" + + num_input_audio_formats 1 + num_output_audio_formats 1 + + #UUID: D8218443-5FF3-4A4C-B388-6CFE07B9562E + uuid "43:84:21:d8:f3:5f:4c:4a:b3:88:6c:fe:07:b9:56:2e" + no_pm "true" + cpc 720000 + num_input_pins 1 + num_output_pins 2 +} diff --git a/tools/topology/topology2/include/components/level_multiplier.conf b/tools/topology/topology2/include/components/level_multiplier.conf new file mode 100644 index 000000000000..784abe4a6bb7 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier.conf @@ -0,0 +1,65 @@ +# +# +# A generic level_multiplier component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.level_multiplier.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.level_multiplier."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."level_multiplier" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for level_multiplier + # + # 30397456-4661-4644-97e5-39a9e5ab1778 + uuid "56:74:39:30:61:46:44:46:97:e5:39:a9:e5:ab:17:78" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_-10_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_-10_db.conf new file mode 100644 index 000000000000..7c1407a75f68 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_-10_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x27,0x7a,0x28,0x00" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_-20_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_-20_db.conf new file mode 100644 index 000000000000..8c962a9a6c4d --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_-20_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcd,0xcc,0x0c,0x00" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_-30_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_-30_db.conf new file mode 100644 index 000000000000..5f4d179ff1b0 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_-30_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x37,0x0c,0x04,0x00" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_-40_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_-40_db.conf new file mode 100644 index 000000000000..5f17d0c3c15b --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_-40_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xae,0x47,0x01,0x00" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_0_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_0_db.conf new file mode 100644 index 000000000000..dcdf92a889df --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_0_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x80,0x00" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_10_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_10_db.conf new file mode 100644 index 000000000000..981d8c8996a0 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_10_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x84,0xc5,0x94,0x01" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_20_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_20_db.conf new file mode 100644 index 000000000000..bffe8376ab90 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_20_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x05" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_30_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_30_db.conf new file mode 100644 index 000000000000..804145ae4c07 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_30_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x25,0xb7,0xcf,0x0f" +} diff --git a/tools/topology/topology2/include/components/level_multiplier/gain_40_db.conf b/tools/topology/topology2/include/components/level_multiplier/gain_40_db.conf new file mode 100644 index 000000000000..063e3ede5399 --- /dev/null +++ b/tools/topology/topology2/include/components/level_multiplier/gain_40_db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_level_multiplier_blobs.m 19-Aug-2025 +# cd tools/tune/level_multiplier; octave sof_level_multiplier_blobs.m +Object.Base.data."level_multiplier_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x32" +} diff --git a/tools/topology/topology2/include/components/mfcc.conf b/tools/topology/topology2/include/components/mfcc.conf new file mode 100644 index 000000000000..221df8f2d437 --- /dev/null +++ b/tools/topology/topology2/include/components/mfcc.conf @@ -0,0 +1,64 @@ +# +# +# A MFCC component for SOF. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.mfcc.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.mfcc."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."mfcc" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for MFCC widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for mfcc + # + uuid "73:a7:10:db:a4:1a:ea:4c:a2:1f:2d:57:a5:c9:82:eb" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/mfcc/default.conf b/tools/topology/topology2/include/components/mfcc/default.conf new file mode 100644 index 000000000000..42a6d6608b8b --- /dev/null +++ b/tools/topology/topology2/include/components/mfcc/default.conf @@ -0,0 +1,22 @@ +# Exported MFCC configuration 05-May-2026 +# cd src/audio/mfcc/tune; octave setup_mfcc.m +Object.Base.data."mfcc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x80,0x3e,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0xc3,0x35,0x00,0x2c,0x00,0x00,0x00,0x00, + 0x90,0x01,0xa0,0x00,0x00,0x00,0x14,0x00, + 0x0d,0x00,0x17,0x00,0x00,0x00,0x00,0x64, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/mfcc/mel80.conf b/tools/topology/topology2/include/components/mfcc/mel80.conf new file mode 100644 index 000000000000..04aa2a15c660 --- /dev/null +++ b/tools/topology/topology2/include/components/mfcc/mel80.conf @@ -0,0 +1,22 @@ +# Exported MFCC configuration 05-May-2026 +# cd src/audio/mfcc/tune; octave setup_mfcc.m +Object.Base.data."mfcc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x00,0x02,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x80,0x3e,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x90,0x01,0xa0,0x00,0x40,0x1f,0x00,0x00, + 0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x01,0x00,0x00,0x01,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel.conf b/tools/topology/topology2/include/components/micsel.conf new file mode 100644 index 000000000000..bccfe2a85bfe --- /dev/null +++ b/tools/topology/topology2/include/components/micsel.conf @@ -0,0 +1,73 @@ +# +# Common widget micsel +# +# A generic micsel widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.micsel.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.micsel."N" { +# +# } +# +# Where N is the unique instance number for the micsel object within the same alsaconf node. + +Class.Widget."micsel" { + # + # Pipeline ID for the micsel object + # + DefineAttribute."index" {} + + # + # Micsel object instance + # + DefineAttribute."instance" {} + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + #include common component definition + <include/components/widget-common.conf> + + attributes { + # + # The micsel widget name would be constructed using the index and + # instance attributes. For example: "micsel.0.1". + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + + unique "instance" + } + + # + # Default attributes for micsel + # + type "effect" + + #UUID: 32FE92C1-1E17-4FC2-9758-C7F3542E980A + uuid "c1:92:fe:32:17:1e:c2:4f:97:58:c7:f3:54:2e:98:0a" + no_pm "true" + cpc 29000 + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/micsel/downmix_51_to_mono_with_lfe.conf b/tools/topology/topology2/include/components/micsel/downmix_51_to_mono_with_lfe.conf new file mode 100644 index 000000000000..76aa09754ebe --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/downmix_51_to_mono_with_lfe.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6e,0x00,0x6e,0x00, + 0x9c,0x00,0xec,0x01,0x4e,0x00,0x4e,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/downmix_51_to_stereo_with_lfe.conf b/tools/topology/topology2/include/components/micsel/downmix_51_to_stereo_with_lfe.conf new file mode 100644 index 000000000000..0fb37e1d840b --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/downmix_51_to_stereo_with_lfe.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, + 0xb5,0x00,0x96,0x01,0xb5,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0xb5,0x00,0x96,0x01,0x00,0x00,0xb5,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/downmix_71_to_51.conf b/tools/topology/topology2/include/components/micsel/downmix_71_to_51.conf new file mode 100644 index 000000000000..93fe5fb1c3f9 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/downmix_71_to_51.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, + 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/downmix_71_to_mono_with_lfe.conf b/tools/topology/topology2/include/components/micsel/downmix_71_to_mono_with_lfe.conf new file mode 100644 index 000000000000..1e67d36bf839 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/downmix_71_to_mono_with_lfe.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xa4,0x00,0xa4,0x00, + 0xe8,0x00,0x00,0x00,0x74,0x00,0x74,0x00, + 0x74,0x00,0x74,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/downmix_71_to_stereo_with_lfe.conf b/tools/topology/topology2/include/components/micsel/downmix_71_to_stereo_with_lfe.conf new file mode 100644 index 000000000000..b94ea59c1a9e --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/downmix_71_to_stereo_with_lfe.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xda,0x00,0x00,0x00, + 0x9a,0x00,0x59,0x01,0x9a,0x00,0x00,0x00, + 0x9a,0x00,0x00,0x00,0x00,0x00,0xda,0x00, + 0x9a,0x00,0x59,0x01,0x00,0x00,0x9a,0x00, + 0x00,0x00,0x9a,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/downmix_stereo_to_mono.conf b/tools/topology/topology2/include/components/micsel/downmix_stereo_to_mono.conf new file mode 100644 index 000000000000..510d303eb2d9 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/downmix_stereo_to_mono.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/passthrough.conf b/tools/topology/topology2/include/components/micsel/passthrough.conf new file mode 100644 index 000000000000..0b795084ba29 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/passthrough.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04" +} diff --git a/tools/topology/topology2/include/components/micsel/stereo_endpoint_playback_updownmix.conf b/tools/topology/topology2/include/components/micsel/stereo_endpoint_playback_updownmix.conf new file mode 100644 index 000000000000..70500ef0e0fa --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/stereo_endpoint_playback_updownmix.conf @@ -0,0 +1,75 @@ +# Exported with script sof_selector_blobs.m 10-Mar-2026 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x10,0x02,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x08,0x08,0x0c,0x0c,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04,0x01,0x02,0x00,0x01, + 0xd5,0x02,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd5,0x02,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x06,0x02,0x08,0x01,0x00,0x01,0x00,0x00, + 0xb5,0x00,0x96,0x01,0xb5,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0xb5,0x00,0x96,0x01,0x00,0x00,0xb5,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x08,0x02,0x0c,0x01, + 0xda,0x00,0x00,0x00,0x9a,0x00,0x59,0x01, + 0x9a,0x00,0x00,0x00,0x9a,0x00,0x00,0x00, + 0x00,0x00,0xda,0x00,0x9a,0x00,0x59,0x01, + 0x00,0x00,0x9a,0x00,0x00,0x00,0x9a,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/upmix_mono_to_51.conf b/tools/topology/topology2/include/components/micsel/upmix_mono_to_51.conf new file mode 100644 index 000000000000..c19828913473 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/upmix_mono_to_51.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/upmix_mono_to_71.conf b/tools/topology/topology2/include/components/micsel/upmix_mono_to_71.conf new file mode 100644 index 000000000000..c19828913473 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/upmix_mono_to_71.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/upmix_mono_to_stereo.conf b/tools/topology/topology2/include/components/micsel/upmix_mono_to_stereo.conf new file mode 100644 index 000000000000..33ef4a7672f2 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/upmix_mono_to_stereo.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xd5,0x02,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xd5,0x02,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/upmix_stereo_to_51.conf b/tools/topology/topology2/include/components/micsel/upmix_stereo_to_51.conf new file mode 100644 index 000000000000..b411410cab70 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/upmix_stereo_to_51.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/upmix_stereo_to_71.conf b/tools/topology/topology2/include/components/micsel/upmix_stereo_to_71.conf new file mode 100644 index 000000000000..b411410cab70 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/upmix_stereo_to_71.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 04-Jun-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_llrr.conf b/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_llrr.conf new file mode 100644 index 000000000000..4b4be2b34840 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_llrr.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 08-Sep-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_lrlr.conf b/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_lrlr.conf new file mode 100644 index 000000000000..70489a0a0040 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_lrlr.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 08-Sep-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_rrll.conf b/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_rrll.conf new file mode 100644 index 000000000000..d88ba2063cd6 --- /dev/null +++ b/tools/topology/topology2/include/components/micsel/xover_selector_lr_to_rrll.conf @@ -0,0 +1,26 @@ +# Exported with script sof_selector_blobs.m 08-Sep-2025 +# cd tools/tune/selector; octave sof_selector_blobs.m +Object.Base.data."selector_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/mixin.conf b/tools/topology/topology2/include/components/mixin.conf new file mode 100644 index 000000000000..9f9e1adff39c --- /dev/null +++ b/tools/topology/topology2/include/components/mixin.conf @@ -0,0 +1,118 @@ +# +# Common widget mixin +# +# A generic mixin widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.mixin.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.mixin."N" { +# type "mixer" +# mix_type "mix_in" +# } +# +# Where N is the unique instance number for the mixin object within the same alsaconf node. + +Class.Widget."mixin" { + # + # Pipeline ID for the mixin object + # + DefineAttribute."index" {} + + # + # Mixin object instance + # + DefineAttribute."instance" {} + + DefineAttribute."mix_type" { + type "string" + token_ref "mixinout.word" + constraints { + !valid_values [ + "mix_in" + "mix_out" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + #include common component definition + <include/components/widget-common.conf> + + attributes { + # + # The mixin widget name would be constructed using the index and + # instance attributes. For ex: "mixin.0.1". + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "mix_type" + "num_input_pins" + "num_output_pins" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + unique "instance" + } + + # Only 32-bit depth format is supported by mixin + 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 + } + ] + + # + # Default attributes for mixin + # + type "mixer" + mix_type "mix_in" + + #UUID: 39656EB2-3B71-4049-8D3F-F92CD5C43C09 + uuid "b2:6e:65:39:71:3b:49:40:8d:3f:f9:2c:d5:c4:3c:09" + no_pm "true" + cpc 910 + num_input_pins 1 + num_output_pins 3 + +} diff --git a/tools/topology/topology2/include/components/mixout.conf b/tools/topology/topology2/include/components/mixout.conf new file mode 100644 index 000000000000..81e5aecce59d --- /dev/null +++ b/tools/topology/topology2/include/components/mixout.conf @@ -0,0 +1,117 @@ +# +# Common widget mixout +# +# A generic mixout widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.mixout.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.mixout."N" { +# type "mixer" +# mix_type "mix_out" +# } +# +# Where N is the unique instance number for the mixout object within the same alsaconf node. + +Class.Widget."mixout" { + # + # Pipeline ID for the mixout object + # + DefineAttribute."index" {} + + # + # Mixout object instance + # + DefineAttribute."instance" {} + + DefineAttribute."mix_type" { + type "string" + token_ref "mixinout.word" + constraints { + !valid_values [ + "mix_in" + "mix_out" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + #include common component definition + <include/components/widget-common.conf> + + attributes { + # + # The mixout widget name is constructed using the index and instance attributes. + # For ex: "mixout.0.1". + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "mix_type" + "num_input_pins" + "num_output_pins" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + unique "instance" + } + + # Only 32-bit depth format is supported by mixout + 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 + } + ] + + # + # Default attributes for mixout + # + type "mixer" + mix_type "mix_out" + + #UUID: 3C56505A-24D7-418F-BDDC-C1F5A3AC2AE0 + uuid "5a:50:56:3c:d7:24:8f:41:bd:dc:c1:f5:a3:ac:2a:e0" + no_pm "true" + cpc 5000 + num_input_pins 8 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/module-copier.conf b/tools/topology/topology2/include/components/module-copier.conf new file mode 100644 index 000000000000..83748f294cdc --- /dev/null +++ b/tools/topology/topology2/include/components/module-copier.conf @@ -0,0 +1,95 @@ +# +# Module-to-module copier +# +# A module-to-module copier widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.module-copier.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.module-copier."N" { +# index 5 +# cpc 100000 +# } +# +# Where N is the unique instance number for the copier object within the same alsaconf node. + +Class.Widget."module-copier" { + # + # Pipeline ID for the module-copier object + # + DefineAttribute."index" {} + + # + # module-copier object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke Attribute Definitions for module-copiers + # + + # + # cycles per chunk processed + # + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."bss_size" {} + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + attributes { + # + # The module-copier widget name would be constructed using the index and + # instance attributes. For ex: "module-copier.1.2". + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the module-copier class is + # instantiated + # + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + "type" + ] + + unique "instance" + } + + # + # Default attributes for module-copier + # + #UUID: 9BA00C83-CA12-4A83-943C-1FA2E82F9DDA. This is same as that of a host/DAI copier + uuid "83:0c:a0:9b:12:CA:83:4a:94:3c:1f:a2:e8:2f:9d:da" + type "buffer" + no_pm "true" + cpc 1647 + bss_size 280 + num_input_pins 1 + num_output_pins 4 + + # math expression for computing is_pages + is_pages "$[(($bss_size + 4095) & -4095) / 4096]" +} diff --git a/tools/topology/topology2/include/components/multiband_drc.conf b/tools/topology/topology2/include/components/multiband_drc.conf new file mode 100644 index 000000000000..a7855c3b21d2 --- /dev/null +++ b/tools/topology/topology2/include/components/multiband_drc.conf @@ -0,0 +1,88 @@ +# +# +# A generic MULTIBAND_DRC component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.multiband_drc.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.multiband_drc."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +<include/controls/bytes.conf> +<include/controls/mixer.conf> + +Class.Widget."multiband_drc" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for MULTIBAND_DRC widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # multiband_drc widget switch control + # + Object.Control { + mixer."1" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + } + + # + # Default attributes for multiband_drc + # + + uuid "56:22:9f:0d:4f:8e:b3:47:84:48:23:9a:33:4f:11:91" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/multiband_drc/default.conf b/tools/topology/topology2/include/components/multiband_drc/default.conf new file mode 100644 index 000000000000..5412f03a7cda --- /dev/null +++ b/tools/topology/topology2/include/components/multiband_drc/default.conf @@ -0,0 +1,82 @@ +# Exported with script sof_example_multiband_drc.m 18-Oct-2024 +Object.Base.data."multiband_drc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x4c,0x02,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x4c,0x02,0x00,0x00,0x03,0x00,0x00,0x00, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x59,0xa5,0xa3,0xfc, + 0x0b,0xdc,0xf0,0x20,0x76,0xe4,0x5e,0x03, + 0x8d,0x98,0x04,0xdf,0x00,0x00,0x00,0x40, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x88,0xf6,0x5c,0xe1,0x67,0xb2,0x3a,0x59, + 0xc3,0xd0,0xa8,0x1e,0x78,0x3b,0xbd,0xa6, + 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00, + 0x2a,0x40,0x00,0x00,0x8a,0x1b,0xa1,0xfc, + 0x73,0x67,0xfb,0x20,0x87,0x92,0x5b,0x03, + 0x7a,0xcd,0x16,0xdf,0x02,0x1d,0xf1,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x3d,0x2f,0x57,0xe1,0x88,0xc4,0x42,0x59, + 0xb9,0x0c,0x96,0x1e,0xdd,0x20,0xeb,0xa6, + 0xa6,0xde,0xe4,0x3f,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x2d,0x3a,0xcd,0xd3, + 0xc0,0xf5,0x82,0x68,0x05,0xf4,0xeb,0x00, + 0x0a,0xe8,0xd7,0x01,0x05,0xf4,0xeb,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x2d,0x3a,0xcd,0xd3,0xc0,0xf5,0x82,0x68, + 0xe5,0x6e,0x2d,0x35,0x36,0x22,0xa5,0x95, + 0xe5,0x6e,0x2d,0x35,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0xe7,0x26,0x9d,0xf0, + 0x8d,0x6c,0xb1,0x27,0x23,0x5b,0xec,0x09, + 0x46,0xb6,0xd8,0x13,0x23,0x5b,0xec,0x09, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xe7,0x26,0x9d,0xf0,0x8d,0x6c,0xb1,0x27, + 0x6a,0x11,0xc5,0x1d,0x2d,0xdd,0x75,0xc4, + 0x6a,0x11,0xc5,0x1d,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0xe7,0x26,0x9d,0xf0, + 0x8d,0x6c,0xb1,0x27,0x23,0x5b,0xec,0x09, + 0x46,0xb6,0xd8,0x13,0x23,0x5b,0xec,0x09, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xe7,0x26,0x9d,0xf0,0x8d,0x6c,0xb1,0x27, + 0x6a,0x11,0xc5,0x1d,0x2d,0xdd,0x75,0xc4, + 0x6a,0x11,0xc5,0x1d,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x14, + 0x00,0x00,0x00,0x0a,0xd3,0x4d,0x62,0x00, + 0x8a,0x1b,0x06,0x02,0x66,0x66,0x66,0x06, + 0x2f,0x97,0xba,0x00,0x18,0x0c,0x1e,0x00, + 0x20,0x42,0xe0,0xff,0x4e,0xf4,0x50,0x00, + 0x9a,0x9f,0x34,0x08,0x0b,0xfa,0x6d,0x03, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00, + 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00, + 0x5b,0x91,0x00,0x00,0x02,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x14, + 0x00,0x00,0x00,0x0a,0xd3,0x4d,0x62,0x00, + 0x8a,0x1b,0x06,0x02,0x66,0x66,0x66,0x06, + 0x2f,0x97,0xba,0x00,0x18,0x0c,0x1e,0x00, + 0x20,0x42,0xe0,0xff,0x4e,0xf4,0x50,0x00, + 0x9a,0x9f,0x34,0x08,0x0b,0xfa,0x6d,0x03, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00, + 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00, + 0x5b,0x91,0x00,0x00,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x14, + 0x00,0x00,0x00,0x0a,0xd3,0x4d,0x62,0x00, + 0x8a,0x1b,0x06,0x02,0x66,0x66,0x66,0x06, + 0x2f,0x97,0xba,0x00,0x18,0x0c,0x1e,0x00, + 0x20,0x42,0xe0,0xff,0x4e,0xf4,0x50,0x00, + 0x9a,0x9f,0x34,0x08,0x0b,0xfa,0x6d,0x03, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00, + 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00, + 0x5b,0x91,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/multiband_drc/passthrough.conf b/tools/topology/topology2/include/components/multiband_drc/passthrough.conf new file mode 100644 index 000000000000..09cb3c4f4ac8 --- /dev/null +++ b/tools/topology/topology2/include/components/multiband_drc/passthrough.conf @@ -0,0 +1,71 @@ +# Exported with script example_multiband_drc.m 01-Sep-2023 +Object.Base.data."multiband_drc_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xf4,0x01,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf4,0x01,0x00,0x00,0x02,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7b,0x8e,0x88,0xfe, + 0x36,0x79,0x57,0x17,0x5f,0x19,0x6f,0x06, + 0xe8,0x79,0x67,0xd4,0x00,0x00,0x00,0x40, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x5f,0x6d,0x19,0xe7,0x39,0xc4,0xd4,0x50, + 0x0c,0x9b,0x09,0x24,0xad,0x76,0x82,0x9f, + 0x00,0x00,0x00,0x40,0xff,0xff,0xff,0xff, + 0x43,0x72,0x00,0x00,0xa1,0xe6,0x90,0xf9, + 0x18,0x86,0x98,0x2b,0xe3,0x32,0xef,0x00, + 0x4b,0xf7,0x20,0xf1,0x18,0x69,0xc6,0x28, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0xf4,0x64,0xf6,0xdb,0x53,0x89,0x7d,0x60, + 0x5c,0x14,0xf2,0x0a,0x84,0x0d,0x78,0xdc, + 0xda,0xef,0x21,0x1c,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x6f,0x82,0x53,0xc2, + 0x3e,0x77,0xa1,0x7d,0x95,0xc1,0x02,0x00, + 0x2a,0x83,0x05,0x00,0x95,0xc1,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x6f,0x82,0x53,0xc2,0x3e,0x77,0xa1,0x7d, + 0x34,0x7d,0xd3,0x3e,0x99,0x05,0x59,0x82, + 0x34,0x7d,0xd3,0x3e,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e, + 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00, + 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05, + 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00, + 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01, + 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00, + 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00, + 0x5b,0x91,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xe8,0x00,0x00,0x00,0x1e, + 0x00,0x00,0x00,0x0c,0xd3,0x4d,0x62,0x00, + 0xb1,0xc2,0x09,0x04,0x55,0x55,0x55,0x05, + 0x50,0xfa,0x1e,0x00,0x55,0x60,0x94,0x00, + 0x7e,0x98,0x6a,0xff,0x83,0xc9,0xfe,0x01, + 0x64,0x47,0x47,0x22,0x17,0x56,0x74,0x01, + 0x1c,0xc7,0x71,0x00,0x77,0x77,0x77,0xff, + 0xd8,0x77,0x1f,0x00,0x05,0x00,0x00,0x00, + 0x00,0x00,0x36,0x00,0xdf,0x97,0x03,0x00, + 0xe7,0x3e,0x1e,0x00,0xdf,0x97,0x07,0x00, + 0x5b,0x91,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/muxdemux.conf b/tools/topology/topology2/include/components/muxdemux.conf new file mode 100644 index 000000000000..71f038c26939 --- /dev/null +++ b/tools/topology/topology2/include/components/muxdemux.conf @@ -0,0 +1,68 @@ +# +# A generic MUX/DEMUX component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.muxdemux.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget { +# muxdemux."N" { +# index 3 +# format "s24le" +# } +# } + +# +# Where N is a unique integer in the parent object. + +Class.Widget."muxdemux" { + # + # Argument used to construct component: pipeline ID + # + DefineAttribute."index" {} + + # + # Unique instance ID for muxdemux widget in the same alsaconf node + # + DefineAttribute."instance" {} + + + #include common widget attribute definitions + <include/components/widget-common.conf> + + # + # Process type for muxdemux widget + # + DefineAttribute.process_type { + type "string" + # Token set reference name and type + token_ref "process.string" + } + + # attribute categories + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "format" + ] + !immutable [ + "uuid" + "type" + "process_type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attribute values for muxdemux widget + # + uuid "68:68:b2:c4:30:14:0e:47:a0:89:15:d1:c7:7f:85:1a" + process_type "DEMUX" + widget_type "effect" + no_pm "true" +} diff --git a/tools/topology/topology2/include/components/ov_noise_suppression.conf b/tools/topology/topology2/include/components/ov_noise_suppression.conf new file mode 100644 index 000000000000..ff06f1fedf6a --- /dev/null +++ b/tools/topology/topology2/include/components/ov_noise_suppression.conf @@ -0,0 +1,81 @@ +# +# OpenVino noise suppression module +# +# A noise suppression widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.ov_ns.N.attribute_name" +# +# Usage: this component can be used by declaring int a parent object. i.e. +# +# Object.Widget.ov_ns."N" { +# index 1 +# no_pm "true" +# } +# +# Where N is the unique instance number for ov_ns widget in the same alsaconf node. + +Class.Widget."ov_ns" { + # + # Pipeline ID for the ov_ns widget object + # + DefineAttribute."index" {} + + # + # ov_ns object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # Only 16-bit depth format is supported by ov_ns + num_input_audio_formats 1 + num_output_audio_formats 1 + # 16-bit 16KHz 2ch + Object.Base.input_audio_format [ + { + in_rate 16000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + Object.Base.output_audio_format [ + { + out_rate 16000 + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + + # Attribute categories + attributes { + # + # The ov_ns widget name would be constructed using the index and instance attributes. + # For ex: "ov_ns.1.1" or "ov_ns.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + "type" + ] + + # + # ov_ns widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for ov_ns widget + type "effect" + uuid "a7:71:e6:7a:17:46:09:4a:bf:6d:9d:29:c9:98:db:c1" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/pipeline.conf b/tools/topology/topology2/include/components/pipeline.conf new file mode 100644 index 000000000000..caf972250f3e --- /dev/null +++ b/tools/topology/topology2/include/components/pipeline.conf @@ -0,0 +1,174 @@ +# +# Class definition for pipeline widget +# +# This should be included within a pipeline class +# +# Usage: this component can be used by declaring in a parent object. i.e. +# +# Object.Widget.pipeline."N" { +# index 1 +# time_domain "timer" +# period 1000 +# } +# +# Where N is the unique instance number for pipeline widget in the same alsaconf node. + +Define { + # If KCPS value for the pipeline is 0 then the driver does not send any + # KCPS adjustment message to the firmware. This is the default. + KCPS_PIPELINE_DEFAULT 0 +} + +Class.Widget."pipeline" { + # pipeline_id for the pipeline widget + DefineAttribute."index" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke Tuples for Pipelines + # + + # Scheduling period + DefineAttribute."period" { + # Token reference and type + token_ref "scheduler.word" + constraints { + min 333 + max 1000 + } + } + + # Scheduler time domain. The value provided will be translated to 0/1 based on + # scheduler_time_domain. For exameple: "timer" will be converted to 0. + DefineAttribute."time_domain" { + # Token reference and type + token_ref "scheduler.word" + constraints { + !valid_values [ + "timer" + "dma" + ] + !tuple_values [ + 1 + 0 + ] + } + } + + # pipeline priority (0 = highest priority, 7 = lowest) + DefineAttribute."priority" { + # Token reference and type + token_ref "scheduler.word" + constraints { + min 0 + max 7 + } + } + + # core that the pipeline should be scheduled on + DefineAttribute."core" { + # Token reference and type + token_ref "scheduler.word" + } + + # frames per period + DefineAttribute."frames" { + # Token reference and type + token_ref "scheduler.word" + } + + # mips requirement for pipeline + DefineAttribute."mips" { + # Token reference and type + token_ref "scheduler.word" + } + + # flag to set the pipeline as dynamic + DefineAttribute."dynamic_pipeline" { + # Token reference and type + token_ref "scheduler.word" + } + + DefineAttribute."lp_mode" { + # Token reference and type + token_ref "scheduler.word" + constraints { + !tuple_values [ + 1 + 0 + ] + } + } + + DefineAttribute."direction" { + type "string" + token_ref "scheduler.word" + constraints { + !valid_values [ + "playback" + "capture" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + DefineAttribute."direction_valid" { + type "string" + token_ref "scheduler.bool" + constraints { + !valid_values [ + "true" + "false" + ] + } + } + + # Skip setting up the pipeline in the DSP in the case of chained DMA mode + DefineAttribute."use_chain_dma" { + type "string" + token_ref "scheduler.bool" + constraints { + !valid_values [ + "true" + "false" + ] + } + } + + # kcps requirements for the pipeline, default value defined bellow + DefineAttribute."kcps" { + # Token reference and type + token_ref "scheduler.word" + } + + attributes { + # pipeline widget name will be constructed as pipeline.1, pipeline.2 etc + !constructor [ + "index" + ] + !mandatory [ + "instance" + ] + !immutable [ + "type" + ] + !deprecated [ + "preload_count" + ] + # + # pipeline widget objects instantiated within the same alsaconf node must have + # unique instance attribute + unique instance + } + + # Default attributes for pipeline + type "scheduler" + no_pm "true" + kcps $KCPS_PIPELINE_DEFAULT + direction_valid "true" +} diff --git a/tools/topology/topology2/include/components/rtnr.conf b/tools/topology/topology2/include/components/rtnr.conf new file mode 100644 index 000000000000..995870995d61 --- /dev/null +++ b/tools/topology/topology2/include/components/rtnr.conf @@ -0,0 +1,86 @@ +# +# +# A generic RTNR component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.rtnr.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.rtnr."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +<include/controls/mixer.conf> + +Class.Widget."rtnr" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for RTNR widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + + # RTNR widget switch control + Object.Control { + mixer."1" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + } + + # + # Default attributes for rtnr + # + # 5c7ca334-e15d-11eb-ba80-0242ac130004 + uuid "34:a3:7c:5c:5d:e1:eb:11:ba:80:02:42:ac:13:00:04" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/rtnr/default_bytes.conf b/tools/topology/topology2/include/components/rtnr/default_bytes.conf new file mode 100644 index 000000000000..a9a83bd9c2ad --- /dev/null +++ b/tools/topology/topology2/include/components/rtnr/default_bytes.conf @@ -0,0 +1,13 @@ +# Copied and modified for IPC4 from RTNR bytes in +# tools/topology/topology1/sof/pipe-rtnr-google-rtc-audio-processing-capture.m4 +# param_id = 0 for SOF_RTNR_CONFIG +Object.Base.data."rtnr_bytes_config" { + bytes "0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0x30,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x80,0xbb,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/rtnr/default_data.conf b/tools/topology/topology2/include/components/rtnr/default_data.conf new file mode 100644 index 000000000000..86b601c37971 --- /dev/null +++ b/tools/topology/topology2/include/components/rtnr/default_data.conf @@ -0,0 +1,9 @@ +# Copied and modified for IPC4 from RTNR data in +# tools/topology/topology1/sof/pipe-rtnr-google-rtc-audio-processing-capture.m4 +# param_id = 1 for SOF_RTNR_DATA +Object.Base.data."rtnr_data_config" { + bytes "0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x30,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/siggen.conf b/tools/topology/topology2/include/components/siggen.conf new file mode 100644 index 000000000000..ba806f8ae7dc --- /dev/null +++ b/tools/topology/topology2/include/components/siggen.conf @@ -0,0 +1,79 @@ +# +# Signal generator +# +# A generic siggen widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.siggen.N.attribute_name" +# +# Usage: this component can be used by declaring in a parent object. i.e. +# +# Object.Widget.siggen."N" { +# index 1 +# format s32le +# no_pm "true" +# } +# +# Where N is the unique instance number for siggen widget in the same alsaconf node. + +Class.Widget."siggen" { + # + # Pipeline ID for the siggen widget object + # + DefineAttribute."index" {} + + # + # siggen object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # Attribute categories + attributes { + # + # The siggen widget name would be constructed using the index and instance attributes. + # For ex: "siggen.1.1" or "siggen.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # 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" + ] + + # + # siggen widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # siggen only supports one output pin with 32-bit audio format + num_output_pins 1 + num_output_audio_formats 1 + + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + # Default attribute values for siggen widget + type "effect" + uuid "94:f8:e3:04:5c:2c:2e:4f:8d:c1:69:4e:ea:ab:53:fa" + no_pm "true" +} diff --git a/tools/topology/topology2/include/components/smart_amp.conf b/tools/topology/topology2/include/components/smart_amp.conf new file mode 100644 index 000000000000..5f446437012d --- /dev/null +++ b/tools/topology/topology2/include/components/smart_amp.conf @@ -0,0 +1,120 @@ +# +# Common widget smart_amp +# +# A generic smart_amp widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.smart_amp.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.smart_amp."N" { +# index 1 +# type "effect" +# } +# +# Where N is the unique instance number for the smart_amp object within the same alsaconf node. + +# set the default the SMART_AMP_UUID to be that of the test smart amp module. +# The top-level machine topology must override this definition to use a different module +Define { + SMART_AMP_UUID "1e:96:7a:16:e4:8a:ea:11:89:f1:00:0c:29:ce:16:35" +} + +Class.Widget."smart_amp" { + # + # Pipeline ID for the smart_amp widget object + # + DefineAttribute."index" {} + + #include common component definition + <include/components/widget-common.conf> + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + Object.Control.bytes."1" { + !access [ + tlv_read + tlv_callback + ] + Object.Base.extops.1 { + name "extctl" + get 258 + put 0 + } + max 4096 + Object.Base.data. 1 { + IncludeByKey.SMART_AMP_UUID { + # smart amp init data for the test smart amp module + "1e:96:7a:16:e4:8a:ea:11:89:f1:00:0c:29:ce:16:35" { + bytes "0x53, 0x4f, 0x46, 0x34, 0x02, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff" + } + } + } + } + + # Attribute categories + attributes { + # + # The smart_amp widget name would be constructed using the index and instance attributes. + # For ex: "smart_amp.1.1" or "smart_amp.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "type" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + # + # smart_amp widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default attribute values for smart_amp widget + + # UUID can be overridden in the top-level topology file + uuid $SMART_AMP_UUID + type "effect" + no_pm "true" + cpc 5000 + is_pages 1 + num_input_pins 2 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/sound_dose.conf b/tools/topology/topology2/include/components/sound_dose.conf new file mode 100644 index 000000000000..264da305e35d --- /dev/null +++ b/tools/topology/topology2/include/components/sound_dose.conf @@ -0,0 +1,67 @@ +# +# +# A Sound Dose component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.sound_dose.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.sound_dose."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."sound_dose" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for Sound Dose widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for sound_dose + # + + # uuid a43f9d7c-ea75-44d5-942d967991a33809 + + uuid "7c:9d:3f:a4:75:ea:d5:44:94:2d:96:79:91:a3:38:09" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/sound_dose/setup_data_init.conf b/tools/topology/topology2/include/components/sound_dose/setup_data_init.conf new file mode 100644 index 000000000000..c75e8ed60392 --- /dev/null +++ b/tools/topology/topology2/include/components/sound_dose/setup_data_init.conf @@ -0,0 +1,9 @@ +# Exported with script sof_sound_dose_blobs.m 17-Sep-2025 +# cd src/audio/sound_dose/tune; octave sof_sound_dose_blobs.m +Object.Base.data."sound_dose_config" { + bytes " + 0x53,0x4f,0x46,0x34,0xca,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/sound_dose/setup_gain_0db.conf b/tools/topology/topology2/include/components/sound_dose/setup_gain_0db.conf new file mode 100644 index 000000000000..4d64fab9a11c --- /dev/null +++ b/tools/topology/topology2/include/components/sound_dose/setup_gain_0db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_sound_dose_blobs.m 17-Sep-2025 +# cd src/audio/sound_dose/tune; octave sof_sound_dose_blobs.m +Object.Base.data."sound_dose_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x02,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/sound_dose/setup_sens_0db.conf b/tools/topology/topology2/include/components/sound_dose/setup_sens_0db.conf new file mode 100644 index 000000000000..ff32c00a6714 --- /dev/null +++ b/tools/topology/topology2/include/components/sound_dose/setup_sens_0db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_sound_dose_blobs.m 17-Sep-2025 +# cd src/audio/sound_dose/tune; octave sof_sound_dose_blobs.m +Object.Base.data."sound_dose_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/sound_dose/setup_sens_100db.conf b/tools/topology/topology2/include/components/sound_dose/setup_sens_100db.conf new file mode 100644 index 000000000000..5c54f455a25c --- /dev/null +++ b/tools/topology/topology2/include/components/sound_dose/setup_sens_100db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_sound_dose_blobs.m 17-Sep-2025 +# cd src/audio/sound_dose/tune; octave sof_sound_dose_blobs.m +Object.Base.data."sound_dose_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x10,0x27,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/sound_dose/setup_vol_0db.conf b/tools/topology/topology2/include/components/sound_dose/setup_vol_0db.conf new file mode 100644 index 000000000000..d75c1503a44b --- /dev/null +++ b/tools/topology/topology2/include/components/sound_dose/setup_vol_0db.conf @@ -0,0 +1,10 @@ +# Exported with script sof_sound_dose_blobs.m 17-Sep-2025 +# cd src/audio/sound_dose/tune; octave sof_sound_dose_blobs.m +Object.Base.data."sound_dose_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x01,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/src.conf b/tools/topology/topology2/include/components/src.conf new file mode 100644 index 000000000000..abb07bc5723e --- /dev/null +++ b/tools/topology/topology2/include/components/src.conf @@ -0,0 +1,89 @@ +# +# +# A generic SRC component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.src.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.src."N" { +# format "s24le" +# rate_out 48000 +# } +# +# Where N is the unique instance number for the src widget within the same alsaconf node. + +Class.Widget."src" { + # + # Pipeline ID for the src widget object + # + DefineAttribute."index" {} + + # + # SRC object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke attributes for SRC + # + + # Source sample rate + DefineAttribute."rate_in" { + # Token set reference name and type + token_ref "src.word" + + } + + # Target sample rate + DefineAttribute."rate_out" { + # Token set reference name and type + token_ref "src.word" + } + + attributes { + # + # The SRC widget name would be constructed using the index and instance attributes. + # For ex: "src.1.1" or "src.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + !mandatory [ + "num_input_audio_formats" + "num_output_audio_formats" + "num_input_pins" + "num_output_pins" + ] + + # + # 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" + ] + + unique "instance" + } + + # + # Default attributes for src + # + type "src" + uuid "8d:b2:1b:e6:9a:14:1f:4c:b7:09:46:82:3e:f5:f5:ae" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/src_format_s16_convert_from_48k.conf b/tools/topology/topology2/include/components/src_format_s16_convert_from_48k.conf new file mode 100644 index 000000000000..c0b3eb1823c0 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s16_convert_from_48k.conf @@ -0,0 +1,43 @@ +#src format array + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 12000 + 16000 + 24000 + 32000 + 48000 + 64000 + 96000 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + { + out_rate [ + 11025 + 22050 + 44100 + 88200 + 176400 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + # actual buffer size in sof is obs * 2, so here simply set to its period size + obs "$[$out_channels * ($out_bit_depth / 8) * (($out_rate / 1000)) * ($period / 1000)]" + } + ] + + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s16_convert_to_48k.conf b/tools/topology/topology2/include/components/src_format_s16_convert_to_48k.conf new file mode 100644 index 000000000000..7b51094462d5 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s16_convert_to_48k.conf @@ -0,0 +1,35 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + ] + + num_output_audio_formats 1 + + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s16_passthrough.conf b/tools/topology/topology2/include/components/src_format_s16_passthrough.conf new file mode 100644 index 000000000000..1c35a9a80164 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s16_passthrough.conf @@ -0,0 +1,50 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + ] + + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s16_to_sxx_convert.conf b/tools/topology/topology2/include/components/src_format_s16_to_sxx_convert.conf new file mode 100644 index 000000000000..8e94c11c65e2 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s16_to_sxx_convert.conf @@ -0,0 +1,73 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + ] + + num_output_audio_formats 42 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ + 24 + 32 + ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s24_convert_from_48k.conf b/tools/topology/topology2/include/components/src_format_s24_convert_from_48k.conf new file mode 100644 index 000000000000..45697da0db87 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s24_convert_from_48k.conf @@ -0,0 +1,43 @@ +#src format array + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 12000 + 16000 + 24000 + 32000 + 48000 + 64000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 24 ] + } + { + out_rate [ + 11025 + 22050 + 44100 + 88200 + 176400 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 24 ] + # actual buffer size in sof is obs * 2, so here simply set to its period size + obs "$[$out_channels * ($out_bit_depth / 8) * (($out_rate / 1000)) * ($period / 1000)]" + } + ] + + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s24_convert_to_48k.conf b/tools/topology/topology2/include/components/src_format_s24_convert_to_48k.conf new file mode 100644 index 000000000000..e4122a1ad78a --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s24_convert_to_48k.conf @@ -0,0 +1,35 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 24 ] + } + ] + + num_output_audio_formats 1 + + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s24_passthrough.conf b/tools/topology/topology2/include/components/src_format_s24_passthrough.conf new file mode 100644 index 000000000000..25870ea864f6 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s24_passthrough.conf @@ -0,0 +1,50 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 24 ] + } + ] + + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 24 ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s24_to_sxx_convert.conf b/tools/topology/topology2/include/components/src_format_s24_to_sxx_convert.conf new file mode 100644 index 000000000000..cc94937f8b57 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s24_to_sxx_convert.conf @@ -0,0 +1,73 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 24 ] + } + ] + + num_output_audio_formats 42 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ + 24 + 32 + ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s32_convert_from_48k.conf b/tools/topology/topology2/include/components/src_format_s32_convert_from_48k.conf new file mode 100644 index 000000000000..7982d2d171ec --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s32_convert_from_48k.conf @@ -0,0 +1,44 @@ +#src format array + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 12000 + 16000 + 24000 + 32000 + 48000 + 64000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + } + { + out_rate [ + 11025 + 22050 + 44100 + 88200 + 176400 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + # actual buffer size in sof is obs * 2, so here simply set to its period size + obs "$[$out_channels * ($out_bit_depth / 8) * (($out_rate / 1000)) * ($period / 1000)]" + } + ] + + num_input_audio_formats 1 + + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + ibs 512 + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s32_convert_to_48k.conf b/tools/topology/topology2/include/components/src_format_s32_convert_to_48k.conf new file mode 100644 index 000000000000..9b47223ec555 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s32_convert_to_48k.conf @@ -0,0 +1,35 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 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_format_s32_passthrough.conf b/tools/topology/topology2/include/components/src_format_s32_passthrough.conf new file mode 100644 index 000000000000..97d87c9b24c4 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s32_passthrough.conf @@ -0,0 +1,50 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + } + ] + + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_s32_to_sxx_convert.conf b/tools/topology/topology2/include/components/src_format_s32_to_sxx_convert.conf new file mode 100644 index 000000000000..3f57456d836f --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_s32_to_sxx_convert.conf @@ -0,0 +1,73 @@ +#src format array + num_input_audio_formats 14 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + } + ] + + num_output_audio_formats 42 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ + 24 + 32 + ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_sxx_to_s16_convert.conf b/tools/topology/topology2/include/components/src_format_sxx_to_s16_convert.conf new file mode 100644 index 000000000000..22ae30485f95 --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_sxx_to_s16_convert.conf @@ -0,0 +1,73 @@ +#src format array + num_input_audio_formats 42 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ + 24 + 32 + ] + } + ] + + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_sxx_to_s24_convert.conf b/tools/topology/topology2/include/components/src_format_sxx_to_s24_convert.conf new file mode 100644 index 000000000000..38c65d43b26b --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_sxx_to_s24_convert.conf @@ -0,0 +1,73 @@ +#src format array + num_input_audio_formats 42 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ + 24 + 32 + ] + } + ] + + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 24 ] + } + ] diff --git a/tools/topology/topology2/include/components/src_format_sxx_to_s32_convert.conf b/tools/topology/topology2/include/components/src_format_sxx_to_s32_convert.conf new file mode 100644 index 000000000000..941bf69f30bf --- /dev/null +++ b/tools/topology/topology2/include/components/src_format_sxx_to_s32_convert.conf @@ -0,0 +1,73 @@ +#src format array + num_input_audio_formats 42 + + CombineArrays.Object.Base.input_audio_format [ + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ + 24 + 32 + ] + } + ] + + num_output_audio_formats 14 + + CombineArrays.Object.Base.output_audio_format [ + { + out_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + } + ] diff --git a/tools/topology/topology2/include/components/src_lite.conf b/tools/topology/topology2/include/components/src_lite.conf new file mode 100644 index 000000000000..264e28683d7c --- /dev/null +++ b/tools/topology/topology2/include/components/src_lite.conf @@ -0,0 +1,89 @@ +# +# +# A generic src_lite component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.src_lite.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.src_lite."N" { +# format "s24le" +# rate_out 48000 +# } +# +# Where N is the unique instance number for the src_lite widget within the same alsaconf node. + +Class.Widget."src_lite" { + # + # Pipeline ID for the src_lite widget object + # + DefineAttribute."index" {} + + # + # src_lite object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke attributes for src_lite + # + + # Source sample rate + DefineAttribute."rate_in" { + # Token set reference name and type + token_ref "src.word" + + } + + # Target sample rate + DefineAttribute."rate_out" { + # Token set reference name and type + token_ref "src.word" + } + + attributes { + # + # The src_lite widget name would be constructed using the index and instance attributes. + # For ex: "src_lite.1.1" or "src_lite.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + !mandatory [ + "num_input_audio_formats" + "num_output_audio_formats" + "num_input_pins" + "num_output_pins" + ] + + # + # 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" + ] + + unique "instance" + } + + # + # Default attributes for src_lite + # + type "src" + uuid "51:10:44:33:cd:44:6a:46:83:a3:17:84:78:70:8a:ea" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/stft_process.conf b/tools/topology/topology2/include/components/stft_process.conf new file mode 100644 index 000000000000..7e78352ddc4e --- /dev/null +++ b/tools/topology/topology2/include/components/stft_process.conf @@ -0,0 +1,64 @@ +# +# +# A STFT_PROCESS component for SOF. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.stft_process.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.stft_process."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +Class.Widget."stft_process" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for STFT_PROCESS widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # Default attributes for stft_process + # + uuid "a6:6e:11:0d:50:91:de:46:98:b8:b2:b3:a7:91:da:29" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/stft_process/hann_1024_256.conf b/tools/topology/topology2/include/components/stft_process/hann_1024_256.conf new file mode 100644 index 000000000000..761398162213 --- /dev/null +++ b/tools/topology/topology2/include/components/stft_process/hann_1024_256.conf @@ -0,0 +1,17 @@ +# Exported STFT_PROCESS configuration 22-Dec-2025 +# cd tools/tune/stft_process; octave setup_stft_process.m +Object.Base.data."stft_process_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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, + 0x01,0xb0,0x6a,0x55,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/stft_process/hann_1536_240.conf b/tools/topology/topology2/include/components/stft_process/hann_1536_240.conf new file mode 100644 index 000000000000..497693eefde8 --- /dev/null +++ b/tools/topology/topology2/include/components/stft_process/hann_1536_240.conf @@ -0,0 +1,17 @@ +# Exported STFT_PROCESS configuration 22-Dec-2025 +# cd tools/tune/stft_process; octave setup_stft_process.m +Object.Base.data."stft_process_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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, + 0x5f,0x3a,0x5e,0x35,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x06,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/stft_process/hann_192_48.conf b/tools/topology/topology2/include/components/stft_process/hann_192_48.conf new file mode 100644 index 000000000000..4ed5586b1f54 --- /dev/null +++ b/tools/topology/topology2/include/components/stft_process/hann_192_48.conf @@ -0,0 +1,17 @@ +# Exported STFT_PROCESS configuration 22-Dec-2025 +# cd tools/tune/stft_process; octave setup_stft_process.m +Object.Base.data."stft_process_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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, + 0xf1,0xb4,0xc7,0x55,0x00,0x00,0x00,0x00, + 0x00,0x00,0xc0,0x00,0x30,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/stft_process/hann_512_128.conf b/tools/topology/topology2/include/components/stft_process/hann_512_128.conf new file mode 100644 index 000000000000..61f9c20b0cdd --- /dev/null +++ b/tools/topology/topology2/include/components/stft_process/hann_512_128.conf @@ -0,0 +1,17 @@ +# Exported STFT_PROCESS configuration 22-Dec-2025 +# cd tools/tune/stft_process; octave setup_stft_process.m +Object.Base.data."stft_process_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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, + 0x60,0x15,0x80,0x55,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0x80,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/stft_process/hann_768_120.conf b/tools/topology/topology2/include/components/stft_process/hann_768_120.conf new file mode 100644 index 000000000000..23aa3e4da281 --- /dev/null +++ b/tools/topology/topology2/include/components/stft_process/hann_768_120.conf @@ -0,0 +1,17 @@ +# Exported STFT_PROCESS configuration 22-Dec-2025 +# cd tools/tune/stft_process; octave setup_stft_process.m +Object.Base.data."stft_process_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x01,0xd0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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, + 0x61,0x22,0x67,0x35,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x03,0x78,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb.conf b/tools/topology/topology2/include/components/tdfb.conf new file mode 100644 index 000000000000..aa8a39a82b3c --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb.conf @@ -0,0 +1,175 @@ +# +# +# A generic Time Domain Fixed Beamformer (TDFB) component. All attributes +# defined herein are namespaced by alsatplg to +# "Object.Widget.tdfb.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.tdfb."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +<include/controls/mixer.conf> +<include/controls/enum.conf> + +Class.Widget."tdfb" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for TDFB widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # tdfb widget switch control + # + Object.Control { + # Switch controls + mixer."1" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + mixer."2" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + + # Enum controls + enum."1" { + Object.Base { + channel.1 { + name "fc" + reg 3 + shift 0 + } + text.0 { + name "tdfb_enum_plus_minus_90_text" + !values [ + "-90" + "-75" + "-60" + "-45" + "-30" + "-15" + "0" + "15" + "30" + "45" + "60" + "75" + "90" + ] + } + ops.1 { + name "ctl" + info "enum" + #257 binds the mixer control to enum get/put handlers + get 257 + put 257 + } + } + } + enum."2" { + Object.Base { + channel.1 { + name "fc" + reg 3 + shift 0 + } + text.0 { + name "mytext" + !values [ + "-90" + "-75" + "-60" + "-45" + "-30" + "-15" + "0" + "15" + "30" + "45" + "60" + "75" + "90" + ] + } + ops.1 { + name "ctl" + info "enum" + #257 binds the mixer control to enum get/put handlers + get 257 + put 257 + } + } + } + } + + # + # Default attributes for tdfb + # + + # dd511749-d9fa-455c-b3a7-13585693f1af + uuid "49:17:51:dd:fa:d9:5c:45:b3:a7:13:58:56:93:f1:af" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_50mm_azm90_90_13_16khz.conf b/tools/topology/topology2/include/components/tdfb/line2_50mm_azm90_90_13_16khz.conf new file mode 100644 index 000000000000..45b7f92588a8 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_50mm_azm90_90_13_16khz.conf @@ -0,0 +1,362 @@ +# Created with script example_line_array.m 23-Oct-2023 +# cd tools/tune/tdfb; octave --no-window-system example_line_array.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x04,0x0b,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x0b,0x00,0x00,0x02,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x0d,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0a,0x00,0x42,0x00,0x59,0x00, + 0x12,0x01,0xef,0x00,0x6b,0x02,0xa9,0x01, + 0x1c,0x04,0x02,0x03,0xa7,0x08,0x38,0x04, + 0x30,0x0b,0x40,0x03,0x58,0x0b,0x31,0xfb, + 0x52,0x0f,0x92,0xed,0xe6,0x34,0x51,0x69, + 0x07,0xe4,0x0b,0x0c,0x08,0xf2,0xc7,0x02, + 0x01,0xf2,0x51,0xfb,0xe9,0xf3,0x75,0xfa, + 0xc7,0xf6,0x63,0xfd,0xdb,0xfa,0xee,0xfd, + 0xce,0xfc,0xb5,0xfe,0x61,0xfe,0x68,0xff, + 0x70,0xff,0xdb,0xff,0xf1,0xff,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf4,0xff,0xcd,0xff,0x8e,0xff,0x2d,0xff, + 0xbd,0xfe,0x24,0xfe,0x99,0xfd,0xd3,0xfc, + 0x61,0xfc,0x29,0xfb,0x9b,0xf8,0xda,0xf7, + 0x9b,0xf7,0xe7,0xf6,0x19,0xf9,0xf1,0xfb, + 0x5e,0xfc,0xad,0xfd,0xbb,0xfe,0xcb,0x7f, + 0x41,0x01,0x43,0x02,0x7e,0x03,0xd9,0x03, + 0x71,0x06,0x5c,0x08,0x95,0x07,0x38,0x07, + 0x69,0x06,0x17,0x04,0xf9,0x02,0x83,0x02, + 0xd1,0x01,0x53,0x01,0xd3,0x00,0x79,0x00, + 0x33,0x00,0x0d,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0a,0x00,0x3e,0x00,0x5c,0x00, + 0x02,0x01,0xfa,0x00,0x47,0x02,0xc4,0x01, + 0xdc,0x03,0xf2,0x02,0x2a,0x08,0xb0,0x04, + 0x73,0x0a,0x16,0x04,0x24,0x0a,0xde,0xfc, + 0xec,0x0c,0xf9,0xf1,0x4e,0x27,0x6c,0x72, + 0x53,0xe7,0x10,0x0a,0xa3,0xf3,0xec,0x01, + 0xa0,0xf3,0x9e,0xfa,0xb2,0xf4,0x13,0xfa, + 0x4b,0xf7,0x29,0xfd,0x2b,0xfb,0xce,0xfd, + 0xfc,0xfc,0xa6,0xfe,0x78,0xfe,0x63,0xff, + 0x78,0xff,0xda,0xff,0xf2,0xff,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf4,0xff,0xcf,0xff,0x90,0xff,0x32,0xff, + 0xc3,0xfe,0x2f,0xfe,0xa2,0xfd,0xe7,0xfc, + 0x68,0xfc,0x63,0xfb,0xcb,0xf8,0xea,0xf7, + 0xb9,0xf7,0xff,0xf6,0x81,0xf9,0xf9,0xfb, + 0x6b,0xfc,0xb2,0xfd,0xbf,0xfe,0xcb,0x7f, + 0x3d,0x01,0x3e,0x02,0x71,0x03,0xd1,0x03, + 0x11,0x06,0x46,0x08,0x79,0x07,0x2a,0x07, + 0x40,0x06,0xe7,0x03,0xf3,0x02,0x74,0x02, + 0xca,0x01,0x4b,0x01,0xcf,0x00,0x76,0x00, + 0x32,0x00,0x0c,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0b,0x00,0x30,0x00,0x6a,0x00, + 0xc7,0x00,0x29,0x01,0xbe,0x01,0x32,0x02, + 0xf1,0x02,0x48,0x03,0xd9,0x05,0xbd,0x06, + 0x6e,0x07,0x7c,0x07,0x52,0x05,0x34,0x03, + 0x00,0x04,0xf1,0x00,0xb2,0x03,0xb1,0x7f, + 0x4e,0xfc,0xfa,0xfe,0xcb,0xfb,0x9b,0xfc, + 0x2a,0xfa,0xc5,0xf7,0xcb,0xf7,0x58,0xf8, + 0x57,0xf9,0x26,0xfc,0x68,0xfc,0x3b,0xfd, + 0xb2,0xfd,0x5f,0xfe,0xcf,0xfe,0x47,0xff, + 0x95,0xff,0xd4,0xff,0xf5,0xff,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf5,0xff,0xd3,0xff,0x97,0xff,0x43,0xff, + 0xd6,0xfe,0x54,0xfe,0xc0,0xfd,0x27,0xfd, + 0x84,0xfc,0x01,0xfc,0x77,0xf9,0x28,0xf8, + 0x0e,0xf8,0x77,0xf7,0xae,0xfa,0x06,0xfc, + 0xa1,0xfc,0xc1,0xfd,0xd2,0xfe,0xcb,0x7f, + 0x2a,0x01,0x31,0x02,0x3e,0x03,0xc4,0x03, + 0xf8,0x04,0xd8,0x07,0x2d,0x07,0xf3,0x06, + 0xaa,0x05,0x61,0x03,0xdc,0x02,0x41,0x02, + 0xb3,0x01,0x30,0x01,0xc3,0x00,0x6c,0x00, + 0x2f,0x00,0x0b,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0d,0x00,0x1a,0x00,0x7b,0x00, + 0x6a,0x00,0x67,0x01,0xe3,0x00,0xca,0x02, + 0x5f,0x01,0x71,0x04,0xb4,0x01,0xf4,0x08, + 0x70,0x03,0x9b,0x0b,0x08,0xff,0xb7,0x0a, + 0x50,0xf9,0x18,0x11,0x01,0xe7,0xb4,0x67, + 0x58,0x37,0x6b,0xe8,0xaf,0x0a,0x2c,0xf3, + 0x73,0x03,0xfd,0xf4,0x8f,0xfc,0xd5,0xf5, + 0x90,0xfc,0xba,0xfa,0x6e,0xfe,0x6d,0xfc, + 0xd5,0xfe,0xfd,0xfd,0x5b,0xff,0x22,0xff, + 0xc5,0xff,0xcc,0xff,0xfa,0xff,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf6,0xff,0xda,0xff,0xa6,0xff,0x61,0xff, + 0xfb,0xfe,0x96,0xfe,0x01,0xfe,0x95,0xfd, + 0xd9,0xfc,0xc7,0xfc,0xd9,0xfa,0xcf,0xf8, + 0x7e,0xf8,0xe5,0xf8,0x30,0xfc,0x45,0xfc, + 0x12,0xfd,0xe1,0xfd,0xf7,0xfe,0xcb,0x7f, + 0x05,0x01,0x11,0x02,0xd0,0x02,0x89,0x03, + 0x90,0x03,0x87,0x06,0xc8,0x06,0x5f,0x06, + 0x77,0x04,0xb9,0x02,0x96,0x02,0xea,0x01, + 0x83,0x01,0x02,0x01,0xab,0x00,0x5b,0x00, + 0x29,0x00,0x09,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x05,0x00,0x26,0x00,0x31,0x00, + 0xa3,0x00,0x8a,0x00,0x7d,0x01,0xf8,0x00, + 0x97,0x02,0x2c,0x01,0x24,0x04,0xc0,0x03, + 0xd3,0x07,0xe4,0x00,0xf9,0x05,0xf7,0xfd, + 0xad,0x08,0xf6,0xf6,0xb1,0x18,0xf1,0x79, + 0x96,0xed,0x60,0x07,0x7e,0xf7,0x9d,0x01, + 0xbc,0xf9,0xcf,0xfd,0xea,0xf6,0x58,0xfc, + 0xb7,0xfb,0x70,0xfe,0xe8,0xfc,0xba,0xfe, + 0x12,0xfe,0x3c,0xff,0x0c,0xff,0xaa,0xff, + 0xad,0xff,0xeb,0xff,0xf7,0xff,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf9,0xff, + 0xe4,0xff,0xbe,0xff,0x8a,0xff,0x3e,0xff, + 0xed,0xfe,0x7f,0xfe,0x25,0xfe,0xaf,0xfd, + 0x79,0xfd,0xdb,0xfc,0x4f,0xfa,0x40,0xf9, + 0xae,0xfb,0x41,0xfd,0x2c,0xfd,0xc3,0xfd, + 0x3d,0xfe,0x26,0xff,0xcb,0x7f,0xd7,0x00, + 0xb8,0x01,0x27,0x02,0xae,0x02,0x91,0x02, + 0xf8,0x03,0x19,0x06,0x0b,0x05,0xba,0x02, + 0x23,0x02,0xe7,0x01,0x78,0x01,0x23,0x01, + 0xc3,0x00,0x7f,0x00,0x43,0x00,0x1e,0x00, + 0x07,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x07,0x00,0x01,0x00,0x46,0x00, + 0x00,0x00,0xd5,0x00,0xfd,0xff,0xb5,0x01, + 0xc9,0xff,0xda,0x02,0x39,0xff,0x7d,0x04, + 0xf2,0x00,0xda,0x06,0x8c,0xfb,0x4e,0x09, + 0xb1,0xf6,0xa6,0x10,0x6b,0xe5,0x9e,0x61, + 0x55,0x3f,0x91,0xe7,0xf2,0x0c,0xf4,0xf4, + 0x8b,0x05,0x22,0xf9,0x4a,0x01,0x4f,0xf8, + 0x52,0x01,0x67,0xfc,0x74,0x00,0xbd,0xfd, + 0x17,0x00,0xc2,0xfe,0x01,0x00,0x7f,0xff, + 0xff,0xff,0xe2,0xff,0x00,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xff, + 0xf0,0xff,0xde,0xff,0xbe,0xff,0x9f,0xff, + 0x5e,0xff,0x3b,0xff,0xe8,0xfe,0xe2,0xfe, + 0x68,0xfe,0xc2,0xfe,0xd6,0xfc,0x87,0xfb, + 0x8f,0xfe,0x32,0xfe,0xa8,0xfe,0xae,0xfe, + 0x11,0xff,0x5f,0xff,0xcb,0x7f,0x9f,0x00, + 0xe9,0x00,0x45,0x01,0x46,0x01,0xaf,0x01, + 0x53,0x01,0x0a,0x04,0xcd,0x02,0x13,0x01, + 0x59,0x01,0xeb,0x00,0xde,0x00,0x95,0x00, + 0x73,0x00,0x3f,0x00,0x26,0x00,0x0f,0x00, + 0x04,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcb,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xcb,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfc,0xff,0xf0,0xff,0xde,0xff, + 0xbe,0xff,0x9f,0xff,0x5e,0xff,0x3b,0xff, + 0xe8,0xfe,0xe2,0xfe,0x68,0xfe,0xc2,0xfe, + 0xd6,0xfc,0x87,0xfb,0x8f,0xfe,0x32,0xfe, + 0xa8,0xfe,0xae,0xfe,0x11,0xff,0x5f,0xff, + 0xcb,0x7f,0x9f,0x00,0xe9,0x00,0x45,0x01, + 0x46,0x01,0xaf,0x01,0x53,0x01,0x0a,0x04, + 0xcd,0x02,0x13,0x01,0x59,0x01,0xeb,0x00, + 0xde,0x00,0x95,0x00,0x73,0x00,0x3f,0x00, + 0x26,0x00,0x0f,0x00,0x04,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00, + 0x01,0x00,0x46,0x00,0x00,0x00,0xd5,0x00, + 0xfd,0xff,0xb5,0x01,0xc9,0xff,0xda,0x02, + 0x39,0xff,0x7d,0x04,0xf2,0x00,0xda,0x06, + 0x8c,0xfb,0x4e,0x09,0xb1,0xf6,0xa6,0x10, + 0x6b,0xe5,0x9e,0x61,0x55,0x3f,0x91,0xe7, + 0xf2,0x0c,0xf4,0xf4,0x8b,0x05,0x22,0xf9, + 0x4a,0x01,0x4f,0xf8,0x52,0x01,0x67,0xfc, + 0x74,0x00,0xbd,0xfd,0x17,0x00,0xc2,0xfe, + 0x01,0x00,0x7f,0xff,0xff,0xff,0xe2,0xff, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf9,0xff,0xe4,0xff,0xbe,0xff, + 0x8a,0xff,0x3e,0xff,0xed,0xfe,0x7f,0xfe, + 0x25,0xfe,0xaf,0xfd,0x79,0xfd,0xdb,0xfc, + 0x4f,0xfa,0x40,0xf9,0xae,0xfb,0x41,0xfd, + 0x2c,0xfd,0xc3,0xfd,0x3d,0xfe,0x26,0xff, + 0xcb,0x7f,0xd7,0x00,0xb8,0x01,0x27,0x02, + 0xae,0x02,0x91,0x02,0xf8,0x03,0x19,0x06, + 0x0b,0x05,0xba,0x02,0x23,0x02,0xe7,0x01, + 0x78,0x01,0x23,0x01,0xc3,0x00,0x7f,0x00, + 0x43,0x00,0x1e,0x00,0x07,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00, + 0x26,0x00,0x31,0x00,0xa3,0x00,0x8a,0x00, + 0x7d,0x01,0xf8,0x00,0x97,0x02,0x2c,0x01, + 0x24,0x04,0xc0,0x03,0xd3,0x07,0xe4,0x00, + 0xf9,0x05,0xf7,0xfd,0xad,0x08,0xf6,0xf6, + 0xb1,0x18,0xf1,0x79,0x96,0xed,0x60,0x07, + 0x7e,0xf7,0x9d,0x01,0xbc,0xf9,0xcf,0xfd, + 0xea,0xf6,0x58,0xfc,0xb7,0xfb,0x70,0xfe, + 0xe8,0xfc,0xba,0xfe,0x12,0xfe,0x3c,0xff, + 0x0c,0xff,0xaa,0xff,0xad,0xff,0xeb,0xff, + 0xf7,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf6,0xff,0xda,0xff, + 0xa6,0xff,0x61,0xff,0xfb,0xfe,0x96,0xfe, + 0x01,0xfe,0x95,0xfd,0xd9,0xfc,0xc7,0xfc, + 0xd9,0xfa,0xcf,0xf8,0x7e,0xf8,0xe5,0xf8, + 0x30,0xfc,0x45,0xfc,0x12,0xfd,0xe1,0xfd, + 0xf7,0xfe,0xcb,0x7f,0x05,0x01,0x11,0x02, + 0xd0,0x02,0x89,0x03,0x90,0x03,0x87,0x06, + 0xc8,0x06,0x5f,0x06,0x77,0x04,0xb9,0x02, + 0x96,0x02,0xea,0x01,0x83,0x01,0x02,0x01, + 0xab,0x00,0x5b,0x00,0x29,0x00,0x09,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x00, + 0x1a,0x00,0x7b,0x00,0x6a,0x00,0x67,0x01, + 0xe3,0x00,0xca,0x02,0x5f,0x01,0x71,0x04, + 0xb4,0x01,0xf4,0x08,0x70,0x03,0x9b,0x0b, + 0x08,0xff,0xb7,0x0a,0x50,0xf9,0x18,0x11, + 0x01,0xe7,0xb4,0x67,0x58,0x37,0x6b,0xe8, + 0xaf,0x0a,0x2c,0xf3,0x73,0x03,0xfd,0xf4, + 0x8f,0xfc,0xd5,0xf5,0x90,0xfc,0xba,0xfa, + 0x6e,0xfe,0x6d,0xfc,0xd5,0xfe,0xfd,0xfd, + 0x5b,0xff,0x22,0xff,0xc5,0xff,0xcc,0xff, + 0xfa,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf5,0xff,0xd3,0xff, + 0x97,0xff,0x43,0xff,0xd6,0xfe,0x54,0xfe, + 0xc0,0xfd,0x27,0xfd,0x84,0xfc,0x01,0xfc, + 0x77,0xf9,0x28,0xf8,0x0e,0xf8,0x77,0xf7, + 0xae,0xfa,0x06,0xfc,0xa1,0xfc,0xc1,0xfd, + 0xd2,0xfe,0xcb,0x7f,0x2a,0x01,0x31,0x02, + 0x3e,0x03,0xc4,0x03,0xf8,0x04,0xd8,0x07, + 0x2d,0x07,0xf3,0x06,0xaa,0x05,0x61,0x03, + 0xdc,0x02,0x41,0x02,0xb3,0x01,0x30,0x01, + 0xc3,0x00,0x6c,0x00,0x2f,0x00,0x0b,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00, + 0x30,0x00,0x6a,0x00,0xc7,0x00,0x29,0x01, + 0xbe,0x01,0x32,0x02,0xf1,0x02,0x48,0x03, + 0xd9,0x05,0xbd,0x06,0x6e,0x07,0x7c,0x07, + 0x52,0x05,0x34,0x03,0x00,0x04,0xf1,0x00, + 0xb2,0x03,0xb1,0x7f,0x4e,0xfc,0xfa,0xfe, + 0xcb,0xfb,0x9b,0xfc,0x2a,0xfa,0xc5,0xf7, + 0xcb,0xf7,0x58,0xf8,0x57,0xf9,0x26,0xfc, + 0x68,0xfc,0x3b,0xfd,0xb2,0xfd,0x5f,0xfe, + 0xcf,0xfe,0x47,0xff,0x95,0xff,0xd4,0xff, + 0xf5,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf4,0xff,0xcf,0xff, + 0x90,0xff,0x32,0xff,0xc3,0xfe,0x2f,0xfe, + 0xa2,0xfd,0xe7,0xfc,0x68,0xfc,0x63,0xfb, + 0xcb,0xf8,0xea,0xf7,0xb9,0xf7,0xff,0xf6, + 0x81,0xf9,0xf9,0xfb,0x6b,0xfc,0xb2,0xfd, + 0xbf,0xfe,0xcb,0x7f,0x3d,0x01,0x3e,0x02, + 0x71,0x03,0xd1,0x03,0x11,0x06,0x46,0x08, + 0x79,0x07,0x2a,0x07,0x40,0x06,0xe7,0x03, + 0xf3,0x02,0x74,0x02,0xca,0x01,0x4b,0x01, + 0xcf,0x00,0x76,0x00,0x32,0x00,0x0c,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00, + 0x3e,0x00,0x5c,0x00,0x02,0x01,0xfa,0x00, + 0x47,0x02,0xc4,0x01,0xdc,0x03,0xf2,0x02, + 0x2a,0x08,0xb0,0x04,0x73,0x0a,0x16,0x04, + 0x24,0x0a,0xde,0xfc,0xec,0x0c,0xf9,0xf1, + 0x4e,0x27,0x6c,0x72,0x53,0xe7,0x10,0x0a, + 0xa3,0xf3,0xec,0x01,0xa0,0xf3,0x9e,0xfa, + 0xb2,0xf4,0x13,0xfa,0x4b,0xf7,0x29,0xfd, + 0x2b,0xfb,0xce,0xfd,0xfc,0xfc,0xa6,0xfe, + 0x78,0xfe,0x63,0xff,0x78,0xff,0xda,0xff, + 0xf2,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf4,0xff,0xcd,0xff, + 0x8e,0xff,0x2d,0xff,0xbd,0xfe,0x24,0xfe, + 0x99,0xfd,0xd3,0xfc,0x61,0xfc,0x29,0xfb, + 0x9b,0xf8,0xda,0xf7,0x9b,0xf7,0xe7,0xf6, + 0x19,0xf9,0xf1,0xfb,0x5e,0xfc,0xad,0xfd, + 0xbb,0xfe,0xcb,0x7f,0x41,0x01,0x43,0x02, + 0x7e,0x03,0xd9,0x03,0x71,0x06,0x5c,0x08, + 0x95,0x07,0x38,0x07,0x69,0x06,0x17,0x04, + 0xf9,0x02,0x83,0x02,0xd1,0x01,0x53,0x01, + 0xd3,0x00,0x79,0x00,0x33,0x00,0x0d,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00, + 0x42,0x00,0x59,0x00,0x12,0x01,0xef,0x00, + 0x6b,0x02,0xa9,0x01,0x1c,0x04,0x02,0x03, + 0xa7,0x08,0x38,0x04,0x30,0x0b,0x40,0x03, + 0x58,0x0b,0x31,0xfb,0x52,0x0f,0x92,0xed, + 0xe6,0x34,0x51,0x69,0x07,0xe4,0x0b,0x0c, + 0x08,0xf2,0xc7,0x02,0x01,0xf2,0x51,0xfb, + 0xe9,0xf3,0x75,0xfa,0xc7,0xf6,0x63,0xfd, + 0xdb,0xfa,0xee,0xfd,0xce,0xfc,0xb5,0xfe, + 0x61,0xfe,0x68,0xff,0x70,0xff,0xdb,0xff, + 0xf1,0xff,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x02,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00, + 0x02,0x00,0x00,0x00,0xc4,0xff,0x00,0x00, + 0x04,0x00,0x00,0x00,0xd3,0xff,0x00,0x00, + 0x06,0x00,0x00,0x00,0xe2,0xff,0x00,0x00, + 0x08,0x00,0x00,0x00,0xf1,0xff,0x00,0x00, + 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x10,0x00,0x00,0x00,0x2d,0x00,0x00,0x00, + 0x12,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x4b,0x00,0x00,0x00, + 0x16,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_50mm_azm90_90_13_48khz.conf b/tools/topology/topology2/include/components/tdfb/line2_50mm_azm90_90_13_48khz.conf new file mode 100644 index 000000000000..1d0afd1c83d7 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_50mm_azm90_90_13_48khz.conf @@ -0,0 +1,518 @@ +# Created with script example_line_array.m 23-Oct-2023 +# cd tools/tune/tdfb; octave --no-window-system example_line_array.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xe4,0x0f,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xe4,0x0f,0x00,0x00,0x02,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x0d,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x19,0x00,0x29,0x00,0x41,0x00,0x58,0x00, + 0x79,0x00,0x95,0x00,0xbd,0x00,0xdb,0x00, + 0x08,0x01,0x24,0x01,0x56,0x01,0x68,0x01, + 0xaa,0x01,0x58,0x01,0xf9,0x00,0x10,0x01, + 0x0a,0x01,0x06,0x01,0x04,0x01,0xef,0x00, + 0xed,0x00,0xc8,0x00,0xc8,0x00,0x91,0x00, + 0x9b,0x00,0x48,0x00,0x74,0x00,0xc5,0xff, + 0xeb,0x7f,0x3c,0x00,0x8b,0xff,0xb7,0xff, + 0x62,0xff,0x6b,0xff,0x32,0xff,0x30,0xff, + 0x09,0xff,0x05,0xff,0xee,0xfe,0xe9,0xfe, + 0xe3,0xfe,0xdb,0xfe,0xf1,0xfe,0x88,0xfe, + 0x28,0xfe,0x6d,0xfe,0x7c,0xfe,0xb1,0xfe, + 0xcc,0xfe,0xfc,0xfe,0x1b,0xff,0x46,0xff, + 0x64,0xff,0x89,0xff,0xa4,0xff,0xc1,0xff, + 0xd5,0xff,0xec,0xff,0xf9,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff, + 0xec,0xff,0xd5,0xff,0xc1,0xff,0xa4,0xff, + 0x89,0xff,0x65,0xff,0x45,0xff,0x1c,0xff, + 0xfb,0xfe,0xcd,0xfe,0xaf,0xfe,0x7e,0xfe, + 0x6a,0xfe,0x2b,0xfe,0x84,0xfe,0xf6,0xfe, + 0xd6,0xfe,0xe9,0xfe,0xe3,0xfe,0xf6,0xfe, + 0xfc,0xfe,0x14,0xff,0x24,0xff,0x40,0xff, + 0x59,0xff,0x79,0xff,0x98,0xff,0xba,0xff, + 0xdd,0xff,0xec,0x7f,0x23,0x00,0x45,0x00, + 0x67,0x00,0x84,0x00,0xa3,0x00,0xba,0x00, + 0xd4,0x00,0xe3,0x00,0xf8,0x00,0xfc,0x00, + 0x0c,0x01,0x05,0x01,0x14,0x01,0xf5,0x00, + 0x5a,0x01,0xa7,0x01,0x6a,0x01,0x55,0x01, + 0x25,0x01,0x07,0x01,0xdc,0x00,0xbc,0x00, + 0x96,0x00,0x78,0x00,0x58,0x00,0x41,0x00, + 0x29,0x00,0x19,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1d,0x00,0x1f,0x00,0x50,0x00,0x40,0x00, + 0x99,0x00,0x67,0x00,0xf6,0x00,0x8e,0x00, + 0x64,0x01,0xae,0x00,0xe0,0x01,0xbe,0x00, + 0x6f,0x02,0x69,0x00,0x0c,0x02,0xcd,0xff, + 0x86,0x02,0x4f,0xff,0x0a,0x03,0x97,0xfe, + 0xb7,0x03,0x81,0xfd,0xc5,0x04,0xb8,0xfb, + 0xce,0x06,0x0f,0xf8,0x97,0x0c,0xbd,0xe9, + 0x08,0x74,0xd1,0x24,0xe9,0xef,0xa4,0x09, + 0x44,0xf8,0xff,0x04,0xc4,0xfa,0xec,0x02, + 0xf7,0xfb,0xb3,0x01,0xb3,0xfc,0xe6,0x00, + 0x3b,0xfd,0x5b,0x00,0xaf,0xfd,0xf7,0xff, + 0x62,0xfd,0x2e,0xff,0xe2,0xfd,0x3d,0xff, + 0x61,0xfe,0x5b,0xff,0xd5,0xfe,0x83,0xff, + 0x3a,0xff,0xac,0xff,0x8d,0xff,0xd2,0xff, + 0xcb,0xff,0xf2,0xff,0xf7,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff, + 0xef,0xff,0xd6,0xff,0xc1,0xff,0xa5,0xff, + 0x8a,0xff,0x67,0xff,0x47,0xff,0x1f,0xff, + 0xfd,0xfe,0xd2,0xfe,0xb2,0xfe,0x84,0xfe, + 0x6c,0xfe,0x36,0xfe,0xb9,0xfe,0xf6,0xfe, + 0xdc,0xfe,0xeb,0xfe,0xe7,0xfe,0xf8,0xfe, + 0x00,0xff,0x16,0xff,0x27,0xff,0x42,0xff, + 0x5b,0xff,0x7b,0xff,0x99,0xff,0xbb,0xff, + 0xdd,0xff,0xec,0x7f,0x23,0x00,0x44,0x00, + 0x66,0x00,0x83,0x00,0xa1,0x00,0xb8,0x00, + 0xd1,0x00,0xe1,0x00,0xf4,0x00,0xfa,0x00, + 0x08,0x01,0x03,0x01,0x0f,0x01,0xf4,0x00, + 0x2a,0x01,0x9d,0x01,0x69,0x01,0x4f,0x01, + 0x23,0x01,0x03,0x01,0xda,0x00,0xb9,0x00, + 0x94,0x00,0x77,0x00,0x58,0x00,0x3f,0x00, + 0x28,0x00,0x18,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0x00,0x12,0x00,0x2b,0x00,0x36,0x00, + 0x5d,0x00,0x66,0x00,0x9e,0x00,0x9d,0x00, + 0xeb,0x00,0xd8,0x00,0x40,0x01,0x0f,0x01, + 0x9f,0x01,0xf6,0x00,0x18,0x01,0xaa,0x00, + 0x4e,0x01,0x95,0x00,0x73,0x01,0x62,0x00, + 0x90,0x01,0x0f,0x00,0xb6,0x01,0x8c,0xff, + 0x02,0x02,0xa9,0xfe,0xdf,0x02,0x66,0xfc, + 0x25,0x08,0x2b,0x7f,0xb5,0xf8,0x66,0x03, + 0x2b,0xfd,0x4d,0x01,0xf5,0xfd,0x6f,0x00, + 0x3a,0xfe,0xeb,0xff,0x5b,0xfe,0x94,0xff, + 0x74,0xfe,0x5d,0xff,0x96,0xfe,0x46,0xff, + 0xca,0xfe,0xd8,0xfe,0x30,0xfe,0xcc,0xfe, + 0x90,0xfe,0x03,0xff,0xe9,0xfe,0x40,0xff, + 0x3b,0xff,0x7d,0xff,0x83,0xff,0xb2,0xff, + 0xbd,0xff,0xe3,0xff,0xf1,0xff,0xfa,0xff, + 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff, + 0xf2,0xff,0xdf,0xff,0xc1,0xff,0xac,0xff, + 0x8c,0xff,0x71,0xff,0x4a,0xff,0x2c,0xff, + 0x02,0xff,0xe5,0xfe,0xb5,0xfe,0xa0,0xfe, + 0x64,0xfe,0xa5,0xfe,0x14,0xff,0xf2,0xfe, + 0xfa,0xfe,0xec,0xfe,0xf9,0xfe,0xfd,0xfe, + 0x0f,0xff,0x1b,0xff,0x33,0xff,0x47,0xff, + 0x64,0xff,0x7f,0xff,0x9f,0xff,0xbe,0xff, + 0xdf,0xff,0xec,0x7f,0x21,0x00,0x42,0x00, + 0x60,0x00,0x7f,0x00,0x98,0x00,0xb3,0x00, + 0xc6,0x00,0xdb,0x00,0xe6,0x00,0xf6,0x00, + 0xf7,0x00,0x01,0x01,0xf3,0x00,0xf8,0x00, + 0xd7,0x00,0x39,0x01,0x70,0x01,0x36,0x01, + 0x20,0x01,0xf3,0x00,0xd6,0x00,0xae,0x00, + 0x91,0x00,0x6f,0x00,0x56,0x00,0x3b,0x00, + 0x29,0x00,0x13,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x05,0x00,0x0d,0x00,0x18,0x00,0x3d,0x00, + 0x46,0x00,0x72,0x00,0x77,0x00,0xb4,0x00, + 0xad,0x00,0xff,0x00,0xe2,0x00,0x56,0x01, + 0xd3,0x00,0xdf,0x00,0x95,0x00,0x10,0x01, + 0x8c,0x00,0x37,0x01,0x74,0x00,0x5b,0x01, + 0x41,0x00,0x76,0x01,0xe6,0xff,0x9f,0x01, + 0x54,0xff,0x03,0x02,0x3b,0xfe,0x6f,0x03, + 0xd2,0xf9,0x5a,0x7f,0xec,0x06,0x5e,0xfc, + 0xe3,0x01,0xea,0xfd,0xba,0x00,0x52,0xfe, + 0x21,0x00,0x7a,0xfe,0xc0,0xff,0x92,0xfe, + 0x88,0xff,0xb4,0xfe,0x6b,0xff,0xd9,0xfe, + 0x5f,0xff,0x08,0xff,0x27,0xff,0x7d,0xfe, + 0xfe,0xfe,0xd6,0xfe,0x33,0xff,0x26,0xff, + 0x6c,0xff,0x6d,0xff,0xa2,0xff,0xa8,0xff, + 0xd8,0xff,0xe9,0xff,0xf4,0xff,0xfa,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xfa,0xff,0xf3,0xff, + 0xeb,0xff,0xd5,0xff,0xae,0xff,0x9a,0xff, + 0x78,0xff,0x5e,0xff,0x37,0xff,0x1d,0xff, + 0xf1,0xfe,0xdd,0xfe,0xa3,0xfe,0xef,0xfe, + 0x3f,0xff,0x1e,0xff,0x23,0xff,0x14,0xff, + 0x18,0xff,0x12,0xff,0x19,0xff,0x20,0xff, + 0x33,0xff,0x43,0xff,0x5b,0xff,0x71,0xff, + 0x8c,0xff,0xa7,0xff,0xc4,0xff,0xe2,0xff, + 0xec,0x7f,0x1e,0x00,0x3b,0x00,0x58,0x00, + 0x72,0x00,0x8c,0x00,0xa0,0x00,0xb6,0x00, + 0xc4,0x00,0xd5,0x00,0xdb,0x00,0xe0,0x00, + 0xd9,0x00,0xdb,0x00,0xcb,0x00,0xce,0x00, + 0xae,0x00,0xf4,0x00,0x34,0x01,0xfe,0x00, + 0xe8,0x00,0xbf,0x00,0xa5,0x00,0x82,0x00, + 0x6a,0x00,0x4c,0x00,0x39,0x00,0x1c,0x00, + 0x0c,0x00,0x06,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x08,0x00,0x01,0x00,0x1e,0x00, + 0x0b,0x00,0x6a,0x00,0x23,0x00,0xb7,0x00, + 0x30,0x00,0x19,0x01,0x39,0x00,0x5c,0x01, + 0x8f,0xff,0x90,0x01,0x4b,0xff,0x0a,0x02, + 0xe0,0xfe,0xa2,0x02,0x44,0xfe,0x64,0x03, + 0x62,0xfd,0x6e,0x04,0x0d,0xfc,0x00,0x06, + 0xcc,0xf9,0xd2,0x08,0x3d,0xf5,0x0f,0x10, + 0x67,0xe5,0xde,0x50,0x9a,0x51,0xb6,0xe4, + 0xf2,0x0f,0x3a,0xf4,0x55,0x08,0x7b,0xf8, + 0x33,0x05,0x83,0xfa,0x76,0x03,0xc7,0xfb, + 0x57,0x02,0xa9,0xfc,0x8f,0x01,0x58,0xfd, + 0x00,0x01,0xe8,0xfd,0x97,0x00,0x69,0xfe, + 0x0c,0x00,0x2f,0xfe,0xbd,0xff,0xb3,0xfe, + 0xbe,0xff,0x21,0xff,0xc9,0xff,0x8c,0xff, + 0x02,0x00,0xce,0xff,0xfe,0xff,0xee,0xff, + 0xff,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfc,0xff,0xf7,0xff,0xf0,0xff, + 0xe7,0xff,0xdb,0xff,0xa9,0xff,0x8c,0xff, + 0x73,0xff,0x56,0xff,0x39,0xff,0x1a,0xff, + 0x04,0xff,0x6c,0xff,0x6f,0xff,0x62,0xff, + 0x5c,0xff,0x55,0xff,0x52,0xff,0x4f,0xff, + 0x50,0xff,0x51,0xff,0x56,0xff,0x5c,0xff, + 0x65,0xff,0x76,0xff,0x8a,0xff,0x9f,0xff, + 0xb7,0xff,0xce,0xff,0xe7,0xff,0xec,0x7f, + 0x19,0x00,0x31,0x00,0x48,0x00,0x5f,0x00, + 0x73,0x00,0x86,0x00,0x95,0x00,0x9d,0x00, + 0xa2,0x00,0xa5,0x00,0xa6,0x00,0xa5,0x00, + 0xa1,0x00,0x9d,0x00,0x95,0x00,0x8f,0x00, + 0x81,0x00,0x83,0x00,0xdb,0x00,0xc5,0x00, + 0xa7,0x00,0x8c,0x00,0x71,0x00,0x5a,0x00, + 0x40,0x00,0x1a,0x00,0x10,0x00,0x09,0x00, + 0x04,0x00,0x01,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0x00,0x00,0x0a,0x00, + 0x00,0x00,0x1b,0x00,0xfe,0xff,0x3a,0x00, + 0x33,0x00,0x9a,0x00,0x4b,0x00,0xb7,0x00, + 0xd1,0xff,0xbd,0x00,0xb7,0xff,0xf8,0x00, + 0x8a,0xff,0x40,0x01,0x47,0xff,0x98,0x01, + 0xe8,0xfe,0x0a,0x02,0x5f,0xfe,0xa9,0x02, + 0x90,0xfd,0x9f,0x03,0x33,0xfc,0x70,0x05, + 0x45,0xf9,0x69,0x0a,0x01,0xed,0x8e,0x78, + 0x09,0x1c,0x5e,0xf3,0xca,0x07,0xf6,0xf9, + 0x39,0x04,0x12,0xfc,0xae,0x02,0x23,0xfd, + 0xca,0x01,0xce,0xfd,0x35,0x01,0x46,0xfe, + 0xce,0x00,0xa3,0xfe,0x84,0x00,0xef,0xfe, + 0x51,0x00,0x2e,0xff,0x30,0x00,0x56,0xff, + 0xad,0xff,0x46,0xff,0xbc,0xff,0xa1,0xff, + 0x06,0x00,0xd8,0xff,0x00,0x00,0xef,0xff, + 0x00,0x00,0xfc,0xff,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfe,0xff,0xfb,0xff,0xf7,0xff, + 0xf3,0xff,0xec,0xff,0xe9,0xff,0xd0,0xff, + 0x8d,0xff,0x84,0xff,0x5c,0xff,0x9e,0xff, + 0xc4,0xff,0xb1,0xff,0xb3,0xff,0xa9,0xff, + 0xa8,0xff,0xa2,0xff,0xa3,0xff,0xa0,0xff, + 0xa2,0xff,0xa1,0xff,0xa5,0xff,0xa7,0xff, + 0xad,0xff,0xb1,0xff,0xb9,0xff,0xbf,0xff, + 0xcc,0xff,0xdd,0xff,0xef,0xff,0xec,0x7f, + 0x11,0x00,0x22,0x00,0x33,0x00,0x40,0x00, + 0x46,0x00,0x4c,0x00,0x50,0x00,0x55,0x00, + 0x57,0x00,0x5a,0x00,0x59,0x00,0x5a,0x00, + 0x56,0x00,0x56,0x00,0x50,0x00,0x4f,0x00, + 0x45,0x00,0x46,0x00,0x34,0x00,0x54,0x00, + 0x8a,0x00,0x66,0x00,0x5c,0x00,0x25,0x00, + 0x11,0x00,0x0e,0x00,0x09,0x00,0x05,0x00, + 0x02,0x00,0x01,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff, + 0xfb,0xff,0xf7,0xff,0xf3,0xff,0xec,0xff, + 0xe9,0xff,0xd0,0xff,0x8d,0xff,0x84,0xff, + 0x5c,0xff,0x9e,0xff,0xc4,0xff,0xb1,0xff, + 0xb3,0xff,0xa9,0xff,0xa8,0xff,0xa2,0xff, + 0xa3,0xff,0xa0,0xff,0xa2,0xff,0xa1,0xff, + 0xa5,0xff,0xa7,0xff,0xad,0xff,0xb1,0xff, + 0xb9,0xff,0xbf,0xff,0xcc,0xff,0xdd,0xff, + 0xef,0xff,0xec,0x7f,0x11,0x00,0x22,0x00, + 0x33,0x00,0x40,0x00,0x46,0x00,0x4c,0x00, + 0x50,0x00,0x55,0x00,0x57,0x00,0x5a,0x00, + 0x59,0x00,0x5a,0x00,0x56,0x00,0x56,0x00, + 0x50,0x00,0x4f,0x00,0x45,0x00,0x46,0x00, + 0x34,0x00,0x54,0x00,0x8a,0x00,0x66,0x00, + 0x5c,0x00,0x25,0x00,0x11,0x00,0x0e,0x00, + 0x09,0x00,0x05,0x00,0x02,0x00,0x01,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x0a,0x00,0x00,0x00,0x1b,0x00, + 0xfe,0xff,0x3a,0x00,0x33,0x00,0x9a,0x00, + 0x4b,0x00,0xb7,0x00,0xd1,0xff,0xbd,0x00, + 0xb7,0xff,0xf8,0x00,0x8a,0xff,0x40,0x01, + 0x47,0xff,0x98,0x01,0xe8,0xfe,0x0a,0x02, + 0x5f,0xfe,0xa9,0x02,0x90,0xfd,0x9f,0x03, + 0x33,0xfc,0x70,0x05,0x45,0xf9,0x69,0x0a, + 0x01,0xed,0x8e,0x78,0x09,0x1c,0x5e,0xf3, + 0xca,0x07,0xf6,0xf9,0x39,0x04,0x12,0xfc, + 0xae,0x02,0x23,0xfd,0xca,0x01,0xce,0xfd, + 0x35,0x01,0x46,0xfe,0xce,0x00,0xa3,0xfe, + 0x84,0x00,0xef,0xfe,0x51,0x00,0x2e,0xff, + 0x30,0x00,0x56,0xff,0xad,0xff,0x46,0xff, + 0xbc,0xff,0xa1,0xff,0x06,0x00,0xd8,0xff, + 0x00,0x00,0xef,0xff,0x00,0x00,0xfc,0xff, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff, + 0xf7,0xff,0xf0,0xff,0xe7,0xff,0xdb,0xff, + 0xa9,0xff,0x8c,0xff,0x73,0xff,0x56,0xff, + 0x39,0xff,0x1a,0xff,0x04,0xff,0x6c,0xff, + 0x6f,0xff,0x62,0xff,0x5c,0xff,0x55,0xff, + 0x52,0xff,0x4f,0xff,0x50,0xff,0x51,0xff, + 0x56,0xff,0x5c,0xff,0x65,0xff,0x76,0xff, + 0x8a,0xff,0x9f,0xff,0xb7,0xff,0xce,0xff, + 0xe7,0xff,0xec,0x7f,0x19,0x00,0x31,0x00, + 0x48,0x00,0x5f,0x00,0x73,0x00,0x86,0x00, + 0x95,0x00,0x9d,0x00,0xa2,0x00,0xa5,0x00, + 0xa6,0x00,0xa5,0x00,0xa1,0x00,0x9d,0x00, + 0x95,0x00,0x8f,0x00,0x81,0x00,0x83,0x00, + 0xdb,0x00,0xc5,0x00,0xa7,0x00,0x8c,0x00, + 0x71,0x00,0x5a,0x00,0x40,0x00,0x1a,0x00, + 0x10,0x00,0x09,0x00,0x04,0x00,0x01,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00, + 0x01,0x00,0x1e,0x00,0x0b,0x00,0x6a,0x00, + 0x23,0x00,0xb7,0x00,0x30,0x00,0x19,0x01, + 0x39,0x00,0x5c,0x01,0x8f,0xff,0x90,0x01, + 0x4b,0xff,0x0a,0x02,0xe0,0xfe,0xa2,0x02, + 0x44,0xfe,0x64,0x03,0x62,0xfd,0x6e,0x04, + 0x0d,0xfc,0x00,0x06,0xcc,0xf9,0xd2,0x08, + 0x3d,0xf5,0x0f,0x10,0x67,0xe5,0xde,0x50, + 0x9a,0x51,0xb6,0xe4,0xf2,0x0f,0x3a,0xf4, + 0x55,0x08,0x7b,0xf8,0x33,0x05,0x83,0xfa, + 0x76,0x03,0xc7,0xfb,0x57,0x02,0xa9,0xfc, + 0x8f,0x01,0x58,0xfd,0x00,0x01,0xe8,0xfd, + 0x97,0x00,0x69,0xfe,0x0c,0x00,0x2f,0xfe, + 0xbd,0xff,0xb3,0xfe,0xbe,0xff,0x21,0xff, + 0xc9,0xff,0x8c,0xff,0x02,0x00,0xce,0xff, + 0xfe,0xff,0xee,0xff,0xff,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xfa,0xff,0xf3,0xff,0xeb,0xff,0xd5,0xff, + 0xae,0xff,0x9a,0xff,0x78,0xff,0x5e,0xff, + 0x37,0xff,0x1d,0xff,0xf1,0xfe,0xdd,0xfe, + 0xa3,0xfe,0xef,0xfe,0x3f,0xff,0x1e,0xff, + 0x23,0xff,0x14,0xff,0x18,0xff,0x12,0xff, + 0x19,0xff,0x20,0xff,0x33,0xff,0x43,0xff, + 0x5b,0xff,0x71,0xff,0x8c,0xff,0xa7,0xff, + 0xc4,0xff,0xe2,0xff,0xec,0x7f,0x1e,0x00, + 0x3b,0x00,0x58,0x00,0x72,0x00,0x8c,0x00, + 0xa0,0x00,0xb6,0x00,0xc4,0x00,0xd5,0x00, + 0xdb,0x00,0xe0,0x00,0xd9,0x00,0xdb,0x00, + 0xcb,0x00,0xce,0x00,0xae,0x00,0xf4,0x00, + 0x34,0x01,0xfe,0x00,0xe8,0x00,0xbf,0x00, + 0xa5,0x00,0x82,0x00,0x6a,0x00,0x4c,0x00, + 0x39,0x00,0x1c,0x00,0x0c,0x00,0x06,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x05,0x00,0x0d,0x00, + 0x18,0x00,0x3d,0x00,0x46,0x00,0x72,0x00, + 0x77,0x00,0xb4,0x00,0xad,0x00,0xff,0x00, + 0xe2,0x00,0x56,0x01,0xd3,0x00,0xdf,0x00, + 0x95,0x00,0x10,0x01,0x8c,0x00,0x37,0x01, + 0x74,0x00,0x5b,0x01,0x41,0x00,0x76,0x01, + 0xe6,0xff,0x9f,0x01,0x54,0xff,0x03,0x02, + 0x3b,0xfe,0x6f,0x03,0xd2,0xf9,0x5a,0x7f, + 0xec,0x06,0x5e,0xfc,0xe3,0x01,0xea,0xfd, + 0xba,0x00,0x52,0xfe,0x21,0x00,0x7a,0xfe, + 0xc0,0xff,0x92,0xfe,0x88,0xff,0xb4,0xfe, + 0x6b,0xff,0xd9,0xfe,0x5f,0xff,0x08,0xff, + 0x27,0xff,0x7d,0xfe,0xfe,0xfe,0xd6,0xfe, + 0x33,0xff,0x26,0xff,0x6c,0xff,0x6d,0xff, + 0xa2,0xff,0xa8,0xff,0xd8,0xff,0xe9,0xff, + 0xf4,0xff,0xfa,0xff,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xf9,0xff,0xf2,0xff,0xdf,0xff, + 0xc1,0xff,0xac,0xff,0x8c,0xff,0x71,0xff, + 0x4a,0xff,0x2c,0xff,0x02,0xff,0xe5,0xfe, + 0xb5,0xfe,0xa0,0xfe,0x64,0xfe,0xa5,0xfe, + 0x14,0xff,0xf2,0xfe,0xfa,0xfe,0xec,0xfe, + 0xf9,0xfe,0xfd,0xfe,0x0f,0xff,0x1b,0xff, + 0x33,0xff,0x47,0xff,0x64,0xff,0x7f,0xff, + 0x9f,0xff,0xbe,0xff,0xdf,0xff,0xec,0x7f, + 0x21,0x00,0x42,0x00,0x60,0x00,0x7f,0x00, + 0x98,0x00,0xb3,0x00,0xc6,0x00,0xdb,0x00, + 0xe6,0x00,0xf6,0x00,0xf7,0x00,0x01,0x01, + 0xf3,0x00,0xf8,0x00,0xd7,0x00,0x39,0x01, + 0x70,0x01,0x36,0x01,0x20,0x01,0xf3,0x00, + 0xd6,0x00,0xae,0x00,0x91,0x00,0x6f,0x00, + 0x56,0x00,0x3b,0x00,0x29,0x00,0x13,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x07,0x00,0x12,0x00, + 0x2b,0x00,0x36,0x00,0x5d,0x00,0x66,0x00, + 0x9e,0x00,0x9d,0x00,0xeb,0x00,0xd8,0x00, + 0x40,0x01,0x0f,0x01,0x9f,0x01,0xf6,0x00, + 0x18,0x01,0xaa,0x00,0x4e,0x01,0x95,0x00, + 0x73,0x01,0x62,0x00,0x90,0x01,0x0f,0x00, + 0xb6,0x01,0x8c,0xff,0x02,0x02,0xa9,0xfe, + 0xdf,0x02,0x66,0xfc,0x25,0x08,0x2b,0x7f, + 0xb5,0xf8,0x66,0x03,0x2b,0xfd,0x4d,0x01, + 0xf5,0xfd,0x6f,0x00,0x3a,0xfe,0xeb,0xff, + 0x5b,0xfe,0x94,0xff,0x74,0xfe,0x5d,0xff, + 0x96,0xfe,0x46,0xff,0xca,0xfe,0xd8,0xfe, + 0x30,0xfe,0xcc,0xfe,0x90,0xfe,0x03,0xff, + 0xe9,0xfe,0x40,0xff,0x3b,0xff,0x7d,0xff, + 0x83,0xff,0xb2,0xff,0xbd,0xff,0xe3,0xff, + 0xf1,0xff,0xfa,0xff,0xfe,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xf9,0xff,0xef,0xff,0xd6,0xff, + 0xc1,0xff,0xa5,0xff,0x8a,0xff,0x67,0xff, + 0x47,0xff,0x1f,0xff,0xfd,0xfe,0xd2,0xfe, + 0xb2,0xfe,0x84,0xfe,0x6c,0xfe,0x36,0xfe, + 0xb9,0xfe,0xf6,0xfe,0xdc,0xfe,0xeb,0xfe, + 0xe7,0xfe,0xf8,0xfe,0x00,0xff,0x16,0xff, + 0x27,0xff,0x42,0xff,0x5b,0xff,0x7b,0xff, + 0x99,0xff,0xbb,0xff,0xdd,0xff,0xec,0x7f, + 0x23,0x00,0x44,0x00,0x66,0x00,0x83,0x00, + 0xa1,0x00,0xb8,0x00,0xd1,0x00,0xe1,0x00, + 0xf4,0x00,0xfa,0x00,0x08,0x01,0x03,0x01, + 0x0f,0x01,0xf4,0x00,0x2a,0x01,0x9d,0x01, + 0x69,0x01,0x4f,0x01,0x23,0x01,0x03,0x01, + 0xda,0x00,0xb9,0x00,0x94,0x00,0x77,0x00, + 0x58,0x00,0x3f,0x00,0x28,0x00,0x18,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1d,0x00,0x1f,0x00, + 0x50,0x00,0x40,0x00,0x99,0x00,0x67,0x00, + 0xf6,0x00,0x8e,0x00,0x64,0x01,0xae,0x00, + 0xe0,0x01,0xbe,0x00,0x6f,0x02,0x69,0x00, + 0x0c,0x02,0xcd,0xff,0x86,0x02,0x4f,0xff, + 0x0a,0x03,0x97,0xfe,0xb7,0x03,0x81,0xfd, + 0xc5,0x04,0xb8,0xfb,0xce,0x06,0x0f,0xf8, + 0x97,0x0c,0xbd,0xe9,0x08,0x74,0xd1,0x24, + 0xe9,0xef,0xa4,0x09,0x44,0xf8,0xff,0x04, + 0xc4,0xfa,0xec,0x02,0xf7,0xfb,0xb3,0x01, + 0xb3,0xfc,0xe6,0x00,0x3b,0xfd,0x5b,0x00, + 0xaf,0xfd,0xf7,0xff,0x62,0xfd,0x2e,0xff, + 0xe2,0xfd,0x3d,0xff,0x61,0xfe,0x5b,0xff, + 0xd5,0xfe,0x83,0xff,0x3a,0xff,0xac,0xff, + 0x8d,0xff,0xd2,0xff,0xcb,0xff,0xf2,0xff, + 0xf7,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd5,0xff, + 0xc1,0xff,0xa4,0xff,0x89,0xff,0x65,0xff, + 0x45,0xff,0x1c,0xff,0xfb,0xfe,0xcd,0xfe, + 0xaf,0xfe,0x7e,0xfe,0x6a,0xfe,0x2b,0xfe, + 0x84,0xfe,0xf6,0xfe,0xd6,0xfe,0xe9,0xfe, + 0xe3,0xfe,0xf6,0xfe,0xfc,0xfe,0x14,0xff, + 0x24,0xff,0x40,0xff,0x59,0xff,0x79,0xff, + 0x98,0xff,0xba,0xff,0xdd,0xff,0xec,0x7f, + 0x23,0x00,0x45,0x00,0x67,0x00,0x84,0x00, + 0xa3,0x00,0xba,0x00,0xd4,0x00,0xe3,0x00, + 0xf8,0x00,0xfc,0x00,0x0c,0x01,0x05,0x01, + 0x14,0x01,0xf5,0x00,0x5a,0x01,0xa7,0x01, + 0x6a,0x01,0x55,0x01,0x25,0x01,0x07,0x01, + 0xdc,0x00,0xbc,0x00,0x96,0x00,0x78,0x00, + 0x58,0x00,0x41,0x00,0x29,0x00,0x19,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x19,0x00,0x29,0x00, + 0x41,0x00,0x58,0x00,0x79,0x00,0x95,0x00, + 0xbd,0x00,0xdb,0x00,0x08,0x01,0x24,0x01, + 0x56,0x01,0x68,0x01,0xaa,0x01,0x58,0x01, + 0xf9,0x00,0x10,0x01,0x0a,0x01,0x06,0x01, + 0x04,0x01,0xef,0x00,0xed,0x00,0xc8,0x00, + 0xc8,0x00,0x91,0x00,0x9b,0x00,0x48,0x00, + 0x74,0x00,0xc5,0xff,0xeb,0x7f,0x3c,0x00, + 0x8b,0xff,0xb7,0xff,0x62,0xff,0x6b,0xff, + 0x32,0xff,0x30,0xff,0x09,0xff,0x05,0xff, + 0xee,0xfe,0xe9,0xfe,0xe3,0xfe,0xdb,0xfe, + 0xf1,0xfe,0x88,0xfe,0x28,0xfe,0x6d,0xfe, + 0x7c,0xfe,0xb1,0xfe,0xcc,0xfe,0xfc,0xfe, + 0x1b,0xff,0x46,0xff,0x64,0xff,0x89,0xff, + 0xa4,0xff,0xc1,0xff,0xd5,0xff,0xec,0xff, + 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0x02,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00, + 0x02,0x00,0x00,0x00,0xc4,0xff,0x00,0x00, + 0x04,0x00,0x00,0x00,0xd3,0xff,0x00,0x00, + 0x06,0x00,0x00,0x00,0xe2,0xff,0x00,0x00, + 0x08,0x00,0x00,0x00,0xf1,0xff,0x00,0x00, + 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x10,0x00,0x00,0x00,0x2d,0x00,0x00,0x00, + 0x12,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0x14,0x00,0x00,0x00,0x4b,0x00,0x00,0x00, + 0x16,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_50mm_pm0_30_90deg_16khz.conf b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm0_30_90deg_16khz.conf new file mode 100644 index 000000000000..c2e9b2003684 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm0_30_90deg_16khz.conf @@ -0,0 +1,258 @@ +# Created with script example_two_beams.m 23-Oct-2023 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xc4,0x07,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc4,0x07,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x03,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0xf9,0xff,0xee,0xff, + 0xe1,0xff,0xcd,0xff,0xb6,0xff,0x97,0xff, + 0x77,0xff,0x4b,0xff,0x22,0xff,0xe9,0xfe, + 0xb7,0xfe,0x72,0xfe,0x3b,0xfe,0xea,0xfd, + 0xa4,0xfd,0x3a,0xfd,0xf7,0xfc,0x87,0xfc, + 0x5f,0xfc,0x0c,0xfc,0x27,0xfc,0xa5,0xfb, + 0xb7,0xf8,0xe9,0xf7,0x18,0xfb,0x03,0xfd, + 0x07,0xfd,0xb4,0xfd,0x39,0xfe,0x26,0xff, + 0xec,0x7f,0xd9,0x00,0xc3,0x01,0x43,0x02, + 0xea,0x02,0xe9,0x02,0xc2,0x04,0xcd,0x07, + 0xfc,0x06,0x26,0x04,0xa5,0x03,0xb8,0x03, + 0x64,0x03,0x38,0x03,0xcb,0x02,0x87,0x02, + 0x21,0x02,0xdd,0x01,0x90,0x01,0x5a,0x01, + 0x1a,0x01,0xea,0x00,0xb7,0x00,0x91,0x00, + 0x6a,0x00,0x4e,0x00,0x34,0x00,0x21,0x00, + 0x12,0x00,0x08,0x00,0x02,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x0a,0x00,0x0e,0x00,0x29,0x00,0x28,0x00, + 0x61,0x00,0x52,0x00,0xb4,0x00,0x8b,0x00, + 0x25,0x01,0xd4,0x00,0xb4,0x01,0x27,0x01, + 0x60,0x02,0x8d,0x01,0x40,0x03,0xfa,0x01, + 0x36,0x04,0x3d,0x02,0x10,0x05,0xff,0x01, + 0x4e,0x06,0x31,0x05,0x03,0x0a,0x11,0x01, + 0xc8,0x06,0xc9,0xfd,0x1f,0x09,0xbb,0xf6, + 0xeb,0x18,0x10,0x7a,0x91,0xed,0x71,0x07, + 0x47,0xf7,0xb2,0x01,0x30,0xf9,0x83,0xfd, + 0x1e,0xf5,0x52,0xfb,0x11,0xfa,0x9e,0xfd, + 0xb9,0xfa,0x83,0xfd,0x8d,0xfb,0xd6,0xfd, + 0x82,0xfc,0x4b,0xfe,0x64,0xfd,0xb1,0xfe, + 0x13,0xfe,0x09,0xff,0xa9,0xfe,0x58,0xff, + 0x23,0xff,0x97,0xff,0x80,0xff,0xc7,0xff, + 0xc1,0xff,0xe8,0xff,0xeb,0xff,0xfa,0xff, + 0xfe,0xff,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0x0a,0x00,0x0e,0x00, + 0x29,0x00,0x28,0x00,0x61,0x00,0x52,0x00, + 0xb4,0x00,0x8b,0x00,0x25,0x01,0xd4,0x00, + 0xb4,0x01,0x27,0x01,0x60,0x02,0x8d,0x01, + 0x40,0x03,0xfa,0x01,0x36,0x04,0x3d,0x02, + 0x10,0x05,0xff,0x01,0x4e,0x06,0x31,0x05, + 0x03,0x0a,0x11,0x01,0xc8,0x06,0xc9,0xfd, + 0x1f,0x09,0xbb,0xf6,0xeb,0x18,0x10,0x7a, + 0x91,0xed,0x71,0x07,0x47,0xf7,0xb2,0x01, + 0x30,0xf9,0x83,0xfd,0x1e,0xf5,0x52,0xfb, + 0x11,0xfa,0x9e,0xfd,0xb9,0xfa,0x83,0xfd, + 0x8d,0xfb,0xd6,0xfd,0x82,0xfc,0x4b,0xfe, + 0x64,0xfd,0xb1,0xfe,0x13,0xfe,0x09,0xff, + 0xa9,0xfe,0x58,0xff,0x23,0xff,0x97,0xff, + 0x80,0xff,0xc7,0xff,0xc1,0xff,0xe8,0xff, + 0xeb,0xff,0xfa,0xff,0xfe,0xff,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff, + 0xf9,0xff,0xee,0xff,0xe1,0xff,0xcd,0xff, + 0xb6,0xff,0x97,0xff,0x77,0xff,0x4b,0xff, + 0x22,0xff,0xe9,0xfe,0xb7,0xfe,0x72,0xfe, + 0x3b,0xfe,0xea,0xfd,0xa4,0xfd,0x3a,0xfd, + 0xf7,0xfc,0x87,0xfc,0x5f,0xfc,0x0c,0xfc, + 0x27,0xfc,0xa5,0xfb,0xb7,0xf8,0xe9,0xf7, + 0x18,0xfb,0x03,0xfd,0x07,0xfd,0xb4,0xfd, + 0x39,0xfe,0x26,0xff,0xec,0x7f,0xd9,0x00, + 0xc3,0x01,0x43,0x02,0xea,0x02,0xe9,0x02, + 0xc2,0x04,0xcd,0x07,0xfc,0x06,0x26,0x04, + 0xa5,0x03,0xb8,0x03,0x64,0x03,0x38,0x03, + 0xcb,0x02,0x87,0x02,0x21,0x02,0xdd,0x01, + 0x90,0x01,0x5a,0x01,0x1a,0x01,0xea,0x00, + 0xb7,0x00,0x91,0x00,0x6a,0x00,0x4e,0x00, + 0x34,0x00,0x21,0x00,0x12,0x00,0x08,0x00, + 0x02,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfd,0xff,0xf2,0xff, + 0xe1,0xff,0xc7,0xff,0xa6,0xff,0x7a,0xff, + 0x49,0xff,0x08,0xff,0xc8,0xfe,0x72,0xfe, + 0x23,0xfe,0xba,0xfd,0x5d,0xfd,0xd1,0xfc, + 0x66,0xfc,0xc9,0xfb,0x63,0xfb,0xbc,0xfa, + 0x74,0xfa,0xca,0xf9,0xd3,0xf9,0xa2,0xf8, + 0xc2,0xf5,0x93,0xf5,0xf1,0xf5,0xac,0xf5, + 0x7f,0xf8,0xbc,0xfb,0x46,0xfc,0xa8,0xfd, + 0xba,0xfe,0xec,0x7f,0x44,0x01,0x52,0x02, + 0xab,0x03,0x2f,0x04,0x51,0x07,0x04,0x0a, + 0xb3,0x09,0xff,0x09,0xc3,0x09,0xfb,0x06, + 0xd0,0x05,0xcd,0x05,0x25,0x05,0xd8,0x04, + 0x35,0x04,0xce,0x03,0x38,0x03,0xcf,0x02, + 0x4c,0x02,0xf3,0x01,0x91,0x01,0x48,0x01, + 0xfa,0x00,0xc0,0x00,0x88,0x00,0x5e,0x00, + 0x3a,0x00,0x20,0x00,0x0e,0x00,0x03,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00, + 0x11,0x00,0x19,0x00,0x48,0x00,0x4a,0x00, + 0xa9,0x00,0x95,0x00,0x39,0x01,0xfc,0x00, + 0xf9,0x01,0x7a,0x01,0xee,0x02,0x1c,0x02, + 0x21,0x04,0xcc,0x02,0x78,0x05,0x6b,0x03, + 0xd8,0x06,0xd5,0x03,0x09,0x08,0x21,0x05, + 0x2c,0x0d,0xd7,0x05,0x50,0x0e,0xe5,0x03, + 0xe1,0x0c,0xc6,0xfa,0x1b,0x10,0x19,0xed, + 0x61,0x35,0x6c,0x69,0x00,0xe4,0x27,0x0c, + 0xad,0xf1,0xeb,0x02,0xc9,0xf0,0xaf,0xfa, + 0x84,0xf1,0xe8,0xf8,0x3b,0xf3,0x06,0xfc, + 0x3a,0xf7,0xf3,0xfb,0xa0,0xf8,0x57,0xfc, + 0x13,0xfa,0xf9,0xfc,0x76,0xfb,0xae,0xfd, + 0xb5,0xfc,0x4f,0xfe,0xb1,0xfd,0xd5,0xfe, + 0x80,0xfe,0x44,0xff,0x20,0xff,0x99,0xff, + 0x92,0xff,0xd4,0xff,0xda,0xff,0xf6,0xff, + 0xfc,0xff,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x00,0x11,0x00,0x19,0x00, + 0x48,0x00,0x4a,0x00,0xa9,0x00,0x95,0x00, + 0x39,0x01,0xfc,0x00,0xf9,0x01,0x7a,0x01, + 0xee,0x02,0x1c,0x02,0x21,0x04,0xcc,0x02, + 0x78,0x05,0x6b,0x03,0xd8,0x06,0xd5,0x03, + 0x09,0x08,0x21,0x05,0x2c,0x0d,0xd7,0x05, + 0x50,0x0e,0xe5,0x03,0xe1,0x0c,0xc6,0xfa, + 0x1b,0x10,0x19,0xed,0x61,0x35,0x6c,0x69, + 0x00,0xe4,0x27,0x0c,0xad,0xf1,0xeb,0x02, + 0xc9,0xf0,0xaf,0xfa,0x84,0xf1,0xe8,0xf8, + 0x3b,0xf3,0x06,0xfc,0x3a,0xf7,0xf3,0xfb, + 0xa0,0xf8,0x57,0xfc,0x13,0xfa,0xf9,0xfc, + 0x76,0xfb,0xae,0xfd,0xb5,0xfc,0x4f,0xfe, + 0xb1,0xfd,0xd5,0xfe,0x80,0xfe,0x44,0xff, + 0x20,0xff,0x99,0xff,0x92,0xff,0xd4,0xff, + 0xda,0xff,0xf6,0xff,0xfc,0xff,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfd,0xff,0xf2,0xff,0xe1,0xff,0xc7,0xff, + 0xa6,0xff,0x7a,0xff,0x49,0xff,0x08,0xff, + 0xc8,0xfe,0x72,0xfe,0x23,0xfe,0xba,0xfd, + 0x5d,0xfd,0xd1,0xfc,0x66,0xfc,0xc9,0xfb, + 0x63,0xfb,0xbc,0xfa,0x74,0xfa,0xca,0xf9, + 0xd3,0xf9,0xa2,0xf8,0xc2,0xf5,0x93,0xf5, + 0xf1,0xf5,0xac,0xf5,0x7f,0xf8,0xbc,0xfb, + 0x46,0xfc,0xa8,0xfd,0xba,0xfe,0xec,0x7f, + 0x44,0x01,0x52,0x02,0xab,0x03,0x2f,0x04, + 0x51,0x07,0x04,0x0a,0xb3,0x09,0xff,0x09, + 0xc3,0x09,0xfb,0x06,0xd0,0x05,0xcd,0x05, + 0x25,0x05,0xd8,0x04,0x35,0x04,0xce,0x03, + 0x38,0x03,0xcf,0x02,0x4c,0x02,0xf3,0x01, + 0x91,0x01,0x48,0x01,0xfa,0x00,0xc0,0x00, + 0x88,0x00,0x5e,0x00,0x3a,0x00,0x20,0x00, + 0x0e,0x00,0x03,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x08,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf new file mode 100644 index 000000000000..339d281c2f27 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf @@ -0,0 +1,258 @@ +# Created with script example_two_beams.m 23-Oct-2023 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xc4,0x07,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc4,0x07,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x03,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff, + 0xf7,0xff,0xf0,0xff,0xe7,0xff,0xdb,0xff, + 0xa9,0xff,0x8c,0xff,0x73,0xff,0x56,0xff, + 0x39,0xff,0x1a,0xff,0x04,0xff,0x6c,0xff, + 0x6f,0xff,0x62,0xff,0x5c,0xff,0x55,0xff, + 0x52,0xff,0x4f,0xff,0x50,0xff,0x51,0xff, + 0x56,0xff,0x5c,0xff,0x65,0xff,0x76,0xff, + 0x8a,0xff,0x9f,0xff,0xb7,0xff,0xce,0xff, + 0xe7,0xff,0xec,0x7f,0x19,0x00,0x31,0x00, + 0x48,0x00,0x5f,0x00,0x73,0x00,0x86,0x00, + 0x95,0x00,0x9d,0x00,0xa2,0x00,0xa5,0x00, + 0xa6,0x00,0xa5,0x00,0xa1,0x00,0x9d,0x00, + 0x95,0x00,0x8f,0x00,0x81,0x00,0x83,0x00, + 0xdb,0x00,0xc5,0x00,0xa7,0x00,0x8c,0x00, + 0x71,0x00,0x5a,0x00,0x40,0x00,0x1a,0x00, + 0x10,0x00,0x09,0x00,0x04,0x00,0x01,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00, + 0x01,0x00,0x1e,0x00,0x0b,0x00,0x6a,0x00, + 0x23,0x00,0xb7,0x00,0x30,0x00,0x19,0x01, + 0x39,0x00,0x5c,0x01,0x8f,0xff,0x90,0x01, + 0x4b,0xff,0x0a,0x02,0xe0,0xfe,0xa2,0x02, + 0x44,0xfe,0x64,0x03,0x62,0xfd,0x6e,0x04, + 0x0d,0xfc,0x00,0x06,0xcc,0xf9,0xd2,0x08, + 0x3d,0xf5,0x0f,0x10,0x67,0xe5,0xde,0x50, + 0x9a,0x51,0xb6,0xe4,0xf2,0x0f,0x3a,0xf4, + 0x55,0x08,0x7b,0xf8,0x33,0x05,0x83,0xfa, + 0x76,0x03,0xc7,0xfb,0x57,0x02,0xa9,0xfc, + 0x8f,0x01,0x58,0xfd,0x00,0x01,0xe8,0xfd, + 0x97,0x00,0x69,0xfe,0x0c,0x00,0x2f,0xfe, + 0xbd,0xff,0xb3,0xfe,0xbe,0xff,0x21,0xff, + 0xc9,0xff,0x8c,0xff,0x02,0x00,0xce,0xff, + 0xfe,0xff,0xee,0xff,0xff,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x08,0x00,0x01,0x00,0x1e,0x00, + 0x0b,0x00,0x6a,0x00,0x23,0x00,0xb7,0x00, + 0x30,0x00,0x19,0x01,0x39,0x00,0x5c,0x01, + 0x8f,0xff,0x90,0x01,0x4b,0xff,0x0a,0x02, + 0xe0,0xfe,0xa2,0x02,0x44,0xfe,0x64,0x03, + 0x62,0xfd,0x6e,0x04,0x0d,0xfc,0x00,0x06, + 0xcc,0xf9,0xd2,0x08,0x3d,0xf5,0x0f,0x10, + 0x67,0xe5,0xde,0x50,0x9a,0x51,0xb6,0xe4, + 0xf2,0x0f,0x3a,0xf4,0x55,0x08,0x7b,0xf8, + 0x33,0x05,0x83,0xfa,0x76,0x03,0xc7,0xfb, + 0x57,0x02,0xa9,0xfc,0x8f,0x01,0x58,0xfd, + 0x00,0x01,0xe8,0xfd,0x97,0x00,0x69,0xfe, + 0x0c,0x00,0x2f,0xfe,0xbd,0xff,0xb3,0xfe, + 0xbe,0xff,0x21,0xff,0xc9,0xff,0x8c,0xff, + 0x02,0x00,0xce,0xff,0xfe,0xff,0xee,0xff, + 0xff,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfc,0xff,0xf7,0xff,0xf0,0xff, + 0xe7,0xff,0xdb,0xff,0xa9,0xff,0x8c,0xff, + 0x73,0xff,0x56,0xff,0x39,0xff,0x1a,0xff, + 0x04,0xff,0x6c,0xff,0x6f,0xff,0x62,0xff, + 0x5c,0xff,0x55,0xff,0x52,0xff,0x4f,0xff, + 0x50,0xff,0x51,0xff,0x56,0xff,0x5c,0xff, + 0x65,0xff,0x76,0xff,0x8a,0xff,0x9f,0xff, + 0xb7,0xff,0xce,0xff,0xe7,0xff,0xec,0x7f, + 0x19,0x00,0x31,0x00,0x48,0x00,0x5f,0x00, + 0x73,0x00,0x86,0x00,0x95,0x00,0x9d,0x00, + 0xa2,0x00,0xa5,0x00,0xa6,0x00,0xa5,0x00, + 0xa1,0x00,0x9d,0x00,0x95,0x00,0x8f,0x00, + 0x81,0x00,0x83,0x00,0xdb,0x00,0xc5,0x00, + 0xa7,0x00,0x8c,0x00,0x71,0x00,0x5a,0x00, + 0x40,0x00,0x1a,0x00,0x10,0x00,0x09,0x00, + 0x04,0x00,0x01,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd5,0xff, + 0xc1,0xff,0xa4,0xff,0x89,0xff,0x65,0xff, + 0x45,0xff,0x1c,0xff,0xfb,0xfe,0xcd,0xfe, + 0xaf,0xfe,0x7e,0xfe,0x6a,0xfe,0x2b,0xfe, + 0x84,0xfe,0xf6,0xfe,0xd6,0xfe,0xe9,0xfe, + 0xe3,0xfe,0xf6,0xfe,0xfc,0xfe,0x14,0xff, + 0x24,0xff,0x40,0xff,0x59,0xff,0x79,0xff, + 0x98,0xff,0xba,0xff,0xdd,0xff,0xec,0x7f, + 0x23,0x00,0x45,0x00,0x67,0x00,0x84,0x00, + 0xa3,0x00,0xba,0x00,0xd4,0x00,0xe3,0x00, + 0xf8,0x00,0xfc,0x00,0x0c,0x01,0x05,0x01, + 0x14,0x01,0xf5,0x00,0x5a,0x01,0xa7,0x01, + 0x6a,0x01,0x55,0x01,0x25,0x01,0x07,0x01, + 0xdc,0x00,0xbc,0x00,0x96,0x00,0x78,0x00, + 0x58,0x00,0x41,0x00,0x29,0x00,0x19,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x19,0x00,0x29,0x00, + 0x41,0x00,0x58,0x00,0x79,0x00,0x95,0x00, + 0xbd,0x00,0xdb,0x00,0x08,0x01,0x24,0x01, + 0x56,0x01,0x68,0x01,0xaa,0x01,0x58,0x01, + 0xf9,0x00,0x10,0x01,0x0a,0x01,0x06,0x01, + 0x04,0x01,0xef,0x00,0xed,0x00,0xc8,0x00, + 0xc8,0x00,0x91,0x00,0x9b,0x00,0x48,0x00, + 0x74,0x00,0xc5,0xff,0xeb,0x7f,0x3c,0x00, + 0x8b,0xff,0xb7,0xff,0x62,0xff,0x6b,0xff, + 0x32,0xff,0x30,0xff,0x09,0xff,0x05,0xff, + 0xee,0xfe,0xe9,0xfe,0xe3,0xfe,0xdb,0xfe, + 0xf1,0xfe,0x88,0xfe,0x28,0xfe,0x6d,0xfe, + 0x7c,0xfe,0xb1,0xfe,0xcc,0xfe,0xfc,0xfe, + 0x1b,0xff,0x46,0xff,0x64,0xff,0x89,0xff, + 0xa4,0xff,0xc1,0xff,0xd5,0xff,0xec,0xff, + 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x19,0x00,0x29,0x00,0x41,0x00,0x58,0x00, + 0x79,0x00,0x95,0x00,0xbd,0x00,0xdb,0x00, + 0x08,0x01,0x24,0x01,0x56,0x01,0x68,0x01, + 0xaa,0x01,0x58,0x01,0xf9,0x00,0x10,0x01, + 0x0a,0x01,0x06,0x01,0x04,0x01,0xef,0x00, + 0xed,0x00,0xc8,0x00,0xc8,0x00,0x91,0x00, + 0x9b,0x00,0x48,0x00,0x74,0x00,0xc5,0xff, + 0xeb,0x7f,0x3c,0x00,0x8b,0xff,0xb7,0xff, + 0x62,0xff,0x6b,0xff,0x32,0xff,0x30,0xff, + 0x09,0xff,0x05,0xff,0xee,0xfe,0xe9,0xfe, + 0xe3,0xfe,0xdb,0xfe,0xf1,0xfe,0x88,0xfe, + 0x28,0xfe,0x6d,0xfe,0x7c,0xfe,0xb1,0xfe, + 0xcc,0xfe,0xfc,0xfe,0x1b,0xff,0x46,0xff, + 0x64,0xff,0x89,0xff,0xa4,0xff,0xc1,0xff, + 0xd5,0xff,0xec,0xff,0xf9,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff, + 0xec,0xff,0xd5,0xff,0xc1,0xff,0xa4,0xff, + 0x89,0xff,0x65,0xff,0x45,0xff,0x1c,0xff, + 0xfb,0xfe,0xcd,0xfe,0xaf,0xfe,0x7e,0xfe, + 0x6a,0xfe,0x2b,0xfe,0x84,0xfe,0xf6,0xfe, + 0xd6,0xfe,0xe9,0xfe,0xe3,0xfe,0xf6,0xfe, + 0xfc,0xfe,0x14,0xff,0x24,0xff,0x40,0xff, + 0x59,0xff,0x79,0xff,0x98,0xff,0xba,0xff, + 0xdd,0xff,0xec,0x7f,0x23,0x00,0x45,0x00, + 0x67,0x00,0x84,0x00,0xa3,0x00,0xba,0x00, + 0xd4,0x00,0xe3,0x00,0xf8,0x00,0xfc,0x00, + 0x0c,0x01,0x05,0x01,0x14,0x01,0xf5,0x00, + 0x5a,0x01,0xa7,0x01,0x6a,0x01,0x55,0x01, + 0x25,0x01,0x07,0x01,0xdc,0x00,0xbc,0x00, + 0x96,0x00,0x78,0x00,0x58,0x00,0x41,0x00, + 0x29,0x00,0x19,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x08,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_50mm_pm90deg_16khz.conf b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm90deg_16khz.conf new file mode 100644 index 000000000000..9547488b9d83 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm90deg_16khz.conf @@ -0,0 +1,93 @@ +# Created with script example_two_beams.m 23-Oct-2023 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x9c,0x02,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x02,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfd,0xff,0xf2,0xff, + 0xe1,0xff,0xc7,0xff,0xa6,0xff,0x7a,0xff, + 0x49,0xff,0x08,0xff,0xc8,0xfe,0x72,0xfe, + 0x23,0xfe,0xba,0xfd,0x5d,0xfd,0xd1,0xfc, + 0x66,0xfc,0xc9,0xfb,0x63,0xfb,0xbc,0xfa, + 0x74,0xfa,0xca,0xf9,0xd3,0xf9,0xa2,0xf8, + 0xc2,0xf5,0x93,0xf5,0xf1,0xf5,0xac,0xf5, + 0x7f,0xf8,0xbc,0xfb,0x46,0xfc,0xa8,0xfd, + 0xba,0xfe,0xec,0x7f,0x44,0x01,0x52,0x02, + 0xab,0x03,0x2f,0x04,0x51,0x07,0x04,0x0a, + 0xb3,0x09,0xff,0x09,0xc3,0x09,0xfb,0x06, + 0xd0,0x05,0xcd,0x05,0x25,0x05,0xd8,0x04, + 0x35,0x04,0xce,0x03,0x38,0x03,0xcf,0x02, + 0x4c,0x02,0xf3,0x01,0x91,0x01,0x48,0x01, + 0xfa,0x00,0xc0,0x00,0x88,0x00,0x5e,0x00, + 0x3a,0x00,0x20,0x00,0x0e,0x00,0x03,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00, + 0x11,0x00,0x19,0x00,0x48,0x00,0x4a,0x00, + 0xa9,0x00,0x95,0x00,0x39,0x01,0xfc,0x00, + 0xf9,0x01,0x7a,0x01,0xee,0x02,0x1c,0x02, + 0x21,0x04,0xcc,0x02,0x78,0x05,0x6b,0x03, + 0xd8,0x06,0xd5,0x03,0x09,0x08,0x21,0x05, + 0x2c,0x0d,0xd7,0x05,0x50,0x0e,0xe5,0x03, + 0xe1,0x0c,0xc6,0xfa,0x1b,0x10,0x19,0xed, + 0x61,0x35,0x6c,0x69,0x00,0xe4,0x27,0x0c, + 0xad,0xf1,0xeb,0x02,0xc9,0xf0,0xaf,0xfa, + 0x84,0xf1,0xe8,0xf8,0x3b,0xf3,0x06,0xfc, + 0x3a,0xf7,0xf3,0xfb,0xa0,0xf8,0x57,0xfc, + 0x13,0xfa,0xf9,0xfc,0x76,0xfb,0xae,0xfd, + 0xb5,0xfc,0x4f,0xfe,0xb1,0xfd,0xd5,0xfe, + 0x80,0xfe,0x44,0xff,0x20,0xff,0x99,0xff, + 0x92,0xff,0xd4,0xff,0xda,0xff,0xf6,0xff, + 0xfc,0xff,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x00,0x11,0x00,0x19,0x00, + 0x48,0x00,0x4a,0x00,0xa9,0x00,0x95,0x00, + 0x39,0x01,0xfc,0x00,0xf9,0x01,0x7a,0x01, + 0xee,0x02,0x1c,0x02,0x21,0x04,0xcc,0x02, + 0x78,0x05,0x6b,0x03,0xd8,0x06,0xd5,0x03, + 0x09,0x08,0x21,0x05,0x2c,0x0d,0xd7,0x05, + 0x50,0x0e,0xe5,0x03,0xe1,0x0c,0xc6,0xfa, + 0x1b,0x10,0x19,0xed,0x61,0x35,0x6c,0x69, + 0x00,0xe4,0x27,0x0c,0xad,0xf1,0xeb,0x02, + 0xc9,0xf0,0xaf,0xfa,0x84,0xf1,0xe8,0xf8, + 0x3b,0xf3,0x06,0xfc,0x3a,0xf7,0xf3,0xfb, + 0xa0,0xf8,0x57,0xfc,0x13,0xfa,0xf9,0xfc, + 0x76,0xfb,0xae,0xfd,0xb5,0xfc,0x4f,0xfe, + 0xb1,0xfd,0xd5,0xfe,0x80,0xfe,0x44,0xff, + 0x20,0xff,0x99,0xff,0x92,0xff,0xd4,0xff, + 0xda,0xff,0xf6,0xff,0xfc,0xff,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfd,0xff,0xf2,0xff,0xe1,0xff,0xc7,0xff, + 0xa6,0xff,0x7a,0xff,0x49,0xff,0x08,0xff, + 0xc8,0xfe,0x72,0xfe,0x23,0xfe,0xba,0xfd, + 0x5d,0xfd,0xd1,0xfc,0x66,0xfc,0xc9,0xfb, + 0x63,0xfb,0xbc,0xfa,0x74,0xfa,0xca,0xf9, + 0xd3,0xf9,0xa2,0xf8,0xc2,0xf5,0x93,0xf5, + 0xf1,0xf5,0xac,0xf5,0x7f,0xf8,0xbc,0xfb, + 0x46,0xfc,0xa8,0xfd,0xba,0xfe,0xec,0x7f, + 0x44,0x01,0x52,0x02,0xab,0x03,0x2f,0x04, + 0x51,0x07,0x04,0x0a,0xb3,0x09,0xff,0x09, + 0xc3,0x09,0xfb,0x06,0xd0,0x05,0xcd,0x05, + 0x25,0x05,0xd8,0x04,0x35,0x04,0xce,0x03, + 0x38,0x03,0xcf,0x02,0x4c,0x02,0xf3,0x01, + 0x91,0x01,0x48,0x01,0xfa,0x00,0xc0,0x00, + 0x88,0x00,0x5e,0x00,0x3a,0x00,0x20,0x00, + 0x0e,0x00,0x03,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_50mm_pm90deg_48khz.conf b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm90deg_48khz.conf new file mode 100644 index 000000000000..0fc17a7bb3a6 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_50mm_pm90deg_48khz.conf @@ -0,0 +1,93 @@ +# Created with script example_two_beams.m 23-Oct-2023 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x9c,0x02,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x9c,0x02,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xf9,0xff,0xec,0xff,0xd5,0xff, + 0xc1,0xff,0xa4,0xff,0x89,0xff,0x65,0xff, + 0x45,0xff,0x1c,0xff,0xfb,0xfe,0xcd,0xfe, + 0xaf,0xfe,0x7e,0xfe,0x6a,0xfe,0x2b,0xfe, + 0x84,0xfe,0xf6,0xfe,0xd6,0xfe,0xe9,0xfe, + 0xe3,0xfe,0xf6,0xfe,0xfc,0xfe,0x14,0xff, + 0x24,0xff,0x40,0xff,0x59,0xff,0x79,0xff, + 0x98,0xff,0xba,0xff,0xdd,0xff,0xec,0x7f, + 0x23,0x00,0x45,0x00,0x67,0x00,0x84,0x00, + 0xa3,0x00,0xba,0x00,0xd4,0x00,0xe3,0x00, + 0xf8,0x00,0xfc,0x00,0x0c,0x01,0x05,0x01, + 0x14,0x01,0xf5,0x00,0x5a,0x01,0xa7,0x01, + 0x6a,0x01,0x55,0x01,0x25,0x01,0x07,0x01, + 0xdc,0x00,0xbc,0x00,0x96,0x00,0x78,0x00, + 0x58,0x00,0x41,0x00,0x29,0x00,0x19,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x19,0x00,0x29,0x00, + 0x41,0x00,0x58,0x00,0x79,0x00,0x95,0x00, + 0xbd,0x00,0xdb,0x00,0x08,0x01,0x24,0x01, + 0x56,0x01,0x68,0x01,0xaa,0x01,0x58,0x01, + 0xf9,0x00,0x10,0x01,0x0a,0x01,0x06,0x01, + 0x04,0x01,0xef,0x00,0xed,0x00,0xc8,0x00, + 0xc8,0x00,0x91,0x00,0x9b,0x00,0x48,0x00, + 0x74,0x00,0xc5,0xff,0xeb,0x7f,0x3c,0x00, + 0x8b,0xff,0xb7,0xff,0x62,0xff,0x6b,0xff, + 0x32,0xff,0x30,0xff,0x09,0xff,0x05,0xff, + 0xee,0xfe,0xe9,0xfe,0xe3,0xfe,0xdb,0xfe, + 0xf1,0xfe,0x88,0xfe,0x28,0xfe,0x6d,0xfe, + 0x7c,0xfe,0xb1,0xfe,0xcc,0xfe,0xfc,0xfe, + 0x1b,0xff,0x46,0xff,0x64,0xff,0x89,0xff, + 0xa4,0xff,0xc1,0xff,0xd5,0xff,0xec,0xff, + 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x19,0x00,0x29,0x00,0x41,0x00,0x58,0x00, + 0x79,0x00,0x95,0x00,0xbd,0x00,0xdb,0x00, + 0x08,0x01,0x24,0x01,0x56,0x01,0x68,0x01, + 0xaa,0x01,0x58,0x01,0xf9,0x00,0x10,0x01, + 0x0a,0x01,0x06,0x01,0x04,0x01,0xef,0x00, + 0xed,0x00,0xc8,0x00,0xc8,0x00,0x91,0x00, + 0x9b,0x00,0x48,0x00,0x74,0x00,0xc5,0xff, + 0xeb,0x7f,0x3c,0x00,0x8b,0xff,0xb7,0xff, + 0x62,0xff,0x6b,0xff,0x32,0xff,0x30,0xff, + 0x09,0xff,0x05,0xff,0xee,0xfe,0xe9,0xfe, + 0xe3,0xfe,0xdb,0xfe,0xf1,0xfe,0x88,0xfe, + 0x28,0xfe,0x6d,0xfe,0x7c,0xfe,0xb1,0xfe, + 0xcc,0xfe,0xfc,0xfe,0x1b,0xff,0x46,0xff, + 0x64,0xff,0x89,0xff,0xa4,0xff,0xc1,0xff, + 0xd5,0xff,0xec,0xff,0xf9,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xf9,0xff, + 0xec,0xff,0xd5,0xff,0xc1,0xff,0xa4,0xff, + 0x89,0xff,0x65,0xff,0x45,0xff,0x1c,0xff, + 0xfb,0xfe,0xcd,0xfe,0xaf,0xfe,0x7e,0xfe, + 0x6a,0xfe,0x2b,0xfe,0x84,0xfe,0xf6,0xfe, + 0xd6,0xfe,0xe9,0xfe,0xe3,0xfe,0xf6,0xfe, + 0xfc,0xfe,0x14,0xff,0x24,0xff,0x40,0xff, + 0x59,0xff,0x79,0xff,0x98,0xff,0xba,0xff, + 0xdd,0xff,0xec,0x7f,0x23,0x00,0x45,0x00, + 0x67,0x00,0x84,0x00,0xa3,0x00,0xba,0x00, + 0xd4,0x00,0xe3,0x00,0xf8,0x00,0xfc,0x00, + 0x0c,0x01,0x05,0x01,0x14,0x01,0xf5,0x00, + 0x5a,0x01,0xa7,0x01,0x6a,0x01,0x55,0x01, + 0x25,0x01,0x07,0x01,0xdc,0x00,0xbc,0x00, + 0x96,0x00,0x78,0x00,0x58,0x00,0x41,0x00, + 0x29,0x00,0x19,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_generic_pm10deg_16khz.conf b/tools/topology/topology2/include/components/tdfb/line2_generic_pm10deg_16khz.conf new file mode 100644 index 000000000000..c8bd09d172ed --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_generic_pm10deg_16khz.conf @@ -0,0 +1,108 @@ +# Created with script example_two_beams_default.m 17-May-2024 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams_default +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x14,0x03,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x14,0x03,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x01,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0xfd,0xff,0x08,0x00,0xf2,0xff,0x17,0x00, + 0xde,0xff,0x2f,0x00,0xc0,0xff,0x53,0x00, + 0x97,0xff,0x83,0x00,0x5f,0xff,0xc3,0x00, + 0x16,0xff,0x16,0x01,0xb9,0xfe,0x80,0x01, + 0x40,0xfe,0x0a,0x02,0xa2,0xfd,0xc1,0x02, + 0xc9,0xfc,0xc3,0x03,0x8f,0xfb,0x4e,0x05, + 0x8d,0xf9,0x0e,0x08,0x7f,0xf5,0xc6,0x0e, + 0xb9,0xe7,0x69,0x41,0x18,0x60,0x70,0xe4, + 0xf1,0x0f,0xe9,0xf4,0x67,0x08,0x53,0xf9, + 0x76,0x05,0x72,0xfb,0xd9,0x03,0xb9,0xfc, + 0xce,0x02,0x97,0xfd,0x12,0x02,0x3a,0xfe, + 0x85,0x01,0xb5,0xfe,0x19,0x01,0x14,0xff, + 0xc5,0x00,0x5d,0xff,0x85,0x00,0x96,0xff, + 0x54,0x00,0xc0,0xff,0x30,0x00,0xde,0xff, + 0x17,0x00,0xf2,0xff,0x08,0x00,0xfd,0xff, + 0x01,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0xfd,0xff,0x08,0x00, + 0xf2,0xff,0x17,0x00,0xde,0xff,0x2f,0x00, + 0xc0,0xff,0x53,0x00,0x97,0xff,0x83,0x00, + 0x5f,0xff,0xc3,0x00,0x16,0xff,0x16,0x01, + 0xb9,0xfe,0x80,0x01,0x40,0xfe,0x0a,0x02, + 0xa2,0xfd,0xc1,0x02,0xc9,0xfc,0xc3,0x03, + 0x8f,0xfb,0x4e,0x05,0x8d,0xf9,0x0e,0x08, + 0x7f,0xf5,0xc6,0x0e,0xb9,0xe7,0x69,0x41, + 0x18,0x60,0x70,0xe4,0xf1,0x0f,0xe9,0xf4, + 0x67,0x08,0x53,0xf9,0x76,0x05,0x72,0xfb, + 0xd9,0x03,0xb9,0xfc,0xce,0x02,0x97,0xfd, + 0x12,0x02,0x3a,0xfe,0x85,0x01,0xb5,0xfe, + 0x19,0x01,0x14,0xff,0xc5,0x00,0x5d,0xff, + 0x85,0x00,0x96,0xff,0x54,0x00,0xc0,0xff, + 0x30,0x00,0xde,0xff,0x17,0x00,0xf2,0xff, + 0x08,0x00,0xfd,0xff,0x01,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_generic_pm10deg_48khz.conf b/tools/topology/topology2/include/components/tdfb/line2_generic_pm10deg_48khz.conf new file mode 100644 index 000000000000..86f6f1012ba7 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_generic_pm10deg_48khz.conf @@ -0,0 +1,108 @@ +# Created with script example_two_beams_default.m 17-May-2024 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams_default +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x14,0x03,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x14,0x03,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x02,0x00,0x01,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x02,0x00,0xfb,0xff,0x0a,0x00,0xf1,0xff, + 0x17,0x00,0xe0,0xff,0x2b,0x00,0xc8,0xff, + 0x48,0x00,0xa6,0xff,0x6e,0x00,0x7a,0xff, + 0xa0,0x00,0x41,0xff,0xe2,0x00,0xf6,0xfe, + 0x38,0x01,0x93,0xfe,0xab,0x01,0x0c,0xfe, + 0x4c,0x02,0x48,0xfd,0x41,0x03,0x0b,0xfc, + 0xef,0x04,0x9a,0xf9,0xdf,0x08,0xf3,0xf1, + 0x46,0x20,0x69,0x76,0x0c,0xeb,0x70,0x0b, + 0x33,0xf8,0xdd,0x05,0x5b,0xfb,0xcc,0x03, + 0xd4,0xfc,0xb0,0x02,0xb4,0xfd,0xf9,0x01, + 0x4c,0xfe,0x79,0x01,0xbb,0xfe,0x18,0x01, + 0x0f,0xff,0xce,0x00,0x51,0xff,0x94,0x00, + 0x84,0xff,0x66,0x00,0xad,0xff,0x43,0x00, + 0xcb,0xff,0x29,0x00,0xe2,0xff,0x16,0x00, + 0xf1,0xff,0x09,0x00,0xfb,0xff,0x02,0x00, + 0xff,0xff,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0x02,0x00,0xfb,0xff, + 0x0a,0x00,0xf1,0xff,0x17,0x00,0xe0,0xff, + 0x2b,0x00,0xc8,0xff,0x48,0x00,0xa6,0xff, + 0x6e,0x00,0x7a,0xff,0xa0,0x00,0x41,0xff, + 0xe2,0x00,0xf6,0xfe,0x38,0x01,0x93,0xfe, + 0xab,0x01,0x0c,0xfe,0x4c,0x02,0x48,0xfd, + 0x41,0x03,0x0b,0xfc,0xef,0x04,0x9a,0xf9, + 0xdf,0x08,0xf3,0xf1,0x46,0x20,0x69,0x76, + 0x0c,0xeb,0x70,0x0b,0x33,0xf8,0xdd,0x05, + 0x5b,0xfb,0xcc,0x03,0xd4,0xfc,0xb0,0x02, + 0xb4,0xfd,0xf9,0x01,0x4c,0xfe,0x79,0x01, + 0xbb,0xfe,0x18,0x01,0x0f,0xff,0xce,0x00, + 0x51,0xff,0x94,0x00,0x84,0xff,0x66,0x00, + 0xad,0xff,0x43,0x00,0xcb,0xff,0x29,0x00, + 0xe2,0xff,0x16,0x00,0xf1,0xff,0x09,0x00, + 0xfb,0xff,0x02,0x00,0xff,0xff,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line2_pass.conf b/tools/topology/topology2/include/components/tdfb/line2_pass.conf new file mode 100644 index 000000000000..08d6ec3ee7bc --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line2_pass.conf @@ -0,0 +1,22 @@ +# Exported with script example_pass_config.m 13-May-2024 +# cd tools/tune/tdfb; octave --no-window-system example_pass_config.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x02,0x00,0x02,0x00, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_28mm_azm90_90_13_16khz.conf b/tools/topology/topology2/include/components/tdfb/line4_28mm_azm90_90_13_16khz.conf new file mode 100644 index 000000000000..0912b10d7410 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_28mm_azm90_90_13_16khz.conf @@ -0,0 +1,698 @@ +# Created with script example_line_array.m 23-Oct-2023 +# cd tools/tune/tdfb; octave --no-window-system example_line_array.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x84,0x15,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x84,0x15,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xf6,0xff,0xee,0xff,0xc8,0xff, + 0xae,0xff,0x51,0xff,0x2a,0xff,0xf8,0xfe, + 0x36,0x00,0xa3,0x00,0x23,0x02,0x96,0x03, + 0xf7,0x07,0xde,0x0c,0xaa,0x14,0xbf,0x14, + 0x1f,0x1a,0x77,0x13,0x9a,0x56,0x9e,0x19, + 0x26,0x0e,0x39,0x0a,0xbf,0x00,0xc2,0x00, + 0x04,0xfd,0xa4,0xfd,0x96,0xfc,0x7b,0xfd, + 0x20,0xfd,0xa5,0xfe,0xda,0xfe,0x14,0xff, + 0xf5,0xfe,0x21,0xff,0x42,0xff,0xa1,0xff, + 0xca,0xff,0xf2,0xff,0x00,0x00,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00, + 0x7b,0x00,0x7e,0x01,0x62,0x02,0x8b,0x04, + 0x14,0x05,0xda,0x07,0x03,0x06,0xd5,0x08, + 0x11,0x01,0x3d,0xff,0xfd,0xee,0x34,0xeb, + 0x39,0xd0,0xd4,0xce,0x02,0xb6,0x00,0xca, + 0x60,0xa5,0x39,0x2e,0xe2,0x1a,0x1f,0xd6, + 0x64,0x0d,0x5f,0x03,0x8a,0x1a,0x90,0x0f, + 0x6b,0x15,0xed,0x07,0x7c,0x07,0x85,0xfd, + 0xaa,0xfe,0x90,0xfb,0x53,0xfd,0x99,0xfc, + 0x99,0xfe,0xe4,0xfe,0xc4,0xff,0xdb,0xff, + 0x03,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0xdf,0xff, + 0xc2,0xff,0xf2,0xfe,0x93,0xfe,0xb1,0xfc, + 0x28,0xfd,0xa1,0xfb,0x59,0xfe,0x74,0xfd, + 0xad,0x06,0xf6,0x07,0x85,0x14,0x4e,0x10, + 0xfa,0x19,0x89,0x05,0xb5,0x0c,0x60,0xdb, + 0x14,0x0e,0xea,0x39,0x3c,0xa8,0xb9,0xc8, + 0xb7,0xb6,0x99,0xcd,0x98,0xcf,0xcd,0xe9, + 0x96,0xee,0x4e,0xfe,0xcb,0x00,0x66,0x08, + 0x10,0x06,0xa6,0x07,0x25,0x05,0x7d,0x04, + 0x6d,0x02,0x7d,0x01,0x7e,0x00,0x23,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf1,0xff,0xcb,0xff,0x9c,0xff, + 0x4b,0xff,0x0d,0xff,0x04,0xff,0xf1,0xfe, + 0xff,0xfe,0x7f,0xfe,0x6c,0xfd,0x1b,0xfd, + 0x02,0xfd,0x0b,0xfd,0x9a,0xfd,0xa8,0xff, + 0xba,0x01,0xc7,0x07,0x60,0x10,0xc7,0x13, + 0x0d,0x57,0x2d,0x18,0xb7,0x17,0x63,0x16, + 0xc2,0x13,0x37,0x0e,0xa6,0x07,0x45,0x04, + 0xdc,0x01,0xf9,0x00,0x13,0x00,0x32,0xff, + 0x0a,0xff,0x64,0xff,0x9e,0xff,0xd0,0xff, + 0xe9,0xff,0xf7,0xff,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf2,0xff,0xf0,0xff,0xb8,0xff, + 0xbd,0xff,0x2c,0xff,0x55,0xff,0x90,0xfe, + 0x55,0x00,0x27,0x00,0x76,0x02,0xd5,0x02, + 0x7e,0x08,0xd7,0x0a,0x35,0x16,0xbe,0x12, + 0x9d,0x1d,0x2b,0x0e,0x25,0x53,0xda,0x24, + 0x9f,0x0a,0xb3,0x0e,0x9d,0xff,0xdb,0x02, + 0xc0,0xfc,0xe5,0xfe,0x55,0xfc,0x51,0xfe, + 0xdc,0xfc,0x07,0xff,0xae,0xfe,0x48,0xff, + 0xda,0xfe,0x37,0xff,0x36,0xff,0xa7,0xff, + 0xc7,0xff,0xf2,0xff,0x00,0x00,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00, + 0x79,0x00,0x7a,0x01,0x58,0x02,0x92,0x04, + 0x07,0x05,0xfa,0x07,0xed,0x05,0xf0,0x08, + 0x7e,0x01,0xf9,0xff,0x8d,0xef,0x1c,0xec, + 0x1d,0xd1,0xb1,0xcf,0xe9,0xb5,0xf8,0xc9, + 0x0f,0xa4,0x25,0x1f,0xf8,0x27,0x01,0xd1, + 0x00,0x0c,0x56,0x00,0x66,0x19,0x50,0x0e, + 0x1b,0x15,0x3e,0x07,0xc4,0x07,0x65,0xfd, + 0xf3,0xfe,0x9d,0xfb,0x87,0xfd,0xa8,0xfc, + 0xb6,0xfe,0xec,0xfe,0xcd,0xff,0xdd,0xff, + 0x04,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0xe6,0xff, + 0xc9,0xff,0x0d,0xff,0xac,0xfe,0xdf,0xfc, + 0x24,0xfd,0xb8,0xfb,0x36,0xfe,0x2e,0xfd, + 0xc1,0x05,0x49,0x07,0xd6,0x12,0x09,0x10, + 0x49,0x18,0x8d,0x05,0xb7,0x0a,0xbd,0xdd, + 0x65,0x06,0x02,0x3f,0x41,0xaa,0x41,0xc7, + 0x3a,0xb7,0xca,0xcc,0x43,0xcf,0xa9,0xe8, + 0x5a,0xee,0xab,0xfd,0xbb,0x00,0xf5,0x07, + 0xfe,0x05,0x7f,0x07,0x2f,0x05,0x73,0x04, + 0x75,0x02,0x7b,0x01,0x81,0x00,0x23,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf1,0xff,0xca,0xff,0x9a,0xff, + 0x4d,0xff,0x06,0xff,0x01,0xff,0xf1,0xfe, + 0x08,0xff,0xac,0xfe,0x9e,0xfd,0x59,0xfd, + 0x6a,0xfd,0x64,0xfd,0x2b,0xfe,0x2d,0x00, + 0xff,0x01,0x54,0x08,0xb7,0x10,0x03,0x14, + 0x51,0x57,0x79,0x18,0x10,0x18,0x9d,0x16, + 0x22,0x14,0x47,0x0e,0xa3,0x07,0x89,0x04, + 0xd2,0x01,0xf0,0x00,0x0c,0x00,0x18,0xff, + 0x05,0xff,0x5b,0xff,0x96,0xff,0xca,0xff, + 0xe4,0xff,0xf5,0xff,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfb,0xff,0xf7,0xff,0xc6,0xff,0xd8,0xff, + 0x48,0xff,0x99,0xff,0x87,0xfe,0xe5,0xff, + 0x96,0xff,0x16,0x02,0x93,0x01,0xee,0x07, + 0xc2,0x06,0xad,0x14,0x06,0x11,0x69,0x1e, + 0x68,0x0d,0x21,0x38,0x8b,0x47,0xd3,0x05, + 0x43,0x17,0xf0,0x00,0x0e,0x06,0xf8,0xfd, + 0x70,0x01,0x54,0xfc,0xd7,0xff,0x8e,0xfc, + 0x6f,0xff,0x69,0xfe,0x6d,0xff,0x6d,0xfe, + 0x0a,0xff,0xbf,0xfe,0x70,0xff,0x7a,0xff, + 0xcc,0xff,0xee,0xff,0x00,0x00,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00, + 0x9f,0x00,0x4f,0x01,0xe0,0x02,0xaa,0x03, + 0xde,0x05,0x1c,0x05,0xb4,0x06,0xe1,0x02, + 0xde,0x00,0x5e,0xf4,0xcd,0xee,0xb7,0xd9, + 0x10,0xd3,0x28,0xbe,0x26,0xc7,0x1c,0xad, + 0x74,0xee,0x4d,0x46,0x5b,0xcd,0x47,0x01, + 0x78,0xfb,0x21,0x13,0x25,0x0d,0x12,0x14, + 0xea,0x06,0xf1,0x07,0xbc,0xfd,0xb2,0xfe, + 0x89,0xfb,0x18,0xfd,0x33,0xfc,0x64,0xfe, + 0xac,0xfe,0xba,0xff,0xcf,0xff,0x14,0x00, + 0x04,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x06,0x00,0xfc,0xff,0xe1,0xff, + 0x59,0xff,0xf3,0xfe,0x7e,0xfd,0x26,0xfd, + 0x13,0xfc,0xbf,0xfd,0xe5,0xfc,0xce,0x02, + 0xaa,0x05,0x61,0x0d,0x47,0x0f,0xac,0x12, + 0xf4,0x05,0xb0,0x03,0x76,0xe5,0xe9,0xf0, + 0x36,0x4a,0x18,0xb4,0xf4,0xc1,0x18,0xba, + 0x1b,0xca,0xa2,0xcf,0xda,0xe4,0x2b,0xee, + 0x68,0xfb,0xd6,0x00,0x6b,0x06,0xd9,0x05, + 0xe4,0x06,0x48,0x05,0x43,0x04,0x89,0x02, + 0x6c,0x01,0x89,0x00,0x22,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf1,0xff,0xc7,0xff,0x94,0xff,0x54,0xff, + 0xfa,0xfe,0xf1,0xfe,0xf4,0xfe,0x17,0xff, + 0x25,0xff,0x32,0xfe,0x13,0xfe,0x7b,0xfe, + 0x6f,0xfe,0xdc,0xff,0xa2,0x01,0xdb,0x02, + 0xe6,0x09,0x98,0x11,0xab,0x14,0xeb,0x57, + 0x34,0x19,0xeb,0x18,0x2c,0x17,0x15,0x15, + 0x6a,0x0e,0x9f,0x07,0x3a,0x05,0xe6,0x01, + 0xc9,0x00,0xf2,0xff,0xde,0xfe,0xfc,0xfe, + 0x42,0xff,0x82,0xff,0xb8,0xff,0xd7,0xff, + 0xf1,0xff,0xfd,0xff,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfd,0xff,0xe7,0xff,0xd7,0xff,0x86,0xff, + 0x95,0xff,0xfb,0xfe,0x4c,0xff,0x5e,0xfe, + 0xf6,0xff,0xc3,0xff,0x09,0x03,0x33,0x04, + 0x33,0x09,0x8c,0x0a,0x29,0x18,0x07,0x14, + 0x65,0x1f,0x72,0x0f,0x89,0x53,0xbe,0x27, + 0xc4,0x0b,0xc3,0x12,0x47,0x02,0xe8,0x05, + 0xfe,0x00,0xf7,0x01,0x8d,0xfe,0x34,0x00, + 0x50,0xfe,0x1c,0x00,0xd2,0xfe,0x4c,0xff, + 0xa7,0xfe,0x23,0xff,0x43,0xff,0x99,0xff, + 0xc1,0xff,0xf1,0xff,0x00,0x00,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00, + 0x83,0x00,0x5d,0x01,0x4c,0x02,0x1b,0x04, + 0xd2,0x04,0x81,0x06,0xf0,0x04,0x53,0x05, + 0x96,0x00,0x40,0xfb,0xf1,0xed,0xa2,0xe4, + 0x0d,0xd1,0x7d,0xcc,0x87,0xba,0x42,0xc4, + 0x79,0xb1,0xa6,0x47,0x4c,0xf2,0x40,0xdf, + 0xb9,0xfd,0x32,0xfe,0xaf,0x0c,0xda,0x09, + 0x03,0x09,0xbb,0x01,0x1e,0x01,0x98,0xfc, + 0x31,0xfe,0x6e,0xfc,0xf6,0xfd,0x31,0xfe, + 0x8d,0xff,0xa5,0xff,0x1c,0x00,0x10,0x00, + 0x0c,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0a,0x00,0x1d,0x00,0x09,0x00, + 0xde,0xff,0x47,0xff,0xc0,0xfe,0x4b,0xfd, + 0x27,0xfd,0xaa,0xfc,0xe9,0xfd,0x22,0xfe, + 0x97,0x03,0x8c,0x04,0x1d,0x0d,0xd0,0x08, + 0x77,0x06,0xe0,0xf6,0xd2,0xf0,0x46,0xd5, + 0x21,0x4e,0x2b,0xcf,0x72,0xb7,0x62,0xc2, + 0xef,0xc4,0xd4,0xd3,0x9a,0xde,0xb7,0xee, + 0x75,0xf7,0x12,0x01,0xd7,0x03,0x88,0x05, + 0xa9,0x05,0x48,0x05,0xd3,0x03,0x92,0x02, + 0x4b,0x01,0x93,0x00,0x20,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xff,0xc5,0xff,0x8b,0xff,0x58,0xff, + 0x07,0xff,0xca,0xfe,0xf6,0xfe,0x23,0xff, + 0x9d,0xff,0x35,0xff,0x30,0xff,0xc2,0xff, + 0x3d,0x00,0x7f,0x02,0xc3,0x03,0x8e,0x04, + 0x48,0x0c,0xb8,0x12,0x9e,0x15,0x83,0x58, + 0xdb,0x19,0xcb,0x19,0xb3,0x17,0x15,0x16, + 0x64,0x0e,0xc9,0x07,0xd7,0x05,0x82,0x02, + 0x9f,0x00,0x91,0xff,0xd1,0xfe,0xee,0xfe, + 0x2b,0xff,0x6a,0xff,0x9b,0xff,0xc7,0xff, + 0xeb,0xff,0xfb,0xff,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf9,0xff,0xe2,0xff,0xbe,0xff, + 0x7f,0xff,0x5d,0xff,0x24,0xff,0x0e,0xff, + 0x0a,0xff,0x25,0xff,0xd5,0x00,0xb1,0x03, + 0xd1,0x05,0xc1,0x08,0x72,0x0d,0xb1,0x16, + 0x27,0x17,0x2a,0x1b,0x9d,0x17,0xbc,0x58, + 0x7f,0x19,0x70,0x12,0x59,0x10,0xf3,0x06, + 0x8b,0x06,0xff,0x04,0xdb,0x02,0xb1,0x00, + 0x60,0x00,0x32,0x00,0xb5,0xff,0x12,0xff, + 0xcf,0xfe,0xb0,0xfe,0x23,0xff,0x42,0xff, + 0x89,0xff,0xc3,0xff,0xf0,0xff,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00, + 0x71,0x00,0x43,0x01,0xe3,0x01,0x9e,0x03, + 0x37,0x04,0x4d,0x06,0xb3,0x04,0xc2,0x05, + 0xad,0x00,0x1c,0x00,0x6b,0xf2,0x9e,0xec, + 0x28,0xd8,0xbf,0xd7,0x38,0xbe,0xda,0xcb, + 0xf3,0xac,0x44,0xf6,0x3f,0x3f,0xe1,0xc4, + 0xe5,0xf5,0xf2,0xe9,0x1f,0x03,0x20,0xfd, + 0xdb,0x06,0xe6,0xfc,0x2e,0x00,0x00,0xfc, + 0xcb,0xff,0xe9,0xfc,0x53,0xff,0xbd,0xfe, + 0x32,0x00,0xe2,0xff,0x58,0x00,0x1c,0x00, + 0x11,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0e,0x00,0x44,0x00,0x38,0x00, + 0x98,0x00,0xbd,0xff,0x41,0x00,0x2d,0xfe, + 0x20,0xff,0xf0,0xfb,0xb2,0xff,0xfd,0xfa, + 0x2d,0x00,0xd2,0xfb,0x73,0x07,0x44,0xfc, + 0xe2,0x03,0x20,0xe8,0xc2,0xf6,0x94,0xc2, + 0xfd,0x38,0x7f,0xff,0x9c,0xac,0x3e,0xcf, + 0x93,0xc0,0x15,0xdb,0xe7,0xda,0xd7,0xee, + 0xb7,0xf3,0x6c,0x00,0x9e,0x00,0x02,0x05, + 0xc3,0x03,0xed,0x04,0x0a,0x03,0x72,0x02, + 0x18,0x01,0x96,0x00,0x1d,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf0,0xff,0xc5,0xff,0x89,0xff,0x4b,0xff, + 0x24,0xff,0xc9,0xfe,0xca,0xfe,0x38,0xff, + 0xac,0xff,0x75,0x00,0x5b,0x00,0x02,0x01, + 0xab,0x02,0x69,0x05,0x5e,0x06,0x8a,0x07, + 0x58,0x0f,0xcc,0x13,0xb6,0x16,0xe9,0x58, + 0xf6,0x19,0xed,0x19,0xbe,0x17,0x0f,0x16, + 0x01,0x0e,0x49,0x08,0xed,0x05,0x61,0x03, + 0xed,0x00,0xed,0xfe,0x05,0xff,0xed,0xfe, + 0x20,0xff,0x4d,0xff,0x7d,0xff,0xb9,0xff, + 0xe2,0xff,0xf9,0xff,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf6,0xff,0xdb,0xff,0xad,0xff, + 0x7b,0xff,0x36,0xff,0x34,0xff,0x30,0xff, + 0x0d,0xff,0x6c,0xff,0x79,0x01,0x0a,0x04, + 0xeb,0x05,0x0a,0x09,0x41,0x0d,0x4b,0x14, + 0x41,0x17,0x51,0x18,0x8b,0x1a,0xea,0x58, + 0xd6,0x16,0x65,0x15,0x52,0x12,0xce,0x0b, + 0x02,0x09,0x71,0x07,0xdb,0x04,0x10,0x02, + 0x1e,0x01,0xae,0x00,0x80,0xff,0xdc,0xfe, + 0x93,0xfe,0xf8,0xfe,0x02,0xff,0x49,0xff, + 0x88,0xff,0xc8,0xff,0xf1,0xff,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00, + 0x64,0x00,0x1b,0x01,0x81,0x01,0xe5,0x02, + 0xcf,0x02,0x99,0x04,0x77,0x02,0xa0,0x03, + 0xd6,0xfc,0x19,0xfe,0x57,0xef,0x46,0xed, + 0xb4,0xdb,0xc7,0xdd,0x0e,0xc2,0xd6,0xd6, + 0x23,0xae,0x9f,0x35,0xfb,0x06,0xeb,0xc4, + 0x8d,0xed,0x32,0xe0,0x19,0xfa,0x68,0xf2, + 0xe1,0xfe,0x5f,0xf7,0xf6,0xfd,0xad,0xfc, + 0xab,0x00,0xb4,0xfe,0x29,0x01,0x2b,0x00, + 0x27,0x01,0x90,0x00,0xab,0x00,0x3e,0x00, + 0x18,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x17,0x00,0x3a,0x00,0xa2,0x00, + 0x81,0x00,0x0f,0x01,0x0a,0x00,0xfd,0x00, + 0x7d,0xfe,0x6e,0x00,0x61,0xfc,0x98,0xfd, + 0x0a,0xf7,0x7a,0xfe,0xff,0xf1,0xa2,0xf9, + 0x8a,0xdf,0x1d,0xed,0x7a,0xc4,0xb1,0x06, + 0x4f,0x35,0x0d,0xae,0xeb,0xd6,0x44,0xc2, + 0x54,0xde,0x30,0xdc,0xc4,0xed,0xf2,0xef, + 0x9e,0xfe,0x44,0xfd,0xff,0x03,0xc1,0x02, + 0xd1,0x04,0xf6,0x02,0xff,0x02,0x91,0x01, + 0x24,0x01,0x67,0x00,0x1f,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0xff, + 0xca,0xff,0x8d,0xff,0x4f,0xff,0x12,0xff, + 0x06,0xff,0xb0,0xfe,0xf7,0xfe,0xb1,0xff, + 0xd0,0x00,0x64,0x01,0x39,0x02,0x34,0x05, + 0x8d,0x07,0x6d,0x09,0xf0,0x0b,0xd0,0x12, + 0x1c,0x15,0xd6,0x17,0xf9,0x58,0x9a,0x19, + 0xa6,0x18,0xcc,0x16,0x26,0x14,0xd2,0x0c, + 0xe3,0x08,0x8c,0x05,0xd9,0x03,0x32,0x01, + 0x48,0xff,0xe3,0xfe,0x1c,0xff,0x1c,0xff, + 0x2c,0xff,0x71,0xff,0xa9,0xff,0xd9,0xff, + 0xf6,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf4,0xff,0xd1,0xff,0x9c,0xff, + 0x5b,0xff,0x1d,0xff,0xee,0xfe,0xf0,0xfe, + 0xcf,0xfe,0x45,0xff,0x4e,0x00,0xbf,0x01, + 0xc5,0x03,0x4c,0x06,0x45,0x09,0x13,0x0c, + 0x42,0x11,0xe6,0x15,0x03,0x17,0x76,0x19, + 0xf4,0x58,0x21,0x18,0xba,0x16,0x96,0x14, + 0x31,0x10,0xd9,0x0a,0x61,0x08,0x57,0x05, + 0x25,0x03,0x3d,0x01,0x20,0x00,0x38,0xff, + 0xf9,0xfe,0x1a,0xff,0x32,0xff,0x61,0xff, + 0x9e,0xff,0xd1,0xff,0xf4,0xff,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00, + 0x5f,0x00,0xc9,0x00,0x49,0x01,0xc9,0x01, + 0x21,0x02,0x25,0x02,0x5c,0x02,0x84,0x01, + 0x5b,0xff,0x99,0xfc,0x69,0xf8,0x8a,0xf3, + 0x5d,0xed,0x0f,0xe8,0x58,0xdd,0x87,0xd4, + 0x89,0xd1,0x09,0xce,0xaa,0x4d,0xcf,0xce, + 0xfa,0xd2,0x85,0xd6,0xbf,0xdf,0x1d,0xea, + 0x54,0xef,0x33,0xf5,0xc3,0xf9,0x73,0xfd, + 0xc7,0xff,0x86,0x01,0x14,0x02,0xc7,0x01, + 0x9f,0x01,0x3b,0x01,0xc5,0x00,0x5e,0x00, + 0x19,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x18,0x00,0x5f,0x00,0xc9,0x00, + 0x49,0x01,0xc9,0x01,0x21,0x02,0x25,0x02, + 0x5c,0x02,0x84,0x01,0x5b,0xff,0x99,0xfc, + 0x69,0xf8,0x8a,0xf3,0x5d,0xed,0x0f,0xe8, + 0x58,0xdd,0x87,0xd4,0x89,0xd1,0x09,0xce, + 0xaa,0x4d,0xcf,0xce,0xfa,0xd2,0x85,0xd6, + 0xbf,0xdf,0x1d,0xea,0x54,0xef,0x33,0xf5, + 0xc3,0xf9,0x73,0xfd,0xc7,0xff,0x86,0x01, + 0x14,0x02,0xc7,0x01,0x9f,0x01,0x3b,0x01, + 0xc5,0x00,0x5e,0x00,0x19,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf4,0xff, + 0xd1,0xff,0x9c,0xff,0x5b,0xff,0x1d,0xff, + 0xee,0xfe,0xf0,0xfe,0xcf,0xfe,0x45,0xff, + 0x4e,0x00,0xbf,0x01,0xc5,0x03,0x4c,0x06, + 0x45,0x09,0x13,0x0c,0x42,0x11,0xe6,0x15, + 0x03,0x17,0x76,0x19,0xf4,0x58,0x21,0x18, + 0xba,0x16,0x96,0x14,0x31,0x10,0xd9,0x0a, + 0x61,0x08,0x57,0x05,0x25,0x03,0x3d,0x01, + 0x20,0x00,0x38,0xff,0xf9,0xfe,0x1a,0xff, + 0x32,0xff,0x61,0xff,0x9e,0xff,0xd1,0xff, + 0xf4,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xf1,0xff,0xca,0xff,0x8d,0xff, + 0x4f,0xff,0x12,0xff,0x06,0xff,0xb0,0xfe, + 0xf7,0xfe,0xb1,0xff,0xd0,0x00,0x64,0x01, + 0x39,0x02,0x34,0x05,0x8d,0x07,0x6d,0x09, + 0xf0,0x0b,0xd0,0x12,0x1c,0x15,0xd6,0x17, + 0xf9,0x58,0x9a,0x19,0xa6,0x18,0xcc,0x16, + 0x26,0x14,0xd2,0x0c,0xe3,0x08,0x8c,0x05, + 0xd9,0x03,0x32,0x01,0x48,0xff,0xe3,0xfe, + 0x1c,0xff,0x1c,0xff,0x2c,0xff,0x71,0xff, + 0xa9,0xff,0xd9,0xff,0xf6,0xff,0x00,0x00, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00, + 0x3a,0x00,0xa2,0x00,0x81,0x00,0x0f,0x01, + 0x0a,0x00,0xfd,0x00,0x7d,0xfe,0x6e,0x00, + 0x61,0xfc,0x98,0xfd,0x0a,0xf7,0x7a,0xfe, + 0xff,0xf1,0xa2,0xf9,0x8a,0xdf,0x1d,0xed, + 0x7a,0xc4,0xb1,0x06,0x4f,0x35,0x0d,0xae, + 0xeb,0xd6,0x44,0xc2,0x54,0xde,0x30,0xdc, + 0xc4,0xed,0xf2,0xef,0x9e,0xfe,0x44,0xfd, + 0xff,0x03,0xc1,0x02,0xd1,0x04,0xf6,0x02, + 0xff,0x02,0x91,0x01,0x24,0x01,0x67,0x00, + 0x1f,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x64,0x00,0x1b,0x01, + 0x81,0x01,0xe5,0x02,0xcf,0x02,0x99,0x04, + 0x77,0x02,0xa0,0x03,0xd6,0xfc,0x19,0xfe, + 0x57,0xef,0x46,0xed,0xb4,0xdb,0xc7,0xdd, + 0x0e,0xc2,0xd6,0xd6,0x23,0xae,0x9f,0x35, + 0xfb,0x06,0xeb,0xc4,0x8d,0xed,0x32,0xe0, + 0x19,0xfa,0x68,0xf2,0xe1,0xfe,0x5f,0xf7, + 0xf6,0xfd,0xad,0xfc,0xab,0x00,0xb4,0xfe, + 0x29,0x01,0x2b,0x00,0x27,0x01,0x90,0x00, + 0xab,0x00,0x3e,0x00,0x18,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf6,0xff, + 0xdb,0xff,0xad,0xff,0x7b,0xff,0x36,0xff, + 0x34,0xff,0x30,0xff,0x0d,0xff,0x6c,0xff, + 0x79,0x01,0x0a,0x04,0xeb,0x05,0x0a,0x09, + 0x41,0x0d,0x4b,0x14,0x41,0x17,0x51,0x18, + 0x8b,0x1a,0xea,0x58,0xd6,0x16,0x65,0x15, + 0x52,0x12,0xce,0x0b,0x02,0x09,0x71,0x07, + 0xdb,0x04,0x10,0x02,0x1e,0x01,0xae,0x00, + 0x80,0xff,0xdc,0xfe,0x93,0xfe,0xf8,0xfe, + 0x02,0xff,0x49,0xff,0x88,0xff,0xc8,0xff, + 0xf1,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xc5,0xff, + 0x89,0xff,0x4b,0xff,0x24,0xff,0xc9,0xfe, + 0xca,0xfe,0x38,0xff,0xac,0xff,0x75,0x00, + 0x5b,0x00,0x02,0x01,0xab,0x02,0x69,0x05, + 0x5e,0x06,0x8a,0x07,0x58,0x0f,0xcc,0x13, + 0xb6,0x16,0xe9,0x58,0xf6,0x19,0xed,0x19, + 0xbe,0x17,0x0f,0x16,0x01,0x0e,0x49,0x08, + 0xed,0x05,0x61,0x03,0xed,0x00,0xed,0xfe, + 0x05,0xff,0xed,0xfe,0x20,0xff,0x4d,0xff, + 0x7d,0xff,0xb9,0xff,0xe2,0xff,0xf9,0xff, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00, + 0x44,0x00,0x38,0x00,0x98,0x00,0xbd,0xff, + 0x41,0x00,0x2d,0xfe,0x20,0xff,0xf0,0xfb, + 0xb2,0xff,0xfd,0xfa,0x2d,0x00,0xd2,0xfb, + 0x73,0x07,0x44,0xfc,0xe2,0x03,0x20,0xe8, + 0xc2,0xf6,0x94,0xc2,0xfd,0x38,0x7f,0xff, + 0x9c,0xac,0x3e,0xcf,0x93,0xc0,0x15,0xdb, + 0xe7,0xda,0xd7,0xee,0xb7,0xf3,0x6c,0x00, + 0x9e,0x00,0x02,0x05,0xc3,0x03,0xed,0x04, + 0x0a,0x03,0x72,0x02,0x18,0x01,0x96,0x00, + 0x1d,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x20,0x00,0x71,0x00,0x43,0x01, + 0xe3,0x01,0x9e,0x03,0x37,0x04,0x4d,0x06, + 0xb3,0x04,0xc2,0x05,0xad,0x00,0x1c,0x00, + 0x6b,0xf2,0x9e,0xec,0x28,0xd8,0xbf,0xd7, + 0x38,0xbe,0xda,0xcb,0xf3,0xac,0x44,0xf6, + 0x3f,0x3f,0xe1,0xc4,0xe5,0xf5,0xf2,0xe9, + 0x1f,0x03,0x20,0xfd,0xdb,0x06,0xe6,0xfc, + 0x2e,0x00,0x00,0xfc,0xcb,0xff,0xe9,0xfc, + 0x53,0xff,0xbd,0xfe,0x32,0x00,0xe2,0xff, + 0x58,0x00,0x1c,0x00,0x11,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf9,0xff, + 0xe2,0xff,0xbe,0xff,0x7f,0xff,0x5d,0xff, + 0x24,0xff,0x0e,0xff,0x0a,0xff,0x25,0xff, + 0xd5,0x00,0xb1,0x03,0xd1,0x05,0xc1,0x08, + 0x72,0x0d,0xb1,0x16,0x27,0x17,0x2a,0x1b, + 0x9d,0x17,0xbc,0x58,0x7f,0x19,0x70,0x12, + 0x59,0x10,0xf3,0x06,0x8b,0x06,0xff,0x04, + 0xdb,0x02,0xb1,0x00,0x60,0x00,0x32,0x00, + 0xb5,0xff,0x12,0xff,0xcf,0xfe,0xb0,0xfe, + 0x23,0xff,0x42,0xff,0x89,0xff,0xc3,0xff, + 0xf0,0xff,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf0,0xff,0xc5,0xff, + 0x8b,0xff,0x58,0xff,0x07,0xff,0xca,0xfe, + 0xf6,0xfe,0x23,0xff,0x9d,0xff,0x35,0xff, + 0x30,0xff,0xc2,0xff,0x3d,0x00,0x7f,0x02, + 0xc3,0x03,0x8e,0x04,0x48,0x0c,0xb8,0x12, + 0x9e,0x15,0x83,0x58,0xdb,0x19,0xcb,0x19, + 0xb3,0x17,0x15,0x16,0x64,0x0e,0xc9,0x07, + 0xd7,0x05,0x82,0x02,0x9f,0x00,0x91,0xff, + 0xd1,0xfe,0xee,0xfe,0x2b,0xff,0x6a,0xff, + 0x9b,0xff,0xc7,0xff,0xeb,0xff,0xfb,0xff, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00, + 0x1d,0x00,0x09,0x00,0xde,0xff,0x47,0xff, + 0xc0,0xfe,0x4b,0xfd,0x27,0xfd,0xaa,0xfc, + 0xe9,0xfd,0x22,0xfe,0x97,0x03,0x8c,0x04, + 0x1d,0x0d,0xd0,0x08,0x77,0x06,0xe0,0xf6, + 0xd2,0xf0,0x46,0xd5,0x21,0x4e,0x2b,0xcf, + 0x72,0xb7,0x62,0xc2,0xef,0xc4,0xd4,0xd3, + 0x9a,0xde,0xb7,0xee,0x75,0xf7,0x12,0x01, + 0xd7,0x03,0x88,0x05,0xa9,0x05,0x48,0x05, + 0xd3,0x03,0x92,0x02,0x4b,0x01,0x93,0x00, + 0x20,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x22,0x00,0x83,0x00,0x5d,0x01, + 0x4c,0x02,0x1b,0x04,0xd2,0x04,0x81,0x06, + 0xf0,0x04,0x53,0x05,0x96,0x00,0x40,0xfb, + 0xf1,0xed,0xa2,0xe4,0x0d,0xd1,0x7d,0xcc, + 0x87,0xba,0x42,0xc4,0x79,0xb1,0xa6,0x47, + 0x4c,0xf2,0x40,0xdf,0xb9,0xfd,0x32,0xfe, + 0xaf,0x0c,0xda,0x09,0x03,0x09,0xbb,0x01, + 0x1e,0x01,0x98,0xfc,0x31,0xfe,0x6e,0xfc, + 0xf6,0xfd,0x31,0xfe,0x8d,0xff,0xa5,0xff, + 0x1c,0x00,0x10,0x00,0x0c,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfd,0xff,0xe7,0xff, + 0xd7,0xff,0x86,0xff,0x95,0xff,0xfb,0xfe, + 0x4c,0xff,0x5e,0xfe,0xf6,0xff,0xc3,0xff, + 0x09,0x03,0x33,0x04,0x33,0x09,0x8c,0x0a, + 0x29,0x18,0x07,0x14,0x65,0x1f,0x72,0x0f, + 0x89,0x53,0xbe,0x27,0xc4,0x0b,0xc3,0x12, + 0x47,0x02,0xe8,0x05,0xfe,0x00,0xf7,0x01, + 0x8d,0xfe,0x34,0x00,0x50,0xfe,0x1c,0x00, + 0xd2,0xfe,0x4c,0xff,0xa7,0xfe,0x23,0xff, + 0x43,0xff,0x99,0xff,0xc1,0xff,0xf1,0xff, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf1,0xff,0xc7,0xff, + 0x94,0xff,0x54,0xff,0xfa,0xfe,0xf1,0xfe, + 0xf4,0xfe,0x17,0xff,0x25,0xff,0x32,0xfe, + 0x13,0xfe,0x7b,0xfe,0x6f,0xfe,0xdc,0xff, + 0xa2,0x01,0xdb,0x02,0xe6,0x09,0x98,0x11, + 0xab,0x14,0xeb,0x57,0x34,0x19,0xeb,0x18, + 0x2c,0x17,0x15,0x15,0x6a,0x0e,0x9f,0x07, + 0x3a,0x05,0xe6,0x01,0xc9,0x00,0xf2,0xff, + 0xde,0xfe,0xfc,0xfe,0x42,0xff,0x82,0xff, + 0xb8,0xff,0xd7,0xff,0xf1,0xff,0xfd,0xff, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00, + 0xfc,0xff,0xe1,0xff,0x59,0xff,0xf3,0xfe, + 0x7e,0xfd,0x26,0xfd,0x13,0xfc,0xbf,0xfd, + 0xe5,0xfc,0xce,0x02,0xaa,0x05,0x61,0x0d, + 0x47,0x0f,0xac,0x12,0xf4,0x05,0xb0,0x03, + 0x76,0xe5,0xe9,0xf0,0x36,0x4a,0x18,0xb4, + 0xf4,0xc1,0x18,0xba,0x1b,0xca,0xa2,0xcf, + 0xda,0xe4,0x2b,0xee,0x68,0xfb,0xd6,0x00, + 0x6b,0x06,0xd9,0x05,0xe4,0x06,0x48,0x05, + 0x43,0x04,0x89,0x02,0x6c,0x01,0x89,0x00, + 0x22,0x00,0x00,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1f,0x00,0x9f,0x00,0x4f,0x01, + 0xe0,0x02,0xaa,0x03,0xde,0x05,0x1c,0x05, + 0xb4,0x06,0xe1,0x02,0xde,0x00,0x5e,0xf4, + 0xcd,0xee,0xb7,0xd9,0x10,0xd3,0x28,0xbe, + 0x26,0xc7,0x1c,0xad,0x74,0xee,0x4d,0x46, + 0x5b,0xcd,0x47,0x01,0x78,0xfb,0x21,0x13, + 0x25,0x0d,0x12,0x14,0xea,0x06,0xf1,0x07, + 0xbc,0xfd,0xb2,0xfe,0x89,0xfb,0x18,0xfd, + 0x33,0xfc,0x64,0xfe,0xac,0xfe,0xba,0xff, + 0xcf,0xff,0x14,0x00,0x04,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfb,0xff,0xf7,0xff, + 0xc6,0xff,0xd8,0xff,0x48,0xff,0x99,0xff, + 0x87,0xfe,0xe5,0xff,0x96,0xff,0x16,0x02, + 0x93,0x01,0xee,0x07,0xc2,0x06,0xad,0x14, + 0x06,0x11,0x69,0x1e,0x68,0x0d,0x21,0x38, + 0x8b,0x47,0xd3,0x05,0x43,0x17,0xf0,0x00, + 0x0e,0x06,0xf8,0xfd,0x70,0x01,0x54,0xfc, + 0xd7,0xff,0x8e,0xfc,0x6f,0xff,0x69,0xfe, + 0x6d,0xff,0x6d,0xfe,0x0a,0xff,0xbf,0xfe, + 0x70,0xff,0x7a,0xff,0xcc,0xff,0xee,0xff, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0xff, + 0xca,0xff,0x9a,0xff,0x4d,0xff,0x06,0xff, + 0x01,0xff,0xf1,0xfe,0x08,0xff,0xac,0xfe, + 0x9e,0xfd,0x59,0xfd,0x6a,0xfd,0x64,0xfd, + 0x2b,0xfe,0x2d,0x00,0xff,0x01,0x54,0x08, + 0xb7,0x10,0x03,0x14,0x51,0x57,0x79,0x18, + 0x10,0x18,0x9d,0x16,0x22,0x14,0x47,0x0e, + 0xa3,0x07,0x89,0x04,0xd2,0x01,0xf0,0x00, + 0x0c,0x00,0x18,0xff,0x05,0xff,0x5b,0xff, + 0x96,0xff,0xca,0xff,0xe4,0xff,0xf5,0xff, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0xe6,0xff,0xc9,0xff,0x0d,0xff, + 0xac,0xfe,0xdf,0xfc,0x24,0xfd,0xb8,0xfb, + 0x36,0xfe,0x2e,0xfd,0xc1,0x05,0x49,0x07, + 0xd6,0x12,0x09,0x10,0x49,0x18,0x8d,0x05, + 0xb7,0x0a,0xbd,0xdd,0x65,0x06,0x02,0x3f, + 0x41,0xaa,0x41,0xc7,0x3a,0xb7,0xca,0xcc, + 0x43,0xcf,0xa9,0xe8,0x5a,0xee,0xab,0xfd, + 0xbb,0x00,0xf5,0x07,0xfe,0x05,0x7f,0x07, + 0x2f,0x05,0x73,0x04,0x75,0x02,0x7b,0x01, + 0x81,0x00,0x23,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x23,0x00,0x79,0x00,0x7a,0x01, + 0x58,0x02,0x92,0x04,0x07,0x05,0xfa,0x07, + 0xed,0x05,0xf0,0x08,0x7e,0x01,0xf9,0xff, + 0x8d,0xef,0x1c,0xec,0x1d,0xd1,0xb1,0xcf, + 0xe9,0xb5,0xf8,0xc9,0x0f,0xa4,0x25,0x1f, + 0xf8,0x27,0x01,0xd1,0x00,0x0c,0x56,0x00, + 0x66,0x19,0x50,0x0e,0x1b,0x15,0x3e,0x07, + 0xc4,0x07,0x65,0xfd,0xf3,0xfe,0x9d,0xfb, + 0x87,0xfd,0xa8,0xfc,0xb6,0xfe,0xec,0xfe, + 0xcd,0xff,0xdd,0xff,0x04,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf2,0xff, + 0xf0,0xff,0xb8,0xff,0xbd,0xff,0x2c,0xff, + 0x55,0xff,0x90,0xfe,0x55,0x00,0x27,0x00, + 0x76,0x02,0xd5,0x02,0x7e,0x08,0xd7,0x0a, + 0x35,0x16,0xbe,0x12,0x9d,0x1d,0x2b,0x0e, + 0x25,0x53,0xda,0x24,0x9f,0x0a,0xb3,0x0e, + 0x9d,0xff,0xdb,0x02,0xc0,0xfc,0xe5,0xfe, + 0x55,0xfc,0x51,0xfe,0xdc,0xfc,0x07,0xff, + 0xae,0xfe,0x48,0xff,0xda,0xfe,0x37,0xff, + 0x36,0xff,0xa7,0xff,0xc7,0xff,0xf2,0xff, + 0x00,0x00,0x00,0x00,0x28,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0xff, + 0xcb,0xff,0x9c,0xff,0x4b,0xff,0x0d,0xff, + 0x04,0xff,0xf1,0xfe,0xff,0xfe,0x7f,0xfe, + 0x6c,0xfd,0x1b,0xfd,0x02,0xfd,0x0b,0xfd, + 0x9a,0xfd,0xa8,0xff,0xba,0x01,0xc7,0x07, + 0x60,0x10,0xc7,0x13,0x0d,0x57,0x2d,0x18, + 0xb7,0x17,0x63,0x16,0xc2,0x13,0x37,0x0e, + 0xa6,0x07,0x45,0x04,0xdc,0x01,0xf9,0x00, + 0x13,0x00,0x32,0xff,0x0a,0xff,0x64,0xff, + 0x9e,0xff,0xd0,0xff,0xe9,0xff,0xf7,0xff, + 0x28,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x00,0xdf,0xff,0xc2,0xff,0xf2,0xfe, + 0x93,0xfe,0xb1,0xfc,0x28,0xfd,0xa1,0xfb, + 0x59,0xfe,0x74,0xfd,0xad,0x06,0xf6,0x07, + 0x85,0x14,0x4e,0x10,0xfa,0x19,0x89,0x05, + 0xb5,0x0c,0x60,0xdb,0x14,0x0e,0xea,0x39, + 0x3c,0xa8,0xb9,0xc8,0xb7,0xb6,0x99,0xcd, + 0x98,0xcf,0xcd,0xe9,0x96,0xee,0x4e,0xfe, + 0xcb,0x00,0x66,0x08,0x10,0x06,0xa6,0x07, + 0x25,0x05,0x7d,0x04,0x6d,0x02,0x7d,0x01, + 0x7e,0x00,0x23,0x00,0x28,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x23,0x00,0x7b,0x00,0x7e,0x01, + 0x62,0x02,0x8b,0x04,0x14,0x05,0xda,0x07, + 0x03,0x06,0xd5,0x08,0x11,0x01,0x3d,0xff, + 0xfd,0xee,0x34,0xeb,0x39,0xd0,0xd4,0xce, + 0x02,0xb6,0x00,0xca,0x60,0xa5,0x39,0x2e, + 0xe2,0x1a,0x1f,0xd6,0x64,0x0d,0x5f,0x03, + 0x8a,0x1a,0x90,0x0f,0x6b,0x15,0xed,0x07, + 0x7c,0x07,0x85,0xfd,0xaa,0xfe,0x90,0xfb, + 0x53,0xfd,0x99,0xfc,0x99,0xfe,0xe4,0xfe, + 0xc4,0xff,0xdb,0xff,0x03,0x00,0x00,0x00, + 0x28,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xf6,0xff, + 0xee,0xff,0xc8,0xff,0xae,0xff,0x51,0xff, + 0x2a,0xff,0xf8,0xfe,0x36,0x00,0xa3,0x00, + 0x23,0x02,0x96,0x03,0xf7,0x07,0xde,0x0c, + 0xaa,0x14,0xbf,0x14,0x1f,0x1a,0x77,0x13, + 0x9a,0x56,0x9e,0x19,0x26,0x0e,0x39,0x0a, + 0xbf,0x00,0xc2,0x00,0x04,0xfd,0xa4,0xfd, + 0x96,0xfc,0x7b,0xfd,0x20,0xfd,0xa5,0xfe, + 0xda,0xfe,0x14,0xff,0xf5,0xfe,0x21,0xff, + 0x42,0xff,0xa1,0xff,0xca,0xff,0xf2,0xff, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00, + 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00, + 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00, + 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00, + 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00, + 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00, + 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00, + 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00, + 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x30,0x00,0x00,0x00,0x00,0x00,0xac,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_28mm_azm90_90_13_48khz.conf b/tools/topology/topology2/include/components/tdfb/line4_28mm_azm90_90_13_48khz.conf new file mode 100644 index 000000000000..fb13f144c246 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_28mm_azm90_90_13_48khz.conf @@ -0,0 +1,1218 @@ +# Created with script example_line_array.m 23-Oct-2023 +# cd tools/tune/tdfb; octave --no-window-system example_line_array.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xc4,0x25,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xc4,0x25,0x00,0x00,0x04,0x00,0x02,0x00, + 0x01,0x00,0x04,0x00,0x0d,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfa,0xff,0xeb,0xff,0x00,0x00,0xf1,0xff, + 0x0e,0x00,0xf3,0xff,0x28,0x00,0x01,0x00, + 0x5b,0x00,0x15,0x00,0x71,0x00,0x38,0x00, + 0xe2,0x00,0x92,0x00,0x7d,0x01,0x0f,0x01, + 0x4c,0x02,0x99,0x01,0x60,0x03,0x7d,0x03, + 0x28,0x05,0x5b,0x04,0x7b,0x06,0x35,0x05, + 0xc9,0x07,0xe6,0x05,0xba,0x08,0x90,0x05, + 0xca,0x09,0x4c,0x05,0x3e,0x0b,0xc9,0x03, + 0x4b,0x0e,0x9a,0xfc,0x99,0x41,0x38,0x1a, + 0x11,0xff,0xca,0x0b,0x8f,0x02,0xa4,0x08, + 0xef,0x02,0xaf,0x06,0x93,0x02,0xb1,0x03, + 0x32,0x00,0x3b,0x02,0xba,0xff,0x40,0x01, + 0x55,0xff,0x84,0x00,0x20,0xff,0x44,0x00, + 0xed,0xfe,0xd5,0xff,0xfc,0xfe,0xb7,0xff, + 0x1d,0xff,0xb4,0xff,0x49,0xff,0xbc,0xff, + 0x61,0xff,0xbc,0xff,0x8b,0xff,0xce,0xff, + 0xaf,0xff,0xde,0xff,0xcc,0xff,0xf4,0xff, + 0xed,0xff,0xfb,0xff,0xf7,0xff,0xfe,0xff, + 0xfe,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0x0c,0x00, + 0x1e,0x00,0x2b,0x00,0x49,0x00,0x4d,0x00, + 0x84,0x00,0x7d,0x00,0xa0,0x00,0x68,0x00, + 0x7e,0x00,0x02,0x00,0x01,0x00,0x3d,0xff, + 0x35,0xff,0xf0,0xfd,0xc3,0xfd,0x0e,0xfc, + 0xd6,0xfb,0xac,0xf9,0x84,0xf9,0xda,0xf6, + 0xb5,0xf5,0x26,0xf2,0x9e,0xf2,0x0f,0xef, + 0x27,0xf0,0x47,0xec,0x54,0xee,0x14,0xea, + 0xae,0xec,0x49,0xe7,0x28,0xed,0xba,0xe6, + 0xd6,0xef,0xdc,0xe5,0x78,0xf6,0x8b,0xdd, + 0xc8,0x6a,0x09,0x0a,0x49,0xe9,0x0e,0xfd, + 0x03,0xf3,0x0d,0xfe,0xbb,0xf8,0x78,0x00, + 0x22,0xfd,0xc9,0x03,0x52,0x01,0x6c,0x05, + 0x50,0x03,0x47,0x06,0x6a,0x04,0x67,0x06, + 0xdb,0x04,0x62,0x06,0x2a,0x04,0x08,0x05, + 0x58,0x03,0xc7,0x03,0x56,0x02,0x88,0x02, + 0x5d,0x01,0x72,0x01,0x7c,0x00,0x96,0x00, + 0x00,0x00,0x19,0x00,0xbe,0xff,0xdb,0xff, + 0xaf,0xff,0xe1,0xff,0xd3,0xff,0xe7,0xff, + 0xe6,0xff,0xf4,0xff,0xf9,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff, + 0xfa,0xff,0xf1,0xff,0xeb,0xff,0xde,0xff, + 0xdd,0xff,0xd1,0xff,0xc7,0xff,0xb5,0xff, + 0xde,0xff,0xdf,0xff,0x2e,0x00,0x42,0x00, + 0xbe,0x00,0xf7,0x00,0xbd,0x01,0xee,0x01, + 0xdb,0x02,0x06,0x03,0x0e,0x04,0x1b,0x04, + 0x20,0x05,0x24,0x05,0x4e,0x06,0x09,0x05, + 0x22,0x06,0x9f,0x04,0x87,0x05,0x5b,0x03, + 0x2d,0x04,0x37,0x01,0x33,0x01,0xb9,0xfc, + 0x14,0xfe,0x83,0xf8,0x17,0xfb,0x38,0xf3, + 0x8f,0xf9,0x0e,0xe9,0x5c,0x6f,0x48,0xfa, + 0x57,0xe8,0xdd,0xef,0xe5,0xe8,0xad,0xec, + 0xa4,0xe8,0x65,0xeb,0x28,0xe9,0xd5,0xec, + 0xce,0xeb,0x60,0xee,0x1a,0xee,0xa0,0xf0, + 0xec,0xf0,0x57,0xf3,0x19,0xf4,0x7b,0xf7, + 0x75,0xf8,0x41,0xfa,0xf9,0xfa,0x7c,0xfc, + 0x16,0xfd,0x40,0xfe,0xb1,0xfe,0x7c,0xff, + 0xa6,0xff,0x2a,0x00,0x40,0x00,0x82,0x00, + 0x7a,0x00,0x8d,0x00,0x73,0x00,0x59,0x00, + 0x3e,0x00,0x30,0x00,0x1b,0x00,0x0d,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xfc,0xff, + 0xfa,0xff,0xf7,0xff,0xf3,0xff,0xee,0xff, + 0xda,0xff,0xce,0xff,0xc2,0xff,0xb6,0xff, + 0xa7,0xff,0x9b,0xff,0x88,0xff,0x89,0xff, + 0x81,0xff,0x74,0xff,0x65,0xff,0x61,0xff, + 0x58,0xff,0x64,0xff,0x60,0xff,0xa2,0xff, + 0xc5,0xff,0xc0,0xff,0x10,0x00,0x48,0x00, + 0xa9,0x00,0xfc,0x00,0x72,0x01,0xde,0x01, + 0xe0,0x03,0xb5,0x04,0x20,0x05,0xb1,0x05, + 0x22,0x06,0xa0,0x06,0x02,0x07,0x66,0x07, + 0xa5,0x47,0xea,0x07,0x00,0x08,0x10,0x08, + 0xfe,0x07,0xe5,0x07,0xac,0x07,0x69,0x07, + 0x1f,0x07,0x3c,0x07,0xb5,0x06,0x47,0x06, + 0xab,0x05,0x37,0x05,0x8b,0x04,0x2c,0x04, + 0x28,0x03,0x19,0x02,0xef,0x01,0x7d,0x01, + 0x37,0x01,0xe6,0x00,0xac,0x00,0x76,0x00, + 0x4a,0x00,0x37,0x00,0x3d,0x00,0x21,0x00, + 0x14,0x00,0x07,0x00,0x01,0x00,0xfd,0xff, + 0xfb,0xff,0xf2,0xff,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf9,0xff,0xe0,0xff,0xf6,0xff,0xe0,0xff, + 0x1a,0x00,0xdd,0xff,0x47,0x00,0xef,0xff, + 0xa1,0x00,0x09,0x00,0xce,0x00,0x42,0x00, + 0xa1,0x01,0xe1,0x00,0xc6,0x02,0xc7,0x01, + 0x46,0x04,0xea,0x02,0x8f,0x05,0xb3,0x05, + 0x39,0x0a,0xb7,0x07,0xdd,0x0c,0x67,0x09, + 0x9a,0x0f,0xc5,0x0a,0x0b,0x12,0x1e,0x0a, + 0x38,0x14,0x88,0x09,0x88,0x17,0x72,0x06, + 0xd3,0x1d,0x16,0xfa,0x4b,0x48,0x5c,0x76, + 0xc2,0xf3,0x5f,0x1d,0x60,0x02,0x5a,0x14, + 0xb2,0x04,0x8c,0x0f,0xcd,0x04,0xf0,0x0a, + 0xde,0xff,0xf7,0x05,0x24,0xff,0xb8,0x03, + 0x68,0xfe,0x0f,0x02,0xe0,0xfd,0x86,0x01, + 0xf7,0xfd,0x16,0x00,0xda,0xfd,0xc5,0xff, + 0x13,0xfe,0xa7,0xff,0x69,0xfe,0xa9,0xff, + 0xb1,0xfe,0x8b,0xff,0xef,0xfe,0xa4,0xff, + 0x3b,0xff,0xbd,0xff,0x7a,0xff,0xe7,0xff, + 0xcc,0xff,0xf5,0xff,0xe4,0xff,0xfa,0xff, + 0xf5,0xff,0xfe,0xff,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0x0b,0x00, + 0x20,0x00,0x28,0x00,0x4f,0x00,0x45,0x00, + 0x86,0x00,0x73,0x00,0xbc,0x00,0x59,0x00, + 0xab,0x00,0xed,0xff,0x44,0x00,0x23,0xff, + 0x90,0xff,0xc4,0xfd,0x3c,0xfe,0xd0,0xfb, + 0x72,0xfc,0x54,0xf9,0x47,0xfa,0x59,0xf6, + 0xec,0xf6,0x90,0xf1,0xb4,0xf3,0x2e,0xee, + 0x75,0xf1,0x0b,0xeb,0xe5,0xef,0x60,0xe8, + 0xc9,0xee,0xbc,0xe4,0x9b,0xef,0x1b,0xe3, + 0x74,0xf3,0x3c,0xe0,0xfa,0xfc,0x68,0xd2, + 0xe5,0x4b,0x90,0x37,0x1a,0xda,0xbd,0x04, + 0x64,0xec,0xc7,0x01,0x5c,0xf4,0xba,0x02, + 0xc1,0xf9,0xd2,0x04,0xdc,0xfe,0x65,0x06, + 0x50,0x01,0x02,0x07,0xcc,0x02,0x00,0x07, + 0x7a,0x03,0x28,0x07,0x61,0x03,0x60,0x05, + 0xaf,0x02,0x16,0x04,0xd8,0x01,0xcc,0x02, + 0x01,0x01,0xb2,0x01,0x52,0x00,0xc0,0x00, + 0xdc,0xff,0x3a,0x00,0xa8,0xff,0xf2,0xff, + 0xa3,0xff,0xef,0xff,0xcd,0xff,0xee,0xff, + 0xe4,0xff,0xf6,0xff,0xf8,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff, + 0xfa,0xff,0xf0,0xff,0xed,0xff,0xd9,0xff, + 0xe2,0xff,0xc8,0xff,0xdb,0xff,0x9d,0xff, + 0xe9,0xff,0xb9,0xff,0x3a,0x00,0x07,0x00, + 0xcd,0x00,0xac,0x00,0xc9,0x01,0x78,0x01, + 0xea,0x02,0x71,0x02,0x29,0x04,0x66,0x03, + 0x4d,0x05,0x62,0x04,0xdf,0x06,0x02,0x04, + 0x9d,0x06,0x6d,0x03,0x3e,0x06,0xf4,0x01, + 0x36,0x05,0x86,0xff,0xae,0x02,0xa6,0xfa, + 0x4d,0x00,0xad,0xf5,0x8a,0xfe,0xa9,0xee, + 0x28,0x00,0x9a,0xdd,0x2d,0x67,0xc0,0x0f, + 0x74,0xdf,0x79,0xf5,0xe3,0xe4,0xd1,0xef, + 0x16,0xe6,0x84,0xed,0x35,0xe7,0x1c,0xee, + 0x83,0xea,0x71,0xef,0x0b,0xed,0x6a,0xf1, + 0x0e,0xf0,0xe9,0xf3,0x62,0xf3,0x98,0xf7, + 0xd2,0xf7,0x8d,0xfa,0x78,0xfa,0xb0,0xfc, + 0xb0,0xfc,0x65,0xfe,0x62,0xfe,0x9e,0xff, + 0x7b,0xff,0x3b,0x00,0x1e,0x00,0x8f,0x00, + 0x64,0x00,0x96,0x00,0x64,0x00,0x5c,0x00, + 0x38,0x00,0x31,0x00,0x19,0x00,0x0e,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xfc,0xff, + 0xfa,0xff,0xf7,0xff,0xf3,0xff,0xf1,0xff, + 0xdf,0xff,0xd0,0xff,0xc7,0xff,0xbb,0xff, + 0xaf,0xff,0xa2,0xff,0x96,0xff,0x9a,0xff, + 0x8f,0xff,0x87,0xff,0x78,0xff,0x78,0xff, + 0x6d,0xff,0x7f,0xff,0x75,0xff,0xdc,0xff, + 0xf0,0xff,0xd9,0xff,0x2a,0x00,0x64,0x00, + 0xbf,0x00,0x1a,0x01,0x80,0x01,0x16,0x02, + 0x22,0x04,0xc1,0x04,0x40,0x05,0xc2,0x05, + 0x3d,0x06,0xb2,0x06,0x1a,0x07,0x78,0x07, + 0xba,0x47,0x00,0x08,0x1b,0x08,0x2a,0x08, + 0x19,0x08,0x01,0x08,0xc7,0x07,0x89,0x07, + 0x2d,0x07,0x4b,0x07,0xd2,0x06,0x5d,0x06, + 0xc3,0x05,0x4d,0x05,0x9e,0x04,0x43,0x04, + 0x11,0x03,0x06,0x02,0x03,0x02,0x84,0x01, + 0x45,0x01,0xec,0x00,0xb7,0x00,0x79,0x00, + 0x53,0x00,0x2b,0x00,0x37,0x00,0x23,0x00, + 0x13,0x00,0x07,0x00,0x00,0x00,0xfd,0xff, + 0xf7,0xff,0xf1,0xff,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfb,0xff,0xf2,0xff,0xf6,0xff,0xea,0xff, + 0x05,0x00,0xf7,0xff,0x17,0x00,0x09,0x00, + 0x31,0x00,0x02,0x00,0x60,0x00,0x42,0x00, + 0xc4,0x00,0xa3,0x00,0x52,0x01,0x28,0x01, + 0x0d,0x02,0xad,0x01,0x71,0x02,0xb0,0x02, + 0xfb,0x04,0x62,0x04,0x34,0x06,0x62,0x05, + 0x76,0x07,0x45,0x06,0x69,0x08,0x2e,0x06, + 0x54,0x09,0x4d,0x06,0x73,0x0a,0x95,0x05, + 0x35,0x0c,0x5d,0x02,0x6c,0x15,0x80,0x44, + 0x5a,0xfe,0x3e,0x0c,0x70,0x03,0xf8,0x08, + 0xde,0x03,0x26,0x07,0x76,0x03,0xa8,0x05, + 0x7f,0x01,0x81,0x02,0x8e,0x00,0xa0,0x01, + 0x0a,0x00,0xea,0x00,0xb6,0xff,0xcf,0x00, + 0xe8,0xff,0x2c,0x00,0x68,0xff,0xf5,0xff, + 0x72,0xff,0xe5,0xff,0x86,0xff,0xdd,0xff, + 0x99,0xff,0xda,0xff,0xa1,0xff,0xd3,0xff, + 0xb9,0xff,0xdc,0xff,0xd4,0xff,0xf9,0xff, + 0xed,0xff,0xfb,0xff,0xf5,0xff,0xfc,0xff, + 0xfb,0xff,0xff,0xff,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0x0c,0x00, + 0x1d,0x00,0x28,0x00,0x46,0x00,0x46,0x00, + 0x6d,0x00,0x67,0x00,0xa5,0x00,0x56,0x00, + 0x84,0x00,0xee,0xff,0x24,0x00,0x28,0xff, + 0x36,0xff,0xc5,0xfd,0xca,0xfd,0xdb,0xfb, + 0xe7,0xfb,0x77,0xf9,0x8b,0xf9,0xe6,0xf5, + 0x5c,0xf6,0x05,0xf2,0xf8,0xf2,0xd4,0xee, + 0xa8,0xf0,0xef,0xeb,0xff,0xee,0x54,0xe9, + 0xfc,0xec,0x88,0xe6,0x9d,0xed,0x6b,0xe5, + 0xaa,0xf0,0xc3,0xe3,0x46,0xf8,0x0d,0xd9, + 0xe1,0x65,0x92,0x12,0xd1,0xe4,0x61,0xfe, + 0x55,0xf0,0x2e,0xfe,0x6f,0xf6,0x07,0x00, + 0xc5,0xfa,0x44,0x02,0x44,0xff,0x4b,0x04, + 0x58,0x01,0x1b,0x05,0x98,0x02,0x49,0x05, + 0x8a,0x03,0xef,0x05,0x52,0x03,0x19,0x04, + 0x4f,0x02,0x0a,0x03,0x80,0x01,0xfa,0x01, + 0xc9,0x00,0x1f,0x01,0x3f,0x00,0x71,0x00, + 0xc7,0xff,0x02,0x00,0xa3,0xff,0xd4,0xff, + 0xc0,0xff,0xe8,0xff,0xd0,0xff,0xea,0xff, + 0xe6,0xff,0xf6,0xff,0xf9,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xf8,0xff,0xf7,0xff,0xe4,0xff,0xee,0xff, + 0xcb,0xff,0xf2,0xff,0xb3,0xff,0xe2,0xff, + 0x98,0xff,0x1b,0x00,0xb6,0xff,0x99,0x00, + 0x24,0x00,0x51,0x01,0xa1,0x00,0x3b,0x02, + 0x48,0x01,0x5d,0x03,0xfe,0x01,0x80,0x04, + 0x01,0x03,0x5b,0x06,0xcb,0x02,0xcc,0x05, + 0xc7,0x01,0xbe,0x05,0x44,0x00,0x1b,0x05, + 0xcf,0xfd,0x17,0x03,0xf4,0xf8,0x82,0x01, + 0xd9,0xf3,0x94,0x00,0x46,0xec,0x46,0x03, + 0x43,0xdb,0x93,0x2f,0xf8,0x51,0x61,0xd2, + 0x4e,0xfc,0x4e,0xe0,0xf4,0xf2,0x2e,0xe3, + 0x33,0xef,0xfd,0xe4,0x4f,0xee,0x69,0xe8, + 0xf4,0xef,0x36,0xeb,0x79,0xf1,0x58,0xee, + 0xa5,0xf3,0xd2,0xf1,0x0b,0xf7,0xb8,0xf5, + 0x30,0xfa,0x48,0xf9,0x5e,0xfc,0xc0,0xfb, + 0x27,0xfe,0xb6,0xfd,0x7d,0xff,0x20,0xff, + 0x55,0x00,0xe5,0xff,0xa8,0x00,0x51,0x00, + 0xbc,0x00,0x5e,0x00,0x78,0x00,0x44,0x00, + 0x4c,0x00,0x27,0x00,0x1f,0x00,0x0b,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0xfd,0xff,0xfa,0xff, + 0xf9,0xff,0xf6,0xff,0xf4,0xff,0xf1,0xff, + 0xdd,0xff,0xd0,0xff,0xcb,0xff,0xc0,0xff, + 0xbe,0xff,0xc0,0xff,0xbd,0xff,0xb7,0xff, + 0xb8,0xff,0xb3,0xff,0xb3,0xff,0xb4,0xff, + 0xbc,0xff,0xe7,0xff,0x60,0x00,0x58,0x00, + 0x3e,0x00,0x67,0x00,0xbf,0x00,0xf7,0x00, + 0x77,0x01,0x9f,0x01,0xee,0x02,0x9b,0x04, + 0xf1,0x04,0x94,0x05,0xfa,0x05,0x81,0x06, + 0xe7,0x06,0x56,0x07,0xa6,0x07,0xee,0x47, + 0x2e,0x08,0x5b,0x08,0x69,0x08,0x5e,0x08, + 0x45,0x08,0x0c,0x08,0xd1,0x07,0x64,0x07, + 0x59,0x07,0x27,0x07,0x90,0x06,0x0b,0x06, + 0x7a,0x05,0xe4,0x04,0x5a,0x04,0xd9,0x02, + 0x06,0x02,0xfd,0x01,0xb3,0x01,0x5c,0x01, + 0x0c,0x01,0xca,0x00,0x8f,0x00,0x5f,0x00, + 0x38,0x00,0x18,0x00,0x1c,0x00,0x17,0x00, + 0x06,0x00,0x01,0x00,0xf9,0xff,0xee,0xff, + 0xf1,0xff,0xf5,0xff,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xf4,0xff,0xf7,0xff,0xe1,0xff,0xf3,0xff, + 0xcc,0xff,0xfa,0xff,0xe8,0xff,0x3a,0x00, + 0xcd,0xff,0x7b,0x00,0x16,0x00,0x19,0x01, + 0x99,0x00,0x06,0x02,0x60,0x01,0x4b,0x03, + 0x6a,0x02,0x5e,0x04,0xfd,0x02,0x2f,0x06, + 0x78,0x04,0x93,0x0a,0xe2,0x08,0xaf,0x0d, + 0xaa,0x0a,0x9b,0x10,0xcb,0x0b,0x16,0x12, + 0xbd,0x0b,0xcd,0x14,0x38,0x0b,0xea,0x17, + 0x62,0x08,0x77,0x1d,0x25,0xfd,0x91,0x41, + 0x9a,0x7c,0xbf,0xf5,0x8f,0x1d,0x07,0x04, + 0x26,0x15,0x43,0x06,0xb4,0x10,0xfa,0x05, + 0x58,0x0d,0x2a,0x04,0xba,0x06,0xff,0x00, + 0xde,0x04,0x4f,0x00,0x5c,0x03,0x5f,0x00, + 0x3d,0x03,0x32,0x00,0x54,0x02,0x7f,0xff, + 0xf8,0x00,0x55,0xff,0x99,0x00,0x56,0xff, + 0x55,0x00,0x64,0xff,0x24,0x00,0x7a,0xff, + 0x04,0x00,0x7c,0xff,0x06,0x00,0xd0,0xff, + 0x07,0x00,0xdd,0xff,0xfe,0xff,0xe9,0xff, + 0xfb,0xff,0xf5,0xff,0xfd,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0x0a,0x00, + 0x1d,0x00,0x22,0x00,0x47,0x00,0x39,0x00, + 0x71,0x00,0x3b,0x00,0x8e,0x00,0x43,0x00, + 0xa7,0x00,0xea,0xff,0x47,0x00,0x09,0xff, + 0x74,0xff,0xa5,0xfd,0x2e,0xfe,0xb7,0xfb, + 0x79,0xfc,0x35,0xf9,0xb0,0xf9,0xc9,0xf5, + 0x67,0xf7,0x93,0xf2,0x30,0xf4,0xa8,0xee, + 0x23,0xf2,0x97,0xeb,0xc5,0xf0,0x47,0xe8, + 0xea,0xee,0x5e,0xe5,0xce,0xef,0xfc,0xe2, + 0x41,0xf3,0xdb,0xdf,0x9d,0xfc,0x24,0xd2, + 0x5c,0x45,0x06,0x3d,0xc5,0xd7,0xb9,0x03, + 0x48,0xea,0xe9,0xff,0xee,0xf1,0x29,0x00, + 0xe0,0xf6,0x24,0x01,0x06,0xfb,0x73,0x03, + 0xfa,0xfd,0x02,0x04,0xa9,0xff,0x37,0x04, + 0x59,0x01,0xb8,0x04,0x99,0x01,0xf0,0x03, + 0xbf,0x00,0x59,0x02,0x4e,0x00,0x8c,0x01, + 0xf6,0xff,0xde,0x00,0xb4,0xff,0x5f,0x00, + 0x93,0xff,0x09,0x00,0x7c,0xff,0xff,0xff, + 0xb7,0xff,0xf1,0xff,0xce,0xff,0xf2,0xff, + 0xe7,0xff,0xfa,0xff,0xfa,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfc,0xff, + 0xf3,0xff,0xf2,0xff,0xdd,0xff,0xe7,0xff, + 0xc4,0xff,0xe3,0xff,0xb6,0xff,0xe2,0xff, + 0x76,0xff,0x01,0x00,0xa3,0xff,0x55,0x00, + 0xd9,0xff,0xd4,0x00,0x34,0x00,0x7f,0x01, + 0xa4,0x00,0x3e,0x02,0x53,0x01,0xe6,0x03, + 0x06,0x02,0x7b,0x04,0x9a,0x01,0x88,0x03, + 0x25,0x00,0x17,0x03,0x7d,0xfe,0x24,0x02, + 0x28,0xfb,0x80,0xff,0x94,0xf7,0xfd,0xfd, + 0x0f,0xf3,0xf8,0xfc,0x50,0xec,0x93,0xff, + 0x0a,0xdb,0x20,0x64,0x2d,0x13,0x84,0xdd, + 0x02,0xf6,0xf6,0xe3,0x17,0xf0,0xb3,0xe5, + 0x23,0xee,0x98,0xe7,0x1b,0xee,0x95,0xea, + 0x6e,0xf0,0x6d,0xed,0x36,0xf2,0x54,0xf0, + 0xb0,0xf4,0x4b,0xf4,0xb6,0xf7,0x23,0xf7, + 0x30,0xfa,0x74,0xfa,0xb6,0xfc,0x9c,0xfc, + 0x5c,0xfe,0x48,0xfe,0x8a,0xff,0x70,0xff, + 0x43,0x00,0x1e,0x00,0x8c,0x00,0x4f,0x00, + 0x6b,0x00,0x40,0x00,0x53,0x00,0x30,0x00, + 0x2d,0x00,0x16,0x00,0x0d,0x00,0x03,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xfe,0xff,0xfd,0xff,0xfb,0xff,0xfa,0xff, + 0xf9,0xff,0xfa,0xff,0xf8,0xff,0xfb,0xff, + 0xe9,0xff,0xdd,0xff,0xe9,0xff,0xe6,0xff, + 0xeb,0xff,0xed,0xff,0xf3,0xff,0xf9,0xff, + 0x03,0x00,0x12,0x00,0x1a,0x00,0x5e,0x00, + 0xb4,0x00,0xbf,0x00,0x08,0x01,0xea,0x00, + 0xec,0x00,0x33,0x01,0x7e,0x01,0xc7,0x01, + 0x55,0x02,0x42,0x04,0xdd,0x04,0x60,0x05, + 0xe9,0x05,0x64,0x06,0xd4,0x06,0x38,0x07, + 0x95,0x07,0xe2,0x07,0x23,0x48,0x5f,0x08, + 0x8b,0x08,0x9d,0x08,0xa4,0x08,0x83,0x08, + 0x59,0x08,0x0b,0x08,0xbe,0x07,0x50,0x07, + 0x5e,0x07,0xe0,0x06,0x5a,0x06,0xae,0x05, + 0x3d,0x05,0x07,0x04,0xab,0x02,0x6c,0x02, + 0xdd,0x01,0xb6,0x01,0x86,0x01,0x34,0x01, + 0xe8,0x00,0xad,0x00,0x75,0x00,0x4e,0x00, + 0x28,0x00,0x11,0x00,0xfb,0xff,0x09,0x00, + 0xfb,0xff,0xeb,0xff,0xee,0xff,0xf0,0xff, + 0xf5,0xff,0xf8,0xff,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xfd,0xff,0xf8,0xff,0xf9,0xff, + 0xf0,0xff,0xf9,0xff,0xe6,0xff,0xeb,0xff, + 0xe0,0xff,0x19,0x00,0x19,0x00,0x56,0x00, + 0x55,0x00,0xb3,0x00,0xb2,0x00,0x37,0x01, + 0x2e,0x01,0x98,0x01,0x89,0x01,0x63,0x02, + 0x44,0x02,0x57,0x03,0x0c,0x03,0x33,0x05, + 0x99,0x05,0xdd,0x06,0x8c,0x06,0xc2,0x07, + 0xb2,0x06,0xa9,0x08,0x31,0x07,0x92,0x09, + 0x28,0x07,0x71,0x0a,0x46,0x06,0x2c,0x0c, + 0xb8,0x01,0xb9,0x46,0xd8,0x10,0xc8,0x03, + 0x32,0x0a,0x42,0x05,0x4f,0x08,0x13,0x05, + 0xea,0x06,0x7a,0x04,0xb8,0x05,0xa8,0x03, + 0x19,0x03,0x99,0x01,0x4b,0x02,0x39,0x01, + 0x2a,0x02,0x48,0x01,0xaf,0x01,0xf9,0x00, + 0x41,0x01,0xb1,0x00,0xb2,0x00,0x25,0x00, + 0x62,0x00,0x0c,0x00,0x38,0x00,0xf9,0xff, + 0x19,0x00,0xec,0xff,0x1b,0x00,0x04,0x00, + 0x0b,0x00,0xf5,0xff,0xff,0xff,0xf6,0xff, + 0xfc,0xff,0xf9,0xff,0xfd,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00, + 0x09,0x00,0x16,0x00,0x1f,0x00,0x32,0x00, + 0x35,0x00,0x48,0x00,0x3c,0x00,0x51,0x00, + 0x1b,0x00,0x4a,0x00,0xeb,0xff,0xd0,0xff, + 0x24,0xff,0xec,0xfe,0xf0,0xfd,0xa0,0xfd, + 0x34,0xfc,0x44,0xfb,0x9b,0xf9,0x20,0xf9, + 0x32,0xf7,0xd4,0xf6,0xb1,0xf4,0xeb,0xf3, + 0x1d,0xf1,0x83,0xf1,0xcf,0xee,0x03,0xef, + 0x97,0xeb,0xa0,0xed,0x16,0xea,0x69,0xed, + 0x23,0xe9,0xa7,0xee,0x5c,0xe8,0x09,0xf3, + 0xed,0xe2,0x4b,0x6d,0x41,0xfe,0x71,0xeb, + 0x74,0xf7,0x8f,0xf1,0x52,0xf8,0x30,0xf5, + 0xfe,0xf9,0x22,0xf8,0xc4,0xfb,0xb3,0xfa, + 0x72,0xfe,0x67,0xfd,0x7a,0xff,0xbf,0xfe, + 0x0f,0x01,0x23,0x00,0x30,0x01,0x58,0x00, + 0x0e,0x01,0x67,0x00,0x72,0x00,0x9b,0xff, + 0x09,0x00,0x87,0xff,0xd4,0xff,0x7d,0xff, + 0xba,0xff,0x85,0xff,0xe8,0xff,0xcf,0xff, + 0xe5,0xff,0xcc,0xff,0xe6,0xff,0xe1,0xff, + 0xf1,0xff,0xf2,0xff,0xfb,0xff,0xfd,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff, + 0xf9,0xff,0xf5,0xff,0xeb,0xff,0xe7,0xff, + 0xd8,0xff,0xd8,0xff,0xcc,0xff,0xe2,0xff, + 0xc6,0xff,0xa7,0xff,0x82,0xff,0xaa,0xff, + 0x88,0xff,0xc5,0xff,0xa2,0xff,0xf1,0xff, + 0xdc,0xff,0xce,0x00,0x71,0x00,0xe6,0x00, + 0x68,0x00,0xdc,0x00,0x21,0x00,0xda,0xff, + 0x3c,0xfe,0xb2,0xfe,0xea,0xfc,0x68,0xfc, + 0xc9,0xf9,0x62,0xfa,0x57,0xf7,0x57,0xf8, + 0x7d,0xf4,0x74,0xf6,0xe5,0xf0,0x7d,0xf5, + 0xae,0xe9,0xab,0x6e,0xed,0xf5,0x87,0xe9, + 0xc6,0xee,0xf7,0xe9,0xe2,0xec,0x5f,0xea, + 0xa7,0xec,0x6e,0xeb,0x80,0xed,0x3c,0xed, + 0x2e,0xf0,0x47,0xf0,0x37,0xf2,0xed,0xf2, + 0x8c,0xf5,0x12,0xf6,0xdf,0xf7,0x88,0xf8, + 0x23,0xfa,0xcc,0xfa,0x91,0xfc,0x4e,0xfd, + 0x3d,0xfe,0xb0,0xfe,0x5d,0xff,0xa6,0xff, + 0x13,0x00,0x34,0x00,0x3e,0x00,0x3e,0x00, + 0x51,0x00,0x3f,0x00,0x40,0x00,0x2e,0x00, + 0x24,0x00,0x15,0x00,0x0b,0x00,0x03,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff, + 0xfd,0xff,0xfb,0xff,0xfb,0xff,0xfa,0xff, + 0xfc,0xff,0xfc,0xff,0x05,0x00,0x0f,0x00, + 0x15,0x00,0x02,0x00,0x09,0x00,0x13,0x00, + 0x22,0x00,0x30,0x00,0x45,0x00,0x54,0x00, + 0x83,0x00,0xe8,0x00,0x10,0x01,0x40,0x01, + 0x6e,0x01,0x9f,0x01,0xdd,0x01,0xc5,0x01, + 0xcf,0x01,0x30,0x02,0x6a,0x02,0x31,0x04, + 0xfe,0x04,0x58,0x05,0xe2,0x05,0x4d,0x06, + 0xca,0x06,0x2e,0x07,0x90,0x07,0xd5,0x07, + 0x1f,0x08,0x46,0x48,0x7f,0x08,0x94,0x08, + 0xa8,0x08,0x9d,0x08,0x8f,0x08,0x5f,0x08, + 0x29,0x08,0xca,0x07,0x6d,0x07,0xff,0x06, + 0x08,0x07,0x64,0x06,0xfa,0x05,0xf6,0x04, + 0x66,0x03,0x02,0x03,0x85,0x02,0x20,0x02, + 0xbc,0x01,0x5f,0x01,0x46,0x01,0x12,0x01, + 0xca,0x00,0x96,0x00,0x66,0x00,0x41,0x00, + 0x23,0x00,0x0c,0x00,0xe9,0xff,0xe0,0xff, + 0xe9,0xff,0xf3,0xff,0xf2,0xff,0xf6,0xff, + 0xf8,0xff,0xfc,0xff,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xfc,0xff,0xfc,0xff, + 0xf6,0xff,0xf1,0xff,0xef,0xff,0xf3,0xff, + 0xf4,0xff,0x03,0x00,0x08,0x00,0x2c,0x00, + 0x5f,0x00,0x91,0x00,0xb5,0x00,0xf4,0x00, + 0xe9,0x00,0x46,0x01,0x78,0x01,0xf3,0x01, + 0x2b,0x02,0xbe,0x02,0xf4,0x02,0x9e,0x03, + 0xc9,0x03,0xb1,0x05,0x3c,0x06,0x96,0x06, + 0x86,0x06,0x6a,0x07,0x34,0x07,0x24,0x08, + 0xa3,0x07,0xc3,0x08,0xc1,0x07,0x5e,0x09, + 0x28,0x07,0x44,0x0b,0x2d,0x48,0xa4,0x05, + 0x68,0x09,0xe8,0x06,0x2b,0x08,0x9f,0x06, + 0x43,0x07,0x0e,0x06,0x68,0x06,0x59,0x05, + 0x99,0x05,0x3f,0x04,0x01,0x03,0x9a,0x02, + 0xf5,0x02,0x72,0x02,0x5f,0x02,0xe5,0x01, + 0xce,0x01,0x6a,0x01,0x54,0x01,0x02,0x01, + 0xe9,0x00,0x70,0x00,0x5e,0x00,0x35,0x00, + 0x2a,0x00,0x2e,0x00,0x2e,0x00,0x13,0x00, + 0x10,0x00,0x01,0x00,0x00,0x00,0xf9,0xff, + 0xf9,0xff,0xf6,0xff,0xfa,0xff,0xfb,0xff, + 0xfe,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, + 0x07,0x00,0x0f,0x00,0x17,0x00,0x21,0x00, + 0x2c,0x00,0x2b,0x00,0x29,0x00,0x18,0x00, + 0x03,0x00,0xd4,0xff,0xb0,0xff,0xa6,0xff, + 0x4c,0xff,0xe1,0xfe,0x4c,0xfe,0x3e,0xfd, + 0x91,0xfc,0xb7,0xfb,0xe7,0xfa,0xec,0xf9, + 0x04,0xf9,0xf4,0xf7,0x04,0xf7,0xf1,0xf5, + 0x39,0xf4,0x00,0xf3,0x6c,0xf1,0x05,0xf0, + 0x8f,0xef,0xaa,0xee,0x83,0xee,0xd2,0xed, + 0x07,0xee,0x78,0xed,0x24,0xee,0x7c,0xed, + 0x9b,0xef,0x31,0x6f,0x1d,0xef,0x5e,0xf1, + 0x69,0xf1,0xc1,0xf2,0x49,0xf3,0x79,0xf4, + 0x2f,0xf5,0x3a,0xf6,0x03,0xf7,0xdf,0xf7, + 0xff,0xf8,0x91,0xfa,0x3a,0xfb,0xba,0xfc, + 0xf9,0xfc,0x89,0xfd,0xd0,0xfd,0x41,0xfe, + 0x78,0xfe,0xcc,0xfe,0xf5,0xfe,0x2e,0xff, + 0xd9,0xfe,0xf1,0xfe,0x15,0xff,0x3b,0xff, + 0x9f,0xff,0xc3,0xff,0xce,0xff,0xdf,0xff, + 0xe9,0xff,0xf3,0xff,0xfa,0xff,0xfb,0xff, + 0xfc,0xff,0x00,0x00,0x01,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xfa,0xff,0xf8,0xff,0xf6,0xff, + 0xef,0xff,0xe3,0xff,0xd8,0xff,0xc5,0xff, + 0xba,0xff,0x8f,0xff,0x2b,0xff,0x0a,0xff, + 0xe0,0xfe,0xca,0xfe,0x19,0xff,0xe2,0xfe, + 0xb3,0xfe,0x63,0xfe,0x23,0xfe,0xb8,0xfd, + 0x67,0xfd,0xe0,0xfc,0x93,0xfc,0x23,0xfb, + 0x5c,0xfa,0xb7,0xf8,0xbe,0xf7,0xde,0xf6, + 0x12,0xf6,0x0e,0xf5,0x4f,0xf4,0x2d,0xf3, + 0x95,0xf2,0x58,0xf1,0x28,0xf1,0x2a,0xef, + 0x19,0x6f,0x57,0xef,0x83,0xed,0x0b,0xee, + 0x7c,0xed,0xfc,0xed,0xda,0xed,0x84,0xee, + 0xb7,0xee,0x9b,0xef,0x18,0xf0,0x82,0xf1, + 0x15,0xf3,0x71,0xf4,0x20,0xf6,0x18,0xf7, + 0x18,0xf8,0x1e,0xf9,0x0f,0xfa,0x01,0xfb, + 0xd8,0xfb,0xa8,0xfc,0x5f,0xfd,0x6a,0xfe, + 0xf7,0xfe,0x60,0xff,0xb7,0xff,0xbf,0xff, + 0xe2,0xff,0x0d,0x00,0x21,0x00,0x30,0x00, + 0x31,0x00,0x2f,0x00,0x23,0x00,0x19,0x00, + 0x0f,0x00,0x08,0x00,0x02,0x00,0x00,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfe,0xff,0xfc,0xff,0xfa,0xff, + 0xf8,0xff,0xf9,0xff,0xfd,0xff,0x01,0x00, + 0x08,0x00,0x11,0x00,0x1d,0x00,0x2e,0x00, + 0x3c,0x00,0x2c,0x00,0x46,0x00,0x5e,0x00, + 0x88,0x00,0xea,0x00,0x1c,0x01,0x51,0x01, + 0x8a,0x01,0xc8,0x01,0x0c,0x02,0x55,0x02, + 0x9f,0x02,0xe8,0x02,0xde,0x02,0xe6,0x02, + 0x95,0x04,0x69,0x05,0xaf,0x05,0x27,0x06, + 0x79,0x06,0xe2,0x06,0x31,0x07,0x8d,0x07, + 0xd2,0x07,0x1e,0x08,0x42,0x08,0x61,0x48, + 0x75,0x08,0x85,0x08,0x75,0x08,0x65,0x08, + 0x36,0x08,0x08,0x08,0xbd,0x07,0x77,0x07, + 0x17,0x07,0xb5,0x06,0x43,0x06,0x54,0x06, + 0x6e,0x05,0xd2,0x03,0x71,0x03,0xfb,0x02, + 0x97,0x02,0x2d,0x02,0xd1,0x01,0x77,0x01, + 0x2b,0x01,0xe6,0x00,0xdc,0x00,0xb3,0x00, + 0x80,0x00,0x5c,0x00,0x1f,0x00,0x06,0x00, + 0xfa,0xff,0xf2,0xff,0xee,0xff,0xee,0xff, + 0xee,0xff,0xf6,0xff,0xfb,0xff,0xfc,0xff, + 0xfe,0xff,0xff,0xff,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xfe,0xff,0xfc,0xff, + 0xf8,0xff,0xf7,0xff,0xf4,0xff,0xf7,0xff, + 0xf7,0xff,0x00,0x00,0x05,0x00,0x17,0x00, + 0x23,0x00,0x41,0x00,0x55,0x00,0x82,0x00, + 0xa2,0x00,0xdf,0x00,0x0b,0x01,0x5a,0x01, + 0x90,0x01,0xf0,0x01,0x2c,0x02,0x9b,0x02, + 0xdb,0x02,0x57,0x03,0x97,0x03,0x1f,0x04, + 0x32,0x05,0x02,0x06,0x18,0x06,0xc6,0x06, + 0xc8,0x06,0x7b,0x07,0x53,0x07,0x1a,0x08, + 0xab,0x07,0xae,0x08,0x9b,0x07,0xdb,0x09, + 0x58,0x48,0x04,0x07,0xed,0x08,0xa8,0x07, + 0x37,0x08,0x68,0x07,0x93,0x07,0xe8,0x06, + 0xdb,0x06,0x42,0x06,0x0d,0x06,0x8c,0x05, + 0xfe,0x04,0xa9,0x03,0x82,0x03,0xf6,0x02, + 0xbe,0x02,0x47,0x02,0x0d,0x02,0xa8,0x01, + 0x73,0x01,0x20,0x01,0xf3,0x00,0xb2,0x00, + 0x8d,0x00,0x5e,0x00,0x4a,0x00,0x2a,0x00, + 0x1d,0x00,0x0a,0x00,0x03,0x00,0xfa,0xff, + 0xf8,0xff,0xf6,0xff,0xf7,0xff,0xf9,0xff, + 0xfb,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x03,0x00,0x08,0x00,0x10,0x00,0x13,0x00, + 0x16,0x00,0x15,0x00,0x10,0x00,0x04,0x00, + 0xf3,0xff,0xd7,0xff,0xb5,0xff,0x86,0xff, + 0x4f,0xff,0x06,0xff,0xb3,0xfe,0x51,0xfe, + 0xdd,0xfd,0x5e,0xfd,0xd0,0xfc,0x38,0xfc, + 0x92,0xfb,0xe8,0xfa,0x2d,0xfa,0x77,0xf9, + 0xac,0xf8,0xf4,0xf7,0x76,0xf5,0x32,0xf4, + 0x95,0xf3,0xbc,0xf2,0x21,0xf2,0x6b,0xf1, + 0xe9,0xf0,0x58,0xf0,0xfb,0xef,0x94,0xef, + 0x62,0xef,0x28,0xef,0x1c,0x6f,0x3b,0xef, + 0x85,0xef,0xc6,0xef,0x3e,0xf0,0xa7,0xf0, + 0x48,0xf1,0xd2,0xf1,0x97,0xf2,0x35,0xf3, + 0x1e,0xf4,0xb3,0xf4,0x26,0xf6,0x7f,0xf8, + 0x20,0xf9,0xf2,0xf9,0x9e,0xfa,0x58,0xfb, + 0xfa,0xfb,0x9a,0xfc,0x29,0xfd,0xaf,0xfd, + 0x26,0xfe,0x8f,0xfe,0xee,0xfe,0x3b,0xff, + 0x73,0xff,0xa5,0xff,0xcb,0xff,0xe8,0xff, + 0xfd,0xff,0x0a,0x00,0x11,0x00,0x13,0x00, + 0x12,0x00,0x0e,0x00,0x0a,0x00,0x04,0x00, + 0x01,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0x03,0x00,0x08,0x00, + 0x10,0x00,0x13,0x00,0x16,0x00,0x15,0x00, + 0x10,0x00,0x04,0x00,0xf3,0xff,0xd7,0xff, + 0xb5,0xff,0x86,0xff,0x4f,0xff,0x06,0xff, + 0xb3,0xfe,0x51,0xfe,0xdd,0xfd,0x5e,0xfd, + 0xd0,0xfc,0x38,0xfc,0x92,0xfb,0xe8,0xfa, + 0x2d,0xfa,0x77,0xf9,0xac,0xf8,0xf4,0xf7, + 0x76,0xf5,0x32,0xf4,0x95,0xf3,0xbc,0xf2, + 0x21,0xf2,0x6b,0xf1,0xe9,0xf0,0x58,0xf0, + 0xfb,0xef,0x94,0xef,0x62,0xef,0x28,0xef, + 0x1c,0x6f,0x3b,0xef,0x85,0xef,0xc6,0xef, + 0x3e,0xf0,0xa7,0xf0,0x48,0xf1,0xd2,0xf1, + 0x97,0xf2,0x35,0xf3,0x1e,0xf4,0xb3,0xf4, + 0x26,0xf6,0x7f,0xf8,0x20,0xf9,0xf2,0xf9, + 0x9e,0xfa,0x58,0xfb,0xfa,0xfb,0x9a,0xfc, + 0x29,0xfd,0xaf,0xfd,0x26,0xfe,0x8f,0xfe, + 0xee,0xfe,0x3b,0xff,0x73,0xff,0xa5,0xff, + 0xcb,0xff,0xe8,0xff,0xfd,0xff,0x0a,0x00, + 0x11,0x00,0x13,0x00,0x12,0x00,0x0e,0x00, + 0x0a,0x00,0x04,0x00,0x01,0x00,0x00,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xfe,0xff,0xfc,0xff,0xf8,0xff,0xf7,0xff, + 0xf4,0xff,0xf7,0xff,0xf7,0xff,0x00,0x00, + 0x05,0x00,0x17,0x00,0x23,0x00,0x41,0x00, + 0x55,0x00,0x82,0x00,0xa2,0x00,0xdf,0x00, + 0x0b,0x01,0x5a,0x01,0x90,0x01,0xf0,0x01, + 0x2c,0x02,0x9b,0x02,0xdb,0x02,0x57,0x03, + 0x97,0x03,0x1f,0x04,0x32,0x05,0x02,0x06, + 0x18,0x06,0xc6,0x06,0xc8,0x06,0x7b,0x07, + 0x53,0x07,0x1a,0x08,0xab,0x07,0xae,0x08, + 0x9b,0x07,0xdb,0x09,0x58,0x48,0x04,0x07, + 0xed,0x08,0xa8,0x07,0x37,0x08,0x68,0x07, + 0x93,0x07,0xe8,0x06,0xdb,0x06,0x42,0x06, + 0x0d,0x06,0x8c,0x05,0xfe,0x04,0xa9,0x03, + 0x82,0x03,0xf6,0x02,0xbe,0x02,0x47,0x02, + 0x0d,0x02,0xa8,0x01,0x73,0x01,0x20,0x01, + 0xf3,0x00,0xb2,0x00,0x8d,0x00,0x5e,0x00, + 0x4a,0x00,0x2a,0x00,0x1d,0x00,0x0a,0x00, + 0x03,0x00,0xfa,0xff,0xf8,0xff,0xf6,0xff, + 0xf7,0xff,0xf9,0xff,0xfb,0xff,0xfe,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0xff, + 0xfc,0xff,0xfa,0xff,0xf8,0xff,0xf9,0xff, + 0xfd,0xff,0x01,0x00,0x08,0x00,0x11,0x00, + 0x1d,0x00,0x2e,0x00,0x3c,0x00,0x2c,0x00, + 0x46,0x00,0x5e,0x00,0x88,0x00,0xea,0x00, + 0x1c,0x01,0x51,0x01,0x8a,0x01,0xc8,0x01, + 0x0c,0x02,0x55,0x02,0x9f,0x02,0xe8,0x02, + 0xde,0x02,0xe6,0x02,0x95,0x04,0x69,0x05, + 0xaf,0x05,0x27,0x06,0x79,0x06,0xe2,0x06, + 0x31,0x07,0x8d,0x07,0xd2,0x07,0x1e,0x08, + 0x42,0x08,0x61,0x48,0x75,0x08,0x85,0x08, + 0x75,0x08,0x65,0x08,0x36,0x08,0x08,0x08, + 0xbd,0x07,0x77,0x07,0x17,0x07,0xb5,0x06, + 0x43,0x06,0x54,0x06,0x6e,0x05,0xd2,0x03, + 0x71,0x03,0xfb,0x02,0x97,0x02,0x2d,0x02, + 0xd1,0x01,0x77,0x01,0x2b,0x01,0xe6,0x00, + 0xdc,0x00,0xb3,0x00,0x80,0x00,0x5c,0x00, + 0x1f,0x00,0x06,0x00,0xfa,0xff,0xf2,0xff, + 0xee,0xff,0xee,0xff,0xee,0xff,0xf6,0xff, + 0xfb,0xff,0xfc,0xff,0xfe,0xff,0xff,0xff, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xfa,0xff, + 0xf8,0xff,0xf6,0xff,0xef,0xff,0xe3,0xff, + 0xd8,0xff,0xc5,0xff,0xba,0xff,0x8f,0xff, + 0x2b,0xff,0x0a,0xff,0xe0,0xfe,0xca,0xfe, + 0x19,0xff,0xe2,0xfe,0xb3,0xfe,0x63,0xfe, + 0x23,0xfe,0xb8,0xfd,0x67,0xfd,0xe0,0xfc, + 0x93,0xfc,0x23,0xfb,0x5c,0xfa,0xb7,0xf8, + 0xbe,0xf7,0xde,0xf6,0x12,0xf6,0x0e,0xf5, + 0x4f,0xf4,0x2d,0xf3,0x95,0xf2,0x58,0xf1, + 0x28,0xf1,0x2a,0xef,0x19,0x6f,0x57,0xef, + 0x83,0xed,0x0b,0xee,0x7c,0xed,0xfc,0xed, + 0xda,0xed,0x84,0xee,0xb7,0xee,0x9b,0xef, + 0x18,0xf0,0x82,0xf1,0x15,0xf3,0x71,0xf4, + 0x20,0xf6,0x18,0xf7,0x18,0xf8,0x1e,0xf9, + 0x0f,0xfa,0x01,0xfb,0xd8,0xfb,0xa8,0xfc, + 0x5f,0xfd,0x6a,0xfe,0xf7,0xfe,0x60,0xff, + 0xb7,0xff,0xbf,0xff,0xe2,0xff,0x0d,0x00, + 0x21,0x00,0x30,0x00,0x31,0x00,0x2f,0x00, + 0x23,0x00,0x19,0x00,0x0f,0x00,0x08,0x00, + 0x02,0x00,0x00,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x02,0x00,0x07,0x00,0x0f,0x00, + 0x17,0x00,0x21,0x00,0x2c,0x00,0x2b,0x00, + 0x29,0x00,0x18,0x00,0x03,0x00,0xd4,0xff, + 0xb0,0xff,0xa6,0xff,0x4c,0xff,0xe1,0xfe, + 0x4c,0xfe,0x3e,0xfd,0x91,0xfc,0xb7,0xfb, + 0xe7,0xfa,0xec,0xf9,0x04,0xf9,0xf4,0xf7, + 0x04,0xf7,0xf1,0xf5,0x39,0xf4,0x00,0xf3, + 0x6c,0xf1,0x05,0xf0,0x8f,0xef,0xaa,0xee, + 0x83,0xee,0xd2,0xed,0x07,0xee,0x78,0xed, + 0x24,0xee,0x7c,0xed,0x9b,0xef,0x31,0x6f, + 0x1d,0xef,0x5e,0xf1,0x69,0xf1,0xc1,0xf2, + 0x49,0xf3,0x79,0xf4,0x2f,0xf5,0x3a,0xf6, + 0x03,0xf7,0xdf,0xf7,0xff,0xf8,0x91,0xfa, + 0x3a,0xfb,0xba,0xfc,0xf9,0xfc,0x89,0xfd, + 0xd0,0xfd,0x41,0xfe,0x78,0xfe,0xcc,0xfe, + 0xf5,0xfe,0x2e,0xff,0xd9,0xfe,0xf1,0xfe, + 0x15,0xff,0x3b,0xff,0x9f,0xff,0xc3,0xff, + 0xce,0xff,0xdf,0xff,0xe9,0xff,0xf3,0xff, + 0xfa,0xff,0xfb,0xff,0xfc,0xff,0x00,0x00, + 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xfc,0xff,0xfc,0xff,0xf6,0xff,0xf1,0xff, + 0xef,0xff,0xf3,0xff,0xf4,0xff,0x03,0x00, + 0x08,0x00,0x2c,0x00,0x5f,0x00,0x91,0x00, + 0xb5,0x00,0xf4,0x00,0xe9,0x00,0x46,0x01, + 0x78,0x01,0xf3,0x01,0x2b,0x02,0xbe,0x02, + 0xf4,0x02,0x9e,0x03,0xc9,0x03,0xb1,0x05, + 0x3c,0x06,0x96,0x06,0x86,0x06,0x6a,0x07, + 0x34,0x07,0x24,0x08,0xa3,0x07,0xc3,0x08, + 0xc1,0x07,0x5e,0x09,0x28,0x07,0x44,0x0b, + 0x2d,0x48,0xa4,0x05,0x68,0x09,0xe8,0x06, + 0x2b,0x08,0x9f,0x06,0x43,0x07,0x0e,0x06, + 0x68,0x06,0x59,0x05,0x99,0x05,0x3f,0x04, + 0x01,0x03,0x9a,0x02,0xf5,0x02,0x72,0x02, + 0x5f,0x02,0xe5,0x01,0xce,0x01,0x6a,0x01, + 0x54,0x01,0x02,0x01,0xe9,0x00,0x70,0x00, + 0x5e,0x00,0x35,0x00,0x2a,0x00,0x2e,0x00, + 0x2e,0x00,0x13,0x00,0x10,0x00,0x01,0x00, + 0x00,0x00,0xf9,0xff,0xf9,0xff,0xf6,0xff, + 0xfa,0xff,0xfb,0xff,0xfe,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfe,0xff,0xfd,0xff,0xfb,0xff, + 0xfb,0xff,0xfa,0xff,0xfc,0xff,0xfc,0xff, + 0x05,0x00,0x0f,0x00,0x15,0x00,0x02,0x00, + 0x09,0x00,0x13,0x00,0x22,0x00,0x30,0x00, + 0x45,0x00,0x54,0x00,0x83,0x00,0xe8,0x00, + 0x10,0x01,0x40,0x01,0x6e,0x01,0x9f,0x01, + 0xdd,0x01,0xc5,0x01,0xcf,0x01,0x30,0x02, + 0x6a,0x02,0x31,0x04,0xfe,0x04,0x58,0x05, + 0xe2,0x05,0x4d,0x06,0xca,0x06,0x2e,0x07, + 0x90,0x07,0xd5,0x07,0x1f,0x08,0x46,0x48, + 0x7f,0x08,0x94,0x08,0xa8,0x08,0x9d,0x08, + 0x8f,0x08,0x5f,0x08,0x29,0x08,0xca,0x07, + 0x6d,0x07,0xff,0x06,0x08,0x07,0x64,0x06, + 0xfa,0x05,0xf6,0x04,0x66,0x03,0x02,0x03, + 0x85,0x02,0x20,0x02,0xbc,0x01,0x5f,0x01, + 0x46,0x01,0x12,0x01,0xca,0x00,0x96,0x00, + 0x66,0x00,0x41,0x00,0x23,0x00,0x0c,0x00, + 0xe9,0xff,0xe0,0xff,0xe9,0xff,0xf3,0xff, + 0xf2,0xff,0xf6,0xff,0xf8,0xff,0xfc,0xff, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfe,0xff,0xf9,0xff,0xf5,0xff, + 0xeb,0xff,0xe7,0xff,0xd8,0xff,0xd8,0xff, + 0xcc,0xff,0xe2,0xff,0xc6,0xff,0xa7,0xff, + 0x82,0xff,0xaa,0xff,0x88,0xff,0xc5,0xff, + 0xa2,0xff,0xf1,0xff,0xdc,0xff,0xce,0x00, + 0x71,0x00,0xe6,0x00,0x68,0x00,0xdc,0x00, + 0x21,0x00,0xda,0xff,0x3c,0xfe,0xb2,0xfe, + 0xea,0xfc,0x68,0xfc,0xc9,0xf9,0x62,0xfa, + 0x57,0xf7,0x57,0xf8,0x7d,0xf4,0x74,0xf6, + 0xe5,0xf0,0x7d,0xf5,0xae,0xe9,0xab,0x6e, + 0xed,0xf5,0x87,0xe9,0xc6,0xee,0xf7,0xe9, + 0xe2,0xec,0x5f,0xea,0xa7,0xec,0x6e,0xeb, + 0x80,0xed,0x3c,0xed,0x2e,0xf0,0x47,0xf0, + 0x37,0xf2,0xed,0xf2,0x8c,0xf5,0x12,0xf6, + 0xdf,0xf7,0x88,0xf8,0x23,0xfa,0xcc,0xfa, + 0x91,0xfc,0x4e,0xfd,0x3d,0xfe,0xb0,0xfe, + 0x5d,0xff,0xa6,0xff,0x13,0x00,0x34,0x00, + 0x3e,0x00,0x3e,0x00,0x51,0x00,0x3f,0x00, + 0x40,0x00,0x2e,0x00,0x24,0x00,0x15,0x00, + 0x0b,0x00,0x03,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x00,0x09,0x00,0x16,0x00, + 0x1f,0x00,0x32,0x00,0x35,0x00,0x48,0x00, + 0x3c,0x00,0x51,0x00,0x1b,0x00,0x4a,0x00, + 0xeb,0xff,0xd0,0xff,0x24,0xff,0xec,0xfe, + 0xf0,0xfd,0xa0,0xfd,0x34,0xfc,0x44,0xfb, + 0x9b,0xf9,0x20,0xf9,0x32,0xf7,0xd4,0xf6, + 0xb1,0xf4,0xeb,0xf3,0x1d,0xf1,0x83,0xf1, + 0xcf,0xee,0x03,0xef,0x97,0xeb,0xa0,0xed, + 0x16,0xea,0x69,0xed,0x23,0xe9,0xa7,0xee, + 0x5c,0xe8,0x09,0xf3,0xed,0xe2,0x4b,0x6d, + 0x41,0xfe,0x71,0xeb,0x74,0xf7,0x8f,0xf1, + 0x52,0xf8,0x30,0xf5,0xfe,0xf9,0x22,0xf8, + 0xc4,0xfb,0xb3,0xfa,0x72,0xfe,0x67,0xfd, + 0x7a,0xff,0xbf,0xfe,0x0f,0x01,0x23,0x00, + 0x30,0x01,0x58,0x00,0x0e,0x01,0x67,0x00, + 0x72,0x00,0x9b,0xff,0x09,0x00,0x87,0xff, + 0xd4,0xff,0x7d,0xff,0xba,0xff,0x85,0xff, + 0xe8,0xff,0xcf,0xff,0xe5,0xff,0xcc,0xff, + 0xe6,0xff,0xe1,0xff,0xf1,0xff,0xf2,0xff, + 0xfb,0xff,0xfd,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xfd,0xff, + 0xf8,0xff,0xf9,0xff,0xf0,0xff,0xf9,0xff, + 0xe6,0xff,0xeb,0xff,0xe0,0xff,0x19,0x00, + 0x19,0x00,0x56,0x00,0x55,0x00,0xb3,0x00, + 0xb2,0x00,0x37,0x01,0x2e,0x01,0x98,0x01, + 0x89,0x01,0x63,0x02,0x44,0x02,0x57,0x03, + 0x0c,0x03,0x33,0x05,0x99,0x05,0xdd,0x06, + 0x8c,0x06,0xc2,0x07,0xb2,0x06,0xa9,0x08, + 0x31,0x07,0x92,0x09,0x28,0x07,0x71,0x0a, + 0x46,0x06,0x2c,0x0c,0xb8,0x01,0xb9,0x46, + 0xd8,0x10,0xc8,0x03,0x32,0x0a,0x42,0x05, + 0x4f,0x08,0x13,0x05,0xea,0x06,0x7a,0x04, + 0xb8,0x05,0xa8,0x03,0x19,0x03,0x99,0x01, + 0x4b,0x02,0x39,0x01,0x2a,0x02,0x48,0x01, + 0xaf,0x01,0xf9,0x00,0x41,0x01,0xb1,0x00, + 0xb2,0x00,0x25,0x00,0x62,0x00,0x0c,0x00, + 0x38,0x00,0xf9,0xff,0x19,0x00,0xec,0xff, + 0x1b,0x00,0x04,0x00,0x0b,0x00,0xf5,0xff, + 0xff,0xff,0xf6,0xff,0xfc,0xff,0xf9,0xff, + 0xfd,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xfe,0xff,0xfd,0xff, + 0xfb,0xff,0xfa,0xff,0xf9,0xff,0xfa,0xff, + 0xf8,0xff,0xfb,0xff,0xe9,0xff,0xdd,0xff, + 0xe9,0xff,0xe6,0xff,0xeb,0xff,0xed,0xff, + 0xf3,0xff,0xf9,0xff,0x03,0x00,0x12,0x00, + 0x1a,0x00,0x5e,0x00,0xb4,0x00,0xbf,0x00, + 0x08,0x01,0xea,0x00,0xec,0x00,0x33,0x01, + 0x7e,0x01,0xc7,0x01,0x55,0x02,0x42,0x04, + 0xdd,0x04,0x60,0x05,0xe9,0x05,0x64,0x06, + 0xd4,0x06,0x38,0x07,0x95,0x07,0xe2,0x07, + 0x23,0x48,0x5f,0x08,0x8b,0x08,0x9d,0x08, + 0xa4,0x08,0x83,0x08,0x59,0x08,0x0b,0x08, + 0xbe,0x07,0x50,0x07,0x5e,0x07,0xe0,0x06, + 0x5a,0x06,0xae,0x05,0x3d,0x05,0x07,0x04, + 0xab,0x02,0x6c,0x02,0xdd,0x01,0xb6,0x01, + 0x86,0x01,0x34,0x01,0xe8,0x00,0xad,0x00, + 0x75,0x00,0x4e,0x00,0x28,0x00,0x11,0x00, + 0xfb,0xff,0x09,0x00,0xfb,0xff,0xeb,0xff, + 0xee,0xff,0xf0,0xff,0xf5,0xff,0xf8,0xff, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xfc,0xff,0xf3,0xff,0xf2,0xff, + 0xdd,0xff,0xe7,0xff,0xc4,0xff,0xe3,0xff, + 0xb6,0xff,0xe2,0xff,0x76,0xff,0x01,0x00, + 0xa3,0xff,0x55,0x00,0xd9,0xff,0xd4,0x00, + 0x34,0x00,0x7f,0x01,0xa4,0x00,0x3e,0x02, + 0x53,0x01,0xe6,0x03,0x06,0x02,0x7b,0x04, + 0x9a,0x01,0x88,0x03,0x25,0x00,0x17,0x03, + 0x7d,0xfe,0x24,0x02,0x28,0xfb,0x80,0xff, + 0x94,0xf7,0xfd,0xfd,0x0f,0xf3,0xf8,0xfc, + 0x50,0xec,0x93,0xff,0x0a,0xdb,0x20,0x64, + 0x2d,0x13,0x84,0xdd,0x02,0xf6,0xf6,0xe3, + 0x17,0xf0,0xb3,0xe5,0x23,0xee,0x98,0xe7, + 0x1b,0xee,0x95,0xea,0x6e,0xf0,0x6d,0xed, + 0x36,0xf2,0x54,0xf0,0xb0,0xf4,0x4b,0xf4, + 0xb6,0xf7,0x23,0xf7,0x30,0xfa,0x74,0xfa, + 0xb6,0xfc,0x9c,0xfc,0x5c,0xfe,0x48,0xfe, + 0x8a,0xff,0x70,0xff,0x43,0x00,0x1e,0x00, + 0x8c,0x00,0x4f,0x00,0x6b,0x00,0x40,0x00, + 0x53,0x00,0x30,0x00,0x2d,0x00,0x16,0x00, + 0x0d,0x00,0x03,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0x0a,0x00,0x1d,0x00,0x22,0x00, + 0x47,0x00,0x39,0x00,0x71,0x00,0x3b,0x00, + 0x8e,0x00,0x43,0x00,0xa7,0x00,0xea,0xff, + 0x47,0x00,0x09,0xff,0x74,0xff,0xa5,0xfd, + 0x2e,0xfe,0xb7,0xfb,0x79,0xfc,0x35,0xf9, + 0xb0,0xf9,0xc9,0xf5,0x67,0xf7,0x93,0xf2, + 0x30,0xf4,0xa8,0xee,0x23,0xf2,0x97,0xeb, + 0xc5,0xf0,0x47,0xe8,0xea,0xee,0x5e,0xe5, + 0xce,0xef,0xfc,0xe2,0x41,0xf3,0xdb,0xdf, + 0x9d,0xfc,0x24,0xd2,0x5c,0x45,0x06,0x3d, + 0xc5,0xd7,0xb9,0x03,0x48,0xea,0xe9,0xff, + 0xee,0xf1,0x29,0x00,0xe0,0xf6,0x24,0x01, + 0x06,0xfb,0x73,0x03,0xfa,0xfd,0x02,0x04, + 0xa9,0xff,0x37,0x04,0x59,0x01,0xb8,0x04, + 0x99,0x01,0xf0,0x03,0xbf,0x00,0x59,0x02, + 0x4e,0x00,0x8c,0x01,0xf6,0xff,0xde,0x00, + 0xb4,0xff,0x5f,0x00,0x93,0xff,0x09,0x00, + 0x7c,0xff,0xff,0xff,0xb7,0xff,0xf1,0xff, + 0xce,0xff,0xf2,0xff,0xe7,0xff,0xfa,0xff, + 0xfa,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf4,0xff,0xf7,0xff, + 0xe1,0xff,0xf3,0xff,0xcc,0xff,0xfa,0xff, + 0xe8,0xff,0x3a,0x00,0xcd,0xff,0x7b,0x00, + 0x16,0x00,0x19,0x01,0x99,0x00,0x06,0x02, + 0x60,0x01,0x4b,0x03,0x6a,0x02,0x5e,0x04, + 0xfd,0x02,0x2f,0x06,0x78,0x04,0x93,0x0a, + 0xe2,0x08,0xaf,0x0d,0xaa,0x0a,0x9b,0x10, + 0xcb,0x0b,0x16,0x12,0xbd,0x0b,0xcd,0x14, + 0x38,0x0b,0xea,0x17,0x62,0x08,0x77,0x1d, + 0x25,0xfd,0x91,0x41,0x9a,0x7c,0xbf,0xf5, + 0x8f,0x1d,0x07,0x04,0x26,0x15,0x43,0x06, + 0xb4,0x10,0xfa,0x05,0x58,0x0d,0x2a,0x04, + 0xba,0x06,0xff,0x00,0xde,0x04,0x4f,0x00, + 0x5c,0x03,0x5f,0x00,0x3d,0x03,0x32,0x00, + 0x54,0x02,0x7f,0xff,0xf8,0x00,0x55,0xff, + 0x99,0x00,0x56,0xff,0x55,0x00,0x64,0xff, + 0x24,0x00,0x7a,0xff,0x04,0x00,0x7c,0xff, + 0x06,0x00,0xd0,0xff,0x07,0x00,0xdd,0xff, + 0xfe,0xff,0xe9,0xff,0xfb,0xff,0xf5,0xff, + 0xfd,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff, + 0xfd,0xff,0xfa,0xff,0xf9,0xff,0xf6,0xff, + 0xf4,0xff,0xf1,0xff,0xdd,0xff,0xd0,0xff, + 0xcb,0xff,0xc0,0xff,0xbe,0xff,0xc0,0xff, + 0xbd,0xff,0xb7,0xff,0xb8,0xff,0xb3,0xff, + 0xb3,0xff,0xb4,0xff,0xbc,0xff,0xe7,0xff, + 0x60,0x00,0x58,0x00,0x3e,0x00,0x67,0x00, + 0xbf,0x00,0xf7,0x00,0x77,0x01,0x9f,0x01, + 0xee,0x02,0x9b,0x04,0xf1,0x04,0x94,0x05, + 0xfa,0x05,0x81,0x06,0xe7,0x06,0x56,0x07, + 0xa6,0x07,0xee,0x47,0x2e,0x08,0x5b,0x08, + 0x69,0x08,0x5e,0x08,0x45,0x08,0x0c,0x08, + 0xd1,0x07,0x64,0x07,0x59,0x07,0x27,0x07, + 0x90,0x06,0x0b,0x06,0x7a,0x05,0xe4,0x04, + 0x5a,0x04,0xd9,0x02,0x06,0x02,0xfd,0x01, + 0xb3,0x01,0x5c,0x01,0x0c,0x01,0xca,0x00, + 0x8f,0x00,0x5f,0x00,0x38,0x00,0x18,0x00, + 0x1c,0x00,0x17,0x00,0x06,0x00,0x01,0x00, + 0xf9,0xff,0xee,0xff,0xf1,0xff,0xf5,0xff, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xf8,0xff,0xf7,0xff, + 0xe4,0xff,0xee,0xff,0xcb,0xff,0xf2,0xff, + 0xb3,0xff,0xe2,0xff,0x98,0xff,0x1b,0x00, + 0xb6,0xff,0x99,0x00,0x24,0x00,0x51,0x01, + 0xa1,0x00,0x3b,0x02,0x48,0x01,0x5d,0x03, + 0xfe,0x01,0x80,0x04,0x01,0x03,0x5b,0x06, + 0xcb,0x02,0xcc,0x05,0xc7,0x01,0xbe,0x05, + 0x44,0x00,0x1b,0x05,0xcf,0xfd,0x17,0x03, + 0xf4,0xf8,0x82,0x01,0xd9,0xf3,0x94,0x00, + 0x46,0xec,0x46,0x03,0x43,0xdb,0x93,0x2f, + 0xf8,0x51,0x61,0xd2,0x4e,0xfc,0x4e,0xe0, + 0xf4,0xf2,0x2e,0xe3,0x33,0xef,0xfd,0xe4, + 0x4f,0xee,0x69,0xe8,0xf4,0xef,0x36,0xeb, + 0x79,0xf1,0x58,0xee,0xa5,0xf3,0xd2,0xf1, + 0x0b,0xf7,0xb8,0xf5,0x30,0xfa,0x48,0xf9, + 0x5e,0xfc,0xc0,0xfb,0x27,0xfe,0xb6,0xfd, + 0x7d,0xff,0x20,0xff,0x55,0x00,0xe5,0xff, + 0xa8,0x00,0x51,0x00,0xbc,0x00,0x5e,0x00, + 0x78,0x00,0x44,0x00,0x4c,0x00,0x27,0x00, + 0x1f,0x00,0x0b,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0x0c,0x00,0x1d,0x00,0x28,0x00, + 0x46,0x00,0x46,0x00,0x6d,0x00,0x67,0x00, + 0xa5,0x00,0x56,0x00,0x84,0x00,0xee,0xff, + 0x24,0x00,0x28,0xff,0x36,0xff,0xc5,0xfd, + 0xca,0xfd,0xdb,0xfb,0xe7,0xfb,0x77,0xf9, + 0x8b,0xf9,0xe6,0xf5,0x5c,0xf6,0x05,0xf2, + 0xf8,0xf2,0xd4,0xee,0xa8,0xf0,0xef,0xeb, + 0xff,0xee,0x54,0xe9,0xfc,0xec,0x88,0xe6, + 0x9d,0xed,0x6b,0xe5,0xaa,0xf0,0xc3,0xe3, + 0x46,0xf8,0x0d,0xd9,0xe1,0x65,0x92,0x12, + 0xd1,0xe4,0x61,0xfe,0x55,0xf0,0x2e,0xfe, + 0x6f,0xf6,0x07,0x00,0xc5,0xfa,0x44,0x02, + 0x44,0xff,0x4b,0x04,0x58,0x01,0x1b,0x05, + 0x98,0x02,0x49,0x05,0x8a,0x03,0xef,0x05, + 0x52,0x03,0x19,0x04,0x4f,0x02,0x0a,0x03, + 0x80,0x01,0xfa,0x01,0xc9,0x00,0x1f,0x01, + 0x3f,0x00,0x71,0x00,0xc7,0xff,0x02,0x00, + 0xa3,0xff,0xd4,0xff,0xc0,0xff,0xe8,0xff, + 0xd0,0xff,0xea,0xff,0xe6,0xff,0xf6,0xff, + 0xf9,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfb,0xff,0xf2,0xff, + 0xf6,0xff,0xea,0xff,0x05,0x00,0xf7,0xff, + 0x17,0x00,0x09,0x00,0x31,0x00,0x02,0x00, + 0x60,0x00,0x42,0x00,0xc4,0x00,0xa3,0x00, + 0x52,0x01,0x28,0x01,0x0d,0x02,0xad,0x01, + 0x71,0x02,0xb0,0x02,0xfb,0x04,0x62,0x04, + 0x34,0x06,0x62,0x05,0x76,0x07,0x45,0x06, + 0x69,0x08,0x2e,0x06,0x54,0x09,0x4d,0x06, + 0x73,0x0a,0x95,0x05,0x35,0x0c,0x5d,0x02, + 0x6c,0x15,0x80,0x44,0x5a,0xfe,0x3e,0x0c, + 0x70,0x03,0xf8,0x08,0xde,0x03,0x26,0x07, + 0x76,0x03,0xa8,0x05,0x7f,0x01,0x81,0x02, + 0x8e,0x00,0xa0,0x01,0x0a,0x00,0xea,0x00, + 0xb6,0xff,0xcf,0x00,0xe8,0xff,0x2c,0x00, + 0x68,0xff,0xf5,0xff,0x72,0xff,0xe5,0xff, + 0x86,0xff,0xdd,0xff,0x99,0xff,0xda,0xff, + 0xa1,0xff,0xd3,0xff,0xb9,0xff,0xdc,0xff, + 0xd4,0xff,0xf9,0xff,0xed,0xff,0xfb,0xff, + 0xf5,0xff,0xfc,0xff,0xfb,0xff,0xff,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xfc,0xff,0xfa,0xff,0xf7,0xff, + 0xf3,0xff,0xf1,0xff,0xdf,0xff,0xd0,0xff, + 0xc7,0xff,0xbb,0xff,0xaf,0xff,0xa2,0xff, + 0x96,0xff,0x9a,0xff,0x8f,0xff,0x87,0xff, + 0x78,0xff,0x78,0xff,0x6d,0xff,0x7f,0xff, + 0x75,0xff,0xdc,0xff,0xf0,0xff,0xd9,0xff, + 0x2a,0x00,0x64,0x00,0xbf,0x00,0x1a,0x01, + 0x80,0x01,0x16,0x02,0x22,0x04,0xc1,0x04, + 0x40,0x05,0xc2,0x05,0x3d,0x06,0xb2,0x06, + 0x1a,0x07,0x78,0x07,0xba,0x47,0x00,0x08, + 0x1b,0x08,0x2a,0x08,0x19,0x08,0x01,0x08, + 0xc7,0x07,0x89,0x07,0x2d,0x07,0x4b,0x07, + 0xd2,0x06,0x5d,0x06,0xc3,0x05,0x4d,0x05, + 0x9e,0x04,0x43,0x04,0x11,0x03,0x06,0x02, + 0x03,0x02,0x84,0x01,0x45,0x01,0xec,0x00, + 0xb7,0x00,0x79,0x00,0x53,0x00,0x2b,0x00, + 0x37,0x00,0x23,0x00,0x13,0x00,0x07,0x00, + 0x00,0x00,0xfd,0xff,0xf7,0xff,0xf1,0xff, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0xfa,0xff,0xf0,0xff, + 0xed,0xff,0xd9,0xff,0xe2,0xff,0xc8,0xff, + 0xdb,0xff,0x9d,0xff,0xe9,0xff,0xb9,0xff, + 0x3a,0x00,0x07,0x00,0xcd,0x00,0xac,0x00, + 0xc9,0x01,0x78,0x01,0xea,0x02,0x71,0x02, + 0x29,0x04,0x66,0x03,0x4d,0x05,0x62,0x04, + 0xdf,0x06,0x02,0x04,0x9d,0x06,0x6d,0x03, + 0x3e,0x06,0xf4,0x01,0x36,0x05,0x86,0xff, + 0xae,0x02,0xa6,0xfa,0x4d,0x00,0xad,0xf5, + 0x8a,0xfe,0xa9,0xee,0x28,0x00,0x9a,0xdd, + 0x2d,0x67,0xc0,0x0f,0x74,0xdf,0x79,0xf5, + 0xe3,0xe4,0xd1,0xef,0x16,0xe6,0x84,0xed, + 0x35,0xe7,0x1c,0xee,0x83,0xea,0x71,0xef, + 0x0b,0xed,0x6a,0xf1,0x0e,0xf0,0xe9,0xf3, + 0x62,0xf3,0x98,0xf7,0xd2,0xf7,0x8d,0xfa, + 0x78,0xfa,0xb0,0xfc,0xb0,0xfc,0x65,0xfe, + 0x62,0xfe,0x9e,0xff,0x7b,0xff,0x3b,0x00, + 0x1e,0x00,0x8f,0x00,0x64,0x00,0x96,0x00, + 0x64,0x00,0x5c,0x00,0x38,0x00,0x31,0x00, + 0x19,0x00,0x0e,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0x0b,0x00,0x20,0x00,0x28,0x00, + 0x4f,0x00,0x45,0x00,0x86,0x00,0x73,0x00, + 0xbc,0x00,0x59,0x00,0xab,0x00,0xed,0xff, + 0x44,0x00,0x23,0xff,0x90,0xff,0xc4,0xfd, + 0x3c,0xfe,0xd0,0xfb,0x72,0xfc,0x54,0xf9, + 0x47,0xfa,0x59,0xf6,0xec,0xf6,0x90,0xf1, + 0xb4,0xf3,0x2e,0xee,0x75,0xf1,0x0b,0xeb, + 0xe5,0xef,0x60,0xe8,0xc9,0xee,0xbc,0xe4, + 0x9b,0xef,0x1b,0xe3,0x74,0xf3,0x3c,0xe0, + 0xfa,0xfc,0x68,0xd2,0xe5,0x4b,0x90,0x37, + 0x1a,0xda,0xbd,0x04,0x64,0xec,0xc7,0x01, + 0x5c,0xf4,0xba,0x02,0xc1,0xf9,0xd2,0x04, + 0xdc,0xfe,0x65,0x06,0x50,0x01,0x02,0x07, + 0xcc,0x02,0x00,0x07,0x7a,0x03,0x28,0x07, + 0x61,0x03,0x60,0x05,0xaf,0x02,0x16,0x04, + 0xd8,0x01,0xcc,0x02,0x01,0x01,0xb2,0x01, + 0x52,0x00,0xc0,0x00,0xdc,0xff,0x3a,0x00, + 0xa8,0xff,0xf2,0xff,0xa3,0xff,0xef,0xff, + 0xcd,0xff,0xee,0xff,0xe4,0xff,0xf6,0xff, + 0xf8,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xf9,0xff,0xe0,0xff, + 0xf6,0xff,0xe0,0xff,0x1a,0x00,0xdd,0xff, + 0x47,0x00,0xef,0xff,0xa1,0x00,0x09,0x00, + 0xce,0x00,0x42,0x00,0xa1,0x01,0xe1,0x00, + 0xc6,0x02,0xc7,0x01,0x46,0x04,0xea,0x02, + 0x8f,0x05,0xb3,0x05,0x39,0x0a,0xb7,0x07, + 0xdd,0x0c,0x67,0x09,0x9a,0x0f,0xc5,0x0a, + 0x0b,0x12,0x1e,0x0a,0x38,0x14,0x88,0x09, + 0x88,0x17,0x72,0x06,0xd3,0x1d,0x16,0xfa, + 0x4b,0x48,0x5c,0x76,0xc2,0xf3,0x5f,0x1d, + 0x60,0x02,0x5a,0x14,0xb2,0x04,0x8c,0x0f, + 0xcd,0x04,0xf0,0x0a,0xde,0xff,0xf7,0x05, + 0x24,0xff,0xb8,0x03,0x68,0xfe,0x0f,0x02, + 0xe0,0xfd,0x86,0x01,0xf7,0xfd,0x16,0x00, + 0xda,0xfd,0xc5,0xff,0x13,0xfe,0xa7,0xff, + 0x69,0xfe,0xa9,0xff,0xb1,0xfe,0x8b,0xff, + 0xef,0xfe,0xa4,0xff,0x3b,0xff,0xbd,0xff, + 0x7a,0xff,0xe7,0xff,0xcc,0xff,0xf5,0xff, + 0xe4,0xff,0xfa,0xff,0xf5,0xff,0xfe,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xfc,0xff,0xfa,0xff,0xf7,0xff, + 0xf3,0xff,0xee,0xff,0xda,0xff,0xce,0xff, + 0xc2,0xff,0xb6,0xff,0xa7,0xff,0x9b,0xff, + 0x88,0xff,0x89,0xff,0x81,0xff,0x74,0xff, + 0x65,0xff,0x61,0xff,0x58,0xff,0x64,0xff, + 0x60,0xff,0xa2,0xff,0xc5,0xff,0xc0,0xff, + 0x10,0x00,0x48,0x00,0xa9,0x00,0xfc,0x00, + 0x72,0x01,0xde,0x01,0xe0,0x03,0xb5,0x04, + 0x20,0x05,0xb1,0x05,0x22,0x06,0xa0,0x06, + 0x02,0x07,0x66,0x07,0xa5,0x47,0xea,0x07, + 0x00,0x08,0x10,0x08,0xfe,0x07,0xe5,0x07, + 0xac,0x07,0x69,0x07,0x1f,0x07,0x3c,0x07, + 0xb5,0x06,0x47,0x06,0xab,0x05,0x37,0x05, + 0x8b,0x04,0x2c,0x04,0x28,0x03,0x19,0x02, + 0xef,0x01,0x7d,0x01,0x37,0x01,0xe6,0x00, + 0xac,0x00,0x76,0x00,0x4a,0x00,0x37,0x00, + 0x3d,0x00,0x21,0x00,0x14,0x00,0x07,0x00, + 0x01,0x00,0xfd,0xff,0xfb,0xff,0xf2,0xff, + 0x50,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0xfa,0xff,0xf1,0xff, + 0xeb,0xff,0xde,0xff,0xdd,0xff,0xd1,0xff, + 0xc7,0xff,0xb5,0xff,0xde,0xff,0xdf,0xff, + 0x2e,0x00,0x42,0x00,0xbe,0x00,0xf7,0x00, + 0xbd,0x01,0xee,0x01,0xdb,0x02,0x06,0x03, + 0x0e,0x04,0x1b,0x04,0x20,0x05,0x24,0x05, + 0x4e,0x06,0x09,0x05,0x22,0x06,0x9f,0x04, + 0x87,0x05,0x5b,0x03,0x2d,0x04,0x37,0x01, + 0x33,0x01,0xb9,0xfc,0x14,0xfe,0x83,0xf8, + 0x17,0xfb,0x38,0xf3,0x8f,0xf9,0x0e,0xe9, + 0x5c,0x6f,0x48,0xfa,0x57,0xe8,0xdd,0xef, + 0xe5,0xe8,0xad,0xec,0xa4,0xe8,0x65,0xeb, + 0x28,0xe9,0xd5,0xec,0xce,0xeb,0x60,0xee, + 0x1a,0xee,0xa0,0xf0,0xec,0xf0,0x57,0xf3, + 0x19,0xf4,0x7b,0xf7,0x75,0xf8,0x41,0xfa, + 0xf9,0xfa,0x7c,0xfc,0x16,0xfd,0x40,0xfe, + 0xb1,0xfe,0x7c,0xff,0xa6,0xff,0x2a,0x00, + 0x40,0x00,0x82,0x00,0x7a,0x00,0x8d,0x00, + 0x73,0x00,0x59,0x00,0x3e,0x00,0x30,0x00, + 0x1b,0x00,0x0d,0x00,0x50,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0x0c,0x00,0x1e,0x00,0x2b,0x00, + 0x49,0x00,0x4d,0x00,0x84,0x00,0x7d,0x00, + 0xa0,0x00,0x68,0x00,0x7e,0x00,0x02,0x00, + 0x01,0x00,0x3d,0xff,0x35,0xff,0xf0,0xfd, + 0xc3,0xfd,0x0e,0xfc,0xd6,0xfb,0xac,0xf9, + 0x84,0xf9,0xda,0xf6,0xb5,0xf5,0x26,0xf2, + 0x9e,0xf2,0x0f,0xef,0x27,0xf0,0x47,0xec, + 0x54,0xee,0x14,0xea,0xae,0xec,0x49,0xe7, + 0x28,0xed,0xba,0xe6,0xd6,0xef,0xdc,0xe5, + 0x78,0xf6,0x8b,0xdd,0xc8,0x6a,0x09,0x0a, + 0x49,0xe9,0x0e,0xfd,0x03,0xf3,0x0d,0xfe, + 0xbb,0xf8,0x78,0x00,0x22,0xfd,0xc9,0x03, + 0x52,0x01,0x6c,0x05,0x50,0x03,0x47,0x06, + 0x6a,0x04,0x67,0x06,0xdb,0x04,0x62,0x06, + 0x2a,0x04,0x08,0x05,0x58,0x03,0xc7,0x03, + 0x56,0x02,0x88,0x02,0x5d,0x01,0x72,0x01, + 0x7c,0x00,0x96,0x00,0x00,0x00,0x19,0x00, + 0xbe,0xff,0xdb,0xff,0xaf,0xff,0xe1,0xff, + 0xd3,0xff,0xe7,0xff,0xe6,0xff,0xf4,0xff, + 0xf9,0xff,0xfe,0xff,0x00,0x00,0x00,0x00, + 0x50,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfa,0xff,0xeb,0xff, + 0x00,0x00,0xf1,0xff,0x0e,0x00,0xf3,0xff, + 0x28,0x00,0x01,0x00,0x5b,0x00,0x15,0x00, + 0x71,0x00,0x38,0x00,0xe2,0x00,0x92,0x00, + 0x7d,0x01,0x0f,0x01,0x4c,0x02,0x99,0x01, + 0x60,0x03,0x7d,0x03,0x28,0x05,0x5b,0x04, + 0x7b,0x06,0x35,0x05,0xc9,0x07,0xe6,0x05, + 0xba,0x08,0x90,0x05,0xca,0x09,0x4c,0x05, + 0x3e,0x0b,0xc9,0x03,0x4b,0x0e,0x9a,0xfc, + 0x99,0x41,0x38,0x1a,0x11,0xff,0xca,0x0b, + 0x8f,0x02,0xa4,0x08,0xef,0x02,0xaf,0x06, + 0x93,0x02,0xb1,0x03,0x32,0x00,0x3b,0x02, + 0xba,0xff,0x40,0x01,0x55,0xff,0x84,0x00, + 0x20,0xff,0x44,0x00,0xed,0xfe,0xd5,0xff, + 0xfc,0xfe,0xb7,0xff,0x1d,0xff,0xb4,0xff, + 0x49,0xff,0xbc,0xff,0x61,0xff,0xbc,0xff, + 0x8b,0xff,0xce,0xff,0xaf,0xff,0xde,0xff, + 0xcc,0xff,0xf4,0xff,0xed,0xff,0xfb,0xff, + 0xf7,0xff,0xfe,0xff,0xfe,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00, + 0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x02,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0xb5,0xff,0x00,0x00, + 0x04,0x00,0x00,0x00,0xc4,0xff,0x00,0x00, + 0x08,0x00,0x00,0x00,0xd3,0xff,0x00,0x00, + 0x0c,0x00,0x00,0x00,0xe2,0xff,0x00,0x00, + 0x10,0x00,0x00,0x00,0xf1,0xff,0x00,0x00, + 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, + 0x20,0x00,0x00,0x00,0x2d,0x00,0x00,0x00, + 0x24,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, + 0x28,0x00,0x00,0x00,0x4b,0x00,0x00,0x00, + 0x2c,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x30,0x00,0x00,0x00,0x00,0x00,0xac,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_28mm_pm90deg_16khz.conf b/tools/topology/topology2/include/components/tdfb/line4_28mm_pm90deg_16khz.conf new file mode 100644 index 000000000000..9e757b4f6e89 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_28mm_pm90deg_16khz.conf @@ -0,0 +1,172 @@ +# Created with script example_two_beams.m 23-Oct-2023 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x14,0x05,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x14,0x05,0x00,0x00,0x08,0x00,0x02,0x00, + 0x01,0x00,0x04,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfb,0xff, + 0xec,0xff,0xd1,0xff,0xa9,0xff,0x72,0xff, + 0x2b,0xff,0xd8,0xfe,0x79,0xfe,0x16,0xfe, + 0xb0,0xfd,0x4f,0xfd,0xf5,0xfc,0xc5,0xfc, + 0xac,0xfc,0xd6,0xfc,0x64,0xfc,0x87,0xfc, + 0x38,0xfd,0x90,0xfd,0x09,0xfe,0x70,0xfd, + 0x14,0xfc,0xfe,0xfb,0x2c,0xfc,0x75,0xfc, + 0x47,0xfd,0xa0,0xff,0xd1,0x01,0xfa,0x07, + 0x86,0x10,0xcc,0x13,0x24,0x57,0x65,0x18, + 0x52,0x18,0x89,0x17,0x7b,0x15,0x23,0x10, + 0x2a,0x09,0x76,0x05,0x94,0x02,0x7b,0x01, + 0x21,0x00,0x6c,0xfe,0xc9,0xfd,0x48,0xfe, + 0x9b,0xfe,0x09,0xff,0x45,0xff,0x72,0xff, + 0xc4,0xff,0xf9,0xff,0x17,0x00,0x27,0x00, + 0x2f,0x00,0x31,0x00,0x2c,0x00,0x24,0x00, + 0x1b,0x00,0x13,0x00,0x0b,0x00,0x05,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x08,0x00,0x24,0x00,0x32,0x00, + 0x81,0x00,0x8e,0x00,0x19,0x01,0xfe,0x00, + 0xb0,0x01,0x24,0x01,0xbf,0x01,0x3e,0x00, + 0x89,0x00,0xe7,0xfd,0x09,0xfe,0x9e,0xfa, + 0xc9,0xfa,0xa2,0xf6,0x6f,0xf9,0x75,0xf7, + 0x2e,0xfd,0x20,0xfc,0x3f,0x09,0x2f,0x0a, + 0x96,0x18,0x83,0x12,0x3e,0x1c,0xd1,0x05, + 0x08,0x0d,0x0b,0xdb,0x17,0x0e,0xf9,0x39, + 0x70,0xa7,0x4f,0xc7,0xf7,0xb2,0x34,0xc9, + 0x0b,0xc9,0x67,0xe5,0xb8,0xe9,0xa7,0xfd, + 0x35,0x01,0x53,0x0e,0xda,0x0b,0xa7,0x11, + 0x8f,0x0e,0x6c,0x10,0x67,0x0c,0x08,0x0c, + 0xe5,0x07,0x97,0x07,0xbf,0x04,0x69,0x04, + 0x7e,0x02,0x58,0x02,0x43,0x01,0x38,0x01, + 0x9e,0x00,0x90,0x00,0x40,0x00,0x31,0x00, + 0x10,0x00,0x05,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x05,0x00,0x0f,0x00,0x32,0x00, + 0x3e,0x00,0x93,0x00,0x99,0x00,0x3d,0x01, + 0x38,0x01,0x5d,0x02,0x67,0x02,0x6e,0x04, + 0x9b,0x04,0xa0,0x07,0xb3,0x07,0x0d,0x0c, + 0x2d,0x0c,0xa0,0x10,0x60,0x0e,0x20,0x12, + 0xc0,0x0b,0x10,0x0f,0x9f,0x01,0xf2,0xfe, + 0x3d,0xea,0x16,0xe7,0xc2,0xc9,0x8b,0xca, + 0x38,0xb2,0x9e,0xc8,0x8e,0xa4,0x45,0x2e, + 0xe9,0x1a,0xbe,0xd5,0xbb,0x0d,0x8c,0x03, + 0xdb,0x1c,0xab,0x11,0xa9,0x19,0x24,0x0a, + 0x5d,0x0a,0x39,0xfc,0xb9,0xfd,0x54,0xf7, + 0xd2,0xf9,0x5f,0xf6,0xe0,0xfa,0x53,0xfa, + 0x19,0xfe,0xaa,0xfd,0x90,0x00,0x16,0x00, + 0xc6,0x01,0x0f,0x01,0xb9,0x01,0xf4,0x00, + 0x20,0x01,0x8b,0x00,0x85,0x00,0x30,0x00, + 0x25,0x00,0x07,0x00,0x03,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x05,0x00, + 0x0c,0x00,0x11,0x00,0x1e,0x00,0x20,0x00, + 0x33,0x00,0x2a,0x00,0x3b,0x00,0x1a,0x00, + 0x2b,0x00,0xe7,0xff,0xe3,0xff,0x58,0xff, + 0x6b,0xff,0xe4,0xfe,0xd3,0xfe,0x12,0xfe, + 0x11,0xfe,0xfb,0xfd,0x5c,0x00,0xf8,0x00, + 0xf5,0x02,0x96,0x04,0x8b,0x09,0x9c,0x0e, + 0x78,0x16,0xcf,0x15,0xca,0x1a,0xa4,0x13, + 0xb0,0x56,0xa4,0x19,0x47,0x0e,0x7c,0x0a, + 0xc9,0x00,0xd3,0x00,0x9d,0xfc,0x2d,0xfd, + 0xa1,0xfb,0x83,0xfc,0x9f,0xfb,0xb0,0xfd, + 0xc1,0xfd,0xe0,0xfd,0x0b,0xfd,0xcf,0xfc, + 0x38,0xfc,0xff,0xfc,0x98,0xfc,0xe3,0xfc, + 0xe5,0xfc,0x61,0xfd,0xa4,0xfd,0x20,0xfe, + 0x70,0xfe,0xdd,0xfe,0x26,0xff,0x74,0xff, + 0xa7,0xff,0xd2,0xff,0xec,0xff,0xfb,0xff, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x00,0x05,0x00,0x0c,0x00,0x11,0x00, + 0x1e,0x00,0x20,0x00,0x33,0x00,0x2a,0x00, + 0x3b,0x00,0x1a,0x00,0x2b,0x00,0xe7,0xff, + 0xe3,0xff,0x58,0xff,0x6b,0xff,0xe4,0xfe, + 0xd3,0xfe,0x12,0xfe,0x11,0xfe,0xfb,0xfd, + 0x5c,0x00,0xf8,0x00,0xf5,0x02,0x96,0x04, + 0x8b,0x09,0x9c,0x0e,0x78,0x16,0xcf,0x15, + 0xca,0x1a,0xa4,0x13,0xb0,0x56,0xa4,0x19, + 0x47,0x0e,0x7c,0x0a,0xc9,0x00,0xd3,0x00, + 0x9d,0xfc,0x2d,0xfd,0xa1,0xfb,0x83,0xfc, + 0x9f,0xfb,0xb0,0xfd,0xc1,0xfd,0xe0,0xfd, + 0x0b,0xfd,0xcf,0xfc,0x38,0xfc,0xff,0xfc, + 0x98,0xfc,0xe3,0xfc,0xe5,0xfc,0x61,0xfd, + 0xa4,0xfd,0x20,0xfe,0x70,0xfe,0xdd,0xfe, + 0x26,0xff,0x74,0xff,0xa7,0xff,0xd2,0xff, + 0xec,0xff,0xfb,0xff,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00, + 0x0f,0x00,0x32,0x00,0x3e,0x00,0x93,0x00, + 0x99,0x00,0x3d,0x01,0x38,0x01,0x5d,0x02, + 0x67,0x02,0x6e,0x04,0x9b,0x04,0xa0,0x07, + 0xb3,0x07,0x0d,0x0c,0x2d,0x0c,0xa0,0x10, + 0x60,0x0e,0x20,0x12,0xc0,0x0b,0x10,0x0f, + 0x9f,0x01,0xf2,0xfe,0x3d,0xea,0x16,0xe7, + 0xc2,0xc9,0x8b,0xca,0x38,0xb2,0x9e,0xc8, + 0x8e,0xa4,0x45,0x2e,0xe9,0x1a,0xbe,0xd5, + 0xbb,0x0d,0x8c,0x03,0xdb,0x1c,0xab,0x11, + 0xa9,0x19,0x24,0x0a,0x5d,0x0a,0x39,0xfc, + 0xb9,0xfd,0x54,0xf7,0xd2,0xf9,0x5f,0xf6, + 0xe0,0xfa,0x53,0xfa,0x19,0xfe,0xaa,0xfd, + 0x90,0x00,0x16,0x00,0xc6,0x01,0x0f,0x01, + 0xb9,0x01,0xf4,0x00,0x20,0x01,0x8b,0x00, + 0x85,0x00,0x30,0x00,0x25,0x00,0x07,0x00, + 0x03,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x08,0x00, + 0x24,0x00,0x32,0x00,0x81,0x00,0x8e,0x00, + 0x19,0x01,0xfe,0x00,0xb0,0x01,0x24,0x01, + 0xbf,0x01,0x3e,0x00,0x89,0x00,0xe7,0xfd, + 0x09,0xfe,0x9e,0xfa,0xc9,0xfa,0xa2,0xf6, + 0x6f,0xf9,0x75,0xf7,0x2e,0xfd,0x20,0xfc, + 0x3f,0x09,0x2f,0x0a,0x96,0x18,0x83,0x12, + 0x3e,0x1c,0xd1,0x05,0x08,0x0d,0x0b,0xdb, + 0x17,0x0e,0xf9,0x39,0x70,0xa7,0x4f,0xc7, + 0xf7,0xb2,0x34,0xc9,0x0b,0xc9,0x67,0xe5, + 0xb8,0xe9,0xa7,0xfd,0x35,0x01,0x53,0x0e, + 0xda,0x0b,0xa7,0x11,0x8f,0x0e,0x6c,0x10, + 0x67,0x0c,0x08,0x0c,0xe5,0x07,0x97,0x07, + 0xbf,0x04,0x69,0x04,0x7e,0x02,0x58,0x02, + 0x43,0x01,0x38,0x01,0x9e,0x00,0x90,0x00, + 0x40,0x00,0x31,0x00,0x10,0x00,0x05,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfb,0xff,0xec,0xff,0xd1,0xff, + 0xa9,0xff,0x72,0xff,0x2b,0xff,0xd8,0xfe, + 0x79,0xfe,0x16,0xfe,0xb0,0xfd,0x4f,0xfd, + 0xf5,0xfc,0xc5,0xfc,0xac,0xfc,0xd6,0xfc, + 0x64,0xfc,0x87,0xfc,0x38,0xfd,0x90,0xfd, + 0x09,0xfe,0x70,0xfd,0x14,0xfc,0xfe,0xfb, + 0x2c,0xfc,0x75,0xfc,0x47,0xfd,0xa0,0xff, + 0xd1,0x01,0xfa,0x07,0x86,0x10,0xcc,0x13, + 0x24,0x57,0x65,0x18,0x52,0x18,0x89,0x17, + 0x7b,0x15,0x23,0x10,0x2a,0x09,0x76,0x05, + 0x94,0x02,0x7b,0x01,0x21,0x00,0x6c,0xfe, + 0xc9,0xfd,0x48,0xfe,0x9b,0xfe,0x09,0xff, + 0x45,0xff,0x72,0xff,0xc4,0xff,0xf9,0xff, + 0x17,0x00,0x27,0x00,0x2f,0x00,0x31,0x00, + 0x2c,0x00,0x24,0x00,0x1b,0x00,0x13,0x00, + 0x0b,0x00,0x05,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_28mm_pm90deg_48khz.conf b/tools/topology/topology2/include/components/tdfb/line4_28mm_pm90deg_48khz.conf new file mode 100644 index 000000000000..150519bdac18 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_28mm_pm90deg_48khz.conf @@ -0,0 +1,172 @@ +# Created with script example_two_beams.m 23-Oct-2023 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x14,0x05,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x14,0x05,0x00,0x00,0x08,0x00,0x02,0x00, + 0x01,0x00,0x04,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xfc,0xff,0xf7,0xff,0xef,0xff,0xe7,0xff, + 0xdb,0xff,0xd4,0xff,0xca,0xff,0xbc,0xff, + 0xae,0xff,0xa4,0xff,0x98,0xff,0x99,0xff, + 0x90,0xff,0xbb,0xff,0xd3,0xff,0xcd,0xff, + 0x0e,0x00,0x3e,0x00,0x94,0x00,0xe2,0x00, + 0x53,0x01,0xbf,0x01,0xad,0x03,0x87,0x04, + 0xfc,0x04,0x96,0x05,0x11,0x06,0x96,0x06, + 0xfe,0x06,0x65,0x07,0xa1,0x47,0xe6,0x07, + 0xf4,0x07,0xf9,0x07,0xd8,0x07,0xad,0x07, + 0x60,0x07,0x07,0x07,0xa5,0x06,0xa1,0x06, + 0x05,0x06,0x81,0x05,0xd6,0x04,0x51,0x04, + 0xa2,0x03,0x36,0x03,0x53,0x02,0x79,0x01, + 0x49,0x01,0xed,0x00,0xb4,0x00,0x7a,0x00, + 0x53,0x00,0x33,0x00,0x1b,0x00,0x11,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xfe,0xff,0xfe,0xff,0xfc,0xff, + 0x09,0x00,0x11,0x00,0x3b,0x00,0x5c,0x00, + 0xbe,0x00,0xee,0x00,0x84,0x01,0xc0,0x01, + 0x86,0x02,0xb9,0x02,0x98,0x03,0xca,0x03, + 0xda,0x04,0x07,0x04,0x13,0x05,0xf1,0x03, + 0xd9,0x04,0x03,0x03,0xd4,0x03,0x22,0x01, + 0x23,0x01,0xd9,0xfc,0x22,0xfe,0xa6,0xf8, + 0x25,0xfb,0x4a,0xf3,0x92,0xf9,0x0f,0xe9, + 0x56,0x6f,0x4b,0xfa,0x79,0xe8,0x0b,0xf0, + 0x52,0xe9,0x35,0xed,0x8b,0xe9,0x75,0xec, + 0xad,0xea,0x6f,0xee,0xe0,0xed,0x8d,0xf0, + 0xba,0xf0,0x46,0xf3,0xf0,0xf3,0x41,0xf6, + 0x3b,0xf7,0x06,0xfa,0xff,0xfa,0x6d,0xfc, + 0x18,0xfd,0x22,0xfe,0x99,0xfe,0x40,0xff, + 0x84,0xff,0xd7,0xff,0xea,0xff,0x08,0x00, + 0x08,0x00,0x09,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x03,0x00,0x07,0x00,0x10,0x00,0x00,0x00, + 0x00,0x00,0xc3,0xff,0xb5,0xff,0x1e,0xff, + 0xed,0xfe,0xe8,0xfd,0x98,0xfd,0x10,0xfc, + 0xb3,0xfb,0x95,0xf9,0x6a,0xf8,0x57,0xf5, + 0x4c,0xf5,0xfa,0xf1,0x7a,0xf2,0xb6,0xee, + 0x23,0xf0,0xe8,0xeb,0xf7,0xed,0x8f,0xe8, + 0xe2,0xed,0x6d,0xe7,0x22,0xf0,0x26,0xe6, + 0x86,0xf6,0x9d,0xdd,0xc1,0x6a,0x08,0x0a, + 0x55,0xe9,0x13,0xfd,0x28,0xf3,0x16,0xfe, + 0xee,0xf8,0x73,0x00,0x48,0xfd,0x88,0x03, + 0x36,0x01,0xde,0x04,0xe7,0x02,0x5b,0x05, + 0xa8,0x03,0x1f,0x05,0xbd,0x03,0xb4,0x04, + 0xec,0x02,0x57,0x03,0x15,0x02,0x2f,0x02, + 0x3e,0x01,0x38,0x01,0x95,0x00,0x89,0x00, + 0x27,0x00,0x25,0x00,0x00,0x00,0x03,0x00, + 0xfc,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x17,0x00,0x06,0x00, + 0x2a,0x00,0x18,0x00,0x6c,0x00,0x4e,0x00, + 0xdd,0x00,0xa9,0x00,0x86,0x01,0x1f,0x01, + 0x7d,0x02,0xaf,0x02,0x20,0x04,0x9b,0x03, + 0x87,0x05,0x90,0x04,0xfd,0x06,0x68,0x05, + 0x25,0x08,0x47,0x05,0x69,0x09,0x27,0x05, + 0x09,0x0b,0xbf,0x03,0x37,0x0e,0x9c,0xfc, + 0x95,0x41,0x37,0x1a,0x11,0xff,0xb9,0x0b, + 0x88,0x02,0x7c,0x08,0xdb,0x02,0x6d,0x06, + 0x71,0x02,0x72,0x03,0x2d,0x00,0x00,0x02, + 0xc3,0xff,0x11,0x01,0x73,0xff,0x6a,0x00, + 0x54,0xff,0x32,0x00,0x3f,0xff,0xe3,0xff, + 0x5e,0xff,0xd6,0xff,0x87,0xff,0xdb,0xff, + 0xb2,0xff,0xe7,0xff,0xcf,0xff,0xef,0xff, + 0xea,0xff,0xfa,0xff,0xfb,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x17,0x00,0x06,0x00,0x2a,0x00,0x18,0x00, + 0x6c,0x00,0x4e,0x00,0xdd,0x00,0xa9,0x00, + 0x86,0x01,0x1f,0x01,0x7d,0x02,0xaf,0x02, + 0x20,0x04,0x9b,0x03,0x87,0x05,0x90,0x04, + 0xfd,0x06,0x68,0x05,0x25,0x08,0x47,0x05, + 0x69,0x09,0x27,0x05,0x09,0x0b,0xbf,0x03, + 0x37,0x0e,0x9c,0xfc,0x95,0x41,0x37,0x1a, + 0x11,0xff,0xb9,0x0b,0x88,0x02,0x7c,0x08, + 0xdb,0x02,0x6d,0x06,0x71,0x02,0x72,0x03, + 0x2d,0x00,0x00,0x02,0xc3,0xff,0x11,0x01, + 0x73,0xff,0x6a,0x00,0x54,0xff,0x32,0x00, + 0x3f,0xff,0xe3,0xff,0x5e,0xff,0xd6,0xff, + 0x87,0xff,0xdb,0xff,0xb2,0xff,0xe7,0xff, + 0xcf,0xff,0xef,0xff,0xea,0xff,0xfa,0xff, + 0xfb,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00, + 0x10,0x00,0x00,0x00,0x00,0x00,0xc3,0xff, + 0xb5,0xff,0x1e,0xff,0xed,0xfe,0xe8,0xfd, + 0x98,0xfd,0x10,0xfc,0xb3,0xfb,0x95,0xf9, + 0x6a,0xf8,0x57,0xf5,0x4c,0xf5,0xfa,0xf1, + 0x7a,0xf2,0xb6,0xee,0x23,0xf0,0xe8,0xeb, + 0xf7,0xed,0x8f,0xe8,0xe2,0xed,0x6d,0xe7, + 0x22,0xf0,0x26,0xe6,0x86,0xf6,0x9d,0xdd, + 0xc1,0x6a,0x08,0x0a,0x55,0xe9,0x13,0xfd, + 0x28,0xf3,0x16,0xfe,0xee,0xf8,0x73,0x00, + 0x48,0xfd,0x88,0x03,0x36,0x01,0xde,0x04, + 0xe7,0x02,0x5b,0x05,0xa8,0x03,0x1f,0x05, + 0xbd,0x03,0xb4,0x04,0xec,0x02,0x57,0x03, + 0x15,0x02,0x2f,0x02,0x3e,0x01,0x38,0x01, + 0x95,0x00,0x89,0x00,0x27,0x00,0x25,0x00, + 0x00,0x00,0x03,0x00,0xfc,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff, + 0xfe,0xff,0xfc,0xff,0x09,0x00,0x11,0x00, + 0x3b,0x00,0x5c,0x00,0xbe,0x00,0xee,0x00, + 0x84,0x01,0xc0,0x01,0x86,0x02,0xb9,0x02, + 0x98,0x03,0xca,0x03,0xda,0x04,0x07,0x04, + 0x13,0x05,0xf1,0x03,0xd9,0x04,0x03,0x03, + 0xd4,0x03,0x22,0x01,0x23,0x01,0xd9,0xfc, + 0x22,0xfe,0xa6,0xf8,0x25,0xfb,0x4a,0xf3, + 0x92,0xf9,0x0f,0xe9,0x56,0x6f,0x4b,0xfa, + 0x79,0xe8,0x0b,0xf0,0x52,0xe9,0x35,0xed, + 0x8b,0xe9,0x75,0xec,0xad,0xea,0x6f,0xee, + 0xe0,0xed,0x8d,0xf0,0xba,0xf0,0x46,0xf3, + 0xf0,0xf3,0x41,0xf6,0x3b,0xf7,0x06,0xfa, + 0xff,0xfa,0x6d,0xfc,0x18,0xfd,0x22,0xfe, + 0x99,0xfe,0x40,0xff,0x84,0xff,0xd7,0xff, + 0xea,0xff,0x08,0x00,0x08,0x00,0x09,0x00, + 0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xfc,0xff,0xf7,0xff, + 0xef,0xff,0xe7,0xff,0xdb,0xff,0xd4,0xff, + 0xca,0xff,0xbc,0xff,0xae,0xff,0xa4,0xff, + 0x98,0xff,0x99,0xff,0x90,0xff,0xbb,0xff, + 0xd3,0xff,0xcd,0xff,0x0e,0x00,0x3e,0x00, + 0x94,0x00,0xe2,0x00,0x53,0x01,0xbf,0x01, + 0xad,0x03,0x87,0x04,0xfc,0x04,0x96,0x05, + 0x11,0x06,0x96,0x06,0xfe,0x06,0x65,0x07, + 0xa1,0x47,0xe6,0x07,0xf4,0x07,0xf9,0x07, + 0xd8,0x07,0xad,0x07,0x60,0x07,0x07,0x07, + 0xa5,0x06,0xa1,0x06,0x05,0x06,0x81,0x05, + 0xd6,0x04,0x51,0x04,0xa2,0x03,0x36,0x03, + 0x53,0x02,0x79,0x01,0x49,0x01,0xed,0x00, + 0xb4,0x00,0x7a,0x00,0x53,0x00,0x33,0x00, + 0x1b,0x00,0x11,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xc7,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_generic_pm10deg_16khz.conf b/tools/topology/topology2/include/components/tdfb/line4_generic_pm10deg_16khz.conf new file mode 100644 index 000000000000..ff71a228821c --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_generic_pm10deg_16khz.conf @@ -0,0 +1,202 @@ +# Created with script example_two_beams_default.m 17-May-2024 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams_default +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x04,0x06,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x06,0x00,0x00,0x08,0x00,0x02,0x00, + 0x01,0x00,0x04,0x00,0x01,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xec,0x7f,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0xfd,0xff,0x07,0x00,0xf4,0xff,0x14,0x00, + 0xe3,0xff,0x29,0x00,0xc9,0xff,0x47,0x00, + 0xa5,0xff,0x71,0x00,0x75,0xff,0xa8,0x00, + 0x37,0xff,0xef,0x00,0xe7,0xfe,0x4a,0x01, + 0x7f,0xfe,0xbf,0x01,0xf8,0xfd,0x5c,0x02, + 0x40,0xfd,0x38,0x03,0x35,0xfc,0x85,0x04, + 0x85,0xfa,0xd2,0x06,0x27,0xf7,0x51,0x0c, + 0x33,0xec,0xb8,0x30,0xb2,0x6c,0x70,0xe6, + 0x5a,0x0e,0x23,0xf6,0x6d,0x07,0x20,0xfa, + 0xcb,0x04,0x03,0xfc,0x5d,0x03,0x23,0xfd, + 0x73,0x02,0xe7,0xfd,0xcd,0x01,0x74,0xfe, + 0x52,0x01,0xe0,0xfe,0xf4,0x00,0x32,0xff, + 0xab,0x00,0x73,0xff,0x73,0x00,0xa4,0xff, + 0x49,0x00,0xc8,0xff,0x29,0x00,0xe2,0xff, + 0x14,0x00,0xf4,0xff,0x07,0x00,0xfd,0xff, + 0x01,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0xfd,0xff,0x07,0x00, + 0xf2,0xff,0x16,0x00,0xdf,0xff,0x2e,0x00, + 0xc3,0xff,0x50,0x00,0x9a,0xff,0x7f,0x00, + 0x64,0xff,0xbd,0x00,0x1e,0xff,0x0d,0x01, + 0xc3,0xfe,0x75,0x01,0x4d,0xfe,0xfc,0x01, + 0xb1,0xfd,0xb1,0x02,0xdb,0xfc,0xb2,0x03, + 0xa0,0xfb,0x40,0x05,0x93,0xf9,0x1a,0x08, + 0x48,0xf5,0x7b,0x0f,0xec,0xe4,0x79,0x65, + 0xb4,0x3a,0x59,0xe9,0xe9,0x0d,0x11,0xf6, + 0xa2,0x07,0xe1,0xf9,0x0a,0x05,0xc7,0xfb, + 0x95,0x03,0xf1,0xfc,0xa0,0x02,0xbe,0xfd, + 0xf1,0x01,0x55,0xfe,0x6e,0x01,0xc8,0xfe, + 0x09,0x01,0x21,0xff,0xba,0x00,0x66,0xff, + 0x7d,0x00,0x9b,0xff,0x4f,0x00,0xc3,0xff, + 0x2d,0x00,0xe0,0xff,0x16,0x00,0xf2,0xff, + 0x07,0x00,0xfd,0xff,0x01,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0xff,0xff,0x02,0x00, + 0xfd,0xff,0x04,0x00,0xfa,0xff,0x08,0x00, + 0xf6,0xff,0x0c,0x00,0xf1,0xff,0x13,0x00, + 0xea,0xff,0x1a,0x00,0xe1,0xff,0x25,0x00, + 0xd5,0xff,0x32,0x00,0xc5,0xff,0x45,0x00, + 0xb0,0xff,0x5f,0x00,0x8f,0xff,0x89,0x00, + 0x57,0xff,0xd9,0x00,0xda,0xfe,0xbe,0x01, + 0x88,0xfc,0xc1,0x7f,0xb0,0x03,0x31,0xfe, + 0x30,0x01,0x20,0xff,0xaf,0x00,0x72,0xff, + 0x76,0x00,0x9c,0xff,0x55,0x00,0xb7,0xff, + 0x3f,0x00,0xca,0xff,0x2f,0x00,0xd8,0xff, + 0x22,0x00,0xe3,0xff,0x19,0x00,0xeb,0xff, + 0x12,0x00,0xf1,0xff,0x0c,0x00,0xf6,0xff, + 0x08,0x00,0xfa,0xff,0x04,0x00,0xfd,0xff, + 0x02,0x00,0xff,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0xff,0xff,0x02,0x00,0xfd,0xff,0x04,0x00, + 0xfa,0xff,0x08,0x00,0xf6,0xff,0x0c,0x00, + 0xf1,0xff,0x13,0x00,0xea,0xff,0x1a,0x00, + 0xe1,0xff,0x25,0x00,0xd5,0xff,0x32,0x00, + 0xc5,0xff,0x45,0x00,0xb0,0xff,0x5f,0x00, + 0x8f,0xff,0x89,0x00,0x57,0xff,0xd9,0x00, + 0xda,0xfe,0xbe,0x01,0x88,0xfc,0xc1,0x7f, + 0xb0,0x03,0x31,0xfe,0x30,0x01,0x20,0xff, + 0xaf,0x00,0x72,0xff,0x76,0x00,0x9c,0xff, + 0x55,0x00,0xb7,0xff,0x3f,0x00,0xca,0xff, + 0x2f,0x00,0xd8,0xff,0x22,0x00,0xe3,0xff, + 0x19,0x00,0xeb,0xff,0x12,0x00,0xf1,0xff, + 0x0c,0x00,0xf6,0xff,0x08,0x00,0xfa,0xff, + 0x04,0x00,0xfd,0xff,0x02,0x00,0xff,0xff, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0xfd,0xff,0x07,0x00,0xf2,0xff,0x16,0x00, + 0xdf,0xff,0x2e,0x00,0xc3,0xff,0x50,0x00, + 0x9a,0xff,0x7f,0x00,0x64,0xff,0xbd,0x00, + 0x1e,0xff,0x0d,0x01,0xc3,0xfe,0x75,0x01, + 0x4d,0xfe,0xfc,0x01,0xb1,0xfd,0xb1,0x02, + 0xdb,0xfc,0xb2,0x03,0xa0,0xfb,0x40,0x05, + 0x93,0xf9,0x1a,0x08,0x48,0xf5,0x7b,0x0f, + 0xec,0xe4,0x79,0x65,0xb4,0x3a,0x59,0xe9, + 0xe9,0x0d,0x11,0xf6,0xa2,0x07,0xe1,0xf9, + 0x0a,0x05,0xc7,0xfb,0x95,0x03,0xf1,0xfc, + 0xa0,0x02,0xbe,0xfd,0xf1,0x01,0x55,0xfe, + 0x6e,0x01,0xc8,0xfe,0x09,0x01,0x21,0xff, + 0xba,0x00,0x66,0xff,0x7d,0x00,0x9b,0xff, + 0x4f,0x00,0xc3,0xff,0x2d,0x00,0xe0,0xff, + 0x16,0x00,0xf2,0xff,0x07,0x00,0xfd,0xff, + 0x01,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x00,0xfd,0xff,0x07,0x00, + 0xf4,0xff,0x14,0x00,0xe3,0xff,0x29,0x00, + 0xc9,0xff,0x47,0x00,0xa5,0xff,0x71,0x00, + 0x75,0xff,0xa8,0x00,0x37,0xff,0xef,0x00, + 0xe7,0xfe,0x4a,0x01,0x7f,0xfe,0xbf,0x01, + 0xf8,0xfd,0x5c,0x02,0x40,0xfd,0x38,0x03, + 0x35,0xfc,0x85,0x04,0x85,0xfa,0xd2,0x06, + 0x27,0xf7,0x51,0x0c,0x33,0xec,0xb8,0x30, + 0xb2,0x6c,0x70,0xe6,0x5a,0x0e,0x23,0xf6, + 0x6d,0x07,0x20,0xfa,0xcb,0x04,0x03,0xfc, + 0x5d,0x03,0x23,0xfd,0x73,0x02,0xe7,0xfd, + 0xcd,0x01,0x74,0xfe,0x52,0x01,0xe0,0xfe, + 0xf4,0x00,0x32,0xff,0xab,0x00,0x73,0xff, + 0x73,0x00,0xa4,0xff,0x49,0x00,0xc8,0xff, + 0x29,0x00,0xe2,0xff,0x14,0x00,0xf4,0xff, + 0x07,0x00,0xfd,0xff,0x01,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xec,0x7f,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf6,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xae,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_generic_pm10deg_48khz.conf b/tools/topology/topology2/include/components/tdfb/line4_generic_pm10deg_48khz.conf new file mode 100644 index 000000000000..ab550cf5c32d --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_generic_pm10deg_48khz.conf @@ -0,0 +1,202 @@ +# Created with script example_two_beams_default.m 17-May-2024 +# cd tools/tune/tdfb; matlab -nodisplay -nosplash -nodesktop -r example_two_beams_default +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x04,0x06,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x06,0x00,0x00,0x08,0x00,0x02,0x00, + 0x01,0x00,0x04,0x00,0x01,0x00,0x01,0x00, + 0x00,0x00,0x0f,0x00,0xa6,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xec,0x7f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x00,0xfe,0xff,0x03,0x00,0xfb,0xff, + 0x08,0x00,0xf5,0xff,0x0f,0x00,0xed,0xff, + 0x18,0x00,0xe2,0xff,0x25,0x00,0xd4,0xff, + 0x35,0x00,0xc1,0xff,0x4a,0x00,0xa9,0xff, + 0x65,0x00,0x8b,0xff,0x88,0x00,0x63,0xff, + 0xb7,0x00,0x2b,0xff,0xf9,0x00,0xd9,0xfe, + 0x63,0x01,0x4d,0xfe,0x29,0x02,0x17,0xfd, + 0x5b,0x04,0x89,0xf7,0xd9,0x7e,0xb8,0x09, + 0x5e,0xfb,0x01,0x03,0xce,0xfd,0xb5,0x01, + 0xa0,0xfe,0x23,0x01,0x0d,0xff,0xce,0x00, + 0x51,0xff,0x96,0x00,0x80,0xff,0x6e,0x00, + 0xa2,0xff,0x50,0x00,0xbd,0xff,0x39,0x00, + 0xd1,0xff,0x27,0x00,0xe0,0xff,0x19,0x00, + 0xec,0xff,0x0f,0x00,0xf5,0xff,0x08,0x00, + 0xfb,0xff,0x03,0x00,0xfe,0xff,0x01,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x00, + 0xfb,0xff,0x07,0x00,0xf5,0xff,0x10,0x00, + 0xeb,0xff,0x1b,0x00,0xdd,0xff,0x2b,0x00, + 0xcb,0xff,0x41,0x00,0xb3,0xff,0x5c,0x00, + 0x93,0xff,0x80,0x00,0x6a,0xff,0xaf,0x00, + 0x34,0xff,0xee,0x00,0xe9,0xfe,0x49,0x01, + 0x79,0xfe,0xd8,0x01,0xb9,0xfd,0xe8,0x02, + 0x15,0xfc,0xe0,0x05,0xab,0xf4,0xd9,0x7d, + 0xe7,0x0d,0x72,0xf9,0x41,0x04,0xe3,0xfc, + 0x6e,0x02,0x08,0xfe,0xa2,0x01,0xa0,0xfe, + 0x2b,0x01,0x00,0xff,0xdd,0x00,0x42,0xff, + 0xa4,0x00,0x73,0xff,0x79,0x00,0x99,0xff, + 0x58,0x00,0xb6,0xff,0x3e,0x00,0xcd,0xff, + 0x2a,0x00,0xdf,0xff,0x1a,0x00,0xec,0xff, + 0x0f,0x00,0xf5,0xff,0x07,0x00,0xfb,0xff, + 0x02,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x02,0x00,0xfc,0xff,0x06,0x00,0xf7,0xff, + 0x0d,0x00,0xee,0xff,0x17,0x00,0xe2,0xff, + 0x25,0x00,0xd3,0xff,0x37,0x00,0xbe,0xff, + 0x4e,0x00,0xa3,0xff,0x6d,0x00,0x81,0xff, + 0x95,0x00,0x53,0xff,0xcb,0x00,0x13,0xff, + 0x18,0x01,0xb3,0xfe,0x92,0x01,0x0f,0xfe, + 0x7a,0x02,0xa7,0xfc,0x07,0x05,0x3d,0xf6, + 0x70,0x7e,0x9d,0x0b,0x7a,0xfa,0x98,0x03, + 0x5d,0xfd,0x0f,0x02,0x55,0xfe,0x62,0x01, + 0xd6,0xfe,0xfe,0x00,0x26,0xff,0xbb,0x00, + 0x5f,0xff,0x8b,0x00,0x88,0xff,0x67,0x00, + 0xa8,0xff,0x4a,0x00,0xc1,0xff,0x34,0x00, + 0xd5,0xff,0x23,0x00,0xe4,0xff,0x16,0x00, + 0xef,0xff,0x0d,0x00,0xf7,0xff,0x06,0x00, + 0xfc,0xff,0x02,0x00,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0x02,0x00,0xfc,0xff, + 0x06,0x00,0xf7,0xff,0x0d,0x00,0xee,0xff, + 0x17,0x00,0xe2,0xff,0x25,0x00,0xd3,0xff, + 0x37,0x00,0xbe,0xff,0x4e,0x00,0xa3,0xff, + 0x6d,0x00,0x81,0xff,0x95,0x00,0x53,0xff, + 0xcb,0x00,0x13,0xff,0x18,0x01,0xb3,0xfe, + 0x92,0x01,0x0f,0xfe,0x7a,0x02,0xa7,0xfc, + 0x07,0x05,0x3d,0xf6,0x70,0x7e,0x9d,0x0b, + 0x7a,0xfa,0x98,0x03,0x5d,0xfd,0x0f,0x02, + 0x55,0xfe,0x62,0x01,0xd6,0xfe,0xfe,0x00, + 0x26,0xff,0xbb,0x00,0x5f,0xff,0x8b,0x00, + 0x88,0xff,0x67,0x00,0xa8,0xff,0x4a,0x00, + 0xc1,0xff,0x34,0x00,0xd5,0xff,0x23,0x00, + 0xe4,0xff,0x16,0x00,0xef,0xff,0x0d,0x00, + 0xf7,0xff,0x06,0x00,0xfc,0xff,0x02,0x00, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x03,0x00,0xfb,0xff,0x07,0x00, + 0xf5,0xff,0x10,0x00,0xeb,0xff,0x1b,0x00, + 0xdd,0xff,0x2b,0x00,0xcb,0xff,0x41,0x00, + 0xb3,0xff,0x5c,0x00,0x93,0xff,0x80,0x00, + 0x6a,0xff,0xaf,0x00,0x34,0xff,0xee,0x00, + 0xe9,0xfe,0x49,0x01,0x79,0xfe,0xd8,0x01, + 0xb9,0xfd,0xe8,0x02,0x15,0xfc,0xe0,0x05, + 0xab,0xf4,0xd9,0x7d,0xe7,0x0d,0x72,0xf9, + 0x41,0x04,0xe3,0xfc,0x6e,0x02,0x08,0xfe, + 0xa2,0x01,0xa0,0xfe,0x2b,0x01,0x00,0xff, + 0xdd,0x00,0x42,0xff,0xa4,0x00,0x73,0xff, + 0x79,0x00,0x99,0xff,0x58,0x00,0xb6,0xff, + 0x3e,0x00,0xcd,0xff,0x2a,0x00,0xdf,0xff, + 0x1a,0x00,0xec,0xff,0x0f,0x00,0xf5,0xff, + 0x07,0x00,0xfb,0xff,0x02,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x40,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0xfe,0xff, + 0x03,0x00,0xfb,0xff,0x08,0x00,0xf5,0xff, + 0x0f,0x00,0xed,0xff,0x18,0x00,0xe2,0xff, + 0x25,0x00,0xd4,0xff,0x35,0x00,0xc1,0xff, + 0x4a,0x00,0xa9,0xff,0x65,0x00,0x8b,0xff, + 0x88,0x00,0x63,0xff,0xb7,0x00,0x2b,0xff, + 0xf9,0x00,0xd9,0xfe,0x63,0x01,0x4d,0xfe, + 0x29,0x02,0x17,0xfd,0x5b,0x04,0x89,0xf7, + 0xd9,0x7e,0xb8,0x09,0x5e,0xfb,0x01,0x03, + 0xce,0xfd,0xb5,0x01,0xa0,0xfe,0x23,0x01, + 0x0d,0xff,0xce,0x00,0x51,0xff,0x96,0x00, + 0x80,0xff,0x6e,0x00,0xa2,0xff,0x50,0x00, + 0xbd,0xff,0x39,0x00,0xd1,0xff,0x27,0x00, + 0xe0,0xff,0x19,0x00,0xec,0xff,0x0f,0x00, + 0xf5,0xff,0x08,0x00,0xfb,0xff,0x03,0x00, + 0xfe,0xff,0x01,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xec,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x00, + 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00, + 0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xf6,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xae,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xff, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4_pass.conf b/tools/topology/topology2/include/components/tdfb/line4_pass.conf new file mode 100644 index 000000000000..9838f4dd32bf --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4_pass.conf @@ -0,0 +1,31 @@ +# Exported with script example_pass_config.m 13-May-2024 +# cd tools/tune/tdfb; octave --no-window-system example_pass_config.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0xac,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xac,0x00,0x00,0x00,0x04,0x00,0x04,0x00, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x02,0x00,0x03,0x00,0x01,0x00,0x02,0x00, + 0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/tdfb/line4to2_pass.conf b/tools/topology/topology2/include/components/tdfb/line4to2_pass.conf new file mode 100644 index 000000000000..2f6a6f839166 --- /dev/null +++ b/tools/topology/topology2/include/components/tdfb/line4to2_pass.conf @@ -0,0 +1,22 @@ +# Exported with script example_pass_config.m 16-May-2024 +# cd tools/tune/tdfb; octave --no-window-system example_pass_config.m +Object.Base.data."tdfb_config" { + bytes " + 0x53,0x4f,0x46,0x34,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x00,0xa0,0x01,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x68,0x00,0x00,0x00,0x02,0x00,0x02,0x00, + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x04,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00, + 0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00" +} diff --git a/tools/topology/topology2/include/components/template_comp.conf b/tools/topology/topology2/include/components/template_comp.conf new file mode 100644 index 000000000000..20bc1a8a9465 --- /dev/null +++ b/tools/topology/topology2/include/components/template_comp.conf @@ -0,0 +1,86 @@ +# +# A TEMPLATE_COMP component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.template_comp.attribute_name" +# +# Usage: this component can be used by declaring in the parent object. i.e. +# +# Object.Widget.template_comp."N" { +# index 1 +# } +# } + +# +# Where M is pipeline ID and N is a unique integer in the parent object. + +<include/controls/mixer.conf> + +Class.Widget."template_comp" { + # + # Pipeline ID + # + DefineAttribute."index" { + type "integer" + } + + # + # Unique instance for TEMPLATE_COMP widget + # + DefineAttribute."instance" { + type "integer" + } + + # Include common widget attributes definition + <include/components/widget-common.conf> + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "num_input_pins" + "num_output_pins" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + !immutable [ + "uuid" + "type" + ] + !deprecated [ + "preload_count" + ] + unique "instance" + } + + # + # template_comp widget switch control + # + Object.Control { + mixer."1" { + Object.Base.channel.1 { + name "fc" + shift 0 + } + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get 259 + put 259 + } + max 1 + } + } + + # + # Default attributes for template_comp + # + + uuid "af:e1:2d:a6:64:59:2e:4e:b1:67:7f:dc:97:27:9a:29" + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/virtual.conf b/tools/topology/topology2/include/components/virtual.conf new file mode 100644 index 000000000000..095628d0a02d --- /dev/null +++ b/tools/topology/topology2/include/components/virtual.conf @@ -0,0 +1,52 @@ +# SOF virtual widget +# +# A generic virtual component. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.virtual.attribute_name" +# +# Usage: this component can be used by declaring in the "widgets" field of +# a parent object. i.e. +# +# "Object.Widget.virtual.name" { +# type "out_drv" +# } +# ] +# + +Class.Widget."virtual" { + DefineAttribute."instance" {} + + # + # Argument used to construct virtual widget object: name + # + DefineAttribute."name" { + type "string" + } + + DefineAttribute."index" {} + + DefineAttribute.no_pm {} + + DefineAttribute.type { + type "string" + constraints { + !valid_values [ + "out_drv" + "input" + "output" + ] + } + } + + attributes { + !constructor [ + "name" + ] + !mandatory [ + "type" + ] + unique "instance" + } + + # default attribute values for virtual widget + no_pm "true" +} diff --git a/tools/topology/topology2/include/components/volume.conf b/tools/topology/topology2/include/components/volume.conf new file mode 100644 index 000000000000..cbcf8b0bffc3 --- /dev/null +++ b/tools/topology/topology2/include/components/volume.conf @@ -0,0 +1,170 @@ +# +# Common pipeline volume +# +# A generic volume widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.pga.N.attribute_name" +# +# Usage: this component can be used by declaring int a parent object. i.e. +# +# Object.Widget.pga."N" { +# index 1 +# format s24le +# no_pm "true" +# } +# +# Where N is the unique instance number for pga widget in the same alsaconf node. + +<include/controls/mixer.conf> + +Class.Widget."pga" { + # + # Pipeline ID for the pga widget object + # + DefineAttribute."index" {} + + # + # pga object instance + # + DefineAttribute."instance" {} + + #include common component definition + <include/components/widget-common.conf> + + # + # Bespoke attributes for PGA + # + + # + # Volume ramp step type. The values provided will be translated to integer values + # as specified in the tuple_values array. + # For example: "linear" is translated to 0, "log" to 1 etc. + # + DefineAttribute."ramp_step_type" { + type "string" + # Token set reference name + token_ref "volume.word" + constraints { + !valid_values [ + "linear" + "log" + "linear_zc" + "log_zc" + ] + !tuple_values [ + 0 + 1 + 2 + 3 + ] + } + } + + # + # Volume ramp step in milliseconds + # + DefineAttribute."ramp_step_ms" { + # Token set reference name + token_ref "volume.word" + } + + # Attribute categories + attributes { + # + # The PGA widget name would be constructed using the index and instance attributes. + # For ex: "pga.1.1" or "pga.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # 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" + ] + + # + # pga widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # + # pga widget mixer controls + # + Object.Control { + # volume mixer control + mixer."1" { + #Channel register and shift for Front Left/Right + Object.Base.channel.1 { + name "fl" + shift 0 + } + Object.Base.channel.2 { + name "fr" + } + + Object.Base.ops.1 { + name "ctl" + info "volsw" + #256 binds the mixer control to volume get/put handlers + get 256 + put 256 + } + max 32 + } + + # mute switch control + mixer."2" { + Object.Base.channel.1 { + name "flw" + reg 2 + shift 0 + } + Object.Base.channel.2 { + name "fl" + reg 2 + shift 1 + } + Object.Base.channel.3 { + name "fr" + reg 2 + shift 2 + } + Object.Base.channel.4 { + name "frw" + reg 2 + shift 3 + } + + Object.Base.ops.1 { + name "ctl" + info "volsw" + #259 binds the mixer control to switch get/put handlers + get "259" + put "259" + } + + #max 1 indicates switch type control + max 1 + } + } + + # Default attribute values for pga widget + type "pga" + uuid "7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:86:82" + no_pm "true" + 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 new file mode 100644 index 000000000000..43ac5691c778 --- /dev/null +++ b/tools/topology/topology2/include/components/widget-common.conf @@ -0,0 +1,181 @@ +# +# Common widget attribute definitions +# + +## instance of the widget object +DefineAttribute."instance" {} + +# +## no_pm - maps to the DAPM widget's reg field +## "false" value indicates that there is no direct DAPM for this widget +# +DefineAttribute."no_pm" { + type "string" + constraints { + !valid_values [ + "true" + "false" + ] + } +} + +# +## Widget Type - maps to the widget ID with values of type enum SND_SOC_TPLG_DAPM_* +# +DefineAttribute."type" { + type "string" +} + +# +## Stream name - maps to the DAPM widget's stream name +# +DefineAttribute."stream_name" { + type "string" +} + +# +## Event type widget binds to +# +DefineAttribute.event_type {} + +# +## Widget event flags +# +DefineAttribute.event_flags {} + +# +# Attributes with a "token_ref" value will be added to widget's private data +# + +## widget format +DefineAttribute."format" { + type "string" + # Token set reference name and type + token_ref "comp.string" + constraints { + !valid_values [ + "s16le" + "s24le" + "s32le" + "float" + ] + } +} + +## ID of the core this widget should be scheduled on +DefineAttribute."core_id" { + # Token set reference name and type + token_ref "comp.word" +} + +## number of periods to preload +DefineAttribute."preload_count" { + # Token set reference name and type + token_ref "comp.word" +} + +## Number of sink pins a widget can support +DefineAttribute."num_input_pins" { + # Token set reference name and type + token_ref "comp.word" +} + +## Number of source pins a widget can support +DefineAttribute."num_output_pins" { + # Token set reference name and type + token_ref "comp.word" +} + +## Number of supported sink(input) audio formats +DefineAttribute."num_input_audio_formats" { + # Token set reference name and type + token_ref "comp.word" +} + +## Number of supported source(output) audio formats +DefineAttribute."num_output_audio_formats" { + # Token set reference name and type + token_ref "comp.word" +} + +## Widget UUID +DefineAttribute.uuid { + type "string" + # Token set reference name and type + token_ref "comp.uuid" +} + +## Whether to add this widget's name to the beginning of all its associated mixer names +DefineAttribute."no_wname_in_kcontrol_name" { + type "string" + # Token set reference name + token_ref "comp.bool" + constraints { + !valid_values [ + "true" + "false" + ] + } +} + +no_wname_in_kcontrol_name "true" + +## widget format +DefineAttribute."scheduler_domain" { + type "string" + # Token set reference name and type + token_ref "comp.string" + constraints { + !valid_values [ + # Low Latency + "LL" + # Data Processing + "DP" + # Use manifest value + "default" + ] + } +} + +## Userspace domain id +DefineAttribute."domain_id" { + # Token set reference name and type + token_ref "comp.word" +} + +## Stack size requirement in bytes for this component. Zero indicates default stack size. +DefineAttribute."stack_bytes_requirement" { + # Token set reference name and type + token_ref "comp.word" +} + +## Interim Heap size requirement in bytes for this component. +## Used for resources that may change in size or be freed during the lifetime of the component. +## In practice this means anything allocated outside module's init() call-back. +DefineAttribute."interim_heap_bytes_requirement" { + # Token set reference name and type + token_ref "comp.word" +} + +## Lifetime heap memory allocation requirement in bytes for this component. +## This token's value indicates the amount of allocated memory needed at component init phase +## and used over the lifetime of the component until the component is destroyed. +## In practice this means anything allocated in init() call-back. +DefineAttribute."lifetime_heap_bytes_requirement" { + # Token set reference name and type + token_ref "comp.word" +} + +## Shared memory allocation requirement in bytes for this component. +## This token's value indicates the amount of shared memory the component may need to allocated. +## Shared memory may be shared to other components. +DefineAttribute."shared_bytes_requirement" { + # Token set reference name and type + token_ref "comp.word" +} + +# These default values are here until we have measured module specific numbers +stack_bytes_requirement 8192 +interim_heap_bytes_requirement 4096 +lifetime_heap_bytes_requirement 16384 +shared_bytes_requirement 4096 \ No newline at end of file diff --git a/tools/topology/topology2/include/components/wov.conf b/tools/topology/topology2/include/components/wov.conf new file mode 100644 index 000000000000..fccf2066be6e --- /dev/null +++ b/tools/topology/topology2/include/components/wov.conf @@ -0,0 +1,104 @@ +# +# wov widget +# +# A wov widget. This is a generic class, which will be used for multiple types of wov +# widget, and the wov widgets can be distinguished from one another with different UUID's. +# All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.wov.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.wov."N" { +# uuid $WOV_UUID +# } +# +# Where N is the unique instance number for the wov object within the same alsaconf node. + +Class.Widget."wov" { + # + # Pipeline ID for the wov object + # + DefineAttribute."index" {} + + # + # wov object instance + # + DefineAttribute."instance" {} + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "comp.word" + } + + #include common component definition + <include/components/widget-common.conf> + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "comp.word" + } + + attributes { + # + # The wov widget name would be constructed using the index and + # instance attributes. For example: "wov.0.1". + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "num_input_audio_formats" + "num_output_audio_formats" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "type" + ] + + unique "instance" + } + + Object.Control.bytes."1" { + name wov_init + access [ + tlv_read + tlv_callback + ] + Object.Base.extops."extctl" { + get 258 + put 0 + } + max 4096 + Object.Base.data."1" { + IncludeByKey.WOV_UUID { + '1f:d5:a8:eb:27:78:b5:47:82:ee:de:6e:77:43:af:67' {bytes "0x53, 0x4f, 0x46, 0x34, 0x02, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, + 0x34, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00" + } + } + } + } + + # + # Default attributes for wov + # + type "effect" + no_pm "true" + num_input_pins 1 + num_output_pins 0 +} diff --git a/tools/topology/topology2/include/controls/bytes.conf b/tools/topology/topology2/include/controls/bytes.conf new file mode 100644 index 000000000000..1483e36f10a3 --- /dev/null +++ b/tools/topology/topology2/include/controls/bytes.conf @@ -0,0 +1,91 @@ +# Common class definitions for bytes +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Control.bytes.N.attribute_name" +# +# Class for byte objects. These are instantiated as: +# Object.Contorl.bytes."N" { +# name "eq filter" +# index N +# max 128 +# access "tlv_read" +# +# Object.Base.data.eqiir { +# } +# } +# + +<include/controls/common.conf> + +Class.Control."bytes" { + + DefineAttribute."name" { + type "string" + } + + # Pipeline ID + DefineAttribute."index" {} + + # unique instance for bytes object in the same alsaconf node + DefineAttribute."instance" {} + + DefineArgument."index" { + type "integer" + } + + DefineAttribute."max" {} + DefineAttribute."base" {} + DefineAttribute."num_regs" {} + DefineAttribute."mask" {} + + DefineAttribute."access" { + constraints { + !valid_values [ + "read_write" + "tlv_read_write" + "read" + "write" + "volatile" + "tlv_read" + "tlv_write" + "tlv_command" + "inactive" + "lock" + "owner" + "tlv_callback" + ] + } + } + + attributes { + !constructor [ + "index" + "instance" + ] + !mandatory [ + "index" + ] + unique "instance" + } + + # control uses bespoke driver get/put/info ID + Object.Base.ops.1 { + name "ctl" + info "bytes" + } + + Object.Base.extops.1 { + name "extctl" + #258 binds the control to byte control get/put handlers + get 258 + put 258 + } + + # Default attribute values for bytes control + max 1024 + !access [ + tlv_write + tlv_read + tlv_callback + ] +} diff --git a/tools/topology/topology2/include/controls/common.conf b/tools/topology/topology2/include/controls/common.conf new file mode 100644 index 000000000000..caf32838b61e --- /dev/null +++ b/tools/topology/topology2/include/controls/common.conf @@ -0,0 +1,203 @@ +## \file common.conf +## \brief Common class definitions for controls. + +## \struct channel +## \brief Class for channel objects. +## These are instantiated as: +## +## Object.Base.channel."fl" { +## reg 1 +## shift 0 +## } +## + +Class.Base."channel" { + DefineAttribute."instance" {} + ## name of the channel + DefineAttribute."name" { + type "string" + } + + DefineAttribute."reg" {} + + DefineAttribute."shift" {} + + attributes { + !constructor [ + "name" + ] + # + # scale objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + reg 1 + shift 1 +} + +## \struct ops +## \brief Class definition for control ops. +## +## These are instantiated as: +## +## Object.Base.ops."ctl" { +## info "volsw" +## get "259" +## put "259" +## } +## + +Class.Base."ops" { + DefineAttribute."instance" {} + # ops name + DefineAttribute."name" { + type "string" + } + + DefineAttribute."info" {} + + DefineAttribute."get" {} + + DefineAttribute."put" {} + + attributes { + !constructor [ + "name" + ] + !mandatory [ + "info" + ] + # + # ops objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } +} + +## \struct extops +## \brief Class definition for control extops. +## These are instantiated as: +## +## Object.Base.extops."ctl" { +## info "volsw" +## get "258" +## put "258" +## } +## + +Class.Base."extops" { + DefineAttribute."instance" {} + # extops name + DefineAttribute."name" { + type "string" + } + + DefineAttribute."info" {} + + DefineAttribute."get" {} + + DefineAttribute."put" {} + + attributes { + !constructor [ + "name" + ] + !mandatory [ + "get" + "put" + ] + # + # extops objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } +} + +## \struct scale +## \brief Class definition for scale objects. +## These are instantiated as follows: +## +## Object.Base.scale."name" { +## mute 1 +## } +## + +Class.Base."scale" { + DefineAttribute."instance" {} + DefineAttribute."name" { + type "string" + } + + DefineAttribute."min" {} + + DefineAttribute."step" {} + + DefineAttribute."mute" {} + + attributes { + !constructor [ + "name" + ] + # + # scale objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + # Default scale attributes: "-64dB step 2dB" + min -6400 + step 200 + mute 1 +} + +## \struct tlv +## \brief Class definition for tlv objects. +## These are instantiated as follows: +## +## Object.Base.tlv."vtlv_m64s2" { +## Object.Base.scale."0" {} +## } +## +## The linked object instance is \link scale \endlink . +## + +Class.Base."tlv" { + DefineAttribute."instance" {} + DefineAttribute."name" { + type "string" + } + attributes { + !constructor [ + "name" + ] + # + # TLV objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } +} + +Class.Base."text" { + DefineAttribute."instance" {} + + DefineAttribute."name" { + type "string" + } + + attributes { + !constructor [ + "name" + ] + # + # text objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } +} diff --git a/tools/topology/topology2/include/controls/enum.conf b/tools/topology/topology2/include/controls/enum.conf new file mode 100644 index 000000000000..48da5fc8a760 --- /dev/null +++ b/tools/topology/topology2/include/controls/enum.conf @@ -0,0 +1,94 @@ +# +# Enum kcontrol class. All attributes defined herein are namespaced +# by alsatplg to "Object.Control.enum.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Control.enum."N" { +# index 1 +# name "Master Playback Enum Control" +# Object.Base.text.1 { +# name "mytext" +# !values [ +# "One" +# "Two" +# "Three" +# ] +# } +# Object.Base.channel.1 { +# name "fc" +# shift 0 +# reg 0 +# } +# Object.Base.ops."ctl" { +# info "enum" +# get "257" +# put "257" +# } +# } +# +# Where N is the unique instance number for the buffer object within the same alsaconf node. +# The enum control object should also include the ops, channels and tlv objects in the object +# instance + +<include/controls/common.conf> + +Class.Control."enum" { + # + # Pipeline ID for the enum object + # + DefineAttribute."index" {} + + # + # Instance of enum object in the same alsaconf node + # + DefineAttribute."instance" {} + + # + # Enum name. A enum object is included in the built topology only if it is given a + # name + # + DefineAttribute."name" { + type "string" + } + + # + # access control for enum + # + DefineAttribute."access" { + type "compound" + constraints { + !valid_values [ + "read_write" + "tlv_read_write" + "read" + "write" + "volatile" + "tlv_read" + "tlv_write" + "tlv_command" + "inactive" + "lock" + "owner" + "tlv_callback" + ] + } + } + + attributes { + # + # The Enum object name would be constructed using the index and instance arguments. + # For ex: "enum.1.1" or "enum.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + # + # enum control objects instantiated within the same alsaconf node must have unique + # index attribute + # + unique "instance" + } + +} diff --git a/tools/topology/topology2/include/controls/mixer.conf b/tools/topology/topology2/include/controls/mixer.conf new file mode 100644 index 000000000000..191230ec5bdc --- /dev/null +++ b/tools/topology/topology2/include/controls/mixer.conf @@ -0,0 +1,128 @@ +## \struct mixer +## \brief Topology Mixer class +## +## All attributes defined herein are namespaced +## by alsatplg to "Object.Control.mixer.N.attribute_name" +## +## Usage: this component can be used by instantiating it in the parent object. i.e. +## +## Object.Control.mixer."N" { +## index 1 +## name "1 Master Playback Volume" +## max 32 +## Object.Base.channel.1 { +## name "fl" +## shift 0 +## reg 0 +## } +## Object.Base.channel.2 { +## name "fr" +## shift 1 +## reg 1 +## } +## Object.Base.ops."ctl" { +## info "volsw" +## get "258" +## put "258" +## } +## } +## +## The linked object instaces are \link channel \endlink and \link ops \endlink . +## +## Where N is the unique instance number for the buffer object within the same alsaconf node. +## The mixer control object should also include the ops, channels and tlv objects in the object +## instance + +<include/controls/common.conf> + +Class.Control."mixer" { + ## + ## @ Pipeline ID for the mixer object + ## + DefineAttribute."index" {} ##< Automatically given unique index + + # + # Instance of mixer object in the same alsaconf node + # + DefineAttribute."instance" {} + + # + # Mixer name. A mixer object is included in the built topology only if it is given a + # name + # + DefineAttribute."name" { + type "string" + } + + # + # Max volume setting + # + DefineAttribute."max" {} + + DefineAttribute."invert" { + type "string" + constraints { + !valid_values [ + "true" + "false" + ] + } + } + + # use mute LED + DefineAttribute."mute_led_use" { + token_ref "mute_led.word" + } + + # LED direction + DefineAttribute."mute_led_direction" { + token_ref "mute_led.word" + } + + # + # access control for mixer + # + DefineAttribute."access" { + type "compound" + constraints { + !valid_values [ + "read_write" + "tlv_read_write" + "read" + "write" + "volatile" + "tlv_read" + "tlv_write" + "tlv_command" + "inactive" + "lock" + "owner" + "tlv_callback" + ] + } + } + + attributes { + # + # The Mixer object name would be constructed using the index and instance arguments. + # For ex: "mixer.1.1" or "mixer.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + !mandatory [ + "max" + ] + # + # mixer control objects instantiated within the same alsaconf node must have unique + # index attribute + # + unique "instance" + } + + # Default attribute values for mixer control + invert "false" + mute_led_use 0 + mute_led_direction 0 +} diff --git a/tools/topology/topology2/include/dais/alh.conf b/tools/topology/topology2/include/dais/alh.conf new file mode 100644 index 000000000000..4f4908455cb6 --- /dev/null +++ b/tools/topology/topology2/include/dais/alh.conf @@ -0,0 +1,92 @@ +# +# ALH DAI class definition. All attributes defined herein are namespaced +# by alsatplg to "Object.Dai.ALH.N.attribute_name" +# +# Usage: ALH DAI objects can be instantiated as: +# +# Object.Dai.ALH."N" { +# direction "capture" # playback or capture +# dai_name "SDW0-Capture" +# id 2 +# Object.hw_config."2" { +# } +# } +# +# where N is the unique instance number for the ALH object within the same alsaconf node. + +# ALH port definition +Class.Dai."ALH" { + + # + # instance ID of ALH DAI object + # + DefineAttribute."instance" {} + + # + # Argument used to construct DAI widget + # + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + DefineAttribute."direction" { + type "string" + token_ref "dai.word" + constraints { + !valid_values [ + "playback" + "capture" + "duplex" + ] + } + } + + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + } + + DefineAttribute."default_hw_config_id" {} + + DefineAttribute."name" { + type "string" + } + + DefineAttribute."type" { + token_ref "sof_dai_tokens.string" + } + + DefineAttribute."rate" { + token_ref "alh.word" + } + + DefineAttribute."channels" { + token_ref "alh.word" + } + + # Backend DAI Link ID matching with the machine driver + DefineAttribute."id" {} + DefineAttribute."default_hw_config_id" {} + DefineAttribute."dai_name" {} + + + attributes { + !constructor [ + "name" + ] + + !mandatory [ + "format" + "rate" + "ch" + "dai_index" + ] + + !immutable [ + "dai_type" + ] + unique "instance" + } + + dai_type "ALH" +} diff --git a/tools/topology/topology2/include/dais/dmic.conf b/tools/topology/topology2/include/dais/dmic.conf new file mode 100644 index 000000000000..812f143fd988 --- /dev/null +++ b/tools/topology/topology2/include/dais/dmic.conf @@ -0,0 +1,122 @@ +# +# Intel DMIC DAI +# +# All attributes defined herein are namespaced by alsatplg to "dmic.attribute_name" +# +# Usage: this component can be used by declaring in the "dais" field of +# a parent object. i.e. +# +# For Capture +# Object.DMIC."M.capture" { +# name "dmic16k" +# id 2 +# Object.Base.hw_config."0" { +# id 0 +# } +# Object.Base.pdm_config."0" { +# ctrl_id 0 +# } +# } +# +# +# Where M is DAI index in the firmware + +Class.Dai."DMIC" { + + # + # instance ID of DMIC DAI object + # + DefineAttribute."instance" {} + + # + # Argument used to construct DAI widget + # + # DAI Index + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + DefineAttribute."direction" { + type "string" + } + + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + } + + # Backend DAI Link ID matching with the machine driver + DefineAttribute.id {} + + DefineAttribute.default_hw_config_id {} + + DefineAttribute.name { + type "string" + } + + DefineAttribute.driver_version { + token_ref "intel_dmic.word" + } + + DefineAttribute.clk_min { + token_ref "intel_dmic.word" + } + + DefineAttribute.clk_max { + token_ref "intel_dmic.word" + } + + DefineAttribute.duty_min { + token_ref "intel_dmic.word" + } + + DefineAttribute.duty_max { + token_ref "intel_dmic.word" + } + + DefineAttribute.num_pdm_active { + token_ref "intel_dmic.word" + } + + DefineAttribute.sample_rate { + token_ref "intel_dmic.word" + } + + DefineAttribute.fifo_word_length { + token_ref "intel_dmic.word" + } + + DefineAttribute.unmute_ramp_time_ms { + token_ref "intel_dmic.word" + } + + # platform clock frequency + DefineAttribute.io_clk {} + + attributes { + !constructor [ + "name" + ] + !mandatory [ + "num_pdm_active" + "dai_index" + ] + !immutable [ + "dai_type" + "direction" + ] + unique "instance" + } + + dai_type "DMIC" + default_hw_config_id 0 + clk_min 2400000 + clk_max 4800000 + duty_min 40 + duty_max 60 + sample_rate 48000 + fifo_word_length 32 + unmute_ramp_time_ms 400 + driver_version 1 + direction "capture" +} diff --git a/tools/topology/topology2/include/dais/hda.conf b/tools/topology/topology2/include/dais/hda.conf new file mode 100644 index 000000000000..6194b74e6d87 --- /dev/null +++ b/tools/topology/topology2/include/dais/hda.conf @@ -0,0 +1,91 @@ +# +# HDA DAI +# +# All attributes defined herein are namespaced by alsatplg to "Object.Dai.hda.attribute_name" +# +# Usage: this component can be used by declaring as follows: +# +# For Playback +#Object.Dai.HDA."N" { +# direction "playback" +# stream_name "iDisp1" +# id 2 +# Object.Base.hw_config."0" {} +# } +# For Capture +#Object.Dai.HDA."N" { +# direction "capture" +# stream_name "codec1_in" +# id 2 +# Object.Base.hw_config."1" {} +# } +# +# +# Where N is the dai index of the HDA DAI in the firmware + +Class.Dai."HDA" { + # + # instance ID of HDA DAI object + # + DefineAttribute."instance" {} + + # + # DAI Index in the firmware + # + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + DefineAttribute."direction" { + type "string" + constraints { + !valid_values [ + "playback" + "capture" + "duplex" + ] + } + } + + # type of DAI + DefineAttribute.dai_type { + type "string" + token_ref "dai.string" + } + + # Backend DAI Link ID matching with the machine driver + DefineAttribute.id {} + + DefineAttribute."default_hw_config_id" {} + + DefineAttribute.name { + type "string" + } + + DefineAttribute.rate {} + + DefineAttribute.ch {} + + attributes { + !constructor [ + "name" + ] + !mandatory [ + "id" + "dai_index" + ] + !immutable [ + "type" + ] + # + # HDA DAI objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + dai_type "HDA" + default_hw_config_id 0 + rate 48000 + ch 2 +} diff --git a/tools/topology/topology2/include/dais/hw_config_simple.conf b/tools/topology/topology2/include/dais/hw_config_simple.conf new file mode 100644 index 000000000000..e87daa36ed52 --- /dev/null +++ b/tools/topology/topology2/include/dais/hw_config_simple.conf @@ -0,0 +1,35 @@ +# Simple hardware config class definition for HDA/SDW/DMIC type DAIs. All attributes defined herein +# are namespaced by alsatplg to "Object.Base.hw_config.1.attribute_name" +# +# Object.Base.hw_config.1 { +# id 0 +# name "HDA0" +# } +# +# where 1 is the unique instance ID for the hw_config object within the same alsaconf +# node. + +Class.Base."hw_config" { + # + # Argument used to construct hw config (hw config ID) + # + DefineAttribute."id" {} + DefineAttribute."instance" {} + + DefineAttribute."name" { + type "string" + } + + attributes { + !constructor [ + "id" + ] + !mandatory [ + "name" + ] + # + # hw_config objects instantiated within the same alsaconf node must have unique + # 'instance' attribute + unique "instance" + } +} diff --git a/tools/topology/topology2/include/dais/mic_config.conf b/tools/topology/topology2/include/dais/mic_config.conf new file mode 100644 index 000000000000..7d28df69f672 --- /dev/null +++ b/tools/topology/topology2/include/dais/mic_config.conf @@ -0,0 +1,111 @@ +# mic vendor config for nhlt type mic config +# +# Object.Base.vendor_mic_config."0" { +# mic_type 0 +# location 4 +# speaker_position_distance 0 +# horizontal_offset 0 +# vertical_offset 0 +# frequency_low_band 0 +# frequency_high_band 0 +# direction_angle 0 +# elevation_angle 0 +# vertical_angle_begin 0 +# vertical_angle_end 0 +# horizontal_angle_begin 0 +# horizontal_angle_end 0 +# } +# +# Object.Base.vendor_mic_config."1" { +# mic_type 0 +# location 4 +# speaker_position_distance 0 +# horizontal_offset 0 +# vertical_offset 0 +# frequency_low_band 0 +# frequency_high_band 0 +# direction_angle 0 +# elevation_angle 0 +# vertical_angle_begin 0 +# vertical_angle_end 0 +# horizontal_angle_begin 0 +# horizontal_angle_end 0 +# } +# +Class.Base."vendor_mic_config" { + + DefineAttribute."mic_id" {} + + # 0 Omnidirectional + # 1 Subcardioid + # 2 Cardioid + # 3 Supercardioid + # 4 Hypercardioid + # 5 Figure-8 + # 6 Reserved + # 7 Vendordefined + DefineAttribute."mic_type" {} + + # 0 Top + # 1 Bottom + # 2 Left + # 3 Right + # 4 Front (default) + # 5 Rear + DefineAttribute."location" {} + + # in mm + DefineAttribute."speaker_position_distance" {} + + # in mm + DefineAttribute."horizontal_offset" {} + + # in mm + DefineAttribute."vertical_offset" {} + + # 5 x Hz + DefineAttribute."frequency_low_band" {} + + # 500 x Hz + DefineAttribute."frequency_low_band" {} + + # -180 - + 180 + DefineAttribute."direction_angle" {} + + # -180 - + 180 + DefineAttribute."elevation_angle" {} + + # -180 - + 180 with 2 deg step + DefineAttribute."vertical_angle_begin" {} + + # -180 - + 180 with 2 deg step + DefineAttribute."vertical_angle_end" {} + + # -180 - + 180 with 2 deg step + DefineAttribute."horizontal_angle_begin" {} + + # -180 - + 180 with 2 deg step + DefineAttribute."horizontal_angle_end" {} + + attributes { + !constructor [ + "mic_id" + ] + !mandatory [ + "mic_type" + "location" + "speaker_position_distance" + "horizontal_offset" + "vertical_offset" + "frequency_low_band" + "frequency_high_band" + "direction_angle" + "elevation_angle" + "vertical_angle_begin" + "vertical_angle_end" + "horizontal_angle_begin" + "horizontal_angle_end" + ] + unique "mic_id" + } +} diff --git a/tools/topology/topology2/include/dais/mic_extension.conf b/tools/topology/topology2/include/dais/mic_extension.conf new file mode 100644 index 000000000000..31628e9b2241 --- /dev/null +++ b/tools/topology/topology2/include/dais/mic_extension.conf @@ -0,0 +1,24 @@ +## \brief Mic extension class +## \struct mic_extension + +Class.Base."mic_extension" { + + DefineAttribute."id" {} + + # 16.16 fixed point value + DefineAttribute."snr" {} + + # 16.16 fixed point value + DefineAttribute."sensitivity" {} + + attributes { + !constructor [ + "id" + ] + !mandatory [ + "snr" + "sensitivity" + ] + unique "id" + } +} diff --git a/tools/topology/topology2/include/dais/pdm_config.conf b/tools/topology/topology2/include/dais/pdm_config.conf new file mode 100644 index 000000000000..3745bea7998e --- /dev/null +++ b/tools/topology/topology2/include/dais/pdm_config.conf @@ -0,0 +1,59 @@ +## \brief Class for PDM config +## \struct pdm_config + +Class.Base."pdm_config" { + DefineAttribute."instance" {} + # + # Argument used to construct DMIC PDM config + # + DefineAttribute."ctrl_id" { + token_ref "intel_dmic_pdm.short" + } + + DefineAttribute.mic_a_enable { + token_ref "intel_dmic_pdm.short" + } + + DefineAttribute.mic_b_enable { + token_ref "intel_dmic_pdm.short" + } + + DefineAttribute.polarity_a { + token_ref "intel_dmic_pdm.short" + } + + DefineAttribute.polarity_b { + token_ref "intel_dmic_pdm.short" + } + + DefineAttribute.clk_edge { + token_ref "intel_dmic_pdm.short" + } + + DefineAttribute.skew { + token_ref "intel_dmic_pdm.short" + } + + attributes { + !constructor [ + "ctrl_id" + ] + !mandatory [ + "mic_a_enable" + "mic_b_enable" + "polarity_a" + "polarity_b" + "clk_edge" + "skew" + ] + unique "instance" + } + + # default attribute values + mic_a_enable 1 + mic_b_enable 1 + polarity_a 0 + polarity_b 0 + clk_edge 0 + skew 0 +} diff --git a/tools/topology/topology2/include/dais/sai.conf b/tools/topology/topology2/include/dais/sai.conf new file mode 100644 index 000000000000..2a8ce6b55e0e --- /dev/null +++ b/tools/topology/topology2/include/dais/sai.conf @@ -0,0 +1,94 @@ +# +# SAI DAI class definition. All attributes defined herein are namespaced +# by alsatplg to "Object.Dai.SAI.N.attribute_name" +# +# Usage: SAI DAI objects can be instantiated as: +# +# Object.Dai.SAI."N" { +# direction "duplex" # playback, capture or duplex +# dai_name "NoCodec-0" +# id 0 +# Object.hw_config."0" { +# mclk_freq 12288000 +# bclk_freq 3072000 +# tdm_slot_width 32 +# } +# Object.dai."playback" { +# } +# Object.dai."capture" { +# } +# } +# +# where N is the unique instance number for the SAI object within the same alsaconf node. + +# SAI port definition +Class.Dai."SAI" { + + # + # instance ID of SAI DAI object + # + DefineAttribute."instance" {} + + # DAI Index + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + DefineAttribute."direction" { + type "string" + constraints { + !valid_values [ + "playback" + "capture" + "duplex" + ] + } + } + + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + } + + DefineAttribute."default_hw_config_id" {} + + DefineAttribute."name" { + type "string" + } + + # Backend DAI Link ID matching with the machine driver + DefineAttribute."id" {} + + DefineAttribute."mclk_id" { + # Token reference and type + token_ref "nxp_sai.short" + } + + # platform clock frequency + DefineAttribute.io_clk {} + + attributes { + !constructor [ + "name" + ] + + !mandatory [ + "id" + "sample_bits" + "dai_index" + ] + + !immutable [ + "dai_type" + ] + # + # SAI DAI objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + dai_type "SAI" + mclk_id 0 + default_hw_config_id 0 +} diff --git a/tools/topology/topology2/include/dais/ssp.conf b/tools/topology/topology2/include/dais/ssp.conf new file mode 100644 index 000000000000..cccba74dea10 --- /dev/null +++ b/tools/topology/topology2/include/dais/ssp.conf @@ -0,0 +1,151 @@ +# +# SSP DAI class definition. All attributes defined herein are namespaced +# by alsatplg to "Object.Dai.SSP.N.attribute_name" +# +# Usage: SSP DAI objects can be instantiated as: +# +# Object.Dai.SSP."N" { +# direction "duplex" # playback, capture or duplex +# dai_name "NoCodec-0" +# id 0 +# quirks "lbm_mode" +# sample_bits 24 +# Object.hw_config."0" { +# mclk_freq 24000000 +# bclk_freq 4800000 +# tdm_slot_width 25 +# } +# Object.dai."playback" { +# } +# Object.dai."capture" { +# } +# } +# +# where N is the unique instance number for the SSP object within the same alsaconf node. + +# SSP port definition +Class.Dai."SSP" { + + # + # instance ID of SSP DAI object + # + DefineAttribute."instance" {} + + # DAI Index + DefineAttribute."dai_index" { + token_ref "dai.word" + } + + DefineAttribute."direction" { + type "string" + constraints { + !valid_values [ + "playback" + "capture" + "duplex" + ] + } + } + + DefineAttribute."dai_type" { + type "string" + token_ref "dai.string" + } + + DefineAttribute."default_hw_config_id" {} + + DefineAttribute."name" { + type "string" + } + + # Backend DAI Link ID matching with the machine driver + DefineAttribute."id" {} + + DefineAttribute."sample_bits" { + # Token reference and type + token_ref "intel_ssp.word" + } + + DefineAttribute."bclk_delay" { + # Token reference and type + token_ref "intel_ssp.word" + } + + DefineAttribute."tdm_padding_per_slot" { + type "string" + # Token reference and type + token_ref "intel_ssp.bool" + constraints { + !valid_values [ + "true" + "false" + ] + } + } + + # SSP quirks. Value will translated based on ssp_quirks. For ex: lb_mode will + # be converted to 64. + DefineAttribute."quirks" { + # Token reference and type + token_ref "intel_ssp.word" + constraints { + !valid_values [ + "lbm_mode" + ] + !tuple_values [ + 64 + ] + + } + } + + DefineAttribute."mclk_id" { + # Token reference and type + token_ref "intel_ssp.short" + } + + # platform clock frequency + DefineAttribute.io_clk {} + + # SSP blob version + DefineAttribute.version { + constraints { + !valid_values [ + $SSP_BLOB_VERSION_1_0 + $SSP_BLOB_VERSION_1_5 + $SSP_BLOB_VERSION_3_0 + ] + } + } + + attributes { + !constructor [ + "name" + ] + + !mandatory [ + "id" + "sample_bits" + "dai_index" + ] + + !immutable [ + "dai_type" + ] + # + # SSP DAI objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + dai_type "SSP" + bclk_delay 0 + mclk_id 0 + default_hw_config_id 0 + clks_control 0 + frame_pulse_width 0 + tdm_padding_per_slot false + # SSP_BLOB_VERSION must be defined in the top-level topology file + version $SSP_BLOB_VERSION +} diff --git a/tools/topology/topology2/include/formats/compr_input_audio_formats.conf b/tools/topology/topology2/include/formats/compr_input_audio_formats.conf new file mode 100644 index 000000000000..8d5694400988 --- /dev/null +++ b/tools/topology/topology2/include/formats/compr_input_audio_formats.conf @@ -0,0 +1,107 @@ + # All input formats for e.g. host-copier, decoder, + # and module-copier + num_input_audio_formats 40 + CombineArrays.Object.Base.input_audio_format [ + { + in_channels [ 1 ] + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 8 ] + in_valid_bit_depth [ 8 ] + in_sample_type [ $SAMPLE_TYPE_UNSIGNED_INTEGER ] + in_ch_map [ $CHANNEL_MAP_MONO ] + in_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + in_channels [ 1 ] + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_ch_map [ $CHANNEL_MAP_MONO ] + in_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + in_channels [ 1 ] + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 24 ] + in_ch_map [ $CHANNEL_MAP_MONO ] + in_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + in_channels [ 1 ] + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + in_ch_map [ $CHANNEL_MAP_MONO ] + in_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 8 ] + in_valid_bit_depth [ 8 ] + in_sample_type [ $SAMPLE_TYPE_UNSIGNED_INTEGER ] + } + { + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + } + { + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 24 ] + } + { + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + } + ] diff --git a/tools/topology/topology2/include/formats/compr_input_audio_formats_s32_48k.conf b/tools/topology/topology2/include/formats/compr_input_audio_formats_s32_48k.conf new file mode 100644 index 000000000000..9ea5b19a2f16 --- /dev/null +++ b/tools/topology/topology2/include/formats/compr_input_audio_formats_s32_48k.conf @@ -0,0 +1,29 @@ + # Input formats for e.g. micsel + num_input_audio_formats 10 + CombineArrays.Object.Base.input_audio_format [ + { + in_channels [ 1 ] + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + in_ch_map [ $CHANNEL_MAP_MONO ] + in_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + in_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + } + ] diff --git a/tools/topology/topology2/include/formats/compr_input_output_formats_src_s32_to_48k.conf b/tools/topology/topology2/include/formats/compr_input_output_formats_src_s32_to_48k.conf new file mode 100644 index 000000000000..836855126233 --- /dev/null +++ b/tools/topology/topology2/include/formats/compr_input_output_formats_src_s32_to_48k.conf @@ -0,0 +1,65 @@ + # Input and output audio formats for SRC + num_input_audio_formats 28 + CombineArrays.Object.Base.input_audio_format [ + { + in_channels [ 1 ] + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + in_ch_map [ $CHANNEL_MAP_MONO ] + in_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + in_rate [ + 8000 + 11025 + 12000 + 16000 + 22050 + 24000 + 32000 + 44100 + 48000 + 64000 + 88200 + 96000 + 176400 + 192000 + ] + in_bit_depth [ 32 ] + in_valid_bit_depth [ 32 ] + } + ] + + num_output_audio_formats 2 + Object.Base.output_audio_format [ + { + out_channels 1 + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_map $CHANNEL_MAP_MONO + out_ch_cfg $CHANNEL_CONFIG_MONO + } + { + out_channels 2 + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] diff --git a/tools/topology/topology2/include/formats/compr_output_audio_formats.conf b/tools/topology/topology2/include/formats/compr_output_audio_formats.conf new file mode 100644 index 000000000000..98d11fa51cbc --- /dev/null +++ b/tools/topology/topology2/include/formats/compr_output_audio_formats.conf @@ -0,0 +1,106 @@ + # Output audio formats for e.g. host-copier and decoder + num_output_audio_formats 40 + CombineArrays.Object.Base.output_audio_format [ + { + out_channels [ 1 ] + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 8 ] + out_valid_bit_depth [ 8 ] + out_sample_type [ $SAMPLE_TYPE_UNSIGNED_INTEGER ] + out_ch_map [ $CHANNEL_MAP_MONO ] + out_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + out_channels [ 1 ] + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_ch_map [ $CHANNEL_MAP_MONO ] + out_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + out_channels [ 1 ] + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 24 ] + out_ch_map [ $CHANNEL_MAP_MONO ] + out_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + out_channels [ 1 ] + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + out_ch_map [ $CHANNEL_MAP_MONO ] + out_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 8 ] + out_valid_bit_depth [ 8 ] + out_sample_type [ $SAMPLE_TYPE_UNSIGNED_INTEGER ] + } + { + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + } + { + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 24 ] + } + { + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + } + ] diff --git a/tools/topology/topology2/include/formats/compr_output_audio_formats_s32.conf b/tools/topology/topology2/include/formats/compr_output_audio_formats_s32.conf new file mode 100644 index 000000000000..e377afa38687 --- /dev/null +++ b/tools/topology/topology2/include/formats/compr_output_audio_formats_s32.conf @@ -0,0 +1,29 @@ + # Output audio formats e.g. module-copier + num_output_audio_formats 10 + CombineArrays.Object.Base.output_audio_format [ + { + out_channels [ 1 ] + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + out_ch_map [ $CHANNEL_MAP_MONO ] + out_ch_cfg [ $CHANNEL_CONFIG_MONO ] + } + { + out_rate [ + 8000 + 44100 + 48000 + 96000 + 192000 + ] + out_bit_depth [ 32 ] + out_valid_bit_depth [ 32 ] + } + ] diff --git a/tools/topology/topology2/include/formats/compr_output_audio_formats_s32_48k_stereo.conf b/tools/topology/topology2/include/formats/compr_output_audio_formats_s32_48k_stereo.conf new file mode 100644 index 000000000000..13ebd43e389d --- /dev/null +++ b/tools/topology/topology2/include/formats/compr_output_audio_formats_s32_48k_stereo.conf @@ -0,0 +1,10 @@ + # Micsel single format output + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels 2 + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] diff --git a/tools/topology/topology2/include/pipelines/cavs/compr-playback.conf b/tools/topology/topology2/include/pipelines/cavs/compr-playback.conf new file mode 100644 index 000000000000..a9cbdde992aa --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/compr-playback.conf @@ -0,0 +1,103 @@ +# +# FE playback pipeline: compr-playback +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.compr-playback.N.attribute_name" +# +# Usage: compr-playback pipeline object can be instantiated as: +# +# Object.Pipeline.compr-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/module-copier.conf> +<include/components/mixin.conf> +<include/components/pipeline.conf> +<include/components/gain.conf> +<include/components/decoder.conf> +<include/components/micsel.conf> +<include/components/src.conf> + +Class.Pipeline."compr-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # compr-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + node_type $HDA_HOST_OUTPUT_CLASS + num_output_pins 1 + deep_buffer_dma_ms $COMPR_DEEPBUFFER_MS + } + + decoder."1" { + scheduler_domain "DP" + } + + module-copier."2" {} + + src."1" {} + + micsel."1" {} + + gain."1" {} + + mixin."1" {} + + pipeline."1" { + priority 0 + # enable lp mode + lp_mode 1 + } + } + + Object.Base.route [ + { + source decoder.$index.1 + sink module-copier.$index.2 + } + { + source module-copier.$index.2 + sink src.$index.1 + } + { + source src.$index.1 + sink micsel.$index.1 + } + { + source micsel.$index.1 + sink gain.$index.1 + } + { + source gain.$index.1 + sink mixin.$index.1 + } + ] + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf b/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf new file mode 100644 index 000000000000..fb0440ed78fb --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf @@ -0,0 +1,104 @@ +# +# BE DAI copier pipeline +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.dai-copier-be.N.attribute_name" +# +# Usage: dai-copier-be pipeline object can be instantiated as: +# +# Object.Pipeline.dai-copier-be."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/pipeline.conf> + +Class.Pipeline."dai-copier-be" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_in + num_input_audio_formats 3 + num_output_audio_formats 3 + num_output_pins 1 + + 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 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + 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 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + + module-copier."2" { + num_input_audio_formats 1 + num_output_audio_formats 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."1" { + priority 0 + lp_mode 0 + } + } + + time_domain "timer" + dynamic_pipeline 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 new file mode 100644 index 000000000000..0f38da399467 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-eqiir-module-copier-capture.conf @@ -0,0 +1,162 @@ +# +# BE capture pipeline: dai-copier-eqiir-module-copier-capture +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.dai-copier-eqiir-module-copier-capture.N.attribute_name" +# +# Usage: dai-copier-eqiir-module-copier-capture pipeline object can be instantiated as: +# +# Object.Pipeline.dai-copier-eqiir-module-copier-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/controls/bytes.conf> +<include/components/eqiir.conf> +<include/components/pipeline.conf> + +Class.Pipeline."dai-copier-eqiir-module-copier-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # dai-copier-eqiir-module-copier-capture objects instantiated + # within the same alsaconf node must have unique pipeline_id + # attribute + # + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_out + num_input_audio_formats 2 + num_output_audio_formats 2 + num_output_pins 1 + + 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 + } + ] + + 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 + } + ] + } + + eqiir."1" { + num_input_audio_formats 2 + num_output_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 + } + ] + + 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 + } + ] + } + + module-copier."2" { + num_input_audio_formats 2 + num_output_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 + } + ] + + 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 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source eqiir.$index.1 + sink module-copier.$index.2 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-eqiir-module-copier-capture.conf b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-eqiir-module-copier-capture.conf new file mode 100644 index 000000000000..7c704065f580 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-eqiir-module-copier-capture.conf @@ -0,0 +1,200 @@ +# +# BE capture pipeline: dai-copier-gain-eqiir-module-copier-capture +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.dai-copier-gain-eqiir-module-copier-capture.N.attribute_name" +# +# Usage: dai-copier-gain-eqiir-module-copier-capture pipeline object can be instantiated as: +# +# Object.Pipeline.dai-copier-gain-eqiir-module-copier-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/controls/bytes.conf> +<include/components/eqiir.conf> +<include/components/pipeline.conf> + +Class.Pipeline."dai-copier-gain-eqiir-module-copier-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # dai-copier-gain-eqiir-module-copier-capture objects instantiated + # within the same alsaconf node must have unique pipeline_id + # attribute + # + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_out + num_input_audio_formats 2 + num_output_audio_formats 2 + num_output_pins 1 + + 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 + } + ] + + 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 + } + ] + } + + eqiir."1" { + num_input_audio_formats 2 + num_output_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 + } + ] + + 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 + } + ] + } + + gain."1" { + num_input_audio_formats 2 + num_input_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + + num_output_audio_formats 2 + num_output_pins 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + + module-copier."2" { + num_input_audio_formats 2 + num_output_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 + } + ] + + 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 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source eqiir.$index.1 + sink module-copier.$index.2 + } + route.2 { + source gain.$index.1 + sink eqiir.$index.1 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} 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 new file mode 100644 index 000000000000..4529d2b64059 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-mixin-capture.conf @@ -0,0 +1,102 @@ +# +# BE capture pipeline: dai-copier-gain-mixin-capture +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.dai-copier-gain-mixin-capture.N.attribute_name" +# +# Usage: dai-copier-gain-mixin-capture pipeline object can be instantiated as: +# +# Object.Pipeline.dai-copier-gain-mixin-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/mixin.conf> +<include/components/pipeline.conf> + +Class.Pipeline."dai-copier-gain-mixin-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # dai-copier-gain-mixin-capture objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_out + node_type $HDA_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_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 + } + ] + } + + mixin."1" {} + 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 gain.$index.1 + sink mixin.$index.1 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} 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 new file mode 100644 index 000000000000..46367c772321 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-module-copier-capture.conf @@ -0,0 +1,117 @@ +# +# BE capture pipeline: dai-copier-gain-module-copier-capture +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.dai-copier-gain-module-copier-capture.N.attribute_name" +# +# Usage: dai-copier-gain-module-copier-capture pipeline object can be instantiated as: +# +# Object.Pipeline.dai-copier-gain-module-copier-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/pipeline.conf> + +Class.Pipeline."dai-copier-gain-module-copier-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # dai-copier-gain-module-copier-capture objects instantiated + # within the same alsaconf node must have unique pipeline_id + # attribute + # + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_out + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_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 + } + ] + } + + module-copier."2" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + 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 gain.$index.1 + sink module-copier.$index.2 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf b/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf new file mode 100644 index 000000000000..91ca50a62bed --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf @@ -0,0 +1,137 @@ +# +# BE dai-kpb pipeline +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.dai-kpb-be.N.attribute_name" +# +# Usage: dai-kpb-be pipeline object can be instantiated as: +# +# Object.Pipeline.dai-kpb-be."N" { +# direction "playback" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/pipeline.conf> +<include/components/kpb.conf> + +Class.Pipeline."dai-kpb-be" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + # + # dai-kpb-be objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_in + node_type $HDA_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 3 + num_output_pins 1 + + 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 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + 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 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + + kpb."1" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate 16000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate 16000 + 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_rate 16000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate 16000 + 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 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route."1" { + source "dai-copier.DMIC.$index.1" + sink "kpb.$index.1" + } + } + + time_domain "timer" + dynamic_pipeline 1 +} diff --git a/tools/topology/topology2/include/pipelines/cavs/deepbuffer-capture.conf b/tools/topology/topology2/include/pipelines/cavs/deepbuffer-capture.conf new file mode 100644 index 000000000000..4fa8c82743aa --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/deepbuffer-capture.conf @@ -0,0 +1,111 @@ +# +# FE capture pipeline: deepbuffer-capture +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.deepbuffer-capture.N.attribute_name" +# +# Usage: deepbuffer-capture pipeline object can be instantiated as: +# +# Object.Pipeline.deepbuffer-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/pipeline.conf> + +Class.Pipeline."deepbuffer-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # deepbuffer-capture objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_out" + node_type $HDA_HOST_INPUT_CLASS + deep_buffer_dma_ms $DEEPBUFFER_FW_DMA_MS + num_input_pins 1 + num_input_audio_formats 2 + num_output_audio_formats 6 + # Input sample format is always 32-bit for capture + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + + pipeline."1" { + priority 0 + # enable lp mode + lp_mode 1 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf b/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf new file mode 100644 index 000000000000..d9ae0717bf1f --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf @@ -0,0 +1,111 @@ +# +# FE playback pipeline: deepbuffer-playback +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.deepbuffer-playback.N.attribute_name" +# +# Usage: deepbuffer-playback pipeline object can be instantiated as: +# +# Object.Pipeline.deepbuffer-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/mixin.conf> +<include/components/pipeline.conf> +<include/components/gain.conf> + +Class.Pipeline."deepbuffer-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # deepbuffer-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + node_type $HDA_HOST_OUTPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 1 + num_output_pins 1 + deep_buffer_dma_ms $DEEPBUFFER_FW_DMA_MS + 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 + } + ] + 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 + + 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 + } + ] + } + + mixin."1" {} + + pipeline."1" { + priority 0 + # enable lp mode + lp_mode 1 + } + } + + Object.Base.route [ + { + source gain.$index.1 + sink mixin.$index.1 + } + ] + + direction "playback" + 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 new file mode 100644 index 000000000000..b193524ebfbd --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/gain-copier-capture.conf @@ -0,0 +1,148 @@ +# +# CAVS gain (volume) capture pipeline +# +# A simple gain (volume) pipeline. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.gain-copier-capture.N.attribute_name". +# +# Usage: gain-copier-capture pipeline object can be instantiated as: +# +# Object.Pipeline.gain-copier-capture."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/gain.conf> +<include/components/pipeline.conf> + +Class.Pipeline."gain-copier-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # gain-copier-capture objects instantiated within the same + # alsaconf node must have unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_out" + num_input_audio_formats 1 + num_output_audio_formats 3 + num_input_pins 1 + + Object.Base.input_audio_format [ + # 32-bit 48KHz 2ch + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + node_type $HDA_HOST_INPUT_CLASS + } + + gain."1" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + #16-bit 48KHz 2ch + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + # 32-bit 48KHz 2ch + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + + module-copier."2" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + #16-bit 48KHz 2ch + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + # 32-bit 48KHz 2ch + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base.route [ + { + source "module-copier.$index.2" + sink "gain.$index.1" + } + ] + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf b/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf new file mode 100644 index 000000000000..9dfc7dab6693 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf @@ -0,0 +1,111 @@ +# +# mid-stream pipeline: gain-module-copier +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.gain-module-copier.N.attribute_name" +# +# Usage: gain-module-copier pipeline object can be instantiated as: +# +# Object.Pipeline.gain-module-copier."N" { +# direction "capture" +# period 1000 +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/pipeline.conf> + +Class.Pipeline."gain-module-copier" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !mandatory [ + "direction" + ] + + # + # dai-copier-gain-module-copier-capture objects instantiated + # within the same alsaconf node must have unique pipeline_id + # attribute + # + unique "instance" + } + + Object.Widget { + gain."1" { + num_input_audio_formats 2 + num_output_audio_formats 2 + + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + module-copier."1" { + num_input_audio_formats 2 + num_output_audio_formats 2 + + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source gain.$index.1 + sink module-copier.$index.1 + } + } + + 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..936d45c28c96 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/google-rtc-aec-capture.conf @@ -0,0 +1,140 @@ +# +# 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" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/dai-copier.conf> +<include/components/pipeline.conf> +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/google-rtc-aec.conf> +<include/controls/bytes.conf> + +Class.Pipeline."google-rtc-aec-capture" { + + <include/pipelines/pipeline-common.conf> + + 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 2 + num_output_audio_formats 2 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 4ch 32-bit on Pin 0 + { + input_pin_index 0 + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + + ] + } + + module-copier."2" { + period_sink_count 1 + period_source_count 1 + num_input_audio_formats 2 + num_output_audio_formats 2 + + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + Object.Base.output_audio_format [ + # 2ch 32-bit + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + # 4ch 32-bit + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + } + + 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" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf b/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf new file mode 100644 index 000000000000..f6e2e7852eed --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf @@ -0,0 +1,88 @@ +# +# BE DAI highpass pipeline for capture +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.highpass-be-capture.N.attribute_name" +# +# Usage: highpass-capture-be pipeline object can be instantiated as: +# +# Object.Pipeline.highpass-capture-be."N" { +# direction "capture" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/pipeline.conf> +<include/controls/bytes.conf> +<include/components/eqiir.conf> + +Class.Pipeline."highpass-capture-be" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_in + 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 + } + ] + } + + eqiir."1" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + } + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + time_domain "timer" + dynamic_pipeline 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 new file mode 100644 index 000000000000..d785ddb2a597 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-mixin-playback.conf @@ -0,0 +1,110 @@ +# +# FE playback pipeline: host-copier-gain-mixin-playback +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.host-copier-gain-mixin-playback.N.attribute_name" +# +# Usage: host-copier-gain-mixin-playback pipeline object can be instantiated as: +# +# Object.Pipeline.host-copier-gain-mixin-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/mixin.conf> +<include/components/pipeline.conf> +<include/components/gain.conf> + +Class.Pipeline."host-copier-gain-mixin-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # host-copier-gain-mixin-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + node_type $HDA_HOST_OUTPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 1 + num_output_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + 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 + } + ] + } + + mixin."1" {} + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base.route [ + { + source gain.$index.1 + sink mixin.$index.1 + } + ] + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} 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 new file mode 100644 index 000000000000..e38b2887b97a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-src-mixin-playback.conf @@ -0,0 +1,86 @@ +# +# FE playback pipeline: host-copier-gain-mixin-playback +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.host-copier-gain-src-mixin-playback.N.attribute_name" +# +# Usage: host-copier-gain-src-mixin-playback pipeline object can be instantiated as: +# +# Object.Pipeline.host-copier-gain-src-mixin-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/mixin.conf> +<include/components/pipeline.conf> +<include/components/gain.conf> +<include/components/src.conf> + +Class.Pipeline."host-copier-gain-src-mixin-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # host-copier-gain-src-mixin-playback objects instantiated within the same + # alsaconf node must have unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + node_type $HDA_HOST_OUTPUT_CLASS + num_output_pins 1 + + <include/components/src_format_sxx_to_s32_convert.conf> + } + + gain."1" { + <include/components/src_format_s32_passthrough.conf> + } + + src."1" { + rate_out 48000 + + <include/components/src_format_s32_convert_to_48k.conf> + } + + mixin."1" {} + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base.route [ + { + source gain.$index.1 + sink src.$index.1 + } + { + source src.$index.1 + sink mixin.$index.1 + } + ] + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/host-copier-micsel-gain-mixin-playback.conf b/tools/topology/topology2/include/pipelines/cavs/host-copier-micsel-gain-mixin-playback.conf new file mode 100644 index 000000000000..fcf0598c3e8d --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-copier-micsel-gain-mixin-playback.conf @@ -0,0 +1,359 @@ +# +# FE playback pipeline: host-copier-micsel-gain-mixin-playback +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.host-copier-micsel-gain-mixin-playback.N.attribute_name" +# +# Usage: host-copier-micsel-gain-mixin-playback pipeline object can be instantiated as: +# +# Object.Pipeline.host-copier-micsel-gain-mixin-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/micsel.conf> +<include/components/mixin.conf> +<include/components/pipeline.conf> +<include/components/gain.conf> + +Class.Pipeline."host-copier-micsel-gain-mixin-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # host-copier-micsel-gain-mixin-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + node_type $HDA_HOST_OUTPUT_CLASS + num_output_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 1 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 3 + out_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + out_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 5 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + out_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 6 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 8 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + + micsel."1" { + num_input_audio_formats 7 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 1 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 3 + in_ch_cfg $CHANNEL_CONFIG_2_POINT_1 + in_ch_map $CHANNEL_MAP_2_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 5 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_0 + in_ch_map $CHANNEL_MAP_5_POINT_0 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 6 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 8 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + ] + } + + 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 + } + ] + } + + mixin."1" {} + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base.route [ + { + source micsel.$index.1 + sink gain.$index.1 + } + { + source gain.$index.1 + sink mixin.$index.1 + } + ] + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf b/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf new file mode 100644 index 000000000000..c9a520f28b80 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf @@ -0,0 +1,109 @@ +# +# Host gateway capture pipeline +# +# A simple host gateway pipeline for capture. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.host-gateway-capture.N.attribute_name". +# +# Usage: host-gateway-capture pipeline object can be instantiated as: +# +# Object.Pipeline.host-gateway-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/pipeline.conf> + +Class.Pipeline."host-gateway-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # host-gateway-capture objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_out" + node_type $HDA_HOST_INPUT_CLASS + num_input_pins 1 + num_input_audio_formats 2 + num_output_audio_formats 6 + # Input sample format is always 32-bit for capture + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf b/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf new file mode 100644 index 000000000000..8954da0f5c9a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf @@ -0,0 +1,81 @@ +# +# Host gateway playback pipeline +# +# A simple host gateway pipeline for playback. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.host-gateway-playback.N.attribute_name" +# +# Usage: host-gateway-playback pipeline object can be instantiated as: +# +# Object.Pipeline.host-gateway-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/host-copier.conf> +<include/components/pipeline.conf> +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> + +Class.Pipeline."host-gateway-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # host-gateway-playback objects instantiated within the same alsaconf node must have + # unique instance attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + node_type $HDA_HOST_OUTPUT_CLASS + type "aif_in" + num_output_pins 1 + num_input_audio_formats 3 + num_output_audio_formats 1 + 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 + } + ] + # Output sample format is always 32-bit for playback + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/host-gateway-src-mfcc-capture.conf b/tools/topology/topology2/include/pipelines/cavs/host-gateway-src-mfcc-capture.conf new file mode 100644 index 000000000000..793f71b883ab --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-gateway-src-mfcc-capture.conf @@ -0,0 +1,134 @@ +# +# SRC-MFCC capture pipeline +# +# This class provides host pipeline for capture with MFCC audio features input. +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.host-gateway-src-mfcc-capture.N.attribute_name". +# +# Usage: host-gateway-src-mfcc-capture pipeline object can be instantiated as: +# +# Object.Pipeline.host-gateway-src-mfcc-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/pipeline.conf> +<include/components/host-copier.conf> +<include/components/src.conf> +<include/components/mfcc.conf> + +Class.Pipeline."host-gateway-src-mfcc-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + # + # host-gateway-src-mfcc-capture objects instantiated within the same alsaconf + # node must have unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + src."1" { + num_input_pins 1 + num_output_pins 1 + num_input_audio_formats 3 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 48000 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 96000 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 192000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + + mfcc."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + + host-copier."1" { + type "aif_out" + node_type $HDA_HOST_INPUT_CLASS + num_input_pins 1 + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_rate 16000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_rate 16000 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + + Object.Base { + !route [ + { + source src.$index.1 + sink mfcc.$index.1 + } + ] + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/host-gateway-tdfb-drc-capture.conf b/tools/topology/topology2/include/pipelines/cavs/host-gateway-tdfb-drc-capture.conf new file mode 100644 index 000000000000..c0912037a424 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/host-gateway-tdfb-drc-capture.conf @@ -0,0 +1,106 @@ +# +# Host gateway capture pipeline +# +# A host gateway pipeline for capture with TDFB and DRC processing. All attributes +# defined herein are namespaced by alsatplg to +# "Object.Pipeline.host-gateway-tdfb-drc-capture.N.attribute_name". +# +# Usage: host-gateway-tdfb-drc-capture pipeline object can be instantiated as: +# +# Object.Pipeline.host-gateway-tdfb-drc-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/drc.conf> +<include/components/tdfb.conf> +<include/pipelines/cavs/host-gateway-capture.conf> + +Class.Pipeline."host-gateway-tdfb-drc-capture" { + + SubTreeCopy.baseclass { + # this class extends the host-gateway-capture pipeline class. + source "Class.Pipeline.host-gateway-capture" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.host-gateway-tdfb-drc-capture {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + tdfb."1" { + Object.Control { + bytes."1" { + max 16384 + IncludeByKey.EFX_MIC_TDFB_PARAMS { + "line2_pass" "include/components/tdfb/line2_pass.conf" + "line2_generic_pm10deg" "include/components/tdfb/line2_generic_pm10deg_48khz.conf" + "line2_50mm" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + "line2_68mm" "include/components/tdfb/line2_68mm_pm0_30_90deg_48khz.conf" + "line2_74mm" "include/components/tdfb/line2_74mm_pm0_30_90deg_48khz.conf" + "line4_pass" "include/components/tdfb/line4_pass.conf" + "line4to2_pass" "include/components/tdfb/line4to2_pass.conf" + "line4_generic_pm10deg" "include/components/tdfb/line4_generic_pm10deg_48khz.conf" + "line4_28mm" "include/components/tdfb/line2_28mm_pm0_30_90deg_48khz.conf" + } + } + } + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + + drc."1" { + Object.Control { + bytes."1" { + IncludeByKey.EFX_MIC_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "dmic_default" "include/components/drc/dmic_default.conf" + } + } + } + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + } + + Object.Base { + !route [ + { + source tdfb.$index.1 + sink drc.$index.1 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf b/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf new file mode 100644 index 000000000000..465e524ee478 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf @@ -0,0 +1,65 @@ +# +# BE DAI passthrough pipeline for capture +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.passthrough-be-capture.N.attribute_name" +# +# Usage: io-gateway-capture pipeline object can be instantiated as: +# +# Object.Pipeline.io-gateway-capture."N" { +# direction "capture" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/pipeline.conf> + +Class.Pipeline."io-gateway-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_in + 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."1" { + priority 0 + lp_mode 0 + } + } + + time_domain "timer" + direction "capture" + dynamic_pipeline 1 +} diff --git a/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf b/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf new file mode 100644 index 000000000000..849dd63e9921 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf @@ -0,0 +1,92 @@ +# +# Just a Backend DAI +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.io-gateway.N.attribute_name" +# +# Usage: io-gateway pipeline object can be instantiated as: +# +# Object.Pipeline.io-gateway."N" { +# direction "playback" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/pipeline.conf> + +Class.Pipeline."io-gateway" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + # + # io-gateway objects instantiated within the same alsaconf node must have + # unique instance attribute + # + unique "instance" + } + + Object.Widget { + dai-copier."1" { + type dai_in + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 32-bit 48KHz 4ch + { + 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 3 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + # 32-bit 48KHz 4ch + { + 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 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + time_domain "timer" + dynamic_pipeline 1 +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-aria-gain-mixin-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-aria-gain-mixin-playback.conf new file mode 100644 index 000000000000..ec8bf0d8ae5a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-aria-gain-mixin-playback.conf @@ -0,0 +1,92 @@ +# +# BE playback pipeline: mixout-aria-gain-mixin. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-aria-gain-mixin-playback.N.attribute_name" +# +# Usage: mixout-aria-gain-mixin-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-aria-gain-mixin-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/mixin.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/aria.conf> +<include/components/pipeline.conf> + +Class.Pipeline."mixout-aria-gain-mixin-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-aria-gain-mixin-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + aria."1" {} + 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 + } + ] + } + mixin.1 {} + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source mixout.$index.1 + sink aria.$index.1 + } + route.2 { + source aria.$index.1 + sink gain.$index.1 + } + route.3 { + source gain.$index.1 + sink mixin.$index.1 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-dai-copier-playback.conf new file mode 100644 index 000000000000..d773ffb55957 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-dai-copier-playback.conf @@ -0,0 +1,75 @@ +# +# BE playback pipeline: mixout-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> + +Class.Pipeline."mixout-dai-copier-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-dai-copier-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + dai-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 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} 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..d98997136537 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf @@ -0,0 +1,105 @@ +# +# 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" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/alh-dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> + +Class.Pipeline."mixout-gain-alh-dai-copier-playback" { + + <include/pipelines/pipeline-common.conf> + + 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 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + 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 [ + { + source mixout.$index.1 + sink gain.$index.1 + } + ] + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-ctc-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-ctc-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..f8346454824d --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-ctc-alh-dai-copier-playback.conf @@ -0,0 +1,71 @@ +# +# BE playback pipeline: mixout-gain-ctc-alh-dai-copier. +# This pipeline is an extension of the mixout-gain-alh-dai-copier-playback pipeline class. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-ctc-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-ctc-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-ctc-alh-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/alh-dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> +<include/components/ctc.conf> +<platform/intel/efx-default.conf> +<include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf> + +Class.Pipeline."mixout-gain-ctc-alh-dai-copier-playback" { + SubTreeCopy.baseclass { + # this class extends the mixout-gain-alh-dai-copier-playback class definition + source "Class.Pipeline.mixout-gain-alh-dai-copier-playback" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-ctc-alh-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + ctc."1" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + } + + Object.Base { + ! route [ + { + source gain.$index.1 + sink ctc.$index.1 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-ctc-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-ctc-dai-copier-playback.conf new file mode 100644 index 000000000000..b95cde91f450 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-ctc-dai-copier-playback.conf @@ -0,0 +1,71 @@ +# +# BE playback pipeline: mixout-gain-ctc-dai-copier. +# This pipeline is an extension of the mixout-gain-dai-copier-playback pipeline class. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-ctc-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-ctc-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-ctc-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> +<include/components/ctc.conf> +<platform/intel/efx-default.conf> +<include/pipelines/cavs/mixout-gain-dai-copier-playback.conf> + +Class.Pipeline."mixout-gain-ctc-dai-copier-playback" { + SubTreeCopy.baseclass { + # this class extends the mixout-gain-dai-copier-playback class definition + source "Class.Pipeline.mixout-gain-dai-copier-playback" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-ctc-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + ctc."1" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + } + + Object.Base { + ! route [ + { + source gain.$index.1 + sink ctc.$index.1 + } + ] + } + } + } +} 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 new file mode 100644 index 000000000000..60d0fdc86cfc --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dai-copier-playback.conf @@ -0,0 +1,102 @@ +# +# BE playback pipeline: mixout-gain-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> + +Class.Pipeline."mixout-gain-dai-copier-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-dai-copier-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + dai-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 + + 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 [ + { + source mixout.$index.1 + sink gain.$index.1 + } + ] + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..71c367e48481 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-alh-dai-copier-playback.conf @@ -0,0 +1,130 @@ +# +# BE playback pipeline: mixout-gain-dax-alh-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-dax-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-dax-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-dax-alh-dai-copier-playback."N" { +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/alh-dai-copier.conf> +<include/components/dolby-dax.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> + +Class.Pipeline."mixout-gain-dax-alh-dai-copier-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-dax-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 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + 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 + } + ] + } + dolby-dax."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + ibs "$[(256 * ($[($in_bit_depth / 8)])) * ($in_channels)]" + } + ] + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + obs "$[(256 * ($[($out_bit_depth / 8)])) * ($out_channels)]" + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + !route [ + { + source gain.$index.1 + sink dolby-dax.$index.1 + } + { + source mixout.$index.1 + sink gain.$index.1 + } + ] + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-ctc-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-ctc-dai-copier-playback.conf new file mode 100644 index 000000000000..2353aa7af719 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-ctc-dai-copier-playback.conf @@ -0,0 +1,74 @@ +# +# BE playback pipeline: mixout-gain-dax-ctc-dai-copier-playback. +# + +<include/components/dolby-dax.conf> +<include/components/ctc.conf> +<include/pipelines/cavs/mixout-gain-dai-copier-playback.conf> + +Class.Pipeline."mixout-gain-dax-ctc-dai-copier-playback" { + SubTreeCopy.baseclass { + # this class extends the mixout-gain-dai-copier-playback class definition + source "Class.Pipeline.mixout-gain-dai-copier-playback" + + tree { + Object.Widget { + dolby-dax."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + ibs "$[(256 * ($[($in_bit_depth / 8)])) * ($in_channels)]" + } + ] + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + obs "$[(256 * ($[($out_bit_depth / 8)])) * ($out_channels)]" + } + ] + } + + ctc."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + ibs "$[(256 * ($[($in_bit_depth / 8)])) * ($in_channels)]" + } + ] + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + obs "$[(256 * ($[($out_bit_depth / 8)])) * ($out_channels)]" + } + ] + } + } + + Object.Base { + ! route [ + { + source gain.$index.1 + sink dolby-dax.$index.1 + } + { + source dolby-dax.$index.1 + sink ctc.$index.1 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-dai-copier-playback.conf new file mode 100644 index 000000000000..0f136364e3d5 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dax-dai-copier-playback.conf @@ -0,0 +1,58 @@ +# +# BE playback pipeline: mixout-gain-dax-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-dax-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-dax-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-dax-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/dolby-dax.conf> +<include/pipelines/cavs/mixout-gain-dai-copier-playback.conf> + +Class.Pipeline."mixout-gain-dax-dai-copier-playback" { + SubTreeCopy.baseclass { + # this class extends the mixout-gain-dai-copier-playback pipeline class. + source "Class.Pipeline.mixout-gain-dai-copier-playback" + tree { + Object.Widget { + dolby-dax."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + ibs "$[(256 * ($[($in_bit_depth / 8)])) * ($in_channels)]" + } + ] + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + obs "$[(256 * ($[($out_bit_depth / 8)])) * ($out_channels)]" + } + ] + } + } + + Object.Base { + !route [ + { + source gain.$index.1 + sink dolby-dax.$index.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 new file mode 100644 index 000000000000..9fd3e3239af2 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-dai-copier-playback.conf @@ -0,0 +1,74 @@ +# +# BE playback pipeline: mixout-gain-efx-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-efx-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-efx-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-efx-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/drc.conf> +<platform/intel/efx-default.conf> +<include/pipelines/cavs/mixout-gain-eqiir-eqfir-playback.conf> + +Class.Pipeline."mixout-gain-efx-dai-copier-playback" { + + SubTreeCopy.baseclass { + # this class extends the mixout-gain-eqiir-eqfir pipeline class. + source "Class.Pipeline.mixout-gain-eqiir-eqfir" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-efx-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + drc."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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "default" "include/components/drc/default.conf" + "enabled" "include/components/drc/enabled.conf" + } + } + } + } + + Object.Base { + !route [ + { + source eqfir.$index.1 + sink drc.$index.1 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-mbdrc-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-mbdrc-dai-copier-playback.conf new file mode 100644 index 000000000000..5e0d28dc3a7a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-mbdrc-dai-copier-playback.conf @@ -0,0 +1,70 @@ +# +# BE playback pipeline: mixout-gain-efx-mbdrc-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-efx-mbdrc-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-efx-mbdrc-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-efx-mbdrc-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/multiband_drc.conf> +<platform/intel/efx-default.conf> +<include/pipelines/cavs/mixout-gain-eqiir-eqfir-playback.conf> + +# this class extends the widgets and overrides the routes in mixout-gain-eqiir-eqfir pipeline class. +Class.Pipeline."mixout-gain-efx-mbdrc-dai-copier-playback" { + + # extend the base class with the new widget + SubTreeCopy.baseclass { + source "Class.Pipeline.mixout-gain-eqiir-eqfir" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-efx-mbdrc-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget.multiband_drc."1" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_MBDRC_PARAMS { + "passthrough" "include/components/multiband_drc/passthrough.conf" + "default" "include/components/multiband_drc/default.conf" + } + } + } + Object.Base { + !route [ + { + source eqfir.$index.1 + sink multiband_drc.$index.1 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-dts-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-dts-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..a34659b0fdfe --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-dts-alh-dai-copier-playback.conf @@ -0,0 +1,156 @@ +# +# BE playback pipeline: mixout-gain-eqiir-dts-alh-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-eqiir-dts-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-eqiir-dts-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-eqiir-dts-alh-dai-copier-playback."N" { +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/alh-dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> +<include/controls/bytes.conf> +<include/components/eqiir.conf> +<include/components/dts.conf> + +Class.Pipeline."mixout-gain-eqiir-dts-alh-dai-copier-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-eqiir-dts-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 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + 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 + } + ] + } + + eqiir."1" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/flat.conf> + } + } + + dts."1" { + num_input_audio_formats 1 + num_output_audio_formats 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."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + !route [ + { + source mixout.$index.1 + sink gain.$index.1 + } + { + source gain.$index.1 + sink eqiir.$index.1 + } + { + source eqiir.$index.1 + sink dts.$index.1 + } + ] + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-dts-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-dts-dai-copier-playback.conf new file mode 100644 index 000000000000..4c1836e849ca --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-dts-dai-copier-playback.conf @@ -0,0 +1,152 @@ +# +# BE playback pipeline: mixout-gain-eqiir-dts-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-eqiir-dts-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-eqiir-dts-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-eqiir-dts-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> +<include/controls/bytes.conf> +<include/components/eqiir.conf> +<include/components/dts.conf> + +Class.Pipeline."mixout-gain-eqiir-dts-dai-copier-playback" { + + DefineAttribute."index" {} + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-dts-dai-copier-playback objects instantiated within the same alsaconf node must have + # unique instance attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + dai-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 + } + ] + } + eqiir."1" { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/flat.conf> + } + } + dts."1" { + num_input_audio_formats 1 + num_output_audio_formats 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."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source mixout..1 + sink gain..1 + } + route.2 { + source gain..1 + sink eqiir..1 + } + route.3 { + source eqiir..1 + sink dts..1 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..47d0aeb7a210 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback.conf @@ -0,0 +1,137 @@ +# +# BE playback pipeline: mixout-gain-eqiir-eqfir-drc-alh-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback."N" { +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + + +<include/components/eqiir.conf> +<include/components/eqfir.conf> +<include/components/drc.conf> +<include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf> + +Class.Pipeline."mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback" { + + SubTreeCopy.baseclass { + # this class extends the mixout-gain-alh-dai-copier-playback pipeline class. + source "Class.Pipeline.mixout-gain-alh-dai-copier-playback" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + eqiir."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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_SPK_IIR_PARAMS { + "passthrough" "include/components/eqiir/passthrough.conf" + "highpass_20hz_0db_48khz" "include/components/eqiir/highpass_20hz_0db_48khz.conf" + "highpass_30hz_0db_48khz" "include/components/eqiir/highpass_30hz_0db_48khz.conf" + "highpass_40hz_0db_48khz" "include/components/eqiir/highpass_40hz_0db_48khz.conf" + "highpass_50hz_0db_48khz" "include/components/eqiir/highpass_50hz_0db_48khz.conf" + "highpass_100hz_0db_48khz" "include/components/eqiir/highpass_100hz_0db_48khz.conf" + } + } + } + + eqfir."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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_SPK_FIR_PARAMS { + "passthrough" "include/components/eqfir/passthrough.conf" + } + } + } + + drc."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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_SPK_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "speaker_default" "include/components/drc/speaker_default.conf" + } + } + } + } + + Object.Base { + !route [ + { + source gain.$index.1 + sink eqiir.$index.1 + } + { + source eqiir.$index.1 + sink eqfir.$index.1 + } + { + source eqfir.$index.1 + sink drc.$index.1 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..cc95dd9799a7 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback.conf @@ -0,0 +1,132 @@ +# +# BE playback pipeline: mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback."N" { +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/pipelines/cavs/mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback.conf> +<include/components/micsel.conf> + +Class.Pipeline."mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback" { + + SubTreeCopy.baseclass { + # this class extends the pipeline class. + source "Class.Pipeline.mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + micsel."1" { + 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_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control { + bytes."1" { + IncludeByKey.SDW_AMP_XOVER_SELECTOR_PARAMS { + "default" "include/components/micsel/passthrough.conf" + "xover_selector_lr_to_llrr" "include/components/micsel/xover_selector_lr_to_llrr.conf" + "xover_selector_lr_to_lrlr" "include/components/micsel/xover_selector_lr_to_lrlr.conf" + } + } + } + } + + eqiir."2" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + IncludeByKey.SDW_AMP_XOVER_EQIIR_PARAMS { + "default" "include/components/eqiir/passthrough.conf" + "xover_lr4_2000hz_lhlh_48khz" "include/components/eqiir/xover_lr4_2000hz_lhlh_48khz.conf" + "xover_lr4_2000hz_llhh_48khz" "include/components/eqiir/xover_lr4_2000hz_llhh_48khz.conf" + "xover_lr4_2000hz_hhll_48khz" "include/components/eqiir/xover_lr4_2000hz_hhll_48khz.conf" + } + } + } + eqfir."2" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + IncludeByKey.SDW_AMP_XOVER_EQFIR_PARAMS { + "default" "include/components/eqfir/passthrough.conf" + "xover_dd00_100us_48khz.conf" "include/components/eqfir/xover_dd00_100us_48khz.conf" + "xover_00dd_100us_48khz.conf" "include/components/eqfir/xover_00dd_100us_48khz.conf" + } + } + } + } + + Object.Base { + !route [ + { + source drc.$index.1 + sink micsel.$index.1 + } + { + source micsel.$index.1 + sink eqiir.$index.2 + } + { + source eqiir.$index.2 + sink eqfir.$index.2 + } + ] + } + } + } +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-playback.conf new file mode 100644 index 000000000000..22562b87b646 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-eqiir-eqfir-playback.conf @@ -0,0 +1,102 @@ +# +# BE playback pipeline: mixout-gain-eqiir-eqfir. +# This pipeline is an extension of the mixout-gain-dai-copier-playback pipeline class +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-eqiir-eqfir.N.attribute_name" +# +# Usage: mixout-gain-efx-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-eqiir-eqfir."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/components/eqiir.conf> +<include/components/eqfir.conf> +<platform/intel/efx-default.conf> +<include/pipelines/cavs/mixout-gain-dai-copier-playback.conf> + +Class.Pipeline."mixout-gain-eqiir-eqfir" { + SubTreeCopy.baseclass { + + # this class extends the mixout-gain-dai-copier-playback class definition + source "Class.Pipeline.mixout-gain-dai-copier-playback" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-eqiir-eqfir {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + eqiir."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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_IIR_PARAMS { + "passthrough" "include/components/eqiir/passthrough.conf" + } + } + } + eqfir."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 + } + ] + + Object.Control.bytes."1" { + IncludeByKey.EFX_FIR_PARAMS { + "passthrough" "include/components/eqfir/passthrough.conf" + } + } + } + } + + Object.Base { + !route [ + { + source gain.$index.1 + sink eqiir.$index.1 + } + { + source eqiir.$index.1 + sink eqfir.$index.1 + } + ] + } + } + } +} 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 new file mode 100644 index 000000000000..ab18e5b48fda --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-host-copier-capture.conf @@ -0,0 +1,120 @@ +# +# FE capture pipeline: mixout-gain-host-copier-capture +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-host-copier-capture.N.attribute_name" +# +# Usage: mixout-gain-host-copier-capture pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-host-copier-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> +<include/components/gain.conf> + +Class.Pipeline."mixout-gain-host-copier-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-host-copier-capture objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + + host-copier."1" { + type "aif_out" + node_type $HDA_HOST_INPUT_CLASS + num_input_audio_formats 2 + num_output_audio_formats 3 + num_input_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + + gain."1"{ + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base.route [ + { + 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/mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..a12503d5d83a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback.conf @@ -0,0 +1,132 @@ +# +# BE playback pipeline: mixout-gain-micsel-eqiir-eqfir-alh-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback."N" { +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf> +<include/components/micsel.conf> + +Class.Pipeline."mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback" { + + SubTreeCopy.baseclass { + # this class extends the pipeline class. + source "Class.Pipeline.mixout-gain-alh-dai-copier-playback" + + # target node is not defined which means that the new subtree will be copied to + # the parent node containing the SubTreeCopy node i.e in this case the + # Class.Pipeline.mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback {} node. + + # default copy type is to extend the base class ie the widgets and routes + # will be added to the existing list of widgets/routes in the base class + + tree { + Object.Widget { + micsel."1" { + 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_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control { + bytes."1" { + IncludeByKey.SDW_AMP_XOVER_SELECTOR_PARAMS { + "default" "include/components/micsel/passthrough.conf" + "xover_selector_lr_to_llrr" "include/components/micsel/xover_selector_lr_to_llrr.conf" + "xover_selector_lr_to_lrlr" "include/components/micsel/xover_selector_lr_to_lrlr.conf" + } + } + } + } + + eqiir."2" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + IncludeByKey.SDW_AMP_XOVER_EQIIR_PARAMS { + "default" "include/components/eqiir/passthrough.conf" + "xover_lr4_2000hz_lhlh_48khz" "include/components/eqiir/xover_lr4_2000hz_lhlh_48khz.conf" + "xover_lr4_2000hz_llhh_48khz" "include/components/eqiir/xover_lr4_2000hz_llhh_48khz.conf" + "xover_lr4_2000hz_hhll_48khz" "include/components/eqiir/xover_lr4_2000hz_hhll_48khz.conf" + } + } + } + eqfir."2" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + IncludeByKey.SDW_AMP_XOVER_EQFIR_PARAMS { + "default" "include/components/eqfir/passthrough.conf" + "xover_dd00_100us_48khz.conf" "include/components/eqfir/xover_dd00_100us_48khz.conf" + "xover_00dd_100us_48khz.conf" "include/components/eqfir/xover_00dd_100us_48khz.conf" + } + } + } + } + + Object.Base { + !route [ + { + source gain.$index.1 + sink micsel.$index.1 + } + { + source micsel.$index.1 + sink eqiir.$index.2 + } + { + source eqiir.$index.2 + sink eqfir.$index.2 + } + ] + } + } + } +} 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 new file mode 100644 index 000000000000..e60243258fe5 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-smart-amp-dai-copier-playback.conf @@ -0,0 +1,132 @@ +# +# BE playback pipeline: mixout-gain-smart-amp-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-smart-amp-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-smart-amp-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-smart-amp-dai-copier-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/gain.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> +<include/components/smart_amp.conf> + +Class.Pipeline."mixout-gain-smart-amp-dai-copier-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-smart-amp-dai-copier-playback objects instantiated within the same + # alsaconf node must have unique instance attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + dai-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 + } + ] + } + + smart_amp."1" { + num_input_audio_formats 2 + num_output_audio_formats 1 + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + input_pin_index 0 + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + input_pin_index 1 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + output_pin_index 0 + 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 + } + + route.2 { + source gain.$index.1 + sink smart_amp.$index.1 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-mixin.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-mixin.conf new file mode 100644 index 000000000000..bf04d339447a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-mixin.conf @@ -0,0 +1,59 @@ +# mid-stream pipeline: mixout-mixin. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-mixin.N.attribute_name" +# +# Usage: mixout-mixin pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-mixin."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. + +<include/components/mixin.conf> +<include/components/mixout.conf> +<include/components/pipeline.conf> + +Class.Pipeline."mixout-mixin" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !mandatory [ + "direction" + ] + + # + # mixout-mixin objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + mixout.1 {} + mixin.1 {} + + pipeline.1 { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source mixout..1 + sink mixin..1 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/siggen-host-copier-capture.conf b/tools/topology/topology2/include/pipelines/cavs/siggen-host-copier-capture.conf new file mode 100644 index 000000000000..26de0b1766f0 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/siggen-host-copier-capture.conf @@ -0,0 +1,98 @@ +# +# Siggen capture pipeline +# +# This class provides host pipeline for capture with siggen input. All +# attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.siggen-host-copier-capture.N.attribute_name". +# +# Usage: siggen-host-copier-capture pipeline object can be instantiated as: +# +# Object.Pipeline.siggen-host-copier-capture."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/pipeline.conf> +<include/components/host-copier.conf> +<include/components/siggen.conf> + +Class.Pipeline."siggen-host-copier-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + # + # siggen-host-copier-capture objects instantiated within the same alsaconf + # node must have unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + siggen."1" { + num_input_pins 1 + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + + host-copier."1" { + type "aif_out" + node_type $HDA_HOST_INPUT_CLASS + num_input_pins 1 + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + 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 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} 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 new file mode 100644 index 000000000000..45f9e3d130c1 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/src-gain-mixin-playback.conf @@ -0,0 +1,112 @@ +# +# src gain (volume) playback pipeline +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.src-gain-mixin-playback.N.attribute_name" +# +# Usage: src-gain-mixin-playback pipeline object can be instantiated as: +# +# Object.Pipeline.src-gain-mixin-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/gain.conf> +<include/components/mixin.conf> +<include/components/src.conf> +<include/components/pipeline.conf> + +Class.Pipeline."src-gain-mixin-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + num_output_pins 1 + + <include/components/src_format_sxx_to_s32_convert.conf> + + node_type $HDA_HOST_OUTPUT_CLASS + } + + src."1" { + rate_out 48000 + + <include/components/src_format_s32_convert_to_48k.conf> + } + + gain."1" { + num_input_audio_formats 3 + num_output_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 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + ] + + } + + mixin."1" { } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base.route [ + { + source "src.$index.1" + sink "gain.$index.1" + } + { + source "gain.$index.1" + sink "mixin.$index.1" + } + ] + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/cavs/wov-detect.conf b/tools/topology/topology2/include/pipelines/cavs/wov-detect.conf new file mode 100644 index 000000000000..0f4490525c83 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/wov-detect.conf @@ -0,0 +1,127 @@ +# +# wov detection pipeline +# +# A wov detection pipeline. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.wov-detect.N.attribute_name". +# +# Usage: wov-detect pipeline object can be instantiated as: +# +# Object.Pipeline.wov-detect."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/dai-copier.conf> +<include/components/micsel.conf> +<include/components/wov.conf> +<include/components/pipeline.conf> +<include/controls/bytes.conf> + +Class.Pipeline."wov-detect" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !mandatory [ + "format" + ] + + !immutable [ + "direction" + ] + + # + # wov-detect objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + + # virtual widget is only used in driver to connect wov widget + # to the host copier. The virtual widget does not exist in + # the firmware. + virtual."1" { + name "virtual.detect_sink" + type out_drv + } + + micsel."1" { + Object.Base.input_audio_format [ + { + in_rate 16000 + in_channels 2 + in_ch_map $CHANNEL_MAP_STEREO + in_ch_cfg 1 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate 16000 + out_channels 1 + out_ch_map $CHANNEL_MAP_MONO + out_ch_cfg 0 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + wov."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 16000 + in_channels 1 + in_ch_cfg 0 + in_ch_map $CHANNEL_MAP_MONO + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate 16000 + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route."1" { + source "micsel.$index.1" + sink "wov.$index.1" + } + + route."2" { + source "wov.$index.1" + sink "virtual.detect_sink" + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/eq-iir-volume-capture.conf b/tools/topology/topology2/include/pipelines/eq-iir-volume-capture.conf new file mode 100644 index 000000000000..ce381181b9c8 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/eq-iir-volume-capture.conf @@ -0,0 +1,122 @@ +# +# Volume capture pipeline with Highpass EQ IIR +# +# Capture pipeline with a EQ IIR filter. All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.eq-iir-volume--capture.attribute_name" +# +# Usage: this component can be used by declaring in the top-level topology conf file as follows: +# +# Object.Pipeline.eq-iir-volume--capture."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# Where N is a unique integer for pipeline ID in the same alsaconf node. +# + +# +# (source) host.N.capture <- buffer.N.1 <- volume.N.1 <- buffer.N.2 <- eqiir.N.1 <- buffer.N.3 (source endpoint) +# + +<include/common/route.conf> +<include/components/buffer.conf> +<include/components/eqiir.conf> +<include/components/host.conf> +<include/components/pipeline.conf> +<include/components/volume.conf> +<include/controls/bytes.conf> + +Class.Pipeline."eq-iir-volume-capture" { + # Include common pipeline attribute definitions + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + !mandatory [ + "format" + ] + !immutable [ + "direction" + ] + unique "instance" + } + + Object.Widget { + pipeline."1" {} + + host."capture" { + type "aif_out" + } + + buffer."1" { + periods 2 + caps "host" + } + + pga."1" { + # set TLV scale for volume control mixer + Object.Control.mixer."1" { + Object.Base.tlv."vtlv_m50s1" { + Object.Base.scale."m50s1" { + min -5000 + step 100 + } + } + } + } + + buffer."2" { + periods 2 + caps "host" + } + + eqiir."1" { + # byte control for EQ IIR + Object.Control.bytes."1" {} + } + + buffer."3" { + periods 2 + caps "dai" + } + } + + # Pipeline connections + Object.Base { + route."1" { + source buffer.$index.1 + sink host.$index.capture + } + + route."2" { + source pga.$index.1 + sink buffer.$index.1 + } + + route."3" { + source buffer.$index.2 + sink pga.$index.1 + } + + route."4" { + source eqiir.$index.1 + sink buffer.$index.2 + } + + route."5" { + source buffer.$index.3 + sink eqiir.$index.1 + } + } + + direction "capture" + time_domain "timer" + period 1000 + priority 0 + core 0 + frames 0 + mips 5000 +} diff --git a/tools/topology/topology2/include/pipelines/gain-capture.conf b/tools/topology/topology2/include/pipelines/gain-capture.conf new file mode 100644 index 000000000000..1255e02026fb --- /dev/null +++ b/tools/topology/topology2/include/pipelines/gain-capture.conf @@ -0,0 +1,225 @@ +# +# Generic gain (volume) capture pipeline +# +# A simple gain (volume) pipeline. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.gain-capture.N.attribute_name". +# +# Usage: gain-capture pipeline object can be instantiated as: +# +# Object.Pipeline.gain-capture."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/gain.conf> +<include/components/pipeline.conf> + +Class.Pipeline."gain-capture" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # gain-capture objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_out" + num_input_audio_formats 2 + num_input_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + + num_output_audio_formats 6 + num_output_pins 1 + 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 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + + node_type $HDA_HOST_INPUT_CLASS + } + + gain."1" { + num_input_audio_formats 4 + num_input_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + + num_output_audio_formats 4 + num_output_pins 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + + module-copier."2" { + num_input_audio_formats 4 + num_input_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 16 + in_valid_bit_depth 16 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 4 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + + num_output_audio_formats 4 + num_output_pins 1 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 16 + out_valid_bit_depth 16 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 4 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/gain-playback.conf b/tools/topology/topology2/include/pipelines/gain-playback.conf new file mode 100644 index 000000000000..425eedcecdc6 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/gain-playback.conf @@ -0,0 +1,106 @@ +# +# Generic gain (volume) playback pipeline +# +# A simple gain (volume) pipeline. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.gain-playback.N.attribute_name" +# +# Usage: gain-playback pipeline object can be instantiated as: +# +# Object.Pipeline.gain-playback."N" { +# period 1000 +# time_domain "timer" +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + +<include/common/input_audio_format.conf> +<include/common/output_audio_format.conf> +<include/components/host-copier.conf> +<include/components/gain.conf> +<include/components/pipeline.conf> + +Class.Pipeline."gain-playback" { + + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # gain-playback objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + host-copier."1" { + type "aif_in" + num_input_audio_formats 3 + num_output_audio_formats 1 + num_output_pins 1 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + node_type $HDA_HOST_OUTPUT_CLASS + } + + gain."1" { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" +} diff --git a/tools/topology/topology2/include/pipelines/passthrough-capture.conf b/tools/topology/topology2/include/pipelines/passthrough-capture.conf new file mode 100644 index 000000000000..e0405178887a --- /dev/null +++ b/tools/topology/topology2/include/pipelines/passthrough-capture.conf @@ -0,0 +1,74 @@ +# +# Volume capture pipeline +# +# A simple pipeline. All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.passthrough-capture.N.attribute_name" +# +# Usage: this component can be used by declaring in the top-level topology conf file as follows: +# +# Object.passthrough-capture."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# and N is the unique pipeline_id for this pipeline object within the same alsaconf node. +# +# +# (sink) host.N.capture <- buffer.N.1 (source endpoint) +# + +<include/common/route.conf> +<include/components/buffer.conf> +<include/components/host.conf> +<include/components/pipeline.conf> + +Class.Pipeline."passthrough-capture" { + # Include common pipeline attribute definitions + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + !immutable [ + "direction" + ] + # + # passthrough-capture pipeline objects instantiated within the same alsaconf node must have + # unique index attribute + # + unique "instance" + } + + Object.Widget { + pipeline."1" {} + + host."capture" { + type "aif_out" + } + + buffer."1" { + periods 2 + caps "pass" + } + } + + # Pipeline connections + Object.Base { + route."1" { + source "buffer.$index.1" + sink "host.$index.capture" + } + } + + # Default attribute values + format "s32le" + direction "capture" + time_domain "timer" + period 1000 + priority 0 + core 0 + frames 0 + mips 5000 +} diff --git a/tools/topology/topology2/include/pipelines/pipeline-common.conf b/tools/topology/topology2/include/pipelines/pipeline-common.conf new file mode 100644 index 000000000000..37a34066d4df --- /dev/null +++ b/tools/topology/topology2/include/pipelines/pipeline-common.conf @@ -0,0 +1,86 @@ +# +# Common pipeline definitions. To be included in Class.Pipeline definitions +# + +# pipeline instance of same pipeline class +DefineAttribute."instance" {} + +# pipeline ID +DefineAttribute."index" {} + +# Number of channels +DefineAttribute."channels" { + constraints { + min 2 + max 8 + } +} + +# Pipeline format +DefineAttribute."format" { + type "string" + constraints { + !valid_values [ + "s32le" + "s24le" + "s16le" + "float" + ] + } +} + +# Pipeline direction +DefineAttribute."direction" { + type "string" + constraints { + !valid_values [ + "playback" + "capture" + ] + } +} + +# Scheduling period +DefineAttribute."period" { + # Token reference and type + token_ref "scheduler.word" + constraints { + min 333 + max 1000 + } +} + +# Scheduler time domain. The value provided will be translated to 0/1 based on +# scheduler_time_domain. For example: value "timer" will be converted to 1. +DefineAttribute."time_domain" { + # Token reference and type + type "string" + token_ref "scheduler.word" + constraints { + # Acceptable values for time_domain + !valid_values [ + "dma" + "timer" + ] + !tuple_values [ + 0 + 1 + ] + } +} + +# flag to indicate if the pipeline is dynamic +DefineAttribute."dynamic_pipeline" {} + +# Skip setting up the pipeline in the DSP when use_chain_dma is set. +DefineAttribute."use_chain_dma" { + type "string" + constraints { + !valid_values [ + "true" + "false" + ] + } +} + +DefineAttribute."core_id" {} diff --git a/tools/topology/topology2/include/pipelines/volume-capture.conf b/tools/topology/topology2/include/pipelines/volume-capture.conf new file mode 100644 index 000000000000..4f11182fe344 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/volume-capture.conf @@ -0,0 +1,106 @@ +# +# Volume capture pipeline +# +# A simple pipeline. All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.volume-capture.N.attribute_name" +# +# Usage: this component can be used by declaring in the top-level topology conf file as follows: +# +# Object.Pipeline.volume-capture."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# and N is the unique pipeline_id for this pipeline object within the same alsaconf node. +# +# +# (sink) host.N.capture <- buffer.N.1 <- volume.N.1 <- buffer.N.2 (source endpoint) +# + +<include/common/route.conf> +<include/components/buffer.conf> +<include/components/host.conf> +<include/components/pipeline.conf> +<include/components/volume.conf> + +Class.Pipeline."volume-capture" { + # include common pipeline attribute definitions + <include/pipelines/pipeline-common.conf> + + attributes { + # pipeline name is constructed as "volume-capture.1" + !constructor [ + "index" + ] + !mandatory [ + "format" + ] + !immutable [ + "direction" + ] + # + # volume-capture objects instantiated within the same alsaconf node must have + # unique index attribute + # + unique "instance" + } + + Object.Widget { + pipeline."1" {} + + host."capture" { + type "aif_out" + } + + buffer."1" { + periods 2 + caps "host" + } + + pga."1" { + ramp_step_ms 250 + + Object.Control.mixer.1 { + Object.Base.tlv."vtlv_m50s1" { + Object.Base.scale."m50s1" { + min -5000 + step 100 + } + } + } + } + + buffer."2" { + periods 2 + caps "dai" + } + } + + # Pipeline connections + Object.Base { + route."1" { + source "buffer.$index.1" + sink "host.$index.capture" + } + + route."2" { + source "pga.$index.1" + sink "buffer.$index.1" + } + + route."3" { + source "buffer.$index.2" + sink "pga.$index.1" + } + } + + # Default attribute values + direction "capture" + time_domain "timer" + period 1000 + priority 0 + core 0 + frames 0 + mips 5000 +} diff --git a/tools/topology/topology2/include/pipelines/volume-demux-playback.conf b/tools/topology/topology2/include/pipelines/volume-demux-playback.conf new file mode 100644 index 000000000000..595827b662ed --- /dev/null +++ b/tools/topology/topology2/include/pipelines/volume-demux-playback.conf @@ -0,0 +1,122 @@ +# +# Low Latency playback pipeline with demux and volume. +# +# All attributes defined herein are namespaced by alsatplg to +# "Object.Pipeline.volume-demux-playback.N.attribute_name" +# +# Usage: this component can be used by declaring in the top-level topology conf file as follows: +# +# Object.Pipeline.volume-demux-playback."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# } +# +# Where N is a unique integer for pipeline ID in the same alsaconf node. +# + +# +# (source) host.N.playback -> buffer.N.1 -> volume.N.1 -> buffer.N.2 -> muxdemux.N.1 -> buffer.N.3 (sink endpoint) +# + +<include/common/route.conf> +<include/components/buffer.conf> +<include/components/host.conf> +<include/components/muxdemux.conf> +<include/components/pipeline.conf> +<include/components/volume.conf> +<include/controls/bytes.conf> + +Class.Pipeline."volume-demux-playback" { + # Include common pipeline attribute definitions + <include/pipelines/pipeline-common.conf> + + attributes { + !constructor [ + "index" + ] + !mandatory [ + "channels" + ] + !immutable [ + "direction" + ] + unique "instance" + } + + Object.Widget { + pipeline."1" {} + + host."playback" { + type "aif_in" + } + + buffer."1" { + periods 2 + caps "host" + } + + pga."1" { + # set TLV scale for volume control mixer + Object.Control.mixer."1" { + Object.Base.tlv."vtlv_m64s2" { + Object.Base.scale."m64s2" {} + } + } + } + + buffer."2" { + periods 2 + caps "comp" + } + + muxdemux."1" { + # byte control for muxemux widget + Object.Control.bytes."0" { + max 304 + } + } + + buffer."3" { + periods 2 + caps "comp" + } + } + + # Pipeline connections + Object.Base { + route."1" { + sink buffer.$index.1 + source host.$index.playback + } + + route."2" { + sink pga.$index.1 + source buffer.$index.1 + } + + route."3" { + sink buffer.$index.2 + source pga.$index.1 + } + + route."4" { + sink muxdemux.$index.1 + source buffer.$index.2 + } + + route."5" { + sink buffer.$index.3 + source muxdemux.$index.1 + } + } + + # default attribute values for volume-demux-playback pipeline + direction "playback" + time_domain "timer" + period 1000 + priority 0 + core 0 + frames 0 + mips 5000 +} diff --git a/tools/topology/topology2/include/pipelines/volume-playback.conf b/tools/topology/topology2/include/pipelines/volume-playback.conf new file mode 100644 index 000000000000..b4ca2646b0a8 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/volume-playback.conf @@ -0,0 +1,107 @@ +## \struct volume_playback +## \brief Volume playback pipeline +## +## \par Instantiating volume-playback pipeline +## +## A simple pipeline. All attributes defined herein are namespaced by alsatplg +## to "Object.Pipeline.volume-playback.N.attribute_name" +## +## Usage: this component can be used by declaring in the top-level topology conf file as follows: +## +## Object.Pipeline.volume-playback."N" { +## format "s16le" +## period 1000 +## time_domain "timer" +## } +## +## where N is the unique pipeline_id for this pipeline object within the same alsaconf node. +## +## +## (source) host.N.playback -> buffer.N.1 -> volume.N.1 -> buffer.N.2 (sink endpoint) +## + +<include/common/route.conf> +<include/components/buffer.conf> +<include/components/host.conf> +<include/components/pipeline.conf> +<include/components/volume.conf> + +Class.Pipeline."volume-playback" { + # include common pipeline attribute definitions + <include/pipelines/pipeline-common.conf> + + attributes { + ## pipeline name is constructed as "volume-playback.1" + !constructor [ + "index" + ] + !mandatory [ + "format" + ] + !immutable [ + "direction" + ] + # + # volume-playback objects instantiated within the same alsaconf node must have + # unique index attribute + # + unique "instance" + } + + Object.Widget { + ## The pipeline object for captured playback + pipeline."1" {} + + host."playback" { + ## "aif_in" is for playback + type "aif_in" + } + + buffer."1" { + periods 2 + caps "host" + } + + pga."1" { + Object.Control.mixer.1 { + Object.Base.tlv."vtlv_m64s2" { + Object.Base.scale."m64s2" {} + } + } + } + + buffer."2" { + periods 2 + caps "dai" + } + } + + # Pipeline connections + # The index attribute values for the source/sink widgets will be populated + # when the route objects are built + Object.Base { + route."1" { + source "host.$index.playback" + sink "buffer.$index.1" + } + + route."2" { + source "buffer.$index.1" + sink "pga.$index.1" + } + + route."3" { + source "pga.$index.1" + sink "buffer.$index.2" + } + } + + # Default attribute values + direction "playback" + time_domain "timer" + period 1000 + priority 0 + core 0 + frames 0 + mips 5000 +} diff --git a/tools/topology/topology2/platform/intel/bt-default.conf b/tools/topology/topology2/platform/intel/bt-default.conf new file mode 100644 index 000000000000..2555288b7221 --- /dev/null +++ b/tools/topology/topology2/platform/intel/bt-default.conf @@ -0,0 +1,23 @@ +# Default BT variable definitions +Define { + # BT_ID is dai link ID that is matched with machine driver + BT_ID 2 + # BT_INDEX is dai_index which passed to firmware + BT_INDEX 2 + FORMAT s16le + BT_MCLK 38400000 + BT_NAME "SSP2-BT" + + BT_PB_HOST_PIPELINE_ID 7 + BT_PB_DAI_PIPELINE_ID 8 + BT_PB_PCM_CAPS "BT Playback" + + BT_CP_HOST_PIPELINE_ID 11 + BT_CP_DAI_PIPELINE_ID 12 + BT_CP_PCM_CAPS "BT Capture" + + BT_PCM_ID 2 + BT_PCM_NAME "Port2" + + BT_LOOPBACK_MODE false +} diff --git a/tools/topology/topology2/platform/intel/bt-generic.conf b/tools/topology/topology2/platform/intel/bt-generic.conf new file mode 100644 index 000000000000..e1549fb69a2e --- /dev/null +++ b/tools/topology/topology2/platform/intel/bt-generic.conf @@ -0,0 +1,252 @@ +IncludeByKey.BT_LOOPBACK_MODE { + "true" "platform/intel/bt-ssp-config-lbm.conf" +} + +IncludeByKey.BT_LOOPBACK_MODE { + "false" "platform/intel/bt-ssp-config.conf" +} + +Object.Pipeline { + # playback pipelines + io-gateway [ + { + index $BT_PB_DAI_PIPELINE_ID + direction playback + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$BT_NAME.playback" + } + + Object.Widget.dai-copier.1 { + dai_index $BT_INDEX + dai_type "SSP" + copier_type "SSP" + stream_name $BT_NAME + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 3 + num_input_pins 1 + + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] + + host-gateway-playback [ + { + index $BT_PB_HOST_PIPELINE_ID + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$BT_NAME.playback" + } + Object.Widget.host-copier.1 { + stream_name $BT_PB_PCM_CAPS + pcm_id $BT_PCM_ID + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] + + # capture pipelines + host-gateway-capture [ + { + index $BT_CP_HOST_PIPELINE_ID + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$BT_NAME.capture" + } + Object.Widget.host-copier.1 { + stream_name $BT_CP_PCM_CAPS + pcm_id $BT_PCM_ID + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] + + io-gateway-capture [ + { + index $BT_CP_DAI_PIPELINE_ID + direction "capture" + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$BT_NAME.capture" + } + + Object.Widget.dai-copier."1" { + dai_index $BT_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name $BT_NAME + node_type $I2S_LINK_INPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 3 + CombineArrays.Object.Base.output_audio_format [ + # array of 2ch format with range of rates + { + out_rate [ + 8000 + 16000 + ] + out_channels [ 1 ] + } + # 2ch 16-bit 48k + { + out_bit_depth [ 16 ] + out_valid_bit_depth [ 16 ] + out_channels [ 2 ] + } + ] + CombineArrays.Object.Base.input_audio_format [ + # array of 2ch format with range of rates + { + in_rate [ + 8000 + 16000 + ] + in_channels [ 1 ] + } + # 2ch 16-bit 48k + { + in_bit_depth [ 16 ] + in_valid_bit_depth [ 16 ] + in_channels [ 2 ] + } + ] + } + } + ] +} + +Object.Base.route [ + { + source "host-copier.$BT_PCM_ID.playback" + sink "dai-copier.SSP.$BT_NAME.playback" + } + { + source "dai-copier.SSP.$BT_NAME.capture" + sink "host-copier.$BT_PCM_ID.capture" + } +] + +Object.PCM.pcm [ + { + name $BT_PCM_NAME + id $BT_PCM_ID + direction "duplex" + + Object.Base.fe_dai.1 { + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name $BT_PB_PCM_CAPS + formats 'S16_LE' + rates '8000,16000,48000' + channels_min 1 + channels_max 2 + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name $BT_CP_PCM_CAPS + formats 'S16_LE' + rates '8000,16000,48000' + channels_min 1 + channels_max 2 + } + } +] diff --git a/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf b/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf new file mode 100644 index 000000000000..d4060ef53c09 --- /dev/null +++ b/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf @@ -0,0 +1,65 @@ +Object.Dai.SSP [ + { + id $BT_ID + dai_index $BT_INDEX + direction "duplex" + name $BT_NAME + default_hw_conf_id 0 + sample_bits 16 + quirks "lbm_mode" + io_clk $BT_MCLK + Object.Base.hw_config.1 { + id 0 + name "BT-SCO-WB" + mclk_freq $BT_MCLK + bclk_freq 256000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 16000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.2 { + id 1 + name "BT-SCO-NB" + mclk_freq $BT_MCLK + bclk_freq 128000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 8000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.3 { + id 2 + name "BT-A2DP" + mclk_freq $BT_MCLK + bclk_freq 1536000 + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 3 + Object.Base.link_config.1 { + clock_source 1 + } + } + } +] diff --git a/tools/topology/topology2/platform/intel/bt-ssp-config.conf b/tools/topology/topology2/platform/intel/bt-ssp-config.conf new file mode 100644 index 000000000000..2c527b55dcb4 --- /dev/null +++ b/tools/topology/topology2/platform/intel/bt-ssp-config.conf @@ -0,0 +1,70 @@ +Object.Dai.SSP [ + { + id $BT_ID + dai_index $BT_INDEX + direction "duplex" + name $BT_NAME + default_hw_conf_id 0 + sample_bits 16 + io_clk $BT_MCLK + Object.Base.hw_config.1 { + id 0 + name "BT-SCO-WB" + mclk_freq $BT_MCLK + bclk_freq 256000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_provider" + fsync "codec_provider" + fsync_freq 16000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + # link_config ignored for <ACE1.5, must be compatible + # with BT_MCLK + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.2 { + id 1 + name "BT-SCO-NB" + mclk_freq $BT_MCLK + bclk_freq 128000 + bclk_invert true + tdm_slot_width 16 + format "DSP_A" + bclk "codec_provider" + fsync "codec_provider" + fsync_freq 8000 + tdm_slots 1 + tx_slots 1 + rx_slots 1 + # link_config ignored for <ACE1.5, must be compatible + # with BT_MCLK + Object.Base.link_config.1 { + clock_source 1 + } + } + Object.Base.hw_config.3 { + id 2 + mclk_freq $BT_MCLK + name "BT-A2DP" + bclk_freq 1536000 + tdm_slot_width 16 + format "DSP_A" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 0 + # link_config ignored for <ACE1.5, must be compatible + # with BT_MCLK + Object.Base.link_config.1 { + clock_source 1 + } + } + } +] diff --git a/tools/topology/topology2/platform/intel/compr-default.conf b/tools/topology/topology2/platform/intel/compr-default.conf new file mode 100644 index 000000000000..12ab39185f5a --- /dev/null +++ b/tools/topology/topology2/platform/intel/compr-default.conf @@ -0,0 +1,16 @@ +# default settings for Compressed Audio Playback +Define { + COMPRESSED false + COMPR_DEEPBUFFER_MS 100 # 100 ms copier dma size + + COMPRESSED_1 true + COMPR_PCM_NAME 'Compress Playback' + COMPR_PCM_ID 50 + COMPR_PIPELINE_ID 90 + + + COMPRESSED_2 false + COMPR_2_PCM_NAME 'Compress Playback 2' + COMPR_2_PCM_ID 52 + COMPR_2_PIPELINE_ID 92 +} diff --git a/tools/topology/topology2/platform/intel/compr.conf b/tools/topology/topology2/platform/intel/compr.conf new file mode 100644 index 000000000000..14c07a0d974d --- /dev/null +++ b/tools/topology/topology2/platform/intel/compr.conf @@ -0,0 +1,229 @@ + +IncludeByKey.COMPRESSED_1 { +"true" { + Object.Pipeline.compr-playback [ + { + index $COMPR_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name $COMPR_PCM_NAME + pcm_id $COMPR_PCM_ID + <include/formats/compr_input_audio_formats.conf> + <include/formats/compr_output_audio_formats.conf> + } + + Object.Widget.decoder.1 { + core_id 1 + <include/formats/compr_input_audio_formats.conf> + <include/formats/compr_output_audio_formats.conf> + } + + # converts the input to S32_LE + Object.Widget.module-copier.2 { + <include/formats/compr_input_audio_formats.conf> + <include/formats/compr_output_audio_formats_s32.conf> + } + + # converts the input to 48KHz + # note: this is wrong for 96/192KHz HiRes audio!!!! + Object.Widget.src.1 { + rate_out 48000 + <include/formats/compr_input_output_formats_src_s32_to_48k.conf> + } + + # converts the input to stereo + Object.Widget.micsel.1 { + Object.Control.bytes."1" { + name '$COMPR_PCM_NAME selector bytes' + <include/components/micsel/stereo_endpoint_playback_updownmix.conf> + } + <include/formats/compr_input_audio_formats_s32_48k.conf> + <include/formats/compr_output_audio_formats_s32_48k_stereo.conf> + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $COMPR_PCM_NAME Volume' + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 48000 + 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 + } + ] + } + Object.Widget.mixin.1 { + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + Object.PCM.pcm [ + { + name $COMPR_PCM_NAME + id $COMPR_PCM_ID + direction playback + compress "true" + + Object.Base.fe_dai.1 { + name "$COMPR_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name $COMPR_PCM_NAME + formats 'S32_LE' + rates '8000' + } + } + ] + + Object.Base.route [ + { + source mixin.$COMPR_PIPELINE_ID.1 + sink $COMPR_PIPELINE_SINK + } + { + source host-copier.$COMPR_PCM_ID.playback + sink decoder.$COMPR_PIPELINE_ID.1 + } + ] +} +} + +# Spawn another instance for speaker +IncludeByKey.COMPRESSED_2 { +"true" { + Object.Pipeline.compr-playback [ + { + index $COMPR_2_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name $COMPR_2_PCM_NAME + pcm_id $COMPR_2_PCM_ID + <include/formats/compr_input_audio_formats.conf> + <include/formats/compr_output_audio_formats.conf> + } + + Object.Widget.decoder.1 { + core_id 1 + <include/formats/compr_input_audio_formats.conf> + <include/formats/compr_output_audio_formats.conf> + } + + # converts the input to S32_LE + Object.Widget.module-copier.2 { + <include/formats/compr_input_audio_formats.conf> + <include/formats/compr_output_audio_formats_s32.conf> + } + + # converts the input to 48KHz + # note: this is wrong for 96/192KHz HiRes audio!!!! + Object.Widget.src.1 { + rate_out 48000 + <include/formats/compr_input_output_formats_src_s32_to_48k.conf> + } + + # converts the input to stereo + Object.Widget.micsel.1 { + Object.Control.bytes."1" { + name '$COMPR_2_PCM_NAME selector bytes' + <include/components/micsel/stereo_endpoint_playback_updownmix.conf> + } + <include/formats/compr_input_audio_formats_s32_48k.conf> + <include/formats/compr_output_audio_formats_s32_48k_stereo.conf> + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $COMPR_2_PCM_NAME Volume' + } + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate 48000 + 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 + } + ] + } + Object.Widget.mixin.1 { + Object.Base.input_audio_format [ + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + Object.PCM.pcm [ + { + name $COMPR_2_PCM_NAME + id $COMPR_2_PCM_ID + direction playback + compress "true" + + Object.Base.fe_dai.1 { + name "$COMPR_2_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name $COMPR_2_PCM_NAME + formats 'S32_LE' + rates '8000' + } + } + ] + + Object.Base.route [ + { + source mixin.$COMPR_2_PIPELINE_ID.1 + sink $COMPR_2_PIPELINE_SINK + } + { + source host-copier.$COMPR_2_PCM_ID.playback + sink decoder.$COMPR_2_PIPELINE_ID.1 + } + ] +} +} diff --git a/tools/topology/topology2/platform/intel/deep-buffer-default.conf b/tools/topology/topology2/platform/intel/deep-buffer-default.conf new file mode 100644 index 000000000000..35d0977bf3c9 --- /dev/null +++ b/tools/topology/topology2/platform/intel/deep-buffer-default.conf @@ -0,0 +1,8 @@ +# default settings for Deep Buffer Speaker +Define { + DEEP_BUF_SPK false + DEEP_BUF_JACK_RATE 48000 + + DEEP_BUFFER_PCM_NAME 'Deepbuffer Jack Out' + DEEP_BUFFER_PCM_NAME_2 'Deepbuffer Speaker' +} diff --git a/tools/topology/topology2/platform/intel/deep-buffer-spk.conf b/tools/topology/topology2/platform/intel/deep-buffer-spk.conf new file mode 100644 index 000000000000..b5743653f84f --- /dev/null +++ b/tools/topology/topology2/platform/intel/deep-buffer-spk.conf @@ -0,0 +1,59 @@ +Define { + SPEAKER_PCM_CORE_ID 0 +} + +Object.Pipeline.deepbuffer-playback [ + { + index $DEEP_BUFFER_PIPELINE_ID_2 + core_id $SPEAKER_PCM_CORE_ID + + Object.Widget.host-copier.1 { + stream_name $DEEP_BUFFER_PCM_NAME_2 + pcm_id $DEEP_BUFFER_PCM_ID_2 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $DEEP_BUFFER_PCM_NAME_2 Volume' + } + } + Object.Widget.pipeline.1 { + core $SPEAKER_PCM_CORE_ID + } + } +] + +Object.PCM.pcm [ + { + name $DEEP_BUFFER_PCM_NAME_2 + id $DEEP_BUFFER_PCM_ID_2 + direction playback + playback_compatible_d0i3 $DEEPBUFFER_D0I3_COMPATIBLE + + Object.Base.fe_dai.1 { + name "$DEEP_BUFFER_PCM_NAME_2" + } + Object.PCM.pcm_caps.1 { + name $DEEP_BUFFER_PCM_NAME_2 + formats 'S16_LE,S24_LE,S32_LE' + # To avoid DMA spinning on a buffer we need bigger + # buffer than the host buffer size, let's say twice as + # big + # (S16_LE, Stereo, 48KHz, DEEPBUFFER_FW_DMA_MS) * 2 + # + # Note: The lower limit for the buffer size is rate + # dependent + buffer_size_min "$[(((2 * $channels_min) * 48) * $DEEPBUFFER_FW_DMA_MS) * 2]" + } + } +] + +Object.Base.route [ + { + source $DEEP_BUFFER_PIPELINE_SRC_2 + sink $DEEP_BUFFER_PIPELINE_SINK_2 + } + { + source host-copier.$DEEP_BUFFER_PCM_ID_2.playback + sink gain.$DEEP_BUFFER_PIPELINE_ID_2.1 + } +] diff --git a/tools/topology/topology2/platform/intel/deep-buffer.conf b/tools/topology/topology2/platform/intel/deep-buffer.conf new file mode 100644 index 000000000000..5b86088feddf --- /dev/null +++ b/tools/topology/topology2/platform/intel/deep-buffer.conf @@ -0,0 +1,168 @@ + +Object.Pipeline.deepbuffer-playback [ + { + index $DEEP_BUFFER_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name $DEEP_BUFFER_PCM_NAME + pcm_id $DEEP_BUFFER_PCM_ID + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + } + } + Object.Base.output_audio_format [ + { + out_rate $DEEP_BUF_JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $DEEP_BUFFER_PCM_NAME Volume' + } + Object.Base.input_audio_format [ + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DEEP_BUF_JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.mixin.1 { + Object.Base.input_audio_format [ + { + in_rate $DEEP_BUF_JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DEEP_BUF_JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } +] + +Object.PCM.pcm [ + { + name $DEEP_BUFFER_PCM_NAME + id $DEEP_BUFFER_PCM_ID + direction playback + playback_compatible_d0i3 $DEEPBUFFER_D0I3_COMPATIBLE + + Object.Base.fe_dai.1 { + name "$DEEP_BUFFER_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name $DEEP_BUFFER_PCM_NAME + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + # To avoid DMA spinning on a buffer we need bigger + # buffer than the host buffer size, let's say twice as + # big + # (S16_LE, Stereo, 48KHz, DEEPBUFFER_FW_DMA_MS) * 2 + # + # Note: The lower limit for the buffer size is rate + # dependent + buffer_size_min "$[(((2 * $channels_min) * 48) * $DEEPBUFFER_FW_DMA_MS) * 2]" + IncludeByKey.DEEP_BUF_JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } +] + +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 + } +] + +# Spawn another instance +IncludeByKey.DEEP_BUF_SPK { +"true" "platform/intel/deep-buffer-spk.conf" +} diff --git a/tools/topology/topology2/platform/intel/dmic-deep-buffer.conf b/tools/topology/topology2/platform/intel/dmic-deep-buffer.conf new file mode 100644 index 000000000000..5e8615c2db21 --- /dev/null +++ b/tools/topology/topology2/platform/intel/dmic-deep-buffer.conf @@ -0,0 +1,117 @@ + Object.Pipeline.deepbuffer-capture [ + { + format $FORMAT + index $DMIC0_DEEP_BUFFER_PIPELINE_ID + Object.Widget.pipeline.1 { + stream_name "$DMIC0_DEEP_BUFFER_PCM_NAME" + } + Object.Widget.host-copier.1 { + stream_name $DMIC0_DEEP_BUFFER_PCM_NAME + pcm_id $DMIC0_DEEP_BUFFER_PCM_ID + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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 6 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + out_channels 4 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_rate $DMIC0_RATE + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_rate $DMIC0_RATE + 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.PCM.pcm [ + { + name "$DMIC0_DEEP_BUFFER_PCM_NAME" + id $DMIC0_DEEP_BUFFER_PCM_ID + direction "capture" + capture_compatible_d0i3 $DEEPBUFFER_D0I3_COMPATIBLE + + Object.Base.fe_dai."$DMIC0_DEEP_BUFFER_PCM_NAME" {} + + Object.PCM.pcm_caps."capture" { + name $DMIC0_DEEP_BUFFER_PCM_NAME + formats 'S16_LE,S24_LE,S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + # To avoid DMA spinning on a buffer we need bigger + # buffer than the host buffer size, let's say twice as + # big + # (S16_LE, Stereo, 48KHz, DEEPBUFFER_FW_DMA_MS) * 2 + # + # Note: The lower limit for the buffer size is rate + # dependent + IncludeByKey.DMIC0_RATE { + "16000" { + buffer_size_min "$[(((2 * $NUM_DMICS) * 16) * $DEEPBUFFER_FW_DMA_MS) * 2]" + rates '16000' + } + "48000" { + buffer_size_min "$[(((2 * $NUM_DMICS) * 48) * $DEEPBUFFER_FW_DMA_MS) * 2]" + rates '48000' + } + "96000" { + buffer_size_min "$[(((2 * $NUM_DMICS) * 96) * $DEEPBUFFER_FW_DMA_MS) * 2]" + rates '96000' + } + } + } + } + ] + Object.Base.route [ + { + source "module-copier.$DMIC0_DAI_PIPELINE_ID.2" + sink "host-copier.$DMIC0_DEEP_BUFFER_PCM_ID.capture" + } + ] \ No newline at end of file diff --git a/tools/topology/topology2/platform/intel/dmic-default.conf b/tools/topology/topology2/platform/intel/dmic-default.conf new file mode 100644 index 000000000000..1bb96a45465b --- /dev/null +++ b/tools/topology/topology2/platform/intel/dmic-default.conf @@ -0,0 +1,56 @@ +# Default DMIC variable definitions +Define { + PDM0_MIC_A_ENABLE 1 + PDM0_MIC_B_ENABLE 1 + PDM1_MIC_A_ENABLE 0 + PDM1_MIC_B_ENABLE 0 + DMIC0_ID 6 # Default link ID based on HDA generic machine driver + DMIC1_ID 7 # Default link ID based on HDA generic machine driver + DMIC0_PCM_ID 10 # Default DMIC0 PCM ID + DMIC1_PCM_ID 11 # Default DMIC1 PCM ID + FORMAT s32le + # IO_CLK applicable for TGL and ADL + DMIC_IO_CLK 38400000 + # driver version applicable for TGL and ADL + DMIC_DRIVER_VERSION 1 + DMIC0_HOST_PIPELINE_ID 11 + DMIC0_DAI_PIPELINE_ID 12 + DMIC0_HOST_PIPELINE_SINK "copier.host.11.1" + DMIC0_DAI_PIPELINE_SRC "dai-copier.DMIC.dmic01.capture" + DMIC0_NAME dmic01 + DMIC1_NAME dmic16k + DMIC0_PCM_CAPS "Passthrough Capture 11" + DMIC0_DAI_EQIIR "highpass_40hz_0db" + DMIC1_DAI_EQIIR "highpass_100hz_20db" + DMIC1_HOST_PIPELINE_ID 18 + DMIC1_DAI_PIPELINE_ID 19 + WOV_PIPELINE_ID 20 + DMIC1_HOST_PIPELINE_SINK 'copier.host.18.1' + DMIC_WOV_DAI_PIPELINE_SRC 'dai-copier.DMIC.dmic16k.capture' + DMIC_WOV_DAI_PIPELINE_KPB 'kpb.19.1' + WOV_PIPELINE_SINK 'micsel.20.1' + WOV_PIPELINE_VIRTUAL 'virtual.detect_sink' + INCLUDE_WOV 'false' + # The UUID corresponds to the test detect component + 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" + DMIC_PIPELINE_PRIORITY 0 + DMIC0_RATE 48000 + DMIC1_RATE 16000 + DMIC1_ENABLE "false" + + # TDFB and DRC pipeline + DMIC0_ENHANCED_CAPTURE "false" + + # Note: This will be redefined in dmic-generic.conf if not set from cmake + DMIC0_PCM_CHANNELS 0 + + # Deep buffer capture + DMIC0_DEEP_BUFFER_PCM_NAME "DMIC Deep Buffer" + DMIC0_DEEP_BUFFER_PIPELINE_ID 18 + DMIC0_DEEP_BUFFER_PCM_ID 46 + DMIC0_DEEP_BUFFER false +} diff --git a/tools/topology/topology2/platform/intel/dmic-generic.conf b/tools/topology/topology2/platform/intel/dmic-generic.conf new file mode 100644 index 000000000000..c473f1eea470 --- /dev/null +++ b/tools/topology/topology2/platform/intel/dmic-generic.conf @@ -0,0 +1,1051 @@ +Define { + DMIC0_PCM_NAME "DMIC Raw" +} + +# If DMIC0_PCM_CHANNELS is zero, copy it from NUM_DMICS. This +# allows by setting both NUM_DMICS and DMIC0_PCM_CHANNELS to +# have a different channels count in DAI and host. +IncludeByKey.DMIC0_PCM_CHANNELS { + "0" { + IncludeByKey.NUM_DMICS { + "1" { + Define { + DMIC0_PCM_CHANNELS 1 + } + } + "2" { + Define { + DMIC0_PCM_CHANNELS 2 + } + } + "4" { + Define { + DMIC0_PCM_CHANNELS 4 + } + } + } + } +} + +Object.Dai.DMIC [ + { + dai_index 0 + name $DMIC0_NAME + id $DMIC0_ID + driver_version $DMIC_DRIVER_VERSION + io_clk $DMIC_IO_CLK + sample_rate $DMIC0_RATE + clk_min 500000 + clk_max 4800000 + unmute_ramp_time_ms 200 + # num_pdm_active should always set to 2 but depending on the number of DMIC's + # the mic's are enabled or disabled in each PDM. + num_pdm_active 2 + + Object.Base.hw_config.1 { + id 0 + name "DMIC0" + } + + # PDM controller config + Object.Base.pdm_config.1 { + mic_a_enable $PDM0_MIC_A_ENABLE + mic_b_enable $PDM0_MIC_B_ENABLE + ctrl_id 0 + } + Object.Base.pdm_config.2 { + ctrl_id 1 + mic_a_enable $PDM1_MIC_A_ENABLE + mic_b_enable $PDM1_MIC_B_ENABLE + } + } + { + name $DMIC1_NAME + id $DMIC1_ID + dai_index 1 + driver_version $DMIC_DRIVER_VERSION + io_clk $DMIC_IO_CLK + sample_rate $DMIC1_RATE + clk_min 500000 + clk_max 4800000 + unmute_ramp_time_ms 200 + # num_pdm_active should always set to 2 but depending on the number of DMIC's + # the mic's are enabled or disabled in each PDM. + num_pdm_active 2 + + Object.Base.hw_config.1 { + id 0 + name "DMIC1" + } + + # PDM controller config + Object.Base.pdm_config.1 { + mic_a_enable $PDM0_MIC_A_ENABLE + mic_b_enable $PDM0_MIC_B_ENABLE + ctrl_id 0 + } + Object.Base.pdm_config.2 { + ctrl_id 1 + mic_a_enable $PDM1_MIC_A_ENABLE + mic_b_enable $PDM1_MIC_B_ENABLE + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.INCLUDE_WOV { + "true" "platform/intel/dmic-wov.conf" + } + + Object.Pipeline.host-gateway-capture [ + { + format $FORMAT + index $DMIC0_HOST_PIPELINE_ID + core_id $DMIC_CORE_ID + Object.Widget.host-copier.1 { + stream_name $DMIC0_PCM_CAPS + pcm_id $DMIC0_PCM_ID + num_input_audio_formats 1 + IncludeByKey.DMIC0_PCM_CHANNELS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_rate $DMIC0_RATE + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "false" { + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + } + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + } + { + out_rate $DMIC0_RATE + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + 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 + } + ] + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 4 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_rate $DMIC0_RATE + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + out_rate $DMIC0_RATE + 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 + } + { + out_rate $DMIC0_RATE + 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 + out_sample_type $SAMPLE_TYPE_FLOAT + } + { + out_rate $DMIC0_RATE + out_channels 4 + out_bit_depth 8 + out_valid_bit_depth 8 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + 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.Widget.pipeline."1" { + core $DMIC_CORE_ID + } + } + ] + + Object.Pipeline.dai-copier-gain-eqiir-module-copier-capture [ + { + index $DMIC0_DAI_PIPELINE_ID + core_id $DMIC_CORE_ID + + Object.Widget.dai-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 3 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + } + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 4 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC0_RATE + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + 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.Widget.module-copier."2" { + stream_name $DMIC0_NAME + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + 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.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'DMIC0 Capture IIR Eq' + IncludeByKey.DMIC0_DAI_EQIIR { + "passthrough" "include/components/eqiir/passthrough.conf" + "highpass_40hz_0db" "include/components/eqiir/highpass_40hz_0db_48khz.conf" + "highpass_40hz_20db" "include/components/eqiir/highpass_40hz_20db_48khz.conf" + } + } + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + 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.Widget.gain.1 { + curve_duration 500000 + num_input_audio_formats 2 + num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + 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.mixer.1 { + name 'Dmic0 Capture Volume' + } + Object.Control.mixer.2 { + name 'Dmic0 Capture Switch' + + mute_led_use 1 + mute_led_direction 1 + } + } + + + Object.Widget.pipeline."1" { + core $DMIC_CORE_ID + priority $DMIC_PIPELINE_PRIORITY + } + } + ] + + IncludeByKey.DMIC0_ENHANCED_CAPTURE { + "true" { + + Object.Widget.tdfb.1 { + index $DMIC0_HOST_PIPELINE_ID + Object.Control { + bytes."1" { + name 'Dmic0 Capture TDFB bytes' + max 16384 + IncludeByKey.EFX_DMIC0_TDFB_PARAMS { + "line2_pass" "include/components/tdfb/line2_pass.conf" + "line2_generic_pm10deg" "include/components/tdfb/line2_generic_pm10deg_48khz.conf" + "line2_50mm" "include/components/tdfb/line2_50mm_pm0_30_90deg_48khz.conf" + "line2_68mm" "include/components/tdfb/line2_68mm_pm0_30_90deg_48khz.conf" + "line2_74mm" "include/components/tdfb/line2_74mm_pm0_30_90deg_48khz.conf" + "line4_pass" "include/components/tdfb/line4_pass.conf" + "line4to2_pass" "include/components/tdfb/line4to2_pass.conf" + "line4_generic_pm10deg" "include/components/tdfb/line4_generic_pm10deg_48khz.conf" + "line4_28mm" "include/components/tdfb/line2_28mm_pm0_30_90deg_48khz.conf" + } + } + mixer."1" { + name 'Dmic0 Capture TDFB beam switch' + } + enum."1" { + name 'Dmic0 Capture TDFB angle set enum' + } + # Tracking is disabled from this topology, causes high MCPS + #mixer."2" { + # name 'Dmic0 Capture TDFB track switch' + #} + #enum."2" { + # name 'Dmic0 Capture TDFB angle estimate enum' + #} + } + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 2 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + 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 + } + ] + } + } + IncludeByKey.DMIC0_PCM_CHANNELS { + "2" { + Object.Base.output_audio_format [ + { + out_channels 2 + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + 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.Widget.drc.1 { + index $DMIC0_HOST_PIPELINE_ID + Object.Control { + bytes."1" { + name 'Dmic0 Capture DRC bytes' + IncludeByKey.EFX_DMIC0_DRC_PARAMS { + "passthrough" "include/components/drc/passthrough.conf" + "dmic_default" "include/components/drc/dmic_default.conf" + } + } + mixer."1" { + name 'Dmic0 Capture DRC switch' + } + } + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.DMIC0_PCM_CHANNELS { + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + 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 + } + ] + } + } + } + } + } + + IncludeByKey.DMIC0_ENHANCED_CAPTURE { + "true" { + Object.Base.route [ + { + source $DMIC0_DAI_COPIER + sink gain.$DMIC0_DAI_PIPELINE_ID.1 + } + { + source $DMIC0_DAI_PIPELINE_SRC + sink tdfb.$DMIC0_HOST_PIPELINE_ID.1 + } + { + source tdfb.$DMIC0_HOST_PIPELINE_ID.1 + sink drc.$DMIC0_HOST_PIPELINE_ID.1 + } + { + source drc.$DMIC0_HOST_PIPELINE_ID.1 + sink $DMIC0_HOST_PIPELINE_SINK + } + ] + } + "false" { + Object.Base.route [ + { + source $DMIC0_DAI_COPIER + sink gain.$DMIC0_DAI_PIPELINE_ID.1 + } + { + source $DMIC0_DAI_PIPELINE_SRC + sink $DMIC0_HOST_PIPELINE_SINK + } + ] + } + } + } + "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_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + 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_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.Pipeline.io-gateway-capture [ + { + index $DMIC0_DAI_PIPELINE_ID + Object.Widget.dai-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 9 + Object.Base.input_audio_format [ + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC0_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC0_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + } + { + in_rate $DMIC0_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $DMIC0_RATE + in_channels 4 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC0_RATE + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC0_RATE + 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 3 + Object.Base.output_audio_format [ + { + out_rate $DMIC0_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + { + out_rate $DMIC0_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $DMIC0_RATE + 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.route [ + { + source "dai-copier.DMIC.$DMIC0_NAME.capture" + sink "host-copier.$DMIC0_PCM_ID.capture" + } + ] + } +} + +Object.PCM.pcm [ + { + name "$DMIC0_PCM_NAME" + id $DMIC0_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$DMIC0_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name $DMIC0_PCM_CAPS + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S32_LE' + } + } + channels_min $DMIC0_PCM_CHANNELS + channels_max $DMIC0_PCM_CHANNELS + IncludeByKey.DMIC0_RATE { + "16000" { + rates '16000' + } + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + } + } + } +] + +IncludeByKey.DMIC0_DEEP_BUFFER { + "true" "platform/intel/dmic-deep-buffer.conf" +} + +IncludeByKey.DMIC1_ENABLE { + "passthrough" "platform/intel/dmic1-passthrough.conf" + "mfcc" "platform/intel/dmic1-mfcc.conf" +} diff --git a/tools/topology/topology2/platform/intel/dmic-wov.conf b/tools/topology/topology2/platform/intel/dmic-wov.conf new file mode 100644 index 000000000000..0094941e0c74 --- /dev/null +++ b/tools/topology/topology2/platform/intel/dmic-wov.conf @@ -0,0 +1,147 @@ +Object.Pipeline { + host-gateway-capture [ + { + format $FORMAT + rate 16000 + rate_min 16000 + rate_max 16000 + index $DMIC1_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name $DMIC1_PCM_CAPS + pcm_id 11 + num_output_audio_formats 2 + Object.Base.output_audio_format [ + { + out_rate 16000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate 16000 + 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 + } + ] + } + } + ] + + dai-kpb-be [ + { + direction "capture" + format $FORMAT + rate 16000 + rate_min 16000 + rate_max 16000 + index $DMIC1_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + dai_index 1 + type "dai_out" + dai_type "DMIC" + copier_type "DMIC" + type dai_out + stream_name $DMIC1_NAME + node_type $DMIC_LINK_INPUT_CLASS + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.input_audio_format [ + { + in_rate 16000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate 16000 + 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_rate 16000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate 16000 + 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.Widget.kpb.1 { + Object.Base.output_pin_binding.1 { + output_pin_binding_name $WOV_PIPELINE_SINK + } + Object.Base.output_pin_binding.2 { + output_pin_binding_name $DMIC1_HOST_PIPELINE_SINK + } + Object.Base.output_pin_binding.3 { + output_pin_binding_name "NotConnected" + } + } + } + ] + + wov-detect [ + { + index $WOV_PIPELINE_ID + format s32le + channels 2 + Object.Widget.wov.1 { + uuid $WOV_UUID + cpc $WOV_CPC + } + } + ] +} + +Object.Base.route [ + { + source $DMIC_WOV_DAI_PIPELINE_KPB + sink "host-copier.11.capture" + } + { + source $DMIC_WOV_DAI_PIPELINE_KPB + sink $WOV_PIPELINE_SINK + } + { + source $WOV_PIPELINE_VIRTUAL + sink "host-copier.11.capture" + } +] + +Object.PCM.pcm [ + { + name "DMIC16k" + id 11 + direction "capture" + capture_compatible_d0i3 true + Object.Base.fe_dai.1 { + name "DMIC16k" + } + + Object.PCM.pcm_caps.1 { + name $DMIC1_PCM_CAPS + # only 32-bit capture supported now + formats 'S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + rate_min 16000 + rate_max 16000 + } + } +] diff --git a/tools/topology/topology2/platform/intel/dmic1-mfcc.conf b/tools/topology/topology2/platform/intel/dmic1-mfcc.conf new file mode 100644 index 000000000000..f3926a283a8b --- /dev/null +++ b/tools/topology/topology2/platform/intel/dmic1-mfcc.conf @@ -0,0 +1,573 @@ +<include/components/mfcc.conf> + +Define { + DMIC1_PCM_NAME "DMIC MFCC" +} + +Object.Pipeline.host-gateway-capture [ + { + index $DMIC1_HOST_PIPELINE_ID + core_id $DMIC_CORE_ID + Object.Widget.host-copier.1 { + stream_name $DMIC1_PCM_CAPS + pcm_id $DMIC1_PCM_ID + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 4 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 4 + out_bit_depth 16 + out_valid_bit_depth 16 + 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.Pipeline.dai-copier-gain-eqiir-module-copier-capture [ + { + index $DMIC1_DAI_PIPELINE_ID + core_id $DMIC_CORE_ID + + Object.Widget.dai-copier.1 { + dai_index 1 + dai_type "DMIC" + copier_type "DMIC" + type dai_out + stream_name $DMIC1_NAME + node_type $DMIC_LINK_INPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + } + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 4 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC1_RATE + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC1_RATE + 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_rate $DMIC1_RATE + 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.Widget.module-copier."2" { + stream_name $DMIC1_NAME + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + 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_rate $DMIC1_RATE + out_channels 4 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + } + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'DMIC1 Capture IIR Eq' + IncludeByKey.DMIC1_RATE { + "16000" { + IncludeByKey.DMIC1_DAI_EQIIR { + "passthrough" "include/components/eqiir/passthrough.conf" + "highpass_40hz_0db" "include/components/eqiir/highpass_40hz_0db_16khz.conf" + "highpass_40hz_20db" "include/components/eqiir/highpass_40hz_20db_16khz.conf" + "highpass_100hz_0db" "include/components/eqiir/highpass_100hz_0db_16khz.conf" + "highpass_100hz_20db" "include/components/eqiir/highpass_100hz_20db_16khz.conf" + } + } + "48000" { + IncludeByKey.DMIC1_DAI_EQIIR { + "passthrough" "include/components/eqiir/passthrough.conf" + "highpass_40hz_0db" "include/components/eqiir/highpass_40hz_0db_16khz.conf" + "highpass_40hz_20db" "include/components/eqiir/highpass_40hz_20db_16khz.conf" + "highpass_100hz_0db" "include/components/eqiir/highpass_100hz_0db_16khz.conf" + "highpass_100hz_20db" "include/components/eqiir/highpass_100hz_20db_16khz.conf" + } + } + } + } + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + 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_rate $DMIC1_RATE + 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.Widget.gain.1 { + curve_duration 500000 + num_input_audio_formats 2 + num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + 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_rate $DMIC1_RATE + 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.mixer.1 { + name 'Dmic1 Capture Volume' + } + Object.Control.mixer.2 { + name 'Dmic1 Capture Switch' + + mute_led_use 1 + mute_led_direction 1 + } + } + + + Object.Widget.pipeline."1" { + core $DMIC_CORE_ID + priority $DMIC_PIPELINE_PRIORITY + } + } +] + +Object.Widget.mfcc.1 { + index $DMIC1_HOST_PIPELINE_ID + Object.Control { + bytes."1" { + name 'Analog Capture TDFB bytes' + IncludeByKey.DMIC1_MFCC_PARAMS { + "default" "include/components/mfcc/default.conf" + } + } + } + IncludeByKey.NUM_DMICS { + "1" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + ] + } + "4" { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 4 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 4 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + } +} + +Object.Base.route [ + { + source "dai-copier.DMIC.$DMIC1_NAME.capture" + sink "gain.$DMIC1_DAI_PIPELINE_ID.1" + } + { + source module-copier.$DMIC1_DAI_PIPELINE_ID.2 + sink mfcc.$DMIC1_HOST_PIPELINE_ID.1 + } + { + source "mfcc.$DMIC1_HOST_PIPELINE_ID.1" + sink "host-copier.$DMIC1_PCM_ID.capture" + } +] + +Object.PCM.pcm [ + { + name "$DMIC1_PCM_NAME" + id $DMIC1_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$DMIC1_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name $DMIC1_PCM_CAPS + # only 16-bit capture supported now + formats 'S16_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + IncludeByKey.DMIC1_RATE { + "16000" { + rates '16000' + } + "48000" { + rates '48000' + } + } + } + } +] diff --git a/tools/topology/topology2/platform/intel/dmic1-passthrough.conf b/tools/topology/topology2/platform/intel/dmic1-passthrough.conf new file mode 100644 index 000000000000..2ea85903d5a9 --- /dev/null +++ b/tools/topology/topology2/platform/intel/dmic1-passthrough.conf @@ -0,0 +1,237 @@ +Define { + DMIC1_PCM_NAME "DMIC Raw2nd" +} + +Object.Pipeline.host-gateway-capture [ + { + index $DMIC1_HOST_PIPELINE_ID + Object.Widget.host-copier.1 { + stream_name $DMIC1_PCM_CAPS + pcm_id $DMIC1_PCM_ID + num_input_audio_formats 1 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + 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_rate $DMIC1_RATE + 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.Pipeline.io-gateway-capture [ + { + index $DMIC1_DAI_PIPELINE_ID + Object.Widget.dai-copier.1 { + dai_index 1 + dai_type "DMIC" + copier_type "DMIC" + type dai_out + stream_name $DMIC1_NAME + node_type $DMIC_LINK_INPUT_CLASS + num_input_audio_formats 3 + num_output_audio_formats 1 + IncludeByKey.NUM_DMICS { + "1" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + { + in_rate $DMIC1_RATE + in_channels 1 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_MONO + in_ch_map $CHANNEL_MAP_MONO + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_channels 1 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_MONO + out_ch_map $CHANNEL_MAP_MONO + } + ] + } + "2" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + } + { + in_rate $DMIC1_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $DMIC1_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + "4" { + Object.Base.input_audio_format [ + { + in_rate $DMIC1_RATE + in_channels 4 + in_bit_depth 16 + in_valid_bit_depth 16 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC1_RATE + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + in_rate $DMIC1_RATE + 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_rate $DMIC1_RATE + 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.route [ + { + source "dai-copier.DMIC.$DMIC1_NAME.capture" + sink "host-copier.$DMIC1_PCM_ID.capture" + } +] + +Object.PCM.pcm [ + { + name "$DMIC1_PCM_NAME" + id $DMIC1_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$DMIC1_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name $DMIC1_PCM_CAPS + # only 32-bit capture supported now + formats 'S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + IncludeByKey.DMIC1_RATE { + "16000" { + rates '16000' + } + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + } + } + } +] diff --git a/tools/topology/topology2/platform/intel/efx-default.conf b/tools/topology/topology2/platform/intel/efx-default.conf new file mode 100644 index 000000000000..6a152e68a1ef --- /dev/null +++ b/tools/topology/topology2/platform/intel/efx-default.conf @@ -0,0 +1,8 @@ +Define { + EFX_FIR_PARAMS 'passthrough' + EFX_IIR_PARAMS 'passthrough' + EFX_CROSSOVER_PARAMS '2way' + EFX_DRC_PARAMS 'passthrough' + EFX_MBDRC_PARAMS 'passthrough' + EFX_DRC_COMPONENT 'singleband' +} 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..57e9bcfa34da --- /dev/null +++ b/tools/topology/topology2/platform/intel/google-rtc-aec-reference.conf @@ -0,0 +1,118 @@ +Object.Pipeline.google-rtc-aec-capture [ + { + index 18 + core_id $GOOGLE_AEC_CORE_ID + + Object.Widget.pipeline.1 { + stream_name "DMIC0 RTC AEC" + core $GOOGLE_AEC_CORE_ID + priority $GOOGLE_AEC_PIPELINE_PRIORITY + } + + Object.Widget.google-rtc-aec.1 { + core_id $GOOGLE_AEC_DP_CORE_ID + Object.Base.input_pin_binding.1 { + input_pin_binding_name "module-copier.18.1" + } + + Object.Base.input_pin_binding.2 { + input_pin_binding_name "dai-copier.SSP.$SPEAKER_CODEC_NAME.capture" + } + } + } +] + +Object.Pipeline.host-gateway-capture[ + { + index 19 + core_id $GOOGLE_AEC_CORE_ID + + Object.Widget.host-copier.1 { + stream_name "DMIC0 AEC" + pcm_id 27 + } + Object.Widget.pipeline."1" { + core $GOOGLE_AEC_CORE_ID + priority $GOOGLE_AEC_HOST_PIPELINE_PRIORITY + } + } +] + +Object.Pipeline.gain-capture [ + { + index 20 + core_id $GOOGLE_AEC_CORE_ID + + Object.Widget.host-copier.1 { + stream_name "DMIC0 AN" + pcm_id 28 + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'AN Volume' + } + } + Object.Widget.pipeline."1" { + core $GOOGLE_AEC_CORE_ID + } + } +] + +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 "dai-copier.SSP.$SPEAKER_CODEC_NAME.capture" + 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-default.conf b/tools/topology/topology2/platform/intel/hdmi-default.conf new file mode 100644 index 000000000000..587387c219db --- /dev/null +++ b/tools/topology/topology2/platform/intel/hdmi-default.conf @@ -0,0 +1,28 @@ +# Default HDMI variable definitions +Define { + HDMI1_ID 5 + HDMI2_ID 6 + HDMI3_ID 7 + HDMI4_ID 8 + HDMI1_PCM_ID 5 + HDMI2_PCM_ID 6 + HDMI3_PCM_ID 7 + HDMI4_PCM_ID 8 + HDMI1_HOST_PIPELINE_ID 50 + HDMI1_DAI_PIPELINE_ID 51 + HDMI2_HOST_PIPELINE_ID 60 + HDMI2_DAI_PIPELINE_ID 61 + HDMI3_HOST_PIPELINE_ID 70 + HDMI3_DAI_PIPELINE_ID 71 + HDMI4_HOST_PIPELINE_ID 80 + HDMI4_DAI_PIPELINE_ID 81 + HDMI1_PCM_CAPS "HDMI1 Playback" + HDMI2_PCM_CAPS "HDMI2 Playback" + HDMI3_PCM_CAPS "HDMI3 Playback" + HDMI4_PCM_CAPS "HDMI4 Playback" + HDMI1_STREAM "iDisp1" + HDMI2_STREAM "iDisp2" + HDMI3_STREAM "iDisp3" + HDMI4_STREAM "iDisp4" + HDMI_USE_CHAIN_DMA "true" +} diff --git a/tools/topology/topology2/platform/intel/hdmi-generic.conf b/tools/topology/topology2/platform/intel/hdmi-generic.conf new file mode 100644 index 000000000000..69f8e8d13506 --- /dev/null +++ b/tools/topology/topology2/platform/intel/hdmi-generic.conf @@ -0,0 +1,295 @@ +Object.Dai.HDA [ + { + dai_index 4 + name $HDMI1_STREAM + id $HDMI1_ID + default_hw_conf_id 1 + Object.Base.hw_config.1 { + name "HDA4" + } + direction playback + } + { + dai_index 5 + name $HDMI2_STREAM + id $HDMI2_ID + default_hw_conf_id 2 + Object.Base.hw_config.1 { + name "HDA5" + } + direction playback + } + { + dai_index 6 + name $HDMI3_STREAM + id $HDMI3_ID + default_hw_conf_id 3 + Object.Base.hw_config.1 { + name "HDA6" + } + direction playback + } +] + +Object.Pipeline { + host-gateway-playback [ + { + Object.Widget.host-copier.1 { + stream_name $HDMI1_PCM_CAPS + pcm_id $HDMI1_PCM_ID + } + + index $HDMI1_HOST_PIPELINE_ID + use_chain_dma $HDMI_USE_CHAIN_DMA + } + { + Object.Widget.host-copier.1 { + stream_name $HDMI2_PCM_CAPS + pcm_id $HDMI2_PCM_ID + } + + index $HDMI2_HOST_PIPELINE_ID + use_chain_dma $HDMI_USE_CHAIN_DMA + } + { + Object.Widget.host-copier.1 { + stream_name $HDMI3_PCM_CAPS + pcm_id $HDMI3_PCM_ID + } + + index $HDMI3_HOST_PIPELINE_ID + use_chain_dma $HDMI_USE_CHAIN_DMA + } + ] + io-gateway [ + { + direction "playback" + index $HDMI1_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name "iDisp1" + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + + # copier only supports 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 + } + ] + } + use_chain_dma $HDMI_USE_CHAIN_DMA + } + { + direction "playback" + index $HDMI2_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name 'iDisp2' + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + + # copier only supports 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 + } + ] + } + use_chain_dma $HDMI_USE_CHAIN_DMA + } + { + direction "playback" + index $HDMI3_DAI_PIPELINE_ID + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name 'iDisp3' + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + + # copier only supports 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 + } + ] + } + use_chain_dma $HDMI_USE_CHAIN_DMA + } + ] +} + +Object.PCM.pcm [ + { + name HDMI1 + id $HDMI1_PCM_ID + Object.Base.fe_dai.1 { + name "HDMI1" + } + Object.PCM.pcm_caps.1 { + name $HDMI1_PCM_CAPS + formats 'S32_LE,S16_LE,IEC958_SUBFRAME_LE' + channels_max 8 + rates '32000,44100,48000,88200,96000,176400,192000' + } + direction playback + } + { + name HDMI2 + id $HDMI2_PCM_ID + Object.Base.fe_dai.1 { + name "HDMI2" + } + Object.PCM.pcm_caps.1 { + name $HDMI2_PCM_CAPS + formats 'S32_LE,S16_LE,IEC958_SUBFRAME_LE' + channels_max 8 + rates '32000,44100,48000,88200,96000,176400,192000' + } + direction playback + } + { + name HDMI3 + id $HDMI3_PCM_ID + Object.Base.fe_dai.1 { + name "HDMI3" + } + Object.PCM.pcm_caps.1 { + name $HDMI3_PCM_CAPS + formats 'S32_LE,S16_LE,IEC958_SUBFRAME_LE' + channels_max 8 + rates '32000,44100,48000,88200,96000,176400,192000' + } + direction playback + } +] + +# top-level pipeline connections +Object.Base.route [ + { + source "host-copier.$HDMI1_PCM_ID.playback" + sink "dai-copier.HDA.iDisp1.playback" + } + { + source "host-copier.$HDMI2_PCM_ID.playback" + sink "dai-copier.HDA.iDisp2.playback" + } + { + source "host-copier.$HDMI3_PCM_ID.playback" + sink "dai-copier.HDA.iDisp3.playback" + } +] + +# Include HDMI4 DAI, pipelines, PCM and route conditionally +IncludeByKey.NUM_HDMIS { +"4" { + Object.Dai.HDA [ + { + dai_index 7 + name $HDMI4_STREAM + id $HDMI4_ID + default_hw_conf_id 3 + Object.Base.hw_config.1 { + name "HDA6" + } + direction playback + } + ] + Object.Pipeline.io-gateway [ + { + direction "playback" + index $HDMI4_DAI_PIPELINE_ID + + Object.Widget.dai-copier.1 { + node_type $HDA_LINK_OUTPUT_CLASS + stream_name 'iDisp4' + dai_type "HDA" + copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + + # copier only supports 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 + } + ] + } + use_chain_dma $HDMI_USE_CHAIN_DMA + } + ] + Object.Pipeline.host-gateway-playback [ + { + Object.Widget.host-copier.1 { + stream_name $HDMI4_PCM_CAPS + pcm_id $HDMI4_PCM_ID + } + + index $HDMI4_HOST_PIPELINE_ID + use_chain_dma $HDMI_USE_CHAIN_DMA + } + ] + Object.PCM.pcm [ + { + name HDMI4 + id $HDMI4_PCM_ID + Object.Base.fe_dai.1 { + name "HDMI4" + } + Object.PCM.pcm_caps.1 { + name $HDMI4_PCM_CAPS + formats 'S32_LE,S16_LE,IEC958_SUBFRAME_LE' + channels_max 8 + rates '32000,44100,48000,88200,96000,176400,192000' + } + direction playback + } + ] + Object.Base.route [ + { + source "host-copier.$HDMI4_PCM_ID.playback" + sink "dai-copier.HDA.iDisp4.playback" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/hdmi-in-capture.conf b/tools/topology/topology2/platform/intel/hdmi-in-capture.conf new file mode 100644 index 000000000000..77dd17ccd259 --- /dev/null +++ b/tools/topology/topology2/platform/intel/hdmi-in-capture.conf @@ -0,0 +1,180 @@ +IncludeByKey.HDMI_IN_CAPTURE { + "true" "platform/intel/hdmi-in-ssp-config.conf" +} + +Object.Pipeline { + # capture pipelines + host-gateway-capture [ + { + index $HDMI_IN_1_CP_HOST_PIPELINE_ID + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$HDMI_IN_1_NAME.capture" + } + Object.Widget.host-copier.1 { + stream_name $HDMI_IN_1_CP_PCM_CAPS + pcm_id $HDMI_IN_1_PCM_ID + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_rate 48000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_rate 48000 + } + ] + } + } + { + index $HDMI_IN_2_CP_HOST_PIPELINE_ID + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$HDMI_IN_2_NAME.capture" + } + Object.Widget.host-copier.1 { + stream_name $HDMI_IN_2_CP_PCM_CAPS + pcm_id $HDMI_IN_2_PCM_ID + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_rate 48000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_rate 48000 + } + ] + } + } + ] + + io-gateway-capture [ + { + index $HDMI_IN_1_CP_DAI_PIPELINE_ID + + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$HDMI_IN_1_NAME.capture" + } + + Object.Widget.dai-copier."1" { + dai_index $HDMI_IN_1_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name $HDMI_IN_1_NAME + node_type $I2S_LINK_INPUT_CLASS + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_rate 48000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_rate 48000 + } + ] + } + } + { + index $HDMI_IN_2_CP_DAI_PIPELINE_ID + direction "capture" + Object.Widget.pipeline.1 { + stream_name "dai-copier.SSP.$HDMI_IN_2_NAME.capture" + } + + Object.Widget.dai-copier."1" { + dai_index $HDMI_IN_2_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name $HDMI_IN_2_NAME + node_type $I2S_LINK_INPUT_CLASS + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_channels 2 + in_rate 48000 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_channels 2 + out_rate 48000 + } + ] + } + } + ] +} + +Object.Base.route [ + { + source "dai-copier.SSP.$HDMI_IN_1_NAME.capture" + sink "host-copier.$HDMI_IN_1_PCM_ID.capture" + } + { + source "dai-copier.SSP.$HDMI_IN_2_NAME.capture" + sink "host-copier.$HDMI_IN_2_PCM_ID.capture" + } +] + +Object.PCM.pcm [ + { + name $HDMI_IN_1_PCM_NAME + id $HDMI_IN_1_PCM_ID + direction "capture" + + Object.Base.fe_dai.1 { + name $HDMI_IN_1_PCM_NAME + } + + Object.PCM.pcm_caps.1 { + direction "capture" + name $HDMI_IN_1_CP_PCM_CAPS + formats 'S32_LE' + rate_min 48000 + rate_max 48000 + channels_min 2 + channels_max 2 + } + } + { + name $HDMI_IN_2_PCM_NAME + id $HDMI_IN_2_PCM_ID + direction "capture" + + Object.Base.fe_dai.1 { + name $HDMI_IN_2_PCM_NAME + } + + Object.PCM.pcm_caps.1 { + direction "capture" + name $HDMI_IN_2_CP_PCM_CAPS + formats 'S32_LE' + rate_min 48000 + rate_max 48000 + channels_min 2 + channels_max 2 + } + } +] diff --git a/tools/topology/topology2/platform/intel/hdmi-in-default.conf b/tools/topology/topology2/platform/intel/hdmi-in-default.conf new file mode 100644 index 000000000000..0d8e10c21017 --- /dev/null +++ b/tools/topology/topology2/platform/intel/hdmi-in-default.conf @@ -0,0 +1,28 @@ +# Default HDMI-IN variable definitions +Define { + # HDMI_IN_ID is dai link ID that is matched with machine driver + HDMI_IN_1_ID 6 + HDMI_IN_2_ID 7 + # HDMI_IN_INDEX is dai_index which passed to firmware + HDMI_IN_1_INDEX 0 + HDMI_IN_2_INDEX 2 + FORMAT s32le + HDMI_IN_MCLK 38400000 + HDMI_IN_1_NAME "SSP0-HDMI" + HDMI_IN_2_NAME "SSP2-HDMI" + + HDMI_IN_1_CP_HOST_PIPELINE_ID 7 + HDMI_IN_1_CP_DAI_PIPELINE_ID 8 + HDMI_IN_1_CP_PCM_CAPS "HDMI-In-1 Capture" + + HDMI_IN_2_CP_HOST_PIPELINE_ID 9 + HDMI_IN_2_CP_DAI_PIPELINE_ID 10 + HDMI_IN_2_CP_PCM_CAPS "HDMI-In-2 Capture" + + HDMI_IN_1_PCM_ID 1 + HDMI_IN_2_PCM_ID 2 + HDMI_IN_1_PCM_NAME "HDMI-In-1" + HDMI_IN_2_PCM_NAME "HDMI-In-2" + + HDMI_IN_CAPTURE false +} diff --git a/tools/topology/topology2/platform/intel/hdmi-in-ssp-config.conf b/tools/topology/topology2/platform/intel/hdmi-in-ssp-config.conf new file mode 100644 index 000000000000..2da8af66d294 --- /dev/null +++ b/tools/topology/topology2/platform/intel/hdmi-in-ssp-config.conf @@ -0,0 +1,56 @@ +#SSP DAI configuration to receive samples via I2S(in slave mode) +#from HDMI input converter chip. +Object.Dai.SSP [ + { + id $HDMI_IN_1_ID + dai_index $HDMI_IN_1_INDEX + direction "capture" + name $HDMI_IN_1_NAME + default_hw_conf_id 0 + sample_bits 32 + io_clk $HDMI_IN_MCLK + Object.Base.hw_config.1 { + id 0 + name "HDMI-In-1" + mclk_freq $HDMI_IN_MCLK + bclk_freq 3072000 + tdm_slot_width 32 + format "I2S" + bclk "codec_provider" + fsync "codec_provider" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 3 + Object.Base.link_config.1 { + clock_source 0 + } + } + } + { + id $HDMI_IN_2_ID + dai_index $HDMI_IN_2_INDEX + direction "capture" + name $HDMI_IN_2_NAME + default_hw_conf_id 1 + sample_bits 32 + io_clk $HDMI_IN_MCLK + Object.Base.hw_config.1 { + id 0 + name "HDMI-In-2" + mclk_freq $HDMI_IN_MCLK + bclk_freq 3072000 + tdm_slot_width 32 + format "I2S" + bclk "codec_provider" + fsync "codec_provider" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 3 + Object.Base.link_config.1 { + clock_source 0 + } + } + } +] diff --git a/tools/topology/topology2/platform/intel/hw_config_cardinal_clk.conf b/tools/topology/topology2/platform/intel/hw_config_cardinal_clk.conf new file mode 100644 index 000000000000..463e98f97d95 --- /dev/null +++ b/tools/topology/topology2/platform/intel/hw_config_cardinal_clk.conf @@ -0,0 +1,107 @@ +# Hardware config class definition. All attributes defined herein +# are namespaced by alsatplg to "Object.Base.hw_config.NAME.attribute_name" +# +# Object.Base.hw_config.1 { +# id 0 +# bclk_freq 3072000 +# tdm_slot_width 32 +# } +# +# where 1 is the unique instance ID for the hw_config object within the same alsaconf +# node. + +<platform/intel/ssp_aux_config.conf> + +Class.Base."hw_config" { + # + # Argument used to construct hw config (hw config ID) + # + DefineAttribute."id" {} + DefineAttribute."instance" {} + + DefineAttribute."name" { + type "string" + } + + # All attributes are only used for SSP. + DefineAttribute."format" { + type "string" + constraints { + !valid_values [ + "I2S" + "DSP_A" + "DSP_B" + ] + } + } + + DefineAttribute."mclk" { + type "string" + } + + DefineAttribute."mclk_freq" {} + + DefineAttribute."bclk" { + type "string" + } + + DefineAttribute."bclk_freq" { + constraints { + # Allowed values of bclk derived from mclk_freq of 24.576MHz + !valid_values [ + "12288000" + "6144000" + "3072000" + "1536000" + "768000" + "384000" + "256000" + "128000" + ] + } + } + + DefineAttribute."fsync" { + type "string" + } + + DefineAttribute."fsync_freq" {} + + DefineAttribute."tdm_slots" {} + + DefineAttribute."tdm_slot_width" {} + + DefineAttribute."tx_slots" {} + + DefineAttribute."rx_slots" {} + + attributes { + !constructor [ + "id" + ] + !mandatory [ + "name" + ] + # + # hw_config objects instantiated within the same alsaconf node must have unique + # 'instance' attribute + unique "instance" + } + + Object.Base.link_config.1 { + clock_source 1 + } + + #TODO: Add link flags + + format "I2S" + # TODO: Make this immutable + mclk_freq 24576000 + mclk "codec_mclk_in" + bclk "codec_consumer" + fsync "codec_consumer" + fsync_freq 48000 + tdm_slots 2 + tx_slots 3 + rx_slots 3 +} diff --git a/tools/topology/topology2/platform/intel/lnl.conf b/tools/topology/topology2/platform/intel/lnl.conf new file mode 100644 index 000000000000..2fbb8ed12fa9 --- /dev/null +++ b/tools/topology/topology2/platform/intel/lnl.conf @@ -0,0 +1,9 @@ +# LNL-specific variable definitions +Define { + DMIC_DRIVER_VERSION 4 + SSP_BLOB_VERSION 0x105 + NUM_HDMIS 3 + + # matches with clock_source=1 (Audio Cardinal Clock) + BT_MCLK 24576000 +} diff --git a/tools/topology/topology2/platform/intel/mtl.conf b/tools/topology/topology2/platform/intel/mtl.conf new file mode 100644 index 000000000000..8bd04bdf734a --- /dev/null +++ b/tools/topology/topology2/platform/intel/mtl.conf @@ -0,0 +1,9 @@ +# MTL-specific variable definitions +Define { + DMIC_DRIVER_VERSION 3 + SSP_BLOB_VERSION 0x105 + NUM_HDMIS 3 + + # matches with clock_source=1 (Audio Cardinal Clock) + BT_MCLK 24576000 +} diff --git a/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf b/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf new file mode 100644 index 000000000000..5c69f8a311c9 --- /dev/null +++ b/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf @@ -0,0 +1,66 @@ +Define { + SSP0_AUX_PCM_NAME "Port0 Aux Playback" +} + +Object.Pipeline.host-copier-gain-mixin-playback [ + { + index $SSP0_MIXER_PIPELINE_ID_2 + + Object.Widget.pipeline.1 { + stream_name 'NoCodec-0' + } + 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 { + name 'Pre Mixer $SSP0_AUX_PCM_NAME Volume' + } + } + } +] + +Object.Pipeline.mixout-mixin [ + { + index $SSP0_MIXER_PIPELINE_ID_1 + + Object.Widget.pipeline.1 { + stream_name 'NoCodec-0' + } + } +] + +Object.PCM.pcm [ + { + name "$SSP0_AUX_PCM_NAME" + id $SSP0_MIXER_PCM_ID_1 + direction "playback" + Object.Base.fe_dai."Port0 aux" {} + + Object.PCM.pcm_caps."playback" { + name "SSP0 Aux Playback" + formats 'S16_LE,S24_LE,S32_LE' + } + } +] + +Object.Base.route [ + { + source $SSP0_MIXER_SOURCE_1 + sink $SSP0_MIXER_SINK_2 + } + { + 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/ptl.conf b/tools/topology/topology2/platform/intel/ptl.conf new file mode 100644 index 000000000000..6ce5ede82d3b --- /dev/null +++ b/tools/topology/topology2/platform/intel/ptl.conf @@ -0,0 +1,9 @@ +# PTL-specific variable definitions +Define { + DMIC_DRIVER_VERSION 5 + SSP_BLOB_VERSION 0x300 + NUM_HDMIS 3 + + # matches with clock_source=1 (Audio Cardinal Clock) + BT_MCLK 24576000 +} diff --git a/tools/topology/topology2/platform/intel/sdw-amp-dax.conf b/tools/topology/topology2/platform/intel/sdw-amp-dax.conf new file mode 100644 index 000000000000..f1d93d01e100 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-amp-dax.conf @@ -0,0 +1,742 @@ +# route and pipeline index start from pcm id * 10 + +Define { + SDW_SPK_STREAM 'SDW1-Playback' + SDW_SPK_IN_STREAM 'SDW1-Capture' + ALH_2ND_SPK_ID 22 + ALH_3RD_SPK_ID 23 + ALH_2ND_SPK_IN_ID 32 + ALH_3RD_SPK_IN_ID 33 + SDW_AMP_BE_ID 2 + SDW_AMP_IN_BE_ID 3 + AMP_FEEDBACK_CH 2 + AMP_FEEDBACK_CH_PER_LINK 2 + SDW_AMP_FEEDBACK true + AMP_PLAYBACK_NAME 'Speaker Playback' +} + +# 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)" { + IncludeByKey.DEEP_BUF_SPK { + "true" { + #deep-buffer-spk.conf is included in deep-buffer.conf + #and deep-buffer.conf is included if SDW_JACK is true. + #Therefore, only include deep-buffer-spk.conf when + #SDW_JACK is false to avoid duplicated. + IncludeByKey.SDW_JACK { + "false" "platform/intel/deep-buffer-spk.conf" + } + } + } + } +} + +Object.Dai.ALH [ + { + dai_index 20 + id $SDW_AMP_BE_ID + direction "playback" + name $SDW_SPK_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH514" + } + } +] + +Object.Widget.module-copier."22" { + index 21 + num_input_pins 1 + num_output_pins 2 + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] +} + +Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 20 + + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + pcm_id 2 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + 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 + } + ] + } + } + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + + mixout-gain-dax-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + Object.Widget.dolby-dax.1 { + core_id $DOLBY_DAX_CORE_ID + Object.Control { + mixer."1" { + name 'DAX Speaker Switch' + } + mixer."2" { + name 'DAX Speaker Switch CP' + } + mixer."3" { + name 'DAX Speaker Switch CTC' + } + mixer."4" { + name 'DAX Speaker Volume' + } + enum."1" { + name 'DAX Speaker Profile' + } + enum."2" { + name 'DAX Speaker Device' + } + bytes."1" { + name 'DAX Speaker Tuning' + max 8192 + } + } + } + } + ] +} + +IncludeByKey.NUM_SDW_AMP_LINKS { +"2" { + Define { + AMP_FEEDBACK_CH 4 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + 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 + } + ] + } + + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + ] + } + +"3" { + Define { + AMP_FEEDBACK_CH 6 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + { + index $ALH_3RD_SPK_ID + type dai_in + stream_name $SDW_SPK_STREAM + dai_index 2 + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + { + index $ALH_3RD_SPK_IN_ID + type dai_out + stream_name $SDW_SPK_IN_STREAM + dai_index 2 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + 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_3RD_SPK_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_2ND_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_3RD_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + virtual [ + { + name 'virtual.sdw-amp' + type output + index $ALH_2ND_SPK_ID + } + { + name 'virtual.sdw-amp' + type output + index $ALH_3RD_SPK_ID + } + ] + } + + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.2" + } + ] + } +} + +Object.PCM.pcm [ + { + name "Speaker" + id 2 + direction "playback" + Object.Base.fe_dai.1 { + name "Speaker" + } + + Object.PCM.pcm_caps.1 { + name "sdw amplifiers" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + } + } +] + +Object.Base.route [ + { + source "dolby-dax.21.1" + sink "module-copier.21.22" + } + { + source "module-copier.21.22" + 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 { + "true" { + Object.Dai.ALH [ + { + dai_index 30 + id $SDW_AMP_IN_BE_ID + direction "capture" + name $SDW_SPK_IN_STREAM + default_hw_conf_id 1 + rate 48000 + channels $AMP_FEEDBACK_CH_PER_LINK + + Object.Base.hw_config.1 { + id 1 + name "ALH515" + } + } + ] + Object.Pipeline { + host-gateway-capture [ + { + index 30 + + Object.Widget.host-copier.1 { + stream_name "amp feedback" + pcm_id 3 + + IncludeByKey.AMP_FEEDBACK_CH { + "6" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 6 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + } + "8" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + } + } + ] + } + Object.Widget { + alh-copier [ + { + index 31 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + } + ] + } + ] + pipeline [ + { + index 31 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + Object.PCM.pcm [ + { + name "Amp feedback" + id 3 + direction "capture" + Object.Base.fe_dai.1 { + name "Amp feedback" + } + + Object.PCM.pcm_caps.1 { + name "amp feedback" + formats 'S16_LE,S24_LE,S32_LE' + channels_min $AMP_FEEDBACK_CH + channels_max $AMP_FEEDBACK_CH + } + } + ] + Object.Base.route [ + { + source "alh-copier.$SDW_SPK_IN_STREAM.0" + sink "host-copier.3.capture" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-amp-dts.conf b/tools/topology/topology2/platform/intel/sdw-amp-dts.conf new file mode 100644 index 000000000000..60710c634782 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-amp-dts.conf @@ -0,0 +1,922 @@ +# route and pipeline index start from pcm id * 10 + +Define { + SDW_SPK_STREAM 'SDW1-Playback' + SDW_SPK_IN_STREAM 'SDW1-Capture' + ALH_2ND_SPK_ID 22 + ALH_3RD_SPK_ID 23 + ALH_2ND_SPK_IN_ID 32 + ALH_3RD_SPK_IN_ID 33 + SDW_AMP_BE_ID 2 + SDW_AMP_IN_BE_ID 3 + AMP_FEEDBACK_CH 2 + AMP_FEEDBACK_CH_PER_LINK 2 + SDW_AMP_FEEDBACK true + AMP_PLAYBACK_NAME 'Speaker Playback' +} + +# include deep buffer config if buffer size is in 1 - 1000 ms. +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.DEEPBUFFER_FW_DMA_MS { + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" { + IncludeByKey.DEEP_BUF_SPK { + "true" { + #deep-buffer-spk.conf is included in deep-buffer.conf + #and deep-buffer.conf is included if SDW_JACK is true. + #Therefore, only include deep-buffer-spk.conf when + #SDW_JACK is false to avoid duplicated. + IncludeByKey.SDW_JACK { + "false" "platform/intel/deep-buffer-spk.conf" + } + } + } + } + } +} +} + +Object.Dai.ALH [ + { + dai_index 20 + id $SDW_AMP_BE_ID + direction "playback" + name $SDW_SPK_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH514" + } + } +] + +Object.Widget.module-copier."22" { + index 21 + num_input_pins 1 + num_output_pins 2 + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] +} + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 20 + + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + pcm_id 2 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + 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 + } + ] + } + } + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + mixout-gain-eqiir-dts-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256)) | ($out_sample_type * 65536)]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME IIR Eq bytes' + } + } + + Object.Widget.dts.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DTS bytes' + max 2048 + } + } + } + } + ] + } + "false" { + mixout-gain-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256)) | ($out_sample_type * 65536)]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + } + } + } +} +"true" { + Object.Pipeline.host-gateway-playback [ + { + index 20 + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + 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 { + alh-copier [ + { + stream_name $SDW_SPK_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_pins 1 + direction playback + type dai_in + index 21 + 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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + pipeline [ + { + index 21 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + } +} + +IncludeByKey.NUM_SDW_AMP_LINKS { +"2" { + Define { + AMP_FEEDBACK_CH 4 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + 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. + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "virtual.sdw-amp" + } + ] + } + } + Object.Base.route [ + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + ] + } + +"3" { + Define { + AMP_FEEDBACK_CH 6 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + { + index $ALH_3RD_SPK_ID + stream_name $SDW_SPK_STREAM + dai_index 2 + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + { + index $ALH_3RD_SPK_IN_ID + stream_name $SDW_SPK_IN_STREAM + dai_index 2 + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + 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_3RD_SPK_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_2ND_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_3RD_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + virtual [ + { + name 'virtual.sdw-amp' + type output + index $ALH_2ND_SPK_ID + } + { + name 'virtual.sdw-amp' + type output + index $ALH_3RD_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. + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "virtual.sdw-amp" + } + ] + } + } + Object.Base.route [ + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.2" + } + ] + } +} + +Object.PCM.pcm [ + { + name "Speaker" + id 2 + direction "playback" + Object.Base.fe_dai.1 { + name "Speaker" + } + + Object.PCM.pcm_caps.1 { + name "sdw amplifiers" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + Object.Base.route [ + { + source "dts.21.1" + sink "module-copier.21.22" + } + { + source "module-copier.21.22" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "module-copier.21.22" + } + { + source "module-copier.21.22" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } + } + Object.Base.route [ + { + source 'mixin.20.1' + sink 'mixout.21.1' + } + { + source 'host-copier.2.playback' + sink 'gain.20.1' + } + ] +} +"true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] +} +} + +IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + Object.Dai.ALH [ + { + dai_index 30 + id $SDW_AMP_IN_BE_ID + direction "capture" + name $SDW_SPK_IN_STREAM + default_hw_conf_id 1 + rate 48000 + channels $AMP_FEEDBACK_CH_PER_LINK + + Object.Base.hw_config.1 { + id 1 + name "ALH515" + } + } + ] + Object.Pipeline { + host-gateway-capture [ + { + index 30 + + Object.Widget.host-copier.1 { + stream_name "amp feedback" + pcm_id 3 + + IncludeByKey.AMP_FEEDBACK_CH { + "6" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 6 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + } + "8" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + } + } + ] + } + Object.Widget { + alh-copier [ + { + index 31 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + } + ] + } + ] + pipeline [ + { + index 31 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + Object.PCM.pcm [ + { + name "Amp feedback" + id 3 + direction "capture" + Object.Base.fe_dai.1 { + name "Amp feedback" + } + + Object.PCM.pcm_caps.1 { + name "amp feedback" + formats 'S16_LE,S24_LE,S32_LE' + channels_min $AMP_FEEDBACK_CH + channels_max $AMP_FEEDBACK_CH + } + } + ] + Object.Base.route [ + { + source "alh-copier.$SDW_SPK_IN_STREAM.0" + sink "host-copier.3.capture" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-amp-echo-ref.conf b/tools/topology/topology2/platform/intel/sdw-amp-echo-ref.conf new file mode 100644 index 000000000000..abde20519f2e --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-amp-echo-ref.conf @@ -0,0 +1,52 @@ +Define { + SDW_SPK_ECHO_REF_PCM_ID 12 + SDW_SPK_ECHO_REF_PIPELINE_ID 120 +} + +IncludeByKey.SDW_SPK_ECHO_REF { + "true" { + Object.Pipeline { + siggen-host-copier-capture [ + { + direction "capture" + index $SDW_SPK_ECHO_REF_PIPELINE_ID + Object.Widget.host-copier."1" { + stream_name "Speaker Echo Reference" + pcm_id $SDW_SPK_ECHO_REF_PCM_ID + } + Object.Widget.siggen."1" {} + } + ] + } + + Object.PCM.pcm [ + { + name "Speaker Echo Reference" + id $SDW_SPK_ECHO_REF_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "Speaker Echo Reference" + } + Object.PCM.pcm_caps.1 { + name "Speaker Echo Reference" + formats 'S16_LE,S24_LE,S32_LE' + } + } + ] + + Object.Base.route [ + { + source "alh-copier.Loopback_Virtual.25" + sink "siggen.$SDW_SPK_ECHO_REF_PIPELINE_ID.1" + } + { + source "module-copier.21.22" + sink "siggen.$SDW_SPK_ECHO_REF_PIPELINE_ID.1" + } + { + source "siggen.$SDW_SPK_ECHO_REF_PIPELINE_ID.1" + sink "host-copier.$SDW_SPK_ECHO_REF_PCM_ID.capture" + } + ] + } # SDW_SPK_ECHO_REF true +} diff --git a/tools/topology/topology2/platform/intel/sdw-amp-generic-ctc.conf b/tools/topology/topology2/platform/intel/sdw-amp-generic-ctc.conf new file mode 100644 index 000000000000..dd78692f1aa5 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-amp-generic-ctc.conf @@ -0,0 +1,853 @@ +# route and pipeline index start from pcm id * 10 + +Define { + SDW_SPK_STREAM 'SDW1-Playback' + SDW_SPK_IN_STREAM 'SDW1-Capture' + ALH_2ND_SPK_ID 22 + ALH_3RD_SPK_ID 23 + ALH_2ND_SPK_IN_ID 32 + ALH_3RD_SPK_IN_ID 33 + SDW_AMP_BE_ID 2 + SDW_AMP_IN_BE_ID 3 + AMP_FEEDBACK_CH 2 + AMP_FEEDBACK_CH_PER_LINK 2 + SDW_AMP_FEEDBACK true + AMP_PLAYBACK_NAME 'Speaker Playback' +} + +Object.Dai.ALH [ + { + dai_index 20 + id $SDW_AMP_BE_ID + direction "playback" + name $SDW_SPK_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH514" + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 20 + + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + pcm_id 2 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME IIR Eq bytes' + } + } + Object.Widget.eqfir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME FIR Eq bytes' + } + } + Object.Widget.drc.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DRC bytes' + } + mixer."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DRC switch' + } + } + } + } + ] + } + "false" { + mixout-gain-ctc-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + Object.Widget.ctc.1 { + Object.Control { + mixer."1" { + name 'CTC Switch' + } + bytes."1" { + name 'CTC.0' + max 4160 + } + } + } + } + ] + } + } + + } + } +"true" { + Object.Pipeline.host-gateway-playback [ + { + index 20 + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + 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 { + alh-copier [ + { + stream_name $SDW_SPK_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_pins 1 + direction playback + type dai_in + index 21 + 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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + pipeline [ + { + index 21 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + } +} + +IncludeByKey.NUM_SDW_AMP_LINKS { +"2" { + Define { + AMP_FEEDBACK_CH 4 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + 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. + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "virtual.sdw-amp" + } + ] + } + } + Object.Base.route [ + { + source "virtual.sdw-amp" + sink "ctc.21.1" + } + { + source "ctc.21.1" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + ] + } + +"3" { + Define { + AMP_FEEDBACK_CH 6 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + { + index $ALH_3RD_SPK_ID + type dai_in + stream_name $SDW_SPK_STREAM + dai_index 2 + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + { + index $ALH_3RD_SPK_IN_ID + type dai_out + stream_name $SDW_SPK_IN_STREAM + dai_index 2 + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + 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_3RD_SPK_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_2ND_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_3RD_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + virtual [ + { + name 'virtual.sdw-amp' + type output + index $ALH_2ND_SPK_ID + } + { + name 'virtual.sdw-amp' + type output + index $ALH_3RD_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. + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "virtual.sdw-amp" + } + ] + } + } + Object.Base.route [ + { + source "virtual.sdw-amp" + sink "ctc.21.1" + } + { + source "ctc.21.1" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + { + source "ctc.21.1" + sink "alh-copier.$SDW_SPK_STREAM.2" + } + ] + } +} + +Object.PCM.pcm [ + { + name "Speaker" + id 2 + direction "playback" + Object.Base.fe_dai.1 { + name "Speaker" + } + + Object.PCM.pcm_caps.1 { + name "sdw amplifiers" + formats 'S16_LE,S24_LE,S32_LE' + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + Object.Base.route [ + { + source "drc.21.1" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } + } + Object.Base.route [ + { + source 'mixin.20.1' + sink 'mixout.21.1' + } + { + source 'host-copier.2.playback' + sink 'gain.20.1' + } + ] +} +"true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] +} +} + +IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + Object.Dai.ALH [ + { + dai_index 30 + id $SDW_AMP_IN_BE_ID + direction "capture" + name $SDW_SPK_IN_STREAM + default_hw_conf_id 1 + rate 48000 + channels $AMP_FEEDBACK_CH_PER_LINK + + Object.Base.hw_config.1 { + id 1 + name "ALH515" + } + } + ] + Object.Pipeline { + host-gateway-capture [ + { + index 30 + + Object.Widget.host-copier.1 { + stream_name "amp feedback" + pcm_id 3 + + IncludeByKey.AMP_FEEDBACK_CH { + "6" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 6 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + } + "8" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + } + } + ] + } + Object.Widget { + alh-copier [ + { + index 31 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + } + ] + } + ] + pipeline [ + { + index 31 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + Object.PCM.pcm [ + { + name "Amp feedback" + id 3 + direction "capture" + Object.Base.fe_dai.1 { + name "Amp feedback" + } + + Object.PCM.pcm_caps.1 { + name "amp feedback" + formats 'S16_LE,S24_LE,S32_LE' + channels_min $AMP_FEEDBACK_CH + channels_max $AMP_FEEDBACK_CH + } + } + ] + Object.Base.route [ + { + source "alh-copier.$SDW_SPK_IN_STREAM.0" + sink "host-copier.3.capture" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-amp-generic.conf b/tools/topology/topology2/platform/intel/sdw-amp-generic.conf new file mode 100644 index 000000000000..d4913ca7dd4f --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-amp-generic.conf @@ -0,0 +1,942 @@ +# route and pipeline index start from pcm id * 10 + +Define { + SDW_SPK_STREAM 'SDW1-Playback' + SDW_SPK_IN_STREAM 'SDW1-Capture' + ALH_2ND_SPK_ID 22 + ALH_3RD_SPK_ID 23 + ALH_2ND_SPK_IN_ID 32 + ALH_3RD_SPK_IN_ID 33 + SDW_AMP_BE_ID 2 + SDW_AMP_IN_BE_ID 3 + AMP_FEEDBACK_CH 2 + AMP_FEEDBACK_CH_PER_LINK 2 + SDW_AMP_FEEDBACK true + AMP_PLAYBACK_NAME 'Speaker Playback' +} + +# include deep buffer config if buffer size is in 1 - 1000 ms. +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.DEEPBUFFER_FW_DMA_MS { + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" { + IncludeByKey.DEEP_BUF_SPK { + "true" { + #deep-buffer-spk.conf is included in deep-buffer.conf + #and deep-buffer.conf is included if SDW_JACK is true. + #Therefore, only include deep-buffer-spk.conf when + #SDW_JACK is false to avoid duplicated. + IncludeByKey.SDW_JACK { + "false" "platform/intel/deep-buffer-spk.conf" + } + } + } + } + } +} +} + +Object.Dai.ALH [ + { + dai_index 20 + id $SDW_AMP_BE_ID + direction "playback" + name $SDW_SPK_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH514" + } + } +] + +Object.Widget.module-copier."22" { + index 21 + num_input_pins 1 + num_output_pins 2 + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] +} + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 20 + + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + pcm_id 2 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + 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 + } + ] + } + } + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + mixout-gain-eqiir-eqfir-drc-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME IIR Eq bytes' + } + } + Object.Widget.eqfir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME FIR Eq bytes' + } + } + Object.Widget.drc.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DRC bytes' + } + mixer."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DRC switch' + } + } + } + } + ] + } + "false" { + mixout-gain-alh-dai-copier-playback [ + { + index 21 + + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + } + } + + } + } +"true" { + Object.Pipeline.host-gateway-playback [ + { + index 20 + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + 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 { + alh-copier [ + { + stream_name $SDW_SPK_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_pins 1 + direction playback + type dai_in + index 21 + 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 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + pipeline [ + { + index 21 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + } +} + +IncludeByKey.NUM_SDW_AMP_LINKS { +"2" { + Define { + AMP_FEEDBACK_CH 4 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + 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. + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "virtual.sdw-amp" + } + ] + } + } + Object.Base.route [ + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + ] + } + +"3" { + Define { + AMP_FEEDBACK_CH 6 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + { + index $ALH_3RD_SPK_ID + type dai_in + stream_name $SDW_SPK_STREAM + dai_index 2 + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + { + index $ALH_3RD_SPK_IN_ID + type dai_out + stream_name $SDW_SPK_IN_STREAM + dai_index 2 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + 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_3RD_SPK_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_2ND_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_3RD_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + virtual [ + { + name 'virtual.sdw-amp' + type output + index $ALH_2ND_SPK_ID + } + { + name 'virtual.sdw-amp' + type output + index $ALH_3RD_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. + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "virtual.sdw-amp" + } + ] + } + } + Object.Base.route [ + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.2" + } + ] + } +} + +Object.PCM.pcm [ + { + name "Speaker" + id 2 + direction "playback" + Object.Base.fe_dai.1 { + name "Speaker" + } + + Object.PCM.pcm_caps.1 { + name "sdw amplifiers" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + } + } +] + +IncludeByKey.PASSTHROUGH { + "false" { + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + Object.Base.route [ + { + source "drc.21.1" + sink "module-copier.21.22" + } + { + source "module-copier.21.22" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } + "false" { + Object.Base.route [ + { + source "gain.21.1" + sink "module-copier.21.22" + } + { + source "module-copier.21.22" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } + } + Object.Base.route [ + { + source 'mixin.20.1' + sink 'mixout.21.1' + } + { + source 'host-copier.2.playback' + sink 'gain.20.1' + } + ] + } + "true" { + Object.Base.route [ + { + source "host-copier.2.playback" + sink "alh-copier.$SDW_SPK_STREAM.0" + } + ] + } +} + +IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + Object.Dai.ALH [ + { + dai_index 30 + id $SDW_AMP_IN_BE_ID + direction "capture" + name $SDW_SPK_IN_STREAM + default_hw_conf_id 1 + rate 48000 + channels $AMP_FEEDBACK_CH_PER_LINK + + Object.Base.hw_config.1 { + id 1 + name "ALH515" + } + } + ] + Object.Pipeline { + host-gateway-capture [ + { + index 30 + + Object.Widget.host-copier.1 { + stream_name "amp feedback" + pcm_id 3 + + IncludeByKey.AMP_FEEDBACK_CH { + "6" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 6 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + } + "8" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + } + } + ] + } + Object.Widget { + alh-copier [ + { + index 31 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + } + ] + } + ] + pipeline [ + { + index 31 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + Object.PCM.pcm [ + { + name "Amp feedback" + id 3 + direction "capture" + Object.Base.fe_dai.1 { + name "Amp feedback" + } + + Object.PCM.pcm_caps.1 { + name "amp feedback" + formats 'S16_LE,S24_LE,S32_LE' + channels_min $AMP_FEEDBACK_CH + channels_max $AMP_FEEDBACK_CH + } + } + ] + Object.Base.route [ + { + source "alh-copier.$SDW_SPK_IN_STREAM.0" + sink "host-copier.3.capture" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-amp-xover.conf b/tools/topology/topology2/platform/intel/sdw-amp-xover.conf new file mode 100644 index 000000000000..3347d4911bc4 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-amp-xover.conf @@ -0,0 +1,1003 @@ +# route and pipeline index start from pcm id * 10 + +Define { + SDW_SPK_STREAM 'SDW1-Playback' + SDW_SPK_IN_STREAM 'SDW1-Capture' + ALH_2ND_SPK_ID 22 + ALH_3RD_SPK_ID 23 + ALH_2ND_SPK_IN_ID 32 + ALH_3RD_SPK_IN_ID 33 + SDW_AMP_BE_ID 2 + SDW_AMP_IN_BE_ID 3 + AMP_FEEDBACK_CH 2 + AMP_FEEDBACK_CH_PER_LINK 2 + SDW_AMP_FEEDBACK true + AMP_PLAYBACK_NAME 'Speaker Playback' +} + +Object.Dai.ALH [ + { + dai_index 20 + id $SDW_AMP_BE_ID + direction "playback" + name $SDW_SPK_STREAM + default_hw_conf_id 0 + rate 48000 + + Object.Base.hw_config.1 { + id 0 + name "ALH514" + } + } +] + +Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 20 + + Object.Widget.host-copier.1 { + stream_name "sdw amplifiers" + pcm_id 2 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $AMP_PLAYBACK_NAME Volume' + } + } + } + ] + + IncludeByKey.SDW_SPK_ENHANCED_PLAYBACK { + "true" { + mixout-gain-eqiir-eqfir-drc-micsel-eqiir-eqfir-alh-dai-copier-playback [ + { + index 21 + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_channels $SDW_AMP_NUM_CHANNELS + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_bit_depth 32 + in_valid_bit_depth 32 + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels $SDW_AMP_NUM_CHANNELS + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME IIR Eq bytes' + } + } + Object.Widget.eqfir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME FIR Eq bytes' + } + } + Object.Widget.drc.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DRC bytes' + } + mixer."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME DRC switch' + } + } + } + Object.Widget.micsel.1 { + 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 [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME Xover Selector bytes' + } + } + Object.Widget.eqiir.2 { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME Xover IIR bytes' + } + } + Object.Widget.eqfir.2 { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME Xover FIR bytes' + } + } + } + ] + } + "false" { + mixout-gain-micsel-eqiir-eqfir-alh-dai-copier-playback [ + { + index 21 + Object.Widget.alh-copier.1 { + stream_name $SDW_SPK_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_channels $SDW_AMP_NUM_CHANNELS + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_bit_depth 32 + in_valid_bit_depth 32 + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_channels $SDW_AMP_NUM_CHANNELS + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $AMP_PLAYBACK_NAME Volume' + } + } + Object.Widget.micsel.1 { + 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 [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME Xover Selector bytes' + } + } + Object.Widget.eqiir.2 { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME Xover IIR bytes' + } + } + Object.Widget.eqfir.2 { + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_channels $SDW_AMP_NUM_CHANNELS + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_channels $SDW_AMP_NUM_CHANNELS + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + Object.Control.bytes."1" { + name 'Post Mixer $AMP_PLAYBACK_NAME Xover FIR bytes' + } + } + } + ] + } + } +} + +IncludeByKey.NUM_SDW_AMP_LINKS { +"2" { + Define { + AMP_FEEDBACK_CH 4 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + Object.Base.input_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + in_bit_depth 32 + in_valid_bit_depth 32 + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + IncludeByKey.SDW_AMP_NUM_CHANNELS { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + 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 "eqfir.21.2" + sink "virtual.sdw-amp" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + ] + } + +"3" { + Define { + AMP_FEEDBACK_CH 6 + AMP_FEEDBACK_CH_PER_LINK 2 + } + + Object.Widget { + alh-copier [ + { + index $ALH_2ND_SPK_ID + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + { + index $ALH_3RD_SPK_ID + type dai_in + stream_name $SDW_SPK_STREAM + dai_index 2 + 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 + 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 $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + IncludeByKey.SDW_AMP_FEEDBACK { + "true" { + alh-copier [ + { + index $ALH_2ND_SPK_IN_ID + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + { + index $ALH_3RD_SPK_IN_ID + type dai_out + stream_name $SDW_SPK_IN_STREAM + dai_index 2 + 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 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_channels $AMP_FEEDBACK_CH + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + 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_3RD_SPK_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_2ND_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_3RD_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + virtual [ + { + name 'virtual.sdw-amp' + type output + index $ALH_2ND_SPK_ID + } + { + name 'virtual.sdw-amp' + type output + index $ALH_3RD_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" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.2" + } + ] + } +} + +Object.PCM.pcm [ + { + name "Speaker" + id 2 + direction "playback" + Object.Base.fe_dai.1 { + name "Speaker" + } + + Object.PCM.pcm_caps.1 { + name "sdw amplifiers" + formats 'S16_LE,S24_LE,S32_LE' + } + } +] + +Object.Base.route [ + { + source "eqfir.21.2" + 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 { + "true" { + Object.Dai.ALH [ + { + dai_index 30 + id $SDW_AMP_IN_BE_ID + direction "capture" + name $SDW_SPK_IN_STREAM + default_hw_conf_id 1 + rate 48000 + channels $AMP_FEEDBACK_CH_PER_LINK + + Object.Base.hw_config.1 { + id 1 + name "ALH515" + } + } + ] + Object.Pipeline { + host-gateway-capture [ + { + index 30 + + Object.Widget.host-copier.1 { + stream_name "amp feedback" + pcm_id 3 + + IncludeByKey.AMP_FEEDBACK_CH { + "4" { + num_input_audio_formats 1 + num_output_audio_formats 3 + 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 24 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + { + 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 + } + { + out_channels 4 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + "6" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 6 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + { + out_channels 6 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + ] + } + "8" { + num_input_audio_formats 1 + num_output_audio_formats 3 + Object.Base.input_audio_format [ + { + in_channels 8 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 24 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + { + out_channels 8 + out_bit_depth 16 + out_valid_bit_depth 16 + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + ] + } + } + } + } + ] + } + Object.Widget { + alh-copier [ + { + index 31 + 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 + + Object.Base.input_audio_format [ + { + in_channels $AMP_FEEDBACK_CH + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + in_ch_cfg $CHANNEL_CONFIG_STEREO + in_ch_map $CHANNEL_MAP_STEREO + } + "4" { + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + in_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + in_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + in_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + in_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_channels $AMP_FEEDBACK_CH + out_bit_depth 32 + out_valid_bit_depth 32 + + IncludeByKey.AMP_FEEDBACK_CH { + "2" { + out_ch_cfg $CHANNEL_CONFIG_STEREO + out_ch_map $CHANNEL_MAP_STEREO + } + "4" { + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + "6" { + out_ch_cfg $CHANNEL_CONFIG_5_POINT_1 + out_ch_map $CHANNEL_MAP_5_POINT_1 + } + "8" { + out_ch_cfg $CHANNEL_CONFIG_7_POINT_1 + out_ch_map $CHANNEL_MAP_7_POINT_1 + } + } + } + ] + } + ] + pipeline [ + { + index 31 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + Object.PCM.pcm [ + { + name "Amp feedback" + id 3 + direction "capture" + Object.Base.fe_dai.1 { + name "Amp feedback" + } + + Object.PCM.pcm_caps.1 { + name "amp feedback" + formats 'S16_LE,S24_LE,S32_LE' + channels_min $AMP_FEEDBACK_CH + channels_max $AMP_FEEDBACK_CH + } + } + ] + Object.Base.route [ + { + source "alh-copier.$SDW_SPK_IN_STREAM.0" + sink "host-copier.3.capture" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-dmic-audio-feature.conf b/tools/topology/topology2/platform/intel/sdw-dmic-audio-feature.conf new file mode 100644 index 000000000000..87039b261597 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-dmic-audio-feature.conf @@ -0,0 +1,56 @@ +Define { + SDW_DMIC_MODULE_COPIER_ID 41 + SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_NAME "Microphone Audio Features" + SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_ID 48 + SDW_DMIC_AUDIO_FEATURE_CAPTURE_STREAM_NAME "Microphone Audio Features Stream" + SDW_DMIC_AUDIO_FEATURE_CAPTURE_PIPELINE_ID 131 +} + +Object.Pipeline.host-gateway-src-mfcc-capture [ + { + index $SDW_DMIC_AUDIO_FEATURE_CAPTURE_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name "$SDW_DMIC_AUDIO_FEATURE_CAPTURE_STREAM_NAME" + pcm_id $SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_ID + } + + Object.Widget.mfcc.1 { + Object.Control { + bytes."1" { + name "$SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_NAME MFCC bytes" + <include/components/mfcc/mel80.conf> + } + } + } + } +] +Object.Base.route [ + { + source "module-copier.$SDW_DMIC_MODULE_COPIER_ID.0" + sink "src.$SDW_DMIC_AUDIO_FEATURE_CAPTURE_PIPELINE_ID.1" + } + { + source "mfcc.$SDW_DMIC_AUDIO_FEATURE_CAPTURE_PIPELINE_ID.1" + sink "host-copier.$SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_ID.capture" + } +] + +Object.PCM.pcm [ + { + name "$SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_NAME" + id $SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$SDW_DMIC_AUDIO_FEATURE_CAPTURE_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "$SDW_DMIC_AUDIO_FEATURE_CAPTURE_STREAM_NAME" + formats 'S32_LE' + rates '16000' + channels_min 2 + channels_max 2 + } + } +] diff --git a/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf b/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf new file mode 100644 index 000000000000..f8fc51303966 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf @@ -0,0 +1,284 @@ +# route and pipeline index start from pcm id * 10 + +Define { + SDW_DMIC_CAPTURE_PCM_NAME "Microphone" + SDW_DMIC_STREAM 'SDW3-Capture' + SDW_DMIC_BE_ID 4 + SDW_DMIC_PASSTHROUGH "false" + SDW_DMIC_HOST_PIPELINE_ID 40 +} + +Object.Dai.ALH [ + { + dai_index $SDW_DMIC_HOST_PIPELINE_ID + id $SDW_DMIC_BE_ID + direction "capture" + name $SDW_DMIC_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH771" + } + } +] + +IncludeByKey.SDW_DMIC_ENHANCED_CAPTURE { + + "true" { + Object.Pipeline { + host-gateway-tdfb-drc-capture [ + { + index $SDW_DMIC_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name "sdw dmic" + pcm_id 4 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + } + { + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + 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.tdfb.1 { + Object.Control { + bytes."1" { + name '$SDW_DMIC_CAPTURE_PCM_NAME Capture TDFB bytes' + } + mixer."1" { + name '$SDW_DMIC_CAPTURE_PCM_NAME Capture TDFB beam switch' + } + enum."1" { + name '$SDW_DMIC_CAPTURE_PCM_NAME Capture TDFB angle set enum' + } + } + } + + Object.Widget.drc.1 { + Object.Control { + bytes."1" { + name '$SDW_DMIC_CAPTURE_PCM_NAME Capture DRC bytes' + } + mixer."1" { + name '$SDW_DMIC_CAPTURE_PCM_NAME Capture DRC switch' + } + } + } + } + ] + } + } + "false" { + Object.Pipeline { + host-gateway-capture [ + { + index $SDW_DMIC_HOST_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name "sdw dmic" + pcm_id 4 + } + } + ] + } + } +} + +Object.Widget { + alh-copier [ + { + index 41 + 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 $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + 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 + + IncludeByKey.SDW_DMIC_PASSTHROUGH { + "false" { + Object.Widget.eqiir [ + { + num_input_audio_formats 1 + num_output_audio_formats 1 + # index 41 is in herited from the pipeline definition + 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 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + name '$SDW_DMIC_CAPTURE_PCM_NAME Capture IIR Eq' + } + } + ] + Object.Widget.module-copier [ + { + num_input_audio_formats 1 + num_output_audio_formats 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 + } + ] + } + ] + } + } + } + ] +} + +Object.PCM.pcm [ + { + name "Microphone" + id 4 + direction "capture" + Object.Base.fe_dai.1 { + name "SDW DMIC" + } + + Object.PCM.pcm_caps.1 { + name "sdw dmic" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + } + } +] + +IncludeByKey.SDW_DMIC_PASSTHROUGH { + "true" { + Object.Base.route [ + { + source "alh-copier.$SDW_DMIC_STREAM.0" + sink "host-copier.4.capture" + } + ] + } + "false" { + Object.Base.route [ + { + source "alh-copier.$SDW_DMIC_STREAM.0" + sink "eqiir.41.0" + } + { + source "eqiir.41.0" + sink "module-copier.41.0" + } + ] + IncludeByKey.SDW_DMIC_ENHANCED_CAPTURE { + "true" { + Object.Base.route [ + { + source "module-copier.41.0" + sink "tdfb.40.1" + } + { + source "drc.40.1" + sink "host-copier.4.capture" + } + ] + } + "false" { + Object.Base.route [ + { + source "module-copier.41.0" + sink "host-copier.4.capture" + } + ] + } + } + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-jack-audio-feature.conf b/tools/topology/topology2/platform/intel/sdw-jack-audio-feature.conf new file mode 100644 index 000000000000..9645199d6907 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-jack-audio-feature.conf @@ -0,0 +1,56 @@ +Define { + SDW_JACK_MODULE_COPIER_ID 11 + SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_NAME "Jack In Audio Features" + SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_ID 47 + SDW_JACK_AUDIO_FEATURE_CAPTURE_STREAM_NAME "Jack In Audio Features Stream" + SDW_JACK_AUDIO_FEATURE_CAPTURE_PIPELINE_ID 130 +} + +Object.Pipeline.host-gateway-src-mfcc-capture [ + { + index $SDW_JACK_AUDIO_FEATURE_CAPTURE_PIPELINE_ID + + Object.Widget.host-copier.1 { + stream_name "$SDW_JACK_AUDIO_FEATURE_CAPTURE_STREAM_NAME" + pcm_id $SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_ID + } + + Object.Widget.mfcc.1 { + Object.Control { + bytes."1" { + name "$SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_NAME MFCC bytes" + <include/components/mfcc/mel80.conf> + } + } + } + } +] +Object.Base.route [ + { + source "module-copier.$SDW_JACK_MODULE_COPIER_ID.0" + sink "src.$SDW_JACK_AUDIO_FEATURE_CAPTURE_PIPELINE_ID.1" + } + { + source "mfcc.$SDW_JACK_AUDIO_FEATURE_CAPTURE_PIPELINE_ID.1" + sink "host-copier.$SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_ID.capture" + } +] + +Object.PCM.pcm [ + { + name "$SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_NAME" + id $SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "$SDW_JACK_AUDIO_FEATURE_CAPTURE_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "$SDW_JACK_AUDIO_FEATURE_CAPTURE_STREAM_NAME" + formats 'S32_LE' + rates '16000' + channels_min $SDW_JACK_CAPTURE_CH + channels_max $SDW_JACK_CAPTURE_CH + } + } +] diff --git a/tools/topology/topology2/platform/intel/sdw-jack-dax.conf b/tools/topology/topology2/platform/intel/sdw-jack-dax.conf new file mode 100644 index 000000000000..9816d85b2018 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-jack-dax.conf @@ -0,0 +1,517 @@ +# 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" +} + +Define { + JACK_PLAYBACK_PCM_NAME "Jack Out" + JACK_CAPTURE_PCM_NAME "Jack In" + JACK_RATE 48000 +} + +# +# 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 $JACK_RATE + 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 $JACK_RATE + 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 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_rate $JACK_RATE + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + } + } + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $JACK_PLAYBACK_PCM_NAME Playback Volume' + } + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.mixin.1 { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + mixout-gain-dax-alh-dai-copier-playback [ + { + index 1 + + Object.Widget.mixout.1 { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.alh-copier.1 { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256)) | ($out_sample_type * 65536)]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $JACK_PLAYBACK_PCM_NAME Playback Volume' + } + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.dolby-dax.1 { + core_id $DOLBY_DAX_CORE_ID + Object.Control { + mixer."1" { + name 'DAX Headphone Switch' + } + mixer."2" { + name 'DAX Headphone Switch CP' + } + mixer."3" { + name 'DAX Headphone Switch CTC' + } + mixer."4" { + name 'DAX Headphone Volume' + } + enum."1" { + name 'DAX Headphone Profile' + } + enum."2" { + name 'DAX Headphone Device' + } + bytes."1" { + name 'DAX Headphone Tuning' + max 8192 + } + } + } + } + ] + +} + +Object.Pipeline.host-gateway-capture [ + { + index 10 + + Object.Widget.host-copier.1 { + stream_name "Passthrough Capture 0" + pcm_id 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + } + { + out_rate $JACK_RATE + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + } +] + +# Jack capture pipeline widgets +Object.Widget { + module-copier."12" { + index 1 + num_input_pins 1 + num_output_pins 2 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + 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.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + + pipeline [ + { + index 11 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + + Object.Widget.eqiir [ + { + num_input_audio_formats 1 + num_output_audio_formats 1 + # index 11 is inherited from the pipeline definition + # the instance number is automatically generated as '0' + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + name '$JACK_CAPTURE_PCM_NAME Capture IIR Eq' + } + } + ] + } + ] +} + +Object.PCM.pcm [ + { + name "$JACK_PLAYBACK_PCM_NAME" + id 0 + direction "playback" + Object.Base.fe_dai.1 { + name "$JACK_PLAYBACK_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "volume playback 0" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } + { + name "$JACK_CAPTURE_PCM_NAME" + id 1 + direction "capture" + Object.Base.fe_dai.1 { + name "$JACK_CAPTURE_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "Passthrough Capture 0" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + channels_min $SDW_JACK_CAPTURE_CH + channels_max $SDW_JACK_CAPTURE_CH + } + } +] + +Object.Base.route [ + { + source "dolby-dax.1.1" + sink "module-copier.1.12" + } + { + source "module-copier.1.12" + 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/sdw-jack-dts.conf b/tools/topology/topology2/platform/intel/sdw-jack-dts.conf new file mode 100644 index 000000000000..3a72531d7219 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-jack-dts.conf @@ -0,0 +1,632 @@ +# include deep buffer config if buffer size is in 1 - 1000 ms. +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" + } +} +} + +Define { + JACK_PLAYBACK_PCM_NAME "Jack Out" + JACK_CAPTURE_PCM_NAME "Jack In" + JACK_RATE 48000 +} + +# +# 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 $JACK_RATE + 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 $JACK_RATE + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH3" + } + } +] + +# +# Pipeline definitions +# +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 0 + + Object.Widget.host-copier.1 { + stream_name "volume playback 0" + pcm_id 0 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_rate $JACK_RATE + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + } + } + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $JACK_PLAYBACK_PCM_NAME Playback Volume' + } + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.mixin.1 { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + mixout-gain-eqiir-dts-alh-dai-copier-playback [ + { + index 1 + + Object.Widget.mixout.1 { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.alh-copier.1 { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256)) | ($out_sample_type * 65536)]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $JACK_PLAYBACK_PCM_NAME Playback Volume' + } + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + Object.Widget.eqiir.1 { + Object.Control.bytes."1" { + name 'Post Mixer $JACK_PLAYBACK_PCM_NAME IIR Eq bytes' + } + } + + Object.Widget.dts.1 { + Object.Control { + bytes."1" { + name 'Post Mixer $JACK_PLAYBACK_PCM_NAME DTS bytes' + max 2048 + } + } + } + } + ] + } +} +"true" { + Object.Pipeline.host-gateway-playback [ + { + index 0 + Object.Widget.host-copier.1 { + stream_name "volume playback 0" + pcm_id 0 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + Object.Widget { + alh-copier [ + { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + index 1 + type dai_in + direction playback + num_input_pins 1 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + pipeline [ + { + index 1 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + } +} + +Object.Pipeline.host-gateway-capture [ + { + index 10 + + Object.Widget.host-copier.1 { + stream_name "Passthrough Capture 0" + pcm_id 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + } + { + out_rate $JACK_RATE + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + } +] + +# Jack capture pipeline widgets +Object.Widget { + module-copier."12" { + index 1 + num_input_pins 1 + num_output_pins 2 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + 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.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + + pipeline [ + { + index 11 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + + IncludeByKey.PASSTHROUGH { + "false" { + Object.Widget.eqiir [ + { + num_input_audio_formats 1 + num_output_audio_formats 1 + # index 11 is inherited from the pipeline definition + # the instance number is automatically generated as '0' + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + name '$JACK_CAPTURE_PCM_NAME Capture IIR Eq' + } + } + ] + } + } + } + ] +} + +Object.PCM.pcm [ + { + name "$JACK_PLAYBACK_PCM_NAME" + id 0 + direction "playback" + Object.Base.fe_dai.1 { + name "$JACK_PLAYBACK_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "volume playback 0" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } + { + name "$JACK_CAPTURE_PCM_NAME" + id 1 + direction "capture" + Object.Base.fe_dai.1 { + name "$JACK_CAPTURE_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "Passthrough Capture 0" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + channels_min $SDW_JACK_CAPTURE_CH + channels_max $SDW_JACK_CAPTURE_CH + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Base.route [ + { + source "dts.1.1" + sink "module-copier.1.12" + } + { + source "module-copier.1.12" + sink "alh-copier.$SDW_JACK_OUT_STREAM.0" + } + ] + + Object.Base.route [ + { + 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" + } + ] + } +"true" { + Object.Base.route [ + { + source "alh-copier.$SDW_JACK_IN_STREAM.0" + sink "host-copier.1.capture" + } + { + source "host-copier.0.playback" + sink "alh-copier.$SDW_JACK_OUT_STREAM.0" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/sdw-jack-echo-ref.conf b/tools/topology/topology2/platform/intel/sdw-jack-echo-ref.conf new file mode 100644 index 000000000000..fa506c6b2d46 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-jack-echo-ref.conf @@ -0,0 +1,108 @@ +Define { + SDW_JACK_ECHO_REF_PCM_ID 11 + SDW_JACK_ECHO_REF_PIPELINE_ID 12 +} + +IncludeByKey.SDW_JACK_ECHO_REF { + "true" { + Object.Pipeline { + siggen-host-copier-capture [ + { + direction "capture" + index $SDW_JACK_ECHO_REF_PIPELINE_ID + Object.Widget.host-copier."1" { + stream_name "Jack Echo Reference" + pcm_id $SDW_JACK_ECHO_REF_PCM_ID + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.siggen."1" { + num_input_pins 1 + num_output_pins 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + } + + Object.PCM.pcm [ + { + name "Jack Echo Reference" + id $SDW_JACK_ECHO_REF_PCM_ID + direction "capture" + Object.Base.fe_dai.1 { + name "Jack Echo Reference" + } + Object.PCM.pcm_caps.1 { + name "Jack Echo Reference" + formats 'S16_LE,S24_LE,S32_LE' + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + ] + + Object.Base.route [ + { + source "alh-copier.Loopback_Virtual.25" + sink "siggen.$SDW_JACK_ECHO_REF_PIPELINE_ID.1" + } + { + source "module-copier.1.12" + sink "siggen.$SDW_JACK_ECHO_REF_PIPELINE_ID.1" + } + { + source "siggen.$SDW_JACK_ECHO_REF_PIPELINE_ID.1" + sink "host-copier.$SDW_JACK_ECHO_REF_PCM_ID.capture" + } + ] + } # SDW_JACK_ECHO_REF true +} 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..b2e1a259d9a0 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-jack-generic.conf @@ -0,0 +1,639 @@ +# include deep buffer config if buffer size is in 1 - 1000 ms. +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" + } +} +} + +Define { + JACK_PLAYBACK_PCM_NAME "Jack Out" + JACK_CAPTURE_PCM_NAME "Jack In" + JACK_RATE 48000 +} + +# +# 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 $JACK_RATE + 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 $JACK_RATE + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH3" + } + } +] + +# +# Pipeline definitions +# +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 0 + + Object.Widget.host-copier.1 { + stream_name "volume playback 0" + pcm_id 0 + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_input_audio_formats 5 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + in_sample_type $SAMPLE_TYPE_FLOAT + } + { + in_rate $JACK_RATE + in_bit_depth 8 + in_valid_bit_depth 8 + in_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + ] + } + } + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Pre Mixer $JACK_PLAYBACK_PCM_NAME Playback Volume' + } + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.mixin.1 { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + mixout-gain-alh-dai-copier-playback [ + { + index 1 + + Object.Widget.mixout.1 { + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + Object.Widget.alh-copier.1 { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256)) | ($out_sample_type * 65536)]" + } + ] + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Post Mixer $JACK_PLAYBACK_PCM_NAME Playback Volume' + } + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + } +} +"true" { + Object.Pipeline.host-gateway-playback [ + { + index 0 + Object.Widget.host-copier.1 { + stream_name "volume playback 0" + pcm_id 0 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + + Object.Widget { + alh-copier [ + { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + index 1 + type dai_in + direction playback + num_input_pins 1 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth $SDW_LINK_VALID_BITS + out_sample_type $SAMPLE_TYPE_MSB_INTEGER + out_fmt_cfg "$[($out_channels | ($out_valid_bit_depth * 256))]" + } + ] + } + ] + pipeline [ + { + index 1 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + } + } +} + +Object.Pipeline.host-gateway-capture [ + { + index 10 + + Object.Widget.host-copier.1 { + stream_name "Passthrough Capture 0" + pcm_id 1 + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + IncludeByKey.PCM_FORMAT_ALL { + "true" { + num_output_audio_formats 5 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + out_sample_type $SAMPLE_TYPE_FLOAT + } + { + out_rate $JACK_RATE + out_bit_depth 8 + out_valid_bit_depth 8 + out_sample_type $SAMPLE_TYPE_UNSIGNED_INTEGER + } + ] + } + "false" { + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + } + } +] + +# Jack capture pipeline widgets +Object.Widget { + module-copier."12" { + index 1 + num_input_pins 1 + num_output_pins 2 + num_input_audio_formats 1 + num_output_audio_formats 1 + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + 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.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth $SDW_LINK_VALID_BITS + in_sample_type $SAMPLE_TYPE_MSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + + pipeline [ + { + index 11 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + + IncludeByKey.PASSTHROUGH { + "false" { + Object.Widget.eqiir [ + { + num_input_audio_formats 1 + num_output_audio_formats 1 + # index 11 is inherited from the pipeline definition + # the instance number is automatically generated as '0' + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + + Object.Control.bytes."1" { + <include/components/eqiir/highpass_40hz_0db_48khz.conf> + name '$JACK_CAPTURE_PCM_NAME Capture IIR Eq' + } + } + ] + Object.Widget.module-copier [ + { + num_input_audio_formats 1 + num_output_audio_formats 1 + # index 11 is inherited from the pipeline definition + # the instance number is automatically generated as '0' + Object.Base.input_audio_format [ + { + in_rate $JACK_RATE + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_rate $JACK_RATE + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + } + } + } + ] +} + +Object.PCM.pcm [ + { + name "$JACK_PLAYBACK_PCM_NAME" + id 0 + direction "playback" + Object.Base.fe_dai.1 { + name "$JACK_PLAYBACK_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "volume playback 0" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + } + } + { + name "$JACK_CAPTURE_PCM_NAME" + id 1 + direction "capture" + Object.Base.fe_dai.1 { + name "$JACK_CAPTURE_PCM_NAME" + } + + Object.PCM.pcm_caps.1 { + name "Passthrough Capture 0" + IncludeByKey.PCM_FORMAT_ALL { + "true" { + formats 'S16_LE,S24_LE,S32_LE,U8,FLOAT_LE' + } + "false" { + formats 'S16_LE,S24_LE,S32_LE' + } + } + IncludeByKey.JACK_RATE { + "48000" { + rates '48000' + } + "96000" { + rates '96000' + } + "192000" { + rates '192000' + } + } + channels_min $SDW_JACK_CAPTURE_CH + channels_max $SDW_JACK_CAPTURE_CH + } + } +] + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Base.route [ + { + source "gain.1.1" + sink "module-copier.1.12" + } + { + source "module-copier.1.12" + 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 "module-copier.11.0" + } + { + source "module-copier.11.0" + sink "host-copier.1.capture" + } + { + source "host-copier.0.playback" + sink "gain.0.1" + } + ] + } +"true" { + Object.Base.route [ + { + source "alh-copier.$SDW_JACK_IN_STREAM.0" + sink "host-copier.1.capture" + } + { + source "host-copier.0.playback" + sink "alh-copier.$SDW_JACK_OUT_STREAM.0" + } + ] + } +} diff --git a/tools/topology/topology2/platform/intel/speaker-echo-ref.conf b/tools/topology/topology2/platform/intel/speaker-echo-ref.conf new file mode 100644 index 000000000000..0a9590516e6e --- /dev/null +++ b/tools/topology/topology2/platform/intel/speaker-echo-ref.conf @@ -0,0 +1,51 @@ +Object.Pipeline { + io-gateway-capture [ + { + index $ECHO_REF_DAI_PIPELINE_ID + core_id $ECHO_REF_CORE_ID + direction "capture" + + Object.Widget.dai-copier."1" { + core_id $ECHO_REF_CORE_ID + dai_index $SPEAKER_SSP_DAI_INDEX + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name $SPEAKER_CODEC_NAME + node_type $I2S_LINK_INPUT_CLASS + num_input_audio_formats 1 + IncludeByKey.SSP_SPK_FMT_24 { + "true" { + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + in_sample_type $SAMPLE_TYPE_LSB_INTEGER + in_fmt_cfg "$[($in_channels | ($in_valid_bit_depth * 256))]" + } + ] + } + "false" { + 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 16 + out_valid_bit_depth 16 + } + ] + } + Object.Widget.pipeline."1" { + core $ECHO_REF_CORE_ID + priority $ECHO_REF_PIPELINE_PRIORITY + } + } + ] +} diff --git a/tools/topology/topology2/platform/intel/ssp-default.conf b/tools/topology/topology2/platform/intel/ssp-default.conf new file mode 100644 index 000000000000..cab144bd5da9 --- /dev/null +++ b/tools/topology/topology2/platform/intel/ssp-default.conf @@ -0,0 +1,12 @@ +# Default SSP variable definitions +Define { + SSP0_RATE 48000 + SSP0_BCLK_FREQ 3072000 + SSP0_TDM_SLOT_WIDTH 32 + SSP1_RATE 48000 + SSP1_BCLK_FREQ 3072000 + SSP1_TDM_SLOT_WIDTH 32 + SSP2_RATE 48000 + SSP2_BCLK_FREQ 3072000 + SSP2_TDM_SLOT_WIDTH 32 +} diff --git a/tools/topology/topology2/platform/intel/ssp_aux_config.conf b/tools/topology/topology2/platform/intel/ssp_aux_config.conf new file mode 100644 index 000000000000..c084faa4195c --- /dev/null +++ b/tools/topology/topology2/platform/intel/ssp_aux_config.conf @@ -0,0 +1,282 @@ +## \struct mn_config + +Class.Base."mn_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Value of m in m/n divider + # + DefineAttribute."m_div" {} + + # + # Value of n in m/n divider + # + DefineAttribute."n_div" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + + +Class.Base."clk_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Value of clock warm up delay in ms + # + DefineAttribute."clock_warm_up" {} + + # + # Value set to 1 -> target is MCLK, otherwise SCLK + # + DefineAttribute."mclk" {} + + # + # Value set to 1 -> clock starts immediately + # + DefineAttribute."warm_up_ovr" {} + + # + # Value of clock stopped after the interface, in ms + # + DefineAttribute."clock_stop_delay" {} + + # + # Value set to 1 means clock should be kept running + # + DefineAttribute."keep_running" {} + + # + # Value set to 1 -> clock stops immediately + # + DefineAttribute."clock_stop_ovr" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."tr_start_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Values for audio format for "not running state" 0 value sample generation + # + DefineAttribute."sampling_frequency" {} + DefineAttribute."bit_depth" {} + DefineAttribute."channel_map" {} + DefineAttribute."channel_config" {} + DefineAttribute."interleaving_style" {} + DefineAttribute."number_of_channels" {} + DefineAttribute."valid_bit_depth" {} + DefineAttribute."sample_type" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."tr_stop_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Values for audio format for "not running state" 0 value sample generation + # + DefineAttribute."sampling_frequency" {} + DefineAttribute."bit_depth" {} + DefineAttribute."channel_map" {} + DefineAttribute."channel_config" {} + DefineAttribute."interleaving_style" {} + DefineAttribute."number_of_channels" {} + DefineAttribute."valid_bit_depth" {} + DefineAttribute."sample_type" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."run_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Value set to 1 -> transfer/production of 0 samples will + # continue in consumer mode even without clock + # + DefineAttribute."always_run" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."sync_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Value in Hz for global sync denominator for all linked items + # + DefineAttribute."sync_denominator" {} + + # + # Follows variable amount of synced node_config items, see above + # + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."node_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Gateway id of the to be synced node + # + DefineAttribute."node_id" {} + + # + # Sample rate of the to be synced node + # + DefineAttribute."sampling_rate" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."ext_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Boolean values for overriding default policies for + # enabling/disabling MCLK + # + DefineAttribute."mclk_policy_override" {} + DefineAttribute."mclk_always_running" {} + DefineAttribute."mclk_starts_on_gtw_init" {} + DefineAttribute."mclk_starts_on_run" {} + DefineAttribute."mclk_starts_on_pause" {} + DefineAttribute."mclk_stops_on_pause" {} + DefineAttribute."mclk_stops_on_reset" {} + + # + # Boolean values for overriding default policies for + # enabling/disabling BCLK + # + DefineAttribute."bclk_policy_override" {} + DefineAttribute."bclk_always_running" {} + DefineAttribute."bclk_starts_on_gtw_init" {} + DefineAttribute."bclk_starts_on_run" {} + DefineAttribute."bclk_starts_on_pause" {} + DefineAttribute."bclk_stops_on_pause" {} + DefineAttribute."bclk_stops_on_reset" {} + + # + # Boolean values for overriding default policies for + # enabling/disabling SYNC + # + DefineAttribute."sync_policy_override" {} + DefineAttribute."sync_always_running" {} + DefineAttribute."sync_starts_on_gtw_init" {} + DefineAttribute."sync_starts_on_run" {} + DefineAttribute."sync_starts_on_pause" {} + DefineAttribute."sync_stops_on_pause" {} + DefineAttribute."sync_stops_on_reset" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} + +Class.Base."link_config" { + DefineAttribute."id" {} + + DefineAttribute."name" { + type "string" + } + + # + # Value for provider link clock source: + # + # XTAL 0 + # CARDINAL 1 + # PLL 2 + # MCLK 3 + # WOV_CRO 4 + # + DefineAttribute."clock_source" {} + + attributes { + !constructor [ + "id" + ] + + unique "name" + } +} diff --git a/tools/topology/topology2/platform/intel/tgl.conf b/tools/topology/topology2/platform/intel/tgl.conf new file mode 100644 index 000000000000..8f8df2db4b7d --- /dev/null +++ b/tools/topology/topology2/platform/intel/tgl.conf @@ -0,0 +1,4 @@ +# TGL/ADL-specific variable definitions +Define { + SSP_BLOB_VERSION 0x100 +} diff --git a/tools/topology/topology2/production/CMakeLists.txt b/tools/topology/topology2/production/CMakeLists.txt new file mode 100644 index 000000000000..c2cb86400e4b --- /dev/null +++ b/tools/topology/topology2/production/CMakeLists.txt @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: BSD-3-Clause + +include(tplg-targets-hda-generic.cmake) +include(tplg-targets-sdca-generic.cmake) +include(tplg-targets-cavs25.cmake) +include(tplg-targets-ace1.cmake) +include(tplg-targets-ace2.cmake) +include(tplg-targets-ace3.cmake) +include(tplg-targets-ace4.cmake) +include(tplg-targets-imx8.cmake) + +add_custom_target(topology2_prod) + +foreach(tplg ${TPLGS}) + set(defines "") + list(LENGTH tplg length) + list(GET tplg 0 input) + list(GET tplg 1 output) + + math(EXPR last_index "${length}-1") + + # Get the pre-processor definitions from the 3rd item in the list for each topology + # ex: "hda-generic\;hda-generic-2ch\;HDA_CONFIG=gain,DMIC_CH=2", "defines" would contain "HDA_CONFIG=gain,DMIC_CH=2" + if (${last_index} EQUAL 2) + list(GET tplg ${last_index} defines) + endif() + + add_alsatplg2_command("${CMAKE_CURRENT_BINARY_DIR}/../abi.conf" abi_target + "${CMAKE_CURRENT_SOURCE_DIR}/../${input}" "${output}" + "${CMAKE_CURRENT_SOURCE_DIR}/../" "${defines}") + + add_custom_target(topology2_prod_${output} DEPENDS ${output}.tplg) + add_dependencies(topology2_prod topology2_prod_${output}) +endforeach() diff --git a/tools/topology/topology2/production/tplg-targets-ace1.cmake b/tools/topology/topology2/production/tplg-targets-ace1.cmake new file mode 100644 index 000000000000..6c3bc7214663 --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-ace1.cmake @@ -0,0 +1,365 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# SDW + DMIC topology with passthrough pipelines +"cavs-sdw\;sof-mtl-rt711-2ch\;PLATFORM=mtl,NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,\ +DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt711-2ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"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,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt711-4ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-rt711-l0-rt1316-l23-rt714-l1\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_SPK_STREAM=SDW2-Playback,SDW_SPK_IN_STREAM=SDW2-Capture,SDW_DMIC_STREAM=SDW1-Capture" + +"cavs-sdw\;sof-mtl-rt711-l0-rt1316-l3\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW3-Playback,SDW_SPK_IN_STREAM=SDW3-Capture,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6" + +"cavs-sdw\;sof-mtl-rt711-l0-rt1316-l3-4ch\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW3-Playback,SDW_SPK_IN_STREAM=SDW3-Capture,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt711-l0-rt1316-l3-4ch.bin,\ +HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-rt711-l0-rt1316-l3-2ch\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW3-Playback,SDW_SPK_IN_STREAM=SDW3-Capture,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt711-l0-rt1316-l3-2ch.bin,\ +HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-rt712-l0-rt1712-l3\;PLATFORM=mtl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-mtl-rt712-l0\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +HDMI1_ID=3,HDMI2_ID=4,HDMI3_ID=5" + +"cavs-sdw\;sof-mtl-rt712-vb-l0\;PLATFORM=mtl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-mtl-rt712-l0-4ch\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt712-l0-4ch.bin,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# sof_sdw creates dmic01 and dmic16k no matter 1 or 2 dmics are present. +# So, HDMI link ids are the same for -2ch and -4ch topologies. +"cavs-sdw\;sof-mtl-rt712-l0-2ch\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt712-l0-2ch.bin,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-rt1318-l12-rt714-l0\;PLATFORM=mtl,SDW_JACK=false,SDW_DMIC=1,\ +NUM_SDW_AMP_LINKS=2,SDW_SPK_STREAM=SDW1-Playback,SDW_SPK_IN_STREAM=SDW1-Capture,\ +SDW_DMIC_STREAM=SDW0-Capture" + +"cavs-sdw\;sof-mtl-rt713-l0-rt1316-l12-rt1713-l3\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1" + +"cavs-sdw\;sof-mtl-rt713-l0-rt1318-l12-rt1713-l3\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1" + +"cavs-sdw\;sof-mtl-rt713-l0-rt1318-l1-rt1713-l3\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1" + +# Jack codec + SmartAmp topology. No SDW_DMIC connection +"cavs-sdw\;sof-mtl-rt713-l0-rt1316-l12\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6" + +"cavs-sdw\;sof-mtl-rt722-l0\;PLATFORM=mtl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-mtl-cs42l43-l0\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-mtl-cs42l43-l0-cs35l56-l12\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_SPK_STREAM=Playback-SmartAmp,SDW_SPK_IN_STREAM=Capture-SmartAmp,\ +SDW_DMIC_STREAM=Capture-SmartMic,SDW_JACK_OUT_STREAM=Playback-SimpleJack,\ +SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-mtl-cs42l43-l0-cs35l56-l23\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +# CS42L43 speaker output aggregated with two buses of CS35L56, so total +# number of amp links is 3. +"cavs-sdw\;sof-mtl-cs42l43-l3-cs35l56-l01-spkagg\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=3,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-mtl-cs35l56-l01-fb8\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=true,SDW_SPK_STREAM=Playback,SDW_SPK_IN_STREAM=Capture,\ +AMP_FEEDBACK_CH=8,AMP_FEEDBACK_CH_PER_LINK=4,SDW_JACK=false,NUM_DMICS=0,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,SDW_SPK_ENHANCED_PLAYBACK=false" + +"cavs-sdw\;sof-mtl-cs35l56-l01-fb6\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=true,SDW_SPK_STREAM=Playback,SDW_SPK_IN_STREAM=Capture,\ +AMP_FEEDBACK_CH=6,AMP_FEEDBACK_CH_PER_LINK=3,SDW_JACK=false,NUM_DMICS=0,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,SDW_SPK_ENHANCED_PLAYBACK=false" + +# ARL has the same DSP generation. So reuse the platform = mtl. +"cavs-sdw\;sof-arl-cs42l43-l0\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-arl-cs42l43-l0-cs35l56-l2\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-arl-cs42l43-l0-cs35l56-l2-2ch\;PLATFORM=mtl,\ +NUM_SDW_AMP_LINKS=1,SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=sof-arl-cs42l43-l0-cs35l56-l2-2ch.bin,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7" + +"cavs-sdw\;sof-arl-cs42l43-l0-cs35l56-l23\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-arl-cs42l43-l2\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-arl-cs42l43-l2-cs35l56-l3\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-arl-cs42l43-l2-cs35l56-l3-2ch\;PLATFORM=mtl,\ +NUM_SDW_AMP_LINKS=1,SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=sof-arl-cs42l43-l2-cs35l56-l3-2ch.bin,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7" + +"cavs-sdw\;sof-arl-rt711-l0\;PLATFORM=mtl,HDMI1_ID=2,HDMI2_ID=3,HDMI3_ID=4" + +"cavs-sdw\;sof-arl-rt711-l0-2ch\;PLATFORM=mtl,NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,\ +DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-arl-rt711-2ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-rt711-l0-4ch\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-arl-rt711-4ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-rt722-l0_rt1320-l2\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-arl-rt711-l0-rt1316-l3\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW3-Playback,SDW_SPK_IN_STREAM=SDW3-Capture,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6" + +"cavs-sdw\;sof-arl-rt711-l0-rt1316-l3-4ch\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW3-Playback,SDW_SPK_IN_STREAM=SDW3-Capture,\ +NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-arl-rt711-l0-rt1316-l3-4ch.bin,\ +HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-rt711-l0-rt1316-l3-2ch\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW3-Playback,SDW_SPK_IN_STREAM=SDW3-Capture,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-arl-rt711-l0-rt1316-l3-2ch.bin,\ +HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# Split topologies +"cavs-sdw\;sof-arl-dmic-2ch-id2\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-2ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-2ch-id3\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-2ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-2ch-id4\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-2ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-2ch-id5\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-2ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-4ch-id2\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-4ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-4ch-id3\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-4ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-4ch-id4\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-4ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-arl-dmic-4ch-id5\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-arl-dmic-4ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-2ch-id2\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-2ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-2ch-id3\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-2ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-2ch-id4\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-2ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-2ch-id5\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-2ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-4ch-id2\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-4ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-4ch-id3\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-4ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-4ch-id4\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-4ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-mtl-dmic-4ch-id5\;PLATFORM=mtl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-dmic-4ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# 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,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true" + +# Note this is same as above but different tplg name +"cavs-rt5682\;sof-mtl-max98360a-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,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true" + +"cavs-rt5682\;sof-mtl-max98357a-rt5682-google-aec\;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-google-aec.bin,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +BT_ID=7,BT_PCM_NAME=Bluetooth,GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true" + +"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-ssp2-ssp0.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,DEEP_BUF_SPK=true" + +"cavs-rt5682\;sof-mtl-max98357a-rt5682-ssp2-ssp0-google-aec\;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-ssp2-ssp0-google-aec.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true,GOOGLE_AEC_DP_CORE_ID=2" + +"cavs-rt5682\;sof-mtl-max98357a-rt5682-ssp2-ssp0-2ch-pdm1\;PLATFORM=mtl,NUM_DMICS=2,\ +PDM0_MIC_A_ENABLE=0,PDM0_MIC_B_ENABLE=0,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-max98357a-rt5682-2ch.bin,\ +HEADSET_SSP_DAI_INDEX=2,SPEAKER_SSP_DAI_INDEX=0,SPK_ID=6,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true" + +"cavs-rt5682\;sof-mtl-max98357a-rt5682-ssp2-ssp0-2ch-pdm1-google-aec\;PLATFORM=mtl,NUM_DMICS=2,\ +PDM0_MIC_A_ENABLE=0,PDM0_MIC_B_ENABLE=0,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-max98357a-rt5682-2ch-google-aec.bin,\ +HEADSET_SSP_DAI_INDEX=2,SPEAKER_SSP_DAI_INDEX=0,SPK_ID=6,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +DEEPBUFFER_FW_DMA_MS=10,GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true,\ +GOOGLE_AEC_DP_CORE_ID=2" + +"cavs-rt5682\;sof-mtl-rt1019-rt5682\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,SPK_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-rt1019-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,\ +INCLUDE_ECHO_REF=true,BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true" + +"cavs-rt5682\;sof-mtl-rt5650\;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-rt5650.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +DEEP_BUF_SPK=true,SSP_SPK_FMT_24=true,SSP_HS_FMT_24=true" + +"cavs-rt5682\;sof-mtl-rt5650-dts\;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-rt5650-dts.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +DEEP_BUF_SPK=true,PLAYBACK_PIPELINE_SRC=dts,SSP_SPK_FMT_24=true,SSP_HS_FMT_24=true" + +"cavs-rt5682\;sof-mtl-rt5650-dts-google-aec\;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-rt5650-dts-google-aec.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ +SPK_ID=6,SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=7,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,\ +GOOGLE_RTC_AEC_SUPPORT=1,DEEP_BUF_SPK=true,PLAYBACK_PIPELINE_SRC=dts,\ +SSP_SPK_FMT_24=true,SSP_HS_FMT_24=true" + +#ES83x6+HDMI-IN +"cavs-es83x6\;sof-mtl-es83x6-ssp1-hdmi-ssp02\;PLATFORM=mtl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-es83x6-ssp1-hdmi-ssp02.bin,HEADSET_SSP_DAI_INDEX=1,\ +HEADSET_CODEC=true,HEADSET_CODEC_NAME=SSP1-Codec,HDMI1_ID=3,HDMI2_ID=4,HDMI3_ID=5,\ +HDMI_IN_CAPTURE=true" + +#No HeadsetCodec+HDMI-IN +"cavs-es83x6\;sof-mtl-hdmi-ssp02\;PLATFORM=mtl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-hdmi-ssp02.bin,HEADSET_CODEC=false,HDMI_IN_CAPTURE=true,\ +HDMI_IN_1_ID=0,HDMI_IN_2_ID=1" + +#ES83x6 codec alone without HDMI-in capture +"cavs-es83x6\;sof-mtl-es83x6-ssp1\;PLATFORM=mtl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-mtl-es83x6-ssp1.bin,HEADSET_SSP_DAI_INDEX=1,\ +HEADSET_CODEC=true,HEADSET_CODEC_NAME=SSP1-Codec,HDMI1_ID=3,HDMI2_ID=4,HDMI3_ID=5,\ +HDMI_IN_CAPTURE=false" + +# SDW + DMIC + HDMI +"cavs-sdw\;sof-mtl-sdw-cs42l42-l0-max98363-l2\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-sdw-cs42l42-l0-max98363-l2.bin,\ +BT_NAME=SSP1-BT,BT_INDEX=1,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +NUM_SDW_AMP_LINKS=1,SDW_SPK_STREAM=SDW2-Playback,SDW_AMP_FEEDBACK=false,\ +SDW_JACK_CAPTURE_CH=1,SDW_SPK_ENHANCED_PLAYBACK=false" +) diff --git a/tools/topology/topology2/production/tplg-targets-ace2.cmake b/tools/topology/topology2/production/tplg-targets-ace2.cmake new file mode 100644 index 000000000000..9891b45812a8 --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-ace2.cmake @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# SDW topology for LNL RVP +"cavs-sdw\;sof-lnl-rt711-4ch\;PLATFORM=lnl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-rt711-4ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-rt711-l0-rt1316-l23-rt714-l1\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_SPK_STREAM=SDW2-Playback,SDW_SPK_IN_STREAM=SDW2-Capture,SDW_DMIC_STREAM=SDW1-Capture" + +"cavs-sdw\;sof-lnl-rt712-l2-rt1712-l3\;PLATFORM=lnl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-rt722-l0\;PLATFORM=lnl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-rt712-l2-rt1320-l1\;PLATFORM=lnl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-rt713-l2-rt1320-l13\;PLATFORM=lnl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-rt713-l0-rt1318-l1\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW1-Playback,SDW_AMP_FEEDBACK=false" + +"cavs-sdw\;sof-lnl-rt713-l0-rt1318-l1-2ch\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=1,\ +SDW_SPK_STREAM=SDW1-Playback,SDW_AMP_FEEDBACK=false,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-rt713-l0-rt1318-l1-2ch.bin,\ +HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# Split topologies +"cavs-sdw\;sof-lnl-dmic-2ch-id2\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-2ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-2ch-id3\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-2ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-2ch-id4\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-2ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-2ch-id5\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-2ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-4ch-id2\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-4ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-4ch-id3\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-4ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-4ch-id4\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-4ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-dmic-4ch-id5\;PLATFORM=lnl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-dmic-4ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# No SDW Jack. SDW DMIC+SPK +"cavs-sdw\;sof-lnl-rt1318-l12-rt714-l0\;PLATFORM=lnl,SDW_JACK=false,SDW_DMIC=1,\ +NUM_SDW_AMP_LINKS=2,SDW_DMIC_STREAM=SDW0-Capture" + +"cavs-sdw\;sof-lnl-rt1320-l12-rt714-l0\;PLATFORM=lnl,SDW_JACK=false,SDW_DMIC=1,\ +NUM_SDW_AMP_LINKS=2,SDW_AMP_FEEDBACK=false,SDW_DMIC_STREAM=SDW0-Capture" + +# SDW bridge to SPK and SDW Jack+DMIC+SPK +"cavs-sdw\;sof-lnl-cs42l43-l0\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-cs42l43-l0-4ch\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-cs42l43-l0-4ch.bin,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-cs42l43-l0-2ch\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=1,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-lnl-cs42l43-l0-2ch.bin,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-cs42l43-l0-cs35l56-l3\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-cs42l43-l0-cs35l56-l3-2ch\;PLATFORM=lnl,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=sof-lnl-cs42l43-l0-cs35l56-l3-2ch.bin,\ +NUM_SDW_AMP_LINKS=1,SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-lnl-cs42l43-l0-cs35l56-l23\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-lnl-cs42l43-l0-cs35l56-l23-2ch\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,NUM_DMICS=2,\ +DMIC0_ID=3,DMIC1_ID=4,HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=sof-lnl-cs42l43-l0-cs35l56-l23-2ch.bin" + +"cavs-sdw\;sof-lnl-cs42l43-l0-cs35l56-l23-4ch\;PLATFORM=lnl,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_ID=3,DMIC1_ID=4,HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=sof-lnl-cs42l43-l0-cs35l56-l23-4ch.bin" + +"cavs-sdw\;sof-lnl-cs42l43-l2-cs35l56x6-l13\;NUM_SDW_AMP_LINKS=3,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +) diff --git a/tools/topology/topology2/production/tplg-targets-ace3.cmake b/tools/topology/topology2/production/tplg-targets-ace3.cmake new file mode 100644 index 000000000000..953964b068a9 --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-ace3.cmake @@ -0,0 +1,344 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# MOCKUP topology for PTL +"cavs-sdw\;sof-ptl-rt711-rt1308-rt715\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,SDW_AMP_FEEDBACK=false" + +"cavs-sdw\;sof-ptl-rt711-rt1308-mono-rt715\;NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,SDW_AMP_FEEDBACK=false" + +"cavs-sdw\;sof-ptl-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,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +# SDW topology for PTL RVP +"cavs-sdw\;sof-ptl-rt711\;PLATFORM=ptl,HDMI1_ID=2,HDMI2_ID=3,HDMI3_ID=4" + +"cavs-sdw\;sof-ptl-rt711-2ch\;PLATFORM=ptl,NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,\ +DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt711-2ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-rt711-4ch\;PLATFORM=ptl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt711-4ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# RT721 eval board with SDW-DMIC, sof_sdw_quirk_table without SOC_SDW_PCH_DMIC +"cavs-sdw\;sof-ptl-rt721\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC +"cavs-sdw\;sof-ptl-rt721-4ch\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC, DMIC1 with 96kHz +"cavs-sdw\;sof-ptl-rt721-4ch-dmic1-96k\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch-dmic1-96k.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DMIC1_ENABLE=passthrough,DMIC1_RATE=96000,DMIC1_PCM_ID=11,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC, 96KHz Jack-rate +"cavs-sdw\;sof-ptl-rt721-4ch-96k\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,JACK_RATE=96000,DEEP_BUF_JACK_RATE=96000" + +"cavs-sdw\;sof-ptl-rt721-l3-rt1320-l3-4ch-ssp2-bt\;PLATFORM=ptl,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-l3-rt1320-l3-4ch-ssp2-bt.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEP_BUF_SPK=true,BT_PCM_ID=8,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true" + +# DTS +"cavs-sdw\;sof-ptl-rt721-l3-rt1320-l3-4ch-ssp2-bt-dts\;PLATFORM=ptl,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt721-l3-rt1320-l3-4ch-ssp2-bt.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEP_BUF_SPK=true,BT_PCM_ID=8,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,SDW_AMP_PIPELINE_SRC=dts,\ +SDW_JACK_PIPELINE_SRC=dts" + +"cavs-sdw\;sof-ptl-rt722\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt722-96k\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +JACK_RATE=96000,DEEP_BUF_JACK_RATE=96000,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +"cavs-sdw\;sof-ptl-rt722-192k\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +JACK_RATE=192000,DEEP_BUF_JACK_RATE=192000,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +"cavs-sdw\;sof-ptl-rt722-4ch\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt722-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-rt722-2ch\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt722-2ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-rt722-l0-rt1320-l23\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt722-l0-rt1320-l23-2ch\;PLATFORM=ptl,NUM_SDW_AMP_LINKS=2,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=SDW2-Playback,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt722-l0-rt1320-l23-2ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-rt722-l0-rt1320-l23-4ch\;PLATFORM=ptl,NUM_SDW_AMP_LINKS=2,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt722-l0-rt1320-l23-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,\ +BT_PCM_ID=20,BT_ID=10,BT_PCM_NAME=Bluetooth,ADD_BT=true" + +"cavs-sdw\;sof-ptl-rt712-l2-rt1320-l1\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt712-l3-rt1320-l2\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt712-l3-rt1320-l3\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt712-l3-rt1320-l3-ctc\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_CTC_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt712-l3-rt1320-l3-4ch\;PLATFORM=ptl,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt712-l3-rt1320-l3-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +BT_PCM_ID=20,BT_ID=10,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true" + +"cavs-sdw\;sof-ptl-rt713-l2-rt1320-l13\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-rt713-l3-rt1320-l12\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +# LG Gram Pro 2026 (16Z90U-KU7BK) with RT713 on link 3 and single stereo RT1320 on link 1 +"cavs-sdw\;sof-ptl-rt713-l3-rt1320-l1\;PLATFORM=ptl,SDW_DMIC=0,NUM_SDW_AMP_LINKS=1,\ +NUM_DMICS=2,PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=SDW1-Playback,\ +SDW_JACK_OUT_STREAM=SDW3-Playback,SDW_JACK_IN_STREAM=SDW3-Capture,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-rt713-l3-rt1320-l1.bin" + +"cavs-sdw\;sof-ptl-cs42l43-l2-cs35l56x6-l13\;NUM_SDW_AMP_LINKS=3,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-ptl-cs42l43-agg-l3-cs35l56-l2\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +SDW_SPK_ENHANCED_PLAYBACK=false" + +"cavs-sdw\;sof-ptl-cs42l43-agg-l3-cs35l56-l2-dax\;PLATFORM=ptl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +SDW_AMP_PIPELINE_SRC=dax,SDW_JACK_PIPELINE_SRC=dax,DOLBY_DAX_CORE_ID=0" + +"cavs-sdw\;sof-ptl-cs42l43-agg-l3-cs35l56-l2-4ch\;PLATFORM=ptl,NUM_SDW_AMP_LINKS=2,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-cs42l43-agg-l3-cs35l56-l2-4ch.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,BT_PCM_ID=20,BT_ID=8,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +SDW_SPK_ENHANCED_PLAYBACK=false" + +# SSP codec topologies for PTL +# ES83x6 codec alone without HDMI-in capture +"cavs-es83x6\;sof-ptl-es8336-ssp1\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-es8336-ssp1.bin,HEADSET_SSP_DAI_INDEX=1,\ +HEADSET_CODEC=true,HEADSET_CODEC_NAME=SSP1-Codec,HDMI1_ID=3,HDMI2_ID=4,HDMI3_ID=5,\ +HDMI_IN_CAPTURE=false" + +#ES83x6+HDMI-IN +"cavs-es83x6\;sof-ptl-es83x6-ssp1-hdmi-ssp02\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-es83x6-ssp1-hdmi-ssp02.bin,HEADSET_SSP_DAI_INDEX=1,\ +HEADSET_CODEC=true,HEADSET_CODEC_NAME=SSP1-Codec,HDMI1_ID=3,HDMI2_ID=4,HDMI3_ID=5,\ +HDMI_IN_CAPTURE=true" + +#No HeadsetCodec+HDMI-IN +"cavs-es83x6\;sof-ptl-hdmi-ssp02\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-hdmi-ssp02.bin,HEADSET_CODEC=false,HDMI_IN_CAPTURE=true,\ +HDMI_IN_1_ID=0,HDMI_IN_2_ID=1" + +# Topology for PTL with rt5682 (SSP 0), tas2563 (SSP 1), BT (SSP 2) and PDM0 enabled +"cavs-rt5682\;sof-ptl-tas2563-rt5682\;PLATFORM=ptl,NUM_DMICS=2,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-tas2563-rt5682.bin,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +BT_NAME=SSP2-BT,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true" + +"cavs-rt5682\;sof-ptl-tas2563-rt5682-ctc\;PLATFORM=ptl,NUM_DMICS=2,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-tas2563-rt5682-ctc.bin,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ +BT_NAME=SSP2-BT,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true,PLAYBACK_PIPELINE_SRC=ctc,USE_CTC_SPK=true" + +"cavs-rt5682\;sof-ptl-tas2563-rt5682-dax\;PLATFORM=ptl,NUM_DMICS=2,DMIC0_PCM_ID=99,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-tas2563-rt5682-dax.bin,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,\ +INCLUDE_ECHO_REF=true,BT_NAME=SSP2-BT,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true,\ +PLAYBACK_PIPELINE_SRC=dax,SSP_HEADSET_DAX=true,DOLBY_DAX_CORE_ID=0" + +"cavs-rt5682\;sof-ptl-tas2563-rt5682-dax-ctc\;PLATFORM=ptl,NUM_DMICS=2,DMIC0_PCM_ID=99,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-tas2563-rt5682-dax-ctc.bin,SPK_ID=6,DEEPBUFFER_FW_DMA_MS=10,\ +INCLUDE_ECHO_REF=true,BT_NAME=SSP2-BT,BT_ID=7,BT_PCM_NAME=Bluetooth,DEEP_BUF_SPK=true,\ +PLAYBACK_PIPELINE_SRC=dax,DOLBY_DAX_CORE_ID=0,USE_CTC_SPK=true" + + +# Split topologies +"cavs-sdw\;sof-ptl-dmic-2ch-id2\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-2ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-2ch-id3\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-2ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-2ch-id4\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-2ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-2ch-id5\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-2ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-4ch-id2\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-4ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-4ch-id3\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-4ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-4ch-id4\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-4ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-ptl-dmic-4ch-id5\;PLATFORM=ptl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-dmic-4ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +# for WCL +"cavs-sdw\;sof-wcl-dmic-2ch-id2\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-2ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-2ch-id3\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-2ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-2ch-id4\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-2ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-2ch-id5\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-2ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-4ch-id2\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-4ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-4ch-id3\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-4ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-4ch-id4\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-4ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-wcl-dmic-4ch-id5\;PLATFORM=wcl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-wcl-dmic-4ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-es83x6\;sof-ptl-ssp1-jack-id0\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-ssp1-jack-id0.bin,HEADSET_SSP_DAI_INDEX=1,\ +HEADSET_CODEC=true,HEADSET_CODEC_NAME=SSP1-Codec,NUM_HDMIS=0,\ +HDMI_IN_CAPTURE=false" + +# HDMI IN port: SSP0 and SSP2, SSP number is a mask in HDMI_IN_1_ID and HDMI_IN_2_ID +# For example, SSP5 indicates SSP 0 and 2 are used for HDMI IN +"cavs-es83x6\;sof-ptl-ssp5-hdmiin-id1\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,NUM_HDMIS=0,\ +NHLT_BIN=nhlt-sof-ptl-ssp5-hdmiin-id1.bin,HEADSET_CODEC=false,HDMI_IN_CAPTURE=true,\ +HDMI_IN_1_ID=0,HDMI_IN_2_ID=1" + +"cavs-es83x6\;sof-ptl-ssp5-hdmiin-id2\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,NUM_HDMIS=0,\ +NHLT_BIN=nhlt-sof-ptl-ssp5-hdmiin-id2.bin,HEADSET_CODEC=false,HDMI_IN_CAPTURE=true,\ +HDMI_IN_1_ID=1,HDMI_IN_2_ID=2" + +"cavs-es83x6\;sof-ptl-ssp5-hdmiin-id7\;PLATFORM=ptl,PREPROCESS_PLUGINS=nhlt,NUM_HDMIS=0,\ +NHLT_BIN=nhlt-sof-ptl-ssp5-hdmiin-id7.bin,HEADSET_CODEC=false,HDMI_IN_CAPTURE=true,\ +HDMI_IN_1_ID=6,HDMI_IN_2_ID=7" + +"cavs-es83x6\;sof-ptl-ssp2-bt-id2\;PLATFORM=ptl,INCLUDE_BT_OFFLOAD=true,NUM_HDMIS=0,\ +HEADSET_CODEC=false,HDMI_IN_CAPTURE=false,BT_ID=2,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-ptl-ssp2-bt-id2.bin" + +#BT_ID=8, 10 for sdw_sof machine +"cavs-sdw\;sof-ptl-ssp2-bt-id8\;PLATFORM=ptl,ADD_BT=true,SDW_JACK=false,NUM_HDMIS=0,\ +HEADSET_CODEC=false,HDMI_IN_CAPTURE=false,BT_ID=8,BT_PCM_ID=20,BT_PCM_NAME=Bluetooth,\ +BT_CP_HOST_PIPELINE_ID=201,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-ssp2-bt-id8.bin" + +"cavs-sdw\;sof-ptl-ssp2-bt-id10\;PLATFORM=ptl,ADD_BT=true,SDW_JACK=false,NUM_HDMIS=0,\ +HEADSET_CODEC=false,HDMI_IN_CAPTURE=false,BT_ID=10,BT_PCM_ID=20,BT_PCM_NAME=Bluetooth,\ +BT_CP_HOST_PIPELINE_ID=201,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-ptl-ssp2-bt-id10.bin" +) diff --git a/tools/topology/topology2/production/tplg-targets-ace4.cmake b/tools/topology/topology2/production/tplg-targets-ace4.cmake new file mode 100644 index 000000000000..66edfda9a1a6 --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-ace4.cmake @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# MOCKUP topology for PTL +"cavs-sdw\;sof-nvl-rt711-rt1308-rt715\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,SDW_AMP_FEEDBACK=false" + +"cavs-sdw\;sof-nvl-rt711-rt1308-mono-rt715\;NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,SDW_AMP_FEEDBACK=false" + +"cavs-sdw\;sof-nvl-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,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC +"cavs-sdw\;sof-nvl-rt721-4ch\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nvl-rt721-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true" + +# RT721 eval board with PCH-DMIC, sof_sdw_quirk_table with SOC_SDW_PCH_DMIC, 96KHz Jack-rate +"cavs-sdw\;sof-nvl-rt721-4ch-96k\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nvl-rt721-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true,JACK_RATE=96000,DEEP_BUF_JACK_RATE=96000" + +"cavs-sdw\;sof-nvl-rt722\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-nvl-rt722-96k\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +JACK_RATE=96000,DEEP_BUF_JACK_RATE=96000,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +"cavs-sdw\;sof-nvl-rt722-192k\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +JACK_RATE=192000,DEEP_BUF_JACK_RATE=192000,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +"cavs-sdw\;sof-nvl-rt722-4ch\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nvl-rt722-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-rt722-2ch\;PLATFORM=nvl,SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nvl-rt722-2ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-rt712-l3-rt1320-l3-4ch-ssp2-bt\;PLATFORM=nvl,NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nvl-rt712-l3-rt1320-l3-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default,\ +BT_PCM_ID=20,BT_ID=10,BT_PCM_NAME=Bluetooth,ADD_BT=true,\ +DEEPBUFFER_FW_DMA_MS=10,DEEP_BUF_SPK=true" + +# Split topologies +"cavs-sdw\;sof-nvl-dmic-2ch-id2\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-2ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-2ch-id3\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-2ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-2ch-id4\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-2ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-2ch-id5\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=2,\ +PDM1_MIC_A_ENABLE=0,PDM1_MIC_B_ENABLE=0,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-2ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-4ch-id2\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=2,DMIC1_ID=3,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-4ch-id2.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-4ch-id3\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=3,DMIC1_ID=4,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-4ch-id3.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-4ch-id4\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=4,DMIC1_ID=5,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-4ch-id4.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"cavs-sdw\;sof-nvl-dmic-4ch-id5\;PLATFORM=nvl,SDW_JACK=false,NUM_HDMIS=0,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ID=5,DMIC1_ID=6,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-nvl-dmic-4ch-id5.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" +) diff --git a/tools/topology/topology2/production/tplg-targets-cavs25.cmake b/tools/topology/topology2/production/tplg-targets-cavs25.cmake new file mode 100644 index 000000000000..977cc29846f1 --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-cavs25.cmake @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# IPC4 topology for TGL/ADL rt711 Headset + rt1316 Amplifier + rt714 DMIC +"cavs-sdw\;sof-tgl-rt711-rt1316-rt714\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1" + +"cavs-sdw\;sof-adl-rt711-l0-rt1316-l12-rt714-l3\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1" + +"cavs-sdw\;sof-adl-rt711-l0-rt1316-l13-rt714-l2\;NUM_SDW_AMP_LINKS=2,\ +SDW_DMIC=1,SDW_DMIC_STREAM=SDW2-Capture" + +# IPC4 topology for TGL/ADL rt711 Headset + rt1308 Amplifier + rt715 DMIC +"cavs-sdw\;sof-tgl-rt711-rt1308-rt715\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,SDW_AMP_FEEDBACK=false" + +"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,\ +SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +"cavs-sdw\;sof-adl-rt711-l0-rt1308-l12-rt715-l3\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,SDW_AMP_FEEDBACK=false" + +# IPC4 topology for TGL rt711 Headset + rt1308 Amplifier + PCH DMIC +"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" + +# ICP4 topology for TGL/ADL cs42l43 Jack + DMIC + cs35l56 Amp and RPL cs42l43 bridge to SPK +"cavs-sdw\;sof-tgl-cs42l43-l3-cs35l56-l01\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-adl-cs42l43-l0-cs35l56-l23\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-rpl-cs42l43-l0\;NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +"cavs-sdw\;sof-tgl-cs35l56-l01-fb8\;NUM_SDW_AMP_LINKS=2,\ +SDW_AMP_FEEDBACK=true,SDW_SPK_STREAM=Playback,SDW_SPK_IN_STREAM=Capture,\ +AMP_FEEDBACK_CH=8,AMP_FEEDBACK_CH_PER_LINK=4,SDW_JACK=false,NUM_DMICS=0,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6,SDW_SPK_ENHANCED_PLAYBACK=false,SDW_DMIC_ENHANCED_CAPTURE=false" + +# IPC4 topology for TGL rt712 Headset, Amp and DMIC +"cavs-sdw\;sof-tgl-rt712\;SDW_JACK_OUT_STREAM=Playback-SimpleJack,\ +SDW_JACK_IN_STREAM=Capture-SimpleJack,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_DMIC_STREAM=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=Capture-SmartMic" + +"cavs-sdw\;sof-adl-rt711-4ch\;NUM_DMICS=4,DMIC0_ID=2,DMIC1_ID=3,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-adl-rt711-4ch.bin,\ +HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6" +) diff --git a/tools/topology/topology2/production/tplg-targets-hda-generic.cmake b/tools/topology/topology2/production/tplg-targets-hda-generic.cmake new file mode 100644 index 000000000000..72872d110a4d --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-hda-generic.cmake @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# HDMI only topology with passthrough pipelines +"sof-hda-generic\;sof-hda-generic-idisp\;" +# HDMI only topology with passthrough pipelines and +# 2 or 4 DMIC, no NHLT blob included in topology +"sof-hda-generic\;sof-hda-generic-idisp-2ch\;NUM_DMICS=2" +"sof-hda-generic\;sof-hda-generic-idisp-4ch\;NUM_DMICS=4" +# HDA topology with mixer-based pipelines for HDA and +# passthrough pipelines for HDMI +"sof-hda-generic\;sof-hda-generic\;HDA_CONFIG=mix,HDA_MIC_ENHANCED_CAPTURE=true,\ +EFX_HDA_MIC_TDFB_PARAMS=line2_pass,EFX_HDA_MIC_DRC_PARAMS=passthrough" + +"sof-hda-generic\;sof-hda-generic-compr\;HDA_CONFIG=mix,HDA_MIC_ENHANCED_CAPTURE=true,\ +EFX_HDA_MIC_TDFB_PARAMS=line2_pass,EFX_HDA_MIC_DRC_PARAMS=passthrough,COMPRESSED=true" + +"sof-hda-generic\;sof-hda-generic-dax\;HDA_CONFIG=dax,HDA_MIC_ENHANCED_CAPTURE=true,\ +EFX_HDA_MIC_TDFB_PARAMS=line2_pass,EFX_HDA_MIC_DRC_PARAMS=passthrough,DOLBY_DAX_CORE_ID=1" + +# HDA topology with mixer-based pipelines for HDA and +# passthrough pipelines for HDMI and +# 2 or 4 DMIC, no NHLT blob included in topology +"sof-hda-generic\;sof-hda-generic-1ch\;HDA_CONFIG=mix,NUM_DMICS=1,PDM0_MIC_B_ENABLE=0" + +"sof-hda-generic\;sof-hda-generic-2ch\;HDA_CONFIG=mix,NUM_DMICS=2,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-4ch\;HDA_CONFIG=mix,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-2ch-dax\;HDA_CONFIG=dax,NUM_DMICS=2,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DOLBY_DAX_CORE_ID=1" + +# HDA topology with mixer-based pipelines for HDA and +# passthrough pipelines for HDMI and +# 2 or 4 DMIC, no NHLT blob included in topology + +# Note: If the alsatplg plugins for NHLT are not available, the NHLT blobs will +# not be added to the topologies below. + +# Topologies for CAVS2.5 architecture +# HDMI + DMICs +"sof-hda-generic\;sof-hda-generic-cavs25-idisp-2ch\;NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-idisp-2ch.bin" +"sof-hda-generic\;sof-hda-generic-cavs25-idisp-4ch\;NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-idisp-4ch.bin" +# HDA + HDMI + DMICs +"sof-hda-generic\;sof-hda-generic-cavs25-1ch\;HDA_CONFIG=mix,NUM_DMICS=1,PDM0_MIC_B_ENABLE=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-1ch.bin" + +"sof-hda-generic\;sof-hda-generic-cavs25-2ch\;HDA_CONFIG=mix,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-2ch.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-cavs25-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-cavs25-4ch.bin,\ +DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-cavs25-2ch-dax\;HDA_CONFIG=dax,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-cavs25-2ch-dax.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DOLBY_DAX_CORE_ID=1" + +# Topologies for ACE1 and ACE2 architectures +# HDMI + DMICs +"sof-hda-generic\;sof-hda-generic-ace1-idisp-2ch\;PLATFORM=mtl,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-idisp-2ch.bin" +"sof-hda-generic\;sof-hda-generic-ace1-idisp-4ch\;PLATFORM=mtl,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-idisp-4ch.bin" +# HDA + HDMI + DMICs +"sof-hda-generic\;sof-hda-generic-ace1-1ch\;PLATFORM=mtl,HDA_CONFIG=mix,NUM_DMICS=1,PDM0_MIC_B_ENABLE=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-1ch.bin" + +"sof-hda-generic\;sof-hda-generic-ace1-2ch\;PLATFORM=mtl,HDA_CONFIG=mix,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-2ch.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-ace1-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-ace1-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-ace1-2ch-dax\;PLATFORM=mtl,HDA_CONFIG=dax,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace1-2ch-dax.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DOLBY_DAX_CORE_ID=1" + +# Topologies for ACE3 architecture +# HDMI + DMICs +"sof-hda-generic\;sof-hda-generic-ace3-idisp-2ch\;PLATFORM=ptl,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace3-idisp-2ch.bin" + +"sof-hda-generic\;sof-hda-generic-ace3-idisp-4ch\;PLATFORM=ptl,NUM_DMICS=4,\ +PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace3-idisp-4ch.bin" + +# HDA + HDMI + DMICs +"sof-hda-generic\;sof-hda-generic-ace3-1ch\;PLATFORM=ptl,HDA_CONFIG=mix,NUM_DMICS=1,PDM0_MIC_B_ENABLE=0,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace3-1ch.bin" + +"sof-hda-generic\;sof-hda-generic-ace3-2ch\;PLATFORM=ptl,HDA_CONFIG=mix,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace3-2ch.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-ace3-4ch\;PLATFORM=ptl,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-ace3-4ch.bin,DMIC0_ENHANCED_CAPTURE=true,\ +EFX_DMIC0_TDFB_PARAMS=line4_pass,EFX_DMIC0_DRC_PARAMS=dmic_default" + +"sof-hda-generic\;sof-hda-generic-ace3-2ch-dax\;PLATFORM=ptl,HDA_CONFIG=dax,NUM_DMICS=2,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-ace3-2ch-dax.bin,\ +DMIC0_ENHANCED_CAPTURE=true,EFX_DMIC0_TDFB_PARAMS=line2_generic_pm10deg,\ +EFX_DMIC0_DRC_PARAMS=dmic_default,DOLBY_DAX_CORE_ID=1" +) diff --git a/tools/topology/topology2/production/tplg-targets-imx8.cmake b/tools/topology/topology2/production/tplg-targets-imx8.cmake new file mode 100644 index 000000000000..34977808d962 --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-imx8.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS +# IPC4 topology for i.MX8MP + WM8960 Codec +"imx8-wm8960\;sof-imx8mp-wm8960\;SAI_DAI_INDEX=3,STREAM_CODEC_NAME=sai3-wm8960-hifi" +) diff --git a/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake b/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake new file mode 100644 index 000000000000..c7d5b5d8af1b --- /dev/null +++ b/tools/topology/topology2/production/tplg-targets-sdca-generic.cmake @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: BSD-3-Clause + +# Array of "input-file-name;output-file-name;comma separated pre-processor variables" +list(APPEND TPLGS + +"cavs-sdw\;sof-sdw-generic\;SDW_DMIC=1,NUM_SDW_AMP_LINKS=1,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,SDW_DMIC_STREAM=Capture-SmartMic,\ +SDW_JACK_OUT_STREAM=Playback-SimpleJack,SDW_JACK_IN_STREAM=Capture-SimpleJack" + +# Split topologies +"cavs-sdw\;sof-sdca-jack-id0\;SDW_JACK_OUT_STREAM=Playback-SimpleJack,\ +SDW_JACK_IN_STREAM=Capture-SimpleJack,NUM_HDMIS=0" + +"cavs-sdw\;sof-sdca-1amp-id2\;NUM_SDW_AMP_LINKS=1,SDW_JACK=false,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,NUM_HDMIS=0,\ +DEEP_BUF_SPK=true" + +"cavs-sdw\;sof-sdca-2amp-id2\;NUM_SDW_AMP_LINKS=2,SDW_JACK=false,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,NUM_HDMIS=0,\ +DEEP_BUF_SPK=true" + +"cavs-sdw\;sof-sdca-3amp-id2\;NUM_SDW_AMP_LINKS=3,SDW_JACK=false,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,NUM_HDMIS=0,\ +DEEP_BUF_SPK=true" + +"cavs-sdw\;sof-sdca-4amp-id2\;NUM_SDW_AMP_LINKS=4,SDW_JACK=false,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,NUM_HDMIS=0,\ +DEEP_BUF_SPK=true" + +"cavs-sdw\;sof-sdca-mic-id4\;SDW_JACK=false,SDW_DMIC=1,NUM_HDMIS=0,\ +SDW_DMIC_STREAM=Capture-SmartMic" + +"cavs-sdw\;sof-hdmi-pcm5-id2\;SDW_JACK=false,HDMI1_ID=2,HDMI2_ID=3,HDMI3_ID=4" +"cavs-sdw\;sof-hdmi-pcm5-id3\;SDW_JACK=false,HDMI1_ID=3,HDMI2_ID=4,HDMI3_ID=5" +"cavs-sdw\;sof-hdmi-pcm5-id4\;SDW_JACK=false,HDMI1_ID=4,HDMI2_ID=5,HDMI3_ID=6" +"cavs-sdw\;sof-hdmi-pcm5-id5\;SDW_JACK=false" +"cavs-sdw\;sof-hdmi-pcm5-id6\;SDW_JACK=false,HDMI1_ID=6,HDMI2_ID=7,HDMI3_ID=8" +"cavs-sdw\;sof-hdmi-pcm5-id7\;SDW_JACK=false,HDMI1_ID=7,HDMI2_ID=8,HDMI3_ID=9" + +# Feature topologies which should work with the function topologies above +"cavs-sdw\;sof-sdca-amp-ref\;SDW_JACK=false,NUM_HDMIS=0,JACK_RATE=48000,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_ECHO_REF=true,SDW_SPK_ECHO_REF_PCM_ID=12" + +"cavs-sdw\;sof-sdca-amp-ref-dai\;SDW_JACK=false,NUM_HDMIS=0,JACK_RATE=48000,\ +SDW_AMP_FEEDBACK=false,SDW_ECHO_REF_DAI=true,SDW_SPK_ECHO_REF=true,SDW_SPK_ECHO_REF_PCM_ID=12" + +"cavs-sdw\;sof-sdca-jack-ref-dai\;SDW_JACK=false,NUM_HDMIS=0,JACK_RATE=48000,\ +SDW_ECHO_REF_DAI=true,SDW_JACK_ECHO_REF=true,SDW_JACK_ECHO_REF_PCM_ID=11" + +# Topology for speaker with 2-way crossover filter in SOF +# with channels order L-low, R-low, L-high, R-high +"cavs-sdw\;sof-sdca-2amp-id2-xover\;NUM_SDW_AMP_LINKS=2,SDW_JACK=false,\ +SDW_AMP_FEEDBACK=false,SDW_SPK_STREAM=Playback-SmartAmp,NUM_HDMIS=0,\ +SDW_AMP_NUM_CHANNELS=4,SDW_AMP_XOVER=true,\ +SDW_AMP_XOVER_SELECTOR_PARAMS=xover_selector_lr_to_lrlr,\ +SDW_AMP_XOVER_EQIIR_PARAMS=xover_lr4_2000hz_llhh_48khz" + +"cavs-sdw\;sof-sdca-2amp-feedback-id3-xover\;NUM_SDW_AMP_LINKS=2,\ +SDW_JACK=false,SDW_AMP_FEEDBACK=true,SDW_SPK_STREAM=Playback-SmartAmp,\ +SDW_SPK_IN_STREAM=Capture-SmartAmp,NUM_HDMIS=0,\ +SDW_AMP_NUM_CHANNELS=4,SDW_AMP_XOVER=true,\ +SDW_AMP_XOVER_SELECTOR_PARAMS=xover_selector_lr_to_lrlr,\ +SDW_AMP_XOVER_EQIIR_PARAMS=xover_lr4_2000hz_llhh_48khz" +) diff --git a/tools/topology/topology2/sof-hda-generic.conf b/tools/topology/topology2/sof-hda-generic.conf new file mode 100644 index 000000000000..01a020bad17f --- /dev/null +++ b/tools/topology/topology2/sof-hda-generic.conf @@ -0,0 +1,189 @@ +<searchdir:include> +<searchdir:include/common> +<searchdir:include/components> +<searchdir:include/dais> +<searchdir:include/pipelines> +<searchdir:include/pipelines/cavs> +<searchdir:platform> +<searchdir:platform/intel> + +<vendor-token.conf> +<tokens.conf> +<virtual.conf> +<host-gateway-playback.conf> +<host-gateway-capture.conf> +<host-copier-gain-mixin-playback.conf> +<host-copier-gain-src-mixin-playback.conf> +<mixout-dai-copier-playback.conf> +<mixout-gain-dai-copier-playback.conf> +<mixout-aria-gain-mixin-playback.conf> +<mixout-gain-efx-dai-copier-playback.conf> +<mixout-gain-dax-dai-copier-playback.conf> +<mixout-gain-efx-mbdrc-dai-copier-playback.conf> +<mixout-gain-host-copier-capture.conf> +<dai-copier-eqiir-module-copier-capture.conf> +<dai-copier-gain-eqiir-module-copier-capture.conf> +<gain-capture.conf> +<deepbuffer-playback.conf> +<deepbuffer-capture.conf> +<compr-playback.conf> +<io-gateway.conf> +<io-gateway-capture.conf> +<highpass-capture-be.conf> +<data.conf> +<pcm.conf> +<pcm_caps.conf> +<fe_dai.conf> +<hda.conf> +<dmic.conf> +<pdm_config.conf> +<hw_config_simple.conf> +<manifest.conf> +<route.conf> +<common_definitions.conf> +<dmic-default.conf> +<hdmi-default.conf> +<deep-buffer-default.conf> +<compr-default.conf> +<module-copier.conf> + +Define { + HDA_CONFIG "none" + PLATFORM "none" + NUM_DMICS 0 +# doesn't it need to define DMIC0_HOST_PIPELINE_SINK and DMIC0_DAI_PIPELINE_SRC? + DMIC0_HOST_PIPELINE_SINK 'host-copier.6.capture' + DMIC0_DAI_PIPELINE_SRC 'module-copier.12.2' + DMIC0_DAI_COPIER 'dai-copier.DMIC.dmic01.capture' + DMIC0_DAI_EQIIR "highpass_40hz_20db" + DMIC0_PCM_CAPS 'Gain Capture 11' +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/lnl.conf" + "ptl" "platform/intel/ptl.conf" +} + +# include HDA config if needed. +IncludeByKey.HDA_CONFIG { + "mix" "cavs-mixin-mixout-hda.conf" + "efx" "cavs-mixin-mixout-efx-hda.conf" + "src" "cavs-src-mixin-mixout-hda.conf" + "dax" "cavs-mixin-mixout-dax-hda.conf" + "passthrough" "cavs-passthrough-hda.conf" +} + +# include DMIC config if needed. +IncludeByKey.NUM_DMICS { + "[1-4]" "platform/intel/dmic-generic.conf" +} + +Define { + NUM_HDMIS 3 + HDMI1_ID 1 + HDMI2_ID 2 + HDMI3_ID 3 + HDMI1_PCM_ID 3 + HDMI2_PCM_ID 4 + HDMI3_PCM_ID 5 + DMIC0_PCM_ID 6 +} + +IncludeByKey.NUM_HDMIS { +"[3-4]" "platform/intel/hdmi-generic.conf" +} + +Object.Widget.virtual [ + { + name 'codec0_in' + type input + index 1 + } + { + name 'codec1_in' + type input + index 2 + } + { + name 'codec0_out' + type output + index 3 + } + { + name 'codec1_out' + type output + index 4 + } + { + name 'codec2_in' + type input + index 5 + } + { + name 'codec2_out' + type output + index 6 + } + { + name 'iDisp1_out' + type output + index 7 + } + { + name 'iDisp2_out' + type output + index 8 + } + { + name 'iDisp3_out' + type output + index 9 + } + { + name 'iDisp3 Tx' + type out_drv + index 0 + } + { + name 'iDisp2 Tx' + type out_drv + index 1 + } + { + name 'iDisp1 Tx' + type out_drv + index 2 + } + { + name 'Analog CPU Playback' + type out_drv + index 3 + } + { + name 'Digital CPU Playback' + type out_drv + index 4 + } + { + name 'Alt Analog CPU Playback' + type out_drv + index 5 + } + { + name 'Analog CPU Capture' + type input + index 6 + } + { + name 'Digital CPU Capture' + type input + index 7 + } + { + name 'Alt Analog CPU Capture' + type input + index 8 + } +] diff --git a/tools/tplg_parser/CMakeLists.txt b/tools/tplg_parser/CMakeLists.txt index 040cf4daa08c..1569284b097d 100644 --- a/tools/tplg_parser/CMakeLists.txt +++ b/tools/tplg_parser/CMakeLists.txt @@ -1,15 +1,76 @@ # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.13) project(SOF_TPLG_PARSER C) +include(../../scripts/cmake/misc.cmake) +include(CheckCCompilerFlag) + +set(default_asoc_h "/usr/include/alsa/sound/uapi/asoc.h") + set(sof_source_directory "${PROJECT_SOURCE_DIR}/../..") -add_library(sof_tplg_parser SHARED tplg_parser.c) +if (CONFIG_LIBRARY_STATIC) + add_library(sof_tplg_parser STATIC "") +else() + add_library(sof_tplg_parser SHARED "") +endif() + +if (CONFIG_IPC4) + set(tplg_ipc CONFIG_IPC_MAJOR_4) +else() + set(tplg_ipc CONFIG_IPC_MAJOR_3) +endif() + +target_sources(sof_tplg_parser PUBLIC + tokens.c + process.c + control.c + pcm.c + pga.c + mixer.c + pipeline.c + host.c + dai.c + asrc.c + src.c + buffer.c + graph.c + object.c + audio_formats.c +) + +sof_append_relative_path_definitions(sof_tplg_parser) + target_include_directories(sof_tplg_parser PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/include) -target_compile_options(sof_tplg_parser PRIVATE -g -O -Wall -Werror -Wl,-EL -Wmissing-prototypes -Wimplicit-fallthrough=3) +target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/audio) +target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/arch/host/include) +target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/src/platform/library/include) +target_include_directories(sof_tplg_parser PRIVATE ${sof_source_directory}/posix/include) + +# Configuration time, make copy +configure_file(${default_asoc_h} ${CMAKE_CURRENT_BINARY_DIR}/include/alsa/sound/asoc.h) + +# Build time +target_include_directories(sof_tplg_parser PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include") + +# -Wimplicit-fallthrough is preferred, check if it's supported +check_c_compiler_flag(-Wimplicit-fallthrough supports_implicit_fallthrough) +if (supports_implicit_fallthrough) + set(implicit_fallthrough -Wimplicit-fallthrough) +endif() + +# TODO: add IPC4 option when it's ready. +target_compile_options(sof_tplg_parser PRIVATE + -g -O -Wall -Werror -fPIC -DPIC + -Wmissing-prototypes ${implicit_fallthrough} + -DCONFIG_LIBRARY -D${tplg_ipc}) + +target_link_libraries(sof_tplg_parser PRIVATE -lm) + +include(../../scripts/cmake/uuid-registry.cmake) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/tplg_parser DESTINATION include @@ -17,4 +78,3 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/tplg_parser ) install(TARGETS sof_tplg_parser DESTINATION lib) - diff --git a/tools/tplg_parser/asrc.c b/tools/tplg_parser/asrc.c new file mode 100644 index 000000000000..fd098e610260 --- /dev/null +++ b/tools/tplg_parser/asrc.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> + +#include <ipc/topology.h> +#include <ipc/stream.h> +#include <sof/common.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +/* ASRC - IPC3 */ +static const struct sof_topology_token asrc3_tokens[] = { + {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_asrc, source_rate), 0}, + {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_asrc, sink_rate), 0}, + {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_asrc, asynchronous_mode), 0}, + {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_asrc, operation_mode), 0}, +}; + +static const struct sof_topology_token_group asrc_ipc3_tokens[] = { + {asrc3_tokens, ARRAY_SIZE(asrc3_tokens)}, + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_asrc, config)}, + {comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens), + sizeof(struct sof_ipc_comp_asrc)}, +}; + +static int asrc_ipc3_build(struct tplg_context *ctx, void *_asrc) +{ + struct sof_ipc_comp_asrc *asrc = _asrc; + int comp_id = ctx->comp_id; + + /* configure asrc */ + asrc->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + asrc->comp.id = comp_id; + asrc->comp.hdr.size = sizeof(struct sof_ipc_comp_asrc) + UUID_SIZE; + asrc->comp.type = SOF_COMP_ASRC; + asrc->comp.pipeline_id = ctx->pipeline_id; + asrc->comp.ext_data_length = UUID_SIZE; + asrc->config.hdr.size = sizeof(struct sof_ipc_comp_config); + + return 0; +} + +/* ASRC - IPC4 */ +static const struct sof_topology_token asrc4_tokens[] = { + {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct ipc4_asrc_module_cfg, out_freq), 0}, + {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct ipc4_asrc_module_cfg, asrc_mode), 0}, +}; + +static const struct sof_topology_token_group asrc_ipc4_tokens[] = { + {asrc4_tokens, ARRAY_SIZE(asrc4_tokens)}, +}; + +static int asrc_ipc4_build(struct tplg_context *ctx, void *asrc) +{ + /* TODO */ + return 0; +} + +static const struct sof_topology_module_desc asrc_ipc[] = { + {3, asrc_ipc3_tokens, ARRAY_SIZE(asrc_ipc3_tokens), + asrc_ipc3_build, sizeof(struct sof_ipc_comp_asrc) + UUID_SIZE}, + {4, asrc_ipc4_tokens, ARRAY_SIZE(asrc_ipc4_tokens), asrc_ipc4_build}, +}; + +/* load asrc dapm widget */ +int tplg_new_asrc(struct tplg_context *ctx, void *asrc, size_t asrc_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size) +{ + int ret; + + ret = tplg_create_object(ctx, asrc_ipc, ARRAY_SIZE(asrc_ipc), + "asrc", asrc, asrc_size); + if (ret < 0) + return ret; + + if (tplg_create_controls(ctx, ctx->widget->num_kcontrols, + rctl, max_ctl_size, asrc) < 0) { + fprintf(stderr, "error: loading controls\n"); + return -EINVAL; + } + + return ret; +} diff --git a/tools/tplg_parser/audio_formats.c b/tools/tplg_parser/audio_formats.c new file mode 100644 index 000000000000..39a54e7f6100 --- /dev/null +++ b/tools/tplg_parser/audio_formats.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Audio format token parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <math.h> +#include <ipc/topology.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +static const struct sof_topology_token ipc4_audio_fmt_num_tokens[] = { + {SOF_TKN_COMP_NUM_INPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_available_audio_format, num_input_formats)}, + {SOF_TKN_COMP_NUM_OUTPUT_AUDIO_FORMATS, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_available_audio_format, num_output_formats)}, +}; + +static const struct sof_topology_token ipc4_in_audio_format_tokens[] = { + {SOF_TKN_CAVS_AUDIO_FORMAT_IN_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IN_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IN_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IN_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_pin_format, audio_fmt.interleaving_style)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IN_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_INPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, pin_index)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_IBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, buffer_size)}, +}; + +static const struct sof_topology_token ipc4_out_audio_format_tokens[] = { + {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_RATE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_pin_format, audio_fmt.sampling_frequency)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_BIT_DEPTH, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.bit_depth)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_MAP, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_map)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_CH_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.ch_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_INTERLEAVING_STYLE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_pin_format, audio_fmt.interleaving_style)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OUT_FMT_CFG, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, audio_fmt.fmt_cfg)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OUTPUT_PIN_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct sof_ipc4_pin_format, pin_index)}, + {SOF_TKN_CAVS_AUDIO_FORMAT_OBS, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc4_pin_format, buffer_size)}, +}; + +static const struct sof_topology_token ipc4_comp_pin_tokens[] = { + {SOF_TKN_COMP_NUM_INPUT_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct tplg_pins_info, num_input_pins)}, + {SOF_TKN_COMP_NUM_OUTPUT_PINS, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, offsetof(struct tplg_pins_info, num_output_pins)}, +}; + +int tplg_parse_widget_audio_formats(struct tplg_context *ctx) +{ + struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0]; + struct tplg_comp_info *comp_info = ctx->current_comp_info; + struct sof_ipc4_available_audio_format *available_fmts = &comp_info->available_fmt; + struct sof_ipc4_pin_format *pin_fmt; + struct sof_ipc4_audio_format *fmt; + int size = ctx->widget->priv.size; + int ret, i; + + /* first parse the number of input and output pin formats */ + ret = sof_parse_token_sets(available_fmts, ipc4_audio_fmt_num_tokens, + ARRAY_SIZE(ipc4_audio_fmt_num_tokens), array, size, 1, 0); + if (ret < 0) { + fprintf(stderr, "widget: %s: Failed to parse audio_fmt_num_tokens\n", + ctx->widget->name); + return ret; + } + + tplg_debug("widget: %s: number of input formats: %d number of output formats: %d\n", + ctx->widget->name, available_fmts->num_input_formats, + available_fmts->num_output_formats); + + /* allocated memory for the audio formats */ + available_fmts->output_pin_fmts = + calloc(sizeof(struct sof_ipc4_pin_format) * available_fmts->num_output_formats, 1); + if (!available_fmts->output_pin_fmts) + return -ENOMEM; + + available_fmts->input_pin_fmts = + calloc(sizeof(struct sof_ipc4_pin_format) * available_fmts->num_input_formats, 1); + if (!available_fmts->input_pin_fmts) { + free(available_fmts->output_pin_fmts); + return -ENOMEM; + } + + /* now parse the pin audio formats */ + array = &ctx->widget->priv.array[0]; + ret = sof_parse_token_sets(available_fmts->input_pin_fmts, ipc4_in_audio_format_tokens, + ARRAY_SIZE(ipc4_in_audio_format_tokens), array, size, + available_fmts->num_input_formats, + sizeof(struct sof_ipc4_pin_format)); + if (ret < 0) { + fprintf(stderr, "widget: %s: failed to parse ipc4_in_audio_format_tokens\n", + ctx->widget->name); + return ret; + } + + array = &ctx->widget->priv.array[0]; + ret = sof_parse_token_sets(available_fmts->output_pin_fmts, ipc4_out_audio_format_tokens, + ARRAY_SIZE(ipc4_out_audio_format_tokens), array, size, + available_fmts->num_output_formats, + sizeof(struct sof_ipc4_pin_format)); + if (ret < 0) { + fprintf(stderr, "widget: %s: failed to parse ipc4_out_audio_format_tokens\n", + ctx->widget->name); + return ret; + } + + /* print available audio formats */ + pin_fmt = available_fmts->output_pin_fmts; + for (i = 0; i < available_fmts->num_output_formats; i++) { + fmt = &pin_fmt[i].audio_fmt; + tplg_debug("Output Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", + pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map, + fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg, + pin_fmt[i].buffer_size); + } + + pin_fmt = available_fmts->input_pin_fmts; + for (i = 0; i < available_fmts->num_input_formats; i++) { + fmt = &pin_fmt[i].audio_fmt; + tplg_debug("Input Pin index #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", + pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, + fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg, + pin_fmt[i].buffer_size); + } + + ret = sof_parse_token_sets(&comp_info->pins_info, ipc4_comp_pin_tokens, + ARRAY_SIZE(ipc4_comp_pin_tokens), array, size, 1, 0); + if (ret < 0) + fprintf(stderr, "widget: %s: Failed to parse ipc4_comp_pin_tokens\n", + ctx->widget->name); + + return ret; +} diff --git a/tools/tplg_parser/buffer.c b/tools/tplg_parser/buffer.c new file mode 100644 index 000000000000..1690693d8a03 --- /dev/null +++ b/tools/tplg_parser/buffer.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <ipc/topology.h> +#include <ipc/stream.h> +#include <ipc4/gateway.h> +#include <sof/common.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +#include "copier/copier.h" + +/* Buffers */ +static const struct sof_topology_token buffer_tokens[] = { + {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_buffer, size), 0}, + {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_buffer, caps), 0}, + {SOF_TKN_BUF_FLAGS, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_buffer, flags), 0}, +}; + +static const struct sof_topology_token buffer_comp_tokens[] = { + {SOF_TKN_COMP_CORE_ID, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp, core), 0}, +}; + + +/* Buffer - IPC3 */ +static const struct sof_topology_token_group buffer_ipc3_tokens[] = { + {buffer_comp_tokens, ARRAY_SIZE(buffer_comp_tokens), + offsetof(struct sof_ipc_buffer, comp)}, + {buffer_tokens, ARRAY_SIZE(buffer_tokens), + 0}, +}; + +static int buffer_ipc3_build(struct tplg_context *ctx, void *_buffer) +{ + struct sof_ipc_buffer *buffer = _buffer; + int comp_id = ctx->comp_id; + + /* configure buffer */ + buffer->comp.core = 0; + buffer->comp.id = comp_id; + buffer->comp.pipeline_id = ctx->pipeline_id; + buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW; + buffer->comp.type = SOF_COMP_BUFFER; + buffer->comp.hdr.size = sizeof(struct sof_ipc_buffer); + + return 0; +} + +static const struct sof_topology_token buffer4_tokens[] = { +}; + +static const struct sof_topology_token_group buffer_ipc4_tokens[] = { + {buffer4_tokens, ARRAY_SIZE(buffer4_tokens)}, +}; + +static int buffer_ipc4_build(struct tplg_context *ctx, void *_copier) +{ + struct ipc4_copier_module_cfg *copier = _copier; + + copier->gtw_cfg.node_id.dw = IPC4_INVALID_NODE_ID; + + return tplg_parse_widget_audio_formats(ctx); +} + +static const struct sof_topology_module_desc buffer_ipc[] = { + {3, buffer_ipc3_tokens, ARRAY_SIZE(buffer_ipc3_tokens), + buffer_ipc3_build, sizeof(struct sof_ipc_buffer)}, + {4, buffer_ipc4_tokens, ARRAY_SIZE(buffer_ipc4_tokens), buffer_ipc4_build}, +}; + +int tplg_new_buffer(struct tplg_context *ctx, void *buffer, size_t buffer_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t buffer_ctl_size) +{ + int ret; + + ret = tplg_create_object(ctx, buffer_ipc, ARRAY_SIZE(buffer_ipc), + "buffer", buffer, buffer_size); + + return ret; +} diff --git a/tools/tplg_parser/control.c b/tools/tplg_parser/control.c new file mode 100644 index 000000000000..c2deddf61a4f --- /dev/null +++ b/tools/tplg_parser/control.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +int tplg_get_single_control(struct tplg_context *ctx, + struct snd_soc_tplg_ctl_hdr **ctl, + struct snd_soc_tplg_private **priv_data) +{ + struct snd_soc_tplg_ctl_hdr *ctl_hdr; + struct snd_soc_tplg_mixer_control *mixer_ctl = NULL; + struct snd_soc_tplg_enum_control *enum_ctl = NULL; + struct snd_soc_tplg_bytes_control *bytes_ctl = NULL; + + /* These are set if success */ + *ctl = NULL; + *priv_data = NULL; + + ctl_hdr = tplg_get(ctx); + + /* load control based on type */ + switch (ctl_hdr->ops.info) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_STROBE: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + case SND_SOC_TPLG_CTL_RANGE: + case SND_SOC_TPLG_DAPM_CTL_VOLSW: + /* load mixer type control */ + mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl_hdr; + if (priv_data) + *priv_data = &mixer_ctl->priv; + /* ctl is after private data */ + *ctl = tplg_get_object_priv(ctx, mixer_ctl, mixer_ctl->priv.size); + break; + + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_CTL_ENUM_VALUE: + case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: + case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: + case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: + /* load enum type control */ + enum_ctl = (struct snd_soc_tplg_enum_control *)ctl_hdr; + if (priv_data) + *priv_data = &enum_ctl->priv; + /* ctl is after private data */ + *ctl = tplg_get_object_priv(ctx, enum_ctl, enum_ctl->priv.size); + break; + case SND_SOC_TPLG_CTL_BYTES: + /* load bytes type control */ + bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl_hdr; + if (priv_data) + *priv_data = &bytes_ctl->priv; + /* ctl is after private data */ + *ctl = tplg_get_object_priv(ctx, bytes_ctl, bytes_ctl->priv.size); + break; + + default: + printf("info: control type %d not supported\n", + ctl_hdr->ops.info); + return -EINVAL; + } + + return 0; +} + +/* load dapm widget kcontrols + * we don't use controls in the fuzzer atm. + * so just skip to the next dapm widget + */ +int tplg_create_controls(struct tplg_context *ctx, int num_kcontrols, + struct snd_soc_tplg_ctl_hdr *rctl, + size_t max_ctl_size, void *object) +{ + struct snd_soc_tplg_ctl_hdr *ctl_hdr = NULL; + struct snd_soc_tplg_mixer_control *mixer_ctl; + struct snd_soc_tplg_enum_control *enum_ctl; + struct snd_soc_tplg_bytes_control *bytes_ctl; + int num_mixers = 0; + int num_enums = 0; + int num_byte_controls = 0; + int index; + int j, ret = 0; + + for (j = 0; j < num_kcontrols; j++) { + + ctl_hdr = tplg_get(ctx); + + /* load control based on type */ + switch (ctl_hdr->ops.info) { + case SND_SOC_TPLG_CTL_VOLSW: + case SND_SOC_TPLG_CTL_STROBE: + case SND_SOC_TPLG_CTL_VOLSW_SX: + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: + case SND_SOC_TPLG_CTL_RANGE: + case SND_SOC_TPLG_DAPM_CTL_VOLSW: + index = num_mixers++; + /* load mixer type control */ + mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl_hdr; + /* ctl is after private data */ + tplg_get_object_priv(ctx, mixer_ctl, mixer_ctl->priv.size); + break; + + case SND_SOC_TPLG_CTL_ENUM: + case SND_SOC_TPLG_CTL_ENUM_VALUE: + case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: + case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: + case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: + index = num_enums++; + /* load enum_ctl type control */ + enum_ctl = (struct snd_soc_tplg_enum_control *)ctl_hdr; + /* ctl is after private data */ + tplg_get_object_priv(ctx, enum_ctl, enum_ctl->priv.size); + break; + + case SND_SOC_TPLG_CTL_BYTES: + index = num_byte_controls++; + /* load bytes_ctl type control */ + bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl_hdr; + /* ctl is after private data */ + tplg_get_object_priv(ctx, bytes_ctl, bytes_ctl->priv.size); + break; + default: + printf("info: control type %d not supported\n", + ctl_hdr->ops.info); + return -EINVAL; + } + + if (ctx->ctl_cb && object) { + ret = ctx->ctl_cb(ctl_hdr, object, ctx->ctl_arg, index); + if (ret) { + fprintf(stderr, "error: failed control callback\n"); + goto err; + } + } + } + + if (rctl && ctl_hdr) { + /* make sure the CTL will fit if we need to copy it for others */ + if (ctl_hdr->size > max_ctl_size) { + fprintf(stderr, "error: failed control control copy\n"); + ret = -EINVAL; + goto err; + } + memcpy(rctl, ctl_hdr, ctl_hdr->size); + } +err: + return ret; +} diff --git a/tools/tplg_parser/dai.c b/tools/tplg_parser/dai.c new file mode 100644 index 000000000000..f74a431bb200 --- /dev/null +++ b/tools/tplg_parser/dai.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <ipc/topology.h> +#include <ipc/stream.h> +#include <ipc/dai.h> +#include <sof/common.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +struct sof_dai_types { + const char *name; + enum sof_ipc_dai_type type; +}; + +const struct sof_dai_types sof_dais[] = { + {"SSP", SOF_DAI_INTEL_SSP}, + {"HDA", SOF_DAI_INTEL_HDA}, + {"DMIC", SOF_DAI_INTEL_DMIC}, +}; + +/* find dai type */ +static enum sof_ipc_dai_type find_dai(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sof_dais); i++) { + if (strcmp(name, sof_dais[i].name) == 0) + return sof_dais[i].type; + } + + return SOF_DAI_INTEL_NONE; +} + +static int get_token_dai_type(void *elem, void *object, uint32_t offset, uint32_t size) +{ + struct snd_soc_tplg_vendor_string_elem *velem = elem; + uint32_t *val = (uint32_t *)((uint8_t *)object + offset); + + *val = find_dai(velem->string); + return 0; +} + +static const struct sof_topology_token dai_tokens[] = { + {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, + offsetof(struct sof_ipc_comp_dai, type), 0}, + {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_dai, dai_index), 0}, + {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_dai, direction), 0}, +}; + +/* DAI - IPC3 */ +static const struct sof_topology_token_group dai_ipc3_tokens[] = { + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_dai, config)}, + {dai_tokens, ARRAY_SIZE(dai_tokens), + 0}, +}; + +static int dai_ipc3_build(struct tplg_context *ctx, void *_dai) +{ + struct sof_ipc_comp_dai *dai = _dai; + int comp_id = ctx->comp_id; + + /* configure dai */ + dai->comp.hdr.size = sizeof(*dai); + dai->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + dai->comp.id = comp_id; + dai->comp.type = SOF_COMP_DAI; + dai->comp.pipeline_id = ctx->pipeline_id; + dai->config.hdr.size = sizeof(dai->config); + + return 0; +} + +/* DAI - IPC4 */ +static const struct sof_topology_token dai4_tokens[] = { + /* TODO */ +}; + +static const struct sof_topology_token_group dai_ipc4_tokens[] = { + {dai4_tokens, ARRAY_SIZE(dai4_tokens)}, +}; + +static int dai_ipc4_build(struct tplg_context *ctx, void *dai) +{ + /* TODO */ + return 0; +} + +static const struct sof_topology_module_desc dai_ipc[] = { + {3, dai_ipc3_tokens, ARRAY_SIZE(dai_ipc3_tokens), + dai_ipc3_build, sizeof(struct sof_ipc_comp_dai)}, + {4, dai_ipc4_tokens, ARRAY_SIZE(dai_ipc4_tokens), dai_ipc4_build}, +}; + +int tplg_new_dai(struct tplg_context *ctx, void *dai, size_t dai_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size) +{ + int ret; + + ret = tplg_create_object(ctx, dai_ipc, ARRAY_SIZE(dai_ipc), + "dai", dai, dai_size); + return ret; +} + diff --git a/tools/tplg_parser/graph.c b/tools/tplg_parser/graph.c new file mode 100644 index 000000000000..7bc9f33449bd --- /dev/null +++ b/tools/tplg_parser/graph.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/list.h> +#include <sof/ipc/topology.h> +#include <kernel/header.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +/* load pipeline graph DAPM widget*/ +int tplg_create_graph(struct tplg_context *ctx, int count, int pipeline_id, + struct tplg_comp_info *temp_comp_list, char *pipeline_string, + struct sof_ipc_pipe_comp_connect *connection, + int route_num) +{ + struct snd_soc_tplg_dapm_graph_elem *graph_elem; + char *source = NULL, *sink = NULL; + int j; + + /* configure route */ + connection->hdr.size = sizeof(*connection); + connection->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT; + + + /* set up component connections */ + connection->source_id = -1; + connection->sink_id = -1; + + graph_elem = tplg_get_graph(ctx); + + /* look up component id from the component list */ + for (j = 0; j < count; j++) { + if (strcmp(temp_comp_list[j].name, + graph_elem->source) == 0) { + connection->source_id = temp_comp_list[j].id; + source = graph_elem->source; + } + + if (strcmp(temp_comp_list[j].name, + graph_elem->sink) == 0) { + connection->sink_id = temp_comp_list[j].id; + sink = graph_elem->sink; + } + } + + if (!source || !sink) { + fprintf(stderr, "%s() error: source=%p, sink=%p\n", + __func__, source, sink); + return -EINVAL; + } + + printf("loading route %s -> %s\n", source, sink); + + strcat(pipeline_string, graph_elem->source); + strcat(pipeline_string, "->"); + + if (route_num == (count - 1)) { + strcat(pipeline_string, graph_elem->sink); + strcat(pipeline_string, "\n"); + } + + return 0; +} + +/* parse and save the route information for IPC4 */ +int tplg_parse_graph(struct tplg_context *ctx, struct list_item *widget_list, + struct list_item *route_list) +{ + struct snd_soc_tplg_dapm_graph_elem *graph_elem; + struct tplg_route_info *route; + struct list_item *item; + + route = calloc(sizeof(struct tplg_route_info), 1); + if (!route) + return -ENOMEM; + + graph_elem = tplg_get_graph(ctx); + + /* look up from the widget list and populate the route info */ + list_for_item(item, widget_list) { + struct tplg_comp_info *comp_info = container_of(item, struct tplg_comp_info, item); + + if (!strcmp(comp_info->name, graph_elem->source)) + route->source = comp_info; + + if (!strcmp(comp_info->name, graph_elem->sink)) + route->sink = comp_info; + } + + if (!route->source || !route->sink) { + fprintf(stderr, "%s() error loading route: source=%s, sink=%s\n", + __func__, graph_elem->source, graph_elem->sink); + free(route); + return -EINVAL; + } + + list_item_append(&route->item, route_list); + + tplg_debug("loading route %s -> %s\n", route->source->name, route->sink->name); + + return 0; +} diff --git a/tools/tplg_parser/host.c b/tools/tplg_parser/host.c new file mode 100644 index 000000000000..55f42f4bc0c0 --- /dev/null +++ b/tools/tplg_parser/host.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +/* PCM */ +static const struct sof_topology_token pcm_tokens[] = { + {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_host, dmac_config), 0}, +}; + +/* PCM - IPC3 */ +static const struct sof_topology_token_group pcm_ipc3_tokens[] = { + {pcm_tokens, ARRAY_SIZE(pcm_tokens), + offsetof(struct sof_ipc_comp_host, comp)}, + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_host, config)}, +}; + +static int pcm_ipc3_build(struct tplg_context *ctx, void *_pcm) +{ + struct sof_ipc_comp_host *host = _pcm; + int comp_id = ctx->comp_id; + + /* configure host comp IPC message */ + host->comp.hdr.size = sizeof(*host); + host->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + host->comp.id = comp_id; + host->comp.type = SOF_COMP_HOST; + host->comp.pipeline_id = ctx->pipeline_id; + host->direction = ctx->dir; + host->config.hdr.size = sizeof(host->config); + + return 0; +} + +/* PCM - IPC4 */ +static const struct sof_topology_token pcm4_tokens[] = { + /* TODO */ +}; + +static const struct sof_topology_token_group pcm_ipc4_tokens[] = { + {pcm4_tokens, ARRAY_SIZE(pcm4_tokens)}, +}; + +static int pcm_ipc4_build(struct tplg_context *ctx, void *pcm) +{ + /* TODO */ + return 0; +} + +static const struct sof_topology_module_desc pcm_ipc[] = { + {3, pcm_ipc3_tokens, ARRAY_SIZE(pcm_ipc3_tokens), + pcm_ipc3_build, sizeof(struct sof_ipc_comp_host)}, + {4, pcm_ipc4_tokens, ARRAY_SIZE(pcm_ipc4_tokens), pcm_ipc4_build}, +}; + +int tplg_new_pcm(struct tplg_context *ctx, void *host, size_t host_size) +{ + return tplg_create_object(ctx, pcm_ipc, ARRAY_SIZE(pcm_ipc), + "pcm", host, host_size); +} + diff --git a/tools/tplg_parser/include/linux/types.h b/tools/tplg_parser/include/linux/types.h new file mode 100644 index 000000000000..b06e50b3c8f4 --- /dev/null +++ b/tools/tplg_parser/include/linux/types.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef __TPLG_PARSER_LINUX_TYPES_H__ +#define __TPLG_PARSER_LINUX_TYPES_H__ + +#include <stdint.h> + +/* + * This header files allows to include asoc.h for topology parsing to + * non-gcc builds with other C library, e.g. the one that is used by + * xt-xcc compiler. The kernel linux/types.h cannot be used because + * the other definitions there are not compatible with the toolchain. + */ + +/* There are minimum types needed for alsa/sound/uapi/asoc.h */ + +typedef int64_t __le64; +typedef int32_t __le32; +typedef int16_t __le16; +typedef uint8_t __u8; + +#endif /* __TPLG_PARSER_LINUX_TYPES_H__ */ diff --git a/tools/tplg_parser/include/tplg_parser/tokens.h b/tools/tplg_parser/include/tplg_parser/tokens.h new file mode 100644 index 000000000000..e6c63f015b04 --- /dev/null +++ b/tools/tplg_parser/include/tplg_parser/tokens.h @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#ifndef _COMMON_TPLG_TOKENS_H +#define _COMMON_TPLG_TOKENS_H + +#include <ipc/topology.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> + +/* temporary - current MAXLEN is not define in UAPI header - fix pending */ +#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN +#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 +#endif + +#include <linux/types.h> +#include <alsa/sound/asoc.h> + +struct sof_topology_token { + uint32_t token; + uint32_t type; + int (*get_token)(void *elem, void *object, uint32_t offset, + uint32_t size); + uint32_t offset; + uint32_t size; +}; + +static const struct sof_topology_token tone_tokens[] = { +}; + +/* Generic components */ +static const struct sof_topology_token comp_tokens[] = { + {SOF_TKN_COMP_PERIOD_SINK_COUNT, + SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_config, periods_sink), 0}, + {SOF_TKN_COMP_PERIOD_SOURCE_COUNT, + SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_config, periods_source), 0}, + {SOF_TKN_COMP_FORMAT, + SND_SOC_TPLG_TUPLE_TYPE_STRING, tplg_token_get_comp_format, + offsetof(struct sof_ipc_comp_config, frame_fmt), 0}, +}; + +/* Component extended tokens */ +static const struct sof_topology_token comp_ext_tokens[] = { + {SOF_TKN_COMP_UUID, SND_SOC_TPLG_TUPLE_TYPE_UUID, tplg_token_get_uuid, 0, 0}, + +}; + +struct sof_topology_token_group { + const struct sof_topology_token *tokens; + const int num_tokens; + const int grp_offset; +}; + +struct sof_topology_module_desc { + const int abi_major; + const struct sof_topology_token_group *grp; + const int num_groups; + int (*builder)(struct tplg_context *ctx, void *data); + const int min_size; +}; + +#endif diff --git a/tools/tplg_parser/include/tplg_parser/topology.h b/tools/tplg_parser/include/tplg_parser/topology.h index 5315baac3394..04988d688082 100644 --- a/tools/tplg_parser/include/tplg_parser/topology.h +++ b/tools/tplg_parser/include/tplg_parser/topology.h @@ -10,258 +10,326 @@ #ifndef _COMMON_TPLG_H #define _COMMON_TPLG_H -#include <sound/asoc.h> +#include <stdbool.h> +#include <stdarg.h> +#include <stddef.h> #include <ipc/dai.h> +#include <ipc/topology.h> +#include <ipc/stream.h> +#include <ipc4/module.h> #include <kernel/tokens.h> +#include <sof/list.h> +#include <volume/peak_volume.h> +#include <src/src_ipc.h> +#include <asrc/asrc_ipc4.h> -#define SOF_DEV 1 -#define FUZZER_DEV 2 +#include "copier/copier.h" -struct comp_info { +#ifdef TPLG_DEBUG +#define DEBUG_MAX_LENGTH 256 +static inline void tplg_debug(char *fmt, ...) +{ + char msg[DEBUG_MAX_LENGTH]; + va_list va; + + va_start(va, fmt); + vsnprintf(msg, DEBUG_MAX_LENGTH, fmt, va); + va_end(va); + + fprintf(stdout, "%s", msg); +} +#else +static inline void tplg_debug(char *fmt, ...) {} +#endif + +/* temporary - current MAXLEN is not define in UAPI header - fix pending */ +#ifndef SNDRV_CTL_ELEM_ID_NAME_MAXLEN +#define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 +#endif + +#include <linux/types.h> +#include <alsa/sound/asoc.h> + +#define TPLG_PARSER_SOF_DEV 1 +#define TPLG_PARSER_FUZZER_DEV 2 +#define TPLG_MAX_PCM_PIPELINES 16 + +#define MOVE_POINTER_BY_BYTES(p, b) ((typeof(p))((uint8_t *)(p) + (b))) + +struct testbench_prm; +struct snd_soc_tplg_vendor_array; +struct snd_soc_tplg_ctl_hdr; +struct sof_topology_token; +struct sof; +struct fuzz; +struct sof_topology_module_desc; + +struct sof_ipc4_audio_format { + uint32_t sampling_frequency; + uint32_t bit_depth; + uint32_t ch_map; + uint32_t ch_cfg; /* sof_ipc4_channel_config */ + uint32_t interleaving_style; + uint32_t fmt_cfg; /* channels_count valid_bit_depth s_type */ +} __packed __aligned(4); + +/** + * struct sof_ipc4_pin_format - Module pin format + * @pin_index: pin index + * @buffer_size: buffer size in bytes + * @audio_fmt: audio format for the pin + * + * This structure can be used for both output or input pins and the pin_index is relative to the + * pin type i.e output/input pin + */ +struct sof_ipc4_pin_format { + uint32_t pin_index; + uint32_t buffer_size; + struct sof_ipc4_audio_format audio_fmt; +}; + +/** + * struct sof_ipc4_available_audio_format - Available audio formats + * @output_pin_fmts: Available output pin formats + * @input_pin_fmts: Available input pin formats + * @num_input_formats: Number of input pin formats + * @num_output_formats: Number of output pin formats + */ +struct sof_ipc4_available_audio_format { + struct sof_ipc4_pin_format *output_pin_fmts; + struct sof_ipc4_pin_format *input_pin_fmts; + uint32_t num_input_formats; + uint32_t num_output_formats; +}; + +struct tplg_pipeline_info { + int id; + int instance_id; + int usage_count; + int mem_usage; + char *name; + struct list_item item; /* item in a list */ +}; + +struct tplg_pins_info { + uint32_t num_input_pins; + uint32_t num_output_pins; +}; + +struct tplg_comp_info { + struct list_item item; /* item in a list */ + struct sof_ipc4_available_audio_format available_fmt; /* available formats in tplg */ + struct ipc4_module_init_instance module_init; + struct ipc4_base_module_cfg basecfg; + struct tplg_pipeline_info *pipe_info; + struct sof_uuid uuid; + struct tplg_pins_info pins_info; char *name; + char *stream_name; int id; int type; int pipeline_id; + void *ipc_payload; + int ipc_size; + int instance_id; + int module_id; }; -struct frame_types { - char *name; - enum sof_ipc_frame frame; +struct tplg_route_info { + struct tplg_comp_info *source; + struct tplg_comp_info *sink; + struct list_item item; /* item in a list */ }; -static const struct frame_types sof_frames[] = { - /* TODO: fix topology to use ALSA formats */ - {"s16le", SOF_IPC_FRAME_S16_LE}, - {"s24le", SOF_IPC_FRAME_S24_4LE}, - {"s32le", SOF_IPC_FRAME_S32_LE}, - {"float", SOF_IPC_FRAME_FLOAT}, - /* ALSA formats */ - {"S16_LE", SOF_IPC_FRAME_S16_LE}, - {"S24_LE", SOF_IPC_FRAME_S24_4LE}, - {"S32_LE", SOF_IPC_FRAME_S32_LE}, - {"FLOAT_LE", SOF_IPC_FRAME_FLOAT}, +struct tplg_pipeline_list { + int count; + struct tplg_pipeline_info *pipelines[TPLG_MAX_PCM_PIPELINES]; }; -/** \brief Types of processing components */ -enum sof_ipc_process_type { - SOF_PROCESS_NONE = 0, /**< None */ - SOF_PROCESS_EQFIR, /**< Intel FIR */ - SOF_PROCESS_EQIIR, /**< Intel IIR */ - SOF_PROCESS_KEYWORD_DETECT, /**< Keyword Detection */ - SOF_PROCESS_KPB, /**< KeyPhrase Buffer Manager */ - SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */ - SOF_PROCESS_MUX, - SOF_PROCESS_DEMUX, +struct tplg_pcm_info { + char *name; + int id; + struct tplg_comp_info *playback_host; + struct tplg_comp_info *capture_host; + struct list_item item; /* item in a list */ + struct tplg_pipeline_list playback_pipeline_list; + struct tplg_pipeline_list capture_pipeline_list; }; -struct sof_topology_token { - uint32_t token; - uint32_t type; - int (*get_token)(void *elem, void *object, uint32_t offset, - uint32_t size); - uint32_t offset; - uint32_t size; -}; +/* + * Per topology data. + * + * TODO: Some refactoring still required to move pipeline specific data. + */ +struct tplg_context { -enum sof_ipc_frame find_format(const char *name); + /* pipeline and core IDs we are processing */ + int pipeline_id; + int core_id; -int get_token_uint32_t(void *elem, void *object, uint32_t offset, - uint32_t size); + /* current IPC object and widget */ + struct snd_soc_tplg_hdr *hdr; + struct snd_soc_tplg_dapm_widget *widget; + struct tplg_comp_info *current_comp_info; + int comp_id; + size_t widget_size; + int dev_type; + int sched_id; + int dir; -int get_token_comp_format(void *elem, void *object, uint32_t offset, - uint32_t size); + /* global data */ + void *tplg_base; + size_t tplg_size; + long tplg_offset; + struct sof *sof; + const char *tplg_file; + struct fuzz *fuzzer; + int ipc_major; -/* Buffers */ -static const struct sof_topology_token buffer_tokens[] = { - {SOF_TKN_BUF_SIZE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_buffer, size), 0}, - {SOF_TKN_BUF_CAPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_buffer, caps), 0}, + /* kcontrol creation */ + void *ctl_arg; + int (*ctl_cb)(struct snd_soc_tplg_ctl_hdr *tplg_ctl, + void *comp, void *arg, int index); }; -/* scheduling */ -static const struct sof_topology_token sched_tokens[] = { - {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_pipe_new, period), 0}, - {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_pipe_new, priority), 0}, - {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_pipe_new, period_mips), 0}, - {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_pipe_new, core), 0}, - {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_pipe_new, frames_per_sched), 0}, - {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_pipe_new, time_domain), 0}, -}; +#define tplg_get(ctx) ((void *)(ctx->tplg_base + ctx->tplg_offset)) -/* volume */ -static const struct sof_topology_token volume_tokens[] = { - {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_volume, ramp), 0}, - {SOF_TKN_VOLUME_RAMP_STEP_MS, - SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_comp_volume, initial_ramp), 0}, -}; +#define tplg_get_hdr(ctx) \ + ({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%zx at offset %ld\n", \ + __func__, __LINE__, ptr->size, sizeof(*ptr), \ + ctx->tplg_offset); assert(0); \ + } \ + ctx->tplg_offset += sizeof(*ptr); (void *)ptr; }) -/* SRC */ -static const struct sof_topology_token src_tokens[] = { - {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_src, source_rate), 0}, - {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_src, sink_rate), 0}, -}; +#define tplg_skip_hdr_payload(ctx) \ + ({struct snd_soc_tplg_hdr *ptr; \ + ptr = (struct snd_soc_tplg_hdr *)(ctx->tplg_base + ctx->tplg_offset); \ + ctx->tplg_offset += hdr->payload_size; (void *)ptr; }) -/* ASRC */ -static const struct sof_topology_token asrc_tokens[] = { - {SOF_TKN_ASRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_comp_asrc, source_rate), 0}, - {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_asrc, sink_rate), 0}, - {SOF_TKN_ASRC_ASYNCHRONOUS_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_asrc, asynchronous_mode), 0}, - {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_asrc, operation_mode), 0}, -}; +#define tplg_get_object(ctx, obj) \ + ({void *ptr; ptr = ctx->tplg_base + ctx->tplg_offset; \ + ctx->tplg_offset += sizeof(*(obj)); ptr; }) -/* EFFECT */ -int get_token_process_type(void *elem, void *object, uint32_t offset, - uint32_t size); +#define tplg_get_object_priv(ctx, obj, priv_size) \ + ({void *ptr; ptr = ctx->tplg_base + ctx->tplg_offset; \ + ctx->tplg_offset += sizeof(*(obj)) + priv_size; ptr; }) -static const struct sof_topology_token process_tokens[] = { - {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, - get_token_process_type, - offsetof(struct sof_ipc_comp_process, type), 0}, -}; +#define tplg_get_widget(ctx) \ + ({struct snd_soc_tplg_dapm_widget *w; \ + w = (struct snd_soc_tplg_dapm_widget *)(ctx->tplg_base + ctx->tplg_offset); \ + ctx->tplg_offset += sizeof(*w) + w->priv.size; w; }) -/* Tone */ -static const struct sof_topology_token tone_tokens[] = { -}; +#define tplg_get_graph(ctx) \ + ({struct snd_soc_tplg_dapm_graph_elem *w; \ + w = (struct snd_soc_tplg_dapm_graph_elem *)(ctx->tplg_base + ctx->tplg_offset); \ + ctx->tplg_offset += sizeof(*w); w; }) -/* Generic components */ -static const struct sof_topology_token comp_tokens[] = { - {SOF_TKN_COMP_PERIOD_SINK_COUNT, - SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_comp_config, periods_sink), 0}, - {SOF_TKN_COMP_PERIOD_SOURCE_COUNT, - SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_comp_config, periods_source), 0}, - {SOF_TKN_COMP_FORMAT, - SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_comp_format, - offsetof(struct sof_ipc_comp_config, frame_fmt), 0}, -}; +#define tplg_get_pcm(ctx) \ + ({struct snd_soc_tplg_pcm *pcm; \ + pcm = (struct snd_soc_tplg_pcm *)(ctx->tplg_base + ctx->tplg_offset); \ + ctx->tplg_offset += sizeof(*pcm) + pcm->priv.size; pcm; }) -/* PCM */ -static const struct sof_topology_token pcm_tokens[] = { - {SOF_TKN_PCM_DMAC_CONFIG, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_host, dmac_config), 0}, -}; +static inline int tplg_valid_widget(struct snd_soc_tplg_dapm_widget *widget) +{ + if (widget->size == sizeof(struct snd_soc_tplg_dapm_widget)) + return 1; + else + return 0; +} -/* DAI */ -enum sof_ipc_dai_type find_dai(const char *name); - -int get_token_dai_type(void *elem, void *object, uint32_t offset, - uint32_t size); -static const struct sof_topology_token dai_tokens[] = { - {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, - offsetof(struct sof_ipc_comp_dai, type), 0}, - {SOF_TKN_DAI_INDEX, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_uint32_t, - offsetof(struct sof_ipc_comp_dai, dai_index), 0}, - {SOF_TKN_DAI_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, - get_token_uint32_t, - offsetof(struct sof_ipc_comp_dai, direction), 0}, -}; +enum sof_ipc_frame tplg_find_format(const char *name); -struct sof_dai_types { - const char *name; - enum sof_ipc_dai_type type; -}; +int tplg_token_get_uint32_t(void *elem, void *object, uint32_t offset, + uint32_t size); + +int tplg_token_get_comp_format(void *elem, void *object, uint32_t offset, + uint32_t size); + +int tplg_token_get_uuid(void *elem, void *object, uint32_t offset, uint32_t size); int sof_parse_tokens(void *object, const struct sof_topology_token *tokens, int count, struct snd_soc_tplg_vendor_array *array, int priv_size); -void sof_parse_string_tokens(void *object, - const struct sof_topology_token *tokens, - int count, + +int sof_parse_string_tokens(void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array); + +int sof_parse_uuid_tokens(void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array); + +int sof_parse_word_tokens(void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array); + +int tplg_read_array(struct snd_soc_tplg_vendor_array *array); + +int tplg_new_buffer(struct tplg_context *ctx, void *buffer, size_t buffer_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t buffer_ctl_size); + +int tplg_create_dai(struct tplg_context *ctx, + struct sof_ipc_comp_dai *comp_dai); + +int tplg_create_pipeline(struct tplg_context *ctx, + struct sof_ipc_pipe_new *pipeline); + +int tplg_get_single_control(struct tplg_context *ctx, + struct snd_soc_tplg_ctl_hdr **ctl, + struct snd_soc_tplg_private **priv); + +int tplg_create_controls(struct tplg_context *ctx, int num_kcontrols, + struct snd_soc_tplg_ctl_hdr *rctl, + size_t max_ctl_size, void *object); + +int tplg_new_pcm(struct tplg_context *ctx, void *host, size_t host_size); + +int tplg_new_pipeline(struct tplg_context *ctx, void *pipeline, + size_t pipeline_size, struct snd_soc_tplg_ctl_hdr *rctl); + +int tplg_new_mixer(struct tplg_context *ctx, void *mixer, size_t mixer_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size); + +int tplg_new_src(struct tplg_context *ctx, void *src, size_t src_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t ctl_size); + +int tplg_new_asrc(struct tplg_context *ctx, void *asrc, size_t asrc_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t ctl_size); + +int tplg_new_pga(struct tplg_context *ctx, void *pga, size_t pga_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t ctl_size); + +int tplg_new_dai(struct tplg_context *ctx, void *dai, size_t dai_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size); + +int tplg_new_process(struct tplg_context *ctx, void *process, size_t process_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size); + +int tplg_create_graph(struct tplg_context *ctx, int count, int pipeline_id, + struct tplg_comp_info *temp_comp_list, char *pipeline_string, + struct sof_ipc_pipe_comp_connect *connection, + int route_num); + +bool tplg_is_valid_priv_size(size_t size_read, size_t priv_size, struct snd_soc_tplg_vendor_array *array); -void sof_parse_uuid_tokens(void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array); -void sof_parse_word_tokens(void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array); -int get_token_dai_type(void *elem, void *object, uint32_t offset, - uint32_t size); -enum sof_ipc_dai_type find_dai(const char *name); - -int tplg_read_array(struct snd_soc_tplg_vendor_array *array, FILE *file); -int tplg_load_buffer(int comp_id, int pipeline_id, int size, - struct sof_ipc_buffer *buffer, FILE *file); -int tplg_load_pcm(int comp_id, int pipeline_id, int size, int dir, - struct sof_ipc_comp_host *host, FILE *file); -int tplg_load_dai(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_dai *comp_dai, FILE *file); -int tplg_load_pga(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_volume *volume, FILE *file); -int tplg_load_pipeline(int comp_id, int pipeline_id, int size, - struct sof_ipc_pipe_new *pipeline, FILE *file); -int tplg_load_one_control(struct snd_soc_tplg_ctl_hdr **ctl, char **priv, - FILE *file); -int tplg_load_controls(int num_kcontrols, FILE *file); -int tplg_load_src(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_src *src, FILE *file); -int tplg_load_asrc(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_asrc *asrc, FILE *file); -int tplg_load_mixer(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_mixer *mixer, FILE *file); -int tplg_load_process(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_process *process, FILE *file); -int tplg_load_graph(int num_comps, int pipeline_id, - struct comp_info *temp_comp_list, char *pipeline_string, - struct sof_ipc_pipe_comp_connect *connection, FILE *file, - int route_num, int count); - -int load_pga(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget); - -int load_aif_in_out(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, void *tp); -int load_dai_in_out(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, int dir, void *tp); -int load_buffer(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget); -int load_pipeline(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, - int sched_id); -int load_src(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, void *params); -int load_asrc(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget, void *params); -int load_mixer(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget); -int load_process(void *dev, int comp_id, int pipeline_id, - struct snd_soc_tplg_dapm_widget *widget); -int load_widget(void *dev, int dev_type, struct comp_info *temp_comp_list, - int comp_id, int comp_index, int pipeline_id, void *tp, - int *sched_id, FILE *file); - -void register_comp(int comp_type); -int find_widget(struct comp_info *temp_comp_list, int count, char *name); + +int tplg_create_object(struct tplg_context *ctx, + const struct sof_topology_module_desc *desc, int num_desc, + const char *name, void *object, size_t max_object_size); +int sof_parse_token_sets(void *object, const struct sof_topology_token *tokens, + int count, struct snd_soc_tplg_vendor_array *array, + int priv_size, int num_sets, int object_size); +int tplg_parse_widget_audio_formats(struct tplg_context *ctx); +int tplg_parse_graph(struct tplg_context *ctx, struct list_item *widget_list, + struct list_item *route_list); +int tplg_parse_pcm(struct tplg_context *ctx, struct list_item *widget_list, + struct list_item *pcm_list); #endif diff --git a/tools/tplg_parser/mixer.c b/tools/tplg_parser/mixer.c new file mode 100644 index 000000000000..61538e87dfae --- /dev/null +++ b/tools/tplg_parser/mixer.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + + +/* MIXER - IPC3 */ +static const struct sof_topology_token_group mixer_ipc3_tokens[] = { + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_mixer, config)}, + {comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens), + sizeof(struct sof_ipc_comp_mixer)}, +}; + +static int mixer_ipc3_build(struct tplg_context *ctx, void *_mixer) +{ + struct sof_ipc_comp_mixer *mixer = _mixer; + int comp_id = ctx->comp_id; + + /* configure mixer */ + mixer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + mixer->comp.id = comp_id; + mixer->comp.hdr.size = sizeof(struct sof_ipc_comp_mixer) + UUID_SIZE; + mixer->comp.type = SOF_COMP_MIXER; + mixer->comp.pipeline_id = ctx->pipeline_id; + mixer->comp.ext_data_length = UUID_SIZE; + mixer->config.hdr.size = sizeof(struct sof_ipc_comp_config); + + return 0; +} + +static int mixer_ipc4_build(struct tplg_context *ctx, void *mixer) +{ + return tplg_parse_widget_audio_formats(ctx); +} + +static const struct sof_topology_module_desc mixer_ipc[] = { + {3, mixer_ipc3_tokens, ARRAY_SIZE(mixer_ipc3_tokens), + mixer_ipc3_build, sizeof(struct sof_ipc_comp_mixer) + UUID_SIZE}, + {4, NULL, 0, mixer_ipc4_build}, +}; + +int tplg_new_mixer(struct tplg_context *ctx, void *mixer, size_t mixer_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size) +{ + int ret; + + ret = tplg_create_object(ctx, mixer_ipc, ARRAY_SIZE(mixer_ipc), + "mixer", mixer, mixer_size); + if (ret < 0) + return ret; + + if (tplg_create_controls(ctx, ctx->widget->num_kcontrols, + rctl, max_ctl_size, mixer) < 0) { + fprintf(stderr, "error: loading controls\n"); + return -EINVAL; + } + + return ret; +} diff --git a/tools/tplg_parser/object.c b/tools/tplg_parser/object.c new file mode 100644 index 000000000000..4592031c7c01 --- /dev/null +++ b/tools/tplg_parser/object.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> + +#include <ipc/topology.h> +#include <ipc/stream.h> +#include <sof/common.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +/* create object from descriptors */ +int tplg_create_object(struct tplg_context *ctx, + const struct sof_topology_module_desc *desc, int num_desc, + const char *name, void *object, size_t max_object_size) +{ + struct snd_soc_tplg_vendor_array *array = &ctx->widget->priv.array[0]; + size_t total_array_size = 0; + const struct sof_topology_module_desc *ipc = NULL; + int ret, i; + int size = ctx->widget->priv.size; + + for (i = 0; i < num_desc; i++) { + if (desc[i].abi_major != ctx->ipc_major) + continue; + /* match */ + ipc = &desc[i]; + break; + } + if (!ipc) { + printf("error: %s no support for IPC major %d\n", __func__, + ctx->ipc_major); + return -EINVAL; + } + + if (max_object_size < ipc->min_size) { + printf("error: %s not enough space, have %zu need %d\n", + __func__, max_object_size, ipc->min_size); + return -EINVAL; + } + + memset(object, 0, max_object_size); + + /* read vendor tokens */ + while (total_array_size < size) { + /* check for array size mismatch */ + if (!tplg_is_valid_priv_size(total_array_size, size, array)) { + fprintf(stderr, "error: load %s array size mismatch\n", name); + return -EINVAL; + } + + for (i = 0; i < ipc->num_groups; i++) { + const struct sof_topology_token *tokens = ipc->grp[i].tokens; + int num_tokens = ipc->grp[i].num_tokens; + int offset = ipc->grp[i].grp_offset; + + ret = sof_parse_tokens(object + offset, tokens, + num_tokens, array, + array->size); + if (ret != 0) { + fprintf(stderr, "error: parse %s comp_tokens %d\n", + name, size); + return -EINVAL; + } + } + + total_array_size += array->size; + + /* read next array */ + array = MOVE_POINTER_BY_BYTES(array, array->size); + } + + ret = ipc->builder(ctx, object); + if (ret < 0) + fprintf(stderr, "error: builder for %s failed\n", name); + + return ret; +} diff --git a/tools/tplg_parser/pcm.c b/tools/tplg_parser/pcm.c new file mode 100644 index 000000000000..8bd560b6a785 --- /dev/null +++ b/tools/tplg_parser/pcm.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* FE DAI or PCM parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/list.h> +#include <sof/ipc/topology.h> +#include <kernel/header.h> +#include <tplg_parser/topology.h> + +/* parse and save the PCM information */ +int tplg_parse_pcm(struct tplg_context *ctx, struct list_item *widget_list, + struct list_item *pcm_list) +{ + struct tplg_pcm_info *pcm_info; + struct snd_soc_tplg_pcm *pcm; + struct list_item *item; + + pcm_info = calloc(sizeof(struct tplg_pcm_info), 1); + if (!pcm_info) + return -ENOMEM; + + pcm = tplg_get_pcm(ctx); + + pcm_info->name = strdup(pcm->pcm_name); + if (!pcm_info->name) { + free(pcm_info); + return -ENOMEM; + } + + pcm_info->id = pcm->pcm_id; + + /* look up from the widget list and populate the PCM info */ + list_for_item(item, widget_list) { + struct tplg_comp_info *comp_info = container_of(item, struct tplg_comp_info, item); + + if (!strcmp(pcm->caps[0].name, comp_info->stream_name) && + (comp_info->type == SND_SOC_TPLG_DAPM_AIF_IN || + comp_info->type == SND_SOC_TPLG_DAPM_AIF_OUT)) { + pcm_info->playback_host = comp_info; + tplg_debug("PCM: '%s' ID: %d Host name: %s\n", pcm_info->name, + pcm_info->id, comp_info->name); + } + if (!strcmp(pcm->caps[1].name, comp_info->stream_name) && + (comp_info->type == SND_SOC_TPLG_DAPM_AIF_IN || + comp_info->type == SND_SOC_TPLG_DAPM_AIF_OUT)) { + pcm_info->capture_host = comp_info; + tplg_debug("PCM: '%s' ID: %d Host name: %s\n", pcm_info->name, + pcm_info->id, comp_info->name); + } + } + + list_item_append(&pcm_info->item, pcm_list); + + return 0; +} diff --git a/tools/tplg_parser/pga.c b/tools/tplg_parser/pga.c new file mode 100644 index 000000000000..b4d86a78e0df --- /dev/null +++ b/tools/tplg_parser/pga.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <math.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> +#include <volume/peak_volume.h> + +#define SOF_IPC4_VOL_ZERO_DB 0x7fffffff + +/* volume IPC3 */ +static const struct sof_topology_token volume3_tokens[] = { + {SOF_TKN_VOLUME_RAMP_STEP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_volume, ramp), 0}, + {SOF_TKN_VOLUME_RAMP_STEP_MS, + SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_volume, initial_ramp), 0}, +}; + +static const struct sof_topology_token_group pga_ipc3_tokens[] = { + {volume3_tokens, ARRAY_SIZE(volume3_tokens)}, + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_volume, config)}, + {comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens), + sizeof(struct sof_ipc_comp_volume)}, +}; + +static int pga_ipc3_build(struct tplg_context *ctx, void *_pga) +{ + struct sof_ipc_comp_volume *volume = _pga; + struct snd_soc_tplg_private *priv_data = NULL; + struct snd_soc_tplg_ctl_hdr *ctl = NULL; + struct snd_soc_tplg_mixer_control *mixer_ctl; + int32_t vol_min = 0; + int32_t vol_step = 0; + int32_t vol_maxs = 0; + float vol_min_db; + float vol_max_db; + int channels = 0; + int i, ret = 0; + + /* configure volume */ + volume->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + volume->comp.id = ctx->comp_id; + volume->comp.hdr.size = sizeof(struct sof_ipc_comp_volume) + UUID_SIZE; + volume->comp.type = SOF_COMP_VOLUME; + volume->comp.pipeline_id = ctx->pipeline_id; + volume->comp.ext_data_length = UUID_SIZE; + volume->config.hdr.size = sizeof(struct sof_ipc_comp_config); + + /* Get control into ctl and priv_data */ + for (i = 0; i < ctx->widget->num_kcontrols; i++) { + ret = tplg_get_single_control(ctx, &ctl, &priv_data); + if (ret < 0) { + fprintf(stderr, "error: failed control load\n"); + goto err; + } + + /* call ctl creation callback if needed */ + if (ctx->ctl_cb) + ctx->ctl_cb(ctl, volume, ctx->ctl_arg, 0); + + /* we only care about the volume ctl - ignore others atm */ + if (ctl->ops.get != 256) + continue; + + /* Get volume scale */ + mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl; + vol_min = (int32_t)mixer_ctl->hdr.tlv.scale.min; + vol_step = mixer_ctl->hdr.tlv.scale.step; + vol_maxs = mixer_ctl->max; + channels = mixer_ctl->num_channels; + + vol_min_db = 0.01 * vol_min; + vol_max_db = 0.01 * (vol_maxs * vol_step) + vol_min_db; + volume->min_value = round(pow(10, vol_min_db / 20.0) * 65535); + volume->max_value = round(pow(10, vol_max_db / 20.0) * 65536); + volume->channels = channels; + } + +err: + return ret; +} + +/* Peak Volume - IPC4 */ +static const struct sof_topology_token pga4_tokens[] = { + {SOF_TKN_GAIN_VAL, + SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct ipc4_peak_volume_config, target_volume), 0}, + {SOF_TKN_GAIN_RAMP_TYPE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct ipc4_peak_volume_config, curve_type), 0}, + {SOF_TKN_GAIN_RAMP_DURATION, + SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct ipc4_peak_volume_config, curve_duration), 0}, +}; + +static const struct sof_topology_token_group pga_ipc4_tokens[] = { + {pga4_tokens, ARRAY_SIZE(pga4_tokens)}, +}; + +static int pga_ipc4_build(struct tplg_context *ctx, void *_pga) +{ + struct ipc4_peak_volume_config *volume = _pga; + + volume->channel_id = IPC4_ALL_CHANNELS_MASK; + + tplg_debug("volume channel ID: %d, target_volume %#x, curve_type: %d curve_duration: %ld\n", + volume->channel_id, volume->target_volume, volume->curve_type, + volume->curve_duration); + + return tplg_parse_widget_audio_formats(ctx); +} + +static const struct sof_topology_module_desc pga_ipc[] = { + {3, pga_ipc3_tokens, ARRAY_SIZE(pga_ipc3_tokens), + pga_ipc3_build, sizeof(struct sof_ipc_comp_volume) + UUID_SIZE}, + {4, pga_ipc4_tokens, ARRAY_SIZE(pga_ipc4_tokens), pga_ipc4_build}, +}; + +/* load pda dapm widget */ +int tplg_new_pga(struct tplg_context *ctx, void *pga, + size_t pga_size, struct snd_soc_tplg_ctl_hdr *rctl, + size_t ctl_size) +{ + int ret; + + ret = tplg_create_object(ctx, pga_ipc, ARRAY_SIZE(pga_ipc), + "pga", pga, pga_size); + return ret; +} diff --git a/tools/tplg_parser/pipeline.c b/tools/tplg_parser/pipeline.c new file mode 100644 index 000000000000..4bdd4ee45094 --- /dev/null +++ b/tools/tplg_parser/pipeline.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +/* scheduling */ +static const struct sof_topology_token sched_tokens[] = { + {SOF_TKN_SCHED_PERIOD, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, period), 0}, + {SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, priority), 0}, + {SOF_TKN_SCHED_MIPS, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, period_mips), 0}, + {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, core), 0}, + {SOF_TKN_SCHED_FRAMES, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, frames_per_sched), 0}, + {SOF_TKN_SCHED_TIME_DOMAIN, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, time_domain), 0}, +}; + +/* Pipeline - IPC3 */ +static const struct sof_topology_token_group pipeline_ipc3_tokens[] = { + {sched_tokens, ARRAY_SIZE(sched_tokens), + 0}, +}; + +static int pipeline_ipc3_build(struct tplg_context *ctx, void *_pipeline) +{ + struct sof_ipc_pipe_new *pipeline = _pipeline; + int comp_id = ctx->comp_id; + + /* configure pipeline */ + pipeline->comp_id = comp_id; + pipeline->pipeline_id = ctx->pipeline_id; + pipeline->hdr.size = sizeof(*pipeline); + pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW; + + return 0; +} + +/* Pipeline - IPC4 */ +static const struct sof_topology_token pipeline4_tokens[] = { + {SOF_TKN_SCHED_CORE, SND_SOC_TPLG_TUPLE_TYPE_WORD, tplg_token_get_uint32_t, + offsetof(struct sof_ipc_pipe_new, core)}, +}; + +static const struct sof_topology_token_group pipeline_ipc4_tokens[] = { + {pipeline4_tokens, ARRAY_SIZE(pipeline4_tokens)}, +}; + +static int pipeline_ipc4_build(struct tplg_context *ctx, void *_pipeline) +{ + struct sof_ipc_pipe_new *pipeline = _pipeline; + + pipeline->pipeline_id = ctx->pipeline_id; + tplg_debug("pipeline: %d core: %d\n", pipeline->pipeline_id, pipeline->core); + + return 0; +} + +static const struct sof_topology_module_desc pipeline_ipc[] = { + {3, pipeline_ipc3_tokens, ARRAY_SIZE(pipeline_ipc3_tokens), + pipeline_ipc3_build, sizeof(struct sof_ipc_pipe_new)}, + {4, pipeline_ipc4_tokens, ARRAY_SIZE(pipeline_ipc4_tokens), pipeline_ipc4_build}, +}; + +/* load pipeline dapm widget */ +int tplg_new_pipeline(struct tplg_context *ctx, void *pipeline, + size_t pipeline_size, struct snd_soc_tplg_ctl_hdr *rctl) +{ + int ret; + + ret = tplg_create_object(ctx, pipeline_ipc, ARRAY_SIZE(pipeline_ipc), + "pipeline", pipeline, pipeline_size); + return ret; +} diff --git a/tools/tplg_parser/process.c b/tools/tplg_parser/process.c new file mode 100644 index 000000000000..5f0d8cdddaf2 --- /dev/null +++ b/tools/tplg_parser/process.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <kernel/header.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +/** \brief Types of processing components */ +enum sof_ipc_process_type { + SOF_PROCESS_NONE = 0, /**< None */ + SOF_PROCESS_EQFIR, /**< Intel FIR */ + SOF_PROCESS_EQIIR, /**< Intel IIR */ + SOF_PROCESS_KEYWORD_DETECT, /**< Keyword Detection */ + SOF_PROCESS_KPB, /**< KeyPhrase Buffer Manager */ + SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */ + SOF_PROCESS_MUX, + SOF_PROCESS_DEMUX, + SOF_PROCESS_DCBLOCK, +}; + +struct sof_process_types { + const char *name; + enum sof_ipc_process_type type; + enum sof_comp_type comp_type; +}; + +static const struct sof_process_types ipc3_process[] = { + {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR}, + {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR}, + {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT}, + {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB}, + {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, + {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, + {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, + {"DCBLOCK", SOF_PROCESS_DCBLOCK, SOF_COMP_DCBLOCK}, +}; + +static enum sof_ipc_process_type process_get_name(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ipc3_process); i++) { + if (strcmp(name, ipc3_process[i].name) == 0) + return ipc3_process[i].type; + } + + return SOF_PROCESS_NONE; +} + +static enum sof_comp_type process_get_type(enum sof_ipc_process_type type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ipc3_process); i++) { + if (ipc3_process[i].type == type) + return ipc3_process[i].comp_type; + } + + return SOF_COMP_NONE; +} + +static int process_token_get_type(void *elem, void *object, uint32_t offset, + uint32_t size) +{ + struct snd_soc_tplg_vendor_string_elem *velem = elem; + uint32_t *val = (uint32_t *)((uint8_t *)object + offset); + + *val = process_get_name(velem->string); + return 0; +} + +static const struct sof_topology_token process_tokens[] = { + {SOF_TKN_PROCESS_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, + process_token_get_type, + offsetof(struct sof_ipc_comp_process, type), 0}, +}; + +/* process - IPC3 */ +static const struct sof_topology_token_group process_ipc3_tokens[] = { + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_process, config)}, + {process_tokens, ARRAY_SIZE(process_tokens), + 0}, + {comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens), + sizeof(struct sof_ipc_comp_process)}, +}; + +static int process_ipc3_build(struct tplg_context *ctx, void *_process) +{ + struct sof_ipc_comp_process *process = _process; + int comp_id = ctx->comp_id; + + /* configure asrc */ + process->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + process->comp.id = comp_id; + process->comp.hdr.size = sizeof(struct sof_ipc_comp_process) + UUID_SIZE; + process->comp.type = process_get_type(process->type); + process->comp.pipeline_id = ctx->pipeline_id; + process->config.hdr.size = sizeof(struct sof_ipc_comp_config); + process->comp.ext_data_length = UUID_SIZE; + + return 0; +} + +/* process - IPC4 */ +static const struct sof_topology_token process4_tokens[] = { + /* TODO */ +}; + +static const struct sof_topology_token_group process_ipc4_tokens[] = { + {process4_tokens, ARRAY_SIZE(process4_tokens)}, +}; + +static int process_ipc4_build(struct tplg_context *ctx, void *process) +{ + return tplg_parse_widget_audio_formats(ctx); +} + +static const struct sof_topology_module_desc process_ipc[] = { + {3, process_ipc3_tokens, ARRAY_SIZE(process_ipc3_tokens), + process_ipc3_build, sizeof(struct sof_ipc_comp_process)}, + {4, process_ipc4_tokens, ARRAY_SIZE(process_ipc4_tokens), + process_ipc4_build}, +}; + +static int process_append_data3(void *_process_ipc, + struct snd_soc_tplg_ctl_hdr *ctl, + struct snd_soc_tplg_private *priv_data, + size_t max_process_size) +{ + struct sof_ipc_comp_process *process_ipc = _process_ipc; + struct snd_soc_tplg_bytes_control *bytes_ctl; + size_t size, ipc_size; + + if (ctl->ops.info != SND_SOC_TPLG_CTL_BYTES) + return 0; + + /* Size is process IPC plus private data minus ABI header */ + bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl; + size = bytes_ctl->priv.size - sizeof(struct sof_abi_hdr); + ipc_size = sizeof(struct sof_ipc_comp_process) + UUID_SIZE + + process_ipc->size + size; + + /* validate if everything will fit */ + if (ipc_size > max_process_size) { + fprintf(stderr, "error: process priv data too big, have %zu need %zu\n", + max_process_size, ipc_size); + return -EINVAL; + } + + /* Copy configuration data, need to strip ABI header*/ + memcpy((char *)process_ipc + sizeof(struct sof_ipc_comp_process) + + UUID_SIZE + process_ipc->size, + (char *)priv_data->data + sizeof(struct sof_abi_hdr), size); + process_ipc->size += size; + return 0; +} + +static int process_append_data4(void *_process_ipc, + struct snd_soc_tplg_ctl_hdr *ctl, + struct snd_soc_tplg_private *priv_data, + size_t max_process_size) +{ + struct sof_ipc_comp_process *process_ipc = _process_ipc; + struct snd_soc_tplg_bytes_control *bytes_ctl; + size_t size; + + if (ctl->ops.info != SND_SOC_TPLG_CTL_BYTES) + return 0; + + /* Size is process IPC plus private data minus ABI header */ + bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl; + size = bytes_ctl->priv.size - sizeof(struct sof_abi_hdr); + + /* validate if everything will fit */ + if (size > max_process_size) { + fprintf(stderr, "error: process priv data too big, have %zu need %zu\n", + max_process_size, size); + return -EINVAL; + } + + /* Copy configuration data, need to strip ABI header */ + memcpy((char *)process_ipc + process_ipc->size, + (char *)priv_data->data + sizeof(struct sof_abi_hdr), size); + process_ipc->size += size; + + fprintf(stdout, "process configuration data size %#x\n", process_ipc->size); + + return 0; +} + +int tplg_new_process(struct tplg_context *ctx, void *process, size_t process_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size) +{ + struct snd_soc_tplg_dapm_widget *widget = ctx->widget; + struct snd_soc_tplg_ctl_hdr *ctl = NULL; + struct snd_soc_tplg_private *priv_data = NULL; + int ret, i; + + ret = tplg_create_object(ctx, process_ipc, ARRAY_SIZE(process_ipc), + "process", process, process_size); + + /* Get control into ctl and priv_data */ + for (i = 0; i < widget->num_kcontrols; i++) { + + ret = tplg_get_single_control(ctx, &ctl, &priv_data); + if (ret < 0) { + fprintf(stderr, "error: failed control load\n"); + return ret; + } + + /* call ctl creation callback if needed */ + if (ctx->ctl_cb) + ctx->ctl_cb(ctl, process, ctx->ctl_arg, 0); + + /* Merge process and priv_data into process_ipc */ + if (!priv_data) + continue; + switch (ctx->ipc_major) { + case 3: + ret = process_append_data3(process, ctl, + priv_data, process_size); + break; + case 4: + ret = process_append_data4(process, ctl, priv_data, process_size); + break; + default: + break; + } + if (ret < 0) { + fprintf(stderr, "error: failed to append process priv data\n"); + return ret; + } + } + + return ret; +} diff --git a/tools/tplg_parser/src.c b/tools/tplg_parser/src.c new file mode 100644 index 000000000000..a6eb6149963a --- /dev/null +++ b/tools/tplg_parser/src.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> +#include <src/src_ipc.h> + +/* SRC - IPC3 */ +static const struct sof_topology_token src3_tokens[] = { + {SOF_TKN_SRC_RATE_IN, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_src, source_rate), 0}, + {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct sof_ipc_comp_src, sink_rate), 0}, +}; + +static const struct sof_topology_token_group src_ipc3_tokens[] = { + {src3_tokens, ARRAY_SIZE(src3_tokens)}, + {comp_tokens, ARRAY_SIZE(comp_tokens), + offsetof(struct sof_ipc_comp_src, config)}, + {comp_ext_tokens, ARRAY_SIZE(comp_ext_tokens), + sizeof(struct sof_ipc_comp_src)}, +}; + +static int src_ipc3_build(struct tplg_context *ctx, void *_src) +{ + struct sof_ipc_comp_src *src = _src; + int comp_id = ctx->comp_id; + + /* configure src */ + src->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; + src->comp.id = comp_id; + src->comp.hdr.size = sizeof(struct sof_ipc_comp_src) + UUID_SIZE; + src->comp.type = SOF_COMP_SRC; + src->comp.pipeline_id = ctx->pipeline_id; + src->comp.ext_data_length = UUID_SIZE; + src->config.hdr.size = sizeof(struct sof_ipc_comp_config); + + return 0; +} + +/* ASRC - IPC4 */ +static const struct sof_topology_token src4_tokens[] = { + {SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, + tplg_token_get_uint32_t, + offsetof(struct ipc4_config_src, sink_rate), 0}, +}; + +static const struct sof_topology_token_group src_ipc4_tokens[] = { + {src4_tokens, ARRAY_SIZE(src4_tokens)}, +}; + +static int src_ipc4_build(struct tplg_context *ctx, void *src) +{ + /* TODO */ + return 0; +} + +static const struct sof_topology_module_desc src_ipc[] = { + {3, src_ipc3_tokens, ARRAY_SIZE(src_ipc3_tokens), + src_ipc3_build, sizeof(struct sof_ipc_comp_src) + UUID_SIZE}, + {4, src_ipc4_tokens, ARRAY_SIZE(src_ipc4_tokens), src_ipc4_build}, +}; + +/* load src dapm widget */ +int tplg_new_src(struct tplg_context *ctx, void *src, size_t src_size, + struct snd_soc_tplg_ctl_hdr *rctl, size_t max_ctl_size) +{ + int ret; + + ret = tplg_create_object(ctx, src_ipc, ARRAY_SIZE(src_ipc), + "src", src, src_size); + if (ret < 0) + return ret; + + if (tplg_create_controls(ctx, ctx->widget->num_kcontrols, + rctl, max_ctl_size, src) < 0) { + fprintf(stderr, "error: loading controls\n"); + return -EINVAL; + } + + return ret; +} diff --git a/tools/tplg_parser/tokens.c b/tools/tplg_parser/tokens.c new file mode 100644 index 000000000000..f736f7ed4bbd --- /dev/null +++ b/tools/tplg_parser/tokens.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> + +/* Topology parser */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <string.h> +#include <ipc/topology.h> +#include <sof/lib/uuid.h> +#include <sof/ipc/topology.h> +#include <tplg_parser/topology.h> +#include <tplg_parser/tokens.h> + +struct frame_types { + char *name; + enum sof_ipc_frame frame; +}; + +static const struct frame_types sof_frames[] = { + /* TODO: fix topology to use ALSA formats */ + {"s16le", SOF_IPC_FRAME_S16_LE}, + {"s24le", SOF_IPC_FRAME_S24_4LE}, + {"s32le", SOF_IPC_FRAME_S32_LE}, + {"float", SOF_IPC_FRAME_FLOAT}, + /* ALSA formats */ + {"S16_LE", SOF_IPC_FRAME_S16_LE}, + {"S24_LE", SOF_IPC_FRAME_S24_4LE}, + {"S32_LE", SOF_IPC_FRAME_S32_LE}, + {"FLOAT_LE", SOF_IPC_FRAME_FLOAT}, +}; + +enum sof_ipc_frame tplg_find_format(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sof_frames); i++) { + if (strcmp(name, sof_frames[i].name) == 0) + return sof_frames[i].frame; + } + + /* use s32le if nothing is specified */ + return SOF_IPC_FRAME_S32_LE; +} + +/* helper functions to get tokens */ +int tplg_token_get_uint32_t(void *elem, void *object, uint32_t offset, + uint32_t size) +{ + struct snd_soc_tplg_vendor_value_elem *velem = elem; + char *vobject = object; + uint32_t *val = (uint32_t *)(vobject + offset); + + *val = velem->value; + return 0; +} + +int tplg_token_get_uuid(void *elem, void *object, uint32_t offset, + uint32_t size) +{ + struct snd_soc_tplg_vendor_uuid_elem *velem = elem; + uint8_t *dst = (uint8_t *)object + offset; + + memcpy(dst, velem->uuid, UUID_SIZE); + + return 0; +} + +int tplg_token_get_comp_format(void *elem, void *object, uint32_t offset, + uint32_t size) +{ + struct snd_soc_tplg_vendor_string_elem *velem = elem; + char *vobject = object; + uint32_t *val = (uint32_t *)(vobject + offset); + + *val = tplg_find_format(velem->string); + return 0; +} + +int sof_parse_token_sets(void *object, const struct sof_topology_token *tokens, + int count, struct snd_soc_tplg_vendor_array *array, + int priv_size, int num_sets, int object_size) +{ + size_t offset = 0; + int total = 0; + int found = 0; + int asize; + int ret; + + while (priv_size > 0 && total < count * num_sets) { + asize = array->size; + + /* validate asize */ + if (asize < 0) { /* FIXME: A zero-size array makes no sense */ + fprintf(stderr, "error: invalid array size 0x%x\n", + asize); + return -EINVAL; + } + + /* make sure there is enough data before parsing */ + priv_size -= asize; + if (priv_size < 0) { + fprintf(stderr, "error: invalid priv size 0x%x\n", + priv_size); + return -EINVAL; + } + + /* call correct parser depending on type */ + switch (array->type) { + case SND_SOC_TPLG_TUPLE_TYPE_UUID: + found = sof_parse_uuid_tokens(object + offset, tokens, count, array); + break; + case SND_SOC_TPLG_TUPLE_TYPE_STRING: + ret = sof_parse_string_tokens(object + offset, tokens, count, array); + if (ret < 0) + return ret; + found = ret; + break; + case SND_SOC_TPLG_TUPLE_TYPE_BOOL: + case SND_SOC_TPLG_TUPLE_TYPE_BYTE: + case SND_SOC_TPLG_TUPLE_TYPE_WORD: + case SND_SOC_TPLG_TUPLE_TYPE_SHORT: + found = sof_parse_word_tokens(object + offset, tokens, count, array); + break; + default: + fprintf(stderr, "error: unknown token type %d\n", + array->type); + return -EINVAL; + } + + array = MOVE_POINTER_BY_BYTES(array, array->size); + + if (found > 0) { + total += count; + offset += object_size; + found = 0; + } + } + + return 0; +} + +/* parse vendor tokens in topology */ +int sof_parse_tokens(void *object, const struct sof_topology_token *tokens, + int count, struct snd_soc_tplg_vendor_array *array, + int priv_size) +{ + /* object_size is not needed when parsing only 1 set of tokens */ + return sof_parse_token_sets(object, tokens, count, array, priv_size, 1, 0); +} + +/* parse word tokens */ +int sof_parse_word_tokens(void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array) +{ + struct snd_soc_tplg_vendor_value_elem *elem; + int found = 0; + int i, j; + + if (sizeof(struct snd_soc_tplg_vendor_value_elem) * array->num_elems + + sizeof(struct snd_soc_tplg_vendor_array) > array->size) { + fprintf(stderr, "error: illegal array number of elements %d\n", + array->num_elems); + return -EINVAL; + } + + /* parse element by element */ + for (i = 0; i < array->num_elems; i++) { + elem = &array->value[i]; + + /* search for token */ + for (j = 0; j < count; j++) { + /* match token type */ + if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_WORD) + continue; + + /* match token id */ + if (tokens[j].token != elem->token) + continue; + + /* matched - now load token */ + tokens[j].get_token(elem, object, tokens[j].offset, + tokens[j].size); + found++; + } + } + + return found; +} + +/* parse uuid tokens */ +int sof_parse_uuid_tokens(void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array) +{ + struct snd_soc_tplg_vendor_uuid_elem *elem; + int found = 0; + int i, j; + + if (sizeof(struct snd_soc_tplg_vendor_uuid_elem) * array->num_elems + + sizeof(struct snd_soc_tplg_vendor_array) > array->size) { + fprintf(stderr, "error: illegal array number of elements %d\n", + array->num_elems); + return -EINVAL; + } + + /* parse element by element */ + for (i = 0; i < array->num_elems; i++) { + elem = &array->uuid[i]; + + /* search for token */ + for (j = 0; j < count; j++) { + /* match token type */ + if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID) + continue; + + /* match token id */ + if (tokens[j].token != elem->token) + continue; + + /* matched - now load token */ + tokens[j].get_token(elem, object, tokens[j].offset, + tokens[j].size); + found++; + } + } + + return found; +} + +/* parse string tokens */ +int sof_parse_string_tokens(void *object, + const struct sof_topology_token *tokens, + int count, + struct snd_soc_tplg_vendor_array *array) +{ + struct snd_soc_tplg_vendor_string_elem *elem; + int found = 0; + int i, j; + + if (sizeof(struct snd_soc_tplg_vendor_string_elem) * array->num_elems + + sizeof(struct snd_soc_tplg_vendor_array) > array->size) { + fprintf(stderr, "error: illegal array number of elements %d\n", + array->num_elems); + return -EINVAL; + } + + /* parse element by element */ + for (i = 0; i < array->num_elems; i++) { + elem = &array->string[i]; + + /* search for token */ + for (j = 0; j < count; j++) { + /* match token type */ + if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING) + continue; + + /* match token id */ + if (tokens[j].token != elem->token) + continue; + + /* matched - now load token */ + tokens[j].get_token(elem, object, tokens[j].offset, + tokens[j].size); + found++; + } + } + + return found; +} + +bool tplg_is_valid_priv_size(size_t size_read, size_t priv_size, + struct snd_soc_tplg_vendor_array *array) +{ + size_t arr_size, elem_size, arr_elems_size; + bool valid; + + arr_size = sizeof(struct snd_soc_tplg_vendor_array); + + switch (array->type) { + case SND_SOC_TPLG_TUPLE_TYPE_UUID: + elem_size = sizeof(struct snd_soc_tplg_vendor_uuid_elem); + break; + case SND_SOC_TPLG_TUPLE_TYPE_STRING: + elem_size = sizeof(struct snd_soc_tplg_vendor_string_elem); + break; + case SND_SOC_TPLG_TUPLE_TYPE_BOOL: + case SND_SOC_TPLG_TUPLE_TYPE_BYTE: + case SND_SOC_TPLG_TUPLE_TYPE_WORD: + case SND_SOC_TPLG_TUPLE_TYPE_SHORT: + elem_size = sizeof(struct snd_soc_tplg_vendor_value_elem); + break; + default: + /* This is handled in the further calls */ + return true; + } + + arr_elems_size = array->num_elems * elem_size; + + /* + * check if size of data to be read from widget's private data + * doesn't exceed private data's size. + */ + valid = size_read + arr_size + arr_elems_size <= priv_size; + if (!valid) + fprintf(stderr, "error: invalid private data size %zu read %zu array %zu elems %zu\n", + priv_size, size_read, arr_size, arr_elems_size); + return valid; +} diff --git a/tools/tplg_parser/tplg_parser.c b/tools/tplg_parser/tplg_parser.c deleted file mode 100644 index ebbf15975376..000000000000 --- a/tools/tplg_parser/tplg_parser.c +++ /dev/null @@ -1,1316 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2019 Intel Corporation. All rights reserved. -// -// Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> - -/* Topology parser */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <stddef.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> -#include <ipc/topology.h> -#include <ipc/stream.h> -#include <ipc/dai.h> -#include <sof/common.h> -#include <tplg_parser/topology.h> - -struct sof_process_types { - const char *name; - enum sof_ipc_process_type type; - enum sof_comp_type comp_type; -}; - -static const struct sof_process_types sof_process[] = { - {"EQFIR", SOF_PROCESS_EQFIR, SOF_COMP_EQ_FIR}, - {"EQIIR", SOF_PROCESS_EQIIR, SOF_COMP_EQ_IIR}, - {"KEYWORD_DETECT", SOF_PROCESS_KEYWORD_DETECT, SOF_COMP_KEYWORD_DETECT}, - {"KPB", SOF_PROCESS_KPB, SOF_COMP_KPB}, - {"CHAN_SELECTOR", SOF_PROCESS_CHAN_SELECTOR, SOF_COMP_SELECTOR}, - {"MUX", SOF_PROCESS_MUX, SOF_COMP_MUX}, - {"DEMUX", SOF_PROCESS_DEMUX, SOF_COMP_DEMUX}, -}; - -static enum sof_ipc_process_type find_process(const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sof_process); i++) { - if (strcmp(name, sof_process[i].name) == 0) - return sof_process[i].type; - } - - return SOF_PROCESS_NONE; -} - -static enum sof_comp_type find_process_comp_type(enum sof_ipc_process_type type) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sof_process); i++) { - if (sof_process[i].type == type) - return sof_process[i].comp_type; - } - - return SOF_COMP_NONE; -} - -/* read vendor tuples array from topology */ -int tplg_read_array(struct snd_soc_tplg_vendor_array *array, FILE *file) -{ - struct snd_soc_tplg_vendor_uuid_elem uuid; - struct snd_soc_tplg_vendor_string_elem string; - struct snd_soc_tplg_vendor_value_elem value; - int j, ret = 0; - size_t size; - - switch (array->type) { - case SND_SOC_TPLG_TUPLE_TYPE_UUID: - - /* copy uuid elems into array */ - for (j = 0; j < array->num_elems; j++) { - size = sizeof(struct snd_soc_tplg_vendor_uuid_elem); - ret = fread(&uuid, size, 1, file); - if (ret != 1) - return -EINVAL; - memcpy(&array->uuid[j], &uuid, size); - } - break; - case SND_SOC_TPLG_TUPLE_TYPE_STRING: - - /* copy string elems into array */ - for (j = 0; j < array->num_elems; j++) { - size = sizeof(struct snd_soc_tplg_vendor_string_elem); - ret = fread(&string, size, 1, file); - if (ret != 1) - return -EINVAL; - memcpy(&array->string[j], &string, size); - } - break; - case SND_SOC_TPLG_TUPLE_TYPE_BOOL: - case SND_SOC_TPLG_TUPLE_TYPE_BYTE: - case SND_SOC_TPLG_TUPLE_TYPE_WORD: - case SND_SOC_TPLG_TUPLE_TYPE_SHORT: - /* copy value elems into array */ - for (j = 0; j < array->num_elems; j++) { - size = sizeof(struct snd_soc_tplg_vendor_value_elem); - ret = fread(&value, size, 1, file); - if (ret != 1) - return -EINVAL; - memcpy(&array->value[j], &value, size); - } - break; - default: - fprintf(stderr, "error: unknown token type %d\n", array->type); - return -EINVAL; - } - return 0; -} - -/* load buffer DAPM widget */ -int tplg_load_buffer(int comp_id, int pipeline_id, int size, - struct sof_ipc_buffer *buffer, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array; - int ret = 0; - - /* configure buffer */ - buffer->comp.core = 0; - buffer->comp.id = comp_id; - buffer->comp.pipeline_id = pipeline_id; - buffer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_BUFFER_NEW; - buffer->comp.type = SOF_COMP_BUFFER; - buffer->comp.hdr.size = sizeof(struct sof_ipc_buffer); - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: malloc fail during load_buffer\n"); - free(array); - return -EINVAL; - } - - ret = fread(array, sizeof(struct snd_soc_tplg_vendor_array), 1, file); - if (ret != 1) { - fprintf(stderr, "error: fread fail during load_buffer\n"); - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - /* parse buffer tokens */ - ret = sof_parse_tokens(buffer, buffer_tokens, - ARRAY_SIZE(buffer_tokens), array, size); - - free(array); - return 0; -} - -int tplg_load_pcm(int comp_id, int pipeline_id, int size, int dir, - struct sof_ipc_comp_host *host, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0, read_size; - int ret = 0; - - /* configure host comp IPC message */ - host->comp.hdr.size = sizeof(*host); - host->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - host->comp.id = comp_id; - host->comp.type = SOF_COMP_HOST; - host->comp.pipeline_id = pipeline_id; - host->direction = dir; - host->config.hdr.size = sizeof(host->config); - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) - return -EINVAL; - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&host->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse comp tokens %d\n", - size); - free(array); - return -EINVAL; - } - - /* parse pcm tokens */ - ret = sof_parse_tokens(host, pcm_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse pcm tokens %d\n", size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - } - - free(array); - return 0; -} - -/* load dai component */ -int tplg_load_dai(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_dai *comp_dai, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array; - size_t total_array_size = 0, read_size; - int ret; - - /* configure comp_dai */ - comp_dai->comp.hdr.size = sizeof(*comp_dai); - comp_dai->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - comp_dai->comp.id = comp_id; - comp_dai->comp.type = SOF_COMP_DAI; - comp_dai->comp.pipeline_id = pipeline_id; - comp_dai->config.hdr.size = sizeof(comp_dai->config); - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - ret = sof_parse_tokens(comp_dai, dai_tokens, - ARRAY_SIZE(dai_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse dai tokens failed %d\n", - size); - free(array); - return -EINVAL; - } - - /* parse comp tokens */ - ret = sof_parse_tokens(&comp_dai->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse filewrite tokens %d\n", - size); - free(array); - return -EINVAL; - } - total_array_size += array->size; - } - - free(array); - return 0; -} - -/* load pda dapm widget */ -int tplg_load_pga(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_volume *volume, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0, read_size; - int ret = 0; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&volume->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse pga comp tokens %d\n", - size); - free(array); - return -EINVAL; - } - - /* parse volume tokens */ - ret = sof_parse_tokens(volume, volume_tokens, - ARRAY_SIZE(volume_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse src tokens %d\n", size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - } - - /* configure volume */ - volume->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - volume->comp.id = comp_id; - volume->comp.hdr.size = sizeof(struct sof_ipc_comp_volume); - volume->comp.type = SOF_COMP_VOLUME; - volume->comp.pipeline_id = pipeline_id; - volume->config.hdr.size = sizeof(struct sof_ipc_comp_config); - - free(array); - return 0; -} - -/* load scheduler dapm widget */ -int tplg_load_pipeline(int comp_id, int pipeline_id, int size, - struct sof_ipc_pipe_new *pipeline, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0, read_size; - int ret = 0; - - /* configure pipeline */ - pipeline->comp_id = comp_id; - pipeline->pipeline_id = pipeline_id; - pipeline->hdr.size = sizeof(*pipeline); - pipeline->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_PIPE_NEW; - pipeline->comp_id = comp_id; - pipeline->pipeline_id = pipeline_id; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read vendor arrays */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - ret = tplg_read_array(array, file); - if (ret < 0) { - free(array); - return -EINVAL; - } - - /* parse scheduler tokens */ - ret = sof_parse_tokens(pipeline, sched_tokens, - ARRAY_SIZE(sched_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse pipeline tokens %d\n", - size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - - /* read next array */ - array = (void *)array + array->size; - } - - array = (void *)array - size; - - free(array); - return 0; -} - -int tplg_load_one_control(struct snd_soc_tplg_ctl_hdr **ctl, char **priv_data, - FILE *file) -{ - struct snd_soc_tplg_ctl_hdr *ctl_hdr; - struct snd_soc_tplg_mixer_control *mixer_ctl = NULL; - struct snd_soc_tplg_enum_control *enum_ctl = NULL; - struct snd_soc_tplg_bytes_control *bytes_ctl = NULL; - size_t rewind_size; - size_t read_size; - size_t hdr_size; - int ret = 0; - - /* These are set if success */ - *ctl = NULL; - *priv_data = NULL; - - /* allocate memory */ - hdr_size = sizeof(struct snd_soc_tplg_ctl_hdr); - ctl_hdr = (struct snd_soc_tplg_ctl_hdr *)malloc(hdr_size); - if (!ctl_hdr) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read control header */ - ret = fread(ctl_hdr, hdr_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* load control based on type */ - switch (ctl_hdr->ops.info) { - case SND_SOC_TPLG_CTL_VOLSW: - case SND_SOC_TPLG_CTL_STROBE: - case SND_SOC_TPLG_CTL_VOLSW_SX: - case SND_SOC_TPLG_CTL_VOLSW_XR_SX: - case SND_SOC_TPLG_CTL_RANGE: - case SND_SOC_TPLG_DAPM_CTL_VOLSW: - /* load mixer type control */ - rewind_size = sizeof(struct snd_soc_tplg_ctl_hdr); - fseek(file, rewind_size * -1, SEEK_CUR); - read_size = sizeof(struct snd_soc_tplg_mixer_control); - mixer_ctl = malloc(read_size); - if (!mixer_ctl) { - fprintf(stderr, "error: mem alloc\n"); - ret = -EINVAL; - goto err; - } - ret = fread(mixer_ctl, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* skip mixer private data */ - fseek(file, mixer_ctl->priv.size, SEEK_CUR); - *ctl = (struct snd_soc_tplg_ctl_hdr *)mixer_ctl; - break; - - case SND_SOC_TPLG_CTL_ENUM: - case SND_SOC_TPLG_CTL_ENUM_VALUE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - /* load enum type control */ - rewind_size = sizeof(struct snd_soc_tplg_ctl_hdr); - fseek(file, rewind_size * -1, SEEK_CUR); - read_size = sizeof(struct snd_soc_tplg_enum_control); - enum_ctl = malloc(read_size); - if (!enum_ctl) { - fprintf(stderr, "error: mem alloc\n"); - ret = -EINVAL; - goto err; - } - ret = fread(enum_ctl, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* skip enum private data */ - fseek(file, enum_ctl->priv.size, SEEK_CUR); - *ctl = (struct snd_soc_tplg_ctl_hdr *)enum_ctl; - break; - - case SND_SOC_TPLG_CTL_BYTES: - /* load bytes type controls */ - rewind_size = sizeof(struct snd_soc_tplg_ctl_hdr); - fseek(file, rewind_size * -1, SEEK_CUR); - read_size = sizeof(struct snd_soc_tplg_bytes_control); - bytes_ctl = malloc(read_size); - if (!bytes_ctl) { - fprintf(stderr, "error: mem alloc\n"); - ret = -EINVAL; - goto err; - } - - ret = fread(bytes_ctl, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* Get private data */ - read_size = bytes_ctl->priv.size; - *priv_data = malloc(read_size); - if (!(*priv_data)) { - fprintf(stderr, "error: mem alloc\n"); - ret = -EINVAL; - goto err; - } - - ret = fread(*priv_data, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - *ctl = (struct snd_soc_tplg_ctl_hdr *)bytes_ctl; - break; - - default: - printf("info: control type not supported\n"); - return -EINVAL; - } - - free(ctl_hdr); - return 0; - -err: - /* free all data */ - free(ctl_hdr); - free(mixer_ctl); - free(enum_ctl); - free(bytes_ctl); - free(*priv_data); - return ret; -} - -/* load dapm widget kcontrols - * we don't use controls in the fuzzer atm. - * so just skip to the next dapm widget - */ -int tplg_load_controls(int num_kcontrols, FILE *file) -{ - struct snd_soc_tplg_ctl_hdr *ctl_hdr; - struct snd_soc_tplg_mixer_control *mixer_ctl; - struct snd_soc_tplg_enum_control *enum_ctl; - struct snd_soc_tplg_bytes_control *bytes_ctl; - size_t read_size, size; - int j, ret = 0; - - /* allocate memory */ - size = sizeof(struct snd_soc_tplg_ctl_hdr); - ctl_hdr = (struct snd_soc_tplg_ctl_hdr *)malloc(size); - if (!ctl_hdr) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - size = sizeof(struct snd_soc_tplg_mixer_control); - mixer_ctl = (struct snd_soc_tplg_mixer_control *)malloc(size); - if (!mixer_ctl) { - fprintf(stderr, "error: mem alloc\n"); - free(ctl_hdr); - return -EINVAL; - } - - size = sizeof(struct snd_soc_tplg_enum_control); - enum_ctl = (struct snd_soc_tplg_enum_control *)malloc(size); - if (!enum_ctl) { - fprintf(stderr, "error: mem alloc\n"); - free(ctl_hdr); - free(mixer_ctl); - return -EINVAL; - } - - size = sizeof(struct snd_soc_tplg_bytes_control); - bytes_ctl = (struct snd_soc_tplg_bytes_control *)malloc(size); - if (!bytes_ctl) { - fprintf(stderr, "error: mem alloc\n"); - free(ctl_hdr); - free(mixer_ctl); - free(enum_ctl); - return -EINVAL; - } - - for (j = 0; j < num_kcontrols; j++) { - /* read control header */ - read_size = sizeof(struct snd_soc_tplg_ctl_hdr); - ret = fread(ctl_hdr, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* load control based on type */ - switch (ctl_hdr->ops.info) { - case SND_SOC_TPLG_CTL_VOLSW: - case SND_SOC_TPLG_CTL_STROBE: - case SND_SOC_TPLG_CTL_VOLSW_SX: - case SND_SOC_TPLG_CTL_VOLSW_XR_SX: - case SND_SOC_TPLG_CTL_RANGE: - case SND_SOC_TPLG_DAPM_CTL_VOLSW: - - /* load mixer type control */ - read_size = sizeof(struct snd_soc_tplg_ctl_hdr); - fseek(file, read_size * -1, SEEK_CUR); - read_size = sizeof(struct snd_soc_tplg_mixer_control); - ret = fread(mixer_ctl, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* skip mixer private data */ - fseek(file, mixer_ctl->priv.size, SEEK_CUR); - break; - case SND_SOC_TPLG_CTL_ENUM: - case SND_SOC_TPLG_CTL_ENUM_VALUE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - - /* load enum type control */ - read_size = sizeof(struct snd_soc_tplg_ctl_hdr); - fseek(file, read_size * -1, SEEK_CUR); - read_size = sizeof(struct snd_soc_tplg_enum_control); - ret = fread(enum_ctl, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* skip enum private data */ - fseek(file, enum_ctl->priv.size, SEEK_CUR); - break; - case SND_SOC_TPLG_CTL_BYTES: - - /* load bytes type controls */ - read_size = sizeof(struct snd_soc_tplg_ctl_hdr); - fseek(file, read_size * -1, SEEK_CUR); - read_size = sizeof(struct snd_soc_tplg_bytes_control); - ret = fread(bytes_ctl, read_size, 1, file); - if (ret != 1) { - ret = -EINVAL; - goto err; - } - - /* skip bytes private data */ - fseek(file, bytes_ctl->priv.size, SEEK_CUR); - break; - default: - printf("info: control type not supported\n"); - return -EINVAL; - } - } - -err: - /* free all data */ - free(mixer_ctl); - free(enum_ctl); - free(bytes_ctl); - free(ctl_hdr); - return ret; -} - -/* load src dapm widget */ -int tplg_load_src(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_src *src, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0, read_size; - int ret = 0; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc for src vendor array\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&src->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse src comp_tokens %d\n", - size); - free(array); - return -EINVAL; - } - - /* parse src tokens */ - ret = sof_parse_tokens(src, src_tokens, - ARRAY_SIZE(src_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse src tokens %d\n", size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - - /* read next array */ - array = (void *)array + array->size; - } - - array = (void *)array - size; - - /* configure src */ - src->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - src->comp.id = comp_id; - src->comp.hdr.size = sizeof(struct sof_ipc_comp_src); - src->comp.type = SOF_COMP_SRC; - src->comp.pipeline_id = pipeline_id; - src->config.hdr.size = sizeof(struct sof_ipc_comp_config); - - free(array); - return 0; -} - -/* load asrc dapm widget */ -int tplg_load_asrc(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_asrc *asrc, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0, read_size; - int ret = 0; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc for asrc vendor array\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&asrc->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse asrc comp_tokens %d\n", - size); - free(array); - return -EINVAL; - } - - /* parse asrc tokens */ - ret = sof_parse_tokens(asrc, asrc_tokens, - ARRAY_SIZE(asrc_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse asrc tokens %d\n", size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - - /* read next array */ - array = (void *)array + array->size; - } - - array = (void *)array - size; - - /* configure asrc */ - asrc->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - asrc->comp.id = comp_id; - asrc->comp.hdr.size = sizeof(struct sof_ipc_comp_asrc); - asrc->comp.type = SOF_COMP_ASRC; - asrc->comp.pipeline_id = pipeline_id; - asrc->config.hdr.size = sizeof(struct sof_ipc_comp_config); - - free(array); - return 0; -} - -/* load asrc dapm widget */ -int tplg_load_process(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_process *process, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0; - size_t read_size; - int ret = 0; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc for asrc vendor array\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&process->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse process comp_tokens %d\n", - size); - free(array); - return -EINVAL; - } - - /* parse process tokens */ - ret = sof_parse_tokens(process, process_tokens, - ARRAY_SIZE(process_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse process tokens %d\n", - size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - - /* read next array */ - array = (void *)array + array->size; - } - - array = (void *)array - size; - - /* configure asrc */ - process->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - process->comp.id = comp_id; - process->comp.hdr.size = sizeof(struct sof_ipc_comp_asrc); - process->comp.type = find_process_comp_type(process->type); - process->comp.pipeline_id = pipeline_id; - process->config.hdr.size = sizeof(struct sof_ipc_comp_config); - - free(array); - return 0; -} - -/* load mixer dapm widget */ -int tplg_load_mixer(int comp_id, int pipeline_id, int size, - struct sof_ipc_comp_mixer *mixer, FILE *file) -{ - struct snd_soc_tplg_vendor_array *array = NULL; - size_t total_array_size = 0, read_size; - int ret = 0; - - /* allocate memory for vendor tuple array */ - array = (struct snd_soc_tplg_vendor_array *)malloc(size); - if (!array) { - fprintf(stderr, "error: mem alloc for src vendor array\n"); - return -EINVAL; - } - - /* read vendor tokens */ - while (total_array_size < size) { - read_size = sizeof(struct snd_soc_tplg_vendor_array); - ret = fread(array, read_size, 1, file); - if (ret != 1) { - free(array); - return -EINVAL; - } - - tplg_read_array(array, file); - - /* parse comp tokens */ - ret = sof_parse_tokens(&mixer->config, comp_tokens, - ARRAY_SIZE(comp_tokens), array, - array->size); - if (ret != 0) { - fprintf(stderr, "error: parse src comp_tokens %d\n", - size); - free(array); - return -EINVAL; - } - - total_array_size += array->size; - - /* read next array */ - array = (void *)array + array->size; - } - - /* point to the start of array so it gets freed properly */ - array = (void *)array - size; - - /* configure src */ - mixer->comp.hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_NEW; - mixer->comp.id = comp_id; - mixer->comp.hdr.size = sizeof(struct sof_ipc_comp_src); - mixer->comp.type = SOF_COMP_MIXER; - mixer->comp.pipeline_id = pipeline_id; - mixer->config.hdr.size = sizeof(struct sof_ipc_comp_config); - - free(array); - return 0; -} - -/* load pipeline graph DAPM widget*/ -int tplg_load_graph(int num_comps, int pipeline_id, - struct comp_info *temp_comp_list, char *pipeline_string, - struct sof_ipc_pipe_comp_connect *connection, FILE *file, - int route_num, int count) -{ - struct snd_soc_tplg_dapm_graph_elem *graph_elem; - char *source, *sink; - int j, ret = 0; - size_t size; - - /* configure route */ - connection->hdr.size = sizeof(*connection); - connection->hdr.cmd = SOF_IPC_GLB_TPLG_MSG | SOF_IPC_TPLG_COMP_CONNECT; - - /* allocate memory for graph elem */ - size = sizeof(struct snd_soc_tplg_dapm_graph_elem); - graph_elem = (struct snd_soc_tplg_dapm_graph_elem *)malloc(size); - if (!graph_elem) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* set up component connections */ - connection->source_id = -1; - connection->sink_id = -1; - - size = sizeof(struct snd_soc_tplg_dapm_graph_elem); - ret = fread(graph_elem, size, 1, file); - if (ret != 1) { - free(graph_elem); - return -EINVAL; - } - - /* look up component id from the component list */ - for (j = 0; j < num_comps; j++) { - if (strcmp(temp_comp_list[j].name, - graph_elem->source) == 0) { - connection->source_id = temp_comp_list[j].id; - source = graph_elem->source; - } - - if (strcmp(temp_comp_list[j].name, - graph_elem->sink) == 0) { - connection->sink_id = temp_comp_list[j].id; - sink = graph_elem->sink; - } - } - - if (connection->source_id == -1 || connection->sink_id == -1) { - free(graph_elem); - return -EINVAL; - } - - printf("loading route %s -> %s\n", source, sink); - - strcat(pipeline_string, graph_elem->source); - strcat(pipeline_string, "->"); - - if (route_num == (count - 1)) - strcat(pipeline_string, graph_elem->sink); - - free(graph_elem); - return 0; -} - -/* load dapm widget */ -int load_widget(void *dev, int dev_type, struct comp_info *temp_comp_list, - int comp_id, int comp_index, int pipeline_id, - void *tp, int *sched_id, FILE *file) -{ - struct snd_soc_tplg_dapm_widget *widget; - size_t read_size; - size_t size; - int ret = 0; - - /* allocate memory for widget */ - size = sizeof(struct snd_soc_tplg_dapm_widget); - widget = (struct snd_soc_tplg_dapm_widget *)malloc(size); - if (!widget) { - fprintf(stderr, "error: mem alloc\n"); - return -EINVAL; - } - - /* read widget data */ - read_size = sizeof(struct snd_soc_tplg_dapm_widget); - ret = fread(widget, read_size, 1, file); - if (ret != 1) - return -EINVAL; - - /* - * create a list with all widget info - * containing mapping between component names and ids - * which will be used for setting up component connections - */ - temp_comp_list[comp_index].id = comp_id; - temp_comp_list[comp_index].name = strdup(widget->name); - temp_comp_list[comp_index].type = widget->id; - temp_comp_list[comp_index].pipeline_id = pipeline_id; - - printf("debug: loading widget %s id %d\n", widget->name, widget->id); - - /* load widget based on type */ - switch (widget->id) { - - /* load pga widget */ - case(SND_SOC_TPLG_DAPM_PGA): - if (load_pga(dev, comp_id, pipeline_id, widget) < 0) { - fprintf(stderr, "error: load pga\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_AIF_IN): - if (load_aif_in_out(dev, comp_id, pipeline_id, widget, - SOF_IPC_STREAM_PLAYBACK, tp) < 0) { - fprintf(stderr, "error: load AIF IN failed\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_AIF_OUT): - if (load_aif_in_out(dev, comp_id, pipeline_id, widget, - SOF_IPC_STREAM_CAPTURE, tp) < 0) { - fprintf(stderr, "error: load AIF OUT failed\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_DAI_IN): - if (load_dai_in_out(dev, comp_id, pipeline_id, widget, - SOF_IPC_STREAM_PLAYBACK, tp) < 0) { - fprintf(stderr, "error: load filewrite\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_DAI_OUT): - if (load_dai_in_out(dev, comp_id, pipeline_id, widget, - SOF_IPC_STREAM_CAPTURE, tp) < 0) { - fprintf(stderr, "error: load filewrite\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_BUFFER): - if (load_buffer(dev, comp_id, pipeline_id, widget) < 0) { - fprintf(stderr, "error: load buffer\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_SCHEDULER): - /* find comp id for scheduling comp */ - if (dev_type == FUZZER_DEV) - *sched_id = find_widget(temp_comp_list, comp_id, - widget->sname); - - if (load_pipeline(dev, comp_id, pipeline_id, widget, - *sched_id) < 0) { - fprintf(stderr, "error: load pipeline\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_SRC): - if (load_src(dev, comp_id, pipeline_id, widget, tp) < 0) { - fprintf(stderr, "error: load src\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_ASRC): - if (load_asrc(dev, comp_id, pipeline_id, widget, tp) < 0) { - fprintf(stderr, "error: load src\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_MIXER): - if (load_mixer(dev, comp_id, pipeline_id, widget) < 0) { - fprintf(stderr, "error: load mixer\n"); - return -EINVAL; - } - break; - case(SND_SOC_TPLG_DAPM_EFFECT): - if (load_process(dev, comp_id, pipeline_id, widget) < 0) { - fprintf(stderr, "error: load effect\n"); - return -EINVAL; - } - break; - /* unsupported widgets */ - default: - fseek(file, widget->priv.size, SEEK_CUR); - printf("info: Widget type not supported %d\n", widget->id); - ret = tplg_load_controls(widget->num_kcontrols, file); - if (ret < 0) { - fprintf(stderr, "error: loading controls\n"); - return ret; - } - break; - } - - free(widget); - return 0; -} - -/* parse vendor tokens in topology */ -int sof_parse_tokens(void *object, const struct sof_topology_token *tokens, - int count, struct snd_soc_tplg_vendor_array *array, - int priv_size) -{ - int asize; - - while (priv_size > 0) { - asize = array->size; - - /* validate asize */ - if (asize < 0) { /* FIXME: A zero-size array makes no sense */ - fprintf(stderr, "error: invalid array size 0x%x\n", - asize); - return -EINVAL; - } - - /* make sure there is enough data before parsing */ - priv_size -= asize; - - if (priv_size < 0) { - fprintf(stderr, "error: invalid array size 0x%x\n", - asize); - return -EINVAL; - } - - /* call correct parser depending on type */ - switch (array->type) { - case SND_SOC_TPLG_TUPLE_TYPE_UUID: - sof_parse_uuid_tokens(object, tokens, count, - array); - break; - case SND_SOC_TPLG_TUPLE_TYPE_STRING: - sof_parse_string_tokens(object, tokens, count, - array); - break; - case SND_SOC_TPLG_TUPLE_TYPE_BOOL: - case SND_SOC_TPLG_TUPLE_TYPE_BYTE: - case SND_SOC_TPLG_TUPLE_TYPE_WORD: - case SND_SOC_TPLG_TUPLE_TYPE_SHORT: - sof_parse_word_tokens(object, tokens, count, - array); - break; - default: - fprintf(stderr, "error: unknown token type %d\n", - array->type); - return -EINVAL; - } - } - return 0; -} - -/* parse word tokens */ -void sof_parse_word_tokens(void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array) -{ - struct snd_soc_tplg_vendor_value_elem *elem; - int i, j; - - /* parse element by element */ - for (i = 0; i < array->num_elems; i++) { - elem = &array->value[i]; - - /* search for token */ - for (j = 0; j < count; j++) { - /* match token type */ - if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_WORD) - continue; - - /* match token id */ - if (tokens[j].token != elem->token) - continue; - - /* matched - now load token */ - tokens[j].get_token(elem, object, tokens[j].offset, - tokens[j].size); - } - } -} - -/* parse uuid tokens */ -void sof_parse_uuid_tokens(void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array) -{ - struct snd_soc_tplg_vendor_uuid_elem *elem; - int i, j; - - /* parse element by element */ - for (i = 0; i < array->num_elems; i++) { - elem = &array->uuid[i]; - - /* search for token */ - for (j = 0; j < count; j++) { - /* match token type */ - if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_UUID) - continue; - - /* match token id */ - if (tokens[j].token != elem->token) - continue; - - /* matched - now load token */ - tokens[j].get_token(elem, object, tokens[j].offset, - tokens[j].size); - } - } -} - -/* parse string tokens */ -void sof_parse_string_tokens(void *object, - const struct sof_topology_token *tokens, - int count, - struct snd_soc_tplg_vendor_array *array) -{ - struct snd_soc_tplg_vendor_string_elem *elem; - int i, j; - - /* parse element by element */ - for (i = 0; i < array->num_elems; i++) { - elem = &array->string[i]; - - /* search for token */ - for (j = 0; j < count; j++) { - /* match token type */ - if (tokens[j].type != SND_SOC_TPLG_TUPLE_TYPE_STRING) - continue; - - /* match token id */ - if (tokens[j].token != elem->token) - continue; - - /* matched - now load token */ - tokens[j].get_token(elem, object, tokens[j].offset, - tokens[j].size); - } - } -} - -enum sof_ipc_frame find_format(const char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sof_frames); i++) { - if (strcmp(name, sof_frames[i].name) == 0) - return sof_frames[i].frame; - } - - /* use s32le if nothing is specified */ - return SOF_IPC_FRAME_S32_LE; -} - -/* helper functions to get tokens */ -int get_token_uint32_t(void *elem, void *object, uint32_t offset, - uint32_t size) -{ - struct snd_soc_tplg_vendor_value_elem *velem = elem; - uint32_t *val = object + offset; - - *val = velem->value; - return 0; -} - -int get_token_comp_format(void *elem, void *object, uint32_t offset, - uint32_t size) -{ - struct snd_soc_tplg_vendor_string_elem *velem = elem; - uint32_t *val = object + offset; - - *val = find_format(velem->string); - return 0; -} - -int get_token_dai_type(void *elem, void *object, uint32_t offset, uint32_t size) -{ - struct snd_soc_tplg_vendor_string_elem *velem = elem; - uint32_t *val = (uint32_t *)((uint8_t *)object + offset); - - *val = find_dai(velem->string); - return 0; -} - -int get_token_process_type(void *elem, void *object, uint32_t offset, - uint32_t size) -{ - struct snd_soc_tplg_vendor_string_elem *velem = elem; - uint32_t *val = (uint32_t *)((uint8_t *)object + offset); - - *val = find_process(velem->string); - return 0; -} diff --git a/tools/tune/common/README.md b/tools/tune/common/README.md new file mode 100644 index 000000000000..1d499dd4485f --- /dev/null +++ b/tools/tune/common/README.md @@ -0,0 +1,31 @@ +Common Scripts to Generate Byte Control Files +======================================= + +The tools need GNU Octave version 4.0.0 or later with octave-signal +package. + +alsactl_write(fn, blob8) +--------------- + +Converts blob8 to a CSV text file. +The output can be used to configure an audio component using sof-ctl. +Example: +``` +sof-ctl -n 22 -s output.csv # Apply config to control numid=22 +``` + +blob_write(fn, blob8) +--------------- + +Converts blob8 to a binary file. +The output can be used to configure an audio component using sof-ctl. +Example: +``` +sof-ctl -n 22 -b set output.bin # Apply config to control numid=22 +``` + +tplg_write(fn, blob8, name, comment) +--------------- + +Converts blob8 to a topology config file. The control bytes generated will +be called {name}_priv. diff --git a/tools/tune/common/sof_alsactl_write.m b/tools/tune/common/sof_alsactl_write.m new file mode 100644 index 000000000000..02bf9ec7dd27 --- /dev/null +++ b/tools/tune/common/sof_alsactl_write.m @@ -0,0 +1,33 @@ +function sof_alsactl_write(fn, blob8) + +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Write blob +sof_check_create_dir(fn); +fh = fopen(fn, 'w'); +if fh < 0 + fprintf(1, 'Error: Could not open file %s\n', fn); + error("Failed."); +end + +%% Pad blob length to multiple of four bytes +n_orig = length(blob8); +n_new = ceil(n_orig/4); +blob8_new = zeros(1, n_new*4); +blob8_new(1:n_orig) = blob8; + +%% Convert to 32 bit +blob32 = zeros(1, n_new, 'uint32'); +k = 2.^[0 8 16 24]; +for i=1:n_new + j = (i-1)*4; + blob32(i) = blob8_new(j+1)*k(1) + blob8_new(j+2)*k(2) ... + + blob8_new(j+3)*k(3) + blob8_new(j+4)*k(4); +end +for i=1:n_new-1 + fprintf(fh, '%ld,', blob32(i)); +end +fprintf(fh, '%ld\n', blob32(end)); +fclose(fh); +end diff --git a/tools/tune/common/sof_blob_write.m b/tools/tune/common/sof_blob_write.m new file mode 100644 index 000000000000..df37669618e1 --- /dev/null +++ b/tools/tune/common/sof_blob_write.m @@ -0,0 +1,30 @@ +function sof_blob_write(fn, blob8) + +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Write blob +check_create_dir(fn); +fh = fopen(fn, 'wb'); +if fh < 0 + fprintf(1, 'Error: Could not open file %s\n', fn); + error("Failed."); +end + +fwrite(fh, blob8, 'uint8'); +fclose(fh); + +%% Print as 8 bit hex +nb = length(blob8); +nl = ceil(nb/16); +for i = 1:nl + m = min(16, nb-(i-1)*16); + for j = 1:m + fprintf(1, "%02x ", blob8((i-1)*16 + j)); + end + fprintf(1, "\n"); +end + +fprintf(1, "\n"); + +end diff --git a/tools/tune/common/sof_check_blob_header.m b/tools/tune/common/sof_check_blob_header.m new file mode 100644 index 000000000000..46a3aed45497 --- /dev/null +++ b/tools/tune/common/sof_check_blob_header.m @@ -0,0 +1,37 @@ +% sof_check_blob_header(blob) +% +% Check for correct header in bytes data. The function +% errors if header is not correct. +% +% Input +% blob - int8 type numbers data +% +% Output +% <none> + +function sof_check_blob_header(blob8) + +% Correct size in header? +blob_bytes = length(blob8); +header_bytes = b2w(blob8(5:8)); +if blob_bytes ~= header_bytes + 8 + fprintf(1, "Error: blob header size %d does not math blob size %d\n", header_bytes, blob_bytes); + fprintf(1, "Is installed sof-ctl up-to-date?\n"); + error("Failed."); +end + +% Correct command? +SOF_CTRL_CMD_BINARY = 3; +value = b2w(blob8(1:4)); +if value ~= SOF_CTRL_CMD_BINARY + fprintf(1, "Error: blob control command is not set to SOF_CTRL_CMD_BINARY.\n"); + fprintf(1, "Is installed sof-ctl up-to-date?\n"); + error("Failed."); +end + +end + +function word =b2w(bytes) + tmp = int32(bytes); + word = tmp(1) + bitshift(tmp(2), 8) + bitshift(tmp(3), 16) + bitshift(tmp(4), 24); +end diff --git a/tools/tune/common/sof_check_create_dir.m b/tools/tune/common/sof_check_create_dir.m new file mode 100644 index 000000000000..49f4b67c52b0 --- /dev/null +++ b/tools/tune/common/sof_check_create_dir.m @@ -0,0 +1,19 @@ +function sof_check_create_dir(fn) + +%% Check path of filename create directory if missing +% +% check_create_dir(fn) +% +% Inputs +% fn - string with path and filename + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2023 Intel Corporation. All rights reserved. + +[filepath, ~, ~] = fileparts(fn); +if ~exist(filepath, "dir") + mkdir(filepath); +end + +end diff --git a/tools/tune/common/sof_get_abi.m b/tools/tune/common/sof_get_abi.m new file mode 100644 index 000000000000..34ebaa3c8e92 --- /dev/null +++ b/tools/tune/common/sof_get_abi.m @@ -0,0 +1,73 @@ +function [bytes, nbytes] = sof_get_abi(setsize, ipc_ver, type, param_id) + +%% Return current SOF ABI header +% +% [bytes, nbytes] = get_abi(setsize, ipc_ver, type, param_id) +% Input +% setsize - size of the payload blob +% ipc_ver - 3 or 4, defaults to 3 +% type - for IPC3, normally 0, defaults to 0 +% param_id - for IPC4, 0 - 255, defaults to 0 +% +% Output +% bytes - returned uint8 type array +% nbytes - length of the array + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright(c) 2018 Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 2 + ipc_ver = 3; +end +if nargin < 3 + type = 0; +end +if nargin < 4 + param_id = 0; +end + +abifn = 'eq_get_abi.bin'; +switch ipc_ver + case 3 + %% Use sof-ctl to write ABI header into a file + cmd = sprintf('sof-ctl -g %d -t %d -b -o %s', setsize, type, abifn); + [bytes, nbytes] = get_abi_with_sofctl(cmd, abifn); + case 4 + cmd = sprintf('sof-ctl -i 4 -g %d -p %d -b -o %s', setsize, param_id, abifn); + [bytes, nbytes] = get_abi_with_sofctl(cmd, abifn); + otherwise + fprintf(1, 'Illegal ipc_ver %d\n', ipc_ver); + error('Failed.'); +end + +end + +function [bytes, nbytes] = get_abi_with_sofctl(cmd, abifn) + +[ret, ~] = system(cmd); +if ret + error('Failed to run sof-ctl. Is it installed?'); +end +fh = fopen(abifn, 'r'); +if fh < 0 + error('Failed to read abi header produced by sof-ctl'); +end +[bytes, nbytes] = fread(fh, inf, 'uint8'); +fclose(fh); +delete(abifn); + +end + +function bytes = w32b(word) + +sh = [0 -8 -16 -24]; +bytes = uint8(zeros(1,4)); +bytes(1) = bitand(bitshift(word, sh(1)), 255); +bytes(2) = bitand(bitshift(word, sh(2)), 255); +bytes(3) = bitand(bitshift(word, sh(3)), 255); +bytes(4) = bitand(bitshift(word, sh(4)), 255); + +end diff --git a/tools/tune/common/sof_tplg2_write.m b/tools/tune/common/sof_tplg2_write.m new file mode 100644 index 000000000000..b0b03b86db11 --- /dev/null +++ b/tools/tune/common/sof_tplg2_write.m @@ -0,0 +1,62 @@ +function sof_tplg2_write(fn, blob8, component, comment, howto) + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2023, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +if nargin < 4 + comment = 'Exported Control Bytes'; +end +if nargin < 5 + howto = []; +end + +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Drop the 8 bytes TLV header from topology embedded blop +blob8 = blob8(9:end); + +%% Check that blob length is multiple of 32 bits +n_blob = length(blob8); +n_test = ceil(n_blob/4)*4; +if (n_blob ~= n_test) + fprintf(1, 'Error: ´Blob length %d is not multiple of 32 bits\n', ... + n_blob); + error('Failed.'); +end + +%% Write blob +sof_check_create_dir(fn); +fh = fopen(fn, 'w'); +if fh < 0 + fprintf(1, 'Error: Could not open file %s\n', fn); + error("Failed."); +end +nl = 8; +fprintf(fh, '# %s %s\n', comment, date()); +if ~isempty(howto) + fprintf(fh, '# %s\n', howto); +end +fprintf(fh, 'Object.Base.data.\"%s\" {\n', component); +fprintf(fh, '\tbytes \"\n'); +for i = 1:nl:n_blob + fprintf(fh, '\t\t'); + for j = 0:nl-1 + n = i + j; + if n < n_blob + fprintf(fh, '0x%02x,', blob8(n)); + end + if n == n_blob + fprintf(fh, '0x%02x"', blob8(n)); + end + end + fprintf(fh, '\n'); +end +fprintf(fh, '}\n'); +fclose(fh); +fprintf('Blob size %d was written to file %s\n', n_blob, fn); + +end diff --git a/tools/tune/common/sof_tplg_write.m b/tools/tune/common/sof_tplg_write.m new file mode 100644 index 000000000000..4a766583b726 --- /dev/null +++ b/tools/tune/common/sof_tplg_write.m @@ -0,0 +1,55 @@ +function sof_tplg_write(fn, blob8, name, comment, howto) + +if nargin < 4 + comment = 'Exported Control Bytes'; +end +if nargin < 5 + howto = []; +end + +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Drop the 8 bytes TLV header from topology embedded blop +blob8 = blob8(9:end); + +%% Pad blob length to multiple of four bytes +n_orig = length(blob8); +n_new = ceil(n_orig/4)*4; +blob8_new = zeros(1, n_new); +blob8_new(1:n_orig) = blob8; + +%% Write blob +sof_check_create_dir(fn); +fh = fopen(fn, 'w'); +if fh < 0 + fprintf(1, 'Error: Could not open file %s\n', fn); + error("Failed."); +end +nl = 8; +fprintf(fh, '# %s %s\n', comment, date()); +if ~isempty(howto) + fprintf(fh, '# %s\n', howto); +end +fprintf(fh, 'CONTROLBYTES_PRIV(%s_priv,\n', name); +fprintf(fh, '` bytes "'); +for i = 1:nl:n_new + if i > 1 + fprintf(fh, '` '); + end + for j = 0:nl-1 + n = i + j; + if n < n_new + fprintf(fh, '0x%02x,', blob8_new(n)); + end + if n == n_new + fprintf(fh, '0x%02x"', blob8_new(n)); + end + end + fprintf(fh, '''\n'); +end +fprintf(fh, ')\n'); +fclose(fh); +fprintf('Blob size %d was written to file %s\n', n_new, fn); + +end diff --git a/tools/tune/common/sof_ucm_blob_write.m b/tools/tune/common/sof_ucm_blob_write.m new file mode 100644 index 000000000000..22eca5ce5ac5 --- /dev/null +++ b/tools/tune/common/sof_ucm_blob_write.m @@ -0,0 +1,42 @@ +function sof_ucm_blob_write(fn, blob8) + +% Export blob to UCM2 cset-tlv binary format +% +% sof_ucm_blob_write(fn, blob) +% +% Input parameters +% fn - Filename for the blob +% blob - Vector of data with uint8 type +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2024, Intel Corporation. All rights reserved. + +%% Check that blob header is sane +sof_check_blob_header(blob8); + +%% Write blob +sof_check_create_dir(fn); +fh = fopen(fn, 'wb'); +if fh < 0 + fprintf(1, 'Error: Could not open file %s\n', fn); + error("Failed."); +end + +fwrite(fh, blob8, 'uint8'); +fclose(fh); + +%% Print as 8 bit hex +nb = length(blob8); +nl = ceil(nb/16); +for i = 1:nl + m = min(16, nb-(i-1)*16); + for j = 1:m + fprintf(1, "%02x ", blob8((i-1)*16 + j)); + end + fprintf(1, "\n"); +end + +fprintf(1, "\n"); +end diff --git a/tools/tune/dmic/dmic_batch.m b/tools/tune/dmic/dmic_batch.m new file mode 100644 index 000000000000..b2be24d53c9e --- /dev/null +++ b/tools/tune/dmic/dmic_batch.m @@ -0,0 +1,57 @@ +%% Create DMIC FIR configuration files + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2019, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +%% Generic parameters +prm.driver_abi_version = 1; +prm.duty_min = 40; +prm.duty_max = 60; +prm.fifo_a_fs = 0; +prm.fifo_a_bits = 24; +prm.fifo_b_fs = 0; +prm.fifo_b_bits = 24; +prm.number_of_pdm_controllers = 2; +prm.pdm(1).enable_mic_a = 1; +prm.pdm(1).enable_mic_b = 1; +prm.pdm(1).polarity_mic_a = 0; +prm.pdm(1).polarity_mic_b = 0; +prm.pdm(1).clk_edge = 0; +prm.pdm(1).skew = 0; +prm.pdm(2).enable_mic_a = 1; +prm.pdm(2).enable_mic_b = 1; +prm.pdm(2).polarity_mic_a = 0; +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; 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; 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.m b/tools/tune/dmic/dmic_fir.m new file mode 100644 index 000000000000..b82a3c0faafe --- /dev/null +++ b/tools/tune/dmic/dmic_fir.m @@ -0,0 +1,271 @@ +% PDM_DECIM_FIRPM +% +% [ coef, shift, used_passhz, used_stophz, used_rs, pb_ripple, sb_ripple, pass] = ... +% pdm_decim_firpm( rp, rs, passhz, stophz, fs_cic, fs_fir, max_length, linph) +% + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2019, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function [ coef, shift, used_passhz, used_stophz, used_rs, pb_ripple, sb_ripple, pass] = ... + dmic_fir( rp, rs, passhz, stophz, fs_cic, fs_fir, max_length, linph) + + +if exist('OCTAVE_VERSION', 'builtin') + error('This function runs only in Matlab'); +end + +%% Suppress iteration prints +verbose = 0; +do_plots = 0; + +%% cic5 response +f = linspace(1, fs_fir/2, 5000); +w = 2*pi*f/fs_cic; +j = sqrt(-1); +z = exp(j.*w); +m_cic = fs_cic / fs_fir; +g_cic = m_cic^5; +g_cic_db = 20*log10(g_cic); +z_cic_hi = z; +z_cic_lo = z.^(m_cic); + +hd = (1 - z_cic_lo.^(-1)).^5; +hi = (1 ./ (1 - z_cic_hi.^(-1))).^5; +h_cic = (1/g_cic) .* hi .* hd; + +%% Get firpm design spec + +[n, fv, mv, w] = filter_spec(rp, rs, passhz, stophz, fs_fir, f, h_cic, linph); +if linph + n = min(n, max_length-1); +end + +%% Iterate order and passband width +iterate = 1; +lo_ind = find(f < passhz/20); +pb_ind = find(f < passhz); +sb_ind = find(f > stophz); +pb_ripple_min = 1000; +sb_ripple_min = 1000; +pb_ripple_prev = 1000; +sb_ripple_prev = 1000; +pb_worse = 0; +sb_worse = 0; + +pass = 0; +nstep = 2; +cpb = 1.0; +csb = 1.0; +cpb_min = 0.95; +cpb_dec = 0.0005; +csb_inc = 0.0005; +rs_dec = 1; +passhz0 = passhz; +stophz0 = stophz; +used_passhz = passhz; +used_stophz = stophz; +used_rs = rs; +ni_max = 200; +rs_min = 90; + +ni = 0; +while (iterate > 0) + ni = ni + 1; + if verbose + fprintf(1, 'N=%3d, max=%3d, order=%3d, bw=%5.2f kHz, sb=%5.2f kHz, rp=%4.1f dB', ... + ni, max_length-1, n, passhz/1e3, stophz/1e3, rs); + end + b = firpm(n, fv, mv, w); + if linph == 0 + error('not supported'); + end + + % Set low frequency gain to max 0 dB + h_lo = freqz(b, 1, f(lo_ind), fs_fir); + g = 1/max(abs(h_lo)); + b = b * g; + n_taps = length(b); + n_fir = n_taps-1; + + %% Scale FIR coefficient to be close to 1.0 + max_abs_coef = max(abs(b)); + scale = 0.9999/max_abs_coef; + + % Check for amount of left shifts for coefficients / right shifts + % for data. + shift = floor(log(scale)/log(2)); + c = 2^shift; + coef = b * c; + + + %% Compute FIR response as H(z^M) + z_fir = z.^m_cic; + h_fir = b(1); + for i=2:(n_fir+1) + h_fir = h_fir + b(i).*z_fir.^(-i+1); + end + + %% Combine CIC5 and FIR response + h_decim = h_cic .* h_fir; + + %% Check passband + % If PB is met then SB should be OK as well due to weights + h_passband_db = 20*log10(abs(h_decim(pb_ind))); + h_stopband_db = 20*log10(abs(h_decim(sb_ind))); + pb_ripple = (max(h_passband_db)-min(h_passband_db))/2; + sb_ripple = max(h_stopband_db); + if verbose + fprintf(1,', rp=%4.2f, rs=%5.1f', pb_ripple, sb_ripple); + end + + if (sb_ripple < -rs) && (pb_ripple < rp) + iterate = 0; + pass = 1; + else + % Check if length can be increased or generic filter spec relaxed + if (sb_ripple < sb_ripple_min) && (pb_ripple < pb_ripple_min) + sb_ripple_min = sb_ripple; + pb_ripple_min = pb_ripple; + n_min = n; + fv_min = fv; + mv_min = mv; + w_min = w; + if verbose + fprintf(' +'); + end + end + if (n_taps + nstep < max_length + 1) && (pb_worse < 10) && (sb_worse < 10) + n = n + nstep; + else + cpb = cpb - cpb_dec; + if cpb < cpb_min + if passhz < 24e3 + cpb = cpb_min; + rs = rs - rs_dec; + if rs < rs_min + rs = rs_min; + csb = csb + csb_inc; + end + end + end + passhz = passhz0 * cpb; + used_passhz = passhz; + stophz = stophz0 * csb; + used_stophz = stophz; + used_rs = rs; + [n, fv, mv, w] = filter_spec(rp, rs, passhz, stophz, fs_fir, f, h_cic, linph); + if linph + n = min(n, max_length-1); + end + pb_ind = find(f < passhz); + sb_ind = find(f > stophz); + pb_worse = 0; + sb_worse = 0; + if verbose + fprintf(1, ' *'); + end + end + if pb_ripple > pb_ripple_prev + pb_worse = pb_worse + 1; + else + pb_worse = 0; + end + if sb_ripple > sb_ripple_prev + sb_worse = sb_worse + 1; + else + sb_worse = 0; + end + if ni > ni_max + n = n_min; + fv = fv_min; + mv = mv_min; + w = w_min; + iterate = 0; + if verbose + fprintf(1, ', Iterate stop, restore n=%d', n); + end + end + pb_ripple_prev = pb_ripple; + sb_ripple_prev = sb_ripple; + end + if verbose + fprintf(1, '\n'); + end + +end + +if do_plots + figure; + plot(f, 20*log10(abs(h_decim)), ... + f, 20*log10(abs(h_fir)), '--', f, 20*log10(abs(h_cic)), '--'); + grid on; + xlabel('Frequency (Hz)'); + ylabel('Magniture (dB)'); + legend('Combined', 'FIR', 'CIC', 'Location', 'SouthWest'); +end + +end + +function [n, fv, mv, w] = filter_spec(rp, rs, passhz, stophz, fs_fir, f, h_cic, linph) + +% Prepare for normal firpm filter design +dp0 = (10^(rp/20)-1)/(10^(rp/20)+1); +ds0 = 10^(-rs/20); +if linph + dp = dp0; + ds = ds0; +else + % See https://www.cs.tut.fi/~ts/FIR_minimumphase.pdf + den = 1 + dp0^2 - 0.5 * ds0^2; + dp = 2 * dp0 / den; + ds = 0.5 * ds0^2 / den; +end + +n_pb = 16; % Number of tilted line slopes for passband +% Make the start of equalized region high enough to have a flat band +% from DC to some kHz. It's the 1st band for firpmord(). +f_pb = linspace(passhz/20, passhz, n_pb); +% Interpolate complex CIC^5 response to this grid +h_cic_pb = interp1(f, h_cic, f_pb, 'linear'); +% Inverse response +h_seq = abs(h_cic_pb(1))./abs(h_cic_pb); +if linph == 0 + h_seq = h_seq .^2; +end + +% Specify response in bands for firpm() / remez() +% First band is from DC to 1st point (1 kHz) +f_fir_cic = [ 0 0.9999*f_pb(1) ]; +a_fir_cic = [ 1 h_seq(1) ]; % Firpm/Remez supports slopes with two points for gain +dev_cic = [ dp ]; +for n = 2:n_pb; + f_fir_cic = [ f_fir_cic f_pb(n-1) 0.9999*f_pb(n) ]; + a_fir_cic = [ a_fir_cic h_seq(n-1) h_seq(n) ]; + dev_cic(n) = dp * h_seq(n)^2; % Ripple spec relax as square of eq +end + +f_fir = f_fir_cic; +a_fir = a_fir_cic; +dev = dev_cic; + +% Append transition/stop band +f_fir = [ f_fir stophz 0.5*fs_fir]; +a_fir = [ a_fir 0 0 ]; +dev = [ dev ds ]; + +fv = 2*f_fir/fs_fir; +mv = a_fir; +a_fir_bands = 0.5*(a_fir(1:2:end)+a_fir(2:2:end)); +sb = (a_fir_bands == 0); % Find stopband +devr = dev ./ (sb + a_fir_bands); % Get relative deviation +w = max(devr)./devr; % Invert and normalize + +% Get FIR order estimate with firpmord() +[n, ~, ~, ~] = firpmord([passhz stophz], [1 0], [dp ds], fs_fir ); +n = round(0.95*n/2)*2; + +end diff --git a/tools/tune/dmic/dmic_fir_export.m b/tools/tune/dmic/dmic_fir_export.m new file mode 100644 index 000000000000..b65561ccd3f2 --- /dev/null +++ b/tools/tune/dmic/dmic_fir_export.m @@ -0,0 +1,62 @@ +% dmic_fir_export - Export FIR coefficients +% +% success=pdm_export_coef(fir, hdir) +% +% fir - fir definition struct +% hdir - directory for header files + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2019, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function success = dmic_fir_export(fir, hdir) + +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_int32_%02d_%04d_%04d_%03d_%03d.h', hdir, fir.m, pbi, sbi, rpi, rsi); +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); +fh = fopen(hfn, 'w'); + +fprintf(fh, '/* SPDX-License-Identifier: BSD-3-Clause\n'); +fprintf(fh, ' *\n'); +fprintf(fh, ' * Copyright(c) 2019 Intel Corporation. All rights reserved.\n'); +fprintf(fh, ' */\n'); +fprintf(fh, '\n'); +fprintf(fh, '#include <stdint.h>\n'); +fprintf(fh, '\n'); + +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); +success = 1; + +end + +function print_int_coef(fir, fh, vtype, vfn) + fprintf(fh, 'const %s %s[%d] = {\n', ... + vtype, vfn, fir.length); + + fprintf(fh,'\t%d', fir.coef(1)); + for n=2:fir.length + fprintf(fh, ',\n'); + fprintf(fh,'\t%d', fir.coef(n)); + end + fprintf(fh,'\n\n};'); +end + 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 <seppo.ingalsuo@linux.intel.com> + +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 <seppo.ingalsuo@linux.intel.com>\n'); + fprintf(fh, '// Jaska Uimonen <jaska.uimonen@linux.intel.com>\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 <stdint.h>\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 new file mode 100644 index 000000000000..b1192b2bffca --- /dev/null +++ b/tools/tune/dmic/dmic_init.m @@ -0,0 +1,300 @@ +% prm = dmic_init(prm) +% +% Create PDM microphones interface configuration + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2019, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> + +function prm = dmic_init(prm) + +hw.controllers = 4; +hw.bits_cic = 26; +hw.bits_fir_coef = 20; +hw.bits_fir_gain = 20; +hw.bits_fir_input = 22; +hw.bits_fir_output = 24; +hw.bits_fir_internal = 26; +hw.bits_gain_output = 22; +hw.cic_shift_right_range = [-8 4]; +hw.fir_shift_right_range = [0 8]; +hw.fir_max_length = 250; +hw.version = 1; +hw.number_of_pdm_controllers = 2; +hw.ioclk = 19.2e6; +spec.scale = 0.95; +spec.linear_phase = 1; +spec.rp = 0.1; +spec.cp = 0.4375; +spec.cs = 0.5100; +spec.rs = 95; + +if (prm.fifo_a_fs == 0) && (prm.fifo_b_fs == 0) + fprintf(1,'Error: At least one FIFO needs non-zero Fs!\n'); + return; +end + +%% Match modes +[a_clkdiv, a_mcic, a_mfir] = find_modes(prm, hw, prm.fifo_a_fs); +[b_clkdiv, b_mcic, b_mfir] = find_modes(prm, hw, prm.fifo_b_fs); +[common_clkdiv_list,common_mcic_list,a_mfir_list,b_mfir_list] = ... + match_modes(a_clkdiv, a_mcic, a_mfir, b_clkdiv, b_mcic, b_mfir); + +if isempty(common_clkdiv_list) + error('No compatible settings were found!\n'); +end + +%% Set basic configuration data +cfg = get_cfg(prm, hw); + +%% 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(cfg, hw); +prm = get_fir_config(prm, cfg, hw, spec); + +end + +%% Functions + +%% Get FIR filters +function prm = get_fir_config(prm, cfg, hw, spec) + +if prm.fifo_a_fs > 0 + 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 + 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 fir = get_fir(mfir, cfg, hw, spec) + +fs_fir = cfg.mic_clk/cfg.mcic; +fs = fs_fir/mfir; +passhz = spec.cp * fs; +stophz = spec.cs * fs; +max_length = min(hw.fir_max_length, floor(hw.ioclk/fs/2-5)); + +[ coef, shift, bw, sb, rs, got_pb, got_sb, passed] = ... + dmic_fir(spec.rp, spec.rs, passhz, stophz, cfg.mic_clk, fs_fir, max_length, spec.linear_phase); + +if passed == 0 + fprintf(1, 'Warning: Filter specification was reduced.\n'); + if (got_pb > 1) || (got_sb > -60) + error('The design is erroneous.'); + end +end + +coef32 = round(2^31 * coef); +fir.length = length(coef32); +fir.coef = coef32; +fir.shift = shift; +cp = bw/fs; +cs = sb/fs; +fir.cp = cp; +fir.cs = cs; +fir.rp = spec.rp; +fir.rs = rs; +fir.m = mfir; + +end + +%% Select one mode from possible combinations +function cfg = select_mode(common_mcic_list, a_mfir_list, b_mfir_list, common_clkdiv_list, cfg) + +cfg.mcic = 0; +cfg.mfir_a = 0; +cfg.mfir_b = 0; +cfg.clk_div = 0; + +% Order of preference for FIR decimation factors, prime numbers +% even if low value, are less preferable due to incompatibility +% with other FIR decimation factor. +mpref = [2 4 6 8 3 5 7 9 10 11 12 13 14 15]; + +% 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 ~isempty(common_mcic_list) + for mtry = mpref + idx = find(a_mfir_list == mtry); + if ~isempty(idx) + n = idx(end); + break; + end + end + cfg.mcic = common_mcic_list(n); + cfg.clk_div = common_clkdiv_list(n); + if a_mfir_list(1) > 0 + cfg.mfir_a = a_mfir_list(n); + end + if b_mfir_list(1) > 0 + cfg.mfir_b = b_mfir_list(n); + end + fprintf(1, 'clk_div=%d, cic=%d, fir_a=%d, fir_b=%d\n', ... + cfg.clk_div, cfg.mcic, cfg.mfir_a, cfg.mfir_b); +end + +end + +%% Compute CIC filter settings +function cfg = get_cic_config(cfg, hw) + +cfg.mic_clk = hw.ioclk/cfg.clk_div; +g_cic = cfg.mcic^5; +bitsneeded = floor(log(g_cic)/log(2)+1)+1; +cfg.cic_shift = bitsneeded - hw.bits_fir_input; + +if hw.bits_cic < bitsneeded + fprintf(1,'Error: Needed CIC word length is exceeded %d\n', bitsneeded); +end + +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) + fprintf(1,'Error: Limited CIC shift right from %d', cfg.cic_shift); + cfg.cic_shift = hw.cic_shift_right_range(2); +end + +% Compute how much gain is left for FIR from scaling to full scale +cfg.remain_gain_to_fir = 2^(hw.bits_fir_input-1)/(g_cic/2^cfg.cic_shift); + +end + +%% Find modes those are possible and exist in setup database +function [clkdiv, mcic, mfir] = find_modes(prm, hw, pcm_fs) + +if pcm_fs < 1 + clkdiv = 0; + mcic = 0; + mfir = 0; + return; +end +osr_min = 50; +if pcm_fs > 48e3 + osr_min = floor(3.0e6 / pcm_fs); +end +mcic_min = 5; +mcic_max = 31; % 8 bits reg but CIC gain and 26 bits implementation limits this +mfir_min = 2; +mfir_max = 15; +clkdiv_min = ceil(hw.ioclk/prm.pdmclk_max); +clkdiv_max = floor(hw.ioclk/prm.pdmclk_min); +n = 1; +clkdiv = []; +mcic = []; +mfir = []; +% Highest to lowest PDM clock, prefer best quality in range +for clkdiv_test = clkdiv_min:clkdiv_max + if clkdiv_test > 4 % Limitation in cAVS1.5-2.0 + c1 = floor(clkdiv_test/2); + c2 = clkdiv_test - c1; + du_min = 100*c1/clkdiv_test; + du_max = 100*c2/clkdiv_test; + pdmclk = hw.ioclk/clkdiv_test; + osr = round(pdmclk/pcm_fs); + % Lowest FIR decimation to highest, prefer low FIR + % decimation ratios + for mfir_test = mfir_min:osr + mcic_test = floor(osr/mfir_test); + if (abs(pcm_fs*mfir_test*mcic_test -pdmclk) < 1) ... + && (osr >= osr_min) ... + && (mcic_test >= mcic_min) ... + && (mcic_test <= mcic_max) ... + && (mfir_test <= mfir_max) ... + && (du_min >= prm.duty_min) ... + && (du_max <= prm.duty_max) + sfir = sprintf('FIR %d x %d x %dHz', ... + mcic_test, mfir_test, round(pcm_fs)); + %fprintf('Found: %s\n',sfir); + clkdiv(n) = clkdiv_test; + mcic(n) = mcic_test; + mfir(n) = mfir_test; + n=n+1; + end + end + end +end +end + + +%% Match found modes for common clkdiv and mcic, a DMIC hardware constraint +function [common_clkdiv_list,common_mcic_list,a_mfir_list,b_mfir_list] = ... + match_modes(a_clkdiv, a_mcic, a_mfir, b_clkdiv, b_mcic, b_mfir) + +if b_clkdiv == 0 + common_clkdiv_list = a_clkdiv; + common_mcic_list = a_mcic; + a_mfir_list = a_mfir; + b_mfir_list = 0; + return; +end +common_clkdiv_list = []; +common_mcic_list = []; +a_mfir_list = []; +b_mfir_list = []; +n_list = 1; +for n=1:length(a_clkdiv) + idx = find(b_clkdiv == a_clkdiv(n)); + for m=1:length(idx) + if b_mcic(idx(m)) == a_mcic(n) + common_clkdiv = a_clkdiv(n); + common_mcic = a_mcic(n); + common_clkdiv_list(n_list) = common_clkdiv; + common_mcic_list(n_list) = common_mcic; + a_mfir_list(n_list) = a_mfir(n); + b_mfir_list(n_list) = b_mfir(idx(m)); + fprintf('Option %d: div=%d, mcic=%d, mfira=%d, mfirb=%d\n', ... + n_list, common_clkdiv, common_mcic, ... + a_mfir_list(n_list), b_mfir_list(n_list)); + n_list = n_list+1; + end + end +end +end + +%% Misc blob details needed +function cfg = get_cfg(prm, hw) + +% if FIFO A or B is disabled, append a dummy blob to keep modes matching +% code happy with identical A and B request +if (prm.fifo_a_fs == 0) && (prm.fifo_b_fs == 0) + fprintf('Error: FIFO A or B need to be assigned a nonzero samplerate\n'); + return; +end + +cfg.hw_version = hw.version; + +cfg.fifo_a_fs = prm.fifo_a_fs; +cfg.fifo_b_fs = prm.fifo_b_fs; + +cfg.pdm01_provided = (prm.pdm(1).enable_mic_a | prm.pdm(1).enable_mic_b) ... + + (prm.pdm(2).enable_mic_a | prm.pdm(2).enable_mic_b)*2; +cfg.ch01_provided = (prm.fifo_a_fs > 0) + (prm.fifo_b_fs > 0)*2; + +if prm.fifo_a_fs > 0 + cfg.a_nchannels = prm.pdm(1).enable_mic_a + prm.pdm(1).enable_mic_b ... + + prm.pdm(2).enable_mic_a + prm.pdm(2).enable_mic_b; +else + cfg.a_nchannels = 0; +end +if prm.fifo_b_fs > 0 + cfg.b_nchannels = prm.pdm(1).enable_mic_a + prm.pdm(1).enable_mic_b ... + + prm.pdm(2).enable_mic_a + prm.pdm(2).enable_mic_b; +else + cfg.b_nchannels = 0; +end + +end diff --git a/tools/tune/eq/eq_align.m b/tools/tune/eq/eq_align.m deleted file mode 100644 index 71edfd632d85..000000000000 --- a/tools/tune/eq/eq_align.m +++ /dev/null @@ -1,52 +0,0 @@ -function [am, offs, p] = eq_align(f, m, f_align, m_align) - -%% [am, offs, p] = eq_align(f, m, f_align, m_align) -% -% Move by adding/subtracting an offset to frequency response -% curve to cross desired frequency and magnitude, usually 997 Hz, 0 dB -% -% Input -% f - frequencies -% m - magnitude response -% -% Output -% am - aligned magnitude resposne -% offs - offset (gain) in decibels used -% p - index of f_align in f -% - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -p = find(f < f_align, 1, 'last')+1; -offs = m_align-m(p); -am = m+offs; - -end diff --git a/tools/tune/eq/eq_alsactl_write.m b/tools/tune/eq/eq_alsactl_write.m deleted file mode 100644 index 56b798889e1c..000000000000 --- a/tools/tune/eq/eq_alsactl_write.m +++ /dev/null @@ -1,56 +0,0 @@ -function eq_alsactl_write(fn, blob8) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Write blob -fh = fopen(fn, 'w'); - -%% Pad blob length to multiple of four bytes -n_orig = length(blob8); -n_new = ceil(n_orig/4); -blob8_new = zeros(1, n_new*4); -blob8_new(1:n_orig) = blob8; - -%% Convert to 32 bit -blob32 = zeros(1, n_new, 'uint32'); -k = 2.^[0 8 16 24]; -for i=1:n_new - j = (i-1)*4; - blob32(i) = blob8_new(j+1)*k(1) + blob8_new(j+2)*k(2) ... - + blob8_new(j+3)*k(3) + blob8_new(j+4)*k(4); -end -for i=1:n_new-1 - fprintf(fh, '%ld,', blob32(i)); -end -fprintf(fh, '%ld,\n', blob32(end)); -fclose(fh); - -end diff --git a/tools/tune/eq/eq_blob_write.m b/tools/tune/eq/eq_blob_write.m deleted file mode 100644 index 95f83854ba22..000000000000 --- a/tools/tune/eq/eq_blob_write.m +++ /dev/null @@ -1,49 +0,0 @@ -function eq_blob_write(fn, blob8) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Write blob -fh = fopen(fn, 'wb'); -fwrite(fh, blob8, 'uint8'); -fclose(fh); - -%% Print as 8 bit hex -nb = length(blob8); -nl = ceil(nb/16); -for i = 1:nl - m = min(16, nb-(i-1)*16); - for j = 1:m - fprintf(1, "%02x ", blob8((i-1)*16 + j)); - end - fprintf(1, "\n"); -end - -end diff --git a/tools/tune/eq/eq_coef_quant.m b/tools/tune/eq/eq_coef_quant.m deleted file mode 100644 index e56efca3350d..000000000000 --- a/tools/tune/eq/eq_coef_quant.m +++ /dev/null @@ -1,50 +0,0 @@ -function qc = eq_coef_quant(c, bits, qf) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -scale = 2^qf; -cmax = 2^(bits-1)-1; -cmin = -2^(bits-1); -qc = int64(round(c*scale)); -idx = find(qc > cmax); -if ~isempty(idx) - fprintf('Warning: Max. value of Q format is exceeded: %d (%d)\n', ... - qc(idx(1)), cmax); - qc(idx) = cmax; -end -idx = find(qc < cmin); -if ~isempty(idx) - fprintf('Warning: Min. value of Q format is exceeded: %d (%d)\n', ... - qc(idx(1)), cmin); - qc(idx) = cmin; -end - -end diff --git a/tools/tune/eq/eq_compute.m b/tools/tune/eq/eq_compute.m deleted file mode 100644 index 57a6293c3556..000000000000 --- a/tools/tune/eq/eq_compute.m +++ /dev/null @@ -1,462 +0,0 @@ -function eq = eq_compute( eq ) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Sanity checks -if eq.enable_iir == 0 && eq.enable_fir == 0 - fprintf('Warning: Nothing to do. Please enable FIR or IIR!\n'); -end - -%% Extrapolate response to 0..fs/2, convert to logaritmic grid, and smooth -% with 1/N octave filter -eq = preprocess_responses(eq); - -%% Define target (e.g. speaker) response as parametric filter. This could also -% be numerical data interpolated to the grid. -if length(eq.parametric_target_response) > 0 - [eq.t_z, eq.t_p, eq.t_k] = eq_define_parametric_eq( ... - eq.parametric_target_response, eq.fs); - eq.t_db = eq_compute_response(eq.t_z, eq.t_p, eq.t_k, eq.f, eq.fs); -end - -if isempty(eq.t_db) - fprintf('Warning: No target response is defined.\n'); -end - -%% Align responses at some frequency and dB -[eq.m_db_s, offs] = eq_align(eq.f, eq.m_db_s, eq.f_align, eq.db_align); -eq.raw_m_db = eq.raw_m_db + offs; -eq.m_db = eq.m_db + offs; -eq.t_db = eq_align(eq.f, eq.t_db, eq.f_align, eq.db_align); - -%% Error to equalize = target - raw response, apply 1/N octave smoothing to -% soften the EQ shape -eq.err_db = eq.t_db - eq.m_db; -[eq.err_db_s, eq.logsmooth_noct] = logsmooth(eq.f, eq.err_db, eq.logsmooth_eq); - -%% Parametric IIR EQ definition -if eq.enable_iir - [eq.p_z, eq.p_p, eq.p_k] = eq_define_parametric_eq(eq.peq, eq.fs); - if max(length(eq.p_z), length(eq.p_p)) > 2*eq.iir_biquads_max - error('Maximum number of IIR biquads is exceeded'); - end -else - [eq.p_z, eq.p_p, eq.p_k] = tf2zp(1, 1); -end -[eq.iir_eq_db, eq.iir_eq_ph, eq.iir_eq_gd] = eq_compute_response(eq.p_z, ... - eq.p_p, eq.p_k, eq.f, eq.fs); - - -%% FIR EQ computation -% Find remaining responses error ater IIR for FIR to handle -if eq.fir_compensate_iir - eq.err2_db = eq.err_db_s-eq.iir_eq_db; -else - eq.err2_db = eq.err_db_s; -end - -if eq.enable_fir - [eq.t_fir_db, eq.fmin_fir, eq.fmax_fir] = ... - get_fir_target(eq.f, eq.err2_db, eq.fmin_fir, eq.fmax_fir, ... - eq.amin_fir, eq.amax_fir, eq.logsmooth_noct, eq.fir_autoband); - - if eq.fir_minph - eq.b_fir = compute_minph_fir(eq.f, eq.t_fir_db, ... - eq.fir_length, eq.fs, eq.fir_beta); - else - eq.b_fir = compute_linph_fir(eq.f, eq.t_fir_db, ... - eq.fir_length, eq.fs, eq.fir_beta); - end -else - eq.b_fir = 1; - eq.tfirdb = zeros(1,length(eq.f)); -end - -%% Update all responses -eq = eq_compute_tot_response(eq); - -%% Normalize -eq = eq_norm(eq); - -end - -function eq = preprocess_responses(eq) -%% Usually too narrow measurement without the lowest and highest frequencies -[f0, m0, gd0] = fix_response_dcnyquist_mult(eq.raw_f, eq.raw_m_db, ... - eq.raw_gd_s, eq.fs); - -%% Create dense logarithmic frequency grid, then average possible multiple -% measurements -[eq.f, eq.m_db, eq.gd_s, eq.num_responses] = map_to_logfreq_mult(f0, m0, ... - gd0, 1, eq.fs/2, eq.np_fine); - -%% Smooth response with 1/N octave filter for plotting -eq.m_db_s = logsmooth(eq.f, eq.m_db, eq.logsmooth_plot); - -if length(eq.target_m_db) > 0 - % Use target_m_db as dummy group delay, ignore other than magnitude - [f0, m0, ~] = fix_response_dcnyquist_mult(eq.target_f, ... - eq.target_m_db, [], eq.fs); - [~, eq.t_db, ~, ~] = map_to_logfreq_mult(f0, m0, [], 1, ... - eq.fs/2, eq.np_fine); -end -end - - -function [f_hz, m_db, gd_s] = fix_response_dcnyquist(f_hz0, m_db0, gd_s0, fs) -%% Append DC and Fs/2 if missing -f_hz = f_hz0; -m_db = m_db0; -gd_s = gd_s0; -if min(f_hz) > 0 - f_hz = [0 f_hz]; - m_db = [m_db(1) m_db]; % DC the same as 1st measured point - if length(gd_s) > 0 - gd_s = [gd_s(1) gd_s]; % DC the same as 1st measured point - end -end -if max(f_hz) < fs/2 - f_hz = [f_hz fs/2]; - m_db = [m_db m_db(end)]; % Fs/2 the same as last measured point - if length(gd_s) > 0 - gd_s = [gd_s gd_s(end)]; % Fs/2 the same as last measured point - end -end -end - -function [f_hz, m_db, gd_s] = fix_response_dcnyquist_mult(f_hz0, m_db0, ... - gd_s0, fs) - -if iscolumn(f_hz0) - f_hz0 = f_hz0.'; -end -if iscolumn(m_db0) - m_db0 = m_db0.'; -end -if iscolumn(gd_s0) - gd_s0 = gd_s0.'; -end - -s1 = size(f_hz0); -s2 = size(m_db0); -s3 = size(gd_s0); - -if s1(1) == 0 - error('Frequencies vector is empty'); -end -if (s1(1) ~= s2(1)) - error('There must be equal number of frequency and magnitude data'); -end -if (s1(2) ~= s2(2)) - error('There must be equal number of points in frequency, magnitude, and group delay data'); -end -if sum(s3) == 0 - gd_s0 = zeros(s2(1),s2(2)); -end -for i=1:s1(1) - [f_hz(i,:), m_db(i,:), gd_s(i,:)] = fix_response_dcnyquist(... - f_hz0(i,:), m_db0(i,:), gd_s0(i,:), fs); -end - -end - -function [f_hz, m_db, gd_s] = map_to_logfreq(f_hz0, m_db0, gd_s0, f1, f2, np) -%% Create logarithmic frequency vector and interpolate -f_hz = logspace(log10(f1),log10(f2), np); -m_db = interp1(f_hz0, m_db0, f_hz); -gd_s = interp1(f_hz0, gd_s0, f_hz); -m_db(end) = m_db(end-1); % Fix NaN in the end -gd_s(end) = gd_s(end-1); % Fix NaN in the end -end - -function [f_hz, mm_db, mgd_s, num] = map_to_logfreq_mult(f_hz0, m_db0, ... - gd_s0, f1, f2, np) - -s1 = size(f_hz0); -s2 = size(m_db0); -s3 = size(gd_s0); -if (s1(1) ~= s2(1)) - error('There must be equal number of frequency and magnitude data sets'); -end -if (s1(2) ~= s2(2)) - error('There must be equal number of points in frequency and magnitude data'); -end -num = s1(1); -if sum(s3) == 0 - gd_s0 = zeros(s2(1),s2(2)); -end -for i=1:num - [f_hz, m_db(i,:), gd_s(i,:)] = map_to_logfreq(f_hz0(i,:), ... - m_db0(i,:), gd_s0(i,:), f1, f2, np); -end - -if num > 1 - mm_db = mean(m_db); - mgd_s = mean(gd_s); -else - mm_db = m_db; - mgd_s = gd_s; -end -end - -function [ms_db, noct] = logsmooth(f, m_db, c) - -%% Create a 1/N octave smoothing filter -ind1 = find(f < 1000); -ind2 = find(f < 2000); -noct = ind2(end)-ind1(end); -n = 2*round(c*noct/2); -b_smooth = ones(1,n)*1/n; - -%% Smooth the response -tmp = filter(b_smooth, 1, m_db); -ms_db = [tmp(n/2+1:end) linspace(tmp(end), m_db(end), n/2)]; -ms_db(1:n) = ones(1,n)*ms_db(n); -end - -function [m_db, fmin_fir, fmax_fir] = get_fir_target(fhz, err2db, fmin_fir, ... - fmax_fir, amin_fir, amax_fir, noct, auto) - - -%% Find maximum in 1-6 kHz band -idx = find(fhz > 1e3, 1, 'first') - 1; -m_db = err2db - err2db(idx); -if auto - cf = [1e3 6e3]; - ind1 = find(fhz < cf(2)); - ind2 = find(fhz(ind1) > cf(1)); - ipeak = find(m_db(ind2) == max(m_db(ind2))) + ind2(1); - ind1 = find(fhz < cf(1)); - ind2 = find(m_db(ind1) > m_db(ipeak)); - if length(ind2) > 0 - fmin_fir = fhz(ind2(end)); - end - ind1 = find(fhz > cf(2)); - ind2 = find(m_db(ind1) > m_db(ipeak)) + ind1(1); - if length(ind2) > 0 - fmax_fir = fhz(ind2(1)); - end -end - -%% Find FIR target response -ind1 = find(fhz < fmin_fir); -ind2 = find(fhz > fmax_fir); -p1 = ind1(end)+1; -if length(ind2) > 0 - p2 = ind2(1)-1; -else - p2 = length(fhz); -end -m_db(ind1) = m_db(p1); -m_db(ind2) = m_db(p2); -ind = find(m_db > amax_fir); -m_db(ind) = amax_fir; -ind = find(m_db < amin_fir); -m_db(ind) = amin_fir; - -%% Smooth high frequency corner with spline -nn = round(noct/8); -x = [p2-nn p2-nn+1 p2+nn-1 p2+nn]; -if max(x) < length(m_db) - y = m_db(x); - xx = p2-nn:p2+nn; - yy = spline(x, y, xx); - m_db(p2-nn:p2+nn) = yy; -end - -%% Smooth low frequency corner with spline -nn = round(noct/8); -x = [p1-nn p1-nn+1 p1+nn-1 p1+nn]; -if min(x) > 0 - y = m_db(x); - xx = p1-nn:p1+nn; - yy = spline(x, y, xx); - m_db(p1-nn:p1+nn) = yy; -end - -end - -function b = compute_linph_fir(f_hz, m_db, taps, fs, beta) -if nargin < 5 - beta = 4; -end -if mod(taps,2) == 0 - fprintf('Warning: Even FIR length requested.\n'); -end -n_fft = 2*2^ceil(log(taps)/log(2)); -n_half = n_fft/2+1; -f_fft = linspace(0, fs/2, n_half); -m_lin = 10.^(m_db/20); -if f_hz(1) > 0 - f_hz = [0 f_hz]; - m_lin = [m_lin(1) m_lin]; -end -a_half = interp1(f_hz, m_lin, f_fft, 'linear'); -a = [a_half conj(a_half(end-1:-1:2))]; -h = real(fftshift(ifft(a))); -b0 = h(n_half-floor((taps-1)/2):n_half+floor((taps-1)/2)); -win = kaiser(length(b0), beta)'; -b = b0 .* win; -if length(b) < taps - % Append to even length - b = [b 0]; -end -end - -function b_fir = compute_minph_fir(f, m_db, fir_length, fs, beta) - -%% Design double length H^2 FIR -n = 2*fir_length+1; -m_lin2 = (10.^(m_db/20)).^2; -m_db2 = 20*log10(m_lin2); -blin = compute_linph_fir(f, m_db2, n, fs, beta); - -%% Find zeros inside unit circle -myeps = 1e-3; -hdzeros = roots(blin); -ind1 = find( abs(hdzeros) < (1-myeps) ); -minzeros = hdzeros(ind1); - -%% Find double zeros at unit circle -ind2 = find( abs(hdzeros) > (1-myeps) ); -outzeros = hdzeros(ind2); -ind3 = find( abs(outzeros) < (1+myeps) ); -circlezeros = outzeros(ind3); - -%% Get half of the unit circle zeros -if isempty(circlezeros) - %% We are fine ... -else - %% Eliminate double zeros - cangle = angle(circlezeros); - [sorted_cangle, ind] = sort(cangle); - sorted_czeros = circlezeros(ind); - pos = find(angle(sorted_czeros) > 0); - neg = find(angle(sorted_czeros) < 0); - pos_czeros = sorted_czeros(pos); - neg_czeros = sorted_czeros(neg(end:-1:1)); - h1 = []; - for i = 1:2:length(pos_czeros)-1 - x=mean(angle(pos_czeros(i:i+1))); - h1 = [h1' complex(cos(x),sin(x))]'; - end - h2 = []; - for i = 1:2:length(neg_czeros)-1; - x=mean(angle(neg_czeros(i:i+1))); - h2 = [h2' complex(cos(x),sin(x))]'; - end - halfcirclezeros = [h1' h2']'; - if length(halfcirclezeros)*2 < length(circlezeros)-0.1 - %% Replace the last zero pair - halfcirclezeros = [halfcirclezeros' complex(-1, 0)]'; - end - minzeros = [ minzeros' halfcirclezeros' ]'; -end - -%% Convert to transfer function -bmin = mypoly(minzeros); - -%% Scale peak in passhz to max m_db -hmin = freqz(bmin, 1, 512, fs); -b_fir = 10^(max(m_db)/20)*bmin/max(abs(hmin)); - -end - -function tf = mypoly( upolyroots ) - -% Sort roots to increasing angle to ensure more consistent behavior -aa = abs(angle(upolyroots)); -[sa, ind] = sort(aa); -polyroots = upolyroots(ind); - -n = length(polyroots); -n1 = 16; % do not change, hardwired to 16 code below - -if n < (2*n1+1) - % No need to split - tf = poly(polyroots); -else - % Split roots evenly to 16 poly computations - % The fist polys will rpb+1 roots and the rest - % rpb roots to compute - rpb = floor(n/n1); - rem = mod(n,n1); - i1 = zeros(1,n1); - i2 = zeros(1,n1); - i1(1) = 1; - for i = 1:n1-1; - if rem > 0 - i2(i) = i1(i)+rpb; - rem = rem-1; - else - i2(i) = i1(i)+rpb-1; - end - i1(i+1) = i2(i)+1; - end - i2(n1) = n; - tf101 = poly(polyroots(i1(1):i2(1))); - tf102 = poly(polyroots(i1(2):i2(2))); - tf103 = poly(polyroots(i1(3):i2(3))); - tf104 = poly(polyroots(i1(4):i2(4))); - tf105 = poly(polyroots(i1(5):i2(5))); - tf106 = poly(polyroots(i1(6):i2(6))); - tf107 = poly(polyroots(i1(7):i2(7))); - tf108 = poly(polyroots(i1(8):i2(8))); - tf109 = poly(polyroots(i1(9):i2(9))); - tf110 = poly(polyroots(i1(10):i2(10))); - tf111 = poly(polyroots(i1(11):i2(11))); - tf112 = poly(polyroots(i1(12):i2(12))); - tf113 = poly(polyroots(i1(13):i2(13))); - tf114 = poly(polyroots(i1(14):i2(14))); - tf115 = poly(polyroots(i1(15):i2(15))); - tf116 = poly(polyroots(i1(16):i2(16))); - % Combine coefficients with convolution - tf21 = conv(tf101, tf116); - tf22 = conv(tf102, tf115); - tf23 = conv(tf103, tf114); - tf24 = conv(tf104, tf113); - tf25 = conv(tf105, tf112); - tf26 = conv(tf106, tf111); - tf27 = conv(tf107, tf110); - tf28 = conv(tf108, tf109); - tf31 = conv(tf21, tf28); - tf32 = conv(tf22, tf27); - tf33 = conv(tf23, tf26); - tf34 = conv(tf24, tf25); - tf41 = conv(tf31, tf34); - tf42 = conv(tf32, tf33); - tf = conv(tf41, tf42); - - % Ensure the tf coefficents are real if rounding issues - tf = real(tf); -end - -end diff --git a/tools/tune/eq/eq_compute_response.m b/tools/tune/eq/eq_compute_response.m deleted file mode 100644 index e8a470466ca7..000000000000 --- a/tools/tune/eq/eq_compute_response.m +++ /dev/null @@ -1,72 +0,0 @@ -function [m, ph, gd] = eq_compute_response(z, p, k, f, fs) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -switch nargin - case 3 - b = z; % 1st arg - f = p; % 2nd arg - fs = k; % 3rd arg - h = freqz(b, 1, f, fs); - m = 20*log10(abs(h)); - ph = 180/pi*angle(h); - - if length(b) == 1 - gd = zeros(1, length(f)); - else - if exist('OCTAVE_VERSION', 'builtin') - % grpdelay() has some issue so better to not show a plot - gd = NaN * zeros(1, length(f)); - else - gd = 1/fs*grpdelay(b, 1, f, fs); - end - end - case 5 - [b, a] = zp2tf(z, p, k); - h = freqz(b, a, f, fs); - m = 20*log10(abs(h)); - ph = 180/pi*angle(h); - - if length(z) == 0 && length(p) == 0 - gd = zeros(1, length(f)); - else - if exist('OCTAVE_VERSION', 'builtin') - % grpdelay() has some issue so better to not show a plot - gd = NaN * zeros(1, length(f)); - else - gd = 1/fs*grpdelay(b, a, f, fs); - end - end - otherwise - error('Incorrect input parameters'); -end - -end diff --git a/tools/tune/eq/eq_compute_tot_response.m b/tools/tune/eq/eq_compute_tot_response.m deleted file mode 100644 index 250c3640c9ed..000000000000 --- a/tools/tune/eq/eq_compute_tot_response.m +++ /dev/null @@ -1,50 +0,0 @@ -function eq = eq_compute_tot_response(eq) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -% FIR response and combined IIR+FIR EQ -[eq.iir_eq_db, eq.iir_eq_ph, eq.iir_eq_gd] = eq_compute_response(eq.p_z, eq.p_p, eq.p_k, eq.f, eq.fs); -[eq.fir_eq_db, eq.fir_eq_ph, eq.fir_eq_gd] = eq_compute_response(eq.b_fir, eq.f, eq.fs); -eq.tot_eq_db = eq.iir_eq_db + eq.fir_eq_db; -eq.tot_eq_gd = eq.iir_eq_gd + eq.fir_eq_gd; - -% Simulated equalized result -eq.m_eqd = eq.m_db + eq.tot_eq_db; % Simulated response -eq.m_eqd_s = eq.m_db_s + eq.tot_eq_db; % Smoothed simulated response -eq.gd_eqd = eq.gd_s' + eq.tot_eq_gd; - -% Align -[eq.m_eqd_s, adjust, p] = eq_align(eq.f, eq.m_eqd_s, eq.f_align, eq.db_align); -eq.m_eqd = eq.m_eqd + adjust; -eq.m_eq_loss = eq.tot_eq_db(p); -eq.m_eqd_abs = eq.m_db_abs+eq.m_eq_loss; - -end diff --git a/tools/tune/eq/eq_defaults.m b/tools/tune/eq/eq_defaults.m deleted file mode 100644 index 771009dc5556..000000000000 --- a/tools/tune/eq/eq_defaults.m +++ /dev/null @@ -1,115 +0,0 @@ -function p = eq_defaults - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -% Misc -p.plot_figs = 0; -p.fn = 'configuration.txt'; -p.fs = 48e3; -p.f_align = 997; -p.db_align = 0; -p.logsmooth_plot = 1/3; % Smooth over 1/3 octaves -p.logsmooth_eq = 1/3; % Smooth over 1/3 octaves -p.np_fine = 5000; % 5000 point design grid - -% Parametric EQ IDs -p.PEQ_HP1 = 1; p.PEQ_HP2 = 2; p.PEQ_LP1 = 3; p.PEQ_LP2 = 4; -p.PEQ_LS1 = 5; p.PEQ_LS2 = 6; p.PEQ_HS1 = 7; p.PEQ_HS2 = 8; -p.PEQ_PN2 = 9; p.PEQ_LP4 = 10; p.PEQ_HP4 = 11; p.PEQ_LP2G = 12; -p.PEQ_HP2G = 13; p.PEQ_BP2 = 14; p.PEQ_NC2 = 15; p.PEQ_LS2G = 16; -p.PEQ_HS2G = 17; - -% FIR constraints -p.fmin_fir = 200; % -p.fmax_fir = 15e3; % -p.amax_fir = 20; -p.amin_fir = -20; -p.fir_beta = 8; -p.fir_length = 63; -p.fir_minph = 0; % 0 = linear phase, 1 = minimum phase -% Adjust fmin_fir, fmax_fir automatically for least gain loss in FIR -p.fir_autoband = 1; -p.enable_fir = 0; - -% IIR conf -p.iir_biquads_max = 8; -p.enable_iir = 0; - -% Initialize other fields those are computed later to allow use of struct -% arrays -p.raw_f = [10 100e3]; -p.raw_m_db = [0 0]; -p.raw_gd_s = []; -p.f = []; -p.m_db = []; -p.gd_s = []; -p.num_responses = 0; -p.m_db_s = []; -p.gd_s_s = []; -p.logsmooth_noct = 0; -p.t_z = []; -p.t_p = []; -p.t_k = []; -p.t_db = []; -p.m_db_abs = 0; -p.m_db_offs = 0; -p.raw_m_noalign_db = []; -p.err_db = []; -p.p_z = []; -p.p_p = []; -p.p_k = []; -p.iir_eq_db = []; -p.iir_eq_ph = []; -p.iir_eq_gd = []; -p.err2_db = []; -p.t_fir_db = []; -p.b_fir = []; -p.fir_eq_db = []; -p.fir_eq_ph = []; -p.fir_eq_gd = []; -p.tot_eq_db = []; -p.tot_eq_gd = []; -p.m_eqd = []; -p.gd_eqd = []; -p.m_eq_loss = 0; -p.m_eqd_abs = 0; -p.sim_m_db = []; -p.parametric_target_response = []; -p.target_f = [10 100e3]; -p.target_m_db = [0 0]; -p.fir_compensate_iir = 1; -p.p_fmin = 10; -p.p_fmax = 30e3; -p.name = ''; -p.norm_type = 'loudness'; % loudness/peak/1k -p.norm_offs_db = 0; - -end diff --git a/tools/tune/eq/eq_define_parametric_eq.m b/tools/tune/eq/eq_define_parametric_eq.m deleted file mode 100644 index 70a728e14c73..000000000000 --- a/tools/tune/eq/eq_define_parametric_eq.m +++ /dev/null @@ -1,395 +0,0 @@ -function [z, p, k] = eq_define_parametric_eq(peq, fs) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -% Parametric types -PEQ_HP1 = 1; PEQ_HP2 = 2; PEQ_LP1 = 3; PEQ_LP2 = 4; -PEQ_LS1 = 5; PEQ_LS2 = 6; PEQ_HS1 = 7; PEQ_HS2 = 8; -PEQ_PN2 = 9; PEQ_LP4 = 10; PEQ_HP4 = 11; PEQ_LP2G= 12; -PEQ_HP2G = 13; PEQ_BP2 = 14; PEQ_NC2 = 15; PEQ_LS2G = 16; -PEQ_HS2G = 17; - -sp = size(peq); -z = []; -p = []; -k = 1; -for i=1:sp(1) - type = peq(i,1); - f = peq(i,2); - g = peq(i,3); - Q = peq(i,4); - if f < fs/2 - a0 = []; - b0 = []; - z0 = []; - p0 = []; - k0 = []; - switch peq(i,1) - case PEQ_HP1, [z0, p0, k0] = butter(1, 2*f/fs, 'high'); - case PEQ_HP2, [z0, p0, k0] = butter(2, 2*f/fs, 'high'); - case PEQ_HP4, [z0, p0, k0] = butter(4, 2*f/fs, 'high'); - case PEQ_LP1, [z0, p0, k0] = butter(1, 2*f/fs); - case PEQ_LP2, [z0, p0, k0] = butter(2, 2*f/fs); - case PEQ_LP4, [z0, p0, k0] = butter(4, 2*f/fs); - case PEQ_LS1, [b0, a0] = low_shelf_1st(f, g, fs); - case PEQ_LS2, [b0, a0] = low_shelf_2nd(f, g, fs); - case PEQ_HS1, [b0, a0] = high_shelf_1st(f, g, fs); - case PEQ_HS2, [b0, a0] = high_shelf_2nd(f, g, fs); - case PEQ_PN2, [b0, a0] = peak_2nd(f, g, Q, fs); - case PEQ_HP2G, [b0, a0] = high_pass_2nd_reasonance(f, Q, fs); - case PEQ_LP2G, [b0, a0] = low_pass_2nd_reasonance(f, Q, fs); - case PEQ_BP2, [b0, a0] = band_pass_2nd(f, Q, fs); - case PEQ_NC2, [b0, a0] = notch_2nd(f, Q, fs); - case PEQ_LS2G, [b0, a0] = low_shelf_2nd_google(f, g, fs); - case PEQ_HS2G, [b0, a0] = high_shelf_2nd_google(f, g, fs); - otherwise - error('Unknown parametric EQ type'); - end - if length(a0) > 0 - [z0, p0, k0] = tf2zp(b0, a0); - end - if length(k0) > 0 - z = [z ; z0(:)]; - p = [p ; p0(:)]; - k = k * k0; - end - end -end -end - -function [b, a] = low_shelf_1st(fhz, gdb, fs) -zw = 2*pi*fhz; -w = wmap(zw, fs); -glin = 10^(gdb/20); -bs = [1 glin*w]; -as = [1 w]; -[b, a] = my_bilinear(bs, as, fs); -end - -function [b, a] = low_shelf_2nd(fhz, gdb, fs) -zw = 2*pi*fhz; -w = wmap(zw, fs); -glin = 10^(gdb/20); -bs = [1 w*sqrt(2*glin) glin*w^2]; -as = [1 w*sqrt(2) w^2]; -[b, a] = my_bilinear(bs, as, fs); -end - -function [b, a] = high_shelf_1st(fhz, gdb, fs) -zw = 2*pi*fhz; -w = wmap(zw, fs); -glin = 10^(gdb/20); -bs = [glin w]; -as = [1 w]; -[b, a] = my_bilinear(bs, as, fs); -end - -function [b, a] = high_shelf_2nd(fhz, gdb, fs) -zw = 2*pi*fhz; -w = wmap(zw, fs); -glin = 10^(gdb/20); -bs = [glin w*sqrt(2*glin) w^2]; -as = [1 w*sqrt(2) w^2]; -[b, a] = my_bilinear(bs, as, fs); -end - - -function [b, a] = peak_2nd(fhz, gdb, Q, fs) - % Reference http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt - A = 10^(gdb/40); % Square root of linear gain - wc = 2*pi*fhz/fs; - - if Q <= 0 - % To fix gui edge cases, comment from CRAS code: - % When Q = 0, the above formulas have problems. If we - % look at the z-transform, we can see that the limit - % as Q->0 is A^2, so set the filter that way. - b = [A * A, 0, 0] - a = [1, 0, 0]; - return; - endif - - alpha = sin(wc)/(2*Q); - b0 = 1 + alpha * A; - b1 = -2 * cos(wc); - b2 = 1 - alpha * A; - a0 = 1 + alpha / A; - a1 = -2 * cos(wc); - a2 = 1 - alpha / A; - b = [b0 / a0 b1 / a0 b2 / a0]; - a = [1 a1 / a0 a2 / a0]; -end - -function [b, a] = high_pass_2nd_reasonance(f, resonance, fs) - cutoff = f/(fs/2); - % Limit cutoff to 0 to 1. - cutoff = max(0.0, min(cutoff, 1.0)); - - if cutoff == 1 || cutoff == 0 - % When cutoff is one, the z-transform is 0. - % When cutoff is zero, we need to be careful because the above - % gives a quadratic divided by the same quadratic, with poles - % and zeros on the unit circle in the same place. When cutoff - % is zero, the z-transform is 1. - - b = [1 - cutoff, 0, 0]; - a = [1, 0, 0]; - return; - endif - - % Compute biquad coefficients for highpass filter - resonance = max(0.0, resonance); % can't go negative - g = 10.0^(0.05 * resonance); - d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); - - theta = pi * cutoff; - sn = 0.5 * d * sin(theta); - beta = 0.5 * (1 - sn) / (1 + sn); - gamma = (0.5 + beta) * cos(theta); - alpha = 0.25 * (0.5 + beta + gamma); - - b0 = 2 * alpha; - b1 = 2 * -2 * alpha; - b2 = 2 * alpha; - a1 = 2 * -gamma; - a2 = 2 * beta; - - b = [b0, b1, b2]; - a = [1.0, a1, a2]; -end - -function [b, a] = low_pass_2nd_reasonance(f, resonance, fs) - cutoff = f/(fs/2); - % Limit cutoff to 0 to 1. - cutoff = max(0.0, min(cutoff, 1.0)); - - if cutoff == 1 || cutoff == 0 - % When cutoff is 1, the z-transform is 1. - % When cutoff is zero, nothing gets through the filter, so set - % coefficients up correctly. - - b = [cutoff, 0, 0]; - a = [1, 0, 0]; - return; - endif - - % Compute biquad coefficients for lowpass filter - resonance = max(0.0, resonance); % can't go negative - g = 10.0^(0.05 * resonance); - d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); - - theta = pi * cutoff; - sn = 0.5 * d * sin(theta); - beta = 0.5 * (1 - sn) / (1 + sn); - gamma = (0.5 + beta) * cos(theta); - alpha = 0.25 * (0.5 + beta - gamma); - - b0 = 2 * alpha; - b1 = 2 * 2 * alpha; - b2 = 2 * alpha; - a1 = 2 * -gamma; - a2 = 2 * beta; - - b = [b0, b1, b2]; - a = [1.0, a1, a2]; -end - -function [b, a] = band_pass_2nd(f, Q, fs) - frequency = f/(fs/2); - % No negative frequencies allowed. - frequency = max(0.0, frequency); - - % Don't let Q go negative, which causes an unstable filter. - Q = max(0.0, Q); - - if frequency <= 0 || frequency >= 1 - % When the cutoff is zero, the z-transform approaches 0, if Q - % > 0. When both Q and cutoff are zero, the z-transform is - % pretty much undefined. What should we do in this case? - % For now, just make the filter 0. When the cutoff is 1, the - % z-transform also approaches 0. - b = [0, 0, 0]; - a = [1, 0, 0]; - return; - endif - if (Q <= 0) - % When Q = 0, the above formulas have problems. If we - % look at the z-transform, we can see that the limit - % as Q->0 is 1, so set the filter that way. - b = [1, 0, 0]; - a = [1, 0, 0]; - return; - endif - - w0 = pi * frequency; - alpha = sin(w0) / (2 * Q); - k = cos(w0); - - b0 = alpha; - b1 = 0; - b2 = -alpha; - a0 = 1 + alpha; - a1 = -2 * k; - a2 = 1 - alpha; - b = [b0 / a0 b1 / a0 b2 / a0]; - a = [1 a1 / a0 a2 / a0]; -end - -function [b, a] = notch_2nd(f, Q, fs) - frequency = f/(fs/2); - % Clip frequencies to between 0 and 1, inclusive. - frequency = max(0.0, min(frequency, 1.0)); - - % Don't let Q go negative, which causes an unstable filter. - Q = max(0.0, Q); - - if frequency <= 0 || frequency >= 1 - % When frequency is 0 or 1, the z-transform is 1. - b = [1, 0, 0]; - a = [1, 0, 0]; - return; - endif - if Q <= 0 - % When Q = 0, the above formulas have problems. If we - % look at the z-transform, we can see that the limit - % as Q->0 is 0, so set the filter that way. - b = [0, 0, 0]; - a = [1, 0, 0]; - return; - endif - - w0 = pi * frequency; - alpha = sin(w0) / (2 * Q); - k = cos(w0); - - b0 = 1; - b1 = -2 * k; - b2 = 1; - a0 = 1 + alpha; - a1 = -2 * k; - a2 = 1 - alpha; - - b = [b0 / a0 b1 / a0 b2 / a0]; - a = [1 a1 / a0 a2 / a0]; -end - -function [b, a] = low_shelf_2nd_google(f, db_gain, fs) - frequency = f/(fs/2); - % Clip frequencies to between 0 and 1, inclusive. - frequency = max(0.0, min(frequency, 1.0)); - - A = 10.0^(db_gain / 40); - - if (frequency == 1) - % The z-transform is a constant gain. - b = [A * A, 0, 0]; - a = [1, 0, 0]; - return; - endif - if (frequency <= 0) - % When frequency is 0, the z-transform is 1. - b = [1, 0, 0]; - a = [1, 0, 0]; - return; - endif - - w0 = pi * frequency; - S = 1; % filter slope (1 is max value) - alpha = 0.5 * sin(w0) * ... - sqrt((A + 1 / A) * (1 / S - 1) + 2); - k = cos(w0); - k2 = 2 * sqrt(A) * alpha; - a_plus_one = A + 1; - a_minus_one = A - 1; - - b0 = A * (a_plus_one - a_minus_one * k + k2); - b1 = 2 * A * (a_minus_one - a_plus_one * k); - b2 = A * (a_plus_one - a_minus_one * k - k2); - a0 = a_plus_one + a_minus_one * k + k2; - a1 = -2 * (a_minus_one + a_plus_one * k); - a2 = a_plus_one + a_minus_one * k - k2; - - b = [b0 / a0 b1 / a0 b2 / a0]; - a = [1 a1 / a0 a2 / a0]; -end - -function [b, a] = high_shelf_2nd_google(f, db_gain, fs) - frequency = f/(fs/2); - % Clip frequencies to between 0 and 1, inclusive. - frequency = max(0.0, min(frequency, 1.0)); - - A = 10.0^(db_gain / 40); - - if (frequency == 1) - % The z-transform is 1. - b = [1, 0, 0]; - a = [1, 0, 0]; - return; - endif - if (frequency <= 0) - % When frequency = 0, the filter is just a gain, A^2. - b = [A * A, 0, 0]; - a = [1, 0, 0]; - return; - endif - - w0 = pi * frequency; - S = 1; % filter slope (1 is max value) - alpha = 0.5 * sin(w0) * ... - sqrt((A + 1 / A) * (1 / S - 1) + 2); - k = cos(w0); - k2 = 2 * sqrt(A) * alpha; - a_plus_one = A + 1; - a_minus_one = A - 1; - - b0 = A * (a_plus_one + a_minus_one * k + k2); - b1 = -2 * A * (a_minus_one + a_plus_one * k); - b2 = A * (a_plus_one + a_minus_one * k - k2); - a0 = a_plus_one - a_minus_one * k + k2; - a1 = 2 * (a_minus_one - a_plus_one * k); - a2 = a_plus_one - a_minus_one * k - k2; - - b = [b0 / a0 b1 / a0 b2 / a0]; - a = [1 a1 / a0 a2 / a0]; -end - -function [b, a] = my_bilinear(sb, sa, fs) -if exist('OCTAVE_VERSION', 'builtin') - [b, a] = bilinear(sb, sa, 1/fs); -else - [b, a] = bilinear(sb, sa, fs); -end -end - -function sw = wmap(w, fs) -t = 1/fs; -sw = 2/t*tan(w*t/2); -end diff --git a/tools/tune/eq/eq_deploy_to_dut.m b/tools/tune/eq/eq_deploy_to_dut.m deleted file mode 100644 index f0b7961e4d2e..000000000000 --- a/tools/tune/eq/eq_deploy_to_dut.m +++ /dev/null @@ -1,27 +0,0 @@ -function status = eq_deploy_to_dut(target, temp_file) -% deploy eq over ssh to a given dut with sof-eqctl -% the end target is expected to be some sort of unix system with sof-eqctl -% already installed. The system should also have ssh keys installed to prevent -% the toolchain from logging in - -ip = target.ip; -user = target.user; -dev = target.device; -ctrl = target.control; - -if isunix() || ismac() - transfer_template = "scp %s %s@%s:/tmp/sof-eq-config.txt"; - config_template = "ssh -t %s@%s sof-eqctl -Dhw:%d -n %d -s /tmp/sof-eq-config.txt"; - transfer_command = sprintf(transfer_template, temp_file, user, ip); - config_command = sprintf(config_template, user, ip, dev, ctrl); - command = sprintf("%s && %s", transfer_command, config_command); -endif - -if ispc() - % TODO -endif - -[status, output] = system(command); -disp(output); -end - diff --git a/tools/tune/eq/eq_fir_blob_decode.m b/tools/tune/eq/eq_fir_blob_decode.m deleted file mode 100644 index a21a9592eb06..000000000000 --- a/tools/tune/eq/eq_fir_blob_decode.m +++ /dev/null @@ -1,127 +0,0 @@ -function eq = eq_fir_blob_decode(blobfn, resp_n, fs, do_plot) - -%% Decode a FIR EQ binary blob -% -% eq = eq_fir_blob_decode(blobfn, resp_n, fs, do_plot) -% -% blobfn - file name of EQ setup blob -% resp_n - index of response to decode -% fs - sample rate, optional -% do_plot - set to 1 for frequency response plot, optional -% -% Returned struct fields -% b - FIR coefficients -% a - Always returns 1 with FIR -% channels_in_config - numbers of channels in blob -% assign_response - vector of EQ indexes assigned to channels -% size - length in bytes - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 4 - do_plot = 0; -end - -if nargin < 3 - fs = 48e3; -end - -if nargin < 2 - resp_n = 0; -end - -%% Defaults -eq.b = []; -eq.a = []; -eq.channels_in_config = 0; -eq.number_of_responses = 0; -eq.assign_response = []; - -%% Read binary file -fh = fopen(blobfn, 'rb'); -blob16 = fread(fh, inf, 'int16'); -fclose(fh); - -%% Decode -abi = 16; -eq.size = blob16(abi + 1) + 65536*blob16(abi + 2); -eq.channels_in_config = blob16(abi + 3); -eq.number_of_responses = blob16(abi + 4); -reserved1 = blob16(abi + 5); -reserved2 = blob16(abi + 6); -reserved3 = blob16(abi + 7); -reserved4 = blob16(abi + 8); -reserved5 = blob16(abi + 9); -reserved6 = blob16(abi + 10); -reserved7 = blob16(abi + 11); -reserved8 = blob16(abi + 12); -eq.assign_response = blob16(abi + 13:abi + 13 + eq.channels_in_config-1); - -fprintf('Blob size = %d\n', eq.size); -fprintf('Channels in config = %d\n', eq.channels_in_config); -fprintf('Number of responses = %d\n', eq.number_of_responses); -fprintf('Assign responses ='); -for i=1:length(eq.assign_response) - fprintf(' %d', eq.assign_response(i)); -end -fprintf('\n'); - -if resp_n > eq.number_of_responses-1; - error('Request of non-available response'); -end - -n_blob_header = 12; -n_fir_header = 10; -b16 = blob16(abi + n_blob_header + eq.channels_in_config + 1:end); -j = 1; -for i=1:eq.number_of_responses - filter_length = b16(j); - output_shift = b16(j+1); - if i-1 == resp_n - bi = b16(j+n_fir_header:j+n_fir_header+filter_length-1); - eq.b = 2^(-output_shift)*double(bi)/32768; - end - j = j+filter_length+n_fir_header; -end -eq.a = 1; - -if do_plot > 0 - figure; - f = logspace(log10(10),log10(fs/2), 500); - h = freqz(eq.b, eq.a, f, fs); - semilogx(f, 20*log10(abs(h))); - axis([20 20e3 -40 20]); - grid on; - xlabel('Frequency (Hz)'); - ylabel('Amplitude (dB)'); -end - -end diff --git a/tools/tune/eq/eq_fir_blob_merge.m b/tools/tune/eq/eq_fir_blob_merge.m deleted file mode 100644 index 9efacdd74b30..000000000000 --- a/tools/tune/eq/eq_fir_blob_merge.m +++ /dev/null @@ -1,50 +0,0 @@ -function bs = eq_fir_blob_merge(channels_in_config, ... - number_of_responses_defined, assign_response, all_coefficients); - -%% Merge equalizer definition into a struct used by successive blob making -% functions. -% -% bs = eq_fir_blob_merge(channels_in_config, number_of_responses_defined, ... -% assign_response, all_coefficients); -% - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if length(assign_response) ~= channels_in_config - error("Incorrect length in EQ assign vector!"); -end - -bs.channels_in_config = channels_in_config; -bs.number_of_responses_defined = number_of_responses_defined; -bs.assign_response = assign_response; -bs.all_coefficients = all_coefficients; - -end diff --git a/tools/tune/eq/eq_fir_blob_pack.m b/tools/tune/eq/eq_fir_blob_pack.m deleted file mode 100644 index 8dbfac1dd760..000000000000 --- a/tools/tune/eq/eq_fir_blob_pack.m +++ /dev/null @@ -1,122 +0,0 @@ -function blob8 = eq_fir_blob_pack(bs, endian) - -%% Pack equalizer struct to bytes -% -% blob8 = eq_fir_blob_pack(bs, endian) -% bs - blob struct -% endian - optional, use 'little' or 'big'. Defaults to little. -% - -% SPDX-License-Identifier: BSD-3-Clause -% -% Copyright(c) 2016 Intel Corporation. All rights reserved. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -if nargin < 2 - endian = 'little'; -end - -%% Endiannes of blob -switch lower(endian) - case 'little' - sh16 = [0 -8]; - sh32 = [0 -8 -16 -24]; - case 'big' - sh16 = [-8 0]; - sh32 = [-24 -16 -8 0]; - otherwise - error('Unknown endiannes'); -end - -%% Channels count must be even -if mod(bs.channels_in_config, 2) > 0 - error("Channels # must be even"); -end - -%% Channels cound and assign vector length must be the same -if bs.channels_in_config ~= length( bs.assign_response) - bs - error("Channels # and response assign length must match"); -end - -%% Coefficients vector length must be multiple of 4 -len = length(bs.all_coefficients); -len_no_header = len - 10 * bs.number_of_responses_defined; -if mod(len_no_header, 4) > 0 - bs - error("Coefficient data vector length must be multiple of 4"); -end - -%% Header format is -% uint32_t size; -% uint16_t channels_in_config; -% uint16_t number_of_responses; -% uint32_t reserved[4]; -% int16_t data[]; - -%% Pack as 16 bits -nh16 = 12+bs.channels_in_config; -h16 = zeros(1, nh16, 'int16'); -nc16 = length(bs.all_coefficients); -nb16 = ceil((nh16+nc16)/2)*2; -h16(1) = 2 * nb16; -h16(2) = 0; -h16(3) = bs.channels_in_config; -h16(4) = bs.number_of_responses_defined; -h16(5) = 0; -h16(6) = 0; -h16(7) = 0; -h16(8) = 0; -h16(9) = 0; -h16(10) = 0; -h16(11) = 0; -h16(12) = 0; -for i=1:bs.channels_in_config - h16(12+i) = bs.assign_response(i); -end - -%% Merge header and coefficients, make even number of int16 to make it -% multiple of int32 -blob16 = zeros(1,nb16, 'int16'); -blob16(1:nh16) = h16; -blob16(nh16+1:nh16+nc16) = int16(bs.all_coefficients); - -%% Pack as 8 bits -nbytes_data = nb16 * 2; - -%% Get ABI information -[abi_bytes, nbytes_abi] = eq_get_abi(nbytes_data); - -%% Initialize uint8 array with correct size -nbytes = nbytes_abi + nbytes_data; -blob8 = zeros(1, nbytes, 'uint8'); - -%% Inset ABI header -blob8(1:nbytes_abi) = abi_bytes; -j = nbytes_abi + 1; - -%% Component data -for i = 1:length(blob16) - blob8(j:j+1) = w16b(blob16(i), sh16); - j = j+2; -end - -%% Done -fprintf('Blob size is %d bytes.\n', nbytes); - -end - -function bytes = w16b(word, sh) -bytes = uint8(zeros(1,2)); -bytes(1) = bitand(bitshift(word, sh(1)), 255); -bytes(2) = bitand(bitshift(word, sh(2)), 255); -end - -function bytes = w32b(word, sh) -bytes = uint8(zeros(1,4)); -bytes(1) = bitand(bitshift(word, sh(1)), 255); -bytes(2) = bitand(bitshift(word, sh(2)), 255); -bytes(3) = bitand(bitshift(word, sh(3)), 255); -bytes(4) = bitand(bitshift(word, sh(4)), 255); -end diff --git a/tools/tune/eq/eq_fir_blob_quant.m b/tools/tune/eq/eq_fir_blob_quant.m deleted file mode 100644 index 541d45dc1dde..000000000000 --- a/tools/tune/eq/eq_fir_blob_quant.m +++ /dev/null @@ -1,112 +0,0 @@ -function fbr = eq_fir_blob_quant(b, bits) - -%% Quantize FIR coefficients and return vector with length, -% out shift, and coefficients to be used in the setup blob. -% -% fbr = eq_fir_blob_resp(b, bits) -% b - FIR coefficients -% bits - optional number of bits, defaults to 16 -% -% fbr - vector with length, in shift, out shift, and quantized coefficients -% - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 2 - bits = 16; -end - -%% Quantize -[bq, shift] = eq_fir_quantize(b, bits); - -%% Check trailing zeros -nf = length(bq); -nz = nf; -while bq(nz) == 0 - nz = nz - 1; -end -if nz < nf - nb = nz + 1; - fprintf(1, 'Note: Filter length was reduced '); - fprintf(1, 'to %d -> %d due to trailing zeros.\n', nf, nb); - bq = bq(1:nb); -else - nb = nf; -end - -%% Make length multiple of four (optimized FIR core) -mod4 = mod(nb, 4); -if mod4 > 0 - pad = zeros(1,4-mod4); - bqp = [bq pad]; - nnew = length(bqp); - fprintf(1,'Note: Filter length was %d, padded length into %d.\n', ... - nb, nnew); -else - fprintf(1,'Note: Filter length is %d\n', nb); - nnew = nb; - bqp = bq; -end - -%% Pack data into FIR coefficient format -% int16_t length -% int16_t out_shift -% uint32_t reserved[4] -% int16_t coef[] -fbr = [nnew shift 0 0 0 0 0 0 0 0 bqp]; - -end - -function [bq, shift] = eq_fir_quantize(b, bits) - -% [bq, shift] = eq_fir_quantize(b, bits) -% -% Inputs -% b - FIR coefficients -% bits - number bits for 2s complement coefficient -% -% Outputs -% bq - quantized coefficients -% shift - shift right parameter to apply after FIR computation to -% compensate for coefficients scaling -% - -scale = 2^(bits-1); - -%% Output shift for coefficients -m = max(abs(b)); -shift = -ceil(log(m+1/scale)/log(2)); -bsr = b*2^shift; - -%% Quantize to Q1.bits-1 format, e.g. Q1.15 for 16 bits -bq = eq_coef_quant(bsr, bits, bits-1); - -end diff --git a/tools/tune/eq/eq_get_abi.m b/tools/tune/eq/eq_get_abi.m deleted file mode 100644 index f7ca049c5a6a..000000000000 --- a/tools/tune/eq/eq_get_abi.m +++ /dev/null @@ -1,28 +0,0 @@ -function [bytes, nbytes] = eq_get_abi(setsize) - -%% Return current SOF ABI header -% -% [bytes, nbytes] = eq_get_abi(setsize) -% - -% SPDX-License-Identifier: BSD-3-Clause -% -% Copyright(c) 2018 Intel Corporation. All rights reserved. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -%% Use sof-ctl to write ABI header into a file -abifn = 'eq_get_abi.bin'; -cmd = sprintf('sof-ctl -g %d -b -o %s', setsize, abifn); -system(cmd); - -%% Read file and delete it -fh = fopen(abifn, 'r'); -if fh < 0 - error("Failed to get ABI header. Is sof-ctl installed?"); -end -[bytes, nbytes] = fread(fh, inf, 'uint8'); -fclose(fh); -delete(abifn); - -end diff --git a/tools/tune/eq/eq_iir_blob_decode.m b/tools/tune/eq/eq_iir_blob_decode.m deleted file mode 100644 index 55a4ab332030..000000000000 --- a/tools/tune/eq/eq_iir_blob_decode.m +++ /dev/null @@ -1,150 +0,0 @@ -function eq = eq_iir_blob_decode(blobfn, resp_n, fs, do_plot) - -%% Decode an IIR EQ binary blob -% -% eq = eq_fir_decode_blob(blobfn, resp_n, fs, do_plot) -% -% blobfn - file name of EQ setup blob -% resp_n - index of response to decode -% fs - sample rate, optional -% do_plot - set to 1 for frequency response plot, optional -% -% Returned struct fields -% b - numerator coefficients -% a - denominator coefficients -% channels_in_config - numbers of channels in blob -% assign response - vector of EQ indexes assigned to channels -% - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 4 - do_plot = 0; -end - -if nargin < 3 - fs = 48e3; -end - -if nargin < 2 - resp_n = 0; -end - -%% Defaults -eq.b = []; -eq.a = []; -eq.channels_in_config = 0; -eq.number_of_responses = 0; -eq.assign_response = []; - -%% Read binary file -fh = fopen(blobfn, 'rb'); -blob = fread(fh, inf, 'uint32'); -fclose(fh); - -%% Decode -abi = 8; -eq.size = blob(abi + 1); -eq.channels_in_config = blob(abi + 2); -eq.number_of_responses = blob(abi + 3); -reserved1 = blob(abi + 4); -reserved2 = blob(abi + 5); -reserved3 = blob(abi + 6); -reserved4 = blob(abi + 7); -eq.assign_response = blob(abi + 8:abi + 8 + eq.channels_in_config - 1); - -fprintf('Blob size = %d\n', eq.size); -fprintf('Channels in config = %d\n', eq.channels_in_config); -fprintf('Number of responses = %d\n', eq.number_of_responses); -fprintf('Assign responses ='); -for i=1:length(eq.assign_response) - fprintf(' %d', eq.assign_response(i)); -end -fprintf('\n'); - -if resp_n > eq.number_of_responses-1; - error('Request of non-available response'); -end - -n_blob_header = 7; -n_iir_header = 6; -n_iir_section = 7; - -f = logspace(log10(10),log10(fs/2), 500); -j = abi + n_blob_header + eq.channels_in_config + 1; -eq.b = 1.0; -eq.a = 1.0; -for i=1:eq.number_of_responses - num_sections = blob(j); - section_length = num_sections * n_iir_section + n_iir_header; - if i-1 == resp_n - k = j + n_iir_header; - for j=1:num_sections - ai = signedint(blob(k+1:-1:k),32)'; - bi = signedint(blob(k+4:-1:k+2),32)'; - shifti = signedint(blob(k+5),32); - gaini = signedint(blob(k+6),16); - b0 = bi/2^30; - a0 = [1 -(ai/2^30)]; - gain = gaini/2^14; - b0 = b0 * 2^(-shifti) * gain; - if do_plot > 1 - figure; - h = freqz(b0, a0, f, fs); - semilogx(f, 20*log10(abs(h))); - ax = axis; axis([20 20e3 -40 20]); - grid on; - end - eq.b = conv(eq.b, b0); - eq.a = conv(eq.a, a0); - k = k + n_iir_section; - end - end - j = j+section_length; -end - -if do_plot > 0 - figure; - h = freqz(eq.b, eq.a, f, fs); - semilogx(f, 20*log10(abs(h))); - axis([20 20e3 -40 20]); - grid on; - xlabel('Frequency (Hz)'); - ylabel('Amplitude (dB)'); -end - -end - -function y = signedint(x, bits) -y = x; -idx = find(x > 2^(bits-1)-1); -y(idx) = x(idx)-2^bits; -end diff --git a/tools/tune/eq/eq_iir_blob_merge.m b/tools/tune/eq/eq_iir_blob_merge.m deleted file mode 100644 index 4c1eef1b99ae..000000000000 --- a/tools/tune/eq/eq_iir_blob_merge.m +++ /dev/null @@ -1,52 +0,0 @@ -function bs = eq_iir_blob_merge(channels_in_config, ... - number_of_responses_defined, ... - assign_response, ... - all_coefficients); - -%% Merge equalizer definition into a struct used by successive blob making -% functions. -% -% bs = eq_iir_blob_merge(channels_in_config, number_of_responses_defined, ... -% assign_response, all_coefficients); -% - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if length(assign_response) ~= channels_in_config - error("Assign response does not match channels count!"); -end - -bs.channels_in_config = channels_in_config; -bs.number_of_responses_defined = number_of_responses_defined; -bs.assign_response = assign_response; -bs.all_coefficients = all_coefficients; - -end diff --git a/tools/tune/eq/eq_iir_blob_pack.m b/tools/tune/eq/eq_iir_blob_pack.m deleted file mode 100644 index f5a5c94f2822..000000000000 --- a/tools/tune/eq/eq_iir_blob_pack.m +++ /dev/null @@ -1,81 +0,0 @@ -function blob8 = eq_iir_blob_pack(bs, endian) - -%% Pack equalizer struct to bytes -% -% blob8 = eq_iir_blob_pack(bs, endian) -% bs - blob struct -% endian - optional, use 'little' or 'big'. Defaults to little. -% - -% SPDX-License-Identifier: BSD-3-Clause -% -% Copyright(c) 2016 Intel Corporation. All rights reserved. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -if nargin < 2 - endian = 'little'; -end - -%% Channels count and assign vector lengths must be the same -if bs.channels_in_config ~= length( bs.assign_response) - bs - error("Channels # and response assign length must match"); -end - -%% Shift values for little/big endian -switch lower(endian) - case 'little' - sh = [0 -8 -16 -24]; - case 'big' - sh = [-24 -16 -8 0]; - otherwise - error('Unknown endiannes'); -end - -%% Pack as 8 bits, header -nbytes_head = (7+bs.channels_in_config)*4; -nbytes_coef = length(bs.all_coefficients)*4; -nbytes_data = nbytes_head + nbytes_coef; - -%% Get ABI information -[abi_bytes, nbytes_abi] = eq_get_abi(nbytes_data); - -%% Initialize correct size uint8 array -nbytes = nbytes_abi + nbytes_data; -blob8 = uint8(zeros(1,nbytes)); - -%% Insert ABI header -blob8(1:nbytes_abi) = abi_bytes; -j = nbytes_abi + 1; - -%% Component data -blob8(j:j+3) = w2b(nbytes_data, sh); j=j+4; -blob8(j:j+3) = w2b(bs.channels_in_config, sh); j=j+4; -blob8(j:j+3) = w2b(bs.number_of_responses_defined, sh); j=j+4; -blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved -blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved -blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved -blob8(j:j+3) = w2b(0, sh);j=j+4; % Reserved - -for i=1:bs.channels_in_config - blob8(j:j+3) = w2b(int32(bs.assign_response(i)), sh); - j=j+4; -end - -%% Pack coefficients -for i=1:length(bs.all_coefficients) - blob8(j:j+3) = w2b(int32(bs.all_coefficients(i)), sh); - j=j+4; -end -fprintf('Blob size is %d bytes.\n', nbytes); - -end - -function bytes = w2b(word, sh) -bytes = uint8(zeros(1,4)); -bytes(1) = bitand(bitshift(word, sh(1)), 255); -bytes(2) = bitand(bitshift(word, sh(2)), 255); -bytes(3) = bitand(bitshift(word, sh(3)), 255); -bytes(4) = bitand(bitshift(word, sh(4)), 255); -end diff --git a/tools/tune/eq/eq_iir_blob_quant.m b/tools/tune/eq/eq_iir_blob_quant.m deleted file mode 100644 index b3c55dadf1ce..000000000000 --- a/tools/tune/eq/eq_iir_blob_quant.m +++ /dev/null @@ -1,144 +0,0 @@ -function iir_resp = eq_iir_blob_quant(eq_z, eq_p, eq_k) - -%% Convert IIR coefficients to 2nd order sections and quantize -% -% iir_resp = eq_iir_blob_quant(z, p, k) -% -% z - zeros -% p - poles -% k - gain -% -% iir_resp - vector to setup an IIR equalizer with number of sections, shifts, -% and quantized coefficients -% - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Settings -bits_iir = 32; % Q2.30 -qf_iir = 30; -bits_gain = 16; % Q2.14 -qf_gain = 14; -scale_max = -6; % dB, scale biquads peak gain to this -plot_pz = 0; -plot_fr = 0; - -%% Convert IIR to 2nd order sections -% This a simple implementation of zp2sos() function. It is not used here due -% to utilization of rather strong scaling and resulting low SNR with the -% available word length in EQ in SOF. This poles and zeros allocation to -% biquads is base only in ascending sort of angular frequency. -sz = length(eq_z); -sp = length(eq_p); -sk = length(eq_k); -nb = max(sz, sp)/2; -az = angle(eq_z); -ap = angle(eq_p); -[~, iz] = sort(abs(az)); -[~, ip] = sort(abs(ap)); -eq_z = eq_z(iz); -eq_p = eq_p(ip); -sos = zeros(nb, 6); -for i = 1:nb - j = 2*(i-1)+1; - if i == 1 - [b, a] = zp2tf(eq_z(j:j+1), eq_p(j:j+1), eq_k); - else - [b, a] = zp2tf(eq_z(j:j+1), eq_p(j:j+1), 1); - end - sos(i,1:3) = b; - sos(i,4:6) = a; -end -gain = 1; - -%% Convert 2nd order sections to SOF parameters format and scale the biquads -% with criteria below (Gain max -6 dB at any frequency). Then calculate -% scaling shifts and finally gain multiplier for output. -sz = size(sos); -nbr_sections = sz(1); -n_section_header = 6; % Two plus reserved[4] in ABI -n_section = 7; -iir_resp = int32(zeros(1,n_section_header+nbr_sections*n_section)); -iir_resp(1) = nbr_sections; -iir_resp(2) = nbr_sections; % Note: All sections in series - -scale_max_lin = 10^(scale_max/20); -for n=1:nbr_sections - b = sos(n,1:3); - a = sos(n,4:6); - if plot_pz - figure - zplane(b,a); - tstr = sprintf('SOS %d poles and zeros', n); - title(tstr); - end - - np = 1024; - [h, w] = freqz(b, a, np); - hm = max(abs(h)); - scale = scale_max_lin/hm; - gain_remain = 1/scale; - gain = gain*gain_remain; - b = b * scale; - ma = max(abs(a)); - mb = max(abs(b)); - if plot_fr - figure - [h, w] = freqz(b, a, np); - plot(w, 20*log10(abs(h))); grid on; - xlabel('Frequency (w)'); - ylabel('Magnitude (dB)'); - tstr = sprintf('SOS %d frequency response', n); - title(tstr); - end - - %% Apply remaining gain at last section output - if n == nbr_sections - section_shift = -fix(log(gain)/log(2)); - section_gain= gain/2^(-section_shift); - else - section_shift = 0; - section_gain = 1; - end - - %% Note: Invert sign of a! - %% Note: a(1) is omitted, it's always 1 - m = n_section_header+(n-1)*n_section+1; - iir_resp(m:m+1) = eq_coef_quant(-a(3:-1:2), bits_iir, qf_iir); - iir_resp(m+2:m+4) = eq_coef_quant( b(3:-1:1), bits_iir, qf_iir); - iir_resp(m+5) = section_shift; - iir_resp(m+6) = eq_coef_quant( section_gain, bits_gain, qf_gain); - - %fprintf('sec=%d, shift=%d, gain=%f\n', n, section_shift, section_gain); - -end - -end diff --git a/tools/tune/eq/eq_load_dsp_ini.m b/tools/tune/eq/eq_load_dsp_ini.m deleted file mode 100644 index 22980ce82dff..000000000000 --- a/tools/tune/eq/eq_load_dsp_ini.m +++ /dev/null @@ -1,110 +0,0 @@ -function eq_load_dsp_ini(h, evnt) - -udata = get(h, "userdata"); -EQ = udata.EQ; -preamble_offset = 4; -config_size = 4; -n_channels = 2; -eq = eq_defaults(); - -[name, path, idx] = uigetfile("*.ini"); -if name == 0 - % cancelled - return; -endif - -% load file -f = fopen(strcat(path, name)); - -% locate eq2 section -do - l = fgets(f); -until strcmp(l, "[eq2]\n") || l == -1 - -if l == -1 - errordlg("eq2 section not found.\n Please check input file."); - return; -endif - -config = []; - -% load config -do - line = fgets(f); - if line == -1 - break; - endif - [v, count] = sscanf(line, "input_%d = %d"); - if count == 2 - config = [config, [v(1); v(2)]]; - endif -until strcmp("\n", line) - -fclose(f); - -% push config to GUI - -% set all fields to off, we will run the callback at the end to avoid graphics flicker -for channel = 1:2 - for i = 1:8 - enable_switch = EQ(i, channel).enable_switch; - set(enable_switch, "value", 0); - endfor -endfor - - % cras type (+1 since its 0 index); sof type -cras_filter2sof_filter = [ ... - -1, ... % none - eq.PEQ_LP2G, ... - eq.PEQ_HP2G, ... - eq.PEQ_BP2, ... - eq.PEQ_LS2G, ... - eq.PEQ_HS2G, ... - eq.PEQ_PN2, ... - eq.PEQ_NC2, ... - -1, ... % allpass, not implemented in audio-tuning or in SOF -]; - -config_item2field_name = { - "type", - "freq", - "Q", - "gain", -}; - -for r = config - index = r(1) - preamble_offset; - config_index = idivide(index, config_size * n_channels, "floor") + 1; - config_item = rem(index, config_size) + 1; - channel = rem(idivide(index, config_size, "floor"), n_channels) + 1; - field_name = config_item2field_name{config_item}; - filter = EQ(config_index, channel); - section = getfield(filter, field_name); - - if strcmp(field_name, "type") && cras_filter2sof_filter(r(2) + 1) == -1 - % invalid filter, skip - continue; - endif - - if strcmp(field_name, "type") - % no need to run this callback since it will get called when we run the - % enable_switch callback at the end - set(section.dropdown, "value", cras_filter2sof_filter(r(2) + 1)); - set(filter.enable_switch, "value", 1); - else - set(section.edit, "string", num2str(r(2))); - % run callback to update slider value - func = get(section.edit, "callback"); - func(section.edit, 0); - endif -endfor - -% now that all values are set lets update eveyone's visibility -for channel = 1:2 - for i = 1:8 - enable_switch = EQ(i, channel).enable_switch; - func = get(enable_switch, "callback"); - func(enable_switch, 0); - endfor -endfor -end diff --git a/tools/tune/eq/eq_norm.m b/tools/tune/eq/eq_norm.m deleted file mode 100644 index 47b40d9a5fca..000000000000 --- a/tools/tune/eq/eq_norm.m +++ /dev/null @@ -1,114 +0,0 @@ -function eq = eq_norm(eq) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Normalize loudness of EQ by computing weighted average of linear -% response. Find scale need to make the average one. -w_lin = level_norm_fweight(eq.f); -m_lin_fir = 10.^(eq.fir_eq_db/20); -m_lin_iir = 10.^(eq.iir_eq_db/20); -i1k = find(eq.f > 1e3, 1, 'first') - 1; -m_max_fir = max(eq.fir_eq_db); -m_max_iir = max(eq.iir_eq_db); -sens_fir = sum(m_lin_fir.*w_lin)/sum(w_lin); -sens_iir = sum(m_lin_iir.*w_lin)/sum(w_lin); -g_offs = 10^(eq.norm_offs_db/20); - -%% Determine scaling gain -switch lower(eq.norm_type) - case 'loudness' - g_fir = 1/sens_fir; - g_iir = 1/sens_iir; - case '1k' - g_fir = 1/m_lin_fir(i1k); - g_iir = 1/m_lin_iir(i1k); - - case 'peak' - g_fir = 10^(-m_max_fir/20); - g_iir = 10^(-m_max_iir/20); - otherwise - error('Requested normalization is not supported'); -end - -%% Adjust FIR and IIR gains if enabled -if eq.enable_fir && eq.enable_iir - eq.b_fir = eq.b_fir * g_fir * g_offs; - eq.p_k = eq.p_k * g_iir * g_offs; -end -if eq.enable_fir && eq.enable_iir == 0 - eq.b_fir = eq.b_fir * g_fir * g_offs; -end -if eq.enable_fir == 0 && eq.enable_iir - eq.p_k = eq.p_k * g_iir * g_offs; -end - -%% Re-compute response after adjusting gain -eq = eq_compute_tot_response(eq); - -end - -function m_lin = level_norm_fweight(f) - -%% w_lin = level_norm_fweight(f) -% -% Provides frequency weight that is useful in normalization of -% loudness of effect like equalizers. The weight consists of pink noise -% like spectral shape that attenuates higher frequencies 3 dB per -% octave. The low frequencies are shaped by 2nd order high-pass -% response at 20 Hz and higher frequencies by 3rd order low-pass at 20 -% kHz. -% -% Note: This weight may have similarity with a standard defined test signal -% characteristic for evaluating music player output levels but this is not -% an implementation of it. This weight may help in avoiding a designed EQ to -% exceed safe playback levels in othervise compliant device. -% -% Input f - frequencies vector in Hz -% -% Output w_lin - weight curve, aligned to peak of 1.0 in the requested f -% - -[z_hp, p_hp] = butter(2, 22.4,'high','s'); -[z_lp, p_lp] = butter(3, 22.4e3,'s'); -z_bp = conv(z_hp, z_lp); -p_bp = conv(p_hp, p_lp); -h = freqs(z_bp, p_bp, f); -m0 = 20*log10(abs(h)); -noct = log(max(f)/min(f))/log(2); -att = 3*noct; -nf = length(f); -w = zeros(1,nf); -w = w - linspace(0,att,nf); -m = m0 + w; -m = m-max(m); -m_lin = 10.^(m/20); - -end diff --git a/tools/tune/eq/eq_plot.m b/tools/tune/eq/eq_plot.m deleted file mode 100644 index b826af721e68..000000000000 --- a/tools/tune/eq/eq_plot.m +++ /dev/null @@ -1,178 +0,0 @@ -function eq_plot(eq, fn) - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 2 - fn = 1; -end - -%% Raw measured response -if length(eq.raw_m_db) > 2 - % Raw without EQ - fh=figure(fn); fn = fn+1; - f1 = min(eq.raw_f); - f2 = max(eq.raw_f); - i1 = find(eq.f > f1, 1, 'first') - 1; - i2 = find(eq.f > f2, 1, 'first') - 1; - idx = i1:i2; - semilogx(eq.f(idx), eq.m_db(idx), eq.f(idx), eq.m_db_s(idx)); - grid on; - ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 20)]); - legend('Raw','Smoothed'); - xlabel('Frequency (Hz)'); - ylabel('Magnitude (dB)'); - tstr = sprintf('Imported frequency response: %s', eq.name); - title(tstr); - - % Simulated with EQ - fh=figure(fn); fn = fn+1; - semilogx(eq.f(idx), eq.m_eqd(idx), eq.f(idx), eq.m_eqd_s(idx)); - grid on; - ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 20)]); - legend('Raw','Smoothed'); - xlabel('Frequency (Hz)'); - ylabel('Magnitude (dB)'); - tstr = sprintf('Simulated frequency response: %s', eq.name); - title(tstr); -end - -%% Filter responses -fh=figure(fn); fn = fn+1; -i1k = find(eq.f > 1e3, 1, 'first') - 1; -offs_tot = -eq.tot_eq_db(i1k); -offs_fir = -eq.fir_eq_db(i1k); -offs_iir = -eq.iir_eq_db(i1k); -if eq.enable_fir && eq.enable_iir - semilogx(eq.f, eq.err_db_s, eq.f, eq.tot_eq_db + offs_tot, ... - eq.f, eq.iir_eq_db + offs_iir, '--',... - eq.f, eq.fir_eq_db + offs_fir, '--'); - legend('Target', 'Combined', 'IIR', 'FIR', 'Location', 'NorthWest'); -end -if eq.enable_fir && eq.enable_iir == 0 - semilogx(eq.f, eq.err_db_s, eq.f, eq.fir_eq_db + offs_fir); - legend('Target', 'FIR', 'Location', 'NorthWest'); -end -if eq.enable_fir == 0 && eq.enable_iir - semilogx(eq.f, eq.err_db_s, eq.f, eq.iir_eq_db + offs_iir); - legend('Target', 'IIR', 'Location', 'NorthWest'); -end -grid on; -ax=axis; axis([eq.p_fmin eq.p_fmax min(max(ax(3:4), -40), 40)]); -xlabel('Frequency (Hz)'); -ylabel('Magnitude (dB)'); -tstr = sprintf('Filter target vs. achieved response: %s', eq.name); -title(tstr); - -%% FIR filter -if length(eq.b_fir) > 1 - % Response - fh=figure(fn); fn = fn+1; - semilogx(eq.f, eq.fir_eq_db); - grid on; - xlabel('Frequency (Hz)'); - ylabel('Magnitude (dB)'); - ax = axis; axis([eq.p_fmin eq.p_fmax max(ax(3:4), -40)]); - tstr = sprintf('FIR filter absolute response: %s', eq.name); - title(tstr); - - % Impulse response / coefficients - fh=figure(fn); fn = fn+1; - stem(eq.b_fir); - grid on; - xlabel('Coefficient #'); - ylabel('Coefficient value'); - tstr = sprintf('FIR filter impulse response: %s', eq.name); - title(tstr); - -end - -%% IIR filter -if length(eq.p_z) > 1 || length(eq.p_p) > 1 - % Response - fh=figure(fn); fn = fn+1; - semilogx(eq.f, eq.iir_eq_db); - grid on; - xlabel('Frequency (Hz)'); - ylabel('Magnitude (dB)'); - ax = axis; axis([eq.p_fmin eq.p_fmax max(ax(3:4), -40)]); - tstr = sprintf('IIR filter absolute response: %s', eq.name); - title(tstr); - - % Polar - fh=figure(fn); fn = fn+1; - zplane(eq.p_z, eq.p_p); - grid on; - tstr = sprintf('IIR zeros and poles: %s', eq.name); - title(tstr); - - % Impulse - ti = 50e-3; - x = zeros(1, ti * round(eq.fs)); - x(1) = 1; - sos = zp2sos(eq.p_z, eq.p_p, eq.p_k); - y = sosfilt(sos, x); - fh=figure(fn); fn = fn+1; - t = (0:(length(x)-1)) / eq.fs; - plot(t, y); - grid on; - xlabel('Time (s)'); - ylabel('Sample value'); - tstr = sprintf('IIR filter impulse response: %s', eq.name); - title(tstr); -end - -%% Group delay -if ~exist('OCTAVE_VERSION', 'builtin') - % Skip plot if running in Octave due to incorrect result - fh=figure(fn); fn = fn+1; - if eq.enable_fir && eq.enable_iir - semilogx(eq.f, eq.tot_eq_gd * 1e3, ... - eq.f, eq.fir_eq_gd * 1e3, '--', ... - eq.f, eq.iir_eq_gd * 1e3, '--'); - legend('Combined','FIR','IIR'); - end - if eq.enable_fir && eq.enable_iir == 0 - semilogx(eq.f, eq.fir_eq_gd * 1e3); - legend('FIR'); - end - if eq.enable_fir == 0 && eq.enable_iir - semilogx(eq.f, eq.iir_eq_gd * 1e3); - legend('IIR'); - end - grid on; - xlabel('Frequency (Hz)'); - ylabel('Group delay (ms)'); - ax = axis; axis([eq.p_fmin eq.p_fmax ax(3:4)]); - tstr = sprintf('Filter group delay: %s', eq.name); - title(tstr); -end - -end diff --git a/tools/tune/eq/eq_tplg_write.m b/tools/tune/eq/eq_tplg_write.m deleted file mode 100644 index 1d9b29a244dd..000000000000 --- a/tools/tune/eq/eq_tplg_write.m +++ /dev/null @@ -1,67 +0,0 @@ -function eq_tplg_write(fn, blob8, eqtype, comment) - -%% -% Copyright (c) 2018, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 4 - comment = 'Exported EQ'; -end - -%% Pad blob length to multiple of four bytes -n_orig = length(blob8); -n_new = ceil(n_orig/4)*4; -blob8_new = zeros(1, n_new); -blob8_new(1:n_orig) = blob8; - -%% Write blob -fh = fopen(fn, 'w'); -nl = 8; -fprintf(fh, '# %s %s\n', comment, date()); -fprintf(fh, 'CONTROLBYTES_PRIV(EQ%s_priv,\n', eqtype); -fprintf(fh, '` bytes "'); -for i = 1:nl:n_new - if i > 1 - fprintf(fh, '` '); - end - for j = 0:nl-1 - n = i + j; - if n < n_new - fprintf(fh, '0x%02x,', blob8_new(n)); - end - if n == n_new - fprintf(fh, '0x%02x"', blob8_new(n)); - end - end - fprintf(fh, '''\n'); -end -fprintf(fh, ')\n'); -fclose(fh); - -end diff --git a/tools/tune/eq/example_fir_eq.m b/tools/tune/eq/example_fir_eq.m deleted file mode 100644 index fe81d52b8779..000000000000 --- a/tools/tune/eq/example_fir_eq.m +++ /dev/null @@ -1,227 +0,0 @@ -%% Design demo EQs and bundle them to parameter block - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -function example_fir_eq() - -%% Common definitions -endian = 'little'; -fs = 48e3; - -%% ------------------- -%% Example 1: Loudness -%% ------------------- -ascii_blob_fn = '../../ctl/eq_fir_loudness.txt'; -binary_blob_fn = 'example_fir_eq.blob'; -tplg_blob_fn = 'example_fir_eq.m4'; - -%% Design FIR loudness equalizer -eq_loud = loudness_fir_eq(fs); - -%% Define a passthru EQ with one tap -b_pass = 1; - -%% Quantize filter coefficients for both equalizers -bq_pass = eq_fir_blob_quant(b_pass); -bq_loud = eq_fir_blob_quant(eq_loud.b_fir); - -%% Build blob -channels_in_config = 4; % Setup max 4 channels EQ -assign_response = [1 1 1 1]; % Switch to response #1 -num_responses = 2; % Two responses pass, loud -bm = eq_fir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - [ bq_pass bq_loud ]); - -%% Pack and write file -bp = eq_fir_blob_pack(bm, endian); -eq_alsactl_write(ascii_blob_fn, bp); -eq_blob_write(binary_blob_fn, bp); -eq_tplg_write(tplg_blob_fn, bp, 'FIR'); - -%% ------------------- -%% Example 2: Mid boost -%% ------------------- -ascii_blob_fn = '../../ctl/eq_fir_mid.txt'; - -%% Define mid frequencies boost EQ -eq_mid = midboost_fir_eq(fs); - -%% Quantize filter coefficients for both equalizers -bq_pass = eq_fir_blob_quant(eq_mid.b_fir); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One response: pass -bm = eq_fir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_pass); - -%% Pack and write file -bp = eq_fir_blob_pack(bm, endian); -eq_alsactl_write(ascii_blob_fn, bp); - -%% ------------------- -%% Example 3: Flat EQ -%% ------------------- -comment = 'Flat FIR EQ'; -ascii_blob_fn = '../../ctl/eq_fir_flat.txt'; -tplg_blob_fn = '../../topology/m4/eq_fir_coef_flat.m4'; - -%% Define a passthru EQ with one tap -b_pass = 1; - -%% Quantize filter coefficients for both equalizers -bq_pass = eq_fir_blob_quant(b_pass); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One response: pass -bm = eq_fir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_pass); - -%% Pack and write file -bp = eq_fir_blob_pack(bm, endian); -eq_alsactl_write(ascii_blob_fn, bp); -eq_tplg_write(tplg_blob_fn, bp, 'FIR', comment); - -%% -------------------------- -%% Example 4: Pass-through EQ -%% -------------------------- -ascii_blob_fn = '../../ctl/eq_fir_pass.txt'; - -%% Define a passthru EQ with one tap -b_pass = 1; - -%% Quantize filter coefficients for both equalizers -bq_pass = eq_fir_blob_quant(b_pass); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [-1 -1]; % Switch to response #0 -num_responses = 1; % One response: pass -bm = eq_fir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_pass); - -%% Pack and write file -bp = eq_fir_blob_pack(bm, endian); -eq_alsactl_write(ascii_blob_fn, bp); - -end - -%% ------------------- -%% EQ design functions -%% ------------------- - -function eq = loudness_fir_eq(fs) - -%% Derived from Fletcher-Munson curves for 80 and 60 phon -f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ... - 68,72,76,81,85,90,96,102,108,114,121,128,136,144,153,162,171, ... - 182,192,204,216,229,243,257,273,289,306,324,344,364,386,409, ... - 434,460,487,516,547,580,614,651,690,731,775,821,870,922,977, ... - 1036,1098,1163,1233,1307,1385,1467,1555,1648,1747,1851,1962, ... - 2079,2203,2335,2474,2622,2779,2945,3121,3308,3505,3715,3937, ... - 4172,4421,4686,4966,5263,5577,5910,6264,6638,7035,7455,7901, ... - 8373,8873,9404,9966,10561,11193,11861,12570,13322,14118,14962, ... - 15856,16803,17808,18872,20000]; - -m = [ 0.00,-0.13,-0.27,-0.39,-0.52,-0.64,-0.77,-0.89,-1.02,-1.16, ... - -1.31,-1.46,-1.61,-1.76,-1.91,-2.07,-2.24,-2.43,-2.64,-2.85, ... - -3.04,-3.21,-3.35,-3.48,-3.62,-3.78,-3.96,-4.16,-4.35,-4.54, ... - -4.72,-4.90,-5.08,-5.26,-5.45,-5.64,-5.83,-6.02,-6.19,-6.37, ... - -6.57,-6.77,-6.98,-7.19,-7.40,-7.58,-7.76,-7.92,-8.08,-8.25, ... - -8.43,-8.60,-8.76,-8.92,-9.08,-9.23,-9.38,-9.54,-9.69,-9.84, ... - -9.97,-10.09,-10.18,-10.26,-10.33,-10.38,-10.43,-10.48,-10.54, ... - -10.61,-10.70,-10.78,-10.85,-10.91,-10.95,-10.98,-11.02, ... - -11.05,-11.07,-11.10,-11.11,-11.11,-11.10,-11.10,-11.11, ... - -11.14,-11.17,-11.20,-11.21,-11.22,-11.21,-11.20,-11.20, ... - -11.21,-11.21,-11.20,-11.17,-11.11,-11.02,-10.91,-10.78, ... - -10.63,-10.46,-10.25,-10.00,-9.72,-9.39,-9.02,-8.62,-8.19, ... - -7.73,-7.25,-6.75,-6.25,-5.75,-5.28,-4.87,-4.54,-4.33,-4.30]; - -%% Design EQ -eq = eq_defaults(); -eq.fs = fs; -eq.target_f = f; % Set EQ frequency response target: frequencies Hz -eq.target_m_db = m; % Set EQ frequency response target: magnitudues dB -eq.norm_type = 'loudness'; % Normalize criteria can be loudness/peak/1k -eq.norm_offs_db = 0; % Offset in dB to normalize - -eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one -eq.fir_beta = 4.0; % Use with care, low value can corrupt -eq.fir_length = 86; % Gives just < 292 bytes -eq.fir_autoband = 0; % Select manually frequency limits -eq.fmin_fir = 100; % Equalization starts from 100 Hz -eq.fmax_fir = 20e3; % Equalization ends at 20 kHz -eq.fir_minph = 1; % Check result carefully if 1 is used, 0 is safe -eq = eq_compute(eq); - -%% Plot -eq_plot(eq); - -end - -function eq = midboost_fir_eq(fs) - -eq = eq_defaults(); - -eq.parametric_target_response = [ ... - eq.PEQ_LS2 1200 -12 NaN ; ... - eq.PEQ_HS2 7000 -12 NaN ; ... - ]; - -%% Design EQ -eq.fs = fs; -eq.norm_type = 'peak'; % Can be loudness/peak/1k to select normalize criteria -eq.norm_offs_db = 0; % E.g. -1 would leave 1 dB headroom if used with peak - -eq.enable_fir = 1; % By default both FIR and IIR disabled, enable one -eq.fir_beta = 3.5; % Use with care, low value can corrupt -eq.fir_length = 39; % At limit of xtensa-gcc build speed -eq.fir_autoband = 0; % Select manually frequency limits -eq.fmin_fir = 100; % Equalization starts from 100 Hz -eq.fmax_fir = 20e3; % Equalization ends at 20 kHz -eq.fir_minph = 1; % If no linear phase required can test with 1 -eq = eq_compute(eq); - -%% Plot -eq_plot(eq); - -end diff --git a/tools/tune/eq/example_iir_eq.m b/tools/tune/eq/example_iir_eq.m deleted file mode 100644 index dd5fa9142908..000000000000 --- a/tools/tune/eq/example_iir_eq.m +++ /dev/null @@ -1,338 +0,0 @@ -%% Design effect EQs and bundle them to parameter block - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -function example_iir_eq() - -%% Common definitions -endian = 'little'; -fs = 48e3; - -%% ------------------- -%% Example 1: Loudness -%% ------------------- -alsa_fn = '../../ctl/eq_iir_loudness.txt'; -blob_fn = 'example_iir_eq.blob'; -tplg_fn = 'example_iir_eq.m4'; - -%% Design IIR loudness equalizer -eq_loud = loudness_iir_eq(fs); - -%% Define a passthru IIR EQ equalizer -[z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_pass = eq_iir_blob_quant(z_pass, p_pass, k_pass); -bq_loud = eq_iir_blob_quant(eq_loud.p_z, eq_loud.p_p, eq_loud.p_k); - -%% Build blob -channels_in_config = 4; % Setup max 4 channels EQ -assign_response = [1 1 1 1]; % Switch to response #1 -num_responses = 2; % Two responses: pass, loud -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - [bq_pass bq_loud]); - -%% Pack and write file -bp = eq_iir_blob_pack(bm); -eq_blob_write(blob_fn, bp); -eq_alsactl_write(alsa_fn, bp); -eq_tplg_write(tplg_fn, bp, 'IIR'); - -%% ------------------------------------ -%% Example 2: Bass boost -%% ------------------------------------ -alsa_fn = '../../ctl/eq_iir_bassboost.txt'; - -%% Design IIR bass boost equalizer -eq_bass = bassboost_iir_eq(fs); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_bass = eq_iir_blob_quant(eq_bass.p_z, eq_bass.p_p, eq_bass.p_k); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One responses: bass -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_bass); - -%% Pack and write file -bp = eq_iir_blob_pack(bm); -eq_alsactl_write(alsa_fn, bp); - -%% ------------------------------------ -%% Example 3: Band-pass -%% ------------------------------------ -alsa_fn = '../../ctl/eq_iir_bandpass.txt'; - -%% Design IIR bass boost equalizer -eq_band = bandpass_iir_eq(fs); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_band = eq_iir_blob_quant(eq_band.p_z, eq_band.p_p, eq_band.p_k); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One responses: bandpass -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_band); - -%% Pack and write file -bp = eq_iir_blob_pack(bm); -eq_alsactl_write(alsa_fn, bp); - - -%% ------------------- -%% Example 4: Flat IIR -%% ------------------- -comment = 'Flat IIR EQ, created with example_iir_eq.m'; -alsa_fn = '../../ctl/eq_iir_flat.txt'; -tplg_fn = '../../topology/m4/eq_iir_coef_flat.m4'; - -%% Define a passthru IIR EQ equalizer -[z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_pass = eq_iir_blob_quant(z_pass, p_pass, k_pass); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % One responses: pass -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_pass); - -%% Pack and write file -bp = eq_iir_blob_pack(bm); -eq_alsactl_write(alsa_fn, bp); -eq_tplg_write(tplg_fn, bp, 'IIR', comment); - -%% --------------------------- -%% Example 5: Pass-through IIR -%% ------------------------------------ -alsa_fn = '../../ctl/eq_iir_pass.txt'; - -%% Define a passthru IIR EQ equalizer -[z_pass, p_pass, k_pass] = tf2zp([1 0 0],[1 0 0]); - -%% Quantize and pack filter coefficients plus shifts etc. -bq_pass = eq_iir_blob_quant(z_pass, p_pass, k_pass); - -%% Build blob -channels_in_config = 2; % Setup max 2 channels EQ -assign_response = [-1 -1]; % Switch to passthrough -num_responses = 1; % One responses: pass -bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_pass); - -%% Pack and write file -bp = eq_iir_blob_pack(bm); -eq_alsactl_write(alsa_fn, bp); - -%% ------------------------------------ -%% Example 6: 20/30/40/50 Hz high-pass -%% ------------------------------------ - -tpath = '../../topology/m4'; -cpath = '../../ctl'; -fs_list = [16e3 48e3]; -fc_list = [20 30 40 50]; -g_list = [0 20]; -for i = 1:length(fs_list) - for j = 1:length(fc_list); - for k = 1:length(g_list); - fs = fs_list(i); - fc = fc_list(j); - g = g_list(k); - fsk = round(fs/1e3); - tplg_fn = sprintf('%s/eq_iir_coef_highpass_%dhz_%ddb_%dkhz.m4', ... - tpath, fc, g, fsk); - alsa_fn = sprintf('%s/eq_iir_highpass_%dhz_%ddb_%dkhz.txt', ... - cpath, fc, g, fsk); - comment = sprintf('%d Hz second order high-pass, gain %d dB, created with example_iir_eq.m', ... - fc, g); - tpid = sprintf('IIR_HP%dHZ%ddB%dK', fc, g, fsk); - - %% Design IIR high-pass - eq_hp = hp_iir_eq(fs, fc, 0); - - %% Quantize and pack filter coefficients plus shifts etc. - bq_hp = eq_iir_blob_quant(eq_hp.p_z, eq_hp.p_p, eq_hp.p_k); - - %% Build blob - channels_in_config = 2; % Setup max 2 channels EQ - assign_response = [0 0]; % Switch to response #0 - num_responses = 1; % One responses: hp - bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - bq_hp); - - %% Pack and write file. If there are several EQ instances need - %% to have identifier string to get correct response to each - %% instance (here _HP50HZ20dB48K) and refer to in topology. - bp = eq_iir_blob_pack(bm); - eq_tplg_write(tplg_fn, bp, tpid, comment); - eq_alsactl_write(alsa_fn, bp); - end - end -end - -end - -%% ------------------- -%% EQ design functions -%% ------------------- - -function eq = loudness_iir_eq(fs) - -%% Derived from Fletcher-Munson curves for 80 and 60 phon -f = [ 20,21,22,24,25,27,28,30,32,34,36,38,40,43,45,48,51,54,57,60,64, ... - 68,72,76,81,85,90,96,102,108,114,121,128,136,144,153,162,171, ... - 182,192,204,216,229,243,257,273,289,306,324,344,364,386,409, ... - 434,460,487,516,547,580,614,651,690,731,775,821,870,922,977, ... - 1036,1098,1163,1233,1307,1385,1467,1555,1648,1747,1851,1962, ... - 2079,2203,2335,2474,2622,2779,2945,3121,3308,3505,3715,3937, ... - 4172,4421,4686,4966,5263,5577,5910,6264,6638,7035,7455,7901, ... - 8373,8873,9404,9966,10561,11193,11861,12570,13322,14118,14962, ... - 15856,16803,17808,18872,20000]; - -m = [ 0.00,-0.13,-0.27,-0.39,-0.52,-0.64,-0.77,-0.89,-1.02,-1.16, ... - -1.31,-1.46,-1.61,-1.76,-1.91,-2.07,-2.24,-2.43,-2.64,-2.85, ... - -3.04,-3.21,-3.35,-3.48,-3.62,-3.78,-3.96,-4.16,-4.35,-4.54, ... - -4.72,-4.90,-5.08,-5.26,-5.45,-5.64,-5.83,-6.02,-6.19,-6.37, ... - -6.57,-6.77,-6.98,-7.19,-7.40,-7.58,-7.76,-7.92,-8.08,-8.25, ... - -8.43,-8.60,-8.76,-8.92,-9.08,-9.23,-9.38,-9.54,-9.69,-9.84, ... - -9.97,-10.09,-10.18,-10.26,-10.33,-10.38,-10.43,-10.48,-10.54, ... - -10.61,-10.70,-10.78,-10.85,-10.91,-10.95,-10.98,-11.02, ... - -11.05,-11.07,-11.10,-11.11,-11.11,-11.10,-11.10,-11.11, ... - -11.14,-11.17,-11.20,-11.21,-11.22,-11.21,-11.20,-11.20, ... - -11.21,-11.21,-11.20,-11.17,-11.11,-11.02,-10.91,-10.78, ... - -10.63,-10.46,-10.25,-10.00,-9.72,-9.39,-9.02,-8.62,-8.19, ... - -7.73,-7.25,-6.75,-6.25,-5.75,-5.28,-4.87,-4.54,-4.33,-4.30]; - -%% Get defaults for equalizer design -eq = eq_defaults(); -eq.fs = fs; -eq.target_f = f; -eq.target_m_db = m; -eq.enable_iir = 1; -eq.norm_type = 'loudness'; -eq.norm_offs_db = 0; - -%% Manually setup low-shelf and high shelf parametric equalizers -% -% Parametric EQs are PEQ_HP1, PEQ_HP2, PEQ_LP1, PEQ_LP2, PEQ_LS1, -% PEQ_LS2, PEQ_HS1, PEQ_HS2 = 8, PEQ_PN2, PEQ_LP4, and PEQ_HP4. -% -% Parametric EQs take as second argument the cutoff frequency in Hz -% and as second argument a dB value (or NaN when not applicable) . The -% Third argument is a Q-value (or NaN when not applicable). -eq.peq = [ ... - eq.PEQ_LS1 40 +2 NaN ; ... - eq.PEQ_LS1 80 +3 NaN ; ... - eq.PEQ_LS1 200 +3 NaN ; ... - eq.PEQ_LS1 400 +3 NaN ; ... - eq.PEQ_HS2 13000 +7 NaN ; ... - ]; - -%% Design EQ -eq = eq_compute(eq); - -%% Plot -eq_plot(eq); - -end - -function eq = hp_iir_eq(fs, fc, gain_db) - -% Get defaults for equalizer design -eq = eq_defaults(); -eq.fs = fs; -eq.enable_iir = 1; -eq.norm_type = '1k'; -eq.norm_offs_db = gain_db; - -% Design -eq.peq = [ eq.PEQ_HP2 fc NaN NaN ]; -eq = eq_compute(eq); -eq_plot(eq); - -end - -function eq = bassboost_iir_eq(fs) - -% Get defaults for equalizer design -eq = eq_defaults(); -eq.fs = fs; -eq.enable_iir = 1; -eq.norm_type = 'loudness'; -eq.norm_offs_db = 0; - -% Design -eq.peq = [ ... - eq.PEQ_HP2 30 NaN NaN ; ... - eq.PEQ_LS2 200 +10 NaN ; ... - ]; -eq = eq_compute(eq); -eq_plot(eq); - -end - -function eq = bandpass_iir_eq(fs) - -% Get defaults for equalizer design -eq = eq_defaults(); -eq.fs = fs; -eq.enable_iir = 1; -eq.norm_type = 'loudness'; -eq.norm_offs_db = 0; - -% Design EQ -eq.peq = [ ... - eq.PEQ_HP2 500 NaN NaN ; ... - eq.PEQ_LP2 5000 NaN NaN ; ... - ]; -eq = eq_compute(eq); -eq_plot(eq); - -end diff --git a/tools/tune/eq/example_spk_eq.m b/tools/tune/eq/example_spk_eq.m deleted file mode 100644 index 27c000c8915c..000000000000 --- a/tools/tune/eq/example_spk_eq.m +++ /dev/null @@ -1,155 +0,0 @@ -function example_spk_eq() - -%% Design an example speaker equalizer with the provided sample data -% This equalizer by default uses a FIR and IIR components those should be -% both in the speaker pipeline. -% -% Note that IIR should be first since the included band-pass response provides -% signal headroom. - -%% -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Get defaults for equalizer design -eq = eq_defaults(); - -%% Settings for this EQ -eq.fs = 48e3; % Default sample rate in SOF -eq.enable_fir = 1; % Try enabling and disabling FIR part -eq.enable_iir = 1; % Try enabling and disabling IIR part -eq.norm_type = 'peak'; % Scale filters to have peak at 0 dB -eq.norm_offs_db = 0; % Can be used to control gain -eq.p_fmin = 100; % With this data start plots from 100 Hz -eq.p_fmax = 20e3; % and end to 20 kHz. - -%% Get acousticial frequency response measurement data. This is -% a quite typical response for a miniature speaker. Alternatively -% the response could be read from spreadsheet column format that is -% commonly supported by audio measurement equipment. Then extract -% the frequency and magnitude columns. E.g. -% -% data = xlsread('spkr.xlsx', 1, 'A5:B78'); -% eq.raw_f = data(:,1); -% eq.raw_m_db = data(:,2); - -eq.raw_f = [ ... - 298.533, 316.232, 334.971, 354.813, 375.838, 398.106, ... - 421.699, 446.685, 473.153, 501.186, 530.887, 562.342, ... - 595.663, 630.958, 668.345, 707.946, 749.895, 794.329, ... - 841.397, 891.252, 944.062, 1000, 1059.26, 1122.02, ... - 1188.5, 1258.93, 1333.52, 1412.54, 1496.24, 1584.9, ... - 1678.81, 1778.28, 1883.65, 1995.27, 2113.49, 2238.72, ... - 2371.38, 2511.89, 2660.73, 2818.39, 2985.39, 3162.28, ... - 3349.66, 3548.14, 3758.38, 3981.08, 4216.97, 4466.84, ... - 4731.52, 5011.88, 5308.85, 5623.42, 5956.63, 6309.58, ... - 6683.45, 7079.47, 7498.95, 7943.3, 8413.97, 8912.52, ... - 9440.62, 10000, 10592.6, 11220.2, 11885, 12589.3, ... - 13335.2, 14125.4, 14962.4, 15849, 16788.1, 17782.8, ... - 18836.5, 19952.7 ... -]; - -eq.raw_m_db = [ ... - 58.1704, 60.074, 60.4541, 61.3079, 62.8198, 64.3749, ... - 65.1556, 66.512, 67.5916, 68.6344, 69.9276, 70.7658, ... - 71.1125, 72.0627, 73.5348, 75.4887, 77.3088, 79.1541, ... - 80.9627, 82.0607, 81.943, 81.2228, 81.9497, 83.1848, ... - 84.3375, 85.4993, 86.4642, 87.1179, 87.4424, 87.53, ... - 85.7425, 85.0095, 82.9405, 82.9242, 82.7327, 83.6423, ... - 83.2839, 82.4201, 84.1403, 84.6485, 83.9274, 83.3366, ... - 83.3005, 84.2598, 85.1544, 86.015, 86.6519, 87.2118, ... - 87.5498, 88.1742, 88.5215, 88.3801, 89.8762, 91.4418, ... - 93.1845, 94.3355, 95.0918, 95.0258, 94.0337, 91.1068, ... - 88.7303, 87.4853, 86.2916, 83.037, 79.8056, 78.2022, ... - 76.0341, 74.5674, 69.2288, 56.1308, 68.697, 69.687, ... - 68.0005, 64.698 ... -]; - -%% With parametric IIR EQ try to place peaking EQ at -% resonant frequencies 1.4 kHz and 7.5 kHz. The gain -% and Q values were experimented manually. Additionally -% The lowest and highest frequeciens below and above speaker -% capability are attenuated with high-pass and low-pass -% filtering. -if eq.enable_iir; - eq.peq = [ ... - eq.PEQ_HP2 100 NaN NaN; ... - eq.PEQ_PN2 1480 -7 2.0; ... - eq.PEQ_PN2 7600 -11 1.3; ... - eq.PEQ_LP2 14500 NaN NaN; ... - ]; -end - -%% With FIR EQ try to flatten frequency response within -% 1 - 13 kHz frequency band. -if eq.enable_fir - eq.fir_minph = 1; - eq.fir_beta = 4; - eq.fir_length = 63; - eq.fir_autoband = 0; - eq.fmin_fir = 900; - eq.fmax_fir = 10700; -end - -%% Design EQ -eq = eq_compute(eq); - -%% Plot -eq_plot(eq, 1); - -%% Export FIR part -channels_in_config = 2; % Identical two speakers -assign_response = [0 0]; % Switch to response #0 -num_responses = 1; % Single response -if eq.enable_fir - bq_fir = eq_fir_blob_quant(eq.b_fir); - bm_fir = eq_fir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - [ bq_fir ]); - bp_fir = eq_fir_blob_pack(bm_fir); - eq_alsactl_write('example_spk_eq_fir.txt', bp_fir); - eq_blob_write('example_spk_eq_fir.blob', bp_fir); - eq_tplg_write('example_spk_eq_fir.m4', bp_fir, 'FIR'); -end - -%% Export IIR part -if eq.enable_iir - bq_iir = eq_iir_blob_quant(eq.p_z, eq.p_p, eq.p_k); - bm_iir = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - [ bq_iir ]); - bp_iir = eq_iir_blob_pack(bm_iir); - eq_alsactl_write('example_spk_eq_iir.txt', bp_iir); - eq_blob_write('example_spk_eq_iir.blob', bp_iir); - eq_tplg_write('example_spk_eq_iir.m4', bp_iir, 'IIR'); -end - -end diff --git a/tools/tune/eq/gui.m b/tools/tune/eq/gui.m deleted file mode 100644 index 9dbc964543cb..000000000000 --- a/tools/tune/eq/gui.m +++ /dev/null @@ -1,507 +0,0 @@ -function gui() - pkg load signal; - clear; - EQ = []; - Fs = get_config().Fs; - nyquist_f = Fs/2; - fn = 1; - % create figure and panel on it - fn = figure(fn, "toolbar", "none", "menubar", "none", 'Position', [200 200 1500 700]); fn = fn + 1; - EQ_right = uipanel ("title", "EQ Right", "position", [0, 0, 1, 0.5]); - EQ_left = uipanel ("title", "EQ Left", "position", [0, 0.5, 1, 0.5]); - main_panes = [struct("pane", EQ_left); struct("pane", EQ_right)]; - - % UI panel relative position table - positions = [ - [0 0 0.25 0.5 ] - [0.25 0 0.5 0.5 ] - [0.5 0 0.75 0.5 ] - [0.75 0 1 0.5 ] - [0 0.5 0.25 1 ] - [0.25 0.5 0.5 1 ] - [0.5 0.5 0.75 1 ] - [0.75 0.5 1 1 ] - ]; - - fn = figure(fn); fn = fn + 1; - h = [0 0]; - w = [1 nyquist_f]; - n_octaves = 10; - subplot(2, 1, 1); - main_panes(1).plot = plot(log2(w), h, "linewidth", 4); - % Range set to match http://audio-tuning.appspot.com/ - axis([log2(nyquist_f / (2 ^ n_octaves)), log2(nyquist_f), -24, 18]); - grid on; - subplot(2, 1, 2); - main_panes(2).plot = plot(log2(w), h, "linewidth", 4); - % Range set to match http://audio-tuning.appspot.com/ - axis([log2(nyquist_f / (2 ^ n_octaves)), log2(nyquist_f), -24, 18]); - grid on; - % TODO add ability to switch between octaves and log(Hz) - for c = 1:2 - for i = 1:length(positions) - EQ = initialize_biquad(i, c, positions(i, 1:end), main_panes, Fs, EQ); - endfor - endfor - % octave is silly and doesn't support references so we have to re-write the - % control matrix so the callbacks have access without using globals - for c = 1:2 - for i = 1:length(positions) - update_control_elements(EQ(i, c), EQ); - endfor - endfor - fn = figure(fn, "toolbar", "none", "menubar", "none", 'Position', [200 200 300 220]); fn = fn + 1; - menu_window = struct(); - menu_window.ip_box = uicontrol( ... - "style", "edit", ... - "position", [120 190 180 30]); - menu_window.ip_label = uicontrol( ... - "style", "text", - "string", "DUT IP:", ... - "position", [0 190 120 30]); - menu_window.user_box = uicontrol( ... - "style", "edit", ... - "position", [120 160 180 30]); - menu_window.user_label = uicontrol( ... - "style", "text", - "string", "DUT User:", ... - "position", [0 160 120 30]); - menu_window.device_box = uicontrol( ... - "style", "edit", ... - "position", [120 130 180 30]); - menu_window.device_label = uicontrol( ... - "style", "text", - "string", "Device Num:", ... - "position", [0 130 120 30]); - menu_window.alsa_box = uicontrol( ... - "style", "edit", ... - "position", [120 100 180 30]); - menu_window.alsa_label = uicontrol( ... - "style", "text", - "string", "ALSA Ctl Num:", ... - "position", [0 100 120 30]); - menu_window.upload = uicontrol( ... - "style", "pushbutton", ... - 'string', 'Push config to DUT', ... - "callback", @push_config, ... - "position", [0 50 300 50], ... - "userdata", struct("menu_window", menu_window, "EQ", EQ)); - menu_window.load_dsp = uicontrol( ... - "style", "pushbutton", ... - 'string', 'Load dsp.ini', ... - "callback", @eq_load_dsp_ini, ... - "position", [0 0 300 50], ... - "userdata", struct("EQ", EQ)); -end - -function conf = get_config() - % since octave has no definitive way to have constants we are going to hack a - % struct into behaving like one - conf = struct( ... - "Fs", 48000 ... - ); -end - -function set_udata_field(h, field, value) - udata = get(h, "userdata"); - udata = setfield(udata, field, value); - set(h, "userdata", udata); -end - -function peq = build_peq(channel, EQ) - peq = []; - for i = 1:8 - biquad = EQ(i, channel); - if get(biquad.enable_switch, "value") == 1 - type = get(biquad.type.dropdown, "value"); - freq = str2num(get(biquad.freq.edit, "string")); - Q = str2double(get(biquad.Q.edit, "string")); - gain = str2double(get(biquad.gain.edit, "string")); - % dropdown maps straight to filter index - % filter only uses needed arguments, all others will be ignored - peq = [peq; type, freq, gain, Q]; - endif - endfor -end - -function update_plot(channel, main_panes, EQ) - Fs = get_config().Fs; - nyquist_f = Fs / 2; - pl = main_panes(channel).plot; - spectrum_size = 1000; - n = logspace(log10(1), log10(nyquist_f), spectrum_size); - peq = build_peq(channel, EQ); - [z p k] = eq_define_parametric_eq(peq, Fs); - % octave gets angry when you pile up poles and zeros - [num den] = zp2tf(z, p, k); - [h, w] = freqz(num,den, n, Fs); - h = 20*log10(h); - set(pl, "YData", h, "XData", log2(w)); -end - -function set_section_visibility(section, visible) - for [control, control_name] = section - set(control, "visible", visible); - endfor -end - -function dropdown_callback(h, event) - udata = get(h, "userdata"); - EQ = udata.EQ; - biquad = EQ(udata.index, udata.channel); - eq = eq_defaults(); - switch (get(h, "value")) - case eq.PEQ_HP1 - % highpass 1st order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_HP2 - % highpass 2nd order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_LP1 - % lowpass 1st order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_LP2 - % lowpass 2nd order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_LS1 - % lowshelf 1st order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "on"); - case eq.PEQ_LS2 - % lowhelf 2nd order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "on"); - case eq.PEQ_HS1 - % highshelf 1st order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "on"); - case eq.PEQ_HS2 - % highshelf 2nd order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "on"); - case eq.PEQ_PN2 - % peaking - set_section_visibility(biquad.Q, "on"); - set_section_visibility(biquad.gain, "on"); - case eq.PEQ_LP4 - % lowpass 4th order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_HP4 - % highpass 4th order - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_LP2G - % lowpass 2nd order with resonnance - set_section_visibility(biquad.Q, "on"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_HP2G - % highpass 2nd order with resonnance - set_section_visibility(biquad.Q, "on"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_BP2 - % bandpass - set_section_visibility(biquad.Q, "on"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_NC2 - % notch - set_section_visibility(biquad.Q, "on"); - set_section_visibility(biquad.gain, "off"); - case eq.PEQ_LS2G - % lowshelf, CRAS implementation - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "on"); - case eq.PEQ_HS2G - % highshelf, CRAS implementation - set_section_visibility(biquad.Q, "off"); - set_section_visibility(biquad.gain, "on"); - endswitch - update_plot(udata.channel, udata.main_panes, EQ); -end - -function enable_callback(h, event) - off = get(h, "value") == 0; - if off - visible = "off"; - else - visible = "on"; - endif - udata = get(h, "userdata"); - EQ = udata.EQ; - biquad = EQ(udata.index, udata.channel); - for [section, section_name] = biquad - if strcmp(section_name, "enable_switch") || strcmp(section_name, "pane") - continue - endif - set_section_visibility(section, visible); - endfor - if !off - dropdown_callback(biquad.type.dropdown,0); - endif - update_plot(udata.channel, udata.main_panes, EQ); -end - -function slider_callback(h, event) - udata = get(h, "userdata"); - EQ = udata.EQ; - editbox = getfield(EQ(udata.index, udata.channel), udata.prefix).edit; - val = get(h, "value"); - if udata.is_log - val = 0.1*2^val; - endif - set(editbox, "string", num2str(val)); - update_plot(udata.channel, udata.main_panes, EQ); -end - -function edit_callback(h, event) - udata = get(h, "userdata"); - EQ = udata.EQ; - slider = getfield(EQ(udata.index, udata.channel), udata.prefix).slider; - val = str2num(get(h, "string")); - if udata.is_log && val != 0 - val = log2(val/0.1); - end - set(slider, "value", val); - update_plot(udata.channel, udata.main_panes, EQ); -end - -function EQ = initialize_biquad(index, channel, position, main_panes, Fs, EQ) - nyquist_f = Fs / 2; - % this string matches the order defined in eq.PEQ_*, do not change the order - eq_strings = {"highpass 1st order", "highpass 2nd order", ... - "lowpass 1st order", "lowpass 2nd order", "lowshelf 1st order", ... - "lowshelf 2nd order", "highshelf 1st order", "highshelf 2nd order", ... - "peaking 2nd order", "lowpass 4th order", "highpass 4th order", ... - "lowpass 2nd order (Google)", "highpass 2nd order (Google)", ... - "bandpass 2nd order", "notch 2nd order", "lowshelf 2nd order (Google)", ... - "highshelf 2nd order (Google)"}; - eq = eq_defaults(); - % UI panels, we have to use absolute positioning - % - % +-------+-----------+-------+--+--+--+--+--+----------+ - % | Label | Dropdown | | | | | | | checkbox | - % +-------+-----------+-------+--+--+--+--+--+----------+ - % | Label | input box | label | slider | - % +-------+-----------+-------+-------------------------+ - % | Label | input box | label | slider | - % +-------+-----------+-------+-------------------------+ - % | Label | input box | label | slider | - % +-------+-----------+-------+-------------------------+ - - EQ(index, channel).pane = uipanel ("parent", main_panes(channel).pane, "position", position); - p = EQ(index, channel).pane; - % octave is silly and doesn't let one position controls relatively inside a uipanel - EQ(index, channel).gain.label = uicontrol( ... - "style", "text", ... - "parent", p, ... - "position", [0 10 40 30], ... - "visible", "off", ... - "string", "Gain"); - EQ(index, channel).gain.edit = uicontrol( ... - "style", "edit", ... - "parent", p, ... - "position", [40 10 90 30], ... - "string", "0", ... - "userdata", struct( ... - "index", index, ... - "channel", channel, ... - "prefix", "gain", ... - "is_log", false, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @edit_callback); - EQ(index, channel).gain.units = uicontrol( ... - "style", "text", ... - "parent", p, ... - "string", "dB", ... - "visible", "off", ... - "position", [140 10 17 30]); - EQ(index, channel).gain.slider = uicontrol( ... - "style", "slider", ... - "parent", p, ... - "position", [160 10 200 30], ... - "min", -40, ... - "max", 40, ... - "userdata", struct( - "index", index, ... - "channel", channel, ... - "prefix", "gain", ... - "is_log", false, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @slider_callback); - - EQ(index, channel).Q.label = uicontrol( ... - "style", "text", ... - "parent", p, ... - "position", [0 50 50 30], ... - "visible", "off", ... - "string", "Q"); - EQ(index, channel).Q.edit = uicontrol( ... - "style", "edit", ... - "parent", p, ... - "position", [40 50 90 30], ... - "string", "1", ... - "userdata", struct( ... - "index", index, ... - "channel", channel, ... - "prefix", "Q", ... - "is_log", true, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @edit_callback); - EQ(index, channel).Q.slider = uicontrol( ... - "style", "slider", ... - "parent", p, ... - "position", [160 50 200 30], ... - "min", 0, ... - "max", log2(1000/0.1), ... - "value", log2(1/0.1), ... - "userdata", struct( - "index", index, ... - "channel", channel, ... - "prefix", "Q", ... - "is_log", true, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @slider_callback); - - EQ(index, channel).freq.label = uicontrol( ... - "style", "text", ... - "parent", p, ... - "position", [0 90 40 30], ... - "visible", "off", ... - "string", "Freq"); - EQ(index, channel).freq.edit = uicontrol( ... - "style", "edit", ... - "parent", p, ... - "position", [40 90 90 30], ... - "string", "350", ... - "userdata", struct( ... - "index", index, ... - "channel", channel, ... - "prefix", "freq", ... - "is_log", true, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @edit_callback); - EQ(index, channel).freq.units = uicontrol( ... - "style", "text", ... - "parent", p, ... - "position", [140 90 17 30], ... - "visible", "off", ... - "string", "Hz"); - EQ(index, channel).freq.slider = uicontrol( ... - "style", "slider", ... - "parent", p, ... - "position", [160 90 200 30], ... - "min", 1, ... - "max", log2(nyquist_f/0.1), ... - "value", log2(350/0.1), ... - "userdata", struct( - "index", index, ... - "channel", channel, ... - "prefix", "freq", ... - "is_log", true, ... - "EQ", EQ, ..., - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @slider_callback); - - EQ(index, channel).type.label = uicontrol( ... - "style", "text", ... - "parent", p, ... - "position", [0 130 40 30], ... - "visible", "off", ... - "string", "Type"); - EQ(index, channel).type.dropdown = uicontrol( ... - "style", "popupmenu", ... - "parent", p, ... - "position", [40 130 240 30], ... - "string", eq_strings, ... - "value", eq.PEQ_PN2, ... - "userdata", struct( ... - "index", index, ... - "channel", channel, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "visible", "off", ... - "callback", @dropdown_callback); - EQ(index, channel).enable_switch = uicontrol( ... - "style", "checkbox", ... - "parent", p, ... - "position", [350 130 30 30], ... - "value", 0, ... - "userdata", struct( - "index", index, ... - "channel", channel, ... - "EQ", EQ, ... - "main_panes", main_panes), ... - "callback", @enable_callback); -end - -function push_config(h, evnt) - udata = get(h, "userdata"); - window = udata.menu_window; - EQ = udata.EQ; - ip = get(window.ip_box, "string"); - user = get(window.user_box, "string"); - device = str2num(get(window.device_box, "string")); - alsa_num = str2num(get(window.alsa_box, "string")); - target = struct("ip", ip, "user", user, "device", device, "control", alsa_num); - - temp_file = tempname(); - - eq_left = eq_defaults(); - eq_left.enable_iir = 1; - eq_left.peq = build_peq(1, EQ); - eq_left.norm_type = 'peak'; - eq_left.norm_offs_db = 0; - eq_left.fs = get_config().Fs; - - eq_right = eq_defaults(); - eq_right.enable_iir = 1; - eq_right.peq = build_peq(2, EQ); - eq_right.norm_type = 'peak'; - eq_right.norm_offs_db = 0; - eq_right.fs = get_config().Fs; - - eq_left = eq_compute(eq_left); - eq_right = eq_compute(eq_right); - - bq_left = eq_iir_blob_quant(eq_left.p_z, eq_left.p_p, eq_left.p_k); - bq_right = eq_iir_blob_quant(eq_right.p_z, eq_right.p_p, eq_right.p_k); - - channels_in_config = 2; - assign_response = [0 1]; - num_responses = 2; - bm = eq_iir_blob_merge(channels_in_config, ... - num_responses, ... - assign_response, ... - [bq_left bq_right]); - - bp = eq_iir_blob_pack(bm); - eq_alsactl_write(temp_file, bp); - eq_deploy_to_dut(target, temp_file); -end - -function update_control_elements(section, EQ) - set_udata_field(section.gain.edit, "EQ", EQ); - set_udata_field(section.gain.slider, "EQ", EQ); - set_udata_field(section.Q.edit, "EQ", EQ); - set_udata_field(section.Q.slider, "EQ", EQ); - set_udata_field(section.freq.edit, "EQ", EQ); - set_udata_field(section.freq.slider, "EQ", EQ); - set_udata_field(section.type.dropdown, "EQ", EQ); - set_udata_field(section.enable_switch, "EQ", EQ); -end - diff --git a/tools/tune/eq/mls_freq_resp.m b/tools/tune/eq/mls_freq_resp.m deleted file mode 100644 index b4ad8e211586..000000000000 --- a/tools/tune/eq/mls_freq_resp.m +++ /dev/null @@ -1,412 +0,0 @@ -function [f, m_db] = mls_freq_resp(id) -%% Measure frequency response with MLS test signal -% -% [f, m] = mls_freq_resp(id) -% -% Input parameters -% id - A string identifier for test case. An id 'selftest' is for special -% usage. It calculates response of filtered MLS signal and computes -% the measurement vs. known. Deviation is reported as error. It can -% be useful if the internal MLS measurement parameters are adjusted. -% -% Output parameters -% f - Frequency vector in Hz -% m - Measured magnitude responses in dB -% -% Configuration (edit these): -% mls_play_config.txt -% mls_rec_config.txt -% -% The script will return also a text CSV format file with name mls-<id>.txt. -% - -%% -% Copyright (c) 2018, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -%% Settings -np = 1024; % Number of frequency points to use -f_lo = 100; % Lower frequency limit for analysis -f_hi = 20e3; % Upper frequency limit for analysis -t_tot = 10e-3; % MLS analysis window length in s -t_mls_s = 1.0; % MLS test signal length in s -a_mls_db = -10; % MLS test signal amplitude in dB -fs = 48e3; % Sample rate in Hz -bits = 16; % Audio format to use (bits) -fmt = 'S16_LE'; % Audio format to use (ALSA) -dir = '/tmp'; % Directory for temporary files -capture_level_max_db = -1; % Expected max. level -capture_level_min_db = -30; % Expacted min. level - -%% Get device identifier to use -if nargin < 1 - id = 'unknown'; -end - -if strcmp(id, 'selftest') - selftest = 1; - % Just some simulated speaker response to use as self test case - stb = [ 0.341762453, -0.915611126, 0.482465118, ... - 1.017612317, -1.722527013, 0.711608745, ... - 0.630608859, -0.813609935, 0.267690582, ]; - sta = [ 1.000000000, -3.931695128, 6.630812276, ... - -6.339248735, 3.800407709, -1.559376698, ... - 0.619626250, -0.317702349, 0.097453451, ]; -else - selftest = 0; -end -measfn = sprintf('mls-%s.wav', id); -csvfn = sprintf('mls-%s.txt', id); - -%% Paths -addpath('../../test/audio/test_utils'); - -%% MLS -n_mls = round(fs*t_mls_s); -mls = 10^(a_mls_db/20) * (2 * mlsp12(1, n_mls) - 1); -mlsfn = 'mls-ref.wav'; -audiowrite(mlsfn, mls, fs); - -%% Chip markers and parameters for find sync -[x1, m1] = sync_chirp(fs, 'up'); -[x2, m2] = sync_chirp(fs, 'down'); -fnd.fs = fs; % Sample rate -fnd.sm = 3; % Max seek from start -fnd.em = 3; % Max seek from end -fnd.idle_t = 2; % max idle in start or end -fnd.mark_t = m1.t; % Marker length -fnd.nf = 1; % One signal (amplitude) -fnd.na = 1; % One signal (frequency) -fnd.tl = t_mls_s; % Length of signal -fnd.mt = 0.1; % Threshold length to issue error -fnd.is = 0; % Ignore from start -fnd.ie = 0; % Ignore from end - -%% Merge markers and MLS -z = zeros(n_mls + m1.n + m2.n, 1); -i1 = m1.n + 1; -i2 = m1.n + n_mls; -z(1:i1 - 1) = x1; -z(i1:i2) = mls; -z(i2 + 1:end) = x2; - -%% Get config -rec_cfg = meas_remote_rec_config(fs, fmt); -play_cfg = meas_remote_play_config; - -%% Capture MLS from all playback channel at time -mixfn = 'mlsmix.wav'; -recfn = 'recch.wav'; -y = []; -for i=1:play_cfg.nch - fprintf('\n'); - fprintf('Measure playback channel %d\n', i); - if selftest - tz =zeros(2*fs+length(z), 1); % Pad 2s - tz(fs:fs+length(z)-1) = z; - t = filter(stb, sta, tz); % Filter with test response - r = t(:) * ones(1, rec_cfg.nch); % Copy to all channels - else - x = zeros(length(z), play_cfg.nch); - x(:,i) = z; - mixdfn = sprintf('%s/%s', dir, mixfn); - audiowrite(mixdfn, x, fs, 'BitsPerSample', bits); - copy_playback(mixdfn, play_cfg); - tcap = floor(3 + t_mls_s); - remote_capture(recfn, rec_cfg, tcap); - pause(1); - remote_play(mixfn, play_cfg); - pause(3); - r = get_recording(recfn, rec_cfg); - end - [d, nt] = find_test_signal(r(:,1), fnd); - for j = 1:rec_cfg.nch - y(:, rec_cfg.nch*(i-1) + j) = r(d:d + nt -1, j); - end - m = 20*log10(max(abs(r))); - fprintf('Peak levels for capture channels (dB):'); - for j = 1:rec_cfg.nch - fprintf(' %5.1f', m(j)); - end - fprintf('\n'); - if max(m) > capture_level_max_db - fprintf('Warning: The recording level is too loud.\n'); - end - if min(m) < capture_level_min_db - fprintf('Warning: The recording level is too silent.\n'); - end - -end -audiowrite(measfn, y, fs, 'BitsPerSample', bits); -fprintf('\n'); -fprintf('Done.\n'); - -[f, m_db, b] = mls_calc_resp(csvfn, mlsfn, measfn, t_tot, np, f_lo, f_hi); - -[f, m_db] = apply_mic_calibration(f, m_db, rec_cfg); - -figure -idx = find(f>1e3, 1, 'first') - 1; -m_db_align = m_db - m_db(idx); -semilogx(f, m_db_align); -ax=axis(); axis([f_lo f_hi ax(3:4)]); -grid on; -xlabel('Frequency (Hz)'); -ylabel('Magnitude (dB)'); - -if selftest - title('Measured vs. reference response'); - h = freqz(stb, sta, f, fs); - ref_db = 20*log10(abs(h)); - ref_db_align = ref_db - ref_db(idx); - hold on; - plot(f, ref_db_align, 'r--'); - hold off; - idx = find(f < f_hi); - idx = find(f(idx) > f_lo); - m_lin = 10.^(m_db_align(idx)/20); - ref_lin = 10.^(ref_db_align(idx)/20); - err_lin = m_lin - ref_lin; - e_rms = sqrt(mean(err_lin.^2)); - e_db = 20*log10(e_rms); - figure; - semilogx(f(idx), 20*log10(abs(err_lin))) - grid on; - xlabel('Frequency (Hz)'); - ylabel('Magnitude (dB)'); - title('Observed Error in self test'); - if e_db < -30 - fprintf('Passed self test. '); - else - fprintf('Failed self test. '); - end - fprintf('Response RMS error is %4.1f dB.\n', e_db); -end - -end - -function copy_playback(fn, cfg) - if cfg.ssh - cmd = sprintf('scp %s %s:%s/', fn, cfg.user, cfg.dir); - fprintf('Remote copy: %s\n', cmd); - system(cmd); - else - %cmd = sprintf('cp %s %s/', fn, cfg.dir); - %fprintf('Local copy: %s\n', cmd); - end -end - -function y = get_recording(fn, cfg) - if cfg.ssh - cmd = sprintf('scp %s:%s/%s %s', cfg.user, cfg.dir, fn, fn); - fprintf('Remote copy: %s\n', cmd); - else - cmd = sprintf('cp %s/%s %s', cfg.dir, fn, fn); - fprintf('Local copy: %s\n', cmd); - end - system(cmd); - y = audioread(fn); - delete(fn); -end - -function remote_play(fn, cfg) - if cfg.ssh - cmd = sprintf('ssh %s aplay -D%s %s/%s', cfg.user, cfg.dev, cfg.dir, fn); - fprintf('Remote play: %s\n', cmd); - else - cmd = sprintf('aplay -D%s %s/%s', cfg.dev, cfg.dir, fn); - fprintf('Local play: %s\n', cmd); - end - system(cmd); -end - -function remote_capture(fn, cfg, t) - if cfg.ssh - cmd = sprintf('ssh %s arecord -q -D%s %s -d %d %s/%s &', ... - cfg.user, cfg.dev, cfg.fmt, t, cfg.dir, fn); - fprintf('Remote capture: %s\n', cmd); - else - cmd = sprintf('arecord -q -D%s %s -d %d %s/%s &', ... - cfg.dev, cfg.fmt, t, cfg.dir, fn); - fprintf('Local capture: %s\n', cmd); - end - system(cmd); -end - -function play = meas_remote_play_config() - source mls_play_config.txt; - fprintf('\nThe setttings for remote playback are\n'); - fprintf('Use ssh : %d\n', play.ssh); - fprintf('User : %s\n', play.user); - fprintf('Directory : %s\n', play.dir); - fprintf('Device : %s\n', play.dev); - fprintf('Channels : %d\n', play.nch); -end - -function rec = meas_remote_rec_config(fs, fmt) - source mls_rec_config.txt; - rec.fmt = sprintf('-t wav -c %d -f %s -r %d', ... - rec.nch, fmt, fs); - - fprintf('\nThe setttings for remote capture are\n'); - fprintf('Use ssh : %d\n', rec.ssh); - fprintf('User : %s\n', rec.user); - fprintf('Directory : %s\n', rec.dir); - fprintf('Device : %s\n', rec.dev); - fprintf('format : %s\n', rec.fmt); - fprintf('Channels : %d\n', rec.nch); - fprintf('Calibration Data : %s\n', rec.cal); - - if length(rec.cal) > 0 - if exist(rec.cal, 'file') - [rec.cf, rec.cm, rec.sens, rec.cs] = get_calibration(rec.cal); - else - error('The calibration file does not exist'); - end - else - rec.cf = []; - rec.cm = []; - rec.sens = []; - rec.cs = ''; - end -end - -% The syntax of ASCII text calibration data is such that first line is -% text string sometimes within "" or text line about Sensitivity. Such -% lines are read and stored to description text. The sensitivty is extracted -% and printed if success but currently it is not utilized by the code. -% -% The next lines are <frequency Hz> <magnitude decibels> for -% measurement data for microphone. If there are more than two numbers -% per line the other than two first columns are ignored. This code -% applies inverse of calibration data for measured response calibration. - -function [f, m, sens, desc] = get_calibration(fn) - fh = fopen(fn, 'r'); - if fh < 0 - error('Cannot open calibration data file'); - end - n = 1; - f = []; - m = []; - sens =[]; - desc = ''; - str = fgets(fh); - idx = findstr(str, '"'); - while length(idx) > 0 - line = str(idx(1)+1:idx(2)-1); - desc = sprintf('%s%s ', desc, line); - str = fgets(fh); - idx = findstr(str, '"'); - end - if length(strfind(str, 'Sens')) - desc = str; - str = fgets(fh); - end - while str ~= -1 - d=sscanf(str,'%f'); - f(n) = d(1); - m(n) = d(2); - n = n + 1; - str = fgets(fh); - end - - % Strip possible linefeed from description end - if double(desc(end)) == 10 - desc = desc(1:end-1); - end - fprintf('Calibration Info : %s\n', desc); - i1 = strfind(desc, 'Sens Factor ='); - i2 = strfind(desc, 'dB'); - if length(i1) == 1 && length(i2) == 1 - sens = sscanf(desc(i1+13:i2-1), '%f'); - fprintf('Calibration Sens : %6.2f dB\n', sens); - end - - fprintf('Calibration range: %.2f .. %.2f Hz\n', min(f), max(f)); - fprintf('Calibration range: %.2f .. %.2f dB\n', min(m), max(m)); - - figure; - semilogx(f, m); - grid on; - title(desc); - xlabel('Frequency (Hz)'); - ylabel('Magnitude (dB)'); -end - -function [x, seed] = mlsp12(seed, n) - -% Based on book Numerical Recipes in C, chapter 7.4 Generation of -% random bits method II p. 298-299 example and 12 bit primitive -% polynomial (12, 6, 4, 1, 0) - - x = zeros(1,n); - ib1 = 2^(1-1); - ib4 = 2^(4-1); - ib6 = 2^(6-1); - ib12 = 2^(12-1); - mask = ib1 + ib4 + ib6 + ib12; - - for i = 1:n - if bitand(seed, ib12) - seed = bitor(bitxor(seed, mask) * 2 , ib1); - x(i) = 1; - else - seed = seed * 2; - x(i) = 0; - end - end -end - -%% Calibration apply function -% Resample microphone calibration data into used grid and -% then subtract calibration response from measured -% response. - -function [cal_f, cal_m_db] = apply_mic_calibration(f, m_db, rec) - - if length(rec.cm) > 0 - if ~isvector(rec.cm) - error('Calibration can be for one channel only'); - end - mic_m_db = interp1(rec.cf, rec.cm, f, 'linear'); - nans = isnan(mic_m_db); - idx = find(nans == 0); - cal_f = f(idx); - cal_db = mic_m_db(idx); - s = size(m_db); - for i = 1:s(2) - cal_m_db(:,i) = m_db(idx,i) - cal_db(:); - end - else - cal_m_db = m_db; - cal_f = f; - end - -end diff --git a/tools/tune/src/README b/tools/tune/src/README deleted file mode 100644 index e135f9a21979..000000000000 --- a/tools/tune/src/README +++ /dev/null @@ -1,36 +0,0 @@ -Sample rate converter (SRC) Setup Tools -======================================= - -This is a tool to set up SRC conversions sample rates list, define -quality related parameters, and test the C implementation for a number -of objective audio quality parameters. - -The tools need GNU Octave version 4.0.0 or later with octave-signal -package. - -src_std_int32.m ---------------- - -This script creates the default coefficient set and contains nothing -else but call for src_generate. - -src_tiny_int16.m ----------------- - -This script creates the tiny coefficient set. The script contains an -example how to customize the input/output rates matrix and in a simple -way the scale conversions quality. More controlled quality adjust can -be done by editing file src_param.m directly. Note that int16 -presentation for SRC coefficients will degrade even the default -quality. - -src_generate.m --------------- - -Creates the header files to include to C into directory "include". A -report of create modes is written to directory "reports". The -coefficients need to be copied to directory -sof.git/src/include/sof/audio/coefficients/src. - -The default quality of SRC is defined in module src_param.m. The -quality impacts the complexity and coefficents tables size of SRC. diff --git a/tools/tune/src/src_export_defines.m b/tools/tune/src/src_export_defines.m deleted file mode 100644 index 63fb4c28f7d5..000000000000 --- a/tools/tune/src/src_export_defines.m +++ /dev/null @@ -1,66 +0,0 @@ -function src_export_defines(defs, ctype, hdir, profile) - -% src_export_defines - Exports the constants to header files -% -% src_export_defines(defs, ctype, hdir) -% -% defs - defs struct -% ctype - e.g. 'int24' appended to file name -% hdir - directory for header file -% profile - string to append to file name -% - - -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 4 - profile = ''; -end - -if isempty(profile) - hfn = sprintf('src_%s_define.h', ctype); -else - hfn = sprintf('src_%s_%s_define.h', profile, ctype); -end -fh = fopen(fullfile(hdir,hfn), 'w'); -fprintf(fh, '/* SRC constants */\n'); -fprintf(fh, '#define MAX_FIR_DELAY_SIZE %d\n', defs.fir_delay_size); -fprintf(fh, '#define MAX_OUT_DELAY_SIZE %d\n', defs.out_delay_size); -fprintf(fh, '#define MAX_BLK_IN %d\n', defs.blk_in); -fprintf(fh, '#define MAX_BLK_OUT %d\n', defs.blk_out); -fprintf(fh, '#define NUM_IN_FS %d\n', defs.num_in_fs); -fprintf(fh, '#define NUM_OUT_FS %d\n', defs.num_out_fs); -fprintf(fh, '#define STAGE1_TIMES_MAX %d\n', defs.stage1_times_max); -fprintf(fh, '#define STAGE2_TIMES_MAX %d\n', defs.stage2_times_max); -fprintf(fh, '#define STAGE_BUF_SIZE %d\n', defs.stage_buf_size); -fprintf(fh, '#define NUM_ALL_COEFFICIENTS %d\n', defs.sum_filter_lengths); -fclose(fh); - -end diff --git a/tools/tune/src/src_export_table_2s.m b/tools/tune/src/src_export_table_2s.m deleted file mode 100644 index 7772b9369205..000000000000 --- a/tools/tune/src/src_export_table_2s.m +++ /dev/null @@ -1,190 +0,0 @@ -function sfl = src_export_table_2s(fs_in, fs_out, l_2s, m_2s, ... - pb_2s, sb_2s, taps_2s, ctype, vtype, ppath, hdir, profile) - -% src_export_table_2s - Export src setup table -% -% src_export_table_2s(fs_in, fs_out, l, m, pb, sb, ctype, vtype, hdir, profile) -% -% The parameters are used to differentiate files for possibly many same -% conversion factor filters with possibly different characteristic. -% -% fs_in - input sample rates -% fs_out - output sample rates -% l - interpolation factors -% m - decimation factors -% pb - passband widths -% sb - stopband start frequencies -% ctype - coefficient quantization -% vtype - C variable type -% ppath - print directory prefix to header file name include -% hdir - directory for header files -% profile - string to append to file name -% - -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -if nargin < 12 - profile = ''; -end - -if isempty(profile) - hfn = sprintf('src_%s_table.h', ctype); -else - hfn = sprintf('src_%s_%s_table.h', profile, ctype); -end -fh = fopen(fullfile(hdir,hfn), 'w'); - -fprintf(fh, '/* SRC conversions */\n'); -sfl = 0; -n_in = length(fs_in); -n_out = length(fs_out); -i=1; -all_modes = zeros(2*n_in*n_out, 7); -for n=1:2 - for b=1:n_out - for a=1:n_in - all_modes(i,:) = [ l_2s(n,a,b) m_2s(n,a,b) ... - pb_2s(n,a,b) sb_2s(n,a,b) n a b ]; - i=i+1; - end - end -end - -all_modes_sub = all_modes(:,1:4); -[unique_modes, ia] = unique(all_modes_sub,'rows'); -sm = size(unique_modes); - -if isempty(profile) - prof_ctype = ctype; -else - prof_ctype = sprintf('%s_%s', profile, ctype); -end -for i=1:sm(1) - um_tmp = unique_modes(i,:); - if isequal(um_tmp(1:2),[1 1]) || isequal(um_tmp(1:2),[0 0]) - else - fprintf(fh, '#include <%ssrc_%s_%d_%d_%d_%d.h>\n', ... - ppath, prof_ctype, um_tmp(1:4)); - - n = all_modes(ia(i), 5); - a = all_modes(ia(i), 6); - b = all_modes(ia(i), 7); - sfl = sfl +taps_2s(n, a, b); % Count sum of filter lengths - end -end -fprintf(fh,'\n'); - -fprintf(fh, '/* SRC table */\n'); -switch ctype - case 'float' - fprintf(fh, '%s fir_one = 1.0;\n', vtype); - fprintf(fh, 'struct src_stage src_double_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, 1.0, &fir_one };\n'); - fprintf(fh, 'struct src_stage src_double_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0.0, &fir_one };\n'); - case 'int16' - scale16 = 2^15; - fprintf(fh, '%s fir_one = %d;\n', vtype, round(scale16*0.5)); - fprintf(fh, 'struct src_stage src_int16_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n'); - fprintf(fh, 'struct src_stage src_int16_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n'); - case 'int24' - scale24 = 2^23; - fprintf(fh, '%s fir_one = %d;\n', vtype, round(scale24*0.5)); - fprintf(fh, 'struct src_stage src_int24_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n'); - fprintf(fh, 'struct src_stage src_int24_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n'); - case 'int32' - scale32 = 2^31; - fprintf(fh, '%s fir_one = %d;\n', vtype, round(scale32*0.5)); - fprintf(fh, 'struct src_stage src_int32_1_1_0_0 = { 0, 0, 1, 1, 1, 1, 1, 0, -1, &fir_one };\n'); - fprintf(fh, 'struct src_stage src_int32_0_0_0_0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, &fir_one };\n'); - otherwise - error('Unknown coefficient type!'); -end - -fprintf(fh, 'int src_in_fs[%d] = {', n_in); -j = 1; -for i=1:n_in - fprintf(fh, ' %d', fs_in(i)); - if i < n_in - fprintf(fh, ','); - end - j = j + 1; - if (j > 8) - fprintf(fh, '\n\t'); - j = 1; - end -end -fprintf(fh, '};\n'); - -fprintf(fh, 'int src_out_fs[%d] = {', n_out); -j = 1; -for i=1:n_out - fprintf(fh, ' %d', fs_out(i)); - if i < n_out - fprintf(fh, ','); - end - j = j + 1; - if (j > 8) - fprintf(fh, '\n\t'); - j = 1; - end -end -fprintf(fh, '};\n'); - -for n = 1:2 - fprintf(fh, 'struct src_stage *src_table%d[%d][%d] = {\n', ... - n, n_out, n_in); - i = 1; - for b = 1:n_out - fprintf(fh, '\t{'); - for a = 1:n_in - fprintf(fh, ' &src_%s_%d_%d_%d_%d', ... - ctype, l_2s(n,a,b), m_2s(n,a,b), ... - pb_2s(n,a,b), sb_2s(n,a,b)); - if a < n_in - fprintf(fh, ','); - end - i = i + 1; - if i > 2 - fprintf(fh, '\n\t'); - i = 1; - end - end - fprintf(fh, '}'); - if b < n_out - fprintf(fh, ',\n'); - else - fprintf(fh, '\n'); - end - end - fprintf(fh, '};\n'); -end - -fclose(fh); - -end diff --git a/tools/tune/src/src_generate.m b/tools/tune/src/src_generate.m deleted file mode 100644 index c94ce4b7396a..000000000000 --- a/tools/tune/src/src_generate.m +++ /dev/null @@ -1,274 +0,0 @@ -function src_generate(fs_in, fs_out, fs_inout, cfg); - -% src_generate - export src conversions for given fs_in and fs_out -% -% src_generate(fs_in, fs_out <, fs_inout, <cfg>>) -% -% fs_in - vector of input sample rates (M) -% fs_out - vector of output sample rates (N) -% fs_inout - matrix of supported conversions (MxN), -% 0 = no support, 1 = supported -% cfg - configuration struct with fields -% ctype - coefficient type, use 'int16','int24', 'int32', or 'float' -% profile - differentiate set with identifier, e.g. 'std' -% quality - quality factor, usually 1.0 -% speed - optimize speed, gives higher RAM size, usually 0 -% -% If fs_inout matrix is omitted this script will compute coefficients -% for all fs_in <-> fs_out combinations. -% -% If cfg is omitted the script will assume 'int32', 'std', 1.0, 0. -% - -% SPDX-License-Identifier: BSD-3-Clause -% -% Copyright (c) 2016-2020, Intel Corporation. All rights reserved. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> - -if (nargin < 2) || (nargin > 4) - error('Incorrect arguments for function!'); -end -if nargin < 4 - cfg.ctype = 'int32'; - cfg.profile = 'std'; - cfg.quality = 1.0; - cfg.speed = 0; -end -if nargin < 3 - fs_inout = ones(length(fs_in), length(fs_out)); -end - -sio = size(fs_inout); -if (length(fs_in) ~= sio(1)) || (length(fs_out) ~= sio(2)) - error('Sample rates in/out matrix size mismatch!'); -end - -%% Exported coefficients type int16, int24, int32, float - -switch cfg.ctype - case 'int16' - coef_label = 'int16'; - coef_ctype = 'int16_t'; - coef_bits = 16; - coef_bytes = 2; - case 'int24' - coef_label = 'int24'; - coef_ctype = 'int32_t'; - coef_bits = 24; - coef_bytes = 4; - case 'int32' - coef_label = 'int32'; - coef_ctype = 'int32_t'; - coef_bits = 32; - coef_bytes = 4; - case 'float' - coef_label = 'float'; - coef_ctype = 'float'; - coef_bits = 24; - coef_bytes = 4; - otherwise - error('Request for incorrect coefficient type'); -end -data_bytes = 4; - -hdir = mkdir_check('include'); -rdir = mkdir_check('reports'); - -%% Find fractional conversion factors -nfsi = length(fs_in); -nfso = length(fs_out); -l_2s = zeros(2, nfsi, nfso); -m_2s = zeros(2, nfsi, nfso); -mops_2s = zeros(2, nfsi, nfso); -pb_2s = zeros(2,nfsi, nfso); -sb_2s = zeros(2,nfsi, nfso); -taps_2s = zeros(2,nfsi, nfso); -defs.fir_delay_size = 0; -defs.out_delay_size = 0; -defs.blk_in = 0; -defs.blk_out = 0; -defs.num_in_fs = nfsi; -defs.num_out_fs = nfso; -defs.stage1_times_max = 0; -defs.stage2_times_max = 0; -defs.stage_buf_size = 0; -h = 1; -for b = 1:nfso - for a = 1:nfsi - fs1 = fs_in(a); - fs2 = fs_out(b); - [l1, m1, l2, m2] = src_factor2_lm(fs1, fs2); - % If the interpolate/decimate factors are low, use single step - % conversion. The increases RAM consumption but lowers the MCPS. - if cfg.speed && max(l1 * l2, m1 * m2) < 30 - l1 = l1 * l2; - l2 = 1; - m1 = m1 * m2; - m2 = 1; - end - fs3 = fs1*l1/m1; - cnv1 = src_param(fs1, fs3, coef_bits, cfg.quality); - cnv2 = src_param(fs3, fs2, coef_bits, cfg.quality); - if (fs2 < fs1) - % When decimating 1st stage passband can be limited - % for wider transition band - f_pb = fs2*cnv2.c_pb; - cnv1.c_pb = f_pb/min(fs1,fs3); - end - if (fs2 > fs1) - % When interpolating 2nd stage passband can be limited - % for wider transition band - f_pb = fs1*cnv1.c_pb; - cnv2.c_pb = f_pb/min(fs2,fs3); - end - if fs_inout(a,b) > 0 || abs(fs1 - fs2) < eps - if cnv2.fs1-cnv2.fs2 > eps - % Allow half ripple for dual stage SRC parts - cnv1.rp = cnv1.rp/2; - cnv2.rp = cnv2.rp/2; - % Distribute gain also - cnv1.gain = cnv1.gain/2; - cnv2.gain = cnv2.gain/2; - end - src1 = src_get(cnv1); - src2 = src_get(cnv2); - k = gcd(src1.blk_out, src2.blk_in); - stage1_times = src2.blk_in/k; - stage2_times = stage1_times*src1.blk_out/src2.blk_in; - defs.stage1_times_max = max(defs.stage1_times_max, stage1_times); - defs.stage2_times_max = max(defs.stage2_times_max, stage2_times); - l_2s(:,a,b) = [src1.L src2.L]; - m_2s(:,a,b) = [src1.M src2.M]; - mops_2s(:,a,b) = [src1.MOPS src2.MOPS]; - pb_2s(:,a,b) = [round(1e4*src1.c_pb) round(1e4*src2.c_pb)]; - sb_2s(:,a,b) = [round(1e4*src1.c_sb) round(1e4*src2.c_sb)]; - taps_2s(:,a,b) = [src1.filter_length src2.filter_length]; - defs.fir_delay_size = max(defs.fir_delay_size, src1.fir_delay_size); - defs.out_delay_size = max(defs.out_delay_size, src1.out_delay_size); - defs.blk_in = max(defs.blk_in, src1.blk_in); - defs.blk_out = max(defs.blk_out, src1.blk_out); - defs.fir_delay_size = max(defs.fir_delay_size, src2.fir_delay_size); - defs.out_delay_size = max(defs.out_delay_size, src2.out_delay_size); - defs.blk_in = max(defs.blk_in, src2.blk_in); - defs.blk_out = max(defs.blk_out, src2.blk_out); - defs.stage_buf_size = max(defs.stage_buf_size, src1.blk_out*stage1_times); - src_export_coef(src1, coef_label, coef_ctype, hdir, cfg.profile); - src_export_coef(src2, coef_label, coef_ctype, hdir, cfg.profile); - end - end -end - -%% Export modes table -defs.sum_filter_lengths = src_export_table_2s(fs_in, fs_out, l_2s, m_2s, ... - pb_2s, sb_2s, taps_2s, coef_label, coef_ctype, ... - 'sof/audio/coefficients/src/', hdir, cfg.profile); -src_export_defines(defs, coef_label, hdir, cfg.profile); - -%% Print 2 stage conversion factors -fn = sprintf('%s/src_2stage.txt', rdir); -fh = fopen(fn,'w'); -fprintf(fh,'\n'); -fprintf(fh,'Dual stage fractional SRC: Ratios\n'); -fprintf(fh,'%8s, ', 'in \ out'); -for b = 1:nfso - fprintf(fh,'%12.1f, ', fs_out(b)/1e3); -end -fprintf(fh,'\n'); -for a = 1:nfsi - fprintf(fh,'%8.1f, ', fs_in(a)/1e3); - for b = 1:nfso - cstr = print_ratios(l_2s, m_2s, a, b); - fprintf(fh,'%12s, ', cstr); - end - fprintf(fh,'\n'); -end -fprintf(fh,'\n'); - -%% Print 2 stage MOPS -fprintf(fh,'Dual stage fractional SRC: MOPS\n'); -fprintf(fh,'%8s, ', 'in \ out'); -for b = 1:nfso - fprintf(fh,'%8.1f, ', fs_out(b)/1e3); -end -fprintf(fh,'\n'); -for a = 1:nfsi - fprintf(fh,'%8.1f, ', fs_in(a)/1e3); - for b = 1:nfso - mops = sum(mops_2s(:,a,b)); - if sum(l_2s(:,a,b)) < eps - mops_str = 'x'; - else - mops_str = sprintf('%.2f', mops); - end - fprintf(fh,'%8s, ', mops_str); - end - fprintf(fh,'\n'); -end -fprintf(fh,'\n'); - -%% Print 2 stage MOPS per stage -fprintf(fh,'Dual stage fractional SRC: MOPS per stage\n'); -fprintf(fh,'%10s, ', 'in \ out'); -for b = 1:nfso - fprintf(fh,'%10.1f, ', fs_out(b)/1e3); -end -fprintf(fh,'\n'); -for a = 1:nfsi - fprintf(fh,'%10.1f, ', fs_in(a)/1e3); - for b = 1:nfso - mops = mops_2s(:,a,b); - if sum(l_2s(:,a,b)) < eps - mops_str = 'x'; - else - mops_str = sprintf('%.2f+%.2f', mops(1), mops(2)); - end - fprintf(fh,'%10s, ', mops_str); - end - fprintf(fh,'\n'); -end -fprintf(fh,'\n'); - -fprintf(fh,'Coefficient RAM %.1f kB\n', ... - defs.sum_filter_lengths*coef_bytes/1024); -fprintf(fh,'Max. data RAM %.1f kB\n', ... - (defs.fir_delay_size + defs.out_delay_size+defs.stage_buf_size) ... - * data_bytes/1024); - -fprintf(fh,'\n'); -fclose(fh); -type(fn); - -end - -function d = mkdir_check(d) -if exist(d) ~= 7 - mkdir(d); -end -end - -function cstr = print_ratios(l_2s, m_2s, a, b) -l1 = l_2s(1,a,b); -m1 = m_2s(1,a,b); -l2 = l_2s(2,a,b); -m2 = m_2s(2,a,b); -if l1+m2+l2+m2 == 0 - cstr = 'x'; -else - if m2 == 1 - if l2 == 1 - cstr2 = ''; - else - cstr2 = sprintf('*%d', l2); - end - else - cstr2 = sprintf('*%d/%d', l2, m2); - end - if m1 == 1 - cstr1 = sprintf('%d', l1); - else - cstr1 = sprintf('%d/%d', l1, m1); - end - cstr = sprintf('%s%s', cstr1, cstr2); -end -end diff --git a/tools/tune/src/src_std_int32.m b/tools/tune/src/src_std_int32.m deleted file mode 100644 index 156da87cf4eb..000000000000 --- a/tools/tune/src/src_std_int32.m +++ /dev/null @@ -1,55 +0,0 @@ -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -fs1 = [8 11.025 12 16 22.05 24 32 44.1 48 50 64 88.2 96 176.4 192] * 1e3; - -fs2 = [8 11.025 12 16 22.05 24 32 44.1 48 50] * 1e3; - -fs_matrix = [ 0 0 0 1 0 1 1 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 1 0 0 0 0 1 1 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 1 0 0 1 0 0 1 0 1 0 ; ... - 1 0 0 1 0 1 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 1 1 1 1 1 1 1 1 0 1 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ; ... - 0 0 0 0 0 0 0 0 1 0 ]; - -cfg.ctype = 'int32'; -cfg.profile = 'std'; -cfg.quality = 1.0; -cfg.speed = 0; - -src_generate(fs1, fs2, fs_matrix, cfg); diff --git a/tools/tune/src/src_tiny_int16.m b/tools/tune/src/src_tiny_int16.m deleted file mode 100644 index 327f8d9ef6c1..000000000000 --- a/tools/tune/src/src_tiny_int16.m +++ /dev/null @@ -1,45 +0,0 @@ -% Copyright (c) 2016, Intel Corporation -% All rights reserved. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the Intel Corporation nor the -% names of its contributors may be used to endorse or promote products -% derived from this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -% POSSIBILITY OF SUCH DAMAGE. -% -% Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> -% - -fs1 = [8e3 16e3 32e3 44.1e3 48e3 50e3]; -fs2 = [8e3 16e3 32e3 44.1e3 48e3 50e3]; -fsm = [0 0 0 0 1 0; ... - 0 0 0 0 1 0; ... - 0 0 0 0 1 0; ... - 0 0 0 0 1 0; ... - 1 1 1 1 0 1; ... - 0 0 0 0 1 0; ... - ]; - -cfg.ctype = 'int16'; -cfg.profile = 'tiny'; -cfg.quality = 0.40; -cfg.speed = 1; - -src_generate(fs1, fs2, fsm, cfg); diff --git a/uuid-registry.txt b/uuid-registry.txt new file mode 100644 index 000000000000..dc5cf5e15297 --- /dev/null +++ b/uuid-registry.txt @@ -0,0 +1,185 @@ +# +# Global UUID/name registry for SOF components in alphabetical order. +# +# All IDs used in shipped binary artifacts must appear in this list. +# All names must be unique. +# All names must be legal C identifiers of at most 31 characters. +# No change to a previously distributed mapping is allowed, ever. +# +# Simple format: "#" indicates a comment to end of line. Remaining +# lines must be entirely empty/whitespace, or two whitespace-separated +# fields of: <UUID> <name> +# +# NOTE: the UUID is in a SOF-unique format to match the (nonstandard +# and endian-ambiguous) representation in struct sof_uuid: the first +# three entries are specified as little endian dword/word values, the +# last as an ordered array of 8 bytes. If you have a value from +# e.g. an RFC-4122 compliant tool, swap the order of the two bytes in +# the fourth cluster and prepend it to the last. Most of the time you +# are just using random values and won't care about the byte swap. +# + + +ab01db67-84b0-4d2d-93d30e619680576e acp_bt_dma +f8a7091c-7d2d-4410-9bb555278378d59f acp_clk +0ae40946-dfd2-4140-91520dd5a3eaae81 acp_dmic_dai +109c7aba-a7ba-43c3-b94259e20a6611be acp_dmic_dma +dc2199ea-cdae-4d23-a413ffe442f785f2 acp_dmic_dma_common +b414df09-9e31-4c59-86577afc8deba70c acp_hs +3ac07334-41ce-4447-a2c5dff0d1fa1392 acp_sp +2ef92c66-78a4-41f7-b52f5539707a9382 acp_sp_common +5871f3ca-dd92-4edb-8a94d651dd208b1e acp_sw_audio +70f2d3f2-cbb6-4984-a2d80dd514b80bc2 acpdma +30290c76-6a05-4784-8464c21f09cee87e afe_dai +4e8f16d1-e935-41f4-b99e42c57e745784 afedrv +c63c4e75-8f61-4420-93191395932efa9e agent_work +ea9c4bca-5b7d-48c6-9586553e27235beb ams +72cee996-39f2-11ed-a08f97fcc42eaaeb aplay +66def9f0-39f2-11ed-f789af98a6440cc4 arecord +99f7166d-372c-43ef-81f622007aa15f03 aria +c8ec72f6-8526-4faf-9d39a23d0b541de2 asrc +66b4402d-b468-42f2-81a7b37121863dd4 asrc4 +0e398c32-5ade-ba4b-93b1c50432280ee4 basefw +2B79E4F3-4675-F649-89DF3BC194A91AEB brngup +20865bfe-b833-4ff9-b22a0482c3477497 btdai +42544c92-8e92-4e41-b67934519f1c1d28 buffer +d8218443-5ff3-4a4c-b3886cfe07b956aa cadence_codec +6a0a274f-27cc-4afb-a3e73444723f432e chain_dma +ec290e95-4a20-47eb-bbffd9c888431831 chmap +53863428-9a72-44df-af0ffe45ea2348ba clkdrv_mt8186 +19d4e680-4479-48cc-af869f63d8b0098b clkdrv_mt8188 +23b12fd5-c2a9-41a8-a2b3231ab7dcdc70 clkdrv_mt8195 +e87bf747-e574-4362-bf2cc015d2859dd9 clkdrv_mt8196 +de358908-c146-4411-98b430ebd002957f clkdrv_mt8365 +8890ea76-0df9-44ae-87e6994f4c15e9fa clock +D406D134-C3C1-402C-8AEC6821C0C2B0E6 cold +7c42ce8b-0108-43d0-913756d660478c5f component +9ba00c83-ca12-4a83-943c1fa2e82f9dda copier +948c9ad1-806a-4131-ad6cb2bda9e35a9f crossover +c2b00d27-ffbc-4150-a51a245c79c5e54b dai +06711c94-d37d-4a76-b302bbf6944fdd2b dai_lib +b809efaf-5681-42b1-9ed604bb012dd384 dcblock +c4b26868-1430-470e-a08915d1c77f851a demux +bc3526a7-9b86-4ab4-84a52e02ae70cc10 dma +729bf8b5-e873-4bf5-96908e2a3fd33911 dma_copy +58782c63-1326-4185-845922272e12d1f1 dma_trace +2b972272-c5b1-4b7e-926f0fc5cb4c4690 dma_trace_task +40f66c8b-5aa5-4345-891953ec431aaa98 dolby_dax_audio_processing +87858bc2-baa9-40b6-8e4c2c95ba8b1545 dp_sched +ee755917-96b9-4130-b49e37b9d0501993 dp_task +b36ee4da-006f-47f9-a06dfecbe2d8b6ce drc +d95fc34f-370f-4ac7-bc86bfdc5be241e6 dts +f6d15ad3-b122-458c-ae9b0ab0b5867aa0 dummy_dma +298873bc-d532-4d93-a54095ee6bcf3456 dw_dma +77de2074-828c-4044-a40b420b72749e8b edf_sched +5dbc3672-e290-43d8-91f881aafe453d5b edf_sched_lib +3d73a110-0930-457f-be5134453e56287b edma +43a90ce7-f3a5-41df-ac06ba98651ae6a3 eq_fir +5150c0e6-27f9-4ec8-8351c705b642d12f eq_iir +889f6dcd-ddcd-4e05-aa5b0d39f8bca961 esai +bfc7488c-75aa-4ce8-9dbed8da08a698c2 file +93446e12-1864-4e04-afe03b1d778ffb79 fir +61bca9a8-18d0-4a18-8e7b2639219804b7 gain +bf0e1bbc-dc6a-45fe-bc902554cb137ab4 google_ctc_audio_processing +c3c74249-058e-414f-82404da5f3fc2389 google_hotword +b780a0a6-269f-466f-b47723dfa05af758 google_rtc_audio_processing +8b9d100c-6d78-418f-90a3e0e805d0852b host +8f00c3bb-e835-4767-9a34b8ec1041e56b hsdai +379a60ae-cedb-4777-aaf25659b0a85735 idc +a5dacb0e-88dc-415c-a1b53e8df77f1976 idc_cmd_task +b90f5a4e-5537-4375-a1df95485472ff9e idc_task +696ae2bc-2877-11eb-adc10242ac120002 igo_nr +b0cdcd9e-ef8b-404f-84800f287fc9d44d iir +2f520e85-49ba-4284-90d83def24af313b intc_mt8196 +fa00558c-d653-4851-a03ab21f125a9524 interrupt +be60f97d-78df-4796-a0ee435cb56b720a ipc +389c9186-5a7d-4ad1-a02ca02ecdadfb33 ipc_task +49be8ff3-71a3-4456-bb7e4723f2e5730c ipc_task_amd +a3fe3bf2-39a4-4fc3-b3418a96e0a26759 ipc_task_mt818x +caef4bd7-7a2e-4039-9b061f5ff9ec3899 ipc_task_mt8196 +6c8f0d53-ff77-4ca1-b825c0c4e1b0d322 ipc_task_posix +a814a1ca-0b83-466c-95872f35ff8d12e8 ipcgw +1862d39a-3a84-4d64-8c91dce1dfc122db irq +6533d0eb-b785-4709-84f5347c81720189 irq_acp +d2e3f730-df39-42ee-81a839bfb4d024c2 irq_mt818x +7eb28333-f08f-436f-bbbd764ac21fc2f1 irq_mt8196 +eba8d51f-7827-47b5-82eede6e7743af67 keyword +d8218443-5ff3-4a4c-b3886cfe07b9562e kpb +a8a0cb32-4a77-4db1-85c753d7ee07bce6 kpb4 +e50057a5-8b27-4db4-bd799a639cee5f50 kpb_task +30397456-4661-4644-97e539a9e5ab1778 level_multiplier +54cf5598-8b29-11ec-a8a30242ac120002 lib_manager +4f9c3ec7-7b55-400c-86b3502b4420e625 ll_sched +9f130ed8-2bbf-421c-836ad5269147c9e7 ll_sched_lib +37f1d41f-252d-448d-b9c41e2bee8e1bf1 main_task +107eb437-0347-4336-ab60f4baaeb5ea49 math_fft +590af515-8fc0-4827-8748c8efbe6ac514 math_fft_multi +d23cf8d0-8dfe-497c-82025f909cf72735 math_power +0cd84e80-ebd3-11ea-adc10242ac120002 maxim_dsm +425d6e68-145c-4455-b0b2c7260b0600a5 mem +df5e94d7-fd93-42e9-bb94ab40becc7151 memif +db10a773-1aa4-4cea-a21f2d57a5c982eb mfcc +dd400475-35d7-4045-ab030c34957d7a08 micfil +bc06c037-12aa-417c-9a9789282e321a76 mixer +39656eb2-3b71-4049-8d3ff92cd5c43c09 mixin +3c56505a-24d7-418f-bddcc1f5a3ac2ae0 mixout +ee2585f2-e7d8-43dc-90ab4224e00c3e84 modules +0d9f2256-8e4f-47b3-8448239a334f1191 multiband_drc +c607ff4d-9cb6-49dc-b6787da3c63ea557 mux +64ce6e35-857a-4878-ace8e2a2f42e3069 mux4 +f36BF24B-9AAF-83f4-8677E072E8AEADB7 notification_pool +1fb15a7a-83cd-4c2e-8b324da1b2adeeaf notifier +7ae671a7-4617-4a09-bf6d9d29c998dbc1 ns +127f4eec-23fa-11f0-a4a6bf0cd6b4583b nxp_eap +376b5e44-9c82-4ec2-bc8310ea101af88f passthrough +64a794f0-55d3-4bca-9d5b7b588badd037 passthru_smart_amp +4e934adb-b0ec-4d33-a086c1022f921321 pipe +f11818eb-e92e-4082-82a3dc54c604ebb3 pipe_task +d7f6712d-131c-45a7-82ed6aa9dc2291ea pm_runtime +76cc9773-440c-4df9-95a872defe7796fc power +9d1fb66e-4ffb-497f-994b17719686596e probe +7cad0808-ab10-cd23-ef4512ab34cd56ef probe4 +2f0b1901-cac0-4b87-812ff2d5e4f19e4a probe_task +393608d8-4188-11ee-be560242ac122002 ring_buffer +5c7ca334-e15d-11eb-ba800242ac130004 rtnr +5276b491-5b64-464e-8984dc228ef9e6a1 sa +9302adf5-88be-4234-a0a7dca538ef81f4 sai +3dee06de-f25a-4e10-ae1fabc9573873ea schedule +70d223ef-2b91-4aac-b444d89a0db2793a sdma +55a88ed5-3d18-46ca-88f10ee6eae9930f selector +32fe92c1-1e17-4fc2-9758c7f3542e980a selector4 +cf90d851-68a2-4987-a2de85aed0c8531c sgen_mt8186 +99316bd9-07b9-4665-81796e048d67cb45 sgen_mt8188 +9eb1a55b-fc20-4442-96131ff1023be493 sgen_mt8195 +bcf54c06-5702-4a60-ac4abb509123c649 sgen_mt8196 +654ef011-6d79-414a-9c1b15e72c0be321 sgen_mt8365 +dabe8814-47e8-11ed-a58bb309974fecce shmread +e2b6031c-47e8-11ed-07a97f801b6efa6c shmwrite +167a961e-8ae4-11ea-89f1000c29ce1635 smart_amp_test +a43f9d7c-ea75-44d5-942d967991a33809 sound_dose +4abd71ba-8619-458a-b33f160fc0cf809b spdai +a417b6fb-459d-4cf9-be65d38dc9057b80 spi_completion +9d346d98-203d-4791-baee1770a03d4a71 spinlock +c1c5326d-8390-46b4-aa4795c3beca6550 src +e61bb28d-149a-4c1f-b70946823ef5f5ae src4 +33441051-44cd-466a-83a3178478708aea src_lite +0d116ea6-9150-46de-98b8b2b3a791da29 stft_process +eb0bd14b-7d5e-4dfa-bbe27762adb279f0 swaudiodai +dd511749-d9fa-455c-b3a713585693f1af tdfb +a62de1af-5964-4e2e-b1677fdc97279a29 template +37c196ae-3532-4282-8a78dd9d50cc7123 testbench +08aeb4ff-7f68-4c71-86c3c842b4262898 tester +c51dc642-a2e1-48df-a490e2748cb6363e tflmcly +04e3f894-2c5c-4f2e-8dc1694eeaab53fa tone +e93326d8-0d14-4bf0-bcb9e063d3d80136 twb_sched +42f8060c-832f-4dbf-b24751e961997b34 up_down_mixer +6f6b6f4b-6f73-7466-20e1e62b9779f003 userspace_proxy +b77e677e-5ff4-4188-af14fba8bdbf8682 volume +8a171323-94a3-4e1d-afe9fe5dbaa4c393 volume4 +1028070e-04e8-46ab-8d8110a0116ce738 wait +d944281a-afe9-4695-a043d7f62b89538e waves +13c8bc59-c4fa-4ad1-b93ace97cd30acc7 wdt +300aaad4-45d2-8313-25d05e1d6086cdd1 zephyr +5f1ec3f8-faaf-4099-903ccee98351f169 zephyr_idc +8fa1d42f-bc6f-464b-867f547af08834da zipc_task +1547fe68-de0c-11eb-84613158a1294853 zll_sched diff --git a/versions.json b/versions.json new file mode 100644 index 000000000000..89bebab40c35 --- /dev/null +++ b/versions.json @@ -0,0 +1,7 @@ +{ + "SOF": { + "MAJOR": "2", + "MINOR": "14", + "MICRO": "99" + } +} diff --git a/west.yml b/west.yml new file mode 100644 index 000000000000..faf374b914fb --- /dev/null +++ b/west.yml @@ -0,0 +1,67 @@ +--- +# SOF west manifest +manifest: + version: "0.13" + + defaults: + remote: thesofproject + + remotes: + - name: thesofproject + url-base: https://github.com/thesofproject + - name: zephyrproject + url-base: https://github.com/zephyrproject-rtos + + # When upgrading projects here please run git log --oneline in the + # project and if not too long then include the output in your commit + # message. See examples of good commit messages at + # https://github.com/thesofproject/sof/commits/4e1d3ba61abd3/rimage + # (git log 4e1d3ba61abd3 -- rimage/) + + # WARNING: for backwards compatibility with non-Zephyr platforms, + # rimage and toml99 are STILL git submodules! Every time you change + # their `revision` revision here you MUST keep their git submodules in + # sync. This is as simple as `git add rimage` before committing (+ + # `git commit --amend` if you forgot and already committed this + # west manifest file). + + # When a submodule is out of sync then both `git status` and `git + # describe` notice and a "-dirty" suffix appears in the SOF version. + # It is generally very bad practice to git push without looking + # at "git status"; even without submodules. + # rimage and tomlc99 to Zephyr's west manifest discussion: + # https://github.com/zephyrproject-rtos/zephyr/issues/58212 + + projects: + # West convenience for Zephyr people who forgot --recursive when + # cloning sof.git. This adds the burden of keeping both tomlc99 + # SHA1s synchronized but in practice it barely ever moves. + - name: tomlc99 + repo-path: tomlc99 + path: sof/tools/rimage/tomlc99 + revision: e3a03f5ec7d8d33be705c5ce8a632d998ce9b4d1 + + - name: zephyr + repo-path: zephyr + revision: c162980efd9ad8616d0e2fe886ca917d8d8d240a + remote: zephyrproject + + # Import some projects listed in zephyr/west.yml@revision + # + # Warning: changes to zephyr/west.yml or to any other _imported_ + # west.yml file are _ignored_ by design! Only the above + # 'revision:' of zephyr/west.yml is used. + import: + name-whitelist: + - hal_xtensa + - hal_nxp + - mbedtls + - mipi-sys-t + - lz4 + - tinycrypt + - cmsis_6 + + self: + # Changes to submanifests/*.yml files _are_ effective; these have no + # specified 'revision:' + import: submanifests diff --git a/xtos/include/rtos/bit.h b/xtos/include/rtos/bit.h new file mode 100644 index 000000000000..3dde908c2d6b --- /dev/null +++ b/xtos/include/rtos/bit.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __XTOS_RTOS_BIT_H__ +#define __XTOS_RTOS_BIT_H__ + +#if ASSEMBLY +#define BIT(b) (1 << (b)) +#else +#define BIT(b) (1UL << (b)) +#endif + +#define MASK(b_hi, b_lo) \ + (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) +#define SET_BIT(b, x) (((x) & 1) << (b)) +#define SET_BITS(b_hi, b_lo, x) \ + (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) +#define GET_BIT(b, x) \ + (((x) & (1ULL << (b))) >> (b)) +#define GET_BITS(b_hi, b_lo, x) \ + (((x) & MASK(b_hi, b_lo)) >> (b_lo)) + +#endif /* __XTOS_RTOS_BIT_H__ */ diff --git a/xtos/include/rtos/interrupt.h b/xtos/include/rtos/interrupt.h new file mode 100644 index 000000000000..58cefae94c81 --- /dev/null +++ b/xtos/include/rtos/interrupt.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> + */ + +#ifndef __SOF_DRIVERS_INTERRUPT_H__ +#define __SOF_DRIVERS_INTERRUPT_H__ + +#include <platform/drivers/interrupt.h> + +#if !defined(__ASSEMBLER__) && !defined(LINKER) +#include <arch/drivers/interrupt.h> +#include <sof/lib/cpu.h> +#include <sof/list.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <stdbool.h> +#include <stdint.h> + +/** + * \brief child IRQ descriptor for cascading IRQ controllers. + */ +struct irq_child { + int enable_count[CONFIG_CORE_COUNT]; /**< IRQ enable counter */ + struct list_item list; /**< head for IRQ descriptors, + * sharing this interrupt + */ +}; + +/** + * \brief interrupt client descriptor + */ +struct irq_desc { + int irq; /**< virtual IRQ number */ + void (*handler)(void *arg); /**< interrupt handler function */ + void *handler_arg; /**< interrupt handler argument */ + uint32_t cpu_mask; /**< a mask of CPUs on which this + * interrupt is enabled + */ + struct list_item irq_list; /**< to link to other irq_desc */ +}; + +/** + * \brief cascading IRQ controller operations. + */ +struct irq_cascade_ops { + void (*mask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< mask */ + void (*unmask)(struct irq_desc *desc, uint32_t irq, + unsigned int cpu); /**< unmask */ +}; + +/** + * \brief cascading interrupt controller descriptor. + */ +struct irq_cascade_desc { + const char *name; /**< name of the + * controller + */ + int irq_base; /**< first virtual IRQ + * number, assigned to + * this controller + */ + const struct irq_cascade_ops *ops; /**< cascading interrupt + * controller driver + * operations + */ + struct irq_desc desc; /**< the interrupt, that + * this controller is + * generating + */ + struct irq_cascade_desc *next; /**< link to the global + * list of interrupt + * controllers + */ + bool global_mask; /**< the controller + * cannot mask input + * interrupts per core + */ + struct k_spinlock lock; /**< protect child + * lists, enable and + * child counters + */ + int enable_count[CONFIG_CORE_COUNT]; /**< enabled child + * interrupt counter + */ + unsigned int num_children[CONFIG_CORE_COUNT]; /**< number of children + */ + struct irq_child child[PLATFORM_IRQ_CHILDREN]; /**< array of child + * lists - one per + * multiplexed IRQ + */ +}; + +/* A descriptor for cascading interrupt controller template */ +struct irq_cascade_tmpl { + const char *name; + const struct irq_cascade_ops *ops; + int irq; + void (*handler)(void *arg); + bool global_mask; +}; + +/** + * \brief Cascading interrupt controller root. + */ +struct cascade_root { + struct k_spinlock lock; /**< locking mechanism */ + struct irq_cascade_desc *list; /**< list of child cascade irqs */ + int last_irq; /**< last registered cascade irq */ +}; + +static inline struct cascade_root *cascade_root_get(void) +{ + return sof_get()->cascade_root; +} + +/* For i.MX, while building SOF with Zephyr use the interrupt_* + * functions from second level interrupt handling and IRQ_STEER. + */ +#if defined(__ZEPHYR__) && (defined(CONFIG_IMX) || defined(CONFIG_AMD)) +int mux_interrupt_get_irq(unsigned int irq, const char *cascade); +int mux_interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void mux_interrupt_unregister(uint32_t irq, const void *arg); +uint32_t mux_interrupt_enable(uint32_t irq, void *arg); +uint32_t mux_interrupt_disable(uint32_t irq, void *arg); +#endif + +int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg); +void interrupt_unregister(uint32_t irq, const void *arg); +uint32_t interrupt_enable(uint32_t irq, void *arg); +uint32_t interrupt_disable(uint32_t irq, void *arg); + +/* Zephyr compat */ +#if !defined(__ZEPHYR__) +#define arch_irq_lock() arch_interrupt_disable_mask(0xffffffff) +#endif + +void platform_interrupt_init(void); + +void platform_interrupt_set(uint32_t irq); +void platform_interrupt_clear(uint32_t irq, uint32_t mask); +uint32_t platform_interrupt_get_enabled(void); +void interrupt_mask(uint32_t irq, unsigned int cpu); +void interrupt_unmask(uint32_t irq, unsigned int cpu); + +/* + * On platforms, supporting cascading interrupts cascaded interrupt numbers + * are greater than or equal to PLATFORM_IRQ_HW_NUM + */ +#define interrupt_is_dsp_direct(irq) (!PLATFORM_IRQ_CHILDREN || \ + irq < PLATFORM_IRQ_HW_NUM) + +void interrupt_init(struct sof *sof); +int interrupt_cascade_register(const struct irq_cascade_tmpl *tmpl); +struct irq_cascade_desc *interrupt_get_parent(uint32_t irq); +int interrupt_get_irq(unsigned int irq, const char *cascade); + +static inline void interrupt_set(int irq) +{ + platform_interrupt_set(irq); +} + +static inline void interrupt_clear_mask(int irq, uint32_t mask) +{ + platform_interrupt_clear(irq, mask); +} + +static inline void interrupt_clear(int irq) +{ + interrupt_clear_mask(irq, 1); +} + +static inline uint32_t interrupt_global_disable(void) +{ + return arch_interrupt_global_disable(); +} + +static inline void interrupt_global_enable(uint32_t flags) +{ + arch_interrupt_global_enable(flags); +} + +#if CONFIG_LIBRARY + +/* temporary fix to remove build warning for testbench that will need shortly + * realigned when Zephyr native APIs are used. + */ +static inline void __irq_local_disable(unsigned long flags) {} +static inline void __irq_local_enable(unsigned long flags) {} + +/* disables all IRQ sources on current core - NO effect on library */ +#define irq_local_disable(flags) \ + do { \ + flags = 0; \ + __irq_local_disable(flags); \ + } while (0) + +/* re-enables IRQ sources on current core - NO effect on library*/ +#define irq_local_enable(flags) \ + __irq_local_enable(flags) + +#else +/* disables all IRQ sources on current core */ +#define irq_local_disable(flags) \ + (flags = interrupt_global_disable()) + +/* re-enables IRQ sources on current core */ +#define irq_local_enable(flags) \ + interrupt_global_enable(flags) +#endif +#endif +#endif /* __SOF_DRIVERS_INTERRUPT_H__ */ diff --git a/xtos/include/rtos/string_macro.h b/xtos/include/rtos/string_macro.h new file mode 100644 index 000000000000..76043b2a47c2 --- /dev/null +++ b/xtos/include/rtos/string_macro.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian <Baofeng.tian@intel.com> + */ + +#ifndef __XTOS_RTOS_STRING_MACRO_H__ +#define __XTOS_RTOS_STRING_MACRO_H__ + +#define Z_STRINGIFY(x) #x +#define STRINGIFY(s) Z_STRINGIFY(s) + +#define _DO_CONCAT(x, y) x ## y +#define _CONCAT(x, y) _DO_CONCAT(x, y) + +#endif /* __XTOS_RTOS_STRING_MACRO_H__ */ diff --git a/xtos/include/sof/compiler_attributes.h b/xtos/include/sof/compiler_attributes.h new file mode 100644 index 000000000000..d961fa990613 --- /dev/null +++ b/xtos/include/sof/compiler_attributes.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2019 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#ifndef __SOF_COMPILER_ATTRIBUTES_H__ +#define __SOF_COMPILER_ATTRIBUTES_H__ + +#define __sparse_cache +#define __sparse_force + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#ifndef __unused +#define __unused __attribute__((unused)) +#endif + +#ifndef __maybe_unused +#define __maybe_unused __attribute__((unused)) +#endif + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif + +#ifndef __section +#define __section(x) __attribute__((section(x))) +#endif + +/* The fallthrough attribute is supported since GCC 7.0 + * and Clang 10.0.0. + * + * Note that Clang sets __GNUC__ == 4 so the GCC version + * test will not be true here, and must go through + * the Clang version test. + */ +#if ((defined(__GNUC__) && (__GNUC__ >= 7)) || \ + (defined(__clang__) && (__clang_major__ >= 10))) && !defined(__CHECKER__) +#define COMPILER_FALLTHROUGH __attribute__((fallthrough)) +#else +#define COMPILER_FALLTHROUGH /* fallthrough */ +#endif + +#endif /* __SOF_COMPILER_ATTRIBUTES_H__ */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt new file mode 100644 index 000000000000..91598a776db0 --- /dev/null +++ b/zephyr/CMakeLists.txt @@ -0,0 +1,634 @@ +# When west is installed, Zephyr's CMake invokes west to list and try to +# compile every Zephyr module that can be found. See +# sof/zephyr/module.yml and +# https://docs.zephyrproject.org/latest/develop/modules.html +if(CONFIG_SOF_FULL_ZEPHYR_APPLICATION) + +if(CONFIG_ZEPHYR_POSIX) + set(ARCH host) + set(PLATFORM "posix") + set(PLATFORM_HEADERS "posix") +else() + # firmware build supports only xtensa arch for now + set(ARCH xtensa) + set(PLATFORM_HEADERS "xtos") +endif() + +# Appends literal with path of the source file relative to the project root +# It is useful if sources in given target need deterministic relative path +# to the actually compiled file. +# __FILE is not always suitable as C standard states that __FILE__ expands to +# input file name, that usually is absolute path what will cause f.e. .rodata +# size to be dependent on where project is physically located on the disk. +function(sof_append_relative_path_definitions target) + get_target_property(sources ${target} SOURCES) + foreach(src ${sources}) + get_filename_component(ABS_PATH ${src} ABSOLUTE) + file(RELATIVE_PATH rel ${PROJECT_SOURCE_DIR} ${ABS_PATH}) + set_property( + SOURCE ${src} + APPEND + PROPERTY COMPILE_DEFINITIONS + RELATIVE_FILE="${rel}") + endforeach() +endfunction() + +define_property(GLOBAL PROPERTY SOF_LLEXT_LAST_TARGET + BRIEF_DOCS "Last LLEXT target" + FULL_DOCS "\ +Building LLEXT targets must be serialized. This property contains the \ +previously added LLEXT module for the establishment of a dependency chain." +) + +# Build an LLEXT module. Provice a module name, a list of sources and an address +# of the .text section as arguments. +function(sof_llext_build module) + set(multi_args SOURCES INCLUDES CFLAGS LIBS LIBS_PATH) + set(single_args LIB) + cmake_parse_arguments(PARSE_ARGV 1 SOF_LLEXT "${options}" "${single_args}" "${multi_args}") + + cmake_path(SET SOF_BASE NORMALIZE ${APPLICATION_SOURCE_DIR}/..) + + add_llext_target(${module} + OUTPUT ${PROJECT_BINARY_DIR}/${module}_llext/${module}.llext + SOURCES ${SOF_LLEXT_SOURCES} + ) + + if(CONFIG_LIBRARY_BUILD_LIB AND NOT("${SOF_LLEXT_LIB}" STREQUAL "")) + file(WRITE ${PROJECT_BINARY_DIR}/${module}_llext/lib_name.txt ${SOF_LLEXT_LIB}) + endif() + + if("${ARCH}" STREQUAL "xtensa") + # This makes sure literals are placed in memory before they are used by + # the L32R instruction. Usually this is guaranteed by the linker script. + # However, since a linker script is not used for LLEXT modules builds, + # correct literal placement is ensured with a compilation option here. + set(SOF_LLEXT_CFLAGS ${SOF_LLEXT_CFLAGS} -mtext-section-literals) + endif() + + target_include_directories(${module}_llext_lib PRIVATE + "${SOF_BASE}/xtos/include" + "${SOF_BASE}/src/include" + "${SOF_BASE}/tools/rimage/src/include" + ) + + target_include_directories(${module}_llext_lib PRIVATE + "${SOF_LLEXT_INCLUDES}" + ) + + target_compile_options(${module}_llext_lib PRIVATE + "${SOF_LLEXT_CFLAGS}" + ) + + target_link_libraries(${module}_llext_lib PRIVATE + "${SOF_LLEXT_LIBS}" + ) + + foreach(lib ${SOF_LLEXT_LIBS}) + set(EXTRA_LIBS ${EXTRA_LIBS} -l${lib}) + endforeach() + + sof_append_relative_path_definitions(${module}_llext_lib) + + add_llext_command(TARGET ${module} + PRE_BUILD + COMMAND ${CMAKE_C_COMPILER} -E ${CMAKE_CURRENT_LIST_DIR}/llext.toml.h -P -DREM= + -I${SOF_BASE} -I${SOF_BASE}src + -imacros ../include/generated/zephyr/autoconf.h + -imacros ../include/generated/uuid-registry.h + -o rimage_config.toml + ) + + if(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE) + set(EXTRA_LINKER_PARAMS -nostdlib -nodefaultlibs -r) + else() + set(EXTRA_LINKER_PARAMS -nostdlib -nodefaultlibs -shared) + endif() + + foreach(path ${SOF_LLEXT_LIBS_PATH}) + llext_link_options(${module} -L${path}) + set(EXTRA_LINKER_PARAMS ${EXTRA_LINKER_PARAMS} -L${path}) + endforeach() + + get_target_property(proc_in_file ${module} lib_output) + get_target_property(proc_out_file ${module} pkg_input) + get_target_property(proc_pkg_file ${module} pkg_output) + set(size_file ${PROJECT_BINARY_DIR}/module_size) + + get_property(last_target GLOBAL PROPERTY SOF_LLEXT_LAST_TARGET) + if(NOT "${last_target}" STREQUAL "") + add_dependencies(${module}_llext_proc ${last_target}) + endif() + set_property(GLOBAL PROPERTY SOF_LLEXT_LAST_TARGET ${module}) + + add_llext_command(TARGET ${module} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -DMODULE=${module} -DZEPHYR_BINARY_DIR=${ZEPHYR_BINARY_DIR} + -P ${SOF_BASE}scripts/cmake/llext_write_uuids.cmake + ) + + add_llext_command(TARGET ${module} + POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} ${SOF_BASE}scripts/llext_link_helper.py -s ${size_file} + --text-addr=${CONFIG_LIBRARY_BASE_ADDRESS} + -c $<TARGET_PROPERTY:bintools,elfconvert_command> + -f ${proc_in_file} -o ${proc_out_file} ${CMAKE_C_COMPILER} -- + ${EXTRA_LINKER_PARAMS} $<TARGET_OBJECTS:${module}_llext_lib> ${EXTRA_LIBS} + ) + + add_llext_command(TARGET ${module} + POST_PKG + COMMAND ${PYTHON_EXECUTABLE} ${SOF_BASE}scripts/llext_offset_calc.py + -i ${proc_pkg_file} -s ${size_file} + ) +endfunction() + +# Initial SOF module will contain +# +# 1. Application logic - pipeline, audio components, IPC processing, topology +# 2. IP drivers - SSP, DMIC, PM, IPC will transition to Zephyr directly over +# time and be removed from the SOF repo. +# 3. Platform IP - PM, init, clocks, IRQs will transition directly to Zephyr +# over time and be removed from SOF repo. +# 4. RTOS logic - scheduler, allocator, notifier - as with 2 & 3. +zephyr_interface_library_named(SOF) + +# SOF source paths. +cmake_path(SET sof_top_dir NORMALIZE "${CMAKE_CURRENT_SOURCE_DIR}/..") +set(SOF_SRC_PATH "${sof_top_dir}/src") + +set(SOF_PLATFORM_PATH "${SOF_SRC_PATH}/platform") +set(SOF_DRIVERS_PATH "${SOF_SRC_PATH}/drivers") +set(SOF_TRACE_PATH "${SOF_SRC_PATH}/trace") + +set(RIMAGE_TOP ${sof_top_dir}/tools/rimage) + +# Save path to rimage configuration files in cmake cache for later use by +# rimage during the "west sign" stage +set(RIMAGE_CONFIG_PATH ${RIMAGE_TOP}/config CACHE PATH + " Path to rimage board configuration files") + +# default SOF includes +target_include_directories(SOF INTERFACE ${RIMAGE_TOP}/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_top_dir}/third_party/include) +target_include_directories(SOF INTERFACE ${sof_top_dir}/zephyr/include) + +# SOF module init +zephyr_library_named(modules_sof) + +# Zephyr C++ code requires 14 or newer standard +set_property(TARGET modules_sof PROPERTY CXX_STANDARD 17) + +zephyr_include_directories(include) +zephyr_include_directories(${ZEPHYR_BASE}/kernel/include) +zephyr_include_directories(${ZEPHYR_BASE}/arch/${ARCH}/include) +zephyr_include_directories(${SOF_SRC_PATH}/include/sof/audio/module_adapter/iadk/) +zephyr_include_directories(${SOF_SRC_PATH}/include/sof/audio/module_adapter/library/) + +# SOC level sources +# Files that are commented may not be needed. + + +# New, "de-centralized Zephyr" way. Requires "is_zephyr()" conditionals in +# the decentralized CMakeLists.txt files shared with XTOS. + +# XTOS duplicate in sof/scripts/misc.cmake; keep in sync +macro(is_zephyr ret) + if(CONFIG_ZEPHYR_SOF_MODULE) + set(${ret} TRUE) + else() + set(${ret} FALSE) + endif() +endmacro() + +# Wrappers for compatibility and re-use of existing, XTOS CMake files. +# Do NOT use these macros in this file or in any other Zephyr-specific +# CMake code. +macro(add_local_sources target) + if (NOT "${target}" STREQUAL "sof") + message(FATAL_ERROR "add_local_sources() target is not 'sof'") + endif() + zephyr_library_sources(${ARGN}) +endmacro() +macro(add_local_sources_ifdef condition target) + if (NOT "${target}" STREQUAL "sof") + message(FATAL_ERROR "add_local_sources_ifdef() target is not 'sof'") + endif() + zephyr_library_sources_ifdef(${condition} ${ARGN}) +endmacro() +macro(sof_list_append_ifdef feature_toggle list) + if(${${feature_toggle}}) + list(APPEND ${list} ${ARGN}) + endif() +endmacro() + +# directories with auxiliary modules need to be listed first +# - llext dependencies need to added to linkage first +add_subdirectory(../src/math/ math_unused_install/) + +# remaining directories (in alphabetical order) +add_subdirectory(../src/audio/ audio_unused_install/) +add_subdirectory(../src/debug/ debug_unused_install/) +add_subdirectory(../src/idc/ idc_unused_install/) +add_subdirectory(../src/init/ init_unused_install/) +add_subdirectory(../src/ipc/ ipc_unused_install/) +add_subdirectory(../src/lib/ lib_unused_install/) +add_subdirectory(../src/library_manager/ library_manager_unused_install/) +add_subdirectory(../src/logging/ logging_unused_install/) +add_subdirectory(../src/probe/ probes_unused_install/) +add_subdirectory(../src/samples/ samples_unused_install/) +add_subdirectory(../src/schedule/ schedule_unused_install/) +add_subdirectory(../src/trace/ trace_unused_install/) +add_subdirectory(test/) + +# Old way below: all .c files added by this giant CMake file. + +# Intel TGL and CAVS 2.5 platforms +if (CONFIG_SOC_SERIES_INTEL_CAVS_V25) + + # Driver sources + zephyr_library_sources_ifdef(CONFIG_INTEL_HDA + ${SOF_DRIVERS_PATH}/intel/hda/hda-dma.c + ) + + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/intel/cavs/platform.c + lib/dma.c + ) + + set(PLATFORM "tigerlake") + zephyr_include_directories(${SOF_PLATFORM_PATH}/intel/cavs/include) +endif() + +# Intel ACE 1.5 and newer platforms +if (CONFIG_SOC_SERIES_INTEL_ADSP_ACE) + + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/intel/ace/platform.c + lib/clk.c + lib/dma.c + ) + + zephyr_library_sources_ifdef(CONFIG_SOC_ACE15_MTPM + ${SOF_PLATFORM_PATH}/meteorlake/lib/clk.c + ) + + zephyr_library_sources_ifdef(CONFIG_SOC_ACE20_LNL + ${SOF_PLATFORM_PATH}/lunarlake/lib/clk.c + ) + + zephyr_library_sources_ifdef(CONFIG_SOC_ACE30 + ${SOF_PLATFORM_PATH}/ace30/lib/clk.c + ) + + zephyr_library_sources_ifdef(CONFIG_SOC_ACE40 + ${SOF_PLATFORM_PATH}/novalake/lib/clk.c + ) + + zephyr_library_sources_ifdef(CONFIG_SOF_VREGIONS + lib/vpage.c + lib/vregion.c + ) + + zephyr_library_sources_ifdef(CONFIG_VIRTUAL_HEAP + lib/regions_mm.c + ) + + zephyr_library_sources_ifdef(CONFIG_CAVS_LPS + ${SOF_PLATFORM_PATH}/intel/ace/lps_wait.c + ) + + zephyr_library_sources_ifdef(CONFIG_LL_WATCHDOG + ${SOF_PLATFORM_PATH}/intel/ace/lib/watchdog.c + ) + + if (CONFIG_SOC_ACE15_MTPM) + set(PLATFORM "meteorlake") + elseif(CONFIG_SOC_ACE20_LNL) + set(PLATFORM "lunarlake") + elseif(CONFIG_SOC_ACE30) + set(PLATFORM "ace30") + elseif(CONFIG_SOC_ACE40) + set(PLATFORM "novalake") + endif() + + zephyr_include_directories(${SOF_PLATFORM_PATH}/intel/ace/include) + zephyr_include_directories(${SOF_PLATFORM_PATH}/${PLATFORM}/include) +endif() + +# NXP IMX8 platforms +if (CONFIG_SOC_MIMX8QM6_ADSP OR CONFIG_SOC_MIMX8QX6_ADSP) + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/imx/ipc.c + ) + + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx8/platform.c + ${SOF_PLATFORM_PATH}/imx8/lib/clk.c + ) + + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + lib/dma.c + ) + + set(PLATFORM "imx8") +endif() + +if (CONFIG_SOC_MIMX8ML8_ADSP) + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/imx/ipc.c + ) + + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx8m/platform.c + ${SOF_PLATFORM_PATH}/imx8m/lib/clk.c + ) + + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + lib/dma.c + ) + + set(PLATFORM "imx8m") +endif() + +if (CONFIG_SOC_MIMX8ML8_M7) + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx8m_cm7/platform.c + ${SOF_PLATFORM_PATH}/imx8m_cm7/lib/clk.c + lib/dma.c + ) + + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/imx/ipc.c + ) + + # SOF-specific linker script additions + zephyr_linker_sources(DATA_SECTIONS ${sof_top_dir}/src/platform/imx8m_cm7/linker/data-sections.ld) + + set(PLATFORM "imx8m_cm7") + + add_custom_target(zephyr.ri ALL + DEPENDS ${CMAKE_BINARY_DIR}/zephyr/zephyr.ri) + + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/zephyr/zephyr.ri + COMMAND west sign --if-tool-available --tool rimage + --build-dir ${CMAKE_BINARY_DIR} ${WEST_SIGN_OPTS} + DEPENDS ${CMAKE_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME}) + + board_set_rimage_target(imx8m_cm7) + +endif() + +if (CONFIG_SOC_MIMX8UD7_ADSP) + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/imx/ipc.c + ) + + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx8ulp/platform.c + ${SOF_PLATFORM_PATH}/imx8ulp/lib/clk.c + ) + + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + lib/dma.c + ) + + set(PLATFORM "imx8ulp") +endif() + +if (CONFIG_SOC_MIMX9352_A55) + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx93_a55/platform.c + ${SOF_PLATFORM_PATH}/imx93_a55/lib/clk.c + lib/dma.c + ) + + # Drivers + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/imx/ipc.c + ) + + set(PLATFORM "imx93_a55") +endif() + +if (CONFIG_SOC_MIMX9596_M7) + + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx95/platform.c + ${SOF_PLATFORM_PATH}/imx95/lib/clk.c + lib/dma.c + ) + + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/imx/ipc.c + ) + + # SOF-specific linker script additions + zephyr_linker_sources(DATA_SECTIONS ${sof_top_dir}/src/platform/imx95/linker/data-sections.ld) + + set(PLATFORM "imx95") + + # no longer done in Zephyr and should be handled by SOF + # See [1], [2], and [3] for more context + # + # [1]: https://github.com/zephyrproject-rtos/zephyr/issues/91061 + # [2]: https://github.com/zephyrproject-rtos/zephyr/pull/97946 + # [3]: https://github.com/zephyrproject-rtos/zephyr/pull/97988 + add_custom_target(zephyr.ri ALL + DEPENDS ${CMAKE_BINARY_DIR}/zephyr/zephyr.ri) + + add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/zephyr/zephyr.ri + COMMAND west sign --if-tool-available --tool rimage + --build-dir ${CMAKE_BINARY_DIR} ${WEST_SIGN_OPTS} + DEPENDS ${CMAKE_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME}) + + board_set_rimage_target(imx95) +endif() + +# AMD RMB platforms +if (CONFIG_SOC_ACP_6_0) + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/amd/common/acp_bt_dai.c + ${SOF_DRIVERS_PATH}/amd/common/acp_dma.c + ${SOF_DRIVERS_PATH}/amd/common/acp_dmic_dai.c + ${SOF_DRIVERS_PATH}/amd/common/acp_dmic_dma.c + ${SOF_DRIVERS_PATH}/amd/common/acp_sp_dma.c + ${SOF_DRIVERS_PATH}/amd/common/ipc.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_bt_dma.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_dma.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_dmic_dma.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_hs_dai.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_hs_dma.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_sp_dai.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/acp_sp_dma.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/interrupt.c + ${SOF_DRIVERS_PATH}/amd/rembrandt/ipc.c + ) + + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/amd/rembrandt/platform.c + ${SOF_PLATFORM_PATH}/amd/rembrandt/lib/clk.c + ${SOF_PLATFORM_PATH}/amd/rembrandt/lib/dai.c + ${SOF_PLATFORM_PATH}/amd/rembrandt/lib/dma.c + ) + + # SOF core infrastructure - runs on top of Zephyr + zephyr_library_sources( + ${SOF_SRC_PATH}/drivers/interrupt.c + ) + + zephyr_include_directories(${SOF_PLATFORM_PATH}/amd/rembrandt/include) + zephyr_include_directories(${SOF_PLATFORM_PATH}/amd/common/include) + zephyr_include_directories(${SOF_PLATFORM_PATH}/amd/rembrandt/include/arch) + + set(PLATFORM "acp_6_0") +endif() + +if (CONFIG_SOC_ACP_7_0) + # Platform sources + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/amd/rembrandt/ipc.c + ${SOF_DRIVERS_PATH}/amd/common/ipc.c + ${SOF_PLATFORM_PATH}/amd/acp_7_0/platform.c + ${SOF_PLATFORM_PATH}/amd/acp_7_0/lib/clk.c + ) + zephyr_library_sources(lib/dma.c) + zephyr_include_directories(${SOF_PLATFORM_PATH}/amd/acp_7_0/include) + zephyr_include_directories(${SOF_PLATFORM_PATH}/amd/common/include) + zephyr_include_directories(${SOF_PLATFORM_PATH}/amd/acp_7_0/include/arch) + + set(PLATFORM "acp_7_0") +endif() + +if (CONFIG_SOC_FAMILY_MTK) + set(PLATFORM "mtk") + + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/mtk/platform.c + ${SOF_PLATFORM_PATH}/mtk/dai.c + ${SOF_DRIVERS_PATH}/generic/dummy-dma.c + ${SOF_SRC_PATH}/drivers/mediatek/afe/afe-memif.c + ${SOF_SRC_PATH}/drivers/mediatek/afe/afe-dai.c + ${SOF_SRC_PATH}/drivers/mediatek/afe/afe-drv.c + ) +endif() + +# Building for native_posix-based whole-OS host emulator +zephyr_library_sources_ifdef(CONFIG_ZEPHYR_POSIX + ${SOF_PLATFORM_PATH}/posix/dma.c + ${SOF_PLATFORM_PATH}/posix/dai.c + ${SOF_PLATFORM_PATH}/posix/ipc.c + ${SOF_PLATFORM_PATH}/posix/posix.c + ${SOF_PLATFORM_PATH}/posix/fuzz.c +) + +if (CONFIG_BOARD_QEMU_XTENSA) + set(PLATFORM "qemu_xtensa") + zephyr_library_sources(${SOF_PLATFORM_PATH}/qemu_xtensa/platform.c) +endif() + +if(NOT DEFINED PLATFORM) + message(FATAL_ERROR "PLATFORM is not defined, check your Kconfiguration?") +endif() +zephyr_include_directories(${SOF_PLATFORM_PATH}/${PLATFORM}/include) + +if(CONFIG_SOF_USERSPACE_INTERFACE_DMA) + zephyr_library_sources(syscall/sof_dma.c) + zephyr_syscall_header(include/sof/lib/sof_dma.h) +endif() + +# Mandatory Files used on all platforms. +# Commented files will be added/removed as integration dictates. +zephyr_library_sources( + + # SOF core infrastructure - runs on top of Zephyr + ${SOF_SRC_PATH}/arch/xtensa/drivers/cache_attr.c + + # Bridge wrapper between SOF and Zephyr APIs - Will shrink over time. + wrapper.c + edf_schedule.c + schedule.c + lib/alloc.c + lib/cpu.c + lib/pm_runtime.c + lib/userspace_helper.c + + # Common library functions - Will be moved to Zephyr over time + lib.c +) + +# SOF module interface functions +add_subdirectory(../src/module module_unused_install/) + +if(CONFIG_COLD_STORE_EXECUTE_DRAM) +zephyr_library_sources_ifdef(CONFIG_FAST_GET lib/fast-get.c) +endif() + +# Optional SOF sources - depends on Kconfig - WIP + +zephyr_library_sources_ifdef(CONFIG_DW_DMA + ${SOF_DRIVERS_PATH}/dw/dma.c +) + +zephyr_library_sources_ifdef(CONFIG_SOF_BOOT_TEST + boot_test.c +) + +zephyr_library_sources_ifdef(CONFIG_SHELL + sof_shell.c +) + +zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/audio/module_adapter/module/generic.h) +zephyr_syscall_header(${SOF_SRC_PATH}/include/sof/lib/fast-get.h) + +zephyr_library_link_libraries(SOF) +target_link_libraries(SOF INTERFACE zephyr_interface) + +# Linker snippet for the UUID table +zephyr_linker_sources("ROM_SECTIONS" uuid-snippet.ld) + +# Setup SOF directories +set(SOF_ROOT_SOURCE_DIRECTORY ${sof_top_dir}) +set(SOF_ROOT_BINARY_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + +# This generated/ directory is shared with Zephyr. +# PROJECT_BINARY_DIR is build/zephyr/ +set(GENERATED_DIRECTORY ${PROJECT_BINARY_DIR}/include/generated) + +set(VERSION_H_PATH ${GENERATED_DIRECTORY}/sof_versions.h) + +find_package(Python3 COMPONENTS Interpreter) +set(PYTHON3 "${Python3_EXECUTABLE}") + +if (NOT CONFIG_COMPILER_INLINE_FUNCTION_OPTION) +target_compile_options(SOF INTERFACE -fno-inline-functions) +endif() + +# SOF needs `typeof`, `__VA_ARGS__` and maybe other GNU C99 +# extensions. TODO other flags required ? +target_compile_options(SOF INTERFACE $<$<COMPILE_LANGUAGE:C,ASM>: -std=gnu99>) + +# Toolchain info +add_definitions(-DXCC_TOOLS_VERSION="${ZEPHYR_TOOLCHAIN_VARIANT}" -DCC_OPTIMIZE_FLAGS="${OPTIMIZATION_FLAG}") + +# create version information +include(../scripts/cmake/version.cmake) + +include(../scripts/cmake/uuid-registry.cmake) + +# Create Trace realtive file paths +sof_append_relative_path_definitions(modules_sof) + +endif() # CONFIG_SOF_FULL_ZEPHYR_APPLICATION diff --git a/zephyr/FindZephyr-sdk.cmake b/zephyr/FindZephyr-sdk.cmake new file mode 100644 index 000000000000..27c8971c4199 --- /dev/null +++ b/zephyr/FindZephyr-sdk.cmake @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2022, Nordic Semiconductor ASA + +# This is copied from the much bigger +# zephyr/cmake/modules/FindZephyr-sdk.cmake. + +find_package(Zephyr-sdk ${Zephyr-sdk_FIND_VERSION} REQUIRED QUIET CONFIG PATHS + /opt/toolchains # in zephyr-build but not in zephyr.git, go figure + /usr + /usr/local + /opt + $ENV{HOME} + $ENV{HOME}/.local + $ENV{HOME}/.local/opt + $ENV{HOME}/bin) + +if(Zephyr-sdk_FOUND) + execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${ZEPHYR_SDK_INSTALL_DIR}") +else() + message(FATAL_ERROR "Zephyr SDK not found") +endif() diff --git a/zephyr/Kconfig b/zephyr/Kconfig new file mode 100644 index 000000000000..f1d1896c4234 --- /dev/null +++ b/zephyr/Kconfig @@ -0,0 +1,285 @@ +config SOF_FULL_ZEPHYR_APPLICATION + bool "Build full SOF Zephyr application" + default y + help + Top-level build option to enable full build of the SOF application + on top of Zephyr. This should be set to no only for unit test and + such special build targets. + +config SOF_STAGING + bool "Enable SOF staging features and modules" + help + SOF staging features are not ready for production but are + upstream to enable developers to continue development in order + to bring the feature to production level faster using the + upstream codebase. + +rsource "../Kconfig.sof" + +config SOF_USERSPACE + bool "Enable SOF support for userspace modules" + help + SOF userspace modules support will enable modules to run in DP + processing mode as userspace code and data. This feature is WIP + and is not yet ready for production, for developers only. + +config SOF_USERSPACE_INTERFACE_DMA + bool "Enable SOF DMA interface to userspace threads" + depends on USERSPACE + help + Allow user-space threads to use the SOF DMA interface. + +config SOF_USERSPACE_LL + bool "Run Low-Latency pipelines in userspace threads" + depends on USERSPACE + select SOF_USERSPACE_INTERFACE_DMA + help + Run Low-Latency (LL) pipelines in userspace threads. This adds + memory protection between operating system resources and + audio application threads. + If unsure, select "N". + +config SOF_ZEPHYR_HEAP_CACHED + bool "Cached Zephyr heap for SOF memory non-shared zones" + default y if CAVS || ACE + help + Enable cached heap by mapping cached SOF memory zones to different + Zephyr sys_heap objects and enable caching for non-shared zones. + +config SOF_ZEPHYR_HEAP_SIZE + hex "Size of the Zephyr heap for SOF" + default 0x40000 if VIRTUAL_HEAP + default 0xF0000 if SOC_ACE15_MTPM || SOC_ACE20_LNL + default 0xD0000 if SOC_ACE30 || SOC_ACE40 + default 0x0 + help + Support scaling of the heap size for different platforms and different types + of heaps. This is the default heap size for most users. + TODO: Currently this setting is only available on platforms with a + simplified heap size configuration. i.e. a single macro that defines the + heap size. This is not the case for all platforms. + NOTE: Keep in mind that the heap size should not be greater than the physical + memory size of the system defined in DT (and this includes baseFW text/data). + +config SOF_USERSPACE_USE_SHARED_HEAP + bool "Use shared heap for SOF userspace modules" + depends on USERSPACE + help + When set a shared heap will be used for audio buffers between SOF + kernel and userspace modules. + +config SOF_ZEPHYR_SHARED_BUFFER_HEAP_SIZE + hex "Size of the shared buffer heap for SOF userspace modules" + default 0x0 if !SOF_USERSPACE_USE_SHARED_HEAP + default 0x1E000 if SOC_ACE15_MTPM || SOC_ACE20_LNL + default 0x10000 if SOC_ACE30 + default 0x0 + depends on USERSPACE + help + The size of the zephyr heap portion designated as the shared buffer heap. + This heap is shared between the sof and userspace modules. It is used exclusively for + allocating audio buffers between the kernel and userspace modules. + NOTE: Keep in mind that the shared heap size should not be greater than the + heap size. + +config VIRTUAL_HEAP_EXTENDED + bool "Extend the Virtual Heap configuration with additional buffers" + depends on MM_DRV_INTEL_ADSP_MTL_TLB + default y + help + Enable additional Virtual Heap buffers. Some configurations need this + while others need the memory for other purposes, e.g. for the virtual + page / virtual region storage. + +config SOF_ZEPHYR_VIRTUAL_HEAP_REGION_SIZE + hex "Size in bytes of virtual memory region for virtual heap shared for all cores" + depends on MM_DRV_INTEL_ADSP_MTL_TLB + default 0x140000 if VIRTUAL_HEAP_EXTENDED + default 0x100000 + help + This config defines size of virtual heap region shared between all cores + +config SOF_USERSPACE_USE_DRIVER_HEAP + bool "Use driver heap for SOF userspace modules" + depends on USERSPACE + help + When selected, multiple instances of the same userspace module will share + a private heap created for that module's driver. Otherwise, each module + instance will have its own independent private heap. + +config SOF_ZEPHYR_USERSPACE_MODULE_HEAP_SIZE + hex "Size of the private heap created for each userspace module" + default 0x1000 + depends on USERSPACE + help + The size of the private heap created for each userspace module. Each userspace + module has its own independent heap to which only it has access. This heap is + shared between instances of the same module. + +config SOF_USERSPACE_PROXY + bool "Use userspace proxy to support userspace modules" + select SOF_USERSPACE_USE_DRIVER_HEAP + select SOF_USERSPACE_USE_SHARED_HEAP + help + When set, userspace modules are launched inside a container created by userspace proxy. + It is responsible for forwarding module function calls coming from sof running in + kernelspace to the module code executed with user privileges. + +config SOF_USERSPACE_MOD_IPC_BY_DP_THREAD + bool "Handle modules IPC in DP thread" + depends on SOF_USERSPACE_PROXY + help + When enabled, IPC requests targeted to a userspace module are executed + in its DP thread instead of the shared user worker thread. + +config SOF_USERSPACE_PROXY_WORKER_STACK_SIZE + int "Userspace IPC worker stack size" + default 4096 + help + Size of the stack used by the IPC worker thread created by the + userspace proxy. This worker handles IPC requests for modules + running in userspace. + +config SOF_USERSPACE_APPLICATION + bool + default USERSPACE && !SOF_USERSPACE_PROXY + depends on SOF_VREGIONS + help + Not manually settable. This is effectively a shortcut to replace numerous + checks for (CONFIG_USERSPACE && !CONFIG_SOF_USERSPACE_PROXY) + +config SOF_VPAGE_MAX_ALLOCS + int "Number of virtual memory page allocations" + default 128 + help + This setting defines the maximum number of virtual memory page + allocations that can be tracked. Each allocation represents a + contiguous block of virtual memory allocated from the virtual memory + region. This API isn't intended for end-user allocations, instead it + should be used by the framework to allocate memory, which is then + used, e.g. to create one or multiple heap allocators in it. Increasing + this number allows for more simultaneous allocations, but also + increases the memory overhead for tracking these allocations. + +config ZEPHYR_NATIVE_DRIVERS + bool "Use Zephyr native drivers" + help + Enable Zephyr native api drivers for host and dai audio components + host-zephyr + dai-zephyr + will be used instead of legacy xtos version. + +config DMA_DOMAIN + bool "Enable the usage of 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 PIPELINE_2_0 + bool "Enable pipeline 2.0 changes" + depends on IPC_MAJOR_4 + default y if ACE + help + This flag enables changes to new pipeline structure, known as pipeline2_0 + It is required for certain new features, like DP_SCHEDULER. + +config ZEPHYR_DP_SCHEDULER + bool "use Zephyr thread based DP scheduler" + default y if ACE + depends on IPC_MAJOR_4 + depends on ZEPHYR_SOF_MODULE + depends on ACE + depends on PIPELINE_2_0 + imply XTENSA_HIFI_SHARING if XTENSA_HIFI + help + Enable Data Processing preemptive scheduler based on + Zephyr preemptive threads. + DP modules can be located in dieffrent cores than LL pipeline modules, may have + different tick (i.e. 300ms for speech reccognition, etc.) + +config CROSS_CORE_STREAM + bool "Enable cross-core connected pipelines" + default y if IPC_MAJOR_4 + help + Enables support for pipelines from different cores to be + connected together cross-core. So stream can travel from one + core to another. Note, this is different from "multicore" + support. In SOF "multicore" support means different streams + can be processed on different cores, however, each stream + is processed entirely on single core. + +config SOF_BOOT_TEST_ALLOWED + bool "Enable SOF boot-time testing" + help + boot-time testing enabled if supported by the platform + +config SOF_BOOT_TEST_SUPPORTED + bool "Platform supports boot-time testing" + default y + help + boot-time testing supported by the platform + +config SOF_BOOT_TEST + bool + depends on ZTEST + default y + help + Run tests during boot. This enables an SOF boot-time self-test. When + enabled, the resulting image will run a number of self-tests when the + first global IPC command is received, i.e. when SOF is completely + initialized. After that SOF will continue running and be usable as + usual. + +config SOF_BOOT_TEST_STANDALONE + bool "enable tests at boot time that are run instead of SOF main" + select SOF_BOOT_TEST + select ZTEST + help + Run extended set of tests at boot that can use IPC and interfere + with system state. Normal IPC handling of the SOF application + is disabled to allow more complex tests to run. + +config SOF_ZEPHYR_NO_SOF_CLOCK + bool + help + Do not use SOF clk.h interface to set the DSP clock frequency. + Requires implementation of platform/lib/clk.h. + +config SOF_VREGIONS + bool "Enable virtual memory regions" + default y if ACE && !ACE_VERSION_1_5 && !ACE_VERSION_2_0 + depends on ACE + help + Enable the virtual regions memory allocator for pipeline resource management. + This provides a way to manage memory resources for audio pipelines, + including + 1) multiple pipeline static lifetime allocations. + 2) runtime pipeline allocations. + +config VIRTUAL_HEAP + bool "Use virtual memory heap to allocate buffers" + default y if ACE + depends on ACE + help + Enabling this option will use the virtual memory heap allocator to allocate buffers. + It is based on a set of buffers whose size is predetermined. + +config STACK_SIZE_EDF + int "EDF scheduler stack size" + default 8192 + help + EDF scheduler work-queue thread stack size. Keep a power of 2. + +config STACK_SIZE_IPC_TX + int "IPC sender stack size" + default 2048 + help + IPC sender work-queue thread stack size. Keep a power of 2. diff --git a/zephyr/README b/zephyr/README new file mode 100644 index 000000000000..79f4f7edc34d --- /dev/null +++ b/zephyr/README @@ -0,0 +1,56 @@ +SOF with Zephyr RTOS +==================== + +SOF currently uses the Cadence Xtos/HAL and it's own kernel functions as +its RTOS. SOF is moving to use Zephyr as it's RTOS in parallel to current +releases using xtos. + +The initial "alpha" of SOF on Zephyr will use the Zephyr RTOS for boot, IRQs, +scheduling and memory allocation. Subsequent release will use more Zephyr +functionality as code is moved from SOF to Zephyr (i.e. EDF scheduler updates +copied from SOF to Zephyr). + +Building SOF on Zephyr +====================== + +Section promoted to +https://thesofproject.github.io/latest/getting_started/build-guide/build-with-zephyr.html + +Testing on Qemu +=============== + +Get the SOF qemu sof-v4.2 branch here. + +git@github.com:thesofproject/qemu.git + +Configure as + +./configure' '--prefix=.' '--target-list=xtensa-softmmu,x86_64-softmmu' \ + '--enable-gtk' '--enable-sdl' '--enable-spice' \ + '--audio-drv-list=alsa' '--enable-libusb' \ + '--enable-usb-redir' '--enable-coroutine-pool' \ + '--disable-opengl' '--enable-fdt' + + Then run make. + +FW can be tested as follows using the qemu helper script. + + ./xtensa-host.sh apl \ + -r ../../sof/sof/build_apl_gcc/src/arch/xtensa/rom-apl.bin \ + -k ../../zephyrproject/zephyr/build/zephyr/zephyr.ri + +Where -r and -k are used to specify the ROM and kernel files. + +The ROMS can be built from the SOF repo by running + +./scripts/xtensa-build-all.sh -r -a + +Using console +------------- + +Using logging and simulator backend with processing printk (LOG_PRINTK) +can bring console in qemu. + + - Enable xtensa simulator logging backend (LOG_BACKEND_XTENSA_SIM). + - Enable printk processing(LOG_PRINTK) + - Add "-semihosting" to qemu command line. Make sure it goes through scripts to real qemu. diff --git a/zephyr/boot_test.c b/zephyr/boot_test.c new file mode 100644 index 000000000000..020072856ecb --- /dev/null +++ b/zephyr/boot_test.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#include <zephyr/logging/log.h> +#include <sof/boot_test.h> + +#include <zephyr/ztest.h> + +LOG_MODULE_REGISTER(sof_boot_test, LOG_LEVEL_DBG); + +ZTEST_SUITE(sof_boot, NULL, NULL, NULL, NULL, NULL); + +void sof_run_boot_tests(void) +{ + ztest_run_all(NULL, false, 1, 1); +} diff --git a/zephyr/docker-build.sh b/zephyr/docker-build.sh new file mode 100755 index 000000000000..fa54fe318d87 --- /dev/null +++ b/zephyr/docker-build.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2021 Intel Corporation. All rights reserved. + +# "All problems can be solved by another level of indirection" +# Ideally, this script would not be needed. +# +# Minor adjustments to the docker image provided by the Zephyr project. + +set -e +set -x + +unset ZEPHYR_BASE + +# Make sure we're in the right place +test -e ./sof/scripts/xtensa-build-zephyr.py + +# See .github/workflows/zephyr.yml +# /opt/sparse is the current location in the zephyr-build image. +# Give any sparse in the workspace precedence. +PATH="$(pwd)"/sparse:/opt/sparse/bin:"$PATH" +command -V sparse || true +: REAL_CC="$REAL_CC" + + +# TODO: move all code to a function +# https://github.com/thesofproject/sof-test/issues/740 + + +# Zephyr's CI has complex use cases and considers FindZephyr-sdk.cmake +# autodetection to be too unpredictable and risky. So in these docker images, +# they install the SDK in /opt/toolchains/ to *avoid autodetection on +# purpose*. By design, this forces Zephyr CI to hardcode ZEPHYR_SDK_INSTALL_DIR +# everywhere (see for instance +# https://github.com/zephyrproject-rtos/zephyr/commit/d6329386e9). But we +# already hardcode the docker image version (currently in +# zephyr/docker-run.sh). Our use case is simple, immutable and safe and we +# don't need to version _twice_ what is for us the same thing. Creating these +# symlinks restores the convenient autodetection so this script can be easily +# re-used with any docker image version. +ls -ld /opt/toolchains/zephyr-sdk-* +ln -s /opt/toolchains/zephyr-sdk-* ~/ || true + +# Make sure FindZephyr-sdk.cmake returns the highest version. For instance, +# the old container version 0.18.4 had two SDKs installed: ZSDK_VERSION=0.12.4 +# and ZSDK_ALT_VERSION=0.13.1. Back then, ZEPHYR_SDK_INSTALL_DIR pointed at the +# older one! +unset ZEPHYR_SDK_INSTALL_DIR + +# CMake v3.21 changed the order object files are passed to the linker. +# This makes builds before that version not reproducible. +# To save time don't install if recent enough. + +if test -e .west || test -e zephyr; then + init_update='' +else + init_update='-u' +fi + +# To investigate what went wrong enable the trailing comment. +# This cannot be enabled by default for automation reasons. +./sof/scripts/xtensa-build-zephyr.py $init_update --no-interactive "$@" # || /bin/bash diff --git a/zephyr/docker-run.sh b/zephyr/docker-run.sh new file mode 100755 index 000000000000..e71e266d52b8 --- /dev/null +++ b/zephyr/docker-run.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2022 Intel Corporation. All rights reserved. + +# set -x + +# Tip: if you're not really sure what image version you're using, +# invoke this script with sample commands like these: +# +# ./sof/zephyr/docker-run.sh ls -l /opt/toolchains/ +# ./sof/zephyr/docker-run.sh /opt/sparse/bin/sparse --version +# ./sof/zephyr/docker-run.sh /bin/bash +# +# etc. +# https://github.com/zephyrproject-rtos/docker-image/commits/master +# +# "latest" is just the default tag used when you don't specify any. To +# 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.26.6 +# ghcr.io/zephyrproject-rtos/zephyr-build:latest +# +# "latest" is just a regular tag like "v0.26.6", it may or many not name +# the most recent image. +# +# To automatically restore the official "latest" tag, just delete it: +# +# docker image rm ghcr.io/zephyrproject-rtos/zephyr-build:latest +# +# (The actual image stays in the docker cache, only the tag is deleted) + +set -e + +SOF_TOP="$(cd "$(dirname "$0")"/.. && /bin/pwd)" + +main() +{ + # Log container versions + # Header + docker images --digests | grep REPOSITORY + docker images --digests | grep -i zephyr | sort + + if tty --quiet; then + SOF_DOCKER_RUN="$SOF_DOCKER_RUN --tty" + fi + + cd "$SOF_TOP" + + run_command lsb_release -a + set -x + run_command "$@" +} + +run_command() +{ + # zephyr-lite:v0.29.0 has /opt/toolchains/zephyr-sdk-1.0.0 + # zephyr-lite:v0.29.0 is based on zephyr-build:v0.29.0 + # https://hub.docker.com/r/zephyrprojectrtos/zephyr-build/tags + # https://hub.docker.com/r/thesofproject/zephyr-lite/tags + # + # Keep this SDK version identical to the one in + # .github/workflows/zephyr.yml#Windows + docker run -i -v "$(west topdir)":/zep_workspace \ + --workdir /zep_workspace \ + $SOF_DOCKER_RUN \ + --env REAL_CC --env http_proxy --env https_proxy \ + thesofproject/zephyr-lite:v0.29.0 \ + ./sof/scripts/sudo-cwd.sh "$@" +} + +main "$@" diff --git a/zephyr/edf_schedule.c b/zephyr/edf_schedule.c new file mode 100644 index 000000000000..1a0231426c27 --- /dev/null +++ b/zephyr/edf_schedule.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> + +#include <sof/audio/component.h> +#include <rtos/alloc.h> +#include <rtos/task.h> +#include <stdint.h> +#include <sof/schedule/edf_schedule.h> +#include <rtos/wait.h> + +#include <zephyr/kernel.h> +#include <zephyr/sys_clock.h> + +static struct k_work_q edf_workq; +static K_THREAD_STACK_DEFINE(edf_workq_stack, CONFIG_STACK_SIZE_EDF); + +/* + * since only IPC is using the EDF scheduler - we schedule the work in the + * next timer_domain time slice + */ +#define EDF_SCHEDULE_DELAY 0 + +static void edf_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct task *task = CONTAINER_OF(dwork, struct task, z_delayed_work); + + task->state = SOF_TASK_STATE_RUNNING; + + task->state = task_run(task); + + if (task->state == SOF_TASK_STATE_RESCHEDULE) { + uint64_t deadline = task_get_deadline(task); + uint64_t now = k_uptime_ticks(); + k_timeout_t timeout = K_MSEC(0); + + if (deadline > now) + timeout = K_TICKS(deadline - now); + + k_work_reschedule_for_queue(&edf_workq, + &task->z_delayed_work, + timeout); + task->state = SOF_TASK_STATE_QUEUED; + } else { + task_complete(task); + task->state = SOF_TASK_STATE_COMPLETED; + } +} + +/* schedule task */ +static int schedule_edf_task(void *data, struct task *task, uint64_t start, + uint64_t period) +{ + /* start time is microseconds from now */ + k_timeout_t start_time = K_USEC(start + EDF_SCHEDULE_DELAY); + + k_work_reschedule_for_queue(&edf_workq, + &task->z_delayed_work, + start_time); + + task->state = SOF_TASK_STATE_QUEUED; + return 0; +} + +static int schedule_edf_task_cancel(void *data, struct task *task) +{ + if (task->state == SOF_TASK_STATE_QUEUED) { + k_work_cancel_delayable(&task->z_delayed_work); + + /* delete task */ + task->state = SOF_TASK_STATE_CANCEL; + } + + return 0; +} + +static int schedule_edf_task_running(void *data, struct task *task) +{ + task->state = SOF_TASK_STATE_RUNNING; + return 0; +} + +static int schedule_edf_task_free(void *data, struct task *task) +{ + task->state = SOF_TASK_STATE_FREE; + task->ops.run = NULL; + task->data = NULL; + + return 0; +} + +static struct scheduler_ops schedule_edf_ops = { + .schedule_task = schedule_edf_task, + .schedule_task_running = schedule_edf_task_running, + .schedule_task_cancel = schedule_edf_task_cancel, + .schedule_task_free = schedule_edf_task_free, +}; + +int scheduler_init_edf(void) +{ + struct k_thread *thread = &edf_workq.thread; + + scheduler_init(SOF_SCHEDULE_EDF, &schedule_edf_ops, NULL); + + k_work_queue_start(&edf_workq, + edf_workq_stack, + K_THREAD_STACK_SIZEOF(edf_workq_stack), + CONFIG_EDF_THREAD_PRIORITY, NULL); + + k_thread_suspend(thread); + + k_thread_heap_assign(thread, sof_sys_heap_get()); +#ifdef CONFIG_SCHED_CPU_MASK + k_thread_cpu_mask_clear(thread); + k_thread_cpu_mask_enable(thread, PLATFORM_PRIMARY_CORE_ID); +#endif + k_thread_name_set(thread, "edf_workq"); + + k_thread_resume(thread); + + return 0; +} + +int schedule_task_init_edf(struct task *task, const struct sof_uuid_entry *uid, + const struct task_ops *ops, + void *data, uint16_t core, uint32_t flags) +{ + int ret; + + ret = schedule_task_init(task, uid, SOF_SCHEDULE_EDF, 0, ops->run, data, + core, flags); + if (ret < 0) + return ret; + + task->ops = *ops; + + k_work_init_delayable(&task->z_delayed_work, edf_work_handler); + + return 0; +} + +int schedule_task_init_edf_with_budget(struct task *task, + const struct sof_uuid_entry *uid, + const struct task_ops *ops, + void *data, uint16_t core, + uint32_t flags, uint32_t cycles_budget) +{ + return schedule_task_init_edf(task, uid, ops, data, core, flags); +} diff --git a/zephyr/include/rtos/alloc.h b/zephyr/include/rtos/alloc.h new file mode 100644 index 000000000000..e21e498f0471 --- /dev/null +++ b/zephyr/include/rtos/alloc.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __ZEPHYR_RTOS_ALLOC_H__ +#define __ZEPHYR_RTOS_ALLOC_H__ + +#include <rtos/bit.h> +#include <rtos/string.h> +#include <sof/lib/memory.h> /* PLATFORM_DCACHE_ALIGN */ +#include <sof/trace/trace.h> +#include <user/trace.h> + +#include <stddef.h> +#include <stdint.h> + +/** \addtogroup alloc_api Memory Allocation API + * @{ + */ + +/* + * for compatibility with the initial `flags` meaning + * SOF_MEM_FLAG_ should start at BIT(2) + * the first two positions are reserved for SOF_BUF_ flags + */ + +/** \name Allocation flags + * @{ + */ + + /** \brief Allocate DMA-able memory. */ +#define SOF_MEM_FLAG_DMA BIT(2) +/** \brief realloc() skips copying the original content. */ +#define SOF_MEM_FLAG_NO_COPY BIT(3) +/** \brief Allocate uncached address. */ +#define SOF_MEM_FLAG_COHERENT BIT(4) +/** \brief Allocate L3 address. */ +#define SOF_MEM_FLAG_L3 BIT(5) +/** \brief Allocate Low power memory address. */ +#define SOF_MEM_FLAG_LOW_POWER BIT(6) +/** \brief Allocate kernel memory address. */ +#define SOF_MEM_FLAG_KERNEL BIT(7) +/** \brief Allocate user memory address. */ +#define SOF_MEM_FLAG_USER BIT(8) +/** \brief Allocate shared user memory address. */ +#define SOF_MEM_FLAG_USER_SHARED_BUFFER BIT(9) +/** \brief Use allocation method for large buffers. */ +#define SOF_MEM_FLAG_LARGE_BUFFER BIT(10) + +/** @} */ + +/** + * Allocates memory block. + * @param flags Flags, see SOF_MEM_FLAG_.... + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + * + */ +void *rmalloc_align(uint32_t flags, size_t bytes, uint32_t alignment); + +/** + * Similar to rmalloc_align(), but no alignment can be specified. + */ +void *rmalloc(uint32_t flags, size_t bytes); + +/** + * Similar to rmalloc(), guarantees that returned block is zeroed. + */ +void *rzalloc(uint32_t flags, size_t bytes); + +/** + * Allocates memory block. + * @param flags Flags, see SOF_MEM_FLAG_... + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + */ +void *rballoc_align(uint32_t flags, size_t bytes, + uint32_t alignment); + +/** + * Similar to rballoc_align(), returns buffer aligned to PLATFORM_DCACHE_ALIGN. + */ +static inline void *rballoc(uint32_t flags, size_t bytes) +{ + return rballoc_align(flags, bytes, PLATFORM_DCACHE_ALIGN); +} + +/** + * Frees the memory block. + * @param ptr Pointer to the memory block. + */ +void rfree(void *ptr); + +/** + * Save L3 heap over DSP reset + */ +void l3_heap_save(void); + +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment); +void sof_heap_free(struct k_heap *heap, void *addr); +#if CONFIG_SOF_FULL_ZEPHYR_APPLICATION +struct k_heap *sof_sys_heap_get(void); +#else +/* for unit-testing */ +static inline struct k_heap *sof_sys_heap_get(void) +{ + return NULL; +} +#endif + +/** + * Returns heap object to use for SOF heap allocations + * for audio application code. + * + * The returned value may be NULL. This matches with semantics + * of sof_heap_alloc() that allows passing NULL as the 'heap'. + * In this case, the heap implementation will choose the heap to + * use. + * + * The function should not be used for heap allocations for objects that + * are only used in SOF kernel space. + * + * Note: audio modules should use mod_alloc() instead! + */ +struct k_heap *sof_sys_user_heap_get(void); + +/* TODO: remove - debug only - only needed for linking */ +static inline void heap_trace_all(int force) {} + +/** @}*/ + +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP +/** + * Returns the start address of shared memory heap for buffers. + * + * @return pointer to shared memory heap start + */ +uintptr_t get_shared_buffer_heap_start(void); + +/** + * Returns the size of shared memory heap for buffers. + * + * @return size of shared memory heap start + */ +size_t get_shared_buffer_heap_size(void); + +#endif + +#endif /* __ZEPHYR_RTOS_ALLOC_H__ */ diff --git a/zephyr/include/rtos/atomic.h b/zephyr/include/rtos/atomic.h new file mode 100644 index 000000000000..60b1ba3b9180 --- /dev/null +++ b/zephyr/include/rtos/atomic.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// + +#ifndef __ZEPHYR_RTOS_ATOMIC_H__ +#define __ZEPHYR_RTOS_ATOMIC_H__ + +#include <zephyr/sys/atomic.h> + +/* Zephyr commit 174cb7f9f183 switched 'atomic_t' from 'int' to + * 'long'. As we don't support 64 bits, this should have made no + * difference but in reality it broke printk("%d / %ld",...) The no-op + * cast to 'long' below provides a transition by making it possible to + * compile SOF both before _and_ after the Zephyr switch. + */ +#define atomic_read(p) ((long)atomic_get(p)) +#define atomic_init(p, v) atomic_set(p, v) + +#endif /*__ZEPHYR_RTOS_ATOMIC_H__ */ diff --git a/zephyr/include/rtos/bit.h b/zephyr/include/rtos/bit.h new file mode 100644 index 000000000000..133ca5424d87 --- /dev/null +++ b/zephyr/include/rtos/bit.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __ZEPHYR_RTOS_BIT_H__ +#define __ZEPHYR_RTOS_BIT_H__ + +#include <zephyr/sys/util.h> + +/* TODO: align with Zephyr BIT APIs */ + +#define MASK(b_hi, b_lo) \ + (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) +#define SET_BIT(b, x) (((x) & 1) << (b)) +#define SET_BITS(b_hi, b_lo, x) \ + (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) +#define GET_BIT(b, x) \ + (((x) & (1ULL << (b))) >> (b)) +#define GET_BITS(b_hi, b_lo, x) \ + (((x) & MASK(b_hi, b_lo)) >> (b_lo)) + +#endif /* __ZEPHYR_RTOS_BIT_H__ */ diff --git a/zephyr/include/rtos/cache.h b/zephyr/include/rtos/cache.h new file mode 100644 index 000000000000..576e1c5bea3d --- /dev/null +++ b/zephyr/include/rtos/cache.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __ZEPHYR_RTOS_CACHE_H__ +#define __ZEPHYR_RTOS_CACHE_H__ + +#define __SOF_LIB_CACHE_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <zephyr/cache.h> +#include <zephyr/debug/sparse.h> + +#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/clk.h b/zephyr/include/rtos/clk.h new file mode 100644 index 000000000000..6db452bdab88 --- /dev/null +++ b/zephyr/include/rtos/clk.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __ZEPHYR_RTOS_CLK_H__ +#define __ZEPHYR_RTOS_CLK_H__ + +#ifndef CONFIG_SOF_ZEPHYR_NO_SOF_CLOCK + +#include <zephyr/kernel.h> + +#define __SOF_LIB_CLK_H__ +#include <platform/lib/clk.h> + +/* TODO: most of the below is tied to the CLK drivers that need wrapped */ +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <stdbool.h> +#include <stdint.h> + +struct timer; + +#define CLOCK_NOTIFY_PRE 0 +#define CLOCK_NOTIFY_POST 1 + +struct clock_notify_data { + uint32_t old_freq; + uint32_t old_ticks_per_msec; + uint32_t freq; + uint32_t ticks_per_msec; + uint32_t message; +}; + +struct freq_table { + uint32_t freq; + uint32_t ticks_per_msec; +}; + +struct clock_info { + uint32_t freqs_num; + const struct freq_table *freqs; + uint32_t default_freq_idx; + uint32_t current_freq_idx; + uint32_t lowest_freq_idx; /* lowest possible clock */ + uint32_t notification_id; + uint32_t notification_mask; + + /* persistent change clock value in active state, caller must hold clk_lock */ + int (*set_freq)(int clock, int freq_idx); + + /* temporary change clock - don't modify default clock settings */ + void (*low_power_mode)(int clock, bool enable); +}; + +uint32_t clock_get_freq(int clock); + +void clock_set_freq(int clock, uint32_t hz); + +void clock_low_power_mode(int clock, bool enable); + +uint64_t clock_ticks_per_sample(int clock, uint32_t sample_rate); + +extern struct k_spinlock clk_lock; + +static inline k_spinlock_key_t clock_lock(void) +{ + return k_spin_lock(&clk_lock); +} + +static inline void clock_unlock(k_spinlock_key_t key) +{ + k_spin_unlock(&clk_lock, key); +} + +static inline struct clock_info *clocks_get(void) +{ + return sof_get()->clocks; +} + +#endif /* CONFIG_SOF_ZEPHYR_NO_SOF_CLOCK */ + +#endif /* __ZEPHYR_RTOS_CLK_H__ */ diff --git a/zephyr/include/rtos/idc.h b/zephyr/include/rtos/idc.h new file mode 100644 index 000000000000..a8616d9e2a11 --- /dev/null +++ b/zephyr/include/rtos/idc.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +/** + * \file include/rtos/idc.h + * \brief IDC header file + * \authors Tomasz Lauda <tomasz.lauda@linux.intel.com> + */ + +#ifndef __ZEPHYR_RTOS_IDC_H__ +#define __ZEPHYR_RTOS_IDC_H__ + +#include <rtos/task.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <stdint.h> +#include <rtos/cache.h> + +#include <sof/debug/telemetry/performance_monitor.h> + +/** \brief IDC send blocking flag. */ +#define IDC_BLOCKING 0 + +/** \brief IDC send non-blocking flag. */ +#define IDC_NON_BLOCKING 1 + +/** \brief IDC send core power up flag. */ +#define IDC_POWER_UP 2 + +/** \brief IDC send core power down flag. */ +#define IDC_POWER_DOWN 3 + +/** \brief IDC task deadline. */ +#define IDC_DEADLINE 100 + +/** \brief ROM wake version parsed by ROM during core wake up. */ +#define IDC_ROM_WAKE_VERSION 0x2 + +/** \brief IDC message type. */ +#define IDC_TYPE_SHIFT 24 +#define IDC_TYPE_MASK 0x7f +#define IDC_TYPE(x) (((x) & IDC_TYPE_MASK) << IDC_TYPE_SHIFT) + +/** \brief IDC message header. */ +#define IDC_HEADER_MASK 0xffffff +#define IDC_HEADER(x) ((x) & IDC_HEADER_MASK) + +/** \brief IDC message extension. */ +#define IDC_EXTENSION_MASK 0x3fffffff +#define IDC_EXTENSION(x) ((x) & IDC_EXTENSION_MASK) + +/** \brief IDC power up message. */ +#define IDC_MSG_POWER_UP (IDC_TYPE(0x1) | \ + IDC_HEADER(IDC_ROM_WAKE_VERSION)) +#define IDC_MSG_POWER_UP_EXT IDC_EXTENSION(SOF_TEXT_START >> 2) + +/** \brief IDC power down message. */ +#define IDC_MSG_POWER_DOWN IDC_TYPE(0x2) +#define IDC_MSG_POWER_DOWN_EXT IDC_EXTENSION(0x0) + +/** \brief IDC notify message. */ +#define IDC_MSG_NOTIFY IDC_TYPE(0x3) +#define IDC_MSG_NOTIFY_EXT IDC_EXTENSION(0x0) + +/** \brief IDC IPC processing message. */ +#define IDC_MSG_IPC IDC_TYPE(0x4) +#define IDC_MSG_IPC_EXT IDC_EXTENSION(0x0) + +/** \brief IDC component params message. */ +#define IDC_MSG_PARAMS IDC_TYPE(0x5) +#define IDC_MSG_PARAMS_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component prepare message. */ +#define IDC_MSG_PREPARE IDC_TYPE(0x6) +#define IDC_MSG_PREPARE_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component trigger message. */ +#define IDC_MSG_TRIGGER IDC_TYPE(0x7) +#define IDC_MSG_TRIGGER_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC component reset message. */ +#define IDC_MSG_RESET IDC_TYPE(0x8) +#define IDC_MSG_RESET_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC prepare D0ix message. */ +#define IDC_MSG_PREPARE_D0ix IDC_TYPE(0x9) +#define IDC_MSG_PREPARE_D0ix_EXT IDC_EXTENSION(0x0) + +/** \brief IDC secondary core crashed notify message. */ +#define IDC_MSG_SECONDARY_CORE_CRASHED IDC_TYPE(0xA) +#define IDC_MSG_SECONDARY_CORE_CRASHED_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC process async msg */ +#define IDC_MSG_AMS IDC_TYPE(0xB) +#define IDC_MSG_AMS_EXT IDC_EXTENSION(0x0) + +#define IDC_HEADER_TO_AMS_SLOT_MASK(x) (x & 0xFFFF) + +#define IDC_MSG_BIND IDC_TYPE(0xD) +#define IDC_MSG_UNBIND IDC_TYPE(0xE) +#define IDC_MSG_GET_ATTRIBUTE IDC_TYPE(0xF) + +/** \brief IDC component delete message. */ +#define IDC_MSG_FREE IDC_TYPE(0x10) +#define IDC_MSG_FREE_EXT(x) IDC_EXTENSION(x) + +/** \brief IDC pipeline set state message. */ +#define IDC_MSG_PPL_STATE IDC_TYPE(0xC) +#define IDC_PPL_STATE_PPL_ID_SHIFT 0 +#define IDC_PPL_STATE_PPL_ID_MASK MASK(23, 0) +#define IDC_PPL_STATE_PHASE_SHIFT 24 +#define IDC_PPL_STATE_PHASE_MASK MASK(27, 24) +#define IDC_PPL_STATE_PHASE_SET(x) (((x) << IDC_PPL_STATE_PHASE_SHIFT) & \ + IDC_PPL_STATE_PHASE_MASK) +#define IDC_PPL_STATE_PHASE_GET(x) (((x) & IDC_PPL_STATE_PHASE_MASK) >> \ + IDC_PPL_STATE_PHASE_SHIFT) +#define IDC_PPL_STATE_PHASE_PREPARE BIT(0) +#define IDC_PPL_STATE_PHASE_TRIGGER BIT(1) +#define IDC_PPL_STATE_PHASE_ONESHOT (IDC_PPL_STATE_PHASE_PREPARE | \ + IDC_PPL_STATE_PHASE_TRIGGER) + +#define IDC_MSG_PPL_STATE_EXT(_ppl_id, _action) \ + IDC_EXTENSION(((_ppl_id) & IDC_PPL_STATE_PPL_ID_MASK) | \ + IDC_PPL_STATE_PHASE_SET(_action)) + +/** \brief IDC_MSG_SECONDARY_CORE_CRASHED header fields. */ +#define IDC_SCC_CORE_SHIFT 0 +#define IDC_SCC_CORE_MASK 0xff +#define IDC_SCC_CORE(x) (((x) & IDC_SCC_CORE_MASK) << IDC_SCC_CORE_SHIFT) + +#define IDC_SCC_REASON_SHIFT 8 +#define IDC_SCC_REASON_MASK 0xff +#define IDC_SCC_REASON(x) (((x) & IDC_SCC_REASON_MASK) << IDC_SCC_REASON_SHIFT) + +/** \brief Secondary core crash reasons. */ +#define IDC_SCC_REASON_WATCHDOG 0x00 +#define IDC_SCC_REASON_EXCEPTION 0x01 + +/** \brief Decodes IDC message type. */ +#define iTS(x) (((x) >> IDC_TYPE_SHIFT) & IDC_TYPE_MASK) + +/** \brief Max IDC message payload size in bytes. */ +#define IDC_MAX_PAYLOAD_SIZE (DCACHE_LINE_SIZE * 2) + +/** \brief IDC free function flags */ +#define IDC_FREE_IRQ_ONLY BIT(0) /**< disable only irqs */ + +/** \brief IDC message payload. */ +struct idc_payload { + uint8_t data[IDC_MAX_PAYLOAD_SIZE]; +}; + +/** \brief IDC message. */ +struct idc_msg { + uint32_t header; /**< header value */ + uint32_t extension; /**< extension value */ + uint32_t core; /**< core id */ + uint32_t size; /**< payload size in bytes */ + void *payload; /**< pointer to payload data */ +}; + +/** \brief IDC data. */ +struct idc { + uint32_t busy_bit_mask; /**< busy interrupt mask */ + struct idc_msg received_msg; /**< received message */ + struct task idc_task; /**< IDC processing task */ + struct idc_payload *payload; + int irq; +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* io performance measurement */ + struct io_perf_data_item *io_perf_in_msg_count; + struct io_perf_data_item *io_perf_out_msg_count; +#endif +}; + +/* idc trace context, used by multiple units */ +extern struct tr_ctx idc_tr; + +static inline struct idc_payload *idc_payload_get(struct idc *idc, + uint32_t core) +{ + return idc->payload + core; +} + +void idc_enable_interrupts(int target_core, int source_core); + +void idc_free(uint32_t flags); + +int platform_idc_init(void); + +int platform_idc_restore(void); + +enum task_state idc_do_cmd(void *data); + +void idc_cmd(struct idc_msg *msg); + +int idc_msg_status_get(uint32_t core); + +int idc_init(void); + +void idc_init_thread(void); + +int idc_send_msg(struct idc_msg *msg, uint32_t mode); + +struct idc **idc_get(void); + +#endif /* __ZEPHYR_RTOS_IDC_H__ */ diff --git a/zephyr/include/rtos/init.h b/zephyr/include/rtos/init.h new file mode 100644 index 000000000000..22341613f06c --- /dev/null +++ b/zephyr/include/rtos/init.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __ZEPHYR_RTOS_INIT_H__ +#define __ZEPHYR_RTOS_INIT_H__ + +#include <zephyr/init.h> + +#define SOF_MODULE_INIT(name, init) \ +static int zephyr_##name##_init(void) \ +{ \ + init(); \ + return 0; \ +} \ +SYS_INIT(zephyr_##name##_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY) + +#endif /* __ZEPHYR_RTOS_INIT_H__ */ diff --git a/zephyr/include/rtos/interrupt.h b/zephyr/include/rtos/interrupt.h new file mode 100644 index 000000000000..200d36e4751e --- /dev/null +++ b/zephyr/include/rtos/interrupt.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * TODO: IMX support, today IRQ is supported via SOF xtos API. + */ + +#ifndef __ZEPHYR_RTOS_INTERRUPT_H__ +#define __ZEPHYR_RTOS_INTERRUPT_H__ + +/* TODO: to be removed completely when the following platforms are switched + * to native drivers. + */ +#if defined(CONFIG_AMD) && !defined(CONFIG_ZEPHYR_NATIVE_DRIVERS) +/* imx currently has no IRQ driver in Zephyr so we force to xtos IRQ */ +#include "../../../xtos/include/rtos/interrupt.h" +#else + +#include <zephyr/device.h> +#include <zephyr/kernel.h> +#include <stdint.h> + +#include <sof/trace/trace.h> + +extern struct tr_ctx zephyr_tr; + +static inline int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg) +{ +#ifdef CONFIG_DYNAMIC_INTERRUPTS + return arch_irq_connect_dynamic(irq, 0, (void (*)(const void *))handler, + arg, 0); +#else + LOG_MODULE_DECLARE(zephyr, CONFIG_SOF_LOG_LEVEL); + tr_err(&zephyr_tr, "Cannot register handler for IRQ %u: dynamic IRQs are disabled", + irq); + return -EOPNOTSUPP; +#endif +} + +/* unregister an IRQ handler - matches on IRQ number and data ptr */ +static inline void interrupt_unregister(uint32_t irq, const void *arg) +{ + /* + * There is no "unregister" (or "disconnect") for + * interrupts in Zephyr. + */ + irq_disable(irq); +} + +static inline int interrupt_get_irq(unsigned int irq, const char *cascade) +{ + return irq; +} + +/* enable an interrupt source - IRQ needs mapped to Zephyr, + * arg is used to match. + */ +static inline uint32_t interrupt_enable(uint32_t irq, void *arg) +{ + irq_enable(irq); + + return 0; +} + +/* disable interrupt */ +static inline uint32_t interrupt_disable(uint32_t irq, void *arg) +{ + irq_disable(irq); + + return 0; +} + +/* TODO: using SOF versions */ +void interrupt_mask(uint32_t irq, unsigned int cpu); +void interrupt_unmask(uint32_t irq, unsigned int cpu); +void interrupt_clear_mask(uint32_t irq, uint32_t mask); + +/* handled by Zephyr */ +static inline void platform_interrupt_init(void) {} + +/* disables all IRQ sources on current core */ +#define irq_local_disable(flags) \ + (flags = arch_irq_lock()) + +/* re-enables IRQ sources on current core */ +#define irq_local_enable(flags) \ + arch_irq_unlock(flags) + +#endif /* CONFIG_AMD && !CONFIG_ZEPHYR_NATIVE_DRIVERS */ + +#endif /* __ZEPHYR_RTOS_INTERRUPT_H__ */ diff --git a/zephyr/include/rtos/kernel.h b/zephyr/include/rtos/kernel.h new file mode 100644 index 000000000000..328fc96d2eaa --- /dev/null +++ b/zephyr/include/rtos/kernel.h @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// + +#ifndef __ZEPHYR_RTOS_KERNEL_H__ +#define __ZEPHYR_RTOS_KERNEL_H__ + +#include <zephyr/kernel.h> + +#include <stdbool.h> + +static inline bool thread_is_userspace(struct k_thread *thread) +{ + return !!(thread->base.user_options & K_USER); +} + +#endif /* __ZEPHYR_RTOS_KERNEL_H__ */ diff --git a/zephyr/include/rtos/mutex.h b/zephyr/include/rtos/mutex.h new file mode 100644 index 000000000000..a8886f768d1e --- /dev/null +++ b/zephyr/include/rtos/mutex.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. +// + +#ifndef __ZEPHYR_RTOS_MUTEX_H__ +#define __ZEPHYR_RTOS_MUTEX_H__ + +#include <zephyr/kernel.h> /* k_mutex_*() */ +#include <zephyr/sys/mutex.h> /* for sys_mutex */ + +#endif /* __ZEPHYR_RTOS_MUTEX_H__ */ diff --git a/zephyr/include/rtos/panic.h b/zephyr/include/rtos/panic.h new file mode 100644 index 000000000000..e065498a5ba5 --- /dev/null +++ b/zephyr/include/rtos/panic.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __ZEPHYR_RTOS_PANIC_H__ +#define __ZEPHYR_RTOS_PANIC_H__ + +#include <rtos/kernel.h> + +#ifndef __ZEPHYR__ +#error "This file should only be included in Zephyr builds." +#endif /* __ZEPHYR__ */ + +#define sof_panic(x) k_panic() +#define assert(x) __ASSERT_NO_MSG(x) + +/* To print the asserted expression on failure: + * #define assert(x) __ASSERT(x, #x) + */ + +#endif /* __ZEPHYR_RTOS_PANIC_H__ */ diff --git a/zephyr/include/rtos/sof.h b/zephyr/include/rtos/sof.h new file mode 100644 index 000000000000..573e6ac63d77 --- /dev/null +++ b/zephyr/include/rtos/sof.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __ZEPHYR_RTOS_SOF_H__ +#define __ZEPHYR_RTOS_SOF_H__ + +#include <sof/common.h> +#include <sof/lib/memory.h> +#include <rtos/spinlock.h> + +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS +struct cascade_root; +#endif +struct clock_info; +struct comp_driver_list; +struct dai_info; +struct dma_info; +struct dma_trace_data; +struct ipc; +struct ll_schedule_domain; +struct mm; +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS +struct mn; +#endif +struct ams_shared_context; +struct notify_data; +struct pm_runtime_data; +struct sa; +struct trace; +struct pipeline_posn; +struct probe_pdata; + +/** + * \brief General firmware context. + * This structure holds all the global pointers, which can potentially + * be accessed by SMP code, hence it should be aligned to platform's + * data cache line size. Alignments in the both beginning and end are needed + * to avoid potential before and after data evictions. + */ +struct sof { + /* init data */ + int argc; + char **argv; + + /* ipc */ + struct ipc *ipc; + + /* system agent */ + struct sa *sa; + + /* DMA for Trace*/ + struct dma_trace_data *dmat; + + /* generic trace structure */ + struct trace *trace; + + /* platform clock information */ + struct clock_info *clocks; + + /* timer domain for driving timer LL scheduler */ + struct ll_schedule_domain *platform_timer_domain; + + /* DMA domain for driving DMA LL scheduler */ + struct ll_schedule_domain *platform_dma_domain; + + /* memory map */ + struct mm *memory_map; + + /* runtime power management data */ + struct pm_runtime_data *prd; + +#ifdef CONFIG_AMS + /* asynchronous messaging service */ + struct ams_shared_context *ams_shared_ctx; +#endif + + /* shared notifier data */ + struct notify_data *notify_data; + + /* platform dai information */ + const struct dai_info *dai_info; + + /* platform DMA information */ + const struct dma_info *dma_info; + +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS + /* cascading interrupt controller root */ + struct cascade_root *cascade_root; +#endif + + /* list of registered component drivers */ + struct comp_driver_list *comp_drivers; + +#ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS + /* M/N dividers */ + struct mn *mn; +#endif + + /* probes */ + struct probe_pdata *probe; + + /* pipelines stream position */ + struct pipeline_posn *pipeline_posn; + +#ifdef CONFIG_LIBRARY_MANAGER + /* dynamically loaded libraries */ + struct ext_library *ext_library; +#endif + + __aligned(PLATFORM_DCACHE_ALIGN) int alignment[0]; +} __aligned(PLATFORM_DCACHE_ALIGN); + +struct sof *sof_get(void); + +#endif /* __ZEPHYR_RTOS_SOF_H__ */ diff --git a/zephyr/include/rtos/spinlock.h b/zephyr/include/rtos/spinlock.h new file mode 100644 index 000000000000..24b0ee9dc579 --- /dev/null +++ b/zephyr/include/rtos/spinlock.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// + +#ifndef __ZEPHYR_RTOS_SPINLOCK_H__ +#define __ZEPHYR_RTOS_SPINLOCK_H__ + +#include <zephyr/kernel.h> +#include <zephyr/spinlock.h> + +/* not implemented on Zephyr, but used within SOF */ +static inline void k_spinlock_init(struct k_spinlock *lock) +{ +#ifdef CONFIG_SMP + atomic_set(&lock->locked, 0); +#endif +} + +#endif /* __ZEPHYR_RTOS_SPINLOCK_H__ */ diff --git a/zephyr/include/rtos/string.h b/zephyr/include/rtos/string.h new file mode 100644 index 000000000000..37bd657ff91d --- /dev/null +++ b/zephyr/include/rtos/string.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __ZEPHYR_RTOS_STRING_H__ +#define __ZEPHYR_RTOS_STRING_H__ + +/* Zephyr uses a C library so lets use it */ +#include <string.h> +#include <stdint.h> +#include <stddef.h> +#include <errno.h> + +void *__vec_memcpy(void *dst, const void *src, size_t len); +void *__vec_memset(void *dest, int data, size_t src_size); + +#ifdef __cplusplus +extern "C" { +#endif +/* missing from zephyr - TODO: convert to memset() */ +#define bzero(ptr, size) \ + memset(ptr, 0, size) + +/* TODO: need converted to C library calling conventions */ +static inline int rstrlen(const char *s) +{ + return strlen(s); +} + +/* TODO: need converted to C library calling conventions */ +static inline int rstrcmp(const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +/* C library does not have the "_s" versions used by Windows */ +static inline int memcpy_s(void *dest, size_t dest_size, + const void *src, size_t count) +{ + if (!dest || !src) + return -EINVAL; + + if (count > dest_size) + return -EINVAL; + + uintptr_t dest_addr = (uintptr_t)dest; + uintptr_t src_addr = (uintptr_t)src; + + /* Check for overflow in pointer arithmetic */ + if ((dest_addr + dest_size < dest_addr) || (src_addr + count < src_addr)) + return -EINVAL; + + /* Check for overlap without causing overflow */ + if ((dest_addr >= src_addr && dest_addr < src_addr + count) || + (src_addr >= dest_addr && src_addr < dest_addr + dest_size)) + return -EINVAL; + + memcpy(dest, src, count); + + return 0; +} + +static inline int memset_s(void *dest, size_t dest_size, int data, size_t count) +{ + if (!dest) + return -EINVAL; + + if (count > dest_size) + return -EINVAL; + + memset(dest, data, count); + /* + * Prevent compiler from optimizing away the memset. + * Memory barrier prevents dead store elimination. + */ +#if defined(CONFIG_XTENSA) + __asm__ __volatile__("memw" ::: "memory"); +#endif + + return 0; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __ZEPHYR_RTOS_STRING_H__ */ diff --git a/zephyr/include/rtos/string_macro.h b/zephyr/include/rtos/string_macro.h new file mode 100644 index 000000000000..974760d2031e --- /dev/null +++ b/zephyr/include/rtos/string_macro.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian <Baofeng.tian@intel.com> + */ + +#ifndef __ZEPHYR_RTOS_STRING_MACRO_H__ +#define __ZEPHYR_RTOS_STRING_MACRO_H__ + +#include <zephyr/toolchain/common.h> + +#endif /* __ZEPHYR_RTOS_STRING_MACRO_H__ */ diff --git a/zephyr/include/rtos/symbol.h b/zephyr/include/rtos/symbol.h new file mode 100644 index 000000000000..9ff742ee730d --- /dev/null +++ b/zephyr/include/rtos/symbol.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __RTOS_SYMBOL_H__ +#define __RTOS_SYMBOL_H__ + +#include <zephyr/llext/symbol.h> + +#endif diff --git a/zephyr/include/rtos/task.h b/zephyr/include/rtos/task.h new file mode 100644 index 000000000000..9fcc202c1e2e --- /dev/null +++ b/zephyr/include/rtos/task.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __ZEPHYR_RTOS_TASK_H__ +#define __ZEPHYR_RTOS_TASK_H__ + +#include <rtos/panic.h> +#include <sof/list.h> +#include <stdbool.h> +#include <stdint.h> +#include <rtos/kernel.h> +#include <sof/lib/perf_cnt.h> + +struct comp_dev; +struct sof; + +/** \brief Predefined LL task priorities. */ +#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */ +#define SOF_TASK_PRI_MED 4 /* priority level 4 - medium */ +#define SOF_TASK_PRI_LOW 9 /* priority level 9 - low */ + +/** \brief Predefined EDF task deadlines. */ +#define SOF_TASK_DEADLINE_IDLE UINT64_MAX +#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1) +#define SOF_TASK_DEADLINE_NOW 0 + +/** \brief Task counter initial value. */ +#define SOF_TASK_SKIP_COUNT 0xFFFFu + +/** \brief Task states. */ +enum task_state { + SOF_TASK_STATE_INIT = 0, + SOF_TASK_STATE_QUEUED, + SOF_TASK_STATE_PENDING, + SOF_TASK_STATE_RUNNING, + SOF_TASK_STATE_PREEMPTED, + SOF_TASK_STATE_COMPLETED, + SOF_TASK_STATE_FREE, + SOF_TASK_STATE_CANCEL, + SOF_TASK_STATE_RESCHEDULE, +}; + +/** \brief Task operations. */ +struct task_ops { + enum task_state (*run)(void *data); /**< task's main operation */ + void (*complete)(void *data); /**< executed on completion */ + uint64_t (*get_deadline)(void *data); /**< returns current deadline */ +}; + +/** \brief Task used by schedulers. */ +struct task { + uint64_t start; /**< start time in [ms] since now (LL only) */ + const struct sof_uuid_entry *uid; /**< Uuid */ + uint16_t type; /**< type of the task (LL or EDF) */ + uint16_t priority; /**< priority of the task (used by LL) */ + uint16_t core; /**< execution core */ + uint16_t flags; /**< custom flags */ + enum task_state state; /**< current state */ + void *data; /**< custom data passed to all ops */ + struct list_item list; /**< used by schedulers to hold tasks */ + void *priv_data; /**< task private data */ + struct task_ops ops; /**< task operations */ + struct k_work_delayable z_delayed_work; + uint32_t cycles_sum; + uint32_t cycles_max; + uint32_t cycles_cnt; +#if CONFIG_PERFORMANCE_COUNTERS + struct perf_cnt_data pcd; +#endif +}; + +static inline bool task_is_active(struct task *task) +{ + switch (task->state) { + case SOF_TASK_STATE_QUEUED: + case SOF_TASK_STATE_PENDING: + case SOF_TASK_STATE_RUNNING: + case SOF_TASK_STATE_PREEMPTED: + case SOF_TASK_STATE_RESCHEDULE: + return true; + default: + return false; + } +} + +static inline enum task_state task_run(struct task *task) +{ + assert(task->ops.run); + + return task->ops.run(task->data); +} + +static inline void task_complete(struct task *task) +{ + if (task->ops.complete) + task->ops.complete(task->data); +} + +static inline uint64_t task_get_deadline(struct task *task) +{ + assert(task->ops.get_deadline); + + return task->ops.get_deadline(task->data); +} + +int task_main_start(struct sof *sof); +int start_complete(void); + +#endif /* __ZEPHYR_RTOS_TASK_H__ */ diff --git a/zephyr/include/rtos/timer.h b/zephyr/include/rtos/timer.h new file mode 100644 index 000000000000..412ceeda0038 --- /dev/null +++ b/zephyr/include/rtos/timer.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __ZEPHYR_RTOS_TIMER_H__ +#define __ZEPHYR_RTOS_TIMER_H__ + +#include <stdint.h> +#include <zephyr/kernel.h> +#include <sof/lib/cpu.h> +#include <rtos/sof.h> +#include <sof/platform.h> + +struct comp_dev; +struct sof_ipc_stream_posn; + +static inline uint64_t sof_cycle_get_64(void) +{ + if (IS_ENABLED(CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER)) + return k_cycle_get_64(); + else + return k_ticks_to_cyc_floor64(k_uptime_ticks()); +} + +static inline uint64_t sys_cycle_get_64_rate(void) +{ + return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; +} + +#define sof_cycle_get_64_safe() sof_cycle_get_64() +#define sof_cycle_get_64_atomic() sof_cycle_get_64() +#define platform_timer_stop(x) + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn); + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn); + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock); + +#endif /* __ZEPHYR_RTOS_TIMER_H__ */ diff --git a/zephyr/include/rtos/userspace_helper.h b/zephyr/include/rtos/userspace_helper.h new file mode 100644 index 000000000000..7d8f7919d865 --- /dev/null +++ b/zephyr/include/rtos/userspace_helper.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2025 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * Adrian Warecki <adrian.warecki@intel.com> + */ + +/** + * \brief Userspace support functions. + */ +#ifndef __ZEPHYR_LIB_USERSPACE_HELPER_H__ +#define __ZEPHYR_LIB_USERSPACE_HELPER_H__ + +#include <zephyr/kernel.h> + +#ifndef CONFIG_USERSPACE +#define APP_TASK_BSS +#define APP_TASK_DATA +#else +#include <zephyr/cache.h> +#include <zephyr/app_memory/app_memdomain.h> + +#define USER_MOD_HEAP_SIZE ALIGN_UP(CONFIG_SOF_ZEPHYR_USERSPACE_MODULE_HEAP_SIZE, \ + CONFIG_MM_DRV_PAGE_SIZE) +#define APP_TASK_BSS K_APP_BMEM(common_partition) +#define APP_TASK_DATA K_APP_DMEM(common_partition) + +#ifdef CONFIG_SOF_USERSPACE_LL +#define APP_SYSUSER_BSS K_APP_BMEM(sysuser_partition) +#define APP_SYSUSER_DATA K_APP_DMEM(sysuser_partition) +#else +#define APP_SYSUSER_BSS +#define APP_SYSUSER_DATA +#endif + +struct processing_module; +struct userspace_context; + +/** + * Initialize private processing module heap. + * @param N/A. + * @return pointer to the k_heap structure. + * + * @note + * Function used only when CONFIG_USERSPACE is set. + * The private heap is used only for non-privileged modules for all processing module allocations + * that should be isolated. The heap helps to accumulate all dynamic allocations in single memory + * region which is then added to modules memory domain. + */ +struct k_heap *module_driver_heap_init(void); + +/** + * Attach common userspace memory partition to a module memory domain. + * @param dom - memory domain to attach the common partition to. + * + * @return 0 for success, error otherwise. + * + * @note + * Function used only when CONFIG_USERSPACE is set. + * The common partition contains shared objects required by user-space modules. + */ +int user_memory_attach_common_partition(struct k_mem_domain *dom); + +#endif + +/** + * Allocates thread stack memory. + * @param stack_size Required stack size. + * @param options Stack configuration options + * K_USER - when creating user thread + * 0 - when creating kernel thread + * @return pointer to the stack or NULL if not created. + * + * When CONFIG_USERSPACE not set function calls rballoc_align(), + * otherwise it uses k_thread_stack_alloc() routine. + * + */ +void *user_stack_allocate(size_t stack_size, uint32_t options); + +/** + * Free thread stack memory. + * @param p_stack Pointer to the stack. + * + * @return 0 for success, error otherwise. + * + * @note + * When CONFIG_USERSPACE not set function calls rfree(), + * otherwise it uses k_thread_stack_free() routine. + * + */ +int user_stack_free(void *p_stack); + +/** + * Free private processing module heap. + * @param sys_heap pointer to the sys_heap structure. + * + * @note + * Function used only when CONFIG_USERSPACE is set. + * Frees private module heap. + */ +void module_driver_heap_remove(struct k_heap *mod_drv_heap); + +#ifdef CONFIG_USERSPACE + +/** + * Add access to mailbox.h interface to a user-space thread. + * + * @param domain memory domain to add the mailbox partitions to + * @param thread_id user-space thread for which access is added + */ +int user_access_to_mailbox(struct k_mem_domain *domain, k_tid_t thread_id); + +/** + * Derive partition attribute from the pointer. If the address is cacheable, sets the cacheable + * attribute. + * + * @param ptr Address of the partition start + */ +static inline uint32_t user_get_partition_attr(uintptr_t ptr) +{ + return sys_cache_is_ptr_cached(UINT_TO_POINTER(ptr)) ? XTENSA_MMU_CACHED_WB : 0; +} + +/** + * Grant DAI device access to a user-space thread. + * + * @param thread user-space thread for which DAI access is granted + */ +void user_grant_dai_access_all(struct k_thread *thread); + +/** + * Grant DMA device access to a user-space thread. + * + * @param thread user-space thread for which DMA access is granted + */ +void user_grant_dma_access_all(struct k_thread *thread); + +#else + +static inline int user_access_to_mailbox(struct k_mem_domain *domain, k_tid_t thread_id) +{ + return 0; +} + +#endif /* CONFIG_USERSPACE */ + +#ifdef CONFIG_SOF_USERSPACE_LL + +int user_memory_attach_system_user_partition(struct k_mem_domain *dom); + +#else + +/** + * Attach SOF system user memory partition to a memory domain. + * @param dom - memory domain to attach the sysuser partition to. + * + * @return 0 for success, error otherwise. + * + * @note + * Function used only when CONFIG_USERSPACE is set. + * The sysuser partition contains shared objects required by user-space modules. + */ +static inline int user_memory_attach_system_user_partition(struct k_mem_domain *dom) +{ + return 0; +} + +#endif /* CONFIG_SOF_USERSPACE_LL */ + +#endif /* __ZEPHYR_LIB_USERSPACE_HELPER_H__ */ diff --git a/zephyr/include/rtos/wait.h b/zephyr/include/rtos/wait.h new file mode 100644 index 000000000000..4741e0c9aa8c --- /dev/null +++ b/zephyr/include/rtos/wait.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#ifndef __ZEPHYR_RTOS_WAIT_H__ +#define __ZEPHYR_RTOS_WAIT_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <zephyr/kernel.h> +#include <zephyr/sys/time_units.h> +#include <rtos/timer.h> + +static inline void wait_delay_us(uint64_t us) +{ + k_busy_wait(us); +} + +static inline void wait_delay(uint64_t number_of_clks) +{ + k_busy_wait(k_cyc_to_us_floor64(number_of_clks)); +} + +static inline void wait_delay_ms(uint64_t ms) +{ + k_busy_wait(ms * 1000); +} + +int poll_for_register_delay(uint32_t reg, uint32_t mask, + uint32_t val, uint64_t us); + +/* TODO: this is tmp used by some IMX IPC drivers that have not transitioned + * to Zephyr. To be removed after drivers migrated to Zephyr. It's xtensa only too. + */ +static inline void wait_for_interrupt(int level) +{ + __asm__ volatile("waiti 0"); +} + +#endif /* __ZEPHYR_RTOS_WAIT_H__ */ diff --git a/zephyr/include/sof/compiler_attributes.h b/zephyr/include/sof/compiler_attributes.h new file mode 100644 index 000000000000..0003c05234fb --- /dev/null +++ b/zephyr/include/sof/compiler_attributes.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_COMPILER_ATTRIBUTES_H__ +#define __SOF_COMPILER_ATTRIBUTES_H__ + +#include <zephyr/toolchain.h> + +/* Get __sparse_cache and __sparse_force definitions if __CHECKER__ is defined */ +#include <zephyr/debug/sparse.h> + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif + +#ifndef __section +#define __section(x) __attribute__((section(x))) +#endif + +/* The fallthrough attribute is supported since GCC 7.0 + * and Clang 10.0.0. + * + * Note that Clang sets __GNUC__ == 4 so the GCC version + * test will not be true here, and must go through + * the Clang version test. + */ +#if ((defined(__GNUC__) && (__GNUC__ >= 7)) || \ + (defined(__clang__) && (__clang_major__ >= 10))) && !defined(__CHECKER__) +#define COMPILER_FALLTHROUGH __attribute__((fallthrough)) +#else +#define COMPILER_FALLTHROUGH /* fallthrough */ +#endif + +#endif /* __SOF_COMPILER_ATTRIBUTES_H__ */ 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 <xtensa/hal.h> + +#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/init.h b/zephyr/include/sof/init.h new file mode 100644 index 000000000000..90c4c2ddb7a3 --- /dev/null +++ b/zephyr/include/sof/init.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016,2024 Intel Corporation. + */ + +#ifndef __SOF_INIT_H__ +#define __SOF_INIT_H__ + +/* main firmware entry point - argc and argv not currently used */ +#ifndef CONFIG_ARCH_POSIX +int main(int argc, char *argv[]); +#endif + +#if CONFIG_MULTICORE + +struct sof; + +int secondary_core_init(struct sof *sof); + +#endif /* CONFIG_MULTICORE */ + +#endif /* __SOF_INIT_H__ */ diff --git a/zephyr/include/sof/lib/cpu.h b/zephyr/include/sof/lib/cpu.h new file mode 100644 index 000000000000..c23405e85121 --- /dev/null +++ b/zephyr/include/sof/lib/cpu.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2018 Intel Corporation. All rights reserved. + * + * Author: Tomasz Leman <tomasz.m.leman@intel.com> + */ + +/** + * \file zephyr/include/sof/lib/cpu.h + * \brief CPU header file + * \authors Tomasz Leman <tomasz.m.leman@intel.com> + */ + +#ifndef __SOF_LIB_CPU_H__ +#define __SOF_LIB_CPU_H__ + +/** + * \brief Id of primary DSP core + * + * SOF IPC protocols make a distinction between primary + * and secondary cores. In Zephyr, primary core id concept + * is not present in public OS interface, but in implementation + * zero is the boot core (see z_smp_init() in Zephyr). + */ +#define PLATFORM_PRIMARY_CORE_ID 0 + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include <stdbool.h> + +#include <zephyr/arch/arch_inlines.h> + +#if CONFIG_PM + +#include <zephyr/pm/pm.h> + +void cpu_notify_state_entry(enum pm_state state); + +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 + +static inline int cpu_get_id(void) +{ + return arch_proc_id(); +} + +static inline bool cpu_is_primary(int id) +{ + return id == PLATFORM_PRIMARY_CORE_ID; +} + +static inline bool cpu_is_me(int id) +{ + return id == cpu_get_id(); +} + +int cpu_enable_core(int id); + +void cpu_disable_core(int id); + +int cpu_is_core_enabled(int id); + +int cpu_enabled_cores(void); + +void cpu_power_down_core(uint32_t flags); + +int cpu_restore_secondary_cores(void); + +int cpu_secondary_cores_prepare_d0ix(void); +#else + +static inline int cpu_get_id(void) { return 0; }; + +static inline bool cpu_is_primary(int id) { return 1; }; + +static inline bool cpu_is_me(int id) { return 1; }; + +static inline int cpu_enable_core(int id) { return 0; }; + +static inline void cpu_disable_core(int id) { }; + +static inline int cpu_is_core_enabled(int id) { return 1; }; + +static inline int cpu_enabled_cores(void) { return 1; }; + +static inline int cpu_restore_secondary_cores(void) { return 0; }; + +static inline int cpu_secondary_cores_prepare_d0ix(void) { return 0; }; + +#endif /* CONFIG_MULTICORE && CONFIG_SMP */ + +#endif + +#endif /* __SOF_LIB_CPU_H__ */ diff --git a/zephyr/include/sof/lib/dai.h b/zephyr/include/sof/lib/dai.h new file mode 100644 index 000000000000..cc6914370b58 --- /dev/null +++ b/zephyr/include/sof/lib/dai.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_LIB_DAI_H__ +#define __SOF_LIB_DAI_H__ + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +#include <sof/lib/dai-zephyr.h> +#else +#include <sof/lib/dai-legacy.h> +#endif + +#endif /* __SOF_LIB_DAI_H__ */ diff --git a/zephyr/include/sof/lib/dma-legacy.h b/zephyr/include/sof/lib/dma-legacy.h new file mode 100644 index 000000000000..016434e2f143 --- /dev/null +++ b/zephyr/include/sof/lib/dma-legacy.h @@ -0,0 +1,309 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_LIB_DMA_LEGACY_H__ +#define __SOF_LIB_DMA_LEGACY_H__ + +/* DMA attributes */ +#define DMA_ATTR_BUFFER_ALIGNMENT 0 +#define DMA_ATTR_COPY_ALIGNMENT 1 +#define DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT 2 +#define DMA_ATTR_BUFFER_PERIOD_COUNT 3 + +/* Compatibility for definitions without SOF_ namespace */ +#define DMA_DIR_MEM_TO_MEM SOF_DMA_DIR_MEM_TO_MEM +#define DMA_DIR_HMEM_TO_LMEM SOF_DMA_DIR_HMEM_TO_LMEM +#define DMA_DIR_LMEM_TO_HMEM SOF_DMA_DIR_LMEM_TO_HMEM +#define DMA_DIR_MEM_TO_DEV SOF_DMA_DIR_MEM_TO_DEV +#define DMA_DIR_DEV_TO_MEM SOF_DMA_DIR_DEV_TO_MEM +#define DMA_DIR_DEV_TO_DEV SOF_DMA_DIR_DEV_TO_DEV +#define DMA_COPY_BLOCKING SOF_DMA_COPY_BLOCKING +#define DMA_COPY_ONE_SHOT SOF_DMA_COPY_ONE_SHOT +#define DMA_DEV_HOST SOF_DMA_DEV_HOST +#define DMA_ACCESS_EXCLUSIVE SOF_DMA_ACCESS_EXCLUSIVE +#define DMA_ACCESS_SHARED SOF_DMA_ACCESS_SHARED +#define DMA_CHAN_INVALID SOF_DMA_CHAN_INVALID +#define DMA_CORE_INVALID SOF_DMA_CORE_INVALID + +struct dma *dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags); +void dma_put(struct dma *dma); + +enum dma_cb_status { + DMA_CB_STATUS_RELOAD = 0, + DMA_CB_STATUS_END, +}; + +/* DMA interrupt commands */ +enum dma_irq_cmd { + DMA_IRQ_STATUS_GET = 0, + DMA_IRQ_CLEAR, + DMA_IRQ_MASK, + DMA_IRQ_UNMASK +}; + +/* DMA operations */ +struct dma_ops { + + struct dma_chan_data *(*channel_get)(struct dma *dma, + unsigned int req_channel); + void (*channel_put)(struct dma_chan_data *channel); + + int (*start)(struct dma_chan_data *channel); + int (*stop)(struct dma_chan_data *channel); + int (*stop_delayed)(struct dma_chan_data *channel); + int (*copy)(struct dma_chan_data *channel, int bytes, uint32_t flags); + int (*pause)(struct dma_chan_data *channel); + int (*release)(struct dma_chan_data *channel); + int (*status)(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction); + + int (*set_config)(struct dma_chan_data *channel, + struct dma_sg_config *config); + + int (*probe)(struct dma *dma); + int (*remove)(struct dma *dma); + + int (*get_data_size)(struct dma_chan_data *channel, uint32_t *avail, + uint32_t *free); + + int (*get_attribute)(struct dma *dma, uint32_t type, uint32_t *value); + + int (*interrupt)(struct dma_chan_data *channel, enum dma_irq_cmd cmd); +}; + +/* DMA API + * Programming flow is :- + * + * 1) dma_channel_get() + * 2) notifier_register() + * 3) dma_set_config() + * 4) dma_start() + * ... DMA now running ... + * 5) dma_stop() + * 6) dma_stop_delayed() + * 7) dma_channel_put() + */ + +static inline struct dma_chan_data *dma_channel_get_legacy(struct dma *dma, + int req_channel) +{ + if (!dma || !dma->ops || !dma->ops->channel_get) + return NULL; + + struct dma_chan_data *chan = dma->ops->channel_get(dma, req_channel); + + return chan; +} + +static inline void dma_channel_put_legacy(struct dma_chan_data *channel) +{ + channel->dma->ops->channel_put(channel); +} + +static inline int dma_start_legacy(struct dma_chan_data *channel) +{ + return channel->dma->ops->start(channel); +} + +static inline int dma_stop_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->stop) + return channel->dma->ops->stop(channel); + + return 0; +} + +static inline int dma_stop_delayed_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->stop_delayed) + return channel->dma->ops->stop_delayed(channel); + + return 0; +} + +/** \defgroup sof_dma_copy_func static int dma_copy (struct dma_chan_data * channel, int bytes, uint32_t flags) + * + * This function is in a separate subgroup to solve a name clash with + * struct dma_copy {} + * @{ + */ +static inline int dma_copy_legacy(struct dma_chan_data *channel, int bytes, + uint32_t flags) +{ + return channel->dma->ops->copy(channel, bytes, flags); +} +/** @} */ + +static inline int dma_pause_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->pause) + return channel->dma->ops->pause(channel); + + return 0; +} + +static inline int dma_release_legacy(struct dma_chan_data *channel) +{ + if (channel->dma->ops->release) + return channel->dma->ops->release(channel); + + return 0; +} + +static inline int dma_status_legacy(struct dma_chan_data *channel, + struct dma_chan_status *status, uint8_t direction) +{ + return channel->dma->ops->status(channel, status, direction); +} + +static inline int dma_set_config_legacy(struct dma_chan_data *channel, + struct dma_sg_config *config) +{ + return channel->dma->ops->set_config(channel, config); +} + +static inline int dma_probe_legacy(struct dma *dma) +{ + return dma->ops->probe(dma); +} + +static inline int dma_remove_legacy(struct dma *dma) +{ + return dma->ops->remove(dma); +} + +static inline int dma_get_data_size_legacy(struct dma_chan_data *channel, + uint32_t *avail, uint32_t *free) +{ + return channel->dma->ops->get_data_size(channel, avail, free); +} + +static inline int dma_get_attribute_legacy(struct dma *dma, uint32_t type, + uint32_t *value) +{ + return dma->ops->get_attribute(dma, type, value); +} + +static inline int dma_interrupt_legacy(struct dma_chan_data *channel, + enum dma_irq_cmd cmd) +{ + return channel->dma->ops->interrupt(channel, cmd); +} + +#define dma_set_drvdata(dma, data) \ + (dma->priv_data = data) +#define dma_get_drvdata(dma) \ + dma->priv_data +#define dma_base(dma) \ + dma->plat_data.base +#define dma_irq(dma) \ + dma->plat_data.irq +#define dma_irq_name(dma) \ + dma->plat_data.irq_name +#define dma_chan_size(dma) \ + dma->plat_data.chan_size +#define dma_chan_base(dma, chan) \ + (dma->plat_data.base + chan * dma->plat_data.chan_size) +#define dma_chan_get_data(chan) \ + ((chan)->priv_data) +#define dma_chan_set_data(chan, data) \ + ((chan)->priv_data = data) + +/* DMA hardware register operations */ +static inline uint32_t dma_reg_read(struct dma *dma, uint32_t reg) +{ + return io_reg_read(dma_base(dma) + reg); +} + +static inline uint16_t dma_reg_read16(struct dma *dma, uint32_t reg) +{ + return io_reg_read16(dma_base(dma) + reg); +} + +static inline void dma_reg_write(struct dma *dma, uint32_t reg, uint32_t value) +{ + io_reg_write(dma_base(dma) + reg, value); +} + +static inline void dma_reg_write16(struct dma *dma, uint32_t reg, + uint16_t value) +{ + io_reg_write16(dma_base(dma) + reg, value); +} + +static inline void dma_reg_update_bits(struct dma *dma, uint32_t reg, + uint32_t mask, uint32_t value) +{ + io_reg_update_bits(dma_base(dma) + reg, mask, value); +} + +static inline uint32_t dma_chan_reg_read(struct dma_chan_data *channel, + uint32_t reg) +{ + return io_reg_read(dma_chan_base(channel->dma, channel->index) + reg); +} + +static inline uint16_t dma_chan_reg_read16(struct dma_chan_data *channel, + uint32_t reg) +{ + return io_reg_read16(dma_chan_base(channel->dma, channel->index) + reg); +} + +static inline void dma_chan_reg_write(struct dma_chan_data *channel, + uint32_t reg, uint32_t value) +{ + io_reg_write(dma_chan_base(channel->dma, channel->index) + reg, value); +} + +static inline void dma_chan_reg_write16(struct dma_chan_data *channel, + uint32_t reg, uint16_t value) +{ + io_reg_write16(dma_chan_base(channel->dma, channel->index) + reg, + value); +} + +static inline void dma_chan_reg_update_bits(struct dma_chan_data *channel, + uint32_t reg, uint32_t mask, + uint32_t value) +{ + io_reg_update_bits(dma_chan_base(channel->dma, channel->index) + reg, + mask, value); +} + +static inline void dma_chan_reg_update_bits16(struct dma_chan_data *channel, + uint32_t reg, uint16_t mask, + uint16_t value) +{ + io_reg_update_bits16(dma_chan_base(channel->dma, channel->index) + reg, + mask, value); +} + +/* init dma copy context */ +int dma_copy_new(struct dma_copy *dc); + +/* free dma copy context resources */ +static inline void dma_copy_free(struct dma_copy *dc) +{ + dma_channel_put_legacy(dc->chan); +} + +/* DMA copy data from host to DSP */ +int dma_copy_from_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_from_host_nowait(struct dma_copy *dc, + struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, + int32_t size); + +/* DMA copy data from DSP to host */ +int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); +int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, + int32_t host_offset, void *local_ptr, int32_t size); + + +int dma_copy_set_stream_tag(struct dma_copy *dc, uint32_t stream_tag); + +#endif /* __SOF_LIB_DMA_LEGACY_H__ */ diff --git a/zephyr/include/sof/lib/dma.h b/zephyr/include/sof/lib/dma.h new file mode 100644 index 000000000000..509495634097 --- /dev/null +++ b/zephyr/include/sof/lib/dma.h @@ -0,0 +1,350 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2016,2024 Intel Corporation. + */ + +#ifndef __SOF_LIB_DMA_H__ +#define __SOF_LIB_DMA_H__ + +#if defined(CONFIG_SCHEDULE_DMA_MULTI_CHANNEL) || \ + defined(CONFIG_SCHEDULE_DMA_SINGLE_CHANNEL) +/* + * The platform/lib/dma.h definitions are only needed + * when using old dma_{single,multi}_chan_domain + * implementations. For new SOF build targets, it is + * recommended to use CONFIG_DMA_DOMAIN instead if + * DMA-driven scheduling is needed. + */ +#include <platform/lib/dma.h> +#endif + +#include <rtos/atomic.h> +#include <rtos/bit.h> +#include <rtos/alloc.h> +#include <sof/lib/io.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include <zephyr/device.h> +#include <zephyr/drivers/dma.h> + +struct comp_buffer; +struct comp_dev; +struct k_heap; + +/** \addtogroup sof_dma_drivers DMA Drivers + * SOF DMA Drivers API specification (deprecated interface, to be + * replaced by Zephyr zephyr/drivers/dma.h interface). + * @{ + */ + +/* + * There is significant overlap with SOF DMA interface and + * Zephyr zephyr/drivers/dma.h. Neither uses a unique namespace + * prefix, leading to at times confusing mix of DMA_ and dma_ + * definitions, some coming from legacy SOF definitions, while + * some from Zephyr. + * + * Definitions in this file are used by following SOF code: + * - Some use of SOF DMA data types and definitions exists in + * generic application code (in IPC, host handling and a few other + * places). To support both XTOS and Zephyr builds, these + * definitions must be provided by the RTOS layer. + * - SOF builds where Zephyr is used but platform has not yet + * moved to native Zephyr drivers, so legacy/XTOS DMA are used. + * - Linking DMA resources to audio usages. Even SOF builds with + * native Zephyr build still use some SOF side DMA definitions + * to describe system DMA resources in terms of their capabilities + * for audio use. See sof/zephyr/lib/dma.c for most of this logic. + */ + +/* DMA direction bitmasks used to define DMA copy direction */ +#define SOF_DMA_DIR_MEM_TO_MEM BIT(0) /**< local memory copy */ +#define SOF_DMA_DIR_HMEM_TO_LMEM BIT(1) /**< host memory to local mem copy */ +#define SOF_DMA_DIR_LMEM_TO_HMEM BIT(2) /**< local mem to host mem copy */ +#define SOF_DMA_DIR_MEM_TO_DEV BIT(3) /**< local mem to dev copy */ +#define SOF_DMA_DIR_DEV_TO_MEM BIT(4) /**< dev to local mem copy */ +#define SOF_DMA_DIR_DEV_TO_DEV BIT(5) /**< dev to dev copy */ + +/* DMA capabilities bitmasks used to define the type of DMA */ +#define SOF_DMA_CAP_HDA BIT(0) /**< HDA DMA */ +#define SOF_DMA_CAP_GP_LP BIT(1) /**< GP LP DMA */ +#define SOF_DMA_CAP_GP_HP BIT(2) /**< GP HP DMA */ +#define SOF_DMA_CAP_BT BIT(3) /**< BT DMA */ +#define SOF_DMA_CAP_SP BIT(4) /**< SP DMA */ +#define SOF_DMA_CAP_DMIC BIT(5) /**< ACP DMA DMIC > */ +#define SOF_DMA_CAP_SP_VIRTUAL BIT(6) /**< SP VIRTUAL DMA */ +#define SOF_DMA_CAP_HS_VIRTUAL BIT(7) /**< HS VIRTUAL DMA */ +#define SOF_DMA_CAP_HS BIT(8) /**< HS DMA */ +#define SOF_DMA_CAP_SW BIT(9) /**< SW DMA */ + +/* DMA dev type bitmasks used to define the type of DMA */ + +#define SOF_DMA_DEV_HOST BIT(0) /**< connectable to host */ +#define SOF_DMA_DEV_HDA BIT(1) /**< connectable to HD/A link */ +#define SOF_DMA_DEV_SSP BIT(2) /**< connectable to SSP fifo */ +#define SOF_DMA_DEV_DMIC BIT(3) /**< connectable to DMIC fifo */ +#define SOF_DMA_DEV_SSI BIT(4) /**< connectable to SSI / SPI fifo */ +#define SOF_DMA_DEV_ALH BIT(5) /**< connectable to ALH link */ +#define SOF_DMA_DEV_SAI BIT(6) /**< connectable to SAI fifo */ +#define SOF_DMA_DEV_ESAI BIT(7) /**< connectable to ESAI fifo */ +#define SOF_DMA_DEV_BT BIT(8) /**< connectable to ACP BT I2S */ +#define SOF_DMA_DEV_SP BIT(9) /**< connectable to ACP SP I2S */ +#define SOF_DMA_DEV_AFE_MEMIF BIT(10) /**< connectable to AFE fifo */ +#define SOF_DMA_DEV_SP_VIRTUAL BIT(11) /**< connectable to ACP SP VIRTUAL I2S */ +#define SOF_DMA_DEV_HS_VIRTUAL BIT(12) /**< connectable to ACP HS VIRTUAL I2S */ +#define SOF_DMA_DEV_HS BIT(13) /**< connectable to ACP HS I2S */ +#define SOF_DMA_DEV_MICFIL BIT(14) /**< connectable to MICFIL fifo */ +#define SOF_DMA_DEV_SW BIT(15) /**< connectable to ACP SW */ + +/* DMA access privilege flag */ +#define SOF_DMA_ACCESS_EXCLUSIVE 1 +#define SOF_DMA_ACCESS_SHARED 0 + +/* DMA copy flags */ +#define SOF_DMA_COPY_BLOCKING BIT(0) +#define SOF_DMA_COPY_ONE_SHOT BIT(1) + +/* We will use this enum in cb handler to inform dma what + * action we need to perform. + */ +enum sof_dma_cb_status { + SOF_DMA_CB_STATUS_RELOAD = 0, + SOF_DMA_CB_STATUS_END, +}; + +#define SOF_DMA_CHAN_INVALID 0xFFFFFFFF +#define SOF_DMA_CORE_INVALID 0xFFFFFFFF + +/* Attributes have been ported to Zephyr. This condition is necessary until full support of + * CONFIG_SOF_ZEPHYR_STRICT_HEADERS. + */ +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +struct sof_dma; +#else +struct dma; +#endif + +/** + * \brief Element of SG list (as array item). + */ +struct dma_sg_elem { + uint32_t src; /**< source address */ + uint32_t dest; /**< destination address */ + uint32_t size; /**< size (in bytes) */ +}; + +/** + * \brief Data used in DMA callbacks. + */ +struct dma_cb_data { + struct dma_chan_data *channel; + struct dma_sg_elem elem; + enum sof_dma_cb_status status; +}; + +/** + * \brief SG elem array. + */ +struct dma_sg_elem_array { + uint32_t count; /**< number of elements in elems */ + struct dma_sg_elem *elems; /**< elements */ +}; + +/* DMA physical SG params */ +struct dma_sg_config { + uint32_t src_width; /* in bytes */ + uint32_t dest_width; /* in bytes */ + uint32_t burst_elems; + uint32_t direction; + uint32_t src_dev; + uint32_t dest_dev; + uint32_t cyclic; /* circular buffer */ + uint64_t period; + struct dma_sg_elem_array elem_array; /* array of dma_sg elems */ + bool scatter; + bool irq_disabled; + /* true if configured DMA channel is the scheduling source */ + bool is_scheduling_source; +}; + +struct dma_chan_status { + uint32_t state; + uint32_t flags; + uint32_t w_pos; + uint32_t r_pos; + uint32_t timestamp; + + /* dma position info for ipc4 */ + void *ipc_posn_data; +}; + +struct dma_ops; +/* DMA platform data */ +struct dma_plat_data { + uint32_t id; + uint32_t dir; /* bitmask of supported copy directions */ + uint32_t caps; /* bitmask of supported capabilities */ + uint32_t devs; /* bitmask of supported devs */ + uint32_t base; + uint32_t channels; + int irq; + const char *irq_name; + uint32_t chan_size; + const void *drv_plat_data; + uint32_t period_count; +}; + +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +struct sof_dma { +#else +struct dma { +#endif + struct dma_plat_data plat_data; + struct k_spinlock lock; /**< locking mechanism */ + int sref; /**< simple ref counter, guarded by lock */ + const struct dma_ops *ops; + atomic_t num_channels_busy; /* number of busy channels */ + struct dma_chan_data *chan; /* channels array */ + const struct device *z_dev; /* Zephyr driver */ + void *priv_data; +}; + +struct dma_chan_data { +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + struct sof_dma *dma; +#else + struct dma *dma; +#endif + + uint32_t status; + uint32_t direction; + uint32_t desc_count; + uint32_t index; + uint32_t core; + uint64_t period; /* DMA channel's transfer period in us */ + /* true if this DMA channel is the scheduling source */ + bool is_scheduling_source; + + /* device specific data set by the device that requests the DMA channel */ + void *dev_data; + + void *priv_data; +}; + +struct dma_info { +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + struct sof_dma *dma_array; +#else + struct dma *dma_array; +#endif + size_t num_dmas; +}; + +/* generic DMA DSP <-> Host copier */ +struct dma_copy { + struct dma_chan_data *chan; +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + struct sof_dma *dmac; +#else + struct dma *dmac; +#endif +}; + +struct audio_stream; +typedef int (*dma_process_func)(const struct audio_stream *source, + uint32_t ioffset, struct audio_stream *sink, + uint32_t ooffset, uint32_t source_samples, uint32_t chmap); + +/** + * \brief API to initialize a platform DMA controllers. + * + * \param[in] sof Pointer to firmware main context. + */ +int dmac_init(struct sof *sof); + +/* + * Need to use sof_dma.h to avoid "syscalls/dma.h" name conflict + * with Zephyr autogenerated headers for syscall support. + */ +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS +#include "sof_dma.h" +#else +#include "dma-legacy.h" +#endif /* !CONFIG_ZEPHYR_NATIVE_DRIVERS */ + +#if defined(CONFIG_SCHEDULE_DMA_MULTI_CHANNEL) || \ + defined(CONFIG_SCHEDULE_DMA_SINGLE_CHANNEL) + +static inline bool dma_is_scheduling_source(struct dma_chan_data *channel) +{ + return channel->is_scheduling_source; +} +#endif + +static inline void dma_sg_init(struct dma_sg_elem_array *ea) +{ + ea->count = 0; + ea->elems = NULL; +} + +int dma_sg_alloc(struct k_heap *heap, + struct dma_sg_elem_array *ea, + uint32_t flags, + uint32_t direction, + uint32_t buffer_count, uint32_t buffer_bytes, + uintptr_t dma_buffer_addr, uintptr_t external_addr); + +void dma_sg_free(struct k_heap *heap, struct dma_sg_elem_array *ea); + +/** + * \brief Get the total size of SG buffer + * + * \param ea Array of SG elements. + * \return Size of the buffer. + */ +static inline uint32_t dma_sg_get_size(struct dma_sg_elem_array *ea) +{ + int i; + uint32_t size = 0; + + for (i = 0 ; i < ea->count; i++) + size += ea->elems[i].size; + + return size; +} + +/* copies data from DMA buffer using provided processing function */ +int dma_buffer_copy_from(struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t source_bytes, uint32_t chmap); + +/* + * Used when copying stream audio 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 stream_copy_from_no_consume(struct comp_dev *dev, + struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, + uint32_t source_bytes, uint32_t chmap); + +/* copies data to DMA buffer using provided processing function */ +int dma_buffer_copy_to(struct comp_buffer *source, + struct comp_buffer *sink, + dma_process_func process, uint32_t sink_bytes, uint32_t chmap); + + +static inline const struct dma_info *dma_info_get(void) +{ + return sof_get()->dma_info; +} + +/** @}*/ + +#endif /* __SOF_LIB_DMA_H__ */ diff --git a/zephyr/include/sof/lib/io.h b/zephyr/include/sof/lib/io.h new file mode 100644 index 000000000000..c7661fbe552c --- /dev/null +++ b/zephyr/include/sof/lib/io.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifndef __ZEPHYR_SOF_LIB_IO_H__ +#define __ZEPHYR_SOF_LIB_IO_H__ + +#if CONFIG_LIBRARY + +#define io_reg_read16(reg) 0 +#define io_reg_write16(reg, val) +#define io_reg_update_bits16(reg, mask, value) +#define io_reg_read(reg) 0 +#define io_reg_write(reg, val) +#define io_reg_update_bits(reg, mask, value) + +#else + +#include <zephyr/arch/cpu.h> + +static inline uint8_t io_reg_read8(uint32_t reg) +{ + return sys_read8(reg); +} + +static inline void io_reg_write8(uint32_t reg, uint8_t val) +{ + sys_write8(val, reg); +} + +static inline void io_reg_update_bits8(uint32_t reg, + uint8_t mask, + uint8_t value) +{ + io_reg_write8(reg, (io_reg_read8(reg) & (~mask)) | (value & mask)); +} + +static inline uint16_t io_reg_read16(uint32_t reg) +{ + return sys_read16(reg); +} + +static inline void io_reg_write16(uint32_t reg, uint16_t val) +{ + sys_write16(val, reg); +} + +static inline void io_reg_update_bits16(uint32_t reg, + uint16_t mask, + uint16_t value) +{ + io_reg_write16(reg, (io_reg_read16(reg) & (~mask)) | (value & mask)); +} + +static inline uint32_t io_reg_read(uint32_t reg) +{ + return sys_read32(reg); +} + +static inline void io_reg_write(uint32_t reg, uint32_t val) +{ + sys_write32(val, reg); +} + +static inline void io_reg_update_bits(uint32_t reg, + uint32_t mask, + uint32_t value) +{ + io_reg_write(reg, (io_reg_read(reg) & (~mask)) | (value & mask)); +} + +static inline uint64_t io_reg_read64(uint32_t reg) +{ +#if CONFIG_64BIT + return sys_read64(reg); +#else + return (uint64_t)io_reg_read(reg) + + (((uint64_t)io_reg_read(reg + 4)) << 32); +#endif /* CONFIG_64BIT */ +} + +#endif /* CONFIG_LIBRARY */ + +#endif /* __ZEPHYR_SOF_LIB_IO_H__ */ diff --git a/zephyr/include/sof/lib/memory.h b/zephyr/include/sof/lib/memory.h new file mode 100644 index 000000000000..6fa6a8ef558d --- /dev/null +++ b/zephyr/include/sof/lib/memory.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_LIB_MEMORY_H__ +#define __SOF_LIB_MEMORY_H__ + +#include <platform/lib/memory.h> + +#ifndef __cold +#define __cold +#endif + +#ifndef __cold_rodata +#define __cold_rodata +#endif + +#if CONFIG_COLD_STORE_EXECUTE_DEBUG +#include <rtos/panic.h> + +#ifdef __ZEPHYR__ +bool ll_sch_is_current(void); +#else +#define ll_sch_is_current() false +#endif + +void dbg_path_hot_start_watching(void); +void dbg_path_hot_stop_watching(void); +void dbg_path_hot_confirm(void); +void dbg_path_cold_enter(const char *fn); + +static inline void __assert_can_be_cold(const char *fn) +{ + if (k_is_user_context()) + return; + + __ASSERT(!ll_sch_is_current(), "%s() called from an LL thread!", fn); + dbg_path_cold_enter(fn); +} +#define assert_can_be_cold() __assert_can_be_cold(__func__) +#else +#define dbg_path_hot_start_watching() do {} while (0) +#define dbg_path_hot_stop_watching() do {} while (0) +#define dbg_path_hot_confirm() do {} while (0) +#define dbg_path_cold_enter() do {} while (0) +#define assert_can_be_cold() do {} while (0) +#endif + +#endif /* __SOF_LIB_MEMORY_H__ */ diff --git a/zephyr/include/sof/lib/mm_heap.h b/zephyr/include/sof/lib/mm_heap.h new file mode 100644 index 000000000000..634b336d9e40 --- /dev/null +++ b/zephyr/include/sof/lib/mm_heap.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_LIB_MM_HEAP_H__ +#define __SOF_LIB_MM_HEAP_H__ + +/* no-op on Zephyr */ + +#endif /* __SOF_LIB_MM_HEAP_H__ */ diff --git a/zephyr/include/sof/lib/pm_runtime.h b/zephyr/include/sof/lib/pm_runtime.h new file mode 100644 index 000000000000..ee02eff51aad --- /dev/null +++ b/zephyr/include/sof/lib/pm_runtime.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_LIB_PM_RUNTIME_H__ +#define __SOF_LIB_PM_RUNTIME_H__ + +#include <rtos/sof.h> +#include <stdint.h> + +/** \addtogroup pm_runtime PM Runtime + * SOF PM runtime specification mapping for Zephyr builds. + * + * This interface is considered deprecated and native Zephyr + * interfaces should be used instead. + * @{ + */ + +/** \brief Runtime power management context */ +enum pm_runtime_context { + PM_RUNTIME_DSP /**< DSP */ +}; + +/** + * \brief Initializes runtime power management. + */ +static inline void pm_runtime_init(struct sof *sof) +{ +} + +/** + * \brief Retrieves power management resource (async). + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_get(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Retrieves power management resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +static inline void pm_runtime_get_sync(enum pm_runtime_context context, uint32_t index) +{ +} + + +/** + * \brief Releases power management resource (async). + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_put(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Releases power management resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +static inline void pm_runtime_put_sync(enum pm_runtime_context context, uint32_t index) +{ +} + +/** + * \brief Enables power management operations for the resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_enable(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Disables power management operations for the resource. + * + * \param[in] context Type of power management context. + * \param[in] index Index of the device. + */ +void pm_runtime_disable(enum pm_runtime_context context, uint32_t index); + +/** + * \brief Reports state of the power managed resource. + * + * @param context Type of power management context. + * @param index Index of the resource. + * + * @return true if the resource is active or pm disabled, false otherwise. + */ +bool pm_runtime_is_active(enum pm_runtime_context context, uint32_t index); + +static inline void platform_pm_runtime_prepare_d0ix_en(uint32_t index) +{ +} + +#if CONFIG_DSP_RESIDENCY_COUNTERS + +/** + * \brief Initializes DSP residency counters. + * + * \param[in] context Type of power management context. + */ +static inline void init_dsp_r_state(enum dsp_r_state) +{ +} + +/** + * \brief Reports DSP residency state. + * + * \param[in] new state + */ +static inline void report_dsp_r_state(enum dsp_r_state) +{ +} + +/** + * \brief Retrieves current DSP residency state. + * + * @return active DSP residency state + */ +static inline enum dsp_r_state get_dsp_r_state(void) +{ +} +#endif + +/** @}*/ + +#endif /* __SOF_LIB_PM_RUNTIME_H__ */ diff --git a/zephyr/include/sof/lib/regions_mm.h b/zephyr/include/sof/lib/regions_mm.h new file mode 100644 index 000000000000..abaaf158d3d4 --- /dev/null +++ b/zephyr/include/sof/lib/regions_mm.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright(c) 2022 - 2023 Intel Corporation. All rights reserved. + * + * Author: Jakub Dabek <jakub.dabek@intel.com> + */ + +#ifndef ZEPHYR_LIB_REGIONS_MM_H_ +#define ZEPHYR_LIB_REGIONS_MM_H_ + +#include <adsp_memory.h> +#include <adsp_memory_regions.h> +#include <ipc/topology.h> +#include <rtos/alloc.h> +#include <sof/list.h> +#include <zephyr/drivers/mm/system_mm.h> +#include <zephyr/init.h> +#include <zephyr/sys/mem_blocks.h> + +/* Attributes for memory regions */ +#define VIRTUAL_REGION_SHARED_HEAP_ATTR 1U /*< region for shared virtual heap */ +#define VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR 2U /*< region for LLEXT libraries */ +#define VIRTUAL_REGION_VPAGES_ATTR 3U /*< region for virtual page allocator */ + +/* Dependency on ipc/topology.h created due to memory capability definitions + * that are defined there + */ + +/* API is NOT re-entry safe. + * This is due to our assumption that only management code will ever handle + * memory operations on heaps themselves. + */ + +/* Defines maximum amount of memory block allocators in one heap + * since minimum realistic block should be cache line size + * and block sizes in allocator must be powers of 2 + * so logically it gives limited block sizes + * eg allocator of block size 64 128 256 512 2048 4096 1024 8192 + * would end up in 8 allocators. + * It is expected that allocations bigger than that would + * either be spanned on specifically configured heap or have + * individual configs with bigger block sizes. + */ +#define MAX_MEMORY_ALLOCATORS_COUNT 10 + +/* vmh_get_default_heap_config() function will try to split the region + * down the given count. Only applicable when API client did not + * use its config. + */ +#define DEFAULT_CONFIG_ALOCATORS_COUNT 5 + +/** @struct vmh_block_bundle_descriptor + * + * @brief This is a struct describing one bundle of blocks + * used as base for allocators blocks. + * + * @var block_size size of memory block. + * @var number_of_blocks number of memory blocks. + */ +struct vmh_block_bundle_descriptor { + size_t block_size; + size_t number_of_blocks; +}; + +/* + * Maybe this heap config should have small bundles first going up to max + * size or there should be a sorting mechanism for those ? + * Should we assume that bundles are given from smallest to biggest ? + */ + +/** @struct vmh_heap_config + * + * @brief This is a struct that aggregates vmh_block_bundle_descriptor to + * create one cfg that can be passed to heap initiation. + * Provided config size must be physical page aligned so it + * will not overlap in physical space with other heaps during mapping. + * So every block has to have its overall size aligned to CONFIG_MM_DRV_PAGE_SIZE + * + * @vmh_block_bundle_descriptor[] aggregation of bundle descriptors. + */ +struct vmh_heap_config { + struct vmh_block_bundle_descriptor block_bundles_table[MAX_MEMORY_ALLOCATORS_COUNT]; +}; + +struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocating_continuously); +void *vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size); +int vmh_free_heap(struct vmh_heap *heap); +int vmh_free(struct vmh_heap *heap, void *ptr); +void vmh_get_default_heap_config(const struct sys_mm_drv_region *region, + struct vmh_heap_config *cfg); +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS +void vmh_log_stats(struct vmh_heap *heap); +#endif +/** + * @brief Checks if ptr is in range of given memory range + * + * @param ptr checked ptr + * @param range_start start of checked memory range + * @param range_size size of checked memory range. + * + * @retval false if no overlap detected. + * @retval true if any overlap detected. + */ +static inline bool vmh_is_ptr_in_memory_range(uintptr_t ptr, uintptr_t range_start, + size_t range_size) +{ + return ptr >= range_start && ptr < range_start + range_size; +} + +#endif /* ZEPHYR_LIB_REGIONS_MM_H_ */ diff --git a/zephyr/include/sof/lib/sof_dma.h b/zephyr/include/sof/lib/sof_dma.h new file mode 100644 index 000000000000..bdd64aeac9fa --- /dev/null +++ b/zephyr/include/sof/lib/sof_dma.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2025, Intel Corporation. + */ + +/* + * Need to use sof_dma.h to avoid "syscalls/dma.h" name conflict + * with Zephyr autogenerated headers for syscall support. + */ + +#ifndef SOF_DMA_H +#define SOF_DMA_H + +/** + * \brief API to request a platform DMAC. + * + * Users can request DMAC based on dev type, copy direction, capabilities + * and access privilege. + * For exclusive access, ret DMAC with no channels draining. + * For shared access, ret DMAC with the least number of channels draining. + */ +__syscall struct sof_dma *sof_dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags); + +struct sof_dma *z_impl_sof_dma_get(uint32_t dir, uint32_t cap, uint32_t dev, uint32_t flags); + + +/** + * \brief API to release a platform DMAC. + * + * @param[in] dma DMAC to release. + */ +__syscall void sof_dma_put(struct sof_dma *dma); + +void z_impl_sof_dma_put(struct sof_dma *dma); + +__syscall int sof_dma_get_attribute(struct sof_dma *dma, uint32_t type, uint32_t *value); + +__syscall int sof_dma_request_channel(struct sof_dma *dma, uint32_t stream_tag); + +__syscall void sof_dma_release_channel(struct sof_dma *dma, + uint32_t channel); + +__syscall int sof_dma_config(struct sof_dma *dma, uint32_t channel, + struct dma_config *config); + +__syscall int sof_dma_start(struct sof_dma *dma, uint32_t channel); + +__syscall int sof_dma_stop(struct sof_dma *dma, uint32_t channel); + +__syscall int sof_dma_get_status(struct sof_dma *dma, uint32_t channel, struct dma_status *stat); + +__syscall int sof_dma_reload(struct sof_dma *dma, uint32_t channel, size_t size); + +__syscall int sof_dma_suspend(struct sof_dma *dma, uint32_t channel); + +__syscall int sof_dma_resume(struct sof_dma *dma, uint32_t channel); + +static inline int z_impl_sof_dma_get_attribute(struct sof_dma *dma, uint32_t type, uint32_t *value) +{ + return dma_get_attribute(dma->z_dev, type, value); +} + +static inline int z_impl_sof_dma_request_channel(struct sof_dma *dma, uint32_t stream_tag) +{ + return dma_request_channel(dma->z_dev, &stream_tag); +} + +static inline void z_impl_sof_dma_release_channel(struct sof_dma *dma, + uint32_t channel) +{ + dma_release_channel(dma->z_dev, channel); +} + +static inline int z_impl_sof_dma_config(struct sof_dma *dma, uint32_t channel, + struct dma_config *config) +{ + return dma_config(dma->z_dev, channel, config); +} + + +static inline int z_impl_sof_dma_start(struct sof_dma *dma, uint32_t channel) +{ + return dma_start(dma->z_dev, channel); +} + +static inline int z_impl_sof_dma_stop(struct sof_dma *dma, uint32_t channel) +{ + return dma_stop(dma->z_dev, channel); +} + +static inline int z_impl_sof_dma_get_status(struct sof_dma *dma, uint32_t channel, + struct dma_status *stat) +{ + return dma_get_status(dma->z_dev, channel, stat); +} + +static inline int z_impl_sof_dma_reload(struct sof_dma *dma, uint32_t channel, size_t size) +{ + return dma_reload(dma->z_dev, channel, 0, 0, size); +} + +static inline int z_impl_sof_dma_suspend(struct sof_dma *dma, uint32_t channel) +{ + return dma_suspend(dma->z_dev, channel); +} + +static inline int z_impl_sof_dma_resume(struct sof_dma *dma, uint32_t channel) +{ + return dma_resume(dma->z_dev, channel); +} + +#ifdef CONFIG_SOF_USERSPACE_INTERFACE_DMA + +/* include definitions from generated file */ +#include <zephyr/syscalls/sof_dma.h> + +#else /* !CONFIG_SOF_USERSPACE_INTERFACE_DMA */ + +/* + * SOF-specific mechanism to allow building SOF with user-space + * support enabled in Zephyr, but not including all syscall + * interfaces in the SOF binary. Thee downside is we cannot + * use the zephyr/syscalls/sof_dma.h boilerplate that is autogenerated + * but instead need a manual wrapper that is below here. + * + * This can be removed if DMA is used in all SOF user-space builds. + */ + +static inline struct sof_dma *sof_dma_get(uint32_t dir, uint32_t caps, uint32_t dev, uint32_t flags) +{ + return z_impl_sof_dma_get(dir, caps, dev, flags); +} + +static inline void sof_dma_put(struct sof_dma *dma) +{ + return z_impl_sof_dma_put(dma); +} + +static inline int sof_dma_get_attribute(struct sof_dma *dma, uint32_t type, uint32_t *value) +{ + return z_impl_sof_dma_get_attribute(dma, type, value); +} + +static inline int sof_dma_request_channel(struct sof_dma *dma, uint32_t stream_tag) +{ + return z_impl_sof_dma_request_channel(dma, stream_tag); +} + +static inline void sof_dma_release_channel(struct sof_dma *dma, + uint32_t channel) +{ + return z_impl_sof_dma_release_channel(dma, channel); +} + +static inline int sof_dma_config(struct sof_dma *dma, uint32_t channel, + struct dma_config *config) +{ + return z_impl_sof_dma_config(dma, channel, config); +} + +static inline int sof_dma_start(struct sof_dma *dma, uint32_t channel) +{ + return z_impl_sof_dma_start(dma, channel); +} + +static inline int sof_dma_stop(struct sof_dma *dma, uint32_t channel) +{ + return z_impl_sof_dma_stop(dma, channel); +} + +static inline int sof_dma_get_status(struct sof_dma *dma, uint32_t channel, struct dma_status *stat) +{ + return z_impl_sof_dma_get_status(dma, channel, stat); +} + +static inline int sof_dma_reload(struct sof_dma *dma, uint32_t channel, size_t size) +{ + return z_impl_sof_dma_reload(dma, channel, size); +} + +static inline int sof_dma_suspend(struct sof_dma *dma, uint32_t channel) +{ + return z_impl_sof_dma_suspend(dma, channel); +} + +static inline int sof_dma_resume(struct sof_dma *dma, uint32_t channel) +{ + return z_impl_sof_dma_resume(dma, channel); +} + +#endif /* CONFIG_SOF_USERSPACE_INTERFACE_DMA */ + +#endif diff --git a/zephyr/include/sof/lib/vpage.h b/zephyr/include/sof/lib/vpage.h new file mode 100644 index 000000000000..f3fc8b89e968 --- /dev/null +++ b/zephyr/include/sof/lib/vpage.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright(c) 2025 Intel Corporation. + +/* Virtual Page Allocator API */ +#ifndef __SOF_LIB_VPAGE_H__ +#define __SOF_LIB_VPAGE_H__ + +#include <zephyr/kernel.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Allocate virtual pages + * Allocates a specified number of contiguous virtual memory pages by mapping + * physical pages. + * + * @param[in] pages Number of pages (usually 4kB large) to allocate. + * + * @return Pointer to the allocated virtual memory region, or NULL on failure. + */ +void *vpage_alloc(unsigned int pages); + +/** + * @brief Free virtual pages + * Frees previously allocated virtual memory pages and unmaps them. + * + * @param[in] ptr Pointer to the memory pages to free. + */ +void vpage_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* __SOF_LIB_VPAGE_H__ */ diff --git a/zephyr/include/sof/trace/preproc.h b/zephyr/include/sof/trace/preproc.h new file mode 100644 index 000000000000..83776e6fea4e --- /dev/null +++ b/zephyr/include/sof/trace/preproc.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2024 Intel Corporation. + */ + +#ifndef __SOF_TRACE_PREPROC_H__ +#define __SOF_TRACE_PREPROC_H__ + +#ifdef CONFIG_TRACE +#error "SOF dma-trace (CONFIG_TRACE) not supported in Zephyr builds. \ + Please use CONFIG_ZEPHYR_LOG instead." +#endif + +#ifndef CONFIG_ZEPHYR_LOG + +/* + * Unlike the XTOS version of this macro, this does not silence all + * compiler warnings about unused variables. + */ +#define SOF_TRACE_UNUSED(arg1, ...) ((void)arg1) + +#endif /* CONFIG_ZEPHYR_LOG */ + +#endif /* __SOF_TRACE_PREPROC_H__ */ diff --git a/zephyr/include/sof/trace/trace.h b/zephyr/include/sof/trace/trace.h new file mode 100644 index 000000000000..656b859fb514 --- /dev/null +++ b/zephyr/include/sof/trace/trace.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// + +#ifndef __SOF_TRACE_TRACE1_H__ +#define __SOF_TRACE_TRACE1_H__ + +#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_H_ +#include <zephyr/logging/log.h> +#include <zephyr/sys/printk.h> + +/* Level of SOF trace on Zephyr */ +#define SOF_ZEPHYR_TRACE_LEVEL LOG_LEVEL_INF + +#endif + +/* printk supports uint64_t so use it until LOG is ready */ +#define USE_PRINTK 1 + +/* SOF trace header */ +#include "../../../../src/include/sof/trace/trace.h" + +struct timer; +uint64_t platform_timer_get(struct timer *timer); + +/* + * Override SOF mtrace_printf() macro for now to support Zephyr's shared + * memory logger. Note the DMA trace can be copied to the shared memory + * too thanks to CONFIG_TRACEM. + */ +#undef mtrace_printf + +#if USE_PRINTK +#define mtrace_printf(level, format, ...) \ + do { \ + if ((level) <= SOF_ZEPHYR_TRACE_LEVEL) \ + printk("%llu: " format "\n", sof_cycle_get_64(), \ + ##__VA_ARGS__); \ + } while (0) +#else +#error "TODO: Z_LOG()" +#endif + +#endif /* __INCLUDE_TRACE__ */ diff --git a/zephyr/lib.c b/zephyr/lib.c new file mode 100644 index 000000000000..4c6fbce0b563 --- /dev/null +++ b/zephyr/lib.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2022 NXP +// +// Author: Daniel Baluta <daniel.baluta@nxp.com> + +#include <rtos/string.h> + +#include <stddef.h> +#include <stdint.h> + +void *__vec_memcpy(void *dst, const void *src, size_t len) +{ + return memcpy(dst, src, len); +} + +void *__vec_memset(void *dest, int data, size_t src_size) +{ + return memset(dest, data, src_size); +} diff --git a/zephyr/lib/alloc.c b/zephyr/lib/alloc.c new file mode 100644 index 000000000000..8192c2caff0f --- /dev/null +++ b/zephyr/lib/alloc.c @@ -0,0 +1,699 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + */ + +#include <sof/init.h> +#include <rtos/alloc.h> +#include <rtos/idc.h> +#include <rtos/interrupt.h> +#include <sof/drivers/interrupt-map.h> +#include <sof/schedule/schedule.h> +#include <sof/lib/notifier.h> +#include <sof/lib/pm_runtime.h> +#include <sof/audio/pipeline.h> +#include <sof/schedule/ll_schedule_domain.h> /* for zephyr_ll_user_heap() */ +#include <sof/trace/trace.h> +#include <rtos/symbol.h> +#include <rtos/wait.h> + +#define SHARED_BUFFER_HEAP_MEM_SIZE 0 + +#if CONFIG_L3_HEAP && CONFIG_MMU +#include <kernel_arch_interface.h> +#endif + +#if CONFIG_VIRTUAL_HEAP +#include <sof/lib/regions_mm.h> +#include <zephyr/drivers/mm/mm_drv_intel_adsp_mtl_tlb.h> + +struct vmh_heap; +struct vmh_heap *virtual_buffers_heap; +#endif /* CONFIG_VIRTUAL_HEAP */ + + +/* Zephyr includes */ +#include <zephyr/init.h> +#include <zephyr/kernel.h> +#include <zephyr/pm/policy.h> +#include <version.h> +#include <zephyr/sys/__assert.h> +#include <zephyr/cache.h> + +#if CONFIG_SYS_HEAP_RUNTIME_STATS && CONFIG_IPC_MAJOR_4 +#include <zephyr/sys/sys_heap.h> +#endif + +LOG_MODULE_REGISTER(mem_allocator, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx zephyr_tr; + +/* + * Memory - Create Zephyr HEAP for SOF. + * + * Currently functional but some items still WIP. + */ + +#ifndef HEAP_RUNTIME_SIZE +#define HEAP_RUNTIME_SIZE 0 +#endif + +/* system size not declared on some platforms */ +#ifndef HEAP_SYSTEM_SIZE +#define HEAP_SYSTEM_SIZE 0 +#endif + +/* The Zephyr heap */ + +#if defined(CONFIG_IMX) || defined(CONFIG_AMD) + +#ifdef CONFIG_XTENSA +#define HEAPMEM_SIZE (HEAP_SYSTEM_SIZE + HEAP_RUNTIME_SIZE + HEAP_BUFFER_SIZE) + +/* + * Include heapmem variable in .heap_mem section, otherwise the HEAPMEM_SIZE is + * duplicated in two sections and the sdram0 region overflows. + */ +__section(".heap_mem") static uint8_t __aligned(64) heapmem[HEAPMEM_SIZE]; + +#else + +/* 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]; +#endif /* CONFIG_XTENSA */ + +#elif CONFIG_ACE + +/* + * System heap definition for ACE is defined below. + * It needs to be explicitly packed into dedicated section + * to allow memory management driver to control unused + * memory pages. + */ +#if CONFIG_USERSPACE +#undef SHARED_BUFFER_HEAP_MEM_SIZE +#define SHARED_BUFFER_HEAP_MEM_SIZE ROUND_UP(CONFIG_SOF_ZEPHYR_SHARED_BUFFER_HEAP_SIZE, \ + HOST_PAGE_SIZE) +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP +__section(".shared_heap_mem") +static uint8_t __aligned(HOST_PAGE_SIZE) shared_heapmem[SHARED_BUFFER_HEAP_MEM_SIZE]; +#endif +#endif /* CONFIG_USERSPACE */ +__section(".heap_mem") +static uint8_t __aligned(HOST_PAGE_SIZE) heapmem[HEAPMEM_SIZE - SHARED_BUFFER_HEAP_MEM_SIZE]; + +#elif defined(CONFIG_ARCH_POSIX) + +/* Zephyr native_posix links as a host binary and lacks the automated heap markers */ +#define HEAPMEM_SIZE (256 * 1024) +char __aligned(8) heapmem[HEAPMEM_SIZE]; + +#elif defined(CONFIG_SOC_FAMILY_MTK) + +extern char _mtk_adsp_sram_end; +#if defined(CONFIG_SOC_MT8365) +#define SRAM_START DT_REG_ADDR(DT_NODELABEL(sram1)) +#define SRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sram1)) +#define heapmem ((uint8_t *)SRAM_START) +#else +#define SRAM_START DT_REG_ADDR(DT_NODELABEL(sram0)) +#define SRAM_SIZE DT_REG_SIZE(DT_NODELABEL(sram0)) +#define heapmem ((uint8_t *)ALIGN_UP((uintptr_t)&_mtk_adsp_sram_end, PLATFORM_DCACHE_ALIGN)) +#endif /* CONFIG_SOC_MT8365 */ + +#define SRAM_END (SRAM_START + SRAM_SIZE) + +/* Heap size is limited to 0x7fffU chunk units when CONFIG_SYS_HEAP_SMALL_ONLY is set */ +#if defined(CONFIG_SYS_HEAP_SMALL_ONLY) +#define HEAPMEM_SIZE MIN(((uint8_t *)SRAM_END - heapmem), 0x7fff * 8) +#else +#define HEAPMEM_SIZE ((uint8_t *)SRAM_END - heapmem) +#endif /* CONFIG_SYS_HEAP_SMALL_ONLY */ + +#else + +extern char _end[], _heap_sentry[]; +#define heapmem ((uint8_t *)ALIGN_UP((uintptr_t)_end, PLATFORM_DCACHE_ALIGN)) +#define HEAPMEM_SIZE ((uint8_t *)_heap_sentry - heapmem) + +#endif + +static struct k_heap sof_heap; + +/** + * Checks whether pointer is from a given heap memory. + * @param heap Pointer to a heap. + * @param ptr Pointer to memory being checked. + * @return True if pointer falls into heap memory region, false otherwise. + */ +static bool is_heap_pointer(const struct k_heap *heap, void *ptr) +{ + uintptr_t heap_start = + POINTER_TO_UINT(sys_cache_cached_ptr_get(heap->heap.init_mem)); + uintptr_t heap_end = heap_start + heap->heap.init_bytes; + + if (!sys_cache_is_ptr_cached(ptr)) + ptr = (__sparse_force void *)sys_cache_cached_ptr_get(ptr); + + return ((POINTER_TO_UINT(ptr) >= heap_start) && + (POINTER_TO_UINT(ptr) < heap_end)); +} + +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP +static struct k_heap shared_buffer_heap; + +/** + * Returns the start of HPSRAM Shared memory heap. + * @return Pointer to the HPSRAM Shared memory location which can be used + * for HPSRAM Shared heap. + */ +uintptr_t get_shared_buffer_heap_start(void) +{ + return ROUND_UP(POINTER_TO_UINT(shared_heapmem), HOST_PAGE_SIZE); +} + +/** + * Returns the size of HPSRAM Shared memory heap. + * @return Size of the HPSRAM Shared memory region which can be used for HPSRAM Shared heap. + */ +size_t get_shared_buffer_heap_size(void) +{ + return ROUND_DOWN(SHARED_BUFFER_HEAP_MEM_SIZE, HOST_PAGE_SIZE); +} +#endif /* CONFIG_SOF_USERSPACE_USE_SHARED_HEAP */ + +#if CONFIG_L3_HEAP +static struct k_heap l3_heap; +static struct k_heap l3_heap_copy __imrdata; + +/** + * Returns the start of L3 memory heap. + * @return Pointer to the L3 memory location which can be used for L3 heap. + */ +static inline uintptr_t get_l3_heap_start(void) +{ + /* + * TODO: parse the actual offset using: + * - HfIMRIA1 register + * - rom_ext_load_offset + * - main_fw_load_offset + * - main fw size in manifest + */ + return (uintptr_t)(ROUND_UP(IMR_L3_HEAP_BASE, L3_MEM_PAGE_SIZE)); +} + +/** + * Returns the size of L3 memory heap. + * @return Size of the L3 memory region which can be used for L3 heap. + */ +static inline size_t get_l3_heap_size(void) +{ + /* + * Calculate the IMR heap size using: + * - total IMR size + * - IMR base address + * - actual IMR heap start + */ + size_t offset = IMR_L3_HEAP_BASE - L3_MEM_BASE_ADDR; + + return ROUND_DOWN(ace_imr_get_mem_size() - offset, L3_MEM_PAGE_SIZE); +} + +void l3_heap_save(void) +{ + l3_heap_copy = l3_heap; + LOG_DBG("L3 heap copy: %p", (void *)l3_heap_copy.heap.heap); + dcache_writeback_region((__sparse_force void __sparse_cache *)&l3_heap_copy, + sizeof(l3_heap_copy)); + dcache_writeback_region((__sparse_force void __sparse_cache *)get_l3_heap_start(), + get_l3_heap_size()); +} + +static void *l3_heap_alloc_aligned(struct k_heap *h, size_t min_align, size_t bytes) +{ + k_spinlock_key_t key; + void *ret; +#if CONFIG_SYS_HEAP_RUNTIME_STATS && CONFIG_IPC_MAJOR_4 + struct sys_memory_stats stats; +#endif + if (!cpu_is_primary(arch_proc_id())) { + tr_err(&zephyr_tr, "L3_HEAP available only for primary core!"); + return NULL; + } + + key = k_spin_lock(&h->lock); + ret = sys_heap_aligned_alloc(&h->heap, min_align, bytes); + k_spin_unlock(&h->lock, key); + +#if CONFIG_SYS_HEAP_RUNTIME_STATS && CONFIG_IPC_MAJOR_4 + sys_heap_runtime_stats_get(&h->heap, &stats); + tr_info(&zephyr_tr, "heap allocated: %u free: %u max allocated: %u", + stats.allocated_bytes, stats.free_bytes, stats.max_allocated_bytes); +#endif + + return ret; +} + +static void l3_heap_free(struct k_heap *h, void *mem) +{ + if (!cpu_is_primary(arch_proc_id())) { + tr_err(&zephyr_tr, "L3_HEAP available only for primary core!"); + return; + } + + k_spinlock_key_t key = k_spin_lock(&h->lock); + + sys_heap_free(&h->heap, mem); + k_spin_unlock(&h->lock, key); +} + +#endif + +#if CONFIG_VIRTUAL_HEAP +static void *virtual_heap_alloc(struct vmh_heap *heap, uint32_t flags, size_t bytes, + uint32_t align) +{ + void *mem = vmh_alloc(heap, bytes); + + if (!mem) { +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + vmh_log_stats(heap); +#endif + return NULL; + } + + assert(align == 0 || IS_ALIGNED(mem, align)); + + if (flags & SOF_MEM_FLAG_COHERENT) + return sys_cache_uncached_ptr_get((__sparse_force void __sparse_cache *)mem); + + return mem; +} + +extern int _unused_ram_start_marker; + +/** + * Checks whether pointer is from virtual memory range. + * @param ptr Pointer to memory being checked. + * @return True if pointer falls into virtual memory region, false otherwise. + */ +static bool is_virtual_heap_pointer(void *ptr) +{ + uintptr_t virtual_heap_start = + POINTER_TO_UINT(sys_cache_cached_ptr_get(&_unused_ram_start_marker)); + uintptr_t virtual_heap_end = CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_SIZE; + + if (!sys_cache_is_ptr_cached(ptr)) + ptr = (__sparse_force void *)sys_cache_cached_ptr_get(ptr); + + return ((POINTER_TO_UINT(ptr) >= virtual_heap_start) && + (POINTER_TO_UINT(ptr) < virtual_heap_end)); +} + +static void virtual_heap_free(void *ptr) +{ + int ret; + + ptr = (__sparse_force void *)sys_cache_cached_ptr_get(ptr); + + ret = vmh_free(virtual_buffers_heap, ptr); + if (ret) { + tr_err(&zephyr_tr, "Unable to free %p! %d", ptr, ret); + k_panic(); + } +} + +static const struct vmh_heap_config static_hp_buffers = { + { + { 128, 32}, + { 512, 8}, + { 1024, 44}, + { 2048, 8}, + { 4096, 11}, + { 8192, 10}, +#if CONFIG_VIRTUAL_HEAP_EXTENDED + { 32768, 8}, +#endif + { 65536, 3}, + { 131072, 1}, + { 524288, 1} /* buffer for kpb */ + }, +}; + +static int virtual_heap_init(void) +{ + int ret; + + if (virtual_buffers_heap) + return -EEXIST; + + /* add a virtual memory region */ + ret = adsp_add_virtual_memory_region(adsp_mm_get_unused_l2_start_aligned(), + CONFIG_SOF_ZEPHYR_VIRTUAL_HEAP_REGION_SIZE, + VIRTUAL_REGION_SHARED_HEAP_ATTR); + if (ret) + return ret; + + virtual_buffers_heap = vmh_init_heap(&static_hp_buffers, false); + if (!virtual_buffers_heap) { + tr_err(&zephyr_tr, "Unable to init virtual heap"); + return -ENOMEM; + } + + return 0; +} + +SYS_INIT(virtual_heap_init, POST_KERNEL, 1); + +#endif /* CONFIG_VIRTUAL_HEAP */ + +struct k_heap *sof_sys_heap_get(void) +{ + return &sof_heap; +} + +struct k_heap *sof_sys_user_heap_get(void) +{ +#ifdef CONFIG_SOF_USERSPACE_LL + return zephyr_ll_user_heap(); +#else + /* let sof_heap_alloc() pick */ + return NULL; +#endif +} + +static void *heap_alloc_aligned(struct k_heap *h, size_t min_align, size_t bytes) +{ + k_spinlock_key_t key; + void *ret; +#if CONFIG_SYS_HEAP_RUNTIME_STATS && CONFIG_IPC_MAJOR_4 + struct sys_memory_stats stats; +#endif + + /* + * Zephyr sys_heap stores metadata at start of each + * heap allocation. To ensure no allocated cached buffer + * overlaps the same cacheline with the metadata chunk, + * align both allocation start and size of allocation + * to cacheline. As cached and non-cached allocations are + * mixed, same rules need to be followed for both type of + * allocations. + */ +#ifdef CONFIG_SOF_ZEPHYR_HEAP_CACHED + min_align = MAX(PLATFORM_DCACHE_ALIGN, min_align); + bytes = ALIGN_UP(bytes, PLATFORM_DCACHE_ALIGN); +#endif + + key = k_spin_lock(&h->lock); + ret = sys_heap_aligned_alloc(&h->heap, min_align, bytes); + k_spin_unlock(&h->lock, key); + +#if CONFIG_SYS_HEAP_RUNTIME_STATS && CONFIG_IPC_MAJOR_4 + sys_heap_runtime_stats_get(&h->heap, &stats); + tr_info(&zephyr_tr, "heap allocated: %u free: %u max allocated: %u", + stats.allocated_bytes, stats.free_bytes, stats.max_allocated_bytes); +#endif + + return ret; +} + +static void __sparse_cache *heap_alloc_aligned_cached(struct k_heap *h, + size_t min_align, size_t bytes) +{ + void __sparse_cache *ptr; + + ptr = (__sparse_force void __sparse_cache *)heap_alloc_aligned(h, min_align, bytes); + +#ifdef CONFIG_SOF_ZEPHYR_HEAP_CACHED + if (ptr) + ptr = sys_cache_cached_ptr_get((__sparse_force void *)ptr); +#endif + + return ptr; +} + +static void heap_free(struct k_heap *h, void *mem) +{ + k_spinlock_key_t key = k_spin_lock(&h->lock); +#ifdef CONFIG_SOF_ZEPHYR_HEAP_CACHED + void *mem_uncached; + + if (sys_cache_is_ptr_cached(mem)) { + mem_uncached = sys_cache_uncached_ptr_get((__sparse_force void __sparse_cache *)mem); + sys_cache_data_flush_and_invd_range(mem, + sys_heap_usable_size(&h->heap, mem_uncached)); + + mem = mem_uncached; + } +#endif + + sys_heap_free(&h->heap, mem); + + k_spin_unlock(&h->lock, key); +} + + +void *rmalloc_align(uint32_t flags, size_t bytes, uint32_t alignment) +{ + void *ptr; + struct k_heap *heap; + + /* choose a heap */ + if (flags & SOF_MEM_FLAG_L3) { +#if CONFIG_L3_HEAP + heap = &l3_heap; + /* Uncached L3_HEAP should not be used */ + if (flags & SOF_MEM_FLAG_COHERENT) { + tr_err(&zephyr_tr, "L3_HEAP available for cached addresses only!"); + return NULL; + } + ptr = (__sparse_force void *)l3_heap_alloc_aligned(heap, alignment, bytes); + + return ptr; +#else + k_panic(); +#endif +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP + } else if (flags & SOF_MEM_FLAG_USER_SHARED_BUFFER) { + heap = &shared_buffer_heap; +#endif + } else { + heap = &sof_heap; + } + + if (!(flags & SOF_MEM_FLAG_COHERENT)) { + ptr = (__sparse_force void *)heap_alloc_aligned_cached(heap, alignment, bytes); + } else { + ptr = heap_alloc_aligned(heap, alignment, bytes); + } + + return ptr; +} +EXPORT_SYMBOL(rmalloc_align); + +void *rmalloc(uint32_t flags, size_t bytes) +{ + return rmalloc_align(flags, bytes, 0); +} +EXPORT_SYMBOL(rmalloc); + +void *rbrealloc_align(void *ptr, uint32_t flags, size_t bytes, + size_t old_bytes, uint32_t alignment) +{ + void *new_ptr; + + if (!ptr) { + return rballoc_align(flags, bytes, alignment); + } + + /* Original version returns NULL without freeing this memory */ + if (!bytes) { + /* TODO: Should we call rfree(ptr); */ + tr_err(&zephyr_tr, "realloc failed for 0 bytes"); + return NULL; + } + + new_ptr = rballoc_align(flags, bytes, alignment); + if (!new_ptr) + return NULL; + + if (!(flags & SOF_MEM_FLAG_NO_COPY)) + memcpy_s(new_ptr, bytes, ptr, MIN(bytes, old_bytes)); + + rfree(ptr); + + tr_info(&zephyr_tr, "rbealloc: new ptr %p", new_ptr); + + return new_ptr; +} + +/** + * Similar to rmalloc(), guarantees that returned block is zeroed. + */ +void *rzalloc(uint32_t flags, size_t bytes) +{ + void *ptr = rmalloc(flags, bytes); + + if (ptr) + memset(ptr, 0, bytes); + + return ptr; +} +EXPORT_SYMBOL(rzalloc); + +/** + * Allocates memory block. + * @param flags see SOF_MEM_FLAG_... + * @param bytes Size in bytes. + * @param align Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + */ +void *rballoc_align(uint32_t flags, size_t bytes, uint32_t align) +{ + struct k_heap *heap; + + /* choose a heap */ + if (flags & SOF_MEM_FLAG_L3) { +#if CONFIG_L3_HEAP + heap = &l3_heap; + return (__sparse_force void *)l3_heap_alloc_aligned(heap, align, bytes); +#else + tr_err(&zephyr_tr, "L3_HEAP not available."); + return NULL; +#endif +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP + } else if (flags & SOF_MEM_FLAG_USER_SHARED_BUFFER) { + heap = &shared_buffer_heap; +#endif /* CONFIG_USERSPACE */ + } else { +#if CONFIG_VIRTUAL_HEAP + /* Use virtual heap if it is available */ + if (virtual_buffers_heap) + return virtual_heap_alloc(virtual_buffers_heap, flags, bytes, align); +#endif /* CONFIG_VIRTUAL_HEAP */ + + heap = &sof_heap; + } + + if (flags & SOF_MEM_FLAG_COHERENT) + return heap_alloc_aligned(heap, align, bytes); + + return (__sparse_force void *)heap_alloc_aligned_cached(heap, align, bytes); +} +EXPORT_SYMBOL(rballoc_align); + +/* + * Free's memory allocated by above alloc calls. + */ +void rfree(void *ptr) +{ + if (!ptr) + return; + +#if CONFIG_L3_HEAP + if (is_heap_pointer(&l3_heap, ptr)) { + l3_heap_free(&l3_heap, ptr); + return; + } +#endif + +#if CONFIG_VIRTUAL_HEAP + if (is_virtual_heap_pointer(ptr)) { + virtual_heap_free(ptr); + return; + } +#endif + +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP + if (is_heap_pointer(&shared_buffer_heap, ptr)) { + heap_free(&shared_buffer_heap, ptr); + return; + } +#endif + + heap_free(&sof_heap, ptr); +} +EXPORT_SYMBOL(rfree); + +/* + * To match the fall-back SOF main heap all private heaps should also be in the + * uncached address range. + */ +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + if (flags & (SOF_MEM_FLAG_LARGE_BUFFER | SOF_MEM_FLAG_USER_SHARED_BUFFER)) + return rballoc_align(flags, bytes, alignment); + + if (!heap) + heap = &sof_heap; + + if (flags & SOF_MEM_FLAG_COHERENT) + return heap_alloc_aligned(heap, alignment, bytes); + + return (__sparse_force void *)heap_alloc_aligned_cached(heap, alignment, bytes); +} + +void sof_heap_free(struct k_heap *heap, void *addr) +{ + if (heap && addr && is_heap_pointer(heap, addr)) + heap_free(heap, addr); + else + rfree(addr); +} + +static int heap_init(void) +{ + sys_heap_init(&sof_heap.heap, heapmem, HEAPMEM_SIZE - SHARED_BUFFER_HEAP_MEM_SIZE); + +#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP + shared_buffer_heap.heap.init_mem = shared_heapmem; + shared_buffer_heap.heap.init_bytes = SHARED_BUFFER_HEAP_MEM_SIZE; + sys_heap_init(&shared_buffer_heap.heap, shared_heapmem, SHARED_BUFFER_HEAP_MEM_SIZE); +#endif + +#if CONFIG_L3_HEAP + if (ace_imr_used()) { + void *l3_heap_start = UINT_TO_POINTER(get_l3_heap_start()); + size_t l3_heap_size = get_l3_heap_size(); +#if CONFIG_MMU + void *cached_ptr = sys_cache_cached_ptr_get(l3_heap_start); + uintptr_t va = POINTER_TO_UINT(cached_ptr); + + arch_mem_map(l3_heap_start, va, l3_heap_size, K_MEM_PERM_RW | K_MEM_CACHE_WB); +#endif + if (l3_heap_copy.heap.heap) { + l3_heap = l3_heap_copy; + } else { + l3_heap.heap.init_mem = l3_heap_start; + l3_heap.heap.init_bytes = l3_heap_size; + sys_heap_init(&l3_heap.heap, l3_heap_start, l3_heap_size); + } + } +#endif + + return 0; +} + +/* This is a weak stub for the Cadence libc's allocator (which is just + * a newlib build). It's traditionally been provided like this in SOF + * for the benefit of C++ code where the standard library needs to + * link to a working malloc() even if it will never call it. + */ +struct _reent; +__weak void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) +{ + k_panic(); + return NULL; +} + +SYS_INIT(heap_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); diff --git a/zephyr/lib/clk.c b/zephyr/lib/clk.c new file mode 100644 index 000000000000..0cc9006e3a11 --- /dev/null +++ b/zephyr/lib/clk.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Janusz Jankowski <janusz.jankowski@linux.intel.com> + +#include <sof/lib/notifier.h> +#include <rtos/clk.h> +#include <sof/drivers/ssp.h> +#include <rtos/sof.h> +#include <sof/common.h> +#include <sof/lib/memory.h> +#include <zephyr/device.h> +#include <zephyr/drivers/clock_control.h> + +static SHARED_DATA struct clock_info platform_clocks_info[NUM_CLOCKS]; + +static int select_cpu_freq(int clock, int hz) +{ + return clock_control_set_rate(DEVICE_DT_GET(DT_NODELABEL(clkctl)), NULL, + (clock_control_subsys_rate_t)hz); +} + +void platform_clock_init(struct sof *sof) +{ + uint32_t platform_lowest_clock = CPU_LOWEST_FREQ_IDX; + int i; + + sof->clocks = platform_clocks_info; + + /* + * plafforms using this clk.c implementation must + * declare the CPU clocks first, and there must be at least + * one clock per core. If this model doesn't fit, platform + * needs a custom platform_clock_init. + */ + BUILD_ASSERT(NUM_CLOCKS >= CONFIG_CORE_COUNT, "Invalid NUM_CLOCKS"); + + for (i = 0; i < CONFIG_CORE_COUNT; i++) { + sof->clocks[i] = (struct clock_info) { + .freqs_num = NUM_CPU_FREQ, + .freqs = cpu_freq, + .default_freq_idx = CPU_DEFAULT_IDX, + .current_freq_idx = CPU_DEFAULT_IDX, + .lowest_freq_idx = platform_lowest_clock, + .notification_id = NOTIFIER_ID_CPU_FREQ, + .notification_mask = NOTIFIER_TARGET_CORE_MASK(i), + .set_freq = select_cpu_freq, + }; + } +} diff --git a/zephyr/lib/cpu.c b/zephyr/lib/cpu.c new file mode 100644 index 000000000000..94f004bd7356 --- /dev/null +++ b/zephyr/lib/cpu.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. +// +// Author: Tomasz Leman <tomasz.m.leman@intel.com> + +/** + * \file + * \brief Zephyr RTOS CPU implementation file + * \authors Tomasz Leman <tomasz.m.leman@intel.com> + */ + +#include <sof/audio/component.h> +#if CONFIG_INTEL_ADSP_MIC_PRIVACY +#include <sof/audio/mic_privacy_manager.h> +#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE +static uint32_t mic_disable_status; +#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */ +#endif /* CONFIG_INTEL_ADSP_MIC_PRIVACY */ +#include <sof/init.h> +#include <sof/lib/cpu.h> +#include <sof/lib/pm_runtime.h> +#include <ipc/topology.h> +#include <module/module/base.h> +#include <rtos/alloc.h> + +#include "../audio/copier/copier.h" + +/* Zephyr includes */ +#include <version.h> +#include <zephyr/kernel.h> +#include <zephyr/kernel/smp.h> +#include <zephyr/device.h> +#include <zephyr/drivers/mm/mm_drv_intel_adsp_mtl_tlb.h> + +#if CONFIG_MULTICORE && CONFIG_SMP + +extern K_KERNEL_STACK_ARRAY_DEFINE(z_interrupt_stacks, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ISR_STACK_SIZE); + +static void secondary_init(void *arg) +{ + secondary_core_init(sof_get()); +} + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +#include <sof/trace/trace.h> +#include <rtos/wait.h> + +LOG_MODULE_DECLARE(zephyr, CONFIG_SOF_LOG_LEVEL); + +extern struct tr_ctx zephyr_tr; + +/* address where zephyr PM will save memory during D3 transition */ +#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE +extern void *global_imr_ram_storage; +#endif + +#if CONFIG_PM +#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE +/* + * SOF explicitly manages DAI power states to meet the audio-specific requirement + * that all audio pipelines must be paused prior to entering the D3 power state. + * Zephyr's PM framework is designed to suspend devices based on their runtime + * usage, which does not align with the audio pipeline lifecycle managed by SOF. + * During system PM transitions, Zephyr does not automatically handle the suspension + * of DAIs, as it lacks the context of audio pipeline states. Therefore, SOF + * implements additional logic to synchronize DAI states with the DSP core during + * audio pipeline pauses and resumes. This ensures seamless audio performance and + * data integrity across D3 transitions, which is critical for SOF's operation + * and currently outside the scope of Zephyr's device-level PM capabilities. + */ + +static void suspend_dais(void) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + struct processing_module *mod; + struct copier_data *cd; + struct dai_data *dd; + + list_for_item(clist, &ipc_get()->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT || dev_comp_type(icd->cd) != SOF_COMP_DAI) + continue; + + mod = comp_mod(icd->cd); + cd = module_get_private_data(mod); +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->mic_priv && mic_privacy_manager_get_policy() == MIC_PRIVACY_FW_MANAGED) + mic_disable_status = mic_privacy_get_mic_disable_status(); +#endif + dd = cd->dd[0]; + if (dai_remove(dd->dai->dev) < 0) { + tr_err(&zephyr_tr, "DAI suspend failed, type %d index %d", + dd->dai->type, dd->dai->index); + } + } +} + +static void resume_dais(void) +{ + struct ipc_comp_dev *icd; + struct list_item *clist; + struct processing_module *mod; + struct copier_data *cd; + struct dai_data *dd; + size_t gtw_cfg_size; + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + /* Re-initialize mic privacy manager first to ensure proper state before DAI resume */ + mic_privacy_manager_init(); +#endif + + list_for_item(clist, &ipc_get()->comp_list) { + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT || dev_comp_type(icd->cd) != SOF_COMP_DAI) + continue; + + mod = comp_mod(icd->cd); + cd = module_get_private_data(mod); + dd = cd->dd[0]; + /* gtw_cfg.config_length is in words */ + gtw_cfg_size = cd->config.gtw_cfg.config_length << 2; + if (dai_probe(dd->dai->dev) < 0) { + tr_err(&zephyr_tr, "DAI resume failed on probe, type %d index %d", + dd->dai->type, dd->dai->index); + } else if (dai_set_config(dd->dai, &dd->ipc_config, cd->config.gtw_cfg.config_data, + gtw_cfg_size) < 0) { + tr_err(&zephyr_tr, "DAI resume failed on config, type %d index %d", + dd->dai->type, dd->dai->index); + } + +#if CONFIG_INTEL_ADSP_MIC_PRIVACY + if (cd->mic_priv && mic_privacy_manager_get_policy() == MIC_PRIVACY_FW_MANAGED) { + uint32_t current_mic_status = mic_privacy_get_mic_disable_status(); + + if (mic_disable_status != current_mic_status) { + tr_dbg(&zephyr_tr, "MIC privacy settings cheange after D3"); + struct mic_privacy_settings settings; + + /* Update privacy settings based on new state */ + mic_privacy_fill_settings(&settings, current_mic_status); + mic_privacy_propagate_settings(&settings); + /* Ensure we're starting from a clean state with no fade effects */ + if (cd->mic_priv->mic_privacy_state) { + /* Force immediate mute without fade effect */ + cd->mic_priv->mic_privacy_state = MIC_PRIV_MUTED; + cd->mic_priv->fade_in_out_bytes = 0; + cd->mic_priv->mic_priv_gain_params.gain_env = 0; + cd->mic_priv->mic_priv_gain_params.fade_in_sg_count = 0; + } + } + } +#endif + } +} +#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */ + +void cpu_notify_state_entry(enum pm_state state) +{ + if (!cpu_is_primary(arch_proc_id())) + return; + + if (state == PM_STATE_SOFT_OFF) { +#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE + size_t storage_buffer_size; + + /* allocate IMR global_imr_ram_storage */ + const struct device *tlb_dev = DEVICE_DT_GET(DT_NODELABEL(tlb)); + + __ASSERT_NO_MSG(tlb_dev); + const struct intel_adsp_tlb_api *tlb_api = + (struct intel_adsp_tlb_api *)tlb_dev->api; + + /* get HPSRAM storage buffer size */ + storage_buffer_size = tlb_api->get_storage_size(); + + /* add space for LPSRAM */ + storage_buffer_size += LP_SRAM_SIZE; + + /* allocate IMR buffer and store it in the global pointer */ + global_imr_ram_storage = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_L3, + storage_buffer_size, + PLATFORM_DCACHE_ALIGN); + + /* If no IMR buffer we can not recover */ + if (!global_imr_ram_storage) { + tr_err(&zephyr_tr, "failed to allocate global_imr_ram_storage"); + k_panic(); + } + + /* Suspend all DAI components before entering D3 state. */ + suspend_dais(); +#endif /* CONFIG_ADSP_IMR_CONTEXT_SAVE */ + } +} +#endif /* CONFIG_PM */ + +/* 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. + */ + return; + } +#endif + +#ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE + /* Resume all DAI components after exiting D3 state. */ + resume_dais(); + /* free global_imr_ram_storage */ + rfree(global_imr_ram_storage); + global_imr_ram_storage = NULL; + + /* send FW Ready message */ + int ret = platform_boot_complete(0); + + if (ret) { + tr_err(&zephyr_tr, "platform_boot_complete failed: %d", ret); + k_panic(); + } +#endif + } +} + +int cpu_enable_core(int id) +{ + /* only called from single core, no RMW lock */ + __ASSERT_NO_MSG(cpu_is_primary(arch_proc_id())); + /* + * This is an open-coded version of zephyr/kernel/smp.c + * z_smp_start_cpu(). We do this, so we can use a customized + * secondary_init() for SOF. + */ + + if (arch_cpu_active(id)) + return 0; + +#if CONFIG_PM + /* 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) { + k_smp_cpu_start(id, secondary_init, NULL); + return 0; + } + + k_smp_cpu_resume(id, secondary_init, NULL, true, false); +#endif /* CONFIG_PM */ + + return 0; +} + +void cpu_disable_core(int id) +{ + /* only called from single core, no RMW lock */ + __ASSERT_NO_MSG(cpu_is_primary(arch_proc_id())); + + if (!arch_cpu_active(id)) { + tr_warn(&zephyr_tr, "core %d is already disabled", id); + return; + } +#if defined(CONFIG_PM) + /* TODO: before requesting core shut down check if it's not actively used */ + if (!pm_state_force(id, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0})) { + tr_err(&zephyr_tr, "failed to set PM_STATE_SOFT_OFF on core %d", id); + return; + } + + /* Primary core will be turn off by the host after it enter SOFT_OFF state */ + if (cpu_is_primary(id)) + return; + + /* Broadcasting interrupts to other cores. */ + arch_sched_broadcast_ipi(); + + uint64_t timeout = k_cycle_get_64() + + k_ms_to_cyc_ceil64(CONFIG_SECONDARY_CORE_DISABLING_TIMEOUT); + + /* Waiting for secondary core to enter idle state */ + while (arch_cpu_active(id) && (k_cycle_get_64() < timeout)) + k_busy_wait(1); + + if (arch_cpu_active(id)) { + tr_err(&zephyr_tr, "core %d did not enter idle state", id); + return; + } + + if (soc_adsp_halt_cpu(id) != 0) + tr_err(&zephyr_tr, "failed to disable core %d", id); +#endif /* CONFIG_PM */ +} + +int cpu_is_core_enabled(int id) +{ + return arch_cpu_active(id); +} + +int cpu_enabled_cores(void) +{ + unsigned int i; + int mask = 0; + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) + if (arch_cpu_active(i)) + mask |= BIT(i); + + return mask; +} +#else +static int w_core_enable_mask = 0x1; /*Core 0 is always active*/ + +int cpu_enable_core(int id) +{ + pm_runtime_get(PM_RUNTIME_DSP, PWRD_BY_TPLG | id); + + /* only called from single core, no RMW lock */ + __ASSERT_NO_MSG(cpu_get_id() == PLATFORM_PRIMARY_CORE_ID); + + w_core_enable_mask |= BIT(id); + + return 0; +} + +int cpu_enable_secondary_core(int id) +{ + if (arch_cpu_active(id)) + return 0; + + /* 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) { + k_smp_cpu_start(id, secondary_init, NULL); + return 0; + } + + k_smp_cpu_resume(id, secondary_init, NULL, true, false); + + return 0; +} + +void cpu_disable_core(int id) +{ + /* TODO: call Zephyr API */ + + /* only called from single core, no RMW lock */ + __ASSERT_NO_MSG(cpu_get_id() == PLATFORM_PRIMARY_CORE_ID); + + w_core_enable_mask &= ~BIT(id); +} + +int cpu_is_core_enabled(int id) +{ + return w_core_enable_mask & BIT(id); +} + +int cpu_enabled_cores(void) +{ + return w_core_enable_mask; +} +#endif /* CONFIG_ZEPHYR_NATIVE_DRIVERS */ + +void cpu_power_down_core(uint32_t flags) +{ + /* TODO: use Zephyr version */ +} + +int cpu_restore_secondary_cores(void) +{ + /* TODO: use Zephyr API */ + return 0; +} + +int cpu_secondary_cores_prepare_d0ix(void) +{ + /* TODO: use Zephyr API */ + return 0; +} + +#endif /* CONFIG_MULTICORE && CONFIG_SMP */ diff --git a/zephyr/lib/dma.c b/zephyr/lib/dma.c new file mode 100644 index 000000000000..380c31d48843 --- /dev/null +++ b/zephyr/lib/dma.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022-2024 Intel Corporation. +// +// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> +// Keyon Jie <yang.jie@linux.intel.com> +// Rander Wang <rander.wang@intel.com> +// Janusz Jankowski <janusz.jankowski@linux.intel.com> +// Adrian Bonislawski <adrian.bonislawski@intel.com> +// Adrian Warecki <adrian.warecki@intel.com> + +#include <sof/common.h> +#include <rtos/interrupt.h> +#include <sof/lib/dma.h> +#include <sof/lib/memory.h> +#include <rtos/sof.h> +#include <rtos/spinlock.h> +#include <zephyr/device.h> + +#define DW_DMA_BUFFER_PERIOD_COUNT 0x4 +#define HDA_DMA_BUFFER_PERIOD_COUNT 4 + +SHARED_DATA struct sof_dma dma[] = { +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpgpdma0), okay) +{ /* Low Power GP DMAC 0 */ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_MEM | SOF_DMA_DIR_MEM_TO_DEV | + SOF_DMA_DIR_DEV_TO_MEM | SOF_DMA_DIR_DEV_TO_DEV, + .caps = SOF_DMA_CAP_GP_LP, + .devs = SOF_DMA_DEV_SSP | SOF_DMA_DEV_DMIC | + SOF_DMA_DEV_ALH, + .channels = 8, + .period_count = DW_DMA_BUFFER_PERIOD_COUNT, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(lpgpdma0)), +}, +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpgpdma1), okay) +{ /* Low Power GP DMAC 1 */ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_MEM | SOF_DMA_DIR_MEM_TO_DEV | + SOF_DMA_DIR_DEV_TO_MEM | SOF_DMA_DIR_DEV_TO_DEV, + .caps = SOF_DMA_CAP_GP_LP, + .devs = SOF_DMA_DEV_SSP | SOF_DMA_DEV_DMIC | + SOF_DMA_DEV_ALH, + .channels = 8, + .period_count = DW_DMA_BUFFER_PERIOD_COUNT, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(lpgpdma1)), +}, +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(hda_host_in), okay) +{ /* Host In DMAC */ + .plat_data = { + .dir = SOF_DMA_DIR_LMEM_TO_HMEM, + .caps = SOF_DMA_CAP_HDA, + .devs = SOF_DMA_DEV_HOST, + .channels = DT_PROP(DT_NODELABEL(hda_host_in), dma_channels), + .period_count = HDA_DMA_BUFFER_PERIOD_COUNT, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(hda_host_in)), +}, +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(hda_host_out), okay) +{ /* Host out DMAC */ + .plat_data = { + .dir = SOF_DMA_DIR_HMEM_TO_LMEM, + .caps = SOF_DMA_CAP_HDA, + .devs = SOF_DMA_DEV_HOST, + .channels = DT_PROP(DT_NODELABEL(hda_host_out), dma_channels), + .period_count = HDA_DMA_BUFFER_PERIOD_COUNT, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(hda_host_out)), +}, +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(hda_link_in), okay) +{ /* Link In DMAC */ + .plat_data = { + .dir = SOF_DMA_DIR_DEV_TO_MEM, + .caps = SOF_DMA_CAP_HDA, +#if defined(CONFIG_SOC_ACE20_LNL) || defined(CONFIG_SOC_ACE30) || \ + defined(CONFIG_SOC_ACE40) + .devs = SOF_DMA_DEV_HDA | SOF_DMA_DEV_SSP | + SOF_DMA_DEV_DMIC | SOF_DMA_DEV_ALH, +#else + .devs = SOF_DMA_DEV_HDA, +#endif /* CONFIG_SOC_ACE20_LNL || CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 */ + .channels = DT_PROP(DT_NODELABEL(hda_link_in), dma_channels), + .period_count = HDA_DMA_BUFFER_PERIOD_COUNT, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(hda_link_in)), +}, +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(hda_link_out), okay) +{ /* Link out DMAC */ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV, + .caps = SOF_DMA_CAP_HDA, +#if defined(CONFIG_SOC_ACE20_LNL) || defined(CONFIG_SOC_ACE30) || \ + defined(CONFIG_SOC_ACE40) + .devs = SOF_DMA_DEV_HDA | SOF_DMA_DEV_SSP | + SOF_DMA_DEV_DMIC | SOF_DMA_DEV_ALH, +#else + .devs = SOF_DMA_DEV_HDA, +#endif /* CONFIG_SOC_ACE20_LNL || CONFIG_SOC_ACE30 || CONFIG_SOC_ACE40 */ + .channels = DT_PROP(DT_NODELABEL(hda_link_out), dma_channels), + .period_count = HDA_DMA_BUFFER_PERIOD_COUNT, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(hda_link_out)), +}, +#endif +#ifdef CONFIG_SOC_MIMX9352_A55 +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SAI, + /* TODO: might be worth using `dma-channels` here + * (needs to become a mandatory property) + */ + .channels = 64, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(edma4)), +}, +{ + .plat_data = { + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, + .channels = DT_PROP(DT_NODELABEL(host_dma), dma_channels), + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(host_dma)), +}, +#endif /* CONFIG_SOC_MIMX9352_A55 */ +#if defined(CONFIG_SOC_MIMX8QM6_ADSP) || defined(CONFIG_SOC_MIMX8QX6_ADSP) +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SAI | SOF_DMA_DEV_ESAI, + .channels = 32, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(edma0)), +}, +{ + .plat_data = { + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, + .channels = DT_PROP(DT_NODELABEL(host_dma), dma_channels), + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(host_dma)), +}, +#endif +#if defined(CONFIG_SOC_MIMX8ML8_ADSP) || defined(CONFIG_SOC_MIMX8ML8_M7) +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SAI, + .channels = 32, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(sdma3)), +}, +{ + .plat_data = { + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, + .channels = 32, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(host_dma)), +}, +#endif /* CONFIG_SOC_MIMX8ML8_ADSP */ +#ifdef CONFIG_SOC_MIMX8UD7_ADSP +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SAI, + .channels = 32, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(edma2)), +}, +{ + .plat_data = { + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, + .channels = DT_PROP(DT_NODELABEL(host_dma), dma_channels), + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(host_dma)), +}, +#endif /* CONFIG_SOC_MIMX8UD7_ADSP */ +#ifdef CONFIG_SOC_MIMX9596_M7 +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SAI, + .channels = 64, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(edma2)), +}, +{ + .plat_data = { + .dir = SOF_DMA_DIR_HMEM_TO_LMEM | SOF_DMA_DIR_LMEM_TO_HMEM, + .devs = SOF_DMA_DEV_HOST, + .channels = DT_PROP(DT_NODELABEL(host_dma), dma_channels), + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(host_dma)), +}, +#endif /* CONFIG_SOC_MIMX9596_M7 */ +#if defined(CONFIG_SOC_ACP_7_0) +{ + .plat_data = { + .dir = SOF_DMA_DIR_LMEM_TO_HMEM | + SOF_DMA_DIR_HMEM_TO_LMEM, + .devs = SOF_DMA_DEV_HOST, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 8, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(acp_host_dma)), +}, +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | + SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_SW, + .caps = SOF_DMA_CAP_SW, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 12, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(acp_sdw_dma)), +}, +#endif +}; + +const struct dma_info lib_dma = { + .dma_array = dma, + .num_dmas = ARRAY_SIZE(dma) +}; + +/* Initialize all platform DMAC's */ +int dmac_init(struct sof *sof) +{ + int i; + + sof->dma_info = &lib_dma; + + /* early lock initialization for ref counting */ + for (i = 0; i < sof->dma_info->num_dmas; i++) + k_spinlock_init(&sof->dma_info->dma_array[i].lock); + + return 0; +} diff --git a/zephyr/lib/fast-get.c b/zephyr/lib/fast-get.c new file mode 100644 index 000000000000..9c502284f082 --- /dev/null +++ b/zephyr/lib/fast-get.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2024 Intel Corporation. All rights reserved. +// +// Author: Jyri Sarha <jyri.sarha@linux.intel.com> + +#include <stdbool.h> +#include <stdint.h> +#include <errno.h> + +#include <sof/audio/component.h> +#include <sof/lib/fast-get.h> +#include <sof/lib/vregion.h> +#include <sof/objpool.h> +#include <rtos/alloc.h> +#include <rtos/cache.h> +#include <rtos/kernel.h> +#include <rtos/spinlock.h> +#include <rtos/symbol.h> +#include <ipc/topology.h> + +#ifdef __ZEPHYR__ +#include <zephyr/logging/log.h> +#else +#define LOG_DBG(...) do {} while (0) +#define LOG_INF(...) do {} while (0) +#define LOG_WRN(...) do {} while (0) +#define LOG_ERR(...) do {} while (0) +#endif + +struct sof_fast_get_entry { + const void *dram_ptr; + void *sram_ptr; + size_t size; + unsigned int refcount; +}; + +struct sof_fast_get_data { + struct k_spinlock lock; + struct objpool_head pool; +}; + +static struct sof_fast_get_data fast_get_data = { + .pool.list = LIST_INIT(fast_get_data.pool.list), +}; + +LOG_MODULE_REGISTER(fast_get, CONFIG_SOF_LOG_LEVEL); + +struct fast_get_find { + const void *ptr; + struct sof_fast_get_entry *entry; +}; + +static bool fast_get_find_entry(void *data, void *arg) +{ + struct sof_fast_get_entry *entry = data; + struct fast_get_find *find = arg; + + if (find->ptr != entry->dram_ptr) + return false; + + find->entry = entry; + return true; +} + +#if CONFIG_MM_DRV +#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE +#define FAST_GET_MAX_COPY_SIZE (PAGE_SZ / 2) +#else +#include <sof/platform.h> +#define PAGE_SZ HOST_PAGE_SIZE +#define FAST_GET_MAX_COPY_SIZE 0 +#endif + +#if CONFIG_USERSPACE +static bool fast_get_partition_exists(struct k_mem_domain *domain, void *start, size_t size) +{ + for (unsigned int i = 0; i < domain->num_partitions; i++) { + struct k_mem_partition *dpart = &domain->partitions[i]; + + if (dpart->start == (uintptr_t)start && dpart->size == size) + return true; + } + + return false; +} + +static int fast_get_access_grant(struct k_mem_domain *mdom, void *addr, size_t size) +{ + struct k_mem_partition part = { + .start = (uintptr_t)addr, + .size = ALIGN_UP(size, CONFIG_MM_DRV_PAGE_SIZE), + .attr = K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB, + }; + + LOG_DBG("add %#zx @ %p", part.size, addr); + return k_mem_domain_add_partition(mdom, &part); +} +#endif /* CONFIG_USERSPACE */ + +const void *fast_get(struct mod_alloc_ctx *alloc, const void *dram_ptr, size_t size) +{ + struct k_heap *heap = alloc ? alloc->heap : NULL; +#if CONFIG_USERSPACE + bool current_is_userspace = thread_is_userspace(k_current_get()); +#endif + struct sof_fast_get_data *data = &fast_get_data; + uint32_t alloc_flags = SOF_MEM_FLAG_USER; + struct sof_fast_get_entry *entry; + size_t alloc_size, alloc_align; + const void *alloc_ptr; + k_spinlock_key_t key; + void *ret; + + key = k_spin_lock(&data->lock); + if (IS_ENABLED(CONFIG_USERSPACE) && size > FAST_GET_MAX_COPY_SIZE) { + alloc_size = ALIGN_UP(size, PAGE_SZ); + alloc_align = PAGE_SZ; + alloc_flags |= SOF_MEM_FLAG_LARGE_BUFFER; + } else { + alloc_size = size; + alloc_align = PLATFORM_DCACHE_ALIGN; + } + + if (size > FAST_GET_MAX_COPY_SIZE || !IS_ENABLED(CONFIG_USERSPACE)) + alloc_ptr = dram_ptr; + else + /* When userspace is enabled only share large buffers */ + alloc_ptr = NULL; + + struct fast_get_find find = { + .ptr = alloc_ptr, + }; + objpool_iterate(&fast_get_data.pool, fast_get_find_entry, &find); + entry = find.entry; + if (!entry) { + entry = objpool_alloc(&fast_get_data.pool, sizeof(*entry), + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT); + if (!entry) { + ret = NULL; + goto out; + } + } + +#if CONFIG_USERSPACE + LOG_DBG("%s: %#zx bytes alloc %p entry %p DRAM %p", + current_is_userspace ? "userspace" : "kernel", size, + alloc_ptr, entry->sram_ptr, dram_ptr); +#endif + + if (entry->sram_ptr) { + if (entry->size != size || entry->dram_ptr != dram_ptr) { + LOG_ERR("size %u != %u or ptr %p != %p mismatch", + entry->size, size, entry->dram_ptr, dram_ptr); + ret = NULL; + goto out; + } + + ret = entry->sram_ptr; + +#if CONFIG_USERSPACE + struct k_mem_domain *mdom = k_current_get()->mem_domain_info.mem_domain; + + /* + * We only get there for large buffers, since small buffers with + * enabled userspace don't create fast-get entries + */ + if (current_is_userspace) { + if (!fast_get_partition_exists(mdom, ret, + ALIGN_UP(size, CONFIG_MM_DRV_PAGE_SIZE))) { + LOG_DBG("grant access to domain %p", mdom); + + int err = fast_get_access_grant(mdom, ret, size); + + if (err < 0) { + LOG_ERR("failed to grant additional access err=%d", err); + ret = NULL; + goto out; + } + /* + * The data is constant, so it's safe to use cached access to + * it, but initially we have to invalidate caches + */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)ret, + size); + } else { + LOG_WRN("Repeated access request by thread"); + } + } +#endif + + entry->refcount++; + goto out; + } + + if (alloc && alloc->vreg && size <= FAST_GET_MAX_COPY_SIZE) + /* A userspace allocation, that won't be shared */ + ret = vregion_alloc_align(alloc->vreg, VREGION_MEM_TYPE_INTERIM, alloc_size, + alloc_align); + else + ret = sof_heap_alloc(heap, alloc_flags, alloc_size, alloc_align); + if (!ret) + goto out; + + memcpy_s(ret, alloc_size, dram_ptr, size); + dcache_writeback_region((__sparse_force void __sparse_cache *)ret, size); + +#if CONFIG_USERSPACE + if (size > FAST_GET_MAX_COPY_SIZE && current_is_userspace) { + /* Otherwise we've allocated on thread's heap, so it already has access */ + int err = fast_get_access_grant(k_current_get()->mem_domain_info.mem_domain, + ret, size); + + if (err < 0) { + LOG_ERR("failed to grant access err=%d", err); + sof_heap_free(heap, ret); + ret = NULL; + goto out; + } + } +#endif /* CONFIG_USERSPACE */ + + entry->dram_ptr = dram_ptr; + entry->size = size; + entry->sram_ptr = ret; + entry->refcount = 1; +out: + k_spin_unlock(&data->lock, key); + LOG_DBG("get %p, %p, size %u, refcnt %u", dram_ptr, ret, size, entry ? entry->refcount : 0); + + return ret; +} +EXPORT_SYMBOL(fast_get); + +static bool fast_put_find_entry(void *data, void *arg) +{ + struct sof_fast_get_entry *entry = data; + struct fast_get_find *find = arg; + + if (find->ptr != entry->sram_ptr) + return false; + + find->entry = entry; + return true; +} + +void fast_put(struct mod_alloc_ctx *alloc, struct k_mem_domain *mdom, const void *sram_ptr) +{ + struct k_heap *heap = alloc ? alloc->heap : NULL; + struct sof_fast_get_data *data = &fast_get_data; + struct sof_fast_get_entry *entry; + k_spinlock_key_t key; + + key = k_spin_lock(&fast_get_data.lock); + + struct fast_get_find find = { + .ptr = sram_ptr, + }; + objpool_iterate(&fast_get_data.pool, fast_put_find_entry, &find); + entry = find.entry; + if (!entry) { + LOG_ERR("Put called to unknown address %p", sram_ptr); + goto out; + } + + entry->refcount--; + + if (!entry->refcount) { + LOG_DBG("freeing buffer %p", sram_ptr); + if (alloc && alloc->vreg && entry->size <= FAST_GET_MAX_COPY_SIZE) + vregion_free(alloc->vreg, entry->sram_ptr); + else + sof_heap_free(heap, entry->sram_ptr); + } + +#if CONFIG_USERSPACE + /* + * For large buffers, each thread that called fast_get() has a partition + * in its memory domain. Each thread must remove its own partition here + * to prevent partition leaks. + */ + if (entry->size > FAST_GET_MAX_COPY_SIZE && mdom) { + struct k_mem_partition part = { + .start = (uintptr_t)sram_ptr, + .size = ALIGN_UP(entry->size, CONFIG_MM_DRV_PAGE_SIZE), + .attr = K_MEM_PARTITION_P_RO_U_RO | XTENSA_MMU_CACHED_WB, + }; + + LOG_DBG("removing partition %p size %#zx memory domain %p", + (void *)part.start, part.size, mdom); + int err = k_mem_domain_remove_partition(mdom, &part); + + if (err) + LOG_WRN("partition removal failed: %d", err); + } +#endif + + if (!entry->refcount) + memset(entry, 0, sizeof(*entry)); +out: + LOG_DBG("put %p, DRAM %p size %u refcnt %u", sram_ptr, entry ? entry->dram_ptr : 0, + entry ? entry->size : 0, entry ? entry->refcount : 0); + k_spin_unlock(&data->lock, key); +} +EXPORT_SYMBOL(fast_put); diff --git a/zephyr/lib/pm_runtime.c b/zephyr/lib/pm_runtime.c new file mode 100644 index 000000000000..fcaa03cb7275 --- /dev/null +++ b/zephyr/lib/pm_runtime.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +#include <sof/ipc/common.h> +#include <sof/lib/pm_runtime.h> +#include <sof/lib/uuid.h> +#include <sof/trace/trace.h> +#include <user/trace.h> +#include <sof_versions.h> +#include <stdint.h> +#include <zephyr/pm/policy.h> +#include <sof/ipc/driver.h> + +LOG_MODULE_REGISTER(power, CONFIG_SOF_LOG_LEVEL); + +SOF_DEFINE_REG_UUID(power); + +DECLARE_TR_CTX(power_tr, SOF_UUID(power_uuid), LOG_LEVEL_INFO); + +#if defined(CONFIG_PM_POLICY_CUSTOM) +const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) +{ + unsigned int num_cpu_states; + const struct pm_state_info *cpu_states; + + num_cpu_states = pm_state_cpu_get_all(cpu, &cpu_states); + + for (int i = num_cpu_states - 1; i >= 0; i--) { + const struct pm_state_info *state = &cpu_states[i]; + uint32_t min_residency, exit_latency; + + /* policy cannot lead to D3 */ + if (state->state == PM_STATE_SOFT_OFF) + continue; + + /* check if there is a lock on state + substate */ + if (pm_policy_state_lock_is_active(state->state, state->substate_id)) + continue; + + /* checking conditions for D0i3 */ + if (state->state == PM_STATE_RUNTIME_IDLE) { + /* skipping when secondary cores are active */ + if (cpu_enabled_cores() & ~BIT(PLATFORM_PRIMARY_CORE_ID)) + continue; + + /* skipping when some ipc task is not finished */ + if (ipc_get()->task_mask || !ipc_platform_poll_is_host_ready()) + continue; + } + + min_residency = k_us_to_ticks_ceil32(state->min_residency_us); + exit_latency = k_us_to_ticks_ceil32(state->exit_latency_us); + + if (ticks == K_TICKS_FOREVER || + (ticks >= (min_residency + exit_latency))) { + tr_dbg(&power_tr, "transition to state %x (min_residency = %u, exit_latency = %u)", + state->state, min_residency, exit_latency); + return state; + } + } + + return NULL; +} +#endif /* CONFIG_PM_POLICY_CUSTOM */ + +void pm_runtime_enable(enum pm_runtime_context context, uint32_t index) +{ + switch (context) { + case PM_RUNTIME_DSP: + pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + tr_dbg(&power_tr, "removing prevent on d0i3 (lock is active=%d)", + pm_policy_state_lock_is_active(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES)); + break; + default: + break; + } +} + +/** Disables power _management_. The management, not the power. */ +void pm_runtime_disable(enum pm_runtime_context context, uint32_t index) +{ + switch (context) { + case PM_RUNTIME_DSP: + tr_dbg(&power_tr, "putting prevent on d0i3"); + pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); + break; + default: + break; + } +} + +/** Is the _power_ active. The power, not its management. */ +bool pm_runtime_is_active(enum pm_runtime_context context, uint32_t index) +{ + switch (context) { + case PM_RUNTIME_DSP: +#if defined(CONFIG_PM) + return pm_policy_state_lock_is_active(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); +#else + return true; +#endif + default: + break; + } + return false; +} diff --git a/zephyr/lib/regions_mm.c b/zephyr/lib/regions_mm.c new file mode 100644 index 000000000000..9b8db4b504af --- /dev/null +++ b/zephyr/lib/regions_mm.c @@ -0,0 +1,776 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2022 - 2023 Intel Corporation. + * + * Author: Jakub Dabek <jakub.dabek@intel.com> + */ + +#include <zephyr/init.h> + +#if defined(CONFIG_MM_DRV) +#include <sof/lib/regions_mm.h> + +LOG_MODULE_DECLARE(mem_allocator, CONFIG_SOF_LOG_LEVEL); + +/** @struct vmh_heap + * + * @brief This structure holds all information about virtual memory heap + * it aggregates information about its allocations and + * physical mappings. + * + * @var virtual_region pointer to virtual region information, it holds its + * attributes size and beginning ptr provided by zephyr. + * @var physical_blocks_allocators[] a table of block allocators + * each representing a virtual regions part in blocks of a given size + * governed by sys_mem_blocks API. + * @var allocation_sizes[] a table of bit arrays representing sizes of allocations + * made in physical_blocks_allocators directly related to physical_blocks_allocators + * @var allocating_continuously configuration value deciding if heap allocations + * will be contiguous or single block. + */ +struct vmh_heap { + struct k_mutex lock; + const struct sys_mm_drv_region *virtual_region; + struct sys_mem_blocks *physical_blocks_allocators[MAX_MEMORY_ALLOCATORS_COUNT]; + struct sys_bitarray *allocation_sizes[MAX_MEMORY_ALLOCATORS_COUNT]; +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + unsigned int out_of_blocks[MAX_MEMORY_ALLOCATORS_COUNT]; + bool logged; +#endif + bool allocating_continuously; +}; + +/** + * @brief Initialize new heap + * + * Initializes new heap based on region that heap is to be assigned to + * and config. The heap size overall must be aligned to physical page + * size. + * @param cfg Configuration structure with block structure for the heap + * @param allocating_continuously Flag deciding if heap can do contiguous allocation. + * + * @retval ptr to a new heap if successful. + * @retval NULL on creation failure. + */ +struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocating_continuously) +{ + const struct sys_mm_drv_region *virtual_memory_regions = + sys_mm_drv_query_memory_regions(); + int i; + + struct vmh_heap *new_heap = + rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, sizeof(*new_heap)); + + if (!new_heap) + return NULL; + + k_mutex_init(&new_heap->lock); + struct vmh_heap_config new_config = {0}; + const struct sys_mm_drv_region *region; + + SYS_MM_DRV_MEMORY_REGION_FOREACH(virtual_memory_regions, region) { + if (region->attr == VIRTUAL_REGION_SHARED_HEAP_ATTR) { + new_heap->virtual_region = region; + break; + } + } + if (!new_heap->virtual_region || !new_heap->virtual_region->size) + goto fail; + + /* If no config was specified we will use default one */ + if (!cfg) { + vmh_get_default_heap_config(new_heap->virtual_region, &new_config); + cfg = &new_config; + } + + /* Check if configuration provided can fit into virtual regions memory + * and if it is physical page aligned + */ + size_t total_requested_size = 0; + + for (i = 0; i < MAX_MEMORY_ALLOCATORS_COUNT; i++) { + if (cfg->block_bundles_table[i].block_size > 0) { + /* Block sizes can only be powers of 2*/ + if (!is_power_of_2(cfg->block_bundles_table[i].block_size)) + goto fail; + total_requested_size += cfg->block_bundles_table[i].block_size * + cfg->block_bundles_table[i].number_of_blocks; + + if (total_requested_size > new_heap->virtual_region->size || + total_requested_size % CONFIG_MM_DRV_PAGE_SIZE) + goto fail; + } + } + + /* Offset used to calculate where in virtual region to start buffer + * for the memblock + */ + uint32_t offset = 0; + + /* Iterate over all blocks and fill those that have config size value + * higher than 0. + * Each cfg entry is converted into new allocators based on mem_blocks + * API. It needs a lot of runtime allocations for members of mem_blocks. + * The allocation_sizes bit arrays are runtime allocated too. + */ + for (i = 0; i < MAX_MEMORY_ALLOCATORS_COUNT; i++) { + /* Only run for sizes > 0 */ + if (!cfg->block_bundles_table[i].block_size) + continue; + + /* bitarray_size is number of bit bundles that bittaray needs + * to represent memory blocks that's why we div round up number of blocks + * by number of bits in byte + */ + size_t bitarray_size = SOF_DIV_ROUND_UP( + SOF_DIV_ROUND_UP((uint64_t)cfg->block_bundles_table[i].number_of_blocks, 8), + sizeof(uint32_t)); + size_t bitfield_size = sizeof(uint32_t) * bitarray_size; + + /* Need to create structs that are components of mem_blocks and constantly keep + * them in memory on sys_heap. + * First create allocator - instance of sys_mem_blocks struct. + */ + struct sys_mem_blocks *new_allocator = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(sys_mem_blocks_t)); + + if (!new_allocator) + goto fail; + + /* Assign allocator(mem_block) to table */ + new_heap->physical_blocks_allocators[i] = new_allocator; + + /* Fill allocators data based on config and virtual region data */ + new_allocator->info.num_blocks = cfg->block_bundles_table[i].number_of_blocks; + new_allocator->info.blk_sz_shift = ilog2(cfg->block_bundles_table[i].block_size); + new_allocator->buffer = (uint8_t *)new_heap->virtual_region->addr + offset; + + /* Create bit array that is a part of mem_block kept as a ptr */ + struct sys_bitarray *allocators_bitarray = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(sys_bitarray_t)); + + if (!allocators_bitarray) + goto fail; + + allocators_bitarray->num_bits = cfg->block_bundles_table[i].number_of_blocks; + allocators_bitarray->num_bundles = bitarray_size; + new_allocator->bitmap = allocators_bitarray; + + /* Create bit array responsible for saving sizes of allocations + * this bit array is saved in heap struct in a table allocation_sizes + * It is also the same size as the allocator one because they will work + * together as a means to save allocation data. + * Mechanism explained in detail in free and alloc function. + */ + struct sys_bitarray *allocation_sizes_bitarray = + rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + sizeof(sys_bitarray_t)); + + if (!allocation_sizes_bitarray) + goto fail; + + allocation_sizes_bitarray->num_bits = allocators_bitarray->num_bits; + allocation_sizes_bitarray->num_bundles = allocators_bitarray->num_bundles; + new_heap->allocation_sizes[i] = allocation_sizes_bitarray; + + /* Each sys_bitarray has a ptr to bit field that has to be allocated + * based on its size. + */ + uint32_t *allocator_bitarray_bitfield = + rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, bitfield_size); + + if (!allocator_bitarray_bitfield) + goto fail; + + allocators_bitarray->bundles = allocator_bitarray_bitfield; + + uint32_t *sizes_bitarray_bitfield = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + bitfield_size); + + if (!sizes_bitarray_bitfield) + goto fail; + + new_heap->allocation_sizes[i]->bundles = sizes_bitarray_bitfield; + + /* Update offset, note that offset is CONFIG_MM_DRV_PAGE_SIZE aligned + * since every cfg size was checked against it earlier + */ + offset += cfg->block_bundles_table[i].number_of_blocks + * cfg->block_bundles_table[i].block_size; + } + + new_heap->allocating_continuously = allocating_continuously; + + return new_heap; +fail: + for (i = 0; i < MAX_MEMORY_ALLOCATORS_COUNT; i++) { + struct sys_mem_blocks *allocator = new_heap->physical_blocks_allocators[i]; + struct sys_bitarray *allocation_sizes = new_heap->allocation_sizes[i]; + + if (allocator) { + if (allocator->bitmap) + rfree(allocator->bitmap->bundles); + rfree(allocator->bitmap); + } + if (allocation_sizes) { + if (allocation_sizes->bundles) + rfree(allocation_sizes->bundles); + rfree(allocation_sizes); + } + rfree(allocator); + } + rfree(new_heap); + return NULL; +} + +/** + * @brief Checks if region of a sys_mem_blocks have any allocated block + * + * @param blocks Pointer to the sys_mem_blocks allocator + * @param ptr Pointer to the memory region to be checked + * @param size Size of memory region + * + * @retval true if there is any allocation in the queried region + */ +static inline bool vmh_is_region_used(struct sys_mem_blocks *blocks, const uintptr_t ptr, + const size_t size) +{ + __ASSERT_NO_MSG(IS_ALIGNED(size, 1 << blocks->info.blk_sz_shift)); + return !sys_mem_blocks_is_region_free(blocks, UINT_TO_POINTER(ptr), + size >> blocks->info.blk_sz_shift); +} + +/** + * @brief Checks whether the memory region is located on memory pages unused by other allocations + * + * @param allocator Pointer to the sys_mem_blocks allocator + * @param ptr Pointer to the memory region to be checked + * @param size Size of memory region + * @param begin Address to a variable where address of the first unused memory page will be placed + * @param out_size Address to a variable where size of unused memory pages will be placed + * + * @retval true if there is any unused memory page + */ +static bool vmh_get_map_region_boundaries(struct sys_mem_blocks *blocks, const void *ptr, + const size_t size, uintptr_t *begin, size_t *out_size) +{ + __ASSERT_NO_MSG(blocks); + __ASSERT_NO_MSG(begin); + __ASSERT_NO_MSG(out_size); + + const size_t block_size = 1 << blocks->info.blk_sz_shift; + const size_t size_aligned = ALIGN_UP(size, block_size); + uintptr_t addr = ALIGN_DOWN((uintptr_t)ptr, CONFIG_MM_DRV_PAGE_SIZE); + uintptr_t addr_end = ALIGN_UP((uintptr_t)ptr + size, CONFIG_MM_DRV_PAGE_SIZE); + const uintptr_t size_before = (uintptr_t)ptr - addr; + const uintptr_t size_after = addr_end - (uintptr_t)ptr - size_aligned; + + __ASSERT_NO_MSG(IS_ALIGNED(size_before, block_size)); + + if (size_before && vmh_is_region_used(blocks, addr, size_before)) + /* skip first page */ + addr += CONFIG_MM_DRV_PAGE_SIZE; + + if (size_after && vmh_is_region_used(blocks, POINTER_TO_UINT(ptr) + size_aligned, + size_after)) + /* skip last page */ + addr_end -= CONFIG_MM_DRV_PAGE_SIZE; + + if (addr >= addr_end) + return false; + + *begin = addr; + *out_size = addr_end - addr; + return true; +} + +/** + * @brief Determine the size of the mapped memory region. + * + * This function calculates the size of a mapped memory region starting from the given address. + * It uses a binary search algorithm to find the boundary of the mapped region by checking if + * pages are mapped or not. + * + * @param addr Starting address of the memory region. + * @param size Pointer to the size of the memory region. This value will be updated to reflect + * the size of the mapped region. + * + * @retval None + */ +static void vmh_get_mapped_size(void *addr, size_t *size) +{ + int ret; + uintptr_t check, unused; + uintptr_t bottom, top; + + if (*size <= CONFIG_MM_DRV_PAGE_SIZE) + return; + + bottom = (POINTER_TO_UINT(addr)); + top = bottom + *size; + check = top - CONFIG_MM_DRV_PAGE_SIZE; + while (top - bottom > CONFIG_MM_DRV_PAGE_SIZE) { + ret = sys_mm_drv_page_phys_get(UINT_TO_POINTER(check), &unused); + if (!ret) + bottom = check; /* Page is mapped */ + else + top = check; /* Page is unmapped */ + + check = ALIGN_DOWN(bottom / 2 + top / 2, CONFIG_MM_DRV_PAGE_SIZE); + } + + *size = top - POINTER_TO_UINT(addr); +} + +/** + * @brief Maps memory pages for a memory region if they have not been previously mapped for other + * allocations. + * + * @param allocator Pointer to the sys_mem_blocks allocator + * @param ptr Pointer to the memory region + * @param size Size of memory region + * + * @retval 0 on success, error code otherwise. + */ +static int vmh_map_region(const struct sys_mm_drv_region *virtual_region, + struct sys_mem_blocks *region, void *ptr, size_t size) +{ + const size_t block_size = 1 << region->info.blk_sz_shift; + uintptr_t begin; + int ret; + + if (block_size >= CONFIG_MM_DRV_PAGE_SIZE) { + begin = POINTER_TO_UINT(ptr); + size = ALIGN_UP(size, CONFIG_MM_DRV_PAGE_SIZE); + } else { + if (!vmh_get_map_region_boundaries(region, ptr, size, &begin, &size)) + return 0; + } + ret = sys_mm_drv_map_region_safe(virtual_region, UINT_TO_POINTER(begin), 0, size, + SYS_MM_MEM_PERM_RW); + + /* In case of an error, the pages that were successfully mapped must be manually released */ + if (ret) + sys_mm_drv_unmap_region(UINT_TO_POINTER(begin), size); + + return ret; +} + +/** + * @brief Unmaps memory pages for a memory region if they are not used by other allocations. + * + * @param allocator Pointer to the sys_mem_blocks allocator + * @param ptr Pointer to the memory region + * @param size Size of memory region + * + * @retval 0 on success, error code otherwise. + */ +static int vmh_unmap_region(struct sys_mem_blocks *region, void *ptr, size_t size) +{ + const size_t block_size = 1 << region->info.blk_sz_shift; + uintptr_t begin; + + if (block_size >= CONFIG_MM_DRV_PAGE_SIZE) { + size = ALIGN_UP(size, CONFIG_MM_DRV_PAGE_SIZE); + vmh_get_mapped_size(ptr, &size); + return sys_mm_drv_unmap_region(ptr, size); + } + + if (vmh_get_map_region_boundaries(region, ptr, size, &begin, &size)) + return sys_mm_drv_unmap_region((void *)begin, size); + + return 0; +} + +/** + * @brief Alloc function, not reentrant + * + * Allocates memory on heap from provided heap pointer. + * Check if we need to map physical memory for given allocation + * and do it when necessary. + * @param heap pointer to a heap that will be used for allocation. + * @param alloc_size Size in bytes to allocate. + * + * @retval ptr to allocated memory if successful + * @retval NULL on allocation failure + */ +static void *_vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size) +{ + if (!alloc_size) + return NULL; + + void *ptr = NULL; + int mem_block_iterator, allocation_error_code = -ENOMEM; + size_t allocation_bitarray_offset, block_count = 0, block_size = 0, + allocation_bitarray_position = 0; +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + bool first_match = true; +#endif + + /* We will gather error code when allocating on physical block + * allocators. + * Loop will continue as long as there are blocks to iterate on and + * if allocation keeps returning error code. + * When alloc succeeded it will return 0 on allocation and we break + * form loop and continue. + * If allocating_continuously is on for heap, allocation will be made on first available + * block series on given block bundle. For allocating_continuously off allocation will only + * happened on first free block on first allocator that can accommodate + * requested size. + */ + for (mem_block_iterator = 0; mem_block_iterator < MAX_MEMORY_ALLOCATORS_COUNT; + mem_block_iterator++) { + + /* continiue so we do not check mem blocks that do not exist */ + if (!heap->physical_blocks_allocators[mem_block_iterator]) + continue; + + /* calculate block count needed to allocate for current + * mem_block. + */ + block_size = + 1 << heap->physical_blocks_allocators[mem_block_iterator]->info.blk_sz_shift; + block_count = SOF_DIV_ROUND_UP((uint64_t)alloc_size, (uint64_t)block_size); + + /* If we do not span alloc and block is smaller than alloc we try next mem_block */ + if (block_size < alloc_size && !heap->allocating_continuously) + continue; + + if (block_count > + heap->physical_blocks_allocators[mem_block_iterator]->info.num_blocks) + continue; + /* Try span alloc on first available mem_block for non span + * check if block size is sufficient. + */ + if (heap->allocating_continuously) { + allocation_error_code = sys_mem_blocks_alloc_contiguous( + heap->physical_blocks_allocators[mem_block_iterator], block_count, + &ptr); + } else if (block_size >= alloc_size) { + allocation_error_code = sys_mem_blocks_alloc( + heap->physical_blocks_allocators[mem_block_iterator], block_count, + &ptr); + } + /* Save allocation data for purpose of freeing correctly + * afterwards should be changed to a implementation in mem_blocks + * that keeps alloc data there. + */ + if (allocation_error_code == 0) { + /* Mechanism of saving allocation size is a bit complicated and genius + * thought up by Adrian Warecki. + * This explanation is long and will be moved to documentation afterwards. + * Initial setup for mechanism: + * First bit array that saves allocated blocks + * in our system this will be bit array saved in mem_blocks API. + * Second bit array which is of exactly same size of first one + * that will save connection of allocation to size of allocation + * by marking if the bit of allocation is connected to next bit. + * + * Examples: lets have simple 16 bit representation of blocks + * First: 0000000000000000 allocate first four blocks 1111000000000000 + * Second:0000000000000000 1110000000000000 + * The allocator saves whether block was allocated and second bit array + * saves information by marking in position of a bit allocated 1 if + * it is a start of the allocation and has more than one + * block allocated, 1 if following bit is also part of allocation. + * 0 for individually allocated block and 0 for block ending allocation + * Continuing the example above + * First: 1111100000000000 allocate another block 1111100000000000 + * Second:1110000000000000 after the first one 1110000000000000 + * based on information above we know exactly how long allocations were + * by checking second bit array against first one + * First: 1111111100000000 allocate another block 1111111100000000 + * Second:1110000000000000 and another two blocks 1110001000000000 + * We are still able to pinpoint allocations size + */ + + /* Set bits count - 1 on the same offset as in allocation bit array */ + allocation_bitarray_offset = (uintptr_t)ptr + - (uintptr_t)heap->physical_blocks_allocators + [mem_block_iterator]->buffer; + allocation_bitarray_position = allocation_bitarray_offset / block_size; + + /* Need to set bits only if we have more than 1 block to allocate */ + if (block_count - 1) + sys_bitarray_set_region(heap->allocation_sizes[mem_block_iterator], + block_count - 1, allocation_bitarray_position); + break; +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS + } else if (first_match) { + ++heap->out_of_blocks[mem_block_iterator]; + first_match = false; +#endif + } + } + + /* If ptr is NULL it means we did not allocate anything and we should + * break execution here + */ + if (!ptr) + return NULL; + + allocation_error_code = vmh_map_region(heap->virtual_region, + heap->physical_blocks_allocators[mem_block_iterator], + ptr, alloc_size); + if (allocation_error_code) { + sys_mem_blocks_free_contiguous(heap->physical_blocks_allocators[mem_block_iterator], + ptr, block_count); + return NULL; + } + + return ptr; +} + +/** + * @brief Alloc function, reentrant + * see _vmh_alloc comment for details + */ +void *vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size) +{ + k_mutex_lock(&heap->lock, K_FOREVER); + + void *ret = _vmh_alloc(heap, alloc_size); + + k_mutex_unlock(&heap->lock); + return ret; +} + +/** + * @brief Free virtual memory heap + * + * Free the virtual memory heap object and its child allocations + * @param heap Ptr to the heap that is supposed to be freed + * + * @retval 0 on success; + * @retval -ENOTEMPTY on heap having active allocations. + */ +int vmh_free_heap(struct vmh_heap *heap) +{ + int i; + + for (i = 0; i < MAX_MEMORY_ALLOCATORS_COUNT; i++) { + if (!heap->physical_blocks_allocators[i]) + continue; + if (!sys_bitarray_is_region_cleared(heap->physical_blocks_allocators[i]->bitmap, + heap->physical_blocks_allocators[i]->info.num_blocks, 0)) + return -ENOTEMPTY; + } + + for (i = 0; i < MAX_MEMORY_ALLOCATORS_COUNT; i++) { + if (heap->physical_blocks_allocators[i]) { + rfree(heap->physical_blocks_allocators[i]->bitmap->bundles); + rfree(heap->physical_blocks_allocators[i]->bitmap); + rfree(heap->physical_blocks_allocators[i]); + rfree(heap->allocation_sizes[i]->bundles); + rfree(heap->allocation_sizes[i]); + } + } + rfree(heap); + return 0; +} + +/** + * @brief Free ptr allocated on given heap, not reentrant + * + * Free the ptr allocation. After free action is complete + * check if any physical memory block can be freed up as + * result. + * @param heap Pointer to the heap on which ptr param is residing. + * @param ptr pointer that should be freed + * + * @retval 0 on success; + * @retval -ENOTEMPTY on heap having active allocations. + */ +static int _vmh_free(struct vmh_heap *heap, void *ptr) +{ + int retval; + + size_t mem_block_iter, i, size_to_free, block_size, ptr_bit_array_offset, + ptr_bit_array_position, blocks_to_free; + bool ptr_range_found; + + /* Get allocator from which ptr was allocated */ + for (mem_block_iter = 0, ptr_range_found = false; + mem_block_iter < MAX_MEMORY_ALLOCATORS_COUNT; + mem_block_iter++) { + /* continiue so we do not check mem blocks that do not exist */ + if (!heap->physical_blocks_allocators[mem_block_iter]) + continue; + + block_size = + 1 << heap->physical_blocks_allocators[mem_block_iter]->info.blk_sz_shift; + + if (vmh_is_ptr_in_memory_range((uintptr_t)ptr, + (uintptr_t)heap->physical_blocks_allocators + [mem_block_iter]->buffer, + heap->physical_blocks_allocators + [mem_block_iter]->info.num_blocks * block_size)) { + ptr_range_found = true; + break; + } + } + if (!ptr_range_found) + return -EINVAL; + + /* Initially set size to block size */ + size_to_free = block_size; + + /* Get size of the allocation from ptr using allocation_sizes bit array + * and allocators bit array. Only span alloc can have different size than + * block_size. + */ + if (heap->allocating_continuously) { + + /* Not sure if that is fastest way to find the size comments welcome */ + ptr_bit_array_offset = (uintptr_t)ptr + - (uintptr_t)heap->physical_blocks_allocators[mem_block_iter]->buffer; + ptr_bit_array_position = ptr_bit_array_offset / block_size; + + /* Allocation bit array check */ + int bit_value, prev_bit_value = 0; + + sys_bitarray_test_bit(heap->allocation_sizes[mem_block_iter], + ptr_bit_array_position, &bit_value); + /* If checked bit is in position 0 we assume it is valid + * and assigned 0 for further logic + */ + if (ptr_bit_array_position) + sys_bitarray_test_bit(heap->allocation_sizes[mem_block_iter], + ptr_bit_array_position - 1, &prev_bit_value); + + /* If bit is 1 we know we could be at the start of the allocation, + * we need to test previous bit from allocation if it is set then + * something went wrong in calculations. + */ + if (prev_bit_value) + return -EINVAL; + + if (bit_value) { + /* Neeeeeeeds optimization - thinking how to do it properly + * each set bit in order after another means one allocated block. + * When we get to 0 in such range we know that is last allocated block. + * Testing bundles looks promising - need to investigate. + */ + for (i = ptr_bit_array_position; + i < heap->physical_blocks_allocators + [mem_block_iter]->info.num_blocks; + i++) { + + sys_bitarray_test_bit(heap->allocation_sizes[mem_block_iter], i, + &bit_value); + if (bit_value) + size_to_free += block_size; + else + break; + } + } else { + /* We know that there is only one block allocated + * since bit related to alloc is 0 + */ + size_to_free = block_size; + } + blocks_to_free = size_to_free / block_size; + retval = sys_mem_blocks_free_contiguous( + heap->physical_blocks_allocators[mem_block_iter], ptr, + blocks_to_free); + if (!retval) + sys_bitarray_clear_region(heap->allocation_sizes[mem_block_iter], + blocks_to_free, ptr_bit_array_position); + } else { + retval = sys_mem_blocks_free(heap->physical_blocks_allocators[mem_block_iter], + 1, &ptr); + } + + if (retval) + return retval; + + /* Platforms based on xtensa have a non-coherent cache between cores. Before releasing + * a memory block, it is necessary to invalidate the cache. This memory block can be + * allocated by another core and performing cache writeback by the previous owner will + * destroy current content of the main memory. The cache is invalidated by the + * sys_mm_drv_unmap_region function, when a memory page is unmapped. There is no need to + * invalidate it when releasing buffers of at least a page in size. + */ + if (size_to_free < CONFIG_MM_DRV_PAGE_SIZE) + sys_cache_data_invd_range(ptr, size_to_free); + + return vmh_unmap_region(heap->physical_blocks_allocators[mem_block_iter], ptr, + size_to_free); +} + +/** + * @brief Free ptr function, reentrant + * see _vmh_free comment for details + */ +int vmh_free(struct vmh_heap *heap, void *ptr) +{ + k_mutex_lock(&heap->lock, K_FOREVER); + + int ret = _vmh_free(heap, ptr); + + k_mutex_unlock(&heap->lock); + return ret; +} + +#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS +/** + * @brief Print stats on heap usage per allocator + * + * @param heap pointer to a heap for which statistics are collected + */ +void vmh_log_stats(struct vmh_heap *heap) +{ + if (heap->logged) + return; + + LOG_INF("Virtual heap stats per allocator"); + LOG_INF(" ID | Total | Max use| Times run out of blocks"); + + for (int idx = 0; idx < MAX_MEMORY_ALLOCATORS_COUNT; idx++) { + if (!heap->physical_blocks_allocators[idx]) + continue; + + struct sys_memory_stats stats = {0}; + + sys_mem_blocks_runtime_stats_get(heap->physical_blocks_allocators[idx], &stats); + + size_t block_size = 1 << heap->physical_blocks_allocators[idx]->info.blk_sz_shift; + size_t block_num = heap->physical_blocks_allocators[idx]->info.num_blocks; + + LOG_INF("%7d| %7u| %7u| %7u", idx, block_num, + (stats.max_allocated_bytes / block_size), + heap->out_of_blocks[idx]); + } + heap->logged = true; +} +#endif + +/** + * @brief Get default configuration for heap + * + * This will return config created based on region provided. + * It will try to split memory in even chunks and split it into + * bundles of size 64,128,...,1024 - exactly 5 sizes. + * + * @param region Virtual region which resources we will be using for heap + * @param cfg Ptr to the struct that function will populate with data. + * + */ +void vmh_get_default_heap_config(const struct sys_mm_drv_region *region, + struct vmh_heap_config *cfg) +{ + int buffer_size = ALIGN_DOWN(region->size / DEFAULT_CONFIG_ALOCATORS_COUNT, + CONFIG_MM_DRV_PAGE_SIZE); + + int i, block_count, block_size; + + for (i = 0; i < DEFAULT_CONFIG_ALOCATORS_COUNT; i++) { + block_size = DCACHE_LINE_SIZE << i; + block_count = buffer_size / block_size; + + cfg->block_bundles_table[i].block_size = block_size; + cfg->block_bundles_table[i].number_of_blocks = block_count; + } +} + +#endif /* if defined (CONFIG_MM_DRV) */ diff --git a/zephyr/lib/userspace_helper.c b/zephyr/lib/userspace_helper.c new file mode 100644 index 000000000000..c7c361295269 --- /dev/null +++ b/zephyr/lib/userspace_helper.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. All rights reserved. +// +// Author: Jaroslaw Stelter <jaroslaw.stelter@intel.com> +// Adrian Warecki <adrian.warecki@intel.com> + +/** + * \file + * \brief Zephyr userspace helper functions + * \authors Jaroslaw Stelter <jaroslaw.stelter@intel.com> + * \authors Adrian Warecki <adrian.warecki@intel.com> + */ + +#include <stdint.h> + +#include <rtos/alloc.h> +#include <rtos/sof.h> +#include <rtos/userspace_helper.h> +#include <sof/audio/module_adapter/module/generic.h> +#include <sof/audio/module_adapter/library/userspace_proxy.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/dai.h> +#include <sof/lib/dma.h> + +#define MODULE_DRIVER_HEAP_CACHED CONFIG_SOF_ZEPHYR_HEAP_CACHED + +/* Zephyr includes */ +#include <zephyr/kernel.h> +#include <zephyr/app_memory/app_memdomain.h> +#include <zephyr/logging/log.h> + +LOG_MODULE_REGISTER(userspace_helper, CONFIG_SOF_LOG_LEVEL); + +#if CONFIG_USERSPACE + +K_APPMEM_PARTITION_DEFINE(common_partition); + +#ifdef CONFIG_SOF_USERSPACE_LL +K_APPMEM_PARTITION_DEFINE(sysuser_partition); +#endif + +struct k_heap *module_driver_heap_init(void) +{ + struct k_heap *mod_drv_heap = rballoc(SOF_MEM_FLAG_USER, sizeof(*mod_drv_heap)); + + if (!mod_drv_heap) + return NULL; + + void *mem = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, USER_MOD_HEAP_SIZE, + CONFIG_MM_DRV_PAGE_SIZE); + if (!mem) { + rfree(mod_drv_heap); + return NULL; + } + + k_heap_init(mod_drv_heap, mem, USER_MOD_HEAP_SIZE); + mod_drv_heap->heap.init_mem = mem; + mod_drv_heap->heap.init_bytes = USER_MOD_HEAP_SIZE; + + return mod_drv_heap; +} + +void module_driver_heap_remove(struct k_heap *mod_drv_heap) +{ + if (mod_drv_heap) { + rfree(mod_drv_heap->heap.init_mem); + rfree(mod_drv_heap); + } +} + +void *user_stack_allocate(size_t stack_size, uint32_t options) +{ + return k_thread_stack_alloc(stack_size, options & K_USER); +} + +int user_stack_free(void *p_stack) +{ + if (!p_stack) + return 0; + return k_thread_stack_free(p_stack); +} + +int user_memory_attach_common_partition(struct k_mem_domain *dom) +{ + return k_mem_domain_add_partition(dom, &common_partition); +} + +#ifdef CONFIG_SOF_USERSPACE_LL +int user_memory_attach_system_user_partition(struct k_mem_domain *dom) +{ + return k_mem_domain_add_partition(dom, &sysuser_partition); +} + +int user_access_to_mailbox(struct k_mem_domain *domain, k_tid_t thread_id) +{ + struct k_mem_partition mem_partition; + int ret; + + /* + * Start with mailbox_swregs. This is aligned with mailbox.h + * implementation with uncached addressed used for register I/O. + */ + mem_partition.start = + (uintptr_t)sys_cache_uncached_ptr_get((void __sparse_cache *)MAILBOX_SW_REG_BASE); + + BUILD_ASSERT(MAILBOX_SW_REG_SIZE == CONFIG_MMU_PAGE_SIZE); + mem_partition.size = CONFIG_MMU_PAGE_SIZE; + mem_partition.attr = K_MEM_PARTITION_P_RW_U_RW; + + ret = k_mem_domain_add_partition(domain, &mem_partition); + if (ret < 0) + return ret; + +#ifndef CONFIG_IPC_MAJOR_4 + /* + * Next mailbox_stream (not available in IPC4). Stream access is cached, + * so different mapping this time. + */ + mem_partition.start = + (uintptr_t)sys_cache_cached_ptr_get((void *)SRAM_STREAM_BASE); + BUILD_ASSERT(MAILBOX_STREAM_SIZE == CONFIG_MMU_PAGE_SIZE); + /* size and attr the same as for mailbox_swregs */ + + ret = k_mem_domain_add_partition(domain, &mem_partition); + if (ret < 0) + return ret; +#endif + + k_mem_domain_add_thread(domain, thread_id); + + return 0; +} + +void user_grant_dai_access_all(struct k_thread *thread) +{ + const struct device **devices; + size_t count; + size_t i; + + devices = dai_get_device_list(&count); + + for (i = 0; i < count; i++) + k_thread_access_grant(thread, devices[i]); + + LOG_DBG("Granted DAI access to thread %p for %zu devices", thread, count); +} + +void user_grant_dma_access_all(struct k_thread *thread) +{ + const struct dma_info *info = dma_info_get(); + struct sof_dma *d; + + for (d = info->dma_array; d < info->dma_array + info->num_dmas; d++) { + k_thread_access_grant(thread, d->z_dev); + LOG_DBG("Granted DMA device access: %s to thread %p", d->z_dev->name, thread); + } +} + +#endif /* CONFIG_SOF_USERSPACE_LL */ + +#else /* CONFIG_USERSPACE */ + +void *user_stack_allocate(size_t stack_size, uint32_t options) +{ + /* allocate stack - must be aligned and cached so a separate alloc */ + stack_size = K_KERNEL_STACK_LEN(stack_size); + void *p_stack = rballoc_align(SOF_MEM_FLAG_USER, stack_size, Z_KERNEL_STACK_OBJ_ALIGN); + + return p_stack; +} + +int user_stack_free(void *p_stack) +{ + rfree(p_stack); + return 0; +} + +void module_driver_heap_remove(struct k_heap *mod_drv_heap) +{ } + +#endif /* CONFIG_USERSPACE */ diff --git a/zephyr/lib/vpage.c b/zephyr/lib/vpage.c new file mode 100644 index 000000000000..ce0da7b5ac97 --- /dev/null +++ b/zephyr/lib/vpage.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#include <zephyr/init.h> +#include <zephyr/kernel.h> +#include <zephyr/logging/log.h> +#include <zephyr/sys/check.h> +#include <sof/lib/regions_mm.h> +#include <sof/lib/vpage.h> +#include <zephyr/drivers/mm/mm_drv_intel_adsp_mtl_tlb.h> + +LOG_MODULE_REGISTER(vpage, CONFIG_SOF_LOG_LEVEL); + +/* Simple Page Allocator. + * + * This allocator manages the allocation and deallocation of virtual memory + * pages from a predefined virtual memory region which is larger than the + * physical memory region. + * + * Both memory regions are divided into pages (usually 4kB) that are represented + * as blocks in a bitmap using the zephyr sys_mem_blocks API. The virtual block + * map tracks the allocation of virtual memory pages while the physical block + * map in the Zephyr MM driver tracks the allocation of physical memory pages. + */ + +/* max number of allocations */ +#define VPAGE_MAX_ALLOCS CONFIG_SOF_VPAGE_MAX_ALLOCS + +/* + * Virtual memory allocation element - tracks allocated virtual page id and size + */ +struct valloc_elem { + unsigned short pages; /* number of pages allocated in contiguous block */ + unsigned short vpage; /* virtual page number from start of region */ +}; + +/* + * Virtual page allocator context + * + * This structure holds all information about virtual memory pages including the + * number of free and total pages, the virtual memory region, the block + * allocator for virtual pages and the allocations. + */ +struct vpage_context { + struct k_mutex lock; + unsigned int free_pages; /* number of free pages */ + unsigned int total_pages; /* total number of pages */ + + /* Virtual memory region information */ + const struct sys_mm_drv_region *virtual_region; + struct sys_mem_blocks vpage_blocks; + sys_bitarray_t bitmap; + + /* allocation elements to track page id to allocation size */ + unsigned int num_elems_in_use; /* number of allocated elements in use*/ + struct valloc_elem velems[VPAGE_MAX_ALLOCS]; +}; + +/* uncache persistent across all cores */ +static struct vpage_context vpage_ctx; + +/** + * @brief Allocate and map virtual memory pages + * + * Allocates memory pages from the virtual page allocator. + * Maps physical memory pages to the virtual region as needed. + * + * @param pages Number of pages to allocate. + * @param ptr Pointer to store the address of allocated pages. + * @retval 0 if successful. + */ +static int vpages_alloc_and_map(unsigned int pages, void **ptr) +{ + void *vaddr; + int ret; + + /* check for valid pages and ptr */ + if (!ptr) + return -EINVAL; + + if (!pages) { + *ptr = NULL; + return 0; + } + + /* quick check for enough free pages */ + if (vpage_ctx.free_pages < pages) { + LOG_ERR("error: not enough free pages %u for requested pages %u", + vpage_ctx.free_pages, pages); + return -ENOMEM; + } + + /* check for allocation elements */ + if (vpage_ctx.num_elems_in_use >= VPAGE_MAX_ALLOCS) { + LOG_ERR("error: max allocation elements reached"); + return -ENOMEM; + } + + /* allocate virtual continuous blocks */ + ret = sys_mem_blocks_alloc_contiguous(&vpage_ctx.vpage_blocks, pages, &vaddr); + if (ret < 0) { + LOG_ERR("error: failed to allocate %u continuous virtual pages, free %u", + pages, vpage_ctx.free_pages); + return ret; + } + + /* map the virtual blocks in virtual region to free physical blocks */ + ret = sys_mm_drv_map_region_safe(vpage_ctx.virtual_region, vaddr, + 0, pages * CONFIG_MM_DRV_PAGE_SIZE, SYS_MM_MEM_PERM_RW); + if (ret < 0) { + LOG_ERR("error: failed to map virtual region %p to physical region %p, error %d", + vaddr, vpage_ctx.virtual_region->addr, ret); + sys_mem_blocks_free_contiguous(&vpage_ctx.vpage_blocks, vaddr, pages); + return ret; + } + + /* success update the free pages */ + vpage_ctx.free_pages -= pages; + + /* Elements are acquired densely, just use the next one */ + vpage_ctx.velems[vpage_ctx.num_elems_in_use].pages = pages; + vpage_ctx.velems[vpage_ctx.num_elems_in_use].vpage = + (POINTER_TO_UINT(vaddr) - + POINTER_TO_UINT(vpage_ctx.virtual_region->addr)) / + CONFIG_MM_DRV_PAGE_SIZE; + vpage_ctx.num_elems_in_use++; + + /* return the virtual address */ + *ptr = vaddr; + + return 0; +} + +/** + * @brief Allocate virtual memory pages + * + * Allocates virtual memory pages from the virtual page allocator. + * + * @param pages Number of pages (usually 4kB large) to allocate. + * @retval NULL on allocation failure. + */ +void *vpage_alloc(unsigned int pages) +{ + void *ptr = NULL; + int ret; + + k_mutex_lock(&vpage_ctx.lock, K_FOREVER); + ret = vpages_alloc_and_map(pages, &ptr); + k_mutex_unlock(&vpage_ctx.lock); + if (ret < 0) + LOG_ERR("vpage_alloc failed %d for %d pages, total %d free %d", + ret, pages, vpage_ctx.total_pages, vpage_ctx.free_pages); + else + LOG_INF("vpage_alloc ptr %p pages %u free %u/%u", ptr, pages, vpage_ctx.free_pages, + vpage_ctx.total_pages); + return ptr; +} + +/** + * @brief Free and unmap virtual memory pages + * + * Frees previously allocated virtual memory pages and unmaps them. + * + * @param ptr Pointer to the memory pages to free. + * @retval 0 if successful. + * @retval -EINVAL if ptr is invalid. + */ +static int vpages_free_and_unmap(uintptr_t *ptr) +{ + unsigned int alloc_idx, elem_idx; + unsigned int pages = 0; + int ret; + + /* check for valid ptr which must be page aligned */ + CHECKIF(!IS_ALIGNED(ptr, CONFIG_MM_DRV_PAGE_SIZE)) { + LOG_ERR("error: invalid non aligned page pointer %p", ptr); + return -EINVAL; + } + + alloc_idx = (POINTER_TO_UINT(ptr) - POINTER_TO_UINT(vpage_ctx.virtual_region->addr)) / + CONFIG_MM_DRV_PAGE_SIZE; + + /* find the allocation element */ + for (elem_idx = 0; elem_idx < VPAGE_MAX_ALLOCS; elem_idx++) { + if (vpage_ctx.velems[elem_idx].pages > 0 && + vpage_ctx.velems[elem_idx].vpage == alloc_idx) { + pages = vpage_ctx.velems[elem_idx].pages; + + LOG_DBG("found allocation element %d pages %u vpage %u for ptr %p", + elem_idx, vpage_ctx.velems[elem_idx].pages, + vpage_ctx.velems[elem_idx].vpage, ptr); + break; + } + } + + /* check we found allocation element */ + CHECKIF(!pages) { + LOG_ERR("error: invalid page pointer %p not found", ptr); + return -EINVAL; + } + + /* unmap the pages from virtual region */ + ret = sys_mm_drv_unmap_region((void *)ptr, pages * CONFIG_MM_DRV_PAGE_SIZE); + if (ret < 0) { + LOG_ERR("error: failed to unmap virtual region %p pages %u, error %d", + ptr, pages, ret); + return ret; + } + + /* free physical blocks */ + ret = sys_mem_blocks_free_contiguous(&vpage_ctx.vpage_blocks, ptr, pages); + if (ret < 0) { + LOG_ERR("error: failed to free %u continuous virtual page blocks at %p, error %d", + pages, ptr, ret); + return ret; + } + + /* move the last element over the released one, clear the last element */ + if (vpage_ctx.num_elems_in_use != elem_idx) + vpage_ctx.velems[elem_idx] = vpage_ctx.velems[vpage_ctx.num_elems_in_use]; + vpage_ctx.velems[vpage_ctx.num_elems_in_use].pages = 0; + vpage_ctx.velems[vpage_ctx.num_elems_in_use].vpage = 0; + vpage_ctx.num_elems_in_use--; + + /* success update the free pages */ + vpage_ctx.free_pages += pages; + + return ret; +} + +/** + * @brief Free virtual pages + * Frees previously allocated virtual memory pages and unmaps them. + * + * @param ptr + */ +void vpage_free(void *ptr) +{ + int ret; + + k_mutex_lock(&vpage_ctx.lock, K_FOREVER); + ret = vpages_free_and_unmap((uintptr_t *)ptr); + k_mutex_unlock(&vpage_ctx.lock); + + if (!ret) + LOG_INF("vptr %p free/total pages %d/%d", ptr, vpage_ctx.free_pages, + vpage_ctx.total_pages); +} + +/** + * @brief Initialize virtual page allocator + * + * Initializes a virtual page allocator that manages a virtual memory region + * using a page table and block structures. + * + * @retval 0 if successful. + * @retval -ENOMEM on creation failure. + */ +static int vpage_init(void) +{ + const struct sys_mm_drv_region *virtual_memory_regions; + const struct sys_mm_drv_region *region; + uint32_t *bundles = NULL; + unsigned int block_count, bitmap_num_bundles; + int ret; + + /* create the virtual memory region and add it to the system */ + size_t remaining_ram = L2_SRAM_BASE + L2_SRAM_SIZE - + (adsp_mm_get_unused_l2_start_aligned() + + CONFIG_SOF_ZEPHYR_VIRTUAL_HEAP_REGION_SIZE + + CONFIG_LIBRARY_REGION_SIZE); + + ret = adsp_add_virtual_memory_region(adsp_mm_get_unused_l2_start_aligned() + + CONFIG_SOF_ZEPHYR_VIRTUAL_HEAP_REGION_SIZE, + remaining_ram, VIRTUAL_REGION_VPAGES_ATTR); + if (ret) + return ret; + + k_mutex_init(&vpage_ctx.lock); + + /* now find the virtual region in all memory regions */ + virtual_memory_regions = sys_mm_drv_query_memory_regions(); + SYS_MM_DRV_MEMORY_REGION_FOREACH(virtual_memory_regions, region) { + if (region->attr == VIRTUAL_REGION_VPAGES_ATTR) { + vpage_ctx.virtual_region = region; + break; + } + } + sys_mm_drv_query_memory_regions_free(virtual_memory_regions); + + /* check for a valid region */ + if (!vpage_ctx.virtual_region) { + LOG_ERR("error: no valid virtual region found"); + k_panic(); + } + + block_count = region->size / CONFIG_MM_DRV_PAGE_SIZE; + if (block_count == 0) { + LOG_ERR("error: virtual region too small %zu", region->size); + k_panic(); + } + + vpage_ctx.total_pages = block_count; + vpage_ctx.free_pages = block_count; + vpage_ctx.num_elems_in_use = 0; + + /* bundles are uint32_t of bits */ + bitmap_num_bundles = SOF_DIV_ROUND_UP(block_count, sizeof(uint32_t) * 8); + + /* allocate memory for bitmap bundles */ + bundles = rzalloc(SOF_MEM_FLAG_KERNEL | SOF_MEM_FLAG_COHERENT, + bitmap_num_bundles * sizeof(uint32_t)); + if (!bundles) { + LOG_ERR("error: virtual region bitmap alloc failed"); + k_panic(); + } + + /* Fill allocators data based on config and virtual region data */ + vpage_ctx.vpage_blocks.info.num_blocks = block_count; + vpage_ctx.vpage_blocks.info.blk_sz_shift = ilog2(CONFIG_MM_DRV_PAGE_SIZE); + /* buffer is the start of the virtual memory region */ + vpage_ctx.vpage_blocks.buffer = (uint8_t *)vpage_ctx.virtual_region->addr; + + /* initialize bitmap */ + vpage_ctx.bitmap.num_bits = block_count; + vpage_ctx.bitmap.num_bundles = bitmap_num_bundles; + vpage_ctx.bitmap.bundles = bundles; + vpage_ctx.vpage_blocks.bitmap = &vpage_ctx.bitmap; + + LOG_INF("region %p size %#zx pages %u", + (void *)vpage_ctx.virtual_region->addr, + vpage_ctx.virtual_region->size, block_count); + + return 0; +} + +SYS_INIT(vpage_init, POST_KERNEL, 1); diff --git a/zephyr/lib/vregion.c b/zephyr/lib/vregion.c new file mode 100644 index 000000000000..84af0d0645e6 --- /dev/null +++ b/zephyr/lib/vregion.c @@ -0,0 +1,440 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#include <zephyr/init.h> +#include <zephyr/kernel.h> +#include <zephyr/logging/log.h> +#include <sof/lib/vpage.h> +#include <sof/lib/vregion.h> +#include <rtos/alloc.h> +#include <sof/common.h> + +LOG_MODULE_REGISTER(vregion, CONFIG_SOF_LOG_LEVEL); + +/* + * Pre Allocated Contiguous Virtual Memory Region Allocator + * + * This allocator manages a pre-allocated virtual memory region that uses the + * virtual page allocator to allocate and free memory pages. + * + * It is designed for use cases where a contiguous virtual memory region + * is required, such as for batched allocation of audio pipelines and modules. + * + * New pipelines will create a new virtual region and will specify the size of the region + * which can be divided into multiple areas for different allocation lifetimes, permissions + * and sharing requirements. + * + * Advantages: + * + * 1) Contiguous virtual memory region for easier management and tracking of + * pipeline & DP module memory. i.e. we just need to track the vregion pointer. + * 2) Reduced fragmentation and better cache utilization by using a simple linear + * allocator for lifetime objects. + * + * Note: Software must pass in the size of the region areas at pipeline creation time. + */ + +/** + * @brief virtual region memory structure. + * + * This structure represents a virtual memory region, which includes + * information about the base address, size, and allocation status + * of the region. + * + * Currently the virtual region memory can be partitioned into two areas on + * page-aligned boundaries: + * + * 1. Interim Heap: An interim memory area used for multiple temporary + * allocations and frees over the lifetime of the audio processing pipeline. + * E.g. for module kcontrol derived allocations. + * + * 2. Lifetime Allocator: A simple incrementing allocator used for long-term + * static allocations that persist for the lifetime of the audio processing + * pipeline. This allocator compresses allocations for better cache + * utilization. + * + * More types can be added in the future. + * + * * TODO: Pipeline/module reset() could reset the dynamic heap. + */ + + /* linear heap used for lifetime allocations */ +struct vlinear_heap { + uint8_t *base; /* base address of linear allocator */ + uint8_t *ptr; /* current alloc pointer */ + size_t size; /* size of linear allocator in bytes */ + size_t used; /* used bytes in linear allocator */ + int free_count; /* number of frees - tuning only */ +}; + +/* zephyr k_heap for interim allocations. TODO: make lockless for improved performance */ +struct interim_heap { + struct k_heap heap; +}; + +/* Main vregion context, see above intro for more details. + * TODO: Add support to flag which heaps should have their contexts saved and restored. + */ +struct vregion { + /* region context */ + uint8_t *base; /* base address of entire region */ + size_t size; /* size of whole region in bytes */ + unsigned int pages; /* size of whole region in pages */ + struct k_mutex lock; /* protect vregion heaps and use-count */ + unsigned int use_count; + + /* interim heap */ + struct interim_heap interim; /* interim heap */ + + /* lifetime heap */ + struct vlinear_heap lifetime; /* lifetime linear heap */ +}; + +/** + * @brief Create a new virtual region instance. + * + * Create a new VIRTUAL REGION instance with specified static and dynamic + * sizes. Total size is their sum. + * + * @param[in] lifetime_size Size of the virtual region lifetime partition. + * @param[in] interim_size Size of the virtual region interim partition. + * @return struct vregion* Pointer to the new virtual region instance, or NULL on failure. + */ +struct vregion *vregion_create(size_t lifetime_size, size_t interim_size) +{ + struct vregion *vr; + unsigned int pages; + size_t total_size; + uint8_t *vregion_base; + + if (!lifetime_size || !interim_size) { + LOG_ERR("error: invalid vregion lifetime size %zu or interim size %zu", + lifetime_size, interim_size); + return NULL; + } + + /* + * Align up lifetime sizes and interim sizes to nearest page, the + * vregion structure is stored in lifetime area so account for its size too. + */ + lifetime_size += sizeof(*vr); + lifetime_size = ALIGN_UP(lifetime_size, CONFIG_MM_DRV_PAGE_SIZE); + interim_size = ALIGN_UP(interim_size, CONFIG_MM_DRV_PAGE_SIZE); + total_size = lifetime_size + interim_size; + + /* allocate pages for vregion */ + pages = total_size / CONFIG_MM_DRV_PAGE_SIZE; + vregion_base = vpage_alloc(pages); + if (!vregion_base) + return NULL; + + /* init vregion - place it at the start of the lifetime region */ + vr = (struct vregion *)(vregion_base + interim_size); + vr->base = vregion_base; + vr->size = total_size; + vr->pages = pages; + + /* set partition sizes */ + vr->interim.heap.heap.init_bytes = interim_size; + vr->lifetime.size = lifetime_size; + + /* set base addresses for partitions */ + vr->interim.heap.heap.init_mem = vr->base; + vr->lifetime.base = vr->base + interim_size; + + /* set alloc ptr addresses for lifetime linear partitions */ + vr->lifetime.ptr = vr->lifetime.base + + ALIGN_UP(sizeof(*vr), CONFIG_DCACHE_LINE_SIZE); /* skip vregion struct */ + vr->lifetime.used = ALIGN_UP(sizeof(*vr), CONFIG_DCACHE_LINE_SIZE); + + /* init interim heaps */ + k_heap_init(&vr->interim.heap, vr->interim.heap.heap.init_mem, interim_size); + + k_mutex_init(&vr->lock); + /* The creator is the first user */ + vr->use_count = 1; + + /* log the new vregion */ + LOG_INF("new at base %p size %#zx pages %u struct embedded at %p", + (void *)vr->base, total_size, pages, (void *)vr); + LOG_DBG(" interim size %#zx at %p", interim_size, (void *)vr->interim.heap.heap.init_mem); + LOG_DBG(" lifetime size %#zx at %p", lifetime_size, (void *)vr->lifetime.base); + + return vr; +} + +struct vregion *vregion_get(struct vregion *vr) +{ + if (!vr) + return NULL; + + k_mutex_lock(&vr->lock, K_FOREVER); + vr->use_count++; + k_mutex_unlock(&vr->lock); + + return vr; +} + +/** + * @brief Decrement virtual region's user count or destroy it. + * + * @param[in] vr Pointer to the virtual region instance to release. + * @return struct vregion* Pointer to the virtual region instance or NULL if it has been destroyed. + */ +struct vregion *vregion_put(struct vregion *vr) +{ + unsigned int use_count; + + if (!vr) + return NULL; + + k_mutex_lock(&vr->lock, K_FOREVER); + use_count = --vr->use_count; + k_mutex_unlock(&vr->lock); + + if (use_count) + return vr; + + /* Last user: nobody else can access the instance. */ + + /* log the vregion being destroyed */ + LOG_DBG("destroy %p size %#zx pages %u", (void *)vr->base, vr->size, vr->pages); + LOG_DBG(" lifetime used %zu free count %d", vr->lifetime.used, vr->lifetime.free_count); + vpage_free(vr->base); + + return NULL; +} + +/** + * @brief Allocate memory with alignment from the virtual region dynamic heap. + * + * @param[in] heap Pointer to the heap to use. + * @param[in] size Size of the allocation. + * @param[in] align Alignment of the allocation. + * @return void* Pointer to the allocated memory, or NULL on failure. + */ +static void *interim_alloc(struct interim_heap *heap, + size_t size, size_t align) +{ + void *ptr; + + ptr = k_heap_aligned_alloc(&heap->heap, align, size, K_NO_WAIT); + if (!ptr) + LOG_WRN("interim alloc failed for %d bytes align %d", + size, align); + + return ptr; +} + +/** + * @brief Free memory from the virtual region interim heap. + * + * @param[in] heap Pointer to the heap to use. + * @param[in] ptr Pointer to the memory to free. + */ +static void interim_free(struct interim_heap *heap, void *ptr) +{ + k_heap_free(&heap->heap, ptr); +} + +/** + * @brief Allocate memory from the virtual region lifetime allocator. + * + * @param[in] heap Pointer to the linear heap to use. + * @param[in] size Size of the allocation. + * @param[in] align Alignment of the allocation. + * + * @return void* Pointer to the allocated memory, or NULL on failure. + */ +static void *lifetime_alloc(struct vlinear_heap *heap, + size_t size, size_t align) +{ + void *ptr; + uint8_t *aligned_ptr; + size_t heap_obj_size; + + /* align heap pointer to alignment requested */ + aligned_ptr = UINT_TO_POINTER(ALIGN_UP(POINTER_TO_UINT(heap->ptr), align)); + + /* also align up size to D$ bytes if asked - allocation head and tail aligned */ + if (align == CONFIG_DCACHE_LINE_SIZE) + size = ALIGN_UP(size, CONFIG_DCACHE_LINE_SIZE); + + /* calculate new heap object size for object and alignment */ + heap_obj_size = aligned_ptr - heap->ptr + size; + + /* check we have enough lifetime space left */ + if (heap_obj_size + heap->used > heap->size) { + LOG_WRN("lifetime alloc failed for object %d heap %d bytes free %d", + size, heap_obj_size, heap->size - heap->used); + return NULL; + } + + /* allocate memory */ + ptr = aligned_ptr; + heap->ptr += heap_obj_size; + heap->used += heap_obj_size; + + return ptr; +} + +/** + * @brief Free memory from the virtual region lifetime allocator. + * + * @param[in] heap Pointer to the linear heap to use. + * @param[in] ptr Pointer to the memory to free. + */ +static void lifetime_free(struct vlinear_heap *heap, void *ptr) +{ + /* simple free, just increment free count, this is for tuning only */ + heap->free_count++; + + LOG_DBG("lifetime free %p count %d", ptr, heap->free_count); +} + +/** + * @brief Free memory from the virtual region. + * + * @param vr Pointer to the virtual region instance. + * @param ptr Pointer to the memory to free. + */ +void vregion_free(struct vregion *vr, void *ptr) +{ + if (!vr || !ptr) + return; + + k_mutex_lock(&vr->lock, K_FOREVER); + + if (sys_cache_is_ptr_uncached(ptr)) + ptr = sys_cache_cached_ptr_get(ptr); + + if (ptr >= (void *)vr->interim.heap.heap.init_mem && + ptr < (void *)((uint8_t *)vr->interim.heap.heap.init_mem + + vr->interim.heap.heap.init_bytes)) + /* pointer is in interim heap */ + interim_free(&vr->interim, ptr); + else if (ptr >= (void *)vr->lifetime.base && + ptr < (void *)(vr->lifetime.base + vr->lifetime.size)) + /* pointer is in lifetime heap */ + lifetime_free(&vr->lifetime, ptr); + else + LOG_ERR("error: vregion free invalid pointer %p", ptr); + + k_mutex_unlock(&vr->lock); +} +EXPORT_SYMBOL(vregion_free); + +/** + * @brief Allocate memory type from the virtual region. + * + * @param[in] vr Pointer to the virtual region instance. + * @param[in] type Memory type to allocate. + * @param[in] size Size of the allocation. + * @param[in] alignment Alignment of the allocation. + * + * @return void* Pointer to the allocated memory, or NULL on failure. + */ +void *vregion_alloc_align(struct vregion *vr, enum vregion_mem_type type, + size_t size, size_t alignment) +{ + void *p; + + if (!vr || !size) + return NULL; + + if (alignment < PLATFORM_DCACHE_ALIGN) + alignment = PLATFORM_DCACHE_ALIGN; + + k_mutex_lock(&vr->lock, K_FOREVER); + + switch (type) { + case VREGION_MEM_TYPE_INTERIM: + p = interim_alloc(&vr->interim, size, alignment); + break; + case VREGION_MEM_TYPE_LIFETIME: + p = lifetime_alloc(&vr->lifetime, size, alignment); + break; + default: + LOG_ERR("error: invalid memory type %d", type); + p = NULL; + } + + k_mutex_unlock(&vr->lock); + + return p; +} +EXPORT_SYMBOL(vregion_alloc_align); + +/** + * @brief Allocate memory from the virtual region. + * @param[in] vr Pointer to the virtual region instance. + * @param[in] type Memory type to allocate. + * @param[in] size Size of the allocation. + * @return void* Pointer to the allocated memory, or NULL on failure. + */ +void *vregion_alloc(struct vregion *vr, enum vregion_mem_type type, size_t size) +{ + return vregion_alloc_align(vr, type, size, 0); +} +EXPORT_SYMBOL(vregion_alloc); + +void *vregion_alloc_coherent(struct vregion *vr, enum vregion_mem_type type, size_t size) +{ + size = ALIGN_UP(size, CONFIG_DCACHE_LINE_SIZE); + + void *p = vregion_alloc_align(vr, type, size, CONFIG_DCACHE_LINE_SIZE); + + if (!p) + return NULL; + + sys_cache_data_invd_range(p, size); + + return sys_cache_uncached_ptr_get(p); +} + +void *vregion_alloc_coherent_align(struct vregion *vr, enum vregion_mem_type type, + size_t size, size_t alignment) +{ + if (alignment < CONFIG_DCACHE_LINE_SIZE) + alignment = CONFIG_DCACHE_LINE_SIZE; + size = ALIGN_UP(size, CONFIG_DCACHE_LINE_SIZE); + + void *p = vregion_alloc_align(vr, type, size, alignment); + + if (!p) + return NULL; + + sys_cache_data_invd_range(p, size); + + return sys_cache_uncached_ptr_get(p); +} + +/** + * @brief Log virtual region memory usage. + * + * @param[in] vr Pointer to the virtual region instance. + */ +void vregion_info(struct vregion *vr) +{ + if (!vr) + return; + + LOG_INF("base %p size %#zx pages %u", + (void *)vr->base, vr->size, vr->pages); + LOG_INF("lifetime used %#zx free count %d", + vr->lifetime.used, vr->lifetime.free_count); +} +EXPORT_SYMBOL(vregion_info); + +void vregion_mem_info(struct vregion *vr, size_t *size, uintptr_t *start) +{ + if (size) + *size = vr->size; + + if (start) + *start = (uintptr_t)vr->base; +} diff --git a/zephyr/module.yml b/zephyr/module.yml new file mode 100644 index 000000000000..2fd290118c9b --- /dev/null +++ b/zephyr/module.yml @@ -0,0 +1,9 @@ +# https://docs.zephyrproject.org/latest/guides/modules.html +name: sof +samples: + - app/ + +# Default values: +# build: +# cmake: ./zephyr +# kconfig: ./zephyr/Kconfig diff --git a/zephyr/schedule.c b/zephyr/schedule.c new file mode 100644 index 000000000000..75155b5d4913 --- /dev/null +++ b/zephyr/schedule.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2019 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko <bartoszx.kokoszko@linux.intel.com> + +/* Generic scheduler */ +#include <sof/schedule/schedule.h> +#include <sof/schedule/edf_schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <rtos/alloc.h> +#include <rtos/symbol.h> +#include <sof/lib/cpu.h> +#include <ipc/topology.h> + +static struct schedulers *_schedulers[CONFIG_CORE_COUNT]; + +/** + * Retrieves registered schedulers. + * @return List of registered schedulers. + */ +struct schedulers **arch_schedulers_get(void) +{ + return _schedulers + cpu_get_id(); +} +EXPORT_SYMBOL(arch_schedulers_get); diff --git a/zephyr/scripts/clean-expected-release-differences.sh b/zephyr/scripts/clean-expected-release-differences.sh new file mode 100755 index 000000000000..b04c61bb8255 --- /dev/null +++ b/zephyr/scripts/clean-expected-release-differences.sh @@ -0,0 +1,69 @@ +#!/bin/sh +# SPDX-License-Identifier: BSD-3-Clause +# shellcheck disable=SC3043 + +set -e + +die() +{ + # shellcheck disable=SC2059 + >&2 printf "$@" + exit 1 +} + +fix_dir() +{ + local bd="$1" + + test -d "$bd"/build-sof-staging || + die 'No %s/build-sof-staging directory\n' "$bd" + + # config files have absolute paths + find "$bd" \( -name 'config.gz' -o -name 'westconfig.ini' \) -exec rm '{}' \; + + # In case of a compression timestamp. Also gives better messages. + find "$bd" -name '*.gz' -print0 | xargs -r -0 gunzip + + ( set -x + + # Native binaries + rm -f "$bd"/build-sof-staging/tools/sof-logger* + # Python and other scripts + dos2unix "$bd"/build-sof-staging/tools/* || true + + # signature salt + find "$bd" -name '*.ri' -exec rm '{}' \; + + # debug symbols + find "$bd" -name main.mod -exec rm '{}' \; + find "$bd" -name zephyr.elf -exec rm '{}' \; + + # Unlike zephyr.lst, zephyr.map includes some debug information which is + # as usual full of absolute paths, e.g.: + # /opt/toolchains/zephyr-sdk-0.15.2/xtensa-intel_s1000_..../libgcc.a(_divsf3.o) + # Delete non-reproducible information inside zephyr.map. + find "$bd" -name zephyr.map -exec sed -i'' -e \ + 's#[^[:blank:]]*zephyr-sdk-[^/]*/xtensa#ZSDK/xtensa#; s#\\#/#g; /^ \.debug_/ d' \ + '{}' \; + + # The above search/replace normalizes MOST but unfortunately not + # all the debug information! So let's delete zephyr.map after all :-( + # Comparing "almost normalized" zephyr.map files can be very + # useful to root cause differences: comment out this line in your + # local workspace. + find "$bd" -name zephyr.map -exec rm '{}' \; + + find "$bd" -name 'compile_commands.json' -exec rm '{}' \; + ) + +} + +main() +{ + for d in "$@"; do + fix_dir "$d" + done +} + + +main "$@" diff --git a/zephyr/sof_shell.c b/zephyr/sof_shell.c new file mode 100644 index 000000000000..9e90abe417bb --- /dev/null +++ b/zephyr/sof_shell.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2024 Intel Corporation. + * + * Author: Kai Vehmanen <kai.vehmanen@linux.intel.com> + */ + +#include <rtos/sof.h> /* sof_get() */ +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/audio/module_adapter/module/generic.h> + +#include <zephyr/kernel.h> +#include <zephyr/sys/printk.h> +#include <zephyr/shell/shell.h> + +#include <stdlib.h> + +#define SOF_TEST_INJECT_SCHED_GAP_USEC 1500 + +static int cmd_sof_test_inject_sched_gap(const struct shell *sh, + size_t argc, char *argv[]) +{ + uint32_t block_time = SOF_TEST_INJECT_SCHED_GAP_USEC; + char *endptr = NULL; + +#ifndef CONFIG_CROSS_CORE_STREAM + shell_fprintf(sh, SHELL_NORMAL, "Domain blocking not supported, not reliable on SMP\n"); +#endif + + domain_block(sof_get()->platform_timer_domain); + + if (argc > 1) { + block_time = strtol(argv[1], &endptr, 0); + if (endptr == argv[1]) + return -EINVAL; + } + + k_busy_wait(block_time); + + domain_unblock(sof_get()->platform_timer_domain); + + return 0; +} + +static int cmd_sof_module_heap_usage(const struct shell *sh, + size_t argc, char *argv[]) +{ + struct ipc *ipc = sof_get()->ipc; + struct list_item *clist, *_clist; + struct ipc_comp_dev *icd; + + if (!ipc) { + shell_print(sh, "No IPC"); + return 0; + } + + list_for_item_safe(clist, _clist, &ipc->comp_list) { + size_t usage, hwm; + + icd = container_of(clist, struct ipc_comp_dev, list); + if (icd->type != COMP_TYPE_COMPONENT) + continue; + + usage = module_adapter_heap_usage(comp_mod(icd->cd), &hwm); + shell_print(sh, "comp id 0x%08x%9zu usage%9zu hwm\tbytes", + icd->id, usage, hwm); + } + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(sof_commands, + SHELL_CMD(test_inject_sched_gap, NULL, + "Inject a gap to audio scheduling\n", + cmd_sof_test_inject_sched_gap), + + SHELL_CMD(module_heap_usage, NULL, + "Print heap memory usage of each module\n", + cmd_sof_module_heap_usage), + + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_REGISTER(sof, &sof_commands, + "SOF application commands", NULL); diff --git a/zephyr/syscall/sof_dma.c b/zephyr/syscall/sof_dma.c new file mode 100644 index 000000000000..ed69ffc78423 --- /dev/null +++ b/zephyr/syscall/sof_dma.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2025 Intel Corporation. + +#include <sof/lib/dma.h> +#include <zephyr/kernel.h> +#include <zephyr/internal/syscall_handler.h> + +#ifdef CONFIG_SOF_USERSPACE_INTERFACE_DMA + +static inline bool sof_dma_has_access(struct sof_dma *dma) +{ + /* + * use the Zephyr dma.h device handle to check calling + * thread has access to it + */ + return k_object_is_valid(dma->z_dev, K_OBJ_DRIVER_DMA); +} + +static inline bool sof_dma_is_valid(struct sof_dma *dma) +{ + const struct dma_info *info = dma_info_get(); + uintptr_t offset = (uintptr_t)dma - (uintptr_t)info->dma_array; + struct sof_dma *array_end = info->dma_array + info->num_dmas; + + if (!info->num_dmas) + return false; + + /* + * The 'dma' pointer is not trusted, so we must first ensure it + * points to a valid "struct sof_dma *" kernel object. + */ + if (dma < info->dma_array || dma >= array_end || offset % sizeof(struct sof_dma)) + return false; + + return sof_dma_has_access(dma); +} + +static inline struct sof_dma *z_vrfy_sof_dma_get(uint32_t dir, uint32_t cap, + uint32_t dev, uint32_t flags) +{ + struct sof_dma *dma = z_impl_sof_dma_get(dir, cap, dev, flags); + + /* + * note: Usually validation is done first, but here + * z_impl_sof_dma_get() is first called with unvalidated input + * arguments on purpose. This is done to reuse the existing SOF + * code to track DMA kernel objects. When called from + * user-space, we use existing functionality to look up the + * kernel object, but add an extra layer to check for access + * permission. + */ + if (dma) { + if (sof_dma_has_access(dma)) + return dma; + + /* no access, release reference on error */ + z_impl_sof_dma_put(dma); + } + + return NULL; +} +#include <zephyr/syscalls/sof_dma_get_mrsh.c> + +static inline void z_vrfy_sof_dma_put(struct sof_dma *dma) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + z_impl_sof_dma_put(dma); +} +#include <zephyr/syscalls/sof_dma_put_mrsh.c> + +static inline int z_vrfy_sof_dma_get_attribute(struct sof_dma *dma, uint32_t type, uint32_t *value) +{ + K_OOPS(!sof_dma_is_valid(dma)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(value, sizeof(*value))); + + return z_impl_sof_dma_get_attribute(dma, type, value); +} +#include <zephyr/syscalls/sof_dma_get_attribute_mrsh.c> + +static inline int z_vrfy_sof_dma_request_channel(struct sof_dma *dma, uint32_t stream_tag) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_request_channel(dma, stream_tag); +} +#include <zephyr/syscalls/sof_dma_request_channel_mrsh.c> + +static inline void z_vrfy_sof_dma_release_channel(struct sof_dma *dma, + uint32_t channel) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_release_channel(dma, channel); +} +#include <zephyr/syscalls/sof_dma_release_channel_mrsh.c> + +/** + * Creates a deep copy of the DMA transfer blocks in kernel address space, + * based on the DMA config description given as argument. + * + * All pointers in 'cfg' are validated for access permission, and if + * ok, contents is copied to a kernel side object. + * + * @arg cfg kernel object for DMA configuration that contains + * user-space pointers to DMA transfer objects + * @return array of kernel DMA block/transfer config objects + */ +static inline struct dma_block_config *deep_copy_dma_blk_cfg_list(struct dma_config *cfg) +{ + struct dma_block_config *kern_cfg = + rmalloc(0, sizeof(*kern_cfg) * cfg->block_count); + struct dma_block_config *kern_prev = NULL, *kern_next, *user_next; + int i = 0; + + if (!kern_cfg) + return NULL; + + for (user_next = cfg->head_block, kern_next = kern_cfg; + user_next; + user_next = user_next->next_block, kern_next++) { + if (++i > cfg->block_count) + goto err; + + if (k_usermode_from_copy(kern_next, user_next, sizeof(*kern_next))) + goto err; + + /* check access permissions for DMA src/dest memory */ + switch (cfg->channel_direction) { + case MEMORY_TO_MEMORY: + if (K_SYSCALL_MEMORY_WRITE((void *)kern_next->dest_address, + kern_next->block_size)) + goto err; + COMPILER_FALLTHROUGH; + case MEMORY_TO_PERIPHERAL: + case MEMORY_TO_HOST: + if (K_SYSCALL_MEMORY_READ((void *)kern_next->source_address, + kern_next->block_size)) + goto err; + break; + case PERIPHERAL_TO_MEMORY: + case HOST_TO_MEMORY: + if (K_SYSCALL_MEMORY_WRITE((void *)kern_next->dest_address, + kern_next->block_size)) + goto err; + break; + default: + goto err; + } + + if (kern_prev) + kern_prev->next_block = kern_next; + + kern_prev = kern_next; + } + + /* set transfer list to point to first kernel transfer config object */ + cfg->head_block = kern_cfg; + + return kern_cfg; + +err: + /* do not call K_OOPS until kernel memory is freed */ + rfree(kern_cfg); + return NULL; +} + +static inline int z_vrfy_sof_dma_config(struct sof_dma *dma, uint32_t channel, + struct dma_config *config) +{ + struct dma_block_config *blk_cfgs; + struct dma_config kern_cfg, user_cfg; + int ret; + + K_OOPS(!sof_dma_is_valid(dma)); + K_OOPS(k_usermode_from_copy(&user_cfg, config, sizeof(user_cfg))); + + /* use only DMA config attributes that are safe to use from user-space */ + kern_cfg.dma_slot = user_cfg.dma_slot; + kern_cfg.channel_direction = user_cfg.channel_direction; + kern_cfg.cyclic = user_cfg.cyclic; + kern_cfg.source_data_size = user_cfg.source_data_size; + kern_cfg.dest_data_size = user_cfg.dest_data_size; + kern_cfg.source_burst_length = user_cfg.source_burst_length; + kern_cfg.dest_burst_length = user_cfg.dest_burst_length; + kern_cfg.block_count = user_cfg.block_count; + kern_cfg.head_block = user_cfg.head_block; + + /* validate and copy transfer blocks to kernel */ + blk_cfgs = deep_copy_dma_blk_cfg_list(&kern_cfg); + K_OOPS(blk_cfgs == NULL); + + /* TODO: add checks for peripheral/host FIFO access? */ + + ret = z_impl_sof_dma_config(dma, channel, &kern_cfg); + + rfree(blk_cfgs); + + return ret; +} +#include <zephyr/syscalls/sof_dma_config_mrsh.c> + +static inline int z_vrfy_sof_dma_start(struct sof_dma *dma, uint32_t channel) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_start(dma, channel); +} +#include <zephyr/syscalls/sof_dma_start_mrsh.c> + +static inline int z_vrfy_sof_dma_stop(struct sof_dma *dma, uint32_t channel) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_stop(dma, channel); +} +#include <zephyr/syscalls/sof_dma_stop_mrsh.c> + +static inline int z_vrfy_sof_dma_get_status(struct sof_dma *dma, uint32_t channel, + struct dma_status *stat) +{ + K_OOPS(!sof_dma_is_valid(dma)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(stat, sizeof(*stat))); + + return z_impl_sof_dma_get_status(dma, channel, stat); +} +#include <zephyr/syscalls/sof_dma_get_status_mrsh.c> + +static inline int z_vrfy_sof_dma_reload(struct sof_dma *dma, uint32_t channel, size_t size) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_reload(dma, channel, size); +} +#include <zephyr/syscalls/sof_dma_reload_mrsh.c> + +static inline int z_vrfy_sof_dma_suspend(struct sof_dma *dma, uint32_t channel) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_suspend(dma, channel); +} +#include <zephyr/syscalls/sof_dma_suspend_mrsh.c> + +static inline int z_vrfy_sof_dma_resume(struct sof_dma *dma, uint32_t channel) +{ + K_OOPS(!sof_dma_is_valid(dma)); + + return z_impl_sof_dma_resume(dma, channel); +} +#include <zephyr/syscalls/sof_dma_resume_mrsh.c> + +#endif /* CONFIG_SOF_USERSPACE_INTERFACE_DMA */ diff --git a/zephyr/test/CMakeLists.txt b/zephyr/test/CMakeLists.txt new file mode 100644 index 000000000000..f548c98c5e73 --- /dev/null +++ b/zephyr/test/CMakeLists.txt @@ -0,0 +1,28 @@ +if(CONFIG_SOF_BOOT_TEST) + zephyr_library_sources_ifdef(CONFIG_VIRTUAL_HEAP + vmh.c + ) + zephyr_library_sources_ifdef(CONFIG_SOF_VREGIONS + vpage.c vregion.c + ) + zephyr_library_sources_ifdef(CONFIG_USERSPACE + userspace/ksem.c + ) +endif() + +if(CONFIG_SOF_BOOT_TEST_STANDALONE AND CONFIG_SOF_USERSPACE_INTERFACE_DMA) + if(CONFIG_DT_HAS_INTEL_ADSP_HDA_HOST_IN_ENABLED) + zephyr_library_sources(userspace/test_intel_hda_dma.c) + endif() + if(CONFIG_DT_HAS_INTEL_ADSP_HDA_SSP_CAP_ENABLED) + zephyr_library_sources(userspace/test_intel_ssp_dai.c) + endif() +endif() + +if(CONFIG_SOF_BOOT_TEST_STANDALONE AND CONFIG_USERSPACE) + zephyr_library_sources(userspace/test_mailbox.c) +endif() + +if(CONFIG_SOF_BOOT_TEST_STANDALONE AND CONFIG_SOF_USERSPACE_LL) + zephyr_library_sources(userspace/test_ll_task.c) +endif() diff --git a/zephyr/test/userspace/README.md b/zephyr/test/userspace/README.md new file mode 100644 index 000000000000..6c14300ee333 --- /dev/null +++ b/zephyr/test/userspace/README.md @@ -0,0 +1,48 @@ +User-space interface tests for Intel ADSP +----------------------------------------- + +This folder contains multiple tests to exercise Intel DSP device interfaces +from a user-space Zephyr thread. + +Available tests: +- test_intel_hda_dma.c + - Test Intel HDA DMA host interface from a userspace + Zephyr thread. Use cavstool.py as host runner. +- test_intel_ssp_dai.c + - Test Zephyr DAI interface, together with SOF DMA + wrapper from a user thread. Mimics the call flows done in + sof/src/audio/dai-zephyr.c. Use cavstool.py as host runner. +- test_ll_task.c + - Test Low-Latency (LL) scheduler in user-space mode. Creates + a user-space LL scheduler, and uses it to create and run tasks. + - Tests functionality used by SOF audio pipeline framework to + create tasks for audio pipeline logic. +- test_mailbox.c + - Test use of sof/mailbox.h interface from a Zephyr user thread. + +Building for Intel Panther Lake: +./scripts/xtensa-build-zephyr.py --cmake-args=-DCONFIG_SOF_BOOT_TEST_STANDALONE=y \ + --cmake-args=-DCONFIG_SOF_USERSPACE_INTERFACE_DMA=y \ + --cmake-args=-DCONFIG_SOF_USERSPACE_LL=y \ + -o app/overlays/ptl/userspace_overlay.conf -o app/winconsole_overlay.conf ptl + +Running test: +- Copy resulting firmware (sof-ptl.ri) to device under test. +- Boot and run the test with cavstool.py: + sudo ./cavstool.py sof-ptl.ri +- Test results printed to cavstool.py + +Running test on QEMU (dc233c MMU): +- Tests can also be built and run locally using Zephyr's QEMU simulator. +- First, build the test application using `xtensa-build-zephyr.py`: + ./scripts/xtensa-build-zephyr.py qemu_xtensa_mmu --cmake-args=-DCONFIG_SOF_BOOT_TEST_STANDALONE=y \ + --cmake-args=-DCONFIG_SOF_USERSPACE_INTERFACE_DMA=y --cmake-args=-DCONFIG_SOF_USERSPACE_LL=y +- Once built, run the test in QEMU: + west build -d build-qemu_xtensa_mmu -t run + +References to related assets in Zephyr codebase: +- cavstool.py + - zephyr/soc/intel/intel_adsp/tools/cavstool.py +- HD DMA tests in Zephyr + - zephyr/tests/boards/intel_adsp/hda/ + - larger set in kernel space, using DMA interface directly without SOF dependencies diff --git a/zephyr/test/userspace/ksem.c b/zephyr/test/userspace/ksem.c new file mode 100644 index 000000000000..cb167191f956 --- /dev/null +++ b/zephyr/test/userspace/ksem.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. + */ + +#include <sof/boot_test.h> + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> + +LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG); + +#define USER_STACKSIZE 2048 + +static struct k_thread user_thread; +static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE); +K_SEM_DEFINE(user_sem, 0, 1); + +static void user_function(void *p1, void *p2, void *p3) +{ + __ASSERT(k_is_user_context(), "isn't user"); + LOG_INF("SOF thread %s (%s)", + k_is_user_context() ? "UserSpace!" : "privileged mode.", + CONFIG_BOARD_TARGET); +} + +static void user_sem_function(void *p1, void *p2, void *p3) +{ + __ASSERT(k_is_user_context(), "isn't user"); + LOG_INF("SOF thread %s (%s)", + k_is_user_context() ? "UserSpace!" : "privileged mode.", + CONFIG_BOARD_TARGET); + k_sem_give(&user_sem); +} + +static void test_user_thread(void) +{ + k_thread_create(&user_thread, user_stack, USER_STACKSIZE, + user_function, NULL, NULL, NULL, + -1, K_USER, K_MSEC(0)); + k_thread_join(&user_thread, K_FOREVER); +} + +static void test_user_thread_with_sem(void) +{ + /* Start in 10ms to have time to grant the thread access to the semaphore */ + k_thread_create(&user_thread, user_stack, USER_STACKSIZE, + user_sem_function, NULL, NULL, NULL, + -1, K_USER, K_MSEC(10)); + k_thread_access_grant(&user_thread, &user_sem); + k_sem_take(&user_sem, K_FOREVER); + k_thread_join(&user_thread, K_FOREVER); +} + +ZTEST(sof_boot, user_space) +{ + test_user_thread(); + test_user_thread_with_sem(); +} + +#include <zephyr/sys/sem.h> +#include <zephyr/app_memory/mem_domain.h> + +struct sem_mem { + struct sys_sem sem1; + struct sys_sem sem2; + uint8_t reserved[4096 - 2 * sizeof(struct sys_sem)]; +}; + +static struct sem_mem simple_sem __attribute__((aligned(4096))); +static struct k_mem_domain dp_mdom; + +static void sys_sem_function(void *p1, void *p2, void *p3) +{ + __ASSERT(k_is_user_context(), "isn't user"); + /* This is the goal, but it hangs with this disabled too */ + sys_sem_give(&simple_sem.sem1); + int ret = sys_sem_take(&simple_sem.sem2, K_MSEC(20)); + + LOG_INF("SOF thread %s (%s) sem %p: %d", + k_is_user_context() ? "UserSpace!" : "privileged mode.", + CONFIG_BOARD_TARGET, &simple_sem, ret); +} + +static void test_user_thread_sys_sem(void) +{ + struct k_mem_partition mpart = { + .start = (uintptr_t)&simple_sem, + .size = 4096, + .attr = K_MEM_PARTITION_P_RW_U_RW/* | XTENSA_MMU_CACHED_WB*/, + }; + + k_mem_domain_init(&dp_mdom, 0, NULL); + sys_sem_init(&simple_sem.sem1, 0, 1); + sys_sem_init(&simple_sem.sem2, 0, 1); + + k_thread_create(&user_thread, user_stack, USER_STACKSIZE, + sys_sem_function, NULL, NULL, NULL, + -1, K_USER, K_FOREVER); + k_mem_domain_add_partition(&dp_mdom, &mpart); + k_mem_domain_add_thread(&dp_mdom, &user_thread); + + k_thread_start(&user_thread); + + /* This is what doesn't work: enabling this line crashes the DSP */ + zassert_ok(sys_sem_take(&simple_sem.sem1, K_MSEC(20))); + + sys_sem_give(&simple_sem.sem2); + + k_thread_join(&user_thread, K_FOREVER); + k_mem_domain_remove_partition(&dp_mdom, &mpart); +} + +ZTEST(sof_boot, test_sys_sem) +{ + test_user_thread_sys_sem(); +} diff --git a/zephyr/test/userspace/test_intel_hda_dma.c b/zephyr/test/userspace/test_intel_hda_dma.c new file mode 100644 index 000000000000..dd54e6d85f2a --- /dev/null +++ b/zephyr/test/userspace/test_intel_hda_dma.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. + */ + +/* + * Test case for user-space use of the SOF DMA interface. The tests + * transfer data from DSP to host using the host HD DMA instance. + * The test uses the cavstool.py infrastructure to perform host side + * programming of the HDA DMA, and to verify the transferred data. + * + * This test is based on the Zephyr kernel tests for Intel HD DMA + * driver (zephyr/tests/boards/intel_adsp/hda/) written by Tom + * Burdick. This test performs only subset of flows. Driver testing + * should primarily done with the Zephyr kernel tests and this test + * is solely to test the added syscall layer added in SOF. + */ + +#include <sof/boot_test.h> + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> +#include <sof/lib/dma.h> + +LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG); + +#define USER_STACKSIZE 2048 +#define TEST_BUF_SIZE 256 +#define TEST_CHANNEL 0 +#define HD_DMA_BUF_ALIGN 128 + +static struct k_thread user_thread; +static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE); + +K_SEM_DEFINE(ipc_sem_wake_user, 0, 1); +K_SEM_DEFINE(ipc_sem_wake_kernel, 0, 1); + +static void intel_hda_dma_user(void *p1, void *p2, void *p3) +{ + uint8_t data_buf[TEST_BUF_SIZE] __aligned(HD_DMA_BUF_ALIGN); + struct dma_block_config dma_block_cfg; + struct dma_config config; + struct dma_status stat; + struct sof_dma *dma; + uint32_t addr_align; + int err, channel; + + zassert_true(k_is_user_context(), "isn't user"); + + LOG_INF("SOF thread %s (%s)", + k_is_user_context() ? "UserSpace!" : "privileged mode.", + CONFIG_BOARD_TARGET); + + /* + * note: this gets a pointer to kernel memory this thread + * cannot access + */ + dma = sof_dma_get(SOF_DMA_DIR_LMEM_TO_HMEM, 0, SOF_DMA_DEV_HOST, SOF_DMA_ACCESS_SHARED); + + k_sem_take(&ipc_sem_wake_user, K_FOREVER); + LOG_INF("configure DMA channel"); + + channel = sof_dma_request_channel(dma, TEST_CHANNEL); + zassert_equal(channel, TEST_CHANNEL); + LOG_INF("sof_dma_request_channel: ret %d", channel); + + err = sof_dma_get_attribute(dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + zassert_equal(err, 0); + zassert_true(addr_align == HD_DMA_BUF_ALIGN); + + /* set up a DMA transfer */ + memset(&dma_block_cfg, 0, sizeof(dma_block_cfg)); + dma_block_cfg.dest_address = 0; /* host fifo */ + dma_block_cfg.source_address = (uintptr_t)data_buf; + dma_block_cfg.block_size = sizeof(data_buf); + + /* + * fill data ramp, this payload is expected by host test + * harness + */ + for (uint32_t i = 0; i < TEST_BUF_SIZE; i++) { + data_buf[i] = i & 0xff; + } + sys_cache_data_flush_range(data_buf, sizeof(data_buf)); + + memset(&config, 0, sizeof(config)); + config.channel_direction = MEMORY_TO_HOST; + config.block_count = 1; + config.head_block = &dma_block_cfg; + + err = sof_dma_config(dma, channel, &config); + zassert_equal(err, 0); + LOG_INF("sof_dma_config: success"); + + err = sof_dma_start(dma, channel); + zassert_equal(err, 0); + LOG_INF("sof_dma_start: ch %d", channel); + + k_sem_give(&ipc_sem_wake_kernel); + LOG_INF("setup ready, waiting for kernel to configure host-side of the test"); + k_sem_take(&ipc_sem_wake_user, K_FOREVER); + LOG_INF("start DMA test and transfer data"); + + err = sof_dma_get_status(dma, channel, &stat); + zassert_equal(err, 0); + LOG_INF("sof_dma_get_status start: pend %u free %u", + stat.pending_length, stat.free); + + err = sof_dma_reload(dma, channel, sizeof(data_buf)); + zassert_equal(err, 0); + + for (int i = 0; stat.pending_length < TEST_BUF_SIZE; i++) { + err = sof_dma_get_status(dma, channel, &stat); + zassert_equal(err, 0); + LOG_INF("sof_dma_get_status %d: pend %u free %u", i, + stat.pending_length, stat.free); + + zassert_true(i < 100, "DMA transfer completes in 100usec"); + + /* let DMA transfer complete */ + k_sleep(K_USEC(1)); + } + + err = sof_dma_get_status(dma, channel, &stat); + zassert_equal(err, 0); + LOG_INF("sof_dma_get_status end: pend %u free %u", + stat.pending_length, stat.free); + + LOG_INF("transfer done, asking host to validate output"); + k_sem_give(&ipc_sem_wake_kernel); + k_sem_take(&ipc_sem_wake_user, K_FOREVER); + LOG_INF("test done, cleaning up resources"); + + err = sof_dma_stop(dma, channel); + zassert_equal(err, 0); + + sof_dma_release_channel(dma, channel); + + sof_dma_put(dma); + + LOG_INF("DMA stopped and resources freed"); + + k_sem_give(&ipc_sem_wake_kernel); +} + +#define IPC_TIMEOUT K_MSEC(1500) +#define DMA_BUF_SIZE 256 + +#define ALIGNMENT DMA_BUF_ADDR_ALIGNMENT(DT_NODELABEL(hda_host_in)) +static __aligned(ALIGNMENT) uint8_t dma_buf[DMA_BUF_SIZE]; + +#include <intel_adsp_hda.h> +#include <../../../../zephyr/tests/boards/intel_adsp/hda/src/tests.h> + +static int msg_validate_res; + +static bool ipc_message(const struct device *dev, void *arg, + uint32_t data, uint32_t ext_data) +{ + LOG_DBG("HDA message received, data %u, ext_data %u", data, ext_data); + msg_validate_res = ext_data; + return true; +} + +static void intel_hda_dma_kernel(void) +{ + const struct device *dma; + + LOG_INF("run %s with buffer at address %p, size %d", + __func__, (void *)dma_buf, DMA_BUF_SIZE); + + intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_message, NULL); + + k_thread_create(&user_thread, user_stack, USER_STACKSIZE, + intel_hda_dma_user, NULL, NULL, NULL, + -1, K_USER, K_FOREVER); + + k_thread_access_grant(&user_thread, &ipc_sem_wake_user); + k_thread_access_grant(&user_thread, &ipc_sem_wake_kernel); + + dma = DEVICE_DT_GET(DT_NODELABEL(hda_host_in)); + k_thread_access_grant(&user_thread, dma); + + hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_RESET, + TEST_CHANNEL, IPC_TIMEOUT); + + hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_CONFIG, + TEST_CHANNEL | (DMA_BUF_SIZE << 8), IPC_TIMEOUT); + + k_thread_start(&user_thread); + + LOG_INF("user started, waiting for it to be ready"); + + k_sem_give(&ipc_sem_wake_user); + k_sem_take(&ipc_sem_wake_kernel, K_FOREVER); + + LOG_INF("user ready, starting HDA test"); + + hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_START, TEST_CHANNEL, IPC_TIMEOUT); + + k_sem_give(&ipc_sem_wake_user); + k_sem_take(&ipc_sem_wake_kernel, K_FOREVER); + + LOG_INF("transfer done, validating results"); + + hda_ipc_msg(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_HDA_VALIDATE, TEST_CHANNEL, + IPC_TIMEOUT); + + hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, TEST_CHANNEL, "host reset"); + + k_sem_give(&ipc_sem_wake_user); + k_sem_take(&ipc_sem_wake_kernel, K_FOREVER); + + LOG_INF("test done, terminate user thread"); + + k_thread_join(&user_thread, K_FOREVER); + + zassert_true(msg_validate_res == 1, "DMA transferred data invalid payload"); +} + +ZTEST(userspace_intel_hda_dma, dma_mem_to_host) +{ + intel_hda_dma_kernel(); + + ztest_test_pass(); +} + +ZTEST_SUITE(userspace_intel_hda_dma, NULL, NULL, NULL, NULL, NULL); + +/** + * SOF main has booted up and IPC handling is stopped. + * Run test suites with ztest_run_all. + */ +static int run_tests(void) +{ + ztest_run_test_suite(userspace_intel_hda_dma, false, 1, 1, NULL); + return 0; +} + +SYS_INIT(run_tests, APPLICATION, 99); diff --git a/zephyr/test/userspace/test_intel_ssp_dai.c b/zephyr/test/userspace/test_intel_ssp_dai.c new file mode 100644 index 000000000000..6c700c3839bb --- /dev/null +++ b/zephyr/test/userspace/test_intel_ssp_dai.c @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2025 Intel Corporation. + */ + +/* + * Test case for user-space use of the SOF DMA interface. The tests + * covers all key interfaces of DMA and DAI, testing their use from + * a user-space threads. Due to hardware constraints, the actual DMA + * transfers cannot be tested as this would require cooperation with a + * host entity that would manage the HDA link DMA in sync with the DP + * test case. Test does check all programming can be done and no + * errors are raised from the drivers. Valid configuration blobs are + * passed, to fully exercise the drivers interfaces. + + * Requirements for host side test execution environment: + * - I2S offload must be enabled on host side (HDAMLI2S) to allow + * the DAI driver to access hardware registers. + */ + +#include <sof/boot_test.h> + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> +#include <sof/lib/dai.h> +#include <sof/lib/uuid.h> +#include <sof/lib/dma.h> +#include <sof/audio/component_ext.h> + +#include "../../../src/audio/copier/dai_copier.h" +#include "../../../../zephyr/drivers/dai/intel/ssp/ssp.h" + +LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG); + +#define USER_STACKSIZE 8192 +#define HD_DMA_BUF_ALIGN 128 +#define TEST_BUF_SIZE (2*HD_DMA_BUF_ALIGN) +#define TEST_CHANNEL_OUT 3 +#define TEST_CHANNEL_IN 4 +#define SSP_DEVICE ssp00 + +static struct k_thread user_thread; +static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE); + +static K_SEM_DEFINE(ipc_sem_wake_user, 0, 1); +static K_SEM_DEFINE(ipc_sem_wake_kernel, 0, 1); + +static int call_dai_set_ssp_v3_config_48k_2ch_32bit(const struct device *dai_dev) +{ + union hdalink_cfg link_cfg; + const uint8_t stream_id = 0; + + link_cfg.full = 0; + link_cfg.part.dir = DAI_DIR_TX; + link_cfg.part.stream = stream_id; + + struct dai_config common_config = { + .type = DAI_INTEL_SSP_NHLT, + .dai_index = 0, + .channels = 2, + .rate = 48000, + .format = DAI_CBC_CFC | DAI_PROTO_I2S | DAI_INVERSION_NB_NF, + .options = 0, + .word_size = 32, + .block_size = 0, + .link_config = link_cfg.full, + .tdm_slot_group = 0 + }; + + /* + * There are no suitable struct definitions to create these + * config objects, so we have to define a custom type that + * includes the common header, a single MDIV entry, one TLV + * entry and the link_ctl struct. These are normally part of + * ACPI NHLT and can be alternatively created with alsa-utils + * nhlt plugin. + */ + struct { + struct dai_intel_ipc4_ssp_configuration_blob_ver_3_0 b; + uint32_t mdivr0; + uint32_t type; + uint32_t size; + struct ssp_intel_link_ctl link_ctl; + } __packed blob30; + + memset(&blob30, 0, sizeof(blob30)); + /* DAI config blob header for SSP v3 */ + blob30.b.version = SSP_BLOB_VER_3_0; + blob30.b.size = sizeof(blob30); + /* I2S config matching sof-ptl-nocodec.tplg (32bit/48kHz/2ch) */ + blob30.b.i2s_ssp_config.ssc0 = 0x81d0077f; + blob30.b.i2s_ssp_config.ssc1 = 0xd0400004; + blob30.b.i2s_ssp_config.sscto = 0; + blob30.b.i2s_ssp_config.sspsp = 0x02200000; + blob30.b.i2s_ssp_config.ssc2 = 0x00004002; + blob30.b.i2s_ssp_config.sspsp2 = 0; + blob30.b.i2s_ssp_config.ssc3 = 0; + blob30.b.i2s_ssp_config.ssioc = 0x00000020; + /* clock control settings matching sof-ptl-nocodec.tplg */ + blob30.b.i2s_mclk_control.mdivctlr = 0x00010001; + blob30.b.i2s_mclk_control.mdivrcnt = 1; + /* variable-size section of clock control, one entry for mdivr */ + blob30.mdivr0 = 0xfff; + /* aux-data with one TLV entry for link-clk-source */ + blob30.type = SSP_LINK_CLK_SOURCE; + blob30.size = sizeof(struct ssp_intel_link_ctl); + blob30.link_ctl.clock_source = 1; + + return dai_config_set(dai_dev, &common_config, &blob30, sizeof(blob30)); +} + +static void intel_ssp_dai_user(void *p1, void *p2, void *p3) +{ + struct dma_block_config dma_block_cfg; + struct sof_dma *dma_in, *dma_out; + uint8_t data_buf_out[TEST_BUF_SIZE] __aligned(HD_DMA_BUF_ALIGN); + uint8_t data_buf_in[TEST_BUF_SIZE] __aligned(HD_DMA_BUF_ALIGN); + uint32_t addr_align = 0; + const struct device *dai_dev; + struct dai_properties dai_props; + struct dma_config config; + struct dma_status stat; + int err, channel_out, channel_in; + + zassert_true(k_is_user_context()); + + /* + * note: this gets a pointer to kernel memory this thread + * cannot access + */ + dma_in = sof_dma_get(SOF_DMA_DIR_DEV_TO_MEM, 0, SOF_DMA_DEV_SSP, SOF_DMA_ACCESS_SHARED); + dma_out = sof_dma_get(SOF_DMA_DIR_MEM_TO_DEV, 0, SOF_DMA_DEV_SSP, SOF_DMA_ACCESS_SHARED); + + k_sem_take(&ipc_sem_wake_user, K_FOREVER); + + LOG_INF("create a DAI device for %s", STRINGIFY(SSP_DEVICE)); + + dai_dev = DEVICE_DT_GET(DT_NODELABEL(SSP_DEVICE)); + err = dai_probe(dai_dev); + zassert_equal(err, 0); + + channel_out = sof_dma_request_channel(dma_out, TEST_CHANNEL_OUT); + zassert_equal(channel_out, TEST_CHANNEL_OUT); + LOG_INF("sof_dma_request_channel (out): ret ch %d", channel_out); + channel_in = sof_dma_request_channel(dma_in, TEST_CHANNEL_IN); + zassert_equal(channel_in, TEST_CHANNEL_IN); + LOG_INF("sof_dma_request_channel (in): ret ch %d", channel_in); + + err = sof_dma_get_attribute(dma_out, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + zassert_equal(err, 0); + zassert_true(addr_align == HD_DMA_BUF_ALIGN); + + /* set up a DMA transfer */ + memset(&dma_block_cfg, 0, sizeof(dma_block_cfg)); + + err = dai_get_properties_copy(dai_dev, DAI_DIR_TX, 0, &dai_props); + zassert_equal(err, 0); + + LOG_INF("dai_get_properties_copy (TX), ret %d, fifo %u", err, dai_props.fifo_address); + + dma_block_cfg.dest_address = dai_props.fifo_address; /* dai fifo */ + dma_block_cfg.source_address = (uintptr_t)data_buf_out; + dma_block_cfg.block_size = sizeof(data_buf_out); + + memset(&config, 0, sizeof(config)); + config.channel_direction = MEMORY_TO_PERIPHERAL; + config.block_count = 1; + config.head_block = &dma_block_cfg; + config.source_data_size = 4; + config.dest_data_size = 4; + + err = sof_dma_config(dma_out, channel_out, &config); + zassert_equal(err, 0); + + err = dai_get_properties_copy(dai_dev, DAI_DIR_RX, 0, &dai_props); + zassert_equal(err, 0); + LOG_INF("dai_get_properties_copy (RX), ret %d, fifo %u", err, dai_props.fifo_address); + + dma_block_cfg.dest_address = (uintptr_t)data_buf_in; + dma_block_cfg.source_address = dai_props.fifo_address; /* dai fifo */ + dma_block_cfg.block_size = sizeof(data_buf_in); + + config.channel_direction = PERIPHERAL_TO_MEMORY; + config.block_count = 1; + + err = sof_dma_config(dma_in, channel_in, &config); + zassert_equal(err, 0, "dma-config error"); + + err = call_dai_set_ssp_v3_config_48k_2ch_32bit(dai_dev); + zassert_equal(err, 0); + LOG_INF("DAI configuration ready, sync with kernel on start"); + + k_sem_give(&ipc_sem_wake_kernel); + k_sem_take(&ipc_sem_wake_user, K_FOREVER); + LOG_INF("start DMA test and transfer data"); + + err = dai_trigger(dai_dev, DAI_DIR_RX, DAI_TRIGGER_PRE_START); + zassert_equal(err, 0); + + err = dai_trigger(dai_dev, DAI_DIR_TX, DAI_TRIGGER_PRE_START); + zassert_equal(err, 0); + LOG_INF("dai_trigger RX+TX PRE_START done"); + + err = sof_dma_get_status(dma_in, channel_in, &stat); + zassert_equal(err, 0); + LOG_INF("sof_dma_get_status ( dma_in/start):\tpend %3u free %3u", + stat.pending_length, stat.free); + + err = sof_dma_get_status(dma_out, channel_out, &stat); + zassert_equal(err, 0); + LOG_INF("sof_dma_get_status (dma_out/start):\tpend %3u free %3u", + stat.pending_length, stat.free); + + err = sof_dma_start(dma_in, channel_in); + zassert_equal(err, 0); + + err = sof_dma_start(dma_out, channel_out); + zassert_equal(err, 0); + + err = dai_trigger(dai_dev, DAI_DIR_RX, DAI_TRIGGER_START); + zassert_equal(err, 0); + + err = dai_trigger(dai_dev, DAI_DIR_TX, DAI_TRIGGER_START); + zassert_equal(err, 0); + LOG_INF("DMAs and DAIs started."); + + k_sleep(K_USEC(10)); + + err = sof_dma_get_status(dma_in, channel_in, &stat); + zassert_equal(err, 0); + /* after start, there should be at least some free data */ + zassert_true(stat.free > 0); + zassert_true(stat.pending_length < TEST_BUF_SIZE); + LOG_INF("sof_dma_get_status ( dma_in/run):\tpend %3u free %3u", + stat.pending_length, stat.free); + + err = sof_dma_reload(dma_in, channel_in, sizeof(data_buf_in)); + zassert_equal(err, 0); + + err = sof_dma_get_status(dma_in, channel_in, &stat); + zassert_equal(err, 0); + /* after reload, there should be at least some data pending */ + zassert_true(stat.free < TEST_BUF_SIZE); + zassert_true(stat.pending_length > 0); + + err = sof_dma_get_status(dma_out, channel_out, &stat); + zassert_equal(err, 0); + LOG_INF("sof_dma_get_status (dma_out/run):\tpend %3u free %3u", + stat.pending_length, stat.free); + zassert_true(stat.free < TEST_BUF_SIZE); + zassert_true(stat.pending_length > 0); + + LOG_INF("DMA setup done, asking host to clean up "); + k_sem_give(&ipc_sem_wake_kernel); + k_sem_take(&ipc_sem_wake_user, K_FOREVER); + LOG_INF("Cleaning up resources"); + + err = sof_dma_stop(dma_out, channel_out); + zassert_equal(err, 0); + + err = sof_dma_stop(dma_in, channel_in); + zassert_equal(err, 0); + + err = dai_trigger(dai_dev, DAI_DIR_TX, DAI_TRIGGER_STOP); + zassert_equal(err, 0); + + err = dai_trigger(dai_dev, DAI_DIR_RX, DAI_TRIGGER_STOP); + zassert_equal(err, 0); + + sof_dma_release_channel(dma_out, channel_out); + + sof_dma_release_channel(dma_in, channel_in); + + err = dai_remove(dai_dev); + zassert_equal(err, 0); + + sof_dma_put(dma_in); + sof_dma_put(dma_out); + + LOG_INF("Cleanup successful, terminating user thread."); + + k_sem_give(&ipc_sem_wake_kernel); +} + +static void intel_ssp_dai_kernel(void) +{ + const struct device *dma_out, *dma_in; + const struct device *dai_dev; + + k_thread_create(&user_thread, user_stack, USER_STACKSIZE, + intel_ssp_dai_user, NULL, NULL, NULL, + -1, K_USER, K_FOREVER); + + k_thread_access_grant(&user_thread, &ipc_sem_wake_user); + k_thread_access_grant(&user_thread, &ipc_sem_wake_kernel); + + dma_out = DEVICE_DT_GET(DT_NODELABEL(hda_link_out)); + dma_in = DEVICE_DT_GET(DT_NODELABEL(hda_link_in)); + dai_dev = DEVICE_DT_GET(DT_NODELABEL(SSP_DEVICE)); + + k_thread_access_grant(&user_thread, dma_out); + k_thread_access_grant(&user_thread, dma_in); + k_thread_access_grant(&user_thread, dai_dev); + + k_thread_start(&user_thread); + + LOG_INF("user started, waiting for it to be ready"); + + k_sem_give(&ipc_sem_wake_user); + k_sem_take(&ipc_sem_wake_kernel, K_FOREVER); + + LOG_INF("user ready, starting HDA test"); + + k_sem_give(&ipc_sem_wake_user); + k_sem_take(&ipc_sem_wake_kernel, K_FOREVER); + + LOG_INF("transfer done, grant permission to clean up"); + + k_sem_give(&ipc_sem_wake_user); + k_sem_take(&ipc_sem_wake_kernel, K_FOREVER); + + LOG_INF("test done, terminate user thread"); + + k_thread_join(&user_thread, K_FOREVER); +} + +ZTEST(userspace_intel_dai_ssp, dai_ssp_loopback_setup) +{ + intel_ssp_dai_kernel(); + + ztest_test_pass(); +} + +ZTEST_SUITE(userspace_intel_dai_ssp, NULL, NULL, NULL, NULL, NULL); + +/** + * SOF main has booted up and IPC handling is stopped. + * Run test suites with ztest_run_all. + */ +static int run_tests(void) +{ + ztest_run_test_suite(userspace_intel_dai_ssp, false, 1, 1, NULL); + return 0; +} + +SYS_INIT(run_tests, APPLICATION, 99); diff --git a/zephyr/test/userspace/test_ll_task.c b/zephyr/test/userspace/test_ll_task.c new file mode 100644 index 000000000000..234423defc60 --- /dev/null +++ b/zephyr/test/userspace/test_ll_task.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2026 Intel Corporation. + */ + +/* + * Test case for creation of low-latency threads in user-space. + */ + +#include <sof/boot_test.h> +#include <sof/lib/mailbox.h> +#include <sof/lib/uuid.h> +#include <sof/schedule/schedule.h> +#include <sof/schedule/ll_schedule.h> +#include <sof/schedule/ll_schedule_domain.h> +#include <sof/audio/pipeline.h> +#include <rtos/task.h> +#include <rtos/userspace_helper.h> +#include <ipc4/fw_reg.h> + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> +#include <zephyr/app_memory/app_memdomain.h> + +#include <stddef.h> /* offsetof() */ + +LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG); + +/* f11818eb-e92e-4082-82a3-dc54c604ebf3 */ +SOF_DEFINE_UUID("test_task", test_task_uuid, 0xf11818eb, 0xe92e, 0x4082, + 0x82, 0xa3, 0xdc, 0x54, 0xc6, 0x04, 0xeb, 0xf3); + +K_APPMEM_PARTITION_DEFINE(userspace_ll_part); + +/* Global variable for test runs counter, accessible from user-space */ +K_APP_BMEM(userspace_ll_part) static int test_runs; + +static enum task_state task_callback(void *arg) +{ + LOG_INF("entry"); + + if (++test_runs > 3) + return SOF_TASK_STATE_COMPLETED; + + return SOF_TASK_STATE_RESCHEDULE; +} + +static void ll_task_test(void) +{ + struct task *task; + int priority = 0; + int core = 0; + int ret; + + /* Initialize global test runs counter */ + test_runs = 0; + + task = zephyr_ll_task_alloc(); + zassert_not_null(task, "task allocation failed"); + + /* allow user space to report status via 'test_runs' */ + k_mem_domain_add_partition(zephyr_ll_mem_domain(), &userspace_ll_part); + + /* work in progress, see pipeline-schedule.c */ + ret = schedule_task_init_ll(task, SOF_UUID(test_task_uuid), SOF_SCHEDULE_LL_TIMER, + priority, task_callback, + (void *)&test_runs, core, 0); + zassert_equal(ret, 0); + + LOG_INF("task init done"); + + /* Schedule the task to run immediately with 1ms period */ + ret = schedule_task(task, 0, 1000); /* 0 = start now, 1000us = 1ms period */ + zassert_equal(ret, 0); + + LOG_INF("task scheduled and running"); + + /* Let the task run for a bit */ + k_sleep(K_MSEC(10)); + + /* Cancel the task to stop any scheduled execution */ + ret = schedule_task_cancel(task); + zassert_equal(ret, 0); + + /* Free task resources */ + ret = schedule_task_free(task); + zassert_equal(ret, 0); + + LOG_INF("test complete"); +} + +ZTEST(userspace_ll, ll_task_test) +{ + ll_task_test(); +} + +static void pipeline_check(void) +{ + struct pipeline *p; + struct k_heap *heap; + uint32_t pipeline_id = 1; + uint32_t priority = 5; + uint32_t comp_id = 10; + int ret; + + heap = zephyr_ll_user_heap(); + zassert_not_null(heap, "user heap not found"); + + /* Create pipeline on user heap */ + p = pipeline_new(heap, pipeline_id, priority, comp_id, NULL); + zassert_not_null(p, "pipeline creation failed"); + + /* Verify heap assignment */ + zassert_equal(p->heap, heap, "pipeline heap not equal to user heap"); + + /* Verify pipeline properties */ + zassert_equal(p->pipeline_id, pipeline_id, "pipeline id mismatch"); + zassert_equal(p->priority, priority, "priority mismatch"); + zassert_equal(p->comp_id, comp_id, "comp id mismatch"); + + /* Free pipeline */ + ret = pipeline_free(p); + zassert_ok(ret, "pipeline free failed"); +} + +ZTEST(userspace_ll, pipeline_check) +{ + pipeline_check(); +} + +ZTEST_SUITE(userspace_ll, NULL, NULL, NULL, NULL, NULL); + +/** + * SOF main has booted up and IPC handling is stopped. + * Run test suites with ztest_run_all. + */ +static int run_tests(void) +{ + ztest_run_test_suite(userspace_ll, false, 1, 1, NULL); + return 0; +} + +SYS_INIT(run_tests, APPLICATION, 99); diff --git a/zephyr/test/userspace/test_mailbox.c b/zephyr/test/userspace/test_mailbox.c new file mode 100644 index 000000000000..766dababb553 --- /dev/null +++ b/zephyr/test/userspace/test_mailbox.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2026 Intel Corporation. + */ + +/* + * Test case for sof/mailbox.h interface use from a Zephyr user + * thread. + */ + +#include <sof/boot_test.h> +#include <sof/lib/mailbox.h> +#include <rtos/userspace_helper.h> + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> +#include <zephyr/logging/log.h> +#include <zephyr/app_memory/app_memdomain.h> + +#include <ipc4/fw_reg.h> /* mailbox definitions */ + +LOG_MODULE_DECLARE(sof_boot_test, LOG_LEVEL_DBG); + +#define USER_STACKSIZE 2048 + +static struct k_thread user_thread; +static K_THREAD_STACK_DEFINE(user_stack, USER_STACKSIZE); + +static void mailbox_write_to_pipeline_regs(void) +{ + unsigned int offset = offsetof(struct ipc4_fw_registers, pipeline_regs); + struct ipc4_pipeline_registers pipe_reg; + + /* + * IPC4 pipe_reg struct used for test, but this test also + * works for IPC3 targets. + */ + pipe_reg.stream_start_offset = (uint64_t)-1; + pipe_reg.stream_end_offset = (uint64_t)-1; + + LOG_INF("Write to sw_regs mailbox at offset %u", offset); + + mailbox_sw_regs_write(offset, &pipe_reg, sizeof(pipe_reg)); +} + +static void mailbox_test_thread(void *p1, void *p2, void *p3) +{ + zassert_true(k_is_user_context(), "isn't user"); + + LOG_INF("SOF thread %s (%s)", + k_is_user_context() ? "UserSpace!" : "privileged mode.", + CONFIG_BOARD_TARGET); + + mailbox_write_to_pipeline_regs(); +} + +static void mailbox_test(void) +{ + struct k_mem_domain domain; + int ret = k_mem_domain_init(&domain, 0, NULL); + + zassert_equal(ret, 0); + + k_thread_create(&user_thread, user_stack, USER_STACKSIZE, + mailbox_test_thread, NULL, NULL, NULL, + -1, K_USER, K_FOREVER); + + LOG_INF("set up user access to mailbox"); + + ret = user_access_to_mailbox(&domain, &user_thread); + zassert_equal(ret, 0); + + k_thread_start(&user_thread); + + LOG_INF("user started, waiting in kernel until test complete"); + + k_thread_join(&user_thread, K_FOREVER); +} + +ZTEST(userspace_mailbox, mailbox_test) +{ + /* first test from kernel */ + mailbox_write_to_pipeline_regs(); + + /* then full test in userspace */ + mailbox_test(); + + ztest_test_pass(); +} + +ZTEST_SUITE(userspace_mailbox, NULL, NULL, NULL, NULL, NULL); + +/** + * SOF main has booted up and IPC handling is stopped. + * Run test suites with ztest_run_all. + */ +static int run_tests(void) +{ + ztest_run_test_suite(userspace_mailbox, false, 1, 1, NULL); + return 0; +} + +SYS_INIT(run_tests, APPLICATION, 99); diff --git a/zephyr/test/vmh.c b/zephyr/test/vmh.c new file mode 100644 index 000000000000..abb00b561b3d --- /dev/null +++ b/zephyr/test/vmh.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <adsp_memory_regions.h> +#include <sof/boot_test.h> +#include <sof/lib/regions_mm.h> + +#include <zephyr/logging/log.h> +#include <zephyr/ztest.h> + +LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL); +struct vmh_heap; + +/* Test creating and freeing a virtual memory heap */ +static void test_vmh_init_and_free_heap(struct vmh_heap_config *config, + bool allocating_continuously, + bool expect_success) +{ + struct vmh_heap *heap = vmh_init_heap(config, allocating_continuously); + if (expect_success) + zassert_not_null(heap, "Heap initialization expected to succeed but failed"); + else + zassert_is_null(heap, "Heap initialization expected to fail but succeeded"); + + if (heap) { + int ret = vmh_free_heap(heap); + + zassert_equal(ret, 0, "Failed to free heap"); + } +} + +/* Test for vmh_alloc and vmh_free */ +static void test_vmh_alloc_free_no_check(struct vmh_heap *heap, + uint32_t alloc_size, + bool expect_success) +{ + void *ptr = vmh_alloc(heap, alloc_size); + + if (expect_success) + zassert_not_null(ptr, "Allocation expected to succeed but failed"); + else + zassert_is_null(ptr, "Allocation expected to fail but succeeded"); + + if (ptr) { + int ret = vmh_free(heap, ptr); + + zassert_equal(ret, 0, "Failed to free allocated memory"); + } +} + +static void verify_memory_content(void *ptr, uint32_t alloc_size) +{ + + /* Calculate check positions end and middle if applicable */ + uint8_t *end_ptr = (uint8_t *)ptr + alloc_size - sizeof(uint32_t); + uint8_t *middle_ptr = (uint8_t *)ptr + (alloc_size / 2); + uint8_t test_value = 0xAA; + int test_write_size = 1; + + /* Write test pattern to the allocated memory beginning middle and end */ + memset(ptr, test_value, test_write_size); + memset(middle_ptr, test_value, test_write_size); + memset(end_ptr, test_value, test_write_size); + + /* Verify the written test pattern at all points */ + zassert_equal(*((uint8_t *)ptr), test_value, + "Memory content verification failed at the start"); + zassert_equal(*end_ptr, test_value, + "Memory content verification failed at the end"); + zassert_equal(*middle_ptr, test_value, + "Memory content verification failed in the middle"); +} + +/* Test function for vmh_alloc and vmh_free with memory read/write */ +static void test_vmh_alloc_free_check(struct vmh_heap *heap, + uint32_t alloc_size, + bool expect_success) +{ + void *ptr = vmh_alloc(heap, alloc_size); + + if (expect_success) + zassert_not_null(ptr, "Allocation expected to succeed but failed"); + else { + zassert_is_null(ptr, "Allocation expected to fail but succeeded"); + return; + } + + if (ptr) + verify_memory_content(ptr, alloc_size); + + int ret = vmh_free(heap, ptr); + + zassert_equal(ret, 0, "Failed to free allocated memory"); +} + +/* Test function for multiple allocations on the same heap with read/write */ +static void test_vmh_multiple_allocs(struct vmh_heap *heap, int num_allocs, + uint32_t min_alloc_size, + uint32_t max_alloc_size) +{ + void *ptrs[num_allocs]; + uint32_t alloc_size; + int ret; + + /* Perform multiple allocations */ + for (int i = 0; i < num_allocs; i++) { + /* Generate a random allocation size between min_alloc_size and max_alloc_size */ + alloc_size = min_alloc_size + + k_cycle_get_32() % (max_alloc_size - min_alloc_size + 1); + + ptrs[i] = vmh_alloc(heap, alloc_size); + + if (!ptrs[i]) + LOG_INF("Test allocation failed for size: %d", alloc_size); + + zassert_true(ptrs[i] != NULL, + "Allocation of size %u expected to succeed but failed", + alloc_size); + + if (ptrs[i]) + verify_memory_content(ptrs[i], alloc_size); + } + + for (int i = 0; i < num_allocs; i++) { + if (ptrs[i]) { + ret = vmh_free(heap, ptrs[i]); + zassert_equal(ret, 0, "Failed to free allocated memory"); + } + } +} + +/* Test case for multiple allocations */ +static void test_vmh_alloc_multiple_times(bool allocating_continuously) +{ + struct vmh_heap *heap = + vmh_init_heap(NULL, allocating_continuously); + + zassert_not_null(heap, "Heap initialization failed"); + + /* Test multiple allocations with small sizes */ + test_vmh_multiple_allocs(heap, 16, 4, 8); + test_vmh_multiple_allocs(heap, 64, 4, 8); + test_vmh_multiple_allocs(heap, 16, 4, 1024); + test_vmh_multiple_allocs(heap, 64, 4, 1024); + if (allocating_continuously) { + test_vmh_multiple_allocs(heap, 16, 1024, 4096); + test_vmh_multiple_allocs(heap, 16, 4096, 8192); + } + + /* Clean up the heap after testing */ + int ret = vmh_free_heap(heap); + + zassert_equal(ret, 0, "Failed to free heap after multiple allocations"); +} + +/* Test case for vmh_alloc and vmh_free */ +static void test_vmh_alloc_free(bool allocating_continuously) +{ + struct vmh_heap *heap = + vmh_init_heap(NULL, allocating_continuously); + + zassert_not_null(heap, "Heap initialization failed"); + + test_vmh_alloc_free_no_check(heap, 512, true); + test_vmh_alloc_free_no_check(heap, 1024, true); + test_vmh_alloc_free_no_check(heap, sizeof(int), true); + test_vmh_alloc_free_no_check(heap, 0, false); + + test_vmh_alloc_free_check(heap, 512, true); + test_vmh_alloc_free_check(heap, 1024, true); + test_vmh_alloc_free_check(heap, sizeof(int), true); + test_vmh_alloc_free_check(heap, 0, false); + + int ret = vmh_free_heap(heap); + + zassert_equal(ret, 0, "Failed to free heap"); + + /* Could add tests with configs for heaps*/ +} + +/* Test case for vmh_alloc and vmh_free with and without config */ +static void test_heap_creation(void) +{ + test_vmh_init_and_free_heap(NULL, false, true); + + /* Try to setup with pre defined heap config */ + struct vmh_heap_config config = {0}; + + config.block_bundles_table[0].block_size = 8; + + config.block_bundles_table[0].number_of_blocks = 1024; + + config.block_bundles_table[1].block_size = 16; + + config.block_bundles_table[1].number_of_blocks = 512; + + test_vmh_init_and_free_heap(&config, false, true); +} + +/* Test case for alloc/free on configured heap */ +static void test_alloc_on_configured_heap(bool allocating_continuously) +{ + + /* Try to setup with pre defined heap config */ + struct vmh_heap_config config = {0}; + + config.block_bundles_table[0].block_size = 32; + + config.block_bundles_table[0].number_of_blocks = 256; + + /* Create continuous allocation heap for success test */ + struct vmh_heap *heap = + vmh_init_heap(&config, allocating_continuously); + + /* Will succeed on continuous and fail with single block alloc */ + test_vmh_alloc_free_check(heap, 512, allocating_continuously); + + int ret = vmh_free_heap(heap); + + zassert_equal(ret, 0, "Failed to free heap"); +} + +ZTEST(sof_boot, virtual_memory_heap) +{ + test_heap_creation(); + test_alloc_on_configured_heap(true); + test_alloc_on_configured_heap(false); + test_vmh_alloc_free(true); + test_vmh_alloc_free(false); + test_vmh_alloc_multiple_times(true); + test_vmh_alloc_multiple_times(false); + + TEST_CHECK_RET(true, "virtual_memory_heap"); +} diff --git a/zephyr/test/vpage.c b/zephyr/test/vpage.c new file mode 100644 index 000000000000..038e299eba70 --- /dev/null +++ b/zephyr/test/vpage.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2026 Intel Corporation. + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <sof/boot_test.h> +#include <sof/lib/vpage.h> + +#include <zephyr/logging/log.h> +#include <zephyr/ztest.h> + +LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL); + +ZTEST(sof_boot, vpage) +{ + void *p1 = vpage_alloc(1); + + zassert_not_null(p1); + + void *p2 = vpage_alloc(2); + + zassert_not_null(p2); + + vpage_free(p1); + vpage_free(p2); + + p1 = vpage_alloc(2); + + zassert_not_null(p1); + + vpage_free(p1); +} diff --git a/zephyr/test/vregion.c b/zephyr/test/vregion.c new file mode 100644 index 000000000000..eb59f68a14d7 --- /dev/null +++ b/zephyr/test/vregion.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2026 Intel Corporation. + */ + +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <sof/boot_test.h> +#include <sof/lib/vregion.h> + +#include <zephyr/logging/log.h> +#include <zephyr/ztest.h> + +LOG_MODULE_DECLARE(sof_boot_test, CONFIG_SOF_LOG_LEVEL); + +static struct vregion *test_vreg_create(void) +{ + struct vregion *vreg = vregion_create(CONFIG_MM_DRV_PAGE_SIZE - 100, + CONFIG_MM_DRV_PAGE_SIZE); + + zassert_not_null(vreg); + + return vreg; +} + +static void test_vreg_alloc_lifet(struct vregion *vreg) +{ + void *ptr = vregion_alloc(vreg, VREGION_MEM_TYPE_LIFETIME, 2000); + + zassert_not_null(ptr); + + void *ptr_align = vregion_alloc_align(vreg, VREGION_MEM_TYPE_LIFETIME, 1600, 16); + + zassert_not_null(ptr_align); + zassert_equal((uintptr_t)ptr_align & 15, 0); + + void *ptr_nomem = vregion_alloc(vreg, VREGION_MEM_TYPE_LIFETIME, 2000); + + zassert_is_null(ptr_nomem); + + vregion_free(vreg, ptr_align); + vregion_free(vreg, ptr); + + /* Freeing isn't possible with LIFETIME */ + ptr_nomem = vregion_alloc(vreg, VREGION_MEM_TYPE_LIFETIME, 2000); + + zassert_is_null(ptr_nomem); +} + +static void test_vreg_alloc_tmp(struct vregion *vreg) +{ + void *ptr = vregion_alloc(vreg, VREGION_MEM_TYPE_INTERIM, 20); + + zassert_not_null(ptr); + + void *ptr_align = vregion_alloc_align(vreg, VREGION_MEM_TYPE_INTERIM, 2000, 16); + + zassert_not_null(ptr_align); + zassert_equal((uintptr_t)ptr_align & 15, 0); + + void *ptr_nomem = vregion_alloc(vreg, VREGION_MEM_TYPE_INTERIM, 2000); + + zassert_is_null(ptr_nomem); + + vregion_free(vreg, ptr_align); + vregion_free(vreg, ptr); + + /* Should be possible to allocate again */ + ptr = vregion_alloc(vreg, VREGION_MEM_TYPE_INTERIM, 2000); + + zassert_not_null(ptr); +} + +static void test_vreg_destroy(struct vregion *vreg) +{ + vregion_info(vreg); + vregion_put(vreg); +} + +ZTEST(sof_boot, vregion) +{ + struct vregion *vreg = test_vreg_create(); + + /* Test interim allocations */ + test_vreg_alloc_tmp(vreg); + /* Test lifetime allocations */ + test_vreg_alloc_lifet(vreg); + + test_vreg_destroy(vreg); +} diff --git a/zephyr/uuid-snippet.ld b/zephyr/uuid-snippet.ld new file mode 100644 index 000000000000..710e044ae226 --- /dev/null +++ b/zephyr/uuid-snippet.ld @@ -0,0 +1,6 @@ +/* This is a Zephyr linker "snippet" + * See zephyr_linker_sources() cmake function + */ + +/* Runtime UUID table. */ +ITERABLE_SECTION_ROM(sof_uuid_entry, 4) diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c new file mode 100644 index 000000000000..c0c167b930fe --- /dev/null +++ b/zephyr/wrapper.c @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> + */ + +#include <sof/init.h> +#include <sof/llext_manager.h> +#include <rtos/idc.h> +#include <rtos/interrupt.h> +#include <sof/drivers/interrupt-map.h> +#include <sof/lib/dma.h> +#include <sof/schedule/schedule.h> +#include <platform/lib/memory.h> +#include <sof/platform.h> +#include <sof/lib/notifier.h> +#include <sof/lib/pm_runtime.h> +#include <sof/audio/pipeline.h> +#include <sof/audio/component_ext.h> +#include <sof/trace/trace.h> +#include <rtos/wait.h> +#include <rtos/clk.h> +#if CONFIG_IPC_MAJOR_4 +#include <ipc4/notification.h> +#endif + +/* Zephyr includes */ +#include <zephyr/arch/cpu.h> +#include <zephyr/device.h> +#include <zephyr/fatal.h> +#include <zephyr/kernel_structs.h> +#include <zephyr/kernel.h> +#include <zephyr/pm/policy.h> +#include <version.h> +#include <zephyr/sys/__assert.h> +#include <zephyr/logging/log_ctrl.h> +#include <zephyr/logging/log.h> + +LOG_MODULE_REGISTER(zephyr, CONFIG_SOF_LOG_LEVEL); + +extern K_KERNEL_STACK_ARRAY_DEFINE(z_interrupt_stacks, CONFIG_MP_MAX_NUM_CPUS, + CONFIG_ISR_STACK_SIZE); + +SOF_DEFINE_REG_UUID(zephyr); + +DECLARE_TR_CTX(zephyr_tr, SOF_UUID(zephyr_uuid), LOG_LEVEL_INFO); + +/* + * Interrupts. + * + * Mostly mapped. Still needs some linkage symbols that can be removed later. + */ + +/* needed for linkage only */ +const char irq_name_level2[] = "level2"; +const char irq_name_level5[] = "level5"; + +/* imx currently has no IRQ driver in Zephyr so we force to xtos IRQ */ +#if defined(CONFIG_AMD) && !defined(CONFIG_ZEPHYR_NATIVE_DRIVERS) +int interrupt_register(uint32_t irq, void(*handler)(void *arg), void *arg) +{ +#ifdef CONFIG_DYNAMIC_INTERRUPTS + return arch_irq_connect_dynamic(irq, 0, (void (*)(const void *))handler, + arg, 0); +#else + tr_err(&zephyr_tr, "Cannot register handler for IRQ %u: dynamic IRQs are disabled", + irq); + return -EOPNOTSUPP; +#endif +} + +/* unregister an IRQ handler - matches on IRQ number and data ptr */ +void interrupt_unregister(uint32_t irq, const void *arg) +{ + /* + * There is no "unregister" (or "disconnect") for + * interrupts in Zephyr. + */ + irq_disable(irq); +} + +/* enable an interrupt source - IRQ needs mapped to Zephyr, + * arg is used to match. + */ +uint32_t interrupt_enable(uint32_t irq, void *arg) +{ + irq_enable(irq); + + return 0; +} + +/* disable interrupt */ +uint32_t interrupt_disable(uint32_t irq, void *arg) +{ + irq_disable(irq); + + return 0; +} +#endif + +/* + * i.MX uses the IRQ_STEER + */ +#if !CONFIG_IMX && !CONFIG_AMD + +void interrupt_mask(uint32_t irq, unsigned int cpu) +{ + /* TODO: how do we mask on other cores with Zephyr APIs */ +} + +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) +{ + /* handled by zephyr - needed for linkage */ +} + +void platform_interrupt_clear(uint32_t irq, uint32_t mask) +{ + /* handled by zephyr - needed for linkage */ +} + +/* + * Asynchronous Messaging Service + * + * Use SOF async messaging service. + */ + +static struct async_message_service *host_ams[CONFIG_CORE_COUNT]; + +struct async_message_service **arch_ams_get(void) +{ + return host_ams + cpu_get_id(); +} + +/* + * Notifier. + * + * Use SOF inter component messaging today. Zephyr has similar APIs that will + * need some minor feature updates prior to merge. i.e. FW to host messages. + * TODO: align with Zephyr API when ready. + */ + +static struct notify *host_notify[CONFIG_CORE_COUNT]; + +struct notify **arch_notify_get(void) +{ + return host_notify + cpu_get_id(); +} + +/* + * Debug + */ +void arch_dump_regs_a(void *dump_buf) +{ + /* needed for linkage only */ +} + +/* + * Xtensa. TODO: this needs removed and fixed in SOF. + */ +unsigned int _xtos_ints_off(unsigned int mask) +{ + /* turn all local IRQs OFF */ + irq_lock(); + return 0; +} + +int task_main_start(struct sof *sof) +{ + /* init default audio components */ + sys_comp_init(sof); + + /* init pipeline position offsets */ + pipeline_posn_init(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 + unsigned int status; + int ret = llext_manager_restore_from_dram(); + + switch (ret) { +#if CONFIG_IPC_MAJOR_4 + case 0: + status = SOF_IPC4_FW_READY_LIB_RESTORED; + break; +#endif + case -ENOSYS: + status = 0; + break; + default: + status = 0; + LOG_ERR("LLEXT restore failed: %d", ret); + } + + /* let host know DSP boot is complete */ + return platform_boot_complete(status); +#endif /* CONFIG_IMX93_A55 */ +} + +int start_complete(void) +{ + /* + * called from primary_core_init(), track state here + * (only called from single core, no RMW lock) + */ + __ASSERT_NO_MSG(cpu_get_id() == PLATFORM_PRIMARY_CORE_ID); +#if defined(CONFIG_PM) + 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 + return boot_complete(); +} + +/* + * Timestamps. + * + * TODO: move to generic code in SOF, currently platform code. + */ + +/* get timestamp for host stream DMA position */ +void platform_host_timestamp(struct comp_dev *host, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get host position */ + err = comp_position(host, posn); + if (err == 0) + posn->flags |= SOF_TIME_HOST_VALID; +} + +/* get timestamp for DAI stream DMA position */ +void platform_dai_timestamp(struct comp_dev *dai, + struct sof_ipc_stream_posn *posn) +{ + int err; + + /* get DAI position */ + err = comp_position(dai, posn); + if (err == 0) + posn->flags |= SOF_TIME_DAI_VALID; + + /* get SSP wallclock - DAI sets this to stream start value */ + posn->wallclock = sof_cycle_get_64() - posn->wallclock; + posn->wallclock_hz = sys_cycle_get_64_rate(); + posn->flags |= SOF_TIME_WALL_VALID; +} + +/* get current wallclock for componnent */ +void platform_dai_wallclock(struct comp_dev *dai, uint64_t *wallclock) +{ + *wallclock = sof_cycle_get_64(); +} + +/* + * Multicore + * + * Mostly empty today waiting pending Zephyr CAVS SMP integration. + */ +#if CONFIG_MULTICORE && CONFIG_SMP + +static struct idc idc[CONFIG_MP_MAX_NUM_CPUS]; +static struct idc *p_idc[CONFIG_MP_MAX_NUM_CPUS]; + +struct idc **idc_get(void) +{ + int cpu = cpu_get_id(); + + p_idc[cpu] = idc + cpu; + + return p_idc + cpu; +} +#endif + +#define DEFAULT_TRY_TIMES 8 + +int poll_for_register_delay(uint32_t reg, uint32_t mask, + uint32_t val, uint64_t us) +{ + uint64_t tick = k_us_to_cyc_ceil64(us); + uint32_t tries = DEFAULT_TRY_TIMES; + uint64_t delta = tick / tries; + + if (!delta) { + /* + * If we want to wait for less than DEFAULT_TRY_TIMES ticks then + * delta has to be set to 1 and number of tries to that of number + * of ticks. + */ + delta = 1; + tries = tick; + } + + while ((io_reg_read(reg) & mask) != val) { + if (!tries--) { + LOG_DBG("poll timeout reg %u mask %u val %u us %u", + reg, mask, val, (uint32_t)us); + return -EIO; + } + wait_delay(delta); + } + return 0; +} + +/* Mutable, volatile and not static to escape optimizers and static + * analyzers. + */ +volatile int *_sof_fatal_null = NULL; + +struct arch_esf; + +void k_sys_fatal_error_handler(unsigned int reason, + const struct arch_esf *esf) +{ + ARG_UNUSED(esf); + + /* flush and switch to immediate mode */ + LOG_PANIC(); + + /* IPC not set up in standalone test mode */ +#ifndef CONFIG_SOF_BOOT_TEST_STANDALONE + ipc_send_panic_notification(); +#endif + +#if defined(CONFIG_ARCH_POSIX) || defined(CONFIG_ZEPHYR_POSIX) + LOG_ERR("Halting emulation"); + + /* In emulation we want to stop _immediately_ and print a useful stack + * trace; not a useless pointer to some signal handler or Zephyr + * cleanup routine. See Zephyr POSIX limitations discussed in: + * https://github.com/zephyrproject-rtos/zephyr/pull/68494 + */ + *_sof_fatal_null = 42; +#else + LOG_ERR("Halting system"); +#endif + k_fatal_halt(reason); +}